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:
authorDalai Felinto <dfelinto@gmail.com>2015-09-24 18:24:20 +0300
committerDalai Felinto <dfelinto@gmail.com>2015-09-24 18:24:20 +0300
commit27b3ea622f8bd313a8e2827dfec752bf2125566c (patch)
treef212e49d224ce8e1cfc3b17a64ae524711494391
parent372dff8d1dc7e24d4b2cd37de245588ecfce8bfa (diff)
parentde80e687689032cb85179a1f7e89750573631d5d (diff)
Merge remote-tracking branch 'origin/master' into cycles_camera_nodescycles_camera_nodes
Note: the branch currently crashes in blender_camera_nodes.cpp: BL::NodeTree b_ntree = b_data.node_groups[nodes_tree_name]; The crash was introduced in: cb7cf523e5c000609f32a382e2c0fcc57f635a42 Conflicts: intern/cycles/SConscript intern/cycles/blender/addon/__init__.py intern/cycles/blender/addon/properties.py intern/cycles/blender/blender_camera.cpp intern/cycles/kernel/kernel_types.h intern/cycles/kernel/svm/svm.h intern/cycles/kernel/svm/svm_types.h intern/cycles/render/camera.cpp intern/cycles/render/camera.h
-rw-r--r--CMakeLists.txt1109
-rw-r--r--GNUmakefile185
-rw-r--r--SConstruct171
-rwxr-xr-xbuild_files/build_environment/install_deps.sh426
-rw-r--r--build_files/buildbot/config/user-config-cuda-glibc211-i686.py2
-rw-r--r--build_files/buildbot/config/user-config-cuda-glibc211-x86_64.py2
-rw-r--r--build_files/buildbot/config/user-config-glibc211-i686.py22
-rw-r--r--build_files/buildbot/config/user-config-glibc211-x86_64.py22
-rw-r--r--build_files/buildbot/config/user-config-mac-i386.py2
-rw-r--r--build_files/buildbot/config/user-config-mac-x86_64.py3
-rw-r--r--build_files/buildbot/config/user-config-player-glibc211-i686.py2
-rw-r--r--build_files/buildbot/config/user-config-player-glibc211-x86_64.py2
-rw-r--r--build_files/buildbot/master.cfg46
-rw-r--r--build_files/buildbot/master_unpack.py43
-rw-r--r--build_files/buildbot/slave_compile.py21
-rw-r--r--build_files/buildbot/slave_pack.py38
-rw-r--r--build_files/cmake/Modules/FindAudaspace.cmake113
-rw-r--r--build_files/cmake/Modules/FindEigen3.cmake56
-rw-r--r--build_files/cmake/Modules/FindGLEW.cmake2
-rw-r--r--build_files/cmake/Modules/FindJeMalloc.cmake1
-rw-r--r--build_files/cmake/Modules/FindLLVM.cmake94
-rw-r--r--build_files/cmake/Modules/FindLZO.cmake68
-rw-r--r--build_files/cmake/Modules/FindOpenCOLLADA.cmake5
-rw-r--r--build_files/cmake/Modules/FindOpenColorIO.cmake13
-rw-r--r--build_files/cmake/Modules/FindOpenEXR.cmake7
-rw-r--r--build_files/cmake/Modules/FindOpenGLES.cmake78
-rw-r--r--build_files/cmake/Modules/FindOpenImageIO.cmake21
-rw-r--r--build_files/cmake/Modules/FindOpenJPEG.cmake2
-rw-r--r--build_files/cmake/Modules/FindOpenShadingLanguage.cmake98
-rw-r--r--build_files/cmake/Modules/FindOpenSubdiv.cmake111
-rw-r--r--build_files/cmake/Modules/FindPCRE.cmake1
-rw-r--r--build_files/cmake/Modules/FindPugiXML.cmake73
-rw-r--r--build_files/cmake/Modules/FindPythonLibsUnix.cmake46
-rw-r--r--build_files/cmake/Modules/FindSDL2.cmake72
-rw-r--r--build_files/cmake/Modules/GTestTesting.cmake18
-rw-r--r--build_files/cmake/buildinfo.cmake17
-rwxr-xr-xbuild_files/cmake/cmake_consistency_check.py178
-rw-r--r--build_files/cmake/cmake_consistency_check_config.py3
-rwxr-xr-xbuild_files/cmake/cmake_netbeans_project.py62
-rwxr-xr-xbuild_files/cmake/cmake_qtcreator_project.py105
-rw-r--r--build_files/cmake/config/blender_full.cmake69
-rw-r--r--build_files/cmake/config/blender_lite.cmake2
-rw-r--r--build_files/cmake/macros.cmake469
-rw-r--r--build_files/cmake/packaging.cmake39
-rwxr-xr-xbuild_files/cmake/project_info.py2
-rw-r--r--build_files/cmake/project_source_info.py21
-rwxr-xr-xbuild_files/package_spec/build_archive.py2
-rw-r--r--build_files/package_spec/pacman/PKGBUILD24
-rw-r--r--build_files/scons/config/darwin-config.py12
-rw-r--r--build_files/scons/config/linux-config.py25
-rw-r--r--build_files/scons/config/win32-mingw-config.py17
-rw-r--r--build_files/scons/config/win32-vc-config.py23
-rw-r--r--build_files/scons/config/win64-mingw-config.py20
-rw-r--r--build_files/scons/config/win64-vc-config.py23
-rw-r--r--[-rwxr-xr-x]build_files/scons/tools/Blender.py65
-rw-r--r--build_files/scons/tools/btools.py54
-rwxr-xr-xbuild_files/utils/build_tgz.sh20
-rwxr-xr-xdoc/blender_file_format/BlendFileDnaExporter_25.py6
-rw-r--r--doc/build_systems/cmake.txt104
-rw-r--r--doc/build_systems/scons-dev.txt15
-rw-r--r--doc/build_systems/scons.txt41
-rw-r--r--doc/doxygen/Doxyfile2388
-rw-r--r--doc/doxygen/doxygen.extern.h (renamed from doc/doxygen/doxygen.extern)0
-rw-r--r--doc/doxygen/doxygen.intern.h (renamed from doc/doxygen/doxygen.intern)12
-rw-r--r--doc/doxygen/doxygen.main.h (renamed from doc/doxygen/doxygen.main)2
-rw-r--r--doc/doxygen/doxygen.source.h (renamed from doc/doxygen/doxygen.source)47
-rwxr-xr-xdoc/manpage/blender.1.py2
-rw-r--r--doc/python_api/examples/aud.py1
-rw-r--r--doc/python_api/examples/bge.constraints.py8
-rw-r--r--doc/python_api/examples/bge.texture.1.py5
-rw-r--r--doc/python_api/examples/bge.texture.py3
-rw-r--r--doc/python_api/examples/bpy.app.handlers.py1
-rw-r--r--doc/python_api/examples/bpy.ops.1.py5
-rw-r--r--doc/python_api/examples/bpy.ops.2.py13
-rw-r--r--doc/python_api/examples/bpy.ops.py22
-rw-r--r--doc/python_api/examples/bpy.props.2.py2
-rw-r--r--doc/python_api/examples/bpy.props.py2
-rw-r--r--doc/python_api/examples/bpy.types.AddonPreferences.1.py3
-rw-r--r--doc/python_api/examples/bpy.types.Menu.1.py1
-rw-r--r--doc/python_api/examples/bpy.types.Menu.2.py8
-rw-r--r--doc/python_api/examples/bpy.types.Menu.py14
-rw-r--r--doc/python_api/examples/bpy.types.Mesh.py8
-rw-r--r--doc/python_api/examples/bpy.types.NodeTree.py1
-rw-r--r--doc/python_api/examples/bpy.types.Object.py1
-rw-r--r--doc/python_api/examples/bpy.types.Operator.1.py3
-rw-r--r--doc/python_api/examples/bpy.types.Operator.2.py2
-rw-r--r--doc/python_api/examples/bpy.types.Operator.3.py1
-rw-r--r--doc/python_api/examples/bpy.types.Operator.4.py1
-rw-r--r--doc/python_api/examples/bpy.types.Operator.5.py7
-rw-r--r--doc/python_api/examples/bpy.types.Operator.py1
-rw-r--r--doc/python_api/examples/bpy.types.Panel.1.py1
-rw-r--r--doc/python_api/examples/bpy.types.Panel.2.py2
-rw-r--r--doc/python_api/examples/bpy.types.Panel.py1
-rw-r--r--doc/python_api/examples/bpy.types.UIList.2.py3
-rw-r--r--doc/python_api/examples/bpy.types.bpy_struct.keyframe_insert.1.py2
-rw-r--r--doc/python_api/examples/mathutils.Quaternion.py9
-rw-r--r--doc/python_api/examples/mathutils.Vector.py10
-rw-r--r--doc/python_api/rst/bge.app.rst47
-rw-r--r--doc/python_api/rst/bge.constraints.rst204
-rw-r--r--doc/python_api/rst/bge.logic.rst26
-rw-r--r--doc/python_api/rst/bge.render.rst164
-rw-r--r--doc/python_api/rst/bge.texture.rst956
-rw-r--r--doc/python_api/rst/bge_types/bge.types.KX_BlenderMaterial.rst161
-rw-r--r--doc/python_api/rst/bge_types/bge.types.KX_Camera.rst12
-rw-r--r--doc/python_api/rst/bge_types/bge.types.KX_CharacterWrapper.rst2
-rw-r--r--doc/python_api/rst/bge_types/bge.types.KX_ConstraintWrapper.rst32
-rw-r--r--doc/python_api/rst/bge_types/bge.types.KX_FontObject.rst22
-rw-r--r--doc/python_api/rst/bge_types/bge.types.KX_GameObject.rst158
-rw-r--r--doc/python_api/rst/bge_types/bge.types.KX_MeshProxy.rst2
-rw-r--r--doc/python_api/rst/bge_types/bge.types.KX_ObjectActuator.rst12
-rw-r--r--doc/python_api/rst/bge_types/bge.types.KX_PolyProxy.rst4
-rw-r--r--doc/python_api/rst/bge_types/bge.types.KX_PolygonMaterial.rst250
-rw-r--r--doc/python_api/rst/bge_types/bge.types.KX_Scene.rst24
-rw-r--r--doc/python_api/rst/bge_types/bge.types.KX_VehicleWrapper.rst21
-rw-r--r--doc/python_api/rst/bge_types/bge.types.KX_VertexProxy.rst22
-rw-r--r--doc/python_api/rst/bge_types/bge.types.KX_WorldInfo.rst79
-rw-r--r--doc/python_api/rst/bge_types/bge.types.SCA_2DFilterActuator.rst4
-rw-r--r--doc/python_api/rst/bge_types/bge.types.SCA_ISensor.rst10
-rw-r--r--doc/python_api/rst/bge_types/bge.types.SCA_PythonMouse.rst2
-rw-r--r--doc/python_api/rst/bgl.rst296
-rw-r--r--doc/python_api/rst/gpu.rst480
-rw-r--r--doc/python_api/rst/info_api_reference.rst44
-rw-r--r--doc/python_api/rst/info_best_practice.rst175
-rw-r--r--doc/python_api/rst/info_gotcha.rst397
-rw-r--r--doc/python_api/rst/info_overview.rst192
-rw-r--r--doc/python_api/rst/info_quickstart.rst223
-rw-r--r--doc/python_api/rst/info_tips_and_tricks.rst164
-rw-r--r--doc/python_api/rst/info_tutorial_addon.rst94
-rw-r--r--doc/python_api/sphinx_changelog_gen.py2
-rw-r--r--doc/python_api/sphinx_doc_gen.py125
-rwxr-xr-xdoc/python_api/sphinx_doc_gen.sh8
-rw-r--r--extern/CMakeLists.txt26
-rw-r--r--extern/Eigen3/CMakeLists.txt41
-rw-r--r--extern/Eigen3/SConscript35
-rw-r--r--extern/Eigen3/eigen3_capi.h32
-rw-r--r--extern/Eigen3/intern/eigenvalues.cc70
-rw-r--r--extern/Eigen3/intern/eigenvalues.h40
-rw-r--r--extern/SConscript12
-rw-r--r--extern/bullet2/readme.txt5
-rw-r--r--extern/bullet2/src/Bullet-C-Api.h1
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionWorld.h2
-rw-r--r--[-rwxr-xr-x]extern/bullet2/src/BulletDynamics/ConstraintSolver/btSliderConstraint.cpp0
-rw-r--r--[-rwxr-xr-x]extern/bullet2/src/BulletDynamics/ConstraintSolver/btSliderConstraint.h0
-rw-r--r--extern/bullet2/src/BulletDynamics/Dynamics/Bullet-C-API.cpp6
-rw-r--r--extern/carve/CMakeLists.txt1
-rw-r--r--extern/carve/SConscript1
-rwxr-xr-xextern/carve/bundle.sh6
-rw-r--r--extern/carve/include/carve/random/random.h61
-rw-r--r--extern/carve/lib/polyhedron.cpp6
-rw-r--r--extern/carve/patches/files/random.h61
-rw-r--r--extern/carve/patches/random.patch16
-rw-r--r--extern/carve/patches/series1
-rw-r--r--extern/clew/include/clew.h35
-rw-r--r--extern/glew-es/CMakeLists.txt57
-rw-r--r--extern/glew-es/SConscript16
-rw-r--r--extern/glew-es/include/GL/eglew.h1470
-rw-r--r--extern/glew-es/include/GL/glesew.h4318
-rw-r--r--extern/glew-es/include/GL/glew.h20525
-rw-r--r--extern/glew-es/include/GL/glxew.h1649
-rw-r--r--extern/glew-es/include/GL/wglew.h1424
-rw-r--r--extern/glew-es/src/glew.c22401
-rw-r--r--extern/glew/CMakeLists.txt6
-rw-r--r--extern/glew/SConscript11
-rw-r--r--extern/glew/include/GL/glew.h2496
-rw-r--r--extern/glew/include/GL/glxew.h476
-rw-r--r--extern/glew/include/GL/wglew.h458
-rw-r--r--extern/glew/src/glew.c2312
-rw-r--r--extern/gtest/CMakeLists.txt7
-rw-r--r--extern/libmv/CMakeLists.txt93
-rw-r--r--extern/libmv/ChangeLog774
-rw-r--r--extern/libmv/SConscript52
-rwxr-xr-xextern/libmv/bundle.sh128
-rw-r--r--extern/libmv/files.txt26
-rw-r--r--extern/libmv/intern/autotrack.cc99
-rw-r--r--extern/libmv/intern/autotrack.h71
-rw-r--r--extern/libmv/intern/camera_intrinsics.cc3
-rw-r--r--extern/libmv/intern/frame_accessor.cc164
-rw-r--r--extern/libmv/intern/frame_accessor.h79
-rw-r--r--extern/libmv/intern/image.cc6
-rw-r--r--extern/libmv/intern/image.h2
-rw-r--r--extern/libmv/intern/logging.cc18
-rw-r--r--extern/libmv/intern/reconstruction.cc16
-rw-r--r--extern/libmv/intern/reconstruction.h19
-rw-r--r--extern/libmv/intern/stub.cc83
-rw-r--r--extern/libmv/intern/track_region.h4
-rw-r--r--extern/libmv/intern/tracksN.cc138
-rw-r--r--extern/libmv/intern/tracksN.h129
-rw-r--r--extern/libmv/libmv-capi.h3
-rw-r--r--extern/libmv/libmv/autotrack/autotrack.cc291
-rw-r--r--extern/libmv/libmv/autotrack/autotrack.h226
-rw-r--r--extern/libmv/libmv/autotrack/callbacks.h38
-rw-r--r--extern/libmv/libmv/autotrack/frame_accessor.h86
-rw-r--r--extern/libmv/libmv/autotrack/marker.h144
-rw-r--r--extern/libmv/libmv/autotrack/model.h44
-rw-r--r--extern/libmv/libmv/autotrack/predict_tracks.cc316
-rw-r--r--extern/libmv/libmv/autotrack/predict_tracks.h37
-rw-r--r--extern/libmv/libmv/autotrack/predict_tracks_test.cc201
-rw-r--r--extern/libmv/libmv/autotrack/quad.h57
-rw-r--r--extern/libmv/libmv/autotrack/reconstruction.h89
-rw-r--r--extern/libmv/libmv/autotrack/region.h67
-rw-r--r--extern/libmv/libmv/autotrack/tracks.cc193
-rw-r--r--extern/libmv/libmv/autotrack/tracks.h82
-rw-r--r--extern/libmv/libmv/autotrack/tracks_test.cc52
-rw-r--r--extern/libmv/libmv/base/vector.h6
-rw-r--r--extern/libmv/libmv/image/array_nd.h24
-rw-r--r--extern/libmv/libmv/multiview/homography.cc25
-rw-r--r--extern/libmv/libmv/simple_pipeline/bundle.cc2
-rw-r--r--extern/libmv/libmv/simple_pipeline/keyframe_selection.cc67
-rw-r--r--extern/libmv/libmv/tracking/kalman_filter.h112
-rw-r--r--extern/libmv/libmv/tracking/track_region.h11
-rw-r--r--extern/libmv/third_party/ceres/CMakeLists.txt6
-rw-r--r--extern/libmv/third_party/ceres/ChangeLog379
-rw-r--r--extern/libmv/third_party/ceres/SConscript14
-rwxr-xr-xextern/libmv/third_party/ceres/bundle.sh22
-rw-r--r--extern/libmv/third_party/ceres/include/ceres/gradient_problem_solver.h16
-rw-r--r--extern/libmv/third_party/ceres/include/ceres/solver.h24
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/block_jacobi_preconditioner.cc109
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/block_jacobi_preconditioner.h18
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/block_random_access_diagonal_matrix.cc40
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/block_random_access_diagonal_matrix.h9
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/block_random_access_sparse_matrix.cc41
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/block_random_access_sparse_matrix.h22
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/callbacks.cc2
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/coordinate_descent_minimizer.cc17
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/linear_solver.cc6
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/linear_solver.h4
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/schur_complement_solver.cc158
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/schur_complement_solver.h11
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/schur_jacobi_preconditioner.cc30
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/schur_jacobi_preconditioner.h4
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/solver.cc8
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/trust_region_preprocessor.cc2
-rw-r--r--extern/libmv/third_party/gflags/AUTHORS.txt (renamed from extern/libmv/third_party/gflags/AUTHORS)0
-rw-r--r--extern/libmv/third_party/gflags/COPYING.txt (renamed from extern/libmv/third_party/gflags/COPYING)0
-rw-r--r--extern/libmv/third_party/gflags/ChangeLog195
-rw-r--r--extern/libmv/third_party/gflags/ChangeLog.txt208
-rw-r--r--extern/libmv/third_party/gflags/NEWS.txt (renamed from extern/libmv/third_party/gflags/NEWS)86
-rw-r--r--extern/libmv/third_party/gflags/README.libmv16
-rw-r--r--extern/libmv/third_party/gflags/config.h162
-rw-r--r--extern/libmv/third_party/gflags/gflags.cc117
-rw-r--r--extern/libmv/third_party/gflags/gflags/gflags.h180
-rw-r--r--extern/libmv/third_party/gflags/gflags/gflags_completions.h17
-rw-r--r--extern/libmv/third_party/gflags/gflags/gflags_declare.h92
-rw-r--r--extern/libmv/third_party/gflags/gflags_completions.cc14
-rw-r--r--extern/libmv/third_party/gflags/gflags_reporting.cc52
-rw-r--r--extern/libmv/third_party/gflags/mutex.h19
-rw-r--r--extern/libmv/third_party/gflags/util.h114
-rw-r--r--extern/libmv/third_party/gflags/windows_port.cc71
-rw-r--r--extern/libmv/third_party/gflags/windows_port.h127
-rw-r--r--extern/libmv/third_party/glog/README.libmv2
-rw-r--r--extern/libmv/third_party/glog/src/demangle.cc5
-rw-r--r--extern/libmv/third_party/glog/src/logging.cc5
-rw-r--r--extern/libmv/third_party/glog/src/symbolize.cc239
-rw-r--r--extern/libmv/third_party/glog/src/symbolize.h41
-rw-r--r--extern/libopenjpeg/CMakeLists.txt4
-rw-r--r--extern/libredcode/CMakeLists.txt2
-rw-r--r--extern/libredcode/format.c2
-rw-r--r--extern/lzo/CMakeLists.txt2
-rw-r--r--extern/lzo/minilzo/README.LZO9
-rw-r--r--extern/lzo/minilzo/lzoconf.h216
-rw-r--r--extern/lzo/minilzo/lzodefs.h2296
-rw-r--r--extern/lzo/minilzo/minilzo.c3776
-rw-r--r--extern/lzo/minilzo/minilzo.h26
-rw-r--r--extern/rangetree/range_tree.hh22
-rw-r--r--extern/rangetree/range_tree_c_api.cc16
-rw-r--r--extern/rangetree/range_tree_c_api.h18
-rw-r--r--extern/sdlew/CMakeLists.txt40
-rw-r--r--extern/sdlew/SConscript35
-rwxr-xr-xextern/sdlew/auto/sdlew_gen.sh250
-rwxr-xr-xextern/sdlew/auto/strip_comments.sh15
-rw-r--r--extern/sdlew/include/SDL2/SDL.h73
-rw-r--r--extern/sdlew/include/SDL2/SDL_assert.h140
-rw-r--r--extern/sdlew/include/SDL2/SDL_atomic.h185
-rw-r--r--extern/sdlew/include/SDL2/SDL_audio.h222
-rw-r--r--extern/sdlew/include/SDL2/SDL_bits.h53
-rw-r--r--extern/sdlew/include/SDL2/SDL_blendmode.h25
-rw-r--r--extern/sdlew/include/SDL2/SDL_clipboard.h29
-rw-r--r--extern/sdlew/include/SDL2/SDL_config.h175
-rw-r--r--extern/sdlew/include/SDL2/SDL_cpuinfo.h86
-rw-r--r--extern/sdlew/include/SDL2/SDL_endian.h193
-rw-r--r--extern/sdlew/include/SDL2/SDL_error.h43
-rw-r--r--extern/sdlew/include/SDL2/SDL_events.h446
-rw-r--r--extern/sdlew/include/SDL2/SDL_gamecontroller.h143
-rw-r--r--extern/sdlew/include/SDL2/SDL_gesture.h38
-rw-r--r--extern/sdlew/include/SDL2/SDL_haptic.h302
-rw-r--r--extern/sdlew/include/SDL2/SDL_hints.h87
-rw-r--r--extern/sdlew/include/SDL2/SDL_joystick.h106
-rw-r--r--extern/sdlew/include/SDL2/SDL_keyboard.h79
-rw-r--r--extern/sdlew/include/SDL2/SDL_keycode.h301
-rw-r--r--extern/sdlew/include/SDL2/SDL_loadso.h31
-rw-r--r--extern/sdlew/include/SDL2/SDL_log.h111
-rw-r--r--extern/sdlew/include/SDL2/SDL_main.h56
-rw-r--r--extern/sdlew/include/SDL2/SDL_messagebox.h80
-rw-r--r--extern/sdlew/include/SDL2/SDL_mouse.h101
-rw-r--r--extern/sdlew/include/SDL2/SDL_mutex.h91
-rw-r--r--extern/sdlew/include/SDL2/SDL_name.h11
-rw-r--r--extern/sdlew/include/SDL2/SDL_opengl.h10607
-rw-r--r--extern/sdlew/include/SDL2/SDL_opengles.h12
-rw-r--r--extern/sdlew/include/SDL2/SDL_opengles2.h12
-rw-r--r--extern/sdlew/include/SDL2/SDL_pixels.h320
-rw-r--r--extern/sdlew/include/SDL2/SDL_platform.h122
-rw-r--r--extern/sdlew/include/SDL2/SDL_power.h32
-rw-r--r--extern/sdlew/include/SDL2/SDL_quit.h11
-rw-r--r--extern/sdlew/include/SDL2/SDL_rect.h72
-rw-r--r--extern/sdlew/include/SDL2/SDL_render.h280
-rw-r--r--extern/sdlew/include/SDL2/SDL_revision.h2
-rw-r--r--extern/sdlew/include/SDL2/SDL_rwops.h162
-rw-r--r--extern/sdlew/include/SDL2/SDL_scancode.h273
-rw-r--r--extern/sdlew/include/SDL2/SDL_shape.h60
-rw-r--r--extern/sdlew/include/SDL2/SDL_stdinc.h378
-rw-r--r--extern/sdlew/include/SDL2/SDL_surface.h190
-rw-r--r--extern/sdlew/include/SDL2/SDL_system.h48
-rw-r--r--extern/sdlew/include/SDL2/SDL_syswm.h171
-rw-r--r--extern/sdlew/include/SDL2/SDL_test.h32
-rw-r--r--extern/sdlew/include/SDL2/SDL_test_assert.h33
-rw-r--r--extern/sdlew/include/SDL2/SDL_test_common.h103
-rw-r--r--extern/sdlew/include/SDL2/SDL_test_compare.h23
-rw-r--r--extern/sdlew/include/SDL2/SDL_test_crc32.h44
-rw-r--r--extern/sdlew/include/SDL2/SDL_test_font.h19
-rw-r--r--extern/sdlew/include/SDL2/SDL_test_fuzzer.h69
-rw-r--r--extern/sdlew/include/SDL2/SDL_test_harness.h67
-rw-r--r--extern/sdlew/include/SDL2/SDL_test_images.h38
-rw-r--r--extern/sdlew/include/SDL2/SDL_test_log.h21
-rw-r--r--extern/sdlew/include/SDL2/SDL_test_md5.h33
-rw-r--r--extern/sdlew/include/SDL2/SDL_test_random.h34
-rw-r--r--extern/sdlew/include/SDL2/SDL_thread.h90
-rw-r--r--extern/sdlew/include/SDL2/SDL_timer.h45
-rw-r--r--extern/sdlew/include/SDL2/SDL_touch.h47
-rw-r--r--extern/sdlew/include/SDL2/SDL_types.h2
-rw-r--r--extern/sdlew/include/SDL2/SDL_version.h56
-rw-r--r--extern/sdlew/include/SDL2/SDL_video.h367
-rw-r--r--extern/sdlew/include/SDL2/begin_code.h107
-rw-r--r--extern/sdlew/include/SDL2/close_code.h9
-rw-r--r--extern/sdlew/include/sdlew.h (renamed from intern/cycles/render/blackbody.h)25
-rw-r--r--extern/sdlew/src/sdlew.c1112
-rw-r--r--extern/sdlew/src/sdlew.map7
-rw-r--r--intern/CMakeLists.txt6
-rw-r--r--intern/SConscript9
-rw-r--r--intern/atomic/atomic_ops.h38
-rw-r--r--intern/audaspace/CMakeLists.txt34
-rw-r--r--intern/audaspace/OpenAL/AUD_OpenALDevice.cpp70
-rw-r--r--intern/audaspace/Python/AUD_PyAPI.cpp2
-rw-r--r--intern/audaspace/SConscript6
-rw-r--r--intern/audaspace/ffmpeg/AUD_FFMPEGWriter.cpp2
-rw-r--r--intern/audaspace/intern/AUD_AnimateableProperty.cpp10
-rw-r--r--intern/audaspace/intern/AUD_C-API.cpp341
-rw-r--r--intern/audaspace/intern/AUD_C-API.h264
-rw-r--r--intern/audaspace/intern/AUD_ConverterFunctions.h9
-rw-r--r--intern/audaspace/intern/AUD_PyInit.cpp78
-rw-r--r--intern/audaspace/intern/AUD_Sequencer.cpp2
-rw-r--r--intern/audaspace/intern/AUD_SequencerHandle.cpp256
-rw-r--r--intern/audaspace/intern/AUD_SequencerHandle.h18
-rw-r--r--intern/audaspace/intern/AUD_Set.cpp69
-rw-r--r--intern/audaspace/intern/AUD_Set.h74
-rw-r--r--intern/audaspace/intern/AUD_SoftwareDevice.cpp2
-rw-r--r--intern/cycles/CMakeLists.txt95
-rw-r--r--intern/cycles/SConscript44
-rw-r--r--intern/cycles/app/CMakeLists.txt79
-rw-r--r--intern/cycles/app/cycles_server.cpp20
-rw-r--r--intern/cycles/app/cycles_standalone.cpp58
-rw-r--r--intern/cycles/app/cycles_xml.cpp147
-rw-r--r--intern/cycles/app/cycles_xml.h2
-rw-r--r--intern/cycles/app/io_export_cycles_xml.py2
-rw-r--r--intern/cycles/blender/CCL_api.h2
-rw-r--r--intern/cycles/blender/CMakeLists.txt7
-rw-r--r--intern/cycles/blender/addon/__init__.py19
-rw-r--r--intern/cycles/blender/addon/engine.py59
-rw-r--r--intern/cycles/blender/addon/osl.py2
-rw-r--r--intern/cycles/blender/addon/presets.py2
-rw-r--r--intern/cycles/blender/addon/properties.py112
-rw-r--r--intern/cycles/blender/addon/ui.py237
-rw-r--r--intern/cycles/blender/addon/version_update.py85
-rw-r--r--intern/cycles/blender/blender_camera.cpp305
-rw-r--r--intern/cycles/blender/blender_curves.cpp125
-rw-r--r--intern/cycles/blender/blender_logging.cpp40
-rw-r--r--intern/cycles/blender/blender_mesh.cpp313
-rw-r--r--intern/cycles/blender/blender_object.cpp184
-rw-r--r--intern/cycles/blender/blender_particles.cpp4
-rw-r--r--intern/cycles/blender/blender_python.cpp122
-rw-r--r--intern/cycles/blender/blender_session.cpp280
-rw-r--r--intern/cycles/blender/blender_session.h9
-rw-r--r--intern/cycles/blender/blender_shader.cpp348
-rw-r--r--intern/cycles/blender/blender_sync.cpp116
-rw-r--r--intern/cycles/blender/blender_sync.h48
-rw-r--r--intern/cycles/blender/blender_texture.cpp116
-rw-r--r--intern/cycles/blender/blender_texture.h (renamed from intern/cycles/util/util_dynlib.h)22
-rw-r--r--intern/cycles/blender/blender_util.h42
-rw-r--r--intern/cycles/bvh/bvh.cpp581
-rw-r--r--intern/cycles/bvh/bvh.h30
-rw-r--r--intern/cycles/bvh/bvh_binning.cpp14
-rw-r--r--intern/cycles/bvh/bvh_build.cpp235
-rw-r--r--intern/cycles/bvh/bvh_build.h29
-rw-r--r--intern/cycles/bvh/bvh_node.cpp14
-rw-r--r--intern/cycles/bvh/bvh_node.h6
-rw-r--r--intern/cycles/bvh/bvh_params.h20
-rw-r--r--intern/cycles/bvh/bvh_split.cpp237
-rw-r--r--intern/cycles/bvh/bvh_split.h53
-rw-r--r--intern/cycles/cmake/external_libs.cmake116
-rw-r--r--intern/cycles/device/CMakeLists.txt6
-rw-r--r--intern/cycles/device/device.cpp132
-rw-r--r--intern/cycles/device/device.h97
-rw-r--r--intern/cycles/device/device_cpu.cpp409
-rw-r--r--intern/cycles/device/device_cuda.cpp314
-rw-r--r--intern/cycles/device/device_intern.h6
-rw-r--r--intern/cycles/device/device_memory.h14
-rw-r--r--intern/cycles/device/device_multi.cpp21
-rw-r--r--intern/cycles/device/device_network.cpp36
-rw-r--r--intern/cycles/device/device_network.h2
-rw-r--r--intern/cycles/device/device_opencl.cpp3254
-rw-r--r--intern/cycles/device/device_task.cpp4
-rw-r--r--intern/cycles/device/device_task.h13
-rw-r--r--intern/cycles/kernel/CMakeLists.txt115
-rw-r--r--intern/cycles/kernel/SConscript12
-rw-r--r--intern/cycles/kernel/closure/bsdf.h174
-rw-r--r--intern/cycles/kernel/closure/bsdf_ashikhmin_shirley.h53
-rw-r--r--intern/cycles/kernel/closure/bsdf_ashikhmin_velvet.h10
-rw-r--r--intern/cycles/kernel/closure/bsdf_diffuse.h13
-rw-r--r--intern/cycles/kernel/closure/bsdf_diffuse_ramp.h8
-rw-r--r--intern/cycles/kernel/closure/bsdf_hair.h120
-rw-r--r--intern/cycles/kernel/closure/bsdf_microfacet.h309
-rw-r--r--intern/cycles/kernel/closure/bsdf_oren_nayar.h18
-rw-r--r--intern/cycles/kernel/closure/bsdf_phong_ramp.h20
-rw-r--r--intern/cycles/kernel/closure/bsdf_reflection.h9
-rw-r--r--intern/cycles/kernel/closure/bsdf_refraction.h16
-rw-r--r--intern/cycles/kernel/closure/bsdf_toon.h16
-rw-r--r--intern/cycles/kernel/closure/bsdf_transparent.h4
-rw-r--r--intern/cycles/kernel/closure/bsdf_westin.h180
-rw-r--r--intern/cycles/kernel/closure/bssrdf.h10
-rw-r--r--intern/cycles/kernel/closure/volume.h33
-rw-r--r--intern/cycles/kernel/geom/geom.h5
-rw-r--r--intern/cycles/kernel/geom/geom_attribute.h13
-rw-r--r--intern/cycles/kernel/geom/geom_bvh.h208
-rw-r--r--intern/cycles/kernel/geom/geom_bvh_shadow.h100
-rw-r--r--intern/cycles/kernel/geom/geom_bvh_subsurface.h132
-rw-r--r--intern/cycles/kernel/geom/geom_bvh_traversal.h210
-rw-r--r--intern/cycles/kernel/geom/geom_bvh_volume.h358
-rw-r--r--intern/cycles/kernel/geom/geom_bvh_volume_all.h454
-rw-r--r--intern/cycles/kernel/geom/geom_curve.h148
-rw-r--r--intern/cycles/kernel/geom/geom_motion_curve.h11
-rw-r--r--intern/cycles/kernel/geom/geom_motion_triangle.h59
-rw-r--r--intern/cycles/kernel/geom/geom_object.h134
-rw-r--r--intern/cycles/kernel/geom/geom_primitive.h46
-rw-r--r--intern/cycles/kernel/geom/geom_qbvh.h147
-rw-r--r--intern/cycles/kernel/geom/geom_qbvh_shadow.h403
-rw-r--r--intern/cycles/kernel/geom/geom_qbvh_subsurface.h326
-rw-r--r--intern/cycles/kernel/geom/geom_qbvh_traversal.h425
-rw-r--r--intern/cycles/kernel/geom/geom_qbvh_volume.h351
-rw-r--r--intern/cycles/kernel/geom/geom_qbvh_volume_all.h446
-rw-r--r--intern/cycles/kernel/geom/geom_triangle.h255
-rw-r--r--intern/cycles/kernel/geom/geom_triangle_intersect.h431
-rw-r--r--intern/cycles/kernel/geom/geom_volume.h16
-rw-r--r--intern/cycles/kernel/kernel.h11
-rw-r--r--intern/cycles/kernel/kernel_accumulate.h12
-rw-r--r--intern/cycles/kernel/kernel_bake.h33
-rw-r--r--intern/cycles/kernel/kernel_camera.h96
-rw-r--r--intern/cycles/kernel/kernel_compat_cpu.h355
-rw-r--r--intern/cycles/kernel/kernel_compat_cuda.h24
-rw-r--r--intern/cycles/kernel/kernel_compat_opencl.h80
-rw-r--r--intern/cycles/kernel/kernel_debug.h50
-rw-r--r--intern/cycles/kernel/kernel_differential.h8
-rw-r--r--intern/cycles/kernel/kernel_emission.h93
-rw-r--r--intern/cycles/kernel/kernel_film.h12
-rw-r--r--intern/cycles/kernel/kernel_globals.h8
-rw-r--r--intern/cycles/kernel/kernel_jitter.h12
-rw-r--r--intern/cycles/kernel/kernel_light.h416
-rw-r--r--intern/cycles/kernel/kernel_math.h3
-rw-r--r--intern/cycles/kernel/kernel_passes.h42
-rw-r--r--intern/cycles/kernel/kernel_path.h607
-rw-r--r--intern/cycles/kernel/kernel_path_branched.h534
-rw-r--r--intern/cycles/kernel/kernel_path_common.h50
-rw-r--r--intern/cycles/kernel/kernel_path_state.h10
-rw-r--r--intern/cycles/kernel/kernel_path_surface.h56
-rw-r--r--intern/cycles/kernel/kernel_path_volume.h32
-rw-r--r--intern/cycles/kernel/kernel_projection.h34
-rw-r--r--intern/cycles/kernel/kernel_queues.h125
-rw-r--r--intern/cycles/kernel/kernel_random.h20
-rw-r--r--intern/cycles/kernel/kernel_shader.h318
-rw-r--r--intern/cycles/kernel/kernel_shaderdata_vars.h99
-rw-r--r--intern/cycles/kernel/kernel_shadow.h70
-rw-r--r--intern/cycles/kernel/kernel_subsurface.h2
-rw-r--r--intern/cycles/kernel/kernel_textures.h3
-rw-r--r--intern/cycles/kernel/kernel_types.h468
-rw-r--r--intern/cycles/kernel/kernel_volume.h197
-rw-r--r--intern/cycles/kernel/kernel_work_stealing.h193
-rw-r--r--intern/cycles/kernel/kernels/cpu/kernel.cpp (renamed from intern/cycles/kernel/kernel.cpp)20
-rw-r--r--intern/cycles/kernel/kernels/cpu/kernel_avx.cpp (renamed from intern/cycles/kernel/kernel_avx.cpp)5
-rw-r--r--intern/cycles/kernel/kernels/cpu/kernel_avx2.cpp (renamed from intern/cycles/kernel/kernel_avx2.cpp)5
-rw-r--r--intern/cycles/kernel/kernels/cpu/kernel_sse2.cpp (renamed from intern/cycles/kernel/kernel_sse2.cpp)5
-rw-r--r--intern/cycles/kernel/kernels/cpu/kernel_sse3.cpp (renamed from intern/cycles/kernel/kernel_sse3.cpp)5
-rw-r--r--intern/cycles/kernel/kernels/cpu/kernel_sse41.cpp (renamed from intern/cycles/kernel/kernel_sse41.cpp)5
-rw-r--r--intern/cycles/kernel/kernels/cuda/kernel.cu (renamed from intern/cycles/kernel/kernel.cu)29
-rw-r--r--intern/cycles/kernel/kernels/opencl/kernel.cl (renamed from intern/cycles/kernel/kernel.cl)103
-rw-r--r--intern/cycles/kernel/kernels/opencl/kernel_background_buffer_update.cl128
-rw-r--r--intern/cycles/kernel/kernels/opencl/kernel_data_init.cl241
-rw-r--r--intern/cycles/kernel/kernels/opencl/kernel_direct_lighting.cl90
-rw-r--r--intern/cycles/kernel/kernels/opencl/kernel_holdout_emission_blurring_pathtermination_ao.cl124
-rw-r--r--intern/cycles/kernel/kernels/opencl/kernel_lamp_emission.cl84
-rw-r--r--intern/cycles/kernel/kernels/opencl/kernel_next_iteration_setup.cl115
-rw-r--r--intern/cycles/kernel/kernels/opencl/kernel_queue_enqueue.cl106
-rw-r--r--intern/cycles/kernel/kernels/opencl/kernel_scene_intersect.cl82
-rw-r--r--intern/cycles/kernel/kernels/opencl/kernel_shader_eval.cl69
-rw-r--r--intern/cycles/kernel/kernels/opencl/kernel_shadow_blocked.cl83
-rw-r--r--intern/cycles/kernel/kernels/opencl/kernel_sum_all_radiance.cl38
-rw-r--r--intern/cycles/kernel/osl/SConscript27
-rw-r--r--intern/cycles/kernel/osl/background.cpp4
-rw-r--r--intern/cycles/kernel/osl/bsdf_diffuse_ramp.cpp3
-rw-r--r--intern/cycles/kernel/osl/bsdf_phong_ramp.cpp3
-rw-r--r--intern/cycles/kernel/osl/emissive.cpp2
-rw-r--r--intern/cycles/kernel/osl/osl_bssrdf.cpp5
-rw-r--r--intern/cycles/kernel/osl/osl_closures.cpp31
-rw-r--r--intern/cycles/kernel/osl/osl_closures.h25
-rw-r--r--intern/cycles/kernel/osl/osl_globals.h3
-rw-r--r--intern/cycles/kernel/osl/osl_services.cpp242
-rw-r--r--intern/cycles/kernel/osl/osl_services.h137
-rw-r--r--intern/cycles/kernel/osl/osl_shader.cpp454
-rw-r--r--intern/cycles/kernel/osl/osl_shader.h2
-rw-r--r--intern/cycles/kernel/shaders/CMakeLists.txt1
-rw-r--r--intern/cycles/kernel/shaders/node_absorption_volume.osl2
-rw-r--r--intern/cycles/kernel/shaders/node_add_closure.osl2
-rw-r--r--intern/cycles/kernel/shaders/node_ambient_occlusion.osl2
-rw-r--r--intern/cycles/kernel/shaders/node_anisotropic_bsdf.osl2
-rw-r--r--intern/cycles/kernel/shaders/node_attribute.osl2
-rw-r--r--intern/cycles/kernel/shaders/node_background.osl2
-rw-r--r--intern/cycles/kernel/shaders/node_blackbody.osl2
-rw-r--r--intern/cycles/kernel/shaders/node_brick_texture.osl10
-rw-r--r--intern/cycles/kernel/shaders/node_brightness.osl2
-rw-r--r--intern/cycles/kernel/shaders/node_bump.osl2
-rw-r--r--intern/cycles/kernel/shaders/node_camera.osl2
-rw-r--r--intern/cycles/kernel/shaders/node_checker_texture.osl2
-rw-r--r--intern/cycles/kernel/shaders/node_color.h2
-rw-r--r--intern/cycles/kernel/shaders/node_combine_hsv.osl2
-rw-r--r--intern/cycles/kernel/shaders/node_combine_rgb.osl2
-rw-r--r--intern/cycles/kernel/shaders/node_combine_xyz.osl2
-rw-r--r--intern/cycles/kernel/shaders/node_convert_from_color.osl2
-rw-r--r--intern/cycles/kernel/shaders/node_convert_from_float.osl2
-rw-r--r--intern/cycles/kernel/shaders/node_convert_from_int.osl2
-rw-r--r--intern/cycles/kernel/shaders/node_convert_from_normal.osl2
-rw-r--r--intern/cycles/kernel/shaders/node_convert_from_point.osl2
-rw-r--r--intern/cycles/kernel/shaders/node_convert_from_string.osl2
-rw-r--r--intern/cycles/kernel/shaders/node_convert_from_vector.osl2
-rw-r--r--intern/cycles/kernel/shaders/node_diffuse_bsdf.osl2
-rw-r--r--intern/cycles/kernel/shaders/node_emission.osl2
-rw-r--r--intern/cycles/kernel/shaders/node_environment_texture.osl2
-rw-r--r--intern/cycles/kernel/shaders/node_fresnel.h8
-rw-r--r--intern/cycles/kernel/shaders/node_fresnel.osl2
-rw-r--r--intern/cycles/kernel/shaders/node_gamma.osl2
-rw-r--r--intern/cycles/kernel/shaders/node_geometry.osl15
-rw-r--r--intern/cycles/kernel/shaders/node_glass_bsdf.osl2
-rw-r--r--intern/cycles/kernel/shaders/node_glossy_bsdf.osl2
-rw-r--r--intern/cycles/kernel/shaders/node_gradient_texture.osl2
-rw-r--r--intern/cycles/kernel/shaders/node_hair_info.osl2
-rw-r--r--intern/cycles/kernel/shaders/node_holdout.osl2
-rw-r--r--intern/cycles/kernel/shaders/node_hsv.osl7
-rw-r--r--intern/cycles/kernel/shaders/node_image_texture.osl115
-rw-r--r--intern/cycles/kernel/shaders/node_invert.osl2
-rw-r--r--intern/cycles/kernel/shaders/node_layer_weight.osl2
-rw-r--r--intern/cycles/kernel/shaders/node_light_falloff.osl2
-rw-r--r--intern/cycles/kernel/shaders/node_light_path.osl2
-rw-r--r--intern/cycles/kernel/shaders/node_magic_texture.osl2
-rw-r--r--intern/cycles/kernel/shaders/node_mapping.osl2
-rw-r--r--intern/cycles/kernel/shaders/node_math.osl6
-rw-r--r--intern/cycles/kernel/shaders/node_mix.osl2
-rw-r--r--intern/cycles/kernel/shaders/node_mix_closure.osl2
-rw-r--r--intern/cycles/kernel/shaders/node_musgrave_texture.osl51
-rw-r--r--intern/cycles/kernel/shaders/node_noise_texture.osl19
-rw-r--r--intern/cycles/kernel/shaders/node_normal.osl4
-rw-r--r--intern/cycles/kernel/shaders/node_normal_map.osl2
-rw-r--r--intern/cycles/kernel/shaders/node_object_info.osl2
-rw-r--r--intern/cycles/kernel/shaders/node_output_displacement.osl2
-rw-r--r--intern/cycles/kernel/shaders/node_output_surface.osl2
-rw-r--r--intern/cycles/kernel/shaders/node_output_volume.osl2
-rw-r--r--intern/cycles/kernel/shaders/node_particle_info.osl2
-rw-r--r--intern/cycles/kernel/shaders/node_refraction_bsdf.osl2
-rw-r--r--intern/cycles/kernel/shaders/node_rgb_curves.osl2
-rw-r--r--intern/cycles/kernel/shaders/node_rgb_ramp.osl2
-rw-r--r--intern/cycles/kernel/shaders/node_scatter_volume.osl2
-rw-r--r--intern/cycles/kernel/shaders/node_separate_hsv.osl2
-rw-r--r--intern/cycles/kernel/shaders/node_separate_rgb.osl2
-rw-r--r--intern/cycles/kernel/shaders/node_separate_xyz.osl2
-rw-r--r--intern/cycles/kernel/shaders/node_set_normal.osl2
-rw-r--r--intern/cycles/kernel/shaders/node_sky_texture.osl2
-rw-r--r--intern/cycles/kernel/shaders/node_subsurface_scattering.osl2
-rw-r--r--intern/cycles/kernel/shaders/node_tangent.osl2
-rw-r--r--intern/cycles/kernel/shaders/node_texture.h112
-rw-r--r--intern/cycles/kernel/shaders/node_texture_coordinate.osl11
-rw-r--r--intern/cycles/kernel/shaders/node_toon_bsdf.osl2
-rw-r--r--intern/cycles/kernel/shaders/node_translucent_bsdf.osl2
-rw-r--r--intern/cycles/kernel/shaders/node_transparent_bsdf.osl2
-rw-r--r--intern/cycles/kernel/shaders/node_uv_map.osl2
-rw-r--r--intern/cycles/kernel/shaders/node_value.osl2
-rw-r--r--intern/cycles/kernel/shaders/node_vector_curves.osl2
-rw-r--r--intern/cycles/kernel/shaders/node_vector_math.osl2
-rw-r--r--intern/cycles/kernel/shaders/node_vector_transform.osl2
-rw-r--r--intern/cycles/kernel/shaders/node_velvet_bsdf.osl2
-rw-r--r--intern/cycles/kernel/shaders/node_voronoi_texture.osl4
-rw-r--r--intern/cycles/kernel/shaders/node_voxel_texture.osl47
-rw-r--r--intern/cycles/kernel/shaders/node_wave_texture.osl4
-rw-r--r--intern/cycles/kernel/shaders/node_wavelength.osl2
-rw-r--r--intern/cycles/kernel/shaders/node_wireframe.osl18
-rw-r--r--intern/cycles/kernel/shaders/stdosl.h57
-rw-r--r--intern/cycles/kernel/split/kernel_background_buffer_update.h254
-rw-r--r--intern/cycles/kernel/split/kernel_data_init.h415
-rw-r--r--intern/cycles/kernel/split/kernel_direct_lighting.h116
-rw-r--r--intern/cycles/kernel/split/kernel_holdout_emission_blurring_pathtermination_ao.h264
-rw-r--r--intern/cycles/kernel/split/kernel_lamp_emission.h179
-rw-r--r--intern/cycles/kernel/split/kernel_next_iteration_setup.h144
-rw-r--r--intern/cycles/kernel/split/kernel_scene_intersect.h138
-rw-r--r--intern/cycles/kernel/split/kernel_shader_eval.h75
-rw-r--r--intern/cycles/kernel/split/kernel_shadow_blocked.h99
-rw-r--r--intern/cycles/kernel/split/kernel_split_common.h62
-rw-r--r--intern/cycles/kernel/split/kernel_sum_all_radiance.h59
-rw-r--r--intern/cycles/kernel/svm/svm.h303
-rw-r--r--intern/cycles/kernel/svm/svm_attribute.h8
-rw-r--r--intern/cycles/kernel/svm/svm_blackbody.h40
-rw-r--r--intern/cycles/kernel/svm/svm_brick.h10
-rw-r--r--intern/cycles/kernel/svm/svm_brightness.h4
-rw-r--r--intern/cycles/kernel/svm/svm_camera.h10
-rw-r--r--intern/cycles/kernel/svm/svm_checker.h2
-rw-r--r--intern/cycles/kernel/svm/svm_closure.h183
-rw-r--r--intern/cycles/kernel/svm/svm_convert.h2
-rw-r--r--intern/cycles/kernel/svm/svm_displace.h12
-rw-r--r--intern/cycles/kernel/svm/svm_fresnel.h16
-rw-r--r--intern/cycles/kernel/svm/svm_gamma.h10
-rw-r--r--intern/cycles/kernel/svm/svm_geometry.h44
-rw-r--r--intern/cycles/kernel/svm/svm_gradient.h4
-rw-r--r--intern/cycles/kernel/svm/svm_hsv.h9
-rw-r--r--intern/cycles/kernel/svm/svm_image.h43
-rw-r--r--intern/cycles/kernel/svm/svm_invert.h4
-rw-r--r--intern/cycles/kernel/svm/svm_light_path.h16
-rw-r--r--intern/cycles/kernel/svm/svm_magic.h2
-rw-r--r--intern/cycles/kernel/svm/svm_mapping.h2
-rw-r--r--intern/cycles/kernel/svm/svm_math.h90
-rw-r--r--intern/cycles/kernel/svm/svm_math_util.h170
-rw-r--r--intern/cycles/kernel/svm/svm_mix.h10
-rw-r--r--intern/cycles/kernel/svm/svm_musgrave.h26
-rw-r--r--intern/cycles/kernel/svm/svm_noise.h49
-rw-r--r--intern/cycles/kernel/svm/svm_noisetex.h15
-rw-r--r--intern/cycles/kernel/svm/svm_normal.h6
-rw-r--r--intern/cycles/kernel/svm/svm_ramp.h4
-rw-r--r--intern/cycles/kernel/svm/svm_sepcomb_hsv.h10
-rw-r--r--intern/cycles/kernel/svm/svm_sepcomb_vector.h10
-rw-r--r--intern/cycles/kernel/svm/svm_sky.h2
-rw-r--r--intern/cycles/kernel/svm/svm_tex_coord.h186
-rw-r--r--intern/cycles/kernel/svm/svm_texture.h260
-rw-r--r--intern/cycles/kernel/svm/svm_types.h69
-rw-r--r--intern/cycles/kernel/svm/svm_value.h2
-rw-r--r--intern/cycles/kernel/svm/svm_vector_transform.h8
-rw-r--r--intern/cycles/kernel/svm/svm_voronoi.h88
-rw-r--r--intern/cycles/kernel/svm/svm_voxel.h64
-rw-r--r--intern/cycles/kernel/svm/svm_wave.h4
-rw-r--r--intern/cycles/kernel/svm/svm_wavelength.h2
-rw-r--r--intern/cycles/kernel/svm/svm_wireframe.h88
-rw-r--r--intern/cycles/render/CMakeLists.txt8
-rw-r--r--intern/cycles/render/attribute.cpp12
-rw-r--r--intern/cycles/render/attribute.h2
-rw-r--r--intern/cycles/render/background.cpp31
-rw-r--r--intern/cycles/render/background.h2
-rw-r--r--intern/cycles/render/bake.cpp14
-rw-r--r--intern/cycles/render/bake.h3
-rw-r--r--intern/cycles/render/blackbody.cpp140
-rw-r--r--intern/cycles/render/buffers.cpp26
-rw-r--r--intern/cycles/render/buffers.h2
-rw-r--r--intern/cycles/render/camera.cpp211
-rw-r--r--intern/cycles/render/camera.h28
-rw-r--r--intern/cycles/render/curves.cpp12
-rw-r--r--intern/cycles/render/curves.h2
-rw-r--r--intern/cycles/render/film.cpp45
-rw-r--r--intern/cycles/render/film.h2
-rw-r--r--intern/cycles/render/graph.cpp213
-rw-r--r--intern/cycles/render/graph.h32
-rw-r--r--intern/cycles/render/image.cpp151
-rw-r--r--intern/cycles/render/image.h31
-rw-r--r--intern/cycles/render/integrator.cpp11
-rw-r--r--intern/cycles/render/integrator.h3
-rw-r--r--intern/cycles/render/light.cpp264
-rw-r--r--intern/cycles/render/light.h8
-rw-r--r--intern/cycles/render/mesh.cpp306
-rw-r--r--intern/cycles/render/mesh.h16
-rw-r--r--intern/cycles/render/mesh_displace.cpp2
-rw-r--r--intern/cycles/render/nodes.cpp427
-rw-r--r--intern/cycles/render/nodes.h125
-rw-r--r--intern/cycles/render/object.cpp97
-rw-r--r--intern/cycles/render/object.h8
-rw-r--r--intern/cycles/render/osl.cpp88
-rw-r--r--intern/cycles/render/osl.h2
-rw-r--r--intern/cycles/render/particles.cpp8
-rw-r--r--intern/cycles/render/particles.h2
-rw-r--r--intern/cycles/render/scene.cpp82
-rw-r--r--intern/cycles/render/scene.h8
-rw-r--r--intern/cycles/render/session.cpp133
-rw-r--r--intern/cycles/render/session.h20
-rw-r--r--intern/cycles/render/shader.cpp124
-rw-r--r--intern/cycles/render/shader.h50
-rw-r--r--intern/cycles/render/sky_model.cpp433
-rw-r--r--intern/cycles/render/sky_model.h296
-rw-r--r--intern/cycles/render/sky_model_data.h29
-rw-r--r--intern/cycles/render/sobol.h2
-rw-r--r--intern/cycles/render/svm.cpp17
-rw-r--r--intern/cycles/render/svm.h2
-rw-r--r--intern/cycles/render/tables.cpp5
-rw-r--r--intern/cycles/render/tables.h2
-rw-r--r--intern/cycles/render/tile.cpp9
-rw-r--r--intern/cycles/render/tile.h2
-rw-r--r--intern/cycles/subd/subd_dice.cpp6
-rw-r--r--intern/cycles/subd/subd_dice.h2
-rw-r--r--intern/cycles/subd/subd_mesh.cpp6
-rw-r--r--intern/cycles/subd/subd_patch.cpp2
-rw-r--r--intern/cycles/subd/subd_patch.h2
-rw-r--r--intern/cycles/subd/subd_split.cpp2
-rw-r--r--intern/cycles/subd/subd_split.h2
-rw-r--r--intern/cycles/util/CMakeLists.txt25
-rw-r--r--intern/cycles/util/util_algorithm.h2
-rw-r--r--intern/cycles/util/util_aligned_malloc.cpp83
-rw-r--r--intern/cycles/util/util_aligned_malloc.h32
-rw-r--r--intern/cycles/util/util_args.h2
-rw-r--r--intern/cycles/util/util_atomic.h65
-rw-r--r--intern/cycles/util/util_boundbox.h2
-rw-r--r--intern/cycles/util/util_cache.cpp8
-rw-r--r--intern/cycles/util/util_cache.h4
-rw-r--r--intern/cycles/util/util_color.h2
-rw-r--r--intern/cycles/util/util_debug.h2
-rw-r--r--intern/cycles/util/util_dynlib.cpp94
-rw-r--r--intern/cycles/util/util_foreach.h10
-rw-r--r--intern/cycles/util/util_function.h29
-rw-r--r--intern/cycles/util/util_guarded_allocator.cpp49
-rw-r--r--intern/cycles/util/util_guarded_allocator.h86
-rw-r--r--intern/cycles/util/util_half.h32
-rw-r--r--intern/cycles/util/util_hash.h4
-rw-r--r--intern/cycles/util/util_image.h2
-rw-r--r--intern/cycles/util/util_list.h2
-rw-r--r--intern/cycles/util/util_logging.cpp50
-rw-r--r--intern/cycles/util/util_logging.h8
-rw-r--r--intern/cycles/util/util_map.h29
-rw-r--r--intern/cycles/util/util_math.h110
-rw-r--r--intern/cycles/util/util_math_fast.h611
-rw-r--r--intern/cycles/util/util_md5.cpp12
-rw-r--r--intern/cycles/util/util_opengl.h11
-rw-r--r--intern/cycles/util/util_optimization.h28
-rw-r--r--intern/cycles/util/util_param.h2
-rw-r--r--intern/cycles/util/util_path.cpp55
-rw-r--r--intern/cycles/util/util_path.h2
-rw-r--r--intern/cycles/util/util_progress.h73
-rw-r--r--intern/cycles/util/util_set.h14
-rw-r--r--intern/cycles/util/util_simd.cpp2
-rw-r--r--intern/cycles/util/util_simd.h16
-rw-r--r--intern/cycles/util/util_sseb.h29
-rw-r--r--intern/cycles/util/util_ssef.h56
-rw-r--r--intern/cycles/util/util_ssei.h22
-rw-r--r--intern/cycles/util/util_stats.h11
-rw-r--r--intern/cycles/util/util_string.cpp19
-rw-r--r--intern/cycles/util/util_string.h4
-rw-r--r--intern/cycles/util/util_system.cpp61
-rw-r--r--intern/cycles/util/util_system.h2
-rw-r--r--intern/cycles/util/util_task.cpp4
-rw-r--r--intern/cycles/util/util_task.h4
-rw-r--r--intern/cycles/util/util_thread.h23
-rw-r--r--intern/cycles/util/util_time.cpp4
-rw-r--r--intern/cycles/util/util_time.h2
-rw-r--r--intern/cycles/util/util_transform.cpp18
-rw-r--r--intern/cycles/util/util_transform.h46
-rw-r--r--intern/cycles/util/util_types.h58
-rw-r--r--intern/cycles/util/util_vector.h124
-rw-r--r--intern/cycles/util/util_view.cpp7
-rw-r--r--intern/cycles/util/util_view.h2
-rw-r--r--intern/cycles/util/util_xml.h6
-rw-r--r--intern/dualcon/CMakeLists.txt2
-rw-r--r--intern/dualcon/dualcon.h16
-rw-r--r--intern/dualcon/intern/Projections.cpp2
-rw-r--r--intern/dualcon/intern/dualcon_c_api.cpp70
-rw-r--r--intern/dualcon/intern/octree.cpp8
-rw-r--r--intern/ghost/CMakeLists.txt127
-rw-r--r--intern/ghost/GHOST_C-api.h81
-rw-r--r--intern/ghost/GHOST_ISystem.h15
-rw-r--r--intern/ghost/GHOST_ITimerTask.h2
-rw-r--r--intern/ghost/GHOST_IWindow.h44
-rw-r--r--intern/ghost/GHOST_Types.h40
-rw-r--r--intern/ghost/SConscript77
-rw-r--r--intern/ghost/intern/GHOST_Buttons.h8
-rw-r--r--intern/ghost/intern/GHOST_C-api.cpp48
-rw-r--r--intern/ghost/intern/GHOST_CallbackEventConsumer.h4
-rw-r--r--intern/ghost/intern/GHOST_Context.cpp159
-rw-r--r--intern/ghost/intern/GHOST_Context.h161
-rw-r--r--intern/ghost/intern/GHOST_ContextCGL.h153
-rw-r--r--intern/ghost/intern/GHOST_ContextCGL.mm354
-rw-r--r--intern/ghost/intern/GHOST_ContextEGL.cpp640
-rw-r--r--intern/ghost/intern/GHOST_ContextEGL.h167
-rw-r--r--intern/ghost/intern/GHOST_ContextGLX.cpp411
-rw-r--r--intern/ghost/intern/GHOST_ContextGLX.h156
-rw-r--r--intern/ghost/intern/GHOST_ContextNone.cpp79
-rw-r--r--intern/ghost/intern/GHOST_ContextNone.h97
-rw-r--r--intern/ghost/intern/GHOST_ContextSDL.cpp204
-rw-r--r--intern/ghost/intern/GHOST_ContextSDL.h131
-rw-r--r--intern/ghost/intern/GHOST_ContextWGL.cpp956
-rw-r--r--intern/ghost/intern/GHOST_ContextWGL.h190
-rw-r--r--intern/ghost/intern/GHOST_Debug.h2
-rw-r--r--intern/ghost/intern/GHOST_DisplayManagerCocoa.h12
-rw-r--r--intern/ghost/intern/GHOST_DisplayManagerWin32.h12
-rw-r--r--intern/ghost/intern/GHOST_DisplayManagerX11.cpp8
-rw-r--r--intern/ghost/intern/GHOST_DisplayManagerX11.h2
-rw-r--r--intern/ghost/intern/GHOST_DropTargetWin32.h2
-rw-r--r--intern/ghost/intern/GHOST_DropTargetX11.cpp3
-rw-r--r--intern/ghost/intern/GHOST_Event.h8
-rw-r--r--intern/ghost/intern/GHOST_EventButton.h5
-rw-r--r--intern/ghost/intern/GHOST_EventDragnDrop.h1
-rw-r--r--intern/ghost/intern/GHOST_EventManager.h28
-rw-r--r--intern/ghost/intern/GHOST_EventPrinter.cpp3
-rw-r--r--intern/ghost/intern/GHOST_EventPrinter.h2
-rw-r--r--intern/ghost/intern/GHOST_EventTrackpad.h2
-rw-r--r--intern/ghost/intern/GHOST_EventWheel.h6
-rw-r--r--intern/ghost/intern/GHOST_ISystem.cpp39
-rw-r--r--intern/ghost/intern/GHOST_ImeWin32.cpp520
-rw-r--r--intern/ghost/intern/GHOST_ImeWin32.h405
-rw-r--r--intern/ghost/intern/GHOST_ModifierKeys.h18
-rw-r--r--intern/ghost/intern/GHOST_NDOFManager.cpp61
-rw-r--r--intern/ghost/intern/GHOST_NDOFManager.h4
-rw-r--r--intern/ghost/intern/GHOST_NDOFManagerWin32.cpp2
-rw-r--r--intern/ghost/intern/GHOST_NDOFManagerX11.cpp12
-rw-r--r--intern/ghost/intern/GHOST_System.cpp24
-rw-r--r--intern/ghost/intern/GHOST_System.h50
-rw-r--r--intern/ghost/intern/GHOST_SystemCocoa.h35
-rw-r--r--intern/ghost/intern/GHOST_SystemCocoa.mm224
-rw-r--r--intern/ghost/intern/GHOST_SystemNULL.h6
-rw-r--r--intern/ghost/intern/GHOST_SystemPathsCocoa.h6
-rw-r--r--intern/ghost/intern/GHOST_SystemPathsCocoa.mm9
-rw-r--r--intern/ghost/intern/GHOST_SystemPathsWin32.h2
-rw-r--r--intern/ghost/intern/GHOST_SystemPathsX11.cpp2
-rw-r--r--intern/ghost/intern/GHOST_SystemPathsX11.h2
-rw-r--r--intern/ghost/intern/GHOST_SystemSDL.cpp14
-rw-r--r--intern/ghost/intern/GHOST_SystemSDL.h3
-rw-r--r--intern/ghost/intern/GHOST_SystemWin32.cpp207
-rw-r--r--intern/ghost/intern/GHOST_SystemWin32.h96
-rw-r--r--intern/ghost/intern/GHOST_SystemX11.cpp49
-rw-r--r--intern/ghost/intern/GHOST_SystemX11.h25
-rw-r--r--intern/ghost/intern/GHOST_TimerManager.h16
-rw-r--r--intern/ghost/intern/GHOST_TimerTask.h30
-rw-r--r--intern/ghost/intern/GHOST_Window.cpp70
-rw-r--r--intern/ghost/intern/GHOST_Window.h191
-rw-r--r--intern/ghost/intern/GHOST_WindowCocoa.h110
-rw-r--r--intern/ghost/intern/GHOST_WindowCocoa.mm448
-rw-r--r--intern/ghost/intern/GHOST_WindowManager.cpp2
-rw-r--r--intern/ghost/intern/GHOST_WindowManager.h24
-rw-r--r--intern/ghost/intern/GHOST_WindowNULL.h8
-rw-r--r--intern/ghost/intern/GHOST_WindowSDL.cpp184
-rw-r--r--intern/ghost/intern/GHOST_WindowSDL.h25
-rw-r--r--intern/ghost/intern/GHOST_WindowWin32.cpp621
-rw-r--r--intern/ghost/intern/GHOST_WindowWin32.h165
-rw-r--r--intern/ghost/intern/GHOST_WindowX11.cpp719
-rw-r--r--intern/ghost/intern/GHOST_WindowX11.h61
-rw-r--r--intern/ghost/test/CMakeLists.txt17
-rw-r--r--intern/ghost/test/gears/GHOST_C-Test.c34
-rw-r--r--intern/ghost/test/gears/GHOST_Test.cpp25
-rw-r--r--intern/ghost/test/multitest/MultiTest.c39
-rw-r--r--intern/glew-mx/CMakeLists.txt44
-rw-r--r--intern/glew-mx/SConscript15
-rw-r--r--intern/glew-mx/glew-mx.h113
-rw-r--r--intern/glew-mx/intern/gl-deprecated.h872
-rw-r--r--intern/glew-mx/intern/glew-mx.c151
-rw-r--r--intern/glew-mx/intern/symbol-binding.h305
-rw-r--r--intern/guardedalloc/MEM_guardedalloc.h22
-rw-r--r--intern/guardedalloc/intern/mallocn.c7
-rw-r--r--intern/guardedalloc/intern/mallocn_guarded_impl.c15
-rw-r--r--intern/guardedalloc/intern/mallocn_intern.h16
-rw-r--r--intern/guardedalloc/intern/mallocn_lockfree_impl.c18
-rw-r--r--intern/iksolver/extern/IK_solver.h10
-rw-r--r--intern/iksolver/intern/IK_Solver.cpp6
-rw-r--r--intern/itasc/CMakeLists.txt469
-rw-r--r--intern/locale/CMakeLists.txt13
-rw-r--r--intern/locale/SConscript4
-rw-r--r--intern/locale/boost_locale_wrapper.cpp3
-rw-r--r--intern/locale/boost_locale_wrapper.h6
-rw-r--r--intern/locale/msgfmt.cc8
-rw-r--r--intern/locale/osx_user_locale.mm22
-rw-r--r--intern/memutil/MEM_CacheLimiter.h49
-rw-r--r--intern/memutil/MEM_CacheLimiterC-Api.h2
-rw-r--r--intern/memutil/MEM_RefCountPtr.h17
-rw-r--r--intern/memutil/MEM_RefCounted.h4
-rw-r--r--intern/memutil/MEM_RefCountedC-Api.h2
-rw-r--r--intern/memutil/MEM_SmartPtr.h16
-rw-r--r--intern/opencolorio/CMakeLists.txt4
-rw-r--r--intern/opencolorio/SConscript7
-rw-r--r--intern/opencolorio/fallback_impl.cc15
-rw-r--r--intern/opencolorio/ocio_capi.cc5
-rw-r--r--intern/opencolorio/ocio_capi.h2
-rw-r--r--intern/opencolorio/ocio_impl.cc17
-rw-r--r--intern/opencolorio/ocio_impl.h6
-rw-r--r--intern/opencolorio/ocio_impl_glsl.cc4
-rw-r--r--intern/opennl/superlu/heap_relax_snode.c2
-rw-r--r--intern/opennl/superlu/relax_snode.c2
-rw-r--r--intern/opennl/superlu/smemory.c6
-rw-r--r--intern/opensubdiv/CMakeLists.txt94
-rw-r--r--intern/opensubdiv/SConscript69
-rw-r--r--intern/opensubdiv/gpu_shader_opensubd_display.glsl333
-rw-r--r--intern/opensubdiv/opensubdiv_capi.cc323
-rw-r--r--intern/opensubdiv/opensubdiv_capi.h151
-rw-r--r--intern/opensubdiv/opensubdiv_converter.cc682
-rw-r--r--intern/opensubdiv/opensubdiv_converter_capi.h124
-rw-r--r--intern/opensubdiv/opensubdiv_device_context_cuda.cc237
-rw-r--r--intern/opensubdiv/opensubdiv_device_context_cuda.h54
-rw-r--r--intern/opensubdiv/opensubdiv_device_context_opencl.cc251
-rw-r--r--intern/opensubdiv/opensubdiv_device_context_opencl.h58
-rw-r--r--intern/opensubdiv/opensubdiv_evaluator_capi.cc495
-rw-r--r--intern/opensubdiv/opensubdiv_gpu_capi.cc674
-rw-r--r--intern/opensubdiv/opensubdiv_intern.h46
-rw-r--r--intern/opensubdiv/opensubdiv_utils_capi.cc110
-rw-r--r--intern/smoke/intern/FLUID_3D.cpp36
-rw-r--r--intern/smoke/intern/FLUID_3D.h3
-rw-r--r--intern/smoke/intern/smoke_API.cpp14
-rw-r--r--intern/smoke/intern/spectrum.cpp2
-rwxr-xr-xrelease/bin/blender-thumbnailer.py17
-rw-r--r--release/datafiles/LICENSE-droidsans.ttf.txt32
-rw-r--r--release/datafiles/blender_icons.svg14324
-rw-r--r--release/datafiles/blender_icons16/icon16_border_lasso.datbin1048 -> 1048 bytes
-rw-r--r--release/datafiles/blender_icons16/icon16_camera_stereo.datbin1048 -> 1048 bytes
-rw-r--r--release/datafiles/blender_icons16/icon16_disclosure_tri_down.datbin1048 -> 1048 bytes
-rw-r--r--release/datafiles/blender_icons16/icon16_file_hidden.datbin0 -> 1048 bytes
-rw-r--r--release/datafiles/blender_icons16/icon16_image_rgb_alpha.datbin1048 -> 1048 bytes
-rw-r--r--release/datafiles/blender_icons16/icon16_library_data_broken.datbin0 -> 1048 bytes
-rw-r--r--release/datafiles/blender_icons16/icon16_mod_data_transfer.datbin0 -> 1048 bytes
-rw-r--r--release/datafiles/blender_icons16/icon16_mod_normaledit.datbin0 -> 1048 bytes
-rw-r--r--release/datafiles/blender_icons16/icon16_node_insert_off.datbin0 -> 1048 bytes
-rw-r--r--release/datafiles/blender_icons16/icon16_node_insert_on.datbin0 -> 1048 bytes
-rw-r--r--release/datafiles/blender_icons16/icon16_snap_grid.datbin0 -> 1048 bytes
-rw-r--r--release/datafiles/blender_icons16/icon16_snap_increment.datbin1048 -> 1048 bytes
-rw-r--r--release/datafiles/blender_icons16/icon16_tria_down_bar.datbin0 -> 1048 bytes
-rw-r--r--release/datafiles/blender_icons16/icon16_tria_left_bar.datbin0 -> 1048 bytes
-rw-r--r--release/datafiles/blender_icons16/icon16_tria_right_bar.datbin0 -> 1048 bytes
-rw-r--r--release/datafiles/blender_icons16/icon16_tria_up_bar.datbin0 -> 1048 bytes
-rw-r--r--release/datafiles/blender_icons32/icon32_border_lasso.datbin4120 -> 4120 bytes
-rw-r--r--release/datafiles/blender_icons32/icon32_camera_stereo.datbin4120 -> 4120 bytes
-rw-r--r--release/datafiles/blender_icons32/icon32_disclosure_tri_down.datbin4120 -> 4120 bytes
-rw-r--r--release/datafiles/blender_icons32/icon32_file_hidden.datbin0 -> 4120 bytes
-rw-r--r--release/datafiles/blender_icons32/icon32_image_rgb_alpha.datbin4120 -> 4120 bytes
-rw-r--r--release/datafiles/blender_icons32/icon32_library_data_broken.datbin0 -> 4120 bytes
-rw-r--r--release/datafiles/blender_icons32/icon32_mod_data_transfer.datbin0 -> 4120 bytes
-rw-r--r--release/datafiles/blender_icons32/icon32_mod_normaledit.datbin0 -> 4120 bytes
-rw-r--r--release/datafiles/blender_icons32/icon32_node_insert_off.datbin0 -> 4120 bytes
-rw-r--r--release/datafiles/blender_icons32/icon32_node_insert_on.datbin0 -> 4120 bytes
-rw-r--r--release/datafiles/blender_icons32/icon32_snap_grid.datbin0 -> 4120 bytes
-rw-r--r--release/datafiles/blender_icons32/icon32_snap_increment.datbin4120 -> 4120 bytes
-rw-r--r--release/datafiles/blender_icons32/icon32_tria_down_bar.datbin0 -> 4120 bytes
-rw-r--r--release/datafiles/blender_icons32/icon32_tria_left_bar.datbin0 -> 4120 bytes
-rw-r--r--release/datafiles/blender_icons32/icon32_tria_right_bar.datbin0 -> 4120 bytes
-rw-r--r--release/datafiles/blender_icons32/icon32_tria_up_bar.datbin0 -> 4120 bytes
-rw-r--r--release/datafiles/colormanagement/config.ocio2
-rwxr-xr-xrelease/datafiles/ctodata.py2
-rwxr-xr-xrelease/datafiles/datatoc.py2
-rw-r--r--release/datafiles/fonts/droidsans.ttf.gzbin2644887 -> 2485497 bytes
m---------release/datafiles/locale0
-rw-r--r--release/datafiles/prvicons.pngbin15991 -> 15781 bytes
-rw-r--r--release/datafiles/prvicons.svg21
-rw-r--r--release/datafiles/splash.pngbin187919 -> 140110 bytes
-rw-r--r--release/datafiles/splash_2x.pngbin582704 -> 444285 bytes
-rw-r--r--release/datafiles/startup.blendbin443048 -> 432264 bytes
-rw-r--r--release/freedesktop/blender.desktop81
m---------release/scripts/addons0
m---------release/scripts/addons_contrib0
-rw-r--r--release/scripts/freestyle/modules/freestyle/chainingiterators.py8
-rw-r--r--release/scripts/freestyle/modules/freestyle/functions.py6
-rw-r--r--release/scripts/freestyle/modules/freestyle/predicates.py75
-rw-r--r--release/scripts/freestyle/modules/freestyle/shaders.py52
-rw-r--r--release/scripts/freestyle/modules/freestyle/utils.py282
-rw-r--r--release/scripts/freestyle/modules/parameter_editor.py489
-rw-r--r--release/scripts/freestyle/styles/anisotropic_diffusion.py4
-rw-r--r--release/scripts/freestyle/styles/apriori_density.py2
-rw-r--r--release/scripts/freestyle/styles/backbone_stretcher.py2
-rw-r--r--release/scripts/freestyle/styles/blueprint_circles.py2
-rw-r--r--release/scripts/freestyle/styles/blueprint_ellipses.py2
-rw-r--r--release/scripts/freestyle/styles/blueprint_squares.py2
-rw-r--r--release/scripts/freestyle/styles/cartoon.py2
-rw-r--r--release/scripts/freestyle/styles/curvature2d.py2
-rw-r--r--release/scripts/freestyle/styles/external_contour_sketchy.py2
-rw-r--r--release/scripts/freestyle/styles/japanese_bigbrush.py4
-rw-r--r--release/scripts/freestyle/styles/multiple_parameterization.py2
-rw-r--r--release/scripts/freestyle/styles/near_lines.py2
-rw-r--r--release/scripts/freestyle/styles/qi0_not_external_contour.py2
-rw-r--r--release/scripts/freestyle/styles/sequentialsplit_sketchy.py2
-rw-r--r--release/scripts/freestyle/styles/sketchy_multiple_parameterization.py2
-rw-r--r--release/scripts/freestyle/styles/sketchy_topology_broken.py10
-rw-r--r--release/scripts/freestyle/styles/sketchy_topology_preserved.py2
-rw-r--r--release/scripts/freestyle/styles/split_at_highest_2d_curvatures.py2
-rw-r--r--release/scripts/freestyle/styles/split_at_tvertices.py2
-rw-r--r--release/scripts/freestyle/styles/stroke_texture.py49
-rw-r--r--release/scripts/freestyle/styles/uniformpruning_zsort.py3
-rw-r--r--release/scripts/modules/addon_utils.py162
-rw-r--r--release/scripts/modules/animsys_refactor.py2
-rw-r--r--release/scripts/modules/bl_i18n_utils/bl_extract_messages.py32
-rwxr-xr-xrelease/scripts/modules/bl_i18n_utils/merge_po.py11
-rw-r--r--release/scripts/modules/bl_i18n_utils/settings.py45
-rw-r--r--release/scripts/modules/bl_i18n_utils/utils.py40
-rwxr-xr-xrelease/scripts/modules/bl_i18n_utils/utils_languages_menu.py2
-rw-r--r--release/scripts/modules/bl_i18n_utils/utils_spell_check.py19
-rw-r--r--release/scripts/modules/bl_previews_utils/bl_previews_render.py491
-rw-r--r--release/scripts/modules/bpy/__init__.py4
-rw-r--r--release/scripts/modules/bpy/ops.py7
-rw-r--r--release/scripts/modules/bpy/path.py104
-rw-r--r--release/scripts/modules/bpy/utils/__init__.py (renamed from release/scripts/modules/bpy/utils.py)91
-rw-r--r--release/scripts/modules/bpy/utils/previews.py153
-rw-r--r--release/scripts/modules/bpy_extras/anim_utils.py56
-rw-r--r--release/scripts/modules/bpy_extras/io_utils.py65
-rw-r--r--release/scripts/modules/bpy_extras/keyconfig_utils.py8
-rw-r--r--release/scripts/modules/bpy_extras/object_utils.py58
-rw-r--r--release/scripts/modules/bpy_extras/view3d_utils.py37
-rw-r--r--release/scripts/modules/bpy_restrict_state.py6
-rw-r--r--release/scripts/modules/bpy_types.py49
-rw-r--r--release/scripts/modules/bpyml.py2
-rw-r--r--release/scripts/modules/bpyml_ui.py2
-rw-r--r--release/scripts/modules/console_python.py13
-rw-r--r--release/scripts/modules/nodeitems_utils.py24
-rw-r--r--release/scripts/modules/progress_report.py166
-rw-r--r--release/scripts/modules/rna_info.py15
-rw-r--r--release/scripts/modules/rna_keymap_ui.py2
-rw-r--r--release/scripts/modules/rna_prop_ui.py20
-rw-r--r--release/scripts/modules/rna_xml.py4
-rw-r--r--release/scripts/modules/sys_info.py101
-rw-r--r--release/scripts/presets/hair_dynamics/default.py17
-rw-r--r--release/scripts/presets/interface_theme/back_to_black.xml36
-rw-r--r--release/scripts/presets/interface_theme/blender_24x.xml106
-rw-r--r--release/scripts/presets/interface_theme/elsyiun.xml62
-rw-r--r--release/scripts/presets/interface_theme/flatty_light.xml1176
-rw-r--r--release/scripts/presets/interface_theme/graph.xml1176
-rw-r--r--release/scripts/presets/interface_theme/hexagon.xml62
-rw-r--r--release/scripts/presets/interface_theme/rtheme.xml1176
-rw-r--r--release/scripts/presets/interface_theme/science_lab.xml1176
-rw-r--r--release/scripts/presets/interface_theme/softimage.xml1176
-rw-r--r--release/scripts/presets/interface_theme/ubuntu_ambiance.xml56
-rw-r--r--release/scripts/presets/keyconfig/3dsmax.py3
-rw-r--r--release/scripts/presets/keyconfig/maya.py39
-rw-r--r--release/scripts/presets/safe_areas/14_colon_9_in_16_colon_9.py7
-rw-r--r--release/scripts/presets/safe_areas/16_colon_9.py7
-rw-r--r--release/scripts/presets/safe_areas/4_colon_3_in_16_colon_9.py7
-rw-r--r--release/scripts/startup/bl_operators/__init__.py8
-rw-r--r--release/scripts/startup/bl_operators/add_mesh_torus.py25
-rw-r--r--release/scripts/startup/bl_operators/anim.py33
-rw-r--r--release/scripts/startup/bl_operators/clip.py163
-rw-r--r--release/scripts/startup/bl_operators/console.py7
-rw-r--r--release/scripts/startup/bl_operators/file.py244
-rw-r--r--release/scripts/startup/bl_operators/freestyle.py24
-rw-r--r--release/scripts/startup/bl_operators/image.py3
-rw-r--r--release/scripts/startup/bl_operators/mask.py1
-rw-r--r--release/scripts/startup/bl_operators/mesh.py1
-rw-r--r--release/scripts/startup/bl_operators/node.py28
-rw-r--r--release/scripts/startup/bl_operators/object.py22
-rw-r--r--release/scripts/startup/bl_operators/object_align.py10
-rw-r--r--release/scripts/startup/bl_operators/object_quick_effects.py17
-rw-r--r--release/scripts/startup/bl_operators/presets.py75
-rw-r--r--release/scripts/startup/bl_operators/rigidbody.py10
-rw-r--r--release/scripts/startup/bl_operators/screen_play_rendered_anim.py11
-rw-r--r--release/scripts/startup/bl_operators/uvcalc_lightmap.py2
-rw-r--r--release/scripts/startup/bl_operators/uvcalc_smart_project.py34
-rw-r--r--release/scripts/startup/bl_operators/vertexpaint_dirt.py34
-rw-r--r--release/scripts/startup/bl_operators/wm.py73
-rw-r--r--release/scripts/startup/bl_ui/__init__.py16
-rw-r--r--release/scripts/startup/bl_ui/properties_animviz.py4
-rw-r--r--release/scripts/startup/bl_ui/properties_constraint.py47
-rw-r--r--release/scripts/startup/bl_ui/properties_data_armature.py11
-rw-r--r--release/scripts/startup/bl_ui/properties_data_bone.py4
-rw-r--r--release/scripts/startup/bl_ui/properties_data_camera.py114
-rw-r--r--release/scripts/startup/bl_ui/properties_data_curve.py6
-rw-r--r--release/scripts/startup/bl_ui/properties_data_empty.py2
-rw-r--r--release/scripts/startup/bl_ui/properties_data_lamp.py3
-rw-r--r--release/scripts/startup/bl_ui/properties_data_lattice.py2
-rw-r--r--release/scripts/startup/bl_ui/properties_data_mesh.py26
-rw-r--r--release/scripts/startup/bl_ui/properties_data_metaball.py2
-rw-r--r--release/scripts/startup/bl_ui/properties_data_modifier.py240
-rw-r--r--release/scripts/startup/bl_ui/properties_data_speaker.py2
-rw-r--r--release/scripts/startup/bl_ui/properties_freestyle.py160
-rw-r--r--release/scripts/startup/bl_ui/properties_game.py89
-rw-r--r--release/scripts/startup/bl_ui/properties_grease_pencil_common.py458
-rw-r--r--release/scripts/startup/bl_ui/properties_mask_common.py22
-rw-r--r--release/scripts/startup/bl_ui/properties_material.py23
-rw-r--r--release/scripts/startup/bl_ui/properties_object.py8
-rw-r--r--release/scripts/startup/bl_ui/properties_paint_common.py53
-rw-r--r--release/scripts/startup/bl_ui/properties_particle.py207
-rw-r--r--release/scripts/startup/bl_ui/properties_physics_cloth.py11
-rw-r--r--release/scripts/startup/bl_ui/properties_physics_common.py4
-rw-r--r--release/scripts/startup/bl_ui/properties_physics_dynamicpaint.py11
-rw-r--r--release/scripts/startup/bl_ui/properties_physics_field.py9
-rw-r--r--release/scripts/startup/bl_ui/properties_physics_fluid.py2
-rw-r--r--release/scripts/startup/bl_ui/properties_physics_rigidbody.py2
-rw-r--r--release/scripts/startup/bl_ui/properties_physics_rigidbody_constraint.py2
-rw-r--r--release/scripts/startup/bl_ui/properties_physics_smoke.py20
-rw-r--r--release/scripts/startup/bl_ui/properties_physics_softbody.py8
-rw-r--r--release/scripts/startup/bl_ui/properties_render.py32
-rw-r--r--release/scripts/startup/bl_ui/properties_render_layer.py74
-rw-r--r--release/scripts/startup/bl_ui/properties_scene.py87
-rw-r--r--release/scripts/startup/bl_ui/properties_texture.py44
-rw-r--r--release/scripts/startup/bl_ui/properties_world.py5
-rw-r--r--release/scripts/startup/bl_ui/space_clip.py116
-rw-r--r--release/scripts/startup/bl_ui/space_console.py3
-rw-r--r--release/scripts/startup/bl_ui/space_dopesheet.py65
-rw-r--r--release/scripts/startup/bl_ui/space_filebrowser.py187
-rw-r--r--release/scripts/startup/bl_ui/space_graph.py56
-rw-r--r--release/scripts/startup/bl_ui/space_image.py142
-rw-r--r--release/scripts/startup/bl_ui/space_info.py31
-rw-r--r--release/scripts/startup/bl_ui/space_logic.py14
-rw-r--r--release/scripts/startup/bl_ui/space_nla.py15
-rw-r--r--release/scripts/startup/bl_ui/space_node.py75
-rw-r--r--release/scripts/startup/bl_ui/space_outliner.py6
-rw-r--r--release/scripts/startup/bl_ui/space_sequencer.py196
-rw-r--r--release/scripts/startup/bl_ui/space_text.py3
-rw-r--r--release/scripts/startup/bl_ui/space_time.py14
-rw-r--r--release/scripts/startup/bl_ui/space_userpref.py78
-rw-r--r--release/scripts/startup/bl_ui/space_view3d.py321
-rw-r--r--release/scripts/startup/bl_ui/space_view3d_toolbar.py221
-rw-r--r--release/scripts/startup/nodeitems_builtins.py56
-rw-r--r--release/scripts/templates_osl/fresnel_conductive.osl6
-rw-r--r--release/scripts/templates_osl/westin_closure.osl12
-rw-r--r--release/scripts/templates_py/addon_add_object.py5
-rw-r--r--release/scripts/templates_py/custom_nodes.py3
-rw-r--r--release/scripts/templates_py/operator_mesh_add.py1
-rw-r--r--release/scripts/templates_py/operator_modal_timer.py3
-rw-r--r--release/scripts/templates_py/operator_modal_view3d_raycast.py4
-rw-r--r--release/scripts/templates_py/ui_previews_custom_icon.py76
-rw-r--r--release/scripts/templates_py/ui_previews_dynamic_enum.py137
-rw-r--r--release/text/readme.html113
-rw-r--r--release/windows/installer/00.sconsblender.nsi7
-rw-r--r--source/blender/CMakeLists.txt4
-rw-r--r--source/blender/SConscript3
-rw-r--r--source/blender/avi/AVI_avi.h7
-rw-r--r--source/blender/avi/intern/avi.c2
-rw-r--r--source/blender/avi/intern/avi_mjpeg.c43
-rw-r--r--source/blender/avi/intern/avi_rgb.c11
-rw-r--r--source/blender/avi/intern/avi_rgb32.c2
-rw-r--r--source/blender/blenfont/BLF_api.h45
-rw-r--r--source/blender/blenfont/BLF_translation.h235
-rw-r--r--source/blender/blenfont/CMakeLists.txt26
-rw-r--r--source/blender/blenfont/SConscript14
-rw-r--r--source/blender/blenfont/intern/blf.c198
-rw-r--r--source/blender/blenfont/intern/blf_dir.c2
-rw-r--r--source/blender/blenfont/intern/blf_font.c324
-rw-r--r--source/blender/blenfont/intern/blf_font_i18n.c124
-rw-r--r--source/blender/blenfont/intern/blf_font_win32_compat.c145
-rw-r--r--source/blender/blenfont/intern/blf_glyph.c14
-rw-r--r--source/blender/blenfont/intern/blf_internal.h28
-rw-r--r--source/blender/blenfont/intern/blf_internal_types.h13
-rw-r--r--source/blender/blenfont/intern/blf_thumbs.c121
-rw-r--r--source/blender/blenfont/intern/blf_util.c1
-rw-r--r--source/blender/blenkernel/BKE_DerivedMesh.h331
-rw-r--r--source/blender/blenkernel/BKE_action.h12
-rw-r--r--source/blender/blenkernel/BKE_addon.h2
-rw-r--r--source/blender/blenkernel/BKE_anim.h3
-rw-r--r--source/blender/blenkernel/BKE_animsys.h51
-rw-r--r--source/blender/blenkernel/BKE_appdir.h85
-rw-r--r--source/blender/blenkernel/BKE_armature.h60
-rw-r--r--source/blender/blenkernel/BKE_blender.h27
-rw-r--r--source/blender/blenkernel/BKE_bpath.h22
-rw-r--r--source/blender/blenkernel/BKE_brush.h44
-rw-r--r--source/blender/blenkernel/BKE_bvhutils.h114
-rw-r--r--source/blender/blenkernel/BKE_camera.h42
-rw-r--r--source/blender/blenkernel/BKE_cdderivedmesh.h19
-rw-r--r--source/blender/blenkernel/BKE_cloth.h92
-rw-r--r--source/blender/blenkernel/BKE_collision.h20
-rw-r--r--source/blender/blenkernel/BKE_colortools.h3
-rw-r--r--source/blender/blenkernel/BKE_constraint.h10
-rw-r--r--source/blender/blenkernel/BKE_context.h12
-rw-r--r--source/blender/blenkernel/BKE_crazyspace.h17
-rw-r--r--source/blender/blenkernel/BKE_curve.h29
-rw-r--r--source/blender/blenkernel/BKE_customdata.h162
-rw-r--r--source/blender/blenkernel/BKE_customdata_file.h12
-rw-r--r--source/blender/blenkernel/BKE_data_transfer.h159
-rw-r--r--source/blender/blenkernel/BKE_deform.h16
-rw-r--r--source/blender/blenkernel/BKE_depsgraph.h16
-rw-r--r--source/blender/blenkernel/BKE_displist.h5
-rw-r--r--source/blender/blenkernel/BKE_dynamicpaint.h12
-rw-r--r--source/blender/blenkernel/BKE_editmesh.h18
-rw-r--r--source/blender/blenkernel/BKE_editmesh_bvh.h20
-rw-r--r--source/blender/blenkernel/BKE_effect.h88
-rw-r--r--source/blender/blenkernel/BKE_fcurve.h14
-rw-r--r--source/blender/blenkernel/BKE_fluidsim.h2
-rw-r--r--source/blender/blenkernel/BKE_font.h2
-rw-r--r--source/blender/blenkernel/BKE_freestyle.h3
-rw-r--r--source/blender/blenkernel/BKE_global.h32
-rw-r--r--source/blender/blenkernel/BKE_gpencil.h9
-rw-r--r--source/blender/blenkernel/BKE_group.h3
-rw-r--r--source/blender/blenkernel/BKE_icons.h38
-rw-r--r--source/blender/blenkernel/BKE_idcode.h4
-rw-r--r--source/blender/blenkernel/BKE_idprop.h16
-rw-r--r--source/blender/blenkernel/BKE_image.h72
-rw-r--r--source/blender/blenkernel/BKE_key.h45
-rw-r--r--source/blender/blenkernel/BKE_lattice.h9
-rw-r--r--source/blender/blenkernel/BKE_library.h11
-rw-r--r--source/blender/blenkernel/BKE_linestyle.h4
-rw-r--r--source/blender/blenkernel/BKE_main.h14
-rw-r--r--source/blender/blenkernel/BKE_mask.h1
-rw-r--r--source/blender/blenkernel/BKE_material.h7
-rw-r--r--source/blender/blenkernel/BKE_mball.h11
-rw-r--r--source/blender/blenkernel/BKE_mball_tessellate.h36
-rw-r--r--source/blender/blenkernel/BKE_mesh.h184
-rw-r--r--source/blender/blenkernel/BKE_mesh_mapping.h80
-rw-r--r--source/blender/blenkernel/BKE_mesh_remap.h178
-rw-r--r--source/blender/blenkernel/BKE_modifier.h27
-rw-r--r--source/blender/blenkernel/BKE_movieclip.h4
-rw-r--r--source/blender/blenkernel/BKE_multires.h14
-rw-r--r--source/blender/blenkernel/BKE_nla.h7
-rw-r--r--source/blender/blenkernel/BKE_node.h98
-rw-r--r--source/blender/blenkernel/BKE_object.h71
-rw-r--r--source/blender/blenkernel/BKE_object_deform.h50
-rw-r--r--source/blender/blenkernel/BKE_ocean.h26
-rw-r--r--source/blender/blenkernel/BKE_outliner_treehash.h (renamed from source/blender/blenkernel/BKE_treehash.h)19
-rw-r--r--source/blender/blenkernel/BKE_packedFile.h2
-rw-r--r--source/blender/blenkernel/BKE_paint.h51
-rw-r--r--source/blender/blenkernel/BKE_particle.h89
-rw-r--r--source/blender/blenkernel/BKE_pbvh.h69
-rw-r--r--source/blender/blenkernel/BKE_pointcache.h3
-rw-r--r--source/blender/blenkernel/BKE_rigidbody.h18
-rw-r--r--source/blender/blenkernel/BKE_sca.h1
-rw-r--r--source/blender/blenkernel/BKE_scene.h44
-rw-r--r--source/blender/blenkernel/BKE_screen.h13
-rw-r--r--source/blender/blenkernel/BKE_sequencer.h66
-rw-r--r--source/blender/blenkernel/BKE_shrinkwrap.h1
-rw-r--r--source/blender/blenkernel/BKE_sound.h105
-rw-r--r--source/blender/blenkernel/BKE_subsurf.h12
-rw-r--r--source/blender/blenkernel/BKE_text.h5
-rw-r--r--source/blender/blenkernel/BKE_texture.h72
-rw-r--r--source/blender/blenkernel/BKE_tracking.h41
-rw-r--r--source/blender/blenkernel/BKE_writeavi.h18
-rw-r--r--source/blender/blenkernel/BKE_writeffmpeg.h14
-rw-r--r--source/blender/blenkernel/BKE_writeframeserver.h15
-rw-r--r--source/blender/blenkernel/CMakeLists.txt107
-rw-r--r--source/blender/blenkernel/SConscript30
-rw-r--r--source/blender/blenkernel/intern/CCGSubSurf.c1946
-rw-r--r--source/blender/blenkernel/intern/CCGSubSurf.h78
-rw-r--r--source/blender/blenkernel/intern/CCGSubSurf_inline.h269
-rw-r--r--source/blender/blenkernel/intern/CCGSubSurf_intern.h330
-rw-r--r--source/blender/blenkernel/intern/CCGSubSurf_legacy.c1180
-rw-r--r--source/blender/blenkernel/intern/CCGSubSurf_opensubdiv.c920
-rw-r--r--source/blender/blenkernel/intern/CCGSubSurf_opensubdiv_converter.c586
-rw-r--r--source/blender/blenkernel/intern/CCGSubSurf_util.c306
-rw-r--r--source/blender/blenkernel/intern/DerivedMesh.c1245
-rw-r--r--source/blender/blenkernel/intern/action.c95
-rw-r--r--source/blender/blenkernel/intern/addon.c12
-rw-r--r--source/blender/blenkernel/intern/anim.c5
-rw-r--r--source/blender/blenkernel/intern/anim_sys.c374
-rw-r--r--source/blender/blenkernel/intern/appdir.c791
-rw-r--r--source/blender/blenkernel/intern/armature.c599
-rw-r--r--source/blender/blenkernel/intern/armature_update.c697
-rw-r--r--source/blender/blenkernel/intern/autoexec.c5
-rw-r--r--source/blender/blenkernel/intern/blender.c133
-rw-r--r--source/blender/blenkernel/intern/boids.c39
-rw-r--r--source/blender/blenkernel/intern/bpath.c79
-rw-r--r--source/blender/blenkernel/intern/brush.c103
-rw-r--r--source/blender/blenkernel/intern/bvhutils.c935
-rw-r--r--source/blender/blenkernel/intern/camera.c544
-rw-r--r--source/blender/blenkernel/intern/cdderivedmesh.c2218
-rw-r--r--source/blender/blenkernel/intern/cloth.c698
-rw-r--r--source/blender/blenkernel/intern/collision.c780
-rw-r--r--source/blender/blenkernel/intern/colortools.c264
-rw-r--r--source/blender/blenkernel/intern/constraint.c189
-rw-r--r--source/blender/blenkernel/intern/context.c42
-rw-r--r--source/blender/blenkernel/intern/crazyspace.c14
-rw-r--r--source/blender/blenkernel/intern/curve.c278
-rw-r--r--source/blender/blenkernel/intern/customdata.c1002
-rw-r--r--source/blender/blenkernel/intern/customdata_file.c14
-rw-r--r--source/blender/blenkernel/intern/data_transfer.c1417
-rw-r--r--source/blender/blenkernel/intern/data_transfer_intern.h58
-rw-r--r--source/blender/blenkernel/intern/deform.c437
-rw-r--r--source/blender/blenkernel/intern/depsgraph.c533
-rw-r--r--source/blender/blenkernel/intern/displist.c45
-rw-r--r--source/blender/blenkernel/intern/dynamicpaint.c746
-rw-r--r--source/blender/blenkernel/intern/editderivedmesh.c555
-rw-r--r--source/blender/blenkernel/intern/editmesh.c18
-rw-r--r--source/blender/blenkernel/intern/editmesh_bvh.c207
-rw-r--r--source/blender/blenkernel/intern/effect.c191
-rw-r--r--source/blender/blenkernel/intern/fcurve.c174
-rw-r--r--source/blender/blenkernel/intern/fluidsim.c56
-rw-r--r--source/blender/blenkernel/intern/fmodifier.c46
-rw-r--r--source/blender/blenkernel/intern/font.c4
-rw-r--r--source/blender/blenkernel/intern/freestyle.c6
-rw-r--r--source/blender/blenkernel/intern/gpencil.c76
-rw-r--r--source/blender/blenkernel/intern/group.c52
-rw-r--r--source/blender/blenkernel/intern/icons.c357
-rw-r--r--source/blender/blenkernel/intern/idcode.c175
-rw-r--r--source/blender/blenkernel/intern/idprop.c173
-rw-r--r--source/blender/blenkernel/intern/image.c1776
-rw-r--r--source/blender/blenkernel/intern/image_gen.c18
-rw-r--r--source/blender/blenkernel/intern/implicit.c1964
-rw-r--r--source/blender/blenkernel/intern/ipo.c56
-rw-r--r--source/blender/blenkernel/intern/key.c713
-rw-r--r--source/blender/blenkernel/intern/lamp.c12
-rw-r--r--source/blender/blenkernel/intern/lattice.c82
-rw-r--r--source/blender/blenkernel/intern/library.c157
-rw-r--r--source/blender/blenkernel/intern/linestyle.c343
-rw-r--r--source/blender/blenkernel/intern/mask.c31
-rw-r--r--source/blender/blenkernel/intern/mask_evaluate.c2
-rw-r--r--source/blender/blenkernel/intern/mask_rasterize.c9
-rw-r--r--source/blender/blenkernel/intern/material.c153
-rw-r--r--source/blender/blenkernel/intern/mball.c1945
-rw-r--r--source/blender/blenkernel/intern/mball_tessellate.c1325
-rw-r--r--source/blender/blenkernel/intern/mesh.c326
-rw-r--r--source/blender/blenkernel/intern/mesh_evaluate.c1861
-rw-r--r--source/blender/blenkernel/intern/mesh_mapping.c484
-rw-r--r--source/blender/blenkernel/intern/mesh_remap.c2275
-rw-r--r--source/blender/blenkernel/intern/mesh_validate.c150
-rw-r--r--source/blender/blenkernel/intern/modifier.c65
-rw-r--r--source/blender/blenkernel/intern/modifiers_bmesh.c5
-rw-r--r--source/blender/blenkernel/intern/movieclip.c59
-rw-r--r--source/blender/blenkernel/intern/multires.c111
-rw-r--r--source/blender/blenkernel/intern/navmesh_conversion.c27
-rw-r--r--source/blender/blenkernel/intern/nla.c228
-rw-r--r--source/blender/blenkernel/intern/node.c212
-rw-r--r--source/blender/blenkernel/intern/object.c924
-rw-r--r--source/blender/blenkernel/intern/object_deform.c546
-rw-r--r--source/blender/blenkernel/intern/object_dupli.c18
-rw-r--r--source/blender/blenkernel/intern/object_update.c349
-rw-r--r--source/blender/blenkernel/intern/ocean.c48
-rw-r--r--source/blender/blenkernel/intern/outliner_treehash.c (renamed from source/blender/blenkernel/intern/treehash.c)55
-rw-r--r--source/blender/blenkernel/intern/packedFile.c158
-rw-r--r--source/blender/blenkernel/intern/paint.c255
-rw-r--r--source/blender/blenkernel/intern/particle.c1288
-rw-r--r--source/blender/blenkernel/intern/particle_child.c732
-rw-r--r--source/blender/blenkernel/intern/particle_distribute.c1417
-rw-r--r--source/blender/blenkernel/intern/particle_system.c1531
-rw-r--r--source/blender/blenkernel/intern/pbvh.c430
-rw-r--r--source/blender/blenkernel/intern/pbvh_bmesh.c1137
-rw-r--r--source/blender/blenkernel/intern/pbvh_intern.h20
-rw-r--r--source/blender/blenkernel/intern/pointcache.c74
-rw-r--r--source/blender/blenkernel/intern/property.c54
-rw-r--r--source/blender/blenkernel/intern/report.c2
-rw-r--r--source/blender/blenkernel/intern/rigidbody.c155
-rw-r--r--source/blender/blenkernel/intern/sca.c39
-rw-r--r--source/blender/blenkernel/intern/scene.c807
-rw-r--r--source/blender/blenkernel/intern/screen.c130
-rw-r--r--source/blender/blenkernel/intern/seqcache.c29
-rw-r--r--source/blender/blenkernel/intern/seqeffects.c165
-rw-r--r--source/blender/blenkernel/intern/seqmodifier.c42
-rw-r--r--source/blender/blenkernel/intern/sequencer.c1425
-rw-r--r--source/blender/blenkernel/intern/shrinkwrap.c20
-rw-r--r--source/blender/blenkernel/intern/sketch.c10
-rw-r--r--source/blender/blenkernel/intern/smoke.c109
-rw-r--r--source/blender/blenkernel/intern/softbody.c851
-rw-r--r--source/blender/blenkernel/intern/sound.c570
-rw-r--r--source/blender/blenkernel/intern/speaker.c6
-rw-r--r--source/blender/blenkernel/intern/subsurf_ccg.c2451
-rw-r--r--source/blender/blenkernel/intern/text.c636
-rw-r--r--source/blender/blenkernel/intern/texture.c191
-rw-r--r--source/blender/blenkernel/intern/tracking.c164
-rw-r--r--source/blender/blenkernel/intern/tracking_auto.c558
-rw-r--r--source/blender/blenkernel/intern/tracking_detect.c1
-rw-r--r--source/blender/blenkernel/intern/tracking_region_tracker.c481
-rw-r--r--source/blender/blenkernel/intern/tracking_solver.c15
-rw-r--r--source/blender/blenkernel/intern/tracking_util.c455
-rw-r--r--source/blender/blenkernel/intern/unit.c11
-rw-r--r--source/blender/blenkernel/intern/world.c19
-rw-r--r--source/blender/blenkernel/intern/writeavi.c117
-rw-r--r--source/blender/blenkernel/intern/writeffmpeg.c462
-rw-r--r--source/blender/blenkernel/intern/writeframeserver.c136
-rw-r--r--source/blender/blenkernel/tracking_private.h28
-rw-r--r--source/blender/blenlib/BLI_array.h89
-rw-r--r--source/blender/blenlib/BLI_array_utils.h49
-rw-r--r--source/blender/blenlib/BLI_astar.h107
-rw-r--r--source/blender/blenlib/BLI_bitmap.h25
-rw-r--r--source/blender/blenlib/BLI_blenlib.h1
-rw-r--r--source/blender/blenlib/BLI_buffer.h8
-rw-r--r--source/blender/blenlib/BLI_callbacks.h2
-rw-r--r--source/blender/blenlib/BLI_compiler_compat.h12
-rw-r--r--source/blender/blenlib/BLI_compiler_typecheck.h322
-rw-r--r--source/blender/blenlib/BLI_dial.h4
-rw-r--r--source/blender/blenlib/BLI_edgehash.h5
-rw-r--r--source/blender/blenlib/BLI_endian_switch_inline.h12
-rw-r--r--source/blender/blenlib/BLI_fileops.h70
-rw-r--r--source/blender/blenlib/BLI_fileops_types.h23
-rw-r--r--source/blender/blenlib/BLI_ghash.h82
-rw-r--r--source/blender/blenlib/BLI_hash_md5.h (renamed from source/blender/blenlib/BLI_md5.h)18
-rw-r--r--source/blender/blenlib/BLI_hash_mm2a.h47
-rw-r--r--source/blender/blenlib/BLI_heap.h1
-rw-r--r--source/blender/blenlib/BLI_kdopbvh.h40
-rw-r--r--source/blender/blenlib/BLI_linklist.h56
-rw-r--r--source/blender/blenlib/BLI_linklist_stack.h44
-rw-r--r--source/blender/blenlib/BLI_listbase.h9
-rw-r--r--source/blender/blenlib/BLI_math.h41
-rw-r--r--source/blender/blenlib/BLI_math_base.h74
-rw-r--r--source/blender/blenlib/BLI_math_bits.h (renamed from source/blender/freestyle/intern/python/StrokeShader/BPy_streamShader.h)42
-rw-r--r--source/blender/blenlib/BLI_math_color.h17
-rw-r--r--source/blender/blenlib/BLI_math_color_blend.h32
-rw-r--r--source/blender/blenlib/BLI_math_geom.h144
-rw-r--r--source/blender/blenlib/BLI_math_matrix.h8
-rw-r--r--source/blender/blenlib/BLI_math_rotation.h5
-rw-r--r--source/blender/blenlib/BLI_math_solvers.h66
-rw-r--r--source/blender/blenlib/BLI_math_statistics.h70
-rw-r--r--source/blender/blenlib/BLI_math_vector.h42
-rw-r--r--source/blender/blenlib/BLI_memarena.h5
-rw-r--r--source/blender/blenlib/BLI_mempool.h13
-rw-r--r--source/blender/blenlib/BLI_path_util.h71
-rw-r--r--source/blender/blenlib/BLI_polyfill2d.h3
-rw-r--r--source/blender/blenlib/BLI_polyfill2d_beautify.h42
-rw-r--r--source/blender/blenlib/BLI_quadric.h14
-rw-r--r--source/blender/blenlib/BLI_rand.h11
-rw-r--r--source/blender/blenlib/BLI_rect.h7
-rw-r--r--source/blender/blenlib/BLI_smallhash.h15
-rw-r--r--source/blender/blenlib/BLI_sort.h3
-rw-r--r--source/blender/blenlib/BLI_stack.h5
-rw-r--r--source/blender/blenlib/BLI_stackdefines.h9
-rw-r--r--source/blender/blenlib/BLI_strict_flags.h6
-rw-r--r--source/blender/blenlib/BLI_string.h26
-rw-r--r--source/blender/blenlib/BLI_string_utf8.h9
-rw-r--r--source/blender/blenlib/BLI_system.h5
-rw-r--r--source/blender/blenlib/BLI_task.h21
-rw-r--r--source/blender/blenlib/BLI_threads.h3
-rw-r--r--source/blender/blenlib/BLI_timecode.h12
-rw-r--r--source/blender/blenlib/BLI_utildefines.h212
-rw-r--r--source/blender/blenlib/BLI_winstuff.h13
-rw-r--r--source/blender/blenlib/CMakeLists.txt49
-rw-r--r--source/blender/blenlib/PIL_time.h8
-rw-r--r--source/blender/blenlib/SConscript7
-rw-r--r--source/blender/blenlib/intern/BLI_args.c2
-rw-r--r--source/blender/blenlib/intern/BLI_array.c78
-rw-r--r--source/blender/blenlib/intern/BLI_dynstr.c8
-rw-r--r--source/blender/blenlib/intern/BLI_filelist.c412
-rw-r--r--source/blender/blenlib/intern/BLI_ghash.c878
-rw-r--r--source/blender/blenlib/intern/BLI_heap.c43
-rw-r--r--source/blender/blenlib/intern/BLI_kdopbvh.c345
-rw-r--r--source/blender/blenlib/intern/BLI_linklist.c152
-rw-r--r--source/blender/blenlib/intern/BLI_memarena.c8
-rw-r--r--source/blender/blenlib/intern/BLI_mempool.c7
-rw-r--r--source/blender/blenlib/intern/array_utils.c144
-rw-r--r--source/blender/blenlib/intern/astar.c282
-rw-r--r--source/blender/blenlib/intern/boxpack2d.c45
-rw-r--r--source/blender/blenlib/intern/buffer.c18
-rw-r--r--source/blender/blenlib/intern/convexhull2d.c6
-rw-r--r--source/blender/blenlib/intern/dynlib.c2
-rw-r--r--source/blender/blenlib/intern/easing.c2
-rw-r--r--source/blender/blenlib/intern/edgehash.c157
-rw-r--r--source/blender/blenlib/intern/endian_switch.c24
-rw-r--r--source/blender/blenlib/intern/fileops.c158
-rw-r--r--source/blender/blenlib/intern/freetypefont.c3
-rw-r--r--source/blender/blenlib/intern/graph.c8
-rw-r--r--source/blender/blenlib/intern/gsqueue.c10
-rw-r--r--source/blender/blenlib/intern/hash_md5.c (renamed from source/blender/blenlib/intern/md5.c)18
-rw-r--r--source/blender/blenlib/intern/hash_mm2a.c145
-rw-r--r--source/blender/blenlib/intern/lasso.c1
-rw-r--r--source/blender/blenlib/intern/list_sort_impl.h341
-rw-r--r--source/blender/blenlib/intern/listbase.c152
-rw-r--r--source/blender/blenlib/intern/math_base.c41
-rw-r--r--source/blender/blenlib/intern/math_base_inline.c90
-rw-r--r--source/blender/blenlib/intern/math_bits_inline.c92
-rw-r--r--source/blender/blenlib/intern/math_color.c21
-rw-r--r--source/blender/blenlib/intern/math_color_blend_inline.c34
-rw-r--r--source/blender/blenlib/intern/math_color_inline.c88
-rw-r--r--source/blender/blenlib/intern/math_geom.c1393
-rw-r--r--source/blender/blenlib/intern/math_geom_inline.c6
-rw-r--r--source/blender/blenlib/intern/math_interp.c16
-rw-r--r--source/blender/blenlib/intern/math_matrix.c191
-rw-r--r--source/blender/blenlib/intern/math_rotation.c62
-rw-r--r--source/blender/blenlib/intern/math_solvers.c61
-rw-r--r--source/blender/blenlib/intern/math_statistics.c116
-rw-r--r--source/blender/blenlib/intern/math_vector.c99
-rw-r--r--source/blender/blenlib/intern/math_vector_inline.c126
-rw-r--r--source/blender/blenlib/intern/noise.c6
-rw-r--r--source/blender/blenlib/intern/path_util.c1194
-rw-r--r--source/blender/blenlib/intern/polyfill2d.c13
-rw-r--r--source/blender/blenlib/intern/polyfill2d_beautify.c495
-rw-r--r--source/blender/blenlib/intern/quadric.c65
-rw-r--r--source/blender/blenlib/intern/rand.c72
-rw-r--r--source/blender/blenlib/intern/rct.c83
-rw-r--r--source/blender/blenlib/intern/scanfill.c30
-rw-r--r--source/blender/blenlib/intern/scanfill_utils.c24
-rw-r--r--source/blender/blenlib/intern/smallhash.c59
-rw-r--r--source/blender/blenlib/intern/sort.c4
-rw-r--r--source/blender/blenlib/intern/stack.c110
-rw-r--r--source/blender/blenlib/intern/storage.c287
-rw-r--r--source/blender/blenlib/intern/string.c234
-rw-r--r--source/blender/blenlib/intern/string_utf8.c69
-rw-r--r--source/blender/blenlib/intern/system.c80
-rw-r--r--source/blender/blenlib/intern/task.c201
-rw-r--r--source/blender/blenlib/intern/threads.c142
-rw-r--r--source/blender/blenlib/intern/time.c18
-rw-r--r--source/blender/blenlib/intern/timecode.c59
-rw-r--r--source/blender/blenlib/intern/winstuff.c4
-rw-r--r--source/blender/blenlib/intern/winstuff_dir.c50
-rw-r--r--source/blender/blenloader/BLO_blend_defs.h49
-rw-r--r--source/blender/blenloader/BLO_readfile.h27
-rw-r--r--source/blender/blenloader/BLO_undofile.h6
-rw-r--r--source/blender/blenloader/BLO_writefile.h6
-rw-r--r--source/blender/blenloader/CMakeLists.txt1
-rw-r--r--source/blender/blenloader/SConscript8
-rw-r--r--source/blender/blenloader/intern/readblenentry.c35
-rw-r--r--source/blender/blenloader/intern/readfile.c1217
-rw-r--r--source/blender/blenloader/intern/readfile.h10
-rw-r--r--source/blender/blenloader/intern/runtime.c1
-rw-r--r--source/blender/blenloader/intern/undofile.c9
-rw-r--r--source/blender/blenloader/intern/versioning_250.c45
-rw-r--r--source/blender/blenloader/intern/versioning_260.c16
-rw-r--r--source/blender/blenloader/intern/versioning_270.c500
-rw-r--r--source/blender/blenloader/intern/versioning_defaults.c41
-rw-r--r--source/blender/blenloader/intern/versioning_legacy.c154
-rw-r--r--source/blender/blenloader/intern/writefile.c428
-rw-r--r--source/blender/blentranslation/BLT_lang.h69
-rw-r--r--source/blender/blentranslation/BLT_translation.h206
-rw-r--r--source/blender/blentranslation/CMakeLists.txt56
-rw-r--r--source/blender/blentranslation/SConscript46
-rw-r--r--source/blender/blentranslation/intern/blt_lang.c (renamed from source/blender/blenfont/intern/blf_lang.c)76
-rw-r--r--source/blender/blentranslation/intern/blt_translation.c (renamed from source/blender/blenfont/intern/blf_translation.c)148
-rw-r--r--source/blender/bmesh/CMakeLists.txt9
-rw-r--r--source/blender/bmesh/SConscript2
-rw-r--r--source/blender/bmesh/bmesh.h44
-rw-r--r--source/blender/bmesh/bmesh_class.h58
-rw-r--r--source/blender/bmesh/bmesh_tools.h1
-rw-r--r--source/blender/bmesh/intern/bmesh_callback_generic.c60
-rw-r--r--source/blender/bmesh/intern/bmesh_callback_generic.h45
-rw-r--r--source/blender/bmesh/intern/bmesh_construct.c288
-rw-r--r--source/blender/bmesh/intern/bmesh_construct.h35
-rw-r--r--source/blender/bmesh/intern/bmesh_core.c792
-rw-r--r--source/blender/bmesh/intern/bmesh_core.h64
-rw-r--r--source/blender/bmesh/intern/bmesh_edgeloop.c24
-rw-r--r--source/blender/bmesh/intern/bmesh_edgeloop.h22
-rw-r--r--source/blender/bmesh/intern/bmesh_inline.h3
-rw-r--r--source/blender/bmesh/intern/bmesh_interp.c449
-rw-r--r--source/blender/bmesh/intern/bmesh_interp.h37
-rw-r--r--source/blender/bmesh/intern/bmesh_iterators.c28
-rw-r--r--source/blender/bmesh/intern/bmesh_iterators.h50
-rw-r--r--source/blender/bmesh/intern/bmesh_iterators_inline.h3
-rw-r--r--source/blender/bmesh/intern/bmesh_log.c87
-rw-r--r--source/blender/bmesh/intern/bmesh_log.h5
-rw-r--r--source/blender/bmesh/intern/bmesh_marking.c225
-rw-r--r--source/blender/bmesh/intern/bmesh_marking.h30
-rw-r--r--source/blender/bmesh/intern/bmesh_mesh.c438
-rw-r--r--source/blender/bmesh/intern/bmesh_mesh.h16
-rw-r--r--source/blender/bmesh/intern/bmesh_mesh_conv.c22
-rw-r--r--source/blender/bmesh/intern/bmesh_mesh_conv.h5
-rw-r--r--source/blender/bmesh/intern/bmesh_mesh_validate.c11
-rw-r--r--source/blender/bmesh/intern/bmesh_mods.c64
-rw-r--r--source/blender/bmesh/intern/bmesh_mods.h58
-rw-r--r--source/blender/bmesh/intern/bmesh_opdefines.c83
-rw-r--r--source/blender/bmesh/intern/bmesh_operator_api.h124
-rw-r--r--source/blender/bmesh/intern/bmesh_operator_api_inline.h49
-rw-r--r--source/blender/bmesh/intern/bmesh_operators.c159
-rw-r--r--source/blender/bmesh/intern/bmesh_operators.h27
-rw-r--r--source/blender/bmesh/intern/bmesh_operators_private.h3
-rw-r--r--source/blender/bmesh/intern/bmesh_polygon.c298
-rw-r--r--source/blender/bmesh/intern/bmesh_polygon.h31
-rw-r--r--source/blender/bmesh/intern/bmesh_private.h1
-rw-r--r--source/blender/bmesh/intern/bmesh_queries.c598
-rw-r--r--source/blender/bmesh/intern/bmesh_queries.h90
-rw-r--r--source/blender/bmesh/intern/bmesh_queries_inline.h12
-rw-r--r--source/blender/bmesh/intern/bmesh_structure.c115
-rw-r--r--source/blender/bmesh/intern/bmesh_structure.h6
-rw-r--r--source/blender/bmesh/intern/bmesh_structure_inline.h5
-rw-r--r--source/blender/bmesh/intern/bmesh_walkers.c11
-rw-r--r--source/blender/bmesh/intern/bmesh_walkers.h18
-rw-r--r--source/blender/bmesh/intern/bmesh_walkers_impl.c412
-rw-r--r--source/blender/bmesh/intern/bmesh_walkers_private.h14
-rw-r--r--source/blender/bmesh/operators/bmo_bevel.c16
-rw-r--r--source/blender/bmesh/operators/bmo_bridge.c46
-rw-r--r--source/blender/bmesh/operators/bmo_connect_concave.c219
-rw-r--r--source/blender/bmesh/operators/bmo_connect_nonplanar.c21
-rw-r--r--source/blender/bmesh/operators/bmo_connect_pair.c395
-rw-r--r--source/blender/bmesh/operators/bmo_create.c2
-rw-r--r--source/blender/bmesh/operators/bmo_dissolve.c4
-rw-r--r--source/blender/bmesh/operators/bmo_dupe.c33
-rw-r--r--source/blender/bmesh/operators/bmo_extrude.c78
-rw-r--r--source/blender/bmesh/operators/bmo_fill_attribute.c10
-rw-r--r--source/blender/bmesh/operators/bmo_fill_grid.c33
-rw-r--r--source/blender/bmesh/operators/bmo_hull.c51
-rw-r--r--source/blender/bmesh/operators/bmo_inset.c28
-rw-r--r--source/blender/bmesh/operators/bmo_join_triangles.c434
-rw-r--r--source/blender/bmesh/operators/bmo_normals.c167
-rw-r--r--source/blender/bmesh/operators/bmo_offset_edgeloops.c290
-rw-r--r--source/blender/bmesh/operators/bmo_planar_faces.c158
-rw-r--r--source/blender/bmesh/operators/bmo_primitive.c102
-rw-r--r--source/blender/bmesh/operators/bmo_removedoubles.c128
-rw-r--r--source/blender/bmesh/operators/bmo_similar.c31
-rw-r--r--source/blender/bmesh/operators/bmo_subdivide.c209
-rw-r--r--source/blender/bmesh/operators/bmo_subdivide_edgering.c47
-rw-r--r--source/blender/bmesh/operators/bmo_triangulate.c9
-rw-r--r--source/blender/bmesh/operators/bmo_utils.c211
-rw-r--r--source/blender/bmesh/operators/bmo_wireframe.c2
-rw-r--r--source/blender/bmesh/tools/bmesh_beautify.c147
-rw-r--r--source/blender/bmesh/tools/bmesh_beautify.h14
-rw-r--r--source/blender/bmesh/tools/bmesh_bevel.c1359
-rw-r--r--source/blender/bmesh/tools/bmesh_bevel.h9
-rw-r--r--source/blender/bmesh/tools/bmesh_bisect_plane.c36
-rw-r--r--source/blender/bmesh/tools/bmesh_bisect_plane.h7
-rw-r--r--source/blender/bmesh/tools/bmesh_decimate.h25
-rw-r--r--source/blender/bmesh/tools/bmesh_decimate_collapse.c254
-rw-r--r--source/blender/bmesh/tools/bmesh_decimate_dissolve.c77
-rw-r--r--source/blender/bmesh/tools/bmesh_edgenet.c18
-rw-r--r--source/blender/bmesh/tools/bmesh_edgenet.h5
-rw-r--r--source/blender/bmesh/tools/bmesh_edgesplit.c112
-rw-r--r--source/blender/bmesh/tools/bmesh_edgesplit.h5
-rw-r--r--source/blender/bmesh/tools/bmesh_intersect.c31
-rw-r--r--source/blender/bmesh/tools/bmesh_path.c12
-rw-r--r--source/blender/bmesh/tools/bmesh_path.h9
-rw-r--r--source/blender/bmesh/tools/bmesh_region_match.c1519
-rw-r--r--source/blender/bmesh/tools/bmesh_region_match.h33
-rw-r--r--source/blender/bmesh/tools/bmesh_triangulate.c75
-rw-r--r--source/blender/bmesh/tools/bmesh_triangulate.h5
-rw-r--r--source/blender/bmesh/tools/bmesh_wireframe.c7
-rw-r--r--source/blender/collada/AnimationExporter.cpp96
-rw-r--r--source/blender/collada/AnimationExporter.h5
-rw-r--r--source/blender/collada/AnimationImporter.cpp41
-rw-r--r--source/blender/collada/AnimationImporter.h3
-rw-r--r--source/blender/collada/ArmatureExporter.cpp4
-rw-r--r--source/blender/collada/ArmatureImporter.cpp342
-rw-r--r--source/blender/collada/ArmatureImporter.h44
-rw-r--r--source/blender/collada/CMakeLists.txt2
-rw-r--r--source/blender/collada/ControllerExporter.cpp7
-rw-r--r--source/blender/collada/DocumentImporter.cpp45
-rw-r--r--source/blender/collada/DocumentImporter.h1
-rw-r--r--source/blender/collada/EffectExporter.cpp16
-rw-r--r--source/blender/collada/ErrorHandler.cpp26
-rw-r--r--source/blender/collada/GeometryExporter.cpp55
-rw-r--r--source/blender/collada/GeometryExporter.h19
-rw-r--r--source/blender/collada/ImageExporter.cpp6
-rw-r--r--source/blender/collada/ImportSettings.cpp2
-rw-r--r--source/blender/collada/ImportSettings.h6
-rw-r--r--source/blender/collada/MeshImporter.cpp61
-rw-r--r--source/blender/collada/MeshImporter.h2
-rw-r--r--source/blender/collada/SConscript2
-rw-r--r--source/blender/collada/SceneExporter.cpp4
-rw-r--r--source/blender/collada/SkinInfo.cpp9
-rw-r--r--source/blender/collada/TransformWriter.cpp2
-rw-r--r--source/blender/collada/collada.cpp33
-rw-r--r--source/blender/collada/collada.h5
-rw-r--r--source/blender/collada/collada_internal.cpp135
-rw-r--r--source/blender/collada/collada_utils.cpp10
-rw-r--r--source/blender/compositor/CMakeLists.txt17
-rw-r--r--source/blender/compositor/COM_compositor.h5
-rw-r--r--source/blender/compositor/COM_defines.h4
-rw-r--r--source/blender/compositor/SConscript4
-rw-r--r--source/blender/compositor/intern/COM_ChannelInfo.h121
-rw-r--r--source/blender/compositor/intern/COM_CompositorContext.h19
-rw-r--r--source/blender/compositor/intern/COM_Converter.cpp8
-rw-r--r--source/blender/compositor/intern/COM_Debug.cpp9
-rw-r--r--source/blender/compositor/intern/COM_ExecutionGroup.cpp48
-rw-r--r--source/blender/compositor/intern/COM_ExecutionGroup.h5
-rw-r--r--source/blender/compositor/intern/COM_ExecutionSystem.cpp26
-rw-r--r--source/blender/compositor/intern/COM_ExecutionSystem.h6
-rw-r--r--source/blender/compositor/intern/COM_MemoryBuffer.cpp137
-rw-r--r--source/blender/compositor/intern/COM_MemoryBuffer.h139
-rw-r--r--source/blender/compositor/intern/COM_MemoryProxy.cpp3
-rw-r--r--source/blender/compositor/intern/COM_MemoryProxy.h9
-rw-r--r--source/blender/compositor/intern/COM_NodeGraph.cpp2
-rw-r--r--source/blender/compositor/intern/COM_NodeOperation.h22
-rw-r--r--source/blender/compositor/intern/COM_NodeOperationBuilder.cpp15
-rw-r--r--source/blender/compositor/intern/COM_OpenCLDevice.cpp40
-rw-r--r--source/blender/compositor/intern/COM_OpenCLDevice.h6
-rw-r--r--source/blender/compositor/intern/COM_SingleThreadedOperation.cpp2
-rw-r--r--source/blender/compositor/intern/COM_SocketReader.h21
-rw-r--r--source/blender/compositor/intern/COM_WorkScheduler.cpp9
-rw-r--r--source/blender/compositor/intern/COM_compositor.cpp8
-rw-r--r--source/blender/compositor/nodes/COM_AlphaOverNode.cpp2
-rw-r--r--source/blender/compositor/nodes/COM_BlurNode.cpp2
-rw-r--r--source/blender/compositor/nodes/COM_BokehBlurNode.cpp9
-rw-r--r--source/blender/compositor/nodes/COM_BokehImageNode.cpp2
-rw-r--r--source/blender/compositor/nodes/COM_BrightnessNode.cpp2
-rw-r--r--source/blender/compositor/nodes/COM_ChannelMatteNode.cpp39
-rw-r--r--source/blender/compositor/nodes/COM_ChromaMatteNode.cpp2
-rw-r--r--source/blender/compositor/nodes/COM_ColorBalanceNode.cpp2
-rw-r--r--source/blender/compositor/nodes/COM_ColorCorrectionNode.cpp2
-rw-r--r--source/blender/compositor/nodes/COM_ColorCurveNode.cpp2
-rw-r--r--source/blender/compositor/nodes/COM_ColorMatteNode.cpp2
-rw-r--r--source/blender/compositor/nodes/COM_ColorNode.cpp2
-rw-r--r--source/blender/compositor/nodes/COM_ColorRampNode.cpp2
-rw-r--r--source/blender/compositor/nodes/COM_ColorSpillNode.cpp12
-rw-r--r--source/blender/compositor/nodes/COM_ColorToBWNode.cpp2
-rw-r--r--source/blender/compositor/nodes/COM_CombineColorNode.cpp8
-rw-r--r--source/blender/compositor/nodes/COM_CompositorNode.cpp3
-rw-r--r--source/blender/compositor/nodes/COM_ConvertAlphaNode.cpp2
-rw-r--r--source/blender/compositor/nodes/COM_CornerPinNode.cpp2
-rw-r--r--source/blender/compositor/nodes/COM_CropNode.cpp2
-rw-r--r--source/blender/compositor/nodes/COM_DespeckleNode.cpp2
-rw-r--r--source/blender/compositor/nodes/COM_DifferenceMatteNode.cpp2
-rw-r--r--source/blender/compositor/nodes/COM_DistanceMatteNode.cpp22
-rw-r--r--source/blender/compositor/nodes/COM_DoubleEdgeMaskNode.cpp2
-rw-r--r--source/blender/compositor/nodes/COM_FilterNode.cpp2
-rw-r--r--source/blender/compositor/nodes/COM_FlipNode.cpp2
-rw-r--r--source/blender/compositor/nodes/COM_GammaNode.cpp2
-rw-r--r--source/blender/compositor/nodes/COM_GlareNode.cpp2
-rw-r--r--source/blender/compositor/nodes/COM_HueSaturationValueCorrectNode.cpp2
-rw-r--r--source/blender/compositor/nodes/COM_HueSaturationValueNode.cpp2
-rw-r--r--source/blender/compositor/nodes/COM_ImageNode.cpp68
-rw-r--r--source/blender/compositor/nodes/COM_ImageNode.h2
-rw-r--r--source/blender/compositor/nodes/COM_InpaintNode.cpp2
-rw-r--r--source/blender/compositor/nodes/COM_InvertNode.cpp2
-rw-r--r--source/blender/compositor/nodes/COM_LensDistortionNode.cpp2
-rw-r--r--source/blender/compositor/nodes/COM_LuminanceMatteNode.cpp2
-rw-r--r--source/blender/compositor/nodes/COM_MapRangeNode.cpp2
-rw-r--r--source/blender/compositor/nodes/COM_MapUVNode.cpp2
-rw-r--r--source/blender/compositor/nodes/COM_MapValueNode.cpp2
-rw-r--r--source/blender/compositor/nodes/COM_MathNode.cpp40
-rw-r--r--source/blender/compositor/nodes/COM_MixNode.cpp6
-rw-r--r--source/blender/compositor/nodes/COM_NormalNode.cpp2
-rw-r--r--source/blender/compositor/nodes/COM_NormalizeNode.cpp2
-rw-r--r--source/blender/compositor/nodes/COM_OutputFileNode.cpp51
-rw-r--r--source/blender/compositor/nodes/COM_PixelateNode.cpp2
-rw-r--r--source/blender/compositor/nodes/COM_PlaneTrackDeformNode.cpp8
-rw-r--r--source/blender/compositor/nodes/COM_PlaneTrackDeformNode.h1
-rw-r--r--source/blender/compositor/nodes/COM_RenderLayersNode.cpp16
-rw-r--r--source/blender/compositor/nodes/COM_RotateNode.cpp2
-rw-r--r--source/blender/compositor/nodes/COM_SeparateColorNode.cpp8
-rw-r--r--source/blender/compositor/nodes/COM_SetAlphaNode.cpp2
-rw-r--r--source/blender/compositor/nodes/COM_SocketProxyNode.cpp9
-rw-r--r--source/blender/compositor/nodes/COM_SplitViewerNode.cpp4
-rw-r--r--source/blender/compositor/nodes/COM_SunBeamsNode.cpp2
-rw-r--r--source/blender/compositor/nodes/COM_SwitchNode.cpp2
-rw-r--r--source/blender/compositor/nodes/COM_SwitchViewNode.cpp42
-rw-r--r--source/blender/compositor/nodes/COM_SwitchViewNode.h37
-rw-r--r--source/blender/compositor/nodes/COM_TextureNode.cpp2
-rw-r--r--source/blender/compositor/nodes/COM_TonemapNode.cpp2
-rw-r--r--source/blender/compositor/nodes/COM_TransformNode.cpp2
-rw-r--r--source/blender/compositor/nodes/COM_TranslateNode.cpp4
-rw-r--r--source/blender/compositor/nodes/COM_ValueNode.cpp2
-rw-r--r--source/blender/compositor/nodes/COM_VectorCurveNode.cpp2
-rw-r--r--source/blender/compositor/nodes/COM_ViewLevelsNode.cpp2
-rw-r--r--source/blender/compositor/nodes/COM_ViewerNode.cpp7
-rw-r--r--source/blender/compositor/operations/COM_AntiAliasOperation.cpp6
-rw-r--r--source/blender/compositor/operations/COM_BilateralBlurOperation.cpp4
-rw-r--r--source/blender/compositor/operations/COM_BlurBaseOperation.cpp5
-rw-r--r--source/blender/compositor/operations/COM_BlurBaseOperation.h2
-rw-r--r--source/blender/compositor/operations/COM_BokehBlurOperation.cpp8
-rw-r--r--source/blender/compositor/operations/COM_BokehImageOperation.cpp4
-rw-r--r--source/blender/compositor/operations/COM_CalculateMeanOperation.cpp12
-rw-r--r--source/blender/compositor/operations/COM_CalculateStandardDeviationOperation.cpp10
-rw-r--r--source/blender/compositor/operations/COM_ChromaMatteOperation.cpp12
-rw-r--r--source/blender/compositor/operations/COM_ColorCorrectionOperation.cpp6
-rw-r--r--source/blender/compositor/operations/COM_ColorSpillOperation.cpp23
-rw-r--r--source/blender/compositor/operations/COM_ColorSpillOperation.h6
-rw-r--r--source/blender/compositor/operations/COM_CompositorOperation.cpp23
-rw-r--r--source/blender/compositor/operations/COM_CompositorOperation.h8
-rw-r--r--source/blender/compositor/operations/COM_ConvertDepthToRadiusOperation.cpp2
-rw-r--r--source/blender/compositor/operations/COM_ConvertOperation.cpp28
-rw-r--r--source/blender/compositor/operations/COM_ConvolutionEdgeFilterOperation.cpp2
-rw-r--r--source/blender/compositor/operations/COM_ConvolutionFilterOperation.cpp2
-rw-r--r--source/blender/compositor/operations/COM_CropOperation.cpp37
-rw-r--r--source/blender/compositor/operations/COM_CropOperation.h2
-rw-r--r--source/blender/compositor/operations/COM_DespeckleOperation.cpp2
-rw-r--r--source/blender/compositor/operations/COM_DilateErodeOperation.cpp33
-rw-r--r--source/blender/compositor/operations/COM_DirectionalBlurOperation.cpp18
-rw-r--r--source/blender/compositor/operations/COM_DisplaceOperation.cpp12
-rw-r--r--source/blender/compositor/operations/COM_DoubleEdgeMaskOperation.cpp8
-rw-r--r--source/blender/compositor/operations/COM_FastGaussianBlurOperation.cpp29
-rw-r--r--source/blender/compositor/operations/COM_FlipOperation.cpp14
-rw-r--r--source/blender/compositor/operations/COM_GaussianAlphaXBlurOperation.cpp9
-rw-r--r--source/blender/compositor/operations/COM_GaussianAlphaYBlurOperation.cpp6
-rw-r--r--source/blender/compositor/operations/COM_GaussianBokehBlurOperation.cpp10
-rw-r--r--source/blender/compositor/operations/COM_GaussianXBlurOperation.cpp31
-rw-r--r--source/blender/compositor/operations/COM_GaussianXBlurOperation.h11
-rw-r--r--source/blender/compositor/operations/COM_GaussianYBlurOperation.cpp31
-rw-r--r--source/blender/compositor/operations/COM_GaussianYBlurOperation.h11
-rw-r--r--source/blender/compositor/operations/COM_GlareBaseOperation.cpp4
-rw-r--r--source/blender/compositor/operations/COM_GlareFogGlowOperation.cpp18
-rw-r--r--source/blender/compositor/operations/COM_GlareGhostOperation.cpp8
-rw-r--r--source/blender/compositor/operations/COM_GlareStreaksOperation.cpp2
-rw-r--r--source/blender/compositor/operations/COM_GlareThresholdOperation.cpp6
-rw-r--r--source/blender/compositor/operations/COM_ImageOperation.cpp19
-rw-r--r--source/blender/compositor/operations/COM_ImageOperation.h7
-rw-r--r--source/blender/compositor/operations/COM_InpaintOperation.cpp8
-rw-r--r--source/blender/compositor/operations/COM_KeyingBlurOperation.cpp38
-rw-r--r--source/blender/compositor/operations/COM_KeyingClipOperation.cpp4
-rw-r--r--source/blender/compositor/operations/COM_KeyingScreenOperation.cpp25
-rw-r--r--source/blender/compositor/operations/COM_KeyingScreenOperation.h2
-rw-r--r--source/blender/compositor/operations/COM_LuminanceMatteOperation.cpp2
-rw-r--r--source/blender/compositor/operations/COM_MapUVOperation.cpp14
-rw-r--r--source/blender/compositor/operations/COM_MaskOperation.cpp3
-rw-r--r--source/blender/compositor/operations/COM_MixOperation.cpp6
-rw-r--r--source/blender/compositor/operations/COM_MixOperation.h2
-rw-r--r--source/blender/compositor/operations/COM_MovieClipAttributeOperation.cpp4
-rw-r--r--source/blender/compositor/operations/COM_MovieClipOperation.cpp10
-rw-r--r--source/blender/compositor/operations/COM_MovieDistortionOperation.cpp2
-rw-r--r--source/blender/compositor/operations/COM_MovieDistortionOperation.h14
-rw-r--r--source/blender/compositor/operations/COM_MultilayerImageOperation.cpp25
-rw-r--r--source/blender/compositor/operations/COM_MultilayerImageOperation.h9
-rw-r--r--source/blender/compositor/operations/COM_NormalizeOperation.cpp6
-rw-r--r--source/blender/compositor/operations/COM_OpenCLKernels.cl75
-rw-r--r--source/blender/compositor/operations/COM_OutputFileMultiViewOperation.cpp322
-rw-r--r--source/blender/compositor/operations/COM_OutputFileMultiViewOperation.h74
-rw-r--r--source/blender/compositor/operations/COM_OutputFileOperation.cpp130
-rw-r--r--source/blender/compositor/operations/COM_OutputFileOperation.h22
-rw-r--r--source/blender/compositor/operations/COM_PlaneCornerPinOperation.cpp5
-rw-r--r--source/blender/compositor/operations/COM_PlaneDistortCommonOperation.cpp154
-rw-r--r--source/blender/compositor/operations/COM_PlaneDistortCommonOperation.h49
-rw-r--r--source/blender/compositor/operations/COM_PlaneTrackOperation.cpp64
-rw-r--r--source/blender/compositor/operations/COM_PlaneTrackOperation.h9
-rw-r--r--source/blender/compositor/operations/COM_PreviewOperation.cpp2
-rw-r--r--source/blender/compositor/operations/COM_PreviewOperation.h2
-rw-r--r--source/blender/compositor/operations/COM_ProjectorLensDistortionOperation.cpp2
-rw-r--r--source/blender/compositor/operations/COM_QualityStepHelper.cpp6
-rw-r--r--source/blender/compositor/operations/COM_ReadBufferOperation.cpp26
-rw-r--r--source/blender/compositor/operations/COM_ReadBufferOperation.h5
-rw-r--r--source/blender/compositor/operations/COM_RenderLayersProg.cpp124
-rw-r--r--source/blender/compositor/operations/COM_RenderLayersProg.h21
-rw-r--r--source/blender/compositor/operations/COM_ScaleOperation.cpp2
-rw-r--r--source/blender/compositor/operations/COM_ScreenLensDistortionOperation.cpp4
-rw-r--r--source/blender/compositor/operations/COM_SetColorOperation.cpp4
-rw-r--r--source/blender/compositor/operations/COM_SetSamplerOperation.cpp2
-rw-r--r--source/blender/compositor/operations/COM_SetValueOperation.cpp4
-rw-r--r--source/blender/compositor/operations/COM_SetVectorOperation.cpp5
-rw-r--r--source/blender/compositor/operations/COM_SplitOperation.cpp2
-rw-r--r--source/blender/compositor/operations/COM_SunBeamsOperation.cpp98
-rw-r--r--source/blender/compositor/operations/COM_TextureOperation.cpp30
-rw-r--r--source/blender/compositor/operations/COM_TonemapOperation.cpp12
-rw-r--r--source/blender/compositor/operations/COM_TrackPositionOperation.cpp4
-rw-r--r--source/blender/compositor/operations/COM_TranslateOperation.cpp2
-rw-r--r--source/blender/compositor/operations/COM_VariableSizeBokehBlurOperation.cpp40
-rw-r--r--source/blender/compositor/operations/COM_VectorBlurOperation.cpp8
-rw-r--r--source/blender/compositor/operations/COM_VectorCurveOperation.cpp1
-rw-r--r--source/blender/compositor/operations/COM_ViewerOperation.cpp26
-rw-r--r--source/blender/compositor/operations/COM_ViewerOperation.h8
-rw-r--r--source/blender/compositor/operations/COM_WrapOperation.cpp2
-rw-r--r--source/blender/compositor/operations/COM_WrapOperation.h2
-rw-r--r--source/blender/compositor/operations/COM_WriteBufferOperation.cpp26
-rw-r--r--source/blender/compositor/operations/COM_WriteBufferOperation.h2
-rw-r--r--source/blender/datatoc/datatoc_icon.c3
-rwxr-xr-xsource/blender/datatoc/datatoc_icon.py11
-rwxr-xr-xsource/blender/datatoc/datatoc_icon_split.py2
-rw-r--r--source/blender/depsgraph/CMakeLists.txt122
-rw-r--r--source/blender/depsgraph/DEG_depsgraph.h223
-rw-r--r--source/blender/depsgraph/DEG_depsgraph_build.h121
-rw-r--r--source/blender/depsgraph/DEG_depsgraph_debug.h111
-rw-r--r--source/blender/depsgraph/DEG_depsgraph_query.h195
-rw-r--r--source/blender/depsgraph/SConscript77
-rw-r--r--source/blender/depsgraph/intern/depsgraph.cc500
-rw-r--r--source/blender/depsgraph/intern/depsgraph.h224
-rw-r--r--source/blender/depsgraph/intern/depsgraph_build.cc370
-rw-r--r--source/blender/depsgraph/intern/depsgraph_build.h408
-rw-r--r--source/blender/depsgraph/intern/depsgraph_build_nodes.cc1204
-rw-r--r--source/blender/depsgraph/intern/depsgraph_build_relations.cc1880
-rw-r--r--source/blender/depsgraph/intern/depsgraph_debug.cc1212
-rw-r--r--source/blender/depsgraph/intern/depsgraph_debug.h87
-rw-r--r--source/blender/depsgraph/intern/depsgraph_eval.cc399
-rw-r--r--source/blender/depsgraph/intern/depsgraph_intern.h168
-rw-r--r--source/blender/depsgraph/intern/depsgraph_query.cc217
-rw-r--r--source/blender/depsgraph/intern/depsgraph_queue.cc177
-rw-r--r--source/blender/depsgraph/intern/depsgraph_queue.h91
-rw-r--r--source/blender/depsgraph/intern/depsgraph_tag.cc541
-rw-r--r--source/blender/depsgraph/intern/depsgraph_type_defines.cc102
-rw-r--r--source/blender/depsgraph/intern/depsgraph_types.h173
-rw-r--r--source/blender/depsgraph/intern/depsnode.cc316
-rw-r--r--source/blender/depsgraph/intern/depsnode.h248
-rw-r--r--source/blender/depsgraph/intern/depsnode_component.cc318
-rw-r--r--source/blender/depsgraph/intern/depsnode_component.h201
-rw-r--r--source/blender/depsgraph/intern/depsnode_opcodes.h145
-rw-r--r--source/blender/depsgraph/intern/depsnode_operation.cc104
-rw-r--r--source/blender/depsgraph/intern/depsnode_operation.h90
-rw-r--r--source/blender/depsgraph/util/depsgraph_util_cycle.cc140
-rw-r--r--source/blender/depsgraph/util/depsgraph_util_cycle.h37
-rw-r--r--source/blender/depsgraph/util/depsgraph_util_function.h112
-rw-r--r--source/blender/depsgraph/util/depsgraph_util_hash.h72
-rw-r--r--source/blender/depsgraph/util/depsgraph_util_map.h67
-rw-r--r--source/blender/depsgraph/util/depsgraph_util_pchanmap.cc136
-rw-r--r--source/blender/depsgraph/util/depsgraph_util_pchanmap.h59
-rw-r--r--source/blender/depsgraph/util/depsgraph_util_set.h66
-rw-r--r--source/blender/depsgraph/util/depsgraph_util_transitive.cc139
-rw-r--r--source/blender/depsgraph/util/depsgraph_util_transitive.h38
-rw-r--r--source/blender/editors/animation/CMakeLists.txt6
-rw-r--r--source/blender/editors/animation/SConscript7
-rw-r--r--source/blender/editors/animation/anim_channels_defines.c551
-rw-r--r--source/blender/editors/animation/anim_channels_edit.c528
-rw-r--r--source/blender/editors/animation/anim_deps.c6
-rw-r--r--source/blender/editors/animation/anim_draw.c238
-rw-r--r--source/blender/editors/animation/anim_filter.c260
-rw-r--r--source/blender/editors/animation/anim_ipo_utils.c2
-rw-r--r--source/blender/editors/animation/anim_markers.c152
-rw-r--r--source/blender/editors/animation/anim_ops.c89
-rw-r--r--source/blender/editors/animation/drivers.c112
-rw-r--r--source/blender/editors/animation/fmodifier_ui.c90
-rw-r--r--source/blender/editors/animation/keyframes_draw.c45
-rw-r--r--source/blender/editors/animation/keyframes_edit.c74
-rw-r--r--source/blender/editors/animation/keyframes_general.c202
-rw-r--r--source/blender/editors/animation/keyframing.c218
-rw-r--r--source/blender/editors/animation/keyingsets.c69
-rw-r--r--source/blender/editors/armature/BIF_retarget.h1
-rw-r--r--source/blender/editors/armature/CMakeLists.txt7
-rw-r--r--source/blender/editors/armature/SConscript8
-rw-r--r--source/blender/editors/armature/armature_add.c348
-rw-r--r--source/blender/editors/armature/armature_edit.c407
-rw-r--r--source/blender/editors/armature/armature_intern.h5
-rw-r--r--source/blender/editors/armature/armature_naming.c13
-rw-r--r--source/blender/editors/armature/armature_ops.c14
-rw-r--r--source/blender/editors/armature/armature_relations.c180
-rw-r--r--source/blender/editors/armature/armature_select.c199
-rw-r--r--source/blender/editors/armature/armature_skinning.c32
-rw-r--r--source/blender/editors/armature/armature_utils.c165
-rw-r--r--source/blender/editors/armature/editarmature_retarget.c22
-rw-r--r--source/blender/editors/armature/editarmature_sketch.c36
-rw-r--r--source/blender/editors/armature/meshlaplacian.c306
-rw-r--r--source/blender/editors/armature/meshlaplacian.h2
-rw-r--r--source/blender/editors/armature/pose_edit.c20
-rw-r--r--source/blender/editors/armature/pose_group.c26
-rw-r--r--source/blender/editors/armature/pose_lib.c56
-rw-r--r--source/blender/editors/armature/pose_select.c110
-rw-r--r--source/blender/editors/armature/pose_slide.c171
-rw-r--r--source/blender/editors/armature/pose_transform.c4
-rw-r--r--source/blender/editors/armature/pose_utils.c4
-rw-r--r--source/blender/editors/armature/reeb.c26
-rw-r--r--source/blender/editors/armature/reeb.h3
-rw-r--r--source/blender/editors/curve/CMakeLists.txt4
-rw-r--r--source/blender/editors/curve/SConscript2
-rw-r--r--source/blender/editors/curve/curve_intern.h55
-rw-r--r--source/blender/editors/curve/curve_ops.c10
-rw-r--r--source/blender/editors/curve/editcurve.c2029
-rw-r--r--source/blender/editors/curve/editcurve_add.c64
-rw-r--r--source/blender/editors/curve/editcurve_select.c1728
-rw-r--r--source/blender/editors/curve/editfont.c77
-rw-r--r--source/blender/editors/curve/lorem.c658
-rw-r--r--source/blender/editors/gpencil/CMakeLists.txt10
-rw-r--r--source/blender/editors/gpencil/SConscript5
-rw-r--r--source/blender/editors/gpencil/drawgpencil.c952
-rw-r--r--source/blender/editors/gpencil/editaction_gpencil.c61
-rw-r--r--source/blender/editors/gpencil/gpencil_buttons.c378
-rw-r--r--source/blender/editors/gpencil/gpencil_convert.c1484
-rw-r--r--source/blender/editors/gpencil/gpencil_data.c447
-rw-r--r--source/blender/editors/gpencil/gpencil_edit.c2144
-rw-r--r--source/blender/editors/gpencil/gpencil_intern.h103
-rw-r--r--source/blender/editors/gpencil/gpencil_ops.c222
-rw-r--r--source/blender/editors/gpencil/gpencil_paint.c451
-rw-r--r--source/blender/editors/gpencil/gpencil_select.c930
-rw-r--r--source/blender/editors/gpencil/gpencil_undo.c61
-rw-r--r--source/blender/editors/gpencil/gpencil_utils.c375
-rw-r--r--source/blender/editors/include/BIF_gl.h54
-rw-r--r--source/blender/editors/include/BIF_glutil.h22
-rw-r--r--source/blender/editors/include/ED_anim_api.h33
-rw-r--r--source/blender/editors/include/ED_armature.h26
-rw-r--r--source/blender/editors/include/ED_buttons.h2
-rw-r--r--source/blender/editors/include/ED_curve.h24
-rw-r--r--source/blender/editors/include/ED_fileselect.h49
-rw-r--r--source/blender/editors/include/ED_gpencil.h39
-rw-r--r--source/blender/editors/include/ED_image.h15
-rw-r--r--source/blender/editors/include/ED_keyframes_draw.h10
-rw-r--r--source/blender/editors/include/ED_keyframes_edit.h21
-rw-r--r--source/blender/editors/include/ED_keyframing.h4
-rw-r--r--source/blender/editors/include/ED_lattice.h1
-rw-r--r--source/blender/editors/include/ED_markers.h5
-rw-r--r--source/blender/editors/include/ED_mask.h3
-rw-r--r--source/blender/editors/include/ED_mball.h1
-rw-r--r--source/blender/editors/include/ED_mesh.h64
-rw-r--r--source/blender/editors/include/ED_node.h3
-rw-r--r--source/blender/editors/include/ED_object.h56
-rw-r--r--source/blender/editors/include/ED_outliner.h36
-rw-r--r--source/blender/editors/include/ED_paint.h7
-rw-r--r--source/blender/editors/include/ED_particle.h7
-rw-r--r--source/blender/editors/include/ED_render.h38
-rw-r--r--source/blender/editors/include/ED_screen.h26
-rw-r--r--source/blender/editors/include/ED_screen_types.h3
-rw-r--r--source/blender/editors/include/ED_sculpt.h2
-rw-r--r--source/blender/editors/include/ED_sequencer.h6
-rw-r--r--source/blender/editors/include/ED_text.h3
-rw-r--r--source/blender/editors/include/ED_transform.h12
-rw-r--r--source/blender/editors/include/ED_util.h12
-rw-r--r--source/blender/editors/include/ED_uvedit.h13
-rw-r--r--source/blender/editors/include/ED_view3d.h104
-rw-r--r--source/blender/editors/include/UI_icons.h44
-rw-r--r--source/blender/editors/include/UI_interface.h520
-rw-r--r--source/blender/editors/include/UI_interface_icons.h19
-rw-r--r--source/blender/editors/include/UI_resources.h26
-rw-r--r--source/blender/editors/include/UI_view2d.h4
-rw-r--r--source/blender/editors/interface/CMakeLists.txt10
-rw-r--r--source/blender/editors/interface/SConscript9
-rw-r--r--source/blender/editors/interface/interface.c1094
-rw-r--r--source/blender/editors/interface/interface_anim.c92
-rw-r--r--source/blender/editors/interface/interface_draw.c153
-rw-r--r--source/blender/editors/interface/interface_eyedropper.c528
-rw-r--r--source/blender/editors/interface/interface_handlers.c2473
-rw-r--r--source/blender/editors/interface/interface_icons.c297
-rw-r--r--source/blender/editors/interface/interface_intern.h223
-rw-r--r--source/blender/editors/interface/interface_layout.c411
-rw-r--r--source/blender/editors/interface/interface_ops.c169
-rw-r--r--source/blender/editors/interface/interface_panel.c361
-rw-r--r--source/blender/editors/interface/interface_regions.c887
-rw-r--r--source/blender/editors/interface/interface_style.c185
-rw-r--r--source/blender/editors/interface/interface_templates.c1026
-rw-r--r--source/blender/editors/interface/interface_utils.c113
-rw-r--r--source/blender/editors/interface/interface_widgets.c766
-rw-r--r--source/blender/editors/interface/resources.c363
-rw-r--r--source/blender/editors/interface/view2d.c235
-rw-r--r--source/blender/editors/interface/view2d_ops.c156
-rw-r--r--source/blender/editors/io/CMakeLists.txt2
-rw-r--r--source/blender/editors/io/SConscript2
-rw-r--r--source/blender/editors/io/io_collada.c130
-rw-r--r--source/blender/editors/io/io_ops.c13
-rw-r--r--source/blender/editors/mask/CMakeLists.txt4
-rw-r--r--source/blender/editors/mask/SConscript5
-rw-r--r--source/blender/editors/mask/mask_add.c34
-rw-r--r--source/blender/editors/mask/mask_draw.c4
-rw-r--r--source/blender/editors/mask/mask_edit.c53
-rw-r--r--source/blender/editors/mask/mask_intern.h9
-rw-r--r--source/blender/editors/mask/mask_ops.c33
-rw-r--r--source/blender/editors/mask/mask_relationships.c1
-rw-r--r--source/blender/editors/mesh/CMakeLists.txt5
-rw-r--r--source/blender/editors/mesh/SConscript6
-rw-r--r--source/blender/editors/mesh/editface.c70
-rw-r--r--source/blender/editors/mesh/editmesh_add.c70
-rw-r--r--source/blender/editors/mesh/editmesh_bevel.c51
-rw-r--r--source/blender/editors/mesh/editmesh_bisect.c12
-rw-r--r--source/blender/editors/mesh/editmesh_extrude.c270
-rw-r--r--source/blender/editors/mesh/editmesh_inset.c10
-rw-r--r--source/blender/editors/mesh/editmesh_intersect.c3
-rw-r--r--source/blender/editors/mesh/editmesh_knife.c841
-rw-r--r--source/blender/editors/mesh/editmesh_knife_project.c2
-rw-r--r--source/blender/editors/mesh/editmesh_loopcut.c60
-rw-r--r--source/blender/editors/mesh/editmesh_path.c24
-rw-r--r--source/blender/editors/mesh/editmesh_rip.c266
-rw-r--r--source/blender/editors/mesh/editmesh_rip_edge.c7
-rw-r--r--source/blender/editors/mesh/editmesh_select.c1330
-rw-r--r--source/blender/editors/mesh/editmesh_tools.c1002
-rw-r--r--source/blender/editors/mesh/editmesh_utils.c255
-rw-r--r--source/blender/editors/mesh/mesh_data.c210
-rw-r--r--source/blender/editors/mesh/mesh_intern.h17
-rw-r--r--source/blender/editors/mesh/mesh_navmesh.c7
-rw-r--r--source/blender/editors/mesh/mesh_ops.c26
-rw-r--r--source/blender/editors/mesh/meshtools.c14
-rw-r--r--source/blender/editors/metaball/mball_edit.c8
-rw-r--r--source/blender/editors/metaball/mball_ops.c4
-rw-r--r--source/blender/editors/object/CMakeLists.txt8
-rw-r--r--source/blender/editors/object/SConscript2
-rw-r--r--source/blender/editors/object/object_add.c278
-rw-r--r--source/blender/editors/object/object_bake.c29
-rw-r--r--source/blender/editors/object/object_bake_api.c70
-rw-r--r--source/blender/editors/object/object_constraint.c560
-rw-r--r--source/blender/editors/object/object_data_transfer.c729
-rw-r--r--source/blender/editors/object/object_edit.c167
-rw-r--r--source/blender/editors/object/object_group.c53
-rw-r--r--source/blender/editors/object/object_hook.c21
-rw-r--r--source/blender/editors/object/object_intern.h29
-rw-r--r--source/blender/editors/object/object_lattice.c4
-rw-r--r--source/blender/editors/object/object_lod.c8
-rw-r--r--source/blender/editors/object/object_modifier.c149
-rw-r--r--source/blender/editors/object/object_ops.c18
-rw-r--r--source/blender/editors/object/object_random.c4
-rw-r--r--source/blender/editors/object/object_relations.c669
-rw-r--r--source/blender/editors/object/object_select.c39
-rw-r--r--source/blender/editors/object/object_shapekey.c212
-rw-r--r--source/blender/editors/object/object_transform.c9
-rw-r--r--source/blender/editors/object/object_vgroup.c1416
-rw-r--r--source/blender/editors/object/object_warp.c5
-rw-r--r--source/blender/editors/physics/CMakeLists.txt6
-rw-r--r--source/blender/editors/physics/SConscript7
-rw-r--r--source/blender/editors/physics/dynamicpaint_ops.c14
-rw-r--r--source/blender/editors/physics/particle_edit.c322
-rw-r--r--source/blender/editors/physics/particle_object.c495
-rw-r--r--source/blender/editors/physics/physics_fluid.c2
-rw-r--r--source/blender/editors/physics/physics_intern.h4
-rw-r--r--source/blender/editors/physics/physics_ops.c8
-rw-r--r--source/blender/editors/physics/rigidbody_constraint.c2
-rw-r--r--source/blender/editors/physics/rigidbody_object.c8
-rw-r--r--source/blender/editors/physics/rigidbody_world.c8
-rw-r--r--source/blender/editors/render/CMakeLists.txt5
-rw-r--r--source/blender/editors/render/SConscript5
-rw-r--r--source/blender/editors/render/render_intern.h8
-rw-r--r--source/blender/editors/render/render_internal.c87
-rw-r--r--source/blender/editors/render/render_opengl.c440
-rw-r--r--source/blender/editors/render/render_ops.c4
-rw-r--r--source/blender/editors/render/render_preview.c275
-rw-r--r--source/blender/editors/render/render_shading.c211
-rw-r--r--source/blender/editors/render/render_update.c114
-rw-r--r--source/blender/editors/render/render_view.c39
-rw-r--r--source/blender/editors/screen/CMakeLists.txt4
-rw-r--r--source/blender/editors/screen/SConscript5
-rw-r--r--source/blender/editors/screen/area.c538
-rw-r--r--source/blender/editors/screen/glutil.c98
-rw-r--r--source/blender/editors/screen/screen_context.c145
-rw-r--r--source/blender/editors/screen/screen_edit.c362
-rw-r--r--source/blender/editors/screen/screen_intern.h4
-rw-r--r--source/blender/editors/screen/screen_ops.c424
-rw-r--r--source/blender/editors/screen/screendump.c48
-rw-r--r--source/blender/editors/sculpt_paint/CMakeLists.txt5
-rw-r--r--source/blender/editors/sculpt_paint/SConscript6
-rw-r--r--source/blender/editors/sculpt_paint/paint_cursor.c72
-rw-r--r--source/blender/editors/sculpt_paint/paint_curve.c72
-rw-r--r--source/blender/editors/sculpt_paint/paint_hide.c4
-rw-r--r--source/blender/editors/sculpt_paint/paint_image.c115
-rw-r--r--source/blender/editors/sculpt_paint/paint_image_2d.c166
-rw-r--r--source/blender/editors/sculpt_paint/paint_image_proj.c3275
-rw-r--r--source/blender/editors/sculpt_paint/paint_intern.h23
-rw-r--r--source/blender/editors/sculpt_paint/paint_mask.c25
-rw-r--r--source/blender/editors/sculpt_paint/paint_ops.c56
-rw-r--r--source/blender/editors/sculpt_paint/paint_stroke.c217
-rw-r--r--source/blender/editors/sculpt_paint/paint_undo.c23
-rw-r--r--source/blender/editors/sculpt_paint/paint_utils.c161
-rw-r--r--source/blender/editors/sculpt_paint/paint_vertex.c283
-rw-r--r--source/blender/editors/sculpt_paint/paint_vertex_proj.c2
-rw-r--r--source/blender/editors/sculpt_paint/sculpt.c1507
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_intern.h6
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_undo.c26
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_uv.c44
-rw-r--r--source/blender/editors/sound/CMakeLists.txt7
-rw-r--r--source/blender/editors/sound/SConscript5
-rw-r--r--source/blender/editors/sound/sound_intern.h1
-rw-r--r--source/blender/editors/sound/sound_ops.c43
-rw-r--r--source/blender/editors/space_action/CMakeLists.txt6
-rw-r--r--source/blender/editors/space_action/SConscript10
-rw-r--r--source/blender/editors/space_action/action_data.c963
-rw-r--r--source/blender/editors/space_action/action_draw.c13
-rw-r--r--source/blender/editors/space_action/action_edit.c213
-rw-r--r--source/blender/editors/space_action/action_intern.h12
-rw-r--r--source/blender/editors/space_action/action_ops.c29
-rw-r--r--source/blender/editors/space_action/action_select.c10
-rw-r--r--source/blender/editors/space_action/space_action.c4
-rw-r--r--source/blender/editors/space_api/spacetypes.c9
-rw-r--r--source/blender/editors/space_buttons/CMakeLists.txt6
-rw-r--r--source/blender/editors/space_buttons/SConscript8
-rw-r--r--source/blender/editors/space_buttons/buttons_context.c43
-rw-r--r--source/blender/editors/space_buttons/buttons_intern.h1
-rw-r--r--source/blender/editors/space_buttons/buttons_ops.c41
-rw-r--r--source/blender/editors/space_buttons/buttons_texture.c26
-rw-r--r--source/blender/editors/space_buttons/space_buttons.c43
-rw-r--r--source/blender/editors/space_clip/CMakeLists.txt8
-rw-r--r--source/blender/editors/space_clip/SConscript7
-rw-r--r--source/blender/editors/space_clip/clip_buttons.c73
-rw-r--r--source/blender/editors/space_clip/clip_dopesheet_draw.c15
-rw-r--r--source/blender/editors/space_clip/clip_dopesheet_ops.c1
-rw-r--r--source/blender/editors/space_clip/clip_draw.c63
-rw-r--r--source/blender/editors/space_clip/clip_editor.c116
-rw-r--r--source/blender/editors/space_clip/clip_graph_draw.c1
-rw-r--r--source/blender/editors/space_clip/clip_graph_ops.c24
-rw-r--r--source/blender/editors/space_clip/clip_ops.c159
-rw-r--r--source/blender/editors/space_clip/clip_toolbar.c6
-rw-r--r--source/blender/editors/space_clip/clip_utils.c50
-rw-r--r--source/blender/editors/space_clip/space_clip.c19
-rw-r--r--source/blender/editors/space_clip/tracking_ops.c61
-rw-r--r--source/blender/editors/space_clip/tracking_select.c11
-rw-r--r--source/blender/editors/space_console/CMakeLists.txt4
-rw-r--r--source/blender/editors/space_console/SConscript6
-rw-r--r--source/blender/editors/space_console/console_draw.c1
-rw-r--r--source/blender/editors/space_console/console_intern.h2
-rw-r--r--source/blender/editors/space_console/console_ops.c98
-rw-r--r--source/blender/editors/space_console/space_console.c2
-rw-r--r--source/blender/editors/space_file/CMakeLists.txt7
-rw-r--r--source/blender/editors/space_file/SConscript7
-rw-r--r--source/blender/editors/space_file/file_draw.c504
-rw-r--r--source/blender/editors/space_file/file_intern.h23
-rw-r--r--source/blender/editors/space_file/file_ops.c949
-rw-r--r--source/blender/editors/space_file/file_panels.c176
-rw-r--r--source/blender/editors/space_file/file_utils.c47
-rw-r--r--source/blender/editors/space_file/filelist.c2919
-rw-r--r--source/blender/editors/space_file/filelist.h93
-rw-r--r--source/blender/editors/space_file/filesel.c263
-rw-r--r--source/blender/editors/space_file/fsmenu.c322
-rw-r--r--source/blender/editors/space_file/fsmenu.h40
-rw-r--r--source/blender/editors/space_file/space_file.c222
-rw-r--r--source/blender/editors/space_graph/CMakeLists.txt13
-rw-r--r--source/blender/editors/space_graph/SConscript12
-rw-r--r--source/blender/editors/space_graph/graph_buttons.c112
-rw-r--r--source/blender/editors/space_graph/graph_draw.c125
-rw-r--r--source/blender/editors/space_graph/graph_edit.c123
-rw-r--r--source/blender/editors/space_graph/graph_intern.h5
-rw-r--r--source/blender/editors/space_graph/graph_ops.c235
-rw-r--r--source/blender/editors/space_graph/graph_select.c145
-rw-r--r--source/blender/editors/space_graph/graph_utils.c10
-rw-r--r--source/blender/editors/space_graph/space_graph.c6
-rw-r--r--source/blender/editors/space_image/CMakeLists.txt8
-rw-r--r--source/blender/editors/space_image/SConscript6
-rw-r--r--source/blender/editors/space_image/image_buttons.c563
-rw-r--r--source/blender/editors/space_image/image_draw.c93
-rw-r--r--source/blender/editors/space_image/image_edit.c46
-rw-r--r--source/blender/editors/space_image/image_intern.h6
-rw-r--r--source/blender/editors/space_image/image_ops.c798
-rw-r--r--source/blender/editors/space_image/space_image.c57
-rw-r--r--source/blender/editors/space_info/CMakeLists.txt5
-rw-r--r--source/blender/editors/space_info/SConscript6
-rw-r--r--source/blender/editors/space_info/info_draw.c5
-rw-r--r--source/blender/editors/space_info/info_ops.c24
-rw-r--r--source/blender/editors/space_info/info_stats.c35
-rw-r--r--source/blender/editors/space_info/space_info.c15
-rw-r--r--source/blender/editors/space_info/textview.c2
-rw-r--r--source/blender/editors/space_logic/CMakeLists.txt6
-rw-r--r--source/blender/editors/space_logic/SConscript7
-rw-r--r--source/blender/editors/space_logic/logic_buttons.c5
-rw-r--r--source/blender/editors/space_logic/logic_intern.h4
-rw-r--r--source/blender/editors/space_logic/logic_ops.c9
-rw-r--r--source/blender/editors/space_logic/logic_window.c233
-rw-r--r--source/blender/editors/space_logic/space_logic.c2
-rw-r--r--source/blender/editors/space_nla/CMakeLists.txt6
-rw-r--r--source/blender/editors/space_nla/SConscript7
-rw-r--r--source/blender/editors/space_nla/nla_buttons.c35
-rw-r--r--source/blender/editors/space_nla/nla_channels.c71
-rw-r--r--source/blender/editors/space_nla/nla_draw.c66
-rw-r--r--source/blender/editors/space_nla/nla_edit.c83
-rw-r--r--source/blender/editors/space_nla/nla_intern.h5
-rw-r--r--source/blender/editors/space_nla/nla_ops.c16
-rw-r--r--source/blender/editors/space_nla/space_nla.c8
-rw-r--r--source/blender/editors/space_node/CMakeLists.txt4
-rw-r--r--source/blender/editors/space_node/SConscript7
-rw-r--r--source/blender/editors/space_node/drawnode.c252
-rw-r--r--source/blender/editors/space_node/node_add.c65
-rw-r--r--source/blender/editors/space_node/node_buttons.c21
-rw-r--r--source/blender/editors/space_node/node_draw.c185
-rw-r--r--source/blender/editors/space_node/node_edit.c156
-rw-r--r--source/blender/editors/space_node/node_group.c26
-rw-r--r--source/blender/editors/space_node/node_intern.h12
-rw-r--r--source/blender/editors/space_node/node_ops.c25
-rw-r--r--source/blender/editors/space_node/node_relationships.c472
-rw-r--r--source/blender/editors/space_node/node_select.c22
-rw-r--r--source/blender/editors/space_node/node_templates.c60
-rw-r--r--source/blender/editors/space_node/node_toolbar.c9
-rw-r--r--source/blender/editors/space_node/node_view.c9
-rw-r--r--source/blender/editors/space_node/space_node.c35
-rw-r--r--source/blender/editors/space_outliner/CMakeLists.txt6
-rw-r--r--source/blender/editors/space_outliner/SConscript8
-rw-r--r--source/blender/editors/space_outliner/outliner_draw.c413
-rw-r--r--source/blender/editors/space_outliner/outliner_edit.c284
-rw-r--r--source/blender/editors/space_outliner/outliner_intern.h57
-rw-r--r--source/blender/editors/space_outliner/outliner_ops.c7
-rw-r--r--source/blender/editors/space_outliner/outliner_select.c21
-rw-r--r--source/blender/editors/space_outliner/outliner_tools.c506
-rw-r--r--source/blender/editors/space_outliner/outliner_tree.c268
-rw-r--r--source/blender/editors/space_outliner/space_outliner.c57
-rw-r--r--source/blender/editors/space_script/CMakeLists.txt4
-rw-r--r--source/blender/editors/space_script/SConscript5
-rw-r--r--source/blender/editors/space_script/script_edit.c3
-rw-r--r--source/blender/editors/space_script/script_ops.c13
-rw-r--r--source/blender/editors/space_script/space_script.c2
-rw-r--r--source/blender/editors/space_sequencer/CMakeLists.txt14
-rw-r--r--source/blender/editors/space_sequencer/SConscript12
-rw-r--r--source/blender/editors/space_sequencer/sequencer_add.c214
-rw-r--r--source/blender/editors/space_sequencer/sequencer_buttons.c11
-rw-r--r--source/blender/editors/space_sequencer/sequencer_draw.c706
-rw-r--r--source/blender/editors/space_sequencer/sequencer_edit.c925
-rw-r--r--source/blender/editors/space_sequencer/sequencer_intern.h33
-rw-r--r--source/blender/editors/space_sequencer/sequencer_modifier.c67
-rw-r--r--source/blender/editors/space_sequencer/sequencer_ops.c11
-rw-r--r--source/blender/editors/space_sequencer/sequencer_preview.c172
-rw-r--r--source/blender/editors/space_sequencer/sequencer_scopes.c64
-rw-r--r--source/blender/editors/space_sequencer/sequencer_select.c224
-rw-r--r--source/blender/editors/space_sequencer/sequencer_view.c9
-rw-r--r--source/blender/editors/space_sequencer/space_sequencer.c46
-rw-r--r--source/blender/editors/space_text/CMakeLists.txt5
-rw-r--r--source/blender/editors/space_text/SConscript8
-rw-r--r--source/blender/editors/space_text/space_text.c6
-rw-r--r--source/blender/editors/space_text/text_autocomplete.c10
-rw-r--r--source/blender/editors/space_text/text_draw.c128
-rw-r--r--source/blender/editors/space_text/text_header.c33
-rw-r--r--source/blender/editors/space_text/text_intern.h6
-rw-r--r--source/blender/editors/space_text/text_ops.c199
-rw-r--r--source/blender/editors/space_time/CMakeLists.txt4
-rw-r--r--source/blender/editors/space_time/SConscript5
-rw-r--r--source/blender/editors/space_time/space_time.c37
-rw-r--r--source/blender/editors/space_time/time_intern.h1
-rw-r--r--source/blender/editors/space_userpref/space_userpref.c4
-rw-r--r--source/blender/editors/space_userpref/userpref_ops.c1
-rw-r--r--source/blender/editors/space_view3d/CMakeLists.txt10
-rw-r--r--source/blender/editors/space_view3d/SConscript12
-rw-r--r--source/blender/editors/space_view3d/drawanimviz.c2
-rw-r--r--source/blender/editors/space_view3d/drawarmature.c23
-rw-r--r--source/blender/editors/space_view3d/drawmesh.c401
-rw-r--r--source/blender/editors/space_view3d/drawobject.c1106
-rw-r--r--source/blender/editors/space_view3d/drawsimdebug.c166
-rw-r--r--source/blender/editors/space_view3d/drawvolume.c115
-rw-r--r--source/blender/editors/space_view3d/space_view3d.c137
-rw-r--r--source/blender/editors/space_view3d/view3d_buttons.c582
-rw-r--r--source/blender/editors/space_view3d/view3d_camera_control.c6
-rw-r--r--source/blender/editors/space_view3d/view3d_draw.c1195
-rw-r--r--source/blender/editors/space_view3d/view3d_edit.c712
-rw-r--r--source/blender/editors/space_view3d/view3d_fly.c64
-rw-r--r--source/blender/editors/space_view3d/view3d_header.c27
-rw-r--r--source/blender/editors/space_view3d/view3d_intern.h16
-rw-r--r--source/blender/editors/space_view3d/view3d_ops.c20
-rw-r--r--source/blender/editors/space_view3d/view3d_project.c10
-rw-r--r--source/blender/editors/space_view3d/view3d_ruler.c43
-rw-r--r--source/blender/editors/space_view3d/view3d_select.c91
-rw-r--r--source/blender/editors/space_view3d/view3d_snap.c224
-rw-r--r--source/blender/editors/space_view3d/view3d_toolbar.c34
-rw-r--r--source/blender/editors/space_view3d/view3d_view.c291
-rw-r--r--source/blender/editors/space_view3d/view3d_walk.c164
-rw-r--r--source/blender/editors/transform/CMakeLists.txt8
-rw-r--r--source/blender/editors/transform/SConscript10
-rw-r--r--source/blender/editors/transform/transform.c2300
-rw-r--r--source/blender/editors/transform/transform.h92
-rw-r--r--source/blender/editors/transform/transform_constraints.c74
-rw-r--r--source/blender/editors/transform/transform_conversions.c1435
-rw-r--r--source/blender/editors/transform/transform_generics.c368
-rw-r--r--source/blender/editors/transform/transform_manipulator.c87
-rw-r--r--source/blender/editors/transform/transform_ops.c109
-rw-r--r--source/blender/editors/transform/transform_orientations.c80
-rw-r--r--source/blender/editors/transform/transform_snap.c469
-rw-r--r--source/blender/editors/util/CMakeLists.txt8
-rw-r--r--source/blender/editors/util/SConscript10
-rw-r--r--source/blender/editors/util/ed_transverts.c10
-rw-r--r--source/blender/editors/util/ed_util.c60
-rw-r--r--source/blender/editors/util/editmode_undo.c19
-rw-r--r--source/blender/editors/util/numinput.c17
-rw-r--r--source/blender/editors/util/undo.c39
-rw-r--r--source/blender/editors/util/util_intern.h12
-rw-r--r--source/blender/editors/uvedit/CMakeLists.txt6
-rw-r--r--source/blender/editors/uvedit/SConscript6
-rw-r--r--source/blender/editors/uvedit/uvedit_buttons.c31
-rw-r--r--source/blender/editors/uvedit/uvedit_draw.c39
-rw-r--r--source/blender/editors/uvedit/uvedit_intern.h5
-rw-r--r--source/blender/editors/uvedit/uvedit_ops.c198
-rw-r--r--source/blender/editors/uvedit/uvedit_parametrizer.c22
-rw-r--r--source/blender/editors/uvedit/uvedit_smart_stitch.c32
-rw-r--r--source/blender/editors/uvedit/uvedit_unwrap_ops.c98
-rw-r--r--source/blender/freestyle/CMakeLists.txt19
-rw-r--r--source/blender/freestyle/FRS_freestyle.h6
-rw-r--r--source/blender/freestyle/intern/application/AppConfig.cpp4
-rw-r--r--source/blender/freestyle/intern/application/AppView.cpp2
-rw-r--r--source/blender/freestyle/intern/application/AppView.h4
-rw-r--r--source/blender/freestyle/intern/application/Controller.cpp158
-rw-r--r--source/blender/freestyle/intern/application/Controller.h54
-rw-r--r--source/blender/freestyle/intern/blender_interface/BlenderFileLoader.cpp29
-rw-r--r--source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp526
-rw-r--r--source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.h21
-rw-r--r--source/blender/freestyle/intern/blender_interface/BlenderStyleModule.h30
-rw-r--r--source/blender/freestyle/intern/blender_interface/FRS_freestyle.cpp83
-rw-r--r--source/blender/freestyle/intern/geometry/GeomCleaner.cpp48
-rw-r--r--source/blender/freestyle/intern/geometry/GeomCleaner.h26
-rw-r--r--source/blender/freestyle/intern/geometry/GeomUtils.cpp2
-rw-r--r--source/blender/freestyle/intern/geometry/GeomUtils.h2
-rw-r--r--source/blender/freestyle/intern/geometry/Grid.h6
-rw-r--r--source/blender/freestyle/intern/image/Image.h2
-rw-r--r--source/blender/freestyle/intern/image/ImagePyramid.cpp2
-rw-r--r--source/blender/freestyle/intern/python/BPy_ContextFunctions.cpp27
-rw-r--r--source/blender/freestyle/intern/python/BPy_Convert.cpp11
-rw-r--r--source/blender/freestyle/intern/python/BPy_Convert.h1
-rw-r--r--source/blender/freestyle/intern/python/BPy_Freestyle.cpp51
-rw-r--r--source/blender/freestyle/intern/python/BPy_FrsMaterial.cpp57
-rw-r--r--source/blender/freestyle/intern/python/BPy_FrsNoise.cpp32
-rw-r--r--source/blender/freestyle/intern/python/BPy_FrsNoise.h2
-rw-r--r--source/blender/freestyle/intern/python/BPy_IntegrationType.cpp2
-rw-r--r--source/blender/freestyle/intern/python/BPy_Operators.cpp66
-rw-r--r--source/blender/freestyle/intern/python/BPy_SShape.cpp14
-rw-r--r--source/blender/freestyle/intern/python/BPy_StrokeShader.cpp36
-rw-r--r--source/blender/freestyle/intern/python/BPy_UnaryFunction0D.cpp2
-rw-r--r--source/blender/freestyle/intern/python/BPy_UnaryFunction1D.cpp2
-rw-r--r--source/blender/freestyle/intern/python/BPy_ViewShape.cpp29
-rw-r--r--source/blender/freestyle/intern/python/Director.cpp6
-rw-r--r--source/blender/freestyle/intern/python/Interface0D/BPy_CurvePoint.cpp9
-rw-r--r--source/blender/freestyle/intern/python/Interface0D/BPy_SVertex.cpp32
-rw-r--r--source/blender/freestyle/intern/python/Interface0D/BPy_ViewVertex.cpp4
-rw-r--r--source/blender/freestyle/intern/python/Interface0D/CurvePoint/BPy_StrokeVertex.cpp8
-rw-r--r--source/blender/freestyle/intern/python/Interface1D/BPy_FEdge.cpp2
-rw-r--r--source/blender/freestyle/intern/python/Interface1D/FEdge/BPy_FEdgeSmooth.cpp8
-rw-r--r--source/blender/freestyle/intern/python/Iterator/BPy_AdjacencyIterator.cpp2
-rw-r--r--source/blender/freestyle/intern/python/Iterator/BPy_Interface0DIterator.cpp12
-rw-r--r--source/blender/freestyle/intern/python/Iterator/BPy_StrokeVertexIterator.cpp38
-rw-r--r--source/blender/freestyle/intern/python/StrokeShader/BPy_BlenderTextureShader.h1
-rw-r--r--source/blender/freestyle/intern/python/StrokeShader/BPy_ColorVariationPatternShader.cpp122
-rw-r--r--source/blender/freestyle/intern/python/StrokeShader/BPy_ColorVariationPatternShader.h54
-rw-r--r--source/blender/freestyle/intern/python/StrokeShader/BPy_StrokeTextureShader.cpp143
-rw-r--r--source/blender/freestyle/intern/python/StrokeShader/BPy_StrokeTextureShader.h53
-rw-r--r--source/blender/freestyle/intern/python/StrokeShader/BPy_TextureAssignerShader.cpp130
-rw-r--r--source/blender/freestyle/intern/python/StrokeShader/BPy_TextureAssignerShader.h53
-rw-r--r--source/blender/freestyle/intern/python/StrokeShader/BPy_ThicknessVariationPatternShader.cpp128
-rw-r--r--source/blender/freestyle/intern/python/StrokeShader/BPy_ThicknessVariationPatternShader.h54
-rw-r--r--source/blender/freestyle/intern/python/StrokeShader/BPy_fstreamShader.cpp114
-rw-r--r--source/blender/freestyle/intern/python/StrokeShader/BPy_fstreamShader.h53
-rw-r--r--source/blender/freestyle/intern/python/StrokeShader/BPy_streamShader.cpp110
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DVectorViewShape.cpp18
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVectorViewShape.cpp16
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetDirectionalViewMapDensityF1D.cpp2
-rw-r--r--source/blender/freestyle/intern/scene_graph/IndexedFaceSet.cpp46
-rw-r--r--source/blender/freestyle/intern/scene_graph/IndexedFaceSet.h17
-rw-r--r--source/blender/freestyle/intern/scene_graph/NodeCamera.h2
-rw-r--r--source/blender/freestyle/intern/scene_graph/NodeSceneRenderLayer.cpp35
-rw-r--r--source/blender/freestyle/intern/scene_graph/NodeSceneRenderLayer.h76
-rw-r--r--source/blender/freestyle/intern/scene_graph/Rep.h12
-rw-r--r--source/blender/freestyle/intern/scene_graph/SceneHash.cpp84
-rw-r--r--source/blender/freestyle/intern/scene_graph/SceneHash.h82
-rw-r--r--source/blender/freestyle/intern/scene_graph/ScenePrettyPrinter.cpp4
-rw-r--r--source/blender/freestyle/intern/scene_graph/SceneVisitor.h2
-rw-r--r--source/blender/freestyle/intern/stroke/AdvancedFunctions1D.h2
-rw-r--r--source/blender/freestyle/intern/stroke/AdvancedStrokeShaders.cpp73
-rw-r--r--source/blender/freestyle/intern/stroke/BasicStrokeShaders.cpp404
-rw-r--r--source/blender/freestyle/intern/stroke/BasicStrokeShaders.h302
-rw-r--r--source/blender/freestyle/intern/stroke/Canvas.cpp2
-rw-r--r--source/blender/freestyle/intern/stroke/Canvas.h6
-rw-r--r--source/blender/freestyle/intern/stroke/Chain.cpp2
-rw-r--r--source/blender/freestyle/intern/stroke/Chain.h4
-rw-r--r--source/blender/freestyle/intern/stroke/ChainingIterators.h2
-rw-r--r--source/blender/freestyle/intern/stroke/Curve.cpp2
-rw-r--r--source/blender/freestyle/intern/stroke/Curve.h8
-rw-r--r--source/blender/freestyle/intern/stroke/Operators.cpp12
-rw-r--r--source/blender/freestyle/intern/stroke/Operators.h2
-rw-r--r--source/blender/freestyle/intern/stroke/Predicates1D.h4
-rw-r--r--source/blender/freestyle/intern/stroke/Stroke.cpp29
-rw-r--r--source/blender/freestyle/intern/stroke/Stroke.h9
-rw-r--r--source/blender/freestyle/intern/stroke/StrokeRep.cpp2
-rw-r--r--source/blender/freestyle/intern/system/BaseObject.h2
-rw-r--r--source/blender/freestyle/intern/system/PythonInterpreter.h22
-rw-r--r--source/blender/freestyle/intern/system/StringUtils.h3
-rw-r--r--source/blender/freestyle/intern/view_map/ArbitraryGridDensityProvider.cpp14
-rw-r--r--source/blender/freestyle/intern/view_map/ArbitraryGridDensityProvider.h8
-rw-r--r--source/blender/freestyle/intern/view_map/AutoPtrHelper.h60
-rw-r--r--source/blender/freestyle/intern/view_map/AverageAreaGridDensityProvider.cpp12
-rw-r--r--source/blender/freestyle/intern/view_map/AverageAreaGridDensityProvider.h8
-rw-r--r--source/blender/freestyle/intern/view_map/BoxGrid.cpp8
-rw-r--r--source/blender/freestyle/intern/view_map/BoxGrid.h4
-rw-r--r--source/blender/freestyle/intern/view_map/FEdgeXDetector.cpp64
-rw-r--r--source/blender/freestyle/intern/view_map/FEdgeXDetector.h24
-rw-r--r--source/blender/freestyle/intern/view_map/GridDensityProvider.h9
-rw-r--r--source/blender/freestyle/intern/view_map/HeuristicGridDensityProviderFactory.cpp32
-rw-r--r--source/blender/freestyle/intern/view_map/HeuristicGridDensityProviderFactory.h8
-rw-r--r--source/blender/freestyle/intern/view_map/Interface1D.cpp4
-rw-r--r--source/blender/freestyle/intern/view_map/Pow23GridDensityProvider.cpp12
-rw-r--r--source/blender/freestyle/intern/view_map/Pow23GridDensityProvider.h8
-rw-r--r--source/blender/freestyle/intern/view_map/Silhouette.h53
-rw-r--r--source/blender/freestyle/intern/view_map/SphericalGrid.cpp8
-rw-r--r--source/blender/freestyle/intern/view_map/SteerableViewMap.cpp2
-rw-r--r--source/blender/freestyle/intern/view_map/ViewEdgeXBuilder.cpp14
-rw-r--r--source/blender/freestyle/intern/view_map/ViewMap.cpp28
-rw-r--r--source/blender/freestyle/intern/view_map/ViewMap.h9
-rw-r--r--source/blender/freestyle/intern/view_map/ViewMapBuilder.cpp35
-rw-r--r--source/blender/freestyle/intern/view_map/ViewMapBuilder.h2
-rw-r--r--source/blender/freestyle/intern/winged_edge/Curvature.cpp7
-rw-r--r--source/blender/freestyle/intern/winged_edge/Nature.h1
-rw-r--r--source/blender/freestyle/intern/winged_edge/WEdge.cpp36
-rw-r--r--source/blender/freestyle/intern/winged_edge/WEdge.h97
-rw-r--r--source/blender/freestyle/intern/winged_edge/WXEdge.cpp52
-rw-r--r--source/blender/freestyle/intern/winged_edge/WXEdge.h97
-rw-r--r--source/blender/freestyle/intern/winged_edge/WXEdgeBuilder.cpp4
-rw-r--r--source/blender/freestyle/intern/winged_edge/WXEdgeBuilder.h2
-rw-r--r--source/blender/freestyle/intern/winged_edge/WingedEdgeBuilder.cpp94
-rw-r--r--source/blender/freestyle/intern/winged_edge/WingedEdgeBuilder.h19
-rw-r--r--source/blender/gpu/CMakeLists.txt48
-rw-r--r--source/blender/gpu/GPU_buffers.h125
-rw-r--r--source/blender/gpu/GPU_compositing.h99
-rw-r--r--source/blender/gpu/GPU_debug.h71
-rw-r--r--source/blender/gpu/GPU_draw.h42
-rw-r--r--source/blender/gpu/GPU_extensions.h144
-rw-r--r--source/blender/gpu/GPU_glew.h37
-rw-r--r--source/blender/gpu/GPU_init_exit.h46
-rw-r--r--source/blender/gpu/GPU_material.h197
-rw-r--r--source/blender/gpu/GPU_select.h4
-rw-r--r--source/blender/gpu/GPU_simple_shader.h8
-rw-r--r--source/blender/gpu/SConscript23
-rw-r--r--source/blender/gpu/intern/gpu_buffers.c1886
-rw-r--r--source/blender/gpu/intern/gpu_codegen.c670
-rw-r--r--source/blender/gpu/intern/gpu_codegen.h118
-rw-r--r--source/blender/gpu/intern/gpu_compositing.c1289
-rw-r--r--source/blender/gpu/intern/gpu_debug.c724
-rw-r--r--source/blender/gpu/intern/gpu_draw.c1225
-rw-r--r--source/blender/gpu/intern/gpu_extensions.c1240
-rw-r--r--source/blender/gpu/intern/gpu_init_exit.c79
-rw-r--r--source/blender/gpu/intern/gpu_material.c884
-rw-r--r--source/blender/gpu/intern/gpu_private.h36
-rw-r--r--source/blender/gpu/intern/gpu_select.c22
-rw-r--r--source/blender/gpu/intern/gpu_simple_shader.c9
-rw-r--r--source/blender/gpu/shaders/gpu_program_smoke_color_frag.glsl32
-rw-r--r--source/blender/gpu/shaders/gpu_program_smoke_frag.glsl27
-rw-r--r--source/blender/gpu/shaders/gpu_shader_fx_depth_resolve.glsl14
-rw-r--r--source/blender/gpu/shaders/gpu_shader_fx_dof_frag.glsl208
-rw-r--r--source/blender/gpu/shaders/gpu_shader_fx_dof_hq_frag.glsl166
-rw-r--r--source/blender/gpu/shaders/gpu_shader_fx_dof_hq_geo.glsl50
-rw-r--r--source/blender/gpu/shaders/gpu_shader_fx_dof_hq_vert.glsl58
-rw-r--r--source/blender/gpu/shaders/gpu_shader_fx_dof_vert.glsl68
-rw-r--r--source/blender/gpu/shaders/gpu_shader_fx_lib.glsl39
-rw-r--r--source/blender/gpu/shaders/gpu_shader_fx_ssao_frag.glsl94
-rw-r--r--source/blender/gpu/shaders/gpu_shader_fx_vert.glsl9
-rw-r--r--source/blender/gpu/shaders/gpu_shader_geometry.glsl100
-rw-r--r--source/blender/gpu/shaders/gpu_shader_material.glsl202
-rw-r--r--source/blender/gpu/shaders/gpu_shader_sep_gaussian_blur_frag.glsl2
-rw-r--r--source/blender/gpu/shaders/gpu_shader_vertex.glsl21
-rw-r--r--source/blender/gpu/shaders/gpu_shader_vertex_world.glsl13
-rw-r--r--source/blender/ikplugin/BIK_api.h1
-rw-r--r--source/blender/ikplugin/CMakeLists.txt4
-rw-r--r--source/blender/ikplugin/intern/ikplugin_api.c7
-rw-r--r--source/blender/ikplugin/intern/ikplugin_api.h1
-rw-r--r--source/blender/ikplugin/intern/iksolver_plugin.c3
-rw-r--r--source/blender/ikplugin/intern/itasc_plugin.cpp3
-rw-r--r--source/blender/imbuf/CMakeLists.txt4
-rw-r--r--source/blender/imbuf/IMB_colormanagement.h7
-rw-r--r--source/blender/imbuf/IMB_imbuf.h80
-rw-r--r--source/blender/imbuf/IMB_imbuf_types.h162
-rw-r--r--source/blender/imbuf/IMB_thumbs.h24
-rw-r--r--source/blender/imbuf/intern/IMB_anim.h7
-rw-r--r--source/blender/imbuf/intern/IMB_filetype.h57
-rw-r--r--source/blender/imbuf/intern/IMB_metadata.h17
-rw-r--r--source/blender/imbuf/intern/allocimbuf.c58
-rw-r--r--source/blender/imbuf/intern/anim_movie.c54
-rw-r--r--source/blender/imbuf/intern/bmp.c146
-rw-r--r--source/blender/imbuf/intern/cache.c3
-rw-r--r--source/blender/imbuf/intern/cineon/cineon_dpx.c23
-rw-r--r--source/blender/imbuf/intern/cineon/cineonlib.c4
-rw-r--r--source/blender/imbuf/intern/cineon/dpxlib.c12
-rw-r--r--source/blender/imbuf/intern/cineon/logImageCore.c2
-rw-r--r--source/blender/imbuf/intern/cineon/logImageCore.h6
-rw-r--r--source/blender/imbuf/intern/colormanagement.c134
-rw-r--r--source/blender/imbuf/intern/dds/BlockDXT.h24
-rw-r--r--source/blender/imbuf/intern/dds/ColorBlock.h3
-rw-r--r--source/blender/imbuf/intern/dds/DirectDrawSurface.cpp6
-rw-r--r--source/blender/imbuf/intern/dds/DirectDrawSurface.h12
-rw-r--r--source/blender/imbuf/intern/dds/Stream.cpp15
-rw-r--r--source/blender/imbuf/intern/dds/Stream.h3
-rw-r--r--source/blender/imbuf/intern/dds/dds_api.cpp10
-rw-r--r--source/blender/imbuf/intern/dds/dds_api.h4
-rw-r--r--source/blender/imbuf/intern/divers.c101
-rw-r--r--source/blender/imbuf/intern/filetype.c44
-rw-r--r--source/blender/imbuf/intern/filter.c6
-rw-r--r--source/blender/imbuf/intern/imageprocess.c81
-rw-r--r--source/blender/imbuf/intern/indexer.c108
-rw-r--r--source/blender/imbuf/intern/iris.c127
-rw-r--r--source/blender/imbuf/intern/jp2.c54
-rw-r--r--source/blender/imbuf/intern/jpeg.c91
-rw-r--r--source/blender/imbuf/intern/metadata.c112
-rw-r--r--source/blender/imbuf/intern/moviecache.c60
-rw-r--r--source/blender/imbuf/intern/oiio/CMakeLists.txt1
-rw-r--r--source/blender/imbuf/intern/oiio/openimageio_api.cpp4
-rw-r--r--source/blender/imbuf/intern/openexr/openexr_api.cpp1210
-rw-r--r--source/blender/imbuf/intern/openexr/openexr_api.h4
-rw-r--r--source/blender/imbuf/intern/openexr/openexr_multi.h45
-rw-r--r--source/blender/imbuf/intern/openexr/openexr_stub.cpp56
-rw-r--r--source/blender/imbuf/intern/png.c78
-rw-r--r--source/blender/imbuf/intern/radiance_hdr.c68
-rw-r--r--source/blender/imbuf/intern/readimage.c22
-rw-r--r--source/blender/imbuf/intern/rectop.c20
-rw-r--r--source/blender/imbuf/intern/rotate.c2
-rw-r--r--source/blender/imbuf/intern/scaling.c4
-rw-r--r--source/blender/imbuf/intern/stereoimbuf.c1292
-rw-r--r--source/blender/imbuf/intern/targa.c23
-rw-r--r--source/blender/imbuf/intern/thumbs.c369
-rw-r--r--source/blender/imbuf/intern/thumbs_blend.c152
-rw-r--r--source/blender/imbuf/intern/thumbs_font.c100
-rw-r--r--source/blender/imbuf/intern/tiff.c30
-rw-r--r--source/blender/imbuf/intern/util.c26
-rw-r--r--source/blender/imbuf/intern/writeimage.c42
-rw-r--r--source/blender/makesdna/DNA_ID.h199
-rw-r--r--source/blender/makesdna/DNA_action_types.h33
-rw-r--r--source/blender/makesdna/DNA_actuator_types.h3
-rw-r--r--source/blender/makesdna/DNA_anim_types.h20
-rw-r--r--source/blender/makesdna/DNA_armature_types.h12
-rw-r--r--source/blender/makesdna/DNA_brush_types.h55
-rw-r--r--source/blender/makesdna/DNA_camera_types.h41
-rw-r--r--source/blender/makesdna/DNA_cloth_types.h19
-rw-r--r--source/blender/makesdna/DNA_color_types.h1
-rw-r--r--source/blender/makesdna/DNA_constraint_types.h36
-rw-r--r--source/blender/makesdna/DNA_curve_types.h214
-rw-r--r--source/blender/makesdna/DNA_customdata_types.h21
-rw-r--r--source/blender/makesdna/DNA_documentation.h18
-rw-r--r--source/blender/makesdna/DNA_dynamicpaint_types.h167
-rw-r--r--source/blender/makesdna/DNA_fileglobal_types.h4
-rw-r--r--source/blender/makesdna/DNA_freestyle_types.h95
-rw-r--r--source/blender/makesdna/DNA_gpencil_types.h110
-rw-r--r--source/blender/makesdna/DNA_gpu_types.h68
-rw-r--r--source/blender/makesdna/DNA_group_types.h4
-rw-r--r--source/blender/makesdna/DNA_image_types.h67
-rw-r--r--source/blender/makesdna/DNA_key_types.h6
-rw-r--r--source/blender/makesdna/DNA_lamp_types.h37
-rw-r--r--source/blender/makesdna/DNA_linestyle_types.h135
-rw-r--r--source/blender/makesdna/DNA_material_types.h2
-rw-r--r--source/blender/makesdna/DNA_mesh_types.h105
-rw-r--r--source/blender/makesdna/DNA_meshdata_types.h113
-rw-r--r--source/blender/makesdna/DNA_modifier_types.h174
-rw-r--r--source/blender/makesdna/DNA_node_types.h96
-rw-r--r--source/blender/makesdna/DNA_object_force.h2
-rw-r--r--source/blender/makesdna/DNA_object_types.h35
-rw-r--r--source/blender/makesdna/DNA_outliner_types.h50
-rw-r--r--source/blender/makesdna/DNA_packedFile_types.h3
-rw-r--r--source/blender/makesdna/DNA_particle_types.h119
-rw-r--r--source/blender/makesdna/DNA_scene_types.h274
-rw-r--r--source/blender/makesdna/DNA_screen_types.h65
-rw-r--r--source/blender/makesdna/DNA_sensor_types.h2
-rw-r--r--source/blender/makesdna/DNA_sequence_types.h91
-rw-r--r--source/blender/makesdna/DNA_smoke_types.h6
-rw-r--r--source/blender/makesdna/DNA_sound_types.h16
-rw-r--r--source/blender/makesdna/DNA_space_types.h267
-rw-r--r--source/blender/makesdna/DNA_texture_types.h22
-rw-r--r--source/blender/makesdna/DNA_tracking_types.h2
-rw-r--r--source/blender/makesdna/DNA_userdef_types.h68
-rw-r--r--source/blender/makesdna/DNA_view2d_types.h2
-rw-r--r--source/blender/makesdna/DNA_view3d_types.h91
-rw-r--r--source/blender/makesdna/DNA_windowmanager_types.h64
-rw-r--r--source/blender/makesdna/DNA_world_types.h7
-rw-r--r--source/blender/makesdna/intern/CMakeLists.txt5
-rw-r--r--source/blender/makesdna/intern/dna_genfile.c24
-rw-r--r--source/blender/makesdna/intern/makesdna.c8
-rw-r--r--source/blender/makesrna/RNA_access.h23
-rw-r--r--source/blender/makesrna/RNA_enum_types.h18
-rw-r--r--source/blender/makesrna/RNA_types.h8
-rw-r--r--source/blender/makesrna/SConscript26
-rw-r--r--source/blender/makesrna/intern/CMakeLists.txt65
-rw-r--r--source/blender/makesrna/intern/SConscript23
-rw-r--r--source/blender/makesrna/intern/makesrna.c129
-rw-r--r--source/blender/makesrna/intern/rna_ID.c430
-rw-r--r--source/blender/makesrna/intern/rna_access.c188
-rw-r--r--source/blender/makesrna/intern/rna_action.c57
-rw-r--r--source/blender/makesrna/intern/rna_actuator.c41
-rw-r--r--source/blender/makesrna/intern/rna_animation.c70
-rw-r--r--source/blender/makesrna/intern/rna_animviz.c10
-rw-r--r--source/blender/makesrna/intern/rna_armature.c10
-rw-r--r--source/blender/makesrna/intern/rna_boid.c4
-rw-r--r--source/blender/makesrna/intern/rna_brush.c137
-rw-r--r--source/blender/makesrna/intern/rna_camera.c107
-rw-r--r--source/blender/makesrna/intern/rna_cloth.c113
-rw-r--r--source/blender/makesrna/intern/rna_color.c25
-rw-r--r--source/blender/makesrna/intern/rna_constraint.c75
-rw-r--r--source/blender/makesrna/intern/rna_controller.c15
-rw-r--r--source/blender/makesrna/intern/rna_curve.c22
-rw-r--r--source/blender/makesrna/intern/rna_define.c73
-rw-r--r--source/blender/makesrna/intern/rna_depsgraph.c112
-rw-r--r--source/blender/makesrna/intern/rna_dynamicpaint.c2
-rw-r--r--source/blender/makesrna/intern/rna_fcurve.c6
-rw-r--r--source/blender/makesrna/intern/rna_fcurve_api.c108
-rw-r--r--source/blender/makesrna/intern/rna_fluidsim.c8
-rw-r--r--source/blender/makesrna/intern/rna_gpencil.c298
-rw-r--r--source/blender/makesrna/intern/rna_image.c228
-rw-r--r--source/blender/makesrna/intern/rna_image_api.c77
-rw-r--r--source/blender/makesrna/intern/rna_internal.h11
-rw-r--r--source/blender/makesrna/intern/rna_internal_types.h2
-rw-r--r--source/blender/makesrna/intern/rna_key.c14
-rw-r--r--source/blender/makesrna/intern/rna_lamp.c28
-rw-r--r--source/blender/makesrna/intern/rna_linestyle.c277
-rw-r--r--source/blender/makesrna/intern/rna_main.c7
-rw-r--r--source/blender/makesrna/intern/rna_main_api.c175
-rw-r--r--source/blender/makesrna/intern/rna_mask.c13
-rw-r--r--source/blender/makesrna/intern/rna_material.c12
-rw-r--r--source/blender/makesrna/intern/rna_mesh.c680
-rw-r--r--source/blender/makesrna/intern/rna_mesh_api.c157
-rw-r--r--source/blender/makesrna/intern/rna_mesh_utils.h4
-rw-r--r--source/blender/makesrna/intern/rna_modifier.c996
-rw-r--r--source/blender/makesrna/intern/rna_movieclip.c4
-rw-r--r--source/blender/makesrna/intern/rna_nla.c62
-rw-r--r--source/blender/makesrna/intern/rna_nodetree.c462
-rw-r--r--source/blender/makesrna/intern/rna_object.c135
-rw-r--r--source/blender/makesrna/intern/rna_object_api.c125
-rw-r--r--source/blender/makesrna/intern/rna_object_force.c6
-rw-r--r--source/blender/makesrna/intern/rna_palette.c181
-rw-r--r--source/blender/makesrna/intern/rna_particle.c153
-rw-r--r--source/blender/makesrna/intern/rna_pose.c39
-rw-r--r--source/blender/makesrna/intern/rna_property.c11
-rw-r--r--source/blender/makesrna/intern/rna_render.c167
-rw-r--r--source/blender/makesrna/intern/rna_rigidbody.c16
-rw-r--r--source/blender/makesrna/intern/rna_rna.c49
-rw-r--r--source/blender/makesrna/intern/rna_scene.c995
-rw-r--r--source/blender/makesrna/intern/rna_scene_api.c50
-rw-r--r--source/blender/makesrna/intern/rna_screen.c13
-rw-r--r--source/blender/makesrna/intern/rna_sculpt_paint.c179
-rw-r--r--source/blender/makesrna/intern/rna_sensor.c32
-rw-r--r--source/blender/makesrna/intern/rna_sequencer.c223
-rw-r--r--source/blender/makesrna/intern/rna_sequencer_api.c50
-rw-r--r--source/blender/makesrna/intern/rna_smoke.c71
-rw-r--r--source/blender/makesrna/intern/rna_sound.c13
-rw-r--r--source/blender/makesrna/intern/rna_sound_api.c73
-rw-r--r--source/blender/makesrna/intern/rna_space.c951
-rw-r--r--source/blender/makesrna/intern/rna_space_api.c31
-rw-r--r--source/blender/makesrna/intern/rna_speaker.c8
-rw-r--r--source/blender/makesrna/intern/rna_test.c8
-rw-r--r--source/blender/makesrna/intern/rna_text.c4
-rw-r--r--source/blender/makesrna/intern/rna_texture.c34
-rw-r--r--source/blender/makesrna/intern/rna_texture_api.c4
-rw-r--r--source/blender/makesrna/intern/rna_tracking.c2
-rw-r--r--source/blender/makesrna/intern/rna_ui.c19
-rw-r--r--source/blender/makesrna/intern/rna_ui_api.c69
-rw-r--r--source/blender/makesrna/intern/rna_userdef.c373
-rw-r--r--source/blender/makesrna/intern/rna_vfont.c2
-rw-r--r--source/blender/makesrna/intern/rna_vfont_api.c73
-rw-r--r--source/blender/makesrna/intern/rna_wm.c376
-rw-r--r--source/blender/makesrna/intern/rna_wm_api.c12
-rw-r--r--source/blender/makesrna/intern/rna_world.c15
-rw-r--r--source/blender/modifiers/CMakeLists.txt9
-rw-r--r--source/blender/modifiers/MOD_modifiertypes.h3
-rw-r--r--source/blender/modifiers/SConscript10
-rw-r--r--source/blender/modifiers/intern/MOD_armature.c14
-rw-r--r--source/blender/modifiers/intern/MOD_array.c93
-rw-r--r--source/blender/modifiers/intern/MOD_bevel.c11
-rw-r--r--source/blender/modifiers/intern/MOD_boolean.c21
-rw-r--r--source/blender/modifiers/intern/MOD_boolean_util.c25
-rw-r--r--source/blender/modifiers/intern/MOD_boolean_util.h2
-rw-r--r--source/blender/modifiers/intern/MOD_build.c62
-rw-r--r--source/blender/modifiers/intern/MOD_cast.c14
-rw-r--r--source/blender/modifiers/intern/MOD_cloth.c39
-rw-r--r--source/blender/modifiers/intern/MOD_collision.c106
-rw-r--r--source/blender/modifiers/intern/MOD_correctivesmooth.c769
-rw-r--r--source/blender/modifiers/intern/MOD_curve.c24
-rw-r--r--source/blender/modifiers/intern/MOD_datatransfer.c265
-rw-r--r--source/blender/modifiers/intern/MOD_decimate.c25
-rw-r--r--source/blender/modifiers/intern/MOD_displace.c57
-rw-r--r--source/blender/modifiers/intern/MOD_dynamicpaint.c34
-rw-r--r--source/blender/modifiers/intern/MOD_edgesplit.c1
-rw-r--r--source/blender/modifiers/intern/MOD_explode.c8
-rw-r--r--source/blender/modifiers/intern/MOD_fluidsim.c35
-rw-r--r--source/blender/modifiers/intern/MOD_hook.c243
-rw-r--r--source/blender/modifiers/intern/MOD_laplaciandeform.c189
-rw-r--r--source/blender/modifiers/intern/MOD_laplaciansmooth.c373
-rw-r--r--source/blender/modifiers/intern/MOD_lattice.c17
-rw-r--r--source/blender/modifiers/intern/MOD_mask.c180
-rw-r--r--source/blender/modifiers/intern/MOD_meshcache.c3
-rw-r--r--source/blender/modifiers/intern/MOD_meshcache_pc2.c3
-rw-r--r--source/blender/modifiers/intern/MOD_meshcache_util.h2
-rw-r--r--source/blender/modifiers/intern/MOD_meshdeform.c195
-rw-r--r--source/blender/modifiers/intern/MOD_mirror.c24
-rw-r--r--source/blender/modifiers/intern/MOD_multires.c4
-rw-r--r--source/blender/modifiers/intern/MOD_none.c1
-rw-r--r--source/blender/modifiers/intern/MOD_normal_edit.c529
-rw-r--r--source/blender/modifiers/intern/MOD_ocean.c25
-rw-r--r--source/blender/modifiers/intern/MOD_particleinstance.c67
-rw-r--r--source/blender/modifiers/intern/MOD_particlesystem.c33
-rw-r--r--source/blender/modifiers/intern/MOD_remesh.c11
-rw-r--r--source/blender/modifiers/intern/MOD_screw.c28
-rw-r--r--source/blender/modifiers/intern/MOD_shapekey.c8
-rw-r--r--source/blender/modifiers/intern/MOD_shrinkwrap.c20
-rw-r--r--source/blender/modifiers/intern/MOD_simpledeform.c16
-rw-r--r--source/blender/modifiers/intern/MOD_skin.c75
-rw-r--r--source/blender/modifiers/intern/MOD_smoke.c180
-rw-r--r--source/blender/modifiers/intern/MOD_smooth.c1
-rw-r--r--source/blender/modifiers/intern/MOD_softbody.c1
-rw-r--r--source/blender/modifiers/intern/MOD_solidify.c47
-rw-r--r--source/blender/modifiers/intern/MOD_subsurf.c62
-rw-r--r--source/blender/modifiers/intern/MOD_surface.c5
-rw-r--r--source/blender/modifiers/intern/MOD_triangulate.c2
-rw-r--r--source/blender/modifiers/intern/MOD_util.c12
-rw-r--r--source/blender/modifiers/intern/MOD_util.h6
-rw-r--r--source/blender/modifiers/intern/MOD_uvproject.c22
-rw-r--r--source/blender/modifiers/intern/MOD_uvwarp.c26
-rw-r--r--source/blender/modifiers/intern/MOD_warp.c76
-rw-r--r--source/blender/modifiers/intern/MOD_wave.c17
-rw-r--r--source/blender/modifiers/intern/MOD_weightvg_util.c7
-rw-r--r--source/blender/modifiers/intern/MOD_weightvgedit.c24
-rw-r--r--source/blender/modifiers/intern/MOD_weightvgmix.c37
-rw-r--r--source/blender/modifiers/intern/MOD_weightvgproximity.c38
-rw-r--r--source/blender/modifiers/intern/MOD_wireframe.c18
-rw-r--r--source/blender/nodes/CMakeLists.txt11
-rw-r--r--source/blender/nodes/NOD_composite.h1
-rw-r--r--source/blender/nodes/NOD_shader.h1
-rw-r--r--source/blender/nodes/NOD_socket.h1
-rw-r--r--source/blender/nodes/NOD_static_types.h6
-rw-r--r--source/blender/nodes/SConscript12
-rw-r--r--source/blender/nodes/composite/node_composite_tree.c17
-rw-r--r--source/blender/nodes/composite/node_composite_util.c2
-rw-r--r--source/blender/nodes/composite/node_composite_util.h2
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_boxmask.c4
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_colorbalance.c3
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_common.c1
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_composite.c4
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_defocus.c4
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_image.c42
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_keying.c6
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_keyingscreen.c6
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_mapValue.c2
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_mask.c4
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_movieclip.c3
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_moviedistortion.c2
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_outputFile.c9
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_planetrackdeform.c3
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_stabilize2d.c3
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_switchview.c153
-rw-r--r--source/blender/nodes/intern/node_common.c27
-rw-r--r--source/blender/nodes/intern/node_socket.c3
-rw-r--r--source/blender/nodes/intern/node_util.c2
-rw-r--r--source/blender/nodes/shader/node_shader_tree.c12
-rw-r--r--source/blender/nodes/shader/node_shader_util.h2
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_background.c6
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_bsdf_anisotropic.c4
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_bump.c8
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_gamma.c15
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_geom.c6
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_geometry.c1
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_lamp.c6
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_mapping.c2
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_material.c8
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_math.c97
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_mixRgb.c12
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_normal.c10
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_object_info.c8
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_output_world.c13
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_particle_info.c21
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_script.c2
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_sepcombXYZ.c6
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_subsurface_scattering.c8
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_tex_brick.c4
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_tex_checker.c4
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_tex_coord.c18
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_tex_environment.c25
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_tex_gradient.c4
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_tex_image.c6
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_tex_magic.c4
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_tex_musgrave.c4
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_tex_noise.c4
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_tex_pointdensity.c76
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_tex_sky.c4
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_tex_voronoi.c4
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_tex_wave.c4
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_texture.c3
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_uvAlongStroke.c2
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_valToRgb.c3
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_vectMath.c7
-rw-r--r--source/blender/nodes/texture/node_texture_tree.c7
-rw-r--r--source/blender/nodes/texture/node_texture_util.h4
-rw-r--r--source/blender/nodes/texture/nodes/node_texture_math.c42
-rw-r--r--source/blender/nodes/texture/nodes/node_texture_proc.c2
-rw-r--r--source/blender/nodes/texture/nodes/node_texture_valToRgb.c3
-rw-r--r--source/blender/physics/BPH_mass_spring.h67
-rw-r--r--source/blender/physics/CMakeLists.txt53
-rw-r--r--source/blender/physics/SConscript44
-rw-r--r--source/blender/physics/intern/BPH_mass_spring.cpp1117
-rw-r--r--source/blender/physics/intern/ConstrainedConjugateGradient.h294
-rw-r--r--source/blender/physics/intern/eigen_utils.h230
-rw-r--r--source/blender/physics/intern/hair_volume.cpp1154
-rw-r--r--source/blender/physics/intern/implicit.h184
-rw-r--r--source/blender/physics/intern/implicit_blender.c2019
-rw-r--r--source/blender/physics/intern/implicit_eigen.cpp1346
-rw-r--r--source/blender/python/BPY_extern.h1
-rw-r--r--source/blender/python/SConscript18
-rw-r--r--source/blender/python/bmesh/bmesh_py_api.c15
-rw-r--r--source/blender/python/bmesh/bmesh_py_geometry.c4
-rw-r--r--source/blender/python/bmesh/bmesh_py_ops.c5
-rw-r--r--source/blender/python/bmesh/bmesh_py_ops_call.c45
-rw-r--r--source/blender/python/bmesh/bmesh_py_types.c465
-rw-r--r--source/blender/python/bmesh/bmesh_py_types.h35
-rw-r--r--source/blender/python/bmesh/bmesh_py_types_customdata.c44
-rw-r--r--source/blender/python/bmesh/bmesh_py_types_meshdata.c25
-rw-r--r--source/blender/python/bmesh/bmesh_py_types_select.c16
-rw-r--r--source/blender/python/bmesh/bmesh_py_utils.c65
-rw-r--r--source/blender/python/generic/CMakeLists.txt7
-rw-r--r--source/blender/python/generic/bgl.c4386
-rw-r--r--source/blender/python/generic/bgl.h304
-rw-r--r--source/blender/python/generic/blf_py_api.c33
-rw-r--r--source/blender/python/generic/bpy_internal_import.c6
-rw-r--r--source/blender/python/generic/idprop_py_api.c66
-rw-r--r--source/blender/python/generic/py_capi_utils.c113
-rw-r--r--source/blender/python/generic/py_capi_utils.h12
-rw-r--r--source/blender/python/generic/python_utildefines.h60
-rw-r--r--source/blender/python/intern/CMakeLists.txt22
-rw-r--r--source/blender/python/intern/bpy.c44
-rw-r--r--source/blender/python/intern/bpy_app.c60
-rw-r--r--source/blender/python/intern/bpy_app_build_options.c7
-rw-r--r--source/blender/python/intern/bpy_app_handlers.c47
-rw-r--r--source/blender/python/intern/bpy_app_sdl.c136
-rw-r--r--source/blender/python/intern/bpy_app_sdl.h (renamed from source/blender/compositor/intern/COM_ChannelInfo.cpp)29
-rw-r--r--source/blender/python/intern/bpy_app_translations.c103
-rw-r--r--source/blender/python/intern/bpy_app_translations.h1
-rw-r--r--source/blender/python/intern/bpy_driver.c2
-rw-r--r--source/blender/python/intern/bpy_interface.c33
-rw-r--r--source/blender/python/intern/bpy_library.c29
-rw-r--r--source/blender/python/intern/bpy_operator.c50
-rw-r--r--source/blender/python/intern/bpy_props.c126
-rw-r--r--source/blender/python/intern/bpy_rna.c187
-rw-r--r--source/blender/python/intern/bpy_rna_anim.c7
-rw-r--r--source/blender/python/intern/bpy_util.c62
-rw-r--r--source/blender/python/intern/bpy_util.h3
-rw-r--r--source/blender/python/intern/bpy_utils_previews.c188
-rw-r--r--source/blender/python/intern/bpy_utils_previews.h32
-rw-r--r--source/blender/python/intern/bpy_utils_units.c23
-rw-r--r--source/blender/python/intern/gpu.c59
-rw-r--r--source/blender/python/mathutils/CMakeLists.txt5
-rw-r--r--source/blender/python/mathutils/mathutils.c167
-rw-r--r--source/blender/python/mathutils/mathutils.h61
-rw-r--r--source/blender/python/mathutils/mathutils_Color.c140
-rw-r--r--source/blender/python/mathutils/mathutils_Color.h15
-rw-r--r--source/blender/python/mathutils/mathutils_Euler.c143
-rw-r--r--source/blender/python/mathutils/mathutils_Euler.h15
-rw-r--r--source/blender/python/mathutils/mathutils_Matrix.c297
-rw-r--r--source/blender/python/mathutils/mathutils_Matrix.h21
-rw-r--r--source/blender/python/mathutils/mathutils_Quaternion.c224
-rw-r--r--source/blender/python/mathutils/mathutils_Quaternion.h15
-rw-r--r--source/blender/python/mathutils/mathutils_Vector.c247
-rw-r--r--source/blender/python/mathutils/mathutils_Vector.h22
-rw-r--r--source/blender/python/mathutils/mathutils_bvhtree.c1233
-rw-r--r--source/blender/python/mathutils/mathutils_bvhtree.h36
-rw-r--r--source/blender/python/mathutils/mathutils_geometry.c845
-rw-r--r--source/blender/python/mathutils/mathutils_interpolate.c137
-rw-r--r--source/blender/python/mathutils/mathutils_interpolate.h32
-rw-r--r--source/blender/python/mathutils/mathutils_kdtree.c14
-rw-r--r--source/blender/python/mathutils/mathutils_noise.c14
-rw-r--r--source/blender/quicktime/CMakeLists.txt7
-rw-r--r--source/blender/quicktime/SConscript7
-rw-r--r--source/blender/quicktime/apple/qtkit_export.m122
-rw-r--r--source/blender/quicktime/apple/qtkit_import.m1
-rw-r--r--source/blender/quicktime/quicktime_export.h13
-rw-r--r--source/blender/render/CMakeLists.txt8
-rw-r--r--source/blender/render/SConscript8
-rw-r--r--source/blender/render/extern/include/RE_bake.h10
-rw-r--r--source/blender/render/extern/include/RE_engine.h13
-rw-r--r--source/blender/render/extern/include/RE_pipeline.h90
-rw-r--r--source/blender/render/extern/include/RE_render_ext.h16
-rw-r--r--source/blender/render/extern/include/RE_shader_ext.h11
-rw-r--r--source/blender/render/intern/include/envmap.h2
-rw-r--r--source/blender/render/intern/include/initrender.h1
-rw-r--r--source/blender/render/intern/include/occlusion.h3
-rw-r--r--source/blender/render/intern/include/pixelshading.h1
-rw-r--r--source/blender/render/intern/include/pointdensity.h4
-rw-r--r--source/blender/render/intern/include/rayintersection.h2
-rw-r--r--source/blender/render/intern/include/render_result.h23
-rw-r--r--source/blender/render/intern/include/render_types.h18
-rw-r--r--source/blender/render/intern/include/rendercore.h3
-rw-r--r--source/blender/render/intern/include/shadbuf.h4
-rw-r--r--source/blender/render/intern/include/shading.h1
-rw-r--r--source/blender/render/intern/include/sss.h1
-rw-r--r--source/blender/render/intern/include/strand.h3
-rw-r--r--source/blender/render/intern/include/texture.h9
-rw-r--r--source/blender/render/intern/include/zbuf.h1
-rw-r--r--source/blender/render/intern/raytrace/rayobject_instance.cpp2
-rw-r--r--source/blender/render/intern/raytrace/rayobject_octree.cpp3
-rw-r--r--source/blender/render/intern/source/bake.c29
-rw-r--r--source/blender/render/intern/source/bake_api.c152
-rw-r--r--source/blender/render/intern/source/convertblender.c153
-rw-r--r--source/blender/render/intern/source/envmap.c34
-rw-r--r--source/blender/render/intern/source/external_engine.c92
-rw-r--r--source/blender/render/intern/source/imagetexture.c32
-rw-r--r--source/blender/render/intern/source/initrender.c37
-rw-r--r--source/blender/render/intern/source/multires_bake.c368
-rw-r--r--source/blender/render/intern/source/occlusion.c8
-rw-r--r--source/blender/render/intern/source/pipeline.c1415
-rw-r--r--source/blender/render/intern/source/pixelblending.c1
-rw-r--r--source/blender/render/intern/source/pixelshading.c11
-rw-r--r--source/blender/render/intern/source/pointdensity.c442
-rw-r--r--source/blender/render/intern/source/rayshade.c65
-rw-r--r--source/blender/render/intern/source/render_result.c867
-rw-r--r--source/blender/render/intern/source/render_texture.c269
-rw-r--r--source/blender/render/intern/source/rendercore.c128
-rw-r--r--source/blender/render/intern/source/renderdatabase.c60
-rw-r--r--source/blender/render/intern/source/shadbuf.c1
-rw-r--r--source/blender/render/intern/source/shadeinput.c19
-rw-r--r--source/blender/render/intern/source/shadeoutput.c110
-rw-r--r--source/blender/render/intern/source/sss.c15
-rw-r--r--source/blender/render/intern/source/strand.c3
-rw-r--r--source/blender/render/intern/source/sunsky.c11
-rw-r--r--source/blender/render/intern/source/texture_ocean.c4
-rw-r--r--source/blender/render/intern/source/volume_precache.c2
-rw-r--r--source/blender/render/intern/source/volumetric.c12
-rw-r--r--source/blender/render/intern/source/voxeldata.c30
-rw-r--r--source/blender/render/intern/source/zbuf.c70
-rw-r--r--source/blender/windowmanager/CMakeLists.txt27
-rw-r--r--source/blender/windowmanager/SConscript23
-rw-r--r--source/blender/windowmanager/WM_api.h50
-rw-r--r--source/blender/windowmanager/WM_keymap.h20
-rw-r--r--source/blender/windowmanager/WM_types.h72
-rw-r--r--source/blender/windowmanager/intern/wm.c25
-rw-r--r--source/blender/windowmanager/intern/wm_cursors.c23
-rw-r--r--source/blender/windowmanager/intern/wm_dragdrop.c47
-rw-r--r--source/blender/windowmanager/intern/wm_draw.c286
-rw-r--r--source/blender/windowmanager/intern/wm_event_system.c479
-rw-r--r--source/blender/windowmanager/intern/wm_files.c496
-rw-r--r--source/blender/windowmanager/intern/wm_gesture.c2
-rw-r--r--source/blender/windowmanager/intern/wm_init_exit.c139
-rw-r--r--source/blender/windowmanager/intern/wm_jobs.c46
-rw-r--r--source/blender/windowmanager/intern/wm_keymap.c380
-rw-r--r--source/blender/windowmanager/intern/wm_operators.c1550
-rw-r--r--source/blender/windowmanager/intern/wm_playanim.c442
-rw-r--r--source/blender/windowmanager/intern/wm_stereo.c598
-rw-r--r--source/blender/windowmanager/intern/wm_subwindow.c88
-rw-r--r--source/blender/windowmanager/intern/wm_window.c251
-rw-r--r--source/blender/windowmanager/wm.h8
-rw-r--r--source/blender/windowmanager/wm_draw.h21
-rw-r--r--source/blender/windowmanager/wm_event_system.h15
-rw-r--r--source/blender/windowmanager/wm_event_types.h38
-rw-r--r--source/blender/windowmanager/wm_files.h5
-rw-r--r--source/blender/windowmanager/wm_window.h22
-rw-r--r--source/blenderplayer/CMakeLists.txt23
-rw-r--r--source/blenderplayer/bad_level_call_stubs/stubs.c114
-rw-r--r--source/creator/CMakeLists.txt415
-rw-r--r--source/creator/blender.map1
-rw-r--r--source/creator/creator.c535
-rw-r--r--source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp45
-rw-r--r--source/gameengine/BlenderRoutines/CMakeLists.txt10
-rw-r--r--source/gameengine/BlenderRoutines/KX_BlenderCanvas.cpp16
-rw-r--r--source/gameengine/BlenderRoutines/KX_BlenderCanvas.h6
-rw-r--r--source/gameengine/BlenderRoutines/SConscript13
-rw-r--r--source/gameengine/CMakeLists.txt2
-rw-r--r--source/gameengine/Converter/BL_ActionActuator.cpp17
-rw-r--r--source/gameengine/Converter/BL_ArmatureChannel.cpp2
-rw-r--r--source/gameengine/Converter/BL_ArmatureChannel.h2
-rw-r--r--source/gameengine/Converter/BL_ArmatureConstraint.cpp2
-rw-r--r--source/gameengine/Converter/BL_ArmatureConstraint.h2
-rw-r--r--source/gameengine/Converter/BL_ArmatureObject.cpp17
-rw-r--r--source/gameengine/Converter/BL_BlenderDataConversion.cpp442
-rw-r--r--source/gameengine/Converter/BL_BlenderDataConversion.h2
-rw-r--r--source/gameengine/Converter/BL_ModifierDeformer.cpp1
-rw-r--r--source/gameengine/Converter/BL_ShapeActionActuator.cpp4
-rw-r--r--source/gameengine/Converter/BL_SkinDeformer.cpp4
-rw-r--r--source/gameengine/Converter/BlenderWorldInfo.cpp200
-rw-r--r--source/gameengine/Converter/BlenderWorldInfo.h82
-rw-r--r--source/gameengine/Converter/CMakeLists.txt11
-rw-r--r--source/gameengine/Converter/KX_BlenderSceneConverter.cpp789
-rw-r--r--source/gameengine/Converter/KX_BlenderSceneConverter.h2
-rw-r--r--source/gameengine/Converter/KX_ConvertActuators.cpp33
-rw-r--r--source/gameengine/Converter/KX_ConvertControllers.cpp4
-rw-r--r--source/gameengine/Converter/KX_ConvertControllers.h4
-rw-r--r--source/gameengine/Converter/KX_ConvertProperties.cpp12
-rw-r--r--source/gameengine/Converter/KX_ConvertSensors.cpp976
-rw-r--r--source/gameengine/Converter/KX_LibLoadStatus.h2
-rw-r--r--source/gameengine/Converter/SConscript5
-rw-r--r--source/gameengine/Expressions/CMakeLists.txt86
-rw-r--r--source/gameengine/Expressions/EXP_BoolValue.h (renamed from source/gameengine/Expressions/BoolValue.h)10
-rw-r--r--source/gameengine/Expressions/EXP_C-Api.cpp123
-rw-r--r--source/gameengine/Expressions/EXP_C-Api.h67
-rw-r--r--source/gameengine/Expressions/EXP_ConstExpr.h (renamed from source/gameengine/Expressions/ConstExpr.h)12
-rw-r--r--source/gameengine/Expressions/EXP_EmptyValue.h (renamed from source/gameengine/Expressions/EmptyValue.h)10
-rw-r--r--source/gameengine/Expressions/EXP_ErrorValue.h (renamed from source/gameengine/Expressions/ErrorValue.h)10
-rw-r--r--source/gameengine/Expressions/EXP_Expression.h (renamed from source/gameengine/Expressions/Expression.h)10
-rw-r--r--source/gameengine/Expressions/EXP_FloatValue.h (renamed from source/gameengine/Expressions/FloatValue.h)10
-rw-r--r--source/gameengine/Expressions/EXP_HashedPtr.h (renamed from source/gameengine/Expressions/KX_HashedPtr.h)10
-rw-r--r--source/gameengine/Expressions/EXP_IdentifierExpr.h (renamed from source/gameengine/Expressions/IdentifierExpr.h)10
-rw-r--r--source/gameengine/Expressions/EXP_IfExpr.h (renamed from source/gameengine/Expressions/IfExpr.h)10
-rw-r--r--source/gameengine/Expressions/EXP_InputParser.h (renamed from source/gameengine/Expressions/InputParser.h)10
-rw-r--r--source/gameengine/Expressions/EXP_IntValue.h (renamed from source/gameengine/Expressions/IntValue.h)10
-rw-r--r--source/gameengine/Expressions/EXP_ListValue.h (renamed from source/gameengine/Expressions/ListValue.h)10
-rw-r--r--source/gameengine/Expressions/EXP_Operator1Expr.h (renamed from source/gameengine/Expressions/Operator1Expr.h)10
-rw-r--r--source/gameengine/Expressions/EXP_Operator2Expr.h (renamed from source/gameengine/Expressions/Operator2Expr.h)12
-rw-r--r--source/gameengine/Expressions/EXP_PyObjectPlus.h (renamed from source/gameengine/Expressions/PyObjectPlus.h)34
-rw-r--r--source/gameengine/Expressions/EXP_Python.h (renamed from source/gameengine/Expressions/KX_Python.h)8
-rw-r--r--source/gameengine/Expressions/EXP_PythonCallBack.h40
-rw-r--r--source/gameengine/Expressions/EXP_StringValue.h (renamed from source/gameengine/Expressions/StringValue.h)10
-rw-r--r--source/gameengine/Expressions/EXP_Value.h (renamed from source/gameengine/Expressions/Value.h)10
-rw-r--r--source/gameengine/Expressions/EXP_VectorValue.h (renamed from source/gameengine/Expressions/VectorValue.h)10
-rw-r--r--source/gameengine/Expressions/EXP_VoidValue.h (renamed from source/gameengine/Expressions/VoidValue.h)10
-rw-r--r--source/gameengine/Expressions/SConscript2
-rw-r--r--source/gameengine/Expressions/intern/BoolValue.cpp (renamed from source/gameengine/Expressions/BoolValue.cpp)8
-rw-r--r--source/gameengine/Expressions/intern/ConstExpr.cpp (renamed from source/gameengine/Expressions/ConstExpr.cpp)6
-rw-r--r--source/gameengine/Expressions/intern/EmptyValue.cpp (renamed from source/gameengine/Expressions/EmptyValue.cpp)14
-rw-r--r--source/gameengine/Expressions/intern/ErrorValue.cpp (renamed from source/gameengine/Expressions/ErrorValue.cpp)2
-rw-r--r--source/gameengine/Expressions/intern/Expression.cpp (renamed from source/gameengine/Expressions/Expression.cpp)4
-rw-r--r--source/gameengine/Expressions/intern/FloatValue.cpp (renamed from source/gameengine/Expressions/FloatValue.cpp)12
-rw-r--r--source/gameengine/Expressions/intern/HashedPtr.cpp (renamed from source/gameengine/Expressions/KX_HashedPtr.cpp)28
-rw-r--r--source/gameengine/Expressions/intern/IdentifierExpr.cpp (renamed from source/gameengine/Expressions/IdentifierExpr.cpp)2
-rw-r--r--source/gameengine/Expressions/intern/IfExpr.cpp (renamed from source/gameengine/Expressions/IfExpr.cpp)8
-rw-r--r--source/gameengine/Expressions/intern/InputParser.cpp (renamed from source/gameengine/Expressions/InputParser.cpp)26
-rw-r--r--source/gameengine/Expressions/intern/IntValue.cpp (renamed from source/gameengine/Expressions/IntValue.cpp)12
-rw-r--r--source/gameengine/Expressions/intern/ListValue.cpp (renamed from source/gameengine/Expressions/ListValue.cpp)19
-rw-r--r--source/gameengine/Expressions/intern/Operator1Expr.cpp (renamed from source/gameengine/Expressions/Operator1Expr.cpp)4
-rw-r--r--source/gameengine/Expressions/intern/Operator2Expr.cpp (renamed from source/gameengine/Expressions/Operator2Expr.cpp)6
-rw-r--r--source/gameengine/Expressions/intern/PyObjectPlus.cpp (renamed from source/gameengine/Expressions/PyObjectPlus.cpp)25
-rw-r--r--source/gameengine/Expressions/intern/PythonCallBack.cpp119
-rw-r--r--source/gameengine/Expressions/intern/StringValue.cpp (renamed from source/gameengine/Expressions/StringValue.cpp)8
-rw-r--r--source/gameengine/Expressions/intern/Value.cpp (renamed from source/gameengine/Expressions/Value.cpp)20
-rw-r--r--source/gameengine/Expressions/intern/VectorValue.cpp (renamed from source/gameengine/Expressions/VectorValue.cpp)10
-rw-r--r--source/gameengine/GameLogic/Joystick/SCA_Joystick.cpp51
-rw-r--r--source/gameengine/GameLogic/Joystick/SCA_JoystickEvents.cpp15
-rw-r--r--source/gameengine/GameLogic/SCA_ANDController.cpp2
-rw-r--r--source/gameengine/GameLogic/SCA_ExpressionController.cpp4
-rw-r--r--source/gameengine/GameLogic/SCA_IController.cpp2
-rw-r--r--source/gameengine/GameLogic/SCA_IController.h2
-rw-r--r--source/gameengine/GameLogic/SCA_IInputDevice.h2
-rw-r--r--source/gameengine/GameLogic/SCA_ILogicBrick.cpp2
-rw-r--r--source/gameengine/GameLogic/SCA_ILogicBrick.h4
-rw-r--r--source/gameengine/GameLogic/SCA_IObject.cpp2
-rw-r--r--source/gameengine/GameLogic/SCA_IObject.h5
-rw-r--r--source/gameengine/GameLogic/SCA_IScene.cpp4
-rw-r--r--source/gameengine/GameLogic/SCA_ISensor.cpp34
-rw-r--r--source/gameengine/GameLogic/SCA_ISensor.h10
-rw-r--r--source/gameengine/GameLogic/SCA_JoystickSensor.cpp14
-rw-r--r--source/gameengine/GameLogic/SCA_KeyboardManager.cpp4
-rw-r--r--source/gameengine/GameLogic/SCA_KeyboardSensor.cpp3
-rw-r--r--source/gameengine/GameLogic/SCA_KeyboardSensor.h2
-rw-r--r--source/gameengine/GameLogic/SCA_LogicManager.cpp2
-rw-r--r--source/gameengine/GameLogic/SCA_LogicManager.h6
-rw-r--r--source/gameengine/GameLogic/SCA_MouseManager.cpp4
-rw-r--r--source/gameengine/GameLogic/SCA_MouseSensor.cpp2
-rw-r--r--source/gameengine/GameLogic/SCA_MouseSensor.h2
-rw-r--r--source/gameengine/GameLogic/SCA_NANDController.cpp2
-rw-r--r--source/gameengine/GameLogic/SCA_NORController.cpp2
-rw-r--r--source/gameengine/GameLogic/SCA_ORController.cpp2
-rw-r--r--source/gameengine/GameLogic/SCA_PropertyActuator.cpp6
-rw-r--r--source/gameengine/GameLogic/SCA_PropertySensor.cpp21
-rw-r--r--source/gameengine/GameLogic/SCA_PythonController.cpp6
-rw-r--r--source/gameengine/GameLogic/SCA_PythonController.h2
-rw-r--r--source/gameengine/GameLogic/SCA_PythonJoystick.h2
-rw-r--r--source/gameengine/GameLogic/SCA_PythonKeyboard.h2
-rw-r--r--source/gameengine/GameLogic/SCA_PythonMouse.h2
-rw-r--r--source/gameengine/GameLogic/SCA_RandomActuator.cpp6
-rw-r--r--source/gameengine/GameLogic/SCA_RandomSensor.cpp4
-rw-r--r--source/gameengine/GameLogic/SCA_RandomSensor.h2
-rw-r--r--source/gameengine/GameLogic/SCA_TimeEventManager.cpp2
-rw-r--r--source/gameengine/GameLogic/SCA_TimeEventManager.h2
-rw-r--r--source/gameengine/GameLogic/SCA_XNORController.cpp2
-rw-r--r--source/gameengine/GameLogic/SCA_XORController.cpp2
-rw-r--r--source/gameengine/GamePlayer/common/CMakeLists.txt3
-rw-r--r--source/gameengine/GamePlayer/common/GPC_Canvas.cpp5
-rw-r--r--source/gameengine/GamePlayer/common/GPC_Canvas.h6
-rw-r--r--source/gameengine/GamePlayer/common/SConscript8
-rw-r--r--source/gameengine/GamePlayer/ghost/CMakeLists.txt16
-rw-r--r--source/gameengine/GamePlayer/ghost/GPG_Application.cpp70
-rw-r--r--source/gameengine/GamePlayer/ghost/GPG_Application.h8
-rw-r--r--source/gameengine/GamePlayer/ghost/GPG_Canvas.cpp18
-rw-r--r--source/gameengine/GamePlayer/ghost/GPG_Canvas.h4
-rw-r--r--source/gameengine/GamePlayer/ghost/GPG_ghost.cpp62
-rw-r--r--source/gameengine/GamePlayer/ghost/SConscript18
-rw-r--r--source/gameengine/Ketsji/BL_Action.cpp21
-rw-r--r--source/gameengine/Ketsji/BL_Action.h2
-rw-r--r--source/gameengine/Ketsji/BL_ActionManager.cpp28
-rw-r--r--source/gameengine/Ketsji/BL_ActionManager.h15
-rw-r--r--source/gameengine/Ketsji/BL_BlenderShader.cpp6
-rw-r--r--source/gameengine/Ketsji/BL_Material.cpp10
-rw-r--r--source/gameengine/Ketsji/BL_Material.h2
-rw-r--r--source/gameengine/Ketsji/BL_Shader.cpp2
-rw-r--r--source/gameengine/Ketsji/BL_Shader.h2
-rw-r--r--source/gameengine/Ketsji/BL_Texture.cpp51
-rw-r--r--source/gameengine/Ketsji/CMakeLists.txt12
-rw-r--r--source/gameengine/Ketsji/KXNetwork/CMakeLists.txt1
-rw-r--r--source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.cpp6
-rw-r--r--source/gameengine/Ketsji/KXNetwork/SConscript1
-rw-r--r--source/gameengine/Ketsji/KX_BlenderMaterial.cpp345
-rw-r--r--source/gameengine/Ketsji/KX_BlenderMaterial.h34
-rw-r--r--source/gameengine/Ketsji/KX_Camera.cpp80
-rw-r--r--source/gameengine/Ketsji/KX_Camera.h14
-rw-r--r--source/gameengine/Ketsji/KX_CameraActuator.cpp16
-rw-r--r--source/gameengine/Ketsji/KX_CharacterWrapper.h2
-rw-r--r--source/gameengine/Ketsji/KX_ClientObjectInfo.h9
-rw-r--r--source/gameengine/Ketsji/KX_ConstraintActuator.cpp17
-rw-r--r--source/gameengine/Ketsji/KX_ConstraintWrapper.cpp2
-rw-r--r--source/gameengine/Ketsji/KX_ConstraintWrapper.h2
-rw-r--r--source/gameengine/Ketsji/KX_Dome.cpp6
-rw-r--r--source/gameengine/Ketsji/KX_Dome.h2
-rw-r--r--source/gameengine/Ketsji/KX_FontObject.cpp3
-rw-r--r--source/gameengine/Ketsji/KX_FontObject.h1
-rw-r--r--source/gameengine/Ketsji/KX_GameActuator.cpp5
-rw-r--r--source/gameengine/Ketsji/KX_GameObject.cpp506
-rw-r--r--source/gameengine/Ketsji/KX_GameObject.h75
-rw-r--r--source/gameengine/Ketsji/KX_ISceneConverter.h10
-rw-r--r--source/gameengine/Ketsji/KX_IpoActuator.cpp2
-rw-r--r--source/gameengine/Ketsji/KX_IpoConvert.cpp88
-rw-r--r--source/gameengine/Ketsji/KX_IpoConvert.h3
-rw-r--r--source/gameengine/Ketsji/KX_KetsjiEngine.cpp249
-rw-r--r--source/gameengine/Ketsji/KX_KetsjiEngine.h13
-rw-r--r--source/gameengine/Ketsji/KX_Light.cpp29
-rw-r--r--source/gameengine/Ketsji/KX_Light.h4
-rw-r--r--source/gameengine/Ketsji/KX_MaterialIpoController.cpp15
-rw-r--r--source/gameengine/Ketsji/KX_MeshProxy.cpp2
-rw-r--r--source/gameengine/Ketsji/KX_MouseActuator.cpp60
-rw-r--r--source/gameengine/Ketsji/KX_MouseActuator.h5
-rw-r--r--source/gameengine/Ketsji/KX_MouseFocusSensor.cpp40
-rw-r--r--source/gameengine/Ketsji/KX_NavMeshObject.cpp14
-rw-r--r--source/gameengine/Ketsji/KX_NavMeshObject.h2
-rw-r--r--source/gameengine/Ketsji/KX_ObjectActuator.cpp32
-rw-r--r--source/gameengine/Ketsji/KX_ObjectActuator.h3
-rw-r--r--source/gameengine/Ketsji/KX_ParentActuator.cpp2
-rw-r--r--source/gameengine/Ketsji/KX_PolyProxy.cpp10
-rw-r--r--source/gameengine/Ketsji/KX_PyConstraintBinding.cpp278
-rw-r--r--source/gameengine/Ketsji/KX_PyConstraintBinding.h3
-rw-r--r--source/gameengine/Ketsji/KX_PyMath.cpp31
-rw-r--r--source/gameengine/Ketsji/KX_PyMath.h9
-rw-r--r--source/gameengine/Ketsji/KX_PythonInit.cpp676
-rw-r--r--source/gameengine/Ketsji/KX_PythonInit.h26
-rw-r--r--source/gameengine/Ketsji/KX_PythonInitTypes.cpp43
-rw-r--r--source/gameengine/Ketsji/KX_PythonInitTypes.h3
-rw-r--r--source/gameengine/Ketsji/KX_PythonSeq.h2
-rw-r--r--source/gameengine/Ketsji/KX_RaySensor.cpp45
-rw-r--r--source/gameengine/Ketsji/KX_SCA_AddObjectActuator.cpp2
-rw-r--r--source/gameengine/Ketsji/KX_SCA_DynamicActuator.cpp4
-rw-r--r--source/gameengine/Ketsji/KX_SCA_ReplaceMeshActuator.cpp2
-rw-r--r--source/gameengine/Ketsji/KX_Scene.cpp311
-rw-r--r--source/gameengine/Ketsji/KX_Scene.h21
-rw-r--r--source/gameengine/Ketsji/KX_SoundActuator.cpp204
-rw-r--r--source/gameengine/Ketsji/KX_SoundActuator.h12
-rw-r--r--source/gameengine/Ketsji/KX_SteeringActuator.cpp21
-rw-r--r--source/gameengine/Ketsji/KX_SteeringActuator.h4
-rw-r--r--source/gameengine/Ketsji/KX_TouchEventManager.cpp24
-rw-r--r--source/gameengine/Ketsji/KX_TouchEventManager.h24
-rw-r--r--source/gameengine/Ketsji/KX_TouchSensor.cpp41
-rw-r--r--source/gameengine/Ketsji/KX_TouchSensor.h2
-rw-r--r--source/gameengine/Ketsji/KX_TrackToActuator.cpp2
-rw-r--r--source/gameengine/Ketsji/KX_VehicleWrapper.cpp82
-rw-r--r--source/gameengine/Ketsji/KX_VehicleWrapper.h2
-rw-r--r--source/gameengine/Ketsji/KX_WorldInfo.cpp456
-rw-r--r--source/gameengine/Ketsji/KX_WorldInfo.h84
-rw-r--r--source/gameengine/Ketsji/KX_WorldIpoController.cpp31
-rw-r--r--source/gameengine/Ketsji/KX_WorldIpoController.h28
-rw-r--r--source/gameengine/Ketsji/SConscript13
-rw-r--r--source/gameengine/Network/CMakeLists.txt1
-rw-r--r--source/gameengine/Network/SConscript1
-rw-r--r--source/gameengine/Physics/Bullet/CMakeLists.txt3
-rw-r--r--source/gameengine/Physics/Bullet/CcdPhysicsController.cpp848
-rw-r--r--source/gameengine/Physics/Bullet/CcdPhysicsController.h101
-rw-r--r--source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp585
-rw-r--r--source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.h44
-rw-r--r--source/gameengine/Physics/Bullet/SConscript4
-rw-r--r--source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.cpp2
-rw-r--r--source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.h2
-rw-r--r--source/gameengine/Physics/common/PHY_IPhysicsController.h16
-rw-r--r--source/gameengine/Physics/common/PHY_IPhysicsEnvironment.h6
-rw-r--r--source/gameengine/Physics/common/PHY_Pro.h2
-rw-r--r--source/gameengine/Rasterizer/CMakeLists.txt3
-rw-r--r--source/gameengine/Rasterizer/RAS_2DFilterManager.cpp63
-rw-r--r--source/gameengine/Rasterizer/RAS_CameraData.h5
-rw-r--r--source/gameengine/Rasterizer/RAS_FramingManager.cpp52
-rw-r--r--source/gameengine/Rasterizer/RAS_FramingManager.h8
-rw-r--r--source/gameengine/Rasterizer/RAS_ICanvas.h5
-rw-r--r--source/gameengine/Rasterizer/RAS_IPolygonMaterial.cpp2
-rw-r--r--source/gameengine/Rasterizer/RAS_IPolygonMaterial.h4
-rw-r--r--source/gameengine/Rasterizer/RAS_IRasterizer.h21
-rw-r--r--source/gameengine/Rasterizer/RAS_MaterialBucket.cpp10
-rw-r--r--source/gameengine/Rasterizer/RAS_MaterialBucket.h10
-rw-r--r--source/gameengine/Rasterizer/RAS_MeshObject.cpp17
-rw-r--r--source/gameengine/Rasterizer/RAS_MeshObject.h8
-rw-r--r--source/gameengine/Rasterizer/RAS_OpenGLRasterizer/CMakeLists.txt3
-rw-r--r--source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_GLExtensionManager.cpp2
-rw-r--r--source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.cpp8
-rw-r--r--source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.h9
-rw-r--r--source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLLight.cpp3
-rw-r--r--source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp222
-rw-r--r--source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.h37
-rw-r--r--source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_StorageIM.cpp8
-rw-r--r--source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_StorageVA.cpp2
-rw-r--r--source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_StorageVBO.cpp2
-rw-r--r--source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_StorageVBO.h2
-rw-r--r--source/gameengine/Rasterizer/RAS_OpenGLRasterizer/SConscript6
-rw-r--r--source/gameengine/Rasterizer/RAS_Polygon.cpp4
-rw-r--r--source/gameengine/Rasterizer/RAS_Polygon.h4
-rw-r--r--source/gameengine/Rasterizer/RAS_texmatrix.cpp2
-rw-r--r--source/gameengine/Rasterizer/SConscript7
-rw-r--r--source/gameengine/VideoTexture/CMakeLists.txt3
-rw-r--r--source/gameengine/VideoTexture/Exception.cpp2
-rw-r--r--source/gameengine/VideoTexture/FilterBase.cpp2
-rw-r--r--source/gameengine/VideoTexture/FilterBase.h6
-rw-r--r--source/gameengine/VideoTexture/FilterBlueScreen.cpp2
-rw-r--r--source/gameengine/VideoTexture/FilterColor.cpp2
-rw-r--r--source/gameengine/VideoTexture/FilterNormal.cpp2
-rw-r--r--source/gameengine/VideoTexture/FilterSource.cpp2
-rw-r--r--source/gameengine/VideoTexture/ImageBase.cpp34
-rw-r--r--source/gameengine/VideoTexture/ImageBase.h2
-rw-r--r--source/gameengine/VideoTexture/ImageBuff.cpp2
-rw-r--r--source/gameengine/VideoTexture/ImageMix.cpp2
-rw-r--r--source/gameengine/VideoTexture/ImageRender.cpp79
-rw-r--r--source/gameengine/VideoTexture/ImageRender.h6
-rw-r--r--source/gameengine/VideoTexture/ImageViewport.cpp4
-rw-r--r--source/gameengine/VideoTexture/PyTypeList.cpp2
-rw-r--r--source/gameengine/VideoTexture/PyTypeList.h2
-rw-r--r--source/gameengine/VideoTexture/SConscript7
-rw-r--r--source/gameengine/VideoTexture/Texture.cpp56
-rw-r--r--source/gameengine/VideoTexture/Texture.h10
-rw-r--r--source/gameengine/VideoTexture/VideoBase.h2
-rw-r--r--source/gameengine/VideoTexture/VideoFFmpeg.cpp26
-rw-r--r--source/gameengine/VideoTexture/VideoFFmpeg.h3
-rw-r--r--source/gameengine/VideoTexture/blendVideoTex.cpp66
-rw-r--r--tests/gtests/blenlib/BLI_ghash_performance_test.cc415
-rw-r--r--tests/gtests/blenlib/BLI_ghash_test.cc158
-rw-r--r--tests/gtests/blenlib/BLI_hash_mm2a_test.cc75
-rw-r--r--tests/gtests/blenlib/BLI_listbase_test.cc218
-rw-r--r--tests/gtests/blenlib/BLI_math_base_test.cc87
-rw-r--r--tests/gtests/blenlib/BLI_path_util_test.cc1
-rw-r--r--tests/gtests/blenlib/BLI_polyfill2d_test.cc518
-rw-r--r--tests/gtests/blenlib/BLI_ressource_strings.h602
-rw-r--r--tests/gtests/blenlib/BLI_stack_test.cc77
-rw-r--r--tests/gtests/blenlib/BLI_string_test.cc70
-rw-r--r--tests/gtests/blenlib/CMakeLists.txt6
-rw-r--r--tests/gtests/testing/testing_main.cc2
-rw-r--r--tests/python/CMakeLists.txt65
-rw-r--r--tests/python/batch_import.py4
-rw-r--r--tests/python/bl_load_addons.py61
-rw-r--r--tests/python/bl_load_py_modules.py42
-rw-r--r--tests/python/bl_mesh_modifiers.py3
-rw-r--r--tests/python/bl_pyapi_bpy_path.py41
-rw-r--r--tests/python/bl_pyapi_bpy_utils_units.py (renamed from tests/python/bl_pyapi_units.py)2
-rw-r--r--tests/python/bl_pyapi_mathutils.py31
-rw-r--r--tests/python/bl_rna_defaults.py117
-rw-r--r--tests/python/bl_rna_manual_reference.py (renamed from tests/python/bl_rna_wiki_reference.py)51
-rw-r--r--tests/python/bl_rst_completeness.py2
-rw-r--r--tests/python/bl_run_operators.py10
-rwxr-xr-xtests/python/cycles_render_tests.py166
-rw-r--r--tests/python/pep8.py25
-rw-r--r--tests/python/rst_to_doctree_mini.py21
3230 files changed, 332248 insertions, 100869 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 2cabeb69e4b..deafa90dbb5 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -53,7 +53,9 @@ if(NOT (${CMAKE_VERSION} VERSION_LESS 3.0))
endif()
if(NOT EXECUTABLE_OUTPUT_PATH)
- set(FIRST_RUN "TRUE")
+ set(FIRST_RUN TRUE)
+else()
+ set(FIRST_RUN FALSE)
endif()
# this starts out unset
@@ -71,7 +73,6 @@ set_property(DIRECTORY APPEND PROPERTY COMPILE_DEFINITIONS_RELEASE NDEBU
set_property(DIRECTORY APPEND PROPERTY COMPILE_DEFINITIONS_MINSIZEREL NDEBUG)
set_property(DIRECTORY APPEND PROPERTY COMPILE_DEFINITIONS_RELWITHDEBINFO NDEBUG)
-
#-----------------------------------------------------------------------------
# Set policy
@@ -117,6 +118,81 @@ set(TESTS_OUTPUT_DIR ${EXECUTABLE_OUTPUT_PATH}/tests CACHE INTERNAL "" FORCE)
get_blender_version()
+#-----------------------------------------------------------------------------
+# Platform Specific Defaults
+
+# list of var-names
+set(_init_vars)
+
+# initialize to ON
+macro(option_defaults_init)
+ foreach(_var ${ARGV})
+ set(${_var} ON)
+ list(APPEND _init_vars "${_var}")
+ endforeach()
+ unset(_var)
+endmacro()
+
+# remove from namespace
+macro(option_defaults_clear)
+ foreach(_var ${_init_vars})
+ unset(${_var})
+ endforeach()
+ unset(_var)
+ unset(_init_vars)
+endmacro()
+
+
+# values to initialize WITH_****
+option_defaults_init(
+ _init_BUILDINFO
+ _init_CODEC_FFMPEG
+ _init_CYCLES_OSL
+ _init_IMAGE_OPENEXR
+ _init_IMAGE_REDCODE
+ _init_INPUT_NDOF
+ _init_JACK
+ _init_LIBMV_SCHUR_SPECIALIZATION
+ _init_OPENCOLLADA
+ _init_OPENCOLORIO
+ _init_SDL
+ _init_FFTW3
+ _init_GAMEENGINE
+ _init_OPENSUBDIV
+)
+
+# customize...
+if (UNIX AND NOT APPLE)
+ # some of these libraries are problematic on Linux
+ # disable less important dependencies by default
+ set(_init_CODEC_FFMPEG OFF)
+ set(_init_CYCLES_OSL OFF)
+ set(_init_IMAGE_OPENEXR OFF)
+ set(_init_IMAGE_REDCODE OFF)
+ set(_init_INPUT_NDOF OFF)
+ set(_init_JACK OFF)
+ set(_init_OPENCOLLADA OFF)
+ set(_init_OPENCOLORIO OFF)
+ set(_init_SDL OFF)
+ set(_init_FFTW3 OFF)
+ set(_init_OPENSUBDIV OFF)
+elseif(WIN32)
+ set(_init_JACK OFF)
+elseif(APPLE)
+ set(_init_INPUT_NDOF OFF)
+ set(_init_JACK OFF)
+ set(_init_OPENSUBDIV OFF)
+endif()
+
+
+#-----------------------------------------------------------------------------
+# Options
+
+# First platform spesific non-cached vars
+if(UNIX AND NOT APPLE)
+ set(WITH_X11 ON)
+endif()
+
# Blender internal features
option(WITH_BLENDER "Build blender (disable to build only the blender player)" ON)
mark_as_advanced(WITH_BLENDER)
@@ -127,15 +203,15 @@ option(WITH_PYTHON "Enable Embedded Python API (only disable for develop
option(WITH_PYTHON_SECURITY "Disables execution of scripts within blend files by default" ON)
mark_as_advanced(WITH_PYTHON) # dont want people disabling this unless they really know what they are doing.
mark_as_advanced(WITH_PYTHON_SECURITY) # some distributions see this as a security issue, rather than have them patch it, make a build option.
-set(WITH_PYTHON_SECURITY ON CACHE BOOL "ON" FORCE) # temp force on.
option(WITH_PYTHON_SAFETY "Enable internal API error checking to track invalid data to prevent crash on access (at the expense of some effeciency, only enable for development)." OFF)
-option(WITH_PYTHON_MODULE "Enable building as a python module which runs without a user interface, like running regular blender in background mode (experimental, only enable for development)" OFF)
+mark_as_advanced(WITH_PYTHON_SAFETY)
+option(WITH_PYTHON_MODULE "Enable building as a python module which runs without a user interface, like running regular blender in background mode (experimental, only enable for development), installs to PYTHON_SITE_PACKAGES (or CMAKE_INSTALL_PREFIX if WITH_INSTALL_PORTABLE is enabled)." OFF)
if(APPLE)
option(WITH_PYTHON_FRAMEWORK "Enable building using the Python available in the framework (OSX only)" OFF)
endif()
-option(WITH_BUILDINFO "Include extra build details (only disable for development & faster builds)" ON)
+option(WITH_BUILDINFO "Include extra build details (only disable for development & faster builds)" ${_init_BUILDINFO})
if(${CMAKE_VERSION} VERSION_LESS 2.8.8)
# add_library OBJECT arg unsupported
set(WITH_BUILDINFO OFF)
@@ -143,14 +219,22 @@ endif()
option(WITH_IK_ITASC "Enable ITASC IK solver (only disable for development & for incompatible C++ compilers)" ON)
option(WITH_IK_SOLVER "Enable Legacy IK solver (only disable for development)" ON)
-option(WITH_FFTW3 "Enable FFTW3 support (Used for smoke and audio effects)" ON)
+option(WITH_FFTW3 "Enable FFTW3 support (Used for smoke and audio effects)" ${_init_FFTW3})
option(WITH_BULLET "Enable Bullet (Physics Engine)" ON)
option(WITH_SYSTEM_BULLET "Use the systems bullet library (currently unsupported due to missing features in upstream!)" )
mark_as_advanced(WITH_SYSTEM_BULLET)
-option(WITH_GAMEENGINE "Enable Game Engine" ON)
+option(WITH_GAMEENGINE "Enable Game Engine" ${_init_GAMEENGINE})
option(WITH_PLAYER "Build Player" OFF)
-option(WITH_OPENCOLORIO "Enable OpenColorIO color management" ON)
-option(WITH_COMPOSITOR "Enable the tile based nodal compositor" ON)
+option(WITH_OPENCOLORIO "Enable OpenColorIO color management" ${_init_OPENCOLORIO})
+
+# Compositor
+option(WITH_COMPOSITOR "Enable the tile based nodal compositor" ON)
+option(WITH_COMPOSITOR_WERROR "Treat warnings as errors in compositor code" OFF)
+mark_as_advanced(WITH_COMPOSITOR_WERROR)
+
+option(WITH_OPENSUBDIV "Enable OpenSubdiv for surface subdivision" _init_OPENSUBDIV)
+option(WITH_SUBSURF_WERROR "Treat warnings as errors in subsurf code" OFF)
+mark_as_advanced(WITH_COMPOSITOR_WERROR)
# GHOST Windowing Library Options
option(WITH_GHOST_DEBUG "Enable debugging output for the GHOST library" OFF)
@@ -159,35 +243,46 @@ mark_as_advanced(WITH_GHOST_DEBUG)
option(WITH_GHOST_SDL "Enable building blender against SDL for windowing rather then the native APIs" OFF)
mark_as_advanced(WITH_GHOST_SDL)
+if(WITH_X11)
+ option(WITH_GHOST_XDND "Enable drag'n'drop support on X11 using XDND protocol" ON)
+endif()
+
# Misc...
option(WITH_HEADLESS "Build without graphical support (renderfarm, server mode only)" OFF)
mark_as_advanced(WITH_HEADLESS)
option(WITH_AUDASPACE "Build with blenders audio library (only disable if you know what you're doing!)" ON)
+option(WITH_SYSTEM_AUDASPACE "Build with external audaspace library installed on the system (only enable if you know what you're doing!)" OFF)
mark_as_advanced(WITH_AUDASPACE)
+mark_as_advanced(WITH_SYSTEM_AUDASPACE)
+
+if(NOT WITH_AUDASPACE)
+ set(WITH_SYSTEM_AUDASPACE OFF)
+endif()
option(WITH_OPENMP "Enable OpenMP (has to be supported by the compiler)" ON)
+if(WITH_X11)
+ option(WITH_X11_XINPUT "Enable X11 Xinput (tablet support and unicode input)" ON)
+ option(WITH_X11_XF86VMODE "Enable X11 video mode switching" ON)
+endif()
+
if(UNIX AND NOT APPLE)
- option(WITH_X11_XINPUT "Enable X11 Xinput (tablet support and unicode input)" ON)
- option(WITH_X11_XF86VMODE "Enable X11 video mode switching" ON)
option(WITH_SYSTEM_GLEW "Use GLEW OpenGL wrapper library provided by the operating system" ON)
-
- option(WITH_GHOST_XDND "Enable drag'n'drop support on X11 using XDND protocol" ON)
+ option(WITH_SYSTEM_GLES "Use OpenGL ES library provided by the operating system" ON)
else()
# not an option for other OS's
set(WITH_SYSTEM_GLEW OFF)
+ set(WITH_SYSTEM_GLES OFF)
endif()
# (unix defaults to System OpenJPEG On)
+option(WITH_SYSTEM_OPENJPEG "Use the operating systems OpenJPEG library" OFF)
+
if(UNIX AND NOT APPLE)
- set(PLATFORM_DEFAULT ON)
-else()
- set(PLATFORM_DEFAULT OFF)
+ option(WITH_SYSTEM_EIGEN3 "Use the systems Eigen3 library" OFF)
endif()
-option(WITH_SYSTEM_OPENJPEG "Use the operating systems OpenJPEG library" ${PLATFORM_DEFAULT})
-unset(PLATFORM_DEFAULT)
# Modifiers
@@ -200,56 +295,62 @@ option(WITH_MOD_REMESH "Enable Remesh Modifier" ON)
option(WITH_MOD_OCEANSIM "Enable Ocean Modifier" OFF)
# Image format support
-option(WITH_OPENIMAGEIO "Enable OpenImageIO Support (http://www.openimageio.org)" OFF)
-option(WITH_IMAGE_OPENEXR "Enable OpenEXR Support (http://www.openexr.com)" ON)
+option(WITH_OPENIMAGEIO "Enable OpenImageIO Support (http://www.openimageio.org)" ON)
+option(WITH_IMAGE_OPENEXR "Enable OpenEXR Support (http://www.openexr.com)" ${_init_IMAGE_OPENEXR})
option(WITH_IMAGE_OPENJPEG "Enable OpenJpeg Support (http://www.openjpeg.org)" ON)
option(WITH_IMAGE_TIFF "Enable LibTIFF Support" ON)
option(WITH_IMAGE_DDS "Enable DDS Image Support" ON)
option(WITH_IMAGE_CINEON "Enable CINEON and DPX Image Support" ON)
option(WITH_IMAGE_HDR "Enable HDR Image Support" ON)
-option(WITH_IMAGE_REDCODE "Enable RedCode Image Support" OFF)
+option(WITH_IMAGE_REDCODE "Enable RedCode Image Support" ${_init_IMAGE_REDCODE})
option(WITH_IMAGE_FRAMESERVER "Enable image FrameServer Support for rendering" ON)
# Audio/Video format support
option(WITH_CODEC_AVI "Enable Blenders own AVI file support (raw/jpeg)" ON)
-option(WITH_CODEC_FFMPEG "Enable FFMPeg Support (http://ffmpeg.org)" OFF)
+option(WITH_CODEC_FFMPEG "Enable FFMPeg Support (http://ffmpeg.org)" ${_init_CODEC_FFMPEG})
option(WITH_CODEC_SNDFILE "Enable libsndfile Support (http://www.mega-nerd.com/libsndfile)" OFF)
if(APPLE)
- option(WITH_CODEC_FFMPEG "Enable FFMPeg Support (http://ffmpeg.org)" ON)
option(WITH_CODEC_QUICKTIME "Enable Quicktime Support" ON)
-else()
- option(WITH_CODEC_FFMPEG "Enable FFMPeg Support (http://ffmpeg.org)" OFF)
endif()
# 3D format support
# Disable opencollada when we don't have precompiled libs
-if(APPLE OR WIN32)
- option(WITH_OPENCOLLADA "Enable OpenCollada Support (http://www.opencollada.org)" ON)
-else()
- option(WITH_OPENCOLLADA "Enable OpenCollada Support (http://www.opencollada.org)" OFF)
-endif()
+option(WITH_OPENCOLLADA "Enable OpenCollada Support (http://www.opencollada.org)" ${_init_OPENCOLLADA})
# Sound output
-option(WITH_SDL "Enable SDL for sound and joystick support" ON)
+option(WITH_SDL "Enable SDL for sound and joystick support" ${_init_SDL})
option(WITH_OPENAL "Enable OpenAL Support (http://www.openal.org)" ON)
-option(WITH_JACK "Enable Jack Support (http://www.jackaudio.org)" OFF)
+option(WITH_JACK "Enable Jack Support (http://www.jackaudio.org)" ${_init_JACK})
if(UNIX AND NOT APPLE)
option(WITH_JACK_DYNLOAD "Enable runtime dynamic Jack libraries loading" OFF)
endif()
+if(UNIX AND NOT APPLE)
+ option(WITH_SDL_DYNLOAD "Enable runtime dynamic SDL libraries loading" OFF)
+endif()
# Compression
option(WITH_LZO "Enable fast LZO compression (used for pointcache)" ON)
option(WITH_LZMA "Enable best LZMA compression, (used for pointcache)" ON)
+if(UNIX AND NOT APPLE)
+ option(WITH_SYSTEM_LZO "Use the system LZO library" OFF)
+endif()
# Camera/motion tracking
-option(WITH_LIBMV "Enable libmv structure from motion library" ON)
+option(WITH_LIBMV "Enable Libmv structure from motion library" ON)
+option(WITH_LIBMV_SCHUR_SPECIALIZATIONS "Enable fixed-size schur specializations." ${_init_LIBMV_SCHUR_SPECIALIZATION})
+option(WITH_LIBMV_WERROR "Treat warnings as errors in Libmv (and Blender's motion tracking) code")
+mark_as_advanced(WITH_LIBMV_SCHUR_SPECIALIZATIONS)
+mark_as_advanced(WITH_LIBMV_WERROR)
# Freestyle
option(WITH_FREESTYLE "Enable Freestyle (advanced edges rendering)" ON)
# Misc
-option(WITH_INPUT_NDOF "Enable NDOF input devices (SpaceNavigator and friends)" ON)
+if(WIN32)
+ option(WITH_INPUT_IME "Enable Input Method Editor (IME) for complex Asian character input" ON)
+endif()
+option(WITH_INPUT_NDOF "Enable NDOF input devices (SpaceNavigator and friends)" ${_init_INPUT_NDOF})
option(WITH_RAYOPTIMIZATION "Enable use of SIMD (SSE) optimizations for the raytracer" ON)
option(WITH_OPENNL "Enable use of Open Numerical Library" ON)
if(UNIX AND NOT APPLE)
@@ -264,6 +365,8 @@ option(WITH_PYTHON_INSTALL "Copy system python into the blender install fo
option(WITH_PYTHON_INSTALL_NUMPY "Copy system numpy into the blender install folder" ON)
set(PYTHON_NUMPY_PATH "" CACHE PATH "Path to python site-packages or dist-packages containing 'numpy' module")
mark_as_advanced(PYTHON_NUMPY_PATH)
+option(WITH_CPU_SSE "Enable SIMD instruction if they're detected on the host machine" ON)
+mark_as_advanced(WITH_CPU_SSE)
if(UNIX AND NOT APPLE)
option(WITH_PYTHON_INSTALL_REQUESTS "Copy system requests into the blender install folder" ON)
@@ -272,15 +375,20 @@ if(UNIX AND NOT APPLE)
endif()
# Cycles
-option(WITH_CYCLES "Enable cycles Render Engine" ON)
-option(WITH_CYCLES_STANDALONE "Build cycles standalone application" OFF)
-option(WITH_CYCLES_STANDALONE_GUI "Build cycles standalone with GUI" OFF)
-option(WITH_CYCLES_OSL "Build Cycles with OSL support" OFF)
-option(WITH_CYCLES_CUDA_BINARIES "Build cycles CUDA binaries" OFF)
-set(CYCLES_CUDA_BINARIES_ARCH sm_20 sm_21 sm_30 sm_35 sm_50 CACHE STRING "CUDA architectures to build binaries for")
+option(WITH_CYCLES "Enable Cycles Render Engine" ON)
+option(WITH_CYCLES_STANDALONE "Build Cycles standalone application" OFF)
+option(WITH_CYCLES_STANDALONE_GUI "Build Cycles standalone with GUI" OFF)
+option(WITH_CYCLES_OSL "Build Cycles with OSL support" ${_init_CYCLES_OSL})
+option(WITH_CYCLES_CUDA_BINARIES "Build Cycles CUDA binaries" OFF)
+set(CYCLES_CUDA_BINARIES_ARCH sm_20 sm_21 sm_30 sm_35 sm_50 sm_52 CACHE STRING "CUDA architectures to build binaries for")
mark_as_advanced(CYCLES_CUDA_BINARIES_ARCH)
unset(PLATFORM_DEFAULT)
-option(WITH_CYCLES_LOGGING "Build cycles with logging support" OFF)
+option(WITH_CYCLES_LOGGING "Build Cycles with logging support" ON)
+option(WITH_CYCLES_DEBUG "Build Cycles with extra debug capabilities" OFF)
+option(WITH_CYCLES_WERROR "Treat warnings as errors in Cycles code" OFF)
+mark_as_advanced(WITH_CYCLES_LOGGING)
+mark_as_advanced(WITH_CYCLES_DEBUG)
+mark_as_advanced(WITH_CYCLES_WERROR)
# LLVM
option(WITH_LLVM "Use LLVM" OFF)
@@ -292,7 +400,7 @@ endif()
mark_as_advanced(LLVM_STATIC)
# disable for now, but plan to support on all platforms eventually
-option(WITH_MEM_JEMALLOC "Enable malloc replacement (http://www.canonware.com/jemalloc)" OFF)
+option(WITH_MEM_JEMALLOC "Enable malloc replacement (http://www.canonware.com/jemalloc)" ON)
mark_as_advanced(WITH_MEM_JEMALLOC)
# currently only used for BLI_mempool
@@ -308,14 +416,88 @@ mark_as_advanced(WITH_ASSERT_ABORT)
option(WITH_BOOST "Enable features depending on boost" ON)
-if(CMAKE_COMPILER_IS_GNUCC)
- option(WITH_GCC_MUDFLAP "Enable mudflap" OFF)
- mark_as_advanced(WITH_GCC_MUDFLAP)
-endif()
-
# Unit testsing
option(WITH_GTESTS "Enable GTest unit testing" OFF)
+
+# Documentation
+if(UNIX AND NOT APPLE)
+ option(WITH_DOC_MANPAGE "Create a manual page (Unix manpage)" OFF)
+endif()
+
+
+# OpenGL
+
+option(WITH_GLEW_MX "Support multiple GLEW contexts (experimental)" OFF )
+option(WITH_GLEW_ES "Switches to experimental copy of GLEW that has support for OpenGL ES. (temporary option for development purposes)" OFF)
+option(WITH_GL_EGL "Use the EGL OpenGL system library instead of the platform specific OpenGL system library (CGL, glX, or WGL)" OFF)
+option(WITH_GL_PROFILE_COMPAT "Support using the OpenGL 'compatibility' profile. (deprecated)" ON )
+option(WITH_GL_PROFILE_CORE "Support using the OpenGL 3.2+ 'core' profile." OFF)
+option(WITH_GL_PROFILE_ES20 "Support using OpenGL ES 2.0. (thru either EGL or the AGL/WGL/XGL 'es20' profile)" OFF)
+
+mark_as_advanced(
+ WITH_GLEW_MX
+ WITH_GLEW_ES
+ WITH_GL_EGL
+ WITH_GL_PROFILE_COMPAT
+ WITH_GL_PROFILE_CORE
+ WITH_GL_PROFILE_ES20
+)
+
+if(WITH_GL_PROFILE_COMPAT)
+ set(WITH_GLU ON)
+else()
+ set(WITH_GLU OFF)
+endif()
+
+if(WIN32)
+ option(WITH_GL_ANGLE "Link with the ANGLE library, an OpenGL ES 2.0 implementation based on Direct3D, instead of the system OpenGL library." OFF)
+ mark_as_advanced(WITH_GL_ANGLE)
+endif()
+
+if(WITH_GLEW_ES AND WITH_SYSTEM_GLEW)
+ message(WARNING Ignoring WITH_SYSTEM_GLEW and using WITH_GLEW_ES)
+ set(WITH_SYSTEM_GLEW OFF)
+endif()
+
+if(MSVC)
+ getDefaultWindowsPrefixBase(CMAKE_GENERIC_PROGRAM_FILES)
+ set(CPACK_INSTALL_PREFIX ${CMAKE_GENERIC_PROGRAM_FILES}/${})
+endif()
+
+# Experimental support of C++11
+option(WITH_CPP11 "Build with C++11 standard enabled, for development use only!" OFF)
+mark_as_advanced(WITH_CPP11)
+
+# Dependency graph
+option(WITH_LEGACY_DEPSGRAPH "Build Blender with legacy dependency graph" ON)
+mark_as_advanced(WITH_LEGACY_DEPSGRAPH)
+
+# avoid using again
+option_defaults_clear()
+
+# end option(...)
+
+
+
+# By default we want to install to the directory we are compiling our executables
+# unless specified otherwise, which we currently do not allow
+if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
+ if(MSVC)
+ set(CMAKE_INSTALL_PREFIX ${EXECUTABLE_OUTPUT_PATH}/\${BUILD_TYPE} CACHE PATH "default install path" FORCE)
+ elseif(APPLE)
+ set(CMAKE_INSTALL_PREFIX ${EXECUTABLE_OUTPUT_PATH}/\${BUILD_TYPE} CACHE PATH "default install path" FORCE)
+ else()
+ if(WITH_INSTALL_PORTABLE)
+ set(CMAKE_INSTALL_PREFIX ${EXECUTABLE_OUTPUT_PATH} CACHE PATH "default install path" FORCE)
+ endif()
+ endif()
+endif()
+
+
+
+# Apple
+
if(APPLE)
if(${CMAKE_VERSION} VERSION_LESS 3.0) # else breaks setting CMP0043 policy
cmake_minimum_required(VERSION 2.8.8)
@@ -466,7 +648,7 @@ if(NOT WITH_PYTHON)
set(WITH_CYCLES OFF)
endif()
-# enable boost for cycles, booleans, audaspace or i18n
+# enable boost for cycles, audaspace or i18n
# otherwise if the user disabled
if(NOT WITH_BOOST)
# Explicitly disabled. so disable all deps.
@@ -479,13 +661,12 @@ if(NOT WITH_BOOST)
endmacro()
set_and_warn(WITH_CYCLES OFF)
- set_and_warn(WITH_MOD_BOOLEAN OFF)
set_and_warn(WITH_AUDASPACE OFF)
set_and_warn(WITH_INTERNATIONAL OFF)
set_and_warn(WITH_OPENAL OFF) # depends on AUDASPACE
set_and_warn(WITH_GAMEENGINE OFF) # depends on AUDASPACE
-elseif(WITH_CYCLES OR WITH_OPENIMAGEIO OR WITH_MOD_BOOLEAN OR WITH_AUDASPACE OR WITH_INTERNATIONAL)
+elseif(WITH_CYCLES OR WITH_OPENIMAGEIO OR WITH_AUDASPACE OR WITH_INTERNATIONAL)
# Keep enabled
else()
# Enabled but we don't need it
@@ -495,6 +676,13 @@ endif()
# auto enable openimageio for cycles
if(WITH_CYCLES)
set(WITH_OPENIMAGEIO ON)
+
+ # auto enable llvm for cycles_osl
+ if(WITH_CYCLES_OSL)
+ set(WITH_LLVM ON CACHE BOOL "" FORCE)
+ endif()
+else()
+ set(WITH_CYCLES_OSL OFF)
endif()
# auto enable openimageio linking dependencies
@@ -503,29 +691,60 @@ if(WITH_OPENIMAGEIO)
set(WITH_IMAGE_TIFF ON)
endif()
-# auto enable llvm for cycles_osl
-if(WITH_CYCLES_OSL)
- set(WITH_LLVM ON CACHE BOOL "ON" FORCE)
-endif()
-
# don't store paths to libs for portable distribution
if(WITH_INSTALL_PORTABLE)
set(CMAKE_SKIP_BUILD_RPATH TRUE)
endif()
if(WITH_GHOST_SDL OR WITH_HEADLESS)
- set(WITH_GHOST_XDND OFF)
+ set(WITH_X11 OFF)
+ set(WITH_X11_XINPUT OFF)
set(WITH_X11_XF86VMODE OFF)
- set(WITH_X11_XINPUT OFF)
+ set(WITH_GHOST_XDND OFF)
+ set(WITH_INPUT_IME OFF)
endif()
-TEST_SSE_SUPPORT(COMPILER_SSE_FLAG COMPILER_SSE2_FLAG)
+if(WITH_CPU_SSE)
+ TEST_SSE_SUPPORT(COMPILER_SSE_FLAG COMPILER_SSE2_FLAG)
+else()
+ message(STATUS "SSE and SSE2 optimizations are DISABLED!")
+ set(COMPILER_SSE_FLAG)
+ set(COMPILER_SSE2_FLAG)
+endif()
TEST_STDBOOL_SUPPORT()
if(HAVE_STDBOOL_H)
add_definitions(-DHAVE_STDBOOL_H)
endif()
+if(WITH_AUDASPACE)
+ if(WITH_SYSTEM_AUDASPACE)
+ set(AUDASPACE_DEFINITIONS
+ -DWITH_AUDASPACE
+ -DWITH_SYSTEM_AUDASPACE
+ "-DAUD_DEVICE_H=<AUD_Device.h>"
+ "-DAUD_SPECIAL_H=<AUD_Special.h>"
+ "-DAUD_SOUND_H=<AUD_Sound.h>"
+ "-DAUD_HANDLE_H=<AUD_Handle.h>"
+ "-DAUD_SEQUENCE_H=<AUD_Sequence.h>"
+ "-DAUD_TYPES_H=<AUD_Types.h>"
+ "-DAUD_PYTHON_H=<python/PyAPI.h>"
+ )
+ else()
+ set(AUDASPACE_C_INCLUDE_DIRS "${CMAKE_SOURCE_DIR}/intern/audaspace/intern")
+ set(AUDASPACE_PY_INCLUDE_DIRS "${CMAKE_SOURCE_DIR}/intern/audaspace/intern")
+ set(AUDASPACE_DEFINITIONS
+ -DWITH_AUDASPACE
+ "-DAUD_DEVICE_H=<AUD_C-API.h>"
+ "-DAUD_SPECIAL_H=<AUD_C-API.h>"
+ "-DAUD_SOUND_H=<AUD_C-API.h>"
+ "-DAUD_HANDLE_H=<AUD_C-API.h>"
+ "-DAUD_SEQUENCE_H=<AUD_C-API.h>"
+ "-DAUD_TYPES_H=<AUD_Space.h>"
+ )
+ endif()
+endif()
+
#-----------------------------------------------------------------------------
# Check for valid directories
# ... a partial checkout may cause this.
@@ -598,9 +817,45 @@ set(PLATFORM_LINKFLAGS_DEBUG "")
#-----------------------------------------------------------------------------
#Platform specifics
+if(WITH_X11)
+ find_package(X11 REQUIRED)
+
+ find_path(X11_XF86keysym_INCLUDE_PATH X11/XF86keysym.h ${X11_INC_SEARCH_PATH})
+ mark_as_advanced(X11_XF86keysym_INCLUDE_PATH)
+
+ list(APPEND PLATFORM_LINKLIBS ${X11_X11_LIB})
+
+ if(WITH_X11_XINPUT)
+ if(X11_Xinput_LIB)
+ list(APPEND PLATFORM_LINKLIBS ${X11_Xinput_LIB})
+ else()
+ set(WITH_X11_XINPUT OFF)
+ endif()
+ endif()
+
+ if(WITH_X11_XF86VMODE)
+ # XXX, why dont cmake make this available?
+ find_library(X11_Xxf86vmode_LIB Xxf86vm ${X11_LIB_SEARCH_PATH})
+ mark_as_advanced(X11_Xxf86vmode_LIB)
+ if(X11_Xxf86vmode_LIB)
+ list(APPEND PLATFORM_LINKLIBS ${X11_Xxf86vmode_LIB})
+ else()
+ set(WITH_X11_XF86VMODE OFF)
+ endif()
+ endif()
+
+endif()
+
+
+# ----------------------------------------------------------------------------
+# Main Platform Checks
+#
+# - UNIX
+# - WIN32
+# - APPLE
+
if(UNIX AND NOT APPLE)
macro(find_package_wrapper)
- string(TOUPPER ${ARGV0} _NAME_UPPER)
if(WITH_STATIC_LIBS)
set(_cmake_find_library_suffixes_back ${CMAKE_FIND_LIBRARY_SUFFIXES})
set(CMAKE_FIND_LIBRARY_SUFFIXES .a ${CMAKE_FIND_LIBRARY_SUFFIXES})
@@ -617,6 +872,21 @@ if(UNIX AND NOT APPLE)
find_package_wrapper(ZLIB REQUIRED)
find_package_wrapper(Freetype REQUIRED)
+ if(WITH_LZO AND WITH_SYSTEM_LZO)
+ find_package_wrapper(LZO)
+ if(NOT LZO_FOUND)
+ message(FATAL_ERROR "Failed finding system LZO version!")
+ endif()
+ endif()
+
+ if(WITH_SYSTEM_EIGEN3)
+ find_package_wrapper(Eigen3)
+ if(NOT EIGEN3_FOUND)
+ message(FATAL_ERROR "Failed finding system Eigen3 version!")
+ endif()
+ endif()
+ # else values are set below for all platforms
+
if(WITH_PYTHON)
# No way to set py34. remove for now.
# find_package(PythonLibs)
@@ -652,6 +922,13 @@ if(UNIX AND NOT APPLE)
endif()
# Audio IO
+ if(WITH_SYSTEM_AUDASPACE)
+ find_package_wrapper(Audaspace)
+ if(NOT AUDASPACE_FOUND OR NOT AUDASPACE_C_FOUND)
+ message(FATAL_ERROR "Audaspace external library not found!")
+ endif()
+ endif()
+
if(WITH_OPENAL)
find_package_wrapper(OpenAL)
if(NOT OPENAL_FOUND)
@@ -660,16 +937,27 @@ if(UNIX AND NOT APPLE)
endif()
if(WITH_SDL)
- find_package_wrapper(SDL)
- mark_as_advanced(
- SDLMAIN_LIBRARY
- SDL_INCLUDE_DIR
- SDL_LIBRARY
- SDL_LIBRARY_TEMP
- )
- # unset(SDLMAIN_LIBRARY CACHE)
- if(NOT SDL_FOUND)
- set(WITH_SDL OFF)
+ if(WITH_SDL_DYNLOAD)
+ set(SDL_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/extern/sdlew/include/SDL2")
+ set(SDL_LIBRARY)
+ else()
+ find_package_wrapper(SDL2)
+ if(SDL2_FOUND)
+ # Use same names for both versions of SDL until we move to 2.x.
+ set(SDL_INCLUDE_DIR "${SDL2_INCLUDE_DIR}")
+ set(SDL_LIBRARY "${SDL2_LIBRARY}")
+ set(SDL_FOUND "${SDL2_FOUND}")
+ else()
+ find_package_wrapper(SDL)
+ endif()
+ mark_as_advanced(
+ SDL_INCLUDE_DIR
+ SDL_LIBRARY
+ )
+ # unset(SDLMAIN_LIBRARY CACHE)
+ if(NOT SDL_FOUND)
+ set(WITH_SDL OFF)
+ endif()
endif()
endif()
@@ -703,7 +991,6 @@ if(UNIX AND NOT APPLE)
mark_as_advanced(FFMPEG_LIBRARIES)
set(FFMPEG_LIBPATH ${FFMPEG}/lib)
- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D__STDC_CONSTANT_MACROS")
endif()
if(WITH_FFTW3)
@@ -743,6 +1030,24 @@ if(UNIX AND NOT APPLE)
endif()
endif()
+ if(WITH_CYCLES_OSL)
+ set(CYCLES_OSL ${LIBDIR}/osl CACHE PATH "Path to OpenShadingLanguage installation")
+ if(NOT OSL_ROOT)
+ set(OSL_ROOT ${CYCLES_OSL})
+ endif()
+ find_package_wrapper(OpenShadingLanguage)
+ if(OSL_FOUND)
+ if(${OSL_LIBRARY_VERSION_MAJOR} EQUAL "1" AND ${OSL_LIBRARY_VERSION_MINOR} LESS "6")
+ # Note: --whole-archive is needed to force loading of all symbols in liboslexec,
+ # otherwise LLVM is missing the osl_allocate_closure_component function
+ set(OSL_LIBRARIES ${OSL_OSLCOMP_LIBRARY} -Wl,--whole-archive ${OSL_OSLEXEC_LIBRARY} -Wl,--no-whole-archive ${OSL_OSLQUERY_LIBRARY})
+ endif()
+ else()
+ message(STATUS "OSL not found, disabling it from Cycles")
+ set(WITH_CYCLES_OSL OFF)
+ endif()
+ endif()
+
if(WITH_BOOST)
# uses in build instructions to override include and library variables
if(NOT BOOST_CUSTOM)
@@ -751,6 +1056,12 @@ if(UNIX AND NOT APPLE)
endif()
set(Boost_USE_MULTITHREADED ON)
set(__boost_packages filesystem regex system thread date_time)
+ if(WITH_CYCLES_OSL)
+ if(NOT (${OSL_LIBRARY_VERSION_MAJOR} EQUAL "1" AND ${OSL_LIBRARY_VERSION_MINOR} LESS "6"))
+ list(APPEND __boost_packages wave)
+ else()
+ endif()
+ endif()
if(WITH_INTERNATIONAL)
list(APPEND __boost_packages locale)
endif()
@@ -780,6 +1091,12 @@ if(UNIX AND NOT APPLE)
if(WITH_OPENIMAGEIO)
find_package_wrapper(OpenImageIO)
+ if(NOT OPENIMAGEIO_PUGIXML_FOUND AND WITH_CYCLES_STANDALONE)
+ find_package_wrapper(PugiXML)
+ else()
+ set(PUGIXML_INCLUDE_DIR "${OPENIMAGEIO_INCLUDE_DIR/OpenImageIO}")
+ set(PUGIXML_LIBRARIES "")
+ endif()
set(OPENIMAGEIO_LIBRARIES ${OPENIMAGEIO_LIBRARIES} ${PNG_LIBRARIES} ${JPEG_LIBRARIES} ${ZLIB_LIBRARIES} ${BOOST_LIBRARIES})
set(OPENIMAGEIO_LIBPATH) # TODO, remove and reference the absolute path everywhere
@@ -811,126 +1128,42 @@ if(UNIX AND NOT APPLE)
endif()
endif()
- # XXX Maybe most of this section should go into an llvm module?
if(WITH_LLVM)
- # Set llvm version if not specified
- if(NOT LLVM_VERSION)
- set(LLVM_VERSION "3.0")
- endif()
-
- if(LLVM_DIRECTORY)
- find_program(LLVM_CONFIG llvm-config-${LLVM_VERSION} HINTS ${LLVM_DIRECTORY}/bin NO_CMAKE_PATH)
- if(NOT LLVM_CONFIG)
- find_program(LLVM_CONFIG llvm-config HINTS ${LLVM_DIRECTORY}/bin NO_CMAKE_PATH)
- endif()
- else()
- find_program(LLVM_CONFIG llvm-config-${LLVM_VERSION})
- if(NOT LLVM_CONFIG)
- find_program(LLVM_CONFIG llvm-config)
- endif()
- endif()
+ find_package_wrapper(LLVM)
- if(NOT DEFINED LLVM_VERSION)
- execute_process(COMMAND ${LLVM_CONFIG} --version
- OUTPUT_VARIABLE LLVM_VERSION
- OUTPUT_STRIP_TRAILING_WHITESPACE)
- set(LLVM_VERSION ${LLVM_VERSION} CACHE STRING "Version of LLVM to use")
- endif()
- if(NOT DEFINED LLVM_DIRECTORY)
- execute_process(COMMAND ${LLVM_CONFIG} --prefix
- OUTPUT_VARIABLE LLVM_DIRECTORY
- OUTPUT_STRIP_TRAILING_WHITESPACE)
- set(LLVM_DIRECTORY ${LLVM_DIRECTORY} CACHE PATH "Path to the LLVM installation")
- endif()
- if(NOT DEFINED LLVM_LIBPATH)
- execute_process(COMMAND ${LLVM_CONFIG} --libdir
- OUTPUT_VARIABLE LLVM_LIBPATH
- OUTPUT_STRIP_TRAILING_WHITESPACE)
- set(LLVM_LIBPATH ${LLVM_LIBPATH} CACHE PATH "Path to the LLVM library path")
- mark_as_advanced(LLVM_LIBPATH)
- endif()
-
- if(LLVM_STATIC)
- find_library(LLVM_LIBRARY
- NAMES LLVMAnalysis # first of a whole bunch of libs to get
- PATHS ${LLVM_LIBPATH})
- else()
- find_library(LLVM_LIBRARY
- NAMES LLVM-${LLVM_VERSION}
- PATHS ${LLVM_LIBPATH})
- endif()
-
-
- if(LLVM_LIBRARY AND LLVM_DIRECTORY AND LLVM_LIBPATH)
- if(LLVM_STATIC)
- # if static LLVM libraries were requested, use llvm-config to generate
- # the list of what libraries we need, and substitute that in the right
- # way for LLVM_LIBRARY.
- execute_process(COMMAND ${LLVM_CONFIG} --libfiles
- OUTPUT_VARIABLE LLVM_LIBRARY
- OUTPUT_STRIP_TRAILING_WHITESPACE)
- string(REPLACE " " ";" LLVM_LIBRARY "${LLVM_LIBRARY}")
- endif()
- else()
- message(FATAL_ERROR "LLVM not found.")
+ if(NOT LLVM_FOUND)
+ set(WITH_LLVM OFF)
+ message(STATUS "LLVM not found")
endif()
+ endif()
+ if(WITH_LLVM OR WITH_SDL_DYNLOAD)
# Fix for conflict with Mesa llvmpipe
- set(PLATFORM_LINKFLAGS "${PLATFORM_LINKFLAGS} -Wl,--version-script=${CMAKE_SOURCE_DIR}/source/creator/blender.map")
+ set(PLATFORM_LINKFLAGS "${PLATFORM_LINKFLAGS} -Wl,--version-script='${CMAKE_SOURCE_DIR}/source/creator/blender.map'")
endif()
- if(WITH_CYCLES_OSL)
- set(CYCLES_OSL ${LIBDIR}/osl CACHE PATH "Path to OpenShadingLanguage installation")
-
- message(STATUS "CYCLES_OSL = ${CYCLES_OSL}")
-
- find_library(OSL_LIB_EXEC NAMES oslexec PATHS ${CYCLES_OSL}/lib)
- find_library(OSL_LIB_COMP NAMES oslcomp PATHS ${CYCLES_OSL}/lib)
- find_library(OSL_LIB_QUERY NAMES oslquery PATHS ${CYCLES_OSL}/lib)
- # Note: --whole-archive is needed to force loading of all symbols in liboslexec,
- # otherwise LLVM is missing the osl_allocate_closure_component function
- list(APPEND OSL_LIBRARIES ${OSL_LIB_COMP} -Wl,--whole-archive ${OSL_LIB_EXEC} -Wl,--no-whole-archive ${OSL_LIB_QUERY})
- find_path(OSL_INCLUDES OSL/oslclosure.h PATHS ${CYCLES_OSL}/include)
- find_program(OSL_COMPILER NAMES oslc PATHS ${CYCLES_OSL}/bin)
-
- if(OSL_INCLUDES AND OSL_LIBRARIES AND OSL_COMPILER)
- set(OSL_FOUND TRUE)
- message(STATUS "OSL includes = ${OSL_INCLUDES}")
- message(STATUS "OSL library = ${OSL_LIBRARIES}")
- message(STATUS "OSL compiler = ${OSL_COMPILER}")
- else()
- message(STATUS "OSL not found")
+ if(WITH_OPENSUBDIV)
+ find_package_wrapper(OpenSubdiv)
+
+ set(OPENSUBDIV_LIBRARIES ${OPENSUBDIV_LIBRARIES})
+ set(OPENSUBDIV_LIBPATH) # TODO, remove and reference the absolute path everywhere
+
+ if(NOT OPENSUBDIV_FOUND)
+ set(WITH_OPENSUBDIV OFF)
+ message(STATUS "OpenSubdiv not found")
endif()
endif()
# OpenSuse needs lutil, ArchLinux not, for now keep, can avoid by using --as-needed
- list(APPEND PLATFORM_LINKLIBS -lutil -lc -lm -lpthread)
-
- if((NOT WITH_HEADLESS) AND (NOT WITH_GHOST_SDL))
- find_package(X11 REQUIRED)
- find_path(X11_XF86keysym_INCLUDE_PATH X11/XF86keysym.h ${X11_INC_SEARCH_PATH})
- mark_as_advanced(X11_XF86keysym_INCLUDE_PATH)
+ list(APPEND PLATFORM_LINKLIBS -lutil -lc -lm)
- list(APPEND PLATFORM_LINKLIBS ${X11_X11_LIB})
+ find_package(Threads REQUIRED)
+ list(APPEND PLATFORM_LINKLIBS ${CMAKE_THREAD_LIBS_INIT})
+ # used by other platforms
+ set(PTHREADS_LIBRARIES ${CMAKE_THREAD_LIBS_INIT})
- if(WITH_X11_XINPUT)
- if(X11_Xinput_LIB)
- list(APPEND PLATFORM_LINKLIBS ${X11_Xinput_LIB})
- else()
- set(WITH_X11_XINPUT OFF)
- endif()
- endif()
-
- if(WITH_X11_XF86VMODE)
- # XXX, why dont cmake make this available?
- find_library(X11_Xxf86vmode_LIB Xxf86vm ${X11_LIB_SEARCH_PATH})
- mark_as_advanced(X11_Xxf86vmode_LIB)
- if(X11_Xxf86vmode_LIB)
- list(APPEND PLATFORM_LINKLIBS ${X11_Xxf86vmode_LIB})
- else()
- set(WITH_X11_XF86VMODE OFF)
- endif()
- endif()
+ if(CMAKE_DL_LIBS)
+ list(APPEND PLATFORM_LINKLIBS ${CMAKE_DL_LIBS})
endif()
if(CMAKE_SYSTEM_NAME MATCHES "Linux")
@@ -941,17 +1174,31 @@ if(UNIX AND NOT APPLE)
endif()
endif()
- set(PLATFORM_LINKFLAGS "${PLATFORM_LINKFLAGS} -pthread")
- if(CMAKE_DL_LIBS)
- list(APPEND PLATFORM_LINKLIBS ${CMAKE_DL_LIBS})
- endif()
-
# lfs on glibc, all compilers should use
add_definitions(-D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE64_SOURCE)
# GNU Compiler
if(CMAKE_COMPILER_IS_GNUCC)
set(PLATFORM_CFLAGS "-pipe -fPIC -funsigned-char -fno-strict-aliasing")
+
+ if(NOT "${CMAKE_C_COMPILER_VERSION}" VERSION_LESS "5.0")
+ # GCC5 uses gnu11, until we update, force c89
+ # though some c11 features can still be used.
+ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=gnu89")
+ endif()
+
+ # use ld.gold linker if available, could make optional
+ execute_process(
+ COMMAND ${CMAKE_C_COMPILER} -fuse-ld=gold -Wl,--version
+ ERROR_QUIET OUTPUT_VARIABLE LD_VERSION)
+ if("${LD_VERSION}" MATCHES "GNU gold")
+ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fuse-ld=gold")
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fuse-ld=gold")
+ else()
+ message(STATUS "GNU gold linker isn't available, using the default system linker.")
+ endif()
+ unset(LD_VERSION)
+
# CLang is the same as GCC for now.
elseif(CMAKE_C_COMPILER_ID MATCHES "Clang")
set(PLATFORM_CFLAGS "-pipe -fPIC -funsigned-char -fno-strict-aliasing")
@@ -993,7 +1240,11 @@ elseif(WIN32)
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /SAFESEH:NO")
set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} /SAFESEH:NO")
- list(APPEND PLATFORM_LINKLIBS ws2_32 vfw32 winmm kernel32 user32 gdi32 comdlg32 advapi32 shfolder shell32 ole32 oleaut32 uuid psapi)
+ list(APPEND PLATFORM_LINKLIBS ws2_32 vfw32 winmm kernel32 user32 gdi32 comdlg32 advapi32 shfolder shell32 ole32 oleaut32 uuid psapi Dbghelp)
+
+ if(WITH_INPUT_IME)
+ list(APPEND PLATFORM_LINKLIBS imm32)
+ endif()
add_definitions(
-D_CRT_NONSTDC_NO_DEPRECATE
@@ -1004,18 +1255,16 @@ elseif(WIN32)
)
# MSVC11 needs _ALLOW_KEYWORD_MACROS to build
- if(NOT MSVC_VERSION VERSION_LESS 1700)
- add_definitions(-D_ALLOW_KEYWORD_MACROS)
- endif()
+ add_definitions(-D_ALLOW_KEYWORD_MACROS)
if(CMAKE_CL_64)
# We want to support Vista level ABI for x64
- if(NOT MSVC_VERSION VERSION_LESS 1700)
- add_definitions(-D_WIN32_WINNT=0x600)
- endif()
+ add_definitions(-D_WIN32_WINNT=0x600)
endif()
- add_definitions(-DOIIO_STATIC_BUILD)
+ # Make cmake find the msvc redistributables
+ set(CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS_SKIP TRUE)
+ include(InstallRequiredSystemLibraries)
set(CMAKE_CXX_FLAGS "/nologo /J /Gd /EHsc /MP" CACHE STRING "MSVC MT C++ flags " FORCE)
set(CMAKE_C_FLAGS "/nologo /J /Gd /MP" CACHE STRING "MSVC MT C++ flags " FORCE)
@@ -1037,30 +1286,6 @@ elseif(WIN32)
set(CMAKE_C_FLAGS_MINSIZEREL "/O1 /Ob1 /MT /MP" CACHE STRING "MSVC MT flags " FORCE)
set(CMAKE_C_FLAGS_RELWITHDEBINFO "/O2 /Ob1 /MT /Zi /MP" CACHE STRING "MSVC MT flags " FORCE)
- # most msvc warnings are C & C++
- set(_WARNINGS
- # warning level:
- "/W3"
- "/w34062" # switch statement contains 'default' but no 'case' labels
- # disable:
- "/wd4018" # signed/unsigned mismatch
- "/wd4065" # switch statement contains 'default' but no 'case' labels
- "/wd4127" # conditional expression is constant
- "/wd4181" # qualifier applied to reference type; ignored
- "/wd4200" # zero-sized array in struct/union
- "/wd4244" # conversion from 'type1' to 'type2', possible loss of data
- "/wd4267" # conversion from 'size_t' to 'type', possible loss of data
- "/wd4305" # truncation from 'type1' to 'type2'
- "/wd4800" # forcing value to bool 'true' or 'false'
- # errors:
- "/we4013" # 'function' undefined; assuming extern returning int
- "/we4431" # missing type specifier - int assumed
- )
-
- string(REPLACE ";" " " _WARNINGS "${_WARNINGS}")
- set(C_WARNINGS "${_WARNINGS}")
- set(CXX_WARNINGS "${_WARNINGS}")
- unset(_WARNINGS)
set(PLATFORM_LINKFLAGS "/SUBSYSTEM:CONSOLE /STACK:2097152 /INCREMENTAL:NO /NODEFAULTLIB:msvcrt.lib /NODEFAULTLIB:msvcmrt.lib /NODEFAULTLIB:msvcurt.lib /NODEFAULTLIB:msvcrtd.lib")
@@ -1077,28 +1302,22 @@ elseif(WIN32)
# Setup 64bit and 64bit windows systems
if(CMAKE_CL_64)
message(STATUS "64 bit compiler detected.")
- set(LIBDIR_BASE ${CMAKE_SOURCE_DIR}/../lib/win64)
+ set(LIBDIR ${CMAKE_SOURCE_DIR}/../lib/win64_vc12)
else()
message(STATUS "32 bit compiler detected.")
- set(LIBDIR_BASE ${CMAKE_SOURCE_DIR}/../lib/windows)
- endif()
- if(MSVC12)
- message(STATUS "Visual C++ 2013 detected.")
- set(LIBDIR ${LIBDIR_BASE}_vc12)
- else()
- set(LIBDIR ${LIBDIR_BASE})
+ set(LIBDIR ${CMAKE_SOURCE_DIR}/../lib/windows_vc12)
endif()
else()
message(STATUS using LIBDIR ${LIBDIR})
endif()
# Add each of our libraries to our cmake_prefix_path so find_package() could work
- FILE(GLOB children RELATIVE ${LIBDIR} ${LIBDIR}/*)
- FOREACH(child ${children})
- IF(IS_DIRECTORY ${LIBDIR}/${child})
- LIST(APPEND CMAKE_PREFIX_PATH ${LIBDIR}/${child})
- ENDIF()
- ENDFOREACH()
+ file(GLOB children RELATIVE ${LIBDIR} ${LIBDIR}/*)
+ foreach(child ${children})
+ if(IS_DIRECTORY ${LIBDIR}/${child})
+ list(APPEND CMAKE_PREFIX_PATH ${LIBDIR}/${child})
+ endif()
+ endforeach()
set(ZLIB_INCLUDE_DIRS ${LIBDIR}/zlib/include)
set(ZLIB_LIBRARIES ${LIBDIR}/zlib/lib/libz_st.lib)
@@ -1110,8 +1329,8 @@ elseif(WIN32)
find_package(png)
if(NOT PNG_FOUND)
- set(PNG_PNG_INCLUDE_DIR ${LIBDIR}/png/include)
message(WARNING "Using HARDCODED libpng locations")
+ set(PNG_PNG_INCLUDE_DIR ${LIBDIR}/png/include)
set(PNG_LIBRARIES libpng)
set(PNG "${LIBDIR}/png")
set(PNG_INCLUDE_DIRS "${PNG}/include")
@@ -1198,29 +1417,19 @@ elseif(WIN32)
set(OPENEXR_VERSION "2.1")
find_package(OPENEXR REQUIRED)
if(NOT OPENEXR_FOUND)
- message(WARNING "Using HARDCODED OpenEXR locations")
- set(OPENEXR ${LIBDIR}/openexr)
- set(OPENEXR_INCLUDE_DIR ${OPENEXR}/include)
- set(OPENEXR_INCLUDE_DIRS ${OPENEXR}/include/OpenEXR)
- set(OPENEXR_LIBPATH ${OPENEXR}/lib)
- if(MSVC12)
- set(OPENEXR_LIBRARIES
- ${OPENEXR_LIBPATH}/Iex-2_1.lib
- ${OPENEXR_LIBPATH}/Half.lib
- ${OPENEXR_LIBPATH}/IlmImf-2_1.lib
- ${OPENEXR_LIBPATH}/Imath-2_1.lib
- ${OPENEXR_LIBPATH}/IlmThread-2_1.lib
- )
- else()
+ message(WARNING "Using HARDCODED OpenEXR locations")
+ set(OPENEXR ${LIBDIR}/openexr)
+ set(OPENEXR_INCLUDE_DIR ${OPENEXR}/include)
+ set(OPENEXR_INCLUDE_DIRS ${OPENEXR}/include/OpenEXR)
+ set(OPENEXR_LIBPATH ${OPENEXR}/lib)
set(OPENEXR_LIBRARIES
- ${OPENEXR_LIBPATH}/Iex.lib
+ ${OPENEXR_LIBPATH}/Iex-2_2.lib
${OPENEXR_LIBPATH}/Half.lib
- ${OPENEXR_LIBPATH}/IlmImf.lib
- ${OPENEXR_LIBPATH}/Imath.lib
- ${OPENEXR_LIBPATH}/IlmThread.lib
+ ${OPENEXR_LIBPATH}/IlmImf-2_2.lib
+ ${OPENEXR_LIBPATH}/Imath-2_2.lib
+ ${OPENEXR_LIBPATH}/IlmThread-2_2.lib
)
endif()
- endif(NOT OPENEXR_FOUND)
endif()
if(WITH_IMAGE_TIFF)
@@ -1260,15 +1469,15 @@ elseif(WIN32)
if(WITH_BOOST)
if(WITH_CYCLES_OSL)
set(boost_extra_libs wave)
- endif(WITH_CYCLES_OSL)
+ endif()
if(WITH_INTERNATIONAL)
list(APPEND boost_extra_libs locale)
- endif(WITH_INTERNATIONAL)
+ endif()
set(Boost_USE_STATIC_RUNTIME ON) # prefix lib
set(Boost_USE_MULTITHREADED ON) # suffix -mt
set(Boost_USE_STATIC_LIBS ON) # suffix -s
find_package(Boost COMPONENTS date_time filesystem thread regex system ${boost_extra_libs})
- IF(NOT Boost_FOUND)
+ if(NOT Boost_FOUND)
message(WARNING "USING HARDCODED boost locations")
set(BOOST ${LIBDIR}/boost)
set(BOOST_INCLUDE_DIR ${BOOST}/include)
@@ -1315,19 +1524,22 @@ elseif(WIN32)
set(OPENIMAGEIO_LIBRARIES ${OIIO_OPTIMIZED} ${OIIO_DEBUG})
set(OPENIMAGEIO_LIBPATH ${OPENIMAGEIO}/lib)
set(OPENIMAGEIO_DEFINITIONS "-DUSE_TBB=0")
+ set(OPENCOLORIO_DEFINITIONS "-DOCIO_STATIC_BUILD")
+ set(OPENIMAGEIO_IDIFF "${OPENIMAGEIO}/bin/idiff.exe")
+ add_definitions(-DOIIO_STATIC_BUILD)
endif()
if(WITH_LLVM)
- set(LLVM_DIRECTORY ${LIBDIR}/llvm CACHE PATH "Path to the LLVM installation")
- file(GLOB LLVM_LIBRARY_OPTIMIZED ${LLVM_DIRECTORY}/lib/*.lib)
+ set(LLVM_ROOT_DIR ${LIBDIR}/llvm CACHE PATH "Path to the LLVM installation")
+ file(GLOB LLVM_LIBRARY_OPTIMIZED ${LLVM_ROOT_DIR}/lib/*.lib)
- if(EXISTS ${LLVM_DIRECTORY}/debug/lib)
+ if(EXISTS ${LLVM_ROOT_DIR}/debug/lib)
foreach(LLVM_OPTIMIZED_LIB ${LLVM_LIBRARY_OPTIMIZED})
get_filename_component(LIBNAME ${LLVM_OPTIMIZED_LIB} ABSOLUTE)
list(APPEND LLVM_LIBS optimized ${LIBNAME})
endforeach(LLVM_OPTIMIZED_LIB)
- file(GLOB LLVM_LIBRARY_DEBUG ${LLVM_DIRECTORY}/debug/lib/*.lib)
+ file(GLOB LLVM_LIBRARY_DEBUG ${LLVM_ROOT_DIR}/debug/lib/*.lib)
foreach(LLVM_DEBUG_LIB ${LLVM_LIBRARY_DEBUG})
get_filename_component(LIBNAME ${LLVM_DEBUG_LIB} ABSOLUTE)
@@ -1362,6 +1574,30 @@ elseif(WIN32)
)
endif()
+ if(WITH_OPENSUBDIV)
+ set(OPENSUBDIV_INCLUDE_DIR ${LIBDIR}/opensubdiv/include)
+ set(OPENSUBDIV_LIBPATH ${LIBDIR}/opensubdiv/lib)
+ set(OPENSUBDIV_LIBRARIES ${OPENSUBDIV_LIBPATH}/osdCPU.lib ${OPENSUBDIV_LIBPATH}/osdGPU.lib)
+ find_package(OpenSubdiv)
+ endif()
+
+ if(WITH_SDL)
+ set(SDL ${LIBDIR}/sdl)
+ set(SDL_INCLUDE_DIR ${SDL}/include)
+ set(SDL_LIBRARY SDL2)
+ set(SDL_LIBPATH ${SDL}/lib)
+ endif()
+
+ # Audio IO
+ if(WITH_SYSTEM_AUDASPACE)
+ set(AUDASPACE_INCLUDE_DIRS ${LIBDIR}/audaspace/include/audaspace)
+ set(AUDASPACE_LIBRARIES ${LIBDIR}/audaspace/lib/audaspace.lib)
+ set(AUDASPACE_C_INCLUDE_DIRS ${LIBDIR}/audaspace/include/audaspace)
+ set(AUDASPACE_C_LIBRARIES ${LIBDIR}/audaspace/lib/audaspace-c.lib)
+ set(AUDASPACE_PY_INCLUDE_DIRS ${LIBDIR}/audaspace/include/audaspace)
+ set(AUDASPACE_PY_LIBRARIES ${LIBDIR}/audaspace/lib/audaspace-py.lib)
+ endif()
+
# used in many places so include globally, like OpenGL
blender_include_dirs_sys("${PTHREADS_INCLUDE_DIRS}")
@@ -1379,7 +1615,12 @@ elseif(WIN32)
if(WITH_MINGW64)
message(STATUS "Compiling for 64 bit with MinGW-w64.")
- set(LIBDIR ${CMAKE_SOURCE_DIR}/../lib/mingw64)
+ execute_process(COMMAND ${CMAKE_C_COMPILER} -dumpversion OUTPUT_VARIABLE GCC_VERSION)
+ if(GCC_VERSION VERSION_GREATER 4.9 OR GCC_VERSION VERSION_EQUAL 4.9)
+ set(LIBDIR ${CMAKE_SOURCE_DIR}/../lib/mingw64_gcc49)
+ else()
+ set(LIBDIR ${CMAKE_SOURCE_DIR}/../lib/mingw64)
+ endif()
else()
message(STATUS "Compiling for 32 bit with MinGW-w32.")
set(LIBDIR ${CMAKE_SOURCE_DIR}/../lib/mingw32)
@@ -1389,7 +1630,12 @@ elseif(WIN32)
endif()
endif()
- list(APPEND PLATFORM_LINKLIBS -lshell32 -lshfolder -lgdi32 -lmsvcrt -lwinmm -lmingw32 -lm -lws2_32 -lz -lstdc++ -lole32 -luuid -lwsock32 -lpsapi)
+ list(APPEND PLATFORM_LINKLIBS -lshell32 -lshfolder -lgdi32 -lmsvcrt -lwinmm -lmingw32 -lm -lws2_32 -lz -lstdc++ -lole32 -luuid -lwsock32 -lpsapi -ldbghelp)
+
+ if(WITH_INPUT_IME)
+ list(APPEND PLATFORM_LINKLIBS -limm32)
+ endif()
+
set(PLATFORM_CFLAGS "-pipe -funsigned-char -fno-strict-aliasing")
if(WITH_MINGW64)
@@ -1543,11 +1789,12 @@ elseif(WIN32)
set(OPENIMAGEIO_LIBRARIES OpenImageIO)
set(OPENIMAGEIO_LIBPATH ${OPENIMAGEIO}/lib)
set(OPENIMAGEIO_DEFINITIONS "")
+ set(OPENIMAGEIO_IDIFF "${OPENIMAGEIO}/bin/idiff.exe")
endif()
if(WITH_LLVM)
- set(LLVM_DIRECTORY ${LIBDIR}/llvm CACHE PATH "Path to the LLVM installation")
- set(LLVM_LIBPATH ${LLVM_DIRECTORY}/lib)
+ set(LLVM_ROOT_DIR ${LIBDIR}/llvm CACHE PATH "Path to the LLVM installation")
+ set(LLVM_LIBPATH ${LLVM_ROOT_DIR}/lib)
# Explicitly set llvm lib order.
#---- WARNING ON GCC ORDER OF LIBS IS IMPORTANT, DO NOT CHANGE! ---------
set(LLVM_LIBRARY LLVMSelectionDAG LLVMCodeGen LLVMScalarOpts LLVMAnalysis LLVMArchive
@@ -1580,6 +1827,13 @@ elseif(WIN32)
set(OPENCOLORIO_DEFINITIONS)
endif()
+ if(WITH_SDL)
+ set(SDL ${LIBDIR}/sdl)
+ set(SDL_INCLUDE_DIR ${SDL}/include)
+ set(SDL_LIBRARY SDL)
+ set(SDL_LIBPATH ${SDL}/lib)
+ endif()
+
set(PLATFORM_LINKFLAGS "-Xlinker --stack=2097152")
## DISABLE - causes linking errors
@@ -1611,13 +1865,6 @@ elseif(WIN32)
set(SNDFILE_LIBPATH ${SNDFILE}/lib) # TODO, deprecate
endif()
- if(WITH_SDL)
- set(SDL ${LIBDIR}/sdl)
- set(SDL_INCLUDE_DIR ${SDL}/include)
- set(SDL_LIBRARY SDL)
- set(SDL_LIBPATH ${SDL}/lib)
- endif()
-
if(WITH_RAYOPTIMIZATION AND SUPPORT_SSE_BUILD)
add_definitions(-D__SSE__ -D__MMX__)
endif()
@@ -1632,13 +1879,14 @@ elseif(WIN32)
find_library(OSL_LIB_COMP_DEBUG NAMES oslcomp_d PATHS ${CYCLES_OSL}/lib)
find_library(OSL_LIB_QUERY_DEBUG NAMES oslquery_d PATHS ${CYCLES_OSL}/lib)
list(APPEND OSL_LIBRARIES optimized ${OSL_LIB_COMP} optimized ${OSL_LIB_EXEC} optimized ${OSL_LIB_QUERY} debug ${OSL_LIB_EXEC_DEBUG} debug ${OSL_LIB_COMP_DEBUG} debug ${OSL_LIB_QUERY_DEBUG})
- find_path(OSL_INCLUDES OSL/oslclosure.h PATHS ${CYCLES_OSL}/include)
+ find_path(OSL_INCLUDE_DIR OSL/oslclosure.h PATHS ${CYCLES_OSL}/include)
find_program(OSL_COMPILER NAMES oslc PATHS ${CYCLES_OSL}/bin)
- if(OSL_INCLUDES AND OSL_LIBRARIES AND OSL_COMPILER)
+ if(OSL_INCLUDE_DIR AND OSL_LIBRARIES AND OSL_COMPILER)
set(OSL_FOUND TRUE)
else()
message(STATUS "OSL not found")
+ set(WITH_CYCLES_OSL OFF)
endif()
endif()
@@ -1669,6 +1917,17 @@ elseif(APPLE)
endif()
endif()
+ if(WITH_OPENSUBDIV)
+ set(OPENSUBDIV ${LIBDIR}/opensubdiv)
+ set(OPENSUBDIV_LIBPATH ${OPENSUBDIV}/lib)
+ find_library(OSL_LIB_UTIL NAMES osdutil PATHS ${OPENSUBDIV_LIBPATH})
+ find_library(OSL_LIB_CPU NAMES osdCPU PATHS ${OPENSUBDIV_LIBPATH})
+ find_library(OSL_LIB_GPU NAMES osdGPU PATHS ${OPENSUBDIV_LIBPATH})
+ set(OPENSUBDIV_INCLUDE_DIR ${OPENSUBDIV}/include)
+ set(OPENSUBDIV_INCLUDE_DIRS ${OPENSUBDIV_INCLUDE_DIR})
+ list(APPEND OPENSUBDIV_LIBRARIES ${OSL_LIB_UTIL} ${OSL_LIB_CPU} ${OSL_LIB_GPU})
+ endif()
+
if(WITH_JACK)
find_library(JACK_FRAMEWORK
NAMES jackmp
@@ -1692,14 +1951,14 @@ elseif(APPLE)
if(NOT WITH_PYTHON_MODULE AND NOT WITH_PYTHON_FRAMEWORK)
# normally cached but not since we include them with blender
set(PYTHON_INCLUDE_DIR "${LIBDIR}/python/include/python${PYTHON_VERSION}m")
- # set(PYTHON_BINARY "${LIBDIR}/python/bin/python${PYTHON_VERSION}") # not used yet
+ # set(PYTHON_EXECUTABLE "${LIBDIR}/python/bin/python${PYTHON_VERSION}") # not used yet
set(PYTHON_LIBRARY python${PYTHON_VERSION}m)
set(PYTHON_LIBPATH "${LIBDIR}/python/lib/python${PYTHON_VERSION}")
# set(PYTHON_LINKFLAGS "-u _PyMac_Error") # won't build with this enabled
else()
# module must be compiled against Python framework
set(PYTHON_INCLUDE_DIR "/Library/Frameworks/Python.framework/Versions/${PYTHON_VERSION}/include/python${PYTHON_VERSION}m")
- set(PYTHON_BINARY "/Library/Frameworks/Python.framework/Versions/${PYTHON_VERSION}/bin/python${PYTHON_VERSION}")
+ set(PYTHON_EXECUTABLE "/Library/Frameworks/Python.framework/Versions/${PYTHON_VERSION}/bin/python${PYTHON_VERSION}")
#set(PYTHON_LIBRARY python${PYTHON_VERSION})
set(PYTHON_LIBPATH "/Library/Frameworks/Python.framework/Versions/${PYTHON_VERSION}/lib/python${PYTHON_VERSION}/config-${PYTHON_VERSION}m")
#set(PYTHON_LINKFLAGS "-u _PyMac_Error -framework Python") # won't build with this enabled
@@ -1742,7 +2001,6 @@ elseif(APPLE)
set(FFMPEG_INCLUDE_DIRS ${FFMPEG}/include)
set(FFMPEG_LIBRARIES avcodec avdevice avformat avutil mp3lame swscale x264 xvidcore theora theoradec theoraenc vorbis vorbisenc vorbisfile ogg)
set(FFMPEG_LIBPATH ${FFMPEG}/lib)
- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D__STDC_CONSTANT_MACROS")
endif()
find_library(SYSTEMSTUBS_LIBRARY
@@ -1823,8 +2081,9 @@ elseif(APPLE)
if(WITH_SDL)
set(SDL ${LIBDIR}/sdl)
set(SDL_INCLUDE_DIR ${SDL}/include)
- set(SDL_LIBRARY SDL)
+ set(SDL_LIBRARY SDL2)
set(SDL_LIBPATH ${SDL}/lib)
+ set(PLATFORM_LINKFLAGS "${PLATFORM_LINKFLAGS} -lazy_framework ForceFeedback")
endif()
set(PNG "${LIBDIR}/png")
@@ -1870,6 +2129,7 @@ elseif(APPLE)
set(OPENIMAGEIO_LIBRARIES ${OPENIMAGEIO}/lib/libOpenImageIO.a ${PNG_LIBRARIES} ${JPEG_LIBRARIES} ${TIFF_LIBRARY} ${OPENEXR_LIBRARIES} ${ZLIB_LIBRARIES})
set(OPENIMAGEIO_LIBPATH ${OPENIMAGEIO}/lib ${JPEG_LIBPATH} ${PNG_LIBPATH} ${TIFF_LIBPATH} ${OPENEXR_LIBPATH} ${ZLIB_LIBPATH})
set(OPENIMAGEIO_DEFINITIONS "-DOIIO_STATIC_BUILD")
+ set(OPENIMAGEIO_IDIFF "${LIBDIR}/openimageio/bin/idiff")
endif()
if(WITH_OPENCOLORIO)
@@ -1877,14 +2137,13 @@ elseif(APPLE)
set(OPENCOLORIO_INCLUDE_DIRS ${OPENCOLORIO}/include)
set(OPENCOLORIO_LIBRARIES OpenColorIO tinyxml yaml-cpp)
set(OPENCOLORIO_LIBPATH ${OPENCOLORIO}/lib)
- set(OPENCOLORIO_DEFINITIONS "-DOCIO_STATIC_BUILD")
endif()
if(WITH_LLVM)
- set(LLVM_DIRECTORY ${LIBDIR}/llvm CACHE PATH "Path to the LLVM installation")
+ set(LLVM_ROOT_DIR ${LIBDIR}/llvm CACHE PATH "Path to the LLVM installation")
set(LLVM_VERSION "3.4" CACHE STRING "Version of LLVM to use")
- if(EXISTS "${LLVM_DIRECTORY}/bin/llvm-config")
- set(LLVM_CONFIG "${LLVM_DIRECTORY}/bin/llvm-config")
+ if(EXISTS "${LLVM_ROOT_DIR}/bin/llvm-config")
+ set(LLVM_CONFIG "${LLVM_ROOT_DIR}/bin/llvm-config")
else()
set(LLVM_CONFIG llvm-config)
endif()
@@ -1892,7 +2151,7 @@ elseif(APPLE)
OUTPUT_VARIABLE LLVM_VERSION
OUTPUT_STRIP_TRAILING_WHITESPACE)
execute_process(COMMAND ${LLVM_CONFIG} --prefix
- OUTPUT_VARIABLE LLVM_DIRECTORY
+ OUTPUT_VARIABLE LLVM_ROOT_DIR
OUTPUT_STRIP_TRAILING_WHITESPACE)
execute_process(COMMAND ${LLVM_CONFIG} --libdir
OUTPUT_VARIABLE LLVM_LIBPATH
@@ -1901,7 +2160,7 @@ elseif(APPLE)
NAMES LLVMAnalysis # first of a whole bunch of libs to get
PATHS ${LLVM_LIBPATH})
- if(LLVM_LIBRARY AND LLVM_DIRECTORY AND LLVM_LIBPATH)
+ if(LLVM_LIBRARY AND LLVM_ROOT_DIR AND LLVM_LIBPATH)
if(LLVM_STATIC)
# if static LLVM libraries were requested, use llvm-config to generate
# the list of what libraries we need, and substitute that in the right
@@ -1926,13 +2185,14 @@ elseif(APPLE)
find_library(OSL_LIB_QUERY NAMES oslquery PATHS ${CYCLES_OSL}/lib)
# WARNING! depends on correct order of OSL libs linking
list(APPEND OSL_LIBRARIES ${OSL_LIB_COMP} -force_load ${OSL_LIB_EXEC} ${OSL_LIB_QUERY})
- find_path(OSL_INCLUDES OSL/oslclosure.h PATHS ${CYCLES_OSL}/include)
+ find_path(OSL_INCLUDE_DIR OSL/oslclosure.h PATHS ${CYCLES_OSL}/include)
find_program(OSL_COMPILER NAMES oslc PATHS ${CYCLES_OSL}/bin)
- if(OSL_INCLUDES AND OSL_LIBRARIES AND OSL_COMPILER)
+ if(OSL_INCLUDE_DIR AND OSL_LIBRARIES AND OSL_COMPILER)
set(OSL_FOUND TRUE)
else()
message(STATUS "OSL not found")
+ set(WITH_CYCLES_OSL OFF)
endif()
endif()
@@ -1951,7 +2211,7 @@ elseif(APPLE)
link_directories(${LIBDIR}/openmp/lib)
# This is a workaround for our helperbinaries ( datatoc, masgfmt, ... ),
# They are linked also to omp lib, so we need it in builddir for runtime exexcution, TODO: remove all unneeded dependencies from these
- execute_process(COMMAND ditto -arch ${CMAKE_OSX_ARCHITECTURES} ${LIBDIR}/openmp/lib/libiomp5.dylib ${CMAKE_BINARY_DIR}/bin/libiomp5.dylib) # for intermediate binaries, lib id @loader_path
+ execute_process(COMMAND ditto -arch ${CMAKE_OSX_ARCHITECTURES} ${LIBDIR}/openmp/lib/libiomp5.dylib ${CMAKE_BINARY_DIR}/Resources/lib/libiomp5.dylib) # for intermediate binaries, in respect to lib ID
endif()
endif()
endif()
@@ -2060,9 +2320,14 @@ endif()
if(WITH_IMAGE_OPENJPEG)
if(WITH_SYSTEM_OPENJPEG)
# dealt with above
+ set(OPENJPEG_DEFINES "")
else()
set(OPENJPEG_INCLUDE_DIRS "${CMAKE_SOURCE_DIR}/extern/libopenjpeg")
- add_definitions(-DOPJ_STATIC)
+ set(OPENJPEG_DEFINES "-DOPJ_STATIC")
+ endif()
+ # Special handling of Windows platform where openjpeg is always static.
+ if(WIN32)
+ set(OPENJPEG_DEFINES "-DOPJ_STATIC")
endif()
endif()
@@ -2071,13 +2336,129 @@ if(WITH_IMAGE_REDCODE)
set(REDCODE_INC ${REDCODE})
endif()
+if(NOT WITH_SYSTEM_EIGEN3)
+ set(EIGEN3_INCLUDE_DIRS ${CMAKE_SOURCE_DIR}/extern/Eigen3)
+endif()
#-----------------------------------------------------------------------------
# Configure OpenGL.
+
find_package(OpenGL)
blender_include_dirs_sys("${OPENGL_INCLUDE_DIR}")
-# unset(OPENGL_LIBRARIES CACHE) # not compat with older cmake
-# unset(OPENGL_xmesa_INCLUDE_DIR CACHE) # not compat with older cmake
+
+if(WITH_GLU)
+ list(APPEND BLENDER_GL_LIBRARIES "${OPENGL_glu_LIBRARY}")
+ list(APPEND GL_DEFINITIONS -DWITH_GLU)
+endif()
+
+if(WITH_SYSTEM_GLES)
+ find_package_wrapper(OpenGLES)
+endif()
+
+if(WITH_GL_PROFILE_COMPAT OR WITH_GL_PROFILE_CORE)
+ list(APPEND BLENDER_GL_LIBRARIES "${OPENGL_gl_LIBRARY}")
+
+elseif(WITH_GL_PROFILE_ES20)
+ if(WITH_SYSTEM_GLES)
+ if(NOT OPENGLES_LIBRARY)
+ message(FATAL_ERROR "Unable to find OpenGL ES libraries. Install them or disable WITH_SYSTEM_GLES.")
+ endif()
+
+ list(APPEND BLENDER_GL_LIBRARIES OPENGLES_LIBRARY)
+
+ else()
+ set(OPENGLES_LIBRARY "" CACHE FILEPATH "OpenGL ES 2.0 library file")
+ mark_as_advanced(OPENGLES_LIBRARY)
+
+ list(APPEND BLENDER_GL_LIBRARIES "${OPENGLES_LIBRARY}")
+
+ if(NOT OPENGLES_LIBRARY)
+ message(FATAL_ERROR "To compile WITH_GL_EGL you need to set OPENGLES_LIBRARY to the file path of an OpenGL ES 2.0 library.")
+ endif()
+
+ endif()
+
+ if(WIN32)
+ # Setup paths to files needed to install and redistribute Windows Blender with OpenGL ES
+
+ set(OPENGLES_DLL "" CACHE FILEPATH "OpenGL ES 2.0 redistributable DLL file")
+ mark_as_advanced(OPENGLES_DLL)
+
+ if(NOT OPENGLES_DLL)
+ message(FATAL_ERROR "To compile WITH_GL_PROFILE_ES20 you need to set OPENGLES_DLL to the file path of an OpenGL ES 2.0 runtime dynamic link library (DLL).")
+ endif()
+
+ if(WITH_GL_ANGLE)
+ list(APPEND GL_DEFINITIONS -DWITH_ANGLE)
+
+ set(D3DCOMPILER_DLL "" CACHE FILEPATH "Direct3D Compiler redistributable DLL file (needed by ANGLE)")
+
+ get_filename_component(D3DCOMPILER_FILENAME "${D3DCOMPILER_DLL}" NAME)
+ list(APPEND GL_DEFINITIONS "-DD3DCOMPILER=\"\\\"${D3DCOMPILER_FILENAME}\\\"\"")
+
+ mark_as_advanced(D3DCOMPILER_DLL)
+
+ if(D3DCOMPILER_DLL STREQUAL "")
+ message(FATAL_ERROR "To compile WITH_GL_ANGLE you need to set D3DCOMPILER_DLL to the file path of a copy of the DirectX redistributable DLL file: D3DCompiler_46.dll")
+ endif()
+
+ endif()
+
+ endif()
+
+endif()
+
+if(WITH_GL_EGL)
+ list(APPEND GL_DEFINITIONS -DWITH_GL_EGL)
+
+ if(WITH_SYSTEM_GLES)
+ if(NOT OPENGLES_EGL_LIBRARY)
+ message(FATAL_ERROR "Unable to find OpenGL ES libraries. Install them or disable WITH_SYSTEM_GLES.")
+ endif()
+
+ list(APPEND BLENDER_GL_LIBRARIES OPENGLES_EGL_LIBRARY)
+
+ else()
+ set(OPENGLES_EGL_LIBRARY "" CACHE FILEPATH "EGL library file")
+ mark_as_advanced(OPENGLES_EGL_LIBRARY)
+
+ list(APPEND BLENDER_GL_LIBRARIES "${OPENGLES_LIBRARY}" "${OPENGLES_EGL_LIBRARY}")
+
+ if(NOT OPENGLES_EGL_LIBRARY)
+ message(FATAL_ERROR "To compile WITH_GL_EGL you need to set OPENGLES_EGL_LIBRARY to the file path of an EGL library.")
+ endif()
+
+ endif()
+
+ if(WIN32)
+ # Setup paths to files needed to install and redistribute Windows Blender with OpenGL ES
+
+ set(OPENGLES_EGL_DLL "" CACHE FILEPATH "EGL redistributable DLL file")
+ mark_as_advanced(OPENGLES_EGL_DLL)
+
+ if(NOT OPENGLES_EGL_DLL)
+ message(FATAL_ERROR "To compile WITH_GL_EGL you need to set OPENGLES_EGL_DLL to the file path of an EGL runtime dynamic link library (DLL).")
+ endif()
+
+ endif()
+
+endif()
+
+if(WITH_GL_PROFILE_COMPAT)
+ list(APPEND GL_DEFINITIONS -DWITH_GL_PROFILE_COMPAT)
+endif()
+
+if(WITH_GL_PROFILE_CORE)
+ list(APPEND GL_DEFINITIONS -DWITH_GL_PROFILE_CORE)
+endif()
+
+if(WITH_GL_PROFILE_ES20)
+ list(APPEND GL_DEFINITIONS -DWITH_GL_PROFILE_ES20)
+endif()
+
+if(WITH_GL_EGL)
+ list(APPEND GL_DEFINITIONS -DWITH_EGL)
+endif()
#-----------------------------------------------------------------------------
# Configure OpenMP.
@@ -2099,19 +2480,76 @@ endif()
#-----------------------------------------------------------------------------
# Configure GLEW
+if(WITH_GLEW_MX)
+ list(APPEND GL_DEFINITIONS -DWITH_GLEW_MX)
+endif()
+
if(WITH_SYSTEM_GLEW)
find_package(GLEW)
+ # Note: There is an assumption here that the system GLEW is not a static library.
+
if(NOT GLEW_FOUND)
- message(FATAL_ERROR "GLEW is required to build blender, install it or disable WITH_SYSTEM_GLEW")
+ message(FATAL_ERROR "GLEW is required to build Blender. Install it or disable WITH_SYSTEM_GLEW.")
endif()
- set(GLEW_INCLUDE_PATH "${GLEW_INCLUDE_DIRS}")
+ if(WITH_GLEW_MX)
+ set(BLENDER_GLEW_LIBRARIES ${GLEW_MX_LIBRARY})
+ else()
+ set(BLENDER_GLEW_LIBRARIES ${GLEW_LIBRARY})
+ endif()
else()
- # set(GLEW_LIBRARY "") # unused
- set(GLEW_INCLUDE_PATH "${CMAKE_SOURCE_DIR}/extern/glew/include")
+ if(WITH_GLEW_ES)
+ set(GLEW_INCLUDE_PATH "${CMAKE_SOURCE_DIR}/extern/glew-es/include")
+
+ list(APPEND GL_DEFINITIONS -DGLEW_STATIC -DWITH_GLEW_ES)
+
+ # These definitions remove APIs from glew.h, making GLEW smaller, and catching unguarded API usage
+ if(NOT WITH_GL_PROFILE_ES20)
+ # No ES functions are needed
+ list(APPEND GL_DEFINITIONS -DGLEW_NO_ES)
+ elseif(NOT (WITH_GL_PROFILE_CORE OR WITH_GL_PROFILE_COMPAT))
+ # ES is enabled, but the other functions are all disabled
+ list(APPEND GL_DEFINITIONS -DGLEW_ES_ONLY)
+ endif()
+
+ if(WITH_GL_PROFILE_ES20)
+ if(WITH_GL_EGL)
+ list(APPEND GL_DEFINITIONS -DGLEW_USE_LIB_ES20)
+ endif()
+
+ # ToDo: This is an experiment to eliminate ES 1 symbols,
+ # GLEW doesn't really properly provide this level of control
+ # (for example, without modification it eliminates too many symbols)
+ # so there are lots of modifications to GLEW to make this work,
+ # and no attempt to make it work beyond Blender at this point.
+ list(APPEND GL_DEFINITIONS -DGL_ES_VERSION_1_0=0 -DGL_ES_VERSION_CL_1_1=0 -DGL_ES_VERSION_CM_1_1=0)
+ endif()
+
+ if(WITH_GL_EGL)
+ list(APPEND GL_DEFINITIONS -DGLEW_INC_EGL)
+ endif()
+
+ set(BLENDER_GLEW_LIBRARIES extern_glew_es bf_intern_glew_mx)
+
+ else()
+ set(GLEW_INCLUDE_PATH "${CMAKE_SOURCE_DIR}/extern/glew/include")
+
+ list(APPEND GL_DEFINITIONS -DGLEW_STATIC)
+
+ # This won't affect the non-experimental glew library,
+ # but is used for conditional compilation elsewhere.
+ list(APPEND GL_DEFINITIONS -DGLEW_NO_ES)
+
+ set(BLENDER_GLEW_LIBRARIES extern_glew)
+
+ endif()
+
endif()
+if(NOT WITH_GLU)
+ list(APPEND GL_DEFINITIONS -DGLEW_NO_GLU)
+endif()
#-----------------------------------------------------------------------------
# Configure Bullet
@@ -2158,6 +2596,7 @@ if(CMAKE_COMPILER_IS_GNUCC)
ADD_CHECK_C_COMPILER_FLAG(C_WARNINGS C_WARN_MISSING_INCLUDE_DIRS -Wmissing-include-dirs)
ADD_CHECK_C_COMPILER_FLAG(C_WARNINGS C_WARN_NO_DIV_BY_ZERO -Wno-div-by-zero)
ADD_CHECK_C_COMPILER_FLAG(C_WARNINGS C_WARN_TYPE_LIMITS -Wtype-limits)
+ ADD_CHECK_C_COMPILER_FLAG(C_WARNINGS C_WARN_FORMAT_SIGN -Wformat-signedness)
# gcc 4.2 gives annoying warnings on every file with this
if(NOT "${CMAKE_C_COMPILER_VERSION}" VERSION_LESS "4.3")
@@ -2185,6 +2624,16 @@ if(CMAKE_COMPILER_IS_GNUCC)
ADD_CHECK_CXX_COMPILER_FLAG(CXX_WARNINGS CXX_WARN_MISSING_INCLUDE_DIRS -Wmissing-include-dirs)
ADD_CHECK_CXX_COMPILER_FLAG(CXX_WARNINGS CXX_WARN_NO_DIV_BY_ZERO -Wno-div-by-zero)
ADD_CHECK_CXX_COMPILER_FLAG(CXX_WARNINGS CXX_WARN_TYPE_LIMITS -Wtype-limits)
+ ADD_CHECK_CXX_COMPILER_FLAG(CXX_WARNINGS CXX_WARN_ERROR_RETURN_TYPE -Werror=return-type)
+ ADD_CHECK_CXX_COMPILER_FLAG(CXX_WARNINGS CXX_WARN_ERROR_DECLARATION_AFTER_STATEMENT -Werror=declaration-after-statement)
+ ADD_CHECK_CXX_COMPILER_FLAG(CXX_WARNINGS CXX_WARN_ERROR_IMPLICIT_FUNCTION_DECLARATION -Werror=implicit-function-declaration)
+ ADD_CHECK_CXX_COMPILER_FLAG(CXX_WARNINGS CXX_WARN_NO_CHAR_SUBSCRIPTS -Wno-char-subscripts)
+ ADD_CHECK_CXX_COMPILER_FLAG(CXX_WARNINGS CXX_WARN_NO_UNKNOWN_PRAGMAS -Wno-unknown-pragmas)
+ ADD_CHECK_CXX_COMPILER_FLAG(CXX_WARNINGS CXX_WARN_POINTER_ARITH -Wpointer-arith)
+ ADD_CHECK_CXX_COMPILER_FLAG(CXX_WARNINGS CXX_WARN_UNUSED_PARAMETER -Wunused-parameter)
+ ADD_CHECK_CXX_COMPILER_FLAG(CXX_WARNINGS CXX_WARN_WRITE_STRINGS -Wwrite-strings)
+ ADD_CHECK_CXX_COMPILER_FLAG(CXX_WARNINGS CXX_WARN_UNDEF -Wundef)
+ ADD_CHECK_CXX_COMPILER_FLAG(CXX_WARNINGS CXX_WARN_FORMAT_SIGN -Wformat-signedness)
# gcc 4.2 gives annoying warnings on every file with this
if(NOT "${CMAKE_C_COMPILER_VERSION}" VERSION_LESS "4.3")
@@ -2267,7 +2716,31 @@ elseif(CMAKE_C_COMPILER_ID MATCHES "Intel")
# disable numbered, false positives
set(C_WARNINGS "${C_WARNINGS} -wd188,186,144,913,556")
set(CXX_WARNINGS "${CXX_WARNINGS} -wd188,186,144,913,556")
+elseif(CMAKE_C_COMPILER_ID MATCHES "MSVC")
+ # most msvc warnings are C & C++
+ set(_WARNINGS
+ # warning level:
+ "/W3"
+ "/w34062" # switch statement contains 'default' but no 'case' labels
+ # disable:
+ "/wd4018" # signed/unsigned mismatch
+ "/wd4065" # switch statement contains 'default' but no 'case' labels
+ "/wd4127" # conditional expression is constant
+ "/wd4181" # qualifier applied to reference type; ignored
+ "/wd4200" # zero-sized array in struct/union
+ "/wd4244" # conversion from 'type1' to 'type2', possible loss of data
+ "/wd4267" # conversion from 'size_t' to 'type', possible loss of data
+ "/wd4305" # truncation from 'type1' to 'type2'
+ "/wd4800" # forcing value to bool 'true' or 'false'
+ # errors:
+ "/we4013" # 'function' undefined; assuming extern returning int
+ "/we4431" # missing type specifier - int assumed
+ )
+ string(REPLACE ";" " " _WARNINGS "${_WARNINGS}")
+ set(C_WARNINGS "${_WARNINGS}")
+ set(CXX_WARNINGS "${_WARNINGS}")
+ unset(_WARNINGS)
endif()
# ensure python header is found since detection can fail, this could happen
@@ -2294,11 +2767,14 @@ if(WITH_PYTHON)
endif()
endif()
-if(WITH_GCC_MUDFLAP)
- set(PLATFORM_CFLAGS "${PLATFORM_CFLAGS} -fmudflapth -funwind-tables")
- set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -lpthread -lmudflapth -rdynamic")
- ADD_CHECK_C_COMPILER_FLAG(C_WARNINGS C_WARN_NO_ERROR_MUDFLAP -Wno-error=mudflap)
- ADD_CHECK_CXX_COMPILER_FLAG(CXX_WARNINGS CXX_WARN_NO_ERROR_MUDFLAP -Wno-error=mudflap)
+if(WITH_CPP11)
+ if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_C_COMPILER_ID MATCHES "Clang")
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
+ elseif(MSVC12)
+ # Nothing special is needed, C++11 features are available by default.
+ else()
+ message(FATAL_ERROR "Compiler ${CMAKE_C_COMPILER_ID} is not supported for C++11 build yet")
+ endif()
endif()
# Include warnings first, so its possible to disable them with user defined flags
@@ -2313,12 +2789,12 @@ mark_as_advanced(
OSL_COMPILER
OSL_LIB_COMP
OSL_LIB_QUERY
- OSL_INCLUDES
+ OSL_INCLUDE_DIR
)
mark_as_advanced(
LLVM_CONFIG
- LLVM_DIRECTORY
+ LLVM_ROOT_DIR
LLVM_LIBRARY
LLVM_VERSION
)
@@ -2390,25 +2866,29 @@ include(build_files/cmake/packaging.cmake)
# Print Final Configuration
if(FIRST_RUN)
- set(_config_msg "\n* Blender Configuration *")
- macro(info_cfg_option
- _setting)
- set(_msg " * ${_setting}")
+
+ set(_config_msg "\nBlender Configuration\n=====================")
+
+ function(info_cfg_option
+ _setting
+ )
+
+ set(_msg " - ${_setting}")
string(LENGTH "${_msg}" _len)
while("32" GREATER "${_len}")
set(_msg "${_msg} ")
math(EXPR _len "${_len} + 1")
endwhile()
- set(_config_msg "${_config_msg}\n${_msg}${${_setting}}")
- endmacro()
+ set(_config_msg "${_config_msg}\n${_msg}${${_setting}}" PARENT_SCOPE)
+ endfunction()
- macro(info_cfg_text
- _text)
- set(_config_msg "${_config_msg}\n\n ${_text}")
+ function(info_cfg_text
+ _text
+ )
-
- endmacro()
+ set(_config_msg "${_config_msg}\n\n ${_text}" PARENT_SCOPE)
+ endfunction()
message(STATUS "C Compiler: \"${CMAKE_C_COMPILER_ID}\"")
message(STATUS "C++ Compiler: \"${CMAKE_CXX_COMPILER_ID}\"")
@@ -2454,6 +2934,7 @@ if(FIRST_RUN)
info_cfg_text("Audio:")
info_cfg_option(WITH_OPENAL)
info_cfg_option(WITH_SDL)
+ info_cfg_option(WITH_SDL_DYNLOAD)
info_cfg_option(WITH_JACK)
info_cfg_option(WITH_JACK_DYNLOAD)
info_cfg_option(WITH_CODEC_AVI)
@@ -2479,6 +2960,17 @@ if(FIRST_RUN)
info_cfg_option(WITH_MOD_FLUID)
info_cfg_option(WITH_MOD_OCEANSIM)
+ info_cfg_text("OpenGL:")
+ info_cfg_option(WITH_GLEW_ES)
+ info_cfg_option(WITH_GLU)
+ info_cfg_option(WITH_GL_EGL)
+ info_cfg_option(WITH_GL_PROFILE_COMPAT)
+ info_cfg_option(WITH_GL_PROFILE_CORE)
+ info_cfg_option(WITH_GL_PROFILE_ES20)
+ if(WIN32)
+ info_cfg_option(WITH_GL_ANGLE)
+ endif()
+
info_cfg_text("Other:")
info_cfg_option(WITH_OPENNL)
@@ -2489,3 +2981,8 @@ if(FIRST_RUN)
message("${_config_msg}")
endif()
+
+if(0)
+ print_all_vars()
+endif()
+
diff --git a/GNUmakefile b/GNUmakefile
index fb38c8ae0f1..c73aaa7bfbb 100644
--- a/GNUmakefile
+++ b/GNUmakefile
@@ -43,6 +43,11 @@ ifndef BUILD_DIR
BUILD_DIR:=$(shell dirname "$(BLENDER_DIR)")/build_$(OS_NCASE)
endif
+# Allow to use alternative binary (pypy3, etc)
+ifndef PYTHON
+ PYTHON:=python3
+endif
+
# -----------------------------------------------------------------------------
# additional targets for the build configuration
@@ -52,6 +57,10 @@ ifneq "$(findstring debug, $(MAKECMDGOALS))" ""
BUILD_DIR:=$(BUILD_DIR)_debug
BUILD_TYPE:=Debug
endif
+ifneq "$(findstring full, $(MAKECMDGOALS))" ""
+ BUILD_DIR:=$(BUILD_DIR)_full
+ BUILD_CMAKE_ARGS:=$(BUILD_CMAKE_ARGS) -C"$(BLENDER_DIR)/build_files/cmake/config/blender_full.cmake"
+endif
ifneq "$(findstring lite, $(MAKECMDGOALS))" ""
BUILD_DIR:=$(BUILD_DIR)_lite
BUILD_CMAKE_ARGS:=$(BUILD_CMAKE_ARGS) -C"$(BLENDER_DIR)/build_files/cmake/config/blender_lite.cmake"
@@ -61,7 +70,7 @@ ifneq "$(findstring cycles, $(MAKECMDGOALS))" ""
BUILD_CMAKE_ARGS:=$(BUILD_CMAKE_ARGS) -C"$(BLENDER_DIR)/build_files/cmake/config/cycles_standalone.cmake"
endif
ifneq "$(findstring headless, $(MAKECMDGOALS))" ""
- BUILD_DIR:=$(BUILD_DIR)_bpy
+ BUILD_DIR:=$(BUILD_DIR)_headless
BUILD_CMAKE_ARGS:=$(BUILD_CMAKE_ARGS) -C"$(BLENDER_DIR)/build_files/cmake/config/blender_headless.cmake"
endif
ifneq "$(findstring bpy, $(MAKECMDGOALS))" ""
@@ -72,18 +81,20 @@ endif
# -----------------------------------------------------------------------------
# Get the number of cores for threaded build
-NPROCS:=1
-ifeq ($(OS), Linux)
- NPROCS:=$(shell nproc)
-endif
-ifeq ($(OS), Darwin)
- NPROCS:=$(shell sysctl -a | grep "hw.ncpu" | cut -d" " -f3)
-endif
-ifeq ($(OS), FreeBSD)
- NPROCS:=$(shell sysctl -a | grep "hw.ncpu" | cut -d" " -f2 )
-endif
-ifeq ($(OS), NetBSD)
- NPROCS:=$(shell sysctl -a | grep "hw.ncpu" | cut -d" " -f2 )
+ifndef NPROCS
+ NPROCS:=1
+ ifeq ($(OS), Linux)
+ NPROCS:=$(shell nproc)
+ endif
+ ifeq ($(OS), Darwin)
+ NPROCS:=$(shell sysctl -a | grep "hw.ncpu" | cut -d" " -f3)
+ endif
+ ifeq ($(OS), FreeBSD)
+ NPROCS:=$(shell sysctl -a | grep "hw.ncpu" | cut -d" " -f2 )
+ endif
+ ifeq ($(OS), NetBSD)
+ NPROCS:=$(shell sysctl -a | grep "hw.ncpu" | cut -d" " -f2 )
+ endif
endif
@@ -109,16 +120,16 @@ endif
# -----------------------------------------------------------------------------
# Build Blender
-all:
+all: FORCE
@echo
- @echo Configuring Blender ...
+ @echo Configuring Blender in \"$(BUILD_DIR)\" ...
- # if test ! -f $(BUILD_DIR)/CMakeCache.txt ; then \
- # $(CMAKE_CONFIG); \
- # fi
+# # if test ! -f $(BUILD_DIR)/CMakeCache.txt ; then \
+# # $(CMAKE_CONFIG); \
+# # fi
- # do this always incase of failed initial build, could be smarter here...
- $(CMAKE_CONFIG)
+# # do this always incase of failed initial build, could be smarter here...
+ @$(CMAKE_CONFIG)
@echo
@echo Building Blender ...
@@ -129,6 +140,7 @@ all:
@echo
debug: all
+full: all
lite: all
cycles: all
headless: all
@@ -137,16 +149,17 @@ bpy: all
# -----------------------------------------------------------------------------
# Configuration (save some cd'ing around)
-config:
+config: FORCE
$(CMAKE_CONFIG_TOOL) "$(BUILD_DIR)"
# -----------------------------------------------------------------------------
# Help for build targets
-help:
+help: FORCE
@echo ""
@echo "Convenience targets provided for building blender, (multiple at once can be used)"
@echo " * debug - build a debug binary"
+ @echo " * full - enable all supported dependencies & options"
@echo " * lite - disable non essential features for a smaller binary and faster build"
@echo " * headless - build without an interface (renderfarm or server automation)"
@echo " * cycles - build Cycles standalone only, without Blender"
@@ -165,7 +178,7 @@ help:
@echo ""
@echo "Package Targets"
@echo " * package_debian - build a debian package"
- @echo " * package_pacman - build an arch linux pacmanpackage"
+ @echo " * package_pacman - build an arch linux pacman package"
@echo " * package_archive - build an archive package"
@echo ""
@echo "Testing Targets (not associated with building blender)"
@@ -195,23 +208,33 @@ help:
@echo " * tgz - create a compressed archive of the source code."
@echo " * update - updates git and all submodules"
@echo ""
+ @echo "Environment Variables"
+ @echo " * BUILD_CMAKE_ARGS - arguments passed to CMake."
+ @echo " * BUILD_DIR - override default build path."
+ @echo " * PYTHON - use this for the Python command (used for checking tools)."
+ @echo " * NPROCS - number of processes to use building (auto-detect when omitted)."
+ @echo ""
@echo "Documentation Targets (not associated with building blender)"
@echo " * doc_py - generate sphinx python api docs"
@echo " * doc_doxy - generate doxygen C/C++ docs"
@echo " * doc_dna - generate blender file format reference"
@echo " * doc_man - generate manpage"
@echo ""
+ @echo "Information"
+ @echo " * help - this help message"
+ @echo " * help_features - show a list of optional features when building"
+ @echo ""
# -----------------------------------------------------------------------------
# Packages
#
-package_debian:
+package_debian: FORCE
cd build_files/package_spec ; DEB_BUILD_OPTIONS="parallel=$(NPROCS)" sh ./build_debian.sh
-package_pacman:
- cd build_files/package_spec/pacman ; MAKEFLAGS="-j$(NPROCS)" makepkg --asroot
+package_pacman: FORCE
+ cd build_files/package_spec/pacman ; MAKEFLAGS="-j$(NPROCS)" makepkg
-package_archive:
+package_archive: FORCE
make -C "$(BUILD_DIR)" -s package_archive
@echo archive in "$(BUILD_DIR)/release"
@@ -219,35 +242,35 @@ package_archive:
# -----------------------------------------------------------------------------
# Tests
#
-test:
+test: FORCE
cd $(BUILD_DIR) ; ctest . --output-on-failure
# run pep8 check check on scripts we distribute.
-test_pep8:
- python3 tests/python/pep8.py > test_pep8.log 2>&1
+test_pep8: FORCE
+ $(PYTHON) tests/python/pep8.py > test_pep8.log 2>&1
@echo "written: test_pep8.log"
# run some checks on our cmakefiles.
-test_cmake:
- python3 build_files/cmake/cmake_consistency_check.py > test_cmake_consistency.log 2>&1
+test_cmake: FORCE
+ $(PYTHON) build_files/cmake/cmake_consistency_check.py > test_cmake_consistency.log 2>&1
@echo "written: test_cmake_consistency.log"
# run deprecation tests, see if we have anything to remove.
-test_deprecated:
- python3 tests/check_deprecated.py
+test_deprecated: FORCE
+ $(PYTHON) tests/check_deprecated.py
-test_style_c:
+test_style_c: FORCE
# run our own checks on C/C++ style
- PYTHONIOENCODING=utf_8 python3 \
+ PYTHONIOENCODING=utf_8 $(PYTHON) \
"$(BLENDER_DIR)/source/tools/check_source/check_style_c.py" \
"$(BLENDER_DIR)/source/blender" \
"$(BLENDER_DIR)/source/creator" \
--no-length-check
-test_style_c_qtc:
+test_style_c_qtc: FORCE
# run our own checks on C/C++ style
USE_QTC_TASK=1 \
- PYTHONIOENCODING=utf_8 python3 \
+ PYTHONIOENCODING=utf_8 $(PYTHON) \
"$(BLENDER_DIR)/source/tools/check_source/check_style_c.py" \
"$(BLENDER_DIR)/source/blender" \
"$(BLENDER_DIR)/source/creator" \
@@ -257,18 +280,18 @@ test_style_c_qtc:
@echo "written: test_style.tasks"
-test_style_osl:
+test_style_osl: FORCE
# run our own checks on C/C++ style
- PYTHONIOENCODING=utf_8 python3 \
+ PYTHONIOENCODING=utf_8 $(PYTHON) \
"$(BLENDER_DIR)/source/tools/check_source/check_style_c.py" \
"$(BLENDER_DIR)/intern/cycles/kernel/shaders" \
"$(BLENDER_DIR)/release/scripts/templates_osl"
-test_style_osl_qtc:
+test_style_osl_qtc: FORCE
# run our own checks on C/C++ style
USE_QTC_TASK=1 \
- PYTHONIOENCODING=utf_8 python3 \
+ PYTHONIOENCODING=utf_8 $(PYTHON) \
"$(BLENDER_DIR)/source/tools/check_source/check_style_c.py" \
"$(BLENDER_DIR)/intern/cycles/kernel/shaders" \
"$(BLENDER_DIR)/release/scripts/templates_osl" \
@@ -280,13 +303,13 @@ test_style_osl_qtc:
# Project Files
#
-project_qtcreator:
- python3 build_files/cmake/cmake_qtcreator_project.py "$(BUILD_DIR)"
+project_qtcreator: FORCE
+ $(PYTHON) build_files/cmake/cmake_qtcreator_project.py "$(BUILD_DIR)"
-project_netbeans:
- python3 build_files/cmake/cmake_netbeans_project.py "$(BUILD_DIR)"
+project_netbeans: FORCE
+ $(PYTHON) build_files/cmake/cmake_netbeans_project.py "$(BUILD_DIR)"
-project_eclipse:
+project_eclipse: FORCE
cmake -G"Eclipse CDT4 - Unix Makefiles" -H"$(BLENDER_DIR)" -B"$(BUILD_DIR)"
@@ -294,51 +317,51 @@ project_eclipse:
# Static Checking
#
-check_cppcheck:
+check_cppcheck: FORCE
$(CMAKE_CONFIG)
cd "$(BUILD_DIR)" ; \
- python3 "$(BLENDER_DIR)/build_files/cmake/cmake_static_check_cppcheck.py" 2> \
+ $(PYTHON) "$(BLENDER_DIR)/build_files/cmake/cmake_static_check_cppcheck.py" 2> \
"$(BLENDER_DIR)/check_cppcheck.txt"
@echo "written: check_cppcheck.txt"
-check_clang_array:
+check_clang_array: FORCE
$(CMAKE_CONFIG)
cd "$(BUILD_DIR)" ; \
- python3 "$(BLENDER_DIR)/build_files/cmake/cmake_static_check_clang_array.py"
+ $(PYTHON) "$(BLENDER_DIR)/build_files/cmake/cmake_static_check_clang_array.py"
-check_splint:
+check_splint: FORCE
$(CMAKE_CONFIG)
cd "$(BUILD_DIR)" ; \
- python3 "$(BLENDER_DIR)/build_files/cmake/cmake_static_check_splint.py"
+ $(PYTHON) "$(BLENDER_DIR)/build_files/cmake/cmake_static_check_splint.py"
-check_sparse:
+check_sparse: FORCE
$(CMAKE_CONFIG)
cd "$(BUILD_DIR)" ; \
- python3 "$(BLENDER_DIR)/build_files/cmake/cmake_static_check_sparse.py"
+ $(PYTHON) "$(BLENDER_DIR)/build_files/cmake/cmake_static_check_sparse.py"
-check_smatch:
+check_smatch: FORCE
$(CMAKE_CONFIG)
cd "$(BUILD_DIR)" ; \
- python3 "$(BLENDER_DIR)/build_files/cmake/cmake_static_check_smatch.py"
+ $(PYTHON) "$(BLENDER_DIR)/build_files/cmake/cmake_static_check_smatch.py"
-check_spelling_py:
+check_spelling_py: FORCE
cd "$(BUILD_DIR)" ; \
- PYTHONIOENCODING=utf_8 python3 \
+ PYTHONIOENCODING=utf_8 $(PYTHON) \
"$(BLENDER_DIR)/source/tools/check_source/check_spelling.py" \
"$(BLENDER_DIR)/release/scripts"
-check_spelling_c:
+check_spelling_c: FORCE
cd "$(BUILD_DIR)" ; \
- PYTHONIOENCODING=utf_8 python3 \
+ PYTHONIOENCODING=utf_8 $(PYTHON) \
"$(BLENDER_DIR)/source/tools/check_source/check_spelling.py" \
"$(BLENDER_DIR)/source" \
"$(BLENDER_DIR)/intern/cycles" \
"$(BLENDER_DIR)/intern/guardedalloc" \
"$(BLENDER_DIR)/intern/ghost" \
-check_spelling_c_qtc:
+check_spelling_c_qtc: FORCE
cd "$(BUILD_DIR)" ; USE_QTC_TASK=1 \
- PYTHONIOENCODING=utf_8 python3 \
+ PYTHONIOENCODING=utf_8 $(PYTHON) \
"$(BLENDER_DIR)/source/tools/check_source/check_spelling.py" \
"$(BLENDER_DIR)/source" \
"$(BLENDER_DIR)/intern/cycles" \
@@ -347,13 +370,13 @@ check_spelling_c_qtc:
> \
"$(BLENDER_DIR)/check_spelling_c.tasks"
-check_spelling_osl:
+check_spelling_osl: FORCE
cd "$(BUILD_DIR)" ;\
- PYTHONIOENCODING=utf_8 python3 \
+ PYTHONIOENCODING=utf_8 $(PYTHON) \
"$(BLENDER_DIR)/source/tools/check_source/check_spelling.py" \
"$(BLENDER_DIR)/intern/cycles/kernel/shaders"
-check_descriptions:
+check_descriptions: FORCE
"$(BUILD_DIR)/bin/blender" --background -noaudio --factory-startup --python \
"$(BLENDER_DIR)/source/tools/check_source/check_descriptions.py"
@@ -361,14 +384,14 @@ check_descriptions:
# Utilities
#
-tgz:
+tgz: FORCE
./build_files/utils/build_tgz.sh
-icons:
+icons: FORCE
"$(BLENDER_DIR)/release/datafiles/blender_icons_update.py"
"$(BLENDER_DIR)/release/datafiles/prvicons_update.py"
-update:
+update: FORCE
if [ -d "../lib" ]; then \
svn update ../lib/* ; \
fi
@@ -381,24 +404,36 @@ update:
#
# Simple version of ./doc/python_api/sphinx_doc_gen.sh with no PDF generation.
-doc_py:
+doc_py: FORCE
"$(BUILD_DIR)/bin/blender" --background -noaudio --factory-startup --python doc/python_api/sphinx_doc_gen.py
cd doc/python_api ; sphinx-build -b html sphinx-in sphinx-out
@echo "docs written into: '$(BLENDER_DIR)/doc/python_api/sphinx-out/contents.html'"
-doc_doxy:
+doc_doxy: FORCE
cd doc/doxygen; doxygen Doxyfile
@echo "docs written into: '$(BLENDER_DIR)/doc/doxygen/html/index.html'"
-doc_dna:
+doc_dna: FORCE
"$(BUILD_DIR)/bin/blender" --background -noaudio --factory-startup --python doc/blender_file_format/BlendFileDnaExporter_25.py
@echo "docs written into: '$(BLENDER_DIR)/doc/blender_file_format/dna.html'"
-doc_man:
- python3 doc/manpage/blender.1.py "$(BUILD_DIR)/bin/blender"
+doc_man: FORCE
+ $(PYTHON) doc/manpage/blender.1.py "$(BUILD_DIR)/bin/blender"
+
+help_features: FORCE
+ @$(PYTHON) -c \
+ "import re; \
+ print('\n'.join([ \
+ w for l in open('"$(BLENDER_DIR)"/CMakeLists.txt', 'r').readlines() \
+ if not l.lstrip().startswith('#') \
+ for w in (re.sub(\
+ r'.*\boption\s*\(\s*(WITH_[a-zA-Z0-9_]+)\s+(\".*\")\s*.*', r'\g<1> - \g<2>', l).strip('() \n'),) \
+ if w.startswith('WITH_')]))" | uniq
-clean:
+clean: FORCE
$(MAKE) -C "$(BUILD_DIR)" clean
.PHONY: all
+
+FORCE:
diff --git a/SConstruct b/SConstruct
index 1ff984ab7e1..b55cca403e9 100644
--- a/SConstruct
+++ b/SConstruct
@@ -218,6 +218,8 @@ else:
if not env['BF_FANCY']:
B.bc.disable()
+if env['WITH_BF_SDL_DYNLOAD']:
+ env['BF_SDL_INC'] = '#extern/sdlew/include/SDL2'
# remove install dir so old and new files are not mixed.
# NOTE: only do the scripts directory for now, otherwise is too disruptive for developers
@@ -264,6 +266,7 @@ if 'blenderlite' in B.targets:
target_env_defs['WITH_BF_BOOLEAN'] = False
target_env_defs['WITH_BF_REMESH'] = False
target_env_defs['WITH_BF_PYTHON'] = False
+ target_env_defs['WITH_BF_IME'] = False
target_env_defs['WITH_BF_3DMOUSE'] = False
target_env_defs['WITH_BF_LIBMV'] = False
target_env_defs['WITH_BF_FREESTYLE'] = False
@@ -420,6 +423,9 @@ if env['OURPLATFORM']=='darwin':
env.Append(LINKFLAGS=['-F/Library/Frameworks','-Xlinker','-weak_framework','-Xlinker','Jackmp'])
print B.bc.OKGREEN + "Using Jack"
+ if env['WITH_BF_SDL']:
+ env.Append(LINKFLAGS=['-lazy_framework','ForceFeedback'])
+
if env['WITH_BF_QUICKTIME'] == 1:
env['PLATFORM_LINKFLAGS'] = env['PLATFORM_LINKFLAGS']+['-framework','QTKit']
@@ -464,6 +470,14 @@ if env['OURPLATFORM']=='darwin':
################### End Automatic configuration for OSX ##################
#############################################################################
+if env['OURPLATFORM'] == 'linux' and not env['C_COMPILER_ID']:
+ command = ["%s"%env['CC'], "--version"]
+ line = btools.get_command_output(command)
+ if line.startswith('gcc'):
+ env['C_COMPILER_ID'] = 'gcc'
+ elif 'clang' in line[0]:
+ env['C_COMPILER_ID'] = 'clang'
+
if env['WITH_BF_OPENMP'] == 1:
if env['OURPLATFORM'] in ('win32-vc', 'win64-vc'):
env['CCFLAGS'].append('/openmp')
@@ -474,6 +488,13 @@ if env['WITH_BF_OPENMP'] == 1:
else:
env.Append(CCFLAGS=['-fopenmp'])
+if env['WITH_BF_CPP11']:
+ if env['OURPLATFORM'] in ('win32-vc', 'win64-vc'):
+ # Nothing special is needed, C++11 features are available by default.
+ pass
+ else:
+ env['CXXFLAGS'].append('-std=c++11')
+
#check for additional debug libnames
if env.has_key('BF_DEBUG_LIBS'):
@@ -493,6 +514,10 @@ if env['WITH_BF_STATICCXX']:
else:
print '\tcould not remove stdc++ library from LLIBS, WITH_BF_STATICCXX may not work for your platform'
+# audaspace is needed for the game engine
+if not env['WITH_BF_AUDASPACE']:
+ env['WITH_BF_GAMEENGINE'] = False
+
# check target for blenderplayer. Set WITH_BF_PLAYER if found on cmdline
if 'blenderplayer' in B.targets:
env['WITH_BF_PLAYER'] = True
@@ -519,13 +544,68 @@ else:
env['CPPFLAGS'].append('-D__LITTLE_ENDIAN__')
# TODO, make optional (as with CMake)
-env['CPPFLAGS'].append('-DWITH_AUDASPACE')
env['CPPFLAGS'].append('-DWITH_AVI')
env['CPPFLAGS'].append('-DWITH_OPENNL')
if env['OURPLATFORM'] not in ('win32-vc', 'win64-vc'):
env['CPPFLAGS'].append('-DHAVE_STDBOOL_H')
+# Audaspace
+
+if env['WITH_BF_AUDASPACE']:
+ env['BF_AUDASPACE_C_INC'] = '#intern/audaspace/intern'
+ env['BF_AUDASPACE_PY_INC'] = '#intern/audaspace/intern'
+ env['BF_AUDASPACE_DEF'] = ['WITH_AUDASPACE']
+ env['BF_AUDASPACE_DEF'].append('AUD_DEVICE_H="<AUD_C-API.h>"')
+ env['BF_AUDASPACE_DEF'].append('AUD_SPECIAL_H="<AUD_C-API.h>"')
+ env['BF_AUDASPACE_DEF'].append('AUD_SOUND_H="<AUD_C-API.h>"')
+ env['BF_AUDASPACE_DEF'].append('AUD_HANDLE_H="<AUD_C-API.h>"')
+ env['BF_AUDASPACE_DEF'].append('AUD_SEQUENCE_H="<AUD_C-API.h>"')
+ env['BF_AUDASPACE_DEF'].append('AUD_TYPES_H="<AUD_Space.h>"')
+
+# OpenGL
+
+if env['WITH_BF_GL_PROFILE_COMPAT']:
+ env['BF_GL_DEFINITIONS'].append('WITH_GL_PROFILE_COMPAT')
+
+if env['WITH_BF_GL_PROFILE_CORE']:
+ env['BF_GL_DEFINITIONS'].append('WITH_GL_PROFILE_CORE')
+
+if env['WITH_BF_GL_PROFILE_ES20']:
+ env['BF_GL_DEFINITIONS'].append('WITH_GL_PROFILE_ES20')
+
+if env['WITH_BF_GL_EGL']:
+ env['BF_GL_DEFINITIONS'].append('WITH_EGL')
+
+# GLEW
+
+if env['WITH_BF_GLEW_MX']:
+ env['BF_GL_DEFINITIONS'].append('WITH_GLEW_MX')
+
+if env['WITH_BF_GLEW_ES']:
+ env['BF_GLEW_INC'] = '#extern/glew-es/include'
+
+ env['BF_GL_DEFINITIONS'] += ['GLEW_STATIC', 'WITH_GLEW_ES']
+
+ if not env['WITH_BF_GL_PROFILE_ES20']:
+ # No ES functions are needed
+ env['BF_GL_DEFINITIONS'].append('GLEW_NO_ES')
+ elif not (env['WITH_BF_GL_PROFILE_CORE'] or env['WITH_BF_GL_PROFILE_COMPAT']):
+ # ES is enabled, but the other functions are all disabled
+ env['BF_GL_DEFINITIONS'].append('GLEW_ES_ONLY')
+
+ if env['WITH_BF_GL_PROFILE_ES20']:
+ if env['WITH_BF_GL_EGL']:
+ env['BF_GL_DEFINITIONS'].append('GLEW_USE_LIB_ES20')
+
+ if env['WITH_BF_GL_EGL']:
+ env['BF_GL_DEFINITIONS'].append('GLEW_INC_EGL')
+
+else:
+ env['BF_GLEW_INC'] = '#extern/glew/include'
+
+ env['BF_GL_DEFINITIONS'].append('GLEW_STATIC')
+
# lastly we check for root_build_dir ( we should not do before, otherwise we might do wrong builddir
B.root_build_dir = env['BF_BUILDDIR']
B.doc_build_dir = os.path.join(env['BF_INSTALLDIR'], 'doc')
@@ -702,6 +782,11 @@ if B.targets != ['cudakernels']:
data_to_c_simple("release/datafiles/preview_cycles.blend")
# --- glsl ---
+ data_to_c_simple("source/blender/gpu/shaders/gpu_shader_geometry.glsl")
+
+ data_to_c_simple("source/blender/gpu/shaders/gpu_program_smoke_frag.glsl")
+ data_to_c_simple("source/blender/gpu/shaders/gpu_program_smoke_color_frag.glsl")
+
data_to_c_simple("source/blender/gpu/shaders/gpu_shader_simple_frag.glsl")
data_to_c_simple("source/blender/gpu/shaders/gpu_shader_simple_vert.glsl")
data_to_c_simple("source/blender/gpu/shaders/gpu_shader_material.glsl")
@@ -709,9 +794,20 @@ if B.targets != ['cudakernels']:
data_to_c_simple("source/blender/gpu/shaders/gpu_shader_sep_gaussian_blur_frag.glsl")
data_to_c_simple("source/blender/gpu/shaders/gpu_shader_sep_gaussian_blur_vert.glsl")
data_to_c_simple("source/blender/gpu/shaders/gpu_shader_vertex.glsl")
+ data_to_c_simple("source/blender/gpu/shaders/gpu_shader_vertex_world.glsl")
data_to_c_simple("source/blender/gpu/shaders/gpu_shader_vsm_store_frag.glsl")
data_to_c_simple("source/blender/gpu/shaders/gpu_shader_vsm_store_vert.glsl")
+ data_to_c_simple("source/blender/gpu/shaders/gpu_shader_fx_ssao_frag.glsl")
+ data_to_c_simple("source/blender/gpu/shaders/gpu_shader_fx_dof_frag.glsl")
+ data_to_c_simple("source/blender/gpu/shaders/gpu_shader_fx_dof_vert.glsl")
+ data_to_c_simple("source/blender/gpu/shaders/gpu_shader_fx_dof_hq_frag.glsl")
+ data_to_c_simple("source/blender/gpu/shaders/gpu_shader_fx_dof_hq_vert.glsl")
+ data_to_c_simple("source/blender/gpu/shaders/gpu_shader_fx_dof_hq_geo.glsl")
+ data_to_c_simple("source/blender/gpu/shaders/gpu_shader_fx_lib.glsl")
+ data_to_c_simple("source/blender/gpu/shaders/gpu_shader_fx_depth_resolve.glsl")
+ data_to_c_simple("source/blender/gpu/shaders/gpu_shader_fx_vert.glsl")
data_to_c_simple("intern/opencolorio/gpu_shader_display_transform.glsl")
+ data_to_c_simple("intern/opensubdiv/gpu_shader_opensubd_display.glsl")
# --- blender ---
data_to_c_simple("release/datafiles/bfont.pfb")
@@ -805,17 +901,21 @@ B.init_lib_dict()
##### END SETUP ##########
-if B.targets != ['cudakernels']:
- # Put all auto configuration run-time tests here
+## Auto-configuration run-time tests
+
+from FindSharedPtr import FindSharedPtr
+from FindUnorderedMap import FindUnorderedMap
- from FindSharedPtr import FindSharedPtr
- from FindUnorderedMap import FindUnorderedMap
+conf = Configure(env)
+old_linkflags = conf.env['LINKFLAGS']
+conf.env.Append(LINKFLAGS=env['PLATFORM_LINKFLAGS'])
- conf = Configure(env)
- conf.env.Append(LINKFLAGS=env['PLATFORM_LINKFLAGS'])
- FindSharedPtr(conf)
- FindUnorderedMap(conf)
- env = conf.Finish()
+# Put all tests here
+FindSharedPtr(conf)
+FindUnorderedMap(conf)
+
+conf.env['LINKFLAGS'] = old_linkflags
+env = conf.Finish()
# End of auto configuration
@@ -947,17 +1047,20 @@ if env['OURPLATFORM']!='darwin':
dir=os.path.join(env['BF_INSTALLDIR'], VERSION, 'scripts', 'addons','cycles', 'kernel')
source=os.listdir('intern/cycles/kernel')
if '__pycache__' in source: source.remove('__pycache__')
- source.remove('kernel.cpp')
source.remove('CMakeLists.txt')
+ source.remove('SConscript')
source.remove('svm')
source.remove('closure')
source.remove('geom')
source.remove('shaders')
source.remove('osl')
+ source.remove('split')
source=['intern/cycles/kernel/'+s for s in source]
+ source.append('intern/cycles/util/util_atomic.h')
source.append('intern/cycles/util/util_color.h')
source.append('intern/cycles/util/util_half.h')
source.append('intern/cycles/util/util_math.h')
+ source.append('intern/cycles/util/util_math_fast.h')
source.append('intern/cycles/util/util_transform.h')
source.append('intern/cycles/util/util_types.h')
scriptinstall.append(env.Install(dir=dir,source=source))
@@ -979,6 +1082,12 @@ if env['OURPLATFORM']!='darwin':
if '__pycache__' in source: source.remove('__pycache__')
source=['intern/cycles/kernel/geom/'+s for s in source]
scriptinstall.append(env.Install(dir=dir,source=source))
+ # split
+ dir=os.path.join(env['BF_INSTALLDIR'], VERSION, 'scripts', 'addons','cycles', 'kernel', 'split')
+ source=os.listdir('intern/cycles/kernel/split')
+ if '__pycache__' in source: source.remove('__pycache__')
+ source=['intern/cycles/kernel/split/'+s for s in source]
+ scriptinstall.append(env.Install(dir=dir,source=source))
# licenses
dir=os.path.join(env['BF_INSTALLDIR'], VERSION, 'scripts', 'addons','cycles', 'license')
@@ -1108,9 +1217,37 @@ if env['OURPLATFORM']=='linuxcross':
textlist = []
texttargetlist = []
for tp, tn, tf in os.walk('release/text'):
+ tf.remove("readme.html")
for f in tf:
textlist.append(tp+os.sep+f)
+def readme_version_patch():
+ readme_src = "release/text/readme.html"
+ readme_dst = os.path.abspath(os.path.normpath(os.path.join(env['BF_BUILDDIR'], "readme.html")))
+
+ if not os.path.exists(readme_dst) or (os.path.getmtime(readme_dst) < os.path.getmtime(readme_src)):
+ f = open(readme_src, "r")
+ data = f.read()
+ f.close()
+
+ data = data.replace("BLENDER_VERSION", VERSION)
+ f = open(readme_dst, "w")
+ f.write(data)
+ f.close()
+
+ textlist.append(readme_dst)
+
+readme_version_patch()
+del readme_version_patch
+
+
+'''Command(
+ "release/text/readme.html"
+
+ )
+Command("file.out", "file.in", Copy(env['BF_INSTALLDIR'], "release/text/readme.html"))
+'''
+
# Font licenses
textlist.append('release/datafiles/LICENSE-bfont.ttf.txt')
if env['WITH_BF_INTERNATIONAL']:
@@ -1137,7 +1274,7 @@ if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'win64-vc', 'linuxcross'):
dllsources += ['${BF_PTHREADS_LIBPATH}/${BF_PTHREADS_LIB}.dll']
if env['WITH_BF_SDL']:
- dllsources.append('${BF_SDL_LIBPATH}/SDL.dll')
+ dllsources.append('${BF_SDL_LIBPATH}/SDL2.dll')
if env['WITH_BF_PYTHON']:
if env['BF_DEBUG']:
@@ -1156,7 +1293,6 @@ if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'win64-vc', 'linuxcross'):
if env['WITH_BF_OPENAL']:
dllsources.append('${LCGDIR}/openal/lib/OpenAL32.dll')
- dllsources.append('${LCGDIR}/openal/lib/wrap_oal.dll')
if env['WITH_BF_SNDFILE']:
dllsources.append('${LCGDIR}/sndfile/lib/libsndfile-1.dll')
@@ -1183,6 +1319,15 @@ if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'win64-vc', 'linuxcross'):
windlls = env.Install(dir=env['BF_INSTALLDIR'], source = dllsources)
allinstall += windlls
+ # TODO(sergey): For unti we've got better way to deal with python binary
+ if env['WITH_BF_PYTHON']:
+ py_target = os.path.join(env['BF_INSTALLDIR'], VERSION, 'python', 'bin')
+ if env['BF_DEBUG']:
+ allinstall += env.Install(dir=py_target, source = ['${BF_PYTHON_LIBPATH}/${BF_PYTHON_DLL}_d.dll'])
+ else:
+ allinstall += env.Install(dir=py_target, source = ['${BF_PYTHON_LIBPATH}/${BF_PYTHON_DLL}.dll'])
+
+
if env['OURPLATFORM'] == 'win64-mingw':
dllsources = []
diff --git a/build_files/build_environment/install_deps.sh b/build_files/build_environment/install_deps.sh
index f081f432c3b..2d839858b80 100755
--- a/build_files/build_environment/install_deps.sh
+++ b/build_files/build_environment/install_deps.sh
@@ -27,20 +27,23 @@ getopt \
-o s:i:t:h \
--long source:,install:,tmp:,info:,threads:,help,no-sudo,with-all,with-opencollada,\
ver-ocio:,ver-oiio:,ver-llvm:,ver-osl:,\
-force-all,force-python,force-numpy,force-boost,force-ocio,force-oiio,force-llvm,force-osl,force-opencollada,\
-force-ffmpeg,\
-skip-python,skip-numpy,skip-boost,skip-ocio,skip-oiio,skip-llvm,skip-osl,skip-ffmpeg,skip-opencollada,\
+force-all,force-python,force-numpy,force-boost,force-ocio,force-oiio,force-llvm,force-osl,force-osd,\
+force-ffmpeg,force-opencollada,\
+skip-python,skip-numpy,skip-boost,skip-ocio,skip-openexr,skip-oiio,skip-llvm,skip-osl,skip-osd,\
+skip-ffmpeg,skip-opencollada,\
required-numpy: \
-- "$@" \
)
+COMMANDLINE=$@
+
DISTRO=""
RPM=""
SRC="$HOME/src/blender-deps"
INST="/opt/lib"
TMP="/tmp"
CWD=$PWD
-INFO_PATH = CWD
+INFO_PATH=$CWD
# Do not install some optional, potentially conflicting libs by default...
WITH_ALL=false
@@ -83,7 +86,7 @@ ARGUMENTS_INFO="\"COMMAND LINE ARGUMENTS:
-t n, --threads=n
Use a specific number of threads when building the libraries (auto-detected as '\$THREADS').
- --no_sudo
+ --no-sudo
Disable use of sudo (this script won't be able to do much though, will just print needed packages...).
--with-all
@@ -138,6 +141,9 @@ ARGUMENTS_INFO="\"COMMAND LINE ARGUMENTS:
--force-osl
Force the rebuild of OpenShadingLanguage.
+ --force-osd
+ Force the rebuild of OpenSubdiv.
+
--force-opencollada
Force the rebuild of OpenCOLLADA.
@@ -174,6 +180,9 @@ ARGUMENTS_INFO="\"COMMAND LINE ARGUMENTS:
--skip-osl
Unconditionally skip OpenShadingLanguage installation/building.
+ --skip-osd
+ Unconditionally skip OpenSubdiv installation/building.
+
--skip-opencollada
Unconditionally skip OpenCOLLADA installation/building.
@@ -209,14 +218,14 @@ OCIO_VERSION_MIN="1.0"
OCIO_FORCE_REBUILD=false
OCIO_SKIP=false
-OPENEXR_VERSION="2.1.0"
+OPENEXR_VERSION="2.2.0"
OPENEXR_VERSION_MIN="2.0.1"
-ILMBASE_VERSION="2.1.0"
+ILMBASE_VERSION="2.2.0"
OPENEXR_FORCE_REBUILD=false
OPENEXR_SKIP=false
_with_built_openexr=false
-OIIO_VERSION="1.4.11"
+OIIO_VERSION="1.4.16"
OIIO_VERSION_MIN="1.4.0"
OIIO_FORCE_REBUILD=false
OIIO_SKIP=false
@@ -228,11 +237,17 @@ LLVM_FORCE_REBUILD=false
LLVM_SKIP=false
# OSL needs to be compiled for now!
-OSL_VERSION="1.5.0"
+OSL_VERSION="1.5.11"
OSL_VERSION_MIN=$OSL_VERSION
OSL_FORCE_REBUILD=false
OSL_SKIP=false
+# OpenSubdiv needs to be compiled for now
+OSD_VERSION="3.0.2"
+OSD_VERSION_MIN=$OSD_VERSION
+OSD_FORCE_REBUILD=false
+OSD_SKIP=false
+
# Version??
OPENCOLLADA_VERSION="1.3"
OPENCOLLADA_FORCE_REBUILD=false
@@ -375,6 +390,11 @@ while true; do
OSL_VERSION_MIN=$OSL_VERSION
shift; shift; continue
;;
+ --ver-osd)
+ OSD_VERSION="$2"
+ OSD_VERSION_MIN=$OSD_VERSION
+ shift; shift; continue
+ ;;
--force-all)
PYTHON_FORCE_REBUILD=true
NUMPY_FORCE_REBUILD=true
@@ -384,6 +404,7 @@ while true; do
OIIO_FORCE_REBUILD=true
LLVM_FORCE_REBUILD=true
OSL_FORCE_REBUILD=true
+ OSD_FORCE_REBUILD=true
OPENCOLLADA_FORCE_REBUILD=true
FFMPEG_FORCE_REBUILD=true
shift; continue
@@ -417,6 +438,9 @@ while true; do
--force-osl)
OSL_FORCE_REBUILD=true; shift; continue
;;
+ --force-osd)
+ OSD_FORCE_REBUILD=true; shift; continue
+ ;;
--force-opencollada)
OPENCOLLADA_FORCE_REBUILD=true; shift; continue
;;
@@ -447,6 +471,9 @@ while true; do
--skip-osl)
OSL_SKIP=true; shift; continue
;;
+ --skip-osd)
+ OSD_SKIP=true; shift; continue
+ ;;
--skip-opencollada)
OPENCOLLADA_SKIP=true; shift; continue
;;
@@ -471,11 +498,12 @@ while true; do
esac
done
-if $WITH_ALL; then
+if [ $WITH_ALL == true -a $OPENCOLLADA_SKIP == false ]; then
WITH_OPENCOLLADA=true
fi
+
# This has to be done here, because user might force some versions...
PYTHON_SOURCE=( "http://python.org/ftp/python/$PYTHON_VERSION/Python-$PYTHON_VERSION.tgz" )
NUMPY_SOURCE=( "http://sourceforge.net/projects/numpy/files/NumPy/$NUMPY_VERSION/numpy-$NUMPY_VERSION.tar.gz" )
@@ -484,24 +512,40 @@ BOOST_SOURCE=( "http://sourceforge.net/projects/boost/files/boost/$BOOST_VERSION
OCIO_SOURCE=( "https://github.com/imageworks/OpenColorIO/tarball/v$OCIO_VERSION" )
-#OPENEXR_SOURCE=( "http://download.savannah.nongnu.org/releases/openexr/openexr-$OPENEXR_VERSION.tar.gz" )
-OPENEXR_SOURCE=( "https://github.com/mont29/openexr.git" )
-OPENEXR_REPO_UID="2787aa1cf652d244ed45ae124eb1553f6cff11ee"
+OPENEXR_USE_REPO=false
+OPENEXR_SOURCE=( "http://download.savannah.nongnu.org/releases/openexr/openexr-$OPENEXR_VERSION.tar.gz" )
+OPENEXR_SOURCE_REPO=( "https://github.com/mont29/openexr.git" )
+OPENEXR_SOURCE_REPO_UID="2787aa1cf652d244ed45ae124eb1553f6cff11ee"
ILMBASE_SOURCE=( "http://download.savannah.nongnu.org/releases/openexr/ilmbase-$ILMBASE_VERSION.tar.gz" )
-#OIIO_SOURCE=( "https://github.com/OpenImageIO/oiio/archive/Release-$OIIO_VERSION.tar.gz" )
-OIIO_SOURCE=( "https://github.com/OpenImageIO/oiio.git" )
-OIIO_REPO_UID="c9e67275a0b248ead96152f6d2221cc0c0f278a4"
+OIIO_USE_REPO=false
+OIIO_SOURCE=( "https://github.com/OpenImageIO/oiio/archive/Release-$OIIO_VERSION.tar.gz" )
+OIIO_SOURCE_REPO=( "https://github.com/OpenImageIO/oiio.git" )
+OIIO_SOURCE_REPO_UID="c9e67275a0b248ead96152f6d2221cc0c0f278a4"
LLVM_SOURCE=( "http://llvm.org/releases/$LLVM_VERSION/llvm-$LLVM_VERSION.src.tar.gz" )
LLVM_CLANG_SOURCE=( "http://llvm.org/releases/$LLVM_VERSION/clang-$LLVM_VERSION.src.tar.gz" "http://llvm.org/releases/$LLVM_VERSION/cfe-$LLVM_VERSION.src.tar.gz" )
-#OSL_SOURCE=( "https://github.com/imageworks/OpenShadingLanguage/archive/Release-$OSL_VERSION.tar.gz" )
-#OSL_SOURCE=( "https://github.com/imageworks/OpenShadingLanguage.git" )
-OSL_SOURCE=( "https://github.com/mont29/OpenShadingLanguage.git" )
-OSL_REPO_UID="85179714e1bc69cd25ecb6bb711c1a156685d395"
+OSL_USE_REPO=true
+#~ OSL_SOURCE=( "https://github.com/imageworks/OpenShadingLanguage/archive/Release-$OSL_VERSION.tar.gz" )
+OSL_SOURCE=( "https://github.com/Nazg-Gul/OpenShadingLanguage/archive/Release-1.5.11.tar.gz" )
+#~ OSL_SOURCE_REPO=( "https://github.com/imageworks/OpenShadingLanguage.git" )
+#~ OSL_SOURCE_REPO=( "https://github.com/mont29/OpenShadingLanguage.git" )
+#~ OSL_SOURCE_REPO_UID="85179714e1bc69cd25ecb6bb711c1a156685d395"
+#~ OSL_SOURCE_REPO_BRANCH="master"
+OSL_SOURCE_REPO=( "https://github.com/Nazg-Gul/OpenShadingLanguage.git" )
+OSL_SOURCE_REPO_UID="22ee5ea298fd215430dfbd160b5aefd507f06db0"
+OSL_SOURCE_REPO_BRANCH="blender-fixes"
+
+OSD_USE_REPO=true
+# Script foo to make the version string compliant with the archive name:
+# ${Varname//SearchForThisChar/ReplaceWithThisChar}
+OSD_SOURCE=( "https://github.com/PixarAnimationStudios/OpenSubdiv/archive/v${OSD_VERSION//./_}.tar.gz" )
+OSD_SOURCE_REPO=( "https://github.com/PixarAnimationStudios/OpenSubdiv.git" )
+OSD_SOURCE_REPO_UID="404659fffa659da075d1c9416e4fc939139a84ee"
+OSD_SOURCE_REPO_BRANCH="dev"
OPENCOLLADA_SOURCE=( "https://github.com/KhronosGroup/OpenCOLLADA.git" )
-OPENCOLLADA_REPO_UID="18da7f4109a8eafaa290a33f5550501cc4c8bae8"
+OPENCOLLADA_REPO_UID="3335ac164e68b2512a40914b14c74db260e6ff7d"
FFMPEG_SOURCE=( "http://ffmpeg.org/releases/ffmpeg-$FFMPEG_VERSION.tar.bz2" )
@@ -974,7 +1018,7 @@ clean_ILMBASE() {
compile_ILMBASE() {
# To be changed each time we make edits that would modify the compiled result!
- ilmbase_magic=9
+ ilmbase_magic=10
_init_ilmbase
# Clean install if needed!
@@ -998,8 +1042,7 @@ compile_ILMBASE() {
download ILMBASE_SOURCE[@] $_src.tar.gz
INFO "Unpacking ILMBase-$ILMBASE_VERSION"
- tar -C $SRC --transform "s,(.*/?)ilmbase-[^/]*(.*),\1ILMBase-$ILMBASE_VERSION\2,x" \
- -xf $_src.tar.gz
+ tar -C $SRC --transform "s,(.*/?)ilmbase-[^/]*(.*),\1ILMBase-$ILMBASE_VERSION\2,x" -xf $_src.tar.gz
fi
@@ -1015,6 +1058,7 @@ compile_ILMBASE() {
cmake_d="$cmake_d -D CMAKE_PREFIX_PATH=$_inst"
cmake_d="$cmake_d -D CMAKE_INSTALL_PREFIX=$_inst"
cmake_d="$cmake_d -D BUILD_SHARED_LIBS=ON"
+ cmake_d="$cmake_d -D NAMESPACE_VERSIONING=OFF" # VERY IMPORTANT!!!
if file /bin/cp | grep -q '32-bit'; then
cflags="-fPIC -m32 -march=i686"
@@ -1087,24 +1131,28 @@ compile_OPENEXR() {
INFO "Downloading OpenEXR-$OPENEXR_VERSION"
mkdir -p $SRC
-# download OPENEXR_SOURCE[@] $_src.tar.gz
-
-# INFO "Unpacking OpenEXR-$OPENEXR_VERSION"
-# tar -C $SRC --transform "s,(.*/?)openexr[^/]*(.*),\1OpenEXR-$OPENEXR_VERSION\2,x" \
-# -xf $_src.tar.gz
-
- git clone ${OPENEXR_SOURCE[0]} $_src
+ if [ $OPENEXR_USE_REPO == true ]; then
+ git clone ${OPENEXR_SOURCE_REPO[0]} $_src
+ else
+ download OPENEXR_SOURCE[@] $_src.tar.gz
+ INFO "Unpacking OpenEXR-$OPENEXR_VERSION"
+ tar -C $SRC --transform "s,(.*/?)openexr[^/]*(.*),\1OpenEXR-$OPENEXR_VERSION\2,x" -xf $_src.tar.gz
+ fi
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
+ if [ $OPENEXR_USE_REPO == true ]; then
+ # XXX For now, always update from latest repo...
+ git pull origin master
+ # Stick to same rev as windows' libs...
+ git checkout $OPENEXR_SOURCE_REPO_UID
+ git reset --hard
+ oiio_src_path="../OpenEXR"
+ else
+ oiio_src_path=".."
+ fi
# Always refresh the whole build!
if [ -d build ]; then
@@ -1118,6 +1166,7 @@ compile_OPENEXR() {
cmake_d="$cmake_d -D CMAKE_INSTALL_PREFIX=$_inst"
cmake_d="$cmake_d -D ILMBASE_PACKAGE_PREFIX=$_ilmbase_inst"
cmake_d="$cmake_d -D BUILD_SHARED_LIBS=ON"
+ cmake_d="$cmake_d -D NAMESPACE_VERSIONING=OFF" # VERY IMPORTANT!!!
if file /bin/cp | grep -q '32-bit'; then
cflags="-fPIC -m32 -march=i686"
@@ -1125,7 +1174,7 @@ compile_OPENEXR() {
cflags="-fPIC"
fi
- cmake $cmake_d -D CMAKE_CXX_FLAGS="$cflags" -D CMAKE_EXE_LINKER_FLAGS="-lgcc_s -lgcc" ../OpenEXR
+ cmake $cmake_d -D CMAKE_CXX_FLAGS="$cflags" -D CMAKE_EXE_LINKER_FLAGS="-lgcc_s -lgcc" $oiio_src_path
make -j$THREADS && make install
@@ -1189,24 +1238,25 @@ compile_OIIO() {
if [ ! -d $_src ]; then
mkdir -p $SRC
- #download OIIO_SOURCE[@] "$_src.tar.gz"
-#
- #INFO "Unpacking OpenImageIO-$OIIO_VERSION"
- #tar -C $SRC --transform "s,(.*/?)oiio-Release-[^/]*(.*),\1OpenImageIO-$OIIO_VERSION\2,x" \
- #-xf $_src.tar.gz
-
- git clone ${OIIO_SOURCE[0]} $_src
+ if [ $OIIO_USE_REPO == true ]; then
+ git clone ${OIIO_SOURCE_REPO[0]} $_src
+ else
+ download OIIO_SOURCE[@] "$_src.tar.gz"
+ INFO "Unpacking OpenImageIO-$OIIO_VERSION"
+ tar -C $SRC --transform "s,(.*/?)oiio-Release-[^/]*(.*),\1OpenImageIO-$OIIO_VERSION\2,x" -xf $_src.tar.gz
+ fi
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
+ if [ $OIIO_USE_REPO == true ]; then
+ # XXX For now, always update from latest repo...
+ git pull origin master
+ # Stick to same rev as windows' libs...
+ git checkout $OIIO_SOURCE_REPO_UID
+ git reset --hard
+ fi
# Always refresh the whole build!
if [ -d build ]; then
@@ -1228,6 +1278,7 @@ compile_OIIO() {
if [ $_with_built_openexr == true ]; then
cmake_d="$cmake_d -D ILMBASE_HOME=$INST/openexr"
cmake_d="$cmake_d -D OPENEXR_HOME=$INST/openexr"
+ INFO "ILMBASE_HOME=$INST/openexr"
fi
# Optional tests and cmd tools
@@ -1358,7 +1409,7 @@ EOF
cmake_d="$cmake_d -D CMAKE_INSTALL_PREFIX=$_inst"
cmake_d="$cmake_d -D LLVM_ENABLE_FFI=ON"
cmake_d="$cmake_d -D LLVM_TARGETS_TO_BUILD=X86"
- cmake_d="$cmake_d -D -DLLVM_ENABLE_TERMINFO=OFF"
+ cmake_d="$cmake_d -D LLVM_ENABLE_TERMINFO=OFF"
if [ -d $_FFI_INCLUDE_DIR ]; then
cmake_d="$cmake_d -D FFI_INCLUDE_DIR=$_FFI_INCLUDE_DIR"
@@ -1404,14 +1455,15 @@ clean_OSL() {
compile_OSL() {
# To be changed each time we make edits that would modify the compiled result!
- osl_magic=15
+ osl_magic=17
_init_osl
# Clean install if needed!
magic_compile_check osl-$OSL_VERSION $osl_magic
- if [ $? -eq 1 -o $OSL_FORCE_REBUILD == true ]; then
- clean_OSL
- fi
+ #~ if [ $? -eq 1 -o $OSL_FORCE_REBUILD == true ]; then
+ #~ rm -Rf $_src # XXX Radical, but not easy to change remote repo fully automatically
+ #~ clean_OSL
+ #~ fi
if [ ! -d $_inst ]; then
INFO "Building OpenShadingLanguage-$OSL_VERSION"
@@ -1421,26 +1473,26 @@ compile_OSL() {
if [ ! -d $_src ]; then
mkdir -p $SRC
- #download OSL_SOURCE[@] "$_src.tar.gz"
-
- #INFO "Unpacking OpenShadingLanguage-$OSL_VERSION"
- #tar -C $SRC --transform "s,(.*/?)OpenShadingLanguage-[^/]*(.*),\1OpenShadingLanguage-$OSL_VERSION\2,x" \
- #-xf $_src.tar.gz
-
- git clone ${OSL_SOURCE[0]} $_src
-
+ if [ $OSL_USE_REPO == true ]; then
+ git clone ${OSL_SOURCE_REPO[0]} $_src
+ else
+ download OSL_SOURCE[@] "$_src.tar.gz"
+ INFO "Unpacking OpenShadingLanguage-$OSL_VERSION"
+ tar -C $SRC --transform "s,(.*/?)OpenShadingLanguage-[^/]*(.*),\1OpenShadingLanguage-$OSL_VERSION\2,x" \
+ -xf $_src.tar.gz
+ fi
fi
cd $_src
- git remote set-url origin $OSL_SOURCE
-
- # XXX For now, always update from latest repo...
- git pull -X theirs origin master
-
- # Stick to same rev as windows' libs...
- git checkout $OSL_REPO_UID
- git reset --hard
+ if [ $OSL_USE_REPO == true ]; then
+ git remote set-url origin ${OSL_SOURCE_REPO[0]}
+ # XXX For now, always update from latest repo...
+ git pull --no-edit -X theirs origin $OSL_SOURCE_REPO_BRANCH
+ # Stick to same rev as windows' libs...
+ git checkout $OSL_SOURCE_REPO_UID
+ git reset --hard
+ fi
# Always refresh the whole build!
if [ -d build ]; then
@@ -1455,11 +1507,14 @@ compile_OSL() {
cmake_d="$cmake_d -D STOP_ON_WARNING=OFF"
cmake_d="$cmake_d -D BUILDSTATIC=OFF"
- cmake_d="$cmake_d -D ILMBASE_VERSION=$ILMBASE_VERSION"
+ #~ cmake_d="$cmake_d -D ILMBASE_VERSION=$ILMBASE_VERSION"
if [ $_with_built_openexr == true ]; then
INFO "ILMBASE_HOME=$INST/openexr"
cmake_d="$cmake_d -D ILMBASE_HOME=$INST/openexr"
+ # XXX Temp workaround... sigh, ILMBase really messed the things up by defining their custom names ON by default :(
+ cmake_d="$cmake_d -D ILMBASE_CUSTOM=ON"
+ cmake_d="$cmake_d -D ILMBASE_CUSTOM_LIBRARIES='Half;Iex;Imath;IlmThread'"
fi
if [ -d $INST/boost ]; then
@@ -1473,7 +1528,7 @@ compile_OSL() {
if [ ! -z $LLVM_VERSION_FOUND ]; then
cmake_d="$cmake_d -D LLVM_VERSION=$LLVM_VERSION_FOUND"
if [ -d $INST/llvm ]; then
- cmake_d="$cmake_d -D LLVM_DIRECTORY=$INST/llvm"
+ cmake_d="$cmake_d -D LLVM_ROOT_DIR=$INST/llvm"
cmake_d="$cmake_d -D LLVM_STATIC=ON"
fi
fi
@@ -1502,6 +1557,99 @@ compile_OSL() {
run_ldconfig "osl"
}
+#### Build OSD ####
+_init_osd() {
+ _src=$SRC/OpenSubdiv-$OSD_VERSION
+ _git=true
+ _inst=$INST/osd-$OSD_VERSION
+ _inst_shortcut=$INST/osd
+}
+
+clean_OSD() {
+ _init_osd
+ _clean
+}
+
+compile_OSD() {
+ # To be changed each time we make edits that would modify the compiled result!
+ osd_magic=0
+ _init_osd
+
+ # Clean install if needed!
+ magic_compile_check osd-$OSD_VERSION $osd_magic
+ if [ $? -eq 1 -o $OSD_FORCE_REBUILD == true ]; then
+ clean_OSD
+ fi
+
+ if [ ! -d $_inst ]; then
+ INFO "Building OpenSubdiv-$OSD_VERSION"
+
+ prepare_opt
+
+ if [ ! -d $_src ]; then
+ mkdir -p $SRC
+
+ if [ $OSD_USE_REPO == true ]; then
+ git clone ${OSD_SOURCE_REPO[0]} $_src
+ else
+ download OSD_SOURCE[@] "$_src.tar.gz"
+ INFO "Unpacking OpenSubdiv-$OSD_VERSION"
+ tar -C $SRC --transform "s,(.*/?)OpenSubdiv-[^/]*(.*),\1OpenSubdiv-$OSD_VERSION\2,x" \
+ -xf $_src.tar.gz
+ fi
+ fi
+
+ cd $_src
+
+ if [ $OSD_USE_REPO == true ]; then
+ git remote set-url origin ${OSD_SOURCE_REPO[0]}
+ # XXX For now, always update from latest repo...
+ git pull --no-edit -X theirs origin $OSD_SOURCE_REPO_BRANCH
+ # Stick to same rev as windows' libs...
+ git checkout $OSD_SOURCE_REPO_UID
+ git reset --hard
+ fi
+
+ # Always refresh the whole build!
+ if [ -d build ]; then
+ rm -rf build
+ fi
+ mkdir build
+ cd build
+
+ cmake_d="-D CMAKE_BUILD_TYPE=Release"
+ cmake_d="$cmake_d -D CMAKE_INSTALL_PREFIX=$_inst"
+ # ptex is only needed when nicholas bishop is ready
+ cmake_d="$cmake_d -D NO_PTEX=1"
+ cmake_d="$cmake_d -D NO_CLEW=1"
+ # maya plugin, docs, tutorials, regression tests and examples are not needed
+ cmake_d="$cmake_d -D NO_MAYA=1 -D NO_DOC=1 -D NO_TUTORIALS=1 -D NO_REGRESSION=1 -DNO_EXAMPLES=1"
+
+ cmake $cmake_d ..
+
+ make -j$THREADS && make install
+ make clean
+
+ if [ -d $_inst ]; then
+ _create_inst_shortcut
+ else
+ ERROR "OpenSubdiv-$OSD_VERSION failed to compile, exiting"
+ exit 1
+ fi
+
+ magic_compile_set osd-$OSD_VERSION $osd_magic
+
+ cd $CWD
+ INFO "Done compiling OpenSubdiv-$OSD_VERSION!"
+ else
+ INFO "Own OpenSubdiv-$OSD_VERSION is up to date, nothing to do!"
+ INFO "If you want to force rebuild of this lib, use the --force-osd option."
+ fi
+
+ run_ldconfig "osd"
+}
+
+
#### Build OpenCOLLADA ####
_init_opencollada() {
_src=$SRC/OpenCOLLADA-$OPENCOLLADA_VERSION
@@ -1517,7 +1665,7 @@ clean_OpenCOLLADA() {
compile_OpenCOLLADA() {
# To be changed each time we make edits that would modify the compiled results!
- opencollada_magic=8
+ opencollada_magic=9
_init_opencollada
# Clean install if needed!
@@ -1793,9 +1941,10 @@ install_DEB() {
THEORA_DEV="libtheora-dev"
_packages="gawk cmake cmake-curses-gui scons build-essential libjpeg-dev libpng-dev \
- libfreetype6-dev libx11-dev libxi-dev wget libsqlite3-dev libbz2-dev \
- libncurses5-dev libssl-dev liblzma-dev libreadline-dev $OPENJPEG_DEV \
- libopenal-dev libglew-dev yasm $THEORA_DEV $VORBIS_DEV $OGG_DEV \
+ libfreetype6-dev libx11-dev \
+ libxcursor-dev libxi-dev wget libsqlite3-dev libxrandr-dev libxinerama-dev \
+ libbz2-dev libncurses5-dev libssl-dev liblzma-dev libreadline-dev $OPENJPEG_DEV \
+ libopenal-dev libglew-dev libglewmx-dev yasm $THEORA_DEV $VORBIS_DEV $OGG_DEV \
libsdl1.2-dev libfftw3-dev patch bzip2 libxml2-dev libtinyxml-dev"
OPENJPEG_USE=true
@@ -1972,7 +2121,7 @@ install_DEB() {
if [ $? -eq 0 ]; then
install_packages_DEB libboost-locale$boost_version-dev libboost-filesystem$boost_version-dev \
libboost-regex$boost_version-dev libboost-system$boost_version-dev \
- libboost-thread$boost_version-dev
+ libboost-thread$boost_version-dev libboost-wave$boost_version-dev
clean_Boost
else
compile_Boost
@@ -2069,6 +2218,20 @@ install_DEB() {
fi
fi
+ PRINT ""
+ if $OSD_SKIP; then
+ WARNING "Skipping OpenSubdiv installation, as requested..."
+ else
+ if $have_llvm; then
+ install_packages_DEB flex bison libtbb-dev
+ # No package currently!
+ PRINT ""
+ compile_OSD
+ else
+ WARNING "No LLVM available, cannot build OSD!"
+ fi
+ fi
+
if $WITH_OPENCOLLADA; then
PRINT ""
if $OPENCOLLADA_SKIP; then
@@ -2267,9 +2430,9 @@ install_RPM() {
OGG_DEV="libogg-devel"
THEORA_DEV="libtheora-devel"
- _packages="gcc gcc-c++ make scons libtiff-devel freetype-devel libjpeg-devel\
- libpng-devel libX11-devel libXi-devel wget ncurses-devel \
- readline-devel $OPENJPEG_DEV openal-soft-devel \
+ _packages="gcc gcc-c++ git make cmake scons libtiff-devel libjpeg-devel\
+ libpng-devel libX11-devel libXi-devel libXcursor-devel libXrandr-devel libXinerama-devel \
+ wget ncurses-devel readline-devel $OPENJPEG_DEV openal-soft-devel \
glew-devel yasm $THEORA_DEV $VORBIS_DEV $OGG_DEV patch \
libxml2-devel yaml-cpp-devel tinyxml-devel"
@@ -2281,7 +2444,7 @@ install_RPM() {
if [ $RPM = "FEDORA" -o $RPM = "RHEL" ]; then
OPENEXR_DEV="openexr-devel"
- _packages="$_packages libsqlite3x-devel fftw-devel SDL-devel"
+ _packages="$_packages freetype-devel libsqlite3x-devel fftw-devel SDL-devel"
if $WITH_ALL; then
_packages="$_packages jack-audio-connection-kit-devel"
@@ -2319,7 +2482,7 @@ install_RPM() {
elif [ $RPM = "SUSE" ]; then
OPENEXR_DEV="libopenexr-devel"
- _packages="$_packages cmake sqlite3-devel fftw3-devel libSDL-devel"
+ _packages="$_packages cmake freetype2-devel sqlite3-devel fftw3-devel libSDL-devel"
PRINT ""
install_packages_RPM $_packages
@@ -2375,7 +2538,7 @@ install_RPM() {
if $NUMPY_SKIP; then
WARNING "Skipping NumPy installation, as requested..."
else
- check_package_version_match_RPM python3-numpy $NUMPY_VERSION_MIN
+ check_package_version_ge_RPM python3-numpy $NUMPY_VERSION_MIN
if [ $? -eq 0 ]; then
install_packages_RPM python3-numpy
elif $NUMPY_REQUIRED; then
@@ -2496,7 +2659,7 @@ install_RPM() {
else
if $have_llvm; then
# No package currently!
- install_packages_RPM flex bison git
+ install_packages_RPM flex bison
if [ $RPM = "FEDORA" -o $RPM = "RHEL" ]; then
install_packages_RPM tbb-devel
fi
@@ -2507,12 +2670,29 @@ install_RPM() {
fi
fi
+ PRINT ""
+ if $OSD_SKIP; then
+ WARNING "Skipping OpenSubdiv installation, as requested..."
+ else
+ if $have_llvm; then
+ # No package currently!
+ install_packages_RPM flex bison
+ if [ $RPM = "FEDORA" -o $RPM = "RHEL" ]; then
+ install_packages_RPM tbb-devel
+ fi
+ PRINT ""
+ compile_OSD
+ else
+ WARNING "No LLVM available, cannot build OSD!"
+ fi
+ fi
+
if $WITH_OPENCOLLADA; then
PRINT ""
if $OPENCOLLADA_SKIP; then
WARNING "Skipping OpenCOLLADA installation, as requested..."
else
- install_packages_RPM pcre-devel git
+ install_packages_RPM pcre-devel
# Find path to libxml shared lib...
_XML2_LIB=`rpm -ql libxml2-devel | grep -e ".*/libxml2.so"`
# No package...
@@ -2620,7 +2800,8 @@ install_ARCH() {
OGG_DEV="libogg"
THEORA_DEV="libtheora"
- _packages="base-devel scons cmake libxi glew libpng libtiff wget openal \
+ _packages="base-devel git scons cmake \
+ libxi libxcursor libxrandr libxinerama glew libpng libtiff wget openal \
$OPENJPEG_DEV $VORBIS_DEV $OGG_DEV $THEORA_DEV yasm sdl fftw \
libxml2 yaml-cpp tinyxml"
@@ -2807,7 +2988,7 @@ install_ARCH() {
clean_OSL
else
#XXX Note: will fail to build with LLVM 3.2!
- install_packages_ARCH git intel-tbb
+ install_packages_ARCH intel-tbb
PRINT ""
compile_OSL
fi
@@ -2816,6 +2997,20 @@ install_ARCH() {
fi
fi
+ PRINT ""
+ if $OSD_SKIP; then
+ WARNING "Skipping OpenSubdiv installation, as requested..."
+ else
+ if $have_llvm; then
+ # No package currently? Just build for now!
+ install_packages_ARCH intel-tbb
+ PRINT ""
+ compile_OSD
+ else
+ WARNING "No LLVM available, cannot build OSD!"
+ fi
+ fi
+
if $WITH_OPENCOLLADA; then
PRINT ""
if $OPENCOLLADA_SKIP; then
@@ -2826,7 +3021,7 @@ install_ARCH() {
install_packages_ARCH opencollada
clean_OpenCOLLADA
else
- install_packages_ARCH pcre git
+ install_packages_ARCH pcre
PRINT ""
compile_OpenCOLLADA
fi
@@ -2927,6 +3122,10 @@ print_info() {
PRINT "Often, changes in the libs built by this script, or in your distro package, cannot be handled simply, so..."
PRINT ""
PRINT ""
+ PRINT "Ran with:"
+ PRINT " install_deps.sh $COMMANDLINE"
+ PRINT ""
+ PRINT ""
PRINT "If you're using CMake add this to your configuration flags:"
_buildargs=""
@@ -2977,7 +3176,7 @@ print_info() {
_buildargs="$_buildargs $_1"
fi
if [ -d $INST/llvm ]; then
- _1="-D LLVM_DIRECTORY=$INST/llvm"
+ _1="-D LLVM_ROOT_DIR=$INST/llvm"
_2="-D LLVM_STATIC=ON"
PRINT " $_1"
PRINT " $_2"
@@ -2991,6 +3190,14 @@ print_info() {
_buildargs="$_buildargs $_1 $_2"
fi
+ if [ -d $INST/osd ]; then
+ _1="-D WITH_OPENSUBDIV=ON"
+ _2="-D OPENSUBDIV_ROOT_DIR=$INST/osd"
+ PRINT " $_1"
+ PRINT " $_2"
+ _buildargs="$_buildargs $_1 $_2"
+ fi
+
if $WITH_OPENCOLLADA; then
_1="-D WITH_OPENCOLLADA=ON"
PRINT " $_1"
@@ -3033,10 +3240,10 @@ print_info() {
PRINT "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
+ #~ 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
PRINT "BF_OPENEXR_LIB = 'Half IlmImf$_ilm_libs_ext Iex$_ilm_libs_ext Imath$_ilm_libs_ext '"
# BF_OPENEXR_LIB does not work, things like '-lIlmImf-2_1' do not suit ld.
# For now, hack around!!!
@@ -3057,6 +3264,13 @@ print_info() {
PRINT "BF_OSL = '$INST/osl'"
fi
+ if [ "$OSD_SKIP" = false ]; then
+ PRINT "WITH_BF_OPENSUBDIV = True"
+ if [ -d $INST/osd ]; then
+ PRINT "BF_OPENSUBDIV = '$INST/osd'"
+ fi
+ fi
+
if [ "$BOOST_SKIP" = false ]; then
PRINT "WITH_BF_BOOST = True"
if [ -d $INST/boost ]; then
@@ -3103,7 +3317,27 @@ elif [ -f /etc/redhat-release -o /etc/SuSE-release ]; then
DISTRO="RPM"
install_RPM
else
- ERROR "Failed to detect distribution type"
+ ERROR "Failed to detect distribution type."
+ PRINT ""
+ PRINT "Your distribution is not supported by this script, you'll have to install dependencies and"
+ PRINT "dev packages yourself (list non-exhaustive, but should cover most needs):"
+ PRINT " * Basics of dev environment (cmake or scons, gcc, svn , git, ...)."
+ PRINT " * Python$PYTHON_VERSION_MIN, numpy."
+ PRINT " * libboost$BOOST_VERSION_MIN (locale, filesystem, regex, system, thread, wave)."
+ PRINT " * libjpeg, libpng, libtiff, libopenjpeg, libopenal."
+ PRINT " * ffmpeg (with libvorbis, libogg, libtheora, libx264, libmp3lame, libxvidcore, libvpx, ...)."
+ PRINT " * libx11, libxcursor, libxi, libxrandr, libxinerama (and other libx... as needed)."
+ PRINT " * libsqlite3, libbz2, libssl, libfftw3, libxml2, libtinyxml, yasm, libyaml-cpp."
+ PRINT " * libsdl1.2, libglew, libglewmx."
+ PRINT " * libopencolorio$OCIO_VERSION_MIN, libopenexr$OPENEXR_VERSION_MIN, libopenimageio$OIIO_VERSION_MIN."
+ PRINT " * llvm-$LLVM_VERSION (with clang)."
+ PRINT ""
+ PRINT "Most of up-listed packages are available in recent distributions. The following are likely not,"
+ PRINT "you'll have to build them (they are all optional, though):"
+ PRINT " * OpenShadingLanguage (from https://github.com/Nazg-Gul/OpenShadingLanguage.git, branch blender-fixes, commit 22ee5ea298fd215430dfbd160b5aefd507f06db0)."
+ PRINT " * OpenSubDiv (from https://github.com/PixarAnimationStudios/OpenSubdiv.git, branch dev, commit 404659fffa659da075d1c9416e4fc939139a84ee)."
+ PRINT " * OpenCollada (from https://github.com/KhronosGroup/OpenCOLLADA.git, branch master, commit 3335ac164e68b2512a40914b14c74db260e6ff7d)."
+ PRINT ""
exit 1
fi
diff --git a/build_files/buildbot/config/user-config-cuda-glibc211-i686.py b/build_files/buildbot/config/user-config-cuda-glibc211-i686.py
index 854f535398b..ae5cbac8cc7 100644
--- a/build_files/buildbot/config/user-config-cuda-glibc211-i686.py
+++ b/build_files/buildbot/config/user-config-cuda-glibc211-i686.py
@@ -2,4 +2,4 @@ BF_BUILDDIR = '../blender-build/linux-glibc211-i686'
BF_INSTALLDIR = '../blender-install/linux-glibc211-i686'
BF_NUMJOBS = 1
-BF_CYCLES_CUDA_BINARIES_ARCH = ['sm_20', 'sm_21', 'sm_30', 'sm_35', 'sm_50']
+BF_CYCLES_CUDA_BINARIES_ARCH = ['sm_20', 'sm_21', 'sm_30', 'sm_35', 'sm_50', 'sm_52']
diff --git a/build_files/buildbot/config/user-config-cuda-glibc211-x86_64.py b/build_files/buildbot/config/user-config-cuda-glibc211-x86_64.py
index 7e928948762..29b1b9f1ad7 100644
--- a/build_files/buildbot/config/user-config-cuda-glibc211-x86_64.py
+++ b/build_files/buildbot/config/user-config-cuda-glibc211-x86_64.py
@@ -2,4 +2,4 @@ BF_BUILDDIR = '../blender-build/linux-glibc211-x86_64'
BF_INSTALLDIR = '../blender-install/linux-glibc211-x86_64'
BF_NUMJOBS = 1
-BF_CYCLES_CUDA_BINARIES_ARCH = ['sm_20', 'sm_21', 'sm_30', 'sm_35', 'sm_50']
+BF_CYCLES_CUDA_BINARIES_ARCH = ['sm_20', 'sm_21', 'sm_30', 'sm_35', 'sm_50', 'sm_52']
diff --git a/build_files/buildbot/config/user-config-glibc211-i686.py b/build_files/buildbot/config/user-config-glibc211-i686.py
index 0971735f641..239625c1bef 100644
--- a/build_files/buildbot/config/user-config-glibc211-i686.py
+++ b/build_files/buildbot/config/user-config-glibc211-i686.py
@@ -79,6 +79,8 @@ WITH_BF_STATICZLIB = True
BF_ZLIB_LIB_STATIC = '${BF_ZLIB}/lib/libz.a'
WITH_BF_SDL = True
+WITH_BF_SDL_DYNLOAD = True
+
WITH_BF_OGG = True
WITH_BF_OPENMP = True
@@ -122,13 +124,15 @@ BF_OIIO_INC = '${BF_OIIO}/include'
BF_OIIO_LIB_STATIC = '${BF_OIIO_LIBPATH}/libOpenImageIO.a ${BF_OPENEXR}/lib/libIlmImf.a ${BF_JPEG}/lib/libjpeg.a'
BF_OIIO_LIBPATH = '${BF_OIIO}/lib'
+BF_IS_NEW_OSL = False
WITH_BF_CYCLES_OSL = True
-WITH_BF_STATICOSL = False
+WITH_BF_STATICOSL = BF_IS_NEW_OSL
BF_OSL = '/opt/lib/osl'
BF_OSL_INC = '${BF_OSL}/include'
# note oslexec would passed via program linkflags, which is needed to
# make llvm happy with osl_allocate_closure_component
BF_OSL_LIB = 'oslcomp oslexec oslquery'
+BF_OSL_LIB_STATIC = '${BF_OSL}/lib/liboslcomp.a ${BF_OSL}/lib/liboslexec.a ${BF_OSL}/lib/liboslquery.a'
BF_OSL_LIBPATH = '${BF_OSL}/lib'
BF_OSL_COMPILER = '${BF_OSL}/bin/oslc'
@@ -155,13 +159,27 @@ BF_BOOST_INC = '${BF_BOOST}/include'
BF_BOOST_LIB_STATIC = '${BF_BOOST_LIBPATH}/libboost_filesystem.a ${BF_BOOST_LIBPATH}/libboost_date_time.a ' + \
'${BF_BOOST_LIBPATH}/libboost_regex.a ${BF_BOOST_LIBPATH}/libboost_locale.a ${BF_BOOST_LIBPATH}/libboost_system.a \
${BF_BOOST_LIBPATH}/libboost_thread.a'
+if BF_IS_NEW_OSL:
+ BF_BOOST_LIB_STATIC += ' ${BF_BOOST_LIBPATH}/libboost_wave.a'
BF_BOOST_LIBPATH = '${BF_BOOST}/lib'
# Ocean Simulation
WITH_BF_OCEANSIM = True
+# OpenSubdiv
+WITH_BF_OPENSUBDIV = True
+WITH_BF_STATICOPENSUBDIV = True
+BF_OPENSUBDIV = '/opt/lib/opensubdiv'
+BF_OPENSUBDIV_INC = '${BF_OPENSUBDIV}/include'
+BF_OPENSUBDIV_LIB = 'osdCPU osdGPU'
+BF_OPENSUBDIV_LIBPATH = '${BF_OPENSUBDIV}/lib'
+BF_OPENSUBDIV_LIB_STATIC = '${BF_OPENSUBDIV}/lib/libosdCPU.a ${BF_OPENSUBDIV}/lib/libosdGPU.a'
+
# Compilation and optimization
BF_DEBUG = False
REL_CCFLAGS = ['-DNDEBUG', '-O2', '-msse', '-msse2'] # C & C++
PLATFORM_LINKFLAGS = ['-lrt']
-BF_PROGRAM_LINKFLAGS = ['-Wl,--whole-archive', '-loslexec', '-Wl,--no-whole-archive', '-Wl,--version-script=source/creator/blender.map']
+if BF_IS_NEW_OSL:
+ BF_PROGRAM_LINKFLAGS = ['-Wl,--version-script=source/creator/blender.map']
+else:
+ BF_PROGRAM_LINKFLAGS = ['-Wl,--whole-archive', '-loslexec', '-Wl,--no-whole-archive', '-Wl,--version-script=source/creator/blender.map']
diff --git a/build_files/buildbot/config/user-config-glibc211-x86_64.py b/build_files/buildbot/config/user-config-glibc211-x86_64.py
index 748d1004850..a3195cd9f06 100644
--- a/build_files/buildbot/config/user-config-glibc211-x86_64.py
+++ b/build_files/buildbot/config/user-config-glibc211-x86_64.py
@@ -79,6 +79,8 @@ WITH_BF_STATICZLIB = True
BF_ZLIB_LIB_STATIC = '${BF_ZLIB}/lib/libz.a'
WITH_BF_SDL = True
+WITH_BF_SDL_DYNLOAD = True
+
WITH_BF_OGG = True
WITH_BF_OPENMP = True
@@ -122,13 +124,15 @@ BF_OIIO_INC = '${BF_OIIO}/include'
BF_OIIO_LIB_STATIC = '${BF_OIIO_LIBPATH}/libOpenImageIO.a ${BF_OPENEXR}/lib/libIlmImf.a ${BF_JPEG}/lib/libjpeg.a'
BF_OIIO_LIBPATH = '${BF_OIIO}/lib'
+BF_IS_NEW_OSL = False
WITH_BF_CYCLES_OSL = True
-WITH_BF_STATICOSL = False
+WITH_BF_STATICOSL = BF_IS_NEW_OSL
BF_OSL = '/opt/lib/osl'
BF_OSL_INC = '${BF_OSL}/include'
# note oslexec would passed via program linkflags, which is needed to
# make llvm happy with osl_allocate_closure_component
BF_OSL_LIB = 'oslcomp oslexec oslquery'
+BF_OSL_LIB_STATIC = '${BF_OSL}/lib/liboslcomp.a ${BF_OSL}/lib/liboslexec.a ${BF_OSL}/lib/liboslquery.a'
BF_OSL_LIBPATH = '${BF_OSL}/lib'
BF_OSL_COMPILER = '${BF_OSL}/bin/oslc'
@@ -155,13 +159,27 @@ BF_BOOST_INC = '${BF_BOOST}/include'
BF_BOOST_LIB_STATIC = '${BF_BOOST_LIBPATH}/libboost_filesystem.a ${BF_BOOST_LIBPATH}/libboost_date_time.a ' + \
'${BF_BOOST_LIBPATH}/libboost_regex.a ${BF_BOOST_LIBPATH}/libboost_locale.a ${BF_BOOST_LIBPATH}/libboost_system.a \
${BF_BOOST_LIBPATH}/libboost_thread.a'
+if BF_IS_NEW_OSL:
+ BF_BOOST_LIB_STATIC += ' ${BF_BOOST_LIBPATH}/libboost_wave.a'
BF_BOOST_LIBPATH = '${BF_BOOST}/lib'
# Ocean Simulation
WITH_BF_OCEANSIM = True
+# OpenSubdiv
+WITH_BF_OPENSUBDIV = True
+WITH_BF_STATICOPENSUBDIV = True
+BF_OPENSUBDIV = '/opt/lib/opensubdiv'
+BF_OPENSUBDIV_INC = '${BF_OPENSUBDIV}/include'
+BF_OPENSUBDIV_LIB = 'osdCPU osdGPU'
+BF_OPENSUBDIV_LIBPATH = '${BF_OPENSUBDIV}/lib'
+BF_OPENSUBDIV_LIB_STATIC = '${BF_OPENSUBDIV}/lib/libosdCPU.a ${BF_OPENSUBDIV}/lib/libosdGPU.a'
+
# Compilation and optimization
BF_DEBUG = False
REL_CCFLAGS = ['-DNDEBUG', '-O2', '-msse', '-msse2'] # C & C++
PLATFORM_LINKFLAGS = ['-lrt']
-BF_PROGRAM_LINKFLAGS = ['-Wl,--whole-archive', '-loslexec', '-Wl,--no-whole-archive', '-Wl,--version-script=source/creator/blender.map']
+if BF_IS_NEW_OSL:
+ BF_PROGRAM_LINKFLAGS = ['-Wl,--version-script=source/creator/blender.map']
+else:
+ BF_PROGRAM_LINKFLAGS = ['-Wl,--whole-archive', '-loslexec', '-Wl,--no-whole-archive', '-Wl,--version-script=source/creator/blender.map']
diff --git a/build_files/buildbot/config/user-config-mac-i386.py b/build_files/buildbot/config/user-config-mac-i386.py
index ab93628c78d..c1beefcf83d 100644
--- a/build_files/buildbot/config/user-config-mac-i386.py
+++ b/build_files/buildbot/config/user-config-mac-i386.py
@@ -5,3 +5,5 @@ WITH_BF_CYCLES_CUDA_BINARIES = True
WITH_BF_CYCLES_OSL = False # OSL never worked on OSX 32bit !
+WITH_BF_COLLADA = False # we drop 32bit, newest collada is only x86_64 !
+
diff --git a/build_files/buildbot/config/user-config-mac-x86_64.py b/build_files/buildbot/config/user-config-mac-x86_64.py
index ac923f48abe..6a13c80f6ce 100644
--- a/build_files/buildbot/config/user-config-mac-x86_64.py
+++ b/build_files/buildbot/config/user-config-mac-x86_64.py
@@ -1,5 +1,6 @@
+CC = "../lib/darwin-9.x.universal/clang-omp-3.5/bin/clang"
+CXX = "../lib/darwin-9.x.universal/clang-omp-3.5/bin/clang++"
MACOSX_ARCHITECTURE = 'x86_64' # valid archs: ppc, i386, ppc64, x86_64
WITH_BF_CYCLES_CUDA_BINARIES = True
-
diff --git a/build_files/buildbot/config/user-config-player-glibc211-i686.py b/build_files/buildbot/config/user-config-player-glibc211-i686.py
index 384da4070eb..b3c26ebb310 100644
--- a/build_files/buildbot/config/user-config-player-glibc211-i686.py
+++ b/build_files/buildbot/config/user-config-player-glibc211-i686.py
@@ -64,6 +64,8 @@ WITH_BF_STATICZLIB = True
BF_ZLIB_LIB_STATIC = '${BF_ZLIB}/lib/libz.a'
WITH_BF_SDL = True
+WITH_BF_SDL_DYNLOAD = True
+
WITH_BF_OGG = False
WITH_BF_OPENMP = True
diff --git a/build_files/buildbot/config/user-config-player-glibc211-x86_64.py b/build_files/buildbot/config/user-config-player-glibc211-x86_64.py
index 5176d59d5a0..173e15b08ca 100644
--- a/build_files/buildbot/config/user-config-player-glibc211-x86_64.py
+++ b/build_files/buildbot/config/user-config-player-glibc211-x86_64.py
@@ -64,6 +64,8 @@ WITH_BF_STATICZLIB = True
BF_ZLIB_LIB_STATIC = '${BF_ZLIB}/lib/libz.a'
WITH_BF_SDL = True
+WITH_BF_SDL_DYNLOAD = True
+
WITH_BF_OGG = False
WITH_BF_OPENMP = True
diff --git a/build_files/buildbot/master.cfg b/build_files/buildbot/master.cfg
index 5f315337d3a..7b8dd175453 100644
--- a/build_files/buildbot/master.cfg
+++ b/build_files/buildbot/master.cfg
@@ -3,6 +3,12 @@
# <pep8 compliant>
+# List of the branches being built automatically overnight
+NIGHT_SCHEDULE_BRANCHES = [None]
+
+# List of the branches available for force build
+FORCE_SCHEDULE_BRANCHES = ["master", "gooseberry", "experimental-build"]
+
"""
Stock Twisted directory lister doesn't provide any information about last file
modification time, we hack the class a bit in order to have such functionaliity
@@ -92,6 +98,7 @@ all_repositories = {
r'https://svn.blender.org/svnroot/bf-blender/': 'lib svn',
}
+
def codebaseGenerator(chdict):
return all_repositories[chdict['repository']]
@@ -107,13 +114,14 @@ from buildbot.schedulers import timed, forcesched
c['schedulers'] = []
+
def schedule_force_build(name):
c['schedulers'].append(forcesched.ForceScheduler(name='force ' + name,
builderNames=[name],
codebases=[forcesched.CodebaseParameter(
codebase="blender",
branch=forcesched.ChoiceStringParameter(
- name="branch", choices=["master", "testbuild"], default="master"),
+ name="branch", choices=FORCE_SCHEDULE_BRANCHES, default="master"),
# Do not hide revision, can be handy!
repository=forcesched.FixedParameter(name="repository", default="", hide=True),
project=forcesched.FixedParameter(name="project", default="", hide=True)),
@@ -127,18 +135,22 @@ def schedule_force_build(name):
def schedule_build(name, hour, minute=0):
- c['schedulers'].append(timed.Nightly(name='nightly ' + name,
- codebases={
- "blender": {"repository": ""},
- "blender-translations": {"repository": ""},
- "blender-addons": {"repository": ""},
- "blender-addons-contrib": {"repository": ""},
- "scons": {"repository": ""},
- "lib svn": {"repository": ""}},
- branch=None,
- builderNames=[name],
- hour=hour,
- minute=minute))
+ for current_branch in NIGHT_SCHEDULE_BRANCHES:
+ scheduler_name = "nightly " + name
+ if current_branch:
+ scheduler_name += ' ' + current_branch
+ c['schedulers'].append(timed.Nightly(name=scheduler_name,
+ codebases={
+ "blender": {"repository": ""},
+ "blender-translations": {"repository": "", "branch": "master"},
+ "blender-addons": {"repository": "", "branch": "master"},
+ "blender-addons-contrib": {"repository": "", "branch": "master"},
+ "scons": {"repository": "", "branch": "master"},
+ "lib svn": {"repository": "", "branch": "trunk"}},
+ branch=current_branch,
+ builderNames=[name],
+ hour=hour,
+ minute=minute))
# BUILDERS
@@ -293,10 +305,12 @@ add_builder(c, 'mac_x86_64_10_6_scons', 'darwin-9.x.universal', generic_builder,
add_builder(c, 'mac_i386_10_6_scons', 'darwin-9.x.universal', generic_builder, hour=11)
add_builder(c, 'linux_glibc211_i386_scons', '', generic_builder, hour=1)
add_builder(c, 'linux_glibc211_x86_64_scons', '', generic_builder, hour=2)
-add_builder(c, 'win32_scons_vc2013', 'windows_vc12', generic_builder, hour=1)
-add_builder(c, 'win64_scons_vc2013', 'win64_vc12', generic_builder, hour=2)
+#add_builder(c, 'win32_scons_vc2013', 'windows_vc12', generic_builder, hour=1)
+#add_builder(c, 'win64_scons_vc2013', 'win64_vc12', generic_builder, hour=2)
+add_builder(c, 'win32_cmake_vc2013', 'windows_vc12', generic_builder, hour=3)
+add_builder(c, 'win64_cmake_vc2013', 'win64_vc12', generic_builder, hour=4)
#add_builder(c, 'mingw_win32_scons', 'mingw32', generic_builder, hour=4)
-add_builder(c, 'mingw_win64_scons', 'mingw64', generic_builder, hour=3)
+#add_builder(c, 'mingw_win64_scons', 'mingw64', generic_builder, hour=3)
#add_builder(c, 'freebsd_i386_cmake', '', generic_builder, hour=1)
#add_builder(c, 'freebsd_x86_64_cmake', '', generic_builder, hour=2)
diff --git a/build_files/buildbot/master_unpack.py b/build_files/buildbot/master_unpack.py
index ecacf3bff6f..ec44705931c 100644
--- a/build_files/buildbot/master_unpack.py
+++ b/build_files/buildbot/master_unpack.py
@@ -30,11 +30,12 @@ import zipfile
# extension stripping
def strip_extension(filename):
extensions = '.zip', '.tar', '.bz2', '.gz', '.tgz', '.tbz', '.exe'
- filename_noext, ext = os.path.splitext(filename)
- if ext in extensions:
- return strip_extension(filename_noext) # may have .tar.bz2
- else:
- return filename
+
+ for ext in extensions:
+ if filename.endswith(ext):
+ filename = filename[:-len(ext)]
+
+ return filename
# extract platform from package name
@@ -48,12 +49,11 @@ def get_platform(filename):
tokens = filename.split("-")
platforms = ('osx', 'mac', 'bsd',
'win', 'linux', 'source',
- 'solaris',
- 'mingw')
+ 'irix', 'solaris', 'mingw')
platform_tokens = []
found = False
- for token in tokens:
+ for i, token in enumerate(tokens):
if not found:
for platform in platforms:
if platform in token.lower():
@@ -71,14 +71,14 @@ def get_branch(filename):
branch = ""
for token in tokens:
+ if token == "blender":
+ return branch
+
if branch == "":
branch = token
else:
branch = branch + "-" + token
- if token == "blender":
- return branch
-
return ""
# get filename
@@ -95,7 +95,7 @@ if not os.path.exists(filename):
try:
z = zipfile.ZipFile(filename, "r")
-except Exception, ex:
+except Exception as ex:
sys.stderr.write('Failed to open zip file: %s\n' % str(ex))
sys.exit(1)
@@ -112,23 +112,28 @@ branch = get_branch(packagename)
if platform == '':
sys.stderr.write('Failed to detect platform ' +
- 'from package: %r\n' % packagename)
+ 'from package: %r\n' % packagename)
sys.exit(1)
# extract
-directory = 'public_html/download'
+if not branch or branch == 'master':
+ directory = 'public_html/download'
+elif branch == 'experimental-build':
+ directory = 'public_html/download/experimental'
+else:
+ directory = 'public_html/download'
try:
+ filename = os.path.join(directory, packagename)
zf = z.open(package)
- f = file(os.path.join(directory, packagename), "wb")
+ f = file(filename, "wb")
shutil.copyfileobj(zf, f)
+ os.chmod(filename, 0644)
zf.close()
z.close()
-
- os.remove(filename)
-except Exception, ex:
+except Exception as ex:
sys.stderr.write('Failed to unzip package: %s\n' % str(ex))
sys.exit(1)
@@ -138,6 +143,6 @@ try:
if get_platform(f) == platform and get_branch(f) == branch:
if f != packagename:
os.remove(os.path.join(directory, f))
-except Exception, ex:
+except Exception as ex:
sys.stderr.write('Failed to remove old packages: %s\n' % str(ex))
sys.exit(1)
diff --git a/build_files/buildbot/slave_compile.py b/build_files/buildbot/slave_compile.py
index a5dadbde05c..d30241a9e5c 100644
--- a/build_files/buildbot/slave_compile.py
+++ b/build_files/buildbot/slave_compile.py
@@ -33,7 +33,7 @@ builder = sys.argv[1]
# we run from build/ directory
blender_dir = '../blender.git'
-if builder.find('cmake') != -1:
+if 'cmake' in builder:
# cmake
# set build options
@@ -46,11 +46,24 @@ if builder.find('cmake') != -1:
elif builder.endswith('mac_ppc_cmake'):
cmake_options.append('-DCMAKE_OSX_ARCHITECTURES:STRING=ppc')
+ if 'win64' in builder:
+ cmake_options.append(['-G', '"Visual Studio 12 2013 Win64"'])
+ elif 'win32' in builder:
+ cmake_options.append(['-G', '"Visual Studio 12 2013"'])
+
+ cmake_options.append("-C../blender.git/build_files/cmake/config/blender_full.cmake")
+ cmake_options.append("-DWITH_CYCLES_CUDA_BINARIES=1")
# configure and make
retcode = subprocess.call(['cmake', blender_dir] + cmake_options)
if retcode != 0:
sys.exit(retcode)
- retcode = subprocess.call(['make', '-s', '-j4', 'install'])
+
+ if 'win32' in builder:
+ retcode = subprocess.call(['msbuild', 'INSTALL.vcxproj', '/Property:PlatformToolset=v120_xp', '/p:Configuration=Release'])
+ elif 'win64' in builder:
+ retcode = subprocess.call(['msbuild', 'INSTALL.vcxproj', '/p:Configuration=Release'])
+ else:
+ retcode = subprocess.call(['make', '-s', '-j4', 'install'])
sys.exit(retcode)
else:
python_bin = 'python'
@@ -106,6 +119,8 @@ else:
if config.find('player') != -1:
scons_options.append('BF_BUILDDIR=%s_player' % (build_dir))
+ elif config.find('cuda') != -1:
+ scons_options.append('BF_BUILDDIR=%s_cuda' % (build_dir))
else:
scons_options.append('BF_BUILDDIR=%s' % (build_dir))
@@ -130,7 +145,7 @@ else:
retcode = subprocess.call(cur_scons_cmd + scons_options)
if retcode != 0:
- print('Error building rules wuth config ' + config)
+ print('Error building rules with config ' + config)
sys.exit(retcode)
sys.exit(0)
diff --git a/build_files/buildbot/slave_pack.py b/build_files/buildbot/slave_pack.py
index c989cd8e31a..aec7cdca80a 100644
--- a/build_files/buildbot/slave_pack.py
+++ b/build_files/buildbot/slave_pack.py
@@ -115,6 +115,40 @@ if builder.find('scons') != -1:
retcode = subprocess.call([python_bin, 'scons/scons.py'] + scons_options)
sys.exit(retcode)
+else:
+ # CMake
+ if 'win' in builder:
+ files = [f for f in os.listdir('.') if os.path.isfile(f) and f.endswith('.zip')]
+ for f in files:
+ os.remove(f)
+ retcode = subprocess.call(['cpack', '-G', 'ZIP'])
+ result_file = [f for f in os.listdir('.') if os.path.isfile(f) and f.endswith('.zip')][0]
+
+ # TODO(sergey): Such magic usually happens in SCon's packaging bu we don't have it
+ # in the CMake yet. For until then we do some magic here.
+ tokens = result_file.split('-')
+ blender_version = tokens[1].split('.')
+ blender_full_version = '.'.join(blender_version[0:2])
+ git_hash = tokens[2].split('.')[1]
+ platform = builder.split('_')[0]
+ builderified_name = 'blender-{}-{}-{}'.format(blender_full_version, git_hash, platform)
+ if branch != '':
+ builderified_name = branch + "-" + builderified_name
+
+ os.rename(result_file, "{}.zip".format(builderified_name))
+ # create zip file
+ try:
+ upload_zip = "buildbot_upload.zip"
+ if os.path.exists(upload_zip):
+ os.remove(upload_zip)
+ z = zipfile.ZipFile(upload_zip, "w", compression=zipfile.ZIP_STORED)
+ z.write("{}.zip".format(builderified_name))
+ z.close()
+ sys.exit(retcode)
+ except Exception as ex:
+ sys.stderr.write('Create buildbot_upload.zip failed' + str(ex) + '\n')
+ sys.exit(1)
+
# clean release directory if it already exists
release_dir = 'release'
@@ -127,7 +161,7 @@ if os.path.exists(release_dir):
# create release package
try:
subprocess.call(['make', 'package_archive'])
-except Exception, ex:
+except Exception as ex:
sys.stderr.write('Make package release failed' + str(ex) + '\n')
sys.exit(1)
@@ -158,6 +192,6 @@ try:
z = zipfile.ZipFile(upload_zip, "w", compression=zipfile.ZIP_STORED)
z.write(filepath, arcname=file)
z.close()
-except Exception, ex:
+except Exception as ex:
sys.stderr.write('Create buildbot_upload.zip failed' + str(ex) + '\n')
sys.exit(1)
diff --git a/build_files/cmake/Modules/FindAudaspace.cmake b/build_files/cmake/Modules/FindAudaspace.cmake
new file mode 100644
index 00000000000..c332ef9a039
--- /dev/null
+++ b/build_files/cmake/Modules/FindAudaspace.cmake
@@ -0,0 +1,113 @@
+# - Try to find audaspace
+# Once done, this will define
+#
+# AUDASPACE_FOUND - system has audaspace
+# AUDASPACE_INCLUDE_DIRS - the audaspace include directories
+# AUDASPACE_LIBRARIES - link these to use audaspace
+# AUDASPACE_C_FOUND - system has audaspace's C binding
+# AUDASPACE_C_INCLUDE_DIRS - the audaspace's C binding include directories
+# AUDASPACE_C_LIBRARIES - link these to use audaspace's C binding
+# AUDASPACE_PY_FOUND - system has audaspace's python binding
+# AUDASPACE_PY_INCLUDE_DIRS - the audaspace's python binding include directories
+# AUDASPACE_PY_LIBRARIES - link these to use audaspace's python binding
+
+IF(NOT AUDASPACE_ROOT_DIR AND NOT $ENV{AUDASPACE_ROOT_DIR} STREQUAL "")
+ SET(AUDASPACE_ROOT_DIR $ENV{AUDASPACE_ROOT_DIR})
+ENDIF()
+
+SET(_audaspace_SEARCH_DIRS
+ ${AUDASPACE_ROOT_DIR}
+ /usr/local
+ /sw # Fink
+ /opt/local # DarwinPorts
+ /opt/csw # Blastwave
+)
+
+# Use pkg-config to get hints about paths
+FIND_PACKAGE(PkgConfig)
+IF(PKG_CONFIG_FOUND)
+ PKG_CHECK_MODULES(AUDASPACE_PKGCONF audaspace)
+ENDIF(PKG_CONFIG_FOUND)
+
+# Include dir
+FIND_PATH(AUDASPACE_INCLUDE_DIR
+ NAMES ISound.h
+ HINTS ${_audaspace_SEARCH_DIRS}
+ PATHS ${AUDASPACE_PKGCONF_INCLUDE_DIRS}
+ PATH_SUFFIXES include/audaspace
+)
+
+# Library
+FIND_LIBRARY(AUDASPACE_LIBRARY
+ NAMES audaspace
+ HINTS ${_audaspace_SEARCH_DIRS}
+ PATHS ${AUDASPACE_PKGCONF_LIBRARY_DIRS}
+ PATH_SUFFIXES lib lib64
+)
+
+# Include dir
+FIND_PATH(AUDASPACE_C_INCLUDE_DIR
+ NAMES AUD_Sound.h
+ HINTS ${_audaspace_SEARCH_DIRS}
+ PATHS ${AUDASPACE_PKGCONF_INCLUDE_DIRS}
+ PATH_SUFFIXES include/audaspace
+)
+
+# Library
+FIND_LIBRARY(AUDASPACE_C_LIBRARY
+ NAMES audaspace-c
+ HINTS ${_audaspace_SEARCH_DIRS}
+ PATHS ${AUDASPACE_PKGCONF_LIBRARY_DIRS}
+ PATH_SUFFIXES lib lib64
+)
+
+# Include dir
+FIND_PATH(AUDASPACE_PY_INCLUDE_DIR
+ NAMES python/PyAPI.h
+ HINTS ${_audaspace_SEARCH_DIRS}
+ PATHS ${AUDASPACE_PKGCONF_INCLUDE_DIRS}
+ PATH_SUFFIXES include/audaspace
+)
+
+# Library
+FIND_LIBRARY(AUDASPACE_PY_LIBRARY
+ NAMES audaspace-py
+ HINTS ${_audaspace_SEARCH_DIRS}
+ PATHS ${AUDASPACE_PKGCONF_LIBRARY_DIRS}
+ PATH_SUFFIXES lib lib64
+)
+
+FIND_PACKAGE(PackageHandleStandardArgs)
+FIND_PACKAGE_HANDLE_STANDARD_ARGS(Audaspace DEFAULT_MSG AUDASPACE_LIBRARY AUDASPACE_INCLUDE_DIR)
+FIND_PACKAGE_HANDLE_STANDARD_ARGS(Audaspace_C DEFAULT_MSG AUDASPACE_C_LIBRARY AUDASPACE_C_INCLUDE_DIR)
+FIND_PACKAGE_HANDLE_STANDARD_ARGS(Audaspace_Py DEFAULT_MSG AUDASPACE_PY_LIBRARY AUDASPACE_PY_INCLUDE_DIR)
+
+IF(AUDASPACE_FOUND)
+ SET(AUDASPACE_LIBRARIES ${AUDASPACE_LIBRARY})
+ SET(AUDASPACE_INCLUDE_DIRS ${AUDASPACE_INCLUDE_DIR})
+ENDIF(AUDASPACE_FOUND)
+
+IF(AUDASPACE_C_FOUND)
+ SET(AUDASPACE_C_LIBRARIES ${AUDASPACE_C_LIBRARY})
+ SET(AUDASPACE_C_INCLUDE_DIRS ${AUDASPACE_C_INCLUDE_DIR})
+ENDIF(AUDASPACE_C_FOUND)
+
+IF(AUDASPACE_PY_FOUND)
+ SET(AUDASPACE_PY_LIBRARIES ${AUDASPACE_PY_LIBRARY})
+ SET(AUDASPACE_PY_INCLUDE_DIRS ${AUDASPACE_PY_INCLUDE_DIR})
+ENDIF(AUDASPACE_PY_FOUND)
+
+MARK_AS_ADVANCED(
+ AUDASPACE_LIBRARY
+ AUDASPACE_LIBRARIES
+ AUDASPACE_INCLUDE_DIR
+ AUDASPACE_INCLUDE_DIRS
+ AUDASPACE_C_LIBRARY
+ AUDASPACE_C_LIBRARIES
+ AUDASPACE_C_INCLUDE_DIR
+ AUDASPACE_C_INCLUDE_DIRS
+ AUDASPACE_PY_LIBRARY
+ AUDASPACE_PY_LIBRARIES
+ AUDASPACE_PY_INCLUDE_DIR
+ AUDASPACE_PY_INCLUDE_DIRS
+)
diff --git a/build_files/cmake/Modules/FindEigen3.cmake b/build_files/cmake/Modules/FindEigen3.cmake
new file mode 100644
index 00000000000..400e8eb047d
--- /dev/null
+++ b/build_files/cmake/Modules/FindEigen3.cmake
@@ -0,0 +1,56 @@
+# - Find Eigen3 library
+# Find the native Eigen3 includes and library
+# This module defines
+# EIGEN3_INCLUDE_DIRS, where to find spnav.h, Set when
+# EIGEN3_INCLUDE_DIR is found.
+# EIGEN3_ROOT_DIR, The base directory to search for Eigen3.
+# This can also be an environment variable.
+# EIGEN3_FOUND, If false, do not try to use Eigen3.
+#
+#=============================================================================
+# Copyright 2015 Blender Foundation.
+#
+# Distributed under the OSI-approved BSD License (the "License");
+# see accompanying file Copyright.txt for details.
+#
+# This software is distributed WITHOUT ANY WARRANTY; without even the
+# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# See the License for more information.
+#=============================================================================
+
+# If EIGEN3_ROOT_DIR was defined in the environment, use it.
+IF(NOT EIGEN3_ROOT_DIR AND NOT $ENV{EIGEN3_ROOT_DIR} STREQUAL "")
+ SET(EIGEN3_ROOT_DIR $ENV{EIGEN3_ROOT_DIR})
+ENDIF()
+
+SET(_eigen3_SEARCH_DIRS
+ ${EIGEN3_ROOT_DIR}
+ /usr/local
+ /sw # Fink
+ /opt/local # DarwinPorts
+ /opt/csw # Blastwave
+)
+
+FIND_PATH(EIGEN3_INCLUDE_DIR
+ NAMES
+ # header has no '.h' suffix
+ Eigen/Eigen
+ HINTS
+ ${_eigen3_SEARCH_DIRS}
+ PATH_SUFFIXES
+ include/eigen3
+)
+
+# handle the QUIETLY and REQUIRED arguments and set EIGEN3_FOUND to TRUE if
+# all listed variables are TRUE
+INCLUDE(FindPackageHandleStandardArgs)
+FIND_PACKAGE_HANDLE_STANDARD_ARGS(Eigen3 DEFAULT_MSG
+ EIGEN3_INCLUDE_DIR)
+
+IF(EIGEN3_FOUND)
+ SET(EIGEN3_INCLUDE_DIRS ${EIGEN3_INCLUDE_DIR})
+ENDIF(EIGEN3_FOUND)
+
+MARK_AS_ADVANCED(
+ EIGEN3_INCLUDE_DIR
+)
diff --git a/build_files/cmake/Modules/FindGLEW.cmake b/build_files/cmake/Modules/FindGLEW.cmake
index 8589e143ada..2f098d5d9a4 100644
--- a/build_files/cmake/Modules/FindGLEW.cmake
+++ b/build_files/cmake/Modules/FindGLEW.cmake
@@ -75,3 +75,5 @@ MARK_AS_ADVANCED(
GLEW_LIBRARY
GLEW_MX_LIBRARY
)
+
+UNSET(_glew_SEARCH_DIRS)
diff --git a/build_files/cmake/Modules/FindJeMalloc.cmake b/build_files/cmake/Modules/FindJeMalloc.cmake
index 5c7aa2cf1e1..466456baf32 100644
--- a/build_files/cmake/Modules/FindJeMalloc.cmake
+++ b/build_files/cmake/Modules/FindJeMalloc.cmake
@@ -33,6 +33,7 @@ SET(_jemalloc_SEARCH_DIRS
/sw # Fink
/opt/local # DarwinPorts
/opt/csw # Blastwave
+ /opt/lib/jemalloc
)
FIND_PATH(JEMALLOC_INCLUDE_DIR
diff --git a/build_files/cmake/Modules/FindLLVM.cmake b/build_files/cmake/Modules/FindLLVM.cmake
new file mode 100644
index 00000000000..43791c8df8c
--- /dev/null
+++ b/build_files/cmake/Modules/FindLLVM.cmake
@@ -0,0 +1,94 @@
+# - Find LLVM library
+# Find the native LLVM includes and library
+# This module defines
+# LLVM_INCLUDE_DIRS, where to find LLVM.h, Set when LLVM_INCLUDE_DIR is found.
+# LLVM_LIBRARIES, libraries to link against to use LLVM.
+# LLVM_ROOT_DIR, The base directory to search for LLVM.
+# This can also be an environment variable.
+# LLVM_FOUND, If false, do not try to use LLVM.
+#
+# also defined, but not for general use are
+# LLVM_LIBRARY, where to find the LLVM library.
+
+#=============================================================================
+# Copyright 2015 Blender Foundation.
+#
+# Distributed under the OSI-approved BSD License (the "License");
+# see accompanying file Copyright.txt for details.
+#
+# This software is distributed WITHOUT ANY WARRANTY; without even the
+# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# See the License for more information.
+#=============================================================================
+
+if(LLVM_ROOT_DIR)
+ if(DEFINED LLVM_VERSION)
+ find_program(LLVM_CONFIG llvm-config-${LLVM_VERSION} HINTS ${LLVM_ROOT_DIR}/bin NO_CMAKE_PATH)
+ endif()
+ if(NOT LLVM_CONFIG)
+ find_program(LLVM_CONFIG llvm-config HINTS ${LLVM_ROOT_DIR}/bin NO_CMAKE_PATH)
+ endif()
+else()
+ if(DEFINED LLVM_VERSION)
+ message(running llvm-config-${LLVM_VERSION})
+ find_program(LLVM_CONFIG llvm-config-${LLVM_VERSION})
+ endif()
+ if(NOT LLVM_CONFIG)
+ find_program(LLVM_CONFIG llvm-config)
+ endif()
+endif()
+
+if(NOT DEFINED LLVM_VERSION)
+ execute_process(COMMAND ${LLVM_CONFIG} --version
+ OUTPUT_VARIABLE LLVM_VERSION
+ OUTPUT_STRIP_TRAILING_WHITESPACE)
+ set(LLVM_VERSION ${LLVM_VERSION} CACHE STRING "Version of LLVM to use")
+endif()
+if(NOT LLVM_ROOT_DIR)
+ execute_process(COMMAND ${LLVM_CONFIG} --prefix
+ OUTPUT_VARIABLE LLVM_ROOT_DIR
+ OUTPUT_STRIP_TRAILING_WHITESPACE)
+ set(LLVM_ROOT_DIR ${LLVM_ROOT_DIR} CACHE PATH "Path to the LLVM installation")
+endif()
+if(NOT LLVM_LIBPATH)
+ execute_process(COMMAND ${LLVM_CONFIG} --libdir
+ OUTPUT_VARIABLE LLVM_LIBPATH
+ OUTPUT_STRIP_TRAILING_WHITESPACE)
+ set(LLVM_LIBPATH ${LLVM_LIBPATH} CACHE PATH "Path to the LLVM library path")
+ mark_as_advanced(LLVM_LIBPATH)
+endif()
+
+if(LLVM_STATIC)
+ find_library(LLVM_LIBRARY
+ NAMES LLVMAnalysis # first of a whole bunch of libs to get
+ PATHS ${LLVM_LIBPATH})
+else()
+ find_library(LLVM_LIBRARY
+ NAMES LLVM-${LLVM_VERSION}
+ PATHS ${LLVM_LIBPATH})
+endif()
+
+
+if(LLVM_LIBRARY AND LLVM_ROOT_DIR AND LLVM_LIBPATH)
+ if(LLVM_STATIC)
+ # if static LLVM libraries were requested, use llvm-config to generate
+ # the list of what libraries we need, and substitute that in the right
+ # way for LLVM_LIBRARY.
+ execute_process(COMMAND ${LLVM_CONFIG} --libfiles
+ OUTPUT_VARIABLE LLVM_LIBRARY
+ OUTPUT_STRIP_TRAILING_WHITESPACE)
+ string(REPLACE " " ";" LLVM_LIBRARY "${LLVM_LIBRARY}")
+ endif()
+endif()
+
+
+# handle the QUIETLY and REQUIRED arguments and set SDL2_FOUND to TRUE if
+# all listed variables are TRUE
+INCLUDE(FindPackageHandleStandardArgs)
+FIND_PACKAGE_HANDLE_STANDARD_ARGS(LLVM DEFAULT_MSG
+ LLVM_LIBRARY)
+
+MARK_AS_ADVANCED(
+ LLVM_LIBRARY
+)
+
diff --git a/build_files/cmake/Modules/FindLZO.cmake b/build_files/cmake/Modules/FindLZO.cmake
new file mode 100644
index 00000000000..a21aa0a03bb
--- /dev/null
+++ b/build_files/cmake/Modules/FindLZO.cmake
@@ -0,0 +1,68 @@
+# - Find LZO library
+# Find the native LZO includes and library
+# This module defines
+# LZO_INCLUDE_DIRS, where to find lzo1x.h, Set when
+# LZO_INCLUDE_DIR is found.
+# LZO_LIBRARIES, libraries to link against to use LZO.
+# LZO_ROOT_DIR, The base directory to search for LZO.
+# This can also be an environment variable.
+# LZO_FOUND, If false, do not try to use LZO.
+#
+# also defined, but not for general use are
+# LZO_LIBRARY, where to find the LZO library.
+
+#=============================================================================
+# Copyright 2015 Blender Foundation.
+#
+# Distributed under the OSI-approved BSD License (the "License");
+# see accompanying file Copyright.txt for details.
+#
+# This software is distributed WITHOUT ANY WARRANTY; without even the
+# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# See the License for more information.
+#=============================================================================
+
+# If LZO_ROOT_DIR was defined in the environment, use it.
+IF(NOT LZO_ROOT_DIR AND NOT $ENV{LZO_ROOT_DIR} STREQUAL "")
+ SET(LZO_ROOT_DIR $ENV{LZO_ROOT_DIR})
+ENDIF()
+
+SET(_lzo_SEARCH_DIRS
+ ${LZO_ROOT_DIR}
+ /usr/local
+ /sw # Fink
+ /opt/local # DarwinPorts
+ /opt/csw # Blastwave
+)
+
+FIND_PATH(LZO_INCLUDE_DIR lzo/lzo1x.h
+ HINTS
+ ${_lzo_SEARCH_DIRS}
+ PATH_SUFFIXES
+ include
+)
+
+FIND_LIBRARY(LZO_LIBRARY
+ NAMES
+ lzo2
+ HINTS
+ ${_lzo_SEARCH_DIRS}
+ PATH_SUFFIXES
+ lib64 lib
+ )
+
+# handle the QUIETLY and REQUIRED arguments and set LZO_FOUND to TRUE if
+# all listed variables are TRUE
+INCLUDE(FindPackageHandleStandardArgs)
+FIND_PACKAGE_HANDLE_STANDARD_ARGS(LZO DEFAULT_MSG
+ LZO_LIBRARY LZO_INCLUDE_DIR)
+
+IF(LZO_FOUND)
+ SET(LZO_LIBRARIES ${LZO_LIBRARY})
+ SET(LZO_INCLUDE_DIRS ${LZO_INCLUDE_DIR})
+ENDIF(LZO_FOUND)
+
+MARK_AS_ADVANCED(
+ LZO_INCLUDE_DIR
+ LZO_LIBRARY
+)
diff --git a/build_files/cmake/Modules/FindOpenCOLLADA.cmake b/build_files/cmake/Modules/FindOpenCOLLADA.cmake
index 84aead58b60..1c10d5a71de 100644
--- a/build_files/cmake/Modules/FindOpenCOLLADA.cmake
+++ b/build_files/cmake/Modules/FindOpenCOLLADA.cmake
@@ -140,3 +140,8 @@ IF(OPENCOLLADA_FOUND)
SET(OPENCOLLADA_LIBRARIES ${_opencollada_LIBRARIES})
SET(OPENCOLLADA_INCLUDE_DIRS ${_opencollada_INCLUDES})
ENDIF(OPENCOLLADA_FOUND)
+
+UNSET(COMPONENT)
+UNSET(UPPERCOMPONENT)
+UNSET(_opencollada_LIBRARIES)
+UNSET(_opencollada_INCLUDES)
diff --git a/build_files/cmake/Modules/FindOpenColorIO.cmake b/build_files/cmake/Modules/FindOpenColorIO.cmake
index e152f0f81d9..bd1ecac0a39 100644
--- a/build_files/cmake/Modules/FindOpenColorIO.cmake
+++ b/build_files/cmake/Modules/FindOpenColorIO.cmake
@@ -63,11 +63,12 @@ FOREACH(COMPONENT ${_opencolorio_FIND_COMPONENTS})
PATH_SUFFIXES
lib64 lib
)
- if(OPENCOLORIO_${UPPERCOMPONENT}_LIBRARY)
+ IF(OPENCOLORIO_${UPPERCOMPONENT}_LIBRARY)
LIST(APPEND _opencolorio_LIBRARIES "${OPENCOLORIO_${UPPERCOMPONENT}_LIBRARY}")
- endif()
+ ENDIF()
ENDFOREACH()
+
# handle the QUIETLY and REQUIRED arguments and set OPENCOLORIO_FOUND to TRUE if
# all listed variables are TRUE
INCLUDE(FindPackageHandleStandardArgs)
@@ -82,5 +83,13 @@ ENDIF(OPENCOLORIO_FOUND)
MARK_AS_ADVANCED(
OPENCOLORIO_INCLUDE_DIR
OPENCOLORIO_LIBRARY
+ OPENCOLORIO_OPENCOLORIO_LIBRARY
+ OPENCOLORIO_TINYXML_LIBRARY
+ OPENCOLORIO_YAML-CPP_LIBRARY
)
+UNSET(COMPONENT)
+UNSET(UPPERCOMPONENT)
+UNSET(_opencolorio_FIND_COMPONENTS)
+UNSET(_opencolorio_LIBRARIES)
+UNSET(_opencolorio_SEARCH_DIRS)
diff --git a/build_files/cmake/Modules/FindOpenEXR.cmake b/build_files/cmake/Modules/FindOpenEXR.cmake
index 1c59ef49e59..41e60a75294 100644
--- a/build_files/cmake/Modules/FindOpenEXR.cmake
+++ b/build_files/cmake/Modules/FindOpenEXR.cmake
@@ -51,6 +51,7 @@ SET(_openexr_SEARCH_DIRS
/sw # Fink
/opt/local # DarwinPorts
/opt/csw # Blastwave
+ /opt/lib/openexr
)
FIND_PATH(OPENEXR_INCLUDE_DIR
@@ -137,3 +138,9 @@ FOREACH(COMPONENT ${_openexr_FIND_COMPONENTS})
STRING(TOUPPER ${COMPONENT} UPPERCOMPONENT)
MARK_AS_ADVANCED(OPENEXR_${UPPERCOMPONENT}_LIBRARY)
ENDFOREACH()
+
+UNSET(COMPONENT)
+UNSET(UPPERCOMPONENT)
+UNSET(_openexr_FIND_COMPONENTS)
+UNSET(_openexr_LIBRARIES)
+UNSET(_openexr_SEARCH_DIRS)
diff --git a/build_files/cmake/Modules/FindOpenGLES.cmake b/build_files/cmake/Modules/FindOpenGLES.cmake
new file mode 100644
index 00000000000..e3484d26ecd
--- /dev/null
+++ b/build_files/cmake/Modules/FindOpenGLES.cmake
@@ -0,0 +1,78 @@
+# - Try to find OpenGLES
+# Once done this will define
+#
+# OPENGLES_FOUND - system has OpenGLES and EGL
+# OPENGL_EGL_FOUND - system has EGL
+# OPENGLES_INCLUDE_DIR - the GLES include directory
+# OPENGLES_LIBRARY - the GLES library
+# OPENGLES_EGL_INCLUDE_DIR - the EGL include directory
+# OPENGLES_EGL_LIBRARY - the EGL library
+# OPENGLES_LIBRARIES - all libraries needed for OpenGLES
+# OPENGLES_INCLUDES - all includes needed for OpenGLES
+
+# If OPENGLES_ROOT_DIR was defined in the environment, use it.
+IF(NOT OPENGLES_ROOT_DIR AND NOT $ENV{OPENGLES_ROOT_DIR} STREQUAL "")
+ SET(OPENGLES_ROOT_DIR $ENV{OPENGLES_ROOT_DIR})
+ENDIF()
+
+SET(_opengles_SEARCH_DIRS
+ ${OPENGLES_ROOT_DIR}
+ /usr/local
+)
+
+FIND_PATH(OPENGLES_INCLUDE_DIR
+ NAMES
+ GLES2/gl2.h
+ HINTS
+ ${_opengles_SEARCH_DIRS}
+)
+
+FIND_LIBRARY(OPENGLES_LIBRARY
+ NAMES
+ GLESv2
+ PATHS
+ ${_opengles_SEARCH_DIRS}
+ PATH_SUFFIXES
+ lib64 lib
+)
+
+FIND_PATH(OPENGLES_EGL_INCLUDE_DIR
+ NAMES
+ EGL/egl.h
+ HINTS
+ ${_opengles_SEARCH_DIRS}
+)
+
+FIND_LIBRARY(OPENGLES_EGL_LIBRARY
+ NAMES
+ EGL
+ HINTS
+ ${_opengles_SEARCH_DIRS}
+ PATH_SUFFIXES
+ lib64 lib
+)
+
+IF(OPENGLES_EGL_LIBRARY AND OPENGLES_EGL_INCLUDE_DIR)
+ SET(OPENGL_EGL_FOUND "YES")
+ELSE()
+ SET(OPENGL_EGL_FOUND "NO")
+ENDIF()
+
+IF(OPENGLES_LIBRARY AND OPENGLES_INCLUDE_DIR AND
+ OPENGLES_EGL_LIBRARY AND OPENGLES_EGL_INCLUDE_DIR)
+ SET(OPENGLES_LIBRARIES ${OPENGLES_LIBRARY} ${OPENGLES_LIBRARIES}
+ ${OPENGLES_EGL_LIBRARY})
+ SET(OPENGLES_INCLUDES ${OPENGLES_INCLUDE_DIR} ${OPENGLES_EGL_INCLUDE_DIR})
+ SET(OPENGLES_FOUND "YES")
+ELSE()
+ SET(OPENGLES_FOUND "NO")
+ENDIF()
+
+MARK_AS_ADVANCED(
+ OPENGLES_EGL_INCLUDE_DIR
+ OPENGLES_EGL_LIBRARY
+ OPENGLES_LIBRARY
+ OPENGLES_INCLUDE_DIR
+)
+
+UNSET(_opengles_SEARCH_DIRS)
diff --git a/build_files/cmake/Modules/FindOpenImageIO.cmake b/build_files/cmake/Modules/FindOpenImageIO.cmake
index 9b8c8b075b1..789097dfd51 100644
--- a/build_files/cmake/Modules/FindOpenImageIO.cmake
+++ b/build_files/cmake/Modules/FindOpenImageIO.cmake
@@ -7,6 +7,8 @@
# OPENIMAGEIO_ROOT_DIR, The base directory to search for OpenImageIO.
# This can also be an environment variable.
# OPENIMAGEIO_FOUND, If false, do not try to use OpenImageIO.
+# OPENIMAGEIO_PUGIXML_FOUND, Indicates whether OIIO has biltin PuguXML parser.
+# OPENIMAGEIO_IDIFF, full path to idiff application if found.
#
# also defined, but not for general use are
# OPENIMAGEIO_LIBRARY, where to find the OpenImageIO library.
@@ -54,6 +56,15 @@ FIND_LIBRARY(OPENIMAGEIO_LIBRARY
lib64 lib
)
+FIND_FILE(OPENIMAGEIO_IDIFF
+ NAMES
+ idiff
+ HINTS
+ ${OPENIMAGEIO_ROOT_DIR}
+ PATH_SUFFIXES
+ bin
+)
+
# handle the QUIETLY and REQUIRED arguments and set OPENIMAGEIO_FOUND to TRUE if
# all listed variables are TRUE
INCLUDE(FindPackageHandleStandardArgs)
@@ -63,9 +74,17 @@ FIND_PACKAGE_HANDLE_STANDARD_ARGS(OpenImageIO DEFAULT_MSG
IF(OPENIMAGEIO_FOUND)
SET(OPENIMAGEIO_LIBRARIES ${OPENIMAGEIO_LIBRARY})
SET(OPENIMAGEIO_INCLUDE_DIRS ${OPENIMAGEIO_INCLUDE_DIR})
-ENDIF(OPENIMAGEIO_FOUND)
+ IF(EXISTS ${OPENIMAGEIO_INCLUDE_DIR}/OpenImageIO/pugixml.hpp)
+ SET(OPENIMAGEIO_PUGIXML_FOUND TRUE)
+ ENDIF()
+ELSE()
+ SET(OPENIMAGEIO_PUGIXML_FOUND FALSE)
+ENDIF()
MARK_AS_ADVANCED(
OPENIMAGEIO_INCLUDE_DIR
OPENIMAGEIO_LIBRARY
+ OPENIMAGEIO_IDIFF
)
+
+UNSET(_openimageio_SEARCH_DIRS)
diff --git a/build_files/cmake/Modules/FindOpenJPEG.cmake b/build_files/cmake/Modules/FindOpenJPEG.cmake
index 8bd1a584ac7..d765103638b 100644
--- a/build_files/cmake/Modules/FindOpenJPEG.cmake
+++ b/build_files/cmake/Modules/FindOpenJPEG.cmake
@@ -69,3 +69,5 @@ MARK_AS_ADVANCED(
OPENJPEG_INCLUDE_DIR
OPENJPEG_LIBRARY
)
+
+UNSET(_openjpeg_SEARCH_DIRS)
diff --git a/build_files/cmake/Modules/FindOpenShadingLanguage.cmake b/build_files/cmake/Modules/FindOpenShadingLanguage.cmake
new file mode 100644
index 00000000000..824d0f90597
--- /dev/null
+++ b/build_files/cmake/Modules/FindOpenShadingLanguage.cmake
@@ -0,0 +1,98 @@
+# - Find OpenShadingLanguage library
+# Find the native OpenShadingLanguage includes and library
+# This module defines
+# OSL_INCLUDE_DIRS, where to find OSL headers, Set when
+# OSL_INCLUDE_DIR is found.
+# OSL_LIBRARIES, libraries to link against to use OSL.
+# OSL_ROOT_DIR, the base directory to search for OSL.
+# This can also be an environment variable.
+# OSL_COMPILER, full path to OSL script compiler.
+# OSL_FOUND, if false, do not try to use OSL.
+# OSL_LIBRARY_VERSION_MAJOR, OSL_LIBRARY_VERSION_MINOR, the major
+# and minor versions of OSL library if found.
+#
+#=============================================================================
+# Copyright 2014 Blender Foundation.
+#
+# Distributed under the OSI-approved BSD License (the "License");
+# see accompanying file Copyright.txt for details.
+#
+# This software is distributed WITHOUT ANY WARRANTY; without even the
+# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# See the License for more information.
+#=============================================================================
+
+# If OSL_ROOT_DIR was defined in the environment, use it.
+IF(NOT OSL_ROOT_DIR AND NOT $ENV{OSL_ROOT_DIR} STREQUAL "")
+ SET(OSL_ROOT_DIR $ENV{OSL_ROOT_DIR})
+ENDIF()
+
+SET(_osl_FIND_COMPONENTS
+ oslcomp
+ oslexec
+ oslquery
+)
+
+SET(_osl_SEARCH_DIRS
+ ${OSL_ROOT_DIR}
+ /usr/local
+ /sw # Fink
+ /opt/local # DarwinPorts
+ /opt/csw # Blastwave
+ /opt/lib/osl
+)
+
+FIND_PATH(OSL_INCLUDE_DIR
+ NAMES
+ OSL/oslversion.h
+ HINTS
+ ${_osl_SEARCH_DIRS}
+ PATH_SUFFIXES
+ include
+)
+
+SET(_osl_LIBRARIES)
+FOREACH(COMPONENT ${_osl_FIND_COMPONENTS})
+ STRING(TOUPPER ${COMPONENT} UPPERCOMPONENT)
+
+ FIND_LIBRARY(OSL_${UPPERCOMPONENT}_LIBRARY
+ NAMES
+ ${COMPONENT}
+ HINTS
+ ${_osl_SEARCH_DIRS}
+ PATH_SUFFIXES
+ lib64 lib
+ )
+ LIST(APPEND _osl_LIBRARIES "${OSL_${UPPERCOMPONENT}_LIBRARY}")
+ENDFOREACH()
+
+FIND_PROGRAM(OSL_COMPILER oslc
+ HINTS ${_osl_SEARCH_DIRS}
+ PATH_SUFFIXES bin)
+
+# handle the QUIETLY and REQUIRED arguments and set OSL_FOUND to TRUE if
+# all listed variables are TRUE
+INCLUDE(FindPackageHandleStandardArgs)
+FIND_PACKAGE_HANDLE_STANDARD_ARGS(OSL DEFAULT_MSG _osl_LIBRARIES OSL_INCLUDE_DIR OSL_COMPILER)
+
+IF(OSL_FOUND)
+ SET(OSL_LIBRARIES ${_osl_LIBRARIES})
+ SET(OSL_INCLUDE_DIRS ${OSL_INCLUDE_DIR})
+
+ FILE(STRINGS "${OSL_INCLUDE_DIR}/OSL/oslversion.h" OSL_LIBRARY_VERSION_MAJOR
+ REGEX "^[ \t]*#define[ \t]+OSL_LIBRARY_VERSION_MAJOR[ \t]+[0-9]+.*$")
+ FILE(STRINGS "${OSL_INCLUDE_DIR}/OSL/oslversion.h" OSL_LIBRARY_VERSION_MINOR
+ REGEX "^[ \t]*#define[ \t]+OSL_LIBRARY_VERSION_MINOR[ \t]+[0-9]+.*$")
+ STRING(REGEX REPLACE ".*#define[ \t]+OSL_LIBRARY_VERSION_MAJOR[ \t]+([.0-9]+).*"
+ "\\1" OSL_LIBRARY_VERSION_MAJOR ${OSL_LIBRARY_VERSION_MAJOR})
+ STRING(REGEX REPLACE ".*#define[ \t]+OSL_LIBRARY_VERSION_MINOR[ \t]+([.0-9]+).*"
+ "\\1" OSL_LIBRARY_VERSION_MINOR ${OSL_LIBRARY_VERSION_MINOR})
+ENDIF(OSL_FOUND)
+
+MARK_AS_ADVANCED(
+ OSL_INCLUDE_DIR
+)
+FOREACH(COMPONENT ${_osl_FIND_COMPONENTS})
+ STRING(TOUPPER ${COMPONENT} UPPERCOMPONENT)
+ MARK_AS_ADVANCED(OSL_${UPPERCOMPONENT}_LIBRARY)
+ENDFOREACH()
diff --git a/build_files/cmake/Modules/FindOpenSubdiv.cmake b/build_files/cmake/Modules/FindOpenSubdiv.cmake
new file mode 100644
index 00000000000..efbe8a967e1
--- /dev/null
+++ b/build_files/cmake/Modules/FindOpenSubdiv.cmake
@@ -0,0 +1,111 @@
+# - Find OpenSubdiv library
+# Find the native OpenSubdiv includes and library
+# This module defines
+# OPENSUBDIV_INCLUDE_DIRS, where to find OpenSubdiv headers, Set when
+# OPENSUBDIV_INCLUDE_DIR is found.
+# OPENSUBDIV_LIBRARIES, libraries to link against to use OpenSubdiv.
+# OPENSUBDIV_ROOT_DIR, the base directory to search for OpenSubdiv.
+# This can also be an environment variable.
+# OPENSUBDIV_FOUND, if false, do not try to use OpenSubdiv.
+#
+# also defined, but not for general use are
+# OPENSUBDIV_LIBRARY, where to find the OpenSubdiv library.
+
+#=============================================================================
+# Copyright 2013 Blender Foundation.
+#
+# Distributed under the OSI-approved BSD License (the "License");
+# see accompanying file Copyright.txt for details.
+#
+# This software is distributed WITHOUT ANY WARRANTY; without even the
+# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# See the License for more information.
+#=============================================================================
+
+# If OPENSUBDIV_ROOT_DIR was defined in the environment, use it.
+IF(NOT OPENSUBDIV_ROOT_DIR AND NOT $ENV{OPENSUBDIV_ROOT_DIR} STREQUAL "")
+ SET(OPENSUBDIV_ROOT_DIR $ENV{OPENSUBDIV_ROOT_DIR})
+ENDIF()
+
+SET(_opensubdiv_FIND_COMPONENTS
+ osdGPU
+ osdCPU
+)
+
+SET(_opensubdiv_SEARCH_DIRS
+ ${OPENSUBDIV_ROOT_DIR}
+ /usr/local
+ /sw # Fink
+ /opt/local # DarwinPorts
+ /opt/csw # Blastwave
+ /opt/lib/opensubdiv
+)
+
+FIND_PATH(OPENSUBDIV_INCLUDE_DIR
+ NAMES
+ opensubdiv/osd/mesh.h
+ HINTS
+ ${_opensubdiv_SEARCH_DIRS}
+ PATH_SUFFIXES
+ include
+)
+
+SET(_opensubdiv_LIBRARIES)
+FOREACH(COMPONENT ${_opensubdiv_FIND_COMPONENTS})
+ STRING(TOUPPER ${COMPONENT} UPPERCOMPONENT)
+
+ FIND_LIBRARY(OPENSUBDIV_${UPPERCOMPONENT}_LIBRARY
+ NAMES
+ ${COMPONENT}
+ HINTS
+ ${_opensubdiv_SEARCH_DIRS}
+ PATH_SUFFIXES
+ lib64 lib
+ )
+ LIST(APPEND _opensubdiv_LIBRARIES "${OPENSUBDIV_${UPPERCOMPONENT}_LIBRARY}")
+ENDFOREACH()
+
+MACRO(OPENSUBDIV_CHECK_CONTROLLER
+ controller_include_file
+ variable_name)
+ IF(EXISTS "${OPENSUBDIV_INCLUDE_DIR}/opensubdiv/osd/${controller_include_file}")
+ SET(${variable_name} TRUE)
+ ELSE()
+ SET(${variable_name} FALSE)
+ ENDIF()
+ENDMACRO()
+
+
+# handle the QUIETLY and REQUIRED arguments and set OPENSUBDIV_FOUND to TRUE if
+# all listed variables are TRUE
+INCLUDE(FindPackageHandleStandardArgs)
+FIND_PACKAGE_HANDLE_STANDARD_ARGS(OpenSubdiv DEFAULT_MSG
+ _opensubdiv_LIBRARIES OPENSUBDIV_INCLUDE_DIR)
+
+IF(OPENSUBDIV_FOUND)
+ SET(OPENSUBDIV_LIBRARIES ${_opensubdiv_LIBRARIES})
+ SET(OPENSUBDIV_INCLUDE_DIRS ${OPENSUBDIV_INCLUDE_DIR})
+
+ # Find available compute controllers.
+
+ FIND_PACKAGE(OpenMP)
+ IF(OPENMP_FOUND)
+ SET(OPENSUBDIV_HAS_OPENMP TRUE)
+ ELSE()
+ SET(OPENSUBDIV_HAS_OPENMP FALSE)
+ ENDIF()
+
+ OPENSUBDIV_CHECK_CONTROLLER("tbbEvaluator.h" OPENSUBDIV_HAS_TBB)
+ OPENSUBDIV_CHECK_CONTROLLER("clEvaluator.h" OPENSUBDIV_HAS_OPENCL)
+ OPENSUBDIV_CHECK_CONTROLLER("cudaEvaluator.h" OPENSUBDIV_HAS_CUDA)
+ OPENSUBDIV_CHECK_CONTROLLER("glXFBEvaluator.h" OPENSUBDIV_HAS_GLSL_TRANSFORM_FEEDBACK)
+ OPENSUBDIV_CHECK_CONTROLLER("glComputeEvaluator.h" OPENSUBDIV_HAS_GLSL_COMPUTE)
+ENDIF(OPENSUBDIV_FOUND)
+
+MARK_AS_ADVANCED(
+ OPENSUBDIV_INCLUDE_DIR
+)
+FOREACH(COMPONENT ${_opensubdiv_FIND_COMPONENTS})
+ STRING(TOUPPER ${COMPONENT} UPPERCOMPONENT)
+ MARK_AS_ADVANCED(OPENSUBDIV_${UPPERCOMPONENT}_LIBRARY)
+ENDFOREACH()
diff --git a/build_files/cmake/Modules/FindPCRE.cmake b/build_files/cmake/Modules/FindPCRE.cmake
index 9d73e9200d9..ff4b7261555 100644
--- a/build_files/cmake/Modules/FindPCRE.cmake
+++ b/build_files/cmake/Modules/FindPCRE.cmake
@@ -40,7 +40,6 @@ FIND_PATH(PCRE_INCLUDE_DIR pcre.h
${_pcre_SEARCH_DIRS}
PATH_SUFFIXES
include
- include
)
FIND_LIBRARY(PCRE_LIBRARY
diff --git a/build_files/cmake/Modules/FindPugiXML.cmake b/build_files/cmake/Modules/FindPugiXML.cmake
new file mode 100644
index 00000000000..f7104c16921
--- /dev/null
+++ b/build_files/cmake/Modules/FindPugiXML.cmake
@@ -0,0 +1,73 @@
+# - Find PugiXML library
+# Find the native PugiXML includes and library
+# This module defines
+# PUGIXML_INCLUDE_DIRS, where to find pugixml.hpp, Set when
+# PugiXML is found.
+# PUGIXML_LIBRARIES, libraries to link against to use PugiiXML.
+# PUGIXML_ROOT_DIR, The base directory to search for PugiXML.
+# This can also be an environment variable.
+# PUGIXML_FOUND, If false, do not try to use PugiXML.
+#
+# also defined, but not for general use are
+# PUGIXML_LIBRARY, where to find the PugiXML library.
+
+#=============================================================================
+# Copyright 2014 Blender Foundation.
+#
+# Distributed under the OSI-approved BSD License (the "License");
+# see accompanying file Copyright.txt for details.
+#
+# This software is distributed WITHOUT ANY WARRANTY; without even the
+# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# See the License for more information.
+#=============================================================================
+
+# If PUGIXML_ROOT_DIR was defined in the environment, use it.
+IF(NOT PUGIXML_ROOT_DIR AND NOT $ENV{PUGIXML_ROOT_DIR} STREQUAL "")
+ SET(PUGIXML_ROOT_DIR $ENV{PUGIXML_ROOT_DIR})
+ENDIF()
+
+SET(_pugixml_SEARCH_DIRS
+ ${PUGIXML_ROOT_DIR}
+ /usr/local
+ /sw # Fink
+ /opt/local # DarwinPorts
+ /opt/csw # Blastwave
+ /opt/lib/oiio
+)
+
+FIND_PATH(PUGIXML_INCLUDE_DIR
+ NAMES
+ pugixml.hpp
+ HINTS
+ ${_pugixml_SEARCH_DIRS}
+ PATH_SUFFIXES
+ include
+)
+
+FIND_LIBRARY(PUGIXML_LIBRARY
+ NAMES
+ pugixml
+ HINTS
+ ${_pugixml_SEARCH_DIRS}
+ PATH_SUFFIXES
+ lib64 lib
+ )
+
+# handle the QUIETLY and REQUIRED arguments and set PUGIXML_FOUND to TRUE if
+# all listed variables are TRUE
+INCLUDE(FindPackageHandleStandardArgs)
+FIND_PACKAGE_HANDLE_STANDARD_ARGS(PUGIXML DEFAULT_MSG
+ PUGIXML_LIBRARY PUGIXML_INCLUDE_DIR)
+
+IF(PUGIXML_FOUND)
+ SET(PUGIXML_LIBRARIES ${PUGIXML_LIBRARY})
+ SET(PUGIXML_INCLUDE_DIRS ${PUGIXML_INCLUDE_DIR})
+ELSE()
+ SET(PUGIXML_PUGIXML_FOUND FALSE)
+ENDIF()
+
+MARK_AS_ADVANCED(
+ PUGIXML_INCLUDE_DIR
+ PUGIXML_LIBRARY
+)
diff --git a/build_files/cmake/Modules/FindPythonLibsUnix.cmake b/build_files/cmake/Modules/FindPythonLibsUnix.cmake
index 1fb27e7898c..e4236fb4c24 100644
--- a/build_files/cmake/Modules/FindPythonLibsUnix.cmake
+++ b/build_files/cmake/Modules/FindPythonLibsUnix.cmake
@@ -14,6 +14,7 @@
# PYTHON_INCLUDE_CONFIG_DIRS
# PYTHON_LIBRARIES
# PYTHON_LIBPATH, Used for installation
+# PYTHON_SITE_PACKAGES, Used for installation (as a Python module)
# PYTHON_LINKFLAGS
# PYTHON_ROOT_DIR, The base directory to search for Python.
# This can also be an environment variable.
@@ -65,6 +66,14 @@ IF(DEFINED PYTHON_LIBPATH)
SET(_IS_LIB_PATH_DEF ON)
ENDIF()
+STRING(REPLACE "." "" _PYTHON_VERSION_NO_DOTS ${PYTHON_VERSION})
+
+SET(_python_SEARCH_DIRS
+ ${PYTHON_ROOT_DIR}
+ "$ENV{HOME}/py${_PYTHON_VERSION_NO_DOTS}"
+ "/opt/py${_PYTHON_VERSION_NO_DOTS}"
+ "/opt/lib/python-${PYTHON_VERSION}"
+)
# only search for the dirs if we havn't already
IF((NOT _IS_INC_DEF) OR (NOT _IS_INC_CONF_DEF) OR (NOT _IS_LIB_DEF) OR (NOT _IS_LIB_PATH_DEF))
@@ -74,14 +83,7 @@ IF((NOT _IS_INC_DEF) OR (NOT _IS_INC_CONF_DEF) OR (NOT _IS_LIB_DEF) OR (NOT _IS_
"dm;dmu;du;d" # debug
)
- STRING(REPLACE "." "" _PYTHON_VERSION_NO_DOTS ${PYTHON_VERSION})
- SET(_python_SEARCH_DIRS
- ${PYTHON_ROOT_DIR}
- "$ENV{HOME}/py${_PYTHON_VERSION_NO_DOTS}"
- "/opt/py${_PYTHON_VERSION_NO_DOTS}"
- "/opt/lib/python-${PYTHON_VERSION}"
- )
FOREACH(_CURRENT_ABI_FLAGS ${_python_ABI_FLAGS})
#IF(CMAKE_BUILD_TYPE STREQUAL Debug)
@@ -146,6 +148,7 @@ IF((NOT _IS_INC_DEF) OR (NOT _IS_INC_CONF_DEF) OR (NOT _IS_LIB_DEF) OR (NOT _IS_
ENDIF()
IF(PYTHON_LIBRARY AND PYTHON_LIBPATH AND PYTHON_INCLUDE_DIR AND PYTHON_INCLUDE_CONFIG_DIR)
+ SET(_PYTHON_ABI_FLAGS "${_CURRENT_ABI_FLAGS}")
break()
ELSE()
# ensure we dont find values from 2 different ABI versions
@@ -168,7 +171,6 @@ IF((NOT _IS_INC_DEF) OR (NOT _IS_INC_CONF_DEF) OR (NOT _IS_LIB_DEF) OR (NOT _IS_
UNSET(_CURRENT_PATH)
UNSET(_python_ABI_FLAGS)
- UNSET(_python_SEARCH_DIRS)
ENDIF()
UNSET(_IS_INC_DEF)
@@ -187,17 +189,41 @@ IF(PYTHONLIBSUNIX_FOUND)
SET(PYTHON_INCLUDE_DIRS ${PYTHON_INCLUDE_DIR} ${PYTHON_INCLUDE_CONFIG_DIR})
SET(PYTHON_LIBRARIES ${PYTHON_LIBRARY})
+ FIND_FILE(PYTHON_SITE_PACKAGES
+ NAMES
+ # debian specific
+ dist-packages
+ site-packages
+ HINTS
+ ${PYTHON_LIBPATH}/python${PYTHON_VERSION}
+ )
+
# we need this for installation
# XXX No more valid with debian-like py3.4 packages...
# GET_FILENAME_COMPONENT(PYTHON_LIBPATH ${PYTHON_LIBRARY} PATH)
- # not used
- # SET(PYTHON_BINARY ${PYTHON_EXECUTABLE} CACHE STRING "")
+ # not required for build, just used when bundling Python.
+ FIND_PROGRAM(
+ PYTHON_EXECUTABLE
+ NAMES
+ "python${PYTHON_VERSION}${_PYTHON_ABI_FLAGS}"
+ "python${PYTHON_VERSION}"
+ "python"
+ HINTS
+ ${_python_SEARCH_DIRS}
+ PATH_SUFFIXES bin
+ )
ENDIF()
+UNSET(_PYTHON_VERSION_NO_DOTS)
+UNSET(_PYTHON_ABI_FLAGS)
+UNSET(_python_SEARCH_DIRS)
+
MARK_AS_ADVANCED(
PYTHON_INCLUDE_DIR
PYTHON_INCLUDE_CONFIG_DIR
PYTHON_LIBRARY
PYTHON_LIBPATH
+ PYTHON_SITE_PACKAGES
+ PYTHON_EXECUTABLE
)
diff --git a/build_files/cmake/Modules/FindSDL2.cmake b/build_files/cmake/Modules/FindSDL2.cmake
new file mode 100644
index 00000000000..2a835cf94fa
--- /dev/null
+++ b/build_files/cmake/Modules/FindSDL2.cmake
@@ -0,0 +1,72 @@
+# - Find SDL library
+# Find the native SDL includes and library
+# This module defines
+# SDL2_INCLUDE_DIRS, where to find SDL.h, Set when SDL2_INCLUDE_DIR is found.
+# SDL2_LIBRARIES, libraries to link against to use SDL.
+# SDL2_ROOT_DIR, The base directory to search for SDL.
+# This can also be an environment variable.
+# SDL2_FOUND, If false, do not try to use SDL.
+#
+# also defined, but not for general use are
+# SDL2_LIBRARY, where to find the SDL library.
+
+#=============================================================================
+# Copyright 2015 Blender Foundation.
+#
+# Distributed under the OSI-approved BSD License (the "License");
+# see accompanying file Copyright.txt for details.
+#
+# This software is distributed WITHOUT ANY WARRANTY; without even the
+# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# See the License for more information.
+#=============================================================================
+
+# If SDL2_ROOT_DIR was defined in the environment, use it.
+IF(NOT SDL2_ROOT_DIR AND NOT $ENV{SDL2_ROOT_DIR} STREQUAL "")
+ SET(SDL2_ROOT_DIR $ENV{SDL2_ROOT_DIR})
+ENDIF()
+
+SET(_sdl2_SEARCH_DIRS
+ ${SDL2_ROOT_DIR}
+ ~/Library/Frameworks
+ /Library/Frameworks
+ /usr/local
+ /usr
+ /sw # Fink
+ /opt/local # DarwinPorts
+ /opt/csw # Blastwave
+)
+
+FIND_PATH(SDL2_INCLUDE_DIR
+ NAMES
+ SDL.h
+ HINTS
+ ${_sdl2_SEARCH_DIRS}
+ PATH_SUFFIXES
+ include/SDL2 include
+)
+
+FIND_LIBRARY(SDL2_LIBRARY
+ NAMES
+ SDL2
+ HINTS
+ ${_sdl2_SEARCH_DIRS}
+ PATH_SUFFIXES
+ lib64 lib
+ )
+
+# handle the QUIETLY and REQUIRED arguments and set SDL2_FOUND to TRUE if
+# all listed variables are TRUE
+INCLUDE(FindPackageHandleStandardArgs)
+FIND_PACKAGE_HANDLE_STANDARD_ARGS(SDL2 DEFAULT_MSG
+ SDL2_LIBRARY SDL2_INCLUDE_DIR)
+
+IF(SDL2_FOUND)
+ SET(SDL2_LIBRARIES ${SDL2_LIBRARY})
+ SET(SDL2_INCLUDE_DIRS ${SDL2_INCLUDE_DIR})
+ENDIF(SDL2_FOUND)
+
+MARK_AS_ADVANCED(
+ SDL2_INCLUDE_DIR
+ SDL2_LIBRARY
+)
diff --git a/build_files/cmake/Modules/GTestTesting.cmake b/build_files/cmake/Modules/GTestTesting.cmake
index fd0379b8f78..b98d15ecd41 100644
--- a/build_files/cmake/Modules/GTestTesting.cmake
+++ b/build_files/cmake/Modules/GTestTesting.cmake
@@ -12,7 +12,7 @@
#
#=============================================================================
-macro(BLENDER_SRC_GTEST NAME SRC EXTRA_LIBS)
+macro(BLENDER_SRC_GTEST_EX NAME SRC EXTRA_LIBS DO_ADD_TEST)
if(WITH_GTESTS)
get_property(_current_include_directories
DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
@@ -32,16 +32,28 @@ macro(BLENDER_SRC_GTEST NAME SRC EXTRA_LIBS)
bf_testing_main
bf_intern_guardedalloc
extern_gtest
+ # needed for glog
+ ${PTHREADS_LIBRARIES}
extern_glog)
set_target_properties(${NAME}_test PROPERTIES
RUNTIME_OUTPUT_DIRECTORY "${TESTS_OUTPUT_DIR}"
RUNTIME_OUTPUT_DIRECTORY_RELEASE "${TESTS_OUTPUT_DIR}"
RUNTIME_OUTPUT_DIRECTORY_DEBUG "${TESTS_OUTPUT_DIR}"
INCLUDE_DIRECTORIES "${TEST_INC}")
- add_test(${NAME}_test ${TESTS_OUTPUT_DIR}/${NAME}_test)
+ if(${DO_ADD_TEST})
+ add_test(${NAME}_test ${TESTS_OUTPUT_DIR}/${NAME}_test)
+ endif()
endif()
endmacro()
+macro(BLENDER_SRC_GTEST NAME SRC EXTRA_LIBS)
+ BLENDER_SRC_GTEST_EX("${NAME}" "${SRC}" "${EXTRA_LIBS}" "TRUE")
+endmacro()
+
macro(BLENDER_TEST NAME EXTRA_LIBS)
- BLENDER_SRC_GTEST("${NAME}" "${NAME}_test.cc" "${EXTRA_LIBS}")
+ BLENDER_SRC_GTEST_EX("${NAME}" "${NAME}_test.cc" "${EXTRA_LIBS}" "TRUE")
+endmacro()
+
+macro(BLENDER_TEST_PERFORMANCE NAME EXTRA_LIBS)
+ BLENDER_SRC_GTEST_EX("${NAME}" "${NAME}_test.cc" "${EXTRA_LIBS}" "FALSE")
endmacro()
diff --git a/build_files/cmake/buildinfo.cmake b/build_files/cmake/buildinfo.cmake
index fecd19c62e2..81b0c1b1e23 100644
--- a/build_files/cmake/buildinfo.cmake
+++ b/build_files/cmake/buildinfo.cmake
@@ -10,7 +10,7 @@ set(MY_WC_COMMIT_TIMESTAMP 0)
# Guess if this is a git working copy and then look up the revision
if(EXISTS ${SOURCE_DIR}/.git)
# The FindGit.cmake module is part of the standard distribution
- include(FindGit)
+ find_package(Git)
if(GIT_FOUND)
message(STATUS "-- Found Git: ${GIT_EXECUTABLE}")
@@ -60,7 +60,8 @@ if(EXISTS ${SOURCE_DIR}/.git)
execute_process(COMMAND git log HEAD..@{u}
WORKING_DIRECTORY ${SOURCE_DIR}
OUTPUT_VARIABLE _git_below_check
- OUTPUT_STRIP_TRAILING_WHITESPACE)
+ OUTPUT_STRIP_TRAILING_WHITESPACE
+ ERROR_QUIET)
if(NOT _git_below_check STREQUAL "")
# If there're commits between HEAD and upstream this means
# that we're reset-ed to older revision. Use it's hash then.
@@ -96,6 +97,10 @@ if(EXISTS ${SOURCE_DIR}/.git)
WORKING_DIRECTORY ${SOURCE_DIR}
OUTPUT_VARIABLE MY_WC_COMMIT_TIMESTAMP
OUTPUT_STRIP_TRAILING_WHITESPACE)
+ # May fail in rare cases
+ if(MY_WC_COMMIT_TIMESTAMP STREQUAL "")
+ set(MY_WC_COMMIT_TIMESTAMP 0)
+ endif()
# Update GIT index before getting dirty files
execute_process(COMMAND git update-index -q --refresh
@@ -146,6 +151,14 @@ file(WRITE buildinfo.h.txt
"#define BUILD_TIME \"${BUILD_TIME}\"\n"
)
+# cleanup
+unset(MY_WC_HASH)
+unset(MY_WC_COMMIT_TIMESTAMP)
+unset(MY_WC_BRANCH)
+unset(BUILD_DATE)
+unset(BUILD_TIME)
+
+
# Copy the file to the final header only if the version changes
# and avoid needless rebuilds
# TODO: verify this comment is true, as BUILD_TIME probably changes
diff --git a/build_files/cmake/cmake_consistency_check.py b/build_files/cmake/cmake_consistency_check.py
index 2e0eeb1e067..d0bbdda1870 100755
--- a/build_files/cmake/cmake_consistency_check.py
+++ b/build_files/cmake/cmake_consistency_check.py
@@ -28,13 +28,17 @@ if not sys.version.startswith("3"):
sys.version.partition(" ")[0])
sys.exit(1)
-from cmake_consistency_check_config import IGNORE, UTF8_CHECK, SOURCE_DIR
+from cmake_consistency_check_config import (
+ IGNORE,
+ UTF8_CHECK,
+ SOURCE_DIR,
+ BUILD_DIR,
+ )
+
import os
from os.path import join, dirname, normpath, splitext
-print("Scanning:", SOURCE_DIR)
-
global_h = set()
global_c = set()
global_refs = {}
@@ -134,6 +138,7 @@ def cmake_get_src(f):
if found:
cmake_base = dirname(f)
+ cmake_base_bin = os.path.join(BUILD_DIR, os.path.relpath(cmake_base, SOURCE_DIR))
while it is not None:
i += 1
@@ -154,6 +159,8 @@ def cmake_get_src(f):
# replace dirs
l = l.replace("${CMAKE_CURRENT_SOURCE_DIR}", cmake_base)
+ l = l.replace("${CMAKE_CURRENT_BINARY_DIR}", cmake_base_bin)
+ l = l.strip('"')
if not l:
pass
@@ -187,21 +194,26 @@ def cmake_get_src(f):
pass
elif new_file.endswith(".osl"): # open shading language
pass
+ elif new_file.endswith(".glsl"):
+ pass
else:
raise Exception("unknown file type - not c or h %s -> %s" % (f, new_file))
elif context_name == "INC":
- if os.path.isdir(new_file):
+ if new_file.startswith(BUILD_DIR):
+ # assume generated path
+ pass
+ elif os.path.isdir(new_file):
new_path_rel = os.path.relpath(new_file, cmake_base)
if new_path_rel != l:
print("overly relative path:\n %s:%d\n %s\n %s" % (f, i, l, new_path_rel))
- ## Save time. just replace the line
+ # # Save time. just replace the line
# replace_line(f, i - 1, new_path_rel)
else:
- raise Exception("non existant include %s:%d -> %s" % (f, i, new_file))
+ raise Exception("non existent include %s:%d -> %s" % (f, i, new_file))
# print(new_file)
@@ -228,10 +240,6 @@ def cmake_get_src(f):
filen.close()
-for cmake in source_list(SOURCE_DIR, is_cmake):
- cmake_get_src(cmake)
-
-
def is_ignore(f):
for ig in IGNORE:
if ig in f:
@@ -239,73 +247,83 @@ def is_ignore(f):
return False
-# First do stupid check, do these files exist?
-print("\nChecking for missing references:")
-is_err = False
-errs = []
-for f in (global_h | global_c):
- if f.endswith("dna.c"):
- continue
-
- if not os.path.exists(f):
- refs = global_refs[f]
- if refs:
- for cf, i in refs:
- errs.append((cf, i))
- else:
- raise Exception("CMake referenecs missing, internal error, aborting!")
- is_err = True
-
-errs.sort()
-errs.reverse()
-for cf, i in errs:
- print("%s:%d" % (cf, i))
- # Write a 'sed' script, useful if we get a lot of these
- # print("sed '%dd' '%s' > '%s.tmp' ; mv '%s.tmp' '%s'" % (i, cf, cf, cf, cf))
-
-
-if is_err:
- raise Exception("CMake referenecs missing files, aborting!")
-del is_err
-del errs
-
-# now check on files not accounted for.
-print("\nC/C++ Files CMake doesnt know about...")
-for cf in sorted(source_list(SOURCE_DIR, is_c)):
- if not is_ignore(cf):
- if cf not in global_c:
- print("missing_c: ", cf)
-
- # check if automake builds a corrasponding .o file.
- '''
- if cf in global_c:
- out1 = os.path.splitext(cf)[0] + ".o"
- out2 = os.path.splitext(cf)[0] + ".Po"
- out2_dir, out2_file = out2 = os.path.split(out2)
- out2 = os.path.join(out2_dir, ".deps", out2_file)
- if not os.path.exists(out1) and not os.path.exists(out2):
- print("bad_c: ", cf)
- '''
-
-print("\nC/C++ Headers CMake doesnt know about...")
-for hf in sorted(source_list(SOURCE_DIR, is_c_header)):
- if not is_ignore(hf):
- if hf not in global_h:
- print("missing_h: ", hf)
-
-if UTF8_CHECK:
- # test encoding
- import traceback
- for files in (global_c, global_h):
- for f in sorted(files):
- if os.path.exists(f):
- # ignore outside of our source tree
- if "extern" not in f:
- i = 1
- try:
- for l in open(f, "r", encoding="utf8"):
- i += 1
- except:
- print("Non utf8: %s:%d" % (f, i))
- if i > 1:
- traceback.print_exc()
+def main():
+
+ print("Scanning:", SOURCE_DIR)
+
+ for cmake in source_list(SOURCE_DIR, is_cmake):
+ cmake_get_src(cmake)
+
+ # First do stupid check, do these files exist?
+ print("\nChecking for missing references:")
+ is_err = False
+ errs = []
+ for f in (global_h | global_c):
+ if f.startswith(BUILD_DIR):
+ continue
+
+ if not os.path.exists(f):
+ refs = global_refs[f]
+ if refs:
+ for cf, i in refs:
+ errs.append((cf, i))
+ else:
+ raise Exception("CMake referenecs missing, internal error, aborting!")
+ is_err = True
+
+ errs.sort()
+ errs.reverse()
+ for cf, i in errs:
+ print("%s:%d" % (cf, i))
+ # Write a 'sed' script, useful if we get a lot of these
+ # print("sed '%dd' '%s' > '%s.tmp' ; mv '%s.tmp' '%s'" % (i, cf, cf, cf, cf))
+
+
+ if is_err:
+ raise Exception("CMake referenecs missing files, aborting!")
+ del is_err
+ del errs
+
+ # now check on files not accounted for.
+ print("\nC/C++ Files CMake doesnt know about...")
+ for cf in sorted(source_list(SOURCE_DIR, is_c)):
+ if not is_ignore(cf):
+ if cf not in global_c:
+ print("missing_c: ", cf)
+
+ # check if automake builds a corrasponding .o file.
+ '''
+ if cf in global_c:
+ out1 = os.path.splitext(cf)[0] + ".o"
+ out2 = os.path.splitext(cf)[0] + ".Po"
+ out2_dir, out2_file = out2 = os.path.split(out2)
+ out2 = os.path.join(out2_dir, ".deps", out2_file)
+ if not os.path.exists(out1) and not os.path.exists(out2):
+ print("bad_c: ", cf)
+ '''
+
+ print("\nC/C++ Headers CMake doesnt know about...")
+ for hf in sorted(source_list(SOURCE_DIR, is_c_header)):
+ if not is_ignore(hf):
+ if hf not in global_h:
+ print("missing_h: ", hf)
+
+ if UTF8_CHECK:
+ # test encoding
+ import traceback
+ for files in (global_c, global_h):
+ for f in sorted(files):
+ if os.path.exists(f):
+ # ignore outside of our source tree
+ if "extern" not in f:
+ i = 1
+ try:
+ for l in open(f, "r", encoding="utf8"):
+ i += 1
+ except UnicodeDecodeError:
+ print("Non utf8: %s:%d" % (f, i))
+ if i > 1:
+ traceback.print_exc()
+
+if __name__ == "__main__":
+ main()
diff --git a/build_files/cmake/cmake_consistency_check_config.py b/build_files/cmake/cmake_consistency_check_config.py
index 729eecce233..1f75b9884bc 100644
--- a/build_files/cmake/cmake_consistency_check_config.py
+++ b/build_files/cmake/cmake_consistency_check_config.py
@@ -74,3 +74,6 @@ IGNORE = (
UTF8_CHECK = True
SOURCE_DIR = os.path.normpath(os.path.abspath(os.path.normpath(os.path.join(os.path.dirname(__file__), "..", ".."))))
+
+# doesn't have to exist, just use as reference
+BUILD_DIR = os.path.normpath(os.path.abspath(os.path.normpath(os.path.join(SOURCE_DIR, "..", "build"))))
diff --git a/build_files/cmake/cmake_netbeans_project.py b/build_files/cmake/cmake_netbeans_project.py
index fc6c64db1cd..d4cce46434d 100755
--- a/build_files/cmake/cmake_netbeans_project.py
+++ b/build_files/cmake/cmake_netbeans_project.py
@@ -29,18 +29,20 @@ Example linux usage
Windows not supported so far
"""
-from project_info import (SIMPLE_PROJECTFILE,
- SOURCE_DIR,
- CMAKE_DIR,
- PROJECT_DIR,
- source_list,
- is_project_file,
- is_c_header,
- # is_py,
- cmake_advanced_info,
- cmake_compiler_defines,
- project_name_get,
- )
+from project_info import (
+ SIMPLE_PROJECTFILE,
+ SOURCE_DIR,
+ CMAKE_DIR,
+ PROJECT_DIR,
+ source_list,
+ is_project_file,
+ is_c_header,
+ # is_py,
+ cmake_advanced_info,
+ cmake_compiler_defines,
+ cmake_cache_var,
+ project_name_get,
+ )
import os
@@ -70,6 +72,10 @@ def create_nb_project_main():
# be tricky, get the project name from git if we can!
PROJECT_NAME = project_name_get()
+
+ make_exe = cmake_cache_var("CMAKE_MAKE_PROGRAM")
+ make_exe_basename = os.path.basename(make_exe)
+
# --------------- NB spesific
defines = [("%s=%s" % cdef) if cdef[1] else cdef[0] for cdef in defines]
defines += [cdef.replace("#define", "").strip() for cdef in cmake_compiler_defines()]
@@ -125,12 +131,14 @@ def create_nb_project_main():
f.write(' </configuration>\n')
f.write('</project>\n')
+ f.close()
+
f = open(join(PROJECT_DIR_NB, "configurations.xml"), 'w')
f.write('<?xml version="1.0" encoding="UTF-8"?>\n')
- f.write('<configurationDescriptor version="94">\n')
+ f.write('<configurationDescriptor version="95">\n')
f.write(' <logicalFolder name="root" displayName="root" projectFiles="true" kind="ROOT">\n')
- f.write(' <df name="0" root="%s">\n' % SOURCE_DIR) # base_root_rel
+ f.write(' <df root="%s" name="0">\n' % SOURCE_DIR) # base_root_rel
# write files!
files_rel_local = [normpath(relpath(join(CMAKE_DIR, path), SOURCE_DIR)) for path in files_rel]
@@ -182,16 +190,27 @@ def create_nb_project_main():
f.write(' <toolsSet>\n')
f.write(' <compilerSet>default</compilerSet>\n')
+ f.write(' <dependencyChecking>false</dependencyChecking>\n')
+ f.write(' <rebuildPropChanged>false</rebuildPropChanged>\n')
f.write(' </toolsSet>\n')
- f.write(' <dependencyChecking>false</dependencyChecking>\n')
- f.write(' <rebuildPropChanged>false</rebuildPropChanged>\n')
+ f.write(' <codeAssistance>\n')
+ f.write(' </codeAssistance>\n')
f.write(' <makefileType>\n')
f.write(' <makeTool>\n')
f.write(' <buildCommandWorkingDir>.</buildCommandWorkingDir>\n')
- f.write(' <buildCommand>${MAKE} -f Makefile</buildCommand>\n')
- f.write(' <cleanCommand>${MAKE} -f Makefile clean</cleanCommand>\n')
+
+ if make_exe_basename == "ninja":
+ build_cmd = "ninja"
+ clean_cmd = "ninja -t clean"
+ else:
+ build_cmd = "${MAKE} -f Makefile"
+ clean_cmd = "${MAKE} -f Makefile clean"
+
+ f.write(' <buildCommand>%s</buildCommand>\n' % build_cmd)
+ f.write(' <cleanCommand>%s</cleanCommand>\n' % clean_cmd)
f.write(' <executablePath>./bin/blender</executablePath>\n')
+ del build_cmd, clean_cmd
def write_toolinfo():
f.write(' <incDir>\n')
@@ -218,10 +237,11 @@ def create_nb_project_main():
f.write(' \n')
for path in files_rel_local:
+ is_c = path.endswith(".c")
f.write(' <item path="%s"\n' % path)
f.write(' ex="false"\n')
- f.write(' tool="1"\n')
- f.write(' flavor2="0">\n')
+ f.write(' tool="%d"\n' % (0 if is_c else 1))
+ f.write(' flavor2="%d">\n' % (3 if is_c else 0))
f.write(' </item>\n')
f.write(' <runprofile version="9">\n')
@@ -243,6 +263,8 @@ def create_nb_project_main():
f.write('</configurationDescriptor>\n')
+ f.close()
+
def main():
create_nb_project_main()
diff --git a/build_files/cmake/cmake_qtcreator_project.py b/build_files/cmake/cmake_qtcreator_project.py
index 346f5ea6a8e..67302c89a68 100755
--- a/build_files/cmake/cmake_qtcreator_project.py
+++ b/build_files/cmake/cmake_qtcreator_project.py
@@ -22,26 +22,27 @@
# <pep8 compliant>
-"""
+r"""
+Example Linux usage:
+ python ~/blender-git/blender/build_files/cmake/cmake_qtcreator_project.py ~/blender-git/cmake
+
Example Win32 usage:
c:\Python32\python.exe c:\blender_dev\blender\build_files\cmake\cmake_qtcreator_project.py c:\blender_dev\cmake_build
-
-example linux usage
- python .~/blender-git/blender/build_files/cmake/cmake_qtcreator_project.py ~/blender-git/cmake
"""
-from project_info import (SIMPLE_PROJECTFILE,
- SOURCE_DIR,
- # CMAKE_DIR,
- PROJECT_DIR,
- source_list,
- is_project_file,
- is_c_header,
- is_py,
- cmake_advanced_info,
- cmake_compiler_defines,
- project_name_get,
- )
+from project_info import (
+ SIMPLE_PROJECTFILE,
+ SOURCE_DIR,
+ # CMAKE_DIR,
+ PROJECT_DIR,
+ source_list,
+ is_project_file,
+ is_c_header,
+ is_py,
+ cmake_advanced_info,
+ cmake_compiler_defines,
+ project_name_get,
+ )
import os
import sys
@@ -63,21 +64,22 @@ def create_qtc_project_main():
if SIMPLE_PROJECTFILE:
# --- qtcreator specific, simple format
PROJECT_NAME = "Blender"
- f = open(os.path.join(PROJECT_DIR, "%s.files" % PROJECT_NAME), 'w')
- f.write("\n".join(files_rel))
+ FILE_NAME = PROJECT_NAME.lower()
+ with open(os.path.join(PROJECT_DIR, "%s.files" % FILE_NAME), 'w') as f:
+ f.write("\n".join(files_rel))
- f = open(os.path.join(PROJECT_DIR, "%s.includes" % PROJECT_NAME), 'w')
- f.write("\n".join(sorted(list(set(os.path.dirname(f)
- for f in files_rel if is_c_header(f))))))
+ with open(os.path.join(PROJECT_DIR, "%s.includes" % FILE_NAME), 'w') as f:
+ f.write("\n".join(sorted(list(set(os.path.dirname(f)
+ for f in files_rel if is_c_header(f))))))
- qtc_prj = os.path.join(PROJECT_DIR, "%s.creator" % PROJECT_NAME)
- f = open(qtc_prj, 'w')
- f.write("[General]\n")
+ qtc_prj = os.path.join(PROJECT_DIR, "%s.creator" % FILE_NAME)
+ with open(qtc_prj, 'w') as f:
+ f.write("[General]\n")
- qtc_cfg = os.path.join(PROJECT_DIR, "%s.config" % PROJECT_NAME)
+ qtc_cfg = os.path.join(PROJECT_DIR, "%s.config" % FILE_NAME)
if not os.path.exists(qtc_cfg):
- f = open(qtc_cfg, 'w')
- f.write("// ADD PREDEFINED MACROS HERE!\n")
+ with open(qtc_cfg, 'w') as f:
+ f.write("// ADD PREDEFINED MACROS HERE!\n")
else:
includes, defines = cmake_advanced_info()
@@ -96,29 +98,30 @@ def create_qtc_project_main():
PROJECT_NAME = project_name_get()
FILE_NAME = PROJECT_NAME.lower()
- f = open(os.path.join(PROJECT_DIR, "%s.files" % FILE_NAME), 'w')
- f.write("\n".join(files_rel))
+ with open(os.path.join(PROJECT_DIR, "%s.files" % FILE_NAME), 'w') as f:
+ f.write("\n".join(files_rel))
- f = open(os.path.join(PROJECT_DIR, "%s.includes" % FILE_NAME), 'w', encoding='utf-8')
- f.write("\n".join(sorted(includes)))
+ with open(os.path.join(PROJECT_DIR, "%s.includes" % FILE_NAME), 'w', encoding='utf-8') as f:
+ f.write("\n".join(sorted(includes)))
qtc_prj = os.path.join(PROJECT_DIR, "%s.creator" % FILE_NAME)
- f = open(qtc_prj, 'w')
- f.write("[General]\n")
+ with open(qtc_prj, 'w') as f:
+ f.write("[General]\n")
qtc_cfg = os.path.join(PROJECT_DIR, "%s.config" % FILE_NAME)
- f = open(qtc_cfg, 'w')
- f.write("// ADD PREDEFINED MACROS TO %s_custom.config!\n" % FILE_NAME)
- qtc_custom_cfg = os.path.join(PROJECT_DIR, "%s_custom.config" % FILE_NAME)
- if os.path.exists(qtc_custom_cfg):
- fc = open(qtc_custom_cfg, 'r')
- f.write(fc.read())
- fc.close()
- f.write("\n")
- defines_final = [("#define %s %s" % (item[0], quote_define(item[1]))) for item in defines]
- if sys.platform != "win32":
- defines_final += cmake_compiler_defines()
- f.write("\n".join(defines_final))
+ with open(qtc_cfg, 'w') as f:
+ f.write("// ADD PREDEFINED MACROS TO %s_custom.config!\n" % FILE_NAME)
+
+ qtc_custom_cfg = os.path.join(PROJECT_DIR, "%s_custom.config" % FILE_NAME)
+ if os.path.exists(qtc_custom_cfg):
+ with open(qtc_custom_cfg, 'r') as fc:
+ f.write(fc.read())
+ f.write("\n")
+
+ defines_final = [("#define %s %s" % (item[0], quote_define(item[1]))) for item in defines]
+ if sys.platform != "win32":
+ defines_final += cmake_compiler_defines()
+ f.write("\n".join(defines_final))
print("Blender project file written to: %r" % qtc_prj)
# --- end
@@ -137,17 +140,17 @@ def create_qtc_project_python():
PROJECT_NAME = project_name_get() + "_Python"
FILE_NAME = PROJECT_NAME.lower()
- f = open(os.path.join(PROJECT_DIR, "%s.files" % FILE_NAME), 'w')
- f.write("\n".join(files_rel))
+ with open(os.path.join(PROJECT_DIR, "%s.files" % FILE_NAME), 'w') as f:
+ f.write("\n".join(files_rel))
qtc_prj = os.path.join(PROJECT_DIR, "%s.creator" % FILE_NAME)
- f = open(qtc_prj, 'w')
- f.write("[General]\n")
+ with open(qtc_prj, 'w') as f:
+ f.write("[General]\n")
qtc_cfg = os.path.join(PROJECT_DIR, "%s.config" % FILE_NAME)
if not os.path.exists(qtc_cfg):
- f = open(qtc_cfg, 'w')
- f.write("// ADD PREDEFINED MACROS HERE!\n")
+ with open(qtc_cfg, 'w') as f:
+ f.write("// ADD PREDEFINED MACROS HERE!\n")
print("Python project file written to: %r" % qtc_prj)
diff --git a/build_files/cmake/config/blender_full.cmake b/build_files/cmake/config/blender_full.cmake
new file mode 100644
index 00000000000..881dc515499
--- /dev/null
+++ b/build_files/cmake/config/blender_full.cmake
@@ -0,0 +1,69 @@
+# Turn everything ON thats expected for an official release builds.
+#
+# Example usage:
+# cmake -C../blender/build_files/cmake/config/blender_full.cmake ../blender
+#
+
+set(WITH_BUILDINFO ON CACHE BOOL "" FORCE)
+set(WITH_BULLET ON CACHE BOOL "" FORCE)
+set(WITH_CODEC_AVI ON CACHE BOOL "" FORCE)
+set(WITH_CODEC_FFMPEG ON CACHE BOOL "" FORCE)
+set(WITH_CODEC_SNDFILE ON CACHE BOOL "" FORCE)
+set(WITH_CYCLES ON CACHE BOOL "" FORCE)
+set(WITH_FFTW3 ON CACHE BOOL "" FORCE)
+set(WITH_LIBMV ON CACHE BOOL "" FORCE)
+set(WITH_LIBMV_SCHUR_SPECIALIZATIONS ON CACHE BOOL "" FORCE)
+set(WITH_GAMEENGINE ON CACHE BOOL "" FORCE)
+set(WITH_COMPOSITOR ON CACHE BOOL "" FORCE)
+set(WITH_FREESTYLE ON CACHE BOOL "" FORCE)
+set(WITH_GHOST_XDND ON CACHE BOOL "" FORCE)
+set(WITH_IK_SOLVER ON CACHE BOOL "" FORCE)
+set(WITH_IK_ITASC ON CACHE BOOL "" FORCE)
+set(WITH_IMAGE_CINEON ON CACHE BOOL "" FORCE)
+set(WITH_IMAGE_DDS ON CACHE BOOL "" FORCE)
+set(WITH_IMAGE_FRAMESERVER ON CACHE BOOL "" FORCE)
+set(WITH_IMAGE_HDR ON CACHE BOOL "" FORCE)
+set(WITH_IMAGE_OPENEXR ON CACHE BOOL "" FORCE)
+set(WITH_IMAGE_OPENJPEG ON CACHE BOOL "" FORCE)
+set(WITH_IMAGE_REDCODE ON CACHE BOOL "" FORCE)
+set(WITH_IMAGE_TIFF ON CACHE BOOL "" FORCE)
+set(WITH_INPUT_NDOF ON CACHE BOOL "" FORCE)
+set(WITH_INTERNATIONAL ON CACHE BOOL "" FORCE)
+set(WITH_JACK ON CACHE BOOL "" FORCE)
+set(WITH_LZMA ON CACHE BOOL "" FORCE)
+set(WITH_LZO ON CACHE BOOL "" FORCE)
+set(WITH_MOD_BOOLEAN ON CACHE BOOL "" FORCE)
+set(WITH_MOD_FLUID ON CACHE BOOL "" FORCE)
+set(WITH_MOD_REMESH ON CACHE BOOL "" FORCE)
+set(WITH_MOD_SMOKE ON CACHE BOOL "" FORCE)
+set(WITH_MOD_OCEANSIM ON CACHE BOOL "" FORCE)
+set(WITH_AUDASPACE ON CACHE BOOL "" FORCE)
+set(WITH_OPENAL ON CACHE BOOL "" FORCE)
+set(WITH_OPENCOLLADA ON CACHE BOOL "" FORCE)
+set(WITH_OPENCOLORIO ON CACHE BOOL "" FORCE)
+set(WITH_OPENMP ON CACHE BOOL "" FORCE)
+set(WITH_OPENNL ON CACHE BOOL "" FORCE)
+set(WITH_PYTHON_INSTALL ON CACHE BOOL "" FORCE)
+set(WITH_RAYOPTIMIZATION ON CACHE BOOL "" FORCE)
+set(WITH_SDL ON CACHE BOOL "" FORCE)
+set(WITH_X11_XINPUT ON CACHE BOOL "" FORCE)
+set(WITH_X11_XF86VMODE ON CACHE BOOL "" FORCE)
+
+set(WITH_PLAYER ON CACHE BOOL "" FORCE)
+set(WITH_MEM_JEMALLOC ON CACHE BOOL "" FORCE)
+
+
+# platform dependant options
+if(UNIX AND NOT APPLE)
+ set(WITH_JACK ON CACHE BOOL "" FORCE)
+ set(WITH_DOC_MANPAGE ON CACHE BOOL "" FORCE)
+ set(WITH_OPENSUBDIV ON CACHE BOOL "" FORCE)
+elseif(WIN32)
+ set(WITH_JACK OFF CACHE BOOL "" FORCE)
+ set(WITH_OPENSUBDIV ON CACHE BOOL "" FORCE)
+elseif (APPLE)
+ set(WITH_JACK ON CACHE BOOL "" FORCE)
+ set(WITH_CODEC_QUICKTIME ON CACHE BOOL "" FORCE)
+ set(WITH_OPENSUBDIV OFF CACHE BOOL "" FORCE)
+endif()
+
diff --git a/build_files/cmake/config/blender_lite.cmake b/build_files/cmake/config/blender_lite.cmake
index bf5c4f9e103..2a57e4c33d8 100644
--- a/build_files/cmake/config/blender_lite.cmake
+++ b/build_files/cmake/config/blender_lite.cmake
@@ -16,6 +16,7 @@ set(WITH_CODEC_SNDFILE OFF CACHE BOOL "" FORCE)
set(WITH_CYCLES OFF CACHE BOOL "" FORCE)
set(WITH_FFTW3 OFF CACHE BOOL "" FORCE)
set(WITH_LIBMV OFF CACHE BOOL "" FORCE)
+set(WITH_LLVM OFF CACHE BOOL "" FORCE)
set(WITH_GAMEENGINE OFF CACHE BOOL "" FORCE)
set(WITH_COMPOSITOR OFF CACHE BOOL "" FORCE)
set(WITH_FREESTYLE OFF CACHE BOOL "" FORCE)
@@ -44,6 +45,7 @@ set(WITH_AUDASPACE OFF CACHE BOOL "" FORCE)
set(WITH_OPENAL OFF CACHE BOOL "" FORCE)
set(WITH_OPENCOLLADA OFF CACHE BOOL "" FORCE)
set(WITH_OPENCOLORIO OFF CACHE BOOL "" FORCE)
+set(WITH_OPENIMAGEIO OFF CACHE BOOL "" FORCE)
set(WITH_OPENMP OFF CACHE BOOL "" FORCE)
set(WITH_OPENNL OFF CACHE BOOL "" FORCE)
set(WITH_PYTHON_INSTALL OFF CACHE BOOL "" FORCE)
diff --git a/build_files/cmake/macros.cmake b/build_files/cmake/macros.cmake
index adbba817150..90c4fbd5674 100644
--- a/build_files/cmake/macros.cmake
+++ b/build_files/cmake/macros.cmake
@@ -48,7 +48,7 @@ macro(list_insert_before
unset(_index)
endmacro()
-function (list_assert_duplicates
+function(list_assert_duplicates
list_id
)
@@ -104,24 +104,48 @@ macro(file_list_suffix
endmacro()
-macro(target_link_libraries_optimized TARGET LIBS)
+function(target_link_libraries_optimized
+ TARGET
+ LIBS
+ )
+
foreach(_LIB ${LIBS})
target_link_libraries(${TARGET} optimized "${_LIB}")
endforeach()
- unset(_LIB)
-endmacro()
+endfunction()
+
+function(target_link_libraries_debug
+ TARGET
+ LIBS
+ )
-macro(target_link_libraries_debug TARGET LIBS)
foreach(_LIB ${LIBS})
target_link_libraries(${TARGET} debug "${_LIB}")
endforeach()
- unset(_LIB)
-endmacro()
+endfunction()
+
+function(target_link_libraries_decoupled
+ target
+ libraries_var
+ )
+
+ if(NOT MSVC)
+ target_link_libraries(${target} ${${libraries_var}})
+ else()
+ # For MSVC we link to different libraries depending whether
+ # release or debug target is being built.
+ file_list_suffix(_libraries_debug "${${libraries_var}}" "_d")
+ target_link_libraries_debug(${target} "${_libraries_debug}")
+ target_link_libraries_optimized(${target} "${${libraries_var}}")
+ endif()
+endfunction()
# Nicer makefiles with -I/1/foo/ instead of -I/1/2/3/../../foo/
# use it instead of include_directories()
-macro(blender_include_dirs
- includes)
+function(blender_include_dirs
+ includes
+ )
+
set(_ALL_INCS "")
foreach(_INC ${ARGV})
get_filename_component(_ABS_INC ${_INC} ABSOLUTE)
@@ -132,13 +156,12 @@ macro(blender_include_dirs
##endif()
endforeach()
include_directories(${_ALL_INCS})
- unset(_INC)
- unset(_ABS_INC)
- unset(_ALL_INCS)
-endmacro()
+endfunction()
+
+function(blender_include_dirs_sys
+ includes
+ )
-macro(blender_include_dirs_sys
- includes)
set(_ALL_INCS "")
foreach(_INC ${ARGV})
get_filename_component(_ABS_INC ${_INC} ABSOLUTE)
@@ -148,13 +171,11 @@ macro(blender_include_dirs_sys
##endif()
endforeach()
include_directories(SYSTEM ${_ALL_INCS})
- unset(_INC)
- unset(_ABS_INC)
- unset(_ALL_INCS)
-endmacro()
+endfunction()
-macro(blender_source_group
- sources)
+function(blender_source_group
+ sources
+ )
# Group by location on disk
source_group("Source Files" FILES CMakeLists.txt)
@@ -164,23 +185,23 @@ macro(blender_source_group
if((${_SRC_EXT} MATCHES ".h") OR
(${_SRC_EXT} MATCHES ".hpp") OR
(${_SRC_EXT} MATCHES ".hh"))
- source_group("Header Files" FILES ${_SRC})
+
+ set(GROUP_ID "Header Files")
else()
- source_group("Source Files" FILES ${_SRC})
+ set(GROUP_ID "Source Files")
endif()
+ source_group("${GROUP_ID}" FILES ${_SRC})
endforeach()
-
- unset(_SRC)
- unset(_SRC_EXT)
-endmacro()
+endfunction()
# only MSVC uses SOURCE_GROUP
-macro(blender_add_lib_nolist
+function(blender_add_lib_nolist
name
sources
includes
- includes_sys)
+ includes_sys
+ )
# message(STATUS "Configuring library ${name}")
@@ -200,28 +221,30 @@ macro(blender_add_lib_nolist
# Not for system includes because they can resolve to the same path
# list_assert_duplicates("${includes_sys}")
-endmacro()
+endfunction()
-macro(blender_add_lib
+function(blender_add_lib
name
sources
includes
- includes_sys)
+ includes_sys
+ )
blender_add_lib_nolist(${name} "${sources}" "${includes}" "${includes_sys}")
set_property(GLOBAL APPEND PROPERTY BLENDER_LINK_LIBS ${name})
-endmacro()
+endfunction()
-macro(SETUP_LIBDIRS)
+function(SETUP_LIBDIRS)
+
link_directories(${JPEG_LIBPATH} ${PNG_LIBPATH} ${ZLIB_LIBPATH} ${FREETYPE_LIBPATH})
if(WITH_PYTHON) # AND NOT WITH_PYTHON_MODULE # WIN32 needs
link_directories(${PYTHON_LIBPATH})
endif()
- if(WITH_SDL)
+ if(WITH_SDL AND NOT WITH_SDL_DYNLOAD)
link_directories(${SDL_LIBPATH})
endif()
if(WITH_CODEC_FFMPEG)
@@ -275,20 +298,27 @@ macro(SETUP_LIBDIRS)
if(WIN32 AND NOT UNIX)
link_directories(${PTHREADS_LIBPATH})
endif()
-endmacro()
+endfunction()
-macro(setup_liblinks
- target)
+function(setup_liblinks
+ target
+ )
- set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${PLATFORM_LINKFLAGS}")
- set(CMAKE_EXE_LINKER_FLAGS_DEBUG "${CMAKE_EXE_LINKER_FLAGS_DEBUG} ${PLATFORM_LINKFLAGS_DEBUG}")
+ set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${PLATFORM_LINKFLAGS}" PARENT_SCOPE)
+ set(CMAKE_EXE_LINKER_FLAGS_DEBUG "${CMAKE_EXE_LINKER_FLAGS_DEBUG} ${PLATFORM_LINKFLAGS_DEBUG}" PARENT_SCOPE)
- target_link_libraries(${target}
- ${OPENGL_gl_LIBRARY}
- ${OPENGL_glu_LIBRARY}
- ${PNG_LIBRARIES}
- ${ZLIB_LIBRARIES}
- ${FREETYPE_LIBRARY})
+ set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ${PLATFORM_LINKFLAGS}" PARENT_SCOPE)
+ set(CMAKE_SHARED_LINKER_FLAGS_DEBUG "${CMAKE_SHARED_LINKER_FLAGS_DEBUG} ${PLATFORM_LINKFLAGS_DEBUG}" PARENT_SCOPE)
+
+ set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} ${PLATFORM_LINKFLAGS}" PARENT_SCOPE)
+ set(CMAKE_MODULE_LINKER_FLAGS_DEBUG "${CMAKE_MODULE_LINKER_FLAGS_DEBUG} ${PLATFORM_LINKFLAGS_DEBUG}" PARENT_SCOPE)
+
+ target_link_libraries(
+ ${target}
+ ${PNG_LIBRARIES}
+ ${ZLIB_LIBRARIES}
+ ${FREETYPE_LIBRARY}
+ )
# since we are using the local libs for python when compiling msvc projects, we need to add _d when compiling debug versions
if(WITH_PYTHON) # AND NOT WITH_PYTHON_MODULE # WIN32 needs
@@ -304,12 +334,18 @@ macro(setup_liblinks
endif()
endif()
+ if(WITH_LZO AND WITH_SYSTEM_LZO)
+ target_link_libraries(${target} ${LZO_LIBRARIES})
+ endif()
if(WITH_SYSTEM_GLEW)
- target_link_libraries(${target} ${GLEW_LIBRARY})
+ target_link_libraries(${target} ${BLENDER_GLEW_LIBRARIES})
endif()
if(WITH_BULLET AND WITH_SYSTEM_BULLET)
target_link_libraries(${target} ${BULLET_LIBRARIES})
endif()
+ if(WITH_AUDASPACE AND WITH_SYSTEM_AUDASPACE)
+ target_link_libraries(${target} ${AUDASPACE_C_LIBRARIES} ${AUDASPACE_PY_LIBRARIES})
+ endif()
if(WITH_OPENAL)
target_link_libraries(${target} ${OPENAL_LIBRARY})
endif()
@@ -322,7 +358,7 @@ macro(setup_liblinks
if(WITH_CODEC_SNDFILE)
target_link_libraries(${target} ${SNDFILE_LIBRARIES})
endif()
- if(WITH_SDL)
+ if(WITH_SDL AND NOT WITH_SDL_DYNLOAD)
target_link_libraries(${target} ${SDL_LIBRARY})
endif()
if(WITH_CODEC_QUICKTIME)
@@ -337,6 +373,19 @@ macro(setup_liblinks
if(WITH_OPENCOLORIO)
target_link_libraries(${target} ${OPENCOLORIO_LIBRARIES})
endif()
+ if(WITH_OPENSUBDIV)
+ if(WIN32 AND NOT UNIX)
+ file_list_suffix(OPENSUBDIV_LIBRARIES_DEBUG "${OPENSUBDIV_LIBRARIES}" "_d")
+ target_link_libraries_debug(${target} "${OPENSUBDIV_LIBRARIES_DEBUG}")
+ target_link_libraries_optimized(${target} "${OPENSUBDIV_LIBRARIES}")
+ unset(OPENSUBDIV_LIBRARIES_DEBUG)
+ else()
+ target_link_libraries(${target} ${OPENSUBDIV_LIBRARIES})
+ endif()
+ endif()
+ if(WITH_CYCLES_OSL)
+ target_link_libraries(${target} ${OSL_LIBRARIES})
+ endif()
if(WITH_BOOST)
target_link_libraries(${target} ${BOOST_LIBRARIES})
if(Boost_USE_STATIC_LIBS AND Boost_USE_ICU)
@@ -358,11 +407,6 @@ macro(setup_liblinks
target_link_libraries(${target} ${OPENJPEG_LIBRARIES})
endif()
if(WITH_CODEC_FFMPEG)
-
- # Strange!, without this ffmpeg gives linking errors (on linux)
- # even though its linked above
- target_link_libraries(${target} ${OPENGL_glu_LIBRARY})
-
target_link_libraries(${target} ${FFMPEG_LIBRARIES})
endif()
if(WITH_OPENCOLLADA)
@@ -384,11 +428,13 @@ macro(setup_liblinks
unset(EXPAT_LIB_DEBUG)
endif()
else()
- target_link_libraries(${target}
- ${OPENCOLLADA_LIBRARIES}
- ${PCRE_LIBRARIES}
- ${XML2_LIBRARIES}
- ${EXPAT_LIB})
+ target_link_libraries(
+ ${target}
+ ${OPENCOLLADA_LIBRARIES}
+ ${PCRE_LIBRARIES}
+ ${XML2_LIBRARIES}
+ ${EXPAT_LIB}
+ )
endif()
endif()
if(WITH_MEM_JEMALLOC)
@@ -400,9 +446,6 @@ macro(setup_liblinks
if(WITH_MOD_CLOTH_ELTOPO)
target_link_libraries(${target} ${LAPACK_LIBRARIES})
endif()
- if(WITH_CYCLES_OSL)
- target_link_libraries(${target} ${OSL_LIBRARIES})
- endif()
if(WITH_LLVM)
target_link_libraries(${target} ${LLVM_LIBRARY})
endif()
@@ -410,16 +453,22 @@ macro(setup_liblinks
target_link_libraries(${target} ${PTHREADS_LIBRARIES})
endif()
- target_link_libraries(${target} ${PLATFORM_LINKLIBS} ${CMAKE_DL_LIBS})
-
# We put CLEW and CUEW here because OPENSUBDIV_LIBRARIES dpeends on them..
if(WITH_CYCLES OR WITH_COMPOSITOR OR WITH_OPENSUBDIV)
target_link_libraries(${target} "extern_clew")
target_link_libraries(${target} "extern_cuew")
endif()
-endmacro()
-macro(SETUP_BLENDER_SORTED_LIBS)
+ #system libraries with no dependencies such as platform link libs or opengl should go last
+ target_link_libraries(${target}
+ ${BLENDER_GL_LIBRARIES})
+
+ target_link_libraries(${target} ${PLATFORM_LINKLIBS} ${CMAKE_DL_LIBS})
+endfunction()
+
+
+function(SETUP_BLENDER_SORTED_LIBS)
+
get_property(BLENDER_LINK_LIBS GLOBAL PROPERTY BLENDER_LINK_LIBS)
list(APPEND BLENDER_LINK_LIBS
@@ -497,13 +546,15 @@ macro(SETUP_BLENDER_SORTED_LIBS)
bf_ikplugin
bf_modifiers
bf_bmesh
+ bf_gpu
bf_blenkernel
+ bf_physics
bf_nodes
bf_rna
- bf_gpu
bf_blenloader
bf_imbuf
bf_blenlib
+ bf_depsgraph
bf_intern_ghost
bf_intern_string
bf_avi
@@ -522,7 +573,6 @@ macro(SETUP_BLENDER_SORTED_LIBS)
ge_phys_dummy
ge_phys_bullet
bf_intern_smoke
- extern_minilzo
extern_lzma
extern_colamd
ge_logic_ketsji
@@ -541,6 +591,7 @@ macro(SETUP_BLENDER_SORTED_LIBS)
ge_videotex
bf_dna
bf_blenfont
+ bf_blentranslation
bf_intern_audaspace
bf_intern_mikktspace
bf_intern_dualcon
@@ -557,6 +608,10 @@ macro(SETUP_BLENDER_SORTED_LIBS)
extern_wcwidth
extern_libmv
extern_glog
+ extern_sdlew
+ extern_eigen3
+
+ bf_intern_glew_mx
)
if(WITH_COMPOSITOR)
@@ -573,8 +628,12 @@ macro(SETUP_BLENDER_SORTED_LIBS)
list(APPEND BLENDER_SORTED_LIBS extern_eltopo)
endif()
+ if(NOT WITH_SYSTEM_LZO)
+ list(APPEND BLENDER_SORTED_LIBS extern_minilzo)
+ endif()
+
if(NOT WITH_SYSTEM_GLEW)
- list(APPEND BLENDER_SORTED_LIBS extern_glew)
+ list(APPEND BLENDER_SORTED_LIBS ${BLENDER_GLEW_LIBRARIES})
endif()
if(WITH_BINRELOC)
@@ -629,6 +688,10 @@ macro(SETUP_BLENDER_SORTED_LIBS)
list_insert_after(BLENDER_SORTED_LIBS "ge_logic_ngnetwork" "extern_bullet")
endif()
+ if(WITH_OPENSUBDIV)
+ list(APPEND BLENDER_SORTED_LIBS bf_intern_opensubdiv)
+ endif()
+
foreach(SORTLIB ${BLENDER_SORTED_LIBS})
set(REMLIB ${SORTLIB})
foreach(SEARCHLIB ${BLENDER_LINK_LIBS})
@@ -647,14 +710,12 @@ macro(SETUP_BLENDER_SORTED_LIBS)
message(STATUS "Blender Skipping: (${REM_MSG})")
endif()
- unset(SEARCHLIB)
- unset(SORTLIB)
- unset(REMLIB)
- unset(REM_MSG)
+
+ set(BLENDER_SORTED_LIBS ${BLENDER_SORTED_LIBS} PARENT_SCOPE)
# for top-level tests
set_property(GLOBAL PROPERTY BLENDER_SORTED_LIBS_PROP ${BLENDER_SORTED_LIBS})
-endmacro()
+endfunction()
macro(TEST_SSE_SUPPORT
_sse_flags
@@ -718,6 +779,8 @@ macro(TEST_SSE_SUPPORT
endmacro()
macro(TEST_STDBOOL_SUPPORT)
+ include(CheckCSourceRuns)
+
# This program will compile correctly if and only if
# this C compiler supports C99 stdbool.
check_c_source_runs("
@@ -874,19 +937,22 @@ endmacro()
# utility macro
macro(remove_cc_flag
- flag)
-
- string(REGEX REPLACE ${flag} "" CMAKE_C_FLAGS "${CMAKE_C_FLAGS}")
- string(REGEX REPLACE ${flag} "" CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG}")
- string(REGEX REPLACE ${flag} "" CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE}")
- string(REGEX REPLACE ${flag} "" CMAKE_C_FLAGS_MINSIZEREL "${CMAKE_C_FLAGS_MINSIZEREL}")
- string(REGEX REPLACE ${flag} "" CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO}")
-
- string(REGEX REPLACE ${flag} "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
- string(REGEX REPLACE ${flag} "" CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}")
- string(REGEX REPLACE ${flag} "" CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE}")
- string(REGEX REPLACE ${flag} "" CMAKE_CXX_FLAGS_MINSIZEREL "${CMAKE_CXX_FLAGS_MINSIZEREL}")
- string(REGEX REPLACE ${flag} "" CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO}")
+ _flag)
+
+ foreach(flag ${ARGV})
+ string(REGEX REPLACE ${flag} "" CMAKE_C_FLAGS "${CMAKE_C_FLAGS}")
+ string(REGEX REPLACE ${flag} "" CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG}")
+ string(REGEX REPLACE ${flag} "" CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE}")
+ string(REGEX REPLACE ${flag} "" CMAKE_C_FLAGS_MINSIZEREL "${CMAKE_C_FLAGS_MINSIZEREL}")
+ string(REGEX REPLACE ${flag} "" CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO}")
+
+ string(REGEX REPLACE ${flag} "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
+ string(REGEX REPLACE ${flag} "" CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}")
+ string(REGEX REPLACE ${flag} "" CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE}")
+ string(REGEX REPLACE ${flag} "" CMAKE_CXX_FLAGS_MINSIZEREL "${CMAKE_CXX_FLAGS_MINSIZEREL}")
+ string(REGEX REPLACE ${flag} "" CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO}")
+ endforeach()
+ unset(flag)
endmacro()
@@ -900,27 +966,34 @@ endmacro()
macro(remove_strict_flags)
if(CMAKE_COMPILER_IS_GNUCC)
- remove_cc_flag("-Wstrict-prototypes")
- remove_cc_flag("-Wmissing-prototypes")
- remove_cc_flag("-Wunused-parameter")
- remove_cc_flag("-Wwrite-strings")
- remove_cc_flag("-Wredundant-decls")
- remove_cc_flag("-Wundef")
- remove_cc_flag("-Wshadow")
- remove_cc_flag("-Wdouble-promotion")
- remove_cc_flag("-Wold-style-definition")
- remove_cc_flag("-Werror=[^ ]+")
- remove_cc_flag("-Werror")
+ remove_cc_flag(
+ "-Wstrict-prototypes"
+ "-Wmissing-prototypes"
+ "-Wmissing-format-attribute"
+ "-Wunused-local-typedefs"
+ "-Wunused-macros"
+ "-Wunused-parameter"
+ "-Wwrite-strings"
+ "-Wredundant-decls"
+ "-Wundef"
+ "-Wshadow"
+ "-Wdouble-promotion"
+ "-Wold-style-definition"
+ "-Werror=[^ ]+"
+ "-Werror"
+ )
# negate flags implied by '-Wall'
add_cc_flag("${CC_REMOVE_STRICT_FLAGS}")
endif()
if(CMAKE_C_COMPILER_ID MATCHES "Clang")
- remove_cc_flag("-Wunused-parameter")
- remove_cc_flag("-Wunused-variable")
- remove_cc_flag("-Werror=[^ ]+")
- remove_cc_flag("-Werror")
+ remove_cc_flag(
+ "-Wunused-parameter"
+ "-Wunused-variable"
+ "-Werror=[^ ]+"
+ "-Werror"
+ )
# negate flags implied by '-Wall'
add_cc_flag("${CC_REMOVE_STRICT_FLAGS}")
@@ -932,6 +1005,24 @@ macro(remove_strict_flags)
endmacro()
+macro(remove_extra_strict_flags)
+ if(CMAKE_COMPILER_IS_GNUCC)
+ remove_cc_flag(
+ "-Wunused-parameter"
+ )
+ endif()
+
+ if(CMAKE_C_COMPILER_ID MATCHES "Clang")
+ remove_cc_flag(
+ "-Wunused-parameter"
+ )
+ endif()
+
+ if(MSVC)
+ # TODO
+ endif()
+endmacro()
+
# note, we can only append flags on a single file so we need to negate the options.
# at the moment we cant shut up ffmpeg deprecations, so use this, but will
# probably add more removals here.
@@ -960,39 +1051,50 @@ macro(remove_strict_flags_file
endmacro()
-macro(ADD_CHECK_C_COMPILER_FLAG
+function(ADD_CHECK_C_COMPILER_FLAG
_CFLAGS
_CACHE_VAR
- _FLAG)
+ _FLAG
+ )
include(CheckCCompilerFlag)
CHECK_C_COMPILER_FLAG("${_FLAG}" "${_CACHE_VAR}")
if(${_CACHE_VAR})
# message(STATUS "Using CFLAG: ${_FLAG}")
- set(${_CFLAGS} "${${_CFLAGS}} ${_FLAG}")
+ set(${_CFLAGS} "${${_CFLAGS}} ${_FLAG}" PARENT_SCOPE)
else()
message(STATUS "Unsupported CFLAG: ${_FLAG}")
endif()
-endmacro()
+endfunction()
-macro(ADD_CHECK_CXX_COMPILER_FLAG
+function(ADD_CHECK_CXX_COMPILER_FLAG
_CXXFLAGS
_CACHE_VAR
- _FLAG)
+ _FLAG
+ )
include(CheckCXXCompilerFlag)
CHECK_CXX_COMPILER_FLAG("${_FLAG}" "${_CACHE_VAR}")
if(${_CACHE_VAR})
# message(STATUS "Using CXXFLAG: ${_FLAG}")
- set(${_CXXFLAGS} "${${_CXXFLAGS}} ${_FLAG}")
+ set(${_CXXFLAGS} "${${_CXXFLAGS}} ${_FLAG}" PARENT_SCOPE)
else()
message(STATUS "Unsupported CXXFLAG: ${_FLAG}")
endif()
-endmacro()
+endfunction()
+
+function(get_blender_version)
+ # extracts header vars and defines them in the parent scope:
+ #
+ # - BLENDER_VERSION (major.minor)
+ # - BLENDER_VERSION_MAJOR
+ # - BLENDER_VERSION_MINOR
+ # - BLENDER_SUBVERSION (used for internal versioning mainly)
+ # - BLENDER_VERSION_CHAR (a, b, c, ...or empty string)
+ # - BLENDER_VERSION_CYCLE (alpha, beta, rc, release)
-macro(get_blender_version)
# So cmake depends on BKE_blender.h, beware of inf-loops!
CONFIGURE_FILE(${CMAKE_SOURCE_DIR}/source/blender/blenkernel/BKE_blender.h
${CMAKE_BINARY_DIR}/source/blender/blenkernel/BKE_blender.h.done)
@@ -1025,33 +1127,29 @@ macro(get_blender_version)
message(FATAL_ERROR "Version parsing failed for BLENDER_VERSION_CYCLE")
endif()
- math(EXPR BLENDER_VERSION_MAJOR "${_out_version} / 100")
- math(EXPR BLENDER_VERSION_MINOR "${_out_version} % 100")
- set(BLENDER_VERSION "${BLENDER_VERSION_MAJOR}.${BLENDER_VERSION_MINOR}")
-
- set(BLENDER_SUBVERSION ${_out_subversion})
- set(BLENDER_VERSION_CHAR ${_out_version_char})
- set(BLENDER_VERSION_CYCLE ${_out_version_cycle})
+ math(EXPR _out_version_major "${_out_version} / 100")
+ math(EXPR _out_version_minor "${_out_version} % 100")
# for packaging, alpha to numbers
- string(COMPARE EQUAL "${BLENDER_VERSION_CHAR}" "" _out_version_char_empty)
+ string(COMPARE EQUAL "${_out_version_char}" "" _out_version_char_empty)
if(${_out_version_char_empty})
- set(BLENDER_VERSION_CHAR_INDEX "0")
+ set(_out_version_char_index "0")
else()
set(_char_ls a b c d e f g h i j k l m n o p q r s t u v w x y z)
- list(FIND _char_ls ${BLENDER_VERSION_CHAR} _out_version_char_index)
- math(EXPR BLENDER_VERSION_CHAR_INDEX "${_out_version_char_index} + 1")
- unset(_char_ls)
- unset(_out_version_char_index)
+ list(FIND _char_ls ${_out_version_char} _out_version_char_index)
+ math(EXPR _out_version_char_index "${_out_version_char_index} + 1")
endif()
- unset(_out_subversion)
- unset(_out_version_char)
- unset(_out_version_char_empty)
- unset(_out_version_cycle)
+ # output vars
+ set(BLENDER_VERSION "${_out_version_major}.${_out_version_minor}" PARENT_SCOPE)
+ set(BLENDER_VERSION_MAJOR "${_out_version_major}" PARENT_SCOPE)
+ set(BLENDER_VERSION_MINOR "${_out_version_minor}" PARENT_SCOPE)
+ set(BLENDER_SUBVERSION "${_out_subversion}" PARENT_SCOPE)
+ set(BLENDER_VERSION_CHAR "${_out_version_char}" PARENT_SCOPE)
+ set(BLENDER_VERSION_CHAR_INDEX "${_out_version_char_index}" PARENT_SCOPE)
+ set(BLENDER_VERSION_CYCLE "${_out_version_cycle}" PARENT_SCOPE)
- # message(STATUS "Version (Internal): ${BLENDER_VERSION}.${BLENDER_SUBVERSION}, Version (external): ${BLENDER_VERSION}${BLENDER_VERSION_CHAR}-${BLENDER_VERSION_CYCLE}")
-endmacro()
+endfunction()
# hacks to override initial project settings
@@ -1088,7 +1186,7 @@ endmacro()
macro(blender_project_hack_post)
# --------------
# MINGW HACK END
- if (_reset_standard_libraries)
+ if(_reset_standard_libraries)
# Must come after projecINCt(...)
#
# MINGW workaround for -ladvapi32 being included which surprisingly causes
@@ -1135,7 +1233,7 @@ endmacro()
# pair of macros to allow libraries to be specify files to install, but to
# only install them at the end so the directories don't get cleared with
# the files in them. used by cycles to install addon.
-macro(delayed_install
+function(delayed_install
base
files
destination)
@@ -1148,7 +1246,7 @@ macro(delayed_install
endif()
set_property(GLOBAL APPEND PROPERTY DELAYED_INSTALL_DESTINATIONS ${destination})
endforeach()
-endmacro()
+endfunction()
# note this is a function instead of a macro so that ${BUILD_TYPE} in targetdir
# does not get expanded in calling but is preserved
@@ -1171,57 +1269,55 @@ function(delayed_do_install
endfunction()
-macro(data_to_c
- file_from file_to
- list_to_add)
+function(data_to_c
+ file_from file_to
+ list_to_add
+ )
list(APPEND ${list_to_add} ${file_to})
+ set(${list_to_add} ${${list_to_add}} PARENT_SCOPE)
get_filename_component(_file_to_path ${file_to} PATH)
add_custom_command(
OUTPUT ${file_to}
COMMAND ${CMAKE_COMMAND} -E make_directory ${_file_to_path}
- COMMAND ${CMAKE_BINARY_DIR}/bin/${CMAKE_CFG_INTDIR}/datatoc ${file_from} ${file_to}
+ COMMAND "$<TARGET_FILE:datatoc>" ${file_from} ${file_to}
DEPENDS ${file_from} datatoc)
set_source_files_properties(${file_to} PROPERTIES GENERATED TRUE)
-
- unset(_file_to_path)
-endmacro()
+endfunction()
# same as above but generates the var name and output automatic.
-macro(data_to_c_simple
- file_from
- list_to_add)
+function(data_to_c_simple
+ file_from
+ list_to_add
+ )
# remove ../'s
get_filename_component(_file_from ${CMAKE_CURRENT_SOURCE_DIR}/${file_from} REALPATH)
get_filename_component(_file_to ${CMAKE_CURRENT_BINARY_DIR}/${file_from}.c REALPATH)
list(APPEND ${list_to_add} ${_file_to})
+ set(${list_to_add} ${${list_to_add}} PARENT_SCOPE)
get_filename_component(_file_to_path ${_file_to} PATH)
add_custom_command(
OUTPUT ${_file_to}
COMMAND ${CMAKE_COMMAND} -E make_directory ${_file_to_path}
- COMMAND ${CMAKE_BINARY_DIR}/bin/${CMAKE_CFG_INTDIR}/datatoc ${_file_from} ${_file_to}
+ COMMAND "$<TARGET_FILE:datatoc>" ${_file_from} ${_file_to}
DEPENDS ${_file_from} datatoc)
set_source_files_properties(${_file_to} PROPERTIES GENERATED TRUE)
-
- unset(_file_from)
- unset(_file_to)
- unset(_file_to_path)
-endmacro()
+endfunction()
# macro for converting pixmap directory to a png and then a c file
-macro(data_to_c_simple_icons
- path_from
- list_to_add
- )
+function(data_to_c_simple_icons
+ path_from
+ list_to_add
+ )
# Conversion steps
# path_from -> _file_from -> _file_to
@@ -1233,6 +1329,7 @@ macro(data_to_c_simple_icons
get_filename_component(_file_to ${CMAKE_CURRENT_BINARY_DIR}/${path_from}.png.c REALPATH)
list(APPEND ${list_to_add} ${_file_to})
+ set(${list_to_add} ${${list_to_add}} PARENT_SCOPE)
get_filename_component(_file_to_path ${_file_to} PATH)
@@ -1243,8 +1340,8 @@ macro(data_to_c_simple_icons
OUTPUT ${_file_from} ${_file_to}
COMMAND ${CMAKE_COMMAND} -E make_directory ${_file_to_path}
#COMMAND python3 ${CMAKE_SOURCE_DIR}/source/blender/datatoc/datatoc_icon.py ${_path_from_abs} ${_file_from}
- COMMAND ${CMAKE_BINARY_DIR}/bin/${CMAKE_CFG_INTDIR}/datatoc_icon ${_path_from_abs} ${_file_from}
- COMMAND ${CMAKE_BINARY_DIR}/bin/${CMAKE_CFG_INTDIR}/datatoc ${_file_from} ${_file_to}
+ COMMAND "$<TARGET_FILE:datatoc_icon>" ${_path_from_abs} ${_file_from}
+ COMMAND "$<TARGET_FILE:datatoc>" ${_file_from} ${_file_to}
DEPENDS
${_icon_files}
datatoc_icon
@@ -1254,27 +1351,22 @@ macro(data_to_c_simple_icons
)
set_source_files_properties(${_file_from} ${_file_to} PROPERTIES GENERATED TRUE)
-
- unset(_path_from_abs)
- unset(_file_from)
- unset(_file_to)
- unset(_file_to_path)
- unset(_icon_files)
-
-endmacro()
+endfunction()
# XXX Not used for now...
-macro(svg_to_png
- file_from
- file_to
- dpi
- list_to_add)
+function(svg_to_png
+ file_from
+ file_to
+ dpi
+ list_to_add
+ )
# remove ../'s
get_filename_component(_file_from ${CMAKE_CURRENT_SOURCE_DIR}/${file_from} REALPATH)
get_filename_component(_file_to ${CMAKE_CURRENT_SOURCE_DIR}/${file_to} REALPATH)
list(APPEND ${list_to_add} ${_file_to})
+ set(${list_to_add} ${${list_to_add}} PARENT_SCOPE)
find_program(INKSCAPE_EXE inkscape)
mark_as_advanced(INKSCAPE_EXE)
@@ -1297,15 +1389,12 @@ macro(svg_to_png
else()
message(WARNING "Inkscape not found, could not re-generate ${_file_to} from ${_file_from}!")
endif()
+endfunction()
- unset(_file_from)
- unset(_file_to)
-
-endmacro()
-
-macro(msgfmt_simple
- file_from
- list_to_add)
+function(msgfmt_simple
+ file_from
+ list_to_add
+ )
# remove ../'s
get_filename_component(_file_from_we ${file_from} NAME_WE)
@@ -1314,25 +1403,22 @@ macro(msgfmt_simple
get_filename_component(_file_to ${CMAKE_CURRENT_BINARY_DIR}/${_file_from_we}.mo REALPATH)
list(APPEND ${list_to_add} ${_file_to})
+ set(${list_to_add} ${${list_to_add}} PARENT_SCOPE)
get_filename_component(_file_to_path ${_file_to} PATH)
add_custom_command(
OUTPUT ${_file_to}
COMMAND ${CMAKE_COMMAND} -E make_directory ${_file_to_path}
- COMMAND ${CMAKE_BINARY_DIR}/bin/${CMAKE_CFG_INTDIR}/msgfmt ${_file_from} ${_file_to}
+ COMMAND "$<TARGET_FILE:msgfmt>" ${_file_from} ${_file_to}
DEPENDS msgfmt ${_file_from})
set_source_files_properties(${_file_to} PROPERTIES GENERATED TRUE)
+endfunction()
- unset(_file_from_we)
- unset(_file_from)
- unset(_file_to)
- unset(_file_to_path)
-endmacro()
-
-macro(find_python_package
- package)
+function(find_python_package
+ package
+ )
string(TOUPPER ${package} _upper_package)
@@ -1370,14 +1456,17 @@ macro(find_python_package
"'${PYTHON_LIBPATH}/python${PYTHON_VERSION}/dist-packages/${package}', "
"'${PYTHON_LIBPATH}/python${_PY_VER_MAJOR}/dist-packages/${package}', "
"WITH_PYTHON_INSTALL_${_upper_package} option will be ignored when installing python")
- set(WITH_PYTHON_INSTALL_${_upper_package} OFF)
+ set(WITH_PYTHON_INSTALL_${_upper_package} OFF PARENT_SCOPE)
else()
message(STATUS "${package} found at '${PYTHON_${_upper_package}_PATH}'")
endif()
-
- unset(_PY_VER_SPLIT)
- unset(_PY_VER_MAJOR)
endif()
+endfunction()
- unset(_upper_package)
-endmacro()
+# like Python's 'print(dir())'
+function(print_all_vars)
+ get_cmake_property(_vars VARIABLES)
+ foreach(_var ${_vars})
+ message("${_var}=${${_var}}")
+ endforeach()
+endfunction()
diff --git a/build_files/cmake/packaging.cmake b/build_files/cmake/packaging.cmake
index 735d3fd819e..f1939cfd474 100644
--- a/build_files/cmake/packaging.cmake
+++ b/build_files/cmake/packaging.cmake
@@ -2,7 +2,6 @@ set(PROJECT_DESCRIPTION "Blender is a very fast and versatile 3D modeller/rende
set(PROJECT_COPYRIGHT "Copyright (C) 2001-2012 Blender Foundation")
set(PROJECT_CONTACT "foundation@blender.org")
set(PROJECT_VENDOR "Blender Foundation")
-set(ORG_WEBSITE "www.blender.org")
set(MAJOR_VERSION ${BLENDER_VERSION_MAJOR})
set(MINOR_VERSION ${BLENDER_VERSION_MINOR})
@@ -22,16 +21,18 @@ 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.
set(MY_WC_HASH "unknown")
if(EXISTS ${CMAKE_SOURCE_DIR}/.git/)
- include(FindGit)
+ find_package(Git)
if(GIT_FOUND)
message(STATUS "-- Found Git: ${GIT_EXECUTABLE}")
- execute_process(COMMAND git rev-parse --short @{u}
+ execute_process(COMMAND git rev-parse --short HEAD
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
OUTPUT_VARIABLE MY_WC_HASH
- OUTPUT_STRIP_TRAILING_WHITESPACE)
+ OUTPUT_STRIP_TRAILING_WHITESPACE
+ ERROR_QUIET)
endif()
endif()
set(BUILD_REV ${MY_WC_HASH})
+unset(MY_WC_HASH)
# Force Package Name
@@ -41,7 +42,7 @@ set(CPACK_PACKAGE_FILE_NAME ${PROJECT_NAME}-${MAJOR_VERSION}.${MINOR_VERSION}.${
if(CMAKE_SYSTEM_NAME MATCHES "Linux")
# RPM packages
include(build_files/cmake/RpmBuild.cmake)
- if(RPMBUILD_FOUND AND NOT WIN32)
+ if(RPMBUILD_FOUND)
set(CPACK_GENERATOR "RPM")
set(CPACK_RPM_PACKAGE_RELEASE "git${CPACK_DATE}.${BUILD_REV}")
set(CPACK_SET_DESTDIR "true")
@@ -61,7 +62,25 @@ if(APPLE)
set(CPACK_COMPONENT_LIBRARIES_HIDDEN TRUE)
endif()
-set(CPACK_PACKAGE_EXECUTABLES "blender")
+if(WIN32)
+ set(CPACK_PACKAGE_INSTALL_DIRECTORY "Blender Foundation/Blender")
+ set(CPACK_PACKAGE_INSTALL_REGISTRY_KEY "Blender Foundation/Blender")
+
+ set(CPACK_NSIS_MUI_ICON ${CMAKE_SOURCE_DIR}/source/icons/winblender.ico)
+ set(CPACK_NSIS_COMPRESSOR "/SOLID lzma")
+
+ set(CPACK_RESOURCE_FILE_LICENSE ${CMAKE_SOURCE_DIR}/release/text/GPL-license.txt)
+ set(CPACK_WIX_PRODUCT_ICON ${CMAKE_SOURCE_DIR}/source/icons/winblender.ico)
+ set(CPACK_WIX_UPGRADE_GUID "B767E4FD-7DE7-4094-B051-3AE62E13A17A")
+
+ set(CPACK_WIX_UI_BANNER ${LIBDIR}/package/installer_wix/WIX_UI_BANNER.bmp)
+ set(CPACK_WIX_UI_DIALOG ${LIBDIR}/package/installer_wix/WIX_UI_DIALOG.bmp)
+
+ #force lzma instead of deflate
+ set(CPACK_WIX_LIGHT_EXTRA_FLAGS -dcl:high)
+endif()
+
+set(CPACK_PACKAGE_EXECUTABLES "blender" "blender")
include(CPack)
# Target for build_archive.py script, to automatically pass along
@@ -76,6 +95,8 @@ macro(add_package_archive packagename extension)
OUTPUT ${package_output}
COMMAND ${build_archive} ${packagename} ${extension} bin release
WORKING_DIRECTORY ${CMAKE_BINARY_DIR})
+ unset(build_archive)
+ unset(package_output)
endmacro()
if(APPLE)
@@ -91,3 +112,9 @@ elseif(UNIX)
"tar.bz2")
endif()
+unset(MAJOR_VERSION)
+unset(MINOR_VERSION)
+unset(PATCH_VERSION)
+
+unset(BUILD_REV)
+
diff --git a/build_files/cmake/project_info.py b/build_files/cmake/project_info.py
index fcd4501f231..c9ea2497987 100755
--- a/build_files/cmake/project_info.py
+++ b/build_files/cmake/project_info.py
@@ -130,7 +130,7 @@ def is_project_file(filename):
def cmake_advanced_info():
- """ Extracr includes and defines from cmake.
+ """ Extract includes and defines from cmake.
"""
make_exe = cmake_cache_var("CMAKE_MAKE_PROGRAM")
diff --git a/build_files/cmake/project_source_info.py b/build_files/cmake/project_source_info.py
index b28c8208d44..45d732c2422 100644
--- a/build_files/cmake/project_source_info.py
+++ b/build_files/cmake/project_source_info.py
@@ -59,14 +59,21 @@ def is_c_any(filename):
CMAKE_DIR = "."
-def cmake_cache_var(var):
- cache_file = open(join(CMAKE_DIR, "CMakeCache.txt"))
- lines = [l_strip for l in cache_file for l_strip in (l.strip(),) if l_strip if not l_strip.startswith("//") if not l_strip.startswith("#")]
- cache_file.close()
+def cmake_cache_var_iter():
+ import re
+ re_cache = re.compile(r'([A-Za-z0-9_\-]+)?:?([A-Za-z0-9_\-]+)?=(.*)$')
+ with open(join(CMAKE_DIR, "CMakeCache.txt"), 'r', encoding='utf-8') as cache_file:
+ for l in cache_file:
+ match = re_cache.match(l.strip())
+ if match is not None:
+ var, type_, val = match.groups()
+ yield (var, type_ or "", val)
+
- for l in lines:
- if l.split(":")[0] == var:
- return l.split("=", 1)[-1]
+def cmake_cache_var(var):
+ for var_iter, type_iter, value_iter in cmake_cache_var_iter():
+ if var == var_iter:
+ return value_iter
return None
diff --git a/build_files/package_spec/build_archive.py b/build_files/package_spec/build_archive.py
index 0329d16b1ec..6a7ec8a0faa 100755
--- a/build_files/package_spec/build_archive.py
+++ b/build_files/package_spec/build_archive.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python
# <pep8 compliant>
diff --git a/build_files/package_spec/pacman/PKGBUILD b/build_files/package_spec/pacman/PKGBUILD
index e59d1cf31d7..961e35578b9 100644
--- a/build_files/package_spec/pacman/PKGBUILD
+++ b/build_files/package_spec/pacman/PKGBUILD
@@ -12,12 +12,12 @@ blender_version_char=$(sed -ne 's/.*BLENDER_VERSION_CHAR.*\([a-z]\)$/\1/p' $blen
# map the version a -> 1
# not to be confused with blender's internal subversions
if [ "$blender_version_char" ]; then
- blender_version_full=${blender_version}.$(expr index abcdefghijklmnopqrstuvwxyz $blender_version_char)
+ blender_version_full=${blender_version}.$(expr index abcdefghijklmnopqrstuvwxyz $blender_version_char)
else
- blender_version_full=${blender_version}
+ blender_version_full=${blender_version}
fi
-blender_ver_string=$blender_version+svn$blender_version_full
+blender_ver_string=$blender_version+git$blender_version_full
pkgname=blender-snapshot
pkgver=$blender_ver_string
@@ -27,8 +27,8 @@ arch=('i686' 'x86_64')
url="www.blender.org"
license=('GPL')
groups=()
-depends=('libjpeg' 'libpng' 'openjpeg' 'libtiff' 'openexr' 'python>=3.2' 'gettext' 'libxi' 'libxmu' 'mesa' 'freetype2' 'openal' 'sdl' 'libsndfile' 'ffmpeg')
-makedepends=('cmake' 'svn')
+depends=('libjpeg' 'libpng' 'openjpeg' 'libtiff' 'openexr' 'python>=3.4' 'gettext' 'libxi' 'libxmu' 'mesa' 'freetype2' 'openal' 'sdl' 'libsndfile' 'ffmpeg')
+makedepends=('cmake' 'git')
optdepends=()
provides=()
conflicts=('blender')
@@ -36,7 +36,7 @@ replaces=('blender')
backup=()
options=()
install=blender.install
-# use current svn to make the package.
+# use current git to make the package.
# source=(http://download.blender.org/source/$pkgname-$pkgver.tar.gz)
# md5sums=('27edb80c82c25252d43d6a01980d953a') #generate with 'makepkg -g'
source=()
@@ -51,11 +51,7 @@ build() {
-DCMAKE_BUILD_TYPE:STRING=Release \
-DWITH_INSTALL_PORTABLE:BOOL=OFF \
-DWITH_PYTHON_INSTALL:BOOL=OFF \
- -DWITH_OPENCOLLADA:BOOL=OFF \
- -DPYTHON_VERSION:STRING=3.2 \
- -DPYTHON_LIBPATH:STRING=/usr/lib \
- -DPYTHON_LIBRARY:STRING=python3.2mu \
- -DPYTHON_INCLUDE_DIRS:STRING=/usr/include/python3.2mu
+ -DWITH_OPENCOLLADA:BOOL=OFF
make $MAKEFLAGS
}
@@ -64,7 +60,7 @@ package() {
cd $srcdir/build
make DESTDIR="$pkgdir" install
python -m compileall \
- $pkgdir/usr/share/blender/$blender_version/scripts/startup \
- $pkgdir/usr/share/blender/$blender_version/scripts/modules \
- $pkgdir/usr/share/blender/$blender_version/scripts/addons
+ $pkgdir/usr/share/blender/$blender_version/scripts/startup \
+ $pkgdir/usr/share/blender/$blender_version/scripts/modules \
+ $pkgdir/usr/share/blender/$blender_version/scripts/addons
}
diff --git a/build_files/scons/config/darwin-config.py b/build_files/scons/config/darwin-config.py
index 338065e5e88..0bf03a46bd2 100644
--- a/build_files/scons/config/darwin-config.py
+++ b/build_files/scons/config/darwin-config.py
@@ -52,6 +52,8 @@ BF_CXX = '/usr'
WITH_BF_STATICCXX = False
BF_CXX_LIB_STATIC = '${BF_CXX}/lib/libstdc++.a'
+WITH_BF_AUDASPACE = True
+
# we use simply jack framework
WITH_BF_JACK = True
BF_JACK = '/Library/Frameworks/Jackmp.framework'
@@ -68,7 +70,7 @@ BF_SNDFILE_LIBPATH = '${BF_SNDFILE}/lib ${BF_FFMPEG}/lib' #ogg libs are stored i
WITH_BF_SDL = True
BF_SDL = LIBDIR + '/sdl' #$(shell sdl-config --prefix)
BF_SDL_INC = '${BF_SDL}/include' #$(shell $(BF_SDL)/bin/sdl-config --cflags)
-BF_SDL_LIB = 'SDL' #BF_SDL #$(shell $(BF_SDL)/bin/sdl-config --libs) -lSDL_mixer
+BF_SDL_LIB = 'SDL2' #BF_SDL #$(shell $(BF_SDL)/bin/sdl-config --libs) -lSDL_mixer
BF_SDL_LIBPATH = '${BF_SDL}/lib'
WITH_BF_OPENEXR = True
@@ -205,7 +207,7 @@ BF_BOOST_LIBPATH = '${BF_BOOST}/lib'
WITH_BF_CYCLES_CUDA_BINARIES = False
BF_CYCLES_CUDA_NVCC = '/usr/local/cuda/bin/nvcc'
-BF_CYCLES_CUDA_BINARIES_ARCH = ['sm_20', 'sm_21', 'sm_30', 'sm_35', 'sm_50']
+BF_CYCLES_CUDA_BINARIES_ARCH = ['sm_20', 'sm_21', 'sm_30', 'sm_35', 'sm_50', 'sm_52']
#Freestyle
WITH_BF_FREESTYLE = True
@@ -213,6 +215,12 @@ WITH_BF_FREESTYLE = True
#OpenMP ( will be checked for compiler support and turned off eventually )
WITH_BF_OPENMP = True
+WITH_BF_OPENSUBDIV = False
+BF_OPENSUBDIV = LIBDIR + '/opensubdiv'
+BF_OPENSUBDIV_INC = '${BF_OPENSUBDIV}/include'
+BF_OPENSUBDIV_LIB = 'osdCPU osdGPU'
+BF_OPENSUBDIV_LIBPATH = '${BF_OPENSUBDIV}/lib'
+
#Ray trace optimization
WITH_BF_RAYOPTIMIZATION = True
BF_RAYOPTIMIZATION_SSE_FLAGS = []
diff --git a/build_files/scons/config/linux-config.py b/build_files/scons/config/linux-config.py
index 05f09c2f2da..ff8ecf0aa72 100644
--- a/build_files/scons/config/linux-config.py
+++ b/build_files/scons/config/linux-config.py
@@ -26,6 +26,8 @@ BF_CXX = '/usr'
WITH_BF_STATICCXX = False
BF_CXX_LIB_STATIC = '${BF_CXX}/lib/libstdc++.a'
+WITH_BF_AUDASPACE = True
+
WITH_BF_JACK = False
BF_JACK = '/usr'
BF_JACK_INC = '${BF_JACK}/include/jack'
@@ -144,7 +146,7 @@ BF_REDCODE_LIB = ''
BF_REDCODE_INC = '${BF_REDCODE}/../' #C files request "libredcode/format.h" which is in "#extern/libredcode/format.h", stupid but compiles for now.
BF_REDCODE_LIBPATH='${BF_REDCODE}/lib'
-# Mesa Libs should go here if your using them as well....
+# Mesa Libs should go here if you're using them as well....
WITH_BF_STATICOPENGL = False
BF_OPENGL = '/usr'
BF_OPENGL_INC = '${BF_OPENGL}/include'
@@ -197,7 +199,7 @@ BF_BOOST = '/usr'
BF_BOOST_INC = '${BF_BOOST}/include'
BF_BOOST_LIB = 'boost_filesystem boost_regex boost_system boost_thread boost_date_time'
BF_BOOST_LIB_STATIC = '${BF_BOOST_LIBPATH}/libboost_filesystem.a ${BF_BOOST_LIBPATH}/libboost_date_time.a ' + \
- '${BF_BOOST_LIBPATH}/libboost_regex.a ${BF_BOOST_LIBPATH}/libboost_locale.a ${BF_BOOST_LIBPATH}/libboost_system.a' + \
+ '${BF_BOOST_LIBPATH}/libboost_regex.a ${BF_BOOST_LIBPATH}/libboost_locale.a ${BF_BOOST_LIBPATH}/libboost_system.a ' + \
'${BF_BOOST_LIBPATH}/libboost_thread.a'
BF_BOOST_LIB_INTERNATIONAL = 'boost_locale'
BF_BOOST_LIBPATH = '${BF_BOOST}/lib'
@@ -206,7 +208,7 @@ WITH_BF_CYCLES = WITH_BF_OIIO and WITH_BF_BOOST
WITH_BF_CYCLES_CUDA_BINARIES = False
BF_CYCLES_CUDA_NVCC = '/usr/local/cuda/bin/nvcc'
-BF_CYCLES_CUDA_BINARIES_ARCH = ['sm_20', 'sm_21', 'sm_30', 'sm_35', 'sm_50']
+BF_CYCLES_CUDA_BINARIES_ARCH = ['sm_20', 'sm_21', 'sm_30', 'sm_35', 'sm_50', 'sm_52']
WITH_BF_OPENMP = True
@@ -226,11 +228,20 @@ BF_3DMOUSE_LIB_STATIC = '${BF_3DMOUSE_LIBPATH}/libspnav.a'
#Freestyle
WITH_BF_FREESTYLE = True
+WITH_BF_OPENSUBDIV = False
+WITH_BF_STATICOPENSUBDIV = False
+BF_OPENSUBDIV = '/usr'
+BF_OPENSUBDIV_INC = '${BF_OPENSUBDIV}/include'
+BF_OPENSUBDIV_LIB = 'osdCPU osdGPU'
+BF_OPENSUBDIV_LIB_STATIC = '${BF_OPENSUBDIV_LIBPATH}/libosdGPU.a ${BF_OPENSUBDIV_LIBPATH}/libosdCPU.a'
+BF_OPENSUBDIV_LIBPATH = '${BF_OPENSUBDIV}/lib'
+
##
CC = 'gcc'
CXX = 'g++'
-CCFLAGS = ['-pipe','-fPIC','-funsigned-char','-fno-strict-aliasing','-D_LARGEFILE_SOURCE', '-D_FILE_OFFSET_BITS=64','-D_LARGEFILE64_SOURCE']
+CCFLAGS = ['-pipe','-fPIC','-funsigned-char','-fno-strict-aliasing', '-D_LARGEFILE_SOURCE', '-D_FILE_OFFSET_BITS=64','-D_LARGEFILE64_SOURCE']
+CFLAGS = ['-std=gnu89']
CXXFLAGS = []
CPPFLAGS = []
@@ -262,6 +273,6 @@ BF_INSTALLDIR='../install/linux'
#Link against pthread
PLATFORM_LINKFLAGS = ['-pthread']
-#Fix for LLVM conflict with Mesa llvmpipe
-if WITH_BF_LLVM:
- PLATFORM_LINKFLAGS += ['-Wl,--version-script=source/creator/blender.map']
+#Fix for LLVM conflict with Mesa llvmpipe, SDL dynload also requires symbols to be hidden.
+# TODO(sergey): Move this to SConstruct, so we can have this line depended on user config.
+PLATFORM_LINKFLAGS += ['-Wl,--version-script=source/creator/blender.map']
diff --git a/build_files/scons/config/win32-mingw-config.py b/build_files/scons/config/win32-mingw-config.py
index 85aa72af19c..552a1a5cec3 100644
--- a/build_files/scons/config/win32-mingw-config.py
+++ b/build_files/scons/config/win32-mingw-config.py
@@ -23,6 +23,8 @@ BF_FFMPEG_LIBPATH = LIBDIR + '/ffmpeg/lib'
BF_FFMPEG_INC = LIBDIR + '/ffmpeg/include'
BF_FFMPEG_DLL = '${BF_FFMPEG_LIBPATH}/avformat-55.dll ${BF_FFMPEG_LIBPATH}/avcodec-55.dll ${BF_FFMPEG_LIBPATH}/avdevice-55.dll ${BF_FFMPEG_LIBPATH}/avutil-52.dll ${BF_FFMPEG_LIBPATH}/swscale-2.dll'
+WITH_BF_AUDASPACE = True
+
WITH_BF_JACK = False
BF_JACK = LIBDIR + '/jack'
BF_JACK_INC = '${BF_JACK}/include'
@@ -145,7 +147,7 @@ BF_OPENCOLLADA_LIBPATH = '${BF_OPENCOLLADA}/lib/opencollada'
WITH_BF_CYCLES = True
WITH_BF_CYCLES_CUDA_BINARIES = False
BF_CYCLES_CUDA_NVCC = "" # Path to the NVIDIA CUDA compiler
-BF_CYCLES_CUDA_BINARIES_ARCH = ['sm_20', 'sm_21', 'sm_30', 'sm_35', 'sm_50']
+BF_CYCLES_CUDA_BINARIES_ARCH = ['sm_20', 'sm_21', 'sm_30', 'sm_35', 'sm_50', 'sm_52']
WITH_BF_OIIO = True
BF_OIIO = LIBDIR + '/openimageio'
@@ -166,10 +168,18 @@ BF_BOOST_LIB = 'boost_date_time-mgw46-mt-s-1_49 boost_filesystem-mgw46-mt-s-1_49
BF_BOOST_LIB_INTERNATIONAL = 'boost_locale-mgw46-mt-s-1_49'
BF_BOOST_LIBPATH = '${BF_BOOST}/lib'
+WITH_BF_OPENSUBDIV = False
+BF_OPENSUBDIV = LIBDIR + '/opensubdiv'
+BF_OPENSUBDIV_INC = '${BF_OPENSUBDIV}/include'
+BF_OPENSUBDIV_LIB = 'osdCPU osdGPU'
+BF_OPENSUBDIV_LIBPATH = '${BF_OPENSUBDIV}/lib'
+
#Ray trace optimization
WITH_BF_RAYOPTIMIZATION = True
BF_RAYOPTIMIZATION_SSE_FLAGS = ['-msse']
+WITH_BF_IME = True
+
WITH_BF_OPENMP = True
#CUDA
@@ -196,7 +206,10 @@ C_WARN = ['-Wno-char-subscripts', '-Wdeclaration-after-statement', '-Wstrict-pro
CC_WARN = [ '-Wall' ]
-LLIBS = ['-lshell32', '-lshfolder', '-lgdi32', '-lmsvcrt', '-lwinmm', '-lmingw32', '-lm', '-lws2_32', '-lz', '-lstdc++','-lole32','-luuid', '-lwsock32', '-lpsapi']
+LLIBS = ['-lshell32', '-lshfolder', '-lgdi32', '-lmsvcrt', '-lwinmm', '-lmingw32', '-lm', '-lws2_32', '-lz', '-lstdc++','-lole32','-luuid', '-lwsock32', '-lpsapi', '-ldbghelp']
+
+if WITH_BF_IME:
+ LLIBS.append('-limm32')
PLATFORM_LINKFLAGS = ['-Xlinker', '--stack=2097152']
diff --git a/build_files/scons/config/win32-vc-config.py b/build_files/scons/config/win32-vc-config.py
index 6dd853b7da4..9bd23a46d66 100644
--- a/build_files/scons/config/win32-vc-config.py
+++ b/build_files/scons/config/win32-vc-config.py
@@ -33,7 +33,7 @@ WITH_BF_PYTHON_INSTALL_NUMPY = True
WITH_BF_OPENAL = True
BF_OPENAL = LIBDIR + '/openal'
BF_OPENAL_INC = '${BF_OPENAL}/include '
-BF_OPENAL_LIB = 'wrap_oal'
+BF_OPENAL_LIB = 'OpenAL32'
BF_OPENAL_LIBPATH = '${BF_OPENAL}/lib'
WITH_BF_ICONV = True
@@ -42,6 +42,8 @@ BF_ICONV_INC = '${BF_ICONV}/include'
BF_ICONV_LIB = 'iconv'
BF_ICONV_LIBPATH = '${BF_ICONV}/lib'
+WITH_BF_AUDASPACE = True
+
WITH_BF_JACK = False
BF_JACK = LIBDIR + '/jack'
BF_JACK_INC = '${BF_JACK}/include ${BF_FFMPEG}/include/msvc'
@@ -57,7 +59,7 @@ BF_SNDFILE_LIBPATH = '${BF_SNDFILE}/lib'
WITH_BF_SDL = True
BF_SDL = LIBDIR + '/sdl'
BF_SDL_INC = '${BF_SDL}/include'
-BF_SDL_LIB = 'SDL.lib'
+BF_SDL_LIB = 'SDL2.lib'
BF_SDL_LIBPATH = '${BF_SDL}/lib'
BF_PTHREADS = LIBDIR + '/pthreads'
@@ -69,7 +71,7 @@ WITH_BF_OPENEXR = True
WITH_BF_STATICOPENEXR = False
BF_OPENEXR = LIBDIR + '/openexr'
BF_OPENEXR_INC = '${BF_OPENEXR}/include ${BF_OPENEXR}/include/OpenEXR '
-BF_OPENEXR_LIB = ' Iex-2_1 Half IlmImf-2_1 Imath-2_1 IlmThread-2_1 '
+BF_OPENEXR_LIB = ' Iex-2_2 Half IlmImf-2_2 Imath-2_2 IlmThread-2_2 '
BF_OPENEXR_LIBPATH = '${BF_OPENEXR}/lib'
BF_OPENEXR_LIB_STATIC = '${BF_OPENEXR}/lib/libHalf.a ${BF_OPENEXR}/lib/libIlmImf.a ${BF_OPENEXR}/lib/libIex.a ${BF_OPENEXR}/lib/libImath.a ${BF_OPENEXR}/lib/libIlmThread.a'
@@ -151,6 +153,8 @@ BF_OPENCOLLADA_INC = '${BF_OPENCOLLADA}/include/opencollada'
BF_OPENCOLLADA_LIB = 'OpenCOLLADAStreamWriter OpenCOLLADASaxFrameworkLoader OpenCOLLADAFramework OpenCOLLADABaseUtils GeneratedSaxParser MathMLSolver xml pcre buffer ftoa'
BF_OPENCOLLADA_LIBPATH = '${BF_OPENCOLLADA}/lib/opencollada'
+WITH_BF_IME = True
+
WITH_BF_3DMOUSE = True
WITH_BF_OPENMP = True
@@ -197,7 +201,7 @@ BF_BOOST_LIBPATH = '${BF_BOOST}/lib'
#CUDA
WITH_BF_CYCLES_CUDA_BINARIES = False
#BF_CYCLES_CUDA_NVCC = "" # Path to the nvidia compiler
-BF_CYCLES_CUDA_BINARIES_ARCH = ['sm_20', 'sm_21', 'sm_30', 'sm_35', 'sm_50']
+BF_CYCLES_CUDA_BINARIES_ARCH = ['sm_20', 'sm_21', 'sm_30', 'sm_35', 'sm_50', 'sm_52']
#Ray trace optimization
WITH_BF_RAYOPTIMIZATION = True
@@ -206,6 +210,12 @@ BF_RAYOPTIMIZATION_SSE_FLAGS = ['/arch:SSE']
#Freestyle
WITH_BF_FREESTYLE = True
+WITH_BF_OPENSUBDIV = True
+BF_OPENSUBDIV = LIBDIR + '/opensubdiv'
+BF_OPENSUBDIV_INC = '${BF_OPENSUBDIV}/include'
+BF_OPENSUBDIV_LIB = 'osdCPU osdGPU'
+BF_OPENSUBDIV_LIBPATH = '${BF_OPENSUBDIV}/lib'
+
WITH_BF_STATICOPENGL = False
BF_OPENGL_INC = '${BF_OPENGL}/include'
BF_OPENGL_LIBINC = '${BF_OPENGL}/lib'
@@ -235,7 +245,10 @@ C_WARN = []
CC_WARN = []
CXX_WARN = []
-LLIBS = ['ws2_32', 'vfw32', 'winmm', 'kernel32', 'user32', 'gdi32', 'comdlg32', 'advapi32', 'shfolder', 'shell32', 'ole32', 'oleaut32', 'uuid', 'psapi']
+LLIBS = ['ws2_32', 'vfw32', 'winmm', 'kernel32', 'user32', 'gdi32', 'comdlg32', 'advapi32', 'shfolder', 'shell32', 'ole32', 'oleaut32', 'uuid', 'psapi', 'Dbghelp']
+
+if WITH_BF_IME:
+ LLIBS.append('imm32')
PLATFORM_LINKFLAGS = ['/SUBSYSTEM:CONSOLE','/MACHINE:IX86','/STACK:2097152','/INCREMENTAL:NO', '/LARGEADDRESSAWARE', '/NODEFAULTLIB:msvcrt.lib', '/NODEFAULTLIB:msvcmrt.lib', '/NODEFAULTLIB:msvcurt.lib', '/NODEFAULTLIB:msvcrtd.lib']
diff --git a/build_files/scons/config/win64-mingw-config.py b/build_files/scons/config/win64-mingw-config.py
index 92dcd6db455..87a9b5e4eac 100644
--- a/build_files/scons/config/win64-mingw-config.py
+++ b/build_files/scons/config/win64-mingw-config.py
@@ -22,6 +22,8 @@ BF_FFMPEG_LIBPATH = LIBDIR + '/ffmpeg/lib'
BF_FFMPEG_INC = LIBDIR + '/ffmpeg/include'
BF_FFMPEG_DLL = '${BF_FFMPEG_LIBPATH}/avformat-53.dll ${BF_FFMPEG_LIBPATH}/avcodec-53.dll ${BF_FFMPEG_LIBPATH}/avdevice-53.dll ${BF_FFMPEG_LIBPATH}/avutil-51.dll ${BF_FFMPEG_LIBPATH}/swscale-2.dll ${BF_FFMPEG_LIBPATH}/swresample-0.dll ${BF_FFMPEG_LIBPATH}/xvidcore.dll'
+WITH_BF_AUDASPACE = True
+
WITH_BF_JACK = False
BF_JACK = LIBDIR + '/jack'
BF_JACK_INC = '${BF_JACK}/include'
@@ -144,7 +146,7 @@ BF_OPENCOLLADA_LIBPATH = '${BF_OPENCOLLADA}/lib/opencollada'
WITH_BF_CYCLES = True
WITH_BF_CYCLES_CUDA_BINARIES = False
BF_CYCLES_CUDA_NVCC = "" # Path to the NVIDIA CUDA compiler
-BF_CYCLES_CUDA_BINARIES_ARCH = ['sm_20', 'sm_21', 'sm_30', 'sm_35', 'sm_50']
+BF_CYCLES_CUDA_BINARIES_ARCH = ['sm_20', 'sm_21', 'sm_30', 'sm_35', 'sm_50', 'sm_52']
WITH_BF_OIIO = True
BF_OIIO = LIBDIR + '/openimageio'
@@ -165,10 +167,18 @@ BF_BOOST_LIB = 'boost_date_time-mgw47-mt-s-1_49 boost_date_time-mgw47-mt-sd-1_49
BF_BOOST_LIB_INTERNATIONAL = ' boost_locale-mgw47-mt-s-1_49 boost_locale-mgw47-mt-sd-1_49'
BF_BOOST_LIBPATH = '${BF_BOOST}/lib'
+WITH_BF_OPENSUBDIV = False
+BF_OPENSUBDIV = LIBDIR + '/opensubdiv'
+BF_OPENSUBDIV_INC = '${BF_OPENSUBDIV}/include'
+BF_OPENSUBDIV_LIB = 'osdCPU osdGPU'
+BF_OPENSUBDIV_LIBPATH = '${BF_OPENSUBDIV}/lib'
+
#Ray trace optimization
WITH_BF_RAYOPTIMIZATION = True
BF_RAYOPTIMIZATION_SSE_FLAGS = ['-mmmx', '-msse', '-msse2']
+WITH_BF_IME = True
+
WITH_BF_OPENMP = True
#Freestyle
@@ -186,11 +196,15 @@ REL_CFLAGS = []
REL_CXXFLAGS = []
REL_CCFLAGS = ['-O2', '-ftree-vectorize']
+# NOTE: C_WARN seems to get ignored - at least -Wno-char-subscripts doesn't work!
C_WARN = ['-Wno-char-subscripts', '-Wdeclaration-after-statement', '-Wstrict-prototypes']
-CC_WARN = [ '-Wall' ]
+CC_WARN = [ '-Wall', '-Wno-char-subscripts' ]
+
+LLIBS = ['-lshell32', '-lshfolder', '-lgdi32', '-lmsvcrt', '-lwinmm', '-lmingw32', '-lm', '-lws2_32', '-lz', '-lstdc++','-lole32','-luuid', '-lwsock32', '-lpsapi', '-lpthread', '-ldbghelp']
-LLIBS = ['-lshell32', '-lshfolder', '-lgdi32', '-lmsvcrt', '-lwinmm', '-lmingw32', '-lm', '-lws2_32', '-lz', '-lstdc++','-lole32','-luuid', '-lwsock32', '-lpsapi', '-lpthread']
+if WITH_BF_IME:
+ LLIBS.append('-limm32')
PLATFORM_LINKFLAGS = ['-Xlinker', '--stack=2097152']
diff --git a/build_files/scons/config/win64-vc-config.py b/build_files/scons/config/win64-vc-config.py
index f928f166ba7..adacc2946c5 100644
--- a/build_files/scons/config/win64-vc-config.py
+++ b/build_files/scons/config/win64-vc-config.py
@@ -34,7 +34,7 @@ WITH_BF_PYTHON_INSTALL_NUMPY = True
WITH_BF_OPENAL = True
BF_OPENAL = LIBDIR + '/openal'
BF_OPENAL_INC = '${BF_OPENAL}/include '
-BF_OPENAL_LIB = 'wrap_oal'
+BF_OPENAL_LIB = 'OpenAL32'
BF_OPENAL_LIBPATH = '${BF_OPENAL}/lib'
WITH_BF_SNDFILE = True
@@ -52,9 +52,11 @@ BF_ICONV_LIBPATH = '${BF_ICONV}/lib'
WITH_BF_SDL = True
BF_SDL = LIBDIR + '/sdl'
BF_SDL_INC = '${BF_SDL}/include'
-BF_SDL_LIB = 'SDL.lib'
+BF_SDL_LIB = 'SDL2.lib'
BF_SDL_LIBPATH = '${BF_SDL}/lib'
+WITH_BF_AUDASPACE = True
+
WITH_BF_JACK = False
BF_PTHREADS = LIBDIR + '/pthreads'
@@ -66,7 +68,7 @@ WITH_BF_OPENEXR = True
WITH_BF_STATICOPENEXR = False
BF_OPENEXR = LIBDIR + '/openexr'
BF_OPENEXR_INC = '${BF_OPENEXR}/include ${BF_OPENEXR}/include/OpenEXR '
-BF_OPENEXR_LIB = ' Iex-2_1 Half IlmImf-2_1 Imath-2_1 IlmThread-2_1 '
+BF_OPENEXR_LIB = ' Iex-2_2 Half IlmImf-2_2 Imath-2_2 IlmThread-2_2 '
BF_OPENEXR_LIBPATH = '${BF_OPENEXR}/lib'
BF_OPENEXR_LIB_STATIC = '${BF_OPENEXR}/lib/libHalf.a ${BF_OPENEXR}/lib/libIlmImf.a ${BF_OPENEXR}/lib/libIex.a ${BF_OPENEXR}/lib/libImath.a ${BF_OPENEXR}/lib/libIlmThread.a'
@@ -154,6 +156,8 @@ BF_OPENCOLLADA_INC = '${BF_OPENCOLLADA}/include/opencollada'
BF_OPENCOLLADA_LIB = 'OpenCOLLADAStreamWriter OpenCOLLADASaxFrameworkLoader OpenCOLLADAFramework OpenCOLLADABaseUtils GeneratedSaxParser MathMLSolver xml pcre buffer ftoa'
BF_OPENCOLLADA_LIBPATH = '${BF_OPENCOLLADA}/lib/opencollada'
+WITH_BF_IME = True
+
WITH_BF_3DMOUSE = True
WITH_BF_OPENMP = True
@@ -200,7 +204,7 @@ BF_BOOST_LIBPATH = '${BF_BOOST}/lib'
#CUDA
WITH_BF_CYCLES_CUDA_BINARIES = False
#BF_CYCLES_CUDA_NVCC = "" # Path to the nvidia compiler
-BF_CYCLES_CUDA_BINARIES_ARCH = ['sm_20', 'sm_21', 'sm_30', 'sm_35', 'sm_50']
+BF_CYCLES_CUDA_BINARIES_ARCH = ['sm_20', 'sm_21', 'sm_30', 'sm_35', 'sm_50', 'sm_52']
#Ray trace optimization
WITH_BF_RAYOPTIMIZATION = True
@@ -210,6 +214,12 @@ BF_RAYOPTIMIZATION_SSE_FLAGS = ['']
#Freestyle
WITH_BF_FREESTYLE = True
+WITH_BF_OPENSUBDIV = True
+BF_OPENSUBDIV = LIBDIR + '/opensubdiv'
+BF_OPENSUBDIV_INC = '${BF_OPENSUBDIV}/include'
+BF_OPENSUBDIV_LIB = 'osdCPU osdGPU'
+BF_OPENSUBDIV_LIBPATH = '${BF_OPENSUBDIV}/lib'
+
WITH_BF_STATICOPENGL = False
BF_OPENGL_INC = '${BF_OPENGL}/include'
BF_OPENGL_LIBINC = '${BF_OPENGL}/lib'
@@ -242,7 +252,10 @@ C_WARN = []
CC_WARN = []
CXX_WARN = []
-LLIBS = ['ws2_32', 'vfw32', 'winmm', 'kernel32', 'user32', 'gdi32', 'comdlg32', 'advapi32', 'shfolder', 'shell32', 'ole32', 'oleaut32', 'uuid', 'psapi']
+LLIBS = ['ws2_32', 'vfw32', 'winmm', 'kernel32', 'user32', 'gdi32', 'comdlg32', 'advapi32', 'shfolder', 'shell32', 'ole32', 'oleaut32', 'uuid', 'psapi', 'Dbghelp']
+
+if WITH_BF_IME:
+ LLIBS.append('imm32')
PLATFORM_LINKFLAGS = ['/SUBSYSTEM:CONSOLE','/MACHINE:X64','/STACK:2097152','/OPT:NOREF','/INCREMENTAL:NO', '/NODEFAULTLIB:msvcrt.lib', '/NODEFAULTLIB:msvcmrt.lib', '/NODEFAULTLIB:msvcurt.lib', '/NODEFAULTLIB:msvcrtd.lib']
diff --git a/build_files/scons/tools/Blender.py b/build_files/scons/tools/Blender.py
index b5853b22455..8419f9703e0 100755..100644
--- a/build_files/scons/tools/Blender.py
+++ b/build_files/scons/tools/Blender.py
@@ -143,7 +143,7 @@ def setup_staticlibs(lenv):
libincs += Split(lenv['BF_FREETYPE_LIBPATH'])
if lenv['WITH_BF_PYTHON']:
libincs += Split(lenv['BF_PYTHON_LIBPATH'])
- if lenv['WITH_BF_SDL']:
+ if lenv['WITH_BF_SDL'] and not lenv['WITH_BF_SDL_DYNLOAD']:
libincs += Split(lenv['BF_SDL_LIBPATH'])
if lenv['WITH_BF_JACK'] and not lenv['WITH_BF_JACK_DYNLOAD']:
libincs += Split(lenv['BF_JACK_LIBPATH'])
@@ -216,16 +216,16 @@ def setup_staticlibs(lenv):
if lenv['WITH_BF_STATICOCIO']:
statlibs += Split(lenv['BF_OCIO_LIB_STATIC'])
- if lenv['WITH_BF_BOOST']:
- libincs += Split(lenv['BF_BOOST_LIBPATH'])
- if lenv['WITH_BF_STATICBOOST']:
- statlibs += Split(lenv['BF_BOOST_LIB_STATIC'])
-
if lenv['WITH_BF_CYCLES_OSL']:
libincs += Split(lenv['BF_OSL_LIBPATH'])
if lenv['WITH_BF_STATICOSL']:
statlibs += Split(lenv['BF_OSL_LIB_STATIC'])
+ if lenv['WITH_BF_BOOST']:
+ libincs += Split(lenv['BF_BOOST_LIBPATH'])
+ if lenv['WITH_BF_STATICBOOST']:
+ statlibs += Split(lenv['BF_BOOST_LIB_STATIC'])
+
if lenv['WITH_BF_LLVM']:
libincs += Split(lenv['BF_LLVM_LIBPATH'])
if lenv['WITH_BF_STATICLLVM']:
@@ -242,6 +242,11 @@ def setup_staticlibs(lenv):
if lenv['WITH_BF_STATIC3DMOUSE']:
statlibs += Split(lenv['BF_3DMOUSE_LIB_STATIC'])
+ if lenv['WITH_BF_OPENSUBDIV']:
+ libincs += Split(lenv['BF_OPENSUBDIV_LIBPATH'])
+ if lenv['WITH_BF_STATICOPENSUBDIV']:
+ statlibs += Split(lenv['BF_OPENSUBDIV_LIB_STATIC'])
+
# setting this last so any overriding of manually libs could be handled
if lenv['OURPLATFORM'] not in ('win32-vc', 'win32-mingw', 'win64-vc', 'linuxcross', 'win64-mingw'):
# We must remove any previous items defining this path, for same reason stated above!
@@ -303,7 +308,7 @@ def setup_syslibs(lenv):
if lenv['WITH_BF_ELTOPO']:
syslibs += Split(lenv['BF_LAPACK_LIB'])
'''
- if lenv['WITH_BF_SDL']:
+ if lenv['WITH_BF_SDL'] and not lenv['WITH_BF_SDL_DYNLOAD']:
syslibs += Split(lenv['BF_SDL_LIB'])
if not lenv['WITH_BF_STATICOPENGL']:
syslibs += Split(lenv['BF_OPENGL_LIB'])
@@ -325,16 +330,16 @@ def setup_syslibs(lenv):
if lenv['WITH_BF_3DMOUSE']:
if not lenv['WITH_BF_STATIC3DMOUSE']:
syslibs += Split(lenv['BF_3DMOUSE_LIB'])
-
+
+ if lenv['WITH_BF_CYCLES_OSL'] and not lenv['WITH_BF_STATICOSL']:
+ syslibs += Split(lenv['BF_OSL_LIB'])
+
if lenv['WITH_BF_BOOST'] and not lenv['WITH_BF_STATICBOOST']:
syslibs += Split(lenv['BF_BOOST_LIB'])
-
+
if lenv['WITH_BF_INTERNATIONAL']:
syslibs += Split(lenv['BF_BOOST_LIB_INTERNATIONAL'])
- if lenv['WITH_BF_CYCLES_OSL'] and not lenv['WITH_BF_STATICOSL']:
- syslibs += Split(lenv['BF_OSL_LIB'])
-
if lenv['WITH_BF_LLVM'] and not lenv['WITH_BF_STATICLLVM']:
syslibs += Split(lenv['BF_LLVM_LIB'])
@@ -344,6 +349,13 @@ def setup_syslibs(lenv):
if not lenv['WITH_BF_STATICPNG']:
syslibs += Split(lenv['BF_PNG_LIB'])
+ if lenv['WITH_BF_OPENSUBDIV']:
+ if not lenv['WITH_BF_STATICOPENSUBDIV']:
+ if lenv['BF_DEBUG'] and lenv['OURPLATFORM'] in ('win32-vc', 'win64-vc', 'win32-mingw', 'win64-mingw'):
+ syslibs += [osdlib+'_d' for osdlib in Split(lenv['BF_OPENSUBDIV_LIB'])]
+ else:
+ syslibs += Split(lenv['BF_OPENSUBDIV_LIB'])
+
# Hack to pass OSD libraries to linker before extern_{clew,cuew}
for syslib in create_blender_liblist(lenv, 'system'):
syslibs.append(os.path.basename(syslib))
@@ -372,7 +384,7 @@ def propose_priorities():
def creator(env):
sources = ['creator.c']# + Blender.buildinfo(env, "dynamic") + Blender.resources
- incs = ['#/intern/guardedalloc', '#/source/blender/blenlib', '#/source/blender/blenkernel', '#/source/blender/editors/include', '#/source/blender/blenloader', '#/source/blender/imbuf', '#/source/blender/renderconverter', '#/source/blender/render/extern/include', '#/source/blender/windowmanager', '#/source/blender/makesdna', '#/source/blender/makesrna', '#/source/gameengine/BlenderRoutines', '#/extern/glew/include', '#/source/blender/gpu', env['BF_OPENGL_INC']]
+ incs = ['#/intern/guardedalloc', '#/source/blender/blenlib', '#/source/blender/blenkernel', '#/source/blender/depsgraph', '#/source/blender/editors/include', '#/source/blender/blenloader', '#/source/blender/imbuf', '#/source/blender/renderconverter', '#/source/blender/render/extern/include', '#/source/blender/windowmanager', '#/source/blender/makesdna', '#/source/blender/makesrna', '#/source/gameengine/BlenderRoutines', '#/extern/glew/include', '#/source/blender/gpu', env['BF_OPENGL_INC']]
defs = []
@@ -381,12 +393,19 @@ def creator(env):
defs.append('WITH_BINRELOC')
if env['WITH_BF_SDL']:
+ if env['WITH_BF_SDL_DYNLOAD']:
+ defs.append('WITH_SDL_DYNLOAD')
+ incs.append('#/extern/sdlew/include')
defs.append('WITH_SDL')
if env['WITH_BF_LIBMV']:
incs.append('#/extern/libmv')
defs.append('WITH_LIBMV')
+ if env['WITH_BF_CYCLES'] and env['WITH_BF_CYCLES_LOGGING']:
+ incs.append('#/intern/cycles/blender')
+ defs.append('WITH_CYCLES_LOGGING')
+
if env['WITH_BF_FFMPEG']:
defs.append('WITH_FFMPEG')
@@ -434,7 +453,7 @@ def buildinfo(lenv, build_type):
no_upstream = False
try :
- build_hash = btools.get_command_output(['git', 'rev-parse', '--short', '@{u}']).strip()
+ build_hash = btools.get_command_output(['git', 'rev-parse', '--short', '@{u}'], stderr=subprocess.STDOUT).strip()
except subprocess.CalledProcessError:
# assume branch has no upstream configured
build_hash = btools.get_command_output(['git', 'rev-parse', '--short', 'HEAD']).strip()
@@ -623,7 +642,7 @@ def WinPyBundle(target=None, source=None, env=None):
py_tar+= '/release/python' + env['BF_PYTHON_VERSION'].replace('.','') + '.tar.gz'
py_target = env.subst(env['BF_INSTALLDIR']).lstrip("#")
- py_target = os.path.join(py_target, VERSION, 'python', 'lib')
+ py_target = os.path.join(py_target, VERSION, 'python')
def printexception(func,path,ex):
if os.path.exists(path): #do not report if path does not exist. eg on a fresh build.
print str(func) + ' failed on ' + str(path)
@@ -647,7 +666,7 @@ def WinPyBundle(target=None, source=None, env=None):
# Extract Numpy
if env['WITH_BF_PYTHON_INSTALL_NUMPY']:
py_tar = env.subst(env['LCGDIR']).lstrip("#")
- py_tar += '/release/python' + env['BF_PYTHON_VERSION'].replace('.','') + '_numpy_1.8.tar.gz'
+ py_tar += '/release/python' + env['BF_PYTHON_VERSION'].replace('.','') + '_numpy_1.9.tar.gz'
py_target = env.subst(env['BF_INSTALLDIR']).lstrip("#")
py_target = os.path.join(py_target, VERSION, 'python', 'lib', 'site-packages')
@@ -663,6 +682,8 @@ def WinPyBundle(target=None, source=None, env=None):
py_dir += '/release/site-packages'
# grr, we have to do one by one because the dir exists
for f in os.listdir(py_dir):
+ if f == '.svn':
+ continue
fn_src = os.path.join(py_dir, f)
fn_dst = os.path.join(py_target, f)
@@ -755,7 +776,7 @@ def AppIt(target=None, source=None, env=None):
commands.getoutput(cmd)
cmd = 'cp -R %s/kernel/*.h %s/kernel/*.cl %s/kernel/*.cu %s/kernel/' % (croot, croot, croot, cinstalldir)
commands.getoutput(cmd)
- cmd = 'cp -R %s/kernel/svm %s/kernel/closure %s/kernel/geom %s/util/util_color.h %s/util/util_half.h %s/util/util_math.h %s/util/util_transform.h %s/util/util_types.h %s/kernel/' % (croot, croot, croot, croot, croot, croot, croot, croot, cinstalldir)
+ cmd = 'cp -R %s/kernel/svm %s/kernel/closure %s/kernel/geom %s/kernel/split %s/kernel/kernels %s/util/util_color.h %s/util/util_half.h %s/util/util_math.h %s/util/util_math_fast.h %s/util/util_transform.h %s/util/util_types.h %s/util/util_atomic.h %s/kernel/' % (croot, croot, croot, croot, croot, croot, croot, croot, croot, croot, croot, croot, cinstalldir)
commands.getoutput(cmd)
cmd = 'cp -R %s/../intern/cycles/kernel/*.cubin %s/lib/' % (builddir, cinstalldir)
commands.getoutput(cmd)
@@ -809,9 +830,7 @@ def AppIt(target=None, source=None, env=None):
instname = env['LCGDIR'][1:] # made libiomp5 part of blender libs
cmd = 'ditto --arch %s %s/openmp/lib/libiomp5.dylib %s/%s.app/Contents/Resources/lib/'%(osxarch, instname, installdir, binary) # copy libiomp5
commands.getoutput(cmd)
- cmd = 'install_name_tool -id @loader_path/../Resources/lib/libiomp5.dylib %s/%s.app/Contents/Resources/lib/libiomp5.dylib'%(installdir, binary) # change id of libiomp5
- commands.getoutput(cmd)
- cmd = 'install_name_tool -change @loader_path/libiomp5.dylib @loader_path/../Resources/lib/libiomp5.dylib %s/%s.app/Contents/MacOS/%s'%(installdir, binary, binary) # change ref to libiomp5 ( blender )
+ cmd = 'cp %s/openmp/LICENSE.txt %s/LICENSE-libiomp5.txt'%(instname, installdir) # copy libiomp5 license
commands.getoutput(cmd)
# extract copy system python, be sure to update other build systems
@@ -836,6 +855,7 @@ def UnixPyBundle(target=None, source=None, env=None):
py_src = env.subst( env['BF_PYTHON_LIBPATH'] + '/python'+env['BF_PYTHON_VERSION'] )
py_target = env.subst( dir + '/python/' + target_lib + '/python'+env['BF_PYTHON_VERSION'] )
+ py_target_bin = env.subst(dir + '/python/bin')
# This is a bit weak, but dont install if its been installed before, makes rebuilds quite slow.
if os.path.exists(py_target):
@@ -855,6 +875,11 @@ def UnixPyBundle(target=None, source=None, env=None):
except:
pass
+ # install the executable
+ run("rm -rf '%s'" % py_target_bin)
+ os.makedirs(py_target_bin)
+ run("cp '%s' '%s'" % (env.subst(env['BF_PYTHON_BINARY']), py_target_bin))
+
run("cp -R '%s' '%s'" % (py_src, os.path.dirname(py_target)))
run("rm -rf '%s/distutils'" % py_target)
run("rm -rf '%s/lib2to3'" % py_target)
diff --git a/build_files/scons/tools/btools.py b/build_files/scons/tools/btools.py
index 5a09e07b3b3..0b85940d024 100644
--- a/build_files/scons/tools/btools.py
+++ b/build_files/scons/tools/btools.py
@@ -107,8 +107,9 @@ def print_arguments(args, bc):
def validate_arguments(args, bc):
opts_list = [
'WITH_BF_FREESTYLE', 'WITH_BF_PYTHON', 'WITH_BF_PYTHON_SAFETY', 'WITH_BF_PYTHON_SECURITY', 'BF_PYTHON', 'BF_PYTHON_VERSION', 'BF_PYTHON_INC', 'BF_PYTHON_BINARY', 'BF_PYTHON_LIB', 'BF_PYTHON_LIBPATH', 'BF_PYTHON_LIBPATH_ARCH', 'WITH_BF_STATICPYTHON', 'WITH_OSX_STATICPYTHON', 'BF_PYTHON_LIB_STATIC', 'BF_PYTHON_DLL', 'BF_PYTHON_ABI_FLAGS',
+ 'WITH_BF_AUDASPACE', 'BF_AUDASPACE_C_INC', 'BF_AUDASPACE_PY_INC', 'BF_AUDASPACE_DEF',
'WITH_BF_OPENAL', 'BF_OPENAL', 'BF_OPENAL_INC', 'BF_OPENAL_LIB', 'BF_OPENAL_LIBPATH', 'WITH_BF_STATICOPENAL', 'BF_OPENAL_LIB_STATIC',
- 'WITH_BF_SDL', 'BF_SDL', 'BF_SDL_INC', 'BF_SDL_LIB', 'BF_SDL_LIBPATH',
+ 'WITH_BF_SDL', 'BF_SDL', 'BF_SDL_INC', 'BF_SDL_LIB', 'BF_SDL_LIBPATH', 'WITH_BF_SDL_DYNLOAD',
'WITH_BF_JACK', 'BF_JACK', 'BF_JACK_INC', 'BF_JACK_LIB', 'BF_JACK_LIBPATH', 'WITH_BF_JACK_DYNLOAD',
'WITH_BF_SNDFILE', 'BF_SNDFILE', 'BF_SNDFILE_INC', 'BF_SNDFILE_LIB', 'BF_SNDFILE_LIBPATH', 'WITH_BF_STATICSNDFILE', 'BF_SNDFILE_LIB_STATIC',
'BF_PTHREADS', 'BF_PTHREADS_INC', 'BF_PTHREADS_LIB', 'BF_PTHREADS_LIBPATH',
@@ -136,6 +137,9 @@ def validate_arguments(args, bc):
'WITH_BF_QUICKTIME', 'BF_QUICKTIME', 'BF_QUICKTIME_INC', 'BF_QUICKTIME_LIB', 'BF_QUICKTIME_LIBPATH',
'WITH_BF_FFTW3', 'BF_FFTW3', 'BF_FFTW3_INC', 'BF_FFTW3_LIB', 'BF_FFTW3_LIBPATH', 'WITH_BF_STATICFFTW3', 'BF_FFTW3_LIB_STATIC',
'WITH_BF_STATICOPENGL', 'BF_OPENGL', 'BF_OPENGL_INC', 'BF_OPENGL_LIB', 'BF_OPENGL_LIBPATH', 'BF_OPENGL_LIB_STATIC',
+ 'WITH_BF_EGL', 'WITH_BF_GLEW_ES', 'BF_GLEW_INC', 'WITH_BF_GL_PROFILE_CORE', 'WITH_BF_GL_PROFILE_COMPAT', 'WITH_BF_GL_PROFILE_ES20',
+ 'WITH_BF_GLEW_MX', 'WITH_BF_GL_EGL', 'WITH_BF_GL_ANGLE',
+
'WITH_BF_COLLADA', 'BF_COLLADA', 'BF_COLLADA_INC', 'BF_COLLADA_LIB', 'BF_OPENCOLLADA', 'BF_OPENCOLLADA_INC', 'BF_OPENCOLLADA_LIB', 'BF_OPENCOLLADA_LIBPATH', 'BF_PCRE', 'BF_PCRE_LIB', 'BF_PCRE_LIBPATH', 'BF_EXPAT', 'BF_EXPAT_LIB', 'BF_EXPAT_LIBPATH',
'WITH_BF_STATICOPENCOLLADA', 'BF_OPENCOLLADA_LIB_STATIC',
'WITH_BF_PLAYER',
@@ -171,20 +175,23 @@ def validate_arguments(args, bc):
'WITH_BF_CXX_GUARDEDALLOC',
'WITH_BF_JEMALLOC', 'WITH_BF_STATICJEMALLOC', 'BF_JEMALLOC', 'BF_JEMALLOC_INC', 'BF_JEMALLOC_LIBPATH', 'BF_JEMALLOC_LIB', 'BF_JEMALLOC_LIB_STATIC',
'BUILDBOT_BRANCH',
+ 'WITH_BF_IME',
'WITH_BF_3DMOUSE', 'WITH_BF_STATIC3DMOUSE', 'BF_3DMOUSE', 'BF_3DMOUSE_INC', 'BF_3DMOUSE_LIB', 'BF_3DMOUSE_LIBPATH', 'BF_3DMOUSE_LIB_STATIC',
'WITH_BF_CYCLES', 'WITH_BF_CYCLES_CUDA_BINARIES', 'BF_CYCLES_CUDA_NVCC', 'BF_CYCLES_CUDA_NVCC', 'WITH_BF_CYCLES_CUDA_THREADED_COMPILE', 'BF_CYCLES_CUDA_ENV',
'WITH_BF_OIIO', 'WITH_BF_STATICOIIO', 'BF_OIIO', 'BF_OIIO_INC', 'BF_OIIO_LIB', 'BF_OIIO_LIB_STATIC', 'BF_OIIO_LIBPATH',
'WITH_BF_OCIO', 'WITH_BF_STATICOCIO', 'BF_OCIO', 'BF_OCIO_INC', 'BF_OCIO_LIB', 'BF_OCIO_LIB_STATIC', 'BF_OCIO_LIBPATH',
'WITH_BF_BOOST', 'WITH_BF_STATICBOOST', 'BF_BOOST', 'BF_BOOST_INC', 'BF_BOOST_LIB', 'BF_BOOST_LIB_INTERNATIONAL', 'BF_BOOST_LIB_STATIC', 'BF_BOOST_LIBPATH',
- 'WITH_BF_LIBMV',
+ 'WITH_BF_LIBMV', 'WITH_BF_LIBMV_SCHUR_SPECIALIZATIONS',
'WITH_BF_CYCLES_OSL', 'WITH_BF_STATICOSL', 'BF_OSL', 'BF_OSL_INC', 'BF_OSL_LIB', 'BF_OSL_LIBPATH', 'BF_OSL_LIB_STATIC', 'BF_OSL_COMPILER',
- 'WITH_BF_LLVM', 'WITH_BF_STATICLLVM', 'BF_LLVM', 'BF_LLVM_LIB', 'BF_LLVM_LIBPATH', 'BF_LLVM_LIB_STATIC', 'BF_PROGRAM_LINKFLAGS'
+ 'WITH_BF_LLVM', 'WITH_BF_STATICLLVM', 'BF_LLVM', 'BF_LLVM_LIB', 'BF_LLVM_LIBPATH', 'BF_LLVM_LIB_STATIC', 'BF_PROGRAM_LINKFLAGS',
+ 'WITH_BF_OPENSUBDIV', 'WITH_BF_STATICOPENSUBDIV', 'BF_OPENSUBDIV', 'BF_OPENSUBDIV_INC', 'BF_OPENSUBDIV_LIB', 'BF_OPENSUBDIV_LIBPATH', 'BF_OPENSUBDIV_LIB_STATIC'
]
# Have options here that scons expects to be lists
opts_list_split = [
'BF_PYTHON_LINKFLAGS',
'BF_OPENGL_LINKFLAGS',
+ 'BF_GL_DEFINITIONS',
'CFLAGS', 'CCFLAGS', 'CXXFLAGS', 'CPPFLAGS',
'REL_CFLAGS', 'REL_CCFLAGS', 'REL_CXXFLAGS',
'BGE_CXXFLAGS',
@@ -192,7 +199,9 @@ def validate_arguments(args, bc):
'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', 'C_COMPILER_ID',
- 'BF_CYCLES_CUDA_BINARIES_ARCH', 'BF_PROGRAM_LINKFLAGS', 'MACOSX_DEPLOYMENT_TARGET'
+ 'BF_CYCLES_CUDA_BINARIES_ARCH', 'BF_PROGRAM_LINKFLAGS', 'MACOSX_DEPLOYMENT_TARGET',
+ 'WITH_BF_CYCLES_DEBUG', 'WITH_BF_CYCLES_LOGGING',
+ 'WITH_BF_CPP11', 'WITH_BF_LEGACY_DEPSGRAPH',
]
@@ -290,11 +299,17 @@ def read_opts(env, cfg, args):
('BF_OPENAL_LIBPATH', 'Path to OpenAL library', ''),
(BoolVariable('WITH_BF_STATICOPENAL', 'Staticly link to openal', False)),
+ (BoolVariable('WITH_BF_AUDASPACE', 'Build with audaspace if true', True)),
+ ('BF_AUDASPACE_C_INC', 'audaspace-c include path', ''),
+ ('BF_AUDASPACE_PY_INC', 'audaspace-py include path', ''),
+ ('BF_AUDASPACE_DEF', 'audaspace defines', ''),
+
(BoolVariable('WITH_BF_SDL', 'Use SDL if true', False)),
('BF_SDL', 'SDL base path', ''),
('BF_SDL_INC', 'SDL include path', ''),
('BF_SDL_LIB', 'SDL library', ''),
('BF_SDL_LIBPATH', 'SDL library path', ''),
+ (BoolVariable('WITH_BF_SDL_DYNLOAD', 'Enable runtime dynamic SDL libraries loading (works only on Linux)', False)),
(BoolVariable('WITH_BF_JACK', 'Enable jack support if true', True)),
('BF_JACK', 'jack base path', ''),
@@ -461,6 +476,18 @@ def read_opts(env, cfg, args):
('BF_OPENGL_LIB_STATIC', 'OpenGL static libraries', ''),
('BF_OPENGL_LINKFLAGS', 'OpenGL link flags', ''),
+ (BoolVariable('WITH_BF_GLEW_MX', '', False)),
+ (BoolVariable('WITH_BF_GLEW_ES', '', False)),
+ (BoolVariable('WITH_BF_GL_EGL', '', False)),
+ (BoolVariable('WITH_BF_GL_PROFILE_COMPAT', '', True)),
+ (BoolVariable('WITH_BF_GL_PROFILE_CORE', '', False)),
+ (BoolVariable('WITH_BF_GL_PROFILE_ES20', '', False)),
+ (BoolVariable('WITH_BF_GL_ANGLE', '', False)),
+ ('BF_GL_DEFINITIONS', '', []),
+ ('BF_GLEW_INC', '', ''),
+ ) # end of opts.AddVariables()
+
+ localopts.AddVariables(
(BoolVariable('WITH_BF_COLLADA', 'Build COLLADA import/export module if true', False)),
(BoolVariable('WITH_BF_STATICOPENCOLLADA', 'Staticly link to OpenCollada', False)),
('BF_COLLADA', 'COLLADA base path', ''),
@@ -489,6 +516,8 @@ def read_opts(env, cfg, args):
(BoolVariable('WITH_BF_PLAYER', 'Build blenderplayer if true', False)),
(BoolVariable('WITH_BF_NOBLENDER', 'Do not build blender if true', False)),
+ (BoolVariable('WITH_BF_IME', 'Enable Input Method Editor (IME) for complex Asian character input', False)),
+
(BoolVariable('WITH_BF_3DMOUSE', 'Build blender with support of 3D mouses', False)),
(BoolVariable('WITH_BF_STATIC3DMOUSE', 'Staticly link to 3d mouse library', False)),
('BF_3DMOUSE', '3d mouse library base path', ''),
@@ -556,6 +585,7 @@ def read_opts(env, cfg, args):
(BoolVariable('WITH_BF_LZMA', 'Enable best LZMA pointcache compression', True)),
(BoolVariable('WITH_BF_LIBMV', 'Enable libmv structure from motion library', True)),
+ (BoolVariable('WITH_BF_LIBMV_SCHUR_SPECIALIZATIONS', 'Enable fixed-size schur specializations', True)),
(BoolVariable('WITH_BF_COMPOSITOR', 'Enable the tile based nodal compositor', True)),
) # end of opts.AddOptions()
@@ -585,6 +615,8 @@ def read_opts(env, cfg, args):
('BF_CYCLES_CUDA_NVCC', 'CUDA nvcc compiler path', ''),
('BF_CYCLES_CUDA_ENV', 'preset environement nvcc will execute in', ''),
('BF_CYCLES_CUDA_BINARIES_ARCH', 'CUDA architectures to compile binaries for', []),
+ (BoolVariable('WITH_BF_CYCLES_DEBUG', 'Build Cycles engine with extra debugging capabilities', False)),
+ (BoolVariable('WITH_BF_CYCLES_LOGGING', 'Build Cycles engine with logging support', True)),
(BoolVariable('WITH_BF_OIIO', 'Build with OpenImageIO', False)),
(BoolVariable('WITH_BF_STATICOIIO', 'Statically link to OpenImageIO', False)),
@@ -629,7 +661,19 @@ def read_opts(env, cfg, args):
('BF_LLVM_LIBPATH', 'LLVM library path', ''),
('BF_LLVM_LIB_STATIC', 'LLVM static library', ''),
- ('BF_PROGRAM_LINKFLAGS', 'Link flags applied only to final binaries (blender and blenderplayer, not makesrna/makesdna)', '')
+ ('BF_PROGRAM_LINKFLAGS', 'Link flags applied only to final binaries (blender and blenderplayer, not makesrna/makesdna)', ''),
+
+ (BoolVariable('WITH_BF_OPENSUBDIV', 'Build with OpenSubdiv library', False)),
+ (BoolVariable('WITH_BF_STATICOPENSUBDIV', 'Staticly link to OpenColorIO', False)),
+ ('BF_OPENSUBDIV', 'OpenSubdiv root path', ''),
+ ('BF_OPENSUBDIV_INC', 'OpenSubdiv include path', ''),
+ ('BF_OPENSUBDIV_LIB', 'OpenSubdiv library', ''),
+ ('BF_OPENSUBDIV_LIBPATH', 'OpenSubdiv library path', ''),
+ ('BF_OPENSUBDIV_LIB_STATIC', 'OpenSubdiv static library', ''),
+
+ (BoolVariable('WITH_BF_CPP11', '"Build with C++11 standard enabled, for development use only!', False)),
+
+ (BoolVariable('WITH_BF_LEGACY_DEPSGRAPH', 'Build Blender with legacy dependency graph', True)),
) # end of opts.AddOptions()
return localopts
diff --git a/build_files/utils/build_tgz.sh b/build_files/utils/build_tgz.sh
index b0ff8ea2aa8..3c921081c29 100755
--- a/build_files/utils/build_tgz.sh
+++ b/build_files/utils/build_tgz.sh
@@ -13,8 +13,10 @@ blender_subversion=$(grep "BLENDER_SUBVERSION\s" "$blender_srcdir/source/blender
if [ "$blender_version_cycle" = "release" ] ; then
VERSION=$(expr $blender_version / 100).$(expr $blender_version % 100)$blender_version_char
+ SUBMODULE_EXCLUDE="^\(release/scripts/addons_contrib\)$"
else
VERSION=$(expr $blender_version / 100).$(expr $blender_version % 100)_$blender_subversion
+ SUBMODULE_EXCLUDE="^$" # dummy regex
fi
MANIFEST="blender-$VERSION-manifest.txt"
@@ -22,15 +24,27 @@ TARBALL="blender-$VERSION.tar.gz"
cd "$blender_srcdir"
+# not so nice, but works
+FILTER_FILES_PY=\
+"import os, sys; "\
+"[print(l[:-1]) for l in sys.stdin.readlines() "\
+"if os.path.isfile(l[:-1]) "\
+"if os.path.basename(l[:-1]) not in {"\
+"'.gitignore', "\
+"'.gitmodules', "\
+"'.arcconfig', "\
+"}"\
+"]"
+
# Build master list
echo -n "Building manifest of files: \"$BASE_DIR/$MANIFEST\" ..."
-git ls-files > $BASE_DIR/$MANIFEST
+git ls-files | python3 -c "$FILTER_FILES_PY" > $BASE_DIR/$MANIFEST
# Enumerate submodules
-for lcv in $(git submodule | cut -f2 -d" "); do
+for lcv in $(git submodule | awk '{print $2}' | grep -v "$SUBMODULE_EXCLUDE"); do
cd "$BASE_DIR"
cd "$blender_srcdir/$lcv"
- git ls-files | awk '$0="'"$lcv"/'"$0' >> $BASE_DIR/$MANIFEST
+ git ls-files | python3 -c "$FILTER_FILES_PY" | awk '$0="'"$lcv"/'"$0' >> $BASE_DIR/$MANIFEST
cd "$BASE_DIR"
done
echo "OK"
diff --git a/doc/blender_file_format/BlendFileDnaExporter_25.py b/doc/blender_file_format/BlendFileDnaExporter_25.py
index 837b67c6eed..64c92c7cf80 100755
--- a/doc/blender_file_format/BlendFileDnaExporter_25.py
+++ b/doc/blender_file_format/BlendFileDnaExporter_25.py
@@ -112,7 +112,7 @@ class DNACatalogHTML:
# ${version} and ${revision}
if bpy:
version = '.'.join(map(str, bpy.app.version))
- revision = bpy.app.build_revision[:-1]
+ revision = bpy.app.build_hash
else:
version = str(header.Version)
revision = 'Unknown'
@@ -404,7 +404,7 @@ def main():
# Files
if '--dna-versioned' in sys.argv:
blender_version = '_'.join(map(str, bpy.app.version))
- filename = 'dna-{0}-{1}_endian-{2}-r{3}'.format(sys.arch, sys.byteorder, blender_version, bpy.app.build_revision[2:-1])
+ filename = 'dna-{0}-{1}_endian-{2}-{3}'.format(sys.arch, sys.byteorder, blender_version, bpy.app.build_hash)
else:
filename = 'dna'
dir = os.path.dirname(__file__)
@@ -451,7 +451,7 @@ def main():
os.remove(Path_Blend)
# export dna to xhtml
- log.info("6: export sdna to xhtml file")
+ log.info("6: export sdna to xhtml file: %r" % Path_HTML)
handleHTML = open(Path_HTML, "w")
catalog.WriteToHTML(handleHTML)
handleHTML.close()
diff --git a/doc/build_systems/cmake.txt b/doc/build_systems/cmake.txt
deleted file mode 100644
index c46978df2fa..00000000000
--- a/doc/build_systems/cmake.txt
+++ /dev/null
@@ -1,104 +0,0 @@
-
- Blender CMake build system
- ============================
-
- Contents
- ---------------
-
- 1. Introduction
- 2. Obtaining CMake
- 3. Building Blender
- 4. Generic Setup
- 5. Configuring the build after SVN updates
-
- 1. Introduction
- ---------------
-
- This document describes general usage of the new CMake scripts. The
- inner workings will be described in blender-cmake-dev.txt (TODO).
-
- 2. Obtaining CMake
- ------------------
-
- CMake for can either be downloaded using your favorite package manager
- or is also available from the CMake website at http://www.cmake.org
- The website also contains some documentation on CMake usage but I found
- the man page alone pretty helpful.
-
- 3. Building Blender
- -------------------
-
- Building Blender requires obtaining a compiler, library dependencies,
- and correct setup depending on the system. For details on how to set
- up a build on various operating systems, see the wiki documentation:
-
- http://wiki.blender.org/index.php/Dev:Doc/Building_Blender
-
- 4. Generic Setup
- ----------------
-
- CMake allows one to generate the build project files and binary objects
- outside the source tree which can be pretty handy in working and experimenting
- with different Blender configurations (Audio/NoAudio, GameEngine/NoGameEngine etc.)
- while maintaining a clean source tree. It also makes it possible to generate files
- for different build systems on the same source tree. This also has benefits for
- general SVN management for the developer as patches and submit logs are much cleaner.
-
- Create a directory outside the blender source tree where you would like to build
- Blender (from now on called $BLENDERBUILD). On the commandline you can then run
- the cmake command to generate your initial build files. First just run 'cmake' which
- will inform you what the available generators are. Thn you can run
- 'cmake -G generator $BLENDERSOURCE' to generate the build files. Here is an example
- of all this for Xcode:
-
- % mkdir $BLENDERBUILD
- % cd $BLENDERBUILD
- % cmake
-
- ...
- ...
- --version [file] = Show program name/version banner and exit.
-
- Generators
-
- The following generators are available on this platform:
- KDevelop3 = Generates KDevelop 3 project files.
- Unix Makefiles = Generates standard UNIX makefiles.
- Xcode = Generate XCode project files.
-
-
-
- % cmake -G Xcode $BLENDERSOURCE
- ...
- ...
- -- Configuring blender
- -- Configuring blenderplayer
- -- Configuring done
- -- Generating done
- -- Build files have been written to: $BLENDERBUILD
-
- This will generate the build files with default values. Specific features can
- be enabled or disabled by running the ccmake "GUI" from $BLENDERBUILD as follows:
-
- % ccmake $BLENDERSOURCE
-
- A number of options appear which can be changed depending on your needs and
- available dependencies (e.g. setting WITH_OPENEXR to OFF will disable support
- for OpenEXR). It will also allow you to override default and detected paths
- (e.g. Python directories) and compile and link flags. When you are satisfied
- used ccmake to re-configure the build files and exit.
-
- It is also possible to use the commandline of 'cmake' to override certain
- of these settings.
-
- 5. Configuring the build after SVN updates
- ------------------------------------------
-
- The $BLENDERBUILD directory maintains a file called CMakeCache.txt which
- remembers the initial run's settings for subsequent generation runs. After
- SVN updates that contain changes to the build system, rebuilding Blender will
- automatically invoke CMake to regenerate the CMakeCache.txt and other files
- as needed.
-
- /Jacques Beaurain (jbinto)
-
diff --git a/doc/build_systems/scons-dev.txt b/doc/build_systems/scons-dev.txt
index ae2be2b2a94..9ca072c38c5 100644
--- a/doc/build_systems/scons-dev.txt
+++ b/doc/build_systems/scons-dev.txt
@@ -35,13 +35,14 @@
defaults.
Much of the actual functionality can be found in the python scripts
- in the directory $BLENDERHOME/tools, with Blender.py defining the
- bulk of the functionality. btools.py has some helper functions, and
- bcolors.py is for the terminal colors. mstoolkit.py and crossmingw.py
- are modules which set up SCons for the MS VC++ 2003 toolkit and
- the cross-compile toolset for compiling Windows binaries on Linux
- respectively. Note: the cross-compile doesn't work yet for Blender,
- but is added in preparation for having it work in the distant future.
+ in the directory $BLENDERHOME/build_files/scons/tools, with
+ Blender.py defining the bulk of the functionality. btools.py has some
+ helper functions, and bcolors.py is for the terminal
+ colors. mstoolkit.py and crossmingw.py are modules which set up SCons
+ for the MS VC++ 2003 toolkit and the cross-compile toolset for
+ compiling Windows binaries on Linux respectively. Note: the
+ cross-compile doesn't work yet for Blender, but is added in
+ preparation for having it work in the distant future.
BlenderEnvironment
------------------
diff --git a/doc/build_systems/scons.txt b/doc/build_systems/scons.txt
index cb88c56ddbc..e3438f1fe04 100644
--- a/doc/build_systems/scons.txt
+++ b/doc/build_systems/scons.txt
@@ -29,9 +29,9 @@
a scons-local installation, which can be found in the scons/ subdirectory.
This document uses the scons-local installation for its examples.
- Check from the page
- http://www.blender.org/development/building-blender/getting-dependencies/
- that you have all dependencies needed for building Blender. Note that for
+ For build instructions, including dependencies, consult the appropriate
+ section for your platform at
+ http://wiki.blender.org/index.php/Dev:Doc/Building_Blender. Note that for
windows many of these dependencies already come in the lib/windows module
from CVS.
@@ -53,12 +53,13 @@
from the command-line is given, then all libraries and binaries to
build are configured.
- The build uses BF_BUILDDIR to build into and BF_INSTALLDIR to
- finally copy all needed files to get a proper setup. The BF_DOCDIR is
- used to generate Blender Python documentation files to. These
- variables have default values for every platform in
- $BLENDERHOME/config/(platform)-config.py. After the build successfully
- completes, you can find everything you need in BF_INSTALLDIR.
+ The build uses BF_BUILDDIR to build into and BF_INSTALLDIR to finally copy
+ all needed files to get a proper setup. The BF_DOCDIR is used to generate
+ Blender Python documentation files to. These variables have default values
+ for every platform in
+ $BLENDERHOME/build_files/scons/config/(platform)-config.py. See the next
+ section of this document for how to customize these paths. After the build
+ successfully completes, you can find everything you need in BF_INSTALLDIR.
If you want to create the installer package of Blender on Windows you'll
need to install nullsoft scriptable install system from http://nsis.sf.net.
@@ -72,8 +73,8 @@
---------------------
The default values for your platform can be found in the directory
- $BLENDERHOME/config. Your platform specific defaults are in
- (platform)-config.py, where platform is one of:
+ $BLENDERHOME/build_files/scons/config. Your platform specific defaults are
+ in (platform)-config.py, where platform is one of:
- linux, for machines running Linux
- win32-vc, for Windows machines, compiling with a Microsoft compiler
@@ -81,12 +82,13 @@
- darwin, for OS X machines
(TBD: add cygwin, solaris and freebsd support)
- These files you will normally not change. If you need to override
- a default value, make a file called $BLENDERHOME/user-config.py, and copy
- settings from the config/(platform)-config.py that you want to change. Don't
- copy the entire file (unless explicitely stated in the configuration file),
- because you may not get updated options you don't change yourself, which may
- result in build errors.
+ These files you will normally not change. If you need to override a
+ default value, make a file called $BLENDERHOME/user-config.py, and copy
+ settings from the build_files/scons/config/(platform)-config.py that you
+ want to change. Don't copy the entire file (unless explicitly stated in
+ the configuration file), because you may not get updated options you don't
+ change yourself, which may result in build errors. You should NEVER have
+ to modify $BLENDERHOME/build_files/scons/config/(platform)-config.py.
You can use BF_CONFIG argument to override the default user-config.py
check. This is just like the user-config.py, but just with another name:
@@ -113,11 +115,6 @@
(unless you have overridden any of them in your
$BLENDERHOME/user-config.py).
- NOTE: The best way to avoid confusion is the
- copy $BLENDERHOME/config/(platform)-config.py to
- $BLENDERHOME/user-config.py. You should NEVER have to modify
- $BLENDERHOME/config/(platform)-config.py
-
Configuring the output
----------------------
diff --git a/doc/doxygen/Doxyfile b/doc/doxygen/Doxyfile
index 397cc301627..153c7983ee5 100644
--- a/doc/doxygen/Doxyfile
+++ b/doc/doxygen/Doxyfile
@@ -1,106 +1,122 @@
-# Doxyfile 1.8.4
+# Doxyfile 1.8.9.1
# This file describes the settings to be used by the documentation system
# doxygen (www.doxygen.org) for a project.
#
-# All text after a double hash (##) is considered a comment and is placed
-# in front of the TAG it is preceding .
-# All text after a hash (#) is considered a comment and will be ignored.
+# All text after a double hash (##) is considered a comment and is placed in
+# front of the TAG it is preceding.
+#
+# All text after a single hash (#) is considered a comment and will be ignored.
# The format is:
-# TAG = value [value, ...]
-# For lists items can also be appended using:
-# TAG += value [value, ...]
-# Values that contain spaces should be placed between quotes (" ").
+# TAG = value [value, ...]
+# For lists, items can also be appended using:
+# TAG += value [value, ...]
+# Values that contain spaces should be placed between quotes (\" \").
#---------------------------------------------------------------------------
# Project related configuration options
#---------------------------------------------------------------------------
# This tag specifies the encoding used for all characters in the config file
-# that follow. The default is UTF-8 which is also the encoding used for all
-# text before the first occurrence of this tag. Doxygen uses libiconv (or the
-# iconv built into libc) for the transcoding. See
-# http://www.gnu.org/software/libiconv for the list of possible encodings.
+# that follow. The default is UTF-8 which is also the encoding used for all text
+# before the first occurrence of this tag. Doxygen uses libiconv (or the iconv
+# built into libc) for the transcoding. See http://www.gnu.org/software/libiconv
+# for the list of possible encodings.
+# The default value is: UTF-8.
DOXYFILE_ENCODING = UTF-8
-# The PROJECT_NAME tag is a single word (or sequence of words) that should
-# identify the project. Note that if you do not use Doxywizard you need
-# to put quotes around the project name if it contains spaces.
+# The PROJECT_NAME tag is a single word (or a sequence of words surrounded by
+# double-quotes, unless you are using Doxywizard) that should identify the
+# project for which the documentation is generated. This name is used in the
+# title of most generated pages and in a few other places.
+# The default value is: My Project.
PROJECT_NAME = Blender
-# The PROJECT_NUMBER tag can be used to enter a project or revision number.
-# This could be handy for archiving the generated documentation or
-# if some version control system is used.
+# The PROJECT_NUMBER tag can be used to enter a project or revision number. This
+# could be handy for archiving the generated documentation or if some version
+# control system is used.
-PROJECT_NUMBER = "V2.6x"
+PROJECT_NUMBER = "V2.7x"
# Using the PROJECT_BRIEF tag one can provide an optional one line description
-# for a project that appears at the top of each page and should give viewer
-# a quick idea about the purpose of the project. Keep the description short.
+# for a project that appears at the top of each page and should give viewer a
+# quick idea about the purpose of the project. Keep the description short.
PROJECT_BRIEF =
-# With the PROJECT_LOGO tag one can specify an logo or icon that is
-# included in the documentation. The maximum height of the logo should not
-# exceed 55 pixels and the maximum width should not exceed 200 pixels.
-# Doxygen will copy the logo to the output directory.
+# With the PROJECT_LOGO tag one can specify a logo or an icon that is included
+# in the documentation. The maximum height of the logo should not exceed 55
+# pixels and the maximum width should not exceed 200 pixels. Doxygen will copy
+# the logo to the output directory.
PROJECT_LOGO = ../../release/freedesktop/icons/48x48/apps/blender.png
-# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
-# base path where the generated documentation will be put.
-# If a relative path is entered, it will be relative to the location
-# where doxygen was started. If left blank the current directory will be used.
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path
+# into which the generated documentation will be written. If a relative path is
+# entered, it will be relative to the location where doxygen was started. If
+# left blank the current directory will be used.
OUTPUT_DIRECTORY =
-# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create
-# 4096 sub-directories (in 2 levels) under the output directory of each output
-# format and will distribute the generated files over these directories.
-# Enabling this option can be useful when feeding doxygen a huge amount of
-# source files, where putting all generated files in the same directory would
-# otherwise cause performance problems for the file system.
+# If the CREATE_SUBDIRS tag is set to YES then doxygen will create 4096 sub-
+# directories (in 2 levels) under the output directory of each output format and
+# will distribute the generated files over these directories. Enabling this
+# option can be useful when feeding doxygen a huge amount of source files, where
+# putting all generated files in the same directory would otherwise causes
+# performance problems for the file system.
+# The default value is: NO.
CREATE_SUBDIRS = YES
+# If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII
+# characters to appear in the names of generated files. If set to NO, non-ASCII
+# characters will be escaped, for example _xE3_x81_x84 will be used for Unicode
+# U+3044.
+# The default value is: NO.
+
+ALLOW_UNICODE_NAMES = NO
+
# The OUTPUT_LANGUAGE tag is used to specify the language in which all
# documentation generated by doxygen is written. Doxygen will use this
# information to generate all constant output in the proper language.
-# The default language is English, other supported languages are:
-# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional,
-# Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German,
-# Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English
-# messages), Korean, Korean-en, Latvian, Lithuanian, Norwegian, Macedonian,
-# Persian, Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrillic,
-# Slovak, Slovene, Spanish, Swedish, Ukrainian, and Vietnamese.
+# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese,
+# Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States),
+# Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian,
+# Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages),
+# Korean, Korean-en (Korean with English messages), Latvian, Lithuanian,
+# Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian,
+# Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish,
+# Ukrainian and Vietnamese.
+# The default value is: English.
OUTPUT_LANGUAGE = English
-# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will
-# include brief member descriptions after the members that are listed in
-# the file and class documentation (similar to JavaDoc).
-# Set to NO to disable this.
+# If the BRIEF_MEMBER_DESC tag is set to YES, doxygen will include brief member
+# descriptions after the members that are listed in the file and class
+# documentation (similar to Javadoc). Set to NO to disable this.
+# The default value is: YES.
BRIEF_MEMBER_DESC = YES
-# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend
-# the brief description of a member or function before the detailed description.
-# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
+# If the REPEAT_BRIEF tag is set to YES, doxygen will prepend the brief
+# description of a member or function before the detailed description
+#
+# Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
# brief descriptions will be completely suppressed.
+# The default value is: YES.
REPEAT_BRIEF = YES
-# This tag implements a quasi-intelligent brief description abbreviator
-# that is used to form the text in various listings. Each string
-# in this list, if found as the leading text of the brief description, will be
-# stripped from the text and the result after processing the whole list, is
-# used as the annotated text. Otherwise, the brief description is used as-is.
-# If left blank, the following values are used ("$name" is automatically
-# replaced with the name of the entity): "The $name class" "The $name widget"
-# "The $name file" "is" "provides" "specifies" "contains"
-# "represents" "a" "an" "the"
+# This tag implements a quasi-intelligent brief description abbreviator that is
+# used to form the text in various listings. Each string in this list, if found
+# as the leading text of the brief description, will be stripped from the text
+# and the result, after processing the whole list, is used as the annotated
+# text. Otherwise, the brief description is used as-is. If left blank, the
+# following values are used ($name is automatically replaced with the name of
+# the entity):The $name class, The $name widget, The $name file, is, provides,
+# specifies, contains, represents, a, an and the.
ABBREVIATE_BRIEF = "The $name class" \
"The $name widget" \
@@ -115,8 +131,9 @@ ABBREVIATE_BRIEF = "The $name class" \
the
# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
-# Doxygen will generate a detailed section even if there is only a brief
+# doxygen will generate a detailed section even if there is only a brief
# description.
+# The default value is: NO.
ALWAYS_DETAILED_SEC = NO
@@ -124,231 +141,269 @@ ALWAYS_DETAILED_SEC = NO
# inherited members of a class in the documentation of that class as if those
# members were ordinary class members. Constructors, destructors and assignment
# operators of the base classes will not be shown.
+# The default value is: NO.
INLINE_INHERITED_MEMB = NO
-# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full
-# path before files name in the file list and in the header files. If set
-# to NO the shortest path that makes the file name unique will be used.
+# If the FULL_PATH_NAMES tag is set to YES, doxygen will prepend the full path
+# before files name in the file list and in the header files. If set to NO the
+# shortest path that makes the file name unique will be used
+# The default value is: YES.
FULL_PATH_NAMES = NO
-# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag
-# can be used to strip a user-defined part of the path. Stripping is
-# only done if one of the specified strings matches the left-hand part of
-# the path. The tag can be used to show relative paths in the file list.
-# If left blank the directory from which doxygen is run is used as the
-# path to strip. Note that you specify absolute paths here, but also
-# relative paths, which will be relative from the directory where doxygen is
-# started.
+# The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path.
+# Stripping is only done if one of the specified strings matches the left-hand
+# part of the path. The tag can be used to show relative paths in the file list.
+# If left blank the directory from which doxygen is run is used as the path to
+# strip.
+#
+# Note that you can specify absolute paths here, but also relative paths, which
+# will be relative from the directory where doxygen is started.
+# This tag requires that the tag FULL_PATH_NAMES is set to YES.
STRIP_FROM_PATH =
-# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of
-# the path mentioned in the documentation of a class, which tells
-# the reader which header file to include in order to use a class.
-# If left blank only the name of the header file containing the class
-# definition is used. Otherwise one should specify the include paths that
-# are normally passed to the compiler using the -I flag.
+# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the
+# path mentioned in the documentation of a class, which tells the reader which
+# header file to include in order to use a class. If left blank only the name of
+# the header file containing the class definition is used. Otherwise one should
+# specify the list of include paths that are normally passed to the compiler
+# using the -I flag.
STRIP_FROM_INC_PATH =
-# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter
-# (but less readable) file names. This can be useful if your file system
-# doesn't support long names like on DOS, Mac, or CD-ROM.
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but
+# less readable) file names. This can be useful is your file systems doesn't
+# support long names like on DOS, Mac, or CD-ROM.
+# The default value is: NO.
SHORT_NAMES = NO
-# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen
-# will interpret the first line (until the first dot) of a JavaDoc-style
-# comment as the brief description. If set to NO, the JavaDoc
-# comments will behave just like regular Qt-style comments
-# (thus requiring an explicit @brief command for a brief description.)
+# If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the
+# first line (until the first dot) of a Javadoc-style comment as the brief
+# description. If set to NO, the Javadoc-style will behave just like regular Qt-
+# style comments (thus requiring an explicit @brief command for a brief
+# description.)
+# The default value is: NO.
JAVADOC_AUTOBRIEF = NO
-# If the QT_AUTOBRIEF tag is set to YES then Doxygen will
-# interpret the first line (until the first dot) of a Qt-style
-# comment as the brief description. If set to NO, the comments
-# will behave just like regular Qt-style comments (thus requiring
-# an explicit \brief command for a brief description.)
+# If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first
+# line (until the first dot) of a Qt-style comment as the brief description. If
+# set to NO, the Qt-style will behave just like regular Qt-style comments (thus
+# requiring an explicit \brief command for a brief description.)
+# The default value is: NO.
QT_AUTOBRIEF = NO
-# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen
-# treat a multi-line C++ special comment block (i.e. a block of //! or ///
-# comments) as a brief description. This used to be the default behaviour.
-# The new default is to treat a multi-line C++ comment block as a detailed
-# description. Set this tag to YES if you prefer the old behaviour instead.
+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a
+# multi-line C++ special comment block (i.e. a block of //! or /// comments) as
+# a brief description. This used to be the default behavior. The new default is
+# to treat a multi-line C++ comment block as a detailed description. Set this
+# tag to YES if you prefer the old behavior instead.
+#
+# Note that setting this tag to YES also means that rational rose comments are
+# not recognized any more.
+# The default value is: NO.
MULTILINE_CPP_IS_BRIEF = NO
-# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented
-# member inherits the documentation from any documented member that it
-# re-implements.
+# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the
+# documentation from any documented member that it re-implements.
+# The default value is: YES.
INHERIT_DOCS = YES
-# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce
-# a new page for each member. If set to NO, the documentation of a member will
-# be part of the file/class/namespace that contains it.
+# If the SEPARATE_MEMBER_PAGES tag is set to YES then doxygen will produce a new
+# page for each member. If set to NO, the documentation of a member will be part
+# of the file/class/namespace that contains it.
+# The default value is: NO.
SEPARATE_MEMBER_PAGES = NO
-# The TAB_SIZE tag can be used to set the number of spaces in a tab.
-# Doxygen uses this value to replace tabs by spaces in code fragments.
+# The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen
+# uses this value to replace tabs by spaces in code fragments.
+# Minimum value: 1, maximum value: 16, default value: 4.
TAB_SIZE = 4
-# This tag can be used to specify a number of aliases that acts
-# as commands in the documentation. An alias has the form "name=value".
-# For example adding "sideeffect=\par Side Effects:\n" will allow you to
-# put the command \sideeffect (or @sideeffect) in the documentation, which
-# will result in a user-defined paragraph with heading "Side Effects:".
-# You can put \n's in the value part of an alias to insert newlines.
+# This tag can be used to specify a number of aliases that act as commands in
+# the documentation. An alias has the form:
+# name=value
+# For example adding
+# "sideeffect=@par Side Effects:\n"
+# will allow you to put the command \sideeffect (or @sideeffect) in the
+# documentation, which will result in a user-defined paragraph with heading
+# "Side Effects:". You can put \n's in the value part of an alias to insert
+# newlines.
ALIASES =
# This tag can be used to specify a number of word-keyword mappings (TCL only).
-# A mapping has the form "name=value". For example adding
-# "class=itcl::class" will allow you to use the command class in the
-# itcl::class meaning.
+# A mapping has the form "name=value". For example adding "class=itcl::class"
+# will allow you to use the command class in the itcl::class meaning.
TCL_SUBST =
-# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C
-# sources only. Doxygen will then generate output that is more tailored for C.
-# For instance, some of the names that are used will be different. The list
-# of all members will be omitted, etc.
+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources
+# only. Doxygen will then generate output that is more tailored for C. For
+# instance, some of the names that are used will be different. The list of all
+# members will be omitted, etc.
+# The default value is: NO.
OPTIMIZE_OUTPUT_FOR_C = NO
-# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java
-# sources only. Doxygen will then generate output that is more tailored for
-# Java. For instance, namespaces will be presented as packages, qualified
-# scopes will look different, etc.
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or
+# Python sources only. Doxygen will then generate output that is more tailored
+# for that language. For instance, namespaces will be presented as packages,
+# qualified scopes will look different, etc.
+# The default value is: NO.
OPTIMIZE_OUTPUT_JAVA = NO
# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran
-# sources only. Doxygen will then generate output that is more tailored for
-# Fortran.
+# sources. Doxygen will then generate output that is tailored for Fortran.
+# The default value is: NO.
OPTIMIZE_FOR_FORTRAN = NO
# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL
-# sources. Doxygen will then generate output that is tailored for
-# VHDL.
+# sources. Doxygen will then generate output that is tailored for VHDL.
+# The default value is: NO.
OPTIMIZE_OUTPUT_VHDL = NO
# Doxygen selects the parser to use depending on the extension of the files it
# parses. With this tag you can assign which parser to use for a given
# extension. Doxygen has a built-in mapping, but you can override or extend it
-# using this tag. The format is ext=language, where ext is a file extension,
-# and language is one of the parsers supported by doxygen: IDL, Java,
-# Javascript, CSharp, C, C++, D, PHP, Objective-C, Python, Fortran, VHDL, C,
-# C++. For instance to make doxygen treat .inc files as Fortran files (default
-# is PHP), and .f files as C (default is Fortran), use: inc=Fortran f=C. Note
-# that for custom extensions you also need to set FILE_PATTERNS otherwise the
-# files are not read by doxygen.
+# using this tag. The format is ext=language, where ext is a file extension, and
+# language is one of the parsers supported by doxygen: IDL, Java, Javascript,
+# C#, C, C++, D, PHP, Objective-C, Python, Fortran (fixed format Fortran:
+# FortranFixed, free formatted Fortran: FortranFree, unknown formatted Fortran:
+# Fortran. In the later case the parser tries to guess whether the code is fixed
+# or free formatted code, this is the default for Fortran type files), VHDL. For
+# instance to make doxygen treat .inc files as Fortran files (default is PHP),
+# and .f files as C (default is Fortran), use: inc=Fortran f=C.
+#
+# Note: For files without extension you can use no_extension as a placeholder.
+#
+# Note that for custom extensions you also need to set FILE_PATTERNS otherwise
+# the files are not read by doxygen.
EXTENSION_MAPPING =
-# If MARKDOWN_SUPPORT is enabled (the default) then doxygen pre-processes all
-# comments according to the Markdown format, which allows for more readable
+# If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments
+# according to the Markdown format, which allows for more readable
# documentation. See http://daringfireball.net/projects/markdown/ for details.
-# The output of markdown processing is further processed by doxygen, so you
-# can mix doxygen, HTML, and XML commands with Markdown formatting.
-# Disable only in case of backward compatibilities issues.
+# The output of markdown processing is further processed by doxygen, so you can
+# mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in
+# case of backward compatibilities issues.
+# The default value is: YES.
MARKDOWN_SUPPORT = YES
# When enabled doxygen tries to link words that correspond to documented
# classes, or namespaces to their corresponding documentation. Such a link can
-# be prevented in individual cases by by putting a % sign in front of the word
-# or globally by setting AUTOLINK_SUPPORT to NO.
+# be prevented in individual cases by putting a % sign in front of the word or
+# globally by setting AUTOLINK_SUPPORT to NO.
+# The default value is: YES.
AUTOLINK_SUPPORT = YES
# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want
-# to include (a tag file for) the STL sources as input, then you should
-# set this tag to YES in order to let doxygen match functions declarations and
-# definitions whose arguments contain STL classes (e.g. func(std::string); v.s.
-# func(std::string) {}). This also makes the inheritance and collaboration
+# to include (a tag file for) the STL sources as input, then you should set this
+# tag to YES in order to let doxygen match functions declarations and
+# definitions whose arguments contain STL classes (e.g. func(std::string);
+# versus func(std::string) {}). This also make the inheritance and collaboration
# diagrams that involve STL classes more complete and accurate.
+# The default value is: NO.
BUILTIN_STL_SUPPORT = NO
# If you use Microsoft's C++/CLI language, you should set this option to YES to
# enable parsing support.
+# The default value is: NO.
CPP_CLI_SUPPORT = NO
-# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only.
-# Doxygen will parse them like normal C++ but will assume all classes use public
-# instead of private inheritance when no explicit protection keyword is present.
+# Set the SIP_SUPPORT tag to YES if your project consists of sip (see:
+# http://www.riverbankcomputing.co.uk/software/sip/intro) sources only. Doxygen
+# will parse them like normal C++ but will assume all classes use public instead
+# of private inheritance when no explicit protection keyword is present.
+# The default value is: NO.
SIP_SUPPORT = NO
# For Microsoft's IDL there are propget and propput attributes to indicate
-# getter and setter methods for a property. Setting this option to YES (the
-# default) will make doxygen replace the get and set methods by a property in
-# the documentation. This will only work if the methods are indeed getting or
-# setting a simple type. If this is not the case, or you want to show the
-# methods anyway, you should set this option to NO.
+# getter and setter methods for a property. Setting this option to YES will make
+# doxygen to replace the get and set methods by a property in the documentation.
+# This will only work if the methods are indeed getting or setting a simple
+# type. If this is not the case, or you want to show the methods anyway, you
+# should set this option to NO.
+# The default value is: YES.
IDL_PROPERTY_SUPPORT = YES
# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
-# tag is set to YES, then doxygen will reuse the documentation of the first
+# tag is set to YES then doxygen will reuse the documentation of the first
# member in the group (if any) for the other members of the group. By default
# all members of a group must be documented explicitly.
+# The default value is: NO.
DISTRIBUTE_GROUP_DOC = YES
-# Set the SUBGROUPING tag to YES (the default) to allow class member groups of
-# the same type (for instance a group of public functions) to be put as a
-# subgroup of that type (e.g. under the Public Functions section). Set it to
-# NO to prevent subgrouping. Alternatively, this can be done per class using
-# the \nosubgrouping command.
+# Set the SUBGROUPING tag to YES to allow class member groups of the same type
+# (for instance a group of public functions) to be put as a subgroup of that
+# type (e.g. under the Public Functions section). Set it to NO to prevent
+# subgrouping. Alternatively, this can be done per class using the
+# \nosubgrouping command.
+# The default value is: YES.
SUBGROUPING = YES
-# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and
-# unions are shown inside the group in which they are included (e.g. using
-# @ingroup) instead of on a separate page (for HTML and Man pages) or
-# section (for LaTeX and RTF).
+# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions
+# are shown inside the group in which they are included (e.g. using \ingroup)
+# instead of on a separate page (for HTML and Man pages) or section (for LaTeX
+# and RTF).
+#
+# Note that this feature does not work in combination with
+# SEPARATE_MEMBER_PAGES.
+# The default value is: NO.
INLINE_GROUPED_CLASSES = NO
-# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and
-# unions with only public data fields or simple typedef fields will be shown
-# inline in the documentation of the scope in which they are defined (i.e. file,
+# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions
+# with only public data fields or simple typedef fields will be shown inline in
+# the documentation of the scope in which they are defined (i.e. file,
# namespace, or group documentation), provided this scope is documented. If set
-# to NO (the default), structs, classes, and unions are shown on a separate
-# page (for HTML and Man pages) or section (for LaTeX and RTF).
+# to NO, structs, classes, and unions are shown on a separate page (for HTML and
+# Man pages) or section (for LaTeX and RTF).
+# The default value is: NO.
INLINE_SIMPLE_STRUCTS = NO
-# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum
-# is documented as struct, union, or enum with the name of the typedef. So
+# When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or
+# enum is documented as struct, union, or enum with the name of the typedef. So
# typedef struct TypeS {} TypeT, will appear in the documentation as a struct
# with name TypeT. When disabled the typedef will appear as a member of a file,
-# namespace, or class. And the struct will be named TypeS. This can typically
-# be useful for C code in case the coding convention dictates that all compound
+# namespace, or class. And the struct will be named TypeS. This can typically be
+# useful for C code in case the coding convention dictates that all compound
# types are typedef'ed and only the typedef is referenced, never the tag name.
+# The default value is: NO.
TYPEDEF_HIDES_STRUCT = NO
# The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This
-# cache is used to resolve symbols given their name and scope. Since this can
-# be an expensive process and often the same symbol appear multiple times in
-# the code, doxygen keeps a cache of pre-resolved symbols. If the cache is too
-# small doxygen will become slower. If the cache is too large, memory is wasted.
-# The cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid
-# range is 0..9, the default is 0, corresponding to a cache size of 2^16 = 65536
-# symbols.
+# cache is used to resolve symbols given their name and scope. Since this can be
+# an expensive process and often the same symbol appears multiple times in the
+# code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small
+# doxygen will become slower. If the cache is too large, memory is wasted. The
+# cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range
+# is 0..9, the default is 0, corresponding to a cache size of 2^16=65536
+# symbols. At the end of a run doxygen will report the cache usage and suggest
+# the optimal cache size from a speed point of view.
+# Minimum value: 0, maximum value: 9, default value: 0.
LOOKUP_CACHE_SIZE = 0
@@ -356,349 +411,401 @@ LOOKUP_CACHE_SIZE = 0
# Build related configuration options
#---------------------------------------------------------------------------
-# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
-# documentation are documented, even if no documentation was available.
-# Private class members and static file members will be hidden unless
-# the EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES
+# If the EXTRACT_ALL tag is set to YES, doxygen will assume all entities in
+# documentation are documented, even if no documentation was available. Private
+# class members and static file members will be hidden unless the
+# EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES.
+# Note: This will also disable the warnings about undocumented members that are
+# normally produced when WARNINGS is set to YES.
+# The default value is: NO.
EXTRACT_ALL = YES
-# If the EXTRACT_PRIVATE tag is set to YES all private members of a class
-# will be included in the documentation.
+# If the EXTRACT_PRIVATE tag is set to YES, all private members of a class will
+# be included in the documentation.
+# The default value is: NO.
EXTRACT_PRIVATE = NO
-# If the EXTRACT_PACKAGE tag is set to YES all members with package or internal
+# If the EXTRACT_PACKAGE tag is set to YES, all members with package or internal
# scope will be included in the documentation.
+# The default value is: NO.
EXTRACT_PACKAGE = NO
-# If the EXTRACT_STATIC tag is set to YES all static members of a file
-# will be included in the documentation.
+# If the EXTRACT_STATIC tag is set to YES, all static members of a file will be
+# included in the documentation.
+# The default value is: NO.
EXTRACT_STATIC = YES
-# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs)
-# defined locally in source files will be included in the documentation.
-# If set to NO only classes defined in header files are included.
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES, classes (and structs) defined
+# locally in source files will be included in the documentation. If set to NO,
+# only classes defined in header files are included. Does not have any effect
+# for Java sources.
+# The default value is: YES.
EXTRACT_LOCAL_CLASSES = YES
-# This flag is only useful for Objective-C code. When set to YES local
-# methods, which are defined in the implementation section but not in
-# the interface are included in the documentation.
-# If set to NO (the default) only methods in the interface are included.
+# This flag is only useful for Objective-C code. If set to YES, local methods,
+# which are defined in the implementation section but not in the interface are
+# included in the documentation. If set to NO, only methods in the interface are
+# included.
+# The default value is: NO.
EXTRACT_LOCAL_METHODS = NO
# If this flag is set to YES, the members of anonymous namespaces will be
# extracted and appear in the documentation as a namespace called
-# 'anonymous_namespace{file}', where file will be replaced with the base
-# name of the file that contains the anonymous namespace. By default
-# anonymous namespaces are hidden.
+# 'anonymous_namespace{file}', where file will be replaced with the base name of
+# the file that contains the anonymous namespace. By default anonymous namespace
+# are hidden.
+# The default value is: NO.
EXTRACT_ANON_NSPACES = NO
-# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all
-# undocumented members of documented classes, files or namespaces.
-# If set to NO (the default) these members will be included in the
-# various overviews, but no documentation section is generated.
-# This option has no effect if EXTRACT_ALL is enabled.
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all
+# undocumented members inside documented classes or files. If set to NO these
+# members will be included in the various overviews, but no documentation
+# section is generated. This option has no effect if EXTRACT_ALL is enabled.
+# The default value is: NO.
HIDE_UNDOC_MEMBERS = NO
-# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all
-# undocumented classes that are normally visible in the class hierarchy.
-# If set to NO (the default) these classes will be included in the various
-# overviews. This option has no effect if EXTRACT_ALL is enabled.
+# If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all
+# undocumented classes that are normally visible in the class hierarchy. If set
+# to NO, these classes will be included in the various overviews. This option
+# has no effect if EXTRACT_ALL is enabled.
+# The default value is: NO.
HIDE_UNDOC_CLASSES = NO
-# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all
-# friend (class|struct|union) declarations.
-# If set to NO (the default) these declarations will be included in the
-# documentation.
+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend
+# (class|struct|union) declarations. If set to NO, these declarations will be
+# included in the documentation.
+# The default value is: NO.
HIDE_FRIEND_COMPOUNDS = NO
-# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any
-# documentation blocks found inside the body of a function.
-# If set to NO (the default) these blocks will be appended to the
-# function's detailed documentation block.
+# If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any
+# documentation blocks found inside the body of a function. If set to NO, these
+# blocks will be appended to the function's detailed documentation block.
+# The default value is: NO.
HIDE_IN_BODY_DOCS = NO
-# The INTERNAL_DOCS tag determines if documentation
-# that is typed after a \internal command is included. If the tag is set
-# to NO (the default) then the documentation will be excluded.
-# Set it to YES to include the internal documentation.
+# The INTERNAL_DOCS tag determines if documentation that is typed after a
+# \internal command is included. If the tag is set to NO then the documentation
+# will be excluded. Set it to YES to include the internal documentation.
+# The default value is: NO.
INTERNAL_DOCS = YES
-# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate
-# file names in lower-case letters. If set to YES upper-case letters are also
+# If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file
+# names in lower-case letters. If set to YES, upper-case letters are also
# allowed. This is useful if you have classes or files whose names only differ
# in case and if your file system supports case sensitive file names. Windows
# and Mac users are advised to set this option to NO.
+# The default value is: system dependent.
CASE_SENSE_NAMES = YES
-# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen
-# will show members with their full class and namespace scopes in the
-# documentation. If set to YES the scope will be hidden.
+# If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with
+# their full class and namespace scopes in the documentation. If set to YES, the
+# scope will be hidden.
+# The default value is: NO.
HIDE_SCOPE_NAMES = NO
-# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen
-# will put a list of the files that are included by a file in the documentation
-# of that file.
+# If the HIDE_COMPOUND_REFERENCE tag is set to NO (default) then doxygen will
+# append additional text to a page's title, such as Class Reference. If set to
+# YES the compound reference will be hidden.
+# The default value is: NO.
+
+HIDE_COMPOUND_REFERENCE= NO
+
+# If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of
+# the files that are included by a file in the documentation of that file.
+# The default value is: YES.
SHOW_INCLUDE_FILES = YES
-# If the FORCE_LOCAL_INCLUDES tag is set to YES then Doxygen
-# will list include files with double quotes in the documentation
-# rather than with sharp brackets.
+# If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each
+# grouped member an include statement to the documentation, telling the reader
+# which file to include in order to use the member.
+# The default value is: NO.
+
+SHOW_GROUPED_MEMB_INC = NO
+
+# If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include
+# files with double quotes in the documentation rather than with sharp brackets.
+# The default value is: NO.
FORCE_LOCAL_INCLUDES = NO
-# If the INLINE_INFO tag is set to YES (the default) then a tag [inline]
-# is inserted in the documentation for inline members.
+# If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the
+# documentation for inline members.
+# The default value is: YES.
INLINE_INFO = YES
-# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen
-# will sort the (detailed) documentation of file and class members
-# alphabetically by member name. If set to NO the members will appear in
-# declaration order.
+# If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the
+# (detailed) documentation of file and class members alphabetically by member
+# name. If set to NO, the members will appear in declaration order.
+# The default value is: YES.
SORT_MEMBER_DOCS = YES
-# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the
-# brief documentation of file, namespace and class members alphabetically
-# by member name. If set to NO (the default) the members will appear in
-# declaration order.
+# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief
+# descriptions of file, namespace and class members alphabetically by member
+# name. If set to NO, the members will appear in declaration order. Note that
+# this will also influence the order of the classes in the class list.
+# The default value is: NO.
SORT_BRIEF_DOCS = NO
-# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen
-# will sort the (brief and detailed) documentation of class members so that
-# constructors and destructors are listed first. If set to NO (the default)
-# the constructors will appear in the respective orders defined by
-# SORT_MEMBER_DOCS and SORT_BRIEF_DOCS.
-# This tag will be ignored for brief docs if SORT_BRIEF_DOCS is set to NO
-# and ignored for detailed docs if SORT_MEMBER_DOCS is set to NO.
+# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the
+# (brief and detailed) documentation of class members so that constructors and
+# destructors are listed first. If set to NO the constructors will appear in the
+# respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS.
+# Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief
+# member documentation.
+# Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting
+# detailed member documentation.
+# The default value is: NO.
SORT_MEMBERS_CTORS_1ST = NO
-# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the
-# hierarchy of group names into alphabetical order. If set to NO (the default)
-# the group names will appear in their defined order.
+# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy
+# of group names into alphabetical order. If set to NO the group names will
+# appear in their defined order.
+# The default value is: NO.
SORT_GROUP_NAMES = NO
-# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be
-# sorted by fully-qualified names, including namespaces. If set to
-# NO (the default), the class list will be sorted only by class name,
-# not including the namespace part.
+# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by
+# fully-qualified names, including namespaces. If set to NO, the class list will
+# be sorted only by class name, not including the namespace part.
# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
-# Note: This option applies only to the class list, not to the
-# alphabetical list.
+# Note: This option applies only to the class list, not to the alphabetical
+# list.
+# The default value is: NO.
SORT_BY_SCOPE_NAME = NO
-# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to
-# do proper type resolution of all parameters of a function it will reject a
-# match between the prototype and the implementation of a member function even
-# if there is only one candidate or it is obvious which candidate to choose
-# by doing a simple string match. By disabling STRICT_PROTO_MATCHING doxygen
-# will still accept a match between prototype and implementation in such cases.
+# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper
+# type resolution of all parameters of a function it will reject a match between
+# the prototype and the implementation of a member function even if there is
+# only one candidate or it is obvious which candidate to choose by doing a
+# simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still
+# accept a match between prototype and implementation in such cases.
+# The default value is: NO.
STRICT_PROTO_MATCHING = NO
-# The GENERATE_TODOLIST tag can be used to enable (YES) or
-# disable (NO) the todo list. This list is created by putting \todo
-# commands in the documentation.
+# The GENERATE_TODOLIST tag can be used to enable (YES) or disable (NO) the todo
+# list. This list is created by putting \todo commands in the documentation.
+# The default value is: YES.
GENERATE_TODOLIST = YES
-# The GENERATE_TESTLIST tag can be used to enable (YES) or
-# disable (NO) the test list. This list is created by putting \test
-# commands in the documentation.
+# The GENERATE_TESTLIST tag can be used to enable (YES) or disable (NO) the test
+# list. This list is created by putting \test commands in the documentation.
+# The default value is: YES.
GENERATE_TESTLIST = YES
-# The GENERATE_BUGLIST tag can be used to enable (YES) or
-# disable (NO) the bug list. This list is created by putting \bug
-# commands in the documentation.
+# The GENERATE_BUGLIST tag can be used to enable (YES) or disable (NO) the bug
+# list. This list is created by putting \bug commands in the documentation.
+# The default value is: YES.
GENERATE_BUGLIST = YES
-# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or
-# disable (NO) the deprecated list. This list is created by putting
-# \deprecated commands in the documentation.
+# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or disable (NO)
+# the deprecated list. This list is created by putting \deprecated commands in
+# the documentation.
+# The default value is: YES.
GENERATE_DEPRECATEDLIST= YES
-# The ENABLED_SECTIONS tag can be used to enable conditional
-# documentation sections, marked by \if section-label ... \endif
-# and \cond section-label ... \endcond blocks.
+# The ENABLED_SECTIONS tag can be used to enable conditional documentation
+# sections, marked by \if <section_label> ... \endif and \cond <section_label>
+# ... \endcond blocks.
ENABLED_SECTIONS =
-# The MAX_INITIALIZER_LINES tag determines the maximum number of lines
-# the initial value of a variable or macro consists of for it to appear in
-# the documentation. If the initializer consists of more lines than specified
-# here it will be hidden. Use a value of 0 to hide initializers completely.
-# The appearance of the initializer of individual variables and macros in the
-# documentation can be controlled using \showinitializer or \hideinitializer
-# command in the documentation regardless of this setting.
+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the
+# initial value of a variable or macro / define can have for it to appear in the
+# documentation. If the initializer consists of more lines than specified here
+# it will be hidden. Use a value of 0 to hide initializers completely. The
+# appearance of the value of individual variables and macros / defines can be
+# controlled using \showinitializer or \hideinitializer command in the
+# documentation regardless of this setting.
+# Minimum value: 0, maximum value: 10000, default value: 30.
MAX_INITIALIZER_LINES = 30
-# Set the SHOW_USED_FILES tag to NO to disable the list of files generated
-# at the bottom of the documentation of classes and structs. If set to YES the
+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated at
+# the bottom of the documentation of classes and structs. If set to YES, the
# list will mention the files that were used to generate the documentation.
+# The default value is: YES.
SHOW_USED_FILES = YES
-# Set the SHOW_FILES tag to NO to disable the generation of the Files page.
-# This will remove the Files entry from the Quick Index and from the
-# Folder Tree View (if specified). The default is YES.
+# Set the SHOW_FILES tag to NO to disable the generation of the Files page. This
+# will remove the Files entry from the Quick Index and from the Folder Tree View
+# (if specified).
+# The default value is: YES.
SHOW_FILES = YES
-# Set the SHOW_NAMESPACES tag to NO to disable the generation of the
-# Namespaces page.
-# This will remove the Namespaces entry from the Quick Index
-# and from the Folder Tree View (if specified). The default is YES.
+# Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces
+# page. This will remove the Namespaces entry from the Quick Index and from the
+# Folder Tree View (if specified).
+# The default value is: YES.
SHOW_NAMESPACES = YES
# The FILE_VERSION_FILTER tag can be used to specify a program or script that
# doxygen should invoke to get the current version for each file (typically from
# the version control system). Doxygen will invoke the program by executing (via
-# popen()) the command <command> <input-file>, where <command> is the value of
-# the FILE_VERSION_FILTER tag, and <input-file> is the name of an input file
-# provided by doxygen. Whatever the program writes to standard output
-# is used as the file version. See the manual for examples.
+# popen()) the command command input-file, where command is the value of the
+# FILE_VERSION_FILTER tag, and input-file is the name of an input file provided
+# by doxygen. Whatever the program writes to standard output is used as the file
+# version. For an example see the documentation.
FILE_VERSION_FILTER =
# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed
# by doxygen. The layout file controls the global structure of the generated
# output files in an output format independent way. To create the layout file
-# that represents doxygen's defaults, run doxygen with the -l option.
-# You can optionally specify a file name after the option, if omitted
-# DoxygenLayout.xml will be used as the name of the layout file.
+# that represents doxygen's defaults, run doxygen with the -l option. You can
+# optionally specify a file name after the option, if omitted DoxygenLayout.xml
+# will be used as the name of the layout file.
+#
+# Note that if you run doxygen from a directory containing a file called
+# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE
+# tag is left empty.
LAYOUT_FILE =
-# The CITE_BIB_FILES tag can be used to specify one or more bib files
-# containing the references data. This must be a list of .bib files. The
-# .bib extension is automatically appended if omitted. Using this command
-# requires the bibtex tool to be installed. See also
-# http://en.wikipedia.org/wiki/BibTeX for more info. For LaTeX the style
-# of the bibliography can be controlled using LATEX_BIB_STYLE. To use this
-# feature you need bibtex and perl available in the search path. Do not use
-# file names with spaces, bibtex cannot handle them.
+# The CITE_BIB_FILES tag can be used to specify one or more bib files containing
+# the reference definitions. This must be a list of .bib files. The .bib
+# extension is automatically appended if omitted. This requires the bibtex tool
+# to be installed. See also http://en.wikipedia.org/wiki/BibTeX for more info.
+# For LaTeX the style of the bibliography can be controlled using
+# LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the
+# search path. See also \cite for info how to create references.
CITE_BIB_FILES =
#---------------------------------------------------------------------------
-# configuration options related to warning and progress messages
+# Configuration options related to warning and progress messages
#---------------------------------------------------------------------------
-# The QUIET tag can be used to turn on/off the messages that are generated
-# by doxygen. Possible values are YES and NO. If left blank NO is used.
+# The QUIET tag can be used to turn on/off the messages that are generated to
+# standard output by doxygen. If QUIET is set to YES this implies that the
+# messages are off.
+# The default value is: NO.
QUIET = NO
# The WARNINGS tag can be used to turn on/off the warning messages that are
-# generated by doxygen. Possible values are YES and NO. If left blank
-# NO is used.
+# generated to standard error (stderr) by doxygen. If WARNINGS is set to YES
+# this implies that the warnings are on.
+#
+# Tip: Turn warnings on while writing the documentation.
+# The default value is: YES.
WARNINGS = YES
-# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings
-# for undocumented members. If EXTRACT_ALL is set to YES then this flag will
-# automatically be disabled.
+# If the WARN_IF_UNDOCUMENTED tag is set to YES then doxygen will generate
+# warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag
+# will automatically be disabled.
+# The default value is: YES.
WARN_IF_UNDOCUMENTED = YES
-# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for
-# potential errors in the documentation, such as not documenting some
-# parameters in a documented function, or documenting parameters that
-# don't exist or using markup commands wrongly.
+# If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for
+# potential errors in the documentation, such as not documenting some parameters
+# in a documented function, or documenting parameters that don't exist or using
+# markup commands wrongly.
+# The default value is: YES.
WARN_IF_DOC_ERROR = YES
-# The WARN_NO_PARAMDOC option can be enabled to get warnings for
-# functions that are documented, but have no documentation for their parameters
-# or return value. If set to NO (the default) doxygen will only warn about
-# wrong or incomplete parameter documentation, but not about the absence of
-# documentation.
+# This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that
+# are documented, but have no documentation for their parameters or return
+# value. If set to NO, doxygen will only warn about wrong or incomplete
+# parameter documentation, but not about the absence of documentation.
+# The default value is: NO.
WARN_NO_PARAMDOC = NO
-# The WARN_FORMAT tag determines the format of the warning messages that
-# doxygen can produce. The string should contain the $file, $line, and $text
-# tags, which will be replaced by the file and line number from which the
-# warning originated and the warning text. Optionally the format may contain
-# $version, which will be replaced by the version of the file (if it could
-# be obtained via FILE_VERSION_FILTER)
+# The WARN_FORMAT tag determines the format of the warning messages that doxygen
+# can produce. The string should contain the $file, $line, and $text tags, which
+# will be replaced by the file and line number from which the warning originated
+# and the warning text. Optionally the format may contain $version, which will
+# be replaced by the version of the file (if it could be obtained via
+# FILE_VERSION_FILTER)
+# The default value is: $file:$line: $text.
WARN_FORMAT = "$file:$line: $text"
-# The WARN_LOGFILE tag can be used to specify a file to which warning
-# and error messages should be written. If left blank the output is written
-# to stderr.
+# The WARN_LOGFILE tag can be used to specify a file to which warning and error
+# messages should be written. If left blank the output is written to standard
+# error (stderr).
WARN_LOGFILE =
#---------------------------------------------------------------------------
-# configuration options related to the input files
+# Configuration options related to the input files
#---------------------------------------------------------------------------
-# The INPUT tag can be used to specify the files and/or directories that contain
-# documented source files. You may enter file names like "myfile.cpp" or
-# directories like "/usr/src/myproject". Separate the files or directories
-# with spaces.
+# The INPUT tag is used to specify the files and/or directories that contain
+# documented source files. You may enter file names like myfile.cpp or
+# directories like /usr/src/myproject. Separate the files or directories with
+# spaces.
+# Note: If this tag is empty the current directory is searched.
-INPUT = doxygen.main \
- doxygen.source \
- doxygen.intern \
- doxygen.extern \
+INPUT = doxygen.main.h \
+ doxygen.source.h \
+ doxygen.intern.h \
+ doxygen.extern.h \
../../source \
../../intern \
../../extern/bullet2
# This tag can be used to specify the character encoding of the source files
-# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is
-# also the default input encoding. Doxygen uses libiconv (or the iconv built
-# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for
-# the list of possible encodings.
+# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
+# libiconv (or the iconv built into libc) for the transcoding. See the libiconv
+# documentation (see: http://www.gnu.org/software/libiconv) for the list of
+# possible encodings.
+# The default value is: UTF-8.
INPUT_ENCODING = UTF-8
# If the value of the INPUT tag contains directories, you can use the
-# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
-# and *.h) to filter out the source-files in the directories. If left
-# blank the following patterns are tested:
-# *.c *.cc *.cxx *.cpp *.c++ *.d *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh
-# *.hxx *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.dox *.py
-# *.f90 *.f *.for *.vhd *.vhdl
+# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and
+# *.h) to filter out the source-files in the directories. If left blank the
+# following patterns are tested:*.c, *.cc, *.cxx, *.cpp, *.c++, *.java, *.ii,
+# *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, *.hh, *.hxx, *.hpp,
+# *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc, *.m, *.markdown,
+# *.md, *.mm, *.dox, *.py, *.f90, *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf,
+# *.qsf, *.as and *.js.
FILE_PATTERNS =
-# The RECURSIVE tag can be used to turn specify whether or not subdirectories
-# should be searched for input files as well. Possible values are YES and NO.
-# If left blank NO is used.
+# The RECURSIVE tag can be used to specify whether or not subdirectories should
+# be searched for input files as well.
+# The default value is: NO.
RECURSIVE = YES
# The EXCLUDE tag can be used to specify files and/or directories that should be
# excluded from the INPUT source files. This way you can easily exclude a
# subdirectory from a directory tree whose root is specified with the INPUT tag.
+#
# Note that relative paths are relative to the directory from which doxygen is
# run.
@@ -708,14 +815,16 @@ EXCLUDE = ../../build_files, \
# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or
# directories that are symbolic links (a Unix file system feature) are excluded
# from the input.
+# The default value is: NO.
EXCLUDE_SYMLINKS = NO
# If the value of the INPUT tag contains directories, you can use the
# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
-# certain files from those directories. Note that the wildcards are matched
-# against the file with absolute path, so to exclude all test directories
-# for example use the pattern */test/*
+# certain files from those directories.
+#
+# Note that the wildcards are matched against the file with absolute path, so to
+# exclude all test directories for example use the pattern */test/*
EXCLUDE_PATTERNS = .svn \
.git \
@@ -726,42 +835,49 @@ EXCLUDE_PATTERNS = .svn \
# output. The symbol name can be a fully qualified name, a word, or if the
# wildcard * is used, a substring. Examples: ANamespace, AClass,
# AClass::ANamespace, ANamespace::*Test
+#
+# Note that the wildcards are matched against the file with absolute path, so to
+# exclude all test directories use the pattern */test/*
EXCLUDE_SYMBOLS =
-# The EXAMPLE_PATH tag can be used to specify one or more files or
-# directories that contain example code fragments that are included (see
-# the \include command).
+# The EXAMPLE_PATH tag can be used to specify one or more files or directories
+# that contain example code fragments that are included (see the \include
+# command).
EXAMPLE_PATH =
# If the value of the EXAMPLE_PATH tag contains directories, you can use the
-# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
-# and *.h) to filter out the source-files in the directories. If left
-# blank all files are included.
+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and
+# *.h) to filter out the source-files in the directories. If left blank all
+# files are included.
EXAMPLE_PATTERNS =
# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
-# searched for input files to be used with the \include or \dontinclude
-# commands irrespective of the value of the RECURSIVE tag.
-# Possible values are YES and NO. If left blank NO is used.
+# searched for input files to be used with the \include or \dontinclude commands
+# irrespective of the value of the RECURSIVE tag.
+# The default value is: NO.
EXAMPLE_RECURSIVE = NO
-# The IMAGE_PATH tag can be used to specify one or more files or
-# directories that contain image that are included in the documentation (see
-# the \image command).
+# The IMAGE_PATH tag can be used to specify one or more files or directories
+# that contain images that are to be included in the documentation (see the
+# \image command).
IMAGE_PATH =
# The INPUT_FILTER tag can be used to specify a program that doxygen should
# invoke to filter for each input file. Doxygen will invoke the filter program
-# by executing (via popen()) the command <filter> <input-file>, where <filter>
-# is the value of the INPUT_FILTER tag, and <input-file> is the name of an
-# input file. Doxygen will then use the output that the filter program writes
-# to standard output.
-# If FILTER_PATTERNS is specified, this tag will be ignored.
+# by executing (via popen()) the command:
+#
+# <filter> <input-file>
+#
+# where <filter> is the value of the INPUT_FILTER tag, and <input-file> is the
+# name of an input file. Doxygen will then use the output that the filter
+# program writes to standard output. If FILTER_PATTERNS is specified, this tag
+# will be ignored.
+#
# Note that the filter must not add or remove lines; it is applied before the
# code is scanned, but not when the output code is generated. If lines are added
# or removed, the anchors will not be placed correctly.
@@ -769,172 +885,224 @@ IMAGE_PATH =
INPUT_FILTER =
# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
-# basis.
-# Doxygen will compare the file name with each pattern and apply the
-# filter if there is a match.
-# The filters are a list of the form:
-# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further
-# info on how filters are used. If FILTER_PATTERNS is empty or if
-# non of the patterns match the file name, INPUT_FILTER is applied.
+# basis. Doxygen will compare the file name with each pattern and apply the
+# filter if there is a match. The filters are a list of the form: pattern=filter
+# (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how
+# filters are used. If the FILTER_PATTERNS tag is empty or if none of the
+# patterns match the file name, INPUT_FILTER is applied.
FILTER_PATTERNS =
# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
-# INPUT_FILTER) will be used to filter the input files when producing source
-# files to browse (i.e. when SOURCE_BROWSER is set to YES).
+# INPUT_FILTER) will also be used to filter the input files that are used for
+# producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES).
+# The default value is: NO.
FILTER_SOURCE_FILES = NO
# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file
-# pattern. A pattern will override the setting for FILTER_PATTERN (if any)
-# and it is also possible to disable source filtering for a specific pattern
-# using *.ext= (so without naming a filter). This option only has effect when
-# FILTER_SOURCE_FILES is enabled.
+# pattern. A pattern will override the setting for FILTER_PATTERN (if any) and
+# it is also possible to disable source filtering for a specific pattern using
+# *.ext= (so without naming a filter).
+# This tag requires that the tag FILTER_SOURCE_FILES is set to YES.
FILTER_SOURCE_PATTERNS =
-# If the USE_MD_FILE_AS_MAINPAGE tag refers to the name of a markdown file that
+# If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that
# is part of the input, its contents will be placed on the main page
# (index.html). This can be useful if you have a project on for instance GitHub
-# and want reuse the introduction page also for the doxygen output.
+# and want to reuse the introduction page also for the doxygen output.
-USE_MDFILE_AS_MAINPAGE =
+# USE_MDFILE_AS_MAINPAGE =
#---------------------------------------------------------------------------
-# configuration options related to source browsing
+# Configuration options related to source browsing
#---------------------------------------------------------------------------
-# If the SOURCE_BROWSER tag is set to YES then a list of source files will
-# be generated. Documented entities will be cross-referenced with these sources.
-# Note: To get rid of all source code in the generated output, make sure also
-# VERBATIM_HEADERS is set to NO.
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will be
+# generated. Documented entities will be cross-referenced with these sources.
+#
+# Note: To get rid of all source code in the generated output, make sure that
+# also VERBATIM_HEADERS is set to NO.
+# The default value is: NO.
SOURCE_BROWSER = YES
-# Setting the INLINE_SOURCES tag to YES will include the body
-# of functions and classes directly in the documentation.
+# Setting the INLINE_SOURCES tag to YES will include the body of functions,
+# classes and enums directly into the documentation.
+# The default value is: NO.
INLINE_SOURCES = NO
-# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct
-# doxygen to hide any special comment blocks from generated source code
-# fragments. Normal C, C++ and Fortran comments will always remain visible.
+# Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any
+# special comment blocks from generated source code fragments. Normal C, C++ and
+# Fortran comments will always remain visible.
+# The default value is: YES.
STRIP_CODE_COMMENTS = YES
-# If the REFERENCED_BY_RELATION tag is set to YES
-# then for each documented function all documented
-# functions referencing it will be listed.
+# If the REFERENCED_BY_RELATION tag is set to YES then for each documented
+# function all documented functions referencing it will be listed.
+# The default value is: NO.
REFERENCED_BY_RELATION = YES
-# If the REFERENCES_RELATION tag is set to YES
-# then for each documented function all documented entities
-# called/used by that function will be listed.
+# If the REFERENCES_RELATION tag is set to YES then for each documented function
+# all documented entities called/used by that function will be listed.
+# The default value is: NO.
REFERENCES_RELATION = YES
-# If the REFERENCES_LINK_SOURCE tag is set to YES (the default)
-# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from
-# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will
-# link to the source code.
-# Otherwise they will link to the documentation.
+# If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set
+# to YES then the hyperlinks from functions in REFERENCES_RELATION and
+# REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will
+# link to the documentation.
+# The default value is: YES.
REFERENCES_LINK_SOURCE = YES
-# If the USE_HTAGS tag is set to YES then the references to source code
-# will point to the HTML generated by the htags(1) tool instead of doxygen
-# built-in source browser. The htags tool is part of GNU's global source
-# tagging system (see http://www.gnu.org/software/global/global.html). You
-# will need version 4.8.6 or higher.
+# If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the
+# source code will show a tooltip with additional information such as prototype,
+# brief description and links to the definition and documentation. Since this
+# will make the HTML file larger and loading of large files a bit slower, you
+# can opt to disable this feature.
+# The default value is: YES.
+# This tag requires that the tag SOURCE_BROWSER is set to YES.
+
+SOURCE_TOOLTIPS = YES
+
+# If the USE_HTAGS tag is set to YES then the references to source code will
+# point to the HTML generated by the htags(1) tool instead of doxygen built-in
+# source browser. The htags tool is part of GNU's global source tagging system
+# (see http://www.gnu.org/software/global/global.html). You will need version
+# 4.8.6 or higher.
+#
+# To use it do the following:
+# - Install the latest version of global
+# - Enable SOURCE_BROWSER and USE_HTAGS in the config file
+# - Make sure the INPUT points to the root of the source tree
+# - Run doxygen as normal
+#
+# Doxygen will invoke htags (and that will in turn invoke gtags), so these
+# tools must be available from the command line (i.e. in the search path).
+#
+# The result: instead of the source browser generated by doxygen, the links to
+# source code will now point to the output of htags.
+# The default value is: NO.
+# This tag requires that the tag SOURCE_BROWSER is set to YES.
USE_HTAGS = NO
-# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen
-# will generate a verbatim copy of the header file for each class for
-# which an include is specified. Set to NO to disable this.
+# If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a
+# verbatim copy of the header file for each class for which an include is
+# specified. Set to NO to disable this.
+# See also: Section \class.
+# The default value is: YES.
VERBATIM_HEADERS = YES
#---------------------------------------------------------------------------
-# configuration options related to the alphabetical class index
+# Configuration options related to the alphabetical class index
#---------------------------------------------------------------------------
-# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index
-# of all compounds will be generated. Enable this if the project
-# contains a lot of classes, structs, unions or interfaces.
+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all
+# compounds will be generated. Enable this if the project contains a lot of
+# classes, structs, unions or interfaces.
+# The default value is: YES.
ALPHABETICAL_INDEX = YES
-# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then
-# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns
-# in which this list will be split (can be a number in the range [1..20])
+# The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in
+# which the alphabetical index list will be split.
+# Minimum value: 1, maximum value: 20, default value: 5.
+# This tag requires that the tag ALPHABETICAL_INDEX is set to YES.
COLS_IN_ALPHA_INDEX = 5
-# In case all classes in a project start with a common prefix, all
-# classes will be put under the same header in the alphabetical index.
-# The IGNORE_PREFIX tag can be used to specify one or more prefixes that
-# should be ignored while generating the index headers.
+# In case all classes in a project start with a common prefix, all classes will
+# be put under the same header in the alphabetical index. The IGNORE_PREFIX tag
+# can be used to specify a prefix (or a list of prefixes) that should be ignored
+# while generating the index headers.
+# This tag requires that the tag ALPHABETICAL_INDEX is set to YES.
IGNORE_PREFIX =
#---------------------------------------------------------------------------
-# configuration options related to the HTML output
+# Configuration options related to the HTML output
#---------------------------------------------------------------------------
-# If the GENERATE_HTML tag is set to YES (the default) Doxygen will
-# generate HTML output.
+# If the GENERATE_HTML tag is set to YES, doxygen will generate HTML output
+# The default value is: YES.
GENERATE_HTML = YES
-# The HTML_OUTPUT tag is used to specify where the HTML docs will be put.
-# If a relative path is entered the value of OUTPUT_DIRECTORY will be
-# put in front of it. If left blank `html' will be used as the default path.
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: html.
+# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_OUTPUT = html
-# The HTML_FILE_EXTENSION tag can be used to specify the file extension for
-# each generated HTML page (for example: .htm,.php,.asp). If it is left blank
-# doxygen will generate files with .html extension.
+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each
+# generated HTML page (for example: .htm, .php, .asp).
+# The default value is: .html.
+# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_FILE_EXTENSION = .html
-# The HTML_HEADER tag can be used to specify a personal HTML header for
-# each generated HTML page. If it is left blank doxygen will generate a
-# standard header. Note that when using a custom header you are responsible
-# for the proper inclusion of any scripts and style sheets that doxygen
-# needs, which is dependent on the configuration options used.
-# It is advised to generate a default header using "doxygen -w html
-# header.html footer.html stylesheet.css YourConfigFile" and then modify
-# that header. Note that the header is subject to change so you typically
-# have to redo this when upgrading to a newer version of doxygen or when
-# changing the value of configuration settings such as GENERATE_TREEVIEW!
+# The HTML_HEADER tag can be used to specify a user-defined HTML header file for
+# each generated HTML page. If the tag is left blank doxygen will generate a
+# standard header.
+#
+# To get valid HTML the header file that includes any scripts and style sheets
+# that doxygen needs, which is dependent on the configuration options used (e.g.
+# the setting GENERATE_TREEVIEW). It is highly recommended to start with a
+# default header using
+# doxygen -w html new_header.html new_footer.html new_stylesheet.css
+# YourConfigFile
+# and then modify the file new_header.html. See also section "Doxygen usage"
+# for information on how to generate the default header that doxygen normally
+# uses.
+# Note: The header is subject to change so you typically have to regenerate the
+# default header when upgrading to a newer version of doxygen. For a description
+# of the possible markers and block names see the documentation.
+# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_HEADER =
-# The HTML_FOOTER tag can be used to specify a personal HTML footer for
-# each generated HTML page. If it is left blank doxygen will generate a
-# standard footer.
+# The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each
+# generated HTML page. If the tag is left blank doxygen will generate a standard
+# footer. See HTML_HEADER for more information on how to generate a default
+# footer and what special commands can be used inside the footer. See also
+# section "Doxygen usage" for information on how to generate the default footer
+# that doxygen normally uses.
+# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_FOOTER = footer.html
-# The HTML_STYLESHEET tag can be used to specify a user-defined cascading
-# style sheet that is used by each HTML page. It can be used to
-# fine-tune the look of the HTML output. If left blank doxygen will
-# generate a default style sheet. Note that it is recommended to use
-# HTML_EXTRA_STYLESHEET instead of this one, as it is more robust and this
-# tag will in the future become obsolete.
+# The HTML_STYLESHEET tag can be used to specify a user-defined cascading style
+# sheet that is used by each HTML page. It can be used to fine-tune the look of
+# the HTML output. If left blank doxygen will generate a default style sheet.
+# See also section "Doxygen usage" for information on how to generate the style
+# sheet that doxygen normally uses.
+# Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as
+# it is more robust and this tag (HTML_STYLESHEET) will in the future become
+# obsolete.
+# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_STYLESHEET =
-# The HTML_EXTRA_STYLESHEET tag can be used to specify an additional
-# user-defined cascading style sheet that is included after the standard
-# style sheets created by doxygen. Using this option one can overrule
-# certain style aspects. This is preferred over using HTML_STYLESHEET
-# since it does not replace the standard style sheet and is therefor more
-# robust against future updates. Doxygen will copy the style sheet file to
-# the output directory.
+# The HTML_EXTRA_STYLESHEET tag can be used to specify additional user-defined
+# cascading style sheets that are included after the standard style sheets
+# created by doxygen. Using this option one can overrule certain style aspects.
+# This is preferred over using HTML_STYLESHEET since it does not replace the
+# standard style sheet and is therefore more robust against future updates.
+# Doxygen will copy the style sheet files to the output directory.
+# Note: The order of the extra style sheet files is of importance (e.g. the last
+# style sheet in the list overrules the setting of the previous ones in the
+# list). For an example see the documentation.
+# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_EXTRA_STYLESHEET =
@@ -942,632 +1110,835 @@ HTML_EXTRA_STYLESHEET =
# other source files which should be copied to the HTML output directory. Note
# that these files will be copied to the base HTML output directory. Use the
# $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these
-# files. In the HTML_STYLESHEET file, use the file name only. Also note that
-# the files will be copied as-is; there are no commands or markers available.
+# files. In the HTML_STYLESHEET file, use the file name only. Also note that the
+# files will be copied as-is; there are no commands or markers available.
+# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_EXTRA_FILES =
-# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output.
-# Doxygen will adjust the colors in the style sheet and background images
-# according to this color. Hue is specified as an angle on a colorwheel,
-# see http://en.wikipedia.org/wiki/Hue for more information.
-# For instance the value 0 represents red, 60 is yellow, 120 is green,
-# 180 is cyan, 240 is blue, 300 purple, and 360 is red again.
-# The allowed range is 0 to 359.
+# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen
+# will adjust the colors in the style sheet and background images according to
+# this color. Hue is specified as an angle on a colorwheel, see
+# http://en.wikipedia.org/wiki/Hue for more information. For instance the value
+# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300
+# purple, and 360 is red again.
+# Minimum value: 0, maximum value: 359, default value: 220.
+# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_COLORSTYLE_HUE = 220
-# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of
-# the colors in the HTML output. For a value of 0 the output will use
-# grayscales only. A value of 255 will produce the most vivid colors.
+# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors
+# in the HTML output. For a value of 0 the output will use grayscales only. A
+# value of 255 will produce the most vivid colors.
+# Minimum value: 0, maximum value: 255, default value: 100.
+# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_COLORSTYLE_SAT = 100
-# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to
-# the luminance component of the colors in the HTML output. Values below
-# 100 gradually make the output lighter, whereas values above 100 make
-# the output darker. The value divided by 100 is the actual gamma applied,
-# so 80 represents a gamma of 0.8, The value 220 represents a gamma of 2.2,
-# and 100 does not change the gamma.
+# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the
+# luminance component of the colors in the HTML output. Values below 100
+# gradually make the output lighter, whereas values above 100 make the output
+# darker. The value divided by 100 is the actual gamma applied, so 80 represents
+# a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not
+# change the gamma.
+# Minimum value: 40, maximum value: 240, default value: 80.
+# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_COLORSTYLE_GAMMA = 79
# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML
-# page will contain the date and time when the page was generated. Setting
-# this to NO can help when comparing the output of multiple runs.
+# page will contain the date and time when the page was generated. Setting this
+# to NO can help when comparing the output of multiple runs.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_TIMESTAMP = YES
# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
# documentation will contain sections that can be hidden and shown after the
# page has loaded.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_DYNAMIC_SECTIONS = NO
-# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of
-# entries shown in the various tree structured indices initially; the user
-# can expand and collapse entries dynamically later on. Doxygen will expand
-# the tree to such a level that at most the specified number of entries are
-# visible (unless a fully collapsed tree already exceeds this amount).
-# So setting the number of entries 1 will produce a full collapsed tree by
-# default. 0 is a special value representing an infinite number of entries
-# and will result in a full expanded tree by default.
+# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries
+# shown in the various tree structured indices initially; the user can expand
+# and collapse entries dynamically later on. Doxygen will expand the tree to
+# such a level that at most the specified number of entries are visible (unless
+# a fully collapsed tree already exceeds this amount). So setting the number of
+# entries 1 will produce a full collapsed tree by default. 0 is a special value
+# representing an infinite number of entries and will result in a full expanded
+# tree by default.
+# Minimum value: 0, maximum value: 9999, default value: 100.
+# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_INDEX_NUM_ENTRIES = 100
-# If the GENERATE_DOCSET tag is set to YES, additional index files
-# will be generated that can be used as input for Apple's Xcode 3
-# integrated development environment, introduced with OSX 10.5 (Leopard).
-# To create a documentation set, doxygen will generate a Makefile in the
-# HTML output directory. Running make will produce the docset in that
-# directory and running "make install" will install the docset in
-# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find
-# it at startup.
-# See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html
+# If the GENERATE_DOCSET tag is set to YES, additional index files will be
+# generated that can be used as input for Apple's Xcode 3 integrated development
+# environment (see: http://developer.apple.com/tools/xcode/), introduced with
+# OSX 10.5 (Leopard). To create a documentation set, doxygen will generate a
+# Makefile in the HTML output directory. Running make will produce the docset in
+# that directory and running make install will install the docset in
+# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at
+# startup. See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html
# for more information.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
GENERATE_DOCSET = NO
-# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the
-# feed. A documentation feed provides an umbrella under which multiple
-# documentation sets from a single provider (such as a company or product suite)
-# can be grouped.
+# This tag determines the name of the docset feed. A documentation feed provides
+# an umbrella under which multiple documentation sets from a single provider
+# (such as a company or product suite) can be grouped.
+# The default value is: Doxygen generated docs.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
DOCSET_FEEDNAME = "Doxygen generated docs"
-# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that
-# should uniquely identify the documentation set bundle. This should be a
-# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen
-# will append .docset to the name.
+# This tag specifies a string that should uniquely identify the documentation
+# set bundle. This should be a reverse domain-name style string, e.g.
+# com.mycompany.MyDocSet. Doxygen will append .docset to the name.
+# The default value is: org.doxygen.Project.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
DOCSET_BUNDLE_ID = org.doxygen.Project
-# When GENERATE_PUBLISHER_ID tag specifies a string that should uniquely
-# identify the documentation publisher. This should be a reverse domain-name
-# style string, e.g. com.mycompany.MyDocSet.documentation.
+# The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify
+# the documentation publisher. This should be a reverse domain-name style
+# string, e.g. com.mycompany.MyDocSet.documentation.
+# The default value is: org.doxygen.Publisher.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
DOCSET_PUBLISHER_ID = org.doxygen.Publisher
-# The GENERATE_PUBLISHER_NAME tag identifies the documentation publisher.
+# The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher.
+# The default value is: Publisher.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
DOCSET_PUBLISHER_NAME = Publisher
-# If the GENERATE_HTMLHELP tag is set to YES, additional index files
-# will be generated that can be used as input for tools like the
-# Microsoft HTML help workshop to generate a compiled HTML help file (.chm)
-# of the generated HTML documentation.
+# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three
+# additional HTML index files: index.hhp, index.hhc, and index.hhk. The
+# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop
+# (see: http://www.microsoft.com/en-us/download/details.aspx?id=21138) on
+# Windows.
+#
+# The HTML Help Workshop contains a compiler that can convert all HTML output
+# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML
+# files are now used as the Windows 98 help format, and will replace the old
+# Windows help format (.hlp) on all Windows platforms in the future. Compressed
+# HTML files also contain an index, a table of contents, and you can search for
+# words in the documentation. The HTML workshop also contains a viewer for
+# compressed HTML files.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
GENERATE_HTMLHELP = YES
-# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can
-# be used to specify the file name of the resulting .chm file. You
-# can add a path in front of the file if the result should not be
+# The CHM_FILE tag can be used to specify the file name of the resulting .chm
+# file. You can add a path in front of the file if the result should not be
# written to the html output directory.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
CHM_FILE = blender.chm
-# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can
-# be used to specify the location (absolute path including file name) of
-# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run
-# the HTML help compiler on the generated index.hhp.
+# The HHC_LOCATION tag can be used to specify the location (absolute path
+# including file name) of the HTML help compiler (hhc.exe). If non-empty,
+# doxygen will try to run the HTML help compiler on the generated index.hhp.
+# The file has to be specified with full path.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
HHC_LOCATION = "C:/Program Files (x86)/HTML Help Workshop/hhc.exe"
-# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag
-# controls if a separate .chi index file is generated (YES) or that
-# it should be included in the master .chm file (NO).
+# The GENERATE_CHI flag controls if a separate .chi index file is generated
+# (YES) or that it should be included in the master .chm file (NO).
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
GENERATE_CHI = NO
-# If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING
-# is used to encode HtmlHelp index (hhk), content (hhc) and project file
-# content.
+# The CHM_INDEX_ENCODING is used to encode HtmlHelp index (hhk), content (hhc)
+# and project file content.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
CHM_INDEX_ENCODING =
-# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag
-# controls whether a binary table of contents is generated (YES) or a
-# normal table of contents (NO) in the .chm file.
+# The BINARY_TOC flag controls whether a binary table of contents is generated
+# (YES) or a normal table of contents (NO) in the .chm file. Furthermore it
+# enables the Previous and Next buttons.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
BINARY_TOC = NO
-# The TOC_EXPAND flag can be set to YES to add extra items for group members
-# to the contents of the HTML help documentation and to the tree view.
+# The TOC_EXPAND flag can be set to YES to add extra items for group members to
+# the table of contents of the HTML help documentation and to the tree view.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
TOC_EXPAND = NO
# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and
-# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated
-# that can be used as input for Qt's qhelpgenerator to generate a
-# Qt Compressed Help (.qch) of the generated HTML documentation.
+# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that
+# can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help
+# (.qch) of the generated HTML documentation.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
GENERATE_QHP = NO
-# If the QHG_LOCATION tag is specified, the QCH_FILE tag can
-# be used to specify the file name of the resulting .qch file.
-# The path specified is relative to the HTML output folder.
+# If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify
+# the file name of the resulting .qch file. The path specified is relative to
+# the HTML output folder.
+# This tag requires that the tag GENERATE_QHP is set to YES.
QCH_FILE =
-# The QHP_NAMESPACE tag specifies the namespace to use when generating
-# Qt Help Project output. For more information please see
-# http://doc.trolltech.com/qthelpproject.html#namespace
+# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help
+# Project output. For more information please see Qt Help Project / Namespace
+# (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#namespace).
+# The default value is: org.doxygen.Project.
+# This tag requires that the tag GENERATE_QHP is set to YES.
QHP_NAMESPACE = org.doxygen.Project
-# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating
-# Qt Help Project output. For more information please see
-# http://doc.trolltech.com/qthelpproject.html#virtual-folders
+# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt
+# Help Project output. For more information please see Qt Help Project / Virtual
+# Folders (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#virtual-
+# folders).
+# The default value is: doc.
+# This tag requires that the tag GENERATE_QHP is set to YES.
QHP_VIRTUAL_FOLDER = doc
-# If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to
-# add. For more information please see
-# http://doc.trolltech.com/qthelpproject.html#custom-filters
+# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom
+# filter to add. For more information please see Qt Help Project / Custom
+# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom-
+# filters).
+# This tag requires that the tag GENERATE_QHP is set to YES.
QHP_CUST_FILTER_NAME =
-# The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the
-# custom filter to add. For more information please see
-# <a href="http://doc.trolltech.com/qthelpproject.html#custom-filters">
-# Qt Help Project / Custom Filters</a>.
+# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the
+# custom filter to add. For more information please see Qt Help Project / Custom
+# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom-
+# filters).
+# This tag requires that the tag GENERATE_QHP is set to YES.
QHP_CUST_FILTER_ATTRS =
# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this
-# project's
-# filter section matches.
-# <a href="http://doc.trolltech.com/qthelpproject.html#filter-attributes">
-# Qt Help Project / Filter Attributes</a>.
+# project's filter section matches. Qt Help Project / Filter Attributes (see:
+# http://qt-project.org/doc/qt-4.8/qthelpproject.html#filter-attributes).
+# This tag requires that the tag GENERATE_QHP is set to YES.
QHP_SECT_FILTER_ATTRS =
-# If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can
-# be used to specify the location of Qt's qhelpgenerator.
-# If non-empty doxygen will try to run qhelpgenerator on the generated
-# .qhp file.
+# The QHG_LOCATION tag can be used to specify the location of Qt's
+# qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the
+# generated .qhp file.
+# This tag requires that the tag GENERATE_QHP is set to YES.
QHG_LOCATION =
-# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files
-# will be generated, which together with the HTML files, form an Eclipse help
-# plugin. To install this plugin and make it available under the help contents
-# menu in Eclipse, the contents of the directory containing the HTML and XML
-# files needs to be copied into the plugins directory of eclipse. The name of
-# the directory within the plugins directory should be the same as
-# the ECLIPSE_DOC_ID value. After copying Eclipse needs to be restarted before
-# the help appears.
+# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be
+# generated, together with the HTML files, they form an Eclipse help plugin. To
+# install this plugin and make it available under the help contents menu in
+# Eclipse, the contents of the directory containing the HTML and XML files needs
+# to be copied into the plugins directory of eclipse. The name of the directory
+# within the plugins directory should be the same as the ECLIPSE_DOC_ID value.
+# After copying Eclipse needs to be restarted before the help appears.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
GENERATE_ECLIPSEHELP = NO
-# A unique identifier for the eclipse help plugin. When installing the plugin
-# the directory name containing the HTML and XML files should also have
-# this name.
+# A unique identifier for the Eclipse help plugin. When installing the plugin
+# the directory name containing the HTML and XML files should also have this
+# name. Each documentation set should have its own identifier.
+# The default value is: org.doxygen.Project.
+# This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES.
ECLIPSE_DOC_ID = org.doxygen.Project
-# The DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs)
-# at top of each HTML page. The value NO (the default) enables the index and
-# the value YES disables it. Since the tabs have the same information as the
-# navigation tree you can set this option to NO if you already set
-# GENERATE_TREEVIEW to YES.
+# If you want full control over the layout of the generated HTML pages it might
+# be necessary to disable the index and replace it with your own. The
+# DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top
+# of each HTML page. A value of NO enables the index and the value YES disables
+# it. Since the tabs in the index contain the same information as the navigation
+# tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
DISABLE_INDEX = NO
# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index
-# structure should be generated to display hierarchical information.
-# If the tag value is set to YES, a side panel will be generated
-# containing a tree-like index structure (just like the one that
-# is generated for HTML Help). For this to work a browser that supports
-# JavaScript, DHTML, CSS and frames is required (i.e. any modern browser).
-# Windows users are probably better off using the HTML help feature.
-# Since the tree basically has the same information as the tab index you
-# could consider to set DISABLE_INDEX to NO when enabling this option.
+# structure should be generated to display hierarchical information. If the tag
+# value is set to YES, a side panel will be generated containing a tree-like
+# index structure (just like the one that is generated for HTML Help). For this
+# to work a browser that supports JavaScript, DHTML, CSS and frames is required
+# (i.e. any modern browser). Windows users are probably better off using the
+# HTML help feature. Via custom style sheets (see HTML_EXTRA_STYLESHEET) one can
+# further fine-tune the look of the index. As an example, the default style
+# sheet generated by doxygen has an example that shows how to put an image at
+# the root of the tree instead of the PROJECT_NAME. Since the tree basically has
+# the same information as the tab index, you could consider setting
+# DISABLE_INDEX to YES when enabling this option.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
GENERATE_TREEVIEW = NO
-# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values
-# (range [0,1..20]) that doxygen will group on one line in the generated HTML
-# documentation. Note that a value of 0 will completely suppress the enum
-# values from appearing in the overview section.
+# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that
+# doxygen will group on one line in the generated HTML documentation.
+#
+# Note that a value of 0 will completely suppress the enum values from appearing
+# in the overview section.
+# Minimum value: 0, maximum value: 20, default value: 4.
+# This tag requires that the tag GENERATE_HTML is set to YES.
ENUM_VALUES_PER_LINE = 4
-# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be
-# used to set the initial width (in pixels) of the frame in which the tree
-# is shown.
+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used
+# to set the initial width (in pixels) of the frame in which the tree is shown.
+# Minimum value: 0, maximum value: 1500, default value: 250.
+# This tag requires that the tag GENERATE_HTML is set to YES.
TREEVIEW_WIDTH = 246
-# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open
-# links to external symbols imported via tag files in a separate window.
+# If the EXT_LINKS_IN_WINDOW option is set to YES, doxygen will open links to
+# external symbols imported via tag files in a separate window.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
EXT_LINKS_IN_WINDOW = NO
-# Use this tag to change the font size of Latex formulas included
-# as images in the HTML documentation. The default is 10. Note that
-# when you change the font size after a successful doxygen run you need
-# to manually remove any form_*.png images from the HTML output directory
-# to force them to be regenerated.
+# Use this tag to change the font size of LaTeX formulas included as images in
+# the HTML documentation. When you change the font size after a successful
+# doxygen run you need to manually remove any form_*.png images from the HTML
+# output directory to force them to be regenerated.
+# Minimum value: 8, maximum value: 50, default value: 10.
+# This tag requires that the tag GENERATE_HTML is set to YES.
FORMULA_FONTSIZE = 10
# Use the FORMULA_TRANPARENT tag to determine whether or not the images
-# generated for formulas are transparent PNGs. Transparent PNGs are
-# not supported properly for IE 6.0, but are supported on all modern browsers.
-# Note that when changing this option you need to delete any form_*.png files
-# in the HTML output before the changes have effect.
+# generated for formulas are transparent PNGs. Transparent PNGs are not
+# supported properly for IE 6.0, but are supported on all modern browsers.
+#
+# Note that when changing this option you need to delete any form_*.png files in
+# the HTML output directory before the changes have effect.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_HTML is set to YES.
FORMULA_TRANSPARENT = YES
-# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax
-# (see http://www.mathjax.org) which uses client side Javascript for the
-# rendering instead of using prerendered bitmaps. Use this if you do not
-# have LaTeX installed or if you want to formulas look prettier in the HTML
-# output. When enabled you may also need to install MathJax separately and
-# configure the path to it using the MATHJAX_RELPATH option.
+# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see
+# http://www.mathjax.org) which uses client side Javascript for the rendering
+# instead of using pre-rendered bitmaps. Use this if you do not have LaTeX
+# installed or if you want to formulas look prettier in the HTML output. When
+# enabled you may also need to install MathJax separately and configure the path
+# to it using the MATHJAX_RELPATH option.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
USE_MATHJAX = NO
# When MathJax is enabled you can set the default output format to be used for
-# the MathJax output. Supported types are HTML-CSS, NativeMML (i.e. MathML) and
-# SVG. The default value is HTML-CSS, which is slower, but has the best
-# compatibility.
+# the MathJax output. See the MathJax site (see:
+# http://docs.mathjax.org/en/latest/output.html) for more details.
+# Possible values are: HTML-CSS (which is slower, but has the best
+# compatibility), NativeMML (i.e. MathML) and SVG.
+# The default value is: HTML-CSS.
+# This tag requires that the tag USE_MATHJAX is set to YES.
MATHJAX_FORMAT = HTML-CSS
-# When MathJax is enabled you need to specify the location relative to the
-# HTML output directory using the MATHJAX_RELPATH option. The destination
-# directory should contain the MathJax.js script. For instance, if the mathjax
-# directory is located at the same level as the HTML output directory, then
-# MATHJAX_RELPATH should be ../mathjax. The default value points to
-# the MathJax Content Delivery Network so you can quickly see the result without
-# installing MathJax.
-# However, it is strongly recommended to install a local
-# copy of MathJax from http://www.mathjax.org before deployment.
+# When MathJax is enabled you need to specify the location relative to the HTML
+# output directory using the MATHJAX_RELPATH option. The destination directory
+# should contain the MathJax.js script. For instance, if the mathjax directory
+# is located at the same level as the HTML output directory, then
+# MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax
+# Content Delivery Network so you can quickly see the result without installing
+# MathJax. However, it is strongly recommended to install a local copy of
+# MathJax from http://www.mathjax.org before deployment.
+# The default value is: http://cdn.mathjax.org/mathjax/latest.
+# This tag requires that the tag USE_MATHJAX is set to YES.
MATHJAX_RELPATH = http://www.mathjax.org/mathjax
-# The MATHJAX_EXTENSIONS tag can be used to specify one or MathJax extension
-# names that should be enabled during MathJax rendering.
+# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax
+# extension names that should be enabled during MathJax rendering. For example
+# MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols
+# This tag requires that the tag USE_MATHJAX is set to YES.
MATHJAX_EXTENSIONS =
-# The MATHJAX_CODEFILE tag can be used to specify a file with javascript
-# pieces of code that will be used on startup of the MathJax code.
+# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces
+# of code that will be used on startup of the MathJax code. See the MathJax site
+# (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an
+# example see the documentation.
+# This tag requires that the tag USE_MATHJAX is set to YES.
MATHJAX_CODEFILE =
-# When the SEARCHENGINE tag is enabled doxygen will generate a search box
-# for the HTML output. The underlying search engine uses javascript
-# and DHTML and should work on any modern browser. Note that when using
-# HTML help (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets
-# (GENERATE_DOCSET) there is already a search function so this one should
-# typically be disabled. For large projects the javascript based search engine
-# can be slow, then enabling SERVER_BASED_SEARCH may provide a better solution.
+# When the SEARCHENGINE tag is enabled doxygen will generate a search box for
+# the HTML output. The underlying search engine uses javascript and DHTML and
+# should work on any modern browser. Note that when using HTML help
+# (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET)
+# there is already a search function so this one should typically be disabled.
+# For large projects the javascript based search engine can be slow, then
+# enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to
+# search using the keyboard; to jump to the search box use <access key> + S
+# (what the <access key> is depends on the OS and browser, but it is typically
+# <CTRL>, <ALT>/<option>, or both). Inside the search box use the <cursor down
+# key> to jump into the search results window, the results can be navigated
+# using the <cursor keys>. Press <Enter> to select an item or <escape> to cancel
+# the search. The filter options can be selected when the cursor is inside the
+# search box by pressing <Shift>+<cursor down>. Also here use the <cursor keys>
+# to select a filter and <Enter> or <escape> to activate or cancel the filter
+# option.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_HTML is set to YES.
SEARCHENGINE = NO
# When the SERVER_BASED_SEARCH tag is enabled the search engine will be
-# implemented using a web server instead of a web client using Javascript.
-# There are two flavours of web server based search depending on the
-# EXTERNAL_SEARCH setting. When disabled, doxygen will generate a PHP script for
-# searching and an index file used by the script. When EXTERNAL_SEARCH is
-# enabled the indexing and searching needs to be provided by external tools.
-# See the manual for details.
+# implemented using a web server instead of a web client using Javascript. There
+# are two flavors of web server based searching depending on the EXTERNAL_SEARCH
+# setting. When disabled, doxygen will generate a PHP script for searching and
+# an index file used by the script. When EXTERNAL_SEARCH is enabled the indexing
+# and searching needs to be provided by external tools. See the section
+# "External Indexing and Searching" for details.
+# The default value is: NO.
+# This tag requires that the tag SEARCHENGINE is set to YES.
SERVER_BASED_SEARCH = NO
-# When EXTERNAL_SEARCH is enabled doxygen will no longer generate the PHP
+# When EXTERNAL_SEARCH tag is enabled doxygen will no longer generate the PHP
# script for searching. Instead the search results are written to an XML file
# which needs to be processed by an external indexer. Doxygen will invoke an
-# external search engine pointed to by the SEARCHENGINE_URL option to obtain
-# the search results. Doxygen ships with an example indexer (doxyindexer) and
-# search engine (doxysearch.cgi) which are based on the open source search
-# engine library Xapian. See the manual for configuration details.
+# external search engine pointed to by the SEARCHENGINE_URL option to obtain the
+# search results.
+#
+# Doxygen ships with an example indexer (doxyindexer) and search engine
+# (doxysearch.cgi) which are based on the open source search engine library
+# Xapian (see: http://xapian.org/).
+#
+# See the section "External Indexing and Searching" for details.
+# The default value is: NO.
+# This tag requires that the tag SEARCHENGINE is set to YES.
EXTERNAL_SEARCH = NO
# The SEARCHENGINE_URL should point to a search engine hosted by a web server
-# which will returned the search results when EXTERNAL_SEARCH is enabled.
-# Doxygen ships with an example search engine (doxysearch) which is based on
-# the open source search engine library Xapian. See the manual for configuration
-# details.
+# which will return the search results when EXTERNAL_SEARCH is enabled.
+#
+# Doxygen ships with an example indexer (doxyindexer) and search engine
+# (doxysearch.cgi) which are based on the open source search engine library
+# Xapian (see: http://xapian.org/). See the section "External Indexing and
+# Searching" for details.
+# This tag requires that the tag SEARCHENGINE is set to YES.
SEARCHENGINE_URL =
# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the unindexed
# search data is written to a file for indexing by an external tool. With the
# SEARCHDATA_FILE tag the name of this file can be specified.
+# The default file is: searchdata.xml.
+# This tag requires that the tag SEARCHENGINE is set to YES.
SEARCHDATA_FILE = searchdata.xml
-# When SERVER_BASED_SEARCH AND EXTERNAL_SEARCH are both enabled the
+# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the
# EXTERNAL_SEARCH_ID tag can be used as an identifier for the project. This is
# useful in combination with EXTRA_SEARCH_MAPPINGS to search through multiple
# projects and redirect the results back to the right project.
+# This tag requires that the tag SEARCHENGINE is set to YES.
EXTERNAL_SEARCH_ID =
# The EXTRA_SEARCH_MAPPINGS tag can be used to enable searching through doxygen
# projects other than the one defined by this configuration file, but that are
# all added to the same external search index. Each project needs to have a
-# unique id set via EXTERNAL_SEARCH_ID. The search mapping then maps the id
-# of to a relative location where the documentation can be found.
-# The format is: EXTRA_SEARCH_MAPPINGS = id1=loc1 id2=loc2 ...
+# unique id set via EXTERNAL_SEARCH_ID. The search mapping then maps the id of
+# to a relative location where the documentation can be found. The format is:
+# EXTRA_SEARCH_MAPPINGS = tagname1=loc1 tagname2=loc2 ...
+# This tag requires that the tag SEARCHENGINE is set to YES.
EXTRA_SEARCH_MAPPINGS =
#---------------------------------------------------------------------------
-# configuration options related to the LaTeX output
+# Configuration options related to the LaTeX output
#---------------------------------------------------------------------------
-# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will
-# generate Latex output.
+# If the GENERATE_LATEX tag is set to YES, doxygen will generate LaTeX output.
+# The default value is: YES.
GENERATE_LATEX = NO
-# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put.
-# If a relative path is entered the value of OUTPUT_DIRECTORY will be
-# put in front of it. If left blank `latex' will be used as the default path.
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: latex.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
LATEX_OUTPUT = latex
# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
-# invoked. If left blank `latex' will be used as the default command name.
-# Note that when enabling USE_PDFLATEX this option is only used for
-# generating bitmaps for formulas in the HTML output, but not in the
-# Makefile that is written to the output directory.
+# invoked.
+#
+# Note that when enabling USE_PDFLATEX this option is only used for generating
+# bitmaps for formulas in the HTML output, but not in the Makefile that is
+# written to the output directory.
+# The default file is: latex.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
LATEX_CMD_NAME = latex
-# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to
-# generate index for LaTeX. If left blank `makeindex' will be used as the
-# default command name.
+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to generate
+# index for LaTeX.
+# The default file is: makeindex.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
MAKEINDEX_CMD_NAME = makeindex
-# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact
-# LaTeX documents. This may be useful for small projects and may help to
-# save some trees in general.
+# If the COMPACT_LATEX tag is set to YES, doxygen generates more compact LaTeX
+# documents. This may be useful for small projects and may help to save some
+# trees in general.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
COMPACT_LATEX = NO
-# The PAPER_TYPE tag can be used to set the paper type that is used
-# by the printer. Possible values are: a4, letter, legal and
-# executive. If left blank a4 will be used.
+# The PAPER_TYPE tag can be used to set the paper type that is used by the
+# printer.
+# Possible values are: a4 (210 x 297 mm), letter (8.5 x 11 inches), legal (8.5 x
+# 14 inches) and executive (7.25 x 10.5 inches).
+# The default value is: a4.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
PAPER_TYPE = a4wide
-# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX
-# packages that should be included in the LaTeX output.
+# The EXTRA_PACKAGES tag can be used to specify one or more LaTeX package names
+# that should be included in the LaTeX output. To get the times font for
+# instance you can specify
+# EXTRA_PACKAGES=times
+# If left blank no extra packages will be included.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
EXTRA_PACKAGES =
-# The LATEX_HEADER tag can be used to specify a personal LaTeX header for
-# the generated latex document. The header should contain everything until
-# the first chapter. If it is left blank doxygen will generate a
-# standard header. Notice: only use this tag if you know what you are doing!
+# The LATEX_HEADER tag can be used to specify a personal LaTeX header for the
+# generated LaTeX document. The header should contain everything until the first
+# chapter. If it is left blank doxygen will generate a standard header. See
+# section "Doxygen usage" for information on how to let doxygen write the
+# default header to a separate file.
+#
+# Note: Only use a user-defined header if you know what you are doing! The
+# following commands have a special meaning inside the header: $title,
+# $datetime, $date, $doxygenversion, $projectname, $projectnumber,
+# $projectbrief, $projectlogo. Doxygen will replace $title with the empty
+# string, for the replacement values of the other commands the user is referred
+# to HTML_HEADER.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
LATEX_HEADER =
-# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for
-# the generated latex document. The footer should contain everything after
-# the last chapter. If it is left blank doxygen will generate a
-# standard footer. Notice: only use this tag if you know what you are doing!
+# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for the
+# generated LaTeX document. The footer should contain everything after the last
+# chapter. If it is left blank doxygen will generate a standard footer. See
+# LATEX_HEADER for more information on how to generate a default footer and what
+# special commands can be used inside the footer.
+#
+# Note: Only use a user-defined footer if you know what you are doing!
+# This tag requires that the tag GENERATE_LATEX is set to YES.
LATEX_FOOTER =
-# The LATEX_EXTRA_FILES tag can be used to specify one or more extra images
-# or other source files which should be copied to the LaTeX output directory.
-# Note that the files will be copied as-is; there are no commands or markers
-# available.
+# The LATEX_EXTRA_STYLESHEET tag can be used to specify additional user-defined
+# LaTeX style sheets that are included after the standard style sheets created
+# by doxygen. Using this option one can overrule certain style aspects. Doxygen
+# will copy the style sheet files to the output directory.
+# Note: The order of the extra style sheet files is of importance (e.g. the last
+# style sheet in the list overrules the setting of the previous ones in the
+# list).
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_EXTRA_STYLESHEET =
+
+# The LATEX_EXTRA_FILES tag can be used to specify one or more extra images or
+# other source files which should be copied to the LATEX_OUTPUT output
+# directory. Note that the files will be copied as-is; there are no commands or
+# markers available.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
LATEX_EXTRA_FILES =
-# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated
-# is prepared for conversion to pdf (using ps2pdf). The pdf file will
-# contain links (just like the HTML output) instead of page references
-# This makes the output suitable for online browsing using a pdf viewer.
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated is
+# prepared for conversion to PDF (using ps2pdf or pdflatex). The PDF file will
+# contain links (just like the HTML output) instead of page references. This
+# makes the output suitable for online browsing using a PDF viewer.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
PDF_HYPERLINKS = NO
-# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of
-# plain latex in the generated Makefile. Set this option to YES to get a
+# If the USE_PDFLATEX tag is set to YES, doxygen will use pdflatex to generate
+# the PDF file directly from the LaTeX files. Set this option to YES, to get a
# higher quality PDF documentation.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
USE_PDFLATEX = NO
-# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode.
-# command to the generated LaTeX files. This will instruct LaTeX to keep
-# running if errors occur, instead of asking the user for help.
-# This option is also used when generating formulas in HTML.
+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \batchmode
+# command to the generated LaTeX files. This will instruct LaTeX to keep running
+# if errors occur, instead of asking the user for help. This option is also used
+# when generating formulas in HTML.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
LATEX_BATCHMODE = NO
-# If LATEX_HIDE_INDICES is set to YES then doxygen will not
-# include the index chapters (such as File Index, Compound Index, etc.)
-# in the output.
+# If the LATEX_HIDE_INDICES tag is set to YES then doxygen will not include the
+# index chapters (such as File Index, Compound Index, etc.) in the output.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
LATEX_HIDE_INDICES = NO
-# If LATEX_SOURCE_CODE is set to YES then doxygen will include
-# source code with syntax highlighting in the LaTeX output.
-# Note that which sources are shown also depends on other settings
-# such as SOURCE_BROWSER.
+# If the LATEX_SOURCE_CODE tag is set to YES then doxygen will include source
+# code with syntax highlighting in the LaTeX output.
+#
+# Note that which sources are shown also depends on other settings such as
+# SOURCE_BROWSER.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
LATEX_SOURCE_CODE = NO
# The LATEX_BIB_STYLE tag can be used to specify the style to use for the
-# bibliography, e.g. plainnat, or ieeetr. The default style is "plain". See
-# http://en.wikipedia.org/wiki/BibTeX for more info.
+# bibliography, e.g. plainnat, or ieeetr. See
+# http://en.wikipedia.org/wiki/BibTeX and \cite for more info.
+# The default value is: plain.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
LATEX_BIB_STYLE = plain
#---------------------------------------------------------------------------
-# configuration options related to the RTF output
+# Configuration options related to the RTF output
#---------------------------------------------------------------------------
-# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output
-# The RTF output is optimized for Word 97 and may not look very pretty with
-# other RTF readers or editors.
+# If the GENERATE_RTF tag is set to YES, doxygen will generate RTF output. The
+# RTF output is optimized for Word 97 and may not look too pretty with other RTF
+# readers/editors.
+# The default value is: NO.
GENERATE_RTF = NO
-# The RTF_OUTPUT tag is used to specify where the RTF docs will be put.
-# If a relative path is entered the value of OUTPUT_DIRECTORY will be
-# put in front of it. If left blank `rtf' will be used as the default path.
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: rtf.
+# This tag requires that the tag GENERATE_RTF is set to YES.
RTF_OUTPUT = rtf
-# If the COMPACT_RTF tag is set to YES Doxygen generates more compact
-# RTF documents. This may be useful for small projects and may help to
-# save some trees in general.
+# If the COMPACT_RTF tag is set to YES, doxygen generates more compact RTF
+# documents. This may be useful for small projects and may help to save some
+# trees in general.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_RTF is set to YES.
COMPACT_RTF = NO
-# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated
-# will contain hyperlink fields. The RTF file will
-# contain links (just like the HTML output) instead of page references.
-# This makes the output suitable for online browsing using WORD or other
-# programs which support those fields.
-# Note: wordpad (write) and others do not support links.
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated will
+# contain hyperlink fields. The RTF file will contain links (just like the HTML
+# output) instead of page references. This makes the output suitable for online
+# browsing using Word or some other Word compatible readers that support those
+# fields.
+#
+# Note: WordPad (write) and others do not support links.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_RTF is set to YES.
RTF_HYPERLINKS = NO
-# Load style sheet definitions from file. Syntax is similar to doxygen's
-# config file, i.e. a series of assignments. You only have to provide
-# replacements, missing definitions are set to their default value.
+# Load stylesheet definitions from file. Syntax is similar to doxygen's config
+# file, i.e. a series of assignments. You only have to provide replacements,
+# missing definitions are set to their default value.
+#
+# See also section "Doxygen usage" for information on how to generate the
+# default style sheet that doxygen normally uses.
+# This tag requires that the tag GENERATE_RTF is set to YES.
RTF_STYLESHEET_FILE =
-# Set optional variables used in the generation of an rtf document.
-# Syntax is similar to doxygen's config file.
+# Set optional variables used in the generation of an RTF document. Syntax is
+# similar to doxygen's config file. A template extensions file can be generated
+# using doxygen -e rtf extensionFile.
+# This tag requires that the tag GENERATE_RTF is set to YES.
RTF_EXTENSIONS_FILE =
+# If the RTF_SOURCE_CODE tag is set to YES then doxygen will include source code
+# with syntax highlighting in the RTF output.
+#
+# Note that which sources are shown also depends on other settings such as
+# SOURCE_BROWSER.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_SOURCE_CODE = NO
+
#---------------------------------------------------------------------------
-# configuration options related to the man page output
+# Configuration options related to the man page output
#---------------------------------------------------------------------------
-# If the GENERATE_MAN tag is set to YES (the default) Doxygen will
-# generate man pages
+# If the GENERATE_MAN tag is set to YES, doxygen will generate man pages for
+# classes and files.
+# The default value is: NO.
GENERATE_MAN = NO
-# The MAN_OUTPUT tag is used to specify where the man pages will be put.
-# If a relative path is entered the value of OUTPUT_DIRECTORY will be
-# put in front of it. If left blank `man' will be used as the default path.
+# The MAN_OUTPUT tag is used to specify where the man pages will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it. A directory man3 will be created inside the directory specified by
+# MAN_OUTPUT.
+# The default directory is: man.
+# This tag requires that the tag GENERATE_MAN is set to YES.
MAN_OUTPUT = man
-# The MAN_EXTENSION tag determines the extension that is added to
-# the generated man pages (default is the subroutine's section .3)
+# The MAN_EXTENSION tag determines the extension that is added to the generated
+# man pages. In case the manual section does not start with a number, the number
+# 3 is prepended. The dot (.) at the beginning of the MAN_EXTENSION tag is
+# optional.
+# The default value is: .3.
+# This tag requires that the tag GENERATE_MAN is set to YES.
MAN_EXTENSION = .3
-# If the MAN_LINKS tag is set to YES and Doxygen generates man output,
-# then it will generate one additional man file for each entity
-# documented in the real man page(s). These additional files
-# only source the real man page, but without them the man command
-# would be unable to find the correct page. The default is NO.
+# The MAN_SUBDIR tag determines the name of the directory created within
+# MAN_OUTPUT in which the man pages are placed. If defaults to man followed by
+# MAN_EXTENSION with the initial . removed.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_SUBDIR =
+
+# If the MAN_LINKS tag is set to YES and doxygen generates man output, then it
+# will generate one additional man file for each entity documented in the real
+# man page(s). These additional files only source the real man page, but without
+# them the man command would be unable to find the correct page.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_MAN is set to YES.
MAN_LINKS = NO
#---------------------------------------------------------------------------
-# configuration options related to the XML output
+# Configuration options related to the XML output
#---------------------------------------------------------------------------
-# If the GENERATE_XML tag is set to YES Doxygen will
-# generate an XML file that captures the structure of
-# the code including all documentation.
+# If the GENERATE_XML tag is set to YES, doxygen will generate an XML file that
+# captures the structure of the code including all documentation.
+# The default value is: NO.
GENERATE_XML = NO
-# The XML_OUTPUT tag is used to specify where the XML pages will be put.
-# If a relative path is entered the value of OUTPUT_DIRECTORY will be
-# put in front of it. If left blank `xml' will be used as the default path.
+# The XML_OUTPUT tag is used to specify where the XML pages will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: xml.
+# This tag requires that the tag GENERATE_XML is set to YES.
XML_OUTPUT = xml
-# The XML_SCHEMA tag can be used to specify an XML schema,
-# which can be used by a validating XML parser to check the
-# syntax of the XML files.
-
-XML_SCHEMA =
-
-# The XML_DTD tag can be used to specify an XML DTD,
-# which can be used by a validating XML parser to check the
-# syntax of the XML files.
-
-XML_DTD =
-
-# If the XML_PROGRAMLISTING tag is set to YES Doxygen will
-# dump the program listings (including syntax highlighting
-# and cross-referencing information) to the XML output. Note that
-# enabling this will significantly increase the size of the XML output.
+# If the XML_PROGRAMLISTING tag is set to YES, doxygen will dump the program
+# listings (including syntax highlighting and cross-referencing information) to
+# the XML output. Note that enabling this will significantly increase the size
+# of the XML output.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_XML is set to YES.
XML_PROGRAMLISTING = YES
#---------------------------------------------------------------------------
-# configuration options related to the DOCBOOK output
+# Configuration options related to the DOCBOOK output
#---------------------------------------------------------------------------
-# If the GENERATE_DOCBOOK tag is set to YES Doxygen will generate DOCBOOK files
+# If the GENERATE_DOCBOOK tag is set to YES, doxygen will generate Docbook files
# that can be used to generate PDF.
+# The default value is: NO.
GENERATE_DOCBOOK = NO
-# The DOCBOOK_OUTPUT tag is used to specify where the DOCBOOK pages will be put.
+# The DOCBOOK_OUTPUT tag is used to specify where the Docbook pages will be put.
# If a relative path is entered the value of OUTPUT_DIRECTORY will be put in
-# front of it. If left blank docbook will be used as the default path.
+# front of it.
+# The default directory is: docbook.
+# This tag requires that the tag GENERATE_DOCBOOK is set to YES.
DOCBOOK_OUTPUT = docbook
+# If the DOCBOOK_PROGRAMLISTING tag is set to YES, doxygen will include the
+# program listings (including syntax highlighting and cross-referencing
+# information) to the DOCBOOK output. Note that enabling this will significantly
+# increase the size of the DOCBOOK output.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_DOCBOOK is set to YES.
+
+DOCBOOK_PROGRAMLISTING = NO
+
#---------------------------------------------------------------------------
-# configuration options for the AutoGen Definitions output
+# Configuration options for the AutoGen Definitions output
#---------------------------------------------------------------------------
-# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will
-# generate an AutoGen Definitions (see autogen.sf.net) file
-# that captures the structure of the code including all
-# documentation. Note that this feature is still experimental
-# and incomplete at the moment.
+# If the GENERATE_AUTOGEN_DEF tag is set to YES, doxygen will generate an
+# AutoGen Definitions (see http://autogen.sf.net) file that captures the
+# structure of the code including all documentation. Note that this feature is
+# still experimental and incomplete at the moment.
+# The default value is: NO.
GENERATE_AUTOGEN_DEF = NO
#---------------------------------------------------------------------------
-# configuration options related to the Perl module output
+# Configuration options related to the Perl module output
#---------------------------------------------------------------------------
-# If the GENERATE_PERLMOD tag is set to YES Doxygen will
-# generate a Perl module file that captures the structure of
-# the code including all documentation. Note that this
-# feature is still experimental and incomplete at the
-# moment.
+# If the GENERATE_PERLMOD tag is set to YES, doxygen will generate a Perl module
+# file that captures the structure of the code including all documentation.
+#
+# Note that this feature is still experimental and incomplete at the moment.
+# The default value is: NO.
GENERATE_PERLMOD = NO
-# If the PERLMOD_LATEX tag is set to YES Doxygen will generate
-# the necessary Makefile rules, Perl scripts and LaTeX code to be able
-# to generate PDF and DVI output from the Perl module output.
+# If the PERLMOD_LATEX tag is set to YES, doxygen will generate the necessary
+# Makefile rules, Perl scripts and LaTeX code to be able to generate PDF and DVI
+# output from the Perl module output.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_PERLMOD is set to YES.
PERLMOD_LATEX = NO
-# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be
-# nicely formatted so it can be parsed by a human reader.
-# This is useful
-# if you want to understand what is going on.
-# On the other hand, if this
-# tag is set to NO the size of the Perl module output will be much smaller
-# and Perl will parse it just the same.
+# If the PERLMOD_PRETTY tag is set to YES, the Perl module output will be nicely
+# formatted so it can be parsed by a human reader. This is useful if you want to
+# understand what is going on. On the other hand, if this tag is set to NO, the
+# size of the Perl module output will be much smaller and Perl will parse it
+# just the same.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_PERLMOD is set to YES.
PERLMOD_PRETTY = YES
-# The names of the make variables in the generated doxyrules.make file
-# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX.
-# This is useful so different doxyrules.make files included by the same
-# Makefile don't overwrite each other's variables.
+# The names of the make variables in the generated doxyrules.make file are
+# prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. This is useful
+# so different doxyrules.make files included by the same Makefile don't
+# overwrite each other's variables.
+# This tag requires that the tag GENERATE_PERLMOD is set to YES.
PERLMOD_MAKEVAR_PREFIX =
@@ -1575,113 +1946,130 @@ PERLMOD_MAKEVAR_PREFIX =
# Configuration options related to the preprocessor
#---------------------------------------------------------------------------
-# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will
-# evaluate all C-preprocessor directives found in the sources and include
-# files.
+# If the ENABLE_PREPROCESSING tag is set to YES, doxygen will evaluate all
+# C-preprocessor directives found in the sources and include files.
+# The default value is: YES.
ENABLE_PREPROCESSING = YES
-# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro
-# names in the source code. If set to NO (the default) only conditional
-# compilation will be performed. Macro expansion can be done in a controlled
-# way by setting EXPAND_ONLY_PREDEF to YES.
+# If the MACRO_EXPANSION tag is set to YES, doxygen will expand all macro names
+# in the source code. If set to NO, only conditional compilation will be
+# performed. Macro expansion can be done in a controlled way by setting
+# EXPAND_ONLY_PREDEF to YES.
+# The default value is: NO.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
MACRO_EXPANSION = NO
-# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES
-# then the macro expansion is limited to the macros specified with the
-# PREDEFINED and EXPAND_AS_DEFINED tags.
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES then
+# the macro expansion is limited to the macros specified with the PREDEFINED and
+# EXPAND_AS_DEFINED tags.
+# The default value is: NO.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
EXPAND_ONLY_PREDEF = NO
-# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files
-# pointed to by INCLUDE_PATH will be searched when a #include is found.
+# If the SEARCH_INCLUDES tag is set to YES, the include files in the
+# INCLUDE_PATH will be searched if a #include is found.
+# The default value is: YES.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
SEARCH_INCLUDES = YES
# The INCLUDE_PATH tag can be used to specify one or more directories that
-# contain include files that are not input files but should be processed by
-# the preprocessor.
+# contain include files that are not input files but should be processed by the
+# preprocessor.
+# This tag requires that the tag SEARCH_INCLUDES is set to YES.
INCLUDE_PATH = ../../source/blender/nodes \
../../source/blender/editors/include
# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
# patterns (like *.h and *.hpp) to filter out the header-files in the
-# directories. If left blank, the patterns specified with FILE_PATTERNS will
-# be used.
+# directories. If left blank, the patterns specified with FILE_PATTERNS will be
+# used.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
INCLUDE_FILE_PATTERNS =
-# The PREDEFINED tag can be used to specify one or more macro names that
-# are defined before the preprocessor is started (similar to the -D option of
-# gcc). The argument of the tag is a list of macros of the form: name
-# or name=definition (no spaces). If the definition and the = are
-# omitted =1 is assumed. To prevent a macro definition from being
-# undefined via #undef or recursively expanded use the := operator
-# instead of the = operator.
+# The PREDEFINED tag can be used to specify one or more macro names that are
+# defined before the preprocessor is started (similar to the -D option of e.g.
+# gcc). The argument of the tag is a list of macros of the form: name or
+# name=definition (no spaces). If the definition and the "=" are omitted, "=1"
+# is assumed. To prevent a macro definition from being undefined via #undef or
+# recursively expanded use the := operator instead of the = operator.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
PREDEFINED = BUILD_DATE
-# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then
-# this tag can be used to specify a list of macro names that should be expanded.
-# The macro definition that is found in the sources will be used.
-# Use the PREDEFINED tag if you want to use a different macro definition that
-# overrules the definition found in the source code.
+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this
+# tag can be used to specify a list of macro names that should be expanded. The
+# macro definition that is found in the sources will be used. Use the PREDEFINED
+# tag if you want to use a different macro definition that overrules the
+# definition found in the source code.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
EXPAND_AS_DEFINED =
-# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then
-# doxygen's preprocessor will remove all references to function-like macros
-# that are alone on a line, have an all uppercase name, and do not end with a
-# semicolon, because these will confuse the parser if not removed.
+# If the SKIP_FUNCTION_MACROS tag is set to YES then doxygen's preprocessor will
+# remove all references to function-like macros that are alone on a line, have
+# an all uppercase name, and do not end with a semicolon. Such function macros
+# are typically used for boiler-plate code, and will confuse the parser if not
+# removed.
+# The default value is: YES.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
SKIP_FUNCTION_MACROS = YES
#---------------------------------------------------------------------------
-# Configuration::additions related to external references
+# Configuration options related to external references
#---------------------------------------------------------------------------
-# The TAGFILES option can be used to specify one or more tagfiles. For each
-# tag file the location of the external documentation should be added. The
-# format of a tag file without this location is as follows:
-#
+# The TAGFILES tag can be used to specify one or more tag files. For each tag
+# file the location of the external documentation should be added. The format of
+# a tag file without this location is as follows:
# TAGFILES = file1 file2 ...
# Adding location for the tag files is done as follows:
-#
# TAGFILES = file1=loc1 "file2 = loc2" ...
-# where "loc1" and "loc2" can be relative or absolute paths
-# or URLs. Note that each tag file must have a unique name (where the name does
-# NOT include the path). If a tag file is not located in the directory in which
-# doxygen is run, you must also specify the path to the tagfile here.
+# where loc1 and loc2 can be relative or absolute paths or URLs. See the
+# section "Linking to external documentation" for more information about the use
+# of tag files.
+# Note: Each tag file must have a unique name (where the name does NOT include
+# the path). If a tag file is not located in the directory in which doxygen is
+# run, you must also specify the path to the tagfile here.
TAGFILES =
-# When a file name is specified after GENERATE_TAGFILE, doxygen will create
-# a tag file that is based on the input files it reads.
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create a
+# tag file that is based on the input files it reads. See section "Linking to
+# external documentation" for more information about the usage of tag files.
GENERATE_TAGFILE =
-# If the ALLEXTERNALS tag is set to YES all external classes will be listed
-# in the class index. If set to NO only the inherited external classes
-# will be listed.
+# If the ALLEXTERNALS tag is set to YES, all external class will be listed in
+# the class index. If set to NO, only the inherited external classes will be
+# listed.
+# The default value is: NO.
ALLEXTERNALS = NO
-# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed
-# in the modules index. If set to NO, only the current project's groups will
-# be listed.
+# If the EXTERNAL_GROUPS tag is set to YES, all external groups will be listed
+# in the modules index. If set to NO, only the current project's groups will be
+# listed.
+# The default value is: YES.
EXTERNAL_GROUPS = YES
-# If the EXTERNAL_PAGES tag is set to YES all external pages will be listed
-# in the related pages index. If set to NO, only the current project's
-# pages will be listed.
+# If the EXTERNAL_PAGES tag is set to YES, all external pages will be listed in
+# the related pages index. If set to NO, only the current project's pages will
+# be listed.
+# The default value is: YES.
EXTERNAL_PAGES = YES
# The PERL_PATH should be the absolute path and name of the perl script
-# interpreter (i.e. the result of `which perl').
+# interpreter (i.e. the result of 'which perl').
+# The default file (with absolute path) is: /usr/bin/perl.
PERL_PATH = /usr/bin/perl
@@ -1689,222 +2077,306 @@ PERL_PATH = /usr/bin/perl
# Configuration options related to the dot tool
#---------------------------------------------------------------------------
-# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will
-# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base
-# or super classes. Setting the tag to NO turns the diagrams off. Note that
-# this option also works with HAVE_DOT disabled, but it is recommended to
-# install and use dot, since it yields more powerful graphs.
+# If the CLASS_DIAGRAMS tag is set to YES, doxygen will generate a class diagram
+# (in HTML and LaTeX) for classes with base or super classes. Setting the tag to
+# NO turns the diagrams off. Note that this option also works with HAVE_DOT
+# disabled, but it is recommended to install and use dot, since it yields more
+# powerful graphs.
+# The default value is: YES.
CLASS_DIAGRAMS = NO
# You can define message sequence charts within doxygen comments using the \msc
-# command. Doxygen will then run the mscgen tool (see
-# http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the
+# command. Doxygen will then run the mscgen tool (see:
+# http://www.mcternan.me.uk/mscgen/)) to produce the chart and insert it in the
# documentation. The MSCGEN_PATH tag allows you to specify the directory where
# the mscgen tool resides. If left empty the tool is assumed to be found in the
# default search path.
MSCGEN_PATH =
-# If set to YES, the inheritance and collaboration graphs will hide
-# inheritance and usage relations if the target is undocumented
-# or is not a class.
+# You can include diagrams made with dia in doxygen documentation. Doxygen will
+# then run dia to produce the diagram and insert it in the documentation. The
+# DIA_PATH tag allows you to specify the directory where the dia binary resides.
+# If left empty dia is assumed to be found in the default search path.
-HIDE_UNDOC_RELATIONS = YES
+DIA_PATH =
-# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
-# available from the path. This tool is part of Graphviz, a graph visualization
-# toolkit from AT&T and Lucent Bell Labs. The other options in this section
-# have no effect if this option is set to NO (the default)
+# If set to YES the inheritance and collaboration graphs will hide inheritance
+# and usage relations if the target is undocumented or is not a class.
+# The default value is: YES.
-HAVE_DOT = YES
+HIDE_UNDOC_RELATIONS = YES
-# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is
-# allowed to run in parallel. When set to 0 (the default) doxygen will
-# base this on the number of processors available in the system. You can set it
-# explicitly to a value larger than 0 to get control over the balance
-# between CPU load and processing speed.
+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
+# available from the path. This tool is part of Graphviz (see:
+# http://www.graphviz.org/), a graph visualization toolkit from AT&T and Lucent
+# Bell Labs. The other options in this section have no effect if this option is
+# set to NO
+# The default value is: NO.
+
+HAVE_DOT = NO
+
+# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is allowed
+# to run in parallel. When set to 0 doxygen will base this on the number of
+# processors available in the system. You can set it explicitly to a value
+# larger than 0 to get control over the balance between CPU load and processing
+# speed.
+# Minimum value: 0, maximum value: 32, default value: 0.
+# This tag requires that the tag HAVE_DOT is set to YES.
DOT_NUM_THREADS = 0
-# By default doxygen will use the Helvetica font for all dot files that
-# doxygen generates. When you want a differently looking font you can specify
-# the font name using DOT_FONTNAME. You need to make sure dot is able to find
-# the font, which can be done by putting it in a standard location or by setting
-# the DOTFONTPATH environment variable or by setting DOT_FONTPATH to the
-# directory containing the font.
+# When you want a differently looking font in the dot files that doxygen
+# generates you can specify the font name using DOT_FONTNAME. You need to make
+# sure dot is able to find the font, which can be done by putting it in a
+# standard location or by setting the DOTFONTPATH environment variable or by
+# setting DOT_FONTPATH to the directory containing the font.
+# The default value is: Helvetica.
+# This tag requires that the tag HAVE_DOT is set to YES.
DOT_FONTNAME = Helvetica
-# The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs.
-# The default size is 10pt.
+# The DOT_FONTSIZE tag can be used to set the size (in points) of the font of
+# dot graphs.
+# Minimum value: 4, maximum value: 24, default value: 10.
+# This tag requires that the tag HAVE_DOT is set to YES.
DOT_FONTSIZE = 10
-# By default doxygen will tell dot to use the Helvetica font.
-# If you specify a different font using DOT_FONTNAME you can use DOT_FONTPATH to
-# set the path where dot can find it.
+# By default doxygen will tell dot to use the default font as specified with
+# DOT_FONTNAME. If you specify a different font using DOT_FONTNAME you can set
+# the path where dot can find it using this tag.
+# This tag requires that the tag HAVE_DOT is set to YES.
DOT_FONTPATH =
-# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen
-# will generate a graph for each documented class showing the direct and
-# indirect inheritance relations. Setting this tag to YES will force the
-# CLASS_DIAGRAMS tag to NO.
+# If the CLASS_GRAPH tag is set to YES then doxygen will generate a graph for
+# each documented class showing the direct and indirect inheritance relations.
+# Setting this tag to YES will force the CLASS_DIAGRAMS tag to NO.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
CLASS_GRAPH = YES
-# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen
-# will generate a graph for each documented class showing the direct and
-# indirect implementation dependencies (inheritance, containment, and
-# class references variables) of the class with other documented classes.
+# If the COLLABORATION_GRAPH tag is set to YES then doxygen will generate a
+# graph for each documented class showing the direct and indirect implementation
+# dependencies (inheritance, containment, and class references variables) of the
+# class with other documented classes.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
COLLABORATION_GRAPH = NO
-# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen
-# will generate a graph for groups, showing the direct groups dependencies
+# If the GROUP_GRAPHS tag is set to YES then doxygen will generate a graph for
+# groups, showing the direct groups dependencies.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
GROUP_GRAPHS = YES
-# If the UML_LOOK tag is set to YES doxygen will generate inheritance and
+# If the UML_LOOK tag is set to YES, doxygen will generate inheritance and
# collaboration diagrams in a style similar to the OMG's Unified Modeling
# Language.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
UML_LOOK = YES
-# If the UML_LOOK tag is enabled, the fields and methods are shown inside
-# the class node. If there are many fields or methods and many nodes the
-# graph may become too big to be useful. The UML_LIMIT_NUM_FIELDS
-# threshold limits the number of items for each type to make the size more
-# manageable. Set this to 0 for no limit. Note that the threshold may be
-# exceeded by 50% before the limit is enforced.
+# If the UML_LOOK tag is enabled, the fields and methods are shown inside the
+# class node. If there are many fields or methods and many nodes the graph may
+# become too big to be useful. The UML_LIMIT_NUM_FIELDS threshold limits the
+# number of items for each type to make the size more manageable. Set this to 0
+# for no limit. Note that the threshold may be exceeded by 50% before the limit
+# is enforced. So when you set the threshold to 10, up to 15 fields may appear,
+# but if the number exceeds 15, the total amount of fields shown is limited to
+# 10.
+# Minimum value: 0, maximum value: 100, default value: 10.
+# This tag requires that the tag HAVE_DOT is set to YES.
UML_LIMIT_NUM_FIELDS = 10
-# If set to YES, the inheritance and collaboration graphs will show the
-# relations between templates and their instances.
+# If the TEMPLATE_RELATIONS tag is set to YES then the inheritance and
+# collaboration graphs will show the relations between templates and their
+# instances.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
TEMPLATE_RELATIONS = YES
-# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT
-# tags are set to YES then doxygen will generate a graph for each documented
-# file showing the direct and indirect include dependencies of the file with
-# other documented files.
+# If the INCLUDE_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are set to
+# YES then doxygen will generate a graph for each documented file showing the
+# direct and indirect include dependencies of the file with other documented
+# files.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
INCLUDE_GRAPH = NO
-# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and
-# HAVE_DOT tags are set to YES then doxygen will generate a graph for each
-# documented header file showing the documented files that directly or
-# indirectly include this file.
+# If the INCLUDED_BY_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are
+# set to YES then doxygen will generate a graph for each documented file showing
+# the direct and indirect include dependencies of the file with other documented
+# files.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
INCLUDED_BY_GRAPH = NO
-# If the CALL_GRAPH and HAVE_DOT options are set to YES then
-# doxygen will generate a call dependency graph for every global function
-# or class method. Note that enabling this option will significantly increase
-# the time of a run. So in most cases it will be better to enable call graphs
-# for selected functions only using the \callgraph command.
+# If the CALL_GRAPH tag is set to YES then doxygen will generate a call
+# dependency graph for every global function or class method.
+#
+# Note that enabling this option will significantly increase the time of a run.
+# So in most cases it will be better to enable call graphs for selected
+# functions only using the \callgraph command.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
CALL_GRAPH = NO
-# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then
-# doxygen will generate a caller dependency graph for every global function
-# or class method. Note that enabling this option will significantly increase
-# the time of a run. So in most cases it will be better to enable caller
-# graphs for selected functions only using the \callergraph command.
+# If the CALLER_GRAPH tag is set to YES then doxygen will generate a caller
+# dependency graph for every global function or class method.
+#
+# Note that enabling this option will significantly increase the time of a run.
+# So in most cases it will be better to enable caller graphs for selected
+# functions only using the \callergraph command.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
CALLER_GRAPH = NO
-# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen
-# will generate a graphical hierarchy of all classes instead of a textual one.
+# If the GRAPHICAL_HIERARCHY tag is set to YES then doxygen will graphical
+# hierarchy of all classes instead of a textual one.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
GRAPHICAL_HIERARCHY = YES
-# If the DIRECTORY_GRAPH and HAVE_DOT tags are set to YES
-# then doxygen will show the dependencies a directory has on other directories
-# in a graphical way. The dependency relations are determined by the #include
-# relations between the files in the directories.
+# If the DIRECTORY_GRAPH tag is set to YES then doxygen will show the
+# dependencies a directory has on other directories in a graphical way. The
+# dependency relations are determined by the #include relations between the
+# files in the directories.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
DIRECTORY_GRAPH = YES
# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
-# generated by dot. Possible values are svg, png, jpg, or gif.
-# If left blank png will be used. If you choose svg you need to set
-# HTML_FILE_EXTENSION to xhtml in order to make the SVG files
-# visible in IE 9+ (other browsers do not have this requirement).
+# generated by dot.
+# Note: If you choose svg you need to set HTML_FILE_EXTENSION to xhtml in order
+# to make the SVG files visible in IE 9+ (other browsers do not have this
+# requirement).
+# Possible values are: png, jpg, gif and svg.
+# The default value is: png.
+# This tag requires that the tag HAVE_DOT is set to YES.
DOT_IMAGE_FORMAT = png
# If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to
# enable generation of interactive SVG images that allow zooming and panning.
-# Note that this requires a modern browser other than Internet Explorer.
-# Tested and working are Firefox, Chrome, Safari, and Opera. For IE 9+ you
-# need to set HTML_FILE_EXTENSION to xhtml in order to make the SVG files
-# visible. Older versions of IE do not have SVG support.
+#
+# Note that this requires a modern browser other than Internet Explorer. Tested
+# and working are Firefox, Chrome, Safari, and Opera.
+# Note: For IE 9+ you need to set HTML_FILE_EXTENSION to xhtml in order to make
+# the SVG files visible. Older versions of IE do not have SVG support.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
INTERACTIVE_SVG = NO
-# The tag DOT_PATH can be used to specify the path where the dot tool can be
+# The DOT_PATH tag can be used to specify the path where the dot tool can be
# found. If left blank, it is assumed the dot tool can be found in the path.
+# This tag requires that the tag HAVE_DOT is set to YES.
DOT_PATH =
# The DOTFILE_DIRS tag can be used to specify one or more directories that
-# contain dot files that are included in the documentation (see the
-# \dotfile command).
+# contain dot files that are included in the documentation (see the \dotfile
+# command).
+# This tag requires that the tag HAVE_DOT is set to YES.
DOTFILE_DIRS =
# The MSCFILE_DIRS tag can be used to specify one or more directories that
-# contain msc files that are included in the documentation (see the
-# \mscfile command).
+# contain msc files that are included in the documentation (see the \mscfile
+# command).
MSCFILE_DIRS =
-# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of
-# nodes that will be shown in the graph. If the number of nodes in a graph
-# becomes larger than this value, doxygen will truncate the graph, which is
-# visualized by representing a node as a red box. Note that doxygen if the
-# number of direct children of the root node in a graph is already larger than
-# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note
-# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH.
+# The DIAFILE_DIRS tag can be used to specify one or more directories that
+# contain dia files that are included in the documentation (see the \diafile
+# command).
+
+DIAFILE_DIRS =
+
+# When using plantuml, the PLANTUML_JAR_PATH tag should be used to specify the
+# path where java can find the plantuml.jar file. If left blank, it is assumed
+# PlantUML is not used or called during a preprocessing step. Doxygen will
+# generate a warning when it encounters a \startuml command in this case and
+# will not generate output for the diagram.
+
+PLANTUML_JAR_PATH =
+
+# When using plantuml, the specified paths are searched for files specified by
+# the !include statement in a plantuml block.
+
+PLANTUML_INCLUDE_PATH =
+
+# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of nodes
+# that will be shown in the graph. If the number of nodes in a graph becomes
+# larger than this value, doxygen will truncate the graph, which is visualized
+# by representing a node as a red box. Note that doxygen if the number of direct
+# children of the root node in a graph is already larger than
+# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note that
+# the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH.
+# Minimum value: 0, maximum value: 10000, default value: 50.
+# This tag requires that the tag HAVE_DOT is set to YES.
DOT_GRAPH_MAX_NODES = 50
-# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the
-# graphs generated by dot. A depth value of 3 means that only nodes reachable
-# from the root by following a path via at most 3 edges will be shown. Nodes
-# that lay further from the root node will be omitted. Note that setting this
-# option to 1 or 2 may greatly reduce the computation time needed for large
-# code bases. Also note that the size of a graph can be further restricted by
+# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the graphs
+# generated by dot. A depth value of 3 means that only nodes reachable from the
+# root by following a path via at most 3 edges will be shown. Nodes that lay
+# further from the root node will be omitted. Note that setting this option to 1
+# or 2 may greatly reduce the computation time needed for large code bases. Also
+# note that the size of a graph can be further restricted by
# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction.
+# Minimum value: 0, maximum value: 1000, default value: 0.
+# This tag requires that the tag HAVE_DOT is set to YES.
MAX_DOT_GRAPH_DEPTH = 0
# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
-# background. This is disabled by default, because dot on Windows does not
-# seem to support this out of the box. Warning: Depending on the platform used,
-# enabling this option may lead to badly anti-aliased labels on the edges of
-# a graph (i.e. they become hard to read).
+# background. This is disabled by default, because dot on Windows does not seem
+# to support this out of the box.
+#
+# Warning: Depending on the platform used, enabling this option may lead to
+# badly anti-aliased labels on the edges of a graph (i.e. they become hard to
+# read).
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
DOT_TRANSPARENT = NO
-# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output
+# Set the DOT_MULTI_TARGETS tag to YES to allow dot to generate multiple output
# files in one run (i.e. multiple -o and -T options on the command line). This
-# makes dot run faster, but since only newer versions of dot (>1.8.10)
-# support this, this feature is disabled by default.
+# makes dot run faster, but since only newer versions of dot (>1.8.10) support
+# this, this feature is disabled by default.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
DOT_MULTI_TARGETS = YES
-# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will
-# generate a legend page explaining the meaning of the various boxes and
-# arrows in the dot generated graphs.
+# If the GENERATE_LEGEND tag is set to YES doxygen will generate a legend page
+# explaining the meaning of the various boxes and arrows in the dot generated
+# graphs.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
GENERATE_LEGEND = YES
-# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will
-# remove the intermediate dot files that are used to generate
-# the various graphs.
+# If the DOT_CLEANUP tag is set to YES, doxygen will remove the intermediate dot
+# files that are used to generate the various graphs.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
DOT_CLEANUP = YES
diff --git a/doc/doxygen/doxygen.extern b/doc/doxygen/doxygen.extern.h
index 6c6872ff53f..6c6872ff53f 100644
--- a/doc/doxygen/doxygen.extern
+++ b/doc/doxygen/doxygen.extern.h
diff --git a/doc/doxygen/doxygen.intern b/doc/doxygen/doxygen.intern.h
index ae8f6ca88e4..2c8ecae0ead 100644
--- a/doc/doxygen/doxygen.intern
+++ b/doc/doxygen/doxygen.intern.h
@@ -10,26 +10,14 @@
* \ingroup intern
*/
-/** \defgroup boolop boolop
- * \ingroup intern
- */
-
/** \defgroup ctr container
* \ingroup intern
*/
-/** \defgroup decimation decimation
- * \ingroup intern
- */
-
/** \defgroup elbeem elbeem
* \ingroup intern
*/
-/** \defgroup bsp bsp
- * \ingroup intern
- */
-
/** \defgroup iksolver iksolver
* \ingroup intern
*/
diff --git a/doc/doxygen/doxygen.main b/doc/doxygen/doxygen.main.h
index 188382d6a9c..d2825761b2a 100644
--- a/doc/doxygen/doxygen.main
+++ b/doc/doxygen/doxygen.main.h
@@ -7,7 +7,7 @@
* These pages document the source code of blender.
*
* \subsection implinks Important Links
- * - <a href="http://projects.blender.org">projects.blender.org</a> with <a href="http://projects.blender.org/tracker/index.php?group_id=9&atid=498">bug tracker</a>
+ * - <a href="http://developer.blender.org">developer.blender.org</a> with bug tracker.
* - <a href="http://wiki.blender.org/index.php/Dev:Contents">Development documents</a> on our wiki.
*
* \subsection blother Other
diff --git a/doc/doxygen/doxygen.source b/doc/doxygen/doxygen.source.h
index f27a5a87807..3ef20466664 100644
--- a/doc/doxygen/doxygen.source
+++ b/doc/doxygen/doxygen.source.h
@@ -11,7 +11,6 @@
/** \defgroup bmesh BMesh
* \ingroup blender
*/
-/** \defgroup texture Texturing */
/** \defgroup compositor Compositing */
/** \defgroup python Python
@@ -93,36 +92,48 @@
/* ================================ */
-/** \defgroup blender blender */
+/** \defgroup blender Blender */
-/** \defgroup blf blenfont
+/** \defgroup blt BlenTranslation
* \ingroup blender
*/
-/** \defgroup bke blenkernel
+/** \defgroup blf BlenFont
* \ingroup blender
*/
-/** \defgroup bli blenlib
+/** \defgroup bke BlenKernel
* \ingroup blender
*/
-/** \defgroup nodes nodes
+/** \defgroup bli BlenLib
* \ingroup blender
*/
-/** \defgroup cmpnodes cmpnodes
+/** \defgroup depsgraph Dependency Graph
+ * \ingroup blender
+ */
+
+/** \defgroup bph Physics
+ * \ingroup blender
+ */
+
+/** \defgroup nodes Nodes
+ * \ingroup blender
+ */
+
+/** \defgroup cmpnodes Nodes (Compositor)
* \ingroup nodes
*/
-/** \defgroup shdnodes shdnodes
+/** \defgroup shdnodes Nodes (Shader)
* \ingroup nodes
*/
-/** \defgroup texnodes texnodes
+/** \defgroup texnodes Nodes (Texture)
* \ingroup nodes
*/
-/** \defgroup modifiers modifiers
+/** \defgroup modifiers Object Modifiers
* \ingroup blender
*/
@@ -132,29 +143,29 @@
* \ingroup blender
*/
-/** \defgroup ikplugin ikplugin
+/** \defgroup ikplugin IK Plugin
* \ingroup blender
*/
-/** \defgroup DNA sDNA
+/** \defgroup DNA Struct DNA (File Format)
* \ingroup blender data
*/
-/** \defgroup RNA RNA
+/** \defgroup RNA RNA (Data API)
* \ingroup blender data
*/
-/** \defgroup blenloader .blend read and write functions
+/** \defgroup blenloader Blend file IO
* \ingroup blender data
* \todo check if \ref blo and \ref blenloader groups can be
* merged in docs.
*/
-/** \defgroup quicktime quicktime
+/** \defgroup quicktime QuickTime
* \ingroup blender
/** \defgroup gui GUI */
-/** \defgroup wm windowmanager
+/** \defgroup wm Window Manager
* \ingroup blender gui
*/
@@ -314,7 +325,7 @@
* \ingroup gui
*/
-/** \defgroup externformats external formats */
+/** \defgroup externformats External Formats */
/** \defgroup collada COLLADA
* \ingroup externformats
@@ -324,7 +335,7 @@
* \ingroup externformats
*/
-/** \defgroup imbuf IMage Buffer
+/** \defgroup imbuf Image Buffer (ImBuf)
* \ingroup blender
*/
diff --git a/doc/manpage/blender.1.py b/doc/manpage/blender.1.py
index 77f5c5e4f16..cdd2d7ca2df 100755
--- a/doc/manpage/blender.1.py
+++ b/doc/manpage/blender.1.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python
# ##### BEGIN GPL LICENSE BLOCK #####
#
diff --git a/doc/python_api/examples/aud.py b/doc/python_api/examples/aud.py
index 2c74d6a0eb1..bbe97168efe 100644
--- a/doc/python_api/examples/aud.py
+++ b/doc/python_api/examples/aud.py
@@ -1,6 +1,7 @@
"""
Basic Sound Playback
++++++++++++++++++++
+
This script shows how to use the classes: :class:`Device`, :class:`Factory` and
:class:`Handle`.
"""
diff --git a/doc/python_api/examples/bge.constraints.py b/doc/python_api/examples/bge.constraints.py
index e76fc3dd13b..c617ac0622b 100644
--- a/doc/python_api/examples/bge.constraints.py
+++ b/doc/python_api/examples/bge.constraints.py
@@ -20,15 +20,15 @@ constraint_type = 2
physics_id_1 = object_1.getPhysicsId()
physics_id_2 = object_2.getPhysicsId()
-# Use bottom right edge of Object1 for hinge position
+# use bottom right edge of Object1 for hinge position
edge_position_x = 1.0
edge_position_y = 0.0
edge_position_z = -1.0
-# use Object1 y axis for angle to point hinge
+# rotate the pivot z axis about 90 degrees
edge_angle_x = 0.0
-edge_angle_y = 1.0
-edge_angle_z = 0.0
+edge_angle_y = 0.0
+edge_angle_z = 90.0
# create an edge constraint
constraints.createConstraint(physics_id_1, physics_id_2,
diff --git a/doc/python_api/examples/bge.texture.1.py b/doc/python_api/examples/bge.texture.1.py
index fba369739f7..732c786c667 100644
--- a/doc/python_api/examples/bge.texture.1.py
+++ b/doc/python_api/examples/bge.texture.1.py
@@ -1,9 +1,10 @@
"""
Texture Replacement
+++++++++++++++++++
+
Example of how to replace a texture in game with an external image.
-createTexture() and removeTexture() are to be called from a module Python
-Controller.
+``createTexture()`` and ``removeTexture()`` are to be called from a
+module Python Controller.
"""
from bge import logic
from bge import texture
diff --git a/doc/python_api/examples/bge.texture.py b/doc/python_api/examples/bge.texture.py
index 1ba0b99fc27..ac1f5a21447 100644
--- a/doc/python_api/examples/bge.texture.py
+++ b/doc/python_api/examples/bge.texture.py
@@ -1,7 +1,8 @@
"""
Basic Video Playback
++++++++++++++++++++
-Example of how to replace a texture in game with a video. It needs to run everyframe
+Example of how to replace a texture in game with a video. It needs to run
+everyframe.
"""
import bge
from bge import texture
diff --git a/doc/python_api/examples/bpy.app.handlers.py b/doc/python_api/examples/bpy.app.handlers.py
index 57b209e15f0..078f9df77f2 100644
--- a/doc/python_api/examples/bpy.app.handlers.py
+++ b/doc/python_api/examples/bpy.app.handlers.py
@@ -1,6 +1,7 @@
"""
Basic Handler Example
+++++++++++++++++++++
+
This script shows the most simple example of adding a handler.
"""
diff --git a/doc/python_api/examples/bpy.ops.1.py b/doc/python_api/examples/bpy.ops.1.py
index a00dbdafb90..b4137e5c740 100644
--- a/doc/python_api/examples/bpy.ops.1.py
+++ b/doc/python_api/examples/bpy.ops.1.py
@@ -7,8 +7,9 @@ act on specified rather than the selected or active data, or to execute an
operator in the different part of the user interface.
The context overrides are passed as a dictionary, with keys matching the context
-member names in bpy.context. For example to override bpy.context.active_object,
-you would pass {'active_object': object}.
+member names in bpy.context.
+For example to override ``bpy.context.active_object``,
+you would pass ``{'active_object': object}``.
"""
# remove all objects in scene rather than the selected ones
diff --git a/doc/python_api/examples/bpy.ops.2.py b/doc/python_api/examples/bpy.ops.2.py
index cf6df946873..dd88c73d5e9 100644
--- a/doc/python_api/examples/bpy.ops.2.py
+++ b/doc/python_api/examples/bpy.ops.2.py
@@ -1,16 +1,19 @@
"""
+.. _operator-execution_context:
+
Execution Context
-----------------
When calling an operator you may want to pass the execution context.
-This determines the context thats given to the operator to run in, and weather
-invoke() is called or execute().
+This determines the context that is given for the operator to run in, and whether
+invoke() is called or only execute().
-'EXEC_DEFAULT' is used by default but you may want the operator to take user
-interaction with 'INVOKE_DEFAULT'.
+'EXEC_DEFAULT' is used by default, running only the execute() method, but you may
+want the operator to take user interaction with 'INVOKE_DEFAULT' which will also
+call invoke() if existing.
-The execution context is as a non keyword, string argument in:
+The execution context is one of:
('INVOKE_DEFAULT', 'INVOKE_REGION_WIN', 'INVOKE_REGION_CHANNELS',
'INVOKE_REGION_PREVIEW', 'INVOKE_AREA', 'INVOKE_SCREEN', 'EXEC_DEFAULT',
'EXEC_REGION_WIN', 'EXEC_REGION_CHANNELS', 'EXEC_REGION_PREVIEW', 'EXEC_AREA',
diff --git a/doc/python_api/examples/bpy.ops.py b/doc/python_api/examples/bpy.ops.py
index 9964ad915bf..76c494ad4f5 100644
--- a/doc/python_api/examples/bpy.ops.py
+++ b/doc/python_api/examples/bpy.ops.py
@@ -3,21 +3,21 @@ Calling Operators
-----------------
Provides python access to calling operators, this includes operators written in
-C, Python or Macros.
+C, Python or macros.
Only keyword arguments can be used to pass operator properties.
-Operators don't have return values as you might expect, instead they return a
-set() which is made up of: {'RUNNING_MODAL', 'CANCELLED', 'FINISHED',
-'PASS_THROUGH'}.
-Common return values are {'FINISHED'} and {'CANCELLED'}.
+Operators don't have return values as you might expect,
+instead they return a set() which is made up of:
+``{'RUNNING_MODAL', 'CANCELLED', 'FINISHED', 'PASS_THROUGH'}``.
+Common return values are ``{'FINISHED'}`` and ``{'CANCELLED'}``.
-Calling an operator in the wrong context will raise a RuntimeError,
+Calling an operator in the wrong context will raise a ``RuntimeError``,
there is a poll() method to avoid this problem.
-Note that the operator ID (bl_idname) in this example is 'mesh.subdivide',
-'bpy.ops' is just the access path for python.
+Note that the operator ID (bl_idname) in this example is ``mesh.subdivide``,
+``bpy.ops`` is just the access path for python.
Keywords and Positional Arguments
@@ -32,9 +32,9 @@ There are 3 optional positional arguments (documented in detail below).
bpy.ops.test.operator(override_context, execution_context, undo)
-* override_context - dict type
-* execution_context - string (enum)
-* undo - boolean
+- override_context - ``dict`` type.
+- execution_context - ``str`` (enum).
+- undo - ``bool`` type.
Each of these arguments is optional, but must be given in the order above.
diff --git a/doc/python_api/examples/bpy.props.2.py b/doc/python_api/examples/bpy.props.2.py
index 22fef5dc13a..ec9c838f5f2 100644
--- a/doc/python_api/examples/bpy.props.2.py
+++ b/doc/python_api/examples/bpy.props.2.py
@@ -3,7 +3,7 @@ PropertyGroup Example
+++++++++++++++++++++
PropertyGroups can be used for collecting custom settings into one value
-to avoid many indervidual settings mixed in together.
+to avoid many individual settings mixed in together.
"""
import bpy
diff --git a/doc/python_api/examples/bpy.props.py b/doc/python_api/examples/bpy.props.py
index f6bc55d6824..c199bd9b83a 100644
--- a/doc/python_api/examples/bpy.props.py
+++ b/doc/python_api/examples/bpy.props.py
@@ -6,7 +6,7 @@ Custom properties can be added to any subclass of an :class:`ID`,
:class:`Bone` and :class:`PoseBone`.
These properties can be animated, accessed by the user interface and python
-like blenders existing properties.
+like Blender's existing properties.
"""
import bpy
diff --git a/doc/python_api/examples/bpy.types.AddonPreferences.1.py b/doc/python_api/examples/bpy.types.AddonPreferences.1.py
index 73f90acb3fa..7a065dbf6a5 100644
--- a/doc/python_api/examples/bpy.types.AddonPreferences.1.py
+++ b/doc/python_api/examples/bpy.types.AddonPreferences.1.py
@@ -8,7 +8,8 @@ bl_info = {
"warning": "",
"wiki_url": "",
"tracker_url": "",
- "category": "Object"}
+ "category": "Object",
+ }
import bpy
diff --git a/doc/python_api/examples/bpy.types.Menu.1.py b/doc/python_api/examples/bpy.types.Menu.1.py
index e82bf398e35..8ccc1123c35 100644
--- a/doc/python_api/examples/bpy.types.Menu.1.py
+++ b/doc/python_api/examples/bpy.types.Menu.1.py
@@ -1,6 +1,7 @@
"""
Submenus
++++++++
+
This menu demonstrates some different functions.
"""
import bpy
diff --git a/doc/python_api/examples/bpy.types.Menu.2.py b/doc/python_api/examples/bpy.types.Menu.2.py
index c87b10cb6e7..86288b5b1c5 100644
--- a/doc/python_api/examples/bpy.types.Menu.2.py
+++ b/doc/python_api/examples/bpy.types.Menu.2.py
@@ -1,12 +1,12 @@
"""
Extending Menus
+++++++++++++++
-When creating menus for addons you can't reference menus in blenders default
-scripts.
-Instead the addon can add menu items to existing menus.
+When creating menus for addons you can't reference menus in Blender's default
+scripts.
+Instead, the addon can add menu items to existing menus.
-The function menu_draw acts like Menu.draw
+The function menu_draw acts like :class:`Menu.draw`.
"""
import bpy
diff --git a/doc/python_api/examples/bpy.types.Menu.py b/doc/python_api/examples/bpy.types.Menu.py
index 4ca18a67b78..c2162444055 100644
--- a/doc/python_api/examples/bpy.types.Menu.py
+++ b/doc/python_api/examples/bpy.types.Menu.py
@@ -1,21 +1,21 @@
"""
Basic Menu Example
++++++++++++++++++
-This script is a simple menu, menus differ from panels in that they must
+
+Here is an example of a simple menu. Menus differ from panels in that they must
reference from a header, panel or another menu.
-Notice the 'CATEGORY_MT_name' :class:`Menu.bl_idname`, this is a naming
+Notice the 'CATEGORY_MT_name' in :class:`Menu.bl_idname`, this is a naming
convention for menus.
.. note::
-
Menu subclasses must be registered before referencing them from blender.
.. note::
- Menu's have their :class:`Layout.operator_context` initialized as
- 'EXEC_REGION_WIN' rather then 'INVOKE_DEFAULT', so if the operator context
- needs to initialize inputs from the :class:`Operator.invoke` function
- then this needs to be explicitly set.
+ Menus have their :class:`Layout.operator_context` initialized as
+ 'EXEC_REGION_WIN' rather than 'INVOKE_DEFAULT' (see :ref:`Execution Context <operator-execution_context>`).
+ If the operator context needs to initialize inputs from the
+ :class:`Operator.invoke` function, then this needs to be explicitly set.
"""
import bpy
diff --git a/doc/python_api/examples/bpy.types.Mesh.py b/doc/python_api/examples/bpy.types.Mesh.py
index 19ccd177d64..68cc42ec6bf 100644
--- a/doc/python_api/examples/bpy.types.Mesh.py
+++ b/doc/python_api/examples/bpy.types.Mesh.py
@@ -7,10 +7,10 @@ for more flexible mesh editing from python see :mod:`bmesh`.
Blender stores 4 main arrays to define mesh geometry.
-* :class:`Mesh.vertices` (3 points in space)
-* :class:`Mesh.edges` (reference 2 vertices)
-* :class:`Mesh.loops` (reference a single vertex and edge)
-* :class:`Mesh.polygons`: (reference a range of loops)
+- :class:`Mesh.vertices` (3 points in space)
+- :class:`Mesh.edges` (reference 2 vertices)
+- :class:`Mesh.loops` (reference a single vertex and edge)
+- :class:`Mesh.polygons`: (reference a range of loops)
Each polygon reference a slice in the loop array, this way, polygons do not store vertices or corner data such as UV's directly,
diff --git a/doc/python_api/examples/bpy.types.NodeTree.py b/doc/python_api/examples/bpy.types.NodeTree.py
index 401b3a01ae0..da2986636ea 100644
--- a/doc/python_api/examples/bpy.types.NodeTree.py
+++ b/doc/python_api/examples/bpy.types.NodeTree.py
@@ -1,6 +1,7 @@
"""
Poll Function
+++++++++++++++
+
The :class:`NodeTree.poll` function determines if a node tree is visible
in the given context (similar to how :class:`Panel.poll`
and :class:`Menu.poll` define visibility). If it returns False,
diff --git a/doc/python_api/examples/bpy.types.Object.py b/doc/python_api/examples/bpy.types.Object.py
index 2ddce248a5b..90c50bcfad7 100644
--- a/doc/python_api/examples/bpy.types.Object.py
+++ b/doc/python_api/examples/bpy.types.Object.py
@@ -1,6 +1,7 @@
"""
Basic Object Operations Example
+++++++++++++++++++++++++++++++
+
This script demonstrates basic operations on object like creating new
object, placing it into scene, selecting it and making it active.
"""
diff --git a/doc/python_api/examples/bpy.types.Operator.1.py b/doc/python_api/examples/bpy.types.Operator.1.py
index fc016508d39..1ba13c040ba 100644
--- a/doc/python_api/examples/bpy.types.Operator.1.py
+++ b/doc/python_api/examples/bpy.types.Operator.1.py
@@ -1,6 +1,7 @@
"""
Invoke Function
+++++++++++++++
+
:class:`Operator.invoke` is used to initialize the operator from the context
at the moment the operator is called.
invoke() is typically used to assign properties which are then used by
@@ -31,7 +32,7 @@ class SimpleMouseOperator(bpy.types.Operator):
y = bpy.props.IntProperty()
def execute(self, context):
- # rather then printing, use the report function,
+ # rather than printing, use the report function,
# this way the message appears in the header,
self.report({'INFO'}, "Mouse coords are %d %d" % (self.x, self.y))
return {'FINISHED'}
diff --git a/doc/python_api/examples/bpy.types.Operator.2.py b/doc/python_api/examples/bpy.types.Operator.2.py
index 39ff5caae8a..e2f9a3a84c4 100644
--- a/doc/python_api/examples/bpy.types.Operator.2.py
+++ b/doc/python_api/examples/bpy.types.Operator.2.py
@@ -4,7 +4,7 @@ Calling a File Selector
This example shows how an operator can use the file selector.
Notice the invoke function calls a window manager method and returns
-RUNNING_MODAL, this means the file selector stays open and the operator does not
+``{'RUNNING_MODAL'}``, this means the file selector stays open and the operator does not
exit immediately after invoke finishes.
The file selector runs the operator, calling :class:`Operator.execute` when the
diff --git a/doc/python_api/examples/bpy.types.Operator.3.py b/doc/python_api/examples/bpy.types.Operator.3.py
index 7fdccd81379..d59c816319d 100644
--- a/doc/python_api/examples/bpy.types.Operator.3.py
+++ b/doc/python_api/examples/bpy.types.Operator.3.py
@@ -1,6 +1,7 @@
"""
Dialog Box
++++++++++
+
This operator uses its :class:`Operator.invoke` function to call a popup.
"""
import bpy
diff --git a/doc/python_api/examples/bpy.types.Operator.4.py b/doc/python_api/examples/bpy.types.Operator.4.py
index 885ed857842..e5bc6e5c70d 100644
--- a/doc/python_api/examples/bpy.types.Operator.4.py
+++ b/doc/python_api/examples/bpy.types.Operator.4.py
@@ -1,6 +1,7 @@
"""
Custom Drawing
++++++++++++++
+
By default operator properties use an automatic user interface layout.
If you need more control you can create your own layout with a
:class:`Operator.draw` function.
diff --git a/doc/python_api/examples/bpy.types.Operator.5.py b/doc/python_api/examples/bpy.types.Operator.5.py
index 78030c7d7c4..310eeceadf3 100644
--- a/doc/python_api/examples/bpy.types.Operator.5.py
+++ b/doc/python_api/examples/bpy.types.Operator.5.py
@@ -1,8 +1,9 @@
"""
Modal Execution
+++++++++++++++
+
This operator defines a :class:`Operator.modal` function which running,
-handling events until it returns {'FINISHED'} or {'CANCELLED'}.
+handling events until it returns ``{'FINISHED'}`` or ``{'CANCELLED'}``.
Grab, Rotate, Scale and Fly-Mode are examples of modal operators.
They are especially useful for interactive tools,
@@ -10,9 +11,9 @@ your operator can have its own state where keys toggle options as the operator
runs.
:class:`Operator.invoke` is used to initialize the operator as being by
-returning {'RUNNING_MODAL'}, initializing the modal loop.
+returning ``{'RUNNING_MODAL'}``, initializing the modal loop.
-Notice __init__() and __del__() are declared.
+Notice ``__init__()`` and ``__del__()`` are declared.
For other operator types they are not useful but for modal operators they will
be called before the :class:`Operator.invoke` and after the operator finishes.
"""
diff --git a/doc/python_api/examples/bpy.types.Operator.py b/doc/python_api/examples/bpy.types.Operator.py
index 0981712e1ff..4baa9380aa6 100644
--- a/doc/python_api/examples/bpy.types.Operator.py
+++ b/doc/python_api/examples/bpy.types.Operator.py
@@ -1,6 +1,7 @@
"""
Basic Operator Example
++++++++++++++++++++++
+
This script shows simple operator which prints a message.
Since the operator only has an :class:`Operator.execute` function it takes no
diff --git a/doc/python_api/examples/bpy.types.Panel.1.py b/doc/python_api/examples/bpy.types.Panel.1.py
index fbcdae8baeb..13a9f53fa7b 100644
--- a/doc/python_api/examples/bpy.types.Panel.1.py
+++ b/doc/python_api/examples/bpy.types.Panel.1.py
@@ -1,6 +1,7 @@
"""
Simple Object Panel
+++++++++++++++++++
+
This panel has a :class:`Panel.poll` and :class:`Panel.draw_header` function,
even though the contents is basic this closely resembles blenders panels.
"""
diff --git a/doc/python_api/examples/bpy.types.Panel.2.py b/doc/python_api/examples/bpy.types.Panel.2.py
index a4b2f1fd338..261430f1396 100644
--- a/doc/python_api/examples/bpy.types.Panel.2.py
+++ b/doc/python_api/examples/bpy.types.Panel.2.py
@@ -7,7 +7,7 @@ A mix-in parent class can be used to share common properties and
import bpy
-class View3DPanel():
+class View3DPanel:
bl_space_type = 'VIEW_3D'
bl_region_type = 'TOOLS'
diff --git a/doc/python_api/examples/bpy.types.Panel.py b/doc/python_api/examples/bpy.types.Panel.py
index 1f64b953786..98187832b56 100644
--- a/doc/python_api/examples/bpy.types.Panel.py
+++ b/doc/python_api/examples/bpy.types.Panel.py
@@ -1,6 +1,7 @@
"""
Basic Panel Example
+++++++++++++++++++
+
This script is a simple panel which will draw into the object properties
section.
diff --git a/doc/python_api/examples/bpy.types.UIList.2.py b/doc/python_api/examples/bpy.types.UIList.2.py
index feed263b2e7..a02a0530a66 100644
--- a/doc/python_api/examples/bpy.types.UIList.2.py
+++ b/doc/python_api/examples/bpy.types.UIList.2.py
@@ -1,7 +1,8 @@
"""
Advanced UIList Example - Filtering and Reordering
++++++++++++++++++++++++++++++++++++++++++++++++++
-This script is an extended version of the UIList subclass used to show vertex groups. It is not used 'as is',
+
+This script is an extended version of the ``UIList`` subclass used to show vertex groups. It is not used 'as is',
because iterating over all vertices in a 'draw' function is a very bad idea for UI performances! However, it's a good
example of how to create/use filtering/reordering callbacks.
"""
diff --git a/doc/python_api/examples/bpy.types.bpy_struct.keyframe_insert.1.py b/doc/python_api/examples/bpy.types.bpy_struct.keyframe_insert.1.py
index faf3b121ec6..6889fe75277 100644
--- a/doc/python_api/examples/bpy.types.bpy_struct.keyframe_insert.1.py
+++ b/doc/python_api/examples/bpy.types.bpy_struct.keyframe_insert.1.py
@@ -1,7 +1,7 @@
"""
Note that when keying data paths which contain nested properties this must be
done from the :class:`ID` subclass, in this case the :class:`Armature` rather
-then the bone.
+than the bone.
"""
import bpy
diff --git a/doc/python_api/examples/mathutils.Quaternion.py b/doc/python_api/examples/mathutils.Quaternion.py
index d8c696e6ba6..7e5538b7a96 100644
--- a/doc/python_api/examples/mathutils.Quaternion.py
+++ b/doc/python_api/examples/mathutils.Quaternion.py
@@ -21,3 +21,12 @@ print(quat_out)
print("%.2f, %.2f, %.2f" % tuple(math.degrees(a) for a in quat_out.to_euler()))
print("(%.2f, %.2f, %.2f), %.2f" % (quat_out.axis[:] +
(math.degrees(quat_out.angle), )))
+
+# multiple rotations can be interpolated using the exponential map
+quat_c = mathutils.Quaternion((1.0, 0.0, 0.0), math.radians(15.0))
+exp_avg = (quat_a.to_exponential_map() +
+ quat_b.to_exponential_map() +
+ quat_c.to_exponential_map()) / 3.0
+quat_avg = mathutils.Quaternion(exp_avg)
+print("Average rotation:")
+print(quat_avg)
diff --git a/doc/python_api/examples/mathutils.Vector.py b/doc/python_api/examples/mathutils.Vector.py
index 14b8829c3b5..3f79fdebff1 100644
--- a/doc/python_api/examples/mathutils.Vector.py
+++ b/doc/python_api/examples/mathutils.Vector.py
@@ -18,16 +18,16 @@ matrix = mathutils.Matrix()
# Comparison operators can be done on Vector classes:
-# greater and less then test vector length.
+# (In)equality operators == and != test component values, e.g. 1,2,3 != 3,2,1
+vec_a == vec_b
+vec_a != vec_b
+
+# Ordering operators >, >=, > and <= test vector length.
vec_a > vec_b
vec_a >= vec_b
vec_a < vec_b
vec_a <= vec_b
-# ==, != test vector values e.g. 1,2,3 != 3,2,1 even if they are the same length
-vec_a == vec_b
-vec_a != vec_b
-
# Math can be performed on Vector classes
vec_a + vec_b
diff --git a/doc/python_api/rst/bge.app.rst b/doc/python_api/rst/bge.app.rst
new file mode 100644
index 00000000000..a0c2cf36314
--- /dev/null
+++ b/doc/python_api/rst/bge.app.rst
@@ -0,0 +1,47 @@
+
+Application Data (bge.app)
+==========================
+
+Module to access application values that remain unchanged during runtime.
+
+.. module:: bge.app
+
+.. data:: version
+
+ The Blender/BGE version as a tuple of 3 ints, eg. (2, 75, 1).
+
+ .. note:: Version tuples can be compared simply with (in)equality symbols;
+ for example, ``(2, 74, 5) <= (2, 75, 0)`` returns True (lexical order).
+
+ :type: tuple of three ints
+
+.. data:: version_string
+
+ The Blender/BGE version formatted as a string, eg. "2.75 (sub 1)".
+
+ :type: str
+
+.. data:: version_char
+
+ The Blender/BGE version character (for minor releases).
+
+ :type: str
+
+.. data:: has_texture_ffmpeg
+
+ True if the BGE has been built with FFmpeg support, enabling use of :class:`~bge.texture.ImageFFmpeg` and :class:`~bge.texture.VideoFFmpeg`.
+
+ :type: bool
+
+.. data:: has_joystick
+
+ True if the BGE has been built with joystick support.
+
+ :type: bool
+
+.. data:: has_physics
+
+ True if the BGE has been built with physics support.
+
+ :type: bool
+
diff --git a/doc/python_api/rst/bge.constraints.rst b/doc/python_api/rst/bge.constraints.rst
index 018be96fd14..bf015057dcb 100644
--- a/doc/python_api/rst/bge.constraints.rst
+++ b/doc/python_api/rst/bge.constraints.rst
@@ -4,72 +4,77 @@ Physics Constraints (bge.constraints)
.. module:: bge.constraints
-.. literalinclude:: ../examples/bge.constraints.py
- :language: rest
- :lines: 2-4
+
+Examples
+--------
+
+.. include:: ../examples/bge.constraints.py
+ :start-line: 1
+ :end-line: 4
.. literalinclude:: ../examples/bge.constraints.py
:lines: 6-
-.. function:: createConstraint(physicsid, physicsid2, constrainttype, [pivotX, pivotY, pivotZ, [axisX, axisY, axisZ, [flag]]]])
- Creates a constraint.
+Functions
+---------
- :arg physicsid: the physics id of the first object in constraint
- :type physicsid: int
+.. function:: createConstraint( \
+ physicsid_1, physicsid_2, constraint_type, \
+ pivot_x=0.0, pivot_y=0.0, pivot_z=0.0, \
+ axis_x=0.0, axis_y=0.0, axis_z=0.0, flag=0)
- :arg physicsid2: the physics id of the second object in constraint
- :type physicsid2: int
+ Creates a constraint.
- :arg constrainttype: the type of the constraint. The constraint types are:
+ :arg physicsid_1: The physics id of the first object in constraint.
+ :type physicsid_1: int
- - :class:`POINTTOPOINT_CONSTRAINT`
- - :class:`LINEHINGE_CONSTRAINT`
- - :class:`ANGULAR_CONSTRAINT`
- - :class:`CONETWIST_CONSTRAINT`
- - :class:`VEHICLE_CONSTRAINT`
- - :class:`GENERIC_6DOF_CONSTRAINT`
+ :arg physicsid_2: The physics id of the second object in constraint.
+ :type physicsid_2: int
- :type constrainttype: int
+ :arg constraint_type: The type of the constraint, see `Create Constraint Constants`_.
- :arg pivotX: pivot X position
- :type pivotX: float
+ :type constraint_type: int
- :arg pivotY: pivot Y position
- :type pivotY: float
+ :arg pivot_x: Pivot X position. (optional)
+ :type pivot_x: float
- :arg pivotZ: pivot Z position
- :type pivotZ: float
+ :arg pivot_y: Pivot Y position. (optional)
+ :type pivot_y: float
- :arg axisX: X axis
- :type axisX: float
+ :arg pivot_z: Pivot Z position. (optional)
+ :type pivot_z: float
- :arg axisY: Y axis
- :type axisY: float
+ :arg axis_x: X axis angle in degrees. (optional)
+ :type axis_x: float
- :arg axisZ: Z axis
- :type axisZ: float
+ :arg axis_y: Y axis angle in degrees. (optional)
+ :type axis_y: float
- :arg flag: 128 to disable collision between linked bodies
- :type flag: int
+ :arg axis_z: Z axis angle in degrees. (optional)
+ :type axis_z: float
-.. attribute:: error
+ :arg flag: 128 to disable collision between linked bodies. (optional)
+ :type flag: int
- Simbolic constant string that indicates error.
+ :return: A constraint wrapper.
+ :rtype: :class:`~bge.types.KX_ConstraintWrapper`
.. function:: exportBulletFile(filename)
- export a .bullet file
+ Exports a file representing the dynamics world (usually using ``.bullet`` extension).
+
+ See `Bullet binary serialization <http://bulletphysics.org/mediawiki-1.5.8/index.php/Bullet_binary_serialization>`__.
- :arg filename: File name
- :type filename: string
+ :arg filename: File path.
+ :type filename: str
.. function:: getAppliedImpulse(constraintId)
:arg constraintId: The id of the constraint.
:type constraintId: int
- :return: the most recent applied impulse.
+ :return: The most recent applied impulse.
:rtype: float
.. function:: getVehicleConstraint(constraintId)
@@ -77,16 +82,16 @@ Physics Constraints (bge.constraints)
:arg constraintId: The id of the vehicle constraint.
:type constraintId: int
- :return: a vehicle constraint object.
- :rtype: :class:`bge.types.KX_VehicleWrapper`
+ :return: A vehicle constraint object.
+ :rtype: :class:`~bge.types.KX_VehicleWrapper`
.. function:: getCharacter(gameobj)
:arg gameobj: The game object with the character physics.
- :type gameobj: :class:`bge.types.KX_GameObject`
+ :type gameobj: :class:`~bge.types.KX_GameObject`
- :return: character wrapper
- :rtype: :class:`bge.types.KX_CharacterWrapper`
+ :return: Character wrapper.
+ :rtype: :class:`~bge.types.KX_CharacterWrapper`
.. function:: removeConstraint(constraintId)
@@ -140,23 +145,8 @@ Physics Constraints (bge.constraints)
Sets the debug mode.
- Debug modes:
- - :class:`DBG_NODEBUG`
- - :class:`DBG_DRAWWIREFRAME`
- - :class:`DBG_DRAWAABB`
- - :class:`DBG_DRAWFREATURESTEXT`
- - :class:`DBG_DRAWCONTACTPOINTS`
- - :class:`DBG_NOHELPTEXT`
- - :class:`DBG_DRAWTEXT`
- - :class:`DBG_PROFILETIMINGS`
- - :class:`DBG_ENABLESATCOMPARISION`
- - :class:`DBG_DISABLEBULLETLCP`
- - :class:`DBG_ENABLECCD`
- - :class:`DBG_DRAWCONSTRAINTS`
- - :class:`DBG_DRAWCONSTRAINTLIMITS`
- - :class:`DBG_FASTWIREFRAME`
-
- :arg mode: The new debug mode.
+ :arg mode: The new debug mode, see `Debug Mode Constants`_.
+
:type mode: int
.. function:: setGravity(x, y, z)
@@ -175,7 +165,8 @@ Physics Constraints (bge.constraints)
.. function:: setLinearAirDamping(damping)
.. note::
- Not implemented.
+
+ Not implemented
Sets the linear air damping for rigidbodies.
@@ -235,144 +226,111 @@ Physics Constraints (bge.constraints)
.. function:: setUseEpa(epa)
- Not implemented.
+ .. note::
-.. data:: DBG_NODEBUG
+ Not implemented
- .. note::
- Debug mode to be used with function :class:`setDebugMode`
+
+Constants
++++++++++
+
+.. attribute:: error
+
+ Symbolic constant string that indicates error.
+
+ :type: str
+
+
+Debug Mode Constants
+^^^^^^^^^^^^^^^^^^^^
+
+Debug mode to be used with :func:`setDebugMode`.
+
+
+.. data:: DBG_NODEBUG
No debug.
.. data:: DBG_DRAWWIREFRAME
- .. note::
- Debug mode to be used with function :class:`setDebugMode`
-
Draw wireframe in debug.
.. data:: DBG_DRAWAABB
- .. note::
- Debug mode to be used with function :class:`setDebugMode`
-
Draw Axis Aligned Bounding Box in debug.
.. data:: DBG_DRAWFREATURESTEXT
- .. note::
- Debug mode to be used with function :class:`setDebugMode`
-
- Draw freatures text in debug.
+ Draw features text in debug.
.. data:: DBG_DRAWCONTACTPOINTS
- .. note::
- Debug mode to be used with function :class:`setDebugMode`
-
Draw contact points in debug.
.. data:: DBG_NOHELPTEXT
- .. note::
- Debug mode to be used with function :class:`setDebugMode`
-
Debug without help text.
.. data:: DBG_DRAWTEXT
- .. note::
- Debug mode to be used with function :class:`setDebugMode`
-
Draw text in debug.
.. data:: DBG_PROFILETIMINGS
- .. note::
- Debug mode to be used with function :class:`setDebugMode`
-
Draw profile timings in debug.
.. data:: DBG_ENABLESATCOMPARISION
- .. note::
- Debug mode to be used with function :class:`setDebugMode`
-
Enable sat comparision in debug.
.. data:: DBG_DISABLEBULLETLCP
- .. note::
- Debug mode to be used with function :class:`setDebugMode`
-
Disable Bullet LCP.
.. data:: DBG_ENABLECCD
- .. note::
- Debug mode to be used with function :class:`setDebugMode`
-
- Enable Continous Colision Detection in debug.
+ Enable Continous Collision Detection in debug.
.. data:: DBG_DRAWCONSTRAINTS
- .. note::
- Debug mode to be used with function :class:`setDebugMode`
-
Draw constraints in debug.
.. data:: DBG_DRAWCONSTRAINTLIMITS
- .. note::
- Debug mode to be used with function :class:`setDebugMode`
-
Draw constraint limits in debug.
.. data:: DBG_FASTWIREFRAME
- .. note::
- Debug mode to be used with function :class:`setDebugMode`
-
Draw a fast wireframe in debug.
-.. data:: POINTTOPOINT_CONSTRAINT
- .. note::
- Constraint type to be used with function :class:`createConstraint`
+Create Constraint Constants
+^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Constraint type to be used with :func:`createConstraint`.
+
+
+.. data:: POINTTOPOINT_CONSTRAINT
.. to do
.. data:: LINEHINGE_CONSTRAINT
- .. note::
- Constraint type to be used with function :class:`createConstraint`
-
.. to do
.. data:: ANGULAR_CONSTRAINT
- .. note::
- Constraint type to be used with function :class:`createConstraint`
-
.. to do
.. data:: CONETWIST_CONSTRAINT
- .. note::
- Constraint type to be used with function :class:`createConstraint`
-
.. to do
.. data:: VEHICLE_CONSTRAINT
- .. note::
- Constraint type to be used with function :class:`createConstraint`
-
.. to do
.. data:: GENERIC_6DOF_CONSTRAINT
- .. note::
- Constraint type to be used with function :class:`createConstraint`
-
.. to do
+
diff --git a/doc/python_api/rst/bge.logic.rst b/doc/python_api/rst/bge.logic.rst
index d901a4e4207..57d9f1ab5e5 100644
--- a/doc/python_api/rst/bge.logic.rst
+++ b/doc/python_api/rst/bge.logic.rst
@@ -337,6 +337,28 @@ General functions
.. warning: Not implimented yet
+.. function:: getAnimRecordFrame()
+
+ Gets the current frame number used for recording animations. This
+ number is incremented automatically by Blender when the "Record
+ animation" feature is turned on.
+
+ :rtype: int
+
+.. function:: setAnimRecordFrame(framenr)
+
+ Sets the current frame number used for recording animations. This
+ number is automatically incremented by Blender when the "Record
+ animation" feature is turned on.
+
+ The frame number Must be non-negative, unless Blender has
+ :attr:`bpy.types.UserPreferencesEdit.use_negative_frames` enabled
+ in its user preferences. Only use non-negative numbers to be on
+ the safe side, unless you know what you are doing.
+
+ :arg framenr: The new frame number.
+ :type framenr: int
+
.. function:: getExitKey()
Gets the key used to exit the game engine
@@ -894,6 +916,8 @@ Various
2D Filter
---------
+.. _Two-D-FilterActuator-mode:
+
.. data:: RAS_2DFILTER_BLUR
:value: 2
@@ -1288,5 +1312,3 @@ See :class:`bge.types.KX_StateActuator.operation`
Add bits to state mask
:value: 3
-
-.. _Two-D-FilterActuator-mode:
diff --git a/doc/python_api/rst/bge.render.rst b/doc/python_api/rst/bge.render.rst
index 9dd4057c82f..2afb2796249 100644
--- a/doc/python_api/rst/bge.render.rst
+++ b/doc/python_api/rst/bge.render.rst
@@ -8,9 +8,14 @@ Intro
.. module:: bge.render
+Example of using a :class:`bge.types.SCA_MouseSensor`,
+and two :class:`bge.types.KX_ObjectActuator` to implement MouseLook:
+
+.. note::
+ This can also be achieved with the :class:`bge.types.KX_MouseActuator`.
+
.. code-block:: python
- # Example Uses an L{SCA_MouseSensor}, and two L{KX_ObjectActuator}s to implement MouseLook::
# To use a mouse movement sensor "Mouse" and a
# motion actuator to mouse look:
import bge
@@ -62,7 +67,7 @@ Constants
.. data:: KX_BLENDER_GLSL_MATERIAL
Materials approximating blender materials with GLSL.
-
+
.. DATA:: VSYNC_OFF
Disables vsync
@@ -73,7 +78,18 @@ Constants
.. DATA:: VSYNC_ADAPTIVE
- Enables adaptive vsync if supported. Adaptive vsync enables vsync if the framerate is above the monitors refresh rate. Otherwise, vsync is diabled if the framerate is too low.
+ Enables adaptive vsync if supported.
+ Adaptive vsync enables vsync if the framerate is above the monitors refresh rate.
+ Otherwise, vsync is diabled if the framerate is too low.
+
+.. data:: LEFT_EYE
+
+ Left eye being used during stereoscopic rendering.
+
+.. data:: RIGHT_EYE
+
+ Right eye being used during stereoscopic rendering.
+
*********
Functions
@@ -82,47 +98,64 @@ Functions
.. function:: getWindowWidth()
Gets the width of the window (in pixels)
-
+
:rtype: integer
.. function:: getWindowHeight()
Gets the height of the window (in pixels)
-
+
:rtype: integer
.. function:: setWindowSize(width, height)
Set the width and height of the window (in pixels). This also works for fullscreen applications.
-
+
+ .. note:: Only works in the standalone player, not the Blender-embedded player.
+
:type width: integer
:type height: integer
.. function:: setFullScreen(enable)
Set whether or not the window should be fullscreen.
-
+
+ .. note:: Only works in the standalone player, not the Blender-embedded player.
+
:type enable: bool
.. function:: getFullScreen()
Returns whether or not the window is fullscreen.
-
+
+ .. note:: Only works in the standalone player, not the Blender-embedded player; there it always returns False.
+
:rtype: bool
-.. function:: makeScreenshot(filename)
+.. function:: getDisplayDimensions()
- Writes a screenshot to the given filename.
-
- If filename starts with // the image will be saved relative to the current directory.
- If the filename contains # it will be replaced with the frame number.
-
- The standalone player saves .png files. It does not support color space conversion
- or gamma correction.
-
- When run from Blender, makeScreenshot supports all Blender image file formats like PNG, TGA, Jpeg and OpenEXR.
- Gamma, Colorspace conversion and Jpeg compression are taken from the Render settings panels.
+ Get the actual display dimensions, in pixels, of the physical display (e.g., the monitor).
+ :type dimension: list [width,heigh]
+
+.. function:: makeScreenshot(filename)
+
+ Writes an image file with the current displayed frame.
+
+ The image is written to *'filename'*.
+ The path may be absolute (eg. ``/home/foo/image``) or relative when started with
+ ``//`` (eg. ``//image``). Note that absolute paths are not portable between platforms.
+ If the filename contains a ``#``,
+ it will be replaced by an incremental index so that screenshots can be taken multiple
+ times without overwriting the previous ones (eg. ``image-#``).
+
+ Settings for the image are taken from the render settings (file format and respective settings,
+ gamma and colospace conversion, etc).
+ The image resolution matches the framebuffer, meaning, the window size and aspect ratio.
+ When running from the standalone player, instead of the embedded player, only PNG files are supported.
+ Additional color conversions are also not supported.
+
+ :arg filename: path and name of the file to write
:type filename: string
@@ -134,65 +167,29 @@ Functions
.. function:: showMouse(visible)
Enables or disables the operating system mouse cursor.
-
+
:type visible: boolean
.. function:: setMousePosition(x, y)
Sets the mouse cursor position.
-
+
:type x: integer
:type y: integer
.. function:: setBackgroundColor(rgba)
- Sets the window background color.
-
- :type rgba: list [r, g, b, a]
-
-
-.. function:: setMistColor(rgb)
-
- Sets the mist color.
-
- :type rgb: list [r, g, b]
-
-
-.. function:: setAmbientColor(rgb)
-
- Sets the color of ambient light.
-
- :type rgb: list [r, g, b]
-
-
-.. function:: setMistStart(start)
-
- Sets the mist start value. Objects further away than start will have mist applied to them.
-
- :type start: float
+ Sets the window background color. (Deprecated: use KX_WorldInfo.background_color)
+ :type rgba: list [r, g, b, a]
-.. function:: setMistEnd(end)
-
- Sets the mist end value. Objects further away from this will be colored solid with
- the color set by setMistColor().
-
- :type end: float
-
-
-.. function:: disableMist()
-
- Disables mist.
-
- .. note:: Set any of the mist properties to enable mist.
-
.. function:: setEyeSeparation(eyesep)
Sets the eye separation for stereo mode. Usually Focal Length/30 provides a confortable value.
-
+
:arg eyesep: The distance between the left and right eye.
:type eyesep: float
@@ -200,27 +197,36 @@ Functions
.. function:: getEyeSeparation()
Gets the current eye separation for stereo mode.
-
+
:rtype: float
-
+
.. function:: setFocalLength(focallength)
Sets the focal length for stereo mode. It uses the current camera focal length as initial value.
-
- :arg focallength: The focal length.
+
+ :arg focallength: The focal length.
:type focallength: float
.. function:: getFocalLength()
Gets the current focal length for stereo mode.
-
+
:rtype: float
+.. function:: getStereoEye()
+
+ Gets the current stereoscopy eye being rendered.
+ This function is mainly used in a :class:`bge.types.KX_Scene.pre_draw` callback
+ function to customize the camera projection matrices for each
+ stereoscopic eye.
+
+ :rtype: LEFT_EYE, RIGHT_EYE
+
.. function:: setMaterialMode(mode)
Set the material mode to use for OpenGL rendering.
-
+
:type mode: KX_TEXFACE_MATERIAL, KX_BLENDER_MULTITEX_MATERIAL, KX_BLENDER_GLSL_MATERIAL
.. note:: Changes will only affect newly created scenes.
@@ -229,14 +235,14 @@ Functions
.. function:: getMaterialMode(mode)
Get the material mode to use for OpenGL rendering.
-
+
:rtype: KX_TEXFACE_MATERIAL, KX_BLENDER_MULTITEX_MATERIAL, KX_BLENDER_GLSL_MATERIAL
.. function:: setGLSLMaterialSetting(setting, enable)
Enables or disables a GLSL material setting.
-
+
:type setting: string (lights, shaders, shadows, ramps, nodes, extra_textures)
:type enable: boolean
@@ -244,43 +250,43 @@ Functions
.. function:: getGLSLMaterialSetting(setting, enable)
Get the state of a GLSL material setting.
-
+
:type setting: string (lights, shaders, shadows, ramps, nodes, extra_textures)
:rtype: boolean
.. function:: setAnisotropicFiltering(level)
Set the anisotropic filtering level for textures.
-
+
:arg level: The new anisotropic filtering level to use
:type level: integer (must be one of 1, 2, 4, 8, 16)
-
+
.. note:: Changing this value can cause all textures to be recreated, which can be slow.
-
+
.. function:: getAnisotropicFiltering()
Get the anisotropic filtering level used for textures.
-
+
:rtype: integer (one of 1, 2, 4, 8, 16)
.. function:: setMipmapping(value)
Change how to use mipmapping.
-
+
:type value: RAS_MIPMAP_NONE, RAS_MIPMAP_NEAREST, RAS_MIPMAP_LINEAR
-
+
.. note:: Changing this value can cause all textures to be recreated, which can be slow.
.. function:: getMipmapping()
Get the current mipmapping setting.
-
+
:rtype: RAS_MIPMAP_NONE, RAS_MIPMAP_NEAREST, RAS_MIPMAP_LINEAR
-
+
.. function:: drawLine(fromVec,toVec,color)
Draw a line in the 3D scene.
-
+
:arg fromVec: the origin of the line
:type fromVec: list [x, y, z]
:arg toVec: the end of the line
@@ -292,7 +298,7 @@ Functions
.. function:: enableMotionBlur(factor)
Enable the motion blur effect.
-
+
:arg factor: the ammount of motion blur to display.
:type factor: float [0.0 - 1.0]
diff --git a/doc/python_api/rst/bge.texture.rst b/doc/python_api/rst/bge.texture.rst
index 0c9e9da0661..4588a3e1800 100644
--- a/doc/python_api/rst/bge.texture.rst
+++ b/doc/python_api/rst/bge.texture.rst
@@ -2,9 +2,9 @@
Video Texture (bge.texture)
===========================
-*****
-Intro
-*****
+************
+Introduction
+************
The bge.texture module allows you to manipulate textures during the game.
@@ -14,7 +14,7 @@ The video and image files can be loaded from the internet using an URL instead o
In addition, you can apply filters on the images before sending them to the GPU, allowing video effect: blue screen, color band, gray, normal map.
-bge.texture uses FFmpeg to load images and videos. All the formats and codecs that FFmpeg supports are supported by this module, including but not limited to::
+bge.texture uses FFmpeg to load images and videos. All the formats and codecs that FFmpeg supports are supported by this module, including but not limited to:
* AVI
* Ogg
@@ -26,7 +26,7 @@ bge.texture uses FFmpeg to load images and videos. All the formats and codecs th
* JPG
The principle is simple: first you identify a texture on an existing object using
-the :materialID: function, then you create a new texture with dynamic content
+the :class:`~bge.texture.materialID` function, then you create a new texture with dynamic content
and swap the two textures in the GPU.
The GE is not aware of the substitution and continues to display the object as always,
@@ -36,538 +36,998 @@ When the texture object is deleted, the new texture is deleted and the old textu
.. module:: bge.texture
+.. include:: ../examples/bge.texture.py
+ :start-line: 1
+ :end-line: 5
+
.. literalinclude:: ../examples/bge.texture.py
- :language: rest
- :lines: 2-4
-
-.. literalinclude:: ../examples/bge.texture.py
- :lines: 6-
-
-.. literalinclude:: ../examples/bge.texture.1.py
- :language: rest
- :lines: 2-6
+ :lines: 7-
+.. include:: ../examples/bge.texture.1.py
+ :start-line: 1
+ :end-line: 6
+
.. literalinclude:: ../examples/bge.texture.1.py
:lines: 8-
-
-.. class:: VideoFFmpeg(file [, capture=-1, rate=25.0, width=0, height=0])
-
- FFmpeg video source
+
+
+*************
+Video classes
+*************
+
+.. class:: VideoFFmpeg(file, capture=-1, rate=25.0, width=0, height=0)
+
+ FFmpeg video source.
+
+ :arg file: Path to the video to load; if capture >= 0 on Windows, this parameter will not be used.
+ :type file: str
+ :arg capture: Capture device number; if >= 0, the corresponding webcam will be used. (optional)
+ :type capture: int
+ :arg rate: Capture rate. (optional, used only if capture >= 0)
+ :type rate: float
+ :arg width: Capture width. (optional, used only if capture >= 0)
+ :type width: int
+ :arg height: Capture height. (optional, used only if capture >= 0)
+ :type height: int
.. attribute:: status
- video status
+ Video status. (readonly)
+
+ :type: int
+ :value: see `FFmpeg Video and Image Status`_.
.. attribute:: range
- replay range
+ Replay range.
+
+ :type: sequence of two floats
.. attribute:: repeat
- repeat count, -1 for infinite repeat
+ Repeat count, -1 for infinite repeat.
:type: int
.. attribute:: framerate
- frame rate
+ Frame rate.
:type: float
.. attribute:: valid
- Tells if an image is available
+ Tells if an image is available. (readonly)
:type: bool
.. attribute:: image
- image data
+ Image data. (readonly)
+
+ :type: :class:`~bgl.Buffer` or None
.. attribute:: size
- image size
+ Image size. (readonly)
+
+ :type: tuple of two ints
.. attribute:: scale
- fast scale of image (near neighbour)
+ Fast scale of image (near neighbour).
+
+ :type: bool
.. attribute:: flip
- flip image vertically
+ Flip image vertically.
+
+ :type: bool
.. attribute:: filter
- pixel filter
+ Pixel filter.
+
+ :type: one of...
+
+ * :class:`FilterBGR24`
+ * :class:`FilterBlueScreen`
+ * :class:`FilterColor`
+ * :class:`FilterGray`
+ * :class:`FilterLevel`
+ * :class:`FilterNormal`
+ * :class:`FilterRGB24`
+ * :class:`FilterRGBA32`
.. attribute:: preseek
- number of frames of preseek
+ Number of frames of preseek.
:type: int
.. attribute:: deinterlace
- deinterlace image
+ Deinterlace image.
:type: bool
.. method:: play()
- Play (restart) video
+ Play (restart) video.
+
+ :return: Whether the video was ready or stopped.
+ :rtype: bool
.. method:: pause()
- pause video
+ Pause video.
+
+ :return: Whether the video was playing.
+ :rtype: bool
.. method:: stop()
- stop video (play will replay it from start)
+ Stop video (play will replay it from start).
+
+ :return: Whether the video was playing.
+ :rtype: bool
.. method:: refresh()
- Refresh video - get its status
+ Refresh video - get its status.
+
+ :value: see `FFmpeg Video and Image Status`_.
+
+ :rtype: int
+
+*************
+Image classes
+*************
.. class:: ImageFFmpeg(file)
- FFmpeg image source
+ FFmpeg image source.
+
+ :arg file: Path to the image to load.
+ :type file: str
.. attribute:: status
- video status
+ Image status. (readonly)
+
+ :type: int
+ :value: see `FFmpeg Video and Image Status`_.
.. attribute:: valid
- Tells if an image is available
+ Tells if an image is available. (readonly)
:type: bool
.. attribute:: image
- image data
+ Image data. (readonly)
+
+ :type: :class:`~bgl.Buffer` or None
.. attribute:: size
- image size
+ Image size. (readonly)
+
+ :type: tuple of two ints
.. attribute:: scale
- fast scale of image (near neighbour)
+ Fast scale of image (near neighbour).
+
+ :type: bool
.. attribute:: flip
- flip image vertically
+ Flip image vertically.
+
+ :type: bool
.. attribute:: filter
- pixel filter
+ Pixel filter.
+
+ :type: one of...
+
+ * :class:`FilterBGR24`
+ * :class:`FilterBlueScreen`
+ * :class:`FilterColor`
+ * :class:`FilterGray`
+ * :class:`FilterLevel`
+ * :class:`FilterNormal`
+ * :class:`FilterRGB24`
+ * :class:`FilterRGBA32`
.. method:: refresh()
- Refresh image, i.e. load it
+ Refresh image, i.e. load it.
+
+ :value: see `FFmpeg Video and Image Status`_.
+
+ :rtype: int
- .. method:: reload([newname])
+ .. method:: reload(newname=None)
- Reload image, i.e. reopen it
+ Reload image, i.e. reopen it.
+
+ :arg newname: Path to a new image. (optional)
+ :type newname: str
-.. class:: ImageBuff()
+.. class:: ImageBuff(width, height, color=0, scale=False)
- Image source from image buffer
+ Image source from image buffer.
+
+ :arg width: Width of the image.
+ :type width: int
+ :arg height: Height of the image.
+ :type height: int
+ :arg color: Value to initialize RGB channels with. The initialized buffer will have
+ all pixels set to (color, color, color, 255). (optional)
+ :type color: int in [0, 255]
+ :arg scale: Image uses scaling. (optional)
+ :type scale: bool
.. attribute:: filter
- pixel filter
+ Pixel filter.
+
+ :type: one of...
+
+ * :class:`FilterBGR24`
+ * :class:`FilterBlueScreen`
+ * :class:`FilterColor`
+ * :class:`FilterGray`
+ * :class:`FilterLevel`
+ * :class:`FilterNormal`
+ * :class:`FilterRGB24`
+ * :class:`FilterRGBA32`
.. attribute:: flip
- flip image vertically
+ Flip image vertically.
+
+ :type: bool
.. attribute:: image
- image data
+ Image data. (readonly)
+
+ :type: :class:`~bgl.Buffer` or None
.. method:: load(imageBuffer, width, height)
- Load image from buffer
-
- .. method:: plot(imageBuffer, width, height, positionX, positionY)
-
- update image buffer
+ Load image from buffer.
+
+ :arg imageBuffer: Buffer to load the image from.
+ :type imageBuffer: :class:`~bgl.Buffer` or Python object implementing the buffer protocol (f.ex. bytes)
+ :arg width: Width of the image to load.
+ :type width: int
+ :arg height: Height of the image to load.
+ :type height: int
+
+ .. method:: plot(imageBuffer, width, height, positionX, positionY, mode=IMB_BLEND_COPY)
+
+ Update image buffer.
+
+ :arg imageBuffer: Buffer to load the new data from.
+ :type imageBuffer: :class:`~bgl.Buffer`, :class:`ImageBuff` or Python object implementing the buffer protocol (f.ex. bytes)
+ :arg width: Width of the data to load.
+ :type width: int
+ :arg height: Height of the data to load.
+ :type height: int
+ :arg positionX: Left boundary of the region to be drawn on.
+ :type positionX: int
+ :arg positionY: Upper boundary of the region to be drawn on.
+ :type positionY: int
+ :arg mode: Drawing mode, see `Image Blending Modes`_.
+ :type mode: int
+
.. attribute:: scale
- fast scale of image (near neighbour)
+ Fast scale of image (near neighbour).
+
+ :type: bool
.. attribute:: size
- image size
+ Image size. (readonly)
+
+ :type: tuple of two ints
.. attribute:: valid
- bool to tell if an image is available
+ Tells if an image is available. (readonly)
-.. class:: ImageMirror(scene)
+ :type: bool
+
+.. class:: ImageMirror(scene, observer, mirror, material=0)
- Image source from mirror
+ Image source from mirror.
+
+ :arg scene: Scene in which the image has to be taken.
+ :type scene: :class:`~bge.types.KX_Scene`
+ :arg observer: Reference object for the mirror (the object from which the mirror has to be looked at, for example a camera).
+ :type observer: :class:`~bge.types.KX_GameObject`
+ :arg mirror: Object holding the mirror.
+ :type mirror: :class:`~bge.types.KX_GameObject`
+ :arg material: ID of the mirror's material to be used for mirroring. (optional)
+ :type material: int
.. attribute:: alpha
- use alpha in texture
+ Use alpha in texture.
+
+ :type: bool
.. attribute:: background
- background color
+ Background color.
+
+ :type: int or float list [r, g, b, a] in [0.0, 255.0]
.. attribute:: capsize
- size of render area
+ Size of render area.
+
+ :type: sequence of two ints
.. attribute:: clip
- clipping distance
+ Clipping distance.
+
+ :type: float in [0.01, 5000.0]
.. attribute:: filter
- pixel filter
+ Pixel filter.
+
+ :type: one of...
+
+ * :class:`FilterBGR24`
+ * :class:`FilterBlueScreen`
+ * :class:`FilterColor`
+ * :class:`FilterGray`
+ * :class:`FilterLevel`
+ * :class:`FilterNormal`
+ * :class:`FilterRGB24`
+ * :class:`FilterRGBA32`
.. attribute:: flip
- flip image vertically
+ Flip image vertically.
+
+ :type: bool
.. attribute:: image
- image data
+ Image data. (readonly)
+
+ :type: :class:`~bgl.Buffer` or None
- .. method:: refresh(imageMirror)
+ .. method:: refresh()
- Refresh image - invalidate its current content
+ Refresh image - invalidate its current content.
.. attribute:: scale
- fast scale of image (near neighbour)
+ Fast scale of image (near neighbour).
+
+ :type: bool
.. attribute:: size
- image size
+ Image size (readonly).
+
+ :type: tuple of two ints
.. attribute:: valid
- bool to tell if an image is available
+ Tells if an image is available. (readonly)
+
+ :type: bool
.. attribute:: whole
- use whole viewport to render
+ Use whole viewport to render.
+
+ :type: bool
-.. class:: ImageMix()
+.. class:: ImageMix
- Image mixer
+ Image mixer.
.. attribute:: filter
- pixel filter
+ Pixel filter.
+
+ :type: one of...
+
+ * :class:`FilterBGR24`
+ * :class:`FilterBlueScreen`
+ * :class:`FilterColor`
+ * :class:`FilterGray`
+ * :class:`FilterLevel`
+ * :class:`FilterNormal`
+ * :class:`FilterRGB24`
+ * :class:`FilterRGBA32`
.. attribute:: flip
- flip image vertically
-
- .. method:: getSource(imageMix)
-
- get image source
-
- .. method:: getWeight(imageMix)
-
- get image source weight
+ Flip image vertically.
+
+ :type: bool
+ .. method:: getSource(id)
+
+ Get image source.
+
+ :arg id: Identifier of the source to get.
+ :type id: str
+
+ :return: Image source.
+ :rtype: one of...
+
+ * :class:`VideoFFmpeg`
+ * :class:`ImageFFmpeg`
+ * :class:`ImageBuff`
+ * :class:`ImageMirror`
+ * :class:`ImageMix`
+ * :class:`ImageRender`
+ * :class:`ImageViewport`
+
+ .. method:: getWeight(id)
+
+ Get image source weight.
+
+ :arg id: Identifier of the source.
+ :type id: str
+
+ :return: Weight of the source.
+ :rtype: int
.. attribute:: image
- image data
+ Image data. (readonly)
+
+ :type: :class:`~bgl.Buffer` or None
- .. method:: refresh(imageMix)
+ .. method:: refresh()
- Refresh image - invalidate its current content
+ Refresh image - invalidate its current content.
.. attribute:: scale
- fast scale of image (near neighbour)
-
- .. method:: setSource(imageMix)
-
- set image source
-
- .. method:: setWeight(imageMix)
+ Fast scale of image (near neighbour).
+
+ :type: bool
+
+ .. attribute:: size
- set image source weight
+ Image size. (readonly)
+
+ :type: tuple of two ints
+
+ .. method:: setSource(id, image)
+
+ Set image source - all sources must have the same size.
+
+ :arg id: Identifier of the source to set.
+ :type id: str
+ :arg image: Image source of type...
+
+ * :class:`VideoFFmpeg`
+ * :class:`ImageFFmpeg`
+ * :class:`ImageBuff`
+ * :class:`ImageMirror`
+ * :class:`ImageMix`
+ * :class:`ImageRender`
+ * :class:`ImageViewport`
+
+ .. method:: setWeight(id, weight)
+
+ Set image source weight - the sum of the weights should be 256 to get full color intensity in the output.
+
+ :arg id: Identifier of the source.
+ :type id: str
+ :arg weight: Weight of the source.
+ :type weight: int
.. attribute:: valid
- bool to tell if an image is available
+ Tells if an image is available. (readonly)
+
+ :type: bool
.. class:: ImageRender(scene, camera)
- Image source from render
+ Image source from render.
+
+ :arg scene: Scene in which the image has to be taken.
+ :type scene: :class:`~bge.types.KX_Scene`
+ :arg camera: Camera from which the image has to be taken.
+ :type camera: :class:`~bge.types.KX_Camera`
.. attribute:: alpha
- use alpha in texture
+ Use alpha in texture.
+
+ :type: bool
.. attribute:: background
- background color
+ Background color.
+
+ :type: int or float list [r, g, b, a] in [0.0, 255.0]
.. attribute:: capsize
- size of render area
+ Size of render area.
+
+ :type: sequence of two ints
.. attribute:: filter
- pixel filter
+ Pixel filter.
+
+ :type: one of...
+
+ * :class:`FilterBGR24`
+ * :class:`FilterBlueScreen`
+ * :class:`FilterColor`
+ * :class:`FilterGray`
+ * :class:`FilterLevel`
+ * :class:`FilterNormal`
+ * :class:`FilterRGB24`
+ * :class:`FilterRGBA32`
.. attribute:: flip
- flip image vertically
+ Flip image vertically.
+
+ :type: bool
.. attribute:: image
- image data
+ Image data. (readonly)
+
+ :type: :class:`~bgl.Buffer` or None
- .. method:: refresh(imageRender)
+ .. method:: refresh()
- Refresh image - invalidate its current content
+ Refresh image - invalidate its current content.
.. attribute:: scale
- fast scale of image (near neighbour)
+ Fast scale of image (near neighbour).
+
+ :type: bool
.. attribute:: size
- image size
+ Image size. (readonly)
+
+ :type: tuple of two ints
.. attribute:: valid
- bool to tell if an image is available
+ Tells if an image is available. (readonly)
+
+ :type: bool
.. attribute:: whole
- use whole viewport to render
+ Use whole viewport to render.
+
+ :type: bool
.. attribute:: depth
- use depth component of render as array of float - not suitable for texture source,
- should only be used with bge.texture.imageToArray(mode='F')
+ Use depth component of render as array of float - not suitable for texture source,
+ should only be used with bge.texture.imageToArray(mode='F').
+
+ :type: bool
.. attribute:: zbuff
- use depth component of render as grey scale color - suitable for texture source
+ Use depth component of render as grey scale color - suitable for texture source.
+
+ :type: bool
-.. class:: ImageViewport()
+.. class:: ImageViewport
- Image source from viewport
+ Image source from viewport.
.. attribute:: alpha
- use alpha in texture
+ Use alpha in texture.
+
+ :type: bool
.. attribute:: capsize
- size of viewport area being captured
+ Size of viewport area being captured.
+
+ :type: sequence of two ints
.. attribute:: filter
- pixel filter
+ Pixel filter.
+
+ :type: one of...
+
+ * :class:`FilterBGR24`
+ * :class:`FilterBlueScreen`
+ * :class:`FilterColor`
+ * :class:`FilterGray`
+ * :class:`FilterLevel`
+ * :class:`FilterNormal`
+ * :class:`FilterRGB24`
+ * :class:`FilterRGBA32`
.. attribute:: flip
- flip image vertically
+ Flip image vertically.
+
+ :type: bool
.. attribute:: image
- image data
+ Image data. (readonly)
+
+ :type: :class:`~bgl.Buffer` or None
.. attribute:: position
- upper left corner of captured area
+ Upper left corner of the captured area.
+
+ :type: sequence of two ints
- .. method:: refresh(imageViewport)
+ .. method:: refresh()
- Refresh image - invalidate its current content
+ Refresh image - invalidate its current content.
.. attribute:: scale
- fast scale of image (near neighbour)
+ Fast scale of image (near neighbour).
+
+ :type: bool
.. attribute:: size
- image size
+ Image size. (readonly)
+
+ :type: tuple of two ints
.. attribute:: valid
- bool to tell if an image is available
+ Tells if an image is available. (readonly)
+
+ :type: bool
.. attribute:: whole
- use whole viewport to capture
+ Use whole viewport to capture.
+
+ :type: bool
.. attribute:: depth
- use depth component of viewport as array of float - not suitable for texture source,
- should only be used with bge.texture.imageToArray(mode='F')
+ Use depth component of viewport as array of float - not suitable for texture source,
+ should only be used with bge.texture.imageToArray(mode='F').
+
+ :type: bool
.. attribute:: zbuff
- use depth component of viewport as grey scale color - suitable for texture source
+ Use depth component of viewport as grey scale color - suitable for texture source.
+
+ :type: bool
+
+
+***************
+Texture classes
+***************
-.. class:: Texture(gameObj)
+.. class:: Texture(gameObj, materialID=0, textureID=0, textureObj=None)
- Texture objects
+ Texture object.
+
+ :arg gameObj: Game object to be created a video texture on.
+ :type gameObj: :class:`~bge.types.KX_GameObject`
+ :arg materialID: Material ID. (optional)
+ :type materialID: int
+ :arg textureID: Texture ID. (optional)
+ :type textureID: int
+ :arg textureObj: Texture object with shared bindId. (optional)
+ :type textureObj: :class:`Texture`
.. attribute:: bindId
- OpenGL Bind Name
+ OpenGL Bind Name. (readonly)
+
+ :type: int
- .. method:: close(texture)
+ .. method:: close()
- Close dynamic texture and restore original
+ Close dynamic texture and restore original.
.. attribute:: mipmap
- mipmap texture
+ Mipmap texture.
+
+ :type: bool
- .. method:: refresh(texture)
+ .. method:: refresh(refresh_source=True, ts=-1.0)
- Refresh texture from source
+ Refresh texture from source.
+
+ :arg refresh_source: Whether to also refresh the image source of the texture.
+ :type refresh_source: bool
+ :arg ts: If the texture controls a VideoFFmpeg object:
+ timestamp (in seconds from the start of the movie) of the frame to be loaded; this can be
+ used for video-sound synchonization by passing :attr:`~bge.types.KX_SoundActuator.time` to it. (optional)
+ :type ts: float
.. attribute:: source
- source of texture
+ Source of texture.
+
+ :type: one of...
+
+ * :class:`VideoFFmpeg`
+ * :class:`ImageFFmpeg`
+ * :class:`ImageBuff`
+ * :class:`ImageMirror`
+ * :class:`ImageMix`
+ * :class:`ImageRender`
+ * :class:`ImageViewport`
+
+
+**************
+Filter classes
+**************
-.. class:: FilterBGR24()
- Source filter BGR24 objects
+.. class:: FilterBGR24
-.. class:: FilterBlueScreen()
+ Source filter BGR24.
- Filter for Blue Screen objects
+.. class:: FilterBlueScreen
+
+ Filter for Blue Screen. The RGB channels of the color are left unchanged, while the output alpha is obtained as follows:
+
+ * if the square of the euclidian distance between the RGB color and the filter's reference color is smaller than the filter's lower limit,
+ the output alpha is set to 0;
+
+ * if that square is bigger than the filter's upper limit, the output alpha is set to 255;
+
+ * otherwise the output alpha is linarly extrapoled between 0 and 255 in the interval of the limits.
.. attribute:: color
- blue screen color
+ Reference color.
+
+ :type: sequence of three ints
+ :default: (0, 0, 255)
.. attribute:: limits
- blue screen color limits
+ Reference color limits.
+
+ :type: sequence of two ints
+ :default: (64, 64)
.. attribute:: previous
- previous pixel filter
+ Previous pixel filter.
+
+ :type: one of...
+
+ * :class:`FilterBGR24`
+ * :class:`FilterBlueScreen`
+ * :class:`FilterColor`
+ * :class:`FilterGray`
+ * :class:`FilterLevel`
+ * :class:`FilterNormal`
+ * :class:`FilterRGB24`
+ * :class:`FilterRGBA32`
-.. class:: FilterColor()
+.. class:: FilterColor
- Filter for color calculations
+ Filter for color calculations. The output color is obtained by multiplying the reduced 4x4 matrix with the input color
+ and adding the remaining column to the result.
.. attribute:: matrix
- matrix [4][5] for color calculation
+ Matrix [4][5] for color calculation.
+
+ :type: sequence of four sequences of five ints
+ :default: ((256, 0, 0, 0, 0), (0, 256, 0, 0, 0), (0, 0, 256, 0, 0), (0, 0, 0, 256, 0))
.. attribute:: previous
- previous pixel filter
+ Previous pixel filter.
+
+ :type: one of...
+
+ * :class:`FilterBGR24`
+ * :class:`FilterBlueScreen`
+ * :class:`FilterColor`
+ * :class:`FilterGray`
+ * :class:`FilterLevel`
+ * :class:`FilterNormal`
+ * :class:`FilterRGB24`
+ * :class:`FilterRGBA32`
-.. class:: FilterGray()
+.. class:: FilterGray
- Filter for gray scale effect
+ Filter for gray scale effect. Proportions of R, G and B contributions in the output gray scale are 28:151:77.
.. attribute:: previous
- previous pixel filter
-
-.. class:: FilterLevel()
-
- Filter for levels calculations
+ Previous pixel filter.
+
+ :type: one of...
+
+ * :class:`FilterBGR24`
+ * :class:`FilterBlueScreen`
+ * :class:`FilterColor`
+ * :class:`FilterGray`
+ * :class:`FilterLevel`
+ * :class:`FilterNormal`
+ * :class:`FilterRGB24`
+ * :class:`FilterRGBA32`
+
+.. class:: FilterLevel
+
+ Filter for levels calculations. Each output color component is obtained as follows:
+
+ * if it is smaller than its corresponding min value, it is set to 0;
+
+ * if it is bigger than its corresponding max value, it is set to 255;
+
+ * Otherwise it is linearly extrapoled between 0 and 255 in the (min, max) interval.
.. attribute:: levels
- levels matrix [4] (min, max)
+ Levels matrix [4] (min, max).
+
+ :type: sequence of four sequences of two ints
+ :default: ((0, 255), (0, 255), (0, 255), (0, 255))
.. attribute:: previous
- previous pixel filter
+ Previous pixel filter.
+
+ :type: one of...
+
+ * :class:`FilterBGR24`
+ * :class:`FilterBlueScreen`
+ * :class:`FilterColor`
+ * :class:`FilterGray`
+ * :class:`FilterLevel`
+ * :class:`FilterNormal`
+ * :class:`FilterRGB24`
+ * :class:`FilterRGBA32`
-.. class:: FilterNormal()
+.. class:: FilterNormal
- Filter for Blue Screen objects
+ Normal map filter.
.. attribute:: colorIdx
- index of color used to calculate normal (0 - red, 1 - green, 2 - blue)
+ Index of color used to calculate normal (0 - red, 1 - green, 2 - blue, 3 - alpha).
+
+ :type: int in [0, 3]
+ :default: 0
.. attribute:: depth
- depth of relief
+ Depth of relief.
+
+ :type: float
+ :default: 4.0
.. attribute:: previous
- previous pixel filter
-
-.. class:: FilterRGB24()
+ Previous pixel filter.
+
+ :type: one of...
+
+ * :class:`FilterBGR24`
+ * :class:`FilterBlueScreen`
+ * :class:`FilterColor`
+ * :class:`FilterGray`
+ * :class:`FilterLevel`
+ * :class:`FilterNormal`
+ * :class:`FilterRGB24`
+ * :class:`FilterRGBA32`
+
+.. class:: FilterRGB24
Returns a new input filter object to be used with :class:`ImageBuff` object when the image passed
- to the ImageBuff.load() function has the 3-bytes pixel format BGR.
-
-.. class:: FilterRGBA32()
+ to the :meth:`ImageBuff.load` function has the 3-bytes pixel format BGR.
- Source filter RGBA32 objects
+.. class:: FilterRGBA32
-.. function:: getLastError()
-
- Last error that occurred in a bge.texture function.
+ Source filter RGBA32.
- :return: the description of the last error occurred in a bge.texture function.
- :rtype: string
-.. function:: imageToArray(image,mode)
+*********
+Functions
+*********
- Returns a :class:`~bgl.buffer` corresponding to the current image stored in a texture source object.
-
- :arg image: Image source object.
- :type image: object of type :class:`VideoFFmpeg`, :class:`ImageFFmpeg`, :class:`ImageBuff`, :class:`ImageMix`, :class:`ImageRender`, :class:`ImageMirror` or :class:`ImageViewport`
- :arg mode: optional argument representing the pixel format.
- You can use the characters R, G, B for the 3 color channels, A for the alpha channel,
- 0 to force a fixed 0 color channel and 1 to force a fixed 255 color channel.
- Example: "BGR" will return 3 bytes per pixel with the Blue, Green and Red channels in that order.
- "RGB1" will return 4 bytes per pixel with the Red, Green, Blue channels in that order and the alpha channel forced to 255.
- A special mode "F" allows to return the image as an array of float. This mode should only be used to retrieve
- the depth buffer of the ImageViewport and ImageRender object.
- The default mode is "RGBA".
-
+.. function:: getLastError()
- :type mode: string
- :rtype: :class:`~bgl.buffer`
- :return: A object representing the image as one dimensional array of bytes of size (pixel_size*width*height),
- line by line starting from the bottom of the image. The pixel size and format is determined by the mode
- parameter. For mode 'F', the array is a one dimensional array of float of size (width*height).
+ Last error that occurred in a bge.texture function.
-.. function:: materialID(object,name)
+ :return: The description of the last error occurred in a bge.texture function.
+ :rtype: str
+
+.. function:: imageToArray(image, mode)
+
+ Returns a :class:`~bgl.Buffer` corresponding to the current image stored in a texture source object.
+
+ :arg image: Image source object of type ...
+
+ * :class:`VideoFFmpeg`
+ * :class:`ImageFFmpeg`
+ * :class:`ImageBuff`
+ * :class:`ImageMirror`
+ * :class:`ImageMix`
+ * :class:`ImageRender`
+ * :class:`ImageViewport`
+
+ :arg mode: Optional argument representing the pixel format.
+
+ * You can use the characters R, G, B for the 3 color channels, A for the alpha channel,
+ 0 to force a fixed 0 color channel and 1 to force a fixed 255 color channel.
+
+ Examples:
+ * "BGR" will return 3 bytes per pixel with the Blue, Green and Red channels in that order.
+ * "RGB1" will return 4 bytes per pixel with the Red, Green, Blue channels in that order and the alpha channel forced to 255.
+
+ * A special mode "F" allows to return the image as an array of float. This mode should only be used to retrieve
+ the depth buffer of the class:`ImageViewport` and :class:`ImageRender` objects.
+ The default mode is "RGBA".
+
+ :type mode: str
+
+ :return: An object representing the image as one dimensional array of bytes of size (pixel_size*width*height),
+ line by line starting from the bottom of the image. The pixel size and format is determined by the mode
+ parameter. For mode 'F', the array is a one dimensional array of float of size (width*height).
+ :rtype: :class:`~bgl.Buffer`
+
+.. function:: materialID(object, name)
Returns a numeric value that can be used in :class:`Texture` to create a dynamic texture.
The value corresponds to an internal material number that uses the texture identified
- by name. name is a string representing a texture name with IM prefix if you want to
- identify the texture directly. This method works for basic tex face and for material,
+ by name. name is a string representing a texture name with ``IM`` prefix if you want to
+ identify the texture directly. This method works for basic tex face and for material,
provided the material has a texture channel using that particular texture in first
- position of the texture stack. name can also have MA prefix if you want to identify
+ position of the texture stack. name can also have ``MA`` prefix if you want to identify
the texture by material. In that case the material must have a texture channel in first
position.
If the object has no material that matches name, it generates a runtime error. Use try/except to catch the exception.
- Ex: bge.texture.materialID(obj, 'IMvideo.png')
+ Ex: ``bge.texture.materialID(obj, 'IMvideo.png')``
- :arg object: the game object that uses the texture you want to make dynamic
- :type object: game object
- :arg name: name of the texture/material you want to make dynamic.
- :type name: string
- :rtype: integer
+ :arg object: The game object that uses the texture you want to make dynamic.
+ :type object: :class:`~bge.types.KX_GameObject`
+ :arg name: Name of the texture/material you want to make dynamic.
+ :type name: str
+
+ :return: The internal material number.
+ :rtype: int
.. function:: setLogFile(filename)
@@ -575,6 +1035,88 @@ When the texture object is deleted, the new texture is deleted and the old textu
of the messages on the Python console. Only the runtime errors specific to the VideoTexture module
are written in that file, ordinary runtime time errors are not written.
- :arg filename: name of error log file
- :type filename: string
- :rtype: integer
+ :arg filename: Name of the error log file.
+ :type filename: str
+
+ :return: -1 if the parameter name is invalid (not of type string), else 0.
+ :rtype: int
+
+
+*********
+Constants
+*********
+
+FFmpeg Video and Image Status
++++++++++++++++++++++++++++++
+
+
+.. data:: SOURCE_ERROR
+
+.. data:: SOURCE_EMPTY
+
+.. data:: SOURCE_READY
+
+.. data:: SOURCE_PLAYING
+
+.. data:: SOURCE_STOPPED
+
+
+Image Blending Modes
+++++++++++++++++++++
+
+See Wikipedia's `Blend Modes <https://en.wikipedia.org/wiki/Blend_modes>`_ for reference.
+
+.. data:: IMB_BLEND_MIX
+
+.. data:: IMB_BLEND_ADD
+
+.. data:: IMB_BLEND_SUB
+
+.. data:: IMB_BLEND_MUL
+
+.. data:: IMB_BLEND_LIGHTEN
+
+.. data:: IMB_BLEND_DARKEN
+
+.. data:: IMB_BLEND_ERASE_ALPHA
+
+.. data:: IMB_BLEND_ADD_ALPHA
+
+.. data:: IMB_BLEND_OVERLAY
+
+.. data:: IMB_BLEND_HARDLIGHT
+
+.. data:: IMB_BLEND_COLORBURN
+
+.. data:: IMB_BLEND_LINEARBURN
+
+.. data:: IMB_BLEND_COLORDODGE
+
+.. data:: IMB_BLEND_SCREEN
+
+.. data:: IMB_BLEND_SOFTLIGHT
+
+.. data:: IMB_BLEND_PINLIGHT
+
+.. data:: IMB_BLEND_VIVIDLIGHT
+
+.. data:: IMB_BLEND_LINEARLIGHT
+
+.. data:: IMB_BLEND_DIFFERENCE
+
+.. data:: IMB_BLEND_EXCLUSION
+
+.. data:: IMB_BLEND_HUE
+
+.. data:: IMB_BLEND_SATURATION
+
+.. data:: IMB_BLEND_LUMINOSITY
+
+.. data:: IMB_BLEND_COLOR
+
+.. data:: IMB_BLEND_COPY
+
+.. data:: IMB_BLEND_COPY_RGB
+
+.. data:: IMB_BLEND_COPY_ALPHA
+
diff --git a/doc/python_api/rst/bge_types/bge.types.KX_BlenderMaterial.rst b/doc/python_api/rst/bge_types/bge.types.KX_BlenderMaterial.rst
index 0dfc7a10d13..17f54031ec3 100644
--- a/doc/python_api/rst/bge_types/bge.types.KX_BlenderMaterial.rst
+++ b/doc/python_api/rst/bge_types/bge.types.KX_BlenderMaterial.rst
@@ -7,11 +7,66 @@ base class --- :class:`PyObjectPlus`
.. class:: KX_BlenderMaterial(PyObjectPlus)
- KX_BlenderMaterial
+ This is the interface to materials in the game engine.
+
+ Materials define the render state to be applied to mesh objects.
+
+ The example below shows a simple GLSL shader setup allowing to dynamically mix two texture channels
+ in a material. All materials of the object executing this script should have two textures using
+ separate UV maps in the two first texture channels.
+
+ The code works for both Multitexture and GLSL rendering modes.
+
+ .. code-block:: python
+
+ from bge import logic
+
+ vertex_shader = """
+
+ void main(void)
+ {
+ // simple projection of the vertex position to view space
+ gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
+ // coordinate of the 1st texture channel
+ gl_TexCoord[0] = gl_MultiTexCoord0;
+ // coordinate of the 2nd texture channel
+ gl_TexCoord[1] = gl_MultiTexCoord1;
+ }
+ """
+
+ fragment_shader ="""
+
+ uniform sampler2D texture_0;
+ uniform sampler2D texture_1;
+ uniform float factor;
+
+ void main(void)
+ {
+ vec4 color_0 = texture2D(texture_0, gl_TexCoord[0].st);
+ vec4 color_1 = texture2D(texture_1, gl_TexCoord[1].st);
+ gl_FragColor = mix(color_0, color_1, factor);
+ }
+ """
+
+ object = logic.getCurrentController().owner
+
+ for mesh in object.meshes:
+ for material in mesh.materials:
+ shader = material.getShader()
+ if shader is not None:
+ if not shader.isValid():
+ shader.setSource(vertex_shader, fragment_shader, True)
+
+ # get the first texture channel of the material
+ shader.setSampler('texture_0', 0)
+ # get the second texture channel of the material
+ shader.setSampler('texture_1', 1)
+ # pass another uniform to the shader
+ shader.setUniform1f('factor', 0.3)
.. attribute:: shader
- The materials shader.
+ The material's shader.
:type: :class:`BL_Shader`
@@ -34,39 +89,83 @@ base class --- :class:`PyObjectPlus`
:return: the material's shader
:rtype: :class:`BL_Shader`
+ .. attribute:: alpha
+
+ The material's alpha transparency.
+
+ :type: float between 0.0 and 1.0 inclusive
+
+ .. attribute:: hardness
+
+ How hard (sharp) the material's specular reflection is.
+
+ :type: integer between 1 and 511 inclusive
+
+ .. attribute:: emit
+
+ Amount of light to emit.
+
+ :type: float between 0.0 and 2.0 inclusive
+
+ .. attribute:: specularIntensity
+
+ How intense (bright) the material's specular reflection is.
+
+ :type: float between 0.0 and 1.0 inclusive
+
+ .. attribute:: diffuseIntensity
+
+ The material's amount of diffuse reflection.
+
+ :type: float between 0.0 and 1.0 inclusive
+
+ .. attribute:: specularColor
+
+ The material's specular color.
+
+ :type: :class:`mathutils.Color`
+
+ .. attribute:: diffuseColor
+
+ The material's diffuse color.
+
+ :type: :class:`mathutils.Color`
+
.. method:: setBlending(src, dest)
Set the pixel color arithmetic functions.
- :arg src: Specifies how the red, green, blue, and alpha source blending factors are computed.
- :type src: Value in...
-
- * GL_ZERO,
- * GL_ONE,
- * GL_SRC_COLOR,
- * GL_ONE_MINUS_SRC_COLOR,
- * GL_DST_COLOR,
- * GL_ONE_MINUS_DST_COLOR,
- * GL_SRC_ALPHA,
- * GL_ONE_MINUS_SRC_ALPHA,
- * GL_DST_ALPHA,
- * GL_ONE_MINUS_DST_ALPHA,
- * GL_SRC_ALPHA_SATURATE
-
- :arg dest: Specifies how the red, green, blue, and alpha destination blending factors are computed.
- :type dest: Value in...
-
- * GL_ZERO
- * GL_ONE
- * GL_SRC_COLOR
- * GL_ONE_MINUS_SRC_COLOR
- * GL_DST_COLOR
- * GL_ONE_MINUS_DST_COLOR
- * GL_SRC_ALPHA
- * GL_ONE_MINUS_SRC_ALPHA
- * GL_DST_ALPHA
- * GL_ONE_MINUS_DST_ALPHA
- * GL_SRC_ALPHA_SATURATE
+ :arg src: Specifies how the red, green, blue, and alpha source blending factors are computed, one of...
+
+ * :data:`~bgl.GL_ZERO`
+ * :data:`~bgl.GL_ONE`
+ * :data:`~bgl.GL_SRC_COLOR`
+ * :data:`~bgl.GL_ONE_MINUS_SRC_COLOR`
+ * :data:`~bgl.GL_DST_COLOR`
+ * :data:`~bgl.GL_ONE_MINUS_DST_COLOR`
+ * :data:`~bgl.GL_SRC_ALPHA`
+ * :data:`~bgl.GL_ONE_MINUS_SRC_ALPHA`
+ * :data:`~bgl.GL_DST_ALPHA`
+ * :data:`~bgl.GL_ONE_MINUS_DST_ALPHA`
+ * :data:`~bgl.GL_SRC_ALPHA_SATURATE`
+
+ :type src: int
+
+ :arg dest: Specifies how the red, green, blue, and alpha destination blending factors are computed, one of...
+
+ * :data:`~bgl.GL_ZERO`
+ * :data:`~bgl.GL_ONE`
+ * :data:`~bgl.GL_SRC_COLOR`
+ * :data:`~bgl.GL_ONE_MINUS_SRC_COLOR`
+ * :data:`~bgl.GL_DST_COLOR`
+ * :data:`~bgl.GL_ONE_MINUS_DST_COLOR`
+ * :data:`~bgl.GL_SRC_ALPHA`
+ * :data:`~bgl.GL_ONE_MINUS_SRC_ALPHA`
+ * :data:`~bgl.GL_DST_ALPHA`
+ * :data:`~bgl.GL_ONE_MINUS_DST_ALPHA`
+ * :data:`~bgl.GL_SRC_ALPHA_SATURATE`
+
+ :type dest: int
.. method:: getMaterialIndex()
diff --git a/doc/python_api/rst/bge_types/bge.types.KX_Camera.rst b/doc/python_api/rst/bge_types/bge.types.KX_Camera.rst
index 0baba5c3359..ac5ab4b5fe5 100644
--- a/doc/python_api/rst/bge_types/bge.types.KX_Camera.rst
+++ b/doc/python_api/rst/bge_types/bge.types.KX_Camera.rst
@@ -51,6 +51,18 @@ base class --- :class:`KX_GameObject`
:type: float
+ .. attribute:: shift_x
+
+ The camera's horizontal shift.
+
+ :type: float
+
+ .. attribute:: shift_y
+
+ The camera's vertical shift.
+
+ :type: float
+
.. attribute:: perspective
True if this camera has a perspective transform, False for an orthographic projection.
diff --git a/doc/python_api/rst/bge_types/bge.types.KX_CharacterWrapper.rst b/doc/python_api/rst/bge_types/bge.types.KX_CharacterWrapper.rst
index 4d9dd5b5c34..e326892a824 100644
--- a/doc/python_api/rst/bge_types/bge.types.KX_CharacterWrapper.rst
+++ b/doc/python_api/rst/bge_types/bge.types.KX_CharacterWrapper.rst
@@ -37,7 +37,7 @@ base class --- :class:`PyObjectPlus`
The speed and direction the character is traveling in using world coordinates. This should be used instead of applyMovement() to properly move the character.
- :type: list [x, y, z]
+ :type: Vector((x, y, z))
.. method:: jump()
diff --git a/doc/python_api/rst/bge_types/bge.types.KX_ConstraintWrapper.rst b/doc/python_api/rst/bge_types/bge.types.KX_ConstraintWrapper.rst
index 53bef120f7a..d9f03395c34 100644
--- a/doc/python_api/rst/bge_types/bge.types.KX_ConstraintWrapper.rst
+++ b/doc/python_api/rst/bge_types/bge.types.KX_ConstraintWrapper.rst
@@ -23,15 +23,14 @@ base class --- :class:`PyObjectPlus`
:arg axis:
:type axis: integer
- .. note::
- For each axis:
- * Lowerlimit == Upperlimit -> axis is locked
- * Lowerlimit > Upperlimit -> axis is free
- * Lowerlimit < Upperlimit -> axis it limited in that range
+ .. note::
+ * Lowerlimit == Upperlimit -> axis is locked
+ * Lowerlimit > Upperlimit -> axis is free
+ * Lowerlimit < Upperlimit -> axis it limited in that range
- PHY_LINEHINGE_CONSTRAINT = 2 or PHY_ANGULAR_CONSTRAINT = 3:
- axis = 3 is a constraint limit, with low/high limit value
+ For PHY_LINEHINGE_CONSTRAINT = 2 or PHY_ANGULAR_CONSTRAINT = 3:
+ axis = 3 is a constraint limit, with low/high limit value
* 3: X axis angle
:arg value0 (min): Set the minimum limit of the axis
@@ -39,7 +38,8 @@ base class --- :class:`PyObjectPlus`
:arg value1 (max): Set the maximum limit of the axis
:type value1: float
- PHY_CONE_TWIST_CONSTRAINT = 3:
+ For PHY_CONE_TWIST_CONSTRAINT = 4:
+
axis = 3..5 are constraint limits, high limit values
* 3: X axis angle
* 4: Y axis angle
@@ -50,7 +50,8 @@ base class --- :class:`PyObjectPlus`
:arg value1 (max): Set the maximum limit of the axis
:type value1: float
- PHY_GENERIC_6DOF_CONSTRAINT = 12:
+ For PHY_GENERIC_6DOF_CONSTRAINT = 12:
+
axis = 0..2 are constraint limits, with low/high limit value
* 0: X axis position
* 1: Y axis position
@@ -133,9 +134,10 @@ base class --- :class:`PyObjectPlus`
:type: integer
- * 1 = POINTTOPOINT_CONSTRAINT
- * 2 = LINEHINGE_CONSTRAINT
- * 3 = ANGULAR_CONSTRAINT (aka LINEHINGE_CONSTRAINT)
- * 4 = CONETWIST_CONSTRAINT
- * 11 = VEHICLE_CONSTRAINT
- * 12 = GENERIC_6DOF_CONSTRAINT
+ - :class:`~bge.constraints.POINTTOPOINT_CONSTRAINT`
+ - :class:`~bge.constraints.LINEHINGE_CONSTRAINT`
+ - :class:`~bge.constraints.ANGULAR_CONSTRAINT`
+ - :class:`~bge.constraints.CONETWIST_CONSTRAINT`
+ - :class:`~bge.constraints.VEHICLE_CONSTRAINT`
+ - :class:`~bge.constraints.GENERIC_6DOF_CONSTRAINT`
+
diff --git a/doc/python_api/rst/bge_types/bge.types.KX_FontObject.rst b/doc/python_api/rst/bge_types/bge.types.KX_FontObject.rst
index 1961f5e3e92..ca35ff49a08 100644
--- a/doc/python_api/rst/bge_types/bge.types.KX_FontObject.rst
+++ b/doc/python_api/rst/bge_types/bge.types.KX_FontObject.rst
@@ -7,6 +7,26 @@ base class --- :class:`KX_GameObject`
.. class:: KX_FontObject(KX_GameObject)
- TODO.
+ A Font object.
+ .. code-block:: python
+
+ # Display a message about the exit key using a Font object.
+ import bge
+
+ co = bge.logic.getCurrentController()
+ font = co.owner
+
+ exit_key = bge.events.EventToString(bge.logic.getExitKey())
+
+ if exit_key.endswith("KEY"):
+ exit_key = exit_key[:-3]
+
+ font.text = "Press key '%s' to quit the game." % exit_key
+
+ .. attribute:: text
+
+ The text displayed by this Font object.
+
+ :type: string
diff --git a/doc/python_api/rst/bge_types/bge.types.KX_GameObject.rst b/doc/python_api/rst/bge_types/bge.types.KX_GameObject.rst
index a6d03dee1a1..74df50ddb58 100644
--- a/doc/python_api/rst/bge_types/bge.types.KX_GameObject.rst
+++ b/doc/python_api/rst/bge_types/bge.types.KX_GameObject.rst
@@ -78,6 +78,35 @@ base class --- :class:`SCA_IObject`
The object must have a physics controller for the mass to be applied, otherwise the mass value will be returned as 0.0.
+ .. attribute:: isSuspendDynamics
+
+ The object's dynamic state (read-only).
+
+ :type: boolean
+
+ .. seealso:: :py:meth:`suspendDynamics` and :py:meth:`restoreDynamics` allow you to change the state.
+
+ .. attribute:: linearDamping
+
+ The object's linear damping, also known as translational damping. Can be set simultaneously with angular damping using the :py:meth:`setDamping` method.
+
+ :type: float between 0 and 1 inclusive.
+
+ .. note::
+
+ The object must have a physics controller for the linear damping to be applied, otherwise the value will be returned as 0.0.
+
+ .. attribute:: angularDamping
+
+ The object's angular damping, also known as rotationation damping. Can be set simultaneously with linear damping using the :py:meth:`setDamping` method.
+
+ :type: float between 0 and 1 inclusive.
+
+ .. note::
+
+ The object must have a physics controller for the angular damping to be applied, otherwise the value will be returned as 0.0.
+
+
.. attribute:: linVelocityMin
Enforces the object keeps moving at a minimum velocity.
@@ -108,13 +137,36 @@ base class --- :class:`SCA_IObject`
.. note::
- A value of 0.0 disables this option (rather then setting it stationary).
+ A value of 0.0 disables this option (rather than setting it stationary).
+
+ .. attribute:: angularVelocityMin
+
+ Enforces the object keeps rotating at a minimum velocity. A value of 0.0 disables this.
+
+ :type: non-negative float
+
+ .. note::
+
+ Applies to dynamic and rigid body objects only.
+ While objects are stationary the minimum velocity will not be applied.
+
+
+ .. attribute:: angularVelocityMax
+
+ Clamp the maximum angular velocity to prevent objects rotating beyond a set speed.
+ A value of 0.0 disables clamping; it does not stop rotation.
+
+ :type: non-negative float
+
+ .. note::
+
+ Applies to dynamic and rigid body objects only.
.. attribute:: localInertia
the object's inertia vector in local coordinates. Read only.
- :type: list [ix, iy, iz]
+ :type: Vector((ix, iy, iz))
.. attribute:: parent
@@ -124,21 +176,70 @@ base class --- :class:`SCA_IObject`
.. attribute:: groupMembers
- Returns the list of group members if the object is a group object, otherwise None is returned.
+ Returns the list of group members if the object is a group object (dupli group instance), otherwise None is returned.
:type: :class:`CListValue` of :class:`KX_GameObject` or None
.. attribute:: groupObject
- Returns the group object that the object belongs to or None if the object is not part of a group.
+ Returns the group object (dupli group instance) that the object belongs to or None if the object is not part of a group.
:type: :class:`KX_GameObject` or None
+ .. attribute:: collisionGroup
+
+ The object's collision group.
+
+ :type: bitfield
+
+ .. attribute:: collisionMask
+
+ The object's collision mask.
+
+ :type: bitfield
+
.. attribute:: collisionCallbacks
- A list of callables to be run when a collision occurs.
+ A list of functions to be called when a collision occurs.
- :type: list
+ :type: list of functions and/or methods
+
+ Callbacks should either accept one argument `(object)`, or three
+ arguments `(object, point, normal)`. For simplicity, per
+ colliding object only the first collision point is reported.
+
+ .. code-block:: python
+
+ # Function form
+ def callback_three(object, point, normal):
+ print('Hit by %r at %s with normal %s' % (object.name, point, normal))
+
+ def callback_one(object):
+ print('Hit by %r' % object.name)
+
+ def register_callback(controller):
+ controller.owner.collisionCallbacks.append(callback_three)
+ controller.owner.collisionCallbacks.append(callback_one)
+
+
+ # Method form
+ class YourGameEntity(bge.types.KX_GameObject):
+ def __init__(self, old_owner):
+ self.collisionCallbacks.append(self.on_collision_three)
+ self.collisionCallbacks.append(self.on_collision_one)
+
+ def on_collision_three(self, object, point, normal):
+ print('Hit by %r at %s with normal %s' % (object.name, point, normal))
+
+ def on_collision_one(self, object):
+ print('Hit by %r' % object.name)
+
+ .. note::
+ For backward compatibility, a callback with variable number of
+ arguments (using `*args`) will be passed only the `object`
+ argument. Only when there is more than one fixed argument (not
+ counting `self` for methods) will the three-argument form be
+ used.
.. attribute:: scene
@@ -374,6 +475,12 @@ base class --- :class:`SCA_IObject`
If true, the object's and children's debug properties will be displayed on screen.
:type: boolean
+
+ .. attribute:: currentLodLevel
+
+ The index of the level of detail (LOD) currently used by this object (read-only).
+
+ :type: int
.. method:: endObject()
@@ -496,7 +603,7 @@ base class --- :class:`SCA_IObject`
* True: you get the "local" velocity ie: relative to object orientation.
:type local: boolean
:return: the object's linear velocity.
- :rtype: list [vx, vy, vz]
+ :rtype: Vector((vx, vy, vz))
.. method:: setLinearVelocity(velocity, local=False)
@@ -523,7 +630,7 @@ base class --- :class:`SCA_IObject`
* True: you get the "local" velocity ie: relative to object orientation.
:type local: boolean
:return: the object's angular velocity.
- :rtype: list [vx, vy, vz]
+ :rtype: Vector((vx, vy, vz))
.. method:: setAngularVelocity(velocity, local=False)
@@ -547,7 +654,7 @@ base class --- :class:`SCA_IObject`
:arg point: optional point to return the velocity for, in local coordinates.
:type point: 3D Vector
:return: the velocity at the specified point.
- :rtype: list [vx, vy, vz]
+ :rtype: Vector((vx, vy, vz))
.. method:: getReactionForce()
@@ -557,7 +664,7 @@ base class --- :class:`SCA_IObject`
This also includes impulses, eg from collisions.
:return: the reaction force of this object.
- :rtype: list [fx, fy, fz]
+ :rtype: Vector((fx, fy, fz))
.. note::
@@ -580,13 +687,28 @@ base class --- :class:`SCA_IObject`
* True: you get the "local" impulse ie: relative to local coordinates with object orientation.
:type local: boolean
- .. method:: suspendDynamics()
+ .. method:: setDamping(linear_damping, angular_damping)
+
+ Sets both the :py:attr:`linearDamping` and :py:attr:`angularDamping` simultaneously. This is more efficient than setting both properties individually.
+
+ :arg linear_damping: Linear ("translational") damping factor.
+ :type linear_damping: float ∈ [0, 1]
+ :arg angular_damping: Angular ("rotational") damping factor.
+ :type angular_damping: float ∈ [0, 1]
+
+ .. method:: suspendDynamics([ghost])
Suspends physics for this object.
+ :arg ghost: When set to `True`, collisions with the object will be ignored, similar to the "ghost" checkbox in
+ Blender. When `False` (the default), the object becomes static but still collide with other objects.
+ :type ghost: bool
+
+ .. seealso:: :py:attr:`isSuspendDynamics` allows you to inspect whether the object is in a suspended state.
+
.. method:: restoreDynamics()
- Resumes physics for this object.
+ Resumes physics for this object. Also reinstates collisions; the object will no longer be a ghost.
.. note::
@@ -850,6 +972,16 @@ base class --- :class:`SCA_IObject`
:return: The current frame of the action
:rtype: float
+ .. method:: getActionName(layer=0)
+
+ Gets the name of the current action playing in the supplied layer.
+
+ :arg layer: The layer that you want to get the action name from.
+ :type layer: integer
+
+ :return: The name of the current action
+ :rtype: string
+
.. method:: setActionFrame(frame, layer=0)
Set the current frame of the action playing in the supplied layer.
@@ -876,4 +1008,4 @@ base class --- :class:`SCA_IObject`
:arg name: name of the property that added to the debug list.
:type name: string
:arg debug: the debug state.
- :type debug: boolean \ No newline at end of file
+ :type debug: boolean
diff --git a/doc/python_api/rst/bge_types/bge.types.KX_MeshProxy.rst b/doc/python_api/rst/bge_types/bge.types.KX_MeshProxy.rst
index 9ef8d6b2026..13fb3263a59 100644
--- a/doc/python_api/rst/bge_types/bge.types.KX_MeshProxy.rst
+++ b/doc/python_api/rst/bge_types/bge.types.KX_MeshProxy.rst
@@ -51,7 +51,7 @@ base class --- :class:`SCA_IObject`
.. attribute:: materials
- :type: list of :class:`KX_BlenderMaterial` or :class:`KX_PolygonMaterial` types
+ :type: list of :class:`KX_BlenderMaterial` type
.. attribute:: numPolygons
diff --git a/doc/python_api/rst/bge_types/bge.types.KX_ObjectActuator.rst b/doc/python_api/rst/bge_types/bge.types.KX_ObjectActuator.rst
index f10f101a4cc..347b000be3d 100644
--- a/doc/python_api/rst/bge_types/bge.types.KX_ObjectActuator.rst
+++ b/doc/python_api/rst/bge_types/bge.types.KX_ObjectActuator.rst
@@ -15,7 +15,7 @@ base class --- :class:`SCA_IActuator`
The force applied by the actuator.
- :type: list [x, y, z]
+ :type: Vector((x, y, z))
.. attribute:: useLocalForce
@@ -27,7 +27,7 @@ base class --- :class:`SCA_IActuator`
The torque applied by the actuator.
- :type: list [x, y, z]
+ :type: Vector((x, y, z))
.. attribute:: useLocalTorque
@@ -39,7 +39,7 @@ base class --- :class:`SCA_IActuator`
The displacement vector applied by the actuator.
- :type: list [x, y, z]
+ :type: Vector((x, y, z))
.. attribute:: useLocalDLoc
@@ -51,7 +51,7 @@ base class --- :class:`SCA_IActuator`
The angular displacement vector applied by the actuator
- :type: list [x, y, z]
+ :type: Vector((x, y, z))
.. note::
@@ -67,7 +67,7 @@ base class --- :class:`SCA_IActuator`
The linear velocity applied by the actuator.
- :type: list [x, y, z]
+ :type: Vector((x, y, z))
.. attribute:: useLocalLinV
@@ -83,7 +83,7 @@ base class --- :class:`SCA_IActuator`
The angular velocity applied by the actuator.
- :type: list [x, y, z]
+ :type: Vector((x, y, z))
.. attribute:: useLocalAngV
diff --git a/doc/python_api/rst/bge_types/bge.types.KX_PolyProxy.rst b/doc/python_api/rst/bge_types/bge.types.KX_PolyProxy.rst
index 534f6deedc0..f43cf62eec1 100644
--- a/doc/python_api/rst/bge_types/bge.types.KX_PolyProxy.rst
+++ b/doc/python_api/rst/bge_types/bge.types.KX_PolyProxy.rst
@@ -23,7 +23,7 @@ base class --- :class:`SCA_IObject`
The material of the polygon.
- :type: :class:`KX_PolygonMaterial` or :class:`KX_BlenderMaterial`
+ :type: :class:`KX_BlenderMaterial`
.. attribute:: texture_name
@@ -84,7 +84,7 @@ base class --- :class:`SCA_IObject`
.. method:: getMaterial()
:return: The polygon material
- :rtype: :class:`KX_PolygonMaterial` or :class:`KX_BlenderMaterial`
+ :rtype: :class:`KX_BlenderMaterial`
.. method:: getTextureName()
diff --git a/doc/python_api/rst/bge_types/bge.types.KX_PolygonMaterial.rst b/doc/python_api/rst/bge_types/bge.types.KX_PolygonMaterial.rst
deleted file mode 100644
index 3421e194d77..00000000000
--- a/doc/python_api/rst/bge_types/bge.types.KX_PolygonMaterial.rst
+++ /dev/null
@@ -1,250 +0,0 @@
-KX_PolygonMaterial(PyObjectPlus)
-================================
-
-.. module:: bge.types
-
-base class --- :class:`PyObjectPlus`
-
-.. class:: KX_PolygonMaterial(PyObjectPlus)
-
- This is the interface to materials in the game engine.
-
- Materials define the render state to be applied to mesh objects.
-
- .. warning::
-
- Some of the methods/variables are CObjects. If you mix these up, you will crash blender.
-
- .. code-block:: python
-
- from bge import logic
-
- vertex_shader = """
-
- void main(void)
- {
- // original vertex position, no changes
- gl_Position = ftransform();
- // coordinate of the 1st texture channel
- gl_TexCoord[0] = gl_MultiTexCoord0;
- // coordinate of the 2nd texture channel
- gl_TexCoord[1] = gl_MultiTexCoord1;
- }
- """
-
- fragment_shader ="""
-
- uniform sampler2D color_0;
- uniform sampler2D color_1;
- uniform float factor;
-
- void main(void)
- {
- vec4 color_0 = texture2D(color_0, gl_TexCoord[0].st);
- vec4 color_1 = texture2D(color_1, gl_TexCoord[1].st);
- gl_FragColor = mix(color_0, color_1, factor);
- }
- """
-
- object = logic.getCurrentController().owner
- object = cont.owner
- for mesh in object.meshes:
- for material in mesh.materials:
- shader = material.getShader()
- if shader != None:
- if not shader.isValid():
- shader.setSource(vertex_shader, fragment_shader, True)
-
- # get the first texture channel of the material
- shader.setSampler('color_0', 0)
- # get the second texture channel of the material
- shader.setSampler('color_1', 1)
- # pass another uniform to the shader
- shader.setUniform1f('factor', 0.3)
-
-
- .. attribute:: texture
-
- Texture name.
-
- :type: string (read-only)
-
- .. attribute:: gl_texture
-
- OpenGL texture handle (eg for glBindTexture(GL_TEXTURE_2D, gl_texture).
-
- :type: integer (read-only)
-
- .. attribute:: material
-
- Material name.
-
- :type: string (read-only)
-
- .. attribute:: tface
-
- Texture face properties.
-
- :type: CObject (read-only)
-
- .. attribute:: tile
-
- Texture is tiling.
-
- :type: boolean
-
- .. attribute:: tilexrep
-
- Number of tile repetitions in x direction.
-
- :type: integer
-
- .. attribute:: tileyrep
-
- Number of tile repetitions in y direction.
-
- :type: integer
-
- .. attribute:: drawingmode
-
- Drawing mode for the material.
- - 2 (drawingmode & 4) Textured
- - 4 (drawingmode & 16) Light
- - 14 (drawingmode & 16384) 3d Polygon Text.
-
- :type: bitfield
-
- .. attribute:: transparent
-
- This material is transparent. All meshes with this
- material will be rendered after non transparent meshes from back
- to front.
-
- :type: boolean
-
- .. attribute:: zsort
-
- Transparent polygons in meshes with this material will be sorted back to
- front before rendering.
- Non-Transparent polygons will be sorted front to back before rendering.
-
- :type: boolean
-
- .. attribute:: diffuse
-
- The diffuse color of the material. black = [0.0, 0.0, 0.0] white = [1.0, 1.0, 1.0].
-
- :type: list [r, g, b]
-
- .. attribute:: specular
-
- The specular color of the material. black = [0.0, 0.0, 0.0] white = [1.0, 1.0, 1.0].
-
- :type: list [r, g, b]
-
- .. attribute:: shininess
-
- The shininess (specular exponent) of the material. 0.0 <= shininess <= 128.0.
-
- :type: float
-
- .. attribute:: specularity
-
- The amount of specular of the material. 0.0 <= specularity <= 1.0.
-
- :type: float
-
- .. method:: updateTexture(tface, rasty)
-
- Updates a realtime animation.
-
- :arg tface: Texture face (eg mat.tface)
- :type tface: CObject
- :arg rasty: Rasterizer
- :type rasty: CObject
-
- .. method:: setTexture(tface)
-
- Sets texture render state.
-
- :arg tface: Texture face
- :type tface: CObject
-
- .. code-block:: python
-
- mat.setTexture(mat.tface)
-
- .. method:: activate(rasty, cachingInfo)
-
- Sets material parameters for this object for rendering.
-
- Material Parameters set:
-
- #. Texture
- #. Backface culling
- #. Line drawing
- #. Specular Colour
- #. Shininess
- #. Diffuse Colour
- #. Polygon Offset.
-
- :arg rasty: Rasterizer instance.
- :type rasty: CObject
- :arg cachingInfo: Material cache instance.
- :type cachingInfo: CObject
-
- .. method:: setCustomMaterial(material)
-
- Sets the material state setup object.
-
- Using this method, you can extend or completely replace the gameengine material
- to do your own advanced multipass effects.
-
- Use this method to register your material class. Instead of the normal material,
- your class's activate method will be called just before rendering the mesh.
- This should setup the texture, material, and any other state you would like.
- It should return True to render the mesh, or False if you are finished. You should
- clean up any state Blender does not set before returning False.
-
- Activate Method Definition:
-
- .. code-block:: python
-
- def activate(self, rasty, cachingInfo, material):
-
- :arg material: The material object.
- :type material: instance
-
- .. code-block:: python
-
- class PyMaterial:
- def __init__(self):
- self.pass_no = -1
-
- def activate(self, rasty, cachingInfo, material):
- # Activate the material here.
- #
- # The activate method will be called until it returns False.
- # Every time the activate method returns True the mesh will
- # be rendered.
- #
- # rasty is a CObject for passing to material.updateTexture()
- # and material.activate()
- # cachingInfo is a CObject for passing to material.activate()
- # material is the KX_PolygonMaterial instance this material
- # was added to
-
- # default material properties:
- self.pass_no += 1
- if self.pass_no == 0:
- material.activate(rasty, cachingInfo)
- # Return True to do this pass
- return True
-
- # clean up and return False to finish.
- self.pass_no = -1
- return False
-
- # Create a new Python Material and pass it to the renderer.
- mat.setCustomMaterial(PyMaterial())
-
diff --git a/doc/python_api/rst/bge_types/bge.types.KX_Scene.rst b/doc/python_api/rst/bge_types/bge.types.KX_Scene.rst
index f2dad58731c..5bd8e3a77de 100644
--- a/doc/python_api/rst/bge_types/bge.types.KX_Scene.rst
+++ b/doc/python_api/rst/bge_types/bge.types.KX_Scene.rst
@@ -83,6 +83,12 @@ base class --- :class:`PyObjectPlus`
This can be set directly from python to avoid using the :class:`KX_SceneActuator`.
+ .. attribute:: world
+
+ The current active world, (read-only).
+
+ :type: :class:`KX_WorldInfo`
+
.. attribute:: suspended
True if the scene is suspended, (read-only).
@@ -119,21 +125,27 @@ base class --- :class:`PyObjectPlus`
:type: list
+ .. attribute:: pre_draw_setup
+
+ A list of callables to be run before the drawing setup (i.e., before the model view and projection matrices are computed).
+
+ :type: list
+
.. attribute:: gravity
The scene gravity using the world x, y and z axis.
- :type: list [fx, fy, fz]
+ :type: Vector((gx, gy, gz))
- .. method:: addObject(object, other, time=0)
+ .. method:: addObject(object, reference, time=0)
Adds an object to the scene like the Add Object Actuator would.
- :arg object: The object to add
+ :arg object: The (name of the) object to add.
:type object: :class:`KX_GameObject` or string
- :arg other: The object's center to use when adding the object
- :type other: :class:`KX_GameObject` or string
- :arg time: The lifetime of the added object, in frames. A time of 0 means the object will last forever.
+ :arg reference: The (name of the) object which position, orientation, and scale to copy (optional), if the object to add is a light and there is not reference the light's layer will be the same that the active layer in the blender scene.
+ :type reference: :class:`KX_GameObject` or string
+ :arg time: The lifetime of the added object, in frames. A time of 0 means the object will last forever (optional).
:type time: integer
:return: The newly added object.
:rtype: :class:`KX_GameObject`
diff --git a/doc/python_api/rst/bge_types/bge.types.KX_VehicleWrapper.rst b/doc/python_api/rst/bge_types/bge.types.KX_VehicleWrapper.rst
index 9340d33f8a9..631075363ca 100644
--- a/doc/python_api/rst/bge_types/bge.types.KX_VehicleWrapper.rst
+++ b/doc/python_api/rst/bge_types/bge.types.KX_VehicleWrapper.rst
@@ -11,22 +11,25 @@ base class --- :class:`PyObjectPlus`
TODO - description
- .. method:: addWheel(wheel, attachPos, attachDir, axleDir, suspensionRestLength, wheelRadius, hasSteering)
+ .. method:: addWheel(wheel, attachPos, downDir, axleDir, suspensionRestLength, wheelRadius, hasSteering)
Add a wheel to the vehicle
:arg wheel: The object to use as a wheel.
- :type wheel: :class:`KX_GameObject` or a KX_GameObject name
- :arg attachPos: The position that this wheel will attach to.
+ :type wheel: :class:`KX_GameObject` or a :class:`KX_GameObject` name
+ :arg attachPos: The position to attach the wheel, relative to the chassis object center.
:type attachPos: vector of 3 floats
- :arg attachDir: The direction this wheel points.
- :type attachDir: vector of 3 floats
- :arg axleDir: The direction of this wheels axle.
+ :arg downDir: The direction vector pointing down to where the vehicle should collide with the floor.
+ :type downDir: vector of 3 floats
+ :arg axleDir: The axis the wheel rotates around, relative to the chassis.
:type axleDir: vector of 3 floats
- :arg suspensionRestLength: TODO - Description
+ :arg suspensionRestLength: The length of the suspension when no forces are being applied.
:type suspensionRestLength: float
- :arg wheelRadius: The size of the wheel.
+ :arg wheelRadius: The radius of the wheel (half the diameter).
:type wheelRadius: float
+ :arg hasSteering: True if the wheel should turn with steering, typically used in front wheels.
+ :type hasSteering: boolean
+
.. method:: applyBraking(force, wheelIndex)
@@ -38,6 +41,7 @@ base class --- :class:`PyObjectPlus`
:arg wheelIndex: index of the wheel where the force needs to be applied
:type wheelIndex: integer
+
.. method:: applyEngineForce(force, wheelIndex)
Apply an engine force to the specified wheel
@@ -48,6 +52,7 @@ base class --- :class:`PyObjectPlus`
:arg wheelIndex: index of the wheel where the force needs to be applied
:type wheelIndex: integer
+
.. method:: getConstraintId()
Get the constraint ID
diff --git a/doc/python_api/rst/bge_types/bge.types.KX_VertexProxy.rst b/doc/python_api/rst/bge_types/bge.types.KX_VertexProxy.rst
index 9c0d1169d49..73d692770d6 100644
--- a/doc/python_api/rst/bge_types/bge.types.KX_VertexProxy.rst
+++ b/doc/python_api/rst/bge_types/bge.types.KX_VertexProxy.rst
@@ -17,25 +17,25 @@ base class --- :class:`SCA_IObject`
The position of the vertex.
- :type: list [x, y, z]
+ :type: Vector((x, y, z))
.. attribute:: UV
The texture coordinates of the vertex.
- :type: list [u, v]
+ :type: Vector((u, v))
.. attribute:: normal
The normal of the vertex.
- :type: list [nx, ny, nz]
+ :type: Vector((nx, ny, nz))
.. attribute:: color
The color of the vertex.
- :type: list [r, g, b, a]
+ :type: Vector((r, g, b, a))
Black = [0.0, 0.0, 0.0, 1.0], White = [1.0, 1.0, 1.0, 1.0]
@@ -110,13 +110,13 @@ base class --- :class:`SCA_IObject`
Gets the position of this vertex.
:return: this vertexes position in local coordinates.
- :rtype: list [x, y, z]
+ :rtype: Vector((x, y, z))
.. method:: setXYZ(pos)
Sets the position of this vertex.
- :type: list [x, y, z]
+ :type: Vector((x, y, z))
:arg pos: the new position for this vertex in local coordinates.
@@ -125,26 +125,26 @@ base class --- :class:`SCA_IObject`
Gets the UV (texture) coordinates of this vertex.
:return: this vertexes UV (texture) coordinates.
- :rtype: list [u, v]
+ :rtype: Vector((u, v))
.. method:: setUV(uv)
Sets the UV (texture) coordinates of this vertex.
- :type: list [u, v]
+ :type: Vector((u, v))
.. method:: getUV2()
Gets the 2nd UV (texture) coordinates of this vertex.
:return: this vertexes UV (texture) coordinates.
- :rtype: list [u, v]
+ :rtype: Vector((u, v))
.. method:: setUV2(uv, unit)
Sets the 2nd UV (texture) coordinates of this vertex.
- :type: list [u, v]
+ :type: Vector((u, v))
:arg unit: optional argument, FLAT==1, SECOND_UV==2, defaults to SECOND_UV
:arg unit: integer
@@ -197,7 +197,7 @@ base class --- :class:`SCA_IObject`
Gets the normal vector of this vertex.
:return: normalized normal vector.
- :rtype: list [nx, ny, nz]
+ :rtype: Vector((nx, ny, nz))
.. method:: setNormal(normal)
diff --git a/doc/python_api/rst/bge_types/bge.types.KX_WorldInfo.rst b/doc/python_api/rst/bge_types/bge.types.KX_WorldInfo.rst
new file mode 100644
index 00000000000..a636af4f083
--- /dev/null
+++ b/doc/python_api/rst/bge_types/bge.types.KX_WorldInfo.rst
@@ -0,0 +1,79 @@
+KX_WorldInfo(PyObjectPlus)
+=============================
+
+.. module:: bge.types
+
+base class --- :class:`PyObjectPlus`
+
+.. class:: KX_WorldInfo(PyObjectPlus)
+
+ A world object.
+
+ .. code-block:: python
+
+ # Set the mist color to red.
+ import bge
+
+ sce = bge.logic.getCurrentScene()
+
+ sce.world.mistColor = [1.0, 0.0, 0.0]
+
+ .. data:: KX_MIST_QUADRATIC
+
+ Type of quadratic attenuation used to fade mist.
+
+ .. data:: KX_MIST_LINEAR
+
+ Type of linear attenuation used to fade mist.
+
+ .. data:: KX_MIST_INV_QUADRATIC
+
+ Type of inverse quadratic attenuation used to fade mist.
+
+ .. attribute:: mistEnable
+
+ Return the state of the mist.
+
+ :type: bool
+
+ .. attribute:: mistStart
+
+ The mist start point.
+
+ :type: float
+
+ .. attribute:: mistDistance
+
+ The mist distance fom the start point to reach 100% mist.
+
+ :type: float
+
+ .. attribute:: mistIntensity
+
+ The mist intensity.
+
+ :type: float
+
+ .. attribute:: mistType
+
+ The type of mist - must be KX_MIST_QUADRATIC, KX_MIST_LINEAR or KX_MIST_INV_QUADRATIC
+
+ .. attribute:: mistColor
+
+ The color of the mist. Black = [0.0, 0.0, 0.0], White = [1.0, 1.0, 1.0].
+ Mist and background color sould always set to the same color.
+
+ :type: :class:`mathutils.Vector`
+
+ .. attribute:: backgroundColor
+
+ The color of the background. Black = [0.0, 0.0, 0.0], White = [1.0, 1.0, 1.0].
+ Mist and background color sould always set to the same color.
+
+ :type: :class:`mathutils.Vector`
+
+ .. attribute:: ambientColor
+
+ The color of the ambient light. Black = [0.0, 0.0, 0.0], White = [1.0, 1.0, 1.0].
+
+ :type: :class:`mathutils.Vector`
diff --git a/doc/python_api/rst/bge_types/bge.types.SCA_2DFilterActuator.rst b/doc/python_api/rst/bge_types/bge.types.SCA_2DFilterActuator.rst
index 291ee8426cf..0a6c5fc9025 100644
--- a/doc/python_api/rst/bge_types/bge.types.SCA_2DFilterActuator.rst
+++ b/doc/python_api/rst/bge_types/bge.types.SCA_2DFilterActuator.rst
@@ -7,7 +7,7 @@ base class --- :class:`SCA_IActuator`
.. class:: SCA_2DFilterActuator(SCA_IActuator)
- Create, enable and disable 2D filters
+ Create, enable and disable 2D filters.
The following properties don't have an immediate effect.
You must active the actuator to get the result.
@@ -29,7 +29,7 @@ base class --- :class:`SCA_IActuator`
.. attribute:: mode
- Type of 2D filter, use one of :ref:`these constants <Two-D-FilterActuator-mode>`
+ Type of 2D filter, use one of :ref:`these constants <Two-D-FilterActuator-mode>`.
:type: integer
diff --git a/doc/python_api/rst/bge_types/bge.types.SCA_ISensor.rst b/doc/python_api/rst/bge_types/bge.types.SCA_ISensor.rst
index 9efd2e2d63a..af444fb9e65 100644
--- a/doc/python_api/rst/bge_types/bge.types.SCA_ISensor.rst
+++ b/doc/python_api/rst/bge_types/bge.types.SCA_ISensor.rst
@@ -23,8 +23,14 @@ base class --- :class:`SCA_ILogicBrick`
.. attribute:: frequency
- The frequency for pulse mode sensors.
-
+ The frequency for pulse mode sensors. (Deprecated: use SCA_ISensor.skippedTicks)
+
+ :type: integer
+
+ .. attribute:: skippedTicks
+
+ Number of logic ticks skipped between 2 active pulses
+
:type: integer
.. attribute:: level
diff --git a/doc/python_api/rst/bge_types/bge.types.SCA_PythonMouse.rst b/doc/python_api/rst/bge_types/bge.types.SCA_PythonMouse.rst
index b1c6e5d1487..5dfa78d3942 100644
--- a/doc/python_api/rst/bge_types/bge.types.SCA_PythonMouse.rst
+++ b/doc/python_api/rst/bge_types/bge.types.SCA_PythonMouse.rst
@@ -25,7 +25,7 @@ base class --- :class:`PyObjectPlus`
The normalized x and y position of the mouse cursor.
- :type: list [x, y]
+ :type: tuple (x, y)
.. attribute:: visible
diff --git a/doc/python_api/rst/bgl.rst b/doc/python_api/rst/bgl.rst
index dfdb4a17998..8b0ad63abb4 100644
--- a/doc/python_api/rst/bgl.rst
+++ b/doc/python_api/rst/bgl.rst
@@ -8,26 +8,28 @@ This module wraps OpenGL constants and functions, making them available from
within Blender Python.
The complete list can be retrieved from the module itself, by listing its
-contents: dir(bgl). A simple search on the net can point to more
+contents: dir(bgl). A simple search on the web can point to more
than enough material to teach OpenGL programming, from books to many
collections of tutorials.
-The "red book": "I{OpenGL Programming Guide: The Official Guide to Learning
-OpenGL}" and the online NeHe tutorials are two of the best resources.
+Here is a comprehensive `list of books <http://www.opengl.org/documentation/books/>`__ (non free).
+The `arcsynthesis tutorials <http://www.arcsynthesis.org/gltut/>`__
+is one of the best resources to learn modern OpenGL and
+`g-truc <http://www.g-truc.net/post-tech-content-sample.html>`__
+offers a set of extensive examples, including advanced features.
+
.. note::
You can use the :class:`Image` type to load and set textures.
See :class:`Image.gl_load` and :class:`Image.gl_load`,
for example.
- `OpenGL.org <http://www.opengl.org>`_
- `NeHe GameDev <http://nehe.gamedev.net>`_
.. function:: glAccum(op, value):
Operate on the accumulation buffer.
- .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glAccum.xml>`_
+ .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glAccum.xml>`__
:type op: Enumerated constant
:arg op: The accumulation buffer operation.
@@ -39,7 +41,7 @@ OpenGL}" and the online NeHe tutorials are two of the best resources.
Specify the alpha test function.
- .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glAlphaFunc.xml>`_
+ .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glAlphaFunc.xml>`__
:type func: Enumerated constant
:arg func: Specifies the alpha comparison function.
@@ -52,7 +54,7 @@ OpenGL}" and the online NeHe tutorials are two of the best resources.
Determine if textures are loaded in texture memory
- .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glAreTexturesResident.xml>`_
+ .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glAreTexturesResident.xml>`__
:type n: int
:arg n: Specifies the number of textures to be queried.
@@ -68,7 +70,7 @@ OpenGL}" and the online NeHe tutorials are two of the best resources.
Delimit the vertices of a primitive or a group of like primatives
- .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glBegin.xml>`_
+ .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glBegin.xml>`__
:type mode: Enumerated constant
:arg mode: Specifies the primitive that will be create from vertices between
@@ -79,7 +81,7 @@ OpenGL}" and the online NeHe tutorials are two of the best resources.
Bind a named texture to a texturing target
- .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glBindTexture.xml>`_
+ .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glBindTexture.xml>`__
:type target: Enumerated constant
:arg target: Specifies the target to which the texture is bound.
@@ -91,7 +93,7 @@ OpenGL}" and the online NeHe tutorials are two of the best resources.
Draw a bitmap
- .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glBitmap.xml>`_
+ .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glBitmap.xml>`__
:type width, height: int
:arg width, height: Specify the pixel width and height of the bitmap image.
@@ -109,7 +111,7 @@ OpenGL}" and the online NeHe tutorials are two of the best resources.
Specify pixel arithmetic
- .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glBlendFunc.xml>`_
+ .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glBlendFunc.xml>`__
:type sfactor: Enumerated constant
:arg sfactor: Specifies how the red, green, blue, and alpha source blending factors are
@@ -123,7 +125,7 @@ OpenGL}" and the online NeHe tutorials are two of the best resources.
Execute a display list
- .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glCallList.xml>`_
+ .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glCallList.xml>`__
:type list: unsigned int
:arg list: Specifies the integer name of the display list to be executed.
@@ -133,7 +135,7 @@ OpenGL}" and the online NeHe tutorials are two of the best resources.
Execute a list of display lists
- .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glCallLists.xml>`_
+ .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glCallLists.xml>`__
:type n: int
:arg n: Specifies the number of display lists to be executed.
@@ -149,7 +151,7 @@ OpenGL}" and the online NeHe tutorials are two of the best resources.
Clear buffers to preset values
- .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glClear.xml>`_
+ .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glClear.xml>`__
:type mask: Enumerated constant(s)
:arg mask: Bitwise OR of masks that indicate the buffers to be cleared.
@@ -159,7 +161,7 @@ OpenGL}" and the online NeHe tutorials are two of the best resources.
Specify clear values for the accumulation buffer
- .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glClearAccum.xml>`_
+ .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glClearAccum.xml>`__
:type red, green, blue, alpha: float
:arg red, green, blue, alpha: Specify the red, green, blue, and alpha values used when the
@@ -170,7 +172,7 @@ OpenGL}" and the online NeHe tutorials are two of the best resources.
Specify clear values for the color buffers
- .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glClearColor.xml>`_
+ .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glClearColor.xml>`__
:type red, green, blue, alpha: float
:arg red, green, blue, alpha: Specify the red, green, blue, and alpha values used when the
@@ -181,7 +183,7 @@ OpenGL}" and the online NeHe tutorials are two of the best resources.
Specify the clear value for the depth buffer
- .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glClearDepth.xml>`_
+ .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glClearDepth.xml>`__
:type depth: int
:arg depth: Specifies the depth value used when the depth buffer is cleared.
@@ -192,7 +194,7 @@ OpenGL}" and the online NeHe tutorials are two of the best resources.
Specify the clear value for the color index buffers
- .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glClearIndex.xml>`_
+ .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glClearIndex.xml>`__
:type c: float
:arg c: Specifies the index used when the color index buffers are cleared.
@@ -203,7 +205,7 @@ OpenGL}" and the online NeHe tutorials are two of the best resources.
Specify the clear value for the stencil buffer
- .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glClearStencil.xml>`_
+ .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glClearStencil.xml>`__
:type s: int
:arg s: Specifies the index used when the stencil buffer is cleared. The initial value is 0.
@@ -213,7 +215,7 @@ OpenGL}" and the online NeHe tutorials are two of the best resources.
Specify a plane against which all geometry is clipped
- .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glClipPlane.xml>`_
+ .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glClipPlane.xml>`__
:type plane: Enumerated constant
:arg plane: Specifies which clipping plane is being positioned.
@@ -232,7 +234,7 @@ OpenGL}" and the online NeHe tutorials are two of the best resources.
Set a new color.
- .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glColor.xml>`_
+ .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glColor.xml>`__
:type red, green, blue, alpha: Depends on function prototype.
:arg red, green, blue: Specify new red, green, and blue values for the current color.
@@ -244,7 +246,7 @@ OpenGL}" and the online NeHe tutorials are two of the best resources.
Enable and disable writing of frame buffer color components
- .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glColorMask.xml>`_
+ .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glColorMask.xml>`__
:type red, green, blue, alpha: int (boolean)
:arg red, green, blue, alpha: Specify whether red, green, blue, and alpha can or cannot be
@@ -256,7 +258,7 @@ OpenGL}" and the online NeHe tutorials are two of the best resources.
Cause a material color to track the current color
- .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glColorMaterial.xml>`_
+ .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glColorMaterial.xml>`__
:type face: Enumerated constant
:arg face: Specifies whether front, back, or both front and back material parameters should
@@ -269,7 +271,7 @@ OpenGL}" and the online NeHe tutorials are two of the best resources.
Copy pixels in the frame buffer
- .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glCopyPixels.xml>`_
+ .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glCopyPixels.xml>`__
:type x, y: int
:arg x, y: Specify the window coordinates of the lower left corner of the rectangular
@@ -285,7 +287,7 @@ OpenGL}" and the online NeHe tutorials are two of the best resources.
Copy pixels into a 2D texture image
- .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glCopyTexImage2D.xml>`_
+ .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glCopyTexImage2D.xml>`__
:type target: Enumerated constant
:arg target: Specifies the target texture.
@@ -314,7 +316,7 @@ OpenGL}" and the online NeHe tutorials are two of the best resources.
Specify whether front- or back-facing facets can be culled
- .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glCullFace.xml>`_
+ .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glCullFace.xml>`__
:type mode: Enumerated constant
:arg mode: Specifies whether front- or back-facing facets are candidates for culling.
@@ -324,7 +326,7 @@ OpenGL}" and the online NeHe tutorials are two of the best resources.
Delete a contiguous group of display lists
- .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glDeleteLists.xml>`_
+ .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glDeleteLists.xml>`__
:type list: unsigned int
:arg list: Specifies the integer name of the first display list to delete
@@ -336,7 +338,7 @@ OpenGL}" and the online NeHe tutorials are two of the best resources.
Delete named textures
- .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glDeleteTextures.xml>`_
+ .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glDeleteTextures.xml>`__
:type n: int
:arg n: Specifies the number of textures to be deleted
@@ -348,7 +350,7 @@ OpenGL}" and the online NeHe tutorials are two of the best resources.
Specify the value used for depth buffer comparisons
- .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glDepthFunc.xml>`_
+ .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glDepthFunc.xml>`__
:type func: Enumerated constant
:arg func: Specifies the depth comparison function.
@@ -358,7 +360,7 @@ OpenGL}" and the online NeHe tutorials are two of the best resources.
Enable or disable writing into the depth buffer
- .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glDepthMask.xml>`_
+ .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glDepthMask.xml>`__
:type flag: int (boolean)
:arg flag: Specifies whether the depth buffer is enabled for writing. If flag is GL_FALSE,
@@ -370,7 +372,7 @@ OpenGL}" and the online NeHe tutorials are two of the best resources.
Specify mapping of depth values from normalized device coordinates to window coordinates
- .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glDepthRange.xml>`_
+ .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glDepthRange.xml>`__
:type zNear: int
:arg zNear: Specifies the mapping of the near clipping plane to window coordinates.
@@ -384,7 +386,7 @@ OpenGL}" and the online NeHe tutorials are two of the best resources.
Disable server-side GL capabilities
- .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glEnable.xml>`_
+ .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glEnable.xml>`__
:type cap: Enumerated constant
:arg cap: Specifies a symbolic constant indicating a GL capability.
@@ -394,7 +396,7 @@ OpenGL}" and the online NeHe tutorials are two of the best resources.
Specify which color buffers are to be drawn into
- .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glDrawBuffer.xml>`_
+ .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glDrawBuffer.xml>`__
:type mode: Enumerated constant
:arg mode: Specifies up to four color buffers to be drawn into.
@@ -404,7 +406,7 @@ OpenGL}" and the online NeHe tutorials are two of the best resources.
Write a block of pixels to the frame buffer
- .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glDrawPixels.xml>`_
+ .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glDrawPixels.xml>`__
:type width, height: int
:arg width, height: Specify the dimensions of the pixel rectangle to be
@@ -423,7 +425,7 @@ OpenGL}" and the online NeHe tutorials are two of the best resources.
Flag edges as either boundary or non-boundary
- .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glEdgeFlag.xml>`_
+ .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glEdgeFlag.xml>`__
:type flag: Depends of function prototype
:arg flag: Specifies the current edge flag value.The initial value is GL_TRUE.
@@ -433,7 +435,7 @@ OpenGL}" and the online NeHe tutorials are two of the best resources.
Enable server-side GL capabilities
- .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glEnable.xml>`_
+ .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glEnable.xml>`__
:type cap: Enumerated constant
:arg cap: Specifies a symbolic constant indicating a GL capability.
@@ -443,14 +445,14 @@ OpenGL}" and the online NeHe tutorials are two of the best resources.
Delimit the vertices of a primitive or group of like primitives
- .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glBegin.xml>`_
+ .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glBegin.xml>`__
.. function:: glEndList():
Create or replace a display list
- .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glNewList.xml>`_
+ .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glNewList.xml>`__
.. function:: glEvalCoord (u,v):
@@ -460,7 +462,7 @@ OpenGL}" and the online NeHe tutorials are two of the best resources.
Evaluate enabled one- and two-dimensional maps
- .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glEvalCoord.xml>`_
+ .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glEvalCoord.xml>`__
:type u: Depends on function prototype.
:arg u: Specifies a value that is the domain coordinate u to the basis function defined
@@ -478,7 +480,7 @@ OpenGL}" and the online NeHe tutorials are two of the best resources.
Compute a one- or two-dimensional grid of points or lines
- .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glEvalMesh.xml>`_
+ .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glEvalMesh.xml>`__
:type mode: Enumerated constant
:arg mode: In glEvalMesh1, specifies whether to compute a one-dimensional
@@ -493,7 +495,7 @@ OpenGL}" and the online NeHe tutorials are two of the best resources.
Generate and evaluate a single point in a mesh
- .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glEvalPoint.xml>`_
+ .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glEvalPoint.xml>`__
:type i: int
:arg i: Specifies the integer value for grid domain variable i.
@@ -505,7 +507,7 @@ OpenGL}" and the online NeHe tutorials are two of the best resources.
Controls feedback mode
- .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glFeedbackBuffer.xml>`_
+ .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glFeedbackBuffer.xml>`__
:type size: int
:arg size: Specifies the maximum number of values that can be written into buffer.
@@ -520,14 +522,14 @@ OpenGL}" and the online NeHe tutorials are two of the best resources.
Block until all GL execution is complete
- .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glFinish.xml>`_
+ .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glFinish.xml>`__
.. function:: glFlush():
Force Execution of GL commands in finite time
- .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glFlush.xml>`_
+ .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glFlush.xml>`__
.. function:: glFog (pname, param):
@@ -536,7 +538,7 @@ OpenGL}" and the online NeHe tutorials are two of the best resources.
Specify fog parameters
- .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glFog.xml>`_
+ .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glFog.xml>`__
:type pname: Enumerated constant
:arg pname: Specifies a single-valued fog parameter. If the function prototype
@@ -551,7 +553,7 @@ OpenGL}" and the online NeHe tutorials are two of the best resources.
Define front- and back-facing polygons
- .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glFrontFace.xml>`_
+ .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glFrontFace.xml>`__
:type mode: Enumerated constant
:arg mode: Specifies the orientation of front-facing polygons.
@@ -561,7 +563,7 @@ OpenGL}" and the online NeHe tutorials are two of the best resources.
Multiply the current matrix by a perspective matrix
- .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glFrustum.xml>`_
+ .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glFrustum.xml>`__
:type left, right: double (float)
:arg left, right: Specify the coordinates for the left and right vertical
@@ -578,7 +580,7 @@ OpenGL}" and the online NeHe tutorials are two of the best resources.
Generate a contiguous set of empty display lists
- .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glGenLists.xml>`_
+ .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glGenLists.xml>`__
:type range: int
:arg range: Specifies the number of contiguous empty display lists to be generated.
@@ -588,7 +590,7 @@ OpenGL}" and the online NeHe tutorials are two of the best resources.
Generate texture names
- .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glGenTextures.xml>`_
+ .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glGenTextures.xml>`__
:type n: int
:arg n: Specifies the number of textures name to be generated.
@@ -602,7 +604,7 @@ OpenGL}" and the online NeHe tutorials are two of the best resources.
Return the value or values of a selected parameter
- .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glGet.xml>`_
+ .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glGet.xml>`__
:type pname: Enumerated constant
:arg pname: Specifies the parameter value to be returned.
@@ -614,7 +616,7 @@ OpenGL}" and the online NeHe tutorials are two of the best resources.
Return the coefficients of the specified clipping plane
- .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glGetClipPlane.xml>`_
+ .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glGetClipPlane.xml>`__
:type plane: Enumerated constant
:arg plane: Specifies a clipping plane. The number of clipping planes depends on the
@@ -629,7 +631,7 @@ OpenGL}" and the online NeHe tutorials are two of the best resources.
Return error information
- .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glGetError.xml>`_
+ .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glGetError.xml>`__
.. function:: glGetLight (light, pname, params):
@@ -638,7 +640,7 @@ OpenGL}" and the online NeHe tutorials are two of the best resources.
Return light source parameter values
- .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glGetLight.xml>`_
+ .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glGetLight.xml>`__
:type light: Enumerated constant
:arg light: Specifies a light source. The number of possible lights depends on the
@@ -672,7 +674,7 @@ OpenGL}" and the online NeHe tutorials are two of the best resources.
Return material parameters
- .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glGetMaterial.xml>`_
+ .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glGetMaterial.xml>`__
:type face: Enumerated constant
:arg face: Specifies which of the two materials is being queried.
@@ -689,7 +691,7 @@ OpenGL}" and the online NeHe tutorials are two of the best resources.
Return the specified pixel map
- .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glGetPixelMap.xml>`_
+ .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glGetPixelMap.xml>`__
:type map: Enumerated constant
:arg map: Specifies the name of the pixel map to return.
@@ -701,7 +703,7 @@ OpenGL}" and the online NeHe tutorials are two of the best resources.
Return the polygon stipple pattern
- .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glGetPolygonStipple.xml>`_
+ .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glGetPolygonStipple.xml>`__
:type mask: :class:`bgl.Buffer` object I{type GL_BYTE}
:arg mask: Returns the stipple pattern. The initial value is all 1's.
@@ -711,7 +713,7 @@ OpenGL}" and the online NeHe tutorials are two of the best resources.
Return a string describing the current GL connection
- .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glGetString.xml>`_
+ .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glGetString.xml>`__
:type name: Enumerated constant
:arg name: Specifies a symbolic constant.
@@ -724,7 +726,7 @@ OpenGL}" and the online NeHe tutorials are two of the best resources.
Return texture environment parameters
- .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glGetTexEnv.xml>`_
+ .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glGetTexEnv.xml>`__
:type target: Enumerated constant
:arg target: Specifies a texture environment. Must be GL_TEXTURE_ENV.
@@ -740,7 +742,7 @@ OpenGL}" and the online NeHe tutorials are two of the best resources.
Return texture coordinate generation parameters
- .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glGetTexGen.xml>`_
+ .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glGetTexGen.xml>`__
:type coord: Enumerated constant
:arg coord: Specifies a texture coordinate.
@@ -754,7 +756,7 @@ OpenGL}" and the online NeHe tutorials are two of the best resources.
Return a texture image
- .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glGetTexImage.xml>`_
+ .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glGetTexImage.xml>`__
:type target: Enumerated constant
:arg target: Specifies which texture is to be obtained.
@@ -776,7 +778,7 @@ OpenGL}" and the online NeHe tutorials are two of the best resources.
return texture parameter values for a specific level of detail
- .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glGetTexLevelParameter.xml>`_
+ .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glGetTexLevelParameter.xml>`__
:type target: Enumerated constant
:arg target: Specifies the symbolic name of the target texture.
@@ -795,7 +797,7 @@ OpenGL}" and the online NeHe tutorials are two of the best resources.
Return texture parameter values
- .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glGetTexParameter.xml>`_
+ .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glGetTexParameter.xml>`__
:type target: Enumerated constant
:arg target: Specifies the symbolic name of the target texture.
@@ -809,7 +811,7 @@ OpenGL}" and the online NeHe tutorials are two of the best resources.
Specify implementation-specific hints
- .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glHint.xml>`_
+ .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glHint.xml>`__
:type target: Enumerated constant
:arg target: Specifies a symbolic constant indicating the behavior to be
@@ -824,7 +826,7 @@ OpenGL}" and the online NeHe tutorials are two of the best resources.
Set the current color index
- .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glIndex.xml>`_
+ .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glIndex.xml>`__
:type c: :class:`bgl.Buffer` object. Depends on function prototype.
:arg c: Specifies a pointer to a one element array that contains the new value for
@@ -835,7 +837,7 @@ OpenGL}" and the online NeHe tutorials are two of the best resources.
Control the writing of individual bits in the color index buffers
- .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glIndexMask.xml>`_
+ .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glIndexMask.xml>`__
:type mask: int
:arg mask: Specifies a bit mask to enable and disable the writing of individual bits
@@ -847,14 +849,14 @@ OpenGL}" and the online NeHe tutorials are two of the best resources.
Initialize the name stack
- .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glInitNames.xml>`_
+ .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glInitNames.xml>`__
.. function:: glIsEnabled(cap):
Test whether a capability is enabled
- .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glIsEnabled.xml>`_
+ .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glIsEnabled.xml>`__
:type cap: Enumerated constant
:arg cap: Specifies a constant representing a GL capability.
@@ -864,7 +866,7 @@ OpenGL}" and the online NeHe tutorials are two of the best resources.
Determine if a name corresponds to a display-list
- .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glIsList.xml>`_
+ .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glIsList.xml>`__
:type list: unsigned int
:arg list: Specifies a potential display-list name.
@@ -874,7 +876,7 @@ OpenGL}" and the online NeHe tutorials are two of the best resources.
Determine if a name corresponds to a texture
- .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glIsTexture.xml>`_
+ .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glIsTexture.xml>`__
:type texture: unsigned int
:arg texture: Specifies a value that may be the name of a texture.
@@ -886,7 +888,7 @@ OpenGL}" and the online NeHe tutorials are two of the best resources.
Set the light source parameters
- .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glLight.xml>`_
+ .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glLight.xml>`__
:type light: Enumerated constant
:arg light: Specifies a light. The number of lights depends on the implementation,
@@ -906,7 +908,7 @@ OpenGL}" and the online NeHe tutorials are two of the best resources.
Set the lighting model parameters
- .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glLightModel.xml>`_
+ .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glLightModel.xml>`__
:type pname: Enumerated constant
:arg pname: Specifies a single-value light model parameter.
@@ -919,7 +921,7 @@ OpenGL}" and the online NeHe tutorials are two of the best resources.
Specify the line stipple pattern
- .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glLineStipple.xml>`_
+ .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glLineStipple.xml>`__
:type factor: int
:arg factor: Specifies a multiplier for each bit in the line stipple pattern.
@@ -936,7 +938,7 @@ OpenGL}" and the online NeHe tutorials are two of the best resources.
Specify the width of rasterized lines.
- .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glLineWidth.xml>`_
+ .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glLineWidth.xml>`__
:type width: float
:arg width: Specifies the width of rasterized lines. The initial value is 1.
@@ -946,7 +948,7 @@ OpenGL}" and the online NeHe tutorials are two of the best resources.
Set the display-list base for glCallLists
- .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glListBase.xml>`_
+ .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glListBase.xml>`__
:type base: unsigned int
:arg base: Specifies an integer offset that will be added to glCallLists
@@ -957,7 +959,7 @@ OpenGL}" and the online NeHe tutorials are two of the best resources.
Replace the current matrix with the identity matrix
- .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glLoadIdentity.xml>`_
+ .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glLoadIdentity.xml>`__
.. function:: glLoadMatrix (m):
@@ -966,7 +968,7 @@ OpenGL}" and the online NeHe tutorials are two of the best resources.
Replace the current matrix with the specified matrix
- .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glLoadMatrix.xml>`_
+ .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glLoadMatrix.xml>`__
:type m: :class:`bgl.Buffer` object. Depends on function prototype.
:arg m: Specifies a pointer to 16 consecutive values, which are used as the elements
@@ -977,7 +979,7 @@ OpenGL}" and the online NeHe tutorials are two of the best resources.
Load a name onto the name stack.
- .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glLoadName.xml>`_
+ .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glLoadName.xml>`__
:type name: unsigned int
:arg name: Specifies a name that will replace the top value on the name stack.
@@ -987,7 +989,7 @@ OpenGL}" and the online NeHe tutorials are two of the best resources.
Specify a logical pixel operation for color index rendering
- .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glLogicOp.xml>`_
+ .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glLogicOp.xml>`__
:type opcode: Enumerated constant
:arg opcode: Specifies a symbolic constant that selects a logical operation.
@@ -999,7 +1001,7 @@ OpenGL}" and the online NeHe tutorials are two of the best resources.
Define a one-dimensional evaluator
- .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glMap1.xml>`_
+ .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glMap1.xml>`__
:type target: Enumerated constant
:arg target: Specifies the kind of values that are generated by the evaluator.
@@ -1024,7 +1026,7 @@ OpenGL}" and the online NeHe tutorials are two of the best resources.
Define a two-dimensional evaluator
- .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glMap2.xml>`_
+ .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glMap2.xml>`__
:type target: Enumerated constant
:arg target: Specifies the kind of values that are generated by the evaluator.
@@ -1065,7 +1067,7 @@ OpenGL}" and the online NeHe tutorials are two of the best resources.
Define a one- or two-dimensional mesh
- .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glMapGrid.xml>`_
+ .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glMapGrid.xml>`__
:type un: int
:arg un: Specifies the number of partitions in the grid range interval
@@ -1084,7 +1086,7 @@ OpenGL}" and the online NeHe tutorials are two of the best resources.
Specify material parameters for the lighting model.
- .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glMaterial.xml>`_
+ .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glMaterial.xml>`__
:type face: Enumerated constant
:arg face: Specifies which face or faces are being updated. Must be one of:
@@ -1101,7 +1103,7 @@ OpenGL}" and the online NeHe tutorials are two of the best resources.
Specify which matrix is the current matrix.
- .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glMatrixMode.xml>`_
+ .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glMatrixMode.xml>`__
:type mode: Enumerated constant
:arg mode: Specifies which matrix stack is the target for subsequent matrix operations.
@@ -1113,7 +1115,7 @@ OpenGL}" and the online NeHe tutorials are two of the best resources.
Multiply the current matrix with the specified matrix
- .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glMultMatrix.xml>`_
+ .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glMultMatrix.xml>`__
:type m: :class:`bgl.Buffer` object. Depends on function prototype.
:arg m: Points to 16 consecutive values that are used as the elements of a 4x4 column
@@ -1124,7 +1126,7 @@ OpenGL}" and the online NeHe tutorials are two of the best resources.
Create or replace a display list
- .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glNewList.xml>`_
+ .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glNewList.xml>`__
:type list: unsigned int
:arg list: Specifies the display list name
@@ -1139,7 +1141,7 @@ OpenGL}" and the online NeHe tutorials are two of the best resources.
Set the current normal vector
- .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glNormal.xml>`_
+ .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glNormal.xml>`__
:type nx, ny, nz: Depends on function prototype. (non - 'v' prototypes only)
:arg nx, ny, nz: Specify the x, y, and z coordinates of the new current normal.
@@ -1153,7 +1155,7 @@ OpenGL}" and the online NeHe tutorials are two of the best resources.
Multiply the current matrix with an orthographic matrix
- .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glOrtho.xml>`_
+ .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glOrtho.xml>`__
:type left, right: double (float)
:arg left, right: Specify the coordinates for the left and
@@ -1170,7 +1172,7 @@ OpenGL}" and the online NeHe tutorials are two of the best resources.
Place a marker in the feedback buffer
- .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glPassThrough.xml>`_
+ .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glPassThrough.xml>`__
:type token: float
:arg token: Specifies a marker value to be placed in the feedback
@@ -1183,7 +1185,7 @@ OpenGL}" and the online NeHe tutorials are two of the best resources.
Set up pixel transfer maps
- .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glPixelMap.xml>`_
+ .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glPixelMap.xml>`__
:type map: Enumerated constant
:arg map: Specifies a symbolic map name.
@@ -1199,7 +1201,7 @@ OpenGL}" and the online NeHe tutorials are two of the best resources.
Set pixel storage modes
- .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glPixelStore.xml>`_
+ .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glPixelStore.xml>`__
:type pname: Enumerated constant
:arg pname: Specifies the symbolic name of the parameter to be set.
@@ -1215,7 +1217,7 @@ OpenGL}" and the online NeHe tutorials are two of the best resources.
Set pixel transfer modes
- .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glPixelTransfer.xml>`_
+ .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glPixelTransfer.xml>`__
:type pname: Enumerated constant
:arg pname: Specifies the symbolic name of the pixel transfer parameter to be set.
@@ -1227,7 +1229,7 @@ OpenGL}" and the online NeHe tutorials are two of the best resources.
Specify the pixel zoom factors
- .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glPixelZoom.xml>`_
+ .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glPixelZoom.xml>`__
:type xfactor, yfactor: float
:arg xfactor, yfactor: Specify the x and y zoom factors for pixel write operations.
@@ -1237,7 +1239,7 @@ OpenGL}" and the online NeHe tutorials are two of the best resources.
Specify the diameter of rasterized points
- .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glPointSize.xml>`_
+ .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glPointSize.xml>`__
:type size: float
:arg size: Specifies the diameter of rasterized points. The initial value is 1.
@@ -1247,7 +1249,7 @@ OpenGL}" and the online NeHe tutorials are two of the best resources.
Select a polygon rasterization mode
- .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glPolygonMode.xml>`_
+ .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glPolygonMode.xml>`__
:type face: Enumerated constant
:arg face: Specifies the polygons that mode applies to.
@@ -1262,7 +1264,7 @@ OpenGL}" and the online NeHe tutorials are two of the best resources.
Set the scale and units used to calculate depth values
- .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glPolygonOffset.xml>`_
+ .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glPolygonOffset.xml>`__
:type factor: float
:arg factor: Specifies a scale factor that is used to create a variable depth
@@ -1276,7 +1278,7 @@ OpenGL}" and the online NeHe tutorials are two of the best resources.
Set the polygon stippling pattern
- .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glPolygonStipple.xml>`_
+ .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glPolygonStipple.xml>`__
:type mask: :class:`bgl.Buffer` object I{type GL_BYTE}
:arg mask: Specifies a pointer to a 32x32 stipple pattern that will be unpacked
@@ -1287,35 +1289,35 @@ OpenGL}" and the online NeHe tutorials are two of the best resources.
Pop the server attribute stack
- .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glPopAttrib.xml>`_
+ .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glPopAttrib.xml>`__
.. function:: glPopClientAttrib():
Pop the client attribute stack
- .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glPopClientAttrib.xml>`_
+ .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glPopClientAttrib.xml>`__
.. function:: glPopMatrix():
Pop the current matrix stack
- .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glPopMatrix.xml>`_
+ .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glPopMatrix.xml>`__
.. function:: glPopName():
Pop the name stack
- .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glPopName.xml>`_
+ .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glPopName.xml>`__
.. function:: glPrioritizeTextures(n, textures, priorities):
Set texture residence priority
- .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glPrioritizeTextures.xml>`_
+ .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glPrioritizeTextures.xml>`__
:type n: int
:arg n: Specifies the number of textures to be prioritized.
@@ -1331,7 +1333,7 @@ OpenGL}" and the online NeHe tutorials are two of the best resources.
Push the server attribute stack
- .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glPushAttrib.xml>`_
+ .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glPushAttrib.xml>`__
:type mask: Enumerated constant(s)
:arg mask: Specifies a mask that indicates which attributes to save.
@@ -1341,7 +1343,7 @@ OpenGL}" and the online NeHe tutorials are two of the best resources.
Push the client attribute stack
- .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glPushClientAttrib.xml>`_
+ .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glPushClientAttrib.xml>`__
:type mask: Enumerated constant(s)
:arg mask: Specifies a mask that indicates which attributes to save.
@@ -1351,14 +1353,14 @@ OpenGL}" and the online NeHe tutorials are two of the best resources.
Push the current matrix stack
- .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glPushMatrix.xml>`_
+ .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glPushMatrix.xml>`__
.. function:: glPushName(name):
Push the name stack
- .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glPushName.xml>`_
+ .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glPushName.xml>`__
:type name: unsigned int
:arg name: Specifies a name that will be pushed onto the name stack.
@@ -1374,7 +1376,7 @@ OpenGL}" and the online NeHe tutorials are two of the best resources.
Specify the raster position for pixel operations
- .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glRasterPos.xml>`_
+ .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glRasterPos.xml>`__
:type x, y, z, w: Depends on function prototype. (z and w for '3' and '4' prototypes only)
:arg x, y, z, w: Specify the x,y,z, and w object coordinates (if present) for the
@@ -1406,7 +1408,7 @@ OpenGL}" and the online NeHe tutorials are two of the best resources.
Select a color buffer source for pixels.
- .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glReadBuffer.xml>`_
+ .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glReadBuffer.xml>`__
:type mode: Enumerated constant
:arg mode: Specifies a color buffer.
@@ -1416,7 +1418,7 @@ OpenGL}" and the online NeHe tutorials are two of the best resources.
Read a block of pixels from the frame buffer
- .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glReadPixels.xml>`_
+ .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glReadPixels.xml>`__
:type x, y: int
:arg x, y: Specify the window coordinates of the first pixel that is read
@@ -1439,7 +1441,7 @@ OpenGL}" and the online NeHe tutorials are two of the best resources.
Draw a rectangle
- .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glRect.xml>`_
+ .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glRect.xml>`__
:type x1, y1: Depends on function prototype. (for non 'v' prototypes only)
:arg x1, y1: Specify one vertex of a rectangle
@@ -1454,7 +1456,7 @@ OpenGL}" and the online NeHe tutorials are two of the best resources.
Set rasterization mode
- .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glRenderMode.xml>`_
+ .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glRenderMode.xml>`__
:type mode: Enumerated constant
:arg mode: Specifies the rasterization mode.
@@ -1466,7 +1468,7 @@ OpenGL}" and the online NeHe tutorials are two of the best resources.
Multiply the current matrix by a rotation matrix
- .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glRotate.xml>`_
+ .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glRotate.xml>`__
:type angle: Depends on function prototype.
:arg angle: Specifies the angle of rotation in degrees.
@@ -1480,7 +1482,7 @@ OpenGL}" and the online NeHe tutorials are two of the best resources.
Multiply the current matrix by a general scaling matrix
- .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glScale.xml>`_
+ .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glScale.xml>`__
:type x, y, z: Depends on function prototype.
:arg x, y, z: Specify scale factors along the x, y, and z axes, respectively.
@@ -1490,7 +1492,7 @@ OpenGL}" and the online NeHe tutorials are two of the best resources.
Define the scissor box
- .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glScissor.xml>`_
+ .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glScissor.xml>`__
:type x, y: int
:arg x, y: Specify the lower left corner of the scissor box. Initially (0, 0).
@@ -1504,7 +1506,7 @@ OpenGL}" and the online NeHe tutorials are two of the best resources.
Establish a buffer for selection mode values
- .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glSelectBuffer.xml>`_
+ .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glSelectBuffer.xml>`__
:type size: int
:arg size: Specifies the size of buffer
@@ -1516,7 +1518,7 @@ OpenGL}" and the online NeHe tutorials are two of the best resources.
Select flat or smooth shading
- .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glShadeModel.xml>`_
+ .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glShadeModel.xml>`__
:type mode: Enumerated constant
:arg mode: Specifies a symbolic value representing a shading technique.
@@ -1526,7 +1528,7 @@ OpenGL}" and the online NeHe tutorials are two of the best resources.
Set function and reference value for stencil testing
- .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glStencilFuc.xml>`_
+ .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glStencilFuc.xml>`__
:type func: Enumerated constant
:arg func: Specifies the test function.
@@ -1543,7 +1545,7 @@ OpenGL}" and the online NeHe tutorials are two of the best resources.
Control the writing of individual bits in the stencil planes
- .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glStencilMask.xml>`_
+ .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glStencilMask.xml>`__
:type mask: unsigned int
:arg mask: Specifies a bit mask to enable and disable writing of individual bits
@@ -1554,7 +1556,7 @@ OpenGL}" and the online NeHe tutorials are two of the best resources.
Set stencil test actions
- .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glStencilOp.xml>`_
+ .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glStencilOp.xml>`__
:type fail: Enumerated constant
:arg fail: Specifies the action to take when the stencil test fails.
@@ -1582,7 +1584,7 @@ OpenGL}" and the online NeHe tutorials are two of the best resources.
Set the current texture coordinates
- .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glTexCoord.xml>`_
+ .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glTexCoord.xml>`__
:type s, t, r, q: Depends on function prototype. (r and q for '3' and '4' prototypes only)
:arg s, t, r, q: Specify s, t, r, and q texture coordinates. Not all parameters are
@@ -1598,7 +1600,7 @@ OpenGL}" and the online NeHe tutorials are two of the best resources.
Set texture environment parameters
- .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glTexEnv.xml>`_
+ .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glTexEnv.xml>`__
:type target: Enumerated constant
:arg target: Specifies a texture environment. Must be GL_TEXTURE_ENV.
@@ -1617,7 +1619,7 @@ OpenGL}" and the online NeHe tutorials are two of the best resources.
Control the generation of texture coordinates
- .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glTexGen.xml>`_
+ .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glTexGen.xml>`__
:type coord: Enumerated constant
:arg coord: Specifies a texture coordinate.
@@ -1635,7 +1637,7 @@ OpenGL}" and the online NeHe tutorials are two of the best resources.
Specify a one-dimensional texture image
- .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glTexImage1D.xml>`_
+ .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glTexImage1D.xml>`__
:type target: Enumerated constant
:arg target: Specifies the target texture.
@@ -1662,7 +1664,7 @@ OpenGL}" and the online NeHe tutorials are two of the best resources.
Specify a two-dimensional texture image
- .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glTexImage2D.xml>`_
+ .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glTexImage2D.xml>`__
:type target: Enumerated constant
:arg target: Specifies the target texture.
@@ -1695,7 +1697,7 @@ OpenGL}" and the online NeHe tutorials are two of the best resources.
Set texture parameters
- .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glTexParameter.xml>`_
+ .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glTexParameter.xml>`__
:type target: Enumerated constant
:arg target: Specifies the target texture.
@@ -1712,7 +1714,7 @@ OpenGL}" and the online NeHe tutorials are two of the best resources.
Multiply the current matrix by a translation matrix
- .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glTranslate.xml>`_
+ .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glTranslate.xml>`__
:type x, y, z: Depends on function prototype.
:arg x, y, z: Specify the x, y, and z coordinates of a translation vector.
@@ -1727,7 +1729,7 @@ OpenGL}" and the online NeHe tutorials are two of the best resources.
Specify a vertex
- .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glVertex.xml>`_
+ .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glVertex.xml>`__
:type x, y, z, w: Depends on function prototype (z and w for '3' and '4' prototypes only)
:arg x, y, z, w: Specify x, y, z, and w coordinates of a vertex. Not all parameters
@@ -1743,7 +1745,7 @@ OpenGL}" and the online NeHe tutorials are two of the best resources.
Set the viewport
- .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glViewport.xml>`_
+ .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glViewport.xml>`__
:type x, y: int
:arg x, y: Specify the lower left corner of the viewport rectangle,
@@ -1851,7 +1853,7 @@ OpenGL}" and the online NeHe tutorials are two of the best resources.
Installs a program object as part of current rendering state
- .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glUseProgram.xml>`_
+ .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glUseProgram.xml>`__
:type program: int
:arg program: Specifies the handle of the program object whose executables are to be used as part of current rendering state.
@@ -1861,7 +1863,7 @@ OpenGL}" and the online NeHe tutorials are two of the best resources.
Validates a program object
- .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glValidateProgram.xml>`_
+ .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glValidateProgram.xml>`__
:type program: int
:arg program: Specifies the handle of the program object to be validated.
@@ -1871,7 +1873,7 @@ OpenGL}" and the online NeHe tutorials are two of the best resources.
Links a program object.
- .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glLinkProgram.xml>`_
+ .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glLinkProgram.xml>`__
:type program: int
:arg program: Specifies the handle of the program object to be linked.
@@ -1881,7 +1883,7 @@ OpenGL}" and the online NeHe tutorials are two of the best resources.
Select active texture unit.
- .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glActiveTexture.xml>`_
+ .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glActiveTexture.xml>`__
:type texture: int
:arg texture: Constant in ``GL_TEXTURE0`` 0 - 8
@@ -1891,7 +1893,7 @@ OpenGL}" and the online NeHe tutorials are two of the best resources.
Attaches a shader object to a program object.
- .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glAttachShader.xml>`_
+ .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glAttachShader.xml>`__
:type program: int
:arg program: Specifies the program object to which a shader object will be attached.
@@ -1903,7 +1905,7 @@ OpenGL}" and the online NeHe tutorials are two of the best resources.
Compiles a shader object.
- .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glCompileShader.xml>`_
+ .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glCompileShader.xml>`__
:type shader: int
:arg shader: Specifies the shader object to be compiled.
@@ -1913,7 +1915,7 @@ OpenGL}" and the online NeHe tutorials are two of the best resources.
Creates a program object
- .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glCreateProgram.xml>`_
+ .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glCreateProgram.xml>`__
:rtype: int
:return: The new program or zero if an error occurs.
@@ -1923,7 +1925,7 @@ OpenGL}" and the online NeHe tutorials are two of the best resources.
Creates a shader object.
- .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glCreateShader.xml>`_
+ .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glCreateShader.xml>`__
:type shaderType: Specifies the type of shader to be created.
Must be one of ``GL_VERTEX_SHADER``,
@@ -1940,7 +1942,7 @@ OpenGL}" and the online NeHe tutorials are two of the best resources.
Deletes a program object.
- .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glDeleteProgram.xml>`_
+ .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glDeleteProgram.xml>`__
:type program: int
:arg program: Specifies the program object to be deleted.
@@ -1950,7 +1952,7 @@ OpenGL}" and the online NeHe tutorials are two of the best resources.
Deletes a shader object.
- .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glDeleteShader.xml>`_
+ .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glDeleteShader.xml>`__
:type shader: int
:arg shader: Specifies the shader object to be deleted.
@@ -1960,7 +1962,7 @@ OpenGL}" and the online NeHe tutorials are two of the best resources.
Detaches a shader object from a program object to which it is attached.
- .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glDetachShader.xml>`_
+ .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glDetachShader.xml>`__
:type program: int
:arg program: Specifies the program object from which to detach the shader object.
@@ -1972,7 +1974,7 @@ OpenGL}" and the online NeHe tutorials are two of the best resources.
Returns the handles of the shader objects attached to a program object.
- .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glGetAttachedShaders.xml>`_
+ .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glGetAttachedShaders.xml>`__
:type program: int
:arg program: Specifies the program object to be queried.
@@ -1988,7 +1990,7 @@ OpenGL}" and the online NeHe tutorials are two of the best resources.
Returns the information log for a program object.
- .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glGetProgramInfoLog.xml>`_
+ .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glGetProgramInfoLog.xml>`__
:type program: int
:arg program: Specifies the program object whose information log is to be queried.
@@ -2004,7 +2006,7 @@ OpenGL}" and the online NeHe tutorials are two of the best resources.
Returns the information log for a shader object.
- .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glGetShaderInfoLog.xml>`_
+ .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glGetShaderInfoLog.xml>`__
:type shader: int
:arg shader: Specifies the shader object whose information log is to be queried.
@@ -2020,7 +2022,7 @@ OpenGL}" and the online NeHe tutorials are two of the best resources.
Returns a parameter from a program object.
- .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glGetProgram.xml>`_
+ .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glGetProgram.xml>`__
:type program: int
:arg program: Specifies the program object to be queried.
@@ -2034,7 +2036,7 @@ OpenGL}" and the online NeHe tutorials are two of the best resources.
Determines if a name corresponds to a shader object.
- .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glIsShader.xml>`_
+ .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glIsShader.xml>`__
:type shader: int
:arg shader: Specifies a potential shader object.
@@ -2044,7 +2046,7 @@ OpenGL}" and the online NeHe tutorials are two of the best resources.
Determines if a name corresponds to a program object
- .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glIsProgram.xml>`_
+ .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glIsProgram.xml>`__
:type program: int
:arg program: Specifies a potential program object.
@@ -2054,7 +2056,7 @@ OpenGL}" and the online NeHe tutorials are two of the best resources.
Returns the source code string from a shader object
- .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glGetShaderSource.xml>`_
+ .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glGetShaderSource.xml>`__
:type shader: int
:arg shader: Specifies the shader object to be queried.
@@ -2070,7 +2072,7 @@ OpenGL}" and the online NeHe tutorials are two of the best resources.
Replaces the source code in a shader object.
- .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man2/xhtml/glShaderSource.xml>`_
+ .. seealso:: `OpenGL Docs <http://www.opengl.org/sdk/docs/man/html/glShaderSource.xhtml>`__
:type shader: int
:arg shader: Specifies the handle of the shader object whose source code is to be replaced.
diff --git a/doc/python_api/rst/gpu.rst b/doc/python_api/rst/gpu.rst
index aaceb3ce32e..b56523c2206 100644
--- a/doc/python_api/rst/gpu.rst
+++ b/doc/python_api/rst/gpu.rst
@@ -16,24 +16,24 @@ and in the game engine.
.. warning::
- The API provided by this module should be consider unstable. The data exposed by the API
- are are closely related to Blender's internal GLSL code and may change if the GLSL code
- is modified (e.g. new uniform type).
+ The API provided by this module is subject to change.
+ The data exposed by the API are are closely related to Blender's internal GLSL code
+ and may change if the GLSL code is modified (e.g. new uniform type).
Constants
=========
-GLSL data type
+GLSL Data Type
--------------
.. _data-type:
Type of GLSL data.
-For shader uniforms, the data type determines which glUniform function
+For shader uniforms, the data type determines which ``glUniform`` function
variant to use to send the uniform value to the GPU.
-For vertex attributes, the data type determines which glVertexAttrib function
+For vertex attributes, the data type determines which ``glVertexAttrib`` function
variant to use to send the vertex attribute to the GPU.
See export_shader_
@@ -42,53 +42,37 @@ See export_shader_
one integer
- :value: 1
-
.. data:: GPU_DATA_1F
one float
- :value: 2
-
.. data:: GPU_DATA_2F
two floats
- :value: 3
-
.. data:: GPU_DATA_3F
three floats
- :value: 4
-
.. data:: GPU_DATA_4F
four floats
- :value: 5
-
.. data:: GPU_DATA_9F
matrix 3x3 in column-major order
- :value: 6
-
.. data:: GPU_DATA_16F
matrix 4x4 in column-major order
- :value: 7
-
.. data:: GPU_DATA_4UB
four unsigned byte
- :value: 8
-
-GLSL uniform type
------------------
+GLSL Uniform Types
+------------------
.. _uniform-type:
@@ -101,7 +85,7 @@ The calculation of some of the uniforms is based on matrices available in the sc
.. _mat4_cam_to_world:
.. _mat4_world_to_cam:
- *mat4_cam_to_world*
+ ``mat4_cam_to_world``
Model matrix of the camera. OpenGL 4x4 matrix that converts
camera local coordinates to world coordinates. In blender this is obtained from the
'matrix_world' attribute of the camera object.
@@ -112,7 +96,7 @@ The calculation of some of the uniforms is based on matrices available in the sc
.. _mat4_object_to_world:
.. _mat4_world_to_object:
- *mat4_object_to_world*
+ ``mat4_object_to_world``
Model matrix of the object that is being rendered. OpenGL 4x4 matric that converts
object local coordinates to world coordinates. In blender this is obtained from the
'matrix_world' attribute of the object.
@@ -122,7 +106,7 @@ The calculation of some of the uniforms is based on matrices available in the sc
.. _mat4_lamp_to_world:
.. _mat4_world_to_lamp:
- *mat4_lamp_to_world*
+ ``mat4_lamp_to_world``
Model matrix of the lamp lighting the object. OpenGL 4x4 matrix that converts lamp
local coordinates to world coordinates. In blender this is obtained from the
'matrix_world' attribute of the lamp object.
@@ -130,151 +114,299 @@ The calculation of some of the uniforms is based on matrices available in the sc
Some uniform will need the *mat4_world_to_lamp* matrix
computed as the inverse of this matrix.
+
+.. note::
+
+ Any uniforms used for view projections or transformations (object, lamp matrices for eg),
+ can only be set once per frame.
+
+
+GLSL Object Uniforms
+^^^^^^^^^^^^^^^^^^^^
+
+.. note::
+
+ - Object transformations and color must be set before drawing the object.
+ - There is at most one uniform of these types per shader.
+
.. data:: GPU_DYNAMIC_OBJECT_VIEWMAT
- The uniform is a 4x4 GL matrix that converts world coordinates to
- camera coordinates (see mat4_world_to_cam_). Can be set once per frame.
- There is at most one uniform of that type per shader.
+ A matrix that converts world coordinates to camera coordinates (see mat4_world_to_cam_).
- :value: 1
+ :type: matrix4x4
.. data:: GPU_DYNAMIC_OBJECT_MAT
- The uniform is a 4x4 GL matrix that converts object coordinates
- to world coordinates (see mat4_object_to_world_). Must be set before drawing the object.
- There is at most one uniform of that type per shader.
+ A matrix that converts object coordinates to world coordinates (see mat4_object_to_world_).
- :value: 2
+ :type: matrix4x4
.. data:: GPU_DYNAMIC_OBJECT_VIEWIMAT
The uniform is a 4x4 GL matrix that converts coordinates
in camera space to world coordinates (see mat4_cam_to_world_).
- Can be set once per frame.
- There is at most one uniform of that type per shader.
- :value: 3
+ :type: matrix4x4
.. data:: GPU_DYNAMIC_OBJECT_IMAT
The uniform is a 4x4 GL matrix that converts world coodinates
to object coordinates (see mat4_world_to_object_).
- Must be set before drawing the object.
- There is at most one uniform of that type per shader.
- :value: 4
+ :type: matrix4x4
.. data:: GPU_DYNAMIC_OBJECT_COLOR
- The uniform is a vector of 4 float representing a RGB color + alpha defined at object level.
- Each values between 0.0 and 1.0. In blender it corresponds to the 'color' attribute of the object.
- Must be set before drawing the object.
- There is at most one uniform of that type per shader.
+ An RGB color + alpha defined at object level.
+ Each values between 0.0 and 1.0.
- :value: 5
+ See :class:`bpy.types.Object.color`.
+
+ :type: float4
+
+.. data:: GPU_DYNAMIC_OBJECT_AUTOBUMPSCALE
+
+ Multiplier for bump-map scaling.
+
+ :type: float
-.. data:: GPU_DYNAMIC_LAMP_DYNVEC
- The uniform is a vector of 3 float representing the direction of light in camera space.
- In Blender, this is computed by
+GLSL Lamp Uniforms
+^^^^^^^^^^^^^^^^^^
- mat4_world_to_cam_ * (-vec3_lamp_Z_axis)
+.. note::
- as the lamp Z axis points to the opposite direction of light.
- The norm of the vector should be unity. Can be set once per frame.
There is one uniform of that type per lamp lighting the material.
- :value: 6
+.. data:: GPU_DYNAMIC_LAMP_DYNVEC
-.. data:: GPU_DYNAMIC_LAMP_DYNCO
+ Represents the direction of light in camera space.
- The uniform is a vector of 3 float representing the position of the light in camera space.
- Computed as
+ Computed as:
+ mat4_world_to_cam_ * (-vec3_lamp_Z_axis)
- mat4_world_to_cam_ * vec3_lamp_pos
+ .. note::
+ - The lamp Z axis points to the opposite direction of light.
+ - The norm of the vector should be unit length.
- Can be set once per frame.
- There is one uniform of that type per lamp lighting the material.
+ :type: float3
- :value: 7
+.. data:: GPU_DYNAMIC_LAMP_DYNCO
-.. data:: GPU_DYNAMIC_LAMP_DYNIMAT
+ Represents the position of the light in camera space.
- The uniform is a 4x4 GL matrix that converts vector in camera space to lamp space.
- Computed as
+ Computed as:
+ mat4_world_to_cam_ * vec3_lamp_pos
- mat4_world_to_lamp_ * mat4_cam_to_world_
+ :type: float3
- Can be set once per frame.
- There is one uniform of that type per lamp lighting the material.
+.. data:: GPU_DYNAMIC_LAMP_DYNIMAT
- :value: 8
+ Matrix that converts vector in camera space to lamp space.
+
+ Computed as:
+ mat4_world_to_lamp_ * mat4_cam_to_world_
+
+ :type: matrix4x4
.. data:: GPU_DYNAMIC_LAMP_DYNPERSMAT
- The uniform is a 4x4 GL matrix that converts a vector in camera space to shadow buffer depth space.
- Computed as
+ Matrix that converts a vector in camera space to shadow buffer depth space.
- mat4_perspective_to_depth_ * mat4_lamp_to_perspective_ * mat4_world_to_lamp_ * mat4_cam_to_world_.
+ Computed as:
+ mat4_perspective_to_depth_ * mat4_lamp_to_perspective_ * mat4_world_to_lamp_ * mat4_cam_to_world_.
.. _mat4_perspective_to_depth:
- *mat4_perspective_to_depth* is a fixed matrix defined as follow::
+ ``mat4_perspective_to_depth`` is a fixed matrix defined as follow::
0.5 0.0 0.0 0.5
0.0 0.5 0.0 0.5
0.0 0.0 0.5 0.5
0.0 0.0 0.0 1.0
- This uniform can be set once per frame. There is one uniform of that type per lamp casting shadow in the scene.
+ .. note::
- :value: 9
+ - There is one uniform of that type per lamp casting shadow in the scene.
+
+ :type: matrix4x4
.. data:: GPU_DYNAMIC_LAMP_DYNENERGY
- The uniform is a single float representing the lamp energy. In blender it corresponds
- to the 'energy' attribute of the lamp data block.
- There is one uniform of that type per lamp lighting the material.
+ See :class:`bpy.types.Lamp.energy`.
- :value: 10
+ :type: float
.. data:: GPU_DYNAMIC_LAMP_DYNCOL
- The uniform is a vector of 3 float representing the lamp color.
- Color elements are between 0.0 and 1.0. In blender it corresponds
- to the 'color' attribute of the lamp data block.
- There is one uniform of that type per lamp lighting the material.
+ See :class:`bpy.types.Lamp.color`.
+
+ :type: float3
+
+.. data:: GPU_DYNAMIC_LAMP_DISTANCE
+
+ See :class:`bpy.types.Lamp.distance`.
+
+ :type: float
+
+.. data:: GPU_DYNAMIC_LAMP_ATT1
+
+ See
+ :class:`bpy.types.PointLamp.linear_attenuation`,
+ :class:`bpy.types.SpotLamp.linear_attenuation`.
+
+ :type: float
+
+.. data:: GPU_DYNAMIC_LAMP_ATT2
+
+ See
+ :class:`bpy.types.PointLamp.quadratic_attenuation`,
+ :class:`bpy.types.SpotLamp.quadratic_attenuation`.
- :value: 11
+ :type: float
+
+.. data:: GPU_DYNAMIC_LAMP_SPOTSIZE
+
+ See :class:`bpy.types.SpotLamp.spot_size`.
+
+ :type: float
+
+.. data:: GPU_DYNAMIC_LAMP_SPOTBLEND
+
+ See :class:`bpy.types.SpotLamp.spot_blend`.
+
+ :type: float
+
+
+GLSL Sampler Uniforms
+^^^^^^^^^^^^^^^^^^^^^
.. data:: GPU_DYNAMIC_SAMPLER_2DBUFFER
- The uniform is an integer representing an internal texture used for certain effect
+ Represents an internal texture used for certain effect
(color band, etc).
- :value: 12
+ :type: integer
.. data:: GPU_DYNAMIC_SAMPLER_2DIMAGE
- The uniform is an integer representing a texture loaded from an image file.
+ Represents a texture loaded from an image file.
- :value: 13
+ :type: integer
.. data:: GPU_DYNAMIC_SAMPLER_2DSHADOW
- The uniform is an float representing the bumpmap scaling.
+ Represents a texture loaded from a shadow buffer file.
- :value: 14
+ :type: integer
-.. data:: GPU_DYNAMIC_OBJECT_AUTOBUMPSCALE
- The uniform is an integer representing a shadow buffer corresponding to a lamp
- casting shadow.
+GLSL Mist Uniforms
+^^^^^^^^^^^^^^^^^^
+
+.. data:: GPU_DYNAMIC_MIST_ENABLE:
+
+ See :class:`bpy.types.WorldMistSettings.use_mist`.
+
+ :type: float (0 or 1)
+
+.. data:: GPU_DYNAMIC_MIST_START
- :value: 15
+ See :class:`bpy.types.WorldMistSettings.start`.
+ :type: float
-GLSL attribute type
+ See :class:`bpy.types.WorldMistSettings.depth`.
+
+.. data:: GPU_DYNAMIC_MIST_DISTANCE
+
+ :type: float
+
+ See :class:`bpy.types.WorldMistSettings.intensity`.
+
+.. data:: GPU_DYNAMIC_MIST_INTENSITY
+
+ :type: float
+
+.. data:: GPU_DYNAMIC_MIST_TYPE
+
+ See :class:`bpy.types.WorldMistSettings.falloff`.
+
+ :type: float (used as an index into the type)
+
+.. data:: GPU_DYNAMIC_MIST_COLOR
+
+
+GLSL World Uniforms
+^^^^^^^^^^^^^^^^^^^
+
+.. data:: GPU_DYNAMIC_HORIZON_COLOR
+
+ See :class:`bpy.types.World.horizon_color`.
+
+ :type: float3
+
+.. data:: GPU_DYNAMIC_AMBIENT_COLOR
+
+ See :class:`bpy.types.World.ambient_color`.
+
+ :type: float3
+
+
+GLSL Material Uniforms
+^^^^^^^^^^^^^^^^^^^^^^
+
+.. data:: GPU_DYNAMIC_MAT_DIFFRGB
+
+ See :class:`bpy.types.Material.diffuse_color`.
+
+ :type: float3
+
+.. data:: GPU_DYNAMIC_MAT_REF
+
+ See :class:`bpy.types.Material.diffuse_intensity`.
+
+ :type: float
+
+.. data:: GPU_DYNAMIC_MAT_SPECRGB
+
+ See :class:`bpy.types.Material.specular_color`.
+
+ :type: float3
+
+.. data:: GPU_DYNAMIC_MAT_SPEC
+
+ See :class:`bpy.types.Material.specular_intensity`.
+
+ :type: float
+
+.. data:: GPU_DYNAMIC_MAT_HARD
+
+ See :class:`bpy.types.Material.specular_hardness`.
+
+ :type: float
+
+.. data:: GPU_DYNAMIC_MAT_EMIT
+
+ See :class:`bpy.types.Material.emit`.
+
+ :type: float
+
+.. data:: GPU_DYNAMIC_MAT_AMB
+
+ See :class:`bpy.types.Material.ambient`.
+
+ :type: float
+
+.. data:: GPU_DYNAMIC_MAT_ALPHA
+
+ See :class:`bpy.types.Material.alpha`.
+
+ :type: float
+
+
+
+GLSL Attribute Type
-------------------
.. _attribute-type:
@@ -291,9 +423,7 @@ layer that contains the vertex attribute.
.. code-block:: python
- mesh.uv_textures[attribute["name"]]
-
- :value: 5
+ mesh.uv_layers[attribute["name"]]
.. data:: CD_MCOL
@@ -306,8 +436,6 @@ layer that contains the vertex attribute.
mesh.vertex_colors[attribute["name"]]
- :value: 6
-
.. data:: CD_ORCO
Vertex attribute is original coordinates. Data type is vector 3 float.
@@ -319,8 +447,6 @@ layer that contains the vertex attribute.
mesh.vertices
- :value: 14
-
.. data:: CD_TANGENT
Vertex attribute is the tangent vector. Data type is vector 4 float.
@@ -330,8 +456,6 @@ layer that contains the vertex attribute.
C function to compute the tangent layer from the other layers can be obtained from
blender.org.
- :value: 18
-
Functions
=========
@@ -341,8 +465,12 @@ Functions
.. function:: export_shader(scene,material)
Extracts the GLSL shader producing the visual effect of material in scene for the purpose of
- reusing the shader in an external engine. This function is meant to be used in material exporter
- so that the GLSL shader can be exported entirely. The return value is a dictionary containing the
+ reusing the shader in an external engine.
+
+ This function is meant to be used in material exporter
+ so that the GLSL shader can be exported entirely.
+
+ The return value is a dictionary containing the
shader source code and all associated data.
:arg scene: the scene in which the material in rendered.
@@ -354,76 +482,91 @@ Functions
The dictionary contains the following elements:
- * ["fragment"] : string
+ - ``["fragment"]``: string
fragment shader source code.
- * ["vertex"] : string
+ - ``["vertex"]``: string
vertex shader source code.
- * ["uniforms"] : sequence
+ - ``["uniforms"]``: sequence
list of uniforms used in fragment shader, can be empty list. Each element of the
sequence is a dictionary with the following elements:
- * ["varname"] : string
+ - ``["varname"]``: string
name of the uniform in the fragment shader. Always of the form 'unf<number>'.
- * ["datatype"] : integer
+ - ``["datatype"]``: integer
data type of the uniform variable. Can be one of the following:
- * :data:`gpu.GPU_DATA_1I` : use glUniform1i
- * :data:`gpu.GPU_DATA_1F` : use glUniform1fv
- * :data:`gpu.GPU_DATA_2F` : use glUniform2fv
- * :data:`gpu.GPU_DATA_3F` : use glUniform3fv
- * :data:`gpu.GPU_DATA_4F` : use glUniform4fv
- * :data:`gpu.GPU_DATA_9F` : use glUniformMatrix3fv
- * :data:`gpu.GPU_DATA_16F` : use glUniformMatrix4fv
+ .. hlist::
+ :columns: 2
+
+ - :data:`gpu.GPU_DATA_1I` : use ``glUniform1i``
+ - :data:`gpu.GPU_DATA_1F` : use ``glUniform1fv``
+ - :data:`gpu.GPU_DATA_2F` : use ``glUniform2fv``
+ - :data:`gpu.GPU_DATA_3F` : use ``glUniform3fv``
+ - :data:`gpu.GPU_DATA_4F` : use ``glUniform4fv``
+ - :data:`gpu.GPU_DATA_9F` : use ``glUniformMatrix3fv``
+ - :data:`gpu.GPU_DATA_16F` : use ``glUniformMatrix4fv``
- * ["type"] : integer
+ - ``["type"]``: integer
type of uniform, determines the origin and method of calculation. See uniform-type_.
Depending on the type, more elements will be be present.
- * ["lamp"] : :class:`bpy.types.Object`
- Reference to the lamp object from which the uniforms value are extracted. Set for the following uniforms types:
+ - ``["lamp"]``: :class:`bpy.types.Object`
+ Reference to the lamp object from which the uniforms value are extracted.
+ Set for the following uniforms types:
.. hlist::
- :columns: 3
+ :columns: 2
- * :data:`gpu.GPU_DYNAMIC_LAMP_DYNVEC`
- * :data:`gpu.GPU_DYNAMIC_LAMP_DYNCO`
- * :data:`gpu.GPU_DYNAMIC_LAMP_DYNIMAT`
- * :data:`gpu.GPU_DYNAMIC_LAMP_DYNPERSMAT`
- * :data:`gpu.GPU_DYNAMIC_LAMP_DYNENERGY`
- * :data:`gpu.GPU_DYNAMIC_LAMP_DYNCOL`
- * :data:`gpu.GPU_DYNAMIC_SAMPLER_2DSHADOW`
+ - :data:`gpu.GPU_DYNAMIC_LAMP_DYNVEC`
+ - :data:`gpu.GPU_DYNAMIC_LAMP_DYNCO`
+ - :data:`gpu.GPU_DYNAMIC_LAMP_DYNIMAT`
+ - :data:`gpu.GPU_DYNAMIC_LAMP_DYNPERSMAT`
+ - :data:`gpu.GPU_DYNAMIC_LAMP_DYNENERGY`
+ - :data:`gpu.GPU_DYNAMIC_LAMP_DYNCOL`
+ - :data:`gpu.GPU_DYNAMIC_SAMPLER_2DSHADOW`
Notes:
- * The uniforms :data:`gpu.GPU_DYNAMIC_LAMP_DYNVEC`, :data:`gpu.GPU_DYNAMIC_LAMP_DYNCO`, :data:`gpu.GPU_DYNAMIC_LAMP_DYNIMAT` and :data:`gpu.GPU_DYNAMIC_LAMP_DYNPERSMAT`
- refer to the lamp object position and orientation, both of can be derived from the object world matrix:
+ - The uniforms
+ :data:`gpu.GPU_DYNAMIC_LAMP_DYNVEC`,
+ :data:`gpu.GPU_DYNAMIC_LAMP_DYNCO`,
+ :data:`gpu.GPU_DYNAMIC_LAMP_DYNIMAT` and
+ :data:`gpu.GPU_DYNAMIC_LAMP_DYNPERSMAT`
+ refer to the lamp object position and orientation,
+ both of can be derived from the object world matrix:
.. code-block:: python
obmat = uniform["lamp"].matrix_world
where obmat is the mat4_lamp_to_world_ matrix of the lamp as a 2 dimensional array,
- the lamp world location location is in obmat[3].
+ the lamp world location location is in ``obmat[3]``.
- * The uniform types :data:`gpu.GPU_DYNAMIC_LAMP_DYNENERGY` and :data:`gpu.GPU_DYNAMIC_LAMP_DYNCOL` refer to the lamp data bloc that you get from:
+ - The uniform types
+ :data:`gpu.GPU_DYNAMIC_LAMP_DYNENERGY` and
+ :data:`gpu.GPU_DYNAMIC_LAMP_DYNCOL`
+ refer to the lamp data bloc that you get from:
.. code-block:: python
la = uniform["lamp"].data
- from which you get la.energy and la.color
+ from which you get ``lamp.energy`` and ``lamp.color``
- * Lamp duplication is not supported: if you have duplicated lamps in your scene
+ - Lamp duplication is not supported: if you have duplicated lamps in your scene
(i.e. lamp that are instantiated by dupligroup, etc), this element will only
give you a reference to the orignal lamp and you will not know which instance
of the lamp it is refering too. You can still handle that case in the exporter
by distributing the uniforms amongst the duplicated lamps.
- * ["image"] : :class:`bpy.types.Image`
- Reference to the image databloc. Set for uniform type :data:`gpu.GPU_DYNAMIC_SAMPLER_2DIMAGE`. You can get the image data from:
+ - ``["image"]``: :class:`bpy.types.Image`
+ Reference to the image databloc.
+ Set for uniform type
+ :data:`gpu.GPU_DYNAMIC_SAMPLER_2DIMAGE`.
+ You can get the image data from:
.. code-block:: python
@@ -432,60 +575,63 @@ Functions
# image size as a 2-dimensional array of int
uniform["image"].size
- * ["texnumber"] : integer
+ - ``["texnumber"]``: integer
Channel number to which the texture is bound when drawing the object.
- Set for uniform types :data:`gpu.GPU_DYNAMIC_SAMPLER_2DBUFFER`, :data:`gpu.GPU_DYNAMIC_SAMPLER_2DIMAGE` and :data:`gpu.GPU_DYNAMIC_SAMPLER_2DSHADOW`.
+ Set for uniform types
+ :data:`gpu.GPU_DYNAMIC_SAMPLER_2DBUFFER`,
+ :data:`gpu.GPU_DYNAMIC_SAMPLER_2DIMAGE` and
+ :data:`gpu.GPU_DYNAMIC_SAMPLER_2DSHADOW`.
This is provided for information only: when reusing the shader outside blencer,
you are free to assign the textures to the channel of your choice and to pass
that number channel to the GPU in the uniform.
- * ["texpixels"] : byte array
- texture data for uniform type :data:`gpu.GPU_DYNAMIC_SAMPLER_2DBUFFER`. Although
- the corresponding uniform is a 2D sampler, the texture is always a 1D texture
- of n x 1 pixel. The texture size n is provided in ["texsize"] element.
+ - ``["texpixels"]``: byte array
+ texture data for uniform type :data:`gpu.GPU_DYNAMIC_SAMPLER_2DBUFFER`.
+ Although the corresponding uniform is a 2D sampler,
+ the texture is always a 1D texture of n x 1 pixel.
+ The texture size n is provided in ["texsize"] element.
These texture are only used for computer generated texture (colorband, etc).
- The texture data is provided so that you can make a real image out of it in the
- exporter.
+ The texture data is provided so that you can make a real image out of it in the exporter.
- * ["texsize"] : integer
+ - ``["texsize"]``: integer
horizontal size of texture for uniform type :data:`gpu.GPU_DYNAMIC_SAMPLER_2DBUFFER`.
The texture data is in ["texpixels"].
- * ["attributes"] : sequence
+ - ``["attributes"]``: sequence
list of attributes used in vertex shader, can be empty. Blender doesn't use
standard attributes except for vertex position and normal. All other vertex
- attributes must be passed using the generic glVertexAttrib functions.
+ attributes must be passed using the generic ``glVertexAttrib`` functions.
The attribute data can be found in the derived mesh custom data using RNA.
Each element of the sequence is a dictionary containing the following elements:
- * ["varname"] : string
+ - ``["varname"]``: string
name of the uniform in the vertex shader. Always of the form 'att<number>'.
- * ["datatype"] : integer
+ - ``["datatype"]``: integer
data type of vertex attribute, can be one of the following:
- * :data:`gpu.GPU_DATA_2F` : use glVertexAttrib2fv
- * :data:`gpu.GPU_DATA_3F` : use glVertexAttrib3fv
- * :data:`gpu.GPU_DATA_4F` : use glVertexAttrib4fv
- * :data:`gpu.GPU_DATA_4UB` : use glVertexAttrib4ubv
+ - :data:`gpu.GPU_DATA_2F`: use ``glVertexAttrib2fv``
+ - :data:`gpu.GPU_DATA_3F`: use ``glVertexAttrib3fv``
+ - :data:`gpu.GPU_DATA_4F`: use ``glVertexAttrib4fv``
+ - :data:`gpu.GPU_DATA_4UB`: use ``glVertexAttrib4ubv``
- * ["number"] : integer
- generic attribute number. This is provided for information only. Blender
- doesn't use glBindAttribLocation to place generic attributes at specific location,
+ - ``["number"]``: integer
+ Generic attribute number. This is provided for information only.
+ Blender doesn't use ``glBindAttribLocation`` to place generic attributes at specific location,
it lets the shader compiler place the attributes automatically and query the
- placement with glGetAttribLocation. The result of this placement is returned in
- this element.
+ placement with ``glGetAttribLocation``.
+ The result of this placement is returned in this element.
When using this shader in a render engine, you should either use
- glBindAttribLocation to force the attribute at this location or use
- glGetAttribLocation to get the placement chosen by the compiler of your GPU.
+ ``glBindAttribLocation`` to force the attribute at this location or use
+ ``glGetAttribLocation`` to get the placement chosen by the compiler of your GPU.
- * ["type"] : integer
+ - ``["type"]``: integer
type of the mesh custom data from which the vertex attribute is loaded.
See attribute-type_.
- * ["name"] : string or integer
+ - ``["name"]``: string or integer
custom data layer name, used for attribute type :data:`gpu.CD_MTFACE` and :data:`gpu.CD_MCOL`.
Example:
@@ -512,14 +658,14 @@ Notes
.. _mat4_lamp_to_perspective:
-1. Calculation of the *mat4_lamp_to_perspective* matrix for a spot lamp.
+#. Calculation of the ``mat4_lamp_to_perspective`` matrix for a spot lamp.
- The following pseudo code shows how the *mat4_lamp_to_perspective* matrix is computed
+ The following pseudo code shows how the ``mat4_lamp_to_perspective`` matrix is computed
in blender for uniforms of :data:`gpu.GPU_DYNAMIC_LAMP_DYNPERSMAT` type:
.. code-block:: python
- #Get the lamp datablock with:
+ # Get the lamp datablock with:
lamp = bpy.data.objects[uniform["lamp"]].data
# Compute the projection matrix:
@@ -531,11 +677,11 @@ Notes
# The size of the projection plane is computed with the usual formula:
wsize = lamp.clista * tan(lamp.spotsize/2)
- #And the projection matrix:
+ # And the projection matrix:
mat4_lamp_to_perspective = glFrustum(-wsize, wsize, -wsize, wsize, lamp.clista, lamp.clipend)
-2. Creation of the shadow map for a spot lamp.
+#. Creation of the shadow map for a spot lamp.
The shadow map is the depth buffer of a render performed by placing the camera at the
- spot light position. The size of the shadow map is given by the attribute lamp.bufsize :
+ spot light position. The size of the shadow map is given by the attribute ``lamp.bufsize``:
shadow map size in pixel, same size in both dimensions.
diff --git a/doc/python_api/rst/info_api_reference.rst b/doc/python_api/rst/info_api_reference.rst
index ddee46dce11..43469fc0cb7 100644
--- a/doc/python_api/rst/info_api_reference.rst
+++ b/doc/python_api/rst/info_api_reference.rst
@@ -121,7 +121,7 @@ Here are some more complex examples:
bpy.context.scene.render.layers["RenderLayer"].samples
# access to the current weight paint brush size
- bpy.context.tool_settings.weight_paint.brush.size
+ bpy.context.tool_settings.weight_paint.brush.size
# check if the window is fullscreen
bpy.context.window.screen.show_fullscreen
@@ -141,15 +141,16 @@ When starting out scripting you will often run into the problem where you're not
There are a few ways to do this.
-- Use the Python console's auto-complete to inspect properties. *This can be hit-and-miss but has the advantage
+- Use the Python console's auto-complete to inspect properties.
+ *This can be hit-and-miss but has the advantage
that you can easily see the values of properties and assign them to interactively see the results.*
+- Copy the Data-Path from the user interface.
+ *Explained further in :ref:`Copy Data Path <info_data_path_copy>`*
+- Using the documentation to follow references.
+ *Explained further in :ref:`Indirect Data Access <info_data_path_indirect>`*
-- Copy the Data-Path from the user interface. *Explained further in :ref:`Copy Data Path <info_data_path_copy>`*
-- Using the documentation to follow references. *Explained further in :ref:`Indirect Data Access <info_data_path_indirect>`*
-
-
-.. _info_data_path_copy
+.. _info_data_path_copy:
Copy Data Path
--------------
@@ -172,7 +173,8 @@ you won't be doing collection look-ups on every access and typically you'll want
then access each :class:`bpy.types.ID` instance by name.
-Type in the ID path into a Python console :mod:`bpy.context.active_object`. Include the trailing dot and don't hit "enter", yet.
+Type in the ID path into a Python console :mod:`bpy.context.active_object`.
+Include the trailing dot and don't hit "enter", yet.
Now right-click on the button and select **Copy Data Path**, then paste the result into the console.
@@ -191,7 +193,7 @@ Hit "enter" and you'll get the current value of 1. Now try changing the value to
You can see the value update in the Subdivision-Surface modifier's UI as well as the cube.
-.. _info_data_path_indirect
+.. _info_data_path_indirect:
Indirect Data Access
--------------------
@@ -201,32 +203,24 @@ For this example we'll go over something more involved, showing the steps to acc
Lets say we want to access the texture of a brush via Python, to adjust its ``contrast`` for example.
- Start in the default scene and enable 'Sculpt' mode from the 3D-View header.
-
- From the toolbar expand the **Texture** panel and add a new texture.
-
*Notice the texture button its self doesn't have very useful links (you can check the tool-tips).*
-
- The contrast setting isn't exposed in the sculpt toolbar, so view the texture in the properties panel...
- In the properties button select the Texture context.
-
- Select the Brush icon to show the brush texture.
-
- - Expand the **Colors** panel to locate the **Contrast** button.
-
-- Right click on the contrast button and select **Online Python Reference** This takes you to ``bpy.types.Texture.contrast``
-
-- Now we can see that ``contrast`` is a property of texture, so next we'll check on how to access the texture from the brush.
-
+ - Expand the *Colors* panel to locate the *Contrast* button.
+- Right click on the contrast button and select **Online Python Reference**
+ This takes you to ``bpy.types.Texture.contrast``
+- Now we can see that ``contrast`` is a property of texture,
+ so next we'll check on how to access the texture from the brush.
- Check on the **References** at the bottom of the page, sometimes there are many references, and it may take
some guess work to find the right one, but in this case its obviously ``Brush.texture``.
*Now we know that the texture can be accessed from* ``bpy.data.brushes["BrushName"].texture``
*but normally you won't want to access the brush by name, so we'll see now to access the active brush instead.*
-
- So the next step is to check on where brushes are accessed from via the **References**.
In this case there is simply ``bpy.context.brush`` which is all we need.
-
Now you can use the Python console to form the nested properties needed to access brush textures contrast,
logically we now know.
@@ -282,7 +276,8 @@ are interested to check on the source code.
.. note::
- Not all operators can be called usefully from Python, for more on this see :ref:`using operators <using_operators>`.
+ Not all operators can be called usefully from Python,
+ for more on this see :ref:`using operators <using_operators>`.
Info View
@@ -294,7 +289,8 @@ This is located above the file-menu which can be dragged down to display its con
Select the **Script** screen that comes default with Blender to see its output.
You can perform some actions and see them show up - delete a vertex for example.
-Each entry can be selected (Right-Mouse-Button), then copied :kbd:`Control-C`, usually to paste in the text editor or python console.
+Each entry can be selected (Right-Mouse-Button),
+then copied :kbd:`Control-C`, usually to paste in the text editor or python console.
.. note::
diff --git a/doc/python_api/rst/info_best_practice.rst b/doc/python_api/rst/info_best_practice.rst
index 1e12daba893..8c5ae3398bc 100644
--- a/doc/python_api/rst/info_best_practice.rst
+++ b/doc/python_api/rst/info_best_practice.rst
@@ -1,16 +1,20 @@
+
*************
Best Practice
*************
-When writing your own scripts python is great for new developers to pick up and become productive, but you can also pick up odd habits or at least write scripts that are not easy for others to understand.
+When writing your own scripts python is great for new developers to pick up and become productive,
+but you can also pick up odd habits or at least write scripts that are not easy for others to understand.
-For your own work this is of course fine, but if you want to collaborate with others or have your work included with blender there are practices we encourage.
+For your own work this is of course fine,
+but if you want to collaborate with others or have your work included with blender there are practices we encourage.
Style Conventions
=================
-For Blender/Python development we have chosen to follow python suggested style guide to avoid mixing styles amongst our own scripts and make it easier to use python scripts from other projects.
+For Blender/Python development we have chosen to follow python suggested style guide to avoid mixing styles
+amongst our own scripts and make it easier to use python scripts from other projects.
Using our style guide for your own scripts makes it easier if you eventually want to contribute them to blender.
@@ -18,22 +22,17 @@ This style guide is known as pep8 and can be found `here <http://www.python.org/
A brief listing of pep8 criteria.
-* camel caps for class names: MyClass
-
-* all lower case underscore separated module names: my_module
-
-* indentation of 4 spaces (no tabs)
-
-* spaces around operators. ``1 + 1``, not ``1+1``
-
-* only use explicit imports, (no importing '*')
-
-* don't use single line: ``if val: body``, separate onto 2 lines instead.
+- camel caps for class names: MyClass
+- all lower case underscore separated module names: my_module
+- indentation of 4 spaces (no tabs)
+- spaces around operators. ``1 + 1``, not ``1+1``
+- only use explicit imports, (no importing ``*``)
+- don't use single line: ``if val: body``, separate onto 2 lines instead.
As well as pep8 we have other conventions used for blender python scripts.
-* Use single quotes for enums, and double quotes for strings.
+- Use single quotes for enums, and double quotes for strings.
Both are of course strings but in our internal API enums are unique items from a limited set. eg.
@@ -42,9 +41,11 @@ As well as pep8 we have other conventions used for blender python scripts.
bpy.context.scene.render.image_settings.file_format = 'PNG'
bpy.context.scene.render.filepath = "//render_out"
-* pep8 also defines that lines should not exceed 79 characters, we felt this is too restrictive so this is optional per script.
+- pep8 also defines that lines should not exceed 79 characters,
+ we felt this is too restrictive so this is optional per script.
-Periodically we run checks for pep8 compliance on blender scripts, for scripts to be included in this check add this line as a comment at the top of the script.
+Periodically we run checks for pep8 compliance on blender scripts,
+for scripts to be included in this check add this line as a comment at the top of the script.
``# <pep8 compliant>``
@@ -58,72 +59,75 @@ User Interface Layout
Some notes to keep in mind when writing UI layouts:
-* UI code is quite simple. Layout declarations are there to easily create a decent layout.
+- UI code is quite simple. Layout declarations are there to easily create a decent layout.
+
+ General rule here: If you need more code for the layout declaration,
+ then for the actual properties, you do it wrong.
- General rule here: If you need more code for the layout declaration, then for the actual properties, you do it wrong.
-
Example layouts:
-* layout()
+- layout()
+
+ The basic layout is a simple Top -> Bottom layout.
- The basic layout is a simple Top -> Bottom layout.
-
.. code-block:: python
- layout.prop()
- layout.prop()
+ layout.prop()
+ layout.prop()
+
+- layout.row()
-* layout.row()
+ Use row(), when you want more than 1 property in one line.
- Use row(), when you want more than 1 property in one line.
-
.. code-block:: python
-
- row = layout.row()
- row.prop()
- row.prop()
-* layout.column()
+ row = layout.row()
+ row.prop()
+ row.prop()
+
+- layout.column()
Use column(), when you want your properties in a column.
-
+
.. code-block:: python
-
- col = layout.column()
- col.prop()
- col.prop()
-* layout.split()
+ col = layout.column()
+ col.prop()
+ col.prop()
- This can be used to create more complex layouts. For example you can split the layout and create two column() layouts next to each other.
+- layout.split()
+
+ This can be used to create more complex layouts.
+ For example you can split the layout and create two column() layouts next to each other.
Don't use split, when you simply want two properties in a row. Use row() for that.
-
+
.. code-block:: python
-
- split = layout.split()
-
- col = split.column()
- col.prop()
- col.prop()
-
- col = split.column()
- col.prop()
- col.prop()
-
+
+ split = layout.split()
+
+ col = split.column()
+ col.prop()
+ col.prop()
+
+ col = split.column()
+ col.prop()
+ col.prop()
+
Declaration names:
Try to only use these variable names for layout declarations:
-* row for a row() layout
-* col for a column() layout
-* split for a split() layout
-* flow for a column_flow() layout
-* sub for a sub layout (a column inside a column for example)
+- row for a row() layout
+- col for a column() layout
+- split for a split() layout
+- flow for a column_flow() layout
+- sub for a sub layout (a column inside a column for example)
Script Efficiency
=================
+
List Manipulation (General Python Tips)
---------------------------------------
@@ -133,7 +137,8 @@ Searching for list items
In Python there are some handy list functions that save you having to search through the list.
-Even though you're not looping on the list data **python is**, so you need to be aware of functions that will slow down your script by searching the whole list.
+Even though you're not looping on the list data **python is**,
+so you need to be aware of functions that will slow down your script by searching the whole list.
.. code-block:: python
@@ -145,11 +150,16 @@ Even though you're not looping on the list data **python is**, so you need to be
Modifying Lists
^^^^^^^^^^^^^^^
-In python we can add and remove from a list, this is slower when the list length is modified, especially at the start of the list, since all the data after the index of modification needs to be moved up or down 1 place.
+In python we can add and remove from a list, this is slower when the list length is modified,
+especially at the start of the list, since all the data after the index of
+modification needs to be moved up or down 1 place.
-The most simple way to add onto the end of the list is to use ``my_list.append(list_item)`` or ``my_list.extend(some_list)`` and the fastest way to remove an item is ``my_list.pop()`` or ``del my_list[-1]``.
+The most simple way to add onto the end of the list is to use
+``my_list.append(list_item)`` or ``my_list.extend(some_list)`` and the fastest way to
+remove an item is ``my_list.pop()`` or ``del my_list[-1]``.
-To use an index you can use ``my_list.insert(index, list_item)`` or ``list.pop(index)`` for list removal, but these are slower.
+To use an index you can use ``my_list.insert(index, list_item)`` or ``list.pop(index)``
+for list removal, but these are slower.
Sometimes its faster (but more memory hungry) to just rebuild the list.
@@ -193,7 +203,8 @@ Use...
my_list.extend([a, b, c...])
-Note that insert can be used when needed, but it is slower than append especially when inserting at the start of a long list.
+Note that insert can be used when needed,
+but it is slower than append especially when inserting at the start of a long list.
This example shows a very sub-optimal way of making a reversed list.
@@ -205,7 +216,8 @@ This example shows a very sub-optimal way of making a reversed list.
reverse_list.insert(0, list_item)
-Python provides more convenient ways to reverse a list using the slice method, but you may want to time this before relying on it too much:
+Python provides more convenient ways to reverse a list using the slice method,
+but you may want to time this before relying on it too much:
.. code-block:: python
@@ -220,7 +232,8 @@ Use ``my_list.pop(index)`` rather than ``my_list.remove(list_item)``
This requires you to have the index of the list item but is faster since ``remove()`` will search the list.
-Here is an example of how to remove items in 1 loop, removing the last items first, which is faster (as explained above).
+Here is an example of how to remove items in 1 loop,
+removing the last items first, which is faster (as explained above).
.. code-block:: python
@@ -232,7 +245,9 @@ Here is an example of how to remove items in 1 loop, removing the last items fir
my_list.pop(list_index)
-This example shows a fast way of removing items, for use in cases where you can alter the list order without breaking the scripts functionality. This works by swapping 2 list items, so the item you remove is always last.
+This example shows a fast way of removing items,
+for use in cases where you can alter the list order without breaking the scripts functionality.
+This works by swapping 2 list items, so the item you remove is always last.
.. code-block:: python
@@ -251,7 +266,9 @@ When removing many items in a large list this can provide a good speedup.
Avoid Copying Lists
^^^^^^^^^^^^^^^^^^^
-When passing a list/dictionary to a function, it is faster to have the function modify the list rather than returning a new list so python doesn't have to duplicate the list in memory.
+When passing a list/dictionary to a function,
+it is faster to have the function modify the list rather than returning
+a new list so python doesn't have to duplicate the list in memory.
Functions that modify a list in-place are more efficient than functions that create new lists.
@@ -296,20 +313,26 @@ Python’s string joining function. To join a list of strings
>>> file.write(" ".join([str1, str2, str3, "\n"]))
-join is fastest on many strings, `string formatting <http://docs.python.org/py3k/library/string.html#string-formatting>`_ is quite fast too (better for converting data types). String arithmetic is slowest.
+join is fastest on many strings,
+`string formatting <http://docs.python.org/py3k/library/string.html#string-formatting>`__
+is quite fast too (better for converting data types). String arithmetic is slowest.
Parsing Strings (Import/Exporting)
----------------------------------
-Since many file formats are ASCII, the way you parse/export strings can make a large difference in how fast your script runs.
+Since many file formats are ASCII,
+the way you parse/export strings can make a large difference in how fast your script runs.
There are a few ways to parse strings when importing them into Blender.
+
Parsing Numbers
^^^^^^^^^^^^^^^
-Use ``float(string)`` rather than ``eval(string)``, if you know the value will be an int then ``int(string)``, float() will work for an int too but it's faster to read ints with int().
+Use ``float(string)`` rather than ``eval(string)``, if you know the value will be an int then ``int(string)``,
+float() will work for an int too but it's faster to read ints with int().
+
Checking String Start/End
^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -322,7 +345,8 @@ Use...
>>> if line.startswith("vert "):
-Using ``startswith()`` is slightly faster (approx 5%) and also avoids a possible error with the slice length not matching the string length.
+Using ``startswith()`` is slightly faster (approx 5%) and also avoids a possible
+error with the slice length not matching the string length.
my_string.endswith("foo_bar") can be used for line endings too.
@@ -336,15 +360,19 @@ Use try/except Sparingly
The **try** statement is useful to save time writing error checking code.
-However **try** is significantly slower than an **if** since an exception has to be set each time, so avoid using **try** in areas of your code that execute in a loop and runs many times.
+However **try** is significantly slower than an **if** since an exception has to be set each time,
+so avoid using **try** in areas of your code that execute in a loop and runs many times.
-There are cases where using **try** is faster than checking whether the condition will raise an error, so it is worth experimenting.
+There are cases where using **try** is faster than checking whether the condition will raise an error,
+so it is worth experimenting.
Value Comparison
----------------
-Python has two ways to compare values ``a == b`` and ``a is b``, the difference is that ``==`` may run the objects comparison function ``__cmp__()`` whereas ``is`` compares identity, that both variables reference the same item in memory.
+Python has two ways to compare values ``a == b`` and ``a is b``,
+the difference is that ``==`` may run the objects comparison function ``__cmp__()`` whereas ``is`` compares identity,
+that both variables reference the same item in memory.
In cases where you know you are checking for the same value which is referenced from multiple places, ``is`` is faster.
@@ -362,3 +390,4 @@ While developing a script it's good to time it to be aware of any changes in per
# do something...
print("My Script Finished: %.4f sec" % time.time() - time_start)
+
diff --git a/doc/python_api/rst/info_gotcha.rst b/doc/python_api/rst/info_gotcha.rst
index 35f9c1bda9f..430a862cf7b 100644
--- a/doc/python_api/rst/info_gotcha.rst
+++ b/doc/python_api/rst/info_gotcha.rst
@@ -2,7 +2,8 @@
Gotchas
*******
-This document attempts to help you work with the Blender API in areas that can be troublesome and avoid practices that are known to give instability.
+This document attempts to help you work with the Blender API in areas
+that can be troublesome and avoid practices that are known to give instability.
.. _using_operators:
@@ -10,16 +11,15 @@ This document attempts to help you work with the Blender API in areas that can b
Using Operators
===============
-Blender's operators are tools for users to access, that python can access them too is very useful nevertheless operators have limitations that can make them cumbersome to script.
+Blender's operators are tools for users to access, that Python can access them too is very useful
+nevertheless operators have limitations that can make them cumbersome to script.
Main limits are...
-* Can't pass data such as objects, meshes or materials to operate on (operators use the context instead)
-
-* The return value from calling an operator gives the success (if it finished or was canceled),
+- Can't pass data such as objects, meshes or materials to operate on (operators use the context instead)
+- The return value from calling an operator gives the success (if it finished or was canceled),
in some cases it would be more logical from an API perspective to return the result of the operation.
-
-* Operators poll function can fail where an API function would raise an exception giving details on exactly why.
+- Operators poll function can fail where an API function would raise an exception giving details on exactly why.
Why does an operator's poll fail?
@@ -32,20 +32,28 @@ When calling an operator gives an error like this:
Which raises the question as to what the correct context might be?
-Typically operators check for the active area type, a selection or active object they can operate on, but some operators are more picky about when they run.
+Typically operators check for the active area type, a selection or active object they can operate on,
+but some operators are more picky about when they run.
-In most cases you can figure out what context an operator needs simply be seeing how it's used in Blender and thinking about what it does.
+In most cases you can figure out what context an operator needs
+simply be seeing how it's used in Blender and thinking about what it does.
-Unfortunately if you're still stuck - the only way to **really** know whats going on is to read the source code for the poll function and see what its checking.
+Unfortunately if you're still stuck - the only way to **really** know
+whats going on is to read the source code for the poll function and see what its checking.
-For python operators it's not so hard to find the source since it's included with Blender and the source file/line is included in the operator reference docs.
+For Python operators it's not so hard to find the source
+since it's included with Blender and the source file/line is included in the operator reference docs.
-Downloading and searching the C code isn't so simple, especially if you're not familiar with the C language but by searching the operator name or description you should be able to find the poll function with no knowledge of C.
+Downloading and searching the C code isn't so simple,
+especially if you're not familiar with the C language but by searching the
+operator name or description you should be able to find the poll function with no knowledge of C.
.. note::
- Blender does have the functionality for poll functions to describe why they fail, but its currently not used much, if you're interested to help improve our API feel free to add calls to ``CTX_wm_operator_poll_msg_set`` where its not obvious why poll fails.
+ Blender does have the functionality for poll functions to describe why they fail,
+ but its currently not used much, if you're interested to help improve our API
+ feel free to add calls to ``CTX_wm_operator_poll_msg_set`` where its not obvious why poll fails.
>>> bpy.ops.gpencil.draw()
RuntimeError: Operator bpy.ops.gpencil.draw.poll() Failed to find Grease Pencil data to draw into
@@ -54,40 +62,57 @@ Downloading and searching the C code isn't so simple, especially if you're not f
The operator still doesn't work!
--------------------------------
-Certain operators in Blender are only intended for use in a specific context, some operators for example are only called from the properties window where they check the current material, modifier or constraint.
+Certain operators in Blender are only intended for use in a specific context,
+some operators for example are only called from the properties window where they check the current material,
+modifier or constraint.
Examples of this are:
-* :mod:`bpy.ops.texture.slot_move`
-* :mod:`bpy.ops.constraint.limitdistance_reset`
-* :mod:`bpy.ops.object.modifier_copy`
-* :mod:`bpy.ops.buttons.file_browse`
+- :mod:`bpy.ops.texture.slot_move`
+- :mod:`bpy.ops.constraint.limitdistance_reset`
+- :mod:`bpy.ops.object.modifier_copy`
+- :mod:`bpy.ops.buttons.file_browse`
-Another possibility is that you are the first person to attempt to use this operator in a script and some modifications need to be made to the operator to run in a different context, if the operator should logically be able to run but fails when accessed from a script it should be reported to the bug tracker.
+Another possibility is that you are the first person to attempt to use this operator
+in a script and some modifications need to be made to the operator to run in a different context,
+if the operator should logically be able to run but fails when accessed from a script
+it should be reported to the bug tracker.
Stale Data
==========
+
No updates after setting values
-------------------------------
-Sometimes you want to modify values from python and immediately access the updated values, eg:
+Sometimes you want to modify values from Python and immediately access the updated values, eg:
-Once changing the objects :class:`bpy.types.Object.location` you may want to access its transformation right after from :class:`bpy.types.Object.matrix_world`, but this doesn't work as you might expect.
+Once changing the objects :class:`bpy.types.Object.location`
+you may want to access its transformation right after from :class:`bpy.types.Object.matrix_world`,
+but this doesn't work as you might expect.
Consider the calculations that might go into working out the object's final transformation, this includes:
-* animation function curves.
-* drivers and their pythons expressions.
-* constraints
-* parent objects and all of their f-curves, constraints etc.
+- animation function curves.
+- drivers and their Python expressions.
+- constraints
+- parent objects and all of their f-curves, constraints etc.
-To avoid expensive recalculations every time a property is modified, Blender defers making the actual calculations until they are needed.
+To avoid expensive recalculations every time a property is modified,
+Blender defers making the actual calculations until they are needed.
However, while the script runs you may want to access the updated values.
+In this case you need to call :class:`bpy.types.Scene.update` after modifying values, for example:
+
+.. code-block:: python
-This can be done by calling :class:`bpy.types.Scene.update` after modifying values which recalculates all data that is tagged to be updated.
+ bpy.context.object.location = 1, 2, 3
+ bpy.context.scene.update()
+
+
+Now all dependent data (child objects, modifiers, drivers... etc)
+has been recalculated and is available to the script.
Can I redraw during the script?
@@ -97,23 +122,33 @@ The official answer to this is no, or... *"You don't want to do that"*.
To give some background on the topic...
-While a script executes Blender waits for it to finish and is effectively locked until its done, while in this state Blender won't redraw or respond to user input.
-Normally this is not such a problem because scripts distributed with Blender tend not to run for an extended period of time, nevertheless scripts *can* take ages to execute and its nice to see whats going on in the view port.
+While a script executes Blender waits for it to finish and is effectively locked until its done,
+while in this state Blender won't redraw or respond to user input.
+Normally this is not such a problem because scripts distributed with Blender
+tend not to run for an extended period of time,
+nevertheless scripts *can* take ages to execute and its nice to see whats going on in the view port.
-Tools that lock Blender in a loop and redraw are highly discouraged since they conflict with Blenders ability to run multiple operators at once and update different parts of the interface as the tool runs.
+Tools that lock Blender in a loop and redraw are highly discouraged
+since they conflict with Blenders ability to run multiple operators
+at once and update different parts of the interface as the tool runs.
-So the solution here is to write a **modal** operator, that is - an operator which defines a modal() function, See the modal operator template in the text editor.
+So the solution here is to write a **modal** operator, that is - an operator which defines a modal() function,
+See the modal operator template in the text editor.
-Modal operators execute on user input or setup their own timers to run frequently, they can handle the events or pass through to be handled by the keymap or other modal operators.
+Modal operators execute on user input or setup their own timers to run frequently,
+they can handle the events or pass through to be handled by the keymap or other modal operators.
Transform, Painting, Fly-Mode and File-Select are example of a modal operators.
-Writing modal operators takes more effort than a simple ``for`` loop that happens to redraw but is more flexible and integrates better with Blenders design.
+Writing modal operators takes more effort than a simple ``for`` loop
+that happens to redraw but is more flexible and integrates better with Blenders design.
-**Ok, Ok! I still want to draw from python**
+**Ok, Ok! I still want to draw from Python**
-If you insist - yes its possible, but scripts that use this hack wont be considered for inclusion in Blender and any issues with using it wont be considered bugs, this is also not guaranteed to work in future releases.
+If you insist - yes its possible, but scripts that use this hack wont be considered
+for inclusion in Blender and any issues with using it wont be considered bugs,
+this is also not guaranteed to work in future releases.
.. code-block:: python
@@ -123,16 +158,18 @@ If you insist - yes its possible, but scripts that use this hack wont be conside
Modes and Mesh Access
=====================
-When working with mesh data you may run into the problem where a script fails to run as expected in edit-mode. This is caused by edit-mode having its own data which is only written back to the mesh when exiting edit-mode.
+When working with mesh data you may run into the problem where a script fails to run as expected in edit-mode.
+This is caused by edit-mode having its own data which is only written back to the mesh when exiting edit-mode.
-A common example is that exporters may access a mesh through ``obj.data`` (a :class:`bpy.types.Mesh`) but the user is in edit-mode, where the mesh data is available but out of sync with the edit mesh.
+A common example is that exporters may access a mesh through ``obj.data`` (a :class:`bpy.types.Mesh`)
+but the user is in edit-mode, where the mesh data is available but out of sync with the edit mesh.
In this situation you can...
-* Exit edit-mode before running the tool.
-* Explicitly update the mesh by calling :class:`bmesh.types.BMesh.to_mesh`.
-* Modify the script to support working on the edit-mode data directly, see: :mod:`bmesh.from_edit_mesh`.
-* Report the context as incorrect and only allow the script to run outside edit-mode.
+- Exit edit-mode before running the tool.
+- Explicitly update the mesh by calling :class:`bmesh.types.BMesh.to_mesh`.
+- Modify the script to support working on the edit-mode data directly, see: :mod:`bmesh.from_edit_mesh`.
+- Report the context as incorrect and only allow the script to run outside edit-mode.
.. _info_gotcha_mesh_faces:
@@ -140,35 +177,55 @@ In this situation you can...
NGons and Tessellation Faces
============================
-Since 2.63 NGons are supported, this adds some complexity since in some cases you need to access triangles/quads still (some exporters for example).
+Since 2.63 NGons are supported, this adds some complexity
+since in some cases you need to access triangles/quads still (some exporters for example).
There are now 3 ways to access faces:
-* :class:`bpy.types.MeshPolygon` - this is the data structure which now stores faces in object mode (access as ``mesh.polygons`` rather then ``mesh.faces``).
-* :class:`bpy.types.MeshTessFace` - the result of triangulating (tessellated) polygons, the main method of face access in 2.62 or older (access as ``mesh.tessfaces``).
-* :class:`bmesh.types.BMFace` - the polygons as used in editmode.
+- :class:`bpy.types.MeshPolygon` -
+ this is the data structure which now stores faces in object mode
+ (access as ``mesh.polygons`` rather than ``mesh.faces``).
+- :class:`bpy.types.MeshTessFace` -
+ the result of triangulating (tessellated) polygons,
+ the main method of face access in 2.62 or older (access as ``mesh.tessfaces``).
+- :class:`bmesh.types.BMFace` -
+ the polygons as used in editmode.
-For the purpose of the following documentation, these will be referred to as polygons, tessfaces and bmesh-faces respectively.
+For the purpose of the following documentation,
+these will be referred to as polygons, tessfaces and bmesh-faces respectively.
5+ sided faces will be referred to as ``ngons``.
+
Support Overview
----------------
-+--------------+------------------------------+--------------------------------+--------------------------------+
-|Usage |:class:`bpy.types.MeshPolygon`|:class:`bpy.types.MeshTessFace` |:class:`bmesh.types.BMFace` |
-+==============+==============================+================================+================================+
-|Import/Create |Bad (inflexible) |Fine (supported as upgrade path)|Best |
-+--------------+------------------------------+--------------------------------+--------------------------------+
-|Manipulate |Bad (inflexible) |Bad (loses ngons) |Best |
-+--------------+------------------------------+--------------------------------+--------------------------------+
-|Export/Output |Good (ngons) |Good (When ngons can't be used) |Good (ngons, memory overhead) |
-+--------------+------------------------------+--------------------------------+--------------------------------+
-
+.. list-table::
+ :header-rows: 1
+ :stub-columns: 1
+
+ * - Usage
+ - :class:`bpy.types.MeshPolygon`
+ - :class:`bpy.types.MeshTessFace`
+ - :class:`bmesh.types.BMFace`
+ * - Import/Create
+ - Poor *(inflexible)*
+ - Good *(supported as upgrade path)*
+ - Best
+ * - Manipulate
+ - Poor *(inflexible)*
+ - Poor *(loses ngons)*
+ - Best
+ * - Export/Output
+ - Good *(ngon support)*
+ - Good *(When ngons can't be used)*
+ - Good *(ngons, extra memory overhead)*
.. note::
- Using the :mod:`bmesh` api is completely separate api from :mod:`bpy`, typically you would would use one or the other based on the level of editing needed, not simply for a different way to access faces.
+ Using the :mod:`bmesh` api is completely separate api from :mod:`bpy`,
+ typically you would would use one or the other based on the level of editing needed,
+ not simply for a different way to access faces.
Creating
@@ -176,9 +233,18 @@ Creating
All 3 datatypes can be used for face creation.
-* polygons are the most efficient way to create faces but the data structure is _very_ rigid and inflexible, you must have all your vertes and faces ready and create them all at once. This is further complicated by the fact that each polygon does not store its own verts (as with tessfaces), rather they reference an index and size in :class:`bpy.types.Mesh.loops` which are a fixed array too.
-* tessfaces ideally should not be used for creating faces since they are really only tessellation cache of polygons, however for scripts upgrading from 2.62 this is by far the most straightforward option. This works by creating tessfaces and when finished - they can be converted into polygons by calling :class:`bpy.types.Mesh.update`. The obvious limitation is ngons can't be created this way.
-* bmesh-faces are most likely the easiest way for new scripts to create faces, since faces can be added one by one and the api has features intended for mesh manipulation. While :class:`bmesh.types.BMesh` uses more memory it can be managed by only operating on one mesh at a time.
+- polygons are the most efficient way to create faces but the data structure is _very_ rigid and inflexible,
+ you must have all your vertes and faces ready and create them all at once.
+ This is further complicated by the fact that each polygon does not store its own verts (as with tessfaces),
+ rather they reference an index and size in :class:`bpy.types.Mesh.loops` which are a fixed array too.
+- tessfaces ideally should not be used for creating faces since they are really only tessellation cache of polygons,
+ however for scripts upgrading from 2.62 this is by far the most straightforward option.
+ This works by creating tessfaces and when finished -
+ they can be converted into polygons by calling :class:`bpy.types.Mesh.update`.
+ The obvious limitation is ngons can't be created this way.
+- bmesh-faces are most likely the easiest way for new scripts to create faces,
+ since faces can be added one by one and the api has features intended for mesh manipulation.
+ While :class:`bmesh.types.BMesh` uses more memory it can be managed by only operating on one mesh at a time.
Editing
@@ -186,18 +252,24 @@ Editing
Editing is where the 3 data types vary most.
-* polygons are very limited for editing, changing materials and options like smooth works but for anything else they are too inflexible and are only intended for storage.
-* tessfaces should not be used for editing geometry because doing so will cause existing ngons to be tessellated.
-* bmesh-faces are by far the best way to manipulate geometry.
+- Polygons are very limited for editing,
+ changing materials and options like smooth works but for anything else
+ they are too inflexible and are only intended for storage.
+- Tessfaces should not be used for editing geometry because doing so will cause existing ngons to be tessellated.
+- BMesh-Faces are by far the best way to manipulate geometry.
+
Exporting
---------
-All 3 data types can be used for exporting, the choice mostly depends on whether the target format supports ngons or not.
+All 3 data types can be used for exporting,
+the choice mostly depends on whether the target format supports ngons or not.
-* polygons are the most direct & efficient way to export providing they convert into the output format easily enough.
-* tessfaces work well for exporting to formats which dont support ngons, in fact this is the only place where their use is encouraged.
-* bmesh-faces can work for exporting too but may not be necessary if polygons can be used since using bmesh gives some overhead because its not the native storage format in object mode.
+- Polygons are the most direct & efficient way to export providing they convert into the output format easily enough.
+- Tessfaces work well for exporting to formats which dont support ngons,
+ in fact this is the only place where their use is encouraged.
+- BMesh-Faces can work for exporting too but may not be necessary if polygons can be used
+ since using bmesh gives some overhead because its not the native storage format in object mode.
Upgrading Importers from 2.62
@@ -207,9 +279,9 @@ Importers can be upgraded to work with only minor changes.
The main change to be made is used the tessellation versions of each attribute.
-* mesh.faces --> :class:`bpy.types.Mesh.tessfaces`
-* mesh.uv_textures --> :class:`bpy.types.Mesh.tessface_uv_textures`
-* mesh.vertex_colors --> :class:`bpy.types.Mesh.tessface_vertex_colors`
+- mesh.faces --> :class:`bpy.types.Mesh.tessfaces`
+- mesh.uv_textures --> :class:`bpy.types.Mesh.tessface_uv_textures`
+- mesh.vertex_colors --> :class:`bpy.types.Mesh.tessface_vertex_colors`
Once the data is created call :class:`bpy.types.Mesh.update` to convert the tessfaces into polygons.
@@ -217,7 +289,9 @@ Once the data is created call :class:`bpy.types.Mesh.update` to convert the tess
Upgrading Exporters from 2.62
-----------------------------
-For exporters the most direct way to upgrade is to use tessfaces as with importing however its important to know that tessfaces may **not** exist for a mesh, the array will be empty as if there are no faces.
+For exporters the most direct way to upgrade is to use tessfaces as with importing
+however its important to know that tessfaces may **not** exist for a mesh,
+the array will be empty as if there are no faces.
So before accessing tessface data call: :class:`bpy.types.Mesh.update` ``(calc_tessface=True)``.
@@ -225,7 +299,8 @@ So before accessing tessface data call: :class:`bpy.types.Mesh.update` ``(calc_t
EditBones, PoseBones, Bone... Bones
===================================
-Armature Bones in Blender have three distinct data structures that contain them. If you are accessing the bones through one of them, you may not have access to the properties you really need.
+Armature Bones in Blender have three distinct data structures that contain them.
+If you are accessing the bones through one of them, you may not have access to the properties you really need.
.. note::
@@ -235,7 +310,9 @@ Armature Bones in Blender have three distinct data structures that contain them.
Edit Bones
----------
-``bpy.context.object.data.edit_bones`` contains a editbones; to access them you must set the armature mode to edit mode first (editbones do not exist in object or pose mode). Use these to create new bones, set their head/tail or roll, change their parenting relationships to other bones, etc.
+``bpy.context.object.data.edit_bones`` contains a editbones;
+to access them you must set the armature mode to edit mode first (editbones do not exist in object or pose mode).
+Use these to create new bones, set their head/tail or roll, change their parenting relationships to other bones, etc.
Example using :class:`bpy.types.EditBone` in armature editmode:
@@ -255,7 +332,9 @@ Returns an editbone only in edit mode.
Bones (Object Mode)
-------------------
-``bpy.context.object.data.bones`` contains bones. These *live* in object mode, and have various properties you can change, note that the head and tail properties are read-only.
+``bpy.context.object.data.bones`` contains bones.
+These *live* in object mode, and have various properties you can change,
+note that the head and tail properties are read-only.
Example using :class:`bpy.types.Bone` in object or pose mode:
@@ -275,7 +354,9 @@ Accessible but read-only
Pose Bones
----------
-``bpy.context.object.pose.bones`` contains pose bones. This is where animation data resides, i.e. animatable transformations are applied to pose bones, as are constraints and ik-settings.
+``bpy.context.object.pose.bones`` contains pose bones.
+This is where animation data resides, i.e. animatable transformations
+are applied to pose bones, as are constraints and ik-settings.
Examples using :class:`bpy.types.PoseBone` in object or pose mode:
@@ -290,19 +371,27 @@ Examples using :class:`bpy.types.PoseBone` in object or pose mode:
.. note::
- Notice the pose is accessed from the object rather than the object data, this is why blender can have 2 or more objects sharing the same armature in different poses.
+ Notice the pose is accessed from the object rather than the object data,
+ this is why blender can have 2 or more objects sharing the same armature in different poses.
.. note::
- Strictly speaking PoseBone's are not bones, they are just the state of the armature, stored in the :class:`bpy.types.Object` rather than the :class:`bpy.types.Armature`, the real bones are however accessible from the pose bones - :class:`bpy.types.PoseBone.bone`
+ Strictly speaking PoseBone's are not bones, they are just the state of the armature,
+ stored in the :class:`bpy.types.Object` rather than the :class:`bpy.types.Armature`,
+ the real bones are however accessible from the pose bones - :class:`bpy.types.PoseBone.bone`
Armature Mode Switching
-----------------------
-While writing scripts that deal with armatures you may find you have to switch between modes, when doing so take care when switching out of editmode not to keep references to the edit-bones or their head/tail vectors. Further access to these will crash blender so its important the script clearly separates sections of the code which operate in different modes.
+While writing scripts that deal with armatures you may find you have to switch between modes,
+when doing so take care when switching out of edit-mode not to keep references
+to the edit-bones or their head/tail vectors.
+Further access to these will crash blender so its important the script
+clearly separates sections of the code which operate in different modes.
-This is mainly an issue with editmode since pose data can be manipulated without having to be in pose mode, however for operator access you may still need to enter pose mode.
+This is mainly an issue with editmode since pose data can be manipulated without having to be in pose mode,
+however for operator access you may still need to enter pose mode.
Data Names
@@ -337,10 +426,13 @@ Or with name assignment...
Data names may not match the assigned values if they exceed the maximum length, are already used or an empty string.
-Its better practice not to reference objects by names at all, once created you can store the data in a list, dictionary, on a class etc, there is rarely a reason to have to keep searching for the same data by name.
-
+Its better practice not to reference objects by names at all,
+once created you can store the data in a list, dictionary, on a class etc,
+there is rarely a reason to have to keep searching for the same data by name.
-If you do need to use name references, its best to use a dictionary to maintain a mapping between the names of the imported assets and the newly created data, this way you don't run this risk of referencing existing data from the blend file, or worse modifying it.
+If you do need to use name references, its best to use a dictionary to maintain
+a mapping between the names of the imported assets and the newly created data,
+this way you don't run this risk of referencing existing data from the blend file, or worse modifying it.
.. code-block:: python
@@ -352,18 +444,22 @@ If you do need to use name references, its best to use a dictionary to maintain
# normally some code, or function calls...
- # use own dictionary rather then bpy.data
+ # use own dictionary rather than bpy.data
mesh = mesh_name_mapping[meshid]
Library Collisions
------------------
-Blender keeps data names unique - :class:`bpy.types.ID.name` so you can't name two objects, meshes, scenes etc the same thing by accident.
+Blender keeps data names unique - :class:`bpy.types.ID.name` so you can't name two objects,
+meshes, scenes etc the same thing by accident.
-However when linking in library data from another blend file naming collisions can occur, so its best to avoid referencing data by name at all.
+However when linking in library data from another blend file naming collisions can occur,
+so its best to avoid referencing data by name at all.
-This can be tricky at times and not even blender handles this correctly in some case (when selecting the modifier object for eg you can't select between multiple objects with the same name), but its still good to try avoid problems in this area.
+This can be tricky at times and not even blender handles this correctly in some case
+(when selecting the modifier object for eg you can't select between multiple objects with the same name),
+but its still good to try avoid problems in this area.
If you need to select between local and library data, there is a feature in ``bpy.data`` members to allow for this.
@@ -388,21 +484,23 @@ If you need to select between local and library data, there is a feature in ``bp
Relative File Paths
===================
-Blenders relative file paths are not compatible with standard python modules such as ``sys`` and ``os``.
+Blenders relative file paths are not compatible with standard Python modules such as ``sys`` and ``os``.
-Built in python functions don't understand blenders ``//`` prefix which denotes the blend file path.
+Built in Python functions don't understand blenders ``//`` prefix which denotes the blend file path.
A common case where you would run into this problem is when exporting a material with associated image paths.
->>> bpy.path.abspath(image.filepath)
+ >>> bpy.path.abspath(image.filepath)
-When using blender data from linked libraries there is an unfortunate complication since the path will be relative to the library rather then the open blend file. When the data block may be from an external blend file pass the library argument from the :class:`bpy.types.ID`.
+When using blender data from linked libraries there is an unfortunate complication
+since the path will be relative to the library rather than the open blend file.
+When the data block may be from an external blend file pass the library argument from the :class:`bpy.types.ID`.
->>> bpy.path.abspath(image.filepath, library=image.library)
+ >>> bpy.path.abspath(image.filepath, library=image.library)
-These returns the absolute path which can be used with native python modules.
+These returns the absolute path which can be used with native Python modules.
Unicode Problems
@@ -443,23 +541,28 @@ Here are 2 ways around filesystem encoding issues:
>>> bpy.context.object.name = filepath_utf8
-Unicode encoding/decoding is a big topic with comprehensive python documentation, to avoid getting stuck too deep in encoding problems - here are some suggestions:
-
-* Always use utf-8 encoiding or convert to utf-8 where the input is unknown.
+Unicode encoding/decoding is a big topic with comprehensive Python documentation,
+to avoid getting stuck too deep in encoding problems - here are some suggestions:
-* Avoid manipulating filepaths as strings directly, use ``os.path`` functions instead.
+- Always use utf-8 encoding or convert to utf-8 where the input is unknown.
+- Avoid manipulating filepaths as strings directly, use ``os.path`` functions instead.
+- Use ``os.fsencode()`` / ``os.fsdecode()`` instead of built in string decoding functions when operating on paths.
+- To print paths or to include them in the user interface use ``repr(path)`` first
+ or ``"%r" % path`` with string formatting.
-* Use ``os.fsencode()`` / ``os.fsdecode()`` rather then the built in string decoding functions when operating on paths.
-
-* To print paths or to include them in the user interface use ``repr(path)`` first or ``"%r" % path`` with string formatting.
+.. note::
-* **Possibly** - use bytes instead of python strings, when reading some input its less trouble to read it as binary data though you will still need to decide how to treat any strings you want to use with Blender, some importers do this.
+ Sometimes it's preferrable to avoid string encoding issues by using bytes instead of Python strings,
+ when reading some input its less trouble to read it as binary data
+ though you will still need to decide how to treat any strings you want to use with Blender,
+ some importers do this.
Strange errors using 'threading' module
=======================================
-Python threading with Blender only works properly when the threads finish up before the script does. By using ``threading.join()`` for example.
+Python threading with Blender only works properly when the threads finish up before the script does.
+By using ``threading.join()`` for example.
Heres an example of threading supported by Blender:
@@ -498,7 +601,8 @@ Heres an example of threading supported by Blender:
t.join()
-This an example of a timer which runs many times a second and moves the default cube continuously while Blender runs **(Unsupported)**.
+This an example of a timer which runs many times a second and moves
+the default cube continuously while Blender runs **(Unsupported)**.
.. code-block:: python
@@ -515,38 +619,48 @@ This an example of a timer which runs many times a second and moves the default
my_timer()
-Use cases like the one above which leave the thread running once the script finishes may seem to work for a while but end up causing random crashes or errors in Blender's own drawing code.
+Use cases like the one above which leave the thread running once the script finishes
+may seem to work for a while but end up causing random crashes or errors in Blender's own drawing code.
-So far, no work has gone into making Blender's python integration thread safe, so until its properly supported, best not make use of this.
+So far, no work has gone into making Blender's Python integration thread safe,
+so until its properly supported, best not make use of this.
.. note::
- Pythons threads only allow co-currency and won't speed up your scripts on multi-processor systems, the ``subprocess`` and ``multiprocess`` modules can be used with Blender and make use of multiple CPU's too.
+ Pythons threads only allow co-currency and won't speed up your scripts on multi-processor systems,
+ the ``subprocess`` and ``multiprocess`` modules can be used with Blender and make use of multiple CPU's too.
Help! My script crashes Blender
===============================
-Ideally it would be impossible to crash Blender from python however there are some problems with the API where it can be made to crash.
+Ideally it would be impossible to crash Blender from Python
+however there are some problems with the API where it can be made to crash.
-Strictly speaking this is a bug in the API but fixing it would mean adding memory verification on every access since most crashes are caused by the python objects referencing Blenders memory directly, whenever the memory is freed, further python access to it can crash the script. But fixing this would make the scripts run very slow, or writing a very different kind of API which doesn't reference the memory directly.
+Strictly speaking this is a bug in the API but fixing it would mean adding memory verification
+on every access since most crashes are caused by the Python objects referencing Blenders memory directly,
+whenever the memory is freed, further Python access to it can crash the script.
+But fixing this would make the scripts run very slow,
+or writing a very different kind of API which doesn't reference the memory directly.
Here are some general hints to avoid running into these problems.
-* Be aware of memory limits, especially when working with large lists since Blender can crash simply by running out of memory.
-
-* Many hard to fix crashes end up being because of referencing freed data, when removing data be sure not to hold any references to it.
-
-* Modules or classes that remain active while Blender is used, should not hold references to data the user may remove, instead, fetch data from the context each time the script is activated.
-
-* Crashes may not happen every time, they may happen more on some configurations/operating-systems.
+- Be aware of memory limits,
+ especially when working with large lists since Blender can crash simply by running out of memory.
+- Many hard to fix crashes end up being because of referencing freed data,
+ when removing data be sure not to hold any references to it.
+- Modules or classes that remain active while Blender is used,
+ should not hold references to data the user may remove, instead,
+ fetch data from the context each time the script is activated.
+- Crashes may not happen every time, they may happen more on some configurations/operating-systems.
.. note::
To find the line of your script that crashes you can use the ``faulthandler`` module.
See `faulthandler docs <http://docs.python.org/dev/library/faulthandler.html>`_.
- While the crash may be in Blenders C/C++ code, this can help a lot to track down the area of the script that causes the crash.
+ While the crash may be in Blenders C/C++ code,
+ this can help a lot to track down the area of the script that causes the crash.
Undo/Redo
@@ -566,28 +680,36 @@ This example shows how you can tell undo changes the memory locations.
>>> hash(bpy.context.object)
-9223372036849951740
-As suggested above, simply not holding references to data when Blender is used interactively by the user is the only way to ensure the script doesn't become unstable.
+As suggested above, simply not holding references to data when Blender is used
+interactively by the user is the only way to ensure the script doesn't become unstable.
Undo & Library Data
^^^^^^^^^^^^^^^^^^^
-One of the advantages with Blenders library linking system that undo can skip checking changes in library data since it is assumed to be static.
+One of the advantages with Blenders library linking system that undo
+can skip checking changes in library data since it is assumed to be static.
Tools in Blender are not allowed to modify library data.
Python however does not enforce this restriction.
This can be useful in some cases, using a script to adjust material values for example.
-But its also possible to use a script to make library data point to newly created local data, which is not supported since a call to undo will remove the local data but leave the library referencing it and likely crash.
+But its also possible to use a script to make library data point to newly created local data,
+which is not supported since a call to undo will remove the local data
+but leave the library referencing it and likely crash.
-So it's best to consider modifying library data an advanced usage of the API and only to use it when you know what you're doing.
+So it's best to consider modifying library data an advanced usage of the API
+and only to use it when you know what you're doing.
Edit Mode / Memory Access
-------------------------
-Switching edit-mode ``bpy.ops.object.mode_set(mode='EDIT')`` / ``bpy.ops.object.mode_set(mode='OBJECT')`` will re-allocate objects data, any references to a meshes vertices/polygons/uvs, armatures bones, curves points etc cannot be accessed after switching edit-mode.
+Switching edit-mode ``bpy.ops.object.mode_set(mode='EDIT')`` / ``bpy.ops.object.mode_set(mode='OBJECT')``
+will re-allocate objects data,
+any references to a meshes vertices/polygons/uvs, armatures bones,
+curves points etc cannot be accessed after switching edit-mode.
Only the reference to the data its self can be re-accessed, the following example will crash.
@@ -602,7 +724,8 @@ Only the reference to the data its self can be re-accessed, the following exampl
print(polygons)
-So after switching edit-mode you need to re-access any object data variables, the following example shows how to avoid the crash above.
+So after switching edit-mode you need to re-access any object data variables,
+the following example shows how to avoid the crash above.
.. code-block:: python
@@ -616,13 +739,15 @@ So after switching edit-mode you need to re-access any object data variables, th
print(polygons)
-These kinds of problems can happen for any functions which re-allocate the object data but are most common when switching edit-mode.
+These kinds of problems can happen for any functions which re-allocate
+the object data but are most common when switching edit-mode.
Array Re-Allocation
-------------------
-When adding new points to a curve or vertices's/edges/polygons to a mesh, internally the array which stores this data is re-allocated.
+When adding new points to a curve or vertices's/edges/polygons to a mesh,
+internally the array which stores this data is re-allocated.
.. code-block:: python
@@ -633,15 +758,20 @@ When adding new points to a curve or vertices's/edges/polygons to a mesh, intern
# this will crash!
point.co = 1.0, 2.0, 3.0
-This can be avoided by re-assigning the point variables after adding the new one or by storing indices's to the points rather then the points themselves.
+This can be avoided by re-assigning the point variables after adding the new one or by storing
+indices's to the points rather than the points themselves.
-The best way is to sidestep the problem altogether add all the points to the curve at once. This means you don't have to worry about array re-allocation and its faster too since reallocating the entire array for every point added is inefficient.
+The best way is to sidestep the problem altogether add all the points to the curve at once.
+This means you don't have to worry about array re-allocation and its faster too
+since reallocating the entire array for every point added is inefficient.
Removing Data
-------------
-**Any** data that you remove shouldn't be modified or accessed afterwards, this includes f-curves, drivers, render layers, timeline markers, modifiers, constraints along with objects, scenes, groups, bones.. etc.
+**Any** data that you remove shouldn't be modified or accessed afterwards,
+this includes f-curves, drivers, render layers, timeline markers, modifiers, constraints
+along with objects, scenes, groups, bones.. etc.
The ``remove()`` api calls will invalidate the data they free to prevent common mistakes.
@@ -652,12 +782,13 @@ The following example shows how this precortion works.
mesh = bpy.data.meshes.new(name="MyMesh")
# normally the script would use the mesh here...
bpy.data.meshes.remove(mesh)
- print(mesh.name) # <- give an exception rather then crashing:
+ print(mesh.name) # <- give an exception rather than crashing:
# ReferenceError: StructRNA of type Mesh has been removed
-But take care because this is limited to scripts accessing the variable which is removed, the next example will still crash.
+But take care because this is limited to scripts accessing the variable which is removed,
+the next example will still crash.
.. code-block:: python
@@ -670,9 +801,11 @@ But take care because this is limited to scripts accessing the variable which is
sys.exit
========
-Some python modules will call ``sys.exit()`` themselves when an error occurs, while not common behavior this is something to watch out for because it may seem as if blender is crashing since ``sys.exit()`` will quit blender immediately.
-
-For example, the ``optparse`` module will print an error and exit if the arguments are invalid.
+Some Python modules will call ``sys.exit()`` themselves when an error occurs,
+while not common behavior this is something to watch out for because it may seem
+as if Blender is crashing since ``sys.exit()`` will close Blender immediately.
-An ugly way of troubleshooting this is to set ``sys.exit = None`` and see what line of python code is quitting, you could of course replace ``sys.exit`` with your own function but manipulating python in this way is bad practice.
+For example, the ``argparse`` module will print an error and exit if the arguments are invalid.
+An ugly way of troubleshooting this is to set ``sys.exit = None`` and see what line of Python code is quitting,
+you could of course replace ``sys.exit`` with your own function but manipulating Python in this way is bad practice.
diff --git a/doc/python_api/rst/info_overview.rst b/doc/python_api/rst/info_overview.rst
index b2d524b74af..960dd07ecf1 100644
--- a/doc/python_api/rst/info_overview.rst
+++ b/doc/python_api/rst/info_overview.rst
@@ -1,18 +1,25 @@
+
.. _info_overview:
*******************
Python API Overview
*******************
-This document is to give an understanding of how python and blender fit together, covering some of the functionality that isn't obvious from reading the API reference and example scripts.
+This document is to give an understanding of how Python and Blender fit together,
+covering some of the functionality that isn't obvious from reading the API reference and example scripts.
Python in Blender
=================
-Blender embeds a python interpreter which is started with blender and stays active. This interpreter runs scripts to draw the user interface and is used for some of Blender's internal tools too.
+Blender embeds a Python interpreter which is started with Blender and stays active.
+This interpreter runs scripts to draw the user interface and is used for some of Blender's internal tools too.
-This is a typical python environment so tutorials on how to write python scripts will work running the scripts in blender too. Blender provides the :mod:`bpy` module to the python interpreter. This module can be imported in a script and gives access to blender data, classes, and functions. Scripts that deal with blender data will need to import this module.
+This is a typical Python environment so tutorials on how to write Python scripts
+will work running the scripts in Blender too.
+Blender provides the :mod:`bpy` module to the Python interpreter.
+This module can be imported in a script and gives access to Blender data, classes, and functions.
+Scripts that deal with Blender data will need to import this module.
Here is a simple example of moving a vertex of the object named **Cube**:
@@ -21,84 +28,96 @@ Here is a simple example of moving a vertex of the object named **Cube**:
import bpy
bpy.data.objects["Cube"].data.vertices[0].co.x += 1.0
-This modifies Blender's internal data directly. When you run this in the interactive console you will see the 3D viewport update.
+This modifies Blender's internal data directly.
+When you run this in the interactive console you will see the 3D viewport update.
The Default Environment
=======================
-When developing your own scripts it may help to understand how blender sets up its python environment. Many python scripts come bundled with blender and can be used as a reference because they use the same API that script authors write tools in. Typical usage for scripts include: user interface, import/export, scene manipulation, automation, defining your own toolset and customization.
+When developing your own scripts it may help to understand how Blender sets up its Python environment.
+Many Python scripts come bundled with Blender and can be used as a reference
+because they use the same API that script authors write tools in.
+Typical usage for scripts include: user interface, import/export,
+scene manipulation, automation, defining your own toolset and customization.
-On startup blender scans the ``scripts/startup/`` directory for python modules and imports them. The exact location of this directory depends on your installation. `See the directory layout docs <http://wiki.blender.org/index.php/Doc:2.6/Manual/Introduction/Installing_Blender/DirectoryLayout>`_
+On startup Blender scans the ``scripts/startup/`` directory for Python modules and imports them.
+The exact location of this directory depends on your installation.
+`See the directory layout docs
+<https://www.blender.org/manual/getting_started/installing_blender/directorylayout.html>`__
Script Loading
==============
-This may seem obvious but it's important to note the difference between executing a script directly or importing it as a module.
-
-Scripts that extend blender - define classes that exist beyond the scripts execution, this makes future access to these classes (to unregister for example) more difficult than importing as a module where class instance is kept in the module and can be accessed by importing that module later on.
+This may seem obvious but it's important to note the difference
+between executing a script directly or importing it as a module.
-For this reason it's preferable to only use directly execute scripts that don't extend blender by registering classes.
+Scripts that extend Blender - define classes that exist beyond the scripts execution,
+this makes future access to these classes (to unregister for example)
+more difficult than importing as a module where class instance is kept
+in the module and can be accessed by importing that module later on.
+For this reason it's preferable to only use directly execute scripts that don't extend Blender by registering classes.
-Here are some ways to run scripts directly in blender.
-* Loaded in the text editor and press **Run Script**.
+Here are some ways to run scripts directly in Blender.
-* Typed or pasted into the interactive console.
+- Loaded in the text editor and press **Run Script**.
+- Typed or pasted into the interactive console.
+- Execute a Python file from the command line with Blender, eg:
-* Execute a python file from the command line with blender, eg:
+ .. code-block:: sh
- ``blender --python /home/me/my_script.py``
+ blender --python /home/me/my_script.py
To run as modules:
-* The obvious way, ``import some_module`` command from the text window or interactive console.
-
-* Open as a text block and tick "Register" option, this will load with the blend file.
-
-* copy into one of the directories ``scripts/startup``, where they will be automatically imported on startup.
-
-* define as an addon, enabling the addon will load it as a python module.
+- The obvious way, ``import some_module`` command from the text window or interactive console.
+- Open as a text block and tick "Register" option, this will load with the blend file.
+- copy into one of the directories ``scripts/startup``, where they will be automatically imported on startup.
+- define as an addon, enabling the addon will load it as a Python module.
Addons
------
-Some of blenders functionality is best kept optional, alongside scripts loaded at startup we have addons which are kept in their own directory ``scripts/addons``, and only load on startup if selected from the user preferences.
+Some of Blenders functionality is best kept optional,
+alongside scripts loaded at startup we have addons which are kept in their own directory ``scripts/addons``,
+and only load on startup if selected from the user preferences.
-The only difference between addons and built-in python modules is that addons must contain a **bl_info** variable which blender uses to read metadata such as name, author, category and URL.
+The only difference between addons and built-in Python modules is that addons must contain a ``bl_info``
+variable which Blender uses to read metadata such as name, author, category and URL.
The user preferences addon listing uses **bl_info** to display information about each addon.
-`See Addons <http://wiki.blender.org/index.php/Dev:2.5/Py/Scripts/Guidelines/Addons>`_ for details on the **bl_info** dictionary.
+`See Addons <http://wiki.blender.org/index.php/Dev:2.5/Py/Scripts/Guidelines/Addons>`__
+for details on the ``bl_info`` dictionary.
Integration through Classes
===========================
-Running python scripts in the text editor is useful for testing but you’ll want to extend blender to make tools accessible like other built-in functionality.
-
-The blender python api allows integration for:
+Running Python scripts in the text editor is useful for testing but you'll
+want to extend Blender to make tools accessible like other built-in functionality.
-* :class:`bpy.types.Panel`
+The Blender Python api allows integration for:
-* :class:`bpy.types.Menu`
+- :class:`bpy.types.Panel`
+- :class:`bpy.types.Menu`
+- :class:`bpy.types.Operator`
+- :class:`bpy.types.PropertyGroup`
+- :class:`bpy.types.KeyingSet`
+- :class:`bpy.types.RenderEngine`
-* :class:`bpy.types.Operator`
-* :class:`bpy.types.PropertyGroup`
+This is intentionally limited. Currently, for more advanced features such as mesh modifiers,
+object types, or shader nodes, C/C++ must be used.
-* :class:`bpy.types.KeyingSet`
-
-* :class:`bpy.types.RenderEngine`
-
-
-This is intentionally limited. Currently, for more advanced features such as mesh modifiers, object types, or shader nodes, C/C++ must be used.
-
-For python intergration Blender defines methods which are common to all types. This works by creating a python subclass of a Blender class which contains variables and functions specified by the parent class which are pre-defined to interface with Blender.
+For Python integration Blender defines methods which are common to all types.
+This works by creating a Python subclass of a Blender class which contains variables and functions
+specified by the parent class which are pre-defined to interface with Blender.
For example:
@@ -115,15 +134,20 @@ For example:
bpy.utils.register_class(SimpleOperator)
-First note that we subclass a member of :mod:`bpy.types`, this is common for all classes which can be integrated with blender and used so we know if this is an Operator and not a Panel when registering.
+First note that we subclass a member of :mod:`bpy.types`,
+this is common for all classes which can be integrated with Blender and
+used so we know if this is an Operator and not a Panel when registering.
-Both class properties start with a **bl_** prefix. This is a convention used to distinguish blender properties from those you add yourself.
+Both class properties start with a ``bl_`` prefix.
+This is a convention used to distinguish Blender properties from those you add yourself.
-Next see the execute function, which takes an instance of the operator and the current context. A common prefix is not used for functions.
+Next see the execute function, which takes an instance of the operator and the current context.
+A common prefix is not used for functions.
-Lastly the register function is called, this takes the class and loads it into blender. See `Class Registration`_.
+Lastly the register function is called, this takes the class and loads it into Blender. See `Class Registration`_.
-Regarding inheritance, blender doesn't impose restrictions on the kinds of class inheritance used, the registration checks will use attributes and functions defined in parent classes.
+Regarding inheritance, Blender doesn't impose restrictions on the kinds of class inheritance used,
+the registration checks will use attributes and functions defined in parent classes.
class mix-in example:
@@ -141,11 +165,20 @@ class mix-in example:
bpy.utils.register_class(SimpleOperator)
-Notice these classes don't define an ``__init__(self)`` function. While ``__init__()`` and ``__del__()`` will be called if defined, the class instances lifetime only spans the execution. So a panel for example will have a new instance for every redraw, for this reason there is rarely a cause to store variables in the panel instance. Instead, persistent variables should be stored in Blenders data so that the state can be restored when blender is restarted.
+Notice these classes don't define an ``__init__(self)`` function.
+While ``__init__()`` and ``__del__()`` will be called if defined,
+the class instances lifetime only spans the execution.
+So a panel for example will have a new instance for every redraw,
+for this reason there is rarely a cause to store variables in the panel instance.
+Instead, persistent variables should be stored in Blenders
+ata so that the state can be restored when Blender is restarted.
+
+.. note::
-.. note:: Modal operators are an exception, keeping their instance variable as blender runs, see modal operator template.
+ Modal operators are an exception, keeping their instance variable as Blender runs, see modal operator template.
-So once the class is registered with blender, instancing the class and calling the functions is left up to blender. In fact you cannot instance these classes from the script as you would expect with most python API's.
+So once the class is registered with Blender, instancing the class and calling the functions is left up to Blender.
+In fact you cannot instance these classes from the script as you would expect with most Python API's.
To run operators you can call them through the operator api, eg:
@@ -154,7 +187,8 @@ To run operators you can call them through the operator api, eg:
import bpy
bpy.ops.object.simple_operator()
-User interface classes are given a context in which to draw, buttons window, file header, toolbar etc, then they are drawn when that area is displayed so they are never called by python scripts directly.
+User interface classes are given a context in which to draw, buttons window, file header, toolbar etc,
+then they are drawn when that area is displayed so they are never called by Python scripts directly.
Registration
@@ -164,9 +198,10 @@ Registration
Module Registration
-------------------
-Blender modules loaded at startup require ``register()`` and ``unregister()`` functions. These are the *only* functions that blender calls from your code, which is otherwise a regular python module.
+Blender modules loaded at startup require ``register()`` and ``unregister()`` functions.
+These are the *only* functions that Blender calls from your code, which is otherwise a regular Python module.
-A simple blender/python module can look like this:
+A simple Blender/Python module can look like this:
.. code-block:: python
@@ -184,12 +219,16 @@ A simple blender/python module can look like this:
if __name__ == "__main__":
register()
-These functions usually appear at the bottom of the script containing class registration sometimes adding menu items. You can also use them for internal purposes setting up data for your own tools but take care since register won't re-run when a new blend file is loaded.
+These functions usually appear at the bottom of the script containing class registration sometimes adding menu items.
+You can also use them for internal purposes setting up data for your own tools but take care
+since register won't re-run when a new blend file is loaded.
-The register/unregister calls are used so it's possible to toggle addons and reload scripts while blender runs.
-If the register calls were placed in the body of the script, registration would be called on import, meaning there would be no distinction between importing a module or loading its classes into blender.
+The register/unregister calls are used so it's possible to toggle addons and reload scripts while Blender runs.
+If the register calls were placed in the body of the script, registration would be called on import,
+meaning there would be no distinction between importing a module or loading its classes into Blender.
-This becomes problematic when a script imports classes from another module making it difficult to manage which classes are being loaded and when.
+This becomes problematic when a script imports classes from another module
+making it difficult to manage which classes are being loaded and when.
The last 2 lines are only for testing:
@@ -199,19 +238,24 @@ The last 2 lines are only for testing:
register()
This allows the script to be run directly in the text editor to test changes.
-This ``register()`` call won't run when the script is imported as a module since ``__main__`` is reserved for direct execution.
+This ``register()`` call won't run when the script is imported as a module
+since ``__main__`` is reserved for direct execution.
Class Registration
------------------
-Registering a class with blender results in the class definition being loaded into blender, where it becomes available alongside existing functionality.
+Registering a class with Blender results in the class definition being loaded into Blender,
+where it becomes available alongside existing functionality.
-Once this class is loaded you can access it from :mod:`bpy.types`, using the bl_idname rather than the classes original name.
+Once this class is loaded you can access it from :mod:`bpy.types`,
+using the bl_idname rather than the classes original name.
-When loading a class, blender performs sanity checks making sure all required properties and functions are found, that properties have the correct type, and that functions have the right number of arguments.
+When loading a class, Blender performs sanity checks making sure all required properties and functions are found,
+that properties have the correct type, and that functions have the right number of arguments.
-Mostly you will not need concern yourself with this but if there is a problem with the class definition it will be raised on registering:
+Mostly you will not need concern yourself with this but if there is a problem
+with the class definition it will be raised on registering:
Using the function arguments ``def execute(self, context, spam)``, will raise an exception:
@@ -225,9 +269,13 @@ Using ``bl_idname = 1`` will raise.
Multiple-Classes
^^^^^^^^^^^^^^^^
-Loading classes into blender is described above, for simple cases calling :mod:`bpy.utils.register_class` (SomeClass) is sufficient, but when there are many classes or a packages submodule has its own classes it can be tedious to list them all for registration.
+Loading classes into Blender is described above,
+for simple cases calling :mod:`bpy.utils.register_class` (SomeClass) is sufficient,
+but when there are many classes or a packages submodule has its own
+classes it can be tedious to list them all for registration.
-For more convenient loading/unloading :mod:`bpy.utils.register_module` (module) and :mod:`bpy.utils.unregister_module` (module) functions exist.
+For more convenient loading/unloading :mod:`bpy.utils.register_module` (module)
+and :mod:`bpy.utils.unregister_module` (module) functions exist.
A script which defines many of its own operators, panels menus etc. you only need to write:
@@ -239,13 +287,19 @@ A script which defines many of its own operators, panels menus etc. you only nee
def unregister():
bpy.utils.unregister_module(__name__)
-Internally blender collects subclasses on registrable types, storing them by the module in which they are defined. By passing the module name to :mod:`bpy.utils.register_module` blender can register all classes created by this module and its submodules.
+Internally Blender collects subclasses on registrable types, storing them by the module in which they are defined.
+By passing the module name to :mod:`bpy.utils.register_module`
+Blender can register all classes created by this module and its submodules.
Inter Classes Dependencies
^^^^^^^^^^^^^^^^^^^^^^^^^^
-When customizing blender you may want to group your own settings together, after all, they will likely have to co-exist with other scripts. To group these properties classes need to be defined, for groups within groups or collections within groups you can find yourself having to deal with order of registration/unregistration.
+When customizing Blender you may want to group your own settings together,
+after all, they will likely have to co-exist with other scripts.
+To group these properties classes need to be defined,
+for groups within groups or collections within groups
+you can find yourself having to deal with order of registration/unregistration.
Custom properties groups are themselves classes which need to be registered.
@@ -311,7 +365,9 @@ Say you want to store material settings for a custom engine.
Manipulating Classes
^^^^^^^^^^^^^^^^^^^^
-Properties can be added and removed as blender runs, normally happens on register or unregister but for some special cases it may be useful to modify types as the script runs.
+Properties can be added and removed as Blender runs,
+normally happens on register or unregister but for some
+special cases it may be useful to modify types as the script runs.
For example:
@@ -341,7 +397,8 @@ This works just as well for PropertyGroup subclasses you define yourself.
Dynamic Defined-Classes (Advanced)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-In some cases the specifier for data may not be in blender, renderman shader definitions for example and it may be useful to define types and remove them on the fly.
+In some cases the specifier for data may not be in Blender,
+renderman shader definitions for example and it may be useful to define types and remove them on the fly.
.. code-block:: python
@@ -360,7 +417,8 @@ In some cases the specifier for data may not be in blender, renderman shader def
.. note::
- Notice ``type()`` is called to define the class. This is an alternative syntax for class creation in python, better suited to constructing classes dynamically.
+ ``type()`` is called to define the class.
+ This is an alternative syntax for class creation in Python, better suited to constructing classes dynamically.
Calling these operators:
diff --git a/doc/python_api/rst/info_quickstart.rst b/doc/python_api/rst/info_quickstart.rst
index a1052bf4208..ab106dd3bb7 100644
--- a/doc/python_api/rst/info_quickstart.rst
+++ b/doc/python_api/rst/info_quickstart.rst
@@ -1,3 +1,4 @@
+
.. _info_quickstart:
***********************
@@ -11,67 +12,61 @@ This API is generally stable but some areas are still being added and improved.
The Blender/Python API can do the following:
-* Edit any data the user interface can (Scenes, Meshes, Particles etc.)
-
-* Modify user preferences, keymaps and themes
-
-* Run tools with own settings
-
-* Create user interface elements such as menus, headers and panels
-
-* Create new tools
-
-* Create interactive tools
-
-* Create new rendering engines that integrate with Blender
-
-* Define new settings in existing Blender data
-
-* Draw in the 3D view using OpenGL commands from Python
+- Edit any data the user interface can (Scenes, Meshes, Particles etc.)
+- Modify user preferences, keymaps and themes
+- Run tools with own settings
+- Create user interface elements such as menus, headers and panels
+- Create new tools
+- Create interactive tools
+- Create new rendering engines that integrate with Blender
+- Define new settings in existing Blender data
+- Draw in the 3D view using OpenGL commands from Python
The Blender/Python API **can't** (yet)...
-* Create new space types.
-
-* Assign custom properties to every type.
-
-* Define callbacks or listeners to be notified when data is changed.
+- Create new space types.
+- Assign custom properties to every type.
+- Define callbacks or listeners to be notified when data is changed.
Before Starting
===============
-This document isn't intended to fully cover each topic. Rather, its purpose is to familiarize you with Blender Python API.
+This document isn't intended to fully cover each topic.
+Rather, its purpose is to familiarize you with Blender Python API.
A quick list of helpful things to know before starting:
-* Blender uses Python 3.x; some 3rd party extensions are not available yet.
-
-* The interactive console is great for testing one-liners, It also has autocompletion so you can inspect the api quickly.
-
-* Button tool tips show Python attributes and operator names.
-
-* Right clicking on buttons and menu items directly links to API documentation.
-
-* For more examples, the text menu has a templates section where some example operators can be found.
+- Blender uses Python 3.x; some online documentation still assumes 2.x.
+- The interactive console is great for testing one-liners.
+ It also has autocompletion so you can inspect the API quickly.
+- Button tool tips show Python attributes and operator names.
+- Right clicking on buttons and menu items directly links to API documentation.
+- For more examples, the text menu has a templates section where some example operators can be found.
+- To examine further scripts distributed with Blender, see:
-* To examine further scripts distributed with Blender, see ``~/.blender/scripts/startup/bl_ui`` for the user interface and ``~/.blender/scripts/startup/bl_op`` for operators.
+ | ``~/.blender/scripts/startup/bl_ui`` for the user interface,
+ | ``~/.blender/scripts/startup/bl_op`` for operators.
Running Scripts
---------------
-The two most common ways to execute python scripts are using the built-in text editor or entering commands in the python console.
+The two most common ways to execute Python scripts are using the built-in
+text editor or entering commands in the Python console.
-Both the **Text Editor** and **Python Console** are space types you can select from the view header.
+Both the *Text Editor* and *Python Console* are space types you can select from the view header.
-Rather then manually configuring your spaces for Python development, you may prefer to use the **Scripting** screen, included default with Blender, accessible from the top headers screen selector.
+Rather than manually configuring your spaces for Python development,
+you may prefer to use the *Scripting* screen, included default with Blender,
+accessible from the top headers screen selector.
-From the text editor you can open ``.py`` files or paste then from the clipboard, then test using **Run Script**.
+From the text editor you can open ``.py`` files or paste then from the clipboard, then test using *Run Script*.
-The Python Console is typically used for typing in snippets and for testing to get immediate feedback, but can also have entire scripts pasted into it.
+The Python Console is typically used for typing in snippets and for testing to get immediate feedback,
+but can also have entire scripts pasted into it.
Scripts can also run from the command line with Blender but to learn Blender/Python this isn't essential.
@@ -82,12 +77,14 @@ Key Concepts
Data Access
-----------
-Accessing datablocks
+Accessing DataBlocks
^^^^^^^^^^^^^^^^^^^^
-Python accesses Blender's data in the same way as the animation system and user interface; this implies that any setting that can be changed via a button can also be changed from Python.
+Python accesses Blender's data in the same way as the animation system and user interface;
+this implies that any setting that can be changed via a button can also be changed from Python.
-Accessing data from the currently loaded blend file is done with the module :mod:`bpy.data`. This gives access to library data. For example:
+Accessing data from the currently loaded blend file is done with the module :mod:`bpy.data`.
+This gives access to library data. For example:
>>> bpy.data.objects
<bpy_collection[3], BlendDataObjects>
@@ -104,7 +101,8 @@ About Collections
You'll notice that an index as well as a string can be used to access members of the collection.
-Unlike Python's dictionaries, both methods are acceptable; however, the index of a member may change while running Blender.
+Unlike Python's dictionaries, both methods are acceptable;
+however, the index of a member may change while running Blender.
>>> list(bpy.data.objects)
[bpy.data.objects["Cube"], bpy.data.objects["Plane"]]
@@ -116,10 +114,13 @@ Unlike Python's dictionaries, both methods are acceptable; however, the index of
bpy.data.objects["Cube"]
-Accessing attributes
+Accessing Attributes
^^^^^^^^^^^^^^^^^^^^
-Once you have a data block, such as a material, object, groups etc., its attributes can be accessed much like you would change a setting using the graphical interface. In fact, the tooltip for each button also displays the Python attribute which can help in finding what settings to change in a script.
+Once you have a data block, such as a material, object, groups etc.,
+its attributes can be accessed much like you would change a setting using the graphical interface.
+In fact, the tooltip for each button also displays the Python attribute
+which can help in finding what settings to change in a script.
>>> bpy.data.objects[0].name
'Camera'
@@ -131,7 +132,8 @@ Once you have a data block, such as a material, object, groups etc., its attribu
bpy.data.materials['MyMaterial']
-For testing what data to access it's useful to use the "Console", which is its own space type. This supports auto-complete, giving you a fast way to dig into different data in your file.
+For testing what data to access it's useful to use the "Console", which is its own space type.
+This supports auto-complete, giving you a fast way to dig into different data in your file.
Example of a data path that can be quickly found via the console:
@@ -144,7 +146,8 @@ Example of a data path that can be quickly found via the console:
Data Creation/Removal
^^^^^^^^^^^^^^^^^^^^^
-Those of you familiar with other python api's may be surprised that new datablocks in the bpy api can't be created by calling the class:
+Those of you familiar with other Python API's may be surprised that
+new datablocks in the bpy API can't be created by calling the class:
>>> bpy.types.Mesh()
Traceback (most recent call last):
@@ -153,9 +156,10 @@ Those of you familiar with other python api's may be surprised that new databloc
This is an intentional part of the API design.
-The blender/python api can't create blender data that exists outside the main blender database (accessed through bpy.data), because this data is managed by blender (save/load/undo/append... etc).
+The Blender/Python API can't create Blender data that exists outside the main Blender database
+(accessed through :mod:`bpy.data`), because this data is managed by Blender (save/load/undo/append... etc).
-Data is added and removed via methods on the collections in bpy.data, eg:
+Data is added and removed via methods on the collections in :mod:`bpy.data`, eg:
>>> mesh = bpy.data.meshes.new(name="MyMesh")
>>> print(mesh)
@@ -167,7 +171,10 @@ Data is added and removed via methods on the collections in bpy.data, eg:
Custom Properties
^^^^^^^^^^^^^^^^^
-Python can access properties on any datablock that has an ID (data that can be linked in and accessed from :mod:`bpy.data`. When assigning a property, you can make up your own names, these will be created when needed or overwritten if they exist.
+Python can access properties on any datablock that has an ID
+(data that can be linked in and accessed from :mod:`bpy.data`.
+When assigning a property, you can make up your own names,
+these will be created when needed or overwritten if they exist.
This data is saved with the blend file and copied with objects.
@@ -180,7 +187,7 @@ Example:
if "SomeProp" in bpy.context.object:
print("Property found")
- # Use the get function like a python dictionary
+ # Use the get function like a Python dictionary
# which can have a fallback value.
value = bpy.data.scenes["Scene"].get("test_prop", "fallback value")
@@ -193,11 +200,9 @@ Example:
Note that these properties can only be assigned basic Python types.
-* int, float, string
-
-* array of ints/floats
-
-* dictionary (only string keys are supported, values must be basic types too)
+- int, float, string
+- array of ints/floats
+- dictionary (only string keys are supported, values must be basic types too)
These properties are valid outside of Python. They can be animated by curves or used in driver paths.
@@ -205,7 +210,10 @@ These properties are valid outside of Python. They can be animated by curves or
Context
-------
-While it's useful to be able to access data directly by name or as a list, it's more common to operate on the user's selection. The context is always available from '''bpy.context''' and can be used to get the active object, scene, tool settings along with many other attributes.
+While it's useful to be able to access data directly by name or as a list,
+it's more common to operate on the user's selection.
+The context is always available from ``bpy.context`` and can be used to get the active object, scene,
+tool settings along with many other attributes.
Common-use cases:
@@ -213,22 +221,28 @@ Common-use cases:
>>> bpy.context.selected_objects
>>> bpy.context.visible_bones
-Note that the context is read-only. These values cannot be modified directly, though they may be changed by running API functions or by using the data API.
+Note that the context is read-only.
+These values cannot be modified directly,
+though they may be changed by running API functions or by using the data API.
So ``bpy.context.object = obj`` will raise an error.
But ``bpy.context.scene.objects.active = obj`` will work as expected.
-The context attributes change depending on where they are accessed. The 3D view has different context members than the console, so take care when accessing context attributes that the user state is known.
+The context attributes change depending on where they are accessed.
+The 3D view has different context members than the console,
+so take care when accessing context attributes that the user state is known.
-See :mod:`bpy.context` API reference
+See :mod:`bpy.context` API reference.
Operators (Tools)
-----------------
-Operators are tools generally accessed by the user from buttons, menu items or key shortcuts. From the user perspective they are a tool but Python can run these with its own settings through the :mod:`bpy.ops` module.
+Operators are tools generally accessed by the user from buttons, menu items or key shortcuts.
+From the user perspective they are a tool but Python can run these with its own settings
+through the :mod:`bpy.ops` module.
Examples:
@@ -241,16 +255,19 @@ Examples:
.. note::
- The menu item: Help -> Operator Cheat Sheet" gives a list of all operators and their default values in Python syntax, along with the generated docs. This is a good way to get an overview of all blender's operators.
+ The menu item: :menuselection:`Help --> Operator Cheat Sheet`
+ gives a list of all operators and their default values in Python syntax, along with the generated docs.
+ This is a good way to get an overview of all Blender's operators.
Operator Poll()
^^^^^^^^^^^^^^^
-Many operators have a "poll" function which may check that the mouse is in a valid area or that the object is in the correct mode (Edit Mode, Weight Paint etc).
-When an operator's poll function fails within python, an exception is raised.
+Many operators have a "poll" function which may check that the cursor
+is in a valid area or that the object is in the correct mode (Edit Mode, Weight Paint etc).
+When an operator's poll function fails within Python, an exception is raised.
-For example, calling bpy.ops.view3d.render_border() from the console raises the following error:
+For example, calling ``bpy.ops.view3d.render_border()`` from the console raises the following error:
.. code-block:: python
@@ -258,7 +275,8 @@ For example, calling bpy.ops.view3d.render_border() from the console raises the
In this case the context must be the 3d view with an active camera.
-To avoid using try/except clauses wherever operators are called you can call the operators own .poll() function to check if it can run in the current context.
+To avoid using try/except clauses wherever operators are called you can call the operators
+own ``poll()`` function to check if it can run in the current context.
.. code-block:: python
@@ -271,13 +289,10 @@ Integration
Python scripts can integrate with Blender in the following ways:
-* By defining a rendering engine.
-
-* By defining operators.
-
-* By defining menus, headers and panels.
-
-* By inserting new buttons into existing menus, headers and panels
+- By defining a rendering engine.
+- By defining operators.
+- By defining menus, headers and panels.
+- By inserting new buttons into existing menus, headers and panels
In Python, this is done by defining a class, which is a subclass of an existing type.
@@ -288,62 +303,52 @@ Example Operator
.. literalinclude:: ../../../release/scripts/templates_py/operator_simple.py
-Once this script runs, ``SimpleOperator`` is registered with Blender and can be called from the operator search popup or added to the toolbar.
+Once this script runs, ``SimpleOperator`` is registered with Blender
+and can be called from the operator search popup or added to the toolbar.
To run the script:
-#. Highlight the above code then press Ctrl+C to copy it.
-
+#. Highlight the above code then press :kbd:`Ctrl-C` to copy it.
#. Start Blender
-
-#. Press Ctrl+Right twice to change to the Scripting layout.
-
+#. Press :kbd:`Ctrl-Right` twice to change to the Scripting layout.
#. Click the button labeled ``New`` and the confirmation pop up in order to create a new text block.
-
-#. Press Ctrl+V to paste the code into the text panel (the upper left frame).
-
+#. Press :kbd:`Ctrl-V` to paste the code into the text panel (the upper left frame).
#. Click on the button **Run Script**.
-
-#. Move your mouse into the 3D view, press spacebar for the operator search menu, and type "Simple".
-
+#. Move your cursor into the 3D view, press spacebar for the operator search menu, and type "Simple".
#. Click on the "Simple Operator" item found in search.
-.. seealso:: The class members with the **bl_** prefix are documented in the API
+.. seealso:: The class members with the ``bl_`` prefix are documented in the API
reference :class:`bpy.types.Operator`
-.. note:: The output from the ``main`` function is sent to the terminal; in order to see this, be sure to :ref:`use the terminal <use_the_terminal>`.
+.. note::
+
+ The output from the ``main`` function is sent to the terminal;
+ in order to see this, be sure to :ref:`use the terminal <use_the_terminal>`.
Example Panel
-------------
-Panels register themselves as a class, like an operator. Notice the extra **bl_** variables used to set the context they display in.
+Panels register themselves as a class, like an operator.
+Notice the extra ``bl_`` variables used to set the context they display in.
.. literalinclude:: ../../../release/scripts/templates_py/ui_panel_simple.py
To run the script:
-#. Highlight the above code then press Ctrl+C to copy it
-
+#. Highlight the above code then press :kbd:`Ctrl-C` to copy it
#. Start Blender
-
-#. Press Ctrl+Right twice to change to the Scripting layout
-
+#. Press :kbd:`Ctrl-Right` twice to change to the Scripting layout
#. Click the button labeled ``New`` and the confirmation pop up in order to create a new text block.
-
-#. Press Ctrl+V to paste the code into the text panel (the upper left frame)
-
+#. Press :kbd:`Ctrl-V` to paste the code into the text panel (the upper left frame)
#. Click on the button **Run Script**.
To view the results:
#. Select the the default cube.
-
#. Click on the Object properties icon in the buttons panel (far right; appears as a tiny cube).
-
#. Scroll down to see a panel named **Hello World Panel**.
-
#. Changing the object name also updates **Hello World Panel's** Name: field.
Note the row distribution and the label and properties that are available through the code.
@@ -362,16 +367,15 @@ Blender's Python API can be split up into 3 categories.
Native Types
------------
-In simple cases returning a number or a string as a custom type would be cumbersome, so these are accessed as normal python types.
+In simple cases returning a number or a string as a custom type would be cumbersome,
+so these are accessed as normal Python types.
-* blender float/int/boolean -> float/int/boolean
-
-* blender enumerator -> string
+- Blender float/int/boolean -> float/int/boolean
+- Blender enumerator -> string
>>> C.object.rotation_mode = 'AXIS_ANGLE'
-
-* blender enumerator (multiple) -> set of strings
+- Blender enumerator (multiple) -> set of strings
.. code-block:: python
@@ -389,7 +393,8 @@ Used for Blender datablocks and collections: :class:`bpy.types.bpy_struct`
For data that contains its own attributes groups/meshes/bones/scenes... etc.
-There are 2 main types that wrap Blenders data, one for datablocks (known internally as bpy_struct), another for properties.
+There are 2 main types that wrap Blenders data, one for datablocks
+(known internally as ``bpy_struct``), another for properties.
>>> bpy.context.object
bpy.data.objects['Cube']
@@ -405,7 +410,9 @@ Mathutils Types
Used for vectors, quaternion, eulers, matrix and color types, accessible from :mod:`mathutils`
-Some attributes such as :class:`bpy.types.Object.location`, :class:`bpy.types.PoseBone.rotation_euler` and :class:`bpy.types.Scene.cursor_location` can be accessed as special math types which can be used together and manipulated in various useful ways.
+Some attributes such as :class:`bpy.types.Object.location`,
+:class:`bpy.types.PoseBone.rotation_euler` and :class:`bpy.types.Scene.cursor_location`
+can be accessed as special math types which can be used together and manipulated in various useful ways.
Example of a matrix, vector multiplication:
@@ -440,7 +447,9 @@ Animation
There are 2 ways to add keyframes through Python.
-The first is through key properties directly, which is similar to inserting a keyframe from the button as a user. You can also manually create the curves and keyframe data, then set the path to the property. Here are examples of both methods.
+The first is through key properties directly, which is similar to inserting a keyframe from the button as a user.
+You can also manually create the curves and keyframe data, then set the path to the property.
+Here are examples of both methods.
Both examples insert a keyframe on the active object's Z axis.
diff --git a/doc/python_api/rst/info_tips_and_tricks.rst b/doc/python_api/rst/info_tips_and_tricks.rst
index e345f36a148..28d129b5b13 100644
--- a/doc/python_api/rst/info_tips_and_tricks.rst
+++ b/doc/python_api/rst/info_tips_and_tricks.rst
@@ -1,10 +1,12 @@
+
***************
Tips and Tricks
***************
Here are various suggestions that you might find useful when writing scripts.
-Some of these are just python features that scripters may not have thought to use with blender, others are blender specific.
+Some of these are just Python features that scripters may not have thought to use with Blender,
+others are Blender specific.
.. _use_the_terminal:
@@ -12,18 +14,21 @@ Some of these are just python features that scripters may not have thought to us
Use The Terminal
================
-When writing python scripts, it's useful to have a terminal open, this is not the built-in python console but a terminal application which is used to start blender.
+When writing Python scripts, it's useful to have a terminal open,
+this is not the built-in Python console but a terminal application which is used to start Blender.
There are 3 main uses for the terminal, these are:
-* You can see the output of ``print()`` as your script runs, which is useful to view debug info.
-
-* The error trace-back is printed in full to the terminal which won't always generate an error popup in blender's user interface (depending on how the script is executed).
-
-* If the script runs for too long or you accidentally enter an infinite loop, Ctrl+C in the terminal (Ctrl+Break on Windows) will quit the script early.
+- You can see the output of ``print()`` as your script runs, which is useful to view debug info.
+- The error trace-back is printed in full to the terminal which won't always generate an error popup in
+ Blender's user interface (depending on how the script is executed).
+- If the script runs for too long or you accidentally enter an infinite loop,
+ :kbd:`Ctrl-C` in the terminal (:kbd:`Ctrl-Break` on Windows) will quit the script early.
.. note::
- For Linux and OSX users this means starting the terminal first, then running blender from within it. On Windows the terminal can be enabled from the help menu.
+
+ For Linux and OSX users this means starting the terminal first, then running Blender from within it.
+ On Windows the terminal can be enabled from the help menu.
Interface Tricks
@@ -33,43 +38,56 @@ Interface Tricks
Access Operator Commands
------------------------
-You may have noticed that the tooltip for menu items and buttons includes the ``bpy.ops``... command to run that button, a handy (hidden) feature is that you can press Ctrl+C over any menu item/button to copy this command into the clipboard.
+You may have noticed that the tooltip for menu items and buttons includes the ``bpy.ops.[...])`` command
+to run that button, a handy (hidden) feature is that you can press :kbd:`Ctrl-C` over
+any menu item/button to copy this command into the clipboard.
Access Data Path
----------------
-To find the path from an :class:`ID` datablock to its setting isn't always so simple since it may be nested away. To get this quickly you can right click on the setting and select select **Copy Data Path**,
+To find the path from an :class:`ID` datablock to its setting isn't always so simple since it may be nested away.
+To get this quickly you can right click on the setting and select select **Copy Data Path**,
if this can't be generated, only the property name is copied.
.. note::
- This uses the same method for creating the animation path used by :class:`bpy.types.FCurve.data_path` and :class:`bpy.types.DriverTarget.data_path` drivers.
+ This uses the same method for creating the animation path used by
+ :class:`bpy.types.FCurve.data_path` and
+ :class:`bpy.types.DriverTarget.data_path` drivers.
-.. _info_show_all_operators
+.. _info_show_all_operators:
Show All Operators
==================
-While blender logs operators in the Info space, this only reports operators with the ``REGISTER`` option enabeld so as not to flood the Info view with calls to ``bpy.ops.view3d.smoothview`` and ``bpy.ops.view3d.zoom``.
+While Blender logs operators in the Info space,
+this only reports operators with the ``REGISTER`` option enabeld so as not to flood the *Info* view
+with calls to ``bpy.ops.view3d.smoothview`` and ``bpy.ops.view3d.zoom``.
-However, for testing it can be useful to see **every** operator called in a terminal, do this by enabling the debug option either by passing the ``--debug-wm`` argument when starting blender or by setting :mod:`bpy.app.debug_wm` to True while blender is running.
+However, for testing it can be useful to see **every** operator called in a terminal,
+do this by enabling the debug option either by passing the ``--debug-wm`` argument when starting Blender
+or by setting :mod:`bpy.app.debug_wm` to ``True`` while Blender is running.
Use an External Editor
======================
-Blenders text editor is fine for small changes and writing tests but its not full featured, for larger projects you'll probably want to use a standalone editor or python IDE.
+Blenders text editor is fine for small changes and writing tests but its not full featured,
+for larger projects you'll probably want to use a standalone editor or Python IDE.
-Editing a text file externally and having the same text open in blender does work but isn't that optimal so here are 2 ways you can easily use an external file from blender.
+Editing a text file externally and having the same text open in Blender does work but isn't that optimal
+so here are 2 ways you can easily use an external file from Blender.
+
+Using the following examples you'll still need textblock in Blender to execute,
+but reference an external file rather than including it directly.
-Using the following examples you'll still need textblock in blender to execute, but reference an external file rather then including it directly.
Executing External Scripts
--------------------------
-This is the equivalent to running the script directly, referencing a scripts path from a 2 line textblock.
+This is the equivalent to running the script directly, referencing a scripts path from a 2 line text-block.
.. code-block:: python
@@ -102,12 +120,17 @@ This example shows loading a script in as a module and executing a module functi
myscript.main()
-Notice that the script is reloaded every time, this forces use of the modified version, otherwise the cached one in ``sys.modules`` would be used until blender was restarted.
+Notice that the script is reloaded every time, this forces use of the modified version,
+otherwise the cached one in ``sys.modules`` would be used until Blender was restarted.
-The important difference between this and executing the script directly is it has to call a function in the module, in this case ``main()`` but it can be any function, an advantage with this is you can pass arguments to the function from this small script which is often useful for testing different settings quickly.
+The important difference between this and executing the script directly is it
+has to call a function in the module, in this case ``main()`` but it can be any function,
+an advantage with this is you can pass arguments to the function from this
+small script which is often useful for testing different settings quickly.
-The other issue with this is the script has to be in pythons module search path.
-While this is not best practice - for testing you can extend the search path, this example adds the current blend files directory to the search path, then loads the script as a module.
+The other issue with this is the script has to be in Pythons module search path.
+While this is not best practice - for testing you can extend the search path,
+this example adds the current blend files directory to the search path, then loads the script as a module.
.. code-block:: python
@@ -128,71 +151,86 @@ While this is not best practice - for testing you can extend the search path, th
Don't Use Blender!
==================
-While developing your own scripts blenders interface can get in the way, manually reloading, running the scripts, opening file import etc. adds overhead.
+While developing your own scripts Blenders interface can get in the way,
+manually reloading, running the scripts, opening file import etc. adds overhead.
-For scripts that are not interactive it can end up being more efficient not to use blenders interface at all and instead execute the script on the command line.
+For scripts that are not interactive it can end up being more efficient not to use
+Blenders interface at all and instead execute the script on the command line.
-.. code-block:: python
+.. code-block:: sh
blender --background --python myscript.py
You might want to run this with a blend file so the script has some data to operate on.
-.. code-block:: python
+.. code-block:: sh
blender myscene.blend --background --python myscript.py
.. note::
- Depending on your setup you might have to enter the full path to the blender executable.
-
+ Depending on your setup you might have to enter the full path to the Blender executable.
-Once the script is running properly in background mode, you'll want to check the output of the script, this depends completely on the task at hand however here are some suggestions.
-* render the output to an image, use an image viewer and keep writing over the same image each time.
+Once the script is running properly in background mode, you'll want to check the output of the script,
+this depends completely on the task at hand however here are some suggestions.
-* save a new blend file, or export the file using one of blenders exporters.
+- render the output to an image, use an image viewer and keep writing over the same image each time.
+- save a new blend file, or export the file using one of Blenders exporters.
+- if the results can be displayed as text - print them or write them to a file.
-* if the results can be displayed as text - print them or write them to a file.
-
-This can take a little time to setup, but it can be well worth the effort to reduce the time it takes to test changes - you can even have blender running the script ever few seconds with a viewer updating the results, so no need to leave your text editor to see changes.
+While this can take a little time to setup, it can be well worth the effort
+to reduce the time it takes to test changes - you can even have
+Blender running the script every few seconds with a viewer updating the results,
+so no need to leave your text editor to see changes.
Use External Tools
==================
-When there are no readily available python modules to perform specific tasks it's worth keeping in mind you may be able to have python execute an external command on your data and read the result back in.
+When there are no readily available Python modules to perform specific tasks it's
+worth keeping in mind you may be able to have Python execute an external command
+on your data and read the result back in.
-Using external programs adds an extra dependency and may limit who can use the script but to quickly setup your own custom pipeline or writing one-off scripts this can be handy.
+Using external programs adds an extra dependency and may limit who can use the script
+but to quickly setup your own custom pipeline or writing one-off scripts this can be handy.
Examples include:
-* Run The Gimp in batch mode to execute custom scripts for advanced image processing.
-
-* Write out 3D models to use external mesh manipulation tools and read back in the results.
-
-* Convert files into recognizable formats before reading.
+- Run The Gimp in batch mode to execute custom scripts for advanced image processing.
+- Write out 3D models to use external mesh manipulation tools and read back in the results.
+- Convert files into recognizable formats before reading.
Bundled Python & Extensions
===========================
-The Blender releases distributed from blender.org include a complete python installation on all platforms, this has the disadvantage that any extensions you have installed in your systems python wont be found by blender.
+The Blender releases distributed from blender.org include a complete Python installation on all platforms,
+this has the disadvantage that any extensions you have installed in your systems Python wont be found by Blender.
There are 2 ways around this:
-* remove blender python sub-directory, blender will then fallback on the systems python and use that instead **python version must match the one that blender comes with**.
+- remove Blender Python sub-directory, Blender will then fallback on the systems Python and use that instead
+ .. warning::
+
+ The Python version must match the one that Blender comes with.
-* copy the extensions into blender's python sub-directory so blender can access them, you could also copy the entire python installation into blenders sub-directory, replacing the one blender comes with. This works as long as the python versions match and the paths are created in the same relative locations. Doing this has the advantage that you can redistribute this bundle to others with blender and/or the game player, including any extensions you rely on.
+- copy the extensions into Blender's Python sub-directory so Blender can access them,
+ you could also copy the entire Python installation into Blenders sub-directory,
+ replacing the one Blender comes with.
+ This works as long as the Python versions match and the paths are created in the same relative locations.
+ Doing this has the advantage that you can redistribute this bundle to others with Blender and/or the game player,
+ including any extensions you rely on.
Drop Into a Python Interpreter in Your Script
=============================================
-In the middle of a script you may want to inspect some variables, run some function and generally dig about to see whats going on.
+In the middle of a script you may want to inspect some variables,
+run some function and generally dig about to see whats going on.
.. code-block:: python
@@ -217,10 +255,13 @@ The next example is an equivalent single line version of the script above which
__import__('code').interact(local=dict(globals(), **locals()))
-``code.interact`` can be added at any line in the script and will pause the script an launch an interactive interpreter in the terminal, when you're done you can quit the interpreter and the script will continue execution.
+``code.interact`` can be added at any line in the script
+and will pause the script an launch an interactive interpreter in the terminal,
+when you're done you can quit the interpreter and the script will continue execution.
-If you have **IPython** installed you can use their ``embed()`` function which will implicitly use the current namespace, this has autocomplete and some useful features that the standard python eval-loop doesn't have.
+If you have **IPython** installed you can use its ``embed()`` function which uses the current namespace.
+The IPython prompt has auto-complete and some useful features that the standard Python eval-loop doesn't have.
.. code-block:: python
@@ -228,7 +269,7 @@ If you have **IPython** installed you can use their ``embed()`` function which w
IPython.embed()
-Admittedly this highlights the lack of any python debugging support built into blender, but its still handy to know.
+Admittedly this highlights the lack of any Python debugging support built into Blender, but its still handy to know.
.. note::
@@ -242,27 +283,32 @@ Advanced
Blender as a module
-------------------
-From a python perspective it's nicer to have everything as an extension which lets the python script combine many components.
+From a Python perspective it's nicer to have everything as an extension
+which lets the Python script combine many components.
Advantages include:
-* you can use external editors/IDE's with blenders python API and execute scripts within the IDE (step over code, inspect variables as the script runs).
+- you can use external editors/IDE's with Blenders Python API and execute scripts within the IDE
+ (step over code, inspect variables as the script runs).
+- editors/IDE's can auto complete Blender modules & variables.
+- existing scripts can import Blender API's without having to run inside Blender.
-* editors/IDE's can auto complete blender modules & variables.
-* existing scripts can import blender API's without having to run inside blender.
+This is marked advanced because to run Blender as a Python module requires a special build option.
-
-This is marked advanced because to run blender as a python module requires a special build option.
-
-For instructions on building see `Building blender as a python module <http://wiki.blender.org/index.php/User:Ideasman42/BlenderAsPyModule>`_
+For instructions on building see
+`Building Blender as a Python module <http://wiki.blender.org/index.php/User:Ideasman42/BlenderAsPyModule>`_
Python Safety (Build Option)
----------------------------
-Since it's possible to access data which has been removed (see Gotcha's), this can be hard to track down the cause of crashes.
+Since it's possible to access data which has been removed (see Gotcha's),
+this can be hard to track down the cause of crashes.
+
+To raise Python exceptions on accessing freed data (rather than crashing),
+enable the CMake build option WITH_PYTHON_SAFETY.
-To raise python exceptions on accessing freed data (rather then crashing), enable the CMake build option WITH_PYTHON_SAFETY.
+This enables data tracking which makes data access about 2x slower
+which is why the option isn't enabled in release builds.
-This enables data tracking which makes data access about 2x slower which is why the option is not enabled in release builds.
diff --git a/doc/python_api/rst/info_tutorial_addon.rst b/doc/python_api/rst/info_tutorial_addon.rst
index 5637cf2f638..239c28859a3 100644
--- a/doc/python_api/rst/info_tutorial_addon.rst
+++ b/doc/python_api/rst/info_tutorial_addon.rst
@@ -19,21 +19,17 @@ Prerequisites
Before going through the tutorial you should...
-* Familiarity with the basics of working in Blender.
-
-* Know how to run a script in Blender's text editor (as documented in the quick-start)
-
-* Have an understanding of Python primitive types (int, boolean, string, list, tuple, dictionary, and set).
-
-* Be familiar with the concept of Python modules.
-
-* Basic understanding of classes (object orientation) in Python.
+- Familiarity with the basics of working in Blender.
+- Know how to run a script in Blender's text editor (as documented in the quick-start)
+- Have an understanding of Python primitive types (int, boolean, string, list, tuple, dictionary, and set).
+- Be familiar with the concept of Python modules.
+- Basic understanding of classes (object orientation) in Python.
Suggested reading before starting this tutorial.
-* `Dive Into Python <http://getpython3.com/diveintopython3/index.html>`_ sections (1, 2, 3, 4, and 7).
-* :ref:`Blender API Quickstart <info_quickstart>`
+- `Dive Into Python <http://getpython3.com/diveintopython3/index.html>`_ sections (1, 2, 3, 4, and 7).
+- :ref:`Blender API Quickstart <info_quickstart>`
to help become familiar with Blender/Python basics.
@@ -45,13 +41,11 @@ Documentation Links
While going through the tutorial you may want to look into our reference documentation.
-* :ref:`Blender API Overview <info_overview>`. -
+- :ref:`Blender API Overview <info_overview>`. -
*This document is rather detailed but helpful if you want to know more on a topic.*
-
-* :mod:`bpy.context` api reference. -
+- :mod:`bpy.context` api reference. -
*Handy to have a list of available items your script may operate on.*
-
-* :class:`bpy.types.Operator`. -
+- :class:`bpy.types.Operator`. -
*The following addons define operators, these docs give details and more examples of operators.*
@@ -78,11 +72,11 @@ To give an example, here is the simplest possible addon.
print("Goodbye World")
-* ``bl_info`` is a dictionary containing addon meta-data such as the title, version and author to be displayed in the
+- ``bl_info`` is a dictionary containing addon meta-data such as the title, version and author to be displayed in the
user preferences addon list.
-* ``register`` is a function which only runs when enabling the addon, this means the module can be loaded without
+- ``register`` is a function which only runs when enabling the addon, this means the module can be loaded without
activating the addon.
-* ``unregister`` is a function to unload anything setup by ``register``, this is called when the addon is disabled.
+- ``unregister`` is a function to unload anything setup by ``register``, this is called when the addon is disabled.
@@ -184,12 +178,15 @@ This addon takes the body of the script above, and adds them to an operator's ``
register()
-.. note:: ``bl_info`` is split across multiple lines, this is just a style convention used to more easily add items.
+.. note::
+
+ ``bl_info`` is split across multiple lines, this is just a style convention used to more easily add items.
+
+.. note::
-.. note:: Rather than using ``bpy.context.scene``, we use the ``context.scene`` argument passed to ``execute()``.
- In most cases these will be the same however in some cases operators will be passed a custom context
- so script authors should prefer the ``context`` argument passed to operators.
-
+ Rather than using ``bpy.context.scene``, we use the ``context.scene`` argument passed to ``execute()``.
+ In most cases these will be the same however in some cases operators will be passed a custom context
+ so script authors should prefer the ``context`` argument passed to operators.
To test the script you can copy and paste this into Blender text editor and run it, this will execute the script
directly and call register immediately.
@@ -202,8 +199,8 @@ However running the script wont move any objects, for this you need to execute t
:height: 574px
:alt: Spacebar
-Do this by pressing ``SpaceBar`` to bring up the operator search dialog and type in "Move X by One" (the ``bl_label``),
-then press ``Enter``.
+Do this by pressing :kbd:`Spacebar` to bring up the operator search dialog and type in
+"Move X by One" (the ``bl_label``), then :kbd:`Enter`.
@@ -211,11 +208,12 @@ The objects should move as before.
*Keep this addon open in Blender for the next step - Installing.*
+
Install The Addon
-----------------
-Once you have your addon within in Blender's text editor, you will want to be able to install it so it can be enabled in
-the user preferences to load on startup.
+Once you have your addon within in Blender's text editor,
+you will want to be able to install it so it can be enabled in the user preferences to load on startup.
Even though the addon above is a test, lets go through the steps anyway so you know how to do it for later.
@@ -224,10 +222,11 @@ restrictions that apply to Python modules and end with a ``.py`` extension.
Once the file is on disk, you can install it as you would for an addon downloaded online.
-Open the user **File -> User Preferences**, Select the **Addon** section, press **Install Addon...** and select the file.
+Open the user :menuselection:`File -> User Preferences`,
+Select the *Addon* section, press *Install Addon...* and select the file.
-Now the addon will be listed and you can enable it by pressing the check-box, if you want it to be enabled on restart,
-press **Save as Default**.
+Now the addon will be listed and you can enable it by pressing the check-box,
+if you want it to be enabled on restart, press *Save as Default*.
.. note::
@@ -241,7 +240,7 @@ press **Save as Default**.
print(addon_utils.paths())
More is written on this topic here:
- `Directory Layout <http://wiki.blender.org/index.php/Doc:2.6/Manual/Introduction/Installing_Blender/DirectoryLayout>`_
+ `Directory Layout <https://www.blender.org/manual/getting_started/installing_blender/directorylayout.html>`_
Your Second Addon
@@ -563,20 +562,26 @@ Bringing it all together
# handle the keymap
wm = bpy.context.window_manager
- km = wm.keyconfigs.addon.keymaps.new(name='Object Mode', space_type='EMPTY')
- kmi = km.keymap_items.new(ObjectCursorArray.bl_idname, 'SPACE', 'PRESS', ctrl=True, shift=True)
- kmi.properties.total = 4
- addon_keymaps.append((km, kmi))
+ # Note that in background mode (no GUI available), keyconfigs are not available either, so we have to check this
+ # to avoid nasty errors in background case.
+ kc = wm.keyconfigs.addon
+ if kc:
+ km = wm.keyconfigs.addon.keymaps.new(name='Object Mode', space_type='EMPTY')
+ kmi = km.keymap_items.new(ObjectCursorArray.bl_idname, 'SPACE', 'PRESS', ctrl=True, shift=True)
+ kmi.properties.total = 4
+ addon_keymaps.append((km, kmi))
def unregister():
- bpy.utils.unregister_class(ObjectCursorArray)
- bpy.types.VIEW3D_MT_object.remove(menu_func)
-
+ # Note: when unregistering, it's usually good practice to do it in reverse order you registered.
+ # Can avoid strange issues like keymap still referring to operators already unregistered...
# handle the keymap
for km, kmi in addon_keymaps:
km.keymap_items.remove(kmi)
addon_keymaps.clear()
+ bpy.utils.unregister_class(ObjectCursorArray)
+ bpy.types.VIEW3D_MT_object.remove(menu_func)
+
if __name__ == "__main__":
register()
@@ -627,15 +632,12 @@ you want to see example code for, this is a good place to start.
Here are some sites you might like to check on after completing this tutorial.
-* :ref:`Blender/Python API Overview <info_overview>` -
+- :ref:`Blender/Python API Overview <info_overview>` -
*For more background details on Blender/Python integration.*
-
-* `How to Think Like a Computer Scientist <http://interactivepython.org/courselib/static/thinkcspy/index.html>`_ -
+- `How to Think Like a Computer Scientist <http://interactivepython.org/courselib/static/thinkcspy/index.html>`_ -
*Great info for those who are still learning Python.*
-
-* `Blender Development (Wiki) <http://wiki.blender.org/index.php/Dev:Contents>`_ -
+- `Blender Development (Wiki) <http://wiki.blender.org/index.php/Dev:Contents>`_ -
*Blender Development, general information and helpful links.*
-
-* `Blender Artists (Coding Section) <http://blenderartists.org/forum/forumdisplay.php?47-Coding>`_ -
+- `Blender Artists (Coding Section) <http://blenderartists.org/forum/forumdisplay.php?47-Coding>`_ -
*forum where people ask Python development questions*
diff --git a/doc/python_api/sphinx_changelog_gen.py b/doc/python_api/sphinx_changelog_gen.py
index 3b968de9a2c..0b083c31c58 100644
--- a/doc/python_api/sphinx_changelog_gen.py
+++ b/doc/python_api/sphinx_changelog_gen.py
@@ -316,7 +316,7 @@ def main():
try:
import argparse
- except:
+ except ImportError:
print("Old Blender, just dumping")
api_dump()
return
diff --git a/doc/python_api/sphinx_doc_gen.py b/doc/python_api/sphinx_doc_gen.py
index 0b9a4e6a37b..f68d6bf617a 100644
--- a/doc/python_api/sphinx_doc_gen.py
+++ b/doc/python_api/sphinx_doc_gen.py
@@ -138,19 +138,9 @@ def handle_args():
parser.add_argument("-T", "--sphinx-theme",
dest="sphinx_theme",
type=str,
- default='default',
- help=
- # see SPHINX_THEMES below
- "Sphinx theme (default='default')\n"
- "Available themes\n"
- "----------------\n"
- "(Blender Foundation) blender-org\n" # naiad
- "(Sphinx) agogo, basic, epub, haiku, nature, "
- "scrolls, sphinxdoc, traditional\n",
-# choices=['naiad', 'blender-org'] + # bf
-# ['agogo', 'basic', 'epub',
-# 'haiku', 'nature', 'scrolls',
-# 'sphinxdoc', 'traditional'], # sphinx
+ default="classic",
+ help="Sphinx theme (default='classic'), "
+ "see: http://sphinx-doc.org/theming.html",
required=False)
parser.add_argument("-N", "--sphinx-named-output",
@@ -244,6 +234,7 @@ else:
EXCLUDE_MODULES = [
"aud",
"bge",
+ "bge.app"
"bge.constraints",
"bge.events",
"bge.logic",
@@ -267,10 +258,12 @@ else:
"bpy.props",
"bpy.types", # supports filtering
"bpy.utils",
+ "bpy.utils.previews",
"bpy_extras",
"gpu",
"mathutils",
"mathutils.geometry",
+ "mathutils.bvhtree",
"mathutils.kdtree",
"mathutils.noise",
"freestyle",
@@ -419,23 +412,7 @@ BLENDER_ZIP_FILENAME = "%s.zip" % REFERENCE_NAME
# -------------------------------SPHINX-----------------------------------------
-SPHINX_THEMES = {'bf': ['blender-org'], # , 'naiad',
- 'sphinx': ['agogo',
- 'basic',
- 'default',
- 'epub',
- 'haiku',
- 'nature',
- 'scrolls',
- 'sphinxdoc',
- 'traditional']}
-
-available_themes = SPHINX_THEMES['bf'] + SPHINX_THEMES['sphinx']
-if ARGS.sphinx_theme not in available_themes:
- print("Please choose a theme among: %s" % ', '.join(available_themes))
- sys.exit()
-
-if ARGS.sphinx_theme in SPHINX_THEMES['bf']:
+if ARGS.sphinx_theme == "blender-org":
SPHINX_THEME_DIR = os.path.join(ARGS.output_dir, ARGS.sphinx_theme)
SPHINX_THEME_SVN_DIR = os.path.join(SCRIPT_DIR, ARGS.sphinx_theme)
@@ -480,9 +457,11 @@ ClassMethodDescriptorType = type(dict.__dict__['fromkeys'])
MethodDescriptorType = type(dict.get)
GetSetDescriptorType = type(int.real)
StaticMethodType = type(staticmethod(lambda: None))
-from types import (MemberDescriptorType,
- MethodType,
- )
+from types import (
+ MemberDescriptorType,
+ MethodType,
+ FunctionType,
+ )
_BPY_STRUCT_FAKE = "bpy_struct"
_BPY_PROP_COLLECTION_FAKE = "bpy_prop_collection"
@@ -493,6 +472,18 @@ else:
_BPY_PROP_COLLECTION_ID = "collection"
+def escape_rst(text):
+ """ Escape plain text which may contain characters used by RST.
+ """
+ return text.translate(escape_rst.trans)
+escape_rst.trans = str.maketrans({
+ "`": "\\`",
+ "|": "\\|",
+ "*": "\\*",
+ "\\": "\\\\",
+ })
+
+
def is_struct_seq(value):
return isinstance(value, tuple) and type(tuple) != tuple and hasattr(value, "n_fields")
@@ -653,25 +644,32 @@ def pyfunc2sphinx(ident, fw, module_name, type_name, identifier, py_func, is_cla
if type(py_func) == MethodType:
return
- arg_str = inspect.formatargspec(*inspect.getargspec(py_func))
+ arg_str = inspect.formatargspec(*inspect.getfullargspec(py_func))
if not is_class:
func_type = "function"
# ther rest are class methods
- elif arg_str.startswith("(self, "):
- arg_str = "(" + arg_str[7:]
+ elif arg_str.startswith("(self, ") or arg_str == "(self)":
+ arg_str = "()" if (arg_str == "(self)") else ("(" + arg_str[7:])
func_type = "method"
elif arg_str.startswith("(cls, "):
- arg_str = "(" + arg_str[6:]
+ arg_str = "()" if (arg_str == "(cls)") else ("(" + arg_str[6:])
func_type = "classmethod"
else:
func_type = "staticmethod"
- fw(ident + ".. %s:: %s%s\n\n" % (func_type, identifier, arg_str))
- if py_func.__doc__:
- write_indented_lines(ident + " ", fw, py_func.__doc__)
+ doc = py_func.__doc__
+ if (not doc) or (not doc.startswith(".. %s:: " % func_type)):
+ fw(ident + ".. %s:: %s%s\n\n" % (func_type, identifier, arg_str))
+ ident_temp = ident + " "
+ else:
+ ident_temp = ident
+
+ if doc:
+ write_indented_lines(ident_temp, fw, doc)
fw("\n")
+ del doc, ident_temp
if is_class:
write_example_ref(ident + " ", fw, module_name + "." + type_name + "." + identifier)
@@ -887,7 +885,7 @@ def pymodule2sphinx(basepath, module_name, module, title):
module_dir_value_type.sort(key=lambda triple: str(triple[2]))
for attribute, value, value_type in module_dir_value_type:
- if value_type == types.FunctionType:
+ if value_type == FunctionType:
pyfunc2sphinx("", fw, module_name, None, attribute, value, is_class=False)
elif value_type in {types.BuiltinMethodType, types.BuiltinFunctionType}: # both the same at the moment but to be future proof
# note: can't get args from these, so dump the string as is
@@ -937,18 +935,29 @@ def pymodule2sphinx(basepath, module_name, module, title):
fw(title_string(heading, heading_char))
# May need to be its own function
- fw(".. class:: %s\n\n" % type_name)
if value.__doc__:
- write_indented_lines(" ", fw, value.__doc__, False)
- fw("\n")
+ if value.__doc__.startswith(".. class::"):
+ fw(value.__doc__)
+ else:
+ fw(".. class:: %s\n\n" % type_name)
+ write_indented_lines(" ", fw, value.__doc__, True)
+ else:
+ fw(".. class:: %s\n\n" % type_name)
+ fw("\n")
+
write_example_ref(" ", fw, module_name + "." + type_name)
- descr_items = [(key, descr) for key, descr in sorted(value.__dict__.items()) if not key.startswith("__")]
+ descr_items = [(key, descr) for key, descr in sorted(value.__dict__.items()) if not key.startswith("_")]
for key, descr in descr_items:
if type(descr) == ClassMethodDescriptorType:
py_descr2sphinx(" ", fw, descr, module_name, type_name, key)
+ # needed for pure python classes
+ for key, descr in descr_items:
+ if type(descr) == FunctionType:
+ pyfunc2sphinx(" ", fw, module_name, type_name, key, descr, is_class=True)
+
for key, descr in descr_items:
if type(descr) == MethodDescriptorType:
py_descr2sphinx(" ", fw, descr, module_name, type_name, key)
@@ -971,10 +980,12 @@ def pymodule2sphinx(basepath, module_name, module, title):
context_type_map = {
"active_base": ("ObjectBase", False),
"active_bone": ("EditBone", False),
+ "active_gpencil_frame": ("GreasePencilLayer", True),
+ "active_gpencil_layer": ("GPencilLayer", True),
+ "active_node": ("Node", False),
"active_object": ("Object", False),
"active_operator": ("Operator", False),
"active_pose_bone": ("PoseBone", False),
- "active_node": ("Node", False),
"armature": ("Armature", False),
"bone": ("Bone", False),
"brush": ("Brush", False),
@@ -990,7 +1001,11 @@ context_type_map = {
"edit_object": ("Object", False),
"edit_text": ("Text", False),
"editable_bones": ("EditBone", True),
+ "editable_gpencil_layers": ("GPencilLayer", True),
+ "editable_gpencil_strokes": ("GPencilStroke", True),
"fluid": ("FluidSimulationModifier", False),
+ "gpencil_data": ("GreasePencel", False),
+ "gpencil_data_owner": ("ID", False),
"image_paint_object": ("Object", False),
"lamp": ("Lamp", False),
"lattice": ("Lattice", False),
@@ -1030,6 +1045,7 @@ context_type_map = {
"vertex_paint_object": ("Object", False),
"visible_bases": ("ObjectBase", True),
"visible_bones": ("EditBone", True),
+ "visible_gpencil_layers": ("GPencilLayer", True),
"visible_objects": ("Object", True),
"visible_pose_bones": ("PoseBone", True),
"weight_paint_object": ("Object", False),
@@ -1135,7 +1151,7 @@ def pycontext2sphinx(basepath):
def pyrna_enum2sphinx(prop, use_empty_descriptions=False):
- """ write a bullet point list of enum + descrptons
+ """ write a bullet point list of enum + descriptions
"""
if use_empty_descriptions:
@@ -1150,7 +1166,7 @@ def pyrna_enum2sphinx(prop, use_empty_descriptions=False):
if ok:
return "".join(["* ``%s`` %s.\n" %
(identifier,
- ", ".join(val for val in (name, description) if val),
+ ", ".join(escape_rst(val) for val in (name, description) if val),
)
for identifier, name, description in prop.enum_items
])
@@ -1252,6 +1268,7 @@ def pyrna2sphinx(basepath):
fw("\n\n")
subclass_ids = [s.identifier for s in structs.values() if s.base is struct if not rna_info.rna_id_ignore(s.identifier)]
+ subclass_ids.sort()
if subclass_ids:
fw("subclasses --- \n" + ", ".join((":class:`%s`" % s) for s in subclass_ids) + "\n\n")
@@ -1559,7 +1576,7 @@ def write_sphinx_conf_py(basepath):
if ARGS.sphinx_theme != 'default':
fw("html_theme = '%s'\n" % ARGS.sphinx_theme)
- if ARGS.sphinx_theme in SPHINX_THEMES['bf']:
+ if ARGS.sphinx_theme == "blender-org":
fw("html_theme_path = ['../']\n")
# copied with the theme, exclude else we get an error [#28873]
fw("html_favicon = 'favicon.ico'\n") # in <theme>/static/
@@ -1595,7 +1612,7 @@ def write_rst_contents(basepath):
fw("\n")
# fw("`A PDF version of this document is also available <%s>`_\n" % BLENDER_PDF_FILENAME)
- fw("`A compressed ZIP file of this site is available <%s>`_\n" % BLENDER_ZIP_FILENAME)
+ fw("This site can be downloaded for offline use `Download the full Documentation (zipped HTML files) <%s>`_\n" % BLENDER_ZIP_FILENAME)
fw("\n")
@@ -1620,6 +1637,7 @@ def write_rst_contents(basepath):
# py modules
"bpy.utils",
+ "bpy.utils.previews",
"bpy.path",
"bpy.app",
"bpy.app.handlers",
@@ -1639,7 +1657,7 @@ def write_rst_contents(basepath):
standalone_modules = (
# mathutils
- "mathutils", "mathutils.geometry", "mathutils.kdtree", "mathutils.noise",
+ "mathutils", "mathutils.geometry", "mathutils.bvhtree", "mathutils.kdtree", "mathutils.noise",
# misc
"freestyle", "bgl", "blf", "gpu", "aud", "bpy_extras",
# bmesh, submodules are in own page
@@ -1665,6 +1683,7 @@ def write_rst_contents(basepath):
fw(" bge.texture.rst\n\n")
fw(" bge.events.rst\n\n")
fw(" bge.constraints.rst\n\n")
+ fw(" bge.app.rst\n\n")
# rna generated change log
fw(title_string("API Info", "=", double=True))
@@ -1790,6 +1809,7 @@ def write_rst_importable_modules(basepath):
"bpy.props" : "Property Definitions",
"mathutils" : "Math Types & Utilities",
"mathutils.geometry" : "Geometry Utilities",
+ "mathutils.bvhtree" : "BVHTree Utilities",
"mathutils.kdtree" : "KDTree Utilities",
"mathutils.noise" : "Noise Utilities",
"freestyle" : "Freestyle Module",
@@ -1821,6 +1841,7 @@ def copy_handwritten_rsts(basepath):
"bge.texture",
"bge.events",
"bge.constraints",
+ "bge.app",
"bgl", # "Blender OpenGl wrapper"
"gpu", # "GPU Shader Module"
@@ -1974,7 +1995,7 @@ def main():
copy_function=shutil.copy)
# eventually, copy the theme dir
- if ARGS.sphinx_theme in SPHINX_THEMES['bf']:
+ if ARGS.sphinx_theme == "blender-org":
if os.path.exists(SPHINX_THEME_DIR):
shutil.rmtree(SPHINX_THEME_DIR, True)
shutil.copytree(SPHINX_THEME_SVN_DIR,
diff --git a/doc/python_api/sphinx_doc_gen.sh b/doc/python_api/sphinx_doc_gen.sh
index d7fc372a8d8..01de3e2c2ea 100755
--- a/doc/python_api/sphinx_doc_gen.sh
+++ b/doc/python_api/sphinx_doc_gen.sh
@@ -3,6 +3,10 @@
# bash doc/python_api/sphinx_doc_gen.sh
# ssh upload means you need an account on the server
+if [ "$1" == "" ] ; then
+ echo "Expected a single argument for the username on blender.org, aborting"
+ exit 1
+fi
# ----------------------------------------------------------------------------
# Upload vars
@@ -16,9 +20,9 @@ DO_OUT_PDF=false
BLENDER="./blender.bin"
-SSH_USER="ideasman42"
+SSH_USER=$1
SSH_HOST=$SSH_USER"@blender.org"
-SSH_UPLOAD="/data/www/vhosts/www.blender.org/documentation" # blender_python_api_VERSION, added after
+SSH_UPLOAD="/data/www/vhosts/www.blender.org/api" # blender_python_api_VERSION, added after
# ----------------------------------------------------------------------------
# Blender Version & Info
diff --git a/extern/CMakeLists.txt b/extern/CMakeLists.txt
index 8d85551d493..93f57b04d4e 100644
--- a/extern/CMakeLists.txt
+++ b/extern/CMakeLists.txt
@@ -26,10 +26,14 @@
# Otherwise we get warnings here that we cant fix in external projects
remove_strict_flags()
-add_subdirectory(colamd)
add_subdirectory(rangetree)
add_subdirectory(wcwidth)
add_subdirectory(libmv)
+add_subdirectory(Eigen3)
+
+if(WITH_OPENNL)
+ add_subdirectory(colamd)
+endif()
if(WITH_BULLET)
if(NOT WITH_SYSTEM_BULLET)
@@ -47,7 +51,11 @@ if(WITH_BINRELOC)
endif()
if(NOT WITH_SYSTEM_GLEW)
- add_subdirectory(glew)
+ if(WITH_GLEW_ES)
+ add_subdirectory(glew-es)
+ else()
+ add_subdirectory(glew)
+ endif()
endif()
if(WITH_GAMEENGINE)
@@ -62,7 +70,7 @@ if(WITH_IMAGE_REDCODE)
add_subdirectory(libredcode)
endif()
-if(WITH_LZO)
+if(WITH_LZO AND NOT WITH_SYSTEM_LZO)
add_subdirectory(lzo)
endif()
@@ -70,7 +78,7 @@ if(WITH_LZMA)
add_subdirectory(lzma)
endif()
-if(WITH_CYCLES OR WITH_COMPOSITOR)
+if(WITH_CYCLES OR WITH_COMPOSITOR OR WITH_OPENSUBDIV)
add_subdirectory(clew)
add_subdirectory(cuew)
endif()
@@ -79,12 +87,14 @@ if(WITH_MOD_BOOLEAN)
add_subdirectory(carve)
endif()
-if(WITH_GHOST_XDND)
- if(UNIX AND NOT APPLE)
- add_subdirectory(xdnd)
- endif()
+if(WITH_X11 AND WITH_GHOST_XDND)
+ add_subdirectory(xdnd)
endif()
if(WITH_GTESTS)
add_subdirectory(gtest)
endif()
+
+if(WITH_SDL AND WITH_SDL_DYNLOAD)
+ add_subdirectory(sdlew)
+endif()
diff --git a/extern/Eigen3/CMakeLists.txt b/extern/Eigen3/CMakeLists.txt
new file mode 100644
index 00000000000..9bbfc9a3670
--- /dev/null
+++ b/extern/Eigen3/CMakeLists.txt
@@ -0,0 +1,41 @@
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# The Original Code is Copyright (C) 2015, Blender Foundation
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): Bastien Montagne.
+#
+# ***** END GPL LICENSE BLOCK *****
+
+set(INC
+ .
+)
+
+set(INC_SYS
+)
+
+set(SRC
+ eigen3_capi.h
+
+ intern/eigenvalues.cc
+
+ intern/eigenvalues.h
+)
+
+blender_add_lib(extern_eigen3 "${SRC}" "${INC}" "${INC_SYS}")
diff --git a/extern/Eigen3/SConscript b/extern/Eigen3/SConscript
new file mode 100644
index 00000000000..2dc2d623768
--- /dev/null
+++ b/extern/Eigen3/SConscript
@@ -0,0 +1,35 @@
+#!/usr/bin/env python
+#
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# The Original Code is Copyright (C) 2015, Blender Foundation
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): Bastien Montagne.
+#
+# ***** END GPL LICENSE BLOCK *****
+
+Import('env')
+
+sources = env.Glob('intern/*.cc')
+
+incs = '.'
+defs = []
+
+env.BlenderLib('extern_eigen3', sources, Split(incs), defs, libtype=['extern','player'], priority=[10, 185])
diff --git a/extern/Eigen3/eigen3_capi.h b/extern/Eigen3/eigen3_capi.h
new file mode 100644
index 00000000000..16f223793a9
--- /dev/null
+++ b/extern/Eigen3/eigen3_capi.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.
+ *
+ * The Original Code is Copyright (C) 2015 Blender Foundation.
+ * All rights reserved.
+ *
+ * Contributor(s): Blender Foundation,
+ * Bastien Montagne
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __EIGEN3_C_API_H__
+#define __EIGEN3_C_API_H__
+
+#include "intern/eigenvalues.h"
+
+#endif /* __EIGEN3_C_API_H__ */
diff --git a/extern/Eigen3/intern/eigenvalues.cc b/extern/Eigen3/intern/eigenvalues.cc
new file mode 100644
index 00000000000..dcaaee8e9c2
--- /dev/null
+++ b/extern/Eigen3/intern/eigenvalues.cc
@@ -0,0 +1,70 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2015 Blender Foundation.
+ * All rights reserved.
+ *
+ * Contributor(s): Blender Foundation,
+ * Bastien Montagne
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __EIGEN3_EIGENVALUES_C_API_CC__
+#define __EIGEN3_EIGENVALUES_C_API_CC__
+
+/* Eigen gives annoying huge amount of warnings here, silence them! */
+#ifdef __GNUC__
+# pragma GCC diagnostic ignored "-Wlogical-op"
+#endif
+
+#include <Eigen/Core>
+#include <Eigen/Eigenvalues>
+
+#include "eigenvalues.h"
+
+using Eigen::SelfAdjointEigenSolver;
+
+using Eigen::MatrixXf;
+using Eigen::VectorXf;
+using Eigen::Map;
+
+using Eigen::Success;
+
+bool EG3_self_adjoint_eigen_solve(const int size, const float *matrix, float *r_eigen_values, float *r_eigen_vectors)
+{
+ SelfAdjointEigenSolver<MatrixXf> eigen_solver;
+
+ /* Blender and Eigen matrices are both column-major. */
+ eigen_solver.compute(Map<MatrixXf>((float *)matrix, size, size));
+
+ if (eigen_solver.info() != Success) {
+ return false;
+ }
+
+ if (r_eigen_values) {
+ Map<VectorXf>(r_eigen_values, size) = eigen_solver.eigenvalues().transpose();
+ }
+
+ if (r_eigen_vectors) {
+ Map<MatrixXf>(r_eigen_vectors, size, size) = eigen_solver.eigenvectors();
+ }
+
+ return true;
+}
+
+#endif /* __EIGEN3_EIGENVALUES_C_API_CC__ */
diff --git a/extern/Eigen3/intern/eigenvalues.h b/extern/Eigen3/intern/eigenvalues.h
new file mode 100644
index 00000000000..93fc06c2339
--- /dev/null
+++ b/extern/Eigen3/intern/eigenvalues.h
@@ -0,0 +1,40 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2015 Blender Foundation.
+ * All rights reserved.
+ *
+ * Contributor(s): Blender Foundation,
+ * Bastien Montagne
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __EIGEN3_EIGENVALUES_C_API_H__
+#define __EIGEN3_EIGENVALUES_C_API_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+bool EG3_self_adjoint_eigen_solve(const int size, const float *matrix, float *r_eigen_values, float *r_eigen_vectors);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __EIGEN3_EIGENVALUES_C_API_H__ */
diff --git a/extern/SConscript b/extern/SConscript
index 714dfd2d537..484c0e959c2 100644
--- a/extern/SConscript
+++ b/extern/SConscript
@@ -2,11 +2,16 @@
Import('env')
-SConscript(['glew/SConscript'])
+if env['WITH_BF_GLEW_ES']:
+ SConscript(['glew-es/SConscript'])
+else:
+ SConscript(['glew/SConscript'])
+
SConscript(['colamd/SConscript'])
SConscript(['rangetree/SConscript'])
SConscript(['wcwidth/SConscript'])
SConscript(['libmv/SConscript'])
+SConscript(['Eigen3/SConscript'])
if env['WITH_BF_GAMEENGINE']:
SConscript(['recastnavigation/SConscript'])
@@ -20,7 +25,7 @@ if env['WITH_BF_ELTOPO']:
if env['WITH_BF_BULLET']:
SConscript(['bullet2/src/SConscript'])
-if env['WITH_BF_COMPOSITOR'] or env['WITH_BF_CYCLES']:
+if env['WITH_BF_COMPOSITOR'] or env['WITH_BF_CYCLES'] or env['WITH_BF_OPENSUBDIV']:
SConscript (['clew/SConscript'])
SConscript (['cuew/SConscript'])
@@ -46,3 +51,6 @@ if env['WITH_GHOST_XDND']:
# FreeBSD doesn't seems to support XDND protocol
if env['OURPLATFORM'] in ('linux', 'openbsd3', 'sunos5', 'aix4', 'aix5'):
SConscript(['xdnd/SConscript'])
+
+if env['WITH_BF_SDL'] and env['WITH_BF_SDL_DYNLOAD']:
+ SConscript(['sdlew/SConscript'])
diff --git a/extern/bullet2/readme.txt b/extern/bullet2/readme.txt
index 3c09dad1fbf..3b286afa579 100644
--- a/extern/bullet2/readme.txt
+++ b/extern/bullet2/readme.txt
@@ -6,3 +6,8 @@ Erwin
Apply patches/convex_hull.patch to add access to the convex hull
operation, used in the BMesh convex hull operator.
+
+Documentation is available at:
+http://code.google.com/p/bullet/source/browse/trunk/Bullet_User_Manual.pdf
+and:
+https://github.com/bulletphysics/bullet3/tree/master/docs
diff --git a/extern/bullet2/src/Bullet-C-Api.h b/extern/bullet2/src/Bullet-C-Api.h
index 2eabf3840e1..5d00f7e3ac3 100644
--- a/extern/bullet2/src/Bullet-C-Api.h
+++ b/extern/bullet2/src/Bullet-C-Api.h
@@ -171,6 +171,7 @@ extern "C" {
/* Convex Hull */
PL_DECLARE_HANDLE(plConvexHull);
plConvexHull plConvexHullCompute(float (*coords)[3], int count);
+ void plConvexHullDelete(plConvexHull hull);
int plConvexHullNumVertices(plConvexHull hull);
int plConvexHullNumFaces(plConvexHull hull);
void plConvexHullGetVertex(plConvexHull hull, int n, float coords[3], int *original_index);
diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionWorld.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionWorld.h
index b3fffdecd98..0ac5563d06e 100644
--- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionWorld.h
+++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionWorld.h
@@ -15,7 +15,7 @@ subject to the following restrictions:
/**
- * @mainpage Bullet Documentation
+ * @page Bullet Documentation
*
* @section intro_sec Introduction
* Bullet is a Collision Detection and Rigid Body Dynamics Library. The Library is Open Source and free for commercial use, under the ZLib license ( http://opensource.org/licenses/zlib-license.php ).
diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSliderConstraint.cpp b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSliderConstraint.cpp
index aff9f27f594..aff9f27f594 100755..100644
--- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSliderConstraint.cpp
+++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSliderConstraint.cpp
diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSliderConstraint.h b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSliderConstraint.h
index 57ebb47d8e7..57ebb47d8e7 100755..100644
--- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSliderConstraint.h
+++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSliderConstraint.h
diff --git a/extern/bullet2/src/BulletDynamics/Dynamics/Bullet-C-API.cpp b/extern/bullet2/src/BulletDynamics/Dynamics/Bullet-C-API.cpp
index 21f0aa93220..e1f69afe101 100644
--- a/extern/bullet2/src/BulletDynamics/Dynamics/Bullet-C-API.cpp
+++ b/extern/bullet2/src/BulletDynamics/Dynamics/Bullet-C-API.cpp
@@ -413,6 +413,12 @@ plConvexHull plConvexHullCompute(float (*coords)[3], int count)
return reinterpret_cast<plConvexHull>(computer);
}
+void plConvexHullDelete(plConvexHull hull)
+{
+ btConvexHullComputer *computer(reinterpret_cast< btConvexHullComputer* >(hull));
+ delete computer;
+}
+
int plConvexHullNumVertices(plConvexHull hull)
{
btConvexHullComputer *computer(reinterpret_cast< btConvexHullComputer* >(hull));
diff --git a/extern/carve/CMakeLists.txt b/extern/carve/CMakeLists.txt
index 5754290d710..643bd423546 100644
--- a/extern/carve/CMakeLists.txt
+++ b/extern/carve/CMakeLists.txt
@@ -161,6 +161,7 @@ if(WITH_BOOST)
add_definitions(
-DCARVE_SYSTEM_BOOST
+ -DHAVE_BOOST_LIBRARY
)
list(APPEND INC_SYS
diff --git a/extern/carve/SConscript b/extern/carve/SConscript
index f975e253d60..e08e75e6640 100644
--- a/extern/carve/SConscript
+++ b/extern/carve/SConscript
@@ -19,6 +19,7 @@ if env['WITH_BF_BOOST']:
defs.append('HAVE_BOOST_UNORDERED_COLLECTIONS')
defs.append('CARVE_SYSTEM_BOOST')
+ defs.append('HAVE_BOOST_LIBRARY')
incs.append(env['BF_BOOST_INC'])
env.BlenderLib ('extern_carve', Split(sources), incs, defs, libtype=['extern'], priority=[40] )
diff --git a/extern/carve/bundle.sh b/extern/carve/bundle.sh
index 2a3e621fab0..dec902e30c0 100755
--- a/extern/carve/bundle.sh
+++ b/extern/carve/bundle.sh
@@ -31,6 +31,8 @@ headers=`find ./lib -type f -iname '*.h' -or -iname '*.hpp' | sed -r 's/^\.\//\t
includes=`find ./include -type f -iname '*.h' -or -iname '*.hpp' | sed -r 's/^\.\//\t/' | sort -d`
cp patches/files/config.h include/carve/config.h
+mkdir -p include/carve/random
+cp patches/files/random.h include/carve/random/random.h
cat > CMakeLists.txt << EOF
# ***** BEGIN GPL LICENSE BLOCK *****
@@ -91,6 +93,7 @@ if(WITH_BOOST)
add_definitions(
-DCARVE_SYSTEM_BOOST
+ -DHAVE_BOOST_LIBRARY
)
list(APPEND INC_SYS
@@ -102,8 +105,6 @@ blender_add_lib(extern_carve "\${SRC}" "\${INC}" "\${INC_SYS}")
EOF
cat > SConscript << EOF
-#!/usr/bin/python
-
# NOTE: This file is automatically generated by bundle.sh script
# If you're doing changes in this file, please update template
# in that script too
@@ -123,6 +124,7 @@ if env['WITH_BF_BOOST']:
defs.append('HAVE_BOOST_UNORDERED_COLLECTIONS')
defs.append('CARVE_SYSTEM_BOOST')
+ defs.append('HAVE_BOOST_LIBRARY')
incs.append(env['BF_BOOST_INC'])
env.BlenderLib ('extern_carve', Split(sources), incs, defs, libtype=['extern'], priority=[40] )
diff --git a/extern/carve/include/carve/random/random.h b/extern/carve/include/carve/random/random.h
new file mode 100644
index 00000000000..634063cb90c
--- /dev/null
+++ b/extern/carve/include/carve/random/random.h
@@ -0,0 +1,61 @@
+#include <cassert>
+#include <cmath>
+#include <vector>
+
+namespace boost {
+#if __cplusplus > 199711L
+# include <random>
+typedef std::mt19937 mt19937;
+#else
+# include <stdlib.h>
+struct mt19937 {
+ int operator()() {
+ return rand();
+ }
+
+ int max() {
+ return RAND_MAX;
+ }
+};
+#endif
+
+template<typename T>
+struct uniform_on_sphere {
+ typedef std::vector<T> result_type;
+
+ uniform_on_sphere(int dimension) {
+ assert(dimension == 3);
+ }
+
+ std::vector<T>
+ operator()(float u1, float u2) {
+ T z = 1.0 - 2.0*u1;
+ T r = std::sqrt(std::max(0.0, 1.0 - z*z));
+ T phi = 2.0*M_PI*u2;
+ T x = r*std::cos(phi);
+ T y = r*std::sin(phi);
+ std::vector<T> result;
+ result.push_back(x);
+ result.push_back(y);
+ result.push_back(z);
+ return result;
+ }
+};
+
+template<typename RNG, typename DISTR>
+struct variate_generator {
+
+ variate_generator(RNG rng, DISTR distr)
+ : rng_(rng), distr_(distr) {}
+
+ typename DISTR::result_type
+ operator()() {
+ float rng_max_inv = 1.0 / rng_.max();
+ return distr_(rng_() * rng_max_inv, rng_() * rng_max_inv);
+ }
+
+ RNG rng_;
+ DISTR distr_;
+};
+
+}
diff --git a/extern/carve/lib/polyhedron.cpp b/extern/carve/lib/polyhedron.cpp
index 7f65da8c125..d402fce36df 100644
--- a/extern/carve/lib/polyhedron.cpp
+++ b/extern/carve/lib/polyhedron.cpp
@@ -36,7 +36,11 @@
#include <carve/mesh.hpp>
-#include BOOST_INCLUDE(random.hpp)
+#ifdef HAVE_BOOST_LIBRARY
+# include BOOST_INCLUDE(random.hpp)
+#else
+# include <carve/random/random.h>
+#endif
namespace {
bool emb_test(carve::poly::Polyhedron *poly,
diff --git a/extern/carve/patches/files/random.h b/extern/carve/patches/files/random.h
new file mode 100644
index 00000000000..634063cb90c
--- /dev/null
+++ b/extern/carve/patches/files/random.h
@@ -0,0 +1,61 @@
+#include <cassert>
+#include <cmath>
+#include <vector>
+
+namespace boost {
+#if __cplusplus > 199711L
+# include <random>
+typedef std::mt19937 mt19937;
+#else
+# include <stdlib.h>
+struct mt19937 {
+ int operator()() {
+ return rand();
+ }
+
+ int max() {
+ return RAND_MAX;
+ }
+};
+#endif
+
+template<typename T>
+struct uniform_on_sphere {
+ typedef std::vector<T> result_type;
+
+ uniform_on_sphere(int dimension) {
+ assert(dimension == 3);
+ }
+
+ std::vector<T>
+ operator()(float u1, float u2) {
+ T z = 1.0 - 2.0*u1;
+ T r = std::sqrt(std::max(0.0, 1.0 - z*z));
+ T phi = 2.0*M_PI*u2;
+ T x = r*std::cos(phi);
+ T y = r*std::sin(phi);
+ std::vector<T> result;
+ result.push_back(x);
+ result.push_back(y);
+ result.push_back(z);
+ return result;
+ }
+};
+
+template<typename RNG, typename DISTR>
+struct variate_generator {
+
+ variate_generator(RNG rng, DISTR distr)
+ : rng_(rng), distr_(distr) {}
+
+ typename DISTR::result_type
+ operator()() {
+ float rng_max_inv = 1.0 / rng_.max();
+ return distr_(rng_() * rng_max_inv, rng_() * rng_max_inv);
+ }
+
+ RNG rng_;
+ DISTR distr_;
+};
+
+}
diff --git a/extern/carve/patches/random.patch b/extern/carve/patches/random.patch
new file mode 100644
index 00000000000..36cc8d10430
--- /dev/null
+++ b/extern/carve/patches/random.patch
@@ -0,0 +1,16 @@
+diff -r 9a85d733a43d lib/polyhedron.cpp
+--- a/lib/polyhedron.cpp Tue Jun 24 11:15:23 2014 +1000
++++ b/lib/polyhedron.cpp Thu Nov 13 17:36:06 2014 +0500
+@@ -36,7 +36,11 @@
+
+ #include <carve/mesh.hpp>
+
+-#include BOOST_INCLUDE(random.hpp)
++#ifdef HAVE_BOOST_LIBRARY
++# include BOOST_INCLUDE(random.hpp)
++#else
++# include <carve/random/random.h>
++#endif
+
+ namespace {
+ bool emb_test(carve::poly::Polyhedron *poly,
diff --git a/extern/carve/patches/series b/extern/carve/patches/series
index 4691339b419..b7e97d68c4c 100644
--- a/extern/carve/patches/series
+++ b/extern/carve/patches/series
@@ -11,3 +11,4 @@ mesh_simplify_uninitialized_var.patch
memory_leak_fix.patch
msvc_fix.patch
face_hole_merge_workaround.patch
+random.patch
diff --git a/extern/clew/include/clew.h b/extern/clew/include/clew.h
index 624fdb299fe..1b72f813c9f 100644
--- a/extern/clew/include/clew.h
+++ b/extern/clew/include/clew.h
@@ -350,7 +350,7 @@ typedef unsigned int cl_GLenum;
#ifdef _MSC_VER
#if defined(_M_IX86)
-#if _M_IX86_FP >= 0
+#if _M_IX86_FP >= 0 && !defined(__SSE__)
#define __SSE__
#endif
#if _M_IX86_FP >= 1
@@ -1815,6 +1815,11 @@ typedef struct _cl_buffer_region {
/* Function signature typedef's */
+#ifdef __APPLE__
+# pragma GCC diagnostic push
+# pragma GCC diagnostic ignored "-Wignored-attributes"
+#endif
+
/* Platform API */
typedef CL_API_ENTRY cl_int (CL_API_CALL *
PFNCLGETPLATFORMIDS)(cl_uint /* num_entries */,
@@ -2476,6 +2481,10 @@ PFNCLCREATEFROMGLTEXTURE3D)(cl_context /* context */,
cl_int * /* errcode_ret */) CL_EXT_SUFFIX__VERSION_1_1_DEPRECATED;
#endif
+#ifdef __APPLE__
+# pragma GCC diagnostic pop // ignored "-Wignored-attributes"
+#endif
+
/* cl_khr_gl_sharing extension */
#define cl_khr_gl_sharing 1
@@ -2742,6 +2751,30 @@ CLEW_FUN_EXPORT PFNCLGETGLCONTEXTINFOKHR __clewGetGLContextInfoKH
#endif
#define clGetGLContextInfoKHR CLEW_GET_FUN(__clewGetGLContextInfoKHR )
+/* cl_ext */
+
+/******************************************
+ * cl_nv_device_attribute_query extension *
+ ******************************************/
+/* cl_nv_device_attribute_query extension - no extension #define since it has no functions */
+#define CL_DEVICE_COMPUTE_CAPABILITY_MAJOR_NV 0x4000
+#define CL_DEVICE_COMPUTE_CAPABILITY_MINOR_NV 0x4001
+#define CL_DEVICE_REGISTERS_PER_BLOCK_NV 0x4002
+#define CL_DEVICE_WARP_SIZE_NV 0x4003
+#define CL_DEVICE_GPU_OVERLAP_NV 0x4004
+#define CL_DEVICE_KERNEL_EXEC_TIMEOUT_NV 0x4005
+#define CL_DEVICE_INTEGRATED_MEMORY_NV 0x4006
+
+/*********************************
+ * cl_amd_device_attribute_query *
+ *********************************/
+#define CL_DEVICE_PROFILING_TIMER_OFFSET_AMD 0x4036
+
+/*********************************
+ * cl_arm_printf extension
+ *********************************/
+#define CL_PRINTF_CALLBACK_ARM 0x40B0
+#define CL_PRINTF_BUFFERSIZE_ARM 0x40B1
#define CLEW_SUCCESS 0 //!< Success error code
#define CLEW_ERROR_OPEN_FAILED -1 //!< Error code for failing to open the dynamic library
diff --git a/extern/glew-es/CMakeLists.txt b/extern/glew-es/CMakeLists.txt
new file mode 100644
index 00000000000..ba80d3f6120
--- /dev/null
+++ b/extern/glew-es/CMakeLists.txt
@@ -0,0 +1,57 @@
+# ***** 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): Jason Wilkins
+#
+# ***** END GPL LICENSE BLOCK *****
+
+set(INC
+ include
+)
+
+set(INC_SYS
+
+)
+
+if(UNIX)
+ list(APPEND INC_SYS
+ ${X11_X11_INCLUDE_PATH}
+ )
+endif()
+
+set(SRC
+ src/glew.c
+
+ include/GL/eglew.h
+ include/GL/glesew.h
+ include/GL/glew.h
+ include/GL/glxew.h
+ include/GL/wglew.h
+)
+
+add_definitions(${GL_DEFINITIONS})
+
+if(WITH_GLEW_MX)
+ add_definitions(-DGLEW_MX)
+endif()
+
+
+blender_add_lib(extern_glew_es "${SRC}" "${INC}" "${INC_SYS}")
diff --git a/extern/glew-es/SConscript b/extern/glew-es/SConscript
new file mode 100644
index 00000000000..7552ce84067
--- /dev/null
+++ b/extern/glew-es/SConscript
@@ -0,0 +1,16 @@
+#!/usr/bin/python
+import sys
+import os
+
+Import('env')
+
+sources = ['src/glew.c']
+
+defs = []
+defs += env['BF_GL_DEFINITIONS']
+
+if env['WITH_BF_GLEW_MX']:
+ defs += ['GLEW_MX']
+incs = ['include']
+
+env.BlenderLib ( 'extern_glew_es', sources, incs, defs, libtype=['extern','player'], priority=[50,230] )
diff --git a/extern/glew-es/include/GL/eglew.h b/extern/glew-es/include/GL/eglew.h
new file mode 100644
index 00000000000..e1eb1be44d1
--- /dev/null
+++ b/extern/glew-es/include/GL/eglew.h
@@ -0,0 +1,1470 @@
+/*
+** The OpenGL Extension Wrangler Library
+** Copyright (C) 2002-2008, Milan Ikits <milan ikits[]ieee org>
+** Copyright (C) 2002-2008, Marcelo E. Magallon <mmagallo[]debian org>
+** Copyright (C) 2002, Lev Povalahev
+** 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.
+** * The name of the author 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.
+*/
+
+/*
+** Copyright (c) 2007 The Khronos Group Inc.
+**
+** Permission is hereby granted, free of charge, to any person obtaining a
+** copy of this software and/or associated documentation files (the
+** "Materials"), to deal in the Materials without restriction, including
+** without limitation the rights to use, copy, modify, merge, publish,
+** distribute, sublicense, and/or sell copies of the Materials, and to
+** permit persons to whom the Materials are furnished to do so, subject to
+** the following conditions:
+**
+** The above copyright notice and this permission notice shall be included
+** in all copies or substantial portions of the Materials.
+**
+** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+*/
+
+/*
+** License Applicability. Except to the extent portions of this file are
+** made subject to an alternative license as permitted in the SGI Free
+** Software License B, Version 1.0 (the "License"), the contents of this
+** file are subject only to the provisions of the License. You may not use
+** this file except in compliance with the License. You may obtain a copy
+** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
+** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
+**
+** http://oss.sgi.com/projects/FreeB
+**
+** Note that, as provided in the License, the Software is distributed on an
+** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
+** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
+** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
+** PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
+**
+** Original Code. The Original Code is: OpenGL Sample Implementation,
+** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
+** Inc. The Original Code is Copyright (c) 1991-2004 Silicon Graphics, Inc.
+** Copyright in any portions created by third parties is as indicated
+** elsewhere herein. All Rights Reserved.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+*/
+
+/*
+** Copyright (c) 2007-2009 The Khronos Group Inc.
+**
+** Permission is hereby granted, free of charge, to any person obtaining a
+** copy of this software and/or associated documentation files (the
+** "Materials"), to deal in the Materials without restriction, including
+** without limitation the rights to use, copy, modify, merge, publish,
+** distribute, sublicense, and/or sell copies of the Materials, and to
+** permit persons to whom the Materials are furnished to do so, subject to
+** the following conditions:
+**
+** The above copyright notice and this permission notice shall be included
+** in all copies or substantial portions of the Materials.
+**
+** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+*/
+
+/* Platform-specific types and definitions for egl.h
+ * $Revision: 12306 $ on $Date: 2010-08-25 09:51:28 -0700 (Wed, 25 Aug 2010) $
+ *
+ * Adopters may modify khrplatform.h and this file to suit their platform.
+ * You are encouraged to submit all modifications to the Khronos group so that
+ * they can be included in future versions of this file. Please submit changes
+ * by sending them to the public Khronos Bugzilla (http://khronos.org/bugzilla)
+ * by filing a bug against product "EGL" component "Registry".
+ */
+
+/* Copyright © 2011 Linaro Limited
+ */
+
+#ifndef __eglew_h__
+#define __eglew_h__
+#define __EGLEW_H__
+
+
+#if defined(__egl_h_) || defined (__EGL_H_)
+#error egl.h included before glew.h
+#endif
+#if defined(__eglext_h_) || defined (__EGLEXT_H_)
+#error eglext.h included before glew.h
+#endif
+#if defined(__eglplatform_h_) || defined (__EGLPLATFORM_H_)
+#error eglplatform.h included before glew.h
+#endif
+#if defined(GLES_EGLTYPES_H) || defined (gles_egltypes_h)
+#error egltypes.h.h included before glew.h
+#endif
+
+#define __egl_h_
+#define __EGL_H_
+#define __eglext_h_
+#define __EGLEXT_H_
+#define GLES_EGLTYPES_H
+#define gles_egltypes_h
+#define __eglplatform_h_
+#define __EGLPLATFORM_H_
+
+/* TODO insert license */
+
+/* Includes */
+#include <GL/glew.h>
+
+/* Macros used in EGL function prototype declarations.
+ *
+ * EGL functions should be prototyped as:
+ *
+ * EGLAPI return-type EGLAPIENTRY eglFunction(arguments);
+ * typedef return-type (EXPAPIENTRYP PFNEGLFUNCTIONPROC) (arguments);
+ *
+ * KHRONOS_APICALL and KHRONOS_APIENTRY are defined in KHR/khrplatform.h
+ */
+
+#ifndef EGLAPI
+#define EGLAPI KHRONOS_APICALL
+#endif
+
+#ifndef EGLAPIENTRY
+#define EGLAPIENTRY KHRONOS_APIENTRY
+#endif
+#define EGLAPIENTRYP EGLAPIENTRY*
+
+/* The types NativeDisplayType, NativeWindowType, and NativePixmapType
+ * are aliases of window-system-dependent types, such as X Display * or
+ * Windows Device Context. They must be defined in platform-specific
+ * code below. The EGL-prefixed versions of Native*Type are the same
+ * types, renamed in EGL 1.3 so all types in the API start with "EGL".
+ *
+ * Khronos STRONGLY RECOMMENDS that you use the default definitions
+ * provided below, since these changes affect both binary and source
+ * portability of applications using EGL running on different EGL
+ * implementations.
+ */
+
+#if defined(_WIN32) || defined(__VC32__) && !defined(__CYGWIN__) && !defined(__SCITECH_SNAP__) /* Win32 and WinCE */
+#ifndef WIN32_LEAN_AND_MEAN
+#define WIN32_LEAN_AND_MEAN 1
+#endif
+#include <windows.h>
+
+typedef HDC EGLNativeDisplayType;
+typedef HBITMAP EGLNativePixmapType;
+typedef HWND EGLNativeWindowType;
+
+#elif defined(__WINSCW__) || defined(__SYMBIAN32__) /* Symbian */
+
+typedef int EGLNativeDisplayType;
+typedef void *EGLNativeWindowType;
+typedef void *EGLNativePixmapType;
+
+#elif defined(__unix__)
+
+/* X11 (tentative) */
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+
+typedef Display *EGLNativeDisplayType;
+typedef Pixmap EGLNativePixmapType;
+typedef Window EGLNativeWindowType;
+
+#elif defined(__APPLE__)
+
+typedef void *EGLNativeDisplayType;
+typedef void *EGLNativePixmapType;
+typedef void *EGLNativeWindowType;
+
+#endif
+
+/* EGL 1.2 types, renamed for consistency in EGL 1.3 */
+typedef EGLNativeDisplayType NativeDisplayType;
+typedef EGLNativePixmapType NativePixmapType;
+typedef EGLNativeWindowType NativeWindowType;
+
+
+/* Define EGLint. This must be a signed integral type large enough to contain
+ * all legal attribute names and values passed into and out of EGL, whether
+ * their type is boolean, bitmask, enumerant (symbolic constant), integer,
+ * handle, or other. While in general a 32-bit integer will suffice, if
+ * handles are 64 bit types, then EGLint should be defined as a signed 64-bit
+ * integer type.
+ */
+typedef khronos_int32_t EGLint;
+
+
+/* Basic types */
+typedef int EGLBoolean;
+
+/* Internal types */
+typedef void *EGLDisplay;
+typedef void *EGLConfig;
+typedef void *EGLSurface;
+typedef void *EGLContext;
+
+/* Handle values */
+#define EGL_DEFAULT_DISPLAY ((EGLNativeDisplayType)-1)
+#define EGL_NO_CONTEXT ((EGLContext)0)
+#define EGL_NO_DISPLAY ((EGLDisplay)0)
+#define EGL_NO_SURFACE ((EGLSurface)0)
+#define EGL_UNKNOWN ((EGLint)-1)
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* ----------------------------- EGL_VERSION_1_1 ---------------------------- */
+
+#ifndef EGL_VERSION_1_1
+#define EGL_VERSION_1_0 1
+#define EGL_VERSION_1_1 1
+
+/*
+** Boolean
+*/
+#define EGL_FALSE 0
+#define EGL_TRUE 1
+
+/*
+** Errors
+*/
+#define EGL_SUCCESS 0x3000
+#define EGL_NOT_INITIALIZED 0x3001
+#define EGL_BAD_ACCESS 0x3002
+#define EGL_BAD_ALLOC 0x3003
+#define EGL_BAD_ATTRIBUTE 0x3004
+#define EGL_BAD_CONFIG 0x3005
+#define EGL_BAD_CONTEXT 0x3006
+#define EGL_BAD_CURRENT_SURFACE 0x3007
+#define EGL_BAD_DISPLAY 0x3008
+#define EGL_BAD_MATCH 0x3009
+#define EGL_BAD_NATIVE_PIXMAP 0x300A
+#define EGL_BAD_NATIVE_WINDOW 0x300B
+#define EGL_BAD_PARAMETER 0x300C
+#define EGL_BAD_SURFACE 0x300D
+#define EGL_CONTEXT_LOST 0x300E
+/* 0x300F - 0x301F reserved for additional errors. */
+
+/*
+** Config attributes
+*/
+#define EGL_BUFFER_SIZE 0x3020
+#define EGL_ALPHA_SIZE 0x3021
+#define EGL_BLUE_SIZE 0x3022
+#define EGL_GREEN_SIZE 0x3023
+#define EGL_RED_SIZE 0x3024
+#define EGL_DEPTH_SIZE 0x3025
+#define EGL_STENCIL_SIZE 0x3026
+#define EGL_CONFIG_CAVEAT 0x3027
+#define EGL_CONFIG_ID 0x3028
+#define EGL_LEVEL 0x3029
+#define EGL_MAX_PBUFFER_HEIGHT 0x302A
+#define EGL_MAX_PBUFFER_PIXELS 0x302B
+#define EGL_MAX_PBUFFER_WIDTH 0x302C
+#define EGL_NATIVE_RENDERABLE 0x302D
+#define EGL_NATIVE_VISUAL_ID 0x302E
+#define EGL_NATIVE_VISUAL_TYPE 0x302F
+/*#define EGL_PRESERVED_RESOURCES 0x3030*/
+#define EGL_SAMPLES 0x3031
+#define EGL_SAMPLE_BUFFERS 0x3032
+#define EGL_SURFACE_TYPE 0x3033
+#define EGL_TRANSPARENT_TYPE 0x3034
+#define EGL_TRANSPARENT_BLUE_VALUE 0x3035
+#define EGL_TRANSPARENT_GREEN_VALUE 0x3036
+#define EGL_TRANSPARENT_RED_VALUE 0x3037
+#define EGL_NONE 0x3038 /* Also a config value */
+#define EGL_BIND_TO_TEXTURE_RGB 0x3039
+#define EGL_BIND_TO_TEXTURE_RGBA 0x303A
+#define EGL_MIN_SWAP_INTERVAL 0x303B
+#define EGL_MAX_SWAP_INTERVAL 0x303C
+
+/*
+** Config values
+*/
+#define EGL_DONT_CARE ((EGLint) -1)
+
+#define EGL_SLOW_CONFIG 0x3050 /* EGL_CONFIG_CAVEAT value */
+#define EGL_NON_CONFORMANT_CONFIG 0x3051 /* " */
+#define EGL_TRANSPARENT_RGB 0x3052 /* EGL_TRANSPARENT_TYPE value */
+#define EGL_NO_TEXTURE 0x305C /* EGL_TEXTURE_FORMAT/TARGET value */
+#define EGL_TEXTURE_RGB 0x305D /* EGL_TEXTURE_FORMAT value */
+#define EGL_TEXTURE_RGBA 0x305E /* " */
+#define EGL_TEXTURE_2D 0x305F /* EGL_TEXTURE_TARGET value */
+
+/*
+** Config attribute mask bits
+*/
+#define EGL_PBUFFER_BIT 0x01 /* EGL_SURFACE_TYPE mask bit */
+#define EGL_PIXMAP_BIT 0x02 /* " */
+#define EGL_WINDOW_BIT 0x04 /* " */
+
+/*
+** String names
+*/
+#define EGL_VENDOR 0x3053 /* eglQueryString target */
+#define EGL_VERSION 0x3054 /* " */
+#define EGL_EXTENSIONS 0x3055 /* " */
+
+/*
+** Surface attributes
+*/
+#define EGL_HEIGHT 0x3056
+#define EGL_WIDTH 0x3057
+#define EGL_LARGEST_PBUFFER 0x3058
+#define EGL_TEXTURE_FORMAT 0x3080 /* For pbuffers bound as textures */
+#define EGL_TEXTURE_TARGET 0x3081 /* " */
+#define EGL_MIPMAP_TEXTURE 0x3082 /* " */
+#define EGL_MIPMAP_LEVEL 0x3083 /* " */
+
+/*
+** BindTexImage / ReleaseTexImage buffer target
+*/
+#define EGL_BACK_BUFFER 0x3084
+
+/*
+** Current surfaces
+*/
+#define EGL_DRAW 0x3059
+#define EGL_READ 0x305A
+
+/*
+** Engines
+*/
+#define EGL_CORE_NATIVE_ENGINE 0x305B
+
+/* 0x305C-0x3FFFF reserved for future use */
+
+/*
+** Functions
+*/
+
+EGLAPI EGLint EGLAPIENTRY eglGetError (void);
+
+EGLAPI EGLDisplay EGLAPIENTRY eglGetDisplay (NativeDisplayType display);
+EGLAPI EGLBoolean EGLAPIENTRY eglInitialize (EGLDisplay dpy, EGLint *major, EGLint *minor);
+EGLAPI EGLBoolean EGLAPIENTRY eglTerminate (EGLDisplay dpy);
+EGLAPI const char * EGLAPIENTRY eglQueryString (EGLDisplay dpy, EGLint name);
+EGLAPI void (* EGLAPIENTRY eglGetProcAddress (const char *procname))();
+
+EGLAPI EGLBoolean EGLAPIENTRY eglGetConfigs (EGLDisplay dpy, EGLConfig *configs, EGLint config_size, EGLint *num_config);
+EGLAPI EGLBoolean EGLAPIENTRY eglChooseConfig (EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs, EGLint config_size, EGLint *num_config);
+EGLAPI EGLBoolean EGLAPIENTRY eglGetConfigAttrib (EGLDisplay dpy, EGLConfig config, EGLint attribute, EGLint *value);
+
+EGLAPI EGLSurface EGLAPIENTRY eglCreateWindowSurface (EGLDisplay dpy, EGLConfig config, NativeWindowType window, const EGLint *attrib_list);
+EGLAPI EGLSurface EGLAPIENTRY eglCreatePixmapSurface (EGLDisplay dpy, EGLConfig config, NativePixmapType pixmap, const EGLint *attrib_list);
+EGLAPI EGLSurface EGLAPIENTRY eglCreatePbufferSurface (EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list);
+EGLAPI EGLBoolean EGLAPIENTRY eglDestroySurface (EGLDisplay dpy, EGLSurface surface);
+EGLAPI EGLBoolean EGLAPIENTRY eglQuerySurface (EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint *value);
+
+/* EGL 1.1 render-to-texture APIs */
+EGLAPI EGLBoolean EGLAPIENTRY eglSurfaceAttrib (EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value);
+EGLAPI EGLBoolean EGLAPIENTRY eglBindTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer);
+EGLAPI EGLBoolean EGLAPIENTRY eglReleaseTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer);
+
+/* EGL 1.1 swap control API */
+EGLAPI EGLBoolean EGLAPIENTRY eglSwapInterval(EGLDisplay dpy, EGLint interval);
+
+EGLAPI EGLContext EGLAPIENTRY eglCreateContext (EGLDisplay dpy, EGLConfig config, EGLContext share_list, const EGLint *attrib_list);
+EGLAPI EGLBoolean EGLAPIENTRY eglDestroyContext (EGLDisplay dpy, EGLContext ctx);
+EGLAPI EGLBoolean EGLAPIENTRY eglMakeCurrent (EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx);
+EGLAPI EGLContext EGLAPIENTRY eglGetCurrentContext (void);
+EGLAPI EGLSurface EGLAPIENTRY eglGetCurrentSurface (EGLint readdraw);
+EGLAPI EGLDisplay EGLAPIENTRY eglGetCurrentDisplay (void);
+EGLAPI EGLBoolean EGLAPIENTRY eglQueryContext (EGLDisplay dpy, EGLContext ctx, EGLint attribute, EGLint *value);
+
+EGLAPI EGLBoolean EGLAPIENTRY eglWaitGL (void);
+EGLAPI EGLBoolean EGLAPIENTRY eglWaitNative (EGLint engine);
+EGLAPI EGLBoolean EGLAPIENTRY eglSwapBuffers (EGLDisplay dpy, EGLSurface draw);
+EGLAPI EGLBoolean EGLAPIENTRY eglCopyBuffers (EGLDisplay dpy, EGLSurface surface, NativePixmapType target);
+
+#define EGLEW_VERSION_1_1 EGLEW_GET_VAR(__EGLEW_VERSION_1_1)
+
+#endif /* EGL_VERSION_1_1 */
+
+/* ---------------------------- EGL_VERSION_1_2 ---------------------------- */
+
+#if !defined(EGL_VERSION_1_2)
+#define EGL_VERSION_1_2 1
+
+#define EGL_OPENGL_ES_BIT 0x01
+#define EGL_OPENVG_BIT 0x02
+#define EGL_PRESERVED_RESOURCES 0x3030
+#define EGL_LUMINANCE_SIZE 0x303D
+#define EGL_ALPHA_MASK_SIZE 0x303E
+#define EGL_COLOR_BUFFER_TYPE 0x303F
+#define EGL_RENDERABLE_TYPE 0x3040
+#define EGL_SINGLE_BUFFER 0x3085
+#define EGL_RENDER_BUFFER 0x3086
+#define EGL_COLORSPACE 0x3087
+#define EGL_ALPHA_FORMAT 0x3088
+#define EGL_COLORSPACE_sRGB 0x3089
+#define EGL_COLORSPACE_LINEAR 0x308A
+#define EGL_ALPHA_FORMAT_NONPRE 0x308B
+#define EGL_ALPHA_FORMAT_PRE 0x308C
+#define EGL_CLIENT_APIS 0x308D
+#define EGL_RGB_BUFFER 0x308E
+#define EGL_LUMINANCE_BUFFER 0x308F
+#define EGL_HORIZONTAL_RESOLUTION 0x3090
+#define EGL_VERTICAL_RESOLUTION 0x3091
+#define EGL_PIXEL_ASPECT_RATIO 0x3092
+#define EGL_SWAP_BEHAVIOR 0x3093
+#define EGL_BUFFER_PRESERVED 0x3094
+#define EGL_BUFFER_DESTROYED 0x3095
+#define EGL_OPENVG_IMAGE 0x3096
+#define EGL_CONTEXT_CLIENT_TYPE 0x3097
+#define EGL_OPENGL_ES_API 0x30A0
+#define EGL_OPENVG_API 0x30A1
+#define EGL_DISPLAY_SCALING 10000
+
+typedef unsigned int EGLenum;
+typedef void *EGLClientBuffer;
+
+typedef EGLBoolean (EGLAPIENTRY * PFNEGLBINDAPIPROC) (EGLenum);
+typedef EGLSurface (EGLAPIENTRY * PFNEGLCREATEPBUFFERFROMCLIENTBUFFERPROC) (EGLDisplay, EGLenum, EGLClientBuffer, EGLConfig, const EGLint *);
+typedef EGLenum (EGLAPIENTRY * PFNEGLQUERYAPIPROC) (void);
+typedef EGLBoolean (EGLAPIENTRY * PFNEGLRELEASETHREADPROC) (void);
+typedef EGLBoolean (EGLAPIENTRY * PFNEGLWAITCLIENTPROC) (void);
+
+#define eglBindAPI EGLEW_GET_FUN(__eglewBindAPI)
+#define eglCreatePbufferFromClientBuffer EGLEW_GET_FUN(__eglewCreatePbufferFromClientBuffer)
+#define eglQueryAPI EGLEW_GET_FUN(__eglewQueryAPI)
+#define eglReleaseThread EGLEW_GET_FUN(__eglewReleaseThread)
+#define eglWaitClient EGLEW_GET_FUN(__eglewWaitClient)
+
+#define EGLEW_VERSION_1_2 EGLEW_GET_VAR(__EGLEW_VERSION_1_2)
+
+#endif /* !EGL_VERSION_1_2 */
+
+/* ---------------------------- EGL_VERSION_1_3 ---------------------------- */
+
+#if !defined(EGL_VERSION_1_3)
+#define EGL_VERSION_1_3 1
+
+#define EGL_OPENGL_ES2_BIT 0x04
+#define EGL_MATCH_NATIVE_PIXMAP 0x3041
+#define EGL_CONTEXT_CLIENT_VERSION 0x3098
+
+#define EGLEW_VERSION_1_3 EGLEW_GET_VAR(__EGLEW_VERSION_1_3)
+
+#endif /* !EGL_VERSION_1_3 */
+
+/* ---------------------------- EGL_VERSION_1_4 ---------------------------- */
+
+#if !defined(EGL_VERSION_1_4)
+#define EGL_VERSION_1_4 1
+
+#define EGL_OPENGL_BIT 0x0008
+#define EGL_VG_COLORSPACE_LINEAR_BIT 0x0020
+#define EGL_VG_ALPHA_FORMAT_PRE_BIT 0x0040
+#define EGL_MULTISAMPLE_RESOLVE_BOX_BIT 0x0200
+#define EGL_SWAP_BEHAVIOR_PRESERVED_BIT 0x0400
+#define EGL_VG_COLORSPACE 0x3087
+#define EGL_VG_ALPHA_FORMAT 0x3088
+#define EGL_VG_COLORSPACE_sRGB 0x3089
+#define EGL_VG_COLORSPACE_LINEAR 0x308A
+#define EGL_VG_ALPHA_FORMAT_NONPRE 0x308B
+#define EGL_VG_ALPHA_FORMAT_PRE 0x308C
+#define EGL_MULTISAMPLE_RESOLVE 0x3099
+#define EGL_MULTISAMPLE_RESOLVE_DEFAULT 0x309A
+#define EGL_MULTISAMPLE_RESOLVE_BOX 0x309B
+#define EGL_OPENGL_API 0x30A2
+
+typedef void (*__eglMustCastToProperFunctionPointerType)(void);
+
+#define EGLEW_VERSION_1_4 EGLEW_GET_VAR(__EGLEW_VERSION_1_4)
+
+#endif /* !EGL_VERSION_1_4 */
+
+/* ---------------------------- EGL_VERSION_1_5 ---------------------------- */
+
+#if !defined(EGL_VERSION_1_5)
+#define EGL_VERSION_1_5 1
+
+typedef void *EGLSync;
+typedef intptr_t EGLAttrib;
+typedef khronos_utime_nanoseconds_t EGLTime;
+#define EGL_CONTEXT_MAJOR_VERSION 0x3098
+#define EGL_CONTEXT_MINOR_VERSION 0x30FB
+#define EGL_CONTEXT_OPENGL_PROFILE_MASK 0x30FD
+#define EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY 0x31BD
+#define EGL_NO_RESET_NOTIFICATION 0x31BE
+#define EGL_LOSE_CONTEXT_ON_RESET 0x31BF
+#define EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT 0x00000001
+#define EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT 0x00000002
+#define EGL_CONTEXT_OPENGL_DEBUG 0x31B0
+#define EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE 0x31B1
+#define EGL_CONTEXT_OPENGL_ROBUST_ACCESS 0x31B2
+#define EGL_OPENGL_ES3_BIT 0x00000040
+#define EGL_CL_EVENT_HANDLE 0x309C
+#define EGL_SYNC_CL_EVENT 0x30FE
+#define EGL_SYNC_CL_EVENT_COMPLETE 0x30FF
+#define EGL_SYNC_PRIOR_COMMANDS_COMPLETE 0x30F0
+#define EGL_SYNC_TYPE 0x30F7
+#define EGL_SYNC_STATUS 0x30F1
+#define EGL_SYNC_CONDITION 0x30F8
+#define EGL_SIGNALED 0x30F2
+#define EGL_UNSIGNALED 0x30F3
+#define EGL_SYNC_FLUSH_COMMANDS_BIT 0x0001
+#define EGL_FOREVER 0xFFFFFFFFFFFFFFFFull
+#define EGL_TIMEOUT_EXPIRED 0x30F5
+#define EGL_CONDITION_SATISFIED 0x30F6
+#define EGL_NO_SYNC ((EGLSync)0)
+#define EGL_SYNC_FENCE 0x30F9
+#define EGL_GL_COLORSPACE 0x309D
+#define EGL_GL_COLORSPACE_SRGB 0x3089
+#define EGL_GL_COLORSPACE_LINEAR 0x308A
+#define EGL_GL_RENDERBUFFER 0x30B9
+#define EGL_GL_TEXTURE_2D 0x30B1
+#define EGL_GL_TEXTURE_LEVEL 0x30BC
+#define EGL_GL_TEXTURE_3D 0x30B2
+#define EGL_GL_TEXTURE_ZOFFSET 0x30BD
+#define EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X 0x30B3
+#define EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X 0x30B4
+#define EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y 0x30B5
+#define EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y 0x30B6
+#define EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z 0x30B7
+#define EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z 0x30B8
+
+typedef EGLSync (EGLAPIENTRY * PFNCREATESYNC ) (EGLDisplay dpy, EGLenum type, const EGLAttrib *attrib_list);
+typedef EGLBoolean (EGLAPIENTRY * PFNDESTROYSYNC ) (EGLDisplay dpy, EGLSync sync);
+typedef EGLint (EGLAPIENTRY * PFNCLIENTWAITSYNC ) (EGLDisplay dpy, EGLSync sync, EGLint flags, EGLTime timeout);
+typedef EGLBoolean (EGLAPIENTRY * PFNGETSYNCATTRIB ) (EGLDisplay dpy, EGLSync sync, EGLint attribute, EGLAttrib *value);
+typedef EGLDisplay (EGLAPIENTRY * PFNGETPLATFORMDISPLAY ) (EGLenum platform, void *native_display, const EGLAttrib *attrib_list);
+typedef EGLSurface (EGLAPIENTRY * PFNCREATEPLATFORMWINDOWSURFACE) (EGLDisplay dpy, EGLConfig config, void *native_window, const EGLAttrib *attrib_list);
+typedef EGLSurface (EGLAPIENTRY * PFNCREATEPLATFORMPIXMAPSURFACE) (EGLDisplay dpy, EGLConfig config, void *native_pixmap, const EGLAttrib *attrib_list);
+typedef EGLBoolean (EGLAPIENTRY * PFNWAITSYNC ) (EGLDisplay dpy, EGLSync sync, EGLint flags);
+
+#define eglCreateSync EGLEW_GET_FUN(__eglewCreateSync )
+#define eglDestroySync EGLEW_GET_FUN(__eglewDestroySync )
+#define eglClientWaitSync EGLEW_GET_FUN(__eglewClientWaitSync )
+#define eglGetSyncAttrib EGLEW_GET_FUN(__eglewGetSyncAttrib )
+#define eglGetPlatformDisplay EGLEW_GET_FUN(__eglewGetPlatformDisplay )
+#define eglCreatePlatformWindowSurface EGLEW_GET_FUN(__eglewCreatePlatformWindowSurface)
+#define eglCreatePlatformPixmapSurface EGLEW_GET_FUN(__eglewCreatePlatformPixmapSurface)
+#define eglWaitSync EGLEW_GET_FUN(__eglewWaitSync )
+
+#define EGLEW_VERSION_1_5 EGLEW_GET_VAR(__EGLEW_VERSION_1_5)
+
+#endif /* !EGL_VERSION_1_5 */
+
+/* ------------------------- EGL_ANDROID_blob_cache ------------------------ */
+
+#if !defined(EGL_ANDROID_blob_cache)
+#define EGL_ANDROID_blob_cache 1
+
+typedef khronos_ssize_t EGLsizeiANDROID; // NOTE jwilkins: missing typedef
+typedef EGLsizeiANDROID (*EGLGetBlobFuncANDROID) (const void* key, EGLsizeiANDROID keySize, void* value, EGLsizeiANDROID valueSize); // NOTE jwilkins: missing typedef
+typedef void (*EGLSetBlobFuncANDROID) (const void* key, EGLsizeiANDROID keySize, const void* value, EGLsizeiANDROID valueSize); // NOTE jwilkins: missing typedef
+
+typedef void (EGLAPIENTRY * PFNEGLSETBLOBCACHEFUNCSANDROIDPROC) (EGLDisplay dpy, EGLSetBlobFuncANDROID set, EGLGetBlobFuncANDROID get);
+
+#define eglSetBlobCacheFuncsANDROID EGLEW_GET_FUN(__eglewSetBlobCacheFuncsANDROID)
+
+#define EGLEW_ANDROID_blob_cache EGLEW_GET_VAR(__EGLEW_ANDROID_blob_cache)
+
+#endif /* !EGL_ANDROID_blob_cache */
+
+/* --------------------- EGL_ANDROID_framebuffer_target -------------------- */
+
+#if !defined(EGL_ANDROID_framebuffer_target)
+#define EGL_ANDROID_framebuffer_target 1
+
+#define EGL_FRAMEBUFFER_TARGET_ANDROID 0x3147
+
+#define EGLEW_ANDROID_framebuffer_target EGLEW_GET_VAR(__EGLEW_ANDROID_framebuffer_target)
+
+#endif /* !EGL_ANDROID_framebuffer_target */
+
+/* -------------------- EGL_ANDROID_image_native_buffer -------------------- */
+
+#if !defined(EGL_ANDROID_image_native_buffer)
+#define EGL_ANDROID_image_native_buffer 1
+
+#define EGL_NATIVE_BUFFER_ANDROID 0x3140
+
+#define EGLEW_ANDROID_image_native_buffer EGLEW_GET_VAR(__EGLEW_ANDROID_image_native_buffer)
+
+#endif /* !EGL_ANDROID_image_native_buffer */
+
+/* --------------------- EGL_ANDROID_native_fence_sync --------------------- */
+
+#if !defined(EGL_ANDROID_native_fence_sync)
+#define EGL_ANDROID_native_fence_sync 1
+
+typedef void* EGLSyncKHR; // NOTE jwilkins: missing typedef
+
+#define EGL_SYNC_NATIVE_FENCE_ANDROID 0x3144
+#define EGL_SYNC_NATIVE_FENCE_FD_ANDROID 0x3145
+#define EGL_SYNC_NATIVE_FENCE_SIGNALED_ANDROID 0x3146
+
+typedef EGLint (EGLAPIENTRY * PFNEGLDUPNATIVEFENCEFDANDROIDPROC) (EGLDisplay dpy, EGLSyncKHR);
+
+#define eglDupNativeFenceFDANDROID EGLEW_GET_FUN(__eglewDupNativeFenceFDANDROID)
+
+#define EGLEW_ANDROID_native_fence_sync EGLEW_GET_VAR(__EGLEW_ANDROID_native_fence_sync)
+
+#endif /* !EGL_ANDROID_native_fence_sync */
+
+/* ------------------------- EGL_ANDROID_recordable ------------------------ */
+
+#if !defined(EGL_ANDROID_recordable)
+#define EGL_ANDROID_recordable 1
+
+#define EGL_RECORDABLE_ANDROID 0x3142
+
+#define EGLEW_ANDROID_recordable EGLEW_GET_VAR(__EGLEW_ANDROID_recordable)
+
+#endif /* !EGL_ANDROID_recordable */
+
+/* ---------------- EGL_ANGLE_d3d_share_handle_client_buffer --------------- */
+
+#if !defined(EGL_ANGLE_d3d_share_handle_client_buffer)
+#define EGL_ANGLE_d3d_share_handle_client_buffer 1
+
+#define EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE 0x3200
+
+#define EGLEW_ANGLE_d3d_share_handle_client_buffer EGLEW_GET_VAR(__EGLEW_ANGLE_d3d_share_handle_client_buffer)
+
+#endif /* !EGL_ANGLE_d3d_share_handle_client_buffer */
+
+/* -------------------- EGL_ANGLE_query_surface_pointer -------------------- */
+
+#if !defined(EGL_ANGLE_query_surface_pointer)
+#define EGL_ANGLE_query_surface_pointer 1
+
+typedef EGLBoolean (EGLAPIENTRY * PFNEGLQUERYSURFACEPOINTERANGLEPROC) (EGLDisplay dpy, EGLSurface surface, EGLint attribute, void ** value);
+
+#define eglQuerySurfacePointerANGLE EGLEW_GET_FUN(__eglewQuerySurfacePointerANGLE)
+
+#define EGLEW_ANGLE_query_surface_pointer EGLEW_GET_VAR(__EGLEW_ANGLE_query_surface_pointer)
+
+#endif /* !EGL_ANGLE_query_surface_pointer */
+
+/* ------------- EGL_ANGLE_surface_d3d_texture_2d_share_handle ------------- */
+
+#if !defined(EGL_ANGLE_surface_d3d_texture_2d_share_handle)
+#define EGL_ANGLE_surface_d3d_texture_2d_share_handle 1
+
+#define EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE 0x3200
+
+#define EGLEW_ANGLE_surface_d3d_texture_2d_share_handle EGLEW_GET_VAR(__EGLEW_ANGLE_surface_d3d_texture_2d_share_handle)
+
+#endif /* !EGL_ANGLE_surface_d3d_texture_2d_share_handle */
+
+/* --------------------------- EGL_EXT_buffer_age -------------------------- */
+
+#if !defined(EGL_EXT_buffer_age)
+#define EGL_EXT_buffer_age 1
+
+#define EGL_BUFFER_AGE_EXT 0x313D
+
+#define EGLEW_EXT_buffer_age EGLEW_GET_VAR(__EGLEW_EXT_buffer_age)
+
+#endif /* !EGL_EXT_buffer_age */
+
+/* ------------------- EGL_EXT_create_context_robustness ------------------- */
+
+#if !defined(EGL_EXT_create_context_robustness)
+#define EGL_EXT_create_context_robustness 1
+
+#define EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT 0x30BF
+#define EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT 0x3138
+#define EGL_NO_RESET_NOTIFICATION_EXT 0x31BE
+#define EGL_LOSE_CONTEXT_ON_RESET_EXT 0x31BF
+
+#define EGLEW_EXT_create_context_robustness EGLEW_GET_VAR(__EGLEW_EXT_create_context_robustness)
+
+#endif /* !EGL_EXT_create_context_robustness */
+
+/* ------------------------ EGL_EXT_multiview_window ----------------------- */
+
+#if !defined(EGL_EXT_multiview_window)
+#define EGL_EXT_multiview_window 1
+
+#define EGL_MULTIVIEW_VIEW_COUNT_EXT 0x3134
+
+#define EGLEW_EXT_multiview_window EGLEW_GET_VAR(__EGLEW_EXT_multiview_window)
+
+#endif /* !EGL_EXT_multiview_window */
+
+/* -------------------------- EGL_HI_clientpixmap -------------------------- */
+
+#if !defined(EGL_HI_clientpixmap)
+#define EGL_HI_clientpixmap 1
+
+#define EGLEW_HI_clientpixmap EGLEW_GET_VAR(__EGLEW_HI_clientpixmap)
+
+#endif /* !EGL_HI_clientpixmap */
+
+/* -------------------------- EGL_HI_colorformats -------------------------- */
+
+#if !defined(EGL_HI_colorformats)
+#define EGL_HI_colorformats 1
+
+#define EGL_COLOR_FORMAT_HI 0x8F70
+#define EGL_COLOR_RGB_HI 0x8F71
+#define EGL_COLOR_RGBA_HI 0x8F72
+#define EGL_COLOR_ARGB_HI 0x8F73
+
+#define EGLEW_HI_colorformats EGLEW_GET_VAR(__EGLEW_HI_colorformats)
+
+#endif /* !EGL_HI_colorformats */
+
+/* ------------------------ EGL_IMG_context_priority ----------------------- */
+
+#if !defined(EGL_IMG_context_priority)
+#define EGL_IMG_context_priority 1
+
+#define EGL_CONTEXT_PRIORITY_LEVEL_IMG 0x3100
+#define EGL_CONTEXT_PRIORITY_HIGH_IMG 0x3101
+#define EGL_CONTEXT_PRIORITY_MEDIUM_IMG 0x3102
+#define EGL_CONTEXT_PRIORITY_LOW_IMG 0x3103
+
+#define EGLEW_IMG_context_priority EGLEW_GET_VAR(__EGLEW_IMG_context_priority)
+
+#endif /* !EGL_IMG_context_priority */
+
+/* ------------------------- EGL_KHR_config_attribs ------------------------ */
+
+#if !defined(EGL_KHR_config_attribs)
+#define EGL_KHR_config_attribs 1
+
+#define EGL_VG_COLORSPACE_LINEAR_BIT_KHR 0x0020
+#define EGL_VG_ALPHA_FORMAT_PRE_BIT_KHR 0x0040
+#define EGL_CONFORMANT_KHR 0x3042
+
+#define EGLEW_KHR_config_attribs EGLEW_GET_VAR(__EGLEW_KHR_config_attribs)
+
+#endif /* !EGL_KHR_config_attribs */
+
+/* ------------------------- EGL_KHR_create_context ------------------------ */
+
+#if !defined(EGL_KHR_create_context)
+#define EGL_KHR_create_context 1
+
+#define EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR 0x00000001
+#define EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR 0x00000001
+#define EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR 0x00000002
+#define EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR 0x00000002
+#define EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR 0x00000004
+#define EGL_OPENGL_ES3_BIT_KHR 0x0040
+#define EGL_CONTEXT_MAJOR_VERSION_KHR 0x3098
+#define EGL_CONTEXT_MINOR_VERSION_KHR 0x30FB
+#define EGL_CONTEXT_FLAGS_KHR 0x30FC
+#define EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR 0x30FD
+#define EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR 0x31BD
+#define EGL_NO_RESET_NOTIFICATION_KHR 0x31BE
+#define EGL_LOSE_CONTEXT_ON_RESET_KHR 0x31BF
+
+#define EGLEW_KHR_create_context EGLEW_GET_VAR(__EGLEW_KHR_create_context)
+
+#endif /* !EGL_KHR_create_context */
+
+/* --------------------------- EGL_KHR_fence_sync -------------------------- */
+
+#if !defined(EGL_KHR_fence_sync)
+#define EGL_KHR_fence_sync 1
+
+#define EGL_SYNC_PRIOR_COMMANDS_COMPLETE_KHR 0x30F0
+#define EGL_SYNC_CONDITION_KHR 0x30F8
+#define EGL_SYNC_FENCE_KHR 0x30F9
+
+#define EGLEW_KHR_fence_sync EGLEW_GET_VAR(__EGLEW_KHR_fence_sync)
+
+#endif /* !EGL_KHR_fence_sync */
+
+/* --------------------- EGL_KHR_gl_renderbuffer_image --------------------- */
+
+#if !defined(EGL_KHR_gl_renderbuffer_image)
+#define EGL_KHR_gl_renderbuffer_image 1
+
+#define EGLEW_KHR_gl_renderbuffer_image EGLEW_GET_VAR(__EGLEW_KHR_gl_renderbuffer_image)
+
+#endif /* !EGL_KHR_gl_renderbuffer_image */
+
+/* ---------------------- EGL_KHR_gl_texture_2D_image ---------------------- */
+
+#if !defined(EGL_KHR_gl_texture_2D_image)
+#define EGL_KHR_gl_texture_2D_image 1
+
+#define EGL_GL_TEXTURE_2D_KHR 0x30B1
+#define EGL_GL_TEXTURE_3D_KHR 0x30B2
+#define EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR 0x30B3
+#define EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X_KHR 0x30B4
+#define EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y_KHR 0x30B5
+#define EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_KHR 0x30B6
+#define EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z_KHR 0x30B7
+#define EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_KHR 0x30B8
+#define EGL_GL_RENDERBUFFER_KHR 0x30B9
+#define EGL_GL_TEXTURE_LEVEL_KHR 0x30BC
+#define EGL_GL_TEXTURE_ZOFFSET_KHR 0x30BD
+
+#define EGLEW_KHR_gl_texture_2D_image EGLEW_GET_VAR(__EGLEW_KHR_gl_texture_2D_image)
+
+#endif /* !EGL_KHR_gl_texture_2D_image */
+
+/* ---------------------- EGL_KHR_gl_texture_3D_image ---------------------- */
+
+#if !defined(EGL_KHR_gl_texture_3D_image)
+#define EGL_KHR_gl_texture_3D_image 1
+
+#define EGLEW_KHR_gl_texture_3D_image EGLEW_GET_VAR(__EGLEW_KHR_gl_texture_3D_image)
+
+#endif /* !EGL_KHR_gl_texture_3D_image */
+
+/* -------------------- EGL_KHR_gl_texture_cubemap_image ------------------- */
+
+#if !defined(EGL_KHR_gl_texture_cubemap_image)
+#define EGL_KHR_gl_texture_cubemap_image 1
+
+#define EGLEW_KHR_gl_texture_cubemap_image EGLEW_GET_VAR(__EGLEW_KHR_gl_texture_cubemap_image)
+
+#endif /* !EGL_KHR_gl_texture_cubemap_image */
+
+/* ----------------------------- EGL_KHR_image ----------------------------- */
+
+#if !defined(EGL_KHR_image)
+#define EGL_KHR_image 1
+
+#define EGLEW_KHR_image EGLEW_GET_VAR(__EGLEW_KHR_image)
+
+#endif /* !EGL_KHR_image */
+
+/* --------------------------- EGL_KHR_image_base -------------------------- */
+
+#if !defined(EGL_KHR_image_base)
+#define EGL_KHR_image_base 1
+
+#define EGL_IMAGE_PRESERVED_KHR 0x30D2
+
+typedef void *EGLImageKHR;
+
+typedef EGLImageKHR (EGLAPIENTRY * PFNEGLCREATEIMAGEKHRPROC) (EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLint* attrib_list);
+typedef EGLBoolean (EGLAPIENTRY * PFNEGLDESTROYIMAGEKHRPROC) (EGLDisplay dpy, EGLImageKHR image);
+
+#define eglCreateImageKHR EGLEW_GET_FUN(__eglewCreateImageKHR)
+#define eglDestroyImageKHR EGLEW_GET_FUN(__eglewDestroyImageKHR)
+
+#define EGLEW_KHR_image_base EGLEW_GET_VAR(__EGLEW_KHR_image_base)
+
+#endif /* !EGL_KHR_image_base */
+
+/* -------------------------- EGL_KHR_image_pixmap ------------------------- */
+
+#if !defined(EGL_KHR_image_pixmap)
+#define EGL_KHR_image_pixmap 1
+
+#define EGL_NATIVE_PIXMAP_KHR 0x30B0
+
+#define EGLEW_KHR_image_pixmap EGLEW_GET_VAR(__EGLEW_KHR_image_pixmap)
+
+#endif /* !EGL_KHR_image_pixmap */
+
+/* -------------------------- EGL_KHR_lock_surface ------------------------- */
+
+#if !defined(EGL_KHR_lock_surface)
+#define EGL_KHR_lock_surface 1
+
+#define EGL_READ_SURFACE_BIT_KHR 0x0001
+#define EGL_WRITE_SURFACE_BIT_KHR 0x0002
+#define EGL_LOCK_SURFACE_BIT_KHR 0x0080
+#define EGL_OPTIMAL_FORMAT_BIT_KHR 0x0100
+#define EGL_MATCH_FORMAT_KHR 0x3043
+#define EGL_FORMAT_RGB_565_EXACT_KHR 0x30C0
+#define EGL_FORMAT_RGB_565_KHR 0x30C1
+#define EGL_FORMAT_RGBA_8888_EXACT_KHR 0x30C2
+#define EGL_FORMAT_RGBA_8888_KHR 0x30C3
+#define EGL_MAP_PRESERVE_PIXELS_KHR 0x30C4
+#define EGL_LOCK_USAGE_HINT_KHR 0x30C5
+#define EGL_BITMAP_POINTER_KHR 0x30C6
+#define EGL_BITMAP_PITCH_KHR 0x30C7
+#define EGL_BITMAP_ORIGIN_KHR 0x30C8
+#define EGL_BITMAP_PIXEL_RED_OFFSET_KHR 0x30C9
+#define EGL_BITMAP_PIXEL_GREEN_OFFSET_KHR 0x30CA
+#define EGL_BITMAP_PIXEL_BLUE_OFFSET_KHR 0x30CB
+#define EGL_BITMAP_PIXEL_ALPHA_OFFSET_KHR 0x30CC
+#define EGL_BITMAP_PIXEL_LUMINANCE_OFFSET_KHR 0x30CD
+#define EGL_LOWER_LEFT_KHR 0x30CE
+#define EGL_UPPER_LEFT_KHR 0x30CF
+
+typedef EGLBoolean (EGLAPIENTRY * PFNEGLLOCKSURFACEKHRPROC) (EGLDisplay display, EGLSurface surface, const EGLint* attrib_list);
+typedef EGLBoolean (EGLAPIENTRY * PFNEGLUNLOCKSURFACEKHRPROC) (EGLDisplay display, EGLSurface surface);
+
+#define eglLockSurfaceKHR EGLEW_GET_FUN(__eglewLockSurfaceKHR)
+#define eglUnlockSurfaceKHR EGLEW_GET_FUN(__eglewUnlockSurfaceKHR)
+
+#define EGLEW_KHR_lock_surface EGLEW_GET_VAR(__EGLEW_KHR_lock_surface)
+
+#endif /* !EGL_KHR_lock_surface */
+
+/* ------------------------- EGL_KHR_lock_surface2 ------------------------- */
+
+#if !defined(EGL_KHR_lock_surface2)
+#define EGL_KHR_lock_surface2 1
+
+#define EGL_BITMAP_PIXEL_SIZE_KHR 0x3110
+
+#define EGLEW_KHR_lock_surface2 EGLEW_GET_VAR(__EGLEW_KHR_lock_surface2)
+
+#endif /* !EGL_KHR_lock_surface2 */
+
+/* ------------------------- EGL_KHR_reusable_sync ------------------------- */
+
+#if !defined(EGL_KHR_reusable_sync)
+#define EGL_KHR_reusable_sync 1
+
+#define EGL_SYNC_FLUSH_COMMANDS_BIT_KHR 0x0001
+#define EGL_SYNC_STATUS_KHR 0x30F1
+#define EGL_SIGNALED_KHR 0x30F2
+#define EGL_UNSIGNALED_KHR 0x30F3
+#define EGL_TIMEOUT_EXPIRED_KHR 0x30F5
+#define EGL_CONDITION_SATISFIED_KHR 0x30F6
+#define EGL_SYNC_TYPE_KHR 0x30F7
+#define EGL_SYNC_REUSABLE_KHR 0x30FA
+#define EGL_FOREVER_KHR 0xFFFFFFFFFFFFFFFF
+
+typedef khronos_utime_nanoseconds_t EGLTimeKHR;
+typedef void* EGLSyncKHR;
+
+typedef EGLint (EGLAPIENTRY * PFNEGLCLIENTWAITSYNCKHRPROC) (EGLDisplay dpy, EGLSyncKHR sync, EGLint flags, EGLTimeKHR timeout);
+typedef EGLSyncKHR (EGLAPIENTRY * PFNEGLCREATESYNCKHRPROC) (EGLDisplay dpy, EGLenum type, const EGLint* attrib_list);
+typedef EGLBoolean (EGLAPIENTRY * PFNEGLDESTROYSYNCKHRPROC) (EGLDisplay dpy, EGLSyncKHR sync);
+typedef EGLBoolean (EGLAPIENTRY * PFNEGLGETSYNCATTRIBKHRPROC) (EGLDisplay dpy, EGLSyncKHR sync, EGLint attribute, EGLint* value);
+typedef EGLBoolean (EGLAPIENTRY * PFNEGLSIGNALSYNCKHRPROC) (EGLDisplay dpy, EGLSyncKHR sync, EGLenum mode);
+
+#define eglClientWaitSyncKHR EGLEW_GET_FUN(__eglewClientWaitSyncKHR)
+#define eglCreateSyncKHR EGLEW_GET_FUN(__eglewCreateSyncKHR)
+#define eglDestroySyncKHR EGLEW_GET_FUN(__eglewDestroySyncKHR)
+#define eglGetSyncAttribKHR EGLEW_GET_FUN(__eglewGetSyncAttribKHR)
+#define eglSignalSyncKHR EGLEW_GET_FUN(__eglewSignalSyncKHR)
+
+#define EGLEW_KHR_reusable_sync EGLEW_GET_VAR(__EGLEW_KHR_reusable_sync)
+
+#endif /* !EGL_KHR_reusable_sync */
+
+/* ----------------------------- EGL_KHR_stream ---------------------------- */
+
+#if !defined(EGL_KHR_stream)
+#define EGL_KHR_stream 1
+
+#define EGL_CONSUMER_LATENCY_USEC_KHR 0x3210
+#define EGL_PRODUCER_FRAME_KHR 0x3212
+#define EGL_CONSUMER_FRAME_KHR 0x3213
+#define EGL_STREAM_STATE_KHR 0x3214
+#define EGL_STREAM_STATE_CREATED_KHR 0x3215
+#define EGL_STREAM_STATE_CONNECTING_KHR 0x3216
+#define EGL_STREAM_STATE_EMPTY_KHR 0x3217
+#define EGL_STREAM_STATE_NEW_FRAME_AVAILABLE_KHR 0x3218
+#define EGL_STREAM_STATE_OLD_FRAME_AVAILABLE_KHR 0x3219
+#define EGL_STREAM_STATE_DISCONNECTED_KHR 0x321A
+#define EGL_BAD_STREAM_KHR 0x321B
+#define EGL_BAD_STATE_KHR 0x321C
+
+#define EGLEW_KHR_stream EGLEW_GET_VAR(__EGLEW_KHR_stream)
+
+#endif /* !EGL_KHR_stream */
+
+/* ------------------- EGL_KHR_stream_consumer_gltexture ------------------- */
+
+#if !defined(EGL_KHR_stream_consumer_gltexture)
+#define EGL_KHR_stream_consumer_gltexture 1
+
+#define EGL_CONSUMER_ACQUIRE_TIMEOUT_USEC_KHR 0x321E
+
+typedef void* EGLStreamKHR; // NOTE jwilkins: missing typedef
+
+typedef EGLBoolean (EGLAPIENTRY * PFNEGLSTREAMCONSUMERACQUIREKHRPROC) (EGLDisplay dpy, EGLStreamKHR stream);
+typedef EGLBoolean (EGLAPIENTRY * PFNEGLSTREAMCONSUMERGLTEXTUREEXTERNALKHRPROC) (EGLDisplay dpy, EGLStreamKHR stream);
+typedef EGLBoolean (EGLAPIENTRY * PFNEGLSTREAMCONSUMERRELEASEKHRPROC) (EGLDisplay dpy, EGLStreamKHR stream);
+
+#define eglStreamConsumerAcquireKHR EGLEW_GET_FUN(__eglewStreamConsumerAcquireKHR)
+#define eglStreamConsumerGLTextureExternalKHR EGLEW_GET_FUN(__eglewStreamConsumerGLTextureExternalKHR)
+#define eglStreamConsumerReleaseKHR EGLEW_GET_FUN(__eglewStreamConsumerReleaseKHR)
+
+#define EGLEW_KHR_stream_consumer_gltexture EGLEW_GET_VAR(__EGLEW_KHR_stream_consumer_gltexture)
+
+#endif /* !EGL_KHR_stream_consumer_gltexture */
+
+/* -------------------- EGL_KHR_stream_cross_process_fd -------------------- */
+
+#if !defined(EGL_KHR_stream_cross_process_fd)
+#define EGL_KHR_stream_cross_process_fd 1
+
+typedef int EGLNativeFileDescriptorKHR; // NOTE jwilkins: missing typedef
+
+typedef EGLStreamKHR (EGLAPIENTRY * PFNEGLCREATESTREAMFROMFILEDESCRIPTORKHRPROC) (EGLDisplay dpy, EGLNativeFileDescriptorKHR file_descriptor);
+typedef EGLNativeFileDescriptorKHR (EGLAPIENTRY * PFNEGLGETSTREAMFILEDESCRIPTORKHRPROC) (EGLDisplay dpy, EGLStreamKHR stream);
+
+#define eglCreateStreamFromFileDescriptorKHR EGLEW_GET_FUN(__eglewCreateStreamFromFileDescriptorKHR)
+#define eglGetStreamFileDescriptorKHR EGLEW_GET_FUN(__eglewGetStreamFileDescriptorKHR)
+
+#define EGLEW_KHR_stream_cross_process_fd EGLEW_GET_VAR(__EGLEW_KHR_stream_cross_process_fd)
+
+#endif /* !EGL_KHR_stream_cross_process_fd */
+
+/* -------------------------- EGL_KHR_stream_fifo -------------------------- */
+
+#if !defined(EGL_KHR_stream_fifo)
+#define EGL_KHR_stream_fifo 1
+
+#define EGL_STREAM_FIFO_LENGTH_KHR 0x31FC
+#define EGL_STREAM_TIME_NOW_KHR 0x31FD
+#define EGL_STREAM_TIME_CONSUMER_KHR 0x31FE
+#define EGL_STREAM_TIME_PRODUCER_KHR 0x31FF
+
+#define EGLEW_KHR_stream_fifo EGLEW_GET_VAR(__EGLEW_KHR_stream_fifo)
+
+#endif /* !EGL_KHR_stream_fifo */
+
+/* ----------------- EGL_KHR_stream_producer_aldatalocator ----------------- */
+
+#if !defined(EGL_KHR_stream_producer_aldatalocator)
+#define EGL_KHR_stream_producer_aldatalocator 1
+
+#define EGLEW_KHR_stream_producer_aldatalocator EGLEW_GET_VAR(__EGLEW_KHR_stream_producer_aldatalocator)
+
+#endif /* !EGL_KHR_stream_producer_aldatalocator */
+
+/* ------------------- EGL_KHR_stream_producer_eglsurface ------------------ */
+
+#if !defined(EGL_KHR_stream_producer_eglsurface)
+#define EGL_KHR_stream_producer_eglsurface 1
+
+#define EGL_STREAM_BIT_KHR 0x0800
+
+typedef EGLSurface (EGLAPIENTRY * PFNEGLCREATESTREAMPRODUCERSURFACEKHRPROC) (EGLDisplay dpy, EGLConfig config, EGLStreamKHR stream, const EGLint* attrib_list);
+
+#define eglCreateStreamProducerSurfaceKHR EGLEW_GET_FUN(__eglewCreateStreamProducerSurfaceKHR)
+
+#define EGLEW_KHR_stream_producer_eglsurface EGLEW_GET_VAR(__EGLEW_KHR_stream_producer_eglsurface)
+
+#endif /* !EGL_KHR_stream_producer_eglsurface */
+
+/* ---------------------- EGL_KHR_surfaceless_context ---------------------- */
+
+#if !defined(EGL_KHR_surfaceless_context)
+#define EGL_KHR_surfaceless_context 1
+
+#define EGLEW_KHR_surfaceless_context EGLEW_GET_VAR(__EGLEW_KHR_surfaceless_context)
+
+#endif /* !EGL_KHR_surfaceless_context */
+
+/* ------------------------ EGL_KHR_vg_parent_image ------------------------ */
+
+#if !defined(EGL_KHR_vg_parent_image)
+#define EGL_KHR_vg_parent_image 1
+
+#define EGL_VG_PARENT_IMAGE_KHR 0x30BA
+
+#define EGLEW_KHR_vg_parent_image EGLEW_GET_VAR(__EGLEW_KHR_vg_parent_image)
+
+#endif /* !EGL_KHR_vg_parent_image */
+
+/* --------------------------- EGL_KHR_wait_sync --------------------------- */
+
+#if !defined(EGL_KHR_wait_sync)
+#define EGL_KHR_wait_sync 1
+
+typedef void* EGLSyncKHR; // NOTE jwilkins: missing typedef
+
+typedef EGLint (EGLAPIENTRY * PFNEGLWAITSYNCKHRPROC) (EGLDisplay dpy, EGLSyncKHR sync, EGLint flags);
+
+#define eglWaitSyncKHR EGLEW_GET_FUN(__eglewWaitSyncKHR)
+
+#define EGLEW_KHR_wait_sync EGLEW_GET_VAR(__EGLEW_KHR_wait_sync)
+
+#endif /* !EGL_KHR_wait_sync */
+
+/* --------------------------- EGL_MESA_drm_image -------------------------- */
+
+#if !defined(EGL_MESA_drm_image)
+#define EGL_MESA_drm_image 1
+
+#define EGL_DRM_BUFFER_USE_SCANOUT_MESA 0x0001
+#define EGL_DRM_BUFFER_USE_SHARE_MESA 0x0002
+#define EGL_DRM_BUFFER_FORMAT_MESA 0x31D0
+#define EGL_DRM_BUFFER_USE_MESA 0x31D1
+#define EGL_DRM_BUFFER_FORMAT_ARGB32_MESA 0x31D2
+#define EGL_DRM_BUFFER_MESA 0x31D3
+#define EGL_DRM_BUFFER_STRIDE_MESA 0x31D4
+
+typedef EGLImageKHR (EGLAPIENTRY * PFNEGLCREATEDRMIMAGEMESAPROC) (EGLDisplay dpy, const EGLint* attrib_list);
+typedef EGLBoolean (EGLAPIENTRY * PFNEGLEXPORTDRMIMAGEMESAPROC) (EGLDisplay dpy, EGLImageKHR image, EGLint* name, EGLint *handle, EGLint *stride);
+
+#define eglCreateDRMImageMESA EGLEW_GET_FUN(__eglewCreateDRMImageMESA)
+#define eglExportDRMImageMESA EGLEW_GET_FUN(__eglewExportDRMImageMESA)
+
+#define EGLEW_MESA_drm_image EGLEW_GET_VAR(__EGLEW_MESA_drm_image)
+
+#endif /* !EGL_MESA_drm_image */
+
+/* ------------------------ EGL_NV_3dvision_surface ------------------------ */
+
+#if !defined(EGL_NV_3dvision_surface)
+#define EGL_NV_3dvision_surface 1
+
+#define EGL_AUTO_STEREO_NV 0x3136
+
+#define EGLEW_NV_3dvision_surface EGLEW_GET_VAR(__EGLEW_NV_3dvision_surface)
+
+#endif /* !EGL_NV_3dvision_surface */
+
+/* ------------------------- EGL_NV_coverage_sample ------------------------ */
+
+#if !defined(EGL_NV_coverage_sample)
+#define EGL_NV_coverage_sample 1
+
+#define EGL_COVERAGE_BUFFERS_NV 0x30E0
+#define EGL_COVERAGE_SAMPLES_NV 0x30E1
+
+#define EGLEW_NV_coverage_sample EGLEW_GET_VAR(__EGLEW_NV_coverage_sample)
+
+#endif /* !EGL_NV_coverage_sample */
+
+/* --------------------- EGL_NV_coverage_sample_resolve -------------------- */
+
+#if !defined(EGL_NV_coverage_sample_resolve)
+#define EGL_NV_coverage_sample_resolve 1
+
+#define EGL_COVERAGE_SAMPLE_RESOLVE_NV 0x3131
+#define EGL_COVERAGE_SAMPLE_RESOLVE_DEFAULT_NV 0x3132
+#define EGL_COVERAGE_SAMPLE_RESOLVE_NONE_NV 0x3133
+
+#define EGLEW_NV_coverage_sample_resolve EGLEW_GET_VAR(__EGLEW_NV_coverage_sample_resolve)
+
+#endif /* !EGL_NV_coverage_sample_resolve */
+
+/* ------------------------- EGL_NV_depth_nonlinear ------------------------ */
+
+#if !defined(EGL_NV_depth_nonlinear)
+#define EGL_NV_depth_nonlinear 1
+
+#define EGL_DEPTH_ENCODING_NONE_NV 0
+#define EGL_DEPTH_ENCODING_NV 0x30E2
+#define EGL_DEPTH_ENCODING_NONLINEAR_NV 0x30E3
+
+#define EGLEW_NV_depth_nonlinear EGLEW_GET_VAR(__EGLEW_NV_depth_nonlinear)
+
+#endif /* !EGL_NV_depth_nonlinear */
+
+/* -------------------------- EGL_NV_native_query -------------------------- */
+
+#if !defined(EGL_NV_native_query)
+#define EGL_NV_native_query 1
+
+typedef EGLBoolean (EGLAPIENTRY * PFNEGLQUERYNATIVEDISPLAYNVPROC) (EGLDisplay dpy, EGLNativeDisplayType* display_id);
+typedef EGLBoolean (EGLAPIENTRY * PFNEGLQUERYNATIVEPIXMAPNVPROC) (EGLDisplay dpy, EGLSurface surf, EGLNativePixmapType* pixmap);
+typedef EGLBoolean (EGLAPIENTRY * PFNEGLQUERYNATIVEWINDOWNVPROC) (EGLDisplay dpy, EGLSurface surf, EGLNativeWindowType* window);
+
+#define eglQueryNativeDisplayNV EGLEW_GET_FUN(__eglewQueryNativeDisplayNV)
+#define eglQueryNativePixmapNV EGLEW_GET_FUN(__eglewQueryNativePixmapNV)
+#define eglQueryNativeWindowNV EGLEW_GET_FUN(__eglewQueryNativeWindowNV)
+
+#define EGLEW_NV_native_query EGLEW_GET_VAR(__EGLEW_NV_native_query)
+
+#endif /* !EGL_NV_native_query */
+
+/* ---------------------- EGL_NV_post_convert_rounding --------------------- */
+
+#if !defined(EGL_NV_post_convert_rounding)
+#define EGL_NV_post_convert_rounding 1
+
+#define EGLEW_NV_post_convert_rounding EGLEW_GET_VAR(__EGLEW_NV_post_convert_rounding)
+
+#endif /* !EGL_NV_post_convert_rounding */
+
+/* ------------------------- EGL_NV_post_sub_buffer ------------------------ */
+
+#if !defined(EGL_NV_post_sub_buffer)
+#define EGL_NV_post_sub_buffer 1
+
+#define EGL_POST_SUB_BUFFER_SUPPORTED_NV 0x30BE
+
+typedef EGLBoolean (EGLAPIENTRY * PFNEGLPOSTSUBBUFFERNVPROC) (EGLDisplay dpy, EGLSurface surface, EGLint x, EGLint y, EGLint width, EGLint height);
+
+#define eglPostSubBufferNV EGLEW_GET_FUN(__eglewPostSubBufferNV)
+
+#define EGLEW_NV_post_sub_buffer EGLEW_GET_VAR(__EGLEW_NV_post_sub_buffer)
+
+#endif /* !EGL_NV_post_sub_buffer */
+
+/* ------------------------------ EGL_NV_sync ------------------------------ */
+
+#if !defined(EGL_NV_sync)
+#define EGL_NV_sync 1
+
+#define EGL_SYNC_FLUSH_COMMANDS_BIT_NV 0x0001
+#define EGL_SYNC_PRIOR_COMMANDS_COMPLETE_NV 0x30E6
+#define EGL_SYNC_STATUS_NV 0x30E7
+#define EGL_SIGNALED_NV 0x30E8
+#define EGL_UNSIGNALED_NV 0x30E9
+#define EGL_ALREADY_SIGNALED_NV 0x30EA
+#define EGL_TIMEOUT_EXPIRED_NV 0x30EB
+#define EGL_CONDITION_SATISFIED_NV 0x30EC
+#define EGL_SYNC_TYPE_NV 0x30ED
+#define EGL_SYNC_CONDITION_NV 0x30EE
+#define EGL_SYNC_FENCE_NV 0x30EF
+#define EGL_FOREVER_NV 0xFFFFFFFFFFFFFFFF
+
+typedef khronos_utime_nanoseconds_t EGLTimeNV;
+typedef void* EGLSyncNV;
+
+typedef EGLint (EGLAPIENTRY * PFNEGLCLIENTWAITSYNCNVPROC) (EGLSyncNV sync, EGLint flags, EGLTimeNV timeout);
+typedef EGLSyncNV (EGLAPIENTRY * PFNEGLCREATEFENCESYNCNVPROC) (EGLDisplay dpy, EGLenum condition, const EGLint* attrib_list);
+typedef EGLBoolean (EGLAPIENTRY * PFNEGLDESTROYSYNCNVPROC) (EGLSyncNV sync);
+typedef EGLBoolean (EGLAPIENTRY * PFNEGLFENCENVPROC) (EGLSyncNV sync);
+typedef EGLBoolean (EGLAPIENTRY * PFNEGLGETSYNCATTRIBNVPROC) (EGLSyncNV sync, EGLint attribute, EGLint* value);
+typedef EGLBoolean (EGLAPIENTRY * PFNEGLSIGNALSYNCNVPROC) (EGLSyncNV sync, EGLenum mode);
+
+#define eglClientWaitSyncNV EGLEW_GET_FUN(__eglewClientWaitSyncNV)
+#define eglCreateFenceSyncNV EGLEW_GET_FUN(__eglewCreateFenceSyncNV)
+#define eglDestroySyncNV EGLEW_GET_FUN(__eglewDestroySyncNV)
+#define eglFenceNV EGLEW_GET_FUN(__eglewFenceNV)
+#define eglGetSyncAttribNV EGLEW_GET_FUN(__eglewGetSyncAttribNV)
+#define eglSignalSyncNV EGLEW_GET_FUN(__eglewSignalSyncNV)
+
+#define EGLEW_NV_sync EGLEW_GET_VAR(__EGLEW_NV_sync)
+
+#endif /* !EGL_NV_sync */
+
+/* --------------------------- EGL_NV_system_time -------------------------- */
+
+#if !defined(EGL_NV_system_time)
+#define EGL_NV_system_time 1
+
+typedef khronos_utime_nanoseconds_t EGLuint64NV;
+
+typedef EGLuint64NV (EGLAPIENTRY * PFNEGLGETSYSTEMTIMEFREQUENCYNVPROC) (void);
+typedef EGLuint64NV (EGLAPIENTRY * PFNEGLGETSYSTEMTIMENVPROC) (void);
+
+#define eglGetSystemTimeFrequencyNV EGLEW_GET_FUN(__eglewGetSystemTimeFrequencyNV)
+#define eglGetSystemTimeNV EGLEW_GET_FUN(__eglewGetSystemTimeNV)
+
+#define EGLEW_NV_system_time EGLEW_GET_VAR(__EGLEW_NV_system_time)
+
+#endif /* !EGL_NV_system_time */
+
+/* ------------------------------------------------------------------------- */
+
+#if defined(GLEW_MX) && defined(_WIN32)
+ #define EGLEW_FUN_EXPORT
+ #else
+ #define EGLEW_FUN_EXPORT GLEWAPI
+ #endif /* GLEW_MX */
+
+#if defined(GLEW_MX)
+ #define EGLEW_VAR_EXPORT
+#else
+#define EGLEW_VAR_EXPORT GLEWAPI
+ #endif /* GLEW_MX */
+
+#if defined (GLEW_MX) && defined(_WIN32)
+struct EGLEWContextStruct
+{
+#endif /* GLEW_MX */
+
+EGLEW_FUN_EXPORT PFNCREATESYNC __eglewCreateSync;
+EGLEW_FUN_EXPORT PFNDESTROYSYNC __eglewDestroySync;
+EGLEW_FUN_EXPORT PFNCLIENTWAITSYNC __eglewClientWaitSync;
+EGLEW_FUN_EXPORT PFNGETSYNCATTRIB __eglewGetSyncAttrib;
+EGLEW_FUN_EXPORT PFNGETPLATFORMDISPLAY __eglewGetPlatformDisplay;
+EGLEW_FUN_EXPORT PFNCREATEPLATFORMWINDOWSURFACE __eglewCreatePlatformWindowSurface;
+EGLEW_FUN_EXPORT PFNCREATEPLATFORMPIXMAPSURFACE __eglewCreatePlatformPixmapSurface;
+EGLEW_FUN_EXPORT PFNWAITSYNC __eglewWaitSync;
+
+EGLEW_FUN_EXPORT PFNEGLBINDAPIPROC __eglewBindAPI;
+EGLEW_FUN_EXPORT PFNEGLCREATEPBUFFERFROMCLIENTBUFFERPROC __eglewCreatePbufferFromClientBuffer;
+EGLEW_FUN_EXPORT PFNEGLQUERYAPIPROC __eglewQueryAPI;
+EGLEW_FUN_EXPORT PFNEGLRELEASETHREADPROC __eglewReleaseThread;
+EGLEW_FUN_EXPORT PFNEGLWAITCLIENTPROC __eglewWaitClient;
+
+EGLEW_FUN_EXPORT PFNEGLSETBLOBCACHEFUNCSANDROIDPROC __eglewSetBlobCacheFuncsANDROID;
+
+EGLEW_FUN_EXPORT PFNEGLDUPNATIVEFENCEFDANDROIDPROC __eglewDupNativeFenceFDANDROID;
+
+EGLEW_FUN_EXPORT PFNEGLQUERYSURFACEPOINTERANGLEPROC __eglewQuerySurfacePointerANGLE;
+
+EGLEW_FUN_EXPORT PFNEGLCREATEIMAGEKHRPROC __eglewCreateImageKHR;
+EGLEW_FUN_EXPORT PFNEGLDESTROYIMAGEKHRPROC __eglewDestroyImageKHR;
+
+EGLEW_FUN_EXPORT PFNEGLLOCKSURFACEKHRPROC __eglewLockSurfaceKHR;
+EGLEW_FUN_EXPORT PFNEGLUNLOCKSURFACEKHRPROC __eglewUnlockSurfaceKHR;
+
+EGLEW_FUN_EXPORT PFNEGLCLIENTWAITSYNCKHRPROC __eglewClientWaitSyncKHR;
+EGLEW_FUN_EXPORT PFNEGLCREATESYNCKHRPROC __eglewCreateSyncKHR;
+EGLEW_FUN_EXPORT PFNEGLDESTROYSYNCKHRPROC __eglewDestroySyncKHR;
+EGLEW_FUN_EXPORT PFNEGLGETSYNCATTRIBKHRPROC __eglewGetSyncAttribKHR;
+EGLEW_FUN_EXPORT PFNEGLSIGNALSYNCKHRPROC __eglewSignalSyncKHR;
+
+EGLEW_FUN_EXPORT PFNEGLSTREAMCONSUMERACQUIREKHRPROC __eglewStreamConsumerAcquireKHR;
+EGLEW_FUN_EXPORT PFNEGLSTREAMCONSUMERGLTEXTUREEXTERNALKHRPROC __eglewStreamConsumerGLTextureExternalKHR;
+EGLEW_FUN_EXPORT PFNEGLSTREAMCONSUMERRELEASEKHRPROC __eglewStreamConsumerReleaseKHR;
+
+EGLEW_FUN_EXPORT PFNEGLCREATESTREAMFROMFILEDESCRIPTORKHRPROC __eglewCreateStreamFromFileDescriptorKHR;
+EGLEW_FUN_EXPORT PFNEGLGETSTREAMFILEDESCRIPTORKHRPROC __eglewGetStreamFileDescriptorKHR;
+
+EGLEW_FUN_EXPORT PFNEGLCREATESTREAMPRODUCERSURFACEKHRPROC __eglewCreateStreamProducerSurfaceKHR;
+
+EGLEW_FUN_EXPORT PFNEGLWAITSYNCKHRPROC __eglewWaitSyncKHR;
+
+EGLEW_FUN_EXPORT PFNEGLCREATEDRMIMAGEMESAPROC __eglewCreateDRMImageMESA;
+EGLEW_FUN_EXPORT PFNEGLEXPORTDRMIMAGEMESAPROC __eglewExportDRMImageMESA;
+
+EGLEW_FUN_EXPORT PFNEGLQUERYNATIVEDISPLAYNVPROC __eglewQueryNativeDisplayNV;
+EGLEW_FUN_EXPORT PFNEGLQUERYNATIVEPIXMAPNVPROC __eglewQueryNativePixmapNV;
+EGLEW_FUN_EXPORT PFNEGLQUERYNATIVEWINDOWNVPROC __eglewQueryNativeWindowNV;
+
+EGLEW_FUN_EXPORT PFNEGLPOSTSUBBUFFERNVPROC __eglewPostSubBufferNV;
+
+EGLEW_FUN_EXPORT PFNEGLCLIENTWAITSYNCNVPROC __eglewClientWaitSyncNV;
+EGLEW_FUN_EXPORT PFNEGLCREATEFENCESYNCNVPROC __eglewCreateFenceSyncNV;
+EGLEW_FUN_EXPORT PFNEGLDESTROYSYNCNVPROC __eglewDestroySyncNV;
+EGLEW_FUN_EXPORT PFNEGLFENCENVPROC __eglewFenceNV;
+EGLEW_FUN_EXPORT PFNEGLGETSYNCATTRIBNVPROC __eglewGetSyncAttribNV;
+EGLEW_FUN_EXPORT PFNEGLSIGNALSYNCNVPROC __eglewSignalSyncNV;
+
+EGLEW_FUN_EXPORT PFNEGLGETSYSTEMTIMEFREQUENCYNVPROC __eglewGetSystemTimeFrequencyNV;
+EGLEW_FUN_EXPORT PFNEGLGETSYSTEMTIMENVPROC __eglewGetSystemTimeNV;
+
+#if defined(GLEW_MX) && !defined(_WIN32)
+struct EGLEWContextStruct
+{
+#endif /* GLEW_MX */
+
+EGLEW_VAR_EXPORT GLboolean __EGLEW_VERSION_1_1;
+EGLEW_VAR_EXPORT GLboolean __EGLEW_VERSION_1_2;
+EGLEW_VAR_EXPORT GLboolean __EGLEW_VERSION_1_3;
+EGLEW_VAR_EXPORT GLboolean __EGLEW_VERSION_1_4;
+EGLEW_VAR_EXPORT GLboolean __EGLEW_VERSION_1_5;
+EGLEW_VAR_EXPORT GLboolean __EGLEW_ANDROID_blob_cache;
+EGLEW_VAR_EXPORT GLboolean __EGLEW_ANDROID_framebuffer_target;
+EGLEW_VAR_EXPORT GLboolean __EGLEW_ANDROID_image_native_buffer;
+EGLEW_VAR_EXPORT GLboolean __EGLEW_ANDROID_native_fence_sync;
+EGLEW_VAR_EXPORT GLboolean __EGLEW_ANDROID_recordable;
+EGLEW_VAR_EXPORT GLboolean __EGLEW_ANGLE_d3d_share_handle_client_buffer;
+EGLEW_VAR_EXPORT GLboolean __EGLEW_ANGLE_query_surface_pointer;
+EGLEW_VAR_EXPORT GLboolean __EGLEW_ANGLE_surface_d3d_texture_2d_share_handle;
+EGLEW_VAR_EXPORT GLboolean __EGLEW_EXT_buffer_age;
+EGLEW_VAR_EXPORT GLboolean __EGLEW_EXT_create_context_robustness;
+EGLEW_VAR_EXPORT GLboolean __EGLEW_EXT_multiview_window;
+EGLEW_VAR_EXPORT GLboolean __EGLEW_HI_clientpixmap;
+EGLEW_VAR_EXPORT GLboolean __EGLEW_HI_colorformats;
+EGLEW_VAR_EXPORT GLboolean __EGLEW_IMG_context_priority;
+EGLEW_VAR_EXPORT GLboolean __EGLEW_KHR_config_attribs;
+EGLEW_VAR_EXPORT GLboolean __EGLEW_KHR_create_context;
+EGLEW_VAR_EXPORT GLboolean __EGLEW_KHR_fence_sync;
+EGLEW_VAR_EXPORT GLboolean __EGLEW_KHR_gl_renderbuffer_image;
+EGLEW_VAR_EXPORT GLboolean __EGLEW_KHR_gl_texture_2D_image;
+EGLEW_VAR_EXPORT GLboolean __EGLEW_KHR_gl_texture_3D_image;
+EGLEW_VAR_EXPORT GLboolean __EGLEW_KHR_gl_texture_cubemap_image;
+EGLEW_VAR_EXPORT GLboolean __EGLEW_KHR_image;
+EGLEW_VAR_EXPORT GLboolean __EGLEW_KHR_image_base;
+EGLEW_VAR_EXPORT GLboolean __EGLEW_KHR_image_pixmap;
+EGLEW_VAR_EXPORT GLboolean __EGLEW_KHR_lock_surface;
+EGLEW_VAR_EXPORT GLboolean __EGLEW_KHR_lock_surface2;
+EGLEW_VAR_EXPORT GLboolean __EGLEW_KHR_reusable_sync;
+EGLEW_VAR_EXPORT GLboolean __EGLEW_KHR_stream;
+EGLEW_VAR_EXPORT GLboolean __EGLEW_KHR_stream_consumer_gltexture;
+EGLEW_VAR_EXPORT GLboolean __EGLEW_KHR_stream_cross_process_fd;
+EGLEW_VAR_EXPORT GLboolean __EGLEW_KHR_stream_fifo;
+EGLEW_VAR_EXPORT GLboolean __EGLEW_KHR_stream_producer_aldatalocator;
+EGLEW_VAR_EXPORT GLboolean __EGLEW_KHR_stream_producer_eglsurface;
+EGLEW_VAR_EXPORT GLboolean __EGLEW_KHR_surfaceless_context;
+EGLEW_VAR_EXPORT GLboolean __EGLEW_KHR_vg_parent_image;
+EGLEW_VAR_EXPORT GLboolean __EGLEW_KHR_wait_sync;
+EGLEW_VAR_EXPORT GLboolean __EGLEW_MESA_drm_image;
+EGLEW_VAR_EXPORT GLboolean __EGLEW_NV_3dvision_surface;
+EGLEW_VAR_EXPORT GLboolean __EGLEW_NV_coverage_sample;
+EGLEW_VAR_EXPORT GLboolean __EGLEW_NV_coverage_sample_resolve;
+EGLEW_VAR_EXPORT GLboolean __EGLEW_NV_depth_nonlinear;
+EGLEW_VAR_EXPORT GLboolean __EGLEW_NV_native_query;
+EGLEW_VAR_EXPORT GLboolean __EGLEW_NV_post_convert_rounding;
+EGLEW_VAR_EXPORT GLboolean __EGLEW_NV_post_sub_buffer;
+EGLEW_VAR_EXPORT GLboolean __EGLEW_NV_sync;
+EGLEW_VAR_EXPORT GLboolean __EGLEW_NV_system_time;
+
+#ifdef GLEW_MX
+}; /* EGLEWContextStruct */
+#endif /* GLEW_MX */
+
+/* ------------------------------------------------------------------------ */
+
+#ifdef GLEW_MX
+
+typedef struct EGLEWContextStruct EGLEWContext;
+extern GLenum eglewContextInit (EGLDisplay display, EGLEWContext* ctx);
+extern GLboolean eglewContextIsSupported (const EGLEWContext* ctx, const char* name);
+
+#define eglewInit(display) eglewContextInit(display, eglewGetContext())
+#define eglewIsSupported(x) eglewContextIsSupported(eglewGetContext(), x)
+
+#define EGLEW_GET_VAR(x) (*(const GLboolean*)&(eglewGetContext()->x))
+#ifdef _WIN32
+# define EGLEW_GET_FUN(x) eglewGetContext()->x
+#else
+# define EGLEW_GET_FUN(x) x
+#endif
+
+#else /* GLEW_MX */
+
+#define EGLEW_GET_VAR(x) (*(const GLboolean*)&x)
+#define EGLEW_GET_FUN(x) x
+
+extern GLenum eglewContextInit(EGLDisplay display); // NOTE jwilkins: context handling not really written yet?
+#define eglewInit eglewContextInit // NOTE jwilkins: context handling not really written yet?
+
+extern GLboolean eglewIsSupported (const char* name);
+
+#endif /* GLEW_MX */
+
+extern GLboolean eglewGetExtension (const char* name);
+
+#ifdef __cplusplus
+}
+#endif
+
+#undef GLEWAPI
+
+#endif /* __eglew_h__ */
diff --git a/extern/glew-es/include/GL/glesew.h b/extern/glew-es/include/GL/glesew.h
new file mode 100644
index 00000000000..0cb8c0d850c
--- /dev/null
+++ b/extern/glew-es/include/GL/glesew.h
@@ -0,0 +1,4318 @@
+/*
+** The OpenGL Extension Wrangler Library
+** Copyright (C) 2002-2008, Milan Ikits <milan ikits[]ieee org>
+** Copyright (C) 2002-2008, Marcelo E. Magallon <mmagallo[]debian org>
+** Copyright (C) 2002, Lev Povalahev
+** 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.
+** * The name of the author 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.
+*/
+
+
+/*
+** Copyright (c) 2008-2009 The Khronos Group Inc.
+**
+** Permission is hereby granted, free of charge, to any person obtaining a
+** copy of this software and/or associated documentation files (the
+** "Materials"), to deal in the Materials without restriction, including
+** without limitation the rights to use, copy, modify, merge, publish,
+** distribute, sublicense, and/or sell copies of the Materials, and to
+** permit persons to whom the Materials are furnished to do so, subject to
+** the following conditions:
+**
+** The above copyright notice and this permission notice shall be included
+** in all copies or substantial portions of the Materials.
+**
+** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+*/
+
+/* Copyright © 2011 Linaro Limited
+ */
+
+#ifndef __glesew_h__
+#define __glesew_h__
+#define __GLESEW_H__
+
+#if !defined(__glew_h__) || !defined(__GLEW_H__)
+#error glesew.h included instead of glew.h
+#endif
+
+// NOTE jwilkins: changing versions from 'ifdef' to 'if' requires setting defaults
+#ifndef GL_ES_VERSION_1_0 // XXX
+#define GL_ES_VERSION_1_0 1 // XXX
+#endif // XXX
+
+// NOTE jwilkins: changing versions from 'ifdef' to 'if' requires setting defaults
+#ifndef GL_ES_VERSION_CL_1_1 // XXX
+#define GL_ES_VERSION_CL_1_1 1 // XXX
+#endif // XXX
+
+// NOTE jwilkins: changing versions from 'ifdef' to 'if' requires setting defaults
+#ifndef GL_ES_VERSION_CM_1_1 // XXX
+#define GL_ES_VERSION_CM_1_1 1 // XXX
+#endif // XXX
+
+// NOTE jwilkins: changing versions from 'ifdef' to 'if' requires setting defaults
+#ifndef GL_ES_VERSION_2_0 // XXX
+#define GL_ES_VERSION_2_0 1 // XXX
+#endif // XXX
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef unsigned int GLenum;
+typedef unsigned char GLboolean;
+typedef unsigned int GLbitfield;
+typedef khronos_int8_t GLbyte;
+typedef short GLshort;
+typedef int GLint;
+typedef int GLsizei;
+typedef khronos_uint8_t GLubyte;
+typedef unsigned short GLushort;
+typedef unsigned int GLuint;
+typedef khronos_float_t GLfloat;
+typedef khronos_float_t GLclampf;
+typedef void GLvoid;
+typedef int GLintptrARB;
+typedef int GLsizeiptrARB;
+typedef khronos_int32_t GLfixed;
+typedef int GLclampx;
+/* Internal convenience typedefs */
+typedef void (*_GLfuncptr)();
+
+// NOTE jwilkins: had to add these
+#if defined(_MSC_VER) && _MSC_VER < 1400
+typedef __int64 GLint64EXT;
+typedef unsigned __int64 GLuint64EXT;
+#elif defined(_MSC_VER) || defined(__BORLANDC__)
+typedef signed long long GLint64EXT;
+typedef unsigned long long GLuint64EXT;
+#else
+# if defined(__MINGW32__) || defined(__CYGWIN__)
+#include <inttypes.h>
+# endif
+typedef int64_t GLint64EXT;
+typedef uint64_t GLuint64EXT;
+#endif
+typedef GLint64EXT GLint64;
+typedef GLuint64EXT GLuint64;
+typedef struct __GLsync *GLsync;
+
+
+
+/********************* GL_ES_VERSION_1_0 functions common with OpenGL 1.1 *************************/
+
+
+/* Extensions */
+//#define GL_OES_VERSION_1_0 1
+//#define GL_OES_read_format 1
+//#define GL_OES_compressed_paletted_texture 1
+
+/* ClearBufferMask */
+#define GL_DEPTH_BUFFER_BIT 0x00000100
+#define GL_STENCIL_BUFFER_BIT 0x00000400
+#define GL_COLOR_BUFFER_BIT 0x00004000
+
+/* Boolean */
+#define GL_FALSE 0
+#define GL_TRUE 1
+
+/* BeginMode */
+#define GL_POINTS 0x0000
+#define GL_LINES 0x0001
+#define GL_LINE_LOOP 0x0002
+#define GL_LINE_STRIP 0x0003
+#define GL_TRIANGLES 0x0004
+#define GL_TRIANGLE_STRIP 0x0005
+#define GL_TRIANGLE_FAN 0x0006
+
+/* AlphaFunction */
+#define GL_NEVER 0x0200
+#define GL_LESS 0x0201
+#define GL_EQUAL 0x0202
+#define GL_LEQUAL 0x0203
+#define GL_GREATER 0x0204
+#define GL_NOTEQUAL 0x0205
+#define GL_GEQUAL 0x0206
+#define GL_ALWAYS 0x0207
+
+/* BlendingFactorDest */
+#define GL_ZERO 0
+#define GL_ONE 1
+#define GL_SRC_COLOR 0x0300
+#define GL_ONE_MINUS_SRC_COLOR 0x0301
+#define GL_SRC_ALPHA 0x0302
+#define GL_ONE_MINUS_SRC_ALPHA 0x0303
+#define GL_DST_ALPHA 0x0304
+#define GL_ONE_MINUS_DST_ALPHA 0x0305
+
+/* BlendingFactorSrc */
+/* GL_ZERO */
+/* GL_ONE */
+#define GL_DST_COLOR 0x0306
+#define GL_ONE_MINUS_DST_COLOR 0x0307
+#define GL_SRC_ALPHA_SATURATE 0x0308
+/* GL_SRC_ALPHA */
+/* GL_ONE_MINUS_SRC_ALPHA */
+/* GL_DST_ALPHA */
+/* GL_ONE_MINUS_DST_ALPHA */
+
+/* ColorMaterialFace */
+/* GL_FRONT_AND_BACK */
+
+/* ColorMaterialParameter */
+/* GL_AMBIENT_AND_DIFFUSE */
+
+/* ColorPointerType */
+/* GL_UNSIGNED_BYTE */
+/* GL_FLOAT */
+/* GL_FIXED */
+
+/* CullFaceMode */
+#define GL_FRONT 0x0404
+#define GL_BACK 0x0405
+#define GL_FRONT_AND_BACK 0x0408
+
+/* DepthFunction */
+/* GL_NEVER */
+/* GL_LESS */
+/* GL_EQUAL */
+/* GL_LEQUAL */
+/* GL_GREATER */
+/* GL_NOTEQUAL */
+/* GL_GEQUAL */
+/* GL_ALWAYS */
+
+/* EnableCap */
+#define GL_FOG 0x0B60
+#define GL_LIGHTING 0x0B50
+#define GL_TEXTURE_2D 0x0DE1
+#define GL_CULL_FACE 0x0B44
+#define GL_ALPHA_TEST 0x0BC0
+#define GL_BLEND 0x0BE2
+#define GL_COLOR_LOGIC_OP 0x0BF2
+#define GL_DITHER 0x0BD0
+#define GL_STENCIL_TEST 0x0B90
+#define GL_DEPTH_TEST 0x0B71
+/* GL_LIGHT0 */
+/* GL_LIGHT1 */
+/* GL_LIGHT2 */
+/* GL_LIGHT3 */
+/* GL_LIGHT4 */
+/* GL_LIGHT5 */
+/* GL_LIGHT6 */
+/* GL_LIGHT7 */
+#define GL_POINT_SMOOTH 0x0B10
+#define GL_LINE_SMOOTH 0x0B20
+#define GL_SCISSOR_TEST 0x0C11
+#define GL_COLOR_MATERIAL 0x0B57
+#define GL_NORMALIZE 0x0BA1
+#define GL_RESCALE_NORMAL 0x803A
+#define GL_POLYGON_OFFSET_FILL 0x8037
+#define GL_VERTEX_ARRAY 0x8074
+#define GL_NORMAL_ARRAY 0x8075
+#define GL_COLOR_ARRAY 0x8076
+#define GL_TEXTURE_COORD_ARRAY 0x8078
+#define GL_MULTISAMPLE 0x809D
+#define GL_SAMPLE_ALPHA_TO_COVERAGE 0x809E
+#define GL_SAMPLE_ALPHA_TO_ONE 0x809F
+#define GL_SAMPLE_COVERAGE 0x80A0
+
+/* ErrorCode */
+#define GL_NO_ERROR 0
+#define GL_INVALID_ENUM 0x0500
+#define GL_INVALID_VALUE 0x0501
+#define GL_INVALID_OPERATION 0x0502
+#define GL_STACK_OVERFLOW 0x0503
+#define GL_STACK_UNDERFLOW 0x0504
+#define GL_OUT_OF_MEMORY 0x0505
+
+/* FogMode */
+/* GL_LINEAR */
+#define GL_EXP 0x0800
+#define GL_EXP2 0x0801
+
+/* FogParameter */
+#define GL_FOG_DENSITY 0x0B62
+#define GL_FOG_START 0x0B63
+#define GL_FOG_END 0x0B64
+#define GL_FOG_MODE 0x0B65
+#define GL_FOG_COLOR 0x0B66
+
+/* FrontFaceDirection */
+#define GL_CW 0x0900
+#define GL_CCW 0x0901
+
+/* GetPName */
+#define GL_SMOOTH_POINT_SIZE_RANGE 0x0B12
+#define GL_SMOOTH_LINE_WIDTH_RANGE 0x0B22
+#define GL_ALIASED_POINT_SIZE_RANGE 0x846D
+#define GL_ALIASED_LINE_WIDTH_RANGE 0x846E
+#define GL_IMPLEMENTATION_COLOR_READ_TYPE_OES 0x8B9A
+#define GL_IMPLEMENTATION_COLOR_READ_FORMAT_OES 0x8B9B
+#define GL_MAX_LIGHTS 0x0D31
+#define GL_MAX_TEXTURE_SIZE 0x0D33
+#define GL_MAX_MODELVIEW_STACK_DEPTH 0x0D36
+#define GL_MAX_PROJECTION_STACK_DEPTH 0x0D38
+#define GL_MAX_TEXTURE_STACK_DEPTH 0x0D39
+#define GL_MAX_VIEWPORT_DIMS 0x0D3A
+#define GL_MAX_ELEMENTS_VERTICES 0x80E8
+#define GL_MAX_ELEMENTS_INDICES 0x80E9
+#define GL_MAX_TEXTURE_UNITS 0x84E2
+#define GL_NUM_COMPRESSED_TEXTURE_FORMATS 0x86A2
+#define GL_COMPRESSED_TEXTURE_FORMATS 0x86A3
+#define GL_SUBPIXEL_BITS 0x0D50
+#define GL_RED_BITS 0x0D52
+#define GL_GREEN_BITS 0x0D53
+#define GL_BLUE_BITS 0x0D54
+#define GL_ALPHA_BITS 0x0D55
+#define GL_DEPTH_BITS 0x0D56
+#define GL_STENCIL_BITS 0x0D57
+
+/* HintMode */
+#define GL_DONT_CARE 0x1100
+#define GL_FASTEST 0x1101
+#define GL_NICEST 0x1102
+
+/* HintTarget */
+#define GL_PERSPECTIVE_CORRECTION_HINT 0x0C50
+#define GL_POINT_SMOOTH_HINT 0x0C51
+#define GL_LINE_SMOOTH_HINT 0x0C52
+#define GL_POLYGON_SMOOTH_HINT 0x0C53
+#define GL_FOG_HINT 0x0C54
+
+/* LightModelParameter */
+#define GL_LIGHT_MODEL_AMBIENT 0x0B53
+#define GL_LIGHT_MODEL_TWO_SIDE 0x0B52
+
+/* LightParameter */
+#define GL_AMBIENT 0x1200
+#define GL_DIFFUSE 0x1201
+#define GL_SPECULAR 0x1202
+#define GL_POSITION 0x1203
+#define GL_SPOT_DIRECTION 0x1204
+#define GL_SPOT_EXPONENT 0x1205
+#define GL_SPOT_CUTOFF 0x1206
+#define GL_CONSTANT_ATTENUATION 0x1207
+#define GL_LINEAR_ATTENUATION 0x1208
+#define GL_QUADRATIC_ATTENUATION 0x1209
+
+/* DataType */
+#define GL_BYTE 0x1400
+#define GL_UNSIGNED_BYTE 0x1401
+#define GL_SHORT 0x1402
+#define GL_UNSIGNED_SHORT 0x1403
+#define GL_FLOAT 0x1406
+#define GL_FIXED 0x140C
+
+/* LogicOp */
+#define GL_CLEAR 0x1500
+#define GL_AND 0x1501
+#define GL_AND_REVERSE 0x1502
+#define GL_COPY 0x1503
+#define GL_AND_INVERTED 0x1504
+#define GL_NOOP 0x1505
+#define GL_XOR 0x1506
+#define GL_OR 0x1507
+#define GL_NOR 0x1508
+#define GL_EQUIV 0x1509
+#define GL_INVERT 0x150A
+#define GL_OR_REVERSE 0x150B
+#define GL_COPY_INVERTED 0x150C
+#define GL_OR_INVERTED 0x150D
+#define GL_NAND 0x150E
+#define GL_SET 0x150F
+
+/* MaterialFace */
+/* GL_FRONT_AND_BACK */
+
+/* MaterialParameter */
+#define GL_EMISSION 0x1600
+#define GL_SHININESS 0x1601
+#define GL_AMBIENT_AND_DIFFUSE 0x1602
+/* GL_AMBIENT */
+/* GL_DIFFUSE */
+/* GL_SPECULAR */
+
+/* MatrixMode */
+#define GL_MODELVIEW 0x1700
+#define GL_PROJECTION 0x1701
+#define GL_TEXTURE 0x1702
+
+/* NormalPointerType */
+/* GL_BYTE */
+/* GL_SHORT */
+/* GL_FLOAT */
+/* GL_FIXED */
+
+/* PixelFormat */
+#define GL_ALPHA 0x1906
+#define GL_RGB 0x1907
+#define GL_RGBA 0x1908
+#define GL_LUMINANCE 0x1909
+#define GL_LUMINANCE_ALPHA 0x190A
+
+/* PixelStoreParameter */
+#define GL_UNPACK_ALIGNMENT 0x0CF5
+#define GL_PACK_ALIGNMENT 0x0D05
+
+/* PixelType */
+/* GL_UNSIGNED_BYTE */
+#define GL_UNSIGNED_SHORT_4_4_4_4 0x8033
+#define GL_UNSIGNED_SHORT_5_5_5_1 0x8034
+#define GL_UNSIGNED_SHORT_5_6_5 0x8363
+
+/* ShadingModel */
+#define GL_FLAT 0x1D00
+#define GL_SMOOTH 0x1D01
+
+/* StencilFunction */
+/* GL_NEVER */
+/* GL_LESS */
+/* GL_EQUAL */
+/* GL_LEQUAL */
+/* GL_GREATER */
+/* GL_NOTEQUAL */
+/* GL_GEQUAL */
+/* GL_ALWAYS */
+
+/* StencilOp */
+/* GL_ZERO */
+#define GL_KEEP 0x1E00
+#define GL_REPLACE 0x1E01
+#define GL_INCR 0x1E02
+#define GL_DECR 0x1E03
+/* GL_INVERT */
+
+/* StringName */
+#define GL_VENDOR 0x1F00
+#define GL_RENDERER 0x1F01
+#define GL_VERSION 0x1F02
+#define GL_EXTENSIONS 0x1F03
+
+/* TexCoordPointerType */
+/* GL_SHORT */
+/* GL_FLOAT */
+/* GL_FIXED */
+/* GL_BYTE */
+
+/* TextureEnvMode */
+#define GL_MODULATE 0x2100
+#define GL_DECAL 0x2101
+/* GL_BLEND */
+#define GL_ADD 0x0104
+/* GL_REPLACE */
+
+/* TextureEnvParameter */
+#define GL_TEXTURE_ENV_MODE 0x2200
+#define GL_TEXTURE_ENV_COLOR 0x2201
+
+/* TextureEnvTarget */
+#define GL_TEXTURE_ENV 0x2300
+
+/* TextureMagFilter */
+#define GL_NEAREST 0x2600
+#define GL_LINEAR 0x2601
+
+/* TextureMinFilter */
+/* GL_NEAREST */
+/* GL_LINEAR */
+#define GL_NEAREST_MIPMAP_NEAREST 0x2700
+#define GL_LINEAR_MIPMAP_NEAREST 0x2701
+#define GL_NEAREST_MIPMAP_LINEAR 0x2702
+#define GL_LINEAR_MIPMAP_LINEAR 0x2703
+
+/* TextureParameterName */
+#define GL_TEXTURE_MAG_FILTER 0x2800
+#define GL_TEXTURE_MIN_FILTER 0x2801
+#define GL_TEXTURE_WRAP_S 0x2802
+#define GL_TEXTURE_WRAP_T 0x2803
+
+/* TextureTarget */
+/* GL_TEXTURE_2D */
+
+/* TextureUnit */
+#define GL_TEXTURE0 0x84C0
+#define GL_TEXTURE1 0x84C1
+#define GL_TEXTURE2 0x84C2
+#define GL_TEXTURE3 0x84C3
+#define GL_TEXTURE4 0x84C4
+#define GL_TEXTURE5 0x84C5
+#define GL_TEXTURE6 0x84C6
+#define GL_TEXTURE7 0x84C7
+#define GL_TEXTURE8 0x84C8
+#define GL_TEXTURE9 0x84C9
+#define GL_TEXTURE10 0x84CA
+#define GL_TEXTURE11 0x84CB
+#define GL_TEXTURE12 0x84CC
+#define GL_TEXTURE13 0x84CD
+#define GL_TEXTURE14 0x84CE
+#define GL_TEXTURE15 0x84CF
+#define GL_TEXTURE16 0x84D0
+#define GL_TEXTURE17 0x84D1
+#define GL_TEXTURE18 0x84D2
+#define GL_TEXTURE19 0x84D3
+#define GL_TEXTURE20 0x84D4
+#define GL_TEXTURE21 0x84D5
+#define GL_TEXTURE22 0x84D6
+#define GL_TEXTURE23 0x84D7
+#define GL_TEXTURE24 0x84D8
+#define GL_TEXTURE25 0x84D9
+#define GL_TEXTURE26 0x84DA
+#define GL_TEXTURE27 0x84DB
+#define GL_TEXTURE28 0x84DC
+#define GL_TEXTURE29 0x84DD
+#define GL_TEXTURE30 0x84DE
+#define GL_TEXTURE31 0x84DF
+
+/* TextureWrapMode */
+#define GL_REPEAT 0x2901
+#define GL_CLAMP_TO_EDGE 0x812F
+
+/* PixelInternalFormat */
+#define GL_PALETTE4_RGB8_OES 0x8B90
+#define GL_PALETTE4_RGBA8_OES 0x8B91
+#define GL_PALETTE4_R5_G6_B5_OES 0x8B92
+#define GL_PALETTE4_RGBA4_OES 0x8B93
+#define GL_PALETTE4_RGB5_A1_OES 0x8B94
+#define GL_PALETTE8_RGB8_OES 0x8B95
+#define GL_PALETTE8_RGBA8_OES 0x8B96
+#define GL_PALETTE8_R5_G6_B5_OES 0x8B97
+#define GL_PALETTE8_RGBA4_OES 0x8B98
+#define GL_PALETTE8_RGB5_A1_OES 0x8B99
+
+/* VertexPointerType */
+/* GL_SHORT */
+/* GL_FLOAT */
+/* GL_FIXED */
+/* GL_BYTE */
+
+/* LightName */
+#define GL_LIGHT0 0x4000
+#define GL_LIGHT1 0x4001
+#define GL_LIGHT2 0x4002
+#define GL_LIGHT3 0x4003
+#define GL_LIGHT4 0x4004
+#define GL_LIGHT5 0x4005
+#define GL_LIGHT6 0x4006
+#define GL_LIGHT7 0x4007
+
+
+/*************************************************************/
+
+#if !GL_ES_VERSION_2_0 // NOTE jwilkins: not in all versions of ES
+GLAPI void GLAPIENTRY glAlphaFunc (GLenum func, GLclampf ref);
+#endif // XXX
+GLAPI void GLAPIENTRY glBindTexture (GLenum target, GLuint texture);
+GLAPI void GLAPIENTRY glBlendFunc (GLenum sfactor, GLenum dfactor);
+GLAPI void GLAPIENTRY glClear (GLbitfield mask);
+GLAPI void GLAPIENTRY glClearColor (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
+GLAPI void GLAPIENTRY glClearStencil (GLint s);
+#if !GL_ES_VERSION_2_0 // NOTE jwilkins: not in all versions of ES
+GLAPI void GLAPIENTRY glColor4f (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
+#endif
+GLAPI void GLAPIENTRY glColorMask (GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha);
+#if !GL_ES_VERSION_2_0 // NOTE jwilkins: not in all versions of ES
+GLAPI void GLAPIENTRY glColorPointer (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);
+#endif
+GLAPI void GLAPIENTRY glCopyTexImage2D (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border);
+GLAPI void GLAPIENTRY glCopyTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+GLAPI void GLAPIENTRY glCullFace (GLenum mode);
+GLAPI void GLAPIENTRY glDeleteTextures (GLsizei n, const GLuint *textures);
+GLAPI void GLAPIENTRY glDepthFunc (GLenum func);
+GLAPI void GLAPIENTRY glDepthMask (GLboolean flag);
+GLAPI void GLAPIENTRY glDisable (GLenum cap);
+#if !GL_ES_VERSION_2_0 // NOTE jwilkins: not in all versions of ES
+GLAPI void GLAPIENTRY glDisableClientState (GLenum array);
+#endif
+GLAPI void GLAPIENTRY glDrawArrays (GLenum mode, GLint first, GLsizei count);
+GLAPI void GLAPIENTRY glDrawElements (GLenum mode, GLsizei count, GLenum type, const GLvoid *indices);
+GLAPI void GLAPIENTRY glEnable (GLenum cap);
+#if !GL_ES_VERSION_2_0 // NOTE jwilkins: not in all versions of ES
+GLAPI void GLAPIENTRY glEnableClientState (GLenum array);
+#endif
+GLAPI void GLAPIENTRY glFinish (void);
+GLAPI void GLAPIENTRY glFlush (void);
+#if !GL_ES_VERSION_2_0 // NOTE jwilkins: not in all versions of ES
+GLAPI void GLAPIENTRY glFogf (GLenum pname, GLfloat param);
+GLAPI void GLAPIENTRY glFogfv (GLenum pname, const GLfloat *params);
+#endif
+GLAPI void GLAPIENTRY glFrontFace (GLenum mode);
+GLAPI void GLAPIENTRY glGenTextures (GLsizei n, GLuint *textures);
+GLAPI GLenum GLAPIENTRY glGetError (void);
+GLAPI void GLAPIENTRY glGetIntegerv (GLenum pname, GLint *params);
+GLAPI const GLubyte * GLAPIENTRY glGetString (GLenum name);
+GLAPI void GLAPIENTRY glHint (GLenum target, GLenum mode);
+#if !GL_ES_VERSION_2_0 // NOTE jwilkins: not in all versions of ES
+GLAPI void GLAPIENTRY glLightModelf (GLenum pname, GLfloat param);
+GLAPI void GLAPIENTRY glLightModelfv (GLenum pname, const GLfloat *params);
+GLAPI void GLAPIENTRY glLightf (GLenum light, GLenum pname, GLfloat param);
+GLAPI void GLAPIENTRY glLightfv (GLenum light, GLenum pname, const GLfloat *params);
+#endif
+GLAPI void GLAPIENTRY glLineWidth (GLfloat width);
+#if !GL_ES_VERSION_2_0 // NOTE jwilkins: not in all versions of ES
+GLAPI void GLAPIENTRY glLoadIdentity (void);
+GLAPI void GLAPIENTRY glLoadMatrixf (const GLfloat *m);
+GLAPI void GLAPIENTRY glLogicOp (GLenum opcode);
+GLAPI void GLAPIENTRY glMaterialf (GLenum face, GLenum pname, GLfloat param);
+GLAPI void GLAPIENTRY glMaterialfv (GLenum face, GLenum pname, const GLfloat *params);
+GLAPI void GLAPIENTRY glMatrixMode (GLenum mode);
+GLAPI void GLAPIENTRY glMultMatrixf (const GLfloat *m);
+GLAPI void GLAPIENTRY glMultiTexCoord4f (GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q);
+GLAPI void GLAPIENTRY glNormal3f (GLfloat nx, GLfloat ny, GLfloat nz);
+GLAPI void GLAPIENTRY glNormalPointer (GLenum type, GLsizei stride, const GLvoid *pointer);
+#endif
+GLAPI void GLAPIENTRY glPixelStorei (GLenum pname, GLint param);
+#if !GL_ES_VERSION_2_0 // NOTE jwilkins: not in all versions of ES
+GLAPI void GLAPIENTRY glPointSize (GLfloat size);
+#endif // XXX
+GLAPI void GLAPIENTRY glPolygonOffset (GLfloat factor, GLfloat units);
+#if !GL_ES_VERSION_2_0 // NOTE jwilkins: not in all versions of ES
+GLAPI void GLAPIENTRY glPopMatrix (void);
+GLAPI void GLAPIENTRY glPushMatrix (void);
+#endif
+GLAPI void GLAPIENTRY glReadPixels (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *pixels);
+#if !GL_ES_VERSION_2_0 // NOTE jwilkins: not in all versions of ES
+GLAPI void GLAPIENTRY glRotatef (GLfloat angle, GLfloat x, GLfloat y, GLfloat z);
+GLAPI void GLAPIENTRY glScalef (GLfloat x, GLfloat y, GLfloat z);
+#endif
+GLAPI void GLAPIENTRY glScissor (GLint x, GLint y, GLsizei width, GLsizei height);
+#if !GL_ES_VERSION_2_0 // NOTE jwilkins: not in all versions of ES
+GLAPI void GLAPIENTRY glShadeModel (GLenum mode);
+#endif // XXX
+GLAPI void GLAPIENTRY glStencilFunc (GLenum func, GLint ref, GLuint mask);
+GLAPI void GLAPIENTRY glStencilMask (GLuint mask);
+GLAPI void GLAPIENTRY glStencilOp (GLenum fail, GLenum zfail, GLenum zpass);
+#if !GL_ES_VERSION_2_0 // NOTE jwilkins: not in all versions of ES
+GLAPI void GLAPIENTRY glTexCoordPointer (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);
+GLAPI void GLAPIENTRY glTexEnvf (GLenum target, GLenum pname, GLfloat param);
+GLAPI void GLAPIENTRY glTexEnvfv (GLenum target, GLenum pname, const GLfloat *params);
+#endif
+GLAPI void GLAPIENTRY glTexImage2D (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels);
+GLAPI void GLAPIENTRY glTexParameterf (GLenum target, GLenum pname, GLfloat param);
+GLAPI void GLAPIENTRY glTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels);
+#if !GL_ES_VERSION_2_0 // NOTE jwilkins: not in all versions of ES
+GLAPI void GLAPIENTRY glTranslatef (GLfloat x, GLfloat y, GLfloat z);
+GLAPI void GLAPIENTRY glVertexPointer (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);
+#endif
+GLAPI void GLAPIENTRY glViewport (GLint x, GLint y, GLsizei width, GLsizei height);
+
+/* --------------------------- GL_ES_VERSION_1_0 --------------------------- */
+
+#if GL_ES_VERSION_1_0 // NOTE jwilkins: should be if not ifdef
+#define GL_ES_VERSION_1_0 1
+
+typedef void (GLAPIENTRY * PFNGLACTIVETEXTUREPROC) (GLenum texture);
+typedef void (GLAPIENTRY * PFNGLALPHAFUNCXPROC) (GLenum func, GLclampx ref);
+typedef void (GLAPIENTRY * PFNGLCLEARCOLORXPROC) (GLclampx red, GLclampx green, GLclampx blue, GLclampx alpha);
+typedef void (GLAPIENTRY * PFNGLCLEARDEPTHFPROC) (GLclampf depth);
+typedef void (GLAPIENTRY * PFNGLCLEARDEPTHXPROC) (GLclampx depth);
+typedef void (GLAPIENTRY * PFNGLCLIENTACTIVETEXTUREPROC) (GLenum texture);
+typedef void (GLAPIENTRY * PFNGLCOLOR4XPROC) (GLfixed red, GLfixed green, GLfixed blue, GLfixed alpha);
+typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXIMAGE2DPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *data);
+typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid *data);
+typedef void (GLAPIENTRY * PFNGLDEPTHRANGEFPROC) (GLclampf zNear, GLclampf zFar);
+typedef void (GLAPIENTRY * PFNGLDEPTHRANGEXPROC) (GLclampx zNear, GLclampx zFar);
+typedef void (GLAPIENTRY * PFNGLFOGXPROC) (GLenum pname, GLfixed param);
+typedef void (GLAPIENTRY * PFNGLFOGXVPROC) (GLenum pname, const GLfixed *params);
+typedef void (GLAPIENTRY * PFNGLFRUSTUMFPROC) (GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat zNear, GLfloat zFar);
+typedef void (GLAPIENTRY * PFNGLFRUSTUMXPROC) (GLfixed left, GLfixed right, GLfixed bottom, GLfixed top, GLfixed zNear, GLfixed zFar);
+typedef void (GLAPIENTRY * PFNGLLIGHTMODELXPROC) (GLenum pname, GLfixed params);
+typedef void (GLAPIENTRY * PFNGLLIGHTMODELXVPROC) (GLenum pname, const GLfixed *params);
+typedef void (GLAPIENTRY * PFNGLLIGHTXPROC) (GLenum light, GLenum pname, GLfixed param);
+typedef void (GLAPIENTRY * PFNGLLIGHTXVPROC) (GLenum light, GLenum pname, const GLfixed *params);
+typedef void (GLAPIENTRY * PFNGLLINEWIDTHXPROC) (GLfixed width);
+typedef void (GLAPIENTRY * PFNGLLOADMATRIXXPROC) (const GLfixed *m);
+typedef void (GLAPIENTRY * PFNGLMATERIALXPROC) (GLenum face, GLenum pname, GLfixed param);
+typedef void (GLAPIENTRY * PFNGLMATERIALXVPROC) (GLenum face, GLenum pname, const GLfixed *params);
+typedef void (GLAPIENTRY * PFNGLMULTMATRIXXPROC) (const GLfixed *m);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD4FPROC) (GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD4XPROC) (GLenum target, GLfixed s, GLfixed t, GLfixed r, GLfixed q);
+typedef void (GLAPIENTRY * PFNGLNORMAL3XPROC) (GLfixed nx, GLfixed ny, GLfixed nz);
+typedef void (GLAPIENTRY * PFNGLORTHOFPROC) (GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat zNear, GLfloat zFar);
+typedef void (GLAPIENTRY * PFNGLORTHOXPROC) (GLfixed left, GLfixed right, GLfixed bottom, GLfixed top, GLfixed zNear, GLfixed zFar);
+typedef void (GLAPIENTRY * PFNGLPOINTSIZEXPROC) (GLfixed size);
+typedef void (GLAPIENTRY * PFNGLPOLYGONOFFSETXPROC) (GLfixed factor, GLfixed units);
+typedef void (GLAPIENTRY * PFNGLROTATEXPROC) (GLfixed angle, GLfixed x, GLfixed y, GLfixed z);
+typedef void (GLAPIENTRY * PFNGLSAMPLECOVERAGEPROC) (GLclampf value, GLboolean invert);
+typedef void (GLAPIENTRY * PFNGLSAMPLECOVERAGEXPROC) (GLclampx value, GLboolean invert);
+typedef void (GLAPIENTRY * PFNGLSCALEXPROC) (GLfixed x, GLfixed y, GLfixed z);
+typedef void (GLAPIENTRY * PFNGLTEXENVXPROC) (GLenum target, GLenum pname, GLfixed param);
+typedef void (GLAPIENTRY * PFNGLTEXENVXVPROC) (GLenum target, GLenum pname, const GLfixed *params);
+typedef void (GLAPIENTRY * PFNGLTEXPARAMETERXPROC) (GLenum target, GLenum pname, GLfixed param);
+typedef void (GLAPIENTRY * PFNGLTRANSLATEXPROC) (GLfixed x, GLfixed y, GLfixed z);
+
+#define glActiveTexture GLEW_GET_FUN(__glewActiveTexture)
+#define glAlphaFuncx GLEW_GET_FUN(__glewAlphaFuncx)
+#define glClearColorx GLEW_GET_FUN(__glewClearColorx)
+#define glClearDepthf GLEW_GET_FUN(__glewClearDepthf)
+#define glClearDepthx GLEW_GET_FUN(__glewClearDepthx)
+#define glClientActiveTexture GLEW_GET_FUN(__glewClientActiveTexture)
+#define glColor4x GLEW_GET_FUN(__glewColor4x)
+#define glCompressedTexImage2D GLEW_GET_FUN(__glewCompressedTexImage2D)
+#define glCompressedTexSubImage2D GLEW_GET_FUN(__glewCompressedTexSubImage2D)
+#define glDepthRangef GLEW_GET_FUN(__glewDepthRangef)
+#define glDepthRangex GLEW_GET_FUN(__glewDepthRangex)
+#define glFogx GLEW_GET_FUN(__glewFogx)
+#define glFogxv GLEW_GET_FUN(__glewFogxv)
+#define glFrustumf GLEW_GET_FUN(__glewFrustumf)
+#define glFrustumx GLEW_GET_FUN(__glewFrustumx)
+#define glLightModelx GLEW_GET_FUN(__glewLightModelx)
+#define glLightModelxv GLEW_GET_FUN(__glewLightModelxv)
+#define glLightx GLEW_GET_FUN(__glewLightx)
+#define glLightxv GLEW_GET_FUN(__glewLightxv)
+#define glLineWidthx GLEW_GET_FUN(__glewLineWidthx)
+#define glLoadMatrixx GLEW_GET_FUN(__glewLoadMatrixx)
+#define glMaterialx GLEW_GET_FUN(__glewMaterialx)
+#define glMaterialxv GLEW_GET_FUN(__glewMaterialxv)
+#define glMultMatrixx GLEW_GET_FUN(__glewMultMatrixx)
+#define glMultiTexCoord4f GLEW_GET_FUN(__glewMultiTexCoord4f)
+#define glMultiTexCoord4x GLEW_GET_FUN(__glewMultiTexCoord4x)
+#define glNormal3x GLEW_GET_FUN(__glewNormal3x)
+#define glOrthof GLEW_GET_FUN(__glewOrthof)
+#define glOrthox GLEW_GET_FUN(__glewOrthox)
+#define glPointSizex GLEW_GET_FUN(__glewPointSizex)
+#define glPolygonOffsetx GLEW_GET_FUN(__glewPolygonOffsetx)
+#define glRotatex GLEW_GET_FUN(__glewRotatex)
+#define glSampleCoverage GLEW_GET_FUN(__glewSampleCoverage)
+#define glSampleCoveragex GLEW_GET_FUN(__glewSampleCoveragex)
+#define glScalex GLEW_GET_FUN(__glewScalex)
+#define glTexEnvx GLEW_GET_FUN(__glewTexEnvx)
+#define glTexEnvxv GLEW_GET_FUN(__glewTexEnvxv)
+#define glTexParameterx GLEW_GET_FUN(__glewTexParameterx)
+#define glTranslatex GLEW_GET_FUN(__glewTranslatex)
+
+#else // XXX
+#define GL_ES_VERSION_1_0 0 // NOTE jwilkins: define version token
+#endif /* !GL_ES_VERSION_1_0 */
+
+#define GLEW_ES_VERSION_1_0 GLEW_GET_VAR(__GLEW_ES_VERSION_1_0) // NOTE jwilkins: always needs to be defined
+
+/* -------------------------- GL_ES_VERSION_CL_1_1 ------------------------- */
+
+#if GL_ES_VERSION_CL_1_1 // NOTE jwilkins: should be if not ifdef
+#define GL_ES_VERSION_CL_1_1 1
+
+#define GL_VERSION_ES_CL_1_1 0x1
+#define GL_VERSION_ES_CL_1_0 0x1
+#define GL_CURRENT_COLOR 0x0B00
+#define GL_CURRENT_NORMAL 0x0B02
+#define GL_CURRENT_TEXTURE_COORDS 0x0B03
+#define GL_POINT_SIZE 0x0B11
+#define GL_LINE_WIDTH 0x0B21
+#define GL_CULL_FACE_MODE 0x0B45
+#define GL_FRONT_FACE 0x0B46
+#define GL_SHADE_MODEL 0x0B54
+#define GL_DEPTH_RANGE 0x0B70
+#define GL_DEPTH_WRITEMASK 0x0B72
+#define GL_DEPTH_CLEAR_VALUE 0x0B73
+#define GL_DEPTH_FUNC 0x0B74
+#define GL_STENCIL_CLEAR_VALUE 0x0B91
+#define GL_STENCIL_FUNC 0x0B92
+#define GL_STENCIL_VALUE_MASK 0x0B93
+#define GL_STENCIL_FAIL 0x0B94
+#define GL_STENCIL_PASS_DEPTH_FAIL 0x0B95
+#define GL_STENCIL_PASS_DEPTH_PASS 0x0B96
+#define GL_STENCIL_REF 0x0B97
+#define GL_STENCIL_WRITEMASK 0x0B98
+#define GL_MATRIX_MODE 0x0BA0
+#define GL_VIEWPORT 0x0BA2
+#define GL_MODELVIEW_STACK_DEPTH 0x0BA3
+#define GL_PROJECTION_STACK_DEPTH 0x0BA4
+#define GL_TEXTURE_STACK_DEPTH 0x0BA5
+#define GL_MODELVIEW_MATRIX 0x0BA6
+#define GL_PROJECTION_MATRIX 0x0BA7
+#define GL_TEXTURE_MATRIX 0x0BA8
+#define GL_ALPHA_TEST_FUNC 0x0BC1
+#define GL_ALPHA_TEST_REF 0x0BC2
+#define GL_BLEND_DST 0x0BE0
+#define GL_BLEND_SRC 0x0BE1
+#define GL_LOGIC_OP_MODE 0x0BF0
+#define GL_SCISSOR_BOX 0x0C10
+#define GL_COLOR_CLEAR_VALUE 0x0C22
+#define GL_COLOR_WRITEMASK 0x0C23
+#define GL_ALPHA_SCALE 0x0D1C
+#define GL_MAX_CLIP_PLANES 0x0D32
+#define GL_POLYGON_OFFSET_UNITS 0x2A00
+#define GL_CLIP_PLANE0 0x3000
+#define GL_CLIP_PLANE1 0x3001
+#define GL_CLIP_PLANE2 0x3002
+#define GL_CLIP_PLANE3 0x3003
+#define GL_CLIP_PLANE4 0x3004
+#define GL_CLIP_PLANE5 0x3005
+#define GL_POLYGON_OFFSET_FACTOR 0x8038
+#define GL_TEXTURE_BINDING_2D 0x8069
+#define GL_VERTEX_ARRAY_SIZE 0x807A
+#define GL_VERTEX_ARRAY_TYPE 0x807B
+#define GL_VERTEX_ARRAY_STRIDE 0x807C
+#define GL_NORMAL_ARRAY_TYPE 0x807E
+#define GL_NORMAL_ARRAY_STRIDE 0x807F
+#define GL_COLOR_ARRAY_SIZE 0x8081
+#define GL_COLOR_ARRAY_TYPE 0x8082
+#define GL_COLOR_ARRAY_STRIDE 0x8083
+#define GL_TEXTURE_COORD_ARRAY_SIZE 0x8088
+#define GL_TEXTURE_COORD_ARRAY_TYPE 0x8089
+#define GL_TEXTURE_COORD_ARRAY_STRIDE 0x808A
+#define GL_VERTEX_ARRAY_POINTER 0x808E
+#define GL_NORMAL_ARRAY_POINTER 0x808F
+#define GL_COLOR_ARRAY_POINTER 0x8090
+#define GL_TEXTURE_COORD_ARRAY_POINTER 0x8092
+#define GL_SAMPLE_BUFFERS 0x80A8
+#define GL_SAMPLES 0x80A9
+#define GL_SAMPLE_COVERAGE_VALUE 0x80AA
+#define GL_SAMPLE_COVERAGE_INVERT 0x80AB
+#define GL_POINT_SIZE_MIN 0x8126
+#define GL_POINT_SIZE_MAX 0x8127
+#define GL_POINT_FADE_THRESHOLD_SIZE 0x8128
+#define GL_POINT_DISTANCE_ATTENUATION 0x8129
+#define GL_GENERATE_MIPMAP 0x8191
+#define GL_GENERATE_MIPMAP_HINT 0x8192
+#define GL_ACTIVE_TEXTURE 0x84E0
+#define GL_CLIENT_ACTIVE_TEXTURE 0x84E1
+#define GL_SUBTRACT 0x84E7
+#define GL_COMBINE 0x8570
+#define GL_COMBINE_RGB 0x8571
+#define GL_COMBINE_ALPHA 0x8572
+#define GL_RGB_SCALE 0x8573
+#define GL_ADD_SIGNED 0x8574
+#define GL_INTERPOLATE 0x8575
+#define GL_CONSTANT 0x8576
+#define GL_PRIMARY_COLOR 0x8577
+#define GL_PREVIOUS 0x8578
+#define GL_SRC0_RGB 0x8580
+#define GL_SRC1_RGB 0x8581
+#define GL_SRC2_RGB 0x8582
+#define GL_SRC0_ALPHA 0x8588
+#define GL_SRC1_ALPHA 0x8589
+#define GL_SRC2_ALPHA 0x858A
+#define GL_OPERAND0_RGB 0x8590
+#define GL_OPERAND1_RGB 0x8591
+#define GL_OPERAND2_RGB 0x8592
+#define GL_OPERAND0_ALPHA 0x8598
+#define GL_OPERAND1_ALPHA 0x8599
+#define GL_OPERAND2_ALPHA 0x859A
+#define GL_DOT3_RGB 0x86AE
+#define GL_DOT3_RGBA 0x86AF
+#define GL_BUFFER_SIZE 0x8764
+#define GL_BUFFER_USAGE 0x8765
+#define GL_ARRAY_BUFFER 0x8892
+#define GL_ELEMENT_ARRAY_BUFFER 0x8893
+#define GL_ARRAY_BUFFER_BINDING 0x8894
+#define GL_ELEMENT_ARRAY_BUFFER_BINDING 0x8895
+#define GL_VERTEX_ARRAY_BUFFER_BINDING 0x8896
+#define GL_NORMAL_ARRAY_BUFFER_BINDING 0x8897
+#define GL_COLOR_ARRAY_BUFFER_BINDING 0x8898
+#define GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING 0x889A
+#define GL_STATIC_DRAW 0x88E4
+#define GL_DYNAMIC_DRAW 0x88E8
+
+typedef char GLchar;
+typedef khronos_intptr_t GLintptr;
+typedef khronos_ssize_t GLsizeiptr;
+
+typedef void (GLAPIENTRY * PFNGLBINDBUFFERPROC) (GLenum , GLuint );
+typedef void (GLAPIENTRY * PFNGLBUFFERDATAPROC) (GLenum , GLsizeiptr, const GLvoid *, GLenum );
+typedef void (GLAPIENTRY * PFNGLBUFFERSUBDATAPROC) (GLenum, GLintptr, GLsizeiptr, const GLvoid *);
+typedef void (GLAPIENTRY * PFNGLCLIPPLANEXPROC) (GLenum ,const GLfixed *);
+typedef void (GLAPIENTRY * PFNGLCOLOR4UBPROC) (GLubyte, GLubyte, GLubyte, GLubyte);
+typedef void (GLAPIENTRY * PFNGLDELETEBUFFERSPROC) (GLsizei , const GLuint *);
+typedef void (GLAPIENTRY * PFNGLGENBUFFERSPROC) (GLsizei, GLuint *);
+typedef void (GLAPIENTRY * PFNGLGETBOOLEANVPROC) (GLenum, GLboolean *);
+typedef void (GLAPIENTRY * PFNGLGETBUFFERPARAMETERIVPROC) (GLenum, GLenum, GLint *);
+typedef void (GLAPIENTRY * PFNGLGETCLIPPLANEXPROC) (GLenum ,GLfixed*);
+typedef void (GLAPIENTRY * PFNGLGETFIXEDVPROC) (GLenum, GLfixed *);
+typedef void (GLAPIENTRY * PFNGLGETLIGHTXVPROC) (GLenum, GLenum, GLfixed *);
+typedef void (GLAPIENTRY * PFNGLGETMATERIALXVPROC) (GLenum, GLenum, GLfixed *);
+typedef void (GLAPIENTRY * PFNGLGETPOINTERVPROC) (GLenum , GLvoid **);
+typedef void (GLAPIENTRY * PFNGLGETTEXENVIVPROC) (GLenum, GLenum , GLint *);
+typedef void (GLAPIENTRY * PFNGLGETTEXENVXVPROC) (GLenum, GLenum, GLfixed *);
+typedef void (GLAPIENTRY * PFNGLGETTEXPARAMETERIVPROC) (GLenum, GLenum, GLint *);
+typedef void (GLAPIENTRY * PFNGLGETTEXPARAMETERXVPROC) (GLenum, GLenum, GLfixed *);
+typedef GLboolean (GLAPIENTRY * PFNGLISBUFFERPROC) (GLuint);
+typedef GLboolean (GLAPIENTRY * PFNGLISENABLEDPROC) (GLenum);
+typedef GLboolean (GLAPIENTRY * PFNGLISTEXTUREPROC) (GLuint);
+typedef void (GLAPIENTRY * PFNGLPOINTPARAMETERXPROC) (GLenum, GLfixed);
+typedef void (GLAPIENTRY * PFNGLPOINTPARAMETERXVPROC) (GLenum, const GLfixed *);
+typedef void (GLAPIENTRY * PFNGLTEXENVIPROC) (GLenum, GLenum, GLint);
+typedef void (GLAPIENTRY * PFNGLTEXENVIVPROC) (GLenum, GLenum, const GLint *);
+typedef void (GLAPIENTRY * PFNGLTEXPARAMETERIPROC) (GLenum, GLenum, GLint);
+typedef void (GLAPIENTRY * PFNGLTEXPARAMETERIVPROC) (GLenum, GLenum, const GLint *);
+typedef void (GLAPIENTRY * PFNGLTEXPARAMETERXVPROC) (GLenum, GLenum, const GLfixed *);
+
+#define glBindBuffer GLEW_GET_FUN(__glewBindBuffer)
+#define glBufferData GLEW_GET_FUN(__glewBufferData)
+#define glBufferSubData GLEW_GET_FUN(__glewBufferSubData)
+#define glClipPlanex GLEW_GET_FUN(__glewClipPlanex)
+#define glColor4ub GLEW_GET_FUN(__glewColor4ub)
+#define glDeleteBuffers GLEW_GET_FUN(__glewDeleteBuffers)
+#define glGenBuffers GLEW_GET_FUN(__glewGenBuffers)
+#define glGetBooleanv GLEW_GET_FUN(__glewGetBooleanv)
+#define glGetBufferParameteriv GLEW_GET_FUN(__glewGetBufferParameteriv)
+#define glGetClipPlanex GLEW_GET_FUN(__glewGetClipPlanex)
+#define glGetFixedv GLEW_GET_FUN(__glewGetFixedv)
+#define glGetLightxv GLEW_GET_FUN(__glewGetLightxv)
+#define glGetMaterialxv GLEW_GET_FUN(__glewGetMaterialxv)
+#define glGetPointerv GLEW_GET_FUN(__glewGetPointerv)
+#define glGetTexEnviv GLEW_GET_FUN(__glewGetTexEnviv)
+#define glGetTexEnvxv GLEW_GET_FUN(__glewGetTexEnvxv)
+#define glGetTexParameteriv GLEW_GET_FUN(__glewGetTexParameteriv)
+#define glGetTexParameterxv GLEW_GET_FUN(__glewGetTexParameterxv)
+#define glIsBuffer GLEW_GET_FUN(__glewIsBuffer)
+#define glIsEnabled GLEW_GET_FUN(__glewIsEnabled)
+#define glIsTexture GLEW_GET_FUN(__glewIsTexture)
+#define glPointParameterx GLEW_GET_FUN(__glewPointParameterx)
+#define glPointParameterxv GLEW_GET_FUN(__glewPointParameterxv)
+#define glTexEnvi GLEW_GET_FUN(__glewTexEnvi)
+#define glTexEnviv GLEW_GET_FUN(__glewTexEnviv)
+#define glTexParameteri GLEW_GET_FUN(__glewTexParameteri)
+#define glTexParameteriv GLEW_GET_FUN(__glewTexParameteriv)
+#define glTexParameterxv GLEW_GET_FUN(__glewTexParameterxv)
+
+#else // XXX
+#define GL_ES_VERSION_CL_1_1 0 // NOTE jwilkins: define version token
+#endif /* !GL_ES_VERSION_CL_1_1 */
+
+#define GLEW_ES_VERSION_CL_1_1 GLEW_GET_VAR(__GLEW_ES_VERSION_CL_1_1) // NOTE jwilkins: always needs to be defined
+
+/* -------------------------- GL_ES_VERSION_CM_1_1 ------------------------- */
+
+#if GL_ES_VERSION_CM_1_1 // NOTE jwilkins: should be if not ifdef
+#define GL_ES_VERSION_CM_1_1 1
+
+#define GL_VERSION_ES_CM_1_1 0x1
+#define GL_VERSION_ES_CM_1_0 0x1
+
+typedef void (GLAPIENTRY * PFNGLCLIPPLANEFPROC) (GLenum, const GLfloat *);
+typedef void (GLAPIENTRY * PFNGLGETCLIPPLANEFPROC) (GLenum , GLfloat* );
+typedef void (GLAPIENTRY * PFNGLGETFLOATVPROC) (GLenum , GLfloat *);
+typedef void (GLAPIENTRY * PFNGLGETLIGHTFVPROC) (GLenum , GLenum , GLfloat *);
+typedef void (GLAPIENTRY * PFNGLGETMATERIALFVPROC) (GLenum, GLenum, GLfloat *);
+typedef void (GLAPIENTRY * PFNGLGETTEXENVFVPROC) (GLenum env, GLenum, GLfloat *);
+typedef void (GLAPIENTRY * PFNGLGETTEXPARAMETERFVPROC) (GLenum, GLenum, GLfloat *);
+typedef void (GLAPIENTRY * PFNGLPOINTPARAMETERFPROC) (GLenum , GLfloat );
+typedef void (GLAPIENTRY * PFNGLPOINTPARAMETERFVPROC) (GLenum, const GLfloat *);
+typedef void (GLAPIENTRY * PFNGLTEXPARAMETERFVPROC) (GLenum, GLenum , const GLfloat *);
+
+#define glClipPlanef GLEW_GET_FUN(__glewClipPlanef)
+#define glGetClipPlanef GLEW_GET_FUN(__glewGetClipPlanef)
+#define glGetFloatv GLEW_GET_FUN(__glewGetFloatv)
+#define glGetLightfv GLEW_GET_FUN(__glewGetLightfv)
+#define glGetMaterialfv GLEW_GET_FUN(__glewGetMaterialfv)
+#define glGetTexEnvfv GLEW_GET_FUN(__glewGetTexEnvfv)
+#define glGetTexParameterfv GLEW_GET_FUN(__glewGetTexParameterfv)
+#define glPointParameterf GLEW_GET_FUN(__glewPointParameterf)
+#define glPointParameterfv GLEW_GET_FUN(__glewPointParameterfv)
+#define glTexParameterfv GLEW_GET_FUN(__glewTexParameterfv)
+
+#else // XXX
+#define GL_ES_VERSION_CM_1_1 0 // NOTE jwilkins: define version token
+#endif /* !GL_ES_VERSION_CM_1_1 */
+
+#define GLEW_ES_VERSION_CM_1_1 GLEW_GET_VAR(__GLEW_ES_VERSION_CM_1_1) // NOTE jwilkins: always needs to be defined
+
+/* --------------------------- GL_ES_VERSION_2_0 --------------------------- */
+
+#if GL_ES_VERSION_2_0 // NOTE jwilkins: should be if not ifdef
+#define GL_ES_VERSION_2_0 1
+
+#define GL_NONE 0
+#define GL_INVALID_FRAMEBUFFER_OPERATION 0x0506
+#define GL_INT 0x1404
+#define GL_UNSIGNED_INT 0x1405
+#define GL_STENCIL_INDEX 0x1901
+#define GL_DEPTH_COMPONENT 0x1902
+#define GL_CONSTANT_COLOR 0x8001
+#define GL_ONE_MINUS_CONSTANT_COLOR 0x8002
+#define GL_CONSTANT_ALPHA 0x8003
+#define GL_ONE_MINUS_CONSTANT_ALPHA 0x8004
+#define GL_BLEND_COLOR 0x8005
+#define GL_FUNC_ADD 0x8006
+#define GL_BLEND_EQUATION 0x8009
+#define GL_BLEND_EQUATION_RGB 0x8009
+#define GL_FUNC_SUBTRACT 0x800A
+#define GL_FUNC_REVERSE_SUBTRACT 0x800B
+#define GL_RGBA4 0x8056
+#define GL_RGB5_A1 0x8057
+#define GL_BLEND_DST_RGB 0x80C8
+#define GL_BLEND_SRC_RGB 0x80C9
+#define GL_BLEND_DST_ALPHA 0x80CA
+#define GL_BLEND_SRC_ALPHA 0x80CB
+#define GL_DEPTH_COMPONENT16 0x81A5
+#define GL_MIRRORED_REPEAT 0x8370
+#define GL_MAX_RENDERBUFFER_SIZE 0x84E8
+#define GL_INCR_WRAP 0x8507
+#define GL_DECR_WRAP 0x8508
+#define GL_TEXTURE_CUBE_MAP 0x8513
+#define GL_TEXTURE_BINDING_CUBE_MAP 0x8514
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_X 0x8515
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_X 0x8516
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_Y 0x8517
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y 0x8518
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z 0x8519
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z 0x851A
+#define GL_MAX_CUBE_MAP_TEXTURE_SIZE 0x851C
+#define GL_VERTEX_ATTRIB_ARRAY_ENABLED 0x8622
+#define GL_VERTEX_ATTRIB_ARRAY_SIZE 0x8623
+#define GL_VERTEX_ATTRIB_ARRAY_STRIDE 0x8624
+#define GL_VERTEX_ATTRIB_ARRAY_TYPE 0x8625
+#define GL_CURRENT_VERTEX_ATTRIB 0x8626
+#define GL_VERTEX_ATTRIB_ARRAY_POINTER 0x8645
+#define GL_STENCIL_BACK_FUNC 0x8800
+#define GL_STENCIL_BACK_FAIL 0x8801
+#define GL_STENCIL_BACK_PASS_DEPTH_FAIL 0x8802
+#define GL_STENCIL_BACK_PASS_DEPTH_PASS 0x8803
+#define GL_BLEND_EQUATION_ALPHA 0x883D
+#define GL_MAX_VERTEX_ATTRIBS 0x8869
+#define GL_VERTEX_ATTRIB_ARRAY_NORMALIZED 0x886A
+#define GL_MAX_TEXTURE_IMAGE_UNITS 0x8872
+#define GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING 0x889F
+#define GL_STREAM_DRAW 0x88E0
+#define GL_FRAGMENT_SHADER 0x8B30
+#define GL_VERTEX_SHADER 0x8B31
+#define GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS 0x8B4C
+#define GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS 0x8B4D
+#define GL_SHADER_TYPE 0x8B4F
+#define GL_FLOAT_VEC2 0x8B50
+#define GL_FLOAT_VEC3 0x8B51
+#define GL_FLOAT_VEC4 0x8B52
+#define GL_INT_VEC2 0x8B53
+#define GL_INT_VEC3 0x8B54
+#define GL_INT_VEC4 0x8B55
+#define GL_BOOL 0x8B56
+#define GL_BOOL_VEC2 0x8B57
+#define GL_BOOL_VEC3 0x8B58
+#define GL_BOOL_VEC4 0x8B59
+#define GL_FLOAT_MAT2 0x8B5A
+#define GL_FLOAT_MAT3 0x8B5B
+#define GL_FLOAT_MAT4 0x8B5C
+#define GL_SAMPLER_2D 0x8B5E
+#define GL_SAMPLER_CUBE 0x8B60
+#define GL_DELETE_STATUS 0x8B80
+#define GL_COMPILE_STATUS 0x8B81
+#define GL_LINK_STATUS 0x8B82
+#define GL_VALIDATE_STATUS 0x8B83
+#define GL_INFO_LOG_LENGTH 0x8B84
+#define GL_ATTACHED_SHADERS 0x8B85
+#define GL_ACTIVE_UNIFORMS 0x8B86
+#define GL_ACTIVE_UNIFORM_MAX_LENGTH 0x8B87
+#define GL_SHADER_SOURCE_LENGTH 0x8B88
+#define GL_ACTIVE_ATTRIBUTES 0x8B89
+#define GL_ACTIVE_ATTRIBUTE_MAX_LENGTH 0x8B8A
+#define GL_SHADING_LANGUAGE_VERSION 0x8B8C
+#define GL_CURRENT_PROGRAM 0x8B8D
+#define GL_IMPLEMENTATION_COLOR_READ_TYPE 0x8B9A
+#define GL_IMPLEMENTATION_COLOR_READ_FORMAT 0x8B9B
+#define GL_STENCIL_BACK_REF 0x8CA3
+#define GL_STENCIL_BACK_VALUE_MASK 0x8CA4
+#define GL_STENCIL_BACK_WRITEMASK 0x8CA5
+#define GL_FRAMEBUFFER_BINDING 0x8CA6
+#define GL_RENDERBUFFER_BINDING 0x8CA7
+#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE 0x8CD0
+#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME 0x8CD1
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL 0x8CD2
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE 0x8CD3
+#define GL_FRAMEBUFFER_COMPLETE 0x8CD5
+#define GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT 0x8CD6
+#define GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT 0x8CD7
+#define GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS 0x8CD9
+#define GL_FRAMEBUFFER_UNSUPPORTED 0x8CDD
+#define GL_COLOR_ATTACHMENT0 0x8CE0
+#define GL_DEPTH_ATTACHMENT 0x8D00
+#define GL_STENCIL_ATTACHMENT 0x8D20
+#define GL_FRAMEBUFFER 0x8D40
+#define GL_RENDERBUFFER 0x8D41
+#define GL_RENDERBUFFER_WIDTH 0x8D42
+#define GL_RENDERBUFFER_HEIGHT 0x8D43
+#define GL_RENDERBUFFER_INTERNAL_FORMAT 0x8D44
+#define GL_STENCIL_INDEX8 0x8D48
+#define GL_RENDERBUFFER_RED_SIZE 0x8D50
+#define GL_RENDERBUFFER_GREEN_SIZE 0x8D51
+#define GL_RENDERBUFFER_BLUE_SIZE 0x8D52
+#define GL_RENDERBUFFER_ALPHA_SIZE 0x8D53
+#define GL_RENDERBUFFER_DEPTH_SIZE 0x8D54
+#define GL_RENDERBUFFER_STENCIL_SIZE 0x8D55
+#define GL_RGB565 0x8D62
+#define GL_LOW_FLOAT 0x8DF0
+#define GL_MEDIUM_FLOAT 0x8DF1
+#define GL_HIGH_FLOAT 0x8DF2
+#define GL_LOW_INT 0x8DF3
+#define GL_MEDIUM_INT 0x8DF4
+#define GL_HIGH_INT 0x8DF5
+#define GL_SHADER_BINARY_FORMATS 0x8DF8
+#define GL_NUM_SHADER_BINARY_FORMATS 0x8DF9
+#define GL_SHADER_COMPILER 0x8DFA
+#define GL_MAX_VERTEX_UNIFORM_VECTORS 0x8DFB
+#define GL_MAX_VARYING_VECTORS 0x8DFC
+#define GL_MAX_FRAGMENT_UNIFORM_VECTORS 0x8DFD
+
+#define GL_VIEWPORT 0x0BA2 // XXX missing enum
+#define GL_SCISSOR_BOX 0x0C10 // XXX missing enum
+#define GL_GENERATE_MIPMAP_HINT 0x8192 // XXX missing enum
+#define GL_ARRAY_BUFFER 0x8892 // XXX missing enum
+#define GL_ELEMENT_ARRAY_BUFFER 0x8893 // XXX missing enum
+#define GL_ARRAY_BUFFER_BINDING 0x8894 // XXX missing enum
+#define GL_ELEMENT_ARRAY_BUFFER_BINDING 0x8895 // XXX missing enum
+#define GL_STATIC_DRAW 0x88E4 // XXX missing enum
+#define GL_DYNAMIC_DRAW 0x88E8 // XXX missing enum
+#define GL_SAMPLE_BUFFERS 0x80A8 // XXX missing enum
+
+typedef char GLchar; // NOTE jwilkins: this typedef is missing when ES 1.1 is not enabled
+typedef khronos_intptr_t GLintptr; // XXX
+typedef khronos_ssize_t GLsizeiptr; // XXX
+
+typedef void (GLAPIENTRY * PFNGLATTACHSHADERPROC) (GLuint program, GLuint shader);
+typedef void (GLAPIENTRY * PFNGLBINDATTRIBLOCATIONPROC) (GLuint program, GLuint index, const GLchar* name);
+typedef void (GLAPIENTRY * PFNGLBINDFRAMEBUFFERPROC) (GLenum target, GLuint framebuffer);
+typedef void (GLAPIENTRY * PFNGLBINDRENDERBUFFERPROC) (GLenum target, GLuint renderbuffer);
+typedef void (GLAPIENTRY * PFNGLBLENDCOLORPROC) (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
+typedef void (GLAPIENTRY * PFNGLBLENDEQUATIONPROC) ( GLenum mode );
+typedef void (GLAPIENTRY * PFNGLBLENDEQUATIONSEPARATEPROC) (GLenum modeRGB, GLenum modeAlpha);
+typedef void (GLAPIENTRY * PFNGLBLENDFUNCSEPARATEPROC) (GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha);
+typedef GLenum (GLAPIENTRY * PFNGLCHECKFRAMEBUFFERSTATUSPROC) (GLenum target);
+typedef void (GLAPIENTRY * PFNGLCOMPILESHADERPROC) (GLuint shader);
+typedef GLuint (GLAPIENTRY * PFNGLCREATEPROGRAMPROC) (void);
+typedef GLuint (GLAPIENTRY * PFNGLCREATESHADERPROC) (GLenum type);
+typedef void (GLAPIENTRY * PFNGLDELETEFRAMEBUFFERSPROC) (GLsizei n, const GLuint* framebuffers);
+typedef void (GLAPIENTRY * PFNGLDELETEPROGRAMPROC) (GLuint program);
+typedef void (GLAPIENTRY * PFNGLDELETERENDERBUFFERSPROC) (GLsizei n, const GLuint* renderbuffers);
+typedef void (GLAPIENTRY * PFNGLDELETESHADERPROC) (GLuint shader);
+typedef void (GLAPIENTRY * PFNGLDETACHSHADERPROC) (GLuint program, GLuint shader);
+typedef void (GLAPIENTRY * PFNGLDISABLEVERTEXATTRIBARRAYPROC) (GLuint index);
+typedef void (GLAPIENTRY * PFNGLENABLEVERTEXATTRIBARRAYPROC) (GLuint index);
+typedef void (GLAPIENTRY * PFNGLFRAMEBUFFERRENDERBUFFERPROC) (GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer);
+typedef void (GLAPIENTRY * PFNGLFRAMEBUFFERTEXTURE2DPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
+typedef void (GLAPIENTRY * PFNGLGENFRAMEBUFFERSPROC) (GLsizei n, GLuint* framebuffers);
+typedef void (GLAPIENTRY * PFNGLGENRENDERBUFFERSPROC) (GLsizei n, GLuint* renderbuffers);
+typedef void (GLAPIENTRY * PFNGLGENERATEMIPMAPPROC) (GLenum target);
+typedef void (GLAPIENTRY * PFNGLGETACTIVEATTRIBPROC) (GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, GLchar* name);
+typedef void (GLAPIENTRY * PFNGLGETACTIVEUNIFORMPROC) (GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, GLchar* name);
+typedef void (GLAPIENTRY * PFNGLGETATTACHEDSHADERSPROC) (GLuint program, GLsizei maxcount, GLsizei* count, GLuint* shaders);
+typedef int (GLAPIENTRY * PFNGLGETATTRIBLOCATIONPROC) (GLuint program, const GLchar* name);
+typedef void (GLAPIENTRY * PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC) (GLenum target, GLenum attachment, GLenum pname, GLint* params);
+typedef void (GLAPIENTRY * PFNGLGETPROGRAMINFOLOGPROC) (GLuint program, GLsizei bufsize, GLsizei* length, GLchar* infolog);
+typedef void (GLAPIENTRY * PFNGLGETPROGRAMIVPROC) (GLuint program, GLenum pname, GLint* params);
+typedef void (GLAPIENTRY * PFNGLGETRENDERBUFFERPARAMETERIVPROC) (GLenum target, GLenum pname, GLint* params);
+typedef void (GLAPIENTRY * PFNGLGETSHADERINFOLOGPROC) (GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* infolog);
+typedef void (GLAPIENTRY * PFNGLGETSHADERPRECISIONFORMATPROC) (GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision);
+typedef void (GLAPIENTRY * PFNGLGETSHADERSOURCEPROC) (GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* source);
+typedef void (GLAPIENTRY * PFNGLGETSHADERIVPROC) (GLuint shader, GLenum pname, GLint* params);
+typedef int (GLAPIENTRY * PFNGLGETUNIFORMLOCATIONPROC) (GLuint program, const GLchar* name);
+typedef void (GLAPIENTRY * PFNGLGETUNIFORMFVPROC) (GLuint program, GLint location, GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLGETUNIFORMIVPROC) (GLuint program, GLint location, GLint* params);
+typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBPOINTERVPROC) (GLuint index, GLenum pname, GLvoid** pointer);
+typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBFVPROC) (GLuint index, GLenum pname, GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBIVPROC) (GLuint index, GLenum pname, GLint* params);
+typedef GLboolean (GLAPIENTRY * PFNGLISFRAMEBUFFERPROC) (GLuint framebuffer);
+typedef GLboolean (GLAPIENTRY * PFNGLISPROGRAMPROC) (GLuint program);
+typedef GLboolean (GLAPIENTRY * PFNGLISRENDERBUFFERPROC) (GLuint renderbuffer);
+typedef GLboolean (GLAPIENTRY * PFNGLISSHADERPROC) (GLuint shader);
+typedef void (GLAPIENTRY * PFNGLLINKPROGRAMPROC) (GLuint program);
+typedef void (GLAPIENTRY * PFNGLRELEASESHADERCOMPILERPROC) (void);
+typedef void (GLAPIENTRY * PFNGLRENDERBUFFERSTORAGEPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
+typedef void (GLAPIENTRY * PFNGLSHADERBINARYPROC) (GLsizei n, const GLuint* shaders, GLenum binaryformat, const GLvoid* binary, GLsizei length);
+typedef void (GLAPIENTRY * PFNGLSHADERSOURCEPROC) (GLuint shader, GLsizei count, const GLchar** string, const GLint* length);
+typedef void (GLAPIENTRY * PFNGLSTENCILFUNCSEPARATEPROC) (GLenum face, GLenum func, GLint ref, GLuint mask);
+typedef void (GLAPIENTRY * PFNGLSTENCILMASKSEPARATEPROC) (GLenum face, GLuint mask);
+typedef void (GLAPIENTRY * PFNGLSTENCILOPSEPARATEPROC) (GLenum face, GLenum fail, GLenum zfail, GLenum zpass);
+typedef void (GLAPIENTRY * PFNGLUNIFORM1FPROC) (GLint location, GLfloat x);
+typedef void (GLAPIENTRY * PFNGLUNIFORM1FVPROC) (GLint location, GLsizei count, const GLfloat* v);
+typedef void (GLAPIENTRY * PFNGLUNIFORM1IPROC) (GLint location, GLint x);
+typedef void (GLAPIENTRY * PFNGLUNIFORM1IVPROC) (GLint location, GLsizei count, const GLint* v);
+typedef void (GLAPIENTRY * PFNGLUNIFORM2FPROC) (GLint location, GLfloat x, GLfloat y);
+typedef void (GLAPIENTRY * PFNGLUNIFORM2FVPROC) (GLint location, GLsizei count, const GLfloat* v);
+typedef void (GLAPIENTRY * PFNGLUNIFORM2IPROC) (GLint location, GLint x, GLint y);
+typedef void (GLAPIENTRY * PFNGLUNIFORM2IVPROC) (GLint location, GLsizei count, const GLint* v);
+typedef void (GLAPIENTRY * PFNGLUNIFORM3FPROC) (GLint location, GLfloat x, GLfloat y, GLfloat z);
+typedef void (GLAPIENTRY * PFNGLUNIFORM3FVPROC) (GLint location, GLsizei count, const GLfloat* v);
+typedef void (GLAPIENTRY * PFNGLUNIFORM3IPROC) (GLint location, GLint x, GLint y, GLint z);
+typedef void (GLAPIENTRY * PFNGLUNIFORM3IVPROC) (GLint location, GLsizei count, const GLint* v);
+typedef void (GLAPIENTRY * PFNGLUNIFORM4FPROC) (GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+typedef void (GLAPIENTRY * PFNGLUNIFORM4FVPROC) (GLint location, GLsizei count, const GLfloat* v);
+typedef void (GLAPIENTRY * PFNGLUNIFORM4IPROC) (GLint location, GLint x, GLint y, GLint z, GLint w);
+typedef void (GLAPIENTRY * PFNGLUNIFORM4IVPROC) (GLint location, GLsizei count, const GLint* v);
+typedef void (GLAPIENTRY * PFNGLUNIFORMMATRIX2FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
+typedef void (GLAPIENTRY * PFNGLUNIFORMMATRIX3FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
+typedef void (GLAPIENTRY * PFNGLUNIFORMMATRIX4FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
+typedef void (GLAPIENTRY * PFNGLUSEPROGRAMPROC) (GLuint program);
+typedef void (GLAPIENTRY * PFNGLVALIDATEPROGRAMPROC) (GLuint program);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB1FPROC) (GLuint indx, GLfloat x);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB1FVPROC) (GLuint indx, const GLfloat* values);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB2FPROC) (GLuint indx, GLfloat x, GLfloat y);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB2FVPROC) (GLuint indx, const GLfloat* values);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB3FPROC) (GLuint indx, GLfloat x, GLfloat y, GLfloat z);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB3FVPROC) (GLuint indx, const GLfloat* values);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4FPROC) (GLuint indx, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4FVPROC) (GLuint indx, const GLfloat* values);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBPOINTERPROC) (GLuint indx, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid* ptr);
+
+typedef void (GLAPIENTRY * PFNGLBINDBUFFERPROC) (GLenum , GLuint ); // NOTE jwilkins: missing function
+typedef void (GLAPIENTRY * PFNGLBUFFERDATAPROC) (GLenum , GLsizeiptr, const GLvoid *, GLenum ); // NOTE jwilkins: missing function
+typedef void (GLAPIENTRY * PFNGLBUFFERSUBDATAPROC) (GLenum, GLintptr, GLsizeiptr, const GLvoid *); // NOTE jwilkins: missing function
+typedef void (GLAPIENTRY * PFNGLDELETEBUFFERSPROC) (GLsizei , const GLuint *); // NOTE jwilkins: missing function
+typedef void (GLAPIENTRY * PFNGLGENBUFFERSPROC) (GLsizei, GLuint *); // NOTE jwilkins: missing function
+typedef void (GLAPIENTRY * PFNGLTEXPARAMETERIPROC) (GLenum, GLenum, GLint); // NOTE jwilkins: missing function
+typedef GLboolean (GLAPIENTRY * PFNGLISENABLEDPROC) (GLenum); // NOTE jwilkins: missing function
+typedef void (GLAPIENTRY * PFNGLGETFLOATVPROC) (GLenum , GLfloat *); // NOTE jwilkins: missing function
+typedef void (GLAPIENTRY * PFNGLDEPTHRANGEFPROC) (GLclampf zNear, GLclampf zFar); // NOTE jwilkins: missing function
+typedef void (GLAPIENTRY * PFNGLACTIVETEXTUREPROC) (GLenum texture); // NOTE jwilkins: missing function
+typedef void (GLAPIENTRY * PFNGLGETBOOLEANVPROC) (GLenum, GLboolean *); // NOTE jwilkins: missing function
+
+#define glAttachShader GLEW_GET_FUN(__glewAttachShader)
+#define glBindAttribLocation GLEW_GET_FUN(__glewBindAttribLocation)
+#define glBindFramebuffer GLEW_GET_FUN(__glewBindFramebuffer)
+#define glBindRenderbuffer GLEW_GET_FUN(__glewBindRenderbuffer)
+#define glBlendColor GLEW_GET_FUN(__glewBlendColor)
+#define glBlendEquation GLEW_GET_FUN(__glewBlendEquation)
+#define glBlendEquationSeparate GLEW_GET_FUN(__glewBlendEquationSeparate)
+#define glBlendFuncSeparate GLEW_GET_FUN(__glewBlendFuncSeparate)
+#define glCheckFramebufferStatus GLEW_GET_FUN(__glewCheckFramebufferStatus)
+#define glCompileShader GLEW_GET_FUN(__glewCompileShader)
+#define glCreateProgram GLEW_GET_FUN(__glewCreateProgram)
+#define glCreateShader GLEW_GET_FUN(__glewCreateShader)
+#define glDeleteFramebuffers GLEW_GET_FUN(__glewDeleteFramebuffers)
+#define glDeleteProgram GLEW_GET_FUN(__glewDeleteProgram)
+#define glDeleteRenderbuffers GLEW_GET_FUN(__glewDeleteRenderbuffers)
+#define glDeleteShader GLEW_GET_FUN(__glewDeleteShader)
+#define glDetachShader GLEW_GET_FUN(__glewDetachShader)
+#define glDisableVertexAttribArray GLEW_GET_FUN(__glewDisableVertexAttribArray)
+#define glEnableVertexAttribArray GLEW_GET_FUN(__glewEnableVertexAttribArray)
+#define glFramebufferRenderbuffer GLEW_GET_FUN(__glewFramebufferRenderbuffer)
+#define glFramebufferTexture2D GLEW_GET_FUN(__glewFramebufferTexture2D)
+#define glGenFramebuffers GLEW_GET_FUN(__glewGenFramebuffers)
+#define glGenRenderbuffers GLEW_GET_FUN(__glewGenRenderbuffers)
+#define glGenerateMipmap GLEW_GET_FUN(__glewGenerateMipmap)
+#define glGetActiveAttrib GLEW_GET_FUN(__glewGetActiveAttrib)
+#define glGetActiveUniform GLEW_GET_FUN(__glewGetActiveUniform)
+#define glGetAttachedShaders GLEW_GET_FUN(__glewGetAttachedShaders)
+#define glGetAttribLocation GLEW_GET_FUN(__glewGetAttribLocation)
+#define glGetFramebufferAttachmentParameteriv GLEW_GET_FUN(__glewGetFramebufferAttachmentParameteriv)
+#define glGetProgramInfoLog GLEW_GET_FUN(__glewGetProgramInfoLog)
+#define glGetProgramiv GLEW_GET_FUN(__glewGetProgramiv)
+#define glGetRenderbufferParameteriv GLEW_GET_FUN(__glewGetRenderbufferParameteriv)
+#define glGetShaderInfoLog GLEW_GET_FUN(__glewGetShaderInfoLog)
+#define glGetShaderPrecisionFormat GLEW_GET_FUN(__glewGetShaderPrecisionFormat)
+#define glGetShaderSource GLEW_GET_FUN(__glewGetShaderSource)
+#define glGetShaderiv GLEW_GET_FUN(__glewGetShaderiv)
+#define glGetUniformLocation GLEW_GET_FUN(__glewGetUniformLocation)
+#define glGetUniformfv GLEW_GET_FUN(__glewGetUniformfv)
+#define glGetUniformiv GLEW_GET_FUN(__glewGetUniformiv)
+#define glGetVertexAttribPointerv GLEW_GET_FUN(__glewGetVertexAttribPointerv)
+#define glGetVertexAttribfv GLEW_GET_FUN(__glewGetVertexAttribfv)
+#define glGetVertexAttribiv GLEW_GET_FUN(__glewGetVertexAttribiv)
+#define glIsFramebuffer GLEW_GET_FUN(__glewIsFramebuffer)
+#define glIsProgram GLEW_GET_FUN(__glewIsProgram)
+#define glIsRenderbuffer GLEW_GET_FUN(__glewIsRenderbuffer)
+#define glIsShader GLEW_GET_FUN(__glewIsShader)
+#define glLinkProgram GLEW_GET_FUN(__glewLinkProgram)
+#define glReleaseShaderCompiler GLEW_GET_FUN(__glewReleaseShaderCompiler)
+#define glRenderbufferStorage GLEW_GET_FUN(__glewRenderbufferStorage)
+#define glShaderBinary GLEW_GET_FUN(__glewShaderBinary)
+#define glShaderSource GLEW_GET_FUN(__glewShaderSource)
+#define glStencilFuncSeparate GLEW_GET_FUN(__glewStencilFuncSeparate)
+#define glStencilMaskSeparate GLEW_GET_FUN(__glewStencilMaskSeparate)
+#define glStencilOpSeparate GLEW_GET_FUN(__glewStencilOpSeparate)
+#define glUniform1f GLEW_GET_FUN(__glewUniform1f)
+#define glUniform1fv GLEW_GET_FUN(__glewUniform1fv)
+#define glUniform1i GLEW_GET_FUN(__glewUniform1i)
+#define glUniform1iv GLEW_GET_FUN(__glewUniform1iv)
+#define glUniform2f GLEW_GET_FUN(__glewUniform2f)
+#define glUniform2fv GLEW_GET_FUN(__glewUniform2fv)
+#define glUniform2i GLEW_GET_FUN(__glewUniform2i)
+#define glUniform2iv GLEW_GET_FUN(__glewUniform2iv)
+#define glUniform3f GLEW_GET_FUN(__glewUniform3f)
+#define glUniform3fv GLEW_GET_FUN(__glewUniform3fv)
+#define glUniform3i GLEW_GET_FUN(__glewUniform3i)
+#define glUniform3iv GLEW_GET_FUN(__glewUniform3iv)
+#define glUniform4f GLEW_GET_FUN(__glewUniform4f)
+#define glUniform4fv GLEW_GET_FUN(__glewUniform4fv)
+#define glUniform4i GLEW_GET_FUN(__glewUniform4i)
+#define glUniform4iv GLEW_GET_FUN(__glewUniform4iv)
+#define glUniformMatrix2fv GLEW_GET_FUN(__glewUniformMatrix2fv)
+#define glUniformMatrix3fv GLEW_GET_FUN(__glewUniformMatrix3fv)
+#define glUniformMatrix4fv GLEW_GET_FUN(__glewUniformMatrix4fv)
+#define glUseProgram GLEW_GET_FUN(__glewUseProgram)
+#define glValidateProgram GLEW_GET_FUN(__glewValidateProgram)
+#define glVertexAttrib1f GLEW_GET_FUN(__glewVertexAttrib1f)
+#define glVertexAttrib1fv GLEW_GET_FUN(__glewVertexAttrib1fv)
+#define glVertexAttrib2f GLEW_GET_FUN(__glewVertexAttrib2f)
+#define glVertexAttrib2fv GLEW_GET_FUN(__glewVertexAttrib2fv)
+#define glVertexAttrib3f GLEW_GET_FUN(__glewVertexAttrib3f)
+#define glVertexAttrib3fv GLEW_GET_FUN(__glewVertexAttrib3fv)
+#define glVertexAttrib4f GLEW_GET_FUN(__glewVertexAttrib4f)
+#define glVertexAttrib4fv GLEW_GET_FUN(__glewVertexAttrib4fv)
+#define glVertexAttribPointer GLEW_GET_FUN(__glewVertexAttribPointer)
+
+#define glBindBuffer GLEW_GET_FUN(__glewBindBuffer) // NOTE jwilkins: missing function
+#define glBufferData GLEW_GET_FUN(__glewBufferData) // NOTE jwilkins: missing function
+#define glBufferSubData GLEW_GET_FUN(__glewBufferSubData) // NOTE jwilkins: missing function
+#define glDeleteBuffers GLEW_GET_FUN(__glewDeleteBuffers) // NOTE jwilkins: missing function
+#define glGenBuffers GLEW_GET_FUN(__glewGenBuffers) // NOTE jwilkins: missing function
+#define glTexParameteri GLEW_GET_FUN(__glewTexParameteri) // NOTE jwilkins: missing function
+#define glIsEnabled GLEW_GET_FUN(__glewIsEnabled) // NOTE jwilkins: missing function
+#define glGetFloatv GLEW_GET_FUN(__glewGetFloatv) // NOTE jwilkins: missing function
+#define glDepthRangef GLEW_GET_FUN(__glewDepthRangef) // NOTE jwilkins: missing function
+#define glActiveTexture GLEW_GET_FUN(__glewActiveTexture) // NOTE jwilkins: missing function
+#define glGetBooleanv GLEW_GET_FUN(__glewGetBooleanv) // NOTE jwilkins: missing function
+
+#define GLEW_ES_VERSION_2_0 GLEW_GET_VAR(__GLEW_ES_VERSION_2_0)
+
+#endif /* !GL_ES_VERSION_2_0 */
+
+/* --------------------- GL_AMD_compressed_3DC_texture --------------------- */
+
+#if !defined(GL_AMD_compressed_3DC_texture)
+#define GL_AMD_compressed_3DC_texture 1
+
+#define GL_3DC_X_AMD 0x87F9
+#define GL_3DC_XY_AMD 0x87FA
+
+#define GLEW_AMD_compressed_3DC_texture GLEW_GET_VAR(__GLEW_AMD_compressed_3DC_texture)
+
+#endif /* !GL_AMD_compressed_3DC_texture */
+
+/* --------------------- GL_AMD_compressed_ATC_texture --------------------- */
+
+#if !defined(GL_AMD_compressed_ATC_texture)
+#define GL_AMD_compressed_ATC_texture 1
+
+#define GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD 0x87EE
+#define GL_ATC_RGB_AMD 0x8C92
+#define GL_ATC_RGBA_EXPLICIT_ALPHA_AMD 0x8C93
+
+#define GLEW_AMD_compressed_ATC_texture GLEW_GET_VAR(__GLEW_AMD_compressed_ATC_texture)
+
+#endif /* !GL_AMD_compressed_ATC_texture */
+
+/* ----------------------- GL_AMD_performance_monitor ---------------------- */
+
+#if !defined(GL_AMD_performance_monitor)
+#define GL_AMD_performance_monitor 1
+
+#define GL_UNSIGNED_INT 0x1405
+#define GL_FLOAT 0x1406
+#define GL_COUNTER_TYPE_AMD 0x8BC0
+#define GL_COUNTER_RANGE_AMD 0x8BC1
+#define GL_UNSIGNED_INT64_AMD 0x8BC2
+#define GL_PERCENTAGE_AMD 0x8BC3
+#define GL_PERFMON_RESULT_AVAILABLE_AMD 0x8BC4
+#define GL_PERFMON_RESULT_SIZE_AMD 0x8BC5
+#define GL_PERFMON_RESULT_AMD 0x8BC6
+
+typedef void (GLAPIENTRY * PFNGLBEGINPERFMONITORAMDPROC) (GLuint monitor);
+typedef void (GLAPIENTRY * PFNGLDELETEPERFMONITORSAMDPROC) (GLsizei n, GLuint* monitors);
+typedef void (GLAPIENTRY * PFNGLENDPERFMONITORAMDPROC) (GLuint monitor);
+typedef void (GLAPIENTRY * PFNGLGENPERFMONITORSAMDPROC) (GLsizei n, GLuint* monitors);
+typedef void (GLAPIENTRY * PFNGLGETPERFMONITORCOUNTERDATAAMDPROC) (GLuint monitor, GLenum pname, GLsizei dataSize, GLuint* data, GLint *bytesWritten);
+typedef void (GLAPIENTRY * PFNGLGETPERFMONITORCOUNTERINFOAMDPROC) (GLuint group, GLuint counter, GLenum pname, void* data);
+typedef void (GLAPIENTRY * PFNGLGETPERFMONITORCOUNTERSTRINGAMDPROC) (GLuint group, GLuint counter, GLsizei bufSize, GLsizei* length, char *counterString);
+typedef void (GLAPIENTRY * PFNGLGETPERFMONITORCOUNTERSAMDPROC) (GLuint group, GLint* numCounters, GLint *maxActiveCounters, GLsizei countersSize, GLuint *counters);
+typedef void (GLAPIENTRY * PFNGLGETPERFMONITORGROUPSTRINGAMDPROC) (GLuint group, GLsizei bufSize, GLsizei* length, char *groupString);
+typedef void (GLAPIENTRY * PFNGLGETPERFMONITORGROUPSAMDPROC) (GLint* numGroups, GLsizei groupsSize, GLuint *groups);
+typedef void (GLAPIENTRY * PFNGLSELECTPERFMONITORCOUNTERSAMDPROC) (GLuint monitor, GLboolean enable, GLuint group, GLint numCounters, GLuint* counterList);
+
+#define glBeginPerfMonitorAMD GLEW_GET_FUN(__glewBeginPerfMonitorAMD)
+#define glDeletePerfMonitorsAMD GLEW_GET_FUN(__glewDeletePerfMonitorsAMD)
+#define glEndPerfMonitorAMD GLEW_GET_FUN(__glewEndPerfMonitorAMD)
+#define glGenPerfMonitorsAMD GLEW_GET_FUN(__glewGenPerfMonitorsAMD)
+#define glGetPerfMonitorCounterDataAMD GLEW_GET_FUN(__glewGetPerfMonitorCounterDataAMD)
+#define glGetPerfMonitorCounterInfoAMD GLEW_GET_FUN(__glewGetPerfMonitorCounterInfoAMD)
+#define glGetPerfMonitorCounterStringAMD GLEW_GET_FUN(__glewGetPerfMonitorCounterStringAMD)
+#define glGetPerfMonitorCountersAMD GLEW_GET_FUN(__glewGetPerfMonitorCountersAMD)
+#define glGetPerfMonitorGroupStringAMD GLEW_GET_FUN(__glewGetPerfMonitorGroupStringAMD)
+#define glGetPerfMonitorGroupsAMD GLEW_GET_FUN(__glewGetPerfMonitorGroupsAMD)
+#define glSelectPerfMonitorCountersAMD GLEW_GET_FUN(__glewSelectPerfMonitorCountersAMD)
+
+#define GLEW_AMD_performance_monitor GLEW_GET_VAR(__GLEW_AMD_performance_monitor)
+
+#endif /* !GL_AMD_performance_monitor */
+
+/* ----------------------- GL_AMD_program_binary_Z400 ---------------------- */
+
+#if !defined(GL_AMD_program_binary_Z400)
+#define GL_AMD_program_binary_Z400 1
+
+#define GL_Z400_BINARY_AMD 0x8740
+
+#define GLEW_AMD_program_binary_Z400 GLEW_GET_VAR(__GLEW_AMD_program_binary_Z400)
+
+#endif /* !GL_AMD_program_binary_Z400 */
+
+/* ----------------------- GL_ANGLE_framebuffer_blit ----------------------- */
+
+#if !defined(GL_ANGLE_framebuffer_blit)
+#define GL_ANGLE_framebuffer_blit 1
+
+#define GL_DRAW_FRAMEBUFFER_BINDING_ANGLE 0x8CA6
+#define GL_READ_FRAMEBUFFER_ANGLE 0x8CA8
+#define GL_DRAW_FRAMEBUFFER_ANGLE 0x8CA9
+#define GL_READ_FRAMEBUFFER_BINDING_ANGLE 0x8CAA
+
+typedef void (GLAPIENTRY * PFNGLBLITFRAMEBUFFERANGLEPROC) (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter);
+
+#define glBlitFramebufferANGLE GLEW_GET_FUN(__glewBlitFramebufferANGLE)
+
+#define GLEW_ANGLE_framebuffer_blit GLEW_GET_VAR(__GLEW_ANGLE_framebuffer_blit)
+
+#endif /* !GL_ANGLE_framebuffer_blit */
+
+/* -------------------- GL_ANGLE_framebuffer_multisample ------------------- */
+
+#if !defined(GL_ANGLE_framebuffer_multisample)
+#define GL_ANGLE_framebuffer_multisample 1
+
+#define GL_RENDERBUFFER_SAMPLES_ANGLE 0x8CAB
+#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE 0x8D56
+#define GL_MAX_SAMPLES_ANGLE 0x8D57
+
+typedef void (GLAPIENTRY * PFNGLRENDERBUFFERSTORAGEMULTISAMPLEANGLEPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
+
+#define glRenderbufferStorageMultisampleANGLE GLEW_GET_FUN(__glewRenderbufferStorageMultisampleANGLE)
+
+#define GLEW_ANGLE_framebuffer_multisample GLEW_GET_VAR(__GLEW_ANGLE_framebuffer_multisample)
+
+#endif /* !GL_ANGLE_framebuffer_multisample */
+
+/* ----------------------- GL_ANGLE_instanced_arrays ----------------------- */
+
+#if !defined(GL_ANGLE_instanced_arrays)
+#define GL_ANGLE_instanced_arrays 1
+
+#define GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE 0x88FE
+
+typedef void (GLAPIENTRY * PFNGLDRAWARRAYSINSTANCEDANGLEPROC) (GLenum mode, GLint first, GLsizei count, GLsizei primcount);
+typedef void (GLAPIENTRY * PFNGLDRAWELEMENTSINSTANCEDANGLEPROC) (GLenum mode, GLsizei count, GLenum type, const void* indices, GLsizei primcount);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBDIVISORANGLEPROC) (GLuint index, GLuint divisor);
+
+#define glDrawArraysInstancedANGLE GLEW_GET_FUN(__glewDrawArraysInstancedANGLE)
+#define glDrawElementsInstancedANGLE GLEW_GET_FUN(__glewDrawElementsInstancedANGLE)
+#define glVertexAttribDivisorANGLE GLEW_GET_FUN(__glewVertexAttribDivisorANGLE)
+
+#define GLEW_ANGLE_instanced_arrays GLEW_GET_VAR(__GLEW_ANGLE_instanced_arrays)
+
+#endif /* !GL_ANGLE_instanced_arrays */
+
+/* -------------------- GL_ANGLE_pack_reverse_row_order -------------------- */
+
+#if !defined(GL_ANGLE_pack_reverse_row_order)
+#define GL_ANGLE_pack_reverse_row_order 1
+
+#define GL_PACK_REVERSE_ROW_ORDER_ANGLE 0x93A4
+
+#define GLEW_ANGLE_pack_reverse_row_order GLEW_GET_VAR(__GLEW_ANGLE_pack_reverse_row_order)
+
+#endif /* !GL_ANGLE_pack_reverse_row_order */
+
+/* ------------------- GL_ANGLE_texture_compression_dxt3 ------------------- */
+
+#if !defined(GL_ANGLE_texture_compression_dxt3)
+#define GL_ANGLE_texture_compression_dxt3 1
+
+#define GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE 0x83F2
+#define GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE 0x83F3
+
+#define GLEW_ANGLE_texture_compression_dxt3 GLEW_GET_VAR(__GLEW_ANGLE_texture_compression_dxt3)
+
+#endif /* !GL_ANGLE_texture_compression_dxt3 */
+
+/* ------------------- GL_ANGLE_texture_compression_dxt5 ------------------- */
+
+#if !defined(GL_ANGLE_texture_compression_dxt5)
+#define GL_ANGLE_texture_compression_dxt5 1
+
+#define GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE 0x83F2
+#define GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE 0x83F3
+
+#define GLEW_ANGLE_texture_compression_dxt5 GLEW_GET_VAR(__GLEW_ANGLE_texture_compression_dxt5)
+
+#endif /* !GL_ANGLE_texture_compression_dxt5 */
+
+/* ------------------------- GL_ANGLE_texture_usage ------------------------ */
+
+#if !defined(GL_ANGLE_texture_usage)
+#define GL_ANGLE_texture_usage 1
+
+#define GL_NONE 0 // NOTE jwilkins: had to change this from 0x0000 so it would match other definition of GL_NONE
+#define GL_TEXTURE_USAGE_ANGLE 0x93A2
+#define GL_FRAMEBUFFER_ATTACHMENT_ANGLE 0x93A3
+
+#define GLEW_ANGLE_texture_usage GLEW_GET_VAR(__GLEW_ANGLE_texture_usage)
+
+#endif /* !GL_ANGLE_texture_usage */
+
+/* ------------------- GL_ANGLE_translated_shader_source ------------------- */
+
+#if !defined(GL_ANGLE_translated_shader_source)
+#define GL_ANGLE_translated_shader_source 1
+
+#define GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE 0x93A0
+
+typedef void (GLAPIENTRY * PFNGLGETTRANSLATEDSHADERSOURCEANGLEPROC) (GLuint shader, GLsizei bufsize, GLsizei* length, char* source);
+
+#define glGetTranslatedShaderSourceANGLE GLEW_GET_FUN(__glewGetTranslatedShaderSourceANGLE)
+
+#define GLEW_ANGLE_translated_shader_source GLEW_GET_VAR(__GLEW_ANGLE_translated_shader_source)
+
+#endif /* !GL_ANGLE_translated_shader_source */
+
+/* ---------------------- GL_APPLE_copy_texture_levels --------------------- */
+
+#if !defined(GL_APPLE_copy_texture_levels)
+#define GL_APPLE_copy_texture_levels 1
+
+typedef void (GLAPIENTRY * PFNGLCOPYTEXTURELEVELSAPPLEPROC) (GLuint destinationTexture, GLuint sourceTexture, GLint sourceBaseLevel, GLsizei sourceLevelCount);
+
+#define glCopyTextureLevelsAPPLE GLEW_GET_FUN(__glewCopyTextureLevelsAPPLE)
+
+#define GLEW_APPLE_copy_texture_levels GLEW_GET_VAR(__GLEW_APPLE_copy_texture_levels)
+
+#endif /* !GL_APPLE_copy_texture_levels */
+
+/* -------------------- GL_APPLE_framebuffer_multisample ------------------- */
+
+#if !defined(GL_APPLE_framebuffer_multisample)
+#define GL_APPLE_framebuffer_multisample 1
+
+#define GL_DRAW_FRAMEBUFFER_BINDING_APPLE 0x8CA6
+#define GL_READ_FRAMEBUFFER_APPLE 0x8CA8
+#define GL_DRAW_FRAMEBUFFER_APPLE 0x8CA9
+#define GL_READ_FRAMEBUFFER_BINDING_APPLE 0x8CAA
+#define GL_RENDERBUFFER_SAMPLES_APPLE 0x8CAB
+#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_APPLE 0x8D56
+#define GL_MAX_SAMPLES_APPLE 0x8D57
+
+typedef void (GLAPIENTRY * PFNGLRENDERBUFFERSTORAGEMULTISAMPLEAPPLEPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
+typedef void (GLAPIENTRY * PFNGLRESOLVEMULTISAMPLEFRAMEBUFFERAPPLEPROC) (void);
+
+#define glRenderbufferStorageMultisampleAPPLE GLEW_GET_FUN(__glewRenderbufferStorageMultisampleAPPLE)
+#define glResolveMultisampleFramebufferAPPLE GLEW_GET_FUN(__glewResolveMultisampleFramebufferAPPLE)
+
+#define GLEW_APPLE_framebuffer_multisample GLEW_GET_VAR(__GLEW_APPLE_framebuffer_multisample)
+
+#endif /* !GL_APPLE_framebuffer_multisample */
+
+/* ---------------------------- GL_APPLE_rgb_422 --------------------------- */
+
+#if !defined(GL_APPLE_rgb_422)
+#define GL_APPLE_rgb_422 1
+
+#define GL_UNSIGNED_SHORT_8_8_APPLE 0x85BA
+#define GL_UNSIGNED_SHORT_8_8_REV_APPLE 0x85BB
+#define GL_RGB_422_APPLE 0x8A1F
+
+#define GLEW_APPLE_rgb_422 GLEW_GET_VAR(__GLEW_APPLE_rgb_422)
+
+#endif /* !GL_APPLE_rgb_422 */
+
+/* ----------------------------- GL_APPLE_sync ----------------------------- */
+
+#if !defined(GL_APPLE_sync)
+#define GL_APPLE_sync 1
+
+#define GL_SYNC_FLUSH_COMMANDS_BIT_APPLE 0x00000001
+#define GL_SYNC_OBJECT_APPLE 0x8A53
+#define GL_MAX_SERVER_WAIT_TIMEOUT_APPLE 0x9111
+#define GL_OBJECT_TYPE_APPLE 0x9112
+#define GL_SYNC_CONDITION_APPLE 0x9113
+#define GL_SYNC_STATUS_APPLE 0x9114
+#define GL_SYNC_FLAGS_APPLE 0x9115
+#define GL_SYNC_FENCE_APPLE 0x9116
+#define GL_SYNC_GPU_COMMANDS_COMPLETE_APPLE 0x9117
+#define GL_UNSIGNALED_APPLE 0x9118
+#define GL_SIGNALED_APPLE 0x9119
+#define GL_ALREADY_SIGNALED_APPLE 0x911A
+#define GL_TIMEOUT_EXPIRED_APPLE 0x911B
+#define GL_CONDITION_SATISFIED_APPLE 0x911C
+#define GL_WAIT_FAILED_APPLE 0x911D
+#define GL_TIMEOUT_IGNORED_APPLE 0xFFFFFFFFFFFFFFFF
+
+typedef GLenum (GLAPIENTRY * PFNGLCLIENTWAITSYNCAPPLEPROC) (GLsync GLsync, GLbitfield flags, GLuint64 timeout);
+typedef void (GLAPIENTRY * PFNGLDELETESYNCAPPLEPROC) (GLsync GLsync);
+typedef GLsync (GLAPIENTRY * PFNGLFENCESYNCAPPLEPROC) (GLenum condition, GLbitfield flags);
+typedef void (GLAPIENTRY * PFNGLGETINTEGER64VAPPLEPROC) (GLenum pname, GLint64* params);
+typedef void (GLAPIENTRY * PFNGLGETSYNCIVAPPLEPROC) (GLsync GLsync, GLenum pname, GLsizei bufSize, GLsizei* length, GLint *values);
+typedef GLboolean (GLAPIENTRY * PFNGLISSYNCAPPLEPROC) (GLsync GLsync);
+typedef void (GLAPIENTRY * PFNGLWAITSYNCAPPLEPROC) (GLsync GLsync, GLbitfield flags, GLuint64 timeout);
+
+#define glClientWaitSyncAPPLE GLEW_GET_FUN(__glewClientWaitSyncAPPLE)
+#define glDeleteSyncAPPLE GLEW_GET_FUN(__glewDeleteSyncAPPLE)
+#define glFenceSyncAPPLE GLEW_GET_FUN(__glewFenceSyncAPPLE)
+#define glGetInteger64vAPPLE GLEW_GET_FUN(__glewGetInteger64vAPPLE)
+#define glGetSyncivAPPLE GLEW_GET_FUN(__glewGetSyncivAPPLE)
+#define glIsSyncAPPLE GLEW_GET_FUN(__glewIsSyncAPPLE)
+#define glWaitSyncAPPLE GLEW_GET_FUN(__glewWaitSyncAPPLE)
+
+#define GLEW_APPLE_sync GLEW_GET_VAR(__GLEW_APPLE_sync)
+
+#endif /* !GL_APPLE_sync */
+
+/* -------------------- GL_APPLE_texture_2D_limited_npot ------------------- */
+
+#if !defined(GL_APPLE_texture_2D_limited_npot)
+#define GL_APPLE_texture_2D_limited_npot 1
+
+#define GLEW_APPLE_texture_2D_limited_npot GLEW_GET_VAR(__GLEW_APPLE_texture_2D_limited_npot)
+
+#endif /* !GL_APPLE_texture_2D_limited_npot */
+
+/* -------------------- GL_APPLE_texture_format_BGRA8888 ------------------- */
+
+#if !defined(GL_APPLE_texture_format_BGRA8888)
+#define GL_APPLE_texture_format_BGRA8888 1
+
+#define GL_BGRA_EXT 0x80E1
+
+#define GLEW_APPLE_texture_format_BGRA8888 GLEW_GET_VAR(__GLEW_APPLE_texture_format_BGRA8888)
+
+#endif /* !GL_APPLE_texture_format_BGRA8888 */
+
+/* ----------------------- GL_APPLE_texture_max_level ---------------------- */
+
+#if !defined(GL_APPLE_texture_max_level)
+#define GL_APPLE_texture_max_level 1
+
+#define GL_TEXTURE_MAX_LEVEL_APPLE 0x813D
+
+#define GLEW_APPLE_texture_max_level GLEW_GET_VAR(__GLEW_APPLE_texture_max_level)
+
+#endif /* !GL_APPLE_texture_max_level */
+
+/* ----------------------- GL_ARM_mali_program_binary ---------------------- */
+
+#if !defined(GL_ARM_mali_program_binary)
+#define GL_ARM_mali_program_binary 1
+
+#define GL_MALI_PROGRAM_BINARY_ARM 0x8F61
+
+#define GLEW_ARM_mali_program_binary GLEW_GET_VAR(__GLEW_ARM_mali_program_binary)
+
+#endif /* !GL_ARM_mali_program_binary */
+
+/* ----------------------- GL_ARM_mali_shader_binary ----------------------- */
+
+#if !defined(GL_ARM_mali_shader_binary)
+#define GL_ARM_mali_shader_binary 1
+
+#define GL_MALI_SHADER_BINARY_ARM 0x8F60
+
+#define GLEW_ARM_mali_shader_binary GLEW_GET_VAR(__GLEW_ARM_mali_shader_binary)
+
+#endif /* !GL_ARM_mali_shader_binary */
+
+/* ------------------------------ GL_ARM_rgba8 ----------------------------- */
+
+#if !defined(GL_ARM_rgba8)
+#define GL_ARM_rgba8 1
+
+#define GL_RGBA8_OES 0x8058
+
+#define GLEW_ARM_rgba8 GLEW_GET_VAR(__GLEW_ARM_rgba8)
+
+#endif /* !GL_ARM_rgba8 */
+
+/* -------------------------- GL_DMP_shader_binary ------------------------- */
+
+#if !defined(GL_DMP_shader_binary)
+#define GL_DMP_shader_binary 1
+
+#define GL_SHADER_BINARY_DMP 0x9250
+
+#define GLEW_DMP_shader_binary GLEW_GET_VAR(__GLEW_DMP_shader_binary)
+
+#endif /* !GL_DMP_shader_binary */
+
+/* -------------------------- GL_EXT_blend_minmax -------------------------- */
+
+#if !defined(GL_EXT_blend_minmax)
+#define GL_EXT_blend_minmax 1
+
+#define GL_FUNC_ADD_EXT 0x8006
+#define GL_MIN_EXT 0x8007
+#define GL_MAX_EXT 0x8008
+#define GL_BLEND_EQUATION_EXT 0x8009
+
+typedef void (GLAPIENTRY * PFNGLBLENDEQUATIONEXTPROC) (GLenum mode);
+
+#define glBlendEquationEXT GLEW_GET_FUN(__glewBlendEquationEXT)
+
+#define GLEW_EXT_blend_minmax GLEW_GET_VAR(__GLEW_EXT_blend_minmax)
+
+#endif /* !GL_EXT_blend_minmax */
+
+/* --------------------- GL_EXT_color_buffer_half_float -------------------- */
+
+#if !defined(GL_EXT_color_buffer_half_float)
+#define GL_EXT_color_buffer_half_float 1
+
+#define GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE_EXT 0x8211
+#define GL_R16F_EXT 0x822D
+#define GL_RG16F_EXT 0x822F
+#define GL_RGBA16F_EXT 0x881A
+#define GL_RGB16F_EXT 0x881B
+#define GL_UNSIGNED_NORMALIZED_EXT 0x8C17
+
+#define GLEW_EXT_color_buffer_half_float GLEW_GET_VAR(__GLEW_EXT_color_buffer_half_float)
+
+#endif /* !GL_EXT_color_buffer_half_float */
+
+/* --------------------------- GL_EXT_debug_label -------------------------- */
+
+#if !defined(GL_EXT_debug_label)
+#define GL_EXT_debug_label 1
+
+#define GL_PROGRAM_PIPELINE_OBJECT_EXT 0x8A4F
+#define GL_PROGRAM_OBJECT_EXT 0x8B40
+#define GL_SHADER_OBJECT_EXT 0x8B48
+#define GL_BUFFER_OBJECT_EXT 0x9151
+#define GL_QUERY_OBJECT_EXT 0x9153
+#define GL_VERTEX_ARRAY_OBJECT_EXT 0x9154
+
+typedef void (GLAPIENTRY * PFNGLGETOBJECTLABELEXTPROC) (GLenum type, GLuint object, GLsizei bufSize, GLsizei* length, char *label);
+typedef void (GLAPIENTRY * PFNGLLABELOBJECTEXTPROC) (GLenum type, GLuint object, GLsizei length, const char* label);
+
+#define glGetObjectLabelEXT GLEW_GET_FUN(__glewGetObjectLabelEXT)
+#define glLabelObjectEXT GLEW_GET_FUN(__glewLabelObjectEXT)
+
+#define GLEW_EXT_debug_label GLEW_GET_VAR(__GLEW_EXT_debug_label)
+
+#endif /* !GL_EXT_debug_label */
+
+/* -------------------------- GL_EXT_debug_marker -------------------------- */
+
+#if !defined(GL_EXT_debug_marker)
+#define GL_EXT_debug_marker 1
+
+typedef void (GLAPIENTRY * PFNGLINSERTEVENTMARKEREXTPROC) (GLsizei length, const char* marker);
+typedef void (GLAPIENTRY * PFNGLPUSHGROUPMARKEREXTPROC) (GLsizei length, const char* marker);
+
+#define glInsertEventMarkerEXT GLEW_GET_FUN(__glewInsertEventMarkerEXT)
+#define glPushGroupMarkerEXT GLEW_GET_FUN(__glewPushGroupMarkerEXT)
+
+#define GLEW_EXT_debug_marker GLEW_GET_VAR(__GLEW_EXT_debug_marker)
+
+#endif /* !GL_EXT_debug_marker */
+
+/* ----------------------- GL_EXT_discard_framebuffer ---------------------- */
+
+#if !defined(GL_EXT_discard_framebuffer)
+#define GL_EXT_discard_framebuffer 1
+
+#define GL_COLOR_EXT 0x1800
+#define GL_DEPTH_EXT 0x1801
+#define GL_STENCIL_EXT 0x1802
+
+typedef void (GLAPIENTRY * PFNGLDISCARDFRAMEBUFFEREXTPROC) (GLenum target, GLsizei numAttachments, const GLenum* attachments);
+
+#define glDiscardFramebufferEXT GLEW_GET_FUN(__glewDiscardFramebufferEXT)
+
+#define GLEW_EXT_discard_framebuffer GLEW_GET_VAR(__GLEW_EXT_discard_framebuffer)
+
+#endif /* !GL_EXT_discard_framebuffer */
+
+/* --------------------------- GL_EXT_frag_depth --------------------------- */
+
+#if !defined(GL_EXT_frag_depth)
+#define GL_EXT_frag_depth 1
+
+#define GLEW_EXT_frag_depth GLEW_GET_VAR(__GLEW_EXT_frag_depth)
+
+#endif /* !GL_EXT_frag_depth */
+
+/* ------------------------ GL_EXT_map_buffer_range ------------------------ */
+
+#if !defined(GL_EXT_map_buffer_range)
+#define GL_EXT_map_buffer_range 1
+
+#define GL_MAP_READ_BIT_EXT 0x0001
+#define GL_MAP_WRITE_BIT_EXT 0x0002
+#define GL_MAP_INVALIDATE_RANGE_BIT_EXT 0x0004
+#define GL_MAP_INVALIDATE_BUFFER_BIT_EXT 0x0008
+#define GL_MAP_FLUSH_EXPLICIT_BIT_EXT 0x0010
+#define GL_MAP_UNSYNCHRONIZED_BIT_EXT 0x0020
+
+typedef void (GLAPIENTRY * PFNGLFLUSHMAPPEDBUFFERRANGEEXTPROC) (GLenum target, GLintptr offset, GLsizeiptr length);
+typedef GLvoid * (GLAPIENTRY * PFNGLMAPBUFFERRANGEEXTPROC) (GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access);
+
+#define glFlushMappedBufferRangeEXT GLEW_GET_FUN(__glewFlushMappedBufferRangeEXT)
+#define glMapBufferRangeEXT GLEW_GET_FUN(__glewMapBufferRangeEXT)
+
+#define GLEW_EXT_map_buffer_range GLEW_GET_VAR(__GLEW_EXT_map_buffer_range)
+
+#endif /* !GL_EXT_map_buffer_range */
+
+/* ------------------------ GL_EXT_multi_draw_arrays ----------------------- */
+
+#if !defined(GL_EXT_multi_draw_arrays)
+#define GL_EXT_multi_draw_arrays 1
+
+typedef void (GLAPIENTRY * PFNGLMULTIDRAWARRAYSEXTPROC) (GLenum mode, const GLint* first, const GLsizei *count, GLsizei primcount);
+typedef void (GLAPIENTRY * PFNGLMULTIDRAWELEMENTSEXTPROC) (GLenum mode, GLsizei* count, GLenum type, const GLvoid **indices, GLsizei primcount);
+
+#define glMultiDrawArraysEXT GLEW_GET_FUN(__glewMultiDrawArraysEXT)
+#define glMultiDrawElementsEXT GLEW_GET_FUN(__glewMultiDrawElementsEXT)
+
+#define GLEW_EXT_multi_draw_arrays GLEW_GET_VAR(__GLEW_EXT_multi_draw_arrays)
+
+#endif /* !GL_EXT_multi_draw_arrays */
+
+/* ----------------- GL_EXT_multisampled_render_to_texture ----------------- */
+
+#if !defined(GL_EXT_multisampled_render_to_texture)
+#define GL_EXT_multisampled_render_to_texture 1
+
+#define GL_RENDERBUFFER_SAMPLES_EXT 0x8CAB
+#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT 0x8D56
+#define GL_MAX_SAMPLES_EXT 0x8D57
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_SAMPLES_EXT 0x8D6C
+
+typedef void (GLAPIENTRY * PFNGLFRAMEBUFFERTEXTURE2DMULTISAMPLEEXTPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLsizei samples);
+typedef void (GLAPIENTRY * PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
+
+#define glFramebufferTexture2DMultisampleEXT GLEW_GET_FUN(__glewFramebufferTexture2DMultisampleEXT)
+#define glRenderbufferStorageMultisampleEXT GLEW_GET_FUN(__glewRenderbufferStorageMultisampleEXT)
+
+#define GLEW_EXT_multisampled_render_to_texture GLEW_GET_VAR(__GLEW_EXT_multisampled_render_to_texture)
+
+#endif /* !GL_EXT_multisampled_render_to_texture */
+
+/* --------------------- GL_EXT_multiview_draw_buffers --------------------- */
+
+#if !defined(GL_EXT_multiview_draw_buffers)
+#define GL_EXT_multiview_draw_buffers 1
+
+#define GL_DRAW_BUFFER_EXT 0x0C01
+#define GL_READ_BUFFER_EXT 0x0C02
+#define GL_COLOR_ATTACHMENT_EXT 0x90F0
+#define GL_MULTIVIEW_EXT 0x90F1
+#define GL_MAX_MULTIVIEW_BUFFERS_EXT 0x90F2
+
+typedef void (GLAPIENTRY * PFNGLDRAWBUFFERSINDEXEDEXTPROC) (GLint n, const GLenum* location, const GLint *indices);
+typedef void (GLAPIENTRY * PFNGLGETINTEGERI_VEXTPROC) (GLenum target, GLuint index, GLint* data);
+typedef void (GLAPIENTRY * PFNGLREADBUFFERINDEXEDEXTPROC) (GLenum src, GLint index);
+
+#define glDrawBuffersIndexedEXT GLEW_GET_FUN(__glewDrawBuffersIndexedEXT)
+#define glGetIntegeri_vEXT GLEW_GET_FUN(__glewGetIntegeri_vEXT)
+#define glReadBufferIndexedEXT GLEW_GET_FUN(__glewReadBufferIndexedEXT)
+
+#define GLEW_EXT_multiview_draw_buffers GLEW_GET_VAR(__GLEW_EXT_multiview_draw_buffers)
+
+#endif /* !GL_EXT_multiview_draw_buffers */
+
+/* --------------------- GL_EXT_occlusion_query_boolean -------------------- */
+
+#if !defined(GL_EXT_occlusion_query_boolean)
+#define GL_EXT_occlusion_query_boolean 1
+
+#define GL_CURRENT_QUERY_EXT 0x8865
+#define GL_QUERY_RESULT_EXT 0x8866
+#define GL_QUERY_RESULT_AVAILABLE_EXT 0x8867
+#define GL_ANY_SAMPLES_PASSED_EXT 0x8C2F
+#define GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT 0x8D6A
+
+typedef void (GLAPIENTRY * PFNGLBEGINQUERYEXTPROC) (GLenum target, GLuint id);
+typedef void (GLAPIENTRY * PFNGLDELETEQUERIESEXTPROC) (GLsizei n, const GLuint* ids);
+typedef void (GLAPIENTRY * PFNGLENDQUERYEXTPROC) (GLenum target);
+typedef void (GLAPIENTRY * PFNGLGENQUERIESEXTPROC) (GLsizei n, GLuint* ids);
+typedef void (GLAPIENTRY * PFNGLGETQUERYOBJECTUIVEXTPROC) (GLuint id, GLenum pname, GLuint* params);
+typedef void (GLAPIENTRY * PFNGLGETQUERYIVEXTPROC) (GLenum target, GLenum pname, GLint* params);
+typedef GLboolean (GLAPIENTRY * PFNGLISQUERYEXTPROC) (GLuint id);
+
+#define glBeginQueryEXT GLEW_GET_FUN(__glewBeginQueryEXT)
+#define glDeleteQueriesEXT GLEW_GET_FUN(__glewDeleteQueriesEXT)
+#define glEndQueryEXT GLEW_GET_FUN(__glewEndQueryEXT)
+#define glGenQueriesEXT GLEW_GET_FUN(__glewGenQueriesEXT)
+#define glGetQueryObjectuivEXT GLEW_GET_FUN(__glewGetQueryObjectuivEXT)
+#define glGetQueryivEXT GLEW_GET_FUN(__glewGetQueryivEXT)
+#define glIsQueryEXT GLEW_GET_FUN(__glewIsQueryEXT)
+
+#define GLEW_EXT_occlusion_query_boolean GLEW_GET_VAR(__GLEW_EXT_occlusion_query_boolean)
+
+#endif /* !GL_EXT_occlusion_query_boolean */
+
+/* ------------------------ GL_EXT_read_format_bgra ------------------------ */
+
+#if !defined(GL_EXT_read_format_bgra)
+#define GL_EXT_read_format_bgra 1
+
+#define GL_BGRA_EXT 0x80E1
+#define GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT 0x8365
+#define GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT 0x8366
+
+#define GLEW_EXT_read_format_bgra GLEW_GET_VAR(__GLEW_EXT_read_format_bgra)
+
+#endif /* !GL_EXT_read_format_bgra */
+
+/* --------------------------- GL_EXT_robustness --------------------------- */
+
+#if !defined(GL_EXT_robustness)
+#define GL_EXT_robustness 1
+
+#define GL_NO_ERROR 0 // NOTE jwilkins: had to change this from 0x0000 so it would math other definition
+#define GL_LOSE_CONTEXT_ON_RESET_EXT 0x8252
+#define GL_GUILTY_CONTEXT_RESET_EXT 0x8253
+#define GL_INNOCENT_CONTEXT_RESET_EXT 0x8254
+#define GL_UNKNOWN_CONTEXT_RESET_EXT 0x8255
+#define GL_RESET_NOTIFICATION_STRATEGY_EXT 0x8256
+#define GL_NO_RESET_NOTIFICATION_EXT 0x8261
+#define GL_CONTEXT_ROBUST_ACCESS_EXT 0x90F3
+
+typedef void (GLAPIENTRY * PFNGLGETNUNIFORMFVEXTPROC) (GLuint program, GLint location, GLsizei bufSize, GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLGETNUNIFORMIVEXTPROC) (GLuint program, GLint location, GLsizei bufSize, GLint* params);
+typedef void (GLAPIENTRY * PFNGLREADNPIXELSEXTPROC) (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei bufSize, void* data);
+
+#define glGetnUniformfvEXT GLEW_GET_FUN(__glewGetnUniformfvEXT)
+#define glGetnUniformivEXT GLEW_GET_FUN(__glewGetnUniformivEXT)
+#define glReadnPixelsEXT GLEW_GET_FUN(__glewReadnPixelsEXT)
+
+#define GLEW_EXT_robustness GLEW_GET_VAR(__GLEW_EXT_robustness)
+
+#endif /* !GL_EXT_robustness */
+
+/* ------------------------------ GL_EXT_sRGB ------------------------------ */
+
+#if !defined(GL_EXT_sRGB)
+#define GL_EXT_sRGB 1
+
+#define GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING_EXT 0x8210
+#define GL_SRGB_EXT 0x8C40
+#define GL_SRGB_ALPHA_EXT 0x8C42
+#define GL_SRGB8_ALPHA8_EXT 0x8C43
+
+#define GLEW_EXT_sRGB GLEW_GET_VAR(__GLEW_EXT_sRGB)
+
+#endif /* !GL_EXT_sRGB */
+
+#if 0 // NOTE jwilkins: there is an inconsistency between the ES and Non-ES versions of this extension??
+/* --------------------- GL_EXT_separate_shader_objects -------------------- */
+
+#if !defined(GL_EXT_separate_shader_objects)
+#define GL_EXT_separate_shader_objects 1
+
+#define GL_VERTEX_SHADER_BIT_EXT 0x00000001
+#define GL_FRAGMENT_SHADER_BIT_EXT 0x00000002
+#define GL_PROGRAM_SEPARABLE_EXT 0x8258
+#define GL_ACTIVE_PROGRAM_EXT 0x8259
+#define GL_PROGRAM_PIPELINE_BINDING_EXT 0x825A
+#define GL_ALL_SHADER_BITS_EXT 0xFFFFFFFF
+
+typedef void (GLAPIENTRY * PFNGLACTIVESHADERPROGRAMEXTPROC) (GLuint pipeline, GLuint program);
+typedef void (GLAPIENTRY * PFNGLBINDPROGRAMPIPELINEEXTPROC) (GLuint pipeline);
+typedef GLuint (GLAPIENTRY * PFNGLCREATESHADERPROGRAMVEXTPROC) (GLenum type, GLsizei count, const char ** strings);
+typedef void (GLAPIENTRY * PFNGLDELETEPROGRAMPIPELINESEXTPROC) (GLsizei n, const GLuint* pipelines);
+typedef void (GLAPIENTRY * PFNGLGENPROGRAMPIPELINESEXTPROC) (GLsizei n, GLuint* pipelines);
+typedef void (GLAPIENTRY * PFNGLGETPROGRAMPIPELINEINFOLOGEXTPROC) (GLuint pipeline, GLsizei bufSize, GLsizei* length, char *infoLog);
+typedef void (GLAPIENTRY * PFNGLGETPROGRAMPIPELINEIVEXTPROC) (GLuint pipeline, GLenum pname, GLint* params);
+typedef GLboolean (GLAPIENTRY * PFNGLISPROGRAMPIPELINEEXTPROC) (GLuint pipeline);
+typedef void (GLAPIENTRY * PFNGLPROGRAMPARAMETERIEXTPROC) (GLuint program, GLenum pname, GLint value);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM1FEXTPROC) (GLuint program, GLint location, GLfloat x);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM1FVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLfloat* value);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM1IEXTPROC) (GLuint program, GLint location, GLint x);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM1IVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLint* value);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM2FEXTPROC) (GLuint program, GLint location, GLfloat x, GLfloat y);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM2FVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLfloat* value);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM2IEXTPROC) (GLuint program, GLint location, GLint x, GLint y);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM2IVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLint* value);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM3FEXTPROC) (GLuint program, GLint location, GLfloat x, GLfloat y, GLfloat z);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM3FVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLfloat* value);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM3IEXTPROC) (GLuint program, GLint location, GLint x, GLint y, GLint z);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM3IVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLint* value);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM4FEXTPROC) (GLuint program, GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM4FVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLfloat* value);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM4IEXTPROC) (GLuint program, GLint location, GLint x, GLint y, GLint z, GLint w);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM4IVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLint* value);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX2FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX3FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX4FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
+typedef void (GLAPIENTRY * PFNGLUSEPROGRAMSTAGESEXTPROC) (GLuint pipeline, GLbitfield stages, GLuint program);
+typedef void (GLAPIENTRY * PFNGLVALIDATEPROGRAMPIPELINEEXTPROC) (GLuint pipeline);
+
+#define glActiveShaderProgramEXT GLEW_GET_FUN(__glewActiveShaderProgramEXT)
+#define glBindProgramPipelineEXT GLEW_GET_FUN(__glewBindProgramPipelineEXT)
+#define glCreateShaderProgramvEXT GLEW_GET_FUN(__glewCreateShaderProgramvEXT)
+#define glDeleteProgramPipelinesEXT GLEW_GET_FUN(__glewDeleteProgramPipelinesEXT)
+#define glGenProgramPipelinesEXT GLEW_GET_FUN(__glewGenProgramPipelinesEXT)
+#define glGetProgramPipelineInfoLogEXT GLEW_GET_FUN(__glewGetProgramPipelineInfoLogEXT)
+#define glGetProgramPipelineivEXT GLEW_GET_FUN(__glewGetProgramPipelineivEXT)
+#define glIsProgramPipelineEXT GLEW_GET_FUN(__glewIsProgramPipelineEXT)
+#define glProgramParameteriEXT GLEW_GET_FUN(__glewProgramParameteriEXT)
+#define glProgramUniform1fEXT GLEW_GET_FUN(__glewProgramUniform1fEXT)
+#define glProgramUniform1fvEXT GLEW_GET_FUN(__glewProgramUniform1fvEXT)
+#define glProgramUniform1iEXT GLEW_GET_FUN(__glewProgramUniform1iEXT)
+#define glProgramUniform1ivEXT GLEW_GET_FUN(__glewProgramUniform1ivEXT)
+#define glProgramUniform2fEXT GLEW_GET_FUN(__glewProgramUniform2fEXT)
+#define glProgramUniform2fvEXT GLEW_GET_FUN(__glewProgramUniform2fvEXT)
+#define glProgramUniform2iEXT GLEW_GET_FUN(__glewProgramUniform2iEXT)
+#define glProgramUniform2ivEXT GLEW_GET_FUN(__glewProgramUniform2ivEXT)
+#define glProgramUniform3fEXT GLEW_GET_FUN(__glewProgramUniform3fEXT)
+#define glProgramUniform3fvEXT GLEW_GET_FUN(__glewProgramUniform3fvEXT)
+#define glProgramUniform3iEXT GLEW_GET_FUN(__glewProgramUniform3iEXT)
+#define glProgramUniform3ivEXT GLEW_GET_FUN(__glewProgramUniform3ivEXT)
+#define glProgramUniform4fEXT GLEW_GET_FUN(__glewProgramUniform4fEXT)
+#define glProgramUniform4fvEXT GLEW_GET_FUN(__glewProgramUniform4fvEXT)
+#define glProgramUniform4iEXT GLEW_GET_FUN(__glewProgramUniform4iEXT)
+#define glProgramUniform4ivEXT GLEW_GET_FUN(__glewProgramUniform4ivEXT)
+#define glProgramUniformMatrix2fvEXT GLEW_GET_FUN(__glewProgramUniformMatrix2fvEXT)
+#define glProgramUniformMatrix3fvEXT GLEW_GET_FUN(__glewProgramUniformMatrix3fvEXT)
+#define glProgramUniformMatrix4fvEXT GLEW_GET_FUN(__glewProgramUniformMatrix4fvEXT)
+#define glUseProgramStagesEXT GLEW_GET_FUN(__glewUseProgramStagesEXT)
+#define glValidateProgramPipelineEXT GLEW_GET_FUN(__glewValidateProgramPipelineEXT)
+
+#define GLEW_EXT_separate_shader_objects GLEW_GET_VAR(__GLEW_EXT_separate_shader_objects)
+
+#endif /* !GL_EXT_separate_shader_objects */
+#endif // XXX
+
+/* -------------------- GL_EXT_shader_framebuffer_fetch -------------------- */
+
+#if !defined(GL_EXT_shader_framebuffer_fetch)
+#define GL_EXT_shader_framebuffer_fetch 1
+
+#define GL_FRAGMENT_SHADER_DISCARDS_SAMPLES_EXT 0x8A52
+
+#define GLEW_EXT_shader_framebuffer_fetch GLEW_GET_VAR(__GLEW_EXT_shader_framebuffer_fetch)
+
+#endif /* !GL_EXT_shader_framebuffer_fetch */
+
+/* ----------------------- GL_EXT_shader_texture_lod ----------------------- */
+
+#if !defined(GL_EXT_shader_texture_lod)
+#define GL_EXT_shader_texture_lod 1
+
+#define GLEW_EXT_shader_texture_lod GLEW_GET_VAR(__GLEW_EXT_shader_texture_lod)
+
+#endif /* !GL_EXT_shader_texture_lod */
+
+/* ------------------------- GL_EXT_shadow_samplers ------------------------ */
+
+#if !defined(GL_EXT_shadow_samplers)
+#define GL_EXT_shadow_samplers 1
+
+#define GL_TEXTURE_COMPARE_MODE_EXT 0x884C
+#define GL_TEXTURE_COMPARE_FUNC_EXT 0x884D
+#define GL_COMPARE_REF_TO_TEXTURE_EXT 0x884E
+#define GL_SAMPLER_2D_SHADOW_EXT 0x8B62
+
+#define GLEW_EXT_shadow_samplers GLEW_GET_VAR(__GLEW_EXT_shadow_samplers)
+
+#endif /* !GL_EXT_shadow_samplers */
+
+/* -------------------- GL_EXT_texture_compression_dxt1 -------------------- */
+
+#if !defined(GL_EXT_texture_compression_dxt1)
+#define GL_EXT_texture_compression_dxt1 1
+
+#define GL_COMPRESSED_RGB_S3TC_DXT1_EXT 0x83F0
+#define GL_COMPRESSED_RGBA_S3TC_DXT1_EXT 0x83F1
+
+#define GLEW_EXT_texture_compression_dxt1 GLEW_GET_VAR(__GLEW_EXT_texture_compression_dxt1)
+
+#endif /* !GL_EXT_texture_compression_dxt1 */
+
+/* ------------------- GL_EXT_texture_filter_anisotropic ------------------- */
+
+#if !defined(GL_EXT_texture_filter_anisotropic)
+#define GL_EXT_texture_filter_anisotropic 1
+
+#define GL_TEXTURE_MAX_ANISOTROPY_EXT 0x84FE
+#define GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT 0x84FF
+
+#define GLEW_EXT_texture_filter_anisotropic GLEW_GET_VAR(__GLEW_EXT_texture_filter_anisotropic)
+
+#endif /* !GL_EXT_texture_filter_anisotropic */
+
+/* --------------------- GL_EXT_texture_format_BGRA8888 -------------------- */
+
+#if !defined(GL_EXT_texture_format_BGRA8888)
+#define GL_EXT_texture_format_BGRA8888 1
+
+#define GL_BGRA_EXT 0x80E1
+
+#define GLEW_EXT_texture_format_BGRA8888 GLEW_GET_VAR(__GLEW_EXT_texture_format_BGRA8888)
+
+#endif /* !GL_EXT_texture_format_BGRA8888 */
+
+/* ------------------------ GL_EXT_texture_lod_bias ------------------------ */
+
+#if !defined(GL_EXT_texture_lod_bias)
+#define GL_EXT_texture_lod_bias 1
+
+#define GL_MAX_TEXTURE_LOD_BIAS_EXT 0x84FD
+#define GL_TEXTURE_FILTER_CONTROL_EXT 0x8500
+#define GL_TEXTURE_LOD_BIAS_EXT 0x8501
+
+#define GLEW_EXT_texture_lod_bias GLEW_GET_VAR(__GLEW_EXT_texture_lod_bias)
+
+#endif /* !GL_EXT_texture_lod_bias */
+
+/* --------------------------- GL_EXT_texture_rg --------------------------- */
+
+#if !defined(GL_EXT_texture_rg)
+#define GL_EXT_texture_rg 1
+
+#define GL_RED_EXT 0x1903
+#define GL_RG_EXT 0x8227
+#define GL_R8_EXT 0x8229
+#define GL_RG8_EXT 0x822B
+
+#define GLEW_EXT_texture_rg GLEW_GET_VAR(__GLEW_EXT_texture_rg)
+
+#endif /* !GL_EXT_texture_rg */
+
+/* ------------------------- GL_EXT_texture_storage ------------------------ */
+
+#if !defined(GL_EXT_texture_storage)
+#define GL_EXT_texture_storage 1
+
+#define GL_ALPHA8_EXT 0x803C
+#define GL_LUMINANCE8_EXT 0x8040
+#define GL_LUMINANCE8_ALPHA8_EXT 0x8045
+#define GL_RGB10_EXT 0x8052
+#define GL_RGB10_A2_EXT 0x8059
+#define GL_R8_EXT 0x8229
+#define GL_RG8_EXT 0x822B
+#define GL_R16F_EXT 0x822D
+#define GL_R32F_EXT 0x822E
+#define GL_RG16F_EXT 0x822F
+#define GL_RG32F_EXT 0x8230
+#define GL_RGBA32F_EXT 0x8814
+#define GL_RGB32F_EXT 0x8815
+#define GL_ALPHA32F_EXT 0x8816
+#define GL_LUMINANCE32F_EXT 0x8818
+#define GL_LUMINANCE_ALPHA32F_EXT 0x8819
+#define GL_RGBA16F_EXT 0x881A
+#define GL_RGB16F_EXT 0x881B
+#define GL_ALPHA16F_EXT 0x881C
+#define GL_LUMINANCE16F_EXT 0x881E
+#define GL_LUMINANCE_ALPHA16F_EXT 0x881F
+#define GL_RGB_422_APPLE 0x8A1F
+#define GL_TEXTURE_IMMUTABLE_FORMAT_EXT 0x912F
+#define GL_BGRA8_EXT 0x93A1
+
+typedef void (GLAPIENTRY * PFNGLTEXSTORAGE1DEXTPROC) (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width);
+typedef void (GLAPIENTRY * PFNGLTEXSTORAGE2DEXTPROC) (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height);
+typedef void (GLAPIENTRY * PFNGLTEXSTORAGE3DEXTPROC) (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth);
+typedef void (GLAPIENTRY * PFNGLTEXTURESTORAGE1DEXTPROC) (GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width);
+typedef void (GLAPIENTRY * PFNGLTEXTURESTORAGE2DEXTPROC) (GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height);
+typedef void (GLAPIENTRY * PFNGLTEXTURESTORAGE3DEXTPROC) (GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth);
+
+#define glTexStorage1DEXT GLEW_GET_FUN(__glewTexStorage1DEXT)
+#define glTexStorage2DEXT GLEW_GET_FUN(__glewTexStorage2DEXT)
+#define glTexStorage3DEXT GLEW_GET_FUN(__glewTexStorage3DEXT)
+#define glTextureStorage1DEXT GLEW_GET_FUN(__glewTextureStorage1DEXT)
+#define glTextureStorage2DEXT GLEW_GET_FUN(__glewTextureStorage2DEXT)
+#define glTextureStorage3DEXT GLEW_GET_FUN(__glewTextureStorage3DEXT)
+
+#define GLEW_EXT_texture_storage GLEW_GET_VAR(__GLEW_EXT_texture_storage)
+
+#endif /* !GL_EXT_texture_storage */
+
+/* ------------------- GL_EXT_texture_type_2_10_10_10_REV ------------------ */
+
+#if !defined(GL_EXT_texture_type_2_10_10_10_REV)
+#define GL_EXT_texture_type_2_10_10_10_REV 1
+
+#define GL_UNSIGNED_INT_2_10_10_10_REV_EXT 0x8368
+
+#define GLEW_EXT_texture_type_2_10_10_10_REV GLEW_GET_VAR(__GLEW_EXT_texture_type_2_10_10_10_REV)
+
+#endif /* !GL_EXT_texture_type_2_10_10_10_REV */
+
+/* ------------------------- GL_EXT_unpack_subimage ------------------------ */
+
+#if !defined(GL_EXT_unpack_subimage)
+#define GL_EXT_unpack_subimage 1
+
+#define GL_UNPACK_ROW_LENGTH 0x0CF2
+#define GL_UNPACK_SKIP_ROWS 0x0CF3
+#define GL_UNPACK_SKIP_PIXELS 0x0CF4
+
+#define GLEW_EXT_unpack_subimage GLEW_GET_VAR(__GLEW_EXT_unpack_subimage)
+
+#endif /* !GL_EXT_unpack_subimage */
+
+/* ----------------------- GL_FJ_shader_binary_GCCSO ----------------------- */
+
+#if !defined(GL_FJ_shader_binary_GCCSO)
+#define GL_FJ_shader_binary_GCCSO 1
+
+#define GL_GCCSO_SHADER_BINARY_FJ 0x9260
+
+#define GLEW_FJ_shader_binary_GCCSO GLEW_GET_VAR(__GLEW_FJ_shader_binary_GCCSO)
+
+#endif /* !GL_FJ_shader_binary_GCCSO */
+
+/* ----------------- GL_IMG_multisampled_render_to_texture ----------------- */
+
+#if !defined(GL_IMG_multisampled_render_to_texture)
+#define GL_IMG_multisampled_render_to_texture 1
+
+#define GL_RENDERBUFFER_SAMPLES_IMG 0x9133
+#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_IMG 0x9134
+#define GL_MAX_SAMPLES_IMG 0x9135
+#define GL_TEXTURE_SAMPLES_IMG 0x9136
+
+typedef void (GLAPIENTRY * PFNGLFRAMEBUFFERTEXTURE2DMULTISAMPLEIMGPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLsizei samples);
+typedef void (GLAPIENTRY * PFNGLRENDERBUFFERSTORAGEMULTISAMPLEIMGPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
+
+#define glFramebufferTexture2DMultisampleIMG GLEW_GET_FUN(__glewFramebufferTexture2DMultisampleIMG)
+#define glRenderbufferStorageMultisampleIMG GLEW_GET_FUN(__glewRenderbufferStorageMultisampleIMG)
+
+#define GLEW_IMG_multisampled_render_to_texture GLEW_GET_VAR(__GLEW_IMG_multisampled_render_to_texture)
+
+#endif /* !GL_IMG_multisampled_render_to_texture */
+
+/* ------------------------- GL_IMG_program_binary ------------------------- */
+
+#if !defined(GL_IMG_program_binary)
+#define GL_IMG_program_binary 1
+
+#define GL_SGX_PROGRAM_BINARY_IMG 0x9130
+
+#define GLEW_IMG_program_binary GLEW_GET_VAR(__GLEW_IMG_program_binary)
+
+#endif /* !GL_IMG_program_binary */
+
+/* --------------------------- GL_IMG_read_format -------------------------- */
+
+#if !defined(GL_IMG_read_format)
+#define GL_IMG_read_format 1
+
+#define GL_BGRA_IMG 0x80E1
+#define GL_UNSIGNED_SHORT_4_4_4_4_REV_IMG 0x8365
+
+#define GLEW_IMG_read_format GLEW_GET_VAR(__GLEW_IMG_read_format)
+
+#endif /* !GL_IMG_read_format */
+
+/* -------------------------- GL_IMG_shader_binary ------------------------- */
+
+#if !defined(GL_IMG_shader_binary)
+#define GL_IMG_shader_binary 1
+
+#define GL_SGX_BINARY_IMG 0x8C0A
+
+#define GLEW_IMG_shader_binary GLEW_GET_VAR(__GLEW_IMG_shader_binary)
+
+#endif /* !GL_IMG_shader_binary */
+
+/* -------------------- GL_IMG_texture_compression_pvrtc ------------------- */
+
+#if !defined(GL_IMG_texture_compression_pvrtc)
+#define GL_IMG_texture_compression_pvrtc 1
+
+#define GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG 0x8C00
+#define GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG 0x8C01
+#define GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG 0x8C02
+#define GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG 0x8C03
+
+#define GLEW_IMG_texture_compression_pvrtc GLEW_GET_VAR(__GLEW_IMG_texture_compression_pvrtc)
+
+#endif /* !GL_IMG_texture_compression_pvrtc */
+
+/* --------------- GL_IMG_texture_env_enhanced_fixed_function -------------- */
+
+#if !defined(GL_IMG_texture_env_enhanced_fixed_function)
+#define GL_IMG_texture_env_enhanced_fixed_function 1
+
+#define GL_DOT3_RGBA_IMG 0x86AF
+#define GL_MODULATE_COLOR_IMG 0x8C04
+#define GL_RECIP_ADD_SIGNED_ALPHA_IMG 0x8C05
+#define GL_TEXTURE_ALPHA_MODULATE_IMG 0x8C06
+#define GL_FACTOR_ALPHA_MODULATE_IMG 0x8C07
+#define GL_FRAGMENT_ALPHA_MODULATE_IMG 0x8C08
+#define GL_ADD_BLEND_IMG 0x8C09
+
+#define GLEW_IMG_texture_env_enhanced_fixed_function GLEW_GET_VAR(__GLEW_IMG_texture_env_enhanced_fixed_function)
+
+#endif /* !GL_IMG_texture_env_enhanced_fixed_function */
+
+/* ------------------------- GL_IMG_user_clip_plane ------------------------ */
+
+#if !defined(GL_IMG_user_clip_plane)
+#define GL_IMG_user_clip_plane 1
+
+#define GL_MAX_CLIP_PLANES_IMG 0x0D32
+#define GL_CLIP_PLANE0_IMG 0x3000
+#define GL_CLIP_PLANE1_IMG 0x3001
+#define GL_CLIP_PLANE2_IMG 0x3002
+#define GL_CLIP_PLANE3_IMG 0x3003
+#define GL_CLIP_PLANE4_IMG 0x3004
+#define GL_CLIP_PLANE5_IMG 0x3005
+
+typedef void (GLAPIENTRY * PFNGLCLIPPLANEFIMGPROC) (GLenum p, GLfloat eqn[4]);
+
+#define glClipPlanefIMG GLEW_GET_FUN(__glewClipPlanefIMG)
+
+#define GLEW_IMG_user_clip_plane GLEW_GET_VAR(__GLEW_IMG_user_clip_plane)
+
+#endif /* !GL_IMG_user_clip_plane */
+
+/* ------------------------------ GL_KHR_debug ----------------------------- */
+
+#if !defined(GL_KHR_debug)
+#define GL_KHR_debug 1
+
+#define GL_CONTEXT_FLAG_DEBUG_BIT 0x00000002
+#define GL_STACK_OVERFLOW 0x0503
+#define GL_STACK_UNDERFLOW 0x0504
+#define GL_DEBUG_OUTPUT_SYNCHRONOUS 0x8242
+#define GL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH 0x8243
+#define GL_DEBUG_CALLBACK_FUNCTION 0x8244
+#define GL_DEBUG_CALLBACK_USER_PARAM 0x8245
+#define GL_DEBUG_SOURCE_API 0x8246
+#define GL_DEBUG_SOURCE_WINDOW_SYSTEM 0x8247
+#define GL_DEBUG_SOURCE_SHADER_COMPILER 0x8248
+#define GL_DEBUG_SOURCE_THIRD_PARTY 0x8249
+#define GL_DEBUG_SOURCE_APPLICATION 0x824A
+#define GL_DEBUG_SOURCE_OTHER 0x824B
+#define GL_DEBUG_TYPE_ERROR 0x824C
+#define GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR 0x824D
+#define GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR 0x824E
+#define GL_DEBUG_TYPE_PORTABILITY 0x824F
+#define GL_DEBUG_TYPE_PERFORMANCE 0x8250
+#define GL_DEBUG_TYPE_OTHER 0x8251
+#define GL_DEBUG_TYPE_MARKER 0x8268
+#define GL_DEBUG_TYPE_PUSH_GROUP 0x8269
+#define GL_DEBUG_TYPE_POP_GROUP 0x826A
+#define GL_DEBUG_SEVERITY_NOTIFICATION 0x826B
+#define GL_MAX_DEBUG_GROUP_STACK_DEPTH 0x826C
+#define GL_DEBUG_GROUP_STACK_DEPTH 0x826D
+#define GL_BUFFER 0x82E0
+#define GL_SHADER 0x82E1
+#define GL_PROGRAM 0x82E2
+#define GL_QUERY 0x82E3
+#define GL_PROGRAM_PIPELINE 0x82E4
+#define GL_SAMPLER 0x82E6
+#define GL_DISPLAY_LIST 0x82E7
+#define GL_MAX_LABEL_LENGTH 0x82E8
+#define GL_MAX_DEBUG_MESSAGE_LENGTH 0x9143
+#define GL_MAX_DEBUG_LOGGED_MESSAGES 0x9144
+#define GL_DEBUG_LOGGED_MESSAGES 0x9145
+#define GL_DEBUG_SEVERITY_HIGH 0x9146
+#define GL_DEBUG_SEVERITY_MEDIUM 0x9147
+#define GL_DEBUG_SEVERITY_LOW 0x9148
+#define GL_DEBUG_OUTPUT 0x92E0
+
+typedef void (APIENTRY *GLDEBUGPROC)(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar* message, GLvoid* userParam); // NOTE jwilkins: added this typedef
+
+typedef void (GLAPIENTRY * PFNGLDEBUGMESSAGECALLBACKPROC) (GLDEBUGPROC callback, void* userParam); // NOTE jwilkins: had to fix DEBUGPROC
+typedef void (GLAPIENTRY * PFNGLDEBUGMESSAGECONTROLPROC) (GLenum source, GLenum type, GLenum severity, GLsizei count, const GLuint* ids, GLboolean enabled);
+typedef void (GLAPIENTRY * PFNGLDEBUGMESSAGEINSERTPROC) (GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const char* buf);
+typedef GLuint (GLAPIENTRY * PFNGLGETDEBUGMESSAGELOGPROC) (GLuint count, GLsizei bufsize, GLenum* sources, GLenum* types, GLuint* ids, GLenum* severities, GLsizei* lengths, char* messageLog);
+typedef void (GLAPIENTRY * PFNGLGETOBJECTLABELPROC) (GLenum identifier, GLuint name, GLsizei bufSize, GLsizei* length, char *label);
+typedef void (GLAPIENTRY * PFNGLGETOBJECTPTRLABELPROC) (void* ptr, GLsizei bufSize, GLsizei* length, char *label);
+typedef void (GLAPIENTRY * PFNGLGETPOINTERVPROC) (GLenum pname, void** params);
+typedef void (GLAPIENTRY * PFNGLOBJECTLABELPROC) (GLenum identifier, GLuint name, GLsizei length, const char* label);
+typedef void (GLAPIENTRY * PFNGLOBJECTPTRLABELPROC) (void* ptr, GLsizei length, const char* label);
+typedef void (GLAPIENTRY * PFNGLPOPDEBUGGROUPPROC) (void);
+typedef void (GLAPIENTRY * PFNGLPUSHDEBUGGROUPPROC) (GLenum source, GLuint id, GLsizei length, const char * message);
+
+#define glDebugMessageCallback GLEW_GET_FUN(__glewDebugMessageCallback)
+#define glDebugMessageControl GLEW_GET_FUN(__glewDebugMessageControl)
+#define glDebugMessageInsert GLEW_GET_FUN(__glewDebugMessageInsert)
+#define glGetDebugMessageLog GLEW_GET_FUN(__glewGetDebugMessageLog)
+#define glGetObjectLabel GLEW_GET_FUN(__glewGetObjectLabel)
+#define glGetObjectPtrLabel GLEW_GET_FUN(__glewGetObjectPtrLabel)
+#define glGetPointerv GLEW_GET_FUN(__glewGetPointerv)
+#define glObjectLabel GLEW_GET_FUN(__glewObjectLabel)
+#define glObjectPtrLabel GLEW_GET_FUN(__glewObjectPtrLabel)
+#define glPopDebugGroup GLEW_GET_FUN(__glewPopDebugGroup)
+#define glPushDebugGroup GLEW_GET_FUN(__glewPushDebugGroup)
+
+#define GLEW_KHR_debug GLEW_GET_VAR(__GLEW_KHR_debug)
+
+#endif /* !GL_KHR_debug */
+
+/* ------------------ GL_KHR_texture_compression_astc_ldr ------------------ */
+
+#if !defined(GL_KHR_texture_compression_astc_ldr)
+#define GL_KHR_texture_compression_astc_ldr 1
+
+#define GL_COMPRESSED_RGBA_ASTC_4x4_KHR 0x93B0
+#define GL_COMPRESSED_RGBA_ASTC_5x4_KHR 0x93B1
+#define GL_COMPRESSED_RGBA_ASTC_5x5_KHR 0x93B2
+#define GL_COMPRESSED_RGBA_ASTC_6x5_KHR 0x93B3
+#define GL_COMPRESSED_RGBA_ASTC_6x6_KHR 0x93B4
+#define GL_COMPRESSED_RGBA_ASTC_8x5_KHR 0x93B5
+#define GL_COMPRESSED_RGBA_ASTC_8x6_KHR 0x93B6
+#define GL_COMPRESSED_RGBA_ASTC_8x8_KHR 0x93B7
+#define GL_COMPRESSED_RGBA_ASTC_10x5_KHR 0x93B8
+#define GL_COMPRESSED_RGBA_ASTC_10x6_KHR 0x93B9
+#define GL_COMPRESSED_RGBA_ASTC_10x8_KHR 0x93BA
+#define GL_COMPRESSED_RGBA_ASTC_10x10_KHR 0x93BB
+#define GL_COMPRESSED_RGBA_ASTC_12x10_KHR 0x93BC
+#define GL_COMPRESSED_RGBA_ASTC_12x12_KHR 0x93BD
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR 0x93D0
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR 0x93D1
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR 0x93D2
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR 0x93D3
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR 0x93D4
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR 0x93D5
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR 0x93D6
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR 0x93D7
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR 0x93D8
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR 0x93D9
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR 0x93DA
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR 0x93DB
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR 0x93DC
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR 0x93DD
+
+#define GLEW_KHR_texture_compression_astc_ldr GLEW_GET_VAR(__GLEW_KHR_texture_compression_astc_ldr)
+
+#endif /* !GL_KHR_texture_compression_astc_ldr */
+
+/* ------------------------ GL_NV_3dvision_settings ------------------------ */
+
+#if !defined(GL_NV_3dvision_settings)
+#define GL_NV_3dvision_settings 1
+
+#define GL_3DVISION_STEREO_NV 0x90F4
+#define GL_STEREO_SEPARATION_NV 0x90F5
+#define GL_STEREO_CONVERGENCE_NV 0x90F6
+#define GL_STEREO_CUTOFF_NV 0x90F7
+#define GL_STEREO_PROJECTION_NV 0x90F8
+#define GL_STEREO_PROJECTION_PERSPECTIVE_NV 0x90F9
+#define GL_STEREO_PROJECTION_ORTHO_NV 0x90FA
+
+typedef void (GLAPIENTRY * PFNGLSTEREOPARAMETERFNVPROC) (GLenum pname, GLfloat param);
+typedef void (GLAPIENTRY * PFNGLSTEREOPARAMETERINVPROC) (GLenum pname, GLint param);
+
+#define glStereoParameterfNV GLEW_GET_FUN(__glewStereoParameterfNV)
+#define glStereoParameteriNV GLEW_GET_FUN(__glewStereoParameteriNV)
+
+#define GLEW_NV_3dvision_settings GLEW_GET_VAR(__GLEW_NV_3dvision_settings)
+
+#endif /* !GL_NV_3dvision_settings */
+
+/* ------------------- GL_NV_EGL_stream_consumer_external ------------------ */
+
+#if !defined(GL_NV_EGL_stream_consumer_external)
+#define GL_NV_EGL_stream_consumer_external 1
+
+#define GL_TEXTURE_EXTERNAL_OES 0x8D65
+#define GL_SAMPLER_EXTERNAL_OES 0x8D66
+#define GL_TEXTURE_BINDING_EXTERNAL_OES 0x8D67
+#define GL_REQUIRED_TEXTURE_IMAGE_UNITS_OES 0x8D68
+
+#define GLEW_NV_EGL_stream_consumer_external GLEW_GET_VAR(__GLEW_NV_EGL_stream_consumer_external)
+
+#endif /* !GL_NV_EGL_stream_consumer_external */
+
+/* ------------------------------- GL_NV_bgr ------------------------------- */
+
+#if !defined(GL_NV_bgr)
+#define GL_NV_bgr 1
+
+#define GL_BGR_NV 0x80E0
+
+#define GLEW_NV_bgr GLEW_GET_VAR(__GLEW_NV_bgr)
+
+#endif /* !GL_NV_bgr */
+
+/* ------------------------- GL_NV_coverage_sample ------------------------- */
+
+#if !defined(GL_NV_coverage_sample)
+#define GL_NV_coverage_sample 1
+
+#define GL_COVERAGE_BUFFER_BIT_NV 0x8000
+#define GL_COVERAGE_COMPONENT_NV 0x8ED0
+#define GL_COVERAGE_COMPONENT4_NV 0x8ED1
+#define GL_COVERAGE_ATTACHMENT_NV 0x8ED2
+#define GL_COVERAGE_BUFFERS_NV 0x8ED3
+#define GL_COVERAGE_ALL_FRAGMENTS_NV 0x8ED5
+#define GL_COVERAGE_EDGE_FRAGMENTS_NV 0x8ED6
+#define GL_COVERAGE_AUTOMATIC_NV 0x8ED7
+
+typedef void (GLAPIENTRY * PFNGLCOVERAGEMASKNVPROC) (GLboolean mask);
+typedef void (GLAPIENTRY * PFNGLCOVERAGEOPERATIONNVPROC) (GLenum operation);
+
+#define glCoverageMaskNV GLEW_GET_FUN(__glewCoverageMaskNV)
+#define glCoverageOperationNV GLEW_GET_FUN(__glewCoverageOperationNV)
+
+#define GLEW_NV_coverage_sample GLEW_GET_VAR(__GLEW_NV_coverage_sample)
+
+#endif /* !GL_NV_coverage_sample */
+
+/* ------------------------- GL_NV_depth_nonlinear ------------------------- */
+
+#if !defined(GL_NV_depth_nonlinear)
+#define GL_NV_depth_nonlinear 1
+
+#define GL_DEPTH_COMPONENT16_NONLINEAR_NV 0x8E2C
+
+#define GLEW_NV_depth_nonlinear GLEW_GET_VAR(__GLEW_NV_depth_nonlinear)
+
+#endif /* !GL_NV_depth_nonlinear */
+
+/* --------------------------- GL_NV_draw_buffers -------------------------- */
+
+#if !defined(GL_NV_draw_buffers)
+#define GL_NV_draw_buffers 1
+
+#define GL_MAX_DRAW_BUFFERS_NV 0x8824
+#define GL_DRAW_BUFFER0_NV 0x8825
+#define GL_DRAW_BUFFER1_NV 0x8826
+#define GL_DRAW_BUFFER2_NV 0x8827
+#define GL_DRAW_BUFFER3_NV 0x8828
+#define GL_DRAW_BUFFER4_NV 0x8829
+#define GL_DRAW_BUFFER5_NV 0x882A
+#define GL_DRAW_BUFFER6_NV 0x882B
+#define GL_DRAW_BUFFER7_NV 0x882C
+#define GL_DRAW_BUFFER8_NV 0x882D
+#define GL_DRAW_BUFFER9_NV 0x882E
+#define GL_DRAW_BUFFER10_NV 0x882F
+#define GL_DRAW_BUFFER11_NV 0x8830
+#define GL_DRAW_BUFFER12_NV 0x8831
+#define GL_DRAW_BUFFER13_NV 0x8832
+#define GL_DRAW_BUFFER14_NV 0x8833
+#define GL_DRAW_BUFFER15_NV 0x8834
+#define GL_COLOR_ATTACHMENT0_NV 0x8CE0
+#define GL_COLOR_ATTACHMENT1_NV 0x8CE1
+#define GL_COLOR_ATTACHMENT2_NV 0x8CE2
+#define GL_COLOR_ATTACHMENT3_NV 0x8CE3
+#define GL_COLOR_ATTACHMENT4_NV 0x8CE4
+#define GL_COLOR_ATTACHMENT5_NV 0x8CE5
+#define GL_COLOR_ATTACHMENT6_NV 0x8CE6
+#define GL_COLOR_ATTACHMENT7_NV 0x8CE7
+#define GL_COLOR_ATTACHMENT8_NV 0x8CE8
+#define GL_COLOR_ATTACHMENT9_NV 0x8CE9
+#define GL_COLOR_ATTACHMENT10_NV 0x8CEA
+#define GL_COLOR_ATTACHMENT11_NV 0x8CEB
+#define GL_COLOR_ATTACHMENT12_NV 0x8CEC
+#define GL_COLOR_ATTACHMENT13_NV 0x8CED
+#define GL_COLOR_ATTACHMENT14_NV 0x8CEE
+#define GL_COLOR_ATTACHMENT15_NV 0x8CEF
+
+typedef void (GLAPIENTRY * PFNGLDRAWBUFFERSNVPROC) (GLsizei n, const GLenum* bufs);
+
+#define glDrawBuffersNV GLEW_GET_FUN(__glewDrawBuffersNV)
+
+#define GLEW_NV_draw_buffers GLEW_GET_VAR(__GLEW_NV_draw_buffers)
+
+#endif /* !GL_NV_draw_buffers */
+
+/* --------------------------- GL_NV_draw_texture -------------------------- */
+
+#if !defined(GL_NV_draw_texture)
+#define GL_NV_draw_texture 1
+
+typedef void (GLAPIENTRY * PFNGLDRAWTEXTURENVPROC) (GLuint texture, GLuint sampler, GLfloat x0, GLfloat y0, GLfloat x1, GLfloat y1, GLfloat z, GLfloat s0, GLfloat t0, GLfloat s1, GLfloat t1);
+
+#define glDrawTextureNV GLEW_GET_FUN(__glewDrawTextureNV)
+
+#define GLEW_NV_draw_texture GLEW_GET_VAR(__GLEW_NV_draw_texture)
+
+#endif /* !GL_NV_draw_texture */
+
+/* ---------------------- GL_NV_fbo_color_attachments ---------------------- */
+
+#if !defined(GL_NV_fbo_color_attachments)
+#define GL_NV_fbo_color_attachments 1
+
+#define GL_MAX_COLOR_ATTACHMENTS_NV 0x8CDF
+#define GL_COLOR_ATTACHMENT0_NV 0x8CE0
+#define GL_COLOR_ATTACHMENT1_NV 0x8CE1
+#define GL_COLOR_ATTACHMENT2_NV 0x8CE2
+#define GL_COLOR_ATTACHMENT3_NV 0x8CE3
+#define GL_COLOR_ATTACHMENT4_NV 0x8CE4
+#define GL_COLOR_ATTACHMENT5_NV 0x8CE5
+#define GL_COLOR_ATTACHMENT6_NV 0x8CE6
+#define GL_COLOR_ATTACHMENT7_NV 0x8CE7
+#define GL_COLOR_ATTACHMENT8_NV 0x8CE8
+#define GL_COLOR_ATTACHMENT9_NV 0x8CE9
+#define GL_COLOR_ATTACHMENT10_NV 0x8CEA
+#define GL_COLOR_ATTACHMENT11_NV 0x8CEB
+#define GL_COLOR_ATTACHMENT12_NV 0x8CEC
+#define GL_COLOR_ATTACHMENT13_NV 0x8CED
+#define GL_COLOR_ATTACHMENT14_NV 0x8CEE
+#define GL_COLOR_ATTACHMENT15_NV 0x8CEF
+
+#define GLEW_NV_fbo_color_attachments GLEW_GET_VAR(__GLEW_NV_fbo_color_attachments)
+
+#endif /* !GL_NV_fbo_color_attachments */
+
+/* ------------------------------ GL_NV_fence ------------------------------ */
+
+#if !defined(GL_NV_fence)
+#define GL_NV_fence 1
+
+#define GL_ALL_COMPLETED_NV 0x84F2
+#define GL_FENCE_STATUS_NV 0x84F3
+#define GL_FENCE_CONDITION_NV 0x84F4
+
+typedef void (GLAPIENTRY * PFNGLDELETEFENCESNVPROC) (GLsizei n, const GLuint* fences);
+typedef void (GLAPIENTRY * PFNGLFINISHFENCENVPROC) (GLuint fence);
+typedef void (GLAPIENTRY * PFNGLGENFENCESNVPROC) (GLsizei n, GLuint* fences);
+typedef void (GLAPIENTRY * PFNGLGETFENCEIVNVPROC) (GLuint fence, GLenum pname, GLint* params);
+typedef GLboolean (GLAPIENTRY * PFNGLISFENCENVPROC) (GLuint fence);
+typedef void (GLAPIENTRY * PFNGLSETFENCENVPROC) (GLuint fence, GLenum condition);
+typedef GLboolean (GLAPIENTRY * PFNGLTESTFENCENVPROC) (GLuint fence);
+
+#define glDeleteFencesNV GLEW_GET_FUN(__glewDeleteFencesNV)
+#define glFinishFenceNV GLEW_GET_FUN(__glewFinishFenceNV)
+#define glGenFencesNV GLEW_GET_FUN(__glewGenFencesNV)
+#define glGetFenceivNV GLEW_GET_FUN(__glewGetFenceivNV)
+#define glIsFenceNV GLEW_GET_FUN(__glewIsFenceNV)
+#define glSetFenceNV GLEW_GET_FUN(__glewSetFenceNV)
+#define glTestFenceNV GLEW_GET_FUN(__glewTestFenceNV)
+
+#define GLEW_NV_fence GLEW_GET_VAR(__GLEW_NV_fence)
+
+#endif /* !GL_NV_fence */
+
+/* -------------------------- GL_NV_pack_subimage -------------------------- */
+
+#if !defined(GL_NV_pack_subimage)
+#define GL_NV_pack_subimage 1
+
+#define GL_PACK_ROW_LENGTH_NV 0x0D02
+#define GL_PACK_SKIP_ROWS_NV 0x0D03
+#define GL_PACK_SKIP_PIXELS_NV 0x0D04
+
+#define GLEW_NV_pack_subimage GLEW_GET_VAR(__GLEW_NV_pack_subimage)
+
+#endif /* !GL_NV_pack_subimage */
+
+/* --------------------------- GL_NV_packed_float -------------------------- */
+
+#if !defined(GL_NV_packed_float)
+#define GL_NV_packed_float 1
+
+#define GL_R11F_G11F_B10F_NV 0x8C3A
+#define GL_UNSIGNED_INT_10F_11F_11F_REV_NV 0x8C3B
+
+#define GLEW_NV_packed_float GLEW_GET_VAR(__GLEW_NV_packed_float)
+
+#endif /* !GL_NV_packed_float */
+
+/* ----------------------- GL_NV_packed_float_linear ----------------------- */
+
+#if !defined(GL_NV_packed_float_linear)
+#define GL_NV_packed_float_linear 1
+
+#define GL_R11F_G11F_B10F_NV 0x8C3A
+#define GL_UNSIGNED_INT_10F_11F_11F_REV_NV 0x8C3B
+
+#define GLEW_NV_packed_float_linear GLEW_GET_VAR(__GLEW_NV_packed_float_linear)
+
+#endif /* !GL_NV_packed_float_linear */
+
+/* ----------------------- GL_NV_pixel_buffer_object ----------------------- */
+
+#if !defined(GL_NV_pixel_buffer_object)
+#define GL_NV_pixel_buffer_object 1
+
+#define GL_PIXEL_PACK_BUFFER_NV 0x88EB
+#define GL_PIXEL_UNPACK_BUFFER_NV 0x88EC
+#define GL_PIXEL_PACK_BUFFER_BINDING_NV 0x88ED
+#define GL_PIXEL_UNPACK_BUFFER_BINDING_NV 0x88EF
+
+#define GLEW_NV_pixel_buffer_object GLEW_GET_VAR(__GLEW_NV_pixel_buffer_object)
+
+#endif /* !GL_NV_pixel_buffer_object */
+
+/* ------------------------- GL_NV_platform_binary ------------------------- */
+
+#if !defined(GL_NV_platform_binary)
+#define GL_NV_platform_binary 1
+
+#define GL_NVIDIA_PLATFORM_BINARY_NV 0x890B
+
+#define GLEW_NV_platform_binary GLEW_GET_VAR(__GLEW_NV_platform_binary)
+
+#endif /* !GL_NV_platform_binary */
+
+/* --------------------------- GL_NV_read_buffer --------------------------- */
+
+#if !defined(GL_NV_read_buffer)
+#define GL_NV_read_buffer 1
+
+#define GL_READ_BUFFER_NV 0x0C02
+
+typedef void (GLAPIENTRY * PFNGLREADBUFFERNVPROC) (GLenum mode);
+
+#define glReadBufferNV GLEW_GET_FUN(__glewReadBufferNV)
+
+#define GLEW_NV_read_buffer GLEW_GET_VAR(__GLEW_NV_read_buffer)
+
+#endif /* !GL_NV_read_buffer */
+
+/* ------------------------ GL_NV_read_buffer_front ------------------------ */
+
+#if !defined(GL_NV_read_buffer_front)
+#define GL_NV_read_buffer_front 1
+
+#define GLEW_NV_read_buffer_front GLEW_GET_VAR(__GLEW_NV_read_buffer_front)
+
+#endif /* !GL_NV_read_buffer_front */
+
+/* ---------------------------- GL_NV_read_depth --------------------------- */
+
+#if !defined(GL_NV_read_depth)
+#define GL_NV_read_depth 1
+
+#define GLEW_NV_read_depth GLEW_GET_VAR(__GLEW_NV_read_depth)
+
+#endif /* !GL_NV_read_depth */
+
+/* ------------------------ GL_NV_read_depth_stencil ----------------------- */
+
+#if !defined(GL_NV_read_depth_stencil)
+#define GL_NV_read_depth_stencil 1
+
+#define GLEW_NV_read_depth_stencil GLEW_GET_VAR(__GLEW_NV_read_depth_stencil)
+
+#endif /* !GL_NV_read_depth_stencil */
+
+/* --------------------------- GL_NV_read_stencil -------------------------- */
+
+#if !defined(GL_NV_read_stencil)
+#define GL_NV_read_stencil 1
+
+#define GLEW_NV_read_stencil GLEW_GET_VAR(__GLEW_NV_read_stencil)
+
+#endif /* !GL_NV_read_stencil */
+
+/* -------------------------- GL_NV_texture_array -------------------------- */
+
+#if !defined(GL_NV_texture_array)
+#define GL_NV_texture_array 1
+
+#define GL_UNPACK_SKIP_IMAGES_NV 0x806D
+#define GL_UNPACK_IMAGE_HEIGHT_NV 0x806E
+#define GL_MAX_ARRAY_TEXTURE_LAYERS_NV 0x88FF
+#define GL_TEXTURE_2D_ARRAY_NV 0x8C1A
+#define GL_TEXTURE_BINDING_2D_ARRAY_NV 0x8C1D
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER_NV 0x8CD4
+#define GL_SAMPLER_2D_ARRAY_NV 0x8DC1
+
+typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXIMAGE3DNVPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void* data);
+typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXSUBIMAGE3DNVPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void* data);
+typedef void (GLAPIENTRY * PFNGLCOPYTEXSUBIMAGE3DNVPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+typedef void (GLAPIENTRY * PFNGLFRAMEBUFFERTEXTURELAYERNVPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer);
+typedef void (GLAPIENTRY * PFNGLTEXIMAGE3DNVPROC) (GLenum target, GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void* pixels);
+typedef void (GLAPIENTRY * PFNGLTEXSUBIMAGE3DNVPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void* pixels);
+
+#define glCompressedTexImage3DNV GLEW_GET_FUN(__glewCompressedTexImage3DNV)
+#define glCompressedTexSubImage3DNV GLEW_GET_FUN(__glewCompressedTexSubImage3DNV)
+#define glCopyTexSubImage3DNV GLEW_GET_FUN(__glewCopyTexSubImage3DNV)
+#define glFramebufferTextureLayerNV GLEW_GET_FUN(__glewFramebufferTextureLayerNV)
+#define glTexImage3DNV GLEW_GET_FUN(__glewTexImage3DNV)
+#define glTexSubImage3DNV GLEW_GET_FUN(__glewTexSubImage3DNV)
+
+#define GLEW_NV_texture_array GLEW_GET_VAR(__GLEW_NV_texture_array)
+
+#endif /* !GL_NV_texture_array */
+
+/* --------------------- GL_NV_texture_compression_latc -------------------- */
+
+#if !defined(GL_NV_texture_compression_latc)
+#define GL_NV_texture_compression_latc 1
+
+#define GL_COMPRESSED_LUMINANCE_LATC1_NV 0x8C70
+#define GL_COMPRESSED_SIGNED_LUMINANCE_LATC1_NV 0x8C71
+#define GL_COMPRESSED_LUMINANCE_ALPHA_LATC2_NV 0x8C72
+#define GL_COMPRESSED_SIGNED_LUMINANCE_ALPHA_LATC2_NV 0x8C73
+
+#define GLEW_NV_texture_compression_latc GLEW_GET_VAR(__GLEW_NV_texture_compression_latc)
+
+#endif /* !GL_NV_texture_compression_latc */
+
+/* --------------------- GL_NV_texture_compression_s3tc -------------------- */
+
+#if !defined(GL_NV_texture_compression_s3tc)
+#define GL_NV_texture_compression_s3tc 1
+
+#define GL_COMPRESSED_RGB_S3TC_DXT1_NV 0x83F0
+#define GL_COMPRESSED_RGBA_S3TC_DXT1_NV 0x83F1
+#define GL_COMPRESSED_RGBA_S3TC_DXT3_NV 0x83F2
+#define GL_COMPRESSED_RGBA_S3TC_DXT5_NV 0x83F3
+
+#define GLEW_NV_texture_compression_s3tc GLEW_GET_VAR(__GLEW_NV_texture_compression_s3tc)
+
+#endif /* !GL_NV_texture_compression_s3tc */
+
+/* ----------------- GL_NV_texture_compression_s3tc_update ----------------- */
+
+#if !defined(GL_NV_texture_compression_s3tc_update)
+#define GL_NV_texture_compression_s3tc_update 1
+
+#define GLEW_NV_texture_compression_s3tc_update GLEW_GET_VAR(__GLEW_NV_texture_compression_s3tc_update)
+
+#endif /* !GL_NV_texture_compression_s3tc_update */
+
+/* ---------------------- GL_NV_texture_npot_2D_mipmap --------------------- */
+
+#if !defined(GL_NV_texture_npot_2D_mipmap)
+#define GL_NV_texture_npot_2D_mipmap 1
+
+#define GLEW_NV_texture_npot_2D_mipmap GLEW_GET_VAR(__GLEW_NV_texture_npot_2D_mipmap)
+
+#endif /* !GL_NV_texture_npot_2D_mipmap */
+
+/* ---------------------------- GL_OES_EGL_image --------------------------- */
+
+#if !defined(GL_OES_EGL_image)
+#define GL_OES_EGL_image 1
+
+typedef void* GLeglImageOES;
+
+typedef void (GLAPIENTRY * PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC) (GLenum target, GLeglImageOES image);
+typedef void (GLAPIENTRY * PFNGLEGLIMAGETARGETTEXTURE2DOESPROC) (GLenum target, GLeglImageOES image);
+
+#define glEGLImageTargetRenderbufferStorageOES GLEW_GET_FUN(__glewEGLImageTargetRenderbufferStorageOES)
+#define glEGLImageTargetTexture2DOES GLEW_GET_FUN(__glewEGLImageTargetTexture2DOES)
+
+#define GLEW_OES_EGL_image GLEW_GET_VAR(__GLEW_OES_EGL_image)
+
+#endif /* !GL_OES_EGL_image */
+
+/* ----------------------- GL_OES_EGL_image_external ----------------------- */
+
+#if !defined(GL_OES_EGL_image_external)
+#define GL_OES_EGL_image_external 1
+
+#define GL_TEXTURE_EXTERNAL_OES 0x8D65
+#define GL_SAMPLER_EXTERNAL_OES 0x8D66
+#define GL_TEXTURE_BINDING_EXTERNAL_OES 0x8D67
+#define GL_REQUIRED_TEXTURE_IMAGE_UNITS_OES 0x8D68
+
+#define GLEW_OES_EGL_image_external GLEW_GET_VAR(__GLEW_OES_EGL_image_external)
+
+#endif /* !GL_OES_EGL_image_external */
+
+/* ---------------------------- GL_OES_EGL_sync ---------------------------- */
+
+#if !defined(GL_OES_EGL_sync)
+#define GL_OES_EGL_sync 1
+
+#define GLEW_OES_EGL_sync GLEW_GET_VAR(__GLEW_OES_EGL_sync)
+
+#endif /* !GL_OES_EGL_sync */
+
+/* --------------------- GL_OES_blend_equation_separate -------------------- */
+
+#if !defined(GL_OES_blend_equation_separate)
+#define GL_OES_blend_equation_separate 1
+
+#define GL_BLEND_EQUATION_RGB_OES 0x8009
+#define GL_BLEND_EQUATION_ALPHA_OES 0x883D
+
+typedef void (GLAPIENTRY * PFNGLBLENDEQUATIONSEPARATEOESPROC) (GLenum modeRGB, GLenum modeAlpha);
+
+#define glBlendEquationSeparateOES GLEW_GET_FUN(__glewBlendEquationSeparateOES)
+
+#define GLEW_OES_blend_equation_separate GLEW_GET_VAR(__GLEW_OES_blend_equation_separate)
+
+#endif /* !GL_OES_blend_equation_separate */
+
+/* ----------------------- GL_OES_blend_func_separate ---------------------- */
+
+#if !defined(GL_OES_blend_func_separate)
+#define GL_OES_blend_func_separate 1
+
+#define GL_BLEND_DST_RGB_OES 0x80C8
+#define GL_BLEND_SRC_RGB_OES 0x80C9
+#define GL_BLEND_DST_ALPHA_OES 0x80CA
+#define GL_BLEND_SRC_ALPHA_OES 0x80CB
+
+typedef void (GLAPIENTRY * PFNGLBLENDFUNCSEPARATEOESPROC) (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha);
+
+#define glBlendFuncSeparateOES GLEW_GET_FUN(__glewBlendFuncSeparateOES)
+
+#define GLEW_OES_blend_func_separate GLEW_GET_VAR(__GLEW_OES_blend_func_separate)
+
+#endif /* !GL_OES_blend_func_separate */
+
+/* ------------------------- GL_OES_blend_subtract ------------------------- */
+
+#if !defined(GL_OES_blend_subtract)
+#define GL_OES_blend_subtract 1
+
+#define GL_FUNC_ADD_OES 0x8006
+#define GL_BLEND_EQUATION_OES 0x8009
+#define GL_FUNC_SUBTRACT_OES 0x800A
+#define GL_FUNC_REVERSE_SUBTRACT_OES 0x800B
+
+typedef void (GLAPIENTRY * PFNGLBLENDEQUATIONOESPROC) (GLenum mode);
+
+#define glBlendEquationOES GLEW_GET_FUN(__glewBlendEquationOES)
+
+#define GLEW_OES_blend_subtract GLEW_GET_VAR(__GLEW_OES_blend_subtract)
+
+#endif /* !GL_OES_blend_subtract */
+
+/* ------------------------ GL_OES_byte_coordinates ------------------------ */
+
+#if !defined(GL_OES_byte_coordinates)
+#define GL_OES_byte_coordinates 1
+
+#define GL_BYTE 0x1400
+
+#define GLEW_OES_byte_coordinates GLEW_GET_VAR(__GLEW_OES_byte_coordinates)
+
+#endif /* !GL_OES_byte_coordinates */
+
+/* ------------------ GL_OES_compressed_ETC1_RGB8_texture ------------------ */
+
+#if !defined(GL_OES_compressed_ETC1_RGB8_texture)
+#define GL_OES_compressed_ETC1_RGB8_texture 1
+
+#define GL_ETC1_RGB8_OES 0x8D64
+
+#define GLEW_OES_compressed_ETC1_RGB8_texture GLEW_GET_VAR(__GLEW_OES_compressed_ETC1_RGB8_texture)
+
+#endif /* !GL_OES_compressed_ETC1_RGB8_texture */
+
+/* ------------------- GL_OES_compressed_paletted_texture ------------------ */
+
+#if !defined(GL_OES_compressed_paletted_texture)
+#define GL_OES_compressed_paletted_texture 1
+
+#define GL_PALETTE4_RGB8_OES 0x8B90
+#define GL_PALETTE4_RGBA8_OES 0x8B91
+#define GL_PALETTE4_R5_G6_B5_OES 0x8B92
+#define GL_PALETTE4_RGBA4_OES 0x8B93
+#define GL_PALETTE4_RGB5_A1_OES 0x8B94
+#define GL_PALETTE8_RGB8_OES 0x8B95
+#define GL_PALETTE8_RGBA8_OES 0x8B96
+#define GL_PALETTE8_R5_G6_B5_OES 0x8B97
+#define GL_PALETTE8_RGBA4_OES 0x8B98
+#define GL_PALETTE8_RGB5_A1_OES 0x8B99
+
+#define GLEW_OES_compressed_paletted_texture GLEW_GET_VAR(__GLEW_OES_compressed_paletted_texture)
+
+#endif /* !GL_OES_compressed_paletted_texture */
+
+/* ----------------------------- GL_OES_depth24 ---------------------------- */
+
+#if !defined(GL_OES_depth24)
+#define GL_OES_depth24 1
+
+#define GL_DEPTH_COMPONENT24_OES 0x81A6
+
+#define GLEW_OES_depth24 GLEW_GET_VAR(__GLEW_OES_depth24)
+
+#endif /* !GL_OES_depth24 */
+
+/* ----------------------------- GL_OES_depth32 ---------------------------- */
+
+#if !defined(GL_OES_depth32)
+#define GL_OES_depth32 1
+
+#define GL_DEPTH_COMPONENT32_OES 0x81A7
+
+#define GLEW_OES_depth32 GLEW_GET_VAR(__GLEW_OES_depth32)
+
+#endif /* !GL_OES_depth32 */
+
+/* -------------------------- GL_OES_depth_texture ------------------------- */
+
+#if !defined(GL_OES_depth_texture)
+#define GL_OES_depth_texture 1
+
+#define GL_UNSIGNED_SHORT 0x1403
+#define GL_UNSIGNED_INT 0x1405
+#define GL_DEPTH_COMPONENT 0x1902
+
+#define GLEW_OES_depth_texture GLEW_GET_VAR(__GLEW_OES_depth_texture)
+
+#endif /* !GL_OES_depth_texture */
+
+/* --------------------- GL_OES_depth_texture_cube_map --------------------- */
+
+#if !defined(GL_OES_depth_texture_cube_map)
+#define GL_OES_depth_texture_cube_map 1
+
+#define GL_UNSIGNED_SHORT 0x1403
+#define GL_UNSIGNED_INT 0x1405
+#define GL_DEPTH_COMPONENT 0x1902
+#define GL_DEPTH_STENCIL_OES 0x84F9
+#define GL_DEPTH24_STENCIL8_OES 0x88F0
+
+#define GLEW_OES_depth_texture_cube_map GLEW_GET_VAR(__GLEW_OES_depth_texture_cube_map)
+
+#endif /* !GL_OES_depth_texture_cube_map */
+
+/* -------------------------- GL_OES_draw_texture -------------------------- */
+
+#if !defined(GL_OES_draw_texture)
+#define GL_OES_draw_texture 1
+
+#define GL_TEXTURE_CROP_RECT_OES 0x8B9D
+
+#define GLEW_OES_draw_texture GLEW_GET_VAR(__GLEW_OES_draw_texture)
+
+#endif /* !GL_OES_draw_texture */
+
+/* ----------------------- GL_OES_element_index_uint ----------------------- */
+
+#if !defined(GL_OES_element_index_uint)
+#define GL_OES_element_index_uint 1
+
+#define GL_UNSIGNED_INT 0x1405
+
+#define GLEW_OES_element_index_uint GLEW_GET_VAR(__GLEW_OES_element_index_uint)
+
+#endif /* !GL_OES_element_index_uint */
+
+/* --------------------- GL_OES_extended_matrix_palette -------------------- */
+
+#if !defined(GL_OES_extended_matrix_palette)
+#define GL_OES_extended_matrix_palette 1
+
+#define GLEW_OES_extended_matrix_palette GLEW_GET_VAR(__GLEW_OES_extended_matrix_palette)
+
+#endif /* !GL_OES_extended_matrix_palette */
+
+/* ------------------------ GL_OES_fbo_render_mipmap ----------------------- */
+
+#if !defined(GL_OES_fbo_render_mipmap)
+#define GL_OES_fbo_render_mipmap 1
+
+#define GLEW_OES_fbo_render_mipmap GLEW_GET_VAR(__GLEW_OES_fbo_render_mipmap)
+
+#endif /* !GL_OES_fbo_render_mipmap */
+
+/* --------------------- GL_OES_fragment_precision_high -------------------- */
+
+#if !defined(GL_OES_fragment_precision_high)
+#define GL_OES_fragment_precision_high 1
+
+#define GLEW_OES_fragment_precision_high GLEW_GET_VAR(__GLEW_OES_fragment_precision_high)
+
+#endif /* !GL_OES_fragment_precision_high */
+
+/* ----------------------- GL_OES_framebuffer_object ----------------------- */
+
+#if !defined(GL_OES_framebuffer_object)
+#define GL_OES_framebuffer_object 1
+
+#define GL_NONE_OES 0
+#define GL_INVALID_FRAMEBUFFER_OPERATION_OES 0x0506
+#define GL_RGBA4_OES 0x8056
+#define GL_RGB5_A1_OES 0x8057
+#define GL_DEPTH_COMPONENT16_OES 0x81A5
+#define GL_MAX_RENDERBUFFER_SIZE_OES 0x84E8
+#define GL_FRAMEBUFFER_BINDING_OES 0x8CA6
+#define GL_RENDERBUFFER_BINDING_OES 0x8CA7
+#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_OES 0x8CD0
+#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_OES 0x8CD1
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL_OES 0x8CD2
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE_OES 0x8CD3
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_3D_ZOFFSET_OES 0x8CD4
+#define GL_FRAMEBUFFER_COMPLETE_OES 0x8CD5
+#define GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_OES 0x8CD6
+#define GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_OES 0x8CD7
+#define GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_OES 0x8CD9
+#define GL_FRAMEBUFFER_INCOMPLETE_FORMATS_OES 0x8CDA
+#define GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_OES 0x8CDB
+#define GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_OES 0x8CDC
+#define GL_FRAMEBUFFER_UNSUPPORTED_OES 0x8CDD
+#define GL_COLOR_ATTACHMENT0_OES 0x8CE0
+#define GL_DEPTH_ATTACHMENT_OES 0x8D00
+#define GL_STENCIL_ATTACHMENT_OES 0x8D20
+#define GL_FRAMEBUFFER_OES 0x8D40
+#define GL_RENDERBUFFER_OES 0x8D41
+#define GL_RENDERBUFFER_WIDTH_OES 0x8D42
+#define GL_RENDERBUFFER_HEIGHT_OES 0x8D43
+#define GL_RENDERBUFFER_INTERNAL_FORMAT_OES 0x8D44
+#define GL_STENCIL_INDEX1_OES 0x8D46
+#define GL_STENCIL_INDEX4_OES 0x8D47
+#define GL_STENCIL_INDEX8_OES 0x8D48
+#define GL_RENDERBUFFER_RED_SIZE_OES 0x8D50
+#define GL_RENDERBUFFER_GREEN_SIZE_OES 0x8D51
+#define GL_RENDERBUFFER_BLUE_SIZE_OES 0x8D52
+#define GL_RENDERBUFFER_ALPHA_SIZE_OES 0x8D53
+#define GL_RENDERBUFFER_DEPTH_SIZE_OES 0x8D54
+#define GL_RENDERBUFFER_STENCIL_SIZE_OES 0x8D55
+#define GL_RGB565_OES 0x8D62
+
+typedef void (GLAPIENTRY * PFNGLBINDFRAMEBUFFEROESPROC) (GLenum target, GLuint framebuffer);
+typedef void (GLAPIENTRY * PFNGLBINDRENDERBUFFEROESPROC) (GLenum target, GLuint renderbuffer);
+typedef GLenum (GLAPIENTRY * PFNGLCHECKFRAMEBUFFERSTATUSOESPROC) (GLenum target);
+typedef void (GLAPIENTRY * PFNGLDELETEFRAMEBUFFERSOESPROC) (GLsizei n, const GLuint* framebuffers);
+typedef void (GLAPIENTRY * PFNGLDELETERENDERBUFFERSOESPROC) (GLsizei n, const GLuint* renderbuffers);
+typedef void (GLAPIENTRY * PFNGLFRAMEBUFFERRENDERBUFFEROESPROC) (GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer);
+typedef void (GLAPIENTRY * PFNGLFRAMEBUFFERTEXTURE2DOESPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
+typedef void (GLAPIENTRY * PFNGLGENFRAMEBUFFERSOESPROC) (GLsizei n, GLuint* framebuffers);
+typedef void (GLAPIENTRY * PFNGLGENRENDERBUFFERSOESPROC) (GLsizei n, GLuint* renderbuffers);
+typedef void (GLAPIENTRY * PFNGLGENERATEMIPMAPOESPROC) (GLenum target);
+typedef void (GLAPIENTRY * PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVOESPROC) (GLenum target, GLenum attachment, GLenum pname, GLint* params);
+typedef void (GLAPIENTRY * PFNGLGETRENDERBUFFERPARAMETERIVOESPROC) (GLenum target, GLenum pname, GLint* params);
+typedef GLboolean (GLAPIENTRY * PFNGLISFRAMEBUFFEROESPROC) (GLuint framebuffer);
+typedef GLboolean (GLAPIENTRY * PFNGLISRENDERBUFFEROESPROC) (GLuint renderbuffer);
+typedef void (GLAPIENTRY * PFNGLRENDERBUFFERSTORAGEOESPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
+
+#define glBindFramebufferOES GLEW_GET_FUN(__glewBindFramebufferOES)
+#define glBindRenderbufferOES GLEW_GET_FUN(__glewBindRenderbufferOES)
+#define glCheckFramebufferStatusOES GLEW_GET_FUN(__glewCheckFramebufferStatusOES)
+#define glDeleteFramebuffersOES GLEW_GET_FUN(__glewDeleteFramebuffersOES)
+#define glDeleteRenderbuffersOES GLEW_GET_FUN(__glewDeleteRenderbuffersOES)
+#define glFramebufferRenderbufferOES GLEW_GET_FUN(__glewFramebufferRenderbufferOES)
+#define glFramebufferTexture2DOES GLEW_GET_FUN(__glewFramebufferTexture2DOES)
+#define glGenFramebuffersOES GLEW_GET_FUN(__glewGenFramebuffersOES)
+#define glGenRenderbuffersOES GLEW_GET_FUN(__glewGenRenderbuffersOES)
+#define glGenerateMipmapOES GLEW_GET_FUN(__glewGenerateMipmapOES)
+#define glGetFramebufferAttachmentParameterivOES GLEW_GET_FUN(__glewGetFramebufferAttachmentParameterivOES)
+#define glGetRenderbufferParameterivOES GLEW_GET_FUN(__glewGetRenderbufferParameterivOES)
+#define glIsFramebufferOES GLEW_GET_FUN(__glewIsFramebufferOES)
+#define glIsRenderbufferOES GLEW_GET_FUN(__glewIsRenderbufferOES)
+#define glRenderbufferStorageOES GLEW_GET_FUN(__glewRenderbufferStorageOES)
+
+#define GLEW_OES_framebuffer_object GLEW_GET_VAR(__GLEW_OES_framebuffer_object)
+
+#endif /* !GL_OES_framebuffer_object */
+
+/* ----------------------- GL_OES_get_program_binary ----------------------- */
+
+#if !defined(GL_OES_get_program_binary)
+#define GL_OES_get_program_binary 1
+
+#define GL_PROGRAM_BINARY_LENGTH_OES 0x8741
+#define GL_NUM_PROGRAM_BINARY_FORMATS_OES 0x87FE
+#define GL_PROGRAM_BINARY_FORMATS_OES 0x87FF
+
+typedef void (GLAPIENTRY * PFNGLGETPROGRAMBINARYOESPROC) (GLuint program, GLsizei bufSize, GLsizei* length, GLenum *binaryFormat, GLvoid*binary);
+typedef void (GLAPIENTRY * PFNGLPROGRAMBINARYOESPROC) (GLuint program, GLenum binaryFormat, const void* binary, GLint length);
+
+#define glGetProgramBinaryOES GLEW_GET_FUN(__glewGetProgramBinaryOES)
+#define glProgramBinaryOES GLEW_GET_FUN(__glewProgramBinaryOES)
+
+#define GLEW_OES_get_program_binary GLEW_GET_VAR(__GLEW_OES_get_program_binary)
+
+#endif /* !GL_OES_get_program_binary */
+
+/* ---------------------------- GL_OES_mapbuffer --------------------------- */
+
+#if !defined(GL_OES_mapbuffer)
+#define GL_OES_mapbuffer 1
+
+#define GL_WRITE_ONLY_OES 0x88B9
+#define GL_BUFFER_ACCESS_OES 0x88BB
+#define GL_BUFFER_MAPPED_OES 0x88BC
+#define GL_BUFFER_MAP_POINTER_OES 0x88BD
+
+typedef void (GLAPIENTRY * PFNGLGETBUFFERPOINTERVOESPROC) (GLenum target, GLenum pname, void** params);
+typedef GLvoid * (GLAPIENTRY * PFNGLMAPBUFFEROESPROC) (GLenum target, GLenum access);
+typedef GLboolean (GLAPIENTRY * PFNGLUNMAPBUFFEROESPROC) (GLenum target);
+
+#define glGetBufferPointervOES GLEW_GET_FUN(__glewGetBufferPointervOES)
+#define glMapBufferOES GLEW_GET_FUN(__glewMapBufferOES)
+#define glUnmapBufferOES GLEW_GET_FUN(__glewUnmapBufferOES)
+
+#define GLEW_OES_mapbuffer GLEW_GET_VAR(__GLEW_OES_mapbuffer)
+
+#endif /* !GL_OES_mapbuffer */
+
+/* --------------------------- GL_OES_matrix_get --------------------------- */
+
+#if !defined(GL_OES_matrix_get)
+#define GL_OES_matrix_get 1
+
+#define GL_PROJECTION_MATRIX_FLOAT_AS_INT_BITS_OES 0x898
+#define GL_MODELVIEW_MATRIX_FLOAT_AS_INT_BITS_OES 0x898
+#define GL_TEXTURE_MATRIX_FLOAT_AS_INT_BITS_OES 0x898
+
+#define GLEW_OES_matrix_get GLEW_GET_VAR(__GLEW_OES_matrix_get)
+
+#endif /* !GL_OES_matrix_get */
+
+/* ------------------------- GL_OES_matrix_palette ------------------------- */
+
+#if !defined(GL_OES_matrix_palette)
+#define GL_OES_matrix_palette 1
+
+#define GL_MAX_VERTEX_UNITS_OES 0x86A4
+#define GL_WEIGHT_ARRAY_TYPE_OES 0x86A9
+#define GL_WEIGHT_ARRAY_STRIDE_OES 0x86AA
+#define GL_WEIGHT_ARRAY_SIZE_OES 0x86AB
+#define GL_WEIGHT_ARRAY_POINTER_OES 0x86AC
+#define GL_WEIGHT_ARRAY_OES 0x86AD
+#define GL_MATRIX_PALETTE_OES 0x8840
+#define GL_MAX_PALETTE_MATRICES_OES 0x8842
+#define GL_CURRENT_PALETTE_MATRIX_OES 0x8843
+#define GL_MATRIX_INDEX_ARRAY_OES 0x8844
+#define GL_MATRIX_INDEX_ARRAY_SIZE_OES 0x8846
+#define GL_MATRIX_INDEX_ARRAY_TYPE_OES 0x8847
+#define GL_MATRIX_INDEX_ARRAY_STRIDE_OES 0x8848
+#define GL_MATRIX_INDEX_ARRAY_POINTER_OES 0x8849
+#define GL_WEIGHT_ARRAY_BUFFER_BINDING_OES 0x889E
+#define GL_MATRIX_INDEX_ARRAY_BUFFER_BINDING_OES 0x8B9E
+
+typedef void (GLAPIENTRY * PFNGLCURRENTPALETTEMATRIXOESPROC) (GLuint index);
+typedef void (GLAPIENTRY * PFNGLMATRIXINDEXPOINTEROESPROC) (GLint size, GLenum type, GLsizei stride, void* pointer);
+typedef void (GLAPIENTRY * PFNGLWEIGHTPOINTEROESPROC) (GLint size, GLenum type, GLsizei stride, void* pointer);
+
+#define glCurrentPaletteMatrixOES GLEW_GET_FUN(__glewCurrentPaletteMatrixOES)
+#define glMatrixIndexPointerOES GLEW_GET_FUN(__glewMatrixIndexPointerOES)
+#define glWeightPointerOES GLEW_GET_FUN(__glewWeightPointerOES)
+
+#define GLEW_OES_matrix_palette GLEW_GET_VAR(__GLEW_OES_matrix_palette)
+
+#endif /* !GL_OES_matrix_palette */
+
+/* ---------------------- GL_OES_packed_depth_stencil ---------------------- */
+
+#if !defined(GL_OES_packed_depth_stencil)
+#define GL_OES_packed_depth_stencil 1
+
+#define GL_DEPTH_STENCIL_OES 0x84F9
+#define GL_UNSIGNED_INT_24_8_OES 0x84FA
+#define GL_DEPTH24_STENCIL8_OES 0x88F0
+
+#define GLEW_OES_packed_depth_stencil GLEW_GET_VAR(__GLEW_OES_packed_depth_stencil)
+
+#endif /* !GL_OES_packed_depth_stencil */
+
+/* ------------------------ GL_OES_point_size_array ------------------------ */
+
+#if !defined(GL_OES_point_size_array)
+#define GL_OES_point_size_array 1
+
+#define GL_POINT_SIZE_ARRAY_TYPE_OES 0x898A
+#define GL_POINT_SIZE_ARRAY_STRIDE_OES 0x898B
+#define GL_POINT_SIZE_ARRAY_POINTER_OES 0x898C
+#define GL_POINT_SIZE_ARRAY_OES 0x8B9C
+#define GL_POINT_SIZE_ARRAY_BUFFER_BINDING_OES 0x8B9F
+
+typedef void (GLAPIENTRY * PFNGLPOINTSIZEPOINTEROESPROC) (GLenum type, GLsizei stride, const void* ptr);
+
+#define glPointSizePointerOES GLEW_GET_FUN(__glewPointSizePointerOES)
+
+#define GLEW_OES_point_size_array GLEW_GET_VAR(__GLEW_OES_point_size_array)
+
+#endif /* !GL_OES_point_size_array */
+
+/* -------------------------- GL_OES_point_sprite -------------------------- */
+
+#if !defined(GL_OES_point_sprite)
+#define GL_OES_point_sprite 1
+
+#define GL_POINT_SPRITE_OES 0x8861
+#define GL_COORD_REPLACE_OES 0x8862
+
+#define GLEW_OES_point_sprite GLEW_GET_VAR(__GLEW_OES_point_sprite)
+
+#endif /* !GL_OES_point_sprite */
+
+/* --------------------------- GL_OES_read_format -------------------------- */
+
+#if !defined(GL_OES_read_format)
+#define GL_OES_read_format 1
+
+#define GL_IMPLEMENTATION_COLOR_READ_TYPE_OES 0x8B9A
+#define GL_IMPLEMENTATION_COLOR_READ_FORMAT_OES 0x8B9B
+
+#define GLEW_OES_read_format GLEW_GET_VAR(__GLEW_OES_read_format)
+
+#endif /* !GL_OES_read_format */
+
+/* --------------------- GL_OES_required_internalformat -------------------- */
+
+#if !defined(GL_OES_required_internalformat)
+#define GL_OES_required_internalformat 1
+
+#define GL_ALPHA8_OES 0x803C
+#define GL_LUMINANCE8_OES 0x8040
+#define GL_LUMINANCE4_ALPHA4_OES 0x8043
+#define GL_LUMINANCE8_ALPHA8_OES 0x8045
+#define GL_RGB8_OES 0x8051
+#define GL_RGB10_EXT 0x8052
+#define GL_RGBA4_OES 0x8056
+#define GL_RGB5_A1_OES 0x8057
+#define GL_RGBA8_OES 0x8058
+#define GL_RGB10_A2_EXT 0x8059
+#define GL_DEPTH_COMPONENT16_OES 0x81A5
+#define GL_DEPTH_COMPONENT24_OES 0x81A6
+#define GL_DEPTH_COMPONENT32_OES 0x81A7
+#define GL_DEPTH24_STENCIL8_OES 0x88F0
+#define GL_RGB565_OES 0x8D62
+
+#define GLEW_OES_required_internalformat GLEW_GET_VAR(__GLEW_OES_required_internalformat)
+
+#endif /* !GL_OES_required_internalformat */
+
+/* --------------------------- GL_OES_rgb8_rgba8 --------------------------- */
+
+#if !defined(GL_OES_rgb8_rgba8)
+#define GL_OES_rgb8_rgba8 1
+
+#define GL_RGB8_OES 0x8051
+#define GL_RGBA8_OES 0x8058
+
+#define GLEW_OES_rgb8_rgba8 GLEW_GET_VAR(__GLEW_OES_rgb8_rgba8)
+
+#endif /* !GL_OES_rgb8_rgba8 */
+
+/* ------------------------ GL_OES_single_precision ------------------------ */
+
+#if !defined(GL_OES_single_precision)
+#define GL_OES_single_precision 1
+
+typedef double GLclampd;
+
+typedef void (GLAPIENTRY * PFNGLCLEARDEPTHFOESPROC) (GLclampd depth);
+typedef void (GLAPIENTRY * PFNGLCLIPPLANEFOESPROC) (GLenum plane, const GLfloat* equation);
+typedef void (GLAPIENTRY * PFNGLDEPTHRANGEFOESPROC) (GLclampf n, GLclampf f);
+typedef void (GLAPIENTRY * PFNGLFRUSTUMFOESPROC) (GLfloat l, GLfloat r, GLfloat b, GLfloat t, GLfloat n, GLfloat f);
+typedef void (GLAPIENTRY * PFNGLGETCLIPPLANEFOESPROC) (GLenum plane, GLfloat* equation);
+typedef void (GLAPIENTRY * PFNGLORTHOFOESPROC) (GLfloat l, GLfloat r, GLfloat b, GLfloat t, GLfloat n, GLfloat f);
+
+#define glClearDepthfOES GLEW_GET_FUN(__glewClearDepthfOES)
+#define glClipPlanefOES GLEW_GET_FUN(__glewClipPlanefOES)
+#define glDepthRangefOES GLEW_GET_FUN(__glewDepthRangefOES)
+#define glFrustumfOES GLEW_GET_FUN(__glewFrustumfOES)
+#define glGetClipPlanefOES GLEW_GET_FUN(__glewGetClipPlanefOES)
+#define glOrthofOES GLEW_GET_FUN(__glewOrthofOES)
+
+#define GLEW_OES_single_precision GLEW_GET_VAR(__GLEW_OES_single_precision)
+
+#endif /* !GL_OES_single_precision */
+
+/* ---------------------- GL_OES_standard_derivatives ---------------------- */
+
+#if !defined(GL_OES_standard_derivatives)
+#define GL_OES_standard_derivatives 1
+
+#define GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES 0x8B8B
+
+#define GLEW_OES_standard_derivatives GLEW_GET_VAR(__GLEW_OES_standard_derivatives)
+
+#endif /* !GL_OES_standard_derivatives */
+
+/* ---------------------------- GL_OES_stencil1 ---------------------------- */
+
+#if !defined(GL_OES_stencil1)
+#define GL_OES_stencil1 1
+
+#define GL_STENCIL_INDEX1_OES 0x8D46
+
+#define GLEW_OES_stencil1 GLEW_GET_VAR(__GLEW_OES_stencil1)
+
+#endif /* !GL_OES_stencil1 */
+
+/* ---------------------------- GL_OES_stencil4 ---------------------------- */
+
+#if !defined(GL_OES_stencil4)
+#define GL_OES_stencil4 1
+
+#define GL_STENCIL_INDEX4_OES 0x8D47
+
+#define GLEW_OES_stencil4 GLEW_GET_VAR(__GLEW_OES_stencil4)
+
+#endif /* !GL_OES_stencil4 */
+
+/* ---------------------------- GL_OES_stencil8 ---------------------------- */
+
+#if !defined(GL_OES_stencil8)
+#define GL_OES_stencil8 1
+
+#define GL_STENCIL_INDEX8_OES 0x8D48
+
+#define GLEW_OES_stencil8 GLEW_GET_VAR(__GLEW_OES_stencil8)
+
+#endif /* !GL_OES_stencil8 */
+
+/* ----------------------- GL_OES_surfaceless_context ---------------------- */
+
+#if !defined(GL_OES_surfaceless_context)
+#define GL_OES_surfaceless_context 1
+
+#define GL_FRAMEBUFFER_UNDEFINED_OES 0x8219
+
+#define GLEW_OES_surfaceless_context GLEW_GET_VAR(__GLEW_OES_surfaceless_context)
+
+#endif /* !GL_OES_surfaceless_context */
+
+/* --------------------------- GL_OES_texture_3D --------------------------- */
+
+#if !defined(GL_OES_texture_3D)
+#define GL_OES_texture_3D 1
+
+#define GL_TEXTURE_BINDING_3D_OES 0x806A
+#define GL_TEXTURE_3D_OES 0x806F
+#define GL_TEXTURE_WRAP_R_OES 0x8072
+#define GL_MAX_3D_TEXTURE_SIZE_OES 0x8073
+#define GL_SAMPLER_3D_OES 0x8B5F
+
+typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXIMAGE3DOESPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void* data);
+typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXSUBIMAGE3DOESPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void* data);
+typedef void (GLAPIENTRY * PFNGLCOPYTEXSUBIMAGE3DOESPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+typedef void (GLAPIENTRY * PFNGLFRAMEBUFFERTEXTURE3DOESPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset);
+typedef void (GLAPIENTRY * PFNGLTEXIMAGE3DOESPROC) (GLenum target, GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void* pixels);
+typedef void (GLAPIENTRY * PFNGLTEXSUBIMAGE3DOESPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void* pixels);
+
+#define glCompressedTexImage3DOES GLEW_GET_FUN(__glewCompressedTexImage3DOES)
+#define glCompressedTexSubImage3DOES GLEW_GET_FUN(__glewCompressedTexSubImage3DOES)
+#define glCopyTexSubImage3DOES GLEW_GET_FUN(__glewCopyTexSubImage3DOES)
+#define glFramebufferTexture3DOES GLEW_GET_FUN(__glewFramebufferTexture3DOES)
+#define glTexImage3DOES GLEW_GET_FUN(__glewTexImage3DOES)
+#define glTexSubImage3DOES GLEW_GET_FUN(__glewTexSubImage3DOES)
+
+#define GLEW_OES_texture_3D GLEW_GET_VAR(__GLEW_OES_texture_3D)
+
+#endif /* !GL_OES_texture_3D */
+
+/* ------------------------ GL_OES_texture_cube_map ------------------------ */
+
+#if !defined(GL_OES_texture_cube_map)
+#define GL_OES_texture_cube_map 1
+
+#define GL_TEXTURE_GEN_MODE_OES 0x2500
+#define GL_NORMAL_MAP_OES 0x8511
+#define GL_REFLECTION_MAP_OES 0x8512
+#define GL_TEXTURE_CUBE_MAP_OES 0x8513
+#define GL_TEXTURE_BINDING_CUBE_MAP_OES 0x8514
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_X_OES 0x8515
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_X_OES 0x8516
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_Y_OES 0x8517
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_OES 0x8518
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z_OES 0x8519
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_OES 0x851A
+#define GL_MAX_CUBE_MAP_TEXTURE_SIZE_OES 0x851C
+#define GL_TEXTURE_GEN_STR_OES 0x8D60
+
+typedef void (GLAPIENTRY * PFNGLGETTEXGENFVOESPROC) (GLenum coord, GLenum pname, GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLGETTEXGENIVOESPROC) (GLenum coord, GLenum pname, GLint* params);
+typedef void (GLAPIENTRY * PFNGLGETTEXGENXVOESPROC) (GLenum coord, GLenum pname, GLfixed* params);
+typedef void (GLAPIENTRY * PFNGLTEXGENFOESPROC) (GLenum coord, GLenum pname, GLfloat param);
+typedef void (GLAPIENTRY * PFNGLTEXGENFVOESPROC) (GLenum coord, GLenum pname, const GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLTEXGENIOESPROC) (GLenum coord, GLenum pname, GLint param);
+typedef void (GLAPIENTRY * PFNGLTEXGENIVOESPROC) (GLenum coord, GLenum pname, const GLint* params);
+typedef void (GLAPIENTRY * PFNGLTEXGENXOESPROC) (GLenum coord, GLenum pname, GLfixed param);
+typedef void (GLAPIENTRY * PFNGLTEXGENXVOESPROC) (GLenum coord, GLenum pname, const GLfixed* params);
+
+#define glGetTexGenfvOES GLEW_GET_FUN(__glewGetTexGenfvOES)
+#define glGetTexGenivOES GLEW_GET_FUN(__glewGetTexGenivOES)
+#define glGetTexGenxvOES GLEW_GET_FUN(__glewGetTexGenxvOES)
+#define glTexGenfOES GLEW_GET_FUN(__glewTexGenfOES)
+#define glTexGenfvOES GLEW_GET_FUN(__glewTexGenfvOES)
+#define glTexGeniOES GLEW_GET_FUN(__glewTexGeniOES)
+#define glTexGenivOES GLEW_GET_FUN(__glewTexGenivOES)
+#define glTexGenxOES GLEW_GET_FUN(__glewTexGenxOES)
+#define glTexGenxvOES GLEW_GET_FUN(__glewTexGenxvOES)
+
+#define GLEW_OES_texture_cube_map GLEW_GET_VAR(__GLEW_OES_texture_cube_map)
+
+#endif /* !GL_OES_texture_cube_map */
+
+/* ---------------------- GL_OES_texture_env_crossbar ---------------------- */
+
+#if !defined(GL_OES_texture_env_crossbar)
+#define GL_OES_texture_env_crossbar 1
+
+#define GLEW_OES_texture_env_crossbar GLEW_GET_VAR(__GLEW_OES_texture_env_crossbar)
+
+#endif /* !GL_OES_texture_env_crossbar */
+
+/* --------------------- GL_OES_texture_mirrored_repeat -------------------- */
+
+#if !defined(GL_OES_texture_mirrored_repeat)
+#define GL_OES_texture_mirrored_repeat 1
+
+#define GL_MIRRORED_REPEAT 0x8370
+
+#define GLEW_OES_texture_mirrored_repeat GLEW_GET_VAR(__GLEW_OES_texture_mirrored_repeat)
+
+#endif /* !GL_OES_texture_mirrored_repeat */
+
+/* -------------------------- GL_OES_texture_npot -------------------------- */
+
+#if !defined(GL_OES_texture_npot)
+#define GL_OES_texture_npot 1
+
+#define GLEW_OES_texture_npot GLEW_GET_VAR(__GLEW_OES_texture_npot)
+
+#endif /* !GL_OES_texture_npot */
+
+/* ----------------------- GL_OES_vertex_array_object ---------------------- */
+
+#if !defined(GL_OES_vertex_array_object)
+#define GL_OES_vertex_array_object 1
+
+#define GL_VERTEX_ARRAY_BINDING_OES 0x85B5
+
+typedef void (GLAPIENTRY * PFNGLBINDVERTEXARRAYOESPROC) (GLuint array);
+typedef void (GLAPIENTRY * PFNGLDELETEVERTEXARRAYSOESPROC) (GLsizei n, const GLuint* arrays);
+typedef void (GLAPIENTRY * PFNGLGENVERTEXARRAYSOESPROC) (GLsizei n, GLuint* arrays);
+typedef GLboolean (GLAPIENTRY * PFNGLISVERTEXARRAYOESPROC) (GLuint array);
+
+#define glBindVertexArrayOES GLEW_GET_FUN(__glewBindVertexArrayOES)
+#define glDeleteVertexArraysOES GLEW_GET_FUN(__glewDeleteVertexArraysOES)
+#define glGenVertexArraysOES GLEW_GET_FUN(__glewGenVertexArraysOES)
+#define glIsVertexArrayOES GLEW_GET_FUN(__glewIsVertexArrayOES)
+
+#define GLEW_OES_vertex_array_object GLEW_GET_VAR(__GLEW_OES_vertex_array_object)
+
+#endif /* !GL_OES_vertex_array_object */
+
+/* ------------------------ GL_OES_vertex_half_float ----------------------- */
+
+#if !defined(GL_OES_vertex_half_float)
+#define GL_OES_vertex_half_float 1
+
+#define GL_HALF_FLOAT_OES 0x8D61
+
+#define GLEW_OES_vertex_half_float GLEW_GET_VAR(__GLEW_OES_vertex_half_float)
+
+#endif /* !GL_OES_vertex_half_float */
+
+/* --------------------- GL_OES_vertex_type_10_10_10_2 --------------------- */
+
+#if !defined(GL_OES_vertex_type_10_10_10_2)
+#define GL_OES_vertex_type_10_10_10_2 1
+
+#define GL_UNSIGNED_INT_10_10_10_2_OES 0x8DF6
+#define GL_INT_10_10_10_2_OES 0x8DF7
+
+#define GLEW_OES_vertex_type_10_10_10_2 GLEW_GET_VAR(__GLEW_OES_vertex_type_10_10_10_2)
+
+#endif /* !GL_OES_vertex_type_10_10_10_2 */
+
+/* --------------------------- GL_QCOM_alpha_test -------------------------- */
+
+#if !defined(GL_QCOM_alpha_test)
+#define GL_QCOM_alpha_test 1
+
+#define GL_ALPHA_TEST_QCOM 0x0BC0
+#define GL_ALPHA_TEST_FUNC_QCOM 0x0BC1
+#define GL_ALPHA_TEST_REF_QCOM 0x0BC2
+
+typedef void (GLAPIENTRY * PFNGLALPHAFUNCQCOMPROC) (GLenum func, GLclampf ref);
+
+#define glAlphaFuncQCOM GLEW_GET_FUN(__glewAlphaFuncQCOM)
+
+#define GLEW_QCOM_alpha_test GLEW_GET_VAR(__GLEW_QCOM_alpha_test)
+
+#endif /* !GL_QCOM_alpha_test */
+
+/* ------------------------ GL_QCOM_binning_control ------------------------ */
+
+#if !defined(GL_QCOM_binning_control)
+#define GL_QCOM_binning_control 1
+
+#define GL_DONT_CARE 0x1100
+#define GL_BINNING_CONTROL_HINT_QCOM 0x8FB0
+#define GL_CPU_OPTIMIZED_QCOM 0x8FB1
+#define GL_GPU_OPTIMIZED_QCOM 0x8FB2
+#define GL_RENDER_DIRECT_TO_FRAMEBUFFER_QCOM 0x8FB3
+
+#define GLEW_QCOM_binning_control GLEW_GET_VAR(__GLEW_QCOM_binning_control)
+
+#endif /* !GL_QCOM_binning_control */
+
+/* ------------------------- GL_QCOM_driver_control ------------------------ */
+
+#if !defined(GL_QCOM_driver_control)
+#define GL_QCOM_driver_control 1
+
+typedef void (GLAPIENTRY * PFNGLDISABLEDRIVERCONTROLQCOMPROC) (GLuint driverControl);
+typedef void (GLAPIENTRY * PFNGLENABLEDRIVERCONTROLQCOMPROC) (GLuint driverControl);
+typedef void (GLAPIENTRY * PFNGLGETDRIVERCONTROLSTRINGQCOMPROC) (GLuint driverControl, GLsizei bufSize, GLsizei* length, char *driverControlString);
+typedef void (GLAPIENTRY * PFNGLGETDRIVERCONTROLSQCOMPROC) (GLint* num, GLsizei size, GLuint *driverControls);
+
+#define glDisableDriverControlQCOM GLEW_GET_FUN(__glewDisableDriverControlQCOM)
+#define glEnableDriverControlQCOM GLEW_GET_FUN(__glewEnableDriverControlQCOM)
+#define glGetDriverControlStringQCOM GLEW_GET_FUN(__glewGetDriverControlStringQCOM)
+#define glGetDriverControlsQCOM GLEW_GET_FUN(__glewGetDriverControlsQCOM)
+
+#define GLEW_QCOM_driver_control GLEW_GET_VAR(__GLEW_QCOM_driver_control)
+
+#endif /* !GL_QCOM_driver_control */
+
+/* -------------------------- GL_QCOM_extended_get ------------------------- */
+
+#if !defined(GL_QCOM_extended_get)
+#define GL_QCOM_extended_get 1
+
+#define GL_TEXTURE_WIDTH_QCOM 0x8BD2
+#define GL_TEXTURE_HEIGHT_QCOM 0x8BD3
+#define GL_TEXTURE_DEPTH_QCOM 0x8BD4
+#define GL_TEXTURE_INTERNAL_FORMAT_QCOM 0x8BD5
+#define GL_TEXTURE_FORMAT_QCOM 0x8BD6
+#define GL_TEXTURE_TYPE_QCOM 0x8BD7
+#define GL_TEXTURE_IMAGE_VALID_QCOM 0x8BD8
+#define GL_TEXTURE_NUM_LEVELS_QCOM 0x8BD9
+#define GL_TEXTURE_TARGET_QCOM 0x8BDA
+#define GL_TEXTURE_OBJECT_VALID_QCOM 0x8BDB
+#define GL_STATE_RESTORE 0x8BDC
+
+typedef void (GLAPIENTRY * PFNGLEXTGETBUFFERPOINTERVQCOMPROC) (GLenum target, GLvoid** params);
+typedef void (GLAPIENTRY * PFNGLEXTGETBUFFERSQCOMPROC) (GLuint* buffers, GLint maxBuffers, GLint* numBuffers);
+typedef void (GLAPIENTRY * PFNGLEXTGETFRAMEBUFFERSQCOMPROC) (GLuint* framebuffers, GLint maxFramebuffers, GLint* numFramebuffers);
+typedef void (GLAPIENTRY * PFNGLEXTGETRENDERBUFFERSQCOMPROC) (GLuint* renderbuffers, GLint maxRenderbuffers, GLint* numRenderbuffers);
+typedef void (GLAPIENTRY * PFNGLEXTGETTEXLEVELPARAMETERIVQCOMPROC) (GLuint texture, GLenum face, GLint level, GLenum pname, GLint* params);
+typedef void (GLAPIENTRY * PFNGLEXTGETTEXSUBIMAGEQCOMPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, void* texels);
+typedef void (GLAPIENTRY * PFNGLEXTGETTEXTURESQCOMPROC) (GLuint* textures, GLint maxTextures, GLint* numTextures);
+typedef void (GLAPIENTRY * PFNGLEXTTEXOBJECTSTATEOVERRIDEIQCOMPROC) (GLenum target, GLenum pname, GLint param);
+
+#define glExtGetBufferPointervQCOM GLEW_GET_FUN(__glewExtGetBufferPointervQCOM)
+#define glExtGetBuffersQCOM GLEW_GET_FUN(__glewExtGetBuffersQCOM)
+#define glExtGetFramebuffersQCOM GLEW_GET_FUN(__glewExtGetFramebuffersQCOM)
+#define glExtGetRenderbuffersQCOM GLEW_GET_FUN(__glewExtGetRenderbuffersQCOM)
+#define glExtGetTexLevelParameterivQCOM GLEW_GET_FUN(__glewExtGetTexLevelParameterivQCOM)
+#define glExtGetTexSubImageQCOM GLEW_GET_FUN(__glewExtGetTexSubImageQCOM)
+#define glExtGetTexturesQCOM GLEW_GET_FUN(__glewExtGetTexturesQCOM)
+#define glExtTexObjectStateOverrideiQCOM GLEW_GET_FUN(__glewExtTexObjectStateOverrideiQCOM)
+
+#define GLEW_QCOM_extended_get GLEW_GET_VAR(__GLEW_QCOM_extended_get)
+
+#endif /* !GL_QCOM_extended_get */
+
+/* ------------------------- GL_QCOM_extended_get2 ------------------------- */
+
+#if !defined(GL_QCOM_extended_get2)
+#define GL_QCOM_extended_get2 1
+
+typedef void (GLAPIENTRY * PFNGLEXTGETPROGRAMBINARYSOURCEQCOMPROC) (GLuint program, GLenum shadertype, char* source, GLint* length);
+typedef void (GLAPIENTRY * PFNGLEXTGETPROGRAMSQCOMPROC) (GLuint* programs, GLint maxPrograms, GLint* numPrograms);
+typedef void (GLAPIENTRY * PFNGLEXTGETSHADERSQCOMPROC) (GLuint* shaders, GLint maxShaders, GLint* numShaders);
+typedef GLboolean (GLAPIENTRY * PFNGLEXTISPROGRAMBINARYQCOMPROC) (GLuint program);
+
+#define glExtGetProgramBinarySourceQCOM GLEW_GET_FUN(__glewExtGetProgramBinarySourceQCOM)
+#define glExtGetProgramsQCOM GLEW_GET_FUN(__glewExtGetProgramsQCOM)
+#define glExtGetShadersQCOM GLEW_GET_FUN(__glewExtGetShadersQCOM)
+#define glExtIsProgramBinaryQCOM GLEW_GET_FUN(__glewExtIsProgramBinaryQCOM)
+
+#define GLEW_QCOM_extended_get2 GLEW_GET_VAR(__GLEW_QCOM_extended_get2)
+
+#endif /* !GL_QCOM_extended_get2 */
+
+/* ---------------------- GL_QCOM_perfmon_global_mode ---------------------- */
+
+#if !defined(GL_QCOM_perfmon_global_mode)
+#define GL_QCOM_perfmon_global_mode 1
+
+#define GL_PERFMON_GLOBAL_MODE_QCOM 0x8FA0
+
+#define GLEW_QCOM_perfmon_global_mode GLEW_GET_VAR(__GLEW_QCOM_perfmon_global_mode)
+
+#endif /* !GL_QCOM_perfmon_global_mode */
+
+/* ------------------------ GL_QCOM_tiled_rendering ------------------------ */
+
+#if !defined(GL_QCOM_tiled_rendering)
+#define GL_QCOM_tiled_rendering 1
+
+#define GL_COLOR_BUFFER_BIT0_QCOM 0x00000001
+#define GL_COLOR_BUFFER_BIT1_QCOM 0x00000002
+#define GL_COLOR_BUFFER_BIT2_QCOM 0x00000004
+#define GL_COLOR_BUFFER_BIT3_QCOM 0x00000008
+#define GL_COLOR_BUFFER_BIT4_QCOM 0x00000010
+#define GL_COLOR_BUFFER_BIT5_QCOM 0x00000020
+#define GL_COLOR_BUFFER_BIT6_QCOM 0x00000040
+#define GL_COLOR_BUFFER_BIT7_QCOM 0x00000080
+#define GL_DEPTH_BUFFER_BIT0_QCOM 0x00000100
+#define GL_DEPTH_BUFFER_BIT1_QCOM 0x00000200
+#define GL_DEPTH_BUFFER_BIT2_QCOM 0x00000400
+#define GL_DEPTH_BUFFER_BIT3_QCOM 0x00000800
+#define GL_DEPTH_BUFFER_BIT4_QCOM 0x00001000
+#define GL_DEPTH_BUFFER_BIT5_QCOM 0x00002000
+#define GL_DEPTH_BUFFER_BIT6_QCOM 0x00004000
+#define GL_DEPTH_BUFFER_BIT7_QCOM 0x00008000
+#define GL_STENCIL_BUFFER_BIT0_QCOM 0x00010000
+#define GL_STENCIL_BUFFER_BIT1_QCOM 0x00020000
+#define GL_STENCIL_BUFFER_BIT2_QCOM 0x00040000
+#define GL_STENCIL_BUFFER_BIT3_QCOM 0x00080000
+#define GL_STENCIL_BUFFER_BIT4_QCOM 0x00100000
+#define GL_STENCIL_BUFFER_BIT5_QCOM 0x00200000
+#define GL_STENCIL_BUFFER_BIT6_QCOM 0x00400000
+#define GL_STENCIL_BUFFER_BIT7_QCOM 0x00800000
+#define GL_MULTISAMPLE_BUFFER_BIT0_QCOM 0x01000000
+#define GL_MULTISAMPLE_BUFFER_BIT1_QCOM 0x02000000
+#define GL_MULTISAMPLE_BUFFER_BIT2_QCOM 0x04000000
+#define GL_MULTISAMPLE_BUFFER_BIT3_QCOM 0x08000000
+#define GL_MULTISAMPLE_BUFFER_BIT4_QCOM 0x10000000
+#define GL_MULTISAMPLE_BUFFER_BIT5_QCOM 0x20000000
+#define GL_MULTISAMPLE_BUFFER_BIT6_QCOM 0x40000000
+#define GL_MULTISAMPLE_BUFFER_BIT7_QCOM 0x80000000
+
+typedef void (GLAPIENTRY * PFNGLENDTILINGQCOMPROC) (GLbitfield preserveMask);
+typedef void (GLAPIENTRY * PFNGLSTARTTILINGQCOMPROC) (GLuint x, GLuint y, GLuint width, GLuint height, GLbitfield preserveMask);
+
+#define glEndTilingQCOM GLEW_GET_FUN(__glewEndTilingQCOM)
+#define glStartTilingQCOM GLEW_GET_FUN(__glewStartTilingQCOM)
+
+#define GLEW_QCOM_tiled_rendering GLEW_GET_VAR(__GLEW_QCOM_tiled_rendering)
+
+#endif /* !GL_QCOM_tiled_rendering */
+
+/* ---------------------- GL_QCOM_writeonly_rendering ---------------------- */
+
+#if !defined(GL_QCOM_writeonly_rendering)
+#define GL_QCOM_writeonly_rendering 1
+
+#define GL_WRITEONLY_RENDERING_QCOM 0x8823
+
+#define GLEW_QCOM_writeonly_rendering GLEW_GET_VAR(__GLEW_QCOM_writeonly_rendering)
+
+#endif /* !GL_QCOM_writeonly_rendering */
+
+/* ------------------------ GL_SUN_multi_draw_arrays ----------------------- */
+
+#if !defined(GL_SUN_multi_draw_arrays)
+#define GL_SUN_multi_draw_arrays 1
+
+typedef void (GLAPIENTRY * PFNGLMULTIDRAWARRAYSSUNPROC) (GLenum mode, const GLint* first, const GLsizei *count, GLsizei primcount);
+typedef void (GLAPIENTRY * PFNGLMULTIDRAWELEMENTSSUNPROC) (GLenum mode, GLsizei* count, GLenum type, const GLvoid **indices, GLsizei primcount);
+
+#define glMultiDrawArraysSUN GLEW_GET_FUN(__glewMultiDrawArraysSUN)
+#define glMultiDrawElementsSUN GLEW_GET_FUN(__glewMultiDrawElementsSUN)
+
+#define GLEW_SUN_multi_draw_arrays GLEW_GET_VAR(__GLEW_SUN_multi_draw_arrays)
+
+#endif /* !GL_SUN_multi_draw_arrays */
+
+/* --------------------------- GL_VG_KHR_EGL_sync -------------------------- */
+
+#if !defined(GL_VG_KHR_EGL_sync)
+#define GL_VG_KHR_EGL_sync 1
+
+#define GLEW_VG_KHR_EGL_sync GLEW_GET_VAR(__GLEW_VG_KHR_EGL_sync)
+
+#endif /* !GL_VG_KHR_EGL_sync */
+
+/* -------------------------- GL_VIV_shader_binary ------------------------- */
+
+#if !defined(GL_VIV_shader_binary)
+#define GL_VIV_shader_binary 1
+
+#define GL_SHADER_BINARY_VIV 0x8FC4
+
+#define GLEW_VIV_shader_binary GLEW_GET_VAR(__GLEW_VIV_shader_binary)
+
+#endif /* !GL_VIV_shader_binary */
+
+/* ------------------------------------------------------------------------- */
+
+#if defined(GLEW_MX) && defined(_WIN32)
+#define GLEW_FUN_EXPORT
+#else
+#define GLEW_FUN_EXPORT GLEWAPI
+#endif /* GLEW_MX */
+
+#if defined(GLEW_MX)
+#define GLEW_VAR_EXPORT
+#else
+#define GLEW_VAR_EXPORT GLEWAPI
+#endif /* GLEW_MX */
+
+#if defined(GLEW_MX) && defined(_WIN32)
+struct GLEWContextStruct
+{
+#endif /* GLEW_MX */
+
+#if GL_ES_VERSION_1_0 // NOTE jwilkins: glew doesn't actually seem to be designed to let you use the extension macros
+GLEW_FUN_EXPORT PFNGLACTIVETEXTUREPROC __glewActiveTexture;
+GLEW_FUN_EXPORT PFNGLALPHAFUNCXPROC __glewAlphaFuncx;
+GLEW_FUN_EXPORT PFNGLCLEARCOLORXPROC __glewClearColorx;
+GLEW_FUN_EXPORT PFNGLCLEARDEPTHFPROC __glewClearDepthf;
+GLEW_FUN_EXPORT PFNGLCLEARDEPTHXPROC __glewClearDepthx;
+GLEW_FUN_EXPORT PFNGLCLIENTACTIVETEXTUREPROC __glewClientActiveTexture;
+GLEW_FUN_EXPORT PFNGLCOLOR4XPROC __glewColor4x;
+GLEW_FUN_EXPORT PFNGLCOMPRESSEDTEXIMAGE2DPROC __glewCompressedTexImage2D;
+GLEW_FUN_EXPORT PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC __glewCompressedTexSubImage2D;
+GLEW_FUN_EXPORT PFNGLDEPTHRANGEFPROC __glewDepthRangef;
+GLEW_FUN_EXPORT PFNGLDEPTHRANGEXPROC __glewDepthRangex;
+GLEW_FUN_EXPORT PFNGLFOGXPROC __glewFogx;
+GLEW_FUN_EXPORT PFNGLFOGXVPROC __glewFogxv;
+GLEW_FUN_EXPORT PFNGLFRUSTUMFPROC __glewFrustumf;
+GLEW_FUN_EXPORT PFNGLFRUSTUMXPROC __glewFrustumx;
+GLEW_FUN_EXPORT PFNGLLIGHTMODELXPROC __glewLightModelx;
+GLEW_FUN_EXPORT PFNGLLIGHTMODELXVPROC __glewLightModelxv;
+GLEW_FUN_EXPORT PFNGLLIGHTXPROC __glewLightx;
+GLEW_FUN_EXPORT PFNGLLIGHTXVPROC __glewLightxv;
+GLEW_FUN_EXPORT PFNGLLINEWIDTHXPROC __glewLineWidthx;
+GLEW_FUN_EXPORT PFNGLLOADMATRIXXPROC __glewLoadMatrixx;
+GLEW_FUN_EXPORT PFNGLMATERIALXPROC __glewMaterialx;
+GLEW_FUN_EXPORT PFNGLMATERIALXVPROC __glewMaterialxv;
+GLEW_FUN_EXPORT PFNGLMULTMATRIXXPROC __glewMultMatrixx;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD4FPROC __glewMultiTexCoord4f;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD4XPROC __glewMultiTexCoord4x;
+GLEW_FUN_EXPORT PFNGLNORMAL3XPROC __glewNormal3x;
+GLEW_FUN_EXPORT PFNGLORTHOFPROC __glewOrthof;
+GLEW_FUN_EXPORT PFNGLORTHOXPROC __glewOrthox;
+GLEW_FUN_EXPORT PFNGLPOINTSIZEXPROC __glewPointSizex;
+GLEW_FUN_EXPORT PFNGLPOLYGONOFFSETXPROC __glewPolygonOffsetx;
+GLEW_FUN_EXPORT PFNGLROTATEXPROC __glewRotatex;
+GLEW_FUN_EXPORT PFNGLSAMPLECOVERAGEPROC __glewSampleCoverage;
+GLEW_FUN_EXPORT PFNGLSAMPLECOVERAGEXPROC __glewSampleCoveragex;
+GLEW_FUN_EXPORT PFNGLSCALEXPROC __glewScalex;
+GLEW_FUN_EXPORT PFNGLTEXENVXPROC __glewTexEnvx;
+GLEW_FUN_EXPORT PFNGLTEXENVXVPROC __glewTexEnvxv;
+GLEW_FUN_EXPORT PFNGLTEXPARAMETERXPROC __glewTexParameterx;
+GLEW_FUN_EXPORT PFNGLTRANSLATEXPROC __glewTranslatex;
+#endif // NOTE jwilkins
+
+#if GL_ES_VERSION_CL_1_1 // NOTE jwilkins
+GLEW_FUN_EXPORT PFNGLBINDBUFFERPROC __glewBindBuffer;
+GLEW_FUN_EXPORT PFNGLBUFFERDATAPROC __glewBufferData;
+GLEW_FUN_EXPORT PFNGLBUFFERSUBDATAPROC __glewBufferSubData;
+GLEW_FUN_EXPORT PFNGLCLIPPLANEXPROC __glewClipPlanex;
+GLEW_FUN_EXPORT PFNGLCOLOR4UBPROC __glewColor4ub;
+GLEW_FUN_EXPORT PFNGLDELETEBUFFERSPROC __glewDeleteBuffers;
+GLEW_FUN_EXPORT PFNGLGENBUFFERSPROC __glewGenBuffers;
+GLEW_FUN_EXPORT PFNGLGETBOOLEANVPROC __glewGetBooleanv;
+GLEW_FUN_EXPORT PFNGLGETBUFFERPARAMETERIVPROC __glewGetBufferParameteriv;
+GLEW_FUN_EXPORT PFNGLGETCLIPPLANEXPROC __glewGetClipPlanex;
+GLEW_FUN_EXPORT PFNGLGETFIXEDVPROC __glewGetFixedv;
+GLEW_FUN_EXPORT PFNGLGETLIGHTXVPROC __glewGetLightxv;
+GLEW_FUN_EXPORT PFNGLGETMATERIALXVPROC __glewGetMaterialxv;
+GLEW_FUN_EXPORT PFNGLGETPOINTERVPROC __glewGetPointerv;
+GLEW_FUN_EXPORT PFNGLGETTEXENVIVPROC __glewGetTexEnviv;
+GLEW_FUN_EXPORT PFNGLGETTEXENVXVPROC __glewGetTexEnvxv;
+GLEW_FUN_EXPORT PFNGLGETTEXPARAMETERIVPROC __glewGetTexParameteriv;
+GLEW_FUN_EXPORT PFNGLGETTEXPARAMETERXVPROC __glewGetTexParameterxv;
+GLEW_FUN_EXPORT PFNGLISBUFFERPROC __glewIsBuffer;
+GLEW_FUN_EXPORT PFNGLISENABLEDPROC __glewIsEnabled;
+GLEW_FUN_EXPORT PFNGLISTEXTUREPROC __glewIsTexture;
+GLEW_FUN_EXPORT PFNGLPOINTPARAMETERXPROC __glewPointParameterx;
+GLEW_FUN_EXPORT PFNGLPOINTPARAMETERXVPROC __glewPointParameterxv;
+GLEW_FUN_EXPORT PFNGLTEXENVIPROC __glewTexEnvi;
+GLEW_FUN_EXPORT PFNGLTEXENVIVPROC __glewTexEnviv;
+GLEW_FUN_EXPORT PFNGLTEXPARAMETERIPROC __glewTexParameteri;
+GLEW_FUN_EXPORT PFNGLTEXPARAMETERIVPROC __glewTexParameteriv;
+GLEW_FUN_EXPORT PFNGLTEXPARAMETERXVPROC __glewTexParameterxv;
+#endif // NOTE jwilkins
+
+#if GL_ES_VERSION_CM_1_1 // XXX
+GLEW_FUN_EXPORT PFNGLCLIPPLANEFPROC __glewClipPlanef;
+GLEW_FUN_EXPORT PFNGLGETCLIPPLANEFPROC __glewGetClipPlanef;
+GLEW_FUN_EXPORT PFNGLGETFLOATVPROC __glewGetFloatv;
+GLEW_FUN_EXPORT PFNGLGETLIGHTFVPROC __glewGetLightfv;
+GLEW_FUN_EXPORT PFNGLGETMATERIALFVPROC __glewGetMaterialfv;
+GLEW_FUN_EXPORT PFNGLGETTEXENVFVPROC __glewGetTexEnvfv;
+GLEW_FUN_EXPORT PFNGLGETTEXPARAMETERFVPROC __glewGetTexParameterfv;
+GLEW_FUN_EXPORT PFNGLPOINTPARAMETERFPROC __glewPointParameterf;
+GLEW_FUN_EXPORT PFNGLPOINTPARAMETERFVPROC __glewPointParameterfv;
+GLEW_FUN_EXPORT PFNGLTEXPARAMETERFVPROC __glewTexParameterfv;
+#endif // NOTE jwilkins
+
+GLEW_FUN_EXPORT PFNGLATTACHSHADERPROC __glewAttachShader;
+GLEW_FUN_EXPORT PFNGLBINDATTRIBLOCATIONPROC __glewBindAttribLocation;
+GLEW_FUN_EXPORT PFNGLBINDFRAMEBUFFERPROC __glewBindFramebuffer;
+GLEW_FUN_EXPORT PFNGLBINDRENDERBUFFERPROC __glewBindRenderbuffer;
+GLEW_FUN_EXPORT PFNGLBLENDCOLORPROC __glewBlendColor;
+GLEW_FUN_EXPORT PFNGLBLENDEQUATIONPROC __glewBlendEquation;
+GLEW_FUN_EXPORT PFNGLBLENDEQUATIONSEPARATEPROC __glewBlendEquationSeparate;
+GLEW_FUN_EXPORT PFNGLBLENDFUNCSEPARATEPROC __glewBlendFuncSeparate;
+GLEW_FUN_EXPORT PFNGLCHECKFRAMEBUFFERSTATUSPROC __glewCheckFramebufferStatus;
+GLEW_FUN_EXPORT PFNGLCOMPILESHADERPROC __glewCompileShader;
+GLEW_FUN_EXPORT PFNGLCREATEPROGRAMPROC __glewCreateProgram;
+GLEW_FUN_EXPORT PFNGLCREATESHADERPROC __glewCreateShader;
+GLEW_FUN_EXPORT PFNGLDELETEFRAMEBUFFERSPROC __glewDeleteFramebuffers;
+GLEW_FUN_EXPORT PFNGLDELETEPROGRAMPROC __glewDeleteProgram;
+GLEW_FUN_EXPORT PFNGLDELETERENDERBUFFERSPROC __glewDeleteRenderbuffers;
+GLEW_FUN_EXPORT PFNGLDELETESHADERPROC __glewDeleteShader;
+GLEW_FUN_EXPORT PFNGLDETACHSHADERPROC __glewDetachShader;
+GLEW_FUN_EXPORT PFNGLDISABLEVERTEXATTRIBARRAYPROC __glewDisableVertexAttribArray;
+GLEW_FUN_EXPORT PFNGLENABLEVERTEXATTRIBARRAYPROC __glewEnableVertexAttribArray;
+GLEW_FUN_EXPORT PFNGLFRAMEBUFFERRENDERBUFFERPROC __glewFramebufferRenderbuffer;
+GLEW_FUN_EXPORT PFNGLFRAMEBUFFERTEXTURE2DPROC __glewFramebufferTexture2D;
+GLEW_FUN_EXPORT PFNGLGENFRAMEBUFFERSPROC __glewGenFramebuffers;
+GLEW_FUN_EXPORT PFNGLGENRENDERBUFFERSPROC __glewGenRenderbuffers;
+GLEW_FUN_EXPORT PFNGLGENERATEMIPMAPPROC __glewGenerateMipmap;
+GLEW_FUN_EXPORT PFNGLGETACTIVEATTRIBPROC __glewGetActiveAttrib;
+GLEW_FUN_EXPORT PFNGLGETACTIVEUNIFORMPROC __glewGetActiveUniform;
+GLEW_FUN_EXPORT PFNGLGETATTACHEDSHADERSPROC __glewGetAttachedShaders;
+GLEW_FUN_EXPORT PFNGLGETATTRIBLOCATIONPROC __glewGetAttribLocation;
+GLEW_FUN_EXPORT PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC __glewGetFramebufferAttachmentParameteriv;
+GLEW_FUN_EXPORT PFNGLGETPROGRAMINFOLOGPROC __glewGetProgramInfoLog;
+GLEW_FUN_EXPORT PFNGLGETPROGRAMIVPROC __glewGetProgramiv;
+GLEW_FUN_EXPORT PFNGLGETRENDERBUFFERPARAMETERIVPROC __glewGetRenderbufferParameteriv;
+GLEW_FUN_EXPORT PFNGLGETSHADERINFOLOGPROC __glewGetShaderInfoLog;
+GLEW_FUN_EXPORT PFNGLGETSHADERPRECISIONFORMATPROC __glewGetShaderPrecisionFormat;
+GLEW_FUN_EXPORT PFNGLGETSHADERSOURCEPROC __glewGetShaderSource;
+GLEW_FUN_EXPORT PFNGLGETSHADERIVPROC __glewGetShaderiv;
+GLEW_FUN_EXPORT PFNGLGETUNIFORMLOCATIONPROC __glewGetUniformLocation;
+GLEW_FUN_EXPORT PFNGLGETUNIFORMFVPROC __glewGetUniformfv;
+GLEW_FUN_EXPORT PFNGLGETUNIFORMIVPROC __glewGetUniformiv;
+GLEW_FUN_EXPORT PFNGLGETVERTEXATTRIBPOINTERVPROC __glewGetVertexAttribPointerv;
+GLEW_FUN_EXPORT PFNGLGETVERTEXATTRIBFVPROC __glewGetVertexAttribfv;
+GLEW_FUN_EXPORT PFNGLGETVERTEXATTRIBIVPROC __glewGetVertexAttribiv;
+GLEW_FUN_EXPORT PFNGLISFRAMEBUFFERPROC __glewIsFramebuffer;
+GLEW_FUN_EXPORT PFNGLISPROGRAMPROC __glewIsProgram;
+GLEW_FUN_EXPORT PFNGLISRENDERBUFFERPROC __glewIsRenderbuffer;
+GLEW_FUN_EXPORT PFNGLISSHADERPROC __glewIsShader;
+GLEW_FUN_EXPORT PFNGLLINKPROGRAMPROC __glewLinkProgram;
+GLEW_FUN_EXPORT PFNGLRELEASESHADERCOMPILERPROC __glewReleaseShaderCompiler;
+GLEW_FUN_EXPORT PFNGLRENDERBUFFERSTORAGEPROC __glewRenderbufferStorage;
+GLEW_FUN_EXPORT PFNGLSHADERBINARYPROC __glewShaderBinary;
+GLEW_FUN_EXPORT PFNGLSHADERSOURCEPROC __glewShaderSource;
+GLEW_FUN_EXPORT PFNGLSTENCILFUNCSEPARATEPROC __glewStencilFuncSeparate;
+GLEW_FUN_EXPORT PFNGLSTENCILMASKSEPARATEPROC __glewStencilMaskSeparate;
+GLEW_FUN_EXPORT PFNGLSTENCILOPSEPARATEPROC __glewStencilOpSeparate;
+GLEW_FUN_EXPORT PFNGLUNIFORM1FPROC __glewUniform1f;
+GLEW_FUN_EXPORT PFNGLUNIFORM1FVPROC __glewUniform1fv;
+GLEW_FUN_EXPORT PFNGLUNIFORM1IPROC __glewUniform1i;
+GLEW_FUN_EXPORT PFNGLUNIFORM1IVPROC __glewUniform1iv;
+GLEW_FUN_EXPORT PFNGLUNIFORM2FPROC __glewUniform2f;
+GLEW_FUN_EXPORT PFNGLUNIFORM2FVPROC __glewUniform2fv;
+GLEW_FUN_EXPORT PFNGLUNIFORM2IPROC __glewUniform2i;
+GLEW_FUN_EXPORT PFNGLUNIFORM2IVPROC __glewUniform2iv;
+GLEW_FUN_EXPORT PFNGLUNIFORM3FPROC __glewUniform3f;
+GLEW_FUN_EXPORT PFNGLUNIFORM3FVPROC __glewUniform3fv;
+GLEW_FUN_EXPORT PFNGLUNIFORM3IPROC __glewUniform3i;
+GLEW_FUN_EXPORT PFNGLUNIFORM3IVPROC __glewUniform3iv;
+GLEW_FUN_EXPORT PFNGLUNIFORM4FPROC __glewUniform4f;
+GLEW_FUN_EXPORT PFNGLUNIFORM4FVPROC __glewUniform4fv;
+GLEW_FUN_EXPORT PFNGLUNIFORM4IPROC __glewUniform4i;
+GLEW_FUN_EXPORT PFNGLUNIFORM4IVPROC __glewUniform4iv;
+GLEW_FUN_EXPORT PFNGLUNIFORMMATRIX2FVPROC __glewUniformMatrix2fv;
+GLEW_FUN_EXPORT PFNGLUNIFORMMATRIX3FVPROC __glewUniformMatrix3fv;
+GLEW_FUN_EXPORT PFNGLUNIFORMMATRIX4FVPROC __glewUniformMatrix4fv;
+GLEW_FUN_EXPORT PFNGLUSEPROGRAMPROC __glewUseProgram;
+GLEW_FUN_EXPORT PFNGLVALIDATEPROGRAMPROC __glewValidateProgram;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB1FPROC __glewVertexAttrib1f;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB1FVPROC __glewVertexAttrib1fv;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB2FPROC __glewVertexAttrib2f;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB2FVPROC __glewVertexAttrib2fv;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB3FPROC __glewVertexAttrib3f;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB3FVPROC __glewVertexAttrib3fv;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4FPROC __glewVertexAttrib4f;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4FVPROC __glewVertexAttrib4fv;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBPOINTERPROC __glewVertexAttribPointer;
+
+#if !GL_ES_VERSION_CL_1_1 // NOTE jwilkins
+GLEW_FUN_EXPORT PFNGLBINDBUFFERPROC __glewBindBuffer; // NOTE jwilkins: missing function
+GLEW_FUN_EXPORT PFNGLBUFFERDATAPROC __glewBufferData; // NOTE jwilkins: missing function
+GLEW_FUN_EXPORT PFNGLBUFFERSUBDATAPROC __glewBufferSubData; // NOTE jwilkins: missing function
+GLEW_FUN_EXPORT PFNGLDELETEBUFFERSPROC __glewDeleteBuffers; // NOTE jwilkins: missing function
+GLEW_FUN_EXPORT PFNGLGENBUFFERSPROC __glewGenBuffers; // NOTE jwilkins: missing function
+GLEW_FUN_EXPORT PFNGLTEXPARAMETERIPROC __glewTexParameteri; // NOTE jwilkins: missing function
+GLEW_FUN_EXPORT PFNGLISENABLEDPROC __glewIsEnabled; // NOTE jwilkins: missing function
+GLEW_FUN_EXPORT PFNGLGETFLOATVPROC __glewGetFloatv; // NOTE jwilkins: missing function
+GLEW_FUN_EXPORT PFNGLDEPTHRANGEFPROC __glewDepthRangef; // NOTE jwilkins: missing function
+GLEW_FUN_EXPORT PFNGLACTIVETEXTUREPROC __glewActiveTexture; // NOTE jwilkins: missing function
+GLEW_FUN_EXPORT PFNGLGETBOOLEANVPROC __glewGetBooleanv; // NOTE jwilkins: missing function
+#endif // XXX
+
+GLEW_FUN_EXPORT PFNGLBEGINPERFMONITORAMDPROC __glewBeginPerfMonitorAMD;
+GLEW_FUN_EXPORT PFNGLDELETEPERFMONITORSAMDPROC __glewDeletePerfMonitorsAMD;
+GLEW_FUN_EXPORT PFNGLENDPERFMONITORAMDPROC __glewEndPerfMonitorAMD;
+GLEW_FUN_EXPORT PFNGLGENPERFMONITORSAMDPROC __glewGenPerfMonitorsAMD;
+GLEW_FUN_EXPORT PFNGLGETPERFMONITORCOUNTERDATAAMDPROC __glewGetPerfMonitorCounterDataAMD;
+GLEW_FUN_EXPORT PFNGLGETPERFMONITORCOUNTERINFOAMDPROC __glewGetPerfMonitorCounterInfoAMD;
+GLEW_FUN_EXPORT PFNGLGETPERFMONITORCOUNTERSTRINGAMDPROC __glewGetPerfMonitorCounterStringAMD;
+GLEW_FUN_EXPORT PFNGLGETPERFMONITORCOUNTERSAMDPROC __glewGetPerfMonitorCountersAMD;
+GLEW_FUN_EXPORT PFNGLGETPERFMONITORGROUPSTRINGAMDPROC __glewGetPerfMonitorGroupStringAMD;
+GLEW_FUN_EXPORT PFNGLGETPERFMONITORGROUPSAMDPROC __glewGetPerfMonitorGroupsAMD;
+GLEW_FUN_EXPORT PFNGLSELECTPERFMONITORCOUNTERSAMDPROC __glewSelectPerfMonitorCountersAMD;
+
+GLEW_FUN_EXPORT PFNGLBLITFRAMEBUFFERANGLEPROC __glewBlitFramebufferANGLE;
+
+GLEW_FUN_EXPORT PFNGLRENDERBUFFERSTORAGEMULTISAMPLEANGLEPROC __glewRenderbufferStorageMultisampleANGLE;
+
+GLEW_FUN_EXPORT PFNGLDRAWARRAYSINSTANCEDANGLEPROC __glewDrawArraysInstancedANGLE;
+GLEW_FUN_EXPORT PFNGLDRAWELEMENTSINSTANCEDANGLEPROC __glewDrawElementsInstancedANGLE;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBDIVISORANGLEPROC __glewVertexAttribDivisorANGLE;
+
+GLEW_FUN_EXPORT PFNGLGETTRANSLATEDSHADERSOURCEANGLEPROC __glewGetTranslatedShaderSourceANGLE;
+
+GLEW_FUN_EXPORT PFNGLCOPYTEXTURELEVELSAPPLEPROC __glewCopyTextureLevelsAPPLE;
+
+GLEW_FUN_EXPORT PFNGLRENDERBUFFERSTORAGEMULTISAMPLEAPPLEPROC __glewRenderbufferStorageMultisampleAPPLE;
+GLEW_FUN_EXPORT PFNGLRESOLVEMULTISAMPLEFRAMEBUFFERAPPLEPROC __glewResolveMultisampleFramebufferAPPLE;
+
+GLEW_FUN_EXPORT PFNGLCLIENTWAITSYNCAPPLEPROC __glewClientWaitSyncAPPLE;
+GLEW_FUN_EXPORT PFNGLDELETESYNCAPPLEPROC __glewDeleteSyncAPPLE;
+GLEW_FUN_EXPORT PFNGLFENCESYNCAPPLEPROC __glewFenceSyncAPPLE;
+GLEW_FUN_EXPORT PFNGLGETINTEGER64VAPPLEPROC __glewGetInteger64vAPPLE;
+GLEW_FUN_EXPORT PFNGLGETSYNCIVAPPLEPROC __glewGetSyncivAPPLE;
+GLEW_FUN_EXPORT PFNGLISSYNCAPPLEPROC __glewIsSyncAPPLE;
+GLEW_FUN_EXPORT PFNGLWAITSYNCAPPLEPROC __glewWaitSyncAPPLE;
+
+GLEW_FUN_EXPORT PFNGLBLENDEQUATIONEXTPROC __glewBlendEquationEXT;
+
+GLEW_FUN_EXPORT PFNGLGETOBJECTLABELEXTPROC __glewGetObjectLabelEXT;
+GLEW_FUN_EXPORT PFNGLLABELOBJECTEXTPROC __glewLabelObjectEXT;
+
+GLEW_FUN_EXPORT PFNGLINSERTEVENTMARKEREXTPROC __glewInsertEventMarkerEXT;
+GLEW_FUN_EXPORT PFNGLPUSHGROUPMARKEREXTPROC __glewPushGroupMarkerEXT;
+
+GLEW_FUN_EXPORT PFNGLDISCARDFRAMEBUFFEREXTPROC __glewDiscardFramebufferEXT;
+
+GLEW_FUN_EXPORT PFNGLFLUSHMAPPEDBUFFERRANGEEXTPROC __glewFlushMappedBufferRangeEXT;
+GLEW_FUN_EXPORT PFNGLMAPBUFFERRANGEEXTPROC __glewMapBufferRangeEXT;
+
+GLEW_FUN_EXPORT PFNGLMULTIDRAWARRAYSEXTPROC __glewMultiDrawArraysEXT;
+GLEW_FUN_EXPORT PFNGLMULTIDRAWELEMENTSEXTPROC __glewMultiDrawElementsEXT;
+
+GLEW_FUN_EXPORT PFNGLFRAMEBUFFERTEXTURE2DMULTISAMPLEEXTPROC __glewFramebufferTexture2DMultisampleEXT;
+GLEW_FUN_EXPORT PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC __glewRenderbufferStorageMultisampleEXT;
+
+GLEW_FUN_EXPORT PFNGLDRAWBUFFERSINDEXEDEXTPROC __glewDrawBuffersIndexedEXT;
+GLEW_FUN_EXPORT PFNGLGETINTEGERI_VEXTPROC __glewGetIntegeri_vEXT;
+GLEW_FUN_EXPORT PFNGLREADBUFFERINDEXEDEXTPROC __glewReadBufferIndexedEXT;
+
+GLEW_FUN_EXPORT PFNGLBEGINQUERYEXTPROC __glewBeginQueryEXT;
+GLEW_FUN_EXPORT PFNGLDELETEQUERIESEXTPROC __glewDeleteQueriesEXT;
+GLEW_FUN_EXPORT PFNGLENDQUERYEXTPROC __glewEndQueryEXT;
+GLEW_FUN_EXPORT PFNGLGENQUERIESEXTPROC __glewGenQueriesEXT;
+GLEW_FUN_EXPORT PFNGLGETQUERYOBJECTUIVEXTPROC __glewGetQueryObjectuivEXT;
+GLEW_FUN_EXPORT PFNGLGETQUERYIVEXTPROC __glewGetQueryivEXT;
+GLEW_FUN_EXPORT PFNGLISQUERYEXTPROC __glewIsQueryEXT;
+
+GLEW_FUN_EXPORT PFNGLGETNUNIFORMFVEXTPROC __glewGetnUniformfvEXT;
+GLEW_FUN_EXPORT PFNGLGETNUNIFORMIVEXTPROC __glewGetnUniformivEXT;
+GLEW_FUN_EXPORT PFNGLREADNPIXELSEXTPROC __glewReadnPixelsEXT;
+
+#if 0 // NOTE jwilkins: there is an inconsistency between the ES and Non-ES versions of this extension??
+GLEW_FUN_EXPORT PFNGLACTIVESHADERPROGRAMEXTPROC __glewActiveShaderProgramEXT;
+GLEW_FUN_EXPORT PFNGLBINDPROGRAMPIPELINEEXTPROC __glewBindProgramPipelineEXT;
+GLEW_FUN_EXPORT PFNGLCREATESHADERPROGRAMVEXTPROC __glewCreateShaderProgramvEXT;
+GLEW_FUN_EXPORT PFNGLDELETEPROGRAMPIPELINESEXTPROC __glewDeleteProgramPipelinesEXT;
+GLEW_FUN_EXPORT PFNGLGENPROGRAMPIPELINESEXTPROC __glewGenProgramPipelinesEXT;
+GLEW_FUN_EXPORT PFNGLGETPROGRAMPIPELINEINFOLOGEXTPROC __glewGetProgramPipelineInfoLogEXT;
+GLEW_FUN_EXPORT PFNGLGETPROGRAMPIPELINEIVEXTPROC __glewGetProgramPipelineivEXT;
+GLEW_FUN_EXPORT PFNGLISPROGRAMPIPELINEEXTPROC __glewIsProgramPipelineEXT;
+GLEW_FUN_EXPORT PFNGLPROGRAMPARAMETERIEXTPROC __glewProgramParameteriEXT;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM1FEXTPROC __glewProgramUniform1fEXT;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM1FVEXTPROC __glewProgramUniform1fvEXT;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM1IEXTPROC __glewProgramUniform1iEXT;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM1IVEXTPROC __glewProgramUniform1ivEXT;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM2FEXTPROC __glewProgramUniform2fEXT;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM2FVEXTPROC __glewProgramUniform2fvEXT;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM2IEXTPROC __glewProgramUniform2iEXT;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM2IVEXTPROC __glewProgramUniform2ivEXT;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM3FEXTPROC __glewProgramUniform3fEXT;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM3FVEXTPROC __glewProgramUniform3fvEXT;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM3IEXTPROC __glewProgramUniform3iEXT;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM3IVEXTPROC __glewProgramUniform3ivEXT;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM4FEXTPROC __glewProgramUniform4fEXT;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM4FVEXTPROC __glewProgramUniform4fvEXT;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM4IEXTPROC __glewProgramUniform4iEXT;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM4IVEXTPROC __glewProgramUniform4ivEXT;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX2FVEXTPROC __glewProgramUniformMatrix2fvEXT;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX3FVEXTPROC __glewProgramUniformMatrix3fvEXT;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX4FVEXTPROC __glewProgramUniformMatrix4fvEXT;
+GLEW_FUN_EXPORT PFNGLUSEPROGRAMSTAGESEXTPROC __glewUseProgramStagesEXT;
+GLEW_FUN_EXPORT PFNGLVALIDATEPROGRAMPIPELINEEXTPROC __glewValidateProgramPipelineEXT;
+#endif // XXX
+
+GLEW_FUN_EXPORT PFNGLTEXSTORAGE1DEXTPROC __glewTexStorage1DEXT;
+GLEW_FUN_EXPORT PFNGLTEXSTORAGE2DEXTPROC __glewTexStorage2DEXT;
+GLEW_FUN_EXPORT PFNGLTEXSTORAGE3DEXTPROC __glewTexStorage3DEXT;
+GLEW_FUN_EXPORT PFNGLTEXTURESTORAGE1DEXTPROC __glewTextureStorage1DEXT;
+GLEW_FUN_EXPORT PFNGLTEXTURESTORAGE2DEXTPROC __glewTextureStorage2DEXT;
+GLEW_FUN_EXPORT PFNGLTEXTURESTORAGE3DEXTPROC __glewTextureStorage3DEXT;
+
+GLEW_FUN_EXPORT PFNGLFRAMEBUFFERTEXTURE2DMULTISAMPLEIMGPROC __glewFramebufferTexture2DMultisampleIMG;
+GLEW_FUN_EXPORT PFNGLRENDERBUFFERSTORAGEMULTISAMPLEIMGPROC __glewRenderbufferStorageMultisampleIMG;
+
+GLEW_FUN_EXPORT PFNGLCLIPPLANEFIMGPROC __glewClipPlanefIMG;
+
+GLEW_FUN_EXPORT PFNGLDEBUGMESSAGECALLBACKPROC __glewDebugMessageCallback;
+GLEW_FUN_EXPORT PFNGLDEBUGMESSAGECONTROLPROC __glewDebugMessageControl;
+GLEW_FUN_EXPORT PFNGLDEBUGMESSAGEINSERTPROC __glewDebugMessageInsert;
+GLEW_FUN_EXPORT PFNGLGETDEBUGMESSAGELOGPROC __glewGetDebugMessageLog;
+GLEW_FUN_EXPORT PFNGLGETOBJECTLABELPROC __glewGetObjectLabel;
+GLEW_FUN_EXPORT PFNGLGETOBJECTPTRLABELPROC __glewGetObjectPtrLabel;
+GLEW_FUN_EXPORT PFNGLGETPOINTERVPROC __glewGetPointerv;
+GLEW_FUN_EXPORT PFNGLOBJECTLABELPROC __glewObjectLabel;
+GLEW_FUN_EXPORT PFNGLOBJECTPTRLABELPROC __glewObjectPtrLabel;
+GLEW_FUN_EXPORT PFNGLPOPDEBUGGROUPPROC __glewPopDebugGroup;
+GLEW_FUN_EXPORT PFNGLPUSHDEBUGGROUPPROC __glewPushDebugGroup;
+
+GLEW_FUN_EXPORT PFNGLSTEREOPARAMETERFNVPROC __glewStereoParameterfNV;
+GLEW_FUN_EXPORT PFNGLSTEREOPARAMETERINVPROC __glewStereoParameteriNV;
+
+GLEW_FUN_EXPORT PFNGLCOVERAGEMASKNVPROC __glewCoverageMaskNV;
+GLEW_FUN_EXPORT PFNGLCOVERAGEOPERATIONNVPROC __glewCoverageOperationNV;
+
+GLEW_FUN_EXPORT PFNGLDRAWBUFFERSNVPROC __glewDrawBuffersNV;
+
+GLEW_FUN_EXPORT PFNGLDRAWTEXTURENVPROC __glewDrawTextureNV;
+
+GLEW_FUN_EXPORT PFNGLDELETEFENCESNVPROC __glewDeleteFencesNV;
+GLEW_FUN_EXPORT PFNGLFINISHFENCENVPROC __glewFinishFenceNV;
+GLEW_FUN_EXPORT PFNGLGENFENCESNVPROC __glewGenFencesNV;
+GLEW_FUN_EXPORT PFNGLGETFENCEIVNVPROC __glewGetFenceivNV;
+GLEW_FUN_EXPORT PFNGLISFENCENVPROC __glewIsFenceNV;
+GLEW_FUN_EXPORT PFNGLSETFENCENVPROC __glewSetFenceNV;
+GLEW_FUN_EXPORT PFNGLTESTFENCENVPROC __glewTestFenceNV;
+
+GLEW_FUN_EXPORT PFNGLREADBUFFERNVPROC __glewReadBufferNV;
+
+GLEW_FUN_EXPORT PFNGLCOMPRESSEDTEXIMAGE3DNVPROC __glewCompressedTexImage3DNV;
+GLEW_FUN_EXPORT PFNGLCOMPRESSEDTEXSUBIMAGE3DNVPROC __glewCompressedTexSubImage3DNV;
+GLEW_FUN_EXPORT PFNGLCOPYTEXSUBIMAGE3DNVPROC __glewCopyTexSubImage3DNV;
+GLEW_FUN_EXPORT PFNGLFRAMEBUFFERTEXTURELAYERNVPROC __glewFramebufferTextureLayerNV;
+GLEW_FUN_EXPORT PFNGLTEXIMAGE3DNVPROC __glewTexImage3DNV;
+GLEW_FUN_EXPORT PFNGLTEXSUBIMAGE3DNVPROC __glewTexSubImage3DNV;
+
+GLEW_FUN_EXPORT PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC __glewEGLImageTargetRenderbufferStorageOES;
+GLEW_FUN_EXPORT PFNGLEGLIMAGETARGETTEXTURE2DOESPROC __glewEGLImageTargetTexture2DOES;
+
+GLEW_FUN_EXPORT PFNGLBLENDEQUATIONSEPARATEOESPROC __glewBlendEquationSeparateOES;
+
+GLEW_FUN_EXPORT PFNGLBLENDFUNCSEPARATEOESPROC __glewBlendFuncSeparateOES;
+
+GLEW_FUN_EXPORT PFNGLBLENDEQUATIONOESPROC __glewBlendEquationOES;
+
+GLEW_FUN_EXPORT PFNGLBINDFRAMEBUFFEROESPROC __glewBindFramebufferOES;
+GLEW_FUN_EXPORT PFNGLBINDRENDERBUFFEROESPROC __glewBindRenderbufferOES;
+GLEW_FUN_EXPORT PFNGLCHECKFRAMEBUFFERSTATUSOESPROC __glewCheckFramebufferStatusOES;
+GLEW_FUN_EXPORT PFNGLDELETEFRAMEBUFFERSOESPROC __glewDeleteFramebuffersOES;
+GLEW_FUN_EXPORT PFNGLDELETERENDERBUFFERSOESPROC __glewDeleteRenderbuffersOES;
+GLEW_FUN_EXPORT PFNGLFRAMEBUFFERRENDERBUFFEROESPROC __glewFramebufferRenderbufferOES;
+GLEW_FUN_EXPORT PFNGLFRAMEBUFFERTEXTURE2DOESPROC __glewFramebufferTexture2DOES;
+GLEW_FUN_EXPORT PFNGLGENFRAMEBUFFERSOESPROC __glewGenFramebuffersOES;
+GLEW_FUN_EXPORT PFNGLGENRENDERBUFFERSOESPROC __glewGenRenderbuffersOES;
+GLEW_FUN_EXPORT PFNGLGENERATEMIPMAPOESPROC __glewGenerateMipmapOES;
+GLEW_FUN_EXPORT PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVOESPROC __glewGetFramebufferAttachmentParameterivOES;
+GLEW_FUN_EXPORT PFNGLGETRENDERBUFFERPARAMETERIVOESPROC __glewGetRenderbufferParameterivOES;
+GLEW_FUN_EXPORT PFNGLISFRAMEBUFFEROESPROC __glewIsFramebufferOES;
+GLEW_FUN_EXPORT PFNGLISRENDERBUFFEROESPROC __glewIsRenderbufferOES;
+GLEW_FUN_EXPORT PFNGLRENDERBUFFERSTORAGEOESPROC __glewRenderbufferStorageOES;
+
+GLEW_FUN_EXPORT PFNGLGETPROGRAMBINARYOESPROC __glewGetProgramBinaryOES;
+GLEW_FUN_EXPORT PFNGLPROGRAMBINARYOESPROC __glewProgramBinaryOES;
+
+GLEW_FUN_EXPORT PFNGLGETBUFFERPOINTERVOESPROC __glewGetBufferPointervOES;
+GLEW_FUN_EXPORT PFNGLMAPBUFFEROESPROC __glewMapBufferOES;
+GLEW_FUN_EXPORT PFNGLUNMAPBUFFEROESPROC __glewUnmapBufferOES;
+
+GLEW_FUN_EXPORT PFNGLCURRENTPALETTEMATRIXOESPROC __glewCurrentPaletteMatrixOES;
+GLEW_FUN_EXPORT PFNGLMATRIXINDEXPOINTEROESPROC __glewMatrixIndexPointerOES;
+GLEW_FUN_EXPORT PFNGLWEIGHTPOINTEROESPROC __glewWeightPointerOES;
+
+GLEW_FUN_EXPORT PFNGLPOINTSIZEPOINTEROESPROC __glewPointSizePointerOES;
+
+GLEW_FUN_EXPORT PFNGLCLEARDEPTHFOESPROC __glewClearDepthfOES;
+GLEW_FUN_EXPORT PFNGLCLIPPLANEFOESPROC __glewClipPlanefOES;
+GLEW_FUN_EXPORT PFNGLDEPTHRANGEFOESPROC __glewDepthRangefOES;
+GLEW_FUN_EXPORT PFNGLFRUSTUMFOESPROC __glewFrustumfOES;
+GLEW_FUN_EXPORT PFNGLGETCLIPPLANEFOESPROC __glewGetClipPlanefOES;
+GLEW_FUN_EXPORT PFNGLORTHOFOESPROC __glewOrthofOES;
+
+GLEW_FUN_EXPORT PFNGLCOMPRESSEDTEXIMAGE3DOESPROC __glewCompressedTexImage3DOES;
+GLEW_FUN_EXPORT PFNGLCOMPRESSEDTEXSUBIMAGE3DOESPROC __glewCompressedTexSubImage3DOES;
+GLEW_FUN_EXPORT PFNGLCOPYTEXSUBIMAGE3DOESPROC __glewCopyTexSubImage3DOES;
+GLEW_FUN_EXPORT PFNGLFRAMEBUFFERTEXTURE3DOESPROC __glewFramebufferTexture3DOES;
+GLEW_FUN_EXPORT PFNGLTEXIMAGE3DOESPROC __glewTexImage3DOES;
+GLEW_FUN_EXPORT PFNGLTEXSUBIMAGE3DOESPROC __glewTexSubImage3DOES;
+
+GLEW_FUN_EXPORT PFNGLGETTEXGENFVOESPROC __glewGetTexGenfvOES;
+GLEW_FUN_EXPORT PFNGLGETTEXGENIVOESPROC __glewGetTexGenivOES;
+GLEW_FUN_EXPORT PFNGLGETTEXGENXVOESPROC __glewGetTexGenxvOES;
+GLEW_FUN_EXPORT PFNGLTEXGENFOESPROC __glewTexGenfOES;
+GLEW_FUN_EXPORT PFNGLTEXGENFVOESPROC __glewTexGenfvOES;
+GLEW_FUN_EXPORT PFNGLTEXGENIOESPROC __glewTexGeniOES;
+GLEW_FUN_EXPORT PFNGLTEXGENIVOESPROC __glewTexGenivOES;
+GLEW_FUN_EXPORT PFNGLTEXGENXOESPROC __glewTexGenxOES;
+GLEW_FUN_EXPORT PFNGLTEXGENXVOESPROC __glewTexGenxvOES;
+
+GLEW_FUN_EXPORT PFNGLBINDVERTEXARRAYOESPROC __glewBindVertexArrayOES;
+GLEW_FUN_EXPORT PFNGLDELETEVERTEXARRAYSOESPROC __glewDeleteVertexArraysOES;
+GLEW_FUN_EXPORT PFNGLGENVERTEXARRAYSOESPROC __glewGenVertexArraysOES;
+GLEW_FUN_EXPORT PFNGLISVERTEXARRAYOESPROC __glewIsVertexArrayOES;
+
+GLEW_FUN_EXPORT PFNGLALPHAFUNCQCOMPROC __glewAlphaFuncQCOM;
+
+GLEW_FUN_EXPORT PFNGLDISABLEDRIVERCONTROLQCOMPROC __glewDisableDriverControlQCOM;
+GLEW_FUN_EXPORT PFNGLENABLEDRIVERCONTROLQCOMPROC __glewEnableDriverControlQCOM;
+GLEW_FUN_EXPORT PFNGLGETDRIVERCONTROLSTRINGQCOMPROC __glewGetDriverControlStringQCOM;
+GLEW_FUN_EXPORT PFNGLGETDRIVERCONTROLSQCOMPROC __glewGetDriverControlsQCOM;
+
+GLEW_FUN_EXPORT PFNGLEXTGETBUFFERPOINTERVQCOMPROC __glewExtGetBufferPointervQCOM;
+GLEW_FUN_EXPORT PFNGLEXTGETBUFFERSQCOMPROC __glewExtGetBuffersQCOM;
+GLEW_FUN_EXPORT PFNGLEXTGETFRAMEBUFFERSQCOMPROC __glewExtGetFramebuffersQCOM;
+GLEW_FUN_EXPORT PFNGLEXTGETRENDERBUFFERSQCOMPROC __glewExtGetRenderbuffersQCOM;
+GLEW_FUN_EXPORT PFNGLEXTGETTEXLEVELPARAMETERIVQCOMPROC __glewExtGetTexLevelParameterivQCOM;
+GLEW_FUN_EXPORT PFNGLEXTGETTEXSUBIMAGEQCOMPROC __glewExtGetTexSubImageQCOM;
+GLEW_FUN_EXPORT PFNGLEXTGETTEXTURESQCOMPROC __glewExtGetTexturesQCOM;
+GLEW_FUN_EXPORT PFNGLEXTTEXOBJECTSTATEOVERRIDEIQCOMPROC __glewExtTexObjectStateOverrideiQCOM;
+
+GLEW_FUN_EXPORT PFNGLEXTGETPROGRAMBINARYSOURCEQCOMPROC __glewExtGetProgramBinarySourceQCOM;
+GLEW_FUN_EXPORT PFNGLEXTGETPROGRAMSQCOMPROC __glewExtGetProgramsQCOM;
+GLEW_FUN_EXPORT PFNGLEXTGETSHADERSQCOMPROC __glewExtGetShadersQCOM;
+GLEW_FUN_EXPORT PFNGLEXTISPROGRAMBINARYQCOMPROC __glewExtIsProgramBinaryQCOM;
+
+GLEW_FUN_EXPORT PFNGLENDTILINGQCOMPROC __glewEndTilingQCOM;
+GLEW_FUN_EXPORT PFNGLSTARTTILINGQCOMPROC __glewStartTilingQCOM;
+
+GLEW_FUN_EXPORT PFNGLMULTIDRAWARRAYSSUNPROC __glewMultiDrawArraysSUN;
+GLEW_FUN_EXPORT PFNGLMULTIDRAWELEMENTSSUNPROC __glewMultiDrawElementsSUN;
+
+#if defined(GLEW_MX) && !defined(_WIN32)
+struct GLEWContextStruct
+{
+#endif /* GLEW_MX */
+
+GLEW_VAR_EXPORT GLboolean __GLEW_ES_VERSION_1_0;
+GLEW_VAR_EXPORT GLboolean __GLEW_ES_VERSION_CL_1_1;
+GLEW_VAR_EXPORT GLboolean __GLEW_ES_VERSION_CM_1_1;
+GLEW_VAR_EXPORT GLboolean __GLEW_ES_VERSION_2_0;
+GLEW_VAR_EXPORT GLboolean __GLEW_AMD_compressed_3DC_texture;
+GLEW_VAR_EXPORT GLboolean __GLEW_AMD_compressed_ATC_texture;
+GLEW_VAR_EXPORT GLboolean __GLEW_AMD_performance_monitor;
+GLEW_VAR_EXPORT GLboolean __GLEW_AMD_program_binary_Z400;
+GLEW_VAR_EXPORT GLboolean __GLEW_ANGLE_framebuffer_blit;
+GLEW_VAR_EXPORT GLboolean __GLEW_ANGLE_framebuffer_multisample;
+GLEW_VAR_EXPORT GLboolean __GLEW_ANGLE_instanced_arrays;
+GLEW_VAR_EXPORT GLboolean __GLEW_ANGLE_pack_reverse_row_order;
+GLEW_VAR_EXPORT GLboolean __GLEW_ANGLE_texture_compression_dxt3;
+GLEW_VAR_EXPORT GLboolean __GLEW_ANGLE_texture_compression_dxt5;
+GLEW_VAR_EXPORT GLboolean __GLEW_ANGLE_texture_usage;
+GLEW_VAR_EXPORT GLboolean __GLEW_ANGLE_translated_shader_source;
+GLEW_VAR_EXPORT GLboolean __GLEW_APPLE_copy_texture_levels;
+GLEW_VAR_EXPORT GLboolean __GLEW_APPLE_framebuffer_multisample;
+GLEW_VAR_EXPORT GLboolean __GLEW_APPLE_rgb_422;
+GLEW_VAR_EXPORT GLboolean __GLEW_APPLE_sync;
+GLEW_VAR_EXPORT GLboolean __GLEW_APPLE_texture_2D_limited_npot;
+GLEW_VAR_EXPORT GLboolean __GLEW_APPLE_texture_format_BGRA8888;
+GLEW_VAR_EXPORT GLboolean __GLEW_APPLE_texture_max_level;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARM_mali_program_binary;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARM_mali_shader_binary;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARM_rgba8;
+GLEW_VAR_EXPORT GLboolean __GLEW_DMP_shader_binary;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_blend_minmax;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_color_buffer_half_float;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_debug_label;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_debug_marker;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_discard_framebuffer;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_frag_depth;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_map_buffer_range;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_multi_draw_arrays;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_multisampled_render_to_texture;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_multiview_draw_buffers;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_occlusion_query_boolean;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_read_format_bgra;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_robustness;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_sRGB;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_separate_shader_objects;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_shader_framebuffer_fetch;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_shader_texture_lod;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_shadow_samplers;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_compression_dxt1;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_filter_anisotropic;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_format_BGRA8888;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_lod_bias;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_rg;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_storage;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_type_2_10_10_10_REV;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_unpack_subimage;
+GLEW_VAR_EXPORT GLboolean __GLEW_FJ_shader_binary_GCCSO;
+GLEW_VAR_EXPORT GLboolean __GLEW_IMG_multisampled_render_to_texture;
+GLEW_VAR_EXPORT GLboolean __GLEW_IMG_program_binary;
+GLEW_VAR_EXPORT GLboolean __GLEW_IMG_read_format;
+GLEW_VAR_EXPORT GLboolean __GLEW_IMG_shader_binary;
+GLEW_VAR_EXPORT GLboolean __GLEW_IMG_texture_compression_pvrtc;
+GLEW_VAR_EXPORT GLboolean __GLEW_IMG_texture_env_enhanced_fixed_function;
+GLEW_VAR_EXPORT GLboolean __GLEW_IMG_user_clip_plane;
+GLEW_VAR_EXPORT GLboolean __GLEW_KHR_debug;
+GLEW_VAR_EXPORT GLboolean __GLEW_KHR_texture_compression_astc_ldr;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_3dvision_settings;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_EGL_stream_consumer_external;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_bgr;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_coverage_sample;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_depth_nonlinear;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_draw_buffers;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_draw_texture;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_fbo_color_attachments;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_fence;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_pack_subimage;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_packed_float;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_packed_float_linear;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_pixel_buffer_object;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_platform_binary;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_read_buffer;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_read_buffer_front;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_read_depth;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_read_depth_stencil;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_read_stencil;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_texture_array;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_texture_compression_latc;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_texture_compression_s3tc;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_texture_compression_s3tc_update;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_texture_npot_2D_mipmap;
+GLEW_VAR_EXPORT GLboolean __GLEW_OES_EGL_image;
+GLEW_VAR_EXPORT GLboolean __GLEW_OES_EGL_image_external;
+GLEW_VAR_EXPORT GLboolean __GLEW_OES_EGL_sync;
+GLEW_VAR_EXPORT GLboolean __GLEW_OES_blend_equation_separate;
+GLEW_VAR_EXPORT GLboolean __GLEW_OES_blend_func_separate;
+GLEW_VAR_EXPORT GLboolean __GLEW_OES_blend_subtract;
+GLEW_VAR_EXPORT GLboolean __GLEW_OES_byte_coordinates;
+GLEW_VAR_EXPORT GLboolean __GLEW_OES_compressed_ETC1_RGB8_texture;
+GLEW_VAR_EXPORT GLboolean __GLEW_OES_compressed_paletted_texture;
+GLEW_VAR_EXPORT GLboolean __GLEW_OES_depth24;
+GLEW_VAR_EXPORT GLboolean __GLEW_OES_depth32;
+GLEW_VAR_EXPORT GLboolean __GLEW_OES_depth_texture;
+GLEW_VAR_EXPORT GLboolean __GLEW_OES_depth_texture_cube_map;
+GLEW_VAR_EXPORT GLboolean __GLEW_OES_draw_texture;
+GLEW_VAR_EXPORT GLboolean __GLEW_OES_element_index_uint;
+GLEW_VAR_EXPORT GLboolean __GLEW_OES_extended_matrix_palette;
+GLEW_VAR_EXPORT GLboolean __GLEW_OES_fbo_render_mipmap;
+GLEW_VAR_EXPORT GLboolean __GLEW_OES_fragment_precision_high;
+GLEW_VAR_EXPORT GLboolean __GLEW_OES_framebuffer_object;
+GLEW_VAR_EXPORT GLboolean __GLEW_OES_get_program_binary;
+GLEW_VAR_EXPORT GLboolean __GLEW_OES_mapbuffer;
+GLEW_VAR_EXPORT GLboolean __GLEW_OES_matrix_get;
+GLEW_VAR_EXPORT GLboolean __GLEW_OES_matrix_palette;
+GLEW_VAR_EXPORT GLboolean __GLEW_OES_packed_depth_stencil;
+GLEW_VAR_EXPORT GLboolean __GLEW_OES_point_size_array;
+GLEW_VAR_EXPORT GLboolean __GLEW_OES_point_sprite;
+GLEW_VAR_EXPORT GLboolean __GLEW_OES_read_format;
+GLEW_VAR_EXPORT GLboolean __GLEW_OES_required_internalformat;
+GLEW_VAR_EXPORT GLboolean __GLEW_OES_rgb8_rgba8;
+GLEW_VAR_EXPORT GLboolean __GLEW_OES_single_precision;
+GLEW_VAR_EXPORT GLboolean __GLEW_OES_standard_derivatives;
+GLEW_VAR_EXPORT GLboolean __GLEW_OES_stencil1;
+GLEW_VAR_EXPORT GLboolean __GLEW_OES_stencil4;
+GLEW_VAR_EXPORT GLboolean __GLEW_OES_stencil8;
+GLEW_VAR_EXPORT GLboolean __GLEW_OES_surfaceless_context;
+GLEW_VAR_EXPORT GLboolean __GLEW_OES_texture_3D;
+GLEW_VAR_EXPORT GLboolean __GLEW_OES_texture_cube_map;
+GLEW_VAR_EXPORT GLboolean __GLEW_OES_texture_env_crossbar;
+GLEW_VAR_EXPORT GLboolean __GLEW_OES_texture_mirrored_repeat;
+GLEW_VAR_EXPORT GLboolean __GLEW_OES_texture_npot;
+GLEW_VAR_EXPORT GLboolean __GLEW_OES_vertex_array_object;
+GLEW_VAR_EXPORT GLboolean __GLEW_OES_vertex_half_float;
+GLEW_VAR_EXPORT GLboolean __GLEW_OES_vertex_type_10_10_10_2;
+GLEW_VAR_EXPORT GLboolean __GLEW_QCOM_alpha_test;
+GLEW_VAR_EXPORT GLboolean __GLEW_QCOM_binning_control;
+GLEW_VAR_EXPORT GLboolean __GLEW_QCOM_driver_control;
+GLEW_VAR_EXPORT GLboolean __GLEW_QCOM_extended_get;
+GLEW_VAR_EXPORT GLboolean __GLEW_QCOM_extended_get2;
+GLEW_VAR_EXPORT GLboolean __GLEW_QCOM_perfmon_global_mode;
+GLEW_VAR_EXPORT GLboolean __GLEW_QCOM_tiled_rendering;
+GLEW_VAR_EXPORT GLboolean __GLEW_QCOM_writeonly_rendering;
+GLEW_VAR_EXPORT GLboolean __GLEW_SUN_multi_draw_arrays;
+GLEW_VAR_EXPORT GLboolean __GLEW_VG_KHR_EGL_sync;
+GLEW_VAR_EXPORT GLboolean __GLEW_VIV_shader_binary;
+
+#ifdef GLEW_MX
+}; /* GLEWContextStruct */
+#endif /* GLEW_MX */
+
+
+#endif /* __glesew_h__ */
diff --git a/extern/glew-es/include/GL/glew.h b/extern/glew-es/include/GL/glew.h
new file mode 100644
index 00000000000..58d49396c5d
--- /dev/null
+++ b/extern/glew-es/include/GL/glew.h
@@ -0,0 +1,20525 @@
+/*
+** The OpenGL Extension Wrangler Library
+** Copyright (C) 2002-2008, Milan Ikits <milan ikits[]ieee org>
+** Copyright (C) 2002-2008, Marcelo E. Magallon <mmagallo[]debian org>
+** Copyright (C) 2002, Lev Povalahev
+** 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.
+** * The name of the author 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.
+*/
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.0
+ *
+ * Copyright (C) 1999-2007 Brian Paul 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
+ * BRIAN PAUL 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.
+ */
+
+/*
+** Copyright (c) 2007 The Khronos Group Inc.
+**
+** Permission is hereby granted, free of charge, to any person obtaining a
+** copy of this software and/or associated documentation files (the
+** "Materials"), to deal in the Materials without restriction, including
+** without limitation the rights to use, copy, modify, merge, publish,
+** distribute, sublicense, and/or sell copies of the Materials, and to
+** permit persons to whom the Materials are furnished to do so, subject to
+** the following conditions:
+**
+** The above copyright notice and this permission notice shall be included
+** in all copies or substantial portions of the Materials.
+**
+** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+*/
+
+#ifndef __glew_h__
+#define __glew_h__
+#define __GLEW_H__
+
+#if defined(__gl_h_) || defined(__GL_H__) || defined(__X_GL_H)
+#error gl.h included before glew.h
+#endif
+#if defined(__glext_h_) || defined(__GLEXT_H_)
+#error glext.h included before glew.h
+#endif
+#if defined(__gl_ATI_h_)
+#error glATI.h included before glew.h
+#endif
+#if defined(__gl2_h_) || defined(__GL2_H_)
+#error gl2.h included before glew.h
+#endif
+#if defined(__gl2ext_h_) || defined(__GL2EXT_H_)
+#error gl2ext.h included before glew.h
+#endif
+#if defined(__gl2platform_h_) || defined(__GL2PLATFORM_H_)
+#error gl2platform.h included before glew.h
+#endif
+#if defined(__khrplatform_h_) || defined(__KHRPLATFORM_H_)
+#error khrplatform.h included before glew.h
+#endif
+
+#define __gl_h_
+#define __GL_H__
+#define __X_GL_H
+#define __glext_h_
+#define __GLEXT_H_
+#define __gl_ATI_h_
+#define __gl2_h_
+#define __gl2ext_h_
+#define __gl2platform_h_
+#define __GL2PLATFORM_H_
+#define __khrplatform_h_
+#define __KHRPLATFORM_H_
+
+
+#if defined(GLEW_USE_LIB_ES11) || defined(GLEW_USE_LIB_ES20)
+#define GLEW_USE_LIB_ES
+#endif
+
+/*
+ * GLEW_STATIC is defined for static library.
+ * GLEW_BUILD is defined for building the DLL library.
+ */
+
+#ifdef WIN32
+# ifdef GLEW_STATIC
+# define GLEWAPI extern
+# else
+# ifdef GLEW_BUILD
+# define GLEWAPI extern __declspec(dllexport)
+# else
+# define GLEWAPI extern __declspec(dllimport)
+# endif
+# endif /* GLEW_STATIC */
+#else
+# ifdef GLEW_STATIC
+# define GLEWAPI extern
+# else
+# if defined(__GNUC__) && __GNUC__>=4
+# define GLEWAPI extern __attribute__ ((visibility("default")))
+# elif defined(__SUNPRO_C) || defined(__SUNPRO_CC)
+# define GLEWAPI extern __global
+# else
+# define GLEWAPI extern
+# endif
+# endif /* GLEW_STATIC */
+#endif /* WIN32 */
+
+
+/* Khronos platform-specific types and definitions.
+ *
+ * $Revision: 9356 $ on $Date: 2009-10-21 02:52:25 -0700 (Wed, 21 Oct 2009) $
+ *
+ * Adopters may modify this file to suit their platform. Adopters are
+ * encouraged to submit platform specific modifications to the Khronos
+ * group so that they can be included in future versions of this file.
+ * Please submit changes by sending them to the public Khronos Bugzilla
+ * (http://khronos.org/bugzilla) by filing a bug against product
+ * "Khronos (general)" component "Registry".
+ *
+ * A predefined template which fills in some of the bug fields can be
+ * reached using http://tinyurl.com/khrplatform-h-bugreport, but you
+ * must create a Bugzilla login first.
+ *
+ *
+ * See the Implementer's Guidelines for information about where this file
+ * should be located on your system and for more details of its use:
+ * http://www.khronos.org/registry/implementers_guide.pdf
+ *
+ * This file should be included as
+ * #include <KHR/khrplatform.h>
+ * by Khronos client API header files that use its types and defines.
+ *
+ * The types in khrplatform.h should only be used to define API-specific types.
+ *
+ * Types defined in khrplatform.h:
+ * khronos_int8_t signed 8 bit
+ * khronos_uint8_t unsigned 8 bit
+ * khronos_int16_t signed 16 bit
+ * khronos_uint16_t unsigned 16 bit
+ * khronos_int32_t signed 32 bit
+ * khronos_uint32_t unsigned 32 bit
+ * khronos_int64_t signed 64 bit
+ * khronos_uint64_t unsigned 64 bit
+ * khronos_intptr_t signed same number of bits as a pointer
+ * khronos_uintptr_t unsigned same number of bits as a pointer
+ * khronos_ssize_t signed size
+ * khronos_usize_t unsigned size
+ * khronos_float_t signed 32 bit floating point
+ * khronos_time_ns_t unsigned 64 bit time in nanoseconds
+ * khronos_utime_nanoseconds_t unsigned time interval or absolute time in
+ * nanoseconds
+ * khronos_stime_nanoseconds_t signed time interval in nanoseconds
+ * khronos_boolean_enum_t enumerated boolean type. This should
+ * only be used as a base type when a client API's boolean type is
+ * an enum. Client APIs which use an integer or other type for
+ * booleans cannot use this as the base type for their boolean.
+ *
+ * Tokens defined in khrplatform.h:
+ *
+ * KHRONOS_FALSE, KHRONOS_TRUE Enumerated boolean false/true values.
+ *
+ * KHRONOS_SUPPORT_INT64 is 1 if 64 bit integers are supported; otherwise 0.
+ * KHRONOS_SUPPORT_FLOAT is 1 if floats are supported; otherwise 0.
+ *
+ * Calling convention macros defined in this file:
+ * KHRONOS_APICALL
+ * KHRONOS_APIENTRY
+ * KHRONOS_APIATTRIBUTES
+ *
+ * These may be used in function prototypes as:
+ *
+ * KHRONOS_APICALL void KHRONOS_APIENTRY funcname(
+ * int arg1,
+ * int arg2) KHRONOS_APIATTRIBUTES;
+ */
+/*-------------------------------------------------------------------------
+ * Definition of KHRONOS_APICALL
+ *-------------------------------------------------------------------------
+ * This precedes the return type of the function in the function prototype.
+ */
+#if defined(_WIN32) && !defined(__SCITECH_SNAP__)
+# define KHRONOS_APICALL __declspec(dllimport)
+#elif defined (__SYMBIAN32__)
+# define KHRONOS_APICALL IMPORT_C
+#else
+# define KHRONOS_APICALL
+#endif
+
+/*-------------------------------------------------------------------------
+ * Definition of KHRONOS_APIENTRY
+ *-------------------------------------------------------------------------
+ * This follows the return type of the function and precedes the function
+ * name in the function prototype.
+ */
+#if defined(_WIN32) && !defined(_WIN32_WCE) && !defined(__SCITECH_SNAP__)
+ /* Win32 but not WinCE */
+# define KHRONOS_APIENTRY __stdcall
+#else
+# define KHRONOS_APIENTRY
+#endif
+
+/*-------------------------------------------------------------------------
+ * Definition of KHRONOS_APIATTRIBUTES
+ *-------------------------------------------------------------------------
+ * This follows the closing parenthesis of the function prototype arguments.
+ */
+#if defined (__ARMCC_2__)
+#define KHRONOS_APIATTRIBUTES __softfp
+#else
+#define KHRONOS_APIATTRIBUTES
+#endif
+
+/*-------------------------------------------------------------------------
+ * basic type definitions
+ *-----------------------------------------------------------------------*/
+#if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || defined(__GNUC__) || defined(__SCO__) || defined(__USLC__)
+
+
+/*
+ * Using <stdint.h>
+ */
+#include <stdint.h>
+typedef int32_t khronos_int32_t;
+typedef uint32_t khronos_uint32_t;
+typedef int64_t khronos_int64_t;
+typedef uint64_t khronos_uint64_t;
+#define KHRONOS_SUPPORT_INT64 1
+#define KHRONOS_SUPPORT_FLOAT 1
+
+#elif defined(__VMS ) || defined(__sgi)
+
+/*
+ * Using <inttypes.h>
+ */
+#include <inttypes.h>
+typedef int32_t khronos_int32_t;
+typedef uint32_t khronos_uint32_t;
+typedef int64_t khronos_int64_t;
+typedef uint64_t khronos_uint64_t;
+#define KHRONOS_SUPPORT_INT64 1
+#define KHRONOS_SUPPORT_FLOAT 1
+
+#elif defined(_WIN32) && !defined(__SCITECH_SNAP__)
+
+/*
+ * Win32
+ */
+typedef __int32 khronos_int32_t;
+typedef unsigned __int32 khronos_uint32_t;
+typedef __int64 khronos_int64_t;
+typedef unsigned __int64 khronos_uint64_t;
+#define KHRONOS_SUPPORT_INT64 1
+#define KHRONOS_SUPPORT_FLOAT 1
+
+#elif defined(__sun__) || defined(__digital__)
+
+/*
+ * Sun or Digital
+ */
+typedef int khronos_int32_t;
+typedef unsigned int khronos_uint32_t;
+#if defined(__arch64__) || defined(_LP64)
+typedef long int khronos_int64_t;
+typedef unsigned long int khronos_uint64_t;
+#else
+typedef long long int khronos_int64_t;
+typedef unsigned long long int khronos_uint64_t;
+#endif /* __arch64__ */
+#define KHRONOS_SUPPORT_INT64 1
+#define KHRONOS_SUPPORT_FLOAT 1
+
+#elif 0
+
+/*
+ * Hypothetical platform with no float or int64 support
+ */
+typedef int khronos_int32_t;
+typedef unsigned int khronos_uint32_t;
+#define KHRONOS_SUPPORT_INT64 0
+#define KHRONOS_SUPPORT_FLOAT 0
+
+#else
+
+/*
+ * Generic fallback
+ */
+#include <stdint.h>
+typedef int32_t khronos_int32_t;
+typedef uint32_t khronos_uint32_t;
+typedef int64_t khronos_int64_t;
+typedef uint64_t khronos_uint64_t;
+#define KHRONOS_SUPPORT_INT64 1
+#define KHRONOS_SUPPORT_FLOAT 1
+
+#endif
+
+
+/*
+ * Types that are (so far) the same on all platforms
+ */
+typedef signed char khronos_int8_t;
+typedef unsigned char khronos_uint8_t;
+typedef signed short int khronos_int16_t;
+typedef unsigned short int khronos_uint16_t;
+typedef signed long int khronos_intptr_t;
+typedef unsigned long int khronos_uintptr_t;
+typedef signed long int khronos_ssize_t;
+typedef unsigned long int khronos_usize_t;
+
+#if KHRONOS_SUPPORT_FLOAT
+/*
+ * Float type
+ */
+typedef float khronos_float_t;
+#endif
+
+#if KHRONOS_SUPPORT_INT64
+/* Time types
+ *
+ * These types can be used to represent a time interval in nanoseconds or
+ * an absolute Unadjusted System Time. Unadjusted System Time is the number
+ * of nanoseconds since some arbitrary system event (e.g. since the last
+ * time the system booted). The Unadjusted System Time is an unsigned
+ * 64 bit value that wraps back to 0 every 584 years. Time intervals
+ * may be either signed or unsigned.
+ */
+typedef khronos_uint64_t khronos_utime_nanoseconds_t;
+typedef khronos_int64_t khronos_stime_nanoseconds_t;
+#endif
+
+/*
+ * Dummy value used to pad enum types to 32 bits.
+ */
+#ifndef KHRONOS_MAX_ENUM
+#define KHRONOS_MAX_ENUM 0x7FFFFFFF
+#endif
+
+/*
+ * Enumerated boolean type
+ *
+ * Values other than zero should be considered to be true. Therefore
+ * comparisons should not be made against KHRONOS_TRUE.
+ */
+typedef enum {
+ KHRONOS_FALSE = 0,
+ KHRONOS_TRUE = 1,
+ KHRONOS_BOOLEAN_ENUM_FORCE_SIZE = KHRONOS_MAX_ENUM
+} khronos_boolean_enum_t;
+
+/**********************************************************************************/
+
+#if defined(_WIN32)
+
+/*
+ * GLEW does not include <windows.h> to avoid name space pollution.
+ * GL needs GLAPI and GLAPIENTRY, GLU needs APIENTRY, CALLBACK, and wchar_t
+ * defined properly.
+ */
+/* <windef.h> */
+#ifndef APIENTRY
+#define GLEW_APIENTRY_DEFINED
+# if defined(__MINGW32__) || defined(__CYGWIN__)
+# define APIENTRY __stdcall
+# elif (_MSC_VER >= 800) || defined(_STDCALL_SUPPORTED) || defined(__BORLANDC__)
+# define APIENTRY __stdcall
+# else
+# define APIENTRY
+# endif
+#endif
+#ifndef GLAPI
+# if defined(__MINGW32__) || defined(__CYGWIN__)
+# define GLAPI extern
+# endif
+#endif
+/* <winnt.h> */
+#ifndef CALLBACK
+#define GLEW_CALLBACK_DEFINED
+# if defined(__MINGW32__) || defined(__CYGWIN__)
+# define CALLBACK __attribute__ ((__stdcall__))
+# elif (defined(_M_MRX000) || defined(_M_IX86) || defined(_M_ALPHA) || defined(_M_PPC)) && !defined(MIDL_PASS)
+# define CALLBACK __stdcall
+# else
+# define CALLBACK
+# endif
+#endif
+/* <wingdi.h> and <winnt.h> */
+#ifndef WINGDIAPI
+#define GLEW_WINGDIAPI_DEFINED
+#define WINGDIAPI __declspec(dllimport)
+#endif
+/* <ctype.h> */
+#if (defined(_MSC_VER) || defined(__BORLANDC__)) && !defined(_WCHAR_T_DEFINED)
+typedef unsigned short wchar_t;
+# define _WCHAR_T_DEFINED
+#endif
+/* <stddef.h> */
+#if !defined(_W64)
+# if !defined(__midl) && (defined(_X86_) || defined(_M_IX86)) && defined(_MSC_VER) && _MSC_VER >= 1300
+# define _W64 __w64
+# else
+# define _W64
+# endif
+#endif
+#if !defined(_PTRDIFF_T_DEFINED) && !defined(_PTRDIFF_T_) && !defined(__MINGW64__)
+# ifdef _WIN64
+typedef __int64 ptrdiff_t;
+# else
+typedef _W64 int ptrdiff_t;
+# endif
+# define _PTRDIFF_T_DEFINED
+# define _PTRDIFF_T_
+#endif
+
+#ifndef GLAPI
+# if defined(__MINGW32__) || defined(__CYGWIN__)
+# define GLAPI extern
+# else
+# define GLAPI WINGDIAPI
+# endif
+#endif
+
+#ifndef GLAPIENTRY
+#define GLAPIENTRY APIENTRY
+#endif
+
+#else /* _UNIX */
+
+/*
+ * Needed for ptrdiff_t in turn needed by VBO. This is defined by ISO
+ * C. On my system, this amounts to _3 lines_ of included code, all of
+ * them pretty much harmless. If you know of a way of detecting 32 vs
+ * 64 _targets_ at compile time you are free to replace this with
+ * something that's portable. For now, _this_ is the portable solution.
+ * (mem, 2004-01-04)
+ */
+
+#include <stddef.h>
+
+/* SGI MIPSPro doesn't like stdint.h in C++ mode */
+/* ID: 3376260 Solaris 9 has inttypes.h, but not stdint.h */
+
+#if (defined(__sgi) || defined(__sun)) && !defined(__GNUC__)
+#include <inttypes.h>
+#else
+#include <stdint.h>
+#endif
+
+#define GLEW_APIENTRY_DEFINED
+#define APIENTRY
+
+
+/* <glu.h> */
+#ifndef GLAPI
+#define GLAPI extern
+#endif
+#ifndef GLAPIENTRY
+#define GLAPIENTRY
+#endif
+
+#endif /* _WIN32 */
+
+/* from OpenGL ES */
+#ifndef GLAPI
+# define GLAPI KHRONOS_APICALL
+#endif
+
+#ifndef GLAPIENTRY
+# define GLAPIENTRY KHRONOS_APIENTRY
+#endif
+
+#ifndef APIENTRY
+# define APIENTRY GLAPIENTRY
+#endif
+
+#ifndef GL_API
+# define GL_API GLAPI
+#endif
+
+#ifndef GL_APIENTRY
+# define GL_APIENTRY GLAPIENTRY
+#endif
+
+/* from glext.h header */
+#ifndef GL_APIENTRYP
+# define GL_APIENTRYP GL_APIENTRY*
+#endif
+
+/* For OpenGL ES only case the header file glesew.h is included */
+#ifdef GLEW_ES_ONLY
+
+#include <GL/glesew.h>
+
+#else
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* ------------------------- GL_VERSION_1_1 functions common with OpenGL ES 1.0 ---------------------- */
+
+typedef unsigned int GLenum;
+typedef unsigned int GLbitfield;
+typedef unsigned int GLuint;
+typedef int GLint;
+typedef int GLsizei;
+typedef unsigned char GLboolean;
+typedef signed char GLbyte;
+typedef short GLshort;
+typedef unsigned char GLubyte;
+typedef unsigned short GLushort;
+typedef unsigned long GLulong;
+typedef float GLfloat;
+typedef float GLclampf;
+typedef double GLdouble;
+typedef double GLclampd;
+typedef void GLvoid;
+#if defined(_MSC_VER) && _MSC_VER < 1400
+typedef __int64 GLint64EXT;
+typedef unsigned __int64 GLuint64EXT;
+#elif defined(_MSC_VER) || defined(__BORLANDC__)
+typedef signed long long GLint64EXT;
+typedef unsigned long long GLuint64EXT;
+#else
+# if defined(__MINGW32__) || defined(__CYGWIN__)
+#include <inttypes.h>
+# endif
+typedef int64_t GLint64EXT;
+typedef uint64_t GLuint64EXT;
+#endif
+typedef GLint64EXT GLint64;
+typedef GLuint64EXT GLuint64;
+typedef struct __GLsync *GLsync;
+
+typedef char GLchar;
+
+#define GL_ZERO 0
+#define GL_FALSE 0
+#define GL_LOGIC_OP 0x0BF1
+#define GL_NONE 0
+#define GL_TEXTURE_COMPONENTS 0x1003
+#define GL_NO_ERROR 0
+#define GL_POINTS 0x0000
+#define GL_CURRENT_BIT 0x00000001
+#define GL_TRUE 1
+#define GL_ONE 1
+#define GL_CLIENT_PIXEL_STORE_BIT 0x00000001
+#define GL_LINES 0x0001
+#define GL_LINE_LOOP 0x0002
+#define GL_POINT_BIT 0x00000002
+#define GL_CLIENT_VERTEX_ARRAY_BIT 0x00000002
+#define GL_LINE_STRIP 0x0003
+#define GL_LINE_BIT 0x00000004
+#define GL_TRIANGLES 0x0004
+#define GL_TRIANGLE_STRIP 0x0005
+#define GL_TRIANGLE_FAN 0x0006
+#define GL_QUADS 0x0007
+#define GL_QUAD_STRIP 0x0008
+#define GL_POLYGON_BIT 0x00000008
+#define GL_POLYGON 0x0009
+#define GL_POLYGON_STIPPLE_BIT 0x00000010
+#define GL_PIXEL_MODE_BIT 0x00000020
+#define GL_LIGHTING_BIT 0x00000040
+#define GL_FOG_BIT 0x00000080
+#define GL_DEPTH_BUFFER_BIT 0x00000100
+#define GL_ACCUM 0x0100
+#define GL_LOAD 0x0101
+#define GL_RETURN 0x0102
+#define GL_MULT 0x0103
+#define GL_ADD 0x0104
+#define GL_NEVER 0x0200
+#define GL_ACCUM_BUFFER_BIT 0x00000200
+#define GL_LESS 0x0201
+#define GL_EQUAL 0x0202
+#define GL_LEQUAL 0x0203
+#define GL_GREATER 0x0204
+#define GL_NOTEQUAL 0x0205
+#define GL_GEQUAL 0x0206
+#define GL_ALWAYS 0x0207
+#define GL_SRC_COLOR 0x0300
+#define GL_ONE_MINUS_SRC_COLOR 0x0301
+#define GL_SRC_ALPHA 0x0302
+#define GL_ONE_MINUS_SRC_ALPHA 0x0303
+#define GL_DST_ALPHA 0x0304
+#define GL_ONE_MINUS_DST_ALPHA 0x0305
+#define GL_DST_COLOR 0x0306
+#define GL_ONE_MINUS_DST_COLOR 0x0307
+#define GL_SRC_ALPHA_SATURATE 0x0308
+#define GL_STENCIL_BUFFER_BIT 0x00000400
+#define GL_FRONT_LEFT 0x0400
+#define GL_FRONT_RIGHT 0x0401
+#define GL_BACK_LEFT 0x0402
+#define GL_BACK_RIGHT 0x0403
+#define GL_FRONT 0x0404
+#define GL_BACK 0x0405
+#define GL_LEFT 0x0406
+#define GL_RIGHT 0x0407
+#define GL_FRONT_AND_BACK 0x0408
+#define GL_AUX0 0x0409
+#define GL_AUX1 0x040A
+#define GL_AUX2 0x040B
+#define GL_AUX3 0x040C
+#define GL_INVALID_ENUM 0x0500
+#define GL_INVALID_VALUE 0x0501
+#define GL_INVALID_OPERATION 0x0502
+#define GL_STACK_OVERFLOW 0x0503
+#define GL_STACK_UNDERFLOW 0x0504
+#define GL_OUT_OF_MEMORY 0x0505
+#define GL_2D 0x0600
+#define GL_3D 0x0601
+#define GL_3D_COLOR 0x0602
+#define GL_3D_COLOR_TEXTURE 0x0603
+#define GL_4D_COLOR_TEXTURE 0x0604
+#define GL_PASS_THROUGH_TOKEN 0x0700
+#define GL_POINT_TOKEN 0x0701
+#define GL_LINE_TOKEN 0x0702
+#define GL_POLYGON_TOKEN 0x0703
+#define GL_BITMAP_TOKEN 0x0704
+#define GL_DRAW_PIXEL_TOKEN 0x0705
+#define GL_COPY_PIXEL_TOKEN 0x0706
+#define GL_LINE_RESET_TOKEN 0x0707
+#define GL_EXP 0x0800
+#define GL_VIEWPORT_BIT 0x00000800
+#define GL_EXP2 0x0801
+#define GL_CW 0x0900
+#define GL_CCW 0x0901
+#define GL_COEFF 0x0A00
+#define GL_ORDER 0x0A01
+#define GL_DOMAIN 0x0A02
+#define GL_CURRENT_COLOR 0x0B00
+#define GL_CURRENT_INDEX 0x0B01
+#define GL_CURRENT_NORMAL 0x0B02
+#define GL_CURRENT_TEXTURE_COORDS 0x0B03
+#define GL_CURRENT_RASTER_COLOR 0x0B04
+#define GL_CURRENT_RASTER_INDEX 0x0B05
+#define GL_CURRENT_RASTER_TEXTURE_COORDS 0x0B06
+#define GL_CURRENT_RASTER_POSITION 0x0B07
+#define GL_CURRENT_RASTER_POSITION_VALID 0x0B08
+#define GL_CURRENT_RASTER_DISTANCE 0x0B09
+#define GL_POINT_SMOOTH 0x0B10
+#define GL_POINT_SIZE 0x0B11
+#define GL_POINT_SIZE_RANGE 0x0B12
+#define GL_POINT_SIZE_GRANULARITY 0x0B13
+#define GL_LINE_SMOOTH 0x0B20
+#define GL_LINE_WIDTH 0x0B21
+#define GL_LINE_WIDTH_RANGE 0x0B22
+#define GL_LINE_WIDTH_GRANULARITY 0x0B23
+#define GL_LINE_STIPPLE 0x0B24
+#define GL_LINE_STIPPLE_PATTERN 0x0B25
+#define GL_LINE_STIPPLE_REPEAT 0x0B26
+#define GL_LIST_MODE 0x0B30
+#define GL_MAX_LIST_NESTING 0x0B31
+#define GL_LIST_BASE 0x0B32
+#define GL_LIST_INDEX 0x0B33
+#define GL_POLYGON_MODE 0x0B40
+#define GL_POLYGON_SMOOTH 0x0B41
+#define GL_POLYGON_STIPPLE 0x0B42
+#define GL_EDGE_FLAG 0x0B43
+#define GL_CULL_FACE 0x0B44
+#define GL_CULL_FACE_MODE 0x0B45
+#define GL_FRONT_FACE 0x0B46
+#define GL_LIGHTING 0x0B50
+#define GL_LIGHT_MODEL_LOCAL_VIEWER 0x0B51
+#define GL_LIGHT_MODEL_TWO_SIDE 0x0B52
+#define GL_LIGHT_MODEL_AMBIENT 0x0B53
+#define GL_SHADE_MODEL 0x0B54
+#define GL_COLOR_MATERIAL_FACE 0x0B55
+#define GL_COLOR_MATERIAL_PARAMETER 0x0B56
+#define GL_COLOR_MATERIAL 0x0B57
+#define GL_FOG 0x0B60
+#define GL_FOG_INDEX 0x0B61
+#define GL_FOG_DENSITY 0x0B62
+#define GL_FOG_START 0x0B63
+#define GL_FOG_END 0x0B64
+#define GL_FOG_MODE 0x0B65
+#define GL_FOG_COLOR 0x0B66
+#define GL_DEPTH_RANGE 0x0B70
+#define GL_DEPTH_TEST 0x0B71
+#define GL_DEPTH_WRITEMASK 0x0B72
+#define GL_DEPTH_CLEAR_VALUE 0x0B73
+#define GL_DEPTH_FUNC 0x0B74
+#define GL_ACCUM_CLEAR_VALUE 0x0B80
+#define GL_STENCIL_TEST 0x0B90
+#define GL_STENCIL_CLEAR_VALUE 0x0B91
+#define GL_STENCIL_FUNC 0x0B92
+#define GL_STENCIL_VALUE_MASK 0x0B93
+#define GL_STENCIL_FAIL 0x0B94
+#define GL_STENCIL_PASS_DEPTH_FAIL 0x0B95
+#define GL_STENCIL_PASS_DEPTH_PASS 0x0B96
+#define GL_STENCIL_REF 0x0B97
+#define GL_STENCIL_WRITEMASK 0x0B98
+#define GL_MATRIX_MODE 0x0BA0
+#define GL_NORMALIZE 0x0BA1
+#define GL_VIEWPORT 0x0BA2
+#define GL_MODELVIEW_STACK_DEPTH 0x0BA3
+#define GL_PROJECTION_STACK_DEPTH 0x0BA4
+#define GL_TEXTURE_STACK_DEPTH 0x0BA5
+#define GL_MODELVIEW_MATRIX 0x0BA6
+#define GL_PROJECTION_MATRIX 0x0BA7
+#define GL_TEXTURE_MATRIX 0x0BA8
+#define GL_ATTRIB_STACK_DEPTH 0x0BB0
+#define GL_CLIENT_ATTRIB_STACK_DEPTH 0x0BB1
+#define GL_ALPHA_TEST 0x0BC0
+#define GL_ALPHA_TEST_FUNC 0x0BC1
+#define GL_ALPHA_TEST_REF 0x0BC2
+#define GL_DITHER 0x0BD0
+#define GL_BLEND_DST 0x0BE0
+#define GL_BLEND_SRC 0x0BE1
+#define GL_BLEND 0x0BE2
+#define GL_LOGIC_OP_MODE 0x0BF0
+#define GL_INDEX_LOGIC_OP 0x0BF1
+#define GL_COLOR_LOGIC_OP 0x0BF2
+#define GL_AUX_BUFFERS 0x0C00
+#define GL_DRAW_BUFFER 0x0C01
+#define GL_READ_BUFFER 0x0C02
+#define GL_SCISSOR_BOX 0x0C10
+#define GL_SCISSOR_TEST 0x0C11
+#define GL_INDEX_CLEAR_VALUE 0x0C20
+#define GL_INDEX_WRITEMASK 0x0C21
+#define GL_COLOR_CLEAR_VALUE 0x0C22
+#define GL_COLOR_WRITEMASK 0x0C23
+#define GL_INDEX_MODE 0x0C30
+#define GL_RGBA_MODE 0x0C31
+#define GL_DOUBLEBUFFER 0x0C32
+#define GL_STEREO 0x0C33
+#define GL_RENDER_MODE 0x0C40
+#define GL_PERSPECTIVE_CORRECTION_HINT 0x0C50
+#define GL_POINT_SMOOTH_HINT 0x0C51
+#define GL_LINE_SMOOTH_HINT 0x0C52
+#define GL_POLYGON_SMOOTH_HINT 0x0C53
+#define GL_FOG_HINT 0x0C54
+#define GL_TEXTURE_GEN_S 0x0C60
+#define GL_TEXTURE_GEN_T 0x0C61
+#define GL_TEXTURE_GEN_R 0x0C62
+#define GL_TEXTURE_GEN_Q 0x0C63
+#define GL_PIXEL_MAP_I_TO_I 0x0C70
+#define GL_PIXEL_MAP_S_TO_S 0x0C71
+#define GL_PIXEL_MAP_I_TO_R 0x0C72
+#define GL_PIXEL_MAP_I_TO_G 0x0C73
+#define GL_PIXEL_MAP_I_TO_B 0x0C74
+#define GL_PIXEL_MAP_I_TO_A 0x0C75
+#define GL_PIXEL_MAP_R_TO_R 0x0C76
+#define GL_PIXEL_MAP_G_TO_G 0x0C77
+#define GL_PIXEL_MAP_B_TO_B 0x0C78
+#define GL_PIXEL_MAP_A_TO_A 0x0C79
+#define GL_PIXEL_MAP_I_TO_I_SIZE 0x0CB0
+#define GL_PIXEL_MAP_S_TO_S_SIZE 0x0CB1
+#define GL_PIXEL_MAP_I_TO_R_SIZE 0x0CB2
+#define GL_PIXEL_MAP_I_TO_G_SIZE 0x0CB3
+#define GL_PIXEL_MAP_I_TO_B_SIZE 0x0CB4
+#define GL_PIXEL_MAP_I_TO_A_SIZE 0x0CB5
+#define GL_PIXEL_MAP_R_TO_R_SIZE 0x0CB6
+#define GL_PIXEL_MAP_G_TO_G_SIZE 0x0CB7
+#define GL_PIXEL_MAP_B_TO_B_SIZE 0x0CB8
+#define GL_PIXEL_MAP_A_TO_A_SIZE 0x0CB9
+#define GL_UNPACK_SWAP_BYTES 0x0CF0
+#define GL_UNPACK_LSB_FIRST 0x0CF1
+#define GL_UNPACK_ROW_LENGTH 0x0CF2
+#define GL_UNPACK_SKIP_ROWS 0x0CF3
+#define GL_UNPACK_SKIP_PIXELS 0x0CF4
+#define GL_UNPACK_ALIGNMENT 0x0CF5
+#define GL_PACK_SWAP_BYTES 0x0D00
+#define GL_PACK_LSB_FIRST 0x0D01
+#define GL_PACK_ROW_LENGTH 0x0D02
+#define GL_PACK_SKIP_ROWS 0x0D03
+#define GL_PACK_SKIP_PIXELS 0x0D04
+#define GL_PACK_ALIGNMENT 0x0D05
+#define GL_MAP_COLOR 0x0D10
+#define GL_MAP_STENCIL 0x0D11
+#define GL_INDEX_SHIFT 0x0D12
+#define GL_INDEX_OFFSET 0x0D13
+#define GL_RED_SCALE 0x0D14
+#define GL_RED_BIAS 0x0D15
+#define GL_ZOOM_X 0x0D16
+#define GL_ZOOM_Y 0x0D17
+#define GL_GREEN_SCALE 0x0D18
+#define GL_GREEN_BIAS 0x0D19
+#define GL_BLUE_SCALE 0x0D1A
+#define GL_BLUE_BIAS 0x0D1B
+#define GL_ALPHA_SCALE 0x0D1C
+#define GL_ALPHA_BIAS 0x0D1D
+#define GL_DEPTH_SCALE 0x0D1E
+#define GL_DEPTH_BIAS 0x0D1F
+#define GL_MAX_EVAL_ORDER 0x0D30
+#define GL_MAX_LIGHTS 0x0D31
+#define GL_MAX_CLIP_PLANES 0x0D32
+#define GL_MAX_TEXTURE_SIZE 0x0D33
+#define GL_MAX_PIXEL_MAP_TABLE 0x0D34
+#define GL_MAX_ATTRIB_STACK_DEPTH 0x0D35
+#define GL_MAX_MODELVIEW_STACK_DEPTH 0x0D36
+#define GL_MAX_NAME_STACK_DEPTH 0x0D37
+#define GL_MAX_PROJECTION_STACK_DEPTH 0x0D38
+#define GL_MAX_TEXTURE_STACK_DEPTH 0x0D39
+#define GL_MAX_VIEWPORT_DIMS 0x0D3A
+#define GL_MAX_CLIENT_ATTRIB_STACK_DEPTH 0x0D3B
+#define GL_SUBPIXEL_BITS 0x0D50
+#define GL_INDEX_BITS 0x0D51
+#define GL_RED_BITS 0x0D52
+#define GL_GREEN_BITS 0x0D53
+#define GL_BLUE_BITS 0x0D54
+#define GL_ALPHA_BITS 0x0D55
+#define GL_DEPTH_BITS 0x0D56
+#define GL_STENCIL_BITS 0x0D57
+#define GL_ACCUM_RED_BITS 0x0D58
+#define GL_ACCUM_GREEN_BITS 0x0D59
+#define GL_ACCUM_BLUE_BITS 0x0D5A
+#define GL_ACCUM_ALPHA_BITS 0x0D5B
+#define GL_NAME_STACK_DEPTH 0x0D70
+#define GL_AUTO_NORMAL 0x0D80
+#define GL_MAP1_COLOR_4 0x0D90
+#define GL_MAP1_INDEX 0x0D91
+#define GL_MAP1_NORMAL 0x0D92
+#define GL_MAP1_TEXTURE_COORD_1 0x0D93
+#define GL_MAP1_TEXTURE_COORD_2 0x0D94
+#define GL_MAP1_TEXTURE_COORD_3 0x0D95
+#define GL_MAP1_TEXTURE_COORD_4 0x0D96
+#define GL_MAP1_VERTEX_3 0x0D97
+#define GL_MAP1_VERTEX_4 0x0D98
+#define GL_MAP2_COLOR_4 0x0DB0
+#define GL_MAP2_INDEX 0x0DB1
+#define GL_MAP2_NORMAL 0x0DB2
+#define GL_MAP2_TEXTURE_COORD_1 0x0DB3
+#define GL_MAP2_TEXTURE_COORD_2 0x0DB4
+#define GL_MAP2_TEXTURE_COORD_3 0x0DB5
+#define GL_MAP2_TEXTURE_COORD_4 0x0DB6
+#define GL_MAP2_VERTEX_3 0x0DB7
+#define GL_MAP2_VERTEX_4 0x0DB8
+#define GL_MAP1_GRID_DOMAIN 0x0DD0
+#define GL_MAP1_GRID_SEGMENTS 0x0DD1
+#define GL_MAP2_GRID_DOMAIN 0x0DD2
+#define GL_MAP2_GRID_SEGMENTS 0x0DD3
+#define GL_TEXTURE_1D 0x0DE0
+#define GL_TEXTURE_2D 0x0DE1
+#define GL_FEEDBACK_BUFFER_POINTER 0x0DF0
+#define GL_FEEDBACK_BUFFER_SIZE 0x0DF1
+#define GL_FEEDBACK_BUFFER_TYPE 0x0DF2
+#define GL_SELECTION_BUFFER_POINTER 0x0DF3
+#define GL_SELECTION_BUFFER_SIZE 0x0DF4
+#define GL_TEXTURE_WIDTH 0x1000
+#define GL_TRANSFORM_BIT 0x00001000
+#define GL_TEXTURE_HEIGHT 0x1001
+#define GL_TEXTURE_INTERNAL_FORMAT 0x1003
+#define GL_TEXTURE_BORDER_COLOR 0x1004
+#define GL_TEXTURE_BORDER 0x1005
+#define GL_DONT_CARE 0x1100
+#define GL_FASTEST 0x1101
+#define GL_NICEST 0x1102
+#define GL_AMBIENT 0x1200
+#define GL_DIFFUSE 0x1201
+#define GL_SPECULAR 0x1202
+#define GL_POSITION 0x1203
+#define GL_SPOT_DIRECTION 0x1204
+#define GL_SPOT_EXPONENT 0x1205
+#define GL_SPOT_CUTOFF 0x1206
+#define GL_CONSTANT_ATTENUATION 0x1207
+#define GL_LINEAR_ATTENUATION 0x1208
+#define GL_QUADRATIC_ATTENUATION 0x1209
+#define GL_COMPILE 0x1300
+#define GL_COMPILE_AND_EXECUTE 0x1301
+#define GL_BYTE 0x1400
+#define GL_UNSIGNED_BYTE 0x1401
+#define GL_SHORT 0x1402
+#define GL_UNSIGNED_SHORT 0x1403
+#define GL_INT 0x1404
+#define GL_UNSIGNED_INT 0x1405
+#define GL_FLOAT 0x1406
+#define GL_2_BYTES 0x1407
+#define GL_3_BYTES 0x1408
+#define GL_4_BYTES 0x1409
+#define GL_DOUBLE 0x140A
+#define GL_CLEAR 0x1500
+#define GL_AND 0x1501
+#define GL_AND_REVERSE 0x1502
+#define GL_COPY 0x1503
+#define GL_AND_INVERTED 0x1504
+#define GL_NOOP 0x1505
+#define GL_XOR 0x1506
+#define GL_OR 0x1507
+#define GL_NOR 0x1508
+#define GL_EQUIV 0x1509
+#define GL_INVERT 0x150A
+#define GL_OR_REVERSE 0x150B
+#define GL_COPY_INVERTED 0x150C
+#define GL_OR_INVERTED 0x150D
+#define GL_NAND 0x150E
+#define GL_SET 0x150F
+#define GL_EMISSION 0x1600
+#define GL_SHININESS 0x1601
+#define GL_AMBIENT_AND_DIFFUSE 0x1602
+#define GL_COLOR_INDEXES 0x1603
+#define GL_MODELVIEW 0x1700
+#define GL_PROJECTION 0x1701
+#define GL_TEXTURE 0x1702
+#define GL_COLOR 0x1800
+#define GL_DEPTH 0x1801
+#define GL_STENCIL 0x1802
+#define GL_COLOR_INDEX 0x1900
+#define GL_STENCIL_INDEX 0x1901
+#define GL_DEPTH_COMPONENT 0x1902
+#define GL_RED 0x1903
+#define GL_GREEN 0x1904
+#define GL_BLUE 0x1905
+#define GL_ALPHA 0x1906
+#define GL_RGB 0x1907
+#define GL_RGBA 0x1908
+#define GL_LUMINANCE 0x1909
+#define GL_LUMINANCE_ALPHA 0x190A
+#define GL_BITMAP 0x1A00
+#define GL_POINT 0x1B00
+#define GL_LINE 0x1B01
+#define GL_FILL 0x1B02
+#define GL_RENDER 0x1C00
+#define GL_FEEDBACK 0x1C01
+#define GL_SELECT 0x1C02
+#define GL_FLAT 0x1D00
+#define GL_SMOOTH 0x1D01
+#define GL_KEEP 0x1E00
+#define GL_REPLACE 0x1E01
+#define GL_INCR 0x1E02
+#define GL_DECR 0x1E03
+#define GL_VENDOR 0x1F00
+#define GL_RENDERER 0x1F01
+#define GL_VERSION 0x1F02
+#define GL_EXTENSIONS 0x1F03
+#define GL_S 0x2000
+#define GL_ENABLE_BIT 0x00002000
+#define GL_T 0x2001
+#define GL_R 0x2002
+#define GL_Q 0x2003
+#define GL_MODULATE 0x2100
+#define GL_DECAL 0x2101
+#define GL_TEXTURE_ENV_MODE 0x2200
+#define GL_TEXTURE_ENV_COLOR 0x2201
+#define GL_TEXTURE_ENV 0x2300
+#define GL_EYE_LINEAR 0x2400
+#define GL_OBJECT_LINEAR 0x2401
+#define GL_SPHERE_MAP 0x2402
+#define GL_TEXTURE_GEN_MODE 0x2500
+#define GL_OBJECT_PLANE 0x2501
+#define GL_EYE_PLANE 0x2502
+#define GL_NEAREST 0x2600
+#define GL_LINEAR 0x2601
+#define GL_NEAREST_MIPMAP_NEAREST 0x2700
+#define GL_LINEAR_MIPMAP_NEAREST 0x2701
+#define GL_NEAREST_MIPMAP_LINEAR 0x2702
+#define GL_LINEAR_MIPMAP_LINEAR 0x2703
+#define GL_TEXTURE_MAG_FILTER 0x2800
+#define GL_TEXTURE_MIN_FILTER 0x2801
+#define GL_TEXTURE_WRAP_S 0x2802
+#define GL_TEXTURE_WRAP_T 0x2803
+#define GL_CLAMP 0x2900
+#define GL_REPEAT 0x2901
+#define GL_POLYGON_OFFSET_UNITS 0x2A00
+#define GL_POLYGON_OFFSET_POINT 0x2A01
+#define GL_POLYGON_OFFSET_LINE 0x2A02
+#define GL_R3_G3_B2 0x2A10
+#define GL_V2F 0x2A20
+#define GL_V3F 0x2A21
+#define GL_C4UB_V2F 0x2A22
+#define GL_C4UB_V3F 0x2A23
+#define GL_C3F_V3F 0x2A24
+#define GL_N3F_V3F 0x2A25
+#define GL_C4F_N3F_V3F 0x2A26
+#define GL_T2F_V3F 0x2A27
+#define GL_T4F_V4F 0x2A28
+#define GL_T2F_C4UB_V3F 0x2A29
+#define GL_T2F_C3F_V3F 0x2A2A
+#define GL_T2F_N3F_V3F 0x2A2B
+#define GL_T2F_C4F_N3F_V3F 0x2A2C
+#define GL_T4F_C4F_N3F_V4F 0x2A2D
+#define GL_CLIP_PLANE0 0x3000
+#define GL_CLIP_PLANE1 0x3001
+#define GL_CLIP_PLANE2 0x3002
+#define GL_CLIP_PLANE3 0x3003
+#define GL_CLIP_PLANE4 0x3004
+#define GL_CLIP_PLANE5 0x3005
+#define GL_LIGHT0 0x4000
+#define GL_COLOR_BUFFER_BIT 0x00004000
+#define GL_LIGHT1 0x4001
+#define GL_LIGHT2 0x4002
+#define GL_LIGHT3 0x4003
+#define GL_LIGHT4 0x4004
+#define GL_LIGHT5 0x4005
+#define GL_LIGHT6 0x4006
+#define GL_LIGHT7 0x4007
+#define GL_HINT_BIT 0x00008000
+#define GL_POLYGON_OFFSET_FILL 0x8037
+#define GL_POLYGON_OFFSET_FACTOR 0x8038
+#define GL_ALPHA4 0x803B
+#define GL_ALPHA8 0x803C
+#define GL_ALPHA12 0x803D
+#define GL_ALPHA16 0x803E
+#define GL_LUMINANCE4 0x803F
+#define GL_LUMINANCE8 0x8040
+#define GL_LUMINANCE12 0x8041
+#define GL_LUMINANCE16 0x8042
+#define GL_LUMINANCE4_ALPHA4 0x8043
+#define GL_LUMINANCE6_ALPHA2 0x8044
+#define GL_LUMINANCE8_ALPHA8 0x8045
+#define GL_LUMINANCE12_ALPHA4 0x8046
+#define GL_LUMINANCE12_ALPHA12 0x8047
+#define GL_LUMINANCE16_ALPHA16 0x8048
+#define GL_INTENSITY 0x8049
+#define GL_INTENSITY4 0x804A
+#define GL_INTENSITY8 0x804B
+#define GL_INTENSITY12 0x804C
+#define GL_INTENSITY16 0x804D
+#define GL_RGB4 0x804F
+#define GL_RGB5 0x8050
+#define GL_RGB8 0x8051
+#define GL_RGB10 0x8052
+#define GL_RGB12 0x8053
+#define GL_RGB16 0x8054
+#define GL_RGBA2 0x8055
+#define GL_RGBA4 0x8056
+#define GL_RGB5_A1 0x8057
+#define GL_RGBA8 0x8058
+#define GL_RGB10_A2 0x8059
+#define GL_RGBA12 0x805A
+#define GL_RGBA16 0x805B
+#define GL_TEXTURE_RED_SIZE 0x805C
+#define GL_TEXTURE_GREEN_SIZE 0x805D
+#define GL_TEXTURE_BLUE_SIZE 0x805E
+#define GL_TEXTURE_ALPHA_SIZE 0x805F
+#define GL_TEXTURE_LUMINANCE_SIZE 0x8060
+#define GL_TEXTURE_INTENSITY_SIZE 0x8061
+#define GL_PROXY_TEXTURE_1D 0x8063
+#define GL_PROXY_TEXTURE_2D 0x8064
+#define GL_TEXTURE_PRIORITY 0x8066
+#define GL_TEXTURE_RESIDENT 0x8067
+#define GL_TEXTURE_BINDING_1D 0x8068
+#define GL_TEXTURE_BINDING_2D 0x8069
+#define GL_VERTEX_ARRAY 0x8074
+#define GL_NORMAL_ARRAY 0x8075
+#define GL_COLOR_ARRAY 0x8076
+#define GL_INDEX_ARRAY 0x8077
+#define GL_TEXTURE_COORD_ARRAY 0x8078
+#define GL_EDGE_FLAG_ARRAY 0x8079
+#define GL_VERTEX_ARRAY_SIZE 0x807A
+#define GL_VERTEX_ARRAY_TYPE 0x807B
+#define GL_VERTEX_ARRAY_STRIDE 0x807C
+#define GL_NORMAL_ARRAY_TYPE 0x807E
+#define GL_NORMAL_ARRAY_STRIDE 0x807F
+#define GL_COLOR_ARRAY_SIZE 0x8081
+#define GL_COLOR_ARRAY_TYPE 0x8082
+#define GL_COLOR_ARRAY_STRIDE 0x8083
+#define GL_INDEX_ARRAY_TYPE 0x8085
+#define GL_INDEX_ARRAY_STRIDE 0x8086
+#define GL_TEXTURE_COORD_ARRAY_SIZE 0x8088
+#define GL_TEXTURE_COORD_ARRAY_TYPE 0x8089
+#define GL_TEXTURE_COORD_ARRAY_STRIDE 0x808A
+#define GL_EDGE_FLAG_ARRAY_STRIDE 0x808C
+#define GL_VERTEX_ARRAY_POINTER 0x808E
+#define GL_NORMAL_ARRAY_POINTER 0x808F
+#define GL_COLOR_ARRAY_POINTER 0x8090
+#define GL_INDEX_ARRAY_POINTER 0x8091
+#define GL_TEXTURE_COORD_ARRAY_POINTER 0x8092
+#define GL_EDGE_FLAG_ARRAY_POINTER 0x8093
+#define GL_COLOR_INDEX1_EXT 0x80E2
+#define GL_COLOR_INDEX2_EXT 0x80E3
+#define GL_COLOR_INDEX4_EXT 0x80E4
+#define GL_COLOR_INDEX8_EXT 0x80E5
+#define GL_COLOR_INDEX12_EXT 0x80E6
+#define GL_COLOR_INDEX16_EXT 0x80E7
+#define GL_EVAL_BIT 0x00010000
+#define GL_LIST_BIT 0x00020000
+#define GL_TEXTURE_BIT 0x00040000
+#define GL_SCISSOR_BIT 0x00080000
+#define GL_ALL_ATTRIB_BITS 0x000fffff
+#define GL_CLIENT_ALL_ATTRIB_BITS 0xffffffff
+
+GLAPI void GLAPIENTRY glAlphaFunc (GLenum func, GLclampf ref);
+GLAPI void GLAPIENTRY glBindTexture (GLenum target, GLuint texture);
+GLAPI void GLAPIENTRY glBlendFunc (GLenum sfactor, GLenum dfactor);
+GLAPI void GLAPIENTRY glClear (GLbitfield mask);
+GLAPI void GLAPIENTRY glClearColor (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
+GLAPI void GLAPIENTRY glClearStencil (GLint s);
+GLAPI void GLAPIENTRY glColor4f (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
+GLAPI void GLAPIENTRY glColorMask (GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha);
+GLAPI void GLAPIENTRY glColorPointer (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);
+GLAPI void GLAPIENTRY glCopyTexImage2D (GLenum target, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border);
+GLAPI void GLAPIENTRY glCopyTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+GLAPI void GLAPIENTRY glCullFace (GLenum mode);
+GLAPI void GLAPIENTRY glDeleteTextures (GLsizei n, const GLuint *textures);
+GLAPI void GLAPIENTRY glDepthFunc (GLenum func);
+GLAPI void GLAPIENTRY glDepthMask (GLboolean flag);
+GLAPI void GLAPIENTRY glDisable (GLenum cap);
+GLAPI void GLAPIENTRY glDisableClientState (GLenum array);
+GLAPI void GLAPIENTRY glDrawArrays (GLenum mode, GLint first, GLsizei count);
+GLAPI void GLAPIENTRY glDrawElements (GLenum mode, GLsizei count, GLenum type, const GLvoid *indices);
+GLAPI void GLAPIENTRY glEnable (GLenum cap);
+GLAPI void GLAPIENTRY glEnableClientState (GLenum array);
+GLAPI void GLAPIENTRY glFinish (void);
+GLAPI void GLAPIENTRY glFlush (void);
+GLAPI void GLAPIENTRY glFogf (GLenum pname, GLfloat param);
+GLAPI void GLAPIENTRY glFogfv (GLenum pname, const GLfloat *params);
+GLAPI void GLAPIENTRY glFrontFace (GLenum mode);
+GLAPI void GLAPIENTRY glGenTextures (GLsizei n, GLuint *textures);
+GLAPI GLenum GLAPIENTRY glGetError (void);
+GLAPI void GLAPIENTRY glGetIntegerv (GLenum pname, GLint *params);
+GLAPI void GLAPIENTRY glGetPolygonStipple (GLubyte *mask);
+GLAPI const GLubyte * GLAPIENTRY glGetString (GLenum name);
+GLAPI void GLAPIENTRY glHint (GLenum target, GLenum mode);
+GLAPI void GLAPIENTRY glLightModelf (GLenum pname, GLfloat param);
+GLAPI void GLAPIENTRY glLightModelfv (GLenum pname, const GLfloat *params);
+GLAPI void GLAPIENTRY glLightf (GLenum light, GLenum pname, GLfloat param);
+GLAPI void GLAPIENTRY glLightfv (GLenum light, GLenum pname, const GLfloat *params);
+GLAPI void GLAPIENTRY glLineWidth (GLfloat width);
+GLAPI void GLAPIENTRY glLoadIdentity (void);
+GLAPI void GLAPIENTRY glLoadMatrixf (const GLfloat *m);
+GLAPI void GLAPIENTRY glLogicOp (GLenum opcode);
+GLAPI void GLAPIENTRY glMaterialf (GLenum face, GLenum pname, GLfloat param);
+GLAPI void GLAPIENTRY glMaterialfv (GLenum face, GLenum pname, const GLfloat *params);
+GLAPI void GLAPIENTRY glMatrixMode (GLenum mode);
+GLAPI void GLAPIENTRY glMultMatrixf (const GLfloat *m);
+GLAPI void GLAPIENTRY glNormal3f (GLfloat nx, GLfloat ny, GLfloat nz);
+GLAPI void GLAPIENTRY glNormalPointer (GLenum type, GLsizei stride, const GLvoid *pointer);
+GLAPI void GLAPIENTRY glPixelStorei (GLenum pname, GLint param);
+GLAPI void GLAPIENTRY glPointSize (GLfloat size);
+GLAPI void GLAPIENTRY glPolygonOffset (GLfloat factor, GLfloat units);
+GLAPI void GLAPIENTRY glPopMatrix (void);
+GLAPI void GLAPIENTRY glPushMatrix (void);
+GLAPI void GLAPIENTRY glReadPixels (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *pixels);
+GLAPI void GLAPIENTRY glRotatef (GLfloat angle, GLfloat x, GLfloat y, GLfloat z);
+GLAPI void GLAPIENTRY glScalef (GLfloat x, GLfloat y, GLfloat z);
+GLAPI void GLAPIENTRY glScissor (GLint x, GLint y, GLsizei width, GLsizei height);
+GLAPI void GLAPIENTRY glShadeModel (GLenum mode);
+GLAPI void GLAPIENTRY glStencilFunc (GLenum func, GLint ref, GLuint mask);
+GLAPI void GLAPIENTRY glStencilMask (GLuint mask);
+GLAPI void GLAPIENTRY glStencilOp (GLenum fail, GLenum zfail, GLenum zpass);
+GLAPI void GLAPIENTRY glTexCoordPointer (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);
+GLAPI void GLAPIENTRY glTexEnvf (GLenum target, GLenum pname, GLfloat param);
+GLAPI void GLAPIENTRY glTexEnvfv (GLenum target, GLenum pname, const GLfloat *params);
+GLAPI void GLAPIENTRY glTexImage2D (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels);
+GLAPI void GLAPIENTRY glTexParameterf (GLenum target, GLenum pname, GLfloat param);
+GLAPI void GLAPIENTRY glTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels);
+GLAPI void GLAPIENTRY glTranslatef (GLfloat x, GLfloat y, GLfloat z);
+GLAPI void GLAPIENTRY glVertexPointer (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);
+GLAPI void GLAPIENTRY glViewport (GLint x, GLint y, GLsizei width, GLsizei height);
+
+
+
+/* ---------------------------------- GLU ---------------------------------- */
+
+#ifndef GLEW_NO_GLU
+/* this is where we can safely include GLU */
+# if defined(__APPLE__) && defined(__MACH__)
+# include <OpenGL/glu.h>
+# else
+# include <GL/glu.h>
+# endif
+#endif
+
+/* ----------------------------- GL_VERSION_1_1 ---------------------------- */
+
+#if !defined(GL_VERSION_1_1)
+#define GL_VERSION_1_1 1
+
+typedef void (GLAPIENTRY * PFNGLACCUMPROC) (GLenum op, GLfloat value);
+typedef GLboolean (GLAPIENTRY * PFNGLARETEXTURESRESIDENTPROC) (GLsizei n, const GLuint *textures, GLboolean *residences);
+typedef void (GLAPIENTRY * PFNGLARRAYELEMENTPROC) (GLint i);
+typedef void (GLAPIENTRY * PFNGLBEGINPROC) (GLenum mode);
+typedef void (GLAPIENTRY * PFNGLBITMAPPROC) (GLsizei width, GLsizei height, GLfloat xorig, GLfloat yorig, GLfloat xmove, GLfloat ymove, const GLubyte *bitmap);
+typedef void (GLAPIENTRY * PFNGLCALLLISTPROC) (GLuint list);
+typedef void (GLAPIENTRY * PFNGLCALLLISTSPROC) (GLsizei n, GLenum type, const GLvoid *lists);
+typedef void (GLAPIENTRY * PFNGLCLEARACCUMPROC) (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
+typedef void (GLAPIENTRY * PFNGLCLEARDEPTHPROC) (GLclampd depth);
+typedef void (GLAPIENTRY * PFNGLCLEARINDEXPROC) (GLfloat c);
+typedef void (GLAPIENTRY * PFNGLCLIPPLANEPROC) (GLenum plane, const GLdouble *equation);
+typedef void (GLAPIENTRY * PFNGLCOLOR3BPROC) (GLbyte red, GLbyte green, GLbyte blue);
+typedef void (GLAPIENTRY * PFNGLCOLOR3BVPROC) (const GLbyte *v);
+typedef void (GLAPIENTRY * PFNGLCOLOR3DPROC) (GLdouble red, GLdouble green, GLdouble blue);
+typedef void (GLAPIENTRY * PFNGLCOLOR3DVPROC) (const GLdouble *v);
+typedef void (GLAPIENTRY * PFNGLCOLOR3FPROC) (GLfloat red, GLfloat green, GLfloat blue);
+typedef void (GLAPIENTRY * PFNGLCOLOR3FVPROC) (const GLfloat *v);
+typedef void (GLAPIENTRY * PFNGLCOLOR3IPROC) (GLint red, GLint green, GLint blue);
+typedef void (GLAPIENTRY * PFNGLCOLOR3IVPROC) (const GLint *v);
+typedef void (GLAPIENTRY * PFNGLCOLOR3SPROC) (GLshort red, GLshort green, GLshort blue);
+typedef void (GLAPIENTRY * PFNGLCOLOR3SVPROC) (const GLshort *v);
+typedef void (GLAPIENTRY * PFNGLCOLOR3UBPROC) (GLubyte red, GLubyte green, GLubyte blue);
+typedef void (GLAPIENTRY * PFNGLCOLOR3UBVPROC) (const GLubyte *v);
+typedef void (GLAPIENTRY * PFNGLCOLOR3UIPROC) (GLuint red, GLuint green, GLuint blue);
+typedef void (GLAPIENTRY * PFNGLCOLOR3UIVPROC) (const GLuint *v);
+typedef void (GLAPIENTRY * PFNGLCOLOR3USPROC) (GLushort red, GLushort green, GLushort blue);
+typedef void (GLAPIENTRY * PFNGLCOLOR3USVPROC) (const GLushort *v);
+typedef void (GLAPIENTRY * PFNGLCOLOR4BPROC) (GLbyte red, GLbyte green, GLbyte blue, GLbyte alpha);
+typedef void (GLAPIENTRY * PFNGLCOLOR4BVPROC) (const GLbyte *v);
+typedef void (GLAPIENTRY * PFNGLCOLOR4DPROC) (GLdouble red, GLdouble green, GLdouble blue, GLdouble alpha);
+typedef void (GLAPIENTRY * PFNGLCOLOR4DVPROC) (const GLdouble *v);
+typedef void (GLAPIENTRY * PFNGLCOLOR4FVPROC) (const GLfloat *v);
+typedef void (GLAPIENTRY * PFNGLCOLOR4IPROC) (GLint red, GLint green, GLint blue, GLint alpha);
+typedef void (GLAPIENTRY * PFNGLCOLOR4IVPROC) (const GLint *v);
+typedef void (GLAPIENTRY * PFNGLCOLOR4SPROC) (GLshort red, GLshort green, GLshort blue, GLshort alpha);
+typedef void (GLAPIENTRY * PFNGLCOLOR4SVPROC) (const GLshort *v);
+typedef void (GLAPIENTRY * PFNGLCOLOR4UBPROC) (GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha);
+typedef void (GLAPIENTRY * PFNGLCOLOR4UBVPROC) (const GLubyte *v);
+typedef void (GLAPIENTRY * PFNGLCOLOR4UIPROC) (GLuint red, GLuint green, GLuint blue, GLuint alpha);
+typedef void (GLAPIENTRY * PFNGLCOLOR4UIVPROC) (const GLuint *v);
+typedef void (GLAPIENTRY * PFNGLCOLOR4USPROC) (GLushort red, GLushort green, GLushort blue, GLushort alpha);
+typedef void (GLAPIENTRY * PFNGLCOLOR4USVPROC) (const GLushort *v);
+typedef void (GLAPIENTRY * PFNGLCOLORMATERIALPROC) (GLenum face, GLenum mode);
+typedef void (GLAPIENTRY * PFNGLCOPYPIXELSPROC) (GLint x, GLint y, GLsizei width, GLsizei height, GLenum type);
+typedef void (GLAPIENTRY * PFNGLCOPYTEXIMAGE1DPROC) (GLenum target, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLint border);
+typedef void (GLAPIENTRY * PFNGLCOPYTEXSUBIMAGE1DPROC) (GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width);
+typedef void (GLAPIENTRY * PFNGLDELETELISTSPROC) (GLuint list, GLsizei range);
+typedef void (GLAPIENTRY * PFNGLDEPTHRANGEPROC) (GLclampd zNear, GLclampd zFar);
+typedef void (GLAPIENTRY * PFNGLDRAWBUFFERPROC) (GLenum mode);
+typedef void (GLAPIENTRY * PFNGLDRAWPIXELSPROC) (GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels);
+typedef void (GLAPIENTRY * PFNGLEDGEFLAGPROC) (GLboolean flag);
+typedef void (GLAPIENTRY * PFNGLEDGEFLAGPOINTERPROC) (GLsizei stride, const GLvoid *pointer);
+typedef void (GLAPIENTRY * PFNGLEDGEFLAGVPROC) (const GLboolean *flag);
+typedef void (GLAPIENTRY * PFNGLENDPROC) (void);
+typedef void (GLAPIENTRY * PFNGLENDLISTPROC) (void);
+typedef void (GLAPIENTRY * PFNGLEVALCOORD1DPROC) (GLdouble u);
+typedef void (GLAPIENTRY * PFNGLEVALCOORD1DVPROC) (const GLdouble *u);
+typedef void (GLAPIENTRY * PFNGLEVALCOORD1FPROC) (GLfloat u);
+typedef void (GLAPIENTRY * PFNGLEVALCOORD1FVPROC) (const GLfloat *u);
+typedef void (GLAPIENTRY * PFNGLEVALCOORD2DPROC) (GLdouble u, GLdouble v);
+typedef void (GLAPIENTRY * PFNGLEVALCOORD2DVPROC) (const GLdouble *u);
+typedef void (GLAPIENTRY * PFNGLEVALCOORD2FPROC) (GLfloat u, GLfloat v);
+typedef void (GLAPIENTRY * PFNGLEVALCOORD2FVPROC) (const GLfloat *u);
+typedef void (GLAPIENTRY * PFNGLEVALMESH1PROC) (GLenum mode, GLint i1, GLint i2);
+typedef void (GLAPIENTRY * PFNGLEVALMESH2PROC) (GLenum mode, GLint i1, GLint i2, GLint j1, GLint j2);
+typedef void (GLAPIENTRY * PFNGLEVALPOINT1PROC) (GLint i);
+typedef void (GLAPIENTRY * PFNGLEVALPOINT2PROC) (GLint i, GLint j);
+typedef void (GLAPIENTRY * PFNGLFEEDBACKBUFFERPROC) (GLsizei size, GLenum type, GLfloat *buffer);
+typedef void (GLAPIENTRY * PFNGLFOGIPROC) (GLenum pname, GLint param);
+typedef void (GLAPIENTRY * PFNGLFOGIVPROC) (GLenum pname, const GLint *params);
+typedef void (GLAPIENTRY * PFNGLFRUSTUMPROC) (GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar);
+typedef GLuint (GLAPIENTRY * PFNGLGENLISTSPROC) (GLsizei range);
+typedef void (GLAPIENTRY * PFNGLGETBOOLEANVPROC) (GLenum pname, GLboolean *params);
+typedef void (GLAPIENTRY * PFNGLGETCLIPPLANEPROC) (GLenum plane, GLdouble *equation);
+typedef void (GLAPIENTRY * PFNGLGETDOUBLEVPROC) (GLenum pname, GLdouble *params);
+typedef void (GLAPIENTRY * PFNGLGETFLOATVPROC) (GLenum pname, GLfloat *params);
+typedef void (GLAPIENTRY * PFNGLGETLIGHTFVPROC) (GLenum light, GLenum pname, GLfloat *params);
+typedef void (GLAPIENTRY * PFNGLGETLIGHTIVPROC) (GLenum light, GLenum pname, GLint *params);
+typedef void (GLAPIENTRY * PFNGLGETMAPDVPROC) (GLenum target, GLenum query, GLdouble *v);
+typedef void (GLAPIENTRY * PFNGLGETMAPFVPROC) (GLenum target, GLenum query, GLfloat *v);
+typedef void (GLAPIENTRY * PFNGLGETMAPIVPROC) (GLenum target, GLenum query, GLint *v);
+typedef void (GLAPIENTRY * PFNGLGETMATERIALFVPROC) (GLenum face, GLenum pname, GLfloat *params);
+typedef void (GLAPIENTRY * PFNGLGETMATERIALIVPROC) (GLenum face, GLenum pname, GLint *params);
+typedef void (GLAPIENTRY * PFNGLGETPIXELMAPFVPROC) (GLenum map, GLfloat *values);
+typedef void (GLAPIENTRY * PFNGLGETPIXELMAPUIVPROC) (GLenum map, GLuint *values);
+typedef void (GLAPIENTRY * PFNGLGETPIXELMAPUSVPROC) (GLenum map, GLushort *values);
+typedef void (GLAPIENTRY * PFNGLGETPOINTERVPROC) (GLenum pname, GLvoid* *params);
+typedef void (GLAPIENTRY * PFNGLGETPOLYGONSTIPPLEPROC) (GLubyte *mask);
+typedef void (GLAPIENTRY * PFNGLGETTEXENVFVPROC) (GLenum target, GLenum pname, GLfloat *params);
+typedef void (GLAPIENTRY * PFNGLGETTEXENVIVPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (GLAPIENTRY * PFNGLGETTEXGENDVPROC) (GLenum coord, GLenum pname, GLdouble *params);
+typedef void (GLAPIENTRY * PFNGLGETTEXGENFVPROC) (GLenum coord, GLenum pname, GLfloat *params);
+typedef void (GLAPIENTRY * PFNGLGETTEXGENIVPROC) (GLenum coord, GLenum pname, GLint *params);
+typedef void (GLAPIENTRY * PFNGLGETTEXIMAGEPROC) (GLenum target, GLint level, GLenum format, GLenum type, GLvoid *pixels);
+typedef void (GLAPIENTRY * PFNGLGETTEXLEVELPARAMETERFVPROC) (GLenum target, GLint level, GLenum pname, GLfloat *params);
+typedef void (GLAPIENTRY * PFNGLGETTEXLEVELPARAMETERIVPROC) (GLenum target, GLint level, GLenum pname, GLint *params);
+typedef void (GLAPIENTRY * PFNGLGETTEXPARAMETERFVPROC) (GLenum target, GLenum pname, GLfloat *params);
+typedef void (GLAPIENTRY * PFNGLGETTEXPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (GLAPIENTRY * PFNGLINDEXMASKPROC) (GLuint mask);
+typedef void (GLAPIENTRY * PFNGLINDEXPOINTERPROC) (GLenum type, GLsizei stride, const GLvoid *pointer);
+typedef void (GLAPIENTRY * PFNGLINDEXDPROC) (GLdouble c);
+typedef void (GLAPIENTRY * PFNGLINDEXDVPROC) (const GLdouble *c);
+typedef void (GLAPIENTRY * PFNGLINDEXFPROC) (GLfloat c);
+typedef void (GLAPIENTRY * PFNGLINDEXFVPROC) (const GLfloat *c);
+typedef void (GLAPIENTRY * PFNGLINDEXIPROC) (GLint c);
+typedef void (GLAPIENTRY * PFNGLINDEXIVPROC) (const GLint *c);
+typedef void (GLAPIENTRY * PFNGLINDEXSPROC) (GLshort c);
+typedef void (GLAPIENTRY * PFNGLINDEXSVPROC) (const GLshort *c);
+typedef void (GLAPIENTRY * PFNGLINDEXUBPROC) (GLubyte c);
+typedef void (GLAPIENTRY * PFNGLINDEXUBVPROC) (const GLubyte *c);
+typedef void (GLAPIENTRY * PFNGLINITNAMESPROC) (void);
+typedef void (GLAPIENTRY * PFNGLINTERLEAVEDARRAYSPROC) (GLenum format, GLsizei stride, const GLvoid *pointer);
+typedef GLboolean (GLAPIENTRY * PFNGLISENABLEDPROC) (GLenum cap);
+typedef GLboolean (GLAPIENTRY * PFNGLISLISTPROC) (GLuint list);
+typedef GLboolean (GLAPIENTRY * PFNGLISTEXTUREPROC) (GLuint texture);
+typedef void (GLAPIENTRY * PFNGLLIGHTMODELIPROC) (GLenum pname, GLint param);
+typedef void (GLAPIENTRY * PFNGLLIGHTMODELIVPROC) (GLenum pname, const GLint *params);
+typedef void (GLAPIENTRY * PFNGLLIGHTIPROC) (GLenum light, GLenum pname, GLint param);
+typedef void (GLAPIENTRY * PFNGLLIGHTIVPROC) (GLenum light, GLenum pname, const GLint *params);
+typedef void (GLAPIENTRY * PFNGLLINESTIPPLEPROC) (GLint factor, GLushort pattern);
+typedef void (GLAPIENTRY * PFNGLLISTBASEPROC) (GLuint base);
+typedef void (GLAPIENTRY * PFNGLLOADMATRIXDPROC) (const GLdouble *m);
+typedef void (GLAPIENTRY * PFNGLLOADNAMEPROC) (GLuint name);
+typedef void (GLAPIENTRY * PFNGLMAP1DPROC) (GLenum target, GLdouble u1, GLdouble u2, GLint stride, GLint order, const GLdouble *points);
+typedef void (GLAPIENTRY * PFNGLMAP1FPROC) (GLenum target, GLfloat u1, GLfloat u2, GLint stride, GLint order, const GLfloat *points);
+typedef void (GLAPIENTRY * PFNGLMAP2DPROC) (GLenum target, GLdouble u1, GLdouble u2, GLint ustride, GLint uorder, GLdouble v1, GLdouble v2, GLint vstride, GLint vorder, const GLdouble *points);
+typedef void (GLAPIENTRY * PFNGLMAP2FPROC) (GLenum target, GLfloat u1, GLfloat u2, GLint ustride, GLint uorder, GLfloat v1, GLfloat v2, GLint vstride, GLint vorder, const GLfloat *points);
+typedef void (GLAPIENTRY * PFNGLMAPGRID1DPROC) (GLint un, GLdouble u1, GLdouble u2);
+typedef void (GLAPIENTRY * PFNGLMAPGRID1FPROC) (GLint un, GLfloat u1, GLfloat u2);
+typedef void (GLAPIENTRY * PFNGLMAPGRID2DPROC) (GLint un, GLdouble u1, GLdouble u2, GLint vn, GLdouble v1, GLdouble v2);
+typedef void (GLAPIENTRY * PFNGLMAPGRID2FPROC) (GLint un, GLfloat u1, GLfloat u2, GLint vn, GLfloat v1, GLfloat v2);
+typedef void (GLAPIENTRY * PFNGLMATERIALIPROC) (GLenum face, GLenum pname, GLint param);
+typedef void (GLAPIENTRY * PFNGLMATERIALIVPROC) (GLenum face, GLenum pname, const GLint *params);
+typedef void (GLAPIENTRY * PFNGLMULTMATRIXDPROC) (const GLdouble *m);
+typedef void (GLAPIENTRY * PFNGLNEWLISTPROC) (GLuint list, GLenum mode);
+typedef void (GLAPIENTRY * PFNGLNORMAL3BPROC) (GLbyte nx, GLbyte ny, GLbyte nz);
+typedef void (GLAPIENTRY * PFNGLNORMAL3BVPROC) (const GLbyte *v);
+typedef void (GLAPIENTRY * PFNGLNORMAL3DPROC) (GLdouble nx, GLdouble ny, GLdouble nz);
+typedef void (GLAPIENTRY * PFNGLNORMAL3DVPROC) (const GLdouble *v);
+typedef void (GLAPIENTRY * PFNGLNORMAL3FVPROC) (const GLfloat *v);
+typedef void (GLAPIENTRY * PFNGLNORMAL3IPROC) (GLint nx, GLint ny, GLint nz);
+typedef void (GLAPIENTRY * PFNGLNORMAL3IVPROC) (const GLint *v);
+typedef void (GLAPIENTRY * PFNGLNORMAL3SPROC) (GLshort nx, GLshort ny, GLshort nz);
+typedef void (GLAPIENTRY * PFNGLNORMAL3SVPROC) (const GLshort *v);
+typedef void (GLAPIENTRY * PFNGLORTHOPROC) (GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar);
+typedef void (GLAPIENTRY * PFNGLPASSTHROUGHPROC) (GLfloat token);
+typedef void (GLAPIENTRY * PFNGLPIXELMAPFVPROC) (GLenum map, GLsizei mapsize, const GLfloat *values);
+typedef void (GLAPIENTRY * PFNGLPIXELMAPUIVPROC) (GLenum map, GLsizei mapsize, const GLuint *values);
+typedef void (GLAPIENTRY * PFNGLPIXELMAPUSVPROC) (GLenum map, GLsizei mapsize, const GLushort *values);
+typedef void (GLAPIENTRY * PFNGLPIXELSTOREFPROC) (GLenum pname, GLfloat param);
+typedef void (GLAPIENTRY * PFNGLPIXELTRANSFERFPROC) (GLenum pname, GLfloat param);
+typedef void (GLAPIENTRY * PFNGLPIXELTRANSFERIPROC) (GLenum pname, GLint param);
+typedef void (GLAPIENTRY * PFNGLPIXELZOOMPROC) (GLfloat xfactor, GLfloat yfactor);
+typedef void (GLAPIENTRY * PFNGLPOLYGONMODEPROC) (GLenum face, GLenum mode);
+typedef void (GLAPIENTRY * PFNGLPOLYGONSTIPPLEPROC) (const GLubyte *mask);
+typedef void (GLAPIENTRY * PFNGLPOPATTRIBPROC) (void);
+typedef void (GLAPIENTRY * PFNGLPOPCLIENTATTRIBPROC) (void);
+typedef void (GLAPIENTRY * PFNGLPOPNAMEPROC) (void);
+typedef void (GLAPIENTRY * PFNGLPRIORITIZETEXTURESPROC) (GLsizei n, const GLuint *textures, const GLclampf *priorities);
+typedef void (GLAPIENTRY * PFNGLPUSHATTRIBPROC) (GLbitfield mask);
+typedef void (GLAPIENTRY * PFNGLPUSHCLIENTATTRIBPROC) (GLbitfield mask);
+typedef void (GLAPIENTRY * PFNGLPUSHNAMEPROC) (GLuint name);
+typedef void (GLAPIENTRY * PFNGLRASTERPOS2DPROC) (GLdouble x, GLdouble y);
+typedef void (GLAPIENTRY * PFNGLRASTERPOS2DVPROC) (const GLdouble *v);
+typedef void (GLAPIENTRY * PFNGLRASTERPOS2FPROC) (GLfloat x, GLfloat y);
+typedef void (GLAPIENTRY * PFNGLRASTERPOS2FVPROC) (const GLfloat *v);
+typedef void (GLAPIENTRY * PFNGLRASTERPOS2IPROC) (GLint x, GLint y);
+typedef void (GLAPIENTRY * PFNGLRASTERPOS2IVPROC) (const GLint *v);
+typedef void (GLAPIENTRY * PFNGLRASTERPOS2SPROC) (GLshort x, GLshort y);
+typedef void (GLAPIENTRY * PFNGLRASTERPOS2SVPROC) (const GLshort *v);
+typedef void (GLAPIENTRY * PFNGLRASTERPOS3DPROC) (GLdouble x, GLdouble y, GLdouble z);
+typedef void (GLAPIENTRY * PFNGLRASTERPOS3DVPROC) (const GLdouble *v);
+typedef void (GLAPIENTRY * PFNGLRASTERPOS3FPROC) (GLfloat x, GLfloat y, GLfloat z);
+typedef void (GLAPIENTRY * PFNGLRASTERPOS3FVPROC) (const GLfloat *v);
+typedef void (GLAPIENTRY * PFNGLRASTERPOS3IPROC) (GLint x, GLint y, GLint z);
+typedef void (GLAPIENTRY * PFNGLRASTERPOS3IVPROC) (const GLint *v);
+typedef void (GLAPIENTRY * PFNGLRASTERPOS3SPROC) (GLshort x, GLshort y, GLshort z);
+typedef void (GLAPIENTRY * PFNGLRASTERPOS3SVPROC) (const GLshort *v);
+typedef void (GLAPIENTRY * PFNGLRASTERPOS4DPROC) (GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+typedef void (GLAPIENTRY * PFNGLRASTERPOS4DVPROC) (const GLdouble *v);
+typedef void (GLAPIENTRY * PFNGLRASTERPOS4FPROC) (GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+typedef void (GLAPIENTRY * PFNGLRASTERPOS4FVPROC) (const GLfloat *v);
+typedef void (GLAPIENTRY * PFNGLRASTERPOS4IPROC) (GLint x, GLint y, GLint z, GLint w);
+typedef void (GLAPIENTRY * PFNGLRASTERPOS4IVPROC) (const GLint *v);
+typedef void (GLAPIENTRY * PFNGLRASTERPOS4SPROC) (GLshort x, GLshort y, GLshort z, GLshort w);
+typedef void (GLAPIENTRY * PFNGLRASTERPOS4SVPROC) (const GLshort *v);
+typedef void (GLAPIENTRY * PFNGLREADBUFFERPROC) (GLenum mode);
+typedef void (GLAPIENTRY * PFNGLRECTDPROC) (GLdouble x1, GLdouble y1, GLdouble x2, GLdouble y2);
+typedef void (GLAPIENTRY * PFNGLRECTDVPROC) (const GLdouble *v1, const GLdouble *v2);
+typedef void (GLAPIENTRY * PFNGLRECTFPROC) (GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2);
+typedef void (GLAPIENTRY * PFNGLRECTFVPROC) (const GLfloat *v1, const GLfloat *v2);
+typedef void (GLAPIENTRY * PFNGLRECTIPROC) (GLint x1, GLint y1, GLint x2, GLint y2);
+typedef void (GLAPIENTRY * PFNGLRECTIVPROC) (const GLint *v1, const GLint *v2);
+typedef void (GLAPIENTRY * PFNGLRECTSPROC) (GLshort x1, GLshort y1, GLshort x2, GLshort y2);
+typedef void (GLAPIENTRY * PFNGLRECTSVPROC) (const GLshort *v1, const GLshort *v2);
+typedef GLint (GLAPIENTRY * PFNGLRENDERMODEPROC) (GLenum mode);
+typedef void (GLAPIENTRY * PFNGLROTATEDPROC) (GLdouble angle, GLdouble x, GLdouble y, GLdouble z);
+typedef void (GLAPIENTRY * PFNGLSCALEDPROC) (GLdouble x, GLdouble y, GLdouble z);
+typedef void (GLAPIENTRY * PFNGLSELECTBUFFERPROC) (GLsizei size, GLuint *buffer);
+typedef void (GLAPIENTRY * PFNGLTEXCOORD1DPROC) (GLdouble s);
+typedef void (GLAPIENTRY * PFNGLTEXCOORD1DVPROC) (const GLdouble *v);
+typedef void (GLAPIENTRY * PFNGLTEXCOORD1FPROC) (GLfloat s);
+typedef void (GLAPIENTRY * PFNGLTEXCOORD1FVPROC) (const GLfloat *v);
+typedef void (GLAPIENTRY * PFNGLTEXCOORD1IPROC) (GLint s);
+typedef void (GLAPIENTRY * PFNGLTEXCOORD1IVPROC) (const GLint *v);
+typedef void (GLAPIENTRY * PFNGLTEXCOORD1SPROC) (GLshort s);
+typedef void (GLAPIENTRY * PFNGLTEXCOORD1SVPROC) (const GLshort *v);
+typedef void (GLAPIENTRY * PFNGLTEXCOORD2DPROC) (GLdouble s, GLdouble t);
+typedef void (GLAPIENTRY * PFNGLTEXCOORD2DVPROC) (const GLdouble *v);
+typedef void (GLAPIENTRY * PFNGLTEXCOORD2FPROC) (GLfloat s, GLfloat t);
+typedef void (GLAPIENTRY * PFNGLTEXCOORD2FVPROC) (const GLfloat *v);
+typedef void (GLAPIENTRY * PFNGLTEXCOORD2IPROC) (GLint s, GLint t);
+typedef void (GLAPIENTRY * PFNGLTEXCOORD2IVPROC) (const GLint *v);
+typedef void (GLAPIENTRY * PFNGLTEXCOORD2SPROC) (GLshort s, GLshort t);
+typedef void (GLAPIENTRY * PFNGLTEXCOORD2SVPROC) (const GLshort *v);
+typedef void (GLAPIENTRY * PFNGLTEXCOORD3DPROC) (GLdouble s, GLdouble t, GLdouble r);
+typedef void (GLAPIENTRY * PFNGLTEXCOORD3DVPROC) (const GLdouble *v);
+typedef void (GLAPIENTRY * PFNGLTEXCOORD3FPROC) (GLfloat s, GLfloat t, GLfloat r);
+typedef void (GLAPIENTRY * PFNGLTEXCOORD3FVPROC) (const GLfloat *v);
+typedef void (GLAPIENTRY * PFNGLTEXCOORD3IPROC) (GLint s, GLint t, GLint r);
+typedef void (GLAPIENTRY * PFNGLTEXCOORD3IVPROC) (const GLint *v);
+typedef void (GLAPIENTRY * PFNGLTEXCOORD3SPROC) (GLshort s, GLshort t, GLshort r);
+typedef void (GLAPIENTRY * PFNGLTEXCOORD3SVPROC) (const GLshort *v);
+typedef void (GLAPIENTRY * PFNGLTEXCOORD4DPROC) (GLdouble s, GLdouble t, GLdouble r, GLdouble q);
+typedef void (GLAPIENTRY * PFNGLTEXCOORD4DVPROC) (const GLdouble *v);
+typedef void (GLAPIENTRY * PFNGLTEXCOORD4FPROC) (GLfloat s, GLfloat t, GLfloat r, GLfloat q);
+typedef void (GLAPIENTRY * PFNGLTEXCOORD4FVPROC) (const GLfloat *v);
+typedef void (GLAPIENTRY * PFNGLTEXCOORD4IPROC) (GLint s, GLint t, GLint r, GLint q);
+typedef void (GLAPIENTRY * PFNGLTEXCOORD4IVPROC) (const GLint *v);
+typedef void (GLAPIENTRY * PFNGLTEXCOORD4SPROC) (GLshort s, GLshort t, GLshort r, GLshort q);
+typedef void (GLAPIENTRY * PFNGLTEXCOORD4SVPROC) (const GLshort *v);
+typedef void (GLAPIENTRY * PFNGLTEXENVIPROC) (GLenum target, GLenum pname, GLint param);
+typedef void (GLAPIENTRY * PFNGLTEXENVIVPROC) (GLenum target, GLenum pname, const GLint *params);
+typedef void (GLAPIENTRY * PFNGLTEXGENDPROC) (GLenum coord, GLenum pname, GLdouble param);
+typedef void (GLAPIENTRY * PFNGLTEXGENDVPROC) (GLenum coord, GLenum pname, const GLdouble *params);
+typedef void (GLAPIENTRY * PFNGLTEXGENFPROC) (GLenum coord, GLenum pname, GLfloat param);
+typedef void (GLAPIENTRY * PFNGLTEXGENFVPROC) (GLenum coord, GLenum pname, const GLfloat *params);
+typedef void (GLAPIENTRY * PFNGLTEXGENIPROC) (GLenum coord, GLenum pname, GLint param);
+typedef void (GLAPIENTRY * PFNGLTEXGENIVPROC) (GLenum coord, GLenum pname, const GLint *params);
+typedef void (GLAPIENTRY * PFNGLTEXIMAGE1DPROC) (GLenum target, GLint level, GLint internalformat, GLsizei width, GLint border, GLenum format, GLenum type, const GLvoid *pixels);
+typedef void (GLAPIENTRY * PFNGLTEXPARAMETERFVPROC) (GLenum target, GLenum pname, const GLfloat *params);
+typedef void (GLAPIENTRY * PFNGLTEXPARAMETERIPROC) (GLenum target, GLenum pname, GLint param);
+typedef void (GLAPIENTRY * PFNGLTEXPARAMETERIVPROC) (GLenum target, GLenum pname, const GLint *params);
+typedef void (GLAPIENTRY * PFNGLTEXSUBIMAGE1DPROC) (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const GLvoid *pixels);
+typedef void (GLAPIENTRY * PFNGLTRANSLATEDPROC) (GLdouble x, GLdouble y, GLdouble z);
+typedef void (GLAPIENTRY * PFNGLVERTEX2DPROC) (GLdouble x, GLdouble y);
+typedef void (GLAPIENTRY * PFNGLVERTEX2DVPROC) (const GLdouble *v);
+typedef void (GLAPIENTRY * PFNGLVERTEX2FPROC) (GLfloat x, GLfloat y);
+typedef void (GLAPIENTRY * PFNGLVERTEX2FVPROC) (const GLfloat *v);
+typedef void (GLAPIENTRY * PFNGLVERTEX2IPROC) (GLint x, GLint y);
+typedef void (GLAPIENTRY * PFNGLVERTEX2IVPROC) (const GLint *v);
+typedef void (GLAPIENTRY * PFNGLVERTEX2SPROC) (GLshort x, GLshort y);
+typedef void (GLAPIENTRY * PFNGLVERTEX2SVPROC) (const GLshort *v);
+typedef void (GLAPIENTRY * PFNGLVERTEX3DPROC) (GLdouble x, GLdouble y, GLdouble z);
+typedef void (GLAPIENTRY * PFNGLVERTEX3DVPROC) (const GLdouble *v);
+typedef void (GLAPIENTRY * PFNGLVERTEX3FPROC) (GLfloat x, GLfloat y, GLfloat z);
+typedef void (GLAPIENTRY * PFNGLVERTEX3FVPROC) (const GLfloat *v);
+typedef void (GLAPIENTRY * PFNGLVERTEX3IPROC) (GLint x, GLint y, GLint z);
+typedef void (GLAPIENTRY * PFNGLVERTEX3IVPROC) (const GLint *v);
+typedef void (GLAPIENTRY * PFNGLVERTEX3SPROC) (GLshort x, GLshort y, GLshort z);
+typedef void (GLAPIENTRY * PFNGLVERTEX3SVPROC) (const GLshort *v);
+typedef void (GLAPIENTRY * PFNGLVERTEX4DPROC) (GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+typedef void (GLAPIENTRY * PFNGLVERTEX4DVPROC) (const GLdouble *v);
+typedef void (GLAPIENTRY * PFNGLVERTEX4FPROC) (GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+typedef void (GLAPIENTRY * PFNGLVERTEX4FVPROC) (const GLfloat *v);
+typedef void (GLAPIENTRY * PFNGLVERTEX4IPROC) (GLint x, GLint y, GLint z, GLint w);
+typedef void (GLAPIENTRY * PFNGLVERTEX4IVPROC) (const GLint *v);
+typedef void (GLAPIENTRY * PFNGLVERTEX4SPROC) (GLshort x, GLshort y, GLshort z, GLshort w);
+typedef void (GLAPIENTRY * PFNGLVERTEX4SVPROC) (const GLshort *v);
+
+#define glAccum GLEW_GET_FUN(__glewAccum)
+#define glAreTexturesResident GLEW_GET_FUN(__glewAreTexturesResident)
+#define glArrayElement GLEW_GET_FUN(__glewArrayElement)
+#define glBegin GLEW_GET_FUN(__glewBegin)
+#define glBitmap GLEW_GET_FUN(__glewBitmap)
+#define glCallList GLEW_GET_FUN(__glewCallList)
+#define glCallLists GLEW_GET_FUN(__glewCallLists)
+#define glClearAccum GLEW_GET_FUN(__glewClearAccum)
+#define glClearDepth GLEW_GET_FUN(__glewClearDepth)
+#define glClearIndex GLEW_GET_FUN(__glewClearIndex)
+#define glClipPlane GLEW_GET_FUN(__glewClipPlane)
+#define glColor3b GLEW_GET_FUN(__glewColor3b)
+#define glColor3bv GLEW_GET_FUN(__glewColor3bv)
+#define glColor3d GLEW_GET_FUN(__glewColor3d)
+#define glColor3dv GLEW_GET_FUN(__glewColor3dv)
+#define glColor3f GLEW_GET_FUN(__glewColor3f)
+#define glColor3fv GLEW_GET_FUN(__glewColor3fv)
+#define glColor3i GLEW_GET_FUN(__glewColor3i)
+#define glColor3iv GLEW_GET_FUN(__glewColor3iv)
+#define glColor3s GLEW_GET_FUN(__glewColor3s)
+#define glColor3sv GLEW_GET_FUN(__glewColor3sv)
+#define glColor3ub GLEW_GET_FUN(__glewColor3ub)
+#define glColor3ubv GLEW_GET_FUN(__glewColor3ubv)
+#define glColor3ui GLEW_GET_FUN(__glewColor3ui)
+#define glColor3uiv GLEW_GET_FUN(__glewColor3uiv)
+#define glColor3us GLEW_GET_FUN(__glewColor3us)
+#define glColor3usv GLEW_GET_FUN(__glewColor3usv)
+#define glColor4b GLEW_GET_FUN(__glewColor4b)
+#define glColor4bv GLEW_GET_FUN(__glewColor4bv)
+#define glColor4d GLEW_GET_FUN(__glewColor4d)
+#define glColor4dv GLEW_GET_FUN(__glewColor4dv)
+#define glColor4fv GLEW_GET_FUN(__glewColor4fv)
+#define glColor4i GLEW_GET_FUN(__glewColor4i)
+#define glColor4iv GLEW_GET_FUN(__glewColor4iv)
+#define glColor4s GLEW_GET_FUN(__glewColor4s)
+#define glColor4sv GLEW_GET_FUN(__glewColor4sv)
+#define glColor4ub GLEW_GET_FUN(__glewColor4ub)
+#define glColor4ubv GLEW_GET_FUN(__glewColor4ubv)
+#define glColor4ui GLEW_GET_FUN(__glewColor4ui)
+#define glColor4uiv GLEW_GET_FUN(__glewColor4uiv)
+#define glColor4us GLEW_GET_FUN(__glewColor4us)
+#define glColor4usv GLEW_GET_FUN(__glewColor4usv)
+#define glColorMaterial GLEW_GET_FUN(__glewColorMaterial)
+#define glCopyPixels GLEW_GET_FUN(__glewCopyPixels)
+#define glCopyTexImage1D GLEW_GET_FUN(__glewCopyTexImage1D)
+#define glCopyTexSubImage1D GLEW_GET_FUN(__glewCopyTexSubImage1D)
+#define glDeleteLists GLEW_GET_FUN(__glewDeleteLists)
+#define glDepthRange GLEW_GET_FUN(__glewDepthRange)
+#define glDrawBuffer GLEW_GET_FUN(__glewDrawBuffer)
+#define glDrawPixels GLEW_GET_FUN(__glewDrawPixels)
+#define glEdgeFlag GLEW_GET_FUN(__glewEdgeFlag)
+#define glEdgeFlagPointer GLEW_GET_FUN(__glewEdgeFlagPointer)
+#define glEdgeFlagv GLEW_GET_FUN(__glewEdgeFlagv)
+#define glEnd GLEW_GET_FUN(__glewEnd)
+#define glEndList GLEW_GET_FUN(__glewEndList)
+#define glEvalCoord1d GLEW_GET_FUN(__glewEvalCoord1d)
+#define glEvalCoord1dv GLEW_GET_FUN(__glewEvalCoord1dv)
+#define glEvalCoord1f GLEW_GET_FUN(__glewEvalCoord1f)
+#define glEvalCoord1fv GLEW_GET_FUN(__glewEvalCoord1fv)
+#define glEvalCoord2d GLEW_GET_FUN(__glewEvalCoord2d)
+#define glEvalCoord2dv GLEW_GET_FUN(__glewEvalCoord2dv)
+#define glEvalCoord2f GLEW_GET_FUN(__glewEvalCoord2f)
+#define glEvalCoord2fv GLEW_GET_FUN(__glewEvalCoord2fv)
+#define glEvalMesh1 GLEW_GET_FUN(__glewEvalMesh1)
+#define glEvalMesh2 GLEW_GET_FUN(__glewEvalMesh2)
+#define glEvalPoint1 GLEW_GET_FUN(__glewEvalPoint1)
+#define glEvalPoint2 GLEW_GET_FUN(__glewEvalPoint2)
+#define glFeedbackBuffer GLEW_GET_FUN(__glewFeedbackBuffer)
+#define glFogi GLEW_GET_FUN(__glewFogi)
+#define glFogiv GLEW_GET_FUN(__glewFogiv)
+#define glFrustum GLEW_GET_FUN(__glewFrustum)
+#define glGenLists GLEW_GET_FUN(__glewGenLists)
+#define glGetBooleanv GLEW_GET_FUN(__glewGetBooleanv)
+#define glGetClipPlane GLEW_GET_FUN(__glewGetClipPlane)
+#define glGetDoublev GLEW_GET_FUN(__glewGetDoublev)
+#define glGetFloatv GLEW_GET_FUN(__glewGetFloatv)
+#define glGetLightfv GLEW_GET_FUN(__glewGetLightfv)
+#define glGetLightiv GLEW_GET_FUN(__glewGetLightiv)
+#define glGetMapdv GLEW_GET_FUN(__glewGetMapdv)
+#define glGetMapfv GLEW_GET_FUN(__glewGetMapfv)
+#define glGetMapiv GLEW_GET_FUN(__glewGetMapiv)
+#define glGetMaterialfv GLEW_GET_FUN(__glewGetMaterialfv)
+#define glGetMaterialiv GLEW_GET_FUN(__glewGetMaterialiv)
+#define glGetPixelMapfv GLEW_GET_FUN(__glewGetPixelMapfv)
+#define glGetPixelMapuiv GLEW_GET_FUN(__glewGetPixelMapuiv)
+#define glGetPixelMapusv GLEW_GET_FUN(__glewGetPixelMapusv)
+#define glGetPointerv GLEW_GET_FUN(__glewGetPointerv)
+#define glGetPolygonStipple GLEW_GET_FUN(__glewGetPolygonStipple)
+#define glGetTexEnvfv GLEW_GET_FUN(__glewGetTexEnvfv)
+#define glGetTexEnviv GLEW_GET_FUN(__glewGetTexEnviv)
+#define glGetTexGendv GLEW_GET_FUN(__glewGetTexGendv)
+#define glGetTexGenfv GLEW_GET_FUN(__glewGetTexGenfv)
+#define glGetTexGeniv GLEW_GET_FUN(__glewGetTexGeniv)
+#define glGetTexImage GLEW_GET_FUN(__glewGetTexImage)
+#define glGetTexLevelParameterfv GLEW_GET_FUN(__glewGetTexLevelParameterfv)
+#define glGetTexLevelParameteriv GLEW_GET_FUN(__glewGetTexLevelParameteriv)
+#define glGetTexParameterfv GLEW_GET_FUN(__glewGetTexParameterfv)
+#define glGetTexParameteriv GLEW_GET_FUN(__glewGetTexParameteriv)
+#define glIndexMask GLEW_GET_FUN(__glewIndexMask)
+#define glIndexPointer GLEW_GET_FUN(__glewIndexPointer)
+#define glIndexd GLEW_GET_FUN(__glewIndexd)
+#define glIndexdv GLEW_GET_FUN(__glewIndexdv)
+#define glIndexf GLEW_GET_FUN(__glewIndexf)
+#define glIndexfv GLEW_GET_FUN(__glewIndexfv)
+#define glIndexi GLEW_GET_FUN(__glewIndexi)
+#define glIndexiv GLEW_GET_FUN(__glewIndexiv)
+#define glIndexs GLEW_GET_FUN(__glewIndexs)
+#define glIndexsv GLEW_GET_FUN(__glewIndexsv)
+#define glIndexub GLEW_GET_FUN(__glewIndexub)
+#define glIndexubv GLEW_GET_FUN(__glewIndexubv)
+#define glInitNames GLEW_GET_FUN(__glewInitNames)
+#define glInterleavedArrays GLEW_GET_FUN(__glewInterleavedArrays)
+#define glIsEnabled GLEW_GET_FUN(__glewIsEnabled)
+#define glIsList GLEW_GET_FUN(__glewIsList)
+#define glIsTexture GLEW_GET_FUN(__glewIsTexture)
+#define glLightModeli GLEW_GET_FUN(__glewLightModeli)
+#define glLightModeliv GLEW_GET_FUN(__glewLightModeliv)
+#define glLighti GLEW_GET_FUN(__glewLighti)
+#define glLightiv GLEW_GET_FUN(__glewLightiv)
+#define glLineStipple GLEW_GET_FUN(__glewLineStipple)
+#define glListBase GLEW_GET_FUN(__glewListBase)
+#define glLoadMatrixd GLEW_GET_FUN(__glewLoadMatrixd)
+#define glLoadName GLEW_GET_FUN(__glewLoadName)
+#define glMap1d GLEW_GET_FUN(__glewMap1d)
+#define glMap1f GLEW_GET_FUN(__glewMap1f)
+#define glMap2d GLEW_GET_FUN(__glewMap2d)
+#define glMap2f GLEW_GET_FUN(__glewMap2f)
+#define glMapGrid1d GLEW_GET_FUN(__glewMapGrid1d)
+#define glMapGrid1f GLEW_GET_FUN(__glewMapGrid1f)
+#define glMapGrid2d GLEW_GET_FUN(__glewMapGrid2d)
+#define glMapGrid2f GLEW_GET_FUN(__glewMapGrid2f)
+#define glMateriali GLEW_GET_FUN(__glewMateriali)
+#define glMaterialiv GLEW_GET_FUN(__glewMaterialiv)
+#define glMultMatrixd GLEW_GET_FUN(__glewMultMatrixd)
+#define glNewList GLEW_GET_FUN(__glewNewList)
+#define glNormal3b GLEW_GET_FUN(__glewNormal3b)
+#define glNormal3bv GLEW_GET_FUN(__glewNormal3bv)
+#define glNormal3d GLEW_GET_FUN(__glewNormal3d)
+#define glNormal3dv GLEW_GET_FUN(__glewNormal3dv)
+#define glNormal3fv GLEW_GET_FUN(__glewNormal3fv)
+#define glNormal3i GLEW_GET_FUN(__glewNormal3i)
+#define glNormal3iv GLEW_GET_FUN(__glewNormal3iv)
+#define glNormal3s GLEW_GET_FUN(__glewNormal3s)
+#define glNormal3sv GLEW_GET_FUN(__glewNormal3sv)
+#define glOrtho GLEW_GET_FUN(__glewOrtho)
+#define glPassThrough GLEW_GET_FUN(__glewPassThrough)
+#define glPixelMapfv GLEW_GET_FUN(__glewPixelMapfv)
+#define glPixelMapuiv GLEW_GET_FUN(__glewPixelMapuiv)
+#define glPixelMapusv GLEW_GET_FUN(__glewPixelMapusv)
+#define glPixelStoref GLEW_GET_FUN(__glewPixelStoref)
+#define glPixelTransferf GLEW_GET_FUN(__glewPixelTransferf)
+#define glPixelTransferi GLEW_GET_FUN(__glewPixelTransferi)
+#define glPixelZoom GLEW_GET_FUN(__glewPixelZoom)
+#define glPolygonMode GLEW_GET_FUN(__glewPolygonMode)
+#define glPolygonStipple GLEW_GET_FUN(__glewPolygonStipple)
+#define glPopAttrib GLEW_GET_FUN(__glewPopAttrib)
+#define glPopClientAttrib GLEW_GET_FUN(__glewPopClientAttrib)
+#define glPopName GLEW_GET_FUN(__glewPopName)
+#define glPrioritizeTextures GLEW_GET_FUN(__glewPrioritizeTextures)
+#define glPushAttrib GLEW_GET_FUN(__glewPushAttrib)
+#define glPushClientAttrib GLEW_GET_FUN(__glewPushClientAttrib)
+#define glPushName GLEW_GET_FUN(__glewPushName)
+#define glRasterPos2d GLEW_GET_FUN(__glewRasterPos2d)
+#define glRasterPos2dv GLEW_GET_FUN(__glewRasterPos2dv)
+#define glRasterPos2f GLEW_GET_FUN(__glewRasterPos2f)
+#define glRasterPos2fv GLEW_GET_FUN(__glewRasterPos2fv)
+#define glRasterPos2i GLEW_GET_FUN(__glewRasterPos2i)
+#define glRasterPos2iv GLEW_GET_FUN(__glewRasterPos2iv)
+#define glRasterPos2s GLEW_GET_FUN(__glewRasterPos2s)
+#define glRasterPos2sv GLEW_GET_FUN(__glewRasterPos2sv)
+#define glRasterPos3d GLEW_GET_FUN(__glewRasterPos3d)
+#define glRasterPos3dv GLEW_GET_FUN(__glewRasterPos3dv)
+#define glRasterPos3f GLEW_GET_FUN(__glewRasterPos3f)
+#define glRasterPos3fv GLEW_GET_FUN(__glewRasterPos3fv)
+#define glRasterPos3i GLEW_GET_FUN(__glewRasterPos3i)
+#define glRasterPos3iv GLEW_GET_FUN(__glewRasterPos3iv)
+#define glRasterPos3s GLEW_GET_FUN(__glewRasterPos3s)
+#define glRasterPos3sv GLEW_GET_FUN(__glewRasterPos3sv)
+#define glRasterPos4d GLEW_GET_FUN(__glewRasterPos4d)
+#define glRasterPos4dv GLEW_GET_FUN(__glewRasterPos4dv)
+#define glRasterPos4f GLEW_GET_FUN(__glewRasterPos4f)
+#define glRasterPos4fv GLEW_GET_FUN(__glewRasterPos4fv)
+#define glRasterPos4i GLEW_GET_FUN(__glewRasterPos4i)
+#define glRasterPos4iv GLEW_GET_FUN(__glewRasterPos4iv)
+#define glRasterPos4s GLEW_GET_FUN(__glewRasterPos4s)
+#define glRasterPos4sv GLEW_GET_FUN(__glewRasterPos4sv)
+#define glReadBuffer GLEW_GET_FUN(__glewReadBuffer)
+#define glRectd GLEW_GET_FUN(__glewRectd)
+#define glRectdv GLEW_GET_FUN(__glewRectdv)
+#define glRectf GLEW_GET_FUN(__glewRectf)
+#define glRectfv GLEW_GET_FUN(__glewRectfv)
+#define glRecti GLEW_GET_FUN(__glewRecti)
+#define glRectiv GLEW_GET_FUN(__glewRectiv)
+#define glRects GLEW_GET_FUN(__glewRects)
+#define glRectsv GLEW_GET_FUN(__glewRectsv)
+#define glRenderMode GLEW_GET_FUN(__glewRenderMode)
+#define glRotated GLEW_GET_FUN(__glewRotated)
+#define glScaled GLEW_GET_FUN(__glewScaled)
+#define glSelectBuffer GLEW_GET_FUN(__glewSelectBuffer)
+#define glTexCoord1d GLEW_GET_FUN(__glewTexCoord1d)
+#define glTexCoord1dv GLEW_GET_FUN(__glewTexCoord1dv)
+#define glTexCoord1f GLEW_GET_FUN(__glewTexCoord1f)
+#define glTexCoord1fv GLEW_GET_FUN(__glewTexCoord1fv)
+#define glTexCoord1i GLEW_GET_FUN(__glewTexCoord1i)
+#define glTexCoord1iv GLEW_GET_FUN(__glewTexCoord1iv)
+#define glTexCoord1s GLEW_GET_FUN(__glewTexCoord1s)
+#define glTexCoord1sv GLEW_GET_FUN(__glewTexCoord1sv)
+#define glTexCoord2d GLEW_GET_FUN(__glewTexCoord2d)
+#define glTexCoord2dv GLEW_GET_FUN(__glewTexCoord2dv)
+#define glTexCoord2f GLEW_GET_FUN(__glewTexCoord2f)
+#define glTexCoord2fv GLEW_GET_FUN(__glewTexCoord2fv)
+#define glTexCoord2i GLEW_GET_FUN(__glewTexCoord2i)
+#define glTexCoord2iv GLEW_GET_FUN(__glewTexCoord2iv)
+#define glTexCoord2s GLEW_GET_FUN(__glewTexCoord2s)
+#define glTexCoord2sv GLEW_GET_FUN(__glewTexCoord2sv)
+#define glTexCoord3d GLEW_GET_FUN(__glewTexCoord3d)
+#define glTexCoord3dv GLEW_GET_FUN(__glewTexCoord3dv)
+#define glTexCoord3f GLEW_GET_FUN(__glewTexCoord3f)
+#define glTexCoord3fv GLEW_GET_FUN(__glewTexCoord3fv)
+#define glTexCoord3i GLEW_GET_FUN(__glewTexCoord3i)
+#define glTexCoord3iv GLEW_GET_FUN(__glewTexCoord3iv)
+#define glTexCoord3s GLEW_GET_FUN(__glewTexCoord3s)
+#define glTexCoord3sv GLEW_GET_FUN(__glewTexCoord3sv)
+#define glTexCoord4d GLEW_GET_FUN(__glewTexCoord4d)
+#define glTexCoord4dv GLEW_GET_FUN(__glewTexCoord4dv)
+#define glTexCoord4f GLEW_GET_FUN(__glewTexCoord4f)
+#define glTexCoord4fv GLEW_GET_FUN(__glewTexCoord4fv)
+#define glTexCoord4i GLEW_GET_FUN(__glewTexCoord4i)
+#define glTexCoord4iv GLEW_GET_FUN(__glewTexCoord4iv)
+#define glTexCoord4s GLEW_GET_FUN(__glewTexCoord4s)
+#define glTexCoord4sv GLEW_GET_FUN(__glewTexCoord4sv)
+#define glTexEnvi GLEW_GET_FUN(__glewTexEnvi)
+#define glTexEnviv GLEW_GET_FUN(__glewTexEnviv)
+#define glTexGend GLEW_GET_FUN(__glewTexGend)
+#define glTexGendv GLEW_GET_FUN(__glewTexGendv)
+#define glTexGenf GLEW_GET_FUN(__glewTexGenf)
+#define glTexGenfv GLEW_GET_FUN(__glewTexGenfv)
+#define glTexGeni GLEW_GET_FUN(__glewTexGeni)
+#define glTexGeniv GLEW_GET_FUN(__glewTexGeniv)
+#define glTexImage1D GLEW_GET_FUN(__glewTexImage1D)
+#define glTexParameterfv GLEW_GET_FUN(__glewTexParameterfv)
+#define glTexParameteri GLEW_GET_FUN(__glewTexParameteri)
+#define glTexParameteriv GLEW_GET_FUN(__glewTexParameteriv)
+#define glTexSubImage1D GLEW_GET_FUN(__glewTexSubImage1D)
+#define glTranslated GLEW_GET_FUN(__glewTranslated)
+#define glVertex2d GLEW_GET_FUN(__glewVertex2d)
+#define glVertex2dv GLEW_GET_FUN(__glewVertex2dv)
+#define glVertex2f GLEW_GET_FUN(__glewVertex2f)
+#define glVertex2fv GLEW_GET_FUN(__glewVertex2fv)
+#define glVertex2i GLEW_GET_FUN(__glewVertex2i)
+#define glVertex2iv GLEW_GET_FUN(__glewVertex2iv)
+#define glVertex2s GLEW_GET_FUN(__glewVertex2s)
+#define glVertex2sv GLEW_GET_FUN(__glewVertex2sv)
+#define glVertex3d GLEW_GET_FUN(__glewVertex3d)
+#define glVertex3dv GLEW_GET_FUN(__glewVertex3dv)
+#define glVertex3f GLEW_GET_FUN(__glewVertex3f)
+#define glVertex3fv GLEW_GET_FUN(__glewVertex3fv)
+#define glVertex3i GLEW_GET_FUN(__glewVertex3i)
+#define glVertex3iv GLEW_GET_FUN(__glewVertex3iv)
+#define glVertex3s GLEW_GET_FUN(__glewVertex3s)
+#define glVertex3sv GLEW_GET_FUN(__glewVertex3sv)
+#define glVertex4d GLEW_GET_FUN(__glewVertex4d)
+#define glVertex4dv GLEW_GET_FUN(__glewVertex4dv)
+#define glVertex4f GLEW_GET_FUN(__glewVertex4f)
+#define glVertex4fv GLEW_GET_FUN(__glewVertex4fv)
+#define glVertex4i GLEW_GET_FUN(__glewVertex4i)
+#define glVertex4iv GLEW_GET_FUN(__glewVertex4iv)
+#define glVertex4s GLEW_GET_FUN(__glewVertex4s)
+#define glVertex4sv GLEW_GET_FUN(__glewVertex4sv)
+
+#define GLEW_VERSION_1_1 GLEW_GET_VAR(__GLEW_VERSION_1_1)
+#endif /* !GL_VERSION_1_1 */
+
+/* ----------------------------- GL_VERSION_1_2 ---------------------------- */
+
+#if !defined(GL_VERSION_1_2)
+#define GL_VERSION_1_2 1
+
+#define GL_SMOOTH_POINT_SIZE_RANGE 0x0B12
+#define GL_SMOOTH_POINT_SIZE_GRANULARITY 0x0B13
+#define GL_SMOOTH_LINE_WIDTH_RANGE 0x0B22
+#define GL_SMOOTH_LINE_WIDTH_GRANULARITY 0x0B23
+#define GL_UNSIGNED_BYTE_3_3_2 0x8032
+#define GL_UNSIGNED_SHORT_4_4_4_4 0x8033
+#define GL_UNSIGNED_SHORT_5_5_5_1 0x8034
+#define GL_UNSIGNED_INT_8_8_8_8 0x8035
+#define GL_UNSIGNED_INT_10_10_10_2 0x8036
+#define GL_RESCALE_NORMAL 0x803A
+#define GL_TEXTURE_BINDING_3D 0x806A
+#define GL_PACK_SKIP_IMAGES 0x806B
+#define GL_PACK_IMAGE_HEIGHT 0x806C
+#define GL_UNPACK_SKIP_IMAGES 0x806D
+#define GL_UNPACK_IMAGE_HEIGHT 0x806E
+#define GL_TEXTURE_3D 0x806F
+#define GL_PROXY_TEXTURE_3D 0x8070
+#define GL_TEXTURE_DEPTH 0x8071
+#define GL_TEXTURE_WRAP_R 0x8072
+#define GL_MAX_3D_TEXTURE_SIZE 0x8073
+#define GL_BGR 0x80E0
+#define GL_BGRA 0x80E1
+#define GL_MAX_ELEMENTS_VERTICES 0x80E8
+#define GL_MAX_ELEMENTS_INDICES 0x80E9
+#define GL_CLAMP_TO_EDGE 0x812F
+#define GL_TEXTURE_MIN_LOD 0x813A
+#define GL_TEXTURE_MAX_LOD 0x813B
+#define GL_TEXTURE_BASE_LEVEL 0x813C
+#define GL_TEXTURE_MAX_LEVEL 0x813D
+#define GL_LIGHT_MODEL_COLOR_CONTROL 0x81F8
+#define GL_SINGLE_COLOR 0x81F9
+#define GL_SEPARATE_SPECULAR_COLOR 0x81FA
+#define GL_UNSIGNED_BYTE_2_3_3_REV 0x8362
+#define GL_UNSIGNED_SHORT_5_6_5 0x8363
+#define GL_UNSIGNED_SHORT_5_6_5_REV 0x8364
+#define GL_UNSIGNED_SHORT_4_4_4_4_REV 0x8365
+#define GL_UNSIGNED_SHORT_1_5_5_5_REV 0x8366
+#define GL_UNSIGNED_INT_8_8_8_8_REV 0x8367
+#define GL_UNSIGNED_INT_2_10_10_10_REV 0x8368
+#define GL_ALIASED_POINT_SIZE_RANGE 0x846D
+#define GL_ALIASED_LINE_WIDTH_RANGE 0x846E
+
+typedef void (GLAPIENTRY * PFNGLCOPYTEXSUBIMAGE3DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+typedef void (GLAPIENTRY * PFNGLDRAWRANGEELEMENTSPROC) (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid *indices);
+typedef void (GLAPIENTRY * PFNGLTEXIMAGE3DPROC) (GLenum target, GLint level, GLint internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid *pixels);
+typedef void (GLAPIENTRY * PFNGLTEXSUBIMAGE3DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid *pixels);
+
+#define glCopyTexSubImage3D GLEW_GET_FUN(__glewCopyTexSubImage3D)
+#define glDrawRangeElements GLEW_GET_FUN(__glewDrawRangeElements)
+#define glTexImage3D GLEW_GET_FUN(__glewTexImage3D)
+#define glTexSubImage3D GLEW_GET_FUN(__glewTexSubImage3D)
+
+#define GLEW_VERSION_1_2 GLEW_GET_VAR(__GLEW_VERSION_1_2)
+
+#endif /* !GL_VERSION_1_2 */
+
+/* ---------------------------- GL_VERSION_1_2_1 --------------------------- */
+
+#if !defined(GL_VERSION_1_2_1)
+#define GL_VERSION_1_2_1 1
+
+#define GLEW_VERSION_1_2_1 GLEW_GET_VAR(__GLEW_VERSION_1_2_1)
+
+#endif /* !GL_VERSION_1_2_1 */
+
+/* ----------------------------- GL_VERSION_1_3 ---------------------------- */
+
+#if !defined(GL_VERSION_1_3)
+#define GL_VERSION_1_3 1
+
+#define GL_MULTISAMPLE 0x809D
+#define GL_SAMPLE_ALPHA_TO_COVERAGE 0x809E
+#define GL_SAMPLE_ALPHA_TO_ONE 0x809F
+#define GL_SAMPLE_COVERAGE 0x80A0
+#define GL_SAMPLE_BUFFERS 0x80A8
+#define GL_SAMPLES 0x80A9
+#define GL_SAMPLE_COVERAGE_VALUE 0x80AA
+#define GL_SAMPLE_COVERAGE_INVERT 0x80AB
+#define GL_CLAMP_TO_BORDER 0x812D
+#define GL_TEXTURE0 0x84C0
+#define GL_TEXTURE1 0x84C1
+#define GL_TEXTURE2 0x84C2
+#define GL_TEXTURE3 0x84C3
+#define GL_TEXTURE4 0x84C4
+#define GL_TEXTURE5 0x84C5
+#define GL_TEXTURE6 0x84C6
+#define GL_TEXTURE7 0x84C7
+#define GL_TEXTURE8 0x84C8
+#define GL_TEXTURE9 0x84C9
+#define GL_TEXTURE10 0x84CA
+#define GL_TEXTURE11 0x84CB
+#define GL_TEXTURE12 0x84CC
+#define GL_TEXTURE13 0x84CD
+#define GL_TEXTURE14 0x84CE
+#define GL_TEXTURE15 0x84CF
+#define GL_TEXTURE16 0x84D0
+#define GL_TEXTURE17 0x84D1
+#define GL_TEXTURE18 0x84D2
+#define GL_TEXTURE19 0x84D3
+#define GL_TEXTURE20 0x84D4
+#define GL_TEXTURE21 0x84D5
+#define GL_TEXTURE22 0x84D6
+#define GL_TEXTURE23 0x84D7
+#define GL_TEXTURE24 0x84D8
+#define GL_TEXTURE25 0x84D9
+#define GL_TEXTURE26 0x84DA
+#define GL_TEXTURE27 0x84DB
+#define GL_TEXTURE28 0x84DC
+#define GL_TEXTURE29 0x84DD
+#define GL_TEXTURE30 0x84DE
+#define GL_TEXTURE31 0x84DF
+#define GL_ACTIVE_TEXTURE 0x84E0
+#define GL_CLIENT_ACTIVE_TEXTURE 0x84E1
+#define GL_MAX_TEXTURE_UNITS 0x84E2
+#define GL_TRANSPOSE_MODELVIEW_MATRIX 0x84E3
+#define GL_TRANSPOSE_PROJECTION_MATRIX 0x84E4
+#define GL_TRANSPOSE_TEXTURE_MATRIX 0x84E5
+#define GL_TRANSPOSE_COLOR_MATRIX 0x84E6
+#define GL_SUBTRACT 0x84E7
+#define GL_COMPRESSED_ALPHA 0x84E9
+#define GL_COMPRESSED_LUMINANCE 0x84EA
+#define GL_COMPRESSED_LUMINANCE_ALPHA 0x84EB
+#define GL_COMPRESSED_INTENSITY 0x84EC
+#define GL_COMPRESSED_RGB 0x84ED
+#define GL_COMPRESSED_RGBA 0x84EE
+#define GL_TEXTURE_COMPRESSION_HINT 0x84EF
+#define GL_NORMAL_MAP 0x8511
+#define GL_REFLECTION_MAP 0x8512
+#define GL_TEXTURE_CUBE_MAP 0x8513
+#define GL_TEXTURE_BINDING_CUBE_MAP 0x8514
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_X 0x8515
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_X 0x8516
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_Y 0x8517
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y 0x8518
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z 0x8519
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z 0x851A
+#define GL_PROXY_TEXTURE_CUBE_MAP 0x851B
+#define GL_MAX_CUBE_MAP_TEXTURE_SIZE 0x851C
+#define GL_COMBINE 0x8570
+#define GL_COMBINE_RGB 0x8571
+#define GL_COMBINE_ALPHA 0x8572
+#define GL_RGB_SCALE 0x8573
+#define GL_ADD_SIGNED 0x8574
+#define GL_INTERPOLATE 0x8575
+#define GL_CONSTANT 0x8576
+#define GL_PRIMARY_COLOR 0x8577
+#define GL_PREVIOUS 0x8578
+#define GL_SOURCE0_RGB 0x8580
+#define GL_SOURCE1_RGB 0x8581
+#define GL_SOURCE2_RGB 0x8582
+#define GL_SOURCE0_ALPHA 0x8588
+#define GL_SOURCE1_ALPHA 0x8589
+#define GL_SOURCE2_ALPHA 0x858A
+#define GL_OPERAND0_RGB 0x8590
+#define GL_OPERAND1_RGB 0x8591
+#define GL_OPERAND2_RGB 0x8592
+#define GL_OPERAND0_ALPHA 0x8598
+#define GL_OPERAND1_ALPHA 0x8599
+#define GL_OPERAND2_ALPHA 0x859A
+#define GL_TEXTURE_COMPRESSED_IMAGE_SIZE 0x86A0
+#define GL_TEXTURE_COMPRESSED 0x86A1
+#define GL_NUM_COMPRESSED_TEXTURE_FORMATS 0x86A2
+#define GL_COMPRESSED_TEXTURE_FORMATS 0x86A3
+#define GL_DOT3_RGB 0x86AE
+#define GL_DOT3_RGBA 0x86AF
+#define GL_MULTISAMPLE_BIT 0x20000000
+
+typedef void (GLAPIENTRY * PFNGLACTIVETEXTUREPROC) (GLenum texture);
+typedef void (GLAPIENTRY * PFNGLCLIENTACTIVETEXTUREPROC) (GLenum texture);
+typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXIMAGE1DPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const GLvoid *data);
+typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXIMAGE2DPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *data);
+typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXIMAGE3DPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid *data);
+typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXSUBIMAGE1DPROC) (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const GLvoid *data);
+typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid *data);
+typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid *data);
+typedef void (GLAPIENTRY * PFNGLGETCOMPRESSEDTEXIMAGEPROC) (GLenum target, GLint lod, GLvoid *img);
+typedef void (GLAPIENTRY * PFNGLLOADTRANSPOSEMATRIXDPROC) (const GLdouble m[16]);
+typedef void (GLAPIENTRY * PFNGLLOADTRANSPOSEMATRIXFPROC) (const GLfloat m[16]);
+typedef void (GLAPIENTRY * PFNGLMULTTRANSPOSEMATRIXDPROC) (const GLdouble m[16]);
+typedef void (GLAPIENTRY * PFNGLMULTTRANSPOSEMATRIXFPROC) (const GLfloat m[16]);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD1DPROC) (GLenum target, GLdouble s);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD1DVPROC) (GLenum target, const GLdouble *v);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD1FPROC) (GLenum target, GLfloat s);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD1FVPROC) (GLenum target, const GLfloat *v);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD1IPROC) (GLenum target, GLint s);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD1IVPROC) (GLenum target, const GLint *v);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD1SPROC) (GLenum target, GLshort s);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD1SVPROC) (GLenum target, const GLshort *v);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD2DPROC) (GLenum target, GLdouble s, GLdouble t);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD2DVPROC) (GLenum target, const GLdouble *v);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD2FPROC) (GLenum target, GLfloat s, GLfloat t);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD2FVPROC) (GLenum target, const GLfloat *v);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD2IPROC) (GLenum target, GLint s, GLint t);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD2IVPROC) (GLenum target, const GLint *v);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD2SPROC) (GLenum target, GLshort s, GLshort t);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD2SVPROC) (GLenum target, const GLshort *v);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD3DPROC) (GLenum target, GLdouble s, GLdouble t, GLdouble r);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD3DVPROC) (GLenum target, const GLdouble *v);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD3FPROC) (GLenum target, GLfloat s, GLfloat t, GLfloat r);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD3FVPROC) (GLenum target, const GLfloat *v);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD3IPROC) (GLenum target, GLint s, GLint t, GLint r);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD3IVPROC) (GLenum target, const GLint *v);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD3SPROC) (GLenum target, GLshort s, GLshort t, GLshort r);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD3SVPROC) (GLenum target, const GLshort *v);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD4DPROC) (GLenum target, GLdouble s, GLdouble t, GLdouble r, GLdouble q);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD4DVPROC) (GLenum target, const GLdouble *v);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD4FPROC) (GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD4FVPROC) (GLenum target, const GLfloat *v);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD4IPROC) (GLenum target, GLint s, GLint t, GLint r, GLint q);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD4IVPROC) (GLenum target, const GLint *v);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD4SPROC) (GLenum target, GLshort s, GLshort t, GLshort r, GLshort q);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD4SVPROC) (GLenum target, const GLshort *v);
+typedef void (GLAPIENTRY * PFNGLSAMPLECOVERAGEPROC) (GLclampf value, GLboolean invert);
+
+#define glActiveTexture GLEW_GET_FUN(__glewActiveTexture)
+#define glClientActiveTexture GLEW_GET_FUN(__glewClientActiveTexture)
+#define glCompressedTexImage1D GLEW_GET_FUN(__glewCompressedTexImage1D)
+#define glCompressedTexImage2D GLEW_GET_FUN(__glewCompressedTexImage2D)
+#define glCompressedTexImage3D GLEW_GET_FUN(__glewCompressedTexImage3D)
+#define glCompressedTexSubImage1D GLEW_GET_FUN(__glewCompressedTexSubImage1D)
+#define glCompressedTexSubImage2D GLEW_GET_FUN(__glewCompressedTexSubImage2D)
+#define glCompressedTexSubImage3D GLEW_GET_FUN(__glewCompressedTexSubImage3D)
+#define glGetCompressedTexImage GLEW_GET_FUN(__glewGetCompressedTexImage)
+#define glLoadTransposeMatrixd GLEW_GET_FUN(__glewLoadTransposeMatrixd)
+#define glLoadTransposeMatrixf GLEW_GET_FUN(__glewLoadTransposeMatrixf)
+#define glMultTransposeMatrixd GLEW_GET_FUN(__glewMultTransposeMatrixd)
+#define glMultTransposeMatrixf GLEW_GET_FUN(__glewMultTransposeMatrixf)
+#define glMultiTexCoord1d GLEW_GET_FUN(__glewMultiTexCoord1d)
+#define glMultiTexCoord1dv GLEW_GET_FUN(__glewMultiTexCoord1dv)
+#define glMultiTexCoord1f GLEW_GET_FUN(__glewMultiTexCoord1f)
+#define glMultiTexCoord1fv GLEW_GET_FUN(__glewMultiTexCoord1fv)
+#define glMultiTexCoord1i GLEW_GET_FUN(__glewMultiTexCoord1i)
+#define glMultiTexCoord1iv GLEW_GET_FUN(__glewMultiTexCoord1iv)
+#define glMultiTexCoord1s GLEW_GET_FUN(__glewMultiTexCoord1s)
+#define glMultiTexCoord1sv GLEW_GET_FUN(__glewMultiTexCoord1sv)
+#define glMultiTexCoord2d GLEW_GET_FUN(__glewMultiTexCoord2d)
+#define glMultiTexCoord2dv GLEW_GET_FUN(__glewMultiTexCoord2dv)
+#define glMultiTexCoord2f GLEW_GET_FUN(__glewMultiTexCoord2f)
+#define glMultiTexCoord2fv GLEW_GET_FUN(__glewMultiTexCoord2fv)
+#define glMultiTexCoord2i GLEW_GET_FUN(__glewMultiTexCoord2i)
+#define glMultiTexCoord2iv GLEW_GET_FUN(__glewMultiTexCoord2iv)
+#define glMultiTexCoord2s GLEW_GET_FUN(__glewMultiTexCoord2s)
+#define glMultiTexCoord2sv GLEW_GET_FUN(__glewMultiTexCoord2sv)
+#define glMultiTexCoord3d GLEW_GET_FUN(__glewMultiTexCoord3d)
+#define glMultiTexCoord3dv GLEW_GET_FUN(__glewMultiTexCoord3dv)
+#define glMultiTexCoord3f GLEW_GET_FUN(__glewMultiTexCoord3f)
+#define glMultiTexCoord3fv GLEW_GET_FUN(__glewMultiTexCoord3fv)
+#define glMultiTexCoord3i GLEW_GET_FUN(__glewMultiTexCoord3i)
+#define glMultiTexCoord3iv GLEW_GET_FUN(__glewMultiTexCoord3iv)
+#define glMultiTexCoord3s GLEW_GET_FUN(__glewMultiTexCoord3s)
+#define glMultiTexCoord3sv GLEW_GET_FUN(__glewMultiTexCoord3sv)
+#define glMultiTexCoord4d GLEW_GET_FUN(__glewMultiTexCoord4d)
+#define glMultiTexCoord4dv GLEW_GET_FUN(__glewMultiTexCoord4dv)
+#define glMultiTexCoord4f GLEW_GET_FUN(__glewMultiTexCoord4f)
+#define glMultiTexCoord4fv GLEW_GET_FUN(__glewMultiTexCoord4fv)
+#define glMultiTexCoord4i GLEW_GET_FUN(__glewMultiTexCoord4i)
+#define glMultiTexCoord4iv GLEW_GET_FUN(__glewMultiTexCoord4iv)
+#define glMultiTexCoord4s GLEW_GET_FUN(__glewMultiTexCoord4s)
+#define glMultiTexCoord4sv GLEW_GET_FUN(__glewMultiTexCoord4sv)
+#define glSampleCoverage GLEW_GET_FUN(__glewSampleCoverage)
+
+#define GLEW_VERSION_1_3 GLEW_GET_VAR(__GLEW_VERSION_1_3)
+
+#endif /* !GL_VERSION_1_3 */
+
+/* ----------------------------- GL_VERSION_1_4 ---------------------------- */
+
+#if !defined(GL_VERSION_1_4)
+#define GL_VERSION_1_4 1
+
+#define GL_BLEND_DST_RGB 0x80C8
+#define GL_BLEND_SRC_RGB 0x80C9
+#define GL_BLEND_DST_ALPHA 0x80CA
+#define GL_BLEND_SRC_ALPHA 0x80CB
+#define GL_POINT_SIZE_MIN 0x8126
+#define GL_POINT_SIZE_MAX 0x8127
+#define GL_POINT_FADE_THRESHOLD_SIZE 0x8128
+#define GL_POINT_DISTANCE_ATTENUATION 0x8129
+#define GL_GENERATE_MIPMAP 0x8191
+#define GL_GENERATE_MIPMAP_HINT 0x8192
+#define GL_DEPTH_COMPONENT16 0x81A5
+#define GL_DEPTH_COMPONENT24 0x81A6
+#define GL_DEPTH_COMPONENT32 0x81A7
+#define GL_MIRRORED_REPEAT 0x8370
+#define GL_FOG_COORDINATE_SOURCE 0x8450
+#define GL_FOG_COORDINATE 0x8451
+#define GL_FRAGMENT_DEPTH 0x8452
+#define GL_CURRENT_FOG_COORDINATE 0x8453
+#define GL_FOG_COORDINATE_ARRAY_TYPE 0x8454
+#define GL_FOG_COORDINATE_ARRAY_STRIDE 0x8455
+#define GL_FOG_COORDINATE_ARRAY_POINTER 0x8456
+#define GL_FOG_COORDINATE_ARRAY 0x8457
+#define GL_COLOR_SUM 0x8458
+#define GL_CURRENT_SECONDARY_COLOR 0x8459
+#define GL_SECONDARY_COLOR_ARRAY_SIZE 0x845A
+#define GL_SECONDARY_COLOR_ARRAY_TYPE 0x845B
+#define GL_SECONDARY_COLOR_ARRAY_STRIDE 0x845C
+#define GL_SECONDARY_COLOR_ARRAY_POINTER 0x845D
+#define GL_SECONDARY_COLOR_ARRAY 0x845E
+#define GL_MAX_TEXTURE_LOD_BIAS 0x84FD
+#define GL_TEXTURE_FILTER_CONTROL 0x8500
+#define GL_TEXTURE_LOD_BIAS 0x8501
+#define GL_INCR_WRAP 0x8507
+#define GL_DECR_WRAP 0x8508
+#define GL_TEXTURE_DEPTH_SIZE 0x884A
+#define GL_DEPTH_TEXTURE_MODE 0x884B
+#define GL_TEXTURE_COMPARE_MODE 0x884C
+#define GL_TEXTURE_COMPARE_FUNC 0x884D
+#define GL_COMPARE_R_TO_TEXTURE 0x884E
+
+typedef void (GLAPIENTRY * PFNGLBLENDCOLORPROC) (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
+typedef void (GLAPIENTRY * PFNGLBLENDEQUATIONPROC) (GLenum mode);
+typedef void (GLAPIENTRY * PFNGLBLENDFUNCSEPARATEPROC) (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha);
+typedef void (GLAPIENTRY * PFNGLFOGCOORDPOINTERPROC) (GLenum type, GLsizei stride, const GLvoid *pointer);
+typedef void (GLAPIENTRY * PFNGLFOGCOORDDPROC) (GLdouble coord);
+typedef void (GLAPIENTRY * PFNGLFOGCOORDDVPROC) (const GLdouble *coord);
+typedef void (GLAPIENTRY * PFNGLFOGCOORDFPROC) (GLfloat coord);
+typedef void (GLAPIENTRY * PFNGLFOGCOORDFVPROC) (const GLfloat *coord);
+typedef void (GLAPIENTRY * PFNGLMULTIDRAWARRAYSPROC) (GLenum mode, const GLint *first, const GLsizei *count, GLsizei primcount);
+typedef void (GLAPIENTRY * PFNGLMULTIDRAWELEMENTSPROC) (GLenum mode, const GLsizei *count, GLenum type, const GLvoid **indices, GLsizei primcount);
+typedef void (GLAPIENTRY * PFNGLPOINTPARAMETERFPROC) (GLenum pname, GLfloat param);
+typedef void (GLAPIENTRY * PFNGLPOINTPARAMETERFVPROC) (GLenum pname, const GLfloat *params);
+typedef void (GLAPIENTRY * PFNGLPOINTPARAMETERIPROC) (GLenum pname, GLint param);
+typedef void (GLAPIENTRY * PFNGLPOINTPARAMETERIVPROC) (GLenum pname, const GLint *params);
+typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3BPROC) (GLbyte red, GLbyte green, GLbyte blue);
+typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3BVPROC) (const GLbyte *v);
+typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3DPROC) (GLdouble red, GLdouble green, GLdouble blue);
+typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3DVPROC) (const GLdouble *v);
+typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3FPROC) (GLfloat red, GLfloat green, GLfloat blue);
+typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3FVPROC) (const GLfloat *v);
+typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3IPROC) (GLint red, GLint green, GLint blue);
+typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3IVPROC) (const GLint *v);
+typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3SPROC) (GLshort red, GLshort green, GLshort blue);
+typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3SVPROC) (const GLshort *v);
+typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3UBPROC) (GLubyte red, GLubyte green, GLubyte blue);
+typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3UBVPROC) (const GLubyte *v);
+typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3UIPROC) (GLuint red, GLuint green, GLuint blue);
+typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3UIVPROC) (const GLuint *v);
+typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3USPROC) (GLushort red, GLushort green, GLushort blue);
+typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3USVPROC) (const GLushort *v);
+typedef void (GLAPIENTRY * PFNGLSECONDARYCOLORPOINTERPROC) (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);
+typedef void (GLAPIENTRY * PFNGLWINDOWPOS2DPROC) (GLdouble x, GLdouble y);
+typedef void (GLAPIENTRY * PFNGLWINDOWPOS2DVPROC) (const GLdouble *p);
+typedef void (GLAPIENTRY * PFNGLWINDOWPOS2FPROC) (GLfloat x, GLfloat y);
+typedef void (GLAPIENTRY * PFNGLWINDOWPOS2FVPROC) (const GLfloat *p);
+typedef void (GLAPIENTRY * PFNGLWINDOWPOS2IPROC) (GLint x, GLint y);
+typedef void (GLAPIENTRY * PFNGLWINDOWPOS2IVPROC) (const GLint *p);
+typedef void (GLAPIENTRY * PFNGLWINDOWPOS2SPROC) (GLshort x, GLshort y);
+typedef void (GLAPIENTRY * PFNGLWINDOWPOS2SVPROC) (const GLshort *p);
+typedef void (GLAPIENTRY * PFNGLWINDOWPOS3DPROC) (GLdouble x, GLdouble y, GLdouble z);
+typedef void (GLAPIENTRY * PFNGLWINDOWPOS3DVPROC) (const GLdouble *p);
+typedef void (GLAPIENTRY * PFNGLWINDOWPOS3FPROC) (GLfloat x, GLfloat y, GLfloat z);
+typedef void (GLAPIENTRY * PFNGLWINDOWPOS3FVPROC) (const GLfloat *p);
+typedef void (GLAPIENTRY * PFNGLWINDOWPOS3IPROC) (GLint x, GLint y, GLint z);
+typedef void (GLAPIENTRY * PFNGLWINDOWPOS3IVPROC) (const GLint *p);
+typedef void (GLAPIENTRY * PFNGLWINDOWPOS3SPROC) (GLshort x, GLshort y, GLshort z);
+typedef void (GLAPIENTRY * PFNGLWINDOWPOS3SVPROC) (const GLshort *p);
+
+#define glBlendColor GLEW_GET_FUN(__glewBlendColor)
+#define glBlendEquation GLEW_GET_FUN(__glewBlendEquation)
+#define glBlendFuncSeparate GLEW_GET_FUN(__glewBlendFuncSeparate)
+#define glFogCoordPointer GLEW_GET_FUN(__glewFogCoordPointer)
+#define glFogCoordd GLEW_GET_FUN(__glewFogCoordd)
+#define glFogCoorddv GLEW_GET_FUN(__glewFogCoorddv)
+#define glFogCoordf GLEW_GET_FUN(__glewFogCoordf)
+#define glFogCoordfv GLEW_GET_FUN(__glewFogCoordfv)
+#define glMultiDrawArrays GLEW_GET_FUN(__glewMultiDrawArrays)
+#define glMultiDrawElements GLEW_GET_FUN(__glewMultiDrawElements)
+#define glPointParameterf GLEW_GET_FUN(__glewPointParameterf)
+#define glPointParameterfv GLEW_GET_FUN(__glewPointParameterfv)
+#define glPointParameteri GLEW_GET_FUN(__glewPointParameteri)
+#define glPointParameteriv GLEW_GET_FUN(__glewPointParameteriv)
+#define glSecondaryColor3b GLEW_GET_FUN(__glewSecondaryColor3b)
+#define glSecondaryColor3bv GLEW_GET_FUN(__glewSecondaryColor3bv)
+#define glSecondaryColor3d GLEW_GET_FUN(__glewSecondaryColor3d)
+#define glSecondaryColor3dv GLEW_GET_FUN(__glewSecondaryColor3dv)
+#define glSecondaryColor3f GLEW_GET_FUN(__glewSecondaryColor3f)
+#define glSecondaryColor3fv GLEW_GET_FUN(__glewSecondaryColor3fv)
+#define glSecondaryColor3i GLEW_GET_FUN(__glewSecondaryColor3i)
+#define glSecondaryColor3iv GLEW_GET_FUN(__glewSecondaryColor3iv)
+#define glSecondaryColor3s GLEW_GET_FUN(__glewSecondaryColor3s)
+#define glSecondaryColor3sv GLEW_GET_FUN(__glewSecondaryColor3sv)
+#define glSecondaryColor3ub GLEW_GET_FUN(__glewSecondaryColor3ub)
+#define glSecondaryColor3ubv GLEW_GET_FUN(__glewSecondaryColor3ubv)
+#define glSecondaryColor3ui GLEW_GET_FUN(__glewSecondaryColor3ui)
+#define glSecondaryColor3uiv GLEW_GET_FUN(__glewSecondaryColor3uiv)
+#define glSecondaryColor3us GLEW_GET_FUN(__glewSecondaryColor3us)
+#define glSecondaryColor3usv GLEW_GET_FUN(__glewSecondaryColor3usv)
+#define glSecondaryColorPointer GLEW_GET_FUN(__glewSecondaryColorPointer)
+#define glWindowPos2d GLEW_GET_FUN(__glewWindowPos2d)
+#define glWindowPos2dv GLEW_GET_FUN(__glewWindowPos2dv)
+#define glWindowPos2f GLEW_GET_FUN(__glewWindowPos2f)
+#define glWindowPos2fv GLEW_GET_FUN(__glewWindowPos2fv)
+#define glWindowPos2i GLEW_GET_FUN(__glewWindowPos2i)
+#define glWindowPos2iv GLEW_GET_FUN(__glewWindowPos2iv)
+#define glWindowPos2s GLEW_GET_FUN(__glewWindowPos2s)
+#define glWindowPos2sv GLEW_GET_FUN(__glewWindowPos2sv)
+#define glWindowPos3d GLEW_GET_FUN(__glewWindowPos3d)
+#define glWindowPos3dv GLEW_GET_FUN(__glewWindowPos3dv)
+#define glWindowPos3f GLEW_GET_FUN(__glewWindowPos3f)
+#define glWindowPos3fv GLEW_GET_FUN(__glewWindowPos3fv)
+#define glWindowPos3i GLEW_GET_FUN(__glewWindowPos3i)
+#define glWindowPos3iv GLEW_GET_FUN(__glewWindowPos3iv)
+#define glWindowPos3s GLEW_GET_FUN(__glewWindowPos3s)
+#define glWindowPos3sv GLEW_GET_FUN(__glewWindowPos3sv)
+
+#define GLEW_VERSION_1_4 GLEW_GET_VAR(__GLEW_VERSION_1_4)
+
+#endif /* !GL_VERSION_1_4 */
+
+/* ----------------------------- GL_VERSION_1_5 ---------------------------- */
+
+#if !defined(GL_VERSION_1_5)
+#define GL_VERSION_1_5 1
+
+#define GL_FOG_COORD_SRC GL_FOG_COORDINATE_SOURCE
+#define GL_FOG_COORD GL_FOG_COORDINATE
+#define GL_FOG_COORD_ARRAY GL_FOG_COORDINATE_ARRAY
+#define GL_SRC0_RGB GL_SOURCE0_RGB
+#define GL_FOG_COORD_ARRAY_POINTER GL_FOG_COORDINATE_ARRAY_POINTER
+#define GL_FOG_COORD_ARRAY_TYPE GL_FOG_COORDINATE_ARRAY_TYPE
+#define GL_SRC1_ALPHA GL_SOURCE1_ALPHA
+#define GL_CURRENT_FOG_COORD GL_CURRENT_FOG_COORDINATE
+#define GL_FOG_COORD_ARRAY_STRIDE GL_FOG_COORDINATE_ARRAY_STRIDE
+#define GL_SRC0_ALPHA GL_SOURCE0_ALPHA
+#define GL_SRC1_RGB GL_SOURCE1_RGB
+#define GL_FOG_COORD_ARRAY_BUFFER_BINDING GL_FOG_COORDINATE_ARRAY_BUFFER_BINDING
+#define GL_SRC2_ALPHA GL_SOURCE2_ALPHA
+#define GL_SRC2_RGB GL_SOURCE2_RGB
+#define GL_BUFFER_SIZE 0x8764
+#define GL_BUFFER_USAGE 0x8765
+#define GL_QUERY_COUNTER_BITS 0x8864
+#define GL_CURRENT_QUERY 0x8865
+#define GL_QUERY_RESULT 0x8866
+#define GL_QUERY_RESULT_AVAILABLE 0x8867
+#define GL_ARRAY_BUFFER 0x8892
+#define GL_ELEMENT_ARRAY_BUFFER 0x8893
+#define GL_ARRAY_BUFFER_BINDING 0x8894
+#define GL_ELEMENT_ARRAY_BUFFER_BINDING 0x8895
+#define GL_VERTEX_ARRAY_BUFFER_BINDING 0x8896
+#define GL_NORMAL_ARRAY_BUFFER_BINDING 0x8897
+#define GL_COLOR_ARRAY_BUFFER_BINDING 0x8898
+#define GL_INDEX_ARRAY_BUFFER_BINDING 0x8899
+#define GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING 0x889A
+#define GL_EDGE_FLAG_ARRAY_BUFFER_BINDING 0x889B
+#define GL_SECONDARY_COLOR_ARRAY_BUFFER_BINDING 0x889C
+#define GL_FOG_COORDINATE_ARRAY_BUFFER_BINDING 0x889D
+#define GL_WEIGHT_ARRAY_BUFFER_BINDING 0x889E
+#define GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING 0x889F
+#define GL_READ_ONLY 0x88B8
+#define GL_WRITE_ONLY 0x88B9
+#define GL_READ_WRITE 0x88BA
+#define GL_BUFFER_ACCESS 0x88BB
+#define GL_BUFFER_MAPPED 0x88BC
+#define GL_BUFFER_MAP_POINTER 0x88BD
+#define GL_STREAM_DRAW 0x88E0
+#define GL_STREAM_READ 0x88E1
+#define GL_STREAM_COPY 0x88E2
+#define GL_STATIC_DRAW 0x88E4
+#define GL_STATIC_READ 0x88E5
+#define GL_STATIC_COPY 0x88E6
+#define GL_DYNAMIC_DRAW 0x88E8
+#define GL_DYNAMIC_READ 0x88E9
+#define GL_DYNAMIC_COPY 0x88EA
+#define GL_SAMPLES_PASSED 0x8914
+
+typedef ptrdiff_t GLintptr;
+typedef ptrdiff_t GLsizeiptr;
+
+typedef void (GLAPIENTRY * PFNGLBEGINQUERYPROC) (GLenum target, GLuint id);
+typedef void (GLAPIENTRY * PFNGLBINDBUFFERPROC) (GLenum target, GLuint buffer);
+typedef void (GLAPIENTRY * PFNGLBUFFERDATAPROC) (GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usage);
+typedef void (GLAPIENTRY * PFNGLBUFFERSUBDATAPROC) (GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid* data);
+typedef void (GLAPIENTRY * PFNGLDELETEBUFFERSPROC) (GLsizei n, const GLuint* buffers);
+typedef void (GLAPIENTRY * PFNGLDELETEQUERIESPROC) (GLsizei n, const GLuint* ids);
+typedef void (GLAPIENTRY * PFNGLENDQUERYPROC) (GLenum target);
+typedef void (GLAPIENTRY * PFNGLGENBUFFERSPROC) (GLsizei n, GLuint* buffers);
+typedef void (GLAPIENTRY * PFNGLGENQUERIESPROC) (GLsizei n, GLuint* ids);
+typedef void (GLAPIENTRY * PFNGLGETBUFFERPARAMETERIVPROC) (GLenum target, GLenum pname, GLint* params);
+typedef void (GLAPIENTRY * PFNGLGETBUFFERPOINTERVPROC) (GLenum target, GLenum pname, GLvoid** params);
+typedef void (GLAPIENTRY * PFNGLGETBUFFERSUBDATAPROC) (GLenum target, GLintptr offset, GLsizeiptr size, GLvoid* data);
+typedef void (GLAPIENTRY * PFNGLGETQUERYOBJECTIVPROC) (GLuint id, GLenum pname, GLint* params);
+typedef void (GLAPIENTRY * PFNGLGETQUERYOBJECTUIVPROC) (GLuint id, GLenum pname, GLuint* params);
+typedef void (GLAPIENTRY * PFNGLGETQUERYIVPROC) (GLenum target, GLenum pname, GLint* params);
+typedef GLboolean (GLAPIENTRY * PFNGLISBUFFERPROC) (GLuint buffer);
+typedef GLboolean (GLAPIENTRY * PFNGLISQUERYPROC) (GLuint id);
+typedef GLvoid* (GLAPIENTRY * PFNGLMAPBUFFERPROC) (GLenum target, GLenum access);
+typedef GLboolean (GLAPIENTRY * PFNGLUNMAPBUFFERPROC) (GLenum target);
+
+#define glBeginQuery GLEW_GET_FUN(__glewBeginQuery)
+#define glBindBuffer GLEW_GET_FUN(__glewBindBuffer)
+#define glBufferData GLEW_GET_FUN(__glewBufferData)
+#define glBufferSubData GLEW_GET_FUN(__glewBufferSubData)
+#define glDeleteBuffers GLEW_GET_FUN(__glewDeleteBuffers)
+#define glDeleteQueries GLEW_GET_FUN(__glewDeleteQueries)
+#define glEndQuery GLEW_GET_FUN(__glewEndQuery)
+#define glGenBuffers GLEW_GET_FUN(__glewGenBuffers)
+#define glGenQueries GLEW_GET_FUN(__glewGenQueries)
+#define glGetBufferParameteriv GLEW_GET_FUN(__glewGetBufferParameteriv)
+#define glGetBufferPointerv GLEW_GET_FUN(__glewGetBufferPointerv)
+#define glGetBufferSubData GLEW_GET_FUN(__glewGetBufferSubData)
+#define glGetQueryObjectiv GLEW_GET_FUN(__glewGetQueryObjectiv)
+#define glGetQueryObjectuiv GLEW_GET_FUN(__glewGetQueryObjectuiv)
+#define glGetQueryiv GLEW_GET_FUN(__glewGetQueryiv)
+#define glIsBuffer GLEW_GET_FUN(__glewIsBuffer)
+#define glIsQuery GLEW_GET_FUN(__glewIsQuery)
+#define glMapBuffer GLEW_GET_FUN(__glewMapBuffer)
+#define glUnmapBuffer GLEW_GET_FUN(__glewUnmapBuffer)
+
+#define GLEW_VERSION_1_5 GLEW_GET_VAR(__GLEW_VERSION_1_5)
+
+#endif /* !GL_VERSION_1_5 */
+
+/* ----------------------------- GL_VERSION_2_0 ---------------------------- */
+
+#if !defined(GL_VERSION_2_0)
+#define GL_VERSION_2_0 1
+
+#define GL_BLEND_EQUATION_RGB GL_BLEND_EQUATION
+#define GL_VERTEX_ATTRIB_ARRAY_ENABLED 0x8622
+#define GL_VERTEX_ATTRIB_ARRAY_SIZE 0x8623
+#define GL_VERTEX_ATTRIB_ARRAY_STRIDE 0x8624
+#define GL_VERTEX_ATTRIB_ARRAY_TYPE 0x8625
+#define GL_CURRENT_VERTEX_ATTRIB 0x8626
+#define GL_VERTEX_PROGRAM_POINT_SIZE 0x8642
+#define GL_VERTEX_PROGRAM_TWO_SIDE 0x8643
+#define GL_VERTEX_ATTRIB_ARRAY_POINTER 0x8645
+#define GL_STENCIL_BACK_FUNC 0x8800
+#define GL_STENCIL_BACK_FAIL 0x8801
+#define GL_STENCIL_BACK_PASS_DEPTH_FAIL 0x8802
+#define GL_STENCIL_BACK_PASS_DEPTH_PASS 0x8803
+#define GL_MAX_DRAW_BUFFERS 0x8824
+#define GL_DRAW_BUFFER0 0x8825
+#define GL_DRAW_BUFFER1 0x8826
+#define GL_DRAW_BUFFER2 0x8827
+#define GL_DRAW_BUFFER3 0x8828
+#define GL_DRAW_BUFFER4 0x8829
+#define GL_DRAW_BUFFER5 0x882A
+#define GL_DRAW_BUFFER6 0x882B
+#define GL_DRAW_BUFFER7 0x882C
+#define GL_DRAW_BUFFER8 0x882D
+#define GL_DRAW_BUFFER9 0x882E
+#define GL_DRAW_BUFFER10 0x882F
+#define GL_DRAW_BUFFER11 0x8830
+#define GL_DRAW_BUFFER12 0x8831
+#define GL_DRAW_BUFFER13 0x8832
+#define GL_DRAW_BUFFER14 0x8833
+#define GL_DRAW_BUFFER15 0x8834
+#define GL_BLEND_EQUATION_ALPHA 0x883D
+#define GL_POINT_SPRITE 0x8861
+#define GL_COORD_REPLACE 0x8862
+#define GL_MAX_VERTEX_ATTRIBS 0x8869
+#define GL_VERTEX_ATTRIB_ARRAY_NORMALIZED 0x886A
+#define GL_MAX_TEXTURE_COORDS 0x8871
+#define GL_MAX_TEXTURE_IMAGE_UNITS 0x8872
+#define GL_FRAGMENT_SHADER 0x8B30
+#define GL_VERTEX_SHADER 0x8B31
+#define GL_MAX_FRAGMENT_UNIFORM_COMPONENTS 0x8B49
+#define GL_MAX_VERTEX_UNIFORM_COMPONENTS 0x8B4A
+#define GL_MAX_VARYING_FLOATS 0x8B4B
+#define GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS 0x8B4C
+#define GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS 0x8B4D
+#define GL_SHADER_TYPE 0x8B4F
+#define GL_FLOAT_VEC2 0x8B50
+#define GL_FLOAT_VEC3 0x8B51
+#define GL_FLOAT_VEC4 0x8B52
+#define GL_INT_VEC2 0x8B53
+#define GL_INT_VEC3 0x8B54
+#define GL_INT_VEC4 0x8B55
+#define GL_BOOL 0x8B56
+#define GL_BOOL_VEC2 0x8B57
+#define GL_BOOL_VEC3 0x8B58
+#define GL_BOOL_VEC4 0x8B59
+#define GL_FLOAT_MAT2 0x8B5A
+#define GL_FLOAT_MAT3 0x8B5B
+#define GL_FLOAT_MAT4 0x8B5C
+#define GL_SAMPLER_1D 0x8B5D
+#define GL_SAMPLER_2D 0x8B5E
+#define GL_SAMPLER_3D 0x8B5F
+#define GL_SAMPLER_CUBE 0x8B60
+#define GL_SAMPLER_1D_SHADOW 0x8B61
+#define GL_SAMPLER_2D_SHADOW 0x8B62
+#define GL_DELETE_STATUS 0x8B80
+#define GL_COMPILE_STATUS 0x8B81
+#define GL_LINK_STATUS 0x8B82
+#define GL_VALIDATE_STATUS 0x8B83
+#define GL_INFO_LOG_LENGTH 0x8B84
+#define GL_ATTACHED_SHADERS 0x8B85
+#define GL_ACTIVE_UNIFORMS 0x8B86
+#define GL_ACTIVE_UNIFORM_MAX_LENGTH 0x8B87
+#define GL_SHADER_SOURCE_LENGTH 0x8B88
+#define GL_ACTIVE_ATTRIBUTES 0x8B89
+#define GL_ACTIVE_ATTRIBUTE_MAX_LENGTH 0x8B8A
+#define GL_FRAGMENT_SHADER_DERIVATIVE_HINT 0x8B8B
+#define GL_SHADING_LANGUAGE_VERSION 0x8B8C
+#define GL_CURRENT_PROGRAM 0x8B8D
+#define GL_POINT_SPRITE_COORD_ORIGIN 0x8CA0
+#define GL_LOWER_LEFT 0x8CA1
+#define GL_UPPER_LEFT 0x8CA2
+#define GL_STENCIL_BACK_REF 0x8CA3
+#define GL_STENCIL_BACK_VALUE_MASK 0x8CA4
+#define GL_STENCIL_BACK_WRITEMASK 0x8CA5
+
+typedef void (GLAPIENTRY * PFNGLATTACHSHADERPROC) (GLuint program, GLuint shader);
+typedef void (GLAPIENTRY * PFNGLBINDATTRIBLOCATIONPROC) (GLuint program, GLuint index, const GLchar* name);
+typedef void (GLAPIENTRY * PFNGLBLENDEQUATIONSEPARATEPROC) (GLenum, GLenum);
+typedef void (GLAPIENTRY * PFNGLCOMPILESHADERPROC) (GLuint shader);
+typedef GLuint (GLAPIENTRY * PFNGLCREATEPROGRAMPROC) (void);
+typedef GLuint (GLAPIENTRY * PFNGLCREATESHADERPROC) (GLenum type);
+typedef void (GLAPIENTRY * PFNGLDELETEPROGRAMPROC) (GLuint program);
+typedef void (GLAPIENTRY * PFNGLDELETESHADERPROC) (GLuint shader);
+typedef void (GLAPIENTRY * PFNGLDETACHSHADERPROC) (GLuint program, GLuint shader);
+typedef void (GLAPIENTRY * PFNGLDISABLEVERTEXATTRIBARRAYPROC) (GLuint);
+typedef void (GLAPIENTRY * PFNGLDRAWBUFFERSPROC) (GLsizei n, const GLenum* bufs);
+typedef void (GLAPIENTRY * PFNGLENABLEVERTEXATTRIBARRAYPROC) (GLuint);
+typedef void (GLAPIENTRY * PFNGLGETACTIVEATTRIBPROC) (GLuint program, GLuint index, GLsizei maxLength, GLsizei* length, GLint* size, GLenum* type, GLchar* name);
+typedef void (GLAPIENTRY * PFNGLGETACTIVEUNIFORMPROC) (GLuint program, GLuint index, GLsizei maxLength, GLsizei* length, GLint* size, GLenum* type, GLchar* name);
+typedef void (GLAPIENTRY * PFNGLGETATTACHEDSHADERSPROC) (GLuint program, GLsizei maxCount, GLsizei* count, GLuint* shaders);
+typedef GLint (GLAPIENTRY * PFNGLGETATTRIBLOCATIONPROC) (GLuint program, const GLchar* name);
+typedef void (GLAPIENTRY * PFNGLGETPROGRAMINFOLOGPROC) (GLuint program, GLsizei bufSize, GLsizei* length, GLchar* infoLog);
+typedef void (GLAPIENTRY * PFNGLGETPROGRAMIVPROC) (GLuint program, GLenum pname, GLint* param);
+typedef void (GLAPIENTRY * PFNGLGETSHADERINFOLOGPROC) (GLuint shader, GLsizei bufSize, GLsizei* length, GLchar* infoLog);
+typedef void (GLAPIENTRY * PFNGLGETSHADERSOURCEPROC) (GLuint obj, GLsizei maxLength, GLsizei* length, GLchar* source);
+typedef void (GLAPIENTRY * PFNGLGETSHADERIVPROC) (GLuint shader, GLenum pname, GLint* param);
+typedef GLint (GLAPIENTRY * PFNGLGETUNIFORMLOCATIONPROC) (GLuint program, const GLchar* name);
+typedef void (GLAPIENTRY * PFNGLGETUNIFORMFVPROC) (GLuint program, GLint location, GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLGETUNIFORMIVPROC) (GLuint program, GLint location, GLint* params);
+typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBPOINTERVPROC) (GLuint, GLenum, GLvoid**);
+typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBDVPROC) (GLuint, GLenum, GLdouble*);
+typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBFVPROC) (GLuint, GLenum, GLfloat*);
+typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBIVPROC) (GLuint, GLenum, GLint*);
+typedef GLboolean (GLAPIENTRY * PFNGLISPROGRAMPROC) (GLuint program);
+typedef GLboolean (GLAPIENTRY * PFNGLISSHADERPROC) (GLuint shader);
+typedef void (GLAPIENTRY * PFNGLLINKPROGRAMPROC) (GLuint program);
+typedef void (GLAPIENTRY * PFNGLSHADERSOURCEPROC) (GLuint shader, GLsizei count, const GLchar** strings, const GLint* lengths);
+typedef void (GLAPIENTRY * PFNGLSTENCILFUNCSEPARATEPROC) (GLenum frontfunc, GLenum backfunc, GLint ref, GLuint mask);
+typedef void (GLAPIENTRY * PFNGLSTENCILMASKSEPARATEPROC) (GLenum, GLuint);
+typedef void (GLAPIENTRY * PFNGLSTENCILOPSEPARATEPROC) (GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass);
+typedef void (GLAPIENTRY * PFNGLUNIFORM1FPROC) (GLint location, GLfloat v0);
+typedef void (GLAPIENTRY * PFNGLUNIFORM1FVPROC) (GLint location, GLsizei count, const GLfloat* value);
+typedef void (GLAPIENTRY * PFNGLUNIFORM1IPROC) (GLint location, GLint v0);
+typedef void (GLAPIENTRY * PFNGLUNIFORM1IVPROC) (GLint location, GLsizei count, const GLint* value);
+typedef void (GLAPIENTRY * PFNGLUNIFORM2FPROC) (GLint location, GLfloat v0, GLfloat v1);
+typedef void (GLAPIENTRY * PFNGLUNIFORM2FVPROC) (GLint location, GLsizei count, const GLfloat* value);
+typedef void (GLAPIENTRY * PFNGLUNIFORM2IPROC) (GLint location, GLint v0, GLint v1);
+typedef void (GLAPIENTRY * PFNGLUNIFORM2IVPROC) (GLint location, GLsizei count, const GLint* value);
+typedef void (GLAPIENTRY * PFNGLUNIFORM3FPROC) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2);
+typedef void (GLAPIENTRY * PFNGLUNIFORM3FVPROC) (GLint location, GLsizei count, const GLfloat* value);
+typedef void (GLAPIENTRY * PFNGLUNIFORM3IPROC) (GLint location, GLint v0, GLint v1, GLint v2);
+typedef void (GLAPIENTRY * PFNGLUNIFORM3IVPROC) (GLint location, GLsizei count, const GLint* value);
+typedef void (GLAPIENTRY * PFNGLUNIFORM4FPROC) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
+typedef void (GLAPIENTRY * PFNGLUNIFORM4FVPROC) (GLint location, GLsizei count, const GLfloat* value);
+typedef void (GLAPIENTRY * PFNGLUNIFORM4IPROC) (GLint location, GLint v0, GLint v1, GLint v2, GLint v3);
+typedef void (GLAPIENTRY * PFNGLUNIFORM4IVPROC) (GLint location, GLsizei count, const GLint* value);
+typedef void (GLAPIENTRY * PFNGLUNIFORMMATRIX2FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
+typedef void (GLAPIENTRY * PFNGLUNIFORMMATRIX3FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
+typedef void (GLAPIENTRY * PFNGLUNIFORMMATRIX4FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
+typedef void (GLAPIENTRY * PFNGLUSEPROGRAMPROC) (GLuint program);
+typedef void (GLAPIENTRY * PFNGLVALIDATEPROGRAMPROC) (GLuint program);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB1DPROC) (GLuint index, GLdouble x);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB1DVPROC) (GLuint index, const GLdouble* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB1FPROC) (GLuint index, GLfloat x);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB1FVPROC) (GLuint index, const GLfloat* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB1SPROC) (GLuint index, GLshort x);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB1SVPROC) (GLuint index, const GLshort* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB2DPROC) (GLuint index, GLdouble x, GLdouble y);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB2DVPROC) (GLuint index, const GLdouble* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB2FPROC) (GLuint index, GLfloat x, GLfloat y);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB2FVPROC) (GLuint index, const GLfloat* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB2SPROC) (GLuint index, GLshort x, GLshort y);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB2SVPROC) (GLuint index, const GLshort* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB3DPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB3DVPROC) (GLuint index, const GLdouble* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB3FPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB3FVPROC) (GLuint index, const GLfloat* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB3SPROC) (GLuint index, GLshort x, GLshort y, GLshort z);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB3SVPROC) (GLuint index, const GLshort* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4NBVPROC) (GLuint index, const GLbyte* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4NIVPROC) (GLuint index, const GLint* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4NSVPROC) (GLuint index, const GLshort* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4NUBPROC) (GLuint index, GLubyte x, GLubyte y, GLubyte z, GLubyte w);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4NUBVPROC) (GLuint index, const GLubyte* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4NUIVPROC) (GLuint index, const GLuint* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4NUSVPROC) (GLuint index, const GLushort* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4BVPROC) (GLuint index, const GLbyte* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4DPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4DVPROC) (GLuint index, const GLdouble* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4FPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4FVPROC) (GLuint index, const GLfloat* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4IVPROC) (GLuint index, const GLint* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4SPROC) (GLuint index, GLshort x, GLshort y, GLshort z, GLshort w);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4SVPROC) (GLuint index, const GLshort* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4UBVPROC) (GLuint index, const GLubyte* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4UIVPROC) (GLuint index, const GLuint* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4USVPROC) (GLuint index, const GLushort* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBPOINTERPROC) (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid* pointer);
+
+#define glAttachShader GLEW_GET_FUN(__glewAttachShader)
+#define glBindAttribLocation GLEW_GET_FUN(__glewBindAttribLocation)
+#define glBlendEquationSeparate GLEW_GET_FUN(__glewBlendEquationSeparate)
+#define glCompileShader GLEW_GET_FUN(__glewCompileShader)
+#define glCreateProgram GLEW_GET_FUN(__glewCreateProgram)
+#define glCreateShader GLEW_GET_FUN(__glewCreateShader)
+#define glDeleteProgram GLEW_GET_FUN(__glewDeleteProgram)
+#define glDeleteShader GLEW_GET_FUN(__glewDeleteShader)
+#define glDetachShader GLEW_GET_FUN(__glewDetachShader)
+#define glDisableVertexAttribArray GLEW_GET_FUN(__glewDisableVertexAttribArray)
+#define glDrawBuffers GLEW_GET_FUN(__glewDrawBuffers)
+#define glEnableVertexAttribArray GLEW_GET_FUN(__glewEnableVertexAttribArray)
+#define glGetActiveAttrib GLEW_GET_FUN(__glewGetActiveAttrib)
+#define glGetActiveUniform GLEW_GET_FUN(__glewGetActiveUniform)
+#define glGetAttachedShaders GLEW_GET_FUN(__glewGetAttachedShaders)
+#define glGetAttribLocation GLEW_GET_FUN(__glewGetAttribLocation)
+#define glGetProgramInfoLog GLEW_GET_FUN(__glewGetProgramInfoLog)
+#define glGetProgramiv GLEW_GET_FUN(__glewGetProgramiv)
+#define glGetShaderInfoLog GLEW_GET_FUN(__glewGetShaderInfoLog)
+#define glGetShaderSource GLEW_GET_FUN(__glewGetShaderSource)
+#define glGetShaderiv GLEW_GET_FUN(__glewGetShaderiv)
+#define glGetUniformLocation GLEW_GET_FUN(__glewGetUniformLocation)
+#define glGetUniformfv GLEW_GET_FUN(__glewGetUniformfv)
+#define glGetUniformiv GLEW_GET_FUN(__glewGetUniformiv)
+#define glGetVertexAttribPointerv GLEW_GET_FUN(__glewGetVertexAttribPointerv)
+#define glGetVertexAttribdv GLEW_GET_FUN(__glewGetVertexAttribdv)
+#define glGetVertexAttribfv GLEW_GET_FUN(__glewGetVertexAttribfv)
+#define glGetVertexAttribiv GLEW_GET_FUN(__glewGetVertexAttribiv)
+#define glIsProgram GLEW_GET_FUN(__glewIsProgram)
+#define glIsShader GLEW_GET_FUN(__glewIsShader)
+#define glLinkProgram GLEW_GET_FUN(__glewLinkProgram)
+#define glShaderSource GLEW_GET_FUN(__glewShaderSource)
+#define glStencilFuncSeparate GLEW_GET_FUN(__glewStencilFuncSeparate)
+#define glStencilMaskSeparate GLEW_GET_FUN(__glewStencilMaskSeparate)
+#define glStencilOpSeparate GLEW_GET_FUN(__glewStencilOpSeparate)
+#define glUniform1f GLEW_GET_FUN(__glewUniform1f)
+#define glUniform1fv GLEW_GET_FUN(__glewUniform1fv)
+#define glUniform1i GLEW_GET_FUN(__glewUniform1i)
+#define glUniform1iv GLEW_GET_FUN(__glewUniform1iv)
+#define glUniform2f GLEW_GET_FUN(__glewUniform2f)
+#define glUniform2fv GLEW_GET_FUN(__glewUniform2fv)
+#define glUniform2i GLEW_GET_FUN(__glewUniform2i)
+#define glUniform2iv GLEW_GET_FUN(__glewUniform2iv)
+#define glUniform3f GLEW_GET_FUN(__glewUniform3f)
+#define glUniform3fv GLEW_GET_FUN(__glewUniform3fv)
+#define glUniform3i GLEW_GET_FUN(__glewUniform3i)
+#define glUniform3iv GLEW_GET_FUN(__glewUniform3iv)
+#define glUniform4f GLEW_GET_FUN(__glewUniform4f)
+#define glUniform4fv GLEW_GET_FUN(__glewUniform4fv)
+#define glUniform4i GLEW_GET_FUN(__glewUniform4i)
+#define glUniform4iv GLEW_GET_FUN(__glewUniform4iv)
+#define glUniformMatrix2fv GLEW_GET_FUN(__glewUniformMatrix2fv)
+#define glUniformMatrix3fv GLEW_GET_FUN(__glewUniformMatrix3fv)
+#define glUniformMatrix4fv GLEW_GET_FUN(__glewUniformMatrix4fv)
+#define glUseProgram GLEW_GET_FUN(__glewUseProgram)
+#define glValidateProgram GLEW_GET_FUN(__glewValidateProgram)
+#define glVertexAttrib1d GLEW_GET_FUN(__glewVertexAttrib1d)
+#define glVertexAttrib1dv GLEW_GET_FUN(__glewVertexAttrib1dv)
+#define glVertexAttrib1f GLEW_GET_FUN(__glewVertexAttrib1f)
+#define glVertexAttrib1fv GLEW_GET_FUN(__glewVertexAttrib1fv)
+#define glVertexAttrib1s GLEW_GET_FUN(__glewVertexAttrib1s)
+#define glVertexAttrib1sv GLEW_GET_FUN(__glewVertexAttrib1sv)
+#define glVertexAttrib2d GLEW_GET_FUN(__glewVertexAttrib2d)
+#define glVertexAttrib2dv GLEW_GET_FUN(__glewVertexAttrib2dv)
+#define glVertexAttrib2f GLEW_GET_FUN(__glewVertexAttrib2f)
+#define glVertexAttrib2fv GLEW_GET_FUN(__glewVertexAttrib2fv)
+#define glVertexAttrib2s GLEW_GET_FUN(__glewVertexAttrib2s)
+#define glVertexAttrib2sv GLEW_GET_FUN(__glewVertexAttrib2sv)
+#define glVertexAttrib3d GLEW_GET_FUN(__glewVertexAttrib3d)
+#define glVertexAttrib3dv GLEW_GET_FUN(__glewVertexAttrib3dv)
+#define glVertexAttrib3f GLEW_GET_FUN(__glewVertexAttrib3f)
+#define glVertexAttrib3fv GLEW_GET_FUN(__glewVertexAttrib3fv)
+#define glVertexAttrib3s GLEW_GET_FUN(__glewVertexAttrib3s)
+#define glVertexAttrib3sv GLEW_GET_FUN(__glewVertexAttrib3sv)
+#define glVertexAttrib4Nbv GLEW_GET_FUN(__glewVertexAttrib4Nbv)
+#define glVertexAttrib4Niv GLEW_GET_FUN(__glewVertexAttrib4Niv)
+#define glVertexAttrib4Nsv GLEW_GET_FUN(__glewVertexAttrib4Nsv)
+#define glVertexAttrib4Nub GLEW_GET_FUN(__glewVertexAttrib4Nub)
+#define glVertexAttrib4Nubv GLEW_GET_FUN(__glewVertexAttrib4Nubv)
+#define glVertexAttrib4Nuiv GLEW_GET_FUN(__glewVertexAttrib4Nuiv)
+#define glVertexAttrib4Nusv GLEW_GET_FUN(__glewVertexAttrib4Nusv)
+#define glVertexAttrib4bv GLEW_GET_FUN(__glewVertexAttrib4bv)
+#define glVertexAttrib4d GLEW_GET_FUN(__glewVertexAttrib4d)
+#define glVertexAttrib4dv GLEW_GET_FUN(__glewVertexAttrib4dv)
+#define glVertexAttrib4f GLEW_GET_FUN(__glewVertexAttrib4f)
+#define glVertexAttrib4fv GLEW_GET_FUN(__glewVertexAttrib4fv)
+#define glVertexAttrib4iv GLEW_GET_FUN(__glewVertexAttrib4iv)
+#define glVertexAttrib4s GLEW_GET_FUN(__glewVertexAttrib4s)
+#define glVertexAttrib4sv GLEW_GET_FUN(__glewVertexAttrib4sv)
+#define glVertexAttrib4ubv GLEW_GET_FUN(__glewVertexAttrib4ubv)
+#define glVertexAttrib4uiv GLEW_GET_FUN(__glewVertexAttrib4uiv)
+#define glVertexAttrib4usv GLEW_GET_FUN(__glewVertexAttrib4usv)
+#define glVertexAttribPointer GLEW_GET_FUN(__glewVertexAttribPointer)
+
+#define GLEW_VERSION_2_0 GLEW_GET_VAR(__GLEW_VERSION_2_0)
+
+#endif /* !GL_VERSION_2_0 */
+
+/* ----------------------------- GL_VERSION_2_1 ---------------------------- */
+
+#if !defined(GL_VERSION_2_1)
+#define GL_VERSION_2_1 1
+
+#define GL_CURRENT_RASTER_SECONDARY_COLOR 0x845F
+#define GL_PIXEL_PACK_BUFFER 0x88EB
+#define GL_PIXEL_UNPACK_BUFFER 0x88EC
+#define GL_PIXEL_PACK_BUFFER_BINDING 0x88ED
+#define GL_PIXEL_UNPACK_BUFFER_BINDING 0x88EF
+#define GL_FLOAT_MAT2x3 0x8B65
+#define GL_FLOAT_MAT2x4 0x8B66
+#define GL_FLOAT_MAT3x2 0x8B67
+#define GL_FLOAT_MAT3x4 0x8B68
+#define GL_FLOAT_MAT4x2 0x8B69
+#define GL_FLOAT_MAT4x3 0x8B6A
+#define GL_SRGB 0x8C40
+#define GL_SRGB8 0x8C41
+#define GL_SRGB_ALPHA 0x8C42
+#define GL_SRGB8_ALPHA8 0x8C43
+#define GL_SLUMINANCE_ALPHA 0x8C44
+#define GL_SLUMINANCE8_ALPHA8 0x8C45
+#define GL_SLUMINANCE 0x8C46
+#define GL_SLUMINANCE8 0x8C47
+#define GL_COMPRESSED_SRGB 0x8C48
+#define GL_COMPRESSED_SRGB_ALPHA 0x8C49
+#define GL_COMPRESSED_SLUMINANCE 0x8C4A
+#define GL_COMPRESSED_SLUMINANCE_ALPHA 0x8C4B
+
+typedef void (GLAPIENTRY * PFNGLUNIFORMMATRIX2X3FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GLAPIENTRY * PFNGLUNIFORMMATRIX2X4FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GLAPIENTRY * PFNGLUNIFORMMATRIX3X2FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GLAPIENTRY * PFNGLUNIFORMMATRIX3X4FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GLAPIENTRY * PFNGLUNIFORMMATRIX4X2FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GLAPIENTRY * PFNGLUNIFORMMATRIX4X3FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+
+#define glUniformMatrix2x3fv GLEW_GET_FUN(__glewUniformMatrix2x3fv)
+#define glUniformMatrix2x4fv GLEW_GET_FUN(__glewUniformMatrix2x4fv)
+#define glUniformMatrix3x2fv GLEW_GET_FUN(__glewUniformMatrix3x2fv)
+#define glUniformMatrix3x4fv GLEW_GET_FUN(__glewUniformMatrix3x4fv)
+#define glUniformMatrix4x2fv GLEW_GET_FUN(__glewUniformMatrix4x2fv)
+#define glUniformMatrix4x3fv GLEW_GET_FUN(__glewUniformMatrix4x3fv)
+
+#define GLEW_VERSION_2_1 GLEW_GET_VAR(__GLEW_VERSION_2_1)
+
+#endif /* !GL_VERSION_2_1 */
+
+/* ----------------------------- GL_VERSION_3_0 ---------------------------- */
+
+#if !defined(GL_VERSION_3_0)
+#define GL_VERSION_3_0 1
+
+#define GL_MAX_CLIP_DISTANCES GL_MAX_CLIP_PLANES
+#define GL_CLIP_DISTANCE5 GL_CLIP_PLANE5
+#define GL_CLIP_DISTANCE1 GL_CLIP_PLANE1
+#define GL_CLIP_DISTANCE3 GL_CLIP_PLANE3
+#define GL_COMPARE_REF_TO_TEXTURE GL_COMPARE_R_TO_TEXTURE_ARB
+#define GL_CLIP_DISTANCE0 GL_CLIP_PLANE0
+#define GL_CLIP_DISTANCE4 GL_CLIP_PLANE4
+#define GL_CLIP_DISTANCE2 GL_CLIP_PLANE2
+#define GL_MAX_VARYING_COMPONENTS GL_MAX_VARYING_FLOATS
+#define GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT 0x0001
+#define GL_MAJOR_VERSION 0x821B
+#define GL_MINOR_VERSION 0x821C
+#define GL_NUM_EXTENSIONS 0x821D
+#define GL_CONTEXT_FLAGS 0x821E
+#define GL_DEPTH_BUFFER 0x8223
+#define GL_STENCIL_BUFFER 0x8224
+#define GL_COMPRESSED_RED 0x8225
+#define GL_COMPRESSED_RG 0x8226
+#define GL_RGBA32F 0x8814
+#define GL_RGB32F 0x8815
+#define GL_RGBA16F 0x881A
+#define GL_RGB16F 0x881B
+#define GL_VERTEX_ATTRIB_ARRAY_INTEGER 0x88FD
+#define GL_MAX_ARRAY_TEXTURE_LAYERS 0x88FF
+#define GL_MIN_PROGRAM_TEXEL_OFFSET 0x8904
+#define GL_MAX_PROGRAM_TEXEL_OFFSET 0x8905
+#define GL_CLAMP_VERTEX_COLOR 0x891A
+#define GL_CLAMP_FRAGMENT_COLOR 0x891B
+#define GL_CLAMP_READ_COLOR 0x891C
+#define GL_FIXED_ONLY 0x891D
+#define GL_TEXTURE_RED_TYPE 0x8C10
+#define GL_TEXTURE_GREEN_TYPE 0x8C11
+#define GL_TEXTURE_BLUE_TYPE 0x8C12
+#define GL_TEXTURE_ALPHA_TYPE 0x8C13
+#define GL_TEXTURE_LUMINANCE_TYPE 0x8C14
+#define GL_TEXTURE_INTENSITY_TYPE 0x8C15
+#define GL_TEXTURE_DEPTH_TYPE 0x8C16
+#define GL_UNSIGNED_NORMALIZED 0x8C17
+#define GL_TEXTURE_1D_ARRAY 0x8C18
+#define GL_PROXY_TEXTURE_1D_ARRAY 0x8C19
+#define GL_TEXTURE_2D_ARRAY 0x8C1A
+#define GL_PROXY_TEXTURE_2D_ARRAY 0x8C1B
+#define GL_TEXTURE_BINDING_1D_ARRAY 0x8C1C
+#define GL_TEXTURE_BINDING_2D_ARRAY 0x8C1D
+#define GL_R11F_G11F_B10F 0x8C3A
+#define GL_UNSIGNED_INT_10F_11F_11F_REV 0x8C3B
+#define GL_RGB9_E5 0x8C3D
+#define GL_UNSIGNED_INT_5_9_9_9_REV 0x8C3E
+#define GL_TEXTURE_SHARED_SIZE 0x8C3F
+#define GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH 0x8C76
+#define GL_TRANSFORM_FEEDBACK_BUFFER_MODE 0x8C7F
+#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS 0x8C80
+#define GL_TRANSFORM_FEEDBACK_VARYINGS 0x8C83
+#define GL_TRANSFORM_FEEDBACK_BUFFER_START 0x8C84
+#define GL_TRANSFORM_FEEDBACK_BUFFER_SIZE 0x8C85
+#define GL_PRIMITIVES_GENERATED 0x8C87
+#define GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN 0x8C88
+#define GL_RASTERIZER_DISCARD 0x8C89
+#define GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS 0x8C8A
+#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS 0x8C8B
+#define GL_INTERLEAVED_ATTRIBS 0x8C8C
+#define GL_SEPARATE_ATTRIBS 0x8C8D
+#define GL_TRANSFORM_FEEDBACK_BUFFER 0x8C8E
+#define GL_TRANSFORM_FEEDBACK_BUFFER_BINDING 0x8C8F
+#define GL_RGBA32UI 0x8D70
+#define GL_RGB32UI 0x8D71
+#define GL_RGBA16UI 0x8D76
+#define GL_RGB16UI 0x8D77
+#define GL_RGBA8UI 0x8D7C
+#define GL_RGB8UI 0x8D7D
+#define GL_RGBA32I 0x8D82
+#define GL_RGB32I 0x8D83
+#define GL_RGBA16I 0x8D88
+#define GL_RGB16I 0x8D89
+#define GL_RGBA8I 0x8D8E
+#define GL_RGB8I 0x8D8F
+#define GL_RED_INTEGER 0x8D94
+#define GL_GREEN_INTEGER 0x8D95
+#define GL_BLUE_INTEGER 0x8D96
+#define GL_ALPHA_INTEGER 0x8D97
+#define GL_RGB_INTEGER 0x8D98
+#define GL_RGBA_INTEGER 0x8D99
+#define GL_BGR_INTEGER 0x8D9A
+#define GL_BGRA_INTEGER 0x8D9B
+#define GL_SAMPLER_1D_ARRAY 0x8DC0
+#define GL_SAMPLER_2D_ARRAY 0x8DC1
+#define GL_SAMPLER_1D_ARRAY_SHADOW 0x8DC3
+#define GL_SAMPLER_2D_ARRAY_SHADOW 0x8DC4
+#define GL_SAMPLER_CUBE_SHADOW 0x8DC5
+#define GL_UNSIGNED_INT_VEC2 0x8DC6
+#define GL_UNSIGNED_INT_VEC3 0x8DC7
+#define GL_UNSIGNED_INT_VEC4 0x8DC8
+#define GL_INT_SAMPLER_1D 0x8DC9
+#define GL_INT_SAMPLER_2D 0x8DCA
+#define GL_INT_SAMPLER_3D 0x8DCB
+#define GL_INT_SAMPLER_CUBE 0x8DCC
+#define GL_INT_SAMPLER_1D_ARRAY 0x8DCE
+#define GL_INT_SAMPLER_2D_ARRAY 0x8DCF
+#define GL_UNSIGNED_INT_SAMPLER_1D 0x8DD1
+#define GL_UNSIGNED_INT_SAMPLER_2D 0x8DD2
+#define GL_UNSIGNED_INT_SAMPLER_3D 0x8DD3
+#define GL_UNSIGNED_INT_SAMPLER_CUBE 0x8DD4
+#define GL_UNSIGNED_INT_SAMPLER_1D_ARRAY 0x8DD6
+#define GL_UNSIGNED_INT_SAMPLER_2D_ARRAY 0x8DD7
+#define GL_QUERY_WAIT 0x8E13
+#define GL_QUERY_NO_WAIT 0x8E14
+#define GL_QUERY_BY_REGION_WAIT 0x8E15
+#define GL_QUERY_BY_REGION_NO_WAIT 0x8E16
+
+typedef void (GLAPIENTRY * PFNGLBEGINCONDITIONALRENDERPROC) (GLuint, GLenum);
+typedef void (GLAPIENTRY * PFNGLBEGINTRANSFORMFEEDBACKPROC) (GLenum);
+typedef void (GLAPIENTRY * PFNGLBINDFRAGDATALOCATIONPROC) (GLuint, GLuint, const GLchar*);
+typedef void (GLAPIENTRY * PFNGLCLAMPCOLORPROC) (GLenum, GLenum);
+typedef void (GLAPIENTRY * PFNGLCLEARBUFFERFIPROC) (GLenum, GLint, GLfloat, GLint);
+typedef void (GLAPIENTRY * PFNGLCLEARBUFFERFVPROC) (GLenum, GLint, const GLfloat*);
+typedef void (GLAPIENTRY * PFNGLCLEARBUFFERIVPROC) (GLenum, GLint, const GLint*);
+typedef void (GLAPIENTRY * PFNGLCLEARBUFFERUIVPROC) (GLenum, GLint, const GLuint*);
+typedef void (GLAPIENTRY * PFNGLCOLORMASKIPROC) (GLuint, GLboolean, GLboolean, GLboolean, GLboolean);
+typedef void (GLAPIENTRY * PFNGLDISABLEIPROC) (GLenum, GLuint);
+typedef void (GLAPIENTRY * PFNGLENABLEIPROC) (GLenum, GLuint);
+typedef void (GLAPIENTRY * PFNGLENDCONDITIONALRENDERPROC) (void);
+typedef void (GLAPIENTRY * PFNGLENDTRANSFORMFEEDBACKPROC) (void);
+typedef void (GLAPIENTRY * PFNGLGETBOOLEANI_VPROC) (GLenum, GLuint, GLboolean*);
+typedef GLint (GLAPIENTRY * PFNGLGETFRAGDATALOCATIONPROC) (GLuint, const GLchar*);
+typedef const GLubyte* (GLAPIENTRY * PFNGLGETSTRINGIPROC) (GLenum, GLuint);
+typedef void (GLAPIENTRY * PFNGLGETTEXPARAMETERIIVPROC) (GLenum, GLenum, GLint*);
+typedef void (GLAPIENTRY * PFNGLGETTEXPARAMETERIUIVPROC) (GLenum, GLenum, GLuint*);
+typedef void (GLAPIENTRY * PFNGLGETTRANSFORMFEEDBACKVARYINGPROC) (GLuint, GLuint, GLsizei, GLsizei *, GLsizei *, GLenum *, GLchar *);
+typedef void (GLAPIENTRY * PFNGLGETUNIFORMUIVPROC) (GLuint, GLint, GLuint*);
+typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBIIVPROC) (GLuint, GLenum, GLint*);
+typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBIUIVPROC) (GLuint, GLenum, GLuint*);
+typedef GLboolean (GLAPIENTRY * PFNGLISENABLEDIPROC) (GLenum, GLuint);
+typedef void (GLAPIENTRY * PFNGLTEXPARAMETERIIVPROC) (GLenum, GLenum, const GLint*);
+typedef void (GLAPIENTRY * PFNGLTEXPARAMETERIUIVPROC) (GLenum, GLenum, const GLuint*);
+typedef void (GLAPIENTRY * PFNGLTRANSFORMFEEDBACKVARYINGSPROC) (GLuint, GLsizei, const GLchar **, GLenum);
+typedef void (GLAPIENTRY * PFNGLUNIFORM1UIPROC) (GLint, GLuint);
+typedef void (GLAPIENTRY * PFNGLUNIFORM1UIVPROC) (GLint, GLsizei, const GLuint*);
+typedef void (GLAPIENTRY * PFNGLUNIFORM2UIPROC) (GLint, GLuint, GLuint);
+typedef void (GLAPIENTRY * PFNGLUNIFORM2UIVPROC) (GLint, GLsizei, const GLuint*);
+typedef void (GLAPIENTRY * PFNGLUNIFORM3UIPROC) (GLint, GLuint, GLuint, GLuint);
+typedef void (GLAPIENTRY * PFNGLUNIFORM3UIVPROC) (GLint, GLsizei, const GLuint*);
+typedef void (GLAPIENTRY * PFNGLUNIFORM4UIPROC) (GLint, GLuint, GLuint, GLuint, GLuint);
+typedef void (GLAPIENTRY * PFNGLUNIFORM4UIVPROC) (GLint, GLsizei, const GLuint*);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI1IPROC) (GLuint, GLint);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI1IVPROC) (GLuint, const GLint*);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI1UIPROC) (GLuint, GLuint);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI1UIVPROC) (GLuint, const GLuint*);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI2IPROC) (GLuint, GLint, GLint);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI2IVPROC) (GLuint, const GLint*);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI2UIPROC) (GLuint, GLuint, GLuint);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI2UIVPROC) (GLuint, const GLuint*);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI3IPROC) (GLuint, GLint, GLint, GLint);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI3IVPROC) (GLuint, const GLint*);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI3UIPROC) (GLuint, GLuint, GLuint, GLuint);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI3UIVPROC) (GLuint, const GLuint*);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI4BVPROC) (GLuint, const GLbyte*);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI4IPROC) (GLuint, GLint, GLint, GLint, GLint);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI4IVPROC) (GLuint, const GLint*);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI4SVPROC) (GLuint, const GLshort*);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI4UBVPROC) (GLuint, const GLubyte*);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI4UIPROC) (GLuint, GLuint, GLuint, GLuint, GLuint);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI4UIVPROC) (GLuint, const GLuint*);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI4USVPROC) (GLuint, const GLushort*);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBIPOINTERPROC) (GLuint, GLint, GLenum, GLsizei, const GLvoid*);
+
+#define glBeginConditionalRender GLEW_GET_FUN(__glewBeginConditionalRender)
+#define glBeginTransformFeedback GLEW_GET_FUN(__glewBeginTransformFeedback)
+#define glBindFragDataLocation GLEW_GET_FUN(__glewBindFragDataLocation)
+#define glClampColor GLEW_GET_FUN(__glewClampColor)
+#define glClearBufferfi GLEW_GET_FUN(__glewClearBufferfi)
+#define glClearBufferfv GLEW_GET_FUN(__glewClearBufferfv)
+#define glClearBufferiv GLEW_GET_FUN(__glewClearBufferiv)
+#define glClearBufferuiv GLEW_GET_FUN(__glewClearBufferuiv)
+#define glColorMaski GLEW_GET_FUN(__glewColorMaski)
+#define glDisablei GLEW_GET_FUN(__glewDisablei)
+#define glEnablei GLEW_GET_FUN(__glewEnablei)
+#define glEndConditionalRender GLEW_GET_FUN(__glewEndConditionalRender)
+#define glEndTransformFeedback GLEW_GET_FUN(__glewEndTransformFeedback)
+#define glGetBooleani_v GLEW_GET_FUN(__glewGetBooleani_v)
+#define glGetFragDataLocation GLEW_GET_FUN(__glewGetFragDataLocation)
+#define glGetStringi GLEW_GET_FUN(__glewGetStringi)
+#define glGetTexParameterIiv GLEW_GET_FUN(__glewGetTexParameterIiv)
+#define glGetTexParameterIuiv GLEW_GET_FUN(__glewGetTexParameterIuiv)
+#define glGetTransformFeedbackVarying GLEW_GET_FUN(__glewGetTransformFeedbackVarying)
+#define glGetUniformuiv GLEW_GET_FUN(__glewGetUniformuiv)
+#define glGetVertexAttribIiv GLEW_GET_FUN(__glewGetVertexAttribIiv)
+#define glGetVertexAttribIuiv GLEW_GET_FUN(__glewGetVertexAttribIuiv)
+#define glIsEnabledi GLEW_GET_FUN(__glewIsEnabledi)
+#define glTexParameterIiv GLEW_GET_FUN(__glewTexParameterIiv)
+#define glTexParameterIuiv GLEW_GET_FUN(__glewTexParameterIuiv)
+#define glTransformFeedbackVaryings GLEW_GET_FUN(__glewTransformFeedbackVaryings)
+#define glUniform1ui GLEW_GET_FUN(__glewUniform1ui)
+#define glUniform1uiv GLEW_GET_FUN(__glewUniform1uiv)
+#define glUniform2ui GLEW_GET_FUN(__glewUniform2ui)
+#define glUniform2uiv GLEW_GET_FUN(__glewUniform2uiv)
+#define glUniform3ui GLEW_GET_FUN(__glewUniform3ui)
+#define glUniform3uiv GLEW_GET_FUN(__glewUniform3uiv)
+#define glUniform4ui GLEW_GET_FUN(__glewUniform4ui)
+#define glUniform4uiv GLEW_GET_FUN(__glewUniform4uiv)
+#define glVertexAttribI1i GLEW_GET_FUN(__glewVertexAttribI1i)
+#define glVertexAttribI1iv GLEW_GET_FUN(__glewVertexAttribI1iv)
+#define glVertexAttribI1ui GLEW_GET_FUN(__glewVertexAttribI1ui)
+#define glVertexAttribI1uiv GLEW_GET_FUN(__glewVertexAttribI1uiv)
+#define glVertexAttribI2i GLEW_GET_FUN(__glewVertexAttribI2i)
+#define glVertexAttribI2iv GLEW_GET_FUN(__glewVertexAttribI2iv)
+#define glVertexAttribI2ui GLEW_GET_FUN(__glewVertexAttribI2ui)
+#define glVertexAttribI2uiv GLEW_GET_FUN(__glewVertexAttribI2uiv)
+#define glVertexAttribI3i GLEW_GET_FUN(__glewVertexAttribI3i)
+#define glVertexAttribI3iv GLEW_GET_FUN(__glewVertexAttribI3iv)
+#define glVertexAttribI3ui GLEW_GET_FUN(__glewVertexAttribI3ui)
+#define glVertexAttribI3uiv GLEW_GET_FUN(__glewVertexAttribI3uiv)
+#define glVertexAttribI4bv GLEW_GET_FUN(__glewVertexAttribI4bv)
+#define glVertexAttribI4i GLEW_GET_FUN(__glewVertexAttribI4i)
+#define glVertexAttribI4iv GLEW_GET_FUN(__glewVertexAttribI4iv)
+#define glVertexAttribI4sv GLEW_GET_FUN(__glewVertexAttribI4sv)
+#define glVertexAttribI4ubv GLEW_GET_FUN(__glewVertexAttribI4ubv)
+#define glVertexAttribI4ui GLEW_GET_FUN(__glewVertexAttribI4ui)
+#define glVertexAttribI4uiv GLEW_GET_FUN(__glewVertexAttribI4uiv)
+#define glVertexAttribI4usv GLEW_GET_FUN(__glewVertexAttribI4usv)
+#define glVertexAttribIPointer GLEW_GET_FUN(__glewVertexAttribIPointer)
+
+#define GLEW_VERSION_3_0 GLEW_GET_VAR(__GLEW_VERSION_3_0)
+
+#endif /* !GL_VERSION_3_0 */
+
+/* ----------------------------- GL_VERSION_3_1 ---------------------------- */
+
+#if !defined(GL_VERSION_3_1)
+#define GL_VERSION_3_1 1
+
+#define GL_TEXTURE_RECTANGLE 0x84F5
+#define GL_TEXTURE_BINDING_RECTANGLE 0x84F6
+#define GL_PROXY_TEXTURE_RECTANGLE 0x84F7
+#define GL_MAX_RECTANGLE_TEXTURE_SIZE 0x84F8
+#define GL_SAMPLER_2D_RECT 0x8B63
+#define GL_SAMPLER_2D_RECT_SHADOW 0x8B64
+#define GL_TEXTURE_BUFFER 0x8C2A
+#define GL_MAX_TEXTURE_BUFFER_SIZE 0x8C2B
+#define GL_TEXTURE_BINDING_BUFFER 0x8C2C
+#define GL_TEXTURE_BUFFER_DATA_STORE_BINDING 0x8C2D
+#define GL_TEXTURE_BUFFER_FORMAT 0x8C2E
+#define GL_SAMPLER_BUFFER 0x8DC2
+#define GL_INT_SAMPLER_2D_RECT 0x8DCD
+#define GL_INT_SAMPLER_BUFFER 0x8DD0
+#define GL_UNSIGNED_INT_SAMPLER_2D_RECT 0x8DD5
+#define GL_UNSIGNED_INT_SAMPLER_BUFFER 0x8DD8
+#define GL_RED_SNORM 0x8F90
+#define GL_RG_SNORM 0x8F91
+#define GL_RGB_SNORM 0x8F92
+#define GL_RGBA_SNORM 0x8F93
+#define GL_R8_SNORM 0x8F94
+#define GL_RG8_SNORM 0x8F95
+#define GL_RGB8_SNORM 0x8F96
+#define GL_RGBA8_SNORM 0x8F97
+#define GL_R16_SNORM 0x8F98
+#define GL_RG16_SNORM 0x8F99
+#define GL_RGB16_SNORM 0x8F9A
+#define GL_RGBA16_SNORM 0x8F9B
+#define GL_SIGNED_NORMALIZED 0x8F9C
+#define GL_PRIMITIVE_RESTART 0x8F9D
+#define GL_PRIMITIVE_RESTART_INDEX 0x8F9E
+#define GL_BUFFER_ACCESS_FLAGS 0x911F
+#define GL_BUFFER_MAP_LENGTH 0x9120
+#define GL_BUFFER_MAP_OFFSET 0x9121
+
+typedef void (GLAPIENTRY * PFNGLDRAWARRAYSINSTANCEDPROC) (GLenum, GLint, GLsizei, GLsizei);
+typedef void (GLAPIENTRY * PFNGLDRAWELEMENTSINSTANCEDPROC) (GLenum, GLsizei, GLenum, const GLvoid*, GLsizei);
+typedef void (GLAPIENTRY * PFNGLPRIMITIVERESTARTINDEXPROC) (GLuint);
+typedef void (GLAPIENTRY * PFNGLTEXBUFFERPROC) (GLenum, GLenum, GLuint);
+
+#define glDrawArraysInstanced GLEW_GET_FUN(__glewDrawArraysInstanced)
+#define glDrawElementsInstanced GLEW_GET_FUN(__glewDrawElementsInstanced)
+#define glPrimitiveRestartIndex GLEW_GET_FUN(__glewPrimitiveRestartIndex)
+#define glTexBuffer GLEW_GET_FUN(__glewTexBuffer)
+
+#define GLEW_VERSION_3_1 GLEW_GET_VAR(__GLEW_VERSION_3_1)
+
+#endif /* !GL_VERSION_3_1 */
+
+/* ----------------------------- GL_VERSION_3_2 ---------------------------- */
+
+#if !defined(GL_VERSION_3_2)
+#define GL_VERSION_3_2 1
+
+#define GL_CONTEXT_CORE_PROFILE_BIT 0x00000001
+#define GL_CONTEXT_COMPATIBILITY_PROFILE_BIT 0x00000002
+#define GL_LINES_ADJACENCY 0x000A
+#define GL_LINE_STRIP_ADJACENCY 0x000B
+#define GL_TRIANGLES_ADJACENCY 0x000C
+#define GL_TRIANGLE_STRIP_ADJACENCY 0x000D
+#define GL_PROGRAM_POINT_SIZE 0x8642
+#define GL_GEOMETRY_VERTICES_OUT 0x8916
+#define GL_GEOMETRY_INPUT_TYPE 0x8917
+#define GL_GEOMETRY_OUTPUT_TYPE 0x8918
+#define GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS 0x8C29
+#define GL_FRAMEBUFFER_ATTACHMENT_LAYERED 0x8DA7
+#define GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS 0x8DA8
+#define GL_GEOMETRY_SHADER 0x8DD9
+#define GL_MAX_GEOMETRY_UNIFORM_COMPONENTS 0x8DDF
+#define GL_MAX_GEOMETRY_OUTPUT_VERTICES 0x8DE0
+#define GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS 0x8DE1
+#define GL_MAX_VERTEX_OUTPUT_COMPONENTS 0x9122
+#define GL_MAX_GEOMETRY_INPUT_COMPONENTS 0x9123
+#define GL_MAX_GEOMETRY_OUTPUT_COMPONENTS 0x9124
+#define GL_MAX_FRAGMENT_INPUT_COMPONENTS 0x9125
+#define GL_CONTEXT_PROFILE_MASK 0x9126
+
+typedef void (GLAPIENTRY * PFNGLFRAMEBUFFERTEXTUREPROC) (GLenum, GLenum, GLuint, GLint);
+typedef void (GLAPIENTRY * PFNGLGETBUFFERPARAMETERI64VPROC) (GLenum, GLenum, GLint64 *);
+typedef void (GLAPIENTRY * PFNGLGETINTEGER64I_VPROC) (GLenum, GLuint, GLint64 *);
+
+#define glFramebufferTexture GLEW_GET_FUN(__glewFramebufferTexture)
+#define glGetBufferParameteri64v GLEW_GET_FUN(__glewGetBufferParameteri64v)
+#define glGetInteger64i_v GLEW_GET_FUN(__glewGetInteger64i_v)
+
+#define GLEW_VERSION_3_2 GLEW_GET_VAR(__GLEW_VERSION_3_2)
+
+#endif /* !GL_VERSION_3_2 */
+
+/* ----------------------------- GL_VERSION_3_3 ---------------------------- */
+
+#if !defined(GL_VERSION_3_3)
+#define GL_VERSION_3_3 1
+
+#define GL_VERTEX_ATTRIB_ARRAY_DIVISOR 0x88FE
+#define GL_ANY_SAMPLES_PASSED 0x8C2F
+#define GL_TEXTURE_SWIZZLE_R 0x8E42
+#define GL_TEXTURE_SWIZZLE_G 0x8E43
+#define GL_TEXTURE_SWIZZLE_B 0x8E44
+#define GL_TEXTURE_SWIZZLE_A 0x8E45
+#define GL_TEXTURE_SWIZZLE_RGBA 0x8E46
+#define GL_RGB10_A2UI 0x906F
+
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBDIVISORPROC) (GLuint index, GLuint divisor);
+
+#define glVertexAttribDivisor GLEW_GET_FUN(__glewVertexAttribDivisor)
+
+#define GLEW_VERSION_3_3 GLEW_GET_VAR(__GLEW_VERSION_3_3)
+
+#endif /* !GL_VERSION_3_3 */
+
+/* ----------------------------- GL_VERSION_4_0 ---------------------------- */
+
+#if !defined(GL_VERSION_4_0)
+#define GL_VERSION_4_0 1
+
+#define GL_GEOMETRY_SHADER_INVOCATIONS 0x887F
+#define GL_SAMPLE_SHADING 0x8C36
+#define GL_MIN_SAMPLE_SHADING_VALUE 0x8C37
+#define GL_MAX_GEOMETRY_SHADER_INVOCATIONS 0x8E5A
+#define GL_MIN_FRAGMENT_INTERPOLATION_OFFSET 0x8E5B
+#define GL_MAX_FRAGMENT_INTERPOLATION_OFFSET 0x8E5C
+#define GL_FRAGMENT_INTERPOLATION_OFFSET_BITS 0x8E5D
+#define GL_MIN_PROGRAM_TEXTURE_GATHER_OFFSET 0x8E5E
+#define GL_MAX_PROGRAM_TEXTURE_GATHER_OFFSET 0x8E5F
+#define GL_MAX_PROGRAM_TEXTURE_GATHER_COMPONENTS 0x8F9F
+#define GL_TEXTURE_CUBE_MAP_ARRAY 0x9009
+#define GL_TEXTURE_BINDING_CUBE_MAP_ARRAY 0x900A
+#define GL_PROXY_TEXTURE_CUBE_MAP_ARRAY 0x900B
+#define GL_SAMPLER_CUBE_MAP_ARRAY 0x900C
+#define GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW 0x900D
+#define GL_INT_SAMPLER_CUBE_MAP_ARRAY 0x900E
+#define GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY 0x900F
+
+typedef void (GLAPIENTRY * PFNGLBLENDEQUATIONSEPARATEIPROC) (GLuint buf, GLenum modeRGB, GLenum modeAlpha);
+typedef void (GLAPIENTRY * PFNGLBLENDEQUATIONIPROC) (GLuint buf, GLenum mode);
+typedef void (GLAPIENTRY * PFNGLBLENDFUNCSEPARATEIPROC) (GLuint buf, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha);
+typedef void (GLAPIENTRY * PFNGLBLENDFUNCIPROC) (GLuint buf, GLenum src, GLenum dst);
+typedef void (GLAPIENTRY * PFNGLMINSAMPLESHADINGPROC) (GLclampf value);
+
+#define glBlendEquationSeparatei GLEW_GET_FUN(__glewBlendEquationSeparatei)
+#define glBlendEquationi GLEW_GET_FUN(__glewBlendEquationi)
+#define glBlendFuncSeparatei GLEW_GET_FUN(__glewBlendFuncSeparatei)
+#define glBlendFunci GLEW_GET_FUN(__glewBlendFunci)
+#define glMinSampleShading GLEW_GET_FUN(__glewMinSampleShading)
+
+#define GLEW_VERSION_4_0 GLEW_GET_VAR(__GLEW_VERSION_4_0)
+
+#endif /* !GL_VERSION_4_0 */
+
+/* ----------------------------- GL_VERSION_4_1 ---------------------------- */
+
+#if !defined(GL_VERSION_4_1)
+#define GL_VERSION_4_1 1
+
+#define GLEW_VERSION_4_1 GLEW_GET_VAR(__GLEW_VERSION_4_1)
+
+#endif /* !GL_VERSION_4_1 */
+
+/* ----------------------------- GL_VERSION_4_2 ---------------------------- */
+
+#if !defined(GL_VERSION_4_2)
+#define GL_VERSION_4_2 1
+
+#define GLEW_VERSION_4_2 GLEW_GET_VAR(__GLEW_VERSION_4_2)
+
+#endif /* !GL_VERSION_4_2 */
+
+/* -------------------------- GL_3DFX_multisample -------------------------- */
+
+#if !defined(GL_3DFX_multisample)
+#define GL_3DFX_multisample 1
+
+#define GL_MULTISAMPLE_3DFX 0x86B2
+#define GL_SAMPLE_BUFFERS_3DFX 0x86B3
+#define GL_SAMPLES_3DFX 0x86B4
+#define GL_MULTISAMPLE_BIT_3DFX 0x20000000
+
+#define GLEW_3DFX_multisample GLEW_GET_VAR(__GLEW_3DFX_multisample)
+
+#endif /* !GL_3DFX_multisample */
+
+/* ---------------------------- GL_3DFX_tbuffer ---------------------------- */
+
+#if !defined(GL_3DFX_tbuffer)
+#define GL_3DFX_tbuffer 1
+
+typedef void (GLAPIENTRY * PFNGLTBUFFERMASK3DFXPROC) (GLuint mask);
+
+#define glTbufferMask3DFX GLEW_GET_FUN(__glewTbufferMask3DFX)
+
+#define GLEW_3DFX_tbuffer GLEW_GET_VAR(__GLEW_3DFX_tbuffer)
+
+#endif /* !GL_3DFX_tbuffer */
+
+/* -------------------- GL_3DFX_texture_compression_FXT1 ------------------- */
+
+#if !defined(GL_3DFX_texture_compression_FXT1)
+#define GL_3DFX_texture_compression_FXT1 1
+
+#define GL_COMPRESSED_RGB_FXT1_3DFX 0x86B0
+#define GL_COMPRESSED_RGBA_FXT1_3DFX 0x86B1
+
+#define GLEW_3DFX_texture_compression_FXT1 GLEW_GET_VAR(__GLEW_3DFX_texture_compression_FXT1)
+
+#endif /* !GL_3DFX_texture_compression_FXT1 */
+
+/* ----------------------- GL_AMD_blend_minmax_factor ---------------------- */
+
+#if !defined(GL_AMD_blend_minmax_factor)
+#define GL_AMD_blend_minmax_factor 1
+
+#define GL_FACTOR_MIN_AMD 0x901C
+#define GL_FACTOR_MAX_AMD 0x901D
+
+#define GLEW_AMD_blend_minmax_factor GLEW_GET_VAR(__GLEW_AMD_blend_minmax_factor)
+
+#endif /* !GL_AMD_blend_minmax_factor */
+
+/* ----------------------- GL_AMD_conservative_depth ----------------------- */
+
+#if !defined(GL_AMD_conservative_depth)
+#define GL_AMD_conservative_depth 1
+
+#define GLEW_AMD_conservative_depth GLEW_GET_VAR(__GLEW_AMD_conservative_depth)
+
+#endif /* !GL_AMD_conservative_depth */
+
+/* -------------------------- GL_AMD_debug_output -------------------------- */
+
+#if !defined(GL_AMD_debug_output)
+#define GL_AMD_debug_output 1
+
+#define GL_MAX_DEBUG_MESSAGE_LENGTH_AMD 0x9143
+#define GL_MAX_DEBUG_LOGGED_MESSAGES_AMD 0x9144
+#define GL_DEBUG_LOGGED_MESSAGES_AMD 0x9145
+#define GL_DEBUG_SEVERITY_HIGH_AMD 0x9146
+#define GL_DEBUG_SEVERITY_MEDIUM_AMD 0x9147
+#define GL_DEBUG_SEVERITY_LOW_AMD 0x9148
+#define GL_DEBUG_CATEGORY_API_ERROR_AMD 0x9149
+#define GL_DEBUG_CATEGORY_WINDOW_SYSTEM_AMD 0x914A
+#define GL_DEBUG_CATEGORY_DEPRECATION_AMD 0x914B
+#define GL_DEBUG_CATEGORY_UNDEFINED_BEHAVIOR_AMD 0x914C
+#define GL_DEBUG_CATEGORY_PERFORMANCE_AMD 0x914D
+#define GL_DEBUG_CATEGORY_SHADER_COMPILER_AMD 0x914E
+#define GL_DEBUG_CATEGORY_APPLICATION_AMD 0x914F
+#define GL_DEBUG_CATEGORY_OTHER_AMD 0x9150
+
+typedef void (APIENTRY *GLDEBUGPROCAMD)(GLuint id, GLenum category, GLenum severity, GLsizei length, const GLchar* message, GLvoid* userParam);
+
+typedef void (GLAPIENTRY * PFNGLDEBUGMESSAGECALLBACKAMDPROC) (GLDEBUGPROCAMD callback, void* userParam);
+typedef void (GLAPIENTRY * PFNGLDEBUGMESSAGEENABLEAMDPROC) (GLenum category, GLenum severity, GLsizei count, const GLuint* ids, GLboolean enabled);
+typedef void (GLAPIENTRY * PFNGLDEBUGMESSAGEINSERTAMDPROC) (GLenum category, GLenum severity, GLuint id, GLsizei length, const char* buf);
+typedef GLuint (GLAPIENTRY * PFNGLGETDEBUGMESSAGELOGAMDPROC) (GLuint count, GLsizei bufsize, GLenum* categories, GLuint* severities, GLuint* ids, GLsizei* lengths, char* message);
+
+#define glDebugMessageCallbackAMD GLEW_GET_FUN(__glewDebugMessageCallbackAMD)
+#define glDebugMessageEnableAMD GLEW_GET_FUN(__glewDebugMessageEnableAMD)
+#define glDebugMessageInsertAMD GLEW_GET_FUN(__glewDebugMessageInsertAMD)
+#define glGetDebugMessageLogAMD GLEW_GET_FUN(__glewGetDebugMessageLogAMD)
+
+#define GLEW_AMD_debug_output GLEW_GET_VAR(__GLEW_AMD_debug_output)
+
+#endif /* !GL_AMD_debug_output */
+
+/* ---------------------- GL_AMD_depth_clamp_separate ---------------------- */
+
+#if !defined(GL_AMD_depth_clamp_separate)
+#define GL_AMD_depth_clamp_separate 1
+
+#define GL_DEPTH_CLAMP_NEAR_AMD 0x901E
+#define GL_DEPTH_CLAMP_FAR_AMD 0x901F
+
+#define GLEW_AMD_depth_clamp_separate GLEW_GET_VAR(__GLEW_AMD_depth_clamp_separate)
+
+#endif /* !GL_AMD_depth_clamp_separate */
+
+/* ----------------------- GL_AMD_draw_buffers_blend ----------------------- */
+
+#if !defined(GL_AMD_draw_buffers_blend)
+#define GL_AMD_draw_buffers_blend 1
+
+typedef void (GLAPIENTRY * PFNGLBLENDEQUATIONINDEXEDAMDPROC) (GLuint buf, GLenum mode);
+typedef void (GLAPIENTRY * PFNGLBLENDEQUATIONSEPARATEINDEXEDAMDPROC) (GLuint buf, GLenum modeRGB, GLenum modeAlpha);
+typedef void (GLAPIENTRY * PFNGLBLENDFUNCINDEXEDAMDPROC) (GLuint buf, GLenum src, GLenum dst);
+typedef void (GLAPIENTRY * PFNGLBLENDFUNCSEPARATEINDEXEDAMDPROC) (GLuint buf, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha);
+
+#define glBlendEquationIndexedAMD GLEW_GET_FUN(__glewBlendEquationIndexedAMD)
+#define glBlendEquationSeparateIndexedAMD GLEW_GET_FUN(__glewBlendEquationSeparateIndexedAMD)
+#define glBlendFuncIndexedAMD GLEW_GET_FUN(__glewBlendFuncIndexedAMD)
+#define glBlendFuncSeparateIndexedAMD GLEW_GET_FUN(__glewBlendFuncSeparateIndexedAMD)
+
+#define GLEW_AMD_draw_buffers_blend GLEW_GET_VAR(__GLEW_AMD_draw_buffers_blend)
+
+#endif /* !GL_AMD_draw_buffers_blend */
+
+/* ----------------------- GL_AMD_multi_draw_indirect ---------------------- */
+
+#if !defined(GL_AMD_multi_draw_indirect)
+#define GL_AMD_multi_draw_indirect 1
+
+typedef void (GLAPIENTRY * PFNGLMULTIDRAWARRAYSINDIRECTAMDPROC) (GLenum mode, const void* indirect, GLsizei primcount, GLsizei stride);
+typedef void (GLAPIENTRY * PFNGLMULTIDRAWELEMENTSINDIRECTAMDPROC) (GLenum mode, GLenum type, const void* indirect, GLsizei primcount, GLsizei stride);
+
+#define glMultiDrawArraysIndirectAMD GLEW_GET_FUN(__glewMultiDrawArraysIndirectAMD)
+#define glMultiDrawElementsIndirectAMD GLEW_GET_FUN(__glewMultiDrawElementsIndirectAMD)
+
+#define GLEW_AMD_multi_draw_indirect GLEW_GET_VAR(__GLEW_AMD_multi_draw_indirect)
+
+#endif /* !GL_AMD_multi_draw_indirect */
+
+/* ------------------------- GL_AMD_name_gen_delete ------------------------ */
+
+#if !defined(GL_AMD_name_gen_delete)
+#define GL_AMD_name_gen_delete 1
+
+#define GL_DATA_BUFFER_AMD 0x9151
+#define GL_PERFORMANCE_MONITOR_AMD 0x9152
+#define GL_QUERY_OBJECT_AMD 0x9153
+#define GL_VERTEX_ARRAY_OBJECT_AMD 0x9154
+#define GL_SAMPLER_OBJECT_AMD 0x9155
+
+typedef void (GLAPIENTRY * PFNGLDELETENAMESAMDPROC) (GLenum identifier, GLuint num, const GLuint* names);
+typedef void (GLAPIENTRY * PFNGLGENNAMESAMDPROC) (GLenum identifier, GLuint num, GLuint* names);
+typedef GLboolean (GLAPIENTRY * PFNGLISNAMEAMDPROC) (GLenum identifier, GLuint name);
+
+#define glDeleteNamesAMD GLEW_GET_FUN(__glewDeleteNamesAMD)
+#define glGenNamesAMD GLEW_GET_FUN(__glewGenNamesAMD)
+#define glIsNameAMD GLEW_GET_FUN(__glewIsNameAMD)
+
+#define GLEW_AMD_name_gen_delete GLEW_GET_VAR(__GLEW_AMD_name_gen_delete)
+
+#endif /* !GL_AMD_name_gen_delete */
+
+/* ----------------------- GL_AMD_performance_monitor ---------------------- */
+
+#if !defined(GL_AMD_performance_monitor)
+#define GL_AMD_performance_monitor 1
+
+#define GL_UNSIGNED_INT 0x1405
+#define GL_FLOAT 0x1406
+#define GL_COUNTER_TYPE_AMD 0x8BC0
+#define GL_COUNTER_RANGE_AMD 0x8BC1
+#define GL_UNSIGNED_INT64_AMD 0x8BC2
+#define GL_PERCENTAGE_AMD 0x8BC3
+#define GL_PERFMON_RESULT_AVAILABLE_AMD 0x8BC4
+#define GL_PERFMON_RESULT_SIZE_AMD 0x8BC5
+#define GL_PERFMON_RESULT_AMD 0x8BC6
+
+typedef void (GLAPIENTRY * PFNGLBEGINPERFMONITORAMDPROC) (GLuint monitor);
+typedef void (GLAPIENTRY * PFNGLDELETEPERFMONITORSAMDPROC) (GLsizei n, GLuint* monitors);
+typedef void (GLAPIENTRY * PFNGLENDPERFMONITORAMDPROC) (GLuint monitor);
+typedef void (GLAPIENTRY * PFNGLGENPERFMONITORSAMDPROC) (GLsizei n, GLuint* monitors);
+typedef void (GLAPIENTRY * PFNGLGETPERFMONITORCOUNTERDATAAMDPROC) (GLuint monitor, GLenum pname, GLsizei dataSize, GLuint* data, GLint *bytesWritten);
+typedef void (GLAPIENTRY * PFNGLGETPERFMONITORCOUNTERINFOAMDPROC) (GLuint group, GLuint counter, GLenum pname, void* data);
+typedef void (GLAPIENTRY * PFNGLGETPERFMONITORCOUNTERSTRINGAMDPROC) (GLuint group, GLuint counter, GLsizei bufSize, GLsizei* length, char *counterString);
+typedef void (GLAPIENTRY * PFNGLGETPERFMONITORCOUNTERSAMDPROC) (GLuint group, GLint* numCounters, GLint *maxActiveCounters, GLsizei countersSize, GLuint *counters);
+typedef void (GLAPIENTRY * PFNGLGETPERFMONITORGROUPSTRINGAMDPROC) (GLuint group, GLsizei bufSize, GLsizei* length, char *groupString);
+typedef void (GLAPIENTRY * PFNGLGETPERFMONITORGROUPSAMDPROC) (GLint* numGroups, GLsizei groupsSize, GLuint *groups);
+typedef void (GLAPIENTRY * PFNGLSELECTPERFMONITORCOUNTERSAMDPROC) (GLuint monitor, GLboolean enable, GLuint group, GLint numCounters, GLuint* counterList);
+
+#define glBeginPerfMonitorAMD GLEW_GET_FUN(__glewBeginPerfMonitorAMD)
+#define glDeletePerfMonitorsAMD GLEW_GET_FUN(__glewDeletePerfMonitorsAMD)
+#define glEndPerfMonitorAMD GLEW_GET_FUN(__glewEndPerfMonitorAMD)
+#define glGenPerfMonitorsAMD GLEW_GET_FUN(__glewGenPerfMonitorsAMD)
+#define glGetPerfMonitorCounterDataAMD GLEW_GET_FUN(__glewGetPerfMonitorCounterDataAMD)
+#define glGetPerfMonitorCounterInfoAMD GLEW_GET_FUN(__glewGetPerfMonitorCounterInfoAMD)
+#define glGetPerfMonitorCounterStringAMD GLEW_GET_FUN(__glewGetPerfMonitorCounterStringAMD)
+#define glGetPerfMonitorCountersAMD GLEW_GET_FUN(__glewGetPerfMonitorCountersAMD)
+#define glGetPerfMonitorGroupStringAMD GLEW_GET_FUN(__glewGetPerfMonitorGroupStringAMD)
+#define glGetPerfMonitorGroupsAMD GLEW_GET_FUN(__glewGetPerfMonitorGroupsAMD)
+#define glSelectPerfMonitorCountersAMD GLEW_GET_FUN(__glewSelectPerfMonitorCountersAMD)
+
+#define GLEW_AMD_performance_monitor GLEW_GET_VAR(__GLEW_AMD_performance_monitor)
+
+#endif /* !GL_AMD_performance_monitor */
+
+/* -------------------------- GL_AMD_pinned_memory ------------------------- */
+
+#if !defined(GL_AMD_pinned_memory)
+#define GL_AMD_pinned_memory 1
+
+#define GL_EXTERNAL_VIRTUAL_MEMORY_BUFFER_AMD 0x9160
+
+#define GLEW_AMD_pinned_memory GLEW_GET_VAR(__GLEW_AMD_pinned_memory)
+
+#endif /* !GL_AMD_pinned_memory */
+
+/* ----------------------- GL_AMD_query_buffer_object ---------------------- */
+
+#if !defined(GL_AMD_query_buffer_object)
+#define GL_AMD_query_buffer_object 1
+
+#define GL_QUERY_BUFFER_AMD 0x9192
+#define GL_QUERY_BUFFER_BINDING_AMD 0x9193
+#define GL_QUERY_RESULT_NO_WAIT_AMD 0x9194
+
+#define GLEW_AMD_query_buffer_object GLEW_GET_VAR(__GLEW_AMD_query_buffer_object)
+
+#endif /* !GL_AMD_query_buffer_object */
+
+/* ------------------------ GL_AMD_sample_positions ------------------------ */
+
+#if !defined(GL_AMD_sample_positions)
+#define GL_AMD_sample_positions 1
+
+#define GL_SUBSAMPLE_DISTANCE_AMD 0x883F
+
+typedef void (GLAPIENTRY * PFNGLSETMULTISAMPLEFVAMDPROC) (GLenum pname, GLuint index, const GLfloat* val);
+
+#define glSetMultisamplefvAMD GLEW_GET_FUN(__glewSetMultisamplefvAMD)
+
+#define GLEW_AMD_sample_positions GLEW_GET_VAR(__GLEW_AMD_sample_positions)
+
+#endif /* !GL_AMD_sample_positions */
+
+/* ------------------ GL_AMD_seamless_cubemap_per_texture ------------------ */
+
+#if !defined(GL_AMD_seamless_cubemap_per_texture)
+#define GL_AMD_seamless_cubemap_per_texture 1
+
+#define GL_TEXTURE_CUBE_MAP_SEAMLESS_ARB 0x884F
+
+#define GLEW_AMD_seamless_cubemap_per_texture GLEW_GET_VAR(__GLEW_AMD_seamless_cubemap_per_texture)
+
+#endif /* !GL_AMD_seamless_cubemap_per_texture */
+
+/* ---------------------- GL_AMD_shader_stencil_export --------------------- */
+
+#if !defined(GL_AMD_shader_stencil_export)
+#define GL_AMD_shader_stencil_export 1
+
+#define GLEW_AMD_shader_stencil_export GLEW_GET_VAR(__GLEW_AMD_shader_stencil_export)
+
+#endif /* !GL_AMD_shader_stencil_export */
+
+/* ---------------------- GL_AMD_shader_trinary_minmax --------------------- */
+
+#if !defined(GL_AMD_shader_trinary_minmax)
+#define GL_AMD_shader_trinary_minmax 1
+
+#define GLEW_AMD_shader_trinary_minmax GLEW_GET_VAR(__GLEW_AMD_shader_trinary_minmax)
+
+#endif /* !GL_AMD_shader_trinary_minmax */
+
+/* ------------------------- GL_AMD_sparse_texture ------------------------- */
+
+#if !defined(GL_AMD_sparse_texture)
+#define GL_AMD_sparse_texture 1
+
+#define GL_TEXTURE_STORAGE_SPARSE_BIT_AMD 0x00000001
+#define GL_VIRTUAL_PAGE_SIZE_X_AMD 0x9195
+#define GL_VIRTUAL_PAGE_SIZE_Y_AMD 0x9196
+#define GL_VIRTUAL_PAGE_SIZE_Z_AMD 0x9197
+#define GL_MAX_SPARSE_TEXTURE_SIZE_AMD 0x9198
+#define GL_MAX_SPARSE_3D_TEXTURE_SIZE_AMD 0x9199
+#define GL_MAX_SPARSE_ARRAY_TEXTURE_LAYERS 0x919A
+#define GL_MIN_SPARSE_LEVEL_AMD 0x919B
+#define GL_MIN_LOD_WARNING_AMD 0x919C
+
+typedef void (GLAPIENTRY * PFNGLTEXSTORAGESPARSEAMDPROC) (GLenum target, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLsizei layers, GLbitfield flags);
+typedef void (GLAPIENTRY * PFNGLTEXTURESTORAGESPARSEAMDPROC) (GLuint texture, GLenum target, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLsizei layers, GLbitfield flags);
+
+#define glTexStorageSparseAMD GLEW_GET_FUN(__glewTexStorageSparseAMD)
+#define glTextureStorageSparseAMD GLEW_GET_FUN(__glewTextureStorageSparseAMD)
+
+#define GLEW_AMD_sparse_texture GLEW_GET_VAR(__GLEW_AMD_sparse_texture)
+
+#endif /* !GL_AMD_sparse_texture */
+
+/* ------------------- GL_AMD_stencil_operation_extended ------------------- */
+
+#if !defined(GL_AMD_stencil_operation_extended)
+#define GL_AMD_stencil_operation_extended 1
+
+#define GL_AND 0x1501
+#define GL_XOR 0x1506
+#define GL_OR 0x1507
+#define GL_NOR 0x1508
+#define GL_EQUIV 0x1509
+#define GL_NAND 0x150E
+#define GL_SET_AMD 0x874A
+#define GL_REPLACE_VALUE_AMD 0x874B
+#define GL_STENCIL_OP_VALUE_AMD 0x874C
+#define GL_STENCIL_BACK_OP_VALUE_AMD 0x874D
+
+typedef void (GLAPIENTRY * PFNGLSTENCILOPVALUEAMDPROC) (GLenum face, GLuint value);
+
+#define glStencilOpValueAMD GLEW_GET_FUN(__glewStencilOpValueAMD)
+
+#define GLEW_AMD_stencil_operation_extended GLEW_GET_VAR(__GLEW_AMD_stencil_operation_extended)
+
+#endif /* !GL_AMD_stencil_operation_extended */
+
+/* ------------------------ GL_AMD_texture_texture4 ------------------------ */
+
+#if !defined(GL_AMD_texture_texture4)
+#define GL_AMD_texture_texture4 1
+
+#define GLEW_AMD_texture_texture4 GLEW_GET_VAR(__GLEW_AMD_texture_texture4)
+
+#endif /* !GL_AMD_texture_texture4 */
+
+/* --------------- GL_AMD_transform_feedback3_lines_triangles -------------- */
+
+#if !defined(GL_AMD_transform_feedback3_lines_triangles)
+#define GL_AMD_transform_feedback3_lines_triangles 1
+
+#define GLEW_AMD_transform_feedback3_lines_triangles GLEW_GET_VAR(__GLEW_AMD_transform_feedback3_lines_triangles)
+
+#endif /* !GL_AMD_transform_feedback3_lines_triangles */
+
+/* ----------------------- GL_AMD_vertex_shader_layer ---------------------- */
+
+#if !defined(GL_AMD_vertex_shader_layer)
+#define GL_AMD_vertex_shader_layer 1
+
+#define GLEW_AMD_vertex_shader_layer GLEW_GET_VAR(__GLEW_AMD_vertex_shader_layer)
+
+#endif /* !GL_AMD_vertex_shader_layer */
+
+/* -------------------- GL_AMD_vertex_shader_tessellator ------------------- */
+
+#if !defined(GL_AMD_vertex_shader_tessellator)
+#define GL_AMD_vertex_shader_tessellator 1
+
+#define GL_SAMPLER_BUFFER_AMD 0x9001
+#define GL_INT_SAMPLER_BUFFER_AMD 0x9002
+#define GL_UNSIGNED_INT_SAMPLER_BUFFER_AMD 0x9003
+#define GL_TESSELLATION_MODE_AMD 0x9004
+#define GL_TESSELLATION_FACTOR_AMD 0x9005
+#define GL_DISCRETE_AMD 0x9006
+#define GL_CONTINUOUS_AMD 0x9007
+
+typedef void (GLAPIENTRY * PFNGLTESSELLATIONFACTORAMDPROC) (GLfloat factor);
+typedef void (GLAPIENTRY * PFNGLTESSELLATIONMODEAMDPROC) (GLenum mode);
+
+#define glTessellationFactorAMD GLEW_GET_FUN(__glewTessellationFactorAMD)
+#define glTessellationModeAMD GLEW_GET_FUN(__glewTessellationModeAMD)
+
+#define GLEW_AMD_vertex_shader_tessellator GLEW_GET_VAR(__GLEW_AMD_vertex_shader_tessellator)
+
+#endif /* !GL_AMD_vertex_shader_tessellator */
+
+/* ------------------ GL_AMD_vertex_shader_viewport_index ------------------ */
+
+#if !defined(GL_AMD_vertex_shader_viewport_index)
+#define GL_AMD_vertex_shader_viewport_index 1
+
+#define GLEW_AMD_vertex_shader_viewport_index GLEW_GET_VAR(__GLEW_AMD_vertex_shader_viewport_index)
+
+#endif /* !GL_AMD_vertex_shader_viewport_index */
+
+/* ----------------------- GL_APPLE_aux_depth_stencil ---------------------- */
+
+#if !defined(GL_APPLE_aux_depth_stencil)
+#define GL_APPLE_aux_depth_stencil 1
+
+#define GL_AUX_DEPTH_STENCIL_APPLE 0x8A14
+
+#define GLEW_APPLE_aux_depth_stencil GLEW_GET_VAR(__GLEW_APPLE_aux_depth_stencil)
+
+#endif /* !GL_APPLE_aux_depth_stencil */
+
+/* ------------------------ GL_APPLE_client_storage ------------------------ */
+
+#if !defined(GL_APPLE_client_storage)
+#define GL_APPLE_client_storage 1
+
+#define GL_UNPACK_CLIENT_STORAGE_APPLE 0x85B2
+
+#define GLEW_APPLE_client_storage GLEW_GET_VAR(__GLEW_APPLE_client_storage)
+
+#endif /* !GL_APPLE_client_storage */
+
+/* ------------------------- GL_APPLE_element_array ------------------------ */
+
+#if !defined(GL_APPLE_element_array)
+#define GL_APPLE_element_array 1
+
+#define GL_ELEMENT_ARRAY_APPLE 0x8A0C
+#define GL_ELEMENT_ARRAY_TYPE_APPLE 0x8A0D
+#define GL_ELEMENT_ARRAY_POINTER_APPLE 0x8A0E
+
+typedef void (GLAPIENTRY * PFNGLDRAWELEMENTARRAYAPPLEPROC) (GLenum mode, GLint first, GLsizei count);
+typedef void (GLAPIENTRY * PFNGLDRAWRANGEELEMENTARRAYAPPLEPROC) (GLenum mode, GLuint start, GLuint end, GLint first, GLsizei count);
+typedef void (GLAPIENTRY * PFNGLELEMENTPOINTERAPPLEPROC) (GLenum type, const void* pointer);
+typedef void (GLAPIENTRY * PFNGLMULTIDRAWELEMENTARRAYAPPLEPROC) (GLenum mode, const GLint* first, const GLsizei *count, GLsizei primcount);
+typedef void (GLAPIENTRY * PFNGLMULTIDRAWRANGEELEMENTARRAYAPPLEPROC) (GLenum mode, GLuint start, GLuint end, const GLint* first, const GLsizei *count, GLsizei primcount);
+
+#define glDrawElementArrayAPPLE GLEW_GET_FUN(__glewDrawElementArrayAPPLE)
+#define glDrawRangeElementArrayAPPLE GLEW_GET_FUN(__glewDrawRangeElementArrayAPPLE)
+#define glElementPointerAPPLE GLEW_GET_FUN(__glewElementPointerAPPLE)
+#define glMultiDrawElementArrayAPPLE GLEW_GET_FUN(__glewMultiDrawElementArrayAPPLE)
+#define glMultiDrawRangeElementArrayAPPLE GLEW_GET_FUN(__glewMultiDrawRangeElementArrayAPPLE)
+
+#define GLEW_APPLE_element_array GLEW_GET_VAR(__GLEW_APPLE_element_array)
+
+#endif /* !GL_APPLE_element_array */
+
+/* ----------------------------- GL_APPLE_fence ---------------------------- */
+
+#if !defined(GL_APPLE_fence)
+#define GL_APPLE_fence 1
+
+#define GL_DRAW_PIXELS_APPLE 0x8A0A
+#define GL_FENCE_APPLE 0x8A0B
+
+typedef void (GLAPIENTRY * PFNGLDELETEFENCESAPPLEPROC) (GLsizei n, const GLuint* fences);
+typedef void (GLAPIENTRY * PFNGLFINISHFENCEAPPLEPROC) (GLuint fence);
+typedef void (GLAPIENTRY * PFNGLFINISHOBJECTAPPLEPROC) (GLenum object, GLint name);
+typedef void (GLAPIENTRY * PFNGLGENFENCESAPPLEPROC) (GLsizei n, GLuint* fences);
+typedef GLboolean (GLAPIENTRY * PFNGLISFENCEAPPLEPROC) (GLuint fence);
+typedef void (GLAPIENTRY * PFNGLSETFENCEAPPLEPROC) (GLuint fence);
+typedef GLboolean (GLAPIENTRY * PFNGLTESTFENCEAPPLEPROC) (GLuint fence);
+typedef GLboolean (GLAPIENTRY * PFNGLTESTOBJECTAPPLEPROC) (GLenum object, GLuint name);
+
+#define glDeleteFencesAPPLE GLEW_GET_FUN(__glewDeleteFencesAPPLE)
+#define glFinishFenceAPPLE GLEW_GET_FUN(__glewFinishFenceAPPLE)
+#define glFinishObjectAPPLE GLEW_GET_FUN(__glewFinishObjectAPPLE)
+#define glGenFencesAPPLE GLEW_GET_FUN(__glewGenFencesAPPLE)
+#define glIsFenceAPPLE GLEW_GET_FUN(__glewIsFenceAPPLE)
+#define glSetFenceAPPLE GLEW_GET_FUN(__glewSetFenceAPPLE)
+#define glTestFenceAPPLE GLEW_GET_FUN(__glewTestFenceAPPLE)
+#define glTestObjectAPPLE GLEW_GET_FUN(__glewTestObjectAPPLE)
+
+#define GLEW_APPLE_fence GLEW_GET_VAR(__GLEW_APPLE_fence)
+
+#endif /* !GL_APPLE_fence */
+
+/* ------------------------- GL_APPLE_float_pixels ------------------------- */
+
+#if !defined(GL_APPLE_float_pixels)
+#define GL_APPLE_float_pixels 1
+
+#define GL_HALF_APPLE 0x140B
+#define GL_RGBA_FLOAT32_APPLE 0x8814
+#define GL_RGB_FLOAT32_APPLE 0x8815
+#define GL_ALPHA_FLOAT32_APPLE 0x8816
+#define GL_INTENSITY_FLOAT32_APPLE 0x8817
+#define GL_LUMINANCE_FLOAT32_APPLE 0x8818
+#define GL_LUMINANCE_ALPHA_FLOAT32_APPLE 0x8819
+#define GL_RGBA_FLOAT16_APPLE 0x881A
+#define GL_RGB_FLOAT16_APPLE 0x881B
+#define GL_ALPHA_FLOAT16_APPLE 0x881C
+#define GL_INTENSITY_FLOAT16_APPLE 0x881D
+#define GL_LUMINANCE_FLOAT16_APPLE 0x881E
+#define GL_LUMINANCE_ALPHA_FLOAT16_APPLE 0x881F
+#define GL_COLOR_FLOAT_APPLE 0x8A0F
+
+#define GLEW_APPLE_float_pixels GLEW_GET_VAR(__GLEW_APPLE_float_pixels)
+
+#endif /* !GL_APPLE_float_pixels */
+
+/* ---------------------- GL_APPLE_flush_buffer_range ---------------------- */
+
+#if !defined(GL_APPLE_flush_buffer_range)
+#define GL_APPLE_flush_buffer_range 1
+
+#define GL_BUFFER_SERIALIZED_MODIFY_APPLE 0x8A12
+#define GL_BUFFER_FLUSHING_UNMAP_APPLE 0x8A13
+
+typedef void (GLAPIENTRY * PFNGLBUFFERPARAMETERIAPPLEPROC) (GLenum target, GLenum pname, GLint param);
+typedef void (GLAPIENTRY * PFNGLFLUSHMAPPEDBUFFERRANGEAPPLEPROC) (GLenum target, GLintptr offset, GLsizeiptr size);
+
+#define glBufferParameteriAPPLE GLEW_GET_FUN(__glewBufferParameteriAPPLE)
+#define glFlushMappedBufferRangeAPPLE GLEW_GET_FUN(__glewFlushMappedBufferRangeAPPLE)
+
+#define GLEW_APPLE_flush_buffer_range GLEW_GET_VAR(__GLEW_APPLE_flush_buffer_range)
+
+#endif /* !GL_APPLE_flush_buffer_range */
+
+/* ----------------------- GL_APPLE_object_purgeable ----------------------- */
+
+#if !defined(GL_APPLE_object_purgeable)
+#define GL_APPLE_object_purgeable 1
+
+#define GL_BUFFER_OBJECT_APPLE 0x85B3
+#define GL_RELEASED_APPLE 0x8A19
+#define GL_VOLATILE_APPLE 0x8A1A
+#define GL_RETAINED_APPLE 0x8A1B
+#define GL_UNDEFINED_APPLE 0x8A1C
+#define GL_PURGEABLE_APPLE 0x8A1D
+
+typedef void (GLAPIENTRY * PFNGLGETOBJECTPARAMETERIVAPPLEPROC) (GLenum objectType, GLuint name, GLenum pname, GLint* params);
+typedef GLenum (GLAPIENTRY * PFNGLOBJECTPURGEABLEAPPLEPROC) (GLenum objectType, GLuint name, GLenum option);
+typedef GLenum (GLAPIENTRY * PFNGLOBJECTUNPURGEABLEAPPLEPROC) (GLenum objectType, GLuint name, GLenum option);
+
+#define glGetObjectParameterivAPPLE GLEW_GET_FUN(__glewGetObjectParameterivAPPLE)
+#define glObjectPurgeableAPPLE GLEW_GET_FUN(__glewObjectPurgeableAPPLE)
+#define glObjectUnpurgeableAPPLE GLEW_GET_FUN(__glewObjectUnpurgeableAPPLE)
+
+#define GLEW_APPLE_object_purgeable GLEW_GET_VAR(__GLEW_APPLE_object_purgeable)
+
+#endif /* !GL_APPLE_object_purgeable */
+
+/* ------------------------- GL_APPLE_pixel_buffer ------------------------- */
+
+#if !defined(GL_APPLE_pixel_buffer)
+#define GL_APPLE_pixel_buffer 1
+
+#define GL_MIN_PBUFFER_VIEWPORT_DIMS_APPLE 0x8A10
+
+#define GLEW_APPLE_pixel_buffer GLEW_GET_VAR(__GLEW_APPLE_pixel_buffer)
+
+#endif /* !GL_APPLE_pixel_buffer */
+
+/* ---------------------------- GL_APPLE_rgb_422 --------------------------- */
+
+#if !defined(GL_APPLE_rgb_422)
+#define GL_APPLE_rgb_422 1
+
+#define GL_UNSIGNED_SHORT_8_8_APPLE 0x85BA
+#define GL_UNSIGNED_SHORT_8_8_REV_APPLE 0x85BB
+#define GL_RGB_422_APPLE 0x8A1F
+
+#define GLEW_APPLE_rgb_422 GLEW_GET_VAR(__GLEW_APPLE_rgb_422)
+
+#endif /* !GL_APPLE_rgb_422 */
+
+/* --------------------------- GL_APPLE_row_bytes -------------------------- */
+
+#if !defined(GL_APPLE_row_bytes)
+#define GL_APPLE_row_bytes 1
+
+#define GL_PACK_ROW_BYTES_APPLE 0x8A15
+#define GL_UNPACK_ROW_BYTES_APPLE 0x8A16
+
+#define GLEW_APPLE_row_bytes GLEW_GET_VAR(__GLEW_APPLE_row_bytes)
+
+#endif /* !GL_APPLE_row_bytes */
+
+/* ------------------------ GL_APPLE_specular_vector ----------------------- */
+
+#if !defined(GL_APPLE_specular_vector)
+#define GL_APPLE_specular_vector 1
+
+#define GL_LIGHT_MODEL_SPECULAR_VECTOR_APPLE 0x85B0
+
+#define GLEW_APPLE_specular_vector GLEW_GET_VAR(__GLEW_APPLE_specular_vector)
+
+#endif /* !GL_APPLE_specular_vector */
+
+/* ------------------------- GL_APPLE_texture_range ------------------------ */
+
+#if !defined(GL_APPLE_texture_range)
+#define GL_APPLE_texture_range 1
+
+#define GL_TEXTURE_RANGE_LENGTH_APPLE 0x85B7
+#define GL_TEXTURE_RANGE_POINTER_APPLE 0x85B8
+#define GL_TEXTURE_STORAGE_HINT_APPLE 0x85BC
+#define GL_STORAGE_PRIVATE_APPLE 0x85BD
+#define GL_STORAGE_CACHED_APPLE 0x85BE
+#define GL_STORAGE_SHARED_APPLE 0x85BF
+
+typedef void (GLAPIENTRY * PFNGLGETTEXPARAMETERPOINTERVAPPLEPROC) (GLenum target, GLenum pname, GLvoid **params);
+typedef void (GLAPIENTRY * PFNGLTEXTURERANGEAPPLEPROC) (GLenum target, GLsizei length, GLvoid *pointer);
+
+#define glGetTexParameterPointervAPPLE GLEW_GET_FUN(__glewGetTexParameterPointervAPPLE)
+#define glTextureRangeAPPLE GLEW_GET_FUN(__glewTextureRangeAPPLE)
+
+#define GLEW_APPLE_texture_range GLEW_GET_VAR(__GLEW_APPLE_texture_range)
+
+#endif /* !GL_APPLE_texture_range */
+
+/* ------------------------ GL_APPLE_transform_hint ------------------------ */
+
+#if !defined(GL_APPLE_transform_hint)
+#define GL_APPLE_transform_hint 1
+
+#define GL_TRANSFORM_HINT_APPLE 0x85B1
+
+#define GLEW_APPLE_transform_hint GLEW_GET_VAR(__GLEW_APPLE_transform_hint)
+
+#endif /* !GL_APPLE_transform_hint */
+
+/* ---------------------- GL_APPLE_vertex_array_object --------------------- */
+
+#if !defined(GL_APPLE_vertex_array_object)
+#define GL_APPLE_vertex_array_object 1
+
+#define GL_VERTEX_ARRAY_BINDING_APPLE 0x85B5
+
+typedef void (GLAPIENTRY * PFNGLBINDVERTEXARRAYAPPLEPROC) (GLuint array);
+typedef void (GLAPIENTRY * PFNGLDELETEVERTEXARRAYSAPPLEPROC) (GLsizei n, const GLuint* arrays);
+typedef void (GLAPIENTRY * PFNGLGENVERTEXARRAYSAPPLEPROC) (GLsizei n, const GLuint* arrays);
+typedef GLboolean (GLAPIENTRY * PFNGLISVERTEXARRAYAPPLEPROC) (GLuint array);
+
+#define glBindVertexArrayAPPLE GLEW_GET_FUN(__glewBindVertexArrayAPPLE)
+#define glDeleteVertexArraysAPPLE GLEW_GET_FUN(__glewDeleteVertexArraysAPPLE)
+#define glGenVertexArraysAPPLE GLEW_GET_FUN(__glewGenVertexArraysAPPLE)
+#define glIsVertexArrayAPPLE GLEW_GET_FUN(__glewIsVertexArrayAPPLE)
+
+#define GLEW_APPLE_vertex_array_object GLEW_GET_VAR(__GLEW_APPLE_vertex_array_object)
+
+#endif /* !GL_APPLE_vertex_array_object */
+
+/* ---------------------- GL_APPLE_vertex_array_range ---------------------- */
+
+#if !defined(GL_APPLE_vertex_array_range)
+#define GL_APPLE_vertex_array_range 1
+
+#define GL_VERTEX_ARRAY_RANGE_APPLE 0x851D
+#define GL_VERTEX_ARRAY_RANGE_LENGTH_APPLE 0x851E
+#define GL_VERTEX_ARRAY_STORAGE_HINT_APPLE 0x851F
+#define GL_MAX_VERTEX_ARRAY_RANGE_ELEMENT_APPLE 0x8520
+#define GL_VERTEX_ARRAY_RANGE_POINTER_APPLE 0x8521
+#define GL_STORAGE_CLIENT_APPLE 0x85B4
+#define GL_STORAGE_CACHED_APPLE 0x85BE
+#define GL_STORAGE_SHARED_APPLE 0x85BF
+
+typedef void (GLAPIENTRY * PFNGLFLUSHVERTEXARRAYRANGEAPPLEPROC) (GLsizei length, void* pointer);
+typedef void (GLAPIENTRY * PFNGLVERTEXARRAYPARAMETERIAPPLEPROC) (GLenum pname, GLint param);
+typedef void (GLAPIENTRY * PFNGLVERTEXARRAYRANGEAPPLEPROC) (GLsizei length, void* pointer);
+
+#define glFlushVertexArrayRangeAPPLE GLEW_GET_FUN(__glewFlushVertexArrayRangeAPPLE)
+#define glVertexArrayParameteriAPPLE GLEW_GET_FUN(__glewVertexArrayParameteriAPPLE)
+#define glVertexArrayRangeAPPLE GLEW_GET_FUN(__glewVertexArrayRangeAPPLE)
+
+#define GLEW_APPLE_vertex_array_range GLEW_GET_VAR(__GLEW_APPLE_vertex_array_range)
+
+#endif /* !GL_APPLE_vertex_array_range */
+
+/* ------------------- GL_APPLE_vertex_program_evaluators ------------------ */
+
+#if !defined(GL_APPLE_vertex_program_evaluators)
+#define GL_APPLE_vertex_program_evaluators 1
+
+#define GL_VERTEX_ATTRIB_MAP1_APPLE 0x8A00
+#define GL_VERTEX_ATTRIB_MAP2_APPLE 0x8A01
+#define GL_VERTEX_ATTRIB_MAP1_SIZE_APPLE 0x8A02
+#define GL_VERTEX_ATTRIB_MAP1_COEFF_APPLE 0x8A03
+#define GL_VERTEX_ATTRIB_MAP1_ORDER_APPLE 0x8A04
+#define GL_VERTEX_ATTRIB_MAP1_DOMAIN_APPLE 0x8A05
+#define GL_VERTEX_ATTRIB_MAP2_SIZE_APPLE 0x8A06
+#define GL_VERTEX_ATTRIB_MAP2_COEFF_APPLE 0x8A07
+#define GL_VERTEX_ATTRIB_MAP2_ORDER_APPLE 0x8A08
+#define GL_VERTEX_ATTRIB_MAP2_DOMAIN_APPLE 0x8A09
+
+typedef void (GLAPIENTRY * PFNGLDISABLEVERTEXATTRIBAPPLEPROC) (GLuint index, GLenum pname);
+typedef void (GLAPIENTRY * PFNGLENABLEVERTEXATTRIBAPPLEPROC) (GLuint index, GLenum pname);
+typedef GLboolean (GLAPIENTRY * PFNGLISVERTEXATTRIBENABLEDAPPLEPROC) (GLuint index, GLenum pname);
+typedef void (GLAPIENTRY * PFNGLMAPVERTEXATTRIB1DAPPLEPROC) (GLuint index, GLuint size, GLdouble u1, GLdouble u2, GLint stride, GLint order, const GLdouble* points);
+typedef void (GLAPIENTRY * PFNGLMAPVERTEXATTRIB1FAPPLEPROC) (GLuint index, GLuint size, GLfloat u1, GLfloat u2, GLint stride, GLint order, const GLfloat* points);
+typedef void (GLAPIENTRY * PFNGLMAPVERTEXATTRIB2DAPPLEPROC) (GLuint index, GLuint size, GLdouble u1, GLdouble u2, GLint ustride, GLint uorder, GLdouble v1, GLdouble v2, GLint vstride, GLint vorder, const GLdouble* points);
+typedef void (GLAPIENTRY * PFNGLMAPVERTEXATTRIB2FAPPLEPROC) (GLuint index, GLuint size, GLfloat u1, GLfloat u2, GLint ustride, GLint uorder, GLfloat v1, GLfloat v2, GLint vstride, GLint vorder, const GLfloat* points);
+
+#define glDisableVertexAttribAPPLE GLEW_GET_FUN(__glewDisableVertexAttribAPPLE)
+#define glEnableVertexAttribAPPLE GLEW_GET_FUN(__glewEnableVertexAttribAPPLE)
+#define glIsVertexAttribEnabledAPPLE GLEW_GET_FUN(__glewIsVertexAttribEnabledAPPLE)
+#define glMapVertexAttrib1dAPPLE GLEW_GET_FUN(__glewMapVertexAttrib1dAPPLE)
+#define glMapVertexAttrib1fAPPLE GLEW_GET_FUN(__glewMapVertexAttrib1fAPPLE)
+#define glMapVertexAttrib2dAPPLE GLEW_GET_FUN(__glewMapVertexAttrib2dAPPLE)
+#define glMapVertexAttrib2fAPPLE GLEW_GET_FUN(__glewMapVertexAttrib2fAPPLE)
+
+#define GLEW_APPLE_vertex_program_evaluators GLEW_GET_VAR(__GLEW_APPLE_vertex_program_evaluators)
+
+#endif /* !GL_APPLE_vertex_program_evaluators */
+
+/* --------------------------- GL_APPLE_ycbcr_422 -------------------------- */
+
+#if !defined(GL_APPLE_ycbcr_422)
+#define GL_APPLE_ycbcr_422 1
+
+#define GL_YCBCR_422_APPLE 0x85B9
+#define GL_UNSIGNED_SHORT_8_8_APPLE 0x85BA
+#define GL_UNSIGNED_SHORT_8_8_REV_APPLE 0x85BB
+
+#define GLEW_APPLE_ycbcr_422 GLEW_GET_VAR(__GLEW_APPLE_ycbcr_422)
+
+#endif /* !GL_APPLE_ycbcr_422 */
+
+/* ------------------------ GL_ARB_ES2_compatibility ----------------------- */
+
+#if !defined(GL_ARB_ES2_compatibility)
+#define GL_ARB_ES2_compatibility 1
+
+#define GL_FIXED 0x140C
+#define GL_IMPLEMENTATION_COLOR_READ_TYPE 0x8B9A
+#define GL_IMPLEMENTATION_COLOR_READ_FORMAT 0x8B9B
+#define GL_RGB565 0x8D62
+#define GL_LOW_FLOAT 0x8DF0
+#define GL_MEDIUM_FLOAT 0x8DF1
+#define GL_HIGH_FLOAT 0x8DF2
+#define GL_LOW_INT 0x8DF3
+#define GL_MEDIUM_INT 0x8DF4
+#define GL_HIGH_INT 0x8DF5
+#define GL_SHADER_BINARY_FORMATS 0x8DF8
+#define GL_NUM_SHADER_BINARY_FORMATS 0x8DF9
+#define GL_SHADER_COMPILER 0x8DFA
+#define GL_MAX_VERTEX_UNIFORM_VECTORS 0x8DFB
+#define GL_MAX_VARYING_VECTORS 0x8DFC
+#define GL_MAX_FRAGMENT_UNIFORM_VECTORS 0x8DFD
+
+typedef void (GLAPIENTRY * PFNGLCLEARDEPTHFPROC) (GLclampf d);
+typedef void (GLAPIENTRY * PFNGLDEPTHRANGEFPROC) (GLclampf n, GLclampf f);
+typedef void (GLAPIENTRY * PFNGLGETSHADERPRECISIONFORMATPROC) (GLenum shadertype, GLenum precisiontype, GLint* range, GLint *precision);
+typedef void (GLAPIENTRY * PFNGLRELEASESHADERCOMPILERPROC) (void);
+typedef void (GLAPIENTRY * PFNGLSHADERBINARYPROC) (GLsizei count, const GLuint* shaders, GLenum binaryformat, const GLvoid*binary, GLsizei length);
+
+#define glClearDepthf GLEW_GET_FUN(__glewClearDepthf)
+#define glDepthRangef GLEW_GET_FUN(__glewDepthRangef)
+#define glGetShaderPrecisionFormat GLEW_GET_FUN(__glewGetShaderPrecisionFormat)
+#define glReleaseShaderCompiler GLEW_GET_FUN(__glewReleaseShaderCompiler)
+#define glShaderBinary GLEW_GET_FUN(__glewShaderBinary)
+
+#define GLEW_ARB_ES2_compatibility GLEW_GET_VAR(__GLEW_ARB_ES2_compatibility)
+
+#endif /* !GL_ARB_ES2_compatibility */
+
+/* ------------------------ GL_ARB_ES3_compatibility ----------------------- */
+
+#if !defined(GL_ARB_ES3_compatibility)
+#define GL_ARB_ES3_compatibility 1
+
+#define GL_TEXTURE_IMMUTABLE_LEVELS 0x82DF
+#define GL_PRIMITIVE_RESTART_FIXED_INDEX 0x8D69
+#define GL_ANY_SAMPLES_PASSED_CONSERVATIVE 0x8D6A
+#define GL_MAX_ELEMENT_INDEX 0x8D6B
+#define GL_COMPRESSED_R11_EAC 0x9270
+#define GL_COMPRESSED_SIGNED_R11_EAC 0x9271
+#define GL_COMPRESSED_RG11_EAC 0x9272
+#define GL_COMPRESSED_SIGNED_RG11_EAC 0x9273
+#define GL_COMPRESSED_RGB8_ETC2 0x9274
+#define GL_COMPRESSED_SRGB8_ETC2 0x9275
+#define GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2 0x9276
+#define GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2 0x9277
+#define GL_COMPRESSED_RGBA8_ETC2_EAC 0x9278
+#define GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC 0x9279
+
+#define GLEW_ARB_ES3_compatibility GLEW_GET_VAR(__GLEW_ARB_ES3_compatibility)
+
+#endif /* !GL_ARB_ES3_compatibility */
+
+/* ------------------------ GL_ARB_arrays_of_arrays ------------------------ */
+
+#if !defined(GL_ARB_arrays_of_arrays)
+#define GL_ARB_arrays_of_arrays 1
+
+#define GLEW_ARB_arrays_of_arrays GLEW_GET_VAR(__GLEW_ARB_arrays_of_arrays)
+
+#endif /* !GL_ARB_arrays_of_arrays */
+
+/* -------------------------- GL_ARB_base_instance ------------------------- */
+
+#if !defined(GL_ARB_base_instance)
+#define GL_ARB_base_instance 1
+
+typedef void (GLAPIENTRY * PFNGLDRAWARRAYSINSTANCEDBASEINSTANCEPROC) (GLenum mode, GLint first, GLsizei count, GLsizei primcount, GLuint baseinstance);
+typedef void (GLAPIENTRY * PFNGLDRAWELEMENTSINSTANCEDBASEINSTANCEPROC) (GLenum mode, GLsizei count, GLenum type, const void* indices, GLsizei primcount, GLuint baseinstance);
+typedef void (GLAPIENTRY * PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXBASEINSTANCEPROC) (GLenum mode, GLsizei count, GLenum type, const void* indices, GLsizei primcount, GLint basevertex, GLuint baseinstance);
+
+#define glDrawArraysInstancedBaseInstance GLEW_GET_FUN(__glewDrawArraysInstancedBaseInstance)
+#define glDrawElementsInstancedBaseInstance GLEW_GET_FUN(__glewDrawElementsInstancedBaseInstance)
+#define glDrawElementsInstancedBaseVertexBaseInstance GLEW_GET_FUN(__glewDrawElementsInstancedBaseVertexBaseInstance)
+
+#define GLEW_ARB_base_instance GLEW_GET_VAR(__GLEW_ARB_base_instance)
+
+#endif /* !GL_ARB_base_instance */
+
+/* ----------------------- GL_ARB_blend_func_extended ---------------------- */
+
+#if !defined(GL_ARB_blend_func_extended)
+#define GL_ARB_blend_func_extended 1
+
+#define GL_SRC1_COLOR 0x88F9
+#define GL_ONE_MINUS_SRC1_COLOR 0x88FA
+#define GL_ONE_MINUS_SRC1_ALPHA 0x88FB
+#define GL_MAX_DUAL_SOURCE_DRAW_BUFFERS 0x88FC
+
+typedef void (GLAPIENTRY * PFNGLBINDFRAGDATALOCATIONINDEXEDPROC) (GLuint program, GLuint colorNumber, GLuint index, const char * name);
+typedef GLint (GLAPIENTRY * PFNGLGETFRAGDATAINDEXPROC) (GLuint program, const char * name);
+
+#define glBindFragDataLocationIndexed GLEW_GET_FUN(__glewBindFragDataLocationIndexed)
+#define glGetFragDataIndex GLEW_GET_FUN(__glewGetFragDataIndex)
+
+#define GLEW_ARB_blend_func_extended GLEW_GET_VAR(__GLEW_ARB_blend_func_extended)
+
+#endif /* !GL_ARB_blend_func_extended */
+
+/* ---------------------------- GL_ARB_cl_event ---------------------------- */
+
+#if !defined(GL_ARB_cl_event)
+#define GL_ARB_cl_event 1
+
+#define GL_SYNC_CL_EVENT_ARB 0x8240
+#define GL_SYNC_CL_EVENT_COMPLETE_ARB 0x8241
+
+typedef struct _cl_context *cl_context;
+typedef struct _cl_event *cl_event;
+
+typedef GLsync (GLAPIENTRY * PFNGLCREATESYNCFROMCLEVENTARBPROC) (cl_context context, cl_event event, GLbitfield flags);
+
+#define glCreateSyncFromCLeventARB GLEW_GET_FUN(__glewCreateSyncFromCLeventARB)
+
+#define GLEW_ARB_cl_event GLEW_GET_VAR(__GLEW_ARB_cl_event)
+
+#endif /* !GL_ARB_cl_event */
+
+/* ----------------------- GL_ARB_clear_buffer_object ---------------------- */
+
+#if !defined(GL_ARB_clear_buffer_object)
+#define GL_ARB_clear_buffer_object 1
+
+typedef void (GLAPIENTRY * PFNGLCLEARBUFFERDATAPROC) (GLenum target, GLenum internalformat, GLenum format, GLenum type, const GLvoid* data);
+typedef void (GLAPIENTRY * PFNGLCLEARBUFFERSUBDATAPROC) (GLenum target, GLenum internalformat, GLintptr offset, GLsizeiptr size, GLenum format, GLenum type, const GLvoid* data);
+typedef void (GLAPIENTRY * PFNGLCLEARNAMEDBUFFERDATAEXTPROC) (GLuint buffer, GLenum internalformat, GLenum format, GLenum type, const GLvoid* data);
+typedef void (GLAPIENTRY * PFNGLCLEARNAMEDBUFFERSUBDATAEXTPROC) (GLuint buffer, GLenum internalformat, GLintptr offset, GLsizeiptr size, GLenum format, GLenum type, const GLvoid* data);
+
+#define glClearBufferData GLEW_GET_FUN(__glewClearBufferData)
+#define glClearBufferSubData GLEW_GET_FUN(__glewClearBufferSubData)
+#define glClearNamedBufferDataEXT GLEW_GET_FUN(__glewClearNamedBufferDataEXT)
+#define glClearNamedBufferSubDataEXT GLEW_GET_FUN(__glewClearNamedBufferSubDataEXT)
+
+#define GLEW_ARB_clear_buffer_object GLEW_GET_VAR(__GLEW_ARB_clear_buffer_object)
+
+#endif /* !GL_ARB_clear_buffer_object */
+
+/* ----------------------- GL_ARB_color_buffer_float ----------------------- */
+
+#if !defined(GL_ARB_color_buffer_float)
+#define GL_ARB_color_buffer_float 1
+
+#define GL_RGBA_FLOAT_MODE_ARB 0x8820
+#define GL_CLAMP_VERTEX_COLOR_ARB 0x891A
+#define GL_CLAMP_FRAGMENT_COLOR_ARB 0x891B
+#define GL_CLAMP_READ_COLOR_ARB 0x891C
+#define GL_FIXED_ONLY_ARB 0x891D
+
+typedef void (GLAPIENTRY * PFNGLCLAMPCOLORARBPROC) (GLenum target, GLenum clamp);
+
+#define glClampColorARB GLEW_GET_FUN(__glewClampColorARB)
+
+#define GLEW_ARB_color_buffer_float GLEW_GET_VAR(__GLEW_ARB_color_buffer_float)
+
+#endif /* !GL_ARB_color_buffer_float */
+
+/* -------------------------- GL_ARB_compatibility ------------------------- */
+
+#if !defined(GL_ARB_compatibility)
+#define GL_ARB_compatibility 1
+
+#define GLEW_ARB_compatibility GLEW_GET_VAR(__GLEW_ARB_compatibility)
+
+#endif /* !GL_ARB_compatibility */
+
+/* ---------------- GL_ARB_compressed_texture_pixel_storage ---------------- */
+
+#if !defined(GL_ARB_compressed_texture_pixel_storage)
+#define GL_ARB_compressed_texture_pixel_storage 1
+
+#define GL_UNPACK_COMPRESSED_BLOCK_WIDTH 0x9127
+#define GL_UNPACK_COMPRESSED_BLOCK_HEIGHT 0x9128
+#define GL_UNPACK_COMPRESSED_BLOCK_DEPTH 0x9129
+#define GL_UNPACK_COMPRESSED_BLOCK_SIZE 0x912A
+#define GL_PACK_COMPRESSED_BLOCK_WIDTH 0x912B
+#define GL_PACK_COMPRESSED_BLOCK_HEIGHT 0x912C
+#define GL_PACK_COMPRESSED_BLOCK_DEPTH 0x912D
+#define GL_PACK_COMPRESSED_BLOCK_SIZE 0x912E
+
+#define GLEW_ARB_compressed_texture_pixel_storage GLEW_GET_VAR(__GLEW_ARB_compressed_texture_pixel_storage)
+
+#endif /* !GL_ARB_compressed_texture_pixel_storage */
+
+/* ------------------------- GL_ARB_compute_shader ------------------------- */
+
+#if !defined(GL_ARB_compute_shader)
+#define GL_ARB_compute_shader 1
+
+#define GL_COMPUTE_SHADER_BIT 0x00000020
+#define GL_MAX_COMPUTE_SHARED_MEMORY_SIZE 0x8262
+#define GL_MAX_COMPUTE_UNIFORM_COMPONENTS 0x8263
+#define GL_MAX_COMPUTE_ATOMIC_COUNTER_BUFFERS 0x8264
+#define GL_MAX_COMPUTE_ATOMIC_COUNTERS 0x8265
+#define GL_MAX_COMBINED_COMPUTE_UNIFORM_COMPONENTS 0x8266
+#define GL_COMPUTE_WORK_GROUP_SIZE 0x8267
+#define GL_MAX_COMPUTE_WORK_GROUP_INVOCATIONS 0x90EB
+#define GL_UNIFORM_BLOCK_REFERENCED_BY_COMPUTE_SHADER 0x90EC
+#define GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_COMPUTE_SHADER 0x90ED
+#define GL_DISPATCH_INDIRECT_BUFFER 0x90EE
+#define GL_DISPATCH_INDIRECT_BUFFER_BINDING 0x90EF
+#define GL_COMPUTE_SHADER 0x91B9
+#define GL_MAX_COMPUTE_UNIFORM_BLOCKS 0x91BB
+#define GL_MAX_COMPUTE_TEXTURE_IMAGE_UNITS 0x91BC
+#define GL_MAX_COMPUTE_IMAGE_UNIFORMS 0x91BD
+#define GL_MAX_COMPUTE_WORK_GROUP_COUNT 0x91BE
+#define GL_MAX_COMPUTE_WORK_GROUP_SIZE 0x91BF
+
+typedef void (GLAPIENTRY * PFNGLDISPATCHCOMPUTEPROC) (GLuint num_groups_x, GLuint num_groups_y, GLuint num_groups_z);
+typedef void (GLAPIENTRY * PFNGLDISPATCHCOMPUTEINDIRECTPROC) (GLintptr indirect);
+
+#define glDispatchCompute GLEW_GET_FUN(__glewDispatchCompute)
+#define glDispatchComputeIndirect GLEW_GET_FUN(__glewDispatchComputeIndirect)
+
+#define GLEW_ARB_compute_shader GLEW_GET_VAR(__GLEW_ARB_compute_shader)
+
+#endif /* !GL_ARB_compute_shader */
+
+/* ----------------------- GL_ARB_conservative_depth ----------------------- */
+
+#if !defined(GL_ARB_conservative_depth)
+#define GL_ARB_conservative_depth 1
+
+#define GLEW_ARB_conservative_depth GLEW_GET_VAR(__GLEW_ARB_conservative_depth)
+
+#endif /* !GL_ARB_conservative_depth */
+
+/* --------------------------- GL_ARB_copy_buffer -------------------------- */
+
+#if !defined(GL_ARB_copy_buffer)
+#define GL_ARB_copy_buffer 1
+
+#define GL_COPY_READ_BUFFER 0x8F36
+#define GL_COPY_WRITE_BUFFER 0x8F37
+
+typedef void (GLAPIENTRY * PFNGLCOPYBUFFERSUBDATAPROC) (GLenum readtarget, GLenum writetarget, GLintptr readoffset, GLintptr writeoffset, GLsizeiptr size);
+
+#define glCopyBufferSubData GLEW_GET_FUN(__glewCopyBufferSubData)
+
+#define GLEW_ARB_copy_buffer GLEW_GET_VAR(__GLEW_ARB_copy_buffer)
+
+#endif /* !GL_ARB_copy_buffer */
+
+/* --------------------------- GL_ARB_copy_image --------------------------- */
+
+#if !defined(GL_ARB_copy_image)
+#define GL_ARB_copy_image 1
+
+typedef void (GLAPIENTRY * PFNGLCOPYIMAGESUBDATAPROC) (GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei srcWidth, GLsizei srcHeight, GLsizei srcDepth);
+
+#define glCopyImageSubData GLEW_GET_FUN(__glewCopyImageSubData)
+
+#define GLEW_ARB_copy_image GLEW_GET_VAR(__GLEW_ARB_copy_image)
+
+#endif /* !GL_ARB_copy_image */
+
+/* -------------------------- GL_ARB_debug_output -------------------------- */
+
+#if !defined(GL_ARB_debug_output)
+#define GL_ARB_debug_output 1
+
+#define GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB 0x8242
+#define GL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH_ARB 0x8243
+#define GL_DEBUG_CALLBACK_FUNCTION_ARB 0x8244
+#define GL_DEBUG_CALLBACK_USER_PARAM_ARB 0x8245
+#define GL_DEBUG_SOURCE_API_ARB 0x8246
+#define GL_DEBUG_SOURCE_WINDOW_SYSTEM_ARB 0x8247
+#define GL_DEBUG_SOURCE_SHADER_COMPILER_ARB 0x8248
+#define GL_DEBUG_SOURCE_THIRD_PARTY_ARB 0x8249
+#define GL_DEBUG_SOURCE_APPLICATION_ARB 0x824A
+#define GL_DEBUG_SOURCE_OTHER_ARB 0x824B
+#define GL_DEBUG_TYPE_ERROR_ARB 0x824C
+#define GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_ARB 0x824D
+#define GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_ARB 0x824E
+#define GL_DEBUG_TYPE_PORTABILITY_ARB 0x824F
+#define GL_DEBUG_TYPE_PERFORMANCE_ARB 0x8250
+#define GL_DEBUG_TYPE_OTHER_ARB 0x8251
+#define GL_MAX_DEBUG_MESSAGE_LENGTH_ARB 0x9143
+#define GL_MAX_DEBUG_LOGGED_MESSAGES_ARB 0x9144
+#define GL_DEBUG_LOGGED_MESSAGES_ARB 0x9145
+#define GL_DEBUG_SEVERITY_HIGH_ARB 0x9146
+#define GL_DEBUG_SEVERITY_MEDIUM_ARB 0x9147
+#define GL_DEBUG_SEVERITY_LOW_ARB 0x9148
+
+typedef void (APIENTRY *GLDEBUGPROCARB)(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar* message, GLvoid* userParam);
+
+typedef void (GLAPIENTRY * PFNGLDEBUGMESSAGECALLBACKARBPROC) (GLDEBUGPROCARB callback, void* userParam);
+typedef void (GLAPIENTRY * PFNGLDEBUGMESSAGECONTROLARBPROC) (GLenum source, GLenum type, GLenum severity, GLsizei count, const GLuint* ids, GLboolean enabled);
+typedef void (GLAPIENTRY * PFNGLDEBUGMESSAGEINSERTARBPROC) (GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const char* buf);
+typedef GLuint (GLAPIENTRY * PFNGLGETDEBUGMESSAGELOGARBPROC) (GLuint count, GLsizei bufsize, GLenum* sources, GLenum* types, GLuint* ids, GLenum* severities, GLsizei* lengths, char* messageLog);
+
+#define glDebugMessageCallbackARB GLEW_GET_FUN(__glewDebugMessageCallbackARB)
+#define glDebugMessageControlARB GLEW_GET_FUN(__glewDebugMessageControlARB)
+#define glDebugMessageInsertARB GLEW_GET_FUN(__glewDebugMessageInsertARB)
+#define glGetDebugMessageLogARB GLEW_GET_FUN(__glewGetDebugMessageLogARB)
+
+#define GLEW_ARB_debug_output GLEW_GET_VAR(__GLEW_ARB_debug_output)
+
+#endif /* !GL_ARB_debug_output */
+
+/* ----------------------- GL_ARB_depth_buffer_float ----------------------- */
+
+#if !defined(GL_ARB_depth_buffer_float)
+#define GL_ARB_depth_buffer_float 1
+
+#define GL_DEPTH_COMPONENT32F 0x8CAC
+#define GL_DEPTH32F_STENCIL8 0x8CAD
+#define GL_FLOAT_32_UNSIGNED_INT_24_8_REV 0x8DAD
+
+#define GLEW_ARB_depth_buffer_float GLEW_GET_VAR(__GLEW_ARB_depth_buffer_float)
+
+#endif /* !GL_ARB_depth_buffer_float */
+
+/* --------------------------- GL_ARB_depth_clamp -------------------------- */
+
+#if !defined(GL_ARB_depth_clamp)
+#define GL_ARB_depth_clamp 1
+
+#define GL_DEPTH_CLAMP 0x864F
+
+#define GLEW_ARB_depth_clamp GLEW_GET_VAR(__GLEW_ARB_depth_clamp)
+
+#endif /* !GL_ARB_depth_clamp */
+
+/* -------------------------- GL_ARB_depth_texture ------------------------- */
+
+#if !defined(GL_ARB_depth_texture)
+#define GL_ARB_depth_texture 1
+
+#define GL_DEPTH_COMPONENT16_ARB 0x81A5
+#define GL_DEPTH_COMPONENT24_ARB 0x81A6
+#define GL_DEPTH_COMPONENT32_ARB 0x81A7
+#define GL_TEXTURE_DEPTH_SIZE_ARB 0x884A
+#define GL_DEPTH_TEXTURE_MODE_ARB 0x884B
+
+#define GLEW_ARB_depth_texture GLEW_GET_VAR(__GLEW_ARB_depth_texture)
+
+#endif /* !GL_ARB_depth_texture */
+
+/* -------------------------- GL_ARB_draw_buffers -------------------------- */
+
+#if !defined(GL_ARB_draw_buffers)
+#define GL_ARB_draw_buffers 1
+
+#define GL_MAX_DRAW_BUFFERS_ARB 0x8824
+#define GL_DRAW_BUFFER0_ARB 0x8825
+#define GL_DRAW_BUFFER1_ARB 0x8826
+#define GL_DRAW_BUFFER2_ARB 0x8827
+#define GL_DRAW_BUFFER3_ARB 0x8828
+#define GL_DRAW_BUFFER4_ARB 0x8829
+#define GL_DRAW_BUFFER5_ARB 0x882A
+#define GL_DRAW_BUFFER6_ARB 0x882B
+#define GL_DRAW_BUFFER7_ARB 0x882C
+#define GL_DRAW_BUFFER8_ARB 0x882D
+#define GL_DRAW_BUFFER9_ARB 0x882E
+#define GL_DRAW_BUFFER10_ARB 0x882F
+#define GL_DRAW_BUFFER11_ARB 0x8830
+#define GL_DRAW_BUFFER12_ARB 0x8831
+#define GL_DRAW_BUFFER13_ARB 0x8832
+#define GL_DRAW_BUFFER14_ARB 0x8833
+#define GL_DRAW_BUFFER15_ARB 0x8834
+
+typedef void (GLAPIENTRY * PFNGLDRAWBUFFERSARBPROC) (GLsizei n, const GLenum* bufs);
+
+#define glDrawBuffersARB GLEW_GET_FUN(__glewDrawBuffersARB)
+
+#define GLEW_ARB_draw_buffers GLEW_GET_VAR(__GLEW_ARB_draw_buffers)
+
+#endif /* !GL_ARB_draw_buffers */
+
+/* ----------------------- GL_ARB_draw_buffers_blend ----------------------- */
+
+#if !defined(GL_ARB_draw_buffers_blend)
+#define GL_ARB_draw_buffers_blend 1
+
+typedef void (GLAPIENTRY * PFNGLBLENDEQUATIONSEPARATEIARBPROC) (GLuint buf, GLenum modeRGB, GLenum modeAlpha);
+typedef void (GLAPIENTRY * PFNGLBLENDEQUATIONIARBPROC) (GLuint buf, GLenum mode);
+typedef void (GLAPIENTRY * PFNGLBLENDFUNCSEPARATEIARBPROC) (GLuint buf, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha);
+typedef void (GLAPIENTRY * PFNGLBLENDFUNCIARBPROC) (GLuint buf, GLenum src, GLenum dst);
+
+#define glBlendEquationSeparateiARB GLEW_GET_FUN(__glewBlendEquationSeparateiARB)
+#define glBlendEquationiARB GLEW_GET_FUN(__glewBlendEquationiARB)
+#define glBlendFuncSeparateiARB GLEW_GET_FUN(__glewBlendFuncSeparateiARB)
+#define glBlendFunciARB GLEW_GET_FUN(__glewBlendFunciARB)
+
+#define GLEW_ARB_draw_buffers_blend GLEW_GET_VAR(__GLEW_ARB_draw_buffers_blend)
+
+#endif /* !GL_ARB_draw_buffers_blend */
+
+/* -------------------- GL_ARB_draw_elements_base_vertex ------------------- */
+
+#if !defined(GL_ARB_draw_elements_base_vertex)
+#define GL_ARB_draw_elements_base_vertex 1
+
+typedef void (GLAPIENTRY * PFNGLDRAWELEMENTSBASEVERTEXPROC) (GLenum mode, GLsizei count, GLenum type, void* indices, GLint basevertex);
+typedef void (GLAPIENTRY * PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXPROC) (GLenum mode, GLsizei count, GLenum type, const void* indices, GLsizei primcount, GLint basevertex);
+typedef void (GLAPIENTRY * PFNGLDRAWRANGEELEMENTSBASEVERTEXPROC) (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, void* indices, GLint basevertex);
+typedef void (GLAPIENTRY * PFNGLMULTIDRAWELEMENTSBASEVERTEXPROC) (GLenum mode, GLsizei* count, GLenum type, GLvoid**indices, GLsizei primcount, GLint *basevertex);
+
+#define glDrawElementsBaseVertex GLEW_GET_FUN(__glewDrawElementsBaseVertex)
+#define glDrawElementsInstancedBaseVertex GLEW_GET_FUN(__glewDrawElementsInstancedBaseVertex)
+#define glDrawRangeElementsBaseVertex GLEW_GET_FUN(__glewDrawRangeElementsBaseVertex)
+#define glMultiDrawElementsBaseVertex GLEW_GET_FUN(__glewMultiDrawElementsBaseVertex)
+
+#define GLEW_ARB_draw_elements_base_vertex GLEW_GET_VAR(__GLEW_ARB_draw_elements_base_vertex)
+
+#endif /* !GL_ARB_draw_elements_base_vertex */
+
+/* -------------------------- GL_ARB_draw_indirect ------------------------- */
+
+#if !defined(GL_ARB_draw_indirect)
+#define GL_ARB_draw_indirect 1
+
+#define GL_DRAW_INDIRECT_BUFFER 0x8F3F
+#define GL_DRAW_INDIRECT_BUFFER_BINDING 0x8F43
+
+typedef void (GLAPIENTRY * PFNGLDRAWARRAYSINDIRECTPROC) (GLenum mode, const void* indirect);
+typedef void (GLAPIENTRY * PFNGLDRAWELEMENTSINDIRECTPROC) (GLenum mode, GLenum type, const void* indirect);
+
+#define glDrawArraysIndirect GLEW_GET_FUN(__glewDrawArraysIndirect)
+#define glDrawElementsIndirect GLEW_GET_FUN(__glewDrawElementsIndirect)
+
+#define GLEW_ARB_draw_indirect GLEW_GET_VAR(__GLEW_ARB_draw_indirect)
+
+#endif /* !GL_ARB_draw_indirect */
+
+/* ------------------------- GL_ARB_draw_instanced ------------------------- */
+
+#if !defined(GL_ARB_draw_instanced)
+#define GL_ARB_draw_instanced 1
+
+#define GLEW_ARB_draw_instanced GLEW_GET_VAR(__GLEW_ARB_draw_instanced)
+
+#endif /* !GL_ARB_draw_instanced */
+
+/* -------------------- GL_ARB_explicit_attrib_location -------------------- */
+
+#if !defined(GL_ARB_explicit_attrib_location)
+#define GL_ARB_explicit_attrib_location 1
+
+#define GLEW_ARB_explicit_attrib_location GLEW_GET_VAR(__GLEW_ARB_explicit_attrib_location)
+
+#endif /* !GL_ARB_explicit_attrib_location */
+
+/* -------------------- GL_ARB_explicit_uniform_location ------------------- */
+
+#if !defined(GL_ARB_explicit_uniform_location)
+#define GL_ARB_explicit_uniform_location 1
+
+#define GL_MAX_UNIFORM_LOCATIONS 0x826E
+
+#define GLEW_ARB_explicit_uniform_location GLEW_GET_VAR(__GLEW_ARB_explicit_uniform_location)
+
+#endif /* !GL_ARB_explicit_uniform_location */
+
+/* ------------------- GL_ARB_fragment_coord_conventions ------------------- */
+
+#if !defined(GL_ARB_fragment_coord_conventions)
+#define GL_ARB_fragment_coord_conventions 1
+
+#define GLEW_ARB_fragment_coord_conventions GLEW_GET_VAR(__GLEW_ARB_fragment_coord_conventions)
+
+#endif /* !GL_ARB_fragment_coord_conventions */
+
+/* --------------------- GL_ARB_fragment_layer_viewport -------------------- */
+
+#if !defined(GL_ARB_fragment_layer_viewport)
+#define GL_ARB_fragment_layer_viewport 1
+
+#define GLEW_ARB_fragment_layer_viewport GLEW_GET_VAR(__GLEW_ARB_fragment_layer_viewport)
+
+#endif /* !GL_ARB_fragment_layer_viewport */
+
+/* ------------------------ GL_ARB_fragment_program ------------------------ */
+
+#if !defined(GL_ARB_fragment_program)
+#define GL_ARB_fragment_program 1
+
+#define GL_FRAGMENT_PROGRAM_ARB 0x8804
+#define GL_PROGRAM_ALU_INSTRUCTIONS_ARB 0x8805
+#define GL_PROGRAM_TEX_INSTRUCTIONS_ARB 0x8806
+#define GL_PROGRAM_TEX_INDIRECTIONS_ARB 0x8807
+#define GL_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB 0x8808
+#define GL_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB 0x8809
+#define GL_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB 0x880A
+#define GL_MAX_PROGRAM_ALU_INSTRUCTIONS_ARB 0x880B
+#define GL_MAX_PROGRAM_TEX_INSTRUCTIONS_ARB 0x880C
+#define GL_MAX_PROGRAM_TEX_INDIRECTIONS_ARB 0x880D
+#define GL_MAX_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB 0x880E
+#define GL_MAX_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB 0x880F
+#define GL_MAX_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB 0x8810
+#define GL_MAX_TEXTURE_COORDS_ARB 0x8871
+#define GL_MAX_TEXTURE_IMAGE_UNITS_ARB 0x8872
+
+#define GLEW_ARB_fragment_program GLEW_GET_VAR(__GLEW_ARB_fragment_program)
+
+#endif /* !GL_ARB_fragment_program */
+
+/* --------------------- GL_ARB_fragment_program_shadow -------------------- */
+
+#if !defined(GL_ARB_fragment_program_shadow)
+#define GL_ARB_fragment_program_shadow 1
+
+#define GLEW_ARB_fragment_program_shadow GLEW_GET_VAR(__GLEW_ARB_fragment_program_shadow)
+
+#endif /* !GL_ARB_fragment_program_shadow */
+
+/* ------------------------- GL_ARB_fragment_shader ------------------------ */
+
+#if !defined(GL_ARB_fragment_shader)
+#define GL_ARB_fragment_shader 1
+
+#define GL_FRAGMENT_SHADER_ARB 0x8B30
+#define GL_MAX_FRAGMENT_UNIFORM_COMPONENTS_ARB 0x8B49
+#define GL_FRAGMENT_SHADER_DERIVATIVE_HINT_ARB 0x8B8B
+
+#define GLEW_ARB_fragment_shader GLEW_GET_VAR(__GLEW_ARB_fragment_shader)
+
+#endif /* !GL_ARB_fragment_shader */
+
+/* ------------------- GL_ARB_framebuffer_no_attachments ------------------- */
+
+#if !defined(GL_ARB_framebuffer_no_attachments)
+#define GL_ARB_framebuffer_no_attachments 1
+
+#define GL_FRAMEBUFFER_DEFAULT_WIDTH 0x9310
+#define GL_FRAMEBUFFER_DEFAULT_HEIGHT 0x9311
+#define GL_FRAMEBUFFER_DEFAULT_LAYERS 0x9312
+#define GL_FRAMEBUFFER_DEFAULT_SAMPLES 0x9313
+#define GL_FRAMEBUFFER_DEFAULT_FIXED_SAMPLE_LOCATIONS 0x9314
+#define GL_MAX_FRAMEBUFFER_WIDTH 0x9315
+#define GL_MAX_FRAMEBUFFER_HEIGHT 0x9316
+#define GL_MAX_FRAMEBUFFER_LAYERS 0x9317
+#define GL_MAX_FRAMEBUFFER_SAMPLES 0x9318
+
+typedef void (GLAPIENTRY * PFNGLFRAMEBUFFERPARAMETERIPROC) (GLenum target, GLenum pname, GLint param);
+typedef void (GLAPIENTRY * PFNGLGETFRAMEBUFFERPARAMETERIVPROC) (GLenum target, GLenum pname, GLint* params);
+typedef void (GLAPIENTRY * PFNGLGETNAMEDFRAMEBUFFERPARAMETERIVEXTPROC) (GLuint framebuffer, GLenum pname, GLint* params);
+typedef void (GLAPIENTRY * PFNGLNAMEDFRAMEBUFFERPARAMETERIEXTPROC) (GLuint framebuffer, GLenum pname, GLint param);
+
+#define glFramebufferParameteri GLEW_GET_FUN(__glewFramebufferParameteri)
+#define glGetFramebufferParameteriv GLEW_GET_FUN(__glewGetFramebufferParameteriv)
+#define glGetNamedFramebufferParameterivEXT GLEW_GET_FUN(__glewGetNamedFramebufferParameterivEXT)
+#define glNamedFramebufferParameteriEXT GLEW_GET_FUN(__glewNamedFramebufferParameteriEXT)
+
+#define GLEW_ARB_framebuffer_no_attachments GLEW_GET_VAR(__GLEW_ARB_framebuffer_no_attachments)
+
+#endif /* !GL_ARB_framebuffer_no_attachments */
+
+/* ----------------------- GL_ARB_framebuffer_object ----------------------- */
+
+#if !defined(GL_ARB_framebuffer_object)
+#define GL_ARB_framebuffer_object 1
+
+#define GL_INVALID_FRAMEBUFFER_OPERATION 0x0506
+#define GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING 0x8210
+#define GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE 0x8211
+#define GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE 0x8212
+#define GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE 0x8213
+#define GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE 0x8214
+#define GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE 0x8215
+#define GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE 0x8216
+#define GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE 0x8217
+#define GL_FRAMEBUFFER_DEFAULT 0x8218
+#define GL_FRAMEBUFFER_UNDEFINED 0x8219
+#define GL_DEPTH_STENCIL_ATTACHMENT 0x821A
+#define GL_INDEX 0x8222
+#define GL_MAX_RENDERBUFFER_SIZE 0x84E8
+#define GL_DEPTH_STENCIL 0x84F9
+#define GL_UNSIGNED_INT_24_8 0x84FA
+#define GL_DEPTH24_STENCIL8 0x88F0
+#define GL_TEXTURE_STENCIL_SIZE 0x88F1
+#define GL_UNSIGNED_NORMALIZED 0x8C17
+#define GL_SRGB 0x8C40
+#define GL_DRAW_FRAMEBUFFER_BINDING 0x8CA6
+#define GL_FRAMEBUFFER_BINDING 0x8CA6
+#define GL_RENDERBUFFER_BINDING 0x8CA7
+#define GL_READ_FRAMEBUFFER 0x8CA8
+#define GL_DRAW_FRAMEBUFFER 0x8CA9
+#define GL_READ_FRAMEBUFFER_BINDING 0x8CAA
+#define GL_RENDERBUFFER_SAMPLES 0x8CAB
+#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE 0x8CD0
+#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME 0x8CD1
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL 0x8CD2
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE 0x8CD3
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER 0x8CD4
+#define GL_FRAMEBUFFER_COMPLETE 0x8CD5
+#define GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT 0x8CD6
+#define GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT 0x8CD7
+#define GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER 0x8CDB
+#define GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER 0x8CDC
+#define GL_FRAMEBUFFER_UNSUPPORTED 0x8CDD
+#define GL_MAX_COLOR_ATTACHMENTS 0x8CDF
+#define GL_COLOR_ATTACHMENT0 0x8CE0
+#define GL_COLOR_ATTACHMENT1 0x8CE1
+#define GL_COLOR_ATTACHMENT2 0x8CE2
+#define GL_COLOR_ATTACHMENT3 0x8CE3
+#define GL_COLOR_ATTACHMENT4 0x8CE4
+#define GL_COLOR_ATTACHMENT5 0x8CE5
+#define GL_COLOR_ATTACHMENT6 0x8CE6
+#define GL_COLOR_ATTACHMENT7 0x8CE7
+#define GL_COLOR_ATTACHMENT8 0x8CE8
+#define GL_COLOR_ATTACHMENT9 0x8CE9
+#define GL_COLOR_ATTACHMENT10 0x8CEA
+#define GL_COLOR_ATTACHMENT11 0x8CEB
+#define GL_COLOR_ATTACHMENT12 0x8CEC
+#define GL_COLOR_ATTACHMENT13 0x8CED
+#define GL_COLOR_ATTACHMENT14 0x8CEE
+#define GL_COLOR_ATTACHMENT15 0x8CEF
+#define GL_DEPTH_ATTACHMENT 0x8D00
+#define GL_STENCIL_ATTACHMENT 0x8D20
+#define GL_FRAMEBUFFER 0x8D40
+#define GL_RENDERBUFFER 0x8D41
+#define GL_RENDERBUFFER_WIDTH 0x8D42
+#define GL_RENDERBUFFER_HEIGHT 0x8D43
+#define GL_RENDERBUFFER_INTERNAL_FORMAT 0x8D44
+#define GL_STENCIL_INDEX1 0x8D46
+#define GL_STENCIL_INDEX4 0x8D47
+#define GL_STENCIL_INDEX8 0x8D48
+#define GL_STENCIL_INDEX16 0x8D49
+#define GL_RENDERBUFFER_RED_SIZE 0x8D50
+#define GL_RENDERBUFFER_GREEN_SIZE 0x8D51
+#define GL_RENDERBUFFER_BLUE_SIZE 0x8D52
+#define GL_RENDERBUFFER_ALPHA_SIZE 0x8D53
+#define GL_RENDERBUFFER_DEPTH_SIZE 0x8D54
+#define GL_RENDERBUFFER_STENCIL_SIZE 0x8D55
+#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE 0x8D56
+#define GL_MAX_SAMPLES 0x8D57
+
+typedef void (GLAPIENTRY * PFNGLBINDFRAMEBUFFERPROC) (GLenum target, GLuint framebuffer);
+typedef void (GLAPIENTRY * PFNGLBINDRENDERBUFFERPROC) (GLenum target, GLuint renderbuffer);
+typedef void (GLAPIENTRY * PFNGLBLITFRAMEBUFFERPROC) (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter);
+typedef GLenum (GLAPIENTRY * PFNGLCHECKFRAMEBUFFERSTATUSPROC) (GLenum target);
+typedef void (GLAPIENTRY * PFNGLDELETEFRAMEBUFFERSPROC) (GLsizei n, const GLuint* framebuffers);
+typedef void (GLAPIENTRY * PFNGLDELETERENDERBUFFERSPROC) (GLsizei n, const GLuint* renderbuffers);
+typedef void (GLAPIENTRY * PFNGLFRAMEBUFFERRENDERBUFFERPROC) (GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer);
+typedef void (GLAPIENTRY * PFNGLFRAMEBUFFERTEXTURE1DPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
+typedef void (GLAPIENTRY * PFNGLFRAMEBUFFERTEXTURE2DPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
+typedef void (GLAPIENTRY * PFNGLFRAMEBUFFERTEXTURE3DPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint layer);
+typedef void (GLAPIENTRY * PFNGLFRAMEBUFFERTEXTURELAYERPROC) (GLenum target,GLenum attachment, GLuint texture,GLint level,GLint layer);
+typedef void (GLAPIENTRY * PFNGLGENFRAMEBUFFERSPROC) (GLsizei n, GLuint* framebuffers);
+typedef void (GLAPIENTRY * PFNGLGENRENDERBUFFERSPROC) (GLsizei n, GLuint* renderbuffers);
+typedef void (GLAPIENTRY * PFNGLGENERATEMIPMAPPROC) (GLenum target);
+typedef void (GLAPIENTRY * PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC) (GLenum target, GLenum attachment, GLenum pname, GLint* params);
+typedef void (GLAPIENTRY * PFNGLGETRENDERBUFFERPARAMETERIVPROC) (GLenum target, GLenum pname, GLint* params);
+typedef GLboolean (GLAPIENTRY * PFNGLISFRAMEBUFFERPROC) (GLuint framebuffer);
+typedef GLboolean (GLAPIENTRY * PFNGLISRENDERBUFFERPROC) (GLuint renderbuffer);
+typedef void (GLAPIENTRY * PFNGLRENDERBUFFERSTORAGEPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
+typedef void (GLAPIENTRY * PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
+
+#define glBindFramebuffer GLEW_GET_FUN(__glewBindFramebuffer)
+#define glBindRenderbuffer GLEW_GET_FUN(__glewBindRenderbuffer)
+#define glBlitFramebuffer GLEW_GET_FUN(__glewBlitFramebuffer)
+#define glCheckFramebufferStatus GLEW_GET_FUN(__glewCheckFramebufferStatus)
+#define glDeleteFramebuffers GLEW_GET_FUN(__glewDeleteFramebuffers)
+#define glDeleteRenderbuffers GLEW_GET_FUN(__glewDeleteRenderbuffers)
+#define glFramebufferRenderbuffer GLEW_GET_FUN(__glewFramebufferRenderbuffer)
+#define glFramebufferTexture1D GLEW_GET_FUN(__glewFramebufferTexture1D)
+#define glFramebufferTexture2D GLEW_GET_FUN(__glewFramebufferTexture2D)
+#define glFramebufferTexture3D GLEW_GET_FUN(__glewFramebufferTexture3D)
+#define glFramebufferTextureLayer GLEW_GET_FUN(__glewFramebufferTextureLayer)
+#define glGenFramebuffers GLEW_GET_FUN(__glewGenFramebuffers)
+#define glGenRenderbuffers GLEW_GET_FUN(__glewGenRenderbuffers)
+#define glGenerateMipmap GLEW_GET_FUN(__glewGenerateMipmap)
+#define glGetFramebufferAttachmentParameteriv GLEW_GET_FUN(__glewGetFramebufferAttachmentParameteriv)
+#define glGetRenderbufferParameteriv GLEW_GET_FUN(__glewGetRenderbufferParameteriv)
+#define glIsFramebuffer GLEW_GET_FUN(__glewIsFramebuffer)
+#define glIsRenderbuffer GLEW_GET_FUN(__glewIsRenderbuffer)
+#define glRenderbufferStorage GLEW_GET_FUN(__glewRenderbufferStorage)
+#define glRenderbufferStorageMultisample GLEW_GET_FUN(__glewRenderbufferStorageMultisample)
+
+#define GLEW_ARB_framebuffer_object GLEW_GET_VAR(__GLEW_ARB_framebuffer_object)
+
+#endif /* !GL_ARB_framebuffer_object */
+
+/* ------------------------ GL_ARB_framebuffer_sRGB ------------------------ */
+
+#if !defined(GL_ARB_framebuffer_sRGB)
+#define GL_ARB_framebuffer_sRGB 1
+
+#define GL_FRAMEBUFFER_SRGB 0x8DB9
+
+#define GLEW_ARB_framebuffer_sRGB GLEW_GET_VAR(__GLEW_ARB_framebuffer_sRGB)
+
+#endif /* !GL_ARB_framebuffer_sRGB */
+
+/* ------------------------ GL_ARB_geometry_shader4 ------------------------ */
+
+#if !defined(GL_ARB_geometry_shader4)
+#define GL_ARB_geometry_shader4 1
+
+#define GL_LINES_ADJACENCY_ARB 0xA
+#define GL_LINE_STRIP_ADJACENCY_ARB 0xB
+#define GL_TRIANGLES_ADJACENCY_ARB 0xC
+#define GL_TRIANGLE_STRIP_ADJACENCY_ARB 0xD
+#define GL_PROGRAM_POINT_SIZE_ARB 0x8642
+#define GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS_ARB 0x8C29
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER 0x8CD4
+#define GL_FRAMEBUFFER_ATTACHMENT_LAYERED_ARB 0x8DA7
+#define GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_ARB 0x8DA8
+#define GL_FRAMEBUFFER_INCOMPLETE_LAYER_COUNT_ARB 0x8DA9
+#define GL_GEOMETRY_SHADER_ARB 0x8DD9
+#define GL_GEOMETRY_VERTICES_OUT_ARB 0x8DDA
+#define GL_GEOMETRY_INPUT_TYPE_ARB 0x8DDB
+#define GL_GEOMETRY_OUTPUT_TYPE_ARB 0x8DDC
+#define GL_MAX_GEOMETRY_VARYING_COMPONENTS_ARB 0x8DDD
+#define GL_MAX_VERTEX_VARYING_COMPONENTS_ARB 0x8DDE
+#define GL_MAX_GEOMETRY_UNIFORM_COMPONENTS_ARB 0x8DDF
+#define GL_MAX_GEOMETRY_OUTPUT_VERTICES_ARB 0x8DE0
+#define GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS_ARB 0x8DE1
+
+typedef void (GLAPIENTRY * PFNGLFRAMEBUFFERTEXTUREARBPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level);
+typedef void (GLAPIENTRY * PFNGLFRAMEBUFFERTEXTUREFACEARBPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level, GLenum face);
+typedef void (GLAPIENTRY * PFNGLFRAMEBUFFERTEXTURELAYERARBPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer);
+typedef void (GLAPIENTRY * PFNGLPROGRAMPARAMETERIARBPROC) (GLuint program, GLenum pname, GLint value);
+
+#define glFramebufferTextureARB GLEW_GET_FUN(__glewFramebufferTextureARB)
+#define glFramebufferTextureFaceARB GLEW_GET_FUN(__glewFramebufferTextureFaceARB)
+#define glFramebufferTextureLayerARB GLEW_GET_FUN(__glewFramebufferTextureLayerARB)
+#define glProgramParameteriARB GLEW_GET_FUN(__glewProgramParameteriARB)
+
+#define GLEW_ARB_geometry_shader4 GLEW_GET_VAR(__GLEW_ARB_geometry_shader4)
+
+#endif /* !GL_ARB_geometry_shader4 */
+
+/* ----------------------- GL_ARB_get_program_binary ----------------------- */
+
+#if !defined(GL_ARB_get_program_binary)
+#define GL_ARB_get_program_binary 1
+
+#define GL_PROGRAM_BINARY_RETRIEVABLE_HINT 0x8257
+#define GL_PROGRAM_BINARY_LENGTH 0x8741
+#define GL_NUM_PROGRAM_BINARY_FORMATS 0x87FE
+#define GL_PROGRAM_BINARY_FORMATS 0x87FF
+
+typedef void (GLAPIENTRY * PFNGLGETPROGRAMBINARYPROC) (GLuint program, GLsizei bufSize, GLsizei* length, GLenum *binaryFormat, GLvoid*binary);
+typedef void (GLAPIENTRY * PFNGLPROGRAMBINARYPROC) (GLuint program, GLenum binaryFormat, const void* binary, GLsizei length);
+typedef void (GLAPIENTRY * PFNGLPROGRAMPARAMETERIPROC) (GLuint program, GLenum pname, GLint value);
+
+#define glGetProgramBinary GLEW_GET_FUN(__glewGetProgramBinary)
+#define glProgramBinary GLEW_GET_FUN(__glewProgramBinary)
+#define glProgramParameteri GLEW_GET_FUN(__glewProgramParameteri)
+
+#define GLEW_ARB_get_program_binary GLEW_GET_VAR(__GLEW_ARB_get_program_binary)
+
+#endif /* !GL_ARB_get_program_binary */
+
+/* --------------------------- GL_ARB_gpu_shader5 -------------------------- */
+
+#if !defined(GL_ARB_gpu_shader5)
+#define GL_ARB_gpu_shader5 1
+
+#define GL_GEOMETRY_SHADER_INVOCATIONS 0x887F
+#define GL_MAX_GEOMETRY_SHADER_INVOCATIONS 0x8E5A
+#define GL_MIN_FRAGMENT_INTERPOLATION_OFFSET 0x8E5B
+#define GL_MAX_FRAGMENT_INTERPOLATION_OFFSET 0x8E5C
+#define GL_FRAGMENT_INTERPOLATION_OFFSET_BITS 0x8E5D
+#define GL_MAX_VERTEX_STREAMS 0x8E71
+
+#define GLEW_ARB_gpu_shader5 GLEW_GET_VAR(__GLEW_ARB_gpu_shader5)
+
+#endif /* !GL_ARB_gpu_shader5 */
+
+/* ------------------------- GL_ARB_gpu_shader_fp64 ------------------------ */
+
+#if !defined(GL_ARB_gpu_shader_fp64)
+#define GL_ARB_gpu_shader_fp64 1
+
+#define GL_DOUBLE_MAT2 0x8F46
+#define GL_DOUBLE_MAT3 0x8F47
+#define GL_DOUBLE_MAT4 0x8F48
+#define GL_DOUBLE_MAT2x3 0x8F49
+#define GL_DOUBLE_MAT2x4 0x8F4A
+#define GL_DOUBLE_MAT3x2 0x8F4B
+#define GL_DOUBLE_MAT3x4 0x8F4C
+#define GL_DOUBLE_MAT4x2 0x8F4D
+#define GL_DOUBLE_MAT4x3 0x8F4E
+#define GL_DOUBLE_VEC2 0x8FFC
+#define GL_DOUBLE_VEC3 0x8FFD
+#define GL_DOUBLE_VEC4 0x8FFE
+
+typedef void (GLAPIENTRY * PFNGLGETUNIFORMDVPROC) (GLuint program, GLint location, GLdouble* params);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM1DEXTPROC) (GLuint program, GLint location, GLdouble x);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM1DVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLdouble* value);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM2DEXTPROC) (GLuint program, GLint location, GLdouble x, GLdouble y);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM2DVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLdouble* value);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM3DEXTPROC) (GLuint program, GLint location, GLdouble x, GLdouble y, GLdouble z);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM3DVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLdouble* value);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM4DEXTPROC) (GLuint program, GLint location, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM4DVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLdouble* value);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX2DVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX2X3DVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX2X4DVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX3DVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX3X2DVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX3X4DVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX4DVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX4X2DVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX4X3DVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value);
+typedef void (GLAPIENTRY * PFNGLUNIFORM1DPROC) (GLint location, GLdouble x);
+typedef void (GLAPIENTRY * PFNGLUNIFORM1DVPROC) (GLint location, GLsizei count, const GLdouble* value);
+typedef void (GLAPIENTRY * PFNGLUNIFORM2DPROC) (GLint location, GLdouble x, GLdouble y);
+typedef void (GLAPIENTRY * PFNGLUNIFORM2DVPROC) (GLint location, GLsizei count, const GLdouble* value);
+typedef void (GLAPIENTRY * PFNGLUNIFORM3DPROC) (GLint location, GLdouble x, GLdouble y, GLdouble z);
+typedef void (GLAPIENTRY * PFNGLUNIFORM3DVPROC) (GLint location, GLsizei count, const GLdouble* value);
+typedef void (GLAPIENTRY * PFNGLUNIFORM4DPROC) (GLint location, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+typedef void (GLAPIENTRY * PFNGLUNIFORM4DVPROC) (GLint location, GLsizei count, const GLdouble* value);
+typedef void (GLAPIENTRY * PFNGLUNIFORMMATRIX2DVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLdouble* value);
+typedef void (GLAPIENTRY * PFNGLUNIFORMMATRIX2X3DVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLdouble* value);
+typedef void (GLAPIENTRY * PFNGLUNIFORMMATRIX2X4DVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLdouble* value);
+typedef void (GLAPIENTRY * PFNGLUNIFORMMATRIX3DVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLdouble* value);
+typedef void (GLAPIENTRY * PFNGLUNIFORMMATRIX3X2DVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLdouble* value);
+typedef void (GLAPIENTRY * PFNGLUNIFORMMATRIX3X4DVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLdouble* value);
+typedef void (GLAPIENTRY * PFNGLUNIFORMMATRIX4DVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLdouble* value);
+typedef void (GLAPIENTRY * PFNGLUNIFORMMATRIX4X2DVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLdouble* value);
+typedef void (GLAPIENTRY * PFNGLUNIFORMMATRIX4X3DVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLdouble* value);
+
+#define glGetUniformdv GLEW_GET_FUN(__glewGetUniformdv)
+#define glProgramUniform1dEXT GLEW_GET_FUN(__glewProgramUniform1dEXT)
+#define glProgramUniform1dvEXT GLEW_GET_FUN(__glewProgramUniform1dvEXT)
+#define glProgramUniform2dEXT GLEW_GET_FUN(__glewProgramUniform2dEXT)
+#define glProgramUniform2dvEXT GLEW_GET_FUN(__glewProgramUniform2dvEXT)
+#define glProgramUniform3dEXT GLEW_GET_FUN(__glewProgramUniform3dEXT)
+#define glProgramUniform3dvEXT GLEW_GET_FUN(__glewProgramUniform3dvEXT)
+#define glProgramUniform4dEXT GLEW_GET_FUN(__glewProgramUniform4dEXT)
+#define glProgramUniform4dvEXT GLEW_GET_FUN(__glewProgramUniform4dvEXT)
+#define glProgramUniformMatrix2dvEXT GLEW_GET_FUN(__glewProgramUniformMatrix2dvEXT)
+#define glProgramUniformMatrix2x3dvEXT GLEW_GET_FUN(__glewProgramUniformMatrix2x3dvEXT)
+#define glProgramUniformMatrix2x4dvEXT GLEW_GET_FUN(__glewProgramUniformMatrix2x4dvEXT)
+#define glProgramUniformMatrix3dvEXT GLEW_GET_FUN(__glewProgramUniformMatrix3dvEXT)
+#define glProgramUniformMatrix3x2dvEXT GLEW_GET_FUN(__glewProgramUniformMatrix3x2dvEXT)
+#define glProgramUniformMatrix3x4dvEXT GLEW_GET_FUN(__glewProgramUniformMatrix3x4dvEXT)
+#define glProgramUniformMatrix4dvEXT GLEW_GET_FUN(__glewProgramUniformMatrix4dvEXT)
+#define glProgramUniformMatrix4x2dvEXT GLEW_GET_FUN(__glewProgramUniformMatrix4x2dvEXT)
+#define glProgramUniformMatrix4x3dvEXT GLEW_GET_FUN(__glewProgramUniformMatrix4x3dvEXT)
+#define glUniform1d GLEW_GET_FUN(__glewUniform1d)
+#define glUniform1dv GLEW_GET_FUN(__glewUniform1dv)
+#define glUniform2d GLEW_GET_FUN(__glewUniform2d)
+#define glUniform2dv GLEW_GET_FUN(__glewUniform2dv)
+#define glUniform3d GLEW_GET_FUN(__glewUniform3d)
+#define glUniform3dv GLEW_GET_FUN(__glewUniform3dv)
+#define glUniform4d GLEW_GET_FUN(__glewUniform4d)
+#define glUniform4dv GLEW_GET_FUN(__glewUniform4dv)
+#define glUniformMatrix2dv GLEW_GET_FUN(__glewUniformMatrix2dv)
+#define glUniformMatrix2x3dv GLEW_GET_FUN(__glewUniformMatrix2x3dv)
+#define glUniformMatrix2x4dv GLEW_GET_FUN(__glewUniformMatrix2x4dv)
+#define glUniformMatrix3dv GLEW_GET_FUN(__glewUniformMatrix3dv)
+#define glUniformMatrix3x2dv GLEW_GET_FUN(__glewUniformMatrix3x2dv)
+#define glUniformMatrix3x4dv GLEW_GET_FUN(__glewUniformMatrix3x4dv)
+#define glUniformMatrix4dv GLEW_GET_FUN(__glewUniformMatrix4dv)
+#define glUniformMatrix4x2dv GLEW_GET_FUN(__glewUniformMatrix4x2dv)
+#define glUniformMatrix4x3dv GLEW_GET_FUN(__glewUniformMatrix4x3dv)
+
+#define GLEW_ARB_gpu_shader_fp64 GLEW_GET_VAR(__GLEW_ARB_gpu_shader_fp64)
+
+#endif /* !GL_ARB_gpu_shader_fp64 */
+
+/* ------------------------ GL_ARB_half_float_pixel ------------------------ */
+
+#if !defined(GL_ARB_half_float_pixel)
+#define GL_ARB_half_float_pixel 1
+
+#define GL_HALF_FLOAT_ARB 0x140B
+
+#define GLEW_ARB_half_float_pixel GLEW_GET_VAR(__GLEW_ARB_half_float_pixel)
+
+#endif /* !GL_ARB_half_float_pixel */
+
+/* ------------------------ GL_ARB_half_float_vertex ----------------------- */
+
+#if !defined(GL_ARB_half_float_vertex)
+#define GL_ARB_half_float_vertex 1
+
+#define GL_HALF_FLOAT 0x140B
+
+#define GLEW_ARB_half_float_vertex GLEW_GET_VAR(__GLEW_ARB_half_float_vertex)
+
+#endif /* !GL_ARB_half_float_vertex */
+
+/* ----------------------------- GL_ARB_imaging ---------------------------- */
+
+#if !defined(GL_ARB_imaging)
+#define GL_ARB_imaging 1
+
+#define GL_CONSTANT_COLOR 0x8001
+#define GL_ONE_MINUS_CONSTANT_COLOR 0x8002
+#define GL_CONSTANT_ALPHA 0x8003
+#define GL_ONE_MINUS_CONSTANT_ALPHA 0x8004
+#define GL_BLEND_COLOR 0x8005
+#define GL_FUNC_ADD 0x8006
+#define GL_MIN 0x8007
+#define GL_MAX 0x8008
+#define GL_BLEND_EQUATION 0x8009
+#define GL_FUNC_SUBTRACT 0x800A
+#define GL_FUNC_REVERSE_SUBTRACT 0x800B
+#define GL_CONVOLUTION_1D 0x8010
+#define GL_CONVOLUTION_2D 0x8011
+#define GL_SEPARABLE_2D 0x8012
+#define GL_CONVOLUTION_BORDER_MODE 0x8013
+#define GL_CONVOLUTION_FILTER_SCALE 0x8014
+#define GL_CONVOLUTION_FILTER_BIAS 0x8015
+#define GL_REDUCE 0x8016
+#define GL_CONVOLUTION_FORMAT 0x8017
+#define GL_CONVOLUTION_WIDTH 0x8018
+#define GL_CONVOLUTION_HEIGHT 0x8019
+#define GL_MAX_CONVOLUTION_WIDTH 0x801A
+#define GL_MAX_CONVOLUTION_HEIGHT 0x801B
+#define GL_POST_CONVOLUTION_RED_SCALE 0x801C
+#define GL_POST_CONVOLUTION_GREEN_SCALE 0x801D
+#define GL_POST_CONVOLUTION_BLUE_SCALE 0x801E
+#define GL_POST_CONVOLUTION_ALPHA_SCALE 0x801F
+#define GL_POST_CONVOLUTION_RED_BIAS 0x8020
+#define GL_POST_CONVOLUTION_GREEN_BIAS 0x8021
+#define GL_POST_CONVOLUTION_BLUE_BIAS 0x8022
+#define GL_POST_CONVOLUTION_ALPHA_BIAS 0x8023
+#define GL_HISTOGRAM 0x8024
+#define GL_PROXY_HISTOGRAM 0x8025
+#define GL_HISTOGRAM_WIDTH 0x8026
+#define GL_HISTOGRAM_FORMAT 0x8027
+#define GL_HISTOGRAM_RED_SIZE 0x8028
+#define GL_HISTOGRAM_GREEN_SIZE 0x8029
+#define GL_HISTOGRAM_BLUE_SIZE 0x802A
+#define GL_HISTOGRAM_ALPHA_SIZE 0x802B
+#define GL_HISTOGRAM_LUMINANCE_SIZE 0x802C
+#define GL_HISTOGRAM_SINK 0x802D
+#define GL_MINMAX 0x802E
+#define GL_MINMAX_FORMAT 0x802F
+#define GL_MINMAX_SINK 0x8030
+#define GL_TABLE_TOO_LARGE 0x8031
+#define GL_COLOR_MATRIX 0x80B1
+#define GL_COLOR_MATRIX_STACK_DEPTH 0x80B2
+#define GL_MAX_COLOR_MATRIX_STACK_DEPTH 0x80B3
+#define GL_POST_COLOR_MATRIX_RED_SCALE 0x80B4
+#define GL_POST_COLOR_MATRIX_GREEN_SCALE 0x80B5
+#define GL_POST_COLOR_MATRIX_BLUE_SCALE 0x80B6
+#define GL_POST_COLOR_MATRIX_ALPHA_SCALE 0x80B7
+#define GL_POST_COLOR_MATRIX_RED_BIAS 0x80B8
+#define GL_POST_COLOR_MATRIX_GREEN_BIAS 0x80B9
+#define GL_POST_COLOR_MATRIX_BLUE_BIAS 0x80BA
+#define GL_POST_COLOR_MATRIX_ALPHA_BIAS 0x80BB
+#define GL_COLOR_TABLE 0x80D0
+#define GL_POST_CONVOLUTION_COLOR_TABLE 0x80D1
+#define GL_POST_COLOR_MATRIX_COLOR_TABLE 0x80D2
+#define GL_PROXY_COLOR_TABLE 0x80D3
+#define GL_PROXY_POST_CONVOLUTION_COLOR_TABLE 0x80D4
+#define GL_PROXY_POST_COLOR_MATRIX_COLOR_TABLE 0x80D5
+#define GL_COLOR_TABLE_SCALE 0x80D6
+#define GL_COLOR_TABLE_BIAS 0x80D7
+#define GL_COLOR_TABLE_FORMAT 0x80D8
+#define GL_COLOR_TABLE_WIDTH 0x80D9
+#define GL_COLOR_TABLE_RED_SIZE 0x80DA
+#define GL_COLOR_TABLE_GREEN_SIZE 0x80DB
+#define GL_COLOR_TABLE_BLUE_SIZE 0x80DC
+#define GL_COLOR_TABLE_ALPHA_SIZE 0x80DD
+#define GL_COLOR_TABLE_LUMINANCE_SIZE 0x80DE
+#define GL_COLOR_TABLE_INTENSITY_SIZE 0x80DF
+#define GL_IGNORE_BORDER 0x8150
+#define GL_CONSTANT_BORDER 0x8151
+#define GL_WRAP_BORDER 0x8152
+#define GL_REPLICATE_BORDER 0x8153
+#define GL_CONVOLUTION_BORDER_COLOR 0x8154
+
+typedef void (GLAPIENTRY * PFNGLCOLORSUBTABLEPROC) (GLenum target, GLsizei start, GLsizei count, GLenum format, GLenum type, const GLvoid *data);
+typedef void (GLAPIENTRY * PFNGLCOLORTABLEPROC) (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const GLvoid *table);
+typedef void (GLAPIENTRY * PFNGLCOLORTABLEPARAMETERFVPROC) (GLenum target, GLenum pname, const GLfloat *params);
+typedef void (GLAPIENTRY * PFNGLCOLORTABLEPARAMETERIVPROC) (GLenum target, GLenum pname, const GLint *params);
+typedef void (GLAPIENTRY * PFNGLCONVOLUTIONFILTER1DPROC) (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const GLvoid *image);
+typedef void (GLAPIENTRY * PFNGLCONVOLUTIONFILTER2DPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *image);
+typedef void (GLAPIENTRY * PFNGLCONVOLUTIONPARAMETERFPROC) (GLenum target, GLenum pname, GLfloat params);
+typedef void (GLAPIENTRY * PFNGLCONVOLUTIONPARAMETERFVPROC) (GLenum target, GLenum pname, const GLfloat *params);
+typedef void (GLAPIENTRY * PFNGLCONVOLUTIONPARAMETERIPROC) (GLenum target, GLenum pname, GLint params);
+typedef void (GLAPIENTRY * PFNGLCONVOLUTIONPARAMETERIVPROC) (GLenum target, GLenum pname, const GLint *params);
+typedef void (GLAPIENTRY * PFNGLCOPYCOLORSUBTABLEPROC) (GLenum target, GLsizei start, GLint x, GLint y, GLsizei width);
+typedef void (GLAPIENTRY * PFNGLCOPYCOLORTABLEPROC) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width);
+typedef void (GLAPIENTRY * PFNGLCOPYCONVOLUTIONFILTER1DPROC) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width);
+typedef void (GLAPIENTRY * PFNGLCOPYCONVOLUTIONFILTER2DPROC) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height);
+typedef void (GLAPIENTRY * PFNGLGETCOLORTABLEPROC) (GLenum target, GLenum format, GLenum type, GLvoid *table);
+typedef void (GLAPIENTRY * PFNGLGETCOLORTABLEPARAMETERFVPROC) (GLenum target, GLenum pname, GLfloat *params);
+typedef void (GLAPIENTRY * PFNGLGETCOLORTABLEPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (GLAPIENTRY * PFNGLGETCONVOLUTIONFILTERPROC) (GLenum target, GLenum format, GLenum type, GLvoid *image);
+typedef void (GLAPIENTRY * PFNGLGETCONVOLUTIONPARAMETERFVPROC) (GLenum target, GLenum pname, GLfloat *params);
+typedef void (GLAPIENTRY * PFNGLGETCONVOLUTIONPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (GLAPIENTRY * PFNGLGETHISTOGRAMPROC) (GLenum target, GLboolean reset, GLenum format, GLenum type, GLvoid *values);
+typedef void (GLAPIENTRY * PFNGLGETHISTOGRAMPARAMETERFVPROC) (GLenum target, GLenum pname, GLfloat *params);
+typedef void (GLAPIENTRY * PFNGLGETHISTOGRAMPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (GLAPIENTRY * PFNGLGETMINMAXPROC) (GLenum target, GLboolean reset, GLenum format, GLenum types, GLvoid *values);
+typedef void (GLAPIENTRY * PFNGLGETMINMAXPARAMETERFVPROC) (GLenum target, GLenum pname, GLfloat *params);
+typedef void (GLAPIENTRY * PFNGLGETMINMAXPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (GLAPIENTRY * PFNGLGETSEPARABLEFILTERPROC) (GLenum target, GLenum format, GLenum type, GLvoid *row, GLvoid *column, GLvoid *span);
+typedef void (GLAPIENTRY * PFNGLHISTOGRAMPROC) (GLenum target, GLsizei width, GLenum internalformat, GLboolean sink);
+typedef void (GLAPIENTRY * PFNGLMINMAXPROC) (GLenum target, GLenum internalformat, GLboolean sink);
+typedef void (GLAPIENTRY * PFNGLRESETHISTOGRAMPROC) (GLenum target);
+typedef void (GLAPIENTRY * PFNGLRESETMINMAXPROC) (GLenum target);
+typedef void (GLAPIENTRY * PFNGLSEPARABLEFILTER2DPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *row, const GLvoid *column);
+
+#define glColorSubTable GLEW_GET_FUN(__glewColorSubTable)
+#define glColorTable GLEW_GET_FUN(__glewColorTable)
+#define glColorTableParameterfv GLEW_GET_FUN(__glewColorTableParameterfv)
+#define glColorTableParameteriv GLEW_GET_FUN(__glewColorTableParameteriv)
+#define glConvolutionFilter1D GLEW_GET_FUN(__glewConvolutionFilter1D)
+#define glConvolutionFilter2D GLEW_GET_FUN(__glewConvolutionFilter2D)
+#define glConvolutionParameterf GLEW_GET_FUN(__glewConvolutionParameterf)
+#define glConvolutionParameterfv GLEW_GET_FUN(__glewConvolutionParameterfv)
+#define glConvolutionParameteri GLEW_GET_FUN(__glewConvolutionParameteri)
+#define glConvolutionParameteriv GLEW_GET_FUN(__glewConvolutionParameteriv)
+#define glCopyColorSubTable GLEW_GET_FUN(__glewCopyColorSubTable)
+#define glCopyColorTable GLEW_GET_FUN(__glewCopyColorTable)
+#define glCopyConvolutionFilter1D GLEW_GET_FUN(__glewCopyConvolutionFilter1D)
+#define glCopyConvolutionFilter2D GLEW_GET_FUN(__glewCopyConvolutionFilter2D)
+#define glGetColorTable GLEW_GET_FUN(__glewGetColorTable)
+#define glGetColorTableParameterfv GLEW_GET_FUN(__glewGetColorTableParameterfv)
+#define glGetColorTableParameteriv GLEW_GET_FUN(__glewGetColorTableParameteriv)
+#define glGetConvolutionFilter GLEW_GET_FUN(__glewGetConvolutionFilter)
+#define glGetConvolutionParameterfv GLEW_GET_FUN(__glewGetConvolutionParameterfv)
+#define glGetConvolutionParameteriv GLEW_GET_FUN(__glewGetConvolutionParameteriv)
+#define glGetHistogram GLEW_GET_FUN(__glewGetHistogram)
+#define glGetHistogramParameterfv GLEW_GET_FUN(__glewGetHistogramParameterfv)
+#define glGetHistogramParameteriv GLEW_GET_FUN(__glewGetHistogramParameteriv)
+#define glGetMinmax GLEW_GET_FUN(__glewGetMinmax)
+#define glGetMinmaxParameterfv GLEW_GET_FUN(__glewGetMinmaxParameterfv)
+#define glGetMinmaxParameteriv GLEW_GET_FUN(__glewGetMinmaxParameteriv)
+#define glGetSeparableFilter GLEW_GET_FUN(__glewGetSeparableFilter)
+#define glHistogram GLEW_GET_FUN(__glewHistogram)
+#define glMinmax GLEW_GET_FUN(__glewMinmax)
+#define glResetHistogram GLEW_GET_FUN(__glewResetHistogram)
+#define glResetMinmax GLEW_GET_FUN(__glewResetMinmax)
+#define glSeparableFilter2D GLEW_GET_FUN(__glewSeparableFilter2D)
+
+#define GLEW_ARB_imaging GLEW_GET_VAR(__GLEW_ARB_imaging)
+
+#endif /* !GL_ARB_imaging */
+
+/* ------------------------ GL_ARB_instanced_arrays ------------------------ */
+
+#if !defined(GL_ARB_instanced_arrays)
+#define GL_ARB_instanced_arrays 1
+
+#define GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ARB 0x88FE
+
+typedef void (GLAPIENTRY * PFNGLDRAWARRAYSINSTANCEDARBPROC) (GLenum mode, GLint first, GLsizei count, GLsizei primcount);
+typedef void (GLAPIENTRY * PFNGLDRAWELEMENTSINSTANCEDARBPROC) (GLenum mode, GLsizei count, GLenum type, const void* indices, GLsizei primcount);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBDIVISORARBPROC) (GLuint index, GLuint divisor);
+
+#define glDrawArraysInstancedARB GLEW_GET_FUN(__glewDrawArraysInstancedARB)
+#define glDrawElementsInstancedARB GLEW_GET_FUN(__glewDrawElementsInstancedARB)
+#define glVertexAttribDivisorARB GLEW_GET_FUN(__glewVertexAttribDivisorARB)
+
+#define GLEW_ARB_instanced_arrays GLEW_GET_VAR(__GLEW_ARB_instanced_arrays)
+
+#endif /* !GL_ARB_instanced_arrays */
+
+/* ---------------------- GL_ARB_internalformat_query ---------------------- */
+
+#if !defined(GL_ARB_internalformat_query)
+#define GL_ARB_internalformat_query 1
+
+#define GL_NUM_SAMPLE_COUNTS 0x9380
+
+typedef void (GLAPIENTRY * PFNGLGETINTERNALFORMATIVPROC) (GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLint* params);
+
+#define glGetInternalformativ GLEW_GET_FUN(__glewGetInternalformativ)
+
+#define GLEW_ARB_internalformat_query GLEW_GET_VAR(__GLEW_ARB_internalformat_query)
+
+#endif /* !GL_ARB_internalformat_query */
+
+/* ---------------------- GL_ARB_internalformat_query2 --------------------- */
+
+#if !defined(GL_ARB_internalformat_query2)
+#define GL_ARB_internalformat_query2 1
+
+#define GL_TEXTURE_1D 0x0DE0
+#define GL_TEXTURE_2D 0x0DE1
+#define GL_TEXTURE_3D 0x806F
+#define GL_SAMPLES 0x80A9
+#define GL_INTERNALFORMAT_SUPPORTED 0x826F
+#define GL_INTERNALFORMAT_PREFERRED 0x8270
+#define GL_INTERNALFORMAT_RED_SIZE 0x8271
+#define GL_INTERNALFORMAT_GREEN_SIZE 0x8272
+#define GL_INTERNALFORMAT_BLUE_SIZE 0x8273
+#define GL_INTERNALFORMAT_ALPHA_SIZE 0x8274
+#define GL_INTERNALFORMAT_DEPTH_SIZE 0x8275
+#define GL_INTERNALFORMAT_STENCIL_SIZE 0x8276
+#define GL_INTERNALFORMAT_SHARED_SIZE 0x8277
+#define GL_INTERNALFORMAT_RED_TYPE 0x8278
+#define GL_INTERNALFORMAT_GREEN_TYPE 0x8279
+#define GL_INTERNALFORMAT_BLUE_TYPE 0x827A
+#define GL_INTERNALFORMAT_ALPHA_TYPE 0x827B
+#define GL_INTERNALFORMAT_DEPTH_TYPE 0x827C
+#define GL_INTERNALFORMAT_STENCIL_TYPE 0x827D
+#define GL_MAX_WIDTH 0x827E
+#define GL_MAX_HEIGHT 0x827F
+#define GL_MAX_DEPTH 0x8280
+#define GL_MAX_LAYERS 0x8281
+#define GL_MAX_COMBINED_DIMENSIONS 0x8282
+#define GL_COLOR_COMPONENTS 0x8283
+#define GL_DEPTH_COMPONENTS 0x8284
+#define GL_STENCIL_COMPONENTS 0x8285
+#define GL_COLOR_RENDERABLE 0x8286
+#define GL_DEPTH_RENDERABLE 0x8287
+#define GL_STENCIL_RENDERABLE 0x8288
+#define GL_FRAMEBUFFER_RENDERABLE 0x8289
+#define GL_FRAMEBUFFER_RENDERABLE_LAYERED 0x828A
+#define GL_FRAMEBUFFER_BLEND 0x828B
+#define GL_READ_PIXELS 0x828C
+#define GL_READ_PIXELS_FORMAT 0x828D
+#define GL_READ_PIXELS_TYPE 0x828E
+#define GL_TEXTURE_IMAGE_FORMAT 0x828F
+#define GL_TEXTURE_IMAGE_TYPE 0x8290
+#define GL_GET_TEXTURE_IMAGE_FORMAT 0x8291
+#define GL_GET_TEXTURE_IMAGE_TYPE 0x8292
+#define GL_MIPMAP 0x8293
+#define GL_MANUAL_GENERATE_MIPMAP 0x8294
+#define GL_AUTO_GENERATE_MIPMAP 0x8295
+#define GL_COLOR_ENCODING 0x8296
+#define GL_SRGB_READ 0x8297
+#define GL_SRGB_WRITE 0x8298
+#define GL_SRGB_DECODE_ARB 0x8299
+#define GL_FILTER 0x829A
+#define GL_VERTEX_TEXTURE 0x829B
+#define GL_TESS_CONTROL_TEXTURE 0x829C
+#define GL_TESS_EVALUATION_TEXTURE 0x829D
+#define GL_GEOMETRY_TEXTURE 0x829E
+#define GL_FRAGMENT_TEXTURE 0x829F
+#define GL_COMPUTE_TEXTURE 0x82A0
+#define GL_TEXTURE_SHADOW 0x82A1
+#define GL_TEXTURE_GATHER 0x82A2
+#define GL_TEXTURE_GATHER_SHADOW 0x82A3
+#define GL_SHADER_IMAGE_LOAD 0x82A4
+#define GL_SHADER_IMAGE_STORE 0x82A5
+#define GL_SHADER_IMAGE_ATOMIC 0x82A6
+#define GL_IMAGE_TEXEL_SIZE 0x82A7
+#define GL_IMAGE_COMPATIBILITY_CLASS 0x82A8
+#define GL_IMAGE_PIXEL_FORMAT 0x82A9
+#define GL_IMAGE_PIXEL_TYPE 0x82AA
+#define GL_SIMULTANEOUS_TEXTURE_AND_DEPTH_TEST 0x82AC
+#define GL_SIMULTANEOUS_TEXTURE_AND_STENCIL_TEST 0x82AD
+#define GL_SIMULTANEOUS_TEXTURE_AND_DEPTH_WRITE 0x82AE
+#define GL_SIMULTANEOUS_TEXTURE_AND_STENCIL_WRITE 0x82AF
+#define GL_TEXTURE_COMPRESSED_BLOCK_WIDTH 0x82B1
+#define GL_TEXTURE_COMPRESSED_BLOCK_HEIGHT 0x82B2
+#define GL_TEXTURE_COMPRESSED_BLOCK_SIZE 0x82B3
+#define GL_CLEAR_BUFFER 0x82B4
+#define GL_TEXTURE_VIEW 0x82B5
+#define GL_VIEW_COMPATIBILITY_CLASS 0x82B6
+#define GL_FULL_SUPPORT 0x82B7
+#define GL_CAVEAT_SUPPORT 0x82B8
+#define GL_IMAGE_CLASS_4_X_32 0x82B9
+#define GL_IMAGE_CLASS_2_X_32 0x82BA
+#define GL_IMAGE_CLASS_1_X_32 0x82BB
+#define GL_IMAGE_CLASS_4_X_16 0x82BC
+#define GL_IMAGE_CLASS_2_X_16 0x82BD
+#define GL_IMAGE_CLASS_1_X_16 0x82BE
+#define GL_IMAGE_CLASS_4_X_8 0x82BF
+#define GL_IMAGE_CLASS_2_X_8 0x82C0
+#define GL_IMAGE_CLASS_1_X_8 0x82C1
+#define GL_IMAGE_CLASS_11_11_10 0x82C2
+#define GL_IMAGE_CLASS_10_10_10_2 0x82C3
+#define GL_VIEW_CLASS_128_BITS 0x82C4
+#define GL_VIEW_CLASS_96_BITS 0x82C5
+#define GL_VIEW_CLASS_64_BITS 0x82C6
+#define GL_VIEW_CLASS_48_BITS 0x82C7
+#define GL_VIEW_CLASS_32_BITS 0x82C8
+#define GL_VIEW_CLASS_24_BITS 0x82C9
+#define GL_VIEW_CLASS_16_BITS 0x82CA
+#define GL_VIEW_CLASS_8_BITS 0x82CB
+#define GL_VIEW_CLASS_S3TC_DXT1_RGB 0x82CC
+#define GL_VIEW_CLASS_S3TC_DXT1_RGBA 0x82CD
+#define GL_VIEW_CLASS_S3TC_DXT3_RGBA 0x82CE
+#define GL_VIEW_CLASS_S3TC_DXT5_RGBA 0x82CF
+#define GL_VIEW_CLASS_RGTC1_RED 0x82D0
+#define GL_VIEW_CLASS_RGTC2_RG 0x82D1
+#define GL_VIEW_CLASS_BPTC_UNORM 0x82D2
+#define GL_VIEW_CLASS_BPTC_FLOAT 0x82D3
+#define GL_TEXTURE_RECTANGLE 0x84F5
+#define GL_TEXTURE_CUBE_MAP 0x8513
+#define GL_TEXTURE_COMPRESSED 0x86A1
+#define GL_TEXTURE_1D_ARRAY 0x8C18
+#define GL_TEXTURE_2D_ARRAY 0x8C1A
+#define GL_TEXTURE_BUFFER 0x8C2A
+#define GL_RENDERBUFFER 0x8D41
+#define GL_TEXTURE_CUBE_MAP_ARRAY 0x9009
+#define GL_IMAGE_FORMAT_COMPATIBILITY_TYPE 0x90C7
+#define GL_TEXTURE_2D_MULTISAMPLE 0x9100
+#define GL_TEXTURE_2D_MULTISAMPLE_ARRAY 0x9102
+#define GL_NUM_SAMPLE_COUNTS 0x9380
+
+typedef void (GLAPIENTRY * PFNGLGETINTERNALFORMATI64VPROC) (GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLint64* params);
+
+#define glGetInternalformati64v GLEW_GET_FUN(__glewGetInternalformati64v)
+
+#define GLEW_ARB_internalformat_query2 GLEW_GET_VAR(__GLEW_ARB_internalformat_query2)
+
+#endif /* !GL_ARB_internalformat_query2 */
+
+/* ----------------------- GL_ARB_invalidate_subdata ----------------------- */
+
+#if !defined(GL_ARB_invalidate_subdata)
+#define GL_ARB_invalidate_subdata 1
+
+typedef void (GLAPIENTRY * PFNGLINVALIDATEBUFFERDATAPROC) (GLuint buffer);
+typedef void (GLAPIENTRY * PFNGLINVALIDATEBUFFERSUBDATAPROC) (GLuint buffer, GLintptr offset, GLsizeiptr length);
+typedef void (GLAPIENTRY * PFNGLINVALIDATEFRAMEBUFFERPROC) (GLenum target, GLsizei numAttachments, const GLenum* attachments);
+typedef void (GLAPIENTRY * PFNGLINVALIDATESUBFRAMEBUFFERPROC) (GLenum target, GLsizei numAttachments, const GLenum* attachments, GLint x, GLint y, GLsizei width, GLsizei height);
+typedef void (GLAPIENTRY * PFNGLINVALIDATETEXIMAGEPROC) (GLuint texture, GLint level);
+typedef void (GLAPIENTRY * PFNGLINVALIDATETEXSUBIMAGEPROC) (GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth);
+
+#define glInvalidateBufferData GLEW_GET_FUN(__glewInvalidateBufferData)
+#define glInvalidateBufferSubData GLEW_GET_FUN(__glewInvalidateBufferSubData)
+#define glInvalidateFramebuffer GLEW_GET_FUN(__glewInvalidateFramebuffer)
+#define glInvalidateSubFramebuffer GLEW_GET_FUN(__glewInvalidateSubFramebuffer)
+#define glInvalidateTexImage GLEW_GET_FUN(__glewInvalidateTexImage)
+#define glInvalidateTexSubImage GLEW_GET_FUN(__glewInvalidateTexSubImage)
+
+#define GLEW_ARB_invalidate_subdata GLEW_GET_VAR(__GLEW_ARB_invalidate_subdata)
+
+#endif /* !GL_ARB_invalidate_subdata */
+
+/* ---------------------- GL_ARB_map_buffer_alignment ---------------------- */
+
+#if !defined(GL_ARB_map_buffer_alignment)
+#define GL_ARB_map_buffer_alignment 1
+
+#define GL_MIN_MAP_BUFFER_ALIGNMENT 0x90BC
+
+#define GLEW_ARB_map_buffer_alignment GLEW_GET_VAR(__GLEW_ARB_map_buffer_alignment)
+
+#endif /* !GL_ARB_map_buffer_alignment */
+
+/* ------------------------ GL_ARB_map_buffer_range ------------------------ */
+
+#if !defined(GL_ARB_map_buffer_range)
+#define GL_ARB_map_buffer_range 1
+
+#define GL_MAP_READ_BIT 0x0001
+#define GL_MAP_WRITE_BIT 0x0002
+#define GL_MAP_INVALIDATE_RANGE_BIT 0x0004
+#define GL_MAP_INVALIDATE_BUFFER_BIT 0x0008
+#define GL_MAP_FLUSH_EXPLICIT_BIT 0x0010
+#define GL_MAP_UNSYNCHRONIZED_BIT 0x0020
+
+typedef void (GLAPIENTRY * PFNGLFLUSHMAPPEDBUFFERRANGEPROC) (GLenum target, GLintptr offset, GLsizeiptr length);
+typedef GLvoid * (GLAPIENTRY * PFNGLMAPBUFFERRANGEPROC) (GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access);
+
+#define glFlushMappedBufferRange GLEW_GET_FUN(__glewFlushMappedBufferRange)
+#define glMapBufferRange GLEW_GET_FUN(__glewMapBufferRange)
+
+#define GLEW_ARB_map_buffer_range GLEW_GET_VAR(__GLEW_ARB_map_buffer_range)
+
+#endif /* !GL_ARB_map_buffer_range */
+
+/* ------------------------- GL_ARB_matrix_palette ------------------------- */
+
+#if !defined(GL_ARB_matrix_palette)
+#define GL_ARB_matrix_palette 1
+
+#define GL_MATRIX_PALETTE_ARB 0x8840
+#define GL_MAX_MATRIX_PALETTE_STACK_DEPTH_ARB 0x8841
+#define GL_MAX_PALETTE_MATRICES_ARB 0x8842
+#define GL_CURRENT_PALETTE_MATRIX_ARB 0x8843
+#define GL_MATRIX_INDEX_ARRAY_ARB 0x8844
+#define GL_CURRENT_MATRIX_INDEX_ARB 0x8845
+#define GL_MATRIX_INDEX_ARRAY_SIZE_ARB 0x8846
+#define GL_MATRIX_INDEX_ARRAY_TYPE_ARB 0x8847
+#define GL_MATRIX_INDEX_ARRAY_STRIDE_ARB 0x8848
+#define GL_MATRIX_INDEX_ARRAY_POINTER_ARB 0x8849
+
+typedef void (GLAPIENTRY * PFNGLCURRENTPALETTEMATRIXARBPROC) (GLint index);
+typedef void (GLAPIENTRY * PFNGLMATRIXINDEXPOINTERARBPROC) (GLint size, GLenum type, GLsizei stride, GLvoid *pointer);
+typedef void (GLAPIENTRY * PFNGLMATRIXINDEXUBVARBPROC) (GLint size, GLubyte *indices);
+typedef void (GLAPIENTRY * PFNGLMATRIXINDEXUIVARBPROC) (GLint size, GLuint *indices);
+typedef void (GLAPIENTRY * PFNGLMATRIXINDEXUSVARBPROC) (GLint size, GLushort *indices);
+
+#define glCurrentPaletteMatrixARB GLEW_GET_FUN(__glewCurrentPaletteMatrixARB)
+#define glMatrixIndexPointerARB GLEW_GET_FUN(__glewMatrixIndexPointerARB)
+#define glMatrixIndexubvARB GLEW_GET_FUN(__glewMatrixIndexubvARB)
+#define glMatrixIndexuivARB GLEW_GET_FUN(__glewMatrixIndexuivARB)
+#define glMatrixIndexusvARB GLEW_GET_FUN(__glewMatrixIndexusvARB)
+
+#define GLEW_ARB_matrix_palette GLEW_GET_VAR(__GLEW_ARB_matrix_palette)
+
+#endif /* !GL_ARB_matrix_palette */
+
+/* ----------------------- GL_ARB_multi_draw_indirect ---------------------- */
+
+#if !defined(GL_ARB_multi_draw_indirect)
+#define GL_ARB_multi_draw_indirect 1
+
+typedef void (GLAPIENTRY * PFNGLMULTIDRAWARRAYSINDIRECTPROC) (GLenum mode, const void* indirect, GLsizei primcount, GLsizei stride);
+typedef void (GLAPIENTRY * PFNGLMULTIDRAWELEMENTSINDIRECTPROC) (GLenum mode, GLenum type, const void* indirect, GLsizei primcount, GLsizei stride);
+
+#define glMultiDrawArraysIndirect GLEW_GET_FUN(__glewMultiDrawArraysIndirect)
+#define glMultiDrawElementsIndirect GLEW_GET_FUN(__glewMultiDrawElementsIndirect)
+
+#define GLEW_ARB_multi_draw_indirect GLEW_GET_VAR(__GLEW_ARB_multi_draw_indirect)
+
+#endif /* !GL_ARB_multi_draw_indirect */
+
+/* --------------------------- GL_ARB_multisample -------------------------- */
+
+#if !defined(GL_ARB_multisample)
+#define GL_ARB_multisample 1
+
+#define GL_MULTISAMPLE_ARB 0x809D
+#define GL_SAMPLE_ALPHA_TO_COVERAGE_ARB 0x809E
+#define GL_SAMPLE_ALPHA_TO_ONE_ARB 0x809F
+#define GL_SAMPLE_COVERAGE_ARB 0x80A0
+#define GL_SAMPLE_BUFFERS_ARB 0x80A8
+#define GL_SAMPLES_ARB 0x80A9
+#define GL_SAMPLE_COVERAGE_VALUE_ARB 0x80AA
+#define GL_SAMPLE_COVERAGE_INVERT_ARB 0x80AB
+#define GL_MULTISAMPLE_BIT_ARB 0x20000000
+
+typedef void (GLAPIENTRY * PFNGLSAMPLECOVERAGEARBPROC) (GLclampf value, GLboolean invert);
+
+#define glSampleCoverageARB GLEW_GET_FUN(__glewSampleCoverageARB)
+
+#define GLEW_ARB_multisample GLEW_GET_VAR(__GLEW_ARB_multisample)
+
+#endif /* !GL_ARB_multisample */
+
+/* -------------------------- GL_ARB_multitexture -------------------------- */
+
+#if !defined(GL_ARB_multitexture)
+#define GL_ARB_multitexture 1
+
+#define GL_TEXTURE0_ARB 0x84C0
+#define GL_TEXTURE1_ARB 0x84C1
+#define GL_TEXTURE2_ARB 0x84C2
+#define GL_TEXTURE3_ARB 0x84C3
+#define GL_TEXTURE4_ARB 0x84C4
+#define GL_TEXTURE5_ARB 0x84C5
+#define GL_TEXTURE6_ARB 0x84C6
+#define GL_TEXTURE7_ARB 0x84C7
+#define GL_TEXTURE8_ARB 0x84C8
+#define GL_TEXTURE9_ARB 0x84C9
+#define GL_TEXTURE10_ARB 0x84CA
+#define GL_TEXTURE11_ARB 0x84CB
+#define GL_TEXTURE12_ARB 0x84CC
+#define GL_TEXTURE13_ARB 0x84CD
+#define GL_TEXTURE14_ARB 0x84CE
+#define GL_TEXTURE15_ARB 0x84CF
+#define GL_TEXTURE16_ARB 0x84D0
+#define GL_TEXTURE17_ARB 0x84D1
+#define GL_TEXTURE18_ARB 0x84D2
+#define GL_TEXTURE19_ARB 0x84D3
+#define GL_TEXTURE20_ARB 0x84D4
+#define GL_TEXTURE21_ARB 0x84D5
+#define GL_TEXTURE22_ARB 0x84D6
+#define GL_TEXTURE23_ARB 0x84D7
+#define GL_TEXTURE24_ARB 0x84D8
+#define GL_TEXTURE25_ARB 0x84D9
+#define GL_TEXTURE26_ARB 0x84DA
+#define GL_TEXTURE27_ARB 0x84DB
+#define GL_TEXTURE28_ARB 0x84DC
+#define GL_TEXTURE29_ARB 0x84DD
+#define GL_TEXTURE30_ARB 0x84DE
+#define GL_TEXTURE31_ARB 0x84DF
+#define GL_ACTIVE_TEXTURE_ARB 0x84E0
+#define GL_CLIENT_ACTIVE_TEXTURE_ARB 0x84E1
+#define GL_MAX_TEXTURE_UNITS_ARB 0x84E2
+
+typedef void (GLAPIENTRY * PFNGLACTIVETEXTUREARBPROC) (GLenum texture);
+typedef void (GLAPIENTRY * PFNGLCLIENTACTIVETEXTUREARBPROC) (GLenum texture);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD1DARBPROC) (GLenum target, GLdouble s);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD1DVARBPROC) (GLenum target, const GLdouble *v);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD1FARBPROC) (GLenum target, GLfloat s);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD1FVARBPROC) (GLenum target, const GLfloat *v);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD1IARBPROC) (GLenum target, GLint s);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD1IVARBPROC) (GLenum target, const GLint *v);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD1SARBPROC) (GLenum target, GLshort s);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD1SVARBPROC) (GLenum target, const GLshort *v);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD2DARBPROC) (GLenum target, GLdouble s, GLdouble t);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD2DVARBPROC) (GLenum target, const GLdouble *v);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD2FARBPROC) (GLenum target, GLfloat s, GLfloat t);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD2FVARBPROC) (GLenum target, const GLfloat *v);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD2IARBPROC) (GLenum target, GLint s, GLint t);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD2IVARBPROC) (GLenum target, const GLint *v);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD2SARBPROC) (GLenum target, GLshort s, GLshort t);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD2SVARBPROC) (GLenum target, const GLshort *v);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD3DARBPROC) (GLenum target, GLdouble s, GLdouble t, GLdouble r);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD3DVARBPROC) (GLenum target, const GLdouble *v);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD3FARBPROC) (GLenum target, GLfloat s, GLfloat t, GLfloat r);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD3FVARBPROC) (GLenum target, const GLfloat *v);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD3IARBPROC) (GLenum target, GLint s, GLint t, GLint r);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD3IVARBPROC) (GLenum target, const GLint *v);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD3SARBPROC) (GLenum target, GLshort s, GLshort t, GLshort r);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD3SVARBPROC) (GLenum target, const GLshort *v);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD4DARBPROC) (GLenum target, GLdouble s, GLdouble t, GLdouble r, GLdouble q);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD4DVARBPROC) (GLenum target, const GLdouble *v);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD4FARBPROC) (GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD4FVARBPROC) (GLenum target, const GLfloat *v);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD4IARBPROC) (GLenum target, GLint s, GLint t, GLint r, GLint q);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD4IVARBPROC) (GLenum target, const GLint *v);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD4SARBPROC) (GLenum target, GLshort s, GLshort t, GLshort r, GLshort q);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD4SVARBPROC) (GLenum target, const GLshort *v);
+
+#define glActiveTextureARB GLEW_GET_FUN(__glewActiveTextureARB)
+#define glClientActiveTextureARB GLEW_GET_FUN(__glewClientActiveTextureARB)
+#define glMultiTexCoord1dARB GLEW_GET_FUN(__glewMultiTexCoord1dARB)
+#define glMultiTexCoord1dvARB GLEW_GET_FUN(__glewMultiTexCoord1dvARB)
+#define glMultiTexCoord1fARB GLEW_GET_FUN(__glewMultiTexCoord1fARB)
+#define glMultiTexCoord1fvARB GLEW_GET_FUN(__glewMultiTexCoord1fvARB)
+#define glMultiTexCoord1iARB GLEW_GET_FUN(__glewMultiTexCoord1iARB)
+#define glMultiTexCoord1ivARB GLEW_GET_FUN(__glewMultiTexCoord1ivARB)
+#define glMultiTexCoord1sARB GLEW_GET_FUN(__glewMultiTexCoord1sARB)
+#define glMultiTexCoord1svARB GLEW_GET_FUN(__glewMultiTexCoord1svARB)
+#define glMultiTexCoord2dARB GLEW_GET_FUN(__glewMultiTexCoord2dARB)
+#define glMultiTexCoord2dvARB GLEW_GET_FUN(__glewMultiTexCoord2dvARB)
+#define glMultiTexCoord2fARB GLEW_GET_FUN(__glewMultiTexCoord2fARB)
+#define glMultiTexCoord2fvARB GLEW_GET_FUN(__glewMultiTexCoord2fvARB)
+#define glMultiTexCoord2iARB GLEW_GET_FUN(__glewMultiTexCoord2iARB)
+#define glMultiTexCoord2ivARB GLEW_GET_FUN(__glewMultiTexCoord2ivARB)
+#define glMultiTexCoord2sARB GLEW_GET_FUN(__glewMultiTexCoord2sARB)
+#define glMultiTexCoord2svARB GLEW_GET_FUN(__glewMultiTexCoord2svARB)
+#define glMultiTexCoord3dARB GLEW_GET_FUN(__glewMultiTexCoord3dARB)
+#define glMultiTexCoord3dvARB GLEW_GET_FUN(__glewMultiTexCoord3dvARB)
+#define glMultiTexCoord3fARB GLEW_GET_FUN(__glewMultiTexCoord3fARB)
+#define glMultiTexCoord3fvARB GLEW_GET_FUN(__glewMultiTexCoord3fvARB)
+#define glMultiTexCoord3iARB GLEW_GET_FUN(__glewMultiTexCoord3iARB)
+#define glMultiTexCoord3ivARB GLEW_GET_FUN(__glewMultiTexCoord3ivARB)
+#define glMultiTexCoord3sARB GLEW_GET_FUN(__glewMultiTexCoord3sARB)
+#define glMultiTexCoord3svARB GLEW_GET_FUN(__glewMultiTexCoord3svARB)
+#define glMultiTexCoord4dARB GLEW_GET_FUN(__glewMultiTexCoord4dARB)
+#define glMultiTexCoord4dvARB GLEW_GET_FUN(__glewMultiTexCoord4dvARB)
+#define glMultiTexCoord4fARB GLEW_GET_FUN(__glewMultiTexCoord4fARB)
+#define glMultiTexCoord4fvARB GLEW_GET_FUN(__glewMultiTexCoord4fvARB)
+#define glMultiTexCoord4iARB GLEW_GET_FUN(__glewMultiTexCoord4iARB)
+#define glMultiTexCoord4ivARB GLEW_GET_FUN(__glewMultiTexCoord4ivARB)
+#define glMultiTexCoord4sARB GLEW_GET_FUN(__glewMultiTexCoord4sARB)
+#define glMultiTexCoord4svARB GLEW_GET_FUN(__glewMultiTexCoord4svARB)
+
+#define GLEW_ARB_multitexture GLEW_GET_VAR(__GLEW_ARB_multitexture)
+
+#endif /* !GL_ARB_multitexture */
+
+/* ------------------------- GL_ARB_occlusion_query ------------------------ */
+
+#if !defined(GL_ARB_occlusion_query)
+#define GL_ARB_occlusion_query 1
+
+#define GL_QUERY_COUNTER_BITS_ARB 0x8864
+#define GL_CURRENT_QUERY_ARB 0x8865
+#define GL_QUERY_RESULT_ARB 0x8866
+#define GL_QUERY_RESULT_AVAILABLE_ARB 0x8867
+#define GL_SAMPLES_PASSED_ARB 0x8914
+
+typedef void (GLAPIENTRY * PFNGLBEGINQUERYARBPROC) (GLenum target, GLuint id);
+typedef void (GLAPIENTRY * PFNGLDELETEQUERIESARBPROC) (GLsizei n, const GLuint* ids);
+typedef void (GLAPIENTRY * PFNGLENDQUERYARBPROC) (GLenum target);
+typedef void (GLAPIENTRY * PFNGLGENQUERIESARBPROC) (GLsizei n, GLuint* ids);
+typedef void (GLAPIENTRY * PFNGLGETQUERYOBJECTIVARBPROC) (GLuint id, GLenum pname, GLint* params);
+typedef void (GLAPIENTRY * PFNGLGETQUERYOBJECTUIVARBPROC) (GLuint id, GLenum pname, GLuint* params);
+typedef void (GLAPIENTRY * PFNGLGETQUERYIVARBPROC) (GLenum target, GLenum pname, GLint* params);
+typedef GLboolean (GLAPIENTRY * PFNGLISQUERYARBPROC) (GLuint id);
+
+#define glBeginQueryARB GLEW_GET_FUN(__glewBeginQueryARB)
+#define glDeleteQueriesARB GLEW_GET_FUN(__glewDeleteQueriesARB)
+#define glEndQueryARB GLEW_GET_FUN(__glewEndQueryARB)
+#define glGenQueriesARB GLEW_GET_FUN(__glewGenQueriesARB)
+#define glGetQueryObjectivARB GLEW_GET_FUN(__glewGetQueryObjectivARB)
+#define glGetQueryObjectuivARB GLEW_GET_FUN(__glewGetQueryObjectuivARB)
+#define glGetQueryivARB GLEW_GET_FUN(__glewGetQueryivARB)
+#define glIsQueryARB GLEW_GET_FUN(__glewIsQueryARB)
+
+#define GLEW_ARB_occlusion_query GLEW_GET_VAR(__GLEW_ARB_occlusion_query)
+
+#endif /* !GL_ARB_occlusion_query */
+
+/* ------------------------ GL_ARB_occlusion_query2 ------------------------ */
+
+#if !defined(GL_ARB_occlusion_query2)
+#define GL_ARB_occlusion_query2 1
+
+#define GL_ANY_SAMPLES_PASSED 0x8C2F
+
+#define GLEW_ARB_occlusion_query2 GLEW_GET_VAR(__GLEW_ARB_occlusion_query2)
+
+#endif /* !GL_ARB_occlusion_query2 */
+
+/* ----------------------- GL_ARB_pixel_buffer_object ---------------------- */
+
+#if !defined(GL_ARB_pixel_buffer_object)
+#define GL_ARB_pixel_buffer_object 1
+
+#define GL_PIXEL_PACK_BUFFER_ARB 0x88EB
+#define GL_PIXEL_UNPACK_BUFFER_ARB 0x88EC
+#define GL_PIXEL_PACK_BUFFER_BINDING_ARB 0x88ED
+#define GL_PIXEL_UNPACK_BUFFER_BINDING_ARB 0x88EF
+
+#define GLEW_ARB_pixel_buffer_object GLEW_GET_VAR(__GLEW_ARB_pixel_buffer_object)
+
+#endif /* !GL_ARB_pixel_buffer_object */
+
+/* ------------------------ GL_ARB_point_parameters ------------------------ */
+
+#if !defined(GL_ARB_point_parameters)
+#define GL_ARB_point_parameters 1
+
+#define GL_POINT_SIZE_MIN_ARB 0x8126
+#define GL_POINT_SIZE_MAX_ARB 0x8127
+#define GL_POINT_FADE_THRESHOLD_SIZE_ARB 0x8128
+#define GL_POINT_DISTANCE_ATTENUATION_ARB 0x8129
+
+typedef void (GLAPIENTRY * PFNGLPOINTPARAMETERFARBPROC) (GLenum pname, GLfloat param);
+typedef void (GLAPIENTRY * PFNGLPOINTPARAMETERFVARBPROC) (GLenum pname, const GLfloat* params);
+
+#define glPointParameterfARB GLEW_GET_FUN(__glewPointParameterfARB)
+#define glPointParameterfvARB GLEW_GET_FUN(__glewPointParameterfvARB)
+
+#define GLEW_ARB_point_parameters GLEW_GET_VAR(__GLEW_ARB_point_parameters)
+
+#endif /* !GL_ARB_point_parameters */
+
+/* -------------------------- GL_ARB_point_sprite -------------------------- */
+
+#if !defined(GL_ARB_point_sprite)
+#define GL_ARB_point_sprite 1
+
+#define GL_POINT_SPRITE_ARB 0x8861
+#define GL_COORD_REPLACE_ARB 0x8862
+
+#define GLEW_ARB_point_sprite GLEW_GET_VAR(__GLEW_ARB_point_sprite)
+
+#endif /* !GL_ARB_point_sprite */
+
+/* --------------------- GL_ARB_program_interface_query -------------------- */
+
+#if !defined(GL_ARB_program_interface_query)
+#define GL_ARB_program_interface_query 1
+
+#define GL_UNIFORM 0x92E1
+#define GL_UNIFORM_BLOCK 0x92E2
+#define GL_PROGRAM_INPUT 0x92E3
+#define GL_PROGRAM_OUTPUT 0x92E4
+#define GL_BUFFER_VARIABLE 0x92E5
+#define GL_SHADER_STORAGE_BLOCK 0x92E6
+#define GL_IS_PER_PATCH 0x92E7
+#define GL_VERTEX_SUBROUTINE 0x92E8
+#define GL_TESS_CONTROL_SUBROUTINE 0x92E9
+#define GL_TESS_EVALUATION_SUBROUTINE 0x92EA
+#define GL_GEOMETRY_SUBROUTINE 0x92EB
+#define GL_FRAGMENT_SUBROUTINE 0x92EC
+#define GL_COMPUTE_SUBROUTINE 0x92ED
+#define GL_VERTEX_SUBROUTINE_UNIFORM 0x92EE
+#define GL_TESS_CONTROL_SUBROUTINE_UNIFORM 0x92EF
+#define GL_TESS_EVALUATION_SUBROUTINE_UNIFORM 0x92F0
+#define GL_GEOMETRY_SUBROUTINE_UNIFORM 0x92F1
+#define GL_FRAGMENT_SUBROUTINE_UNIFORM 0x92F2
+#define GL_COMPUTE_SUBROUTINE_UNIFORM 0x92F3
+#define GL_TRANSFORM_FEEDBACK_VARYING 0x92F4
+#define GL_ACTIVE_RESOURCES 0x92F5
+#define GL_MAX_NAME_LENGTH 0x92F6
+#define GL_MAX_NUM_ACTIVE_VARIABLES 0x92F7
+#define GL_MAX_NUM_COMPATIBLE_SUBROUTINES 0x92F8
+#define GL_NAME_LENGTH 0x92F9
+#define GL_TYPE 0x92FA
+#define GL_ARRAY_SIZE 0x92FB
+#define GL_OFFSET 0x92FC
+#define GL_BLOCK_INDEX 0x92FD
+#define GL_ARRAY_STRIDE 0x92FE
+#define GL_MATRIX_STRIDE 0x92FF
+#define GL_IS_ROW_MAJOR 0x9300
+#define GL_ATOMIC_COUNTER_BUFFER_INDEX 0x9301
+#define GL_BUFFER_BINDING 0x9302
+#define GL_BUFFER_DATA_SIZE 0x9303
+#define GL_NUM_ACTIVE_VARIABLES 0x9304
+#define GL_ACTIVE_VARIABLES 0x9305
+#define GL_REFERENCED_BY_VERTEX_SHADER 0x9306
+#define GL_REFERENCED_BY_TESS_CONTROL_SHADER 0x9307
+#define GL_REFERENCED_BY_TESS_EVALUATION_SHADER 0x9308
+#define GL_REFERENCED_BY_GEOMETRY_SHADER 0x9309
+#define GL_REFERENCED_BY_FRAGMENT_SHADER 0x930A
+#define GL_REFERENCED_BY_COMPUTE_SHADER 0x930B
+#define GL_TOP_LEVEL_ARRAY_SIZE 0x930C
+#define GL_TOP_LEVEL_ARRAY_STRIDE 0x930D
+#define GL_LOCATION 0x930E
+#define GL_LOCATION_INDEX 0x930F
+
+typedef void (GLAPIENTRY * PFNGLGETPROGRAMINTERFACEIVPROC) (GLuint program, GLenum programInterface, GLenum pname, GLint* params);
+typedef GLuint (GLAPIENTRY * PFNGLGETPROGRAMRESOURCEINDEXPROC) (GLuint program, GLenum programInterface, const char* name);
+typedef GLint (GLAPIENTRY * PFNGLGETPROGRAMRESOURCELOCATIONPROC) (GLuint program, GLenum programInterface, const char* name);
+typedef GLint (GLAPIENTRY * PFNGLGETPROGRAMRESOURCELOCATIONINDEXPROC) (GLuint program, GLenum programInterface, const char* name);
+typedef void (GLAPIENTRY * PFNGLGETPROGRAMRESOURCENAMEPROC) (GLuint program, GLenum programInterface, GLuint index, GLsizei bufSize, GLsizei* length, char *name);
+typedef void (GLAPIENTRY * PFNGLGETPROGRAMRESOURCEIVPROC) (GLuint program, GLenum programInterface, GLuint index, GLsizei propCount, const GLenum* props, GLsizei bufSize, GLsizei *length, GLint *params);
+
+#define glGetProgramInterfaceiv GLEW_GET_FUN(__glewGetProgramInterfaceiv)
+#define glGetProgramResourceIndex GLEW_GET_FUN(__glewGetProgramResourceIndex)
+#define glGetProgramResourceLocation GLEW_GET_FUN(__glewGetProgramResourceLocation)
+#define glGetProgramResourceLocationIndex GLEW_GET_FUN(__glewGetProgramResourceLocationIndex)
+#define glGetProgramResourceName GLEW_GET_FUN(__glewGetProgramResourceName)
+#define glGetProgramResourceiv GLEW_GET_FUN(__glewGetProgramResourceiv)
+
+#define GLEW_ARB_program_interface_query GLEW_GET_VAR(__GLEW_ARB_program_interface_query)
+
+#endif /* !GL_ARB_program_interface_query */
+
+/* ------------------------ GL_ARB_provoking_vertex ------------------------ */
+
+#if !defined(GL_ARB_provoking_vertex)
+#define GL_ARB_provoking_vertex 1
+
+#define GL_QUADS_FOLLOW_PROVOKING_VERTEX_CONVENTION 0x8E4C
+#define GL_FIRST_VERTEX_CONVENTION 0x8E4D
+#define GL_LAST_VERTEX_CONVENTION 0x8E4E
+#define GL_PROVOKING_VERTEX 0x8E4F
+
+typedef void (GLAPIENTRY * PFNGLPROVOKINGVERTEXPROC) (GLenum mode);
+
+#define glProvokingVertex GLEW_GET_FUN(__glewProvokingVertex)
+
+#define GLEW_ARB_provoking_vertex GLEW_GET_VAR(__GLEW_ARB_provoking_vertex)
+
+#endif /* !GL_ARB_provoking_vertex */
+
+/* ------------------ GL_ARB_robust_buffer_access_behavior ----------------- */
+
+#if !defined(GL_ARB_robust_buffer_access_behavior)
+#define GL_ARB_robust_buffer_access_behavior 1
+
+#define GLEW_ARB_robust_buffer_access_behavior GLEW_GET_VAR(__GLEW_ARB_robust_buffer_access_behavior)
+
+#endif /* !GL_ARB_robust_buffer_access_behavior */
+
+/* --------------------------- GL_ARB_robustness --------------------------- */
+
+#if !defined(GL_ARB_robustness)
+#define GL_ARB_robustness 1
+
+#define GL_CONTEXT_FLAG_ROBUST_ACCESS_BIT_ARB 0x00000004
+#define GL_LOSE_CONTEXT_ON_RESET_ARB 0x8252
+#define GL_GUILTY_CONTEXT_RESET_ARB 0x8253
+#define GL_INNOCENT_CONTEXT_RESET_ARB 0x8254
+#define GL_UNKNOWN_CONTEXT_RESET_ARB 0x8255
+#define GL_RESET_NOTIFICATION_STRATEGY_ARB 0x8256
+#define GL_NO_RESET_NOTIFICATION_ARB 0x8261
+
+typedef GLenum (GLAPIENTRY * PFNGLGETGRAPHICSRESETSTATUSARBPROC) (void);
+typedef void (GLAPIENTRY * PFNGLGETNCOLORTABLEARBPROC) (GLenum target, GLenum format, GLenum type, GLsizei bufSize, void* table);
+typedef void (GLAPIENTRY * PFNGLGETNCOMPRESSEDTEXIMAGEARBPROC) (GLenum target, GLint lod, GLsizei bufSize, void* img);
+typedef void (GLAPIENTRY * PFNGLGETNCONVOLUTIONFILTERARBPROC) (GLenum target, GLenum format, GLenum type, GLsizei bufSize, void* image);
+typedef void (GLAPIENTRY * PFNGLGETNHISTOGRAMARBPROC) (GLenum target, GLboolean reset, GLenum format, GLenum type, GLsizei bufSize, void* values);
+typedef void (GLAPIENTRY * PFNGLGETNMAPDVARBPROC) (GLenum target, GLenum query, GLsizei bufSize, GLdouble* v);
+typedef void (GLAPIENTRY * PFNGLGETNMAPFVARBPROC) (GLenum target, GLenum query, GLsizei bufSize, GLfloat* v);
+typedef void (GLAPIENTRY * PFNGLGETNMAPIVARBPROC) (GLenum target, GLenum query, GLsizei bufSize, GLint* v);
+typedef void (GLAPIENTRY * PFNGLGETNMINMAXARBPROC) (GLenum target, GLboolean reset, GLenum format, GLenum type, GLsizei bufSize, void* values);
+typedef void (GLAPIENTRY * PFNGLGETNPIXELMAPFVARBPROC) (GLenum map, GLsizei bufSize, GLfloat* values);
+typedef void (GLAPIENTRY * PFNGLGETNPIXELMAPUIVARBPROC) (GLenum map, GLsizei bufSize, GLuint* values);
+typedef void (GLAPIENTRY * PFNGLGETNPIXELMAPUSVARBPROC) (GLenum map, GLsizei bufSize, GLushort* values);
+typedef void (GLAPIENTRY * PFNGLGETNPOLYGONSTIPPLEARBPROC) (GLsizei bufSize, GLubyte* pattern);
+typedef void (GLAPIENTRY * PFNGLGETNSEPARABLEFILTERARBPROC) (GLenum target, GLenum format, GLenum type, GLsizei rowBufSize, void* row, GLsizei columnBufSize, GLvoid*column, GLvoid*span);
+typedef void (GLAPIENTRY * PFNGLGETNTEXIMAGEARBPROC) (GLenum target, GLint level, GLenum format, GLenum type, GLsizei bufSize, void* img);
+typedef void (GLAPIENTRY * PFNGLGETNUNIFORMDVARBPROC) (GLuint program, GLint location, GLsizei bufSize, GLdouble* params);
+typedef void (GLAPIENTRY * PFNGLGETNUNIFORMFVARBPROC) (GLuint program, GLint location, GLsizei bufSize, GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLGETNUNIFORMIVARBPROC) (GLuint program, GLint location, GLsizei bufSize, GLint* params);
+typedef void (GLAPIENTRY * PFNGLGETNUNIFORMUIVARBPROC) (GLuint program, GLint location, GLsizei bufSize, GLuint* params);
+typedef void (GLAPIENTRY * PFNGLREADNPIXELSARBPROC) (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei bufSize, void* data);
+
+#define glGetGraphicsResetStatusARB GLEW_GET_FUN(__glewGetGraphicsResetStatusARB)
+#define glGetnColorTableARB GLEW_GET_FUN(__glewGetnColorTableARB)
+#define glGetnCompressedTexImageARB GLEW_GET_FUN(__glewGetnCompressedTexImageARB)
+#define glGetnConvolutionFilterARB GLEW_GET_FUN(__glewGetnConvolutionFilterARB)
+#define glGetnHistogramARB GLEW_GET_FUN(__glewGetnHistogramARB)
+#define glGetnMapdvARB GLEW_GET_FUN(__glewGetnMapdvARB)
+#define glGetnMapfvARB GLEW_GET_FUN(__glewGetnMapfvARB)
+#define glGetnMapivARB GLEW_GET_FUN(__glewGetnMapivARB)
+#define glGetnMinmaxARB GLEW_GET_FUN(__glewGetnMinmaxARB)
+#define glGetnPixelMapfvARB GLEW_GET_FUN(__glewGetnPixelMapfvARB)
+#define glGetnPixelMapuivARB GLEW_GET_FUN(__glewGetnPixelMapuivARB)
+#define glGetnPixelMapusvARB GLEW_GET_FUN(__glewGetnPixelMapusvARB)
+#define glGetnPolygonStippleARB GLEW_GET_FUN(__glewGetnPolygonStippleARB)
+#define glGetnSeparableFilterARB GLEW_GET_FUN(__glewGetnSeparableFilterARB)
+#define glGetnTexImageARB GLEW_GET_FUN(__glewGetnTexImageARB)
+#define glGetnUniformdvARB GLEW_GET_FUN(__glewGetnUniformdvARB)
+#define glGetnUniformfvARB GLEW_GET_FUN(__glewGetnUniformfvARB)
+#define glGetnUniformivARB GLEW_GET_FUN(__glewGetnUniformivARB)
+#define glGetnUniformuivARB GLEW_GET_FUN(__glewGetnUniformuivARB)
+#define glReadnPixelsARB GLEW_GET_FUN(__glewReadnPixelsARB)
+
+#define GLEW_ARB_robustness GLEW_GET_VAR(__GLEW_ARB_robustness)
+
+#endif /* !GL_ARB_robustness */
+
+/* ---------------- GL_ARB_robustness_application_isolation ---------------- */
+
+#if !defined(GL_ARB_robustness_application_isolation)
+#define GL_ARB_robustness_application_isolation 1
+
+#define GLEW_ARB_robustness_application_isolation GLEW_GET_VAR(__GLEW_ARB_robustness_application_isolation)
+
+#endif /* !GL_ARB_robustness_application_isolation */
+
+/* ---------------- GL_ARB_robustness_share_group_isolation ---------------- */
+
+#if !defined(GL_ARB_robustness_share_group_isolation)
+#define GL_ARB_robustness_share_group_isolation 1
+
+#define GLEW_ARB_robustness_share_group_isolation GLEW_GET_VAR(__GLEW_ARB_robustness_share_group_isolation)
+
+#endif /* !GL_ARB_robustness_share_group_isolation */
+
+/* ------------------------- GL_ARB_sample_shading ------------------------- */
+
+#if !defined(GL_ARB_sample_shading)
+#define GL_ARB_sample_shading 1
+
+#define GL_SAMPLE_SHADING_ARB 0x8C36
+#define GL_MIN_SAMPLE_SHADING_VALUE_ARB 0x8C37
+
+typedef void (GLAPIENTRY * PFNGLMINSAMPLESHADINGARBPROC) (GLclampf value);
+
+#define glMinSampleShadingARB GLEW_GET_FUN(__glewMinSampleShadingARB)
+
+#define GLEW_ARB_sample_shading GLEW_GET_VAR(__GLEW_ARB_sample_shading)
+
+#endif /* !GL_ARB_sample_shading */
+
+/* ------------------------- GL_ARB_sampler_objects ------------------------ */
+
+#if !defined(GL_ARB_sampler_objects)
+#define GL_ARB_sampler_objects 1
+
+#define GL_SAMPLER_BINDING 0x8919
+
+typedef void (GLAPIENTRY * PFNGLBINDSAMPLERPROC) (GLuint unit, GLuint sampler);
+typedef void (GLAPIENTRY * PFNGLDELETESAMPLERSPROC) (GLsizei count, const GLuint * samplers);
+typedef void (GLAPIENTRY * PFNGLGENSAMPLERSPROC) (GLsizei count, GLuint* samplers);
+typedef void (GLAPIENTRY * PFNGLGETSAMPLERPARAMETERIIVPROC) (GLuint sampler, GLenum pname, GLint* params);
+typedef void (GLAPIENTRY * PFNGLGETSAMPLERPARAMETERIUIVPROC) (GLuint sampler, GLenum pname, GLuint* params);
+typedef void (GLAPIENTRY * PFNGLGETSAMPLERPARAMETERFVPROC) (GLuint sampler, GLenum pname, GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLGETSAMPLERPARAMETERIVPROC) (GLuint sampler, GLenum pname, GLint* params);
+typedef GLboolean (GLAPIENTRY * PFNGLISSAMPLERPROC) (GLuint sampler);
+typedef void (GLAPIENTRY * PFNGLSAMPLERPARAMETERIIVPROC) (GLuint sampler, GLenum pname, const GLint* params);
+typedef void (GLAPIENTRY * PFNGLSAMPLERPARAMETERIUIVPROC) (GLuint sampler, GLenum pname, const GLuint* params);
+typedef void (GLAPIENTRY * PFNGLSAMPLERPARAMETERFPROC) (GLuint sampler, GLenum pname, GLfloat param);
+typedef void (GLAPIENTRY * PFNGLSAMPLERPARAMETERFVPROC) (GLuint sampler, GLenum pname, const GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLSAMPLERPARAMETERIPROC) (GLuint sampler, GLenum pname, GLint param);
+typedef void (GLAPIENTRY * PFNGLSAMPLERPARAMETERIVPROC) (GLuint sampler, GLenum pname, const GLint* params);
+
+#define glBindSampler GLEW_GET_FUN(__glewBindSampler)
+#define glDeleteSamplers GLEW_GET_FUN(__glewDeleteSamplers)
+#define glGenSamplers GLEW_GET_FUN(__glewGenSamplers)
+#define glGetSamplerParameterIiv GLEW_GET_FUN(__glewGetSamplerParameterIiv)
+#define glGetSamplerParameterIuiv GLEW_GET_FUN(__glewGetSamplerParameterIuiv)
+#define glGetSamplerParameterfv GLEW_GET_FUN(__glewGetSamplerParameterfv)
+#define glGetSamplerParameteriv GLEW_GET_FUN(__glewGetSamplerParameteriv)
+#define glIsSampler GLEW_GET_FUN(__glewIsSampler)
+#define glSamplerParameterIiv GLEW_GET_FUN(__glewSamplerParameterIiv)
+#define glSamplerParameterIuiv GLEW_GET_FUN(__glewSamplerParameterIuiv)
+#define glSamplerParameterf GLEW_GET_FUN(__glewSamplerParameterf)
+#define glSamplerParameterfv GLEW_GET_FUN(__glewSamplerParameterfv)
+#define glSamplerParameteri GLEW_GET_FUN(__glewSamplerParameteri)
+#define glSamplerParameteriv GLEW_GET_FUN(__glewSamplerParameteriv)
+
+#define GLEW_ARB_sampler_objects GLEW_GET_VAR(__GLEW_ARB_sampler_objects)
+
+#endif /* !GL_ARB_sampler_objects */
+
+/* ------------------------ GL_ARB_seamless_cube_map ----------------------- */
+
+#if !defined(GL_ARB_seamless_cube_map)
+#define GL_ARB_seamless_cube_map 1
+
+#define GL_TEXTURE_CUBE_MAP_SEAMLESS 0x884F
+
+#define GLEW_ARB_seamless_cube_map GLEW_GET_VAR(__GLEW_ARB_seamless_cube_map)
+
+#endif /* !GL_ARB_seamless_cube_map */
+
+#if 0 // NOTE jwilkins: there is an inconsistency between the ES and Non-ES versions of this extension??
+/* --------------------- GL_ARB_separate_shader_objects -------------------- */
+
+#if !defined(GL_ARB_separate_shader_objects)
+#define GL_ARB_separate_shader_objects 1
+
+#define GL_VERTEX_SHADER_BIT 0x00000001
+#define GL_FRAGMENT_SHADER_BIT 0x00000002
+#define GL_GEOMETRY_SHADER_BIT 0x00000004
+#define GL_TESS_CONTROL_SHADER_BIT 0x00000008
+#define GL_TESS_EVALUATION_SHADER_BIT 0x00000010
+#define GL_PROGRAM_SEPARABLE 0x8258
+#define GL_ACTIVE_PROGRAM 0x8259
+#define GL_PROGRAM_PIPELINE_BINDING 0x825A
+#define GL_ALL_SHADER_BITS 0xFFFFFFFF
+
+typedef void (GLAPIENTRY * PFNGLACTIVESHADERPROGRAMPROC) (GLuint pipeline, GLuint program);
+typedef void (GLAPIENTRY * PFNGLBINDPROGRAMPIPELINEPROC) (GLuint pipeline);
+typedef GLuint (GLAPIENTRY * PFNGLCREATESHADERPROGRAMVPROC) (GLenum type, GLsizei count, const char ** strings);
+typedef void (GLAPIENTRY * PFNGLDELETEPROGRAMPIPELINESPROC) (GLsizei n, const GLuint* pipelines);
+typedef void (GLAPIENTRY * PFNGLGENPROGRAMPIPELINESPROC) (GLsizei n, GLuint* pipelines);
+typedef void (GLAPIENTRY * PFNGLGETPROGRAMPIPELINEINFOLOGPROC) (GLuint pipeline, GLsizei bufSize, GLsizei* length, char *infoLog);
+typedef void (GLAPIENTRY * PFNGLGETPROGRAMPIPELINEIVPROC) (GLuint pipeline, GLenum pname, GLint* params);
+typedef GLboolean (GLAPIENTRY * PFNGLISPROGRAMPIPELINEPROC) (GLuint pipeline);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM1DPROC) (GLuint program, GLint location, GLdouble x);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM1DVPROC) (GLuint program, GLint location, GLsizei count, const GLdouble* value);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM1FPROC) (GLuint program, GLint location, GLfloat x);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM1FVPROC) (GLuint program, GLint location, GLsizei count, const GLfloat* value);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM1IPROC) (GLuint program, GLint location, GLint x);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM1IVPROC) (GLuint program, GLint location, GLsizei count, const GLint* value);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM1UIPROC) (GLuint program, GLint location, GLuint x);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM1UIVPROC) (GLuint program, GLint location, GLsizei count, const GLuint* value);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM2DPROC) (GLuint program, GLint location, GLdouble x, GLdouble y);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM2DVPROC) (GLuint program, GLint location, GLsizei count, const GLdouble* value);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM2FPROC) (GLuint program, GLint location, GLfloat x, GLfloat y);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM2FVPROC) (GLuint program, GLint location, GLsizei count, const GLfloat* value);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM2IPROC) (GLuint program, GLint location, GLint x, GLint y);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM2IVPROC) (GLuint program, GLint location, GLsizei count, const GLint* value);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM2UIPROC) (GLuint program, GLint location, GLuint x, GLuint y);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM2UIVPROC) (GLuint program, GLint location, GLsizei count, const GLuint* value);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM3DPROC) (GLuint program, GLint location, GLdouble x, GLdouble y, GLdouble z);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM3DVPROC) (GLuint program, GLint location, GLsizei count, const GLdouble* value);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM3FPROC) (GLuint program, GLint location, GLfloat x, GLfloat y, GLfloat z);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM3FVPROC) (GLuint program, GLint location, GLsizei count, const GLfloat* value);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM3IPROC) (GLuint program, GLint location, GLint x, GLint y, GLint z);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM3IVPROC) (GLuint program, GLint location, GLsizei count, const GLint* value);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM3UIPROC) (GLuint program, GLint location, GLuint x, GLuint y, GLuint z);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM3UIVPROC) (GLuint program, GLint location, GLsizei count, const GLuint* value);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM4DPROC) (GLuint program, GLint location, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM4DVPROC) (GLuint program, GLint location, GLsizei count, const GLdouble* value);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM4FPROC) (GLuint program, GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM4FVPROC) (GLuint program, GLint location, GLsizei count, const GLfloat* value);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM4IPROC) (GLuint program, GLint location, GLint x, GLint y, GLint z, GLint w);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM4IVPROC) (GLuint program, GLint location, GLsizei count, const GLint* value);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM4UIPROC) (GLuint program, GLint location, GLuint x, GLuint y, GLuint z, GLuint w);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM4UIVPROC) (GLuint program, GLint location, GLsizei count, const GLuint* value);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX2DVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX2FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX2X3DVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX2X3FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX2X4DVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX2X4FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX3DVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX3FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX3X2DVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX3X2FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX3X4DVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX3X4FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX4DVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX4FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX4X2DVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX4X2FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX4X3DVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX4X3FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
+typedef void (GLAPIENTRY * PFNGLUSEPROGRAMSTAGESPROC) (GLuint pipeline, GLbitfield stages, GLuint program);
+typedef void (GLAPIENTRY * PFNGLVALIDATEPROGRAMPIPELINEPROC) (GLuint pipeline);
+
+#define glActiveShaderProgram GLEW_GET_FUN(__glewActiveShaderProgram)
+#define glBindProgramPipeline GLEW_GET_FUN(__glewBindProgramPipeline)
+#define glCreateShaderProgramv GLEW_GET_FUN(__glewCreateShaderProgramv)
+#define glDeleteProgramPipelines GLEW_GET_FUN(__glewDeleteProgramPipelines)
+#define glGenProgramPipelines GLEW_GET_FUN(__glewGenProgramPipelines)
+#define glGetProgramPipelineInfoLog GLEW_GET_FUN(__glewGetProgramPipelineInfoLog)
+#define glGetProgramPipelineiv GLEW_GET_FUN(__glewGetProgramPipelineiv)
+#define glIsProgramPipeline GLEW_GET_FUN(__glewIsProgramPipeline)
+#define glProgramUniform1d GLEW_GET_FUN(__glewProgramUniform1d)
+#define glProgramUniform1dv GLEW_GET_FUN(__glewProgramUniform1dv)
+#define glProgramUniform1f GLEW_GET_FUN(__glewProgramUniform1f)
+#define glProgramUniform1fv GLEW_GET_FUN(__glewProgramUniform1fv)
+#define glProgramUniform1i GLEW_GET_FUN(__glewProgramUniform1i)
+#define glProgramUniform1iv GLEW_GET_FUN(__glewProgramUniform1iv)
+#define glProgramUniform1ui GLEW_GET_FUN(__glewProgramUniform1ui)
+#define glProgramUniform1uiv GLEW_GET_FUN(__glewProgramUniform1uiv)
+#define glProgramUniform2d GLEW_GET_FUN(__glewProgramUniform2d)
+#define glProgramUniform2dv GLEW_GET_FUN(__glewProgramUniform2dv)
+#define glProgramUniform2f GLEW_GET_FUN(__glewProgramUniform2f)
+#define glProgramUniform2fv GLEW_GET_FUN(__glewProgramUniform2fv)
+#define glProgramUniform2i GLEW_GET_FUN(__glewProgramUniform2i)
+#define glProgramUniform2iv GLEW_GET_FUN(__glewProgramUniform2iv)
+#define glProgramUniform2ui GLEW_GET_FUN(__glewProgramUniform2ui)
+#define glProgramUniform2uiv GLEW_GET_FUN(__glewProgramUniform2uiv)
+#define glProgramUniform3d GLEW_GET_FUN(__glewProgramUniform3d)
+#define glProgramUniform3dv GLEW_GET_FUN(__glewProgramUniform3dv)
+#define glProgramUniform3f GLEW_GET_FUN(__glewProgramUniform3f)
+#define glProgramUniform3fv GLEW_GET_FUN(__glewProgramUniform3fv)
+#define glProgramUniform3i GLEW_GET_FUN(__glewProgramUniform3i)
+#define glProgramUniform3iv GLEW_GET_FUN(__glewProgramUniform3iv)
+#define glProgramUniform3ui GLEW_GET_FUN(__glewProgramUniform3ui)
+#define glProgramUniform3uiv GLEW_GET_FUN(__glewProgramUniform3uiv)
+#define glProgramUniform4d GLEW_GET_FUN(__glewProgramUniform4d)
+#define glProgramUniform4dv GLEW_GET_FUN(__glewProgramUniform4dv)
+#define glProgramUniform4f GLEW_GET_FUN(__glewProgramUniform4f)
+#define glProgramUniform4fv GLEW_GET_FUN(__glewProgramUniform4fv)
+#define glProgramUniform4i GLEW_GET_FUN(__glewProgramUniform4i)
+#define glProgramUniform4iv GLEW_GET_FUN(__glewProgramUniform4iv)
+#define glProgramUniform4ui GLEW_GET_FUN(__glewProgramUniform4ui)
+#define glProgramUniform4uiv GLEW_GET_FUN(__glewProgramUniform4uiv)
+#define glProgramUniformMatrix2dv GLEW_GET_FUN(__glewProgramUniformMatrix2dv)
+#define glProgramUniformMatrix2fv GLEW_GET_FUN(__glewProgramUniformMatrix2fv)
+#define glProgramUniformMatrix2x3dv GLEW_GET_FUN(__glewProgramUniformMatrix2x3dv)
+#define glProgramUniformMatrix2x3fv GLEW_GET_FUN(__glewProgramUniformMatrix2x3fv)
+#define glProgramUniformMatrix2x4dv GLEW_GET_FUN(__glewProgramUniformMatrix2x4dv)
+#define glProgramUniformMatrix2x4fv GLEW_GET_FUN(__glewProgramUniformMatrix2x4fv)
+#define glProgramUniformMatrix3dv GLEW_GET_FUN(__glewProgramUniformMatrix3dv)
+#define glProgramUniformMatrix3fv GLEW_GET_FUN(__glewProgramUniformMatrix3fv)
+#define glProgramUniformMatrix3x2dv GLEW_GET_FUN(__glewProgramUniformMatrix3x2dv)
+#define glProgramUniformMatrix3x2fv GLEW_GET_FUN(__glewProgramUniformMatrix3x2fv)
+#define glProgramUniformMatrix3x4dv GLEW_GET_FUN(__glewProgramUniformMatrix3x4dv)
+#define glProgramUniformMatrix3x4fv GLEW_GET_FUN(__glewProgramUniformMatrix3x4fv)
+#define glProgramUniformMatrix4dv GLEW_GET_FUN(__glewProgramUniformMatrix4dv)
+#define glProgramUniformMatrix4fv GLEW_GET_FUN(__glewProgramUniformMatrix4fv)
+#define glProgramUniformMatrix4x2dv GLEW_GET_FUN(__glewProgramUniformMatrix4x2dv)
+#define glProgramUniformMatrix4x2fv GLEW_GET_FUN(__glewProgramUniformMatrix4x2fv)
+#define glProgramUniformMatrix4x3dv GLEW_GET_FUN(__glewProgramUniformMatrix4x3dv)
+#define glProgramUniformMatrix4x3fv GLEW_GET_FUN(__glewProgramUniformMatrix4x3fv)
+#define glUseProgramStages GLEW_GET_FUN(__glewUseProgramStages)
+#define glValidateProgramPipeline GLEW_GET_FUN(__glewValidateProgramPipeline)
+
+#define GLEW_ARB_separate_shader_objects GLEW_GET_VAR(__GLEW_ARB_separate_shader_objects)
+
+#endif /* !GL_ARB_separate_shader_objects */
+#endif // XXX
+
+/* --------------------- GL_ARB_shader_atomic_counters --------------------- */
+
+#if !defined(GL_ARB_shader_atomic_counters)
+#define GL_ARB_shader_atomic_counters 1
+
+#define GL_ATOMIC_COUNTER_BUFFER 0x92C0
+#define GL_ATOMIC_COUNTER_BUFFER_BINDING 0x92C1
+#define GL_ATOMIC_COUNTER_BUFFER_START 0x92C2
+#define GL_ATOMIC_COUNTER_BUFFER_SIZE 0x92C3
+#define GL_ATOMIC_COUNTER_BUFFER_DATA_SIZE 0x92C4
+#define GL_ATOMIC_COUNTER_BUFFER_ACTIVE_ATOMIC_COUNTERS 0x92C5
+#define GL_ATOMIC_COUNTER_BUFFER_ACTIVE_ATOMIC_COUNTER_INDICES 0x92C6
+#define GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_VERTEX_SHADER 0x92C7
+#define GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_TESS_CONTROL_SHADER 0x92C8
+#define GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_TESS_EVALUATION_SHADER 0x92C9
+#define GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_GEOMETRY_SHADER 0x92CA
+#define GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_FRAGMENT_SHADER 0x92CB
+#define GL_MAX_VERTEX_ATOMIC_COUNTER_BUFFERS 0x92CC
+#define GL_MAX_TESS_CONTROL_ATOMIC_COUNTER_BUFFERS 0x92CD
+#define GL_MAX_TESS_EVALUATION_ATOMIC_COUNTER_BUFFERS 0x92CE
+#define GL_MAX_GEOMETRY_ATOMIC_COUNTER_BUFFERS 0x92CF
+#define GL_MAX_FRAGMENT_ATOMIC_COUNTER_BUFFERS 0x92D0
+#define GL_MAX_COMBINED_ATOMIC_COUNTER_BUFFERS 0x92D1
+#define GL_MAX_VERTEX_ATOMIC_COUNTERS 0x92D2
+#define GL_MAX_TESS_CONTROL_ATOMIC_COUNTERS 0x92D3
+#define GL_MAX_TESS_EVALUATION_ATOMIC_COUNTERS 0x92D4
+#define GL_MAX_GEOMETRY_ATOMIC_COUNTERS 0x92D5
+#define GL_MAX_FRAGMENT_ATOMIC_COUNTERS 0x92D6
+#define GL_MAX_COMBINED_ATOMIC_COUNTERS 0x92D7
+#define GL_MAX_ATOMIC_COUNTER_BUFFER_SIZE 0x92D8
+#define GL_ACTIVE_ATOMIC_COUNTER_BUFFERS 0x92D9
+#define GL_UNIFORM_ATOMIC_COUNTER_BUFFER_INDEX 0x92DA
+#define GL_UNSIGNED_INT_ATOMIC_COUNTER 0x92DB
+#define GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS 0x92DC
+
+typedef void (GLAPIENTRY * PFNGLGETACTIVEATOMICCOUNTERBUFFERIVPROC) (GLuint program, GLuint bufferIndex, GLenum pname, GLint* params);
+
+#define glGetActiveAtomicCounterBufferiv GLEW_GET_FUN(__glewGetActiveAtomicCounterBufferiv)
+
+#define GLEW_ARB_shader_atomic_counters GLEW_GET_VAR(__GLEW_ARB_shader_atomic_counters)
+
+#endif /* !GL_ARB_shader_atomic_counters */
+
+/* ----------------------- GL_ARB_shader_bit_encoding ---------------------- */
+
+#if !defined(GL_ARB_shader_bit_encoding)
+#define GL_ARB_shader_bit_encoding 1
+
+#define GLEW_ARB_shader_bit_encoding GLEW_GET_VAR(__GLEW_ARB_shader_bit_encoding)
+
+#endif /* !GL_ARB_shader_bit_encoding */
+
+/* --------------------- GL_ARB_shader_image_load_store -------------------- */
+
+#if !defined(GL_ARB_shader_image_load_store)
+#define GL_ARB_shader_image_load_store 1
+
+#define GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT 0x00000001
+#define GL_ELEMENT_ARRAY_BARRIER_BIT 0x00000002
+#define GL_UNIFORM_BARRIER_BIT 0x00000004
+#define GL_TEXTURE_FETCH_BARRIER_BIT 0x00000008
+#define GL_SHADER_IMAGE_ACCESS_BARRIER_BIT 0x00000020
+#define GL_COMMAND_BARRIER_BIT 0x00000040
+#define GL_PIXEL_BUFFER_BARRIER_BIT 0x00000080
+#define GL_TEXTURE_UPDATE_BARRIER_BIT 0x00000100
+#define GL_BUFFER_UPDATE_BARRIER_BIT 0x00000200
+#define GL_FRAMEBUFFER_BARRIER_BIT 0x00000400
+#define GL_TRANSFORM_FEEDBACK_BARRIER_BIT 0x00000800
+#define GL_ATOMIC_COUNTER_BARRIER_BIT 0x00001000
+#define GL_MAX_IMAGE_UNITS 0x8F38
+#define GL_MAX_COMBINED_IMAGE_UNITS_AND_FRAGMENT_OUTPUTS 0x8F39
+#define GL_IMAGE_BINDING_NAME 0x8F3A
+#define GL_IMAGE_BINDING_LEVEL 0x8F3B
+#define GL_IMAGE_BINDING_LAYERED 0x8F3C
+#define GL_IMAGE_BINDING_LAYER 0x8F3D
+#define GL_IMAGE_BINDING_ACCESS 0x8F3E
+#define GL_IMAGE_1D 0x904C
+#define GL_IMAGE_2D 0x904D
+#define GL_IMAGE_3D 0x904E
+#define GL_IMAGE_2D_RECT 0x904F
+#define GL_IMAGE_CUBE 0x9050
+#define GL_IMAGE_BUFFER 0x9051
+#define GL_IMAGE_1D_ARRAY 0x9052
+#define GL_IMAGE_2D_ARRAY 0x9053
+#define GL_IMAGE_CUBE_MAP_ARRAY 0x9054
+#define GL_IMAGE_2D_MULTISAMPLE 0x9055
+#define GL_IMAGE_2D_MULTISAMPLE_ARRAY 0x9056
+#define GL_INT_IMAGE_1D 0x9057
+#define GL_INT_IMAGE_2D 0x9058
+#define GL_INT_IMAGE_3D 0x9059
+#define GL_INT_IMAGE_2D_RECT 0x905A
+#define GL_INT_IMAGE_CUBE 0x905B
+#define GL_INT_IMAGE_BUFFER 0x905C
+#define GL_INT_IMAGE_1D_ARRAY 0x905D
+#define GL_INT_IMAGE_2D_ARRAY 0x905E
+#define GL_INT_IMAGE_CUBE_MAP_ARRAY 0x905F
+#define GL_INT_IMAGE_2D_MULTISAMPLE 0x9060
+#define GL_INT_IMAGE_2D_MULTISAMPLE_ARRAY 0x9061
+#define GL_UNSIGNED_INT_IMAGE_1D 0x9062
+#define GL_UNSIGNED_INT_IMAGE_2D 0x9063
+#define GL_UNSIGNED_INT_IMAGE_3D 0x9064
+#define GL_UNSIGNED_INT_IMAGE_2D_RECT 0x9065
+#define GL_UNSIGNED_INT_IMAGE_CUBE 0x9066
+#define GL_UNSIGNED_INT_IMAGE_BUFFER 0x9067
+#define GL_UNSIGNED_INT_IMAGE_1D_ARRAY 0x9068
+#define GL_UNSIGNED_INT_IMAGE_2D_ARRAY 0x9069
+#define GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY 0x906A
+#define GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE 0x906B
+#define GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE_ARRAY 0x906C
+#define GL_MAX_IMAGE_SAMPLES 0x906D
+#define GL_IMAGE_BINDING_FORMAT 0x906E
+#define GL_IMAGE_FORMAT_COMPATIBILITY_TYPE 0x90C7
+#define GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE 0x90C8
+#define GL_IMAGE_FORMAT_COMPATIBILITY_BY_CLASS 0x90C9
+#define GL_MAX_VERTEX_IMAGE_UNIFORMS 0x90CA
+#define GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS 0x90CB
+#define GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS 0x90CC
+#define GL_MAX_GEOMETRY_IMAGE_UNIFORMS 0x90CD
+#define GL_MAX_FRAGMENT_IMAGE_UNIFORMS 0x90CE
+#define GL_MAX_COMBINED_IMAGE_UNIFORMS 0x90CF
+#define GL_ALL_BARRIER_BITS 0xFFFFFFFF
+
+typedef void (GLAPIENTRY * PFNGLBINDIMAGETEXTUREPROC) (GLuint unit, GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum access, GLenum format);
+typedef void (GLAPIENTRY * PFNGLMEMORYBARRIERPROC) (GLbitfield barriers);
+
+#define glBindImageTexture GLEW_GET_FUN(__glewBindImageTexture)
+#define glMemoryBarrier GLEW_GET_FUN(__glewMemoryBarrier)
+
+#define GLEW_ARB_shader_image_load_store GLEW_GET_VAR(__GLEW_ARB_shader_image_load_store)
+
+#endif /* !GL_ARB_shader_image_load_store */
+
+/* ------------------------ GL_ARB_shader_image_size ----------------------- */
+
+#if !defined(GL_ARB_shader_image_size)
+#define GL_ARB_shader_image_size 1
+
+#define GLEW_ARB_shader_image_size GLEW_GET_VAR(__GLEW_ARB_shader_image_size)
+
+#endif /* !GL_ARB_shader_image_size */
+
+/* ------------------------- GL_ARB_shader_objects ------------------------- */
+
+#if !defined(GL_ARB_shader_objects)
+#define GL_ARB_shader_objects 1
+
+#define GL_PROGRAM_OBJECT_ARB 0x8B40
+#define GL_SHADER_OBJECT_ARB 0x8B48
+#define GL_OBJECT_TYPE_ARB 0x8B4E
+#define GL_OBJECT_SUBTYPE_ARB 0x8B4F
+#define GL_FLOAT_VEC2_ARB 0x8B50
+#define GL_FLOAT_VEC3_ARB 0x8B51
+#define GL_FLOAT_VEC4_ARB 0x8B52
+#define GL_INT_VEC2_ARB 0x8B53
+#define GL_INT_VEC3_ARB 0x8B54
+#define GL_INT_VEC4_ARB 0x8B55
+#define GL_BOOL_ARB 0x8B56
+#define GL_BOOL_VEC2_ARB 0x8B57
+#define GL_BOOL_VEC3_ARB 0x8B58
+#define GL_BOOL_VEC4_ARB 0x8B59
+#define GL_FLOAT_MAT2_ARB 0x8B5A
+#define GL_FLOAT_MAT3_ARB 0x8B5B
+#define GL_FLOAT_MAT4_ARB 0x8B5C
+#define GL_SAMPLER_1D_ARB 0x8B5D
+#define GL_SAMPLER_2D_ARB 0x8B5E
+#define GL_SAMPLER_3D_ARB 0x8B5F
+#define GL_SAMPLER_CUBE_ARB 0x8B60
+#define GL_SAMPLER_1D_SHADOW_ARB 0x8B61
+#define GL_SAMPLER_2D_SHADOW_ARB 0x8B62
+#define GL_SAMPLER_2D_RECT_ARB 0x8B63
+#define GL_SAMPLER_2D_RECT_SHADOW_ARB 0x8B64
+#define GL_OBJECT_DELETE_STATUS_ARB 0x8B80
+#define GL_OBJECT_COMPILE_STATUS_ARB 0x8B81
+#define GL_OBJECT_LINK_STATUS_ARB 0x8B82
+#define GL_OBJECT_VALIDATE_STATUS_ARB 0x8B83
+#define GL_OBJECT_INFO_LOG_LENGTH_ARB 0x8B84
+#define GL_OBJECT_ATTACHED_OBJECTS_ARB 0x8B85
+#define GL_OBJECT_ACTIVE_UNIFORMS_ARB 0x8B86
+#define GL_OBJECT_ACTIVE_UNIFORM_MAX_LENGTH_ARB 0x8B87
+#define GL_OBJECT_SHADER_SOURCE_LENGTH_ARB 0x8B88
+
+typedef char GLcharARB;
+typedef unsigned int GLhandleARB;
+
+typedef void (GLAPIENTRY * PFNGLATTACHOBJECTARBPROC) (GLhandleARB containerObj, GLhandleARB obj);
+typedef void (GLAPIENTRY * PFNGLCOMPILESHADERARBPROC) (GLhandleARB shaderObj);
+typedef GLhandleARB (GLAPIENTRY * PFNGLCREATEPROGRAMOBJECTARBPROC) (void);
+typedef GLhandleARB (GLAPIENTRY * PFNGLCREATESHADEROBJECTARBPROC) (GLenum shaderType);
+typedef void (GLAPIENTRY * PFNGLDELETEOBJECTARBPROC) (GLhandleARB obj);
+typedef void (GLAPIENTRY * PFNGLDETACHOBJECTARBPROC) (GLhandleARB containerObj, GLhandleARB attachedObj);
+typedef void (GLAPIENTRY * PFNGLGETACTIVEUNIFORMARBPROC) (GLhandleARB programObj, GLuint index, GLsizei maxLength, GLsizei* length, GLint *size, GLenum *type, GLcharARB *name);
+typedef void (GLAPIENTRY * PFNGLGETATTACHEDOBJECTSARBPROC) (GLhandleARB containerObj, GLsizei maxCount, GLsizei* count, GLhandleARB *obj);
+typedef GLhandleARB (GLAPIENTRY * PFNGLGETHANDLEARBPROC) (GLenum pname);
+typedef void (GLAPIENTRY * PFNGLGETINFOLOGARBPROC) (GLhandleARB obj, GLsizei maxLength, GLsizei* length, GLcharARB *infoLog);
+typedef void (GLAPIENTRY * PFNGLGETOBJECTPARAMETERFVARBPROC) (GLhandleARB obj, GLenum pname, GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLGETOBJECTPARAMETERIVARBPROC) (GLhandleARB obj, GLenum pname, GLint* params);
+typedef void (GLAPIENTRY * PFNGLGETSHADERSOURCEARBPROC) (GLhandleARB obj, GLsizei maxLength, GLsizei* length, GLcharARB *source);
+typedef GLint (GLAPIENTRY * PFNGLGETUNIFORMLOCATIONARBPROC) (GLhandleARB programObj, const GLcharARB* name);
+typedef void (GLAPIENTRY * PFNGLGETUNIFORMFVARBPROC) (GLhandleARB programObj, GLint location, GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLGETUNIFORMIVARBPROC) (GLhandleARB programObj, GLint location, GLint* params);
+typedef void (GLAPIENTRY * PFNGLLINKPROGRAMARBPROC) (GLhandleARB programObj);
+typedef void (GLAPIENTRY * PFNGLSHADERSOURCEARBPROC) (GLhandleARB shaderObj, GLsizei count, const GLcharARB ** string, const GLint *length);
+typedef void (GLAPIENTRY * PFNGLUNIFORM1FARBPROC) (GLint location, GLfloat v0);
+typedef void (GLAPIENTRY * PFNGLUNIFORM1FVARBPROC) (GLint location, GLsizei count, const GLfloat* value);
+typedef void (GLAPIENTRY * PFNGLUNIFORM1IARBPROC) (GLint location, GLint v0);
+typedef void (GLAPIENTRY * PFNGLUNIFORM1IVARBPROC) (GLint location, GLsizei count, const GLint* value);
+typedef void (GLAPIENTRY * PFNGLUNIFORM2FARBPROC) (GLint location, GLfloat v0, GLfloat v1);
+typedef void (GLAPIENTRY * PFNGLUNIFORM2FVARBPROC) (GLint location, GLsizei count, const GLfloat* value);
+typedef void (GLAPIENTRY * PFNGLUNIFORM2IARBPROC) (GLint location, GLint v0, GLint v1);
+typedef void (GLAPIENTRY * PFNGLUNIFORM2IVARBPROC) (GLint location, GLsizei count, const GLint* value);
+typedef void (GLAPIENTRY * PFNGLUNIFORM3FARBPROC) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2);
+typedef void (GLAPIENTRY * PFNGLUNIFORM3FVARBPROC) (GLint location, GLsizei count, const GLfloat* value);
+typedef void (GLAPIENTRY * PFNGLUNIFORM3IARBPROC) (GLint location, GLint v0, GLint v1, GLint v2);
+typedef void (GLAPIENTRY * PFNGLUNIFORM3IVARBPROC) (GLint location, GLsizei count, const GLint* value);
+typedef void (GLAPIENTRY * PFNGLUNIFORM4FARBPROC) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
+typedef void (GLAPIENTRY * PFNGLUNIFORM4FVARBPROC) (GLint location, GLsizei count, const GLfloat* value);
+typedef void (GLAPIENTRY * PFNGLUNIFORM4IARBPROC) (GLint location, GLint v0, GLint v1, GLint v2, GLint v3);
+typedef void (GLAPIENTRY * PFNGLUNIFORM4IVARBPROC) (GLint location, GLsizei count, const GLint* value);
+typedef void (GLAPIENTRY * PFNGLUNIFORMMATRIX2FVARBPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
+typedef void (GLAPIENTRY * PFNGLUNIFORMMATRIX3FVARBPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
+typedef void (GLAPIENTRY * PFNGLUNIFORMMATRIX4FVARBPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
+typedef void (GLAPIENTRY * PFNGLUSEPROGRAMOBJECTARBPROC) (GLhandleARB programObj);
+typedef void (GLAPIENTRY * PFNGLVALIDATEPROGRAMARBPROC) (GLhandleARB programObj);
+
+#define glAttachObjectARB GLEW_GET_FUN(__glewAttachObjectARB)
+#define glCompileShaderARB GLEW_GET_FUN(__glewCompileShaderARB)
+#define glCreateProgramObjectARB GLEW_GET_FUN(__glewCreateProgramObjectARB)
+#define glCreateShaderObjectARB GLEW_GET_FUN(__glewCreateShaderObjectARB)
+#define glDeleteObjectARB GLEW_GET_FUN(__glewDeleteObjectARB)
+#define glDetachObjectARB GLEW_GET_FUN(__glewDetachObjectARB)
+#define glGetActiveUniformARB GLEW_GET_FUN(__glewGetActiveUniformARB)
+#define glGetAttachedObjectsARB GLEW_GET_FUN(__glewGetAttachedObjectsARB)
+#define glGetHandleARB GLEW_GET_FUN(__glewGetHandleARB)
+#define glGetInfoLogARB GLEW_GET_FUN(__glewGetInfoLogARB)
+#define glGetObjectParameterfvARB GLEW_GET_FUN(__glewGetObjectParameterfvARB)
+#define glGetObjectParameterivARB GLEW_GET_FUN(__glewGetObjectParameterivARB)
+#define glGetShaderSourceARB GLEW_GET_FUN(__glewGetShaderSourceARB)
+#define glGetUniformLocationARB GLEW_GET_FUN(__glewGetUniformLocationARB)
+#define glGetUniformfvARB GLEW_GET_FUN(__glewGetUniformfvARB)
+#define glGetUniformivARB GLEW_GET_FUN(__glewGetUniformivARB)
+#define glLinkProgramARB GLEW_GET_FUN(__glewLinkProgramARB)
+#define glShaderSourceARB GLEW_GET_FUN(__glewShaderSourceARB)
+#define glUniform1fARB GLEW_GET_FUN(__glewUniform1fARB)
+#define glUniform1fvARB GLEW_GET_FUN(__glewUniform1fvARB)
+#define glUniform1iARB GLEW_GET_FUN(__glewUniform1iARB)
+#define glUniform1ivARB GLEW_GET_FUN(__glewUniform1ivARB)
+#define glUniform2fARB GLEW_GET_FUN(__glewUniform2fARB)
+#define glUniform2fvARB GLEW_GET_FUN(__glewUniform2fvARB)
+#define glUniform2iARB GLEW_GET_FUN(__glewUniform2iARB)
+#define glUniform2ivARB GLEW_GET_FUN(__glewUniform2ivARB)
+#define glUniform3fARB GLEW_GET_FUN(__glewUniform3fARB)
+#define glUniform3fvARB GLEW_GET_FUN(__glewUniform3fvARB)
+#define glUniform3iARB GLEW_GET_FUN(__glewUniform3iARB)
+#define glUniform3ivARB GLEW_GET_FUN(__glewUniform3ivARB)
+#define glUniform4fARB GLEW_GET_FUN(__glewUniform4fARB)
+#define glUniform4fvARB GLEW_GET_FUN(__glewUniform4fvARB)
+#define glUniform4iARB GLEW_GET_FUN(__glewUniform4iARB)
+#define glUniform4ivARB GLEW_GET_FUN(__glewUniform4ivARB)
+#define glUniformMatrix2fvARB GLEW_GET_FUN(__glewUniformMatrix2fvARB)
+#define glUniformMatrix3fvARB GLEW_GET_FUN(__glewUniformMatrix3fvARB)
+#define glUniformMatrix4fvARB GLEW_GET_FUN(__glewUniformMatrix4fvARB)
+#define glUseProgramObjectARB GLEW_GET_FUN(__glewUseProgramObjectARB)
+#define glValidateProgramARB GLEW_GET_FUN(__glewValidateProgramARB)
+
+#define GLEW_ARB_shader_objects GLEW_GET_VAR(__GLEW_ARB_shader_objects)
+
+#endif /* !GL_ARB_shader_objects */
+
+/* ------------------------ GL_ARB_shader_precision ------------------------ */
+
+#if !defined(GL_ARB_shader_precision)
+#define GL_ARB_shader_precision 1
+
+#define GLEW_ARB_shader_precision GLEW_GET_VAR(__GLEW_ARB_shader_precision)
+
+#endif /* !GL_ARB_shader_precision */
+
+/* ---------------------- GL_ARB_shader_stencil_export --------------------- */
+
+#if !defined(GL_ARB_shader_stencil_export)
+#define GL_ARB_shader_stencil_export 1
+
+#define GLEW_ARB_shader_stencil_export GLEW_GET_VAR(__GLEW_ARB_shader_stencil_export)
+
+#endif /* !GL_ARB_shader_stencil_export */
+
+/* ------------------ GL_ARB_shader_storage_buffer_object ------------------ */
+
+#if !defined(GL_ARB_shader_storage_buffer_object)
+#define GL_ARB_shader_storage_buffer_object 1
+
+#define GL_SHADER_STORAGE_BARRIER_BIT 0x2000
+#define GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES 0x8F39
+#define GL_SHADER_STORAGE_BUFFER 0x90D2
+#define GL_SHADER_STORAGE_BUFFER_BINDING 0x90D3
+#define GL_SHADER_STORAGE_BUFFER_START 0x90D4
+#define GL_SHADER_STORAGE_BUFFER_SIZE 0x90D5
+#define GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS 0x90D6
+#define GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS 0x90D7
+#define GL_MAX_TESS_CONTROL_SHADER_STORAGE_BLOCKS 0x90D8
+#define GL_MAX_TESS_EVALUATION_SHADER_STORAGE_BLOCKS 0x90D9
+#define GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS 0x90DA
+#define GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS 0x90DB
+#define GL_MAX_COMBINED_SHADER_STORAGE_BLOCKS 0x90DC
+#define GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS 0x90DD
+#define GL_MAX_SHADER_STORAGE_BLOCK_SIZE 0x90DE
+#define GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT 0x90DF
+
+typedef void (GLAPIENTRY * PFNGLSHADERSTORAGEBLOCKBINDINGPROC) (GLuint program, GLuint storageBlockIndex, GLuint storageBlockBinding);
+
+#define glShaderStorageBlockBinding GLEW_GET_FUN(__glewShaderStorageBlockBinding)
+
+#define GLEW_ARB_shader_storage_buffer_object GLEW_GET_VAR(__GLEW_ARB_shader_storage_buffer_object)
+
+#endif /* !GL_ARB_shader_storage_buffer_object */
+
+/* ------------------------ GL_ARB_shader_subroutine ----------------------- */
+
+#if !defined(GL_ARB_shader_subroutine)
+#define GL_ARB_shader_subroutine 1
+
+#define GL_ACTIVE_SUBROUTINES 0x8DE5
+#define GL_ACTIVE_SUBROUTINE_UNIFORMS 0x8DE6
+#define GL_MAX_SUBROUTINES 0x8DE7
+#define GL_MAX_SUBROUTINE_UNIFORM_LOCATIONS 0x8DE8
+#define GL_ACTIVE_SUBROUTINE_UNIFORM_LOCATIONS 0x8E47
+#define GL_ACTIVE_SUBROUTINE_MAX_LENGTH 0x8E48
+#define GL_ACTIVE_SUBROUTINE_UNIFORM_MAX_LENGTH 0x8E49
+#define GL_NUM_COMPATIBLE_SUBROUTINES 0x8E4A
+#define GL_COMPATIBLE_SUBROUTINES 0x8E4B
+
+typedef void (GLAPIENTRY * PFNGLGETACTIVESUBROUTINENAMEPROC) (GLuint program, GLenum shadertype, GLuint index, GLsizei bufsize, GLsizei* length, char *name);
+typedef void (GLAPIENTRY * PFNGLGETACTIVESUBROUTINEUNIFORMNAMEPROC) (GLuint program, GLenum shadertype, GLuint index, GLsizei bufsize, GLsizei* length, char *name);
+typedef void (GLAPIENTRY * PFNGLGETACTIVESUBROUTINEUNIFORMIVPROC) (GLuint program, GLenum shadertype, GLuint index, GLenum pname, GLint* values);
+typedef void (GLAPIENTRY * PFNGLGETPROGRAMSTAGEIVPROC) (GLuint program, GLenum shadertype, GLenum pname, GLint* values);
+typedef GLuint (GLAPIENTRY * PFNGLGETSUBROUTINEINDEXPROC) (GLuint program, GLenum shadertype, const char* name);
+typedef GLint (GLAPIENTRY * PFNGLGETSUBROUTINEUNIFORMLOCATIONPROC) (GLuint program, GLenum shadertype, const char* name);
+typedef void (GLAPIENTRY * PFNGLGETUNIFORMSUBROUTINEUIVPROC) (GLenum shadertype, GLint location, GLuint* params);
+typedef void (GLAPIENTRY * PFNGLUNIFORMSUBROUTINESUIVPROC) (GLenum shadertype, GLsizei count, const GLuint* indices);
+
+#define glGetActiveSubroutineName GLEW_GET_FUN(__glewGetActiveSubroutineName)
+#define glGetActiveSubroutineUniformName GLEW_GET_FUN(__glewGetActiveSubroutineUniformName)
+#define glGetActiveSubroutineUniformiv GLEW_GET_FUN(__glewGetActiveSubroutineUniformiv)
+#define glGetProgramStageiv GLEW_GET_FUN(__glewGetProgramStageiv)
+#define glGetSubroutineIndex GLEW_GET_FUN(__glewGetSubroutineIndex)
+#define glGetSubroutineUniformLocation GLEW_GET_FUN(__glewGetSubroutineUniformLocation)
+#define glGetUniformSubroutineuiv GLEW_GET_FUN(__glewGetUniformSubroutineuiv)
+#define glUniformSubroutinesuiv GLEW_GET_FUN(__glewUniformSubroutinesuiv)
+
+#define GLEW_ARB_shader_subroutine GLEW_GET_VAR(__GLEW_ARB_shader_subroutine)
+
+#endif /* !GL_ARB_shader_subroutine */
+
+/* ----------------------- GL_ARB_shader_texture_lod ----------------------- */
+
+#if !defined(GL_ARB_shader_texture_lod)
+#define GL_ARB_shader_texture_lod 1
+
+#define GLEW_ARB_shader_texture_lod GLEW_GET_VAR(__GLEW_ARB_shader_texture_lod)
+
+#endif /* !GL_ARB_shader_texture_lod */
+
+/* ---------------------- GL_ARB_shading_language_100 ---------------------- */
+
+#if !defined(GL_ARB_shading_language_100)
+#define GL_ARB_shading_language_100 1
+
+#define GL_SHADING_LANGUAGE_VERSION_ARB 0x8B8C
+
+#define GLEW_ARB_shading_language_100 GLEW_GET_VAR(__GLEW_ARB_shading_language_100)
+
+#endif /* !GL_ARB_shading_language_100 */
+
+/* -------------------- GL_ARB_shading_language_420pack -------------------- */
+
+#if !defined(GL_ARB_shading_language_420pack)
+#define GL_ARB_shading_language_420pack 1
+
+#define GLEW_ARB_shading_language_420pack GLEW_GET_VAR(__GLEW_ARB_shading_language_420pack)
+
+#endif /* !GL_ARB_shading_language_420pack */
+
+/* -------------------- GL_ARB_shading_language_include -------------------- */
+
+#if !defined(GL_ARB_shading_language_include)
+#define GL_ARB_shading_language_include 1
+
+#define GL_SHADER_INCLUDE_ARB 0x8DAE
+#define GL_NAMED_STRING_LENGTH_ARB 0x8DE9
+#define GL_NAMED_STRING_TYPE_ARB 0x8DEA
+
+typedef void (GLAPIENTRY * PFNGLCOMPILESHADERINCLUDEARBPROC) (GLuint shader, GLsizei count, const char ** path, const GLint *length);
+typedef void (GLAPIENTRY * PFNGLDELETENAMEDSTRINGARBPROC) (GLint namelen, const char* name);
+typedef void (GLAPIENTRY * PFNGLGETNAMEDSTRINGARBPROC) (GLint namelen, const char* name, GLsizei bufSize, GLint *stringlen, char *string);
+typedef void (GLAPIENTRY * PFNGLGETNAMEDSTRINGIVARBPROC) (GLint namelen, const char* name, GLenum pname, GLint *params);
+typedef GLboolean (GLAPIENTRY * PFNGLISNAMEDSTRINGARBPROC) (GLint namelen, const char* name);
+typedef void (GLAPIENTRY * PFNGLNAMEDSTRINGARBPROC) (GLenum type, GLint namelen, const char* name, GLint stringlen, const char *string);
+
+#define glCompileShaderIncludeARB GLEW_GET_FUN(__glewCompileShaderIncludeARB)
+#define glDeleteNamedStringARB GLEW_GET_FUN(__glewDeleteNamedStringARB)
+#define glGetNamedStringARB GLEW_GET_FUN(__glewGetNamedStringARB)
+#define glGetNamedStringivARB GLEW_GET_FUN(__glewGetNamedStringivARB)
+#define glIsNamedStringARB GLEW_GET_FUN(__glewIsNamedStringARB)
+#define glNamedStringARB GLEW_GET_FUN(__glewNamedStringARB)
+
+#define GLEW_ARB_shading_language_include GLEW_GET_VAR(__GLEW_ARB_shading_language_include)
+
+#endif /* !GL_ARB_shading_language_include */
+
+/* -------------------- GL_ARB_shading_language_packing -------------------- */
+
+#if !defined(GL_ARB_shading_language_packing)
+#define GL_ARB_shading_language_packing 1
+
+#define GLEW_ARB_shading_language_packing GLEW_GET_VAR(__GLEW_ARB_shading_language_packing)
+
+#endif /* !GL_ARB_shading_language_packing */
+
+/* ----------------------------- GL_ARB_shadow ----------------------------- */
+
+#if !defined(GL_ARB_shadow)
+#define GL_ARB_shadow 1
+
+#define GL_TEXTURE_COMPARE_MODE_ARB 0x884C
+#define GL_TEXTURE_COMPARE_FUNC_ARB 0x884D
+#define GL_COMPARE_R_TO_TEXTURE_ARB 0x884E
+
+#define GLEW_ARB_shadow GLEW_GET_VAR(__GLEW_ARB_shadow)
+
+#endif /* !GL_ARB_shadow */
+
+/* ------------------------- GL_ARB_shadow_ambient ------------------------- */
+
+#if !defined(GL_ARB_shadow_ambient)
+#define GL_ARB_shadow_ambient 1
+
+#define GL_TEXTURE_COMPARE_FAIL_VALUE_ARB 0x80BF
+
+#define GLEW_ARB_shadow_ambient GLEW_GET_VAR(__GLEW_ARB_shadow_ambient)
+
+#endif /* !GL_ARB_shadow_ambient */
+
+/* ------------------------ GL_ARB_stencil_texturing ----------------------- */
+
+#if !defined(GL_ARB_stencil_texturing)
+#define GL_ARB_stencil_texturing 1
+
+#define GL_DEPTH_STENCIL_TEXTURE_MODE 0x90EA
+
+#define GLEW_ARB_stencil_texturing GLEW_GET_VAR(__GLEW_ARB_stencil_texturing)
+
+#endif /* !GL_ARB_stencil_texturing */
+
+/* ------------------------------ GL_ARB_sync ------------------------------ */
+
+#if !defined(GL_ARB_sync)
+#define GL_ARB_sync 1
+
+#define GL_SYNC_FLUSH_COMMANDS_BIT 0x00000001
+#define GL_MAX_SERVER_WAIT_TIMEOUT 0x9111
+#define GL_OBJECT_TYPE 0x9112
+#define GL_SYNC_CONDITION 0x9113
+#define GL_SYNC_STATUS 0x9114
+#define GL_SYNC_FLAGS 0x9115
+#define GL_SYNC_FENCE 0x9116
+#define GL_SYNC_GPU_COMMANDS_COMPLETE 0x9117
+#define GL_UNSIGNALED 0x9118
+#define GL_SIGNALED 0x9119
+#define GL_ALREADY_SIGNALED 0x911A
+#define GL_TIMEOUT_EXPIRED 0x911B
+#define GL_CONDITION_SATISFIED 0x911C
+#define GL_WAIT_FAILED 0x911D
+#define GL_TIMEOUT_IGNORED 0xFFFFFFFFFFFFFFFF
+
+typedef GLenum (GLAPIENTRY * PFNGLCLIENTWAITSYNCPROC) (GLsync GLsync,GLbitfield flags,GLuint64 timeout);
+typedef void (GLAPIENTRY * PFNGLDELETESYNCPROC) (GLsync GLsync);
+typedef GLsync (GLAPIENTRY * PFNGLFENCESYNCPROC) (GLenum condition,GLbitfield flags);
+typedef void (GLAPIENTRY * PFNGLGETINTEGER64VPROC) (GLenum pname, GLint64* params);
+typedef void (GLAPIENTRY * PFNGLGETSYNCIVPROC) (GLsync GLsync,GLenum pname,GLsizei bufSize,GLsizei* length, GLint *values);
+typedef GLboolean (GLAPIENTRY * PFNGLISSYNCPROC) (GLsync GLsync);
+typedef void (GLAPIENTRY * PFNGLWAITSYNCPROC) (GLsync GLsync,GLbitfield flags,GLuint64 timeout);
+
+#define glClientWaitSync GLEW_GET_FUN(__glewClientWaitSync)
+#define glDeleteSync GLEW_GET_FUN(__glewDeleteSync)
+#define glFenceSync GLEW_GET_FUN(__glewFenceSync)
+#define glGetInteger64v GLEW_GET_FUN(__glewGetInteger64v)
+#define glGetSynciv GLEW_GET_FUN(__glewGetSynciv)
+#define glIsSync GLEW_GET_FUN(__glewIsSync)
+#define glWaitSync GLEW_GET_FUN(__glewWaitSync)
+
+#define GLEW_ARB_sync GLEW_GET_VAR(__GLEW_ARB_sync)
+
+#endif /* !GL_ARB_sync */
+
+/* ----------------------- GL_ARB_tessellation_shader ---------------------- */
+
+#if !defined(GL_ARB_tessellation_shader)
+#define GL_ARB_tessellation_shader 1
+
+#define GL_PATCHES 0xE
+#define GL_UNIFORM_BLOCK_REFERENCED_BY_TESS_CONTROL_SHADER 0x84F0
+#define GL_UNIFORM_BLOCK_REFERENCED_BY_TESS_EVALUATION_SHADER 0x84F1
+#define GL_MAX_TESS_CONTROL_INPUT_COMPONENTS 0x886C
+#define GL_MAX_TESS_EVALUATION_INPUT_COMPONENTS 0x886D
+#define GL_MAX_COMBINED_TESS_CONTROL_UNIFORM_COMPONENTS 0x8E1E
+#define GL_MAX_COMBINED_TESS_EVALUATION_UNIFORM_COMPONENTS 0x8E1F
+#define GL_PATCH_VERTICES 0x8E72
+#define GL_PATCH_DEFAULT_INNER_LEVEL 0x8E73
+#define GL_PATCH_DEFAULT_OUTER_LEVEL 0x8E74
+#define GL_TESS_CONTROL_OUTPUT_VERTICES 0x8E75
+#define GL_TESS_GEN_MODE 0x8E76
+#define GL_TESS_GEN_SPACING 0x8E77
+#define GL_TESS_GEN_VERTEX_ORDER 0x8E78
+#define GL_TESS_GEN_POINT_MODE 0x8E79
+#define GL_ISOLINES 0x8E7A
+#define GL_FRACTIONAL_ODD 0x8E7B
+#define GL_FRACTIONAL_EVEN 0x8E7C
+#define GL_MAX_PATCH_VERTICES 0x8E7D
+#define GL_MAX_TESS_GEN_LEVEL 0x8E7E
+#define GL_MAX_TESS_CONTROL_UNIFORM_COMPONENTS 0x8E7F
+#define GL_MAX_TESS_EVALUATION_UNIFORM_COMPONENTS 0x8E80
+#define GL_MAX_TESS_CONTROL_TEXTURE_IMAGE_UNITS 0x8E81
+#define GL_MAX_TESS_EVALUATION_TEXTURE_IMAGE_UNITS 0x8E82
+#define GL_MAX_TESS_CONTROL_OUTPUT_COMPONENTS 0x8E83
+#define GL_MAX_TESS_PATCH_COMPONENTS 0x8E84
+#define GL_MAX_TESS_CONTROL_TOTAL_OUTPUT_COMPONENTS 0x8E85
+#define GL_MAX_TESS_EVALUATION_OUTPUT_COMPONENTS 0x8E86
+#define GL_TESS_EVALUATION_SHADER 0x8E87
+#define GL_TESS_CONTROL_SHADER 0x8E88
+#define GL_MAX_TESS_CONTROL_UNIFORM_BLOCKS 0x8E89
+#define GL_MAX_TESS_EVALUATION_UNIFORM_BLOCKS 0x8E8A
+
+typedef void (GLAPIENTRY * PFNGLPATCHPARAMETERFVPROC) (GLenum pname, const GLfloat* values);
+typedef void (GLAPIENTRY * PFNGLPATCHPARAMETERIPROC) (GLenum pname, GLint value);
+
+#define glPatchParameterfv GLEW_GET_FUN(__glewPatchParameterfv)
+#define glPatchParameteri GLEW_GET_FUN(__glewPatchParameteri)
+
+#define GLEW_ARB_tessellation_shader GLEW_GET_VAR(__GLEW_ARB_tessellation_shader)
+
+#endif /* !GL_ARB_tessellation_shader */
+
+/* ---------------------- GL_ARB_texture_border_clamp ---------------------- */
+
+#if !defined(GL_ARB_texture_border_clamp)
+#define GL_ARB_texture_border_clamp 1
+
+#define GL_CLAMP_TO_BORDER_ARB 0x812D
+
+#define GLEW_ARB_texture_border_clamp GLEW_GET_VAR(__GLEW_ARB_texture_border_clamp)
+
+#endif /* !GL_ARB_texture_border_clamp */
+
+/* ---------------------- GL_ARB_texture_buffer_object --------------------- */
+
+#if !defined(GL_ARB_texture_buffer_object)
+#define GL_ARB_texture_buffer_object 1
+
+#define GL_TEXTURE_BUFFER_ARB 0x8C2A
+#define GL_MAX_TEXTURE_BUFFER_SIZE_ARB 0x8C2B
+#define GL_TEXTURE_BINDING_BUFFER_ARB 0x8C2C
+#define GL_TEXTURE_BUFFER_DATA_STORE_BINDING_ARB 0x8C2D
+#define GL_TEXTURE_BUFFER_FORMAT_ARB 0x8C2E
+
+typedef void (GLAPIENTRY * PFNGLTEXBUFFERARBPROC) (GLenum target, GLenum internalformat, GLuint buffer);
+
+#define glTexBufferARB GLEW_GET_FUN(__glewTexBufferARB)
+
+#define GLEW_ARB_texture_buffer_object GLEW_GET_VAR(__GLEW_ARB_texture_buffer_object)
+
+#endif /* !GL_ARB_texture_buffer_object */
+
+/* ------------------- GL_ARB_texture_buffer_object_rgb32 ------------------ */
+
+#if !defined(GL_ARB_texture_buffer_object_rgb32)
+#define GL_ARB_texture_buffer_object_rgb32 1
+
+#define GLEW_ARB_texture_buffer_object_rgb32 GLEW_GET_VAR(__GLEW_ARB_texture_buffer_object_rgb32)
+
+#endif /* !GL_ARB_texture_buffer_object_rgb32 */
+
+/* ---------------------- GL_ARB_texture_buffer_range ---------------------- */
+
+#if !defined(GL_ARB_texture_buffer_range)
+#define GL_ARB_texture_buffer_range 1
+
+#define GL_TEXTURE_BUFFER_OFFSET 0x919D
+#define GL_TEXTURE_BUFFER_SIZE 0x919E
+#define GL_TEXTURE_BUFFER_OFFSET_ALIGNMENT 0x919F
+
+typedef void (GLAPIENTRY * PFNGLTEXBUFFERRANGEPROC) (GLenum target, GLenum internalformat, GLuint buffer, GLintptr offset, GLsizeiptr size);
+typedef void (GLAPIENTRY * PFNGLTEXTUREBUFFERRANGEEXTPROC) (GLuint texture, GLenum target, GLenum internalformat, GLuint buffer, GLintptr offset, GLsizeiptr size);
+
+#define glTexBufferRange GLEW_GET_FUN(__glewTexBufferRange)
+#define glTextureBufferRangeEXT GLEW_GET_FUN(__glewTextureBufferRangeEXT)
+
+#define GLEW_ARB_texture_buffer_range GLEW_GET_VAR(__GLEW_ARB_texture_buffer_range)
+
+#endif /* !GL_ARB_texture_buffer_range */
+
+/* ----------------------- GL_ARB_texture_compression ---------------------- */
+
+#if !defined(GL_ARB_texture_compression)
+#define GL_ARB_texture_compression 1
+
+#define GL_COMPRESSED_ALPHA_ARB 0x84E9
+#define GL_COMPRESSED_LUMINANCE_ARB 0x84EA
+#define GL_COMPRESSED_LUMINANCE_ALPHA_ARB 0x84EB
+#define GL_COMPRESSED_INTENSITY_ARB 0x84EC
+#define GL_COMPRESSED_RGB_ARB 0x84ED
+#define GL_COMPRESSED_RGBA_ARB 0x84EE
+#define GL_TEXTURE_COMPRESSION_HINT_ARB 0x84EF
+#define GL_TEXTURE_COMPRESSED_IMAGE_SIZE_ARB 0x86A0
+#define GL_TEXTURE_COMPRESSED_ARB 0x86A1
+#define GL_NUM_COMPRESSED_TEXTURE_FORMATS_ARB 0x86A2
+#define GL_COMPRESSED_TEXTURE_FORMATS_ARB 0x86A3
+
+typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXIMAGE1DARBPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const void* data);
+typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXIMAGE2DARBPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void* data);
+typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXIMAGE3DARBPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void* data);
+typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXSUBIMAGE1DARBPROC) (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const void* data);
+typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXSUBIMAGE2DARBPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void* data);
+typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXSUBIMAGE3DARBPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void* data);
+typedef void (GLAPIENTRY * PFNGLGETCOMPRESSEDTEXIMAGEARBPROC) (GLenum target, GLint lod, void* img);
+
+#define glCompressedTexImage1DARB GLEW_GET_FUN(__glewCompressedTexImage1DARB)
+#define glCompressedTexImage2DARB GLEW_GET_FUN(__glewCompressedTexImage2DARB)
+#define glCompressedTexImage3DARB GLEW_GET_FUN(__glewCompressedTexImage3DARB)
+#define glCompressedTexSubImage1DARB GLEW_GET_FUN(__glewCompressedTexSubImage1DARB)
+#define glCompressedTexSubImage2DARB GLEW_GET_FUN(__glewCompressedTexSubImage2DARB)
+#define glCompressedTexSubImage3DARB GLEW_GET_FUN(__glewCompressedTexSubImage3DARB)
+#define glGetCompressedTexImageARB GLEW_GET_FUN(__glewGetCompressedTexImageARB)
+
+#define GLEW_ARB_texture_compression GLEW_GET_VAR(__GLEW_ARB_texture_compression)
+
+#endif /* !GL_ARB_texture_compression */
+
+/* -------------------- GL_ARB_texture_compression_bptc -------------------- */
+
+#if !defined(GL_ARB_texture_compression_bptc)
+#define GL_ARB_texture_compression_bptc 1
+
+#define GL_COMPRESSED_RGBA_BPTC_UNORM_ARB 0x8E8C
+#define GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_ARB 0x8E8D
+#define GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_ARB 0x8E8E
+#define GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_ARB 0x8E8F
+
+#define GLEW_ARB_texture_compression_bptc GLEW_GET_VAR(__GLEW_ARB_texture_compression_bptc)
+
+#endif /* !GL_ARB_texture_compression_bptc */
+
+/* -------------------- GL_ARB_texture_compression_rgtc -------------------- */
+
+#if !defined(GL_ARB_texture_compression_rgtc)
+#define GL_ARB_texture_compression_rgtc 1
+
+#define GL_COMPRESSED_RED_RGTC1 0x8DBB
+#define GL_COMPRESSED_SIGNED_RED_RGTC1 0x8DBC
+#define GL_COMPRESSED_RG_RGTC2 0x8DBD
+#define GL_COMPRESSED_SIGNED_RG_RGTC2 0x8DBE
+
+#define GLEW_ARB_texture_compression_rgtc GLEW_GET_VAR(__GLEW_ARB_texture_compression_rgtc)
+
+#endif /* !GL_ARB_texture_compression_rgtc */
+
+/* ------------------------ GL_ARB_texture_cube_map ------------------------ */
+
+#if !defined(GL_ARB_texture_cube_map)
+#define GL_ARB_texture_cube_map 1
+
+#define GL_NORMAL_MAP_ARB 0x8511
+#define GL_REFLECTION_MAP_ARB 0x8512
+#define GL_TEXTURE_CUBE_MAP_ARB 0x8513
+#define GL_TEXTURE_BINDING_CUBE_MAP_ARB 0x8514
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB 0x8515
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB 0x8516
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB 0x8517
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB 0x8518
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB 0x8519
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB 0x851A
+#define GL_PROXY_TEXTURE_CUBE_MAP_ARB 0x851B
+#define GL_MAX_CUBE_MAP_TEXTURE_SIZE_ARB 0x851C
+
+#define GLEW_ARB_texture_cube_map GLEW_GET_VAR(__GLEW_ARB_texture_cube_map)
+
+#endif /* !GL_ARB_texture_cube_map */
+
+/* --------------------- GL_ARB_texture_cube_map_array --------------------- */
+
+#if !defined(GL_ARB_texture_cube_map_array)
+#define GL_ARB_texture_cube_map_array 1
+
+#define GL_TEXTURE_CUBE_MAP_ARRAY_ARB 0x9009
+#define GL_TEXTURE_BINDING_CUBE_MAP_ARRAY_ARB 0x900A
+#define GL_PROXY_TEXTURE_CUBE_MAP_ARRAY_ARB 0x900B
+#define GL_SAMPLER_CUBE_MAP_ARRAY_ARB 0x900C
+#define GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW_ARB 0x900D
+#define GL_INT_SAMPLER_CUBE_MAP_ARRAY_ARB 0x900E
+#define GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY_ARB 0x900F
+
+#define GLEW_ARB_texture_cube_map_array GLEW_GET_VAR(__GLEW_ARB_texture_cube_map_array)
+
+#endif /* !GL_ARB_texture_cube_map_array */
+
+/* ------------------------- GL_ARB_texture_env_add ------------------------ */
+
+#if !defined(GL_ARB_texture_env_add)
+#define GL_ARB_texture_env_add 1
+
+#define GLEW_ARB_texture_env_add GLEW_GET_VAR(__GLEW_ARB_texture_env_add)
+
+#endif /* !GL_ARB_texture_env_add */
+
+/* ----------------------- GL_ARB_texture_env_combine ---------------------- */
+
+#if !defined(GL_ARB_texture_env_combine)
+#define GL_ARB_texture_env_combine 1
+
+#define GL_SUBTRACT_ARB 0x84E7
+#define GL_COMBINE_ARB 0x8570
+#define GL_COMBINE_RGB_ARB 0x8571
+#define GL_COMBINE_ALPHA_ARB 0x8572
+#define GL_RGB_SCALE_ARB 0x8573
+#define GL_ADD_SIGNED_ARB 0x8574
+#define GL_INTERPOLATE_ARB 0x8575
+#define GL_CONSTANT_ARB 0x8576
+#define GL_PRIMARY_COLOR_ARB 0x8577
+#define GL_PREVIOUS_ARB 0x8578
+#define GL_SOURCE0_RGB_ARB 0x8580
+#define GL_SOURCE1_RGB_ARB 0x8581
+#define GL_SOURCE2_RGB_ARB 0x8582
+#define GL_SOURCE0_ALPHA_ARB 0x8588
+#define GL_SOURCE1_ALPHA_ARB 0x8589
+#define GL_SOURCE2_ALPHA_ARB 0x858A
+#define GL_OPERAND0_RGB_ARB 0x8590
+#define GL_OPERAND1_RGB_ARB 0x8591
+#define GL_OPERAND2_RGB_ARB 0x8592
+#define GL_OPERAND0_ALPHA_ARB 0x8598
+#define GL_OPERAND1_ALPHA_ARB 0x8599
+#define GL_OPERAND2_ALPHA_ARB 0x859A
+
+#define GLEW_ARB_texture_env_combine GLEW_GET_VAR(__GLEW_ARB_texture_env_combine)
+
+#endif /* !GL_ARB_texture_env_combine */
+
+/* ---------------------- GL_ARB_texture_env_crossbar ---------------------- */
+
+#if !defined(GL_ARB_texture_env_crossbar)
+#define GL_ARB_texture_env_crossbar 1
+
+#define GLEW_ARB_texture_env_crossbar GLEW_GET_VAR(__GLEW_ARB_texture_env_crossbar)
+
+#endif /* !GL_ARB_texture_env_crossbar */
+
+/* ------------------------ GL_ARB_texture_env_dot3 ------------------------ */
+
+#if !defined(GL_ARB_texture_env_dot3)
+#define GL_ARB_texture_env_dot3 1
+
+#define GL_DOT3_RGB_ARB 0x86AE
+#define GL_DOT3_RGBA_ARB 0x86AF
+
+#define GLEW_ARB_texture_env_dot3 GLEW_GET_VAR(__GLEW_ARB_texture_env_dot3)
+
+#endif /* !GL_ARB_texture_env_dot3 */
+
+/* -------------------------- GL_ARB_texture_float ------------------------- */
+
+#if !defined(GL_ARB_texture_float)
+#define GL_ARB_texture_float 1
+
+#define GL_RGBA32F_ARB 0x8814
+#define GL_RGB32F_ARB 0x8815
+#define GL_ALPHA32F_ARB 0x8816
+#define GL_INTENSITY32F_ARB 0x8817
+#define GL_LUMINANCE32F_ARB 0x8818
+#define GL_LUMINANCE_ALPHA32F_ARB 0x8819
+#define GL_RGBA16F_ARB 0x881A
+#define GL_RGB16F_ARB 0x881B
+#define GL_ALPHA16F_ARB 0x881C
+#define GL_INTENSITY16F_ARB 0x881D
+#define GL_LUMINANCE16F_ARB 0x881E
+#define GL_LUMINANCE_ALPHA16F_ARB 0x881F
+#define GL_TEXTURE_RED_TYPE_ARB 0x8C10
+#define GL_TEXTURE_GREEN_TYPE_ARB 0x8C11
+#define GL_TEXTURE_BLUE_TYPE_ARB 0x8C12
+#define GL_TEXTURE_ALPHA_TYPE_ARB 0x8C13
+#define GL_TEXTURE_LUMINANCE_TYPE_ARB 0x8C14
+#define GL_TEXTURE_INTENSITY_TYPE_ARB 0x8C15
+#define GL_TEXTURE_DEPTH_TYPE_ARB 0x8C16
+#define GL_UNSIGNED_NORMALIZED_ARB 0x8C17
+
+#define GLEW_ARB_texture_float GLEW_GET_VAR(__GLEW_ARB_texture_float)
+
+#endif /* !GL_ARB_texture_float */
+
+/* ------------------------- GL_ARB_texture_gather ------------------------- */
+
+#if !defined(GL_ARB_texture_gather)
+#define GL_ARB_texture_gather 1
+
+#define GL_MIN_PROGRAM_TEXTURE_GATHER_OFFSET_ARB 0x8E5E
+#define GL_MAX_PROGRAM_TEXTURE_GATHER_OFFSET_ARB 0x8E5F
+#define GL_MAX_PROGRAM_TEXTURE_GATHER_COMPONENTS_ARB 0x8F9F
+
+#define GLEW_ARB_texture_gather GLEW_GET_VAR(__GLEW_ARB_texture_gather)
+
+#endif /* !GL_ARB_texture_gather */
+
+/* --------------------- GL_ARB_texture_mirrored_repeat -------------------- */
+
+#if !defined(GL_ARB_texture_mirrored_repeat)
+#define GL_ARB_texture_mirrored_repeat 1
+
+#define GL_MIRRORED_REPEAT_ARB 0x8370
+
+#define GLEW_ARB_texture_mirrored_repeat GLEW_GET_VAR(__GLEW_ARB_texture_mirrored_repeat)
+
+#endif /* !GL_ARB_texture_mirrored_repeat */
+
+/* ----------------------- GL_ARB_texture_multisample ---------------------- */
+
+#if !defined(GL_ARB_texture_multisample)
+#define GL_ARB_texture_multisample 1
+
+#define GL_SAMPLE_POSITION 0x8E50
+#define GL_SAMPLE_MASK 0x8E51
+#define GL_SAMPLE_MASK_VALUE 0x8E52
+#define GL_MAX_SAMPLE_MASK_WORDS 0x8E59
+#define GL_TEXTURE_2D_MULTISAMPLE 0x9100
+#define GL_PROXY_TEXTURE_2D_MULTISAMPLE 0x9101
+#define GL_TEXTURE_2D_MULTISAMPLE_ARRAY 0x9102
+#define GL_PROXY_TEXTURE_2D_MULTISAMPLE_ARRAY 0x9103
+#define GL_TEXTURE_BINDING_2D_MULTISAMPLE 0x9104
+#define GL_TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY 0x9105
+#define GL_TEXTURE_SAMPLES 0x9106
+#define GL_TEXTURE_FIXED_SAMPLE_LOCATIONS 0x9107
+#define GL_SAMPLER_2D_MULTISAMPLE 0x9108
+#define GL_INT_SAMPLER_2D_MULTISAMPLE 0x9109
+#define GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE 0x910A
+#define GL_SAMPLER_2D_MULTISAMPLE_ARRAY 0x910B
+#define GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY 0x910C
+#define GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY 0x910D
+#define GL_MAX_COLOR_TEXTURE_SAMPLES 0x910E
+#define GL_MAX_DEPTH_TEXTURE_SAMPLES 0x910F
+#define GL_MAX_INTEGER_SAMPLES 0x9110
+
+typedef void (GLAPIENTRY * PFNGLGETMULTISAMPLEFVPROC) (GLenum pname, GLuint index, GLfloat* val);
+typedef void (GLAPIENTRY * PFNGLSAMPLEMASKIPROC) (GLuint index, GLbitfield mask);
+typedef void (GLAPIENTRY * PFNGLTEXIMAGE2DMULTISAMPLEPROC) (GLenum target, GLsizei samples, GLint internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations);
+typedef void (GLAPIENTRY * PFNGLTEXIMAGE3DMULTISAMPLEPROC) (GLenum target, GLsizei samples, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedsamplelocations);
+
+#define glGetMultisamplefv GLEW_GET_FUN(__glewGetMultisamplefv)
+#define glSampleMaski GLEW_GET_FUN(__glewSampleMaski)
+#define glTexImage2DMultisample GLEW_GET_FUN(__glewTexImage2DMultisample)
+#define glTexImage3DMultisample GLEW_GET_FUN(__glewTexImage3DMultisample)
+
+#define GLEW_ARB_texture_multisample GLEW_GET_VAR(__GLEW_ARB_texture_multisample)
+
+#endif /* !GL_ARB_texture_multisample */
+
+/* -------------------- GL_ARB_texture_non_power_of_two -------------------- */
+
+#if !defined(GL_ARB_texture_non_power_of_two)
+#define GL_ARB_texture_non_power_of_two 1
+
+#define GLEW_ARB_texture_non_power_of_two GLEW_GET_VAR(__GLEW_ARB_texture_non_power_of_two)
+
+#endif /* !GL_ARB_texture_non_power_of_two */
+
+/* ---------------------- GL_ARB_texture_query_levels ---------------------- */
+
+#if !defined(GL_ARB_texture_query_levels)
+#define GL_ARB_texture_query_levels 1
+
+#define GLEW_ARB_texture_query_levels GLEW_GET_VAR(__GLEW_ARB_texture_query_levels)
+
+#endif /* !GL_ARB_texture_query_levels */
+
+/* ------------------------ GL_ARB_texture_query_lod ----------------------- */
+
+#if !defined(GL_ARB_texture_query_lod)
+#define GL_ARB_texture_query_lod 1
+
+#define GLEW_ARB_texture_query_lod GLEW_GET_VAR(__GLEW_ARB_texture_query_lod)
+
+#endif /* !GL_ARB_texture_query_lod */
+
+/* ------------------------ GL_ARB_texture_rectangle ----------------------- */
+
+#if !defined(GL_ARB_texture_rectangle)
+#define GL_ARB_texture_rectangle 1
+
+#define GL_TEXTURE_RECTANGLE_ARB 0x84F5
+#define GL_TEXTURE_BINDING_RECTANGLE_ARB 0x84F6
+#define GL_PROXY_TEXTURE_RECTANGLE_ARB 0x84F7
+#define GL_MAX_RECTANGLE_TEXTURE_SIZE_ARB 0x84F8
+#define GL_SAMPLER_2D_RECT_ARB 0x8B63
+#define GL_SAMPLER_2D_RECT_SHADOW_ARB 0x8B64
+
+#define GLEW_ARB_texture_rectangle GLEW_GET_VAR(__GLEW_ARB_texture_rectangle)
+
+#endif /* !GL_ARB_texture_rectangle */
+
+/* --------------------------- GL_ARB_texture_rg --------------------------- */
+
+#if !defined(GL_ARB_texture_rg)
+#define GL_ARB_texture_rg 1
+
+#define GL_RED 0x1903
+#define GL_COMPRESSED_RED 0x8225
+#define GL_COMPRESSED_RG 0x8226
+#define GL_RG 0x8227
+#define GL_RG_INTEGER 0x8228
+#define GL_R8 0x8229
+#define GL_R16 0x822A
+#define GL_RG8 0x822B
+#define GL_RG16 0x822C
+#define GL_R16F 0x822D
+#define GL_R32F 0x822E
+#define GL_RG16F 0x822F
+#define GL_RG32F 0x8230
+#define GL_R8I 0x8231
+#define GL_R8UI 0x8232
+#define GL_R16I 0x8233
+#define GL_R16UI 0x8234
+#define GL_R32I 0x8235
+#define GL_R32UI 0x8236
+#define GL_RG8I 0x8237
+#define GL_RG8UI 0x8238
+#define GL_RG16I 0x8239
+#define GL_RG16UI 0x823A
+#define GL_RG32I 0x823B
+#define GL_RG32UI 0x823C
+
+#define GLEW_ARB_texture_rg GLEW_GET_VAR(__GLEW_ARB_texture_rg)
+
+#endif /* !GL_ARB_texture_rg */
+
+/* ----------------------- GL_ARB_texture_rgb10_a2ui ----------------------- */
+
+#if !defined(GL_ARB_texture_rgb10_a2ui)
+#define GL_ARB_texture_rgb10_a2ui 1
+
+#define GL_RGB10_A2UI 0x906F
+
+#define GLEW_ARB_texture_rgb10_a2ui GLEW_GET_VAR(__GLEW_ARB_texture_rgb10_a2ui)
+
+#endif /* !GL_ARB_texture_rgb10_a2ui */
+
+/* ------------------------- GL_ARB_texture_storage ------------------------ */
+
+#if !defined(GL_ARB_texture_storage)
+#define GL_ARB_texture_storage 1
+
+#define GL_ALPHA8_EXT 0x803C
+#define GL_LUMINANCE8_EXT 0x8040
+#define GL_LUMINANCE8_ALPHA8_EXT 0x8045
+#define GL_TEXTURE_IMMUTABLE_FORMAT 0x912F
+
+typedef void (GLAPIENTRY * PFNGLTEXSTORAGE1DPROC) (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width);
+typedef void (GLAPIENTRY * PFNGLTEXSTORAGE2DPROC) (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height);
+typedef void (GLAPIENTRY * PFNGLTEXSTORAGE3DPROC) (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth);
+typedef void (GLAPIENTRY * PFNGLTEXTURESTORAGE1DEXTPROC) (GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width);
+typedef void (GLAPIENTRY * PFNGLTEXTURESTORAGE2DEXTPROC) (GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height);
+typedef void (GLAPIENTRY * PFNGLTEXTURESTORAGE3DEXTPROC) (GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth);
+
+#define glTexStorage1D GLEW_GET_FUN(__glewTexStorage1D)
+#define glTexStorage2D GLEW_GET_FUN(__glewTexStorage2D)
+#define glTexStorage3D GLEW_GET_FUN(__glewTexStorage3D)
+#define glTextureStorage1DEXT GLEW_GET_FUN(__glewTextureStorage1DEXT)
+#define glTextureStorage2DEXT GLEW_GET_FUN(__glewTextureStorage2DEXT)
+#define glTextureStorage3DEXT GLEW_GET_FUN(__glewTextureStorage3DEXT)
+
+#define GLEW_ARB_texture_storage GLEW_GET_VAR(__GLEW_ARB_texture_storage)
+
+#endif /* !GL_ARB_texture_storage */
+
+/* ------------------- GL_ARB_texture_storage_multisample ------------------ */
+
+#if !defined(GL_ARB_texture_storage_multisample)
+#define GL_ARB_texture_storage_multisample 1
+
+typedef void (GLAPIENTRY * PFNGLTEXSTORAGE2DMULTISAMPLEPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations);
+typedef void (GLAPIENTRY * PFNGLTEXSTORAGE3DMULTISAMPLEPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedsamplelocations);
+typedef void (GLAPIENTRY * PFNGLTEXTURESTORAGE2DMULTISAMPLEEXTPROC) (GLuint texture, GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations);
+typedef void (GLAPIENTRY * PFNGLTEXTURESTORAGE3DMULTISAMPLEEXTPROC) (GLuint texture, GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedsamplelocations);
+
+#define glTexStorage2DMultisample GLEW_GET_FUN(__glewTexStorage2DMultisample)
+#define glTexStorage3DMultisample GLEW_GET_FUN(__glewTexStorage3DMultisample)
+#define glTextureStorage2DMultisampleEXT GLEW_GET_FUN(__glewTextureStorage2DMultisampleEXT)
+#define glTextureStorage3DMultisampleEXT GLEW_GET_FUN(__glewTextureStorage3DMultisampleEXT)
+
+#define GLEW_ARB_texture_storage_multisample GLEW_GET_VAR(__GLEW_ARB_texture_storage_multisample)
+
+#endif /* !GL_ARB_texture_storage_multisample */
+
+/* ------------------------- GL_ARB_texture_swizzle ------------------------ */
+
+#if !defined(GL_ARB_texture_swizzle)
+#define GL_ARB_texture_swizzle 1
+
+#define GL_TEXTURE_SWIZZLE_R 0x8E42
+#define GL_TEXTURE_SWIZZLE_G 0x8E43
+#define GL_TEXTURE_SWIZZLE_B 0x8E44
+#define GL_TEXTURE_SWIZZLE_A 0x8E45
+#define GL_TEXTURE_SWIZZLE_RGBA 0x8E46
+
+#define GLEW_ARB_texture_swizzle GLEW_GET_VAR(__GLEW_ARB_texture_swizzle)
+
+#endif /* !GL_ARB_texture_swizzle */
+
+/* -------------------------- GL_ARB_texture_view -------------------------- */
+
+#if !defined(GL_ARB_texture_view)
+#define GL_ARB_texture_view 1
+
+#define GL_TEXTURE_VIEW_MIN_LEVEL 0x82DB
+#define GL_TEXTURE_VIEW_NUM_LEVELS 0x82DC
+#define GL_TEXTURE_VIEW_MIN_LAYER 0x82DD
+#define GL_TEXTURE_VIEW_NUM_LAYERS 0x82DE
+#define GL_TEXTURE_IMMUTABLE_LEVELS 0x82DF
+
+typedef void (GLAPIENTRY * PFNGLTEXTUREVIEWPROC) (GLuint texture, GLenum target, GLuint origtexture, GLenum internalformat, GLuint minlevel, GLuint numlevels, GLuint minlayer, GLuint numlayers);
+
+#define glTextureView GLEW_GET_FUN(__glewTextureView)
+
+#define GLEW_ARB_texture_view GLEW_GET_VAR(__GLEW_ARB_texture_view)
+
+#endif /* !GL_ARB_texture_view */
+
+/* --------------------------- GL_ARB_timer_query -------------------------- */
+
+#if !defined(GL_ARB_timer_query)
+#define GL_ARB_timer_query 1
+
+#define GL_TIME_ELAPSED 0x88BF
+#define GL_TIMESTAMP 0x8E28
+
+typedef void (GLAPIENTRY * PFNGLGETQUERYOBJECTI64VPROC) (GLuint id, GLenum pname, GLint64* params);
+typedef void (GLAPIENTRY * PFNGLGETQUERYOBJECTUI64VPROC) (GLuint id, GLenum pname, GLuint64* params);
+typedef void (GLAPIENTRY * PFNGLQUERYCOUNTERPROC) (GLuint id, GLenum target);
+
+#define glGetQueryObjecti64v GLEW_GET_FUN(__glewGetQueryObjecti64v)
+#define glGetQueryObjectui64v GLEW_GET_FUN(__glewGetQueryObjectui64v)
+#define glQueryCounter GLEW_GET_FUN(__glewQueryCounter)
+
+#define GLEW_ARB_timer_query GLEW_GET_VAR(__GLEW_ARB_timer_query)
+
+#endif /* !GL_ARB_timer_query */
+
+/* ----------------------- GL_ARB_transform_feedback2 ---------------------- */
+
+#if !defined(GL_ARB_transform_feedback2)
+#define GL_ARB_transform_feedback2 1
+
+#define GL_TRANSFORM_FEEDBACK 0x8E22
+#define GL_TRANSFORM_FEEDBACK_BUFFER_PAUSED 0x8E23
+#define GL_TRANSFORM_FEEDBACK_BUFFER_ACTIVE 0x8E24
+#define GL_TRANSFORM_FEEDBACK_BINDING 0x8E25
+
+typedef void (GLAPIENTRY * PFNGLBINDTRANSFORMFEEDBACKPROC) (GLenum target, GLuint id);
+typedef void (GLAPIENTRY * PFNGLDELETETRANSFORMFEEDBACKSPROC) (GLsizei n, const GLuint* ids);
+typedef void (GLAPIENTRY * PFNGLDRAWTRANSFORMFEEDBACKPROC) (GLenum mode, GLuint id);
+typedef void (GLAPIENTRY * PFNGLGENTRANSFORMFEEDBACKSPROC) (GLsizei n, GLuint* ids);
+typedef GLboolean (GLAPIENTRY * PFNGLISTRANSFORMFEEDBACKPROC) (GLuint id);
+typedef void (GLAPIENTRY * PFNGLPAUSETRANSFORMFEEDBACKPROC) (void);
+typedef void (GLAPIENTRY * PFNGLRESUMETRANSFORMFEEDBACKPROC) (void);
+
+#define glBindTransformFeedback GLEW_GET_FUN(__glewBindTransformFeedback)
+#define glDeleteTransformFeedbacks GLEW_GET_FUN(__glewDeleteTransformFeedbacks)
+#define glDrawTransformFeedback GLEW_GET_FUN(__glewDrawTransformFeedback)
+#define glGenTransformFeedbacks GLEW_GET_FUN(__glewGenTransformFeedbacks)
+#define glIsTransformFeedback GLEW_GET_FUN(__glewIsTransformFeedback)
+#define glPauseTransformFeedback GLEW_GET_FUN(__glewPauseTransformFeedback)
+#define glResumeTransformFeedback GLEW_GET_FUN(__glewResumeTransformFeedback)
+
+#define GLEW_ARB_transform_feedback2 GLEW_GET_VAR(__GLEW_ARB_transform_feedback2)
+
+#endif /* !GL_ARB_transform_feedback2 */
+
+/* ----------------------- GL_ARB_transform_feedback3 ---------------------- */
+
+#if !defined(GL_ARB_transform_feedback3)
+#define GL_ARB_transform_feedback3 1
+
+#define GL_MAX_TRANSFORM_FEEDBACK_BUFFERS 0x8E70
+#define GL_MAX_VERTEX_STREAMS 0x8E71
+
+typedef void (GLAPIENTRY * PFNGLBEGINQUERYINDEXEDPROC) (GLenum target, GLuint index, GLuint id);
+typedef void (GLAPIENTRY * PFNGLDRAWTRANSFORMFEEDBACKSTREAMPROC) (GLenum mode, GLuint id, GLuint stream);
+typedef void (GLAPIENTRY * PFNGLENDQUERYINDEXEDPROC) (GLenum target, GLuint index);
+typedef void (GLAPIENTRY * PFNGLGETQUERYINDEXEDIVPROC) (GLenum target, GLuint index, GLenum pname, GLint* params);
+
+#define glBeginQueryIndexed GLEW_GET_FUN(__glewBeginQueryIndexed)
+#define glDrawTransformFeedbackStream GLEW_GET_FUN(__glewDrawTransformFeedbackStream)
+#define glEndQueryIndexed GLEW_GET_FUN(__glewEndQueryIndexed)
+#define glGetQueryIndexediv GLEW_GET_FUN(__glewGetQueryIndexediv)
+
+#define GLEW_ARB_transform_feedback3 GLEW_GET_VAR(__GLEW_ARB_transform_feedback3)
+
+#endif /* !GL_ARB_transform_feedback3 */
+
+/* ------------------ GL_ARB_transform_feedback_instanced ------------------ */
+
+#if !defined(GL_ARB_transform_feedback_instanced)
+#define GL_ARB_transform_feedback_instanced 1
+
+typedef void (GLAPIENTRY * PFNGLDRAWTRANSFORMFEEDBACKINSTANCEDPROC) (GLenum mode, GLuint id, GLsizei primcount);
+typedef void (GLAPIENTRY * PFNGLDRAWTRANSFORMFEEDBACKSTREAMINSTANCEDPROC) (GLenum mode, GLuint id, GLuint stream, GLsizei primcount);
+
+#define glDrawTransformFeedbackInstanced GLEW_GET_FUN(__glewDrawTransformFeedbackInstanced)
+#define glDrawTransformFeedbackStreamInstanced GLEW_GET_FUN(__glewDrawTransformFeedbackStreamInstanced)
+
+#define GLEW_ARB_transform_feedback_instanced GLEW_GET_VAR(__GLEW_ARB_transform_feedback_instanced)
+
+#endif /* !GL_ARB_transform_feedback_instanced */
+
+/* ------------------------ GL_ARB_transpose_matrix ------------------------ */
+
+#if !defined(GL_ARB_transpose_matrix)
+#define GL_ARB_transpose_matrix 1
+
+#define GL_TRANSPOSE_MODELVIEW_MATRIX_ARB 0x84E3
+#define GL_TRANSPOSE_PROJECTION_MATRIX_ARB 0x84E4
+#define GL_TRANSPOSE_TEXTURE_MATRIX_ARB 0x84E5
+#define GL_TRANSPOSE_COLOR_MATRIX_ARB 0x84E6
+
+typedef void (GLAPIENTRY * PFNGLLOADTRANSPOSEMATRIXDARBPROC) (GLdouble m[16]);
+typedef void (GLAPIENTRY * PFNGLLOADTRANSPOSEMATRIXFARBPROC) (GLfloat m[16]);
+typedef void (GLAPIENTRY * PFNGLMULTTRANSPOSEMATRIXDARBPROC) (GLdouble m[16]);
+typedef void (GLAPIENTRY * PFNGLMULTTRANSPOSEMATRIXFARBPROC) (GLfloat m[16]);
+
+#define glLoadTransposeMatrixdARB GLEW_GET_FUN(__glewLoadTransposeMatrixdARB)
+#define glLoadTransposeMatrixfARB GLEW_GET_FUN(__glewLoadTransposeMatrixfARB)
+#define glMultTransposeMatrixdARB GLEW_GET_FUN(__glewMultTransposeMatrixdARB)
+#define glMultTransposeMatrixfARB GLEW_GET_FUN(__glewMultTransposeMatrixfARB)
+
+#define GLEW_ARB_transpose_matrix GLEW_GET_VAR(__GLEW_ARB_transpose_matrix)
+
+#endif /* !GL_ARB_transpose_matrix */
+
+/* ---------------------- GL_ARB_uniform_buffer_object --------------------- */
+
+#if !defined(GL_ARB_uniform_buffer_object)
+#define GL_ARB_uniform_buffer_object 1
+
+#define GL_UNIFORM_BUFFER 0x8A11
+#define GL_UNIFORM_BUFFER_BINDING 0x8A28
+#define GL_UNIFORM_BUFFER_START 0x8A29
+#define GL_UNIFORM_BUFFER_SIZE 0x8A2A
+#define GL_MAX_VERTEX_UNIFORM_BLOCKS 0x8A2B
+#define GL_MAX_GEOMETRY_UNIFORM_BLOCKS 0x8A2C
+#define GL_MAX_FRAGMENT_UNIFORM_BLOCKS 0x8A2D
+#define GL_MAX_COMBINED_UNIFORM_BLOCKS 0x8A2E
+#define GL_MAX_UNIFORM_BUFFER_BINDINGS 0x8A2F
+#define GL_MAX_UNIFORM_BLOCK_SIZE 0x8A30
+#define GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS 0x8A31
+#define GL_MAX_COMBINED_GEOMETRY_UNIFORM_COMPONENTS 0x8A32
+#define GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS 0x8A33
+#define GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT 0x8A34
+#define GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH 0x8A35
+#define GL_ACTIVE_UNIFORM_BLOCKS 0x8A36
+#define GL_UNIFORM_TYPE 0x8A37
+#define GL_UNIFORM_SIZE 0x8A38
+#define GL_UNIFORM_NAME_LENGTH 0x8A39
+#define GL_UNIFORM_BLOCK_INDEX 0x8A3A
+#define GL_UNIFORM_OFFSET 0x8A3B
+#define GL_UNIFORM_ARRAY_STRIDE 0x8A3C
+#define GL_UNIFORM_MATRIX_STRIDE 0x8A3D
+#define GL_UNIFORM_IS_ROW_MAJOR 0x8A3E
+#define GL_UNIFORM_BLOCK_BINDING 0x8A3F
+#define GL_UNIFORM_BLOCK_DATA_SIZE 0x8A40
+#define GL_UNIFORM_BLOCK_NAME_LENGTH 0x8A41
+#define GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS 0x8A42
+#define GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES 0x8A43
+#define GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER 0x8A44
+#define GL_UNIFORM_BLOCK_REFERENCED_BY_GEOMETRY_SHADER 0x8A45
+#define GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER 0x8A46
+#define GL_INVALID_INDEX 0xFFFFFFFF
+
+typedef void (GLAPIENTRY * PFNGLBINDBUFFERBASEPROC) (GLenum target, GLuint index, GLuint buffer);
+typedef void (GLAPIENTRY * PFNGLBINDBUFFERRANGEPROC) (GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size);
+typedef void (GLAPIENTRY * PFNGLGETACTIVEUNIFORMBLOCKNAMEPROC) (GLuint program, GLuint uniformBlockIndex, GLsizei bufSize, GLsizei* length, char* uniformBlockName);
+typedef void (GLAPIENTRY * PFNGLGETACTIVEUNIFORMBLOCKIVPROC) (GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint* params);
+typedef void (GLAPIENTRY * PFNGLGETACTIVEUNIFORMNAMEPROC) (GLuint program, GLuint uniformIndex, GLsizei bufSize, GLsizei* length, char* uniformName);
+typedef void (GLAPIENTRY * PFNGLGETACTIVEUNIFORMSIVPROC) (GLuint program, GLsizei uniformCount, const GLuint* uniformIndices, GLenum pname, GLint* params);
+typedef void (GLAPIENTRY * PFNGLGETINTEGERI_VPROC) (GLenum target, GLuint index, GLint* data);
+typedef GLuint (GLAPIENTRY * PFNGLGETUNIFORMBLOCKINDEXPROC) (GLuint program, const char* uniformBlockName);
+typedef void (GLAPIENTRY * PFNGLGETUNIFORMINDICESPROC) (GLuint program, GLsizei uniformCount, const char** uniformNames, GLuint* uniformIndices);
+typedef void (GLAPIENTRY * PFNGLUNIFORMBLOCKBINDINGPROC) (GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding);
+
+#define glBindBufferBase GLEW_GET_FUN(__glewBindBufferBase)
+#define glBindBufferRange GLEW_GET_FUN(__glewBindBufferRange)
+#define glGetActiveUniformBlockName GLEW_GET_FUN(__glewGetActiveUniformBlockName)
+#define glGetActiveUniformBlockiv GLEW_GET_FUN(__glewGetActiveUniformBlockiv)
+#define glGetActiveUniformName GLEW_GET_FUN(__glewGetActiveUniformName)
+#define glGetActiveUniformsiv GLEW_GET_FUN(__glewGetActiveUniformsiv)
+#define glGetIntegeri_v GLEW_GET_FUN(__glewGetIntegeri_v)
+#define glGetUniformBlockIndex GLEW_GET_FUN(__glewGetUniformBlockIndex)
+#define glGetUniformIndices GLEW_GET_FUN(__glewGetUniformIndices)
+#define glUniformBlockBinding GLEW_GET_FUN(__glewUniformBlockBinding)
+
+#define GLEW_ARB_uniform_buffer_object GLEW_GET_VAR(__GLEW_ARB_uniform_buffer_object)
+
+#endif /* !GL_ARB_uniform_buffer_object */
+
+/* ------------------------ GL_ARB_vertex_array_bgra ----------------------- */
+
+#if !defined(GL_ARB_vertex_array_bgra)
+#define GL_ARB_vertex_array_bgra 1
+
+#define GL_BGRA 0x80E1
+
+#define GLEW_ARB_vertex_array_bgra GLEW_GET_VAR(__GLEW_ARB_vertex_array_bgra)
+
+#endif /* !GL_ARB_vertex_array_bgra */
+
+/* ----------------------- GL_ARB_vertex_array_object ---------------------- */
+
+#if !defined(GL_ARB_vertex_array_object)
+#define GL_ARB_vertex_array_object 1
+
+#define GL_VERTEX_ARRAY_BINDING 0x85B5
+
+typedef void (GLAPIENTRY * PFNGLBINDVERTEXARRAYPROC) (GLuint array);
+typedef void (GLAPIENTRY * PFNGLDELETEVERTEXARRAYSPROC) (GLsizei n, const GLuint* arrays);
+typedef void (GLAPIENTRY * PFNGLGENVERTEXARRAYSPROC) (GLsizei n, GLuint* arrays);
+typedef GLboolean (GLAPIENTRY * PFNGLISVERTEXARRAYPROC) (GLuint array);
+
+#define glBindVertexArray GLEW_GET_FUN(__glewBindVertexArray)
+#define glDeleteVertexArrays GLEW_GET_FUN(__glewDeleteVertexArrays)
+#define glGenVertexArrays GLEW_GET_FUN(__glewGenVertexArrays)
+#define glIsVertexArray GLEW_GET_FUN(__glewIsVertexArray)
+
+#define GLEW_ARB_vertex_array_object GLEW_GET_VAR(__GLEW_ARB_vertex_array_object)
+
+#endif /* !GL_ARB_vertex_array_object */
+
+/* ----------------------- GL_ARB_vertex_attrib_64bit ---------------------- */
+
+#if !defined(GL_ARB_vertex_attrib_64bit)
+#define GL_ARB_vertex_attrib_64bit 1
+
+#define GL_DOUBLE_MAT2 0x8F46
+#define GL_DOUBLE_MAT3 0x8F47
+#define GL_DOUBLE_MAT4 0x8F48
+#define GL_DOUBLE_VEC2 0x8FFC
+#define GL_DOUBLE_VEC3 0x8FFD
+#define GL_DOUBLE_VEC4 0x8FFE
+
+typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBLDVPROC) (GLuint index, GLenum pname, GLdouble* params);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL1DPROC) (GLuint index, GLdouble x);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL1DVPROC) (GLuint index, const GLdouble* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL2DPROC) (GLuint index, GLdouble x, GLdouble y);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL2DVPROC) (GLuint index, const GLdouble* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL3DPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL3DVPROC) (GLuint index, const GLdouble* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL4DPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL4DVPROC) (GLuint index, const GLdouble* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBLPOINTERPROC) (GLuint index, GLint size, GLenum type, GLsizei stride, const void* pointer);
+
+#define glGetVertexAttribLdv GLEW_GET_FUN(__glewGetVertexAttribLdv)
+#define glVertexAttribL1d GLEW_GET_FUN(__glewVertexAttribL1d)
+#define glVertexAttribL1dv GLEW_GET_FUN(__glewVertexAttribL1dv)
+#define glVertexAttribL2d GLEW_GET_FUN(__glewVertexAttribL2d)
+#define glVertexAttribL2dv GLEW_GET_FUN(__glewVertexAttribL2dv)
+#define glVertexAttribL3d GLEW_GET_FUN(__glewVertexAttribL3d)
+#define glVertexAttribL3dv GLEW_GET_FUN(__glewVertexAttribL3dv)
+#define glVertexAttribL4d GLEW_GET_FUN(__glewVertexAttribL4d)
+#define glVertexAttribL4dv GLEW_GET_FUN(__glewVertexAttribL4dv)
+#define glVertexAttribLPointer GLEW_GET_FUN(__glewVertexAttribLPointer)
+
+#define GLEW_ARB_vertex_attrib_64bit GLEW_GET_VAR(__GLEW_ARB_vertex_attrib_64bit)
+
+#endif /* !GL_ARB_vertex_attrib_64bit */
+
+/* ---------------------- GL_ARB_vertex_attrib_binding --------------------- */
+
+#if !defined(GL_ARB_vertex_attrib_binding)
+#define GL_ARB_vertex_attrib_binding 1
+
+#define GL_VERTEX_ATTRIB_BINDING 0x82D4
+#define GL_VERTEX_ATTRIB_RELATIVE_OFFSET 0x82D5
+#define GL_VERTEX_BINDING_DIVISOR 0x82D6
+#define GL_VERTEX_BINDING_OFFSET 0x82D7
+#define GL_VERTEX_BINDING_STRIDE 0x82D8
+#define GL_MAX_VERTEX_ATTRIB_RELATIVE_OFFSET 0x82D9
+#define GL_MAX_VERTEX_ATTRIB_BINDINGS 0x82DA
+
+typedef void (GLAPIENTRY * PFNGLBINDVERTEXBUFFERPROC) (GLuint bindingindex, GLuint buffer, GLintptr offset, GLsizei stride);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBBINDINGPROC) (GLuint attribindex, GLuint bindingindex);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBFORMATPROC) (GLuint attribindex, GLint size, GLenum type, GLboolean normalized, GLuint relativeoffset);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBIFORMATPROC) (GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBLFORMATPROC) (GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset);
+typedef void (GLAPIENTRY * PFNGLVERTEXBINDINGDIVISORPROC) (GLuint bindingindex, GLuint divisor);
+
+#define glBindVertexBuffer GLEW_GET_FUN(__glewBindVertexBuffer)
+#define glVertexAttribBinding GLEW_GET_FUN(__glewVertexAttribBinding)
+#define glVertexAttribFormat GLEW_GET_FUN(__glewVertexAttribFormat)
+#define glVertexAttribIFormat GLEW_GET_FUN(__glewVertexAttribIFormat)
+#define glVertexAttribLFormat GLEW_GET_FUN(__glewVertexAttribLFormat)
+#define glVertexBindingDivisor GLEW_GET_FUN(__glewVertexBindingDivisor)
+
+#define GLEW_ARB_vertex_attrib_binding GLEW_GET_VAR(__GLEW_ARB_vertex_attrib_binding)
+
+#endif /* !GL_ARB_vertex_attrib_binding */
+
+/* -------------------------- GL_ARB_vertex_blend -------------------------- */
+
+#if !defined(GL_ARB_vertex_blend)
+#define GL_ARB_vertex_blend 1
+
+#define GL_MODELVIEW0_ARB 0x1700
+#define GL_MODELVIEW1_ARB 0x850A
+#define GL_MAX_VERTEX_UNITS_ARB 0x86A4
+#define GL_ACTIVE_VERTEX_UNITS_ARB 0x86A5
+#define GL_WEIGHT_SUM_UNITY_ARB 0x86A6
+#define GL_VERTEX_BLEND_ARB 0x86A7
+#define GL_CURRENT_WEIGHT_ARB 0x86A8
+#define GL_WEIGHT_ARRAY_TYPE_ARB 0x86A9
+#define GL_WEIGHT_ARRAY_STRIDE_ARB 0x86AA
+#define GL_WEIGHT_ARRAY_SIZE_ARB 0x86AB
+#define GL_WEIGHT_ARRAY_POINTER_ARB 0x86AC
+#define GL_WEIGHT_ARRAY_ARB 0x86AD
+#define GL_MODELVIEW2_ARB 0x8722
+#define GL_MODELVIEW3_ARB 0x8723
+#define GL_MODELVIEW4_ARB 0x8724
+#define GL_MODELVIEW5_ARB 0x8725
+#define GL_MODELVIEW6_ARB 0x8726
+#define GL_MODELVIEW7_ARB 0x8727
+#define GL_MODELVIEW8_ARB 0x8728
+#define GL_MODELVIEW9_ARB 0x8729
+#define GL_MODELVIEW10_ARB 0x872A
+#define GL_MODELVIEW11_ARB 0x872B
+#define GL_MODELVIEW12_ARB 0x872C
+#define GL_MODELVIEW13_ARB 0x872D
+#define GL_MODELVIEW14_ARB 0x872E
+#define GL_MODELVIEW15_ARB 0x872F
+#define GL_MODELVIEW16_ARB 0x8730
+#define GL_MODELVIEW17_ARB 0x8731
+#define GL_MODELVIEW18_ARB 0x8732
+#define GL_MODELVIEW19_ARB 0x8733
+#define GL_MODELVIEW20_ARB 0x8734
+#define GL_MODELVIEW21_ARB 0x8735
+#define GL_MODELVIEW22_ARB 0x8736
+#define GL_MODELVIEW23_ARB 0x8737
+#define GL_MODELVIEW24_ARB 0x8738
+#define GL_MODELVIEW25_ARB 0x8739
+#define GL_MODELVIEW26_ARB 0x873A
+#define GL_MODELVIEW27_ARB 0x873B
+#define GL_MODELVIEW28_ARB 0x873C
+#define GL_MODELVIEW29_ARB 0x873D
+#define GL_MODELVIEW30_ARB 0x873E
+#define GL_MODELVIEW31_ARB 0x873F
+
+typedef void (GLAPIENTRY * PFNGLVERTEXBLENDARBPROC) (GLint count);
+typedef void (GLAPIENTRY * PFNGLWEIGHTPOINTERARBPROC) (GLint size, GLenum type, GLsizei stride, GLvoid *pointer);
+typedef void (GLAPIENTRY * PFNGLWEIGHTBVARBPROC) (GLint size, GLbyte *weights);
+typedef void (GLAPIENTRY * PFNGLWEIGHTDVARBPROC) (GLint size, GLdouble *weights);
+typedef void (GLAPIENTRY * PFNGLWEIGHTFVARBPROC) (GLint size, GLfloat *weights);
+typedef void (GLAPIENTRY * PFNGLWEIGHTIVARBPROC) (GLint size, GLint *weights);
+typedef void (GLAPIENTRY * PFNGLWEIGHTSVARBPROC) (GLint size, GLshort *weights);
+typedef void (GLAPIENTRY * PFNGLWEIGHTUBVARBPROC) (GLint size, GLubyte *weights);
+typedef void (GLAPIENTRY * PFNGLWEIGHTUIVARBPROC) (GLint size, GLuint *weights);
+typedef void (GLAPIENTRY * PFNGLWEIGHTUSVARBPROC) (GLint size, GLushort *weights);
+
+#define glVertexBlendARB GLEW_GET_FUN(__glewVertexBlendARB)
+#define glWeightPointerARB GLEW_GET_FUN(__glewWeightPointerARB)
+#define glWeightbvARB GLEW_GET_FUN(__glewWeightbvARB)
+#define glWeightdvARB GLEW_GET_FUN(__glewWeightdvARB)
+#define glWeightfvARB GLEW_GET_FUN(__glewWeightfvARB)
+#define glWeightivARB GLEW_GET_FUN(__glewWeightivARB)
+#define glWeightsvARB GLEW_GET_FUN(__glewWeightsvARB)
+#define glWeightubvARB GLEW_GET_FUN(__glewWeightubvARB)
+#define glWeightuivARB GLEW_GET_FUN(__glewWeightuivARB)
+#define glWeightusvARB GLEW_GET_FUN(__glewWeightusvARB)
+
+#define GLEW_ARB_vertex_blend GLEW_GET_VAR(__GLEW_ARB_vertex_blend)
+
+#endif /* !GL_ARB_vertex_blend */
+
+/* ---------------------- GL_ARB_vertex_buffer_object ---------------------- */
+
+#if !defined(GL_ARB_vertex_buffer_object)
+#define GL_ARB_vertex_buffer_object 1
+
+#define GL_BUFFER_SIZE_ARB 0x8764
+#define GL_BUFFER_USAGE_ARB 0x8765
+#define GL_ARRAY_BUFFER_ARB 0x8892
+#define GL_ELEMENT_ARRAY_BUFFER_ARB 0x8893
+#define GL_ARRAY_BUFFER_BINDING_ARB 0x8894
+#define GL_ELEMENT_ARRAY_BUFFER_BINDING_ARB 0x8895
+#define GL_VERTEX_ARRAY_BUFFER_BINDING_ARB 0x8896
+#define GL_NORMAL_ARRAY_BUFFER_BINDING_ARB 0x8897
+#define GL_COLOR_ARRAY_BUFFER_BINDING_ARB 0x8898
+#define GL_INDEX_ARRAY_BUFFER_BINDING_ARB 0x8899
+#define GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING_ARB 0x889A
+#define GL_EDGE_FLAG_ARRAY_BUFFER_BINDING_ARB 0x889B
+#define GL_SECONDARY_COLOR_ARRAY_BUFFER_BINDING_ARB 0x889C
+#define GL_FOG_COORDINATE_ARRAY_BUFFER_BINDING_ARB 0x889D
+#define GL_WEIGHT_ARRAY_BUFFER_BINDING_ARB 0x889E
+#define GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING_ARB 0x889F
+#define GL_READ_ONLY_ARB 0x88B8
+#define GL_WRITE_ONLY_ARB 0x88B9
+#define GL_READ_WRITE_ARB 0x88BA
+#define GL_BUFFER_ACCESS_ARB 0x88BB
+#define GL_BUFFER_MAPPED_ARB 0x88BC
+#define GL_BUFFER_MAP_POINTER_ARB 0x88BD
+#define GL_STREAM_DRAW_ARB 0x88E0
+#define GL_STREAM_READ_ARB 0x88E1
+#define GL_STREAM_COPY_ARB 0x88E2
+#define GL_STATIC_DRAW_ARB 0x88E4
+#define GL_STATIC_READ_ARB 0x88E5
+#define GL_STATIC_COPY_ARB 0x88E6
+#define GL_DYNAMIC_DRAW_ARB 0x88E8
+#define GL_DYNAMIC_READ_ARB 0x88E9
+#define GL_DYNAMIC_COPY_ARB 0x88EA
+
+typedef ptrdiff_t GLintptrARB;
+typedef ptrdiff_t GLsizeiptrARB;
+
+typedef void (GLAPIENTRY * PFNGLBINDBUFFERARBPROC) (GLenum target, GLuint buffer);
+typedef void (GLAPIENTRY * PFNGLBUFFERDATAARBPROC) (GLenum target, GLsizeiptrARB size, const GLvoid* data, GLenum usage);
+typedef void (GLAPIENTRY * PFNGLBUFFERSUBDATAARBPROC) (GLenum target, GLintptrARB offset, GLsizeiptrARB size, const GLvoid* data);
+typedef void (GLAPIENTRY * PFNGLDELETEBUFFERSARBPROC) (GLsizei n, const GLuint* buffers);
+typedef void (GLAPIENTRY * PFNGLGENBUFFERSARBPROC) (GLsizei n, GLuint* buffers);
+typedef void (GLAPIENTRY * PFNGLGETBUFFERPARAMETERIVARBPROC) (GLenum target, GLenum pname, GLint* params);
+typedef void (GLAPIENTRY * PFNGLGETBUFFERPOINTERVARBPROC) (GLenum target, GLenum pname, GLvoid** params);
+typedef void (GLAPIENTRY * PFNGLGETBUFFERSUBDATAARBPROC) (GLenum target, GLintptrARB offset, GLsizeiptrARB size, GLvoid* data);
+typedef GLboolean (GLAPIENTRY * PFNGLISBUFFERARBPROC) (GLuint buffer);
+typedef GLvoid * (GLAPIENTRY * PFNGLMAPBUFFERARBPROC) (GLenum target, GLenum access);
+typedef GLboolean (GLAPIENTRY * PFNGLUNMAPBUFFERARBPROC) (GLenum target);
+
+#define glBindBufferARB GLEW_GET_FUN(__glewBindBufferARB)
+#define glBufferDataARB GLEW_GET_FUN(__glewBufferDataARB)
+#define glBufferSubDataARB GLEW_GET_FUN(__glewBufferSubDataARB)
+#define glDeleteBuffersARB GLEW_GET_FUN(__glewDeleteBuffersARB)
+#define glGenBuffersARB GLEW_GET_FUN(__glewGenBuffersARB)
+#define glGetBufferParameterivARB GLEW_GET_FUN(__glewGetBufferParameterivARB)
+#define glGetBufferPointervARB GLEW_GET_FUN(__glewGetBufferPointervARB)
+#define glGetBufferSubDataARB GLEW_GET_FUN(__glewGetBufferSubDataARB)
+#define glIsBufferARB GLEW_GET_FUN(__glewIsBufferARB)
+#define glMapBufferARB GLEW_GET_FUN(__glewMapBufferARB)
+#define glUnmapBufferARB GLEW_GET_FUN(__glewUnmapBufferARB)
+
+#define GLEW_ARB_vertex_buffer_object GLEW_GET_VAR(__GLEW_ARB_vertex_buffer_object)
+
+#endif /* !GL_ARB_vertex_buffer_object */
+
+/* ------------------------- GL_ARB_vertex_program ------------------------- */
+
+#if !defined(GL_ARB_vertex_program)
+#define GL_ARB_vertex_program 1
+
+#define GL_COLOR_SUM_ARB 0x8458
+#define GL_VERTEX_PROGRAM_ARB 0x8620
+#define GL_VERTEX_ATTRIB_ARRAY_ENABLED_ARB 0x8622
+#define GL_VERTEX_ATTRIB_ARRAY_SIZE_ARB 0x8623
+#define GL_VERTEX_ATTRIB_ARRAY_STRIDE_ARB 0x8624
+#define GL_VERTEX_ATTRIB_ARRAY_TYPE_ARB 0x8625
+#define GL_CURRENT_VERTEX_ATTRIB_ARB 0x8626
+#define GL_PROGRAM_LENGTH_ARB 0x8627
+#define GL_PROGRAM_STRING_ARB 0x8628
+#define GL_MAX_PROGRAM_MATRIX_STACK_DEPTH_ARB 0x862E
+#define GL_MAX_PROGRAM_MATRICES_ARB 0x862F
+#define GL_CURRENT_MATRIX_STACK_DEPTH_ARB 0x8640
+#define GL_CURRENT_MATRIX_ARB 0x8641
+#define GL_VERTEX_PROGRAM_POINT_SIZE_ARB 0x8642
+#define GL_VERTEX_PROGRAM_TWO_SIDE_ARB 0x8643
+#define GL_VERTEX_ATTRIB_ARRAY_POINTER_ARB 0x8645
+#define GL_PROGRAM_ERROR_POSITION_ARB 0x864B
+#define GL_PROGRAM_BINDING_ARB 0x8677
+#define GL_MAX_VERTEX_ATTRIBS_ARB 0x8869
+#define GL_VERTEX_ATTRIB_ARRAY_NORMALIZED_ARB 0x886A
+#define GL_PROGRAM_ERROR_STRING_ARB 0x8874
+#define GL_PROGRAM_FORMAT_ASCII_ARB 0x8875
+#define GL_PROGRAM_FORMAT_ARB 0x8876
+#define GL_PROGRAM_INSTRUCTIONS_ARB 0x88A0
+#define GL_MAX_PROGRAM_INSTRUCTIONS_ARB 0x88A1
+#define GL_PROGRAM_NATIVE_INSTRUCTIONS_ARB 0x88A2
+#define GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB 0x88A3
+#define GL_PROGRAM_TEMPORARIES_ARB 0x88A4
+#define GL_MAX_PROGRAM_TEMPORARIES_ARB 0x88A5
+#define GL_PROGRAM_NATIVE_TEMPORARIES_ARB 0x88A6
+#define GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB 0x88A7
+#define GL_PROGRAM_PARAMETERS_ARB 0x88A8
+#define GL_MAX_PROGRAM_PARAMETERS_ARB 0x88A9
+#define GL_PROGRAM_NATIVE_PARAMETERS_ARB 0x88AA
+#define GL_MAX_PROGRAM_NATIVE_PARAMETERS_ARB 0x88AB
+#define GL_PROGRAM_ATTRIBS_ARB 0x88AC
+#define GL_MAX_PROGRAM_ATTRIBS_ARB 0x88AD
+#define GL_PROGRAM_NATIVE_ATTRIBS_ARB 0x88AE
+#define GL_MAX_PROGRAM_NATIVE_ATTRIBS_ARB 0x88AF
+#define GL_PROGRAM_ADDRESS_REGISTERS_ARB 0x88B0
+#define GL_MAX_PROGRAM_ADDRESS_REGISTERS_ARB 0x88B1
+#define GL_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB 0x88B2
+#define GL_MAX_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB 0x88B3
+#define GL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB 0x88B4
+#define GL_MAX_PROGRAM_ENV_PARAMETERS_ARB 0x88B5
+#define GL_PROGRAM_UNDER_NATIVE_LIMITS_ARB 0x88B6
+#define GL_TRANSPOSE_CURRENT_MATRIX_ARB 0x88B7
+#define GL_MATRIX0_ARB 0x88C0
+#define GL_MATRIX1_ARB 0x88C1
+#define GL_MATRIX2_ARB 0x88C2
+#define GL_MATRIX3_ARB 0x88C3
+#define GL_MATRIX4_ARB 0x88C4
+#define GL_MATRIX5_ARB 0x88C5
+#define GL_MATRIX6_ARB 0x88C6
+#define GL_MATRIX7_ARB 0x88C7
+#define GL_MATRIX8_ARB 0x88C8
+#define GL_MATRIX9_ARB 0x88C9
+#define GL_MATRIX10_ARB 0x88CA
+#define GL_MATRIX11_ARB 0x88CB
+#define GL_MATRIX12_ARB 0x88CC
+#define GL_MATRIX13_ARB 0x88CD
+#define GL_MATRIX14_ARB 0x88CE
+#define GL_MATRIX15_ARB 0x88CF
+#define GL_MATRIX16_ARB 0x88D0
+#define GL_MATRIX17_ARB 0x88D1
+#define GL_MATRIX18_ARB 0x88D2
+#define GL_MATRIX19_ARB 0x88D3
+#define GL_MATRIX20_ARB 0x88D4
+#define GL_MATRIX21_ARB 0x88D5
+#define GL_MATRIX22_ARB 0x88D6
+#define GL_MATRIX23_ARB 0x88D7
+#define GL_MATRIX24_ARB 0x88D8
+#define GL_MATRIX25_ARB 0x88D9
+#define GL_MATRIX26_ARB 0x88DA
+#define GL_MATRIX27_ARB 0x88DB
+#define GL_MATRIX28_ARB 0x88DC
+#define GL_MATRIX29_ARB 0x88DD
+#define GL_MATRIX30_ARB 0x88DE
+#define GL_MATRIX31_ARB 0x88DF
+
+typedef void (GLAPIENTRY * PFNGLBINDPROGRAMARBPROC) (GLenum target, GLuint program);
+typedef void (GLAPIENTRY * PFNGLDELETEPROGRAMSARBPROC) (GLsizei n, const GLuint* programs);
+typedef void (GLAPIENTRY * PFNGLDISABLEVERTEXATTRIBARRAYARBPROC) (GLuint index);
+typedef void (GLAPIENTRY * PFNGLENABLEVERTEXATTRIBARRAYARBPROC) (GLuint index);
+typedef void (GLAPIENTRY * PFNGLGENPROGRAMSARBPROC) (GLsizei n, GLuint* programs);
+typedef void (GLAPIENTRY * PFNGLGETPROGRAMENVPARAMETERDVARBPROC) (GLenum target, GLuint index, GLdouble* params);
+typedef void (GLAPIENTRY * PFNGLGETPROGRAMENVPARAMETERFVARBPROC) (GLenum target, GLuint index, GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLGETPROGRAMLOCALPARAMETERDVARBPROC) (GLenum target, GLuint index, GLdouble* params);
+typedef void (GLAPIENTRY * PFNGLGETPROGRAMLOCALPARAMETERFVARBPROC) (GLenum target, GLuint index, GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLGETPROGRAMSTRINGARBPROC) (GLenum target, GLenum pname, void* string);
+typedef void (GLAPIENTRY * PFNGLGETPROGRAMIVARBPROC) (GLenum target, GLenum pname, GLint* params);
+typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBPOINTERVARBPROC) (GLuint index, GLenum pname, GLvoid** pointer);
+typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBDVARBPROC) (GLuint index, GLenum pname, GLdouble* params);
+typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBFVARBPROC) (GLuint index, GLenum pname, GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBIVARBPROC) (GLuint index, GLenum pname, GLint* params);
+typedef GLboolean (GLAPIENTRY * PFNGLISPROGRAMARBPROC) (GLuint program);
+typedef void (GLAPIENTRY * PFNGLPROGRAMENVPARAMETER4DARBPROC) (GLenum target, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+typedef void (GLAPIENTRY * PFNGLPROGRAMENVPARAMETER4DVARBPROC) (GLenum target, GLuint index, const GLdouble* params);
+typedef void (GLAPIENTRY * PFNGLPROGRAMENVPARAMETER4FARBPROC) (GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+typedef void (GLAPIENTRY * PFNGLPROGRAMENVPARAMETER4FVARBPROC) (GLenum target, GLuint index, const GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLPROGRAMLOCALPARAMETER4DARBPROC) (GLenum target, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+typedef void (GLAPIENTRY * PFNGLPROGRAMLOCALPARAMETER4DVARBPROC) (GLenum target, GLuint index, const GLdouble* params);
+typedef void (GLAPIENTRY * PFNGLPROGRAMLOCALPARAMETER4FARBPROC) (GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+typedef void (GLAPIENTRY * PFNGLPROGRAMLOCALPARAMETER4FVARBPROC) (GLenum target, GLuint index, const GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLPROGRAMSTRINGARBPROC) (GLenum target, GLenum format, GLsizei len, const void* string);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB1DARBPROC) (GLuint index, GLdouble x);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB1DVARBPROC) (GLuint index, const GLdouble* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB1FARBPROC) (GLuint index, GLfloat x);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB1FVARBPROC) (GLuint index, const GLfloat* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB1SARBPROC) (GLuint index, GLshort x);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB1SVARBPROC) (GLuint index, const GLshort* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB2DARBPROC) (GLuint index, GLdouble x, GLdouble y);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB2DVARBPROC) (GLuint index, const GLdouble* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB2FARBPROC) (GLuint index, GLfloat x, GLfloat y);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB2FVARBPROC) (GLuint index, const GLfloat* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB2SARBPROC) (GLuint index, GLshort x, GLshort y);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB2SVARBPROC) (GLuint index, const GLshort* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB3DARBPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB3DVARBPROC) (GLuint index, const GLdouble* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB3FARBPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB3FVARBPROC) (GLuint index, const GLfloat* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB3SARBPROC) (GLuint index, GLshort x, GLshort y, GLshort z);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB3SVARBPROC) (GLuint index, const GLshort* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4NBVARBPROC) (GLuint index, const GLbyte* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4NIVARBPROC) (GLuint index, const GLint* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4NSVARBPROC) (GLuint index, const GLshort* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4NUBARBPROC) (GLuint index, GLubyte x, GLubyte y, GLubyte z, GLubyte w);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4NUBVARBPROC) (GLuint index, const GLubyte* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4NUIVARBPROC) (GLuint index, const GLuint* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4NUSVARBPROC) (GLuint index, const GLushort* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4BVARBPROC) (GLuint index, const GLbyte* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4DARBPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4DVARBPROC) (GLuint index, const GLdouble* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4FARBPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4FVARBPROC) (GLuint index, const GLfloat* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4IVARBPROC) (GLuint index, const GLint* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4SARBPROC) (GLuint index, GLshort x, GLshort y, GLshort z, GLshort w);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4SVARBPROC) (GLuint index, const GLshort* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4UBVARBPROC) (GLuint index, const GLubyte* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4UIVARBPROC) (GLuint index, const GLuint* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4USVARBPROC) (GLuint index, const GLushort* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBPOINTERARBPROC) (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void* pointer);
+
+#define glBindProgramARB GLEW_GET_FUN(__glewBindProgramARB)
+#define glDeleteProgramsARB GLEW_GET_FUN(__glewDeleteProgramsARB)
+#define glDisableVertexAttribArrayARB GLEW_GET_FUN(__glewDisableVertexAttribArrayARB)
+#define glEnableVertexAttribArrayARB GLEW_GET_FUN(__glewEnableVertexAttribArrayARB)
+#define glGenProgramsARB GLEW_GET_FUN(__glewGenProgramsARB)
+#define glGetProgramEnvParameterdvARB GLEW_GET_FUN(__glewGetProgramEnvParameterdvARB)
+#define glGetProgramEnvParameterfvARB GLEW_GET_FUN(__glewGetProgramEnvParameterfvARB)
+#define glGetProgramLocalParameterdvARB GLEW_GET_FUN(__glewGetProgramLocalParameterdvARB)
+#define glGetProgramLocalParameterfvARB GLEW_GET_FUN(__glewGetProgramLocalParameterfvARB)
+#define glGetProgramStringARB GLEW_GET_FUN(__glewGetProgramStringARB)
+#define glGetProgramivARB GLEW_GET_FUN(__glewGetProgramivARB)
+#define glGetVertexAttribPointervARB GLEW_GET_FUN(__glewGetVertexAttribPointervARB)
+#define glGetVertexAttribdvARB GLEW_GET_FUN(__glewGetVertexAttribdvARB)
+#define glGetVertexAttribfvARB GLEW_GET_FUN(__glewGetVertexAttribfvARB)
+#define glGetVertexAttribivARB GLEW_GET_FUN(__glewGetVertexAttribivARB)
+#define glIsProgramARB GLEW_GET_FUN(__glewIsProgramARB)
+#define glProgramEnvParameter4dARB GLEW_GET_FUN(__glewProgramEnvParameter4dARB)
+#define glProgramEnvParameter4dvARB GLEW_GET_FUN(__glewProgramEnvParameter4dvARB)
+#define glProgramEnvParameter4fARB GLEW_GET_FUN(__glewProgramEnvParameter4fARB)
+#define glProgramEnvParameter4fvARB GLEW_GET_FUN(__glewProgramEnvParameter4fvARB)
+#define glProgramLocalParameter4dARB GLEW_GET_FUN(__glewProgramLocalParameter4dARB)
+#define glProgramLocalParameter4dvARB GLEW_GET_FUN(__glewProgramLocalParameter4dvARB)
+#define glProgramLocalParameter4fARB GLEW_GET_FUN(__glewProgramLocalParameter4fARB)
+#define glProgramLocalParameter4fvARB GLEW_GET_FUN(__glewProgramLocalParameter4fvARB)
+#define glProgramStringARB GLEW_GET_FUN(__glewProgramStringARB)
+#define glVertexAttrib1dARB GLEW_GET_FUN(__glewVertexAttrib1dARB)
+#define glVertexAttrib1dvARB GLEW_GET_FUN(__glewVertexAttrib1dvARB)
+#define glVertexAttrib1fARB GLEW_GET_FUN(__glewVertexAttrib1fARB)
+#define glVertexAttrib1fvARB GLEW_GET_FUN(__glewVertexAttrib1fvARB)
+#define glVertexAttrib1sARB GLEW_GET_FUN(__glewVertexAttrib1sARB)
+#define glVertexAttrib1svARB GLEW_GET_FUN(__glewVertexAttrib1svARB)
+#define glVertexAttrib2dARB GLEW_GET_FUN(__glewVertexAttrib2dARB)
+#define glVertexAttrib2dvARB GLEW_GET_FUN(__glewVertexAttrib2dvARB)
+#define glVertexAttrib2fARB GLEW_GET_FUN(__glewVertexAttrib2fARB)
+#define glVertexAttrib2fvARB GLEW_GET_FUN(__glewVertexAttrib2fvARB)
+#define glVertexAttrib2sARB GLEW_GET_FUN(__glewVertexAttrib2sARB)
+#define glVertexAttrib2svARB GLEW_GET_FUN(__glewVertexAttrib2svARB)
+#define glVertexAttrib3dARB GLEW_GET_FUN(__glewVertexAttrib3dARB)
+#define glVertexAttrib3dvARB GLEW_GET_FUN(__glewVertexAttrib3dvARB)
+#define glVertexAttrib3fARB GLEW_GET_FUN(__glewVertexAttrib3fARB)
+#define glVertexAttrib3fvARB GLEW_GET_FUN(__glewVertexAttrib3fvARB)
+#define glVertexAttrib3sARB GLEW_GET_FUN(__glewVertexAttrib3sARB)
+#define glVertexAttrib3svARB GLEW_GET_FUN(__glewVertexAttrib3svARB)
+#define glVertexAttrib4NbvARB GLEW_GET_FUN(__glewVertexAttrib4NbvARB)
+#define glVertexAttrib4NivARB GLEW_GET_FUN(__glewVertexAttrib4NivARB)
+#define glVertexAttrib4NsvARB GLEW_GET_FUN(__glewVertexAttrib4NsvARB)
+#define glVertexAttrib4NubARB GLEW_GET_FUN(__glewVertexAttrib4NubARB)
+#define glVertexAttrib4NubvARB GLEW_GET_FUN(__glewVertexAttrib4NubvARB)
+#define glVertexAttrib4NuivARB GLEW_GET_FUN(__glewVertexAttrib4NuivARB)
+#define glVertexAttrib4NusvARB GLEW_GET_FUN(__glewVertexAttrib4NusvARB)
+#define glVertexAttrib4bvARB GLEW_GET_FUN(__glewVertexAttrib4bvARB)
+#define glVertexAttrib4dARB GLEW_GET_FUN(__glewVertexAttrib4dARB)
+#define glVertexAttrib4dvARB GLEW_GET_FUN(__glewVertexAttrib4dvARB)
+#define glVertexAttrib4fARB GLEW_GET_FUN(__glewVertexAttrib4fARB)
+#define glVertexAttrib4fvARB GLEW_GET_FUN(__glewVertexAttrib4fvARB)
+#define glVertexAttrib4ivARB GLEW_GET_FUN(__glewVertexAttrib4ivARB)
+#define glVertexAttrib4sARB GLEW_GET_FUN(__glewVertexAttrib4sARB)
+#define glVertexAttrib4svARB GLEW_GET_FUN(__glewVertexAttrib4svARB)
+#define glVertexAttrib4ubvARB GLEW_GET_FUN(__glewVertexAttrib4ubvARB)
+#define glVertexAttrib4uivARB GLEW_GET_FUN(__glewVertexAttrib4uivARB)
+#define glVertexAttrib4usvARB GLEW_GET_FUN(__glewVertexAttrib4usvARB)
+#define glVertexAttribPointerARB GLEW_GET_FUN(__glewVertexAttribPointerARB)
+
+#define GLEW_ARB_vertex_program GLEW_GET_VAR(__GLEW_ARB_vertex_program)
+
+#endif /* !GL_ARB_vertex_program */
+
+/* -------------------------- GL_ARB_vertex_shader ------------------------- */
+
+#if !defined(GL_ARB_vertex_shader)
+#define GL_ARB_vertex_shader 1
+
+#define GL_VERTEX_SHADER_ARB 0x8B31
+#define GL_MAX_VERTEX_UNIFORM_COMPONENTS_ARB 0x8B4A
+#define GL_MAX_VARYING_FLOATS_ARB 0x8B4B
+#define GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS_ARB 0x8B4C
+#define GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS_ARB 0x8B4D
+#define GL_OBJECT_ACTIVE_ATTRIBUTES_ARB 0x8B89
+#define GL_OBJECT_ACTIVE_ATTRIBUTE_MAX_LENGTH_ARB 0x8B8A
+
+typedef void (GLAPIENTRY * PFNGLBINDATTRIBLOCATIONARBPROC) (GLhandleARB programObj, GLuint index, const GLcharARB* name);
+typedef void (GLAPIENTRY * PFNGLGETACTIVEATTRIBARBPROC) (GLhandleARB programObj, GLuint index, GLsizei maxLength, GLsizei* length, GLint *size, GLenum *type, GLcharARB *name);
+typedef GLint (GLAPIENTRY * PFNGLGETATTRIBLOCATIONARBPROC) (GLhandleARB programObj, const GLcharARB* name);
+
+#define glBindAttribLocationARB GLEW_GET_FUN(__glewBindAttribLocationARB)
+#define glGetActiveAttribARB GLEW_GET_FUN(__glewGetActiveAttribARB)
+#define glGetAttribLocationARB GLEW_GET_FUN(__glewGetAttribLocationARB)
+
+#define GLEW_ARB_vertex_shader GLEW_GET_VAR(__GLEW_ARB_vertex_shader)
+
+#endif /* !GL_ARB_vertex_shader */
+
+/* ------------------- GL_ARB_vertex_type_2_10_10_10_rev ------------------- */
+
+#if !defined(GL_ARB_vertex_type_2_10_10_10_rev)
+#define GL_ARB_vertex_type_2_10_10_10_rev 1
+
+#define GL_UNSIGNED_INT_2_10_10_10_REV 0x8368
+#define GL_INT_2_10_10_10_REV 0x8D9F
+
+typedef void (GLAPIENTRY * PFNGLCOLORP3UIPROC) (GLenum type, GLuint color);
+typedef void (GLAPIENTRY * PFNGLCOLORP3UIVPROC) (GLenum type, const GLuint* color);
+typedef void (GLAPIENTRY * PFNGLCOLORP4UIPROC) (GLenum type, GLuint color);
+typedef void (GLAPIENTRY * PFNGLCOLORP4UIVPROC) (GLenum type, const GLuint* color);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORDP1UIPROC) (GLenum texture, GLenum type, GLuint coords);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORDP1UIVPROC) (GLenum texture, GLenum type, const GLuint* coords);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORDP2UIPROC) (GLenum texture, GLenum type, GLuint coords);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORDP2UIVPROC) (GLenum texture, GLenum type, const GLuint* coords);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORDP3UIPROC) (GLenum texture, GLenum type, GLuint coords);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORDP3UIVPROC) (GLenum texture, GLenum type, const GLuint* coords);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORDP4UIPROC) (GLenum texture, GLenum type, GLuint coords);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORDP4UIVPROC) (GLenum texture, GLenum type, const GLuint* coords);
+typedef void (GLAPIENTRY * PFNGLNORMALP3UIPROC) (GLenum type, GLuint coords);
+typedef void (GLAPIENTRY * PFNGLNORMALP3UIVPROC) (GLenum type, const GLuint* coords);
+typedef void (GLAPIENTRY * PFNGLSECONDARYCOLORP3UIPROC) (GLenum type, GLuint color);
+typedef void (GLAPIENTRY * PFNGLSECONDARYCOLORP3UIVPROC) (GLenum type, const GLuint* color);
+typedef void (GLAPIENTRY * PFNGLTEXCOORDP1UIPROC) (GLenum type, GLuint coords);
+typedef void (GLAPIENTRY * PFNGLTEXCOORDP1UIVPROC) (GLenum type, const GLuint* coords);
+typedef void (GLAPIENTRY * PFNGLTEXCOORDP2UIPROC) (GLenum type, GLuint coords);
+typedef void (GLAPIENTRY * PFNGLTEXCOORDP2UIVPROC) (GLenum type, const GLuint* coords);
+typedef void (GLAPIENTRY * PFNGLTEXCOORDP3UIPROC) (GLenum type, GLuint coords);
+typedef void (GLAPIENTRY * PFNGLTEXCOORDP3UIVPROC) (GLenum type, const GLuint* coords);
+typedef void (GLAPIENTRY * PFNGLTEXCOORDP4UIPROC) (GLenum type, GLuint coords);
+typedef void (GLAPIENTRY * PFNGLTEXCOORDP4UIVPROC) (GLenum type, const GLuint* coords);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBP1UIPROC) (GLuint index, GLenum type, GLboolean normalized, GLuint value);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBP1UIVPROC) (GLuint index, GLenum type, GLboolean normalized, const GLuint* value);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBP2UIPROC) (GLuint index, GLenum type, GLboolean normalized, GLuint value);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBP2UIVPROC) (GLuint index, GLenum type, GLboolean normalized, const GLuint* value);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBP3UIPROC) (GLuint index, GLenum type, GLboolean normalized, GLuint value);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBP3UIVPROC) (GLuint index, GLenum type, GLboolean normalized, const GLuint* value);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBP4UIPROC) (GLuint index, GLenum type, GLboolean normalized, GLuint value);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBP4UIVPROC) (GLuint index, GLenum type, GLboolean normalized, const GLuint* value);
+typedef void (GLAPIENTRY * PFNGLVERTEXP2UIPROC) (GLenum type, GLuint value);
+typedef void (GLAPIENTRY * PFNGLVERTEXP2UIVPROC) (GLenum type, const GLuint* value);
+typedef void (GLAPIENTRY * PFNGLVERTEXP3UIPROC) (GLenum type, GLuint value);
+typedef void (GLAPIENTRY * PFNGLVERTEXP3UIVPROC) (GLenum type, const GLuint* value);
+typedef void (GLAPIENTRY * PFNGLVERTEXP4UIPROC) (GLenum type, GLuint value);
+typedef void (GLAPIENTRY * PFNGLVERTEXP4UIVPROC) (GLenum type, const GLuint* value);
+
+#define glColorP3ui GLEW_GET_FUN(__glewColorP3ui)
+#define glColorP3uiv GLEW_GET_FUN(__glewColorP3uiv)
+#define glColorP4ui GLEW_GET_FUN(__glewColorP4ui)
+#define glColorP4uiv GLEW_GET_FUN(__glewColorP4uiv)
+#define glMultiTexCoordP1ui GLEW_GET_FUN(__glewMultiTexCoordP1ui)
+#define glMultiTexCoordP1uiv GLEW_GET_FUN(__glewMultiTexCoordP1uiv)
+#define glMultiTexCoordP2ui GLEW_GET_FUN(__glewMultiTexCoordP2ui)
+#define glMultiTexCoordP2uiv GLEW_GET_FUN(__glewMultiTexCoordP2uiv)
+#define glMultiTexCoordP3ui GLEW_GET_FUN(__glewMultiTexCoordP3ui)
+#define glMultiTexCoordP3uiv GLEW_GET_FUN(__glewMultiTexCoordP3uiv)
+#define glMultiTexCoordP4ui GLEW_GET_FUN(__glewMultiTexCoordP4ui)
+#define glMultiTexCoordP4uiv GLEW_GET_FUN(__glewMultiTexCoordP4uiv)
+#define glNormalP3ui GLEW_GET_FUN(__glewNormalP3ui)
+#define glNormalP3uiv GLEW_GET_FUN(__glewNormalP3uiv)
+#define glSecondaryColorP3ui GLEW_GET_FUN(__glewSecondaryColorP3ui)
+#define glSecondaryColorP3uiv GLEW_GET_FUN(__glewSecondaryColorP3uiv)
+#define glTexCoordP1ui GLEW_GET_FUN(__glewTexCoordP1ui)
+#define glTexCoordP1uiv GLEW_GET_FUN(__glewTexCoordP1uiv)
+#define glTexCoordP2ui GLEW_GET_FUN(__glewTexCoordP2ui)
+#define glTexCoordP2uiv GLEW_GET_FUN(__glewTexCoordP2uiv)
+#define glTexCoordP3ui GLEW_GET_FUN(__glewTexCoordP3ui)
+#define glTexCoordP3uiv GLEW_GET_FUN(__glewTexCoordP3uiv)
+#define glTexCoordP4ui GLEW_GET_FUN(__glewTexCoordP4ui)
+#define glTexCoordP4uiv GLEW_GET_FUN(__glewTexCoordP4uiv)
+#define glVertexAttribP1ui GLEW_GET_FUN(__glewVertexAttribP1ui)
+#define glVertexAttribP1uiv GLEW_GET_FUN(__glewVertexAttribP1uiv)
+#define glVertexAttribP2ui GLEW_GET_FUN(__glewVertexAttribP2ui)
+#define glVertexAttribP2uiv GLEW_GET_FUN(__glewVertexAttribP2uiv)
+#define glVertexAttribP3ui GLEW_GET_FUN(__glewVertexAttribP3ui)
+#define glVertexAttribP3uiv GLEW_GET_FUN(__glewVertexAttribP3uiv)
+#define glVertexAttribP4ui GLEW_GET_FUN(__glewVertexAttribP4ui)
+#define glVertexAttribP4uiv GLEW_GET_FUN(__glewVertexAttribP4uiv)
+#define glVertexP2ui GLEW_GET_FUN(__glewVertexP2ui)
+#define glVertexP2uiv GLEW_GET_FUN(__glewVertexP2uiv)
+#define glVertexP3ui GLEW_GET_FUN(__glewVertexP3ui)
+#define glVertexP3uiv GLEW_GET_FUN(__glewVertexP3uiv)
+#define glVertexP4ui GLEW_GET_FUN(__glewVertexP4ui)
+#define glVertexP4uiv GLEW_GET_FUN(__glewVertexP4uiv)
+
+#define GLEW_ARB_vertex_type_2_10_10_10_rev GLEW_GET_VAR(__GLEW_ARB_vertex_type_2_10_10_10_rev)
+
+#endif /* !GL_ARB_vertex_type_2_10_10_10_rev */
+
+/* ------------------------- GL_ARB_viewport_array ------------------------- */
+
+#if !defined(GL_ARB_viewport_array)
+#define GL_ARB_viewport_array 1
+
+#define GL_DEPTH_RANGE 0x0B70
+#define GL_VIEWPORT 0x0BA2
+#define GL_SCISSOR_BOX 0x0C10
+#define GL_SCISSOR_TEST 0x0C11
+#define GL_MAX_VIEWPORTS 0x825B
+#define GL_VIEWPORT_SUBPIXEL_BITS 0x825C
+#define GL_VIEWPORT_BOUNDS_RANGE 0x825D
+#define GL_LAYER_PROVOKING_VERTEX 0x825E
+#define GL_VIEWPORT_INDEX_PROVOKING_VERTEX 0x825F
+#define GL_UNDEFINED_VERTEX 0x8260
+#define GL_FIRST_VERTEX_CONVENTION 0x8E4D
+#define GL_LAST_VERTEX_CONVENTION 0x8E4E
+#define GL_PROVOKING_VERTEX 0x8E4F
+
+typedef void (GLAPIENTRY * PFNGLDEPTHRANGEARRAYVPROC) (GLuint first, GLsizei count, const GLclampd * v);
+typedef void (GLAPIENTRY * PFNGLDEPTHRANGEINDEXEDPROC) (GLuint index, GLclampd n, GLclampd f);
+typedef void (GLAPIENTRY * PFNGLGETDOUBLEI_VPROC) (GLenum target, GLuint index, GLdouble* data);
+typedef void (GLAPIENTRY * PFNGLGETFLOATI_VPROC) (GLenum target, GLuint index, GLfloat* data);
+typedef void (GLAPIENTRY * PFNGLSCISSORARRAYVPROC) (GLuint first, GLsizei count, const GLint * v);
+typedef void (GLAPIENTRY * PFNGLSCISSORINDEXEDPROC) (GLuint index, GLint left, GLint bottom, GLsizei width, GLsizei height);
+typedef void (GLAPIENTRY * PFNGLSCISSORINDEXEDVPROC) (GLuint index, const GLint * v);
+typedef void (GLAPIENTRY * PFNGLVIEWPORTARRAYVPROC) (GLuint first, GLsizei count, const GLfloat * v);
+typedef void (GLAPIENTRY * PFNGLVIEWPORTINDEXEDFPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat w, GLfloat h);
+typedef void (GLAPIENTRY * PFNGLVIEWPORTINDEXEDFVPROC) (GLuint index, const GLfloat * v);
+
+#define glDepthRangeArrayv GLEW_GET_FUN(__glewDepthRangeArrayv)
+#define glDepthRangeIndexed GLEW_GET_FUN(__glewDepthRangeIndexed)
+#define glGetDoublei_v GLEW_GET_FUN(__glewGetDoublei_v)
+#define glGetFloati_v GLEW_GET_FUN(__glewGetFloati_v)
+#define glScissorArrayv GLEW_GET_FUN(__glewScissorArrayv)
+#define glScissorIndexed GLEW_GET_FUN(__glewScissorIndexed)
+#define glScissorIndexedv GLEW_GET_FUN(__glewScissorIndexedv)
+#define glViewportArrayv GLEW_GET_FUN(__glewViewportArrayv)
+#define glViewportIndexedf GLEW_GET_FUN(__glewViewportIndexedf)
+#define glViewportIndexedfv GLEW_GET_FUN(__glewViewportIndexedfv)
+
+#define GLEW_ARB_viewport_array GLEW_GET_VAR(__GLEW_ARB_viewport_array)
+
+#endif /* !GL_ARB_viewport_array */
+
+/* --------------------------- GL_ARB_window_pos --------------------------- */
+
+#if !defined(GL_ARB_window_pos)
+#define GL_ARB_window_pos 1
+
+typedef void (GLAPIENTRY * PFNGLWINDOWPOS2DARBPROC) (GLdouble x, GLdouble y);
+typedef void (GLAPIENTRY * PFNGLWINDOWPOS2DVARBPROC) (const GLdouble* p);
+typedef void (GLAPIENTRY * PFNGLWINDOWPOS2FARBPROC) (GLfloat x, GLfloat y);
+typedef void (GLAPIENTRY * PFNGLWINDOWPOS2FVARBPROC) (const GLfloat* p);
+typedef void (GLAPIENTRY * PFNGLWINDOWPOS2IARBPROC) (GLint x, GLint y);
+typedef void (GLAPIENTRY * PFNGLWINDOWPOS2IVARBPROC) (const GLint* p);
+typedef void (GLAPIENTRY * PFNGLWINDOWPOS2SARBPROC) (GLshort x, GLshort y);
+typedef void (GLAPIENTRY * PFNGLWINDOWPOS2SVARBPROC) (const GLshort* p);
+typedef void (GLAPIENTRY * PFNGLWINDOWPOS3DARBPROC) (GLdouble x, GLdouble y, GLdouble z);
+typedef void (GLAPIENTRY * PFNGLWINDOWPOS3DVARBPROC) (const GLdouble* p);
+typedef void (GLAPIENTRY * PFNGLWINDOWPOS3FARBPROC) (GLfloat x, GLfloat y, GLfloat z);
+typedef void (GLAPIENTRY * PFNGLWINDOWPOS3FVARBPROC) (const GLfloat* p);
+typedef void (GLAPIENTRY * PFNGLWINDOWPOS3IARBPROC) (GLint x, GLint y, GLint z);
+typedef void (GLAPIENTRY * PFNGLWINDOWPOS3IVARBPROC) (const GLint* p);
+typedef void (GLAPIENTRY * PFNGLWINDOWPOS3SARBPROC) (GLshort x, GLshort y, GLshort z);
+typedef void (GLAPIENTRY * PFNGLWINDOWPOS3SVARBPROC) (const GLshort* p);
+
+#define glWindowPos2dARB GLEW_GET_FUN(__glewWindowPos2dARB)
+#define glWindowPos2dvARB GLEW_GET_FUN(__glewWindowPos2dvARB)
+#define glWindowPos2fARB GLEW_GET_FUN(__glewWindowPos2fARB)
+#define glWindowPos2fvARB GLEW_GET_FUN(__glewWindowPos2fvARB)
+#define glWindowPos2iARB GLEW_GET_FUN(__glewWindowPos2iARB)
+#define glWindowPos2ivARB GLEW_GET_FUN(__glewWindowPos2ivARB)
+#define glWindowPos2sARB GLEW_GET_FUN(__glewWindowPos2sARB)
+#define glWindowPos2svARB GLEW_GET_FUN(__glewWindowPos2svARB)
+#define glWindowPos3dARB GLEW_GET_FUN(__glewWindowPos3dARB)
+#define glWindowPos3dvARB GLEW_GET_FUN(__glewWindowPos3dvARB)
+#define glWindowPos3fARB GLEW_GET_FUN(__glewWindowPos3fARB)
+#define glWindowPos3fvARB GLEW_GET_FUN(__glewWindowPos3fvARB)
+#define glWindowPos3iARB GLEW_GET_FUN(__glewWindowPos3iARB)
+#define glWindowPos3ivARB GLEW_GET_FUN(__glewWindowPos3ivARB)
+#define glWindowPos3sARB GLEW_GET_FUN(__glewWindowPos3sARB)
+#define glWindowPos3svARB GLEW_GET_FUN(__glewWindowPos3svARB)
+
+#define GLEW_ARB_window_pos GLEW_GET_VAR(__GLEW_ARB_window_pos)
+
+#endif /* !GL_ARB_window_pos */
+
+/* ------------------------- GL_ATIX_point_sprites ------------------------- */
+
+#if !defined(GL_ATIX_point_sprites)
+#define GL_ATIX_point_sprites 1
+
+#define GL_TEXTURE_POINT_MODE_ATIX 0x60B0
+#define GL_TEXTURE_POINT_ONE_COORD_ATIX 0x60B1
+#define GL_TEXTURE_POINT_SPRITE_ATIX 0x60B2
+#define GL_POINT_SPRITE_CULL_MODE_ATIX 0x60B3
+#define GL_POINT_SPRITE_CULL_CENTER_ATIX 0x60B4
+#define GL_POINT_SPRITE_CULL_CLIP_ATIX 0x60B5
+
+#define GLEW_ATIX_point_sprites GLEW_GET_VAR(__GLEW_ATIX_point_sprites)
+
+#endif /* !GL_ATIX_point_sprites */
+
+/* ---------------------- GL_ATIX_texture_env_combine3 --------------------- */
+
+#if !defined(GL_ATIX_texture_env_combine3)
+#define GL_ATIX_texture_env_combine3 1
+
+#define GL_MODULATE_ADD_ATIX 0x8744
+#define GL_MODULATE_SIGNED_ADD_ATIX 0x8745
+#define GL_MODULATE_SUBTRACT_ATIX 0x8746
+
+#define GLEW_ATIX_texture_env_combine3 GLEW_GET_VAR(__GLEW_ATIX_texture_env_combine3)
+
+#endif /* !GL_ATIX_texture_env_combine3 */
+
+/* ----------------------- GL_ATIX_texture_env_route ----------------------- */
+
+#if !defined(GL_ATIX_texture_env_route)
+#define GL_ATIX_texture_env_route 1
+
+#define GL_SECONDARY_COLOR_ATIX 0x8747
+#define GL_TEXTURE_OUTPUT_RGB_ATIX 0x8748
+#define GL_TEXTURE_OUTPUT_ALPHA_ATIX 0x8749
+
+#define GLEW_ATIX_texture_env_route GLEW_GET_VAR(__GLEW_ATIX_texture_env_route)
+
+#endif /* !GL_ATIX_texture_env_route */
+
+/* ---------------- GL_ATIX_vertex_shader_output_point_size ---------------- */
+
+#if !defined(GL_ATIX_vertex_shader_output_point_size)
+#define GL_ATIX_vertex_shader_output_point_size 1
+
+#define GL_OUTPUT_POINT_SIZE_ATIX 0x610E
+
+#define GLEW_ATIX_vertex_shader_output_point_size GLEW_GET_VAR(__GLEW_ATIX_vertex_shader_output_point_size)
+
+#endif /* !GL_ATIX_vertex_shader_output_point_size */
+
+/* -------------------------- GL_ATI_draw_buffers -------------------------- */
+
+#if !defined(GL_ATI_draw_buffers)
+#define GL_ATI_draw_buffers 1
+
+#define GL_MAX_DRAW_BUFFERS_ATI 0x8824
+#define GL_DRAW_BUFFER0_ATI 0x8825
+#define GL_DRAW_BUFFER1_ATI 0x8826
+#define GL_DRAW_BUFFER2_ATI 0x8827
+#define GL_DRAW_BUFFER3_ATI 0x8828
+#define GL_DRAW_BUFFER4_ATI 0x8829
+#define GL_DRAW_BUFFER5_ATI 0x882A
+#define GL_DRAW_BUFFER6_ATI 0x882B
+#define GL_DRAW_BUFFER7_ATI 0x882C
+#define GL_DRAW_BUFFER8_ATI 0x882D
+#define GL_DRAW_BUFFER9_ATI 0x882E
+#define GL_DRAW_BUFFER10_ATI 0x882F
+#define GL_DRAW_BUFFER11_ATI 0x8830
+#define GL_DRAW_BUFFER12_ATI 0x8831
+#define GL_DRAW_BUFFER13_ATI 0x8832
+#define GL_DRAW_BUFFER14_ATI 0x8833
+#define GL_DRAW_BUFFER15_ATI 0x8834
+
+typedef void (GLAPIENTRY * PFNGLDRAWBUFFERSATIPROC) (GLsizei n, const GLenum* bufs);
+
+#define glDrawBuffersATI GLEW_GET_FUN(__glewDrawBuffersATI)
+
+#define GLEW_ATI_draw_buffers GLEW_GET_VAR(__GLEW_ATI_draw_buffers)
+
+#endif /* !GL_ATI_draw_buffers */
+
+/* -------------------------- GL_ATI_element_array ------------------------- */
+
+#if !defined(GL_ATI_element_array)
+#define GL_ATI_element_array 1
+
+#define GL_ELEMENT_ARRAY_ATI 0x8768
+#define GL_ELEMENT_ARRAY_TYPE_ATI 0x8769
+#define GL_ELEMENT_ARRAY_POINTER_ATI 0x876A
+
+typedef void (GLAPIENTRY * PFNGLDRAWELEMENTARRAYATIPROC) (GLenum mode, GLsizei count);
+typedef void (GLAPIENTRY * PFNGLDRAWRANGEELEMENTARRAYATIPROC) (GLenum mode, GLuint start, GLuint end, GLsizei count);
+typedef void (GLAPIENTRY * PFNGLELEMENTPOINTERATIPROC) (GLenum type, const void* pointer);
+
+#define glDrawElementArrayATI GLEW_GET_FUN(__glewDrawElementArrayATI)
+#define glDrawRangeElementArrayATI GLEW_GET_FUN(__glewDrawRangeElementArrayATI)
+#define glElementPointerATI GLEW_GET_FUN(__glewElementPointerATI)
+
+#define GLEW_ATI_element_array GLEW_GET_VAR(__GLEW_ATI_element_array)
+
+#endif /* !GL_ATI_element_array */
+
+/* ------------------------- GL_ATI_envmap_bumpmap ------------------------- */
+
+#if !defined(GL_ATI_envmap_bumpmap)
+#define GL_ATI_envmap_bumpmap 1
+
+#define GL_BUMP_ROT_MATRIX_ATI 0x8775
+#define GL_BUMP_ROT_MATRIX_SIZE_ATI 0x8776
+#define GL_BUMP_NUM_TEX_UNITS_ATI 0x8777
+#define GL_BUMP_TEX_UNITS_ATI 0x8778
+#define GL_DUDV_ATI 0x8779
+#define GL_DU8DV8_ATI 0x877A
+#define GL_BUMP_ENVMAP_ATI 0x877B
+#define GL_BUMP_TARGET_ATI 0x877C
+
+typedef void (GLAPIENTRY * PFNGLGETTEXBUMPPARAMETERFVATIPROC) (GLenum pname, GLfloat *param);
+typedef void (GLAPIENTRY * PFNGLGETTEXBUMPPARAMETERIVATIPROC) (GLenum pname, GLint *param);
+typedef void (GLAPIENTRY * PFNGLTEXBUMPPARAMETERFVATIPROC) (GLenum pname, GLfloat *param);
+typedef void (GLAPIENTRY * PFNGLTEXBUMPPARAMETERIVATIPROC) (GLenum pname, GLint *param);
+
+#define glGetTexBumpParameterfvATI GLEW_GET_FUN(__glewGetTexBumpParameterfvATI)
+#define glGetTexBumpParameterivATI GLEW_GET_FUN(__glewGetTexBumpParameterivATI)
+#define glTexBumpParameterfvATI GLEW_GET_FUN(__glewTexBumpParameterfvATI)
+#define glTexBumpParameterivATI GLEW_GET_FUN(__glewTexBumpParameterivATI)
+
+#define GLEW_ATI_envmap_bumpmap GLEW_GET_VAR(__GLEW_ATI_envmap_bumpmap)
+
+#endif /* !GL_ATI_envmap_bumpmap */
+
+/* ------------------------- GL_ATI_fragment_shader ------------------------ */
+
+#if !defined(GL_ATI_fragment_shader)
+#define GL_ATI_fragment_shader 1
+
+#define GL_RED_BIT_ATI 0x00000001
+#define GL_2X_BIT_ATI 0x00000001
+#define GL_4X_BIT_ATI 0x00000002
+#define GL_GREEN_BIT_ATI 0x00000002
+#define GL_COMP_BIT_ATI 0x00000002
+#define GL_BLUE_BIT_ATI 0x00000004
+#define GL_8X_BIT_ATI 0x00000004
+#define GL_NEGATE_BIT_ATI 0x00000004
+#define GL_BIAS_BIT_ATI 0x00000008
+#define GL_HALF_BIT_ATI 0x00000008
+#define GL_QUARTER_BIT_ATI 0x00000010
+#define GL_EIGHTH_BIT_ATI 0x00000020
+#define GL_SATURATE_BIT_ATI 0x00000040
+#define GL_FRAGMENT_SHADER_ATI 0x8920
+#define GL_REG_0_ATI 0x8921
+#define GL_REG_1_ATI 0x8922
+#define GL_REG_2_ATI 0x8923
+#define GL_REG_3_ATI 0x8924
+#define GL_REG_4_ATI 0x8925
+#define GL_REG_5_ATI 0x8926
+#define GL_CON_0_ATI 0x8941
+#define GL_CON_1_ATI 0x8942
+#define GL_CON_2_ATI 0x8943
+#define GL_CON_3_ATI 0x8944
+#define GL_CON_4_ATI 0x8945
+#define GL_CON_5_ATI 0x8946
+#define GL_CON_6_ATI 0x8947
+#define GL_CON_7_ATI 0x8948
+#define GL_MOV_ATI 0x8961
+#define GL_ADD_ATI 0x8963
+#define GL_MUL_ATI 0x8964
+#define GL_SUB_ATI 0x8965
+#define GL_DOT3_ATI 0x8966
+#define GL_DOT4_ATI 0x8967
+#define GL_MAD_ATI 0x8968
+#define GL_LERP_ATI 0x8969
+#define GL_CND_ATI 0x896A
+#define GL_CND0_ATI 0x896B
+#define GL_DOT2_ADD_ATI 0x896C
+#define GL_SECONDARY_INTERPOLATOR_ATI 0x896D
+#define GL_NUM_FRAGMENT_REGISTERS_ATI 0x896E
+#define GL_NUM_FRAGMENT_CONSTANTS_ATI 0x896F
+#define GL_NUM_PASSES_ATI 0x8970
+#define GL_NUM_INSTRUCTIONS_PER_PASS_ATI 0x8971
+#define GL_NUM_INSTRUCTIONS_TOTAL_ATI 0x8972
+#define GL_NUM_INPUT_INTERPOLATOR_COMPONENTS_ATI 0x8973
+#define GL_NUM_LOOPBACK_COMPONENTS_ATI 0x8974
+#define GL_COLOR_ALPHA_PAIRING_ATI 0x8975
+#define GL_SWIZZLE_STR_ATI 0x8976
+#define GL_SWIZZLE_STQ_ATI 0x8977
+#define GL_SWIZZLE_STR_DR_ATI 0x8978
+#define GL_SWIZZLE_STQ_DQ_ATI 0x8979
+#define GL_SWIZZLE_STRQ_ATI 0x897A
+#define GL_SWIZZLE_STRQ_DQ_ATI 0x897B
+
+typedef void (GLAPIENTRY * PFNGLALPHAFRAGMENTOP1ATIPROC) (GLenum op, GLuint dst, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod);
+typedef void (GLAPIENTRY * PFNGLALPHAFRAGMENTOP2ATIPROC) (GLenum op, GLuint dst, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, GLuint arg2Mod);
+typedef void (GLAPIENTRY * PFNGLALPHAFRAGMENTOP3ATIPROC) (GLenum op, GLuint dst, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, GLuint arg2Mod, GLuint arg3, GLuint arg3Rep, GLuint arg3Mod);
+typedef void (GLAPIENTRY * PFNGLBEGINFRAGMENTSHADERATIPROC) (void);
+typedef void (GLAPIENTRY * PFNGLBINDFRAGMENTSHADERATIPROC) (GLuint id);
+typedef void (GLAPIENTRY * PFNGLCOLORFRAGMENTOP1ATIPROC) (GLenum op, GLuint dst, GLuint dstMask, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod);
+typedef void (GLAPIENTRY * PFNGLCOLORFRAGMENTOP2ATIPROC) (GLenum op, GLuint dst, GLuint dstMask, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, GLuint arg2Mod);
+typedef void (GLAPIENTRY * PFNGLCOLORFRAGMENTOP3ATIPROC) (GLenum op, GLuint dst, GLuint dstMask, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, GLuint arg2Mod, GLuint arg3, GLuint arg3Rep, GLuint arg3Mod);
+typedef void (GLAPIENTRY * PFNGLDELETEFRAGMENTSHADERATIPROC) (GLuint id);
+typedef void (GLAPIENTRY * PFNGLENDFRAGMENTSHADERATIPROC) (void);
+typedef GLuint (GLAPIENTRY * PFNGLGENFRAGMENTSHADERSATIPROC) (GLuint range);
+typedef void (GLAPIENTRY * PFNGLPASSTEXCOORDATIPROC) (GLuint dst, GLuint coord, GLenum swizzle);
+typedef void (GLAPIENTRY * PFNGLSAMPLEMAPATIPROC) (GLuint dst, GLuint interp, GLenum swizzle);
+typedef void (GLAPIENTRY * PFNGLSETFRAGMENTSHADERCONSTANTATIPROC) (GLuint dst, const GLfloat* value);
+
+#define glAlphaFragmentOp1ATI GLEW_GET_FUN(__glewAlphaFragmentOp1ATI)
+#define glAlphaFragmentOp2ATI GLEW_GET_FUN(__glewAlphaFragmentOp2ATI)
+#define glAlphaFragmentOp3ATI GLEW_GET_FUN(__glewAlphaFragmentOp3ATI)
+#define glBeginFragmentShaderATI GLEW_GET_FUN(__glewBeginFragmentShaderATI)
+#define glBindFragmentShaderATI GLEW_GET_FUN(__glewBindFragmentShaderATI)
+#define glColorFragmentOp1ATI GLEW_GET_FUN(__glewColorFragmentOp1ATI)
+#define glColorFragmentOp2ATI GLEW_GET_FUN(__glewColorFragmentOp2ATI)
+#define glColorFragmentOp3ATI GLEW_GET_FUN(__glewColorFragmentOp3ATI)
+#define glDeleteFragmentShaderATI GLEW_GET_FUN(__glewDeleteFragmentShaderATI)
+#define glEndFragmentShaderATI GLEW_GET_FUN(__glewEndFragmentShaderATI)
+#define glGenFragmentShadersATI GLEW_GET_FUN(__glewGenFragmentShadersATI)
+#define glPassTexCoordATI GLEW_GET_FUN(__glewPassTexCoordATI)
+#define glSampleMapATI GLEW_GET_FUN(__glewSampleMapATI)
+#define glSetFragmentShaderConstantATI GLEW_GET_FUN(__glewSetFragmentShaderConstantATI)
+
+#define GLEW_ATI_fragment_shader GLEW_GET_VAR(__GLEW_ATI_fragment_shader)
+
+#endif /* !GL_ATI_fragment_shader */
+
+/* ------------------------ GL_ATI_map_object_buffer ----------------------- */
+
+#if !defined(GL_ATI_map_object_buffer)
+#define GL_ATI_map_object_buffer 1
+
+typedef void* (GLAPIENTRY * PFNGLMAPOBJECTBUFFERATIPROC) (GLuint buffer);
+typedef void (GLAPIENTRY * PFNGLUNMAPOBJECTBUFFERATIPROC) (GLuint buffer);
+
+#define glMapObjectBufferATI GLEW_GET_FUN(__glewMapObjectBufferATI)
+#define glUnmapObjectBufferATI GLEW_GET_FUN(__glewUnmapObjectBufferATI)
+
+#define GLEW_ATI_map_object_buffer GLEW_GET_VAR(__GLEW_ATI_map_object_buffer)
+
+#endif /* !GL_ATI_map_object_buffer */
+
+/* ----------------------------- GL_ATI_meminfo ---------------------------- */
+
+#if !defined(GL_ATI_meminfo)
+#define GL_ATI_meminfo 1
+
+#define GL_VBO_FREE_MEMORY_ATI 0x87FB
+#define GL_TEXTURE_FREE_MEMORY_ATI 0x87FC
+#define GL_RENDERBUFFER_FREE_MEMORY_ATI 0x87FD
+
+#define GLEW_ATI_meminfo GLEW_GET_VAR(__GLEW_ATI_meminfo)
+
+#endif /* !GL_ATI_meminfo */
+
+/* -------------------------- GL_ATI_pn_triangles -------------------------- */
+
+#if !defined(GL_ATI_pn_triangles)
+#define GL_ATI_pn_triangles 1
+
+#define GL_PN_TRIANGLES_ATI 0x87F0
+#define GL_MAX_PN_TRIANGLES_TESSELATION_LEVEL_ATI 0x87F1
+#define GL_PN_TRIANGLES_POINT_MODE_ATI 0x87F2
+#define GL_PN_TRIANGLES_NORMAL_MODE_ATI 0x87F3
+#define GL_PN_TRIANGLES_TESSELATION_LEVEL_ATI 0x87F4
+#define GL_PN_TRIANGLES_POINT_MODE_LINEAR_ATI 0x87F5
+#define GL_PN_TRIANGLES_POINT_MODE_CUBIC_ATI 0x87F6
+#define GL_PN_TRIANGLES_NORMAL_MODE_LINEAR_ATI 0x87F7
+#define GL_PN_TRIANGLES_NORMAL_MODE_QUADRATIC_ATI 0x87F8
+
+typedef void (GLAPIENTRY * PFNGLPNTRIANGLESFATIPROC) (GLenum pname, GLfloat param);
+typedef void (GLAPIENTRY * PFNGLPNTRIANGLESIATIPROC) (GLenum pname, GLint param);
+
+#define glPNTrianglesfATI GLEW_GET_FUN(__glewPNTrianglesfATI)
+#define glPNTrianglesiATI GLEW_GET_FUN(__glewPNTrianglesiATI)
+
+#define GLEW_ATI_pn_triangles GLEW_GET_VAR(__GLEW_ATI_pn_triangles)
+
+#endif /* !GL_ATI_pn_triangles */
+
+/* ------------------------ GL_ATI_separate_stencil ------------------------ */
+
+#if !defined(GL_ATI_separate_stencil)
+#define GL_ATI_separate_stencil 1
+
+#define GL_STENCIL_BACK_FUNC_ATI 0x8800
+#define GL_STENCIL_BACK_FAIL_ATI 0x8801
+#define GL_STENCIL_BACK_PASS_DEPTH_FAIL_ATI 0x8802
+#define GL_STENCIL_BACK_PASS_DEPTH_PASS_ATI 0x8803
+
+typedef void (GLAPIENTRY * PFNGLSTENCILFUNCSEPARATEATIPROC) (GLenum frontfunc, GLenum backfunc, GLint ref, GLuint mask);
+typedef void (GLAPIENTRY * PFNGLSTENCILOPSEPARATEATIPROC) (GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass);
+
+#define glStencilFuncSeparateATI GLEW_GET_FUN(__glewStencilFuncSeparateATI)
+#define glStencilOpSeparateATI GLEW_GET_FUN(__glewStencilOpSeparateATI)
+
+#define GLEW_ATI_separate_stencil GLEW_GET_VAR(__GLEW_ATI_separate_stencil)
+
+#endif /* !GL_ATI_separate_stencil */
+
+/* ----------------------- GL_ATI_shader_texture_lod ----------------------- */
+
+#if !defined(GL_ATI_shader_texture_lod)
+#define GL_ATI_shader_texture_lod 1
+
+#define GLEW_ATI_shader_texture_lod GLEW_GET_VAR(__GLEW_ATI_shader_texture_lod)
+
+#endif /* !GL_ATI_shader_texture_lod */
+
+/* ---------------------- GL_ATI_text_fragment_shader ---------------------- */
+
+#if !defined(GL_ATI_text_fragment_shader)
+#define GL_ATI_text_fragment_shader 1
+
+#define GL_TEXT_FRAGMENT_SHADER_ATI 0x8200
+
+#define GLEW_ATI_text_fragment_shader GLEW_GET_VAR(__GLEW_ATI_text_fragment_shader)
+
+#endif /* !GL_ATI_text_fragment_shader */
+
+/* --------------------- GL_ATI_texture_compression_3dc -------------------- */
+
+#if !defined(GL_ATI_texture_compression_3dc)
+#define GL_ATI_texture_compression_3dc 1
+
+#define GL_COMPRESSED_LUMINANCE_ALPHA_3DC_ATI 0x8837
+
+#define GLEW_ATI_texture_compression_3dc GLEW_GET_VAR(__GLEW_ATI_texture_compression_3dc)
+
+#endif /* !GL_ATI_texture_compression_3dc */
+
+/* ---------------------- GL_ATI_texture_env_combine3 ---------------------- */
+
+#if !defined(GL_ATI_texture_env_combine3)
+#define GL_ATI_texture_env_combine3 1
+
+#define GL_MODULATE_ADD_ATI 0x8744
+#define GL_MODULATE_SIGNED_ADD_ATI 0x8745
+#define GL_MODULATE_SUBTRACT_ATI 0x8746
+
+#define GLEW_ATI_texture_env_combine3 GLEW_GET_VAR(__GLEW_ATI_texture_env_combine3)
+
+#endif /* !GL_ATI_texture_env_combine3 */
+
+/* -------------------------- GL_ATI_texture_float ------------------------- */
+
+#if !defined(GL_ATI_texture_float)
+#define GL_ATI_texture_float 1
+
+#define GL_RGBA_FLOAT32_ATI 0x8814
+#define GL_RGB_FLOAT32_ATI 0x8815
+#define GL_ALPHA_FLOAT32_ATI 0x8816
+#define GL_INTENSITY_FLOAT32_ATI 0x8817
+#define GL_LUMINANCE_FLOAT32_ATI 0x8818
+#define GL_LUMINANCE_ALPHA_FLOAT32_ATI 0x8819
+#define GL_RGBA_FLOAT16_ATI 0x881A
+#define GL_RGB_FLOAT16_ATI 0x881B
+#define GL_ALPHA_FLOAT16_ATI 0x881C
+#define GL_INTENSITY_FLOAT16_ATI 0x881D
+#define GL_LUMINANCE_FLOAT16_ATI 0x881E
+#define GL_LUMINANCE_ALPHA_FLOAT16_ATI 0x881F
+
+#define GLEW_ATI_texture_float GLEW_GET_VAR(__GLEW_ATI_texture_float)
+
+#endif /* !GL_ATI_texture_float */
+
+/* ----------------------- GL_ATI_texture_mirror_once ---------------------- */
+
+#if !defined(GL_ATI_texture_mirror_once)
+#define GL_ATI_texture_mirror_once 1
+
+#define GL_MIRROR_CLAMP_ATI 0x8742
+#define GL_MIRROR_CLAMP_TO_EDGE_ATI 0x8743
+
+#define GLEW_ATI_texture_mirror_once GLEW_GET_VAR(__GLEW_ATI_texture_mirror_once)
+
+#endif /* !GL_ATI_texture_mirror_once */
+
+/* ----------------------- GL_ATI_vertex_array_object ---------------------- */
+
+#if !defined(GL_ATI_vertex_array_object)
+#define GL_ATI_vertex_array_object 1
+
+#define GL_STATIC_ATI 0x8760
+#define GL_DYNAMIC_ATI 0x8761
+#define GL_PRESERVE_ATI 0x8762
+#define GL_DISCARD_ATI 0x8763
+#define GL_OBJECT_BUFFER_SIZE_ATI 0x8764
+#define GL_OBJECT_BUFFER_USAGE_ATI 0x8765
+#define GL_ARRAY_OBJECT_BUFFER_ATI 0x8766
+#define GL_ARRAY_OBJECT_OFFSET_ATI 0x8767
+
+typedef void (GLAPIENTRY * PFNGLARRAYOBJECTATIPROC) (GLenum array, GLint size, GLenum type, GLsizei stride, GLuint buffer, GLuint offset);
+typedef void (GLAPIENTRY * PFNGLFREEOBJECTBUFFERATIPROC) (GLuint buffer);
+typedef void (GLAPIENTRY * PFNGLGETARRAYOBJECTFVATIPROC) (GLenum array, GLenum pname, GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLGETARRAYOBJECTIVATIPROC) (GLenum array, GLenum pname, GLint* params);
+typedef void (GLAPIENTRY * PFNGLGETOBJECTBUFFERFVATIPROC) (GLuint buffer, GLenum pname, GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLGETOBJECTBUFFERIVATIPROC) (GLuint buffer, GLenum pname, GLint* params);
+typedef void (GLAPIENTRY * PFNGLGETVARIANTARRAYOBJECTFVATIPROC) (GLuint id, GLenum pname, GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLGETVARIANTARRAYOBJECTIVATIPROC) (GLuint id, GLenum pname, GLint* params);
+typedef GLboolean (GLAPIENTRY * PFNGLISOBJECTBUFFERATIPROC) (GLuint buffer);
+typedef GLuint (GLAPIENTRY * PFNGLNEWOBJECTBUFFERATIPROC) (GLsizei size, const void* pointer, GLenum usage);
+typedef void (GLAPIENTRY * PFNGLUPDATEOBJECTBUFFERATIPROC) (GLuint buffer, GLuint offset, GLsizei size, const void* pointer, GLenum preserve);
+typedef void (GLAPIENTRY * PFNGLVARIANTARRAYOBJECTATIPROC) (GLuint id, GLenum type, GLsizei stride, GLuint buffer, GLuint offset);
+
+#define glArrayObjectATI GLEW_GET_FUN(__glewArrayObjectATI)
+#define glFreeObjectBufferATI GLEW_GET_FUN(__glewFreeObjectBufferATI)
+#define glGetArrayObjectfvATI GLEW_GET_FUN(__glewGetArrayObjectfvATI)
+#define glGetArrayObjectivATI GLEW_GET_FUN(__glewGetArrayObjectivATI)
+#define glGetObjectBufferfvATI GLEW_GET_FUN(__glewGetObjectBufferfvATI)
+#define glGetObjectBufferivATI GLEW_GET_FUN(__glewGetObjectBufferivATI)
+#define glGetVariantArrayObjectfvATI GLEW_GET_FUN(__glewGetVariantArrayObjectfvATI)
+#define glGetVariantArrayObjectivATI GLEW_GET_FUN(__glewGetVariantArrayObjectivATI)
+#define glIsObjectBufferATI GLEW_GET_FUN(__glewIsObjectBufferATI)
+#define glNewObjectBufferATI GLEW_GET_FUN(__glewNewObjectBufferATI)
+#define glUpdateObjectBufferATI GLEW_GET_FUN(__glewUpdateObjectBufferATI)
+#define glVariantArrayObjectATI GLEW_GET_FUN(__glewVariantArrayObjectATI)
+
+#define GLEW_ATI_vertex_array_object GLEW_GET_VAR(__GLEW_ATI_vertex_array_object)
+
+#endif /* !GL_ATI_vertex_array_object */
+
+/* ------------------- GL_ATI_vertex_attrib_array_object ------------------- */
+
+#if !defined(GL_ATI_vertex_attrib_array_object)
+#define GL_ATI_vertex_attrib_array_object 1
+
+typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBARRAYOBJECTFVATIPROC) (GLuint index, GLenum pname, GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBARRAYOBJECTIVATIPROC) (GLuint index, GLenum pname, GLint* params);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBARRAYOBJECTATIPROC) (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, GLuint buffer, GLuint offset);
+
+#define glGetVertexAttribArrayObjectfvATI GLEW_GET_FUN(__glewGetVertexAttribArrayObjectfvATI)
+#define glGetVertexAttribArrayObjectivATI GLEW_GET_FUN(__glewGetVertexAttribArrayObjectivATI)
+#define glVertexAttribArrayObjectATI GLEW_GET_FUN(__glewVertexAttribArrayObjectATI)
+
+#define GLEW_ATI_vertex_attrib_array_object GLEW_GET_VAR(__GLEW_ATI_vertex_attrib_array_object)
+
+#endif /* !GL_ATI_vertex_attrib_array_object */
+
+/* ------------------------- GL_ATI_vertex_streams ------------------------- */
+
+#if !defined(GL_ATI_vertex_streams)
+#define GL_ATI_vertex_streams 1
+
+#define GL_MAX_VERTEX_STREAMS_ATI 0x876B
+#define GL_VERTEX_SOURCE_ATI 0x876C
+#define GL_VERTEX_STREAM0_ATI 0x876D
+#define GL_VERTEX_STREAM1_ATI 0x876E
+#define GL_VERTEX_STREAM2_ATI 0x876F
+#define GL_VERTEX_STREAM3_ATI 0x8770
+#define GL_VERTEX_STREAM4_ATI 0x8771
+#define GL_VERTEX_STREAM5_ATI 0x8772
+#define GL_VERTEX_STREAM6_ATI 0x8773
+#define GL_VERTEX_STREAM7_ATI 0x8774
+
+typedef void (GLAPIENTRY * PFNGLCLIENTACTIVEVERTEXSTREAMATIPROC) (GLenum stream);
+typedef void (GLAPIENTRY * PFNGLNORMALSTREAM3BATIPROC) (GLenum stream, GLbyte x, GLbyte y, GLbyte z);
+typedef void (GLAPIENTRY * PFNGLNORMALSTREAM3BVATIPROC) (GLenum stream, const GLbyte *v);
+typedef void (GLAPIENTRY * PFNGLNORMALSTREAM3DATIPROC) (GLenum stream, GLdouble x, GLdouble y, GLdouble z);
+typedef void (GLAPIENTRY * PFNGLNORMALSTREAM3DVATIPROC) (GLenum stream, const GLdouble *v);
+typedef void (GLAPIENTRY * PFNGLNORMALSTREAM3FATIPROC) (GLenum stream, GLfloat x, GLfloat y, GLfloat z);
+typedef void (GLAPIENTRY * PFNGLNORMALSTREAM3FVATIPROC) (GLenum stream, const GLfloat *v);
+typedef void (GLAPIENTRY * PFNGLNORMALSTREAM3IATIPROC) (GLenum stream, GLint x, GLint y, GLint z);
+typedef void (GLAPIENTRY * PFNGLNORMALSTREAM3IVATIPROC) (GLenum stream, const GLint *v);
+typedef void (GLAPIENTRY * PFNGLNORMALSTREAM3SATIPROC) (GLenum stream, GLshort x, GLshort y, GLshort z);
+typedef void (GLAPIENTRY * PFNGLNORMALSTREAM3SVATIPROC) (GLenum stream, const GLshort *v);
+typedef void (GLAPIENTRY * PFNGLVERTEXBLENDENVFATIPROC) (GLenum pname, GLfloat param);
+typedef void (GLAPIENTRY * PFNGLVERTEXBLENDENVIATIPROC) (GLenum pname, GLint param);
+typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM2DATIPROC) (GLenum stream, GLdouble x, GLdouble y);
+typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM2DVATIPROC) (GLenum stream, const GLdouble *v);
+typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM2FATIPROC) (GLenum stream, GLfloat x, GLfloat y);
+typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM2FVATIPROC) (GLenum stream, const GLfloat *v);
+typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM2IATIPROC) (GLenum stream, GLint x, GLint y);
+typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM2IVATIPROC) (GLenum stream, const GLint *v);
+typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM2SATIPROC) (GLenum stream, GLshort x, GLshort y);
+typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM2SVATIPROC) (GLenum stream, const GLshort *v);
+typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM3DATIPROC) (GLenum stream, GLdouble x, GLdouble y, GLdouble z);
+typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM3DVATIPROC) (GLenum stream, const GLdouble *v);
+typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM3FATIPROC) (GLenum stream, GLfloat x, GLfloat y, GLfloat z);
+typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM3FVATIPROC) (GLenum stream, const GLfloat *v);
+typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM3IATIPROC) (GLenum stream, GLint x, GLint y, GLint z);
+typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM3IVATIPROC) (GLenum stream, const GLint *v);
+typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM3SATIPROC) (GLenum stream, GLshort x, GLshort y, GLshort z);
+typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM3SVATIPROC) (GLenum stream, const GLshort *v);
+typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM4DATIPROC) (GLenum stream, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM4DVATIPROC) (GLenum stream, const GLdouble *v);
+typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM4FATIPROC) (GLenum stream, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM4FVATIPROC) (GLenum stream, const GLfloat *v);
+typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM4IATIPROC) (GLenum stream, GLint x, GLint y, GLint z, GLint w);
+typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM4IVATIPROC) (GLenum stream, const GLint *v);
+typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM4SATIPROC) (GLenum stream, GLshort x, GLshort y, GLshort z, GLshort w);
+typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM4SVATIPROC) (GLenum stream, const GLshort *v);
+
+#define glClientActiveVertexStreamATI GLEW_GET_FUN(__glewClientActiveVertexStreamATI)
+#define glNormalStream3bATI GLEW_GET_FUN(__glewNormalStream3bATI)
+#define glNormalStream3bvATI GLEW_GET_FUN(__glewNormalStream3bvATI)
+#define glNormalStream3dATI GLEW_GET_FUN(__glewNormalStream3dATI)
+#define glNormalStream3dvATI GLEW_GET_FUN(__glewNormalStream3dvATI)
+#define glNormalStream3fATI GLEW_GET_FUN(__glewNormalStream3fATI)
+#define glNormalStream3fvATI GLEW_GET_FUN(__glewNormalStream3fvATI)
+#define glNormalStream3iATI GLEW_GET_FUN(__glewNormalStream3iATI)
+#define glNormalStream3ivATI GLEW_GET_FUN(__glewNormalStream3ivATI)
+#define glNormalStream3sATI GLEW_GET_FUN(__glewNormalStream3sATI)
+#define glNormalStream3svATI GLEW_GET_FUN(__glewNormalStream3svATI)
+#define glVertexBlendEnvfATI GLEW_GET_FUN(__glewVertexBlendEnvfATI)
+#define glVertexBlendEnviATI GLEW_GET_FUN(__glewVertexBlendEnviATI)
+#define glVertexStream2dATI GLEW_GET_FUN(__glewVertexStream2dATI)
+#define glVertexStream2dvATI GLEW_GET_FUN(__glewVertexStream2dvATI)
+#define glVertexStream2fATI GLEW_GET_FUN(__glewVertexStream2fATI)
+#define glVertexStream2fvATI GLEW_GET_FUN(__glewVertexStream2fvATI)
+#define glVertexStream2iATI GLEW_GET_FUN(__glewVertexStream2iATI)
+#define glVertexStream2ivATI GLEW_GET_FUN(__glewVertexStream2ivATI)
+#define glVertexStream2sATI GLEW_GET_FUN(__glewVertexStream2sATI)
+#define glVertexStream2svATI GLEW_GET_FUN(__glewVertexStream2svATI)
+#define glVertexStream3dATI GLEW_GET_FUN(__glewVertexStream3dATI)
+#define glVertexStream3dvATI GLEW_GET_FUN(__glewVertexStream3dvATI)
+#define glVertexStream3fATI GLEW_GET_FUN(__glewVertexStream3fATI)
+#define glVertexStream3fvATI GLEW_GET_FUN(__glewVertexStream3fvATI)
+#define glVertexStream3iATI GLEW_GET_FUN(__glewVertexStream3iATI)
+#define glVertexStream3ivATI GLEW_GET_FUN(__glewVertexStream3ivATI)
+#define glVertexStream3sATI GLEW_GET_FUN(__glewVertexStream3sATI)
+#define glVertexStream3svATI GLEW_GET_FUN(__glewVertexStream3svATI)
+#define glVertexStream4dATI GLEW_GET_FUN(__glewVertexStream4dATI)
+#define glVertexStream4dvATI GLEW_GET_FUN(__glewVertexStream4dvATI)
+#define glVertexStream4fATI GLEW_GET_FUN(__glewVertexStream4fATI)
+#define glVertexStream4fvATI GLEW_GET_FUN(__glewVertexStream4fvATI)
+#define glVertexStream4iATI GLEW_GET_FUN(__glewVertexStream4iATI)
+#define glVertexStream4ivATI GLEW_GET_FUN(__glewVertexStream4ivATI)
+#define glVertexStream4sATI GLEW_GET_FUN(__glewVertexStream4sATI)
+#define glVertexStream4svATI GLEW_GET_FUN(__glewVertexStream4svATI)
+
+#define GLEW_ATI_vertex_streams GLEW_GET_VAR(__GLEW_ATI_vertex_streams)
+
+#endif /* !GL_ATI_vertex_streams */
+
+/* --------------------------- GL_EXT_422_pixels --------------------------- */
+
+#if !defined(GL_EXT_422_pixels)
+#define GL_EXT_422_pixels 1
+
+#define GL_422_EXT 0x80CC
+#define GL_422_REV_EXT 0x80CD
+#define GL_422_AVERAGE_EXT 0x80CE
+#define GL_422_REV_AVERAGE_EXT 0x80CF
+
+#define GLEW_EXT_422_pixels GLEW_GET_VAR(__GLEW_EXT_422_pixels)
+
+#endif /* !GL_EXT_422_pixels */
+
+/* ---------------------------- GL_EXT_Cg_shader --------------------------- */
+
+#if !defined(GL_EXT_Cg_shader)
+#define GL_EXT_Cg_shader 1
+
+#define GL_CG_VERTEX_SHADER_EXT 0x890E
+#define GL_CG_FRAGMENT_SHADER_EXT 0x890F
+
+#define GLEW_EXT_Cg_shader GLEW_GET_VAR(__GLEW_EXT_Cg_shader)
+
+#endif /* !GL_EXT_Cg_shader */
+
+/* ------------------------------ GL_EXT_abgr ------------------------------ */
+
+#if !defined(GL_EXT_abgr)
+#define GL_EXT_abgr 1
+
+#define GL_ABGR_EXT 0x8000
+
+#define GLEW_EXT_abgr GLEW_GET_VAR(__GLEW_EXT_abgr)
+
+#endif /* !GL_EXT_abgr */
+
+/* ------------------------------ GL_EXT_bgra ------------------------------ */
+
+#if !defined(GL_EXT_bgra)
+#define GL_EXT_bgra 1
+
+#define GL_BGR_EXT 0x80E0
+#define GL_BGRA_EXT 0x80E1
+
+#define GLEW_EXT_bgra GLEW_GET_VAR(__GLEW_EXT_bgra)
+
+#endif /* !GL_EXT_bgra */
+
+/* ------------------------ GL_EXT_bindable_uniform ------------------------ */
+
+#if !defined(GL_EXT_bindable_uniform)
+#define GL_EXT_bindable_uniform 1
+
+#define GL_MAX_VERTEX_BINDABLE_UNIFORMS_EXT 0x8DE2
+#define GL_MAX_FRAGMENT_BINDABLE_UNIFORMS_EXT 0x8DE3
+#define GL_MAX_GEOMETRY_BINDABLE_UNIFORMS_EXT 0x8DE4
+#define GL_MAX_BINDABLE_UNIFORM_SIZE_EXT 0x8DED
+#define GL_UNIFORM_BUFFER_EXT 0x8DEE
+#define GL_UNIFORM_BUFFER_BINDING_EXT 0x8DEF
+
+typedef GLint (GLAPIENTRY * PFNGLGETUNIFORMBUFFERSIZEEXTPROC) (GLuint program, GLint location);
+typedef GLintptr (GLAPIENTRY * PFNGLGETUNIFORMOFFSETEXTPROC) (GLuint program, GLint location);
+typedef void (GLAPIENTRY * PFNGLUNIFORMBUFFEREXTPROC) (GLuint program, GLint location, GLuint buffer);
+
+#define glGetUniformBufferSizeEXT GLEW_GET_FUN(__glewGetUniformBufferSizeEXT)
+#define glGetUniformOffsetEXT GLEW_GET_FUN(__glewGetUniformOffsetEXT)
+#define glUniformBufferEXT GLEW_GET_FUN(__glewUniformBufferEXT)
+
+#define GLEW_EXT_bindable_uniform GLEW_GET_VAR(__GLEW_EXT_bindable_uniform)
+
+#endif /* !GL_EXT_bindable_uniform */
+
+/* --------------------------- GL_EXT_blend_color -------------------------- */
+
+#if !defined(GL_EXT_blend_color)
+#define GL_EXT_blend_color 1
+
+#define GL_CONSTANT_COLOR_EXT 0x8001
+#define GL_ONE_MINUS_CONSTANT_COLOR_EXT 0x8002
+#define GL_CONSTANT_ALPHA_EXT 0x8003
+#define GL_ONE_MINUS_CONSTANT_ALPHA_EXT 0x8004
+#define GL_BLEND_COLOR_EXT 0x8005
+
+typedef void (GLAPIENTRY * PFNGLBLENDCOLOREXTPROC) (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
+
+#define glBlendColorEXT GLEW_GET_FUN(__glewBlendColorEXT)
+
+#define GLEW_EXT_blend_color GLEW_GET_VAR(__GLEW_EXT_blend_color)
+
+#endif /* !GL_EXT_blend_color */
+
+/* --------------------- GL_EXT_blend_equation_separate -------------------- */
+
+#if !defined(GL_EXT_blend_equation_separate)
+#define GL_EXT_blend_equation_separate 1
+
+#define GL_BLEND_EQUATION_RGB_EXT 0x8009
+#define GL_BLEND_EQUATION_ALPHA_EXT 0x883D
+
+typedef void (GLAPIENTRY * PFNGLBLENDEQUATIONSEPARATEEXTPROC) (GLenum modeRGB, GLenum modeAlpha);
+
+#define glBlendEquationSeparateEXT GLEW_GET_FUN(__glewBlendEquationSeparateEXT)
+
+#define GLEW_EXT_blend_equation_separate GLEW_GET_VAR(__GLEW_EXT_blend_equation_separate)
+
+#endif /* !GL_EXT_blend_equation_separate */
+
+/* ----------------------- GL_EXT_blend_func_separate ---------------------- */
+
+#if !defined(GL_EXT_blend_func_separate)
+#define GL_EXT_blend_func_separate 1
+
+#define GL_BLEND_DST_RGB_EXT 0x80C8
+#define GL_BLEND_SRC_RGB_EXT 0x80C9
+#define GL_BLEND_DST_ALPHA_EXT 0x80CA
+#define GL_BLEND_SRC_ALPHA_EXT 0x80CB
+
+typedef void (GLAPIENTRY * PFNGLBLENDFUNCSEPARATEEXTPROC) (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha);
+
+#define glBlendFuncSeparateEXT GLEW_GET_FUN(__glewBlendFuncSeparateEXT)
+
+#define GLEW_EXT_blend_func_separate GLEW_GET_VAR(__GLEW_EXT_blend_func_separate)
+
+#endif /* !GL_EXT_blend_func_separate */
+
+/* ------------------------- GL_EXT_blend_logic_op ------------------------- */
+
+#if !defined(GL_EXT_blend_logic_op)
+#define GL_EXT_blend_logic_op 1
+
+#define GLEW_EXT_blend_logic_op GLEW_GET_VAR(__GLEW_EXT_blend_logic_op)
+
+#endif /* !GL_EXT_blend_logic_op */
+
+/* -------------------------- GL_EXT_blend_minmax -------------------------- */
+
+#if !defined(GL_EXT_blend_minmax)
+#define GL_EXT_blend_minmax 1
+
+#define GL_FUNC_ADD_EXT 0x8006
+#define GL_MIN_EXT 0x8007
+#define GL_MAX_EXT 0x8008
+#define GL_BLEND_EQUATION_EXT 0x8009
+
+typedef void (GLAPIENTRY * PFNGLBLENDEQUATIONEXTPROC) (GLenum mode);
+
+#define glBlendEquationEXT GLEW_GET_FUN(__glewBlendEquationEXT)
+
+#define GLEW_EXT_blend_minmax GLEW_GET_VAR(__GLEW_EXT_blend_minmax)
+
+#endif /* !GL_EXT_blend_minmax */
+
+/* ------------------------- GL_EXT_blend_subtract ------------------------- */
+
+#if !defined(GL_EXT_blend_subtract)
+#define GL_EXT_blend_subtract 1
+
+#define GL_FUNC_SUBTRACT_EXT 0x800A
+#define GL_FUNC_REVERSE_SUBTRACT_EXT 0x800B
+
+#define GLEW_EXT_blend_subtract GLEW_GET_VAR(__GLEW_EXT_blend_subtract)
+
+#endif /* !GL_EXT_blend_subtract */
+
+/* ------------------------ GL_EXT_clip_volume_hint ------------------------ */
+
+#if !defined(GL_EXT_clip_volume_hint)
+#define GL_EXT_clip_volume_hint 1
+
+#define GL_CLIP_VOLUME_CLIPPING_HINT_EXT 0x80F0
+
+#define GLEW_EXT_clip_volume_hint GLEW_GET_VAR(__GLEW_EXT_clip_volume_hint)
+
+#endif /* !GL_EXT_clip_volume_hint */
+
+/* ------------------------------ GL_EXT_cmyka ----------------------------- */
+
+#if !defined(GL_EXT_cmyka)
+#define GL_EXT_cmyka 1
+
+#define GL_CMYK_EXT 0x800C
+#define GL_CMYKA_EXT 0x800D
+#define GL_PACK_CMYK_HINT_EXT 0x800E
+#define GL_UNPACK_CMYK_HINT_EXT 0x800F
+
+#define GLEW_EXT_cmyka GLEW_GET_VAR(__GLEW_EXT_cmyka)
+
+#endif /* !GL_EXT_cmyka */
+
+/* ------------------------- GL_EXT_color_subtable ------------------------- */
+
+#if !defined(GL_EXT_color_subtable)
+#define GL_EXT_color_subtable 1
+
+typedef void (GLAPIENTRY * PFNGLCOLORSUBTABLEEXTPROC) (GLenum target, GLsizei start, GLsizei count, GLenum format, GLenum type, const void* data);
+typedef void (GLAPIENTRY * PFNGLCOPYCOLORSUBTABLEEXTPROC) (GLenum target, GLsizei start, GLint x, GLint y, GLsizei width);
+
+#define glColorSubTableEXT GLEW_GET_FUN(__glewColorSubTableEXT)
+#define glCopyColorSubTableEXT GLEW_GET_FUN(__glewCopyColorSubTableEXT)
+
+#define GLEW_EXT_color_subtable GLEW_GET_VAR(__GLEW_EXT_color_subtable)
+
+#endif /* !GL_EXT_color_subtable */
+
+/* ---------------------- GL_EXT_compiled_vertex_array --------------------- */
+
+#if !defined(GL_EXT_compiled_vertex_array)
+#define GL_EXT_compiled_vertex_array 1
+
+#define GL_ARRAY_ELEMENT_LOCK_FIRST_EXT 0x81A8
+#define GL_ARRAY_ELEMENT_LOCK_COUNT_EXT 0x81A9
+
+typedef void (GLAPIENTRY * PFNGLLOCKARRAYSEXTPROC) (GLint first, GLsizei count);
+typedef void (GLAPIENTRY * PFNGLUNLOCKARRAYSEXTPROC) (void);
+
+#define glLockArraysEXT GLEW_GET_FUN(__glewLockArraysEXT)
+#define glUnlockArraysEXT GLEW_GET_FUN(__glewUnlockArraysEXT)
+
+#define GLEW_EXT_compiled_vertex_array GLEW_GET_VAR(__GLEW_EXT_compiled_vertex_array)
+
+#endif /* !GL_EXT_compiled_vertex_array */
+
+/* --------------------------- GL_EXT_convolution -------------------------- */
+
+#if !defined(GL_EXT_convolution)
+#define GL_EXT_convolution 1
+
+#define GL_CONVOLUTION_1D_EXT 0x8010
+#define GL_CONVOLUTION_2D_EXT 0x8011
+#define GL_SEPARABLE_2D_EXT 0x8012
+#define GL_CONVOLUTION_BORDER_MODE_EXT 0x8013
+#define GL_CONVOLUTION_FILTER_SCALE_EXT 0x8014
+#define GL_CONVOLUTION_FILTER_BIAS_EXT 0x8015
+#define GL_REDUCE_EXT 0x8016
+#define GL_CONVOLUTION_FORMAT_EXT 0x8017
+#define GL_CONVOLUTION_WIDTH_EXT 0x8018
+#define GL_CONVOLUTION_HEIGHT_EXT 0x8019
+#define GL_MAX_CONVOLUTION_WIDTH_EXT 0x801A
+#define GL_MAX_CONVOLUTION_HEIGHT_EXT 0x801B
+#define GL_POST_CONVOLUTION_RED_SCALE_EXT 0x801C
+#define GL_POST_CONVOLUTION_GREEN_SCALE_EXT 0x801D
+#define GL_POST_CONVOLUTION_BLUE_SCALE_EXT 0x801E
+#define GL_POST_CONVOLUTION_ALPHA_SCALE_EXT 0x801F
+#define GL_POST_CONVOLUTION_RED_BIAS_EXT 0x8020
+#define GL_POST_CONVOLUTION_GREEN_BIAS_EXT 0x8021
+#define GL_POST_CONVOLUTION_BLUE_BIAS_EXT 0x8022
+#define GL_POST_CONVOLUTION_ALPHA_BIAS_EXT 0x8023
+
+typedef void (GLAPIENTRY * PFNGLCONVOLUTIONFILTER1DEXTPROC) (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const void* image);
+typedef void (GLAPIENTRY * PFNGLCONVOLUTIONFILTER2DEXTPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const void* image);
+typedef void (GLAPIENTRY * PFNGLCONVOLUTIONPARAMETERFEXTPROC) (GLenum target, GLenum pname, GLfloat param);
+typedef void (GLAPIENTRY * PFNGLCONVOLUTIONPARAMETERFVEXTPROC) (GLenum target, GLenum pname, const GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLCONVOLUTIONPARAMETERIEXTPROC) (GLenum target, GLenum pname, GLint param);
+typedef void (GLAPIENTRY * PFNGLCONVOLUTIONPARAMETERIVEXTPROC) (GLenum target, GLenum pname, const GLint* params);
+typedef void (GLAPIENTRY * PFNGLCOPYCONVOLUTIONFILTER1DEXTPROC) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width);
+typedef void (GLAPIENTRY * PFNGLCOPYCONVOLUTIONFILTER2DEXTPROC) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height);
+typedef void (GLAPIENTRY * PFNGLGETCONVOLUTIONFILTEREXTPROC) (GLenum target, GLenum format, GLenum type, void* image);
+typedef void (GLAPIENTRY * PFNGLGETCONVOLUTIONPARAMETERFVEXTPROC) (GLenum target, GLenum pname, GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLGETCONVOLUTIONPARAMETERIVEXTPROC) (GLenum target, GLenum pname, GLint* params);
+typedef void (GLAPIENTRY * PFNGLGETSEPARABLEFILTEREXTPROC) (GLenum target, GLenum format, GLenum type, void* row, void* column, void* span);
+typedef void (GLAPIENTRY * PFNGLSEPARABLEFILTER2DEXTPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const void* row, const void* column);
+
+#define glConvolutionFilter1DEXT GLEW_GET_FUN(__glewConvolutionFilter1DEXT)
+#define glConvolutionFilter2DEXT GLEW_GET_FUN(__glewConvolutionFilter2DEXT)
+#define glConvolutionParameterfEXT GLEW_GET_FUN(__glewConvolutionParameterfEXT)
+#define glConvolutionParameterfvEXT GLEW_GET_FUN(__glewConvolutionParameterfvEXT)
+#define glConvolutionParameteriEXT GLEW_GET_FUN(__glewConvolutionParameteriEXT)
+#define glConvolutionParameterivEXT GLEW_GET_FUN(__glewConvolutionParameterivEXT)
+#define glCopyConvolutionFilter1DEXT GLEW_GET_FUN(__glewCopyConvolutionFilter1DEXT)
+#define glCopyConvolutionFilter2DEXT GLEW_GET_FUN(__glewCopyConvolutionFilter2DEXT)
+#define glGetConvolutionFilterEXT GLEW_GET_FUN(__glewGetConvolutionFilterEXT)
+#define glGetConvolutionParameterfvEXT GLEW_GET_FUN(__glewGetConvolutionParameterfvEXT)
+#define glGetConvolutionParameterivEXT GLEW_GET_FUN(__glewGetConvolutionParameterivEXT)
+#define glGetSeparableFilterEXT GLEW_GET_FUN(__glewGetSeparableFilterEXT)
+#define glSeparableFilter2DEXT GLEW_GET_FUN(__glewSeparableFilter2DEXT)
+
+#define GLEW_EXT_convolution GLEW_GET_VAR(__GLEW_EXT_convolution)
+
+#endif /* !GL_EXT_convolution */
+
+/* ------------------------ GL_EXT_coordinate_frame ------------------------ */
+
+#if !defined(GL_EXT_coordinate_frame)
+#define GL_EXT_coordinate_frame 1
+
+#define GL_TANGENT_ARRAY_EXT 0x8439
+#define GL_BINORMAL_ARRAY_EXT 0x843A
+#define GL_CURRENT_TANGENT_EXT 0x843B
+#define GL_CURRENT_BINORMAL_EXT 0x843C
+#define GL_TANGENT_ARRAY_TYPE_EXT 0x843E
+#define GL_TANGENT_ARRAY_STRIDE_EXT 0x843F
+#define GL_BINORMAL_ARRAY_TYPE_EXT 0x8440
+#define GL_BINORMAL_ARRAY_STRIDE_EXT 0x8441
+#define GL_TANGENT_ARRAY_POINTER_EXT 0x8442
+#define GL_BINORMAL_ARRAY_POINTER_EXT 0x8443
+#define GL_MAP1_TANGENT_EXT 0x8444
+#define GL_MAP2_TANGENT_EXT 0x8445
+#define GL_MAP1_BINORMAL_EXT 0x8446
+#define GL_MAP2_BINORMAL_EXT 0x8447
+
+typedef void (GLAPIENTRY * PFNGLBINORMALPOINTEREXTPROC) (GLenum type, GLsizei stride, void* pointer);
+typedef void (GLAPIENTRY * PFNGLTANGENTPOINTEREXTPROC) (GLenum type, GLsizei stride, void* pointer);
+
+#define glBinormalPointerEXT GLEW_GET_FUN(__glewBinormalPointerEXT)
+#define glTangentPointerEXT GLEW_GET_FUN(__glewTangentPointerEXT)
+
+#define GLEW_EXT_coordinate_frame GLEW_GET_VAR(__GLEW_EXT_coordinate_frame)
+
+#endif /* !GL_EXT_coordinate_frame */
+
+/* -------------------------- GL_EXT_copy_texture -------------------------- */
+
+#if !defined(GL_EXT_copy_texture)
+#define GL_EXT_copy_texture 1
+
+typedef void (GLAPIENTRY * PFNGLCOPYTEXIMAGE1DEXTPROC) (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLint border);
+typedef void (GLAPIENTRY * PFNGLCOPYTEXIMAGE2DEXTPROC) (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border);
+typedef void (GLAPIENTRY * PFNGLCOPYTEXSUBIMAGE1DEXTPROC) (GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width);
+typedef void (GLAPIENTRY * PFNGLCOPYTEXSUBIMAGE2DEXTPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+typedef void (GLAPIENTRY * PFNGLCOPYTEXSUBIMAGE3DEXTPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+
+#define glCopyTexImage1DEXT GLEW_GET_FUN(__glewCopyTexImage1DEXT)
+#define glCopyTexImage2DEXT GLEW_GET_FUN(__glewCopyTexImage2DEXT)
+#define glCopyTexSubImage1DEXT GLEW_GET_FUN(__glewCopyTexSubImage1DEXT)
+#define glCopyTexSubImage2DEXT GLEW_GET_FUN(__glewCopyTexSubImage2DEXT)
+#define glCopyTexSubImage3DEXT GLEW_GET_FUN(__glewCopyTexSubImage3DEXT)
+
+#define GLEW_EXT_copy_texture GLEW_GET_VAR(__GLEW_EXT_copy_texture)
+
+#endif /* !GL_EXT_copy_texture */
+
+/* --------------------------- GL_EXT_cull_vertex -------------------------- */
+
+#if !defined(GL_EXT_cull_vertex)
+#define GL_EXT_cull_vertex 1
+
+#define GL_CULL_VERTEX_EXT 0x81AA
+#define GL_CULL_VERTEX_EYE_POSITION_EXT 0x81AB
+#define GL_CULL_VERTEX_OBJECT_POSITION_EXT 0x81AC
+
+typedef void (GLAPIENTRY * PFNGLCULLPARAMETERDVEXTPROC) (GLenum pname, GLdouble* params);
+typedef void (GLAPIENTRY * PFNGLCULLPARAMETERFVEXTPROC) (GLenum pname, GLfloat* params);
+
+#define glCullParameterdvEXT GLEW_GET_FUN(__glewCullParameterdvEXT)
+#define glCullParameterfvEXT GLEW_GET_FUN(__glewCullParameterfvEXT)
+
+#define GLEW_EXT_cull_vertex GLEW_GET_VAR(__GLEW_EXT_cull_vertex)
+
+#endif /* !GL_EXT_cull_vertex */
+
+/* ------------------------ GL_EXT_depth_bounds_test ----------------------- */
+
+#if !defined(GL_EXT_depth_bounds_test)
+#define GL_EXT_depth_bounds_test 1
+
+#define GL_DEPTH_BOUNDS_TEST_EXT 0x8890
+#define GL_DEPTH_BOUNDS_EXT 0x8891
+
+typedef void (GLAPIENTRY * PFNGLDEPTHBOUNDSEXTPROC) (GLclampd zmin, GLclampd zmax);
+
+#define glDepthBoundsEXT GLEW_GET_FUN(__glewDepthBoundsEXT)
+
+#define GLEW_EXT_depth_bounds_test GLEW_GET_VAR(__GLEW_EXT_depth_bounds_test)
+
+#endif /* !GL_EXT_depth_bounds_test */
+
+/* ----------------------- GL_EXT_direct_state_access ---------------------- */
+
+#if !defined(GL_EXT_direct_state_access)
+#define GL_EXT_direct_state_access 1
+
+#define GL_PROGRAM_MATRIX_EXT 0x8E2D
+#define GL_TRANSPOSE_PROGRAM_MATRIX_EXT 0x8E2E
+#define GL_PROGRAM_MATRIX_STACK_DEPTH_EXT 0x8E2F
+
+typedef void (GLAPIENTRY * PFNGLBINDMULTITEXTUREEXTPROC) (GLenum texunit, GLenum target, GLuint texture);
+typedef GLenum (GLAPIENTRY * PFNGLCHECKNAMEDFRAMEBUFFERSTATUSEXTPROC) (GLuint framebuffer, GLenum target);
+typedef void (GLAPIENTRY * PFNGLCLIENTATTRIBDEFAULTEXTPROC) (GLbitfield mask);
+typedef void (GLAPIENTRY * PFNGLCOMPRESSEDMULTITEXIMAGE1DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const void* data);
+typedef void (GLAPIENTRY * PFNGLCOMPRESSEDMULTITEXIMAGE2DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void* data);
+typedef void (GLAPIENTRY * PFNGLCOMPRESSEDMULTITEXIMAGE3DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void* data);
+typedef void (GLAPIENTRY * PFNGLCOMPRESSEDMULTITEXSUBIMAGE1DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const void* data);
+typedef void (GLAPIENTRY * PFNGLCOMPRESSEDMULTITEXSUBIMAGE2DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void* data);
+typedef void (GLAPIENTRY * PFNGLCOMPRESSEDMULTITEXSUBIMAGE3DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void* data);
+typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXTUREIMAGE1DEXTPROC) (GLuint texture, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const void* data);
+typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXTUREIMAGE2DEXTPROC) (GLuint texture, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void* data);
+typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXTUREIMAGE3DEXTPROC) (GLuint texture, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void* data);
+typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXTURESUBIMAGE1DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const void* data);
+typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXTURESUBIMAGE2DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void* data);
+typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXTURESUBIMAGE3DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void* data);
+typedef void (GLAPIENTRY * PFNGLCOPYMULTITEXIMAGE1DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLint border);
+typedef void (GLAPIENTRY * PFNGLCOPYMULTITEXIMAGE2DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border);
+typedef void (GLAPIENTRY * PFNGLCOPYMULTITEXSUBIMAGE1DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width);
+typedef void (GLAPIENTRY * PFNGLCOPYMULTITEXSUBIMAGE2DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+typedef void (GLAPIENTRY * PFNGLCOPYMULTITEXSUBIMAGE3DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+typedef void (GLAPIENTRY * PFNGLCOPYTEXTUREIMAGE1DEXTPROC) (GLuint texture, GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLint border);
+typedef void (GLAPIENTRY * PFNGLCOPYTEXTUREIMAGE2DEXTPROC) (GLuint texture, GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border);
+typedef void (GLAPIENTRY * PFNGLCOPYTEXTURESUBIMAGE1DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width);
+typedef void (GLAPIENTRY * PFNGLCOPYTEXTURESUBIMAGE2DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+typedef void (GLAPIENTRY * PFNGLCOPYTEXTURESUBIMAGE3DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+typedef void (GLAPIENTRY * PFNGLDISABLECLIENTSTATEINDEXEDEXTPROC) (GLenum array, GLuint index);
+typedef void (GLAPIENTRY * PFNGLDISABLECLIENTSTATEIEXTPROC) (GLenum array, GLuint index);
+typedef void (GLAPIENTRY * PFNGLDISABLEVERTEXARRAYATTRIBEXTPROC) (GLuint vaobj, GLuint index);
+typedef void (GLAPIENTRY * PFNGLDISABLEVERTEXARRAYEXTPROC) (GLuint vaobj, GLenum array);
+typedef void (GLAPIENTRY * PFNGLENABLECLIENTSTATEINDEXEDEXTPROC) (GLenum array, GLuint index);
+typedef void (GLAPIENTRY * PFNGLENABLECLIENTSTATEIEXTPROC) (GLenum array, GLuint index);
+typedef void (GLAPIENTRY * PFNGLENABLEVERTEXARRAYATTRIBEXTPROC) (GLuint vaobj, GLuint index);
+typedef void (GLAPIENTRY * PFNGLENABLEVERTEXARRAYEXTPROC) (GLuint vaobj, GLenum array);
+typedef void (GLAPIENTRY * PFNGLFLUSHMAPPEDNAMEDBUFFERRANGEEXTPROC) (GLuint buffer, GLintptr offset, GLsizeiptr length);
+typedef void (GLAPIENTRY * PFNGLFRAMEBUFFERDRAWBUFFEREXTPROC) (GLuint framebuffer, GLenum mode);
+typedef void (GLAPIENTRY * PFNGLFRAMEBUFFERDRAWBUFFERSEXTPROC) (GLuint framebuffer, GLsizei n, const GLenum* bufs);
+typedef void (GLAPIENTRY * PFNGLFRAMEBUFFERREADBUFFEREXTPROC) (GLuint framebuffer, GLenum mode);
+typedef void (GLAPIENTRY * PFNGLGENERATEMULTITEXMIPMAPEXTPROC) (GLenum texunit, GLenum target);
+typedef void (GLAPIENTRY * PFNGLGENERATETEXTUREMIPMAPEXTPROC) (GLuint texture, GLenum target);
+typedef void (GLAPIENTRY * PFNGLGETCOMPRESSEDMULTITEXIMAGEEXTPROC) (GLenum texunit, GLenum target, GLint level, void* img);
+typedef void (GLAPIENTRY * PFNGLGETCOMPRESSEDTEXTUREIMAGEEXTPROC) (GLuint texture, GLenum target, GLint level, void* img);
+typedef void (GLAPIENTRY * PFNGLGETDOUBLEINDEXEDVEXTPROC) (GLenum target, GLuint index, GLdouble* params);
+typedef void (GLAPIENTRY * PFNGLGETDOUBLEI_VEXTPROC) (GLenum pname, GLuint index, GLdouble* params);
+typedef void (GLAPIENTRY * PFNGLGETFLOATINDEXEDVEXTPROC) (GLenum target, GLuint index, GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLGETFLOATI_VEXTPROC) (GLenum pname, GLuint index, GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLGETFRAMEBUFFERPARAMETERIVEXTPROC) (GLuint framebuffer, GLenum pname, GLint* param);
+typedef void (GLAPIENTRY * PFNGLGETMULTITEXENVFVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLGETMULTITEXENVIVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, GLint* params);
+typedef void (GLAPIENTRY * PFNGLGETMULTITEXGENDVEXTPROC) (GLenum texunit, GLenum coord, GLenum pname, GLdouble* params);
+typedef void (GLAPIENTRY * PFNGLGETMULTITEXGENFVEXTPROC) (GLenum texunit, GLenum coord, GLenum pname, GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLGETMULTITEXGENIVEXTPROC) (GLenum texunit, GLenum coord, GLenum pname, GLint* params);
+typedef void (GLAPIENTRY * PFNGLGETMULTITEXIMAGEEXTPROC) (GLenum texunit, GLenum target, GLint level, GLenum format, GLenum type, void* pixels);
+typedef void (GLAPIENTRY * PFNGLGETMULTITEXLEVELPARAMETERFVEXTPROC) (GLenum texunit, GLenum target, GLint level, GLenum pname, GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLGETMULTITEXLEVELPARAMETERIVEXTPROC) (GLenum texunit, GLenum target, GLint level, GLenum pname, GLint* params);
+typedef void (GLAPIENTRY * PFNGLGETMULTITEXPARAMETERIIVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, GLint* params);
+typedef void (GLAPIENTRY * PFNGLGETMULTITEXPARAMETERIUIVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, GLuint* params);
+typedef void (GLAPIENTRY * PFNGLGETMULTITEXPARAMETERFVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLGETMULTITEXPARAMETERIVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, GLint* params);
+typedef void (GLAPIENTRY * PFNGLGETNAMEDBUFFERPARAMETERIVEXTPROC) (GLuint buffer, GLenum pname, GLint* params);
+typedef void (GLAPIENTRY * PFNGLGETNAMEDBUFFERPOINTERVEXTPROC) (GLuint buffer, GLenum pname, void** params);
+typedef void (GLAPIENTRY * PFNGLGETNAMEDBUFFERSUBDATAEXTPROC) (GLuint buffer, GLintptr offset, GLsizeiptr size, void* data);
+typedef void (GLAPIENTRY * PFNGLGETNAMEDFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC) (GLuint framebuffer, GLenum attachment, GLenum pname, GLint* params);
+typedef void (GLAPIENTRY * PFNGLGETNAMEDPROGRAMLOCALPARAMETERIIVEXTPROC) (GLuint program, GLenum target, GLuint index, GLint* params);
+typedef void (GLAPIENTRY * PFNGLGETNAMEDPROGRAMLOCALPARAMETERIUIVEXTPROC) (GLuint program, GLenum target, GLuint index, GLuint* params);
+typedef void (GLAPIENTRY * PFNGLGETNAMEDPROGRAMLOCALPARAMETERDVEXTPROC) (GLuint program, GLenum target, GLuint index, GLdouble* params);
+typedef void (GLAPIENTRY * PFNGLGETNAMEDPROGRAMLOCALPARAMETERFVEXTPROC) (GLuint program, GLenum target, GLuint index, GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLGETNAMEDPROGRAMSTRINGEXTPROC) (GLuint program, GLenum target, GLenum pname, void* string);
+typedef void (GLAPIENTRY * PFNGLGETNAMEDPROGRAMIVEXTPROC) (GLuint program, GLenum target, GLenum pname, GLint* params);
+typedef void (GLAPIENTRY * PFNGLGETNAMEDRENDERBUFFERPARAMETERIVEXTPROC) (GLuint renderbuffer, GLenum pname, GLint* params);
+typedef void (GLAPIENTRY * PFNGLGETPOINTERINDEXEDVEXTPROC) (GLenum target, GLuint index, GLvoid** params);
+typedef void (GLAPIENTRY * PFNGLGETPOINTERI_VEXTPROC) (GLenum pname, GLuint index, GLvoid** params);
+typedef void (GLAPIENTRY * PFNGLGETTEXTUREIMAGEEXTPROC) (GLuint texture, GLenum target, GLint level, GLenum format, GLenum type, void* pixels);
+typedef void (GLAPIENTRY * PFNGLGETTEXTURELEVELPARAMETERFVEXTPROC) (GLuint texture, GLenum target, GLint level, GLenum pname, GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLGETTEXTURELEVELPARAMETERIVEXTPROC) (GLuint texture, GLenum target, GLint level, GLenum pname, GLint* params);
+typedef void (GLAPIENTRY * PFNGLGETTEXTUREPARAMETERIIVEXTPROC) (GLuint texture, GLenum target, GLenum pname, GLint* params);
+typedef void (GLAPIENTRY * PFNGLGETTEXTUREPARAMETERIUIVEXTPROC) (GLuint texture, GLenum target, GLenum pname, GLuint* params);
+typedef void (GLAPIENTRY * PFNGLGETTEXTUREPARAMETERFVEXTPROC) (GLuint texture, GLenum target, GLenum pname, GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLGETTEXTUREPARAMETERIVEXTPROC) (GLuint texture, GLenum target, GLenum pname, GLint* params);
+typedef void (GLAPIENTRY * PFNGLGETVERTEXARRAYINTEGERI_VEXTPROC) (GLuint vaobj, GLuint index, GLenum pname, GLint* param);
+typedef void (GLAPIENTRY * PFNGLGETVERTEXARRAYINTEGERVEXTPROC) (GLuint vaobj, GLenum pname, GLint* param);
+typedef void (GLAPIENTRY * PFNGLGETVERTEXARRAYPOINTERI_VEXTPROC) (GLuint vaobj, GLuint index, GLenum pname, GLvoid** param);
+typedef void (GLAPIENTRY * PFNGLGETVERTEXARRAYPOINTERVEXTPROC) (GLuint vaobj, GLenum pname, GLvoid** param);
+typedef GLvoid * (GLAPIENTRY * PFNGLMAPNAMEDBUFFEREXTPROC) (GLuint buffer, GLenum access);
+typedef GLvoid * (GLAPIENTRY * PFNGLMAPNAMEDBUFFERRANGEEXTPROC) (GLuint buffer, GLintptr offset, GLsizeiptr length, GLbitfield access);
+typedef void (GLAPIENTRY * PFNGLMATRIXFRUSTUMEXTPROC) (GLenum matrixMode, GLdouble l, GLdouble r, GLdouble b, GLdouble t, GLdouble n, GLdouble f);
+typedef void (GLAPIENTRY * PFNGLMATRIXLOADIDENTITYEXTPROC) (GLenum matrixMode);
+typedef void (GLAPIENTRY * PFNGLMATRIXLOADTRANSPOSEDEXTPROC) (GLenum matrixMode, const GLdouble* m);
+typedef void (GLAPIENTRY * PFNGLMATRIXLOADTRANSPOSEFEXTPROC) (GLenum matrixMode, const GLfloat* m);
+typedef void (GLAPIENTRY * PFNGLMATRIXLOADDEXTPROC) (GLenum matrixMode, const GLdouble* m);
+typedef void (GLAPIENTRY * PFNGLMATRIXLOADFEXTPROC) (GLenum matrixMode, const GLfloat* m);
+typedef void (GLAPIENTRY * PFNGLMATRIXMULTTRANSPOSEDEXTPROC) (GLenum matrixMode, const GLdouble* m);
+typedef void (GLAPIENTRY * PFNGLMATRIXMULTTRANSPOSEFEXTPROC) (GLenum matrixMode, const GLfloat* m);
+typedef void (GLAPIENTRY * PFNGLMATRIXMULTDEXTPROC) (GLenum matrixMode, const GLdouble* m);
+typedef void (GLAPIENTRY * PFNGLMATRIXMULTFEXTPROC) (GLenum matrixMode, const GLfloat* m);
+typedef void (GLAPIENTRY * PFNGLMATRIXORTHOEXTPROC) (GLenum matrixMode, GLdouble l, GLdouble r, GLdouble b, GLdouble t, GLdouble n, GLdouble f);
+typedef void (GLAPIENTRY * PFNGLMATRIXPOPEXTPROC) (GLenum matrixMode);
+typedef void (GLAPIENTRY * PFNGLMATRIXPUSHEXTPROC) (GLenum matrixMode);
+typedef void (GLAPIENTRY * PFNGLMATRIXROTATEDEXTPROC) (GLenum matrixMode, GLdouble angle, GLdouble x, GLdouble y, GLdouble z);
+typedef void (GLAPIENTRY * PFNGLMATRIXROTATEFEXTPROC) (GLenum matrixMode, GLfloat angle, GLfloat x, GLfloat y, GLfloat z);
+typedef void (GLAPIENTRY * PFNGLMATRIXSCALEDEXTPROC) (GLenum matrixMode, GLdouble x, GLdouble y, GLdouble z);
+typedef void (GLAPIENTRY * PFNGLMATRIXSCALEFEXTPROC) (GLenum matrixMode, GLfloat x, GLfloat y, GLfloat z);
+typedef void (GLAPIENTRY * PFNGLMATRIXTRANSLATEDEXTPROC) (GLenum matrixMode, GLdouble x, GLdouble y, GLdouble z);
+typedef void (GLAPIENTRY * PFNGLMATRIXTRANSLATEFEXTPROC) (GLenum matrixMode, GLfloat x, GLfloat y, GLfloat z);
+typedef void (GLAPIENTRY * PFNGLMULTITEXBUFFEREXTPROC) (GLenum texunit, GLenum target, GLenum internalformat, GLuint buffer);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORDPOINTEREXTPROC) (GLenum texunit, GLint size, GLenum type, GLsizei stride, const void* pointer);
+typedef void (GLAPIENTRY * PFNGLMULTITEXENVFEXTPROC) (GLenum texunit, GLenum target, GLenum pname, GLfloat param);
+typedef void (GLAPIENTRY * PFNGLMULTITEXENVFVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, const GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLMULTITEXENVIEXTPROC) (GLenum texunit, GLenum target, GLenum pname, GLint param);
+typedef void (GLAPIENTRY * PFNGLMULTITEXENVIVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, const GLint* params);
+typedef void (GLAPIENTRY * PFNGLMULTITEXGENDEXTPROC) (GLenum texunit, GLenum coord, GLenum pname, GLdouble param);
+typedef void (GLAPIENTRY * PFNGLMULTITEXGENDVEXTPROC) (GLenum texunit, GLenum coord, GLenum pname, const GLdouble* params);
+typedef void (GLAPIENTRY * PFNGLMULTITEXGENFEXTPROC) (GLenum texunit, GLenum coord, GLenum pname, GLfloat param);
+typedef void (GLAPIENTRY * PFNGLMULTITEXGENFVEXTPROC) (GLenum texunit, GLenum coord, GLenum pname, const GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLMULTITEXGENIEXTPROC) (GLenum texunit, GLenum coord, GLenum pname, GLint param);
+typedef void (GLAPIENTRY * PFNGLMULTITEXGENIVEXTPROC) (GLenum texunit, GLenum coord, GLenum pname, const GLint* params);
+typedef void (GLAPIENTRY * PFNGLMULTITEXIMAGE1DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint internalformat, GLsizei width, GLint border, GLenum format, GLenum type, const void* pixels);
+typedef void (GLAPIENTRY * PFNGLMULTITEXIMAGE2DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void* pixels);
+typedef void (GLAPIENTRY * PFNGLMULTITEXIMAGE3DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void* pixels);
+typedef void (GLAPIENTRY * PFNGLMULTITEXPARAMETERIIVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, const GLint* params);
+typedef void (GLAPIENTRY * PFNGLMULTITEXPARAMETERIUIVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, const GLuint* params);
+typedef void (GLAPIENTRY * PFNGLMULTITEXPARAMETERFEXTPROC) (GLenum texunit, GLenum target, GLenum pname, GLfloat param);
+typedef void (GLAPIENTRY * PFNGLMULTITEXPARAMETERFVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, const GLfloat* param);
+typedef void (GLAPIENTRY * PFNGLMULTITEXPARAMETERIEXTPROC) (GLenum texunit, GLenum target, GLenum pname, GLint param);
+typedef void (GLAPIENTRY * PFNGLMULTITEXPARAMETERIVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, const GLint* param);
+typedef void (GLAPIENTRY * PFNGLMULTITEXRENDERBUFFEREXTPROC) (GLenum texunit, GLenum target, GLuint renderbuffer);
+typedef void (GLAPIENTRY * PFNGLMULTITEXSUBIMAGE1DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const void* pixels);
+typedef void (GLAPIENTRY * PFNGLMULTITEXSUBIMAGE2DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void* pixels);
+typedef void (GLAPIENTRY * PFNGLMULTITEXSUBIMAGE3DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void* pixels);
+typedef void (GLAPIENTRY * PFNGLNAMEDBUFFERDATAEXTPROC) (GLuint buffer, GLsizeiptr size, const void* data, GLenum usage);
+typedef void (GLAPIENTRY * PFNGLNAMEDBUFFERSUBDATAEXTPROC) (GLuint buffer, GLintptr offset, GLsizeiptr size, const void* data);
+typedef void (GLAPIENTRY * PFNGLNAMEDCOPYBUFFERSUBDATAEXTPROC) (GLuint readBuffer, GLuint writeBuffer, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size);
+typedef void (GLAPIENTRY * PFNGLNAMEDFRAMEBUFFERRENDERBUFFEREXTPROC) (GLuint framebuffer, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer);
+typedef void (GLAPIENTRY * PFNGLNAMEDFRAMEBUFFERTEXTURE1DEXTPROC) (GLuint framebuffer, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
+typedef void (GLAPIENTRY * PFNGLNAMEDFRAMEBUFFERTEXTURE2DEXTPROC) (GLuint framebuffer, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
+typedef void (GLAPIENTRY * PFNGLNAMEDFRAMEBUFFERTEXTURE3DEXTPROC) (GLuint framebuffer, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset);
+typedef void (GLAPIENTRY * PFNGLNAMEDFRAMEBUFFERTEXTUREEXTPROC) (GLuint framebuffer, GLenum attachment, GLuint texture, GLint level);
+typedef void (GLAPIENTRY * PFNGLNAMEDFRAMEBUFFERTEXTUREFACEEXTPROC) (GLuint framebuffer, GLenum attachment, GLuint texture, GLint level, GLenum face);
+typedef void (GLAPIENTRY * PFNGLNAMEDFRAMEBUFFERTEXTURELAYEREXTPROC) (GLuint framebuffer, GLenum attachment, GLuint texture, GLint level, GLint layer);
+typedef void (GLAPIENTRY * PFNGLNAMEDPROGRAMLOCALPARAMETER4DEXTPROC) (GLuint program, GLenum target, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+typedef void (GLAPIENTRY * PFNGLNAMEDPROGRAMLOCALPARAMETER4DVEXTPROC) (GLuint program, GLenum target, GLuint index, const GLdouble* params);
+typedef void (GLAPIENTRY * PFNGLNAMEDPROGRAMLOCALPARAMETER4FEXTPROC) (GLuint program, GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+typedef void (GLAPIENTRY * PFNGLNAMEDPROGRAMLOCALPARAMETER4FVEXTPROC) (GLuint program, GLenum target, GLuint index, const GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLNAMEDPROGRAMLOCALPARAMETERI4IEXTPROC) (GLuint program, GLenum target, GLuint index, GLint x, GLint y, GLint z, GLint w);
+typedef void (GLAPIENTRY * PFNGLNAMEDPROGRAMLOCALPARAMETERI4IVEXTPROC) (GLuint program, GLenum target, GLuint index, const GLint* params);
+typedef void (GLAPIENTRY * PFNGLNAMEDPROGRAMLOCALPARAMETERI4UIEXTPROC) (GLuint program, GLenum target, GLuint index, GLuint x, GLuint y, GLuint z, GLuint w);
+typedef void (GLAPIENTRY * PFNGLNAMEDPROGRAMLOCALPARAMETERI4UIVEXTPROC) (GLuint program, GLenum target, GLuint index, const GLuint* params);
+typedef void (GLAPIENTRY * PFNGLNAMEDPROGRAMLOCALPARAMETERS4FVEXTPROC) (GLuint program, GLenum target, GLuint index, GLsizei count, const GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLNAMEDPROGRAMLOCALPARAMETERSI4IVEXTPROC) (GLuint program, GLenum target, GLuint index, GLsizei count, const GLint* params);
+typedef void (GLAPIENTRY * PFNGLNAMEDPROGRAMLOCALPARAMETERSI4UIVEXTPROC) (GLuint program, GLenum target, GLuint index, GLsizei count, const GLuint* params);
+typedef void (GLAPIENTRY * PFNGLNAMEDPROGRAMSTRINGEXTPROC) (GLuint program, GLenum target, GLenum format, GLsizei len, const void* string);
+typedef void (GLAPIENTRY * PFNGLNAMEDRENDERBUFFERSTORAGEEXTPROC) (GLuint renderbuffer, GLenum internalformat, GLsizei width, GLsizei height);
+typedef void (GLAPIENTRY * PFNGLNAMEDRENDERBUFFERSTORAGEMULTISAMPLECOVERAGEEXTPROC) (GLuint renderbuffer, GLsizei coverageSamples, GLsizei colorSamples, GLenum internalformat, GLsizei width, GLsizei height);
+typedef void (GLAPIENTRY * PFNGLNAMEDRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC) (GLuint renderbuffer, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM1FEXTPROC) (GLuint program, GLint location, GLfloat v0);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM1FVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLfloat* value);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM1IEXTPROC) (GLuint program, GLint location, GLint v0);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM1IVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLint* value);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM1UIEXTPROC) (GLuint program, GLint location, GLuint v0);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM1UIVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLuint* value);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM2FEXTPROC) (GLuint program, GLint location, GLfloat v0, GLfloat v1);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM2FVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLfloat* value);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM2IEXTPROC) (GLuint program, GLint location, GLint v0, GLint v1);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM2IVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLint* value);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM2UIEXTPROC) (GLuint program, GLint location, GLuint v0, GLuint v1);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM2UIVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLuint* value);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM3FEXTPROC) (GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM3FVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLfloat* value);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM3IEXTPROC) (GLuint program, GLint location, GLint v0, GLint v1, GLint v2);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM3IVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLint* value);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM3UIEXTPROC) (GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM3UIVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLuint* value);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM4FEXTPROC) (GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM4FVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLfloat* value);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM4IEXTPROC) (GLuint program, GLint location, GLint v0, GLint v1, GLint v2, GLint v3);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM4IVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLint* value);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM4UIEXTPROC) (GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM4UIVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLuint* value);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX2FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX2X3FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX2X4FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX3FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX3X2FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX3X4FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX4FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX4X2FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX4X3FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
+typedef void (GLAPIENTRY * PFNGLPUSHCLIENTATTRIBDEFAULTEXTPROC) (GLbitfield mask);
+typedef void (GLAPIENTRY * PFNGLTEXTUREBUFFEREXTPROC) (GLuint texture, GLenum target, GLenum internalformat, GLuint buffer);
+typedef void (GLAPIENTRY * PFNGLTEXTUREIMAGE1DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint internalformat, GLsizei width, GLint border, GLenum format, GLenum type, const void* pixels);
+typedef void (GLAPIENTRY * PFNGLTEXTUREIMAGE2DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void* pixels);
+typedef void (GLAPIENTRY * PFNGLTEXTUREIMAGE3DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void* pixels);
+typedef void (GLAPIENTRY * PFNGLTEXTUREPARAMETERIIVEXTPROC) (GLuint texture, GLenum target, GLenum pname, const GLint* params);
+typedef void (GLAPIENTRY * PFNGLTEXTUREPARAMETERIUIVEXTPROC) (GLuint texture, GLenum target, GLenum pname, const GLuint* params);
+typedef void (GLAPIENTRY * PFNGLTEXTUREPARAMETERFEXTPROC) (GLuint texture, GLenum target, GLenum pname, GLfloat param);
+typedef void (GLAPIENTRY * PFNGLTEXTUREPARAMETERFVEXTPROC) (GLuint texture, GLenum target, GLenum pname, const GLfloat* param);
+typedef void (GLAPIENTRY * PFNGLTEXTUREPARAMETERIEXTPROC) (GLuint texture, GLenum target, GLenum pname, GLint param);
+typedef void (GLAPIENTRY * PFNGLTEXTUREPARAMETERIVEXTPROC) (GLuint texture, GLenum target, GLenum pname, const GLint* param);
+typedef void (GLAPIENTRY * PFNGLTEXTURERENDERBUFFEREXTPROC) (GLuint texture, GLenum target, GLuint renderbuffer);
+typedef void (GLAPIENTRY * PFNGLTEXTURESUBIMAGE1DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const void* pixels);
+typedef void (GLAPIENTRY * PFNGLTEXTURESUBIMAGE2DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void* pixels);
+typedef void (GLAPIENTRY * PFNGLTEXTURESUBIMAGE3DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void* pixels);
+typedef GLboolean (GLAPIENTRY * PFNGLUNMAPNAMEDBUFFEREXTPROC) (GLuint buffer);
+typedef void (GLAPIENTRY * PFNGLVERTEXARRAYCOLOROFFSETEXTPROC) (GLuint vaobj, GLuint buffer, GLint size, GLenum type, GLsizei stride, GLintptr offset);
+typedef void (GLAPIENTRY * PFNGLVERTEXARRAYEDGEFLAGOFFSETEXTPROC) (GLuint vaobj, GLuint buffer, GLsizei stride, GLintptr offset);
+typedef void (GLAPIENTRY * PFNGLVERTEXARRAYFOGCOORDOFFSETEXTPROC) (GLuint vaobj, GLuint buffer, GLenum type, GLsizei stride, GLintptr offset);
+typedef void (GLAPIENTRY * PFNGLVERTEXARRAYINDEXOFFSETEXTPROC) (GLuint vaobj, GLuint buffer, GLenum type, GLsizei stride, GLintptr offset);
+typedef void (GLAPIENTRY * PFNGLVERTEXARRAYMULTITEXCOORDOFFSETEXTPROC) (GLuint vaobj, GLuint buffer, GLenum texunit, GLint size, GLenum type, GLsizei stride, GLintptr offset);
+typedef void (GLAPIENTRY * PFNGLVERTEXARRAYNORMALOFFSETEXTPROC) (GLuint vaobj, GLuint buffer, GLenum type, GLsizei stride, GLintptr offset);
+typedef void (GLAPIENTRY * PFNGLVERTEXARRAYSECONDARYCOLOROFFSETEXTPROC) (GLuint vaobj, GLuint buffer, GLint size, GLenum type, GLsizei stride, GLintptr offset);
+typedef void (GLAPIENTRY * PFNGLVERTEXARRAYTEXCOORDOFFSETEXTPROC) (GLuint vaobj, GLuint buffer, GLint size, GLenum type, GLsizei stride, GLintptr offset);
+typedef void (GLAPIENTRY * PFNGLVERTEXARRAYVERTEXATTRIBIOFFSETEXTPROC) (GLuint vaobj, GLuint buffer, GLuint index, GLint size, GLenum type, GLsizei stride, GLintptr offset);
+typedef void (GLAPIENTRY * PFNGLVERTEXARRAYVERTEXATTRIBOFFSETEXTPROC) (GLuint vaobj, GLuint buffer, GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, GLintptr offset);
+typedef void (GLAPIENTRY * PFNGLVERTEXARRAYVERTEXOFFSETEXTPROC) (GLuint vaobj, GLuint buffer, GLint size, GLenum type, GLsizei stride, GLintptr offset);
+
+#define glBindMultiTextureEXT GLEW_GET_FUN(__glewBindMultiTextureEXT)
+#define glCheckNamedFramebufferStatusEXT GLEW_GET_FUN(__glewCheckNamedFramebufferStatusEXT)
+#define glClientAttribDefaultEXT GLEW_GET_FUN(__glewClientAttribDefaultEXT)
+#define glCompressedMultiTexImage1DEXT GLEW_GET_FUN(__glewCompressedMultiTexImage1DEXT)
+#define glCompressedMultiTexImage2DEXT GLEW_GET_FUN(__glewCompressedMultiTexImage2DEXT)
+#define glCompressedMultiTexImage3DEXT GLEW_GET_FUN(__glewCompressedMultiTexImage3DEXT)
+#define glCompressedMultiTexSubImage1DEXT GLEW_GET_FUN(__glewCompressedMultiTexSubImage1DEXT)
+#define glCompressedMultiTexSubImage2DEXT GLEW_GET_FUN(__glewCompressedMultiTexSubImage2DEXT)
+#define glCompressedMultiTexSubImage3DEXT GLEW_GET_FUN(__glewCompressedMultiTexSubImage3DEXT)
+#define glCompressedTextureImage1DEXT GLEW_GET_FUN(__glewCompressedTextureImage1DEXT)
+#define glCompressedTextureImage2DEXT GLEW_GET_FUN(__glewCompressedTextureImage2DEXT)
+#define glCompressedTextureImage3DEXT GLEW_GET_FUN(__glewCompressedTextureImage3DEXT)
+#define glCompressedTextureSubImage1DEXT GLEW_GET_FUN(__glewCompressedTextureSubImage1DEXT)
+#define glCompressedTextureSubImage2DEXT GLEW_GET_FUN(__glewCompressedTextureSubImage2DEXT)
+#define glCompressedTextureSubImage3DEXT GLEW_GET_FUN(__glewCompressedTextureSubImage3DEXT)
+#define glCopyMultiTexImage1DEXT GLEW_GET_FUN(__glewCopyMultiTexImage1DEXT)
+#define glCopyMultiTexImage2DEXT GLEW_GET_FUN(__glewCopyMultiTexImage2DEXT)
+#define glCopyMultiTexSubImage1DEXT GLEW_GET_FUN(__glewCopyMultiTexSubImage1DEXT)
+#define glCopyMultiTexSubImage2DEXT GLEW_GET_FUN(__glewCopyMultiTexSubImage2DEXT)
+#define glCopyMultiTexSubImage3DEXT GLEW_GET_FUN(__glewCopyMultiTexSubImage3DEXT)
+#define glCopyTextureImage1DEXT GLEW_GET_FUN(__glewCopyTextureImage1DEXT)
+#define glCopyTextureImage2DEXT GLEW_GET_FUN(__glewCopyTextureImage2DEXT)
+#define glCopyTextureSubImage1DEXT GLEW_GET_FUN(__glewCopyTextureSubImage1DEXT)
+#define glCopyTextureSubImage2DEXT GLEW_GET_FUN(__glewCopyTextureSubImage2DEXT)
+#define glCopyTextureSubImage3DEXT GLEW_GET_FUN(__glewCopyTextureSubImage3DEXT)
+#define glDisableClientStateIndexedEXT GLEW_GET_FUN(__glewDisableClientStateIndexedEXT)
+#define glDisableClientStateiEXT GLEW_GET_FUN(__glewDisableClientStateiEXT)
+#define glDisableVertexArrayAttribEXT GLEW_GET_FUN(__glewDisableVertexArrayAttribEXT)
+#define glDisableVertexArrayEXT GLEW_GET_FUN(__glewDisableVertexArrayEXT)
+#define glEnableClientStateIndexedEXT GLEW_GET_FUN(__glewEnableClientStateIndexedEXT)
+#define glEnableClientStateiEXT GLEW_GET_FUN(__glewEnableClientStateiEXT)
+#define glEnableVertexArrayAttribEXT GLEW_GET_FUN(__glewEnableVertexArrayAttribEXT)
+#define glEnableVertexArrayEXT GLEW_GET_FUN(__glewEnableVertexArrayEXT)
+#define glFlushMappedNamedBufferRangeEXT GLEW_GET_FUN(__glewFlushMappedNamedBufferRangeEXT)
+#define glFramebufferDrawBufferEXT GLEW_GET_FUN(__glewFramebufferDrawBufferEXT)
+#define glFramebufferDrawBuffersEXT GLEW_GET_FUN(__glewFramebufferDrawBuffersEXT)
+#define glFramebufferReadBufferEXT GLEW_GET_FUN(__glewFramebufferReadBufferEXT)
+#define glGenerateMultiTexMipmapEXT GLEW_GET_FUN(__glewGenerateMultiTexMipmapEXT)
+#define glGenerateTextureMipmapEXT GLEW_GET_FUN(__glewGenerateTextureMipmapEXT)
+#define glGetCompressedMultiTexImageEXT GLEW_GET_FUN(__glewGetCompressedMultiTexImageEXT)
+#define glGetCompressedTextureImageEXT GLEW_GET_FUN(__glewGetCompressedTextureImageEXT)
+#define glGetDoubleIndexedvEXT GLEW_GET_FUN(__glewGetDoubleIndexedvEXT)
+#define glGetDoublei_vEXT GLEW_GET_FUN(__glewGetDoublei_vEXT)
+#define glGetFloatIndexedvEXT GLEW_GET_FUN(__glewGetFloatIndexedvEXT)
+#define glGetFloati_vEXT GLEW_GET_FUN(__glewGetFloati_vEXT)
+#define glGetFramebufferParameterivEXT GLEW_GET_FUN(__glewGetFramebufferParameterivEXT)
+#define glGetMultiTexEnvfvEXT GLEW_GET_FUN(__glewGetMultiTexEnvfvEXT)
+#define glGetMultiTexEnvivEXT GLEW_GET_FUN(__glewGetMultiTexEnvivEXT)
+#define glGetMultiTexGendvEXT GLEW_GET_FUN(__glewGetMultiTexGendvEXT)
+#define glGetMultiTexGenfvEXT GLEW_GET_FUN(__glewGetMultiTexGenfvEXT)
+#define glGetMultiTexGenivEXT GLEW_GET_FUN(__glewGetMultiTexGenivEXT)
+#define glGetMultiTexImageEXT GLEW_GET_FUN(__glewGetMultiTexImageEXT)
+#define glGetMultiTexLevelParameterfvEXT GLEW_GET_FUN(__glewGetMultiTexLevelParameterfvEXT)
+#define glGetMultiTexLevelParameterivEXT GLEW_GET_FUN(__glewGetMultiTexLevelParameterivEXT)
+#define glGetMultiTexParameterIivEXT GLEW_GET_FUN(__glewGetMultiTexParameterIivEXT)
+#define glGetMultiTexParameterIuivEXT GLEW_GET_FUN(__glewGetMultiTexParameterIuivEXT)
+#define glGetMultiTexParameterfvEXT GLEW_GET_FUN(__glewGetMultiTexParameterfvEXT)
+#define glGetMultiTexParameterivEXT GLEW_GET_FUN(__glewGetMultiTexParameterivEXT)
+#define glGetNamedBufferParameterivEXT GLEW_GET_FUN(__glewGetNamedBufferParameterivEXT)
+#define glGetNamedBufferPointervEXT GLEW_GET_FUN(__glewGetNamedBufferPointervEXT)
+#define glGetNamedBufferSubDataEXT GLEW_GET_FUN(__glewGetNamedBufferSubDataEXT)
+#define glGetNamedFramebufferAttachmentParameterivEXT GLEW_GET_FUN(__glewGetNamedFramebufferAttachmentParameterivEXT)
+#define glGetNamedProgramLocalParameterIivEXT GLEW_GET_FUN(__glewGetNamedProgramLocalParameterIivEXT)
+#define glGetNamedProgramLocalParameterIuivEXT GLEW_GET_FUN(__glewGetNamedProgramLocalParameterIuivEXT)
+#define glGetNamedProgramLocalParameterdvEXT GLEW_GET_FUN(__glewGetNamedProgramLocalParameterdvEXT)
+#define glGetNamedProgramLocalParameterfvEXT GLEW_GET_FUN(__glewGetNamedProgramLocalParameterfvEXT)
+#define glGetNamedProgramStringEXT GLEW_GET_FUN(__glewGetNamedProgramStringEXT)
+#define glGetNamedProgramivEXT GLEW_GET_FUN(__glewGetNamedProgramivEXT)
+#define glGetNamedRenderbufferParameterivEXT GLEW_GET_FUN(__glewGetNamedRenderbufferParameterivEXT)
+#define glGetPointerIndexedvEXT GLEW_GET_FUN(__glewGetPointerIndexedvEXT)
+#define glGetPointeri_vEXT GLEW_GET_FUN(__glewGetPointeri_vEXT)
+#define glGetTextureImageEXT GLEW_GET_FUN(__glewGetTextureImageEXT)
+#define glGetTextureLevelParameterfvEXT GLEW_GET_FUN(__glewGetTextureLevelParameterfvEXT)
+#define glGetTextureLevelParameterivEXT GLEW_GET_FUN(__glewGetTextureLevelParameterivEXT)
+#define glGetTextureParameterIivEXT GLEW_GET_FUN(__glewGetTextureParameterIivEXT)
+#define glGetTextureParameterIuivEXT GLEW_GET_FUN(__glewGetTextureParameterIuivEXT)
+#define glGetTextureParameterfvEXT GLEW_GET_FUN(__glewGetTextureParameterfvEXT)
+#define glGetTextureParameterivEXT GLEW_GET_FUN(__glewGetTextureParameterivEXT)
+#define glGetVertexArrayIntegeri_vEXT GLEW_GET_FUN(__glewGetVertexArrayIntegeri_vEXT)
+#define glGetVertexArrayIntegervEXT GLEW_GET_FUN(__glewGetVertexArrayIntegervEXT)
+#define glGetVertexArrayPointeri_vEXT GLEW_GET_FUN(__glewGetVertexArrayPointeri_vEXT)
+#define glGetVertexArrayPointervEXT GLEW_GET_FUN(__glewGetVertexArrayPointervEXT)
+#define glMapNamedBufferEXT GLEW_GET_FUN(__glewMapNamedBufferEXT)
+#define glMapNamedBufferRangeEXT GLEW_GET_FUN(__glewMapNamedBufferRangeEXT)
+#define glMatrixFrustumEXT GLEW_GET_FUN(__glewMatrixFrustumEXT)
+#define glMatrixLoadIdentityEXT GLEW_GET_FUN(__glewMatrixLoadIdentityEXT)
+#define glMatrixLoadTransposedEXT GLEW_GET_FUN(__glewMatrixLoadTransposedEXT)
+#define glMatrixLoadTransposefEXT GLEW_GET_FUN(__glewMatrixLoadTransposefEXT)
+#define glMatrixLoaddEXT GLEW_GET_FUN(__glewMatrixLoaddEXT)
+#define glMatrixLoadfEXT GLEW_GET_FUN(__glewMatrixLoadfEXT)
+#define glMatrixMultTransposedEXT GLEW_GET_FUN(__glewMatrixMultTransposedEXT)
+#define glMatrixMultTransposefEXT GLEW_GET_FUN(__glewMatrixMultTransposefEXT)
+#define glMatrixMultdEXT GLEW_GET_FUN(__glewMatrixMultdEXT)
+#define glMatrixMultfEXT GLEW_GET_FUN(__glewMatrixMultfEXT)
+#define glMatrixOrthoEXT GLEW_GET_FUN(__glewMatrixOrthoEXT)
+#define glMatrixPopEXT GLEW_GET_FUN(__glewMatrixPopEXT)
+#define glMatrixPushEXT GLEW_GET_FUN(__glewMatrixPushEXT)
+#define glMatrixRotatedEXT GLEW_GET_FUN(__glewMatrixRotatedEXT)
+#define glMatrixRotatefEXT GLEW_GET_FUN(__glewMatrixRotatefEXT)
+#define glMatrixScaledEXT GLEW_GET_FUN(__glewMatrixScaledEXT)
+#define glMatrixScalefEXT GLEW_GET_FUN(__glewMatrixScalefEXT)
+#define glMatrixTranslatedEXT GLEW_GET_FUN(__glewMatrixTranslatedEXT)
+#define glMatrixTranslatefEXT GLEW_GET_FUN(__glewMatrixTranslatefEXT)
+#define glMultiTexBufferEXT GLEW_GET_FUN(__glewMultiTexBufferEXT)
+#define glMultiTexCoordPointerEXT GLEW_GET_FUN(__glewMultiTexCoordPointerEXT)
+#define glMultiTexEnvfEXT GLEW_GET_FUN(__glewMultiTexEnvfEXT)
+#define glMultiTexEnvfvEXT GLEW_GET_FUN(__glewMultiTexEnvfvEXT)
+#define glMultiTexEnviEXT GLEW_GET_FUN(__glewMultiTexEnviEXT)
+#define glMultiTexEnvivEXT GLEW_GET_FUN(__glewMultiTexEnvivEXT)
+#define glMultiTexGendEXT GLEW_GET_FUN(__glewMultiTexGendEXT)
+#define glMultiTexGendvEXT GLEW_GET_FUN(__glewMultiTexGendvEXT)
+#define glMultiTexGenfEXT GLEW_GET_FUN(__glewMultiTexGenfEXT)
+#define glMultiTexGenfvEXT GLEW_GET_FUN(__glewMultiTexGenfvEXT)
+#define glMultiTexGeniEXT GLEW_GET_FUN(__glewMultiTexGeniEXT)
+#define glMultiTexGenivEXT GLEW_GET_FUN(__glewMultiTexGenivEXT)
+#define glMultiTexImage1DEXT GLEW_GET_FUN(__glewMultiTexImage1DEXT)
+#define glMultiTexImage2DEXT GLEW_GET_FUN(__glewMultiTexImage2DEXT)
+#define glMultiTexImage3DEXT GLEW_GET_FUN(__glewMultiTexImage3DEXT)
+#define glMultiTexParameterIivEXT GLEW_GET_FUN(__glewMultiTexParameterIivEXT)
+#define glMultiTexParameterIuivEXT GLEW_GET_FUN(__glewMultiTexParameterIuivEXT)
+#define glMultiTexParameterfEXT GLEW_GET_FUN(__glewMultiTexParameterfEXT)
+#define glMultiTexParameterfvEXT GLEW_GET_FUN(__glewMultiTexParameterfvEXT)
+#define glMultiTexParameteriEXT GLEW_GET_FUN(__glewMultiTexParameteriEXT)
+#define glMultiTexParameterivEXT GLEW_GET_FUN(__glewMultiTexParameterivEXT)
+#define glMultiTexRenderbufferEXT GLEW_GET_FUN(__glewMultiTexRenderbufferEXT)
+#define glMultiTexSubImage1DEXT GLEW_GET_FUN(__glewMultiTexSubImage1DEXT)
+#define glMultiTexSubImage2DEXT GLEW_GET_FUN(__glewMultiTexSubImage2DEXT)
+#define glMultiTexSubImage3DEXT GLEW_GET_FUN(__glewMultiTexSubImage3DEXT)
+#define glNamedBufferDataEXT GLEW_GET_FUN(__glewNamedBufferDataEXT)
+#define glNamedBufferSubDataEXT GLEW_GET_FUN(__glewNamedBufferSubDataEXT)
+#define glNamedCopyBufferSubDataEXT GLEW_GET_FUN(__glewNamedCopyBufferSubDataEXT)
+#define glNamedFramebufferRenderbufferEXT GLEW_GET_FUN(__glewNamedFramebufferRenderbufferEXT)
+#define glNamedFramebufferTexture1DEXT GLEW_GET_FUN(__glewNamedFramebufferTexture1DEXT)
+#define glNamedFramebufferTexture2DEXT GLEW_GET_FUN(__glewNamedFramebufferTexture2DEXT)
+#define glNamedFramebufferTexture3DEXT GLEW_GET_FUN(__glewNamedFramebufferTexture3DEXT)
+#define glNamedFramebufferTextureEXT GLEW_GET_FUN(__glewNamedFramebufferTextureEXT)
+#define glNamedFramebufferTextureFaceEXT GLEW_GET_FUN(__glewNamedFramebufferTextureFaceEXT)
+#define glNamedFramebufferTextureLayerEXT GLEW_GET_FUN(__glewNamedFramebufferTextureLayerEXT)
+#define glNamedProgramLocalParameter4dEXT GLEW_GET_FUN(__glewNamedProgramLocalParameter4dEXT)
+#define glNamedProgramLocalParameter4dvEXT GLEW_GET_FUN(__glewNamedProgramLocalParameter4dvEXT)
+#define glNamedProgramLocalParameter4fEXT GLEW_GET_FUN(__glewNamedProgramLocalParameter4fEXT)
+#define glNamedProgramLocalParameter4fvEXT GLEW_GET_FUN(__glewNamedProgramLocalParameter4fvEXT)
+#define glNamedProgramLocalParameterI4iEXT GLEW_GET_FUN(__glewNamedProgramLocalParameterI4iEXT)
+#define glNamedProgramLocalParameterI4ivEXT GLEW_GET_FUN(__glewNamedProgramLocalParameterI4ivEXT)
+#define glNamedProgramLocalParameterI4uiEXT GLEW_GET_FUN(__glewNamedProgramLocalParameterI4uiEXT)
+#define glNamedProgramLocalParameterI4uivEXT GLEW_GET_FUN(__glewNamedProgramLocalParameterI4uivEXT)
+#define glNamedProgramLocalParameters4fvEXT GLEW_GET_FUN(__glewNamedProgramLocalParameters4fvEXT)
+#define glNamedProgramLocalParametersI4ivEXT GLEW_GET_FUN(__glewNamedProgramLocalParametersI4ivEXT)
+#define glNamedProgramLocalParametersI4uivEXT GLEW_GET_FUN(__glewNamedProgramLocalParametersI4uivEXT)
+#define glNamedProgramStringEXT GLEW_GET_FUN(__glewNamedProgramStringEXT)
+#define glNamedRenderbufferStorageEXT GLEW_GET_FUN(__glewNamedRenderbufferStorageEXT)
+#define glNamedRenderbufferStorageMultisampleCoverageEXT GLEW_GET_FUN(__glewNamedRenderbufferStorageMultisampleCoverageEXT)
+#define glNamedRenderbufferStorageMultisampleEXT GLEW_GET_FUN(__glewNamedRenderbufferStorageMultisampleEXT)
+#define glProgramUniform1fEXT GLEW_GET_FUN(__glewProgramUniform1fEXT)
+#define glProgramUniform1fvEXT GLEW_GET_FUN(__glewProgramUniform1fvEXT)
+#define glProgramUniform1iEXT GLEW_GET_FUN(__glewProgramUniform1iEXT)
+#define glProgramUniform1ivEXT GLEW_GET_FUN(__glewProgramUniform1ivEXT)
+#define glProgramUniform1uiEXT GLEW_GET_FUN(__glewProgramUniform1uiEXT)
+#define glProgramUniform1uivEXT GLEW_GET_FUN(__glewProgramUniform1uivEXT)
+#define glProgramUniform2fEXT GLEW_GET_FUN(__glewProgramUniform2fEXT)
+#define glProgramUniform2fvEXT GLEW_GET_FUN(__glewProgramUniform2fvEXT)
+#define glProgramUniform2iEXT GLEW_GET_FUN(__glewProgramUniform2iEXT)
+#define glProgramUniform2ivEXT GLEW_GET_FUN(__glewProgramUniform2ivEXT)
+#define glProgramUniform2uiEXT GLEW_GET_FUN(__glewProgramUniform2uiEXT)
+#define glProgramUniform2uivEXT GLEW_GET_FUN(__glewProgramUniform2uivEXT)
+#define glProgramUniform3fEXT GLEW_GET_FUN(__glewProgramUniform3fEXT)
+#define glProgramUniform3fvEXT GLEW_GET_FUN(__glewProgramUniform3fvEXT)
+#define glProgramUniform3iEXT GLEW_GET_FUN(__glewProgramUniform3iEXT)
+#define glProgramUniform3ivEXT GLEW_GET_FUN(__glewProgramUniform3ivEXT)
+#define glProgramUniform3uiEXT GLEW_GET_FUN(__glewProgramUniform3uiEXT)
+#define glProgramUniform3uivEXT GLEW_GET_FUN(__glewProgramUniform3uivEXT)
+#define glProgramUniform4fEXT GLEW_GET_FUN(__glewProgramUniform4fEXT)
+#define glProgramUniform4fvEXT GLEW_GET_FUN(__glewProgramUniform4fvEXT)
+#define glProgramUniform4iEXT GLEW_GET_FUN(__glewProgramUniform4iEXT)
+#define glProgramUniform4ivEXT GLEW_GET_FUN(__glewProgramUniform4ivEXT)
+#define glProgramUniform4uiEXT GLEW_GET_FUN(__glewProgramUniform4uiEXT)
+#define glProgramUniform4uivEXT GLEW_GET_FUN(__glewProgramUniform4uivEXT)
+#define glProgramUniformMatrix2fvEXT GLEW_GET_FUN(__glewProgramUniformMatrix2fvEXT)
+#define glProgramUniformMatrix2x3fvEXT GLEW_GET_FUN(__glewProgramUniformMatrix2x3fvEXT)
+#define glProgramUniformMatrix2x4fvEXT GLEW_GET_FUN(__glewProgramUniformMatrix2x4fvEXT)
+#define glProgramUniformMatrix3fvEXT GLEW_GET_FUN(__glewProgramUniformMatrix3fvEXT)
+#define glProgramUniformMatrix3x2fvEXT GLEW_GET_FUN(__glewProgramUniformMatrix3x2fvEXT)
+#define glProgramUniformMatrix3x4fvEXT GLEW_GET_FUN(__glewProgramUniformMatrix3x4fvEXT)
+#define glProgramUniformMatrix4fvEXT GLEW_GET_FUN(__glewProgramUniformMatrix4fvEXT)
+#define glProgramUniformMatrix4x2fvEXT GLEW_GET_FUN(__glewProgramUniformMatrix4x2fvEXT)
+#define glProgramUniformMatrix4x3fvEXT GLEW_GET_FUN(__glewProgramUniformMatrix4x3fvEXT)
+#define glPushClientAttribDefaultEXT GLEW_GET_FUN(__glewPushClientAttribDefaultEXT)
+#define glTextureBufferEXT GLEW_GET_FUN(__glewTextureBufferEXT)
+#define glTextureImage1DEXT GLEW_GET_FUN(__glewTextureImage1DEXT)
+#define glTextureImage2DEXT GLEW_GET_FUN(__glewTextureImage2DEXT)
+#define glTextureImage3DEXT GLEW_GET_FUN(__glewTextureImage3DEXT)
+#define glTextureParameterIivEXT GLEW_GET_FUN(__glewTextureParameterIivEXT)
+#define glTextureParameterIuivEXT GLEW_GET_FUN(__glewTextureParameterIuivEXT)
+#define glTextureParameterfEXT GLEW_GET_FUN(__glewTextureParameterfEXT)
+#define glTextureParameterfvEXT GLEW_GET_FUN(__glewTextureParameterfvEXT)
+#define glTextureParameteriEXT GLEW_GET_FUN(__glewTextureParameteriEXT)
+#define glTextureParameterivEXT GLEW_GET_FUN(__glewTextureParameterivEXT)
+#define glTextureRenderbufferEXT GLEW_GET_FUN(__glewTextureRenderbufferEXT)
+#define glTextureSubImage1DEXT GLEW_GET_FUN(__glewTextureSubImage1DEXT)
+#define glTextureSubImage2DEXT GLEW_GET_FUN(__glewTextureSubImage2DEXT)
+#define glTextureSubImage3DEXT GLEW_GET_FUN(__glewTextureSubImage3DEXT)
+#define glUnmapNamedBufferEXT GLEW_GET_FUN(__glewUnmapNamedBufferEXT)
+#define glVertexArrayColorOffsetEXT GLEW_GET_FUN(__glewVertexArrayColorOffsetEXT)
+#define glVertexArrayEdgeFlagOffsetEXT GLEW_GET_FUN(__glewVertexArrayEdgeFlagOffsetEXT)
+#define glVertexArrayFogCoordOffsetEXT GLEW_GET_FUN(__glewVertexArrayFogCoordOffsetEXT)
+#define glVertexArrayIndexOffsetEXT GLEW_GET_FUN(__glewVertexArrayIndexOffsetEXT)
+#define glVertexArrayMultiTexCoordOffsetEXT GLEW_GET_FUN(__glewVertexArrayMultiTexCoordOffsetEXT)
+#define glVertexArrayNormalOffsetEXT GLEW_GET_FUN(__glewVertexArrayNormalOffsetEXT)
+#define glVertexArraySecondaryColorOffsetEXT GLEW_GET_FUN(__glewVertexArraySecondaryColorOffsetEXT)
+#define glVertexArrayTexCoordOffsetEXT GLEW_GET_FUN(__glewVertexArrayTexCoordOffsetEXT)
+#define glVertexArrayVertexAttribIOffsetEXT GLEW_GET_FUN(__glewVertexArrayVertexAttribIOffsetEXT)
+#define glVertexArrayVertexAttribOffsetEXT GLEW_GET_FUN(__glewVertexArrayVertexAttribOffsetEXT)
+#define glVertexArrayVertexOffsetEXT GLEW_GET_FUN(__glewVertexArrayVertexOffsetEXT)
+
+#define GLEW_EXT_direct_state_access GLEW_GET_VAR(__GLEW_EXT_direct_state_access)
+
+#endif /* !GL_EXT_direct_state_access */
+
+/* -------------------------- GL_EXT_draw_buffers2 ------------------------- */
+
+#if !defined(GL_EXT_draw_buffers2)
+#define GL_EXT_draw_buffers2 1
+
+typedef void (GLAPIENTRY * PFNGLCOLORMASKINDEXEDEXTPROC) (GLuint buf, GLboolean r, GLboolean g, GLboolean b, GLboolean a);
+typedef void (GLAPIENTRY * PFNGLDISABLEINDEXEDEXTPROC) (GLenum target, GLuint index);
+typedef void (GLAPIENTRY * PFNGLENABLEINDEXEDEXTPROC) (GLenum target, GLuint index);
+typedef void (GLAPIENTRY * PFNGLGETBOOLEANINDEXEDVEXTPROC) (GLenum value, GLuint index, GLboolean* data);
+typedef void (GLAPIENTRY * PFNGLGETINTEGERINDEXEDVEXTPROC) (GLenum value, GLuint index, GLint* data);
+typedef GLboolean (GLAPIENTRY * PFNGLISENABLEDINDEXEDEXTPROC) (GLenum target, GLuint index);
+
+#define glColorMaskIndexedEXT GLEW_GET_FUN(__glewColorMaskIndexedEXT)
+#define glDisableIndexedEXT GLEW_GET_FUN(__glewDisableIndexedEXT)
+#define glEnableIndexedEXT GLEW_GET_FUN(__glewEnableIndexedEXT)
+#define glGetBooleanIndexedvEXT GLEW_GET_FUN(__glewGetBooleanIndexedvEXT)
+#define glGetIntegerIndexedvEXT GLEW_GET_FUN(__glewGetIntegerIndexedvEXT)
+#define glIsEnabledIndexedEXT GLEW_GET_FUN(__glewIsEnabledIndexedEXT)
+
+#define GLEW_EXT_draw_buffers2 GLEW_GET_VAR(__GLEW_EXT_draw_buffers2)
+
+#endif /* !GL_EXT_draw_buffers2 */
+
+/* ------------------------- GL_EXT_draw_instanced ------------------------- */
+
+#if !defined(GL_EXT_draw_instanced)
+#define GL_EXT_draw_instanced 1
+
+typedef void (GLAPIENTRY * PFNGLDRAWARRAYSINSTANCEDEXTPROC) (GLenum mode, GLint start, GLsizei count, GLsizei primcount);
+typedef void (GLAPIENTRY * PFNGLDRAWELEMENTSINSTANCEDEXTPROC) (GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLsizei primcount);
+
+#define glDrawArraysInstancedEXT GLEW_GET_FUN(__glewDrawArraysInstancedEXT)
+#define glDrawElementsInstancedEXT GLEW_GET_FUN(__glewDrawElementsInstancedEXT)
+
+#define GLEW_EXT_draw_instanced GLEW_GET_VAR(__GLEW_EXT_draw_instanced)
+
+#endif /* !GL_EXT_draw_instanced */
+
+/* ----------------------- GL_EXT_draw_range_elements ---------------------- */
+
+#if !defined(GL_EXT_draw_range_elements)
+#define GL_EXT_draw_range_elements 1
+
+#define GL_MAX_ELEMENTS_VERTICES_EXT 0x80E8
+#define GL_MAX_ELEMENTS_INDICES_EXT 0x80E9
+
+typedef void (GLAPIENTRY * PFNGLDRAWRANGEELEMENTSEXTPROC) (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid *indices);
+
+#define glDrawRangeElementsEXT GLEW_GET_FUN(__glewDrawRangeElementsEXT)
+
+#define GLEW_EXT_draw_range_elements GLEW_GET_VAR(__GLEW_EXT_draw_range_elements)
+
+#endif /* !GL_EXT_draw_range_elements */
+
+/* ---------------------------- GL_EXT_fog_coord --------------------------- */
+
+#if !defined(GL_EXT_fog_coord)
+#define GL_EXT_fog_coord 1
+
+#define GL_FOG_COORDINATE_SOURCE_EXT 0x8450
+#define GL_FOG_COORDINATE_EXT 0x8451
+#define GL_FRAGMENT_DEPTH_EXT 0x8452
+#define GL_CURRENT_FOG_COORDINATE_EXT 0x8453
+#define GL_FOG_COORDINATE_ARRAY_TYPE_EXT 0x8454
+#define GL_FOG_COORDINATE_ARRAY_STRIDE_EXT 0x8455
+#define GL_FOG_COORDINATE_ARRAY_POINTER_EXT 0x8456
+#define GL_FOG_COORDINATE_ARRAY_EXT 0x8457
+
+typedef void (GLAPIENTRY * PFNGLFOGCOORDPOINTEREXTPROC) (GLenum type, GLsizei stride, const GLvoid *pointer);
+typedef void (GLAPIENTRY * PFNGLFOGCOORDDEXTPROC) (GLdouble coord);
+typedef void (GLAPIENTRY * PFNGLFOGCOORDDVEXTPROC) (const GLdouble *coord);
+typedef void (GLAPIENTRY * PFNGLFOGCOORDFEXTPROC) (GLfloat coord);
+typedef void (GLAPIENTRY * PFNGLFOGCOORDFVEXTPROC) (const GLfloat *coord);
+
+#define glFogCoordPointerEXT GLEW_GET_FUN(__glewFogCoordPointerEXT)
+#define glFogCoorddEXT GLEW_GET_FUN(__glewFogCoorddEXT)
+#define glFogCoorddvEXT GLEW_GET_FUN(__glewFogCoorddvEXT)
+#define glFogCoordfEXT GLEW_GET_FUN(__glewFogCoordfEXT)
+#define glFogCoordfvEXT GLEW_GET_FUN(__glewFogCoordfvEXT)
+
+#define GLEW_EXT_fog_coord GLEW_GET_VAR(__GLEW_EXT_fog_coord)
+
+#endif /* !GL_EXT_fog_coord */
+
+/* ------------------------ GL_EXT_fragment_lighting ----------------------- */
+
+#if !defined(GL_EXT_fragment_lighting)
+#define GL_EXT_fragment_lighting 1
+
+#define GL_FRAGMENT_LIGHTING_EXT 0x8400
+#define GL_FRAGMENT_COLOR_MATERIAL_EXT 0x8401
+#define GL_FRAGMENT_COLOR_MATERIAL_FACE_EXT 0x8402
+#define GL_FRAGMENT_COLOR_MATERIAL_PARAMETER_EXT 0x8403
+#define GL_MAX_FRAGMENT_LIGHTS_EXT 0x8404
+#define GL_MAX_ACTIVE_LIGHTS_EXT 0x8405
+#define GL_CURRENT_RASTER_NORMAL_EXT 0x8406
+#define GL_LIGHT_ENV_MODE_EXT 0x8407
+#define GL_FRAGMENT_LIGHT_MODEL_LOCAL_VIEWER_EXT 0x8408
+#define GL_FRAGMENT_LIGHT_MODEL_TWO_SIDE_EXT 0x8409
+#define GL_FRAGMENT_LIGHT_MODEL_AMBIENT_EXT 0x840A
+#define GL_FRAGMENT_LIGHT_MODEL_NORMAL_INTERPOLATION_EXT 0x840B
+#define GL_FRAGMENT_LIGHT0_EXT 0x840C
+#define GL_FRAGMENT_LIGHT7_EXT 0x8413
+
+typedef void (GLAPIENTRY * PFNGLFRAGMENTCOLORMATERIALEXTPROC) (GLenum face, GLenum mode);
+typedef void (GLAPIENTRY * PFNGLFRAGMENTLIGHTMODELFEXTPROC) (GLenum pname, GLfloat param);
+typedef void (GLAPIENTRY * PFNGLFRAGMENTLIGHTMODELFVEXTPROC) (GLenum pname, GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLFRAGMENTLIGHTMODELIEXTPROC) (GLenum pname, GLint param);
+typedef void (GLAPIENTRY * PFNGLFRAGMENTLIGHTMODELIVEXTPROC) (GLenum pname, GLint* params);
+typedef void (GLAPIENTRY * PFNGLFRAGMENTLIGHTFEXTPROC) (GLenum light, GLenum pname, GLfloat param);
+typedef void (GLAPIENTRY * PFNGLFRAGMENTLIGHTFVEXTPROC) (GLenum light, GLenum pname, GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLFRAGMENTLIGHTIEXTPROC) (GLenum light, GLenum pname, GLint param);
+typedef void (GLAPIENTRY * PFNGLFRAGMENTLIGHTIVEXTPROC) (GLenum light, GLenum pname, GLint* params);
+typedef void (GLAPIENTRY * PFNGLFRAGMENTMATERIALFEXTPROC) (GLenum face, GLenum pname, const GLfloat param);
+typedef void (GLAPIENTRY * PFNGLFRAGMENTMATERIALFVEXTPROC) (GLenum face, GLenum pname, const GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLFRAGMENTMATERIALIEXTPROC) (GLenum face, GLenum pname, const GLint param);
+typedef void (GLAPIENTRY * PFNGLFRAGMENTMATERIALIVEXTPROC) (GLenum face, GLenum pname, const GLint* params);
+typedef void (GLAPIENTRY * PFNGLGETFRAGMENTLIGHTFVEXTPROC) (GLenum light, GLenum pname, GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLGETFRAGMENTLIGHTIVEXTPROC) (GLenum light, GLenum pname, GLint* params);
+typedef void (GLAPIENTRY * PFNGLGETFRAGMENTMATERIALFVEXTPROC) (GLenum face, GLenum pname, const GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLGETFRAGMENTMATERIALIVEXTPROC) (GLenum face, GLenum pname, const GLint* params);
+typedef void (GLAPIENTRY * PFNGLLIGHTENVIEXTPROC) (GLenum pname, GLint param);
+
+#define glFragmentColorMaterialEXT GLEW_GET_FUN(__glewFragmentColorMaterialEXT)
+#define glFragmentLightModelfEXT GLEW_GET_FUN(__glewFragmentLightModelfEXT)
+#define glFragmentLightModelfvEXT GLEW_GET_FUN(__glewFragmentLightModelfvEXT)
+#define glFragmentLightModeliEXT GLEW_GET_FUN(__glewFragmentLightModeliEXT)
+#define glFragmentLightModelivEXT GLEW_GET_FUN(__glewFragmentLightModelivEXT)
+#define glFragmentLightfEXT GLEW_GET_FUN(__glewFragmentLightfEXT)
+#define glFragmentLightfvEXT GLEW_GET_FUN(__glewFragmentLightfvEXT)
+#define glFragmentLightiEXT GLEW_GET_FUN(__glewFragmentLightiEXT)
+#define glFragmentLightivEXT GLEW_GET_FUN(__glewFragmentLightivEXT)
+#define glFragmentMaterialfEXT GLEW_GET_FUN(__glewFragmentMaterialfEXT)
+#define glFragmentMaterialfvEXT GLEW_GET_FUN(__glewFragmentMaterialfvEXT)
+#define glFragmentMaterialiEXT GLEW_GET_FUN(__glewFragmentMaterialiEXT)
+#define glFragmentMaterialivEXT GLEW_GET_FUN(__glewFragmentMaterialivEXT)
+#define glGetFragmentLightfvEXT GLEW_GET_FUN(__glewGetFragmentLightfvEXT)
+#define glGetFragmentLightivEXT GLEW_GET_FUN(__glewGetFragmentLightivEXT)
+#define glGetFragmentMaterialfvEXT GLEW_GET_FUN(__glewGetFragmentMaterialfvEXT)
+#define glGetFragmentMaterialivEXT GLEW_GET_FUN(__glewGetFragmentMaterialivEXT)
+#define glLightEnviEXT GLEW_GET_FUN(__glewLightEnviEXT)
+
+#define GLEW_EXT_fragment_lighting GLEW_GET_VAR(__GLEW_EXT_fragment_lighting)
+
+#endif /* !GL_EXT_fragment_lighting */
+
+/* ------------------------ GL_EXT_framebuffer_blit ------------------------ */
+
+#if !defined(GL_EXT_framebuffer_blit)
+#define GL_EXT_framebuffer_blit 1
+
+#define GL_DRAW_FRAMEBUFFER_BINDING_EXT 0x8CA6
+#define GL_READ_FRAMEBUFFER_EXT 0x8CA8
+#define GL_DRAW_FRAMEBUFFER_EXT 0x8CA9
+#define GL_READ_FRAMEBUFFER_BINDING_EXT 0x8CAA
+
+typedef void (GLAPIENTRY * PFNGLBLITFRAMEBUFFEREXTPROC) (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter);
+
+#define glBlitFramebufferEXT GLEW_GET_FUN(__glewBlitFramebufferEXT)
+
+#define GLEW_EXT_framebuffer_blit GLEW_GET_VAR(__GLEW_EXT_framebuffer_blit)
+
+#endif /* !GL_EXT_framebuffer_blit */
+
+/* --------------------- GL_EXT_framebuffer_multisample -------------------- */
+
+#if !defined(GL_EXT_framebuffer_multisample)
+#define GL_EXT_framebuffer_multisample 1
+
+#define GL_RENDERBUFFER_SAMPLES_EXT 0x8CAB
+#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT 0x8D56
+#define GL_MAX_SAMPLES_EXT 0x8D57
+
+typedef void (GLAPIENTRY * PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
+
+#define glRenderbufferStorageMultisampleEXT GLEW_GET_FUN(__glewRenderbufferStorageMultisampleEXT)
+
+#define GLEW_EXT_framebuffer_multisample GLEW_GET_VAR(__GLEW_EXT_framebuffer_multisample)
+
+#endif /* !GL_EXT_framebuffer_multisample */
+
+/* --------------- GL_EXT_framebuffer_multisample_blit_scaled -------------- */
+
+#if !defined(GL_EXT_framebuffer_multisample_blit_scaled)
+#define GL_EXT_framebuffer_multisample_blit_scaled 1
+
+#define GL_SCALED_RESOLVE_FASTEST_EXT 0x90BA
+#define GL_SCALED_RESOLVE_NICEST_EXT 0x90BB
+
+#define GLEW_EXT_framebuffer_multisample_blit_scaled GLEW_GET_VAR(__GLEW_EXT_framebuffer_multisample_blit_scaled)
+
+#endif /* !GL_EXT_framebuffer_multisample_blit_scaled */
+
+/* ----------------------- GL_EXT_framebuffer_object ----------------------- */
+
+#if !defined(GL_EXT_framebuffer_object)
+#define GL_EXT_framebuffer_object 1
+
+#define GL_INVALID_FRAMEBUFFER_OPERATION_EXT 0x0506
+#define GL_MAX_RENDERBUFFER_SIZE_EXT 0x84E8
+#define GL_FRAMEBUFFER_BINDING_EXT 0x8CA6
+#define GL_RENDERBUFFER_BINDING_EXT 0x8CA7
+#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_EXT 0x8CD0
+#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_EXT 0x8CD1
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL_EXT 0x8CD2
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE_EXT 0x8CD3
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_3D_ZOFFSET_EXT 0x8CD4
+#define GL_FRAMEBUFFER_COMPLETE_EXT 0x8CD5
+#define GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT 0x8CD6
+#define GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT 0x8CD7
+#define GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT 0x8CD9
+#define GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT 0x8CDA
+#define GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT 0x8CDB
+#define GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT 0x8CDC
+#define GL_FRAMEBUFFER_UNSUPPORTED_EXT 0x8CDD
+#define GL_MAX_COLOR_ATTACHMENTS_EXT 0x8CDF
+#define GL_COLOR_ATTACHMENT0_EXT 0x8CE0
+#define GL_COLOR_ATTACHMENT1_EXT 0x8CE1
+#define GL_COLOR_ATTACHMENT2_EXT 0x8CE2
+#define GL_COLOR_ATTACHMENT3_EXT 0x8CE3
+#define GL_COLOR_ATTACHMENT4_EXT 0x8CE4
+#define GL_COLOR_ATTACHMENT5_EXT 0x8CE5
+#define GL_COLOR_ATTACHMENT6_EXT 0x8CE6
+#define GL_COLOR_ATTACHMENT7_EXT 0x8CE7
+#define GL_COLOR_ATTACHMENT8_EXT 0x8CE8
+#define GL_COLOR_ATTACHMENT9_EXT 0x8CE9
+#define GL_COLOR_ATTACHMENT10_EXT 0x8CEA
+#define GL_COLOR_ATTACHMENT11_EXT 0x8CEB
+#define GL_COLOR_ATTACHMENT12_EXT 0x8CEC
+#define GL_COLOR_ATTACHMENT13_EXT 0x8CED
+#define GL_COLOR_ATTACHMENT14_EXT 0x8CEE
+#define GL_COLOR_ATTACHMENT15_EXT 0x8CEF
+#define GL_DEPTH_ATTACHMENT_EXT 0x8D00
+#define GL_STENCIL_ATTACHMENT_EXT 0x8D20
+#define GL_FRAMEBUFFER_EXT 0x8D40
+#define GL_RENDERBUFFER_EXT 0x8D41
+#define GL_RENDERBUFFER_WIDTH_EXT 0x8D42
+#define GL_RENDERBUFFER_HEIGHT_EXT 0x8D43
+#define GL_RENDERBUFFER_INTERNAL_FORMAT_EXT 0x8D44
+#define GL_STENCIL_INDEX1_EXT 0x8D46
+#define GL_STENCIL_INDEX4_EXT 0x8D47
+#define GL_STENCIL_INDEX8_EXT 0x8D48
+#define GL_STENCIL_INDEX16_EXT 0x8D49
+#define GL_RENDERBUFFER_RED_SIZE_EXT 0x8D50
+#define GL_RENDERBUFFER_GREEN_SIZE_EXT 0x8D51
+#define GL_RENDERBUFFER_BLUE_SIZE_EXT 0x8D52
+#define GL_RENDERBUFFER_ALPHA_SIZE_EXT 0x8D53
+#define GL_RENDERBUFFER_DEPTH_SIZE_EXT 0x8D54
+#define GL_RENDERBUFFER_STENCIL_SIZE_EXT 0x8D55
+
+typedef void (GLAPIENTRY * PFNGLBINDFRAMEBUFFEREXTPROC) (GLenum target, GLuint framebuffer);
+typedef void (GLAPIENTRY * PFNGLBINDRENDERBUFFEREXTPROC) (GLenum target, GLuint renderbuffer);
+typedef GLenum (GLAPIENTRY * PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC) (GLenum target);
+typedef void (GLAPIENTRY * PFNGLDELETEFRAMEBUFFERSEXTPROC) (GLsizei n, const GLuint* framebuffers);
+typedef void (GLAPIENTRY * PFNGLDELETERENDERBUFFERSEXTPROC) (GLsizei n, const GLuint* renderbuffers);
+typedef void (GLAPIENTRY * PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC) (GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer);
+typedef void (GLAPIENTRY * PFNGLFRAMEBUFFERTEXTURE1DEXTPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
+typedef void (GLAPIENTRY * PFNGLFRAMEBUFFERTEXTURE2DEXTPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
+typedef void (GLAPIENTRY * PFNGLFRAMEBUFFERTEXTURE3DEXTPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset);
+typedef void (GLAPIENTRY * PFNGLGENFRAMEBUFFERSEXTPROC) (GLsizei n, GLuint* framebuffers);
+typedef void (GLAPIENTRY * PFNGLGENRENDERBUFFERSEXTPROC) (GLsizei n, GLuint* renderbuffers);
+typedef void (GLAPIENTRY * PFNGLGENERATEMIPMAPEXTPROC) (GLenum target);
+typedef void (GLAPIENTRY * PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC) (GLenum target, GLenum attachment, GLenum pname, GLint* params);
+typedef void (GLAPIENTRY * PFNGLGETRENDERBUFFERPARAMETERIVEXTPROC) (GLenum target, GLenum pname, GLint* params);
+typedef GLboolean (GLAPIENTRY * PFNGLISFRAMEBUFFEREXTPROC) (GLuint framebuffer);
+typedef GLboolean (GLAPIENTRY * PFNGLISRENDERBUFFEREXTPROC) (GLuint renderbuffer);
+typedef void (GLAPIENTRY * PFNGLRENDERBUFFERSTORAGEEXTPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
+
+#define glBindFramebufferEXT GLEW_GET_FUN(__glewBindFramebufferEXT)
+#define glBindRenderbufferEXT GLEW_GET_FUN(__glewBindRenderbufferEXT)
+#define glCheckFramebufferStatusEXT GLEW_GET_FUN(__glewCheckFramebufferStatusEXT)
+#define glDeleteFramebuffersEXT GLEW_GET_FUN(__glewDeleteFramebuffersEXT)
+#define glDeleteRenderbuffersEXT GLEW_GET_FUN(__glewDeleteRenderbuffersEXT)
+#define glFramebufferRenderbufferEXT GLEW_GET_FUN(__glewFramebufferRenderbufferEXT)
+#define glFramebufferTexture1DEXT GLEW_GET_FUN(__glewFramebufferTexture1DEXT)
+#define glFramebufferTexture2DEXT GLEW_GET_FUN(__glewFramebufferTexture2DEXT)
+#define glFramebufferTexture3DEXT GLEW_GET_FUN(__glewFramebufferTexture3DEXT)
+#define glGenFramebuffersEXT GLEW_GET_FUN(__glewGenFramebuffersEXT)
+#define glGenRenderbuffersEXT GLEW_GET_FUN(__glewGenRenderbuffersEXT)
+#define glGenerateMipmapEXT GLEW_GET_FUN(__glewGenerateMipmapEXT)
+#define glGetFramebufferAttachmentParameterivEXT GLEW_GET_FUN(__glewGetFramebufferAttachmentParameterivEXT)
+#define glGetRenderbufferParameterivEXT GLEW_GET_FUN(__glewGetRenderbufferParameterivEXT)
+#define glIsFramebufferEXT GLEW_GET_FUN(__glewIsFramebufferEXT)
+#define glIsRenderbufferEXT GLEW_GET_FUN(__glewIsRenderbufferEXT)
+#define glRenderbufferStorageEXT GLEW_GET_FUN(__glewRenderbufferStorageEXT)
+
+#define GLEW_EXT_framebuffer_object GLEW_GET_VAR(__GLEW_EXT_framebuffer_object)
+
+#endif /* !GL_EXT_framebuffer_object */
+
+/* ------------------------ GL_EXT_framebuffer_sRGB ------------------------ */
+
+#if !defined(GL_EXT_framebuffer_sRGB)
+#define GL_EXT_framebuffer_sRGB 1
+
+#define GL_FRAMEBUFFER_SRGB_EXT 0x8DB9
+#define GL_FRAMEBUFFER_SRGB_CAPABLE_EXT 0x8DBA
+
+#define GLEW_EXT_framebuffer_sRGB GLEW_GET_VAR(__GLEW_EXT_framebuffer_sRGB)
+
+#endif /* !GL_EXT_framebuffer_sRGB */
+
+/* ------------------------ GL_EXT_geometry_shader4 ------------------------ */
+
+#if !defined(GL_EXT_geometry_shader4)
+#define GL_EXT_geometry_shader4 1
+
+#define GL_LINES_ADJACENCY_EXT 0xA
+#define GL_LINE_STRIP_ADJACENCY_EXT 0xB
+#define GL_TRIANGLES_ADJACENCY_EXT 0xC
+#define GL_TRIANGLE_STRIP_ADJACENCY_EXT 0xD
+#define GL_PROGRAM_POINT_SIZE_EXT 0x8642
+#define GL_MAX_VARYING_COMPONENTS_EXT 0x8B4B
+#define GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS_EXT 0x8C29
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER_EXT 0x8CD4
+#define GL_FRAMEBUFFER_ATTACHMENT_LAYERED_EXT 0x8DA7
+#define GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_EXT 0x8DA8
+#define GL_FRAMEBUFFER_INCOMPLETE_LAYER_COUNT_EXT 0x8DA9
+#define GL_GEOMETRY_SHADER_EXT 0x8DD9
+#define GL_GEOMETRY_VERTICES_OUT_EXT 0x8DDA
+#define GL_GEOMETRY_INPUT_TYPE_EXT 0x8DDB
+#define GL_GEOMETRY_OUTPUT_TYPE_EXT 0x8DDC
+#define GL_MAX_GEOMETRY_VARYING_COMPONENTS_EXT 0x8DDD
+#define GL_MAX_VERTEX_VARYING_COMPONENTS_EXT 0x8DDE
+#define GL_MAX_GEOMETRY_UNIFORM_COMPONENTS_EXT 0x8DDF
+#define GL_MAX_GEOMETRY_OUTPUT_VERTICES_EXT 0x8DE0
+#define GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS_EXT 0x8DE1
+
+typedef void (GLAPIENTRY * PFNGLFRAMEBUFFERTEXTUREEXTPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level);
+typedef void (GLAPIENTRY * PFNGLFRAMEBUFFERTEXTUREFACEEXTPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level, GLenum face);
+typedef void (GLAPIENTRY * PFNGLPROGRAMPARAMETERIEXTPROC) (GLuint program, GLenum pname, GLint value);
+
+#define glFramebufferTextureEXT GLEW_GET_FUN(__glewFramebufferTextureEXT)
+#define glFramebufferTextureFaceEXT GLEW_GET_FUN(__glewFramebufferTextureFaceEXT)
+#define glProgramParameteriEXT GLEW_GET_FUN(__glewProgramParameteriEXT)
+
+#define GLEW_EXT_geometry_shader4 GLEW_GET_VAR(__GLEW_EXT_geometry_shader4)
+
+#endif /* !GL_EXT_geometry_shader4 */
+
+/* --------------------- GL_EXT_gpu_program_parameters --------------------- */
+
+#if !defined(GL_EXT_gpu_program_parameters)
+#define GL_EXT_gpu_program_parameters 1
+
+typedef void (GLAPIENTRY * PFNGLPROGRAMENVPARAMETERS4FVEXTPROC) (GLenum target, GLuint index, GLsizei count, const GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLPROGRAMLOCALPARAMETERS4FVEXTPROC) (GLenum target, GLuint index, GLsizei count, const GLfloat* params);
+
+#define glProgramEnvParameters4fvEXT GLEW_GET_FUN(__glewProgramEnvParameters4fvEXT)
+#define glProgramLocalParameters4fvEXT GLEW_GET_FUN(__glewProgramLocalParameters4fvEXT)
+
+#define GLEW_EXT_gpu_program_parameters GLEW_GET_VAR(__GLEW_EXT_gpu_program_parameters)
+
+#endif /* !GL_EXT_gpu_program_parameters */
+
+/* --------------------------- GL_EXT_gpu_shader4 -------------------------- */
+
+#if !defined(GL_EXT_gpu_shader4)
+#define GL_EXT_gpu_shader4 1
+
+#define GL_VERTEX_ATTRIB_ARRAY_INTEGER_EXT 0x88FD
+#define GL_SAMPLER_1D_ARRAY_EXT 0x8DC0
+#define GL_SAMPLER_2D_ARRAY_EXT 0x8DC1
+#define GL_SAMPLER_BUFFER_EXT 0x8DC2
+#define GL_SAMPLER_1D_ARRAY_SHADOW_EXT 0x8DC3
+#define GL_SAMPLER_2D_ARRAY_SHADOW_EXT 0x8DC4
+#define GL_SAMPLER_CUBE_SHADOW_EXT 0x8DC5
+#define GL_UNSIGNED_INT_VEC2_EXT 0x8DC6
+#define GL_UNSIGNED_INT_VEC3_EXT 0x8DC7
+#define GL_UNSIGNED_INT_VEC4_EXT 0x8DC8
+#define GL_INT_SAMPLER_1D_EXT 0x8DC9
+#define GL_INT_SAMPLER_2D_EXT 0x8DCA
+#define GL_INT_SAMPLER_3D_EXT 0x8DCB
+#define GL_INT_SAMPLER_CUBE_EXT 0x8DCC
+#define GL_INT_SAMPLER_2D_RECT_EXT 0x8DCD
+#define GL_INT_SAMPLER_1D_ARRAY_EXT 0x8DCE
+#define GL_INT_SAMPLER_2D_ARRAY_EXT 0x8DCF
+#define GL_INT_SAMPLER_BUFFER_EXT 0x8DD0
+#define GL_UNSIGNED_INT_SAMPLER_1D_EXT 0x8DD1
+#define GL_UNSIGNED_INT_SAMPLER_2D_EXT 0x8DD2
+#define GL_UNSIGNED_INT_SAMPLER_3D_EXT 0x8DD3
+#define GL_UNSIGNED_INT_SAMPLER_CUBE_EXT 0x8DD4
+#define GL_UNSIGNED_INT_SAMPLER_2D_RECT_EXT 0x8DD5
+#define GL_UNSIGNED_INT_SAMPLER_1D_ARRAY_EXT 0x8DD6
+#define GL_UNSIGNED_INT_SAMPLER_2D_ARRAY_EXT 0x8DD7
+#define GL_UNSIGNED_INT_SAMPLER_BUFFER_EXT 0x8DD8
+
+typedef void (GLAPIENTRY * PFNGLBINDFRAGDATALOCATIONEXTPROC) (GLuint program, GLuint color, const GLchar *name);
+typedef GLint (GLAPIENTRY * PFNGLGETFRAGDATALOCATIONEXTPROC) (GLuint program, const GLchar *name);
+typedef void (GLAPIENTRY * PFNGLGETUNIFORMUIVEXTPROC) (GLuint program, GLint location, GLuint *params);
+typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBIIVEXTPROC) (GLuint index, GLenum pname, GLint *params);
+typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBIUIVEXTPROC) (GLuint index, GLenum pname, GLuint *params);
+typedef void (GLAPIENTRY * PFNGLUNIFORM1UIEXTPROC) (GLint location, GLuint v0);
+typedef void (GLAPIENTRY * PFNGLUNIFORM1UIVEXTPROC) (GLint location, GLsizei count, const GLuint *value);
+typedef void (GLAPIENTRY * PFNGLUNIFORM2UIEXTPROC) (GLint location, GLuint v0, GLuint v1);
+typedef void (GLAPIENTRY * PFNGLUNIFORM2UIVEXTPROC) (GLint location, GLsizei count, const GLuint *value);
+typedef void (GLAPIENTRY * PFNGLUNIFORM3UIEXTPROC) (GLint location, GLuint v0, GLuint v1, GLuint v2);
+typedef void (GLAPIENTRY * PFNGLUNIFORM3UIVEXTPROC) (GLint location, GLsizei count, const GLuint *value);
+typedef void (GLAPIENTRY * PFNGLUNIFORM4UIEXTPROC) (GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3);
+typedef void (GLAPIENTRY * PFNGLUNIFORM4UIVEXTPROC) (GLint location, GLsizei count, const GLuint *value);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI1IEXTPROC) (GLuint index, GLint x);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI1IVEXTPROC) (GLuint index, const GLint *v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI1UIEXTPROC) (GLuint index, GLuint x);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI1UIVEXTPROC) (GLuint index, const GLuint *v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI2IEXTPROC) (GLuint index, GLint x, GLint y);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI2IVEXTPROC) (GLuint index, const GLint *v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI2UIEXTPROC) (GLuint index, GLuint x, GLuint y);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI2UIVEXTPROC) (GLuint index, const GLuint *v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI3IEXTPROC) (GLuint index, GLint x, GLint y, GLint z);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI3IVEXTPROC) (GLuint index, const GLint *v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI3UIEXTPROC) (GLuint index, GLuint x, GLuint y, GLuint z);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI3UIVEXTPROC) (GLuint index, const GLuint *v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI4BVEXTPROC) (GLuint index, const GLbyte *v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI4IEXTPROC) (GLuint index, GLint x, GLint y, GLint z, GLint w);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI4IVEXTPROC) (GLuint index, const GLint *v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI4SVEXTPROC) (GLuint index, const GLshort *v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI4UBVEXTPROC) (GLuint index, const GLubyte *v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI4UIEXTPROC) (GLuint index, GLuint x, GLuint y, GLuint z, GLuint w);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI4UIVEXTPROC) (GLuint index, const GLuint *v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI4USVEXTPROC) (GLuint index, const GLushort *v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBIPOINTEREXTPROC) (GLuint index, GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);
+
+#define glBindFragDataLocationEXT GLEW_GET_FUN(__glewBindFragDataLocationEXT)
+#define glGetFragDataLocationEXT GLEW_GET_FUN(__glewGetFragDataLocationEXT)
+#define glGetUniformuivEXT GLEW_GET_FUN(__glewGetUniformuivEXT)
+#define glGetVertexAttribIivEXT GLEW_GET_FUN(__glewGetVertexAttribIivEXT)
+#define glGetVertexAttribIuivEXT GLEW_GET_FUN(__glewGetVertexAttribIuivEXT)
+#define glUniform1uiEXT GLEW_GET_FUN(__glewUniform1uiEXT)
+#define glUniform1uivEXT GLEW_GET_FUN(__glewUniform1uivEXT)
+#define glUniform2uiEXT GLEW_GET_FUN(__glewUniform2uiEXT)
+#define glUniform2uivEXT GLEW_GET_FUN(__glewUniform2uivEXT)
+#define glUniform3uiEXT GLEW_GET_FUN(__glewUniform3uiEXT)
+#define glUniform3uivEXT GLEW_GET_FUN(__glewUniform3uivEXT)
+#define glUniform4uiEXT GLEW_GET_FUN(__glewUniform4uiEXT)
+#define glUniform4uivEXT GLEW_GET_FUN(__glewUniform4uivEXT)
+#define glVertexAttribI1iEXT GLEW_GET_FUN(__glewVertexAttribI1iEXT)
+#define glVertexAttribI1ivEXT GLEW_GET_FUN(__glewVertexAttribI1ivEXT)
+#define glVertexAttribI1uiEXT GLEW_GET_FUN(__glewVertexAttribI1uiEXT)
+#define glVertexAttribI1uivEXT GLEW_GET_FUN(__glewVertexAttribI1uivEXT)
+#define glVertexAttribI2iEXT GLEW_GET_FUN(__glewVertexAttribI2iEXT)
+#define glVertexAttribI2ivEXT GLEW_GET_FUN(__glewVertexAttribI2ivEXT)
+#define glVertexAttribI2uiEXT GLEW_GET_FUN(__glewVertexAttribI2uiEXT)
+#define glVertexAttribI2uivEXT GLEW_GET_FUN(__glewVertexAttribI2uivEXT)
+#define glVertexAttribI3iEXT GLEW_GET_FUN(__glewVertexAttribI3iEXT)
+#define glVertexAttribI3ivEXT GLEW_GET_FUN(__glewVertexAttribI3ivEXT)
+#define glVertexAttribI3uiEXT GLEW_GET_FUN(__glewVertexAttribI3uiEXT)
+#define glVertexAttribI3uivEXT GLEW_GET_FUN(__glewVertexAttribI3uivEXT)
+#define glVertexAttribI4bvEXT GLEW_GET_FUN(__glewVertexAttribI4bvEXT)
+#define glVertexAttribI4iEXT GLEW_GET_FUN(__glewVertexAttribI4iEXT)
+#define glVertexAttribI4ivEXT GLEW_GET_FUN(__glewVertexAttribI4ivEXT)
+#define glVertexAttribI4svEXT GLEW_GET_FUN(__glewVertexAttribI4svEXT)
+#define glVertexAttribI4ubvEXT GLEW_GET_FUN(__glewVertexAttribI4ubvEXT)
+#define glVertexAttribI4uiEXT GLEW_GET_FUN(__glewVertexAttribI4uiEXT)
+#define glVertexAttribI4uivEXT GLEW_GET_FUN(__glewVertexAttribI4uivEXT)
+#define glVertexAttribI4usvEXT GLEW_GET_FUN(__glewVertexAttribI4usvEXT)
+#define glVertexAttribIPointerEXT GLEW_GET_FUN(__glewVertexAttribIPointerEXT)
+
+#define GLEW_EXT_gpu_shader4 GLEW_GET_VAR(__GLEW_EXT_gpu_shader4)
+
+#endif /* !GL_EXT_gpu_shader4 */
+
+/* ---------------------------- GL_EXT_histogram --------------------------- */
+
+#if !defined(GL_EXT_histogram)
+#define GL_EXT_histogram 1
+
+#define GL_HISTOGRAM_EXT 0x8024
+#define GL_PROXY_HISTOGRAM_EXT 0x8025
+#define GL_HISTOGRAM_WIDTH_EXT 0x8026
+#define GL_HISTOGRAM_FORMAT_EXT 0x8027
+#define GL_HISTOGRAM_RED_SIZE_EXT 0x8028
+#define GL_HISTOGRAM_GREEN_SIZE_EXT 0x8029
+#define GL_HISTOGRAM_BLUE_SIZE_EXT 0x802A
+#define GL_HISTOGRAM_ALPHA_SIZE_EXT 0x802B
+#define GL_HISTOGRAM_LUMINANCE_SIZE_EXT 0x802C
+#define GL_HISTOGRAM_SINK_EXT 0x802D
+#define GL_MINMAX_EXT 0x802E
+#define GL_MINMAX_FORMAT_EXT 0x802F
+#define GL_MINMAX_SINK_EXT 0x8030
+
+typedef void (GLAPIENTRY * PFNGLGETHISTOGRAMEXTPROC) (GLenum target, GLboolean reset, GLenum format, GLenum type, void* values);
+typedef void (GLAPIENTRY * PFNGLGETHISTOGRAMPARAMETERFVEXTPROC) (GLenum target, GLenum pname, GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLGETHISTOGRAMPARAMETERIVEXTPROC) (GLenum target, GLenum pname, GLint* params);
+typedef void (GLAPIENTRY * PFNGLGETMINMAXEXTPROC) (GLenum target, GLboolean reset, GLenum format, GLenum type, void* values);
+typedef void (GLAPIENTRY * PFNGLGETMINMAXPARAMETERFVEXTPROC) (GLenum target, GLenum pname, GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLGETMINMAXPARAMETERIVEXTPROC) (GLenum target, GLenum pname, GLint* params);
+typedef void (GLAPIENTRY * PFNGLHISTOGRAMEXTPROC) (GLenum target, GLsizei width, GLenum internalformat, GLboolean sink);
+typedef void (GLAPIENTRY * PFNGLMINMAXEXTPROC) (GLenum target, GLenum internalformat, GLboolean sink);
+typedef void (GLAPIENTRY * PFNGLRESETHISTOGRAMEXTPROC) (GLenum target);
+typedef void (GLAPIENTRY * PFNGLRESETMINMAXEXTPROC) (GLenum target);
+
+#define glGetHistogramEXT GLEW_GET_FUN(__glewGetHistogramEXT)
+#define glGetHistogramParameterfvEXT GLEW_GET_FUN(__glewGetHistogramParameterfvEXT)
+#define glGetHistogramParameterivEXT GLEW_GET_FUN(__glewGetHistogramParameterivEXT)
+#define glGetMinmaxEXT GLEW_GET_FUN(__glewGetMinmaxEXT)
+#define glGetMinmaxParameterfvEXT GLEW_GET_FUN(__glewGetMinmaxParameterfvEXT)
+#define glGetMinmaxParameterivEXT GLEW_GET_FUN(__glewGetMinmaxParameterivEXT)
+#define glHistogramEXT GLEW_GET_FUN(__glewHistogramEXT)
+#define glMinmaxEXT GLEW_GET_FUN(__glewMinmaxEXT)
+#define glResetHistogramEXT GLEW_GET_FUN(__glewResetHistogramEXT)
+#define glResetMinmaxEXT GLEW_GET_FUN(__glewResetMinmaxEXT)
+
+#define GLEW_EXT_histogram GLEW_GET_VAR(__GLEW_EXT_histogram)
+
+#endif /* !GL_EXT_histogram */
+
+/* ----------------------- GL_EXT_index_array_formats ---------------------- */
+
+#if !defined(GL_EXT_index_array_formats)
+#define GL_EXT_index_array_formats 1
+
+#define GLEW_EXT_index_array_formats GLEW_GET_VAR(__GLEW_EXT_index_array_formats)
+
+#endif /* !GL_EXT_index_array_formats */
+
+/* --------------------------- GL_EXT_index_func --------------------------- */
+
+#if !defined(GL_EXT_index_func)
+#define GL_EXT_index_func 1
+
+typedef void (GLAPIENTRY * PFNGLINDEXFUNCEXTPROC) (GLenum func, GLfloat ref);
+
+#define glIndexFuncEXT GLEW_GET_FUN(__glewIndexFuncEXT)
+
+#define GLEW_EXT_index_func GLEW_GET_VAR(__GLEW_EXT_index_func)
+
+#endif /* !GL_EXT_index_func */
+
+/* ------------------------- GL_EXT_index_material ------------------------- */
+
+#if !defined(GL_EXT_index_material)
+#define GL_EXT_index_material 1
+
+typedef void (GLAPIENTRY * PFNGLINDEXMATERIALEXTPROC) (GLenum face, GLenum mode);
+
+#define glIndexMaterialEXT GLEW_GET_FUN(__glewIndexMaterialEXT)
+
+#define GLEW_EXT_index_material GLEW_GET_VAR(__GLEW_EXT_index_material)
+
+#endif /* !GL_EXT_index_material */
+
+/* -------------------------- GL_EXT_index_texture ------------------------- */
+
+#if !defined(GL_EXT_index_texture)
+#define GL_EXT_index_texture 1
+
+#define GLEW_EXT_index_texture GLEW_GET_VAR(__GLEW_EXT_index_texture)
+
+#endif /* !GL_EXT_index_texture */
+
+/* -------------------------- GL_EXT_light_texture ------------------------- */
+
+#if !defined(GL_EXT_light_texture)
+#define GL_EXT_light_texture 1
+
+#define GL_FRAGMENT_MATERIAL_EXT 0x8349
+#define GL_FRAGMENT_NORMAL_EXT 0x834A
+#define GL_FRAGMENT_COLOR_EXT 0x834C
+#define GL_ATTENUATION_EXT 0x834D
+#define GL_SHADOW_ATTENUATION_EXT 0x834E
+#define GL_TEXTURE_APPLICATION_MODE_EXT 0x834F
+#define GL_TEXTURE_LIGHT_EXT 0x8350
+#define GL_TEXTURE_MATERIAL_FACE_EXT 0x8351
+#define GL_TEXTURE_MATERIAL_PARAMETER_EXT 0x8352
+#define GL_FRAGMENT_DEPTH_EXT 0x8452
+
+typedef void (GLAPIENTRY * PFNGLAPPLYTEXTUREEXTPROC) (GLenum mode);
+typedef void (GLAPIENTRY * PFNGLTEXTURELIGHTEXTPROC) (GLenum pname);
+typedef void (GLAPIENTRY * PFNGLTEXTUREMATERIALEXTPROC) (GLenum face, GLenum mode);
+
+#define glApplyTextureEXT GLEW_GET_FUN(__glewApplyTextureEXT)
+#define glTextureLightEXT GLEW_GET_FUN(__glewTextureLightEXT)
+#define glTextureMaterialEXT GLEW_GET_FUN(__glewTextureMaterialEXT)
+
+#define GLEW_EXT_light_texture GLEW_GET_VAR(__GLEW_EXT_light_texture)
+
+#endif /* !GL_EXT_light_texture */
+
+/* ------------------------- GL_EXT_misc_attribute ------------------------- */
+
+#if !defined(GL_EXT_misc_attribute)
+#define GL_EXT_misc_attribute 1
+
+#define GLEW_EXT_misc_attribute GLEW_GET_VAR(__GLEW_EXT_misc_attribute)
+
+#endif /* !GL_EXT_misc_attribute */
+
+/* ------------------------ GL_EXT_multi_draw_arrays ----------------------- */
+
+#if !defined(GL_EXT_multi_draw_arrays)
+#define GL_EXT_multi_draw_arrays 1
+
+typedef void (GLAPIENTRY * PFNGLMULTIDRAWARRAYSEXTPROC) (GLenum mode, const GLint* first, const GLsizei *count, GLsizei primcount);
+typedef void (GLAPIENTRY * PFNGLMULTIDRAWELEMENTSEXTPROC) (GLenum mode, GLsizei* count, GLenum type, const GLvoid **indices, GLsizei primcount);
+
+#define glMultiDrawArraysEXT GLEW_GET_FUN(__glewMultiDrawArraysEXT)
+#define glMultiDrawElementsEXT GLEW_GET_FUN(__glewMultiDrawElementsEXT)
+
+#define GLEW_EXT_multi_draw_arrays GLEW_GET_VAR(__GLEW_EXT_multi_draw_arrays)
+
+#endif /* !GL_EXT_multi_draw_arrays */
+
+/* --------------------------- GL_EXT_multisample -------------------------- */
+
+#if !defined(GL_EXT_multisample)
+#define GL_EXT_multisample 1
+
+#define GL_MULTISAMPLE_EXT 0x809D
+#define GL_SAMPLE_ALPHA_TO_MASK_EXT 0x809E
+#define GL_SAMPLE_ALPHA_TO_ONE_EXT 0x809F
+#define GL_SAMPLE_MASK_EXT 0x80A0
+#define GL_1PASS_EXT 0x80A1
+#define GL_2PASS_0_EXT 0x80A2
+#define GL_2PASS_1_EXT 0x80A3
+#define GL_4PASS_0_EXT 0x80A4
+#define GL_4PASS_1_EXT 0x80A5
+#define GL_4PASS_2_EXT 0x80A6
+#define GL_4PASS_3_EXT 0x80A7
+#define GL_SAMPLE_BUFFERS_EXT 0x80A8
+#define GL_SAMPLES_EXT 0x80A9
+#define GL_SAMPLE_MASK_VALUE_EXT 0x80AA
+#define GL_SAMPLE_MASK_INVERT_EXT 0x80AB
+#define GL_SAMPLE_PATTERN_EXT 0x80AC
+#define GL_MULTISAMPLE_BIT_EXT 0x20000000
+
+typedef void (GLAPIENTRY * PFNGLSAMPLEMASKEXTPROC) (GLclampf value, GLboolean invert);
+typedef void (GLAPIENTRY * PFNGLSAMPLEPATTERNEXTPROC) (GLenum pattern);
+
+#define glSampleMaskEXT GLEW_GET_FUN(__glewSampleMaskEXT)
+#define glSamplePatternEXT GLEW_GET_FUN(__glewSamplePatternEXT)
+
+#define GLEW_EXT_multisample GLEW_GET_VAR(__GLEW_EXT_multisample)
+
+#endif /* !GL_EXT_multisample */
+
+/* ---------------------- GL_EXT_packed_depth_stencil ---------------------- */
+
+#if !defined(GL_EXT_packed_depth_stencil)
+#define GL_EXT_packed_depth_stencil 1
+
+#define GL_DEPTH_STENCIL_EXT 0x84F9
+#define GL_UNSIGNED_INT_24_8_EXT 0x84FA
+#define GL_DEPTH24_STENCIL8_EXT 0x88F0
+#define GL_TEXTURE_STENCIL_SIZE_EXT 0x88F1
+
+#define GLEW_EXT_packed_depth_stencil GLEW_GET_VAR(__GLEW_EXT_packed_depth_stencil)
+
+#endif /* !GL_EXT_packed_depth_stencil */
+
+/* -------------------------- GL_EXT_packed_float -------------------------- */
+
+#if !defined(GL_EXT_packed_float)
+#define GL_EXT_packed_float 1
+
+#define GL_R11F_G11F_B10F_EXT 0x8C3A
+#define GL_UNSIGNED_INT_10F_11F_11F_REV_EXT 0x8C3B
+#define GL_RGBA_SIGNED_COMPONENTS_EXT 0x8C3C
+
+#define GLEW_EXT_packed_float GLEW_GET_VAR(__GLEW_EXT_packed_float)
+
+#endif /* !GL_EXT_packed_float */
+
+/* -------------------------- GL_EXT_packed_pixels ------------------------- */
+
+#if !defined(GL_EXT_packed_pixels)
+#define GL_EXT_packed_pixels 1
+
+#define GL_UNSIGNED_BYTE_3_3_2_EXT 0x8032
+#define GL_UNSIGNED_SHORT_4_4_4_4_EXT 0x8033
+#define GL_UNSIGNED_SHORT_5_5_5_1_EXT 0x8034
+#define GL_UNSIGNED_INT_8_8_8_8_EXT 0x8035
+#define GL_UNSIGNED_INT_10_10_10_2_EXT 0x8036
+
+#define GLEW_EXT_packed_pixels GLEW_GET_VAR(__GLEW_EXT_packed_pixels)
+
+#endif /* !GL_EXT_packed_pixels */
+
+/* ------------------------ GL_EXT_paletted_texture ------------------------ */
+
+#if !defined(GL_EXT_paletted_texture)
+#define GL_EXT_paletted_texture 1
+
+#define GL_TEXTURE_1D 0x0DE0
+#define GL_TEXTURE_2D 0x0DE1
+#define GL_PROXY_TEXTURE_1D 0x8063
+#define GL_PROXY_TEXTURE_2D 0x8064
+#define GL_TEXTURE_3D_EXT 0x806F
+#define GL_PROXY_TEXTURE_3D_EXT 0x8070
+#define GL_COLOR_TABLE_FORMAT_EXT 0x80D8
+#define GL_COLOR_TABLE_WIDTH_EXT 0x80D9
+#define GL_COLOR_TABLE_RED_SIZE_EXT 0x80DA
+#define GL_COLOR_TABLE_GREEN_SIZE_EXT 0x80DB
+#define GL_COLOR_TABLE_BLUE_SIZE_EXT 0x80DC
+#define GL_COLOR_TABLE_ALPHA_SIZE_EXT 0x80DD
+#define GL_COLOR_TABLE_LUMINANCE_SIZE_EXT 0x80DE
+#define GL_COLOR_TABLE_INTENSITY_SIZE_EXT 0x80DF
+#define GL_COLOR_INDEX1_EXT 0x80E2
+#define GL_COLOR_INDEX2_EXT 0x80E3
+#define GL_COLOR_INDEX4_EXT 0x80E4
+#define GL_COLOR_INDEX8_EXT 0x80E5
+#define GL_COLOR_INDEX12_EXT 0x80E6
+#define GL_COLOR_INDEX16_EXT 0x80E7
+#define GL_TEXTURE_INDEX_SIZE_EXT 0x80ED
+#define GL_TEXTURE_CUBE_MAP_ARB 0x8513
+#define GL_PROXY_TEXTURE_CUBE_MAP_ARB 0x851B
+
+typedef void (GLAPIENTRY * PFNGLCOLORTABLEEXTPROC) (GLenum target, GLenum internalFormat, GLsizei width, GLenum format, GLenum type, const void* data);
+typedef void (GLAPIENTRY * PFNGLGETCOLORTABLEEXTPROC) (GLenum target, GLenum format, GLenum type, void* data);
+typedef void (GLAPIENTRY * PFNGLGETCOLORTABLEPARAMETERFVEXTPROC) (GLenum target, GLenum pname, GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLGETCOLORTABLEPARAMETERIVEXTPROC) (GLenum target, GLenum pname, GLint* params);
+
+#define glColorTableEXT GLEW_GET_FUN(__glewColorTableEXT)
+#define glGetColorTableEXT GLEW_GET_FUN(__glewGetColorTableEXT)
+#define glGetColorTableParameterfvEXT GLEW_GET_FUN(__glewGetColorTableParameterfvEXT)
+#define glGetColorTableParameterivEXT GLEW_GET_FUN(__glewGetColorTableParameterivEXT)
+
+#define GLEW_EXT_paletted_texture GLEW_GET_VAR(__GLEW_EXT_paletted_texture)
+
+#endif /* !GL_EXT_paletted_texture */
+
+/* ----------------------- GL_EXT_pixel_buffer_object ---------------------- */
+
+#if !defined(GL_EXT_pixel_buffer_object)
+#define GL_EXT_pixel_buffer_object 1
+
+#define GL_PIXEL_PACK_BUFFER_EXT 0x88EB
+#define GL_PIXEL_UNPACK_BUFFER_EXT 0x88EC
+#define GL_PIXEL_PACK_BUFFER_BINDING_EXT 0x88ED
+#define GL_PIXEL_UNPACK_BUFFER_BINDING_EXT 0x88EF
+
+#define GLEW_EXT_pixel_buffer_object GLEW_GET_VAR(__GLEW_EXT_pixel_buffer_object)
+
+#endif /* !GL_EXT_pixel_buffer_object */
+
+/* ------------------------- GL_EXT_pixel_transform ------------------------ */
+
+#if !defined(GL_EXT_pixel_transform)
+#define GL_EXT_pixel_transform 1
+
+#define GL_PIXEL_TRANSFORM_2D_EXT 0x8330
+#define GL_PIXEL_MAG_FILTER_EXT 0x8331
+#define GL_PIXEL_MIN_FILTER_EXT 0x8332
+#define GL_PIXEL_CUBIC_WEIGHT_EXT 0x8333
+#define GL_CUBIC_EXT 0x8334
+#define GL_AVERAGE_EXT 0x8335
+#define GL_PIXEL_TRANSFORM_2D_STACK_DEPTH_EXT 0x8336
+#define GL_MAX_PIXEL_TRANSFORM_2D_STACK_DEPTH_EXT 0x8337
+#define GL_PIXEL_TRANSFORM_2D_MATRIX_EXT 0x8338
+
+typedef void (GLAPIENTRY * PFNGLGETPIXELTRANSFORMPARAMETERFVEXTPROC) (GLenum target, GLenum pname, const GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLGETPIXELTRANSFORMPARAMETERIVEXTPROC) (GLenum target, GLenum pname, const GLint* params);
+typedef void (GLAPIENTRY * PFNGLPIXELTRANSFORMPARAMETERFEXTPROC) (GLenum target, GLenum pname, const GLfloat param);
+typedef void (GLAPIENTRY * PFNGLPIXELTRANSFORMPARAMETERFVEXTPROC) (GLenum target, GLenum pname, const GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLPIXELTRANSFORMPARAMETERIEXTPROC) (GLenum target, GLenum pname, const GLint param);
+typedef void (GLAPIENTRY * PFNGLPIXELTRANSFORMPARAMETERIVEXTPROC) (GLenum target, GLenum pname, const GLint* params);
+
+#define glGetPixelTransformParameterfvEXT GLEW_GET_FUN(__glewGetPixelTransformParameterfvEXT)
+#define glGetPixelTransformParameterivEXT GLEW_GET_FUN(__glewGetPixelTransformParameterivEXT)
+#define glPixelTransformParameterfEXT GLEW_GET_FUN(__glewPixelTransformParameterfEXT)
+#define glPixelTransformParameterfvEXT GLEW_GET_FUN(__glewPixelTransformParameterfvEXT)
+#define glPixelTransformParameteriEXT GLEW_GET_FUN(__glewPixelTransformParameteriEXT)
+#define glPixelTransformParameterivEXT GLEW_GET_FUN(__glewPixelTransformParameterivEXT)
+
+#define GLEW_EXT_pixel_transform GLEW_GET_VAR(__GLEW_EXT_pixel_transform)
+
+#endif /* !GL_EXT_pixel_transform */
+
+/* ------------------- GL_EXT_pixel_transform_color_table ------------------ */
+
+#if !defined(GL_EXT_pixel_transform_color_table)
+#define GL_EXT_pixel_transform_color_table 1
+
+#define GLEW_EXT_pixel_transform_color_table GLEW_GET_VAR(__GLEW_EXT_pixel_transform_color_table)
+
+#endif /* !GL_EXT_pixel_transform_color_table */
+
+/* ------------------------ GL_EXT_point_parameters ------------------------ */
+
+#if !defined(GL_EXT_point_parameters)
+#define GL_EXT_point_parameters 1
+
+#define GL_POINT_SIZE_MIN_EXT 0x8126
+#define GL_POINT_SIZE_MAX_EXT 0x8127
+#define GL_POINT_FADE_THRESHOLD_SIZE_EXT 0x8128
+#define GL_DISTANCE_ATTENUATION_EXT 0x8129
+
+typedef void (GLAPIENTRY * PFNGLPOINTPARAMETERFEXTPROC) (GLenum pname, GLfloat param);
+typedef void (GLAPIENTRY * PFNGLPOINTPARAMETERFVEXTPROC) (GLenum pname, const GLfloat* params);
+
+#define glPointParameterfEXT GLEW_GET_FUN(__glewPointParameterfEXT)
+#define glPointParameterfvEXT GLEW_GET_FUN(__glewPointParameterfvEXT)
+
+#define GLEW_EXT_point_parameters GLEW_GET_VAR(__GLEW_EXT_point_parameters)
+
+#endif /* !GL_EXT_point_parameters */
+
+/* ------------------------- GL_EXT_polygon_offset ------------------------- */
+
+#if !defined(GL_EXT_polygon_offset)
+#define GL_EXT_polygon_offset 1
+
+#define GL_POLYGON_OFFSET_EXT 0x8037
+#define GL_POLYGON_OFFSET_FACTOR_EXT 0x8038
+#define GL_POLYGON_OFFSET_BIAS_EXT 0x8039
+
+typedef void (GLAPIENTRY * PFNGLPOLYGONOFFSETEXTPROC) (GLfloat factor, GLfloat bias);
+
+#define glPolygonOffsetEXT GLEW_GET_FUN(__glewPolygonOffsetEXT)
+
+#define GLEW_EXT_polygon_offset GLEW_GET_VAR(__GLEW_EXT_polygon_offset)
+
+#endif /* !GL_EXT_polygon_offset */
+
+/* ------------------------ GL_EXT_provoking_vertex ------------------------ */
+
+#if !defined(GL_EXT_provoking_vertex)
+#define GL_EXT_provoking_vertex 1
+
+#define GL_QUADS_FOLLOW_PROVOKING_VERTEX_CONVENTION_EXT 0x8E4C
+#define GL_FIRST_VERTEX_CONVENTION_EXT 0x8E4D
+#define GL_LAST_VERTEX_CONVENTION_EXT 0x8E4E
+#define GL_PROVOKING_VERTEX_EXT 0x8E4F
+
+typedef void (GLAPIENTRY * PFNGLPROVOKINGVERTEXEXTPROC) (GLenum mode);
+
+#define glProvokingVertexEXT GLEW_GET_FUN(__glewProvokingVertexEXT)
+
+#define GLEW_EXT_provoking_vertex GLEW_GET_VAR(__GLEW_EXT_provoking_vertex)
+
+#endif /* !GL_EXT_provoking_vertex */
+
+/* ------------------------- GL_EXT_rescale_normal ------------------------- */
+
+#if !defined(GL_EXT_rescale_normal)
+#define GL_EXT_rescale_normal 1
+
+#define GL_RESCALE_NORMAL_EXT 0x803A
+
+#define GLEW_EXT_rescale_normal GLEW_GET_VAR(__GLEW_EXT_rescale_normal)
+
+#endif /* !GL_EXT_rescale_normal */
+
+/* -------------------------- GL_EXT_scene_marker -------------------------- */
+
+#if !defined(GL_EXT_scene_marker)
+#define GL_EXT_scene_marker 1
+
+typedef void (GLAPIENTRY * PFNGLBEGINSCENEEXTPROC) (void);
+typedef void (GLAPIENTRY * PFNGLENDSCENEEXTPROC) (void);
+
+#define glBeginSceneEXT GLEW_GET_FUN(__glewBeginSceneEXT)
+#define glEndSceneEXT GLEW_GET_FUN(__glewEndSceneEXT)
+
+#define GLEW_EXT_scene_marker GLEW_GET_VAR(__GLEW_EXT_scene_marker)
+
+#endif /* !GL_EXT_scene_marker */
+
+/* ------------------------- GL_EXT_secondary_color ------------------------ */
+
+#if !defined(GL_EXT_secondary_color)
+#define GL_EXT_secondary_color 1
+
+#define GL_COLOR_SUM_EXT 0x8458
+#define GL_CURRENT_SECONDARY_COLOR_EXT 0x8459
+#define GL_SECONDARY_COLOR_ARRAY_SIZE_EXT 0x845A
+#define GL_SECONDARY_COLOR_ARRAY_TYPE_EXT 0x845B
+#define GL_SECONDARY_COLOR_ARRAY_STRIDE_EXT 0x845C
+#define GL_SECONDARY_COLOR_ARRAY_POINTER_EXT 0x845D
+#define GL_SECONDARY_COLOR_ARRAY_EXT 0x845E
+
+typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3BEXTPROC) (GLbyte red, GLbyte green, GLbyte blue);
+typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3BVEXTPROC) (const GLbyte *v);
+typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3DEXTPROC) (GLdouble red, GLdouble green, GLdouble blue);
+typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3DVEXTPROC) (const GLdouble *v);
+typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3FEXTPROC) (GLfloat red, GLfloat green, GLfloat blue);
+typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3FVEXTPROC) (const GLfloat *v);
+typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3IEXTPROC) (GLint red, GLint green, GLint blue);
+typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3IVEXTPROC) (const GLint *v);
+typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3SEXTPROC) (GLshort red, GLshort green, GLshort blue);
+typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3SVEXTPROC) (const GLshort *v);
+typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3UBEXTPROC) (GLubyte red, GLubyte green, GLubyte blue);
+typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3UBVEXTPROC) (const GLubyte *v);
+typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3UIEXTPROC) (GLuint red, GLuint green, GLuint blue);
+typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3UIVEXTPROC) (const GLuint *v);
+typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3USEXTPROC) (GLushort red, GLushort green, GLushort blue);
+typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3USVEXTPROC) (const GLushort *v);
+typedef void (GLAPIENTRY * PFNGLSECONDARYCOLORPOINTEREXTPROC) (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);
+
+#define glSecondaryColor3bEXT GLEW_GET_FUN(__glewSecondaryColor3bEXT)
+#define glSecondaryColor3bvEXT GLEW_GET_FUN(__glewSecondaryColor3bvEXT)
+#define glSecondaryColor3dEXT GLEW_GET_FUN(__glewSecondaryColor3dEXT)
+#define glSecondaryColor3dvEXT GLEW_GET_FUN(__glewSecondaryColor3dvEXT)
+#define glSecondaryColor3fEXT GLEW_GET_FUN(__glewSecondaryColor3fEXT)
+#define glSecondaryColor3fvEXT GLEW_GET_FUN(__glewSecondaryColor3fvEXT)
+#define glSecondaryColor3iEXT GLEW_GET_FUN(__glewSecondaryColor3iEXT)
+#define glSecondaryColor3ivEXT GLEW_GET_FUN(__glewSecondaryColor3ivEXT)
+#define glSecondaryColor3sEXT GLEW_GET_FUN(__glewSecondaryColor3sEXT)
+#define glSecondaryColor3svEXT GLEW_GET_FUN(__glewSecondaryColor3svEXT)
+#define glSecondaryColor3ubEXT GLEW_GET_FUN(__glewSecondaryColor3ubEXT)
+#define glSecondaryColor3ubvEXT GLEW_GET_FUN(__glewSecondaryColor3ubvEXT)
+#define glSecondaryColor3uiEXT GLEW_GET_FUN(__glewSecondaryColor3uiEXT)
+#define glSecondaryColor3uivEXT GLEW_GET_FUN(__glewSecondaryColor3uivEXT)
+#define glSecondaryColor3usEXT GLEW_GET_FUN(__glewSecondaryColor3usEXT)
+#define glSecondaryColor3usvEXT GLEW_GET_FUN(__glewSecondaryColor3usvEXT)
+#define glSecondaryColorPointerEXT GLEW_GET_FUN(__glewSecondaryColorPointerEXT)
+
+#define GLEW_EXT_secondary_color GLEW_GET_VAR(__GLEW_EXT_secondary_color)
+
+#endif /* !GL_EXT_secondary_color */
+
+#if 0 // NOTE jwilkins: there is an inconsistency between the ES and Non-ES versions of this extension??
+/* --------------------- GL_EXT_separate_shader_objects -------------------- */
+
+#if !defined(GL_EXT_separate_shader_objects)
+#define GL_EXT_separate_shader_objects 1
+
+#define GL_ACTIVE_PROGRAM_EXT 0x8B8D
+
+typedef void (GLAPIENTRY * PFNGLACTIVEPROGRAMEXTPROC) (GLuint program);
+typedef GLuint (GLAPIENTRY * PFNGLCREATESHADERPROGRAMEXTPROC) (GLenum type, const char* string);
+typedef void (GLAPIENTRY * PFNGLUSESHADERPROGRAMEXTPROC) (GLenum type, GLuint program);
+
+#define glActiveProgramEXT GLEW_GET_FUN(__glewActiveProgramEXT)
+#define glCreateShaderProgramEXT GLEW_GET_FUN(__glewCreateShaderProgramEXT)
+#define glUseShaderProgramEXT GLEW_GET_FUN(__glewUseShaderProgramEXT)
+
+#define GLEW_EXT_separate_shader_objects GLEW_GET_VAR(__GLEW_EXT_separate_shader_objects)
+
+#endif /* !GL_EXT_separate_shader_objects */
+#endif // XXX
+
+/* --------------------- GL_EXT_separate_specular_color -------------------- */
+
+#if !defined(GL_EXT_separate_specular_color)
+#define GL_EXT_separate_specular_color 1
+
+#define GL_LIGHT_MODEL_COLOR_CONTROL_EXT 0x81F8
+#define GL_SINGLE_COLOR_EXT 0x81F9
+#define GL_SEPARATE_SPECULAR_COLOR_EXT 0x81FA
+
+#define GLEW_EXT_separate_specular_color GLEW_GET_VAR(__GLEW_EXT_separate_specular_color)
+
+#endif /* !GL_EXT_separate_specular_color */
+
+/* --------------------- GL_EXT_shader_image_load_store -------------------- */
+
+#if !defined(GL_EXT_shader_image_load_store)
+#define GL_EXT_shader_image_load_store 1
+
+#define GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT_EXT 0x00000001
+#define GL_ELEMENT_ARRAY_BARRIER_BIT_EXT 0x00000002
+#define GL_UNIFORM_BARRIER_BIT_EXT 0x00000004
+#define GL_TEXTURE_FETCH_BARRIER_BIT_EXT 0x00000008
+#define GL_SHADER_IMAGE_ACCESS_BARRIER_BIT_EXT 0x00000020
+#define GL_COMMAND_BARRIER_BIT_EXT 0x00000040
+#define GL_PIXEL_BUFFER_BARRIER_BIT_EXT 0x00000080
+#define GL_TEXTURE_UPDATE_BARRIER_BIT_EXT 0x00000100
+#define GL_BUFFER_UPDATE_BARRIER_BIT_EXT 0x00000200
+#define GL_FRAMEBUFFER_BARRIER_BIT_EXT 0x00000400
+#define GL_TRANSFORM_FEEDBACK_BARRIER_BIT_EXT 0x00000800
+#define GL_ATOMIC_COUNTER_BARRIER_BIT_EXT 0x00001000
+#define GL_MAX_IMAGE_UNITS_EXT 0x8F38
+#define GL_MAX_COMBINED_IMAGE_UNITS_AND_FRAGMENT_OUTPUTS_EXT 0x8F39
+#define GL_IMAGE_BINDING_NAME_EXT 0x8F3A
+#define GL_IMAGE_BINDING_LEVEL_EXT 0x8F3B
+#define GL_IMAGE_BINDING_LAYERED_EXT 0x8F3C
+#define GL_IMAGE_BINDING_LAYER_EXT 0x8F3D
+#define GL_IMAGE_BINDING_ACCESS_EXT 0x8F3E
+#define GL_IMAGE_1D_EXT 0x904C
+#define GL_IMAGE_2D_EXT 0x904D
+#define GL_IMAGE_3D_EXT 0x904E
+#define GL_IMAGE_2D_RECT_EXT 0x904F
+#define GL_IMAGE_CUBE_EXT 0x9050
+#define GL_IMAGE_BUFFER_EXT 0x9051
+#define GL_IMAGE_1D_ARRAY_EXT 0x9052
+#define GL_IMAGE_2D_ARRAY_EXT 0x9053
+#define GL_IMAGE_CUBE_MAP_ARRAY_EXT 0x9054
+#define GL_IMAGE_2D_MULTISAMPLE_EXT 0x9055
+#define GL_IMAGE_2D_MULTISAMPLE_ARRAY_EXT 0x9056
+#define GL_INT_IMAGE_1D_EXT 0x9057
+#define GL_INT_IMAGE_2D_EXT 0x9058
+#define GL_INT_IMAGE_3D_EXT 0x9059
+#define GL_INT_IMAGE_2D_RECT_EXT 0x905A
+#define GL_INT_IMAGE_CUBE_EXT 0x905B
+#define GL_INT_IMAGE_BUFFER_EXT 0x905C
+#define GL_INT_IMAGE_1D_ARRAY_EXT 0x905D
+#define GL_INT_IMAGE_2D_ARRAY_EXT 0x905E
+#define GL_INT_IMAGE_CUBE_MAP_ARRAY_EXT 0x905F
+#define GL_INT_IMAGE_2D_MULTISAMPLE_EXT 0x9060
+#define GL_INT_IMAGE_2D_MULTISAMPLE_ARRAY_EXT 0x9061
+#define GL_UNSIGNED_INT_IMAGE_1D_EXT 0x9062
+#define GL_UNSIGNED_INT_IMAGE_2D_EXT 0x9063
+#define GL_UNSIGNED_INT_IMAGE_3D_EXT 0x9064
+#define GL_UNSIGNED_INT_IMAGE_2D_RECT_EXT 0x9065
+#define GL_UNSIGNED_INT_IMAGE_CUBE_EXT 0x9066
+#define GL_UNSIGNED_INT_IMAGE_BUFFER_EXT 0x9067
+#define GL_UNSIGNED_INT_IMAGE_1D_ARRAY_EXT 0x9068
+#define GL_UNSIGNED_INT_IMAGE_2D_ARRAY_EXT 0x9069
+#define GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY_EXT 0x906A
+#define GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE_EXT 0x906B
+#define GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE_ARRAY_EXT 0x906C
+#define GL_MAX_IMAGE_SAMPLES_EXT 0x906D
+#define GL_IMAGE_BINDING_FORMAT_EXT 0x906E
+#define GL_ALL_BARRIER_BITS_EXT 0xFFFFFFFF
+
+typedef void (GLAPIENTRY * PFNGLBINDIMAGETEXTUREEXTPROC) (GLuint index, GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum access, GLint format);
+typedef void (GLAPIENTRY * PFNGLMEMORYBARRIEREXTPROC) (GLbitfield barriers);
+
+#define glBindImageTextureEXT GLEW_GET_FUN(__glewBindImageTextureEXT)
+#define glMemoryBarrierEXT GLEW_GET_FUN(__glewMemoryBarrierEXT)
+
+#define GLEW_EXT_shader_image_load_store GLEW_GET_VAR(__GLEW_EXT_shader_image_load_store)
+
+#endif /* !GL_EXT_shader_image_load_store */
+
+/* -------------------------- GL_EXT_shadow_funcs -------------------------- */
+
+#if !defined(GL_EXT_shadow_funcs)
+#define GL_EXT_shadow_funcs 1
+
+#define GLEW_EXT_shadow_funcs GLEW_GET_VAR(__GLEW_EXT_shadow_funcs)
+
+#endif /* !GL_EXT_shadow_funcs */
+
+/* --------------------- GL_EXT_shared_texture_palette --------------------- */
+
+#if !defined(GL_EXT_shared_texture_palette)
+#define GL_EXT_shared_texture_palette 1
+
+#define GL_SHARED_TEXTURE_PALETTE_EXT 0x81FB
+
+#define GLEW_EXT_shared_texture_palette GLEW_GET_VAR(__GLEW_EXT_shared_texture_palette)
+
+#endif /* !GL_EXT_shared_texture_palette */
+
+/* ------------------------ GL_EXT_stencil_clear_tag ----------------------- */
+
+#if !defined(GL_EXT_stencil_clear_tag)
+#define GL_EXT_stencil_clear_tag 1
+
+#define GL_STENCIL_TAG_BITS_EXT 0x88F2
+#define GL_STENCIL_CLEAR_TAG_VALUE_EXT 0x88F3
+
+#define GLEW_EXT_stencil_clear_tag GLEW_GET_VAR(__GLEW_EXT_stencil_clear_tag)
+
+#endif /* !GL_EXT_stencil_clear_tag */
+
+/* ------------------------ GL_EXT_stencil_two_side ------------------------ */
+
+#if !defined(GL_EXT_stencil_two_side)
+#define GL_EXT_stencil_two_side 1
+
+#define GL_STENCIL_TEST_TWO_SIDE_EXT 0x8910
+#define GL_ACTIVE_STENCIL_FACE_EXT 0x8911
+
+typedef void (GLAPIENTRY * PFNGLACTIVESTENCILFACEEXTPROC) (GLenum face);
+
+#define glActiveStencilFaceEXT GLEW_GET_FUN(__glewActiveStencilFaceEXT)
+
+#define GLEW_EXT_stencil_two_side GLEW_GET_VAR(__GLEW_EXT_stencil_two_side)
+
+#endif /* !GL_EXT_stencil_two_side */
+
+/* -------------------------- GL_EXT_stencil_wrap -------------------------- */
+
+#if !defined(GL_EXT_stencil_wrap)
+#define GL_EXT_stencil_wrap 1
+
+#define GL_INCR_WRAP_EXT 0x8507
+#define GL_DECR_WRAP_EXT 0x8508
+
+#define GLEW_EXT_stencil_wrap GLEW_GET_VAR(__GLEW_EXT_stencil_wrap)
+
+#endif /* !GL_EXT_stencil_wrap */
+
+/* --------------------------- GL_EXT_subtexture --------------------------- */
+
+#if !defined(GL_EXT_subtexture)
+#define GL_EXT_subtexture 1
+
+typedef void (GLAPIENTRY * PFNGLTEXSUBIMAGE1DEXTPROC) (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const void* pixels);
+typedef void (GLAPIENTRY * PFNGLTEXSUBIMAGE2DEXTPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void* pixels);
+typedef void (GLAPIENTRY * PFNGLTEXSUBIMAGE3DEXTPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void* pixels);
+
+#define glTexSubImage1DEXT GLEW_GET_FUN(__glewTexSubImage1DEXT)
+#define glTexSubImage2DEXT GLEW_GET_FUN(__glewTexSubImage2DEXT)
+#define glTexSubImage3DEXT GLEW_GET_FUN(__glewTexSubImage3DEXT)
+
+#define GLEW_EXT_subtexture GLEW_GET_VAR(__GLEW_EXT_subtexture)
+
+#endif /* !GL_EXT_subtexture */
+
+/* ----------------------------- GL_EXT_texture ---------------------------- */
+
+#if !defined(GL_EXT_texture)
+#define GL_EXT_texture 1
+
+#define GL_ALPHA4_EXT 0x803B
+#define GL_ALPHA8_EXT 0x803C
+#define GL_ALPHA12_EXT 0x803D
+#define GL_ALPHA16_EXT 0x803E
+#define GL_LUMINANCE4_EXT 0x803F
+#define GL_LUMINANCE8_EXT 0x8040
+#define GL_LUMINANCE12_EXT 0x8041
+#define GL_LUMINANCE16_EXT 0x8042
+#define GL_LUMINANCE4_ALPHA4_EXT 0x8043
+#define GL_LUMINANCE6_ALPHA2_EXT 0x8044
+#define GL_LUMINANCE8_ALPHA8_EXT 0x8045
+#define GL_LUMINANCE12_ALPHA4_EXT 0x8046
+#define GL_LUMINANCE12_ALPHA12_EXT 0x8047
+#define GL_LUMINANCE16_ALPHA16_EXT 0x8048
+#define GL_INTENSITY_EXT 0x8049
+#define GL_INTENSITY4_EXT 0x804A
+#define GL_INTENSITY8_EXT 0x804B
+#define GL_INTENSITY12_EXT 0x804C
+#define GL_INTENSITY16_EXT 0x804D
+#define GL_RGB2_EXT 0x804E
+#define GL_RGB4_EXT 0x804F
+#define GL_RGB5_EXT 0x8050
+#define GL_RGB8_EXT 0x8051
+#define GL_RGB10_EXT 0x8052
+#define GL_RGB12_EXT 0x8053
+#define GL_RGB16_EXT 0x8054
+#define GL_RGBA2_EXT 0x8055
+#define GL_RGBA4_EXT 0x8056
+#define GL_RGB5_A1_EXT 0x8057
+#define GL_RGBA8_EXT 0x8058
+#define GL_RGB10_A2_EXT 0x8059
+#define GL_RGBA12_EXT 0x805A
+#define GL_RGBA16_EXT 0x805B
+#define GL_TEXTURE_RED_SIZE_EXT 0x805C
+#define GL_TEXTURE_GREEN_SIZE_EXT 0x805D
+#define GL_TEXTURE_BLUE_SIZE_EXT 0x805E
+#define GL_TEXTURE_ALPHA_SIZE_EXT 0x805F
+#define GL_TEXTURE_LUMINANCE_SIZE_EXT 0x8060
+#define GL_TEXTURE_INTENSITY_SIZE_EXT 0x8061
+#define GL_REPLACE_EXT 0x8062
+#define GL_PROXY_TEXTURE_1D_EXT 0x8063
+#define GL_PROXY_TEXTURE_2D_EXT 0x8064
+
+#define GLEW_EXT_texture GLEW_GET_VAR(__GLEW_EXT_texture)
+
+#endif /* !GL_EXT_texture */
+
+/* ---------------------------- GL_EXT_texture3D --------------------------- */
+
+#if !defined(GL_EXT_texture3D)
+#define GL_EXT_texture3D 1
+
+#define GL_PACK_SKIP_IMAGES_EXT 0x806B
+#define GL_PACK_IMAGE_HEIGHT_EXT 0x806C
+#define GL_UNPACK_SKIP_IMAGES_EXT 0x806D
+#define GL_UNPACK_IMAGE_HEIGHT_EXT 0x806E
+#define GL_TEXTURE_3D_EXT 0x806F
+#define GL_PROXY_TEXTURE_3D_EXT 0x8070
+#define GL_TEXTURE_DEPTH_EXT 0x8071
+#define GL_TEXTURE_WRAP_R_EXT 0x8072
+#define GL_MAX_3D_TEXTURE_SIZE_EXT 0x8073
+
+typedef void (GLAPIENTRY * PFNGLTEXIMAGE3DEXTPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void* pixels);
+
+#define glTexImage3DEXT GLEW_GET_FUN(__glewTexImage3DEXT)
+
+#define GLEW_EXT_texture3D GLEW_GET_VAR(__GLEW_EXT_texture3D)
+
+#endif /* !GL_EXT_texture3D */
+
+/* -------------------------- GL_EXT_texture_array ------------------------- */
+
+#if !defined(GL_EXT_texture_array)
+#define GL_EXT_texture_array 1
+
+#define GL_COMPARE_REF_DEPTH_TO_TEXTURE_EXT 0x884E
+#define GL_MAX_ARRAY_TEXTURE_LAYERS_EXT 0x88FF
+#define GL_TEXTURE_1D_ARRAY_EXT 0x8C18
+#define GL_PROXY_TEXTURE_1D_ARRAY_EXT 0x8C19
+#define GL_TEXTURE_2D_ARRAY_EXT 0x8C1A
+#define GL_PROXY_TEXTURE_2D_ARRAY_EXT 0x8C1B
+#define GL_TEXTURE_BINDING_1D_ARRAY_EXT 0x8C1C
+#define GL_TEXTURE_BINDING_2D_ARRAY_EXT 0x8C1D
+
+typedef void (GLAPIENTRY * PFNGLFRAMEBUFFERTEXTURELAYEREXTPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer);
+
+#define glFramebufferTextureLayerEXT GLEW_GET_FUN(__glewFramebufferTextureLayerEXT)
+
+#define GLEW_EXT_texture_array GLEW_GET_VAR(__GLEW_EXT_texture_array)
+
+#endif /* !GL_EXT_texture_array */
+
+/* ---------------------- GL_EXT_texture_buffer_object --------------------- */
+
+#if !defined(GL_EXT_texture_buffer_object)
+#define GL_EXT_texture_buffer_object 1
+
+#define GL_TEXTURE_BUFFER_EXT 0x8C2A
+#define GL_MAX_TEXTURE_BUFFER_SIZE_EXT 0x8C2B
+#define GL_TEXTURE_BINDING_BUFFER_EXT 0x8C2C
+#define GL_TEXTURE_BUFFER_DATA_STORE_BINDING_EXT 0x8C2D
+#define GL_TEXTURE_BUFFER_FORMAT_EXT 0x8C2E
+
+typedef void (GLAPIENTRY * PFNGLTEXBUFFEREXTPROC) (GLenum target, GLenum internalformat, GLuint buffer);
+
+#define glTexBufferEXT GLEW_GET_FUN(__glewTexBufferEXT)
+
+#define GLEW_EXT_texture_buffer_object GLEW_GET_VAR(__GLEW_EXT_texture_buffer_object)
+
+#endif /* !GL_EXT_texture_buffer_object */
+
+/* -------------------- GL_EXT_texture_compression_dxt1 -------------------- */
+
+#if !defined(GL_EXT_texture_compression_dxt1)
+#define GL_EXT_texture_compression_dxt1 1
+
+#define GL_COMPRESSED_RGB_S3TC_DXT1_EXT 0x83F0
+#define GL_COMPRESSED_RGBA_S3TC_DXT1_EXT 0x83F1
+
+#define GLEW_EXT_texture_compression_dxt1 GLEW_GET_VAR(__GLEW_EXT_texture_compression_dxt1)
+
+#endif /* !GL_EXT_texture_compression_dxt1 */
+
+/* -------------------- GL_EXT_texture_compression_latc -------------------- */
+
+#if !defined(GL_EXT_texture_compression_latc)
+#define GL_EXT_texture_compression_latc 1
+
+#define GL_COMPRESSED_LUMINANCE_LATC1_EXT 0x8C70
+#define GL_COMPRESSED_SIGNED_LUMINANCE_LATC1_EXT 0x8C71
+#define GL_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT 0x8C72
+#define GL_COMPRESSED_SIGNED_LUMINANCE_ALPHA_LATC2_EXT 0x8C73
+
+#define GLEW_EXT_texture_compression_latc GLEW_GET_VAR(__GLEW_EXT_texture_compression_latc)
+
+#endif /* !GL_EXT_texture_compression_latc */
+
+/* -------------------- GL_EXT_texture_compression_rgtc -------------------- */
+
+#if !defined(GL_EXT_texture_compression_rgtc)
+#define GL_EXT_texture_compression_rgtc 1
+
+#define GL_COMPRESSED_RED_RGTC1_EXT 0x8DBB
+#define GL_COMPRESSED_SIGNED_RED_RGTC1_EXT 0x8DBC
+#define GL_COMPRESSED_RED_GREEN_RGTC2_EXT 0x8DBD
+#define GL_COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT 0x8DBE
+
+#define GLEW_EXT_texture_compression_rgtc GLEW_GET_VAR(__GLEW_EXT_texture_compression_rgtc)
+
+#endif /* !GL_EXT_texture_compression_rgtc */
+
+/* -------------------- GL_EXT_texture_compression_s3tc -------------------- */
+
+#if !defined(GL_EXT_texture_compression_s3tc)
+#define GL_EXT_texture_compression_s3tc 1
+
+#define GL_COMPRESSED_RGB_S3TC_DXT1_EXT 0x83F0
+#define GL_COMPRESSED_RGBA_S3TC_DXT1_EXT 0x83F1
+#define GL_COMPRESSED_RGBA_S3TC_DXT3_EXT 0x83F2
+#define GL_COMPRESSED_RGBA_S3TC_DXT5_EXT 0x83F3
+
+#define GLEW_EXT_texture_compression_s3tc GLEW_GET_VAR(__GLEW_EXT_texture_compression_s3tc)
+
+#endif /* !GL_EXT_texture_compression_s3tc */
+
+/* ------------------------ GL_EXT_texture_cube_map ------------------------ */
+
+#if !defined(GL_EXT_texture_cube_map)
+#define GL_EXT_texture_cube_map 1
+
+#define GL_NORMAL_MAP_EXT 0x8511
+#define GL_REFLECTION_MAP_EXT 0x8512
+#define GL_TEXTURE_CUBE_MAP_EXT 0x8513
+#define GL_TEXTURE_BINDING_CUBE_MAP_EXT 0x8514
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_X_EXT 0x8515
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_X_EXT 0x8516
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_Y_EXT 0x8517
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_EXT 0x8518
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z_EXT 0x8519
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_EXT 0x851A
+#define GL_PROXY_TEXTURE_CUBE_MAP_EXT 0x851B
+#define GL_MAX_CUBE_MAP_TEXTURE_SIZE_EXT 0x851C
+
+#define GLEW_EXT_texture_cube_map GLEW_GET_VAR(__GLEW_EXT_texture_cube_map)
+
+#endif /* !GL_EXT_texture_cube_map */
+
+/* ----------------------- GL_EXT_texture_edge_clamp ----------------------- */
+
+#if !defined(GL_EXT_texture_edge_clamp)
+#define GL_EXT_texture_edge_clamp 1
+
+#define GL_CLAMP_TO_EDGE_EXT 0x812F
+
+#define GLEW_EXT_texture_edge_clamp GLEW_GET_VAR(__GLEW_EXT_texture_edge_clamp)
+
+#endif /* !GL_EXT_texture_edge_clamp */
+
+/* --------------------------- GL_EXT_texture_env -------------------------- */
+
+#if !defined(GL_EXT_texture_env)
+#define GL_EXT_texture_env 1
+
+#define GL_TEXTURE_ENV0_EXT 0
+#define GL_ENV_BLEND_EXT 0
+#define GL_TEXTURE_ENV_SHIFT_EXT 0
+#define GL_ENV_REPLACE_EXT 0
+#define GL_ENV_ADD_EXT 0
+#define GL_ENV_SUBTRACT_EXT 0
+#define GL_TEXTURE_ENV_MODE_ALPHA_EXT 0
+#define GL_ENV_REVERSE_SUBTRACT_EXT 0
+#define GL_ENV_REVERSE_BLEND_EXT 0
+#define GL_ENV_COPY_EXT 0
+#define GL_ENV_MODULATE_EXT 0
+
+#define GLEW_EXT_texture_env GLEW_GET_VAR(__GLEW_EXT_texture_env)
+
+#endif /* !GL_EXT_texture_env */
+
+/* ------------------------- GL_EXT_texture_env_add ------------------------ */
+
+#if !defined(GL_EXT_texture_env_add)
+#define GL_EXT_texture_env_add 1
+
+#define GLEW_EXT_texture_env_add GLEW_GET_VAR(__GLEW_EXT_texture_env_add)
+
+#endif /* !GL_EXT_texture_env_add */
+
+/* ----------------------- GL_EXT_texture_env_combine ---------------------- */
+
+#if !defined(GL_EXT_texture_env_combine)
+#define GL_EXT_texture_env_combine 1
+
+#define GL_COMBINE_EXT 0x8570
+#define GL_COMBINE_RGB_EXT 0x8571
+#define GL_COMBINE_ALPHA_EXT 0x8572
+#define GL_RGB_SCALE_EXT 0x8573
+#define GL_ADD_SIGNED_EXT 0x8574
+#define GL_INTERPOLATE_EXT 0x8575
+#define GL_CONSTANT_EXT 0x8576
+#define GL_PRIMARY_COLOR_EXT 0x8577
+#define GL_PREVIOUS_EXT 0x8578
+#define GL_SOURCE0_RGB_EXT 0x8580
+#define GL_SOURCE1_RGB_EXT 0x8581
+#define GL_SOURCE2_RGB_EXT 0x8582
+#define GL_SOURCE0_ALPHA_EXT 0x8588
+#define GL_SOURCE1_ALPHA_EXT 0x8589
+#define GL_SOURCE2_ALPHA_EXT 0x858A
+#define GL_OPERAND0_RGB_EXT 0x8590
+#define GL_OPERAND1_RGB_EXT 0x8591
+#define GL_OPERAND2_RGB_EXT 0x8592
+#define GL_OPERAND0_ALPHA_EXT 0x8598
+#define GL_OPERAND1_ALPHA_EXT 0x8599
+#define GL_OPERAND2_ALPHA_EXT 0x859A
+
+#define GLEW_EXT_texture_env_combine GLEW_GET_VAR(__GLEW_EXT_texture_env_combine)
+
+#endif /* !GL_EXT_texture_env_combine */
+
+/* ------------------------ GL_EXT_texture_env_dot3 ------------------------ */
+
+#if !defined(GL_EXT_texture_env_dot3)
+#define GL_EXT_texture_env_dot3 1
+
+#define GL_DOT3_RGB_EXT 0x8740
+#define GL_DOT3_RGBA_EXT 0x8741
+
+#define GLEW_EXT_texture_env_dot3 GLEW_GET_VAR(__GLEW_EXT_texture_env_dot3)
+
+#endif /* !GL_EXT_texture_env_dot3 */
+
+/* ------------------- GL_EXT_texture_filter_anisotropic ------------------- */
+
+#if !defined(GL_EXT_texture_filter_anisotropic)
+#define GL_EXT_texture_filter_anisotropic 1
+
+#define GL_TEXTURE_MAX_ANISOTROPY_EXT 0x84FE
+#define GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT 0x84FF
+
+#define GLEW_EXT_texture_filter_anisotropic GLEW_GET_VAR(__GLEW_EXT_texture_filter_anisotropic)
+
+#endif /* !GL_EXT_texture_filter_anisotropic */
+
+/* ------------------------- GL_EXT_texture_integer ------------------------ */
+
+#if !defined(GL_EXT_texture_integer)
+#define GL_EXT_texture_integer 1
+
+#define GL_RGBA32UI_EXT 0x8D70
+#define GL_RGB32UI_EXT 0x8D71
+#define GL_ALPHA32UI_EXT 0x8D72
+#define GL_INTENSITY32UI_EXT 0x8D73
+#define GL_LUMINANCE32UI_EXT 0x8D74
+#define GL_LUMINANCE_ALPHA32UI_EXT 0x8D75
+#define GL_RGBA16UI_EXT 0x8D76
+#define GL_RGB16UI_EXT 0x8D77
+#define GL_ALPHA16UI_EXT 0x8D78
+#define GL_INTENSITY16UI_EXT 0x8D79
+#define GL_LUMINANCE16UI_EXT 0x8D7A
+#define GL_LUMINANCE_ALPHA16UI_EXT 0x8D7B
+#define GL_RGBA8UI_EXT 0x8D7C
+#define GL_RGB8UI_EXT 0x8D7D
+#define GL_ALPHA8UI_EXT 0x8D7E
+#define GL_INTENSITY8UI_EXT 0x8D7F
+#define GL_LUMINANCE8UI_EXT 0x8D80
+#define GL_LUMINANCE_ALPHA8UI_EXT 0x8D81
+#define GL_RGBA32I_EXT 0x8D82
+#define GL_RGB32I_EXT 0x8D83
+#define GL_ALPHA32I_EXT 0x8D84
+#define GL_INTENSITY32I_EXT 0x8D85
+#define GL_LUMINANCE32I_EXT 0x8D86
+#define GL_LUMINANCE_ALPHA32I_EXT 0x8D87
+#define GL_RGBA16I_EXT 0x8D88
+#define GL_RGB16I_EXT 0x8D89
+#define GL_ALPHA16I_EXT 0x8D8A
+#define GL_INTENSITY16I_EXT 0x8D8B
+#define GL_LUMINANCE16I_EXT 0x8D8C
+#define GL_LUMINANCE_ALPHA16I_EXT 0x8D8D
+#define GL_RGBA8I_EXT 0x8D8E
+#define GL_RGB8I_EXT 0x8D8F
+#define GL_ALPHA8I_EXT 0x8D90
+#define GL_INTENSITY8I_EXT 0x8D91
+#define GL_LUMINANCE8I_EXT 0x8D92
+#define GL_LUMINANCE_ALPHA8I_EXT 0x8D93
+#define GL_RED_INTEGER_EXT 0x8D94
+#define GL_GREEN_INTEGER_EXT 0x8D95
+#define GL_BLUE_INTEGER_EXT 0x8D96
+#define GL_ALPHA_INTEGER_EXT 0x8D97
+#define GL_RGB_INTEGER_EXT 0x8D98
+#define GL_RGBA_INTEGER_EXT 0x8D99
+#define GL_BGR_INTEGER_EXT 0x8D9A
+#define GL_BGRA_INTEGER_EXT 0x8D9B
+#define GL_LUMINANCE_INTEGER_EXT 0x8D9C
+#define GL_LUMINANCE_ALPHA_INTEGER_EXT 0x8D9D
+#define GL_RGBA_INTEGER_MODE_EXT 0x8D9E
+
+typedef void (GLAPIENTRY * PFNGLCLEARCOLORIIEXTPROC) (GLint red, GLint green, GLint blue, GLint alpha);
+typedef void (GLAPIENTRY * PFNGLCLEARCOLORIUIEXTPROC) (GLuint red, GLuint green, GLuint blue, GLuint alpha);
+typedef void (GLAPIENTRY * PFNGLGETTEXPARAMETERIIVEXTPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (GLAPIENTRY * PFNGLGETTEXPARAMETERIUIVEXTPROC) (GLenum target, GLenum pname, GLuint *params);
+typedef void (GLAPIENTRY * PFNGLTEXPARAMETERIIVEXTPROC) (GLenum target, GLenum pname, const GLint *params);
+typedef void (GLAPIENTRY * PFNGLTEXPARAMETERIUIVEXTPROC) (GLenum target, GLenum pname, const GLuint *params);
+
+#define glClearColorIiEXT GLEW_GET_FUN(__glewClearColorIiEXT)
+#define glClearColorIuiEXT GLEW_GET_FUN(__glewClearColorIuiEXT)
+#define glGetTexParameterIivEXT GLEW_GET_FUN(__glewGetTexParameterIivEXT)
+#define glGetTexParameterIuivEXT GLEW_GET_FUN(__glewGetTexParameterIuivEXT)
+#define glTexParameterIivEXT GLEW_GET_FUN(__glewTexParameterIivEXT)
+#define glTexParameterIuivEXT GLEW_GET_FUN(__glewTexParameterIuivEXT)
+
+#define GLEW_EXT_texture_integer GLEW_GET_VAR(__GLEW_EXT_texture_integer)
+
+#endif /* !GL_EXT_texture_integer */
+
+/* ------------------------ GL_EXT_texture_lod_bias ------------------------ */
+
+#if !defined(GL_EXT_texture_lod_bias)
+#define GL_EXT_texture_lod_bias 1
+
+#define GL_MAX_TEXTURE_LOD_BIAS_EXT 0x84FD
+#define GL_TEXTURE_FILTER_CONTROL_EXT 0x8500
+#define GL_TEXTURE_LOD_BIAS_EXT 0x8501
+
+#define GLEW_EXT_texture_lod_bias GLEW_GET_VAR(__GLEW_EXT_texture_lod_bias)
+
+#endif /* !GL_EXT_texture_lod_bias */
+
+/* ---------------------- GL_EXT_texture_mirror_clamp ---------------------- */
+
+#if !defined(GL_EXT_texture_mirror_clamp)
+#define GL_EXT_texture_mirror_clamp 1
+
+#define GL_MIRROR_CLAMP_EXT 0x8742
+#define GL_MIRROR_CLAMP_TO_EDGE_EXT 0x8743
+#define GL_MIRROR_CLAMP_TO_BORDER_EXT 0x8912
+
+#define GLEW_EXT_texture_mirror_clamp GLEW_GET_VAR(__GLEW_EXT_texture_mirror_clamp)
+
+#endif /* !GL_EXT_texture_mirror_clamp */
+
+/* ------------------------- GL_EXT_texture_object ------------------------- */
+
+#if !defined(GL_EXT_texture_object)
+#define GL_EXT_texture_object 1
+
+#define GL_TEXTURE_PRIORITY_EXT 0x8066
+#define GL_TEXTURE_RESIDENT_EXT 0x8067
+#define GL_TEXTURE_1D_BINDING_EXT 0x8068
+#define GL_TEXTURE_2D_BINDING_EXT 0x8069
+#define GL_TEXTURE_3D_BINDING_EXT 0x806A
+
+typedef GLboolean (GLAPIENTRY * PFNGLARETEXTURESRESIDENTEXTPROC) (GLsizei n, const GLuint* textures, GLboolean* residences);
+typedef void (GLAPIENTRY * PFNGLBINDTEXTUREEXTPROC) (GLenum target, GLuint texture);
+typedef void (GLAPIENTRY * PFNGLDELETETEXTURESEXTPROC) (GLsizei n, const GLuint* textures);
+typedef void (GLAPIENTRY * PFNGLGENTEXTURESEXTPROC) (GLsizei n, GLuint* textures);
+typedef GLboolean (GLAPIENTRY * PFNGLISTEXTUREEXTPROC) (GLuint texture);
+typedef void (GLAPIENTRY * PFNGLPRIORITIZETEXTURESEXTPROC) (GLsizei n, const GLuint* textures, const GLclampf* priorities);
+
+#define glAreTexturesResidentEXT GLEW_GET_FUN(__glewAreTexturesResidentEXT)
+#define glBindTextureEXT GLEW_GET_FUN(__glewBindTextureEXT)
+#define glDeleteTexturesEXT GLEW_GET_FUN(__glewDeleteTexturesEXT)
+#define glGenTexturesEXT GLEW_GET_FUN(__glewGenTexturesEXT)
+#define glIsTextureEXT GLEW_GET_FUN(__glewIsTextureEXT)
+#define glPrioritizeTexturesEXT GLEW_GET_FUN(__glewPrioritizeTexturesEXT)
+
+#define GLEW_EXT_texture_object GLEW_GET_VAR(__GLEW_EXT_texture_object)
+
+#endif /* !GL_EXT_texture_object */
+
+/* --------------------- GL_EXT_texture_perturb_normal --------------------- */
+
+#if !defined(GL_EXT_texture_perturb_normal)
+#define GL_EXT_texture_perturb_normal 1
+
+#define GL_PERTURB_EXT 0x85AE
+#define GL_TEXTURE_NORMAL_EXT 0x85AF
+
+typedef void (GLAPIENTRY * PFNGLTEXTURENORMALEXTPROC) (GLenum mode);
+
+#define glTextureNormalEXT GLEW_GET_FUN(__glewTextureNormalEXT)
+
+#define GLEW_EXT_texture_perturb_normal GLEW_GET_VAR(__GLEW_EXT_texture_perturb_normal)
+
+#endif /* !GL_EXT_texture_perturb_normal */
+
+/* ------------------------ GL_EXT_texture_rectangle ----------------------- */
+
+#if !defined(GL_EXT_texture_rectangle)
+#define GL_EXT_texture_rectangle 1
+
+#define GL_TEXTURE_RECTANGLE_EXT 0x84F5
+#define GL_TEXTURE_BINDING_RECTANGLE_EXT 0x84F6
+#define GL_PROXY_TEXTURE_RECTANGLE_EXT 0x84F7
+#define GL_MAX_RECTANGLE_TEXTURE_SIZE_EXT 0x84F8
+
+#define GLEW_EXT_texture_rectangle GLEW_GET_VAR(__GLEW_EXT_texture_rectangle)
+
+#endif /* !GL_EXT_texture_rectangle */
+
+/* -------------------------- GL_EXT_texture_sRGB -------------------------- */
+
+#if !defined(GL_EXT_texture_sRGB)
+#define GL_EXT_texture_sRGB 1
+
+#define GL_SRGB_EXT 0x8C40
+#define GL_SRGB8_EXT 0x8C41
+#define GL_SRGB_ALPHA_EXT 0x8C42
+#define GL_SRGB8_ALPHA8_EXT 0x8C43
+#define GL_SLUMINANCE_ALPHA_EXT 0x8C44
+#define GL_SLUMINANCE8_ALPHA8_EXT 0x8C45
+#define GL_SLUMINANCE_EXT 0x8C46
+#define GL_SLUMINANCE8_EXT 0x8C47
+#define GL_COMPRESSED_SRGB_EXT 0x8C48
+#define GL_COMPRESSED_SRGB_ALPHA_EXT 0x8C49
+#define GL_COMPRESSED_SLUMINANCE_EXT 0x8C4A
+#define GL_COMPRESSED_SLUMINANCE_ALPHA_EXT 0x8C4B
+#define GL_COMPRESSED_SRGB_S3TC_DXT1_EXT 0x8C4C
+#define GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT 0x8C4D
+#define GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT 0x8C4E
+#define GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT 0x8C4F
+
+#define GLEW_EXT_texture_sRGB GLEW_GET_VAR(__GLEW_EXT_texture_sRGB)
+
+#endif /* !GL_EXT_texture_sRGB */
+
+/* ----------------------- GL_EXT_texture_sRGB_decode ---------------------- */
+
+#if !defined(GL_EXT_texture_sRGB_decode)
+#define GL_EXT_texture_sRGB_decode 1
+
+#define GL_TEXTURE_SRGB_DECODE_EXT 0x8A48
+#define GL_DECODE_EXT 0x8A49
+#define GL_SKIP_DECODE_EXT 0x8A4A
+
+#define GLEW_EXT_texture_sRGB_decode GLEW_GET_VAR(__GLEW_EXT_texture_sRGB_decode)
+
+#endif /* !GL_EXT_texture_sRGB_decode */
+
+/* --------------------- GL_EXT_texture_shared_exponent -------------------- */
+
+#if !defined(GL_EXT_texture_shared_exponent)
+#define GL_EXT_texture_shared_exponent 1
+
+#define GL_RGB9_E5_EXT 0x8C3D
+#define GL_UNSIGNED_INT_5_9_9_9_REV_EXT 0x8C3E
+#define GL_TEXTURE_SHARED_SIZE_EXT 0x8C3F
+
+#define GLEW_EXT_texture_shared_exponent GLEW_GET_VAR(__GLEW_EXT_texture_shared_exponent)
+
+#endif /* !GL_EXT_texture_shared_exponent */
+
+/* -------------------------- GL_EXT_texture_snorm ------------------------- */
+
+#if !defined(GL_EXT_texture_snorm)
+#define GL_EXT_texture_snorm 1
+
+#define GL_RED_SNORM 0x8F90
+#define GL_RG_SNORM 0x8F91
+#define GL_RGB_SNORM 0x8F92
+#define GL_RGBA_SNORM 0x8F93
+#define GL_R8_SNORM 0x8F94
+#define GL_RG8_SNORM 0x8F95
+#define GL_RGB8_SNORM 0x8F96
+#define GL_RGBA8_SNORM 0x8F97
+#define GL_R16_SNORM 0x8F98
+#define GL_RG16_SNORM 0x8F99
+#define GL_RGB16_SNORM 0x8F9A
+#define GL_RGBA16_SNORM 0x8F9B
+#define GL_SIGNED_NORMALIZED 0x8F9C
+#define GL_ALPHA_SNORM 0x9010
+#define GL_LUMINANCE_SNORM 0x9011
+#define GL_LUMINANCE_ALPHA_SNORM 0x9012
+#define GL_INTENSITY_SNORM 0x9013
+#define GL_ALPHA8_SNORM 0x9014
+#define GL_LUMINANCE8_SNORM 0x9015
+#define GL_LUMINANCE8_ALPHA8_SNORM 0x9016
+#define GL_INTENSITY8_SNORM 0x9017
+#define GL_ALPHA16_SNORM 0x9018
+#define GL_LUMINANCE16_SNORM 0x9019
+#define GL_LUMINANCE16_ALPHA16_SNORM 0x901A
+#define GL_INTENSITY16_SNORM 0x901B
+
+#define GLEW_EXT_texture_snorm GLEW_GET_VAR(__GLEW_EXT_texture_snorm)
+
+#endif /* !GL_EXT_texture_snorm */
+
+/* ------------------------- GL_EXT_texture_swizzle ------------------------ */
+
+#if !defined(GL_EXT_texture_swizzle)
+#define GL_EXT_texture_swizzle 1
+
+#define GL_TEXTURE_SWIZZLE_R_EXT 0x8E42
+#define GL_TEXTURE_SWIZZLE_G_EXT 0x8E43
+#define GL_TEXTURE_SWIZZLE_B_EXT 0x8E44
+#define GL_TEXTURE_SWIZZLE_A_EXT 0x8E45
+#define GL_TEXTURE_SWIZZLE_RGBA_EXT 0x8E46
+
+#define GLEW_EXT_texture_swizzle GLEW_GET_VAR(__GLEW_EXT_texture_swizzle)
+
+#endif /* !GL_EXT_texture_swizzle */
+
+/* --------------------------- GL_EXT_timer_query -------------------------- */
+
+#if !defined(GL_EXT_timer_query)
+#define GL_EXT_timer_query 1
+
+#define GL_TIME_ELAPSED_EXT 0x88BF
+
+typedef void (GLAPIENTRY * PFNGLGETQUERYOBJECTI64VEXTPROC) (GLuint id, GLenum pname, GLint64EXT *params);
+typedef void (GLAPIENTRY * PFNGLGETQUERYOBJECTUI64VEXTPROC) (GLuint id, GLenum pname, GLuint64EXT *params);
+
+#define glGetQueryObjecti64vEXT GLEW_GET_FUN(__glewGetQueryObjecti64vEXT)
+#define glGetQueryObjectui64vEXT GLEW_GET_FUN(__glewGetQueryObjectui64vEXT)
+
+#define GLEW_EXT_timer_query GLEW_GET_VAR(__GLEW_EXT_timer_query)
+
+#endif /* !GL_EXT_timer_query */
+
+/* ----------------------- GL_EXT_transform_feedback ----------------------- */
+
+#if !defined(GL_EXT_transform_feedback)
+#define GL_EXT_transform_feedback 1
+
+#define GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH_EXT 0x8C76
+#define GL_TRANSFORM_FEEDBACK_BUFFER_MODE_EXT 0x8C7F
+#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS_EXT 0x8C80
+#define GL_TRANSFORM_FEEDBACK_VARYINGS_EXT 0x8C83
+#define GL_TRANSFORM_FEEDBACK_BUFFER_START_EXT 0x8C84
+#define GL_TRANSFORM_FEEDBACK_BUFFER_SIZE_EXT 0x8C85
+#define GL_PRIMITIVES_GENERATED_EXT 0x8C87
+#define GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN_EXT 0x8C88
+#define GL_RASTERIZER_DISCARD_EXT 0x8C89
+#define GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS_EXT 0x8C8A
+#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS_EXT 0x8C8B
+#define GL_INTERLEAVED_ATTRIBS_EXT 0x8C8C
+#define GL_SEPARATE_ATTRIBS_EXT 0x8C8D
+#define GL_TRANSFORM_FEEDBACK_BUFFER_EXT 0x8C8E
+#define GL_TRANSFORM_FEEDBACK_BUFFER_BINDING_EXT 0x8C8F
+
+typedef void (GLAPIENTRY * PFNGLBEGINTRANSFORMFEEDBACKEXTPROC) (GLenum primitiveMode);
+typedef void (GLAPIENTRY * PFNGLBINDBUFFERBASEEXTPROC) (GLenum target, GLuint index, GLuint buffer);
+typedef void (GLAPIENTRY * PFNGLBINDBUFFEROFFSETEXTPROC) (GLenum target, GLuint index, GLuint buffer, GLintptr offset);
+typedef void (GLAPIENTRY * PFNGLBINDBUFFERRANGEEXTPROC) (GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size);
+typedef void (GLAPIENTRY * PFNGLENDTRANSFORMFEEDBACKEXTPROC) (void);
+typedef void (GLAPIENTRY * PFNGLGETTRANSFORMFEEDBACKVARYINGEXTPROC) (GLuint program, GLuint index, GLsizei bufSize, GLsizei* length, GLsizei *size, GLenum *type, char *name);
+typedef void (GLAPIENTRY * PFNGLTRANSFORMFEEDBACKVARYINGSEXTPROC) (GLuint program, GLsizei count, const char ** varyings, GLenum bufferMode);
+
+#define glBeginTransformFeedbackEXT GLEW_GET_FUN(__glewBeginTransformFeedbackEXT)
+#define glBindBufferBaseEXT GLEW_GET_FUN(__glewBindBufferBaseEXT)
+#define glBindBufferOffsetEXT GLEW_GET_FUN(__glewBindBufferOffsetEXT)
+#define glBindBufferRangeEXT GLEW_GET_FUN(__glewBindBufferRangeEXT)
+#define glEndTransformFeedbackEXT GLEW_GET_FUN(__glewEndTransformFeedbackEXT)
+#define glGetTransformFeedbackVaryingEXT GLEW_GET_FUN(__glewGetTransformFeedbackVaryingEXT)
+#define glTransformFeedbackVaryingsEXT GLEW_GET_FUN(__glewTransformFeedbackVaryingsEXT)
+
+#define GLEW_EXT_transform_feedback GLEW_GET_VAR(__GLEW_EXT_transform_feedback)
+
+#endif /* !GL_EXT_transform_feedback */
+
+/* -------------------------- GL_EXT_vertex_array -------------------------- */
+
+#if !defined(GL_EXT_vertex_array)
+#define GL_EXT_vertex_array 1
+
+#define GL_DOUBLE_EXT 0x140A
+#define GL_VERTEX_ARRAY_EXT 0x8074
+#define GL_NORMAL_ARRAY_EXT 0x8075
+#define GL_COLOR_ARRAY_EXT 0x8076
+#define GL_INDEX_ARRAY_EXT 0x8077
+#define GL_TEXTURE_COORD_ARRAY_EXT 0x8078
+#define GL_EDGE_FLAG_ARRAY_EXT 0x8079
+#define GL_VERTEX_ARRAY_SIZE_EXT 0x807A
+#define GL_VERTEX_ARRAY_TYPE_EXT 0x807B
+#define GL_VERTEX_ARRAY_STRIDE_EXT 0x807C
+#define GL_VERTEX_ARRAY_COUNT_EXT 0x807D
+#define GL_NORMAL_ARRAY_TYPE_EXT 0x807E
+#define GL_NORMAL_ARRAY_STRIDE_EXT 0x807F
+#define GL_NORMAL_ARRAY_COUNT_EXT 0x8080
+#define GL_COLOR_ARRAY_SIZE_EXT 0x8081
+#define GL_COLOR_ARRAY_TYPE_EXT 0x8082
+#define GL_COLOR_ARRAY_STRIDE_EXT 0x8083
+#define GL_COLOR_ARRAY_COUNT_EXT 0x8084
+#define GL_INDEX_ARRAY_TYPE_EXT 0x8085
+#define GL_INDEX_ARRAY_STRIDE_EXT 0x8086
+#define GL_INDEX_ARRAY_COUNT_EXT 0x8087
+#define GL_TEXTURE_COORD_ARRAY_SIZE_EXT 0x8088
+#define GL_TEXTURE_COORD_ARRAY_TYPE_EXT 0x8089
+#define GL_TEXTURE_COORD_ARRAY_STRIDE_EXT 0x808A
+#define GL_TEXTURE_COORD_ARRAY_COUNT_EXT 0x808B
+#define GL_EDGE_FLAG_ARRAY_STRIDE_EXT 0x808C
+#define GL_EDGE_FLAG_ARRAY_COUNT_EXT 0x808D
+#define GL_VERTEX_ARRAY_POINTER_EXT 0x808E
+#define GL_NORMAL_ARRAY_POINTER_EXT 0x808F
+#define GL_COLOR_ARRAY_POINTER_EXT 0x8090
+#define GL_INDEX_ARRAY_POINTER_EXT 0x8091
+#define GL_TEXTURE_COORD_ARRAY_POINTER_EXT 0x8092
+#define GL_EDGE_FLAG_ARRAY_POINTER_EXT 0x8093
+
+typedef void (GLAPIENTRY * PFNGLARRAYELEMENTEXTPROC) (GLint i);
+typedef void (GLAPIENTRY * PFNGLCOLORPOINTEREXTPROC) (GLint size, GLenum type, GLsizei stride, GLsizei count, const void* pointer);
+typedef void (GLAPIENTRY * PFNGLDRAWARRAYSEXTPROC) (GLenum mode, GLint first, GLsizei count);
+typedef void (GLAPIENTRY * PFNGLEDGEFLAGPOINTEREXTPROC) (GLsizei stride, GLsizei count, const GLboolean* pointer);
+typedef void (GLAPIENTRY * PFNGLINDEXPOINTEREXTPROC) (GLenum type, GLsizei stride, GLsizei count, const void* pointer);
+typedef void (GLAPIENTRY * PFNGLNORMALPOINTEREXTPROC) (GLenum type, GLsizei stride, GLsizei count, const void* pointer);
+typedef void (GLAPIENTRY * PFNGLTEXCOORDPOINTEREXTPROC) (GLint size, GLenum type, GLsizei stride, GLsizei count, const void* pointer);
+typedef void (GLAPIENTRY * PFNGLVERTEXPOINTEREXTPROC) (GLint size, GLenum type, GLsizei stride, GLsizei count, const void* pointer);
+
+#define glArrayElementEXT GLEW_GET_FUN(__glewArrayElementEXT)
+#define glColorPointerEXT GLEW_GET_FUN(__glewColorPointerEXT)
+#define glDrawArraysEXT GLEW_GET_FUN(__glewDrawArraysEXT)
+#define glEdgeFlagPointerEXT GLEW_GET_FUN(__glewEdgeFlagPointerEXT)
+#define glIndexPointerEXT GLEW_GET_FUN(__glewIndexPointerEXT)
+#define glNormalPointerEXT GLEW_GET_FUN(__glewNormalPointerEXT)
+#define glTexCoordPointerEXT GLEW_GET_FUN(__glewTexCoordPointerEXT)
+#define glVertexPointerEXT GLEW_GET_FUN(__glewVertexPointerEXT)
+
+#define GLEW_EXT_vertex_array GLEW_GET_VAR(__GLEW_EXT_vertex_array)
+
+#endif /* !GL_EXT_vertex_array */
+
+/* ------------------------ GL_EXT_vertex_array_bgra ----------------------- */
+
+#if !defined(GL_EXT_vertex_array_bgra)
+#define GL_EXT_vertex_array_bgra 1
+
+#define GL_BGRA 0x80E1
+
+#define GLEW_EXT_vertex_array_bgra GLEW_GET_VAR(__GLEW_EXT_vertex_array_bgra)
+
+#endif /* !GL_EXT_vertex_array_bgra */
+
+/* ----------------------- GL_EXT_vertex_attrib_64bit ---------------------- */
+
+#if !defined(GL_EXT_vertex_attrib_64bit)
+#define GL_EXT_vertex_attrib_64bit 1
+
+#define GL_DOUBLE_MAT2_EXT 0x8F46
+#define GL_DOUBLE_MAT3_EXT 0x8F47
+#define GL_DOUBLE_MAT4_EXT 0x8F48
+#define GL_DOUBLE_MAT2x3_EXT 0x8F49
+#define GL_DOUBLE_MAT2x4_EXT 0x8F4A
+#define GL_DOUBLE_MAT3x2_EXT 0x8F4B
+#define GL_DOUBLE_MAT3x4_EXT 0x8F4C
+#define GL_DOUBLE_MAT4x2_EXT 0x8F4D
+#define GL_DOUBLE_MAT4x3_EXT 0x8F4E
+#define GL_DOUBLE_VEC2_EXT 0x8FFC
+#define GL_DOUBLE_VEC3_EXT 0x8FFD
+#define GL_DOUBLE_VEC4_EXT 0x8FFE
+
+typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBLDVEXTPROC) (GLuint index, GLenum pname, GLdouble* params);
+typedef void (GLAPIENTRY * PFNGLVERTEXARRAYVERTEXATTRIBLOFFSETEXTPROC) (GLuint vaobj, GLuint buffer, GLuint index, GLint size, GLenum type, GLsizei stride, GLintptr offset);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL1DEXTPROC) (GLuint index, GLdouble x);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL1DVEXTPROC) (GLuint index, const GLdouble* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL2DEXTPROC) (GLuint index, GLdouble x, GLdouble y);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL2DVEXTPROC) (GLuint index, const GLdouble* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL3DEXTPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL3DVEXTPROC) (GLuint index, const GLdouble* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL4DEXTPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL4DVEXTPROC) (GLuint index, const GLdouble* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBLPOINTEREXTPROC) (GLuint index, GLint size, GLenum type, GLsizei stride, const void* pointer);
+
+#define glGetVertexAttribLdvEXT GLEW_GET_FUN(__glewGetVertexAttribLdvEXT)
+#define glVertexArrayVertexAttribLOffsetEXT GLEW_GET_FUN(__glewVertexArrayVertexAttribLOffsetEXT)
+#define glVertexAttribL1dEXT GLEW_GET_FUN(__glewVertexAttribL1dEXT)
+#define glVertexAttribL1dvEXT GLEW_GET_FUN(__glewVertexAttribL1dvEXT)
+#define glVertexAttribL2dEXT GLEW_GET_FUN(__glewVertexAttribL2dEXT)
+#define glVertexAttribL2dvEXT GLEW_GET_FUN(__glewVertexAttribL2dvEXT)
+#define glVertexAttribL3dEXT GLEW_GET_FUN(__glewVertexAttribL3dEXT)
+#define glVertexAttribL3dvEXT GLEW_GET_FUN(__glewVertexAttribL3dvEXT)
+#define glVertexAttribL4dEXT GLEW_GET_FUN(__glewVertexAttribL4dEXT)
+#define glVertexAttribL4dvEXT GLEW_GET_FUN(__glewVertexAttribL4dvEXT)
+#define glVertexAttribLPointerEXT GLEW_GET_FUN(__glewVertexAttribLPointerEXT)
+
+#define GLEW_EXT_vertex_attrib_64bit GLEW_GET_VAR(__GLEW_EXT_vertex_attrib_64bit)
+
+#endif /* !GL_EXT_vertex_attrib_64bit */
+
+/* -------------------------- GL_EXT_vertex_shader ------------------------- */
+
+#if !defined(GL_EXT_vertex_shader)
+#define GL_EXT_vertex_shader 1
+
+#define GL_VERTEX_SHADER_EXT 0x8780
+#define GL_VERTEX_SHADER_BINDING_EXT 0x8781
+#define GL_OP_INDEX_EXT 0x8782
+#define GL_OP_NEGATE_EXT 0x8783
+#define GL_OP_DOT3_EXT 0x8784
+#define GL_OP_DOT4_EXT 0x8785
+#define GL_OP_MUL_EXT 0x8786
+#define GL_OP_ADD_EXT 0x8787
+#define GL_OP_MADD_EXT 0x8788
+#define GL_OP_FRAC_EXT 0x8789
+#define GL_OP_MAX_EXT 0x878A
+#define GL_OP_MIN_EXT 0x878B
+#define GL_OP_SET_GE_EXT 0x878C
+#define GL_OP_SET_LT_EXT 0x878D
+#define GL_OP_CLAMP_EXT 0x878E
+#define GL_OP_FLOOR_EXT 0x878F
+#define GL_OP_ROUND_EXT 0x8790
+#define GL_OP_EXP_BASE_2_EXT 0x8791
+#define GL_OP_LOG_BASE_2_EXT 0x8792
+#define GL_OP_POWER_EXT 0x8793
+#define GL_OP_RECIP_EXT 0x8794
+#define GL_OP_RECIP_SQRT_EXT 0x8795
+#define GL_OP_SUB_EXT 0x8796
+#define GL_OP_CROSS_PRODUCT_EXT 0x8797
+#define GL_OP_MULTIPLY_MATRIX_EXT 0x8798
+#define GL_OP_MOV_EXT 0x8799
+#define GL_OUTPUT_VERTEX_EXT 0x879A
+#define GL_OUTPUT_COLOR0_EXT 0x879B
+#define GL_OUTPUT_COLOR1_EXT 0x879C
+#define GL_OUTPUT_TEXTURE_COORD0_EXT 0x879D
+#define GL_OUTPUT_TEXTURE_COORD1_EXT 0x879E
+#define GL_OUTPUT_TEXTURE_COORD2_EXT 0x879F
+#define GL_OUTPUT_TEXTURE_COORD3_EXT 0x87A0
+#define GL_OUTPUT_TEXTURE_COORD4_EXT 0x87A1
+#define GL_OUTPUT_TEXTURE_COORD5_EXT 0x87A2
+#define GL_OUTPUT_TEXTURE_COORD6_EXT 0x87A3
+#define GL_OUTPUT_TEXTURE_COORD7_EXT 0x87A4
+#define GL_OUTPUT_TEXTURE_COORD8_EXT 0x87A5
+#define GL_OUTPUT_TEXTURE_COORD9_EXT 0x87A6
+#define GL_OUTPUT_TEXTURE_COORD10_EXT 0x87A7
+#define GL_OUTPUT_TEXTURE_COORD11_EXT 0x87A8
+#define GL_OUTPUT_TEXTURE_COORD12_EXT 0x87A9
+#define GL_OUTPUT_TEXTURE_COORD13_EXT 0x87AA
+#define GL_OUTPUT_TEXTURE_COORD14_EXT 0x87AB
+#define GL_OUTPUT_TEXTURE_COORD15_EXT 0x87AC
+#define GL_OUTPUT_TEXTURE_COORD16_EXT 0x87AD
+#define GL_OUTPUT_TEXTURE_COORD17_EXT 0x87AE
+#define GL_OUTPUT_TEXTURE_COORD18_EXT 0x87AF
+#define GL_OUTPUT_TEXTURE_COORD19_EXT 0x87B0
+#define GL_OUTPUT_TEXTURE_COORD20_EXT 0x87B1
+#define GL_OUTPUT_TEXTURE_COORD21_EXT 0x87B2
+#define GL_OUTPUT_TEXTURE_COORD22_EXT 0x87B3
+#define GL_OUTPUT_TEXTURE_COORD23_EXT 0x87B4
+#define GL_OUTPUT_TEXTURE_COORD24_EXT 0x87B5
+#define GL_OUTPUT_TEXTURE_COORD25_EXT 0x87B6
+#define GL_OUTPUT_TEXTURE_COORD26_EXT 0x87B7
+#define GL_OUTPUT_TEXTURE_COORD27_EXT 0x87B8
+#define GL_OUTPUT_TEXTURE_COORD28_EXT 0x87B9
+#define GL_OUTPUT_TEXTURE_COORD29_EXT 0x87BA
+#define GL_OUTPUT_TEXTURE_COORD30_EXT 0x87BB
+#define GL_OUTPUT_TEXTURE_COORD31_EXT 0x87BC
+#define GL_OUTPUT_FOG_EXT 0x87BD
+#define GL_SCALAR_EXT 0x87BE
+#define GL_VECTOR_EXT 0x87BF
+#define GL_MATRIX_EXT 0x87C0
+#define GL_VARIANT_EXT 0x87C1
+#define GL_INVARIANT_EXT 0x87C2
+#define GL_LOCAL_CONSTANT_EXT 0x87C3
+#define GL_LOCAL_EXT 0x87C4
+#define GL_MAX_VERTEX_SHADER_INSTRUCTIONS_EXT 0x87C5
+#define GL_MAX_VERTEX_SHADER_VARIANTS_EXT 0x87C6
+#define GL_MAX_VERTEX_SHADER_INVARIANTS_EXT 0x87C7
+#define GL_MAX_VERTEX_SHADER_LOCAL_CONSTANTS_EXT 0x87C8
+#define GL_MAX_VERTEX_SHADER_LOCALS_EXT 0x87C9
+#define GL_MAX_OPTIMIZED_VERTEX_SHADER_INSTRUCTIONS_EXT 0x87CA
+#define GL_MAX_OPTIMIZED_VERTEX_SHADER_VARIANTS_EXT 0x87CB
+#define GL_MAX_OPTIMIZED_VERTEX_SHADER_INVARIANTS_EXT 0x87CC
+#define GL_MAX_OPTIMIZED_VERTEX_SHADER_LOCAL_CONSTANTS_EXT 0x87CD
+#define GL_MAX_OPTIMIZED_VERTEX_SHADER_LOCALS_EXT 0x87CE
+#define GL_VERTEX_SHADER_INSTRUCTIONS_EXT 0x87CF
+#define GL_VERTEX_SHADER_VARIANTS_EXT 0x87D0
+#define GL_VERTEX_SHADER_INVARIANTS_EXT 0x87D1
+#define GL_VERTEX_SHADER_LOCAL_CONSTANTS_EXT 0x87D2
+#define GL_VERTEX_SHADER_LOCALS_EXT 0x87D3
+#define GL_VERTEX_SHADER_OPTIMIZED_EXT 0x87D4
+#define GL_X_EXT 0x87D5
+#define GL_Y_EXT 0x87D6
+#define GL_Z_EXT 0x87D7
+#define GL_W_EXT 0x87D8
+#define GL_NEGATIVE_X_EXT 0x87D9
+#define GL_NEGATIVE_Y_EXT 0x87DA
+#define GL_NEGATIVE_Z_EXT 0x87DB
+#define GL_NEGATIVE_W_EXT 0x87DC
+#define GL_ZERO_EXT 0x87DD
+#define GL_ONE_EXT 0x87DE
+#define GL_NEGATIVE_ONE_EXT 0x87DF
+#define GL_NORMALIZED_RANGE_EXT 0x87E0
+#define GL_FULL_RANGE_EXT 0x87E1
+#define GL_CURRENT_VERTEX_EXT 0x87E2
+#define GL_MVP_MATRIX_EXT 0x87E3
+#define GL_VARIANT_VALUE_EXT 0x87E4
+#define GL_VARIANT_DATATYPE_EXT 0x87E5
+#define GL_VARIANT_ARRAY_STRIDE_EXT 0x87E6
+#define GL_VARIANT_ARRAY_TYPE_EXT 0x87E7
+#define GL_VARIANT_ARRAY_EXT 0x87E8
+#define GL_VARIANT_ARRAY_POINTER_EXT 0x87E9
+#define GL_INVARIANT_VALUE_EXT 0x87EA
+#define GL_INVARIANT_DATATYPE_EXT 0x87EB
+#define GL_LOCAL_CONSTANT_VALUE_EXT 0x87EC
+#define GL_LOCAL_CONSTANT_DATATYPE_EXT 0x87ED
+
+typedef void (GLAPIENTRY * PFNGLBEGINVERTEXSHADEREXTPROC) (void);
+typedef GLuint (GLAPIENTRY * PFNGLBINDLIGHTPARAMETEREXTPROC) (GLenum light, GLenum value);
+typedef GLuint (GLAPIENTRY * PFNGLBINDMATERIALPARAMETEREXTPROC) (GLenum face, GLenum value);
+typedef GLuint (GLAPIENTRY * PFNGLBINDPARAMETEREXTPROC) (GLenum value);
+typedef GLuint (GLAPIENTRY * PFNGLBINDTEXGENPARAMETEREXTPROC) (GLenum unit, GLenum coord, GLenum value);
+typedef GLuint (GLAPIENTRY * PFNGLBINDTEXTUREUNITPARAMETEREXTPROC) (GLenum unit, GLenum value);
+typedef void (GLAPIENTRY * PFNGLBINDVERTEXSHADEREXTPROC) (GLuint id);
+typedef void (GLAPIENTRY * PFNGLDELETEVERTEXSHADEREXTPROC) (GLuint id);
+typedef void (GLAPIENTRY * PFNGLDISABLEVARIANTCLIENTSTATEEXTPROC) (GLuint id);
+typedef void (GLAPIENTRY * PFNGLENABLEVARIANTCLIENTSTATEEXTPROC) (GLuint id);
+typedef void (GLAPIENTRY * PFNGLENDVERTEXSHADEREXTPROC) (void);
+typedef void (GLAPIENTRY * PFNGLEXTRACTCOMPONENTEXTPROC) (GLuint res, GLuint src, GLuint num);
+typedef GLuint (GLAPIENTRY * PFNGLGENSYMBOLSEXTPROC) (GLenum dataType, GLenum storageType, GLenum range, GLuint components);
+typedef GLuint (GLAPIENTRY * PFNGLGENVERTEXSHADERSEXTPROC) (GLuint range);
+typedef void (GLAPIENTRY * PFNGLGETINVARIANTBOOLEANVEXTPROC) (GLuint id, GLenum value, GLboolean *data);
+typedef void (GLAPIENTRY * PFNGLGETINVARIANTFLOATVEXTPROC) (GLuint id, GLenum value, GLfloat *data);
+typedef void (GLAPIENTRY * PFNGLGETINVARIANTINTEGERVEXTPROC) (GLuint id, GLenum value, GLint *data);
+typedef void (GLAPIENTRY * PFNGLGETLOCALCONSTANTBOOLEANVEXTPROC) (GLuint id, GLenum value, GLboolean *data);
+typedef void (GLAPIENTRY * PFNGLGETLOCALCONSTANTFLOATVEXTPROC) (GLuint id, GLenum value, GLfloat *data);
+typedef void (GLAPIENTRY * PFNGLGETLOCALCONSTANTINTEGERVEXTPROC) (GLuint id, GLenum value, GLint *data);
+typedef void (GLAPIENTRY * PFNGLGETVARIANTBOOLEANVEXTPROC) (GLuint id, GLenum value, GLboolean *data);
+typedef void (GLAPIENTRY * PFNGLGETVARIANTFLOATVEXTPROC) (GLuint id, GLenum value, GLfloat *data);
+typedef void (GLAPIENTRY * PFNGLGETVARIANTINTEGERVEXTPROC) (GLuint id, GLenum value, GLint *data);
+typedef void (GLAPIENTRY * PFNGLGETVARIANTPOINTERVEXTPROC) (GLuint id, GLenum value, GLvoid **data);
+typedef void (GLAPIENTRY * PFNGLINSERTCOMPONENTEXTPROC) (GLuint res, GLuint src, GLuint num);
+typedef GLboolean (GLAPIENTRY * PFNGLISVARIANTENABLEDEXTPROC) (GLuint id, GLenum cap);
+typedef void (GLAPIENTRY * PFNGLSETINVARIANTEXTPROC) (GLuint id, GLenum type, GLvoid *addr);
+typedef void (GLAPIENTRY * PFNGLSETLOCALCONSTANTEXTPROC) (GLuint id, GLenum type, GLvoid *addr);
+typedef void (GLAPIENTRY * PFNGLSHADEROP1EXTPROC) (GLenum op, GLuint res, GLuint arg1);
+typedef void (GLAPIENTRY * PFNGLSHADEROP2EXTPROC) (GLenum op, GLuint res, GLuint arg1, GLuint arg2);
+typedef void (GLAPIENTRY * PFNGLSHADEROP3EXTPROC) (GLenum op, GLuint res, GLuint arg1, GLuint arg2, GLuint arg3);
+typedef void (GLAPIENTRY * PFNGLSWIZZLEEXTPROC) (GLuint res, GLuint in, GLenum outX, GLenum outY, GLenum outZ, GLenum outW);
+typedef void (GLAPIENTRY * PFNGLVARIANTPOINTEREXTPROC) (GLuint id, GLenum type, GLuint stride, GLvoid *addr);
+typedef void (GLAPIENTRY * PFNGLVARIANTBVEXTPROC) (GLuint id, GLbyte *addr);
+typedef void (GLAPIENTRY * PFNGLVARIANTDVEXTPROC) (GLuint id, GLdouble *addr);
+typedef void (GLAPIENTRY * PFNGLVARIANTFVEXTPROC) (GLuint id, GLfloat *addr);
+typedef void (GLAPIENTRY * PFNGLVARIANTIVEXTPROC) (GLuint id, GLint *addr);
+typedef void (GLAPIENTRY * PFNGLVARIANTSVEXTPROC) (GLuint id, GLshort *addr);
+typedef void (GLAPIENTRY * PFNGLVARIANTUBVEXTPROC) (GLuint id, GLubyte *addr);
+typedef void (GLAPIENTRY * PFNGLVARIANTUIVEXTPROC) (GLuint id, GLuint *addr);
+typedef void (GLAPIENTRY * PFNGLVARIANTUSVEXTPROC) (GLuint id, GLushort *addr);
+typedef void (GLAPIENTRY * PFNGLWRITEMASKEXTPROC) (GLuint res, GLuint in, GLenum outX, GLenum outY, GLenum outZ, GLenum outW);
+
+#define glBeginVertexShaderEXT GLEW_GET_FUN(__glewBeginVertexShaderEXT)
+#define glBindLightParameterEXT GLEW_GET_FUN(__glewBindLightParameterEXT)
+#define glBindMaterialParameterEXT GLEW_GET_FUN(__glewBindMaterialParameterEXT)
+#define glBindParameterEXT GLEW_GET_FUN(__glewBindParameterEXT)
+#define glBindTexGenParameterEXT GLEW_GET_FUN(__glewBindTexGenParameterEXT)
+#define glBindTextureUnitParameterEXT GLEW_GET_FUN(__glewBindTextureUnitParameterEXT)
+#define glBindVertexShaderEXT GLEW_GET_FUN(__glewBindVertexShaderEXT)
+#define glDeleteVertexShaderEXT GLEW_GET_FUN(__glewDeleteVertexShaderEXT)
+#define glDisableVariantClientStateEXT GLEW_GET_FUN(__glewDisableVariantClientStateEXT)
+#define glEnableVariantClientStateEXT GLEW_GET_FUN(__glewEnableVariantClientStateEXT)
+#define glEndVertexShaderEXT GLEW_GET_FUN(__glewEndVertexShaderEXT)
+#define glExtractComponentEXT GLEW_GET_FUN(__glewExtractComponentEXT)
+#define glGenSymbolsEXT GLEW_GET_FUN(__glewGenSymbolsEXT)
+#define glGenVertexShadersEXT GLEW_GET_FUN(__glewGenVertexShadersEXT)
+#define glGetInvariantBooleanvEXT GLEW_GET_FUN(__glewGetInvariantBooleanvEXT)
+#define glGetInvariantFloatvEXT GLEW_GET_FUN(__glewGetInvariantFloatvEXT)
+#define glGetInvariantIntegervEXT GLEW_GET_FUN(__glewGetInvariantIntegervEXT)
+#define glGetLocalConstantBooleanvEXT GLEW_GET_FUN(__glewGetLocalConstantBooleanvEXT)
+#define glGetLocalConstantFloatvEXT GLEW_GET_FUN(__glewGetLocalConstantFloatvEXT)
+#define glGetLocalConstantIntegervEXT GLEW_GET_FUN(__glewGetLocalConstantIntegervEXT)
+#define glGetVariantBooleanvEXT GLEW_GET_FUN(__glewGetVariantBooleanvEXT)
+#define glGetVariantFloatvEXT GLEW_GET_FUN(__glewGetVariantFloatvEXT)
+#define glGetVariantIntegervEXT GLEW_GET_FUN(__glewGetVariantIntegervEXT)
+#define glGetVariantPointervEXT GLEW_GET_FUN(__glewGetVariantPointervEXT)
+#define glInsertComponentEXT GLEW_GET_FUN(__glewInsertComponentEXT)
+#define glIsVariantEnabledEXT GLEW_GET_FUN(__glewIsVariantEnabledEXT)
+#define glSetInvariantEXT GLEW_GET_FUN(__glewSetInvariantEXT)
+#define glSetLocalConstantEXT GLEW_GET_FUN(__glewSetLocalConstantEXT)
+#define glShaderOp1EXT GLEW_GET_FUN(__glewShaderOp1EXT)
+#define glShaderOp2EXT GLEW_GET_FUN(__glewShaderOp2EXT)
+#define glShaderOp3EXT GLEW_GET_FUN(__glewShaderOp3EXT)
+#define glSwizzleEXT GLEW_GET_FUN(__glewSwizzleEXT)
+#define glVariantPointerEXT GLEW_GET_FUN(__glewVariantPointerEXT)
+#define glVariantbvEXT GLEW_GET_FUN(__glewVariantbvEXT)
+#define glVariantdvEXT GLEW_GET_FUN(__glewVariantdvEXT)
+#define glVariantfvEXT GLEW_GET_FUN(__glewVariantfvEXT)
+#define glVariantivEXT GLEW_GET_FUN(__glewVariantivEXT)
+#define glVariantsvEXT GLEW_GET_FUN(__glewVariantsvEXT)
+#define glVariantubvEXT GLEW_GET_FUN(__glewVariantubvEXT)
+#define glVariantuivEXT GLEW_GET_FUN(__glewVariantuivEXT)
+#define glVariantusvEXT GLEW_GET_FUN(__glewVariantusvEXT)
+#define glWriteMaskEXT GLEW_GET_FUN(__glewWriteMaskEXT)
+
+#define GLEW_EXT_vertex_shader GLEW_GET_VAR(__GLEW_EXT_vertex_shader)
+
+#endif /* !GL_EXT_vertex_shader */
+
+/* ------------------------ GL_EXT_vertex_weighting ------------------------ */
+
+#if !defined(GL_EXT_vertex_weighting)
+#define GL_EXT_vertex_weighting 1
+
+#define GL_MODELVIEW0_STACK_DEPTH_EXT 0x0BA3
+#define GL_MODELVIEW0_MATRIX_EXT 0x0BA6
+#define GL_MODELVIEW0_EXT 0x1700
+#define GL_MODELVIEW1_STACK_DEPTH_EXT 0x8502
+#define GL_MODELVIEW1_MATRIX_EXT 0x8506
+#define GL_VERTEX_WEIGHTING_EXT 0x8509
+#define GL_MODELVIEW1_EXT 0x850A
+#define GL_CURRENT_VERTEX_WEIGHT_EXT 0x850B
+#define GL_VERTEX_WEIGHT_ARRAY_EXT 0x850C
+#define GL_VERTEX_WEIGHT_ARRAY_SIZE_EXT 0x850D
+#define GL_VERTEX_WEIGHT_ARRAY_TYPE_EXT 0x850E
+#define GL_VERTEX_WEIGHT_ARRAY_STRIDE_EXT 0x850F
+#define GL_VERTEX_WEIGHT_ARRAY_POINTER_EXT 0x8510
+
+typedef void (GLAPIENTRY * PFNGLVERTEXWEIGHTPOINTEREXTPROC) (GLint size, GLenum type, GLsizei stride, void* pointer);
+typedef void (GLAPIENTRY * PFNGLVERTEXWEIGHTFEXTPROC) (GLfloat weight);
+typedef void (GLAPIENTRY * PFNGLVERTEXWEIGHTFVEXTPROC) (GLfloat* weight);
+
+#define glVertexWeightPointerEXT GLEW_GET_FUN(__glewVertexWeightPointerEXT)
+#define glVertexWeightfEXT GLEW_GET_FUN(__glewVertexWeightfEXT)
+#define glVertexWeightfvEXT GLEW_GET_FUN(__glewVertexWeightfvEXT)
+
+#define GLEW_EXT_vertex_weighting GLEW_GET_VAR(__GLEW_EXT_vertex_weighting)
+
+#endif /* !GL_EXT_vertex_weighting */
+
+/* ------------------------- GL_EXT_x11_sync_object ------------------------ */
+
+#if !defined(GL_EXT_x11_sync_object)
+#define GL_EXT_x11_sync_object 1
+
+#define GL_SYNC_X11_FENCE_EXT 0x90E1
+
+typedef GLsync (GLAPIENTRY * PFNGLIMPORTSYNCEXTPROC) (GLenum external_sync_type, GLintptr external_sync, GLbitfield flags);
+
+#define glImportSyncEXT GLEW_GET_FUN(__glewImportSyncEXT)
+
+#define GLEW_EXT_x11_sync_object GLEW_GET_VAR(__GLEW_EXT_x11_sync_object)
+
+#endif /* !GL_EXT_x11_sync_object */
+
+/* ---------------------- GL_GREMEDY_frame_terminator ---------------------- */
+
+#if !defined(GL_GREMEDY_frame_terminator)
+#define GL_GREMEDY_frame_terminator 1
+
+typedef void (GLAPIENTRY * PFNGLFRAMETERMINATORGREMEDYPROC) (void);
+
+#define glFrameTerminatorGREMEDY GLEW_GET_FUN(__glewFrameTerminatorGREMEDY)
+
+#define GLEW_GREMEDY_frame_terminator GLEW_GET_VAR(__GLEW_GREMEDY_frame_terminator)
+
+#endif /* !GL_GREMEDY_frame_terminator */
+
+/* ------------------------ GL_GREMEDY_string_marker ----------------------- */
+
+#if !defined(GL_GREMEDY_string_marker)
+#define GL_GREMEDY_string_marker 1
+
+typedef void (GLAPIENTRY * PFNGLSTRINGMARKERGREMEDYPROC) (GLsizei len, const void* string);
+
+#define glStringMarkerGREMEDY GLEW_GET_FUN(__glewStringMarkerGREMEDY)
+
+#define GLEW_GREMEDY_string_marker GLEW_GET_VAR(__GLEW_GREMEDY_string_marker)
+
+#endif /* !GL_GREMEDY_string_marker */
+
+/* --------------------- GL_HP_convolution_border_modes -------------------- */
+
+#if !defined(GL_HP_convolution_border_modes)
+#define GL_HP_convolution_border_modes 1
+
+#define GLEW_HP_convolution_border_modes GLEW_GET_VAR(__GLEW_HP_convolution_border_modes)
+
+#endif /* !GL_HP_convolution_border_modes */
+
+/* ------------------------- GL_HP_image_transform ------------------------- */
+
+#if !defined(GL_HP_image_transform)
+#define GL_HP_image_transform 1
+
+typedef void (GLAPIENTRY * PFNGLGETIMAGETRANSFORMPARAMETERFVHPPROC) (GLenum target, GLenum pname, const GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLGETIMAGETRANSFORMPARAMETERIVHPPROC) (GLenum target, GLenum pname, const GLint* params);
+typedef void (GLAPIENTRY * PFNGLIMAGETRANSFORMPARAMETERFHPPROC) (GLenum target, GLenum pname, const GLfloat param);
+typedef void (GLAPIENTRY * PFNGLIMAGETRANSFORMPARAMETERFVHPPROC) (GLenum target, GLenum pname, const GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLIMAGETRANSFORMPARAMETERIHPPROC) (GLenum target, GLenum pname, const GLint param);
+typedef void (GLAPIENTRY * PFNGLIMAGETRANSFORMPARAMETERIVHPPROC) (GLenum target, GLenum pname, const GLint* params);
+
+#define glGetImageTransformParameterfvHP GLEW_GET_FUN(__glewGetImageTransformParameterfvHP)
+#define glGetImageTransformParameterivHP GLEW_GET_FUN(__glewGetImageTransformParameterivHP)
+#define glImageTransformParameterfHP GLEW_GET_FUN(__glewImageTransformParameterfHP)
+#define glImageTransformParameterfvHP GLEW_GET_FUN(__glewImageTransformParameterfvHP)
+#define glImageTransformParameteriHP GLEW_GET_FUN(__glewImageTransformParameteriHP)
+#define glImageTransformParameterivHP GLEW_GET_FUN(__glewImageTransformParameterivHP)
+
+#define GLEW_HP_image_transform GLEW_GET_VAR(__GLEW_HP_image_transform)
+
+#endif /* !GL_HP_image_transform */
+
+/* -------------------------- GL_HP_occlusion_test ------------------------- */
+
+#if !defined(GL_HP_occlusion_test)
+#define GL_HP_occlusion_test 1
+
+#define GL_OCCLUSION_TEST_HP 0x8165
+#define GL_OCCLUSION_TEST_RESULT_HP 0x8166
+
+#define GLEW_HP_occlusion_test GLEW_GET_VAR(__GLEW_HP_occlusion_test)
+
+#endif /* !GL_HP_occlusion_test */
+
+/* ------------------------- GL_HP_texture_lighting ------------------------ */
+
+#if !defined(GL_HP_texture_lighting)
+#define GL_HP_texture_lighting 1
+
+#define GLEW_HP_texture_lighting GLEW_GET_VAR(__GLEW_HP_texture_lighting)
+
+#endif /* !GL_HP_texture_lighting */
+
+/* --------------------------- GL_IBM_cull_vertex -------------------------- */
+
+#if !defined(GL_IBM_cull_vertex)
+#define GL_IBM_cull_vertex 1
+
+#define GL_CULL_VERTEX_IBM 103050
+
+#define GLEW_IBM_cull_vertex GLEW_GET_VAR(__GLEW_IBM_cull_vertex)
+
+#endif /* !GL_IBM_cull_vertex */
+
+/* ---------------------- GL_IBM_multimode_draw_arrays --------------------- */
+
+#if !defined(GL_IBM_multimode_draw_arrays)
+#define GL_IBM_multimode_draw_arrays 1
+
+typedef void (GLAPIENTRY * PFNGLMULTIMODEDRAWARRAYSIBMPROC) (const GLenum* mode, const GLint *first, const GLsizei *count, GLsizei primcount, GLint modestride);
+typedef void (GLAPIENTRY * PFNGLMULTIMODEDRAWELEMENTSIBMPROC) (const GLenum* mode, const GLsizei *count, GLenum type, const GLvoid * const *indices, GLsizei primcount, GLint modestride);
+
+#define glMultiModeDrawArraysIBM GLEW_GET_FUN(__glewMultiModeDrawArraysIBM)
+#define glMultiModeDrawElementsIBM GLEW_GET_FUN(__glewMultiModeDrawElementsIBM)
+
+#define GLEW_IBM_multimode_draw_arrays GLEW_GET_VAR(__GLEW_IBM_multimode_draw_arrays)
+
+#endif /* !GL_IBM_multimode_draw_arrays */
+
+/* ------------------------- GL_IBM_rasterpos_clip ------------------------- */
+
+#if !defined(GL_IBM_rasterpos_clip)
+#define GL_IBM_rasterpos_clip 1
+
+#define GL_RASTER_POSITION_UNCLIPPED_IBM 103010
+
+#define GLEW_IBM_rasterpos_clip GLEW_GET_VAR(__GLEW_IBM_rasterpos_clip)
+
+#endif /* !GL_IBM_rasterpos_clip */
+
+/* --------------------------- GL_IBM_static_data -------------------------- */
+
+#if !defined(GL_IBM_static_data)
+#define GL_IBM_static_data 1
+
+#define GL_ALL_STATIC_DATA_IBM 103060
+#define GL_STATIC_VERTEX_ARRAY_IBM 103061
+
+#define GLEW_IBM_static_data GLEW_GET_VAR(__GLEW_IBM_static_data)
+
+#endif /* !GL_IBM_static_data */
+
+/* --------------------- GL_IBM_texture_mirrored_repeat -------------------- */
+
+#if !defined(GL_IBM_texture_mirrored_repeat)
+#define GL_IBM_texture_mirrored_repeat 1
+
+#define GL_MIRRORED_REPEAT_IBM 0x8370
+
+#define GLEW_IBM_texture_mirrored_repeat GLEW_GET_VAR(__GLEW_IBM_texture_mirrored_repeat)
+
+#endif /* !GL_IBM_texture_mirrored_repeat */
+
+/* ----------------------- GL_IBM_vertex_array_lists ----------------------- */
+
+#if !defined(GL_IBM_vertex_array_lists)
+#define GL_IBM_vertex_array_lists 1
+
+#define GL_VERTEX_ARRAY_LIST_IBM 103070
+#define GL_NORMAL_ARRAY_LIST_IBM 103071
+#define GL_COLOR_ARRAY_LIST_IBM 103072
+#define GL_INDEX_ARRAY_LIST_IBM 103073
+#define GL_TEXTURE_COORD_ARRAY_LIST_IBM 103074
+#define GL_EDGE_FLAG_ARRAY_LIST_IBM 103075
+#define GL_FOG_COORDINATE_ARRAY_LIST_IBM 103076
+#define GL_SECONDARY_COLOR_ARRAY_LIST_IBM 103077
+#define GL_VERTEX_ARRAY_LIST_STRIDE_IBM 103080
+#define GL_NORMAL_ARRAY_LIST_STRIDE_IBM 103081
+#define GL_COLOR_ARRAY_LIST_STRIDE_IBM 103082
+#define GL_INDEX_ARRAY_LIST_STRIDE_IBM 103083
+#define GL_TEXTURE_COORD_ARRAY_LIST_STRIDE_IBM 103084
+#define GL_EDGE_FLAG_ARRAY_LIST_STRIDE_IBM 103085
+#define GL_FOG_COORDINATE_ARRAY_LIST_STRIDE_IBM 103086
+#define GL_SECONDARY_COLOR_ARRAY_LIST_STRIDE_IBM 103087
+
+typedef void (GLAPIENTRY * PFNGLCOLORPOINTERLISTIBMPROC) (GLint size, GLenum type, GLint stride, const GLvoid ** pointer, GLint ptrstride);
+typedef void (GLAPIENTRY * PFNGLEDGEFLAGPOINTERLISTIBMPROC) (GLint stride, const GLboolean ** pointer, GLint ptrstride);
+typedef void (GLAPIENTRY * PFNGLFOGCOORDPOINTERLISTIBMPROC) (GLenum type, GLint stride, const GLvoid ** pointer, GLint ptrstride);
+typedef void (GLAPIENTRY * PFNGLINDEXPOINTERLISTIBMPROC) (GLenum type, GLint stride, const GLvoid ** pointer, GLint ptrstride);
+typedef void (GLAPIENTRY * PFNGLNORMALPOINTERLISTIBMPROC) (GLenum type, GLint stride, const GLvoid ** pointer, GLint ptrstride);
+typedef void (GLAPIENTRY * PFNGLSECONDARYCOLORPOINTERLISTIBMPROC) (GLint size, GLenum type, GLint stride, const GLvoid ** pointer, GLint ptrstride);
+typedef void (GLAPIENTRY * PFNGLTEXCOORDPOINTERLISTIBMPROC) (GLint size, GLenum type, GLint stride, const GLvoid ** pointer, GLint ptrstride);
+typedef void (GLAPIENTRY * PFNGLVERTEXPOINTERLISTIBMPROC) (GLint size, GLenum type, GLint stride, const GLvoid ** pointer, GLint ptrstride);
+
+#define glColorPointerListIBM GLEW_GET_FUN(__glewColorPointerListIBM)
+#define glEdgeFlagPointerListIBM GLEW_GET_FUN(__glewEdgeFlagPointerListIBM)
+#define glFogCoordPointerListIBM GLEW_GET_FUN(__glewFogCoordPointerListIBM)
+#define glIndexPointerListIBM GLEW_GET_FUN(__glewIndexPointerListIBM)
+#define glNormalPointerListIBM GLEW_GET_FUN(__glewNormalPointerListIBM)
+#define glSecondaryColorPointerListIBM GLEW_GET_FUN(__glewSecondaryColorPointerListIBM)
+#define glTexCoordPointerListIBM GLEW_GET_FUN(__glewTexCoordPointerListIBM)
+#define glVertexPointerListIBM GLEW_GET_FUN(__glewVertexPointerListIBM)
+
+#define GLEW_IBM_vertex_array_lists GLEW_GET_VAR(__GLEW_IBM_vertex_array_lists)
+
+#endif /* !GL_IBM_vertex_array_lists */
+
+/* -------------------------- GL_INGR_color_clamp -------------------------- */
+
+#if !defined(GL_INGR_color_clamp)
+#define GL_INGR_color_clamp 1
+
+#define GL_RED_MIN_CLAMP_INGR 0x8560
+#define GL_GREEN_MIN_CLAMP_INGR 0x8561
+#define GL_BLUE_MIN_CLAMP_INGR 0x8562
+#define GL_ALPHA_MIN_CLAMP_INGR 0x8563
+#define GL_RED_MAX_CLAMP_INGR 0x8564
+#define GL_GREEN_MAX_CLAMP_INGR 0x8565
+#define GL_BLUE_MAX_CLAMP_INGR 0x8566
+#define GL_ALPHA_MAX_CLAMP_INGR 0x8567
+
+#define GLEW_INGR_color_clamp GLEW_GET_VAR(__GLEW_INGR_color_clamp)
+
+#endif /* !GL_INGR_color_clamp */
+
+/* ------------------------- GL_INGR_interlace_read ------------------------ */
+
+#if !defined(GL_INGR_interlace_read)
+#define GL_INGR_interlace_read 1
+
+#define GL_INTERLACE_READ_INGR 0x8568
+
+#define GLEW_INGR_interlace_read GLEW_GET_VAR(__GLEW_INGR_interlace_read)
+
+#endif /* !GL_INGR_interlace_read */
+
+/* -------------------------- GL_INTEL_map_texture ------------------------- */
+
+#if !defined(GL_INTEL_map_texture)
+#define GL_INTEL_map_texture 1
+
+#define GL_LAYOUT_DEFAULT_INTEL 0
+#define GL_LAYOUT_LINEAR_INTEL 1
+#define GL_LAYOUT_LINEAR_CPU_CACHED_INTEL 2
+#define GL_TEXTURE_MEMORY_LAYOUT_INTEL 0x83FF
+
+typedef GLvoid * (GLAPIENTRY * PFNGLMAPTEXTURE2DINTELPROC) (GLuint texture, GLint level, GLbitfield access, GLint* stride, GLenum *layout);
+typedef void (GLAPIENTRY * PFNGLSYNCTEXTUREINTELPROC) (GLuint texture);
+typedef void (GLAPIENTRY * PFNGLUNMAPTEXTURE2DINTELPROC) (GLuint texture, GLint level);
+
+#define glMapTexture2DINTEL GLEW_GET_FUN(__glewMapTexture2DINTEL)
+#define glSyncTextureINTEL GLEW_GET_FUN(__glewSyncTextureINTEL)
+#define glUnmapTexture2DINTEL GLEW_GET_FUN(__glewUnmapTexture2DINTEL)
+
+#define GLEW_INTEL_map_texture GLEW_GET_VAR(__GLEW_INTEL_map_texture)
+
+#endif /* !GL_INTEL_map_texture */
+
+/* ------------------------ GL_INTEL_parallel_arrays ----------------------- */
+
+#if !defined(GL_INTEL_parallel_arrays)
+#define GL_INTEL_parallel_arrays 1
+
+#define GL_PARALLEL_ARRAYS_INTEL 0x83F4
+#define GL_VERTEX_ARRAY_PARALLEL_POINTERS_INTEL 0x83F5
+#define GL_NORMAL_ARRAY_PARALLEL_POINTERS_INTEL 0x83F6
+#define GL_COLOR_ARRAY_PARALLEL_POINTERS_INTEL 0x83F7
+#define GL_TEXTURE_COORD_ARRAY_PARALLEL_POINTERS_INTEL 0x83F8
+
+typedef void (GLAPIENTRY * PFNGLCOLORPOINTERVINTELPROC) (GLint size, GLenum type, const void** pointer);
+typedef void (GLAPIENTRY * PFNGLNORMALPOINTERVINTELPROC) (GLenum type, const void** pointer);
+typedef void (GLAPIENTRY * PFNGLTEXCOORDPOINTERVINTELPROC) (GLint size, GLenum type, const void** pointer);
+typedef void (GLAPIENTRY * PFNGLVERTEXPOINTERVINTELPROC) (GLint size, GLenum type, const void** pointer);
+
+#define glColorPointervINTEL GLEW_GET_FUN(__glewColorPointervINTEL)
+#define glNormalPointervINTEL GLEW_GET_FUN(__glewNormalPointervINTEL)
+#define glTexCoordPointervINTEL GLEW_GET_FUN(__glewTexCoordPointervINTEL)
+#define glVertexPointervINTEL GLEW_GET_FUN(__glewVertexPointervINTEL)
+
+#define GLEW_INTEL_parallel_arrays GLEW_GET_VAR(__GLEW_INTEL_parallel_arrays)
+
+#endif /* !GL_INTEL_parallel_arrays */
+
+/* ------------------------ GL_INTEL_texture_scissor ----------------------- */
+
+#if !defined(GL_INTEL_texture_scissor)
+#define GL_INTEL_texture_scissor 1
+
+typedef void (GLAPIENTRY * PFNGLTEXSCISSORFUNCINTELPROC) (GLenum target, GLenum lfunc, GLenum hfunc);
+typedef void (GLAPIENTRY * PFNGLTEXSCISSORINTELPROC) (GLenum target, GLclampf tlow, GLclampf thigh);
+
+#define glTexScissorFuncINTEL GLEW_GET_FUN(__glewTexScissorFuncINTEL)
+#define glTexScissorINTEL GLEW_GET_FUN(__glewTexScissorINTEL)
+
+#define GLEW_INTEL_texture_scissor GLEW_GET_VAR(__GLEW_INTEL_texture_scissor)
+
+#endif /* !GL_INTEL_texture_scissor */
+
+/* ------------------------------ GL_KHR_debug ----------------------------- */
+
+#if !defined(GL_KHR_debug)
+#define GL_KHR_debug 1
+
+#define GL_CONTEXT_FLAG_DEBUG_BIT 0x00000002
+#define GL_STACK_OVERFLOW 0x0503
+#define GL_STACK_UNDERFLOW 0x0504
+#define GL_DEBUG_OUTPUT_SYNCHRONOUS 0x8242
+#define GL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH 0x8243
+#define GL_DEBUG_CALLBACK_FUNCTION 0x8244
+#define GL_DEBUG_CALLBACK_USER_PARAM 0x8245
+#define GL_DEBUG_SOURCE_API 0x8246
+#define GL_DEBUG_SOURCE_WINDOW_SYSTEM 0x8247
+#define GL_DEBUG_SOURCE_SHADER_COMPILER 0x8248
+#define GL_DEBUG_SOURCE_THIRD_PARTY 0x8249
+#define GL_DEBUG_SOURCE_APPLICATION 0x824A
+#define GL_DEBUG_SOURCE_OTHER 0x824B
+#define GL_DEBUG_TYPE_ERROR 0x824C
+#define GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR 0x824D
+#define GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR 0x824E
+#define GL_DEBUG_TYPE_PORTABILITY 0x824F
+#define GL_DEBUG_TYPE_PERFORMANCE 0x8250
+#define GL_DEBUG_TYPE_OTHER 0x8251
+#define GL_DEBUG_TYPE_MARKER 0x8268
+#define GL_DEBUG_TYPE_PUSH_GROUP 0x8269
+#define GL_DEBUG_TYPE_POP_GROUP 0x826A
+#define GL_DEBUG_SEVERITY_NOTIFICATION 0x826B
+#define GL_MAX_DEBUG_GROUP_STACK_DEPTH 0x826C
+#define GL_DEBUG_GROUP_STACK_DEPTH 0x826D
+#define GL_BUFFER 0x82E0
+#define GL_SHADER 0x82E1
+#define GL_PROGRAM 0x82E2
+#define GL_QUERY 0x82E3
+#define GL_PROGRAM_PIPELINE 0x82E4
+#define GL_SAMPLER 0x82E6
+#define GL_DISPLAY_LIST 0x82E7
+#define GL_MAX_LABEL_LENGTH 0x82E8
+#define GL_MAX_DEBUG_MESSAGE_LENGTH 0x9143
+#define GL_MAX_DEBUG_LOGGED_MESSAGES 0x9144
+#define GL_DEBUG_LOGGED_MESSAGES 0x9145
+#define GL_DEBUG_SEVERITY_HIGH 0x9146
+#define GL_DEBUG_SEVERITY_MEDIUM 0x9147
+#define GL_DEBUG_SEVERITY_LOW 0x9148
+#define GL_DEBUG_OUTPUT 0x92E0
+
+typedef void (APIENTRY *GLDEBUGPROC)(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar* message, GLvoid* userParam);
+
+typedef void (GLAPIENTRY * PFNGLDEBUGMESSAGECALLBACKPROC) (GLDEBUGPROC callback, void* userParam);
+typedef void (GLAPIENTRY * PFNGLDEBUGMESSAGECONTROLPROC) (GLenum source, GLenum type, GLenum severity, GLsizei count, const GLuint* ids, GLboolean enabled);
+typedef void (GLAPIENTRY * PFNGLDEBUGMESSAGEINSERTPROC) (GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const char* buf);
+typedef GLuint (GLAPIENTRY * PFNGLGETDEBUGMESSAGELOGPROC) (GLuint count, GLsizei bufsize, GLenum* sources, GLenum* types, GLuint* ids, GLenum* severities, GLsizei* lengths, char* messageLog);
+typedef void (GLAPIENTRY * PFNGLGETOBJECTLABELPROC) (GLenum identifier, GLuint name, GLsizei bufSize, GLsizei* length, char *label);
+typedef void (GLAPIENTRY * PFNGLGETOBJECTPTRLABELPROC) (void* ptr, GLsizei bufSize, GLsizei* length, char *label);
+typedef void (GLAPIENTRY * PFNGLGETPOINTERVPROC) (GLenum pname, void** params);
+typedef void (GLAPIENTRY * PFNGLOBJECTLABELPROC) (GLenum identifier, GLuint name, GLsizei length, const char* label);
+typedef void (GLAPIENTRY * PFNGLOBJECTPTRLABELPROC) (void* ptr, GLsizei length, const char* label);
+typedef void (GLAPIENTRY * PFNGLPOPDEBUGGROUPPROC) (void);
+typedef void (GLAPIENTRY * PFNGLPUSHDEBUGGROUPPROC) (GLenum source, GLuint id, GLsizei length, const char * message);
+
+#define glDebugMessageCallback GLEW_GET_FUN(__glewDebugMessageCallback)
+#define glDebugMessageControl GLEW_GET_FUN(__glewDebugMessageControl)
+#define glDebugMessageInsert GLEW_GET_FUN(__glewDebugMessageInsert)
+#define glGetDebugMessageLog GLEW_GET_FUN(__glewGetDebugMessageLog)
+#define glGetObjectLabel GLEW_GET_FUN(__glewGetObjectLabel)
+#define glGetObjectPtrLabel GLEW_GET_FUN(__glewGetObjectPtrLabel)
+#define glGetPointerv GLEW_GET_FUN(__glewGetPointerv)
+#define glObjectLabel GLEW_GET_FUN(__glewObjectLabel)
+#define glObjectPtrLabel GLEW_GET_FUN(__glewObjectPtrLabel)
+#define glPopDebugGroup GLEW_GET_FUN(__glewPopDebugGroup)
+#define glPushDebugGroup GLEW_GET_FUN(__glewPushDebugGroup)
+
+#define GLEW_KHR_debug GLEW_GET_VAR(__GLEW_KHR_debug)
+
+#endif /* !GL_KHR_debug */
+
+/* ------------------ GL_KHR_texture_compression_astc_ldr ------------------ */
+
+#if !defined(GL_KHR_texture_compression_astc_ldr)
+#define GL_KHR_texture_compression_astc_ldr 1
+
+#define GL_COMPRESSED_RGBA_ASTC_4x4_KHR 0x93B0
+#define GL_COMPRESSED_RGBA_ASTC_5x4_KHR 0x93B1
+#define GL_COMPRESSED_RGBA_ASTC_5x5_KHR 0x93B2
+#define GL_COMPRESSED_RGBA_ASTC_6x5_KHR 0x93B3
+#define GL_COMPRESSED_RGBA_ASTC_6x6_KHR 0x93B4
+#define GL_COMPRESSED_RGBA_ASTC_8x5_KHR 0x93B5
+#define GL_COMPRESSED_RGBA_ASTC_8x6_KHR 0x93B6
+#define GL_COMPRESSED_RGBA_ASTC_8x8_KHR 0x93B7
+#define GL_COMPRESSED_RGBA_ASTC_10x5_KHR 0x93B8
+#define GL_COMPRESSED_RGBA_ASTC_10x6_KHR 0x93B9
+#define GL_COMPRESSED_RGBA_ASTC_10x8_KHR 0x93BA
+#define GL_COMPRESSED_RGBA_ASTC_10x10_KHR 0x93BB
+#define GL_COMPRESSED_RGBA_ASTC_12x10_KHR 0x93BC
+#define GL_COMPRESSED_RGBA_ASTC_12x12_KHR 0x93BD
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR 0x93D0
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR 0x93D1
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR 0x93D2
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR 0x93D3
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR 0x93D4
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR 0x93D5
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR 0x93D6
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR 0x93D7
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR 0x93D8
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR 0x93D9
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR 0x93DA
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR 0x93DB
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR 0x93DC
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR 0x93DD
+
+#define GLEW_KHR_texture_compression_astc_ldr GLEW_GET_VAR(__GLEW_KHR_texture_compression_astc_ldr)
+
+#endif /* !GL_KHR_texture_compression_astc_ldr */
+
+/* -------------------------- GL_KTX_buffer_region ------------------------- */
+
+#if !defined(GL_KTX_buffer_region)
+#define GL_KTX_buffer_region 1
+
+#define GL_KTX_FRONT_REGION 0x0
+#define GL_KTX_BACK_REGION 0x1
+#define GL_KTX_Z_REGION 0x2
+#define GL_KTX_STENCIL_REGION 0x3
+
+typedef GLuint (GLAPIENTRY * PFNGLBUFFERREGIONENABLEDPROC) (void);
+typedef void (GLAPIENTRY * PFNGLDELETEBUFFERREGIONPROC) (GLenum region);
+typedef void (GLAPIENTRY * PFNGLDRAWBUFFERREGIONPROC) (GLuint region, GLint x, GLint y, GLsizei width, GLsizei height, GLint xDest, GLint yDest);
+typedef GLuint (GLAPIENTRY * PFNGLNEWBUFFERREGIONPROC) (GLenum region);
+typedef void (GLAPIENTRY * PFNGLREADBUFFERREGIONPROC) (GLuint region, GLint x, GLint y, GLsizei width, GLsizei height);
+
+#define glBufferRegionEnabled GLEW_GET_FUN(__glewBufferRegionEnabled)
+#define glDeleteBufferRegion GLEW_GET_FUN(__glewDeleteBufferRegion)
+#define glDrawBufferRegion GLEW_GET_FUN(__glewDrawBufferRegion)
+#define glNewBufferRegion GLEW_GET_FUN(__glewNewBufferRegion)
+#define glReadBufferRegion GLEW_GET_FUN(__glewReadBufferRegion)
+
+#define GLEW_KTX_buffer_region GLEW_GET_VAR(__GLEW_KTX_buffer_region)
+
+#endif /* !GL_KTX_buffer_region */
+
+/* ------------------------- GL_MESAX_texture_stack ------------------------ */
+
+#if !defined(GL_MESAX_texture_stack)
+#define GL_MESAX_texture_stack 1
+
+#define GL_TEXTURE_1D_STACK_MESAX 0x8759
+#define GL_TEXTURE_2D_STACK_MESAX 0x875A
+#define GL_PROXY_TEXTURE_1D_STACK_MESAX 0x875B
+#define GL_PROXY_TEXTURE_2D_STACK_MESAX 0x875C
+#define GL_TEXTURE_1D_STACK_BINDING_MESAX 0x875D
+#define GL_TEXTURE_2D_STACK_BINDING_MESAX 0x875E
+
+#define GLEW_MESAX_texture_stack GLEW_GET_VAR(__GLEW_MESAX_texture_stack)
+
+#endif /* !GL_MESAX_texture_stack */
+
+/* -------------------------- GL_MESA_pack_invert -------------------------- */
+
+#if !defined(GL_MESA_pack_invert)
+#define GL_MESA_pack_invert 1
+
+#define GL_PACK_INVERT_MESA 0x8758
+
+#define GLEW_MESA_pack_invert GLEW_GET_VAR(__GLEW_MESA_pack_invert)
+
+#endif /* !GL_MESA_pack_invert */
+
+/* ------------------------- GL_MESA_resize_buffers ------------------------ */
+
+#if !defined(GL_MESA_resize_buffers)
+#define GL_MESA_resize_buffers 1
+
+typedef void (GLAPIENTRY * PFNGLRESIZEBUFFERSMESAPROC) (void);
+
+#define glResizeBuffersMESA GLEW_GET_FUN(__glewResizeBuffersMESA)
+
+#define GLEW_MESA_resize_buffers GLEW_GET_VAR(__GLEW_MESA_resize_buffers)
+
+#endif /* !GL_MESA_resize_buffers */
+
+/* --------------------------- GL_MESA_window_pos -------------------------- */
+
+#if !defined(GL_MESA_window_pos)
+#define GL_MESA_window_pos 1
+
+typedef void (GLAPIENTRY * PFNGLWINDOWPOS2DMESAPROC) (GLdouble x, GLdouble y);
+typedef void (GLAPIENTRY * PFNGLWINDOWPOS2DVMESAPROC) (const GLdouble* p);
+typedef void (GLAPIENTRY * PFNGLWINDOWPOS2FMESAPROC) (GLfloat x, GLfloat y);
+typedef void (GLAPIENTRY * PFNGLWINDOWPOS2FVMESAPROC) (const GLfloat* p);
+typedef void (GLAPIENTRY * PFNGLWINDOWPOS2IMESAPROC) (GLint x, GLint y);
+typedef void (GLAPIENTRY * PFNGLWINDOWPOS2IVMESAPROC) (const GLint* p);
+typedef void (GLAPIENTRY * PFNGLWINDOWPOS2SMESAPROC) (GLshort x, GLshort y);
+typedef void (GLAPIENTRY * PFNGLWINDOWPOS2SVMESAPROC) (const GLshort* p);
+typedef void (GLAPIENTRY * PFNGLWINDOWPOS3DMESAPROC) (GLdouble x, GLdouble y, GLdouble z);
+typedef void (GLAPIENTRY * PFNGLWINDOWPOS3DVMESAPROC) (const GLdouble* p);
+typedef void (GLAPIENTRY * PFNGLWINDOWPOS3FMESAPROC) (GLfloat x, GLfloat y, GLfloat z);
+typedef void (GLAPIENTRY * PFNGLWINDOWPOS3FVMESAPROC) (const GLfloat* p);
+typedef void (GLAPIENTRY * PFNGLWINDOWPOS3IMESAPROC) (GLint x, GLint y, GLint z);
+typedef void (GLAPIENTRY * PFNGLWINDOWPOS3IVMESAPROC) (const GLint* p);
+typedef void (GLAPIENTRY * PFNGLWINDOWPOS3SMESAPROC) (GLshort x, GLshort y, GLshort z);
+typedef void (GLAPIENTRY * PFNGLWINDOWPOS3SVMESAPROC) (const GLshort* p);
+typedef void (GLAPIENTRY * PFNGLWINDOWPOS4DMESAPROC) (GLdouble x, GLdouble y, GLdouble z, GLdouble);
+typedef void (GLAPIENTRY * PFNGLWINDOWPOS4DVMESAPROC) (const GLdouble* p);
+typedef void (GLAPIENTRY * PFNGLWINDOWPOS4FMESAPROC) (GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+typedef void (GLAPIENTRY * PFNGLWINDOWPOS4FVMESAPROC) (const GLfloat* p);
+typedef void (GLAPIENTRY * PFNGLWINDOWPOS4IMESAPROC) (GLint x, GLint y, GLint z, GLint w);
+typedef void (GLAPIENTRY * PFNGLWINDOWPOS4IVMESAPROC) (const GLint* p);
+typedef void (GLAPIENTRY * PFNGLWINDOWPOS4SMESAPROC) (GLshort x, GLshort y, GLshort z, GLshort w);
+typedef void (GLAPIENTRY * PFNGLWINDOWPOS4SVMESAPROC) (const GLshort* p);
+
+#define glWindowPos2dMESA GLEW_GET_FUN(__glewWindowPos2dMESA)
+#define glWindowPos2dvMESA GLEW_GET_FUN(__glewWindowPos2dvMESA)
+#define glWindowPos2fMESA GLEW_GET_FUN(__glewWindowPos2fMESA)
+#define glWindowPos2fvMESA GLEW_GET_FUN(__glewWindowPos2fvMESA)
+#define glWindowPos2iMESA GLEW_GET_FUN(__glewWindowPos2iMESA)
+#define glWindowPos2ivMESA GLEW_GET_FUN(__glewWindowPos2ivMESA)
+#define glWindowPos2sMESA GLEW_GET_FUN(__glewWindowPos2sMESA)
+#define glWindowPos2svMESA GLEW_GET_FUN(__glewWindowPos2svMESA)
+#define glWindowPos3dMESA GLEW_GET_FUN(__glewWindowPos3dMESA)
+#define glWindowPos3dvMESA GLEW_GET_FUN(__glewWindowPos3dvMESA)
+#define glWindowPos3fMESA GLEW_GET_FUN(__glewWindowPos3fMESA)
+#define glWindowPos3fvMESA GLEW_GET_FUN(__glewWindowPos3fvMESA)
+#define glWindowPos3iMESA GLEW_GET_FUN(__glewWindowPos3iMESA)
+#define glWindowPos3ivMESA GLEW_GET_FUN(__glewWindowPos3ivMESA)
+#define glWindowPos3sMESA GLEW_GET_FUN(__glewWindowPos3sMESA)
+#define glWindowPos3svMESA GLEW_GET_FUN(__glewWindowPos3svMESA)
+#define glWindowPos4dMESA GLEW_GET_FUN(__glewWindowPos4dMESA)
+#define glWindowPos4dvMESA GLEW_GET_FUN(__glewWindowPos4dvMESA)
+#define glWindowPos4fMESA GLEW_GET_FUN(__glewWindowPos4fMESA)
+#define glWindowPos4fvMESA GLEW_GET_FUN(__glewWindowPos4fvMESA)
+#define glWindowPos4iMESA GLEW_GET_FUN(__glewWindowPos4iMESA)
+#define glWindowPos4ivMESA GLEW_GET_FUN(__glewWindowPos4ivMESA)
+#define glWindowPos4sMESA GLEW_GET_FUN(__glewWindowPos4sMESA)
+#define glWindowPos4svMESA GLEW_GET_FUN(__glewWindowPos4svMESA)
+
+#define GLEW_MESA_window_pos GLEW_GET_VAR(__GLEW_MESA_window_pos)
+
+#endif /* !GL_MESA_window_pos */
+
+/* ------------------------- GL_MESA_ycbcr_texture ------------------------- */
+
+#if !defined(GL_MESA_ycbcr_texture)
+#define GL_MESA_ycbcr_texture 1
+
+#define GL_UNSIGNED_SHORT_8_8_MESA 0x85BA
+#define GL_UNSIGNED_SHORT_8_8_REV_MESA 0x85BB
+#define GL_YCBCR_MESA 0x8757
+
+#define GLEW_MESA_ycbcr_texture GLEW_GET_VAR(__GLEW_MESA_ycbcr_texture)
+
+#endif /* !GL_MESA_ycbcr_texture */
+
+/* ----------------------- GL_NVX_conditional_render ----------------------- */
+
+#if !defined(GL_NVX_conditional_render)
+#define GL_NVX_conditional_render 1
+
+typedef void (GLAPIENTRY * PFNGLBEGINCONDITIONALRENDERNVXPROC) (GLuint id);
+typedef void (GLAPIENTRY * PFNGLENDCONDITIONALRENDERNVXPROC) (void);
+
+#define glBeginConditionalRenderNVX GLEW_GET_FUN(__glewBeginConditionalRenderNVX)
+#define glEndConditionalRenderNVX GLEW_GET_FUN(__glewEndConditionalRenderNVX)
+
+#define GLEW_NVX_conditional_render GLEW_GET_VAR(__GLEW_NVX_conditional_render)
+
+#endif /* !GL_NVX_conditional_render */
+
+/* ------------------------- GL_NVX_gpu_memory_info ------------------------ */
+
+#if !defined(GL_NVX_gpu_memory_info)
+#define GL_NVX_gpu_memory_info 1
+
+#define GL_GPU_MEMORY_INFO_DEDICATED_VIDMEM_NVX 0x9047
+#define GL_GPU_MEMORY_INFO_TOTAL_AVAILABLE_MEMORY_NVX 0x9048
+#define GL_GPU_MEMORY_INFO_CURRENT_AVAILABLE_VIDMEM_NVX 0x9049
+#define GL_GPU_MEMORY_INFO_EVICTION_COUNT_NVX 0x904A
+#define GL_GPU_MEMORY_INFO_EVICTED_MEMORY_NVX 0x904B
+
+#define GLEW_NVX_gpu_memory_info GLEW_GET_VAR(__GLEW_NVX_gpu_memory_info)
+
+#endif /* !GL_NVX_gpu_memory_info */
+
+/* ------------------------- GL_NV_bindless_texture ------------------------ */
+
+#if !defined(GL_NV_bindless_texture)
+#define GL_NV_bindless_texture 1
+
+typedef GLuint64 (GLAPIENTRY * PFNGLGETIMAGEHANDLENVPROC) (GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum format);
+typedef GLuint64 (GLAPIENTRY * PFNGLGETTEXTUREHANDLENVPROC) (GLuint texture);
+typedef GLuint64 (GLAPIENTRY * PFNGLGETTEXTURESAMPLERHANDLENVPROC) (GLuint texture, GLuint sampler);
+typedef GLboolean (GLAPIENTRY * PFNGLISIMAGEHANDLERESIDENTNVPROC) (GLuint64 handle);
+typedef GLboolean (GLAPIENTRY * PFNGLISTEXTUREHANDLERESIDENTNVPROC) (GLuint64 handle);
+typedef void (GLAPIENTRY * PFNGLMAKEIMAGEHANDLENONRESIDENTNVPROC) (GLuint64 handle);
+typedef void (GLAPIENTRY * PFNGLMAKEIMAGEHANDLERESIDENTNVPROC) (GLuint64 handle, GLenum access);
+typedef void (GLAPIENTRY * PFNGLMAKETEXTUREHANDLENONRESIDENTNVPROC) (GLuint64 handle);
+typedef void (GLAPIENTRY * PFNGLMAKETEXTUREHANDLERESIDENTNVPROC) (GLuint64 handle);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMHANDLEUI64NVPROC) (GLuint program, GLint location, GLuint64 value);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMHANDLEUI64VNVPROC) (GLuint program, GLint location, GLsizei count, const GLuint64* values);
+typedef void (GLAPIENTRY * PFNGLUNIFORMHANDLEUI64NVPROC) (GLint location, GLuint64 value);
+typedef void (GLAPIENTRY * PFNGLUNIFORMHANDLEUI64VNVPROC) (GLint location, GLsizei count, const GLuint64* value);
+
+#define glGetImageHandleNV GLEW_GET_FUN(__glewGetImageHandleNV)
+#define glGetTextureHandleNV GLEW_GET_FUN(__glewGetTextureHandleNV)
+#define glGetTextureSamplerHandleNV GLEW_GET_FUN(__glewGetTextureSamplerHandleNV)
+#define glIsImageHandleResidentNV GLEW_GET_FUN(__glewIsImageHandleResidentNV)
+#define glIsTextureHandleResidentNV GLEW_GET_FUN(__glewIsTextureHandleResidentNV)
+#define glMakeImageHandleNonResidentNV GLEW_GET_FUN(__glewMakeImageHandleNonResidentNV)
+#define glMakeImageHandleResidentNV GLEW_GET_FUN(__glewMakeImageHandleResidentNV)
+#define glMakeTextureHandleNonResidentNV GLEW_GET_FUN(__glewMakeTextureHandleNonResidentNV)
+#define glMakeTextureHandleResidentNV GLEW_GET_FUN(__glewMakeTextureHandleResidentNV)
+#define glProgramUniformHandleui64NV GLEW_GET_FUN(__glewProgramUniformHandleui64NV)
+#define glProgramUniformHandleui64vNV GLEW_GET_FUN(__glewProgramUniformHandleui64vNV)
+#define glUniformHandleui64NV GLEW_GET_FUN(__glewUniformHandleui64NV)
+#define glUniformHandleui64vNV GLEW_GET_FUN(__glewUniformHandleui64vNV)
+
+#define GLEW_NV_bindless_texture GLEW_GET_VAR(__GLEW_NV_bindless_texture)
+
+#endif /* !GL_NV_bindless_texture */
+
+/* --------------------------- GL_NV_blend_square -------------------------- */
+
+#if !defined(GL_NV_blend_square)
+#define GL_NV_blend_square 1
+
+#define GLEW_NV_blend_square GLEW_GET_VAR(__GLEW_NV_blend_square)
+
+#endif /* !GL_NV_blend_square */
+
+/* ------------------------- GL_NV_compute_program5 ------------------------ */
+
+#if !defined(GL_NV_compute_program5)
+#define GL_NV_compute_program5 1
+
+#define GL_COMPUTE_PROGRAM_NV 0x90FB
+#define GL_COMPUTE_PROGRAM_PARAMETER_BUFFER_NV 0x90FC
+
+#define GLEW_NV_compute_program5 GLEW_GET_VAR(__GLEW_NV_compute_program5)
+
+#endif /* !GL_NV_compute_program5 */
+
+/* ------------------------ GL_NV_conditional_render ----------------------- */
+
+#if !defined(GL_NV_conditional_render)
+#define GL_NV_conditional_render 1
+
+#define GL_QUERY_WAIT_NV 0x8E13
+#define GL_QUERY_NO_WAIT_NV 0x8E14
+#define GL_QUERY_BY_REGION_WAIT_NV 0x8E15
+#define GL_QUERY_BY_REGION_NO_WAIT_NV 0x8E16
+
+typedef void (GLAPIENTRY * PFNGLBEGINCONDITIONALRENDERNVPROC) (GLuint id, GLenum mode);
+typedef void (GLAPIENTRY * PFNGLENDCONDITIONALRENDERNVPROC) (void);
+
+#define glBeginConditionalRenderNV GLEW_GET_FUN(__glewBeginConditionalRenderNV)
+#define glEndConditionalRenderNV GLEW_GET_FUN(__glewEndConditionalRenderNV)
+
+#define GLEW_NV_conditional_render GLEW_GET_VAR(__GLEW_NV_conditional_render)
+
+#endif /* !GL_NV_conditional_render */
+
+/* ----------------------- GL_NV_copy_depth_to_color ----------------------- */
+
+#if !defined(GL_NV_copy_depth_to_color)
+#define GL_NV_copy_depth_to_color 1
+
+#define GL_DEPTH_STENCIL_TO_RGBA_NV 0x886E
+#define GL_DEPTH_STENCIL_TO_BGRA_NV 0x886F
+
+#define GLEW_NV_copy_depth_to_color GLEW_GET_VAR(__GLEW_NV_copy_depth_to_color)
+
+#endif /* !GL_NV_copy_depth_to_color */
+
+/* ---------------------------- GL_NV_copy_image --------------------------- */
+
+#if !defined(GL_NV_copy_image)
+#define GL_NV_copy_image 1
+
+typedef void (GLAPIENTRY * PFNGLCOPYIMAGESUBDATANVPROC) (GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei width, GLsizei height, GLsizei depth);
+
+#define glCopyImageSubDataNV GLEW_GET_FUN(__glewCopyImageSubDataNV)
+
+#define GLEW_NV_copy_image GLEW_GET_VAR(__GLEW_NV_copy_image)
+
+#endif /* !GL_NV_copy_image */
+
+/* -------------------------- GL_NV_deep_texture3D ------------------------- */
+
+#if !defined(GL_NV_deep_texture3D)
+#define GL_NV_deep_texture3D 1
+
+#define GL_MAX_DEEP_3D_TEXTURE_WIDTH_HEIGHT_NV 0x90D0
+#define GL_MAX_DEEP_3D_TEXTURE_DEPTH_NV 0x90D1
+
+#define GLEW_NV_deep_texture3D GLEW_GET_VAR(__GLEW_NV_deep_texture3D)
+
+#endif /* !GL_NV_deep_texture3D */
+
+/* ------------------------ GL_NV_depth_buffer_float ----------------------- */
+
+#if !defined(GL_NV_depth_buffer_float)
+#define GL_NV_depth_buffer_float 1
+
+#define GL_DEPTH_COMPONENT32F_NV 0x8DAB
+#define GL_DEPTH32F_STENCIL8_NV 0x8DAC
+#define GL_FLOAT_32_UNSIGNED_INT_24_8_REV_NV 0x8DAD
+#define GL_DEPTH_BUFFER_FLOAT_MODE_NV 0x8DAF
+
+typedef void (GLAPIENTRY * PFNGLCLEARDEPTHDNVPROC) (GLdouble depth);
+typedef void (GLAPIENTRY * PFNGLDEPTHBOUNDSDNVPROC) (GLdouble zmin, GLdouble zmax);
+typedef void (GLAPIENTRY * PFNGLDEPTHRANGEDNVPROC) (GLdouble zNear, GLdouble zFar);
+
+#define glClearDepthdNV GLEW_GET_FUN(__glewClearDepthdNV)
+#define glDepthBoundsdNV GLEW_GET_FUN(__glewDepthBoundsdNV)
+#define glDepthRangedNV GLEW_GET_FUN(__glewDepthRangedNV)
+
+#define GLEW_NV_depth_buffer_float GLEW_GET_VAR(__GLEW_NV_depth_buffer_float)
+
+#endif /* !GL_NV_depth_buffer_float */
+
+/* --------------------------- GL_NV_depth_clamp --------------------------- */
+
+#if !defined(GL_NV_depth_clamp)
+#define GL_NV_depth_clamp 1
+
+#define GL_DEPTH_CLAMP_NV 0x864F
+
+#define GLEW_NV_depth_clamp GLEW_GET_VAR(__GLEW_NV_depth_clamp)
+
+#endif /* !GL_NV_depth_clamp */
+
+/* ---------------------- GL_NV_depth_range_unclamped ---------------------- */
+
+#if !defined(GL_NV_depth_range_unclamped)
+#define GL_NV_depth_range_unclamped 1
+
+#define GL_SAMPLE_COUNT_BITS_NV 0x8864
+#define GL_CURRENT_SAMPLE_COUNT_QUERY_NV 0x8865
+#define GL_QUERY_RESULT_NV 0x8866
+#define GL_QUERY_RESULT_AVAILABLE_NV 0x8867
+#define GL_SAMPLE_COUNT_NV 0x8914
+
+#define GLEW_NV_depth_range_unclamped GLEW_GET_VAR(__GLEW_NV_depth_range_unclamped)
+
+#endif /* !GL_NV_depth_range_unclamped */
+
+/* --------------------------- GL_NV_draw_texture -------------------------- */
+
+#if !defined(GL_NV_draw_texture)
+#define GL_NV_draw_texture 1
+
+typedef void (GLAPIENTRY * PFNGLDRAWTEXTURENVPROC) (GLuint texture, GLuint sampler, GLfloat x0, GLfloat y0, GLfloat x1, GLfloat y1, GLfloat z, GLfloat s0, GLfloat t0, GLfloat s1, GLfloat t1);
+
+#define glDrawTextureNV GLEW_GET_FUN(__glewDrawTextureNV)
+
+#define GLEW_NV_draw_texture GLEW_GET_VAR(__GLEW_NV_draw_texture)
+
+#endif /* !GL_NV_draw_texture */
+
+/* ---------------------------- GL_NV_evaluators --------------------------- */
+
+#if !defined(GL_NV_evaluators)
+#define GL_NV_evaluators 1
+
+#define GL_EVAL_2D_NV 0x86C0
+#define GL_EVAL_TRIANGULAR_2D_NV 0x86C1
+#define GL_MAP_TESSELLATION_NV 0x86C2
+#define GL_MAP_ATTRIB_U_ORDER_NV 0x86C3
+#define GL_MAP_ATTRIB_V_ORDER_NV 0x86C4
+#define GL_EVAL_FRACTIONAL_TESSELLATION_NV 0x86C5
+#define GL_EVAL_VERTEX_ATTRIB0_NV 0x86C6
+#define GL_EVAL_VERTEX_ATTRIB1_NV 0x86C7
+#define GL_EVAL_VERTEX_ATTRIB2_NV 0x86C8
+#define GL_EVAL_VERTEX_ATTRIB3_NV 0x86C9
+#define GL_EVAL_VERTEX_ATTRIB4_NV 0x86CA
+#define GL_EVAL_VERTEX_ATTRIB5_NV 0x86CB
+#define GL_EVAL_VERTEX_ATTRIB6_NV 0x86CC
+#define GL_EVAL_VERTEX_ATTRIB7_NV 0x86CD
+#define GL_EVAL_VERTEX_ATTRIB8_NV 0x86CE
+#define GL_EVAL_VERTEX_ATTRIB9_NV 0x86CF
+#define GL_EVAL_VERTEX_ATTRIB10_NV 0x86D0
+#define GL_EVAL_VERTEX_ATTRIB11_NV 0x86D1
+#define GL_EVAL_VERTEX_ATTRIB12_NV 0x86D2
+#define GL_EVAL_VERTEX_ATTRIB13_NV 0x86D3
+#define GL_EVAL_VERTEX_ATTRIB14_NV 0x86D4
+#define GL_EVAL_VERTEX_ATTRIB15_NV 0x86D5
+#define GL_MAX_MAP_TESSELLATION_NV 0x86D6
+#define GL_MAX_RATIONAL_EVAL_ORDER_NV 0x86D7
+
+typedef void (GLAPIENTRY * PFNGLEVALMAPSNVPROC) (GLenum target, GLenum mode);
+typedef void (GLAPIENTRY * PFNGLGETMAPATTRIBPARAMETERFVNVPROC) (GLenum target, GLuint index, GLenum pname, GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLGETMAPATTRIBPARAMETERIVNVPROC) (GLenum target, GLuint index, GLenum pname, GLint* params);
+typedef void (GLAPIENTRY * PFNGLGETMAPCONTROLPOINTSNVPROC) (GLenum target, GLuint index, GLenum type, GLsizei ustride, GLsizei vstride, GLboolean packed, void* points);
+typedef void (GLAPIENTRY * PFNGLGETMAPPARAMETERFVNVPROC) (GLenum target, GLenum pname, GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLGETMAPPARAMETERIVNVPROC) (GLenum target, GLenum pname, GLint* params);
+typedef void (GLAPIENTRY * PFNGLMAPCONTROLPOINTSNVPROC) (GLenum target, GLuint index, GLenum type, GLsizei ustride, GLsizei vstride, GLint uorder, GLint vorder, GLboolean packed, const void* points);
+typedef void (GLAPIENTRY * PFNGLMAPPARAMETERFVNVPROC) (GLenum target, GLenum pname, const GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLMAPPARAMETERIVNVPROC) (GLenum target, GLenum pname, const GLint* params);
+
+#define glEvalMapsNV GLEW_GET_FUN(__glewEvalMapsNV)
+#define glGetMapAttribParameterfvNV GLEW_GET_FUN(__glewGetMapAttribParameterfvNV)
+#define glGetMapAttribParameterivNV GLEW_GET_FUN(__glewGetMapAttribParameterivNV)
+#define glGetMapControlPointsNV GLEW_GET_FUN(__glewGetMapControlPointsNV)
+#define glGetMapParameterfvNV GLEW_GET_FUN(__glewGetMapParameterfvNV)
+#define glGetMapParameterivNV GLEW_GET_FUN(__glewGetMapParameterivNV)
+#define glMapControlPointsNV GLEW_GET_FUN(__glewMapControlPointsNV)
+#define glMapParameterfvNV GLEW_GET_FUN(__glewMapParameterfvNV)
+#define glMapParameterivNV GLEW_GET_FUN(__glewMapParameterivNV)
+
+#define GLEW_NV_evaluators GLEW_GET_VAR(__GLEW_NV_evaluators)
+
+#endif /* !GL_NV_evaluators */
+
+/* ----------------------- GL_NV_explicit_multisample ---------------------- */
+
+#if !defined(GL_NV_explicit_multisample)
+#define GL_NV_explicit_multisample 1
+
+#define GL_SAMPLE_POSITION_NV 0x8E50
+#define GL_SAMPLE_MASK_NV 0x8E51
+#define GL_SAMPLE_MASK_VALUE_NV 0x8E52
+#define GL_TEXTURE_BINDING_RENDERBUFFER_NV 0x8E53
+#define GL_TEXTURE_RENDERBUFFER_DATA_STORE_BINDING_NV 0x8E54
+#define GL_TEXTURE_RENDERBUFFER_NV 0x8E55
+#define GL_SAMPLER_RENDERBUFFER_NV 0x8E56
+#define GL_INT_SAMPLER_RENDERBUFFER_NV 0x8E57
+#define GL_UNSIGNED_INT_SAMPLER_RENDERBUFFER_NV 0x8E58
+#define GL_MAX_SAMPLE_MASK_WORDS_NV 0x8E59
+
+typedef void (GLAPIENTRY * PFNGLGETMULTISAMPLEFVNVPROC) (GLenum pname, GLuint index, GLfloat* val);
+typedef void (GLAPIENTRY * PFNGLSAMPLEMASKINDEXEDNVPROC) (GLuint index, GLbitfield mask);
+typedef void (GLAPIENTRY * PFNGLTEXRENDERBUFFERNVPROC) (GLenum target, GLuint renderbuffer);
+
+#define glGetMultisamplefvNV GLEW_GET_FUN(__glewGetMultisamplefvNV)
+#define glSampleMaskIndexedNV GLEW_GET_FUN(__glewSampleMaskIndexedNV)
+#define glTexRenderbufferNV GLEW_GET_FUN(__glewTexRenderbufferNV)
+
+#define GLEW_NV_explicit_multisample GLEW_GET_VAR(__GLEW_NV_explicit_multisample)
+
+#endif /* !GL_NV_explicit_multisample */
+
+/* ------------------------------ GL_NV_fence ------------------------------ */
+
+#if !defined(GL_NV_fence)
+#define GL_NV_fence 1
+
+#define GL_ALL_COMPLETED_NV 0x84F2
+#define GL_FENCE_STATUS_NV 0x84F3
+#define GL_FENCE_CONDITION_NV 0x84F4
+
+typedef void (GLAPIENTRY * PFNGLDELETEFENCESNVPROC) (GLsizei n, const GLuint* fences);
+typedef void (GLAPIENTRY * PFNGLFINISHFENCENVPROC) (GLuint fence);
+typedef void (GLAPIENTRY * PFNGLGENFENCESNVPROC) (GLsizei n, GLuint* fences);
+typedef void (GLAPIENTRY * PFNGLGETFENCEIVNVPROC) (GLuint fence, GLenum pname, GLint* params);
+typedef GLboolean (GLAPIENTRY * PFNGLISFENCENVPROC) (GLuint fence);
+typedef void (GLAPIENTRY * PFNGLSETFENCENVPROC) (GLuint fence, GLenum condition);
+typedef GLboolean (GLAPIENTRY * PFNGLTESTFENCENVPROC) (GLuint fence);
+
+#define glDeleteFencesNV GLEW_GET_FUN(__glewDeleteFencesNV)
+#define glFinishFenceNV GLEW_GET_FUN(__glewFinishFenceNV)
+#define glGenFencesNV GLEW_GET_FUN(__glewGenFencesNV)
+#define glGetFenceivNV GLEW_GET_FUN(__glewGetFenceivNV)
+#define glIsFenceNV GLEW_GET_FUN(__glewIsFenceNV)
+#define glSetFenceNV GLEW_GET_FUN(__glewSetFenceNV)
+#define glTestFenceNV GLEW_GET_FUN(__glewTestFenceNV)
+
+#define GLEW_NV_fence GLEW_GET_VAR(__GLEW_NV_fence)
+
+#endif /* !GL_NV_fence */
+
+/* --------------------------- GL_NV_float_buffer -------------------------- */
+
+#if !defined(GL_NV_float_buffer)
+#define GL_NV_float_buffer 1
+
+#define GL_FLOAT_R_NV 0x8880
+#define GL_FLOAT_RG_NV 0x8881
+#define GL_FLOAT_RGB_NV 0x8882
+#define GL_FLOAT_RGBA_NV 0x8883
+#define GL_FLOAT_R16_NV 0x8884
+#define GL_FLOAT_R32_NV 0x8885
+#define GL_FLOAT_RG16_NV 0x8886
+#define GL_FLOAT_RG32_NV 0x8887
+#define GL_FLOAT_RGB16_NV 0x8888
+#define GL_FLOAT_RGB32_NV 0x8889
+#define GL_FLOAT_RGBA16_NV 0x888A
+#define GL_FLOAT_RGBA32_NV 0x888B
+#define GL_TEXTURE_FLOAT_COMPONENTS_NV 0x888C
+#define GL_FLOAT_CLEAR_COLOR_VALUE_NV 0x888D
+#define GL_FLOAT_RGBA_MODE_NV 0x888E
+
+#define GLEW_NV_float_buffer GLEW_GET_VAR(__GLEW_NV_float_buffer)
+
+#endif /* !GL_NV_float_buffer */
+
+/* --------------------------- GL_NV_fog_distance -------------------------- */
+
+#if !defined(GL_NV_fog_distance)
+#define GL_NV_fog_distance 1
+
+#define GL_FOG_DISTANCE_MODE_NV 0x855A
+#define GL_EYE_RADIAL_NV 0x855B
+#define GL_EYE_PLANE_ABSOLUTE_NV 0x855C
+
+#define GLEW_NV_fog_distance GLEW_GET_VAR(__GLEW_NV_fog_distance)
+
+#endif /* !GL_NV_fog_distance */
+
+/* ------------------------- GL_NV_fragment_program ------------------------ */
+
+#if !defined(GL_NV_fragment_program)
+#define GL_NV_fragment_program 1
+
+#define GL_MAX_FRAGMENT_PROGRAM_LOCAL_PARAMETERS_NV 0x8868
+#define GL_FRAGMENT_PROGRAM_NV 0x8870
+#define GL_MAX_TEXTURE_COORDS_NV 0x8871
+#define GL_MAX_TEXTURE_IMAGE_UNITS_NV 0x8872
+#define GL_FRAGMENT_PROGRAM_BINDING_NV 0x8873
+#define GL_PROGRAM_ERROR_STRING_NV 0x8874
+
+typedef void (GLAPIENTRY * PFNGLGETPROGRAMNAMEDPARAMETERDVNVPROC) (GLuint id, GLsizei len, const GLubyte* name, GLdouble *params);
+typedef void (GLAPIENTRY * PFNGLGETPROGRAMNAMEDPARAMETERFVNVPROC) (GLuint id, GLsizei len, const GLubyte* name, GLfloat *params);
+typedef void (GLAPIENTRY * PFNGLPROGRAMNAMEDPARAMETER4DNVPROC) (GLuint id, GLsizei len, const GLubyte* name, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+typedef void (GLAPIENTRY * PFNGLPROGRAMNAMEDPARAMETER4DVNVPROC) (GLuint id, GLsizei len, const GLubyte* name, const GLdouble v[]);
+typedef void (GLAPIENTRY * PFNGLPROGRAMNAMEDPARAMETER4FNVPROC) (GLuint id, GLsizei len, const GLubyte* name, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+typedef void (GLAPIENTRY * PFNGLPROGRAMNAMEDPARAMETER4FVNVPROC) (GLuint id, GLsizei len, const GLubyte* name, const GLfloat v[]);
+
+#define glGetProgramNamedParameterdvNV GLEW_GET_FUN(__glewGetProgramNamedParameterdvNV)
+#define glGetProgramNamedParameterfvNV GLEW_GET_FUN(__glewGetProgramNamedParameterfvNV)
+#define glProgramNamedParameter4dNV GLEW_GET_FUN(__glewProgramNamedParameter4dNV)
+#define glProgramNamedParameter4dvNV GLEW_GET_FUN(__glewProgramNamedParameter4dvNV)
+#define glProgramNamedParameter4fNV GLEW_GET_FUN(__glewProgramNamedParameter4fNV)
+#define glProgramNamedParameter4fvNV GLEW_GET_FUN(__glewProgramNamedParameter4fvNV)
+
+#define GLEW_NV_fragment_program GLEW_GET_VAR(__GLEW_NV_fragment_program)
+
+#endif /* !GL_NV_fragment_program */
+
+/* ------------------------ GL_NV_fragment_program2 ------------------------ */
+
+#if !defined(GL_NV_fragment_program2)
+#define GL_NV_fragment_program2 1
+
+#define GL_MAX_PROGRAM_EXEC_INSTRUCTIONS_NV 0x88F4
+#define GL_MAX_PROGRAM_CALL_DEPTH_NV 0x88F5
+#define GL_MAX_PROGRAM_IF_DEPTH_NV 0x88F6
+#define GL_MAX_PROGRAM_LOOP_DEPTH_NV 0x88F7
+#define GL_MAX_PROGRAM_LOOP_COUNT_NV 0x88F8
+
+#define GLEW_NV_fragment_program2 GLEW_GET_VAR(__GLEW_NV_fragment_program2)
+
+#endif /* !GL_NV_fragment_program2 */
+
+/* ------------------------ GL_NV_fragment_program4 ------------------------ */
+
+#if !defined(GL_NV_fragment_program4)
+#define GL_NV_fragment_program4 1
+
+#define GLEW_NV_fragment_program4 GLEW_GET_VAR(__GLEW_NV_fragment_program4)
+
+#endif /* !GL_NV_fragment_program4 */
+
+/* --------------------- GL_NV_fragment_program_option --------------------- */
+
+#if !defined(GL_NV_fragment_program_option)
+#define GL_NV_fragment_program_option 1
+
+#define GLEW_NV_fragment_program_option GLEW_GET_VAR(__GLEW_NV_fragment_program_option)
+
+#endif /* !GL_NV_fragment_program_option */
+
+/* ----------------- GL_NV_framebuffer_multisample_coverage ---------------- */
+
+#if !defined(GL_NV_framebuffer_multisample_coverage)
+#define GL_NV_framebuffer_multisample_coverage 1
+
+#define GL_RENDERBUFFER_COVERAGE_SAMPLES_NV 0x8CAB
+#define GL_RENDERBUFFER_COLOR_SAMPLES_NV 0x8E10
+#define GL_MAX_MULTISAMPLE_COVERAGE_MODES_NV 0x8E11
+#define GL_MULTISAMPLE_COVERAGE_MODES_NV 0x8E12
+
+typedef void (GLAPIENTRY * PFNGLRENDERBUFFERSTORAGEMULTISAMPLECOVERAGENVPROC) (GLenum target, GLsizei coverageSamples, GLsizei colorSamples, GLenum internalformat, GLsizei width, GLsizei height);
+
+#define glRenderbufferStorageMultisampleCoverageNV GLEW_GET_FUN(__glewRenderbufferStorageMultisampleCoverageNV)
+
+#define GLEW_NV_framebuffer_multisample_coverage GLEW_GET_VAR(__GLEW_NV_framebuffer_multisample_coverage)
+
+#endif /* !GL_NV_framebuffer_multisample_coverage */
+
+/* ------------------------ GL_NV_geometry_program4 ------------------------ */
+
+#if !defined(GL_NV_geometry_program4)
+#define GL_NV_geometry_program4 1
+
+#define GL_GEOMETRY_PROGRAM_NV 0x8C26
+#define GL_MAX_PROGRAM_OUTPUT_VERTICES_NV 0x8C27
+#define GL_MAX_PROGRAM_TOTAL_OUTPUT_COMPONENTS_NV 0x8C28
+
+typedef void (GLAPIENTRY * PFNGLPROGRAMVERTEXLIMITNVPROC) (GLenum target, GLint limit);
+
+#define glProgramVertexLimitNV GLEW_GET_FUN(__glewProgramVertexLimitNV)
+
+#define GLEW_NV_geometry_program4 GLEW_GET_VAR(__GLEW_NV_geometry_program4)
+
+#endif /* !GL_NV_geometry_program4 */
+
+/* ------------------------- GL_NV_geometry_shader4 ------------------------ */
+
+#if !defined(GL_NV_geometry_shader4)
+#define GL_NV_geometry_shader4 1
+
+#define GLEW_NV_geometry_shader4 GLEW_GET_VAR(__GLEW_NV_geometry_shader4)
+
+#endif /* !GL_NV_geometry_shader4 */
+
+/* --------------------------- GL_NV_gpu_program4 -------------------------- */
+
+#if !defined(GL_NV_gpu_program4)
+#define GL_NV_gpu_program4 1
+
+#define GL_MIN_PROGRAM_TEXEL_OFFSET_NV 0x8904
+#define GL_MAX_PROGRAM_TEXEL_OFFSET_NV 0x8905
+#define GL_PROGRAM_ATTRIB_COMPONENTS_NV 0x8906
+#define GL_PROGRAM_RESULT_COMPONENTS_NV 0x8907
+#define GL_MAX_PROGRAM_ATTRIB_COMPONENTS_NV 0x8908
+#define GL_MAX_PROGRAM_RESULT_COMPONENTS_NV 0x8909
+#define GL_MAX_PROGRAM_GENERIC_ATTRIBS_NV 0x8DA5
+#define GL_MAX_PROGRAM_GENERIC_RESULTS_NV 0x8DA6
+
+typedef void (GLAPIENTRY * PFNGLPROGRAMENVPARAMETERI4INVPROC) (GLenum target, GLuint index, GLint x, GLint y, GLint z, GLint w);
+typedef void (GLAPIENTRY * PFNGLPROGRAMENVPARAMETERI4IVNVPROC) (GLenum target, GLuint index, const GLint *params);
+typedef void (GLAPIENTRY * PFNGLPROGRAMENVPARAMETERI4UINVPROC) (GLenum target, GLuint index, GLuint x, GLuint y, GLuint z, GLuint w);
+typedef void (GLAPIENTRY * PFNGLPROGRAMENVPARAMETERI4UIVNVPROC) (GLenum target, GLuint index, const GLuint *params);
+typedef void (GLAPIENTRY * PFNGLPROGRAMENVPARAMETERSI4IVNVPROC) (GLenum target, GLuint index, GLsizei count, const GLint *params);
+typedef void (GLAPIENTRY * PFNGLPROGRAMENVPARAMETERSI4UIVNVPROC) (GLenum target, GLuint index, GLsizei count, const GLuint *params);
+typedef void (GLAPIENTRY * PFNGLPROGRAMLOCALPARAMETERI4INVPROC) (GLenum target, GLuint index, GLint x, GLint y, GLint z, GLint w);
+typedef void (GLAPIENTRY * PFNGLPROGRAMLOCALPARAMETERI4IVNVPROC) (GLenum target, GLuint index, const GLint *params);
+typedef void (GLAPIENTRY * PFNGLPROGRAMLOCALPARAMETERI4UINVPROC) (GLenum target, GLuint index, GLuint x, GLuint y, GLuint z, GLuint w);
+typedef void (GLAPIENTRY * PFNGLPROGRAMLOCALPARAMETERI4UIVNVPROC) (GLenum target, GLuint index, const GLuint *params);
+typedef void (GLAPIENTRY * PFNGLPROGRAMLOCALPARAMETERSI4IVNVPROC) (GLenum target, GLuint index, GLsizei count, const GLint *params);
+typedef void (GLAPIENTRY * PFNGLPROGRAMLOCALPARAMETERSI4UIVNVPROC) (GLenum target, GLuint index, GLsizei count, const GLuint *params);
+
+#define glProgramEnvParameterI4iNV GLEW_GET_FUN(__glewProgramEnvParameterI4iNV)
+#define glProgramEnvParameterI4ivNV GLEW_GET_FUN(__glewProgramEnvParameterI4ivNV)
+#define glProgramEnvParameterI4uiNV GLEW_GET_FUN(__glewProgramEnvParameterI4uiNV)
+#define glProgramEnvParameterI4uivNV GLEW_GET_FUN(__glewProgramEnvParameterI4uivNV)
+#define glProgramEnvParametersI4ivNV GLEW_GET_FUN(__glewProgramEnvParametersI4ivNV)
+#define glProgramEnvParametersI4uivNV GLEW_GET_FUN(__glewProgramEnvParametersI4uivNV)
+#define glProgramLocalParameterI4iNV GLEW_GET_FUN(__glewProgramLocalParameterI4iNV)
+#define glProgramLocalParameterI4ivNV GLEW_GET_FUN(__glewProgramLocalParameterI4ivNV)
+#define glProgramLocalParameterI4uiNV GLEW_GET_FUN(__glewProgramLocalParameterI4uiNV)
+#define glProgramLocalParameterI4uivNV GLEW_GET_FUN(__glewProgramLocalParameterI4uivNV)
+#define glProgramLocalParametersI4ivNV GLEW_GET_FUN(__glewProgramLocalParametersI4ivNV)
+#define glProgramLocalParametersI4uivNV GLEW_GET_FUN(__glewProgramLocalParametersI4uivNV)
+
+#define GLEW_NV_gpu_program4 GLEW_GET_VAR(__GLEW_NV_gpu_program4)
+
+#endif /* !GL_NV_gpu_program4 */
+
+/* --------------------------- GL_NV_gpu_program5 -------------------------- */
+
+#if !defined(GL_NV_gpu_program5)
+#define GL_NV_gpu_program5 1
+
+#define GL_MAX_GEOMETRY_PROGRAM_INVOCATIONS_NV 0x8E5A
+#define GL_MIN_FRAGMENT_INTERPOLATION_OFFSET_NV 0x8E5B
+#define GL_MAX_FRAGMENT_INTERPOLATION_OFFSET_NV 0x8E5C
+#define GL_FRAGMENT_PROGRAM_INTERPOLATION_OFFSET_BITS_NV 0x8E5D
+#define GL_MIN_PROGRAM_TEXTURE_GATHER_OFFSET_NV 0x8E5E
+#define GL_MAX_PROGRAM_TEXTURE_GATHER_OFFSET_NV 0x8E5F
+
+#define GLEW_NV_gpu_program5 GLEW_GET_VAR(__GLEW_NV_gpu_program5)
+
+#endif /* !GL_NV_gpu_program5 */
+
+/* ------------------------- GL_NV_gpu_program_fp64 ------------------------ */
+
+#if !defined(GL_NV_gpu_program_fp64)
+#define GL_NV_gpu_program_fp64 1
+
+#define GLEW_NV_gpu_program_fp64 GLEW_GET_VAR(__GLEW_NV_gpu_program_fp64)
+
+#endif /* !GL_NV_gpu_program_fp64 */
+
+/* --------------------------- GL_NV_gpu_shader5 --------------------------- */
+
+#if !defined(GL_NV_gpu_shader5)
+#define GL_NV_gpu_shader5 1
+
+#define GL_INT64_NV 0x140E
+#define GL_UNSIGNED_INT64_NV 0x140F
+#define GL_INT8_NV 0x8FE0
+#define GL_INT8_VEC2_NV 0x8FE1
+#define GL_INT8_VEC3_NV 0x8FE2
+#define GL_INT8_VEC4_NV 0x8FE3
+#define GL_INT16_NV 0x8FE4
+#define GL_INT16_VEC2_NV 0x8FE5
+#define GL_INT16_VEC3_NV 0x8FE6
+#define GL_INT16_VEC4_NV 0x8FE7
+#define GL_INT64_VEC2_NV 0x8FE9
+#define GL_INT64_VEC3_NV 0x8FEA
+#define GL_INT64_VEC4_NV 0x8FEB
+#define GL_UNSIGNED_INT8_NV 0x8FEC
+#define GL_UNSIGNED_INT8_VEC2_NV 0x8FED
+#define GL_UNSIGNED_INT8_VEC3_NV 0x8FEE
+#define GL_UNSIGNED_INT8_VEC4_NV 0x8FEF
+#define GL_UNSIGNED_INT16_NV 0x8FF0
+#define GL_UNSIGNED_INT16_VEC2_NV 0x8FF1
+#define GL_UNSIGNED_INT16_VEC3_NV 0x8FF2
+#define GL_UNSIGNED_INT16_VEC4_NV 0x8FF3
+#define GL_UNSIGNED_INT64_VEC2_NV 0x8FF5
+#define GL_UNSIGNED_INT64_VEC3_NV 0x8FF6
+#define GL_UNSIGNED_INT64_VEC4_NV 0x8FF7
+#define GL_FLOAT16_NV 0x8FF8
+#define GL_FLOAT16_VEC2_NV 0x8FF9
+#define GL_FLOAT16_VEC3_NV 0x8FFA
+#define GL_FLOAT16_VEC4_NV 0x8FFB
+
+typedef void (GLAPIENTRY * PFNGLGETUNIFORMI64VNVPROC) (GLuint program, GLint location, GLint64EXT* params);
+typedef void (GLAPIENTRY * PFNGLGETUNIFORMUI64VNVPROC) (GLuint program, GLint location, GLuint64EXT* params);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM1I64NVPROC) (GLuint program, GLint location, GLint64EXT x);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM1I64VNVPROC) (GLuint program, GLint location, GLsizei count, const GLint64EXT* value);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM1UI64NVPROC) (GLuint program, GLint location, GLuint64EXT x);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM1UI64VNVPROC) (GLuint program, GLint location, GLsizei count, const GLuint64EXT* value);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM2I64NVPROC) (GLuint program, GLint location, GLint64EXT x, GLint64EXT y);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM2I64VNVPROC) (GLuint program, GLint location, GLsizei count, const GLint64EXT* value);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM2UI64NVPROC) (GLuint program, GLint location, GLuint64EXT x, GLuint64EXT y);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM2UI64VNVPROC) (GLuint program, GLint location, GLsizei count, const GLuint64EXT* value);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM3I64NVPROC) (GLuint program, GLint location, GLint64EXT x, GLint64EXT y, GLint64EXT z);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM3I64VNVPROC) (GLuint program, GLint location, GLsizei count, const GLint64EXT* value);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM3UI64NVPROC) (GLuint program, GLint location, GLuint64EXT x, GLuint64EXT y, GLuint64EXT z);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM3UI64VNVPROC) (GLuint program, GLint location, GLsizei count, const GLuint64EXT* value);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM4I64NVPROC) (GLuint program, GLint location, GLint64EXT x, GLint64EXT y, GLint64EXT z, GLint64EXT w);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM4I64VNVPROC) (GLuint program, GLint location, GLsizei count, const GLint64EXT* value);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM4UI64NVPROC) (GLuint program, GLint location, GLuint64EXT x, GLuint64EXT y, GLuint64EXT z, GLuint64EXT w);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM4UI64VNVPROC) (GLuint program, GLint location, GLsizei count, const GLuint64EXT* value);
+typedef void (GLAPIENTRY * PFNGLUNIFORM1I64NVPROC) (GLint location, GLint64EXT x);
+typedef void (GLAPIENTRY * PFNGLUNIFORM1I64VNVPROC) (GLint location, GLsizei count, const GLint64EXT* value);
+typedef void (GLAPIENTRY * PFNGLUNIFORM1UI64NVPROC) (GLint location, GLuint64EXT x);
+typedef void (GLAPIENTRY * PFNGLUNIFORM1UI64VNVPROC) (GLint location, GLsizei count, const GLuint64EXT* value);
+typedef void (GLAPIENTRY * PFNGLUNIFORM2I64NVPROC) (GLint location, GLint64EXT x, GLint64EXT y);
+typedef void (GLAPIENTRY * PFNGLUNIFORM2I64VNVPROC) (GLint location, GLsizei count, const GLint64EXT* value);
+typedef void (GLAPIENTRY * PFNGLUNIFORM2UI64NVPROC) (GLint location, GLuint64EXT x, GLuint64EXT y);
+typedef void (GLAPIENTRY * PFNGLUNIFORM2UI64VNVPROC) (GLint location, GLsizei count, const GLuint64EXT* value);
+typedef void (GLAPIENTRY * PFNGLUNIFORM3I64NVPROC) (GLint location, GLint64EXT x, GLint64EXT y, GLint64EXT z);
+typedef void (GLAPIENTRY * PFNGLUNIFORM3I64VNVPROC) (GLint location, GLsizei count, const GLint64EXT* value);
+typedef void (GLAPIENTRY * PFNGLUNIFORM3UI64NVPROC) (GLint location, GLuint64EXT x, GLuint64EXT y, GLuint64EXT z);
+typedef void (GLAPIENTRY * PFNGLUNIFORM3UI64VNVPROC) (GLint location, GLsizei count, const GLuint64EXT* value);
+typedef void (GLAPIENTRY * PFNGLUNIFORM4I64NVPROC) (GLint location, GLint64EXT x, GLint64EXT y, GLint64EXT z, GLint64EXT w);
+typedef void (GLAPIENTRY * PFNGLUNIFORM4I64VNVPROC) (GLint location, GLsizei count, const GLint64EXT* value);
+typedef void (GLAPIENTRY * PFNGLUNIFORM4UI64NVPROC) (GLint location, GLuint64EXT x, GLuint64EXT y, GLuint64EXT z, GLuint64EXT w);
+typedef void (GLAPIENTRY * PFNGLUNIFORM4UI64VNVPROC) (GLint location, GLsizei count, const GLuint64EXT* value);
+
+#define glGetUniformi64vNV GLEW_GET_FUN(__glewGetUniformi64vNV)
+#define glGetUniformui64vNV GLEW_GET_FUN(__glewGetUniformui64vNV)
+#define glProgramUniform1i64NV GLEW_GET_FUN(__glewProgramUniform1i64NV)
+#define glProgramUniform1i64vNV GLEW_GET_FUN(__glewProgramUniform1i64vNV)
+#define glProgramUniform1ui64NV GLEW_GET_FUN(__glewProgramUniform1ui64NV)
+#define glProgramUniform1ui64vNV GLEW_GET_FUN(__glewProgramUniform1ui64vNV)
+#define glProgramUniform2i64NV GLEW_GET_FUN(__glewProgramUniform2i64NV)
+#define glProgramUniform2i64vNV GLEW_GET_FUN(__glewProgramUniform2i64vNV)
+#define glProgramUniform2ui64NV GLEW_GET_FUN(__glewProgramUniform2ui64NV)
+#define glProgramUniform2ui64vNV GLEW_GET_FUN(__glewProgramUniform2ui64vNV)
+#define glProgramUniform3i64NV GLEW_GET_FUN(__glewProgramUniform3i64NV)
+#define glProgramUniform3i64vNV GLEW_GET_FUN(__glewProgramUniform3i64vNV)
+#define glProgramUniform3ui64NV GLEW_GET_FUN(__glewProgramUniform3ui64NV)
+#define glProgramUniform3ui64vNV GLEW_GET_FUN(__glewProgramUniform3ui64vNV)
+#define glProgramUniform4i64NV GLEW_GET_FUN(__glewProgramUniform4i64NV)
+#define glProgramUniform4i64vNV GLEW_GET_FUN(__glewProgramUniform4i64vNV)
+#define glProgramUniform4ui64NV GLEW_GET_FUN(__glewProgramUniform4ui64NV)
+#define glProgramUniform4ui64vNV GLEW_GET_FUN(__glewProgramUniform4ui64vNV)
+#define glUniform1i64NV GLEW_GET_FUN(__glewUniform1i64NV)
+#define glUniform1i64vNV GLEW_GET_FUN(__glewUniform1i64vNV)
+#define glUniform1ui64NV GLEW_GET_FUN(__glewUniform1ui64NV)
+#define glUniform1ui64vNV GLEW_GET_FUN(__glewUniform1ui64vNV)
+#define glUniform2i64NV GLEW_GET_FUN(__glewUniform2i64NV)
+#define glUniform2i64vNV GLEW_GET_FUN(__glewUniform2i64vNV)
+#define glUniform2ui64NV GLEW_GET_FUN(__glewUniform2ui64NV)
+#define glUniform2ui64vNV GLEW_GET_FUN(__glewUniform2ui64vNV)
+#define glUniform3i64NV GLEW_GET_FUN(__glewUniform3i64NV)
+#define glUniform3i64vNV GLEW_GET_FUN(__glewUniform3i64vNV)
+#define glUniform3ui64NV GLEW_GET_FUN(__glewUniform3ui64NV)
+#define glUniform3ui64vNV GLEW_GET_FUN(__glewUniform3ui64vNV)
+#define glUniform4i64NV GLEW_GET_FUN(__glewUniform4i64NV)
+#define glUniform4i64vNV GLEW_GET_FUN(__glewUniform4i64vNV)
+#define glUniform4ui64NV GLEW_GET_FUN(__glewUniform4ui64NV)
+#define glUniform4ui64vNV GLEW_GET_FUN(__glewUniform4ui64vNV)
+
+#define GLEW_NV_gpu_shader5 GLEW_GET_VAR(__GLEW_NV_gpu_shader5)
+
+#endif /* !GL_NV_gpu_shader5 */
+
+/* ---------------------------- GL_NV_half_float --------------------------- */
+
+#if !defined(GL_NV_half_float)
+#define GL_NV_half_float 1
+
+#define GL_HALF_FLOAT_NV 0x140B
+
+typedef unsigned short GLhalf;
+
+typedef void (GLAPIENTRY * PFNGLCOLOR3HNVPROC) (GLhalf red, GLhalf green, GLhalf blue);
+typedef void (GLAPIENTRY * PFNGLCOLOR3HVNVPROC) (const GLhalf* v);
+typedef void (GLAPIENTRY * PFNGLCOLOR4HNVPROC) (GLhalf red, GLhalf green, GLhalf blue, GLhalf alpha);
+typedef void (GLAPIENTRY * PFNGLCOLOR4HVNVPROC) (const GLhalf* v);
+typedef void (GLAPIENTRY * PFNGLFOGCOORDHNVPROC) (GLhalf fog);
+typedef void (GLAPIENTRY * PFNGLFOGCOORDHVNVPROC) (const GLhalf* fog);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD1HNVPROC) (GLenum target, GLhalf s);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD1HVNVPROC) (GLenum target, const GLhalf* v);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD2HNVPROC) (GLenum target, GLhalf s, GLhalf t);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD2HVNVPROC) (GLenum target, const GLhalf* v);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD3HNVPROC) (GLenum target, GLhalf s, GLhalf t, GLhalf r);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD3HVNVPROC) (GLenum target, const GLhalf* v);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD4HNVPROC) (GLenum target, GLhalf s, GLhalf t, GLhalf r, GLhalf q);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD4HVNVPROC) (GLenum target, const GLhalf* v);
+typedef void (GLAPIENTRY * PFNGLNORMAL3HNVPROC) (GLhalf nx, GLhalf ny, GLhalf nz);
+typedef void (GLAPIENTRY * PFNGLNORMAL3HVNVPROC) (const GLhalf* v);
+typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3HNVPROC) (GLhalf red, GLhalf green, GLhalf blue);
+typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3HVNVPROC) (const GLhalf* v);
+typedef void (GLAPIENTRY * PFNGLTEXCOORD1HNVPROC) (GLhalf s);
+typedef void (GLAPIENTRY * PFNGLTEXCOORD1HVNVPROC) (const GLhalf* v);
+typedef void (GLAPIENTRY * PFNGLTEXCOORD2HNVPROC) (GLhalf s, GLhalf t);
+typedef void (GLAPIENTRY * PFNGLTEXCOORD2HVNVPROC) (const GLhalf* v);
+typedef void (GLAPIENTRY * PFNGLTEXCOORD3HNVPROC) (GLhalf s, GLhalf t, GLhalf r);
+typedef void (GLAPIENTRY * PFNGLTEXCOORD3HVNVPROC) (const GLhalf* v);
+typedef void (GLAPIENTRY * PFNGLTEXCOORD4HNVPROC) (GLhalf s, GLhalf t, GLhalf r, GLhalf q);
+typedef void (GLAPIENTRY * PFNGLTEXCOORD4HVNVPROC) (const GLhalf* v);
+typedef void (GLAPIENTRY * PFNGLVERTEX2HNVPROC) (GLhalf x, GLhalf y);
+typedef void (GLAPIENTRY * PFNGLVERTEX2HVNVPROC) (const GLhalf* v);
+typedef void (GLAPIENTRY * PFNGLVERTEX3HNVPROC) (GLhalf x, GLhalf y, GLhalf z);
+typedef void (GLAPIENTRY * PFNGLVERTEX3HVNVPROC) (const GLhalf* v);
+typedef void (GLAPIENTRY * PFNGLVERTEX4HNVPROC) (GLhalf x, GLhalf y, GLhalf z, GLhalf w);
+typedef void (GLAPIENTRY * PFNGLVERTEX4HVNVPROC) (const GLhalf* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB1HNVPROC) (GLuint index, GLhalf x);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB1HVNVPROC) (GLuint index, const GLhalf* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB2HNVPROC) (GLuint index, GLhalf x, GLhalf y);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB2HVNVPROC) (GLuint index, const GLhalf* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB3HNVPROC) (GLuint index, GLhalf x, GLhalf y, GLhalf z);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB3HVNVPROC) (GLuint index, const GLhalf* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4HNVPROC) (GLuint index, GLhalf x, GLhalf y, GLhalf z, GLhalf w);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4HVNVPROC) (GLuint index, const GLhalf* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBS1HVNVPROC) (GLuint index, GLsizei n, const GLhalf* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBS2HVNVPROC) (GLuint index, GLsizei n, const GLhalf* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBS3HVNVPROC) (GLuint index, GLsizei n, const GLhalf* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBS4HVNVPROC) (GLuint index, GLsizei n, const GLhalf* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXWEIGHTHNVPROC) (GLhalf weight);
+typedef void (GLAPIENTRY * PFNGLVERTEXWEIGHTHVNVPROC) (const GLhalf* weight);
+
+#define glColor3hNV GLEW_GET_FUN(__glewColor3hNV)
+#define glColor3hvNV GLEW_GET_FUN(__glewColor3hvNV)
+#define glColor4hNV GLEW_GET_FUN(__glewColor4hNV)
+#define glColor4hvNV GLEW_GET_FUN(__glewColor4hvNV)
+#define glFogCoordhNV GLEW_GET_FUN(__glewFogCoordhNV)
+#define glFogCoordhvNV GLEW_GET_FUN(__glewFogCoordhvNV)
+#define glMultiTexCoord1hNV GLEW_GET_FUN(__glewMultiTexCoord1hNV)
+#define glMultiTexCoord1hvNV GLEW_GET_FUN(__glewMultiTexCoord1hvNV)
+#define glMultiTexCoord2hNV GLEW_GET_FUN(__glewMultiTexCoord2hNV)
+#define glMultiTexCoord2hvNV GLEW_GET_FUN(__glewMultiTexCoord2hvNV)
+#define glMultiTexCoord3hNV GLEW_GET_FUN(__glewMultiTexCoord3hNV)
+#define glMultiTexCoord3hvNV GLEW_GET_FUN(__glewMultiTexCoord3hvNV)
+#define glMultiTexCoord4hNV GLEW_GET_FUN(__glewMultiTexCoord4hNV)
+#define glMultiTexCoord4hvNV GLEW_GET_FUN(__glewMultiTexCoord4hvNV)
+#define glNormal3hNV GLEW_GET_FUN(__glewNormal3hNV)
+#define glNormal3hvNV GLEW_GET_FUN(__glewNormal3hvNV)
+#define glSecondaryColor3hNV GLEW_GET_FUN(__glewSecondaryColor3hNV)
+#define glSecondaryColor3hvNV GLEW_GET_FUN(__glewSecondaryColor3hvNV)
+#define glTexCoord1hNV GLEW_GET_FUN(__glewTexCoord1hNV)
+#define glTexCoord1hvNV GLEW_GET_FUN(__glewTexCoord1hvNV)
+#define glTexCoord2hNV GLEW_GET_FUN(__glewTexCoord2hNV)
+#define glTexCoord2hvNV GLEW_GET_FUN(__glewTexCoord2hvNV)
+#define glTexCoord3hNV GLEW_GET_FUN(__glewTexCoord3hNV)
+#define glTexCoord3hvNV GLEW_GET_FUN(__glewTexCoord3hvNV)
+#define glTexCoord4hNV GLEW_GET_FUN(__glewTexCoord4hNV)
+#define glTexCoord4hvNV GLEW_GET_FUN(__glewTexCoord4hvNV)
+#define glVertex2hNV GLEW_GET_FUN(__glewVertex2hNV)
+#define glVertex2hvNV GLEW_GET_FUN(__glewVertex2hvNV)
+#define glVertex3hNV GLEW_GET_FUN(__glewVertex3hNV)
+#define glVertex3hvNV GLEW_GET_FUN(__glewVertex3hvNV)
+#define glVertex4hNV GLEW_GET_FUN(__glewVertex4hNV)
+#define glVertex4hvNV GLEW_GET_FUN(__glewVertex4hvNV)
+#define glVertexAttrib1hNV GLEW_GET_FUN(__glewVertexAttrib1hNV)
+#define glVertexAttrib1hvNV GLEW_GET_FUN(__glewVertexAttrib1hvNV)
+#define glVertexAttrib2hNV GLEW_GET_FUN(__glewVertexAttrib2hNV)
+#define glVertexAttrib2hvNV GLEW_GET_FUN(__glewVertexAttrib2hvNV)
+#define glVertexAttrib3hNV GLEW_GET_FUN(__glewVertexAttrib3hNV)
+#define glVertexAttrib3hvNV GLEW_GET_FUN(__glewVertexAttrib3hvNV)
+#define glVertexAttrib4hNV GLEW_GET_FUN(__glewVertexAttrib4hNV)
+#define glVertexAttrib4hvNV GLEW_GET_FUN(__glewVertexAttrib4hvNV)
+#define glVertexAttribs1hvNV GLEW_GET_FUN(__glewVertexAttribs1hvNV)
+#define glVertexAttribs2hvNV GLEW_GET_FUN(__glewVertexAttribs2hvNV)
+#define glVertexAttribs3hvNV GLEW_GET_FUN(__glewVertexAttribs3hvNV)
+#define glVertexAttribs4hvNV GLEW_GET_FUN(__glewVertexAttribs4hvNV)
+#define glVertexWeighthNV GLEW_GET_FUN(__glewVertexWeighthNV)
+#define glVertexWeighthvNV GLEW_GET_FUN(__glewVertexWeighthvNV)
+
+#define GLEW_NV_half_float GLEW_GET_VAR(__GLEW_NV_half_float)
+
+#endif /* !GL_NV_half_float */
+
+/* ------------------------ GL_NV_light_max_exponent ----------------------- */
+
+#if !defined(GL_NV_light_max_exponent)
+#define GL_NV_light_max_exponent 1
+
+#define GL_MAX_SHININESS_NV 0x8504
+#define GL_MAX_SPOT_EXPONENT_NV 0x8505
+
+#define GLEW_NV_light_max_exponent GLEW_GET_VAR(__GLEW_NV_light_max_exponent)
+
+#endif /* !GL_NV_light_max_exponent */
+
+/* ----------------------- GL_NV_multisample_coverage ---------------------- */
+
+#if !defined(GL_NV_multisample_coverage)
+#define GL_NV_multisample_coverage 1
+
+#define GL_COVERAGE_SAMPLES_NV 0x80A9
+#define GL_COLOR_SAMPLES_NV 0x8E20
+
+#define GLEW_NV_multisample_coverage GLEW_GET_VAR(__GLEW_NV_multisample_coverage)
+
+#endif /* !GL_NV_multisample_coverage */
+
+/* --------------------- GL_NV_multisample_filter_hint --------------------- */
+
+#if !defined(GL_NV_multisample_filter_hint)
+#define GL_NV_multisample_filter_hint 1
+
+#define GL_MULTISAMPLE_FILTER_HINT_NV 0x8534
+
+#define GLEW_NV_multisample_filter_hint GLEW_GET_VAR(__GLEW_NV_multisample_filter_hint)
+
+#endif /* !GL_NV_multisample_filter_hint */
+
+/* ------------------------- GL_NV_occlusion_query ------------------------- */
+
+#if !defined(GL_NV_occlusion_query)
+#define GL_NV_occlusion_query 1
+
+#define GL_PIXEL_COUNTER_BITS_NV 0x8864
+#define GL_CURRENT_OCCLUSION_QUERY_ID_NV 0x8865
+#define GL_PIXEL_COUNT_NV 0x8866
+#define GL_PIXEL_COUNT_AVAILABLE_NV 0x8867
+
+typedef void (GLAPIENTRY * PFNGLBEGINOCCLUSIONQUERYNVPROC) (GLuint id);
+typedef void (GLAPIENTRY * PFNGLDELETEOCCLUSIONQUERIESNVPROC) (GLsizei n, const GLuint* ids);
+typedef void (GLAPIENTRY * PFNGLENDOCCLUSIONQUERYNVPROC) (void);
+typedef void (GLAPIENTRY * PFNGLGENOCCLUSIONQUERIESNVPROC) (GLsizei n, GLuint* ids);
+typedef void (GLAPIENTRY * PFNGLGETOCCLUSIONQUERYIVNVPROC) (GLuint id, GLenum pname, GLint* params);
+typedef void (GLAPIENTRY * PFNGLGETOCCLUSIONQUERYUIVNVPROC) (GLuint id, GLenum pname, GLuint* params);
+typedef GLboolean (GLAPIENTRY * PFNGLISOCCLUSIONQUERYNVPROC) (GLuint id);
+
+#define glBeginOcclusionQueryNV GLEW_GET_FUN(__glewBeginOcclusionQueryNV)
+#define glDeleteOcclusionQueriesNV GLEW_GET_FUN(__glewDeleteOcclusionQueriesNV)
+#define glEndOcclusionQueryNV GLEW_GET_FUN(__glewEndOcclusionQueryNV)
+#define glGenOcclusionQueriesNV GLEW_GET_FUN(__glewGenOcclusionQueriesNV)
+#define glGetOcclusionQueryivNV GLEW_GET_FUN(__glewGetOcclusionQueryivNV)
+#define glGetOcclusionQueryuivNV GLEW_GET_FUN(__glewGetOcclusionQueryuivNV)
+#define glIsOcclusionQueryNV GLEW_GET_FUN(__glewIsOcclusionQueryNV)
+
+#define GLEW_NV_occlusion_query GLEW_GET_VAR(__GLEW_NV_occlusion_query)
+
+#endif /* !GL_NV_occlusion_query */
+
+/* ----------------------- GL_NV_packed_depth_stencil ---------------------- */
+
+#if !defined(GL_NV_packed_depth_stencil)
+#define GL_NV_packed_depth_stencil 1
+
+#define GL_DEPTH_STENCIL_NV 0x84F9
+#define GL_UNSIGNED_INT_24_8_NV 0x84FA
+
+#define GLEW_NV_packed_depth_stencil GLEW_GET_VAR(__GLEW_NV_packed_depth_stencil)
+
+#endif /* !GL_NV_packed_depth_stencil */
+
+/* --------------------- GL_NV_parameter_buffer_object --------------------- */
+
+#if !defined(GL_NV_parameter_buffer_object)
+#define GL_NV_parameter_buffer_object 1
+
+#define GL_MAX_PROGRAM_PARAMETER_BUFFER_BINDINGS_NV 0x8DA0
+#define GL_MAX_PROGRAM_PARAMETER_BUFFER_SIZE_NV 0x8DA1
+#define GL_VERTEX_PROGRAM_PARAMETER_BUFFER_NV 0x8DA2
+#define GL_GEOMETRY_PROGRAM_PARAMETER_BUFFER_NV 0x8DA3
+#define GL_FRAGMENT_PROGRAM_PARAMETER_BUFFER_NV 0x8DA4
+
+typedef void (GLAPIENTRY * PFNGLPROGRAMBUFFERPARAMETERSIIVNVPROC) (GLenum target, GLuint buffer, GLuint index, GLsizei count, const GLint *params);
+typedef void (GLAPIENTRY * PFNGLPROGRAMBUFFERPARAMETERSIUIVNVPROC) (GLenum target, GLuint buffer, GLuint index, GLsizei count, const GLuint *params);
+typedef void (GLAPIENTRY * PFNGLPROGRAMBUFFERPARAMETERSFVNVPROC) (GLenum target, GLuint buffer, GLuint index, GLsizei count, const GLfloat *params);
+
+#define glProgramBufferParametersIivNV GLEW_GET_FUN(__glewProgramBufferParametersIivNV)
+#define glProgramBufferParametersIuivNV GLEW_GET_FUN(__glewProgramBufferParametersIuivNV)
+#define glProgramBufferParametersfvNV GLEW_GET_FUN(__glewProgramBufferParametersfvNV)
+
+#define GLEW_NV_parameter_buffer_object GLEW_GET_VAR(__GLEW_NV_parameter_buffer_object)
+
+#endif /* !GL_NV_parameter_buffer_object */
+
+/* --------------------- GL_NV_parameter_buffer_object2 -------------------- */
+
+#if !defined(GL_NV_parameter_buffer_object2)
+#define GL_NV_parameter_buffer_object2 1
+
+#define GLEW_NV_parameter_buffer_object2 GLEW_GET_VAR(__GLEW_NV_parameter_buffer_object2)
+
+#endif /* !GL_NV_parameter_buffer_object2 */
+
+/* -------------------------- GL_NV_path_rendering ------------------------- */
+
+#if !defined(GL_NV_path_rendering)
+#define GL_NV_path_rendering 1
+
+#define GL_CLOSE_PATH_NV 0x00
+#define GL_BOLD_BIT_NV 0x01
+#define GL_GLYPH_WIDTH_BIT_NV 0x01
+#define GL_GLYPH_HEIGHT_BIT_NV 0x02
+#define GL_ITALIC_BIT_NV 0x02
+#define GL_MOVE_TO_NV 0x02
+#define GL_RELATIVE_MOVE_TO_NV 0x03
+#define GL_LINE_TO_NV 0x04
+#define GL_GLYPH_HORIZONTAL_BEARING_X_BIT_NV 0x04
+#define GL_RELATIVE_LINE_TO_NV 0x05
+#define GL_HORIZONTAL_LINE_TO_NV 0x06
+#define GL_RELATIVE_HORIZONTAL_LINE_TO_NV 0x07
+#define GL_GLYPH_HORIZONTAL_BEARING_Y_BIT_NV 0x08
+#define GL_VERTICAL_LINE_TO_NV 0x08
+#define GL_RELATIVE_VERTICAL_LINE_TO_NV 0x09
+#define GL_QUADRATIC_CURVE_TO_NV 0x0A
+#define GL_RELATIVE_QUADRATIC_CURVE_TO_NV 0x0B
+#define GL_CUBIC_CURVE_TO_NV 0x0C
+#define GL_RELATIVE_CUBIC_CURVE_TO_NV 0x0D
+#define GL_SMOOTH_QUADRATIC_CURVE_TO_NV 0x0E
+#define GL_RELATIVE_SMOOTH_QUADRATIC_CURVE_TO_NV 0x0F
+#define GL_GLYPH_HORIZONTAL_BEARING_ADVANCE_BIT_NV 0x10
+#define GL_SMOOTH_CUBIC_CURVE_TO_NV 0x10
+#define GL_RELATIVE_SMOOTH_CUBIC_CURVE_TO_NV 0x11
+#define GL_SMALL_CCW_ARC_TO_NV 0x12
+#define GL_RELATIVE_SMALL_CCW_ARC_TO_NV 0x13
+#define GL_SMALL_CW_ARC_TO_NV 0x14
+#define GL_RELATIVE_SMALL_CW_ARC_TO_NV 0x15
+#define GL_LARGE_CCW_ARC_TO_NV 0x16
+#define GL_RELATIVE_LARGE_CCW_ARC_TO_NV 0x17
+#define GL_LARGE_CW_ARC_TO_NV 0x18
+#define GL_RELATIVE_LARGE_CW_ARC_TO_NV 0x19
+#define GL_GLYPH_VERTICAL_BEARING_X_BIT_NV 0x20
+#define GL_GLYPH_VERTICAL_BEARING_Y_BIT_NV 0x40
+#define GL_GLYPH_VERTICAL_BEARING_ADVANCE_BIT_NV 0x80
+#define GL_RESTART_PATH_NV 0xF0
+#define GL_DUP_FIRST_CUBIC_CURVE_TO_NV 0xF2
+#define GL_DUP_LAST_CUBIC_CURVE_TO_NV 0xF4
+#define GL_RECT_NV 0xF6
+#define GL_CIRCULAR_CCW_ARC_TO_NV 0xF8
+#define GL_CIRCULAR_CW_ARC_TO_NV 0xFA
+#define GL_CIRCULAR_TANGENT_ARC_TO_NV 0xFC
+#define GL_ARC_TO_NV 0xFE
+#define GL_RELATIVE_ARC_TO_NV 0xFF
+#define GL_GLYPH_HAS_KERNING_BIT_NV 0x100
+#define GL_PRIMARY_COLOR_NV 0x852C
+#define GL_SECONDARY_COLOR_NV 0x852D
+#define GL_PRIMARY_COLOR 0x8577
+#define GL_PATH_FORMAT_SVG_NV 0x9070
+#define GL_PATH_FORMAT_PS_NV 0x9071
+#define GL_STANDARD_FONT_NAME_NV 0x9072
+#define GL_SYSTEM_FONT_NAME_NV 0x9073
+#define GL_FILE_NAME_NV 0x9074
+#define GL_PATH_STROKE_WIDTH_NV 0x9075
+#define GL_PATH_END_CAPS_NV 0x9076
+#define GL_PATH_INITIAL_END_CAP_NV 0x9077
+#define GL_PATH_TERMINAL_END_CAP_NV 0x9078
+#define GL_PATH_JOIN_STYLE_NV 0x9079
+#define GL_PATH_MITER_LIMIT_NV 0x907A
+#define GL_PATH_DASH_CAPS_NV 0x907B
+#define GL_PATH_INITIAL_DASH_CAP_NV 0x907C
+#define GL_PATH_TERMINAL_DASH_CAP_NV 0x907D
+#define GL_PATH_DASH_OFFSET_NV 0x907E
+#define GL_PATH_CLIENT_LENGTH_NV 0x907F
+#define GL_PATH_FILL_MODE_NV 0x9080
+#define GL_PATH_FILL_MASK_NV 0x9081
+#define GL_PATH_FILL_COVER_MODE_NV 0x9082
+#define GL_PATH_STROKE_COVER_MODE_NV 0x9083
+#define GL_PATH_STROKE_MASK_NV 0x9084
+#define GL_COUNT_UP_NV 0x9088
+#define GL_COUNT_DOWN_NV 0x9089
+#define GL_PATH_OBJECT_BOUNDING_BOX_NV 0x908A
+#define GL_CONVEX_HULL_NV 0x908B
+#define GL_BOUNDING_BOX_NV 0x908D
+#define GL_TRANSLATE_X_NV 0x908E
+#define GL_TRANSLATE_Y_NV 0x908F
+#define GL_TRANSLATE_2D_NV 0x9090
+#define GL_TRANSLATE_3D_NV 0x9091
+#define GL_AFFINE_2D_NV 0x9092
+#define GL_AFFINE_3D_NV 0x9094
+#define GL_TRANSPOSE_AFFINE_2D_NV 0x9096
+#define GL_TRANSPOSE_AFFINE_3D_NV 0x9098
+#define GL_UTF8_NV 0x909A
+#define GL_UTF16_NV 0x909B
+#define GL_BOUNDING_BOX_OF_BOUNDING_BOXES_NV 0x909C
+#define GL_PATH_COMMAND_COUNT_NV 0x909D
+#define GL_PATH_COORD_COUNT_NV 0x909E
+#define GL_PATH_DASH_ARRAY_COUNT_NV 0x909F
+#define GL_PATH_COMPUTED_LENGTH_NV 0x90A0
+#define GL_PATH_FILL_BOUNDING_BOX_NV 0x90A1
+#define GL_PATH_STROKE_BOUNDING_BOX_NV 0x90A2
+#define GL_SQUARE_NV 0x90A3
+#define GL_ROUND_NV 0x90A4
+#define GL_TRIANGULAR_NV 0x90A5
+#define GL_BEVEL_NV 0x90A6
+#define GL_MITER_REVERT_NV 0x90A7
+#define GL_MITER_TRUNCATE_NV 0x90A8
+#define GL_SKIP_MISSING_GLYPH_NV 0x90A9
+#define GL_USE_MISSING_GLYPH_NV 0x90AA
+#define GL_PATH_ERROR_POSITION_NV 0x90AB
+#define GL_PATH_FOG_GEN_MODE_NV 0x90AC
+#define GL_ACCUM_ADJACENT_PAIRS_NV 0x90AD
+#define GL_ADJACENT_PAIRS_NV 0x90AE
+#define GL_FIRST_TO_REST_NV 0x90AF
+#define GL_PATH_GEN_MODE_NV 0x90B0
+#define GL_PATH_GEN_COEFF_NV 0x90B1
+#define GL_PATH_GEN_COLOR_FORMAT_NV 0x90B2
+#define GL_PATH_GEN_COMPONENTS_NV 0x90B3
+#define GL_PATH_DASH_OFFSET_RESET_NV 0x90B4
+#define GL_MOVE_TO_RESETS_NV 0x90B5
+#define GL_MOVE_TO_CONTINUES_NV 0x90B6
+#define GL_PATH_STENCIL_FUNC_NV 0x90B7
+#define GL_PATH_STENCIL_REF_NV 0x90B8
+#define GL_PATH_STENCIL_VALUE_MASK_NV 0x90B9
+#define GL_PATH_STENCIL_DEPTH_OFFSET_FACTOR_NV 0x90BD
+#define GL_PATH_STENCIL_DEPTH_OFFSET_UNITS_NV 0x90BE
+#define GL_PATH_COVER_DEPTH_FUNC_NV 0x90BF
+#define GL_FONT_X_MIN_BOUNDS_BIT_NV 0x00010000
+#define GL_FONT_Y_MIN_BOUNDS_BIT_NV 0x00020000
+#define GL_FONT_X_MAX_BOUNDS_BIT_NV 0x00040000
+#define GL_FONT_Y_MAX_BOUNDS_BIT_NV 0x00080000
+#define GL_FONT_UNITS_PER_EM_BIT_NV 0x00100000
+#define GL_FONT_ASCENDER_BIT_NV 0x00200000
+#define GL_FONT_DESCENDER_BIT_NV 0x00400000
+#define GL_FONT_HEIGHT_BIT_NV 0x00800000
+#define GL_FONT_MAX_ADVANCE_WIDTH_BIT_NV 0x01000000
+#define GL_FONT_MAX_ADVANCE_HEIGHT_BIT_NV 0x02000000
+#define GL_FONT_UNDERLINE_POSITION_BIT_NV 0x04000000
+#define GL_FONT_UNDERLINE_THICKNESS_BIT_NV 0x08000000
+#define GL_FONT_HAS_KERNING_BIT_NV 0x10000000
+
+typedef void (GLAPIENTRY * PFNGLCOPYPATHNVPROC) (GLuint resultPath, GLuint srcPath);
+typedef void (GLAPIENTRY * PFNGLCOVERFILLPATHINSTANCEDNVPROC) (GLsizei numPaths, GLenum pathNameType, const void* paths, GLuint pathBase, GLenum coverMode, GLenum transformType, const GLfloat *transformValues);
+typedef void (GLAPIENTRY * PFNGLCOVERFILLPATHNVPROC) (GLuint path, GLenum coverMode);
+typedef void (GLAPIENTRY * PFNGLCOVERSTROKEPATHINSTANCEDNVPROC) (GLsizei numPaths, GLenum pathNameType, const void* paths, GLuint pathBase, GLenum coverMode, GLenum transformType, const GLfloat *transformValues);
+typedef void (GLAPIENTRY * PFNGLCOVERSTROKEPATHNVPROC) (GLuint name, GLenum coverMode);
+typedef void (GLAPIENTRY * PFNGLDELETEPATHSNVPROC) (GLuint path, GLsizei range);
+typedef GLuint (GLAPIENTRY * PFNGLGENPATHSNVPROC) (GLsizei range);
+typedef void (GLAPIENTRY * PFNGLGETPATHCOLORGENFVNVPROC) (GLenum color, GLenum pname, GLfloat* value);
+typedef void (GLAPIENTRY * PFNGLGETPATHCOLORGENIVNVPROC) (GLenum color, GLenum pname, GLint* value);
+typedef void (GLAPIENTRY * PFNGLGETPATHCOMMANDSNVPROC) (GLuint name, GLubyte* commands);
+typedef void (GLAPIENTRY * PFNGLGETPATHCOORDSNVPROC) (GLuint name, GLfloat* coords);
+typedef void (GLAPIENTRY * PFNGLGETPATHDASHARRAYNVPROC) (GLuint name, GLfloat* dashArray);
+typedef GLfloat (GLAPIENTRY * PFNGLGETPATHLENGTHNVPROC) (GLuint path, GLsizei startSegment, GLsizei numSegments);
+typedef void (GLAPIENTRY * PFNGLGETPATHMETRICRANGENVPROC) (GLbitfield metricQueryMask, GLuint fistPathName, GLsizei numPaths, GLsizei stride, GLfloat* metrics);
+typedef void (GLAPIENTRY * PFNGLGETPATHMETRICSNVPROC) (GLbitfield metricQueryMask, GLsizei numPaths, GLenum pathNameType, const void* paths, GLuint pathBase, GLsizei stride, GLfloat *metrics);
+typedef void (GLAPIENTRY * PFNGLGETPATHPARAMETERFVNVPROC) (GLuint name, GLenum param, GLfloat* value);
+typedef void (GLAPIENTRY * PFNGLGETPATHPARAMETERIVNVPROC) (GLuint name, GLenum param, GLint* value);
+typedef void (GLAPIENTRY * PFNGLGETPATHSPACINGNVPROC) (GLenum pathListMode, GLsizei numPaths, GLenum pathNameType, const void* paths, GLuint pathBase, GLfloat advanceScale, GLfloat kerningScale, GLenum transformType, GLfloat *returnedSpacing);
+typedef void (GLAPIENTRY * PFNGLGETPATHTEXGENFVNVPROC) (GLenum texCoordSet, GLenum pname, GLfloat* value);
+typedef void (GLAPIENTRY * PFNGLGETPATHTEXGENIVNVPROC) (GLenum texCoordSet, GLenum pname, GLint* value);
+typedef void (GLAPIENTRY * PFNGLINTERPOLATEPATHSNVPROC) (GLuint resultPath, GLuint pathA, GLuint pathB, GLfloat weight);
+typedef GLboolean (GLAPIENTRY * PFNGLISPATHNVPROC) (GLuint path);
+typedef GLboolean (GLAPIENTRY * PFNGLISPOINTINFILLPATHNVPROC) (GLuint path, GLuint mask, GLfloat x, GLfloat y);
+typedef GLboolean (GLAPIENTRY * PFNGLISPOINTINSTROKEPATHNVPROC) (GLuint path, GLfloat x, GLfloat y);
+typedef void (GLAPIENTRY * PFNGLPATHCOLORGENNVPROC) (GLenum color, GLenum genMode, GLenum colorFormat, const GLfloat* coeffs);
+typedef void (GLAPIENTRY * PFNGLPATHCOMMANDSNVPROC) (GLuint path, GLsizei numCommands, const GLubyte* commands, GLsizei numCoords, GLenum coordType, const GLvoid*coords);
+typedef void (GLAPIENTRY * PFNGLPATHCOORDSNVPROC) (GLuint path, GLsizei numCoords, GLenum coordType, const void* coords);
+typedef void (GLAPIENTRY * PFNGLPATHCOVERDEPTHFUNCNVPROC) (GLenum zfunc);
+typedef void (GLAPIENTRY * PFNGLPATHDASHARRAYNVPROC) (GLuint path, GLsizei dashCount, const GLfloat* dashArray);
+typedef void (GLAPIENTRY * PFNGLPATHFOGGENNVPROC) (GLenum genMode);
+typedef void (GLAPIENTRY * PFNGLPATHGLYPHRANGENVPROC) (GLuint firstPathName, GLenum fontTarget, const void* fontName, GLbitfield fontStyle, GLuint firstGlyph, GLsizei numGlyphs, GLenum handleMissingGlyphs, GLuint pathParameterTemplate, GLfloat emScale);
+typedef void (GLAPIENTRY * PFNGLPATHGLYPHSNVPROC) (GLuint firstPathName, GLenum fontTarget, const void* fontName, GLbitfield fontStyle, GLsizei numGlyphs, GLenum type, const GLvoid*charcodes, GLenum handleMissingGlyphs, GLuint pathParameterTemplate, GLfloat emScale);
+typedef void (GLAPIENTRY * PFNGLPATHPARAMETERFNVPROC) (GLuint path, GLenum pname, GLfloat value);
+typedef void (GLAPIENTRY * PFNGLPATHPARAMETERFVNVPROC) (GLuint path, GLenum pname, const GLfloat* value);
+typedef void (GLAPIENTRY * PFNGLPATHPARAMETERINVPROC) (GLuint path, GLenum pname, GLint value);
+typedef void (GLAPIENTRY * PFNGLPATHPARAMETERIVNVPROC) (GLuint path, GLenum pname, const GLint* value);
+typedef void (GLAPIENTRY * PFNGLPATHSTENCILDEPTHOFFSETNVPROC) (GLfloat factor, GLfloat units);
+typedef void (GLAPIENTRY * PFNGLPATHSTENCILFUNCNVPROC) (GLenum func, GLint ref, GLuint mask);
+typedef void (GLAPIENTRY * PFNGLPATHSTRINGNVPROC) (GLuint path, GLenum format, GLsizei length, const void* pathString);
+typedef void (GLAPIENTRY * PFNGLPATHSUBCOMMANDSNVPROC) (GLuint path, GLsizei commandStart, GLsizei commandsToDelete, GLsizei numCommands, const GLubyte* commands, GLsizei numCoords, GLenum coordType, const GLvoid*coords);
+typedef void (GLAPIENTRY * PFNGLPATHSUBCOORDSNVPROC) (GLuint path, GLsizei coordStart, GLsizei numCoords, GLenum coordType, const void* coords);
+typedef void (GLAPIENTRY * PFNGLPATHTEXGENNVPROC) (GLenum texCoordSet, GLenum genMode, GLint components, const GLfloat* coeffs);
+typedef GLboolean (GLAPIENTRY * PFNGLPOINTALONGPATHNVPROC) (GLuint path, GLsizei startSegment, GLsizei numSegments, GLfloat distance, GLfloat* x, GLfloat *y, GLfloat *tangentX, GLfloat *tangentY);
+typedef void (GLAPIENTRY * PFNGLSTENCILFILLPATHINSTANCEDNVPROC) (GLsizei numPaths, GLenum pathNameType, const void* paths, GLuint pathBase, GLenum fillMode, GLuint mask, GLenum transformType, const GLfloat *transformValues);
+typedef void (GLAPIENTRY * PFNGLSTENCILFILLPATHNVPROC) (GLuint path, GLenum fillMode, GLuint mask);
+typedef void (GLAPIENTRY * PFNGLSTENCILSTROKEPATHINSTANCEDNVPROC) (GLsizei numPaths, GLenum pathNameType, const void* paths, GLuint pathBase, GLint reference, GLuint mask, GLenum transformType, const GLfloat *transformValues);
+typedef void (GLAPIENTRY * PFNGLSTENCILSTROKEPATHNVPROC) (GLuint path, GLint reference, GLuint mask);
+typedef void (GLAPIENTRY * PFNGLTRANSFORMPATHNVPROC) (GLuint resultPath, GLuint srcPath, GLenum transformType, const GLfloat* transformValues);
+typedef void (GLAPIENTRY * PFNGLWEIGHTPATHSNVPROC) (GLuint resultPath, GLsizei numPaths, const GLuint paths[], const GLfloat weights[]);
+
+#define glCopyPathNV GLEW_GET_FUN(__glewCopyPathNV)
+#define glCoverFillPathInstancedNV GLEW_GET_FUN(__glewCoverFillPathInstancedNV)
+#define glCoverFillPathNV GLEW_GET_FUN(__glewCoverFillPathNV)
+#define glCoverStrokePathInstancedNV GLEW_GET_FUN(__glewCoverStrokePathInstancedNV)
+#define glCoverStrokePathNV GLEW_GET_FUN(__glewCoverStrokePathNV)
+#define glDeletePathsNV GLEW_GET_FUN(__glewDeletePathsNV)
+#define glGenPathsNV GLEW_GET_FUN(__glewGenPathsNV)
+#define glGetPathColorGenfvNV GLEW_GET_FUN(__glewGetPathColorGenfvNV)
+#define glGetPathColorGenivNV GLEW_GET_FUN(__glewGetPathColorGenivNV)
+#define glGetPathCommandsNV GLEW_GET_FUN(__glewGetPathCommandsNV)
+#define glGetPathCoordsNV GLEW_GET_FUN(__glewGetPathCoordsNV)
+#define glGetPathDashArrayNV GLEW_GET_FUN(__glewGetPathDashArrayNV)
+#define glGetPathLengthNV GLEW_GET_FUN(__glewGetPathLengthNV)
+#define glGetPathMetricRangeNV GLEW_GET_FUN(__glewGetPathMetricRangeNV)
+#define glGetPathMetricsNV GLEW_GET_FUN(__glewGetPathMetricsNV)
+#define glGetPathParameterfvNV GLEW_GET_FUN(__glewGetPathParameterfvNV)
+#define glGetPathParameterivNV GLEW_GET_FUN(__glewGetPathParameterivNV)
+#define glGetPathSpacingNV GLEW_GET_FUN(__glewGetPathSpacingNV)
+#define glGetPathTexGenfvNV GLEW_GET_FUN(__glewGetPathTexGenfvNV)
+#define glGetPathTexGenivNV GLEW_GET_FUN(__glewGetPathTexGenivNV)
+#define glInterpolatePathsNV GLEW_GET_FUN(__glewInterpolatePathsNV)
+#define glIsPathNV GLEW_GET_FUN(__glewIsPathNV)
+#define glIsPointInFillPathNV GLEW_GET_FUN(__glewIsPointInFillPathNV)
+#define glIsPointInStrokePathNV GLEW_GET_FUN(__glewIsPointInStrokePathNV)
+#define glPathColorGenNV GLEW_GET_FUN(__glewPathColorGenNV)
+#define glPathCommandsNV GLEW_GET_FUN(__glewPathCommandsNV)
+#define glPathCoordsNV GLEW_GET_FUN(__glewPathCoordsNV)
+#define glPathCoverDepthFuncNV GLEW_GET_FUN(__glewPathCoverDepthFuncNV)
+#define glPathDashArrayNV GLEW_GET_FUN(__glewPathDashArrayNV)
+#define glPathFogGenNV GLEW_GET_FUN(__glewPathFogGenNV)
+#define glPathGlyphRangeNV GLEW_GET_FUN(__glewPathGlyphRangeNV)
+#define glPathGlyphsNV GLEW_GET_FUN(__glewPathGlyphsNV)
+#define glPathParameterfNV GLEW_GET_FUN(__glewPathParameterfNV)
+#define glPathParameterfvNV GLEW_GET_FUN(__glewPathParameterfvNV)
+#define glPathParameteriNV GLEW_GET_FUN(__glewPathParameteriNV)
+#define glPathParameterivNV GLEW_GET_FUN(__glewPathParameterivNV)
+#define glPathStencilDepthOffsetNV GLEW_GET_FUN(__glewPathStencilDepthOffsetNV)
+#define glPathStencilFuncNV GLEW_GET_FUN(__glewPathStencilFuncNV)
+#define glPathStringNV GLEW_GET_FUN(__glewPathStringNV)
+#define glPathSubCommandsNV GLEW_GET_FUN(__glewPathSubCommandsNV)
+#define glPathSubCoordsNV GLEW_GET_FUN(__glewPathSubCoordsNV)
+#define glPathTexGenNV GLEW_GET_FUN(__glewPathTexGenNV)
+#define glPointAlongPathNV GLEW_GET_FUN(__glewPointAlongPathNV)
+#define glStencilFillPathInstancedNV GLEW_GET_FUN(__glewStencilFillPathInstancedNV)
+#define glStencilFillPathNV GLEW_GET_FUN(__glewStencilFillPathNV)
+#define glStencilStrokePathInstancedNV GLEW_GET_FUN(__glewStencilStrokePathInstancedNV)
+#define glStencilStrokePathNV GLEW_GET_FUN(__glewStencilStrokePathNV)
+#define glTransformPathNV GLEW_GET_FUN(__glewTransformPathNV)
+#define glWeightPathsNV GLEW_GET_FUN(__glewWeightPathsNV)
+
+#define GLEW_NV_path_rendering GLEW_GET_VAR(__GLEW_NV_path_rendering)
+
+#endif /* !GL_NV_path_rendering */
+
+/* ------------------------- GL_NV_pixel_data_range ------------------------ */
+
+#if !defined(GL_NV_pixel_data_range)
+#define GL_NV_pixel_data_range 1
+
+#define GL_WRITE_PIXEL_DATA_RANGE_NV 0x8878
+#define GL_READ_PIXEL_DATA_RANGE_NV 0x8879
+#define GL_WRITE_PIXEL_DATA_RANGE_LENGTH_NV 0x887A
+#define GL_READ_PIXEL_DATA_RANGE_LENGTH_NV 0x887B
+#define GL_WRITE_PIXEL_DATA_RANGE_POINTER_NV 0x887C
+#define GL_READ_PIXEL_DATA_RANGE_POINTER_NV 0x887D
+
+typedef void (GLAPIENTRY * PFNGLFLUSHPIXELDATARANGENVPROC) (GLenum target);
+typedef void (GLAPIENTRY * PFNGLPIXELDATARANGENVPROC) (GLenum target, GLsizei length, void* pointer);
+
+#define glFlushPixelDataRangeNV GLEW_GET_FUN(__glewFlushPixelDataRangeNV)
+#define glPixelDataRangeNV GLEW_GET_FUN(__glewPixelDataRangeNV)
+
+#define GLEW_NV_pixel_data_range GLEW_GET_VAR(__GLEW_NV_pixel_data_range)
+
+#endif /* !GL_NV_pixel_data_range */
+
+/* --------------------------- GL_NV_point_sprite -------------------------- */
+
+#if !defined(GL_NV_point_sprite)
+#define GL_NV_point_sprite 1
+
+#define GL_POINT_SPRITE_NV 0x8861
+#define GL_COORD_REPLACE_NV 0x8862
+#define GL_POINT_SPRITE_R_MODE_NV 0x8863
+
+typedef void (GLAPIENTRY * PFNGLPOINTPARAMETERINVPROC) (GLenum pname, GLint param);
+typedef void (GLAPIENTRY * PFNGLPOINTPARAMETERIVNVPROC) (GLenum pname, const GLint* params);
+
+#define glPointParameteriNV GLEW_GET_FUN(__glewPointParameteriNV)
+#define glPointParameterivNV GLEW_GET_FUN(__glewPointParameterivNV)
+
+#define GLEW_NV_point_sprite GLEW_GET_VAR(__GLEW_NV_point_sprite)
+
+#endif /* !GL_NV_point_sprite */
+
+/* -------------------------- GL_NV_present_video -------------------------- */
+
+#if !defined(GL_NV_present_video)
+#define GL_NV_present_video 1
+
+#define GL_FRAME_NV 0x8E26
+#define GL_FIELDS_NV 0x8E27
+#define GL_CURRENT_TIME_NV 0x8E28
+#define GL_NUM_FILL_STREAMS_NV 0x8E29
+#define GL_PRESENT_TIME_NV 0x8E2A
+#define GL_PRESENT_DURATION_NV 0x8E2B
+
+typedef void (GLAPIENTRY * PFNGLGETVIDEOI64VNVPROC) (GLuint video_slot, GLenum pname, GLint64EXT* params);
+typedef void (GLAPIENTRY * PFNGLGETVIDEOIVNVPROC) (GLuint video_slot, GLenum pname, GLint* params);
+typedef void (GLAPIENTRY * PFNGLGETVIDEOUI64VNVPROC) (GLuint video_slot, GLenum pname, GLuint64EXT* params);
+typedef void (GLAPIENTRY * PFNGLGETVIDEOUIVNVPROC) (GLuint video_slot, GLenum pname, GLuint* params);
+typedef void (GLAPIENTRY * PFNGLPRESENTFRAMEDUALFILLNVPROC) (GLuint video_slot, GLuint64EXT minPresentTime, GLuint beginPresentTimeId, GLuint presentDurationId, GLenum type, GLenum target0, GLuint fill0, GLenum target1, GLuint fill1, GLenum target2, GLuint fill2, GLenum target3, GLuint fill3);
+typedef void (GLAPIENTRY * PFNGLPRESENTFRAMEKEYEDNVPROC) (GLuint video_slot, GLuint64EXT minPresentTime, GLuint beginPresentTimeId, GLuint presentDurationId, GLenum type, GLenum target0, GLuint fill0, GLuint key0, GLenum target1, GLuint fill1, GLuint key1);
+
+#define glGetVideoi64vNV GLEW_GET_FUN(__glewGetVideoi64vNV)
+#define glGetVideoivNV GLEW_GET_FUN(__glewGetVideoivNV)
+#define glGetVideoui64vNV GLEW_GET_FUN(__glewGetVideoui64vNV)
+#define glGetVideouivNV GLEW_GET_FUN(__glewGetVideouivNV)
+#define glPresentFrameDualFillNV GLEW_GET_FUN(__glewPresentFrameDualFillNV)
+#define glPresentFrameKeyedNV GLEW_GET_FUN(__glewPresentFrameKeyedNV)
+
+#define GLEW_NV_present_video GLEW_GET_VAR(__GLEW_NV_present_video)
+
+#endif /* !GL_NV_present_video */
+
+/* ------------------------ GL_NV_primitive_restart ------------------------ */
+
+#if !defined(GL_NV_primitive_restart)
+#define GL_NV_primitive_restart 1
+
+#define GL_PRIMITIVE_RESTART_NV 0x8558
+#define GL_PRIMITIVE_RESTART_INDEX_NV 0x8559
+
+typedef void (GLAPIENTRY * PFNGLPRIMITIVERESTARTINDEXNVPROC) (GLuint index);
+typedef void (GLAPIENTRY * PFNGLPRIMITIVERESTARTNVPROC) (void);
+
+#define glPrimitiveRestartIndexNV GLEW_GET_FUN(__glewPrimitiveRestartIndexNV)
+#define glPrimitiveRestartNV GLEW_GET_FUN(__glewPrimitiveRestartNV)
+
+#define GLEW_NV_primitive_restart GLEW_GET_VAR(__GLEW_NV_primitive_restart)
+
+#endif /* !GL_NV_primitive_restart */
+
+/* ------------------------ GL_NV_register_combiners ----------------------- */
+
+#if !defined(GL_NV_register_combiners)
+#define GL_NV_register_combiners 1
+
+#define GL_REGISTER_COMBINERS_NV 0x8522
+#define GL_VARIABLE_A_NV 0x8523
+#define GL_VARIABLE_B_NV 0x8524
+#define GL_VARIABLE_C_NV 0x8525
+#define GL_VARIABLE_D_NV 0x8526
+#define GL_VARIABLE_E_NV 0x8527
+#define GL_VARIABLE_F_NV 0x8528
+#define GL_VARIABLE_G_NV 0x8529
+#define GL_CONSTANT_COLOR0_NV 0x852A
+#define GL_CONSTANT_COLOR1_NV 0x852B
+#define GL_PRIMARY_COLOR_NV 0x852C
+#define GL_SECONDARY_COLOR_NV 0x852D
+#define GL_SPARE0_NV 0x852E
+#define GL_SPARE1_NV 0x852F
+#define GL_DISCARD_NV 0x8530
+#define GL_E_TIMES_F_NV 0x8531
+#define GL_SPARE0_PLUS_SECONDARY_COLOR_NV 0x8532
+#define GL_UNSIGNED_IDENTITY_NV 0x8536
+#define GL_UNSIGNED_INVERT_NV 0x8537
+#define GL_EXPAND_NORMAL_NV 0x8538
+#define GL_EXPAND_NEGATE_NV 0x8539
+#define GL_HALF_BIAS_NORMAL_NV 0x853A
+#define GL_HALF_BIAS_NEGATE_NV 0x853B
+#define GL_SIGNED_IDENTITY_NV 0x853C
+#define GL_SIGNED_NEGATE_NV 0x853D
+#define GL_SCALE_BY_TWO_NV 0x853E
+#define GL_SCALE_BY_FOUR_NV 0x853F
+#define GL_SCALE_BY_ONE_HALF_NV 0x8540
+#define GL_BIAS_BY_NEGATIVE_ONE_HALF_NV 0x8541
+#define GL_COMBINER_INPUT_NV 0x8542
+#define GL_COMBINER_MAPPING_NV 0x8543
+#define GL_COMBINER_COMPONENT_USAGE_NV 0x8544
+#define GL_COMBINER_AB_DOT_PRODUCT_NV 0x8545
+#define GL_COMBINER_CD_DOT_PRODUCT_NV 0x8546
+#define GL_COMBINER_MUX_SUM_NV 0x8547
+#define GL_COMBINER_SCALE_NV 0x8548
+#define GL_COMBINER_BIAS_NV 0x8549
+#define GL_COMBINER_AB_OUTPUT_NV 0x854A
+#define GL_COMBINER_CD_OUTPUT_NV 0x854B
+#define GL_COMBINER_SUM_OUTPUT_NV 0x854C
+#define GL_MAX_GENERAL_COMBINERS_NV 0x854D
+#define GL_NUM_GENERAL_COMBINERS_NV 0x854E
+#define GL_COLOR_SUM_CLAMP_NV 0x854F
+#define GL_COMBINER0_NV 0x8550
+#define GL_COMBINER1_NV 0x8551
+#define GL_COMBINER2_NV 0x8552
+#define GL_COMBINER3_NV 0x8553
+#define GL_COMBINER4_NV 0x8554
+#define GL_COMBINER5_NV 0x8555
+#define GL_COMBINER6_NV 0x8556
+#define GL_COMBINER7_NV 0x8557
+
+typedef void (GLAPIENTRY * PFNGLCOMBINERINPUTNVPROC) (GLenum stage, GLenum portion, GLenum variable, GLenum input, GLenum mapping, GLenum componentUsage);
+typedef void (GLAPIENTRY * PFNGLCOMBINEROUTPUTNVPROC) (GLenum stage, GLenum portion, GLenum abOutput, GLenum cdOutput, GLenum sumOutput, GLenum scale, GLenum bias, GLboolean abDotProduct, GLboolean cdDotProduct, GLboolean muxSum);
+typedef void (GLAPIENTRY * PFNGLCOMBINERPARAMETERFNVPROC) (GLenum pname, GLfloat param);
+typedef void (GLAPIENTRY * PFNGLCOMBINERPARAMETERFVNVPROC) (GLenum pname, const GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLCOMBINERPARAMETERINVPROC) (GLenum pname, GLint param);
+typedef void (GLAPIENTRY * PFNGLCOMBINERPARAMETERIVNVPROC) (GLenum pname, const GLint* params);
+typedef void (GLAPIENTRY * PFNGLFINALCOMBINERINPUTNVPROC) (GLenum variable, GLenum input, GLenum mapping, GLenum componentUsage);
+typedef void (GLAPIENTRY * PFNGLGETCOMBINERINPUTPARAMETERFVNVPROC) (GLenum stage, GLenum portion, GLenum variable, GLenum pname, GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLGETCOMBINERINPUTPARAMETERIVNVPROC) (GLenum stage, GLenum portion, GLenum variable, GLenum pname, GLint* params);
+typedef void (GLAPIENTRY * PFNGLGETCOMBINEROUTPUTPARAMETERFVNVPROC) (GLenum stage, GLenum portion, GLenum pname, GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLGETCOMBINEROUTPUTPARAMETERIVNVPROC) (GLenum stage, GLenum portion, GLenum pname, GLint* params);
+typedef void (GLAPIENTRY * PFNGLGETFINALCOMBINERINPUTPARAMETERFVNVPROC) (GLenum variable, GLenum pname, GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLGETFINALCOMBINERINPUTPARAMETERIVNVPROC) (GLenum variable, GLenum pname, GLint* params);
+
+#define glCombinerInputNV GLEW_GET_FUN(__glewCombinerInputNV)
+#define glCombinerOutputNV GLEW_GET_FUN(__glewCombinerOutputNV)
+#define glCombinerParameterfNV GLEW_GET_FUN(__glewCombinerParameterfNV)
+#define glCombinerParameterfvNV GLEW_GET_FUN(__glewCombinerParameterfvNV)
+#define glCombinerParameteriNV GLEW_GET_FUN(__glewCombinerParameteriNV)
+#define glCombinerParameterivNV GLEW_GET_FUN(__glewCombinerParameterivNV)
+#define glFinalCombinerInputNV GLEW_GET_FUN(__glewFinalCombinerInputNV)
+#define glGetCombinerInputParameterfvNV GLEW_GET_FUN(__glewGetCombinerInputParameterfvNV)
+#define glGetCombinerInputParameterivNV GLEW_GET_FUN(__glewGetCombinerInputParameterivNV)
+#define glGetCombinerOutputParameterfvNV GLEW_GET_FUN(__glewGetCombinerOutputParameterfvNV)
+#define glGetCombinerOutputParameterivNV GLEW_GET_FUN(__glewGetCombinerOutputParameterivNV)
+#define glGetFinalCombinerInputParameterfvNV GLEW_GET_FUN(__glewGetFinalCombinerInputParameterfvNV)
+#define glGetFinalCombinerInputParameterivNV GLEW_GET_FUN(__glewGetFinalCombinerInputParameterivNV)
+
+#define GLEW_NV_register_combiners GLEW_GET_VAR(__GLEW_NV_register_combiners)
+
+#endif /* !GL_NV_register_combiners */
+
+/* ----------------------- GL_NV_register_combiners2 ----------------------- */
+
+#if !defined(GL_NV_register_combiners2)
+#define GL_NV_register_combiners2 1
+
+#define GL_PER_STAGE_CONSTANTS_NV 0x8535
+
+typedef void (GLAPIENTRY * PFNGLCOMBINERSTAGEPARAMETERFVNVPROC) (GLenum stage, GLenum pname, const GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLGETCOMBINERSTAGEPARAMETERFVNVPROC) (GLenum stage, GLenum pname, GLfloat* params);
+
+#define glCombinerStageParameterfvNV GLEW_GET_FUN(__glewCombinerStageParameterfvNV)
+#define glGetCombinerStageParameterfvNV GLEW_GET_FUN(__glewGetCombinerStageParameterfvNV)
+
+#define GLEW_NV_register_combiners2 GLEW_GET_VAR(__GLEW_NV_register_combiners2)
+
+#endif /* !GL_NV_register_combiners2 */
+
+/* ---------------------- GL_NV_shader_atomic_counters --------------------- */
+
+#if !defined(GL_NV_shader_atomic_counters)
+#define GL_NV_shader_atomic_counters 1
+
+#define GLEW_NV_shader_atomic_counters GLEW_GET_VAR(__GLEW_NV_shader_atomic_counters)
+
+#endif /* !GL_NV_shader_atomic_counters */
+
+/* ----------------------- GL_NV_shader_atomic_float ----------------------- */
+
+#if !defined(GL_NV_shader_atomic_float)
+#define GL_NV_shader_atomic_float 1
+
+#define GLEW_NV_shader_atomic_float GLEW_GET_VAR(__GLEW_NV_shader_atomic_float)
+
+#endif /* !GL_NV_shader_atomic_float */
+
+/* ------------------------ GL_NV_shader_buffer_load ----------------------- */
+
+#if !defined(GL_NV_shader_buffer_load)
+#define GL_NV_shader_buffer_load 1
+
+#define GL_BUFFER_GPU_ADDRESS_NV 0x8F1D
+#define GL_GPU_ADDRESS_NV 0x8F34
+#define GL_MAX_SHADER_BUFFER_ADDRESS_NV 0x8F35
+
+typedef void (GLAPIENTRY * PFNGLGETBUFFERPARAMETERUI64VNVPROC) (GLenum target, GLenum pname, GLuint64EXT* params);
+typedef void (GLAPIENTRY * PFNGLGETINTEGERUI64VNVPROC) (GLenum value, GLuint64EXT* result);
+typedef void (GLAPIENTRY * PFNGLGETNAMEDBUFFERPARAMETERUI64VNVPROC) (GLuint buffer, GLenum pname, GLuint64EXT* params);
+typedef GLboolean (GLAPIENTRY * PFNGLISBUFFERRESIDENTNVPROC) (GLenum target);
+typedef GLboolean (GLAPIENTRY * PFNGLISNAMEDBUFFERRESIDENTNVPROC) (GLuint buffer);
+typedef void (GLAPIENTRY * PFNGLMAKEBUFFERNONRESIDENTNVPROC) (GLenum target);
+typedef void (GLAPIENTRY * PFNGLMAKEBUFFERRESIDENTNVPROC) (GLenum target, GLenum access);
+typedef void (GLAPIENTRY * PFNGLMAKENAMEDBUFFERNONRESIDENTNVPROC) (GLuint buffer);
+typedef void (GLAPIENTRY * PFNGLMAKENAMEDBUFFERRESIDENTNVPROC) (GLuint buffer, GLenum access);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMUI64NVPROC) (GLuint program, GLint location, GLuint64EXT value);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMUI64VNVPROC) (GLuint program, GLint location, GLsizei count, const GLuint64EXT* value);
+typedef void (GLAPIENTRY * PFNGLUNIFORMUI64NVPROC) (GLint location, GLuint64EXT value);
+typedef void (GLAPIENTRY * PFNGLUNIFORMUI64VNVPROC) (GLint location, GLsizei count, const GLuint64EXT* value);
+
+#define glGetBufferParameterui64vNV GLEW_GET_FUN(__glewGetBufferParameterui64vNV)
+#define glGetIntegerui64vNV GLEW_GET_FUN(__glewGetIntegerui64vNV)
+#define glGetNamedBufferParameterui64vNV GLEW_GET_FUN(__glewGetNamedBufferParameterui64vNV)
+#define glIsBufferResidentNV GLEW_GET_FUN(__glewIsBufferResidentNV)
+#define glIsNamedBufferResidentNV GLEW_GET_FUN(__glewIsNamedBufferResidentNV)
+#define glMakeBufferNonResidentNV GLEW_GET_FUN(__glewMakeBufferNonResidentNV)
+#define glMakeBufferResidentNV GLEW_GET_FUN(__glewMakeBufferResidentNV)
+#define glMakeNamedBufferNonResidentNV GLEW_GET_FUN(__glewMakeNamedBufferNonResidentNV)
+#define glMakeNamedBufferResidentNV GLEW_GET_FUN(__glewMakeNamedBufferResidentNV)
+#define glProgramUniformui64NV GLEW_GET_FUN(__glewProgramUniformui64NV)
+#define glProgramUniformui64vNV GLEW_GET_FUN(__glewProgramUniformui64vNV)
+#define glUniformui64NV GLEW_GET_FUN(__glewUniformui64NV)
+#define glUniformui64vNV GLEW_GET_FUN(__glewUniformui64vNV)
+
+#define GLEW_NV_shader_buffer_load GLEW_GET_VAR(__GLEW_NV_shader_buffer_load)
+
+#endif /* !GL_NV_shader_buffer_load */
+
+/* ------------------- GL_NV_shader_storage_buffer_object ------------------ */
+
+#if !defined(GL_NV_shader_storage_buffer_object)
+#define GL_NV_shader_storage_buffer_object 1
+
+#define GLEW_NV_shader_storage_buffer_object GLEW_GET_VAR(__GLEW_NV_shader_storage_buffer_object)
+
+#endif /* !GL_NV_shader_storage_buffer_object */
+
+/* ---------------------- GL_NV_tessellation_program5 ---------------------- */
+
+#if !defined(GL_NV_tessellation_program5)
+#define GL_NV_tessellation_program5 1
+
+#define GL_MAX_PROGRAM_PATCH_ATTRIBS_NV 0x86D8
+#define GL_TESS_CONTROL_PROGRAM_NV 0x891E
+#define GL_TESS_EVALUATION_PROGRAM_NV 0x891F
+#define GL_TESS_CONTROL_PROGRAM_PARAMETER_BUFFER_NV 0x8C74
+#define GL_TESS_EVALUATION_PROGRAM_PARAMETER_BUFFER_NV 0x8C75
+
+#define GLEW_NV_tessellation_program5 GLEW_GET_VAR(__GLEW_NV_tessellation_program5)
+
+#endif /* !GL_NV_tessellation_program5 */
+
+/* -------------------------- GL_NV_texgen_emboss -------------------------- */
+
+#if !defined(GL_NV_texgen_emboss)
+#define GL_NV_texgen_emboss 1
+
+#define GL_EMBOSS_LIGHT_NV 0x855D
+#define GL_EMBOSS_CONSTANT_NV 0x855E
+#define GL_EMBOSS_MAP_NV 0x855F
+
+#define GLEW_NV_texgen_emboss GLEW_GET_VAR(__GLEW_NV_texgen_emboss)
+
+#endif /* !GL_NV_texgen_emboss */
+
+/* ------------------------ GL_NV_texgen_reflection ------------------------ */
+
+#if !defined(GL_NV_texgen_reflection)
+#define GL_NV_texgen_reflection 1
+
+#define GL_NORMAL_MAP_NV 0x8511
+#define GL_REFLECTION_MAP_NV 0x8512
+
+#define GLEW_NV_texgen_reflection GLEW_GET_VAR(__GLEW_NV_texgen_reflection)
+
+#endif /* !GL_NV_texgen_reflection */
+
+/* ------------------------- GL_NV_texture_barrier ------------------------- */
+
+#if !defined(GL_NV_texture_barrier)
+#define GL_NV_texture_barrier 1
+
+typedef void (GLAPIENTRY * PFNGLTEXTUREBARRIERNVPROC) (void);
+
+#define glTextureBarrierNV GLEW_GET_FUN(__glewTextureBarrierNV)
+
+#define GLEW_NV_texture_barrier GLEW_GET_VAR(__GLEW_NV_texture_barrier)
+
+#endif /* !GL_NV_texture_barrier */
+
+/* --------------------- GL_NV_texture_compression_vtc --------------------- */
+
+#if !defined(GL_NV_texture_compression_vtc)
+#define GL_NV_texture_compression_vtc 1
+
+#define GLEW_NV_texture_compression_vtc GLEW_GET_VAR(__GLEW_NV_texture_compression_vtc)
+
+#endif /* !GL_NV_texture_compression_vtc */
+
+/* ----------------------- GL_NV_texture_env_combine4 ---------------------- */
+
+#if !defined(GL_NV_texture_env_combine4)
+#define GL_NV_texture_env_combine4 1
+
+#define GL_COMBINE4_NV 0x8503
+#define GL_SOURCE3_RGB_NV 0x8583
+#define GL_SOURCE3_ALPHA_NV 0x858B
+#define GL_OPERAND3_RGB_NV 0x8593
+#define GL_OPERAND3_ALPHA_NV 0x859B
+
+#define GLEW_NV_texture_env_combine4 GLEW_GET_VAR(__GLEW_NV_texture_env_combine4)
+
+#endif /* !GL_NV_texture_env_combine4 */
+
+/* ---------------------- GL_NV_texture_expand_normal ---------------------- */
+
+#if !defined(GL_NV_texture_expand_normal)
+#define GL_NV_texture_expand_normal 1
+
+#define GL_TEXTURE_UNSIGNED_REMAP_MODE_NV 0x888F
+
+#define GLEW_NV_texture_expand_normal GLEW_GET_VAR(__GLEW_NV_texture_expand_normal)
+
+#endif /* !GL_NV_texture_expand_normal */
+
+/* ----------------------- GL_NV_texture_multisample ----------------------- */
+
+#if !defined(GL_NV_texture_multisample)
+#define GL_NV_texture_multisample 1
+
+#define GL_TEXTURE_COVERAGE_SAMPLES_NV 0x9045
+#define GL_TEXTURE_COLOR_SAMPLES_NV 0x9046
+
+typedef void (GLAPIENTRY * PFNGLTEXIMAGE2DMULTISAMPLECOVERAGENVPROC) (GLenum target, GLsizei coverageSamples, GLsizei colorSamples, GLint internalFormat, GLsizei width, GLsizei height, GLboolean fixedSampleLocations);
+typedef void (GLAPIENTRY * PFNGLTEXIMAGE3DMULTISAMPLECOVERAGENVPROC) (GLenum target, GLsizei coverageSamples, GLsizei colorSamples, GLint internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedSampleLocations);
+typedef void (GLAPIENTRY * PFNGLTEXTUREIMAGE2DMULTISAMPLECOVERAGENVPROC) (GLuint texture, GLenum target, GLsizei coverageSamples, GLsizei colorSamples, GLint internalFormat, GLsizei width, GLsizei height, GLboolean fixedSampleLocations);
+typedef void (GLAPIENTRY * PFNGLTEXTUREIMAGE2DMULTISAMPLENVPROC) (GLuint texture, GLenum target, GLsizei samples, GLint internalFormat, GLsizei width, GLsizei height, GLboolean fixedSampleLocations);
+typedef void (GLAPIENTRY * PFNGLTEXTUREIMAGE3DMULTISAMPLECOVERAGENVPROC) (GLuint texture, GLenum target, GLsizei coverageSamples, GLsizei colorSamples, GLint internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedSampleLocations);
+typedef void (GLAPIENTRY * PFNGLTEXTUREIMAGE3DMULTISAMPLENVPROC) (GLuint texture, GLenum target, GLsizei samples, GLint internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedSampleLocations);
+
+#define glTexImage2DMultisampleCoverageNV GLEW_GET_FUN(__glewTexImage2DMultisampleCoverageNV)
+#define glTexImage3DMultisampleCoverageNV GLEW_GET_FUN(__glewTexImage3DMultisampleCoverageNV)
+#define glTextureImage2DMultisampleCoverageNV GLEW_GET_FUN(__glewTextureImage2DMultisampleCoverageNV)
+#define glTextureImage2DMultisampleNV GLEW_GET_FUN(__glewTextureImage2DMultisampleNV)
+#define glTextureImage3DMultisampleCoverageNV GLEW_GET_FUN(__glewTextureImage3DMultisampleCoverageNV)
+#define glTextureImage3DMultisampleNV GLEW_GET_FUN(__glewTextureImage3DMultisampleNV)
+
+#define GLEW_NV_texture_multisample GLEW_GET_VAR(__GLEW_NV_texture_multisample)
+
+#endif /* !GL_NV_texture_multisample */
+
+/* ------------------------ GL_NV_texture_rectangle ------------------------ */
+
+#if !defined(GL_NV_texture_rectangle)
+#define GL_NV_texture_rectangle 1
+
+#define GL_TEXTURE_RECTANGLE_NV 0x84F5
+#define GL_TEXTURE_BINDING_RECTANGLE_NV 0x84F6
+#define GL_PROXY_TEXTURE_RECTANGLE_NV 0x84F7
+#define GL_MAX_RECTANGLE_TEXTURE_SIZE_NV 0x84F8
+
+#define GLEW_NV_texture_rectangle GLEW_GET_VAR(__GLEW_NV_texture_rectangle)
+
+#endif /* !GL_NV_texture_rectangle */
+
+/* -------------------------- GL_NV_texture_shader ------------------------- */
+
+#if !defined(GL_NV_texture_shader)
+#define GL_NV_texture_shader 1
+
+#define GL_OFFSET_TEXTURE_RECTANGLE_NV 0x864C
+#define GL_OFFSET_TEXTURE_RECTANGLE_SCALE_NV 0x864D
+#define GL_DOT_PRODUCT_TEXTURE_RECTANGLE_NV 0x864E
+#define GL_RGBA_UNSIGNED_DOT_PRODUCT_MAPPING_NV 0x86D9
+#define GL_UNSIGNED_INT_S8_S8_8_8_NV 0x86DA
+#define GL_UNSIGNED_INT_8_8_S8_S8_REV_NV 0x86DB
+#define GL_DSDT_MAG_INTENSITY_NV 0x86DC
+#define GL_SHADER_CONSISTENT_NV 0x86DD
+#define GL_TEXTURE_SHADER_NV 0x86DE
+#define GL_SHADER_OPERATION_NV 0x86DF
+#define GL_CULL_MODES_NV 0x86E0
+#define GL_OFFSET_TEXTURE_2D_MATRIX_NV 0x86E1
+#define GL_OFFSET_TEXTURE_MATRIX_NV 0x86E1
+#define GL_OFFSET_TEXTURE_2D_SCALE_NV 0x86E2
+#define GL_OFFSET_TEXTURE_SCALE_NV 0x86E2
+#define GL_OFFSET_TEXTURE_BIAS_NV 0x86E3
+#define GL_OFFSET_TEXTURE_2D_BIAS_NV 0x86E3
+#define GL_PREVIOUS_TEXTURE_INPUT_NV 0x86E4
+#define GL_CONST_EYE_NV 0x86E5
+#define GL_PASS_THROUGH_NV 0x86E6
+#define GL_CULL_FRAGMENT_NV 0x86E7
+#define GL_OFFSET_TEXTURE_2D_NV 0x86E8
+#define GL_DEPENDENT_AR_TEXTURE_2D_NV 0x86E9
+#define GL_DEPENDENT_GB_TEXTURE_2D_NV 0x86EA
+#define GL_DOT_PRODUCT_NV 0x86EC
+#define GL_DOT_PRODUCT_DEPTH_REPLACE_NV 0x86ED
+#define GL_DOT_PRODUCT_TEXTURE_2D_NV 0x86EE
+#define GL_DOT_PRODUCT_TEXTURE_CUBE_MAP_NV 0x86F0
+#define GL_DOT_PRODUCT_DIFFUSE_CUBE_MAP_NV 0x86F1
+#define GL_DOT_PRODUCT_REFLECT_CUBE_MAP_NV 0x86F2
+#define GL_DOT_PRODUCT_CONST_EYE_REFLECT_CUBE_MAP_NV 0x86F3
+#define GL_HILO_NV 0x86F4
+#define GL_DSDT_NV 0x86F5
+#define GL_DSDT_MAG_NV 0x86F6
+#define GL_DSDT_MAG_VIB_NV 0x86F7
+#define GL_HILO16_NV 0x86F8
+#define GL_SIGNED_HILO_NV 0x86F9
+#define GL_SIGNED_HILO16_NV 0x86FA
+#define GL_SIGNED_RGBA_NV 0x86FB
+#define GL_SIGNED_RGBA8_NV 0x86FC
+#define GL_SIGNED_RGB_NV 0x86FE
+#define GL_SIGNED_RGB8_NV 0x86FF
+#define GL_SIGNED_LUMINANCE_NV 0x8701
+#define GL_SIGNED_LUMINANCE8_NV 0x8702
+#define GL_SIGNED_LUMINANCE_ALPHA_NV 0x8703
+#define GL_SIGNED_LUMINANCE8_ALPHA8_NV 0x8704
+#define GL_SIGNED_ALPHA_NV 0x8705
+#define GL_SIGNED_ALPHA8_NV 0x8706
+#define GL_SIGNED_INTENSITY_NV 0x8707
+#define GL_SIGNED_INTENSITY8_NV 0x8708
+#define GL_DSDT8_NV 0x8709
+#define GL_DSDT8_MAG8_NV 0x870A
+#define GL_DSDT8_MAG8_INTENSITY8_NV 0x870B
+#define GL_SIGNED_RGB_UNSIGNED_ALPHA_NV 0x870C
+#define GL_SIGNED_RGB8_UNSIGNED_ALPHA8_NV 0x870D
+#define GL_HI_SCALE_NV 0x870E
+#define GL_LO_SCALE_NV 0x870F
+#define GL_DS_SCALE_NV 0x8710
+#define GL_DT_SCALE_NV 0x8711
+#define GL_MAGNITUDE_SCALE_NV 0x8712
+#define GL_VIBRANCE_SCALE_NV 0x8713
+#define GL_HI_BIAS_NV 0x8714
+#define GL_LO_BIAS_NV 0x8715
+#define GL_DS_BIAS_NV 0x8716
+#define GL_DT_BIAS_NV 0x8717
+#define GL_MAGNITUDE_BIAS_NV 0x8718
+#define GL_VIBRANCE_BIAS_NV 0x8719
+#define GL_TEXTURE_BORDER_VALUES_NV 0x871A
+#define GL_TEXTURE_HI_SIZE_NV 0x871B
+#define GL_TEXTURE_LO_SIZE_NV 0x871C
+#define GL_TEXTURE_DS_SIZE_NV 0x871D
+#define GL_TEXTURE_DT_SIZE_NV 0x871E
+#define GL_TEXTURE_MAG_SIZE_NV 0x871F
+
+#define GLEW_NV_texture_shader GLEW_GET_VAR(__GLEW_NV_texture_shader)
+
+#endif /* !GL_NV_texture_shader */
+
+/* ------------------------- GL_NV_texture_shader2 ------------------------- */
+
+#if !defined(GL_NV_texture_shader2)
+#define GL_NV_texture_shader2 1
+
+#define GL_UNSIGNED_INT_S8_S8_8_8_NV 0x86DA
+#define GL_UNSIGNED_INT_8_8_S8_S8_REV_NV 0x86DB
+#define GL_DSDT_MAG_INTENSITY_NV 0x86DC
+#define GL_DOT_PRODUCT_TEXTURE_3D_NV 0x86EF
+#define GL_HILO_NV 0x86F4
+#define GL_DSDT_NV 0x86F5
+#define GL_DSDT_MAG_NV 0x86F6
+#define GL_DSDT_MAG_VIB_NV 0x86F7
+#define GL_HILO16_NV 0x86F8
+#define GL_SIGNED_HILO_NV 0x86F9
+#define GL_SIGNED_HILO16_NV 0x86FA
+#define GL_SIGNED_RGBA_NV 0x86FB
+#define GL_SIGNED_RGBA8_NV 0x86FC
+#define GL_SIGNED_RGB_NV 0x86FE
+#define GL_SIGNED_RGB8_NV 0x86FF
+#define GL_SIGNED_LUMINANCE_NV 0x8701
+#define GL_SIGNED_LUMINANCE8_NV 0x8702
+#define GL_SIGNED_LUMINANCE_ALPHA_NV 0x8703
+#define GL_SIGNED_LUMINANCE8_ALPHA8_NV 0x8704
+#define GL_SIGNED_ALPHA_NV 0x8705
+#define GL_SIGNED_ALPHA8_NV 0x8706
+#define GL_SIGNED_INTENSITY_NV 0x8707
+#define GL_SIGNED_INTENSITY8_NV 0x8708
+#define GL_DSDT8_NV 0x8709
+#define GL_DSDT8_MAG8_NV 0x870A
+#define GL_DSDT8_MAG8_INTENSITY8_NV 0x870B
+#define GL_SIGNED_RGB_UNSIGNED_ALPHA_NV 0x870C
+#define GL_SIGNED_RGB8_UNSIGNED_ALPHA8_NV 0x870D
+
+#define GLEW_NV_texture_shader2 GLEW_GET_VAR(__GLEW_NV_texture_shader2)
+
+#endif /* !GL_NV_texture_shader2 */
+
+/* ------------------------- GL_NV_texture_shader3 ------------------------- */
+
+#if !defined(GL_NV_texture_shader3)
+#define GL_NV_texture_shader3 1
+
+#define GL_OFFSET_PROJECTIVE_TEXTURE_2D_NV 0x8850
+#define GL_OFFSET_PROJECTIVE_TEXTURE_2D_SCALE_NV 0x8851
+#define GL_OFFSET_PROJECTIVE_TEXTURE_RECTANGLE_NV 0x8852
+#define GL_OFFSET_PROJECTIVE_TEXTURE_RECTANGLE_SCALE_NV 0x8853
+#define GL_OFFSET_HILO_TEXTURE_2D_NV 0x8854
+#define GL_OFFSET_HILO_TEXTURE_RECTANGLE_NV 0x8855
+#define GL_OFFSET_HILO_PROJECTIVE_TEXTURE_2D_NV 0x8856
+#define GL_OFFSET_HILO_PROJECTIVE_TEXTURE_RECTANGLE_NV 0x8857
+#define GL_DEPENDENT_HILO_TEXTURE_2D_NV 0x8858
+#define GL_DEPENDENT_RGB_TEXTURE_3D_NV 0x8859
+#define GL_DEPENDENT_RGB_TEXTURE_CUBE_MAP_NV 0x885A
+#define GL_DOT_PRODUCT_PASS_THROUGH_NV 0x885B
+#define GL_DOT_PRODUCT_TEXTURE_1D_NV 0x885C
+#define GL_DOT_PRODUCT_AFFINE_DEPTH_REPLACE_NV 0x885D
+#define GL_HILO8_NV 0x885E
+#define GL_SIGNED_HILO8_NV 0x885F
+#define GL_FORCE_BLUE_TO_ONE_NV 0x8860
+
+#define GLEW_NV_texture_shader3 GLEW_GET_VAR(__GLEW_NV_texture_shader3)
+
+#endif /* !GL_NV_texture_shader3 */
+
+/* ------------------------ GL_NV_transform_feedback ----------------------- */
+
+#if !defined(GL_NV_transform_feedback)
+#define GL_NV_transform_feedback 1
+
+#define GL_BACK_PRIMARY_COLOR_NV 0x8C77
+#define GL_BACK_SECONDARY_COLOR_NV 0x8C78
+#define GL_TEXTURE_COORD_NV 0x8C79
+#define GL_CLIP_DISTANCE_NV 0x8C7A
+#define GL_VERTEX_ID_NV 0x8C7B
+#define GL_PRIMITIVE_ID_NV 0x8C7C
+#define GL_GENERIC_ATTRIB_NV 0x8C7D
+#define GL_TRANSFORM_FEEDBACK_ATTRIBS_NV 0x8C7E
+#define GL_TRANSFORM_FEEDBACK_BUFFER_MODE_NV 0x8C7F
+#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS_NV 0x8C80
+#define GL_ACTIVE_VARYINGS_NV 0x8C81
+#define GL_ACTIVE_VARYING_MAX_LENGTH_NV 0x8C82
+#define GL_TRANSFORM_FEEDBACK_VARYINGS_NV 0x8C83
+#define GL_TRANSFORM_FEEDBACK_BUFFER_START_NV 0x8C84
+#define GL_TRANSFORM_FEEDBACK_BUFFER_SIZE_NV 0x8C85
+#define GL_TRANSFORM_FEEDBACK_RECORD_NV 0x8C86
+#define GL_PRIMITIVES_GENERATED_NV 0x8C87
+#define GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN_NV 0x8C88
+#define GL_RASTERIZER_DISCARD_NV 0x8C89
+#define GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS_NV 0x8C8A
+#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS_NV 0x8C8B
+#define GL_INTERLEAVED_ATTRIBS_NV 0x8C8C
+#define GL_SEPARATE_ATTRIBS_NV 0x8C8D
+#define GL_TRANSFORM_FEEDBACK_BUFFER_NV 0x8C8E
+#define GL_TRANSFORM_FEEDBACK_BUFFER_BINDING_NV 0x8C8F
+
+typedef void (GLAPIENTRY * PFNGLACTIVEVARYINGNVPROC) (GLuint program, const GLchar *name);
+typedef void (GLAPIENTRY * PFNGLBEGINTRANSFORMFEEDBACKNVPROC) (GLenum primitiveMode);
+typedef void (GLAPIENTRY * PFNGLBINDBUFFERBASENVPROC) (GLenum target, GLuint index, GLuint buffer);
+typedef void (GLAPIENTRY * PFNGLBINDBUFFEROFFSETNVPROC) (GLenum target, GLuint index, GLuint buffer, GLintptr offset);
+typedef void (GLAPIENTRY * PFNGLBINDBUFFERRANGENVPROC) (GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size);
+typedef void (GLAPIENTRY * PFNGLENDTRANSFORMFEEDBACKNVPROC) (void);
+typedef void (GLAPIENTRY * PFNGLGETACTIVEVARYINGNVPROC) (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLsizei *size, GLenum *type, GLchar *name);
+typedef void (GLAPIENTRY * PFNGLGETTRANSFORMFEEDBACKVARYINGNVPROC) (GLuint program, GLuint index, GLint *location);
+typedef GLint (GLAPIENTRY * PFNGLGETVARYINGLOCATIONNVPROC) (GLuint program, const GLchar *name);
+typedef void (GLAPIENTRY * PFNGLTRANSFORMFEEDBACKATTRIBSNVPROC) (GLuint count, const GLint *attribs, GLenum bufferMode);
+typedef void (GLAPIENTRY * PFNGLTRANSFORMFEEDBACKVARYINGSNVPROC) (GLuint program, GLsizei count, const GLint *locations, GLenum bufferMode);
+
+#define glActiveVaryingNV GLEW_GET_FUN(__glewActiveVaryingNV)
+#define glBeginTransformFeedbackNV GLEW_GET_FUN(__glewBeginTransformFeedbackNV)
+#define glBindBufferBaseNV GLEW_GET_FUN(__glewBindBufferBaseNV)
+#define glBindBufferOffsetNV GLEW_GET_FUN(__glewBindBufferOffsetNV)
+#define glBindBufferRangeNV GLEW_GET_FUN(__glewBindBufferRangeNV)
+#define glEndTransformFeedbackNV GLEW_GET_FUN(__glewEndTransformFeedbackNV)
+#define glGetActiveVaryingNV GLEW_GET_FUN(__glewGetActiveVaryingNV)
+#define glGetTransformFeedbackVaryingNV GLEW_GET_FUN(__glewGetTransformFeedbackVaryingNV)
+#define glGetVaryingLocationNV GLEW_GET_FUN(__glewGetVaryingLocationNV)
+#define glTransformFeedbackAttribsNV GLEW_GET_FUN(__glewTransformFeedbackAttribsNV)
+#define glTransformFeedbackVaryingsNV GLEW_GET_FUN(__glewTransformFeedbackVaryingsNV)
+
+#define GLEW_NV_transform_feedback GLEW_GET_VAR(__GLEW_NV_transform_feedback)
+
+#endif /* !GL_NV_transform_feedback */
+
+/* ----------------------- GL_NV_transform_feedback2 ----------------------- */
+
+#if !defined(GL_NV_transform_feedback2)
+#define GL_NV_transform_feedback2 1
+
+#define GL_TRANSFORM_FEEDBACK_NV 0x8E22
+#define GL_TRANSFORM_FEEDBACK_BUFFER_PAUSED_NV 0x8E23
+#define GL_TRANSFORM_FEEDBACK_BUFFER_ACTIVE_NV 0x8E24
+#define GL_TRANSFORM_FEEDBACK_BINDING_NV 0x8E25
+
+typedef void (GLAPIENTRY * PFNGLBINDTRANSFORMFEEDBACKNVPROC) (GLenum target, GLuint id);
+typedef void (GLAPIENTRY * PFNGLDELETETRANSFORMFEEDBACKSNVPROC) (GLsizei n, const GLuint* ids);
+typedef void (GLAPIENTRY * PFNGLDRAWTRANSFORMFEEDBACKNVPROC) (GLenum mode, GLuint id);
+typedef void (GLAPIENTRY * PFNGLGENTRANSFORMFEEDBACKSNVPROC) (GLsizei n, GLuint* ids);
+typedef GLboolean (GLAPIENTRY * PFNGLISTRANSFORMFEEDBACKNVPROC) (GLuint id);
+typedef void (GLAPIENTRY * PFNGLPAUSETRANSFORMFEEDBACKNVPROC) (void);
+typedef void (GLAPIENTRY * PFNGLRESUMETRANSFORMFEEDBACKNVPROC) (void);
+
+#define glBindTransformFeedbackNV GLEW_GET_FUN(__glewBindTransformFeedbackNV)
+#define glDeleteTransformFeedbacksNV GLEW_GET_FUN(__glewDeleteTransformFeedbacksNV)
+#define glDrawTransformFeedbackNV GLEW_GET_FUN(__glewDrawTransformFeedbackNV)
+#define glGenTransformFeedbacksNV GLEW_GET_FUN(__glewGenTransformFeedbacksNV)
+#define glIsTransformFeedbackNV GLEW_GET_FUN(__glewIsTransformFeedbackNV)
+#define glPauseTransformFeedbackNV GLEW_GET_FUN(__glewPauseTransformFeedbackNV)
+#define glResumeTransformFeedbackNV GLEW_GET_FUN(__glewResumeTransformFeedbackNV)
+
+#define GLEW_NV_transform_feedback2 GLEW_GET_VAR(__GLEW_NV_transform_feedback2)
+
+#endif /* !GL_NV_transform_feedback2 */
+
+/* -------------------------- GL_NV_vdpau_interop -------------------------- */
+
+#if !defined(GL_NV_vdpau_interop)
+#define GL_NV_vdpau_interop 1
+
+#define GL_SURFACE_STATE_NV 0x86EB
+#define GL_SURFACE_REGISTERED_NV 0x86FD
+#define GL_SURFACE_MAPPED_NV 0x8700
+#define GL_WRITE_DISCARD_NV 0x88BE
+
+typedef GLintptr GLvdpauSurfaceNV;
+
+typedef void (GLAPIENTRY * PFNGLVDPAUFININVPROC) (void);
+typedef void (GLAPIENTRY * PFNGLVDPAUGETSURFACEIVNVPROC) (GLvdpauSurfaceNV surface, GLenum pname, GLsizei bufSize, GLsizei* length, GLint *values);
+typedef void (GLAPIENTRY * PFNGLVDPAUINITNVPROC) (const void* vdpDevice, const GLvoid*getProcAddress);
+typedef void (GLAPIENTRY * PFNGLVDPAUISSURFACENVPROC) (GLvdpauSurfaceNV surface);
+typedef void (GLAPIENTRY * PFNGLVDPAUMAPSURFACESNVPROC) (GLsizei numSurfaces, const GLvdpauSurfaceNV* surfaces);
+typedef GLvdpauSurfaceNV (GLAPIENTRY * PFNGLVDPAUREGISTEROUTPUTSURFACENVPROC) (const void* vdpSurface, GLenum target, GLsizei numTextureNames, const GLuint *textureNames);
+typedef GLvdpauSurfaceNV (GLAPIENTRY * PFNGLVDPAUREGISTERVIDEOSURFACENVPROC) (const void* vdpSurface, GLenum target, GLsizei numTextureNames, const GLuint *textureNames);
+typedef void (GLAPIENTRY * PFNGLVDPAUSURFACEACCESSNVPROC) (GLvdpauSurfaceNV surface, GLenum access);
+typedef void (GLAPIENTRY * PFNGLVDPAUUNMAPSURFACESNVPROC) (GLsizei numSurface, const GLvdpauSurfaceNV* surfaces);
+typedef void (GLAPIENTRY * PFNGLVDPAUUNREGISTERSURFACENVPROC) (GLvdpauSurfaceNV surface);
+
+#define glVDPAUFiniNV GLEW_GET_FUN(__glewVDPAUFiniNV)
+#define glVDPAUGetSurfaceivNV GLEW_GET_FUN(__glewVDPAUGetSurfaceivNV)
+#define glVDPAUInitNV GLEW_GET_FUN(__glewVDPAUInitNV)
+#define glVDPAUIsSurfaceNV GLEW_GET_FUN(__glewVDPAUIsSurfaceNV)
+#define glVDPAUMapSurfacesNV GLEW_GET_FUN(__glewVDPAUMapSurfacesNV)
+#define glVDPAURegisterOutputSurfaceNV GLEW_GET_FUN(__glewVDPAURegisterOutputSurfaceNV)
+#define glVDPAURegisterVideoSurfaceNV GLEW_GET_FUN(__glewVDPAURegisterVideoSurfaceNV)
+#define glVDPAUSurfaceAccessNV GLEW_GET_FUN(__glewVDPAUSurfaceAccessNV)
+#define glVDPAUUnmapSurfacesNV GLEW_GET_FUN(__glewVDPAUUnmapSurfacesNV)
+#define glVDPAUUnregisterSurfaceNV GLEW_GET_FUN(__glewVDPAUUnregisterSurfaceNV)
+
+#define GLEW_NV_vdpau_interop GLEW_GET_VAR(__GLEW_NV_vdpau_interop)
+
+#endif /* !GL_NV_vdpau_interop */
+
+/* ------------------------ GL_NV_vertex_array_range ----------------------- */
+
+#if !defined(GL_NV_vertex_array_range)
+#define GL_NV_vertex_array_range 1
+
+#define GL_VERTEX_ARRAY_RANGE_NV 0x851D
+#define GL_VERTEX_ARRAY_RANGE_LENGTH_NV 0x851E
+#define GL_VERTEX_ARRAY_RANGE_VALID_NV 0x851F
+#define GL_MAX_VERTEX_ARRAY_RANGE_ELEMENT_NV 0x8520
+#define GL_VERTEX_ARRAY_RANGE_POINTER_NV 0x8521
+
+typedef void (GLAPIENTRY * PFNGLFLUSHVERTEXARRAYRANGENVPROC) (void);
+typedef void (GLAPIENTRY * PFNGLVERTEXARRAYRANGENVPROC) (GLsizei length, void* pointer);
+
+#define glFlushVertexArrayRangeNV GLEW_GET_FUN(__glewFlushVertexArrayRangeNV)
+#define glVertexArrayRangeNV GLEW_GET_FUN(__glewVertexArrayRangeNV)
+
+#define GLEW_NV_vertex_array_range GLEW_GET_VAR(__GLEW_NV_vertex_array_range)
+
+#endif /* !GL_NV_vertex_array_range */
+
+/* ----------------------- GL_NV_vertex_array_range2 ----------------------- */
+
+#if !defined(GL_NV_vertex_array_range2)
+#define GL_NV_vertex_array_range2 1
+
+#define GL_VERTEX_ARRAY_RANGE_WITHOUT_FLUSH_NV 0x8533
+
+#define GLEW_NV_vertex_array_range2 GLEW_GET_VAR(__GLEW_NV_vertex_array_range2)
+
+#endif /* !GL_NV_vertex_array_range2 */
+
+/* ------------------- GL_NV_vertex_attrib_integer_64bit ------------------- */
+
+#if !defined(GL_NV_vertex_attrib_integer_64bit)
+#define GL_NV_vertex_attrib_integer_64bit 1
+
+#define GL_INT64_NV 0x140E
+#define GL_UNSIGNED_INT64_NV 0x140F
+
+typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBLI64VNVPROC) (GLuint index, GLenum pname, GLint64EXT* params);
+typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBLUI64VNVPROC) (GLuint index, GLenum pname, GLuint64EXT* params);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL1I64NVPROC) (GLuint index, GLint64EXT x);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL1I64VNVPROC) (GLuint index, const GLint64EXT* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL1UI64NVPROC) (GLuint index, GLuint64EXT x);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL1UI64VNVPROC) (GLuint index, const GLuint64EXT* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL2I64NVPROC) (GLuint index, GLint64EXT x, GLint64EXT y);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL2I64VNVPROC) (GLuint index, const GLint64EXT* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL2UI64NVPROC) (GLuint index, GLuint64EXT x, GLuint64EXT y);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL2UI64VNVPROC) (GLuint index, const GLuint64EXT* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL3I64NVPROC) (GLuint index, GLint64EXT x, GLint64EXT y, GLint64EXT z);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL3I64VNVPROC) (GLuint index, const GLint64EXT* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL3UI64NVPROC) (GLuint index, GLuint64EXT x, GLuint64EXT y, GLuint64EXT z);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL3UI64VNVPROC) (GLuint index, const GLuint64EXT* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL4I64NVPROC) (GLuint index, GLint64EXT x, GLint64EXT y, GLint64EXT z, GLint64EXT w);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL4I64VNVPROC) (GLuint index, const GLint64EXT* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL4UI64NVPROC) (GLuint index, GLuint64EXT x, GLuint64EXT y, GLuint64EXT z, GLuint64EXT w);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL4UI64VNVPROC) (GLuint index, const GLuint64EXT* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBLFORMATNVPROC) (GLuint index, GLint size, GLenum type, GLsizei stride);
+
+#define glGetVertexAttribLi64vNV GLEW_GET_FUN(__glewGetVertexAttribLi64vNV)
+#define glGetVertexAttribLui64vNV GLEW_GET_FUN(__glewGetVertexAttribLui64vNV)
+#define glVertexAttribL1i64NV GLEW_GET_FUN(__glewVertexAttribL1i64NV)
+#define glVertexAttribL1i64vNV GLEW_GET_FUN(__glewVertexAttribL1i64vNV)
+#define glVertexAttribL1ui64NV GLEW_GET_FUN(__glewVertexAttribL1ui64NV)
+#define glVertexAttribL1ui64vNV GLEW_GET_FUN(__glewVertexAttribL1ui64vNV)
+#define glVertexAttribL2i64NV GLEW_GET_FUN(__glewVertexAttribL2i64NV)
+#define glVertexAttribL2i64vNV GLEW_GET_FUN(__glewVertexAttribL2i64vNV)
+#define glVertexAttribL2ui64NV GLEW_GET_FUN(__glewVertexAttribL2ui64NV)
+#define glVertexAttribL2ui64vNV GLEW_GET_FUN(__glewVertexAttribL2ui64vNV)
+#define glVertexAttribL3i64NV GLEW_GET_FUN(__glewVertexAttribL3i64NV)
+#define glVertexAttribL3i64vNV GLEW_GET_FUN(__glewVertexAttribL3i64vNV)
+#define glVertexAttribL3ui64NV GLEW_GET_FUN(__glewVertexAttribL3ui64NV)
+#define glVertexAttribL3ui64vNV GLEW_GET_FUN(__glewVertexAttribL3ui64vNV)
+#define glVertexAttribL4i64NV GLEW_GET_FUN(__glewVertexAttribL4i64NV)
+#define glVertexAttribL4i64vNV GLEW_GET_FUN(__glewVertexAttribL4i64vNV)
+#define glVertexAttribL4ui64NV GLEW_GET_FUN(__glewVertexAttribL4ui64NV)
+#define glVertexAttribL4ui64vNV GLEW_GET_FUN(__glewVertexAttribL4ui64vNV)
+#define glVertexAttribLFormatNV GLEW_GET_FUN(__glewVertexAttribLFormatNV)
+
+#define GLEW_NV_vertex_attrib_integer_64bit GLEW_GET_VAR(__GLEW_NV_vertex_attrib_integer_64bit)
+
+#endif /* !GL_NV_vertex_attrib_integer_64bit */
+
+/* ------------------- GL_NV_vertex_buffer_unified_memory ------------------ */
+
+#if !defined(GL_NV_vertex_buffer_unified_memory)
+#define GL_NV_vertex_buffer_unified_memory 1
+
+#define GL_VERTEX_ATTRIB_ARRAY_UNIFIED_NV 0x8F1E
+#define GL_ELEMENT_ARRAY_UNIFIED_NV 0x8F1F
+#define GL_VERTEX_ATTRIB_ARRAY_ADDRESS_NV 0x8F20
+#define GL_VERTEX_ARRAY_ADDRESS_NV 0x8F21
+#define GL_NORMAL_ARRAY_ADDRESS_NV 0x8F22
+#define GL_COLOR_ARRAY_ADDRESS_NV 0x8F23
+#define GL_INDEX_ARRAY_ADDRESS_NV 0x8F24
+#define GL_TEXTURE_COORD_ARRAY_ADDRESS_NV 0x8F25
+#define GL_EDGE_FLAG_ARRAY_ADDRESS_NV 0x8F26
+#define GL_SECONDARY_COLOR_ARRAY_ADDRESS_NV 0x8F27
+#define GL_FOG_COORD_ARRAY_ADDRESS_NV 0x8F28
+#define GL_ELEMENT_ARRAY_ADDRESS_NV 0x8F29
+#define GL_VERTEX_ATTRIB_ARRAY_LENGTH_NV 0x8F2A
+#define GL_VERTEX_ARRAY_LENGTH_NV 0x8F2B
+#define GL_NORMAL_ARRAY_LENGTH_NV 0x8F2C
+#define GL_COLOR_ARRAY_LENGTH_NV 0x8F2D
+#define GL_INDEX_ARRAY_LENGTH_NV 0x8F2E
+#define GL_TEXTURE_COORD_ARRAY_LENGTH_NV 0x8F2F
+#define GL_EDGE_FLAG_ARRAY_LENGTH_NV 0x8F30
+#define GL_SECONDARY_COLOR_ARRAY_LENGTH_NV 0x8F31
+#define GL_FOG_COORD_ARRAY_LENGTH_NV 0x8F32
+#define GL_ELEMENT_ARRAY_LENGTH_NV 0x8F33
+#define GL_DRAW_INDIRECT_UNIFIED_NV 0x8F40
+#define GL_DRAW_INDIRECT_ADDRESS_NV 0x8F41
+#define GL_DRAW_INDIRECT_LENGTH_NV 0x8F42
+
+typedef void (GLAPIENTRY * PFNGLBUFFERADDRESSRANGENVPROC) (GLenum pname, GLuint index, GLuint64EXT address, GLsizeiptr length);
+typedef void (GLAPIENTRY * PFNGLCOLORFORMATNVPROC) (GLint size, GLenum type, GLsizei stride);
+typedef void (GLAPIENTRY * PFNGLEDGEFLAGFORMATNVPROC) (GLsizei stride);
+typedef void (GLAPIENTRY * PFNGLFOGCOORDFORMATNVPROC) (GLenum type, GLsizei stride);
+typedef void (GLAPIENTRY * PFNGLGETINTEGERUI64I_VNVPROC) (GLenum value, GLuint index, GLuint64EXT result[]);
+typedef void (GLAPIENTRY * PFNGLINDEXFORMATNVPROC) (GLenum type, GLsizei stride);
+typedef void (GLAPIENTRY * PFNGLNORMALFORMATNVPROC) (GLenum type, GLsizei stride);
+typedef void (GLAPIENTRY * PFNGLSECONDARYCOLORFORMATNVPROC) (GLint size, GLenum type, GLsizei stride);
+typedef void (GLAPIENTRY * PFNGLTEXCOORDFORMATNVPROC) (GLint size, GLenum type, GLsizei stride);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBFORMATNVPROC) (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBIFORMATNVPROC) (GLuint index, GLint size, GLenum type, GLsizei stride);
+typedef void (GLAPIENTRY * PFNGLVERTEXFORMATNVPROC) (GLint size, GLenum type, GLsizei stride);
+
+#define glBufferAddressRangeNV GLEW_GET_FUN(__glewBufferAddressRangeNV)
+#define glColorFormatNV GLEW_GET_FUN(__glewColorFormatNV)
+#define glEdgeFlagFormatNV GLEW_GET_FUN(__glewEdgeFlagFormatNV)
+#define glFogCoordFormatNV GLEW_GET_FUN(__glewFogCoordFormatNV)
+#define glGetIntegerui64i_vNV GLEW_GET_FUN(__glewGetIntegerui64i_vNV)
+#define glIndexFormatNV GLEW_GET_FUN(__glewIndexFormatNV)
+#define glNormalFormatNV GLEW_GET_FUN(__glewNormalFormatNV)
+#define glSecondaryColorFormatNV GLEW_GET_FUN(__glewSecondaryColorFormatNV)
+#define glTexCoordFormatNV GLEW_GET_FUN(__glewTexCoordFormatNV)
+#define glVertexAttribFormatNV GLEW_GET_FUN(__glewVertexAttribFormatNV)
+#define glVertexAttribIFormatNV GLEW_GET_FUN(__glewVertexAttribIFormatNV)
+#define glVertexFormatNV GLEW_GET_FUN(__glewVertexFormatNV)
+
+#define GLEW_NV_vertex_buffer_unified_memory GLEW_GET_VAR(__GLEW_NV_vertex_buffer_unified_memory)
+
+#endif /* !GL_NV_vertex_buffer_unified_memory */
+
+/* -------------------------- GL_NV_vertex_program ------------------------- */
+
+#if !defined(GL_NV_vertex_program)
+#define GL_NV_vertex_program 1
+
+#define GL_VERTEX_PROGRAM_NV 0x8620
+#define GL_VERTEX_STATE_PROGRAM_NV 0x8621
+#define GL_ATTRIB_ARRAY_SIZE_NV 0x8623
+#define GL_ATTRIB_ARRAY_STRIDE_NV 0x8624
+#define GL_ATTRIB_ARRAY_TYPE_NV 0x8625
+#define GL_CURRENT_ATTRIB_NV 0x8626
+#define GL_PROGRAM_LENGTH_NV 0x8627
+#define GL_PROGRAM_STRING_NV 0x8628
+#define GL_MODELVIEW_PROJECTION_NV 0x8629
+#define GL_IDENTITY_NV 0x862A
+#define GL_INVERSE_NV 0x862B
+#define GL_TRANSPOSE_NV 0x862C
+#define GL_INVERSE_TRANSPOSE_NV 0x862D
+#define GL_MAX_TRACK_MATRIX_STACK_DEPTH_NV 0x862E
+#define GL_MAX_TRACK_MATRICES_NV 0x862F
+#define GL_MATRIX0_NV 0x8630
+#define GL_MATRIX1_NV 0x8631
+#define GL_MATRIX2_NV 0x8632
+#define GL_MATRIX3_NV 0x8633
+#define GL_MATRIX4_NV 0x8634
+#define GL_MATRIX5_NV 0x8635
+#define GL_MATRIX6_NV 0x8636
+#define GL_MATRIX7_NV 0x8637
+#define GL_CURRENT_MATRIX_STACK_DEPTH_NV 0x8640
+#define GL_CURRENT_MATRIX_NV 0x8641
+#define GL_VERTEX_PROGRAM_POINT_SIZE_NV 0x8642
+#define GL_VERTEX_PROGRAM_TWO_SIDE_NV 0x8643
+#define GL_PROGRAM_PARAMETER_NV 0x8644
+#define GL_ATTRIB_ARRAY_POINTER_NV 0x8645
+#define GL_PROGRAM_TARGET_NV 0x8646
+#define GL_PROGRAM_RESIDENT_NV 0x8647
+#define GL_TRACK_MATRIX_NV 0x8648
+#define GL_TRACK_MATRIX_TRANSFORM_NV 0x8649
+#define GL_VERTEX_PROGRAM_BINDING_NV 0x864A
+#define GL_PROGRAM_ERROR_POSITION_NV 0x864B
+#define GL_VERTEX_ATTRIB_ARRAY0_NV 0x8650
+#define GL_VERTEX_ATTRIB_ARRAY1_NV 0x8651
+#define GL_VERTEX_ATTRIB_ARRAY2_NV 0x8652
+#define GL_VERTEX_ATTRIB_ARRAY3_NV 0x8653
+#define GL_VERTEX_ATTRIB_ARRAY4_NV 0x8654
+#define GL_VERTEX_ATTRIB_ARRAY5_NV 0x8655
+#define GL_VERTEX_ATTRIB_ARRAY6_NV 0x8656
+#define GL_VERTEX_ATTRIB_ARRAY7_NV 0x8657
+#define GL_VERTEX_ATTRIB_ARRAY8_NV 0x8658
+#define GL_VERTEX_ATTRIB_ARRAY9_NV 0x8659
+#define GL_VERTEX_ATTRIB_ARRAY10_NV 0x865A
+#define GL_VERTEX_ATTRIB_ARRAY11_NV 0x865B
+#define GL_VERTEX_ATTRIB_ARRAY12_NV 0x865C
+#define GL_VERTEX_ATTRIB_ARRAY13_NV 0x865D
+#define GL_VERTEX_ATTRIB_ARRAY14_NV 0x865E
+#define GL_VERTEX_ATTRIB_ARRAY15_NV 0x865F
+#define GL_MAP1_VERTEX_ATTRIB0_4_NV 0x8660
+#define GL_MAP1_VERTEX_ATTRIB1_4_NV 0x8661
+#define GL_MAP1_VERTEX_ATTRIB2_4_NV 0x8662
+#define GL_MAP1_VERTEX_ATTRIB3_4_NV 0x8663
+#define GL_MAP1_VERTEX_ATTRIB4_4_NV 0x8664
+#define GL_MAP1_VERTEX_ATTRIB5_4_NV 0x8665
+#define GL_MAP1_VERTEX_ATTRIB6_4_NV 0x8666
+#define GL_MAP1_VERTEX_ATTRIB7_4_NV 0x8667
+#define GL_MAP1_VERTEX_ATTRIB8_4_NV 0x8668
+#define GL_MAP1_VERTEX_ATTRIB9_4_NV 0x8669
+#define GL_MAP1_VERTEX_ATTRIB10_4_NV 0x866A
+#define GL_MAP1_VERTEX_ATTRIB11_4_NV 0x866B
+#define GL_MAP1_VERTEX_ATTRIB12_4_NV 0x866C
+#define GL_MAP1_VERTEX_ATTRIB13_4_NV 0x866D
+#define GL_MAP1_VERTEX_ATTRIB14_4_NV 0x866E
+#define GL_MAP1_VERTEX_ATTRIB15_4_NV 0x866F
+#define GL_MAP2_VERTEX_ATTRIB0_4_NV 0x8670
+#define GL_MAP2_VERTEX_ATTRIB1_4_NV 0x8671
+#define GL_MAP2_VERTEX_ATTRIB2_4_NV 0x8672
+#define GL_MAP2_VERTEX_ATTRIB3_4_NV 0x8673
+#define GL_MAP2_VERTEX_ATTRIB4_4_NV 0x8674
+#define GL_MAP2_VERTEX_ATTRIB5_4_NV 0x8675
+#define GL_MAP2_VERTEX_ATTRIB6_4_NV 0x8676
+#define GL_MAP2_VERTEX_ATTRIB7_4_NV 0x8677
+#define GL_MAP2_VERTEX_ATTRIB8_4_NV 0x8678
+#define GL_MAP2_VERTEX_ATTRIB9_4_NV 0x8679
+#define GL_MAP2_VERTEX_ATTRIB10_4_NV 0x867A
+#define GL_MAP2_VERTEX_ATTRIB11_4_NV 0x867B
+#define GL_MAP2_VERTEX_ATTRIB12_4_NV 0x867C
+#define GL_MAP2_VERTEX_ATTRIB13_4_NV 0x867D
+#define GL_MAP2_VERTEX_ATTRIB14_4_NV 0x867E
+#define GL_MAP2_VERTEX_ATTRIB15_4_NV 0x867F
+
+typedef GLboolean (GLAPIENTRY * PFNGLAREPROGRAMSRESIDENTNVPROC) (GLsizei n, const GLuint* ids, GLboolean *residences);
+typedef void (GLAPIENTRY * PFNGLBINDPROGRAMNVPROC) (GLenum target, GLuint id);
+typedef void (GLAPIENTRY * PFNGLDELETEPROGRAMSNVPROC) (GLsizei n, const GLuint* ids);
+typedef void (GLAPIENTRY * PFNGLEXECUTEPROGRAMNVPROC) (GLenum target, GLuint id, const GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLGENPROGRAMSNVPROC) (GLsizei n, GLuint* ids);
+typedef void (GLAPIENTRY * PFNGLGETPROGRAMPARAMETERDVNVPROC) (GLenum target, GLuint index, GLenum pname, GLdouble* params);
+typedef void (GLAPIENTRY * PFNGLGETPROGRAMPARAMETERFVNVPROC) (GLenum target, GLuint index, GLenum pname, GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLGETPROGRAMSTRINGNVPROC) (GLuint id, GLenum pname, GLubyte* program);
+typedef void (GLAPIENTRY * PFNGLGETPROGRAMIVNVPROC) (GLuint id, GLenum pname, GLint* params);
+typedef void (GLAPIENTRY * PFNGLGETTRACKMATRIXIVNVPROC) (GLenum target, GLuint address, GLenum pname, GLint* params);
+typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBPOINTERVNVPROC) (GLuint index, GLenum pname, GLvoid** pointer);
+typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBDVNVPROC) (GLuint index, GLenum pname, GLdouble* params);
+typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBFVNVPROC) (GLuint index, GLenum pname, GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBIVNVPROC) (GLuint index, GLenum pname, GLint* params);
+typedef GLboolean (GLAPIENTRY * PFNGLISPROGRAMNVPROC) (GLuint id);
+typedef void (GLAPIENTRY * PFNGLLOADPROGRAMNVPROC) (GLenum target, GLuint id, GLsizei len, const GLubyte* program);
+typedef void (GLAPIENTRY * PFNGLPROGRAMPARAMETER4DNVPROC) (GLenum target, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+typedef void (GLAPIENTRY * PFNGLPROGRAMPARAMETER4DVNVPROC) (GLenum target, GLuint index, const GLdouble* params);
+typedef void (GLAPIENTRY * PFNGLPROGRAMPARAMETER4FNVPROC) (GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+typedef void (GLAPIENTRY * PFNGLPROGRAMPARAMETER4FVNVPROC) (GLenum target, GLuint index, const GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLPROGRAMPARAMETERS4DVNVPROC) (GLenum target, GLuint index, GLsizei num, const GLdouble* params);
+typedef void (GLAPIENTRY * PFNGLPROGRAMPARAMETERS4FVNVPROC) (GLenum target, GLuint index, GLsizei num, const GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLREQUESTRESIDENTPROGRAMSNVPROC) (GLsizei n, GLuint* ids);
+typedef void (GLAPIENTRY * PFNGLTRACKMATRIXNVPROC) (GLenum target, GLuint address, GLenum matrix, GLenum transform);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB1DNVPROC) (GLuint index, GLdouble x);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB1DVNVPROC) (GLuint index, const GLdouble* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB1FNVPROC) (GLuint index, GLfloat x);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB1FVNVPROC) (GLuint index, const GLfloat* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB1SNVPROC) (GLuint index, GLshort x);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB1SVNVPROC) (GLuint index, const GLshort* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB2DNVPROC) (GLuint index, GLdouble x, GLdouble y);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB2DVNVPROC) (GLuint index, const GLdouble* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB2FNVPROC) (GLuint index, GLfloat x, GLfloat y);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB2FVNVPROC) (GLuint index, const GLfloat* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB2SNVPROC) (GLuint index, GLshort x, GLshort y);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB2SVNVPROC) (GLuint index, const GLshort* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB3DNVPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB3DVNVPROC) (GLuint index, const GLdouble* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB3FNVPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB3FVNVPROC) (GLuint index, const GLfloat* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB3SNVPROC) (GLuint index, GLshort x, GLshort y, GLshort z);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB3SVNVPROC) (GLuint index, const GLshort* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4DNVPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4DVNVPROC) (GLuint index, const GLdouble* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4FNVPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4FVNVPROC) (GLuint index, const GLfloat* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4SNVPROC) (GLuint index, GLshort x, GLshort y, GLshort z, GLshort w);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4SVNVPROC) (GLuint index, const GLshort* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4UBNVPROC) (GLuint index, GLubyte x, GLubyte y, GLubyte z, GLubyte w);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4UBVNVPROC) (GLuint index, const GLubyte* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBPOINTERNVPROC) (GLuint index, GLint size, GLenum type, GLsizei stride, const void* pointer);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBS1DVNVPROC) (GLuint index, GLsizei n, const GLdouble* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBS1FVNVPROC) (GLuint index, GLsizei n, const GLfloat* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBS1SVNVPROC) (GLuint index, GLsizei n, const GLshort* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBS2DVNVPROC) (GLuint index, GLsizei n, const GLdouble* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBS2FVNVPROC) (GLuint index, GLsizei n, const GLfloat* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBS2SVNVPROC) (GLuint index, GLsizei n, const GLshort* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBS3DVNVPROC) (GLuint index, GLsizei n, const GLdouble* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBS3FVNVPROC) (GLuint index, GLsizei n, const GLfloat* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBS3SVNVPROC) (GLuint index, GLsizei n, const GLshort* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBS4DVNVPROC) (GLuint index, GLsizei n, const GLdouble* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBS4FVNVPROC) (GLuint index, GLsizei n, const GLfloat* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBS4SVNVPROC) (GLuint index, GLsizei n, const GLshort* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBS4UBVNVPROC) (GLuint index, GLsizei n, const GLubyte* v);
+
+#define glAreProgramsResidentNV GLEW_GET_FUN(__glewAreProgramsResidentNV)
+#define glBindProgramNV GLEW_GET_FUN(__glewBindProgramNV)
+#define glDeleteProgramsNV GLEW_GET_FUN(__glewDeleteProgramsNV)
+#define glExecuteProgramNV GLEW_GET_FUN(__glewExecuteProgramNV)
+#define glGenProgramsNV GLEW_GET_FUN(__glewGenProgramsNV)
+#define glGetProgramParameterdvNV GLEW_GET_FUN(__glewGetProgramParameterdvNV)
+#define glGetProgramParameterfvNV GLEW_GET_FUN(__glewGetProgramParameterfvNV)
+#define glGetProgramStringNV GLEW_GET_FUN(__glewGetProgramStringNV)
+#define glGetProgramivNV GLEW_GET_FUN(__glewGetProgramivNV)
+#define glGetTrackMatrixivNV GLEW_GET_FUN(__glewGetTrackMatrixivNV)
+#define glGetVertexAttribPointervNV GLEW_GET_FUN(__glewGetVertexAttribPointervNV)
+#define glGetVertexAttribdvNV GLEW_GET_FUN(__glewGetVertexAttribdvNV)
+#define glGetVertexAttribfvNV GLEW_GET_FUN(__glewGetVertexAttribfvNV)
+#define glGetVertexAttribivNV GLEW_GET_FUN(__glewGetVertexAttribivNV)
+#define glIsProgramNV GLEW_GET_FUN(__glewIsProgramNV)
+#define glLoadProgramNV GLEW_GET_FUN(__glewLoadProgramNV)
+#define glProgramParameter4dNV GLEW_GET_FUN(__glewProgramParameter4dNV)
+#define glProgramParameter4dvNV GLEW_GET_FUN(__glewProgramParameter4dvNV)
+#define glProgramParameter4fNV GLEW_GET_FUN(__glewProgramParameter4fNV)
+#define glProgramParameter4fvNV GLEW_GET_FUN(__glewProgramParameter4fvNV)
+#define glProgramParameters4dvNV GLEW_GET_FUN(__glewProgramParameters4dvNV)
+#define glProgramParameters4fvNV GLEW_GET_FUN(__glewProgramParameters4fvNV)
+#define glRequestResidentProgramsNV GLEW_GET_FUN(__glewRequestResidentProgramsNV)
+#define glTrackMatrixNV GLEW_GET_FUN(__glewTrackMatrixNV)
+#define glVertexAttrib1dNV GLEW_GET_FUN(__glewVertexAttrib1dNV)
+#define glVertexAttrib1dvNV GLEW_GET_FUN(__glewVertexAttrib1dvNV)
+#define glVertexAttrib1fNV GLEW_GET_FUN(__glewVertexAttrib1fNV)
+#define glVertexAttrib1fvNV GLEW_GET_FUN(__glewVertexAttrib1fvNV)
+#define glVertexAttrib1sNV GLEW_GET_FUN(__glewVertexAttrib1sNV)
+#define glVertexAttrib1svNV GLEW_GET_FUN(__glewVertexAttrib1svNV)
+#define glVertexAttrib2dNV GLEW_GET_FUN(__glewVertexAttrib2dNV)
+#define glVertexAttrib2dvNV GLEW_GET_FUN(__glewVertexAttrib2dvNV)
+#define glVertexAttrib2fNV GLEW_GET_FUN(__glewVertexAttrib2fNV)
+#define glVertexAttrib2fvNV GLEW_GET_FUN(__glewVertexAttrib2fvNV)
+#define glVertexAttrib2sNV GLEW_GET_FUN(__glewVertexAttrib2sNV)
+#define glVertexAttrib2svNV GLEW_GET_FUN(__glewVertexAttrib2svNV)
+#define glVertexAttrib3dNV GLEW_GET_FUN(__glewVertexAttrib3dNV)
+#define glVertexAttrib3dvNV GLEW_GET_FUN(__glewVertexAttrib3dvNV)
+#define glVertexAttrib3fNV GLEW_GET_FUN(__glewVertexAttrib3fNV)
+#define glVertexAttrib3fvNV GLEW_GET_FUN(__glewVertexAttrib3fvNV)
+#define glVertexAttrib3sNV GLEW_GET_FUN(__glewVertexAttrib3sNV)
+#define glVertexAttrib3svNV GLEW_GET_FUN(__glewVertexAttrib3svNV)
+#define glVertexAttrib4dNV GLEW_GET_FUN(__glewVertexAttrib4dNV)
+#define glVertexAttrib4dvNV GLEW_GET_FUN(__glewVertexAttrib4dvNV)
+#define glVertexAttrib4fNV GLEW_GET_FUN(__glewVertexAttrib4fNV)
+#define glVertexAttrib4fvNV GLEW_GET_FUN(__glewVertexAttrib4fvNV)
+#define glVertexAttrib4sNV GLEW_GET_FUN(__glewVertexAttrib4sNV)
+#define glVertexAttrib4svNV GLEW_GET_FUN(__glewVertexAttrib4svNV)
+#define glVertexAttrib4ubNV GLEW_GET_FUN(__glewVertexAttrib4ubNV)
+#define glVertexAttrib4ubvNV GLEW_GET_FUN(__glewVertexAttrib4ubvNV)
+#define glVertexAttribPointerNV GLEW_GET_FUN(__glewVertexAttribPointerNV)
+#define glVertexAttribs1dvNV GLEW_GET_FUN(__glewVertexAttribs1dvNV)
+#define glVertexAttribs1fvNV GLEW_GET_FUN(__glewVertexAttribs1fvNV)
+#define glVertexAttribs1svNV GLEW_GET_FUN(__glewVertexAttribs1svNV)
+#define glVertexAttribs2dvNV GLEW_GET_FUN(__glewVertexAttribs2dvNV)
+#define glVertexAttribs2fvNV GLEW_GET_FUN(__glewVertexAttribs2fvNV)
+#define glVertexAttribs2svNV GLEW_GET_FUN(__glewVertexAttribs2svNV)
+#define glVertexAttribs3dvNV GLEW_GET_FUN(__glewVertexAttribs3dvNV)
+#define glVertexAttribs3fvNV GLEW_GET_FUN(__glewVertexAttribs3fvNV)
+#define glVertexAttribs3svNV GLEW_GET_FUN(__glewVertexAttribs3svNV)
+#define glVertexAttribs4dvNV GLEW_GET_FUN(__glewVertexAttribs4dvNV)
+#define glVertexAttribs4fvNV GLEW_GET_FUN(__glewVertexAttribs4fvNV)
+#define glVertexAttribs4svNV GLEW_GET_FUN(__glewVertexAttribs4svNV)
+#define glVertexAttribs4ubvNV GLEW_GET_FUN(__glewVertexAttribs4ubvNV)
+
+#define GLEW_NV_vertex_program GLEW_GET_VAR(__GLEW_NV_vertex_program)
+
+#endif /* !GL_NV_vertex_program */
+
+/* ------------------------ GL_NV_vertex_program1_1 ------------------------ */
+
+#if !defined(GL_NV_vertex_program1_1)
+#define GL_NV_vertex_program1_1 1
+
+#define GLEW_NV_vertex_program1_1 GLEW_GET_VAR(__GLEW_NV_vertex_program1_1)
+
+#endif /* !GL_NV_vertex_program1_1 */
+
+/* ------------------------- GL_NV_vertex_program2 ------------------------- */
+
+#if !defined(GL_NV_vertex_program2)
+#define GL_NV_vertex_program2 1
+
+#define GLEW_NV_vertex_program2 GLEW_GET_VAR(__GLEW_NV_vertex_program2)
+
+#endif /* !GL_NV_vertex_program2 */
+
+/* ---------------------- GL_NV_vertex_program2_option --------------------- */
+
+#if !defined(GL_NV_vertex_program2_option)
+#define GL_NV_vertex_program2_option 1
+
+#define GL_MAX_PROGRAM_EXEC_INSTRUCTIONS_NV 0x88F4
+#define GL_MAX_PROGRAM_CALL_DEPTH_NV 0x88F5
+
+#define GLEW_NV_vertex_program2_option GLEW_GET_VAR(__GLEW_NV_vertex_program2_option)
+
+#endif /* !GL_NV_vertex_program2_option */
+
+/* ------------------------- GL_NV_vertex_program3 ------------------------- */
+
+#if !defined(GL_NV_vertex_program3)
+#define GL_NV_vertex_program3 1
+
+#define MAX_VERTEX_TEXTURE_IMAGE_UNITS_ARB 0x8B4C
+
+#define GLEW_NV_vertex_program3 GLEW_GET_VAR(__GLEW_NV_vertex_program3)
+
+#endif /* !GL_NV_vertex_program3 */
+
+/* ------------------------- GL_NV_vertex_program4 ------------------------- */
+
+#if !defined(GL_NV_vertex_program4)
+#define GL_NV_vertex_program4 1
+
+#define GL_VERTEX_ATTRIB_ARRAY_INTEGER_NV 0x88FD
+
+#define GLEW_NV_vertex_program4 GLEW_GET_VAR(__GLEW_NV_vertex_program4)
+
+#endif /* !GL_NV_vertex_program4 */
+
+/* -------------------------- GL_NV_video_capture -------------------------- */
+
+#if !defined(GL_NV_video_capture)
+#define GL_NV_video_capture 1
+
+#define GL_VIDEO_BUFFER_NV 0x9020
+#define GL_VIDEO_BUFFER_BINDING_NV 0x9021
+#define GL_FIELD_UPPER_NV 0x9022
+#define GL_FIELD_LOWER_NV 0x9023
+#define GL_NUM_VIDEO_CAPTURE_STREAMS_NV 0x9024
+#define GL_NEXT_VIDEO_CAPTURE_BUFFER_STATUS_NV 0x9025
+#define GL_VIDEO_CAPTURE_TO_422_SUPPORTED_NV 0x9026
+#define GL_LAST_VIDEO_CAPTURE_STATUS_NV 0x9027
+#define GL_VIDEO_BUFFER_PITCH_NV 0x9028
+#define GL_VIDEO_COLOR_CONVERSION_MATRIX_NV 0x9029
+#define GL_VIDEO_COLOR_CONVERSION_MAX_NV 0x902A
+#define GL_VIDEO_COLOR_CONVERSION_MIN_NV 0x902B
+#define GL_VIDEO_COLOR_CONVERSION_OFFSET_NV 0x902C
+#define GL_VIDEO_BUFFER_INTERNAL_FORMAT_NV 0x902D
+#define GL_PARTIAL_SUCCESS_NV 0x902E
+#define GL_SUCCESS_NV 0x902F
+#define GL_FAILURE_NV 0x9030
+#define GL_YCBYCR8_422_NV 0x9031
+#define GL_YCBAYCR8A_4224_NV 0x9032
+#define GL_Z6Y10Z6CB10Z6Y10Z6CR10_422_NV 0x9033
+#define GL_Z6Y10Z6CB10Z6A10Z6Y10Z6CR10Z6A10_4224_NV 0x9034
+#define GL_Z4Y12Z4CB12Z4Y12Z4CR12_422_NV 0x9035
+#define GL_Z4Y12Z4CB12Z4A12Z4Y12Z4CR12Z4A12_4224_NV 0x9036
+#define GL_Z4Y12Z4CB12Z4CR12_444_NV 0x9037
+#define GL_VIDEO_CAPTURE_FRAME_WIDTH_NV 0x9038
+#define GL_VIDEO_CAPTURE_FRAME_HEIGHT_NV 0x9039
+#define GL_VIDEO_CAPTURE_FIELD_UPPER_HEIGHT_NV 0x903A
+#define GL_VIDEO_CAPTURE_FIELD_LOWER_HEIGHT_NV 0x903B
+#define GL_VIDEO_CAPTURE_SURFACE_ORIGIN_NV 0x903C
+
+typedef void (GLAPIENTRY * PFNGLBEGINVIDEOCAPTURENVPROC) (GLuint video_capture_slot);
+typedef void (GLAPIENTRY * PFNGLBINDVIDEOCAPTURESTREAMBUFFERNVPROC) (GLuint video_capture_slot, GLuint stream, GLenum frame_region, GLintptrARB offset);
+typedef void (GLAPIENTRY * PFNGLBINDVIDEOCAPTURESTREAMTEXTURENVPROC) (GLuint video_capture_slot, GLuint stream, GLenum frame_region, GLenum target, GLuint texture);
+typedef void (GLAPIENTRY * PFNGLENDVIDEOCAPTURENVPROC) (GLuint video_capture_slot);
+typedef void (GLAPIENTRY * PFNGLGETVIDEOCAPTURESTREAMDVNVPROC) (GLuint video_capture_slot, GLuint stream, GLenum pname, GLdouble* params);
+typedef void (GLAPIENTRY * PFNGLGETVIDEOCAPTURESTREAMFVNVPROC) (GLuint video_capture_slot, GLuint stream, GLenum pname, GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLGETVIDEOCAPTURESTREAMIVNVPROC) (GLuint video_capture_slot, GLuint stream, GLenum pname, GLint* params);
+typedef void (GLAPIENTRY * PFNGLGETVIDEOCAPTUREIVNVPROC) (GLuint video_capture_slot, GLenum pname, GLint* params);
+typedef GLenum (GLAPIENTRY * PFNGLVIDEOCAPTURENVPROC) (GLuint video_capture_slot, GLuint* sequence_num, GLuint64EXT *capture_time);
+typedef void (GLAPIENTRY * PFNGLVIDEOCAPTURESTREAMPARAMETERDVNVPROC) (GLuint video_capture_slot, GLuint stream, GLenum pname, const GLdouble* params);
+typedef void (GLAPIENTRY * PFNGLVIDEOCAPTURESTREAMPARAMETERFVNVPROC) (GLuint video_capture_slot, GLuint stream, GLenum pname, const GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLVIDEOCAPTURESTREAMPARAMETERIVNVPROC) (GLuint video_capture_slot, GLuint stream, GLenum pname, const GLint* params);
+
+#define glBeginVideoCaptureNV GLEW_GET_FUN(__glewBeginVideoCaptureNV)
+#define glBindVideoCaptureStreamBufferNV GLEW_GET_FUN(__glewBindVideoCaptureStreamBufferNV)
+#define glBindVideoCaptureStreamTextureNV GLEW_GET_FUN(__glewBindVideoCaptureStreamTextureNV)
+#define glEndVideoCaptureNV GLEW_GET_FUN(__glewEndVideoCaptureNV)
+#define glGetVideoCaptureStreamdvNV GLEW_GET_FUN(__glewGetVideoCaptureStreamdvNV)
+#define glGetVideoCaptureStreamfvNV GLEW_GET_FUN(__glewGetVideoCaptureStreamfvNV)
+#define glGetVideoCaptureStreamivNV GLEW_GET_FUN(__glewGetVideoCaptureStreamivNV)
+#define glGetVideoCaptureivNV GLEW_GET_FUN(__glewGetVideoCaptureivNV)
+#define glVideoCaptureNV GLEW_GET_FUN(__glewVideoCaptureNV)
+#define glVideoCaptureStreamParameterdvNV GLEW_GET_FUN(__glewVideoCaptureStreamParameterdvNV)
+#define glVideoCaptureStreamParameterfvNV GLEW_GET_FUN(__glewVideoCaptureStreamParameterfvNV)
+#define glVideoCaptureStreamParameterivNV GLEW_GET_FUN(__glewVideoCaptureStreamParameterivNV)
+
+#define GLEW_NV_video_capture GLEW_GET_VAR(__GLEW_NV_video_capture)
+
+#endif /* !GL_NV_video_capture */
+
+/* ------------------------ GL_OES_byte_coordinates ------------------------ */
+
+#if !defined(GL_OES_byte_coordinates)
+#define GL_OES_byte_coordinates 1
+
+#define GL_BYTE 0x1400
+
+#define GLEW_OES_byte_coordinates GLEW_GET_VAR(__GLEW_OES_byte_coordinates)
+
+#endif /* !GL_OES_byte_coordinates */
+
+/* ------------------- GL_OES_compressed_paletted_texture ------------------ */
+
+#if !defined(GL_OES_compressed_paletted_texture)
+#define GL_OES_compressed_paletted_texture 1
+
+#define GL_PALETTE4_RGB8_OES 0x8B90
+#define GL_PALETTE4_RGBA8_OES 0x8B91
+#define GL_PALETTE4_R5_G6_B5_OES 0x8B92
+#define GL_PALETTE4_RGBA4_OES 0x8B93
+#define GL_PALETTE4_RGB5_A1_OES 0x8B94
+#define GL_PALETTE8_RGB8_OES 0x8B95
+#define GL_PALETTE8_RGBA8_OES 0x8B96
+#define GL_PALETTE8_R5_G6_B5_OES 0x8B97
+#define GL_PALETTE8_RGBA4_OES 0x8B98
+#define GL_PALETTE8_RGB5_A1_OES 0x8B99
+
+#define GLEW_OES_compressed_paletted_texture GLEW_GET_VAR(__GLEW_OES_compressed_paletted_texture)
+
+#endif /* !GL_OES_compressed_paletted_texture */
+
+/* --------------------------- GL_OES_read_format -------------------------- */
+
+#if !defined(GL_OES_read_format)
+#define GL_OES_read_format 1
+
+#define GL_IMPLEMENTATION_COLOR_READ_TYPE_OES 0x8B9A
+#define GL_IMPLEMENTATION_COLOR_READ_FORMAT_OES 0x8B9B
+
+#define GLEW_OES_read_format GLEW_GET_VAR(__GLEW_OES_read_format)
+
+#endif /* !GL_OES_read_format */
+
+/* ------------------------ GL_OES_single_precision ------------------------ */
+
+#if !defined(GL_OES_single_precision)
+#define GL_OES_single_precision 1
+
+typedef void (GLAPIENTRY * PFNGLCLEARDEPTHFOESPROC) (GLclampd depth);
+typedef void (GLAPIENTRY * PFNGLCLIPPLANEFOESPROC) (GLenum plane, const GLfloat* equation);
+typedef void (GLAPIENTRY * PFNGLDEPTHRANGEFOESPROC) (GLclampf n, GLclampf f);
+typedef void (GLAPIENTRY * PFNGLFRUSTUMFOESPROC) (GLfloat l, GLfloat r, GLfloat b, GLfloat t, GLfloat n, GLfloat f);
+typedef void (GLAPIENTRY * PFNGLGETCLIPPLANEFOESPROC) (GLenum plane, GLfloat* equation);
+typedef void (GLAPIENTRY * PFNGLORTHOFOESPROC) (GLfloat l, GLfloat r, GLfloat b, GLfloat t, GLfloat n, GLfloat f);
+
+#define glClearDepthfOES GLEW_GET_FUN(__glewClearDepthfOES)
+#define glClipPlanefOES GLEW_GET_FUN(__glewClipPlanefOES)
+#define glDepthRangefOES GLEW_GET_FUN(__glewDepthRangefOES)
+#define glFrustumfOES GLEW_GET_FUN(__glewFrustumfOES)
+#define glGetClipPlanefOES GLEW_GET_FUN(__glewGetClipPlanefOES)
+#define glOrthofOES GLEW_GET_FUN(__glewOrthofOES)
+
+#define GLEW_OES_single_precision GLEW_GET_VAR(__GLEW_OES_single_precision)
+
+#endif /* !GL_OES_single_precision */
+
+/* ---------------------------- GL_OML_interlace --------------------------- */
+
+#if !defined(GL_OML_interlace)
+#define GL_OML_interlace 1
+
+#define GL_INTERLACE_OML 0x8980
+#define GL_INTERLACE_READ_OML 0x8981
+
+#define GLEW_OML_interlace GLEW_GET_VAR(__GLEW_OML_interlace)
+
+#endif /* !GL_OML_interlace */
+
+/* ---------------------------- GL_OML_resample ---------------------------- */
+
+#if !defined(GL_OML_resample)
+#define GL_OML_resample 1
+
+#define GL_PACK_RESAMPLE_OML 0x8984
+#define GL_UNPACK_RESAMPLE_OML 0x8985
+#define GL_RESAMPLE_REPLICATE_OML 0x8986
+#define GL_RESAMPLE_ZERO_FILL_OML 0x8987
+#define GL_RESAMPLE_AVERAGE_OML 0x8988
+#define GL_RESAMPLE_DECIMATE_OML 0x8989
+
+#define GLEW_OML_resample GLEW_GET_VAR(__GLEW_OML_resample)
+
+#endif /* !GL_OML_resample */
+
+/* ---------------------------- GL_OML_subsample --------------------------- */
+
+#if !defined(GL_OML_subsample)
+#define GL_OML_subsample 1
+
+#define GL_FORMAT_SUBSAMPLE_24_24_OML 0x8982
+#define GL_FORMAT_SUBSAMPLE_244_244_OML 0x8983
+
+#define GLEW_OML_subsample GLEW_GET_VAR(__GLEW_OML_subsample)
+
+#endif /* !GL_OML_subsample */
+
+/* --------------------------- GL_PGI_misc_hints --------------------------- */
+
+#if !defined(GL_PGI_misc_hints)
+#define GL_PGI_misc_hints 1
+
+#define GL_PREFER_DOUBLEBUFFER_HINT_PGI 107000
+#define GL_CONSERVE_MEMORY_HINT_PGI 107005
+#define GL_RECLAIM_MEMORY_HINT_PGI 107006
+#define GL_NATIVE_GRAPHICS_HANDLE_PGI 107010
+#define GL_NATIVE_GRAPHICS_BEGIN_HINT_PGI 107011
+#define GL_NATIVE_GRAPHICS_END_HINT_PGI 107012
+#define GL_ALWAYS_FAST_HINT_PGI 107020
+#define GL_ALWAYS_SOFT_HINT_PGI 107021
+#define GL_ALLOW_DRAW_OBJ_HINT_PGI 107022
+#define GL_ALLOW_DRAW_WIN_HINT_PGI 107023
+#define GL_ALLOW_DRAW_FRG_HINT_PGI 107024
+#define GL_ALLOW_DRAW_MEM_HINT_PGI 107025
+#define GL_STRICT_DEPTHFUNC_HINT_PGI 107030
+#define GL_STRICT_LIGHTING_HINT_PGI 107031
+#define GL_STRICT_SCISSOR_HINT_PGI 107032
+#define GL_FULL_STIPPLE_HINT_PGI 107033
+#define GL_CLIP_NEAR_HINT_PGI 107040
+#define GL_CLIP_FAR_HINT_PGI 107041
+#define GL_WIDE_LINE_HINT_PGI 107042
+#define GL_BACK_NORMALS_HINT_PGI 107043
+
+#define GLEW_PGI_misc_hints GLEW_GET_VAR(__GLEW_PGI_misc_hints)
+
+#endif /* !GL_PGI_misc_hints */
+
+/* -------------------------- GL_PGI_vertex_hints -------------------------- */
+
+#if !defined(GL_PGI_vertex_hints)
+#define GL_PGI_vertex_hints 1
+
+#define GL_VERTEX23_BIT_PGI 0x00000004
+#define GL_VERTEX4_BIT_PGI 0x00000008
+#define GL_COLOR3_BIT_PGI 0x00010000
+#define GL_COLOR4_BIT_PGI 0x00020000
+#define GL_EDGEFLAG_BIT_PGI 0x00040000
+#define GL_INDEX_BIT_PGI 0x00080000
+#define GL_MAT_AMBIENT_BIT_PGI 0x00100000
+#define GL_VERTEX_DATA_HINT_PGI 107050
+#define GL_VERTEX_CONSISTENT_HINT_PGI 107051
+#define GL_MATERIAL_SIDE_HINT_PGI 107052
+#define GL_MAX_VERTEX_HINT_PGI 107053
+#define GL_MAT_AMBIENT_AND_DIFFUSE_BIT_PGI 0x00200000
+#define GL_MAT_DIFFUSE_BIT_PGI 0x00400000
+#define GL_MAT_EMISSION_BIT_PGI 0x00800000
+#define GL_MAT_COLOR_INDEXES_BIT_PGI 0x01000000
+#define GL_MAT_SHININESS_BIT_PGI 0x02000000
+#define GL_MAT_SPECULAR_BIT_PGI 0x04000000
+#define GL_NORMAL_BIT_PGI 0x08000000
+#define GL_TEXCOORD1_BIT_PGI 0x10000000
+#define GL_TEXCOORD2_BIT_PGI 0x20000000
+#define GL_TEXCOORD3_BIT_PGI 0x40000000
+#define GL_TEXCOORD4_BIT_PGI 0x80000000
+
+#define GLEW_PGI_vertex_hints GLEW_GET_VAR(__GLEW_PGI_vertex_hints)
+
+#endif /* !GL_PGI_vertex_hints */
+
+/* ----------------------- GL_REND_screen_coordinates ---------------------- */
+
+#if !defined(GL_REND_screen_coordinates)
+#define GL_REND_screen_coordinates 1
+
+#define GL_SCREEN_COORDINATES_REND 0x8490
+#define GL_INVERTED_SCREEN_W_REND 0x8491
+
+#define GLEW_REND_screen_coordinates GLEW_GET_VAR(__GLEW_REND_screen_coordinates)
+
+#endif /* !GL_REND_screen_coordinates */
+
+/* ------------------------------- GL_S3_s3tc ------------------------------ */
+
+#if !defined(GL_S3_s3tc)
+#define GL_S3_s3tc 1
+
+#define GL_RGB_S3TC 0x83A0
+#define GL_RGB4_S3TC 0x83A1
+#define GL_RGBA_S3TC 0x83A2
+#define GL_RGBA4_S3TC 0x83A3
+#define GL_RGBA_DXT5_S3TC 0x83A4
+#define GL_RGBA4_DXT5_S3TC 0x83A5
+
+#define GLEW_S3_s3tc GLEW_GET_VAR(__GLEW_S3_s3tc)
+
+#endif /* !GL_S3_s3tc */
+
+/* -------------------------- GL_SGIS_color_range -------------------------- */
+
+#if !defined(GL_SGIS_color_range)
+#define GL_SGIS_color_range 1
+
+#define GL_EXTENDED_RANGE_SGIS 0x85A5
+#define GL_MIN_RED_SGIS 0x85A6
+#define GL_MAX_RED_SGIS 0x85A7
+#define GL_MIN_GREEN_SGIS 0x85A8
+#define GL_MAX_GREEN_SGIS 0x85A9
+#define GL_MIN_BLUE_SGIS 0x85AA
+#define GL_MAX_BLUE_SGIS 0x85AB
+#define GL_MIN_ALPHA_SGIS 0x85AC
+#define GL_MAX_ALPHA_SGIS 0x85AD
+
+#define GLEW_SGIS_color_range GLEW_GET_VAR(__GLEW_SGIS_color_range)
+
+#endif /* !GL_SGIS_color_range */
+
+/* ------------------------- GL_SGIS_detail_texture ------------------------ */
+
+#if !defined(GL_SGIS_detail_texture)
+#define GL_SGIS_detail_texture 1
+
+typedef void (GLAPIENTRY * PFNGLDETAILTEXFUNCSGISPROC) (GLenum target, GLsizei n, const GLfloat* points);
+typedef void (GLAPIENTRY * PFNGLGETDETAILTEXFUNCSGISPROC) (GLenum target, GLfloat* points);
+
+#define glDetailTexFuncSGIS GLEW_GET_FUN(__glewDetailTexFuncSGIS)
+#define glGetDetailTexFuncSGIS GLEW_GET_FUN(__glewGetDetailTexFuncSGIS)
+
+#define GLEW_SGIS_detail_texture GLEW_GET_VAR(__GLEW_SGIS_detail_texture)
+
+#endif /* !GL_SGIS_detail_texture */
+
+/* -------------------------- GL_SGIS_fog_function ------------------------- */
+
+#if !defined(GL_SGIS_fog_function)
+#define GL_SGIS_fog_function 1
+
+typedef void (GLAPIENTRY * PFNGLFOGFUNCSGISPROC) (GLsizei n, const GLfloat* points);
+typedef void (GLAPIENTRY * PFNGLGETFOGFUNCSGISPROC) (GLfloat* points);
+
+#define glFogFuncSGIS GLEW_GET_FUN(__glewFogFuncSGIS)
+#define glGetFogFuncSGIS GLEW_GET_FUN(__glewGetFogFuncSGIS)
+
+#define GLEW_SGIS_fog_function GLEW_GET_VAR(__GLEW_SGIS_fog_function)
+
+#endif /* !GL_SGIS_fog_function */
+
+/* ------------------------ GL_SGIS_generate_mipmap ------------------------ */
+
+#if !defined(GL_SGIS_generate_mipmap)
+#define GL_SGIS_generate_mipmap 1
+
+#define GL_GENERATE_MIPMAP_SGIS 0x8191
+#define GL_GENERATE_MIPMAP_HINT_SGIS 0x8192
+
+#define GLEW_SGIS_generate_mipmap GLEW_GET_VAR(__GLEW_SGIS_generate_mipmap)
+
+#endif /* !GL_SGIS_generate_mipmap */
+
+/* -------------------------- GL_SGIS_multisample -------------------------- */
+
+#if !defined(GL_SGIS_multisample)
+#define GL_SGIS_multisample 1
+
+#define GL_MULTISAMPLE_SGIS 0x809D
+#define GL_SAMPLE_ALPHA_TO_MASK_SGIS 0x809E
+#define GL_SAMPLE_ALPHA_TO_ONE_SGIS 0x809F
+#define GL_SAMPLE_MASK_SGIS 0x80A0
+#define GL_1PASS_SGIS 0x80A1
+#define GL_2PASS_0_SGIS 0x80A2
+#define GL_2PASS_1_SGIS 0x80A3
+#define GL_4PASS_0_SGIS 0x80A4
+#define GL_4PASS_1_SGIS 0x80A5
+#define GL_4PASS_2_SGIS 0x80A6
+#define GL_4PASS_3_SGIS 0x80A7
+#define GL_SAMPLE_BUFFERS_SGIS 0x80A8
+#define GL_SAMPLES_SGIS 0x80A9
+#define GL_SAMPLE_MASK_VALUE_SGIS 0x80AA
+#define GL_SAMPLE_MASK_INVERT_SGIS 0x80AB
+#define GL_SAMPLE_PATTERN_SGIS 0x80AC
+#define GL_MULTISAMPLE_BIT_EXT 0x20000000
+
+typedef void (GLAPIENTRY * PFNGLSAMPLEMASKSGISPROC) (GLclampf value, GLboolean invert);
+typedef void (GLAPIENTRY * PFNGLSAMPLEPATTERNSGISPROC) (GLenum pattern);
+
+#define glSampleMaskSGIS GLEW_GET_FUN(__glewSampleMaskSGIS)
+#define glSamplePatternSGIS GLEW_GET_FUN(__glewSamplePatternSGIS)
+
+#define GLEW_SGIS_multisample GLEW_GET_VAR(__GLEW_SGIS_multisample)
+
+#endif /* !GL_SGIS_multisample */
+
+/* ------------------------- GL_SGIS_pixel_texture ------------------------- */
+
+#if !defined(GL_SGIS_pixel_texture)
+#define GL_SGIS_pixel_texture 1
+
+#define GLEW_SGIS_pixel_texture GLEW_GET_VAR(__GLEW_SGIS_pixel_texture)
+
+#endif /* !GL_SGIS_pixel_texture */
+
+/* ----------------------- GL_SGIS_point_line_texgen ----------------------- */
+
+#if !defined(GL_SGIS_point_line_texgen)
+#define GL_SGIS_point_line_texgen 1
+
+#define GL_EYE_DISTANCE_TO_POINT_SGIS 0x81F0
+#define GL_OBJECT_DISTANCE_TO_POINT_SGIS 0x81F1
+#define GL_EYE_DISTANCE_TO_LINE_SGIS 0x81F2
+#define GL_OBJECT_DISTANCE_TO_LINE_SGIS 0x81F3
+#define GL_EYE_POINT_SGIS 0x81F4
+#define GL_OBJECT_POINT_SGIS 0x81F5
+#define GL_EYE_LINE_SGIS 0x81F6
+#define GL_OBJECT_LINE_SGIS 0x81F7
+
+#define GLEW_SGIS_point_line_texgen GLEW_GET_VAR(__GLEW_SGIS_point_line_texgen)
+
+#endif /* !GL_SGIS_point_line_texgen */
+
+/* ------------------------ GL_SGIS_sharpen_texture ------------------------ */
+
+#if !defined(GL_SGIS_sharpen_texture)
+#define GL_SGIS_sharpen_texture 1
+
+typedef void (GLAPIENTRY * PFNGLGETSHARPENTEXFUNCSGISPROC) (GLenum target, GLfloat* points);
+typedef void (GLAPIENTRY * PFNGLSHARPENTEXFUNCSGISPROC) (GLenum target, GLsizei n, const GLfloat* points);
+
+#define glGetSharpenTexFuncSGIS GLEW_GET_FUN(__glewGetSharpenTexFuncSGIS)
+#define glSharpenTexFuncSGIS GLEW_GET_FUN(__glewSharpenTexFuncSGIS)
+
+#define GLEW_SGIS_sharpen_texture GLEW_GET_VAR(__GLEW_SGIS_sharpen_texture)
+
+#endif /* !GL_SGIS_sharpen_texture */
+
+/* --------------------------- GL_SGIS_texture4D --------------------------- */
+
+#if !defined(GL_SGIS_texture4D)
+#define GL_SGIS_texture4D 1
+
+typedef void (GLAPIENTRY * PFNGLTEXIMAGE4DSGISPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLsizei extent, GLint border, GLenum format, GLenum type, const void* pixels);
+typedef void (GLAPIENTRY * PFNGLTEXSUBIMAGE4DSGISPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint woffset, GLsizei width, GLsizei height, GLsizei depth, GLsizei extent, GLenum format, GLenum type, const void* pixels);
+
+#define glTexImage4DSGIS GLEW_GET_FUN(__glewTexImage4DSGIS)
+#define glTexSubImage4DSGIS GLEW_GET_FUN(__glewTexSubImage4DSGIS)
+
+#define GLEW_SGIS_texture4D GLEW_GET_VAR(__GLEW_SGIS_texture4D)
+
+#endif /* !GL_SGIS_texture4D */
+
+/* ---------------------- GL_SGIS_texture_border_clamp --------------------- */
+
+#if !defined(GL_SGIS_texture_border_clamp)
+#define GL_SGIS_texture_border_clamp 1
+
+#define GL_CLAMP_TO_BORDER_SGIS 0x812D
+
+#define GLEW_SGIS_texture_border_clamp GLEW_GET_VAR(__GLEW_SGIS_texture_border_clamp)
+
+#endif /* !GL_SGIS_texture_border_clamp */
+
+/* ----------------------- GL_SGIS_texture_edge_clamp ---------------------- */
+
+#if !defined(GL_SGIS_texture_edge_clamp)
+#define GL_SGIS_texture_edge_clamp 1
+
+#define GL_CLAMP_TO_EDGE_SGIS 0x812F
+
+#define GLEW_SGIS_texture_edge_clamp GLEW_GET_VAR(__GLEW_SGIS_texture_edge_clamp)
+
+#endif /* !GL_SGIS_texture_edge_clamp */
+
+/* ------------------------ GL_SGIS_texture_filter4 ------------------------ */
+
+#if !defined(GL_SGIS_texture_filter4)
+#define GL_SGIS_texture_filter4 1
+
+typedef void (GLAPIENTRY * PFNGLGETTEXFILTERFUNCSGISPROC) (GLenum target, GLenum filter, GLfloat* weights);
+typedef void (GLAPIENTRY * PFNGLTEXFILTERFUNCSGISPROC) (GLenum target, GLenum filter, GLsizei n, const GLfloat* weights);
+
+#define glGetTexFilterFuncSGIS GLEW_GET_FUN(__glewGetTexFilterFuncSGIS)
+#define glTexFilterFuncSGIS GLEW_GET_FUN(__glewTexFilterFuncSGIS)
+
+#define GLEW_SGIS_texture_filter4 GLEW_GET_VAR(__GLEW_SGIS_texture_filter4)
+
+#endif /* !GL_SGIS_texture_filter4 */
+
+/* -------------------------- GL_SGIS_texture_lod -------------------------- */
+
+#if !defined(GL_SGIS_texture_lod)
+#define GL_SGIS_texture_lod 1
+
+#define GL_TEXTURE_MIN_LOD_SGIS 0x813A
+#define GL_TEXTURE_MAX_LOD_SGIS 0x813B
+#define GL_TEXTURE_BASE_LEVEL_SGIS 0x813C
+#define GL_TEXTURE_MAX_LEVEL_SGIS 0x813D
+
+#define GLEW_SGIS_texture_lod GLEW_GET_VAR(__GLEW_SGIS_texture_lod)
+
+#endif /* !GL_SGIS_texture_lod */
+
+/* ------------------------- GL_SGIS_texture_select ------------------------ */
+
+#if !defined(GL_SGIS_texture_select)
+#define GL_SGIS_texture_select 1
+
+#define GLEW_SGIS_texture_select GLEW_GET_VAR(__GLEW_SGIS_texture_select)
+
+#endif /* !GL_SGIS_texture_select */
+
+/* ----------------------------- GL_SGIX_async ----------------------------- */
+
+#if !defined(GL_SGIX_async)
+#define GL_SGIX_async 1
+
+#define GL_ASYNC_MARKER_SGIX 0x8329
+
+typedef void (GLAPIENTRY * PFNGLASYNCMARKERSGIXPROC) (GLuint marker);
+typedef void (GLAPIENTRY * PFNGLDELETEASYNCMARKERSSGIXPROC) (GLuint marker, GLsizei range);
+typedef GLint (GLAPIENTRY * PFNGLFINISHASYNCSGIXPROC) (GLuint* markerp);
+typedef GLuint (GLAPIENTRY * PFNGLGENASYNCMARKERSSGIXPROC) (GLsizei range);
+typedef GLboolean (GLAPIENTRY * PFNGLISASYNCMARKERSGIXPROC) (GLuint marker);
+typedef GLint (GLAPIENTRY * PFNGLPOLLASYNCSGIXPROC) (GLuint* markerp);
+
+#define glAsyncMarkerSGIX GLEW_GET_FUN(__glewAsyncMarkerSGIX)
+#define glDeleteAsyncMarkersSGIX GLEW_GET_FUN(__glewDeleteAsyncMarkersSGIX)
+#define glFinishAsyncSGIX GLEW_GET_FUN(__glewFinishAsyncSGIX)
+#define glGenAsyncMarkersSGIX GLEW_GET_FUN(__glewGenAsyncMarkersSGIX)
+#define glIsAsyncMarkerSGIX GLEW_GET_FUN(__glewIsAsyncMarkerSGIX)
+#define glPollAsyncSGIX GLEW_GET_FUN(__glewPollAsyncSGIX)
+
+#define GLEW_SGIX_async GLEW_GET_VAR(__GLEW_SGIX_async)
+
+#endif /* !GL_SGIX_async */
+
+/* ------------------------ GL_SGIX_async_histogram ------------------------ */
+
+#if !defined(GL_SGIX_async_histogram)
+#define GL_SGIX_async_histogram 1
+
+#define GL_ASYNC_HISTOGRAM_SGIX 0x832C
+#define GL_MAX_ASYNC_HISTOGRAM_SGIX 0x832D
+
+#define GLEW_SGIX_async_histogram GLEW_GET_VAR(__GLEW_SGIX_async_histogram)
+
+#endif /* !GL_SGIX_async_histogram */
+
+/* -------------------------- GL_SGIX_async_pixel -------------------------- */
+
+#if !defined(GL_SGIX_async_pixel)
+#define GL_SGIX_async_pixel 1
+
+#define GL_ASYNC_TEX_IMAGE_SGIX 0x835C
+#define GL_ASYNC_DRAW_PIXELS_SGIX 0x835D
+#define GL_ASYNC_READ_PIXELS_SGIX 0x835E
+#define GL_MAX_ASYNC_TEX_IMAGE_SGIX 0x835F
+#define GL_MAX_ASYNC_DRAW_PIXELS_SGIX 0x8360
+#define GL_MAX_ASYNC_READ_PIXELS_SGIX 0x8361
+
+#define GLEW_SGIX_async_pixel GLEW_GET_VAR(__GLEW_SGIX_async_pixel)
+
+#endif /* !GL_SGIX_async_pixel */
+
+/* ----------------------- GL_SGIX_blend_alpha_minmax ---------------------- */
+
+#if !defined(GL_SGIX_blend_alpha_minmax)
+#define GL_SGIX_blend_alpha_minmax 1
+
+#define GL_ALPHA_MIN_SGIX 0x8320
+#define GL_ALPHA_MAX_SGIX 0x8321
+
+#define GLEW_SGIX_blend_alpha_minmax GLEW_GET_VAR(__GLEW_SGIX_blend_alpha_minmax)
+
+#endif /* !GL_SGIX_blend_alpha_minmax */
+
+/* ---------------------------- GL_SGIX_clipmap ---------------------------- */
+
+#if !defined(GL_SGIX_clipmap)
+#define GL_SGIX_clipmap 1
+
+#define GLEW_SGIX_clipmap GLEW_GET_VAR(__GLEW_SGIX_clipmap)
+
+#endif /* !GL_SGIX_clipmap */
+
+/* ---------------------- GL_SGIX_convolution_accuracy --------------------- */
+
+#if !defined(GL_SGIX_convolution_accuracy)
+#define GL_SGIX_convolution_accuracy 1
+
+#define GL_CONVOLUTION_HINT_SGIX 0x8316
+
+#define GLEW_SGIX_convolution_accuracy GLEW_GET_VAR(__GLEW_SGIX_convolution_accuracy)
+
+#endif /* !GL_SGIX_convolution_accuracy */
+
+/* ------------------------- GL_SGIX_depth_texture ------------------------- */
+
+#if !defined(GL_SGIX_depth_texture)
+#define GL_SGIX_depth_texture 1
+
+#define GL_DEPTH_COMPONENT16_SGIX 0x81A5
+#define GL_DEPTH_COMPONENT24_SGIX 0x81A6
+#define GL_DEPTH_COMPONENT32_SGIX 0x81A7
+
+#define GLEW_SGIX_depth_texture GLEW_GET_VAR(__GLEW_SGIX_depth_texture)
+
+#endif /* !GL_SGIX_depth_texture */
+
+/* -------------------------- GL_SGIX_flush_raster ------------------------- */
+
+#if !defined(GL_SGIX_flush_raster)
+#define GL_SGIX_flush_raster 1
+
+typedef void (GLAPIENTRY * PFNGLFLUSHRASTERSGIXPROC) (void);
+
+#define glFlushRasterSGIX GLEW_GET_FUN(__glewFlushRasterSGIX)
+
+#define GLEW_SGIX_flush_raster GLEW_GET_VAR(__GLEW_SGIX_flush_raster)
+
+#endif /* !GL_SGIX_flush_raster */
+
+/* --------------------------- GL_SGIX_fog_offset -------------------------- */
+
+#if !defined(GL_SGIX_fog_offset)
+#define GL_SGIX_fog_offset 1
+
+#define GL_FOG_OFFSET_SGIX 0x8198
+#define GL_FOG_OFFSET_VALUE_SGIX 0x8199
+
+#define GLEW_SGIX_fog_offset GLEW_GET_VAR(__GLEW_SGIX_fog_offset)
+
+#endif /* !GL_SGIX_fog_offset */
+
+/* -------------------------- GL_SGIX_fog_texture -------------------------- */
+
+#if !defined(GL_SGIX_fog_texture)
+#define GL_SGIX_fog_texture 1
+
+#define GL_TEXTURE_FOG_SGIX 0
+#define GL_FOG_PATCHY_FACTOR_SGIX 0
+#define GL_FRAGMENT_FOG_SGIX 0
+
+typedef void (GLAPIENTRY * PFNGLTEXTUREFOGSGIXPROC) (GLenum pname);
+
+#define glTextureFogSGIX GLEW_GET_FUN(__glewTextureFogSGIX)
+
+#define GLEW_SGIX_fog_texture GLEW_GET_VAR(__GLEW_SGIX_fog_texture)
+
+#endif /* !GL_SGIX_fog_texture */
+
+/* ------------------- GL_SGIX_fragment_specular_lighting ------------------ */
+
+#if !defined(GL_SGIX_fragment_specular_lighting)
+#define GL_SGIX_fragment_specular_lighting 1
+
+typedef void (GLAPIENTRY * PFNGLFRAGMENTCOLORMATERIALSGIXPROC) (GLenum face, GLenum mode);
+typedef void (GLAPIENTRY * PFNGLFRAGMENTLIGHTMODELFSGIXPROC) (GLenum pname, GLfloat param);
+typedef void (GLAPIENTRY * PFNGLFRAGMENTLIGHTMODELFVSGIXPROC) (GLenum pname, GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLFRAGMENTLIGHTMODELISGIXPROC) (GLenum pname, GLint param);
+typedef void (GLAPIENTRY * PFNGLFRAGMENTLIGHTMODELIVSGIXPROC) (GLenum pname, GLint* params);
+typedef void (GLAPIENTRY * PFNGLFRAGMENTLIGHTFSGIXPROC) (GLenum light, GLenum pname, GLfloat param);
+typedef void (GLAPIENTRY * PFNGLFRAGMENTLIGHTFVSGIXPROC) (GLenum light, GLenum pname, GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLFRAGMENTLIGHTISGIXPROC) (GLenum light, GLenum pname, GLint param);
+typedef void (GLAPIENTRY * PFNGLFRAGMENTLIGHTIVSGIXPROC) (GLenum light, GLenum pname, GLint* params);
+typedef void (GLAPIENTRY * PFNGLFRAGMENTMATERIALFSGIXPROC) (GLenum face, GLenum pname, const GLfloat param);
+typedef void (GLAPIENTRY * PFNGLFRAGMENTMATERIALFVSGIXPROC) (GLenum face, GLenum pname, const GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLFRAGMENTMATERIALISGIXPROC) (GLenum face, GLenum pname, const GLint param);
+typedef void (GLAPIENTRY * PFNGLFRAGMENTMATERIALIVSGIXPROC) (GLenum face, GLenum pname, const GLint* params);
+typedef void (GLAPIENTRY * PFNGLGETFRAGMENTLIGHTFVSGIXPROC) (GLenum light, GLenum value, GLfloat* data);
+typedef void (GLAPIENTRY * PFNGLGETFRAGMENTLIGHTIVSGIXPROC) (GLenum light, GLenum value, GLint* data);
+typedef void (GLAPIENTRY * PFNGLGETFRAGMENTMATERIALFVSGIXPROC) (GLenum face, GLenum pname, const GLfloat* data);
+typedef void (GLAPIENTRY * PFNGLGETFRAGMENTMATERIALIVSGIXPROC) (GLenum face, GLenum pname, const GLint* data);
+
+#define glFragmentColorMaterialSGIX GLEW_GET_FUN(__glewFragmentColorMaterialSGIX)
+#define glFragmentLightModelfSGIX GLEW_GET_FUN(__glewFragmentLightModelfSGIX)
+#define glFragmentLightModelfvSGIX GLEW_GET_FUN(__glewFragmentLightModelfvSGIX)
+#define glFragmentLightModeliSGIX GLEW_GET_FUN(__glewFragmentLightModeliSGIX)
+#define glFragmentLightModelivSGIX GLEW_GET_FUN(__glewFragmentLightModelivSGIX)
+#define glFragmentLightfSGIX GLEW_GET_FUN(__glewFragmentLightfSGIX)
+#define glFragmentLightfvSGIX GLEW_GET_FUN(__glewFragmentLightfvSGIX)
+#define glFragmentLightiSGIX GLEW_GET_FUN(__glewFragmentLightiSGIX)
+#define glFragmentLightivSGIX GLEW_GET_FUN(__glewFragmentLightivSGIX)
+#define glFragmentMaterialfSGIX GLEW_GET_FUN(__glewFragmentMaterialfSGIX)
+#define glFragmentMaterialfvSGIX GLEW_GET_FUN(__glewFragmentMaterialfvSGIX)
+#define glFragmentMaterialiSGIX GLEW_GET_FUN(__glewFragmentMaterialiSGIX)
+#define glFragmentMaterialivSGIX GLEW_GET_FUN(__glewFragmentMaterialivSGIX)
+#define glGetFragmentLightfvSGIX GLEW_GET_FUN(__glewGetFragmentLightfvSGIX)
+#define glGetFragmentLightivSGIX GLEW_GET_FUN(__glewGetFragmentLightivSGIX)
+#define glGetFragmentMaterialfvSGIX GLEW_GET_FUN(__glewGetFragmentMaterialfvSGIX)
+#define glGetFragmentMaterialivSGIX GLEW_GET_FUN(__glewGetFragmentMaterialivSGIX)
+
+#define GLEW_SGIX_fragment_specular_lighting GLEW_GET_VAR(__GLEW_SGIX_fragment_specular_lighting)
+
+#endif /* !GL_SGIX_fragment_specular_lighting */
+
+/* --------------------------- GL_SGIX_framezoom --------------------------- */
+
+#if !defined(GL_SGIX_framezoom)
+#define GL_SGIX_framezoom 1
+
+typedef void (GLAPIENTRY * PFNGLFRAMEZOOMSGIXPROC) (GLint factor);
+
+#define glFrameZoomSGIX GLEW_GET_FUN(__glewFrameZoomSGIX)
+
+#define GLEW_SGIX_framezoom GLEW_GET_VAR(__GLEW_SGIX_framezoom)
+
+#endif /* !GL_SGIX_framezoom */
+
+/* --------------------------- GL_SGIX_interlace --------------------------- */
+
+#if !defined(GL_SGIX_interlace)
+#define GL_SGIX_interlace 1
+
+#define GL_INTERLACE_SGIX 0x8094
+
+#define GLEW_SGIX_interlace GLEW_GET_VAR(__GLEW_SGIX_interlace)
+
+#endif /* !GL_SGIX_interlace */
+
+/* ------------------------- GL_SGIX_ir_instrument1 ------------------------ */
+
+#if !defined(GL_SGIX_ir_instrument1)
+#define GL_SGIX_ir_instrument1 1
+
+#define GLEW_SGIX_ir_instrument1 GLEW_GET_VAR(__GLEW_SGIX_ir_instrument1)
+
+#endif /* !GL_SGIX_ir_instrument1 */
+
+/* ------------------------- GL_SGIX_list_priority ------------------------- */
+
+#if !defined(GL_SGIX_list_priority)
+#define GL_SGIX_list_priority 1
+
+#define GLEW_SGIX_list_priority GLEW_GET_VAR(__GLEW_SGIX_list_priority)
+
+#endif /* !GL_SGIX_list_priority */
+
+/* ------------------------- GL_SGIX_pixel_texture ------------------------- */
+
+#if !defined(GL_SGIX_pixel_texture)
+#define GL_SGIX_pixel_texture 1
+
+typedef void (GLAPIENTRY * PFNGLPIXELTEXGENSGIXPROC) (GLenum mode);
+
+#define glPixelTexGenSGIX GLEW_GET_FUN(__glewPixelTexGenSGIX)
+
+#define GLEW_SGIX_pixel_texture GLEW_GET_VAR(__GLEW_SGIX_pixel_texture)
+
+#endif /* !GL_SGIX_pixel_texture */
+
+/* ----------------------- GL_SGIX_pixel_texture_bits ---------------------- */
+
+#if !defined(GL_SGIX_pixel_texture_bits)
+#define GL_SGIX_pixel_texture_bits 1
+
+#define GLEW_SGIX_pixel_texture_bits GLEW_GET_VAR(__GLEW_SGIX_pixel_texture_bits)
+
+#endif /* !GL_SGIX_pixel_texture_bits */
+
+/* ------------------------ GL_SGIX_reference_plane ------------------------ */
+
+#if !defined(GL_SGIX_reference_plane)
+#define GL_SGIX_reference_plane 1
+
+typedef void (GLAPIENTRY * PFNGLREFERENCEPLANESGIXPROC) (const GLdouble* equation);
+
+#define glReferencePlaneSGIX GLEW_GET_FUN(__glewReferencePlaneSGIX)
+
+#define GLEW_SGIX_reference_plane GLEW_GET_VAR(__GLEW_SGIX_reference_plane)
+
+#endif /* !GL_SGIX_reference_plane */
+
+/* ---------------------------- GL_SGIX_resample --------------------------- */
+
+#if !defined(GL_SGIX_resample)
+#define GL_SGIX_resample 1
+
+#define GL_PACK_RESAMPLE_SGIX 0x842E
+#define GL_UNPACK_RESAMPLE_SGIX 0x842F
+#define GL_RESAMPLE_DECIMATE_SGIX 0x8430
+#define GL_RESAMPLE_REPLICATE_SGIX 0x8433
+#define GL_RESAMPLE_ZERO_FILL_SGIX 0x8434
+
+#define GLEW_SGIX_resample GLEW_GET_VAR(__GLEW_SGIX_resample)
+
+#endif /* !GL_SGIX_resample */
+
+/* ----------------------------- GL_SGIX_shadow ---------------------------- */
+
+#if !defined(GL_SGIX_shadow)
+#define GL_SGIX_shadow 1
+
+#define GL_TEXTURE_COMPARE_SGIX 0x819A
+#define GL_TEXTURE_COMPARE_OPERATOR_SGIX 0x819B
+#define GL_TEXTURE_LEQUAL_R_SGIX 0x819C
+#define GL_TEXTURE_GEQUAL_R_SGIX 0x819D
+
+#define GLEW_SGIX_shadow GLEW_GET_VAR(__GLEW_SGIX_shadow)
+
+#endif /* !GL_SGIX_shadow */
+
+/* ------------------------- GL_SGIX_shadow_ambient ------------------------ */
+
+#if !defined(GL_SGIX_shadow_ambient)
+#define GL_SGIX_shadow_ambient 1
+
+#define GL_SHADOW_AMBIENT_SGIX 0x80BF
+
+#define GLEW_SGIX_shadow_ambient GLEW_GET_VAR(__GLEW_SGIX_shadow_ambient)
+
+#endif /* !GL_SGIX_shadow_ambient */
+
+/* ----------------------------- GL_SGIX_sprite ---------------------------- */
+
+#if !defined(GL_SGIX_sprite)
+#define GL_SGIX_sprite 1
+
+typedef void (GLAPIENTRY * PFNGLSPRITEPARAMETERFSGIXPROC) (GLenum pname, GLfloat param);
+typedef void (GLAPIENTRY * PFNGLSPRITEPARAMETERFVSGIXPROC) (GLenum pname, GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLSPRITEPARAMETERISGIXPROC) (GLenum pname, GLint param);
+typedef void (GLAPIENTRY * PFNGLSPRITEPARAMETERIVSGIXPROC) (GLenum pname, GLint* params);
+
+#define glSpriteParameterfSGIX GLEW_GET_FUN(__glewSpriteParameterfSGIX)
+#define glSpriteParameterfvSGIX GLEW_GET_FUN(__glewSpriteParameterfvSGIX)
+#define glSpriteParameteriSGIX GLEW_GET_FUN(__glewSpriteParameteriSGIX)
+#define glSpriteParameterivSGIX GLEW_GET_FUN(__glewSpriteParameterivSGIX)
+
+#define GLEW_SGIX_sprite GLEW_GET_VAR(__GLEW_SGIX_sprite)
+
+#endif /* !GL_SGIX_sprite */
+
+/* ----------------------- GL_SGIX_tag_sample_buffer ----------------------- */
+
+#if !defined(GL_SGIX_tag_sample_buffer)
+#define GL_SGIX_tag_sample_buffer 1
+
+typedef void (GLAPIENTRY * PFNGLTAGSAMPLEBUFFERSGIXPROC) (void);
+
+#define glTagSampleBufferSGIX GLEW_GET_FUN(__glewTagSampleBufferSGIX)
+
+#define GLEW_SGIX_tag_sample_buffer GLEW_GET_VAR(__GLEW_SGIX_tag_sample_buffer)
+
+#endif /* !GL_SGIX_tag_sample_buffer */
+
+/* ------------------------ GL_SGIX_texture_add_env ------------------------ */
+
+#if !defined(GL_SGIX_texture_add_env)
+#define GL_SGIX_texture_add_env 1
+
+#define GLEW_SGIX_texture_add_env GLEW_GET_VAR(__GLEW_SGIX_texture_add_env)
+
+#endif /* !GL_SGIX_texture_add_env */
+
+/* -------------------- GL_SGIX_texture_coordinate_clamp ------------------- */
+
+#if !defined(GL_SGIX_texture_coordinate_clamp)
+#define GL_SGIX_texture_coordinate_clamp 1
+
+#define GL_TEXTURE_MAX_CLAMP_S_SGIX 0x8369
+#define GL_TEXTURE_MAX_CLAMP_T_SGIX 0x836A
+#define GL_TEXTURE_MAX_CLAMP_R_SGIX 0x836B
+
+#define GLEW_SGIX_texture_coordinate_clamp GLEW_GET_VAR(__GLEW_SGIX_texture_coordinate_clamp)
+
+#endif /* !GL_SGIX_texture_coordinate_clamp */
+
+/* ------------------------ GL_SGIX_texture_lod_bias ----------------------- */
+
+#if !defined(GL_SGIX_texture_lod_bias)
+#define GL_SGIX_texture_lod_bias 1
+
+#define GLEW_SGIX_texture_lod_bias GLEW_GET_VAR(__GLEW_SGIX_texture_lod_bias)
+
+#endif /* !GL_SGIX_texture_lod_bias */
+
+/* ---------------------- GL_SGIX_texture_multi_buffer --------------------- */
+
+#if !defined(GL_SGIX_texture_multi_buffer)
+#define GL_SGIX_texture_multi_buffer 1
+
+#define GL_TEXTURE_MULTI_BUFFER_HINT_SGIX 0x812E
+
+#define GLEW_SGIX_texture_multi_buffer GLEW_GET_VAR(__GLEW_SGIX_texture_multi_buffer)
+
+#endif /* !GL_SGIX_texture_multi_buffer */
+
+/* ------------------------- GL_SGIX_texture_range ------------------------- */
+
+#if !defined(GL_SGIX_texture_range)
+#define GL_SGIX_texture_range 1
+
+#define GL_RGB_SIGNED_SGIX 0x85E0
+#define GL_RGBA_SIGNED_SGIX 0x85E1
+#define GL_ALPHA_SIGNED_SGIX 0x85E2
+#define GL_LUMINANCE_SIGNED_SGIX 0x85E3
+#define GL_INTENSITY_SIGNED_SGIX 0x85E4
+#define GL_LUMINANCE_ALPHA_SIGNED_SGIX 0x85E5
+#define GL_RGB16_SIGNED_SGIX 0x85E6
+#define GL_RGBA16_SIGNED_SGIX 0x85E7
+#define GL_ALPHA16_SIGNED_SGIX 0x85E8
+#define GL_LUMINANCE16_SIGNED_SGIX 0x85E9
+#define GL_INTENSITY16_SIGNED_SGIX 0x85EA
+#define GL_LUMINANCE16_ALPHA16_SIGNED_SGIX 0x85EB
+#define GL_RGB_EXTENDED_RANGE_SGIX 0x85EC
+#define GL_RGBA_EXTENDED_RANGE_SGIX 0x85ED
+#define GL_ALPHA_EXTENDED_RANGE_SGIX 0x85EE
+#define GL_LUMINANCE_EXTENDED_RANGE_SGIX 0x85EF
+#define GL_INTENSITY_EXTENDED_RANGE_SGIX 0x85F0
+#define GL_LUMINANCE_ALPHA_EXTENDED_RANGE_SGIX 0x85F1
+#define GL_RGB16_EXTENDED_RANGE_SGIX 0x85F2
+#define GL_RGBA16_EXTENDED_RANGE_SGIX 0x85F3
+#define GL_ALPHA16_EXTENDED_RANGE_SGIX 0x85F4
+#define GL_LUMINANCE16_EXTENDED_RANGE_SGIX 0x85F5
+#define GL_INTENSITY16_EXTENDED_RANGE_SGIX 0x85F6
+#define GL_LUMINANCE16_ALPHA16_EXTENDED_RANGE_SGIX 0x85F7
+#define GL_MIN_LUMINANCE_SGIS 0x85F8
+#define GL_MAX_LUMINANCE_SGIS 0x85F9
+#define GL_MIN_INTENSITY_SGIS 0x85FA
+#define GL_MAX_INTENSITY_SGIS 0x85FB
+
+#define GLEW_SGIX_texture_range GLEW_GET_VAR(__GLEW_SGIX_texture_range)
+
+#endif /* !GL_SGIX_texture_range */
+
+/* ----------------------- GL_SGIX_texture_scale_bias ---------------------- */
+
+#if !defined(GL_SGIX_texture_scale_bias)
+#define GL_SGIX_texture_scale_bias 1
+
+#define GL_POST_TEXTURE_FILTER_BIAS_SGIX 0x8179
+#define GL_POST_TEXTURE_FILTER_SCALE_SGIX 0x817A
+#define GL_POST_TEXTURE_FILTER_BIAS_RANGE_SGIX 0x817B
+#define GL_POST_TEXTURE_FILTER_SCALE_RANGE_SGIX 0x817C
+
+#define GLEW_SGIX_texture_scale_bias GLEW_GET_VAR(__GLEW_SGIX_texture_scale_bias)
+
+#endif /* !GL_SGIX_texture_scale_bias */
+
+/* ------------------------- GL_SGIX_vertex_preclip ------------------------ */
+
+#if !defined(GL_SGIX_vertex_preclip)
+#define GL_SGIX_vertex_preclip 1
+
+#define GL_VERTEX_PRECLIP_SGIX 0x83EE
+#define GL_VERTEX_PRECLIP_HINT_SGIX 0x83EF
+
+#define GLEW_SGIX_vertex_preclip GLEW_GET_VAR(__GLEW_SGIX_vertex_preclip)
+
+#endif /* !GL_SGIX_vertex_preclip */
+
+/* ---------------------- GL_SGIX_vertex_preclip_hint ---------------------- */
+
+#if !defined(GL_SGIX_vertex_preclip_hint)
+#define GL_SGIX_vertex_preclip_hint 1
+
+#define GL_VERTEX_PRECLIP_SGIX 0x83EE
+#define GL_VERTEX_PRECLIP_HINT_SGIX 0x83EF
+
+#define GLEW_SGIX_vertex_preclip_hint GLEW_GET_VAR(__GLEW_SGIX_vertex_preclip_hint)
+
+#endif /* !GL_SGIX_vertex_preclip_hint */
+
+/* ----------------------------- GL_SGIX_ycrcb ----------------------------- */
+
+#if !defined(GL_SGIX_ycrcb)
+#define GL_SGIX_ycrcb 1
+
+#define GLEW_SGIX_ycrcb GLEW_GET_VAR(__GLEW_SGIX_ycrcb)
+
+#endif /* !GL_SGIX_ycrcb */
+
+/* -------------------------- GL_SGI_color_matrix -------------------------- */
+
+#if !defined(GL_SGI_color_matrix)
+#define GL_SGI_color_matrix 1
+
+#define GL_COLOR_MATRIX_SGI 0x80B1
+#define GL_COLOR_MATRIX_STACK_DEPTH_SGI 0x80B2
+#define GL_MAX_COLOR_MATRIX_STACK_DEPTH_SGI 0x80B3
+#define GL_POST_COLOR_MATRIX_RED_SCALE_SGI 0x80B4
+#define GL_POST_COLOR_MATRIX_GREEN_SCALE_SGI 0x80B5
+#define GL_POST_COLOR_MATRIX_BLUE_SCALE_SGI 0x80B6
+#define GL_POST_COLOR_MATRIX_ALPHA_SCALE_SGI 0x80B7
+#define GL_POST_COLOR_MATRIX_RED_BIAS_SGI 0x80B8
+#define GL_POST_COLOR_MATRIX_GREEN_BIAS_SGI 0x80B9
+#define GL_POST_COLOR_MATRIX_BLUE_BIAS_SGI 0x80BA
+#define GL_POST_COLOR_MATRIX_ALPHA_BIAS_SGI 0x80BB
+
+#define GLEW_SGI_color_matrix GLEW_GET_VAR(__GLEW_SGI_color_matrix)
+
+#endif /* !GL_SGI_color_matrix */
+
+/* --------------------------- GL_SGI_color_table -------------------------- */
+
+#if !defined(GL_SGI_color_table)
+#define GL_SGI_color_table 1
+
+#define GL_COLOR_TABLE_SGI 0x80D0
+#define GL_POST_CONVOLUTION_COLOR_TABLE_SGI 0x80D1
+#define GL_POST_COLOR_MATRIX_COLOR_TABLE_SGI 0x80D2
+#define GL_PROXY_COLOR_TABLE_SGI 0x80D3
+#define GL_PROXY_POST_CONVOLUTION_COLOR_TABLE_SGI 0x80D4
+#define GL_PROXY_POST_COLOR_MATRIX_COLOR_TABLE_SGI 0x80D5
+#define GL_COLOR_TABLE_SCALE_SGI 0x80D6
+#define GL_COLOR_TABLE_BIAS_SGI 0x80D7
+#define GL_COLOR_TABLE_FORMAT_SGI 0x80D8
+#define GL_COLOR_TABLE_WIDTH_SGI 0x80D9
+#define GL_COLOR_TABLE_RED_SIZE_SGI 0x80DA
+#define GL_COLOR_TABLE_GREEN_SIZE_SGI 0x80DB
+#define GL_COLOR_TABLE_BLUE_SIZE_SGI 0x80DC
+#define GL_COLOR_TABLE_ALPHA_SIZE_SGI 0x80DD
+#define GL_COLOR_TABLE_LUMINANCE_SIZE_SGI 0x80DE
+#define GL_COLOR_TABLE_INTENSITY_SIZE_SGI 0x80DF
+
+typedef void (GLAPIENTRY * PFNGLCOLORTABLEPARAMETERFVSGIPROC) (GLenum target, GLenum pname, const GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLCOLORTABLEPARAMETERIVSGIPROC) (GLenum target, GLenum pname, const GLint* params);
+typedef void (GLAPIENTRY * PFNGLCOLORTABLESGIPROC) (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const void* table);
+typedef void (GLAPIENTRY * PFNGLCOPYCOLORTABLESGIPROC) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width);
+typedef void (GLAPIENTRY * PFNGLGETCOLORTABLEPARAMETERFVSGIPROC) (GLenum target, GLenum pname, GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLGETCOLORTABLEPARAMETERIVSGIPROC) (GLenum target, GLenum pname, GLint* params);
+typedef void (GLAPIENTRY * PFNGLGETCOLORTABLESGIPROC) (GLenum target, GLenum format, GLenum type, void* table);
+
+#define glColorTableParameterfvSGI GLEW_GET_FUN(__glewColorTableParameterfvSGI)
+#define glColorTableParameterivSGI GLEW_GET_FUN(__glewColorTableParameterivSGI)
+#define glColorTableSGI GLEW_GET_FUN(__glewColorTableSGI)
+#define glCopyColorTableSGI GLEW_GET_FUN(__glewCopyColorTableSGI)
+#define glGetColorTableParameterfvSGI GLEW_GET_FUN(__glewGetColorTableParameterfvSGI)
+#define glGetColorTableParameterivSGI GLEW_GET_FUN(__glewGetColorTableParameterivSGI)
+#define glGetColorTableSGI GLEW_GET_FUN(__glewGetColorTableSGI)
+
+#define GLEW_SGI_color_table GLEW_GET_VAR(__GLEW_SGI_color_table)
+
+#endif /* !GL_SGI_color_table */
+
+/* ----------------------- GL_SGI_texture_color_table ---------------------- */
+
+#if !defined(GL_SGI_texture_color_table)
+#define GL_SGI_texture_color_table 1
+
+#define GL_TEXTURE_COLOR_TABLE_SGI 0x80BC
+#define GL_PROXY_TEXTURE_COLOR_TABLE_SGI 0x80BD
+
+#define GLEW_SGI_texture_color_table GLEW_GET_VAR(__GLEW_SGI_texture_color_table)
+
+#endif /* !GL_SGI_texture_color_table */
+
+/* ------------------------- GL_SUNX_constant_data ------------------------- */
+
+#if !defined(GL_SUNX_constant_data)
+#define GL_SUNX_constant_data 1
+
+#define GL_UNPACK_CONSTANT_DATA_SUNX 0x81D5
+#define GL_TEXTURE_CONSTANT_DATA_SUNX 0x81D6
+
+typedef void (GLAPIENTRY * PFNGLFINISHTEXTURESUNXPROC) (void);
+
+#define glFinishTextureSUNX GLEW_GET_FUN(__glewFinishTextureSUNX)
+
+#define GLEW_SUNX_constant_data GLEW_GET_VAR(__GLEW_SUNX_constant_data)
+
+#endif /* !GL_SUNX_constant_data */
+
+/* -------------------- GL_SUN_convolution_border_modes -------------------- */
+
+#if !defined(GL_SUN_convolution_border_modes)
+#define GL_SUN_convolution_border_modes 1
+
+#define GL_WRAP_BORDER_SUN 0x81D4
+
+#define GLEW_SUN_convolution_border_modes GLEW_GET_VAR(__GLEW_SUN_convolution_border_modes)
+
+#endif /* !GL_SUN_convolution_border_modes */
+
+/* -------------------------- GL_SUN_global_alpha -------------------------- */
+
+#if !defined(GL_SUN_global_alpha)
+#define GL_SUN_global_alpha 1
+
+#define GL_GLOBAL_ALPHA_SUN 0x81D9
+#define GL_GLOBAL_ALPHA_FACTOR_SUN 0x81DA
+
+typedef void (GLAPIENTRY * PFNGLGLOBALALPHAFACTORBSUNPROC) (GLbyte factor);
+typedef void (GLAPIENTRY * PFNGLGLOBALALPHAFACTORDSUNPROC) (GLdouble factor);
+typedef void (GLAPIENTRY * PFNGLGLOBALALPHAFACTORFSUNPROC) (GLfloat factor);
+typedef void (GLAPIENTRY * PFNGLGLOBALALPHAFACTORISUNPROC) (GLint factor);
+typedef void (GLAPIENTRY * PFNGLGLOBALALPHAFACTORSSUNPROC) (GLshort factor);
+typedef void (GLAPIENTRY * PFNGLGLOBALALPHAFACTORUBSUNPROC) (GLubyte factor);
+typedef void (GLAPIENTRY * PFNGLGLOBALALPHAFACTORUISUNPROC) (GLuint factor);
+typedef void (GLAPIENTRY * PFNGLGLOBALALPHAFACTORUSSUNPROC) (GLushort factor);
+
+#define glGlobalAlphaFactorbSUN GLEW_GET_FUN(__glewGlobalAlphaFactorbSUN)
+#define glGlobalAlphaFactordSUN GLEW_GET_FUN(__glewGlobalAlphaFactordSUN)
+#define glGlobalAlphaFactorfSUN GLEW_GET_FUN(__glewGlobalAlphaFactorfSUN)
+#define glGlobalAlphaFactoriSUN GLEW_GET_FUN(__glewGlobalAlphaFactoriSUN)
+#define glGlobalAlphaFactorsSUN GLEW_GET_FUN(__glewGlobalAlphaFactorsSUN)
+#define glGlobalAlphaFactorubSUN GLEW_GET_FUN(__glewGlobalAlphaFactorubSUN)
+#define glGlobalAlphaFactoruiSUN GLEW_GET_FUN(__glewGlobalAlphaFactoruiSUN)
+#define glGlobalAlphaFactorusSUN GLEW_GET_FUN(__glewGlobalAlphaFactorusSUN)
+
+#define GLEW_SUN_global_alpha GLEW_GET_VAR(__GLEW_SUN_global_alpha)
+
+#endif /* !GL_SUN_global_alpha */
+
+/* --------------------------- GL_SUN_mesh_array --------------------------- */
+
+#if !defined(GL_SUN_mesh_array)
+#define GL_SUN_mesh_array 1
+
+#define GL_QUAD_MESH_SUN 0x8614
+#define GL_TRIANGLE_MESH_SUN 0x8615
+
+#define GLEW_SUN_mesh_array GLEW_GET_VAR(__GLEW_SUN_mesh_array)
+
+#endif /* !GL_SUN_mesh_array */
+
+/* ------------------------ GL_SUN_read_video_pixels ----------------------- */
+
+#if !defined(GL_SUN_read_video_pixels)
+#define GL_SUN_read_video_pixels 1
+
+typedef void (GLAPIENTRY * PFNGLREADVIDEOPIXELSSUNPROC) (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid* pixels);
+
+#define glReadVideoPixelsSUN GLEW_GET_FUN(__glewReadVideoPixelsSUN)
+
+#define GLEW_SUN_read_video_pixels GLEW_GET_VAR(__GLEW_SUN_read_video_pixels)
+
+#endif /* !GL_SUN_read_video_pixels */
+
+/* --------------------------- GL_SUN_slice_accum -------------------------- */
+
+#if !defined(GL_SUN_slice_accum)
+#define GL_SUN_slice_accum 1
+
+#define GL_SLICE_ACCUM_SUN 0x85CC
+
+#define GLEW_SUN_slice_accum GLEW_GET_VAR(__GLEW_SUN_slice_accum)
+
+#endif /* !GL_SUN_slice_accum */
+
+/* -------------------------- GL_SUN_triangle_list ------------------------- */
+
+#if !defined(GL_SUN_triangle_list)
+#define GL_SUN_triangle_list 1
+
+#define GL_RESTART_SUN 0x01
+#define GL_REPLACE_MIDDLE_SUN 0x02
+#define GL_REPLACE_OLDEST_SUN 0x03
+#define GL_TRIANGLE_LIST_SUN 0x81D7
+#define GL_REPLACEMENT_CODE_SUN 0x81D8
+#define GL_REPLACEMENT_CODE_ARRAY_SUN 0x85C0
+#define GL_REPLACEMENT_CODE_ARRAY_TYPE_SUN 0x85C1
+#define GL_REPLACEMENT_CODE_ARRAY_STRIDE_SUN 0x85C2
+#define GL_REPLACEMENT_CODE_ARRAY_POINTER_SUN 0x85C3
+#define GL_R1UI_V3F_SUN 0x85C4
+#define GL_R1UI_C4UB_V3F_SUN 0x85C5
+#define GL_R1UI_C3F_V3F_SUN 0x85C6
+#define GL_R1UI_N3F_V3F_SUN 0x85C7
+#define GL_R1UI_C4F_N3F_V3F_SUN 0x85C8
+#define GL_R1UI_T2F_V3F_SUN 0x85C9
+#define GL_R1UI_T2F_N3F_V3F_SUN 0x85CA
+#define GL_R1UI_T2F_C4F_N3F_V3F_SUN 0x85CB
+
+typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEPOINTERSUNPROC) (GLenum type, GLsizei stride, const void* pointer);
+typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUBSUNPROC) (GLubyte code);
+typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUBVSUNPROC) (const GLubyte* code);
+typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUISUNPROC) (GLuint code);
+typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUIVSUNPROC) (const GLuint* code);
+typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUSSUNPROC) (GLushort code);
+typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUSVSUNPROC) (const GLushort* code);
+
+#define glReplacementCodePointerSUN GLEW_GET_FUN(__glewReplacementCodePointerSUN)
+#define glReplacementCodeubSUN GLEW_GET_FUN(__glewReplacementCodeubSUN)
+#define glReplacementCodeubvSUN GLEW_GET_FUN(__glewReplacementCodeubvSUN)
+#define glReplacementCodeuiSUN GLEW_GET_FUN(__glewReplacementCodeuiSUN)
+#define glReplacementCodeuivSUN GLEW_GET_FUN(__glewReplacementCodeuivSUN)
+#define glReplacementCodeusSUN GLEW_GET_FUN(__glewReplacementCodeusSUN)
+#define glReplacementCodeusvSUN GLEW_GET_FUN(__glewReplacementCodeusvSUN)
+
+#define GLEW_SUN_triangle_list GLEW_GET_VAR(__GLEW_SUN_triangle_list)
+
+#endif /* !GL_SUN_triangle_list */
+
+/* ----------------------------- GL_SUN_vertex ----------------------------- */
+
+#if !defined(GL_SUN_vertex)
+#define GL_SUN_vertex 1
+
+typedef void (GLAPIENTRY * PFNGLCOLOR3FVERTEX3FSUNPROC) (GLfloat r, GLfloat g, GLfloat b, GLfloat x, GLfloat y, GLfloat z);
+typedef void (GLAPIENTRY * PFNGLCOLOR3FVERTEX3FVSUNPROC) (const GLfloat* c, const GLfloat *v);
+typedef void (GLAPIENTRY * PFNGLCOLOR4FNORMAL3FVERTEX3FSUNPROC) (GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z);
+typedef void (GLAPIENTRY * PFNGLCOLOR4FNORMAL3FVERTEX3FVSUNPROC) (const GLfloat* c, const GLfloat *n, const GLfloat *v);
+typedef void (GLAPIENTRY * PFNGLCOLOR4UBVERTEX2FSUNPROC) (GLubyte r, GLubyte g, GLubyte b, GLubyte a, GLfloat x, GLfloat y);
+typedef void (GLAPIENTRY * PFNGLCOLOR4UBVERTEX2FVSUNPROC) (const GLubyte* c, const GLfloat *v);
+typedef void (GLAPIENTRY * PFNGLCOLOR4UBVERTEX3FSUNPROC) (GLubyte r, GLubyte g, GLubyte b, GLubyte a, GLfloat x, GLfloat y, GLfloat z);
+typedef void (GLAPIENTRY * PFNGLCOLOR4UBVERTEX3FVSUNPROC) (const GLubyte* c, const GLfloat *v);
+typedef void (GLAPIENTRY * PFNGLNORMAL3FVERTEX3FSUNPROC) (GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z);
+typedef void (GLAPIENTRY * PFNGLNORMAL3FVERTEX3FVSUNPROC) (const GLfloat* n, const GLfloat *v);
+typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUICOLOR3FVERTEX3FSUNPROC) (GLuint rc, GLfloat r, GLfloat g, GLfloat b, GLfloat x, GLfloat y, GLfloat z);
+typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUICOLOR3FVERTEX3FVSUNPROC) (const GLuint* rc, const GLfloat *c, const GLfloat *v);
+typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUICOLOR4FNORMAL3FVERTEX3FSUNPROC) (GLuint rc, GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z);
+typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUICOLOR4FNORMAL3FVERTEX3FVSUNPROC) (const GLuint* rc, const GLfloat *c, const GLfloat *n, const GLfloat *v);
+typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUICOLOR4UBVERTEX3FSUNPROC) (GLuint rc, GLubyte r, GLubyte g, GLubyte b, GLubyte a, GLfloat x, GLfloat y, GLfloat z);
+typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUICOLOR4UBVERTEX3FVSUNPROC) (const GLuint* rc, const GLubyte *c, const GLfloat *v);
+typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUINORMAL3FVERTEX3FSUNPROC) (GLuint rc, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z);
+typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUINORMAL3FVERTEX3FVSUNPROC) (const GLuint* rc, const GLfloat *n, const GLfloat *v);
+typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUITEXCOORD2FCOLOR4FNORMAL3FVERTEX3FSUNPROC) (GLuint rc, GLfloat s, GLfloat t, GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z);
+typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUITEXCOORD2FCOLOR4FNORMAL3FVERTEX3FVSUNPROC) (const GLuint* rc, const GLfloat *tc, const GLfloat *c, const GLfloat *n, const GLfloat *v);
+typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUITEXCOORD2FNORMAL3FVERTEX3FSUNPROC) (GLuint rc, GLfloat s, GLfloat t, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z);
+typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUITEXCOORD2FNORMAL3FVERTEX3FVSUNPROC) (const GLuint* rc, const GLfloat *tc, const GLfloat *n, const GLfloat *v);
+typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUITEXCOORD2FVERTEX3FSUNPROC) (GLuint rc, GLfloat s, GLfloat t, GLfloat x, GLfloat y, GLfloat z);
+typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUITEXCOORD2FVERTEX3FVSUNPROC) (const GLuint* rc, const GLfloat *tc, const GLfloat *v);
+typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUIVERTEX3FSUNPROC) (GLuint rc, GLfloat x, GLfloat y, GLfloat z);
+typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUIVERTEX3FVSUNPROC) (const GLuint* rc, const GLfloat *v);
+typedef void (GLAPIENTRY * PFNGLTEXCOORD2FCOLOR3FVERTEX3FSUNPROC) (GLfloat s, GLfloat t, GLfloat r, GLfloat g, GLfloat b, GLfloat x, GLfloat y, GLfloat z);
+typedef void (GLAPIENTRY * PFNGLTEXCOORD2FCOLOR3FVERTEX3FVSUNPROC) (const GLfloat* tc, const GLfloat *c, const GLfloat *v);
+typedef void (GLAPIENTRY * PFNGLTEXCOORD2FCOLOR4FNORMAL3FVERTEX3FSUNPROC) (GLfloat s, GLfloat t, GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z);
+typedef void (GLAPIENTRY * PFNGLTEXCOORD2FCOLOR4FNORMAL3FVERTEX3FVSUNPROC) (const GLfloat* tc, const GLfloat *c, const GLfloat *n, const GLfloat *v);
+typedef void (GLAPIENTRY * PFNGLTEXCOORD2FCOLOR4UBVERTEX3FSUNPROC) (GLfloat s, GLfloat t, GLubyte r, GLubyte g, GLubyte b, GLubyte a, GLfloat x, GLfloat y, GLfloat z);
+typedef void (GLAPIENTRY * PFNGLTEXCOORD2FCOLOR4UBVERTEX3FVSUNPROC) (const GLfloat* tc, const GLubyte *c, const GLfloat *v);
+typedef void (GLAPIENTRY * PFNGLTEXCOORD2FNORMAL3FVERTEX3FSUNPROC) (GLfloat s, GLfloat t, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z);
+typedef void (GLAPIENTRY * PFNGLTEXCOORD2FNORMAL3FVERTEX3FVSUNPROC) (const GLfloat* tc, const GLfloat *n, const GLfloat *v);
+typedef void (GLAPIENTRY * PFNGLTEXCOORD2FVERTEX3FSUNPROC) (GLfloat s, GLfloat t, GLfloat x, GLfloat y, GLfloat z);
+typedef void (GLAPIENTRY * PFNGLTEXCOORD2FVERTEX3FVSUNPROC) (const GLfloat* tc, const GLfloat *v);
+typedef void (GLAPIENTRY * PFNGLTEXCOORD4FCOLOR4FNORMAL3FVERTEX4FSUNPROC) (GLfloat s, GLfloat t, GLfloat p, GLfloat q, GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+typedef void (GLAPIENTRY * PFNGLTEXCOORD4FCOLOR4FNORMAL3FVERTEX4FVSUNPROC) (const GLfloat* tc, const GLfloat *c, const GLfloat *n, const GLfloat *v);
+typedef void (GLAPIENTRY * PFNGLTEXCOORD4FVERTEX4FSUNPROC) (GLfloat s, GLfloat t, GLfloat p, GLfloat q, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+typedef void (GLAPIENTRY * PFNGLTEXCOORD4FVERTEX4FVSUNPROC) (const GLfloat* tc, const GLfloat *v);
+
+#define glColor3fVertex3fSUN GLEW_GET_FUN(__glewColor3fVertex3fSUN)
+#define glColor3fVertex3fvSUN GLEW_GET_FUN(__glewColor3fVertex3fvSUN)
+#define glColor4fNormal3fVertex3fSUN GLEW_GET_FUN(__glewColor4fNormal3fVertex3fSUN)
+#define glColor4fNormal3fVertex3fvSUN GLEW_GET_FUN(__glewColor4fNormal3fVertex3fvSUN)
+#define glColor4ubVertex2fSUN GLEW_GET_FUN(__glewColor4ubVertex2fSUN)
+#define glColor4ubVertex2fvSUN GLEW_GET_FUN(__glewColor4ubVertex2fvSUN)
+#define glColor4ubVertex3fSUN GLEW_GET_FUN(__glewColor4ubVertex3fSUN)
+#define glColor4ubVertex3fvSUN GLEW_GET_FUN(__glewColor4ubVertex3fvSUN)
+#define glNormal3fVertex3fSUN GLEW_GET_FUN(__glewNormal3fVertex3fSUN)
+#define glNormal3fVertex3fvSUN GLEW_GET_FUN(__glewNormal3fVertex3fvSUN)
+#define glReplacementCodeuiColor3fVertex3fSUN GLEW_GET_FUN(__glewReplacementCodeuiColor3fVertex3fSUN)
+#define glReplacementCodeuiColor3fVertex3fvSUN GLEW_GET_FUN(__glewReplacementCodeuiColor3fVertex3fvSUN)
+#define glReplacementCodeuiColor4fNormal3fVertex3fSUN GLEW_GET_FUN(__glewReplacementCodeuiColor4fNormal3fVertex3fSUN)
+#define glReplacementCodeuiColor4fNormal3fVertex3fvSUN GLEW_GET_FUN(__glewReplacementCodeuiColor4fNormal3fVertex3fvSUN)
+#define glReplacementCodeuiColor4ubVertex3fSUN GLEW_GET_FUN(__glewReplacementCodeuiColor4ubVertex3fSUN)
+#define glReplacementCodeuiColor4ubVertex3fvSUN GLEW_GET_FUN(__glewReplacementCodeuiColor4ubVertex3fvSUN)
+#define glReplacementCodeuiNormal3fVertex3fSUN GLEW_GET_FUN(__glewReplacementCodeuiNormal3fVertex3fSUN)
+#define glReplacementCodeuiNormal3fVertex3fvSUN GLEW_GET_FUN(__glewReplacementCodeuiNormal3fVertex3fvSUN)
+#define glReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fSUN GLEW_GET_FUN(__glewReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fSUN)
+#define glReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fvSUN GLEW_GET_FUN(__glewReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fvSUN)
+#define glReplacementCodeuiTexCoord2fNormal3fVertex3fSUN GLEW_GET_FUN(__glewReplacementCodeuiTexCoord2fNormal3fVertex3fSUN)
+#define glReplacementCodeuiTexCoord2fNormal3fVertex3fvSUN GLEW_GET_FUN(__glewReplacementCodeuiTexCoord2fNormal3fVertex3fvSUN)
+#define glReplacementCodeuiTexCoord2fVertex3fSUN GLEW_GET_FUN(__glewReplacementCodeuiTexCoord2fVertex3fSUN)
+#define glReplacementCodeuiTexCoord2fVertex3fvSUN GLEW_GET_FUN(__glewReplacementCodeuiTexCoord2fVertex3fvSUN)
+#define glReplacementCodeuiVertex3fSUN GLEW_GET_FUN(__glewReplacementCodeuiVertex3fSUN)
+#define glReplacementCodeuiVertex3fvSUN GLEW_GET_FUN(__glewReplacementCodeuiVertex3fvSUN)
+#define glTexCoord2fColor3fVertex3fSUN GLEW_GET_FUN(__glewTexCoord2fColor3fVertex3fSUN)
+#define glTexCoord2fColor3fVertex3fvSUN GLEW_GET_FUN(__glewTexCoord2fColor3fVertex3fvSUN)
+#define glTexCoord2fColor4fNormal3fVertex3fSUN GLEW_GET_FUN(__glewTexCoord2fColor4fNormal3fVertex3fSUN)
+#define glTexCoord2fColor4fNormal3fVertex3fvSUN GLEW_GET_FUN(__glewTexCoord2fColor4fNormal3fVertex3fvSUN)
+#define glTexCoord2fColor4ubVertex3fSUN GLEW_GET_FUN(__glewTexCoord2fColor4ubVertex3fSUN)
+#define glTexCoord2fColor4ubVertex3fvSUN GLEW_GET_FUN(__glewTexCoord2fColor4ubVertex3fvSUN)
+#define glTexCoord2fNormal3fVertex3fSUN GLEW_GET_FUN(__glewTexCoord2fNormal3fVertex3fSUN)
+#define glTexCoord2fNormal3fVertex3fvSUN GLEW_GET_FUN(__glewTexCoord2fNormal3fVertex3fvSUN)
+#define glTexCoord2fVertex3fSUN GLEW_GET_FUN(__glewTexCoord2fVertex3fSUN)
+#define glTexCoord2fVertex3fvSUN GLEW_GET_FUN(__glewTexCoord2fVertex3fvSUN)
+#define glTexCoord4fColor4fNormal3fVertex4fSUN GLEW_GET_FUN(__glewTexCoord4fColor4fNormal3fVertex4fSUN)
+#define glTexCoord4fColor4fNormal3fVertex4fvSUN GLEW_GET_FUN(__glewTexCoord4fColor4fNormal3fVertex4fvSUN)
+#define glTexCoord4fVertex4fSUN GLEW_GET_FUN(__glewTexCoord4fVertex4fSUN)
+#define glTexCoord4fVertex4fvSUN GLEW_GET_FUN(__glewTexCoord4fVertex4fvSUN)
+
+#define GLEW_SUN_vertex GLEW_GET_VAR(__GLEW_SUN_vertex)
+
+#endif /* !GL_SUN_vertex */
+
+/* -------------------------- GL_WIN_phong_shading ------------------------- */
+
+#if !defined(GL_WIN_phong_shading)
+#define GL_WIN_phong_shading 1
+
+#define GL_PHONG_WIN 0x80EA
+#define GL_PHONG_HINT_WIN 0x80EB
+
+#define GLEW_WIN_phong_shading GLEW_GET_VAR(__GLEW_WIN_phong_shading)
+
+#endif /* !GL_WIN_phong_shading */
+
+/* -------------------------- GL_WIN_specular_fog -------------------------- */
+
+#if !defined(GL_WIN_specular_fog)
+#define GL_WIN_specular_fog 1
+
+#define GL_FOG_SPECULAR_TEXTURE_WIN 0x80EC
+
+#define GLEW_WIN_specular_fog GLEW_GET_VAR(__GLEW_WIN_specular_fog)
+
+#endif /* !GL_WIN_specular_fog */
+
+/* ---------------------------- GL_WIN_swap_hint --------------------------- */
+
+#if !defined(GL_WIN_swap_hint)
+#define GL_WIN_swap_hint 1
+
+typedef void (GLAPIENTRY * PFNGLADDSWAPHINTRECTWINPROC) (GLint x, GLint y, GLsizei width, GLsizei height);
+
+#define glAddSwapHintRectWIN GLEW_GET_FUN(__glewAddSwapHintRectWIN)
+
+#define GLEW_WIN_swap_hint GLEW_GET_VAR(__GLEW_WIN_swap_hint)
+
+#endif /* !GL_WIN_swap_hint */
+
+/* --------------------------- GL_ES_VERSION_1_0 --------------------------- */
+
+#if !defined(GL_ES_VERSION_1_0) && !defined(GLEW_NO_ES)
+#define GL_ES_VERSION_1_0 1
+
+typedef int GLclampx;
+typedef khronos_int32_t GLfixed;
+typedef void (*_GLfuncptr)();
+
+typedef void (GLAPIENTRY * PFNGLALPHAFUNCXPROC) (GLenum func, GLclampx ref);
+typedef void (GLAPIENTRY * PFNGLCLEARCOLORXPROC) (GLclampx red, GLclampx green, GLclampx blue, GLclampx alpha);
+typedef void (GLAPIENTRY * PFNGLCLEARDEPTHXPROC) (GLclampx depth);
+typedef void (GLAPIENTRY * PFNGLCOLOR4XPROC) (GLfixed red, GLfixed green, GLfixed blue, GLfixed alpha);
+typedef void (GLAPIENTRY * PFNGLDEPTHRANGEXPROC) (GLclampx zNear, GLclampx zFar);
+typedef void (GLAPIENTRY * PFNGLFOGXPROC) (GLenum pname, GLfixed param);
+typedef void (GLAPIENTRY * PFNGLFOGXVPROC) (GLenum pname, const GLfixed *params);
+typedef void (GLAPIENTRY * PFNGLFRUSTUMFPROC) (GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat zNear, GLfloat zFar);
+typedef void (GLAPIENTRY * PFNGLFRUSTUMXPROC) (GLfixed left, GLfixed right, GLfixed bottom, GLfixed top, GLfixed zNear, GLfixed zFar);
+typedef void (GLAPIENTRY * PFNGLLIGHTMODELXPROC) (GLenum pname, GLfixed params);
+typedef void (GLAPIENTRY * PFNGLLIGHTMODELXVPROC) (GLenum pname, const GLfixed *params);
+typedef void (GLAPIENTRY * PFNGLLIGHTXPROC) (GLenum light, GLenum pname, GLfixed param);
+typedef void (GLAPIENTRY * PFNGLLIGHTXVPROC) (GLenum light, GLenum pname, const GLfixed *params);
+typedef void (GLAPIENTRY * PFNGLLINEWIDTHXPROC) (GLfixed width);
+typedef void (GLAPIENTRY * PFNGLLOADMATRIXXPROC) (const GLfixed *m);
+typedef void (GLAPIENTRY * PFNGLMATERIALXPROC) (GLenum face, GLenum pname, GLfixed param);
+typedef void (GLAPIENTRY * PFNGLMATERIALXVPROC) (GLenum face, GLenum pname, const GLfixed *params);
+typedef void (GLAPIENTRY * PFNGLMULTMATRIXXPROC) (const GLfixed *m);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD4XPROC) (GLenum target, GLfixed s, GLfixed t, GLfixed r, GLfixed q);
+typedef void (GLAPIENTRY * PFNGLNORMAL3XPROC) (GLfixed nx, GLfixed ny, GLfixed nz);
+typedef void (GLAPIENTRY * PFNGLORTHOFPROC) (GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat zNear, GLfloat zFar);
+typedef void (GLAPIENTRY * PFNGLORTHOXPROC) (GLfixed left, GLfixed right, GLfixed bottom, GLfixed top, GLfixed zNear, GLfixed zFar);
+typedef void (GLAPIENTRY * PFNGLPOINTSIZEXPROC) (GLfixed size);
+typedef void (GLAPIENTRY * PFNGLPOLYGONOFFSETXPROC) (GLfixed factor, GLfixed units);
+typedef void (GLAPIENTRY * PFNGLROTATEXPROC) (GLfixed angle, GLfixed x, GLfixed y, GLfixed z);
+typedef void (GLAPIENTRY * PFNGLSAMPLECOVERAGEXPROC) (GLclampx value, GLboolean invert);
+typedef void (GLAPIENTRY * PFNGLSCALEXPROC) (GLfixed x, GLfixed y, GLfixed z);
+typedef void (GLAPIENTRY * PFNGLTEXENVXPROC) (GLenum target, GLenum pname, GLfixed param);
+typedef void (GLAPIENTRY * PFNGLTEXENVXVPROC) (GLenum target, GLenum pname, const GLfixed *params);
+typedef void (GLAPIENTRY * PFNGLTEXPARAMETERXPROC) (GLenum target, GLenum pname, GLfixed param);
+typedef void (GLAPIENTRY * PFNGLTRANSLATEXPROC) (GLfixed x, GLfixed y, GLfixed z);
+
+#define glAlphaFuncx GLEW_GET_FUN(__glewAlphaFuncx)
+#define glClearColorx GLEW_GET_FUN(__glewClearColorx)
+#define glClearDepthx GLEW_GET_FUN(__glewClearDepthx)
+#define glColor4x GLEW_GET_FUN(__glewColor4x)
+#define glDepthRangex GLEW_GET_FUN(__glewDepthRangex)
+#define glFogx GLEW_GET_FUN(__glewFogx)
+#define glFogxv GLEW_GET_FUN(__glewFogxv)
+#define glFrustumf GLEW_GET_FUN(__glewFrustumf)
+#define glFrustumx GLEW_GET_FUN(__glewFrustumx)
+#define glLightModelx GLEW_GET_FUN(__glewLightModelx)
+#define glLightModelxv GLEW_GET_FUN(__glewLightModelxv)
+#define glLightx GLEW_GET_FUN(__glewLightx)
+#define glLightxv GLEW_GET_FUN(__glewLightxv)
+#define glLineWidthx GLEW_GET_FUN(__glewLineWidthx)
+#define glLoadMatrixx GLEW_GET_FUN(__glewLoadMatrixx)
+#define glMaterialx GLEW_GET_FUN(__glewMaterialx)
+#define glMaterialxv GLEW_GET_FUN(__glewMaterialxv)
+#define glMultMatrixx GLEW_GET_FUN(__glewMultMatrixx)
+#define glMultiTexCoord4x GLEW_GET_FUN(__glewMultiTexCoord4x)
+#define glNormal3x GLEW_GET_FUN(__glewNormal3x)
+#define glOrthof GLEW_GET_FUN(__glewOrthof)
+#define glOrthox GLEW_GET_FUN(__glewOrthox)
+#define glPointSizex GLEW_GET_FUN(__glewPointSizex)
+#define glPolygonOffsetx GLEW_GET_FUN(__glewPolygonOffsetx)
+#define glRotatex GLEW_GET_FUN(__glewRotatex)
+#define glSampleCoveragex GLEW_GET_FUN(__glewSampleCoveragex)
+#define glScalex GLEW_GET_FUN(__glewScalex)
+#define glTexEnvx GLEW_GET_FUN(__glewTexEnvx)
+#define glTexEnvxv GLEW_GET_FUN(__glewTexEnvxv)
+#define glTexParameterx GLEW_GET_FUN(__glewTexParameterx)
+#define glTranslatex GLEW_GET_FUN(__glewTranslatex)
+
+#define GLEW_ES_VERSION_1_0 GLEW_GET_VAR(__GLEW_ES_VERSION_1_0)
+
+#endif /* !GL_ES_VERSION_1_0 && !GLEW_NO_ES*/
+
+/* -------------------------- GL_ES_VERSION_CL_1_1 ------------------------- */
+
+#if !defined(GL_ES_VERSION_CL_1_1) && !defined(GLEW_NO_ES)
+#define GL_ES_VERSION_CL_1_1 1
+
+#define GL_VERSION_ES_CL_1_1 0x1
+#define GL_VERSION_ES_CL_1_0 0x1
+
+typedef void (GLAPIENTRY * PFNGLCLIPPLANEXPROC) (GLenum ,const GLfixed *);
+typedef void (GLAPIENTRY * PFNGLGETCLIPPLANEXPROC) (GLenum ,GLfixed*);
+typedef void (GLAPIENTRY * PFNGLGETFIXEDVPROC) (GLenum, GLfixed *);
+typedef void (GLAPIENTRY * PFNGLGETLIGHTXVPROC) (GLenum, GLenum, GLfixed *);
+typedef void (GLAPIENTRY * PFNGLGETMATERIALXVPROC) (GLenum, GLenum, GLfixed *);
+typedef void (GLAPIENTRY * PFNGLGETTEXENVXVPROC) (GLenum, GLenum, GLfixed *);
+typedef void (GLAPIENTRY * PFNGLGETTEXPARAMETERXVPROC) (GLenum, GLenum, GLfixed *);
+typedef void (GLAPIENTRY * PFNGLPOINTPARAMETERXPROC) (GLenum, GLfixed);
+typedef void (GLAPIENTRY * PFNGLPOINTPARAMETERXVPROC) (GLenum, const GLfixed *);
+typedef void (GLAPIENTRY * PFNGLTEXPARAMETERXVPROC) (GLenum, GLenum, const GLfixed *);
+
+#define glClipPlanex GLEW_GET_FUN(__glewClipPlanex)
+#define glGetClipPlanex GLEW_GET_FUN(__glewGetClipPlanex)
+#define glGetFixedv GLEW_GET_FUN(__glewGetFixedv)
+#define glGetLightxv GLEW_GET_FUN(__glewGetLightxv)
+#define glGetMaterialxv GLEW_GET_FUN(__glewGetMaterialxv)
+#define glGetTexEnvxv GLEW_GET_FUN(__glewGetTexEnvxv)
+#define glGetTexParameterxv GLEW_GET_FUN(__glewGetTexParameterxv)
+#define glPointParameterx GLEW_GET_FUN(__glewPointParameterx)
+#define glPointParameterxv GLEW_GET_FUN(__glewPointParameterxv)
+#define glTexParameterxv GLEW_GET_FUN(__glewTexParameterxv)
+
+#define GLEW_ES_VERSION_CL_1_1 GLEW_GET_VAR(__GLEW_ES_VERSION_CL_1_1)
+
+#endif /* !GL_ES_VERSION_CL_1_1 && !GLEW_NO_ES*/
+
+/* -------------------------- GL_ES_VERSION_CM_1_1 ------------------------- */
+
+#if !defined(GL_ES_VERSION_CM_1_1) && !defined(GLEW_NO_ES)
+#define GL_ES_VERSION_CM_1_1 1
+
+#define GL_VERSION_ES_CM_1_1 0x1
+#define GL_VERSION_ES_CM_1_0 0x1
+
+typedef void (GLAPIENTRY * PFNGLCLIPPLANEFPROC) (GLenum, const GLfloat *);
+typedef void (GLAPIENTRY * PFNGLGETCLIPPLANEFPROC) (GLenum , GLfloat* );
+
+#define glClipPlanef GLEW_GET_FUN(__glewClipPlanef)
+#define glGetClipPlanef GLEW_GET_FUN(__glewGetClipPlanef)
+
+#define GLEW_ES_VERSION_CM_1_1 GLEW_GET_VAR(__GLEW_ES_VERSION_CM_1_1)
+
+#endif /* !GL_ES_VERSION_CM_1_1 && !GLEW_NO_ES*/
+
+/* --------------------------- GL_ES_VERSION_2_0 --------------------------- */
+
+#if !defined(GL_ES_VERSION_2_0) && !defined(GLEW_NO_ES)
+#define GL_ES_VERSION_2_0 1
+
+#define GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS 0x8CD9
+#define GL_RGB565 0x8D62
+
+#define GLEW_ES_VERSION_2_0 GLEW_GET_VAR(__GLEW_ES_VERSION_2_0)
+
+#endif /* !GL_ES_VERSION_2_0 && !GLEW_NO_ES*/
+
+/* --------------------- GL_AMD_compressed_3DC_texture --------------------- */
+
+#if !defined(GL_AMD_compressed_3DC_texture) && !defined(GLEW_NO_ES)
+#define GL_AMD_compressed_3DC_texture 1
+
+#define GL_3DC_X_AMD 0x87F9
+#define GL_3DC_XY_AMD 0x87FA
+
+#define GLEW_AMD_compressed_3DC_texture GLEW_GET_VAR(__GLEW_AMD_compressed_3DC_texture)
+
+#endif /* !GL_AMD_compressed_3DC_texture && !GLEW_NO_ES*/
+
+/* --------------------- GL_AMD_compressed_ATC_texture --------------------- */
+
+#if !defined(GL_AMD_compressed_ATC_texture) && !defined(GLEW_NO_ES)
+#define GL_AMD_compressed_ATC_texture 1
+
+#define GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD 0x87EE
+#define GL_ATC_RGB_AMD 0x8C92
+#define GL_ATC_RGBA_EXPLICIT_ALPHA_AMD 0x8C93
+
+#define GLEW_AMD_compressed_ATC_texture GLEW_GET_VAR(__GLEW_AMD_compressed_ATC_texture)
+
+#endif /* !GL_AMD_compressed_ATC_texture && !GLEW_NO_ES*/
+
+/* ----------------------- GL_AMD_program_binary_Z400 ---------------------- */
+
+#if !defined(GL_AMD_program_binary_Z400) && !defined(GLEW_NO_ES)
+#define GL_AMD_program_binary_Z400 1
+
+#define GL_Z400_BINARY_AMD 0x8740
+
+#define GLEW_AMD_program_binary_Z400 GLEW_GET_VAR(__GLEW_AMD_program_binary_Z400)
+
+#endif /* !GL_AMD_program_binary_Z400 && !GLEW_NO_ES*/
+
+/* ----------------------- GL_ANGLE_framebuffer_blit ----------------------- */
+
+#if !defined(GL_ANGLE_framebuffer_blit) && !defined(GLEW_NO_ES)
+#define GL_ANGLE_framebuffer_blit 1
+
+#define GL_DRAW_FRAMEBUFFER_BINDING_ANGLE 0x8CA6
+#define GL_READ_FRAMEBUFFER_ANGLE 0x8CA8
+#define GL_DRAW_FRAMEBUFFER_ANGLE 0x8CA9
+#define GL_READ_FRAMEBUFFER_BINDING_ANGLE 0x8CAA
+
+typedef void (GLAPIENTRY * PFNGLBLITFRAMEBUFFERANGLEPROC) (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter);
+
+#define glBlitFramebufferANGLE GLEW_GET_FUN(__glewBlitFramebufferANGLE)
+
+#define GLEW_ANGLE_framebuffer_blit GLEW_GET_VAR(__GLEW_ANGLE_framebuffer_blit)
+
+#endif /* !GL_ANGLE_framebuffer_blit && !GLEW_NO_ES*/
+
+/* -------------------- GL_ANGLE_framebuffer_multisample ------------------- */
+
+#if !defined(GL_ANGLE_framebuffer_multisample) && !defined(GLEW_NO_ES)
+#define GL_ANGLE_framebuffer_multisample 1
+
+#define GL_RENDERBUFFER_SAMPLES_ANGLE 0x8CAB
+#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE 0x8D56
+#define GL_MAX_SAMPLES_ANGLE 0x8D57
+
+typedef void (GLAPIENTRY * PFNGLRENDERBUFFERSTORAGEMULTISAMPLEANGLEPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
+
+#define glRenderbufferStorageMultisampleANGLE GLEW_GET_FUN(__glewRenderbufferStorageMultisampleANGLE)
+
+#define GLEW_ANGLE_framebuffer_multisample GLEW_GET_VAR(__GLEW_ANGLE_framebuffer_multisample)
+
+#endif /* !GL_ANGLE_framebuffer_multisample && !GLEW_NO_ES*/
+
+/* ----------------------- GL_ANGLE_instanced_arrays ----------------------- */
+
+#if !defined(GL_ANGLE_instanced_arrays) && !defined(GLEW_NO_ES)
+#define GL_ANGLE_instanced_arrays 1
+
+#define GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE 0x88FE
+
+typedef void (GLAPIENTRY * PFNGLDRAWARRAYSINSTANCEDANGLEPROC) (GLenum mode, GLint first, GLsizei count, GLsizei primcount);
+typedef void (GLAPIENTRY * PFNGLDRAWELEMENTSINSTANCEDANGLEPROC) (GLenum mode, GLsizei count, GLenum type, const void* indices, GLsizei primcount);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBDIVISORANGLEPROC) (GLuint index, GLuint divisor);
+
+#define glDrawArraysInstancedANGLE GLEW_GET_FUN(__glewDrawArraysInstancedANGLE)
+#define glDrawElementsInstancedANGLE GLEW_GET_FUN(__glewDrawElementsInstancedANGLE)
+#define glVertexAttribDivisorANGLE GLEW_GET_FUN(__glewVertexAttribDivisorANGLE)
+
+#define GLEW_ANGLE_instanced_arrays GLEW_GET_VAR(__GLEW_ANGLE_instanced_arrays)
+
+#endif /* !GL_ANGLE_instanced_arrays && !GLEW_NO_ES*/
+
+/* -------------------- GL_ANGLE_pack_reverse_row_order -------------------- */
+
+#if !defined(GL_ANGLE_pack_reverse_row_order) && !defined(GLEW_NO_ES)
+#define GL_ANGLE_pack_reverse_row_order 1
+
+#define GL_PACK_REVERSE_ROW_ORDER_ANGLE 0x93A4
+
+#define GLEW_ANGLE_pack_reverse_row_order GLEW_GET_VAR(__GLEW_ANGLE_pack_reverse_row_order)
+
+#endif /* !GL_ANGLE_pack_reverse_row_order && !GLEW_NO_ES*/
+
+/* ------------------- GL_ANGLE_texture_compression_dxt3 ------------------- */
+
+#if !defined(GL_ANGLE_texture_compression_dxt3) && !defined(GLEW_NO_ES)
+#define GL_ANGLE_texture_compression_dxt3 1
+
+#define GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE 0x83F2
+#define GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE 0x83F3
+
+#define GLEW_ANGLE_texture_compression_dxt3 GLEW_GET_VAR(__GLEW_ANGLE_texture_compression_dxt3)
+
+#endif /* !GL_ANGLE_texture_compression_dxt3 && !GLEW_NO_ES*/
+
+/* ------------------- GL_ANGLE_texture_compression_dxt5 ------------------- */
+
+#if !defined(GL_ANGLE_texture_compression_dxt5) && !defined(GLEW_NO_ES)
+#define GL_ANGLE_texture_compression_dxt5 1
+
+#define GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE 0x83F2
+#define GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE 0x83F3
+
+#define GLEW_ANGLE_texture_compression_dxt5 GLEW_GET_VAR(__GLEW_ANGLE_texture_compression_dxt5)
+
+#endif /* !GL_ANGLE_texture_compression_dxt5 && !GLEW_NO_ES*/
+
+/* ------------------------- GL_ANGLE_texture_usage ------------------------ */
+
+#if !defined(GL_ANGLE_texture_usage) && !defined(GLEW_NO_ES)
+#define GL_ANGLE_texture_usage 1
+
+#define GL_NONE 0x0000
+#define GL_TEXTURE_USAGE_ANGLE 0x93A2
+#define GL_FRAMEBUFFER_ATTACHMENT_ANGLE 0x93A3
+
+#define GLEW_ANGLE_texture_usage GLEW_GET_VAR(__GLEW_ANGLE_texture_usage)
+
+#endif /* !GL_ANGLE_texture_usage && !GLEW_NO_ES*/
+
+/* ------------------- GL_ANGLE_translated_shader_source ------------------- */
+
+#if !defined(GL_ANGLE_translated_shader_source) && !defined(GLEW_NO_ES)
+#define GL_ANGLE_translated_shader_source 1
+
+#define GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE 0x93A0
+
+typedef void (GLAPIENTRY * PFNGLGETTRANSLATEDSHADERSOURCEANGLEPROC) (GLuint shader, GLsizei bufsize, GLsizei* length, char* source);
+
+#define glGetTranslatedShaderSourceANGLE GLEW_GET_FUN(__glewGetTranslatedShaderSourceANGLE)
+
+#define GLEW_ANGLE_translated_shader_source GLEW_GET_VAR(__GLEW_ANGLE_translated_shader_source)
+
+#endif /* !GL_ANGLE_translated_shader_source && !GLEW_NO_ES*/
+
+/* ---------------------- GL_APPLE_copy_texture_levels --------------------- */
+
+#if !defined(GL_APPLE_copy_texture_levels) && !defined(GLEW_NO_ES)
+#define GL_APPLE_copy_texture_levels 1
+
+typedef void (GLAPIENTRY * PFNGLCOPYTEXTURELEVELSAPPLEPROC) (GLuint destinationTexture, GLuint sourceTexture, GLint sourceBaseLevel, GLsizei sourceLevelCount);
+
+#define glCopyTextureLevelsAPPLE GLEW_GET_FUN(__glewCopyTextureLevelsAPPLE)
+
+#define GLEW_APPLE_copy_texture_levels GLEW_GET_VAR(__GLEW_APPLE_copy_texture_levels)
+
+#endif /* !GL_APPLE_copy_texture_levels && !GLEW_NO_ES*/
+
+/* -------------------- GL_APPLE_framebuffer_multisample ------------------- */
+
+#if !defined(GL_APPLE_framebuffer_multisample) && !defined(GLEW_NO_ES)
+#define GL_APPLE_framebuffer_multisample 1
+
+#define GL_DRAW_FRAMEBUFFER_BINDING_APPLE 0x8CA6
+#define GL_READ_FRAMEBUFFER_APPLE 0x8CA8
+#define GL_DRAW_FRAMEBUFFER_APPLE 0x8CA9
+#define GL_READ_FRAMEBUFFER_BINDING_APPLE 0x8CAA
+#define GL_RENDERBUFFER_SAMPLES_APPLE 0x8CAB
+#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_APPLE 0x8D56
+#define GL_MAX_SAMPLES_APPLE 0x8D57
+
+typedef void (GLAPIENTRY * PFNGLRENDERBUFFERSTORAGEMULTISAMPLEAPPLEPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
+typedef void (GLAPIENTRY * PFNGLRESOLVEMULTISAMPLEFRAMEBUFFERAPPLEPROC) (void);
+
+#define glRenderbufferStorageMultisampleAPPLE GLEW_GET_FUN(__glewRenderbufferStorageMultisampleAPPLE)
+#define glResolveMultisampleFramebufferAPPLE GLEW_GET_FUN(__glewResolveMultisampleFramebufferAPPLE)
+
+#define GLEW_APPLE_framebuffer_multisample GLEW_GET_VAR(__GLEW_APPLE_framebuffer_multisample)
+
+#endif /* !GL_APPLE_framebuffer_multisample && !GLEW_NO_ES*/
+
+/* ----------------------------- GL_APPLE_sync ----------------------------- */
+
+#if !defined(GL_APPLE_sync) && !defined(GLEW_NO_ES)
+#define GL_APPLE_sync 1
+
+#define GL_SYNC_FLUSH_COMMANDS_BIT_APPLE 0x00000001
+#define GL_SYNC_OBJECT_APPLE 0x8A53
+#define GL_MAX_SERVER_WAIT_TIMEOUT_APPLE 0x9111
+#define GL_OBJECT_TYPE_APPLE 0x9112
+#define GL_SYNC_CONDITION_APPLE 0x9113
+#define GL_SYNC_STATUS_APPLE 0x9114
+#define GL_SYNC_FLAGS_APPLE 0x9115
+#define GL_SYNC_FENCE_APPLE 0x9116
+#define GL_SYNC_GPU_COMMANDS_COMPLETE_APPLE 0x9117
+#define GL_UNSIGNALED_APPLE 0x9118
+#define GL_SIGNALED_APPLE 0x9119
+#define GL_ALREADY_SIGNALED_APPLE 0x911A
+#define GL_TIMEOUT_EXPIRED_APPLE 0x911B
+#define GL_CONDITION_SATISFIED_APPLE 0x911C
+#define GL_WAIT_FAILED_APPLE 0x911D
+#define GL_TIMEOUT_IGNORED_APPLE 0xFFFFFFFFFFFFFFFF
+
+typedef GLenum (GLAPIENTRY * PFNGLCLIENTWAITSYNCAPPLEPROC) (GLsync GLsync, GLbitfield flags, GLuint64 timeout);
+typedef void (GLAPIENTRY * PFNGLDELETESYNCAPPLEPROC) (GLsync GLsync);
+typedef GLsync (GLAPIENTRY * PFNGLFENCESYNCAPPLEPROC) (GLenum condition, GLbitfield flags);
+typedef void (GLAPIENTRY * PFNGLGETINTEGER64VAPPLEPROC) (GLenum pname, GLint64* params);
+typedef void (GLAPIENTRY * PFNGLGETSYNCIVAPPLEPROC) (GLsync GLsync, GLenum pname, GLsizei bufSize, GLsizei* length, GLint *values);
+typedef GLboolean (GLAPIENTRY * PFNGLISSYNCAPPLEPROC) (GLsync GLsync);
+typedef void (GLAPIENTRY * PFNGLWAITSYNCAPPLEPROC) (GLsync GLsync, GLbitfield flags, GLuint64 timeout);
+
+#define glClientWaitSyncAPPLE GLEW_GET_FUN(__glewClientWaitSyncAPPLE)
+#define glDeleteSyncAPPLE GLEW_GET_FUN(__glewDeleteSyncAPPLE)
+#define glFenceSyncAPPLE GLEW_GET_FUN(__glewFenceSyncAPPLE)
+#define glGetInteger64vAPPLE GLEW_GET_FUN(__glewGetInteger64vAPPLE)
+#define glGetSyncivAPPLE GLEW_GET_FUN(__glewGetSyncivAPPLE)
+#define glIsSyncAPPLE GLEW_GET_FUN(__glewIsSyncAPPLE)
+#define glWaitSyncAPPLE GLEW_GET_FUN(__glewWaitSyncAPPLE)
+
+#define GLEW_APPLE_sync GLEW_GET_VAR(__GLEW_APPLE_sync)
+
+#endif /* !GL_APPLE_sync && !GLEW_NO_ES*/
+
+/* -------------------- GL_APPLE_texture_2D_limited_npot ------------------- */
+
+#if !defined(GL_APPLE_texture_2D_limited_npot) && !defined(GLEW_NO_ES)
+#define GL_APPLE_texture_2D_limited_npot 1
+
+#define GLEW_APPLE_texture_2D_limited_npot GLEW_GET_VAR(__GLEW_APPLE_texture_2D_limited_npot)
+
+#endif /* !GL_APPLE_texture_2D_limited_npot && !GLEW_NO_ES*/
+
+/* -------------------- GL_APPLE_texture_format_BGRA8888 ------------------- */
+
+#if !defined(GL_APPLE_texture_format_BGRA8888) && !defined(GLEW_NO_ES)
+#define GL_APPLE_texture_format_BGRA8888 1
+
+#define GL_BGRA_EXT 0x80E1
+
+#define GLEW_APPLE_texture_format_BGRA8888 GLEW_GET_VAR(__GLEW_APPLE_texture_format_BGRA8888)
+
+#endif /* !GL_APPLE_texture_format_BGRA8888 && !GLEW_NO_ES*/
+
+/* ----------------------- GL_APPLE_texture_max_level ---------------------- */
+
+#if !defined(GL_APPLE_texture_max_level) && !defined(GLEW_NO_ES)
+#define GL_APPLE_texture_max_level 1
+
+#define GL_TEXTURE_MAX_LEVEL_APPLE 0x813D
+
+#define GLEW_APPLE_texture_max_level GLEW_GET_VAR(__GLEW_APPLE_texture_max_level)
+
+#endif /* !GL_APPLE_texture_max_level && !GLEW_NO_ES*/
+
+/* ----------------------- GL_ARM_mali_program_binary ---------------------- */
+
+#if !defined(GL_ARM_mali_program_binary) && !defined(GLEW_NO_ES)
+#define GL_ARM_mali_program_binary 1
+
+#define GL_MALI_PROGRAM_BINARY_ARM 0x8F61
+
+#define GLEW_ARM_mali_program_binary GLEW_GET_VAR(__GLEW_ARM_mali_program_binary)
+
+#endif /* !GL_ARM_mali_program_binary && !GLEW_NO_ES*/
+
+/* ----------------------- GL_ARM_mali_shader_binary ----------------------- */
+
+#if !defined(GL_ARM_mali_shader_binary) && !defined(GLEW_NO_ES)
+#define GL_ARM_mali_shader_binary 1
+
+#define GL_MALI_SHADER_BINARY_ARM 0x8F60
+
+#define GLEW_ARM_mali_shader_binary GLEW_GET_VAR(__GLEW_ARM_mali_shader_binary)
+
+#endif /* !GL_ARM_mali_shader_binary && !GLEW_NO_ES*/
+
+/* ------------------------------ GL_ARM_rgba8 ----------------------------- */
+
+#if !defined(GL_ARM_rgba8) && !defined(GLEW_NO_ES)
+#define GL_ARM_rgba8 1
+
+#define GL_RGBA8_OES 0x8058
+
+#define GLEW_ARM_rgba8 GLEW_GET_VAR(__GLEW_ARM_rgba8)
+
+#endif /* !GL_ARM_rgba8 && !GLEW_NO_ES*/
+
+/* -------------------------- GL_DMP_shader_binary ------------------------- */
+
+#if !defined(GL_DMP_shader_binary) && !defined(GLEW_NO_ES)
+#define GL_DMP_shader_binary 1
+
+#define GL_SHADER_BINARY_DMP 0x9250
+
+#define GLEW_DMP_shader_binary GLEW_GET_VAR(__GLEW_DMP_shader_binary)
+
+#endif /* !GL_DMP_shader_binary && !GLEW_NO_ES*/
+
+/* --------------------- GL_EXT_color_buffer_half_float -------------------- */
+
+#if !defined(GL_EXT_color_buffer_half_float) && !defined(GLEW_NO_ES)
+#define GL_EXT_color_buffer_half_float 1
+
+#define GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE_EXT 0x8211
+#define GL_R16F_EXT 0x822D
+#define GL_RG16F_EXT 0x822F
+#define GL_RGBA16F_EXT 0x881A
+#define GL_RGB16F_EXT 0x881B
+#define GL_UNSIGNED_NORMALIZED_EXT 0x8C17
+
+#define GLEW_EXT_color_buffer_half_float GLEW_GET_VAR(__GLEW_EXT_color_buffer_half_float)
+
+#endif /* !GL_EXT_color_buffer_half_float && !GLEW_NO_ES*/
+
+/* --------------------------- GL_EXT_debug_label -------------------------- */
+
+#if !defined(GL_EXT_debug_label) && !defined(GLEW_NO_ES)
+#define GL_EXT_debug_label 1
+
+#define GL_PROGRAM_PIPELINE_OBJECT_EXT 0x8A4F
+#define GL_PROGRAM_OBJECT_EXT 0x8B40
+#define GL_SHADER_OBJECT_EXT 0x8B48
+#define GL_BUFFER_OBJECT_EXT 0x9151
+#define GL_QUERY_OBJECT_EXT 0x9153
+#define GL_VERTEX_ARRAY_OBJECT_EXT 0x9154
+
+typedef void (GLAPIENTRY * PFNGLGETOBJECTLABELEXTPROC) (GLenum type, GLuint object, GLsizei bufSize, GLsizei* length, char *label);
+typedef void (GLAPIENTRY * PFNGLLABELOBJECTEXTPROC) (GLenum type, GLuint object, GLsizei length, const char* label);
+
+#define glGetObjectLabelEXT GLEW_GET_FUN(__glewGetObjectLabelEXT)
+#define glLabelObjectEXT GLEW_GET_FUN(__glewLabelObjectEXT)
+
+#define GLEW_EXT_debug_label GLEW_GET_VAR(__GLEW_EXT_debug_label)
+
+#endif /* !GL_EXT_debug_label && !GLEW_NO_ES*/
+
+/* -------------------------- GL_EXT_debug_marker -------------------------- */
+
+#if !defined(GL_EXT_debug_marker) && !defined(GLEW_NO_ES)
+#define GL_EXT_debug_marker 1
+
+typedef void (GLAPIENTRY * PFNGLINSERTEVENTMARKEREXTPROC) (GLsizei length, const char* marker);
+typedef void (GLAPIENTRY * PFNGLPUSHGROUPMARKEREXTPROC) (GLsizei length, const char* marker);
+
+#define glInsertEventMarkerEXT GLEW_GET_FUN(__glewInsertEventMarkerEXT)
+#define glPushGroupMarkerEXT GLEW_GET_FUN(__glewPushGroupMarkerEXT)
+
+#define GLEW_EXT_debug_marker GLEW_GET_VAR(__GLEW_EXT_debug_marker)
+
+#endif /* !GL_EXT_debug_marker && !GLEW_NO_ES*/
+
+/* ----------------------- GL_EXT_discard_framebuffer ---------------------- */
+
+#if !defined(GL_EXT_discard_framebuffer) && !defined(GLEW_NO_ES)
+#define GL_EXT_discard_framebuffer 1
+
+#define GL_COLOR_EXT 0x1800
+#define GL_DEPTH_EXT 0x1801
+#define GL_STENCIL_EXT 0x1802
+
+typedef void (GLAPIENTRY * PFNGLDISCARDFRAMEBUFFEREXTPROC) (GLenum target, GLsizei numAttachments, const GLenum* attachments);
+
+#define glDiscardFramebufferEXT GLEW_GET_FUN(__glewDiscardFramebufferEXT)
+
+#define GLEW_EXT_discard_framebuffer GLEW_GET_VAR(__GLEW_EXT_discard_framebuffer)
+
+#endif /* !GL_EXT_discard_framebuffer && !GLEW_NO_ES*/
+
+/* --------------------------- GL_EXT_frag_depth --------------------------- */
+
+#if !defined(GL_EXT_frag_depth) && !defined(GLEW_NO_ES)
+#define GL_EXT_frag_depth 1
+
+#define GLEW_EXT_frag_depth GLEW_GET_VAR(__GLEW_EXT_frag_depth)
+
+#endif /* !GL_EXT_frag_depth && !GLEW_NO_ES*/
+
+/* ------------------------ GL_EXT_map_buffer_range ------------------------ */
+
+#if !defined(GL_EXT_map_buffer_range) && !defined(GLEW_NO_ES)
+#define GL_EXT_map_buffer_range 1
+
+#define GL_MAP_READ_BIT_EXT 0x0001
+#define GL_MAP_WRITE_BIT_EXT 0x0002
+#define GL_MAP_INVALIDATE_RANGE_BIT_EXT 0x0004
+#define GL_MAP_INVALIDATE_BUFFER_BIT_EXT 0x0008
+#define GL_MAP_FLUSH_EXPLICIT_BIT_EXT 0x0010
+#define GL_MAP_UNSYNCHRONIZED_BIT_EXT 0x0020
+
+typedef void (GLAPIENTRY * PFNGLFLUSHMAPPEDBUFFERRANGEEXTPROC) (GLenum target, GLintptr offset, GLsizeiptr length);
+typedef GLvoid * (GLAPIENTRY * PFNGLMAPBUFFERRANGEEXTPROC) (GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access);
+
+#define glFlushMappedBufferRangeEXT GLEW_GET_FUN(__glewFlushMappedBufferRangeEXT)
+#define glMapBufferRangeEXT GLEW_GET_FUN(__glewMapBufferRangeEXT)
+
+#define GLEW_EXT_map_buffer_range GLEW_GET_VAR(__GLEW_EXT_map_buffer_range)
+
+#endif /* !GL_EXT_map_buffer_range && !GLEW_NO_ES*/
+
+/* ----------------- GL_EXT_multisampled_render_to_texture ----------------- */
+
+#if !defined(GL_EXT_multisampled_render_to_texture) && !defined(GLEW_NO_ES)
+#define GL_EXT_multisampled_render_to_texture 1
+
+#define GL_RENDERBUFFER_SAMPLES_EXT 0x8CAB
+#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT 0x8D56
+#define GL_MAX_SAMPLES_EXT 0x8D57
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_SAMPLES_EXT 0x8D6C
+
+typedef void (GLAPIENTRY * PFNGLFRAMEBUFFERTEXTURE2DMULTISAMPLEEXTPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLsizei samples);
+typedef void (GLAPIENTRY * PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
+
+#define glFramebufferTexture2DMultisampleEXT GLEW_GET_FUN(__glewFramebufferTexture2DMultisampleEXT)
+#define glRenderbufferStorageMultisampleEXT GLEW_GET_FUN(__glewRenderbufferStorageMultisampleEXT)
+
+#define GLEW_EXT_multisampled_render_to_texture GLEW_GET_VAR(__GLEW_EXT_multisampled_render_to_texture)
+
+#endif /* !GL_EXT_multisampled_render_to_texture && !GLEW_NO_ES*/
+
+/* --------------------- GL_EXT_multiview_draw_buffers --------------------- */
+
+#if !defined(GL_EXT_multiview_draw_buffers) && !defined(GLEW_NO_ES)
+#define GL_EXT_multiview_draw_buffers 1
+
+#define GL_DRAW_BUFFER_EXT 0x0C01
+#define GL_READ_BUFFER_EXT 0x0C02
+#define GL_COLOR_ATTACHMENT_EXT 0x90F0
+#define GL_MULTIVIEW_EXT 0x90F1
+#define GL_MAX_MULTIVIEW_BUFFERS_EXT 0x90F2
+
+typedef void (GLAPIENTRY * PFNGLDRAWBUFFERSINDEXEDEXTPROC) (GLint n, const GLenum* location, const GLint *indices);
+typedef void (GLAPIENTRY * PFNGLGETINTEGERI_VEXTPROC) (GLenum target, GLuint index, GLint* data);
+typedef void (GLAPIENTRY * PFNGLREADBUFFERINDEXEDEXTPROC) (GLenum src, GLint index);
+
+#define glDrawBuffersIndexedEXT GLEW_GET_FUN(__glewDrawBuffersIndexedEXT)
+#define glGetIntegeri_vEXT GLEW_GET_FUN(__glewGetIntegeri_vEXT)
+#define glReadBufferIndexedEXT GLEW_GET_FUN(__glewReadBufferIndexedEXT)
+
+#define GLEW_EXT_multiview_draw_buffers GLEW_GET_VAR(__GLEW_EXT_multiview_draw_buffers)
+
+#endif /* !GL_EXT_multiview_draw_buffers && !GLEW_NO_ES*/
+
+/* --------------------- GL_EXT_occlusion_query_boolean -------------------- */
+
+#if !defined(GL_EXT_occlusion_query_boolean) && !defined(GLEW_NO_ES)
+#define GL_EXT_occlusion_query_boolean 1
+
+#define GL_CURRENT_QUERY_EXT 0x8865
+#define GL_QUERY_RESULT_EXT 0x8866
+#define GL_QUERY_RESULT_AVAILABLE_EXT 0x8867
+#define GL_ANY_SAMPLES_PASSED_EXT 0x8C2F
+#define GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT 0x8D6A
+
+typedef void (GLAPIENTRY * PFNGLBEGINQUERYEXTPROC) (GLenum target, GLuint id);
+typedef void (GLAPIENTRY * PFNGLDELETEQUERIESEXTPROC) (GLsizei n, const GLuint* ids);
+typedef void (GLAPIENTRY * PFNGLENDQUERYEXTPROC) (GLenum target);
+typedef void (GLAPIENTRY * PFNGLGENQUERIESEXTPROC) (GLsizei n, GLuint* ids);
+typedef void (GLAPIENTRY * PFNGLGETQUERYOBJECTUIVEXTPROC) (GLuint id, GLenum pname, GLuint* params);
+typedef void (GLAPIENTRY * PFNGLGETQUERYIVEXTPROC) (GLenum target, GLenum pname, GLint* params);
+typedef GLboolean (GLAPIENTRY * PFNGLISQUERYEXTPROC) (GLuint id);
+
+#define glBeginQueryEXT GLEW_GET_FUN(__glewBeginQueryEXT)
+#define glDeleteQueriesEXT GLEW_GET_FUN(__glewDeleteQueriesEXT)
+#define glEndQueryEXT GLEW_GET_FUN(__glewEndQueryEXT)
+#define glGenQueriesEXT GLEW_GET_FUN(__glewGenQueriesEXT)
+#define glGetQueryObjectuivEXT GLEW_GET_FUN(__glewGetQueryObjectuivEXT)
+#define glGetQueryivEXT GLEW_GET_FUN(__glewGetQueryivEXT)
+#define glIsQueryEXT GLEW_GET_FUN(__glewIsQueryEXT)
+
+#define GLEW_EXT_occlusion_query_boolean GLEW_GET_VAR(__GLEW_EXT_occlusion_query_boolean)
+
+#endif /* !GL_EXT_occlusion_query_boolean && !GLEW_NO_ES*/
+
+/* ------------------------ GL_EXT_read_format_bgra ------------------------ */
+
+#if !defined(GL_EXT_read_format_bgra) && !defined(GLEW_NO_ES)
+#define GL_EXT_read_format_bgra 1
+
+#define GL_BGRA_EXT 0x80E1
+#define GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT 0x8365
+#define GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT 0x8366
+
+#define GLEW_EXT_read_format_bgra GLEW_GET_VAR(__GLEW_EXT_read_format_bgra)
+
+#endif /* !GL_EXT_read_format_bgra && !GLEW_NO_ES*/
+
+/* --------------------------- GL_EXT_robustness --------------------------- */
+
+#if !defined(GL_EXT_robustness) && !defined(GLEW_NO_ES)
+#define GL_EXT_robustness 1
+
+#define GL_NO_ERROR 0x0000
+#define GL_LOSE_CONTEXT_ON_RESET_EXT 0x8252
+#define GL_GUILTY_CONTEXT_RESET_EXT 0x8253
+#define GL_INNOCENT_CONTEXT_RESET_EXT 0x8254
+#define GL_UNKNOWN_CONTEXT_RESET_EXT 0x8255
+#define GL_RESET_NOTIFICATION_STRATEGY_EXT 0x8256
+#define GL_NO_RESET_NOTIFICATION_EXT 0x8261
+#define GL_CONTEXT_ROBUST_ACCESS_EXT 0x90F3
+
+typedef void (GLAPIENTRY * PFNGLGETNUNIFORMFVEXTPROC) (GLuint program, GLint location, GLsizei bufSize, GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLGETNUNIFORMIVEXTPROC) (GLuint program, GLint location, GLsizei bufSize, GLint* params);
+typedef void (GLAPIENTRY * PFNGLREADNPIXELSEXTPROC) (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei bufSize, void* data);
+
+#define glGetnUniformfvEXT GLEW_GET_FUN(__glewGetnUniformfvEXT)
+#define glGetnUniformivEXT GLEW_GET_FUN(__glewGetnUniformivEXT)
+#define glReadnPixelsEXT GLEW_GET_FUN(__glewReadnPixelsEXT)
+
+#define GLEW_EXT_robustness GLEW_GET_VAR(__GLEW_EXT_robustness)
+
+#endif /* !GL_EXT_robustness && !GLEW_NO_ES*/
+
+/* ------------------------------ GL_EXT_sRGB ------------------------------ */
+
+#if !defined(GL_EXT_sRGB) && !defined(GLEW_NO_ES)
+#define GL_EXT_sRGB 1
+
+#define GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING_EXT 0x8210
+#define GL_SRGB_EXT 0x8C40
+#define GL_SRGB_ALPHA_EXT 0x8C42
+#define GL_SRGB8_ALPHA8_EXT 0x8C43
+
+#define GLEW_EXT_sRGB GLEW_GET_VAR(__GLEW_EXT_sRGB)
+
+#endif /* !GL_EXT_sRGB && !GLEW_NO_ES*/
+
+/* -------------------- GL_EXT_shader_framebuffer_fetch -------------------- */
+
+#if !defined(GL_EXT_shader_framebuffer_fetch) && !defined(GLEW_NO_ES)
+#define GL_EXT_shader_framebuffer_fetch 1
+
+#define GL_FRAGMENT_SHADER_DISCARDS_SAMPLES_EXT 0x8A52
+
+#define GLEW_EXT_shader_framebuffer_fetch GLEW_GET_VAR(__GLEW_EXT_shader_framebuffer_fetch)
+
+#endif /* !GL_EXT_shader_framebuffer_fetch && !GLEW_NO_ES*/
+
+/* ----------------------- GL_EXT_shader_texture_lod ----------------------- */
+
+#if !defined(GL_EXT_shader_texture_lod) && !defined(GLEW_NO_ES)
+#define GL_EXT_shader_texture_lod 1
+
+#define GLEW_EXT_shader_texture_lod GLEW_GET_VAR(__GLEW_EXT_shader_texture_lod)
+
+#endif /* !GL_EXT_shader_texture_lod && !GLEW_NO_ES*/
+
+/* ------------------------- GL_EXT_shadow_samplers ------------------------ */
+
+#if !defined(GL_EXT_shadow_samplers) && !defined(GLEW_NO_ES)
+#define GL_EXT_shadow_samplers 1
+
+#define GL_TEXTURE_COMPARE_MODE_EXT 0x884C
+#define GL_TEXTURE_COMPARE_FUNC_EXT 0x884D
+#define GL_COMPARE_REF_TO_TEXTURE_EXT 0x884E
+#define GL_SAMPLER_2D_SHADOW_EXT 0x8B62
+
+#define GLEW_EXT_shadow_samplers GLEW_GET_VAR(__GLEW_EXT_shadow_samplers)
+
+#endif /* !GL_EXT_shadow_samplers && !GLEW_NO_ES*/
+
+/* --------------------- GL_EXT_texture_format_BGRA8888 -------------------- */
+
+#if !defined(GL_EXT_texture_format_BGRA8888) && !defined(GLEW_NO_ES)
+#define GL_EXT_texture_format_BGRA8888 1
+
+#define GL_BGRA_EXT 0x80E1
+
+#define GLEW_EXT_texture_format_BGRA8888 GLEW_GET_VAR(__GLEW_EXT_texture_format_BGRA8888)
+
+#endif /* !GL_EXT_texture_format_BGRA8888 && !GLEW_NO_ES*/
+
+/* --------------------------- GL_EXT_texture_rg --------------------------- */
+
+#if !defined(GL_EXT_texture_rg) && !defined(GLEW_NO_ES)
+#define GL_EXT_texture_rg 1
+
+#define GL_RED_EXT 0x1903
+#define GL_RG_EXT 0x8227
+#define GL_R8_EXT 0x8229
+#define GL_RG8_EXT 0x822B
+
+#define GLEW_EXT_texture_rg GLEW_GET_VAR(__GLEW_EXT_texture_rg)
+
+#endif /* !GL_EXT_texture_rg && !GLEW_NO_ES*/
+
+/* ------------------------- GL_EXT_texture_storage ------------------------ */
+
+#if !defined(GL_EXT_texture_storage) && !defined(GLEW_NO_ES)
+#define GL_EXT_texture_storage 1
+
+#define GL_ALPHA8_EXT 0x803C
+#define GL_LUMINANCE8_EXT 0x8040
+#define GL_LUMINANCE8_ALPHA8_EXT 0x8045
+#define GL_RGB10_EXT 0x8052
+#define GL_RGB10_A2_EXT 0x8059
+#define GL_R8_EXT 0x8229
+#define GL_RG8_EXT 0x822B
+#define GL_R16F_EXT 0x822D
+#define GL_R32F_EXT 0x822E
+#define GL_RG16F_EXT 0x822F
+#define GL_RG32F_EXT 0x8230
+#define GL_RGBA32F_EXT 0x8814
+#define GL_RGB32F_EXT 0x8815
+#define GL_ALPHA32F_EXT 0x8816
+#define GL_LUMINANCE32F_EXT 0x8818
+#define GL_LUMINANCE_ALPHA32F_EXT 0x8819
+#define GL_RGBA16F_EXT 0x881A
+#define GL_RGB16F_EXT 0x881B
+#define GL_ALPHA16F_EXT 0x881C
+#define GL_LUMINANCE16F_EXT 0x881E
+#define GL_LUMINANCE_ALPHA16F_EXT 0x881F
+#define GL_RGB_422_APPLE 0x8A1F
+#define GL_TEXTURE_IMMUTABLE_FORMAT_EXT 0x912F
+#define GL_BGRA8_EXT 0x93A1
+
+typedef void (GLAPIENTRY * PFNGLTEXSTORAGE1DEXTPROC) (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width);
+typedef void (GLAPIENTRY * PFNGLTEXSTORAGE2DEXTPROC) (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height);
+typedef void (GLAPIENTRY * PFNGLTEXSTORAGE3DEXTPROC) (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth);
+typedef void (GLAPIENTRY * PFNGLTEXTURESTORAGE1DEXTPROC) (GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width);
+typedef void (GLAPIENTRY * PFNGLTEXTURESTORAGE2DEXTPROC) (GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height);
+typedef void (GLAPIENTRY * PFNGLTEXTURESTORAGE3DEXTPROC) (GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth);
+
+#define glTexStorage1DEXT GLEW_GET_FUN(__glewTexStorage1DEXT)
+#define glTexStorage2DEXT GLEW_GET_FUN(__glewTexStorage2DEXT)
+#define glTexStorage3DEXT GLEW_GET_FUN(__glewTexStorage3DEXT)
+#define glTextureStorage1DEXT GLEW_GET_FUN(__glewTextureStorage1DEXT)
+#define glTextureStorage2DEXT GLEW_GET_FUN(__glewTextureStorage2DEXT)
+#define glTextureStorage3DEXT GLEW_GET_FUN(__glewTextureStorage3DEXT)
+
+#define GLEW_EXT_texture_storage GLEW_GET_VAR(__GLEW_EXT_texture_storage)
+
+#endif /* !GL_EXT_texture_storage && !GLEW_NO_ES*/
+
+/* ------------------- GL_EXT_texture_type_2_10_10_10_REV ------------------ */
+
+#if !defined(GL_EXT_texture_type_2_10_10_10_REV) && !defined(GLEW_NO_ES)
+#define GL_EXT_texture_type_2_10_10_10_REV 1
+
+#define GL_UNSIGNED_INT_2_10_10_10_REV_EXT 0x8368
+
+#define GLEW_EXT_texture_type_2_10_10_10_REV GLEW_GET_VAR(__GLEW_EXT_texture_type_2_10_10_10_REV)
+
+#endif /* !GL_EXT_texture_type_2_10_10_10_REV && !GLEW_NO_ES*/
+
+/* ------------------------- GL_EXT_unpack_subimage ------------------------ */
+
+#if !defined(GL_EXT_unpack_subimage) && !defined(GLEW_NO_ES)
+#define GL_EXT_unpack_subimage 1
+
+#define GL_UNPACK_ROW_LENGTH 0x0CF2
+#define GL_UNPACK_SKIP_ROWS 0x0CF3
+#define GL_UNPACK_SKIP_PIXELS 0x0CF4
+
+#define GLEW_EXT_unpack_subimage GLEW_GET_VAR(__GLEW_EXT_unpack_subimage)
+
+#endif /* !GL_EXT_unpack_subimage && !GLEW_NO_ES*/
+
+/* ----------------------- GL_FJ_shader_binary_GCCSO ----------------------- */
+
+#if !defined(GL_FJ_shader_binary_GCCSO) && !defined(GLEW_NO_ES)
+#define GL_FJ_shader_binary_GCCSO 1
+
+#define GL_GCCSO_SHADER_BINARY_FJ 0x9260
+
+#define GLEW_FJ_shader_binary_GCCSO GLEW_GET_VAR(__GLEW_FJ_shader_binary_GCCSO)
+
+#endif /* !GL_FJ_shader_binary_GCCSO && !GLEW_NO_ES*/
+
+/* ----------------- GL_IMG_multisampled_render_to_texture ----------------- */
+
+#if !defined(GL_IMG_multisampled_render_to_texture) && !defined(GLEW_NO_ES)
+#define GL_IMG_multisampled_render_to_texture 1
+
+#define GL_RENDERBUFFER_SAMPLES_IMG 0x9133
+#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_IMG 0x9134
+#define GL_MAX_SAMPLES_IMG 0x9135
+#define GL_TEXTURE_SAMPLES_IMG 0x9136
+
+typedef void (GLAPIENTRY * PFNGLFRAMEBUFFERTEXTURE2DMULTISAMPLEIMGPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLsizei samples);
+typedef void (GLAPIENTRY * PFNGLRENDERBUFFERSTORAGEMULTISAMPLEIMGPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
+
+#define glFramebufferTexture2DMultisampleIMG GLEW_GET_FUN(__glewFramebufferTexture2DMultisampleIMG)
+#define glRenderbufferStorageMultisampleIMG GLEW_GET_FUN(__glewRenderbufferStorageMultisampleIMG)
+
+#define GLEW_IMG_multisampled_render_to_texture GLEW_GET_VAR(__GLEW_IMG_multisampled_render_to_texture)
+
+#endif /* !GL_IMG_multisampled_render_to_texture && !GLEW_NO_ES*/
+
+/* ------------------------- GL_IMG_program_binary ------------------------- */
+
+#if !defined(GL_IMG_program_binary) && !defined(GLEW_NO_ES)
+#define GL_IMG_program_binary 1
+
+#define GL_SGX_PROGRAM_BINARY_IMG 0x9130
+
+#define GLEW_IMG_program_binary GLEW_GET_VAR(__GLEW_IMG_program_binary)
+
+#endif /* !GL_IMG_program_binary && !GLEW_NO_ES*/
+
+/* --------------------------- GL_IMG_read_format -------------------------- */
+
+#if !defined(GL_IMG_read_format) && !defined(GLEW_NO_ES)
+#define GL_IMG_read_format 1
+
+#define GL_BGRA_IMG 0x80E1
+#define GL_UNSIGNED_SHORT_4_4_4_4_REV_IMG 0x8365
+
+#define GLEW_IMG_read_format GLEW_GET_VAR(__GLEW_IMG_read_format)
+
+#endif /* !GL_IMG_read_format && !GLEW_NO_ES*/
+
+/* -------------------------- GL_IMG_shader_binary ------------------------- */
+
+#if !defined(GL_IMG_shader_binary) && !defined(GLEW_NO_ES)
+#define GL_IMG_shader_binary 1
+
+#define GL_SGX_BINARY_IMG 0x8C0A
+
+#define GLEW_IMG_shader_binary GLEW_GET_VAR(__GLEW_IMG_shader_binary)
+
+#endif /* !GL_IMG_shader_binary && !GLEW_NO_ES*/
+
+/* -------------------- GL_IMG_texture_compression_pvrtc ------------------- */
+
+#if !defined(GL_IMG_texture_compression_pvrtc) && !defined(GLEW_NO_ES)
+#define GL_IMG_texture_compression_pvrtc 1
+
+#define GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG 0x8C00
+#define GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG 0x8C01
+#define GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG 0x8C02
+#define GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG 0x8C03
+
+#define GLEW_IMG_texture_compression_pvrtc GLEW_GET_VAR(__GLEW_IMG_texture_compression_pvrtc)
+
+#endif /* !GL_IMG_texture_compression_pvrtc && !GLEW_NO_ES*/
+
+/* --------------- GL_IMG_texture_env_enhanced_fixed_function -------------- */
+
+#if !defined(GL_IMG_texture_env_enhanced_fixed_function) && !defined(GLEW_NO_ES)
+#define GL_IMG_texture_env_enhanced_fixed_function 1
+
+#define GL_DOT3_RGBA_IMG 0x86AF
+#define GL_MODULATE_COLOR_IMG 0x8C04
+#define GL_RECIP_ADD_SIGNED_ALPHA_IMG 0x8C05
+#define GL_TEXTURE_ALPHA_MODULATE_IMG 0x8C06
+#define GL_FACTOR_ALPHA_MODULATE_IMG 0x8C07
+#define GL_FRAGMENT_ALPHA_MODULATE_IMG 0x8C08
+#define GL_ADD_BLEND_IMG 0x8C09
+
+#define GLEW_IMG_texture_env_enhanced_fixed_function GLEW_GET_VAR(__GLEW_IMG_texture_env_enhanced_fixed_function)
+
+#endif /* !GL_IMG_texture_env_enhanced_fixed_function && !GLEW_NO_ES*/
+
+/* ------------------------- GL_IMG_user_clip_plane ------------------------ */
+
+#if !defined(GL_IMG_user_clip_plane) && !defined(GLEW_NO_ES)
+#define GL_IMG_user_clip_plane 1
+
+#define GL_MAX_CLIP_PLANES_IMG 0x0D32
+#define GL_CLIP_PLANE0_IMG 0x3000
+#define GL_CLIP_PLANE1_IMG 0x3001
+#define GL_CLIP_PLANE2_IMG 0x3002
+#define GL_CLIP_PLANE3_IMG 0x3003
+#define GL_CLIP_PLANE4_IMG 0x3004
+#define GL_CLIP_PLANE5_IMG 0x3005
+
+typedef void (GLAPIENTRY * PFNGLCLIPPLANEFIMGPROC) (GLenum p, GLfloat eqn[4]);
+
+#define glClipPlanefIMG GLEW_GET_FUN(__glewClipPlanefIMG)
+
+#define GLEW_IMG_user_clip_plane GLEW_GET_VAR(__GLEW_IMG_user_clip_plane)
+
+#endif /* !GL_IMG_user_clip_plane && !GLEW_NO_ES*/
+
+/* ------------------------ GL_NV_3dvision_settings ------------------------ */
+
+#if !defined(GL_NV_3dvision_settings) && !defined(GLEW_NO_ES)
+#define GL_NV_3dvision_settings 1
+
+#define GL_3DVISION_STEREO_NV 0x90F4
+#define GL_STEREO_SEPARATION_NV 0x90F5
+#define GL_STEREO_CONVERGENCE_NV 0x90F6
+#define GL_STEREO_CUTOFF_NV 0x90F7
+#define GL_STEREO_PROJECTION_NV 0x90F8
+#define GL_STEREO_PROJECTION_PERSPECTIVE_NV 0x90F9
+#define GL_STEREO_PROJECTION_ORTHO_NV 0x90FA
+
+typedef void (GLAPIENTRY * PFNGLSTEREOPARAMETERFNVPROC) (GLenum pname, GLfloat param);
+typedef void (GLAPIENTRY * PFNGLSTEREOPARAMETERINVPROC) (GLenum pname, GLint param);
+
+#define glStereoParameterfNV GLEW_GET_FUN(__glewStereoParameterfNV)
+#define glStereoParameteriNV GLEW_GET_FUN(__glewStereoParameteriNV)
+
+#define GLEW_NV_3dvision_settings GLEW_GET_VAR(__GLEW_NV_3dvision_settings)
+
+#endif /* !GL_NV_3dvision_settings && !GLEW_NO_ES*/
+
+/* ------------------- GL_NV_EGL_stream_consumer_external ------------------ */
+
+#if !defined(GL_NV_EGL_stream_consumer_external) && !defined(GLEW_NO_ES)
+#define GL_NV_EGL_stream_consumer_external 1
+
+#define GL_TEXTURE_EXTERNAL_OES 0x8D65
+#define GL_SAMPLER_EXTERNAL_OES 0x8D66
+#define GL_TEXTURE_BINDING_EXTERNAL_OES 0x8D67
+#define GL_REQUIRED_TEXTURE_IMAGE_UNITS_OES 0x8D68
+
+#define GLEW_NV_EGL_stream_consumer_external GLEW_GET_VAR(__GLEW_NV_EGL_stream_consumer_external)
+
+#endif /* !GL_NV_EGL_stream_consumer_external && !GLEW_NO_ES*/
+
+/* ------------------------------- GL_NV_bgr ------------------------------- */
+
+#if !defined(GL_NV_bgr) && !defined(GLEW_NO_ES)
+#define GL_NV_bgr 1
+
+#define GL_BGR_NV 0x80E0
+
+#define GLEW_NV_bgr GLEW_GET_VAR(__GLEW_NV_bgr)
+
+#endif /* !GL_NV_bgr && !GLEW_NO_ES*/
+
+/* ------------------------- GL_NV_coverage_sample ------------------------- */
+
+#if !defined(GL_NV_coverage_sample) && !defined(GLEW_NO_ES)
+#define GL_NV_coverage_sample 1
+
+#define GL_COVERAGE_BUFFER_BIT_NV 0x8000
+#define GL_COVERAGE_COMPONENT_NV 0x8ED0
+#define GL_COVERAGE_COMPONENT4_NV 0x8ED1
+#define GL_COVERAGE_ATTACHMENT_NV 0x8ED2
+#define GL_COVERAGE_BUFFERS_NV 0x8ED3
+#define GL_COVERAGE_ALL_FRAGMENTS_NV 0x8ED5
+#define GL_COVERAGE_EDGE_FRAGMENTS_NV 0x8ED6
+#define GL_COVERAGE_AUTOMATIC_NV 0x8ED7
+
+typedef void (GLAPIENTRY * PFNGLCOVERAGEMASKNVPROC) (GLboolean mask);
+typedef void (GLAPIENTRY * PFNGLCOVERAGEOPERATIONNVPROC) (GLenum operation);
+
+#define glCoverageMaskNV GLEW_GET_FUN(__glewCoverageMaskNV)
+#define glCoverageOperationNV GLEW_GET_FUN(__glewCoverageOperationNV)
+
+#define GLEW_NV_coverage_sample GLEW_GET_VAR(__GLEW_NV_coverage_sample)
+
+#endif /* !GL_NV_coverage_sample && !GLEW_NO_ES*/
+
+/* ------------------------- GL_NV_depth_nonlinear ------------------------- */
+
+#if !defined(GL_NV_depth_nonlinear) && !defined(GLEW_NO_ES)
+#define GL_NV_depth_nonlinear 1
+
+#define GL_DEPTH_COMPONENT16_NONLINEAR_NV 0x8E2C
+
+#define GLEW_NV_depth_nonlinear GLEW_GET_VAR(__GLEW_NV_depth_nonlinear)
+
+#endif /* !GL_NV_depth_nonlinear && !GLEW_NO_ES*/
+
+/* --------------------------- GL_NV_draw_buffers -------------------------- */
+
+#if !defined(GL_NV_draw_buffers) && !defined(GLEW_NO_ES)
+#define GL_NV_draw_buffers 1
+
+#define GL_MAX_DRAW_BUFFERS_NV 0x8824
+#define GL_DRAW_BUFFER0_NV 0x8825
+#define GL_DRAW_BUFFER1_NV 0x8826
+#define GL_DRAW_BUFFER2_NV 0x8827
+#define GL_DRAW_BUFFER3_NV 0x8828
+#define GL_DRAW_BUFFER4_NV 0x8829
+#define GL_DRAW_BUFFER5_NV 0x882A
+#define GL_DRAW_BUFFER6_NV 0x882B
+#define GL_DRAW_BUFFER7_NV 0x882C
+#define GL_DRAW_BUFFER8_NV 0x882D
+#define GL_DRAW_BUFFER9_NV 0x882E
+#define GL_DRAW_BUFFER10_NV 0x882F
+#define GL_DRAW_BUFFER11_NV 0x8830
+#define GL_DRAW_BUFFER12_NV 0x8831
+#define GL_DRAW_BUFFER13_NV 0x8832
+#define GL_DRAW_BUFFER14_NV 0x8833
+#define GL_DRAW_BUFFER15_NV 0x8834
+#define GL_COLOR_ATTACHMENT0_NV 0x8CE0
+#define GL_COLOR_ATTACHMENT1_NV 0x8CE1
+#define GL_COLOR_ATTACHMENT2_NV 0x8CE2
+#define GL_COLOR_ATTACHMENT3_NV 0x8CE3
+#define GL_COLOR_ATTACHMENT4_NV 0x8CE4
+#define GL_COLOR_ATTACHMENT5_NV 0x8CE5
+#define GL_COLOR_ATTACHMENT6_NV 0x8CE6
+#define GL_COLOR_ATTACHMENT7_NV 0x8CE7
+#define GL_COLOR_ATTACHMENT8_NV 0x8CE8
+#define GL_COLOR_ATTACHMENT9_NV 0x8CE9
+#define GL_COLOR_ATTACHMENT10_NV 0x8CEA
+#define GL_COLOR_ATTACHMENT11_NV 0x8CEB
+#define GL_COLOR_ATTACHMENT12_NV 0x8CEC
+#define GL_COLOR_ATTACHMENT13_NV 0x8CED
+#define GL_COLOR_ATTACHMENT14_NV 0x8CEE
+#define GL_COLOR_ATTACHMENT15_NV 0x8CEF
+
+typedef void (GLAPIENTRY * PFNGLDRAWBUFFERSNVPROC) (GLsizei n, const GLenum* bufs);
+
+#define glDrawBuffersNV GLEW_GET_FUN(__glewDrawBuffersNV)
+
+#define GLEW_NV_draw_buffers GLEW_GET_VAR(__GLEW_NV_draw_buffers)
+
+#endif /* !GL_NV_draw_buffers && !GLEW_NO_ES*/
+
+/* ---------------------- GL_NV_fbo_color_attachments ---------------------- */
+
+#if !defined(GL_NV_fbo_color_attachments) && !defined(GLEW_NO_ES)
+#define GL_NV_fbo_color_attachments 1
+
+#define GL_MAX_COLOR_ATTACHMENTS_NV 0x8CDF
+#define GL_COLOR_ATTACHMENT0_NV 0x8CE0
+#define GL_COLOR_ATTACHMENT1_NV 0x8CE1
+#define GL_COLOR_ATTACHMENT2_NV 0x8CE2
+#define GL_COLOR_ATTACHMENT3_NV 0x8CE3
+#define GL_COLOR_ATTACHMENT4_NV 0x8CE4
+#define GL_COLOR_ATTACHMENT5_NV 0x8CE5
+#define GL_COLOR_ATTACHMENT6_NV 0x8CE6
+#define GL_COLOR_ATTACHMENT7_NV 0x8CE7
+#define GL_COLOR_ATTACHMENT8_NV 0x8CE8
+#define GL_COLOR_ATTACHMENT9_NV 0x8CE9
+#define GL_COLOR_ATTACHMENT10_NV 0x8CEA
+#define GL_COLOR_ATTACHMENT11_NV 0x8CEB
+#define GL_COLOR_ATTACHMENT12_NV 0x8CEC
+#define GL_COLOR_ATTACHMENT13_NV 0x8CED
+#define GL_COLOR_ATTACHMENT14_NV 0x8CEE
+#define GL_COLOR_ATTACHMENT15_NV 0x8CEF
+
+#define GLEW_NV_fbo_color_attachments GLEW_GET_VAR(__GLEW_NV_fbo_color_attachments)
+
+#endif /* !GL_NV_fbo_color_attachments && !GLEW_NO_ES*/
+
+/* -------------------------- GL_NV_pack_subimage -------------------------- */
+
+#if !defined(GL_NV_pack_subimage) && !defined(GLEW_NO_ES)
+#define GL_NV_pack_subimage 1
+
+#define GL_PACK_ROW_LENGTH_NV 0x0D02
+#define GL_PACK_SKIP_ROWS_NV 0x0D03
+#define GL_PACK_SKIP_PIXELS_NV 0x0D04
+
+#define GLEW_NV_pack_subimage GLEW_GET_VAR(__GLEW_NV_pack_subimage)
+
+#endif /* !GL_NV_pack_subimage && !GLEW_NO_ES*/
+
+/* --------------------------- GL_NV_packed_float -------------------------- */
+
+#if !defined(GL_NV_packed_float) && !defined(GLEW_NO_ES)
+#define GL_NV_packed_float 1
+
+#define GL_R11F_G11F_B10F_NV 0x8C3A
+#define GL_UNSIGNED_INT_10F_11F_11F_REV_NV 0x8C3B
+
+#define GLEW_NV_packed_float GLEW_GET_VAR(__GLEW_NV_packed_float)
+
+#endif /* !GL_NV_packed_float && !GLEW_NO_ES*/
+
+/* ----------------------- GL_NV_packed_float_linear ----------------------- */
+
+#if !defined(GL_NV_packed_float_linear) && !defined(GLEW_NO_ES)
+#define GL_NV_packed_float_linear 1
+
+#define GL_R11F_G11F_B10F_NV 0x8C3A
+#define GL_UNSIGNED_INT_10F_11F_11F_REV_NV 0x8C3B
+
+#define GLEW_NV_packed_float_linear GLEW_GET_VAR(__GLEW_NV_packed_float_linear)
+
+#endif /* !GL_NV_packed_float_linear && !GLEW_NO_ES*/
+
+/* ----------------------- GL_NV_pixel_buffer_object ----------------------- */
+
+#if !defined(GL_NV_pixel_buffer_object) && !defined(GLEW_NO_ES)
+#define GL_NV_pixel_buffer_object 1
+
+#define GL_PIXEL_PACK_BUFFER_NV 0x88EB
+#define GL_PIXEL_UNPACK_BUFFER_NV 0x88EC
+#define GL_PIXEL_PACK_BUFFER_BINDING_NV 0x88ED
+#define GL_PIXEL_UNPACK_BUFFER_BINDING_NV 0x88EF
+
+#define GLEW_NV_pixel_buffer_object GLEW_GET_VAR(__GLEW_NV_pixel_buffer_object)
+
+#endif /* !GL_NV_pixel_buffer_object && !GLEW_NO_ES*/
+
+/* ------------------------- GL_NV_platform_binary ------------------------- */
+
+#if !defined(GL_NV_platform_binary) && !defined(GLEW_NO_ES)
+#define GL_NV_platform_binary 1
+
+#define GL_NVIDIA_PLATFORM_BINARY_NV 0x890B
+
+#define GLEW_NV_platform_binary GLEW_GET_VAR(__GLEW_NV_platform_binary)
+
+#endif /* !GL_NV_platform_binary && !GLEW_NO_ES*/
+
+/* --------------------------- GL_NV_read_buffer --------------------------- */
+
+#if !defined(GL_NV_read_buffer) && !defined(GLEW_NO_ES)
+#define GL_NV_read_buffer 1
+
+#define GL_READ_BUFFER_NV 0x0C02
+
+typedef void (GLAPIENTRY * PFNGLREADBUFFERNVPROC) (GLenum mode);
+
+#define glReadBufferNV GLEW_GET_FUN(__glewReadBufferNV)
+
+#define GLEW_NV_read_buffer GLEW_GET_VAR(__GLEW_NV_read_buffer)
+
+#endif /* !GL_NV_read_buffer && !GLEW_NO_ES*/
+
+/* ------------------------ GL_NV_read_buffer_front ------------------------ */
+
+#if !defined(GL_NV_read_buffer_front) && !defined(GLEW_NO_ES)
+#define GL_NV_read_buffer_front 1
+
+#define GLEW_NV_read_buffer_front GLEW_GET_VAR(__GLEW_NV_read_buffer_front)
+
+#endif /* !GL_NV_read_buffer_front && !GLEW_NO_ES*/
+
+/* ---------------------------- GL_NV_read_depth --------------------------- */
+
+#if !defined(GL_NV_read_depth) && !defined(GLEW_NO_ES)
+#define GL_NV_read_depth 1
+
+#define GLEW_NV_read_depth GLEW_GET_VAR(__GLEW_NV_read_depth)
+
+#endif /* !GL_NV_read_depth && !GLEW_NO_ES*/
+
+/* ------------------------ GL_NV_read_depth_stencil ----------------------- */
+
+#if !defined(GL_NV_read_depth_stencil) && !defined(GLEW_NO_ES)
+#define GL_NV_read_depth_stencil 1
+
+#define GLEW_NV_read_depth_stencil GLEW_GET_VAR(__GLEW_NV_read_depth_stencil)
+
+#endif /* !GL_NV_read_depth_stencil && !GLEW_NO_ES*/
+
+/* --------------------------- GL_NV_read_stencil -------------------------- */
+
+#if !defined(GL_NV_read_stencil) && !defined(GLEW_NO_ES)
+#define GL_NV_read_stencil 1
+
+#define GLEW_NV_read_stencil GLEW_GET_VAR(__GLEW_NV_read_stencil)
+
+#endif /* !GL_NV_read_stencil && !GLEW_NO_ES*/
+
+/* -------------------------- GL_NV_texture_array -------------------------- */
+
+#if !defined(GL_NV_texture_array) && !defined(GLEW_NO_ES)
+#define GL_NV_texture_array 1
+
+#define GL_UNPACK_SKIP_IMAGES_NV 0x806D
+#define GL_UNPACK_IMAGE_HEIGHT_NV 0x806E
+#define GL_MAX_ARRAY_TEXTURE_LAYERS_NV 0x88FF
+#define GL_TEXTURE_2D_ARRAY_NV 0x8C1A
+#define GL_TEXTURE_BINDING_2D_ARRAY_NV 0x8C1D
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER_NV 0x8CD4
+#define GL_SAMPLER_2D_ARRAY_NV 0x8DC1
+
+typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXIMAGE3DNVPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void* data);
+typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXSUBIMAGE3DNVPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void* data);
+typedef void (GLAPIENTRY * PFNGLCOPYTEXSUBIMAGE3DNVPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+typedef void (GLAPIENTRY * PFNGLFRAMEBUFFERTEXTURELAYERNVPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer);
+typedef void (GLAPIENTRY * PFNGLTEXIMAGE3DNVPROC) (GLenum target, GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void* pixels);
+typedef void (GLAPIENTRY * PFNGLTEXSUBIMAGE3DNVPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void* pixels);
+
+#define glCompressedTexImage3DNV GLEW_GET_FUN(__glewCompressedTexImage3DNV)
+#define glCompressedTexSubImage3DNV GLEW_GET_FUN(__glewCompressedTexSubImage3DNV)
+#define glCopyTexSubImage3DNV GLEW_GET_FUN(__glewCopyTexSubImage3DNV)
+#define glFramebufferTextureLayerNV GLEW_GET_FUN(__glewFramebufferTextureLayerNV)
+#define glTexImage3DNV GLEW_GET_FUN(__glewTexImage3DNV)
+#define glTexSubImage3DNV GLEW_GET_FUN(__glewTexSubImage3DNV)
+
+#define GLEW_NV_texture_array GLEW_GET_VAR(__GLEW_NV_texture_array)
+
+#endif /* !GL_NV_texture_array && !GLEW_NO_ES*/
+
+/* --------------------- GL_NV_texture_compression_latc -------------------- */
+
+#if !defined(GL_NV_texture_compression_latc) && !defined(GLEW_NO_ES)
+#define GL_NV_texture_compression_latc 1
+
+#define GL_COMPRESSED_LUMINANCE_LATC1_NV 0x8C70
+#define GL_COMPRESSED_SIGNED_LUMINANCE_LATC1_NV 0x8C71
+#define GL_COMPRESSED_LUMINANCE_ALPHA_LATC2_NV 0x8C72
+#define GL_COMPRESSED_SIGNED_LUMINANCE_ALPHA_LATC2_NV 0x8C73
+
+#define GLEW_NV_texture_compression_latc GLEW_GET_VAR(__GLEW_NV_texture_compression_latc)
+
+#endif /* !GL_NV_texture_compression_latc && !GLEW_NO_ES*/
+
+/* --------------------- GL_NV_texture_compression_s3tc -------------------- */
+
+#if !defined(GL_NV_texture_compression_s3tc) && !defined(GLEW_NO_ES)
+#define GL_NV_texture_compression_s3tc 1
+
+#define GL_COMPRESSED_RGB_S3TC_DXT1_NV 0x83F0
+#define GL_COMPRESSED_RGBA_S3TC_DXT1_NV 0x83F1
+#define GL_COMPRESSED_RGBA_S3TC_DXT3_NV 0x83F2
+#define GL_COMPRESSED_RGBA_S3TC_DXT5_NV 0x83F3
+
+#define GLEW_NV_texture_compression_s3tc GLEW_GET_VAR(__GLEW_NV_texture_compression_s3tc)
+
+#endif /* !GL_NV_texture_compression_s3tc && !GLEW_NO_ES*/
+
+/* ----------------- GL_NV_texture_compression_s3tc_update ----------------- */
+
+#if !defined(GL_NV_texture_compression_s3tc_update) && !defined(GLEW_NO_ES)
+#define GL_NV_texture_compression_s3tc_update 1
+
+#define GLEW_NV_texture_compression_s3tc_update GLEW_GET_VAR(__GLEW_NV_texture_compression_s3tc_update)
+
+#endif /* !GL_NV_texture_compression_s3tc_update && !GLEW_NO_ES*/
+
+/* ---------------------- GL_NV_texture_npot_2D_mipmap --------------------- */
+
+#if !defined(GL_NV_texture_npot_2D_mipmap) && !defined(GLEW_NO_ES)
+#define GL_NV_texture_npot_2D_mipmap 1
+
+#define GLEW_NV_texture_npot_2D_mipmap GLEW_GET_VAR(__GLEW_NV_texture_npot_2D_mipmap)
+
+#endif /* !GL_NV_texture_npot_2D_mipmap && !GLEW_NO_ES*/
+
+/* ---------------------------- GL_OES_EGL_image --------------------------- */
+
+#if !defined(GL_OES_EGL_image) && !defined(GLEW_NO_ES)
+#define GL_OES_EGL_image 1
+
+typedef void* GLeglImageOES;
+
+typedef void (GLAPIENTRY * PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC) (GLenum target, GLeglImageOES image);
+typedef void (GLAPIENTRY * PFNGLEGLIMAGETARGETTEXTURE2DOESPROC) (GLenum target, GLeglImageOES image);
+
+#define glEGLImageTargetRenderbufferStorageOES GLEW_GET_FUN(__glewEGLImageTargetRenderbufferStorageOES)
+#define glEGLImageTargetTexture2DOES GLEW_GET_FUN(__glewEGLImageTargetTexture2DOES)
+
+#define GLEW_OES_EGL_image GLEW_GET_VAR(__GLEW_OES_EGL_image)
+
+#endif /* !GL_OES_EGL_image && !GLEW_NO_ES*/
+
+/* ----------------------- GL_OES_EGL_image_external ----------------------- */
+
+#if !defined(GL_OES_EGL_image_external) && !defined(GLEW_NO_ES)
+#define GL_OES_EGL_image_external 1
+
+#define GL_TEXTURE_EXTERNAL_OES 0x8D65
+#define GL_SAMPLER_EXTERNAL_OES 0x8D66
+#define GL_TEXTURE_BINDING_EXTERNAL_OES 0x8D67
+#define GL_REQUIRED_TEXTURE_IMAGE_UNITS_OES 0x8D68
+
+#define GLEW_OES_EGL_image_external GLEW_GET_VAR(__GLEW_OES_EGL_image_external)
+
+#endif /* !GL_OES_EGL_image_external && !GLEW_NO_ES*/
+
+/* ---------------------------- GL_OES_EGL_sync ---------------------------- */
+
+#if !defined(GL_OES_EGL_sync) && !defined(GLEW_NO_ES)
+#define GL_OES_EGL_sync 1
+
+#define GLEW_OES_EGL_sync GLEW_GET_VAR(__GLEW_OES_EGL_sync)
+
+#endif /* !GL_OES_EGL_sync && !GLEW_NO_ES*/
+
+/* --------------------- GL_OES_blend_equation_separate -------------------- */
+
+#if !defined(GL_OES_blend_equation_separate) && !defined(GLEW_NO_ES)
+#define GL_OES_blend_equation_separate 1
+
+#define GL_BLEND_EQUATION_RGB_OES 0x8009
+#define GL_BLEND_EQUATION_ALPHA_OES 0x883D
+
+typedef void (GLAPIENTRY * PFNGLBLENDEQUATIONSEPARATEOESPROC) (GLenum modeRGB, GLenum modeAlpha);
+
+#define glBlendEquationSeparateOES GLEW_GET_FUN(__glewBlendEquationSeparateOES)
+
+#define GLEW_OES_blend_equation_separate GLEW_GET_VAR(__GLEW_OES_blend_equation_separate)
+
+#endif /* !GL_OES_blend_equation_separate && !GLEW_NO_ES*/
+
+/* ----------------------- GL_OES_blend_func_separate ---------------------- */
+
+#if !defined(GL_OES_blend_func_separate) && !defined(GLEW_NO_ES)
+#define GL_OES_blend_func_separate 1
+
+#define GL_BLEND_DST_RGB_OES 0x80C8
+#define GL_BLEND_SRC_RGB_OES 0x80C9
+#define GL_BLEND_DST_ALPHA_OES 0x80CA
+#define GL_BLEND_SRC_ALPHA_OES 0x80CB
+
+typedef void (GLAPIENTRY * PFNGLBLENDFUNCSEPARATEOESPROC) (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha);
+
+#define glBlendFuncSeparateOES GLEW_GET_FUN(__glewBlendFuncSeparateOES)
+
+#define GLEW_OES_blend_func_separate GLEW_GET_VAR(__GLEW_OES_blend_func_separate)
+
+#endif /* !GL_OES_blend_func_separate && !GLEW_NO_ES*/
+
+/* ------------------------- GL_OES_blend_subtract ------------------------- */
+
+#if !defined(GL_OES_blend_subtract) && !defined(GLEW_NO_ES)
+#define GL_OES_blend_subtract 1
+
+#define GL_FUNC_ADD_OES 0x8006
+#define GL_BLEND_EQUATION_OES 0x8009
+#define GL_FUNC_SUBTRACT_OES 0x800A
+#define GL_FUNC_REVERSE_SUBTRACT_OES 0x800B
+
+typedef void (GLAPIENTRY * PFNGLBLENDEQUATIONOESPROC) (GLenum mode);
+
+#define glBlendEquationOES GLEW_GET_FUN(__glewBlendEquationOES)
+
+#define GLEW_OES_blend_subtract GLEW_GET_VAR(__GLEW_OES_blend_subtract)
+
+#endif /* !GL_OES_blend_subtract && !GLEW_NO_ES*/
+
+/* ------------------ GL_OES_compressed_ETC1_RGB8_texture ------------------ */
+
+#if !defined(GL_OES_compressed_ETC1_RGB8_texture) && !defined(GLEW_NO_ES)
+#define GL_OES_compressed_ETC1_RGB8_texture 1
+
+#define GL_ETC1_RGB8_OES 0x8D64
+
+#define GLEW_OES_compressed_ETC1_RGB8_texture GLEW_GET_VAR(__GLEW_OES_compressed_ETC1_RGB8_texture)
+
+#endif /* !GL_OES_compressed_ETC1_RGB8_texture && !GLEW_NO_ES*/
+
+/* ----------------------------- GL_OES_depth24 ---------------------------- */
+
+#if !defined(GL_OES_depth24) && !defined(GLEW_NO_ES)
+#define GL_OES_depth24 1
+
+#define GL_DEPTH_COMPONENT24_OES 0x81A6
+
+#define GLEW_OES_depth24 GLEW_GET_VAR(__GLEW_OES_depth24)
+
+#endif /* !GL_OES_depth24 && !GLEW_NO_ES*/
+
+/* ----------------------------- GL_OES_depth32 ---------------------------- */
+
+#if !defined(GL_OES_depth32) && !defined(GLEW_NO_ES)
+#define GL_OES_depth32 1
+
+#define GL_DEPTH_COMPONENT32_OES 0x81A7
+
+#define GLEW_OES_depth32 GLEW_GET_VAR(__GLEW_OES_depth32)
+
+#endif /* !GL_OES_depth32 && !GLEW_NO_ES*/
+
+/* -------------------------- GL_OES_depth_texture ------------------------- */
+
+#if !defined(GL_OES_depth_texture) && !defined(GLEW_NO_ES)
+#define GL_OES_depth_texture 1
+
+#define GL_UNSIGNED_SHORT 0x1403
+#define GL_UNSIGNED_INT 0x1405
+#define GL_DEPTH_COMPONENT 0x1902
+
+#define GLEW_OES_depth_texture GLEW_GET_VAR(__GLEW_OES_depth_texture)
+
+#endif /* !GL_OES_depth_texture && !GLEW_NO_ES*/
+
+/* --------------------- GL_OES_depth_texture_cube_map --------------------- */
+
+#if !defined(GL_OES_depth_texture_cube_map) && !defined(GLEW_NO_ES)
+#define GL_OES_depth_texture_cube_map 1
+
+#define GL_UNSIGNED_SHORT 0x1403
+#define GL_UNSIGNED_INT 0x1405
+#define GL_DEPTH_COMPONENT 0x1902
+#define GL_DEPTH_STENCIL_OES 0x84F9
+#define GL_DEPTH24_STENCIL8_OES 0x88F0
+
+#define GLEW_OES_depth_texture_cube_map GLEW_GET_VAR(__GLEW_OES_depth_texture_cube_map)
+
+#endif /* !GL_OES_depth_texture_cube_map && !GLEW_NO_ES*/
+
+/* -------------------------- GL_OES_draw_texture -------------------------- */
+
+#if !defined(GL_OES_draw_texture) && !defined(GLEW_NO_ES)
+#define GL_OES_draw_texture 1
+
+#define GL_TEXTURE_CROP_RECT_OES 0x8B9D
+
+#define GLEW_OES_draw_texture GLEW_GET_VAR(__GLEW_OES_draw_texture)
+
+#endif /* !GL_OES_draw_texture && !GLEW_NO_ES*/
+
+/* ----------------------- GL_OES_element_index_uint ----------------------- */
+
+#if !defined(GL_OES_element_index_uint) && !defined(GLEW_NO_ES)
+#define GL_OES_element_index_uint 1
+
+#define GL_UNSIGNED_INT 0x1405
+
+#define GLEW_OES_element_index_uint GLEW_GET_VAR(__GLEW_OES_element_index_uint)
+
+#endif /* !GL_OES_element_index_uint && !GLEW_NO_ES*/
+
+/* --------------------- GL_OES_extended_matrix_palette -------------------- */
+
+#if !defined(GL_OES_extended_matrix_palette) && !defined(GLEW_NO_ES)
+#define GL_OES_extended_matrix_palette 1
+
+#define GLEW_OES_extended_matrix_palette GLEW_GET_VAR(__GLEW_OES_extended_matrix_palette)
+
+#endif /* !GL_OES_extended_matrix_palette && !GLEW_NO_ES*/
+
+/* ------------------------ GL_OES_fbo_render_mipmap ----------------------- */
+
+#if !defined(GL_OES_fbo_render_mipmap) && !defined(GLEW_NO_ES)
+#define GL_OES_fbo_render_mipmap 1
+
+#define GLEW_OES_fbo_render_mipmap GLEW_GET_VAR(__GLEW_OES_fbo_render_mipmap)
+
+#endif /* !GL_OES_fbo_render_mipmap && !GLEW_NO_ES*/
+
+/* --------------------- GL_OES_fragment_precision_high -------------------- */
+
+#if !defined(GL_OES_fragment_precision_high) && !defined(GLEW_NO_ES)
+#define GL_OES_fragment_precision_high 1
+
+#define GLEW_OES_fragment_precision_high GLEW_GET_VAR(__GLEW_OES_fragment_precision_high)
+
+#endif /* !GL_OES_fragment_precision_high && !GLEW_NO_ES*/
+
+/* ----------------------- GL_OES_framebuffer_object ----------------------- */
+
+#if !defined(GL_OES_framebuffer_object) && !defined(GLEW_NO_ES)
+#define GL_OES_framebuffer_object 1
+
+#define GL_NONE_OES 0
+#define GL_INVALID_FRAMEBUFFER_OPERATION_OES 0x0506
+#define GL_RGBA4_OES 0x8056
+#define GL_RGB5_A1_OES 0x8057
+#define GL_DEPTH_COMPONENT16_OES 0x81A5
+#define GL_MAX_RENDERBUFFER_SIZE_OES 0x84E8
+#define GL_FRAMEBUFFER_BINDING_OES 0x8CA6
+#define GL_RENDERBUFFER_BINDING_OES 0x8CA7
+#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_OES 0x8CD0
+#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_OES 0x8CD1
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL_OES 0x8CD2
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE_OES 0x8CD3
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_3D_ZOFFSET_OES 0x8CD4
+#define GL_FRAMEBUFFER_COMPLETE_OES 0x8CD5
+#define GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_OES 0x8CD6
+#define GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_OES 0x8CD7
+#define GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_OES 0x8CD9
+#define GL_FRAMEBUFFER_INCOMPLETE_FORMATS_OES 0x8CDA
+#define GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_OES 0x8CDB
+#define GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_OES 0x8CDC
+#define GL_FRAMEBUFFER_UNSUPPORTED_OES 0x8CDD
+#define GL_COLOR_ATTACHMENT0_OES 0x8CE0
+#define GL_DEPTH_ATTACHMENT_OES 0x8D00
+#define GL_STENCIL_ATTACHMENT_OES 0x8D20
+#define GL_FRAMEBUFFER_OES 0x8D40
+#define GL_RENDERBUFFER_OES 0x8D41
+#define GL_RENDERBUFFER_WIDTH_OES 0x8D42
+#define GL_RENDERBUFFER_HEIGHT_OES 0x8D43
+#define GL_RENDERBUFFER_INTERNAL_FORMAT_OES 0x8D44
+#define GL_STENCIL_INDEX1_OES 0x8D46
+#define GL_STENCIL_INDEX4_OES 0x8D47
+#define GL_STENCIL_INDEX8_OES 0x8D48
+#define GL_RENDERBUFFER_RED_SIZE_OES 0x8D50
+#define GL_RENDERBUFFER_GREEN_SIZE_OES 0x8D51
+#define GL_RENDERBUFFER_BLUE_SIZE_OES 0x8D52
+#define GL_RENDERBUFFER_ALPHA_SIZE_OES 0x8D53
+#define GL_RENDERBUFFER_DEPTH_SIZE_OES 0x8D54
+#define GL_RENDERBUFFER_STENCIL_SIZE_OES 0x8D55
+#define GL_RGB565_OES 0x8D62
+
+typedef void (GLAPIENTRY * PFNGLBINDFRAMEBUFFEROESPROC) (GLenum target, GLuint framebuffer);
+typedef void (GLAPIENTRY * PFNGLBINDRENDERBUFFEROESPROC) (GLenum target, GLuint renderbuffer);
+typedef GLenum (GLAPIENTRY * PFNGLCHECKFRAMEBUFFERSTATUSOESPROC) (GLenum target);
+typedef void (GLAPIENTRY * PFNGLDELETEFRAMEBUFFERSOESPROC) (GLsizei n, const GLuint* framebuffers);
+typedef void (GLAPIENTRY * PFNGLDELETERENDERBUFFERSOESPROC) (GLsizei n, const GLuint* renderbuffers);
+typedef void (GLAPIENTRY * PFNGLFRAMEBUFFERRENDERBUFFEROESPROC) (GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer);
+typedef void (GLAPIENTRY * PFNGLFRAMEBUFFERTEXTURE2DOESPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
+typedef void (GLAPIENTRY * PFNGLGENFRAMEBUFFERSOESPROC) (GLsizei n, GLuint* framebuffers);
+typedef void (GLAPIENTRY * PFNGLGENRENDERBUFFERSOESPROC) (GLsizei n, GLuint* renderbuffers);
+typedef void (GLAPIENTRY * PFNGLGENERATEMIPMAPOESPROC) (GLenum target);
+typedef void (GLAPIENTRY * PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVOESPROC) (GLenum target, GLenum attachment, GLenum pname, GLint* params);
+typedef void (GLAPIENTRY * PFNGLGETRENDERBUFFERPARAMETERIVOESPROC) (GLenum target, GLenum pname, GLint* params);
+typedef GLboolean (GLAPIENTRY * PFNGLISFRAMEBUFFEROESPROC) (GLuint framebuffer);
+typedef GLboolean (GLAPIENTRY * PFNGLISRENDERBUFFEROESPROC) (GLuint renderbuffer);
+typedef void (GLAPIENTRY * PFNGLRENDERBUFFERSTORAGEOESPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
+
+#define glBindFramebufferOES GLEW_GET_FUN(__glewBindFramebufferOES)
+#define glBindRenderbufferOES GLEW_GET_FUN(__glewBindRenderbufferOES)
+#define glCheckFramebufferStatusOES GLEW_GET_FUN(__glewCheckFramebufferStatusOES)
+#define glDeleteFramebuffersOES GLEW_GET_FUN(__glewDeleteFramebuffersOES)
+#define glDeleteRenderbuffersOES GLEW_GET_FUN(__glewDeleteRenderbuffersOES)
+#define glFramebufferRenderbufferOES GLEW_GET_FUN(__glewFramebufferRenderbufferOES)
+#define glFramebufferTexture2DOES GLEW_GET_FUN(__glewFramebufferTexture2DOES)
+#define glGenFramebuffersOES GLEW_GET_FUN(__glewGenFramebuffersOES)
+#define glGenRenderbuffersOES GLEW_GET_FUN(__glewGenRenderbuffersOES)
+#define glGenerateMipmapOES GLEW_GET_FUN(__glewGenerateMipmapOES)
+#define glGetFramebufferAttachmentParameterivOES GLEW_GET_FUN(__glewGetFramebufferAttachmentParameterivOES)
+#define glGetRenderbufferParameterivOES GLEW_GET_FUN(__glewGetRenderbufferParameterivOES)
+#define glIsFramebufferOES GLEW_GET_FUN(__glewIsFramebufferOES)
+#define glIsRenderbufferOES GLEW_GET_FUN(__glewIsRenderbufferOES)
+#define glRenderbufferStorageOES GLEW_GET_FUN(__glewRenderbufferStorageOES)
+
+#define GLEW_OES_framebuffer_object GLEW_GET_VAR(__GLEW_OES_framebuffer_object)
+
+#endif /* !GL_OES_framebuffer_object && !GLEW_NO_ES*/
+
+/* ----------------------- GL_OES_get_program_binary ----------------------- */
+
+#if !defined(GL_OES_get_program_binary) && !defined(GLEW_NO_ES)
+#define GL_OES_get_program_binary 1
+
+#define GL_PROGRAM_BINARY_LENGTH_OES 0x8741
+#define GL_NUM_PROGRAM_BINARY_FORMATS_OES 0x87FE
+#define GL_PROGRAM_BINARY_FORMATS_OES 0x87FF
+
+typedef void (GLAPIENTRY * PFNGLGETPROGRAMBINARYOESPROC) (GLuint program, GLsizei bufSize, GLsizei* length, GLenum *binaryFormat, GLvoid*binary);
+typedef void (GLAPIENTRY * PFNGLPROGRAMBINARYOESPROC) (GLuint program, GLenum binaryFormat, const void* binary, GLint length);
+
+#define glGetProgramBinaryOES GLEW_GET_FUN(__glewGetProgramBinaryOES)
+#define glProgramBinaryOES GLEW_GET_FUN(__glewProgramBinaryOES)
+
+#define GLEW_OES_get_program_binary GLEW_GET_VAR(__GLEW_OES_get_program_binary)
+
+#endif /* !GL_OES_get_program_binary && !GLEW_NO_ES*/
+
+/* ---------------------------- GL_OES_mapbuffer --------------------------- */
+
+#if !defined(GL_OES_mapbuffer) && !defined(GLEW_NO_ES)
+#define GL_OES_mapbuffer 1
+
+#define GL_WRITE_ONLY_OES 0x88B9
+#define GL_BUFFER_ACCESS_OES 0x88BB
+#define GL_BUFFER_MAPPED_OES 0x88BC
+#define GL_BUFFER_MAP_POINTER_OES 0x88BD
+
+typedef void (GLAPIENTRY * PFNGLGETBUFFERPOINTERVOESPROC) (GLenum target, GLenum pname, void** params);
+typedef GLvoid * (GLAPIENTRY * PFNGLMAPBUFFEROESPROC) (GLenum target, GLenum access);
+typedef GLboolean (GLAPIENTRY * PFNGLUNMAPBUFFEROESPROC) (GLenum target);
+
+#define glGetBufferPointervOES GLEW_GET_FUN(__glewGetBufferPointervOES)
+#define glMapBufferOES GLEW_GET_FUN(__glewMapBufferOES)
+#define glUnmapBufferOES GLEW_GET_FUN(__glewUnmapBufferOES)
+
+#define GLEW_OES_mapbuffer GLEW_GET_VAR(__GLEW_OES_mapbuffer)
+
+#endif /* !GL_OES_mapbuffer && !GLEW_NO_ES*/
+
+/* --------------------------- GL_OES_matrix_get --------------------------- */
+
+#if !defined(GL_OES_matrix_get) && !defined(GLEW_NO_ES)
+#define GL_OES_matrix_get 1
+
+#define GL_PROJECTION_MATRIX_FLOAT_AS_INT_BITS_OES 0x898
+#define GL_MODELVIEW_MATRIX_FLOAT_AS_INT_BITS_OES 0x898
+#define GL_TEXTURE_MATRIX_FLOAT_AS_INT_BITS_OES 0x898
+
+#define GLEW_OES_matrix_get GLEW_GET_VAR(__GLEW_OES_matrix_get)
+
+#endif /* !GL_OES_matrix_get && !GLEW_NO_ES*/
+
+/* ------------------------- GL_OES_matrix_palette ------------------------- */
+
+#if !defined(GL_OES_matrix_palette) && !defined(GLEW_NO_ES)
+#define GL_OES_matrix_palette 1
+
+#define GL_MAX_VERTEX_UNITS_OES 0x86A4
+#define GL_WEIGHT_ARRAY_TYPE_OES 0x86A9
+#define GL_WEIGHT_ARRAY_STRIDE_OES 0x86AA
+#define GL_WEIGHT_ARRAY_SIZE_OES 0x86AB
+#define GL_WEIGHT_ARRAY_POINTER_OES 0x86AC
+#define GL_WEIGHT_ARRAY_OES 0x86AD
+#define GL_MATRIX_PALETTE_OES 0x8840
+#define GL_MAX_PALETTE_MATRICES_OES 0x8842
+#define GL_CURRENT_PALETTE_MATRIX_OES 0x8843
+#define GL_MATRIX_INDEX_ARRAY_OES 0x8844
+#define GL_MATRIX_INDEX_ARRAY_SIZE_OES 0x8846
+#define GL_MATRIX_INDEX_ARRAY_TYPE_OES 0x8847
+#define GL_MATRIX_INDEX_ARRAY_STRIDE_OES 0x8848
+#define GL_MATRIX_INDEX_ARRAY_POINTER_OES 0x8849
+#define GL_WEIGHT_ARRAY_BUFFER_BINDING_OES 0x889E
+#define GL_MATRIX_INDEX_ARRAY_BUFFER_BINDING_OES 0x8B9E
+
+typedef void (GLAPIENTRY * PFNGLCURRENTPALETTEMATRIXOESPROC) (GLuint index);
+typedef void (GLAPIENTRY * PFNGLMATRIXINDEXPOINTEROESPROC) (GLint size, GLenum type, GLsizei stride, void* pointer);
+typedef void (GLAPIENTRY * PFNGLWEIGHTPOINTEROESPROC) (GLint size, GLenum type, GLsizei stride, void* pointer);
+
+#define glCurrentPaletteMatrixOES GLEW_GET_FUN(__glewCurrentPaletteMatrixOES)
+#define glMatrixIndexPointerOES GLEW_GET_FUN(__glewMatrixIndexPointerOES)
+#define glWeightPointerOES GLEW_GET_FUN(__glewWeightPointerOES)
+
+#define GLEW_OES_matrix_palette GLEW_GET_VAR(__GLEW_OES_matrix_palette)
+
+#endif /* !GL_OES_matrix_palette && !GLEW_NO_ES*/
+
+/* ---------------------- GL_OES_packed_depth_stencil ---------------------- */
+
+#if !defined(GL_OES_packed_depth_stencil) && !defined(GLEW_NO_ES)
+#define GL_OES_packed_depth_stencil 1
+
+#define GL_DEPTH_STENCIL_OES 0x84F9
+#define GL_UNSIGNED_INT_24_8_OES 0x84FA
+#define GL_DEPTH24_STENCIL8_OES 0x88F0
+
+#define GLEW_OES_packed_depth_stencil GLEW_GET_VAR(__GLEW_OES_packed_depth_stencil)
+
+#endif /* !GL_OES_packed_depth_stencil && !GLEW_NO_ES*/
+
+/* ------------------------ GL_OES_point_size_array ------------------------ */
+
+#if !defined(GL_OES_point_size_array) && !defined(GLEW_NO_ES)
+#define GL_OES_point_size_array 1
+
+#define GL_POINT_SIZE_ARRAY_TYPE_OES 0x898A
+#define GL_POINT_SIZE_ARRAY_STRIDE_OES 0x898B
+#define GL_POINT_SIZE_ARRAY_POINTER_OES 0x898C
+#define GL_POINT_SIZE_ARRAY_OES 0x8B9C
+#define GL_POINT_SIZE_ARRAY_BUFFER_BINDING_OES 0x8B9F
+
+typedef void (GLAPIENTRY * PFNGLPOINTSIZEPOINTEROESPROC) (GLenum type, GLsizei stride, const void* ptr);
+
+#define glPointSizePointerOES GLEW_GET_FUN(__glewPointSizePointerOES)
+
+#define GLEW_OES_point_size_array GLEW_GET_VAR(__GLEW_OES_point_size_array)
+
+#endif /* !GL_OES_point_size_array && !GLEW_NO_ES*/
+
+/* -------------------------- GL_OES_point_sprite -------------------------- */
+
+#if !defined(GL_OES_point_sprite) && !defined(GLEW_NO_ES)
+#define GL_OES_point_sprite 1
+
+#define GL_POINT_SPRITE_OES 0x8861
+#define GL_COORD_REPLACE_OES 0x8862
+
+#define GLEW_OES_point_sprite GLEW_GET_VAR(__GLEW_OES_point_sprite)
+
+#endif /* !GL_OES_point_sprite && !GLEW_NO_ES*/
+
+/* --------------------- GL_OES_required_internalformat -------------------- */
+
+#if !defined(GL_OES_required_internalformat) && !defined(GLEW_NO_ES)
+#define GL_OES_required_internalformat 1
+
+#define GL_ALPHA8_OES 0x803C
+#define GL_LUMINANCE8_OES 0x8040
+#define GL_LUMINANCE4_ALPHA4_OES 0x8043
+#define GL_LUMINANCE8_ALPHA8_OES 0x8045
+#define GL_RGB8_OES 0x8051
+#define GL_RGB10_EXT 0x8052
+#define GL_RGBA4_OES 0x8056
+#define GL_RGB5_A1_OES 0x8057
+#define GL_RGBA8_OES 0x8058
+#define GL_RGB10_A2_EXT 0x8059
+#define GL_DEPTH_COMPONENT16_OES 0x81A5
+#define GL_DEPTH_COMPONENT24_OES 0x81A6
+#define GL_DEPTH_COMPONENT32_OES 0x81A7
+#define GL_DEPTH24_STENCIL8_OES 0x88F0
+#define GL_RGB565_OES 0x8D62
+
+#define GLEW_OES_required_internalformat GLEW_GET_VAR(__GLEW_OES_required_internalformat)
+
+#endif /* !GL_OES_required_internalformat && !GLEW_NO_ES*/
+
+/* --------------------------- GL_OES_rgb8_rgba8 --------------------------- */
+
+#if !defined(GL_OES_rgb8_rgba8) && !defined(GLEW_NO_ES)
+#define GL_OES_rgb8_rgba8 1
+
+#define GL_RGB8_OES 0x8051
+#define GL_RGBA8_OES 0x8058
+
+#define GLEW_OES_rgb8_rgba8 GLEW_GET_VAR(__GLEW_OES_rgb8_rgba8)
+
+#endif /* !GL_OES_rgb8_rgba8 && !GLEW_NO_ES*/
+
+/* ---------------------- GL_OES_standard_derivatives ---------------------- */
+
+#if !defined(GL_OES_standard_derivatives) && !defined(GLEW_NO_ES)
+#define GL_OES_standard_derivatives 1
+
+#define GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES 0x8B8B
+
+#define GLEW_OES_standard_derivatives GLEW_GET_VAR(__GLEW_OES_standard_derivatives)
+
+#endif /* !GL_OES_standard_derivatives && !GLEW_NO_ES*/
+
+/* ---------------------------- GL_OES_stencil1 ---------------------------- */
+
+#if !defined(GL_OES_stencil1) && !defined(GLEW_NO_ES)
+#define GL_OES_stencil1 1
+
+#define GL_STENCIL_INDEX1_OES 0x8D46
+
+#define GLEW_OES_stencil1 GLEW_GET_VAR(__GLEW_OES_stencil1)
+
+#endif /* !GL_OES_stencil1 && !GLEW_NO_ES*/
+
+/* ---------------------------- GL_OES_stencil4 ---------------------------- */
+
+#if !defined(GL_OES_stencil4) && !defined(GLEW_NO_ES)
+#define GL_OES_stencil4 1
+
+#define GL_STENCIL_INDEX4_OES 0x8D47
+
+#define GLEW_OES_stencil4 GLEW_GET_VAR(__GLEW_OES_stencil4)
+
+#endif /* !GL_OES_stencil4 && !GLEW_NO_ES*/
+
+/* ---------------------------- GL_OES_stencil8 ---------------------------- */
+
+#if !defined(GL_OES_stencil8) && !defined(GLEW_NO_ES)
+#define GL_OES_stencil8 1
+
+#define GL_STENCIL_INDEX8_OES 0x8D48
+
+#define GLEW_OES_stencil8 GLEW_GET_VAR(__GLEW_OES_stencil8)
+
+#endif /* !GL_OES_stencil8 && !GLEW_NO_ES*/
+
+/* ----------------------- GL_OES_surfaceless_context ---------------------- */
+
+#if !defined(GL_OES_surfaceless_context) && !defined(GLEW_NO_ES)
+#define GL_OES_surfaceless_context 1
+
+#define GL_FRAMEBUFFER_UNDEFINED_OES 0x8219
+
+#define GLEW_OES_surfaceless_context GLEW_GET_VAR(__GLEW_OES_surfaceless_context)
+
+#endif /* !GL_OES_surfaceless_context && !GLEW_NO_ES*/
+
+/* --------------------------- GL_OES_texture_3D --------------------------- */
+
+#if !defined(GL_OES_texture_3D) && !defined(GLEW_NO_ES)
+#define GL_OES_texture_3D 1
+
+#define GL_TEXTURE_BINDING_3D_OES 0x806A
+#define GL_TEXTURE_3D_OES 0x806F
+#define GL_TEXTURE_WRAP_R_OES 0x8072
+#define GL_MAX_3D_TEXTURE_SIZE_OES 0x8073
+#define GL_SAMPLER_3D_OES 0x8B5F
+
+typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXIMAGE3DOESPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void* data);
+typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXSUBIMAGE3DOESPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void* data);
+typedef void (GLAPIENTRY * PFNGLCOPYTEXSUBIMAGE3DOESPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+typedef void (GLAPIENTRY * PFNGLFRAMEBUFFERTEXTURE3DOESPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset);
+typedef void (GLAPIENTRY * PFNGLTEXIMAGE3DOESPROC) (GLenum target, GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void* pixels);
+typedef void (GLAPIENTRY * PFNGLTEXSUBIMAGE3DOESPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void* pixels);
+
+#define glCompressedTexImage3DOES GLEW_GET_FUN(__glewCompressedTexImage3DOES)
+#define glCompressedTexSubImage3DOES GLEW_GET_FUN(__glewCompressedTexSubImage3DOES)
+#define glCopyTexSubImage3DOES GLEW_GET_FUN(__glewCopyTexSubImage3DOES)
+#define glFramebufferTexture3DOES GLEW_GET_FUN(__glewFramebufferTexture3DOES)
+#define glTexImage3DOES GLEW_GET_FUN(__glewTexImage3DOES)
+#define glTexSubImage3DOES GLEW_GET_FUN(__glewTexSubImage3DOES)
+
+#define GLEW_OES_texture_3D GLEW_GET_VAR(__GLEW_OES_texture_3D)
+
+#endif /* !GL_OES_texture_3D && !GLEW_NO_ES*/
+
+/* ------------------------ GL_OES_texture_cube_map ------------------------ */
+
+#if !defined(GL_OES_texture_cube_map) && !defined(GLEW_NO_ES)
+#define GL_OES_texture_cube_map 1
+
+#define GL_TEXTURE_GEN_MODE_OES 0x2500
+#define GL_NORMAL_MAP_OES 0x8511
+#define GL_REFLECTION_MAP_OES 0x8512
+#define GL_TEXTURE_CUBE_MAP_OES 0x8513
+#define GL_TEXTURE_BINDING_CUBE_MAP_OES 0x8514
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_X_OES 0x8515
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_X_OES 0x8516
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_Y_OES 0x8517
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_OES 0x8518
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z_OES 0x8519
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_OES 0x851A
+#define GL_MAX_CUBE_MAP_TEXTURE_SIZE_OES 0x851C
+#define GL_TEXTURE_GEN_STR_OES 0x8D60
+
+typedef void (GLAPIENTRY * PFNGLGETTEXGENFVOESPROC) (GLenum coord, GLenum pname, GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLGETTEXGENIVOESPROC) (GLenum coord, GLenum pname, GLint* params);
+typedef void (GLAPIENTRY * PFNGLGETTEXGENXVOESPROC) (GLenum coord, GLenum pname, GLfixed* params);
+typedef void (GLAPIENTRY * PFNGLTEXGENFOESPROC) (GLenum coord, GLenum pname, GLfloat param);
+typedef void (GLAPIENTRY * PFNGLTEXGENFVOESPROC) (GLenum coord, GLenum pname, const GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLTEXGENIOESPROC) (GLenum coord, GLenum pname, GLint param);
+typedef void (GLAPIENTRY * PFNGLTEXGENIVOESPROC) (GLenum coord, GLenum pname, const GLint* params);
+typedef void (GLAPIENTRY * PFNGLTEXGENXOESPROC) (GLenum coord, GLenum pname, GLfixed param);
+typedef void (GLAPIENTRY * PFNGLTEXGENXVOESPROC) (GLenum coord, GLenum pname, const GLfixed* params);
+
+#define glGetTexGenfvOES GLEW_GET_FUN(__glewGetTexGenfvOES)
+#define glGetTexGenivOES GLEW_GET_FUN(__glewGetTexGenivOES)
+#define glGetTexGenxvOES GLEW_GET_FUN(__glewGetTexGenxvOES)
+#define glTexGenfOES GLEW_GET_FUN(__glewTexGenfOES)
+#define glTexGenfvOES GLEW_GET_FUN(__glewTexGenfvOES)
+#define glTexGeniOES GLEW_GET_FUN(__glewTexGeniOES)
+#define glTexGenivOES GLEW_GET_FUN(__glewTexGenivOES)
+#define glTexGenxOES GLEW_GET_FUN(__glewTexGenxOES)
+#define glTexGenxvOES GLEW_GET_FUN(__glewTexGenxvOES)
+
+#define GLEW_OES_texture_cube_map GLEW_GET_VAR(__GLEW_OES_texture_cube_map)
+
+#endif /* !GL_OES_texture_cube_map && !GLEW_NO_ES*/
+
+/* ---------------------- GL_OES_texture_env_crossbar ---------------------- */
+
+#if !defined(GL_OES_texture_env_crossbar) && !defined(GLEW_NO_ES)
+#define GL_OES_texture_env_crossbar 1
+
+#define GLEW_OES_texture_env_crossbar GLEW_GET_VAR(__GLEW_OES_texture_env_crossbar)
+
+#endif /* !GL_OES_texture_env_crossbar && !GLEW_NO_ES*/
+
+/* --------------------- GL_OES_texture_mirrored_repeat -------------------- */
+
+#if !defined(GL_OES_texture_mirrored_repeat) && !defined(GLEW_NO_ES)
+#define GL_OES_texture_mirrored_repeat 1
+
+#define GL_MIRRORED_REPEAT 0x8370
+
+#define GLEW_OES_texture_mirrored_repeat GLEW_GET_VAR(__GLEW_OES_texture_mirrored_repeat)
+
+#endif /* !GL_OES_texture_mirrored_repeat && !GLEW_NO_ES*/
+
+/* -------------------------- GL_OES_texture_npot -------------------------- */
+
+#if !defined(GL_OES_texture_npot) && !defined(GLEW_NO_ES)
+#define GL_OES_texture_npot 1
+
+#define GLEW_OES_texture_npot GLEW_GET_VAR(__GLEW_OES_texture_npot)
+
+#endif /* !GL_OES_texture_npot && !GLEW_NO_ES*/
+
+/* ----------------------- GL_OES_vertex_array_object ---------------------- */
+
+#if !defined(GL_OES_vertex_array_object) && !defined(GLEW_NO_ES)
+#define GL_OES_vertex_array_object 1
+
+#define GL_VERTEX_ARRAY_BINDING_OES 0x85B5
+
+typedef void (GLAPIENTRY * PFNGLBINDVERTEXARRAYOESPROC) (GLuint array);
+typedef void (GLAPIENTRY * PFNGLDELETEVERTEXARRAYSOESPROC) (GLsizei n, const GLuint* arrays);
+typedef void (GLAPIENTRY * PFNGLGENVERTEXARRAYSOESPROC) (GLsizei n, GLuint* arrays);
+typedef GLboolean (GLAPIENTRY * PFNGLISVERTEXARRAYOESPROC) (GLuint array);
+
+#define glBindVertexArrayOES GLEW_GET_FUN(__glewBindVertexArrayOES)
+#define glDeleteVertexArraysOES GLEW_GET_FUN(__glewDeleteVertexArraysOES)
+#define glGenVertexArraysOES GLEW_GET_FUN(__glewGenVertexArraysOES)
+#define glIsVertexArrayOES GLEW_GET_FUN(__glewIsVertexArrayOES)
+
+#define GLEW_OES_vertex_array_object GLEW_GET_VAR(__GLEW_OES_vertex_array_object)
+
+#endif /* !GL_OES_vertex_array_object && !GLEW_NO_ES*/
+
+/* ------------------------ GL_OES_vertex_half_float ----------------------- */
+
+#if !defined(GL_OES_vertex_half_float) && !defined(GLEW_NO_ES)
+#define GL_OES_vertex_half_float 1
+
+#define GL_HALF_FLOAT_OES 0x8D61
+
+#define GLEW_OES_vertex_half_float GLEW_GET_VAR(__GLEW_OES_vertex_half_float)
+
+#endif /* !GL_OES_vertex_half_float && !GLEW_NO_ES*/
+
+/* --------------------- GL_OES_vertex_type_10_10_10_2 --------------------- */
+
+#if !defined(GL_OES_vertex_type_10_10_10_2) && !defined(GLEW_NO_ES)
+#define GL_OES_vertex_type_10_10_10_2 1
+
+#define GL_UNSIGNED_INT_10_10_10_2_OES 0x8DF6
+#define GL_INT_10_10_10_2_OES 0x8DF7
+
+#define GLEW_OES_vertex_type_10_10_10_2 GLEW_GET_VAR(__GLEW_OES_vertex_type_10_10_10_2)
+
+#endif /* !GL_OES_vertex_type_10_10_10_2 && !GLEW_NO_ES*/
+
+/* --------------------------- GL_QCOM_alpha_test -------------------------- */
+
+#if !defined(GL_QCOM_alpha_test) && !defined(GLEW_NO_ES)
+#define GL_QCOM_alpha_test 1
+
+#define GL_ALPHA_TEST_QCOM 0x0BC0
+#define GL_ALPHA_TEST_FUNC_QCOM 0x0BC1
+#define GL_ALPHA_TEST_REF_QCOM 0x0BC2
+
+typedef void (GLAPIENTRY * PFNGLALPHAFUNCQCOMPROC) (GLenum func, GLclampf ref);
+
+#define glAlphaFuncQCOM GLEW_GET_FUN(__glewAlphaFuncQCOM)
+
+#define GLEW_QCOM_alpha_test GLEW_GET_VAR(__GLEW_QCOM_alpha_test)
+
+#endif /* !GL_QCOM_alpha_test && !GLEW_NO_ES*/
+
+/* ------------------------ GL_QCOM_binning_control ------------------------ */
+
+#if !defined(GL_QCOM_binning_control) && !defined(GLEW_NO_ES)
+#define GL_QCOM_binning_control 1
+
+#define GL_DONT_CARE 0x1100
+#define GL_BINNING_CONTROL_HINT_QCOM 0x8FB0
+#define GL_CPU_OPTIMIZED_QCOM 0x8FB1
+#define GL_GPU_OPTIMIZED_QCOM 0x8FB2
+#define GL_RENDER_DIRECT_TO_FRAMEBUFFER_QCOM 0x8FB3
+
+#define GLEW_QCOM_binning_control GLEW_GET_VAR(__GLEW_QCOM_binning_control)
+
+#endif /* !GL_QCOM_binning_control && !GLEW_NO_ES*/
+
+/* ------------------------- GL_QCOM_driver_control ------------------------ */
+
+#if !defined(GL_QCOM_driver_control) && !defined(GLEW_NO_ES)
+#define GL_QCOM_driver_control 1
+
+typedef void (GLAPIENTRY * PFNGLDISABLEDRIVERCONTROLQCOMPROC) (GLuint driverControl);
+typedef void (GLAPIENTRY * PFNGLENABLEDRIVERCONTROLQCOMPROC) (GLuint driverControl);
+typedef void (GLAPIENTRY * PFNGLGETDRIVERCONTROLSTRINGQCOMPROC) (GLuint driverControl, GLsizei bufSize, GLsizei* length, char *driverControlString);
+typedef void (GLAPIENTRY * PFNGLGETDRIVERCONTROLSQCOMPROC) (GLint* num, GLsizei size, GLuint *driverControls);
+
+#define glDisableDriverControlQCOM GLEW_GET_FUN(__glewDisableDriverControlQCOM)
+#define glEnableDriverControlQCOM GLEW_GET_FUN(__glewEnableDriverControlQCOM)
+#define glGetDriverControlStringQCOM GLEW_GET_FUN(__glewGetDriverControlStringQCOM)
+#define glGetDriverControlsQCOM GLEW_GET_FUN(__glewGetDriverControlsQCOM)
+
+#define GLEW_QCOM_driver_control GLEW_GET_VAR(__GLEW_QCOM_driver_control)
+
+#endif /* !GL_QCOM_driver_control && !GLEW_NO_ES*/
+
+/* -------------------------- GL_QCOM_extended_get ------------------------- */
+
+#if !defined(GL_QCOM_extended_get) && !defined(GLEW_NO_ES)
+#define GL_QCOM_extended_get 1
+
+#define GL_TEXTURE_WIDTH_QCOM 0x8BD2
+#define GL_TEXTURE_HEIGHT_QCOM 0x8BD3
+#define GL_TEXTURE_DEPTH_QCOM 0x8BD4
+#define GL_TEXTURE_INTERNAL_FORMAT_QCOM 0x8BD5
+#define GL_TEXTURE_FORMAT_QCOM 0x8BD6
+#define GL_TEXTURE_TYPE_QCOM 0x8BD7
+#define GL_TEXTURE_IMAGE_VALID_QCOM 0x8BD8
+#define GL_TEXTURE_NUM_LEVELS_QCOM 0x8BD9
+#define GL_TEXTURE_TARGET_QCOM 0x8BDA
+#define GL_TEXTURE_OBJECT_VALID_QCOM 0x8BDB
+#define GL_STATE_RESTORE 0x8BDC
+
+typedef void (GLAPIENTRY * PFNGLEXTGETBUFFERPOINTERVQCOMPROC) (GLenum target, GLvoid** params);
+typedef void (GLAPIENTRY * PFNGLEXTGETBUFFERSQCOMPROC) (GLuint* buffers, GLint maxBuffers, GLint* numBuffers);
+typedef void (GLAPIENTRY * PFNGLEXTGETFRAMEBUFFERSQCOMPROC) (GLuint* framebuffers, GLint maxFramebuffers, GLint* numFramebuffers);
+typedef void (GLAPIENTRY * PFNGLEXTGETRENDERBUFFERSQCOMPROC) (GLuint* renderbuffers, GLint maxRenderbuffers, GLint* numRenderbuffers);
+typedef void (GLAPIENTRY * PFNGLEXTGETTEXLEVELPARAMETERIVQCOMPROC) (GLuint texture, GLenum face, GLint level, GLenum pname, GLint* params);
+typedef void (GLAPIENTRY * PFNGLEXTGETTEXSUBIMAGEQCOMPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, void* texels);
+typedef void (GLAPIENTRY * PFNGLEXTGETTEXTURESQCOMPROC) (GLuint* textures, GLint maxTextures, GLint* numTextures);
+typedef void (GLAPIENTRY * PFNGLEXTTEXOBJECTSTATEOVERRIDEIQCOMPROC) (GLenum target, GLenum pname, GLint param);
+
+#define glExtGetBufferPointervQCOM GLEW_GET_FUN(__glewExtGetBufferPointervQCOM)
+#define glExtGetBuffersQCOM GLEW_GET_FUN(__glewExtGetBuffersQCOM)
+#define glExtGetFramebuffersQCOM GLEW_GET_FUN(__glewExtGetFramebuffersQCOM)
+#define glExtGetRenderbuffersQCOM GLEW_GET_FUN(__glewExtGetRenderbuffersQCOM)
+#define glExtGetTexLevelParameterivQCOM GLEW_GET_FUN(__glewExtGetTexLevelParameterivQCOM)
+#define glExtGetTexSubImageQCOM GLEW_GET_FUN(__glewExtGetTexSubImageQCOM)
+#define glExtGetTexturesQCOM GLEW_GET_FUN(__glewExtGetTexturesQCOM)
+#define glExtTexObjectStateOverrideiQCOM GLEW_GET_FUN(__glewExtTexObjectStateOverrideiQCOM)
+
+#define GLEW_QCOM_extended_get GLEW_GET_VAR(__GLEW_QCOM_extended_get)
+
+#endif /* !GL_QCOM_extended_get && !GLEW_NO_ES*/
+
+/* ------------------------- GL_QCOM_extended_get2 ------------------------- */
+
+#if !defined(GL_QCOM_extended_get2) && !defined(GLEW_NO_ES)
+#define GL_QCOM_extended_get2 1
+
+typedef void (GLAPIENTRY * PFNGLEXTGETPROGRAMBINARYSOURCEQCOMPROC) (GLuint program, GLenum shadertype, char* source, GLint* length);
+typedef void (GLAPIENTRY * PFNGLEXTGETPROGRAMSQCOMPROC) (GLuint* programs, GLint maxPrograms, GLint* numPrograms);
+typedef void (GLAPIENTRY * PFNGLEXTGETSHADERSQCOMPROC) (GLuint* shaders, GLint maxShaders, GLint* numShaders);
+typedef GLboolean (GLAPIENTRY * PFNGLEXTISPROGRAMBINARYQCOMPROC) (GLuint program);
+
+#define glExtGetProgramBinarySourceQCOM GLEW_GET_FUN(__glewExtGetProgramBinarySourceQCOM)
+#define glExtGetProgramsQCOM GLEW_GET_FUN(__glewExtGetProgramsQCOM)
+#define glExtGetShadersQCOM GLEW_GET_FUN(__glewExtGetShadersQCOM)
+#define glExtIsProgramBinaryQCOM GLEW_GET_FUN(__glewExtIsProgramBinaryQCOM)
+
+#define GLEW_QCOM_extended_get2 GLEW_GET_VAR(__GLEW_QCOM_extended_get2)
+
+#endif /* !GL_QCOM_extended_get2 && !GLEW_NO_ES*/
+
+/* ---------------------- GL_QCOM_perfmon_global_mode ---------------------- */
+
+#if !defined(GL_QCOM_perfmon_global_mode) && !defined(GLEW_NO_ES)
+#define GL_QCOM_perfmon_global_mode 1
+
+#define GL_PERFMON_GLOBAL_MODE_QCOM 0x8FA0
+
+#define GLEW_QCOM_perfmon_global_mode GLEW_GET_VAR(__GLEW_QCOM_perfmon_global_mode)
+
+#endif /* !GL_QCOM_perfmon_global_mode && !GLEW_NO_ES*/
+
+/* ------------------------ GL_QCOM_tiled_rendering ------------------------ */
+
+#if !defined(GL_QCOM_tiled_rendering) && !defined(GLEW_NO_ES)
+#define GL_QCOM_tiled_rendering 1
+
+#define GL_COLOR_BUFFER_BIT0_QCOM 0x00000001
+#define GL_COLOR_BUFFER_BIT1_QCOM 0x00000002
+#define GL_COLOR_BUFFER_BIT2_QCOM 0x00000004
+#define GL_COLOR_BUFFER_BIT3_QCOM 0x00000008
+#define GL_COLOR_BUFFER_BIT4_QCOM 0x00000010
+#define GL_COLOR_BUFFER_BIT5_QCOM 0x00000020
+#define GL_COLOR_BUFFER_BIT6_QCOM 0x00000040
+#define GL_COLOR_BUFFER_BIT7_QCOM 0x00000080
+#define GL_DEPTH_BUFFER_BIT0_QCOM 0x00000100
+#define GL_DEPTH_BUFFER_BIT1_QCOM 0x00000200
+#define GL_DEPTH_BUFFER_BIT2_QCOM 0x00000400
+#define GL_DEPTH_BUFFER_BIT3_QCOM 0x00000800
+#define GL_DEPTH_BUFFER_BIT4_QCOM 0x00001000
+#define GL_DEPTH_BUFFER_BIT5_QCOM 0x00002000
+#define GL_DEPTH_BUFFER_BIT6_QCOM 0x00004000
+#define GL_DEPTH_BUFFER_BIT7_QCOM 0x00008000
+#define GL_STENCIL_BUFFER_BIT0_QCOM 0x00010000
+#define GL_STENCIL_BUFFER_BIT1_QCOM 0x00020000
+#define GL_STENCIL_BUFFER_BIT2_QCOM 0x00040000
+#define GL_STENCIL_BUFFER_BIT3_QCOM 0x00080000
+#define GL_STENCIL_BUFFER_BIT4_QCOM 0x00100000
+#define GL_STENCIL_BUFFER_BIT5_QCOM 0x00200000
+#define GL_STENCIL_BUFFER_BIT6_QCOM 0x00400000
+#define GL_STENCIL_BUFFER_BIT7_QCOM 0x00800000
+#define GL_MULTISAMPLE_BUFFER_BIT0_QCOM 0x01000000
+#define GL_MULTISAMPLE_BUFFER_BIT1_QCOM 0x02000000
+#define GL_MULTISAMPLE_BUFFER_BIT2_QCOM 0x04000000
+#define GL_MULTISAMPLE_BUFFER_BIT3_QCOM 0x08000000
+#define GL_MULTISAMPLE_BUFFER_BIT4_QCOM 0x10000000
+#define GL_MULTISAMPLE_BUFFER_BIT5_QCOM 0x20000000
+#define GL_MULTISAMPLE_BUFFER_BIT6_QCOM 0x40000000
+#define GL_MULTISAMPLE_BUFFER_BIT7_QCOM 0x80000000
+
+typedef void (GLAPIENTRY * PFNGLENDTILINGQCOMPROC) (GLbitfield preserveMask);
+typedef void (GLAPIENTRY * PFNGLSTARTTILINGQCOMPROC) (GLuint x, GLuint y, GLuint width, GLuint height, GLbitfield preserveMask);
+
+#define glEndTilingQCOM GLEW_GET_FUN(__glewEndTilingQCOM)
+#define glStartTilingQCOM GLEW_GET_FUN(__glewStartTilingQCOM)
+
+#define GLEW_QCOM_tiled_rendering GLEW_GET_VAR(__GLEW_QCOM_tiled_rendering)
+
+#endif /* !GL_QCOM_tiled_rendering && !GLEW_NO_ES*/
+
+/* ---------------------- GL_QCOM_writeonly_rendering ---------------------- */
+
+#if !defined(GL_QCOM_writeonly_rendering) && !defined(GLEW_NO_ES)
+#define GL_QCOM_writeonly_rendering 1
+
+#define GL_WRITEONLY_RENDERING_QCOM 0x8823
+
+#define GLEW_QCOM_writeonly_rendering GLEW_GET_VAR(__GLEW_QCOM_writeonly_rendering)
+
+#endif /* !GL_QCOM_writeonly_rendering && !GLEW_NO_ES*/
+
+/* ------------------------ GL_SUN_multi_draw_arrays ----------------------- */
+
+#if !defined(GL_SUN_multi_draw_arrays) && !defined(GLEW_NO_ES)
+#define GL_SUN_multi_draw_arrays 1
+
+typedef void (GLAPIENTRY * PFNGLMULTIDRAWARRAYSSUNPROC) (GLenum mode, const GLint* first, const GLsizei *count, GLsizei primcount);
+typedef void (GLAPIENTRY * PFNGLMULTIDRAWELEMENTSSUNPROC) (GLenum mode, GLsizei* count, GLenum type, const GLvoid **indices, GLsizei primcount);
+
+#define glMultiDrawArraysSUN GLEW_GET_FUN(__glewMultiDrawArraysSUN)
+#define glMultiDrawElementsSUN GLEW_GET_FUN(__glewMultiDrawElementsSUN)
+
+#define GLEW_SUN_multi_draw_arrays GLEW_GET_VAR(__GLEW_SUN_multi_draw_arrays)
+
+#endif /* !GL_SUN_multi_draw_arrays && !GLEW_NO_ES*/
+
+/* --------------------------- GL_VG_KHR_EGL_sync -------------------------- */
+
+#if !defined(GL_VG_KHR_EGL_sync) && !defined(GLEW_NO_ES)
+#define GL_VG_KHR_EGL_sync 1
+
+#define GLEW_VG_KHR_EGL_sync GLEW_GET_VAR(__GLEW_VG_KHR_EGL_sync)
+
+#endif /* !GL_VG_KHR_EGL_sync && !GLEW_NO_ES*/
+
+/* -------------------------- GL_VIV_shader_binary ------------------------- */
+
+#if !defined(GL_VIV_shader_binary) && !defined(GLEW_NO_ES)
+#define GL_VIV_shader_binary 1
+
+#define GL_SHADER_BINARY_VIV 0x8FC4
+
+#define GLEW_VIV_shader_binary GLEW_GET_VAR(__GLEW_VIV_shader_binary)
+
+#endif /* !GL_VIV_shader_binary && !GLEW_NO_ES*/
+
+/* ------------------------------------------------------------------------- */
+
+#if defined(GLEW_MX) && defined(_WIN32)
+#define GLEW_FUN_EXPORT
+#else
+#define GLEW_FUN_EXPORT GLEWAPI
+#endif /* GLEW_MX */
+
+#if defined(GLEW_MX)
+#define GLEW_VAR_EXPORT
+#else
+#define GLEW_VAR_EXPORT GLEWAPI
+#endif /* GLEW_MX */
+
+#if defined(GLEW_MX) && defined(_WIN32)
+struct GLEWContextStruct
+{
+#endif /* GLEW_MX */
+
+GLEW_FUN_EXPORT PFNGLACCUMPROC __glewAccum;
+GLEW_FUN_EXPORT PFNGLARETEXTURESRESIDENTPROC __glewAreTexturesResident;
+GLEW_FUN_EXPORT PFNGLARRAYELEMENTPROC __glewArrayElement;
+GLEW_FUN_EXPORT PFNGLBEGINPROC __glewBegin;
+GLEW_FUN_EXPORT PFNGLBITMAPPROC __glewBitmap;
+GLEW_FUN_EXPORT PFNGLCALLLISTPROC __glewCallList;
+GLEW_FUN_EXPORT PFNGLCALLLISTSPROC __glewCallLists;
+GLEW_FUN_EXPORT PFNGLCLEARACCUMPROC __glewClearAccum;
+GLEW_FUN_EXPORT PFNGLCLEARDEPTHPROC __glewClearDepth;
+GLEW_FUN_EXPORT PFNGLCLEARINDEXPROC __glewClearIndex;
+GLEW_FUN_EXPORT PFNGLCLIPPLANEPROC __glewClipPlane;
+GLEW_FUN_EXPORT PFNGLCOLOR3BPROC __glewColor3b;
+GLEW_FUN_EXPORT PFNGLCOLOR3BVPROC __glewColor3bv;
+GLEW_FUN_EXPORT PFNGLCOLOR3DPROC __glewColor3d;
+GLEW_FUN_EXPORT PFNGLCOLOR3DVPROC __glewColor3dv;
+GLEW_FUN_EXPORT PFNGLCOLOR3FPROC __glewColor3f;
+GLEW_FUN_EXPORT PFNGLCOLOR3FVPROC __glewColor3fv;
+GLEW_FUN_EXPORT PFNGLCOLOR3IPROC __glewColor3i;
+GLEW_FUN_EXPORT PFNGLCOLOR3IVPROC __glewColor3iv;
+GLEW_FUN_EXPORT PFNGLCOLOR3SPROC __glewColor3s;
+GLEW_FUN_EXPORT PFNGLCOLOR3SVPROC __glewColor3sv;
+GLEW_FUN_EXPORT PFNGLCOLOR3UBPROC __glewColor3ub;
+GLEW_FUN_EXPORT PFNGLCOLOR3UBVPROC __glewColor3ubv;
+GLEW_FUN_EXPORT PFNGLCOLOR3UIPROC __glewColor3ui;
+GLEW_FUN_EXPORT PFNGLCOLOR3UIVPROC __glewColor3uiv;
+GLEW_FUN_EXPORT PFNGLCOLOR3USPROC __glewColor3us;
+GLEW_FUN_EXPORT PFNGLCOLOR3USVPROC __glewColor3usv;
+GLEW_FUN_EXPORT PFNGLCOLOR4BPROC __glewColor4b;
+GLEW_FUN_EXPORT PFNGLCOLOR4BVPROC __glewColor4bv;
+GLEW_FUN_EXPORT PFNGLCOLOR4DPROC __glewColor4d;
+GLEW_FUN_EXPORT PFNGLCOLOR4DVPROC __glewColor4dv;
+GLEW_FUN_EXPORT PFNGLCOLOR4FVPROC __glewColor4fv;
+GLEW_FUN_EXPORT PFNGLCOLOR4IPROC __glewColor4i;
+GLEW_FUN_EXPORT PFNGLCOLOR4IVPROC __glewColor4iv;
+GLEW_FUN_EXPORT PFNGLCOLOR4SPROC __glewColor4s;
+GLEW_FUN_EXPORT PFNGLCOLOR4SVPROC __glewColor4sv;
+GLEW_FUN_EXPORT PFNGLCOLOR4UBPROC __glewColor4ub;
+GLEW_FUN_EXPORT PFNGLCOLOR4UBVPROC __glewColor4ubv;
+GLEW_FUN_EXPORT PFNGLCOLOR4UIPROC __glewColor4ui;
+GLEW_FUN_EXPORT PFNGLCOLOR4UIVPROC __glewColor4uiv;
+GLEW_FUN_EXPORT PFNGLCOLOR4USPROC __glewColor4us;
+GLEW_FUN_EXPORT PFNGLCOLOR4USVPROC __glewColor4usv;
+GLEW_FUN_EXPORT PFNGLCOLORMATERIALPROC __glewColorMaterial;
+GLEW_FUN_EXPORT PFNGLCOPYPIXELSPROC __glewCopyPixels;
+GLEW_FUN_EXPORT PFNGLCOPYTEXIMAGE1DPROC __glewCopyTexImage1D;
+GLEW_FUN_EXPORT PFNGLCOPYTEXSUBIMAGE1DPROC __glewCopyTexSubImage1D;
+GLEW_FUN_EXPORT PFNGLDELETELISTSPROC __glewDeleteLists;
+GLEW_FUN_EXPORT PFNGLDEPTHRANGEPROC __glewDepthRange;
+GLEW_FUN_EXPORT PFNGLDRAWBUFFERPROC __glewDrawBuffer;
+GLEW_FUN_EXPORT PFNGLDRAWPIXELSPROC __glewDrawPixels;
+GLEW_FUN_EXPORT PFNGLEDGEFLAGPROC __glewEdgeFlag;
+GLEW_FUN_EXPORT PFNGLEDGEFLAGPOINTERPROC __glewEdgeFlagPointer;
+GLEW_FUN_EXPORT PFNGLEDGEFLAGVPROC __glewEdgeFlagv;
+GLEW_FUN_EXPORT PFNGLENDPROC __glewEnd;
+GLEW_FUN_EXPORT PFNGLENDLISTPROC __glewEndList;
+GLEW_FUN_EXPORT PFNGLEVALCOORD1DPROC __glewEvalCoord1d;
+GLEW_FUN_EXPORT PFNGLEVALCOORD1DVPROC __glewEvalCoord1dv;
+GLEW_FUN_EXPORT PFNGLEVALCOORD1FPROC __glewEvalCoord1f;
+GLEW_FUN_EXPORT PFNGLEVALCOORD1FVPROC __glewEvalCoord1fv;
+GLEW_FUN_EXPORT PFNGLEVALCOORD2DPROC __glewEvalCoord2d;
+GLEW_FUN_EXPORT PFNGLEVALCOORD2DVPROC __glewEvalCoord2dv;
+GLEW_FUN_EXPORT PFNGLEVALCOORD2FPROC __glewEvalCoord2f;
+GLEW_FUN_EXPORT PFNGLEVALCOORD2FVPROC __glewEvalCoord2fv;
+GLEW_FUN_EXPORT PFNGLEVALMESH1PROC __glewEvalMesh1;
+GLEW_FUN_EXPORT PFNGLEVALMESH2PROC __glewEvalMesh2;
+GLEW_FUN_EXPORT PFNGLEVALPOINT1PROC __glewEvalPoint1;
+GLEW_FUN_EXPORT PFNGLEVALPOINT2PROC __glewEvalPoint2;
+GLEW_FUN_EXPORT PFNGLFEEDBACKBUFFERPROC __glewFeedbackBuffer;
+GLEW_FUN_EXPORT PFNGLFOGIPROC __glewFogi;
+GLEW_FUN_EXPORT PFNGLFOGIVPROC __glewFogiv;
+GLEW_FUN_EXPORT PFNGLFRUSTUMPROC __glewFrustum;
+GLEW_FUN_EXPORT PFNGLGENLISTSPROC __glewGenLists;
+GLEW_FUN_EXPORT PFNGLGETBOOLEANVPROC __glewGetBooleanv;
+GLEW_FUN_EXPORT PFNGLGETCLIPPLANEPROC __glewGetClipPlane;
+GLEW_FUN_EXPORT PFNGLGETDOUBLEVPROC __glewGetDoublev;
+GLEW_FUN_EXPORT PFNGLGETFLOATVPROC __glewGetFloatv;
+GLEW_FUN_EXPORT PFNGLGETLIGHTFVPROC __glewGetLightfv;
+GLEW_FUN_EXPORT PFNGLGETLIGHTIVPROC __glewGetLightiv;
+GLEW_FUN_EXPORT PFNGLGETMAPDVPROC __glewGetMapdv;
+GLEW_FUN_EXPORT PFNGLGETMAPFVPROC __glewGetMapfv;
+GLEW_FUN_EXPORT PFNGLGETMAPIVPROC __glewGetMapiv;
+GLEW_FUN_EXPORT PFNGLGETMATERIALFVPROC __glewGetMaterialfv;
+GLEW_FUN_EXPORT PFNGLGETMATERIALIVPROC __glewGetMaterialiv;
+GLEW_FUN_EXPORT PFNGLGETPIXELMAPFVPROC __glewGetPixelMapfv;
+GLEW_FUN_EXPORT PFNGLGETPIXELMAPUIVPROC __glewGetPixelMapuiv;
+GLEW_FUN_EXPORT PFNGLGETPIXELMAPUSVPROC __glewGetPixelMapusv;
+GLEW_FUN_EXPORT PFNGLGETPOINTERVPROC __glewGetPointerv;
+GLEW_FUN_EXPORT PFNGLGETPOLYGONSTIPPLEPROC __glewGetPolygonStipple;
+GLEW_FUN_EXPORT PFNGLGETTEXENVFVPROC __glewGetTexEnvfv;
+GLEW_FUN_EXPORT PFNGLGETTEXENVIVPROC __glewGetTexEnviv;
+GLEW_FUN_EXPORT PFNGLGETTEXGENDVPROC __glewGetTexGendv;
+GLEW_FUN_EXPORT PFNGLGETTEXGENFVPROC __glewGetTexGenfv;
+GLEW_FUN_EXPORT PFNGLGETTEXGENIVPROC __glewGetTexGeniv;
+GLEW_FUN_EXPORT PFNGLGETTEXIMAGEPROC __glewGetTexImage;
+GLEW_FUN_EXPORT PFNGLGETTEXLEVELPARAMETERFVPROC __glewGetTexLevelParameterfv;
+GLEW_FUN_EXPORT PFNGLGETTEXLEVELPARAMETERIVPROC __glewGetTexLevelParameteriv;
+GLEW_FUN_EXPORT PFNGLGETTEXPARAMETERFVPROC __glewGetTexParameterfv;
+GLEW_FUN_EXPORT PFNGLGETTEXPARAMETERIVPROC __glewGetTexParameteriv;
+GLEW_FUN_EXPORT PFNGLINDEXMASKPROC __glewIndexMask;
+GLEW_FUN_EXPORT PFNGLINDEXPOINTERPROC __glewIndexPointer;
+GLEW_FUN_EXPORT PFNGLINDEXDPROC __glewIndexd;
+GLEW_FUN_EXPORT PFNGLINDEXDVPROC __glewIndexdv;
+GLEW_FUN_EXPORT PFNGLINDEXFPROC __glewIndexf;
+GLEW_FUN_EXPORT PFNGLINDEXFVPROC __glewIndexfv;
+GLEW_FUN_EXPORT PFNGLINDEXIPROC __glewIndexi;
+GLEW_FUN_EXPORT PFNGLINDEXIVPROC __glewIndexiv;
+GLEW_FUN_EXPORT PFNGLINDEXSPROC __glewIndexs;
+GLEW_FUN_EXPORT PFNGLINDEXSVPROC __glewIndexsv;
+GLEW_FUN_EXPORT PFNGLINDEXUBPROC __glewIndexub;
+GLEW_FUN_EXPORT PFNGLINDEXUBVPROC __glewIndexubv;
+GLEW_FUN_EXPORT PFNGLINITNAMESPROC __glewInitNames;
+GLEW_FUN_EXPORT PFNGLINTERLEAVEDARRAYSPROC __glewInterleavedArrays;
+GLEW_FUN_EXPORT PFNGLISENABLEDPROC __glewIsEnabled;
+GLEW_FUN_EXPORT PFNGLISLISTPROC __glewIsList;
+GLEW_FUN_EXPORT PFNGLISTEXTUREPROC __glewIsTexture;
+GLEW_FUN_EXPORT PFNGLLIGHTMODELIPROC __glewLightModeli;
+GLEW_FUN_EXPORT PFNGLLIGHTMODELIVPROC __glewLightModeliv;
+GLEW_FUN_EXPORT PFNGLLIGHTIPROC __glewLighti;
+GLEW_FUN_EXPORT PFNGLLIGHTIVPROC __glewLightiv;
+GLEW_FUN_EXPORT PFNGLLINESTIPPLEPROC __glewLineStipple;
+GLEW_FUN_EXPORT PFNGLLISTBASEPROC __glewListBase;
+GLEW_FUN_EXPORT PFNGLLOADMATRIXDPROC __glewLoadMatrixd;
+GLEW_FUN_EXPORT PFNGLLOADNAMEPROC __glewLoadName;
+GLEW_FUN_EXPORT PFNGLMAP1DPROC __glewMap1d;
+GLEW_FUN_EXPORT PFNGLMAP1FPROC __glewMap1f;
+GLEW_FUN_EXPORT PFNGLMAP2DPROC __glewMap2d;
+GLEW_FUN_EXPORT PFNGLMAP2FPROC __glewMap2f;
+GLEW_FUN_EXPORT PFNGLMAPGRID1DPROC __glewMapGrid1d;
+GLEW_FUN_EXPORT PFNGLMAPGRID1FPROC __glewMapGrid1f;
+GLEW_FUN_EXPORT PFNGLMAPGRID2DPROC __glewMapGrid2d;
+GLEW_FUN_EXPORT PFNGLMAPGRID2FPROC __glewMapGrid2f;
+GLEW_FUN_EXPORT PFNGLMATERIALIPROC __glewMateriali;
+GLEW_FUN_EXPORT PFNGLMATERIALIVPROC __glewMaterialiv;
+GLEW_FUN_EXPORT PFNGLMULTMATRIXDPROC __glewMultMatrixd;
+GLEW_FUN_EXPORT PFNGLNEWLISTPROC __glewNewList;
+GLEW_FUN_EXPORT PFNGLNORMAL3BPROC __glewNormal3b;
+GLEW_FUN_EXPORT PFNGLNORMAL3BVPROC __glewNormal3bv;
+GLEW_FUN_EXPORT PFNGLNORMAL3DPROC __glewNormal3d;
+GLEW_FUN_EXPORT PFNGLNORMAL3DVPROC __glewNormal3dv;
+GLEW_FUN_EXPORT PFNGLNORMAL3FVPROC __glewNormal3fv;
+GLEW_FUN_EXPORT PFNGLNORMAL3IPROC __glewNormal3i;
+GLEW_FUN_EXPORT PFNGLNORMAL3IVPROC __glewNormal3iv;
+GLEW_FUN_EXPORT PFNGLNORMAL3SPROC __glewNormal3s;
+GLEW_FUN_EXPORT PFNGLNORMAL3SVPROC __glewNormal3sv;
+GLEW_FUN_EXPORT PFNGLORTHOPROC __glewOrtho;
+GLEW_FUN_EXPORT PFNGLPASSTHROUGHPROC __glewPassThrough;
+GLEW_FUN_EXPORT PFNGLPIXELMAPFVPROC __glewPixelMapfv;
+GLEW_FUN_EXPORT PFNGLPIXELMAPUIVPROC __glewPixelMapuiv;
+GLEW_FUN_EXPORT PFNGLPIXELMAPUSVPROC __glewPixelMapusv;
+GLEW_FUN_EXPORT PFNGLPIXELSTOREFPROC __glewPixelStoref;
+GLEW_FUN_EXPORT PFNGLPIXELTRANSFERFPROC __glewPixelTransferf;
+GLEW_FUN_EXPORT PFNGLPIXELTRANSFERIPROC __glewPixelTransferi;
+GLEW_FUN_EXPORT PFNGLPIXELZOOMPROC __glewPixelZoom;
+GLEW_FUN_EXPORT PFNGLPOLYGONMODEPROC __glewPolygonMode;
+GLEW_FUN_EXPORT PFNGLPOLYGONSTIPPLEPROC __glewPolygonStipple;
+GLEW_FUN_EXPORT PFNGLPOPATTRIBPROC __glewPopAttrib;
+GLEW_FUN_EXPORT PFNGLPOPCLIENTATTRIBPROC __glewPopClientAttrib;
+GLEW_FUN_EXPORT PFNGLPOPNAMEPROC __glewPopName;
+GLEW_FUN_EXPORT PFNGLPRIORITIZETEXTURESPROC __glewPrioritizeTextures;
+GLEW_FUN_EXPORT PFNGLPUSHATTRIBPROC __glewPushAttrib;
+GLEW_FUN_EXPORT PFNGLPUSHCLIENTATTRIBPROC __glewPushClientAttrib;
+GLEW_FUN_EXPORT PFNGLPUSHNAMEPROC __glewPushName;
+GLEW_FUN_EXPORT PFNGLRASTERPOS2DPROC __glewRasterPos2d;
+GLEW_FUN_EXPORT PFNGLRASTERPOS2DVPROC __glewRasterPos2dv;
+GLEW_FUN_EXPORT PFNGLRASTERPOS2FPROC __glewRasterPos2f;
+GLEW_FUN_EXPORT PFNGLRASTERPOS2FVPROC __glewRasterPos2fv;
+GLEW_FUN_EXPORT PFNGLRASTERPOS2IPROC __glewRasterPos2i;
+GLEW_FUN_EXPORT PFNGLRASTERPOS2IVPROC __glewRasterPos2iv;
+GLEW_FUN_EXPORT PFNGLRASTERPOS2SPROC __glewRasterPos2s;
+GLEW_FUN_EXPORT PFNGLRASTERPOS2SVPROC __glewRasterPos2sv;
+GLEW_FUN_EXPORT PFNGLRASTERPOS3DPROC __glewRasterPos3d;
+GLEW_FUN_EXPORT PFNGLRASTERPOS3DVPROC __glewRasterPos3dv;
+GLEW_FUN_EXPORT PFNGLRASTERPOS3FPROC __glewRasterPos3f;
+GLEW_FUN_EXPORT PFNGLRASTERPOS3FVPROC __glewRasterPos3fv;
+GLEW_FUN_EXPORT PFNGLRASTERPOS3IPROC __glewRasterPos3i;
+GLEW_FUN_EXPORT PFNGLRASTERPOS3IVPROC __glewRasterPos3iv;
+GLEW_FUN_EXPORT PFNGLRASTERPOS3SPROC __glewRasterPos3s;
+GLEW_FUN_EXPORT PFNGLRASTERPOS3SVPROC __glewRasterPos3sv;
+GLEW_FUN_EXPORT PFNGLRASTERPOS4DPROC __glewRasterPos4d;
+GLEW_FUN_EXPORT PFNGLRASTERPOS4DVPROC __glewRasterPos4dv;
+GLEW_FUN_EXPORT PFNGLRASTERPOS4FPROC __glewRasterPos4f;
+GLEW_FUN_EXPORT PFNGLRASTERPOS4FVPROC __glewRasterPos4fv;
+GLEW_FUN_EXPORT PFNGLRASTERPOS4IPROC __glewRasterPos4i;
+GLEW_FUN_EXPORT PFNGLRASTERPOS4IVPROC __glewRasterPos4iv;
+GLEW_FUN_EXPORT PFNGLRASTERPOS4SPROC __glewRasterPos4s;
+GLEW_FUN_EXPORT PFNGLRASTERPOS4SVPROC __glewRasterPos4sv;
+GLEW_FUN_EXPORT PFNGLREADBUFFERPROC __glewReadBuffer;
+GLEW_FUN_EXPORT PFNGLRECTDPROC __glewRectd;
+GLEW_FUN_EXPORT PFNGLRECTDVPROC __glewRectdv;
+GLEW_FUN_EXPORT PFNGLRECTFPROC __glewRectf;
+GLEW_FUN_EXPORT PFNGLRECTFVPROC __glewRectfv;
+GLEW_FUN_EXPORT PFNGLRECTIPROC __glewRecti;
+GLEW_FUN_EXPORT PFNGLRECTIVPROC __glewRectiv;
+GLEW_FUN_EXPORT PFNGLRECTSPROC __glewRects;
+GLEW_FUN_EXPORT PFNGLRECTSVPROC __glewRectsv;
+GLEW_FUN_EXPORT PFNGLRENDERMODEPROC __glewRenderMode;
+GLEW_FUN_EXPORT PFNGLROTATEDPROC __glewRotated;
+GLEW_FUN_EXPORT PFNGLSCALEDPROC __glewScaled;
+GLEW_FUN_EXPORT PFNGLSELECTBUFFERPROC __glewSelectBuffer;
+GLEW_FUN_EXPORT PFNGLTEXCOORD1DPROC __glewTexCoord1d;
+GLEW_FUN_EXPORT PFNGLTEXCOORD1DVPROC __glewTexCoord1dv;
+GLEW_FUN_EXPORT PFNGLTEXCOORD1FPROC __glewTexCoord1f;
+GLEW_FUN_EXPORT PFNGLTEXCOORD1FVPROC __glewTexCoord1fv;
+GLEW_FUN_EXPORT PFNGLTEXCOORD1IPROC __glewTexCoord1i;
+GLEW_FUN_EXPORT PFNGLTEXCOORD1IVPROC __glewTexCoord1iv;
+GLEW_FUN_EXPORT PFNGLTEXCOORD1SPROC __glewTexCoord1s;
+GLEW_FUN_EXPORT PFNGLTEXCOORD1SVPROC __glewTexCoord1sv;
+GLEW_FUN_EXPORT PFNGLTEXCOORD2DPROC __glewTexCoord2d;
+GLEW_FUN_EXPORT PFNGLTEXCOORD2DVPROC __glewTexCoord2dv;
+GLEW_FUN_EXPORT PFNGLTEXCOORD2FPROC __glewTexCoord2f;
+GLEW_FUN_EXPORT PFNGLTEXCOORD2FVPROC __glewTexCoord2fv;
+GLEW_FUN_EXPORT PFNGLTEXCOORD2IPROC __glewTexCoord2i;
+GLEW_FUN_EXPORT PFNGLTEXCOORD2IVPROC __glewTexCoord2iv;
+GLEW_FUN_EXPORT PFNGLTEXCOORD2SPROC __glewTexCoord2s;
+GLEW_FUN_EXPORT PFNGLTEXCOORD2SVPROC __glewTexCoord2sv;
+GLEW_FUN_EXPORT PFNGLTEXCOORD3DPROC __glewTexCoord3d;
+GLEW_FUN_EXPORT PFNGLTEXCOORD3DVPROC __glewTexCoord3dv;
+GLEW_FUN_EXPORT PFNGLTEXCOORD3FPROC __glewTexCoord3f;
+GLEW_FUN_EXPORT PFNGLTEXCOORD3FVPROC __glewTexCoord3fv;
+GLEW_FUN_EXPORT PFNGLTEXCOORD3IPROC __glewTexCoord3i;
+GLEW_FUN_EXPORT PFNGLTEXCOORD3IVPROC __glewTexCoord3iv;
+GLEW_FUN_EXPORT PFNGLTEXCOORD3SPROC __glewTexCoord3s;
+GLEW_FUN_EXPORT PFNGLTEXCOORD3SVPROC __glewTexCoord3sv;
+GLEW_FUN_EXPORT PFNGLTEXCOORD4DPROC __glewTexCoord4d;
+GLEW_FUN_EXPORT PFNGLTEXCOORD4DVPROC __glewTexCoord4dv;
+GLEW_FUN_EXPORT PFNGLTEXCOORD4FPROC __glewTexCoord4f;
+GLEW_FUN_EXPORT PFNGLTEXCOORD4FVPROC __glewTexCoord4fv;
+GLEW_FUN_EXPORT PFNGLTEXCOORD4IPROC __glewTexCoord4i;
+GLEW_FUN_EXPORT PFNGLTEXCOORD4IVPROC __glewTexCoord4iv;
+GLEW_FUN_EXPORT PFNGLTEXCOORD4SPROC __glewTexCoord4s;
+GLEW_FUN_EXPORT PFNGLTEXCOORD4SVPROC __glewTexCoord4sv;
+GLEW_FUN_EXPORT PFNGLTEXENVIPROC __glewTexEnvi;
+GLEW_FUN_EXPORT PFNGLTEXENVIVPROC __glewTexEnviv;
+GLEW_FUN_EXPORT PFNGLTEXGENDPROC __glewTexGend;
+GLEW_FUN_EXPORT PFNGLTEXGENDVPROC __glewTexGendv;
+GLEW_FUN_EXPORT PFNGLTEXGENFPROC __glewTexGenf;
+GLEW_FUN_EXPORT PFNGLTEXGENFVPROC __glewTexGenfv;
+GLEW_FUN_EXPORT PFNGLTEXGENIPROC __glewTexGeni;
+GLEW_FUN_EXPORT PFNGLTEXGENIVPROC __glewTexGeniv;
+GLEW_FUN_EXPORT PFNGLTEXIMAGE1DPROC __glewTexImage1D;
+GLEW_FUN_EXPORT PFNGLTEXPARAMETERFVPROC __glewTexParameterfv;
+GLEW_FUN_EXPORT PFNGLTEXPARAMETERIPROC __glewTexParameteri;
+GLEW_FUN_EXPORT PFNGLTEXPARAMETERIVPROC __glewTexParameteriv;
+GLEW_FUN_EXPORT PFNGLTEXSUBIMAGE1DPROC __glewTexSubImage1D;
+GLEW_FUN_EXPORT PFNGLTRANSLATEDPROC __glewTranslated;
+GLEW_FUN_EXPORT PFNGLVERTEX2DPROC __glewVertex2d;
+GLEW_FUN_EXPORT PFNGLVERTEX2DVPROC __glewVertex2dv;
+GLEW_FUN_EXPORT PFNGLVERTEX2FPROC __glewVertex2f;
+GLEW_FUN_EXPORT PFNGLVERTEX2FVPROC __glewVertex2fv;
+GLEW_FUN_EXPORT PFNGLVERTEX2IPROC __glewVertex2i;
+GLEW_FUN_EXPORT PFNGLVERTEX2IVPROC __glewVertex2iv;
+GLEW_FUN_EXPORT PFNGLVERTEX2SPROC __glewVertex2s;
+GLEW_FUN_EXPORT PFNGLVERTEX2SVPROC __glewVertex2sv;
+GLEW_FUN_EXPORT PFNGLVERTEX3DPROC __glewVertex3d;
+GLEW_FUN_EXPORT PFNGLVERTEX3DVPROC __glewVertex3dv;
+GLEW_FUN_EXPORT PFNGLVERTEX3FPROC __glewVertex3f;
+GLEW_FUN_EXPORT PFNGLVERTEX3FVPROC __glewVertex3fv;
+GLEW_FUN_EXPORT PFNGLVERTEX3IPROC __glewVertex3i;
+GLEW_FUN_EXPORT PFNGLVERTEX3IVPROC __glewVertex3iv;
+GLEW_FUN_EXPORT PFNGLVERTEX3SPROC __glewVertex3s;
+GLEW_FUN_EXPORT PFNGLVERTEX3SVPROC __glewVertex3sv;
+GLEW_FUN_EXPORT PFNGLVERTEX4DPROC __glewVertex4d;
+GLEW_FUN_EXPORT PFNGLVERTEX4DVPROC __glewVertex4dv;
+GLEW_FUN_EXPORT PFNGLVERTEX4FPROC __glewVertex4f;
+GLEW_FUN_EXPORT PFNGLVERTEX4FVPROC __glewVertex4fv;
+GLEW_FUN_EXPORT PFNGLVERTEX4IPROC __glewVertex4i;
+GLEW_FUN_EXPORT PFNGLVERTEX4IVPROC __glewVertex4iv;
+GLEW_FUN_EXPORT PFNGLVERTEX4SPROC __glewVertex4s;
+GLEW_FUN_EXPORT PFNGLVERTEX4SVPROC __glewVertex4sv;
+
+GLEW_FUN_EXPORT PFNGLCOPYTEXSUBIMAGE3DPROC __glewCopyTexSubImage3D;
+GLEW_FUN_EXPORT PFNGLDRAWRANGEELEMENTSPROC __glewDrawRangeElements;
+GLEW_FUN_EXPORT PFNGLTEXIMAGE3DPROC __glewTexImage3D;
+GLEW_FUN_EXPORT PFNGLTEXSUBIMAGE3DPROC __glewTexSubImage3D;
+
+GLEW_FUN_EXPORT PFNGLACTIVETEXTUREPROC __glewActiveTexture;
+GLEW_FUN_EXPORT PFNGLCLIENTACTIVETEXTUREPROC __glewClientActiveTexture;
+GLEW_FUN_EXPORT PFNGLCOMPRESSEDTEXIMAGE1DPROC __glewCompressedTexImage1D;
+GLEW_FUN_EXPORT PFNGLCOMPRESSEDTEXIMAGE2DPROC __glewCompressedTexImage2D;
+GLEW_FUN_EXPORT PFNGLCOMPRESSEDTEXIMAGE3DPROC __glewCompressedTexImage3D;
+GLEW_FUN_EXPORT PFNGLCOMPRESSEDTEXSUBIMAGE1DPROC __glewCompressedTexSubImage1D;
+GLEW_FUN_EXPORT PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC __glewCompressedTexSubImage2D;
+GLEW_FUN_EXPORT PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC __glewCompressedTexSubImage3D;
+GLEW_FUN_EXPORT PFNGLGETCOMPRESSEDTEXIMAGEPROC __glewGetCompressedTexImage;
+GLEW_FUN_EXPORT PFNGLLOADTRANSPOSEMATRIXDPROC __glewLoadTransposeMatrixd;
+GLEW_FUN_EXPORT PFNGLLOADTRANSPOSEMATRIXFPROC __glewLoadTransposeMatrixf;
+GLEW_FUN_EXPORT PFNGLMULTTRANSPOSEMATRIXDPROC __glewMultTransposeMatrixd;
+GLEW_FUN_EXPORT PFNGLMULTTRANSPOSEMATRIXFPROC __glewMultTransposeMatrixf;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD1DPROC __glewMultiTexCoord1d;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD1DVPROC __glewMultiTexCoord1dv;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD1FPROC __glewMultiTexCoord1f;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD1FVPROC __glewMultiTexCoord1fv;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD1IPROC __glewMultiTexCoord1i;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD1IVPROC __glewMultiTexCoord1iv;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD1SPROC __glewMultiTexCoord1s;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD1SVPROC __glewMultiTexCoord1sv;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD2DPROC __glewMultiTexCoord2d;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD2DVPROC __glewMultiTexCoord2dv;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD2FPROC __glewMultiTexCoord2f;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD2FVPROC __glewMultiTexCoord2fv;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD2IPROC __glewMultiTexCoord2i;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD2IVPROC __glewMultiTexCoord2iv;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD2SPROC __glewMultiTexCoord2s;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD2SVPROC __glewMultiTexCoord2sv;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD3DPROC __glewMultiTexCoord3d;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD3DVPROC __glewMultiTexCoord3dv;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD3FPROC __glewMultiTexCoord3f;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD3FVPROC __glewMultiTexCoord3fv;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD3IPROC __glewMultiTexCoord3i;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD3IVPROC __glewMultiTexCoord3iv;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD3SPROC __glewMultiTexCoord3s;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD3SVPROC __glewMultiTexCoord3sv;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD4DPROC __glewMultiTexCoord4d;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD4DVPROC __glewMultiTexCoord4dv;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD4FPROC __glewMultiTexCoord4f;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD4FVPROC __glewMultiTexCoord4fv;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD4IPROC __glewMultiTexCoord4i;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD4IVPROC __glewMultiTexCoord4iv;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD4SPROC __glewMultiTexCoord4s;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD4SVPROC __glewMultiTexCoord4sv;
+GLEW_FUN_EXPORT PFNGLSAMPLECOVERAGEPROC __glewSampleCoverage;
+
+GLEW_FUN_EXPORT PFNGLBLENDCOLORPROC __glewBlendColor;
+GLEW_FUN_EXPORT PFNGLBLENDEQUATIONPROC __glewBlendEquation;
+GLEW_FUN_EXPORT PFNGLBLENDFUNCSEPARATEPROC __glewBlendFuncSeparate;
+GLEW_FUN_EXPORT PFNGLFOGCOORDPOINTERPROC __glewFogCoordPointer;
+GLEW_FUN_EXPORT PFNGLFOGCOORDDPROC __glewFogCoordd;
+GLEW_FUN_EXPORT PFNGLFOGCOORDDVPROC __glewFogCoorddv;
+GLEW_FUN_EXPORT PFNGLFOGCOORDFPROC __glewFogCoordf;
+GLEW_FUN_EXPORT PFNGLFOGCOORDFVPROC __glewFogCoordfv;
+GLEW_FUN_EXPORT PFNGLMULTIDRAWARRAYSPROC __glewMultiDrawArrays;
+GLEW_FUN_EXPORT PFNGLMULTIDRAWELEMENTSPROC __glewMultiDrawElements;
+GLEW_FUN_EXPORT PFNGLPOINTPARAMETERFPROC __glewPointParameterf;
+GLEW_FUN_EXPORT PFNGLPOINTPARAMETERFVPROC __glewPointParameterfv;
+GLEW_FUN_EXPORT PFNGLPOINTPARAMETERIPROC __glewPointParameteri;
+GLEW_FUN_EXPORT PFNGLPOINTPARAMETERIVPROC __glewPointParameteriv;
+GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3BPROC __glewSecondaryColor3b;
+GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3BVPROC __glewSecondaryColor3bv;
+GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3DPROC __glewSecondaryColor3d;
+GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3DVPROC __glewSecondaryColor3dv;
+GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3FPROC __glewSecondaryColor3f;
+GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3FVPROC __glewSecondaryColor3fv;
+GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3IPROC __glewSecondaryColor3i;
+GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3IVPROC __glewSecondaryColor3iv;
+GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3SPROC __glewSecondaryColor3s;
+GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3SVPROC __glewSecondaryColor3sv;
+GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3UBPROC __glewSecondaryColor3ub;
+GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3UBVPROC __glewSecondaryColor3ubv;
+GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3UIPROC __glewSecondaryColor3ui;
+GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3UIVPROC __glewSecondaryColor3uiv;
+GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3USPROC __glewSecondaryColor3us;
+GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3USVPROC __glewSecondaryColor3usv;
+GLEW_FUN_EXPORT PFNGLSECONDARYCOLORPOINTERPROC __glewSecondaryColorPointer;
+GLEW_FUN_EXPORT PFNGLWINDOWPOS2DPROC __glewWindowPos2d;
+GLEW_FUN_EXPORT PFNGLWINDOWPOS2DVPROC __glewWindowPos2dv;
+GLEW_FUN_EXPORT PFNGLWINDOWPOS2FPROC __glewWindowPos2f;
+GLEW_FUN_EXPORT PFNGLWINDOWPOS2FVPROC __glewWindowPos2fv;
+GLEW_FUN_EXPORT PFNGLWINDOWPOS2IPROC __glewWindowPos2i;
+GLEW_FUN_EXPORT PFNGLWINDOWPOS2IVPROC __glewWindowPos2iv;
+GLEW_FUN_EXPORT PFNGLWINDOWPOS2SPROC __glewWindowPos2s;
+GLEW_FUN_EXPORT PFNGLWINDOWPOS2SVPROC __glewWindowPos2sv;
+GLEW_FUN_EXPORT PFNGLWINDOWPOS3DPROC __glewWindowPos3d;
+GLEW_FUN_EXPORT PFNGLWINDOWPOS3DVPROC __glewWindowPos3dv;
+GLEW_FUN_EXPORT PFNGLWINDOWPOS3FPROC __glewWindowPos3f;
+GLEW_FUN_EXPORT PFNGLWINDOWPOS3FVPROC __glewWindowPos3fv;
+GLEW_FUN_EXPORT PFNGLWINDOWPOS3IPROC __glewWindowPos3i;
+GLEW_FUN_EXPORT PFNGLWINDOWPOS3IVPROC __glewWindowPos3iv;
+GLEW_FUN_EXPORT PFNGLWINDOWPOS3SPROC __glewWindowPos3s;
+GLEW_FUN_EXPORT PFNGLWINDOWPOS3SVPROC __glewWindowPos3sv;
+
+GLEW_FUN_EXPORT PFNGLBEGINQUERYPROC __glewBeginQuery;
+GLEW_FUN_EXPORT PFNGLBINDBUFFERPROC __glewBindBuffer;
+GLEW_FUN_EXPORT PFNGLBUFFERDATAPROC __glewBufferData;
+GLEW_FUN_EXPORT PFNGLBUFFERSUBDATAPROC __glewBufferSubData;
+GLEW_FUN_EXPORT PFNGLDELETEBUFFERSPROC __glewDeleteBuffers;
+GLEW_FUN_EXPORT PFNGLDELETEQUERIESPROC __glewDeleteQueries;
+GLEW_FUN_EXPORT PFNGLENDQUERYPROC __glewEndQuery;
+GLEW_FUN_EXPORT PFNGLGENBUFFERSPROC __glewGenBuffers;
+GLEW_FUN_EXPORT PFNGLGENQUERIESPROC __glewGenQueries;
+GLEW_FUN_EXPORT PFNGLGETBUFFERPARAMETERIVPROC __glewGetBufferParameteriv;
+GLEW_FUN_EXPORT PFNGLGETBUFFERPOINTERVPROC __glewGetBufferPointerv;
+GLEW_FUN_EXPORT PFNGLGETBUFFERSUBDATAPROC __glewGetBufferSubData;
+GLEW_FUN_EXPORT PFNGLGETQUERYOBJECTIVPROC __glewGetQueryObjectiv;
+GLEW_FUN_EXPORT PFNGLGETQUERYOBJECTUIVPROC __glewGetQueryObjectuiv;
+GLEW_FUN_EXPORT PFNGLGETQUERYIVPROC __glewGetQueryiv;
+GLEW_FUN_EXPORT PFNGLISBUFFERPROC __glewIsBuffer;
+GLEW_FUN_EXPORT PFNGLISQUERYPROC __glewIsQuery;
+GLEW_FUN_EXPORT PFNGLMAPBUFFERPROC __glewMapBuffer;
+GLEW_FUN_EXPORT PFNGLUNMAPBUFFERPROC __glewUnmapBuffer;
+
+GLEW_FUN_EXPORT PFNGLATTACHSHADERPROC __glewAttachShader;
+GLEW_FUN_EXPORT PFNGLBINDATTRIBLOCATIONPROC __glewBindAttribLocation;
+GLEW_FUN_EXPORT PFNGLBLENDEQUATIONSEPARATEPROC __glewBlendEquationSeparate;
+GLEW_FUN_EXPORT PFNGLCOMPILESHADERPROC __glewCompileShader;
+GLEW_FUN_EXPORT PFNGLCREATEPROGRAMPROC __glewCreateProgram;
+GLEW_FUN_EXPORT PFNGLCREATESHADERPROC __glewCreateShader;
+GLEW_FUN_EXPORT PFNGLDELETEPROGRAMPROC __glewDeleteProgram;
+GLEW_FUN_EXPORT PFNGLDELETESHADERPROC __glewDeleteShader;
+GLEW_FUN_EXPORT PFNGLDETACHSHADERPROC __glewDetachShader;
+GLEW_FUN_EXPORT PFNGLDISABLEVERTEXATTRIBARRAYPROC __glewDisableVertexAttribArray;
+GLEW_FUN_EXPORT PFNGLDRAWBUFFERSPROC __glewDrawBuffers;
+GLEW_FUN_EXPORT PFNGLENABLEVERTEXATTRIBARRAYPROC __glewEnableVertexAttribArray;
+GLEW_FUN_EXPORT PFNGLGETACTIVEATTRIBPROC __glewGetActiveAttrib;
+GLEW_FUN_EXPORT PFNGLGETACTIVEUNIFORMPROC __glewGetActiveUniform;
+GLEW_FUN_EXPORT PFNGLGETATTACHEDSHADERSPROC __glewGetAttachedShaders;
+GLEW_FUN_EXPORT PFNGLGETATTRIBLOCATIONPROC __glewGetAttribLocation;
+GLEW_FUN_EXPORT PFNGLGETPROGRAMINFOLOGPROC __glewGetProgramInfoLog;
+GLEW_FUN_EXPORT PFNGLGETPROGRAMIVPROC __glewGetProgramiv;
+GLEW_FUN_EXPORT PFNGLGETSHADERINFOLOGPROC __glewGetShaderInfoLog;
+GLEW_FUN_EXPORT PFNGLGETSHADERSOURCEPROC __glewGetShaderSource;
+GLEW_FUN_EXPORT PFNGLGETSHADERIVPROC __glewGetShaderiv;
+GLEW_FUN_EXPORT PFNGLGETUNIFORMLOCATIONPROC __glewGetUniformLocation;
+GLEW_FUN_EXPORT PFNGLGETUNIFORMFVPROC __glewGetUniformfv;
+GLEW_FUN_EXPORT PFNGLGETUNIFORMIVPROC __glewGetUniformiv;
+GLEW_FUN_EXPORT PFNGLGETVERTEXATTRIBPOINTERVPROC __glewGetVertexAttribPointerv;
+GLEW_FUN_EXPORT PFNGLGETVERTEXATTRIBDVPROC __glewGetVertexAttribdv;
+GLEW_FUN_EXPORT PFNGLGETVERTEXATTRIBFVPROC __glewGetVertexAttribfv;
+GLEW_FUN_EXPORT PFNGLGETVERTEXATTRIBIVPROC __glewGetVertexAttribiv;
+GLEW_FUN_EXPORT PFNGLISPROGRAMPROC __glewIsProgram;
+GLEW_FUN_EXPORT PFNGLISSHADERPROC __glewIsShader;
+GLEW_FUN_EXPORT PFNGLLINKPROGRAMPROC __glewLinkProgram;
+GLEW_FUN_EXPORT PFNGLSHADERSOURCEPROC __glewShaderSource;
+GLEW_FUN_EXPORT PFNGLSTENCILFUNCSEPARATEPROC __glewStencilFuncSeparate;
+GLEW_FUN_EXPORT PFNGLSTENCILMASKSEPARATEPROC __glewStencilMaskSeparate;
+GLEW_FUN_EXPORT PFNGLSTENCILOPSEPARATEPROC __glewStencilOpSeparate;
+GLEW_FUN_EXPORT PFNGLUNIFORM1FPROC __glewUniform1f;
+GLEW_FUN_EXPORT PFNGLUNIFORM1FVPROC __glewUniform1fv;
+GLEW_FUN_EXPORT PFNGLUNIFORM1IPROC __glewUniform1i;
+GLEW_FUN_EXPORT PFNGLUNIFORM1IVPROC __glewUniform1iv;
+GLEW_FUN_EXPORT PFNGLUNIFORM2FPROC __glewUniform2f;
+GLEW_FUN_EXPORT PFNGLUNIFORM2FVPROC __glewUniform2fv;
+GLEW_FUN_EXPORT PFNGLUNIFORM2IPROC __glewUniform2i;
+GLEW_FUN_EXPORT PFNGLUNIFORM2IVPROC __glewUniform2iv;
+GLEW_FUN_EXPORT PFNGLUNIFORM3FPROC __glewUniform3f;
+GLEW_FUN_EXPORT PFNGLUNIFORM3FVPROC __glewUniform3fv;
+GLEW_FUN_EXPORT PFNGLUNIFORM3IPROC __glewUniform3i;
+GLEW_FUN_EXPORT PFNGLUNIFORM3IVPROC __glewUniform3iv;
+GLEW_FUN_EXPORT PFNGLUNIFORM4FPROC __glewUniform4f;
+GLEW_FUN_EXPORT PFNGLUNIFORM4FVPROC __glewUniform4fv;
+GLEW_FUN_EXPORT PFNGLUNIFORM4IPROC __glewUniform4i;
+GLEW_FUN_EXPORT PFNGLUNIFORM4IVPROC __glewUniform4iv;
+GLEW_FUN_EXPORT PFNGLUNIFORMMATRIX2FVPROC __glewUniformMatrix2fv;
+GLEW_FUN_EXPORT PFNGLUNIFORMMATRIX3FVPROC __glewUniformMatrix3fv;
+GLEW_FUN_EXPORT PFNGLUNIFORMMATRIX4FVPROC __glewUniformMatrix4fv;
+GLEW_FUN_EXPORT PFNGLUSEPROGRAMPROC __glewUseProgram;
+GLEW_FUN_EXPORT PFNGLVALIDATEPROGRAMPROC __glewValidateProgram;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB1DPROC __glewVertexAttrib1d;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB1DVPROC __glewVertexAttrib1dv;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB1FPROC __glewVertexAttrib1f;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB1FVPROC __glewVertexAttrib1fv;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB1SPROC __glewVertexAttrib1s;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB1SVPROC __glewVertexAttrib1sv;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB2DPROC __glewVertexAttrib2d;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB2DVPROC __glewVertexAttrib2dv;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB2FPROC __glewVertexAttrib2f;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB2FVPROC __glewVertexAttrib2fv;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB2SPROC __glewVertexAttrib2s;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB2SVPROC __glewVertexAttrib2sv;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB3DPROC __glewVertexAttrib3d;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB3DVPROC __glewVertexAttrib3dv;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB3FPROC __glewVertexAttrib3f;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB3FVPROC __glewVertexAttrib3fv;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB3SPROC __glewVertexAttrib3s;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB3SVPROC __glewVertexAttrib3sv;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4NBVPROC __glewVertexAttrib4Nbv;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4NIVPROC __glewVertexAttrib4Niv;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4NSVPROC __glewVertexAttrib4Nsv;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4NUBPROC __glewVertexAttrib4Nub;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4NUBVPROC __glewVertexAttrib4Nubv;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4NUIVPROC __glewVertexAttrib4Nuiv;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4NUSVPROC __glewVertexAttrib4Nusv;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4BVPROC __glewVertexAttrib4bv;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4DPROC __glewVertexAttrib4d;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4DVPROC __glewVertexAttrib4dv;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4FPROC __glewVertexAttrib4f;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4FVPROC __glewVertexAttrib4fv;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4IVPROC __glewVertexAttrib4iv;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4SPROC __glewVertexAttrib4s;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4SVPROC __glewVertexAttrib4sv;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4UBVPROC __glewVertexAttrib4ubv;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4UIVPROC __glewVertexAttrib4uiv;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4USVPROC __glewVertexAttrib4usv;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBPOINTERPROC __glewVertexAttribPointer;
+
+GLEW_FUN_EXPORT PFNGLUNIFORMMATRIX2X3FVPROC __glewUniformMatrix2x3fv;
+GLEW_FUN_EXPORT PFNGLUNIFORMMATRIX2X4FVPROC __glewUniformMatrix2x4fv;
+GLEW_FUN_EXPORT PFNGLUNIFORMMATRIX3X2FVPROC __glewUniformMatrix3x2fv;
+GLEW_FUN_EXPORT PFNGLUNIFORMMATRIX3X4FVPROC __glewUniformMatrix3x4fv;
+GLEW_FUN_EXPORT PFNGLUNIFORMMATRIX4X2FVPROC __glewUniformMatrix4x2fv;
+GLEW_FUN_EXPORT PFNGLUNIFORMMATRIX4X3FVPROC __glewUniformMatrix4x3fv;
+
+GLEW_FUN_EXPORT PFNGLBEGINCONDITIONALRENDERPROC __glewBeginConditionalRender;
+GLEW_FUN_EXPORT PFNGLBEGINTRANSFORMFEEDBACKPROC __glewBeginTransformFeedback;
+GLEW_FUN_EXPORT PFNGLBINDFRAGDATALOCATIONPROC __glewBindFragDataLocation;
+GLEW_FUN_EXPORT PFNGLCLAMPCOLORPROC __glewClampColor;
+GLEW_FUN_EXPORT PFNGLCLEARBUFFERFIPROC __glewClearBufferfi;
+GLEW_FUN_EXPORT PFNGLCLEARBUFFERFVPROC __glewClearBufferfv;
+GLEW_FUN_EXPORT PFNGLCLEARBUFFERIVPROC __glewClearBufferiv;
+GLEW_FUN_EXPORT PFNGLCLEARBUFFERUIVPROC __glewClearBufferuiv;
+GLEW_FUN_EXPORT PFNGLCOLORMASKIPROC __glewColorMaski;
+GLEW_FUN_EXPORT PFNGLDISABLEIPROC __glewDisablei;
+GLEW_FUN_EXPORT PFNGLENABLEIPROC __glewEnablei;
+GLEW_FUN_EXPORT PFNGLENDCONDITIONALRENDERPROC __glewEndConditionalRender;
+GLEW_FUN_EXPORT PFNGLENDTRANSFORMFEEDBACKPROC __glewEndTransformFeedback;
+GLEW_FUN_EXPORT PFNGLGETBOOLEANI_VPROC __glewGetBooleani_v;
+GLEW_FUN_EXPORT PFNGLGETFRAGDATALOCATIONPROC __glewGetFragDataLocation;
+GLEW_FUN_EXPORT PFNGLGETSTRINGIPROC __glewGetStringi;
+GLEW_FUN_EXPORT PFNGLGETTEXPARAMETERIIVPROC __glewGetTexParameterIiv;
+GLEW_FUN_EXPORT PFNGLGETTEXPARAMETERIUIVPROC __glewGetTexParameterIuiv;
+GLEW_FUN_EXPORT PFNGLGETTRANSFORMFEEDBACKVARYINGPROC __glewGetTransformFeedbackVarying;
+GLEW_FUN_EXPORT PFNGLGETUNIFORMUIVPROC __glewGetUniformuiv;
+GLEW_FUN_EXPORT PFNGLGETVERTEXATTRIBIIVPROC __glewGetVertexAttribIiv;
+GLEW_FUN_EXPORT PFNGLGETVERTEXATTRIBIUIVPROC __glewGetVertexAttribIuiv;
+GLEW_FUN_EXPORT PFNGLISENABLEDIPROC __glewIsEnabledi;
+GLEW_FUN_EXPORT PFNGLTEXPARAMETERIIVPROC __glewTexParameterIiv;
+GLEW_FUN_EXPORT PFNGLTEXPARAMETERIUIVPROC __glewTexParameterIuiv;
+GLEW_FUN_EXPORT PFNGLTRANSFORMFEEDBACKVARYINGSPROC __glewTransformFeedbackVaryings;
+GLEW_FUN_EXPORT PFNGLUNIFORM1UIPROC __glewUniform1ui;
+GLEW_FUN_EXPORT PFNGLUNIFORM1UIVPROC __glewUniform1uiv;
+GLEW_FUN_EXPORT PFNGLUNIFORM2UIPROC __glewUniform2ui;
+GLEW_FUN_EXPORT PFNGLUNIFORM2UIVPROC __glewUniform2uiv;
+GLEW_FUN_EXPORT PFNGLUNIFORM3UIPROC __glewUniform3ui;
+GLEW_FUN_EXPORT PFNGLUNIFORM3UIVPROC __glewUniform3uiv;
+GLEW_FUN_EXPORT PFNGLUNIFORM4UIPROC __glewUniform4ui;
+GLEW_FUN_EXPORT PFNGLUNIFORM4UIVPROC __glewUniform4uiv;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI1IPROC __glewVertexAttribI1i;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI1IVPROC __glewVertexAttribI1iv;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI1UIPROC __glewVertexAttribI1ui;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI1UIVPROC __glewVertexAttribI1uiv;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI2IPROC __glewVertexAttribI2i;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI2IVPROC __glewVertexAttribI2iv;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI2UIPROC __glewVertexAttribI2ui;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI2UIVPROC __glewVertexAttribI2uiv;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI3IPROC __glewVertexAttribI3i;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI3IVPROC __glewVertexAttribI3iv;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI3UIPROC __glewVertexAttribI3ui;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI3UIVPROC __glewVertexAttribI3uiv;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI4BVPROC __glewVertexAttribI4bv;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI4IPROC __glewVertexAttribI4i;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI4IVPROC __glewVertexAttribI4iv;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI4SVPROC __glewVertexAttribI4sv;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI4UBVPROC __glewVertexAttribI4ubv;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI4UIPROC __glewVertexAttribI4ui;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI4UIVPROC __glewVertexAttribI4uiv;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI4USVPROC __glewVertexAttribI4usv;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBIPOINTERPROC __glewVertexAttribIPointer;
+
+GLEW_FUN_EXPORT PFNGLDRAWARRAYSINSTANCEDPROC __glewDrawArraysInstanced;
+GLEW_FUN_EXPORT PFNGLDRAWELEMENTSINSTANCEDPROC __glewDrawElementsInstanced;
+GLEW_FUN_EXPORT PFNGLPRIMITIVERESTARTINDEXPROC __glewPrimitiveRestartIndex;
+GLEW_FUN_EXPORT PFNGLTEXBUFFERPROC __glewTexBuffer;
+
+GLEW_FUN_EXPORT PFNGLFRAMEBUFFERTEXTUREPROC __glewFramebufferTexture;
+GLEW_FUN_EXPORT PFNGLGETBUFFERPARAMETERI64VPROC __glewGetBufferParameteri64v;
+GLEW_FUN_EXPORT PFNGLGETINTEGER64I_VPROC __glewGetInteger64i_v;
+
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBDIVISORPROC __glewVertexAttribDivisor;
+
+GLEW_FUN_EXPORT PFNGLBLENDEQUATIONSEPARATEIPROC __glewBlendEquationSeparatei;
+GLEW_FUN_EXPORT PFNGLBLENDEQUATIONIPROC __glewBlendEquationi;
+GLEW_FUN_EXPORT PFNGLBLENDFUNCSEPARATEIPROC __glewBlendFuncSeparatei;
+GLEW_FUN_EXPORT PFNGLBLENDFUNCIPROC __glewBlendFunci;
+GLEW_FUN_EXPORT PFNGLMINSAMPLESHADINGPROC __glewMinSampleShading;
+
+GLEW_FUN_EXPORT PFNGLTBUFFERMASK3DFXPROC __glewTbufferMask3DFX;
+
+GLEW_FUN_EXPORT PFNGLDEBUGMESSAGECALLBACKAMDPROC __glewDebugMessageCallbackAMD;
+GLEW_FUN_EXPORT PFNGLDEBUGMESSAGEENABLEAMDPROC __glewDebugMessageEnableAMD;
+GLEW_FUN_EXPORT PFNGLDEBUGMESSAGEINSERTAMDPROC __glewDebugMessageInsertAMD;
+GLEW_FUN_EXPORT PFNGLGETDEBUGMESSAGELOGAMDPROC __glewGetDebugMessageLogAMD;
+
+GLEW_FUN_EXPORT PFNGLBLENDEQUATIONINDEXEDAMDPROC __glewBlendEquationIndexedAMD;
+GLEW_FUN_EXPORT PFNGLBLENDEQUATIONSEPARATEINDEXEDAMDPROC __glewBlendEquationSeparateIndexedAMD;
+GLEW_FUN_EXPORT PFNGLBLENDFUNCINDEXEDAMDPROC __glewBlendFuncIndexedAMD;
+GLEW_FUN_EXPORT PFNGLBLENDFUNCSEPARATEINDEXEDAMDPROC __glewBlendFuncSeparateIndexedAMD;
+
+GLEW_FUN_EXPORT PFNGLMULTIDRAWARRAYSINDIRECTAMDPROC __glewMultiDrawArraysIndirectAMD;
+GLEW_FUN_EXPORT PFNGLMULTIDRAWELEMENTSINDIRECTAMDPROC __glewMultiDrawElementsIndirectAMD;
+
+GLEW_FUN_EXPORT PFNGLDELETENAMESAMDPROC __glewDeleteNamesAMD;
+GLEW_FUN_EXPORT PFNGLGENNAMESAMDPROC __glewGenNamesAMD;
+GLEW_FUN_EXPORT PFNGLISNAMEAMDPROC __glewIsNameAMD;
+
+GLEW_FUN_EXPORT PFNGLBEGINPERFMONITORAMDPROC __glewBeginPerfMonitorAMD;
+GLEW_FUN_EXPORT PFNGLDELETEPERFMONITORSAMDPROC __glewDeletePerfMonitorsAMD;
+GLEW_FUN_EXPORT PFNGLENDPERFMONITORAMDPROC __glewEndPerfMonitorAMD;
+GLEW_FUN_EXPORT PFNGLGENPERFMONITORSAMDPROC __glewGenPerfMonitorsAMD;
+GLEW_FUN_EXPORT PFNGLGETPERFMONITORCOUNTERDATAAMDPROC __glewGetPerfMonitorCounterDataAMD;
+GLEW_FUN_EXPORT PFNGLGETPERFMONITORCOUNTERINFOAMDPROC __glewGetPerfMonitorCounterInfoAMD;
+GLEW_FUN_EXPORT PFNGLGETPERFMONITORCOUNTERSTRINGAMDPROC __glewGetPerfMonitorCounterStringAMD;
+GLEW_FUN_EXPORT PFNGLGETPERFMONITORCOUNTERSAMDPROC __glewGetPerfMonitorCountersAMD;
+GLEW_FUN_EXPORT PFNGLGETPERFMONITORGROUPSTRINGAMDPROC __glewGetPerfMonitorGroupStringAMD;
+GLEW_FUN_EXPORT PFNGLGETPERFMONITORGROUPSAMDPROC __glewGetPerfMonitorGroupsAMD;
+GLEW_FUN_EXPORT PFNGLSELECTPERFMONITORCOUNTERSAMDPROC __glewSelectPerfMonitorCountersAMD;
+
+GLEW_FUN_EXPORT PFNGLSETMULTISAMPLEFVAMDPROC __glewSetMultisamplefvAMD;
+
+GLEW_FUN_EXPORT PFNGLTEXSTORAGESPARSEAMDPROC __glewTexStorageSparseAMD;
+GLEW_FUN_EXPORT PFNGLTEXTURESTORAGESPARSEAMDPROC __glewTextureStorageSparseAMD;
+
+GLEW_FUN_EXPORT PFNGLSTENCILOPVALUEAMDPROC __glewStencilOpValueAMD;
+
+GLEW_FUN_EXPORT PFNGLTESSELLATIONFACTORAMDPROC __glewTessellationFactorAMD;
+GLEW_FUN_EXPORT PFNGLTESSELLATIONMODEAMDPROC __glewTessellationModeAMD;
+
+GLEW_FUN_EXPORT PFNGLDRAWELEMENTARRAYAPPLEPROC __glewDrawElementArrayAPPLE;
+GLEW_FUN_EXPORT PFNGLDRAWRANGEELEMENTARRAYAPPLEPROC __glewDrawRangeElementArrayAPPLE;
+GLEW_FUN_EXPORT PFNGLELEMENTPOINTERAPPLEPROC __glewElementPointerAPPLE;
+GLEW_FUN_EXPORT PFNGLMULTIDRAWELEMENTARRAYAPPLEPROC __glewMultiDrawElementArrayAPPLE;
+GLEW_FUN_EXPORT PFNGLMULTIDRAWRANGEELEMENTARRAYAPPLEPROC __glewMultiDrawRangeElementArrayAPPLE;
+
+GLEW_FUN_EXPORT PFNGLDELETEFENCESAPPLEPROC __glewDeleteFencesAPPLE;
+GLEW_FUN_EXPORT PFNGLFINISHFENCEAPPLEPROC __glewFinishFenceAPPLE;
+GLEW_FUN_EXPORT PFNGLFINISHOBJECTAPPLEPROC __glewFinishObjectAPPLE;
+GLEW_FUN_EXPORT PFNGLGENFENCESAPPLEPROC __glewGenFencesAPPLE;
+GLEW_FUN_EXPORT PFNGLISFENCEAPPLEPROC __glewIsFenceAPPLE;
+GLEW_FUN_EXPORT PFNGLSETFENCEAPPLEPROC __glewSetFenceAPPLE;
+GLEW_FUN_EXPORT PFNGLTESTFENCEAPPLEPROC __glewTestFenceAPPLE;
+GLEW_FUN_EXPORT PFNGLTESTOBJECTAPPLEPROC __glewTestObjectAPPLE;
+
+GLEW_FUN_EXPORT PFNGLBUFFERPARAMETERIAPPLEPROC __glewBufferParameteriAPPLE;
+GLEW_FUN_EXPORT PFNGLFLUSHMAPPEDBUFFERRANGEAPPLEPROC __glewFlushMappedBufferRangeAPPLE;
+
+GLEW_FUN_EXPORT PFNGLGETOBJECTPARAMETERIVAPPLEPROC __glewGetObjectParameterivAPPLE;
+GLEW_FUN_EXPORT PFNGLOBJECTPURGEABLEAPPLEPROC __glewObjectPurgeableAPPLE;
+GLEW_FUN_EXPORT PFNGLOBJECTUNPURGEABLEAPPLEPROC __glewObjectUnpurgeableAPPLE;
+
+GLEW_FUN_EXPORT PFNGLGETTEXPARAMETERPOINTERVAPPLEPROC __glewGetTexParameterPointervAPPLE;
+GLEW_FUN_EXPORT PFNGLTEXTURERANGEAPPLEPROC __glewTextureRangeAPPLE;
+
+GLEW_FUN_EXPORT PFNGLBINDVERTEXARRAYAPPLEPROC __glewBindVertexArrayAPPLE;
+GLEW_FUN_EXPORT PFNGLDELETEVERTEXARRAYSAPPLEPROC __glewDeleteVertexArraysAPPLE;
+GLEW_FUN_EXPORT PFNGLGENVERTEXARRAYSAPPLEPROC __glewGenVertexArraysAPPLE;
+GLEW_FUN_EXPORT PFNGLISVERTEXARRAYAPPLEPROC __glewIsVertexArrayAPPLE;
+
+GLEW_FUN_EXPORT PFNGLFLUSHVERTEXARRAYRANGEAPPLEPROC __glewFlushVertexArrayRangeAPPLE;
+GLEW_FUN_EXPORT PFNGLVERTEXARRAYPARAMETERIAPPLEPROC __glewVertexArrayParameteriAPPLE;
+GLEW_FUN_EXPORT PFNGLVERTEXARRAYRANGEAPPLEPROC __glewVertexArrayRangeAPPLE;
+
+GLEW_FUN_EXPORT PFNGLDISABLEVERTEXATTRIBAPPLEPROC __glewDisableVertexAttribAPPLE;
+GLEW_FUN_EXPORT PFNGLENABLEVERTEXATTRIBAPPLEPROC __glewEnableVertexAttribAPPLE;
+GLEW_FUN_EXPORT PFNGLISVERTEXATTRIBENABLEDAPPLEPROC __glewIsVertexAttribEnabledAPPLE;
+GLEW_FUN_EXPORT PFNGLMAPVERTEXATTRIB1DAPPLEPROC __glewMapVertexAttrib1dAPPLE;
+GLEW_FUN_EXPORT PFNGLMAPVERTEXATTRIB1FAPPLEPROC __glewMapVertexAttrib1fAPPLE;
+GLEW_FUN_EXPORT PFNGLMAPVERTEXATTRIB2DAPPLEPROC __glewMapVertexAttrib2dAPPLE;
+GLEW_FUN_EXPORT PFNGLMAPVERTEXATTRIB2FAPPLEPROC __glewMapVertexAttrib2fAPPLE;
+
+GLEW_FUN_EXPORT PFNGLCLEARDEPTHFPROC __glewClearDepthf;
+GLEW_FUN_EXPORT PFNGLDEPTHRANGEFPROC __glewDepthRangef;
+GLEW_FUN_EXPORT PFNGLGETSHADERPRECISIONFORMATPROC __glewGetShaderPrecisionFormat;
+GLEW_FUN_EXPORT PFNGLRELEASESHADERCOMPILERPROC __glewReleaseShaderCompiler;
+GLEW_FUN_EXPORT PFNGLSHADERBINARYPROC __glewShaderBinary;
+
+GLEW_FUN_EXPORT PFNGLDRAWARRAYSINSTANCEDBASEINSTANCEPROC __glewDrawArraysInstancedBaseInstance;
+GLEW_FUN_EXPORT PFNGLDRAWELEMENTSINSTANCEDBASEINSTANCEPROC __glewDrawElementsInstancedBaseInstance;
+GLEW_FUN_EXPORT PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXBASEINSTANCEPROC __glewDrawElementsInstancedBaseVertexBaseInstance;
+
+GLEW_FUN_EXPORT PFNGLBINDFRAGDATALOCATIONINDEXEDPROC __glewBindFragDataLocationIndexed;
+GLEW_FUN_EXPORT PFNGLGETFRAGDATAINDEXPROC __glewGetFragDataIndex;
+
+GLEW_FUN_EXPORT PFNGLCREATESYNCFROMCLEVENTARBPROC __glewCreateSyncFromCLeventARB;
+
+GLEW_FUN_EXPORT PFNGLCLEARBUFFERDATAPROC __glewClearBufferData;
+GLEW_FUN_EXPORT PFNGLCLEARBUFFERSUBDATAPROC __glewClearBufferSubData;
+GLEW_FUN_EXPORT PFNGLCLEARNAMEDBUFFERDATAEXTPROC __glewClearNamedBufferDataEXT;
+GLEW_FUN_EXPORT PFNGLCLEARNAMEDBUFFERSUBDATAEXTPROC __glewClearNamedBufferSubDataEXT;
+
+GLEW_FUN_EXPORT PFNGLCLAMPCOLORARBPROC __glewClampColorARB;
+
+GLEW_FUN_EXPORT PFNGLDISPATCHCOMPUTEPROC __glewDispatchCompute;
+GLEW_FUN_EXPORT PFNGLDISPATCHCOMPUTEINDIRECTPROC __glewDispatchComputeIndirect;
+
+GLEW_FUN_EXPORT PFNGLCOPYBUFFERSUBDATAPROC __glewCopyBufferSubData;
+
+GLEW_FUN_EXPORT PFNGLCOPYIMAGESUBDATAPROC __glewCopyImageSubData;
+
+GLEW_FUN_EXPORT PFNGLDEBUGMESSAGECALLBACKARBPROC __glewDebugMessageCallbackARB;
+GLEW_FUN_EXPORT PFNGLDEBUGMESSAGECONTROLARBPROC __glewDebugMessageControlARB;
+GLEW_FUN_EXPORT PFNGLDEBUGMESSAGEINSERTARBPROC __glewDebugMessageInsertARB;
+GLEW_FUN_EXPORT PFNGLGETDEBUGMESSAGELOGARBPROC __glewGetDebugMessageLogARB;
+
+GLEW_FUN_EXPORT PFNGLDRAWBUFFERSARBPROC __glewDrawBuffersARB;
+
+GLEW_FUN_EXPORT PFNGLBLENDEQUATIONSEPARATEIARBPROC __glewBlendEquationSeparateiARB;
+GLEW_FUN_EXPORT PFNGLBLENDEQUATIONIARBPROC __glewBlendEquationiARB;
+GLEW_FUN_EXPORT PFNGLBLENDFUNCSEPARATEIARBPROC __glewBlendFuncSeparateiARB;
+GLEW_FUN_EXPORT PFNGLBLENDFUNCIARBPROC __glewBlendFunciARB;
+
+GLEW_FUN_EXPORT PFNGLDRAWELEMENTSBASEVERTEXPROC __glewDrawElementsBaseVertex;
+GLEW_FUN_EXPORT PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXPROC __glewDrawElementsInstancedBaseVertex;
+GLEW_FUN_EXPORT PFNGLDRAWRANGEELEMENTSBASEVERTEXPROC __glewDrawRangeElementsBaseVertex;
+GLEW_FUN_EXPORT PFNGLMULTIDRAWELEMENTSBASEVERTEXPROC __glewMultiDrawElementsBaseVertex;
+
+GLEW_FUN_EXPORT PFNGLDRAWARRAYSINDIRECTPROC __glewDrawArraysIndirect;
+GLEW_FUN_EXPORT PFNGLDRAWELEMENTSINDIRECTPROC __glewDrawElementsIndirect;
+
+GLEW_FUN_EXPORT PFNGLFRAMEBUFFERPARAMETERIPROC __glewFramebufferParameteri;
+GLEW_FUN_EXPORT PFNGLGETFRAMEBUFFERPARAMETERIVPROC __glewGetFramebufferParameteriv;
+GLEW_FUN_EXPORT PFNGLGETNAMEDFRAMEBUFFERPARAMETERIVEXTPROC __glewGetNamedFramebufferParameterivEXT;
+GLEW_FUN_EXPORT PFNGLNAMEDFRAMEBUFFERPARAMETERIEXTPROC __glewNamedFramebufferParameteriEXT;
+
+GLEW_FUN_EXPORT PFNGLBINDFRAMEBUFFERPROC __glewBindFramebuffer;
+GLEW_FUN_EXPORT PFNGLBINDRENDERBUFFERPROC __glewBindRenderbuffer;
+GLEW_FUN_EXPORT PFNGLBLITFRAMEBUFFERPROC __glewBlitFramebuffer;
+GLEW_FUN_EXPORT PFNGLCHECKFRAMEBUFFERSTATUSPROC __glewCheckFramebufferStatus;
+GLEW_FUN_EXPORT PFNGLDELETEFRAMEBUFFERSPROC __glewDeleteFramebuffers;
+GLEW_FUN_EXPORT PFNGLDELETERENDERBUFFERSPROC __glewDeleteRenderbuffers;
+GLEW_FUN_EXPORT PFNGLFRAMEBUFFERRENDERBUFFERPROC __glewFramebufferRenderbuffer;
+GLEW_FUN_EXPORT PFNGLFRAMEBUFFERTEXTURE1DPROC __glewFramebufferTexture1D;
+GLEW_FUN_EXPORT PFNGLFRAMEBUFFERTEXTURE2DPROC __glewFramebufferTexture2D;
+GLEW_FUN_EXPORT PFNGLFRAMEBUFFERTEXTURE3DPROC __glewFramebufferTexture3D;
+GLEW_FUN_EXPORT PFNGLFRAMEBUFFERTEXTURELAYERPROC __glewFramebufferTextureLayer;
+GLEW_FUN_EXPORT PFNGLGENFRAMEBUFFERSPROC __glewGenFramebuffers;
+GLEW_FUN_EXPORT PFNGLGENRENDERBUFFERSPROC __glewGenRenderbuffers;
+GLEW_FUN_EXPORT PFNGLGENERATEMIPMAPPROC __glewGenerateMipmap;
+GLEW_FUN_EXPORT PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC __glewGetFramebufferAttachmentParameteriv;
+GLEW_FUN_EXPORT PFNGLGETRENDERBUFFERPARAMETERIVPROC __glewGetRenderbufferParameteriv;
+GLEW_FUN_EXPORT PFNGLISFRAMEBUFFERPROC __glewIsFramebuffer;
+GLEW_FUN_EXPORT PFNGLISRENDERBUFFERPROC __glewIsRenderbuffer;
+GLEW_FUN_EXPORT PFNGLRENDERBUFFERSTORAGEPROC __glewRenderbufferStorage;
+GLEW_FUN_EXPORT PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC __glewRenderbufferStorageMultisample;
+
+GLEW_FUN_EXPORT PFNGLFRAMEBUFFERTEXTUREARBPROC __glewFramebufferTextureARB;
+GLEW_FUN_EXPORT PFNGLFRAMEBUFFERTEXTUREFACEARBPROC __glewFramebufferTextureFaceARB;
+GLEW_FUN_EXPORT PFNGLFRAMEBUFFERTEXTURELAYERARBPROC __glewFramebufferTextureLayerARB;
+GLEW_FUN_EXPORT PFNGLPROGRAMPARAMETERIARBPROC __glewProgramParameteriARB;
+
+GLEW_FUN_EXPORT PFNGLGETPROGRAMBINARYPROC __glewGetProgramBinary;
+GLEW_FUN_EXPORT PFNGLPROGRAMBINARYPROC __glewProgramBinary;
+GLEW_FUN_EXPORT PFNGLPROGRAMPARAMETERIPROC __glewProgramParameteri;
+
+GLEW_FUN_EXPORT PFNGLGETUNIFORMDVPROC __glewGetUniformdv;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM1DEXTPROC __glewProgramUniform1dEXT;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM1DVEXTPROC __glewProgramUniform1dvEXT;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM2DEXTPROC __glewProgramUniform2dEXT;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM2DVEXTPROC __glewProgramUniform2dvEXT;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM3DEXTPROC __glewProgramUniform3dEXT;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM3DVEXTPROC __glewProgramUniform3dvEXT;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM4DEXTPROC __glewProgramUniform4dEXT;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM4DVEXTPROC __glewProgramUniform4dvEXT;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX2DVEXTPROC __glewProgramUniformMatrix2dvEXT;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX2X3DVEXTPROC __glewProgramUniformMatrix2x3dvEXT;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX2X4DVEXTPROC __glewProgramUniformMatrix2x4dvEXT;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX3DVEXTPROC __glewProgramUniformMatrix3dvEXT;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX3X2DVEXTPROC __glewProgramUniformMatrix3x2dvEXT;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX3X4DVEXTPROC __glewProgramUniformMatrix3x4dvEXT;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX4DVEXTPROC __glewProgramUniformMatrix4dvEXT;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX4X2DVEXTPROC __glewProgramUniformMatrix4x2dvEXT;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX4X3DVEXTPROC __glewProgramUniformMatrix4x3dvEXT;
+GLEW_FUN_EXPORT PFNGLUNIFORM1DPROC __glewUniform1d;
+GLEW_FUN_EXPORT PFNGLUNIFORM1DVPROC __glewUniform1dv;
+GLEW_FUN_EXPORT PFNGLUNIFORM2DPROC __glewUniform2d;
+GLEW_FUN_EXPORT PFNGLUNIFORM2DVPROC __glewUniform2dv;
+GLEW_FUN_EXPORT PFNGLUNIFORM3DPROC __glewUniform3d;
+GLEW_FUN_EXPORT PFNGLUNIFORM3DVPROC __glewUniform3dv;
+GLEW_FUN_EXPORT PFNGLUNIFORM4DPROC __glewUniform4d;
+GLEW_FUN_EXPORT PFNGLUNIFORM4DVPROC __glewUniform4dv;
+GLEW_FUN_EXPORT PFNGLUNIFORMMATRIX2DVPROC __glewUniformMatrix2dv;
+GLEW_FUN_EXPORT PFNGLUNIFORMMATRIX2X3DVPROC __glewUniformMatrix2x3dv;
+GLEW_FUN_EXPORT PFNGLUNIFORMMATRIX2X4DVPROC __glewUniformMatrix2x4dv;
+GLEW_FUN_EXPORT PFNGLUNIFORMMATRIX3DVPROC __glewUniformMatrix3dv;
+GLEW_FUN_EXPORT PFNGLUNIFORMMATRIX3X2DVPROC __glewUniformMatrix3x2dv;
+GLEW_FUN_EXPORT PFNGLUNIFORMMATRIX3X4DVPROC __glewUniformMatrix3x4dv;
+GLEW_FUN_EXPORT PFNGLUNIFORMMATRIX4DVPROC __glewUniformMatrix4dv;
+GLEW_FUN_EXPORT PFNGLUNIFORMMATRIX4X2DVPROC __glewUniformMatrix4x2dv;
+GLEW_FUN_EXPORT PFNGLUNIFORMMATRIX4X3DVPROC __glewUniformMatrix4x3dv;
+
+GLEW_FUN_EXPORT PFNGLCOLORSUBTABLEPROC __glewColorSubTable;
+GLEW_FUN_EXPORT PFNGLCOLORTABLEPROC __glewColorTable;
+GLEW_FUN_EXPORT PFNGLCOLORTABLEPARAMETERFVPROC __glewColorTableParameterfv;
+GLEW_FUN_EXPORT PFNGLCOLORTABLEPARAMETERIVPROC __glewColorTableParameteriv;
+GLEW_FUN_EXPORT PFNGLCONVOLUTIONFILTER1DPROC __glewConvolutionFilter1D;
+GLEW_FUN_EXPORT PFNGLCONVOLUTIONFILTER2DPROC __glewConvolutionFilter2D;
+GLEW_FUN_EXPORT PFNGLCONVOLUTIONPARAMETERFPROC __glewConvolutionParameterf;
+GLEW_FUN_EXPORT PFNGLCONVOLUTIONPARAMETERFVPROC __glewConvolutionParameterfv;
+GLEW_FUN_EXPORT PFNGLCONVOLUTIONPARAMETERIPROC __glewConvolutionParameteri;
+GLEW_FUN_EXPORT PFNGLCONVOLUTIONPARAMETERIVPROC __glewConvolutionParameteriv;
+GLEW_FUN_EXPORT PFNGLCOPYCOLORSUBTABLEPROC __glewCopyColorSubTable;
+GLEW_FUN_EXPORT PFNGLCOPYCOLORTABLEPROC __glewCopyColorTable;
+GLEW_FUN_EXPORT PFNGLCOPYCONVOLUTIONFILTER1DPROC __glewCopyConvolutionFilter1D;
+GLEW_FUN_EXPORT PFNGLCOPYCONVOLUTIONFILTER2DPROC __glewCopyConvolutionFilter2D;
+GLEW_FUN_EXPORT PFNGLGETCOLORTABLEPROC __glewGetColorTable;
+GLEW_FUN_EXPORT PFNGLGETCOLORTABLEPARAMETERFVPROC __glewGetColorTableParameterfv;
+GLEW_FUN_EXPORT PFNGLGETCOLORTABLEPARAMETERIVPROC __glewGetColorTableParameteriv;
+GLEW_FUN_EXPORT PFNGLGETCONVOLUTIONFILTERPROC __glewGetConvolutionFilter;
+GLEW_FUN_EXPORT PFNGLGETCONVOLUTIONPARAMETERFVPROC __glewGetConvolutionParameterfv;
+GLEW_FUN_EXPORT PFNGLGETCONVOLUTIONPARAMETERIVPROC __glewGetConvolutionParameteriv;
+GLEW_FUN_EXPORT PFNGLGETHISTOGRAMPROC __glewGetHistogram;
+GLEW_FUN_EXPORT PFNGLGETHISTOGRAMPARAMETERFVPROC __glewGetHistogramParameterfv;
+GLEW_FUN_EXPORT PFNGLGETHISTOGRAMPARAMETERIVPROC __glewGetHistogramParameteriv;
+GLEW_FUN_EXPORT PFNGLGETMINMAXPROC __glewGetMinmax;
+GLEW_FUN_EXPORT PFNGLGETMINMAXPARAMETERFVPROC __glewGetMinmaxParameterfv;
+GLEW_FUN_EXPORT PFNGLGETMINMAXPARAMETERIVPROC __glewGetMinmaxParameteriv;
+GLEW_FUN_EXPORT PFNGLGETSEPARABLEFILTERPROC __glewGetSeparableFilter;
+GLEW_FUN_EXPORT PFNGLHISTOGRAMPROC __glewHistogram;
+GLEW_FUN_EXPORT PFNGLMINMAXPROC __glewMinmax;
+GLEW_FUN_EXPORT PFNGLRESETHISTOGRAMPROC __glewResetHistogram;
+GLEW_FUN_EXPORT PFNGLRESETMINMAXPROC __glewResetMinmax;
+GLEW_FUN_EXPORT PFNGLSEPARABLEFILTER2DPROC __glewSeparableFilter2D;
+
+GLEW_FUN_EXPORT PFNGLDRAWARRAYSINSTANCEDARBPROC __glewDrawArraysInstancedARB;
+GLEW_FUN_EXPORT PFNGLDRAWELEMENTSINSTANCEDARBPROC __glewDrawElementsInstancedARB;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBDIVISORARBPROC __glewVertexAttribDivisorARB;
+
+GLEW_FUN_EXPORT PFNGLGETINTERNALFORMATIVPROC __glewGetInternalformativ;
+
+GLEW_FUN_EXPORT PFNGLGETINTERNALFORMATI64VPROC __glewGetInternalformati64v;
+
+GLEW_FUN_EXPORT PFNGLINVALIDATEBUFFERDATAPROC __glewInvalidateBufferData;
+GLEW_FUN_EXPORT PFNGLINVALIDATEBUFFERSUBDATAPROC __glewInvalidateBufferSubData;
+GLEW_FUN_EXPORT PFNGLINVALIDATEFRAMEBUFFERPROC __glewInvalidateFramebuffer;
+GLEW_FUN_EXPORT PFNGLINVALIDATESUBFRAMEBUFFERPROC __glewInvalidateSubFramebuffer;
+GLEW_FUN_EXPORT PFNGLINVALIDATETEXIMAGEPROC __glewInvalidateTexImage;
+GLEW_FUN_EXPORT PFNGLINVALIDATETEXSUBIMAGEPROC __glewInvalidateTexSubImage;
+
+GLEW_FUN_EXPORT PFNGLFLUSHMAPPEDBUFFERRANGEPROC __glewFlushMappedBufferRange;
+GLEW_FUN_EXPORT PFNGLMAPBUFFERRANGEPROC __glewMapBufferRange;
+
+GLEW_FUN_EXPORT PFNGLCURRENTPALETTEMATRIXARBPROC __glewCurrentPaletteMatrixARB;
+GLEW_FUN_EXPORT PFNGLMATRIXINDEXPOINTERARBPROC __glewMatrixIndexPointerARB;
+GLEW_FUN_EXPORT PFNGLMATRIXINDEXUBVARBPROC __glewMatrixIndexubvARB;
+GLEW_FUN_EXPORT PFNGLMATRIXINDEXUIVARBPROC __glewMatrixIndexuivARB;
+GLEW_FUN_EXPORT PFNGLMATRIXINDEXUSVARBPROC __glewMatrixIndexusvARB;
+
+GLEW_FUN_EXPORT PFNGLMULTIDRAWARRAYSINDIRECTPROC __glewMultiDrawArraysIndirect;
+GLEW_FUN_EXPORT PFNGLMULTIDRAWELEMENTSINDIRECTPROC __glewMultiDrawElementsIndirect;
+
+GLEW_FUN_EXPORT PFNGLSAMPLECOVERAGEARBPROC __glewSampleCoverageARB;
+
+GLEW_FUN_EXPORT PFNGLACTIVETEXTUREARBPROC __glewActiveTextureARB;
+GLEW_FUN_EXPORT PFNGLCLIENTACTIVETEXTUREARBPROC __glewClientActiveTextureARB;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD1DARBPROC __glewMultiTexCoord1dARB;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD1DVARBPROC __glewMultiTexCoord1dvARB;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD1FARBPROC __glewMultiTexCoord1fARB;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD1FVARBPROC __glewMultiTexCoord1fvARB;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD1IARBPROC __glewMultiTexCoord1iARB;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD1IVARBPROC __glewMultiTexCoord1ivARB;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD1SARBPROC __glewMultiTexCoord1sARB;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD1SVARBPROC __glewMultiTexCoord1svARB;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD2DARBPROC __glewMultiTexCoord2dARB;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD2DVARBPROC __glewMultiTexCoord2dvARB;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD2FARBPROC __glewMultiTexCoord2fARB;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD2FVARBPROC __glewMultiTexCoord2fvARB;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD2IARBPROC __glewMultiTexCoord2iARB;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD2IVARBPROC __glewMultiTexCoord2ivARB;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD2SARBPROC __glewMultiTexCoord2sARB;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD2SVARBPROC __glewMultiTexCoord2svARB;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD3DARBPROC __glewMultiTexCoord3dARB;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD3DVARBPROC __glewMultiTexCoord3dvARB;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD3FARBPROC __glewMultiTexCoord3fARB;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD3FVARBPROC __glewMultiTexCoord3fvARB;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD3IARBPROC __glewMultiTexCoord3iARB;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD3IVARBPROC __glewMultiTexCoord3ivARB;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD3SARBPROC __glewMultiTexCoord3sARB;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD3SVARBPROC __glewMultiTexCoord3svARB;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD4DARBPROC __glewMultiTexCoord4dARB;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD4DVARBPROC __glewMultiTexCoord4dvARB;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD4FARBPROC __glewMultiTexCoord4fARB;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD4FVARBPROC __glewMultiTexCoord4fvARB;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD4IARBPROC __glewMultiTexCoord4iARB;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD4IVARBPROC __glewMultiTexCoord4ivARB;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD4SARBPROC __glewMultiTexCoord4sARB;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD4SVARBPROC __glewMultiTexCoord4svARB;
+
+GLEW_FUN_EXPORT PFNGLBEGINQUERYARBPROC __glewBeginQueryARB;
+GLEW_FUN_EXPORT PFNGLDELETEQUERIESARBPROC __glewDeleteQueriesARB;
+GLEW_FUN_EXPORT PFNGLENDQUERYARBPROC __glewEndQueryARB;
+GLEW_FUN_EXPORT PFNGLGENQUERIESARBPROC __glewGenQueriesARB;
+GLEW_FUN_EXPORT PFNGLGETQUERYOBJECTIVARBPROC __glewGetQueryObjectivARB;
+GLEW_FUN_EXPORT PFNGLGETQUERYOBJECTUIVARBPROC __glewGetQueryObjectuivARB;
+GLEW_FUN_EXPORT PFNGLGETQUERYIVARBPROC __glewGetQueryivARB;
+GLEW_FUN_EXPORT PFNGLISQUERYARBPROC __glewIsQueryARB;
+
+GLEW_FUN_EXPORT PFNGLPOINTPARAMETERFARBPROC __glewPointParameterfARB;
+GLEW_FUN_EXPORT PFNGLPOINTPARAMETERFVARBPROC __glewPointParameterfvARB;
+
+GLEW_FUN_EXPORT PFNGLGETPROGRAMINTERFACEIVPROC __glewGetProgramInterfaceiv;
+GLEW_FUN_EXPORT PFNGLGETPROGRAMRESOURCEINDEXPROC __glewGetProgramResourceIndex;
+GLEW_FUN_EXPORT PFNGLGETPROGRAMRESOURCELOCATIONPROC __glewGetProgramResourceLocation;
+GLEW_FUN_EXPORT PFNGLGETPROGRAMRESOURCELOCATIONINDEXPROC __glewGetProgramResourceLocationIndex;
+GLEW_FUN_EXPORT PFNGLGETPROGRAMRESOURCENAMEPROC __glewGetProgramResourceName;
+GLEW_FUN_EXPORT PFNGLGETPROGRAMRESOURCEIVPROC __glewGetProgramResourceiv;
+
+GLEW_FUN_EXPORT PFNGLPROVOKINGVERTEXPROC __glewProvokingVertex;
+
+GLEW_FUN_EXPORT PFNGLGETGRAPHICSRESETSTATUSARBPROC __glewGetGraphicsResetStatusARB;
+GLEW_FUN_EXPORT PFNGLGETNCOLORTABLEARBPROC __glewGetnColorTableARB;
+GLEW_FUN_EXPORT PFNGLGETNCOMPRESSEDTEXIMAGEARBPROC __glewGetnCompressedTexImageARB;
+GLEW_FUN_EXPORT PFNGLGETNCONVOLUTIONFILTERARBPROC __glewGetnConvolutionFilterARB;
+GLEW_FUN_EXPORT PFNGLGETNHISTOGRAMARBPROC __glewGetnHistogramARB;
+GLEW_FUN_EXPORT PFNGLGETNMAPDVARBPROC __glewGetnMapdvARB;
+GLEW_FUN_EXPORT PFNGLGETNMAPFVARBPROC __glewGetnMapfvARB;
+GLEW_FUN_EXPORT PFNGLGETNMAPIVARBPROC __glewGetnMapivARB;
+GLEW_FUN_EXPORT PFNGLGETNMINMAXARBPROC __glewGetnMinmaxARB;
+GLEW_FUN_EXPORT PFNGLGETNPIXELMAPFVARBPROC __glewGetnPixelMapfvARB;
+GLEW_FUN_EXPORT PFNGLGETNPIXELMAPUIVARBPROC __glewGetnPixelMapuivARB;
+GLEW_FUN_EXPORT PFNGLGETNPIXELMAPUSVARBPROC __glewGetnPixelMapusvARB;
+GLEW_FUN_EXPORT PFNGLGETNPOLYGONSTIPPLEARBPROC __glewGetnPolygonStippleARB;
+GLEW_FUN_EXPORT PFNGLGETNSEPARABLEFILTERARBPROC __glewGetnSeparableFilterARB;
+GLEW_FUN_EXPORT PFNGLGETNTEXIMAGEARBPROC __glewGetnTexImageARB;
+GLEW_FUN_EXPORT PFNGLGETNUNIFORMDVARBPROC __glewGetnUniformdvARB;
+GLEW_FUN_EXPORT PFNGLGETNUNIFORMFVARBPROC __glewGetnUniformfvARB;
+GLEW_FUN_EXPORT PFNGLGETNUNIFORMIVARBPROC __glewGetnUniformivARB;
+GLEW_FUN_EXPORT PFNGLGETNUNIFORMUIVARBPROC __glewGetnUniformuivARB;
+GLEW_FUN_EXPORT PFNGLREADNPIXELSARBPROC __glewReadnPixelsARB;
+
+GLEW_FUN_EXPORT PFNGLMINSAMPLESHADINGARBPROC __glewMinSampleShadingARB;
+
+GLEW_FUN_EXPORT PFNGLBINDSAMPLERPROC __glewBindSampler;
+GLEW_FUN_EXPORT PFNGLDELETESAMPLERSPROC __glewDeleteSamplers;
+GLEW_FUN_EXPORT PFNGLGENSAMPLERSPROC __glewGenSamplers;
+GLEW_FUN_EXPORT PFNGLGETSAMPLERPARAMETERIIVPROC __glewGetSamplerParameterIiv;
+GLEW_FUN_EXPORT PFNGLGETSAMPLERPARAMETERIUIVPROC __glewGetSamplerParameterIuiv;
+GLEW_FUN_EXPORT PFNGLGETSAMPLERPARAMETERFVPROC __glewGetSamplerParameterfv;
+GLEW_FUN_EXPORT PFNGLGETSAMPLERPARAMETERIVPROC __glewGetSamplerParameteriv;
+GLEW_FUN_EXPORT PFNGLISSAMPLERPROC __glewIsSampler;
+GLEW_FUN_EXPORT PFNGLSAMPLERPARAMETERIIVPROC __glewSamplerParameterIiv;
+GLEW_FUN_EXPORT PFNGLSAMPLERPARAMETERIUIVPROC __glewSamplerParameterIuiv;
+GLEW_FUN_EXPORT PFNGLSAMPLERPARAMETERFPROC __glewSamplerParameterf;
+GLEW_FUN_EXPORT PFNGLSAMPLERPARAMETERFVPROC __glewSamplerParameterfv;
+GLEW_FUN_EXPORT PFNGLSAMPLERPARAMETERIPROC __glewSamplerParameteri;
+GLEW_FUN_EXPORT PFNGLSAMPLERPARAMETERIVPROC __glewSamplerParameteriv;
+
+#if 0 // NOTE jwilkins: inconsistencies between ES and Desktop versions
+GLEW_FUN_EXPORT PFNGLACTIVESHADERPROGRAMPROC __glewActiveShaderProgram;
+GLEW_FUN_EXPORT PFNGLBINDPROGRAMPIPELINEPROC __glewBindProgramPipeline;
+GLEW_FUN_EXPORT PFNGLCREATESHADERPROGRAMVPROC __glewCreateShaderProgramv;
+GLEW_FUN_EXPORT PFNGLDELETEPROGRAMPIPELINESPROC __glewDeleteProgramPipelines;
+GLEW_FUN_EXPORT PFNGLGENPROGRAMPIPELINESPROC __glewGenProgramPipelines;
+GLEW_FUN_EXPORT PFNGLGETPROGRAMPIPELINEINFOLOGPROC __glewGetProgramPipelineInfoLog;
+GLEW_FUN_EXPORT PFNGLGETPROGRAMPIPELINEIVPROC __glewGetProgramPipelineiv;
+GLEW_FUN_EXPORT PFNGLISPROGRAMPIPELINEPROC __glewIsProgramPipeline;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM1DPROC __glewProgramUniform1d;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM1DVPROC __glewProgramUniform1dv;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM1FPROC __glewProgramUniform1f;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM1FVPROC __glewProgramUniform1fv;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM1IPROC __glewProgramUniform1i;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM1IVPROC __glewProgramUniform1iv;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM1UIPROC __glewProgramUniform1ui;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM1UIVPROC __glewProgramUniform1uiv;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM2DPROC __glewProgramUniform2d;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM2DVPROC __glewProgramUniform2dv;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM2FPROC __glewProgramUniform2f;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM2FVPROC __glewProgramUniform2fv;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM2IPROC __glewProgramUniform2i;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM2IVPROC __glewProgramUniform2iv;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM2UIPROC __glewProgramUniform2ui;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM2UIVPROC __glewProgramUniform2uiv;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM3DPROC __glewProgramUniform3d;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM3DVPROC __glewProgramUniform3dv;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM3FPROC __glewProgramUniform3f;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM3FVPROC __glewProgramUniform3fv;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM3IPROC __glewProgramUniform3i;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM3IVPROC __glewProgramUniform3iv;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM3UIPROC __glewProgramUniform3ui;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM3UIVPROC __glewProgramUniform3uiv;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM4DPROC __glewProgramUniform4d;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM4DVPROC __glewProgramUniform4dv;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM4FPROC __glewProgramUniform4f;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM4FVPROC __glewProgramUniform4fv;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM4IPROC __glewProgramUniform4i;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM4IVPROC __glewProgramUniform4iv;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM4UIPROC __glewProgramUniform4ui;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM4UIVPROC __glewProgramUniform4uiv;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX2DVPROC __glewProgramUniformMatrix2dv;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX2FVPROC __glewProgramUniformMatrix2fv;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX2X3DVPROC __glewProgramUniformMatrix2x3dv;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX2X3FVPROC __glewProgramUniformMatrix2x3fv;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX2X4DVPROC __glewProgramUniformMatrix2x4dv;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX2X4FVPROC __glewProgramUniformMatrix2x4fv;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX3DVPROC __glewProgramUniformMatrix3dv;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX3FVPROC __glewProgramUniformMatrix3fv;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX3X2DVPROC __glewProgramUniformMatrix3x2dv;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX3X2FVPROC __glewProgramUniformMatrix3x2fv;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX3X4DVPROC __glewProgramUniformMatrix3x4dv;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX3X4FVPROC __glewProgramUniformMatrix3x4fv;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX4DVPROC __glewProgramUniformMatrix4dv;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX4FVPROC __glewProgramUniformMatrix4fv;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX4X2DVPROC __glewProgramUniformMatrix4x2dv;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX4X2FVPROC __glewProgramUniformMatrix4x2fv;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX4X3DVPROC __glewProgramUniformMatrix4x3dv;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX4X3FVPROC __glewProgramUniformMatrix4x3fv;
+GLEW_FUN_EXPORT PFNGLUSEPROGRAMSTAGESPROC __glewUseProgramStages;
+GLEW_FUN_EXPORT PFNGLVALIDATEPROGRAMPIPELINEPROC __glewValidateProgramPipeline;
+#endif
+
+GLEW_FUN_EXPORT PFNGLGETACTIVEATOMICCOUNTERBUFFERIVPROC __glewGetActiveAtomicCounterBufferiv;
+
+GLEW_FUN_EXPORT PFNGLBINDIMAGETEXTUREPROC __glewBindImageTexture;
+GLEW_FUN_EXPORT PFNGLMEMORYBARRIERPROC __glewMemoryBarrier;
+
+GLEW_FUN_EXPORT PFNGLATTACHOBJECTARBPROC __glewAttachObjectARB;
+GLEW_FUN_EXPORT PFNGLCOMPILESHADERARBPROC __glewCompileShaderARB;
+GLEW_FUN_EXPORT PFNGLCREATEPROGRAMOBJECTARBPROC __glewCreateProgramObjectARB;
+GLEW_FUN_EXPORT PFNGLCREATESHADEROBJECTARBPROC __glewCreateShaderObjectARB;
+GLEW_FUN_EXPORT PFNGLDELETEOBJECTARBPROC __glewDeleteObjectARB;
+GLEW_FUN_EXPORT PFNGLDETACHOBJECTARBPROC __glewDetachObjectARB;
+GLEW_FUN_EXPORT PFNGLGETACTIVEUNIFORMARBPROC __glewGetActiveUniformARB;
+GLEW_FUN_EXPORT PFNGLGETATTACHEDOBJECTSARBPROC __glewGetAttachedObjectsARB;
+GLEW_FUN_EXPORT PFNGLGETHANDLEARBPROC __glewGetHandleARB;
+GLEW_FUN_EXPORT PFNGLGETINFOLOGARBPROC __glewGetInfoLogARB;
+GLEW_FUN_EXPORT PFNGLGETOBJECTPARAMETERFVARBPROC __glewGetObjectParameterfvARB;
+GLEW_FUN_EXPORT PFNGLGETOBJECTPARAMETERIVARBPROC __glewGetObjectParameterivARB;
+GLEW_FUN_EXPORT PFNGLGETSHADERSOURCEARBPROC __glewGetShaderSourceARB;
+GLEW_FUN_EXPORT PFNGLGETUNIFORMLOCATIONARBPROC __glewGetUniformLocationARB;
+GLEW_FUN_EXPORT PFNGLGETUNIFORMFVARBPROC __glewGetUniformfvARB;
+GLEW_FUN_EXPORT PFNGLGETUNIFORMIVARBPROC __glewGetUniformivARB;
+GLEW_FUN_EXPORT PFNGLLINKPROGRAMARBPROC __glewLinkProgramARB;
+GLEW_FUN_EXPORT PFNGLSHADERSOURCEARBPROC __glewShaderSourceARB;
+GLEW_FUN_EXPORT PFNGLUNIFORM1FARBPROC __glewUniform1fARB;
+GLEW_FUN_EXPORT PFNGLUNIFORM1FVARBPROC __glewUniform1fvARB;
+GLEW_FUN_EXPORT PFNGLUNIFORM1IARBPROC __glewUniform1iARB;
+GLEW_FUN_EXPORT PFNGLUNIFORM1IVARBPROC __glewUniform1ivARB;
+GLEW_FUN_EXPORT PFNGLUNIFORM2FARBPROC __glewUniform2fARB;
+GLEW_FUN_EXPORT PFNGLUNIFORM2FVARBPROC __glewUniform2fvARB;
+GLEW_FUN_EXPORT PFNGLUNIFORM2IARBPROC __glewUniform2iARB;
+GLEW_FUN_EXPORT PFNGLUNIFORM2IVARBPROC __glewUniform2ivARB;
+GLEW_FUN_EXPORT PFNGLUNIFORM3FARBPROC __glewUniform3fARB;
+GLEW_FUN_EXPORT PFNGLUNIFORM3FVARBPROC __glewUniform3fvARB;
+GLEW_FUN_EXPORT PFNGLUNIFORM3IARBPROC __glewUniform3iARB;
+GLEW_FUN_EXPORT PFNGLUNIFORM3IVARBPROC __glewUniform3ivARB;
+GLEW_FUN_EXPORT PFNGLUNIFORM4FARBPROC __glewUniform4fARB;
+GLEW_FUN_EXPORT PFNGLUNIFORM4FVARBPROC __glewUniform4fvARB;
+GLEW_FUN_EXPORT PFNGLUNIFORM4IARBPROC __glewUniform4iARB;
+GLEW_FUN_EXPORT PFNGLUNIFORM4IVARBPROC __glewUniform4ivARB;
+GLEW_FUN_EXPORT PFNGLUNIFORMMATRIX2FVARBPROC __glewUniformMatrix2fvARB;
+GLEW_FUN_EXPORT PFNGLUNIFORMMATRIX3FVARBPROC __glewUniformMatrix3fvARB;
+GLEW_FUN_EXPORT PFNGLUNIFORMMATRIX4FVARBPROC __glewUniformMatrix4fvARB;
+GLEW_FUN_EXPORT PFNGLUSEPROGRAMOBJECTARBPROC __glewUseProgramObjectARB;
+GLEW_FUN_EXPORT PFNGLVALIDATEPROGRAMARBPROC __glewValidateProgramARB;
+
+GLEW_FUN_EXPORT PFNGLSHADERSTORAGEBLOCKBINDINGPROC __glewShaderStorageBlockBinding;
+
+GLEW_FUN_EXPORT PFNGLGETACTIVESUBROUTINENAMEPROC __glewGetActiveSubroutineName;
+GLEW_FUN_EXPORT PFNGLGETACTIVESUBROUTINEUNIFORMNAMEPROC __glewGetActiveSubroutineUniformName;
+GLEW_FUN_EXPORT PFNGLGETACTIVESUBROUTINEUNIFORMIVPROC __glewGetActiveSubroutineUniformiv;
+GLEW_FUN_EXPORT PFNGLGETPROGRAMSTAGEIVPROC __glewGetProgramStageiv;
+GLEW_FUN_EXPORT PFNGLGETSUBROUTINEINDEXPROC __glewGetSubroutineIndex;
+GLEW_FUN_EXPORT PFNGLGETSUBROUTINEUNIFORMLOCATIONPROC __glewGetSubroutineUniformLocation;
+GLEW_FUN_EXPORT PFNGLGETUNIFORMSUBROUTINEUIVPROC __glewGetUniformSubroutineuiv;
+GLEW_FUN_EXPORT PFNGLUNIFORMSUBROUTINESUIVPROC __glewUniformSubroutinesuiv;
+
+GLEW_FUN_EXPORT PFNGLCOMPILESHADERINCLUDEARBPROC __glewCompileShaderIncludeARB;
+GLEW_FUN_EXPORT PFNGLDELETENAMEDSTRINGARBPROC __glewDeleteNamedStringARB;
+GLEW_FUN_EXPORT PFNGLGETNAMEDSTRINGARBPROC __glewGetNamedStringARB;
+GLEW_FUN_EXPORT PFNGLGETNAMEDSTRINGIVARBPROC __glewGetNamedStringivARB;
+GLEW_FUN_EXPORT PFNGLISNAMEDSTRINGARBPROC __glewIsNamedStringARB;
+GLEW_FUN_EXPORT PFNGLNAMEDSTRINGARBPROC __glewNamedStringARB;
+
+GLEW_FUN_EXPORT PFNGLCLIENTWAITSYNCPROC __glewClientWaitSync;
+GLEW_FUN_EXPORT PFNGLDELETESYNCPROC __glewDeleteSync;
+GLEW_FUN_EXPORT PFNGLFENCESYNCPROC __glewFenceSync;
+GLEW_FUN_EXPORT PFNGLGETINTEGER64VPROC __glewGetInteger64v;
+GLEW_FUN_EXPORT PFNGLGETSYNCIVPROC __glewGetSynciv;
+GLEW_FUN_EXPORT PFNGLISSYNCPROC __glewIsSync;
+GLEW_FUN_EXPORT PFNGLWAITSYNCPROC __glewWaitSync;
+
+GLEW_FUN_EXPORT PFNGLPATCHPARAMETERFVPROC __glewPatchParameterfv;
+GLEW_FUN_EXPORT PFNGLPATCHPARAMETERIPROC __glewPatchParameteri;
+
+GLEW_FUN_EXPORT PFNGLTEXBUFFERARBPROC __glewTexBufferARB;
+
+GLEW_FUN_EXPORT PFNGLTEXBUFFERRANGEPROC __glewTexBufferRange;
+GLEW_FUN_EXPORT PFNGLTEXTUREBUFFERRANGEEXTPROC __glewTextureBufferRangeEXT;
+
+GLEW_FUN_EXPORT PFNGLCOMPRESSEDTEXIMAGE1DARBPROC __glewCompressedTexImage1DARB;
+GLEW_FUN_EXPORT PFNGLCOMPRESSEDTEXIMAGE2DARBPROC __glewCompressedTexImage2DARB;
+GLEW_FUN_EXPORT PFNGLCOMPRESSEDTEXIMAGE3DARBPROC __glewCompressedTexImage3DARB;
+GLEW_FUN_EXPORT PFNGLCOMPRESSEDTEXSUBIMAGE1DARBPROC __glewCompressedTexSubImage1DARB;
+GLEW_FUN_EXPORT PFNGLCOMPRESSEDTEXSUBIMAGE2DARBPROC __glewCompressedTexSubImage2DARB;
+GLEW_FUN_EXPORT PFNGLCOMPRESSEDTEXSUBIMAGE3DARBPROC __glewCompressedTexSubImage3DARB;
+GLEW_FUN_EXPORT PFNGLGETCOMPRESSEDTEXIMAGEARBPROC __glewGetCompressedTexImageARB;
+
+GLEW_FUN_EXPORT PFNGLGETMULTISAMPLEFVPROC __glewGetMultisamplefv;
+GLEW_FUN_EXPORT PFNGLSAMPLEMASKIPROC __glewSampleMaski;
+GLEW_FUN_EXPORT PFNGLTEXIMAGE2DMULTISAMPLEPROC __glewTexImage2DMultisample;
+GLEW_FUN_EXPORT PFNGLTEXIMAGE3DMULTISAMPLEPROC __glewTexImage3DMultisample;
+
+GLEW_FUN_EXPORT PFNGLTEXSTORAGE1DPROC __glewTexStorage1D;
+GLEW_FUN_EXPORT PFNGLTEXSTORAGE2DPROC __glewTexStorage2D;
+GLEW_FUN_EXPORT PFNGLTEXSTORAGE3DPROC __glewTexStorage3D;
+GLEW_FUN_EXPORT PFNGLTEXTURESTORAGE1DEXTPROC __glewTextureStorage1DEXT;
+GLEW_FUN_EXPORT PFNGLTEXTURESTORAGE2DEXTPROC __glewTextureStorage2DEXT;
+GLEW_FUN_EXPORT PFNGLTEXTURESTORAGE3DEXTPROC __glewTextureStorage3DEXT;
+
+GLEW_FUN_EXPORT PFNGLTEXSTORAGE2DMULTISAMPLEPROC __glewTexStorage2DMultisample;
+GLEW_FUN_EXPORT PFNGLTEXSTORAGE3DMULTISAMPLEPROC __glewTexStorage3DMultisample;
+GLEW_FUN_EXPORT PFNGLTEXTURESTORAGE2DMULTISAMPLEEXTPROC __glewTextureStorage2DMultisampleEXT;
+GLEW_FUN_EXPORT PFNGLTEXTURESTORAGE3DMULTISAMPLEEXTPROC __glewTextureStorage3DMultisampleEXT;
+
+GLEW_FUN_EXPORT PFNGLTEXTUREVIEWPROC __glewTextureView;
+
+GLEW_FUN_EXPORT PFNGLGETQUERYOBJECTI64VPROC __glewGetQueryObjecti64v;
+GLEW_FUN_EXPORT PFNGLGETQUERYOBJECTUI64VPROC __glewGetQueryObjectui64v;
+GLEW_FUN_EXPORT PFNGLQUERYCOUNTERPROC __glewQueryCounter;
+
+GLEW_FUN_EXPORT PFNGLBINDTRANSFORMFEEDBACKPROC __glewBindTransformFeedback;
+GLEW_FUN_EXPORT PFNGLDELETETRANSFORMFEEDBACKSPROC __glewDeleteTransformFeedbacks;
+GLEW_FUN_EXPORT PFNGLDRAWTRANSFORMFEEDBACKPROC __glewDrawTransformFeedback;
+GLEW_FUN_EXPORT PFNGLGENTRANSFORMFEEDBACKSPROC __glewGenTransformFeedbacks;
+GLEW_FUN_EXPORT PFNGLISTRANSFORMFEEDBACKPROC __glewIsTransformFeedback;
+GLEW_FUN_EXPORT PFNGLPAUSETRANSFORMFEEDBACKPROC __glewPauseTransformFeedback;
+GLEW_FUN_EXPORT PFNGLRESUMETRANSFORMFEEDBACKPROC __glewResumeTransformFeedback;
+
+GLEW_FUN_EXPORT PFNGLBEGINQUERYINDEXEDPROC __glewBeginQueryIndexed;
+GLEW_FUN_EXPORT PFNGLDRAWTRANSFORMFEEDBACKSTREAMPROC __glewDrawTransformFeedbackStream;
+GLEW_FUN_EXPORT PFNGLENDQUERYINDEXEDPROC __glewEndQueryIndexed;
+GLEW_FUN_EXPORT PFNGLGETQUERYINDEXEDIVPROC __glewGetQueryIndexediv;
+
+GLEW_FUN_EXPORT PFNGLDRAWTRANSFORMFEEDBACKINSTANCEDPROC __glewDrawTransformFeedbackInstanced;
+GLEW_FUN_EXPORT PFNGLDRAWTRANSFORMFEEDBACKSTREAMINSTANCEDPROC __glewDrawTransformFeedbackStreamInstanced;
+
+GLEW_FUN_EXPORT PFNGLLOADTRANSPOSEMATRIXDARBPROC __glewLoadTransposeMatrixdARB;
+GLEW_FUN_EXPORT PFNGLLOADTRANSPOSEMATRIXFARBPROC __glewLoadTransposeMatrixfARB;
+GLEW_FUN_EXPORT PFNGLMULTTRANSPOSEMATRIXDARBPROC __glewMultTransposeMatrixdARB;
+GLEW_FUN_EXPORT PFNGLMULTTRANSPOSEMATRIXFARBPROC __glewMultTransposeMatrixfARB;
+
+GLEW_FUN_EXPORT PFNGLBINDBUFFERBASEPROC __glewBindBufferBase;
+GLEW_FUN_EXPORT PFNGLBINDBUFFERRANGEPROC __glewBindBufferRange;
+GLEW_FUN_EXPORT PFNGLGETACTIVEUNIFORMBLOCKNAMEPROC __glewGetActiveUniformBlockName;
+GLEW_FUN_EXPORT PFNGLGETACTIVEUNIFORMBLOCKIVPROC __glewGetActiveUniformBlockiv;
+GLEW_FUN_EXPORT PFNGLGETACTIVEUNIFORMNAMEPROC __glewGetActiveUniformName;
+GLEW_FUN_EXPORT PFNGLGETACTIVEUNIFORMSIVPROC __glewGetActiveUniformsiv;
+GLEW_FUN_EXPORT PFNGLGETINTEGERI_VPROC __glewGetIntegeri_v;
+GLEW_FUN_EXPORT PFNGLGETUNIFORMBLOCKINDEXPROC __glewGetUniformBlockIndex;
+GLEW_FUN_EXPORT PFNGLGETUNIFORMINDICESPROC __glewGetUniformIndices;
+GLEW_FUN_EXPORT PFNGLUNIFORMBLOCKBINDINGPROC __glewUniformBlockBinding;
+
+GLEW_FUN_EXPORT PFNGLBINDVERTEXARRAYPROC __glewBindVertexArray;
+GLEW_FUN_EXPORT PFNGLDELETEVERTEXARRAYSPROC __glewDeleteVertexArrays;
+GLEW_FUN_EXPORT PFNGLGENVERTEXARRAYSPROC __glewGenVertexArrays;
+GLEW_FUN_EXPORT PFNGLISVERTEXARRAYPROC __glewIsVertexArray;
+
+GLEW_FUN_EXPORT PFNGLGETVERTEXATTRIBLDVPROC __glewGetVertexAttribLdv;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL1DPROC __glewVertexAttribL1d;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL1DVPROC __glewVertexAttribL1dv;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL2DPROC __glewVertexAttribL2d;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL2DVPROC __glewVertexAttribL2dv;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL3DPROC __glewVertexAttribL3d;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL3DVPROC __glewVertexAttribL3dv;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL4DPROC __glewVertexAttribL4d;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL4DVPROC __glewVertexAttribL4dv;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBLPOINTERPROC __glewVertexAttribLPointer;
+
+GLEW_FUN_EXPORT PFNGLBINDVERTEXBUFFERPROC __glewBindVertexBuffer;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBBINDINGPROC __glewVertexAttribBinding;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBFORMATPROC __glewVertexAttribFormat;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBIFORMATPROC __glewVertexAttribIFormat;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBLFORMATPROC __glewVertexAttribLFormat;
+GLEW_FUN_EXPORT PFNGLVERTEXBINDINGDIVISORPROC __glewVertexBindingDivisor;
+
+GLEW_FUN_EXPORT PFNGLVERTEXBLENDARBPROC __glewVertexBlendARB;
+GLEW_FUN_EXPORT PFNGLWEIGHTPOINTERARBPROC __glewWeightPointerARB;
+GLEW_FUN_EXPORT PFNGLWEIGHTBVARBPROC __glewWeightbvARB;
+GLEW_FUN_EXPORT PFNGLWEIGHTDVARBPROC __glewWeightdvARB;
+GLEW_FUN_EXPORT PFNGLWEIGHTFVARBPROC __glewWeightfvARB;
+GLEW_FUN_EXPORT PFNGLWEIGHTIVARBPROC __glewWeightivARB;
+GLEW_FUN_EXPORT PFNGLWEIGHTSVARBPROC __glewWeightsvARB;
+GLEW_FUN_EXPORT PFNGLWEIGHTUBVARBPROC __glewWeightubvARB;
+GLEW_FUN_EXPORT PFNGLWEIGHTUIVARBPROC __glewWeightuivARB;
+GLEW_FUN_EXPORT PFNGLWEIGHTUSVARBPROC __glewWeightusvARB;
+
+GLEW_FUN_EXPORT PFNGLBINDBUFFERARBPROC __glewBindBufferARB;
+GLEW_FUN_EXPORT PFNGLBUFFERDATAARBPROC __glewBufferDataARB;
+GLEW_FUN_EXPORT PFNGLBUFFERSUBDATAARBPROC __glewBufferSubDataARB;
+GLEW_FUN_EXPORT PFNGLDELETEBUFFERSARBPROC __glewDeleteBuffersARB;
+GLEW_FUN_EXPORT PFNGLGENBUFFERSARBPROC __glewGenBuffersARB;
+GLEW_FUN_EXPORT PFNGLGETBUFFERPARAMETERIVARBPROC __glewGetBufferParameterivARB;
+GLEW_FUN_EXPORT PFNGLGETBUFFERPOINTERVARBPROC __glewGetBufferPointervARB;
+GLEW_FUN_EXPORT PFNGLGETBUFFERSUBDATAARBPROC __glewGetBufferSubDataARB;
+GLEW_FUN_EXPORT PFNGLISBUFFERARBPROC __glewIsBufferARB;
+GLEW_FUN_EXPORT PFNGLMAPBUFFERARBPROC __glewMapBufferARB;
+GLEW_FUN_EXPORT PFNGLUNMAPBUFFERARBPROC __glewUnmapBufferARB;
+
+GLEW_FUN_EXPORT PFNGLBINDPROGRAMARBPROC __glewBindProgramARB;
+GLEW_FUN_EXPORT PFNGLDELETEPROGRAMSARBPROC __glewDeleteProgramsARB;
+GLEW_FUN_EXPORT PFNGLDISABLEVERTEXATTRIBARRAYARBPROC __glewDisableVertexAttribArrayARB;
+GLEW_FUN_EXPORT PFNGLENABLEVERTEXATTRIBARRAYARBPROC __glewEnableVertexAttribArrayARB;
+GLEW_FUN_EXPORT PFNGLGENPROGRAMSARBPROC __glewGenProgramsARB;
+GLEW_FUN_EXPORT PFNGLGETPROGRAMENVPARAMETERDVARBPROC __glewGetProgramEnvParameterdvARB;
+GLEW_FUN_EXPORT PFNGLGETPROGRAMENVPARAMETERFVARBPROC __glewGetProgramEnvParameterfvARB;
+GLEW_FUN_EXPORT PFNGLGETPROGRAMLOCALPARAMETERDVARBPROC __glewGetProgramLocalParameterdvARB;
+GLEW_FUN_EXPORT PFNGLGETPROGRAMLOCALPARAMETERFVARBPROC __glewGetProgramLocalParameterfvARB;
+GLEW_FUN_EXPORT PFNGLGETPROGRAMSTRINGARBPROC __glewGetProgramStringARB;
+GLEW_FUN_EXPORT PFNGLGETPROGRAMIVARBPROC __glewGetProgramivARB;
+GLEW_FUN_EXPORT PFNGLGETVERTEXATTRIBPOINTERVARBPROC __glewGetVertexAttribPointervARB;
+GLEW_FUN_EXPORT PFNGLGETVERTEXATTRIBDVARBPROC __glewGetVertexAttribdvARB;
+GLEW_FUN_EXPORT PFNGLGETVERTEXATTRIBFVARBPROC __glewGetVertexAttribfvARB;
+GLEW_FUN_EXPORT PFNGLGETVERTEXATTRIBIVARBPROC __glewGetVertexAttribivARB;
+GLEW_FUN_EXPORT PFNGLISPROGRAMARBPROC __glewIsProgramARB;
+GLEW_FUN_EXPORT PFNGLPROGRAMENVPARAMETER4DARBPROC __glewProgramEnvParameter4dARB;
+GLEW_FUN_EXPORT PFNGLPROGRAMENVPARAMETER4DVARBPROC __glewProgramEnvParameter4dvARB;
+GLEW_FUN_EXPORT PFNGLPROGRAMENVPARAMETER4FARBPROC __glewProgramEnvParameter4fARB;
+GLEW_FUN_EXPORT PFNGLPROGRAMENVPARAMETER4FVARBPROC __glewProgramEnvParameter4fvARB;
+GLEW_FUN_EXPORT PFNGLPROGRAMLOCALPARAMETER4DARBPROC __glewProgramLocalParameter4dARB;
+GLEW_FUN_EXPORT PFNGLPROGRAMLOCALPARAMETER4DVARBPROC __glewProgramLocalParameter4dvARB;
+GLEW_FUN_EXPORT PFNGLPROGRAMLOCALPARAMETER4FARBPROC __glewProgramLocalParameter4fARB;
+GLEW_FUN_EXPORT PFNGLPROGRAMLOCALPARAMETER4FVARBPROC __glewProgramLocalParameter4fvARB;
+GLEW_FUN_EXPORT PFNGLPROGRAMSTRINGARBPROC __glewProgramStringARB;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB1DARBPROC __glewVertexAttrib1dARB;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB1DVARBPROC __glewVertexAttrib1dvARB;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB1FARBPROC __glewVertexAttrib1fARB;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB1FVARBPROC __glewVertexAttrib1fvARB;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB1SARBPROC __glewVertexAttrib1sARB;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB1SVARBPROC __glewVertexAttrib1svARB;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB2DARBPROC __glewVertexAttrib2dARB;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB2DVARBPROC __glewVertexAttrib2dvARB;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB2FARBPROC __glewVertexAttrib2fARB;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB2FVARBPROC __glewVertexAttrib2fvARB;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB2SARBPROC __glewVertexAttrib2sARB;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB2SVARBPROC __glewVertexAttrib2svARB;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB3DARBPROC __glewVertexAttrib3dARB;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB3DVARBPROC __glewVertexAttrib3dvARB;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB3FARBPROC __glewVertexAttrib3fARB;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB3FVARBPROC __glewVertexAttrib3fvARB;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB3SARBPROC __glewVertexAttrib3sARB;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB3SVARBPROC __glewVertexAttrib3svARB;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4NBVARBPROC __glewVertexAttrib4NbvARB;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4NIVARBPROC __glewVertexAttrib4NivARB;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4NSVARBPROC __glewVertexAttrib4NsvARB;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4NUBARBPROC __glewVertexAttrib4NubARB;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4NUBVARBPROC __glewVertexAttrib4NubvARB;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4NUIVARBPROC __glewVertexAttrib4NuivARB;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4NUSVARBPROC __glewVertexAttrib4NusvARB;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4BVARBPROC __glewVertexAttrib4bvARB;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4DARBPROC __glewVertexAttrib4dARB;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4DVARBPROC __glewVertexAttrib4dvARB;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4FARBPROC __glewVertexAttrib4fARB;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4FVARBPROC __glewVertexAttrib4fvARB;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4IVARBPROC __glewVertexAttrib4ivARB;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4SARBPROC __glewVertexAttrib4sARB;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4SVARBPROC __glewVertexAttrib4svARB;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4UBVARBPROC __glewVertexAttrib4ubvARB;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4UIVARBPROC __glewVertexAttrib4uivARB;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4USVARBPROC __glewVertexAttrib4usvARB;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBPOINTERARBPROC __glewVertexAttribPointerARB;
+
+GLEW_FUN_EXPORT PFNGLBINDATTRIBLOCATIONARBPROC __glewBindAttribLocationARB;
+GLEW_FUN_EXPORT PFNGLGETACTIVEATTRIBARBPROC __glewGetActiveAttribARB;
+GLEW_FUN_EXPORT PFNGLGETATTRIBLOCATIONARBPROC __glewGetAttribLocationARB;
+
+GLEW_FUN_EXPORT PFNGLCOLORP3UIPROC __glewColorP3ui;
+GLEW_FUN_EXPORT PFNGLCOLORP3UIVPROC __glewColorP3uiv;
+GLEW_FUN_EXPORT PFNGLCOLORP4UIPROC __glewColorP4ui;
+GLEW_FUN_EXPORT PFNGLCOLORP4UIVPROC __glewColorP4uiv;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORDP1UIPROC __glewMultiTexCoordP1ui;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORDP1UIVPROC __glewMultiTexCoordP1uiv;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORDP2UIPROC __glewMultiTexCoordP2ui;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORDP2UIVPROC __glewMultiTexCoordP2uiv;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORDP3UIPROC __glewMultiTexCoordP3ui;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORDP3UIVPROC __glewMultiTexCoordP3uiv;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORDP4UIPROC __glewMultiTexCoordP4ui;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORDP4UIVPROC __glewMultiTexCoordP4uiv;
+GLEW_FUN_EXPORT PFNGLNORMALP3UIPROC __glewNormalP3ui;
+GLEW_FUN_EXPORT PFNGLNORMALP3UIVPROC __glewNormalP3uiv;
+GLEW_FUN_EXPORT PFNGLSECONDARYCOLORP3UIPROC __glewSecondaryColorP3ui;
+GLEW_FUN_EXPORT PFNGLSECONDARYCOLORP3UIVPROC __glewSecondaryColorP3uiv;
+GLEW_FUN_EXPORT PFNGLTEXCOORDP1UIPROC __glewTexCoordP1ui;
+GLEW_FUN_EXPORT PFNGLTEXCOORDP1UIVPROC __glewTexCoordP1uiv;
+GLEW_FUN_EXPORT PFNGLTEXCOORDP2UIPROC __glewTexCoordP2ui;
+GLEW_FUN_EXPORT PFNGLTEXCOORDP2UIVPROC __glewTexCoordP2uiv;
+GLEW_FUN_EXPORT PFNGLTEXCOORDP3UIPROC __glewTexCoordP3ui;
+GLEW_FUN_EXPORT PFNGLTEXCOORDP3UIVPROC __glewTexCoordP3uiv;
+GLEW_FUN_EXPORT PFNGLTEXCOORDP4UIPROC __glewTexCoordP4ui;
+GLEW_FUN_EXPORT PFNGLTEXCOORDP4UIVPROC __glewTexCoordP4uiv;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBP1UIPROC __glewVertexAttribP1ui;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBP1UIVPROC __glewVertexAttribP1uiv;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBP2UIPROC __glewVertexAttribP2ui;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBP2UIVPROC __glewVertexAttribP2uiv;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBP3UIPROC __glewVertexAttribP3ui;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBP3UIVPROC __glewVertexAttribP3uiv;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBP4UIPROC __glewVertexAttribP4ui;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBP4UIVPROC __glewVertexAttribP4uiv;
+GLEW_FUN_EXPORT PFNGLVERTEXP2UIPROC __glewVertexP2ui;
+GLEW_FUN_EXPORT PFNGLVERTEXP2UIVPROC __glewVertexP2uiv;
+GLEW_FUN_EXPORT PFNGLVERTEXP3UIPROC __glewVertexP3ui;
+GLEW_FUN_EXPORT PFNGLVERTEXP3UIVPROC __glewVertexP3uiv;
+GLEW_FUN_EXPORT PFNGLVERTEXP4UIPROC __glewVertexP4ui;
+GLEW_FUN_EXPORT PFNGLVERTEXP4UIVPROC __glewVertexP4uiv;
+
+GLEW_FUN_EXPORT PFNGLDEPTHRANGEARRAYVPROC __glewDepthRangeArrayv;
+GLEW_FUN_EXPORT PFNGLDEPTHRANGEINDEXEDPROC __glewDepthRangeIndexed;
+GLEW_FUN_EXPORT PFNGLGETDOUBLEI_VPROC __glewGetDoublei_v;
+GLEW_FUN_EXPORT PFNGLGETFLOATI_VPROC __glewGetFloati_v;
+GLEW_FUN_EXPORT PFNGLSCISSORARRAYVPROC __glewScissorArrayv;
+GLEW_FUN_EXPORT PFNGLSCISSORINDEXEDPROC __glewScissorIndexed;
+GLEW_FUN_EXPORT PFNGLSCISSORINDEXEDVPROC __glewScissorIndexedv;
+GLEW_FUN_EXPORT PFNGLVIEWPORTARRAYVPROC __glewViewportArrayv;
+GLEW_FUN_EXPORT PFNGLVIEWPORTINDEXEDFPROC __glewViewportIndexedf;
+GLEW_FUN_EXPORT PFNGLVIEWPORTINDEXEDFVPROC __glewViewportIndexedfv;
+
+GLEW_FUN_EXPORT PFNGLWINDOWPOS2DARBPROC __glewWindowPos2dARB;
+GLEW_FUN_EXPORT PFNGLWINDOWPOS2DVARBPROC __glewWindowPos2dvARB;
+GLEW_FUN_EXPORT PFNGLWINDOWPOS2FARBPROC __glewWindowPos2fARB;
+GLEW_FUN_EXPORT PFNGLWINDOWPOS2FVARBPROC __glewWindowPos2fvARB;
+GLEW_FUN_EXPORT PFNGLWINDOWPOS2IARBPROC __glewWindowPos2iARB;
+GLEW_FUN_EXPORT PFNGLWINDOWPOS2IVARBPROC __glewWindowPos2ivARB;
+GLEW_FUN_EXPORT PFNGLWINDOWPOS2SARBPROC __glewWindowPos2sARB;
+GLEW_FUN_EXPORT PFNGLWINDOWPOS2SVARBPROC __glewWindowPos2svARB;
+GLEW_FUN_EXPORT PFNGLWINDOWPOS3DARBPROC __glewWindowPos3dARB;
+GLEW_FUN_EXPORT PFNGLWINDOWPOS3DVARBPROC __glewWindowPos3dvARB;
+GLEW_FUN_EXPORT PFNGLWINDOWPOS3FARBPROC __glewWindowPos3fARB;
+GLEW_FUN_EXPORT PFNGLWINDOWPOS3FVARBPROC __glewWindowPos3fvARB;
+GLEW_FUN_EXPORT PFNGLWINDOWPOS3IARBPROC __glewWindowPos3iARB;
+GLEW_FUN_EXPORT PFNGLWINDOWPOS3IVARBPROC __glewWindowPos3ivARB;
+GLEW_FUN_EXPORT PFNGLWINDOWPOS3SARBPROC __glewWindowPos3sARB;
+GLEW_FUN_EXPORT PFNGLWINDOWPOS3SVARBPROC __glewWindowPos3svARB;
+
+GLEW_FUN_EXPORT PFNGLDRAWBUFFERSATIPROC __glewDrawBuffersATI;
+
+GLEW_FUN_EXPORT PFNGLDRAWELEMENTARRAYATIPROC __glewDrawElementArrayATI;
+GLEW_FUN_EXPORT PFNGLDRAWRANGEELEMENTARRAYATIPROC __glewDrawRangeElementArrayATI;
+GLEW_FUN_EXPORT PFNGLELEMENTPOINTERATIPROC __glewElementPointerATI;
+
+GLEW_FUN_EXPORT PFNGLGETTEXBUMPPARAMETERFVATIPROC __glewGetTexBumpParameterfvATI;
+GLEW_FUN_EXPORT PFNGLGETTEXBUMPPARAMETERIVATIPROC __glewGetTexBumpParameterivATI;
+GLEW_FUN_EXPORT PFNGLTEXBUMPPARAMETERFVATIPROC __glewTexBumpParameterfvATI;
+GLEW_FUN_EXPORT PFNGLTEXBUMPPARAMETERIVATIPROC __glewTexBumpParameterivATI;
+
+GLEW_FUN_EXPORT PFNGLALPHAFRAGMENTOP1ATIPROC __glewAlphaFragmentOp1ATI;
+GLEW_FUN_EXPORT PFNGLALPHAFRAGMENTOP2ATIPROC __glewAlphaFragmentOp2ATI;
+GLEW_FUN_EXPORT PFNGLALPHAFRAGMENTOP3ATIPROC __glewAlphaFragmentOp3ATI;
+GLEW_FUN_EXPORT PFNGLBEGINFRAGMENTSHADERATIPROC __glewBeginFragmentShaderATI;
+GLEW_FUN_EXPORT PFNGLBINDFRAGMENTSHADERATIPROC __glewBindFragmentShaderATI;
+GLEW_FUN_EXPORT PFNGLCOLORFRAGMENTOP1ATIPROC __glewColorFragmentOp1ATI;
+GLEW_FUN_EXPORT PFNGLCOLORFRAGMENTOP2ATIPROC __glewColorFragmentOp2ATI;
+GLEW_FUN_EXPORT PFNGLCOLORFRAGMENTOP3ATIPROC __glewColorFragmentOp3ATI;
+GLEW_FUN_EXPORT PFNGLDELETEFRAGMENTSHADERATIPROC __glewDeleteFragmentShaderATI;
+GLEW_FUN_EXPORT PFNGLENDFRAGMENTSHADERATIPROC __glewEndFragmentShaderATI;
+GLEW_FUN_EXPORT PFNGLGENFRAGMENTSHADERSATIPROC __glewGenFragmentShadersATI;
+GLEW_FUN_EXPORT PFNGLPASSTEXCOORDATIPROC __glewPassTexCoordATI;
+GLEW_FUN_EXPORT PFNGLSAMPLEMAPATIPROC __glewSampleMapATI;
+GLEW_FUN_EXPORT PFNGLSETFRAGMENTSHADERCONSTANTATIPROC __glewSetFragmentShaderConstantATI;
+
+GLEW_FUN_EXPORT PFNGLMAPOBJECTBUFFERATIPROC __glewMapObjectBufferATI;
+GLEW_FUN_EXPORT PFNGLUNMAPOBJECTBUFFERATIPROC __glewUnmapObjectBufferATI;
+
+GLEW_FUN_EXPORT PFNGLPNTRIANGLESFATIPROC __glewPNTrianglesfATI;
+GLEW_FUN_EXPORT PFNGLPNTRIANGLESIATIPROC __glewPNTrianglesiATI;
+
+GLEW_FUN_EXPORT PFNGLSTENCILFUNCSEPARATEATIPROC __glewStencilFuncSeparateATI;
+GLEW_FUN_EXPORT PFNGLSTENCILOPSEPARATEATIPROC __glewStencilOpSeparateATI;
+
+GLEW_FUN_EXPORT PFNGLARRAYOBJECTATIPROC __glewArrayObjectATI;
+GLEW_FUN_EXPORT PFNGLFREEOBJECTBUFFERATIPROC __glewFreeObjectBufferATI;
+GLEW_FUN_EXPORT PFNGLGETARRAYOBJECTFVATIPROC __glewGetArrayObjectfvATI;
+GLEW_FUN_EXPORT PFNGLGETARRAYOBJECTIVATIPROC __glewGetArrayObjectivATI;
+GLEW_FUN_EXPORT PFNGLGETOBJECTBUFFERFVATIPROC __glewGetObjectBufferfvATI;
+GLEW_FUN_EXPORT PFNGLGETOBJECTBUFFERIVATIPROC __glewGetObjectBufferivATI;
+GLEW_FUN_EXPORT PFNGLGETVARIANTARRAYOBJECTFVATIPROC __glewGetVariantArrayObjectfvATI;
+GLEW_FUN_EXPORT PFNGLGETVARIANTARRAYOBJECTIVATIPROC __glewGetVariantArrayObjectivATI;
+GLEW_FUN_EXPORT PFNGLISOBJECTBUFFERATIPROC __glewIsObjectBufferATI;
+GLEW_FUN_EXPORT PFNGLNEWOBJECTBUFFERATIPROC __glewNewObjectBufferATI;
+GLEW_FUN_EXPORT PFNGLUPDATEOBJECTBUFFERATIPROC __glewUpdateObjectBufferATI;
+GLEW_FUN_EXPORT PFNGLVARIANTARRAYOBJECTATIPROC __glewVariantArrayObjectATI;
+
+GLEW_FUN_EXPORT PFNGLGETVERTEXATTRIBARRAYOBJECTFVATIPROC __glewGetVertexAttribArrayObjectfvATI;
+GLEW_FUN_EXPORT PFNGLGETVERTEXATTRIBARRAYOBJECTIVATIPROC __glewGetVertexAttribArrayObjectivATI;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBARRAYOBJECTATIPROC __glewVertexAttribArrayObjectATI;
+
+GLEW_FUN_EXPORT PFNGLCLIENTACTIVEVERTEXSTREAMATIPROC __glewClientActiveVertexStreamATI;
+GLEW_FUN_EXPORT PFNGLNORMALSTREAM3BATIPROC __glewNormalStream3bATI;
+GLEW_FUN_EXPORT PFNGLNORMALSTREAM3BVATIPROC __glewNormalStream3bvATI;
+GLEW_FUN_EXPORT PFNGLNORMALSTREAM3DATIPROC __glewNormalStream3dATI;
+GLEW_FUN_EXPORT PFNGLNORMALSTREAM3DVATIPROC __glewNormalStream3dvATI;
+GLEW_FUN_EXPORT PFNGLNORMALSTREAM3FATIPROC __glewNormalStream3fATI;
+GLEW_FUN_EXPORT PFNGLNORMALSTREAM3FVATIPROC __glewNormalStream3fvATI;
+GLEW_FUN_EXPORT PFNGLNORMALSTREAM3IATIPROC __glewNormalStream3iATI;
+GLEW_FUN_EXPORT PFNGLNORMALSTREAM3IVATIPROC __glewNormalStream3ivATI;
+GLEW_FUN_EXPORT PFNGLNORMALSTREAM3SATIPROC __glewNormalStream3sATI;
+GLEW_FUN_EXPORT PFNGLNORMALSTREAM3SVATIPROC __glewNormalStream3svATI;
+GLEW_FUN_EXPORT PFNGLVERTEXBLENDENVFATIPROC __glewVertexBlendEnvfATI;
+GLEW_FUN_EXPORT PFNGLVERTEXBLENDENVIATIPROC __glewVertexBlendEnviATI;
+GLEW_FUN_EXPORT PFNGLVERTEXSTREAM2DATIPROC __glewVertexStream2dATI;
+GLEW_FUN_EXPORT PFNGLVERTEXSTREAM2DVATIPROC __glewVertexStream2dvATI;
+GLEW_FUN_EXPORT PFNGLVERTEXSTREAM2FATIPROC __glewVertexStream2fATI;
+GLEW_FUN_EXPORT PFNGLVERTEXSTREAM2FVATIPROC __glewVertexStream2fvATI;
+GLEW_FUN_EXPORT PFNGLVERTEXSTREAM2IATIPROC __glewVertexStream2iATI;
+GLEW_FUN_EXPORT PFNGLVERTEXSTREAM2IVATIPROC __glewVertexStream2ivATI;
+GLEW_FUN_EXPORT PFNGLVERTEXSTREAM2SATIPROC __glewVertexStream2sATI;
+GLEW_FUN_EXPORT PFNGLVERTEXSTREAM2SVATIPROC __glewVertexStream2svATI;
+GLEW_FUN_EXPORT PFNGLVERTEXSTREAM3DATIPROC __glewVertexStream3dATI;
+GLEW_FUN_EXPORT PFNGLVERTEXSTREAM3DVATIPROC __glewVertexStream3dvATI;
+GLEW_FUN_EXPORT PFNGLVERTEXSTREAM3FATIPROC __glewVertexStream3fATI;
+GLEW_FUN_EXPORT PFNGLVERTEXSTREAM3FVATIPROC __glewVertexStream3fvATI;
+GLEW_FUN_EXPORT PFNGLVERTEXSTREAM3IATIPROC __glewVertexStream3iATI;
+GLEW_FUN_EXPORT PFNGLVERTEXSTREAM3IVATIPROC __glewVertexStream3ivATI;
+GLEW_FUN_EXPORT PFNGLVERTEXSTREAM3SATIPROC __glewVertexStream3sATI;
+GLEW_FUN_EXPORT PFNGLVERTEXSTREAM3SVATIPROC __glewVertexStream3svATI;
+GLEW_FUN_EXPORT PFNGLVERTEXSTREAM4DATIPROC __glewVertexStream4dATI;
+GLEW_FUN_EXPORT PFNGLVERTEXSTREAM4DVATIPROC __glewVertexStream4dvATI;
+GLEW_FUN_EXPORT PFNGLVERTEXSTREAM4FATIPROC __glewVertexStream4fATI;
+GLEW_FUN_EXPORT PFNGLVERTEXSTREAM4FVATIPROC __glewVertexStream4fvATI;
+GLEW_FUN_EXPORT PFNGLVERTEXSTREAM4IATIPROC __glewVertexStream4iATI;
+GLEW_FUN_EXPORT PFNGLVERTEXSTREAM4IVATIPROC __glewVertexStream4ivATI;
+GLEW_FUN_EXPORT PFNGLVERTEXSTREAM4SATIPROC __glewVertexStream4sATI;
+GLEW_FUN_EXPORT PFNGLVERTEXSTREAM4SVATIPROC __glewVertexStream4svATI;
+
+GLEW_FUN_EXPORT PFNGLGETUNIFORMBUFFERSIZEEXTPROC __glewGetUniformBufferSizeEXT;
+GLEW_FUN_EXPORT PFNGLGETUNIFORMOFFSETEXTPROC __glewGetUniformOffsetEXT;
+GLEW_FUN_EXPORT PFNGLUNIFORMBUFFEREXTPROC __glewUniformBufferEXT;
+
+GLEW_FUN_EXPORT PFNGLBLENDCOLOREXTPROC __glewBlendColorEXT;
+
+GLEW_FUN_EXPORT PFNGLBLENDEQUATIONSEPARATEEXTPROC __glewBlendEquationSeparateEXT;
+
+GLEW_FUN_EXPORT PFNGLBLENDFUNCSEPARATEEXTPROC __glewBlendFuncSeparateEXT;
+
+GLEW_FUN_EXPORT PFNGLBLENDEQUATIONEXTPROC __glewBlendEquationEXT;
+
+GLEW_FUN_EXPORT PFNGLCOLORSUBTABLEEXTPROC __glewColorSubTableEXT;
+GLEW_FUN_EXPORT PFNGLCOPYCOLORSUBTABLEEXTPROC __glewCopyColorSubTableEXT;
+
+GLEW_FUN_EXPORT PFNGLLOCKARRAYSEXTPROC __glewLockArraysEXT;
+GLEW_FUN_EXPORT PFNGLUNLOCKARRAYSEXTPROC __glewUnlockArraysEXT;
+
+GLEW_FUN_EXPORT PFNGLCONVOLUTIONFILTER1DEXTPROC __glewConvolutionFilter1DEXT;
+GLEW_FUN_EXPORT PFNGLCONVOLUTIONFILTER2DEXTPROC __glewConvolutionFilter2DEXT;
+GLEW_FUN_EXPORT PFNGLCONVOLUTIONPARAMETERFEXTPROC __glewConvolutionParameterfEXT;
+GLEW_FUN_EXPORT PFNGLCONVOLUTIONPARAMETERFVEXTPROC __glewConvolutionParameterfvEXT;
+GLEW_FUN_EXPORT PFNGLCONVOLUTIONPARAMETERIEXTPROC __glewConvolutionParameteriEXT;
+GLEW_FUN_EXPORT PFNGLCONVOLUTIONPARAMETERIVEXTPROC __glewConvolutionParameterivEXT;
+GLEW_FUN_EXPORT PFNGLCOPYCONVOLUTIONFILTER1DEXTPROC __glewCopyConvolutionFilter1DEXT;
+GLEW_FUN_EXPORT PFNGLCOPYCONVOLUTIONFILTER2DEXTPROC __glewCopyConvolutionFilter2DEXT;
+GLEW_FUN_EXPORT PFNGLGETCONVOLUTIONFILTEREXTPROC __glewGetConvolutionFilterEXT;
+GLEW_FUN_EXPORT PFNGLGETCONVOLUTIONPARAMETERFVEXTPROC __glewGetConvolutionParameterfvEXT;
+GLEW_FUN_EXPORT PFNGLGETCONVOLUTIONPARAMETERIVEXTPROC __glewGetConvolutionParameterivEXT;
+GLEW_FUN_EXPORT PFNGLGETSEPARABLEFILTEREXTPROC __glewGetSeparableFilterEXT;
+GLEW_FUN_EXPORT PFNGLSEPARABLEFILTER2DEXTPROC __glewSeparableFilter2DEXT;
+
+GLEW_FUN_EXPORT PFNGLBINORMALPOINTEREXTPROC __glewBinormalPointerEXT;
+GLEW_FUN_EXPORT PFNGLTANGENTPOINTEREXTPROC __glewTangentPointerEXT;
+
+GLEW_FUN_EXPORT PFNGLCOPYTEXIMAGE1DEXTPROC __glewCopyTexImage1DEXT;
+GLEW_FUN_EXPORT PFNGLCOPYTEXIMAGE2DEXTPROC __glewCopyTexImage2DEXT;
+GLEW_FUN_EXPORT PFNGLCOPYTEXSUBIMAGE1DEXTPROC __glewCopyTexSubImage1DEXT;
+GLEW_FUN_EXPORT PFNGLCOPYTEXSUBIMAGE2DEXTPROC __glewCopyTexSubImage2DEXT;
+GLEW_FUN_EXPORT PFNGLCOPYTEXSUBIMAGE3DEXTPROC __glewCopyTexSubImage3DEXT;
+
+GLEW_FUN_EXPORT PFNGLCULLPARAMETERDVEXTPROC __glewCullParameterdvEXT;
+GLEW_FUN_EXPORT PFNGLCULLPARAMETERFVEXTPROC __glewCullParameterfvEXT;
+
+GLEW_FUN_EXPORT PFNGLDEPTHBOUNDSEXTPROC __glewDepthBoundsEXT;
+
+GLEW_FUN_EXPORT PFNGLBINDMULTITEXTUREEXTPROC __glewBindMultiTextureEXT;
+GLEW_FUN_EXPORT PFNGLCHECKNAMEDFRAMEBUFFERSTATUSEXTPROC __glewCheckNamedFramebufferStatusEXT;
+GLEW_FUN_EXPORT PFNGLCLIENTATTRIBDEFAULTEXTPROC __glewClientAttribDefaultEXT;
+GLEW_FUN_EXPORT PFNGLCOMPRESSEDMULTITEXIMAGE1DEXTPROC __glewCompressedMultiTexImage1DEXT;
+GLEW_FUN_EXPORT PFNGLCOMPRESSEDMULTITEXIMAGE2DEXTPROC __glewCompressedMultiTexImage2DEXT;
+GLEW_FUN_EXPORT PFNGLCOMPRESSEDMULTITEXIMAGE3DEXTPROC __glewCompressedMultiTexImage3DEXT;
+GLEW_FUN_EXPORT PFNGLCOMPRESSEDMULTITEXSUBIMAGE1DEXTPROC __glewCompressedMultiTexSubImage1DEXT;
+GLEW_FUN_EXPORT PFNGLCOMPRESSEDMULTITEXSUBIMAGE2DEXTPROC __glewCompressedMultiTexSubImage2DEXT;
+GLEW_FUN_EXPORT PFNGLCOMPRESSEDMULTITEXSUBIMAGE3DEXTPROC __glewCompressedMultiTexSubImage3DEXT;
+GLEW_FUN_EXPORT PFNGLCOMPRESSEDTEXTUREIMAGE1DEXTPROC __glewCompressedTextureImage1DEXT;
+GLEW_FUN_EXPORT PFNGLCOMPRESSEDTEXTUREIMAGE2DEXTPROC __glewCompressedTextureImage2DEXT;
+GLEW_FUN_EXPORT PFNGLCOMPRESSEDTEXTUREIMAGE3DEXTPROC __glewCompressedTextureImage3DEXT;
+GLEW_FUN_EXPORT PFNGLCOMPRESSEDTEXTURESUBIMAGE1DEXTPROC __glewCompressedTextureSubImage1DEXT;
+GLEW_FUN_EXPORT PFNGLCOMPRESSEDTEXTURESUBIMAGE2DEXTPROC __glewCompressedTextureSubImage2DEXT;
+GLEW_FUN_EXPORT PFNGLCOMPRESSEDTEXTURESUBIMAGE3DEXTPROC __glewCompressedTextureSubImage3DEXT;
+GLEW_FUN_EXPORT PFNGLCOPYMULTITEXIMAGE1DEXTPROC __glewCopyMultiTexImage1DEXT;
+GLEW_FUN_EXPORT PFNGLCOPYMULTITEXIMAGE2DEXTPROC __glewCopyMultiTexImage2DEXT;
+GLEW_FUN_EXPORT PFNGLCOPYMULTITEXSUBIMAGE1DEXTPROC __glewCopyMultiTexSubImage1DEXT;
+GLEW_FUN_EXPORT PFNGLCOPYMULTITEXSUBIMAGE2DEXTPROC __glewCopyMultiTexSubImage2DEXT;
+GLEW_FUN_EXPORT PFNGLCOPYMULTITEXSUBIMAGE3DEXTPROC __glewCopyMultiTexSubImage3DEXT;
+GLEW_FUN_EXPORT PFNGLCOPYTEXTUREIMAGE1DEXTPROC __glewCopyTextureImage1DEXT;
+GLEW_FUN_EXPORT PFNGLCOPYTEXTUREIMAGE2DEXTPROC __glewCopyTextureImage2DEXT;
+GLEW_FUN_EXPORT PFNGLCOPYTEXTURESUBIMAGE1DEXTPROC __glewCopyTextureSubImage1DEXT;
+GLEW_FUN_EXPORT PFNGLCOPYTEXTURESUBIMAGE2DEXTPROC __glewCopyTextureSubImage2DEXT;
+GLEW_FUN_EXPORT PFNGLCOPYTEXTURESUBIMAGE3DEXTPROC __glewCopyTextureSubImage3DEXT;
+GLEW_FUN_EXPORT PFNGLDISABLECLIENTSTATEINDEXEDEXTPROC __glewDisableClientStateIndexedEXT;
+GLEW_FUN_EXPORT PFNGLDISABLECLIENTSTATEIEXTPROC __glewDisableClientStateiEXT;
+GLEW_FUN_EXPORT PFNGLDISABLEVERTEXARRAYATTRIBEXTPROC __glewDisableVertexArrayAttribEXT;
+GLEW_FUN_EXPORT PFNGLDISABLEVERTEXARRAYEXTPROC __glewDisableVertexArrayEXT;
+GLEW_FUN_EXPORT PFNGLENABLECLIENTSTATEINDEXEDEXTPROC __glewEnableClientStateIndexedEXT;
+GLEW_FUN_EXPORT PFNGLENABLECLIENTSTATEIEXTPROC __glewEnableClientStateiEXT;
+GLEW_FUN_EXPORT PFNGLENABLEVERTEXARRAYATTRIBEXTPROC __glewEnableVertexArrayAttribEXT;
+GLEW_FUN_EXPORT PFNGLENABLEVERTEXARRAYEXTPROC __glewEnableVertexArrayEXT;
+GLEW_FUN_EXPORT PFNGLFLUSHMAPPEDNAMEDBUFFERRANGEEXTPROC __glewFlushMappedNamedBufferRangeEXT;
+GLEW_FUN_EXPORT PFNGLFRAMEBUFFERDRAWBUFFEREXTPROC __glewFramebufferDrawBufferEXT;
+GLEW_FUN_EXPORT PFNGLFRAMEBUFFERDRAWBUFFERSEXTPROC __glewFramebufferDrawBuffersEXT;
+GLEW_FUN_EXPORT PFNGLFRAMEBUFFERREADBUFFEREXTPROC __glewFramebufferReadBufferEXT;
+GLEW_FUN_EXPORT PFNGLGENERATEMULTITEXMIPMAPEXTPROC __glewGenerateMultiTexMipmapEXT;
+GLEW_FUN_EXPORT PFNGLGENERATETEXTUREMIPMAPEXTPROC __glewGenerateTextureMipmapEXT;
+GLEW_FUN_EXPORT PFNGLGETCOMPRESSEDMULTITEXIMAGEEXTPROC __glewGetCompressedMultiTexImageEXT;
+GLEW_FUN_EXPORT PFNGLGETCOMPRESSEDTEXTUREIMAGEEXTPROC __glewGetCompressedTextureImageEXT;
+GLEW_FUN_EXPORT PFNGLGETDOUBLEINDEXEDVEXTPROC __glewGetDoubleIndexedvEXT;
+GLEW_FUN_EXPORT PFNGLGETDOUBLEI_VEXTPROC __glewGetDoublei_vEXT;
+GLEW_FUN_EXPORT PFNGLGETFLOATINDEXEDVEXTPROC __glewGetFloatIndexedvEXT;
+GLEW_FUN_EXPORT PFNGLGETFLOATI_VEXTPROC __glewGetFloati_vEXT;
+GLEW_FUN_EXPORT PFNGLGETFRAMEBUFFERPARAMETERIVEXTPROC __glewGetFramebufferParameterivEXT;
+GLEW_FUN_EXPORT PFNGLGETMULTITEXENVFVEXTPROC __glewGetMultiTexEnvfvEXT;
+GLEW_FUN_EXPORT PFNGLGETMULTITEXENVIVEXTPROC __glewGetMultiTexEnvivEXT;
+GLEW_FUN_EXPORT PFNGLGETMULTITEXGENDVEXTPROC __glewGetMultiTexGendvEXT;
+GLEW_FUN_EXPORT PFNGLGETMULTITEXGENFVEXTPROC __glewGetMultiTexGenfvEXT;
+GLEW_FUN_EXPORT PFNGLGETMULTITEXGENIVEXTPROC __glewGetMultiTexGenivEXT;
+GLEW_FUN_EXPORT PFNGLGETMULTITEXIMAGEEXTPROC __glewGetMultiTexImageEXT;
+GLEW_FUN_EXPORT PFNGLGETMULTITEXLEVELPARAMETERFVEXTPROC __glewGetMultiTexLevelParameterfvEXT;
+GLEW_FUN_EXPORT PFNGLGETMULTITEXLEVELPARAMETERIVEXTPROC __glewGetMultiTexLevelParameterivEXT;
+GLEW_FUN_EXPORT PFNGLGETMULTITEXPARAMETERIIVEXTPROC __glewGetMultiTexParameterIivEXT;
+GLEW_FUN_EXPORT PFNGLGETMULTITEXPARAMETERIUIVEXTPROC __glewGetMultiTexParameterIuivEXT;
+GLEW_FUN_EXPORT PFNGLGETMULTITEXPARAMETERFVEXTPROC __glewGetMultiTexParameterfvEXT;
+GLEW_FUN_EXPORT PFNGLGETMULTITEXPARAMETERIVEXTPROC __glewGetMultiTexParameterivEXT;
+GLEW_FUN_EXPORT PFNGLGETNAMEDBUFFERPARAMETERIVEXTPROC __glewGetNamedBufferParameterivEXT;
+GLEW_FUN_EXPORT PFNGLGETNAMEDBUFFERPOINTERVEXTPROC __glewGetNamedBufferPointervEXT;
+GLEW_FUN_EXPORT PFNGLGETNAMEDBUFFERSUBDATAEXTPROC __glewGetNamedBufferSubDataEXT;
+GLEW_FUN_EXPORT PFNGLGETNAMEDFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC __glewGetNamedFramebufferAttachmentParameterivEXT;
+GLEW_FUN_EXPORT PFNGLGETNAMEDPROGRAMLOCALPARAMETERIIVEXTPROC __glewGetNamedProgramLocalParameterIivEXT;
+GLEW_FUN_EXPORT PFNGLGETNAMEDPROGRAMLOCALPARAMETERIUIVEXTPROC __glewGetNamedProgramLocalParameterIuivEXT;
+GLEW_FUN_EXPORT PFNGLGETNAMEDPROGRAMLOCALPARAMETERDVEXTPROC __glewGetNamedProgramLocalParameterdvEXT;
+GLEW_FUN_EXPORT PFNGLGETNAMEDPROGRAMLOCALPARAMETERFVEXTPROC __glewGetNamedProgramLocalParameterfvEXT;
+GLEW_FUN_EXPORT PFNGLGETNAMEDPROGRAMSTRINGEXTPROC __glewGetNamedProgramStringEXT;
+GLEW_FUN_EXPORT PFNGLGETNAMEDPROGRAMIVEXTPROC __glewGetNamedProgramivEXT;
+GLEW_FUN_EXPORT PFNGLGETNAMEDRENDERBUFFERPARAMETERIVEXTPROC __glewGetNamedRenderbufferParameterivEXT;
+GLEW_FUN_EXPORT PFNGLGETPOINTERINDEXEDVEXTPROC __glewGetPointerIndexedvEXT;
+GLEW_FUN_EXPORT PFNGLGETPOINTERI_VEXTPROC __glewGetPointeri_vEXT;
+GLEW_FUN_EXPORT PFNGLGETTEXTUREIMAGEEXTPROC __glewGetTextureImageEXT;
+GLEW_FUN_EXPORT PFNGLGETTEXTURELEVELPARAMETERFVEXTPROC __glewGetTextureLevelParameterfvEXT;
+GLEW_FUN_EXPORT PFNGLGETTEXTURELEVELPARAMETERIVEXTPROC __glewGetTextureLevelParameterivEXT;
+GLEW_FUN_EXPORT PFNGLGETTEXTUREPARAMETERIIVEXTPROC __glewGetTextureParameterIivEXT;
+GLEW_FUN_EXPORT PFNGLGETTEXTUREPARAMETERIUIVEXTPROC __glewGetTextureParameterIuivEXT;
+GLEW_FUN_EXPORT PFNGLGETTEXTUREPARAMETERFVEXTPROC __glewGetTextureParameterfvEXT;
+GLEW_FUN_EXPORT PFNGLGETTEXTUREPARAMETERIVEXTPROC __glewGetTextureParameterivEXT;
+GLEW_FUN_EXPORT PFNGLGETVERTEXARRAYINTEGERI_VEXTPROC __glewGetVertexArrayIntegeri_vEXT;
+GLEW_FUN_EXPORT PFNGLGETVERTEXARRAYINTEGERVEXTPROC __glewGetVertexArrayIntegervEXT;
+GLEW_FUN_EXPORT PFNGLGETVERTEXARRAYPOINTERI_VEXTPROC __glewGetVertexArrayPointeri_vEXT;
+GLEW_FUN_EXPORT PFNGLGETVERTEXARRAYPOINTERVEXTPROC __glewGetVertexArrayPointervEXT;
+GLEW_FUN_EXPORT PFNGLMAPNAMEDBUFFEREXTPROC __glewMapNamedBufferEXT;
+GLEW_FUN_EXPORT PFNGLMAPNAMEDBUFFERRANGEEXTPROC __glewMapNamedBufferRangeEXT;
+GLEW_FUN_EXPORT PFNGLMATRIXFRUSTUMEXTPROC __glewMatrixFrustumEXT;
+GLEW_FUN_EXPORT PFNGLMATRIXLOADIDENTITYEXTPROC __glewMatrixLoadIdentityEXT;
+GLEW_FUN_EXPORT PFNGLMATRIXLOADTRANSPOSEDEXTPROC __glewMatrixLoadTransposedEXT;
+GLEW_FUN_EXPORT PFNGLMATRIXLOADTRANSPOSEFEXTPROC __glewMatrixLoadTransposefEXT;
+GLEW_FUN_EXPORT PFNGLMATRIXLOADDEXTPROC __glewMatrixLoaddEXT;
+GLEW_FUN_EXPORT PFNGLMATRIXLOADFEXTPROC __glewMatrixLoadfEXT;
+GLEW_FUN_EXPORT PFNGLMATRIXMULTTRANSPOSEDEXTPROC __glewMatrixMultTransposedEXT;
+GLEW_FUN_EXPORT PFNGLMATRIXMULTTRANSPOSEFEXTPROC __glewMatrixMultTransposefEXT;
+GLEW_FUN_EXPORT PFNGLMATRIXMULTDEXTPROC __glewMatrixMultdEXT;
+GLEW_FUN_EXPORT PFNGLMATRIXMULTFEXTPROC __glewMatrixMultfEXT;
+GLEW_FUN_EXPORT PFNGLMATRIXORTHOEXTPROC __glewMatrixOrthoEXT;
+GLEW_FUN_EXPORT PFNGLMATRIXPOPEXTPROC __glewMatrixPopEXT;
+GLEW_FUN_EXPORT PFNGLMATRIXPUSHEXTPROC __glewMatrixPushEXT;
+GLEW_FUN_EXPORT PFNGLMATRIXROTATEDEXTPROC __glewMatrixRotatedEXT;
+GLEW_FUN_EXPORT PFNGLMATRIXROTATEFEXTPROC __glewMatrixRotatefEXT;
+GLEW_FUN_EXPORT PFNGLMATRIXSCALEDEXTPROC __glewMatrixScaledEXT;
+GLEW_FUN_EXPORT PFNGLMATRIXSCALEFEXTPROC __glewMatrixScalefEXT;
+GLEW_FUN_EXPORT PFNGLMATRIXTRANSLATEDEXTPROC __glewMatrixTranslatedEXT;
+GLEW_FUN_EXPORT PFNGLMATRIXTRANSLATEFEXTPROC __glewMatrixTranslatefEXT;
+GLEW_FUN_EXPORT PFNGLMULTITEXBUFFEREXTPROC __glewMultiTexBufferEXT;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORDPOINTEREXTPROC __glewMultiTexCoordPointerEXT;
+GLEW_FUN_EXPORT PFNGLMULTITEXENVFEXTPROC __glewMultiTexEnvfEXT;
+GLEW_FUN_EXPORT PFNGLMULTITEXENVFVEXTPROC __glewMultiTexEnvfvEXT;
+GLEW_FUN_EXPORT PFNGLMULTITEXENVIEXTPROC __glewMultiTexEnviEXT;
+GLEW_FUN_EXPORT PFNGLMULTITEXENVIVEXTPROC __glewMultiTexEnvivEXT;
+GLEW_FUN_EXPORT PFNGLMULTITEXGENDEXTPROC __glewMultiTexGendEXT;
+GLEW_FUN_EXPORT PFNGLMULTITEXGENDVEXTPROC __glewMultiTexGendvEXT;
+GLEW_FUN_EXPORT PFNGLMULTITEXGENFEXTPROC __glewMultiTexGenfEXT;
+GLEW_FUN_EXPORT PFNGLMULTITEXGENFVEXTPROC __glewMultiTexGenfvEXT;
+GLEW_FUN_EXPORT PFNGLMULTITEXGENIEXTPROC __glewMultiTexGeniEXT;
+GLEW_FUN_EXPORT PFNGLMULTITEXGENIVEXTPROC __glewMultiTexGenivEXT;
+GLEW_FUN_EXPORT PFNGLMULTITEXIMAGE1DEXTPROC __glewMultiTexImage1DEXT;
+GLEW_FUN_EXPORT PFNGLMULTITEXIMAGE2DEXTPROC __glewMultiTexImage2DEXT;
+GLEW_FUN_EXPORT PFNGLMULTITEXIMAGE3DEXTPROC __glewMultiTexImage3DEXT;
+GLEW_FUN_EXPORT PFNGLMULTITEXPARAMETERIIVEXTPROC __glewMultiTexParameterIivEXT;
+GLEW_FUN_EXPORT PFNGLMULTITEXPARAMETERIUIVEXTPROC __glewMultiTexParameterIuivEXT;
+GLEW_FUN_EXPORT PFNGLMULTITEXPARAMETERFEXTPROC __glewMultiTexParameterfEXT;
+GLEW_FUN_EXPORT PFNGLMULTITEXPARAMETERFVEXTPROC __glewMultiTexParameterfvEXT;
+GLEW_FUN_EXPORT PFNGLMULTITEXPARAMETERIEXTPROC __glewMultiTexParameteriEXT;
+GLEW_FUN_EXPORT PFNGLMULTITEXPARAMETERIVEXTPROC __glewMultiTexParameterivEXT;
+GLEW_FUN_EXPORT PFNGLMULTITEXRENDERBUFFEREXTPROC __glewMultiTexRenderbufferEXT;
+GLEW_FUN_EXPORT PFNGLMULTITEXSUBIMAGE1DEXTPROC __glewMultiTexSubImage1DEXT;
+GLEW_FUN_EXPORT PFNGLMULTITEXSUBIMAGE2DEXTPROC __glewMultiTexSubImage2DEXT;
+GLEW_FUN_EXPORT PFNGLMULTITEXSUBIMAGE3DEXTPROC __glewMultiTexSubImage3DEXT;
+GLEW_FUN_EXPORT PFNGLNAMEDBUFFERDATAEXTPROC __glewNamedBufferDataEXT;
+GLEW_FUN_EXPORT PFNGLNAMEDBUFFERSUBDATAEXTPROC __glewNamedBufferSubDataEXT;
+GLEW_FUN_EXPORT PFNGLNAMEDCOPYBUFFERSUBDATAEXTPROC __glewNamedCopyBufferSubDataEXT;
+GLEW_FUN_EXPORT PFNGLNAMEDFRAMEBUFFERRENDERBUFFEREXTPROC __glewNamedFramebufferRenderbufferEXT;
+GLEW_FUN_EXPORT PFNGLNAMEDFRAMEBUFFERTEXTURE1DEXTPROC __glewNamedFramebufferTexture1DEXT;
+GLEW_FUN_EXPORT PFNGLNAMEDFRAMEBUFFERTEXTURE2DEXTPROC __glewNamedFramebufferTexture2DEXT;
+GLEW_FUN_EXPORT PFNGLNAMEDFRAMEBUFFERTEXTURE3DEXTPROC __glewNamedFramebufferTexture3DEXT;
+GLEW_FUN_EXPORT PFNGLNAMEDFRAMEBUFFERTEXTUREEXTPROC __glewNamedFramebufferTextureEXT;
+GLEW_FUN_EXPORT PFNGLNAMEDFRAMEBUFFERTEXTUREFACEEXTPROC __glewNamedFramebufferTextureFaceEXT;
+GLEW_FUN_EXPORT PFNGLNAMEDFRAMEBUFFERTEXTURELAYEREXTPROC __glewNamedFramebufferTextureLayerEXT;
+GLEW_FUN_EXPORT PFNGLNAMEDPROGRAMLOCALPARAMETER4DEXTPROC __glewNamedProgramLocalParameter4dEXT;
+GLEW_FUN_EXPORT PFNGLNAMEDPROGRAMLOCALPARAMETER4DVEXTPROC __glewNamedProgramLocalParameter4dvEXT;
+GLEW_FUN_EXPORT PFNGLNAMEDPROGRAMLOCALPARAMETER4FEXTPROC __glewNamedProgramLocalParameter4fEXT;
+GLEW_FUN_EXPORT PFNGLNAMEDPROGRAMLOCALPARAMETER4FVEXTPROC __glewNamedProgramLocalParameter4fvEXT;
+GLEW_FUN_EXPORT PFNGLNAMEDPROGRAMLOCALPARAMETERI4IEXTPROC __glewNamedProgramLocalParameterI4iEXT;
+GLEW_FUN_EXPORT PFNGLNAMEDPROGRAMLOCALPARAMETERI4IVEXTPROC __glewNamedProgramLocalParameterI4ivEXT;
+GLEW_FUN_EXPORT PFNGLNAMEDPROGRAMLOCALPARAMETERI4UIEXTPROC __glewNamedProgramLocalParameterI4uiEXT;
+GLEW_FUN_EXPORT PFNGLNAMEDPROGRAMLOCALPARAMETERI4UIVEXTPROC __glewNamedProgramLocalParameterI4uivEXT;
+GLEW_FUN_EXPORT PFNGLNAMEDPROGRAMLOCALPARAMETERS4FVEXTPROC __glewNamedProgramLocalParameters4fvEXT;
+GLEW_FUN_EXPORT PFNGLNAMEDPROGRAMLOCALPARAMETERSI4IVEXTPROC __glewNamedProgramLocalParametersI4ivEXT;
+GLEW_FUN_EXPORT PFNGLNAMEDPROGRAMLOCALPARAMETERSI4UIVEXTPROC __glewNamedProgramLocalParametersI4uivEXT;
+GLEW_FUN_EXPORT PFNGLNAMEDPROGRAMSTRINGEXTPROC __glewNamedProgramStringEXT;
+GLEW_FUN_EXPORT PFNGLNAMEDRENDERBUFFERSTORAGEEXTPROC __glewNamedRenderbufferStorageEXT;
+GLEW_FUN_EXPORT PFNGLNAMEDRENDERBUFFERSTORAGEMULTISAMPLECOVERAGEEXTPROC __glewNamedRenderbufferStorageMultisampleCoverageEXT;
+GLEW_FUN_EXPORT PFNGLNAMEDRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC __glewNamedRenderbufferStorageMultisampleEXT;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM1FEXTPROC __glewProgramUniform1fEXT;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM1FVEXTPROC __glewProgramUniform1fvEXT;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM1IEXTPROC __glewProgramUniform1iEXT;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM1IVEXTPROC __glewProgramUniform1ivEXT;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM1UIEXTPROC __glewProgramUniform1uiEXT;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM1UIVEXTPROC __glewProgramUniform1uivEXT;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM2FEXTPROC __glewProgramUniform2fEXT;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM2FVEXTPROC __glewProgramUniform2fvEXT;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM2IEXTPROC __glewProgramUniform2iEXT;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM2IVEXTPROC __glewProgramUniform2ivEXT;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM2UIEXTPROC __glewProgramUniform2uiEXT;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM2UIVEXTPROC __glewProgramUniform2uivEXT;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM3FEXTPROC __glewProgramUniform3fEXT;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM3FVEXTPROC __glewProgramUniform3fvEXT;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM3IEXTPROC __glewProgramUniform3iEXT;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM3IVEXTPROC __glewProgramUniform3ivEXT;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM3UIEXTPROC __glewProgramUniform3uiEXT;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM3UIVEXTPROC __glewProgramUniform3uivEXT;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM4FEXTPROC __glewProgramUniform4fEXT;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM4FVEXTPROC __glewProgramUniform4fvEXT;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM4IEXTPROC __glewProgramUniform4iEXT;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM4IVEXTPROC __glewProgramUniform4ivEXT;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM4UIEXTPROC __glewProgramUniform4uiEXT;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM4UIVEXTPROC __glewProgramUniform4uivEXT;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX2FVEXTPROC __glewProgramUniformMatrix2fvEXT;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX2X3FVEXTPROC __glewProgramUniformMatrix2x3fvEXT;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX2X4FVEXTPROC __glewProgramUniformMatrix2x4fvEXT;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX3FVEXTPROC __glewProgramUniformMatrix3fvEXT;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX3X2FVEXTPROC __glewProgramUniformMatrix3x2fvEXT;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX3X4FVEXTPROC __glewProgramUniformMatrix3x4fvEXT;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX4FVEXTPROC __glewProgramUniformMatrix4fvEXT;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX4X2FVEXTPROC __glewProgramUniformMatrix4x2fvEXT;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX4X3FVEXTPROC __glewProgramUniformMatrix4x3fvEXT;
+GLEW_FUN_EXPORT PFNGLPUSHCLIENTATTRIBDEFAULTEXTPROC __glewPushClientAttribDefaultEXT;
+GLEW_FUN_EXPORT PFNGLTEXTUREBUFFEREXTPROC __glewTextureBufferEXT;
+GLEW_FUN_EXPORT PFNGLTEXTUREIMAGE1DEXTPROC __glewTextureImage1DEXT;
+GLEW_FUN_EXPORT PFNGLTEXTUREIMAGE2DEXTPROC __glewTextureImage2DEXT;
+GLEW_FUN_EXPORT PFNGLTEXTUREIMAGE3DEXTPROC __glewTextureImage3DEXT;
+GLEW_FUN_EXPORT PFNGLTEXTUREPARAMETERIIVEXTPROC __glewTextureParameterIivEXT;
+GLEW_FUN_EXPORT PFNGLTEXTUREPARAMETERIUIVEXTPROC __glewTextureParameterIuivEXT;
+GLEW_FUN_EXPORT PFNGLTEXTUREPARAMETERFEXTPROC __glewTextureParameterfEXT;
+GLEW_FUN_EXPORT PFNGLTEXTUREPARAMETERFVEXTPROC __glewTextureParameterfvEXT;
+GLEW_FUN_EXPORT PFNGLTEXTUREPARAMETERIEXTPROC __glewTextureParameteriEXT;
+GLEW_FUN_EXPORT PFNGLTEXTUREPARAMETERIVEXTPROC __glewTextureParameterivEXT;
+GLEW_FUN_EXPORT PFNGLTEXTURERENDERBUFFEREXTPROC __glewTextureRenderbufferEXT;
+GLEW_FUN_EXPORT PFNGLTEXTURESUBIMAGE1DEXTPROC __glewTextureSubImage1DEXT;
+GLEW_FUN_EXPORT PFNGLTEXTURESUBIMAGE2DEXTPROC __glewTextureSubImage2DEXT;
+GLEW_FUN_EXPORT PFNGLTEXTURESUBIMAGE3DEXTPROC __glewTextureSubImage3DEXT;
+GLEW_FUN_EXPORT PFNGLUNMAPNAMEDBUFFEREXTPROC __glewUnmapNamedBufferEXT;
+GLEW_FUN_EXPORT PFNGLVERTEXARRAYCOLOROFFSETEXTPROC __glewVertexArrayColorOffsetEXT;
+GLEW_FUN_EXPORT PFNGLVERTEXARRAYEDGEFLAGOFFSETEXTPROC __glewVertexArrayEdgeFlagOffsetEXT;
+GLEW_FUN_EXPORT PFNGLVERTEXARRAYFOGCOORDOFFSETEXTPROC __glewVertexArrayFogCoordOffsetEXT;
+GLEW_FUN_EXPORT PFNGLVERTEXARRAYINDEXOFFSETEXTPROC __glewVertexArrayIndexOffsetEXT;
+GLEW_FUN_EXPORT PFNGLVERTEXARRAYMULTITEXCOORDOFFSETEXTPROC __glewVertexArrayMultiTexCoordOffsetEXT;
+GLEW_FUN_EXPORT PFNGLVERTEXARRAYNORMALOFFSETEXTPROC __glewVertexArrayNormalOffsetEXT;
+GLEW_FUN_EXPORT PFNGLVERTEXARRAYSECONDARYCOLOROFFSETEXTPROC __glewVertexArraySecondaryColorOffsetEXT;
+GLEW_FUN_EXPORT PFNGLVERTEXARRAYTEXCOORDOFFSETEXTPROC __glewVertexArrayTexCoordOffsetEXT;
+GLEW_FUN_EXPORT PFNGLVERTEXARRAYVERTEXATTRIBIOFFSETEXTPROC __glewVertexArrayVertexAttribIOffsetEXT;
+GLEW_FUN_EXPORT PFNGLVERTEXARRAYVERTEXATTRIBOFFSETEXTPROC __glewVertexArrayVertexAttribOffsetEXT;
+GLEW_FUN_EXPORT PFNGLVERTEXARRAYVERTEXOFFSETEXTPROC __glewVertexArrayVertexOffsetEXT;
+
+GLEW_FUN_EXPORT PFNGLCOLORMASKINDEXEDEXTPROC __glewColorMaskIndexedEXT;
+GLEW_FUN_EXPORT PFNGLDISABLEINDEXEDEXTPROC __glewDisableIndexedEXT;
+GLEW_FUN_EXPORT PFNGLENABLEINDEXEDEXTPROC __glewEnableIndexedEXT;
+GLEW_FUN_EXPORT PFNGLGETBOOLEANINDEXEDVEXTPROC __glewGetBooleanIndexedvEXT;
+GLEW_FUN_EXPORT PFNGLGETINTEGERINDEXEDVEXTPROC __glewGetIntegerIndexedvEXT;
+GLEW_FUN_EXPORT PFNGLISENABLEDINDEXEDEXTPROC __glewIsEnabledIndexedEXT;
+
+GLEW_FUN_EXPORT PFNGLDRAWARRAYSINSTANCEDEXTPROC __glewDrawArraysInstancedEXT;
+GLEW_FUN_EXPORT PFNGLDRAWELEMENTSINSTANCEDEXTPROC __glewDrawElementsInstancedEXT;
+
+GLEW_FUN_EXPORT PFNGLDRAWRANGEELEMENTSEXTPROC __glewDrawRangeElementsEXT;
+
+GLEW_FUN_EXPORT PFNGLFOGCOORDPOINTEREXTPROC __glewFogCoordPointerEXT;
+GLEW_FUN_EXPORT PFNGLFOGCOORDDEXTPROC __glewFogCoorddEXT;
+GLEW_FUN_EXPORT PFNGLFOGCOORDDVEXTPROC __glewFogCoorddvEXT;
+GLEW_FUN_EXPORT PFNGLFOGCOORDFEXTPROC __glewFogCoordfEXT;
+GLEW_FUN_EXPORT PFNGLFOGCOORDFVEXTPROC __glewFogCoordfvEXT;
+
+GLEW_FUN_EXPORT PFNGLFRAGMENTCOLORMATERIALEXTPROC __glewFragmentColorMaterialEXT;
+GLEW_FUN_EXPORT PFNGLFRAGMENTLIGHTMODELFEXTPROC __glewFragmentLightModelfEXT;
+GLEW_FUN_EXPORT PFNGLFRAGMENTLIGHTMODELFVEXTPROC __glewFragmentLightModelfvEXT;
+GLEW_FUN_EXPORT PFNGLFRAGMENTLIGHTMODELIEXTPROC __glewFragmentLightModeliEXT;
+GLEW_FUN_EXPORT PFNGLFRAGMENTLIGHTMODELIVEXTPROC __glewFragmentLightModelivEXT;
+GLEW_FUN_EXPORT PFNGLFRAGMENTLIGHTFEXTPROC __glewFragmentLightfEXT;
+GLEW_FUN_EXPORT PFNGLFRAGMENTLIGHTFVEXTPROC __glewFragmentLightfvEXT;
+GLEW_FUN_EXPORT PFNGLFRAGMENTLIGHTIEXTPROC __glewFragmentLightiEXT;
+GLEW_FUN_EXPORT PFNGLFRAGMENTLIGHTIVEXTPROC __glewFragmentLightivEXT;
+GLEW_FUN_EXPORT PFNGLFRAGMENTMATERIALFEXTPROC __glewFragmentMaterialfEXT;
+GLEW_FUN_EXPORT PFNGLFRAGMENTMATERIALFVEXTPROC __glewFragmentMaterialfvEXT;
+GLEW_FUN_EXPORT PFNGLFRAGMENTMATERIALIEXTPROC __glewFragmentMaterialiEXT;
+GLEW_FUN_EXPORT PFNGLFRAGMENTMATERIALIVEXTPROC __glewFragmentMaterialivEXT;
+GLEW_FUN_EXPORT PFNGLGETFRAGMENTLIGHTFVEXTPROC __glewGetFragmentLightfvEXT;
+GLEW_FUN_EXPORT PFNGLGETFRAGMENTLIGHTIVEXTPROC __glewGetFragmentLightivEXT;
+GLEW_FUN_EXPORT PFNGLGETFRAGMENTMATERIALFVEXTPROC __glewGetFragmentMaterialfvEXT;
+GLEW_FUN_EXPORT PFNGLGETFRAGMENTMATERIALIVEXTPROC __glewGetFragmentMaterialivEXT;
+GLEW_FUN_EXPORT PFNGLLIGHTENVIEXTPROC __glewLightEnviEXT;
+
+GLEW_FUN_EXPORT PFNGLBLITFRAMEBUFFEREXTPROC __glewBlitFramebufferEXT;
+
+GLEW_FUN_EXPORT PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC __glewRenderbufferStorageMultisampleEXT;
+
+GLEW_FUN_EXPORT PFNGLBINDFRAMEBUFFEREXTPROC __glewBindFramebufferEXT;
+GLEW_FUN_EXPORT PFNGLBINDRENDERBUFFEREXTPROC __glewBindRenderbufferEXT;
+GLEW_FUN_EXPORT PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC __glewCheckFramebufferStatusEXT;
+GLEW_FUN_EXPORT PFNGLDELETEFRAMEBUFFERSEXTPROC __glewDeleteFramebuffersEXT;
+GLEW_FUN_EXPORT PFNGLDELETERENDERBUFFERSEXTPROC __glewDeleteRenderbuffersEXT;
+GLEW_FUN_EXPORT PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC __glewFramebufferRenderbufferEXT;
+GLEW_FUN_EXPORT PFNGLFRAMEBUFFERTEXTURE1DEXTPROC __glewFramebufferTexture1DEXT;
+GLEW_FUN_EXPORT PFNGLFRAMEBUFFERTEXTURE2DEXTPROC __glewFramebufferTexture2DEXT;
+GLEW_FUN_EXPORT PFNGLFRAMEBUFFERTEXTURE3DEXTPROC __glewFramebufferTexture3DEXT;
+GLEW_FUN_EXPORT PFNGLGENFRAMEBUFFERSEXTPROC __glewGenFramebuffersEXT;
+GLEW_FUN_EXPORT PFNGLGENRENDERBUFFERSEXTPROC __glewGenRenderbuffersEXT;
+GLEW_FUN_EXPORT PFNGLGENERATEMIPMAPEXTPROC __glewGenerateMipmapEXT;
+GLEW_FUN_EXPORT PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC __glewGetFramebufferAttachmentParameterivEXT;
+GLEW_FUN_EXPORT PFNGLGETRENDERBUFFERPARAMETERIVEXTPROC __glewGetRenderbufferParameterivEXT;
+GLEW_FUN_EXPORT PFNGLISFRAMEBUFFEREXTPROC __glewIsFramebufferEXT;
+GLEW_FUN_EXPORT PFNGLISRENDERBUFFEREXTPROC __glewIsRenderbufferEXT;
+GLEW_FUN_EXPORT PFNGLRENDERBUFFERSTORAGEEXTPROC __glewRenderbufferStorageEXT;
+
+GLEW_FUN_EXPORT PFNGLFRAMEBUFFERTEXTUREEXTPROC __glewFramebufferTextureEXT;
+GLEW_FUN_EXPORT PFNGLFRAMEBUFFERTEXTUREFACEEXTPROC __glewFramebufferTextureFaceEXT;
+GLEW_FUN_EXPORT PFNGLPROGRAMPARAMETERIEXTPROC __glewProgramParameteriEXT;
+
+GLEW_FUN_EXPORT PFNGLPROGRAMENVPARAMETERS4FVEXTPROC __glewProgramEnvParameters4fvEXT;
+GLEW_FUN_EXPORT PFNGLPROGRAMLOCALPARAMETERS4FVEXTPROC __glewProgramLocalParameters4fvEXT;
+
+GLEW_FUN_EXPORT PFNGLBINDFRAGDATALOCATIONEXTPROC __glewBindFragDataLocationEXT;
+GLEW_FUN_EXPORT PFNGLGETFRAGDATALOCATIONEXTPROC __glewGetFragDataLocationEXT;
+GLEW_FUN_EXPORT PFNGLGETUNIFORMUIVEXTPROC __glewGetUniformuivEXT;
+GLEW_FUN_EXPORT PFNGLGETVERTEXATTRIBIIVEXTPROC __glewGetVertexAttribIivEXT;
+GLEW_FUN_EXPORT PFNGLGETVERTEXATTRIBIUIVEXTPROC __glewGetVertexAttribIuivEXT;
+GLEW_FUN_EXPORT PFNGLUNIFORM1UIEXTPROC __glewUniform1uiEXT;
+GLEW_FUN_EXPORT PFNGLUNIFORM1UIVEXTPROC __glewUniform1uivEXT;
+GLEW_FUN_EXPORT PFNGLUNIFORM2UIEXTPROC __glewUniform2uiEXT;
+GLEW_FUN_EXPORT PFNGLUNIFORM2UIVEXTPROC __glewUniform2uivEXT;
+GLEW_FUN_EXPORT PFNGLUNIFORM3UIEXTPROC __glewUniform3uiEXT;
+GLEW_FUN_EXPORT PFNGLUNIFORM3UIVEXTPROC __glewUniform3uivEXT;
+GLEW_FUN_EXPORT PFNGLUNIFORM4UIEXTPROC __glewUniform4uiEXT;
+GLEW_FUN_EXPORT PFNGLUNIFORM4UIVEXTPROC __glewUniform4uivEXT;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI1IEXTPROC __glewVertexAttribI1iEXT;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI1IVEXTPROC __glewVertexAttribI1ivEXT;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI1UIEXTPROC __glewVertexAttribI1uiEXT;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI1UIVEXTPROC __glewVertexAttribI1uivEXT;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI2IEXTPROC __glewVertexAttribI2iEXT;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI2IVEXTPROC __glewVertexAttribI2ivEXT;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI2UIEXTPROC __glewVertexAttribI2uiEXT;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI2UIVEXTPROC __glewVertexAttribI2uivEXT;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI3IEXTPROC __glewVertexAttribI3iEXT;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI3IVEXTPROC __glewVertexAttribI3ivEXT;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI3UIEXTPROC __glewVertexAttribI3uiEXT;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI3UIVEXTPROC __glewVertexAttribI3uivEXT;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI4BVEXTPROC __glewVertexAttribI4bvEXT;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI4IEXTPROC __glewVertexAttribI4iEXT;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI4IVEXTPROC __glewVertexAttribI4ivEXT;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI4SVEXTPROC __glewVertexAttribI4svEXT;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI4UBVEXTPROC __glewVertexAttribI4ubvEXT;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI4UIEXTPROC __glewVertexAttribI4uiEXT;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI4UIVEXTPROC __glewVertexAttribI4uivEXT;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI4USVEXTPROC __glewVertexAttribI4usvEXT;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBIPOINTEREXTPROC __glewVertexAttribIPointerEXT;
+
+GLEW_FUN_EXPORT PFNGLGETHISTOGRAMEXTPROC __glewGetHistogramEXT;
+GLEW_FUN_EXPORT PFNGLGETHISTOGRAMPARAMETERFVEXTPROC __glewGetHistogramParameterfvEXT;
+GLEW_FUN_EXPORT PFNGLGETHISTOGRAMPARAMETERIVEXTPROC __glewGetHistogramParameterivEXT;
+GLEW_FUN_EXPORT PFNGLGETMINMAXEXTPROC __glewGetMinmaxEXT;
+GLEW_FUN_EXPORT PFNGLGETMINMAXPARAMETERFVEXTPROC __glewGetMinmaxParameterfvEXT;
+GLEW_FUN_EXPORT PFNGLGETMINMAXPARAMETERIVEXTPROC __glewGetMinmaxParameterivEXT;
+GLEW_FUN_EXPORT PFNGLHISTOGRAMEXTPROC __glewHistogramEXT;
+GLEW_FUN_EXPORT PFNGLMINMAXEXTPROC __glewMinmaxEXT;
+GLEW_FUN_EXPORT PFNGLRESETHISTOGRAMEXTPROC __glewResetHistogramEXT;
+GLEW_FUN_EXPORT PFNGLRESETMINMAXEXTPROC __glewResetMinmaxEXT;
+
+GLEW_FUN_EXPORT PFNGLINDEXFUNCEXTPROC __glewIndexFuncEXT;
+
+GLEW_FUN_EXPORT PFNGLINDEXMATERIALEXTPROC __glewIndexMaterialEXT;
+
+GLEW_FUN_EXPORT PFNGLAPPLYTEXTUREEXTPROC __glewApplyTextureEXT;
+GLEW_FUN_EXPORT PFNGLTEXTURELIGHTEXTPROC __glewTextureLightEXT;
+GLEW_FUN_EXPORT PFNGLTEXTUREMATERIALEXTPROC __glewTextureMaterialEXT;
+
+GLEW_FUN_EXPORT PFNGLMULTIDRAWARRAYSEXTPROC __glewMultiDrawArraysEXT;
+GLEW_FUN_EXPORT PFNGLMULTIDRAWELEMENTSEXTPROC __glewMultiDrawElementsEXT;
+
+GLEW_FUN_EXPORT PFNGLSAMPLEMASKEXTPROC __glewSampleMaskEXT;
+GLEW_FUN_EXPORT PFNGLSAMPLEPATTERNEXTPROC __glewSamplePatternEXT;
+
+GLEW_FUN_EXPORT PFNGLCOLORTABLEEXTPROC __glewColorTableEXT;
+GLEW_FUN_EXPORT PFNGLGETCOLORTABLEEXTPROC __glewGetColorTableEXT;
+GLEW_FUN_EXPORT PFNGLGETCOLORTABLEPARAMETERFVEXTPROC __glewGetColorTableParameterfvEXT;
+GLEW_FUN_EXPORT PFNGLGETCOLORTABLEPARAMETERIVEXTPROC __glewGetColorTableParameterivEXT;
+
+GLEW_FUN_EXPORT PFNGLGETPIXELTRANSFORMPARAMETERFVEXTPROC __glewGetPixelTransformParameterfvEXT;
+GLEW_FUN_EXPORT PFNGLGETPIXELTRANSFORMPARAMETERIVEXTPROC __glewGetPixelTransformParameterivEXT;
+GLEW_FUN_EXPORT PFNGLPIXELTRANSFORMPARAMETERFEXTPROC __glewPixelTransformParameterfEXT;
+GLEW_FUN_EXPORT PFNGLPIXELTRANSFORMPARAMETERFVEXTPROC __glewPixelTransformParameterfvEXT;
+GLEW_FUN_EXPORT PFNGLPIXELTRANSFORMPARAMETERIEXTPROC __glewPixelTransformParameteriEXT;
+GLEW_FUN_EXPORT PFNGLPIXELTRANSFORMPARAMETERIVEXTPROC __glewPixelTransformParameterivEXT;
+
+GLEW_FUN_EXPORT PFNGLPOINTPARAMETERFEXTPROC __glewPointParameterfEXT;
+GLEW_FUN_EXPORT PFNGLPOINTPARAMETERFVEXTPROC __glewPointParameterfvEXT;
+
+GLEW_FUN_EXPORT PFNGLPOLYGONOFFSETEXTPROC __glewPolygonOffsetEXT;
+
+GLEW_FUN_EXPORT PFNGLPROVOKINGVERTEXEXTPROC __glewProvokingVertexEXT;
+
+GLEW_FUN_EXPORT PFNGLBEGINSCENEEXTPROC __glewBeginSceneEXT;
+GLEW_FUN_EXPORT PFNGLENDSCENEEXTPROC __glewEndSceneEXT;
+
+GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3BEXTPROC __glewSecondaryColor3bEXT;
+GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3BVEXTPROC __glewSecondaryColor3bvEXT;
+GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3DEXTPROC __glewSecondaryColor3dEXT;
+GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3DVEXTPROC __glewSecondaryColor3dvEXT;
+GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3FEXTPROC __glewSecondaryColor3fEXT;
+GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3FVEXTPROC __glewSecondaryColor3fvEXT;
+GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3IEXTPROC __glewSecondaryColor3iEXT;
+GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3IVEXTPROC __glewSecondaryColor3ivEXT;
+GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3SEXTPROC __glewSecondaryColor3sEXT;
+GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3SVEXTPROC __glewSecondaryColor3svEXT;
+GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3UBEXTPROC __glewSecondaryColor3ubEXT;
+GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3UBVEXTPROC __glewSecondaryColor3ubvEXT;
+GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3UIEXTPROC __glewSecondaryColor3uiEXT;
+GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3UIVEXTPROC __glewSecondaryColor3uivEXT;
+GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3USEXTPROC __glewSecondaryColor3usEXT;
+GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3USVEXTPROC __glewSecondaryColor3usvEXT;
+GLEW_FUN_EXPORT PFNGLSECONDARYCOLORPOINTEREXTPROC __glewSecondaryColorPointerEXT;
+
+#if 0 // NOTE jwilkins: inconsistencies...
+GLEW_FUN_EXPORT PFNGLACTIVEPROGRAMEXTPROC __glewActiveProgramEXT;
+GLEW_FUN_EXPORT PFNGLCREATESHADERPROGRAMEXTPROC __glewCreateShaderProgramEXT;
+GLEW_FUN_EXPORT PFNGLUSESHADERPROGRAMEXTPROC __glewUseShaderProgramEXT;
+#endif
+
+GLEW_FUN_EXPORT PFNGLBINDIMAGETEXTUREEXTPROC __glewBindImageTextureEXT;
+GLEW_FUN_EXPORT PFNGLMEMORYBARRIEREXTPROC __glewMemoryBarrierEXT;
+
+GLEW_FUN_EXPORT PFNGLACTIVESTENCILFACEEXTPROC __glewActiveStencilFaceEXT;
+
+GLEW_FUN_EXPORT PFNGLTEXSUBIMAGE1DEXTPROC __glewTexSubImage1DEXT;
+GLEW_FUN_EXPORT PFNGLTEXSUBIMAGE2DEXTPROC __glewTexSubImage2DEXT;
+GLEW_FUN_EXPORT PFNGLTEXSUBIMAGE3DEXTPROC __glewTexSubImage3DEXT;
+
+GLEW_FUN_EXPORT PFNGLTEXIMAGE3DEXTPROC __glewTexImage3DEXT;
+
+GLEW_FUN_EXPORT PFNGLFRAMEBUFFERTEXTURELAYEREXTPROC __glewFramebufferTextureLayerEXT;
+
+GLEW_FUN_EXPORT PFNGLTEXBUFFEREXTPROC __glewTexBufferEXT;
+
+GLEW_FUN_EXPORT PFNGLCLEARCOLORIIEXTPROC __glewClearColorIiEXT;
+GLEW_FUN_EXPORT PFNGLCLEARCOLORIUIEXTPROC __glewClearColorIuiEXT;
+GLEW_FUN_EXPORT PFNGLGETTEXPARAMETERIIVEXTPROC __glewGetTexParameterIivEXT;
+GLEW_FUN_EXPORT PFNGLGETTEXPARAMETERIUIVEXTPROC __glewGetTexParameterIuivEXT;
+GLEW_FUN_EXPORT PFNGLTEXPARAMETERIIVEXTPROC __glewTexParameterIivEXT;
+GLEW_FUN_EXPORT PFNGLTEXPARAMETERIUIVEXTPROC __glewTexParameterIuivEXT;
+
+GLEW_FUN_EXPORT PFNGLARETEXTURESRESIDENTEXTPROC __glewAreTexturesResidentEXT;
+GLEW_FUN_EXPORT PFNGLBINDTEXTUREEXTPROC __glewBindTextureEXT;
+GLEW_FUN_EXPORT PFNGLDELETETEXTURESEXTPROC __glewDeleteTexturesEXT;
+GLEW_FUN_EXPORT PFNGLGENTEXTURESEXTPROC __glewGenTexturesEXT;
+GLEW_FUN_EXPORT PFNGLISTEXTUREEXTPROC __glewIsTextureEXT;
+GLEW_FUN_EXPORT PFNGLPRIORITIZETEXTURESEXTPROC __glewPrioritizeTexturesEXT;
+
+GLEW_FUN_EXPORT PFNGLTEXTURENORMALEXTPROC __glewTextureNormalEXT;
+
+GLEW_FUN_EXPORT PFNGLGETQUERYOBJECTI64VEXTPROC __glewGetQueryObjecti64vEXT;
+GLEW_FUN_EXPORT PFNGLGETQUERYOBJECTUI64VEXTPROC __glewGetQueryObjectui64vEXT;
+
+GLEW_FUN_EXPORT PFNGLBEGINTRANSFORMFEEDBACKEXTPROC __glewBeginTransformFeedbackEXT;
+GLEW_FUN_EXPORT PFNGLBINDBUFFERBASEEXTPROC __glewBindBufferBaseEXT;
+GLEW_FUN_EXPORT PFNGLBINDBUFFEROFFSETEXTPROC __glewBindBufferOffsetEXT;
+GLEW_FUN_EXPORT PFNGLBINDBUFFERRANGEEXTPROC __glewBindBufferRangeEXT;
+GLEW_FUN_EXPORT PFNGLENDTRANSFORMFEEDBACKEXTPROC __glewEndTransformFeedbackEXT;
+GLEW_FUN_EXPORT PFNGLGETTRANSFORMFEEDBACKVARYINGEXTPROC __glewGetTransformFeedbackVaryingEXT;
+GLEW_FUN_EXPORT PFNGLTRANSFORMFEEDBACKVARYINGSEXTPROC __glewTransformFeedbackVaryingsEXT;
+
+GLEW_FUN_EXPORT PFNGLARRAYELEMENTEXTPROC __glewArrayElementEXT;
+GLEW_FUN_EXPORT PFNGLCOLORPOINTEREXTPROC __glewColorPointerEXT;
+GLEW_FUN_EXPORT PFNGLDRAWARRAYSEXTPROC __glewDrawArraysEXT;
+GLEW_FUN_EXPORT PFNGLEDGEFLAGPOINTEREXTPROC __glewEdgeFlagPointerEXT;
+GLEW_FUN_EXPORT PFNGLINDEXPOINTEREXTPROC __glewIndexPointerEXT;
+GLEW_FUN_EXPORT PFNGLNORMALPOINTEREXTPROC __glewNormalPointerEXT;
+GLEW_FUN_EXPORT PFNGLTEXCOORDPOINTEREXTPROC __glewTexCoordPointerEXT;
+GLEW_FUN_EXPORT PFNGLVERTEXPOINTEREXTPROC __glewVertexPointerEXT;
+
+GLEW_FUN_EXPORT PFNGLGETVERTEXATTRIBLDVEXTPROC __glewGetVertexAttribLdvEXT;
+GLEW_FUN_EXPORT PFNGLVERTEXARRAYVERTEXATTRIBLOFFSETEXTPROC __glewVertexArrayVertexAttribLOffsetEXT;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL1DEXTPROC __glewVertexAttribL1dEXT;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL1DVEXTPROC __glewVertexAttribL1dvEXT;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL2DEXTPROC __glewVertexAttribL2dEXT;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL2DVEXTPROC __glewVertexAttribL2dvEXT;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL3DEXTPROC __glewVertexAttribL3dEXT;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL3DVEXTPROC __glewVertexAttribL3dvEXT;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL4DEXTPROC __glewVertexAttribL4dEXT;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL4DVEXTPROC __glewVertexAttribL4dvEXT;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBLPOINTEREXTPROC __glewVertexAttribLPointerEXT;
+
+GLEW_FUN_EXPORT PFNGLBEGINVERTEXSHADEREXTPROC __glewBeginVertexShaderEXT;
+GLEW_FUN_EXPORT PFNGLBINDLIGHTPARAMETEREXTPROC __glewBindLightParameterEXT;
+GLEW_FUN_EXPORT PFNGLBINDMATERIALPARAMETEREXTPROC __glewBindMaterialParameterEXT;
+GLEW_FUN_EXPORT PFNGLBINDPARAMETEREXTPROC __glewBindParameterEXT;
+GLEW_FUN_EXPORT PFNGLBINDTEXGENPARAMETEREXTPROC __glewBindTexGenParameterEXT;
+GLEW_FUN_EXPORT PFNGLBINDTEXTUREUNITPARAMETEREXTPROC __glewBindTextureUnitParameterEXT;
+GLEW_FUN_EXPORT PFNGLBINDVERTEXSHADEREXTPROC __glewBindVertexShaderEXT;
+GLEW_FUN_EXPORT PFNGLDELETEVERTEXSHADEREXTPROC __glewDeleteVertexShaderEXT;
+GLEW_FUN_EXPORT PFNGLDISABLEVARIANTCLIENTSTATEEXTPROC __glewDisableVariantClientStateEXT;
+GLEW_FUN_EXPORT PFNGLENABLEVARIANTCLIENTSTATEEXTPROC __glewEnableVariantClientStateEXT;
+GLEW_FUN_EXPORT PFNGLENDVERTEXSHADEREXTPROC __glewEndVertexShaderEXT;
+GLEW_FUN_EXPORT PFNGLEXTRACTCOMPONENTEXTPROC __glewExtractComponentEXT;
+GLEW_FUN_EXPORT PFNGLGENSYMBOLSEXTPROC __glewGenSymbolsEXT;
+GLEW_FUN_EXPORT PFNGLGENVERTEXSHADERSEXTPROC __glewGenVertexShadersEXT;
+GLEW_FUN_EXPORT PFNGLGETINVARIANTBOOLEANVEXTPROC __glewGetInvariantBooleanvEXT;
+GLEW_FUN_EXPORT PFNGLGETINVARIANTFLOATVEXTPROC __glewGetInvariantFloatvEXT;
+GLEW_FUN_EXPORT PFNGLGETINVARIANTINTEGERVEXTPROC __glewGetInvariantIntegervEXT;
+GLEW_FUN_EXPORT PFNGLGETLOCALCONSTANTBOOLEANVEXTPROC __glewGetLocalConstantBooleanvEXT;
+GLEW_FUN_EXPORT PFNGLGETLOCALCONSTANTFLOATVEXTPROC __glewGetLocalConstantFloatvEXT;
+GLEW_FUN_EXPORT PFNGLGETLOCALCONSTANTINTEGERVEXTPROC __glewGetLocalConstantIntegervEXT;
+GLEW_FUN_EXPORT PFNGLGETVARIANTBOOLEANVEXTPROC __glewGetVariantBooleanvEXT;
+GLEW_FUN_EXPORT PFNGLGETVARIANTFLOATVEXTPROC __glewGetVariantFloatvEXT;
+GLEW_FUN_EXPORT PFNGLGETVARIANTINTEGERVEXTPROC __glewGetVariantIntegervEXT;
+GLEW_FUN_EXPORT PFNGLGETVARIANTPOINTERVEXTPROC __glewGetVariantPointervEXT;
+GLEW_FUN_EXPORT PFNGLINSERTCOMPONENTEXTPROC __glewInsertComponentEXT;
+GLEW_FUN_EXPORT PFNGLISVARIANTENABLEDEXTPROC __glewIsVariantEnabledEXT;
+GLEW_FUN_EXPORT PFNGLSETINVARIANTEXTPROC __glewSetInvariantEXT;
+GLEW_FUN_EXPORT PFNGLSETLOCALCONSTANTEXTPROC __glewSetLocalConstantEXT;
+GLEW_FUN_EXPORT PFNGLSHADEROP1EXTPROC __glewShaderOp1EXT;
+GLEW_FUN_EXPORT PFNGLSHADEROP2EXTPROC __glewShaderOp2EXT;
+GLEW_FUN_EXPORT PFNGLSHADEROP3EXTPROC __glewShaderOp3EXT;
+GLEW_FUN_EXPORT PFNGLSWIZZLEEXTPROC __glewSwizzleEXT;
+GLEW_FUN_EXPORT PFNGLVARIANTPOINTEREXTPROC __glewVariantPointerEXT;
+GLEW_FUN_EXPORT PFNGLVARIANTBVEXTPROC __glewVariantbvEXT;
+GLEW_FUN_EXPORT PFNGLVARIANTDVEXTPROC __glewVariantdvEXT;
+GLEW_FUN_EXPORT PFNGLVARIANTFVEXTPROC __glewVariantfvEXT;
+GLEW_FUN_EXPORT PFNGLVARIANTIVEXTPROC __glewVariantivEXT;
+GLEW_FUN_EXPORT PFNGLVARIANTSVEXTPROC __glewVariantsvEXT;
+GLEW_FUN_EXPORT PFNGLVARIANTUBVEXTPROC __glewVariantubvEXT;
+GLEW_FUN_EXPORT PFNGLVARIANTUIVEXTPROC __glewVariantuivEXT;
+GLEW_FUN_EXPORT PFNGLVARIANTUSVEXTPROC __glewVariantusvEXT;
+GLEW_FUN_EXPORT PFNGLWRITEMASKEXTPROC __glewWriteMaskEXT;
+
+GLEW_FUN_EXPORT PFNGLVERTEXWEIGHTPOINTEREXTPROC __glewVertexWeightPointerEXT;
+GLEW_FUN_EXPORT PFNGLVERTEXWEIGHTFEXTPROC __glewVertexWeightfEXT;
+GLEW_FUN_EXPORT PFNGLVERTEXWEIGHTFVEXTPROC __glewVertexWeightfvEXT;
+
+GLEW_FUN_EXPORT PFNGLIMPORTSYNCEXTPROC __glewImportSyncEXT;
+
+GLEW_FUN_EXPORT PFNGLFRAMETERMINATORGREMEDYPROC __glewFrameTerminatorGREMEDY;
+
+GLEW_FUN_EXPORT PFNGLSTRINGMARKERGREMEDYPROC __glewStringMarkerGREMEDY;
+
+GLEW_FUN_EXPORT PFNGLGETIMAGETRANSFORMPARAMETERFVHPPROC __glewGetImageTransformParameterfvHP;
+GLEW_FUN_EXPORT PFNGLGETIMAGETRANSFORMPARAMETERIVHPPROC __glewGetImageTransformParameterivHP;
+GLEW_FUN_EXPORT PFNGLIMAGETRANSFORMPARAMETERFHPPROC __glewImageTransformParameterfHP;
+GLEW_FUN_EXPORT PFNGLIMAGETRANSFORMPARAMETERFVHPPROC __glewImageTransformParameterfvHP;
+GLEW_FUN_EXPORT PFNGLIMAGETRANSFORMPARAMETERIHPPROC __glewImageTransformParameteriHP;
+GLEW_FUN_EXPORT PFNGLIMAGETRANSFORMPARAMETERIVHPPROC __glewImageTransformParameterivHP;
+
+GLEW_FUN_EXPORT PFNGLMULTIMODEDRAWARRAYSIBMPROC __glewMultiModeDrawArraysIBM;
+GLEW_FUN_EXPORT PFNGLMULTIMODEDRAWELEMENTSIBMPROC __glewMultiModeDrawElementsIBM;
+
+GLEW_FUN_EXPORT PFNGLCOLORPOINTERLISTIBMPROC __glewColorPointerListIBM;
+GLEW_FUN_EXPORT PFNGLEDGEFLAGPOINTERLISTIBMPROC __glewEdgeFlagPointerListIBM;
+GLEW_FUN_EXPORT PFNGLFOGCOORDPOINTERLISTIBMPROC __glewFogCoordPointerListIBM;
+GLEW_FUN_EXPORT PFNGLINDEXPOINTERLISTIBMPROC __glewIndexPointerListIBM;
+GLEW_FUN_EXPORT PFNGLNORMALPOINTERLISTIBMPROC __glewNormalPointerListIBM;
+GLEW_FUN_EXPORT PFNGLSECONDARYCOLORPOINTERLISTIBMPROC __glewSecondaryColorPointerListIBM;
+GLEW_FUN_EXPORT PFNGLTEXCOORDPOINTERLISTIBMPROC __glewTexCoordPointerListIBM;
+GLEW_FUN_EXPORT PFNGLVERTEXPOINTERLISTIBMPROC __glewVertexPointerListIBM;
+
+GLEW_FUN_EXPORT PFNGLMAPTEXTURE2DINTELPROC __glewMapTexture2DINTEL;
+GLEW_FUN_EXPORT PFNGLSYNCTEXTUREINTELPROC __glewSyncTextureINTEL;
+GLEW_FUN_EXPORT PFNGLUNMAPTEXTURE2DINTELPROC __glewUnmapTexture2DINTEL;
+
+GLEW_FUN_EXPORT PFNGLCOLORPOINTERVINTELPROC __glewColorPointervINTEL;
+GLEW_FUN_EXPORT PFNGLNORMALPOINTERVINTELPROC __glewNormalPointervINTEL;
+GLEW_FUN_EXPORT PFNGLTEXCOORDPOINTERVINTELPROC __glewTexCoordPointervINTEL;
+GLEW_FUN_EXPORT PFNGLVERTEXPOINTERVINTELPROC __glewVertexPointervINTEL;
+
+GLEW_FUN_EXPORT PFNGLTEXSCISSORFUNCINTELPROC __glewTexScissorFuncINTEL;
+GLEW_FUN_EXPORT PFNGLTEXSCISSORINTELPROC __glewTexScissorINTEL;
+
+GLEW_FUN_EXPORT PFNGLDEBUGMESSAGECALLBACKPROC __glewDebugMessageCallback;
+GLEW_FUN_EXPORT PFNGLDEBUGMESSAGECONTROLPROC __glewDebugMessageControl;
+GLEW_FUN_EXPORT PFNGLDEBUGMESSAGEINSERTPROC __glewDebugMessageInsert;
+GLEW_FUN_EXPORT PFNGLGETDEBUGMESSAGELOGPROC __glewGetDebugMessageLog;
+GLEW_FUN_EXPORT PFNGLGETOBJECTLABELPROC __glewGetObjectLabel;
+GLEW_FUN_EXPORT PFNGLGETOBJECTPTRLABELPROC __glewGetObjectPtrLabel;
+//GLEW_FUN_EXPORT PFNGLGETPOINTERVPROC __glewGetPointerv; // NOTE jwilkins redefinition?
+GLEW_FUN_EXPORT PFNGLOBJECTLABELPROC __glewObjectLabel;
+GLEW_FUN_EXPORT PFNGLOBJECTPTRLABELPROC __glewObjectPtrLabel;
+GLEW_FUN_EXPORT PFNGLPOPDEBUGGROUPPROC __glewPopDebugGroup;
+GLEW_FUN_EXPORT PFNGLPUSHDEBUGGROUPPROC __glewPushDebugGroup;
+
+GLEW_FUN_EXPORT PFNGLBUFFERREGIONENABLEDPROC __glewBufferRegionEnabled;
+GLEW_FUN_EXPORT PFNGLDELETEBUFFERREGIONPROC __glewDeleteBufferRegion;
+GLEW_FUN_EXPORT PFNGLDRAWBUFFERREGIONPROC __glewDrawBufferRegion;
+GLEW_FUN_EXPORT PFNGLNEWBUFFERREGIONPROC __glewNewBufferRegion;
+GLEW_FUN_EXPORT PFNGLREADBUFFERREGIONPROC __glewReadBufferRegion;
+
+GLEW_FUN_EXPORT PFNGLRESIZEBUFFERSMESAPROC __glewResizeBuffersMESA;
+
+GLEW_FUN_EXPORT PFNGLWINDOWPOS2DMESAPROC __glewWindowPos2dMESA;
+GLEW_FUN_EXPORT PFNGLWINDOWPOS2DVMESAPROC __glewWindowPos2dvMESA;
+GLEW_FUN_EXPORT PFNGLWINDOWPOS2FMESAPROC __glewWindowPos2fMESA;
+GLEW_FUN_EXPORT PFNGLWINDOWPOS2FVMESAPROC __glewWindowPos2fvMESA;
+GLEW_FUN_EXPORT PFNGLWINDOWPOS2IMESAPROC __glewWindowPos2iMESA;
+GLEW_FUN_EXPORT PFNGLWINDOWPOS2IVMESAPROC __glewWindowPos2ivMESA;
+GLEW_FUN_EXPORT PFNGLWINDOWPOS2SMESAPROC __glewWindowPos2sMESA;
+GLEW_FUN_EXPORT PFNGLWINDOWPOS2SVMESAPROC __glewWindowPos2svMESA;
+GLEW_FUN_EXPORT PFNGLWINDOWPOS3DMESAPROC __glewWindowPos3dMESA;
+GLEW_FUN_EXPORT PFNGLWINDOWPOS3DVMESAPROC __glewWindowPos3dvMESA;
+GLEW_FUN_EXPORT PFNGLWINDOWPOS3FMESAPROC __glewWindowPos3fMESA;
+GLEW_FUN_EXPORT PFNGLWINDOWPOS3FVMESAPROC __glewWindowPos3fvMESA;
+GLEW_FUN_EXPORT PFNGLWINDOWPOS3IMESAPROC __glewWindowPos3iMESA;
+GLEW_FUN_EXPORT PFNGLWINDOWPOS3IVMESAPROC __glewWindowPos3ivMESA;
+GLEW_FUN_EXPORT PFNGLWINDOWPOS3SMESAPROC __glewWindowPos3sMESA;
+GLEW_FUN_EXPORT PFNGLWINDOWPOS3SVMESAPROC __glewWindowPos3svMESA;
+GLEW_FUN_EXPORT PFNGLWINDOWPOS4DMESAPROC __glewWindowPos4dMESA;
+GLEW_FUN_EXPORT PFNGLWINDOWPOS4DVMESAPROC __glewWindowPos4dvMESA;
+GLEW_FUN_EXPORT PFNGLWINDOWPOS4FMESAPROC __glewWindowPos4fMESA;
+GLEW_FUN_EXPORT PFNGLWINDOWPOS4FVMESAPROC __glewWindowPos4fvMESA;
+GLEW_FUN_EXPORT PFNGLWINDOWPOS4IMESAPROC __glewWindowPos4iMESA;
+GLEW_FUN_EXPORT PFNGLWINDOWPOS4IVMESAPROC __glewWindowPos4ivMESA;
+GLEW_FUN_EXPORT PFNGLWINDOWPOS4SMESAPROC __glewWindowPos4sMESA;
+GLEW_FUN_EXPORT PFNGLWINDOWPOS4SVMESAPROC __glewWindowPos4svMESA;
+
+GLEW_FUN_EXPORT PFNGLBEGINCONDITIONALRENDERNVXPROC __glewBeginConditionalRenderNVX;
+GLEW_FUN_EXPORT PFNGLENDCONDITIONALRENDERNVXPROC __glewEndConditionalRenderNVX;
+
+GLEW_FUN_EXPORT PFNGLGETIMAGEHANDLENVPROC __glewGetImageHandleNV;
+GLEW_FUN_EXPORT PFNGLGETTEXTUREHANDLENVPROC __glewGetTextureHandleNV;
+GLEW_FUN_EXPORT PFNGLGETTEXTURESAMPLERHANDLENVPROC __glewGetTextureSamplerHandleNV;
+GLEW_FUN_EXPORT PFNGLISIMAGEHANDLERESIDENTNVPROC __glewIsImageHandleResidentNV;
+GLEW_FUN_EXPORT PFNGLISTEXTUREHANDLERESIDENTNVPROC __glewIsTextureHandleResidentNV;
+GLEW_FUN_EXPORT PFNGLMAKEIMAGEHANDLENONRESIDENTNVPROC __glewMakeImageHandleNonResidentNV;
+GLEW_FUN_EXPORT PFNGLMAKEIMAGEHANDLERESIDENTNVPROC __glewMakeImageHandleResidentNV;
+GLEW_FUN_EXPORT PFNGLMAKETEXTUREHANDLENONRESIDENTNVPROC __glewMakeTextureHandleNonResidentNV;
+GLEW_FUN_EXPORT PFNGLMAKETEXTUREHANDLERESIDENTNVPROC __glewMakeTextureHandleResidentNV;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMHANDLEUI64NVPROC __glewProgramUniformHandleui64NV;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMHANDLEUI64VNVPROC __glewProgramUniformHandleui64vNV;
+GLEW_FUN_EXPORT PFNGLUNIFORMHANDLEUI64NVPROC __glewUniformHandleui64NV;
+GLEW_FUN_EXPORT PFNGLUNIFORMHANDLEUI64VNVPROC __glewUniformHandleui64vNV;
+
+GLEW_FUN_EXPORT PFNGLBEGINCONDITIONALRENDERNVPROC __glewBeginConditionalRenderNV;
+GLEW_FUN_EXPORT PFNGLENDCONDITIONALRENDERNVPROC __glewEndConditionalRenderNV;
+
+GLEW_FUN_EXPORT PFNGLCOPYIMAGESUBDATANVPROC __glewCopyImageSubDataNV;
+
+GLEW_FUN_EXPORT PFNGLCLEARDEPTHDNVPROC __glewClearDepthdNV;
+GLEW_FUN_EXPORT PFNGLDEPTHBOUNDSDNVPROC __glewDepthBoundsdNV;
+GLEW_FUN_EXPORT PFNGLDEPTHRANGEDNVPROC __glewDepthRangedNV;
+
+GLEW_FUN_EXPORT PFNGLDRAWTEXTURENVPROC __glewDrawTextureNV;
+
+GLEW_FUN_EXPORT PFNGLEVALMAPSNVPROC __glewEvalMapsNV;
+GLEW_FUN_EXPORT PFNGLGETMAPATTRIBPARAMETERFVNVPROC __glewGetMapAttribParameterfvNV;
+GLEW_FUN_EXPORT PFNGLGETMAPATTRIBPARAMETERIVNVPROC __glewGetMapAttribParameterivNV;
+GLEW_FUN_EXPORT PFNGLGETMAPCONTROLPOINTSNVPROC __glewGetMapControlPointsNV;
+GLEW_FUN_EXPORT PFNGLGETMAPPARAMETERFVNVPROC __glewGetMapParameterfvNV;
+GLEW_FUN_EXPORT PFNGLGETMAPPARAMETERIVNVPROC __glewGetMapParameterivNV;
+GLEW_FUN_EXPORT PFNGLMAPCONTROLPOINTSNVPROC __glewMapControlPointsNV;
+GLEW_FUN_EXPORT PFNGLMAPPARAMETERFVNVPROC __glewMapParameterfvNV;
+GLEW_FUN_EXPORT PFNGLMAPPARAMETERIVNVPROC __glewMapParameterivNV;
+
+GLEW_FUN_EXPORT PFNGLGETMULTISAMPLEFVNVPROC __glewGetMultisamplefvNV;
+GLEW_FUN_EXPORT PFNGLSAMPLEMASKINDEXEDNVPROC __glewSampleMaskIndexedNV;
+GLEW_FUN_EXPORT PFNGLTEXRENDERBUFFERNVPROC __glewTexRenderbufferNV;
+
+GLEW_FUN_EXPORT PFNGLDELETEFENCESNVPROC __glewDeleteFencesNV;
+GLEW_FUN_EXPORT PFNGLFINISHFENCENVPROC __glewFinishFenceNV;
+GLEW_FUN_EXPORT PFNGLGENFENCESNVPROC __glewGenFencesNV;
+GLEW_FUN_EXPORT PFNGLGETFENCEIVNVPROC __glewGetFenceivNV;
+GLEW_FUN_EXPORT PFNGLISFENCENVPROC __glewIsFenceNV;
+GLEW_FUN_EXPORT PFNGLSETFENCENVPROC __glewSetFenceNV;
+GLEW_FUN_EXPORT PFNGLTESTFENCENVPROC __glewTestFenceNV;
+
+GLEW_FUN_EXPORT PFNGLGETPROGRAMNAMEDPARAMETERDVNVPROC __glewGetProgramNamedParameterdvNV;
+GLEW_FUN_EXPORT PFNGLGETPROGRAMNAMEDPARAMETERFVNVPROC __glewGetProgramNamedParameterfvNV;
+GLEW_FUN_EXPORT PFNGLPROGRAMNAMEDPARAMETER4DNVPROC __glewProgramNamedParameter4dNV;
+GLEW_FUN_EXPORT PFNGLPROGRAMNAMEDPARAMETER4DVNVPROC __glewProgramNamedParameter4dvNV;
+GLEW_FUN_EXPORT PFNGLPROGRAMNAMEDPARAMETER4FNVPROC __glewProgramNamedParameter4fNV;
+GLEW_FUN_EXPORT PFNGLPROGRAMNAMEDPARAMETER4FVNVPROC __glewProgramNamedParameter4fvNV;
+
+GLEW_FUN_EXPORT PFNGLRENDERBUFFERSTORAGEMULTISAMPLECOVERAGENVPROC __glewRenderbufferStorageMultisampleCoverageNV;
+
+GLEW_FUN_EXPORT PFNGLPROGRAMVERTEXLIMITNVPROC __glewProgramVertexLimitNV;
+
+GLEW_FUN_EXPORT PFNGLPROGRAMENVPARAMETERI4INVPROC __glewProgramEnvParameterI4iNV;
+GLEW_FUN_EXPORT PFNGLPROGRAMENVPARAMETERI4IVNVPROC __glewProgramEnvParameterI4ivNV;
+GLEW_FUN_EXPORT PFNGLPROGRAMENVPARAMETERI4UINVPROC __glewProgramEnvParameterI4uiNV;
+GLEW_FUN_EXPORT PFNGLPROGRAMENVPARAMETERI4UIVNVPROC __glewProgramEnvParameterI4uivNV;
+GLEW_FUN_EXPORT PFNGLPROGRAMENVPARAMETERSI4IVNVPROC __glewProgramEnvParametersI4ivNV;
+GLEW_FUN_EXPORT PFNGLPROGRAMENVPARAMETERSI4UIVNVPROC __glewProgramEnvParametersI4uivNV;
+GLEW_FUN_EXPORT PFNGLPROGRAMLOCALPARAMETERI4INVPROC __glewProgramLocalParameterI4iNV;
+GLEW_FUN_EXPORT PFNGLPROGRAMLOCALPARAMETERI4IVNVPROC __glewProgramLocalParameterI4ivNV;
+GLEW_FUN_EXPORT PFNGLPROGRAMLOCALPARAMETERI4UINVPROC __glewProgramLocalParameterI4uiNV;
+GLEW_FUN_EXPORT PFNGLPROGRAMLOCALPARAMETERI4UIVNVPROC __glewProgramLocalParameterI4uivNV;
+GLEW_FUN_EXPORT PFNGLPROGRAMLOCALPARAMETERSI4IVNVPROC __glewProgramLocalParametersI4ivNV;
+GLEW_FUN_EXPORT PFNGLPROGRAMLOCALPARAMETERSI4UIVNVPROC __glewProgramLocalParametersI4uivNV;
+
+GLEW_FUN_EXPORT PFNGLGETUNIFORMI64VNVPROC __glewGetUniformi64vNV;
+GLEW_FUN_EXPORT PFNGLGETUNIFORMUI64VNVPROC __glewGetUniformui64vNV;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM1I64NVPROC __glewProgramUniform1i64NV;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM1I64VNVPROC __glewProgramUniform1i64vNV;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM1UI64NVPROC __glewProgramUniform1ui64NV;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM1UI64VNVPROC __glewProgramUniform1ui64vNV;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM2I64NVPROC __glewProgramUniform2i64NV;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM2I64VNVPROC __glewProgramUniform2i64vNV;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM2UI64NVPROC __glewProgramUniform2ui64NV;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM2UI64VNVPROC __glewProgramUniform2ui64vNV;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM3I64NVPROC __glewProgramUniform3i64NV;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM3I64VNVPROC __glewProgramUniform3i64vNV;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM3UI64NVPROC __glewProgramUniform3ui64NV;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM3UI64VNVPROC __glewProgramUniform3ui64vNV;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM4I64NVPROC __glewProgramUniform4i64NV;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM4I64VNVPROC __glewProgramUniform4i64vNV;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM4UI64NVPROC __glewProgramUniform4ui64NV;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM4UI64VNVPROC __glewProgramUniform4ui64vNV;
+GLEW_FUN_EXPORT PFNGLUNIFORM1I64NVPROC __glewUniform1i64NV;
+GLEW_FUN_EXPORT PFNGLUNIFORM1I64VNVPROC __glewUniform1i64vNV;
+GLEW_FUN_EXPORT PFNGLUNIFORM1UI64NVPROC __glewUniform1ui64NV;
+GLEW_FUN_EXPORT PFNGLUNIFORM1UI64VNVPROC __glewUniform1ui64vNV;
+GLEW_FUN_EXPORT PFNGLUNIFORM2I64NVPROC __glewUniform2i64NV;
+GLEW_FUN_EXPORT PFNGLUNIFORM2I64VNVPROC __glewUniform2i64vNV;
+GLEW_FUN_EXPORT PFNGLUNIFORM2UI64NVPROC __glewUniform2ui64NV;
+GLEW_FUN_EXPORT PFNGLUNIFORM2UI64VNVPROC __glewUniform2ui64vNV;
+GLEW_FUN_EXPORT PFNGLUNIFORM3I64NVPROC __glewUniform3i64NV;
+GLEW_FUN_EXPORT PFNGLUNIFORM3I64VNVPROC __glewUniform3i64vNV;
+GLEW_FUN_EXPORT PFNGLUNIFORM3UI64NVPROC __glewUniform3ui64NV;
+GLEW_FUN_EXPORT PFNGLUNIFORM3UI64VNVPROC __glewUniform3ui64vNV;
+GLEW_FUN_EXPORT PFNGLUNIFORM4I64NVPROC __glewUniform4i64NV;
+GLEW_FUN_EXPORT PFNGLUNIFORM4I64VNVPROC __glewUniform4i64vNV;
+GLEW_FUN_EXPORT PFNGLUNIFORM4UI64NVPROC __glewUniform4ui64NV;
+GLEW_FUN_EXPORT PFNGLUNIFORM4UI64VNVPROC __glewUniform4ui64vNV;
+
+GLEW_FUN_EXPORT PFNGLCOLOR3HNVPROC __glewColor3hNV;
+GLEW_FUN_EXPORT PFNGLCOLOR3HVNVPROC __glewColor3hvNV;
+GLEW_FUN_EXPORT PFNGLCOLOR4HNVPROC __glewColor4hNV;
+GLEW_FUN_EXPORT PFNGLCOLOR4HVNVPROC __glewColor4hvNV;
+GLEW_FUN_EXPORT PFNGLFOGCOORDHNVPROC __glewFogCoordhNV;
+GLEW_FUN_EXPORT PFNGLFOGCOORDHVNVPROC __glewFogCoordhvNV;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD1HNVPROC __glewMultiTexCoord1hNV;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD1HVNVPROC __glewMultiTexCoord1hvNV;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD2HNVPROC __glewMultiTexCoord2hNV;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD2HVNVPROC __glewMultiTexCoord2hvNV;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD3HNVPROC __glewMultiTexCoord3hNV;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD3HVNVPROC __glewMultiTexCoord3hvNV;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD4HNVPROC __glewMultiTexCoord4hNV;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD4HVNVPROC __glewMultiTexCoord4hvNV;
+GLEW_FUN_EXPORT PFNGLNORMAL3HNVPROC __glewNormal3hNV;
+GLEW_FUN_EXPORT PFNGLNORMAL3HVNVPROC __glewNormal3hvNV;
+GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3HNVPROC __glewSecondaryColor3hNV;
+GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3HVNVPROC __glewSecondaryColor3hvNV;
+GLEW_FUN_EXPORT PFNGLTEXCOORD1HNVPROC __glewTexCoord1hNV;
+GLEW_FUN_EXPORT PFNGLTEXCOORD1HVNVPROC __glewTexCoord1hvNV;
+GLEW_FUN_EXPORT PFNGLTEXCOORD2HNVPROC __glewTexCoord2hNV;
+GLEW_FUN_EXPORT PFNGLTEXCOORD2HVNVPROC __glewTexCoord2hvNV;
+GLEW_FUN_EXPORT PFNGLTEXCOORD3HNVPROC __glewTexCoord3hNV;
+GLEW_FUN_EXPORT PFNGLTEXCOORD3HVNVPROC __glewTexCoord3hvNV;
+GLEW_FUN_EXPORT PFNGLTEXCOORD4HNVPROC __glewTexCoord4hNV;
+GLEW_FUN_EXPORT PFNGLTEXCOORD4HVNVPROC __glewTexCoord4hvNV;
+GLEW_FUN_EXPORT PFNGLVERTEX2HNVPROC __glewVertex2hNV;
+GLEW_FUN_EXPORT PFNGLVERTEX2HVNVPROC __glewVertex2hvNV;
+GLEW_FUN_EXPORT PFNGLVERTEX3HNVPROC __glewVertex3hNV;
+GLEW_FUN_EXPORT PFNGLVERTEX3HVNVPROC __glewVertex3hvNV;
+GLEW_FUN_EXPORT PFNGLVERTEX4HNVPROC __glewVertex4hNV;
+GLEW_FUN_EXPORT PFNGLVERTEX4HVNVPROC __glewVertex4hvNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB1HNVPROC __glewVertexAttrib1hNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB1HVNVPROC __glewVertexAttrib1hvNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB2HNVPROC __glewVertexAttrib2hNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB2HVNVPROC __glewVertexAttrib2hvNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB3HNVPROC __glewVertexAttrib3hNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB3HVNVPROC __glewVertexAttrib3hvNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4HNVPROC __glewVertexAttrib4hNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4HVNVPROC __glewVertexAttrib4hvNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBS1HVNVPROC __glewVertexAttribs1hvNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBS2HVNVPROC __glewVertexAttribs2hvNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBS3HVNVPROC __glewVertexAttribs3hvNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBS4HVNVPROC __glewVertexAttribs4hvNV;
+GLEW_FUN_EXPORT PFNGLVERTEXWEIGHTHNVPROC __glewVertexWeighthNV;
+GLEW_FUN_EXPORT PFNGLVERTEXWEIGHTHVNVPROC __glewVertexWeighthvNV;
+
+GLEW_FUN_EXPORT PFNGLBEGINOCCLUSIONQUERYNVPROC __glewBeginOcclusionQueryNV;
+GLEW_FUN_EXPORT PFNGLDELETEOCCLUSIONQUERIESNVPROC __glewDeleteOcclusionQueriesNV;
+GLEW_FUN_EXPORT PFNGLENDOCCLUSIONQUERYNVPROC __glewEndOcclusionQueryNV;
+GLEW_FUN_EXPORT PFNGLGENOCCLUSIONQUERIESNVPROC __glewGenOcclusionQueriesNV;
+GLEW_FUN_EXPORT PFNGLGETOCCLUSIONQUERYIVNVPROC __glewGetOcclusionQueryivNV;
+GLEW_FUN_EXPORT PFNGLGETOCCLUSIONQUERYUIVNVPROC __glewGetOcclusionQueryuivNV;
+GLEW_FUN_EXPORT PFNGLISOCCLUSIONQUERYNVPROC __glewIsOcclusionQueryNV;
+
+GLEW_FUN_EXPORT PFNGLPROGRAMBUFFERPARAMETERSIIVNVPROC __glewProgramBufferParametersIivNV;
+GLEW_FUN_EXPORT PFNGLPROGRAMBUFFERPARAMETERSIUIVNVPROC __glewProgramBufferParametersIuivNV;
+GLEW_FUN_EXPORT PFNGLPROGRAMBUFFERPARAMETERSFVNVPROC __glewProgramBufferParametersfvNV;
+
+GLEW_FUN_EXPORT PFNGLCOPYPATHNVPROC __glewCopyPathNV;
+GLEW_FUN_EXPORT PFNGLCOVERFILLPATHINSTANCEDNVPROC __glewCoverFillPathInstancedNV;
+GLEW_FUN_EXPORT PFNGLCOVERFILLPATHNVPROC __glewCoverFillPathNV;
+GLEW_FUN_EXPORT PFNGLCOVERSTROKEPATHINSTANCEDNVPROC __glewCoverStrokePathInstancedNV;
+GLEW_FUN_EXPORT PFNGLCOVERSTROKEPATHNVPROC __glewCoverStrokePathNV;
+GLEW_FUN_EXPORT PFNGLDELETEPATHSNVPROC __glewDeletePathsNV;
+GLEW_FUN_EXPORT PFNGLGENPATHSNVPROC __glewGenPathsNV;
+GLEW_FUN_EXPORT PFNGLGETPATHCOLORGENFVNVPROC __glewGetPathColorGenfvNV;
+GLEW_FUN_EXPORT PFNGLGETPATHCOLORGENIVNVPROC __glewGetPathColorGenivNV;
+GLEW_FUN_EXPORT PFNGLGETPATHCOMMANDSNVPROC __glewGetPathCommandsNV;
+GLEW_FUN_EXPORT PFNGLGETPATHCOORDSNVPROC __glewGetPathCoordsNV;
+GLEW_FUN_EXPORT PFNGLGETPATHDASHARRAYNVPROC __glewGetPathDashArrayNV;
+GLEW_FUN_EXPORT PFNGLGETPATHLENGTHNVPROC __glewGetPathLengthNV;
+GLEW_FUN_EXPORT PFNGLGETPATHMETRICRANGENVPROC __glewGetPathMetricRangeNV;
+GLEW_FUN_EXPORT PFNGLGETPATHMETRICSNVPROC __glewGetPathMetricsNV;
+GLEW_FUN_EXPORT PFNGLGETPATHPARAMETERFVNVPROC __glewGetPathParameterfvNV;
+GLEW_FUN_EXPORT PFNGLGETPATHPARAMETERIVNVPROC __glewGetPathParameterivNV;
+GLEW_FUN_EXPORT PFNGLGETPATHSPACINGNVPROC __glewGetPathSpacingNV;
+GLEW_FUN_EXPORT PFNGLGETPATHTEXGENFVNVPROC __glewGetPathTexGenfvNV;
+GLEW_FUN_EXPORT PFNGLGETPATHTEXGENIVNVPROC __glewGetPathTexGenivNV;
+GLEW_FUN_EXPORT PFNGLINTERPOLATEPATHSNVPROC __glewInterpolatePathsNV;
+GLEW_FUN_EXPORT PFNGLISPATHNVPROC __glewIsPathNV;
+GLEW_FUN_EXPORT PFNGLISPOINTINFILLPATHNVPROC __glewIsPointInFillPathNV;
+GLEW_FUN_EXPORT PFNGLISPOINTINSTROKEPATHNVPROC __glewIsPointInStrokePathNV;
+GLEW_FUN_EXPORT PFNGLPATHCOLORGENNVPROC __glewPathColorGenNV;
+GLEW_FUN_EXPORT PFNGLPATHCOMMANDSNVPROC __glewPathCommandsNV;
+GLEW_FUN_EXPORT PFNGLPATHCOORDSNVPROC __glewPathCoordsNV;
+GLEW_FUN_EXPORT PFNGLPATHCOVERDEPTHFUNCNVPROC __glewPathCoverDepthFuncNV;
+GLEW_FUN_EXPORT PFNGLPATHDASHARRAYNVPROC __glewPathDashArrayNV;
+GLEW_FUN_EXPORT PFNGLPATHFOGGENNVPROC __glewPathFogGenNV;
+GLEW_FUN_EXPORT PFNGLPATHGLYPHRANGENVPROC __glewPathGlyphRangeNV;
+GLEW_FUN_EXPORT PFNGLPATHGLYPHSNVPROC __glewPathGlyphsNV;
+GLEW_FUN_EXPORT PFNGLPATHPARAMETERFNVPROC __glewPathParameterfNV;
+GLEW_FUN_EXPORT PFNGLPATHPARAMETERFVNVPROC __glewPathParameterfvNV;
+GLEW_FUN_EXPORT PFNGLPATHPARAMETERINVPROC __glewPathParameteriNV;
+GLEW_FUN_EXPORT PFNGLPATHPARAMETERIVNVPROC __glewPathParameterivNV;
+GLEW_FUN_EXPORT PFNGLPATHSTENCILDEPTHOFFSETNVPROC __glewPathStencilDepthOffsetNV;
+GLEW_FUN_EXPORT PFNGLPATHSTENCILFUNCNVPROC __glewPathStencilFuncNV;
+GLEW_FUN_EXPORT PFNGLPATHSTRINGNVPROC __glewPathStringNV;
+GLEW_FUN_EXPORT PFNGLPATHSUBCOMMANDSNVPROC __glewPathSubCommandsNV;
+GLEW_FUN_EXPORT PFNGLPATHSUBCOORDSNVPROC __glewPathSubCoordsNV;
+GLEW_FUN_EXPORT PFNGLPATHTEXGENNVPROC __glewPathTexGenNV;
+GLEW_FUN_EXPORT PFNGLPOINTALONGPATHNVPROC __glewPointAlongPathNV;
+GLEW_FUN_EXPORT PFNGLSTENCILFILLPATHINSTANCEDNVPROC __glewStencilFillPathInstancedNV;
+GLEW_FUN_EXPORT PFNGLSTENCILFILLPATHNVPROC __glewStencilFillPathNV;
+GLEW_FUN_EXPORT PFNGLSTENCILSTROKEPATHINSTANCEDNVPROC __glewStencilStrokePathInstancedNV;
+GLEW_FUN_EXPORT PFNGLSTENCILSTROKEPATHNVPROC __glewStencilStrokePathNV;
+GLEW_FUN_EXPORT PFNGLTRANSFORMPATHNVPROC __glewTransformPathNV;
+GLEW_FUN_EXPORT PFNGLWEIGHTPATHSNVPROC __glewWeightPathsNV;
+
+GLEW_FUN_EXPORT PFNGLFLUSHPIXELDATARANGENVPROC __glewFlushPixelDataRangeNV;
+GLEW_FUN_EXPORT PFNGLPIXELDATARANGENVPROC __glewPixelDataRangeNV;
+
+GLEW_FUN_EXPORT PFNGLPOINTPARAMETERINVPROC __glewPointParameteriNV;
+GLEW_FUN_EXPORT PFNGLPOINTPARAMETERIVNVPROC __glewPointParameterivNV;
+
+GLEW_FUN_EXPORT PFNGLGETVIDEOI64VNVPROC __glewGetVideoi64vNV;
+GLEW_FUN_EXPORT PFNGLGETVIDEOIVNVPROC __glewGetVideoivNV;
+GLEW_FUN_EXPORT PFNGLGETVIDEOUI64VNVPROC __glewGetVideoui64vNV;
+GLEW_FUN_EXPORT PFNGLGETVIDEOUIVNVPROC __glewGetVideouivNV;
+GLEW_FUN_EXPORT PFNGLPRESENTFRAMEDUALFILLNVPROC __glewPresentFrameDualFillNV;
+GLEW_FUN_EXPORT PFNGLPRESENTFRAMEKEYEDNVPROC __glewPresentFrameKeyedNV;
+
+GLEW_FUN_EXPORT PFNGLPRIMITIVERESTARTINDEXNVPROC __glewPrimitiveRestartIndexNV;
+GLEW_FUN_EXPORT PFNGLPRIMITIVERESTARTNVPROC __glewPrimitiveRestartNV;
+
+GLEW_FUN_EXPORT PFNGLCOMBINERINPUTNVPROC __glewCombinerInputNV;
+GLEW_FUN_EXPORT PFNGLCOMBINEROUTPUTNVPROC __glewCombinerOutputNV;
+GLEW_FUN_EXPORT PFNGLCOMBINERPARAMETERFNVPROC __glewCombinerParameterfNV;
+GLEW_FUN_EXPORT PFNGLCOMBINERPARAMETERFVNVPROC __glewCombinerParameterfvNV;
+GLEW_FUN_EXPORT PFNGLCOMBINERPARAMETERINVPROC __glewCombinerParameteriNV;
+GLEW_FUN_EXPORT PFNGLCOMBINERPARAMETERIVNVPROC __glewCombinerParameterivNV;
+GLEW_FUN_EXPORT PFNGLFINALCOMBINERINPUTNVPROC __glewFinalCombinerInputNV;
+GLEW_FUN_EXPORT PFNGLGETCOMBINERINPUTPARAMETERFVNVPROC __glewGetCombinerInputParameterfvNV;
+GLEW_FUN_EXPORT PFNGLGETCOMBINERINPUTPARAMETERIVNVPROC __glewGetCombinerInputParameterivNV;
+GLEW_FUN_EXPORT PFNGLGETCOMBINEROUTPUTPARAMETERFVNVPROC __glewGetCombinerOutputParameterfvNV;
+GLEW_FUN_EXPORT PFNGLGETCOMBINEROUTPUTPARAMETERIVNVPROC __glewGetCombinerOutputParameterivNV;
+GLEW_FUN_EXPORT PFNGLGETFINALCOMBINERINPUTPARAMETERFVNVPROC __glewGetFinalCombinerInputParameterfvNV;
+GLEW_FUN_EXPORT PFNGLGETFINALCOMBINERINPUTPARAMETERIVNVPROC __glewGetFinalCombinerInputParameterivNV;
+
+GLEW_FUN_EXPORT PFNGLCOMBINERSTAGEPARAMETERFVNVPROC __glewCombinerStageParameterfvNV;
+GLEW_FUN_EXPORT PFNGLGETCOMBINERSTAGEPARAMETERFVNVPROC __glewGetCombinerStageParameterfvNV;
+
+GLEW_FUN_EXPORT PFNGLGETBUFFERPARAMETERUI64VNVPROC __glewGetBufferParameterui64vNV;
+GLEW_FUN_EXPORT PFNGLGETINTEGERUI64VNVPROC __glewGetIntegerui64vNV;
+GLEW_FUN_EXPORT PFNGLGETNAMEDBUFFERPARAMETERUI64VNVPROC __glewGetNamedBufferParameterui64vNV;
+GLEW_FUN_EXPORT PFNGLISBUFFERRESIDENTNVPROC __glewIsBufferResidentNV;
+GLEW_FUN_EXPORT PFNGLISNAMEDBUFFERRESIDENTNVPROC __glewIsNamedBufferResidentNV;
+GLEW_FUN_EXPORT PFNGLMAKEBUFFERNONRESIDENTNVPROC __glewMakeBufferNonResidentNV;
+GLEW_FUN_EXPORT PFNGLMAKEBUFFERRESIDENTNVPROC __glewMakeBufferResidentNV;
+GLEW_FUN_EXPORT PFNGLMAKENAMEDBUFFERNONRESIDENTNVPROC __glewMakeNamedBufferNonResidentNV;
+GLEW_FUN_EXPORT PFNGLMAKENAMEDBUFFERRESIDENTNVPROC __glewMakeNamedBufferResidentNV;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMUI64NVPROC __glewProgramUniformui64NV;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMUI64VNVPROC __glewProgramUniformui64vNV;
+GLEW_FUN_EXPORT PFNGLUNIFORMUI64NVPROC __glewUniformui64NV;
+GLEW_FUN_EXPORT PFNGLUNIFORMUI64VNVPROC __glewUniformui64vNV;
+
+GLEW_FUN_EXPORT PFNGLTEXTUREBARRIERNVPROC __glewTextureBarrierNV;
+
+GLEW_FUN_EXPORT PFNGLTEXIMAGE2DMULTISAMPLECOVERAGENVPROC __glewTexImage2DMultisampleCoverageNV;
+GLEW_FUN_EXPORT PFNGLTEXIMAGE3DMULTISAMPLECOVERAGENVPROC __glewTexImage3DMultisampleCoverageNV;
+GLEW_FUN_EXPORT PFNGLTEXTUREIMAGE2DMULTISAMPLECOVERAGENVPROC __glewTextureImage2DMultisampleCoverageNV;
+GLEW_FUN_EXPORT PFNGLTEXTUREIMAGE2DMULTISAMPLENVPROC __glewTextureImage2DMultisampleNV;
+GLEW_FUN_EXPORT PFNGLTEXTUREIMAGE3DMULTISAMPLECOVERAGENVPROC __glewTextureImage3DMultisampleCoverageNV;
+GLEW_FUN_EXPORT PFNGLTEXTUREIMAGE3DMULTISAMPLENVPROC __glewTextureImage3DMultisampleNV;
+
+GLEW_FUN_EXPORT PFNGLACTIVEVARYINGNVPROC __glewActiveVaryingNV;
+GLEW_FUN_EXPORT PFNGLBEGINTRANSFORMFEEDBACKNVPROC __glewBeginTransformFeedbackNV;
+GLEW_FUN_EXPORT PFNGLBINDBUFFERBASENVPROC __glewBindBufferBaseNV;
+GLEW_FUN_EXPORT PFNGLBINDBUFFEROFFSETNVPROC __glewBindBufferOffsetNV;
+GLEW_FUN_EXPORT PFNGLBINDBUFFERRANGENVPROC __glewBindBufferRangeNV;
+GLEW_FUN_EXPORT PFNGLENDTRANSFORMFEEDBACKNVPROC __glewEndTransformFeedbackNV;
+GLEW_FUN_EXPORT PFNGLGETACTIVEVARYINGNVPROC __glewGetActiveVaryingNV;
+GLEW_FUN_EXPORT PFNGLGETTRANSFORMFEEDBACKVARYINGNVPROC __glewGetTransformFeedbackVaryingNV;
+GLEW_FUN_EXPORT PFNGLGETVARYINGLOCATIONNVPROC __glewGetVaryingLocationNV;
+GLEW_FUN_EXPORT PFNGLTRANSFORMFEEDBACKATTRIBSNVPROC __glewTransformFeedbackAttribsNV;
+GLEW_FUN_EXPORT PFNGLTRANSFORMFEEDBACKVARYINGSNVPROC __glewTransformFeedbackVaryingsNV;
+
+GLEW_FUN_EXPORT PFNGLBINDTRANSFORMFEEDBACKNVPROC __glewBindTransformFeedbackNV;
+GLEW_FUN_EXPORT PFNGLDELETETRANSFORMFEEDBACKSNVPROC __glewDeleteTransformFeedbacksNV;
+GLEW_FUN_EXPORT PFNGLDRAWTRANSFORMFEEDBACKNVPROC __glewDrawTransformFeedbackNV;
+GLEW_FUN_EXPORT PFNGLGENTRANSFORMFEEDBACKSNVPROC __glewGenTransformFeedbacksNV;
+GLEW_FUN_EXPORT PFNGLISTRANSFORMFEEDBACKNVPROC __glewIsTransformFeedbackNV;
+GLEW_FUN_EXPORT PFNGLPAUSETRANSFORMFEEDBACKNVPROC __glewPauseTransformFeedbackNV;
+GLEW_FUN_EXPORT PFNGLRESUMETRANSFORMFEEDBACKNVPROC __glewResumeTransformFeedbackNV;
+
+GLEW_FUN_EXPORT PFNGLVDPAUFININVPROC __glewVDPAUFiniNV;
+GLEW_FUN_EXPORT PFNGLVDPAUGETSURFACEIVNVPROC __glewVDPAUGetSurfaceivNV;
+GLEW_FUN_EXPORT PFNGLVDPAUINITNVPROC __glewVDPAUInitNV;
+GLEW_FUN_EXPORT PFNGLVDPAUISSURFACENVPROC __glewVDPAUIsSurfaceNV;
+GLEW_FUN_EXPORT PFNGLVDPAUMAPSURFACESNVPROC __glewVDPAUMapSurfacesNV;
+GLEW_FUN_EXPORT PFNGLVDPAUREGISTEROUTPUTSURFACENVPROC __glewVDPAURegisterOutputSurfaceNV;
+GLEW_FUN_EXPORT PFNGLVDPAUREGISTERVIDEOSURFACENVPROC __glewVDPAURegisterVideoSurfaceNV;
+GLEW_FUN_EXPORT PFNGLVDPAUSURFACEACCESSNVPROC __glewVDPAUSurfaceAccessNV;
+GLEW_FUN_EXPORT PFNGLVDPAUUNMAPSURFACESNVPROC __glewVDPAUUnmapSurfacesNV;
+GLEW_FUN_EXPORT PFNGLVDPAUUNREGISTERSURFACENVPROC __glewVDPAUUnregisterSurfaceNV;
+
+GLEW_FUN_EXPORT PFNGLFLUSHVERTEXARRAYRANGENVPROC __glewFlushVertexArrayRangeNV;
+GLEW_FUN_EXPORT PFNGLVERTEXARRAYRANGENVPROC __glewVertexArrayRangeNV;
+
+GLEW_FUN_EXPORT PFNGLGETVERTEXATTRIBLI64VNVPROC __glewGetVertexAttribLi64vNV;
+GLEW_FUN_EXPORT PFNGLGETVERTEXATTRIBLUI64VNVPROC __glewGetVertexAttribLui64vNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL1I64NVPROC __glewVertexAttribL1i64NV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL1I64VNVPROC __glewVertexAttribL1i64vNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL1UI64NVPROC __glewVertexAttribL1ui64NV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL1UI64VNVPROC __glewVertexAttribL1ui64vNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL2I64NVPROC __glewVertexAttribL2i64NV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL2I64VNVPROC __glewVertexAttribL2i64vNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL2UI64NVPROC __glewVertexAttribL2ui64NV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL2UI64VNVPROC __glewVertexAttribL2ui64vNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL3I64NVPROC __glewVertexAttribL3i64NV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL3I64VNVPROC __glewVertexAttribL3i64vNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL3UI64NVPROC __glewVertexAttribL3ui64NV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL3UI64VNVPROC __glewVertexAttribL3ui64vNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL4I64NVPROC __glewVertexAttribL4i64NV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL4I64VNVPROC __glewVertexAttribL4i64vNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL4UI64NVPROC __glewVertexAttribL4ui64NV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL4UI64VNVPROC __glewVertexAttribL4ui64vNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBLFORMATNVPROC __glewVertexAttribLFormatNV;
+
+GLEW_FUN_EXPORT PFNGLBUFFERADDRESSRANGENVPROC __glewBufferAddressRangeNV;
+GLEW_FUN_EXPORT PFNGLCOLORFORMATNVPROC __glewColorFormatNV;
+GLEW_FUN_EXPORT PFNGLEDGEFLAGFORMATNVPROC __glewEdgeFlagFormatNV;
+GLEW_FUN_EXPORT PFNGLFOGCOORDFORMATNVPROC __glewFogCoordFormatNV;
+GLEW_FUN_EXPORT PFNGLGETINTEGERUI64I_VNVPROC __glewGetIntegerui64i_vNV;
+GLEW_FUN_EXPORT PFNGLINDEXFORMATNVPROC __glewIndexFormatNV;
+GLEW_FUN_EXPORT PFNGLNORMALFORMATNVPROC __glewNormalFormatNV;
+GLEW_FUN_EXPORT PFNGLSECONDARYCOLORFORMATNVPROC __glewSecondaryColorFormatNV;
+GLEW_FUN_EXPORT PFNGLTEXCOORDFORMATNVPROC __glewTexCoordFormatNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBFORMATNVPROC __glewVertexAttribFormatNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBIFORMATNVPROC __glewVertexAttribIFormatNV;
+GLEW_FUN_EXPORT PFNGLVERTEXFORMATNVPROC __glewVertexFormatNV;
+
+GLEW_FUN_EXPORT PFNGLAREPROGRAMSRESIDENTNVPROC __glewAreProgramsResidentNV;
+GLEW_FUN_EXPORT PFNGLBINDPROGRAMNVPROC __glewBindProgramNV;
+GLEW_FUN_EXPORT PFNGLDELETEPROGRAMSNVPROC __glewDeleteProgramsNV;
+GLEW_FUN_EXPORT PFNGLEXECUTEPROGRAMNVPROC __glewExecuteProgramNV;
+GLEW_FUN_EXPORT PFNGLGENPROGRAMSNVPROC __glewGenProgramsNV;
+GLEW_FUN_EXPORT PFNGLGETPROGRAMPARAMETERDVNVPROC __glewGetProgramParameterdvNV;
+GLEW_FUN_EXPORT PFNGLGETPROGRAMPARAMETERFVNVPROC __glewGetProgramParameterfvNV;
+GLEW_FUN_EXPORT PFNGLGETPROGRAMSTRINGNVPROC __glewGetProgramStringNV;
+GLEW_FUN_EXPORT PFNGLGETPROGRAMIVNVPROC __glewGetProgramivNV;
+GLEW_FUN_EXPORT PFNGLGETTRACKMATRIXIVNVPROC __glewGetTrackMatrixivNV;
+GLEW_FUN_EXPORT PFNGLGETVERTEXATTRIBPOINTERVNVPROC __glewGetVertexAttribPointervNV;
+GLEW_FUN_EXPORT PFNGLGETVERTEXATTRIBDVNVPROC __glewGetVertexAttribdvNV;
+GLEW_FUN_EXPORT PFNGLGETVERTEXATTRIBFVNVPROC __glewGetVertexAttribfvNV;
+GLEW_FUN_EXPORT PFNGLGETVERTEXATTRIBIVNVPROC __glewGetVertexAttribivNV;
+GLEW_FUN_EXPORT PFNGLISPROGRAMNVPROC __glewIsProgramNV;
+GLEW_FUN_EXPORT PFNGLLOADPROGRAMNVPROC __glewLoadProgramNV;
+GLEW_FUN_EXPORT PFNGLPROGRAMPARAMETER4DNVPROC __glewProgramParameter4dNV;
+GLEW_FUN_EXPORT PFNGLPROGRAMPARAMETER4DVNVPROC __glewProgramParameter4dvNV;
+GLEW_FUN_EXPORT PFNGLPROGRAMPARAMETER4FNVPROC __glewProgramParameter4fNV;
+GLEW_FUN_EXPORT PFNGLPROGRAMPARAMETER4FVNVPROC __glewProgramParameter4fvNV;
+GLEW_FUN_EXPORT PFNGLPROGRAMPARAMETERS4DVNVPROC __glewProgramParameters4dvNV;
+GLEW_FUN_EXPORT PFNGLPROGRAMPARAMETERS4FVNVPROC __glewProgramParameters4fvNV;
+GLEW_FUN_EXPORT PFNGLREQUESTRESIDENTPROGRAMSNVPROC __glewRequestResidentProgramsNV;
+GLEW_FUN_EXPORT PFNGLTRACKMATRIXNVPROC __glewTrackMatrixNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB1DNVPROC __glewVertexAttrib1dNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB1DVNVPROC __glewVertexAttrib1dvNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB1FNVPROC __glewVertexAttrib1fNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB1FVNVPROC __glewVertexAttrib1fvNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB1SNVPROC __glewVertexAttrib1sNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB1SVNVPROC __glewVertexAttrib1svNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB2DNVPROC __glewVertexAttrib2dNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB2DVNVPROC __glewVertexAttrib2dvNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB2FNVPROC __glewVertexAttrib2fNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB2FVNVPROC __glewVertexAttrib2fvNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB2SNVPROC __glewVertexAttrib2sNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB2SVNVPROC __glewVertexAttrib2svNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB3DNVPROC __glewVertexAttrib3dNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB3DVNVPROC __glewVertexAttrib3dvNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB3FNVPROC __glewVertexAttrib3fNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB3FVNVPROC __glewVertexAttrib3fvNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB3SNVPROC __glewVertexAttrib3sNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB3SVNVPROC __glewVertexAttrib3svNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4DNVPROC __glewVertexAttrib4dNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4DVNVPROC __glewVertexAttrib4dvNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4FNVPROC __glewVertexAttrib4fNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4FVNVPROC __glewVertexAttrib4fvNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4SNVPROC __glewVertexAttrib4sNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4SVNVPROC __glewVertexAttrib4svNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4UBNVPROC __glewVertexAttrib4ubNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4UBVNVPROC __glewVertexAttrib4ubvNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBPOINTERNVPROC __glewVertexAttribPointerNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBS1DVNVPROC __glewVertexAttribs1dvNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBS1FVNVPROC __glewVertexAttribs1fvNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBS1SVNVPROC __glewVertexAttribs1svNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBS2DVNVPROC __glewVertexAttribs2dvNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBS2FVNVPROC __glewVertexAttribs2fvNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBS2SVNVPROC __glewVertexAttribs2svNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBS3DVNVPROC __glewVertexAttribs3dvNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBS3FVNVPROC __glewVertexAttribs3fvNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBS3SVNVPROC __glewVertexAttribs3svNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBS4DVNVPROC __glewVertexAttribs4dvNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBS4FVNVPROC __glewVertexAttribs4fvNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBS4SVNVPROC __glewVertexAttribs4svNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBS4UBVNVPROC __glewVertexAttribs4ubvNV;
+
+GLEW_FUN_EXPORT PFNGLBEGINVIDEOCAPTURENVPROC __glewBeginVideoCaptureNV;
+GLEW_FUN_EXPORT PFNGLBINDVIDEOCAPTURESTREAMBUFFERNVPROC __glewBindVideoCaptureStreamBufferNV;
+GLEW_FUN_EXPORT PFNGLBINDVIDEOCAPTURESTREAMTEXTURENVPROC __glewBindVideoCaptureStreamTextureNV;
+GLEW_FUN_EXPORT PFNGLENDVIDEOCAPTURENVPROC __glewEndVideoCaptureNV;
+GLEW_FUN_EXPORT PFNGLGETVIDEOCAPTURESTREAMDVNVPROC __glewGetVideoCaptureStreamdvNV;
+GLEW_FUN_EXPORT PFNGLGETVIDEOCAPTURESTREAMFVNVPROC __glewGetVideoCaptureStreamfvNV;
+GLEW_FUN_EXPORT PFNGLGETVIDEOCAPTURESTREAMIVNVPROC __glewGetVideoCaptureStreamivNV;
+GLEW_FUN_EXPORT PFNGLGETVIDEOCAPTUREIVNVPROC __glewGetVideoCaptureivNV;
+GLEW_FUN_EXPORT PFNGLVIDEOCAPTURENVPROC __glewVideoCaptureNV;
+GLEW_FUN_EXPORT PFNGLVIDEOCAPTURESTREAMPARAMETERDVNVPROC __glewVideoCaptureStreamParameterdvNV;
+GLEW_FUN_EXPORT PFNGLVIDEOCAPTURESTREAMPARAMETERFVNVPROC __glewVideoCaptureStreamParameterfvNV;
+GLEW_FUN_EXPORT PFNGLVIDEOCAPTURESTREAMPARAMETERIVNVPROC __glewVideoCaptureStreamParameterivNV;
+
+GLEW_FUN_EXPORT PFNGLCLEARDEPTHFOESPROC __glewClearDepthfOES;
+GLEW_FUN_EXPORT PFNGLCLIPPLANEFOESPROC __glewClipPlanefOES;
+GLEW_FUN_EXPORT PFNGLDEPTHRANGEFOESPROC __glewDepthRangefOES;
+GLEW_FUN_EXPORT PFNGLFRUSTUMFOESPROC __glewFrustumfOES;
+GLEW_FUN_EXPORT PFNGLGETCLIPPLANEFOESPROC __glewGetClipPlanefOES;
+GLEW_FUN_EXPORT PFNGLORTHOFOESPROC __glewOrthofOES;
+
+GLEW_FUN_EXPORT PFNGLDETAILTEXFUNCSGISPROC __glewDetailTexFuncSGIS;
+GLEW_FUN_EXPORT PFNGLGETDETAILTEXFUNCSGISPROC __glewGetDetailTexFuncSGIS;
+
+GLEW_FUN_EXPORT PFNGLFOGFUNCSGISPROC __glewFogFuncSGIS;
+GLEW_FUN_EXPORT PFNGLGETFOGFUNCSGISPROC __glewGetFogFuncSGIS;
+
+GLEW_FUN_EXPORT PFNGLSAMPLEMASKSGISPROC __glewSampleMaskSGIS;
+GLEW_FUN_EXPORT PFNGLSAMPLEPATTERNSGISPROC __glewSamplePatternSGIS;
+
+GLEW_FUN_EXPORT PFNGLGETSHARPENTEXFUNCSGISPROC __glewGetSharpenTexFuncSGIS;
+GLEW_FUN_EXPORT PFNGLSHARPENTEXFUNCSGISPROC __glewSharpenTexFuncSGIS;
+
+GLEW_FUN_EXPORT PFNGLTEXIMAGE4DSGISPROC __glewTexImage4DSGIS;
+GLEW_FUN_EXPORT PFNGLTEXSUBIMAGE4DSGISPROC __glewTexSubImage4DSGIS;
+
+GLEW_FUN_EXPORT PFNGLGETTEXFILTERFUNCSGISPROC __glewGetTexFilterFuncSGIS;
+GLEW_FUN_EXPORT PFNGLTEXFILTERFUNCSGISPROC __glewTexFilterFuncSGIS;
+
+GLEW_FUN_EXPORT PFNGLASYNCMARKERSGIXPROC __glewAsyncMarkerSGIX;
+GLEW_FUN_EXPORT PFNGLDELETEASYNCMARKERSSGIXPROC __glewDeleteAsyncMarkersSGIX;
+GLEW_FUN_EXPORT PFNGLFINISHASYNCSGIXPROC __glewFinishAsyncSGIX;
+GLEW_FUN_EXPORT PFNGLGENASYNCMARKERSSGIXPROC __glewGenAsyncMarkersSGIX;
+GLEW_FUN_EXPORT PFNGLISASYNCMARKERSGIXPROC __glewIsAsyncMarkerSGIX;
+GLEW_FUN_EXPORT PFNGLPOLLASYNCSGIXPROC __glewPollAsyncSGIX;
+
+GLEW_FUN_EXPORT PFNGLFLUSHRASTERSGIXPROC __glewFlushRasterSGIX;
+
+GLEW_FUN_EXPORT PFNGLTEXTUREFOGSGIXPROC __glewTextureFogSGIX;
+
+GLEW_FUN_EXPORT PFNGLFRAGMENTCOLORMATERIALSGIXPROC __glewFragmentColorMaterialSGIX;
+GLEW_FUN_EXPORT PFNGLFRAGMENTLIGHTMODELFSGIXPROC __glewFragmentLightModelfSGIX;
+GLEW_FUN_EXPORT PFNGLFRAGMENTLIGHTMODELFVSGIXPROC __glewFragmentLightModelfvSGIX;
+GLEW_FUN_EXPORT PFNGLFRAGMENTLIGHTMODELISGIXPROC __glewFragmentLightModeliSGIX;
+GLEW_FUN_EXPORT PFNGLFRAGMENTLIGHTMODELIVSGIXPROC __glewFragmentLightModelivSGIX;
+GLEW_FUN_EXPORT PFNGLFRAGMENTLIGHTFSGIXPROC __glewFragmentLightfSGIX;
+GLEW_FUN_EXPORT PFNGLFRAGMENTLIGHTFVSGIXPROC __glewFragmentLightfvSGIX;
+GLEW_FUN_EXPORT PFNGLFRAGMENTLIGHTISGIXPROC __glewFragmentLightiSGIX;
+GLEW_FUN_EXPORT PFNGLFRAGMENTLIGHTIVSGIXPROC __glewFragmentLightivSGIX;
+GLEW_FUN_EXPORT PFNGLFRAGMENTMATERIALFSGIXPROC __glewFragmentMaterialfSGIX;
+GLEW_FUN_EXPORT PFNGLFRAGMENTMATERIALFVSGIXPROC __glewFragmentMaterialfvSGIX;
+GLEW_FUN_EXPORT PFNGLFRAGMENTMATERIALISGIXPROC __glewFragmentMaterialiSGIX;
+GLEW_FUN_EXPORT PFNGLFRAGMENTMATERIALIVSGIXPROC __glewFragmentMaterialivSGIX;
+GLEW_FUN_EXPORT PFNGLGETFRAGMENTLIGHTFVSGIXPROC __glewGetFragmentLightfvSGIX;
+GLEW_FUN_EXPORT PFNGLGETFRAGMENTLIGHTIVSGIXPROC __glewGetFragmentLightivSGIX;
+GLEW_FUN_EXPORT PFNGLGETFRAGMENTMATERIALFVSGIXPROC __glewGetFragmentMaterialfvSGIX;
+GLEW_FUN_EXPORT PFNGLGETFRAGMENTMATERIALIVSGIXPROC __glewGetFragmentMaterialivSGIX;
+
+GLEW_FUN_EXPORT PFNGLFRAMEZOOMSGIXPROC __glewFrameZoomSGIX;
+
+GLEW_FUN_EXPORT PFNGLPIXELTEXGENSGIXPROC __glewPixelTexGenSGIX;
+
+GLEW_FUN_EXPORT PFNGLREFERENCEPLANESGIXPROC __glewReferencePlaneSGIX;
+
+GLEW_FUN_EXPORT PFNGLSPRITEPARAMETERFSGIXPROC __glewSpriteParameterfSGIX;
+GLEW_FUN_EXPORT PFNGLSPRITEPARAMETERFVSGIXPROC __glewSpriteParameterfvSGIX;
+GLEW_FUN_EXPORT PFNGLSPRITEPARAMETERISGIXPROC __glewSpriteParameteriSGIX;
+GLEW_FUN_EXPORT PFNGLSPRITEPARAMETERIVSGIXPROC __glewSpriteParameterivSGIX;
+
+GLEW_FUN_EXPORT PFNGLTAGSAMPLEBUFFERSGIXPROC __glewTagSampleBufferSGIX;
+
+GLEW_FUN_EXPORT PFNGLCOLORTABLEPARAMETERFVSGIPROC __glewColorTableParameterfvSGI;
+GLEW_FUN_EXPORT PFNGLCOLORTABLEPARAMETERIVSGIPROC __glewColorTableParameterivSGI;
+GLEW_FUN_EXPORT PFNGLCOLORTABLESGIPROC __glewColorTableSGI;
+GLEW_FUN_EXPORT PFNGLCOPYCOLORTABLESGIPROC __glewCopyColorTableSGI;
+GLEW_FUN_EXPORT PFNGLGETCOLORTABLEPARAMETERFVSGIPROC __glewGetColorTableParameterfvSGI;
+GLEW_FUN_EXPORT PFNGLGETCOLORTABLEPARAMETERIVSGIPROC __glewGetColorTableParameterivSGI;
+GLEW_FUN_EXPORT PFNGLGETCOLORTABLESGIPROC __glewGetColorTableSGI;
+
+GLEW_FUN_EXPORT PFNGLFINISHTEXTURESUNXPROC __glewFinishTextureSUNX;
+
+GLEW_FUN_EXPORT PFNGLGLOBALALPHAFACTORBSUNPROC __glewGlobalAlphaFactorbSUN;
+GLEW_FUN_EXPORT PFNGLGLOBALALPHAFACTORDSUNPROC __glewGlobalAlphaFactordSUN;
+GLEW_FUN_EXPORT PFNGLGLOBALALPHAFACTORFSUNPROC __glewGlobalAlphaFactorfSUN;
+GLEW_FUN_EXPORT PFNGLGLOBALALPHAFACTORISUNPROC __glewGlobalAlphaFactoriSUN;
+GLEW_FUN_EXPORT PFNGLGLOBALALPHAFACTORSSUNPROC __glewGlobalAlphaFactorsSUN;
+GLEW_FUN_EXPORT PFNGLGLOBALALPHAFACTORUBSUNPROC __glewGlobalAlphaFactorubSUN;
+GLEW_FUN_EXPORT PFNGLGLOBALALPHAFACTORUISUNPROC __glewGlobalAlphaFactoruiSUN;
+GLEW_FUN_EXPORT PFNGLGLOBALALPHAFACTORUSSUNPROC __glewGlobalAlphaFactorusSUN;
+
+GLEW_FUN_EXPORT PFNGLREADVIDEOPIXELSSUNPROC __glewReadVideoPixelsSUN;
+
+GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEPOINTERSUNPROC __glewReplacementCodePointerSUN;
+GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUBSUNPROC __glewReplacementCodeubSUN;
+GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUBVSUNPROC __glewReplacementCodeubvSUN;
+GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUISUNPROC __glewReplacementCodeuiSUN;
+GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUIVSUNPROC __glewReplacementCodeuivSUN;
+GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUSSUNPROC __glewReplacementCodeusSUN;
+GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUSVSUNPROC __glewReplacementCodeusvSUN;
+
+GLEW_FUN_EXPORT PFNGLCOLOR3FVERTEX3FSUNPROC __glewColor3fVertex3fSUN;
+GLEW_FUN_EXPORT PFNGLCOLOR3FVERTEX3FVSUNPROC __glewColor3fVertex3fvSUN;
+GLEW_FUN_EXPORT PFNGLCOLOR4FNORMAL3FVERTEX3FSUNPROC __glewColor4fNormal3fVertex3fSUN;
+GLEW_FUN_EXPORT PFNGLCOLOR4FNORMAL3FVERTEX3FVSUNPROC __glewColor4fNormal3fVertex3fvSUN;
+GLEW_FUN_EXPORT PFNGLCOLOR4UBVERTEX2FSUNPROC __glewColor4ubVertex2fSUN;
+GLEW_FUN_EXPORT PFNGLCOLOR4UBVERTEX2FVSUNPROC __glewColor4ubVertex2fvSUN;
+GLEW_FUN_EXPORT PFNGLCOLOR4UBVERTEX3FSUNPROC __glewColor4ubVertex3fSUN;
+GLEW_FUN_EXPORT PFNGLCOLOR4UBVERTEX3FVSUNPROC __glewColor4ubVertex3fvSUN;
+GLEW_FUN_EXPORT PFNGLNORMAL3FVERTEX3FSUNPROC __glewNormal3fVertex3fSUN;
+GLEW_FUN_EXPORT PFNGLNORMAL3FVERTEX3FVSUNPROC __glewNormal3fVertex3fvSUN;
+GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUICOLOR3FVERTEX3FSUNPROC __glewReplacementCodeuiColor3fVertex3fSUN;
+GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUICOLOR3FVERTEX3FVSUNPROC __glewReplacementCodeuiColor3fVertex3fvSUN;
+GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUICOLOR4FNORMAL3FVERTEX3FSUNPROC __glewReplacementCodeuiColor4fNormal3fVertex3fSUN;
+GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUICOLOR4FNORMAL3FVERTEX3FVSUNPROC __glewReplacementCodeuiColor4fNormal3fVertex3fvSUN;
+GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUICOLOR4UBVERTEX3FSUNPROC __glewReplacementCodeuiColor4ubVertex3fSUN;
+GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUICOLOR4UBVERTEX3FVSUNPROC __glewReplacementCodeuiColor4ubVertex3fvSUN;
+GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUINORMAL3FVERTEX3FSUNPROC __glewReplacementCodeuiNormal3fVertex3fSUN;
+GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUINORMAL3FVERTEX3FVSUNPROC __glewReplacementCodeuiNormal3fVertex3fvSUN;
+GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUITEXCOORD2FCOLOR4FNORMAL3FVERTEX3FSUNPROC __glewReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fSUN;
+GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUITEXCOORD2FCOLOR4FNORMAL3FVERTEX3FVSUNPROC __glewReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fvSUN;
+GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUITEXCOORD2FNORMAL3FVERTEX3FSUNPROC __glewReplacementCodeuiTexCoord2fNormal3fVertex3fSUN;
+GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUITEXCOORD2FNORMAL3FVERTEX3FVSUNPROC __glewReplacementCodeuiTexCoord2fNormal3fVertex3fvSUN;
+GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUITEXCOORD2FVERTEX3FSUNPROC __glewReplacementCodeuiTexCoord2fVertex3fSUN;
+GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUITEXCOORD2FVERTEX3FVSUNPROC __glewReplacementCodeuiTexCoord2fVertex3fvSUN;
+GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUIVERTEX3FSUNPROC __glewReplacementCodeuiVertex3fSUN;
+GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUIVERTEX3FVSUNPROC __glewReplacementCodeuiVertex3fvSUN;
+GLEW_FUN_EXPORT PFNGLTEXCOORD2FCOLOR3FVERTEX3FSUNPROC __glewTexCoord2fColor3fVertex3fSUN;
+GLEW_FUN_EXPORT PFNGLTEXCOORD2FCOLOR3FVERTEX3FVSUNPROC __glewTexCoord2fColor3fVertex3fvSUN;
+GLEW_FUN_EXPORT PFNGLTEXCOORD2FCOLOR4FNORMAL3FVERTEX3FSUNPROC __glewTexCoord2fColor4fNormal3fVertex3fSUN;
+GLEW_FUN_EXPORT PFNGLTEXCOORD2FCOLOR4FNORMAL3FVERTEX3FVSUNPROC __glewTexCoord2fColor4fNormal3fVertex3fvSUN;
+GLEW_FUN_EXPORT PFNGLTEXCOORD2FCOLOR4UBVERTEX3FSUNPROC __glewTexCoord2fColor4ubVertex3fSUN;
+GLEW_FUN_EXPORT PFNGLTEXCOORD2FCOLOR4UBVERTEX3FVSUNPROC __glewTexCoord2fColor4ubVertex3fvSUN;
+GLEW_FUN_EXPORT PFNGLTEXCOORD2FNORMAL3FVERTEX3FSUNPROC __glewTexCoord2fNormal3fVertex3fSUN;
+GLEW_FUN_EXPORT PFNGLTEXCOORD2FNORMAL3FVERTEX3FVSUNPROC __glewTexCoord2fNormal3fVertex3fvSUN;
+GLEW_FUN_EXPORT PFNGLTEXCOORD2FVERTEX3FSUNPROC __glewTexCoord2fVertex3fSUN;
+GLEW_FUN_EXPORT PFNGLTEXCOORD2FVERTEX3FVSUNPROC __glewTexCoord2fVertex3fvSUN;
+GLEW_FUN_EXPORT PFNGLTEXCOORD4FCOLOR4FNORMAL3FVERTEX4FSUNPROC __glewTexCoord4fColor4fNormal3fVertex4fSUN;
+GLEW_FUN_EXPORT PFNGLTEXCOORD4FCOLOR4FNORMAL3FVERTEX4FVSUNPROC __glewTexCoord4fColor4fNormal3fVertex4fvSUN;
+GLEW_FUN_EXPORT PFNGLTEXCOORD4FVERTEX4FSUNPROC __glewTexCoord4fVertex4fSUN;
+GLEW_FUN_EXPORT PFNGLTEXCOORD4FVERTEX4FVSUNPROC __glewTexCoord4fVertex4fvSUN;
+
+GLEW_FUN_EXPORT PFNGLADDSWAPHINTRECTWINPROC __glewAddSwapHintRectWIN;
+
+#if !defined(GLEW_NO_ES)
+
+
+GLEW_FUN_EXPORT PFNGLALPHAFUNCXPROC __glewAlphaFuncx;
+GLEW_FUN_EXPORT PFNGLCLEARCOLORXPROC __glewClearColorx;
+GLEW_FUN_EXPORT PFNGLCLEARDEPTHXPROC __glewClearDepthx;
+GLEW_FUN_EXPORT PFNGLCOLOR4XPROC __glewColor4x;
+GLEW_FUN_EXPORT PFNGLDEPTHRANGEXPROC __glewDepthRangex;
+GLEW_FUN_EXPORT PFNGLFOGXPROC __glewFogx;
+GLEW_FUN_EXPORT PFNGLFOGXVPROC __glewFogxv;
+GLEW_FUN_EXPORT PFNGLFRUSTUMFPROC __glewFrustumf;
+GLEW_FUN_EXPORT PFNGLFRUSTUMXPROC __glewFrustumx;
+GLEW_FUN_EXPORT PFNGLLIGHTMODELXPROC __glewLightModelx;
+GLEW_FUN_EXPORT PFNGLLIGHTMODELXVPROC __glewLightModelxv;
+GLEW_FUN_EXPORT PFNGLLIGHTXPROC __glewLightx;
+GLEW_FUN_EXPORT PFNGLLIGHTXVPROC __glewLightxv;
+GLEW_FUN_EXPORT PFNGLLINEWIDTHXPROC __glewLineWidthx;
+GLEW_FUN_EXPORT PFNGLLOADMATRIXXPROC __glewLoadMatrixx;
+GLEW_FUN_EXPORT PFNGLMATERIALXPROC __glewMaterialx;
+GLEW_FUN_EXPORT PFNGLMATERIALXVPROC __glewMaterialxv;
+GLEW_FUN_EXPORT PFNGLMULTMATRIXXPROC __glewMultMatrixx;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD4XPROC __glewMultiTexCoord4x;
+GLEW_FUN_EXPORT PFNGLNORMAL3XPROC __glewNormal3x;
+GLEW_FUN_EXPORT PFNGLORTHOFPROC __glewOrthof;
+GLEW_FUN_EXPORT PFNGLORTHOXPROC __glewOrthox;
+GLEW_FUN_EXPORT PFNGLPOINTSIZEXPROC __glewPointSizex;
+GLEW_FUN_EXPORT PFNGLPOLYGONOFFSETXPROC __glewPolygonOffsetx;
+GLEW_FUN_EXPORT PFNGLROTATEXPROC __glewRotatex;
+GLEW_FUN_EXPORT PFNGLSAMPLECOVERAGEXPROC __glewSampleCoveragex;
+GLEW_FUN_EXPORT PFNGLSCALEXPROC __glewScalex;
+GLEW_FUN_EXPORT PFNGLTEXENVXPROC __glewTexEnvx;
+GLEW_FUN_EXPORT PFNGLTEXENVXVPROC __glewTexEnvxv;
+GLEW_FUN_EXPORT PFNGLTEXPARAMETERXPROC __glewTexParameterx;
+GLEW_FUN_EXPORT PFNGLTRANSLATEXPROC __glewTranslatex;
+
+GLEW_FUN_EXPORT PFNGLCLIPPLANEXPROC __glewClipPlanex;
+GLEW_FUN_EXPORT PFNGLGETCLIPPLANEXPROC __glewGetClipPlanex;
+GLEW_FUN_EXPORT PFNGLGETFIXEDVPROC __glewGetFixedv;
+GLEW_FUN_EXPORT PFNGLGETLIGHTXVPROC __glewGetLightxv;
+GLEW_FUN_EXPORT PFNGLGETMATERIALXVPROC __glewGetMaterialxv;
+GLEW_FUN_EXPORT PFNGLGETTEXENVXVPROC __glewGetTexEnvxv;
+GLEW_FUN_EXPORT PFNGLGETTEXPARAMETERXVPROC __glewGetTexParameterxv;
+GLEW_FUN_EXPORT PFNGLPOINTPARAMETERXPROC __glewPointParameterx;
+GLEW_FUN_EXPORT PFNGLPOINTPARAMETERXVPROC __glewPointParameterxv;
+GLEW_FUN_EXPORT PFNGLTEXPARAMETERXVPROC __glewTexParameterxv;
+
+GLEW_FUN_EXPORT PFNGLCLIPPLANEFPROC __glewClipPlanef;
+GLEW_FUN_EXPORT PFNGLGETCLIPPLANEFPROC __glewGetClipPlanef;
+
+GLEW_FUN_EXPORT PFNGLBLITFRAMEBUFFERANGLEPROC __glewBlitFramebufferANGLE;
+
+GLEW_FUN_EXPORT PFNGLRENDERBUFFERSTORAGEMULTISAMPLEANGLEPROC __glewRenderbufferStorageMultisampleANGLE;
+
+GLEW_FUN_EXPORT PFNGLDRAWARRAYSINSTANCEDANGLEPROC __glewDrawArraysInstancedANGLE;
+GLEW_FUN_EXPORT PFNGLDRAWELEMENTSINSTANCEDANGLEPROC __glewDrawElementsInstancedANGLE;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBDIVISORANGLEPROC __glewVertexAttribDivisorANGLE;
+
+GLEW_FUN_EXPORT PFNGLGETTRANSLATEDSHADERSOURCEANGLEPROC __glewGetTranslatedShaderSourceANGLE;
+
+GLEW_FUN_EXPORT PFNGLCOPYTEXTURELEVELSAPPLEPROC __glewCopyTextureLevelsAPPLE;
+
+GLEW_FUN_EXPORT PFNGLRENDERBUFFERSTORAGEMULTISAMPLEAPPLEPROC __glewRenderbufferStorageMultisampleAPPLE;
+GLEW_FUN_EXPORT PFNGLRESOLVEMULTISAMPLEFRAMEBUFFERAPPLEPROC __glewResolveMultisampleFramebufferAPPLE;
+
+GLEW_FUN_EXPORT PFNGLCLIENTWAITSYNCAPPLEPROC __glewClientWaitSyncAPPLE;
+GLEW_FUN_EXPORT PFNGLDELETESYNCAPPLEPROC __glewDeleteSyncAPPLE;
+GLEW_FUN_EXPORT PFNGLFENCESYNCAPPLEPROC __glewFenceSyncAPPLE;
+GLEW_FUN_EXPORT PFNGLGETINTEGER64VAPPLEPROC __glewGetInteger64vAPPLE;
+GLEW_FUN_EXPORT PFNGLGETSYNCIVAPPLEPROC __glewGetSyncivAPPLE;
+GLEW_FUN_EXPORT PFNGLISSYNCAPPLEPROC __glewIsSyncAPPLE;
+GLEW_FUN_EXPORT PFNGLWAITSYNCAPPLEPROC __glewWaitSyncAPPLE;
+
+GLEW_FUN_EXPORT PFNGLGETOBJECTLABELEXTPROC __glewGetObjectLabelEXT;
+GLEW_FUN_EXPORT PFNGLLABELOBJECTEXTPROC __glewLabelObjectEXT;
+
+GLEW_FUN_EXPORT PFNGLINSERTEVENTMARKEREXTPROC __glewInsertEventMarkerEXT;
+GLEW_FUN_EXPORT PFNGLPUSHGROUPMARKEREXTPROC __glewPushGroupMarkerEXT;
+
+GLEW_FUN_EXPORT PFNGLDISCARDFRAMEBUFFEREXTPROC __glewDiscardFramebufferEXT;
+
+GLEW_FUN_EXPORT PFNGLFLUSHMAPPEDBUFFERRANGEEXTPROC __glewFlushMappedBufferRangeEXT;
+GLEW_FUN_EXPORT PFNGLMAPBUFFERRANGEEXTPROC __glewMapBufferRangeEXT;
+
+GLEW_FUN_EXPORT PFNGLFRAMEBUFFERTEXTURE2DMULTISAMPLEEXTPROC __glewFramebufferTexture2DMultisampleEXT;
+GLEW_FUN_EXPORT PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC __glewRenderbufferStorageMultisampleEXT;
+
+GLEW_FUN_EXPORT PFNGLDRAWBUFFERSINDEXEDEXTPROC __glewDrawBuffersIndexedEXT;
+GLEW_FUN_EXPORT PFNGLGETINTEGERI_VEXTPROC __glewGetIntegeri_vEXT;
+GLEW_FUN_EXPORT PFNGLREADBUFFERINDEXEDEXTPROC __glewReadBufferIndexedEXT;
+
+GLEW_FUN_EXPORT PFNGLBEGINQUERYEXTPROC __glewBeginQueryEXT;
+GLEW_FUN_EXPORT PFNGLDELETEQUERIESEXTPROC __glewDeleteQueriesEXT;
+GLEW_FUN_EXPORT PFNGLENDQUERYEXTPROC __glewEndQueryEXT;
+GLEW_FUN_EXPORT PFNGLGENQUERIESEXTPROC __glewGenQueriesEXT;
+GLEW_FUN_EXPORT PFNGLGETQUERYOBJECTUIVEXTPROC __glewGetQueryObjectuivEXT;
+GLEW_FUN_EXPORT PFNGLGETQUERYIVEXTPROC __glewGetQueryivEXT;
+GLEW_FUN_EXPORT PFNGLISQUERYEXTPROC __glewIsQueryEXT;
+
+GLEW_FUN_EXPORT PFNGLGETNUNIFORMFVEXTPROC __glewGetnUniformfvEXT;
+GLEW_FUN_EXPORT PFNGLGETNUNIFORMIVEXTPROC __glewGetnUniformivEXT;
+GLEW_FUN_EXPORT PFNGLREADNPIXELSEXTPROC __glewReadnPixelsEXT;
+
+GLEW_FUN_EXPORT PFNGLTEXSTORAGE1DEXTPROC __glewTexStorage1DEXT;
+GLEW_FUN_EXPORT PFNGLTEXSTORAGE2DEXTPROC __glewTexStorage2DEXT;
+GLEW_FUN_EXPORT PFNGLTEXSTORAGE3DEXTPROC __glewTexStorage3DEXT;
+GLEW_FUN_EXPORT PFNGLTEXTURESTORAGE1DEXTPROC __glewTextureStorage1DEXT;
+GLEW_FUN_EXPORT PFNGLTEXTURESTORAGE2DEXTPROC __glewTextureStorage2DEXT;
+GLEW_FUN_EXPORT PFNGLTEXTURESTORAGE3DEXTPROC __glewTextureStorage3DEXT;
+
+GLEW_FUN_EXPORT PFNGLFRAMEBUFFERTEXTURE2DMULTISAMPLEIMGPROC __glewFramebufferTexture2DMultisampleIMG;
+GLEW_FUN_EXPORT PFNGLRENDERBUFFERSTORAGEMULTISAMPLEIMGPROC __glewRenderbufferStorageMultisampleIMG;
+
+GLEW_FUN_EXPORT PFNGLCLIPPLANEFIMGPROC __glewClipPlanefIMG;
+
+GLEW_FUN_EXPORT PFNGLSTEREOPARAMETERFNVPROC __glewStereoParameterfNV;
+GLEW_FUN_EXPORT PFNGLSTEREOPARAMETERINVPROC __glewStereoParameteriNV;
+
+GLEW_FUN_EXPORT PFNGLCOVERAGEMASKNVPROC __glewCoverageMaskNV;
+GLEW_FUN_EXPORT PFNGLCOVERAGEOPERATIONNVPROC __glewCoverageOperationNV;
+
+GLEW_FUN_EXPORT PFNGLDRAWBUFFERSNVPROC __glewDrawBuffersNV;
+
+GLEW_FUN_EXPORT PFNGLREADBUFFERNVPROC __glewReadBufferNV;
+
+GLEW_FUN_EXPORT PFNGLCOMPRESSEDTEXIMAGE3DNVPROC __glewCompressedTexImage3DNV;
+GLEW_FUN_EXPORT PFNGLCOMPRESSEDTEXSUBIMAGE3DNVPROC __glewCompressedTexSubImage3DNV;
+GLEW_FUN_EXPORT PFNGLCOPYTEXSUBIMAGE3DNVPROC __glewCopyTexSubImage3DNV;
+GLEW_FUN_EXPORT PFNGLFRAMEBUFFERTEXTURELAYERNVPROC __glewFramebufferTextureLayerNV;
+GLEW_FUN_EXPORT PFNGLTEXIMAGE3DNVPROC __glewTexImage3DNV;
+GLEW_FUN_EXPORT PFNGLTEXSUBIMAGE3DNVPROC __glewTexSubImage3DNV;
+
+GLEW_FUN_EXPORT PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC __glewEGLImageTargetRenderbufferStorageOES;
+GLEW_FUN_EXPORT PFNGLEGLIMAGETARGETTEXTURE2DOESPROC __glewEGLImageTargetTexture2DOES;
+
+GLEW_FUN_EXPORT PFNGLBLENDEQUATIONSEPARATEOESPROC __glewBlendEquationSeparateOES;
+
+GLEW_FUN_EXPORT PFNGLBLENDFUNCSEPARATEOESPROC __glewBlendFuncSeparateOES;
+
+GLEW_FUN_EXPORT PFNGLBLENDEQUATIONOESPROC __glewBlendEquationOES;
+
+GLEW_FUN_EXPORT PFNGLBINDFRAMEBUFFEROESPROC __glewBindFramebufferOES;
+GLEW_FUN_EXPORT PFNGLBINDRENDERBUFFEROESPROC __glewBindRenderbufferOES;
+GLEW_FUN_EXPORT PFNGLCHECKFRAMEBUFFERSTATUSOESPROC __glewCheckFramebufferStatusOES;
+GLEW_FUN_EXPORT PFNGLDELETEFRAMEBUFFERSOESPROC __glewDeleteFramebuffersOES;
+GLEW_FUN_EXPORT PFNGLDELETERENDERBUFFERSOESPROC __glewDeleteRenderbuffersOES;
+GLEW_FUN_EXPORT PFNGLFRAMEBUFFERRENDERBUFFEROESPROC __glewFramebufferRenderbufferOES;
+GLEW_FUN_EXPORT PFNGLFRAMEBUFFERTEXTURE2DOESPROC __glewFramebufferTexture2DOES;
+GLEW_FUN_EXPORT PFNGLGENFRAMEBUFFERSOESPROC __glewGenFramebuffersOES;
+GLEW_FUN_EXPORT PFNGLGENRENDERBUFFERSOESPROC __glewGenRenderbuffersOES;
+GLEW_FUN_EXPORT PFNGLGENERATEMIPMAPOESPROC __glewGenerateMipmapOES;
+GLEW_FUN_EXPORT PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVOESPROC __glewGetFramebufferAttachmentParameterivOES;
+GLEW_FUN_EXPORT PFNGLGETRENDERBUFFERPARAMETERIVOESPROC __glewGetRenderbufferParameterivOES;
+GLEW_FUN_EXPORT PFNGLISFRAMEBUFFEROESPROC __glewIsFramebufferOES;
+GLEW_FUN_EXPORT PFNGLISRENDERBUFFEROESPROC __glewIsRenderbufferOES;
+GLEW_FUN_EXPORT PFNGLRENDERBUFFERSTORAGEOESPROC __glewRenderbufferStorageOES;
+
+GLEW_FUN_EXPORT PFNGLGETPROGRAMBINARYOESPROC __glewGetProgramBinaryOES;
+GLEW_FUN_EXPORT PFNGLPROGRAMBINARYOESPROC __glewProgramBinaryOES;
+
+GLEW_FUN_EXPORT PFNGLGETBUFFERPOINTERVOESPROC __glewGetBufferPointervOES;
+GLEW_FUN_EXPORT PFNGLMAPBUFFEROESPROC __glewMapBufferOES;
+GLEW_FUN_EXPORT PFNGLUNMAPBUFFEROESPROC __glewUnmapBufferOES;
+
+GLEW_FUN_EXPORT PFNGLCURRENTPALETTEMATRIXOESPROC __glewCurrentPaletteMatrixOES;
+GLEW_FUN_EXPORT PFNGLMATRIXINDEXPOINTEROESPROC __glewMatrixIndexPointerOES;
+GLEW_FUN_EXPORT PFNGLWEIGHTPOINTEROESPROC __glewWeightPointerOES;
+
+GLEW_FUN_EXPORT PFNGLPOINTSIZEPOINTEROESPROC __glewPointSizePointerOES;
+
+GLEW_FUN_EXPORT PFNGLCOMPRESSEDTEXIMAGE3DOESPROC __glewCompressedTexImage3DOES;
+GLEW_FUN_EXPORT PFNGLCOMPRESSEDTEXSUBIMAGE3DOESPROC __glewCompressedTexSubImage3DOES;
+GLEW_FUN_EXPORT PFNGLCOPYTEXSUBIMAGE3DOESPROC __glewCopyTexSubImage3DOES;
+GLEW_FUN_EXPORT PFNGLFRAMEBUFFERTEXTURE3DOESPROC __glewFramebufferTexture3DOES;
+GLEW_FUN_EXPORT PFNGLTEXIMAGE3DOESPROC __glewTexImage3DOES;
+GLEW_FUN_EXPORT PFNGLTEXSUBIMAGE3DOESPROC __glewTexSubImage3DOES;
+
+GLEW_FUN_EXPORT PFNGLGETTEXGENFVOESPROC __glewGetTexGenfvOES;
+GLEW_FUN_EXPORT PFNGLGETTEXGENIVOESPROC __glewGetTexGenivOES;
+GLEW_FUN_EXPORT PFNGLGETTEXGENXVOESPROC __glewGetTexGenxvOES;
+GLEW_FUN_EXPORT PFNGLTEXGENFOESPROC __glewTexGenfOES;
+GLEW_FUN_EXPORT PFNGLTEXGENFVOESPROC __glewTexGenfvOES;
+GLEW_FUN_EXPORT PFNGLTEXGENIOESPROC __glewTexGeniOES;
+GLEW_FUN_EXPORT PFNGLTEXGENIVOESPROC __glewTexGenivOES;
+GLEW_FUN_EXPORT PFNGLTEXGENXOESPROC __glewTexGenxOES;
+GLEW_FUN_EXPORT PFNGLTEXGENXVOESPROC __glewTexGenxvOES;
+
+GLEW_FUN_EXPORT PFNGLBINDVERTEXARRAYOESPROC __glewBindVertexArrayOES;
+GLEW_FUN_EXPORT PFNGLDELETEVERTEXARRAYSOESPROC __glewDeleteVertexArraysOES;
+GLEW_FUN_EXPORT PFNGLGENVERTEXARRAYSOESPROC __glewGenVertexArraysOES;
+GLEW_FUN_EXPORT PFNGLISVERTEXARRAYOESPROC __glewIsVertexArrayOES;
+
+GLEW_FUN_EXPORT PFNGLALPHAFUNCQCOMPROC __glewAlphaFuncQCOM;
+
+GLEW_FUN_EXPORT PFNGLDISABLEDRIVERCONTROLQCOMPROC __glewDisableDriverControlQCOM;
+GLEW_FUN_EXPORT PFNGLENABLEDRIVERCONTROLQCOMPROC __glewEnableDriverControlQCOM;
+GLEW_FUN_EXPORT PFNGLGETDRIVERCONTROLSTRINGQCOMPROC __glewGetDriverControlStringQCOM;
+GLEW_FUN_EXPORT PFNGLGETDRIVERCONTROLSQCOMPROC __glewGetDriverControlsQCOM;
+
+GLEW_FUN_EXPORT PFNGLEXTGETBUFFERPOINTERVQCOMPROC __glewExtGetBufferPointervQCOM;
+GLEW_FUN_EXPORT PFNGLEXTGETBUFFERSQCOMPROC __glewExtGetBuffersQCOM;
+GLEW_FUN_EXPORT PFNGLEXTGETFRAMEBUFFERSQCOMPROC __glewExtGetFramebuffersQCOM;
+GLEW_FUN_EXPORT PFNGLEXTGETRENDERBUFFERSQCOMPROC __glewExtGetRenderbuffersQCOM;
+GLEW_FUN_EXPORT PFNGLEXTGETTEXLEVELPARAMETERIVQCOMPROC __glewExtGetTexLevelParameterivQCOM;
+GLEW_FUN_EXPORT PFNGLEXTGETTEXSUBIMAGEQCOMPROC __glewExtGetTexSubImageQCOM;
+GLEW_FUN_EXPORT PFNGLEXTGETTEXTURESQCOMPROC __glewExtGetTexturesQCOM;
+GLEW_FUN_EXPORT PFNGLEXTTEXOBJECTSTATEOVERRIDEIQCOMPROC __glewExtTexObjectStateOverrideiQCOM;
+
+GLEW_FUN_EXPORT PFNGLEXTGETPROGRAMBINARYSOURCEQCOMPROC __glewExtGetProgramBinarySourceQCOM;
+GLEW_FUN_EXPORT PFNGLEXTGETPROGRAMSQCOMPROC __glewExtGetProgramsQCOM;
+GLEW_FUN_EXPORT PFNGLEXTGETSHADERSQCOMPROC __glewExtGetShadersQCOM;
+GLEW_FUN_EXPORT PFNGLEXTISPROGRAMBINARYQCOMPROC __glewExtIsProgramBinaryQCOM;
+
+GLEW_FUN_EXPORT PFNGLENDTILINGQCOMPROC __glewEndTilingQCOM;
+GLEW_FUN_EXPORT PFNGLSTARTTILINGQCOMPROC __glewStartTilingQCOM;
+
+GLEW_FUN_EXPORT PFNGLMULTIDRAWARRAYSSUNPROC __glewMultiDrawArraysSUN;
+GLEW_FUN_EXPORT PFNGLMULTIDRAWELEMENTSSUNPROC __glewMultiDrawElementsSUN;
+#endif /* !(GLEW_NO_ES) */
+
+
+#if defined(GLEW_MX) && !defined(_WIN32)
+struct GLEWContextStruct
+{
+#endif /* GLEW_MX */
+
+GLEW_VAR_EXPORT GLboolean __GLEW_VERSION_1_1;
+GLEW_VAR_EXPORT GLboolean __GLEW_VERSION_1_2;
+GLEW_VAR_EXPORT GLboolean __GLEW_VERSION_1_2_1;
+GLEW_VAR_EXPORT GLboolean __GLEW_VERSION_1_3;
+GLEW_VAR_EXPORT GLboolean __GLEW_VERSION_1_4;
+GLEW_VAR_EXPORT GLboolean __GLEW_VERSION_1_5;
+GLEW_VAR_EXPORT GLboolean __GLEW_VERSION_2_0;
+GLEW_VAR_EXPORT GLboolean __GLEW_VERSION_2_1;
+GLEW_VAR_EXPORT GLboolean __GLEW_VERSION_3_0;
+GLEW_VAR_EXPORT GLboolean __GLEW_VERSION_3_1;
+GLEW_VAR_EXPORT GLboolean __GLEW_VERSION_3_2;
+GLEW_VAR_EXPORT GLboolean __GLEW_VERSION_3_3;
+GLEW_VAR_EXPORT GLboolean __GLEW_VERSION_4_0;
+GLEW_VAR_EXPORT GLboolean __GLEW_VERSION_4_1;
+GLEW_VAR_EXPORT GLboolean __GLEW_VERSION_4_2;
+GLEW_VAR_EXPORT GLboolean __GLEW_3DFX_multisample;
+GLEW_VAR_EXPORT GLboolean __GLEW_3DFX_tbuffer;
+GLEW_VAR_EXPORT GLboolean __GLEW_3DFX_texture_compression_FXT1;
+GLEW_VAR_EXPORT GLboolean __GLEW_AMD_blend_minmax_factor;
+GLEW_VAR_EXPORT GLboolean __GLEW_AMD_conservative_depth;
+GLEW_VAR_EXPORT GLboolean __GLEW_AMD_debug_output;
+GLEW_VAR_EXPORT GLboolean __GLEW_AMD_depth_clamp_separate;
+GLEW_VAR_EXPORT GLboolean __GLEW_AMD_draw_buffers_blend;
+GLEW_VAR_EXPORT GLboolean __GLEW_AMD_multi_draw_indirect;
+GLEW_VAR_EXPORT GLboolean __GLEW_AMD_name_gen_delete;
+GLEW_VAR_EXPORT GLboolean __GLEW_AMD_performance_monitor;
+GLEW_VAR_EXPORT GLboolean __GLEW_AMD_pinned_memory;
+GLEW_VAR_EXPORT GLboolean __GLEW_AMD_query_buffer_object;
+GLEW_VAR_EXPORT GLboolean __GLEW_AMD_sample_positions;
+GLEW_VAR_EXPORT GLboolean __GLEW_AMD_seamless_cubemap_per_texture;
+GLEW_VAR_EXPORT GLboolean __GLEW_AMD_shader_stencil_export;
+GLEW_VAR_EXPORT GLboolean __GLEW_AMD_shader_trinary_minmax;
+GLEW_VAR_EXPORT GLboolean __GLEW_AMD_sparse_texture;
+GLEW_VAR_EXPORT GLboolean __GLEW_AMD_stencil_operation_extended;
+GLEW_VAR_EXPORT GLboolean __GLEW_AMD_texture_texture4;
+GLEW_VAR_EXPORT GLboolean __GLEW_AMD_transform_feedback3_lines_triangles;
+GLEW_VAR_EXPORT GLboolean __GLEW_AMD_vertex_shader_layer;
+GLEW_VAR_EXPORT GLboolean __GLEW_AMD_vertex_shader_tessellator;
+GLEW_VAR_EXPORT GLboolean __GLEW_AMD_vertex_shader_viewport_index;
+GLEW_VAR_EXPORT GLboolean __GLEW_APPLE_aux_depth_stencil;
+GLEW_VAR_EXPORT GLboolean __GLEW_APPLE_client_storage;
+GLEW_VAR_EXPORT GLboolean __GLEW_APPLE_element_array;
+GLEW_VAR_EXPORT GLboolean __GLEW_APPLE_fence;
+GLEW_VAR_EXPORT GLboolean __GLEW_APPLE_float_pixels;
+GLEW_VAR_EXPORT GLboolean __GLEW_APPLE_flush_buffer_range;
+GLEW_VAR_EXPORT GLboolean __GLEW_APPLE_object_purgeable;
+GLEW_VAR_EXPORT GLboolean __GLEW_APPLE_pixel_buffer;
+GLEW_VAR_EXPORT GLboolean __GLEW_APPLE_rgb_422;
+GLEW_VAR_EXPORT GLboolean __GLEW_APPLE_row_bytes;
+GLEW_VAR_EXPORT GLboolean __GLEW_APPLE_specular_vector;
+GLEW_VAR_EXPORT GLboolean __GLEW_APPLE_texture_range;
+GLEW_VAR_EXPORT GLboolean __GLEW_APPLE_transform_hint;
+GLEW_VAR_EXPORT GLboolean __GLEW_APPLE_vertex_array_object;
+GLEW_VAR_EXPORT GLboolean __GLEW_APPLE_vertex_array_range;
+GLEW_VAR_EXPORT GLboolean __GLEW_APPLE_vertex_program_evaluators;
+GLEW_VAR_EXPORT GLboolean __GLEW_APPLE_ycbcr_422;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_ES2_compatibility;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_ES3_compatibility;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_arrays_of_arrays;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_base_instance;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_blend_func_extended;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_cl_event;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_clear_buffer_object;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_color_buffer_float;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_compatibility;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_compressed_texture_pixel_storage;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_compute_shader;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_conservative_depth;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_copy_buffer;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_copy_image;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_debug_output;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_depth_buffer_float;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_depth_clamp;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_depth_texture;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_draw_buffers;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_draw_buffers_blend;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_draw_elements_base_vertex;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_draw_indirect;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_draw_instanced;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_explicit_attrib_location;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_explicit_uniform_location;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_fragment_coord_conventions;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_fragment_layer_viewport;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_fragment_program;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_fragment_program_shadow;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_fragment_shader;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_framebuffer_no_attachments;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_framebuffer_object;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_framebuffer_sRGB;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_geometry_shader4;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_get_program_binary;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_gpu_shader5;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_gpu_shader_fp64;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_half_float_pixel;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_half_float_vertex;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_imaging;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_instanced_arrays;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_internalformat_query;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_internalformat_query2;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_invalidate_subdata;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_map_buffer_alignment;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_map_buffer_range;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_matrix_palette;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_multi_draw_indirect;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_multisample;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_multitexture;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_occlusion_query;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_occlusion_query2;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_pixel_buffer_object;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_point_parameters;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_point_sprite;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_program_interface_query;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_provoking_vertex;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_robust_buffer_access_behavior;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_robustness;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_robustness_application_isolation;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_robustness_share_group_isolation;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_sample_shading;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_sampler_objects;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_seamless_cube_map;
+#if 0 // NOTE jwilkins: there is an inconsistency between the ES and Non-ES versions of this extension??
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_separate_shader_objects;
+#endif
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_shader_atomic_counters;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_shader_bit_encoding;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_shader_image_load_store;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_shader_image_size;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_shader_objects;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_shader_precision;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_shader_stencil_export;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_shader_storage_buffer_object;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_shader_subroutine;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_shader_texture_lod;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_shading_language_100;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_shading_language_420pack;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_shading_language_include;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_shading_language_packing;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_shadow;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_shadow_ambient;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_stencil_texturing;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_sync;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_tessellation_shader;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_border_clamp;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_buffer_object;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_buffer_object_rgb32;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_buffer_range;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_compression;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_compression_bptc;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_compression_rgtc;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_cube_map;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_cube_map_array;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_env_add;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_env_combine;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_env_crossbar;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_env_dot3;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_float;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_gather;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_mirrored_repeat;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_multisample;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_non_power_of_two;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_query_levels;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_query_lod;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_rectangle;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_rg;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_rgb10_a2ui;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_storage;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_storage_multisample;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_swizzle;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_view;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_timer_query;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_transform_feedback2;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_transform_feedback3;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_transform_feedback_instanced;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_transpose_matrix;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_uniform_buffer_object;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_vertex_array_bgra;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_vertex_array_object;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_vertex_attrib_64bit;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_vertex_attrib_binding;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_vertex_blend;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_vertex_buffer_object;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_vertex_program;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_vertex_shader;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_vertex_type_2_10_10_10_rev;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_viewport_array;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_window_pos;
+GLEW_VAR_EXPORT GLboolean __GLEW_ATIX_point_sprites;
+GLEW_VAR_EXPORT GLboolean __GLEW_ATIX_texture_env_combine3;
+GLEW_VAR_EXPORT GLboolean __GLEW_ATIX_texture_env_route;
+GLEW_VAR_EXPORT GLboolean __GLEW_ATIX_vertex_shader_output_point_size;
+GLEW_VAR_EXPORT GLboolean __GLEW_ATI_draw_buffers;
+GLEW_VAR_EXPORT GLboolean __GLEW_ATI_element_array;
+GLEW_VAR_EXPORT GLboolean __GLEW_ATI_envmap_bumpmap;
+GLEW_VAR_EXPORT GLboolean __GLEW_ATI_fragment_shader;
+GLEW_VAR_EXPORT GLboolean __GLEW_ATI_map_object_buffer;
+GLEW_VAR_EXPORT GLboolean __GLEW_ATI_meminfo;
+GLEW_VAR_EXPORT GLboolean __GLEW_ATI_pn_triangles;
+GLEW_VAR_EXPORT GLboolean __GLEW_ATI_separate_stencil;
+GLEW_VAR_EXPORT GLboolean __GLEW_ATI_shader_texture_lod;
+GLEW_VAR_EXPORT GLboolean __GLEW_ATI_text_fragment_shader;
+GLEW_VAR_EXPORT GLboolean __GLEW_ATI_texture_compression_3dc;
+GLEW_VAR_EXPORT GLboolean __GLEW_ATI_texture_env_combine3;
+GLEW_VAR_EXPORT GLboolean __GLEW_ATI_texture_float;
+GLEW_VAR_EXPORT GLboolean __GLEW_ATI_texture_mirror_once;
+GLEW_VAR_EXPORT GLboolean __GLEW_ATI_vertex_array_object;
+GLEW_VAR_EXPORT GLboolean __GLEW_ATI_vertex_attrib_array_object;
+GLEW_VAR_EXPORT GLboolean __GLEW_ATI_vertex_streams;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_422_pixels;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_Cg_shader;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_abgr;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_bgra;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_bindable_uniform;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_blend_color;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_blend_equation_separate;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_blend_func_separate;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_blend_logic_op;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_blend_minmax;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_blend_subtract;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_clip_volume_hint;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_cmyka;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_color_subtable;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_compiled_vertex_array;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_convolution;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_coordinate_frame;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_copy_texture;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_cull_vertex;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_depth_bounds_test;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_direct_state_access;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_draw_buffers2;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_draw_instanced;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_draw_range_elements;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_fog_coord;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_fragment_lighting;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_framebuffer_blit;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_framebuffer_multisample;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_framebuffer_multisample_blit_scaled;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_framebuffer_object;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_framebuffer_sRGB;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_geometry_shader4;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_gpu_program_parameters;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_gpu_shader4;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_histogram;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_index_array_formats;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_index_func;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_index_material;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_index_texture;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_light_texture;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_misc_attribute;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_multi_draw_arrays;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_multisample;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_packed_depth_stencil;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_packed_float;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_packed_pixels;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_paletted_texture;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_pixel_buffer_object;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_pixel_transform;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_pixel_transform_color_table;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_point_parameters;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_polygon_offset;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_provoking_vertex;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_rescale_normal;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_scene_marker;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_secondary_color;
+#if 0 // NOTE jwilkins: there is an inconsistency between the ES and Non-ES versions of this extension??
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_separate_shader_objects;
+#endif
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_separate_specular_color;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_shader_image_load_store;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_shadow_funcs;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_shared_texture_palette;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_stencil_clear_tag;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_stencil_two_side;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_stencil_wrap;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_subtexture;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture3D;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_array;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_buffer_object;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_compression_dxt1;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_compression_latc;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_compression_rgtc;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_compression_s3tc;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_cube_map;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_edge_clamp;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_env;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_env_add;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_env_combine;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_env_dot3;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_filter_anisotropic;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_integer;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_lod_bias;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_mirror_clamp;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_object;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_perturb_normal;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_rectangle;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_sRGB;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_sRGB_decode;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_shared_exponent;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_snorm;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_swizzle;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_timer_query;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_transform_feedback;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_vertex_array;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_vertex_array_bgra;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_vertex_attrib_64bit;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_vertex_shader;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_vertex_weighting;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_x11_sync_object;
+GLEW_VAR_EXPORT GLboolean __GLEW_GREMEDY_frame_terminator;
+GLEW_VAR_EXPORT GLboolean __GLEW_GREMEDY_string_marker;
+GLEW_VAR_EXPORT GLboolean __GLEW_HP_convolution_border_modes;
+GLEW_VAR_EXPORT GLboolean __GLEW_HP_image_transform;
+GLEW_VAR_EXPORT GLboolean __GLEW_HP_occlusion_test;
+GLEW_VAR_EXPORT GLboolean __GLEW_HP_texture_lighting;
+GLEW_VAR_EXPORT GLboolean __GLEW_IBM_cull_vertex;
+GLEW_VAR_EXPORT GLboolean __GLEW_IBM_multimode_draw_arrays;
+GLEW_VAR_EXPORT GLboolean __GLEW_IBM_rasterpos_clip;
+GLEW_VAR_EXPORT GLboolean __GLEW_IBM_static_data;
+GLEW_VAR_EXPORT GLboolean __GLEW_IBM_texture_mirrored_repeat;
+GLEW_VAR_EXPORT GLboolean __GLEW_IBM_vertex_array_lists;
+GLEW_VAR_EXPORT GLboolean __GLEW_INGR_color_clamp;
+GLEW_VAR_EXPORT GLboolean __GLEW_INGR_interlace_read;
+GLEW_VAR_EXPORT GLboolean __GLEW_INTEL_map_texture;
+GLEW_VAR_EXPORT GLboolean __GLEW_INTEL_parallel_arrays;
+GLEW_VAR_EXPORT GLboolean __GLEW_INTEL_texture_scissor;
+GLEW_VAR_EXPORT GLboolean __GLEW_KHR_debug;
+GLEW_VAR_EXPORT GLboolean __GLEW_KHR_texture_compression_astc_ldr;
+GLEW_VAR_EXPORT GLboolean __GLEW_KTX_buffer_region;
+GLEW_VAR_EXPORT GLboolean __GLEW_MESAX_texture_stack;
+GLEW_VAR_EXPORT GLboolean __GLEW_MESA_pack_invert;
+GLEW_VAR_EXPORT GLboolean __GLEW_MESA_resize_buffers;
+GLEW_VAR_EXPORT GLboolean __GLEW_MESA_window_pos;
+GLEW_VAR_EXPORT GLboolean __GLEW_MESA_ycbcr_texture;
+GLEW_VAR_EXPORT GLboolean __GLEW_NVX_conditional_render;
+GLEW_VAR_EXPORT GLboolean __GLEW_NVX_gpu_memory_info;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_bindless_texture;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_blend_square;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_compute_program5;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_conditional_render;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_copy_depth_to_color;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_copy_image;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_deep_texture3D;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_depth_buffer_float;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_depth_clamp;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_depth_range_unclamped;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_draw_texture;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_evaluators;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_explicit_multisample;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_fence;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_float_buffer;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_fog_distance;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_fragment_program;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_fragment_program2;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_fragment_program4;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_fragment_program_option;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_framebuffer_multisample_coverage;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_geometry_program4;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_geometry_shader4;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_gpu_program4;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_gpu_program5;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_gpu_program_fp64;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_gpu_shader5;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_half_float;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_light_max_exponent;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_multisample_coverage;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_multisample_filter_hint;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_occlusion_query;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_packed_depth_stencil;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_parameter_buffer_object;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_parameter_buffer_object2;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_path_rendering;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_pixel_data_range;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_point_sprite;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_present_video;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_primitive_restart;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_register_combiners;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_register_combiners2;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_shader_atomic_counters;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_shader_atomic_float;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_shader_buffer_load;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_shader_storage_buffer_object;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_tessellation_program5;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_texgen_emboss;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_texgen_reflection;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_texture_barrier;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_texture_compression_vtc;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_texture_env_combine4;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_texture_expand_normal;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_texture_multisample;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_texture_rectangle;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_texture_shader;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_texture_shader2;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_texture_shader3;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_transform_feedback;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_transform_feedback2;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_vdpau_interop;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_vertex_array_range;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_vertex_array_range2;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_vertex_attrib_integer_64bit;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_vertex_buffer_unified_memory;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_vertex_program;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_vertex_program1_1;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_vertex_program2;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_vertex_program2_option;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_vertex_program3;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_vertex_program4;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_video_capture;
+GLEW_VAR_EXPORT GLboolean __GLEW_OES_byte_coordinates;
+GLEW_VAR_EXPORT GLboolean __GLEW_OES_compressed_paletted_texture;
+GLEW_VAR_EXPORT GLboolean __GLEW_OES_read_format;
+GLEW_VAR_EXPORT GLboolean __GLEW_OES_single_precision;
+GLEW_VAR_EXPORT GLboolean __GLEW_OML_interlace;
+GLEW_VAR_EXPORT GLboolean __GLEW_OML_resample;
+GLEW_VAR_EXPORT GLboolean __GLEW_OML_subsample;
+GLEW_VAR_EXPORT GLboolean __GLEW_PGI_misc_hints;
+GLEW_VAR_EXPORT GLboolean __GLEW_PGI_vertex_hints;
+GLEW_VAR_EXPORT GLboolean __GLEW_REND_screen_coordinates;
+GLEW_VAR_EXPORT GLboolean __GLEW_S3_s3tc;
+GLEW_VAR_EXPORT GLboolean __GLEW_SGIS_color_range;
+GLEW_VAR_EXPORT GLboolean __GLEW_SGIS_detail_texture;
+GLEW_VAR_EXPORT GLboolean __GLEW_SGIS_fog_function;
+GLEW_VAR_EXPORT GLboolean __GLEW_SGIS_generate_mipmap;
+GLEW_VAR_EXPORT GLboolean __GLEW_SGIS_multisample;
+GLEW_VAR_EXPORT GLboolean __GLEW_SGIS_pixel_texture;
+GLEW_VAR_EXPORT GLboolean __GLEW_SGIS_point_line_texgen;
+GLEW_VAR_EXPORT GLboolean __GLEW_SGIS_sharpen_texture;
+GLEW_VAR_EXPORT GLboolean __GLEW_SGIS_texture4D;
+GLEW_VAR_EXPORT GLboolean __GLEW_SGIS_texture_border_clamp;
+GLEW_VAR_EXPORT GLboolean __GLEW_SGIS_texture_edge_clamp;
+GLEW_VAR_EXPORT GLboolean __GLEW_SGIS_texture_filter4;
+GLEW_VAR_EXPORT GLboolean __GLEW_SGIS_texture_lod;
+GLEW_VAR_EXPORT GLboolean __GLEW_SGIS_texture_select;
+GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_async;
+GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_async_histogram;
+GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_async_pixel;
+GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_blend_alpha_minmax;
+GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_clipmap;
+GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_convolution_accuracy;
+GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_depth_texture;
+GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_flush_raster;
+GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_fog_offset;
+GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_fog_texture;
+GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_fragment_specular_lighting;
+GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_framezoom;
+GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_interlace;
+GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_ir_instrument1;
+GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_list_priority;
+GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_pixel_texture;
+GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_pixel_texture_bits;
+GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_reference_plane;
+GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_resample;
+GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_shadow;
+GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_shadow_ambient;
+GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_sprite;
+GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_tag_sample_buffer;
+GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_texture_add_env;
+GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_texture_coordinate_clamp;
+GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_texture_lod_bias;
+GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_texture_multi_buffer;
+GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_texture_range;
+GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_texture_scale_bias;
+GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_vertex_preclip;
+GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_vertex_preclip_hint;
+GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_ycrcb;
+GLEW_VAR_EXPORT GLboolean __GLEW_SGI_color_matrix;
+GLEW_VAR_EXPORT GLboolean __GLEW_SGI_color_table;
+GLEW_VAR_EXPORT GLboolean __GLEW_SGI_texture_color_table;
+GLEW_VAR_EXPORT GLboolean __GLEW_SUNX_constant_data;
+GLEW_VAR_EXPORT GLboolean __GLEW_SUN_convolution_border_modes;
+GLEW_VAR_EXPORT GLboolean __GLEW_SUN_global_alpha;
+GLEW_VAR_EXPORT GLboolean __GLEW_SUN_mesh_array;
+GLEW_VAR_EXPORT GLboolean __GLEW_SUN_read_video_pixels;
+GLEW_VAR_EXPORT GLboolean __GLEW_SUN_slice_accum;
+GLEW_VAR_EXPORT GLboolean __GLEW_SUN_triangle_list;
+GLEW_VAR_EXPORT GLboolean __GLEW_SUN_vertex;
+GLEW_VAR_EXPORT GLboolean __GLEW_WIN_phong_shading;
+GLEW_VAR_EXPORT GLboolean __GLEW_WIN_specular_fog;
+GLEW_VAR_EXPORT GLboolean __GLEW_WIN_swap_hint;
+
+#if !defined(GLEW_NO_ES)
+
+GLEW_VAR_EXPORT GLboolean __GLEW_ES_VERSION_1_0;
+GLEW_VAR_EXPORT GLboolean __GLEW_ES_VERSION_CL_1_1;
+GLEW_VAR_EXPORT GLboolean __GLEW_ES_VERSION_CM_1_1;
+GLEW_VAR_EXPORT GLboolean __GLEW_ES_VERSION_2_0;
+GLEW_VAR_EXPORT GLboolean __GLEW_AMD_compressed_3DC_texture;
+GLEW_VAR_EXPORT GLboolean __GLEW_AMD_compressed_ATC_texture;
+GLEW_VAR_EXPORT GLboolean __GLEW_AMD_program_binary_Z400;
+GLEW_VAR_EXPORT GLboolean __GLEW_ANGLE_framebuffer_blit;
+GLEW_VAR_EXPORT GLboolean __GLEW_ANGLE_framebuffer_multisample;
+GLEW_VAR_EXPORT GLboolean __GLEW_ANGLE_instanced_arrays;
+GLEW_VAR_EXPORT GLboolean __GLEW_ANGLE_pack_reverse_row_order;
+GLEW_VAR_EXPORT GLboolean __GLEW_ANGLE_texture_compression_dxt3;
+GLEW_VAR_EXPORT GLboolean __GLEW_ANGLE_texture_compression_dxt5;
+GLEW_VAR_EXPORT GLboolean __GLEW_ANGLE_texture_usage;
+GLEW_VAR_EXPORT GLboolean __GLEW_ANGLE_translated_shader_source;
+GLEW_VAR_EXPORT GLboolean __GLEW_APPLE_copy_texture_levels;
+GLEW_VAR_EXPORT GLboolean __GLEW_APPLE_framebuffer_multisample;
+GLEW_VAR_EXPORT GLboolean __GLEW_APPLE_sync;
+GLEW_VAR_EXPORT GLboolean __GLEW_APPLE_texture_2D_limited_npot;
+GLEW_VAR_EXPORT GLboolean __GLEW_APPLE_texture_format_BGRA8888;
+GLEW_VAR_EXPORT GLboolean __GLEW_APPLE_texture_max_level;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARM_mali_program_binary;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARM_mali_shader_binary;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARM_rgba8;
+GLEW_VAR_EXPORT GLboolean __GLEW_DMP_shader_binary;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_color_buffer_half_float;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_debug_label;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_debug_marker;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_discard_framebuffer;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_frag_depth;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_map_buffer_range;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_multisampled_render_to_texture;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_multiview_draw_buffers;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_occlusion_query_boolean;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_read_format_bgra;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_robustness;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_sRGB;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_shader_framebuffer_fetch;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_shader_texture_lod;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_shadow_samplers;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_format_BGRA8888;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_rg;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_storage;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_type_2_10_10_10_REV;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_unpack_subimage;
+GLEW_VAR_EXPORT GLboolean __GLEW_FJ_shader_binary_GCCSO;
+GLEW_VAR_EXPORT GLboolean __GLEW_IMG_multisampled_render_to_texture;
+GLEW_VAR_EXPORT GLboolean __GLEW_IMG_program_binary;
+GLEW_VAR_EXPORT GLboolean __GLEW_IMG_read_format;
+GLEW_VAR_EXPORT GLboolean __GLEW_IMG_shader_binary;
+GLEW_VAR_EXPORT GLboolean __GLEW_IMG_texture_compression_pvrtc;
+GLEW_VAR_EXPORT GLboolean __GLEW_IMG_texture_env_enhanced_fixed_function;
+GLEW_VAR_EXPORT GLboolean __GLEW_IMG_user_clip_plane;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_3dvision_settings;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_EGL_stream_consumer_external;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_bgr;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_coverage_sample;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_depth_nonlinear;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_draw_buffers;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_fbo_color_attachments;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_pack_subimage;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_packed_float;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_packed_float_linear;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_pixel_buffer_object;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_platform_binary;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_read_buffer;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_read_buffer_front;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_read_depth;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_read_depth_stencil;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_read_stencil;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_texture_array;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_texture_compression_latc;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_texture_compression_s3tc;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_texture_compression_s3tc_update;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_texture_npot_2D_mipmap;
+GLEW_VAR_EXPORT GLboolean __GLEW_OES_EGL_image;
+GLEW_VAR_EXPORT GLboolean __GLEW_OES_EGL_image_external;
+GLEW_VAR_EXPORT GLboolean __GLEW_OES_EGL_sync;
+GLEW_VAR_EXPORT GLboolean __GLEW_OES_blend_equation_separate;
+GLEW_VAR_EXPORT GLboolean __GLEW_OES_blend_func_separate;
+GLEW_VAR_EXPORT GLboolean __GLEW_OES_blend_subtract;
+GLEW_VAR_EXPORT GLboolean __GLEW_OES_compressed_ETC1_RGB8_texture;
+GLEW_VAR_EXPORT GLboolean __GLEW_OES_depth24;
+GLEW_VAR_EXPORT GLboolean __GLEW_OES_depth32;
+GLEW_VAR_EXPORT GLboolean __GLEW_OES_depth_texture;
+GLEW_VAR_EXPORT GLboolean __GLEW_OES_depth_texture_cube_map;
+GLEW_VAR_EXPORT GLboolean __GLEW_OES_draw_texture;
+GLEW_VAR_EXPORT GLboolean __GLEW_OES_element_index_uint;
+GLEW_VAR_EXPORT GLboolean __GLEW_OES_extended_matrix_palette;
+GLEW_VAR_EXPORT GLboolean __GLEW_OES_fbo_render_mipmap;
+GLEW_VAR_EXPORT GLboolean __GLEW_OES_fragment_precision_high;
+GLEW_VAR_EXPORT GLboolean __GLEW_OES_framebuffer_object;
+GLEW_VAR_EXPORT GLboolean __GLEW_OES_get_program_binary;
+GLEW_VAR_EXPORT GLboolean __GLEW_OES_mapbuffer;
+GLEW_VAR_EXPORT GLboolean __GLEW_OES_matrix_get;
+GLEW_VAR_EXPORT GLboolean __GLEW_OES_matrix_palette;
+GLEW_VAR_EXPORT GLboolean __GLEW_OES_packed_depth_stencil;
+GLEW_VAR_EXPORT GLboolean __GLEW_OES_point_size_array;
+GLEW_VAR_EXPORT GLboolean __GLEW_OES_point_sprite;
+GLEW_VAR_EXPORT GLboolean __GLEW_OES_required_internalformat;
+GLEW_VAR_EXPORT GLboolean __GLEW_OES_rgb8_rgba8;
+GLEW_VAR_EXPORT GLboolean __GLEW_OES_standard_derivatives;
+GLEW_VAR_EXPORT GLboolean __GLEW_OES_stencil1;
+GLEW_VAR_EXPORT GLboolean __GLEW_OES_stencil4;
+GLEW_VAR_EXPORT GLboolean __GLEW_OES_stencil8;
+GLEW_VAR_EXPORT GLboolean __GLEW_OES_surfaceless_context;
+GLEW_VAR_EXPORT GLboolean __GLEW_OES_texture_3D;
+GLEW_VAR_EXPORT GLboolean __GLEW_OES_texture_cube_map;
+GLEW_VAR_EXPORT GLboolean __GLEW_OES_texture_env_crossbar;
+GLEW_VAR_EXPORT GLboolean __GLEW_OES_texture_mirrored_repeat;
+GLEW_VAR_EXPORT GLboolean __GLEW_OES_texture_npot;
+GLEW_VAR_EXPORT GLboolean __GLEW_OES_vertex_array_object;
+GLEW_VAR_EXPORT GLboolean __GLEW_OES_vertex_half_float;
+GLEW_VAR_EXPORT GLboolean __GLEW_OES_vertex_type_10_10_10_2;
+GLEW_VAR_EXPORT GLboolean __GLEW_QCOM_alpha_test;
+GLEW_VAR_EXPORT GLboolean __GLEW_QCOM_binning_control;
+GLEW_VAR_EXPORT GLboolean __GLEW_QCOM_driver_control;
+GLEW_VAR_EXPORT GLboolean __GLEW_QCOM_extended_get;
+GLEW_VAR_EXPORT GLboolean __GLEW_QCOM_extended_get2;
+GLEW_VAR_EXPORT GLboolean __GLEW_QCOM_perfmon_global_mode;
+GLEW_VAR_EXPORT GLboolean __GLEW_QCOM_tiled_rendering;
+GLEW_VAR_EXPORT GLboolean __GLEW_QCOM_writeonly_rendering;
+GLEW_VAR_EXPORT GLboolean __GLEW_SUN_multi_draw_arrays;
+GLEW_VAR_EXPORT GLboolean __GLEW_VG_KHR_EGL_sync;
+GLEW_VAR_EXPORT GLboolean __GLEW_VIV_shader_binary;
+#endif /* !(GLEW_NO_ES) */
+
+
+#ifdef GLEW_MX
+}; /* GLEWContextStruct */
+#endif /* GLEW_MX */
+
+#endif /* GLEW_ES_ONLY */
+
+/* ------------------------------------------------------------------------- */
+
+/* error codes */
+#define GLEW_OK 0
+#define GLEW_NO_ERROR 0
+#define GLEW_ERROR_NO_GL_VERSION 1 /* missing GL version */
+#define GLEW_ERROR_GL_VERSION_10_ONLY 2 /* Need at least OpenGL 1.1 */
+#define GLEW_ERROR_GLX_VERSION_11_ONLY 3 /* Need at least GLX 1.2 */
+#define GLEW_ERROR_NOT_GLES_VERSION 4 /* Need to be OpenGL ES version */
+#define GLEW_ERROR_GLES_VERSION 5 /* Need to be desktop OpenGL version */
+#define GLEW_ERROR_NO_EGL_VERSION 6 /* missing EGL version */
+#define GLEW_ERROR_EGL_VERSION_10_ONLY 7 /* need at least EGL 1.1 */
+
+/* string codes */
+#define GLEW_VERSION 1
+#define GLEW_VERSION_MAJOR 2
+#define GLEW_VERSION_MINOR 3
+#define GLEW_VERSION_MICRO 4
+
+/* API */
+#ifdef GLEW_MX
+
+typedef struct GLEWContextStruct GLEWContext;
+GLEWAPI GLenum glewContextInit (GLEWContext* ctx);
+GLEWAPI GLboolean glewContextIsSupported (const GLEWContext* ctx, const char* name);
+
+#define glewInit() glewContextInit(glewGetContext())
+#define glewIsSupported(x) glewContextIsSupported(glewGetContext(), x)
+#define glewIsExtensionSupported(x) glewIsSupported(x)
+
+#define GLEW_GET_VAR(x) (*(const GLboolean*)&(glewGetContext()->x))
+#ifdef _WIN32
+# define GLEW_GET_FUN(x) glewGetContext()->x
+#else
+# define GLEW_GET_FUN(x) x
+#endif
+
+#else /* GLEW_MX */
+
+GLEWAPI GLenum glewInit ();
+GLEWAPI GLboolean glewIsSupported (const char* name);
+#define glewIsExtensionSupported(x) glewIsSupported(x)
+
+#define GLEW_GET_VAR(x) (*(const GLboolean*)&x)
+#define GLEW_GET_FUN(x) x
+
+#endif /* GLEW_MX */
+
+GLEWAPI GLboolean glewExperimental;
+GLEWAPI GLboolean glewGetExtension (const char* name);
+GLEWAPI const GLubyte* glewGetErrorString (GLenum error);
+GLEWAPI const GLubyte* glewGetString (GLenum name);
+
+#ifdef __cplusplus
+}
+#endif
+
+#ifdef GLEW_APIENTRY_DEFINED
+#undef GLEW_APIENTRY_DEFINED
+#undef APIENTRY
+#undef GLAPIENTRY
+#define GLAPIENTRY
+#endif
+
+#ifdef GLEW_CALLBACK_DEFINED
+#undef GLEW_CALLBACK_DEFINED
+#undef CALLBACK
+#endif
+
+#ifdef GLEW_WINGDIAPI_DEFINED
+#undef GLEW_WINGDIAPI_DEFINED
+#undef WINGDIAPI
+#endif
+
+#undef GLAPI
+/* #undef GLEWAPI */
+
+#endif /* __glew_h__ */
diff --git a/extern/glew-es/include/GL/glxew.h b/extern/glew-es/include/GL/glxew.h
new file mode 100644
index 00000000000..a217bda9b22
--- /dev/null
+++ b/extern/glew-es/include/GL/glxew.h
@@ -0,0 +1,1649 @@
+/*
+** The OpenGL Extension Wrangler Library
+** Copyright (C) 2002-2008, Milan Ikits <milan ikits[]ieee org>
+** Copyright (C) 2002-2008, Marcelo E. Magallon <mmagallo[]debian org>
+** Copyright (C) 2002, Lev Povalahev
+** 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.
+** * The name of the author 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.
+*/
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.0
+ *
+ * Copyright (C) 1999-2007 Brian Paul 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
+ * BRIAN PAUL 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.
+ */
+
+/*
+** Copyright (c) 2007 The Khronos Group Inc.
+**
+** Permission is hereby granted, free of charge, to any person obtaining a
+** copy of this software and/or associated documentation files (the
+** "Materials"), to deal in the Materials without restriction, including
+** without limitation the rights to use, copy, modify, merge, publish,
+** distribute, sublicense, and/or sell copies of the Materials, and to
+** permit persons to whom the Materials are furnished to do so, subject to
+** the following conditions:
+**
+** The above copyright notice and this permission notice shall be included
+** in all copies or substantial portions of the Materials.
+**
+** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+*/
+
+#ifndef __glxew_h__
+#define __glxew_h__
+#define __GLXEW_H__
+
+#ifdef __glxext_h_
+#error glxext.h included before glxew.h
+#endif
+
+#if defined(GLX_H) || defined(__GLX_glx_h__) || defined(__glx_h__)
+#error glx.h included before glxew.h
+#endif
+
+#define __glxext_h_
+
+#define GLX_H
+#define __GLX_glx_h__
+#define __glx_h__
+
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <X11/Xmd.h>
+#include <GL/glew.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* ---------------------------- GLX_VERSION_1_0 --------------------------- */
+
+#ifndef GLX_VERSION_1_0
+#define GLX_VERSION_1_0 1
+
+#define GLX_USE_GL 1
+#define GLX_BUFFER_SIZE 2
+#define GLX_LEVEL 3
+#define GLX_RGBA 4
+#define GLX_DOUBLEBUFFER 5
+#define GLX_STEREO 6
+#define GLX_AUX_BUFFERS 7
+#define GLX_RED_SIZE 8
+#define GLX_GREEN_SIZE 9
+#define GLX_BLUE_SIZE 10
+#define GLX_ALPHA_SIZE 11
+#define GLX_DEPTH_SIZE 12
+#define GLX_STENCIL_SIZE 13
+#define GLX_ACCUM_RED_SIZE 14
+#define GLX_ACCUM_GREEN_SIZE 15
+#define GLX_ACCUM_BLUE_SIZE 16
+#define GLX_ACCUM_ALPHA_SIZE 17
+#define GLX_BAD_SCREEN 1
+#define GLX_BAD_ATTRIBUTE 2
+#define GLX_NO_EXTENSION 3
+#define GLX_BAD_VISUAL 4
+#define GLX_BAD_CONTEXT 5
+#define GLX_BAD_VALUE 6
+#define GLX_BAD_ENUM 7
+
+typedef XID GLXDrawable;
+typedef XID GLXPixmap;
+#ifdef __sun
+typedef struct __glXContextRec *GLXContext;
+#else
+typedef struct __GLXcontextRec *GLXContext;
+#endif
+
+typedef unsigned int GLXVideoDeviceNV;
+
+extern Bool glXQueryExtension (Display *dpy, int *errorBase, int *eventBase);
+extern Bool glXQueryVersion (Display *dpy, int *major, int *minor);
+extern int glXGetConfig (Display *dpy, XVisualInfo *vis, int attrib, int *value);
+extern XVisualInfo* glXChooseVisual (Display *dpy, int screen, int *attribList);
+extern GLXPixmap glXCreateGLXPixmap (Display *dpy, XVisualInfo *vis, Pixmap pixmap);
+extern void glXDestroyGLXPixmap (Display *dpy, GLXPixmap pix);
+extern GLXContext glXCreateContext (Display *dpy, XVisualInfo *vis, GLXContext shareList, Bool direct);
+extern void glXDestroyContext (Display *dpy, GLXContext ctx);
+extern Bool glXIsDirect (Display *dpy, GLXContext ctx);
+extern void glXCopyContext (Display *dpy, GLXContext src, GLXContext dst, GLulong mask);
+extern Bool glXMakeCurrent (Display *dpy, GLXDrawable drawable, GLXContext ctx);
+extern GLXContext glXGetCurrentContext (void);
+extern GLXDrawable glXGetCurrentDrawable (void);
+extern void glXWaitGL (void);
+extern void glXWaitX (void);
+extern void glXSwapBuffers (Display *dpy, GLXDrawable drawable);
+extern void glXUseXFont (Font font, int first, int count, int listBase);
+
+#define GLXEW_VERSION_1_0 GLXEW_GET_VAR(__GLXEW_VERSION_1_0)
+
+#endif /* GLX_VERSION_1_0 */
+
+/* ---------------------------- GLX_VERSION_1_1 --------------------------- */
+
+#ifndef GLX_VERSION_1_1
+#define GLX_VERSION_1_1
+
+#define GLX_VENDOR 0x1
+#define GLX_VERSION 0x2
+#define GLX_EXTENSIONS 0x3
+
+extern const char* glXQueryExtensionsString (Display *dpy, int screen);
+extern const char* glXGetClientString (Display *dpy, int name);
+extern const char* glXQueryServerString (Display *dpy, int screen, int name);
+
+#define GLXEW_VERSION_1_1 GLXEW_GET_VAR(__GLXEW_VERSION_1_1)
+
+#endif /* GLX_VERSION_1_1 */
+
+/* ---------------------------- GLX_VERSION_1_2 ---------------------------- */
+
+#if !defined(GLX_VERSION_1_2)
+#define GLX_VERSION_1_2 1
+
+typedef Display* ( * PFNGLXGETCURRENTDISPLAYPROC) (void);
+
+#define glXGetCurrentDisplay GLXEW_GET_FUN(__glewXGetCurrentDisplay)
+
+#define GLXEW_VERSION_1_2 GLXEW_GET_VAR(__GLXEW_VERSION_1_2)
+
+#endif /* !GLX_VERSION_1_2 */
+
+/* ---------------------------- GLX_VERSION_1_3 ---------------------------- */
+
+#if !defined(GLX_VERSION_1_3)
+#define GLX_VERSION_1_3 1
+
+#define GLX_RGBA_BIT 0x00000001
+#define GLX_FRONT_LEFT_BUFFER_BIT 0x00000001
+#define GLX_WINDOW_BIT 0x00000001
+#define GLX_COLOR_INDEX_BIT 0x00000002
+#define GLX_PIXMAP_BIT 0x00000002
+#define GLX_FRONT_RIGHT_BUFFER_BIT 0x00000002
+#define GLX_BACK_LEFT_BUFFER_BIT 0x00000004
+#define GLX_PBUFFER_BIT 0x00000004
+#define GLX_BACK_RIGHT_BUFFER_BIT 0x00000008
+#define GLX_AUX_BUFFERS_BIT 0x00000010
+#define GLX_CONFIG_CAVEAT 0x20
+#define GLX_DEPTH_BUFFER_BIT 0x00000020
+#define GLX_X_VISUAL_TYPE 0x22
+#define GLX_TRANSPARENT_TYPE 0x23
+#define GLX_TRANSPARENT_INDEX_VALUE 0x24
+#define GLX_TRANSPARENT_RED_VALUE 0x25
+#define GLX_TRANSPARENT_GREEN_VALUE 0x26
+#define GLX_TRANSPARENT_BLUE_VALUE 0x27
+#define GLX_TRANSPARENT_ALPHA_VALUE 0x28
+#define GLX_STENCIL_BUFFER_BIT 0x00000040
+#define GLX_ACCUM_BUFFER_BIT 0x00000080
+#define GLX_NONE 0x8000
+#define GLX_SLOW_CONFIG 0x8001
+#define GLX_TRUE_COLOR 0x8002
+#define GLX_DIRECT_COLOR 0x8003
+#define GLX_PSEUDO_COLOR 0x8004
+#define GLX_STATIC_COLOR 0x8005
+#define GLX_GRAY_SCALE 0x8006
+#define GLX_STATIC_GRAY 0x8007
+#define GLX_TRANSPARENT_RGB 0x8008
+#define GLX_TRANSPARENT_INDEX 0x8009
+#define GLX_VISUAL_ID 0x800B
+#define GLX_SCREEN 0x800C
+#define GLX_NON_CONFORMANT_CONFIG 0x800D
+#define GLX_DRAWABLE_TYPE 0x8010
+#define GLX_RENDER_TYPE 0x8011
+#define GLX_X_RENDERABLE 0x8012
+#define GLX_FBCONFIG_ID 0x8013
+#define GLX_RGBA_TYPE 0x8014
+#define GLX_COLOR_INDEX_TYPE 0x8015
+#define GLX_MAX_PBUFFER_WIDTH 0x8016
+#define GLX_MAX_PBUFFER_HEIGHT 0x8017
+#define GLX_MAX_PBUFFER_PIXELS 0x8018
+#define GLX_PRESERVED_CONTENTS 0x801B
+#define GLX_LARGEST_PBUFFER 0x801C
+#define GLX_WIDTH 0x801D
+#define GLX_HEIGHT 0x801E
+#define GLX_EVENT_MASK 0x801F
+#define GLX_DAMAGED 0x8020
+#define GLX_SAVED 0x8021
+#define GLX_WINDOW 0x8022
+#define GLX_PBUFFER 0x8023
+#define GLX_PBUFFER_HEIGHT 0x8040
+#define GLX_PBUFFER_WIDTH 0x8041
+#define GLX_PBUFFER_CLOBBER_MASK 0x08000000
+#define GLX_DONT_CARE 0xFFFFFFFF
+
+typedef XID GLXFBConfigID;
+typedef XID GLXPbuffer;
+typedef XID GLXWindow;
+typedef struct __GLXFBConfigRec *GLXFBConfig;
+
+typedef struct {
+ int event_type;
+ int draw_type;
+ unsigned long serial;
+ Bool send_event;
+ Display *display;
+ GLXDrawable drawable;
+ unsigned int buffer_mask;
+ unsigned int aux_buffer;
+ int x, y;
+ int width, height;
+ int count;
+} GLXPbufferClobberEvent;
+typedef union __GLXEvent {
+ GLXPbufferClobberEvent glxpbufferclobber;
+ long pad[24];
+} GLXEvent;
+
+typedef GLXFBConfig* ( * PFNGLXCHOOSEFBCONFIGPROC) (Display *dpy, int screen, const int *attrib_list, int *nelements);
+typedef GLXContext ( * PFNGLXCREATENEWCONTEXTPROC) (Display *dpy, GLXFBConfig config, int render_type, GLXContext share_list, Bool direct);
+typedef GLXPbuffer ( * PFNGLXCREATEPBUFFERPROC) (Display *dpy, GLXFBConfig config, const int *attrib_list);
+typedef GLXPixmap ( * PFNGLXCREATEPIXMAPPROC) (Display *dpy, GLXFBConfig config, Pixmap pixmap, const int *attrib_list);
+typedef GLXWindow ( * PFNGLXCREATEWINDOWPROC) (Display *dpy, GLXFBConfig config, Window win, const int *attrib_list);
+typedef void ( * PFNGLXDESTROYPBUFFERPROC) (Display *dpy, GLXPbuffer pbuf);
+typedef void ( * PFNGLXDESTROYPIXMAPPROC) (Display *dpy, GLXPixmap pixmap);
+typedef void ( * PFNGLXDESTROYWINDOWPROC) (Display *dpy, GLXWindow win);
+typedef GLXDrawable ( * PFNGLXGETCURRENTREADDRAWABLEPROC) (void);
+typedef int ( * PFNGLXGETFBCONFIGATTRIBPROC) (Display *dpy, GLXFBConfig config, int attribute, int *value);
+typedef GLXFBConfig* ( * PFNGLXGETFBCONFIGSPROC) (Display *dpy, int screen, int *nelements);
+typedef void ( * PFNGLXGETSELECTEDEVENTPROC) (Display *dpy, GLXDrawable draw, unsigned long *event_mask);
+typedef XVisualInfo* ( * PFNGLXGETVISUALFROMFBCONFIGPROC) (Display *dpy, GLXFBConfig config);
+typedef Bool ( * PFNGLXMAKECONTEXTCURRENTPROC) (Display *display, GLXDrawable draw, GLXDrawable read, GLXContext ctx);
+typedef int ( * PFNGLXQUERYCONTEXTPROC) (Display *dpy, GLXContext ctx, int attribute, int *value);
+typedef void ( * PFNGLXQUERYDRAWABLEPROC) (Display *dpy, GLXDrawable draw, int attribute, unsigned int *value);
+typedef void ( * PFNGLXSELECTEVENTPROC) (Display *dpy, GLXDrawable draw, unsigned long event_mask);
+
+#define glXChooseFBConfig GLXEW_GET_FUN(__glewXChooseFBConfig)
+#define glXCreateNewContext GLXEW_GET_FUN(__glewXCreateNewContext)
+#define glXCreatePbuffer GLXEW_GET_FUN(__glewXCreatePbuffer)
+#define glXCreatePixmap GLXEW_GET_FUN(__glewXCreatePixmap)
+#define glXCreateWindow GLXEW_GET_FUN(__glewXCreateWindow)
+#define glXDestroyPbuffer GLXEW_GET_FUN(__glewXDestroyPbuffer)
+#define glXDestroyPixmap GLXEW_GET_FUN(__glewXDestroyPixmap)
+#define glXDestroyWindow GLXEW_GET_FUN(__glewXDestroyWindow)
+#define glXGetCurrentReadDrawable GLXEW_GET_FUN(__glewXGetCurrentReadDrawable)
+#define glXGetFBConfigAttrib GLXEW_GET_FUN(__glewXGetFBConfigAttrib)
+#define glXGetFBConfigs GLXEW_GET_FUN(__glewXGetFBConfigs)
+#define glXGetSelectedEvent GLXEW_GET_FUN(__glewXGetSelectedEvent)
+#define glXGetVisualFromFBConfig GLXEW_GET_FUN(__glewXGetVisualFromFBConfig)
+#define glXMakeContextCurrent GLXEW_GET_FUN(__glewXMakeContextCurrent)
+#define glXQueryContext GLXEW_GET_FUN(__glewXQueryContext)
+#define glXQueryDrawable GLXEW_GET_FUN(__glewXQueryDrawable)
+#define glXSelectEvent GLXEW_GET_FUN(__glewXSelectEvent)
+
+#define GLXEW_VERSION_1_3 GLXEW_GET_VAR(__GLXEW_VERSION_1_3)
+
+#endif /* !GLX_VERSION_1_3 */
+
+/* ---------------------------- GLX_VERSION_1_4 ---------------------------- */
+
+#if !defined(GLX_VERSION_1_4)
+#define GLX_VERSION_1_4 1
+
+#define GLX_SAMPLE_BUFFERS 100000
+#define GLX_SAMPLES 100001
+
+extern void ( * glXGetProcAddress (const GLubyte *procName)) (void);
+
+#define GLXEW_VERSION_1_4 GLXEW_GET_VAR(__GLXEW_VERSION_1_4)
+
+#endif /* !GLX_VERSION_1_4 */
+
+/* -------------------------- GLX_3DFX_multisample ------------------------- */
+
+#if !defined(GLX_3DFX_multisample)
+#define GLX_3DFX_multisample 1
+
+#define GLX_SAMPLE_BUFFERS_3DFX 0x8050
+#define GLX_SAMPLES_3DFX 0x8051
+
+#define GLXEW_3DFX_multisample GLXEW_GET_VAR(__GLXEW_3DFX_multisample)
+
+#endif /* !GLX_3DFX_multisample */
+
+/* ------------------------ GLX_AMD_gpu_association ------------------------ */
+
+#if !defined(GLX_AMD_gpu_association)
+#define GLX_AMD_gpu_association 1
+
+#define GLX_GPU_VENDOR_AMD 0x1F00
+#define GLX_GPU_RENDERER_STRING_AMD 0x1F01
+#define GLX_GPU_OPENGL_VERSION_STRING_AMD 0x1F02
+#define GLX_GPU_FASTEST_TARGET_GPUS_AMD 0x21A2
+#define GLX_GPU_RAM_AMD 0x21A3
+#define GLX_GPU_CLOCK_AMD 0x21A4
+#define GLX_GPU_NUM_PIPES_AMD 0x21A5
+#define GLX_GPU_NUM_SIMD_AMD 0x21A6
+#define GLX_GPU_NUM_RB_AMD 0x21A7
+#define GLX_GPU_NUM_SPI_AMD 0x21A8
+
+#define GLXEW_AMD_gpu_association GLXEW_GET_VAR(__GLXEW_AMD_gpu_association)
+
+#endif /* !GLX_AMD_gpu_association */
+
+/* ------------------------- GLX_ARB_create_context ------------------------ */
+
+#if !defined(GLX_ARB_create_context)
+#define GLX_ARB_create_context 1
+
+#define GLX_CONTEXT_DEBUG_BIT_ARB 0x0001
+#define GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB 0x0002
+#define GLX_CONTEXT_MAJOR_VERSION_ARB 0x2091
+#define GLX_CONTEXT_MINOR_VERSION_ARB 0x2092
+#define GLX_CONTEXT_FLAGS_ARB 0x2094
+
+typedef GLXContext ( * PFNGLXCREATECONTEXTATTRIBSARBPROC) (Display* dpy, GLXFBConfig config, GLXContext share_context, Bool direct, const int *attrib_list);
+
+#define glXCreateContextAttribsARB GLXEW_GET_FUN(__glewXCreateContextAttribsARB)
+
+#define GLXEW_ARB_create_context GLXEW_GET_VAR(__GLXEW_ARB_create_context)
+
+#endif /* !GLX_ARB_create_context */
+
+/* --------------------- GLX_ARB_create_context_profile -------------------- */
+
+#if !defined(GLX_ARB_create_context_profile)
+#define GLX_ARB_create_context_profile 1
+
+#define GLX_CONTEXT_CORE_PROFILE_BIT_ARB 0x00000001
+#define GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002
+#define GLX_CONTEXT_PROFILE_MASK_ARB 0x9126
+
+#define GLXEW_ARB_create_context_profile GLXEW_GET_VAR(__GLXEW_ARB_create_context_profile)
+
+#endif /* !GLX_ARB_create_context_profile */
+
+/* ------------------- GLX_ARB_create_context_robustness ------------------- */
+
+#if !defined(GLX_ARB_create_context_robustness)
+#define GLX_ARB_create_context_robustness 1
+
+#define GLX_CONTEXT_ROBUST_ACCESS_BIT_ARB 0x00000004
+#define GLX_LOSE_CONTEXT_ON_RESET_ARB 0x8252
+#define GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB 0x8256
+#define GLX_NO_RESET_NOTIFICATION_ARB 0x8261
+
+#define GLXEW_ARB_create_context_robustness GLXEW_GET_VAR(__GLXEW_ARB_create_context_robustness)
+
+#endif /* !GLX_ARB_create_context_robustness */
+
+/* ------------------------- GLX_ARB_fbconfig_float ------------------------ */
+
+#if !defined(GLX_ARB_fbconfig_float)
+#define GLX_ARB_fbconfig_float 1
+
+#define GLX_RGBA_FLOAT_BIT 0x00000004
+#define GLX_RGBA_FLOAT_TYPE 0x20B9
+
+#define GLXEW_ARB_fbconfig_float GLXEW_GET_VAR(__GLXEW_ARB_fbconfig_float)
+
+#endif /* !GLX_ARB_fbconfig_float */
+
+/* ------------------------ GLX_ARB_framebuffer_sRGB ----------------------- */
+
+#if !defined(GLX_ARB_framebuffer_sRGB)
+#define GLX_ARB_framebuffer_sRGB 1
+
+#define GLX_FRAMEBUFFER_SRGB_CAPABLE_ARB 0x20B2
+
+#define GLXEW_ARB_framebuffer_sRGB GLXEW_GET_VAR(__GLXEW_ARB_framebuffer_sRGB)
+
+#endif /* !GLX_ARB_framebuffer_sRGB */
+
+/* ------------------------ GLX_ARB_get_proc_address ----------------------- */
+
+#if !defined(GLX_ARB_get_proc_address)
+#define GLX_ARB_get_proc_address 1
+
+extern void ( * glXGetProcAddressARB (const GLubyte *procName)) (void);
+
+#define GLXEW_ARB_get_proc_address GLXEW_GET_VAR(__GLXEW_ARB_get_proc_address)
+
+#endif /* !GLX_ARB_get_proc_address */
+
+/* -------------------------- GLX_ARB_multisample -------------------------- */
+
+#if !defined(GLX_ARB_multisample)
+#define GLX_ARB_multisample 1
+
+#define GLX_SAMPLE_BUFFERS_ARB 100000
+#define GLX_SAMPLES_ARB 100001
+
+#define GLXEW_ARB_multisample GLXEW_GET_VAR(__GLXEW_ARB_multisample)
+
+#endif /* !GLX_ARB_multisample */
+
+/* ---------------- GLX_ARB_robustness_application_isolation --------------- */
+
+#if !defined(GLX_ARB_robustness_application_isolation)
+#define GLX_ARB_robustness_application_isolation 1
+
+#define GLX_CONTEXT_RESET_ISOLATION_BIT_ARB 0x00000008
+
+#define GLXEW_ARB_robustness_application_isolation GLXEW_GET_VAR(__GLXEW_ARB_robustness_application_isolation)
+
+#endif /* !GLX_ARB_robustness_application_isolation */
+
+/* ---------------- GLX_ARB_robustness_share_group_isolation --------------- */
+
+#if !defined(GLX_ARB_robustness_share_group_isolation)
+#define GLX_ARB_robustness_share_group_isolation 1
+
+#define GLX_CONTEXT_RESET_ISOLATION_BIT_ARB 0x00000008
+
+#define GLXEW_ARB_robustness_share_group_isolation GLXEW_GET_VAR(__GLXEW_ARB_robustness_share_group_isolation)
+
+#endif /* !GLX_ARB_robustness_share_group_isolation */
+
+/* ---------------------- GLX_ARB_vertex_buffer_object --------------------- */
+
+#if !defined(GLX_ARB_vertex_buffer_object)
+#define GLX_ARB_vertex_buffer_object 1
+
+#define GLX_CONTEXT_ALLOW_BUFFER_BYTE_ORDER_MISMATCH_ARB 0x2095
+
+#define GLXEW_ARB_vertex_buffer_object GLXEW_GET_VAR(__GLXEW_ARB_vertex_buffer_object)
+
+#endif /* !GLX_ARB_vertex_buffer_object */
+
+/* ----------------------- GLX_ATI_pixel_format_float ---------------------- */
+
+#if !defined(GLX_ATI_pixel_format_float)
+#define GLX_ATI_pixel_format_float 1
+
+#define GLX_RGBA_FLOAT_ATI_BIT 0x00000100
+
+#define GLXEW_ATI_pixel_format_float GLXEW_GET_VAR(__GLXEW_ATI_pixel_format_float)
+
+#endif /* !GLX_ATI_pixel_format_float */
+
+/* ------------------------- GLX_ATI_render_texture ------------------------ */
+
+#if !defined(GLX_ATI_render_texture)
+#define GLX_ATI_render_texture 1
+
+#define GLX_BIND_TO_TEXTURE_RGB_ATI 0x9800
+#define GLX_BIND_TO_TEXTURE_RGBA_ATI 0x9801
+#define GLX_TEXTURE_FORMAT_ATI 0x9802
+#define GLX_TEXTURE_TARGET_ATI 0x9803
+#define GLX_MIPMAP_TEXTURE_ATI 0x9804
+#define GLX_TEXTURE_RGB_ATI 0x9805
+#define GLX_TEXTURE_RGBA_ATI 0x9806
+#define GLX_NO_TEXTURE_ATI 0x9807
+#define GLX_TEXTURE_CUBE_MAP_ATI 0x9808
+#define GLX_TEXTURE_1D_ATI 0x9809
+#define GLX_TEXTURE_2D_ATI 0x980A
+#define GLX_MIPMAP_LEVEL_ATI 0x980B
+#define GLX_CUBE_MAP_FACE_ATI 0x980C
+#define GLX_TEXTURE_CUBE_MAP_POSITIVE_X_ATI 0x980D
+#define GLX_TEXTURE_CUBE_MAP_NEGATIVE_X_ATI 0x980E
+#define GLX_TEXTURE_CUBE_MAP_POSITIVE_Y_ATI 0x980F
+#define GLX_TEXTURE_CUBE_MAP_NEGATIVE_Y_ATI 0x9810
+#define GLX_TEXTURE_CUBE_MAP_POSITIVE_Z_ATI 0x9811
+#define GLX_TEXTURE_CUBE_MAP_NEGATIVE_Z_ATI 0x9812
+#define GLX_FRONT_LEFT_ATI 0x9813
+#define GLX_FRONT_RIGHT_ATI 0x9814
+#define GLX_BACK_LEFT_ATI 0x9815
+#define GLX_BACK_RIGHT_ATI 0x9816
+#define GLX_AUX0_ATI 0x9817
+#define GLX_AUX1_ATI 0x9818
+#define GLX_AUX2_ATI 0x9819
+#define GLX_AUX3_ATI 0x981A
+#define GLX_AUX4_ATI 0x981B
+#define GLX_AUX5_ATI 0x981C
+#define GLX_AUX6_ATI 0x981D
+#define GLX_AUX7_ATI 0x981E
+#define GLX_AUX8_ATI 0x981F
+#define GLX_AUX9_ATI 0x9820
+#define GLX_BIND_TO_TEXTURE_LUMINANCE_ATI 0x9821
+#define GLX_BIND_TO_TEXTURE_INTENSITY_ATI 0x9822
+
+typedef void ( * PFNGLXBINDTEXIMAGEATIPROC) (Display *dpy, GLXPbuffer pbuf, int buffer);
+typedef void ( * PFNGLXDRAWABLEATTRIBATIPROC) (Display *dpy, GLXDrawable draw, const int *attrib_list);
+typedef void ( * PFNGLXRELEASETEXIMAGEATIPROC) (Display *dpy, GLXPbuffer pbuf, int buffer);
+
+#define glXBindTexImageATI GLXEW_GET_FUN(__glewXBindTexImageATI)
+#define glXDrawableAttribATI GLXEW_GET_FUN(__glewXDrawableAttribATI)
+#define glXReleaseTexImageATI GLXEW_GET_FUN(__glewXReleaseTexImageATI)
+
+#define GLXEW_ATI_render_texture GLXEW_GET_VAR(__GLXEW_ATI_render_texture)
+
+#endif /* !GLX_ATI_render_texture */
+
+/* --------------------------- GLX_EXT_buffer_age -------------------------- */
+
+#if !defined(GLX_EXT_buffer_age)
+#define GLX_EXT_buffer_age 1
+
+#define GLX_BACK_BUFFER_AGE_EXT 0x20F4
+
+#define GLXEW_EXT_buffer_age GLXEW_GET_VAR(__GLXEW_EXT_buffer_age)
+
+#endif /* !GLX_EXT_buffer_age */
+
+/* ------------------- GLX_EXT_create_context_es2_profile ------------------ */
+
+#if !defined(GLX_EXT_create_context_es2_profile)
+#define GLX_EXT_create_context_es2_profile 1
+
+#define GLX_CONTEXT_ES_PROFILE_BIT_EXT 0x00000004
+#define GLX_CONTEXT_ES2_PROFILE_BIT_EXT 0x00000004
+
+#define GLXEW_EXT_create_context_es2_profile GLXEW_GET_VAR(__GLXEW_EXT_create_context_es2_profile)
+
+#endif /* !GLX_EXT_create_context_es2_profile */
+
+/* ------------------- GLX_EXT_create_context_es_profile ------------------- */
+
+#if !defined(GLX_EXT_create_context_es_profile)
+#define GLX_EXT_create_context_es_profile 1
+
+#define GLX_CONTEXT_ES_PROFILE_BIT_EXT 0x00000004
+#define GLX_CONTEXT_ES2_PROFILE_BIT_EXT 0x00000004
+
+#define GLXEW_EXT_create_context_es_profile GLXEW_GET_VAR(__GLXEW_EXT_create_context_es_profile)
+
+#endif /* !GLX_EXT_create_context_es_profile */
+
+/* --------------------- GLX_EXT_fbconfig_packed_float --------------------- */
+
+#if !defined(GLX_EXT_fbconfig_packed_float)
+#define GLX_EXT_fbconfig_packed_float 1
+
+#define GLX_RGBA_UNSIGNED_FLOAT_BIT_EXT 0x00000008
+#define GLX_RGBA_UNSIGNED_FLOAT_TYPE_EXT 0x20B1
+
+#define GLXEW_EXT_fbconfig_packed_float GLXEW_GET_VAR(__GLXEW_EXT_fbconfig_packed_float)
+
+#endif /* !GLX_EXT_fbconfig_packed_float */
+
+/* ------------------------ GLX_EXT_framebuffer_sRGB ----------------------- */
+
+#if !defined(GLX_EXT_framebuffer_sRGB)
+#define GLX_EXT_framebuffer_sRGB 1
+
+#define GLX_FRAMEBUFFER_SRGB_CAPABLE_EXT 0x20B2
+
+#define GLXEW_EXT_framebuffer_sRGB GLXEW_GET_VAR(__GLXEW_EXT_framebuffer_sRGB)
+
+#endif /* !GLX_EXT_framebuffer_sRGB */
+
+/* ------------------------- GLX_EXT_import_context ------------------------ */
+
+#if !defined(GLX_EXT_import_context)
+#define GLX_EXT_import_context 1
+
+#define GLX_SHARE_CONTEXT_EXT 0x800A
+#define GLX_VISUAL_ID_EXT 0x800B
+#define GLX_SCREEN_EXT 0x800C
+
+typedef XID GLXContextID;
+
+typedef void ( * PFNGLXFREECONTEXTEXTPROC) (Display* dpy, GLXContext context);
+typedef GLXContextID ( * PFNGLXGETCONTEXTIDEXTPROC) (const GLXContext context);
+typedef GLXContext ( * PFNGLXIMPORTCONTEXTEXTPROC) (Display* dpy, GLXContextID contextID);
+typedef int ( * PFNGLXQUERYCONTEXTINFOEXTPROC) (Display* dpy, GLXContext context, int attribute,int *value);
+
+#define glXFreeContextEXT GLXEW_GET_FUN(__glewXFreeContextEXT)
+#define glXGetContextIDEXT GLXEW_GET_FUN(__glewXGetContextIDEXT)
+#define glXImportContextEXT GLXEW_GET_FUN(__glewXImportContextEXT)
+#define glXQueryContextInfoEXT GLXEW_GET_FUN(__glewXQueryContextInfoEXT)
+
+#define GLXEW_EXT_import_context GLXEW_GET_VAR(__GLXEW_EXT_import_context)
+
+#endif /* !GLX_EXT_import_context */
+
+/* -------------------------- GLX_EXT_scene_marker ------------------------- */
+
+#if !defined(GLX_EXT_scene_marker)
+#define GLX_EXT_scene_marker 1
+
+#define GLXEW_EXT_scene_marker GLXEW_GET_VAR(__GLXEW_EXT_scene_marker)
+
+#endif /* !GLX_EXT_scene_marker */
+
+/* -------------------------- GLX_EXT_swap_control ------------------------- */
+
+#if !defined(GLX_EXT_swap_control)
+#define GLX_EXT_swap_control 1
+
+#define GLX_SWAP_INTERVAL_EXT 0x20F1
+#define GLX_MAX_SWAP_INTERVAL_EXT 0x20F2
+
+typedef void ( * PFNGLXSWAPINTERVALEXTPROC) (Display* dpy, GLXDrawable drawable, int interval);
+
+#define glXSwapIntervalEXT GLXEW_GET_FUN(__glewXSwapIntervalEXT)
+
+#define GLXEW_EXT_swap_control GLXEW_GET_VAR(__GLXEW_EXT_swap_control)
+
+#endif /* !GLX_EXT_swap_control */
+
+/* ----------------------- GLX_EXT_swap_control_tear ----------------------- */
+
+#if !defined(GLX_EXT_swap_control_tear)
+#define GLX_EXT_swap_control_tear 1
+
+#define GLX_LATE_SWAPS_TEAR_EXT 0x20F3
+
+#define GLXEW_EXT_swap_control_tear GLXEW_GET_VAR(__GLXEW_EXT_swap_control_tear)
+
+#endif /* !GLX_EXT_swap_control_tear */
+
+/* ---------------------- GLX_EXT_texture_from_pixmap ---------------------- */
+
+#if !defined(GLX_EXT_texture_from_pixmap)
+#define GLX_EXT_texture_from_pixmap 1
+
+#define GLX_TEXTURE_1D_BIT_EXT 0x00000001
+#define GLX_TEXTURE_2D_BIT_EXT 0x00000002
+#define GLX_TEXTURE_RECTANGLE_BIT_EXT 0x00000004
+#define GLX_BIND_TO_TEXTURE_RGB_EXT 0x20D0
+#define GLX_BIND_TO_TEXTURE_RGBA_EXT 0x20D1
+#define GLX_BIND_TO_MIPMAP_TEXTURE_EXT 0x20D2
+#define GLX_BIND_TO_TEXTURE_TARGETS_EXT 0x20D3
+#define GLX_Y_INVERTED_EXT 0x20D4
+#define GLX_TEXTURE_FORMAT_EXT 0x20D5
+#define GLX_TEXTURE_TARGET_EXT 0x20D6
+#define GLX_MIPMAP_TEXTURE_EXT 0x20D7
+#define GLX_TEXTURE_FORMAT_NONE_EXT 0x20D8
+#define GLX_TEXTURE_FORMAT_RGB_EXT 0x20D9
+#define GLX_TEXTURE_FORMAT_RGBA_EXT 0x20DA
+#define GLX_TEXTURE_1D_EXT 0x20DB
+#define GLX_TEXTURE_2D_EXT 0x20DC
+#define GLX_TEXTURE_RECTANGLE_EXT 0x20DD
+#define GLX_FRONT_LEFT_EXT 0x20DE
+#define GLX_FRONT_RIGHT_EXT 0x20DF
+#define GLX_BACK_LEFT_EXT 0x20E0
+#define GLX_BACK_RIGHT_EXT 0x20E1
+#define GLX_AUX0_EXT 0x20E2
+#define GLX_AUX1_EXT 0x20E3
+#define GLX_AUX2_EXT 0x20E4
+#define GLX_AUX3_EXT 0x20E5
+#define GLX_AUX4_EXT 0x20E6
+#define GLX_AUX5_EXT 0x20E7
+#define GLX_AUX6_EXT 0x20E8
+#define GLX_AUX7_EXT 0x20E9
+#define GLX_AUX8_EXT 0x20EA
+#define GLX_AUX9_EXT 0x20EB
+
+typedef void ( * PFNGLXBINDTEXIMAGEEXTPROC) (Display* display, GLXDrawable drawable, int buffer, const int *attrib_list);
+typedef void ( * PFNGLXRELEASETEXIMAGEEXTPROC) (Display* display, GLXDrawable drawable, int buffer);
+
+#define glXBindTexImageEXT GLXEW_GET_FUN(__glewXBindTexImageEXT)
+#define glXReleaseTexImageEXT GLXEW_GET_FUN(__glewXReleaseTexImageEXT)
+
+#define GLXEW_EXT_texture_from_pixmap GLXEW_GET_VAR(__GLXEW_EXT_texture_from_pixmap)
+
+#endif /* !GLX_EXT_texture_from_pixmap */
+
+/* -------------------------- GLX_EXT_visual_info -------------------------- */
+
+#if !defined(GLX_EXT_visual_info)
+#define GLX_EXT_visual_info 1
+
+#define GLX_X_VISUAL_TYPE_EXT 0x22
+#define GLX_TRANSPARENT_TYPE_EXT 0x23
+#define GLX_TRANSPARENT_INDEX_VALUE_EXT 0x24
+#define GLX_TRANSPARENT_RED_VALUE_EXT 0x25
+#define GLX_TRANSPARENT_GREEN_VALUE_EXT 0x26
+#define GLX_TRANSPARENT_BLUE_VALUE_EXT 0x27
+#define GLX_TRANSPARENT_ALPHA_VALUE_EXT 0x28
+#define GLX_NONE_EXT 0x8000
+#define GLX_TRUE_COLOR_EXT 0x8002
+#define GLX_DIRECT_COLOR_EXT 0x8003
+#define GLX_PSEUDO_COLOR_EXT 0x8004
+#define GLX_STATIC_COLOR_EXT 0x8005
+#define GLX_GRAY_SCALE_EXT 0x8006
+#define GLX_STATIC_GRAY_EXT 0x8007
+#define GLX_TRANSPARENT_RGB_EXT 0x8008
+#define GLX_TRANSPARENT_INDEX_EXT 0x8009
+
+#define GLXEW_EXT_visual_info GLXEW_GET_VAR(__GLXEW_EXT_visual_info)
+
+#endif /* !GLX_EXT_visual_info */
+
+/* ------------------------- GLX_EXT_visual_rating ------------------------- */
+
+#if !defined(GLX_EXT_visual_rating)
+#define GLX_EXT_visual_rating 1
+
+#define GLX_VISUAL_CAVEAT_EXT 0x20
+#define GLX_SLOW_VISUAL_EXT 0x8001
+#define GLX_NON_CONFORMANT_VISUAL_EXT 0x800D
+
+#define GLXEW_EXT_visual_rating GLXEW_GET_VAR(__GLXEW_EXT_visual_rating)
+
+#endif /* !GLX_EXT_visual_rating */
+
+/* -------------------------- GLX_INTEL_swap_event ------------------------- */
+
+#if !defined(GLX_INTEL_swap_event)
+#define GLX_INTEL_swap_event 1
+
+#define GLX_EXCHANGE_COMPLETE_INTEL 0x8180
+#define GLX_COPY_COMPLETE_INTEL 0x8181
+#define GLX_FLIP_COMPLETE_INTEL 0x8182
+#define GLX_BUFFER_SWAP_COMPLETE_INTEL_MASK 0x04000000
+
+#define GLXEW_INTEL_swap_event GLXEW_GET_VAR(__GLXEW_INTEL_swap_event)
+
+#endif /* !GLX_INTEL_swap_event */
+
+/* -------------------------- GLX_MESA_agp_offset -------------------------- */
+
+#if !defined(GLX_MESA_agp_offset)
+#define GLX_MESA_agp_offset 1
+
+typedef unsigned int ( * PFNGLXGETAGPOFFSETMESAPROC) (const void* pointer);
+
+#define glXGetAGPOffsetMESA GLXEW_GET_FUN(__glewXGetAGPOffsetMESA)
+
+#define GLXEW_MESA_agp_offset GLXEW_GET_VAR(__GLXEW_MESA_agp_offset)
+
+#endif /* !GLX_MESA_agp_offset */
+
+/* ------------------------ GLX_MESA_copy_sub_buffer ----------------------- */
+
+#if !defined(GLX_MESA_copy_sub_buffer)
+#define GLX_MESA_copy_sub_buffer 1
+
+typedef void ( * PFNGLXCOPYSUBBUFFERMESAPROC) (Display* dpy, GLXDrawable drawable, int x, int y, int width, int height);
+
+#define glXCopySubBufferMESA GLXEW_GET_FUN(__glewXCopySubBufferMESA)
+
+#define GLXEW_MESA_copy_sub_buffer GLXEW_GET_VAR(__GLXEW_MESA_copy_sub_buffer)
+
+#endif /* !GLX_MESA_copy_sub_buffer */
+
+/* ------------------------ GLX_MESA_pixmap_colormap ----------------------- */
+
+#if !defined(GLX_MESA_pixmap_colormap)
+#define GLX_MESA_pixmap_colormap 1
+
+typedef GLXPixmap ( * PFNGLXCREATEGLXPIXMAPMESAPROC) (Display* dpy, XVisualInfo *visual, Pixmap pixmap, Colormap cmap);
+
+#define glXCreateGLXPixmapMESA GLXEW_GET_FUN(__glewXCreateGLXPixmapMESA)
+
+#define GLXEW_MESA_pixmap_colormap GLXEW_GET_VAR(__GLXEW_MESA_pixmap_colormap)
+
+#endif /* !GLX_MESA_pixmap_colormap */
+
+/* ------------------------ GLX_MESA_release_buffers ----------------------- */
+
+#if !defined(GLX_MESA_release_buffers)
+#define GLX_MESA_release_buffers 1
+
+typedef Bool ( * PFNGLXRELEASEBUFFERSMESAPROC) (Display* dpy, GLXDrawable d);
+
+#define glXReleaseBuffersMESA GLXEW_GET_FUN(__glewXReleaseBuffersMESA)
+
+#define GLXEW_MESA_release_buffers GLXEW_GET_VAR(__GLXEW_MESA_release_buffers)
+
+#endif /* !GLX_MESA_release_buffers */
+
+/* ------------------------- GLX_MESA_set_3dfx_mode ------------------------ */
+
+#if !defined(GLX_MESA_set_3dfx_mode)
+#define GLX_MESA_set_3dfx_mode 1
+
+#define GLX_3DFX_WINDOW_MODE_MESA 0x1
+#define GLX_3DFX_FULLSCREEN_MODE_MESA 0x2
+
+typedef GLboolean ( * PFNGLXSET3DFXMODEMESAPROC) (GLint mode);
+
+#define glXSet3DfxModeMESA GLXEW_GET_FUN(__glewXSet3DfxModeMESA)
+
+#define GLXEW_MESA_set_3dfx_mode GLXEW_GET_VAR(__GLXEW_MESA_set_3dfx_mode)
+
+#endif /* !GLX_MESA_set_3dfx_mode */
+
+/* ------------------------- GLX_MESA_swap_control ------------------------- */
+
+#if !defined(GLX_MESA_swap_control)
+#define GLX_MESA_swap_control 1
+
+typedef int ( * PFNGLXGETSWAPINTERVALMESAPROC) (void);
+typedef int ( * PFNGLXSWAPINTERVALMESAPROC) (unsigned int interval);
+
+#define glXGetSwapIntervalMESA GLXEW_GET_FUN(__glewXGetSwapIntervalMESA)
+#define glXSwapIntervalMESA GLXEW_GET_FUN(__glewXSwapIntervalMESA)
+
+#define GLXEW_MESA_swap_control GLXEW_GET_VAR(__GLXEW_MESA_swap_control)
+
+#endif /* !GLX_MESA_swap_control */
+
+/* --------------------------- GLX_NV_copy_image --------------------------- */
+
+#if !defined(GLX_NV_copy_image)
+#define GLX_NV_copy_image 1
+
+typedef void ( * PFNGLXCOPYIMAGESUBDATANVPROC) (Display *dpy, GLXContext srcCtx, GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, GLXContext dstCtx, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei width, GLsizei height, GLsizei depth);
+
+#define glXCopyImageSubDataNV GLXEW_GET_FUN(__glewXCopyImageSubDataNV)
+
+#define GLXEW_NV_copy_image GLXEW_GET_VAR(__GLXEW_NV_copy_image)
+
+#endif /* !GLX_NV_copy_image */
+
+/* -------------------------- GLX_NV_float_buffer -------------------------- */
+
+#if !defined(GLX_NV_float_buffer)
+#define GLX_NV_float_buffer 1
+
+#define GLX_FLOAT_COMPONENTS_NV 0x20B0
+
+#define GLXEW_NV_float_buffer GLXEW_GET_VAR(__GLXEW_NV_float_buffer)
+
+#endif /* !GLX_NV_float_buffer */
+
+/* ---------------------- GLX_NV_multisample_coverage ---------------------- */
+
+#if !defined(GLX_NV_multisample_coverage)
+#define GLX_NV_multisample_coverage 1
+
+#define GLX_COLOR_SAMPLES_NV 0x20B3
+#define GLX_COVERAGE_SAMPLES_NV 100001
+
+#define GLXEW_NV_multisample_coverage GLXEW_GET_VAR(__GLXEW_NV_multisample_coverage)
+
+#endif /* !GLX_NV_multisample_coverage */
+
+/* -------------------------- GLX_NV_present_video ------------------------- */
+
+#if !defined(GLX_NV_present_video)
+#define GLX_NV_present_video 1
+
+#define GLX_NUM_VIDEO_SLOTS_NV 0x20F0
+
+typedef int ( * PFNGLXBINDVIDEODEVICENVPROC) (Display* dpy, unsigned int video_slot, unsigned int video_device, const int *attrib_list);
+typedef unsigned int* ( * PFNGLXENUMERATEVIDEODEVICESNVPROC) (Display *dpy, int screen, int *nelements);
+
+#define glXBindVideoDeviceNV GLXEW_GET_FUN(__glewXBindVideoDeviceNV)
+#define glXEnumerateVideoDevicesNV GLXEW_GET_FUN(__glewXEnumerateVideoDevicesNV)
+
+#define GLXEW_NV_present_video GLXEW_GET_VAR(__GLXEW_NV_present_video)
+
+#endif /* !GLX_NV_present_video */
+
+/* --------------------------- GLX_NV_swap_group --------------------------- */
+
+#if !defined(GLX_NV_swap_group)
+#define GLX_NV_swap_group 1
+
+typedef Bool ( * PFNGLXBINDSWAPBARRIERNVPROC) (Display* dpy, GLuint group, GLuint barrier);
+typedef Bool ( * PFNGLXJOINSWAPGROUPNVPROC) (Display* dpy, GLXDrawable drawable, GLuint group);
+typedef Bool ( * PFNGLXQUERYFRAMECOUNTNVPROC) (Display* dpy, int screen, GLuint *count);
+typedef Bool ( * PFNGLXQUERYMAXSWAPGROUPSNVPROC) (Display* dpy, int screen, GLuint *maxGroups, GLuint *maxBarriers);
+typedef Bool ( * PFNGLXQUERYSWAPGROUPNVPROC) (Display* dpy, GLXDrawable drawable, GLuint *group, GLuint *barrier);
+typedef Bool ( * PFNGLXRESETFRAMECOUNTNVPROC) (Display* dpy, int screen);
+
+#define glXBindSwapBarrierNV GLXEW_GET_FUN(__glewXBindSwapBarrierNV)
+#define glXJoinSwapGroupNV GLXEW_GET_FUN(__glewXJoinSwapGroupNV)
+#define glXQueryFrameCountNV GLXEW_GET_FUN(__glewXQueryFrameCountNV)
+#define glXQueryMaxSwapGroupsNV GLXEW_GET_FUN(__glewXQueryMaxSwapGroupsNV)
+#define glXQuerySwapGroupNV GLXEW_GET_FUN(__glewXQuerySwapGroupNV)
+#define glXResetFrameCountNV GLXEW_GET_FUN(__glewXResetFrameCountNV)
+
+#define GLXEW_NV_swap_group GLXEW_GET_VAR(__GLXEW_NV_swap_group)
+
+#endif /* !GLX_NV_swap_group */
+
+/* ----------------------- GLX_NV_vertex_array_range ----------------------- */
+
+#if !defined(GLX_NV_vertex_array_range)
+#define GLX_NV_vertex_array_range 1
+
+typedef void * ( * PFNGLXALLOCATEMEMORYNVPROC) (GLsizei size, GLfloat readFrequency, GLfloat writeFrequency, GLfloat priority);
+typedef void ( * PFNGLXFREEMEMORYNVPROC) (void *pointer);
+
+#define glXAllocateMemoryNV GLXEW_GET_FUN(__glewXAllocateMemoryNV)
+#define glXFreeMemoryNV GLXEW_GET_FUN(__glewXFreeMemoryNV)
+
+#define GLXEW_NV_vertex_array_range GLXEW_GET_VAR(__GLXEW_NV_vertex_array_range)
+
+#endif /* !GLX_NV_vertex_array_range */
+
+/* -------------------------- GLX_NV_video_capture ------------------------- */
+
+#if !defined(GLX_NV_video_capture)
+#define GLX_NV_video_capture 1
+
+#define GLX_DEVICE_ID_NV 0x20CD
+#define GLX_UNIQUE_ID_NV 0x20CE
+#define GLX_NUM_VIDEO_CAPTURE_SLOTS_NV 0x20CF
+
+typedef XID GLXVideoCaptureDeviceNV;
+
+typedef int ( * PFNGLXBINDVIDEOCAPTUREDEVICENVPROC) (Display* dpy, unsigned int video_capture_slot, GLXVideoCaptureDeviceNV device);
+typedef GLXVideoCaptureDeviceNV * ( * PFNGLXENUMERATEVIDEOCAPTUREDEVICESNVPROC) (Display* dpy, int screen, int *nelements);
+typedef void ( * PFNGLXLOCKVIDEOCAPTUREDEVICENVPROC) (Display* dpy, GLXVideoCaptureDeviceNV device);
+typedef int ( * PFNGLXQUERYVIDEOCAPTUREDEVICENVPROC) (Display* dpy, GLXVideoCaptureDeviceNV device, int attribute, int *value);
+typedef void ( * PFNGLXRELEASEVIDEOCAPTUREDEVICENVPROC) (Display* dpy, GLXVideoCaptureDeviceNV device);
+
+#define glXBindVideoCaptureDeviceNV GLXEW_GET_FUN(__glewXBindVideoCaptureDeviceNV)
+#define glXEnumerateVideoCaptureDevicesNV GLXEW_GET_FUN(__glewXEnumerateVideoCaptureDevicesNV)
+#define glXLockVideoCaptureDeviceNV GLXEW_GET_FUN(__glewXLockVideoCaptureDeviceNV)
+#define glXQueryVideoCaptureDeviceNV GLXEW_GET_FUN(__glewXQueryVideoCaptureDeviceNV)
+#define glXReleaseVideoCaptureDeviceNV GLXEW_GET_FUN(__glewXReleaseVideoCaptureDeviceNV)
+
+#define GLXEW_NV_video_capture GLXEW_GET_VAR(__GLXEW_NV_video_capture)
+
+#endif /* !GLX_NV_video_capture */
+
+/* -------------------------- GLX_NV_video_output -------------------------- */
+
+#if !defined(GLX_NV_video_output)
+#define GLX_NV_video_output 1
+
+#define GLX_VIDEO_OUT_COLOR_NV 0x20C3
+#define GLX_VIDEO_OUT_ALPHA_NV 0x20C4
+#define GLX_VIDEO_OUT_DEPTH_NV 0x20C5
+#define GLX_VIDEO_OUT_COLOR_AND_ALPHA_NV 0x20C6
+#define GLX_VIDEO_OUT_COLOR_AND_DEPTH_NV 0x20C7
+#define GLX_VIDEO_OUT_FRAME_NV 0x20C8
+#define GLX_VIDEO_OUT_FIELD_1_NV 0x20C9
+#define GLX_VIDEO_OUT_FIELD_2_NV 0x20CA
+#define GLX_VIDEO_OUT_STACKED_FIELDS_1_2_NV 0x20CB
+#define GLX_VIDEO_OUT_STACKED_FIELDS_2_1_NV 0x20CC
+
+typedef int ( * PFNGLXBINDVIDEOIMAGENVPROC) (Display* dpy, GLXVideoDeviceNV VideoDevice, GLXPbuffer pbuf, int iVideoBuffer);
+typedef int ( * PFNGLXGETVIDEODEVICENVPROC) (Display* dpy, int screen, int numVideoDevices, GLXVideoDeviceNV *pVideoDevice);
+typedef int ( * PFNGLXGETVIDEOINFONVPROC) (Display* dpy, int screen, GLXVideoDeviceNV VideoDevice, unsigned long *pulCounterOutputPbuffer, unsigned long *pulCounterOutputVideo);
+typedef int ( * PFNGLXRELEASEVIDEODEVICENVPROC) (Display* dpy, int screen, GLXVideoDeviceNV VideoDevice);
+typedef int ( * PFNGLXRELEASEVIDEOIMAGENVPROC) (Display* dpy, GLXPbuffer pbuf);
+typedef int ( * PFNGLXSENDPBUFFERTOVIDEONVPROC) (Display* dpy, GLXPbuffer pbuf, int iBufferType, unsigned long *pulCounterPbuffer, GLboolean bBlock);
+
+#define glXBindVideoImageNV GLXEW_GET_FUN(__glewXBindVideoImageNV)
+#define glXGetVideoDeviceNV GLXEW_GET_FUN(__glewXGetVideoDeviceNV)
+#define glXGetVideoInfoNV GLXEW_GET_FUN(__glewXGetVideoInfoNV)
+#define glXReleaseVideoDeviceNV GLXEW_GET_FUN(__glewXReleaseVideoDeviceNV)
+#define glXReleaseVideoImageNV GLXEW_GET_FUN(__glewXReleaseVideoImageNV)
+#define glXSendPbufferToVideoNV GLXEW_GET_FUN(__glewXSendPbufferToVideoNV)
+
+#define GLXEW_NV_video_output GLXEW_GET_VAR(__GLXEW_NV_video_output)
+
+#endif /* !GLX_NV_video_output */
+
+/* -------------------------- GLX_OML_swap_method -------------------------- */
+
+#if !defined(GLX_OML_swap_method)
+#define GLX_OML_swap_method 1
+
+#define GLX_SWAP_METHOD_OML 0x8060
+#define GLX_SWAP_EXCHANGE_OML 0x8061
+#define GLX_SWAP_COPY_OML 0x8062
+#define GLX_SWAP_UNDEFINED_OML 0x8063
+
+#define GLXEW_OML_swap_method GLXEW_GET_VAR(__GLXEW_OML_swap_method)
+
+#endif /* !GLX_OML_swap_method */
+
+/* -------------------------- GLX_OML_sync_control ------------------------- */
+
+#if !defined(GLX_OML_sync_control)
+#define GLX_OML_sync_control 1
+
+typedef Bool ( * PFNGLXGETMSCRATEOMLPROC) (Display* dpy, GLXDrawable drawable, int32_t* numerator, int32_t* denominator);
+typedef Bool ( * PFNGLXGETSYNCVALUESOMLPROC) (Display* dpy, GLXDrawable drawable, int64_t* ust, int64_t* msc, int64_t* sbc);
+typedef int64_t ( * PFNGLXSWAPBUFFERSMSCOMLPROC) (Display* dpy, GLXDrawable drawable, int64_t target_msc, int64_t divisor, int64_t remainder);
+typedef Bool ( * PFNGLXWAITFORMSCOMLPROC) (Display* dpy, GLXDrawable drawable, int64_t target_msc, int64_t divisor, int64_t remainder, int64_t* ust, int64_t* msc, int64_t* sbc);
+typedef Bool ( * PFNGLXWAITFORSBCOMLPROC) (Display* dpy, GLXDrawable drawable, int64_t target_sbc, int64_t* ust, int64_t* msc, int64_t* sbc);
+
+#define glXGetMscRateOML GLXEW_GET_FUN(__glewXGetMscRateOML)
+#define glXGetSyncValuesOML GLXEW_GET_FUN(__glewXGetSyncValuesOML)
+#define glXSwapBuffersMscOML GLXEW_GET_FUN(__glewXSwapBuffersMscOML)
+#define glXWaitForMscOML GLXEW_GET_FUN(__glewXWaitForMscOML)
+#define glXWaitForSbcOML GLXEW_GET_FUN(__glewXWaitForSbcOML)
+
+#define GLXEW_OML_sync_control GLXEW_GET_VAR(__GLXEW_OML_sync_control)
+
+#endif /* !GLX_OML_sync_control */
+
+/* ------------------------ GLX_SGIS_blended_overlay ----------------------- */
+
+#if !defined(GLX_SGIS_blended_overlay)
+#define GLX_SGIS_blended_overlay 1
+
+#define GLX_BLENDED_RGBA_SGIS 0x8025
+
+#define GLXEW_SGIS_blended_overlay GLXEW_GET_VAR(__GLXEW_SGIS_blended_overlay)
+
+#endif /* !GLX_SGIS_blended_overlay */
+
+/* -------------------------- GLX_SGIS_color_range ------------------------- */
+
+#if !defined(GLX_SGIS_color_range)
+#define GLX_SGIS_color_range 1
+
+#define GLX_MIN_RED_SGIS 0
+#define GLX_MAX_GREEN_SGIS 0
+#define GLX_MIN_BLUE_SGIS 0
+#define GLX_MAX_ALPHA_SGIS 0
+#define GLX_MIN_GREEN_SGIS 0
+#define GLX_MIN_ALPHA_SGIS 0
+#define GLX_MAX_RED_SGIS 0
+#define GLX_EXTENDED_RANGE_SGIS 0
+#define GLX_MAX_BLUE_SGIS 0
+
+#define GLXEW_SGIS_color_range GLXEW_GET_VAR(__GLXEW_SGIS_color_range)
+
+#endif /* !GLX_SGIS_color_range */
+
+/* -------------------------- GLX_SGIS_multisample ------------------------- */
+
+#if !defined(GLX_SGIS_multisample)
+#define GLX_SGIS_multisample 1
+
+#define GLX_SAMPLE_BUFFERS_SGIS 100000
+#define GLX_SAMPLES_SGIS 100001
+
+#define GLXEW_SGIS_multisample GLXEW_GET_VAR(__GLXEW_SGIS_multisample)
+
+#endif /* !GLX_SGIS_multisample */
+
+/* ---------------------- GLX_SGIS_shared_multisample ---------------------- */
+
+#if !defined(GLX_SGIS_shared_multisample)
+#define GLX_SGIS_shared_multisample 1
+
+#define GLX_MULTISAMPLE_SUB_RECT_WIDTH_SGIS 0x8026
+#define GLX_MULTISAMPLE_SUB_RECT_HEIGHT_SGIS 0x8027
+
+#define GLXEW_SGIS_shared_multisample GLXEW_GET_VAR(__GLXEW_SGIS_shared_multisample)
+
+#endif /* !GLX_SGIS_shared_multisample */
+
+/* --------------------------- GLX_SGIX_fbconfig --------------------------- */
+
+#if !defined(GLX_SGIX_fbconfig)
+#define GLX_SGIX_fbconfig 1
+
+#define GLX_WINDOW_BIT_SGIX 0x00000001
+#define GLX_RGBA_BIT_SGIX 0x00000001
+#define GLX_PIXMAP_BIT_SGIX 0x00000002
+#define GLX_COLOR_INDEX_BIT_SGIX 0x00000002
+#define GLX_SCREEN_EXT 0x800C
+#define GLX_DRAWABLE_TYPE_SGIX 0x8010
+#define GLX_RENDER_TYPE_SGIX 0x8011
+#define GLX_X_RENDERABLE_SGIX 0x8012
+#define GLX_FBCONFIG_ID_SGIX 0x8013
+#define GLX_RGBA_TYPE_SGIX 0x8014
+#define GLX_COLOR_INDEX_TYPE_SGIX 0x8015
+
+typedef XID GLXFBConfigIDSGIX;
+typedef struct __GLXFBConfigRec *GLXFBConfigSGIX;
+
+typedef GLXFBConfigSGIX* ( * PFNGLXCHOOSEFBCONFIGSGIXPROC) (Display *dpy, int screen, const int *attrib_list, int *nelements);
+typedef GLXContext ( * PFNGLXCREATECONTEXTWITHCONFIGSGIXPROC) (Display* dpy, GLXFBConfig config, int render_type, GLXContext share_list, Bool direct);
+typedef GLXPixmap ( * PFNGLXCREATEGLXPIXMAPWITHCONFIGSGIXPROC) (Display* dpy, GLXFBConfig config, Pixmap pixmap);
+typedef int ( * PFNGLXGETFBCONFIGATTRIBSGIXPROC) (Display* dpy, GLXFBConfigSGIX config, int attribute, int *value);
+typedef GLXFBConfigSGIX ( * PFNGLXGETFBCONFIGFROMVISUALSGIXPROC) (Display* dpy, XVisualInfo *vis);
+typedef XVisualInfo* ( * PFNGLXGETVISUALFROMFBCONFIGSGIXPROC) (Display *dpy, GLXFBConfig config);
+
+#define glXChooseFBConfigSGIX GLXEW_GET_FUN(__glewXChooseFBConfigSGIX)
+#define glXCreateContextWithConfigSGIX GLXEW_GET_FUN(__glewXCreateContextWithConfigSGIX)
+#define glXCreateGLXPixmapWithConfigSGIX GLXEW_GET_FUN(__glewXCreateGLXPixmapWithConfigSGIX)
+#define glXGetFBConfigAttribSGIX GLXEW_GET_FUN(__glewXGetFBConfigAttribSGIX)
+#define glXGetFBConfigFromVisualSGIX GLXEW_GET_FUN(__glewXGetFBConfigFromVisualSGIX)
+#define glXGetVisualFromFBConfigSGIX GLXEW_GET_FUN(__glewXGetVisualFromFBConfigSGIX)
+
+#define GLXEW_SGIX_fbconfig GLXEW_GET_VAR(__GLXEW_SGIX_fbconfig)
+
+#endif /* !GLX_SGIX_fbconfig */
+
+/* --------------------------- GLX_SGIX_hyperpipe -------------------------- */
+
+#if !defined(GLX_SGIX_hyperpipe)
+#define GLX_SGIX_hyperpipe 1
+
+#define GLX_HYPERPIPE_DISPLAY_PIPE_SGIX 0x00000001
+#define GLX_PIPE_RECT_SGIX 0x00000001
+#define GLX_PIPE_RECT_LIMITS_SGIX 0x00000002
+#define GLX_HYPERPIPE_RENDER_PIPE_SGIX 0x00000002
+#define GLX_HYPERPIPE_STEREO_SGIX 0x00000003
+#define GLX_HYPERPIPE_PIXEL_AVERAGE_SGIX 0x00000004
+#define GLX_HYPERPIPE_PIPE_NAME_LENGTH_SGIX 80
+#define GLX_BAD_HYPERPIPE_CONFIG_SGIX 91
+#define GLX_BAD_HYPERPIPE_SGIX 92
+#define GLX_HYPERPIPE_ID_SGIX 0x8030
+
+typedef struct {
+ char pipeName[GLX_HYPERPIPE_PIPE_NAME_LENGTH_SGIX];
+ int networkId;
+} GLXHyperpipeNetworkSGIX;
+typedef struct {
+ char pipeName[GLX_HYPERPIPE_PIPE_NAME_LENGTH_SGIX];
+ int XOrigin;
+ int YOrigin;
+ int maxHeight;
+ int maxWidth;
+} GLXPipeRectLimits;
+typedef struct {
+ char pipeName[GLX_HYPERPIPE_PIPE_NAME_LENGTH_SGIX];
+ int channel;
+ unsigned int participationType;
+ int timeSlice;
+} GLXHyperpipeConfigSGIX;
+typedef struct {
+ char pipeName[GLX_HYPERPIPE_PIPE_NAME_LENGTH_SGIX];
+ int srcXOrigin;
+ int srcYOrigin;
+ int srcWidth;
+ int srcHeight;
+ int destXOrigin;
+ int destYOrigin;
+ int destWidth;
+ int destHeight;
+} GLXPipeRect;
+
+typedef int ( * PFNGLXBINDHYPERPIPESGIXPROC) (Display *dpy, int hpId);
+typedef int ( * PFNGLXDESTROYHYPERPIPECONFIGSGIXPROC) (Display *dpy, int hpId);
+typedef int ( * PFNGLXHYPERPIPEATTRIBSGIXPROC) (Display *dpy, int timeSlice, int attrib, int size, void *attribList);
+typedef int ( * PFNGLXHYPERPIPECONFIGSGIXPROC) (Display *dpy, int networkId, int npipes, GLXHyperpipeConfigSGIX *cfg, int *hpId);
+typedef int ( * PFNGLXQUERYHYPERPIPEATTRIBSGIXPROC) (Display *dpy, int timeSlice, int attrib, int size, void *returnAttribList);
+typedef int ( * PFNGLXQUERYHYPERPIPEBESTATTRIBSGIXPROC) (Display *dpy, int timeSlice, int attrib, int size, void *attribList, void *returnAttribList);
+typedef GLXHyperpipeConfigSGIX * ( * PFNGLXQUERYHYPERPIPECONFIGSGIXPROC) (Display *dpy, int hpId, int *npipes);
+typedef GLXHyperpipeNetworkSGIX * ( * PFNGLXQUERYHYPERPIPENETWORKSGIXPROC) (Display *dpy, int *npipes);
+
+#define glXBindHyperpipeSGIX GLXEW_GET_FUN(__glewXBindHyperpipeSGIX)
+#define glXDestroyHyperpipeConfigSGIX GLXEW_GET_FUN(__glewXDestroyHyperpipeConfigSGIX)
+#define glXHyperpipeAttribSGIX GLXEW_GET_FUN(__glewXHyperpipeAttribSGIX)
+#define glXHyperpipeConfigSGIX GLXEW_GET_FUN(__glewXHyperpipeConfigSGIX)
+#define glXQueryHyperpipeAttribSGIX GLXEW_GET_FUN(__glewXQueryHyperpipeAttribSGIX)
+#define glXQueryHyperpipeBestAttribSGIX GLXEW_GET_FUN(__glewXQueryHyperpipeBestAttribSGIX)
+#define glXQueryHyperpipeConfigSGIX GLXEW_GET_FUN(__glewXQueryHyperpipeConfigSGIX)
+#define glXQueryHyperpipeNetworkSGIX GLXEW_GET_FUN(__glewXQueryHyperpipeNetworkSGIX)
+
+#define GLXEW_SGIX_hyperpipe GLXEW_GET_VAR(__GLXEW_SGIX_hyperpipe)
+
+#endif /* !GLX_SGIX_hyperpipe */
+
+/* ---------------------------- GLX_SGIX_pbuffer --------------------------- */
+
+#if !defined(GLX_SGIX_pbuffer)
+#define GLX_SGIX_pbuffer 1
+
+#define GLX_FRONT_LEFT_BUFFER_BIT_SGIX 0x00000001
+#define GLX_FRONT_RIGHT_BUFFER_BIT_SGIX 0x00000002
+#define GLX_PBUFFER_BIT_SGIX 0x00000004
+#define GLX_BACK_LEFT_BUFFER_BIT_SGIX 0x00000004
+#define GLX_BACK_RIGHT_BUFFER_BIT_SGIX 0x00000008
+#define GLX_AUX_BUFFERS_BIT_SGIX 0x00000010
+#define GLX_DEPTH_BUFFER_BIT_SGIX 0x00000020
+#define GLX_STENCIL_BUFFER_BIT_SGIX 0x00000040
+#define GLX_ACCUM_BUFFER_BIT_SGIX 0x00000080
+#define GLX_SAMPLE_BUFFERS_BIT_SGIX 0x00000100
+#define GLX_MAX_PBUFFER_WIDTH_SGIX 0x8016
+#define GLX_MAX_PBUFFER_HEIGHT_SGIX 0x8017
+#define GLX_MAX_PBUFFER_PIXELS_SGIX 0x8018
+#define GLX_OPTIMAL_PBUFFER_WIDTH_SGIX 0x8019
+#define GLX_OPTIMAL_PBUFFER_HEIGHT_SGIX 0x801A
+#define GLX_PRESERVED_CONTENTS_SGIX 0x801B
+#define GLX_LARGEST_PBUFFER_SGIX 0x801C
+#define GLX_WIDTH_SGIX 0x801D
+#define GLX_HEIGHT_SGIX 0x801E
+#define GLX_EVENT_MASK_SGIX 0x801F
+#define GLX_DAMAGED_SGIX 0x8020
+#define GLX_SAVED_SGIX 0x8021
+#define GLX_WINDOW_SGIX 0x8022
+#define GLX_PBUFFER_SGIX 0x8023
+#define GLX_BUFFER_CLOBBER_MASK_SGIX 0x08000000
+
+typedef XID GLXPbufferSGIX;
+typedef struct { int type; unsigned long serial; Bool send_event; Display *display; GLXDrawable drawable; int event_type; int draw_type; unsigned int mask; int x, y; int width, height; int count; } GLXBufferClobberEventSGIX;
+
+typedef GLXPbuffer ( * PFNGLXCREATEGLXPBUFFERSGIXPROC) (Display* dpy, GLXFBConfig config, unsigned int width, unsigned int height, int *attrib_list);
+typedef void ( * PFNGLXDESTROYGLXPBUFFERSGIXPROC) (Display* dpy, GLXPbuffer pbuf);
+typedef void ( * PFNGLXGETSELECTEDEVENTSGIXPROC) (Display* dpy, GLXDrawable drawable, unsigned long *mask);
+typedef void ( * PFNGLXQUERYGLXPBUFFERSGIXPROC) (Display* dpy, GLXPbuffer pbuf, int attribute, unsigned int *value);
+typedef void ( * PFNGLXSELECTEVENTSGIXPROC) (Display* dpy, GLXDrawable drawable, unsigned long mask);
+
+#define glXCreateGLXPbufferSGIX GLXEW_GET_FUN(__glewXCreateGLXPbufferSGIX)
+#define glXDestroyGLXPbufferSGIX GLXEW_GET_FUN(__glewXDestroyGLXPbufferSGIX)
+#define glXGetSelectedEventSGIX GLXEW_GET_FUN(__glewXGetSelectedEventSGIX)
+#define glXQueryGLXPbufferSGIX GLXEW_GET_FUN(__glewXQueryGLXPbufferSGIX)
+#define glXSelectEventSGIX GLXEW_GET_FUN(__glewXSelectEventSGIX)
+
+#define GLXEW_SGIX_pbuffer GLXEW_GET_VAR(__GLXEW_SGIX_pbuffer)
+
+#endif /* !GLX_SGIX_pbuffer */
+
+/* ------------------------- GLX_SGIX_swap_barrier ------------------------- */
+
+#if !defined(GLX_SGIX_swap_barrier)
+#define GLX_SGIX_swap_barrier 1
+
+typedef void ( * PFNGLXBINDSWAPBARRIERSGIXPROC) (Display *dpy, GLXDrawable drawable, int barrier);
+typedef Bool ( * PFNGLXQUERYMAXSWAPBARRIERSSGIXPROC) (Display *dpy, int screen, int *max);
+
+#define glXBindSwapBarrierSGIX GLXEW_GET_FUN(__glewXBindSwapBarrierSGIX)
+#define glXQueryMaxSwapBarriersSGIX GLXEW_GET_FUN(__glewXQueryMaxSwapBarriersSGIX)
+
+#define GLXEW_SGIX_swap_barrier GLXEW_GET_VAR(__GLXEW_SGIX_swap_barrier)
+
+#endif /* !GLX_SGIX_swap_barrier */
+
+/* -------------------------- GLX_SGIX_swap_group -------------------------- */
+
+#if !defined(GLX_SGIX_swap_group)
+#define GLX_SGIX_swap_group 1
+
+typedef void ( * PFNGLXJOINSWAPGROUPSGIXPROC) (Display *dpy, GLXDrawable drawable, GLXDrawable member);
+
+#define glXJoinSwapGroupSGIX GLXEW_GET_FUN(__glewXJoinSwapGroupSGIX)
+
+#define GLXEW_SGIX_swap_group GLXEW_GET_VAR(__GLXEW_SGIX_swap_group)
+
+#endif /* !GLX_SGIX_swap_group */
+
+/* ------------------------- GLX_SGIX_video_resize ------------------------- */
+
+#if !defined(GLX_SGIX_video_resize)
+#define GLX_SGIX_video_resize 1
+
+#define GLX_SYNC_FRAME_SGIX 0x00000000
+#define GLX_SYNC_SWAP_SGIX 0x00000001
+
+typedef int ( * PFNGLXBINDCHANNELTOWINDOWSGIXPROC) (Display* display, int screen, int channel, Window window);
+typedef int ( * PFNGLXCHANNELRECTSGIXPROC) (Display* display, int screen, int channel, int x, int y, int w, int h);
+typedef int ( * PFNGLXCHANNELRECTSYNCSGIXPROC) (Display* display, int screen, int channel, GLenum synctype);
+typedef int ( * PFNGLXQUERYCHANNELDELTASSGIXPROC) (Display* display, int screen, int channel, int *x, int *y, int *w, int *h);
+typedef int ( * PFNGLXQUERYCHANNELRECTSGIXPROC) (Display* display, int screen, int channel, int *dx, int *dy, int *dw, int *dh);
+
+#define glXBindChannelToWindowSGIX GLXEW_GET_FUN(__glewXBindChannelToWindowSGIX)
+#define glXChannelRectSGIX GLXEW_GET_FUN(__glewXChannelRectSGIX)
+#define glXChannelRectSyncSGIX GLXEW_GET_FUN(__glewXChannelRectSyncSGIX)
+#define glXQueryChannelDeltasSGIX GLXEW_GET_FUN(__glewXQueryChannelDeltasSGIX)
+#define glXQueryChannelRectSGIX GLXEW_GET_FUN(__glewXQueryChannelRectSGIX)
+
+#define GLXEW_SGIX_video_resize GLXEW_GET_VAR(__GLXEW_SGIX_video_resize)
+
+#endif /* !GLX_SGIX_video_resize */
+
+/* ---------------------- GLX_SGIX_visual_select_group --------------------- */
+
+#if !defined(GLX_SGIX_visual_select_group)
+#define GLX_SGIX_visual_select_group 1
+
+#define GLX_VISUAL_SELECT_GROUP_SGIX 0x8028
+
+#define GLXEW_SGIX_visual_select_group GLXEW_GET_VAR(__GLXEW_SGIX_visual_select_group)
+
+#endif /* !GLX_SGIX_visual_select_group */
+
+/* ---------------------------- GLX_SGI_cushion ---------------------------- */
+
+#if !defined(GLX_SGI_cushion)
+#define GLX_SGI_cushion 1
+
+typedef void ( * PFNGLXCUSHIONSGIPROC) (Display* dpy, Window window, float cushion);
+
+#define glXCushionSGI GLXEW_GET_FUN(__glewXCushionSGI)
+
+#define GLXEW_SGI_cushion GLXEW_GET_VAR(__GLXEW_SGI_cushion)
+
+#endif /* !GLX_SGI_cushion */
+
+/* ----------------------- GLX_SGI_make_current_read ----------------------- */
+
+#if !defined(GLX_SGI_make_current_read)
+#define GLX_SGI_make_current_read 1
+
+typedef GLXDrawable ( * PFNGLXGETCURRENTREADDRAWABLESGIPROC) (void);
+typedef Bool ( * PFNGLXMAKECURRENTREADSGIPROC) (Display* dpy, GLXDrawable draw, GLXDrawable read, GLXContext ctx);
+
+#define glXGetCurrentReadDrawableSGI GLXEW_GET_FUN(__glewXGetCurrentReadDrawableSGI)
+#define glXMakeCurrentReadSGI GLXEW_GET_FUN(__glewXMakeCurrentReadSGI)
+
+#define GLXEW_SGI_make_current_read GLXEW_GET_VAR(__GLXEW_SGI_make_current_read)
+
+#endif /* !GLX_SGI_make_current_read */
+
+/* -------------------------- GLX_SGI_swap_control ------------------------- */
+
+#if !defined(GLX_SGI_swap_control)
+#define GLX_SGI_swap_control 1
+
+typedef int ( * PFNGLXSWAPINTERVALSGIPROC) (int interval);
+
+#define glXSwapIntervalSGI GLXEW_GET_FUN(__glewXSwapIntervalSGI)
+
+#define GLXEW_SGI_swap_control GLXEW_GET_VAR(__GLXEW_SGI_swap_control)
+
+#endif /* !GLX_SGI_swap_control */
+
+/* --------------------------- GLX_SGI_video_sync -------------------------- */
+
+#if !defined(GLX_SGI_video_sync)
+#define GLX_SGI_video_sync 1
+
+typedef int ( * PFNGLXGETVIDEOSYNCSGIPROC) (unsigned int* count);
+typedef int ( * PFNGLXWAITVIDEOSYNCSGIPROC) (int divisor, int remainder, unsigned int* count);
+
+#define glXGetVideoSyncSGI GLXEW_GET_FUN(__glewXGetVideoSyncSGI)
+#define glXWaitVideoSyncSGI GLXEW_GET_FUN(__glewXWaitVideoSyncSGI)
+
+#define GLXEW_SGI_video_sync GLXEW_GET_VAR(__GLXEW_SGI_video_sync)
+
+#endif /* !GLX_SGI_video_sync */
+
+/* --------------------- GLX_SUN_get_transparent_index --------------------- */
+
+#if !defined(GLX_SUN_get_transparent_index)
+#define GLX_SUN_get_transparent_index 1
+
+typedef Status ( * PFNGLXGETTRANSPARENTINDEXSUNPROC) (Display* dpy, Window overlay, Window underlay, unsigned long *pTransparentIndex);
+
+#define glXGetTransparentIndexSUN GLXEW_GET_FUN(__glewXGetTransparentIndexSUN)
+
+#define GLXEW_SUN_get_transparent_index GLXEW_GET_VAR(__GLXEW_SUN_get_transparent_index)
+
+#endif /* !GLX_SUN_get_transparent_index */
+
+/* -------------------------- GLX_SUN_video_resize ------------------------- */
+
+#if !defined(GLX_SUN_video_resize)
+#define GLX_SUN_video_resize 1
+
+#define GLX_VIDEO_RESIZE_SUN 0x8171
+#define GL_VIDEO_RESIZE_COMPENSATION_SUN 0x85CD
+
+typedef int ( * PFNGLXGETVIDEORESIZESUNPROC) (Display* display, GLXDrawable window, float* factor);
+typedef int ( * PFNGLXVIDEORESIZESUNPROC) (Display* display, GLXDrawable window, float factor);
+
+#define glXGetVideoResizeSUN GLXEW_GET_FUN(__glewXGetVideoResizeSUN)
+#define glXVideoResizeSUN GLXEW_GET_FUN(__glewXVideoResizeSUN)
+
+#define GLXEW_SUN_video_resize GLXEW_GET_VAR(__GLXEW_SUN_video_resize)
+
+#endif /* !GLX_SUN_video_resize */
+
+/* ------------------------------------------------------------------------- */
+
+#ifdef GLEW_MX
+#define GLXEW_EXPORT
+#else
+#define GLXEW_EXPORT extern
+#endif /* GLEW_MX */
+
+extern PFNGLXGETCURRENTDISPLAYPROC __glewXGetCurrentDisplay;
+
+extern PFNGLXCHOOSEFBCONFIGPROC __glewXChooseFBConfig;
+extern PFNGLXCREATENEWCONTEXTPROC __glewXCreateNewContext;
+extern PFNGLXCREATEPBUFFERPROC __glewXCreatePbuffer;
+extern PFNGLXCREATEPIXMAPPROC __glewXCreatePixmap;
+extern PFNGLXCREATEWINDOWPROC __glewXCreateWindow;
+extern PFNGLXDESTROYPBUFFERPROC __glewXDestroyPbuffer;
+extern PFNGLXDESTROYPIXMAPPROC __glewXDestroyPixmap;
+extern PFNGLXDESTROYWINDOWPROC __glewXDestroyWindow;
+extern PFNGLXGETCURRENTREADDRAWABLEPROC __glewXGetCurrentReadDrawable;
+extern PFNGLXGETFBCONFIGATTRIBPROC __glewXGetFBConfigAttrib;
+extern PFNGLXGETFBCONFIGSPROC __glewXGetFBConfigs;
+extern PFNGLXGETSELECTEDEVENTPROC __glewXGetSelectedEvent;
+extern PFNGLXGETVISUALFROMFBCONFIGPROC __glewXGetVisualFromFBConfig;
+extern PFNGLXMAKECONTEXTCURRENTPROC __glewXMakeContextCurrent;
+extern PFNGLXQUERYCONTEXTPROC __glewXQueryContext;
+extern PFNGLXQUERYDRAWABLEPROC __glewXQueryDrawable;
+extern PFNGLXSELECTEVENTPROC __glewXSelectEvent;
+
+extern PFNGLXCREATECONTEXTATTRIBSARBPROC __glewXCreateContextAttribsARB;
+
+extern PFNGLXBINDTEXIMAGEATIPROC __glewXBindTexImageATI;
+extern PFNGLXDRAWABLEATTRIBATIPROC __glewXDrawableAttribATI;
+extern PFNGLXRELEASETEXIMAGEATIPROC __glewXReleaseTexImageATI;
+
+extern PFNGLXFREECONTEXTEXTPROC __glewXFreeContextEXT;
+extern PFNGLXGETCONTEXTIDEXTPROC __glewXGetContextIDEXT;
+extern PFNGLXIMPORTCONTEXTEXTPROC __glewXImportContextEXT;
+extern PFNGLXQUERYCONTEXTINFOEXTPROC __glewXQueryContextInfoEXT;
+
+extern PFNGLXSWAPINTERVALEXTPROC __glewXSwapIntervalEXT;
+
+extern PFNGLXBINDTEXIMAGEEXTPROC __glewXBindTexImageEXT;
+extern PFNGLXRELEASETEXIMAGEEXTPROC __glewXReleaseTexImageEXT;
+
+extern PFNGLXGETAGPOFFSETMESAPROC __glewXGetAGPOffsetMESA;
+
+extern PFNGLXCOPYSUBBUFFERMESAPROC __glewXCopySubBufferMESA;
+
+extern PFNGLXCREATEGLXPIXMAPMESAPROC __glewXCreateGLXPixmapMESA;
+
+extern PFNGLXRELEASEBUFFERSMESAPROC __glewXReleaseBuffersMESA;
+
+extern PFNGLXSET3DFXMODEMESAPROC __glewXSet3DfxModeMESA;
+
+extern PFNGLXGETSWAPINTERVALMESAPROC __glewXGetSwapIntervalMESA;
+extern PFNGLXSWAPINTERVALMESAPROC __glewXSwapIntervalMESA;
+
+extern PFNGLXCOPYIMAGESUBDATANVPROC __glewXCopyImageSubDataNV;
+
+extern PFNGLXBINDVIDEODEVICENVPROC __glewXBindVideoDeviceNV;
+extern PFNGLXENUMERATEVIDEODEVICESNVPROC __glewXEnumerateVideoDevicesNV;
+
+extern PFNGLXBINDSWAPBARRIERNVPROC __glewXBindSwapBarrierNV;
+extern PFNGLXJOINSWAPGROUPNVPROC __glewXJoinSwapGroupNV;
+extern PFNGLXQUERYFRAMECOUNTNVPROC __glewXQueryFrameCountNV;
+extern PFNGLXQUERYMAXSWAPGROUPSNVPROC __glewXQueryMaxSwapGroupsNV;
+extern PFNGLXQUERYSWAPGROUPNVPROC __glewXQuerySwapGroupNV;
+extern PFNGLXRESETFRAMECOUNTNVPROC __glewXResetFrameCountNV;
+
+extern PFNGLXALLOCATEMEMORYNVPROC __glewXAllocateMemoryNV;
+extern PFNGLXFREEMEMORYNVPROC __glewXFreeMemoryNV;
+
+extern PFNGLXBINDVIDEOCAPTUREDEVICENVPROC __glewXBindVideoCaptureDeviceNV;
+extern PFNGLXENUMERATEVIDEOCAPTUREDEVICESNVPROC __glewXEnumerateVideoCaptureDevicesNV;
+extern PFNGLXLOCKVIDEOCAPTUREDEVICENVPROC __glewXLockVideoCaptureDeviceNV;
+extern PFNGLXQUERYVIDEOCAPTUREDEVICENVPROC __glewXQueryVideoCaptureDeviceNV;
+extern PFNGLXRELEASEVIDEOCAPTUREDEVICENVPROC __glewXReleaseVideoCaptureDeviceNV;
+
+extern PFNGLXBINDVIDEOIMAGENVPROC __glewXBindVideoImageNV;
+extern PFNGLXGETVIDEODEVICENVPROC __glewXGetVideoDeviceNV;
+extern PFNGLXGETVIDEOINFONVPROC __glewXGetVideoInfoNV;
+extern PFNGLXRELEASEVIDEODEVICENVPROC __glewXReleaseVideoDeviceNV;
+extern PFNGLXRELEASEVIDEOIMAGENVPROC __glewXReleaseVideoImageNV;
+extern PFNGLXSENDPBUFFERTOVIDEONVPROC __glewXSendPbufferToVideoNV;
+
+extern PFNGLXGETMSCRATEOMLPROC __glewXGetMscRateOML;
+extern PFNGLXGETSYNCVALUESOMLPROC __glewXGetSyncValuesOML;
+extern PFNGLXSWAPBUFFERSMSCOMLPROC __glewXSwapBuffersMscOML;
+extern PFNGLXWAITFORMSCOMLPROC __glewXWaitForMscOML;
+extern PFNGLXWAITFORSBCOMLPROC __glewXWaitForSbcOML;
+
+extern PFNGLXCHOOSEFBCONFIGSGIXPROC __glewXChooseFBConfigSGIX;
+extern PFNGLXCREATECONTEXTWITHCONFIGSGIXPROC __glewXCreateContextWithConfigSGIX;
+extern PFNGLXCREATEGLXPIXMAPWITHCONFIGSGIXPROC __glewXCreateGLXPixmapWithConfigSGIX;
+extern PFNGLXGETFBCONFIGATTRIBSGIXPROC __glewXGetFBConfigAttribSGIX;
+extern PFNGLXGETFBCONFIGFROMVISUALSGIXPROC __glewXGetFBConfigFromVisualSGIX;
+extern PFNGLXGETVISUALFROMFBCONFIGSGIXPROC __glewXGetVisualFromFBConfigSGIX;
+
+extern PFNGLXBINDHYPERPIPESGIXPROC __glewXBindHyperpipeSGIX;
+extern PFNGLXDESTROYHYPERPIPECONFIGSGIXPROC __glewXDestroyHyperpipeConfigSGIX;
+extern PFNGLXHYPERPIPEATTRIBSGIXPROC __glewXHyperpipeAttribSGIX;
+extern PFNGLXHYPERPIPECONFIGSGIXPROC __glewXHyperpipeConfigSGIX;
+extern PFNGLXQUERYHYPERPIPEATTRIBSGIXPROC __glewXQueryHyperpipeAttribSGIX;
+extern PFNGLXQUERYHYPERPIPEBESTATTRIBSGIXPROC __glewXQueryHyperpipeBestAttribSGIX;
+extern PFNGLXQUERYHYPERPIPECONFIGSGIXPROC __glewXQueryHyperpipeConfigSGIX;
+extern PFNGLXQUERYHYPERPIPENETWORKSGIXPROC __glewXQueryHyperpipeNetworkSGIX;
+
+extern PFNGLXCREATEGLXPBUFFERSGIXPROC __glewXCreateGLXPbufferSGIX;
+extern PFNGLXDESTROYGLXPBUFFERSGIXPROC __glewXDestroyGLXPbufferSGIX;
+extern PFNGLXGETSELECTEDEVENTSGIXPROC __glewXGetSelectedEventSGIX;
+extern PFNGLXQUERYGLXPBUFFERSGIXPROC __glewXQueryGLXPbufferSGIX;
+extern PFNGLXSELECTEVENTSGIXPROC __glewXSelectEventSGIX;
+
+extern PFNGLXBINDSWAPBARRIERSGIXPROC __glewXBindSwapBarrierSGIX;
+extern PFNGLXQUERYMAXSWAPBARRIERSSGIXPROC __glewXQueryMaxSwapBarriersSGIX;
+
+extern PFNGLXJOINSWAPGROUPSGIXPROC __glewXJoinSwapGroupSGIX;
+
+extern PFNGLXBINDCHANNELTOWINDOWSGIXPROC __glewXBindChannelToWindowSGIX;
+extern PFNGLXCHANNELRECTSGIXPROC __glewXChannelRectSGIX;
+extern PFNGLXCHANNELRECTSYNCSGIXPROC __glewXChannelRectSyncSGIX;
+extern PFNGLXQUERYCHANNELDELTASSGIXPROC __glewXQueryChannelDeltasSGIX;
+extern PFNGLXQUERYCHANNELRECTSGIXPROC __glewXQueryChannelRectSGIX;
+
+extern PFNGLXCUSHIONSGIPROC __glewXCushionSGI;
+
+extern PFNGLXGETCURRENTREADDRAWABLESGIPROC __glewXGetCurrentReadDrawableSGI;
+extern PFNGLXMAKECURRENTREADSGIPROC __glewXMakeCurrentReadSGI;
+
+extern PFNGLXSWAPINTERVALSGIPROC __glewXSwapIntervalSGI;
+
+extern PFNGLXGETVIDEOSYNCSGIPROC __glewXGetVideoSyncSGI;
+extern PFNGLXWAITVIDEOSYNCSGIPROC __glewXWaitVideoSyncSGI;
+
+extern PFNGLXGETTRANSPARENTINDEXSUNPROC __glewXGetTransparentIndexSUN;
+
+extern PFNGLXGETVIDEORESIZESUNPROC __glewXGetVideoResizeSUN;
+extern PFNGLXVIDEORESIZESUNPROC __glewXVideoResizeSUN;
+
+#if defined(GLEW_MX)
+struct GLXEWContextStruct
+{
+#endif /* GLEW_MX */
+
+GLXEW_EXPORT GLboolean __GLXEW_VERSION_1_0;
+GLXEW_EXPORT GLboolean __GLXEW_VERSION_1_1;
+GLXEW_EXPORT GLboolean __GLXEW_VERSION_1_2;
+GLXEW_EXPORT GLboolean __GLXEW_VERSION_1_3;
+GLXEW_EXPORT GLboolean __GLXEW_VERSION_1_4;
+GLXEW_EXPORT GLboolean __GLXEW_3DFX_multisample;
+GLXEW_EXPORT GLboolean __GLXEW_AMD_gpu_association;
+GLXEW_EXPORT GLboolean __GLXEW_ARB_create_context;
+GLXEW_EXPORT GLboolean __GLXEW_ARB_create_context_profile;
+GLXEW_EXPORT GLboolean __GLXEW_ARB_create_context_robustness;
+GLXEW_EXPORT GLboolean __GLXEW_ARB_fbconfig_float;
+GLXEW_EXPORT GLboolean __GLXEW_ARB_framebuffer_sRGB;
+GLXEW_EXPORT GLboolean __GLXEW_ARB_get_proc_address;
+GLXEW_EXPORT GLboolean __GLXEW_ARB_multisample;
+GLXEW_EXPORT GLboolean __GLXEW_ARB_robustness_application_isolation;
+GLXEW_EXPORT GLboolean __GLXEW_ARB_robustness_share_group_isolation;
+GLXEW_EXPORT GLboolean __GLXEW_ARB_vertex_buffer_object;
+GLXEW_EXPORT GLboolean __GLXEW_ATI_pixel_format_float;
+GLXEW_EXPORT GLboolean __GLXEW_ATI_render_texture;
+GLXEW_EXPORT GLboolean __GLXEW_EXT_buffer_age;
+GLXEW_EXPORT GLboolean __GLXEW_EXT_create_context_es2_profile;
+GLXEW_EXPORT GLboolean __GLXEW_EXT_create_context_es_profile;
+GLXEW_EXPORT GLboolean __GLXEW_EXT_fbconfig_packed_float;
+GLXEW_EXPORT GLboolean __GLXEW_EXT_framebuffer_sRGB;
+GLXEW_EXPORT GLboolean __GLXEW_EXT_import_context;
+GLXEW_EXPORT GLboolean __GLXEW_EXT_scene_marker;
+GLXEW_EXPORT GLboolean __GLXEW_EXT_swap_control;
+GLXEW_EXPORT GLboolean __GLXEW_EXT_swap_control_tear;
+GLXEW_EXPORT GLboolean __GLXEW_EXT_texture_from_pixmap;
+GLXEW_EXPORT GLboolean __GLXEW_EXT_visual_info;
+GLXEW_EXPORT GLboolean __GLXEW_EXT_visual_rating;
+GLXEW_EXPORT GLboolean __GLXEW_INTEL_swap_event;
+GLXEW_EXPORT GLboolean __GLXEW_MESA_agp_offset;
+GLXEW_EXPORT GLboolean __GLXEW_MESA_copy_sub_buffer;
+GLXEW_EXPORT GLboolean __GLXEW_MESA_pixmap_colormap;
+GLXEW_EXPORT GLboolean __GLXEW_MESA_release_buffers;
+GLXEW_EXPORT GLboolean __GLXEW_MESA_set_3dfx_mode;
+GLXEW_EXPORT GLboolean __GLXEW_MESA_swap_control;
+GLXEW_EXPORT GLboolean __GLXEW_NV_copy_image;
+GLXEW_EXPORT GLboolean __GLXEW_NV_float_buffer;
+GLXEW_EXPORT GLboolean __GLXEW_NV_multisample_coverage;
+GLXEW_EXPORT GLboolean __GLXEW_NV_present_video;
+GLXEW_EXPORT GLboolean __GLXEW_NV_swap_group;
+GLXEW_EXPORT GLboolean __GLXEW_NV_vertex_array_range;
+GLXEW_EXPORT GLboolean __GLXEW_NV_video_capture;
+GLXEW_EXPORT GLboolean __GLXEW_NV_video_output;
+GLXEW_EXPORT GLboolean __GLXEW_OML_swap_method;
+GLXEW_EXPORT GLboolean __GLXEW_OML_sync_control;
+GLXEW_EXPORT GLboolean __GLXEW_SGIS_blended_overlay;
+GLXEW_EXPORT GLboolean __GLXEW_SGIS_color_range;
+GLXEW_EXPORT GLboolean __GLXEW_SGIS_multisample;
+GLXEW_EXPORT GLboolean __GLXEW_SGIS_shared_multisample;
+GLXEW_EXPORT GLboolean __GLXEW_SGIX_fbconfig;
+GLXEW_EXPORT GLboolean __GLXEW_SGIX_hyperpipe;
+GLXEW_EXPORT GLboolean __GLXEW_SGIX_pbuffer;
+GLXEW_EXPORT GLboolean __GLXEW_SGIX_swap_barrier;
+GLXEW_EXPORT GLboolean __GLXEW_SGIX_swap_group;
+GLXEW_EXPORT GLboolean __GLXEW_SGIX_video_resize;
+GLXEW_EXPORT GLboolean __GLXEW_SGIX_visual_select_group;
+GLXEW_EXPORT GLboolean __GLXEW_SGI_cushion;
+GLXEW_EXPORT GLboolean __GLXEW_SGI_make_current_read;
+GLXEW_EXPORT GLboolean __GLXEW_SGI_swap_control;
+GLXEW_EXPORT GLboolean __GLXEW_SGI_video_sync;
+GLXEW_EXPORT GLboolean __GLXEW_SUN_get_transparent_index;
+GLXEW_EXPORT GLboolean __GLXEW_SUN_video_resize;
+
+#ifdef GLEW_MX
+}; /* GLXEWContextStruct */
+#endif /* GLEW_MX */
+
+/* ------------------------------------------------------------------------ */
+
+#ifdef GLEW_MX
+
+typedef struct GLXEWContextStruct GLXEWContext;
+extern GLenum glxewContextInit (GLXEWContext* ctx);
+extern GLboolean glxewContextIsSupported (const GLXEWContext* ctx, const char* name);
+
+#define glxewInit() glxewContextInit(glxewGetContext())
+#define glxewIsSupported(x) glxewContextIsSupported(glxewGetContext(), x)
+
+#define GLXEW_GET_VAR(x) (*(const GLboolean*)&(glxewGetContext()->x))
+#define GLXEW_GET_FUN(x) x
+
+#else /* GLEW_MX */
+
+#define GLXEW_GET_VAR(x) (*(const GLboolean*)&x)
+#define GLXEW_GET_FUN(x) x
+
+extern GLboolean glxewIsSupported (const char* name);
+
+#endif /* GLEW_MX */
+
+extern GLboolean glxewGetExtension (const char* name);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __glxew_h__ */
diff --git a/extern/glew-es/include/GL/wglew.h b/extern/glew-es/include/GL/wglew.h
new file mode 100644
index 00000000000..df68427d809
--- /dev/null
+++ b/extern/glew-es/include/GL/wglew.h
@@ -0,0 +1,1424 @@
+/*
+** The OpenGL Extension Wrangler Library
+** Copyright (C) 2002-2008, Milan Ikits <milan ikits[]ieee org>
+** Copyright (C) 2002-2008, Marcelo E. Magallon <mmagallo[]debian org>
+** Copyright (C) 2002, Lev Povalahev
+** 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.
+** * The name of the author 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.
+*/
+
+/*
+** Copyright (c) 2007 The Khronos Group Inc.
+**
+** Permission is hereby granted, free of charge, to any person obtaining a
+** copy of this software and/or associated documentation files (the
+** "Materials"), to deal in the Materials without restriction, including
+** without limitation the rights to use, copy, modify, merge, publish,
+** distribute, sublicense, and/or sell copies of the Materials, and to
+** permit persons to whom the Materials are furnished to do so, subject to
+** the following conditions:
+**
+** The above copyright notice and this permission notice shall be included
+** in all copies or substantial portions of the Materials.
+**
+** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+*/
+
+#ifndef __wglew_h__
+#define __wglew_h__
+#define __WGLEW_H__
+
+#ifdef __wglext_h_
+#error wglext.h included before wglew.h
+#endif
+
+#define __wglext_h_
+
+#if !defined(WINAPI)
+# ifndef WIN32_LEAN_AND_MEAN
+# define WIN32_LEAN_AND_MEAN 1
+# endif
+#include <windows.h>
+# undef WIN32_LEAN_AND_MEAN
+#endif
+
+/*
+ * GLEW_STATIC needs to be set when using the static version.
+ * GLEW_BUILD is set when building the DLL version.
+ */
+#ifdef GLEW_STATIC
+# define GLEWAPI extern
+#else
+# ifdef GLEW_BUILD
+# define GLEWAPI extern __declspec(dllexport)
+# else
+# define GLEWAPI extern __declspec(dllimport)
+# endif
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* -------------------------- WGL_3DFX_multisample ------------------------- */
+
+#if !defined(WGL_3DFX_multisample)
+#define WGL_3DFX_multisample 1
+
+#define WGL_SAMPLE_BUFFERS_3DFX 0x2060
+#define WGL_SAMPLES_3DFX 0x2061
+
+#define WGLEW_3DFX_multisample WGLEW_GET_VAR(__WGLEW_3DFX_multisample)
+
+#endif /* !WGL_3DFX_multisample */
+
+/* ------------------------- WGL_3DL_stereo_control ------------------------ */
+
+#if !defined(WGL_3DL_stereo_control)
+#define WGL_3DL_stereo_control 1
+
+#define WGL_STEREO_EMITTER_ENABLE_3DL 0x2055
+#define WGL_STEREO_EMITTER_DISABLE_3DL 0x2056
+#define WGL_STEREO_POLARITY_NORMAL_3DL 0x2057
+#define WGL_STEREO_POLARITY_INVERT_3DL 0x2058
+
+typedef BOOL (WINAPI * PFNWGLSETSTEREOEMITTERSTATE3DLPROC) (HDC hDC, UINT uState);
+
+#define wglSetStereoEmitterState3DL WGLEW_GET_FUN(__wglewSetStereoEmitterState3DL)
+
+#define WGLEW_3DL_stereo_control WGLEW_GET_VAR(__WGLEW_3DL_stereo_control)
+
+#endif /* !WGL_3DL_stereo_control */
+
+/* ------------------------ WGL_AMD_gpu_association ------------------------ */
+
+#if !defined(WGL_AMD_gpu_association)
+#define WGL_AMD_gpu_association 1
+
+#define WGL_GPU_VENDOR_AMD 0x1F00
+#define WGL_GPU_RENDERER_STRING_AMD 0x1F01
+#define WGL_GPU_OPENGL_VERSION_STRING_AMD 0x1F02
+#define WGL_GPU_FASTEST_TARGET_GPUS_AMD 0x21A2
+#define WGL_GPU_RAM_AMD 0x21A3
+#define WGL_GPU_CLOCK_AMD 0x21A4
+#define WGL_GPU_NUM_PIPES_AMD 0x21A5
+#define WGL_GPU_NUM_SIMD_AMD 0x21A6
+#define WGL_GPU_NUM_RB_AMD 0x21A7
+#define WGL_GPU_NUM_SPI_AMD 0x21A8
+
+typedef VOID (WINAPI * PFNWGLBLITCONTEXTFRAMEBUFFERAMDPROC) (HGLRC dstCtx, GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter);
+typedef HGLRC (WINAPI * PFNWGLCREATEASSOCIATEDCONTEXTAMDPROC) (UINT id);
+typedef HGLRC (WINAPI * PFNWGLCREATEASSOCIATEDCONTEXTATTRIBSAMDPROC) (UINT id, HGLRC hShareContext, const int* attribList);
+typedef BOOL (WINAPI * PFNWGLDELETEASSOCIATEDCONTEXTAMDPROC) (HGLRC hglrc);
+typedef UINT (WINAPI * PFNWGLGETCONTEXTGPUIDAMDPROC) (HGLRC hglrc);
+typedef HGLRC (WINAPI * PFNWGLGETCURRENTASSOCIATEDCONTEXTAMDPROC) (void);
+typedef UINT (WINAPI * PFNWGLGETGPUIDSAMDPROC) (UINT maxCount, UINT* ids);
+typedef INT (WINAPI * PFNWGLGETGPUINFOAMDPROC) (UINT id, INT property, GLenum dataType, UINT size, void* data);
+typedef BOOL (WINAPI * PFNWGLMAKEASSOCIATEDCONTEXTCURRENTAMDPROC) (HGLRC hglrc);
+
+#define wglBlitContextFramebufferAMD WGLEW_GET_FUN(__wglewBlitContextFramebufferAMD)
+#define wglCreateAssociatedContextAMD WGLEW_GET_FUN(__wglewCreateAssociatedContextAMD)
+#define wglCreateAssociatedContextAttribsAMD WGLEW_GET_FUN(__wglewCreateAssociatedContextAttribsAMD)
+#define wglDeleteAssociatedContextAMD WGLEW_GET_FUN(__wglewDeleteAssociatedContextAMD)
+#define wglGetContextGPUIDAMD WGLEW_GET_FUN(__wglewGetContextGPUIDAMD)
+#define wglGetCurrentAssociatedContextAMD WGLEW_GET_FUN(__wglewGetCurrentAssociatedContextAMD)
+#define wglGetGPUIDsAMD WGLEW_GET_FUN(__wglewGetGPUIDsAMD)
+#define wglGetGPUInfoAMD WGLEW_GET_FUN(__wglewGetGPUInfoAMD)
+#define wglMakeAssociatedContextCurrentAMD WGLEW_GET_FUN(__wglewMakeAssociatedContextCurrentAMD)
+
+#define WGLEW_AMD_gpu_association WGLEW_GET_VAR(__WGLEW_AMD_gpu_association)
+
+#endif /* !WGL_AMD_gpu_association */
+
+/* ------------------------- WGL_ARB_buffer_region ------------------------- */
+
+#if !defined(WGL_ARB_buffer_region)
+#define WGL_ARB_buffer_region 1
+
+#define WGL_FRONT_COLOR_BUFFER_BIT_ARB 0x00000001
+#define WGL_BACK_COLOR_BUFFER_BIT_ARB 0x00000002
+#define WGL_DEPTH_BUFFER_BIT_ARB 0x00000004
+#define WGL_STENCIL_BUFFER_BIT_ARB 0x00000008
+
+typedef HANDLE (WINAPI * PFNWGLCREATEBUFFERREGIONARBPROC) (HDC hDC, int iLayerPlane, UINT uType);
+typedef VOID (WINAPI * PFNWGLDELETEBUFFERREGIONARBPROC) (HANDLE hRegion);
+typedef BOOL (WINAPI * PFNWGLRESTOREBUFFERREGIONARBPROC) (HANDLE hRegion, int x, int y, int width, int height, int xSrc, int ySrc);
+typedef BOOL (WINAPI * PFNWGLSAVEBUFFERREGIONARBPROC) (HANDLE hRegion, int x, int y, int width, int height);
+
+#define wglCreateBufferRegionARB WGLEW_GET_FUN(__wglewCreateBufferRegionARB)
+#define wglDeleteBufferRegionARB WGLEW_GET_FUN(__wglewDeleteBufferRegionARB)
+#define wglRestoreBufferRegionARB WGLEW_GET_FUN(__wglewRestoreBufferRegionARB)
+#define wglSaveBufferRegionARB WGLEW_GET_FUN(__wglewSaveBufferRegionARB)
+
+#define WGLEW_ARB_buffer_region WGLEW_GET_VAR(__WGLEW_ARB_buffer_region)
+
+#endif /* !WGL_ARB_buffer_region */
+
+/* ------------------------- WGL_ARB_create_context ------------------------ */
+
+#if !defined(WGL_ARB_create_context)
+#define WGL_ARB_create_context 1
+
+#define WGL_CONTEXT_DEBUG_BIT_ARB 0x0001
+#define WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB 0x0002
+#define WGL_CONTEXT_MAJOR_VERSION_ARB 0x2091
+#define WGL_CONTEXT_MINOR_VERSION_ARB 0x2092
+#define WGL_CONTEXT_LAYER_PLANE_ARB 0x2093
+#define WGL_CONTEXT_FLAGS_ARB 0x2094
+#define ERROR_INVALID_VERSION_ARB 0x2095
+#define ERROR_INVALID_PROFILE_ARB 0x2096
+
+typedef HGLRC (WINAPI * PFNWGLCREATECONTEXTATTRIBSARBPROC) (HDC hDC, HGLRC hShareContext, const int* attribList);
+
+#define wglCreateContextAttribsARB WGLEW_GET_FUN(__wglewCreateContextAttribsARB)
+
+#define WGLEW_ARB_create_context WGLEW_GET_VAR(__WGLEW_ARB_create_context)
+
+#endif /* !WGL_ARB_create_context */
+
+/* --------------------- WGL_ARB_create_context_profile -------------------- */
+
+#if !defined(WGL_ARB_create_context_profile)
+#define WGL_ARB_create_context_profile 1
+
+#define WGL_CONTEXT_CORE_PROFILE_BIT_ARB 0x00000001
+#define WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002
+#define WGL_CONTEXT_PROFILE_MASK_ARB 0x9126
+
+#define WGLEW_ARB_create_context_profile WGLEW_GET_VAR(__WGLEW_ARB_create_context_profile)
+
+#endif /* !WGL_ARB_create_context_profile */
+
+/* ------------------- WGL_ARB_create_context_robustness ------------------- */
+
+#if !defined(WGL_ARB_create_context_robustness)
+#define WGL_ARB_create_context_robustness 1
+
+#define WGL_CONTEXT_ROBUST_ACCESS_BIT_ARB 0x00000004
+#define WGL_LOSE_CONTEXT_ON_RESET_ARB 0x8252
+#define WGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB 0x8256
+#define WGL_NO_RESET_NOTIFICATION_ARB 0x8261
+
+#define WGLEW_ARB_create_context_robustness WGLEW_GET_VAR(__WGLEW_ARB_create_context_robustness)
+
+#endif /* !WGL_ARB_create_context_robustness */
+
+/* ----------------------- WGL_ARB_extensions_string ----------------------- */
+
+#if !defined(WGL_ARB_extensions_string)
+#define WGL_ARB_extensions_string 1
+
+typedef const char* (WINAPI * PFNWGLGETEXTENSIONSSTRINGARBPROC) (HDC hdc);
+
+#define wglGetExtensionsStringARB WGLEW_GET_FUN(__wglewGetExtensionsStringARB)
+
+#define WGLEW_ARB_extensions_string WGLEW_GET_VAR(__WGLEW_ARB_extensions_string)
+
+#endif /* !WGL_ARB_extensions_string */
+
+/* ------------------------ WGL_ARB_framebuffer_sRGB ----------------------- */
+
+#if !defined(WGL_ARB_framebuffer_sRGB)
+#define WGL_ARB_framebuffer_sRGB 1
+
+#define WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB 0x20A9
+
+#define WGLEW_ARB_framebuffer_sRGB WGLEW_GET_VAR(__WGLEW_ARB_framebuffer_sRGB)
+
+#endif /* !WGL_ARB_framebuffer_sRGB */
+
+/* ----------------------- WGL_ARB_make_current_read ----------------------- */
+
+#if !defined(WGL_ARB_make_current_read)
+#define WGL_ARB_make_current_read 1
+
+#define ERROR_INVALID_PIXEL_TYPE_ARB 0x2043
+#define ERROR_INCOMPATIBLE_DEVICE_CONTEXTS_ARB 0x2054
+
+typedef HDC (WINAPI * PFNWGLGETCURRENTREADDCARBPROC) (VOID);
+typedef BOOL (WINAPI * PFNWGLMAKECONTEXTCURRENTARBPROC) (HDC hDrawDC, HDC hReadDC, HGLRC hglrc);
+
+#define wglGetCurrentReadDCARB WGLEW_GET_FUN(__wglewGetCurrentReadDCARB)
+#define wglMakeContextCurrentARB WGLEW_GET_FUN(__wglewMakeContextCurrentARB)
+
+#define WGLEW_ARB_make_current_read WGLEW_GET_VAR(__WGLEW_ARB_make_current_read)
+
+#endif /* !WGL_ARB_make_current_read */
+
+/* -------------------------- WGL_ARB_multisample -------------------------- */
+
+#if !defined(WGL_ARB_multisample)
+#define WGL_ARB_multisample 1
+
+#define WGL_SAMPLE_BUFFERS_ARB 0x2041
+#define WGL_SAMPLES_ARB 0x2042
+
+#define WGLEW_ARB_multisample WGLEW_GET_VAR(__WGLEW_ARB_multisample)
+
+#endif /* !WGL_ARB_multisample */
+
+/* ---------------------------- WGL_ARB_pbuffer ---------------------------- */
+
+#if !defined(WGL_ARB_pbuffer)
+#define WGL_ARB_pbuffer 1
+
+#define WGL_DRAW_TO_PBUFFER_ARB 0x202D
+#define WGL_MAX_PBUFFER_PIXELS_ARB 0x202E
+#define WGL_MAX_PBUFFER_WIDTH_ARB 0x202F
+#define WGL_MAX_PBUFFER_HEIGHT_ARB 0x2030
+#define WGL_PBUFFER_LARGEST_ARB 0x2033
+#define WGL_PBUFFER_WIDTH_ARB 0x2034
+#define WGL_PBUFFER_HEIGHT_ARB 0x2035
+#define WGL_PBUFFER_LOST_ARB 0x2036
+
+DECLARE_HANDLE(HPBUFFERARB);
+
+typedef HPBUFFERARB (WINAPI * PFNWGLCREATEPBUFFERARBPROC) (HDC hDC, int iPixelFormat, int iWidth, int iHeight, const int* piAttribList);
+typedef BOOL (WINAPI * PFNWGLDESTROYPBUFFERARBPROC) (HPBUFFERARB hPbuffer);
+typedef HDC (WINAPI * PFNWGLGETPBUFFERDCARBPROC) (HPBUFFERARB hPbuffer);
+typedef BOOL (WINAPI * PFNWGLQUERYPBUFFERARBPROC) (HPBUFFERARB hPbuffer, int iAttribute, int* piValue);
+typedef int (WINAPI * PFNWGLRELEASEPBUFFERDCARBPROC) (HPBUFFERARB hPbuffer, HDC hDC);
+
+#define wglCreatePbufferARB WGLEW_GET_FUN(__wglewCreatePbufferARB)
+#define wglDestroyPbufferARB WGLEW_GET_FUN(__wglewDestroyPbufferARB)
+#define wglGetPbufferDCARB WGLEW_GET_FUN(__wglewGetPbufferDCARB)
+#define wglQueryPbufferARB WGLEW_GET_FUN(__wglewQueryPbufferARB)
+#define wglReleasePbufferDCARB WGLEW_GET_FUN(__wglewReleasePbufferDCARB)
+
+#define WGLEW_ARB_pbuffer WGLEW_GET_VAR(__WGLEW_ARB_pbuffer)
+
+#endif /* !WGL_ARB_pbuffer */
+
+/* -------------------------- WGL_ARB_pixel_format ------------------------- */
+
+#if !defined(WGL_ARB_pixel_format)
+#define WGL_ARB_pixel_format 1
+
+#define WGL_NUMBER_PIXEL_FORMATS_ARB 0x2000
+#define WGL_DRAW_TO_WINDOW_ARB 0x2001
+#define WGL_DRAW_TO_BITMAP_ARB 0x2002
+#define WGL_ACCELERATION_ARB 0x2003
+#define WGL_NEED_PALETTE_ARB 0x2004
+#define WGL_NEED_SYSTEM_PALETTE_ARB 0x2005
+#define WGL_SWAP_LAYER_BUFFERS_ARB 0x2006
+#define WGL_SWAP_METHOD_ARB 0x2007
+#define WGL_NUMBER_OVERLAYS_ARB 0x2008
+#define WGL_NUMBER_UNDERLAYS_ARB 0x2009
+#define WGL_TRANSPARENT_ARB 0x200A
+#define WGL_SHARE_DEPTH_ARB 0x200C
+#define WGL_SHARE_STENCIL_ARB 0x200D
+#define WGL_SHARE_ACCUM_ARB 0x200E
+#define WGL_SUPPORT_GDI_ARB 0x200F
+#define WGL_SUPPORT_OPENGL_ARB 0x2010
+#define WGL_DOUBLE_BUFFER_ARB 0x2011
+#define WGL_STEREO_ARB 0x2012
+#define WGL_PIXEL_TYPE_ARB 0x2013
+#define WGL_COLOR_BITS_ARB 0x2014
+#define WGL_RED_BITS_ARB 0x2015
+#define WGL_RED_SHIFT_ARB 0x2016
+#define WGL_GREEN_BITS_ARB 0x2017
+#define WGL_GREEN_SHIFT_ARB 0x2018
+#define WGL_BLUE_BITS_ARB 0x2019
+#define WGL_BLUE_SHIFT_ARB 0x201A
+#define WGL_ALPHA_BITS_ARB 0x201B
+#define WGL_ALPHA_SHIFT_ARB 0x201C
+#define WGL_ACCUM_BITS_ARB 0x201D
+#define WGL_ACCUM_RED_BITS_ARB 0x201E
+#define WGL_ACCUM_GREEN_BITS_ARB 0x201F
+#define WGL_ACCUM_BLUE_BITS_ARB 0x2020
+#define WGL_ACCUM_ALPHA_BITS_ARB 0x2021
+#define WGL_DEPTH_BITS_ARB 0x2022
+#define WGL_STENCIL_BITS_ARB 0x2023
+#define WGL_AUX_BUFFERS_ARB 0x2024
+#define WGL_NO_ACCELERATION_ARB 0x2025
+#define WGL_GENERIC_ACCELERATION_ARB 0x2026
+#define WGL_FULL_ACCELERATION_ARB 0x2027
+#define WGL_SWAP_EXCHANGE_ARB 0x2028
+#define WGL_SWAP_COPY_ARB 0x2029
+#define WGL_SWAP_UNDEFINED_ARB 0x202A
+#define WGL_TYPE_RGBA_ARB 0x202B
+#define WGL_TYPE_COLORINDEX_ARB 0x202C
+#define WGL_TRANSPARENT_RED_VALUE_ARB 0x2037
+#define WGL_TRANSPARENT_GREEN_VALUE_ARB 0x2038
+#define WGL_TRANSPARENT_BLUE_VALUE_ARB 0x2039
+#define WGL_TRANSPARENT_ALPHA_VALUE_ARB 0x203A
+#define WGL_TRANSPARENT_INDEX_VALUE_ARB 0x203B
+
+typedef BOOL (WINAPI * PFNWGLCHOOSEPIXELFORMATARBPROC) (HDC hdc, const int* piAttribIList, const FLOAT *pfAttribFList, UINT nMaxFormats, int *piFormats, UINT *nNumFormats);
+typedef BOOL (WINAPI * PFNWGLGETPIXELFORMATATTRIBFVARBPROC) (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, const int* piAttributes, FLOAT *pfValues);
+typedef BOOL (WINAPI * PFNWGLGETPIXELFORMATATTRIBIVARBPROC) (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, const int* piAttributes, int *piValues);
+
+#define wglChoosePixelFormatARB WGLEW_GET_FUN(__wglewChoosePixelFormatARB)
+#define wglGetPixelFormatAttribfvARB WGLEW_GET_FUN(__wglewGetPixelFormatAttribfvARB)
+#define wglGetPixelFormatAttribivARB WGLEW_GET_FUN(__wglewGetPixelFormatAttribivARB)
+
+#define WGLEW_ARB_pixel_format WGLEW_GET_VAR(__WGLEW_ARB_pixel_format)
+
+#endif /* !WGL_ARB_pixel_format */
+
+/* ----------------------- WGL_ARB_pixel_format_float ---------------------- */
+
+#if !defined(WGL_ARB_pixel_format_float)
+#define WGL_ARB_pixel_format_float 1
+
+#define WGL_TYPE_RGBA_FLOAT_ARB 0x21A0
+
+#define WGLEW_ARB_pixel_format_float WGLEW_GET_VAR(__WGLEW_ARB_pixel_format_float)
+
+#endif /* !WGL_ARB_pixel_format_float */
+
+/* ------------------------- WGL_ARB_render_texture ------------------------ */
+
+#if !defined(WGL_ARB_render_texture)
+#define WGL_ARB_render_texture 1
+
+#define WGL_BIND_TO_TEXTURE_RGB_ARB 0x2070
+#define WGL_BIND_TO_TEXTURE_RGBA_ARB 0x2071
+#define WGL_TEXTURE_FORMAT_ARB 0x2072
+#define WGL_TEXTURE_TARGET_ARB 0x2073
+#define WGL_MIPMAP_TEXTURE_ARB 0x2074
+#define WGL_TEXTURE_RGB_ARB 0x2075
+#define WGL_TEXTURE_RGBA_ARB 0x2076
+#define WGL_NO_TEXTURE_ARB 0x2077
+#define WGL_TEXTURE_CUBE_MAP_ARB 0x2078
+#define WGL_TEXTURE_1D_ARB 0x2079
+#define WGL_TEXTURE_2D_ARB 0x207A
+#define WGL_MIPMAP_LEVEL_ARB 0x207B
+#define WGL_CUBE_MAP_FACE_ARB 0x207C
+#define WGL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB 0x207D
+#define WGL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB 0x207E
+#define WGL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB 0x207F
+#define WGL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB 0x2080
+#define WGL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB 0x2081
+#define WGL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB 0x2082
+#define WGL_FRONT_LEFT_ARB 0x2083
+#define WGL_FRONT_RIGHT_ARB 0x2084
+#define WGL_BACK_LEFT_ARB 0x2085
+#define WGL_BACK_RIGHT_ARB 0x2086
+#define WGL_AUX0_ARB 0x2087
+#define WGL_AUX1_ARB 0x2088
+#define WGL_AUX2_ARB 0x2089
+#define WGL_AUX3_ARB 0x208A
+#define WGL_AUX4_ARB 0x208B
+#define WGL_AUX5_ARB 0x208C
+#define WGL_AUX6_ARB 0x208D
+#define WGL_AUX7_ARB 0x208E
+#define WGL_AUX8_ARB 0x208F
+#define WGL_AUX9_ARB 0x2090
+
+typedef BOOL (WINAPI * PFNWGLBINDTEXIMAGEARBPROC) (HPBUFFERARB hPbuffer, int iBuffer);
+typedef BOOL (WINAPI * PFNWGLRELEASETEXIMAGEARBPROC) (HPBUFFERARB hPbuffer, int iBuffer);
+typedef BOOL (WINAPI * PFNWGLSETPBUFFERATTRIBARBPROC) (HPBUFFERARB hPbuffer, const int* piAttribList);
+
+#define wglBindTexImageARB WGLEW_GET_FUN(__wglewBindTexImageARB)
+#define wglReleaseTexImageARB WGLEW_GET_FUN(__wglewReleaseTexImageARB)
+#define wglSetPbufferAttribARB WGLEW_GET_FUN(__wglewSetPbufferAttribARB)
+
+#define WGLEW_ARB_render_texture WGLEW_GET_VAR(__WGLEW_ARB_render_texture)
+
+#endif /* !WGL_ARB_render_texture */
+
+/* ---------------- WGL_ARB_robustness_application_isolation --------------- */
+
+#if !defined(WGL_ARB_robustness_application_isolation)
+#define WGL_ARB_robustness_application_isolation 1
+
+#define WGL_CONTEXT_RESET_ISOLATION_BIT_ARB 0x00000008
+
+#define WGLEW_ARB_robustness_application_isolation WGLEW_GET_VAR(__WGLEW_ARB_robustness_application_isolation)
+
+#endif /* !WGL_ARB_robustness_application_isolation */
+
+/* ---------------- WGL_ARB_robustness_share_group_isolation --------------- */
+
+#if !defined(WGL_ARB_robustness_share_group_isolation)
+#define WGL_ARB_robustness_share_group_isolation 1
+
+#define WGL_CONTEXT_RESET_ISOLATION_BIT_ARB 0x00000008
+
+#define WGLEW_ARB_robustness_share_group_isolation WGLEW_GET_VAR(__WGLEW_ARB_robustness_share_group_isolation)
+
+#endif /* !WGL_ARB_robustness_share_group_isolation */
+
+/* ----------------------- WGL_ATI_pixel_format_float ---------------------- */
+
+#if !defined(WGL_ATI_pixel_format_float)
+#define WGL_ATI_pixel_format_float 1
+
+#define WGL_TYPE_RGBA_FLOAT_ATI 0x21A0
+#define GL_RGBA_FLOAT_MODE_ATI 0x8820
+#define GL_COLOR_CLEAR_UNCLAMPED_VALUE_ATI 0x8835
+
+#define WGLEW_ATI_pixel_format_float WGLEW_GET_VAR(__WGLEW_ATI_pixel_format_float)
+
+#endif /* !WGL_ATI_pixel_format_float */
+
+/* -------------------- WGL_ATI_render_texture_rectangle ------------------- */
+
+#if !defined(WGL_ATI_render_texture_rectangle)
+#define WGL_ATI_render_texture_rectangle 1
+
+#define WGL_TEXTURE_RECTANGLE_ATI 0x21A5
+
+#define WGLEW_ATI_render_texture_rectangle WGLEW_GET_VAR(__WGLEW_ATI_render_texture_rectangle)
+
+#endif /* !WGL_ATI_render_texture_rectangle */
+
+/* ------------------- WGL_EXT_create_context_es2_profile ------------------ */
+
+#if !defined(WGL_EXT_create_context_es2_profile)
+#define WGL_EXT_create_context_es2_profile 1
+
+#define WGL_CONTEXT_ES_PROFILE_BIT_EXT 0x00000004
+#define WGL_CONTEXT_ES2_PROFILE_BIT_EXT 0x00000004
+
+#define WGLEW_EXT_create_context_es2_profile WGLEW_GET_VAR(__WGLEW_EXT_create_context_es2_profile)
+
+#endif /* !WGL_EXT_create_context_es2_profile */
+
+/* ------------------- WGL_EXT_create_context_es_profile ------------------- */
+
+#if !defined(WGL_EXT_create_context_es_profile)
+#define WGL_EXT_create_context_es_profile 1
+
+#define WGL_CONTEXT_ES_PROFILE_BIT_EXT 0x00000004
+#define WGL_CONTEXT_ES2_PROFILE_BIT_EXT 0x00000004
+
+#define WGLEW_EXT_create_context_es_profile WGLEW_GET_VAR(__WGLEW_EXT_create_context_es_profile)
+
+#endif /* !WGL_EXT_create_context_es_profile */
+
+/* -------------------------- WGL_EXT_depth_float -------------------------- */
+
+#if !defined(WGL_EXT_depth_float)
+#define WGL_EXT_depth_float 1
+
+#define WGL_DEPTH_FLOAT_EXT 0x2040
+
+#define WGLEW_EXT_depth_float WGLEW_GET_VAR(__WGLEW_EXT_depth_float)
+
+#endif /* !WGL_EXT_depth_float */
+
+/* ---------------------- WGL_EXT_display_color_table ---------------------- */
+
+#if !defined(WGL_EXT_display_color_table)
+#define WGL_EXT_display_color_table 1
+
+typedef GLboolean (WINAPI * PFNWGLBINDDISPLAYCOLORTABLEEXTPROC) (GLushort id);
+typedef GLboolean (WINAPI * PFNWGLCREATEDISPLAYCOLORTABLEEXTPROC) (GLushort id);
+typedef void (WINAPI * PFNWGLDESTROYDISPLAYCOLORTABLEEXTPROC) (GLushort id);
+typedef GLboolean (WINAPI * PFNWGLLOADDISPLAYCOLORTABLEEXTPROC) (GLushort* table, GLuint length);
+
+#define wglBindDisplayColorTableEXT WGLEW_GET_FUN(__wglewBindDisplayColorTableEXT)
+#define wglCreateDisplayColorTableEXT WGLEW_GET_FUN(__wglewCreateDisplayColorTableEXT)
+#define wglDestroyDisplayColorTableEXT WGLEW_GET_FUN(__wglewDestroyDisplayColorTableEXT)
+#define wglLoadDisplayColorTableEXT WGLEW_GET_FUN(__wglewLoadDisplayColorTableEXT)
+
+#define WGLEW_EXT_display_color_table WGLEW_GET_VAR(__WGLEW_EXT_display_color_table)
+
+#endif /* !WGL_EXT_display_color_table */
+
+/* ----------------------- WGL_EXT_extensions_string ----------------------- */
+
+#if !defined(WGL_EXT_extensions_string)
+#define WGL_EXT_extensions_string 1
+
+typedef const char* (WINAPI * PFNWGLGETEXTENSIONSSTRINGEXTPROC) (void);
+
+#define wglGetExtensionsStringEXT WGLEW_GET_FUN(__wglewGetExtensionsStringEXT)
+
+#define WGLEW_EXT_extensions_string WGLEW_GET_VAR(__WGLEW_EXT_extensions_string)
+
+#endif /* !WGL_EXT_extensions_string */
+
+/* ------------------------ WGL_EXT_framebuffer_sRGB ----------------------- */
+
+#if !defined(WGL_EXT_framebuffer_sRGB)
+#define WGL_EXT_framebuffer_sRGB 1
+
+#define WGL_FRAMEBUFFER_SRGB_CAPABLE_EXT 0x20A9
+
+#define WGLEW_EXT_framebuffer_sRGB WGLEW_GET_VAR(__WGLEW_EXT_framebuffer_sRGB)
+
+#endif /* !WGL_EXT_framebuffer_sRGB */
+
+/* ----------------------- WGL_EXT_make_current_read ----------------------- */
+
+#if !defined(WGL_EXT_make_current_read)
+#define WGL_EXT_make_current_read 1
+
+#define ERROR_INVALID_PIXEL_TYPE_EXT 0x2043
+
+typedef HDC (WINAPI * PFNWGLGETCURRENTREADDCEXTPROC) (VOID);
+typedef BOOL (WINAPI * PFNWGLMAKECONTEXTCURRENTEXTPROC) (HDC hDrawDC, HDC hReadDC, HGLRC hglrc);
+
+#define wglGetCurrentReadDCEXT WGLEW_GET_FUN(__wglewGetCurrentReadDCEXT)
+#define wglMakeContextCurrentEXT WGLEW_GET_FUN(__wglewMakeContextCurrentEXT)
+
+#define WGLEW_EXT_make_current_read WGLEW_GET_VAR(__WGLEW_EXT_make_current_read)
+
+#endif /* !WGL_EXT_make_current_read */
+
+/* -------------------------- WGL_EXT_multisample -------------------------- */
+
+#if !defined(WGL_EXT_multisample)
+#define WGL_EXT_multisample 1
+
+#define WGL_SAMPLE_BUFFERS_EXT 0x2041
+#define WGL_SAMPLES_EXT 0x2042
+
+#define WGLEW_EXT_multisample WGLEW_GET_VAR(__WGLEW_EXT_multisample)
+
+#endif /* !WGL_EXT_multisample */
+
+/* ---------------------------- WGL_EXT_pbuffer ---------------------------- */
+
+#if !defined(WGL_EXT_pbuffer)
+#define WGL_EXT_pbuffer 1
+
+#define WGL_DRAW_TO_PBUFFER_EXT 0x202D
+#define WGL_MAX_PBUFFER_PIXELS_EXT 0x202E
+#define WGL_MAX_PBUFFER_WIDTH_EXT 0x202F
+#define WGL_MAX_PBUFFER_HEIGHT_EXT 0x2030
+#define WGL_OPTIMAL_PBUFFER_WIDTH_EXT 0x2031
+#define WGL_OPTIMAL_PBUFFER_HEIGHT_EXT 0x2032
+#define WGL_PBUFFER_LARGEST_EXT 0x2033
+#define WGL_PBUFFER_WIDTH_EXT 0x2034
+#define WGL_PBUFFER_HEIGHT_EXT 0x2035
+
+DECLARE_HANDLE(HPBUFFEREXT);
+
+typedef HPBUFFEREXT (WINAPI * PFNWGLCREATEPBUFFEREXTPROC) (HDC hDC, int iPixelFormat, int iWidth, int iHeight, const int* piAttribList);
+typedef BOOL (WINAPI * PFNWGLDESTROYPBUFFEREXTPROC) (HPBUFFEREXT hPbuffer);
+typedef HDC (WINAPI * PFNWGLGETPBUFFERDCEXTPROC) (HPBUFFEREXT hPbuffer);
+typedef BOOL (WINAPI * PFNWGLQUERYPBUFFEREXTPROC) (HPBUFFEREXT hPbuffer, int iAttribute, int* piValue);
+typedef int (WINAPI * PFNWGLRELEASEPBUFFERDCEXTPROC) (HPBUFFEREXT hPbuffer, HDC hDC);
+
+#define wglCreatePbufferEXT WGLEW_GET_FUN(__wglewCreatePbufferEXT)
+#define wglDestroyPbufferEXT WGLEW_GET_FUN(__wglewDestroyPbufferEXT)
+#define wglGetPbufferDCEXT WGLEW_GET_FUN(__wglewGetPbufferDCEXT)
+#define wglQueryPbufferEXT WGLEW_GET_FUN(__wglewQueryPbufferEXT)
+#define wglReleasePbufferDCEXT WGLEW_GET_FUN(__wglewReleasePbufferDCEXT)
+
+#define WGLEW_EXT_pbuffer WGLEW_GET_VAR(__WGLEW_EXT_pbuffer)
+
+#endif /* !WGL_EXT_pbuffer */
+
+/* -------------------------- WGL_EXT_pixel_format ------------------------- */
+
+#if !defined(WGL_EXT_pixel_format)
+#define WGL_EXT_pixel_format 1
+
+#define WGL_NUMBER_PIXEL_FORMATS_EXT 0x2000
+#define WGL_DRAW_TO_WINDOW_EXT 0x2001
+#define WGL_DRAW_TO_BITMAP_EXT 0x2002
+#define WGL_ACCELERATION_EXT 0x2003
+#define WGL_NEED_PALETTE_EXT 0x2004
+#define WGL_NEED_SYSTEM_PALETTE_EXT 0x2005
+#define WGL_SWAP_LAYER_BUFFERS_EXT 0x2006
+#define WGL_SWAP_METHOD_EXT 0x2007
+#define WGL_NUMBER_OVERLAYS_EXT 0x2008
+#define WGL_NUMBER_UNDERLAYS_EXT 0x2009
+#define WGL_TRANSPARENT_EXT 0x200A
+#define WGL_TRANSPARENT_VALUE_EXT 0x200B
+#define WGL_SHARE_DEPTH_EXT 0x200C
+#define WGL_SHARE_STENCIL_EXT 0x200D
+#define WGL_SHARE_ACCUM_EXT 0x200E
+#define WGL_SUPPORT_GDI_EXT 0x200F
+#define WGL_SUPPORT_OPENGL_EXT 0x2010
+#define WGL_DOUBLE_BUFFER_EXT 0x2011
+#define WGL_STEREO_EXT 0x2012
+#define WGL_PIXEL_TYPE_EXT 0x2013
+#define WGL_COLOR_BITS_EXT 0x2014
+#define WGL_RED_BITS_EXT 0x2015
+#define WGL_RED_SHIFT_EXT 0x2016
+#define WGL_GREEN_BITS_EXT 0x2017
+#define WGL_GREEN_SHIFT_EXT 0x2018
+#define WGL_BLUE_BITS_EXT 0x2019
+#define WGL_BLUE_SHIFT_EXT 0x201A
+#define WGL_ALPHA_BITS_EXT 0x201B
+#define WGL_ALPHA_SHIFT_EXT 0x201C
+#define WGL_ACCUM_BITS_EXT 0x201D
+#define WGL_ACCUM_RED_BITS_EXT 0x201E
+#define WGL_ACCUM_GREEN_BITS_EXT 0x201F
+#define WGL_ACCUM_BLUE_BITS_EXT 0x2020
+#define WGL_ACCUM_ALPHA_BITS_EXT 0x2021
+#define WGL_DEPTH_BITS_EXT 0x2022
+#define WGL_STENCIL_BITS_EXT 0x2023
+#define WGL_AUX_BUFFERS_EXT 0x2024
+#define WGL_NO_ACCELERATION_EXT 0x2025
+#define WGL_GENERIC_ACCELERATION_EXT 0x2026
+#define WGL_FULL_ACCELERATION_EXT 0x2027
+#define WGL_SWAP_EXCHANGE_EXT 0x2028
+#define WGL_SWAP_COPY_EXT 0x2029
+#define WGL_SWAP_UNDEFINED_EXT 0x202A
+#define WGL_TYPE_RGBA_EXT 0x202B
+#define WGL_TYPE_COLORINDEX_EXT 0x202C
+
+typedef BOOL (WINAPI * PFNWGLCHOOSEPIXELFORMATEXTPROC) (HDC hdc, const int* piAttribIList, const FLOAT *pfAttribFList, UINT nMaxFormats, int *piFormats, UINT *nNumFormats);
+typedef BOOL (WINAPI * PFNWGLGETPIXELFORMATATTRIBFVEXTPROC) (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, int* piAttributes, FLOAT *pfValues);
+typedef BOOL (WINAPI * PFNWGLGETPIXELFORMATATTRIBIVEXTPROC) (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, int* piAttributes, int *piValues);
+
+#define wglChoosePixelFormatEXT WGLEW_GET_FUN(__wglewChoosePixelFormatEXT)
+#define wglGetPixelFormatAttribfvEXT WGLEW_GET_FUN(__wglewGetPixelFormatAttribfvEXT)
+#define wglGetPixelFormatAttribivEXT WGLEW_GET_FUN(__wglewGetPixelFormatAttribivEXT)
+
+#define WGLEW_EXT_pixel_format WGLEW_GET_VAR(__WGLEW_EXT_pixel_format)
+
+#endif /* !WGL_EXT_pixel_format */
+
+/* ------------------- WGL_EXT_pixel_format_packed_float ------------------- */
+
+#if !defined(WGL_EXT_pixel_format_packed_float)
+#define WGL_EXT_pixel_format_packed_float 1
+
+#define WGL_TYPE_RGBA_UNSIGNED_FLOAT_EXT 0x20A8
+
+#define WGLEW_EXT_pixel_format_packed_float WGLEW_GET_VAR(__WGLEW_EXT_pixel_format_packed_float)
+
+#endif /* !WGL_EXT_pixel_format_packed_float */
+
+/* -------------------------- WGL_EXT_swap_control ------------------------- */
+
+#if !defined(WGL_EXT_swap_control)
+#define WGL_EXT_swap_control 1
+
+typedef int (WINAPI * PFNWGLGETSWAPINTERVALEXTPROC) (void);
+typedef BOOL (WINAPI * PFNWGLSWAPINTERVALEXTPROC) (int interval);
+
+#define wglGetSwapIntervalEXT WGLEW_GET_FUN(__wglewGetSwapIntervalEXT)
+#define wglSwapIntervalEXT WGLEW_GET_FUN(__wglewSwapIntervalEXT)
+
+#define WGLEW_EXT_swap_control WGLEW_GET_VAR(__WGLEW_EXT_swap_control)
+
+#endif /* !WGL_EXT_swap_control */
+
+/* ----------------------- WGL_EXT_swap_control_tear ----------------------- */
+
+#if !defined(WGL_EXT_swap_control_tear)
+#define WGL_EXT_swap_control_tear 1
+
+#define WGLEW_EXT_swap_control_tear WGLEW_GET_VAR(__WGLEW_EXT_swap_control_tear)
+
+#endif /* !WGL_EXT_swap_control_tear */
+
+/* --------------------- WGL_I3D_digital_video_control --------------------- */
+
+#if !defined(WGL_I3D_digital_video_control)
+#define WGL_I3D_digital_video_control 1
+
+#define WGL_DIGITAL_VIDEO_CURSOR_ALPHA_FRAMEBUFFER_I3D 0x2050
+#define WGL_DIGITAL_VIDEO_CURSOR_ALPHA_VALUE_I3D 0x2051
+#define WGL_DIGITAL_VIDEO_CURSOR_INCLUDED_I3D 0x2052
+#define WGL_DIGITAL_VIDEO_GAMMA_CORRECTED_I3D 0x2053
+
+typedef BOOL (WINAPI * PFNWGLGETDIGITALVIDEOPARAMETERSI3DPROC) (HDC hDC, int iAttribute, int* piValue);
+typedef BOOL (WINAPI * PFNWGLSETDIGITALVIDEOPARAMETERSI3DPROC) (HDC hDC, int iAttribute, const int* piValue);
+
+#define wglGetDigitalVideoParametersI3D WGLEW_GET_FUN(__wglewGetDigitalVideoParametersI3D)
+#define wglSetDigitalVideoParametersI3D WGLEW_GET_FUN(__wglewSetDigitalVideoParametersI3D)
+
+#define WGLEW_I3D_digital_video_control WGLEW_GET_VAR(__WGLEW_I3D_digital_video_control)
+
+#endif /* !WGL_I3D_digital_video_control */
+
+/* ----------------------------- WGL_I3D_gamma ----------------------------- */
+
+#if !defined(WGL_I3D_gamma)
+#define WGL_I3D_gamma 1
+
+#define WGL_GAMMA_TABLE_SIZE_I3D 0x204E
+#define WGL_GAMMA_EXCLUDE_DESKTOP_I3D 0x204F
+
+typedef BOOL (WINAPI * PFNWGLGETGAMMATABLEI3DPROC) (HDC hDC, int iEntries, USHORT* puRed, USHORT *puGreen, USHORT *puBlue);
+typedef BOOL (WINAPI * PFNWGLGETGAMMATABLEPARAMETERSI3DPROC) (HDC hDC, int iAttribute, int* piValue);
+typedef BOOL (WINAPI * PFNWGLSETGAMMATABLEI3DPROC) (HDC hDC, int iEntries, const USHORT* puRed, const USHORT *puGreen, const USHORT *puBlue);
+typedef BOOL (WINAPI * PFNWGLSETGAMMATABLEPARAMETERSI3DPROC) (HDC hDC, int iAttribute, const int* piValue);
+
+#define wglGetGammaTableI3D WGLEW_GET_FUN(__wglewGetGammaTableI3D)
+#define wglGetGammaTableParametersI3D WGLEW_GET_FUN(__wglewGetGammaTableParametersI3D)
+#define wglSetGammaTableI3D WGLEW_GET_FUN(__wglewSetGammaTableI3D)
+#define wglSetGammaTableParametersI3D WGLEW_GET_FUN(__wglewSetGammaTableParametersI3D)
+
+#define WGLEW_I3D_gamma WGLEW_GET_VAR(__WGLEW_I3D_gamma)
+
+#endif /* !WGL_I3D_gamma */
+
+/* ---------------------------- WGL_I3D_genlock ---------------------------- */
+
+#if !defined(WGL_I3D_genlock)
+#define WGL_I3D_genlock 1
+
+#define WGL_GENLOCK_SOURCE_MULTIVIEW_I3D 0x2044
+#define WGL_GENLOCK_SOURCE_EXTERNAL_SYNC_I3D 0x2045
+#define WGL_GENLOCK_SOURCE_EXTERNAL_FIELD_I3D 0x2046
+#define WGL_GENLOCK_SOURCE_EXTERNAL_TTL_I3D 0x2047
+#define WGL_GENLOCK_SOURCE_DIGITAL_SYNC_I3D 0x2048
+#define WGL_GENLOCK_SOURCE_DIGITAL_FIELD_I3D 0x2049
+#define WGL_GENLOCK_SOURCE_EDGE_FALLING_I3D 0x204A
+#define WGL_GENLOCK_SOURCE_EDGE_RISING_I3D 0x204B
+#define WGL_GENLOCK_SOURCE_EDGE_BOTH_I3D 0x204C
+
+typedef BOOL (WINAPI * PFNWGLDISABLEGENLOCKI3DPROC) (HDC hDC);
+typedef BOOL (WINAPI * PFNWGLENABLEGENLOCKI3DPROC) (HDC hDC);
+typedef BOOL (WINAPI * PFNWGLGENLOCKSAMPLERATEI3DPROC) (HDC hDC, UINT uRate);
+typedef BOOL (WINAPI * PFNWGLGENLOCKSOURCEDELAYI3DPROC) (HDC hDC, UINT uDelay);
+typedef BOOL (WINAPI * PFNWGLGENLOCKSOURCEEDGEI3DPROC) (HDC hDC, UINT uEdge);
+typedef BOOL (WINAPI * PFNWGLGENLOCKSOURCEI3DPROC) (HDC hDC, UINT uSource);
+typedef BOOL (WINAPI * PFNWGLGETGENLOCKSAMPLERATEI3DPROC) (HDC hDC, UINT* uRate);
+typedef BOOL (WINAPI * PFNWGLGETGENLOCKSOURCEDELAYI3DPROC) (HDC hDC, UINT* uDelay);
+typedef BOOL (WINAPI * PFNWGLGETGENLOCKSOURCEEDGEI3DPROC) (HDC hDC, UINT* uEdge);
+typedef BOOL (WINAPI * PFNWGLGETGENLOCKSOURCEI3DPROC) (HDC hDC, UINT* uSource);
+typedef BOOL (WINAPI * PFNWGLISENABLEDGENLOCKI3DPROC) (HDC hDC, BOOL* pFlag);
+typedef BOOL (WINAPI * PFNWGLQUERYGENLOCKMAXSOURCEDELAYI3DPROC) (HDC hDC, UINT* uMaxLineDelay, UINT *uMaxPixelDelay);
+
+#define wglDisableGenlockI3D WGLEW_GET_FUN(__wglewDisableGenlockI3D)
+#define wglEnableGenlockI3D WGLEW_GET_FUN(__wglewEnableGenlockI3D)
+#define wglGenlockSampleRateI3D WGLEW_GET_FUN(__wglewGenlockSampleRateI3D)
+#define wglGenlockSourceDelayI3D WGLEW_GET_FUN(__wglewGenlockSourceDelayI3D)
+#define wglGenlockSourceEdgeI3D WGLEW_GET_FUN(__wglewGenlockSourceEdgeI3D)
+#define wglGenlockSourceI3D WGLEW_GET_FUN(__wglewGenlockSourceI3D)
+#define wglGetGenlockSampleRateI3D WGLEW_GET_FUN(__wglewGetGenlockSampleRateI3D)
+#define wglGetGenlockSourceDelayI3D WGLEW_GET_FUN(__wglewGetGenlockSourceDelayI3D)
+#define wglGetGenlockSourceEdgeI3D WGLEW_GET_FUN(__wglewGetGenlockSourceEdgeI3D)
+#define wglGetGenlockSourceI3D WGLEW_GET_FUN(__wglewGetGenlockSourceI3D)
+#define wglIsEnabledGenlockI3D WGLEW_GET_FUN(__wglewIsEnabledGenlockI3D)
+#define wglQueryGenlockMaxSourceDelayI3D WGLEW_GET_FUN(__wglewQueryGenlockMaxSourceDelayI3D)
+
+#define WGLEW_I3D_genlock WGLEW_GET_VAR(__WGLEW_I3D_genlock)
+
+#endif /* !WGL_I3D_genlock */
+
+/* -------------------------- WGL_I3D_image_buffer ------------------------- */
+
+#if !defined(WGL_I3D_image_buffer)
+#define WGL_I3D_image_buffer 1
+
+#define WGL_IMAGE_BUFFER_MIN_ACCESS_I3D 0x00000001
+#define WGL_IMAGE_BUFFER_LOCK_I3D 0x00000002
+
+typedef BOOL (WINAPI * PFNWGLASSOCIATEIMAGEBUFFEREVENTSI3DPROC) (HDC hdc, HANDLE* pEvent, LPVOID *pAddress, DWORD *pSize, UINT count);
+typedef LPVOID (WINAPI * PFNWGLCREATEIMAGEBUFFERI3DPROC) (HDC hDC, DWORD dwSize, UINT uFlags);
+typedef BOOL (WINAPI * PFNWGLDESTROYIMAGEBUFFERI3DPROC) (HDC hDC, LPVOID pAddress);
+typedef BOOL (WINAPI * PFNWGLRELEASEIMAGEBUFFEREVENTSI3DPROC) (HDC hdc, LPVOID* pAddress, UINT count);
+
+#define wglAssociateImageBufferEventsI3D WGLEW_GET_FUN(__wglewAssociateImageBufferEventsI3D)
+#define wglCreateImageBufferI3D WGLEW_GET_FUN(__wglewCreateImageBufferI3D)
+#define wglDestroyImageBufferI3D WGLEW_GET_FUN(__wglewDestroyImageBufferI3D)
+#define wglReleaseImageBufferEventsI3D WGLEW_GET_FUN(__wglewReleaseImageBufferEventsI3D)
+
+#define WGLEW_I3D_image_buffer WGLEW_GET_VAR(__WGLEW_I3D_image_buffer)
+
+#endif /* !WGL_I3D_image_buffer */
+
+/* ------------------------ WGL_I3D_swap_frame_lock ------------------------ */
+
+#if !defined(WGL_I3D_swap_frame_lock)
+#define WGL_I3D_swap_frame_lock 1
+
+typedef BOOL (WINAPI * PFNWGLDISABLEFRAMELOCKI3DPROC) (VOID);
+typedef BOOL (WINAPI * PFNWGLENABLEFRAMELOCKI3DPROC) (VOID);
+typedef BOOL (WINAPI * PFNWGLISENABLEDFRAMELOCKI3DPROC) (BOOL* pFlag);
+typedef BOOL (WINAPI * PFNWGLQUERYFRAMELOCKMASTERI3DPROC) (BOOL* pFlag);
+
+#define wglDisableFrameLockI3D WGLEW_GET_FUN(__wglewDisableFrameLockI3D)
+#define wglEnableFrameLockI3D WGLEW_GET_FUN(__wglewEnableFrameLockI3D)
+#define wglIsEnabledFrameLockI3D WGLEW_GET_FUN(__wglewIsEnabledFrameLockI3D)
+#define wglQueryFrameLockMasterI3D WGLEW_GET_FUN(__wglewQueryFrameLockMasterI3D)
+
+#define WGLEW_I3D_swap_frame_lock WGLEW_GET_VAR(__WGLEW_I3D_swap_frame_lock)
+
+#endif /* !WGL_I3D_swap_frame_lock */
+
+/* ------------------------ WGL_I3D_swap_frame_usage ----------------------- */
+
+#if !defined(WGL_I3D_swap_frame_usage)
+#define WGL_I3D_swap_frame_usage 1
+
+typedef BOOL (WINAPI * PFNWGLBEGINFRAMETRACKINGI3DPROC) (void);
+typedef BOOL (WINAPI * PFNWGLENDFRAMETRACKINGI3DPROC) (void);
+typedef BOOL (WINAPI * PFNWGLGETFRAMEUSAGEI3DPROC) (float* pUsage);
+typedef BOOL (WINAPI * PFNWGLQUERYFRAMETRACKINGI3DPROC) (DWORD* pFrameCount, DWORD *pMissedFrames, float *pLastMissedUsage);
+
+#define wglBeginFrameTrackingI3D WGLEW_GET_FUN(__wglewBeginFrameTrackingI3D)
+#define wglEndFrameTrackingI3D WGLEW_GET_FUN(__wglewEndFrameTrackingI3D)
+#define wglGetFrameUsageI3D WGLEW_GET_FUN(__wglewGetFrameUsageI3D)
+#define wglQueryFrameTrackingI3D WGLEW_GET_FUN(__wglewQueryFrameTrackingI3D)
+
+#define WGLEW_I3D_swap_frame_usage WGLEW_GET_VAR(__WGLEW_I3D_swap_frame_usage)
+
+#endif /* !WGL_I3D_swap_frame_usage */
+
+/* --------------------------- WGL_NV_DX_interop --------------------------- */
+
+#if !defined(WGL_NV_DX_interop)
+#define WGL_NV_DX_interop 1
+
+#define WGL_ACCESS_READ_ONLY_NV 0x0000
+#define WGL_ACCESS_READ_WRITE_NV 0x0001
+#define WGL_ACCESS_WRITE_DISCARD_NV 0x0002
+
+typedef BOOL (WINAPI * PFNWGLDXCLOSEDEVICENVPROC) (HANDLE hDevice);
+typedef BOOL (WINAPI * PFNWGLDXLOCKOBJECTSNVPROC) (HANDLE hDevice, GLint count, HANDLE* hObjects);
+typedef BOOL (WINAPI * PFNWGLDXOBJECTACCESSNVPROC) (HANDLE hObject, GLenum access);
+typedef HANDLE (WINAPI * PFNWGLDXOPENDEVICENVPROC) (void* dxDevice);
+typedef HANDLE (WINAPI * PFNWGLDXREGISTEROBJECTNVPROC) (HANDLE hDevice, void* dxObject, GLuint name, GLenum type, GLenum access);
+typedef BOOL (WINAPI * PFNWGLDXSETRESOURCESHAREHANDLENVPROC) (void* dxObject, HANDLE shareHandle);
+typedef BOOL (WINAPI * PFNWGLDXUNLOCKOBJECTSNVPROC) (HANDLE hDevice, GLint count, HANDLE* hObjects);
+typedef BOOL (WINAPI * PFNWGLDXUNREGISTEROBJECTNVPROC) (HANDLE hDevice, HANDLE hObject);
+
+#define wglDXCloseDeviceNV WGLEW_GET_FUN(__wglewDXCloseDeviceNV)
+#define wglDXLockObjectsNV WGLEW_GET_FUN(__wglewDXLockObjectsNV)
+#define wglDXObjectAccessNV WGLEW_GET_FUN(__wglewDXObjectAccessNV)
+#define wglDXOpenDeviceNV WGLEW_GET_FUN(__wglewDXOpenDeviceNV)
+#define wglDXRegisterObjectNV WGLEW_GET_FUN(__wglewDXRegisterObjectNV)
+#define wglDXSetResourceShareHandleNV WGLEW_GET_FUN(__wglewDXSetResourceShareHandleNV)
+#define wglDXUnlockObjectsNV WGLEW_GET_FUN(__wglewDXUnlockObjectsNV)
+#define wglDXUnregisterObjectNV WGLEW_GET_FUN(__wglewDXUnregisterObjectNV)
+
+#define WGLEW_NV_DX_interop WGLEW_GET_VAR(__WGLEW_NV_DX_interop)
+
+#endif /* !WGL_NV_DX_interop */
+
+/* --------------------------- WGL_NV_DX_interop2 -------------------------- */
+
+#if !defined(WGL_NV_DX_interop2)
+#define WGL_NV_DX_interop2 1
+
+#define WGLEW_NV_DX_interop2 WGLEW_GET_VAR(__WGLEW_NV_DX_interop2)
+
+#endif /* !WGL_NV_DX_interop2 */
+
+/* --------------------------- WGL_NV_copy_image --------------------------- */
+
+#if !defined(WGL_NV_copy_image)
+#define WGL_NV_copy_image 1
+
+typedef BOOL (WINAPI * PFNWGLCOPYIMAGESUBDATANVPROC) (HGLRC hSrcRC, GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, HGLRC hDstRC, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei width, GLsizei height, GLsizei depth);
+
+#define wglCopyImageSubDataNV WGLEW_GET_FUN(__wglewCopyImageSubDataNV)
+
+#define WGLEW_NV_copy_image WGLEW_GET_VAR(__WGLEW_NV_copy_image)
+
+#endif /* !WGL_NV_copy_image */
+
+/* -------------------------- WGL_NV_float_buffer -------------------------- */
+
+#if !defined(WGL_NV_float_buffer)
+#define WGL_NV_float_buffer 1
+
+#define WGL_FLOAT_COMPONENTS_NV 0x20B0
+#define WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_R_NV 0x20B1
+#define WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RG_NV 0x20B2
+#define WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RGB_NV 0x20B3
+#define WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RGBA_NV 0x20B4
+#define WGL_TEXTURE_FLOAT_R_NV 0x20B5
+#define WGL_TEXTURE_FLOAT_RG_NV 0x20B6
+#define WGL_TEXTURE_FLOAT_RGB_NV 0x20B7
+#define WGL_TEXTURE_FLOAT_RGBA_NV 0x20B8
+
+#define WGLEW_NV_float_buffer WGLEW_GET_VAR(__WGLEW_NV_float_buffer)
+
+#endif /* !WGL_NV_float_buffer */
+
+/* -------------------------- WGL_NV_gpu_affinity -------------------------- */
+
+#if !defined(WGL_NV_gpu_affinity)
+#define WGL_NV_gpu_affinity 1
+
+#define ERROR_INCOMPATIBLE_AFFINITY_MASKS_NV 0x20D0 // NOTE jwilkins: incorrect name
+#define ERROR_MISSING_AFFINITY_MASK_NV 0x20D1 // NOTE jwilkins: incorrect name
+
+DECLARE_HANDLE(HGPUNV);
+typedef struct _GPU_DEVICE {
+ DWORD cb;
+ CHAR DeviceName[32];
+ CHAR DeviceString[128];
+ DWORD Flags;
+ RECT rcVirtualScreen;
+} GPU_DEVICE, *PGPU_DEVICE;
+
+typedef HDC (WINAPI * PFNWGLCREATEAFFINITYDCNVPROC) (const HGPUNV *phGpuList);
+typedef BOOL (WINAPI * PFNWGLDELETEDCNVPROC) (HDC hdc);
+typedef BOOL (WINAPI * PFNWGLENUMGPUDEVICESNVPROC) (HGPUNV hGpu, UINT iDeviceIndex, PGPU_DEVICE lpGpuDevice);
+typedef BOOL (WINAPI * PFNWGLENUMGPUSFROMAFFINITYDCNVPROC) (HDC hAffinityDC, UINT iGpuIndex, HGPUNV *hGpu);
+typedef BOOL (WINAPI * PFNWGLENUMGPUSNVPROC) (UINT iGpuIndex, HGPUNV *phGpu);
+
+#define wglCreateAffinityDCNV WGLEW_GET_FUN(__wglewCreateAffinityDCNV)
+#define wglDeleteDCNV WGLEW_GET_FUN(__wglewDeleteDCNV)
+#define wglEnumGpuDevicesNV WGLEW_GET_FUN(__wglewEnumGpuDevicesNV)
+#define wglEnumGpusFromAffinityDCNV WGLEW_GET_FUN(__wglewEnumGpusFromAffinityDCNV)
+#define wglEnumGpusNV WGLEW_GET_FUN(__wglewEnumGpusNV)
+
+#define WGLEW_NV_gpu_affinity WGLEW_GET_VAR(__WGLEW_NV_gpu_affinity)
+
+#endif /* !WGL_NV_gpu_affinity */
+
+/* ---------------------- WGL_NV_multisample_coverage ---------------------- */
+
+#if !defined(WGL_NV_multisample_coverage)
+#define WGL_NV_multisample_coverage 1
+
+#define WGL_COVERAGE_SAMPLES_NV 0x2042
+#define WGL_COLOR_SAMPLES_NV 0x20B9
+
+#define WGLEW_NV_multisample_coverage WGLEW_GET_VAR(__WGLEW_NV_multisample_coverage)
+
+#endif /* !WGL_NV_multisample_coverage */
+
+/* -------------------------- WGL_NV_present_video ------------------------- */
+
+#if !defined(WGL_NV_present_video)
+#define WGL_NV_present_video 1
+
+#define WGL_NUM_VIDEO_SLOTS_NV 0x20F0
+
+DECLARE_HANDLE(HVIDEOOUTPUTDEVICENV);
+
+typedef BOOL (WINAPI * PFNWGLBINDVIDEODEVICENVPROC) (HDC hDc, unsigned int uVideoSlot, HVIDEOOUTPUTDEVICENV hVideoDevice, const int* piAttribList);
+typedef int (WINAPI * PFNWGLENUMERATEVIDEODEVICESNVPROC) (HDC hDc, HVIDEOOUTPUTDEVICENV* phDeviceList);
+typedef BOOL (WINAPI * PFNWGLQUERYCURRENTCONTEXTNVPROC) (int iAttribute, int* piValue);
+
+#define wglBindVideoDeviceNV WGLEW_GET_FUN(__wglewBindVideoDeviceNV)
+#define wglEnumerateVideoDevicesNV WGLEW_GET_FUN(__wglewEnumerateVideoDevicesNV)
+#define wglQueryCurrentContextNV WGLEW_GET_FUN(__wglewQueryCurrentContextNV)
+
+#define WGLEW_NV_present_video WGLEW_GET_VAR(__WGLEW_NV_present_video)
+
+#endif /* !WGL_NV_present_video */
+
+/* ---------------------- WGL_NV_render_depth_texture ---------------------- */
+
+#if !defined(WGL_NV_render_depth_texture)
+#define WGL_NV_render_depth_texture 1
+
+#define WGL_NO_TEXTURE_ARB 0x2077
+#define WGL_BIND_TO_TEXTURE_DEPTH_NV 0x20A3
+#define WGL_BIND_TO_TEXTURE_RECTANGLE_DEPTH_NV 0x20A4
+#define WGL_DEPTH_TEXTURE_FORMAT_NV 0x20A5
+#define WGL_TEXTURE_DEPTH_COMPONENT_NV 0x20A6
+#define WGL_DEPTH_COMPONENT_NV 0x20A7
+
+#define WGLEW_NV_render_depth_texture WGLEW_GET_VAR(__WGLEW_NV_render_depth_texture)
+
+#endif /* !WGL_NV_render_depth_texture */
+
+/* -------------------- WGL_NV_render_texture_rectangle -------------------- */
+
+#if !defined(WGL_NV_render_texture_rectangle)
+#define WGL_NV_render_texture_rectangle 1
+
+#define WGL_BIND_TO_TEXTURE_RECTANGLE_RGB_NV 0x20A0
+#define WGL_BIND_TO_TEXTURE_RECTANGLE_RGBA_NV 0x20A1
+#define WGL_TEXTURE_RECTANGLE_NV 0x20A2
+
+#define WGLEW_NV_render_texture_rectangle WGLEW_GET_VAR(__WGLEW_NV_render_texture_rectangle)
+
+#endif /* !WGL_NV_render_texture_rectangle */
+
+/* --------------------------- WGL_NV_swap_group --------------------------- */
+
+#if !defined(WGL_NV_swap_group)
+#define WGL_NV_swap_group 1
+
+typedef BOOL (WINAPI * PFNWGLBINDSWAPBARRIERNVPROC) (GLuint group, GLuint barrier);
+typedef BOOL (WINAPI * PFNWGLJOINSWAPGROUPNVPROC) (HDC hDC, GLuint group);
+typedef BOOL (WINAPI * PFNWGLQUERYFRAMECOUNTNVPROC) (HDC hDC, GLuint* count);
+typedef BOOL (WINAPI * PFNWGLQUERYMAXSWAPGROUPSNVPROC) (HDC hDC, GLuint* maxGroups, GLuint *maxBarriers);
+typedef BOOL (WINAPI * PFNWGLQUERYSWAPGROUPNVPROC) (HDC hDC, GLuint* group, GLuint *barrier);
+typedef BOOL (WINAPI * PFNWGLRESETFRAMECOUNTNVPROC) (HDC hDC);
+
+#define wglBindSwapBarrierNV WGLEW_GET_FUN(__wglewBindSwapBarrierNV)
+#define wglJoinSwapGroupNV WGLEW_GET_FUN(__wglewJoinSwapGroupNV)
+#define wglQueryFrameCountNV WGLEW_GET_FUN(__wglewQueryFrameCountNV)
+#define wglQueryMaxSwapGroupsNV WGLEW_GET_FUN(__wglewQueryMaxSwapGroupsNV)
+#define wglQuerySwapGroupNV WGLEW_GET_FUN(__wglewQuerySwapGroupNV)
+#define wglResetFrameCountNV WGLEW_GET_FUN(__wglewResetFrameCountNV)
+
+#define WGLEW_NV_swap_group WGLEW_GET_VAR(__WGLEW_NV_swap_group)
+
+#endif /* !WGL_NV_swap_group */
+
+/* ----------------------- WGL_NV_vertex_array_range ----------------------- */
+
+#if !defined(WGL_NV_vertex_array_range)
+#define WGL_NV_vertex_array_range 1
+
+typedef void * (WINAPI * PFNWGLALLOCATEMEMORYNVPROC) (GLsizei size, GLfloat readFrequency, GLfloat writeFrequency, GLfloat priority);
+typedef void (WINAPI * PFNWGLFREEMEMORYNVPROC) (void *pointer);
+
+#define wglAllocateMemoryNV WGLEW_GET_FUN(__wglewAllocateMemoryNV)
+#define wglFreeMemoryNV WGLEW_GET_FUN(__wglewFreeMemoryNV)
+
+#define WGLEW_NV_vertex_array_range WGLEW_GET_VAR(__WGLEW_NV_vertex_array_range)
+
+#endif /* !WGL_NV_vertex_array_range */
+
+/* -------------------------- WGL_NV_video_capture ------------------------- */
+
+#if !defined(WGL_NV_video_capture)
+#define WGL_NV_video_capture 1
+
+#define WGL_UNIQUE_ID_NV 0x20CE
+#define WGL_NUM_VIDEO_CAPTURE_SLOTS_NV 0x20CF
+
+DECLARE_HANDLE(HVIDEOINPUTDEVICENV);
+
+typedef BOOL (WINAPI * PFNWGLBINDVIDEOCAPTUREDEVICENVPROC) (UINT uVideoSlot, HVIDEOINPUTDEVICENV hDevice);
+typedef UINT (WINAPI * PFNWGLENUMERATEVIDEOCAPTUREDEVICESNVPROC) (HDC hDc, HVIDEOINPUTDEVICENV* phDeviceList);
+typedef BOOL (WINAPI * PFNWGLLOCKVIDEOCAPTUREDEVICENVPROC) (HDC hDc, HVIDEOINPUTDEVICENV hDevice);
+typedef BOOL (WINAPI * PFNWGLQUERYVIDEOCAPTUREDEVICENVPROC) (HDC hDc, HVIDEOINPUTDEVICENV hDevice, int iAttribute, int* piValue);
+typedef BOOL (WINAPI * PFNWGLRELEASEVIDEOCAPTUREDEVICENVPROC) (HDC hDc, HVIDEOINPUTDEVICENV hDevice);
+
+#define wglBindVideoCaptureDeviceNV WGLEW_GET_FUN(__wglewBindVideoCaptureDeviceNV)
+#define wglEnumerateVideoCaptureDevicesNV WGLEW_GET_FUN(__wglewEnumerateVideoCaptureDevicesNV)
+#define wglLockVideoCaptureDeviceNV WGLEW_GET_FUN(__wglewLockVideoCaptureDeviceNV)
+#define wglQueryVideoCaptureDeviceNV WGLEW_GET_FUN(__wglewQueryVideoCaptureDeviceNV)
+#define wglReleaseVideoCaptureDeviceNV WGLEW_GET_FUN(__wglewReleaseVideoCaptureDeviceNV)
+
+#define WGLEW_NV_video_capture WGLEW_GET_VAR(__WGLEW_NV_video_capture)
+
+#endif /* !WGL_NV_video_capture */
+
+/* -------------------------- WGL_NV_video_output -------------------------- */
+
+#if !defined(WGL_NV_video_output)
+#define WGL_NV_video_output 1
+
+#define WGL_BIND_TO_VIDEO_RGB_NV 0x20C0
+#define WGL_BIND_TO_VIDEO_RGBA_NV 0x20C1
+#define WGL_BIND_TO_VIDEO_RGB_AND_DEPTH_NV 0x20C2
+#define WGL_VIDEO_OUT_COLOR_NV 0x20C3
+#define WGL_VIDEO_OUT_ALPHA_NV 0x20C4
+#define WGL_VIDEO_OUT_DEPTH_NV 0x20C5
+#define WGL_VIDEO_OUT_COLOR_AND_ALPHA_NV 0x20C6
+#define WGL_VIDEO_OUT_COLOR_AND_DEPTH_NV 0x20C7
+#define WGL_VIDEO_OUT_FRAME 0x20C8
+#define WGL_VIDEO_OUT_FIELD_1 0x20C9
+#define WGL_VIDEO_OUT_FIELD_2 0x20CA
+#define WGL_VIDEO_OUT_STACKED_FIELDS_1_2 0x20CB
+#define WGL_VIDEO_OUT_STACKED_FIELDS_2_1 0x20CC
+
+DECLARE_HANDLE(HPVIDEODEV);
+
+typedef BOOL (WINAPI * PFNWGLBINDVIDEOIMAGENVPROC) (HPVIDEODEV hVideoDevice, HPBUFFERARB hPbuffer, int iVideoBuffer);
+typedef BOOL (WINAPI * PFNWGLGETVIDEODEVICENVPROC) (HDC hDC, int numDevices, HPVIDEODEV* hVideoDevice);
+typedef BOOL (WINAPI * PFNWGLGETVIDEOINFONVPROC) (HPVIDEODEV hpVideoDevice, unsigned long* pulCounterOutputPbuffer, unsigned long *pulCounterOutputVideo);
+typedef BOOL (WINAPI * PFNWGLRELEASEVIDEODEVICENVPROC) (HPVIDEODEV hVideoDevice);
+typedef BOOL (WINAPI * PFNWGLRELEASEVIDEOIMAGENVPROC) (HPBUFFERARB hPbuffer, int iVideoBuffer);
+typedef BOOL (WINAPI * PFNWGLSENDPBUFFERTOVIDEONVPROC) (HPBUFFERARB hPbuffer, int iBufferType, unsigned long* pulCounterPbuffer, BOOL bBlock);
+
+#define wglBindVideoImageNV WGLEW_GET_FUN(__wglewBindVideoImageNV)
+#define wglGetVideoDeviceNV WGLEW_GET_FUN(__wglewGetVideoDeviceNV)
+#define wglGetVideoInfoNV WGLEW_GET_FUN(__wglewGetVideoInfoNV)
+#define wglReleaseVideoDeviceNV WGLEW_GET_FUN(__wglewReleaseVideoDeviceNV)
+#define wglReleaseVideoImageNV WGLEW_GET_FUN(__wglewReleaseVideoImageNV)
+#define wglSendPbufferToVideoNV WGLEW_GET_FUN(__wglewSendPbufferToVideoNV)
+
+#define WGLEW_NV_video_output WGLEW_GET_VAR(__WGLEW_NV_video_output)
+
+#endif /* !WGL_NV_video_output */
+
+/* -------------------------- WGL_OML_sync_control ------------------------- */
+
+#if !defined(WGL_OML_sync_control)
+#define WGL_OML_sync_control 1
+
+typedef BOOL (WINAPI * PFNWGLGETMSCRATEOMLPROC) (HDC hdc, INT32* numerator, INT32 *denominator);
+typedef BOOL (WINAPI * PFNWGLGETSYNCVALUESOMLPROC) (HDC hdc, INT64* ust, INT64 *msc, INT64 *sbc);
+typedef INT64 (WINAPI * PFNWGLSWAPBUFFERSMSCOMLPROC) (HDC hdc, INT64 target_msc, INT64 divisor, INT64 remainder);
+typedef INT64 (WINAPI * PFNWGLSWAPLAYERBUFFERSMSCOMLPROC) (HDC hdc, INT fuPlanes, INT64 target_msc, INT64 divisor, INT64 remainder);
+typedef BOOL (WINAPI * PFNWGLWAITFORMSCOMLPROC) (HDC hdc, INT64 target_msc, INT64 divisor, INT64 remainder, INT64* ust, INT64 *msc, INT64 *sbc);
+typedef BOOL (WINAPI * PFNWGLWAITFORSBCOMLPROC) (HDC hdc, INT64 target_sbc, INT64* ust, INT64 *msc, INT64 *sbc);
+
+#define wglGetMscRateOML WGLEW_GET_FUN(__wglewGetMscRateOML)
+#define wglGetSyncValuesOML WGLEW_GET_FUN(__wglewGetSyncValuesOML)
+#define wglSwapBuffersMscOML WGLEW_GET_FUN(__wglewSwapBuffersMscOML)
+#define wglSwapLayerBuffersMscOML WGLEW_GET_FUN(__wglewSwapLayerBuffersMscOML)
+#define wglWaitForMscOML WGLEW_GET_FUN(__wglewWaitForMscOML)
+#define wglWaitForSbcOML WGLEW_GET_FUN(__wglewWaitForSbcOML)
+
+#define WGLEW_OML_sync_control WGLEW_GET_VAR(__WGLEW_OML_sync_control)
+
+#endif /* !WGL_OML_sync_control */
+
+/* ------------------------------------------------------------------------- */
+
+#ifdef GLEW_MX
+#define WGLEW_EXPORT
+#else
+#define WGLEW_EXPORT GLEWAPI
+#endif /* GLEW_MX */
+
+#ifdef GLEW_MX
+struct WGLEWContextStruct
+{
+#endif /* GLEW_MX */
+
+WGLEW_EXPORT PFNWGLSETSTEREOEMITTERSTATE3DLPROC __wglewSetStereoEmitterState3DL;
+
+WGLEW_EXPORT PFNWGLBLITCONTEXTFRAMEBUFFERAMDPROC __wglewBlitContextFramebufferAMD;
+WGLEW_EXPORT PFNWGLCREATEASSOCIATEDCONTEXTAMDPROC __wglewCreateAssociatedContextAMD;
+WGLEW_EXPORT PFNWGLCREATEASSOCIATEDCONTEXTATTRIBSAMDPROC __wglewCreateAssociatedContextAttribsAMD;
+WGLEW_EXPORT PFNWGLDELETEASSOCIATEDCONTEXTAMDPROC __wglewDeleteAssociatedContextAMD;
+WGLEW_EXPORT PFNWGLGETCONTEXTGPUIDAMDPROC __wglewGetContextGPUIDAMD;
+WGLEW_EXPORT PFNWGLGETCURRENTASSOCIATEDCONTEXTAMDPROC __wglewGetCurrentAssociatedContextAMD;
+WGLEW_EXPORT PFNWGLGETGPUIDSAMDPROC __wglewGetGPUIDsAMD;
+WGLEW_EXPORT PFNWGLGETGPUINFOAMDPROC __wglewGetGPUInfoAMD;
+WGLEW_EXPORT PFNWGLMAKEASSOCIATEDCONTEXTCURRENTAMDPROC __wglewMakeAssociatedContextCurrentAMD;
+
+WGLEW_EXPORT PFNWGLCREATEBUFFERREGIONARBPROC __wglewCreateBufferRegionARB;
+WGLEW_EXPORT PFNWGLDELETEBUFFERREGIONARBPROC __wglewDeleteBufferRegionARB;
+WGLEW_EXPORT PFNWGLRESTOREBUFFERREGIONARBPROC __wglewRestoreBufferRegionARB;
+WGLEW_EXPORT PFNWGLSAVEBUFFERREGIONARBPROC __wglewSaveBufferRegionARB;
+
+WGLEW_EXPORT PFNWGLCREATECONTEXTATTRIBSARBPROC __wglewCreateContextAttribsARB;
+
+WGLEW_EXPORT PFNWGLGETEXTENSIONSSTRINGARBPROC __wglewGetExtensionsStringARB;
+
+WGLEW_EXPORT PFNWGLGETCURRENTREADDCARBPROC __wglewGetCurrentReadDCARB;
+WGLEW_EXPORT PFNWGLMAKECONTEXTCURRENTARBPROC __wglewMakeContextCurrentARB;
+
+WGLEW_EXPORT PFNWGLCREATEPBUFFERARBPROC __wglewCreatePbufferARB;
+WGLEW_EXPORT PFNWGLDESTROYPBUFFERARBPROC __wglewDestroyPbufferARB;
+WGLEW_EXPORT PFNWGLGETPBUFFERDCARBPROC __wglewGetPbufferDCARB;
+WGLEW_EXPORT PFNWGLQUERYPBUFFERARBPROC __wglewQueryPbufferARB;
+WGLEW_EXPORT PFNWGLRELEASEPBUFFERDCARBPROC __wglewReleasePbufferDCARB;
+
+WGLEW_EXPORT PFNWGLCHOOSEPIXELFORMATARBPROC __wglewChoosePixelFormatARB;
+WGLEW_EXPORT PFNWGLGETPIXELFORMATATTRIBFVARBPROC __wglewGetPixelFormatAttribfvARB;
+WGLEW_EXPORT PFNWGLGETPIXELFORMATATTRIBIVARBPROC __wglewGetPixelFormatAttribivARB;
+
+WGLEW_EXPORT PFNWGLBINDTEXIMAGEARBPROC __wglewBindTexImageARB;
+WGLEW_EXPORT PFNWGLRELEASETEXIMAGEARBPROC __wglewReleaseTexImageARB;
+WGLEW_EXPORT PFNWGLSETPBUFFERATTRIBARBPROC __wglewSetPbufferAttribARB;
+
+WGLEW_EXPORT PFNWGLBINDDISPLAYCOLORTABLEEXTPROC __wglewBindDisplayColorTableEXT;
+WGLEW_EXPORT PFNWGLCREATEDISPLAYCOLORTABLEEXTPROC __wglewCreateDisplayColorTableEXT;
+WGLEW_EXPORT PFNWGLDESTROYDISPLAYCOLORTABLEEXTPROC __wglewDestroyDisplayColorTableEXT;
+WGLEW_EXPORT PFNWGLLOADDISPLAYCOLORTABLEEXTPROC __wglewLoadDisplayColorTableEXT;
+
+WGLEW_EXPORT PFNWGLGETEXTENSIONSSTRINGEXTPROC __wglewGetExtensionsStringEXT;
+
+WGLEW_EXPORT PFNWGLGETCURRENTREADDCEXTPROC __wglewGetCurrentReadDCEXT;
+WGLEW_EXPORT PFNWGLMAKECONTEXTCURRENTEXTPROC __wglewMakeContextCurrentEXT;
+
+WGLEW_EXPORT PFNWGLCREATEPBUFFEREXTPROC __wglewCreatePbufferEXT;
+WGLEW_EXPORT PFNWGLDESTROYPBUFFEREXTPROC __wglewDestroyPbufferEXT;
+WGLEW_EXPORT PFNWGLGETPBUFFERDCEXTPROC __wglewGetPbufferDCEXT;
+WGLEW_EXPORT PFNWGLQUERYPBUFFEREXTPROC __wglewQueryPbufferEXT;
+WGLEW_EXPORT PFNWGLRELEASEPBUFFERDCEXTPROC __wglewReleasePbufferDCEXT;
+
+WGLEW_EXPORT PFNWGLCHOOSEPIXELFORMATEXTPROC __wglewChoosePixelFormatEXT;
+WGLEW_EXPORT PFNWGLGETPIXELFORMATATTRIBFVEXTPROC __wglewGetPixelFormatAttribfvEXT;
+WGLEW_EXPORT PFNWGLGETPIXELFORMATATTRIBIVEXTPROC __wglewGetPixelFormatAttribivEXT;
+
+WGLEW_EXPORT PFNWGLGETSWAPINTERVALEXTPROC __wglewGetSwapIntervalEXT;
+WGLEW_EXPORT PFNWGLSWAPINTERVALEXTPROC __wglewSwapIntervalEXT;
+
+WGLEW_EXPORT PFNWGLGETDIGITALVIDEOPARAMETERSI3DPROC __wglewGetDigitalVideoParametersI3D;
+WGLEW_EXPORT PFNWGLSETDIGITALVIDEOPARAMETERSI3DPROC __wglewSetDigitalVideoParametersI3D;
+
+WGLEW_EXPORT PFNWGLGETGAMMATABLEI3DPROC __wglewGetGammaTableI3D;
+WGLEW_EXPORT PFNWGLGETGAMMATABLEPARAMETERSI3DPROC __wglewGetGammaTableParametersI3D;
+WGLEW_EXPORT PFNWGLSETGAMMATABLEI3DPROC __wglewSetGammaTableI3D;
+WGLEW_EXPORT PFNWGLSETGAMMATABLEPARAMETERSI3DPROC __wglewSetGammaTableParametersI3D;
+
+WGLEW_EXPORT PFNWGLDISABLEGENLOCKI3DPROC __wglewDisableGenlockI3D;
+WGLEW_EXPORT PFNWGLENABLEGENLOCKI3DPROC __wglewEnableGenlockI3D;
+WGLEW_EXPORT PFNWGLGENLOCKSAMPLERATEI3DPROC __wglewGenlockSampleRateI3D;
+WGLEW_EXPORT PFNWGLGENLOCKSOURCEDELAYI3DPROC __wglewGenlockSourceDelayI3D;
+WGLEW_EXPORT PFNWGLGENLOCKSOURCEEDGEI3DPROC __wglewGenlockSourceEdgeI3D;
+WGLEW_EXPORT PFNWGLGENLOCKSOURCEI3DPROC __wglewGenlockSourceI3D;
+WGLEW_EXPORT PFNWGLGETGENLOCKSAMPLERATEI3DPROC __wglewGetGenlockSampleRateI3D;
+WGLEW_EXPORT PFNWGLGETGENLOCKSOURCEDELAYI3DPROC __wglewGetGenlockSourceDelayI3D;
+WGLEW_EXPORT PFNWGLGETGENLOCKSOURCEEDGEI3DPROC __wglewGetGenlockSourceEdgeI3D;
+WGLEW_EXPORT PFNWGLGETGENLOCKSOURCEI3DPROC __wglewGetGenlockSourceI3D;
+WGLEW_EXPORT PFNWGLISENABLEDGENLOCKI3DPROC __wglewIsEnabledGenlockI3D;
+WGLEW_EXPORT PFNWGLQUERYGENLOCKMAXSOURCEDELAYI3DPROC __wglewQueryGenlockMaxSourceDelayI3D;
+
+WGLEW_EXPORT PFNWGLASSOCIATEIMAGEBUFFEREVENTSI3DPROC __wglewAssociateImageBufferEventsI3D;
+WGLEW_EXPORT PFNWGLCREATEIMAGEBUFFERI3DPROC __wglewCreateImageBufferI3D;
+WGLEW_EXPORT PFNWGLDESTROYIMAGEBUFFERI3DPROC __wglewDestroyImageBufferI3D;
+WGLEW_EXPORT PFNWGLRELEASEIMAGEBUFFEREVENTSI3DPROC __wglewReleaseImageBufferEventsI3D;
+
+WGLEW_EXPORT PFNWGLDISABLEFRAMELOCKI3DPROC __wglewDisableFrameLockI3D;
+WGLEW_EXPORT PFNWGLENABLEFRAMELOCKI3DPROC __wglewEnableFrameLockI3D;
+WGLEW_EXPORT PFNWGLISENABLEDFRAMELOCKI3DPROC __wglewIsEnabledFrameLockI3D;
+WGLEW_EXPORT PFNWGLQUERYFRAMELOCKMASTERI3DPROC __wglewQueryFrameLockMasterI3D;
+
+WGLEW_EXPORT PFNWGLBEGINFRAMETRACKINGI3DPROC __wglewBeginFrameTrackingI3D;
+WGLEW_EXPORT PFNWGLENDFRAMETRACKINGI3DPROC __wglewEndFrameTrackingI3D;
+WGLEW_EXPORT PFNWGLGETFRAMEUSAGEI3DPROC __wglewGetFrameUsageI3D;
+WGLEW_EXPORT PFNWGLQUERYFRAMETRACKINGI3DPROC __wglewQueryFrameTrackingI3D;
+
+WGLEW_EXPORT PFNWGLDXCLOSEDEVICENVPROC __wglewDXCloseDeviceNV;
+WGLEW_EXPORT PFNWGLDXLOCKOBJECTSNVPROC __wglewDXLockObjectsNV;
+WGLEW_EXPORT PFNWGLDXOBJECTACCESSNVPROC __wglewDXObjectAccessNV;
+WGLEW_EXPORT PFNWGLDXOPENDEVICENVPROC __wglewDXOpenDeviceNV;
+WGLEW_EXPORT PFNWGLDXREGISTEROBJECTNVPROC __wglewDXRegisterObjectNV;
+WGLEW_EXPORT PFNWGLDXSETRESOURCESHAREHANDLENVPROC __wglewDXSetResourceShareHandleNV;
+WGLEW_EXPORT PFNWGLDXUNLOCKOBJECTSNVPROC __wglewDXUnlockObjectsNV;
+WGLEW_EXPORT PFNWGLDXUNREGISTEROBJECTNVPROC __wglewDXUnregisterObjectNV;
+
+WGLEW_EXPORT PFNWGLCOPYIMAGESUBDATANVPROC __wglewCopyImageSubDataNV;
+
+WGLEW_EXPORT PFNWGLCREATEAFFINITYDCNVPROC __wglewCreateAffinityDCNV;
+WGLEW_EXPORT PFNWGLDELETEDCNVPROC __wglewDeleteDCNV;
+WGLEW_EXPORT PFNWGLENUMGPUDEVICESNVPROC __wglewEnumGpuDevicesNV;
+WGLEW_EXPORT PFNWGLENUMGPUSFROMAFFINITYDCNVPROC __wglewEnumGpusFromAffinityDCNV;
+WGLEW_EXPORT PFNWGLENUMGPUSNVPROC __wglewEnumGpusNV;
+
+WGLEW_EXPORT PFNWGLBINDVIDEODEVICENVPROC __wglewBindVideoDeviceNV;
+WGLEW_EXPORT PFNWGLENUMERATEVIDEODEVICESNVPROC __wglewEnumerateVideoDevicesNV;
+WGLEW_EXPORT PFNWGLQUERYCURRENTCONTEXTNVPROC __wglewQueryCurrentContextNV;
+
+WGLEW_EXPORT PFNWGLBINDSWAPBARRIERNVPROC __wglewBindSwapBarrierNV;
+WGLEW_EXPORT PFNWGLJOINSWAPGROUPNVPROC __wglewJoinSwapGroupNV;
+WGLEW_EXPORT PFNWGLQUERYFRAMECOUNTNVPROC __wglewQueryFrameCountNV;
+WGLEW_EXPORT PFNWGLQUERYMAXSWAPGROUPSNVPROC __wglewQueryMaxSwapGroupsNV;
+WGLEW_EXPORT PFNWGLQUERYSWAPGROUPNVPROC __wglewQuerySwapGroupNV;
+WGLEW_EXPORT PFNWGLRESETFRAMECOUNTNVPROC __wglewResetFrameCountNV;
+
+WGLEW_EXPORT PFNWGLALLOCATEMEMORYNVPROC __wglewAllocateMemoryNV;
+WGLEW_EXPORT PFNWGLFREEMEMORYNVPROC __wglewFreeMemoryNV;
+
+WGLEW_EXPORT PFNWGLBINDVIDEOCAPTUREDEVICENVPROC __wglewBindVideoCaptureDeviceNV;
+WGLEW_EXPORT PFNWGLENUMERATEVIDEOCAPTUREDEVICESNVPROC __wglewEnumerateVideoCaptureDevicesNV;
+WGLEW_EXPORT PFNWGLLOCKVIDEOCAPTUREDEVICENVPROC __wglewLockVideoCaptureDeviceNV;
+WGLEW_EXPORT PFNWGLQUERYVIDEOCAPTUREDEVICENVPROC __wglewQueryVideoCaptureDeviceNV;
+WGLEW_EXPORT PFNWGLRELEASEVIDEOCAPTUREDEVICENVPROC __wglewReleaseVideoCaptureDeviceNV;
+
+WGLEW_EXPORT PFNWGLBINDVIDEOIMAGENVPROC __wglewBindVideoImageNV;
+WGLEW_EXPORT PFNWGLGETVIDEODEVICENVPROC __wglewGetVideoDeviceNV;
+WGLEW_EXPORT PFNWGLGETVIDEOINFONVPROC __wglewGetVideoInfoNV;
+WGLEW_EXPORT PFNWGLRELEASEVIDEODEVICENVPROC __wglewReleaseVideoDeviceNV;
+WGLEW_EXPORT PFNWGLRELEASEVIDEOIMAGENVPROC __wglewReleaseVideoImageNV;
+WGLEW_EXPORT PFNWGLSENDPBUFFERTOVIDEONVPROC __wglewSendPbufferToVideoNV;
+
+WGLEW_EXPORT PFNWGLGETMSCRATEOMLPROC __wglewGetMscRateOML;
+WGLEW_EXPORT PFNWGLGETSYNCVALUESOMLPROC __wglewGetSyncValuesOML;
+WGLEW_EXPORT PFNWGLSWAPBUFFERSMSCOMLPROC __wglewSwapBuffersMscOML;
+WGLEW_EXPORT PFNWGLSWAPLAYERBUFFERSMSCOMLPROC __wglewSwapLayerBuffersMscOML;
+WGLEW_EXPORT PFNWGLWAITFORMSCOMLPROC __wglewWaitForMscOML;
+WGLEW_EXPORT PFNWGLWAITFORSBCOMLPROC __wglewWaitForSbcOML;
+WGLEW_EXPORT GLboolean __WGLEW_3DFX_multisample;
+WGLEW_EXPORT GLboolean __WGLEW_3DL_stereo_control;
+WGLEW_EXPORT GLboolean __WGLEW_AMD_gpu_association;
+WGLEW_EXPORT GLboolean __WGLEW_ARB_buffer_region;
+WGLEW_EXPORT GLboolean __WGLEW_ARB_create_context;
+WGLEW_EXPORT GLboolean __WGLEW_ARB_create_context_profile;
+WGLEW_EXPORT GLboolean __WGLEW_ARB_create_context_robustness;
+WGLEW_EXPORT GLboolean __WGLEW_ARB_extensions_string;
+WGLEW_EXPORT GLboolean __WGLEW_ARB_framebuffer_sRGB;
+WGLEW_EXPORT GLboolean __WGLEW_ARB_make_current_read;
+WGLEW_EXPORT GLboolean __WGLEW_ARB_multisample;
+WGLEW_EXPORT GLboolean __WGLEW_ARB_pbuffer;
+WGLEW_EXPORT GLboolean __WGLEW_ARB_pixel_format;
+WGLEW_EXPORT GLboolean __WGLEW_ARB_pixel_format_float;
+WGLEW_EXPORT GLboolean __WGLEW_ARB_render_texture;
+WGLEW_EXPORT GLboolean __WGLEW_ARB_robustness_application_isolation;
+WGLEW_EXPORT GLboolean __WGLEW_ARB_robustness_share_group_isolation;
+WGLEW_EXPORT GLboolean __WGLEW_ATI_pixel_format_float;
+WGLEW_EXPORT GLboolean __WGLEW_ATI_render_texture_rectangle;
+WGLEW_EXPORT GLboolean __WGLEW_EXT_create_context_es2_profile;
+WGLEW_EXPORT GLboolean __WGLEW_EXT_create_context_es_profile;
+WGLEW_EXPORT GLboolean __WGLEW_EXT_depth_float;
+WGLEW_EXPORT GLboolean __WGLEW_EXT_display_color_table;
+WGLEW_EXPORT GLboolean __WGLEW_EXT_extensions_string;
+WGLEW_EXPORT GLboolean __WGLEW_EXT_framebuffer_sRGB;
+WGLEW_EXPORT GLboolean __WGLEW_EXT_make_current_read;
+WGLEW_EXPORT GLboolean __WGLEW_EXT_multisample;
+WGLEW_EXPORT GLboolean __WGLEW_EXT_pbuffer;
+WGLEW_EXPORT GLboolean __WGLEW_EXT_pixel_format;
+WGLEW_EXPORT GLboolean __WGLEW_EXT_pixel_format_packed_float;
+WGLEW_EXPORT GLboolean __WGLEW_EXT_swap_control;
+WGLEW_EXPORT GLboolean __WGLEW_EXT_swap_control_tear;
+WGLEW_EXPORT GLboolean __WGLEW_I3D_digital_video_control;
+WGLEW_EXPORT GLboolean __WGLEW_I3D_gamma;
+WGLEW_EXPORT GLboolean __WGLEW_I3D_genlock;
+WGLEW_EXPORT GLboolean __WGLEW_I3D_image_buffer;
+WGLEW_EXPORT GLboolean __WGLEW_I3D_swap_frame_lock;
+WGLEW_EXPORT GLboolean __WGLEW_I3D_swap_frame_usage;
+WGLEW_EXPORT GLboolean __WGLEW_NV_DX_interop;
+WGLEW_EXPORT GLboolean __WGLEW_NV_DX_interop2;
+WGLEW_EXPORT GLboolean __WGLEW_NV_copy_image;
+WGLEW_EXPORT GLboolean __WGLEW_NV_float_buffer;
+WGLEW_EXPORT GLboolean __WGLEW_NV_gpu_affinity;
+WGLEW_EXPORT GLboolean __WGLEW_NV_multisample_coverage;
+WGLEW_EXPORT GLboolean __WGLEW_NV_present_video;
+WGLEW_EXPORT GLboolean __WGLEW_NV_render_depth_texture;
+WGLEW_EXPORT GLboolean __WGLEW_NV_render_texture_rectangle;
+WGLEW_EXPORT GLboolean __WGLEW_NV_swap_group;
+WGLEW_EXPORT GLboolean __WGLEW_NV_vertex_array_range;
+WGLEW_EXPORT GLboolean __WGLEW_NV_video_capture;
+WGLEW_EXPORT GLboolean __WGLEW_NV_video_output;
+WGLEW_EXPORT GLboolean __WGLEW_OML_sync_control;
+
+#ifdef GLEW_MX
+}; /* WGLEWContextStruct */
+#endif /* GLEW_MX */
+
+/* ------------------------------------------------------------------------- */
+
+#ifdef GLEW_MX
+
+typedef struct WGLEWContextStruct WGLEWContext;
+GLEWAPI GLenum wglewContextInit (WGLEWContext* ctx);
+GLEWAPI GLboolean wglewContextIsSupported (const WGLEWContext* ctx, const char* name);
+
+#define wglewInit() wglewContextInit(wglewGetContext())
+#define wglewIsSupported(x) wglewContextIsSupported(wglewGetContext(), x)
+
+#define WGLEW_GET_VAR(x) (*(const GLboolean*)&(wglewGetContext()->x))
+#define WGLEW_GET_FUN(x) wglewGetContext()->x
+
+#else /* GLEW_MX */
+
+#define WGLEW_GET_VAR(x) (*(const GLboolean*)&x)
+#define WGLEW_GET_FUN(x) x
+
+GLEWAPI GLenum wglewContextInit (void); // NOTE jwilkins: Why does this require GLEW_MX? Should I enable GLEW_MX? instead?
+#define wglewInit() wglewContextInit() // NOTE jwilkins: Why does this require GLEW_MX? Should I enable GLEW_MX? instead?
+
+GLEWAPI GLboolean wglewIsSupported (const char* name);
+
+#endif /* GLEW_MX */
+
+GLEWAPI GLboolean wglewGetExtension (const char* name);
+
+#ifdef __cplusplus
+}
+#endif
+
+#undef GLEWAPI
+
+#endif /* __wglew_h__ */
diff --git a/extern/glew-es/src/glew.c b/extern/glew-es/src/glew.c
new file mode 100644
index 00000000000..e13e4c92d65
--- /dev/null
+++ b/extern/glew-es/src/glew.c
@@ -0,0 +1,22401 @@
+/*
+** The OpenGL Extension Wrangler Library
+** Copyright (C) 2002-2008, Milan Ikits <milan ikits[]ieee org>
+** Copyright (C) 2002-2008, Marcelo E. Magallon <mmagallo[]debian org>
+** Copyright (C) 2002, Lev Povalahev
+** 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.
+** * The name of the author 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.
+*/
+
+#include <GL/glew.h>
+#if defined(GLEW_INC_EGL)
+# include <GL/eglew.h>
+#elif defined(_WIN32)
+# include <GL/wglew.h>
+#elif !defined(__APPLE__) || defined(GLEW_APPLE_GLX)
+# include <GL/glxew.h>
+#endif
+
+/* Invalid build macro combination error checking */
+
+#if defined(GLEW_ES_ONLY) && defined(GLEW_NO_ES)
+#error GLEW_ES_ONLY (pure ES) and GLEW_NO_ES (pure desktop OpenGL) are mutually exclusive
+#endif
+
+#if defined(GLEW_USE_LIB_ES) && defined(GLEW_NO_ES)
+#error GLEW_NO_ES (pure desktop OpenGL) and GLEW_USE_LIB_ES (ES lib is linked) are mutually exclusive
+#endif
+
+/*
+ * Define glewGetContext and related helper macros.
+ */
+#ifdef GLEW_MX
+# define glewGetContext() ctx
+# ifdef _WIN32
+# define GLEW_CONTEXT_ARG_DEF_INIT GLEWContext* ctx
+# define GLEW_CONTEXT_ARG_VAR_INIT ctx
+# if defined(GLEW_INC_EGL)
+# define eglewGetContext() ctx
+# define EGLEW_CONTEXT_ARG_DEF_INIT EGLEWContext* ctx
+# define EGLEW_CONTEXT_ARG_DEF_LIST EGLDisplay display, EGLEWContext* ctx
+# else
+# define wglewGetContext() ctx
+# define WGLEW_CONTEXT_ARG_DEF_INIT WGLEWContext* ctx
+# define WGLEW_CONTEXT_ARG_DEF_LIST WGLEWContext* ctx
+# endif
+# else /* _WIN32 */
+# define GLEW_CONTEXT_ARG_DEF_INIT void
+# define GLEW_CONTEXT_ARG_VAR_INIT
+# if defined(GLEW_INC_EGL)
+# define eglewGetContext() ctx
+# define EGLEW_CONTEXT_ARG_DEF_INIT void
+# define EGLEW_CONTEXT_ARG_DEF_LIST EGLEWContext* ctx
+# endif /* GLEW_INC_EGL */
+# if !defined(GLEW_EGL_ONLY)
+# define glxewGetContext() ctx
+# define GLXEW_CONTEXT_ARG_DEF_INIT void
+# define GLXEW_CONTEXT_ARG_DEF_LIST GLXEWContext* ctx
+# endif /* GLEW_EGL_ONLY */
+# endif /* _WIN32 */
+# define GLEW_CONTEXT_ARG_DEF_LIST GLEWContext* ctx
+#else /* GLEW_MX */
+# define GLEW_CONTEXT_ARG_DEF_INIT void
+# define GLEW_CONTEXT_ARG_VAR_INIT
+# define GLEW_CONTEXT_ARG_DEF_LIST void
+# define WGLEW_CONTEXT_ARG_DEF_INIT void
+# define WGLEW_CONTEXT_ARG_DEF_LIST void
+# define GLXEW_CONTEXT_ARG_DEF_INIT void
+# define GLXEW_CONTEXT_ARG_DEF_LIST void
+# define EGLEW_CONTEXT_ARG_DEF_INIT void
+# define EGLEW_CONTEXT_ARG_DEF_LIST EGLDisplay display
+#endif /* GLEW_MX */
+
+#if defined(GLEW_INC_EGL)
+
+#ifdef linux
+
+#include <dlfcn.h>
+//NOTE jwilkins: to do ?? properly set the lib paths depending on openGL version.
+#if defined(GLEW_USE_LIB_ES20)
+#define GLEW_OPENGLES_LIB_PATH "/usr/lib/libGLESv2.so"
+#elif defined(GLEW_USE_LIB_ES11)
+#define GLEW_OPENGLES_LIB_PATH "/usr/lib/libGLESv1_CM.so"
+#endif
+
+#if defined GLEW_INC_EGL
+#define GLEW_EGL_LIB_PATH "/usr/lib/libEGL.so"
+#endif
+
+void* esGetProcAddress (const GLubyte *name)
+{
+ static void* imageGLES = NULL;
+#if defined GLEW_INC_EGL
+ static void* imageEGL = NULL;
+ if ((name[0] == 'e') && (name[1] == 'g') && (name[2] == 'l'))
+ {
+ if (NULL == imageEGL)
+ {
+ imageEGL = dlopen(GLEW_EGL_LIB_PATH, RTLD_LAZY);
+ }
+ if( !imageEGL ) return NULL;
+ void* addr = dlsym(imageEGL, (const char*)name);
+ if( addr ) return addr;
+ return NULL;
+ }
+ else
+#endif
+ if((name[0] == 'g') && (name[1] == 'l'))
+ {
+ if (NULL == imageGLES)
+ {
+ imageGLES = dlopen(GLEW_OPENGLES_LIB_PATH, RTLD_LAZY);
+ }
+ if( !imageGLES ) return NULL;
+ void* addr = dlsym(imageGLES, (const char*)name);
+ if( addr ) return addr;
+ return NULL;
+ }
+ return NULL;
+}
+#endif /* linux */
+
+#else
+
+#if defined(__sgi) || defined (__sun) || defined(GLEW_APPLE_GLX)
+#include <dlfcn.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+void* dlGetProcAddress (const GLubyte* name)
+{
+ static void* h = NULL;
+ static void* gpa;
+
+ if (h == NULL)
+ {
+ if ((h = dlopen(NULL, RTLD_LAZY | RTLD_LOCAL)) == NULL) return NULL;
+ gpa = dlsym(h, "glXGetProcAddress");
+ }
+
+ if (gpa != NULL)
+ return ((void*(*)(const GLubyte*))gpa)(name);
+ else
+ return dlsym(h, (const char*)name);
+}
+#endif /* __sgi || __sun || GLEW_APPLE_GLX */
+
+#if defined(__APPLE__)
+#include <stdlib.h>
+#include <string.h>
+#include <AvailabilityMacros.h>
+
+#ifdef MAC_OS_X_VERSION_10_3
+
+#include <dlfcn.h>
+
+void* NSGLGetProcAddress (const GLubyte *name)
+{
+ static void* image = NULL;
+ if (NULL == image)
+ {
+ image = dlopen("/System/Library/Frameworks/OpenGL.framework/Versions/Current/OpenGL", RTLD_LAZY);
+ }
+ if( !image ) return NULL;
+ void* addr = dlsym(image, (const char*)name);
+ if( addr ) return addr;
+#ifdef GLEW_APPLE_GLX
+ return dlGetProcAddress( name ); // try next for glx symbols
+#else
+ return NULL;
+#endif
+}
+#else
+
+#include <mach-o/dyld.h>
+
+void* NSGLGetProcAddress (const GLubyte *name)
+{
+ static const struct mach_header* image = NULL;
+ NSSymbol symbol;
+ char* symbolName;
+ if (NULL == image)
+ {
+ image = NSAddImage("/System/Library/Frameworks/OpenGL.framework/Versions/Current/OpenGL", NSADDIMAGE_OPTION_RETURN_ON_ERROR);
+ }
+ /* prepend a '_' for the Unix C symbol mangling convention */
+ symbolName = malloc(strlen((const char*)name) + 2);
+ strcpy(symbolName+1, (const char*)name);
+ symbolName[0] = '_';
+ symbol = NULL;
+ /* if (NSIsSymbolNameDefined(symbolName))
+ symbol = NSLookupAndBindSymbol(symbolName); */
+ symbol = image ? NSLookupSymbolInImage(image, symbolName, NSLOOKUPSYMBOLINIMAGE_OPTION_BIND | NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR) : NULL;
+ free(symbolName);
+ if( symbol ) return NSAddressOfSymbol(symbol);
+#ifdef GLEW_APPLE_GLX
+ return dlGetProcAddress( name ); // try next for glx symbols
+#else
+ return NULL;
+#endif
+}
+#endif /* MAC_OS_X_VERSION_10_3 */
+#endif /* __APPLE__ */
+#endif /* GLEW_USE_LIB_ES */
+
+/*
+ * Define glewGetProcAddress.
+ */
+#if defined(GLEW_INC_EGL)
+#if linux
+# define glewGetProcAddress(name) esGetProcAddress(name)
+#else
+#if defined(_WIN32)
+ static HMODULE hLibEGL = NULL;
+ static HMODULE hLibGLESv2 = NULL;
+
+ void* weGetProcAddress(const char* name) // NOTE jwilkins
+ {
+ void* proc = eglGetProcAddress(name);
+
+ if (proc != NULL)
+ return proc;
+
+ if (hLibEGL == NULL)
+ hLibEGL = LoadLibrary("libEGL.dll");
+
+ if (hLibEGL != NULL)
+ proc = GetProcAddress(hLibEGL, name);
+
+ if (proc != NULL)
+ return proc;
+
+ if (hLibGLESv2 == NULL)
+ hLibGLESv2 = LoadLibrary("libGLESv2.dll");
+
+ if (hLibGLESv2 != NULL)
+ proc = GetProcAddress(hLibGLESv2, name);
+
+ if (proc != NULL)
+ return proc;
+
+ return NULL;
+ }
+
+# define glewGetProcAddress(name) weGetProcAddress(name)
+#else
+# define glewGetProcAddress(name) eglGetProcAddress(name)
+#endif
+#endif
+#elif defined(_WIN32)
+ static HMODULE hOpenGL = NULL;
+
+ void* wGetProcAddress(const char* name) // NOTE jwilkins
+ {
+ void* proc = wglGetProcAddress(name);
+
+ if (proc == NULL && hOpenGL == NULL) {
+ hOpenGL = LoadLibrary("opengl32.dll");
+ }
+
+ if (proc == NULL && hOpenGL != NULL) {
+ return GetProcAddress(hOpenGL, name);
+ }
+ else {
+ return proc;
+ }
+ }
+
+# define glewGetProcAddress(name) wGetProcAddress((LPCSTR)name)
+#else
+# if defined(__APPLE__)
+# define glewGetProcAddress(name) NSGLGetProcAddress(name)
+# else
+# if defined(__sgi) || defined(__sun)
+# define glewGetProcAddress(name) dlGetProcAddress(name)
+# else /* __linux */
+# define glewGetProcAddress(name) (*glXGetProcAddressARB)(name)
+# endif
+# endif
+#endif
+
+/*
+ * Define GLboolean const cast.
+ */
+#define CONST_CAST(x) (*(GLboolean*)&x)
+
+/*
+ * GLEW, just like OpenGL or GLU, does not rely on the standard C library.
+ * These functions implement the functionality required in this file.
+ */
+static GLuint _glewStrLen (const GLubyte* s)
+{
+ GLuint i=0;
+ if (s == NULL) return 0;
+ while (s[i] != '\0') i++;
+ return i;
+}
+
+static GLuint _glewStrCLen (const GLubyte* s, GLubyte c)
+{
+ GLuint i=0;
+ if (s == NULL) return 0;
+ while (s[i] != '\0' && s[i] != c) i++;
+ return (s[i] == '\0' || s[i] == c) ? i : 0;
+}
+
+static GLboolean _glewStrSame (const GLubyte* a, const GLubyte* b, GLuint n)
+{
+ GLuint i=0;
+ if(a == NULL || b == NULL)
+ return (a == NULL && b == NULL && n == 0) ? GL_TRUE : GL_FALSE;
+ while (i < n && a[i] != '\0' && b[i] != '\0' && a[i] == b[i]) i++;
+ return i == n ? GL_TRUE : GL_FALSE;
+}
+
+static GLboolean _glewStrSame1 (GLubyte** a, GLuint* na, const GLubyte* b, GLuint nb)
+{
+ while (*na > 0 && (**a == ' ' || **a == '\n' || **a == '\r' || **a == '\t'))
+ {
+ (*a)++;
+ (*na)--;
+ }
+ if(*na >= nb)
+ {
+ GLuint i=0;
+ while (i < nb && (*a)+i != NULL && b+i != NULL && (*a)[i] == b[i]) i++;
+ if(i == nb)
+ {
+ *a = *a + nb;
+ *na = *na - nb;
+ return GL_TRUE;
+ }
+ }
+ return GL_FALSE;
+}
+
+static GLboolean _glewStrSame2 (GLubyte** a, GLuint* na, const GLubyte* b, GLuint nb)
+{
+ if(*na >= nb)
+ {
+ GLuint i=0;
+ while (i < nb && (*a)+i != NULL && b+i != NULL && (*a)[i] == b[i]) i++;
+ if(i == nb)
+ {
+ *a = *a + nb;
+ *na = *na - nb;
+ return GL_TRUE;
+ }
+ }
+ return GL_FALSE;
+}
+
+static GLboolean _glewStrSame3 (GLubyte** a, GLuint* na, const GLubyte* b, GLuint nb)
+{
+ if(*na >= nb)
+ {
+ GLuint i=0;
+ while (i < nb && (*a)+i != NULL && b+i != NULL && (*a)[i] == b[i]) i++;
+ if (i == nb && (*na == nb || (*a)[i] == ' ' || (*a)[i] == '\n' || (*a)[i] == '\r' || (*a)[i] == '\t'))
+ {
+ *a = *a + nb;
+ *na = *na - nb;
+ return GL_TRUE;
+ }
+ }
+ return GL_FALSE;
+}
+
+/*
+ * Search for name in the extensions string. Use of strstr()
+ * is not sufficient because extension names can be prefixes of
+ * other extension names. Could use strtok() but the constant
+ * string returned by glGetString might be in read-only memory.
+ */
+static GLboolean _glewSearchExtension (const char* name, const GLubyte *start, const GLubyte *end)
+{
+ if (start != NULL) {
+ const GLubyte* p;
+ GLuint len = _glewStrLen((const GLubyte*)name);
+ p = start;
+ while (p < end)
+ {
+ GLuint n = _glewStrCLen(p, ' ');
+ if (len == n && _glewStrSame((const GLubyte*)name, p, n)) return GL_TRUE;
+ p += n+1;
+ }
+ return GL_FALSE;
+ }
+#ifndef GLEW_ES_ONLY
+ else { // NOTE jwilkins: unified extension string is deprecated
+ PFNGLGETSTRINGIPROC pglGetStringi = (PFNGLGETSTRINGIPROC)glewGetProcAddress("glGetStringi");
+
+ if (pglGetStringi != NULL) {
+ const GLubyte* ext;
+ int i;
+ int max = 0;
+ const GLenum NUM_EXTENSIONS = 0x821D;
+ GLuint len;
+
+ glGetIntegerv(NUM_EXTENSIONS, &max);
+
+ len = _glewStrLen((const GLubyte*)name);
+
+ for (i = 0; i < max; i++) {
+ ext = pglGetStringi(GL_EXTENSIONS, i);
+
+ if (_glewStrSame((const GLubyte*)name, ext, len))
+ return GL_TRUE;
+ }
+ }
+ }
+#endif
+
+ return GL_FALSE;
+}
+
+#if !defined(_WIN32) || !defined(GLEW_MX)
+
+#ifndef GLEW_ES_ONLY
+
+PFNGLACCUMPROC __glewAccum = NULL;
+PFNGLARETEXTURESRESIDENTPROC __glewAreTexturesResident = NULL;
+PFNGLARRAYELEMENTPROC __glewArrayElement = NULL;
+PFNGLBEGINPROC __glewBegin = NULL;
+PFNGLBITMAPPROC __glewBitmap = NULL;
+PFNGLCALLLISTPROC __glewCallList = NULL;
+PFNGLCALLLISTSPROC __glewCallLists = NULL;
+PFNGLCLEARACCUMPROC __glewClearAccum = NULL;
+PFNGLCLEARDEPTHPROC __glewClearDepth = NULL;
+PFNGLCLEARINDEXPROC __glewClearIndex = NULL;
+PFNGLCLIPPLANEPROC __glewClipPlane = NULL;
+PFNGLCOLOR3BPROC __glewColor3b = NULL;
+PFNGLCOLOR3BVPROC __glewColor3bv = NULL;
+PFNGLCOLOR3DPROC __glewColor3d = NULL;
+PFNGLCOLOR3DVPROC __glewColor3dv = NULL;
+PFNGLCOLOR3FPROC __glewColor3f = NULL;
+PFNGLCOLOR3FVPROC __glewColor3fv = NULL;
+PFNGLCOLOR3IPROC __glewColor3i = NULL;
+PFNGLCOLOR3IVPROC __glewColor3iv = NULL;
+PFNGLCOLOR3SPROC __glewColor3s = NULL;
+PFNGLCOLOR3SVPROC __glewColor3sv = NULL;
+PFNGLCOLOR3UBPROC __glewColor3ub = NULL;
+PFNGLCOLOR3UBVPROC __glewColor3ubv = NULL;
+PFNGLCOLOR3UIPROC __glewColor3ui = NULL;
+PFNGLCOLOR3UIVPROC __glewColor3uiv = NULL;
+PFNGLCOLOR3USPROC __glewColor3us = NULL;
+PFNGLCOLOR3USVPROC __glewColor3usv = NULL;
+PFNGLCOLOR4BPROC __glewColor4b = NULL;
+PFNGLCOLOR4BVPROC __glewColor4bv = NULL;
+PFNGLCOLOR4DPROC __glewColor4d = NULL;
+PFNGLCOLOR4DVPROC __glewColor4dv = NULL;
+PFNGLCOLOR4FVPROC __glewColor4fv = NULL;
+PFNGLCOLOR4IPROC __glewColor4i = NULL;
+PFNGLCOLOR4IVPROC __glewColor4iv = NULL;
+PFNGLCOLOR4SPROC __glewColor4s = NULL;
+PFNGLCOLOR4SVPROC __glewColor4sv = NULL;
+PFNGLCOLOR4UBPROC __glewColor4ub = NULL;
+PFNGLCOLOR4UBVPROC __glewColor4ubv = NULL;
+PFNGLCOLOR4UIPROC __glewColor4ui = NULL;
+PFNGLCOLOR4UIVPROC __glewColor4uiv = NULL;
+PFNGLCOLOR4USPROC __glewColor4us = NULL;
+PFNGLCOLOR4USVPROC __glewColor4usv = NULL;
+PFNGLCOLORMATERIALPROC __glewColorMaterial = NULL;
+PFNGLCOPYPIXELSPROC __glewCopyPixels = NULL;
+PFNGLCOPYTEXIMAGE1DPROC __glewCopyTexImage1D = NULL;
+PFNGLCOPYTEXSUBIMAGE1DPROC __glewCopyTexSubImage1D = NULL;
+PFNGLDELETELISTSPROC __glewDeleteLists = NULL;
+PFNGLDEPTHRANGEPROC __glewDepthRange = NULL;
+PFNGLDRAWBUFFERPROC __glewDrawBuffer = NULL;
+PFNGLDRAWPIXELSPROC __glewDrawPixels = NULL;
+PFNGLEDGEFLAGPROC __glewEdgeFlag = NULL;
+PFNGLEDGEFLAGPOINTERPROC __glewEdgeFlagPointer = NULL;
+PFNGLEDGEFLAGVPROC __glewEdgeFlagv = NULL;
+PFNGLENDPROC __glewEnd = NULL;
+PFNGLENDLISTPROC __glewEndList = NULL;
+PFNGLEVALCOORD1DPROC __glewEvalCoord1d = NULL;
+PFNGLEVALCOORD1DVPROC __glewEvalCoord1dv = NULL;
+PFNGLEVALCOORD1FPROC __glewEvalCoord1f = NULL;
+PFNGLEVALCOORD1FVPROC __glewEvalCoord1fv = NULL;
+PFNGLEVALCOORD2DPROC __glewEvalCoord2d = NULL;
+PFNGLEVALCOORD2DVPROC __glewEvalCoord2dv = NULL;
+PFNGLEVALCOORD2FPROC __glewEvalCoord2f = NULL;
+PFNGLEVALCOORD2FVPROC __glewEvalCoord2fv = NULL;
+PFNGLEVALMESH1PROC __glewEvalMesh1 = NULL;
+PFNGLEVALMESH2PROC __glewEvalMesh2 = NULL;
+PFNGLEVALPOINT1PROC __glewEvalPoint1 = NULL;
+PFNGLEVALPOINT2PROC __glewEvalPoint2 = NULL;
+PFNGLFEEDBACKBUFFERPROC __glewFeedbackBuffer = NULL;
+PFNGLFOGIPROC __glewFogi = NULL;
+PFNGLFOGIVPROC __glewFogiv = NULL;
+PFNGLFRUSTUMPROC __glewFrustum = NULL;
+PFNGLGENLISTSPROC __glewGenLists = NULL;
+PFNGLGETBOOLEANVPROC __glewGetBooleanv = NULL;
+PFNGLGETCLIPPLANEPROC __glewGetClipPlane = NULL;
+PFNGLGETDOUBLEVPROC __glewGetDoublev = NULL;
+PFNGLGETFLOATVPROC __glewGetFloatv = NULL;
+PFNGLGETLIGHTFVPROC __glewGetLightfv = NULL;
+PFNGLGETLIGHTIVPROC __glewGetLightiv = NULL;
+PFNGLGETMAPDVPROC __glewGetMapdv = NULL;
+PFNGLGETMAPFVPROC __glewGetMapfv = NULL;
+PFNGLGETMAPIVPROC __glewGetMapiv = NULL;
+PFNGLGETMATERIALFVPROC __glewGetMaterialfv = NULL;
+PFNGLGETMATERIALIVPROC __glewGetMaterialiv = NULL;
+PFNGLGETPIXELMAPFVPROC __glewGetPixelMapfv = NULL;
+PFNGLGETPIXELMAPUIVPROC __glewGetPixelMapuiv = NULL;
+PFNGLGETPIXELMAPUSVPROC __glewGetPixelMapusv = NULL;
+PFNGLGETPOINTERVPROC __glewGetPointerv = NULL;
+PFNGLGETPOLYGONSTIPPLEPROC __glewGetPolygonStipple = NULL;
+PFNGLGETTEXENVFVPROC __glewGetTexEnvfv = NULL;
+PFNGLGETTEXENVIVPROC __glewGetTexEnviv = NULL;
+PFNGLGETTEXGENDVPROC __glewGetTexGendv = NULL;
+PFNGLGETTEXGENFVPROC __glewGetTexGenfv = NULL;
+PFNGLGETTEXGENIVPROC __glewGetTexGeniv = NULL;
+PFNGLGETTEXIMAGEPROC __glewGetTexImage = NULL;
+PFNGLGETTEXLEVELPARAMETERFVPROC __glewGetTexLevelParameterfv = NULL;
+PFNGLGETTEXLEVELPARAMETERIVPROC __glewGetTexLevelParameteriv = NULL;
+PFNGLGETTEXPARAMETERFVPROC __glewGetTexParameterfv = NULL;
+PFNGLGETTEXPARAMETERIVPROC __glewGetTexParameteriv = NULL;
+PFNGLINDEXMASKPROC __glewIndexMask = NULL;
+PFNGLINDEXPOINTERPROC __glewIndexPointer = NULL;
+PFNGLINDEXDPROC __glewIndexd = NULL;
+PFNGLINDEXDVPROC __glewIndexdv = NULL;
+PFNGLINDEXFPROC __glewIndexf = NULL;
+PFNGLINDEXFVPROC __glewIndexfv = NULL;
+PFNGLINDEXIPROC __glewIndexi = NULL;
+PFNGLINDEXIVPROC __glewIndexiv = NULL;
+PFNGLINDEXSPROC __glewIndexs = NULL;
+PFNGLINDEXSVPROC __glewIndexsv = NULL;
+PFNGLINDEXUBPROC __glewIndexub = NULL;
+PFNGLINDEXUBVPROC __glewIndexubv = NULL;
+PFNGLINITNAMESPROC __glewInitNames = NULL;
+PFNGLINTERLEAVEDARRAYSPROC __glewInterleavedArrays = NULL;
+PFNGLISENABLEDPROC __glewIsEnabled = NULL;
+PFNGLISLISTPROC __glewIsList = NULL;
+PFNGLISTEXTUREPROC __glewIsTexture = NULL;
+PFNGLLIGHTMODELIPROC __glewLightModeli = NULL;
+PFNGLLIGHTMODELIVPROC __glewLightModeliv = NULL;
+PFNGLLIGHTIPROC __glewLighti = NULL;
+PFNGLLIGHTIVPROC __glewLightiv = NULL;
+PFNGLLINESTIPPLEPROC __glewLineStipple = NULL;
+PFNGLLISTBASEPROC __glewListBase = NULL;
+PFNGLLOADMATRIXDPROC __glewLoadMatrixd = NULL;
+PFNGLLOADNAMEPROC __glewLoadName = NULL;
+PFNGLMAP1DPROC __glewMap1d = NULL;
+PFNGLMAP1FPROC __glewMap1f = NULL;
+PFNGLMAP2DPROC __glewMap2d = NULL;
+PFNGLMAP2FPROC __glewMap2f = NULL;
+PFNGLMAPGRID1DPROC __glewMapGrid1d = NULL;
+PFNGLMAPGRID1FPROC __glewMapGrid1f = NULL;
+PFNGLMAPGRID2DPROC __glewMapGrid2d = NULL;
+PFNGLMAPGRID2FPROC __glewMapGrid2f = NULL;
+PFNGLMATERIALIPROC __glewMateriali = NULL;
+PFNGLMATERIALIVPROC __glewMaterialiv = NULL;
+PFNGLMULTMATRIXDPROC __glewMultMatrixd = NULL;
+PFNGLNEWLISTPROC __glewNewList = NULL;
+PFNGLNORMAL3BPROC __glewNormal3b = NULL;
+PFNGLNORMAL3BVPROC __glewNormal3bv = NULL;
+PFNGLNORMAL3DPROC __glewNormal3d = NULL;
+PFNGLNORMAL3DVPROC __glewNormal3dv = NULL;
+PFNGLNORMAL3FVPROC __glewNormal3fv = NULL;
+PFNGLNORMAL3IPROC __glewNormal3i = NULL;
+PFNGLNORMAL3IVPROC __glewNormal3iv = NULL;
+PFNGLNORMAL3SPROC __glewNormal3s = NULL;
+PFNGLNORMAL3SVPROC __glewNormal3sv = NULL;
+PFNGLORTHOPROC __glewOrtho = NULL;
+PFNGLPASSTHROUGHPROC __glewPassThrough = NULL;
+PFNGLPIXELMAPFVPROC __glewPixelMapfv = NULL;
+PFNGLPIXELMAPUIVPROC __glewPixelMapuiv = NULL;
+PFNGLPIXELMAPUSVPROC __glewPixelMapusv = NULL;
+PFNGLPIXELSTOREFPROC __glewPixelStoref = NULL;
+PFNGLPIXELTRANSFERFPROC __glewPixelTransferf = NULL;
+PFNGLPIXELTRANSFERIPROC __glewPixelTransferi = NULL;
+PFNGLPIXELZOOMPROC __glewPixelZoom = NULL;
+PFNGLPOLYGONMODEPROC __glewPolygonMode = NULL;
+PFNGLPOLYGONSTIPPLEPROC __glewPolygonStipple = NULL;
+PFNGLPOPATTRIBPROC __glewPopAttrib = NULL;
+PFNGLPOPCLIENTATTRIBPROC __glewPopClientAttrib = NULL;
+PFNGLPOPNAMEPROC __glewPopName = NULL;
+PFNGLPRIORITIZETEXTURESPROC __glewPrioritizeTextures = NULL;
+PFNGLPUSHATTRIBPROC __glewPushAttrib = NULL;
+PFNGLPUSHCLIENTATTRIBPROC __glewPushClientAttrib = NULL;
+PFNGLPUSHNAMEPROC __glewPushName = NULL;
+PFNGLRASTERPOS2DPROC __glewRasterPos2d = NULL;
+PFNGLRASTERPOS2DVPROC __glewRasterPos2dv = NULL;
+PFNGLRASTERPOS2FPROC __glewRasterPos2f = NULL;
+PFNGLRASTERPOS2FVPROC __glewRasterPos2fv = NULL;
+PFNGLRASTERPOS2IPROC __glewRasterPos2i = NULL;
+PFNGLRASTERPOS2IVPROC __glewRasterPos2iv = NULL;
+PFNGLRASTERPOS2SPROC __glewRasterPos2s = NULL;
+PFNGLRASTERPOS2SVPROC __glewRasterPos2sv = NULL;
+PFNGLRASTERPOS3DPROC __glewRasterPos3d = NULL;
+PFNGLRASTERPOS3DVPROC __glewRasterPos3dv = NULL;
+PFNGLRASTERPOS3FPROC __glewRasterPos3f = NULL;
+PFNGLRASTERPOS3FVPROC __glewRasterPos3fv = NULL;
+PFNGLRASTERPOS3IPROC __glewRasterPos3i = NULL;
+PFNGLRASTERPOS3IVPROC __glewRasterPos3iv = NULL;
+PFNGLRASTERPOS3SPROC __glewRasterPos3s = NULL;
+PFNGLRASTERPOS3SVPROC __glewRasterPos3sv = NULL;
+PFNGLRASTERPOS4DPROC __glewRasterPos4d = NULL;
+PFNGLRASTERPOS4DVPROC __glewRasterPos4dv = NULL;
+PFNGLRASTERPOS4FPROC __glewRasterPos4f = NULL;
+PFNGLRASTERPOS4FVPROC __glewRasterPos4fv = NULL;
+PFNGLRASTERPOS4IPROC __glewRasterPos4i = NULL;
+PFNGLRASTERPOS4IVPROC __glewRasterPos4iv = NULL;
+PFNGLRASTERPOS4SPROC __glewRasterPos4s = NULL;
+PFNGLRASTERPOS4SVPROC __glewRasterPos4sv = NULL;
+PFNGLREADBUFFERPROC __glewReadBuffer = NULL;
+PFNGLRECTDPROC __glewRectd = NULL;
+PFNGLRECTDVPROC __glewRectdv = NULL;
+PFNGLRECTFPROC __glewRectf = NULL;
+PFNGLRECTFVPROC __glewRectfv = NULL;
+PFNGLRECTIPROC __glewRecti = NULL;
+PFNGLRECTIVPROC __glewRectiv = NULL;
+PFNGLRECTSPROC __glewRects = NULL;
+PFNGLRECTSVPROC __glewRectsv = NULL;
+PFNGLRENDERMODEPROC __glewRenderMode = NULL;
+PFNGLROTATEDPROC __glewRotated = NULL;
+PFNGLSCALEDPROC __glewScaled = NULL;
+PFNGLSELECTBUFFERPROC __glewSelectBuffer = NULL;
+PFNGLTEXCOORD1DPROC __glewTexCoord1d = NULL;
+PFNGLTEXCOORD1DVPROC __glewTexCoord1dv = NULL;
+PFNGLTEXCOORD1FPROC __glewTexCoord1f = NULL;
+PFNGLTEXCOORD1FVPROC __glewTexCoord1fv = NULL;
+PFNGLTEXCOORD1IPROC __glewTexCoord1i = NULL;
+PFNGLTEXCOORD1IVPROC __glewTexCoord1iv = NULL;
+PFNGLTEXCOORD1SPROC __glewTexCoord1s = NULL;
+PFNGLTEXCOORD1SVPROC __glewTexCoord1sv = NULL;
+PFNGLTEXCOORD2DPROC __glewTexCoord2d = NULL;
+PFNGLTEXCOORD2DVPROC __glewTexCoord2dv = NULL;
+PFNGLTEXCOORD2FPROC __glewTexCoord2f = NULL;
+PFNGLTEXCOORD2FVPROC __glewTexCoord2fv = NULL;
+PFNGLTEXCOORD2IPROC __glewTexCoord2i = NULL;
+PFNGLTEXCOORD2IVPROC __glewTexCoord2iv = NULL;
+PFNGLTEXCOORD2SPROC __glewTexCoord2s = NULL;
+PFNGLTEXCOORD2SVPROC __glewTexCoord2sv = NULL;
+PFNGLTEXCOORD3DPROC __glewTexCoord3d = NULL;
+PFNGLTEXCOORD3DVPROC __glewTexCoord3dv = NULL;
+PFNGLTEXCOORD3FPROC __glewTexCoord3f = NULL;
+PFNGLTEXCOORD3FVPROC __glewTexCoord3fv = NULL;
+PFNGLTEXCOORD3IPROC __glewTexCoord3i = NULL;
+PFNGLTEXCOORD3IVPROC __glewTexCoord3iv = NULL;
+PFNGLTEXCOORD3SPROC __glewTexCoord3s = NULL;
+PFNGLTEXCOORD3SVPROC __glewTexCoord3sv = NULL;
+PFNGLTEXCOORD4DPROC __glewTexCoord4d = NULL;
+PFNGLTEXCOORD4DVPROC __glewTexCoord4dv = NULL;
+PFNGLTEXCOORD4FPROC __glewTexCoord4f = NULL;
+PFNGLTEXCOORD4FVPROC __glewTexCoord4fv = NULL;
+PFNGLTEXCOORD4IPROC __glewTexCoord4i = NULL;
+PFNGLTEXCOORD4IVPROC __glewTexCoord4iv = NULL;
+PFNGLTEXCOORD4SPROC __glewTexCoord4s = NULL;
+PFNGLTEXCOORD4SVPROC __glewTexCoord4sv = NULL;
+PFNGLTEXENVIPROC __glewTexEnvi = NULL;
+PFNGLTEXENVIVPROC __glewTexEnviv = NULL;
+PFNGLTEXGENDPROC __glewTexGend = NULL;
+PFNGLTEXGENDVPROC __glewTexGendv = NULL;
+PFNGLTEXGENFPROC __glewTexGenf = NULL;
+PFNGLTEXGENFVPROC __glewTexGenfv = NULL;
+PFNGLTEXGENIPROC __glewTexGeni = NULL;
+PFNGLTEXGENIVPROC __glewTexGeniv = NULL;
+PFNGLTEXIMAGE1DPROC __glewTexImage1D = NULL;
+PFNGLTEXPARAMETERFVPROC __glewTexParameterfv = NULL;
+PFNGLTEXPARAMETERIPROC __glewTexParameteri = NULL;
+PFNGLTEXPARAMETERIVPROC __glewTexParameteriv = NULL;
+PFNGLTEXSUBIMAGE1DPROC __glewTexSubImage1D = NULL;
+PFNGLTRANSLATEDPROC __glewTranslated = NULL;
+PFNGLVERTEX2DPROC __glewVertex2d = NULL;
+PFNGLVERTEX2DVPROC __glewVertex2dv = NULL;
+PFNGLVERTEX2FPROC __glewVertex2f = NULL;
+PFNGLVERTEX2FVPROC __glewVertex2fv = NULL;
+PFNGLVERTEX2IPROC __glewVertex2i = NULL;
+PFNGLVERTEX2IVPROC __glewVertex2iv = NULL;
+PFNGLVERTEX2SPROC __glewVertex2s = NULL;
+PFNGLVERTEX2SVPROC __glewVertex2sv = NULL;
+PFNGLVERTEX3DPROC __glewVertex3d = NULL;
+PFNGLVERTEX3DVPROC __glewVertex3dv = NULL;
+PFNGLVERTEX3FPROC __glewVertex3f = NULL;
+PFNGLVERTEX3FVPROC __glewVertex3fv = NULL;
+PFNGLVERTEX3IPROC __glewVertex3i = NULL;
+PFNGLVERTEX3IVPROC __glewVertex3iv = NULL;
+PFNGLVERTEX3SPROC __glewVertex3s = NULL;
+PFNGLVERTEX3SVPROC __glewVertex3sv = NULL;
+PFNGLVERTEX4DPROC __glewVertex4d = NULL;
+PFNGLVERTEX4DVPROC __glewVertex4dv = NULL;
+PFNGLVERTEX4FPROC __glewVertex4f = NULL;
+PFNGLVERTEX4FVPROC __glewVertex4fv = NULL;
+PFNGLVERTEX4IPROC __glewVertex4i = NULL;
+PFNGLVERTEX4IVPROC __glewVertex4iv = NULL;
+PFNGLVERTEX4SPROC __glewVertex4s = NULL;
+PFNGLVERTEX4SVPROC __glewVertex4sv = NULL;
+
+PFNGLCOPYTEXSUBIMAGE3DPROC __glewCopyTexSubImage3D = NULL;
+PFNGLDRAWRANGEELEMENTSPROC __glewDrawRangeElements = NULL;
+PFNGLTEXIMAGE3DPROC __glewTexImage3D = NULL;
+PFNGLTEXSUBIMAGE3DPROC __glewTexSubImage3D = NULL;
+
+PFNGLACTIVETEXTUREPROC __glewActiveTexture = NULL;
+PFNGLCLIENTACTIVETEXTUREPROC __glewClientActiveTexture = NULL;
+PFNGLCOMPRESSEDTEXIMAGE1DPROC __glewCompressedTexImage1D = NULL;
+PFNGLCOMPRESSEDTEXIMAGE2DPROC __glewCompressedTexImage2D = NULL;
+PFNGLCOMPRESSEDTEXIMAGE3DPROC __glewCompressedTexImage3D = NULL;
+PFNGLCOMPRESSEDTEXSUBIMAGE1DPROC __glewCompressedTexSubImage1D = NULL;
+PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC __glewCompressedTexSubImage2D = NULL;
+PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC __glewCompressedTexSubImage3D = NULL;
+PFNGLGETCOMPRESSEDTEXIMAGEPROC __glewGetCompressedTexImage = NULL;
+PFNGLLOADTRANSPOSEMATRIXDPROC __glewLoadTransposeMatrixd = NULL;
+PFNGLLOADTRANSPOSEMATRIXFPROC __glewLoadTransposeMatrixf = NULL;
+PFNGLMULTTRANSPOSEMATRIXDPROC __glewMultTransposeMatrixd = NULL;
+PFNGLMULTTRANSPOSEMATRIXFPROC __glewMultTransposeMatrixf = NULL;
+PFNGLMULTITEXCOORD1DPROC __glewMultiTexCoord1d = NULL;
+PFNGLMULTITEXCOORD1DVPROC __glewMultiTexCoord1dv = NULL;
+PFNGLMULTITEXCOORD1FPROC __glewMultiTexCoord1f = NULL;
+PFNGLMULTITEXCOORD1FVPROC __glewMultiTexCoord1fv = NULL;
+PFNGLMULTITEXCOORD1IPROC __glewMultiTexCoord1i = NULL;
+PFNGLMULTITEXCOORD1IVPROC __glewMultiTexCoord1iv = NULL;
+PFNGLMULTITEXCOORD1SPROC __glewMultiTexCoord1s = NULL;
+PFNGLMULTITEXCOORD1SVPROC __glewMultiTexCoord1sv = NULL;
+PFNGLMULTITEXCOORD2DPROC __glewMultiTexCoord2d = NULL;
+PFNGLMULTITEXCOORD2DVPROC __glewMultiTexCoord2dv = NULL;
+PFNGLMULTITEXCOORD2FPROC __glewMultiTexCoord2f = NULL;
+PFNGLMULTITEXCOORD2FVPROC __glewMultiTexCoord2fv = NULL;
+PFNGLMULTITEXCOORD2IPROC __glewMultiTexCoord2i = NULL;
+PFNGLMULTITEXCOORD2IVPROC __glewMultiTexCoord2iv = NULL;
+PFNGLMULTITEXCOORD2SPROC __glewMultiTexCoord2s = NULL;
+PFNGLMULTITEXCOORD2SVPROC __glewMultiTexCoord2sv = NULL;
+PFNGLMULTITEXCOORD3DPROC __glewMultiTexCoord3d = NULL;
+PFNGLMULTITEXCOORD3DVPROC __glewMultiTexCoord3dv = NULL;
+PFNGLMULTITEXCOORD3FPROC __glewMultiTexCoord3f = NULL;
+PFNGLMULTITEXCOORD3FVPROC __glewMultiTexCoord3fv = NULL;
+PFNGLMULTITEXCOORD3IPROC __glewMultiTexCoord3i = NULL;
+PFNGLMULTITEXCOORD3IVPROC __glewMultiTexCoord3iv = NULL;
+PFNGLMULTITEXCOORD3SPROC __glewMultiTexCoord3s = NULL;
+PFNGLMULTITEXCOORD3SVPROC __glewMultiTexCoord3sv = NULL;
+PFNGLMULTITEXCOORD4DPROC __glewMultiTexCoord4d = NULL;
+PFNGLMULTITEXCOORD4DVPROC __glewMultiTexCoord4dv = NULL;
+PFNGLMULTITEXCOORD4FPROC __glewMultiTexCoord4f = NULL;
+PFNGLMULTITEXCOORD4FVPROC __glewMultiTexCoord4fv = NULL;
+PFNGLMULTITEXCOORD4IPROC __glewMultiTexCoord4i = NULL;
+PFNGLMULTITEXCOORD4IVPROC __glewMultiTexCoord4iv = NULL;
+PFNGLMULTITEXCOORD4SPROC __glewMultiTexCoord4s = NULL;
+PFNGLMULTITEXCOORD4SVPROC __glewMultiTexCoord4sv = NULL;
+PFNGLSAMPLECOVERAGEPROC __glewSampleCoverage = NULL;
+
+PFNGLBLENDCOLORPROC __glewBlendColor = NULL;
+PFNGLBLENDEQUATIONPROC __glewBlendEquation = NULL;
+PFNGLBLENDFUNCSEPARATEPROC __glewBlendFuncSeparate = NULL;
+PFNGLFOGCOORDPOINTERPROC __glewFogCoordPointer = NULL;
+PFNGLFOGCOORDDPROC __glewFogCoordd = NULL;
+PFNGLFOGCOORDDVPROC __glewFogCoorddv = NULL;
+PFNGLFOGCOORDFPROC __glewFogCoordf = NULL;
+PFNGLFOGCOORDFVPROC __glewFogCoordfv = NULL;
+PFNGLMULTIDRAWARRAYSPROC __glewMultiDrawArrays = NULL;
+PFNGLMULTIDRAWELEMENTSPROC __glewMultiDrawElements = NULL;
+PFNGLPOINTPARAMETERFPROC __glewPointParameterf = NULL;
+PFNGLPOINTPARAMETERFVPROC __glewPointParameterfv = NULL;
+PFNGLPOINTPARAMETERIPROC __glewPointParameteri = NULL;
+PFNGLPOINTPARAMETERIVPROC __glewPointParameteriv = NULL;
+PFNGLSECONDARYCOLOR3BPROC __glewSecondaryColor3b = NULL;
+PFNGLSECONDARYCOLOR3BVPROC __glewSecondaryColor3bv = NULL;
+PFNGLSECONDARYCOLOR3DPROC __glewSecondaryColor3d = NULL;
+PFNGLSECONDARYCOLOR3DVPROC __glewSecondaryColor3dv = NULL;
+PFNGLSECONDARYCOLOR3FPROC __glewSecondaryColor3f = NULL;
+PFNGLSECONDARYCOLOR3FVPROC __glewSecondaryColor3fv = NULL;
+PFNGLSECONDARYCOLOR3IPROC __glewSecondaryColor3i = NULL;
+PFNGLSECONDARYCOLOR3IVPROC __glewSecondaryColor3iv = NULL;
+PFNGLSECONDARYCOLOR3SPROC __glewSecondaryColor3s = NULL;
+PFNGLSECONDARYCOLOR3SVPROC __glewSecondaryColor3sv = NULL;
+PFNGLSECONDARYCOLOR3UBPROC __glewSecondaryColor3ub = NULL;
+PFNGLSECONDARYCOLOR3UBVPROC __glewSecondaryColor3ubv = NULL;
+PFNGLSECONDARYCOLOR3UIPROC __glewSecondaryColor3ui = NULL;
+PFNGLSECONDARYCOLOR3UIVPROC __glewSecondaryColor3uiv = NULL;
+PFNGLSECONDARYCOLOR3USPROC __glewSecondaryColor3us = NULL;
+PFNGLSECONDARYCOLOR3USVPROC __glewSecondaryColor3usv = NULL;
+PFNGLSECONDARYCOLORPOINTERPROC __glewSecondaryColorPointer = NULL;
+PFNGLWINDOWPOS2DPROC __glewWindowPos2d = NULL;
+PFNGLWINDOWPOS2DVPROC __glewWindowPos2dv = NULL;
+PFNGLWINDOWPOS2FPROC __glewWindowPos2f = NULL;
+PFNGLWINDOWPOS2FVPROC __glewWindowPos2fv = NULL;
+PFNGLWINDOWPOS2IPROC __glewWindowPos2i = NULL;
+PFNGLWINDOWPOS2IVPROC __glewWindowPos2iv = NULL;
+PFNGLWINDOWPOS2SPROC __glewWindowPos2s = NULL;
+PFNGLWINDOWPOS2SVPROC __glewWindowPos2sv = NULL;
+PFNGLWINDOWPOS3DPROC __glewWindowPos3d = NULL;
+PFNGLWINDOWPOS3DVPROC __glewWindowPos3dv = NULL;
+PFNGLWINDOWPOS3FPROC __glewWindowPos3f = NULL;
+PFNGLWINDOWPOS3FVPROC __glewWindowPos3fv = NULL;
+PFNGLWINDOWPOS3IPROC __glewWindowPos3i = NULL;
+PFNGLWINDOWPOS3IVPROC __glewWindowPos3iv = NULL;
+PFNGLWINDOWPOS3SPROC __glewWindowPos3s = NULL;
+PFNGLWINDOWPOS3SVPROC __glewWindowPos3sv = NULL;
+
+PFNGLBEGINQUERYPROC __glewBeginQuery = NULL;
+PFNGLBINDBUFFERPROC __glewBindBuffer = NULL;
+PFNGLBUFFERDATAPROC __glewBufferData = NULL;
+PFNGLBUFFERSUBDATAPROC __glewBufferSubData = NULL;
+PFNGLDELETEBUFFERSPROC __glewDeleteBuffers = NULL;
+PFNGLDELETEQUERIESPROC __glewDeleteQueries = NULL;
+PFNGLENDQUERYPROC __glewEndQuery = NULL;
+PFNGLGENBUFFERSPROC __glewGenBuffers = NULL;
+PFNGLGENQUERIESPROC __glewGenQueries = NULL;
+PFNGLGETBUFFERPARAMETERIVPROC __glewGetBufferParameteriv = NULL;
+PFNGLGETBUFFERPOINTERVPROC __glewGetBufferPointerv = NULL;
+PFNGLGETBUFFERSUBDATAPROC __glewGetBufferSubData = NULL;
+PFNGLGETQUERYOBJECTIVPROC __glewGetQueryObjectiv = NULL;
+PFNGLGETQUERYOBJECTUIVPROC __glewGetQueryObjectuiv = NULL;
+PFNGLGETQUERYIVPROC __glewGetQueryiv = NULL;
+PFNGLISBUFFERPROC __glewIsBuffer = NULL;
+PFNGLISQUERYPROC __glewIsQuery = NULL;
+PFNGLMAPBUFFERPROC __glewMapBuffer = NULL;
+PFNGLUNMAPBUFFERPROC __glewUnmapBuffer = NULL;
+
+PFNGLATTACHSHADERPROC __glewAttachShader = NULL;
+PFNGLBINDATTRIBLOCATIONPROC __glewBindAttribLocation = NULL;
+PFNGLBLENDEQUATIONSEPARATEPROC __glewBlendEquationSeparate = NULL;
+PFNGLCOMPILESHADERPROC __glewCompileShader = NULL;
+PFNGLCREATEPROGRAMPROC __glewCreateProgram = NULL;
+PFNGLCREATESHADERPROC __glewCreateShader = NULL;
+PFNGLDELETEPROGRAMPROC __glewDeleteProgram = NULL;
+PFNGLDELETESHADERPROC __glewDeleteShader = NULL;
+PFNGLDETACHSHADERPROC __glewDetachShader = NULL;
+PFNGLDISABLEVERTEXATTRIBARRAYPROC __glewDisableVertexAttribArray = NULL;
+PFNGLDRAWBUFFERSPROC __glewDrawBuffers = NULL;
+PFNGLENABLEVERTEXATTRIBARRAYPROC __glewEnableVertexAttribArray = NULL;
+PFNGLGETACTIVEATTRIBPROC __glewGetActiveAttrib = NULL;
+PFNGLGETACTIVEUNIFORMPROC __glewGetActiveUniform = NULL;
+PFNGLGETATTACHEDSHADERSPROC __glewGetAttachedShaders = NULL;
+PFNGLGETATTRIBLOCATIONPROC __glewGetAttribLocation = NULL;
+PFNGLGETPROGRAMINFOLOGPROC __glewGetProgramInfoLog = NULL;
+PFNGLGETPROGRAMIVPROC __glewGetProgramiv = NULL;
+PFNGLGETSHADERINFOLOGPROC __glewGetShaderInfoLog = NULL;
+PFNGLGETSHADERSOURCEPROC __glewGetShaderSource = NULL;
+PFNGLGETSHADERIVPROC __glewGetShaderiv = NULL;
+PFNGLGETUNIFORMLOCATIONPROC __glewGetUniformLocation = NULL;
+PFNGLGETUNIFORMFVPROC __glewGetUniformfv = NULL;
+PFNGLGETUNIFORMIVPROC __glewGetUniformiv = NULL;
+PFNGLGETVERTEXATTRIBPOINTERVPROC __glewGetVertexAttribPointerv = NULL;
+PFNGLGETVERTEXATTRIBDVPROC __glewGetVertexAttribdv = NULL;
+PFNGLGETVERTEXATTRIBFVPROC __glewGetVertexAttribfv = NULL;
+PFNGLGETVERTEXATTRIBIVPROC __glewGetVertexAttribiv = NULL;
+PFNGLISPROGRAMPROC __glewIsProgram = NULL;
+PFNGLISSHADERPROC __glewIsShader = NULL;
+PFNGLLINKPROGRAMPROC __glewLinkProgram = NULL;
+PFNGLSHADERSOURCEPROC __glewShaderSource = NULL;
+PFNGLSTENCILFUNCSEPARATEPROC __glewStencilFuncSeparate = NULL;
+PFNGLSTENCILMASKSEPARATEPROC __glewStencilMaskSeparate = NULL;
+PFNGLSTENCILOPSEPARATEPROC __glewStencilOpSeparate = NULL;
+PFNGLUNIFORM1FPROC __glewUniform1f = NULL;
+PFNGLUNIFORM1FVPROC __glewUniform1fv = NULL;
+PFNGLUNIFORM1IPROC __glewUniform1i = NULL;
+PFNGLUNIFORM1IVPROC __glewUniform1iv = NULL;
+PFNGLUNIFORM2FPROC __glewUniform2f = NULL;
+PFNGLUNIFORM2FVPROC __glewUniform2fv = NULL;
+PFNGLUNIFORM2IPROC __glewUniform2i = NULL;
+PFNGLUNIFORM2IVPROC __glewUniform2iv = NULL;
+PFNGLUNIFORM3FPROC __glewUniform3f = NULL;
+PFNGLUNIFORM3FVPROC __glewUniform3fv = NULL;
+PFNGLUNIFORM3IPROC __glewUniform3i = NULL;
+PFNGLUNIFORM3IVPROC __glewUniform3iv = NULL;
+PFNGLUNIFORM4FPROC __glewUniform4f = NULL;
+PFNGLUNIFORM4FVPROC __glewUniform4fv = NULL;
+PFNGLUNIFORM4IPROC __glewUniform4i = NULL;
+PFNGLUNIFORM4IVPROC __glewUniform4iv = NULL;
+PFNGLUNIFORMMATRIX2FVPROC __glewUniformMatrix2fv = NULL;
+PFNGLUNIFORMMATRIX3FVPROC __glewUniformMatrix3fv = NULL;
+PFNGLUNIFORMMATRIX4FVPROC __glewUniformMatrix4fv = NULL;
+PFNGLUSEPROGRAMPROC __glewUseProgram = NULL;
+PFNGLVALIDATEPROGRAMPROC __glewValidateProgram = NULL;
+PFNGLVERTEXATTRIB1DPROC __glewVertexAttrib1d = NULL;
+PFNGLVERTEXATTRIB1DVPROC __glewVertexAttrib1dv = NULL;
+PFNGLVERTEXATTRIB1FPROC __glewVertexAttrib1f = NULL;
+PFNGLVERTEXATTRIB1FVPROC __glewVertexAttrib1fv = NULL;
+PFNGLVERTEXATTRIB1SPROC __glewVertexAttrib1s = NULL;
+PFNGLVERTEXATTRIB1SVPROC __glewVertexAttrib1sv = NULL;
+PFNGLVERTEXATTRIB2DPROC __glewVertexAttrib2d = NULL;
+PFNGLVERTEXATTRIB2DVPROC __glewVertexAttrib2dv = NULL;
+PFNGLVERTEXATTRIB2FPROC __glewVertexAttrib2f = NULL;
+PFNGLVERTEXATTRIB2FVPROC __glewVertexAttrib2fv = NULL;
+PFNGLVERTEXATTRIB2SPROC __glewVertexAttrib2s = NULL;
+PFNGLVERTEXATTRIB2SVPROC __glewVertexAttrib2sv = NULL;
+PFNGLVERTEXATTRIB3DPROC __glewVertexAttrib3d = NULL;
+PFNGLVERTEXATTRIB3DVPROC __glewVertexAttrib3dv = NULL;
+PFNGLVERTEXATTRIB3FPROC __glewVertexAttrib3f = NULL;
+PFNGLVERTEXATTRIB3FVPROC __glewVertexAttrib3fv = NULL;
+PFNGLVERTEXATTRIB3SPROC __glewVertexAttrib3s = NULL;
+PFNGLVERTEXATTRIB3SVPROC __glewVertexAttrib3sv = NULL;
+PFNGLVERTEXATTRIB4NBVPROC __glewVertexAttrib4Nbv = NULL;
+PFNGLVERTEXATTRIB4NIVPROC __glewVertexAttrib4Niv = NULL;
+PFNGLVERTEXATTRIB4NSVPROC __glewVertexAttrib4Nsv = NULL;
+PFNGLVERTEXATTRIB4NUBPROC __glewVertexAttrib4Nub = NULL;
+PFNGLVERTEXATTRIB4NUBVPROC __glewVertexAttrib4Nubv = NULL;
+PFNGLVERTEXATTRIB4NUIVPROC __glewVertexAttrib4Nuiv = NULL;
+PFNGLVERTEXATTRIB4NUSVPROC __glewVertexAttrib4Nusv = NULL;
+PFNGLVERTEXATTRIB4BVPROC __glewVertexAttrib4bv = NULL;
+PFNGLVERTEXATTRIB4DPROC __glewVertexAttrib4d = NULL;
+PFNGLVERTEXATTRIB4DVPROC __glewVertexAttrib4dv = NULL;
+PFNGLVERTEXATTRIB4FPROC __glewVertexAttrib4f = NULL;
+PFNGLVERTEXATTRIB4FVPROC __glewVertexAttrib4fv = NULL;
+PFNGLVERTEXATTRIB4IVPROC __glewVertexAttrib4iv = NULL;
+PFNGLVERTEXATTRIB4SPROC __glewVertexAttrib4s = NULL;
+PFNGLVERTEXATTRIB4SVPROC __glewVertexAttrib4sv = NULL;
+PFNGLVERTEXATTRIB4UBVPROC __glewVertexAttrib4ubv = NULL;
+PFNGLVERTEXATTRIB4UIVPROC __glewVertexAttrib4uiv = NULL;
+PFNGLVERTEXATTRIB4USVPROC __glewVertexAttrib4usv = NULL;
+PFNGLVERTEXATTRIBPOINTERPROC __glewVertexAttribPointer = NULL;
+
+PFNGLUNIFORMMATRIX2X3FVPROC __glewUniformMatrix2x3fv = NULL;
+PFNGLUNIFORMMATRIX2X4FVPROC __glewUniformMatrix2x4fv = NULL;
+PFNGLUNIFORMMATRIX3X2FVPROC __glewUniformMatrix3x2fv = NULL;
+PFNGLUNIFORMMATRIX3X4FVPROC __glewUniformMatrix3x4fv = NULL;
+PFNGLUNIFORMMATRIX4X2FVPROC __glewUniformMatrix4x2fv = NULL;
+PFNGLUNIFORMMATRIX4X3FVPROC __glewUniformMatrix4x3fv = NULL;
+
+PFNGLBEGINCONDITIONALRENDERPROC __glewBeginConditionalRender = NULL;
+PFNGLBEGINTRANSFORMFEEDBACKPROC __glewBeginTransformFeedback = NULL;
+PFNGLBINDFRAGDATALOCATIONPROC __glewBindFragDataLocation = NULL;
+PFNGLCLAMPCOLORPROC __glewClampColor = NULL;
+PFNGLCLEARBUFFERFIPROC __glewClearBufferfi = NULL;
+PFNGLCLEARBUFFERFVPROC __glewClearBufferfv = NULL;
+PFNGLCLEARBUFFERIVPROC __glewClearBufferiv = NULL;
+PFNGLCLEARBUFFERUIVPROC __glewClearBufferuiv = NULL;
+PFNGLCOLORMASKIPROC __glewColorMaski = NULL;
+PFNGLDISABLEIPROC __glewDisablei = NULL;
+PFNGLENABLEIPROC __glewEnablei = NULL;
+PFNGLENDCONDITIONALRENDERPROC __glewEndConditionalRender = NULL;
+PFNGLENDTRANSFORMFEEDBACKPROC __glewEndTransformFeedback = NULL;
+PFNGLGETBOOLEANI_VPROC __glewGetBooleani_v = NULL;
+PFNGLGETFRAGDATALOCATIONPROC __glewGetFragDataLocation = NULL;
+PFNGLGETSTRINGIPROC __glewGetStringi = NULL;
+PFNGLGETTEXPARAMETERIIVPROC __glewGetTexParameterIiv = NULL;
+PFNGLGETTEXPARAMETERIUIVPROC __glewGetTexParameterIuiv = NULL;
+PFNGLGETTRANSFORMFEEDBACKVARYINGPROC __glewGetTransformFeedbackVarying = NULL;
+PFNGLGETUNIFORMUIVPROC __glewGetUniformuiv = NULL;
+PFNGLGETVERTEXATTRIBIIVPROC __glewGetVertexAttribIiv = NULL;
+PFNGLGETVERTEXATTRIBIUIVPROC __glewGetVertexAttribIuiv = NULL;
+PFNGLISENABLEDIPROC __glewIsEnabledi = NULL;
+PFNGLTEXPARAMETERIIVPROC __glewTexParameterIiv = NULL;
+PFNGLTEXPARAMETERIUIVPROC __glewTexParameterIuiv = NULL;
+PFNGLTRANSFORMFEEDBACKVARYINGSPROC __glewTransformFeedbackVaryings = NULL;
+PFNGLUNIFORM1UIPROC __glewUniform1ui = NULL;
+PFNGLUNIFORM1UIVPROC __glewUniform1uiv = NULL;
+PFNGLUNIFORM2UIPROC __glewUniform2ui = NULL;
+PFNGLUNIFORM2UIVPROC __glewUniform2uiv = NULL;
+PFNGLUNIFORM3UIPROC __glewUniform3ui = NULL;
+PFNGLUNIFORM3UIVPROC __glewUniform3uiv = NULL;
+PFNGLUNIFORM4UIPROC __glewUniform4ui = NULL;
+PFNGLUNIFORM4UIVPROC __glewUniform4uiv = NULL;
+PFNGLVERTEXATTRIBI1IPROC __glewVertexAttribI1i = NULL;
+PFNGLVERTEXATTRIBI1IVPROC __glewVertexAttribI1iv = NULL;
+PFNGLVERTEXATTRIBI1UIPROC __glewVertexAttribI1ui = NULL;
+PFNGLVERTEXATTRIBI1UIVPROC __glewVertexAttribI1uiv = NULL;
+PFNGLVERTEXATTRIBI2IPROC __glewVertexAttribI2i = NULL;
+PFNGLVERTEXATTRIBI2IVPROC __glewVertexAttribI2iv = NULL;
+PFNGLVERTEXATTRIBI2UIPROC __glewVertexAttribI2ui = NULL;
+PFNGLVERTEXATTRIBI2UIVPROC __glewVertexAttribI2uiv = NULL;
+PFNGLVERTEXATTRIBI3IPROC __glewVertexAttribI3i = NULL;
+PFNGLVERTEXATTRIBI3IVPROC __glewVertexAttribI3iv = NULL;
+PFNGLVERTEXATTRIBI3UIPROC __glewVertexAttribI3ui = NULL;
+PFNGLVERTEXATTRIBI3UIVPROC __glewVertexAttribI3uiv = NULL;
+PFNGLVERTEXATTRIBI4BVPROC __glewVertexAttribI4bv = NULL;
+PFNGLVERTEXATTRIBI4IPROC __glewVertexAttribI4i = NULL;
+PFNGLVERTEXATTRIBI4IVPROC __glewVertexAttribI4iv = NULL;
+PFNGLVERTEXATTRIBI4SVPROC __glewVertexAttribI4sv = NULL;
+PFNGLVERTEXATTRIBI4UBVPROC __glewVertexAttribI4ubv = NULL;
+PFNGLVERTEXATTRIBI4UIPROC __glewVertexAttribI4ui = NULL;
+PFNGLVERTEXATTRIBI4UIVPROC __glewVertexAttribI4uiv = NULL;
+PFNGLVERTEXATTRIBI4USVPROC __glewVertexAttribI4usv = NULL;
+PFNGLVERTEXATTRIBIPOINTERPROC __glewVertexAttribIPointer = NULL;
+
+PFNGLDRAWARRAYSINSTANCEDPROC __glewDrawArraysInstanced = NULL;
+PFNGLDRAWELEMENTSINSTANCEDPROC __glewDrawElementsInstanced = NULL;
+PFNGLPRIMITIVERESTARTINDEXPROC __glewPrimitiveRestartIndex = NULL;
+PFNGLTEXBUFFERPROC __glewTexBuffer = NULL;
+
+PFNGLFRAMEBUFFERTEXTUREPROC __glewFramebufferTexture = NULL;
+PFNGLGETBUFFERPARAMETERI64VPROC __glewGetBufferParameteri64v = NULL;
+PFNGLGETINTEGER64I_VPROC __glewGetInteger64i_v = NULL;
+
+PFNGLVERTEXATTRIBDIVISORPROC __glewVertexAttribDivisor = NULL;
+
+PFNGLBLENDEQUATIONSEPARATEIPROC __glewBlendEquationSeparatei = NULL;
+PFNGLBLENDEQUATIONIPROC __glewBlendEquationi = NULL;
+PFNGLBLENDFUNCSEPARATEIPROC __glewBlendFuncSeparatei = NULL;
+PFNGLBLENDFUNCIPROC __glewBlendFunci = NULL;
+PFNGLMINSAMPLESHADINGPROC __glewMinSampleShading = NULL;
+
+PFNGLTBUFFERMASK3DFXPROC __glewTbufferMask3DFX = NULL;
+
+PFNGLDEBUGMESSAGECALLBACKAMDPROC __glewDebugMessageCallbackAMD = NULL;
+PFNGLDEBUGMESSAGEENABLEAMDPROC __glewDebugMessageEnableAMD = NULL;
+PFNGLDEBUGMESSAGEINSERTAMDPROC __glewDebugMessageInsertAMD = NULL;
+PFNGLGETDEBUGMESSAGELOGAMDPROC __glewGetDebugMessageLogAMD = NULL;
+
+PFNGLBLENDEQUATIONINDEXEDAMDPROC __glewBlendEquationIndexedAMD = NULL;
+PFNGLBLENDEQUATIONSEPARATEINDEXEDAMDPROC __glewBlendEquationSeparateIndexedAMD = NULL;
+PFNGLBLENDFUNCINDEXEDAMDPROC __glewBlendFuncIndexedAMD = NULL;
+PFNGLBLENDFUNCSEPARATEINDEXEDAMDPROC __glewBlendFuncSeparateIndexedAMD = NULL;
+
+PFNGLMULTIDRAWARRAYSINDIRECTAMDPROC __glewMultiDrawArraysIndirectAMD = NULL;
+PFNGLMULTIDRAWELEMENTSINDIRECTAMDPROC __glewMultiDrawElementsIndirectAMD = NULL;
+
+PFNGLDELETENAMESAMDPROC __glewDeleteNamesAMD = NULL;
+PFNGLGENNAMESAMDPROC __glewGenNamesAMD = NULL;
+PFNGLISNAMEAMDPROC __glewIsNameAMD = NULL;
+
+PFNGLBEGINPERFMONITORAMDPROC __glewBeginPerfMonitorAMD = NULL;
+PFNGLDELETEPERFMONITORSAMDPROC __glewDeletePerfMonitorsAMD = NULL;
+PFNGLENDPERFMONITORAMDPROC __glewEndPerfMonitorAMD = NULL;
+PFNGLGENPERFMONITORSAMDPROC __glewGenPerfMonitorsAMD = NULL;
+PFNGLGETPERFMONITORCOUNTERDATAAMDPROC __glewGetPerfMonitorCounterDataAMD = NULL;
+PFNGLGETPERFMONITORCOUNTERINFOAMDPROC __glewGetPerfMonitorCounterInfoAMD = NULL;
+PFNGLGETPERFMONITORCOUNTERSTRINGAMDPROC __glewGetPerfMonitorCounterStringAMD = NULL;
+PFNGLGETPERFMONITORCOUNTERSAMDPROC __glewGetPerfMonitorCountersAMD = NULL;
+PFNGLGETPERFMONITORGROUPSTRINGAMDPROC __glewGetPerfMonitorGroupStringAMD = NULL;
+PFNGLGETPERFMONITORGROUPSAMDPROC __glewGetPerfMonitorGroupsAMD = NULL;
+PFNGLSELECTPERFMONITORCOUNTERSAMDPROC __glewSelectPerfMonitorCountersAMD = NULL;
+
+PFNGLSETMULTISAMPLEFVAMDPROC __glewSetMultisamplefvAMD = NULL;
+
+PFNGLTEXSTORAGESPARSEAMDPROC __glewTexStorageSparseAMD = NULL;
+PFNGLTEXTURESTORAGESPARSEAMDPROC __glewTextureStorageSparseAMD = NULL;
+
+PFNGLSTENCILOPVALUEAMDPROC __glewStencilOpValueAMD = NULL;
+
+PFNGLTESSELLATIONFACTORAMDPROC __glewTessellationFactorAMD = NULL;
+PFNGLTESSELLATIONMODEAMDPROC __glewTessellationModeAMD = NULL;
+
+PFNGLDRAWELEMENTARRAYAPPLEPROC __glewDrawElementArrayAPPLE = NULL;
+PFNGLDRAWRANGEELEMENTARRAYAPPLEPROC __glewDrawRangeElementArrayAPPLE = NULL;
+PFNGLELEMENTPOINTERAPPLEPROC __glewElementPointerAPPLE = NULL;
+PFNGLMULTIDRAWELEMENTARRAYAPPLEPROC __glewMultiDrawElementArrayAPPLE = NULL;
+PFNGLMULTIDRAWRANGEELEMENTARRAYAPPLEPROC __glewMultiDrawRangeElementArrayAPPLE = NULL;
+
+PFNGLDELETEFENCESAPPLEPROC __glewDeleteFencesAPPLE = NULL;
+PFNGLFINISHFENCEAPPLEPROC __glewFinishFenceAPPLE = NULL;
+PFNGLFINISHOBJECTAPPLEPROC __glewFinishObjectAPPLE = NULL;
+PFNGLGENFENCESAPPLEPROC __glewGenFencesAPPLE = NULL;
+PFNGLISFENCEAPPLEPROC __glewIsFenceAPPLE = NULL;
+PFNGLSETFENCEAPPLEPROC __glewSetFenceAPPLE = NULL;
+PFNGLTESTFENCEAPPLEPROC __glewTestFenceAPPLE = NULL;
+PFNGLTESTOBJECTAPPLEPROC __glewTestObjectAPPLE = NULL;
+
+PFNGLBUFFERPARAMETERIAPPLEPROC __glewBufferParameteriAPPLE = NULL;
+PFNGLFLUSHMAPPEDBUFFERRANGEAPPLEPROC __glewFlushMappedBufferRangeAPPLE = NULL;
+
+PFNGLGETOBJECTPARAMETERIVAPPLEPROC __glewGetObjectParameterivAPPLE = NULL;
+PFNGLOBJECTPURGEABLEAPPLEPROC __glewObjectPurgeableAPPLE = NULL;
+PFNGLOBJECTUNPURGEABLEAPPLEPROC __glewObjectUnpurgeableAPPLE = NULL;
+
+PFNGLGETTEXPARAMETERPOINTERVAPPLEPROC __glewGetTexParameterPointervAPPLE = NULL;
+PFNGLTEXTURERANGEAPPLEPROC __glewTextureRangeAPPLE = NULL;
+
+PFNGLBINDVERTEXARRAYAPPLEPROC __glewBindVertexArrayAPPLE = NULL;
+PFNGLDELETEVERTEXARRAYSAPPLEPROC __glewDeleteVertexArraysAPPLE = NULL;
+PFNGLGENVERTEXARRAYSAPPLEPROC __glewGenVertexArraysAPPLE = NULL;
+PFNGLISVERTEXARRAYAPPLEPROC __glewIsVertexArrayAPPLE = NULL;
+
+PFNGLFLUSHVERTEXARRAYRANGEAPPLEPROC __glewFlushVertexArrayRangeAPPLE = NULL;
+PFNGLVERTEXARRAYPARAMETERIAPPLEPROC __glewVertexArrayParameteriAPPLE = NULL;
+PFNGLVERTEXARRAYRANGEAPPLEPROC __glewVertexArrayRangeAPPLE = NULL;
+
+PFNGLDISABLEVERTEXATTRIBAPPLEPROC __glewDisableVertexAttribAPPLE = NULL;
+PFNGLENABLEVERTEXATTRIBAPPLEPROC __glewEnableVertexAttribAPPLE = NULL;
+PFNGLISVERTEXATTRIBENABLEDAPPLEPROC __glewIsVertexAttribEnabledAPPLE = NULL;
+PFNGLMAPVERTEXATTRIB1DAPPLEPROC __glewMapVertexAttrib1dAPPLE = NULL;
+PFNGLMAPVERTEXATTRIB1FAPPLEPROC __glewMapVertexAttrib1fAPPLE = NULL;
+PFNGLMAPVERTEXATTRIB2DAPPLEPROC __glewMapVertexAttrib2dAPPLE = NULL;
+PFNGLMAPVERTEXATTRIB2FAPPLEPROC __glewMapVertexAttrib2fAPPLE = NULL;
+
+PFNGLCLEARDEPTHFPROC __glewClearDepthf = NULL;
+PFNGLDEPTHRANGEFPROC __glewDepthRangef = NULL;
+PFNGLGETSHADERPRECISIONFORMATPROC __glewGetShaderPrecisionFormat = NULL;
+PFNGLRELEASESHADERCOMPILERPROC __glewReleaseShaderCompiler = NULL;
+PFNGLSHADERBINARYPROC __glewShaderBinary = NULL;
+
+PFNGLDRAWARRAYSINSTANCEDBASEINSTANCEPROC __glewDrawArraysInstancedBaseInstance = NULL;
+PFNGLDRAWELEMENTSINSTANCEDBASEINSTANCEPROC __glewDrawElementsInstancedBaseInstance = NULL;
+PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXBASEINSTANCEPROC __glewDrawElementsInstancedBaseVertexBaseInstance = NULL;
+
+PFNGLBINDFRAGDATALOCATIONINDEXEDPROC __glewBindFragDataLocationIndexed = NULL;
+PFNGLGETFRAGDATAINDEXPROC __glewGetFragDataIndex = NULL;
+
+PFNGLCREATESYNCFROMCLEVENTARBPROC __glewCreateSyncFromCLeventARB = NULL;
+
+PFNGLCLEARBUFFERDATAPROC __glewClearBufferData = NULL;
+PFNGLCLEARBUFFERSUBDATAPROC __glewClearBufferSubData = NULL;
+PFNGLCLEARNAMEDBUFFERDATAEXTPROC __glewClearNamedBufferDataEXT = NULL;
+PFNGLCLEARNAMEDBUFFERSUBDATAEXTPROC __glewClearNamedBufferSubDataEXT = NULL;
+
+PFNGLCLAMPCOLORARBPROC __glewClampColorARB = NULL;
+
+PFNGLDISPATCHCOMPUTEPROC __glewDispatchCompute = NULL;
+PFNGLDISPATCHCOMPUTEINDIRECTPROC __glewDispatchComputeIndirect = NULL;
+
+PFNGLCOPYBUFFERSUBDATAPROC __glewCopyBufferSubData = NULL;
+
+PFNGLCOPYIMAGESUBDATAPROC __glewCopyImageSubData = NULL;
+
+PFNGLDEBUGMESSAGECALLBACKARBPROC __glewDebugMessageCallbackARB = NULL;
+PFNGLDEBUGMESSAGECONTROLARBPROC __glewDebugMessageControlARB = NULL;
+PFNGLDEBUGMESSAGEINSERTARBPROC __glewDebugMessageInsertARB = NULL;
+PFNGLGETDEBUGMESSAGELOGARBPROC __glewGetDebugMessageLogARB = NULL;
+
+PFNGLDRAWBUFFERSARBPROC __glewDrawBuffersARB = NULL;
+
+PFNGLBLENDEQUATIONSEPARATEIARBPROC __glewBlendEquationSeparateiARB = NULL;
+PFNGLBLENDEQUATIONIARBPROC __glewBlendEquationiARB = NULL;
+PFNGLBLENDFUNCSEPARATEIARBPROC __glewBlendFuncSeparateiARB = NULL;
+PFNGLBLENDFUNCIARBPROC __glewBlendFunciARB = NULL;
+
+PFNGLDRAWELEMENTSBASEVERTEXPROC __glewDrawElementsBaseVertex = NULL;
+PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXPROC __glewDrawElementsInstancedBaseVertex = NULL;
+PFNGLDRAWRANGEELEMENTSBASEVERTEXPROC __glewDrawRangeElementsBaseVertex = NULL;
+PFNGLMULTIDRAWELEMENTSBASEVERTEXPROC __glewMultiDrawElementsBaseVertex = NULL;
+
+PFNGLDRAWARRAYSINDIRECTPROC __glewDrawArraysIndirect = NULL;
+PFNGLDRAWELEMENTSINDIRECTPROC __glewDrawElementsIndirect = NULL;
+
+PFNGLFRAMEBUFFERPARAMETERIPROC __glewFramebufferParameteri = NULL;
+PFNGLGETFRAMEBUFFERPARAMETERIVPROC __glewGetFramebufferParameteriv = NULL;
+PFNGLGETNAMEDFRAMEBUFFERPARAMETERIVEXTPROC __glewGetNamedFramebufferParameterivEXT = NULL;
+PFNGLNAMEDFRAMEBUFFERPARAMETERIEXTPROC __glewNamedFramebufferParameteriEXT = NULL;
+
+PFNGLBINDFRAMEBUFFERPROC __glewBindFramebuffer = NULL;
+PFNGLBINDRENDERBUFFERPROC __glewBindRenderbuffer = NULL;
+PFNGLBLITFRAMEBUFFERPROC __glewBlitFramebuffer = NULL;
+PFNGLCHECKFRAMEBUFFERSTATUSPROC __glewCheckFramebufferStatus = NULL;
+PFNGLDELETEFRAMEBUFFERSPROC __glewDeleteFramebuffers = NULL;
+PFNGLDELETERENDERBUFFERSPROC __glewDeleteRenderbuffers = NULL;
+PFNGLFRAMEBUFFERRENDERBUFFERPROC __glewFramebufferRenderbuffer = NULL;
+PFNGLFRAMEBUFFERTEXTURE1DPROC __glewFramebufferTexture1D = NULL;
+PFNGLFRAMEBUFFERTEXTURE2DPROC __glewFramebufferTexture2D = NULL;
+PFNGLFRAMEBUFFERTEXTURE3DPROC __glewFramebufferTexture3D = NULL;
+PFNGLFRAMEBUFFERTEXTURELAYERPROC __glewFramebufferTextureLayer = NULL;
+PFNGLGENFRAMEBUFFERSPROC __glewGenFramebuffers = NULL;
+PFNGLGENRENDERBUFFERSPROC __glewGenRenderbuffers = NULL;
+PFNGLGENERATEMIPMAPPROC __glewGenerateMipmap = NULL;
+PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC __glewGetFramebufferAttachmentParameteriv = NULL;
+PFNGLGETRENDERBUFFERPARAMETERIVPROC __glewGetRenderbufferParameteriv = NULL;
+PFNGLISFRAMEBUFFERPROC __glewIsFramebuffer = NULL;
+PFNGLISRENDERBUFFERPROC __glewIsRenderbuffer = NULL;
+PFNGLRENDERBUFFERSTORAGEPROC __glewRenderbufferStorage = NULL;
+PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC __glewRenderbufferStorageMultisample = NULL;
+
+PFNGLFRAMEBUFFERTEXTUREARBPROC __glewFramebufferTextureARB = NULL;
+PFNGLFRAMEBUFFERTEXTUREFACEARBPROC __glewFramebufferTextureFaceARB = NULL;
+PFNGLFRAMEBUFFERTEXTURELAYERARBPROC __glewFramebufferTextureLayerARB = NULL;
+PFNGLPROGRAMPARAMETERIARBPROC __glewProgramParameteriARB = NULL;
+
+PFNGLGETPROGRAMBINARYPROC __glewGetProgramBinary = NULL;
+PFNGLPROGRAMBINARYPROC __glewProgramBinary = NULL;
+PFNGLPROGRAMPARAMETERIPROC __glewProgramParameteri = NULL;
+
+PFNGLGETUNIFORMDVPROC __glewGetUniformdv = NULL;
+PFNGLPROGRAMUNIFORM1DEXTPROC __glewProgramUniform1dEXT = NULL;
+PFNGLPROGRAMUNIFORM1DVEXTPROC __glewProgramUniform1dvEXT = NULL;
+PFNGLPROGRAMUNIFORM2DEXTPROC __glewProgramUniform2dEXT = NULL;
+PFNGLPROGRAMUNIFORM2DVEXTPROC __glewProgramUniform2dvEXT = NULL;
+PFNGLPROGRAMUNIFORM3DEXTPROC __glewProgramUniform3dEXT = NULL;
+PFNGLPROGRAMUNIFORM3DVEXTPROC __glewProgramUniform3dvEXT = NULL;
+PFNGLPROGRAMUNIFORM4DEXTPROC __glewProgramUniform4dEXT = NULL;
+PFNGLPROGRAMUNIFORM4DVEXTPROC __glewProgramUniform4dvEXT = NULL;
+PFNGLPROGRAMUNIFORMMATRIX2DVEXTPROC __glewProgramUniformMatrix2dvEXT = NULL;
+PFNGLPROGRAMUNIFORMMATRIX2X3DVEXTPROC __glewProgramUniformMatrix2x3dvEXT = NULL;
+PFNGLPROGRAMUNIFORMMATRIX2X4DVEXTPROC __glewProgramUniformMatrix2x4dvEXT = NULL;
+PFNGLPROGRAMUNIFORMMATRIX3DVEXTPROC __glewProgramUniformMatrix3dvEXT = NULL;
+PFNGLPROGRAMUNIFORMMATRIX3X2DVEXTPROC __glewProgramUniformMatrix3x2dvEXT = NULL;
+PFNGLPROGRAMUNIFORMMATRIX3X4DVEXTPROC __glewProgramUniformMatrix3x4dvEXT = NULL;
+PFNGLPROGRAMUNIFORMMATRIX4DVEXTPROC __glewProgramUniformMatrix4dvEXT = NULL;
+PFNGLPROGRAMUNIFORMMATRIX4X2DVEXTPROC __glewProgramUniformMatrix4x2dvEXT = NULL;
+PFNGLPROGRAMUNIFORMMATRIX4X3DVEXTPROC __glewProgramUniformMatrix4x3dvEXT = NULL;
+PFNGLUNIFORM1DPROC __glewUniform1d = NULL;
+PFNGLUNIFORM1DVPROC __glewUniform1dv = NULL;
+PFNGLUNIFORM2DPROC __glewUniform2d = NULL;
+PFNGLUNIFORM2DVPROC __glewUniform2dv = NULL;
+PFNGLUNIFORM3DPROC __glewUniform3d = NULL;
+PFNGLUNIFORM3DVPROC __glewUniform3dv = NULL;
+PFNGLUNIFORM4DPROC __glewUniform4d = NULL;
+PFNGLUNIFORM4DVPROC __glewUniform4dv = NULL;
+PFNGLUNIFORMMATRIX2DVPROC __glewUniformMatrix2dv = NULL;
+PFNGLUNIFORMMATRIX2X3DVPROC __glewUniformMatrix2x3dv = NULL;
+PFNGLUNIFORMMATRIX2X4DVPROC __glewUniformMatrix2x4dv = NULL;
+PFNGLUNIFORMMATRIX3DVPROC __glewUniformMatrix3dv = NULL;
+PFNGLUNIFORMMATRIX3X2DVPROC __glewUniformMatrix3x2dv = NULL;
+PFNGLUNIFORMMATRIX3X4DVPROC __glewUniformMatrix3x4dv = NULL;
+PFNGLUNIFORMMATRIX4DVPROC __glewUniformMatrix4dv = NULL;
+PFNGLUNIFORMMATRIX4X2DVPROC __glewUniformMatrix4x2dv = NULL;
+PFNGLUNIFORMMATRIX4X3DVPROC __glewUniformMatrix4x3dv = NULL;
+
+PFNGLCOLORSUBTABLEPROC __glewColorSubTable = NULL;
+PFNGLCOLORTABLEPROC __glewColorTable = NULL;
+PFNGLCOLORTABLEPARAMETERFVPROC __glewColorTableParameterfv = NULL;
+PFNGLCOLORTABLEPARAMETERIVPROC __glewColorTableParameteriv = NULL;
+PFNGLCONVOLUTIONFILTER1DPROC __glewConvolutionFilter1D = NULL;
+PFNGLCONVOLUTIONFILTER2DPROC __glewConvolutionFilter2D = NULL;
+PFNGLCONVOLUTIONPARAMETERFPROC __glewConvolutionParameterf = NULL;
+PFNGLCONVOLUTIONPARAMETERFVPROC __glewConvolutionParameterfv = NULL;
+PFNGLCONVOLUTIONPARAMETERIPROC __glewConvolutionParameteri = NULL;
+PFNGLCONVOLUTIONPARAMETERIVPROC __glewConvolutionParameteriv = NULL;
+PFNGLCOPYCOLORSUBTABLEPROC __glewCopyColorSubTable = NULL;
+PFNGLCOPYCOLORTABLEPROC __glewCopyColorTable = NULL;
+PFNGLCOPYCONVOLUTIONFILTER1DPROC __glewCopyConvolutionFilter1D = NULL;
+PFNGLCOPYCONVOLUTIONFILTER2DPROC __glewCopyConvolutionFilter2D = NULL;
+PFNGLGETCOLORTABLEPROC __glewGetColorTable = NULL;
+PFNGLGETCOLORTABLEPARAMETERFVPROC __glewGetColorTableParameterfv = NULL;
+PFNGLGETCOLORTABLEPARAMETERIVPROC __glewGetColorTableParameteriv = NULL;
+PFNGLGETCONVOLUTIONFILTERPROC __glewGetConvolutionFilter = NULL;
+PFNGLGETCONVOLUTIONPARAMETERFVPROC __glewGetConvolutionParameterfv = NULL;
+PFNGLGETCONVOLUTIONPARAMETERIVPROC __glewGetConvolutionParameteriv = NULL;
+PFNGLGETHISTOGRAMPROC __glewGetHistogram = NULL;
+PFNGLGETHISTOGRAMPARAMETERFVPROC __glewGetHistogramParameterfv = NULL;
+PFNGLGETHISTOGRAMPARAMETERIVPROC __glewGetHistogramParameteriv = NULL;
+PFNGLGETMINMAXPROC __glewGetMinmax = NULL;
+PFNGLGETMINMAXPARAMETERFVPROC __glewGetMinmaxParameterfv = NULL;
+PFNGLGETMINMAXPARAMETERIVPROC __glewGetMinmaxParameteriv = NULL;
+PFNGLGETSEPARABLEFILTERPROC __glewGetSeparableFilter = NULL;
+PFNGLHISTOGRAMPROC __glewHistogram = NULL;
+PFNGLMINMAXPROC __glewMinmax = NULL;
+PFNGLRESETHISTOGRAMPROC __glewResetHistogram = NULL;
+PFNGLRESETMINMAXPROC __glewResetMinmax = NULL;
+PFNGLSEPARABLEFILTER2DPROC __glewSeparableFilter2D = NULL;
+
+PFNGLDRAWARRAYSINSTANCEDARBPROC __glewDrawArraysInstancedARB = NULL;
+PFNGLDRAWELEMENTSINSTANCEDARBPROC __glewDrawElementsInstancedARB = NULL;
+PFNGLVERTEXATTRIBDIVISORARBPROC __glewVertexAttribDivisorARB = NULL;
+
+PFNGLGETINTERNALFORMATIVPROC __glewGetInternalformativ = NULL;
+
+PFNGLGETINTERNALFORMATI64VPROC __glewGetInternalformati64v = NULL;
+
+PFNGLINVALIDATEBUFFERDATAPROC __glewInvalidateBufferData = NULL;
+PFNGLINVALIDATEBUFFERSUBDATAPROC __glewInvalidateBufferSubData = NULL;
+PFNGLINVALIDATEFRAMEBUFFERPROC __glewInvalidateFramebuffer = NULL;
+PFNGLINVALIDATESUBFRAMEBUFFERPROC __glewInvalidateSubFramebuffer = NULL;
+PFNGLINVALIDATETEXIMAGEPROC __glewInvalidateTexImage = NULL;
+PFNGLINVALIDATETEXSUBIMAGEPROC __glewInvalidateTexSubImage = NULL;
+
+PFNGLFLUSHMAPPEDBUFFERRANGEPROC __glewFlushMappedBufferRange = NULL;
+PFNGLMAPBUFFERRANGEPROC __glewMapBufferRange = NULL;
+
+PFNGLCURRENTPALETTEMATRIXARBPROC __glewCurrentPaletteMatrixARB = NULL;
+PFNGLMATRIXINDEXPOINTERARBPROC __glewMatrixIndexPointerARB = NULL;
+PFNGLMATRIXINDEXUBVARBPROC __glewMatrixIndexubvARB = NULL;
+PFNGLMATRIXINDEXUIVARBPROC __glewMatrixIndexuivARB = NULL;
+PFNGLMATRIXINDEXUSVARBPROC __glewMatrixIndexusvARB = NULL;
+
+PFNGLMULTIDRAWARRAYSINDIRECTPROC __glewMultiDrawArraysIndirect = NULL;
+PFNGLMULTIDRAWELEMENTSINDIRECTPROC __glewMultiDrawElementsIndirect = NULL;
+
+PFNGLSAMPLECOVERAGEARBPROC __glewSampleCoverageARB = NULL;
+
+PFNGLACTIVETEXTUREARBPROC __glewActiveTextureARB = NULL;
+PFNGLCLIENTACTIVETEXTUREARBPROC __glewClientActiveTextureARB = NULL;
+PFNGLMULTITEXCOORD1DARBPROC __glewMultiTexCoord1dARB = NULL;
+PFNGLMULTITEXCOORD1DVARBPROC __glewMultiTexCoord1dvARB = NULL;
+PFNGLMULTITEXCOORD1FARBPROC __glewMultiTexCoord1fARB = NULL;
+PFNGLMULTITEXCOORD1FVARBPROC __glewMultiTexCoord1fvARB = NULL;
+PFNGLMULTITEXCOORD1IARBPROC __glewMultiTexCoord1iARB = NULL;
+PFNGLMULTITEXCOORD1IVARBPROC __glewMultiTexCoord1ivARB = NULL;
+PFNGLMULTITEXCOORD1SARBPROC __glewMultiTexCoord1sARB = NULL;
+PFNGLMULTITEXCOORD1SVARBPROC __glewMultiTexCoord1svARB = NULL;
+PFNGLMULTITEXCOORD2DARBPROC __glewMultiTexCoord2dARB = NULL;
+PFNGLMULTITEXCOORD2DVARBPROC __glewMultiTexCoord2dvARB = NULL;
+PFNGLMULTITEXCOORD2FARBPROC __glewMultiTexCoord2fARB = NULL;
+PFNGLMULTITEXCOORD2FVARBPROC __glewMultiTexCoord2fvARB = NULL;
+PFNGLMULTITEXCOORD2IARBPROC __glewMultiTexCoord2iARB = NULL;
+PFNGLMULTITEXCOORD2IVARBPROC __glewMultiTexCoord2ivARB = NULL;
+PFNGLMULTITEXCOORD2SARBPROC __glewMultiTexCoord2sARB = NULL;
+PFNGLMULTITEXCOORD2SVARBPROC __glewMultiTexCoord2svARB = NULL;
+PFNGLMULTITEXCOORD3DARBPROC __glewMultiTexCoord3dARB = NULL;
+PFNGLMULTITEXCOORD3DVARBPROC __glewMultiTexCoord3dvARB = NULL;
+PFNGLMULTITEXCOORD3FARBPROC __glewMultiTexCoord3fARB = NULL;
+PFNGLMULTITEXCOORD3FVARBPROC __glewMultiTexCoord3fvARB = NULL;
+PFNGLMULTITEXCOORD3IARBPROC __glewMultiTexCoord3iARB = NULL;
+PFNGLMULTITEXCOORD3IVARBPROC __glewMultiTexCoord3ivARB = NULL;
+PFNGLMULTITEXCOORD3SARBPROC __glewMultiTexCoord3sARB = NULL;
+PFNGLMULTITEXCOORD3SVARBPROC __glewMultiTexCoord3svARB = NULL;
+PFNGLMULTITEXCOORD4DARBPROC __glewMultiTexCoord4dARB = NULL;
+PFNGLMULTITEXCOORD4DVARBPROC __glewMultiTexCoord4dvARB = NULL;
+PFNGLMULTITEXCOORD4FARBPROC __glewMultiTexCoord4fARB = NULL;
+PFNGLMULTITEXCOORD4FVARBPROC __glewMultiTexCoord4fvARB = NULL;
+PFNGLMULTITEXCOORD4IARBPROC __glewMultiTexCoord4iARB = NULL;
+PFNGLMULTITEXCOORD4IVARBPROC __glewMultiTexCoord4ivARB = NULL;
+PFNGLMULTITEXCOORD4SARBPROC __glewMultiTexCoord4sARB = NULL;
+PFNGLMULTITEXCOORD4SVARBPROC __glewMultiTexCoord4svARB = NULL;
+
+PFNGLBEGINQUERYARBPROC __glewBeginQueryARB = NULL;
+PFNGLDELETEQUERIESARBPROC __glewDeleteQueriesARB = NULL;
+PFNGLENDQUERYARBPROC __glewEndQueryARB = NULL;
+PFNGLGENQUERIESARBPROC __glewGenQueriesARB = NULL;
+PFNGLGETQUERYOBJECTIVARBPROC __glewGetQueryObjectivARB = NULL;
+PFNGLGETQUERYOBJECTUIVARBPROC __glewGetQueryObjectuivARB = NULL;
+PFNGLGETQUERYIVARBPROC __glewGetQueryivARB = NULL;
+PFNGLISQUERYARBPROC __glewIsQueryARB = NULL;
+
+PFNGLPOINTPARAMETERFARBPROC __glewPointParameterfARB = NULL;
+PFNGLPOINTPARAMETERFVARBPROC __glewPointParameterfvARB = NULL;
+
+PFNGLGETPROGRAMINTERFACEIVPROC __glewGetProgramInterfaceiv = NULL;
+PFNGLGETPROGRAMRESOURCEINDEXPROC __glewGetProgramResourceIndex = NULL;
+PFNGLGETPROGRAMRESOURCELOCATIONPROC __glewGetProgramResourceLocation = NULL;
+PFNGLGETPROGRAMRESOURCELOCATIONINDEXPROC __glewGetProgramResourceLocationIndex = NULL;
+PFNGLGETPROGRAMRESOURCENAMEPROC __glewGetProgramResourceName = NULL;
+PFNGLGETPROGRAMRESOURCEIVPROC __glewGetProgramResourceiv = NULL;
+
+PFNGLPROVOKINGVERTEXPROC __glewProvokingVertex = NULL;
+
+PFNGLGETGRAPHICSRESETSTATUSARBPROC __glewGetGraphicsResetStatusARB = NULL;
+PFNGLGETNCOLORTABLEARBPROC __glewGetnColorTableARB = NULL;
+PFNGLGETNCOMPRESSEDTEXIMAGEARBPROC __glewGetnCompressedTexImageARB = NULL;
+PFNGLGETNCONVOLUTIONFILTERARBPROC __glewGetnConvolutionFilterARB = NULL;
+PFNGLGETNHISTOGRAMARBPROC __glewGetnHistogramARB = NULL;
+PFNGLGETNMAPDVARBPROC __glewGetnMapdvARB = NULL;
+PFNGLGETNMAPFVARBPROC __glewGetnMapfvARB = NULL;
+PFNGLGETNMAPIVARBPROC __glewGetnMapivARB = NULL;
+PFNGLGETNMINMAXARBPROC __glewGetnMinmaxARB = NULL;
+PFNGLGETNPIXELMAPFVARBPROC __glewGetnPixelMapfvARB = NULL;
+PFNGLGETNPIXELMAPUIVARBPROC __glewGetnPixelMapuivARB = NULL;
+PFNGLGETNPIXELMAPUSVARBPROC __glewGetnPixelMapusvARB = NULL;
+PFNGLGETNPOLYGONSTIPPLEARBPROC __glewGetnPolygonStippleARB = NULL;
+PFNGLGETNSEPARABLEFILTERARBPROC __glewGetnSeparableFilterARB = NULL;
+PFNGLGETNTEXIMAGEARBPROC __glewGetnTexImageARB = NULL;
+PFNGLGETNUNIFORMDVARBPROC __glewGetnUniformdvARB = NULL;
+PFNGLGETNUNIFORMFVARBPROC __glewGetnUniformfvARB = NULL;
+PFNGLGETNUNIFORMIVARBPROC __glewGetnUniformivARB = NULL;
+PFNGLGETNUNIFORMUIVARBPROC __glewGetnUniformuivARB = NULL;
+PFNGLREADNPIXELSARBPROC __glewReadnPixelsARB = NULL;
+
+PFNGLMINSAMPLESHADINGARBPROC __glewMinSampleShadingARB = NULL;
+
+PFNGLBINDSAMPLERPROC __glewBindSampler = NULL;
+PFNGLDELETESAMPLERSPROC __glewDeleteSamplers = NULL;
+PFNGLGENSAMPLERSPROC __glewGenSamplers = NULL;
+PFNGLGETSAMPLERPARAMETERIIVPROC __glewGetSamplerParameterIiv = NULL;
+PFNGLGETSAMPLERPARAMETERIUIVPROC __glewGetSamplerParameterIuiv = NULL;
+PFNGLGETSAMPLERPARAMETERFVPROC __glewGetSamplerParameterfv = NULL;
+PFNGLGETSAMPLERPARAMETERIVPROC __glewGetSamplerParameteriv = NULL;
+PFNGLISSAMPLERPROC __glewIsSampler = NULL;
+PFNGLSAMPLERPARAMETERIIVPROC __glewSamplerParameterIiv = NULL;
+PFNGLSAMPLERPARAMETERIUIVPROC __glewSamplerParameterIuiv = NULL;
+PFNGLSAMPLERPARAMETERFPROC __glewSamplerParameterf = NULL;
+PFNGLSAMPLERPARAMETERFVPROC __glewSamplerParameterfv = NULL;
+PFNGLSAMPLERPARAMETERIPROC __glewSamplerParameteri = NULL;
+PFNGLSAMPLERPARAMETERIVPROC __glewSamplerParameteriv = NULL;
+
+#if 0 // NOTE jwilkins: inconsistencies
+PFNGLACTIVESHADERPROGRAMPROC __glewActiveShaderProgram = NULL;
+PFNGLBINDPROGRAMPIPELINEPROC __glewBindProgramPipeline = NULL;
+PFNGLCREATESHADERPROGRAMVPROC __glewCreateShaderProgramv = NULL;
+PFNGLDELETEPROGRAMPIPELINESPROC __glewDeleteProgramPipelines = NULL;
+PFNGLGENPROGRAMPIPELINESPROC __glewGenProgramPipelines = NULL;
+PFNGLGETPROGRAMPIPELINEINFOLOGPROC __glewGetProgramPipelineInfoLog = NULL;
+PFNGLGETPROGRAMPIPELINEIVPROC __glewGetProgramPipelineiv = NULL;
+PFNGLISPROGRAMPIPELINEPROC __glewIsProgramPipeline = NULL;
+PFNGLPROGRAMUNIFORM1DPROC __glewProgramUniform1d = NULL;
+PFNGLPROGRAMUNIFORM1DVPROC __glewProgramUniform1dv = NULL;
+PFNGLPROGRAMUNIFORM1FPROC __glewProgramUniform1f = NULL;
+PFNGLPROGRAMUNIFORM1FVPROC __glewProgramUniform1fv = NULL;
+PFNGLPROGRAMUNIFORM1IPROC __glewProgramUniform1i = NULL;
+PFNGLPROGRAMUNIFORM1IVPROC __glewProgramUniform1iv = NULL;
+PFNGLPROGRAMUNIFORM1UIPROC __glewProgramUniform1ui = NULL;
+PFNGLPROGRAMUNIFORM1UIVPROC __glewProgramUniform1uiv = NULL;
+PFNGLPROGRAMUNIFORM2DPROC __glewProgramUniform2d = NULL;
+PFNGLPROGRAMUNIFORM2DVPROC __glewProgramUniform2dv = NULL;
+PFNGLPROGRAMUNIFORM2FPROC __glewProgramUniform2f = NULL;
+PFNGLPROGRAMUNIFORM2FVPROC __glewProgramUniform2fv = NULL;
+PFNGLPROGRAMUNIFORM2IPROC __glewProgramUniform2i = NULL;
+PFNGLPROGRAMUNIFORM2IVPROC __glewProgramUniform2iv = NULL;
+PFNGLPROGRAMUNIFORM2UIPROC __glewProgramUniform2ui = NULL;
+PFNGLPROGRAMUNIFORM2UIVPROC __glewProgramUniform2uiv = NULL;
+PFNGLPROGRAMUNIFORM3DPROC __glewProgramUniform3d = NULL;
+PFNGLPROGRAMUNIFORM3DVPROC __glewProgramUniform3dv = NULL;
+PFNGLPROGRAMUNIFORM3FPROC __glewProgramUniform3f = NULL;
+PFNGLPROGRAMUNIFORM3FVPROC __glewProgramUniform3fv = NULL;
+PFNGLPROGRAMUNIFORM3IPROC __glewProgramUniform3i = NULL;
+PFNGLPROGRAMUNIFORM3IVPROC __glewProgramUniform3iv = NULL;
+PFNGLPROGRAMUNIFORM3UIPROC __glewProgramUniform3ui = NULL;
+PFNGLPROGRAMUNIFORM3UIVPROC __glewProgramUniform3uiv = NULL;
+PFNGLPROGRAMUNIFORM4DPROC __glewProgramUniform4d = NULL;
+PFNGLPROGRAMUNIFORM4DVPROC __glewProgramUniform4dv = NULL;
+PFNGLPROGRAMUNIFORM4FPROC __glewProgramUniform4f = NULL;
+PFNGLPROGRAMUNIFORM4FVPROC __glewProgramUniform4fv = NULL;
+PFNGLPROGRAMUNIFORM4IPROC __glewProgramUniform4i = NULL;
+PFNGLPROGRAMUNIFORM4IVPROC __glewProgramUniform4iv = NULL;
+PFNGLPROGRAMUNIFORM4UIPROC __glewProgramUniform4ui = NULL;
+PFNGLPROGRAMUNIFORM4UIVPROC __glewProgramUniform4uiv = NULL;
+PFNGLPROGRAMUNIFORMMATRIX2DVPROC __glewProgramUniformMatrix2dv = NULL;
+PFNGLPROGRAMUNIFORMMATRIX2FVPROC __glewProgramUniformMatrix2fv = NULL;
+PFNGLPROGRAMUNIFORMMATRIX2X3DVPROC __glewProgramUniformMatrix2x3dv = NULL;
+PFNGLPROGRAMUNIFORMMATRIX2X3FVPROC __glewProgramUniformMatrix2x3fv = NULL;
+PFNGLPROGRAMUNIFORMMATRIX2X4DVPROC __glewProgramUniformMatrix2x4dv = NULL;
+PFNGLPROGRAMUNIFORMMATRIX2X4FVPROC __glewProgramUniformMatrix2x4fv = NULL;
+PFNGLPROGRAMUNIFORMMATRIX3DVPROC __glewProgramUniformMatrix3dv = NULL;
+PFNGLPROGRAMUNIFORMMATRIX3FVPROC __glewProgramUniformMatrix3fv = NULL;
+PFNGLPROGRAMUNIFORMMATRIX3X2DVPROC __glewProgramUniformMatrix3x2dv = NULL;
+PFNGLPROGRAMUNIFORMMATRIX3X2FVPROC __glewProgramUniformMatrix3x2fv = NULL;
+PFNGLPROGRAMUNIFORMMATRIX3X4DVPROC __glewProgramUniformMatrix3x4dv = NULL;
+PFNGLPROGRAMUNIFORMMATRIX3X4FVPROC __glewProgramUniformMatrix3x4fv = NULL;
+PFNGLPROGRAMUNIFORMMATRIX4DVPROC __glewProgramUniformMatrix4dv = NULL;
+PFNGLPROGRAMUNIFORMMATRIX4FVPROC __glewProgramUniformMatrix4fv = NULL;
+PFNGLPROGRAMUNIFORMMATRIX4X2DVPROC __glewProgramUniformMatrix4x2dv = NULL;
+PFNGLPROGRAMUNIFORMMATRIX4X2FVPROC __glewProgramUniformMatrix4x2fv = NULL;
+PFNGLPROGRAMUNIFORMMATRIX4X3DVPROC __glewProgramUniformMatrix4x3dv = NULL;
+PFNGLPROGRAMUNIFORMMATRIX4X3FVPROC __glewProgramUniformMatrix4x3fv = NULL;
+PFNGLUSEPROGRAMSTAGESPROC __glewUseProgramStages = NULL;
+PFNGLVALIDATEPROGRAMPIPELINEPROC __glewValidateProgramPipeline = NULL;
+#endif
+
+PFNGLGETACTIVEATOMICCOUNTERBUFFERIVPROC __glewGetActiveAtomicCounterBufferiv = NULL;
+
+PFNGLBINDIMAGETEXTUREPROC __glewBindImageTexture = NULL;
+PFNGLMEMORYBARRIERPROC __glewMemoryBarrier = NULL;
+
+PFNGLATTACHOBJECTARBPROC __glewAttachObjectARB = NULL;
+PFNGLCOMPILESHADERARBPROC __glewCompileShaderARB = NULL;
+PFNGLCREATEPROGRAMOBJECTARBPROC __glewCreateProgramObjectARB = NULL;
+PFNGLCREATESHADEROBJECTARBPROC __glewCreateShaderObjectARB = NULL;
+PFNGLDELETEOBJECTARBPROC __glewDeleteObjectARB = NULL;
+PFNGLDETACHOBJECTARBPROC __glewDetachObjectARB = NULL;
+PFNGLGETACTIVEUNIFORMARBPROC __glewGetActiveUniformARB = NULL;
+PFNGLGETATTACHEDOBJECTSARBPROC __glewGetAttachedObjectsARB = NULL;
+PFNGLGETHANDLEARBPROC __glewGetHandleARB = NULL;
+PFNGLGETINFOLOGARBPROC __glewGetInfoLogARB = NULL;
+PFNGLGETOBJECTPARAMETERFVARBPROC __glewGetObjectParameterfvARB = NULL;
+PFNGLGETOBJECTPARAMETERIVARBPROC __glewGetObjectParameterivARB = NULL;
+PFNGLGETSHADERSOURCEARBPROC __glewGetShaderSourceARB = NULL;
+PFNGLGETUNIFORMLOCATIONARBPROC __glewGetUniformLocationARB = NULL;
+PFNGLGETUNIFORMFVARBPROC __glewGetUniformfvARB = NULL;
+PFNGLGETUNIFORMIVARBPROC __glewGetUniformivARB = NULL;
+PFNGLLINKPROGRAMARBPROC __glewLinkProgramARB = NULL;
+PFNGLSHADERSOURCEARBPROC __glewShaderSourceARB = NULL;
+PFNGLUNIFORM1FARBPROC __glewUniform1fARB = NULL;
+PFNGLUNIFORM1FVARBPROC __glewUniform1fvARB = NULL;
+PFNGLUNIFORM1IARBPROC __glewUniform1iARB = NULL;
+PFNGLUNIFORM1IVARBPROC __glewUniform1ivARB = NULL;
+PFNGLUNIFORM2FARBPROC __glewUniform2fARB = NULL;
+PFNGLUNIFORM2FVARBPROC __glewUniform2fvARB = NULL;
+PFNGLUNIFORM2IARBPROC __glewUniform2iARB = NULL;
+PFNGLUNIFORM2IVARBPROC __glewUniform2ivARB = NULL;
+PFNGLUNIFORM3FARBPROC __glewUniform3fARB = NULL;
+PFNGLUNIFORM3FVARBPROC __glewUniform3fvARB = NULL;
+PFNGLUNIFORM3IARBPROC __glewUniform3iARB = NULL;
+PFNGLUNIFORM3IVARBPROC __glewUniform3ivARB = NULL;
+PFNGLUNIFORM4FARBPROC __glewUniform4fARB = NULL;
+PFNGLUNIFORM4FVARBPROC __glewUniform4fvARB = NULL;
+PFNGLUNIFORM4IARBPROC __glewUniform4iARB = NULL;
+PFNGLUNIFORM4IVARBPROC __glewUniform4ivARB = NULL;
+PFNGLUNIFORMMATRIX2FVARBPROC __glewUniformMatrix2fvARB = NULL;
+PFNGLUNIFORMMATRIX3FVARBPROC __glewUniformMatrix3fvARB = NULL;
+PFNGLUNIFORMMATRIX4FVARBPROC __glewUniformMatrix4fvARB = NULL;
+PFNGLUSEPROGRAMOBJECTARBPROC __glewUseProgramObjectARB = NULL;
+PFNGLVALIDATEPROGRAMARBPROC __glewValidateProgramARB = NULL;
+
+PFNGLSHADERSTORAGEBLOCKBINDINGPROC __glewShaderStorageBlockBinding = NULL;
+
+PFNGLGETACTIVESUBROUTINENAMEPROC __glewGetActiveSubroutineName = NULL;
+PFNGLGETACTIVESUBROUTINEUNIFORMNAMEPROC __glewGetActiveSubroutineUniformName = NULL;
+PFNGLGETACTIVESUBROUTINEUNIFORMIVPROC __glewGetActiveSubroutineUniformiv = NULL;
+PFNGLGETPROGRAMSTAGEIVPROC __glewGetProgramStageiv = NULL;
+PFNGLGETSUBROUTINEINDEXPROC __glewGetSubroutineIndex = NULL;
+PFNGLGETSUBROUTINEUNIFORMLOCATIONPROC __glewGetSubroutineUniformLocation = NULL;
+PFNGLGETUNIFORMSUBROUTINEUIVPROC __glewGetUniformSubroutineuiv = NULL;
+PFNGLUNIFORMSUBROUTINESUIVPROC __glewUniformSubroutinesuiv = NULL;
+
+PFNGLCOMPILESHADERINCLUDEARBPROC __glewCompileShaderIncludeARB = NULL;
+PFNGLDELETENAMEDSTRINGARBPROC __glewDeleteNamedStringARB = NULL;
+PFNGLGETNAMEDSTRINGARBPROC __glewGetNamedStringARB = NULL;
+PFNGLGETNAMEDSTRINGIVARBPROC __glewGetNamedStringivARB = NULL;
+PFNGLISNAMEDSTRINGARBPROC __glewIsNamedStringARB = NULL;
+PFNGLNAMEDSTRINGARBPROC __glewNamedStringARB = NULL;
+
+PFNGLCLIENTWAITSYNCPROC __glewClientWaitSync = NULL;
+PFNGLDELETESYNCPROC __glewDeleteSync = NULL;
+PFNGLFENCESYNCPROC __glewFenceSync = NULL;
+PFNGLGETINTEGER64VPROC __glewGetInteger64v = NULL;
+PFNGLGETSYNCIVPROC __glewGetSynciv = NULL;
+PFNGLISSYNCPROC __glewIsSync = NULL;
+PFNGLWAITSYNCPROC __glewWaitSync = NULL;
+
+PFNGLPATCHPARAMETERFVPROC __glewPatchParameterfv = NULL;
+PFNGLPATCHPARAMETERIPROC __glewPatchParameteri = NULL;
+
+PFNGLTEXBUFFERARBPROC __glewTexBufferARB = NULL;
+
+PFNGLTEXBUFFERRANGEPROC __glewTexBufferRange = NULL;
+PFNGLTEXTUREBUFFERRANGEEXTPROC __glewTextureBufferRangeEXT = NULL;
+
+PFNGLCOMPRESSEDTEXIMAGE1DARBPROC __glewCompressedTexImage1DARB = NULL;
+PFNGLCOMPRESSEDTEXIMAGE2DARBPROC __glewCompressedTexImage2DARB = NULL;
+PFNGLCOMPRESSEDTEXIMAGE3DARBPROC __glewCompressedTexImage3DARB = NULL;
+PFNGLCOMPRESSEDTEXSUBIMAGE1DARBPROC __glewCompressedTexSubImage1DARB = NULL;
+PFNGLCOMPRESSEDTEXSUBIMAGE2DARBPROC __glewCompressedTexSubImage2DARB = NULL;
+PFNGLCOMPRESSEDTEXSUBIMAGE3DARBPROC __glewCompressedTexSubImage3DARB = NULL;
+PFNGLGETCOMPRESSEDTEXIMAGEARBPROC __glewGetCompressedTexImageARB = NULL;
+
+PFNGLGETMULTISAMPLEFVPROC __glewGetMultisamplefv = NULL;
+PFNGLSAMPLEMASKIPROC __glewSampleMaski = NULL;
+PFNGLTEXIMAGE2DMULTISAMPLEPROC __glewTexImage2DMultisample = NULL;
+PFNGLTEXIMAGE3DMULTISAMPLEPROC __glewTexImage3DMultisample = NULL;
+
+PFNGLTEXSTORAGE1DPROC __glewTexStorage1D = NULL;
+PFNGLTEXSTORAGE2DPROC __glewTexStorage2D = NULL;
+PFNGLTEXSTORAGE3DPROC __glewTexStorage3D = NULL;
+PFNGLTEXTURESTORAGE1DEXTPROC __glewTextureStorage1DEXT = NULL;
+PFNGLTEXTURESTORAGE2DEXTPROC __glewTextureStorage2DEXT = NULL;
+PFNGLTEXTURESTORAGE3DEXTPROC __glewTextureStorage3DEXT = NULL;
+
+PFNGLTEXSTORAGE2DMULTISAMPLEPROC __glewTexStorage2DMultisample = NULL;
+PFNGLTEXSTORAGE3DMULTISAMPLEPROC __glewTexStorage3DMultisample = NULL;
+PFNGLTEXTURESTORAGE2DMULTISAMPLEEXTPROC __glewTextureStorage2DMultisampleEXT = NULL;
+PFNGLTEXTURESTORAGE3DMULTISAMPLEEXTPROC __glewTextureStorage3DMultisampleEXT = NULL;
+
+PFNGLTEXTUREVIEWPROC __glewTextureView = NULL;
+
+PFNGLGETQUERYOBJECTI64VPROC __glewGetQueryObjecti64v = NULL;
+PFNGLGETQUERYOBJECTUI64VPROC __glewGetQueryObjectui64v = NULL;
+PFNGLQUERYCOUNTERPROC __glewQueryCounter = NULL;
+
+PFNGLBINDTRANSFORMFEEDBACKPROC __glewBindTransformFeedback = NULL;
+PFNGLDELETETRANSFORMFEEDBACKSPROC __glewDeleteTransformFeedbacks = NULL;
+PFNGLDRAWTRANSFORMFEEDBACKPROC __glewDrawTransformFeedback = NULL;
+PFNGLGENTRANSFORMFEEDBACKSPROC __glewGenTransformFeedbacks = NULL;
+PFNGLISTRANSFORMFEEDBACKPROC __glewIsTransformFeedback = NULL;
+PFNGLPAUSETRANSFORMFEEDBACKPROC __glewPauseTransformFeedback = NULL;
+PFNGLRESUMETRANSFORMFEEDBACKPROC __glewResumeTransformFeedback = NULL;
+
+PFNGLBEGINQUERYINDEXEDPROC __glewBeginQueryIndexed = NULL;
+PFNGLDRAWTRANSFORMFEEDBACKSTREAMPROC __glewDrawTransformFeedbackStream = NULL;
+PFNGLENDQUERYINDEXEDPROC __glewEndQueryIndexed = NULL;
+PFNGLGETQUERYINDEXEDIVPROC __glewGetQueryIndexediv = NULL;
+
+PFNGLDRAWTRANSFORMFEEDBACKINSTANCEDPROC __glewDrawTransformFeedbackInstanced = NULL;
+PFNGLDRAWTRANSFORMFEEDBACKSTREAMINSTANCEDPROC __glewDrawTransformFeedbackStreamInstanced = NULL;
+
+PFNGLLOADTRANSPOSEMATRIXDARBPROC __glewLoadTransposeMatrixdARB = NULL;
+PFNGLLOADTRANSPOSEMATRIXFARBPROC __glewLoadTransposeMatrixfARB = NULL;
+PFNGLMULTTRANSPOSEMATRIXDARBPROC __glewMultTransposeMatrixdARB = NULL;
+PFNGLMULTTRANSPOSEMATRIXFARBPROC __glewMultTransposeMatrixfARB = NULL;
+
+PFNGLBINDBUFFERBASEPROC __glewBindBufferBase = NULL;
+PFNGLBINDBUFFERRANGEPROC __glewBindBufferRange = NULL;
+PFNGLGETACTIVEUNIFORMBLOCKNAMEPROC __glewGetActiveUniformBlockName = NULL;
+PFNGLGETACTIVEUNIFORMBLOCKIVPROC __glewGetActiveUniformBlockiv = NULL;
+PFNGLGETACTIVEUNIFORMNAMEPROC __glewGetActiveUniformName = NULL;
+PFNGLGETACTIVEUNIFORMSIVPROC __glewGetActiveUniformsiv = NULL;
+PFNGLGETINTEGERI_VPROC __glewGetIntegeri_v = NULL;
+PFNGLGETUNIFORMBLOCKINDEXPROC __glewGetUniformBlockIndex = NULL;
+PFNGLGETUNIFORMINDICESPROC __glewGetUniformIndices = NULL;
+PFNGLUNIFORMBLOCKBINDINGPROC __glewUniformBlockBinding = NULL;
+
+PFNGLBINDVERTEXARRAYPROC __glewBindVertexArray = NULL;
+PFNGLDELETEVERTEXARRAYSPROC __glewDeleteVertexArrays = NULL;
+PFNGLGENVERTEXARRAYSPROC __glewGenVertexArrays = NULL;
+PFNGLISVERTEXARRAYPROC __glewIsVertexArray = NULL;
+
+PFNGLGETVERTEXATTRIBLDVPROC __glewGetVertexAttribLdv = NULL;
+PFNGLVERTEXATTRIBL1DPROC __glewVertexAttribL1d = NULL;
+PFNGLVERTEXATTRIBL1DVPROC __glewVertexAttribL1dv = NULL;
+PFNGLVERTEXATTRIBL2DPROC __glewVertexAttribL2d = NULL;
+PFNGLVERTEXATTRIBL2DVPROC __glewVertexAttribL2dv = NULL;
+PFNGLVERTEXATTRIBL3DPROC __glewVertexAttribL3d = NULL;
+PFNGLVERTEXATTRIBL3DVPROC __glewVertexAttribL3dv = NULL;
+PFNGLVERTEXATTRIBL4DPROC __glewVertexAttribL4d = NULL;
+PFNGLVERTEXATTRIBL4DVPROC __glewVertexAttribL4dv = NULL;
+PFNGLVERTEXATTRIBLPOINTERPROC __glewVertexAttribLPointer = NULL;
+
+PFNGLBINDVERTEXBUFFERPROC __glewBindVertexBuffer = NULL;
+PFNGLVERTEXATTRIBBINDINGPROC __glewVertexAttribBinding = NULL;
+PFNGLVERTEXATTRIBFORMATPROC __glewVertexAttribFormat = NULL;
+PFNGLVERTEXATTRIBIFORMATPROC __glewVertexAttribIFormat = NULL;
+PFNGLVERTEXATTRIBLFORMATPROC __glewVertexAttribLFormat = NULL;
+PFNGLVERTEXBINDINGDIVISORPROC __glewVertexBindingDivisor = NULL;
+
+PFNGLVERTEXBLENDARBPROC __glewVertexBlendARB = NULL;
+PFNGLWEIGHTPOINTERARBPROC __glewWeightPointerARB = NULL;
+PFNGLWEIGHTBVARBPROC __glewWeightbvARB = NULL;
+PFNGLWEIGHTDVARBPROC __glewWeightdvARB = NULL;
+PFNGLWEIGHTFVARBPROC __glewWeightfvARB = NULL;
+PFNGLWEIGHTIVARBPROC __glewWeightivARB = NULL;
+PFNGLWEIGHTSVARBPROC __glewWeightsvARB = NULL;
+PFNGLWEIGHTUBVARBPROC __glewWeightubvARB = NULL;
+PFNGLWEIGHTUIVARBPROC __glewWeightuivARB = NULL;
+PFNGLWEIGHTUSVARBPROC __glewWeightusvARB = NULL;
+
+PFNGLBINDBUFFERARBPROC __glewBindBufferARB = NULL;
+PFNGLBUFFERDATAARBPROC __glewBufferDataARB = NULL;
+PFNGLBUFFERSUBDATAARBPROC __glewBufferSubDataARB = NULL;
+PFNGLDELETEBUFFERSARBPROC __glewDeleteBuffersARB = NULL;
+PFNGLGENBUFFERSARBPROC __glewGenBuffersARB = NULL;
+PFNGLGETBUFFERPARAMETERIVARBPROC __glewGetBufferParameterivARB = NULL;
+PFNGLGETBUFFERPOINTERVARBPROC __glewGetBufferPointervARB = NULL;
+PFNGLGETBUFFERSUBDATAARBPROC __glewGetBufferSubDataARB = NULL;
+PFNGLISBUFFERARBPROC __glewIsBufferARB = NULL;
+PFNGLMAPBUFFERARBPROC __glewMapBufferARB = NULL;
+PFNGLUNMAPBUFFERARBPROC __glewUnmapBufferARB = NULL;
+
+PFNGLBINDPROGRAMARBPROC __glewBindProgramARB = NULL;
+PFNGLDELETEPROGRAMSARBPROC __glewDeleteProgramsARB = NULL;
+PFNGLDISABLEVERTEXATTRIBARRAYARBPROC __glewDisableVertexAttribArrayARB = NULL;
+PFNGLENABLEVERTEXATTRIBARRAYARBPROC __glewEnableVertexAttribArrayARB = NULL;
+PFNGLGENPROGRAMSARBPROC __glewGenProgramsARB = NULL;
+PFNGLGETPROGRAMENVPARAMETERDVARBPROC __glewGetProgramEnvParameterdvARB = NULL;
+PFNGLGETPROGRAMENVPARAMETERFVARBPROC __glewGetProgramEnvParameterfvARB = NULL;
+PFNGLGETPROGRAMLOCALPARAMETERDVARBPROC __glewGetProgramLocalParameterdvARB = NULL;
+PFNGLGETPROGRAMLOCALPARAMETERFVARBPROC __glewGetProgramLocalParameterfvARB = NULL;
+PFNGLGETPROGRAMSTRINGARBPROC __glewGetProgramStringARB = NULL;
+PFNGLGETPROGRAMIVARBPROC __glewGetProgramivARB = NULL;
+PFNGLGETVERTEXATTRIBPOINTERVARBPROC __glewGetVertexAttribPointervARB = NULL;
+PFNGLGETVERTEXATTRIBDVARBPROC __glewGetVertexAttribdvARB = NULL;
+PFNGLGETVERTEXATTRIBFVARBPROC __glewGetVertexAttribfvARB = NULL;
+PFNGLGETVERTEXATTRIBIVARBPROC __glewGetVertexAttribivARB = NULL;
+PFNGLISPROGRAMARBPROC __glewIsProgramARB = NULL;
+PFNGLPROGRAMENVPARAMETER4DARBPROC __glewProgramEnvParameter4dARB = NULL;
+PFNGLPROGRAMENVPARAMETER4DVARBPROC __glewProgramEnvParameter4dvARB = NULL;
+PFNGLPROGRAMENVPARAMETER4FARBPROC __glewProgramEnvParameter4fARB = NULL;
+PFNGLPROGRAMENVPARAMETER4FVARBPROC __glewProgramEnvParameter4fvARB = NULL;
+PFNGLPROGRAMLOCALPARAMETER4DARBPROC __glewProgramLocalParameter4dARB = NULL;
+PFNGLPROGRAMLOCALPARAMETER4DVARBPROC __glewProgramLocalParameter4dvARB = NULL;
+PFNGLPROGRAMLOCALPARAMETER4FARBPROC __glewProgramLocalParameter4fARB = NULL;
+PFNGLPROGRAMLOCALPARAMETER4FVARBPROC __glewProgramLocalParameter4fvARB = NULL;
+PFNGLPROGRAMSTRINGARBPROC __glewProgramStringARB = NULL;
+PFNGLVERTEXATTRIB1DARBPROC __glewVertexAttrib1dARB = NULL;
+PFNGLVERTEXATTRIB1DVARBPROC __glewVertexAttrib1dvARB = NULL;
+PFNGLVERTEXATTRIB1FARBPROC __glewVertexAttrib1fARB = NULL;
+PFNGLVERTEXATTRIB1FVARBPROC __glewVertexAttrib1fvARB = NULL;
+PFNGLVERTEXATTRIB1SARBPROC __glewVertexAttrib1sARB = NULL;
+PFNGLVERTEXATTRIB1SVARBPROC __glewVertexAttrib1svARB = NULL;
+PFNGLVERTEXATTRIB2DARBPROC __glewVertexAttrib2dARB = NULL;
+PFNGLVERTEXATTRIB2DVARBPROC __glewVertexAttrib2dvARB = NULL;
+PFNGLVERTEXATTRIB2FARBPROC __glewVertexAttrib2fARB = NULL;
+PFNGLVERTEXATTRIB2FVARBPROC __glewVertexAttrib2fvARB = NULL;
+PFNGLVERTEXATTRIB2SARBPROC __glewVertexAttrib2sARB = NULL;
+PFNGLVERTEXATTRIB2SVARBPROC __glewVertexAttrib2svARB = NULL;
+PFNGLVERTEXATTRIB3DARBPROC __glewVertexAttrib3dARB = NULL;
+PFNGLVERTEXATTRIB3DVARBPROC __glewVertexAttrib3dvARB = NULL;
+PFNGLVERTEXATTRIB3FARBPROC __glewVertexAttrib3fARB = NULL;
+PFNGLVERTEXATTRIB3FVARBPROC __glewVertexAttrib3fvARB = NULL;
+PFNGLVERTEXATTRIB3SARBPROC __glewVertexAttrib3sARB = NULL;
+PFNGLVERTEXATTRIB3SVARBPROC __glewVertexAttrib3svARB = NULL;
+PFNGLVERTEXATTRIB4NBVARBPROC __glewVertexAttrib4NbvARB = NULL;
+PFNGLVERTEXATTRIB4NIVARBPROC __glewVertexAttrib4NivARB = NULL;
+PFNGLVERTEXATTRIB4NSVARBPROC __glewVertexAttrib4NsvARB = NULL;
+PFNGLVERTEXATTRIB4NUBARBPROC __glewVertexAttrib4NubARB = NULL;
+PFNGLVERTEXATTRIB4NUBVARBPROC __glewVertexAttrib4NubvARB = NULL;
+PFNGLVERTEXATTRIB4NUIVARBPROC __glewVertexAttrib4NuivARB = NULL;
+PFNGLVERTEXATTRIB4NUSVARBPROC __glewVertexAttrib4NusvARB = NULL;
+PFNGLVERTEXATTRIB4BVARBPROC __glewVertexAttrib4bvARB = NULL;
+PFNGLVERTEXATTRIB4DARBPROC __glewVertexAttrib4dARB = NULL;
+PFNGLVERTEXATTRIB4DVARBPROC __glewVertexAttrib4dvARB = NULL;
+PFNGLVERTEXATTRIB4FARBPROC __glewVertexAttrib4fARB = NULL;
+PFNGLVERTEXATTRIB4FVARBPROC __glewVertexAttrib4fvARB = NULL;
+PFNGLVERTEXATTRIB4IVARBPROC __glewVertexAttrib4ivARB = NULL;
+PFNGLVERTEXATTRIB4SARBPROC __glewVertexAttrib4sARB = NULL;
+PFNGLVERTEXATTRIB4SVARBPROC __glewVertexAttrib4svARB = NULL;
+PFNGLVERTEXATTRIB4UBVARBPROC __glewVertexAttrib4ubvARB = NULL;
+PFNGLVERTEXATTRIB4UIVARBPROC __glewVertexAttrib4uivARB = NULL;
+PFNGLVERTEXATTRIB4USVARBPROC __glewVertexAttrib4usvARB = NULL;
+PFNGLVERTEXATTRIBPOINTERARBPROC __glewVertexAttribPointerARB = NULL;
+
+PFNGLBINDATTRIBLOCATIONARBPROC __glewBindAttribLocationARB = NULL;
+PFNGLGETACTIVEATTRIBARBPROC __glewGetActiveAttribARB = NULL;
+PFNGLGETATTRIBLOCATIONARBPROC __glewGetAttribLocationARB = NULL;
+
+PFNGLCOLORP3UIPROC __glewColorP3ui = NULL;
+PFNGLCOLORP3UIVPROC __glewColorP3uiv = NULL;
+PFNGLCOLORP4UIPROC __glewColorP4ui = NULL;
+PFNGLCOLORP4UIVPROC __glewColorP4uiv = NULL;
+PFNGLMULTITEXCOORDP1UIPROC __glewMultiTexCoordP1ui = NULL;
+PFNGLMULTITEXCOORDP1UIVPROC __glewMultiTexCoordP1uiv = NULL;
+PFNGLMULTITEXCOORDP2UIPROC __glewMultiTexCoordP2ui = NULL;
+PFNGLMULTITEXCOORDP2UIVPROC __glewMultiTexCoordP2uiv = NULL;
+PFNGLMULTITEXCOORDP3UIPROC __glewMultiTexCoordP3ui = NULL;
+PFNGLMULTITEXCOORDP3UIVPROC __glewMultiTexCoordP3uiv = NULL;
+PFNGLMULTITEXCOORDP4UIPROC __glewMultiTexCoordP4ui = NULL;
+PFNGLMULTITEXCOORDP4UIVPROC __glewMultiTexCoordP4uiv = NULL;
+PFNGLNORMALP3UIPROC __glewNormalP3ui = NULL;
+PFNGLNORMALP3UIVPROC __glewNormalP3uiv = NULL;
+PFNGLSECONDARYCOLORP3UIPROC __glewSecondaryColorP3ui = NULL;
+PFNGLSECONDARYCOLORP3UIVPROC __glewSecondaryColorP3uiv = NULL;
+PFNGLTEXCOORDP1UIPROC __glewTexCoordP1ui = NULL;
+PFNGLTEXCOORDP1UIVPROC __glewTexCoordP1uiv = NULL;
+PFNGLTEXCOORDP2UIPROC __glewTexCoordP2ui = NULL;
+PFNGLTEXCOORDP2UIVPROC __glewTexCoordP2uiv = NULL;
+PFNGLTEXCOORDP3UIPROC __glewTexCoordP3ui = NULL;
+PFNGLTEXCOORDP3UIVPROC __glewTexCoordP3uiv = NULL;
+PFNGLTEXCOORDP4UIPROC __glewTexCoordP4ui = NULL;
+PFNGLTEXCOORDP4UIVPROC __glewTexCoordP4uiv = NULL;
+PFNGLVERTEXATTRIBP1UIPROC __glewVertexAttribP1ui = NULL;
+PFNGLVERTEXATTRIBP1UIVPROC __glewVertexAttribP1uiv = NULL;
+PFNGLVERTEXATTRIBP2UIPROC __glewVertexAttribP2ui = NULL;
+PFNGLVERTEXATTRIBP2UIVPROC __glewVertexAttribP2uiv = NULL;
+PFNGLVERTEXATTRIBP3UIPROC __glewVertexAttribP3ui = NULL;
+PFNGLVERTEXATTRIBP3UIVPROC __glewVertexAttribP3uiv = NULL;
+PFNGLVERTEXATTRIBP4UIPROC __glewVertexAttribP4ui = NULL;
+PFNGLVERTEXATTRIBP4UIVPROC __glewVertexAttribP4uiv = NULL;
+PFNGLVERTEXP2UIPROC __glewVertexP2ui = NULL;
+PFNGLVERTEXP2UIVPROC __glewVertexP2uiv = NULL;
+PFNGLVERTEXP3UIPROC __glewVertexP3ui = NULL;
+PFNGLVERTEXP3UIVPROC __glewVertexP3uiv = NULL;
+PFNGLVERTEXP4UIPROC __glewVertexP4ui = NULL;
+PFNGLVERTEXP4UIVPROC __glewVertexP4uiv = NULL;
+
+PFNGLDEPTHRANGEARRAYVPROC __glewDepthRangeArrayv = NULL;
+PFNGLDEPTHRANGEINDEXEDPROC __glewDepthRangeIndexed = NULL;
+PFNGLGETDOUBLEI_VPROC __glewGetDoublei_v = NULL;
+PFNGLGETFLOATI_VPROC __glewGetFloati_v = NULL;
+PFNGLSCISSORARRAYVPROC __glewScissorArrayv = NULL;
+PFNGLSCISSORINDEXEDPROC __glewScissorIndexed = NULL;
+PFNGLSCISSORINDEXEDVPROC __glewScissorIndexedv = NULL;
+PFNGLVIEWPORTARRAYVPROC __glewViewportArrayv = NULL;
+PFNGLVIEWPORTINDEXEDFPROC __glewViewportIndexedf = NULL;
+PFNGLVIEWPORTINDEXEDFVPROC __glewViewportIndexedfv = NULL;
+
+PFNGLWINDOWPOS2DARBPROC __glewWindowPos2dARB = NULL;
+PFNGLWINDOWPOS2DVARBPROC __glewWindowPos2dvARB = NULL;
+PFNGLWINDOWPOS2FARBPROC __glewWindowPos2fARB = NULL;
+PFNGLWINDOWPOS2FVARBPROC __glewWindowPos2fvARB = NULL;
+PFNGLWINDOWPOS2IARBPROC __glewWindowPos2iARB = NULL;
+PFNGLWINDOWPOS2IVARBPROC __glewWindowPos2ivARB = NULL;
+PFNGLWINDOWPOS2SARBPROC __glewWindowPos2sARB = NULL;
+PFNGLWINDOWPOS2SVARBPROC __glewWindowPos2svARB = NULL;
+PFNGLWINDOWPOS3DARBPROC __glewWindowPos3dARB = NULL;
+PFNGLWINDOWPOS3DVARBPROC __glewWindowPos3dvARB = NULL;
+PFNGLWINDOWPOS3FARBPROC __glewWindowPos3fARB = NULL;
+PFNGLWINDOWPOS3FVARBPROC __glewWindowPos3fvARB = NULL;
+PFNGLWINDOWPOS3IARBPROC __glewWindowPos3iARB = NULL;
+PFNGLWINDOWPOS3IVARBPROC __glewWindowPos3ivARB = NULL;
+PFNGLWINDOWPOS3SARBPROC __glewWindowPos3sARB = NULL;
+PFNGLWINDOWPOS3SVARBPROC __glewWindowPos3svARB = NULL;
+
+PFNGLDRAWBUFFERSATIPROC __glewDrawBuffersATI = NULL;
+
+PFNGLDRAWELEMENTARRAYATIPROC __glewDrawElementArrayATI = NULL;
+PFNGLDRAWRANGEELEMENTARRAYATIPROC __glewDrawRangeElementArrayATI = NULL;
+PFNGLELEMENTPOINTERATIPROC __glewElementPointerATI = NULL;
+
+PFNGLGETTEXBUMPPARAMETERFVATIPROC __glewGetTexBumpParameterfvATI = NULL;
+PFNGLGETTEXBUMPPARAMETERIVATIPROC __glewGetTexBumpParameterivATI = NULL;
+PFNGLTEXBUMPPARAMETERFVATIPROC __glewTexBumpParameterfvATI = NULL;
+PFNGLTEXBUMPPARAMETERIVATIPROC __glewTexBumpParameterivATI = NULL;
+
+PFNGLALPHAFRAGMENTOP1ATIPROC __glewAlphaFragmentOp1ATI = NULL;
+PFNGLALPHAFRAGMENTOP2ATIPROC __glewAlphaFragmentOp2ATI = NULL;
+PFNGLALPHAFRAGMENTOP3ATIPROC __glewAlphaFragmentOp3ATI = NULL;
+PFNGLBEGINFRAGMENTSHADERATIPROC __glewBeginFragmentShaderATI = NULL;
+PFNGLBINDFRAGMENTSHADERATIPROC __glewBindFragmentShaderATI = NULL;
+PFNGLCOLORFRAGMENTOP1ATIPROC __glewColorFragmentOp1ATI = NULL;
+PFNGLCOLORFRAGMENTOP2ATIPROC __glewColorFragmentOp2ATI = NULL;
+PFNGLCOLORFRAGMENTOP3ATIPROC __glewColorFragmentOp3ATI = NULL;
+PFNGLDELETEFRAGMENTSHADERATIPROC __glewDeleteFragmentShaderATI = NULL;
+PFNGLENDFRAGMENTSHADERATIPROC __glewEndFragmentShaderATI = NULL;
+PFNGLGENFRAGMENTSHADERSATIPROC __glewGenFragmentShadersATI = NULL;
+PFNGLPASSTEXCOORDATIPROC __glewPassTexCoordATI = NULL;
+PFNGLSAMPLEMAPATIPROC __glewSampleMapATI = NULL;
+PFNGLSETFRAGMENTSHADERCONSTANTATIPROC __glewSetFragmentShaderConstantATI = NULL;
+
+PFNGLMAPOBJECTBUFFERATIPROC __glewMapObjectBufferATI = NULL;
+PFNGLUNMAPOBJECTBUFFERATIPROC __glewUnmapObjectBufferATI = NULL;
+
+PFNGLPNTRIANGLESFATIPROC __glewPNTrianglesfATI = NULL;
+PFNGLPNTRIANGLESIATIPROC __glewPNTrianglesiATI = NULL;
+
+PFNGLSTENCILFUNCSEPARATEATIPROC __glewStencilFuncSeparateATI = NULL;
+PFNGLSTENCILOPSEPARATEATIPROC __glewStencilOpSeparateATI = NULL;
+
+PFNGLARRAYOBJECTATIPROC __glewArrayObjectATI = NULL;
+PFNGLFREEOBJECTBUFFERATIPROC __glewFreeObjectBufferATI = NULL;
+PFNGLGETARRAYOBJECTFVATIPROC __glewGetArrayObjectfvATI = NULL;
+PFNGLGETARRAYOBJECTIVATIPROC __glewGetArrayObjectivATI = NULL;
+PFNGLGETOBJECTBUFFERFVATIPROC __glewGetObjectBufferfvATI = NULL;
+PFNGLGETOBJECTBUFFERIVATIPROC __glewGetObjectBufferivATI = NULL;
+PFNGLGETVARIANTARRAYOBJECTFVATIPROC __glewGetVariantArrayObjectfvATI = NULL;
+PFNGLGETVARIANTARRAYOBJECTIVATIPROC __glewGetVariantArrayObjectivATI = NULL;
+PFNGLISOBJECTBUFFERATIPROC __glewIsObjectBufferATI = NULL;
+PFNGLNEWOBJECTBUFFERATIPROC __glewNewObjectBufferATI = NULL;
+PFNGLUPDATEOBJECTBUFFERATIPROC __glewUpdateObjectBufferATI = NULL;
+PFNGLVARIANTARRAYOBJECTATIPROC __glewVariantArrayObjectATI = NULL;
+
+PFNGLGETVERTEXATTRIBARRAYOBJECTFVATIPROC __glewGetVertexAttribArrayObjectfvATI = NULL;
+PFNGLGETVERTEXATTRIBARRAYOBJECTIVATIPROC __glewGetVertexAttribArrayObjectivATI = NULL;
+PFNGLVERTEXATTRIBARRAYOBJECTATIPROC __glewVertexAttribArrayObjectATI = NULL;
+
+PFNGLCLIENTACTIVEVERTEXSTREAMATIPROC __glewClientActiveVertexStreamATI = NULL;
+PFNGLNORMALSTREAM3BATIPROC __glewNormalStream3bATI = NULL;
+PFNGLNORMALSTREAM3BVATIPROC __glewNormalStream3bvATI = NULL;
+PFNGLNORMALSTREAM3DATIPROC __glewNormalStream3dATI = NULL;
+PFNGLNORMALSTREAM3DVATIPROC __glewNormalStream3dvATI = NULL;
+PFNGLNORMALSTREAM3FATIPROC __glewNormalStream3fATI = NULL;
+PFNGLNORMALSTREAM3FVATIPROC __glewNormalStream3fvATI = NULL;
+PFNGLNORMALSTREAM3IATIPROC __glewNormalStream3iATI = NULL;
+PFNGLNORMALSTREAM3IVATIPROC __glewNormalStream3ivATI = NULL;
+PFNGLNORMALSTREAM3SATIPROC __glewNormalStream3sATI = NULL;
+PFNGLNORMALSTREAM3SVATIPROC __glewNormalStream3svATI = NULL;
+PFNGLVERTEXBLENDENVFATIPROC __glewVertexBlendEnvfATI = NULL;
+PFNGLVERTEXBLENDENVIATIPROC __glewVertexBlendEnviATI = NULL;
+PFNGLVERTEXSTREAM2DATIPROC __glewVertexStream2dATI = NULL;
+PFNGLVERTEXSTREAM2DVATIPROC __glewVertexStream2dvATI = NULL;
+PFNGLVERTEXSTREAM2FATIPROC __glewVertexStream2fATI = NULL;
+PFNGLVERTEXSTREAM2FVATIPROC __glewVertexStream2fvATI = NULL;
+PFNGLVERTEXSTREAM2IATIPROC __glewVertexStream2iATI = NULL;
+PFNGLVERTEXSTREAM2IVATIPROC __glewVertexStream2ivATI = NULL;
+PFNGLVERTEXSTREAM2SATIPROC __glewVertexStream2sATI = NULL;
+PFNGLVERTEXSTREAM2SVATIPROC __glewVertexStream2svATI = NULL;
+PFNGLVERTEXSTREAM3DATIPROC __glewVertexStream3dATI = NULL;
+PFNGLVERTEXSTREAM3DVATIPROC __glewVertexStream3dvATI = NULL;
+PFNGLVERTEXSTREAM3FATIPROC __glewVertexStream3fATI = NULL;
+PFNGLVERTEXSTREAM3FVATIPROC __glewVertexStream3fvATI = NULL;
+PFNGLVERTEXSTREAM3IATIPROC __glewVertexStream3iATI = NULL;
+PFNGLVERTEXSTREAM3IVATIPROC __glewVertexStream3ivATI = NULL;
+PFNGLVERTEXSTREAM3SATIPROC __glewVertexStream3sATI = NULL;
+PFNGLVERTEXSTREAM3SVATIPROC __glewVertexStream3svATI = NULL;
+PFNGLVERTEXSTREAM4DATIPROC __glewVertexStream4dATI = NULL;
+PFNGLVERTEXSTREAM4DVATIPROC __glewVertexStream4dvATI = NULL;
+PFNGLVERTEXSTREAM4FATIPROC __glewVertexStream4fATI = NULL;
+PFNGLVERTEXSTREAM4FVATIPROC __glewVertexStream4fvATI = NULL;
+PFNGLVERTEXSTREAM4IATIPROC __glewVertexStream4iATI = NULL;
+PFNGLVERTEXSTREAM4IVATIPROC __glewVertexStream4ivATI = NULL;
+PFNGLVERTEXSTREAM4SATIPROC __glewVertexStream4sATI = NULL;
+PFNGLVERTEXSTREAM4SVATIPROC __glewVertexStream4svATI = NULL;
+
+PFNGLGETUNIFORMBUFFERSIZEEXTPROC __glewGetUniformBufferSizeEXT = NULL;
+PFNGLGETUNIFORMOFFSETEXTPROC __glewGetUniformOffsetEXT = NULL;
+PFNGLUNIFORMBUFFEREXTPROC __glewUniformBufferEXT = NULL;
+
+PFNGLBLENDCOLOREXTPROC __glewBlendColorEXT = NULL;
+
+PFNGLBLENDEQUATIONSEPARATEEXTPROC __glewBlendEquationSeparateEXT = NULL;
+
+PFNGLBLENDFUNCSEPARATEEXTPROC __glewBlendFuncSeparateEXT = NULL;
+
+PFNGLBLENDEQUATIONEXTPROC __glewBlendEquationEXT = NULL;
+
+PFNGLCOLORSUBTABLEEXTPROC __glewColorSubTableEXT = NULL;
+PFNGLCOPYCOLORSUBTABLEEXTPROC __glewCopyColorSubTableEXT = NULL;
+
+PFNGLLOCKARRAYSEXTPROC __glewLockArraysEXT = NULL;
+PFNGLUNLOCKARRAYSEXTPROC __glewUnlockArraysEXT = NULL;
+
+PFNGLCONVOLUTIONFILTER1DEXTPROC __glewConvolutionFilter1DEXT = NULL;
+PFNGLCONVOLUTIONFILTER2DEXTPROC __glewConvolutionFilter2DEXT = NULL;
+PFNGLCONVOLUTIONPARAMETERFEXTPROC __glewConvolutionParameterfEXT = NULL;
+PFNGLCONVOLUTIONPARAMETERFVEXTPROC __glewConvolutionParameterfvEXT = NULL;
+PFNGLCONVOLUTIONPARAMETERIEXTPROC __glewConvolutionParameteriEXT = NULL;
+PFNGLCONVOLUTIONPARAMETERIVEXTPROC __glewConvolutionParameterivEXT = NULL;
+PFNGLCOPYCONVOLUTIONFILTER1DEXTPROC __glewCopyConvolutionFilter1DEXT = NULL;
+PFNGLCOPYCONVOLUTIONFILTER2DEXTPROC __glewCopyConvolutionFilter2DEXT = NULL;
+PFNGLGETCONVOLUTIONFILTEREXTPROC __glewGetConvolutionFilterEXT = NULL;
+PFNGLGETCONVOLUTIONPARAMETERFVEXTPROC __glewGetConvolutionParameterfvEXT = NULL;
+PFNGLGETCONVOLUTIONPARAMETERIVEXTPROC __glewGetConvolutionParameterivEXT = NULL;
+PFNGLGETSEPARABLEFILTEREXTPROC __glewGetSeparableFilterEXT = NULL;
+PFNGLSEPARABLEFILTER2DEXTPROC __glewSeparableFilter2DEXT = NULL;
+
+PFNGLBINORMALPOINTEREXTPROC __glewBinormalPointerEXT = NULL;
+PFNGLTANGENTPOINTEREXTPROC __glewTangentPointerEXT = NULL;
+
+PFNGLCOPYTEXIMAGE1DEXTPROC __glewCopyTexImage1DEXT = NULL;
+PFNGLCOPYTEXIMAGE2DEXTPROC __glewCopyTexImage2DEXT = NULL;
+PFNGLCOPYTEXSUBIMAGE1DEXTPROC __glewCopyTexSubImage1DEXT = NULL;
+PFNGLCOPYTEXSUBIMAGE2DEXTPROC __glewCopyTexSubImage2DEXT = NULL;
+PFNGLCOPYTEXSUBIMAGE3DEXTPROC __glewCopyTexSubImage3DEXT = NULL;
+
+PFNGLCULLPARAMETERDVEXTPROC __glewCullParameterdvEXT = NULL;
+PFNGLCULLPARAMETERFVEXTPROC __glewCullParameterfvEXT = NULL;
+
+PFNGLDEPTHBOUNDSEXTPROC __glewDepthBoundsEXT = NULL;
+
+PFNGLBINDMULTITEXTUREEXTPROC __glewBindMultiTextureEXT = NULL;
+PFNGLCHECKNAMEDFRAMEBUFFERSTATUSEXTPROC __glewCheckNamedFramebufferStatusEXT = NULL;
+PFNGLCLIENTATTRIBDEFAULTEXTPROC __glewClientAttribDefaultEXT = NULL;
+PFNGLCOMPRESSEDMULTITEXIMAGE1DEXTPROC __glewCompressedMultiTexImage1DEXT = NULL;
+PFNGLCOMPRESSEDMULTITEXIMAGE2DEXTPROC __glewCompressedMultiTexImage2DEXT = NULL;
+PFNGLCOMPRESSEDMULTITEXIMAGE3DEXTPROC __glewCompressedMultiTexImage3DEXT = NULL;
+PFNGLCOMPRESSEDMULTITEXSUBIMAGE1DEXTPROC __glewCompressedMultiTexSubImage1DEXT = NULL;
+PFNGLCOMPRESSEDMULTITEXSUBIMAGE2DEXTPROC __glewCompressedMultiTexSubImage2DEXT = NULL;
+PFNGLCOMPRESSEDMULTITEXSUBIMAGE3DEXTPROC __glewCompressedMultiTexSubImage3DEXT = NULL;
+PFNGLCOMPRESSEDTEXTUREIMAGE1DEXTPROC __glewCompressedTextureImage1DEXT = NULL;
+PFNGLCOMPRESSEDTEXTUREIMAGE2DEXTPROC __glewCompressedTextureImage2DEXT = NULL;
+PFNGLCOMPRESSEDTEXTUREIMAGE3DEXTPROC __glewCompressedTextureImage3DEXT = NULL;
+PFNGLCOMPRESSEDTEXTURESUBIMAGE1DEXTPROC __glewCompressedTextureSubImage1DEXT = NULL;
+PFNGLCOMPRESSEDTEXTURESUBIMAGE2DEXTPROC __glewCompressedTextureSubImage2DEXT = NULL;
+PFNGLCOMPRESSEDTEXTURESUBIMAGE3DEXTPROC __glewCompressedTextureSubImage3DEXT = NULL;
+PFNGLCOPYMULTITEXIMAGE1DEXTPROC __glewCopyMultiTexImage1DEXT = NULL;
+PFNGLCOPYMULTITEXIMAGE2DEXTPROC __glewCopyMultiTexImage2DEXT = NULL;
+PFNGLCOPYMULTITEXSUBIMAGE1DEXTPROC __glewCopyMultiTexSubImage1DEXT = NULL;
+PFNGLCOPYMULTITEXSUBIMAGE2DEXTPROC __glewCopyMultiTexSubImage2DEXT = NULL;
+PFNGLCOPYMULTITEXSUBIMAGE3DEXTPROC __glewCopyMultiTexSubImage3DEXT = NULL;
+PFNGLCOPYTEXTUREIMAGE1DEXTPROC __glewCopyTextureImage1DEXT = NULL;
+PFNGLCOPYTEXTUREIMAGE2DEXTPROC __glewCopyTextureImage2DEXT = NULL;
+PFNGLCOPYTEXTURESUBIMAGE1DEXTPROC __glewCopyTextureSubImage1DEXT = NULL;
+PFNGLCOPYTEXTURESUBIMAGE2DEXTPROC __glewCopyTextureSubImage2DEXT = NULL;
+PFNGLCOPYTEXTURESUBIMAGE3DEXTPROC __glewCopyTextureSubImage3DEXT = NULL;
+PFNGLDISABLECLIENTSTATEINDEXEDEXTPROC __glewDisableClientStateIndexedEXT = NULL;
+PFNGLDISABLECLIENTSTATEIEXTPROC __glewDisableClientStateiEXT = NULL;
+PFNGLDISABLEVERTEXARRAYATTRIBEXTPROC __glewDisableVertexArrayAttribEXT = NULL;
+PFNGLDISABLEVERTEXARRAYEXTPROC __glewDisableVertexArrayEXT = NULL;
+PFNGLENABLECLIENTSTATEINDEXEDEXTPROC __glewEnableClientStateIndexedEXT = NULL;
+PFNGLENABLECLIENTSTATEIEXTPROC __glewEnableClientStateiEXT = NULL;
+PFNGLENABLEVERTEXARRAYATTRIBEXTPROC __glewEnableVertexArrayAttribEXT = NULL;
+PFNGLENABLEVERTEXARRAYEXTPROC __glewEnableVertexArrayEXT = NULL;
+PFNGLFLUSHMAPPEDNAMEDBUFFERRANGEEXTPROC __glewFlushMappedNamedBufferRangeEXT = NULL;
+PFNGLFRAMEBUFFERDRAWBUFFEREXTPROC __glewFramebufferDrawBufferEXT = NULL;
+PFNGLFRAMEBUFFERDRAWBUFFERSEXTPROC __glewFramebufferDrawBuffersEXT = NULL;
+PFNGLFRAMEBUFFERREADBUFFEREXTPROC __glewFramebufferReadBufferEXT = NULL;
+PFNGLGENERATEMULTITEXMIPMAPEXTPROC __glewGenerateMultiTexMipmapEXT = NULL;
+PFNGLGENERATETEXTUREMIPMAPEXTPROC __glewGenerateTextureMipmapEXT = NULL;
+PFNGLGETCOMPRESSEDMULTITEXIMAGEEXTPROC __glewGetCompressedMultiTexImageEXT = NULL;
+PFNGLGETCOMPRESSEDTEXTUREIMAGEEXTPROC __glewGetCompressedTextureImageEXT = NULL;
+PFNGLGETDOUBLEINDEXEDVEXTPROC __glewGetDoubleIndexedvEXT = NULL;
+PFNGLGETDOUBLEI_VEXTPROC __glewGetDoublei_vEXT = NULL;
+PFNGLGETFLOATINDEXEDVEXTPROC __glewGetFloatIndexedvEXT = NULL;
+PFNGLGETFLOATI_VEXTPROC __glewGetFloati_vEXT = NULL;
+PFNGLGETFRAMEBUFFERPARAMETERIVEXTPROC __glewGetFramebufferParameterivEXT = NULL;
+PFNGLGETMULTITEXENVFVEXTPROC __glewGetMultiTexEnvfvEXT = NULL;
+PFNGLGETMULTITEXENVIVEXTPROC __glewGetMultiTexEnvivEXT = NULL;
+PFNGLGETMULTITEXGENDVEXTPROC __glewGetMultiTexGendvEXT = NULL;
+PFNGLGETMULTITEXGENFVEXTPROC __glewGetMultiTexGenfvEXT = NULL;
+PFNGLGETMULTITEXGENIVEXTPROC __glewGetMultiTexGenivEXT = NULL;
+PFNGLGETMULTITEXIMAGEEXTPROC __glewGetMultiTexImageEXT = NULL;
+PFNGLGETMULTITEXLEVELPARAMETERFVEXTPROC __glewGetMultiTexLevelParameterfvEXT = NULL;
+PFNGLGETMULTITEXLEVELPARAMETERIVEXTPROC __glewGetMultiTexLevelParameterivEXT = NULL;
+PFNGLGETMULTITEXPARAMETERIIVEXTPROC __glewGetMultiTexParameterIivEXT = NULL;
+PFNGLGETMULTITEXPARAMETERIUIVEXTPROC __glewGetMultiTexParameterIuivEXT = NULL;
+PFNGLGETMULTITEXPARAMETERFVEXTPROC __glewGetMultiTexParameterfvEXT = NULL;
+PFNGLGETMULTITEXPARAMETERIVEXTPROC __glewGetMultiTexParameterivEXT = NULL;
+PFNGLGETNAMEDBUFFERPARAMETERIVEXTPROC __glewGetNamedBufferParameterivEXT = NULL;
+PFNGLGETNAMEDBUFFERPOINTERVEXTPROC __glewGetNamedBufferPointervEXT = NULL;
+PFNGLGETNAMEDBUFFERSUBDATAEXTPROC __glewGetNamedBufferSubDataEXT = NULL;
+PFNGLGETNAMEDFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC __glewGetNamedFramebufferAttachmentParameterivEXT = NULL;
+PFNGLGETNAMEDPROGRAMLOCALPARAMETERIIVEXTPROC __glewGetNamedProgramLocalParameterIivEXT = NULL;
+PFNGLGETNAMEDPROGRAMLOCALPARAMETERIUIVEXTPROC __glewGetNamedProgramLocalParameterIuivEXT = NULL;
+PFNGLGETNAMEDPROGRAMLOCALPARAMETERDVEXTPROC __glewGetNamedProgramLocalParameterdvEXT = NULL;
+PFNGLGETNAMEDPROGRAMLOCALPARAMETERFVEXTPROC __glewGetNamedProgramLocalParameterfvEXT = NULL;
+PFNGLGETNAMEDPROGRAMSTRINGEXTPROC __glewGetNamedProgramStringEXT = NULL;
+PFNGLGETNAMEDPROGRAMIVEXTPROC __glewGetNamedProgramivEXT = NULL;
+PFNGLGETNAMEDRENDERBUFFERPARAMETERIVEXTPROC __glewGetNamedRenderbufferParameterivEXT = NULL;
+PFNGLGETPOINTERINDEXEDVEXTPROC __glewGetPointerIndexedvEXT = NULL;
+PFNGLGETPOINTERI_VEXTPROC __glewGetPointeri_vEXT = NULL;
+PFNGLGETTEXTUREIMAGEEXTPROC __glewGetTextureImageEXT = NULL;
+PFNGLGETTEXTURELEVELPARAMETERFVEXTPROC __glewGetTextureLevelParameterfvEXT = NULL;
+PFNGLGETTEXTURELEVELPARAMETERIVEXTPROC __glewGetTextureLevelParameterivEXT = NULL;
+PFNGLGETTEXTUREPARAMETERIIVEXTPROC __glewGetTextureParameterIivEXT = NULL;
+PFNGLGETTEXTUREPARAMETERIUIVEXTPROC __glewGetTextureParameterIuivEXT = NULL;
+PFNGLGETTEXTUREPARAMETERFVEXTPROC __glewGetTextureParameterfvEXT = NULL;
+PFNGLGETTEXTUREPARAMETERIVEXTPROC __glewGetTextureParameterivEXT = NULL;
+PFNGLGETVERTEXARRAYINTEGERI_VEXTPROC __glewGetVertexArrayIntegeri_vEXT = NULL;
+PFNGLGETVERTEXARRAYINTEGERVEXTPROC __glewGetVertexArrayIntegervEXT = NULL;
+PFNGLGETVERTEXARRAYPOINTERI_VEXTPROC __glewGetVertexArrayPointeri_vEXT = NULL;
+PFNGLGETVERTEXARRAYPOINTERVEXTPROC __glewGetVertexArrayPointervEXT = NULL;
+PFNGLMAPNAMEDBUFFEREXTPROC __glewMapNamedBufferEXT = NULL;
+PFNGLMAPNAMEDBUFFERRANGEEXTPROC __glewMapNamedBufferRangeEXT = NULL;
+PFNGLMATRIXFRUSTUMEXTPROC __glewMatrixFrustumEXT = NULL;
+PFNGLMATRIXLOADIDENTITYEXTPROC __glewMatrixLoadIdentityEXT = NULL;
+PFNGLMATRIXLOADTRANSPOSEDEXTPROC __glewMatrixLoadTransposedEXT = NULL;
+PFNGLMATRIXLOADTRANSPOSEFEXTPROC __glewMatrixLoadTransposefEXT = NULL;
+PFNGLMATRIXLOADDEXTPROC __glewMatrixLoaddEXT = NULL;
+PFNGLMATRIXLOADFEXTPROC __glewMatrixLoadfEXT = NULL;
+PFNGLMATRIXMULTTRANSPOSEDEXTPROC __glewMatrixMultTransposedEXT = NULL;
+PFNGLMATRIXMULTTRANSPOSEFEXTPROC __glewMatrixMultTransposefEXT = NULL;
+PFNGLMATRIXMULTDEXTPROC __glewMatrixMultdEXT = NULL;
+PFNGLMATRIXMULTFEXTPROC __glewMatrixMultfEXT = NULL;
+PFNGLMATRIXORTHOEXTPROC __glewMatrixOrthoEXT = NULL;
+PFNGLMATRIXPOPEXTPROC __glewMatrixPopEXT = NULL;
+PFNGLMATRIXPUSHEXTPROC __glewMatrixPushEXT = NULL;
+PFNGLMATRIXROTATEDEXTPROC __glewMatrixRotatedEXT = NULL;
+PFNGLMATRIXROTATEFEXTPROC __glewMatrixRotatefEXT = NULL;
+PFNGLMATRIXSCALEDEXTPROC __glewMatrixScaledEXT = NULL;
+PFNGLMATRIXSCALEFEXTPROC __glewMatrixScalefEXT = NULL;
+PFNGLMATRIXTRANSLATEDEXTPROC __glewMatrixTranslatedEXT = NULL;
+PFNGLMATRIXTRANSLATEFEXTPROC __glewMatrixTranslatefEXT = NULL;
+PFNGLMULTITEXBUFFEREXTPROC __glewMultiTexBufferEXT = NULL;
+PFNGLMULTITEXCOORDPOINTEREXTPROC __glewMultiTexCoordPointerEXT = NULL;
+PFNGLMULTITEXENVFEXTPROC __glewMultiTexEnvfEXT = NULL;
+PFNGLMULTITEXENVFVEXTPROC __glewMultiTexEnvfvEXT = NULL;
+PFNGLMULTITEXENVIEXTPROC __glewMultiTexEnviEXT = NULL;
+PFNGLMULTITEXENVIVEXTPROC __glewMultiTexEnvivEXT = NULL;
+PFNGLMULTITEXGENDEXTPROC __glewMultiTexGendEXT = NULL;
+PFNGLMULTITEXGENDVEXTPROC __glewMultiTexGendvEXT = NULL;
+PFNGLMULTITEXGENFEXTPROC __glewMultiTexGenfEXT = NULL;
+PFNGLMULTITEXGENFVEXTPROC __glewMultiTexGenfvEXT = NULL;
+PFNGLMULTITEXGENIEXTPROC __glewMultiTexGeniEXT = NULL;
+PFNGLMULTITEXGENIVEXTPROC __glewMultiTexGenivEXT = NULL;
+PFNGLMULTITEXIMAGE1DEXTPROC __glewMultiTexImage1DEXT = NULL;
+PFNGLMULTITEXIMAGE2DEXTPROC __glewMultiTexImage2DEXT = NULL;
+PFNGLMULTITEXIMAGE3DEXTPROC __glewMultiTexImage3DEXT = NULL;
+PFNGLMULTITEXPARAMETERIIVEXTPROC __glewMultiTexParameterIivEXT = NULL;
+PFNGLMULTITEXPARAMETERIUIVEXTPROC __glewMultiTexParameterIuivEXT = NULL;
+PFNGLMULTITEXPARAMETERFEXTPROC __glewMultiTexParameterfEXT = NULL;
+PFNGLMULTITEXPARAMETERFVEXTPROC __glewMultiTexParameterfvEXT = NULL;
+PFNGLMULTITEXPARAMETERIEXTPROC __glewMultiTexParameteriEXT = NULL;
+PFNGLMULTITEXPARAMETERIVEXTPROC __glewMultiTexParameterivEXT = NULL;
+PFNGLMULTITEXRENDERBUFFEREXTPROC __glewMultiTexRenderbufferEXT = NULL;
+PFNGLMULTITEXSUBIMAGE1DEXTPROC __glewMultiTexSubImage1DEXT = NULL;
+PFNGLMULTITEXSUBIMAGE2DEXTPROC __glewMultiTexSubImage2DEXT = NULL;
+PFNGLMULTITEXSUBIMAGE3DEXTPROC __glewMultiTexSubImage3DEXT = NULL;
+PFNGLNAMEDBUFFERDATAEXTPROC __glewNamedBufferDataEXT = NULL;
+PFNGLNAMEDBUFFERSUBDATAEXTPROC __glewNamedBufferSubDataEXT = NULL;
+PFNGLNAMEDCOPYBUFFERSUBDATAEXTPROC __glewNamedCopyBufferSubDataEXT = NULL;
+PFNGLNAMEDFRAMEBUFFERRENDERBUFFEREXTPROC __glewNamedFramebufferRenderbufferEXT = NULL;
+PFNGLNAMEDFRAMEBUFFERTEXTURE1DEXTPROC __glewNamedFramebufferTexture1DEXT = NULL;
+PFNGLNAMEDFRAMEBUFFERTEXTURE2DEXTPROC __glewNamedFramebufferTexture2DEXT = NULL;
+PFNGLNAMEDFRAMEBUFFERTEXTURE3DEXTPROC __glewNamedFramebufferTexture3DEXT = NULL;
+PFNGLNAMEDFRAMEBUFFERTEXTUREEXTPROC __glewNamedFramebufferTextureEXT = NULL;
+PFNGLNAMEDFRAMEBUFFERTEXTUREFACEEXTPROC __glewNamedFramebufferTextureFaceEXT = NULL;
+PFNGLNAMEDFRAMEBUFFERTEXTURELAYEREXTPROC __glewNamedFramebufferTextureLayerEXT = NULL;
+PFNGLNAMEDPROGRAMLOCALPARAMETER4DEXTPROC __glewNamedProgramLocalParameter4dEXT = NULL;
+PFNGLNAMEDPROGRAMLOCALPARAMETER4DVEXTPROC __glewNamedProgramLocalParameter4dvEXT = NULL;
+PFNGLNAMEDPROGRAMLOCALPARAMETER4FEXTPROC __glewNamedProgramLocalParameter4fEXT = NULL;
+PFNGLNAMEDPROGRAMLOCALPARAMETER4FVEXTPROC __glewNamedProgramLocalParameter4fvEXT = NULL;
+PFNGLNAMEDPROGRAMLOCALPARAMETERI4IEXTPROC __glewNamedProgramLocalParameterI4iEXT = NULL;
+PFNGLNAMEDPROGRAMLOCALPARAMETERI4IVEXTPROC __glewNamedProgramLocalParameterI4ivEXT = NULL;
+PFNGLNAMEDPROGRAMLOCALPARAMETERI4UIEXTPROC __glewNamedProgramLocalParameterI4uiEXT = NULL;
+PFNGLNAMEDPROGRAMLOCALPARAMETERI4UIVEXTPROC __glewNamedProgramLocalParameterI4uivEXT = NULL;
+PFNGLNAMEDPROGRAMLOCALPARAMETERS4FVEXTPROC __glewNamedProgramLocalParameters4fvEXT = NULL;
+PFNGLNAMEDPROGRAMLOCALPARAMETERSI4IVEXTPROC __glewNamedProgramLocalParametersI4ivEXT = NULL;
+PFNGLNAMEDPROGRAMLOCALPARAMETERSI4UIVEXTPROC __glewNamedProgramLocalParametersI4uivEXT = NULL;
+PFNGLNAMEDPROGRAMSTRINGEXTPROC __glewNamedProgramStringEXT = NULL;
+PFNGLNAMEDRENDERBUFFERSTORAGEEXTPROC __glewNamedRenderbufferStorageEXT = NULL;
+PFNGLNAMEDRENDERBUFFERSTORAGEMULTISAMPLECOVERAGEEXTPROC __glewNamedRenderbufferStorageMultisampleCoverageEXT = NULL;
+PFNGLNAMEDRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC __glewNamedRenderbufferStorageMultisampleEXT = NULL;
+PFNGLPROGRAMUNIFORM1FEXTPROC __glewProgramUniform1fEXT = NULL;
+PFNGLPROGRAMUNIFORM1FVEXTPROC __glewProgramUniform1fvEXT = NULL;
+PFNGLPROGRAMUNIFORM1IEXTPROC __glewProgramUniform1iEXT = NULL;
+PFNGLPROGRAMUNIFORM1IVEXTPROC __glewProgramUniform1ivEXT = NULL;
+PFNGLPROGRAMUNIFORM1UIEXTPROC __glewProgramUniform1uiEXT = NULL;
+PFNGLPROGRAMUNIFORM1UIVEXTPROC __glewProgramUniform1uivEXT = NULL;
+PFNGLPROGRAMUNIFORM2FEXTPROC __glewProgramUniform2fEXT = NULL;
+PFNGLPROGRAMUNIFORM2FVEXTPROC __glewProgramUniform2fvEXT = NULL;
+PFNGLPROGRAMUNIFORM2IEXTPROC __glewProgramUniform2iEXT = NULL;
+PFNGLPROGRAMUNIFORM2IVEXTPROC __glewProgramUniform2ivEXT = NULL;
+PFNGLPROGRAMUNIFORM2UIEXTPROC __glewProgramUniform2uiEXT = NULL;
+PFNGLPROGRAMUNIFORM2UIVEXTPROC __glewProgramUniform2uivEXT = NULL;
+PFNGLPROGRAMUNIFORM3FEXTPROC __glewProgramUniform3fEXT = NULL;
+PFNGLPROGRAMUNIFORM3FVEXTPROC __glewProgramUniform3fvEXT = NULL;
+PFNGLPROGRAMUNIFORM3IEXTPROC __glewProgramUniform3iEXT = NULL;
+PFNGLPROGRAMUNIFORM3IVEXTPROC __glewProgramUniform3ivEXT = NULL;
+PFNGLPROGRAMUNIFORM3UIEXTPROC __glewProgramUniform3uiEXT = NULL;
+PFNGLPROGRAMUNIFORM3UIVEXTPROC __glewProgramUniform3uivEXT = NULL;
+PFNGLPROGRAMUNIFORM4FEXTPROC __glewProgramUniform4fEXT = NULL;
+PFNGLPROGRAMUNIFORM4FVEXTPROC __glewProgramUniform4fvEXT = NULL;
+PFNGLPROGRAMUNIFORM4IEXTPROC __glewProgramUniform4iEXT = NULL;
+PFNGLPROGRAMUNIFORM4IVEXTPROC __glewProgramUniform4ivEXT = NULL;
+PFNGLPROGRAMUNIFORM4UIEXTPROC __glewProgramUniform4uiEXT = NULL;
+PFNGLPROGRAMUNIFORM4UIVEXTPROC __glewProgramUniform4uivEXT = NULL;
+PFNGLPROGRAMUNIFORMMATRIX2FVEXTPROC __glewProgramUniformMatrix2fvEXT = NULL;
+PFNGLPROGRAMUNIFORMMATRIX2X3FVEXTPROC __glewProgramUniformMatrix2x3fvEXT = NULL;
+PFNGLPROGRAMUNIFORMMATRIX2X4FVEXTPROC __glewProgramUniformMatrix2x4fvEXT = NULL;
+PFNGLPROGRAMUNIFORMMATRIX3FVEXTPROC __glewProgramUniformMatrix3fvEXT = NULL;
+PFNGLPROGRAMUNIFORMMATRIX3X2FVEXTPROC __glewProgramUniformMatrix3x2fvEXT = NULL;
+PFNGLPROGRAMUNIFORMMATRIX3X4FVEXTPROC __glewProgramUniformMatrix3x4fvEXT = NULL;
+PFNGLPROGRAMUNIFORMMATRIX4FVEXTPROC __glewProgramUniformMatrix4fvEXT = NULL;
+PFNGLPROGRAMUNIFORMMATRIX4X2FVEXTPROC __glewProgramUniformMatrix4x2fvEXT = NULL;
+PFNGLPROGRAMUNIFORMMATRIX4X3FVEXTPROC __glewProgramUniformMatrix4x3fvEXT = NULL;
+PFNGLPUSHCLIENTATTRIBDEFAULTEXTPROC __glewPushClientAttribDefaultEXT = NULL;
+PFNGLTEXTUREBUFFEREXTPROC __glewTextureBufferEXT = NULL;
+PFNGLTEXTUREIMAGE1DEXTPROC __glewTextureImage1DEXT = NULL;
+PFNGLTEXTUREIMAGE2DEXTPROC __glewTextureImage2DEXT = NULL;
+PFNGLTEXTUREIMAGE3DEXTPROC __glewTextureImage3DEXT = NULL;
+PFNGLTEXTUREPARAMETERIIVEXTPROC __glewTextureParameterIivEXT = NULL;
+PFNGLTEXTUREPARAMETERIUIVEXTPROC __glewTextureParameterIuivEXT = NULL;
+PFNGLTEXTUREPARAMETERFEXTPROC __glewTextureParameterfEXT = NULL;
+PFNGLTEXTUREPARAMETERFVEXTPROC __glewTextureParameterfvEXT = NULL;
+PFNGLTEXTUREPARAMETERIEXTPROC __glewTextureParameteriEXT = NULL;
+PFNGLTEXTUREPARAMETERIVEXTPROC __glewTextureParameterivEXT = NULL;
+PFNGLTEXTURERENDERBUFFEREXTPROC __glewTextureRenderbufferEXT = NULL;
+PFNGLTEXTURESUBIMAGE1DEXTPROC __glewTextureSubImage1DEXT = NULL;
+PFNGLTEXTURESUBIMAGE2DEXTPROC __glewTextureSubImage2DEXT = NULL;
+PFNGLTEXTURESUBIMAGE3DEXTPROC __glewTextureSubImage3DEXT = NULL;
+PFNGLUNMAPNAMEDBUFFEREXTPROC __glewUnmapNamedBufferEXT = NULL;
+PFNGLVERTEXARRAYCOLOROFFSETEXTPROC __glewVertexArrayColorOffsetEXT = NULL;
+PFNGLVERTEXARRAYEDGEFLAGOFFSETEXTPROC __glewVertexArrayEdgeFlagOffsetEXT = NULL;
+PFNGLVERTEXARRAYFOGCOORDOFFSETEXTPROC __glewVertexArrayFogCoordOffsetEXT = NULL;
+PFNGLVERTEXARRAYINDEXOFFSETEXTPROC __glewVertexArrayIndexOffsetEXT = NULL;
+PFNGLVERTEXARRAYMULTITEXCOORDOFFSETEXTPROC __glewVertexArrayMultiTexCoordOffsetEXT = NULL;
+PFNGLVERTEXARRAYNORMALOFFSETEXTPROC __glewVertexArrayNormalOffsetEXT = NULL;
+PFNGLVERTEXARRAYSECONDARYCOLOROFFSETEXTPROC __glewVertexArraySecondaryColorOffsetEXT = NULL;
+PFNGLVERTEXARRAYTEXCOORDOFFSETEXTPROC __glewVertexArrayTexCoordOffsetEXT = NULL;
+PFNGLVERTEXARRAYVERTEXATTRIBIOFFSETEXTPROC __glewVertexArrayVertexAttribIOffsetEXT = NULL;
+PFNGLVERTEXARRAYVERTEXATTRIBOFFSETEXTPROC __glewVertexArrayVertexAttribOffsetEXT = NULL;
+PFNGLVERTEXARRAYVERTEXOFFSETEXTPROC __glewVertexArrayVertexOffsetEXT = NULL;
+
+PFNGLCOLORMASKINDEXEDEXTPROC __glewColorMaskIndexedEXT = NULL;
+PFNGLDISABLEINDEXEDEXTPROC __glewDisableIndexedEXT = NULL;
+PFNGLENABLEINDEXEDEXTPROC __glewEnableIndexedEXT = NULL;
+PFNGLGETBOOLEANINDEXEDVEXTPROC __glewGetBooleanIndexedvEXT = NULL;
+PFNGLGETINTEGERINDEXEDVEXTPROC __glewGetIntegerIndexedvEXT = NULL;
+PFNGLISENABLEDINDEXEDEXTPROC __glewIsEnabledIndexedEXT = NULL;
+
+PFNGLDRAWARRAYSINSTANCEDEXTPROC __glewDrawArraysInstancedEXT = NULL;
+PFNGLDRAWELEMENTSINSTANCEDEXTPROC __glewDrawElementsInstancedEXT = NULL;
+
+PFNGLDRAWRANGEELEMENTSEXTPROC __glewDrawRangeElementsEXT = NULL;
+
+PFNGLFOGCOORDPOINTEREXTPROC __glewFogCoordPointerEXT = NULL;
+PFNGLFOGCOORDDEXTPROC __glewFogCoorddEXT = NULL;
+PFNGLFOGCOORDDVEXTPROC __glewFogCoorddvEXT = NULL;
+PFNGLFOGCOORDFEXTPROC __glewFogCoordfEXT = NULL;
+PFNGLFOGCOORDFVEXTPROC __glewFogCoordfvEXT = NULL;
+
+PFNGLFRAGMENTCOLORMATERIALEXTPROC __glewFragmentColorMaterialEXT = NULL;
+PFNGLFRAGMENTLIGHTMODELFEXTPROC __glewFragmentLightModelfEXT = NULL;
+PFNGLFRAGMENTLIGHTMODELFVEXTPROC __glewFragmentLightModelfvEXT = NULL;
+PFNGLFRAGMENTLIGHTMODELIEXTPROC __glewFragmentLightModeliEXT = NULL;
+PFNGLFRAGMENTLIGHTMODELIVEXTPROC __glewFragmentLightModelivEXT = NULL;
+PFNGLFRAGMENTLIGHTFEXTPROC __glewFragmentLightfEXT = NULL;
+PFNGLFRAGMENTLIGHTFVEXTPROC __glewFragmentLightfvEXT = NULL;
+PFNGLFRAGMENTLIGHTIEXTPROC __glewFragmentLightiEXT = NULL;
+PFNGLFRAGMENTLIGHTIVEXTPROC __glewFragmentLightivEXT = NULL;
+PFNGLFRAGMENTMATERIALFEXTPROC __glewFragmentMaterialfEXT = NULL;
+PFNGLFRAGMENTMATERIALFVEXTPROC __glewFragmentMaterialfvEXT = NULL;
+PFNGLFRAGMENTMATERIALIEXTPROC __glewFragmentMaterialiEXT = NULL;
+PFNGLFRAGMENTMATERIALIVEXTPROC __glewFragmentMaterialivEXT = NULL;
+PFNGLGETFRAGMENTLIGHTFVEXTPROC __glewGetFragmentLightfvEXT = NULL;
+PFNGLGETFRAGMENTLIGHTIVEXTPROC __glewGetFragmentLightivEXT = NULL;
+PFNGLGETFRAGMENTMATERIALFVEXTPROC __glewGetFragmentMaterialfvEXT = NULL;
+PFNGLGETFRAGMENTMATERIALIVEXTPROC __glewGetFragmentMaterialivEXT = NULL;
+PFNGLLIGHTENVIEXTPROC __glewLightEnviEXT = NULL;
+
+PFNGLBLITFRAMEBUFFEREXTPROC __glewBlitFramebufferEXT = NULL;
+
+PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC __glewRenderbufferStorageMultisampleEXT = NULL;
+
+PFNGLBINDFRAMEBUFFEREXTPROC __glewBindFramebufferEXT = NULL;
+PFNGLBINDRENDERBUFFEREXTPROC __glewBindRenderbufferEXT = NULL;
+PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC __glewCheckFramebufferStatusEXT = NULL;
+PFNGLDELETEFRAMEBUFFERSEXTPROC __glewDeleteFramebuffersEXT = NULL;
+PFNGLDELETERENDERBUFFERSEXTPROC __glewDeleteRenderbuffersEXT = NULL;
+PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC __glewFramebufferRenderbufferEXT = NULL;
+PFNGLFRAMEBUFFERTEXTURE1DEXTPROC __glewFramebufferTexture1DEXT = NULL;
+PFNGLFRAMEBUFFERTEXTURE2DEXTPROC __glewFramebufferTexture2DEXT = NULL;
+PFNGLFRAMEBUFFERTEXTURE3DEXTPROC __glewFramebufferTexture3DEXT = NULL;
+PFNGLGENFRAMEBUFFERSEXTPROC __glewGenFramebuffersEXT = NULL;
+PFNGLGENRENDERBUFFERSEXTPROC __glewGenRenderbuffersEXT = NULL;
+PFNGLGENERATEMIPMAPEXTPROC __glewGenerateMipmapEXT = NULL;
+PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC __glewGetFramebufferAttachmentParameterivEXT = NULL;
+PFNGLGETRENDERBUFFERPARAMETERIVEXTPROC __glewGetRenderbufferParameterivEXT = NULL;
+PFNGLISFRAMEBUFFEREXTPROC __glewIsFramebufferEXT = NULL;
+PFNGLISRENDERBUFFEREXTPROC __glewIsRenderbufferEXT = NULL;
+PFNGLRENDERBUFFERSTORAGEEXTPROC __glewRenderbufferStorageEXT = NULL;
+
+PFNGLFRAMEBUFFERTEXTUREEXTPROC __glewFramebufferTextureEXT = NULL;
+PFNGLFRAMEBUFFERTEXTUREFACEEXTPROC __glewFramebufferTextureFaceEXT = NULL;
+PFNGLPROGRAMPARAMETERIEXTPROC __glewProgramParameteriEXT = NULL;
+
+PFNGLPROGRAMENVPARAMETERS4FVEXTPROC __glewProgramEnvParameters4fvEXT = NULL;
+PFNGLPROGRAMLOCALPARAMETERS4FVEXTPROC __glewProgramLocalParameters4fvEXT = NULL;
+
+PFNGLBINDFRAGDATALOCATIONEXTPROC __glewBindFragDataLocationEXT = NULL;
+PFNGLGETFRAGDATALOCATIONEXTPROC __glewGetFragDataLocationEXT = NULL;
+PFNGLGETUNIFORMUIVEXTPROC __glewGetUniformuivEXT = NULL;
+PFNGLGETVERTEXATTRIBIIVEXTPROC __glewGetVertexAttribIivEXT = NULL;
+PFNGLGETVERTEXATTRIBIUIVEXTPROC __glewGetVertexAttribIuivEXT = NULL;
+PFNGLUNIFORM1UIEXTPROC __glewUniform1uiEXT = NULL;
+PFNGLUNIFORM1UIVEXTPROC __glewUniform1uivEXT = NULL;
+PFNGLUNIFORM2UIEXTPROC __glewUniform2uiEXT = NULL;
+PFNGLUNIFORM2UIVEXTPROC __glewUniform2uivEXT = NULL;
+PFNGLUNIFORM3UIEXTPROC __glewUniform3uiEXT = NULL;
+PFNGLUNIFORM3UIVEXTPROC __glewUniform3uivEXT = NULL;
+PFNGLUNIFORM4UIEXTPROC __glewUniform4uiEXT = NULL;
+PFNGLUNIFORM4UIVEXTPROC __glewUniform4uivEXT = NULL;
+PFNGLVERTEXATTRIBI1IEXTPROC __glewVertexAttribI1iEXT = NULL;
+PFNGLVERTEXATTRIBI1IVEXTPROC __glewVertexAttribI1ivEXT = NULL;
+PFNGLVERTEXATTRIBI1UIEXTPROC __glewVertexAttribI1uiEXT = NULL;
+PFNGLVERTEXATTRIBI1UIVEXTPROC __glewVertexAttribI1uivEXT = NULL;
+PFNGLVERTEXATTRIBI2IEXTPROC __glewVertexAttribI2iEXT = NULL;
+PFNGLVERTEXATTRIBI2IVEXTPROC __glewVertexAttribI2ivEXT = NULL;
+PFNGLVERTEXATTRIBI2UIEXTPROC __glewVertexAttribI2uiEXT = NULL;
+PFNGLVERTEXATTRIBI2UIVEXTPROC __glewVertexAttribI2uivEXT = NULL;
+PFNGLVERTEXATTRIBI3IEXTPROC __glewVertexAttribI3iEXT = NULL;
+PFNGLVERTEXATTRIBI3IVEXTPROC __glewVertexAttribI3ivEXT = NULL;
+PFNGLVERTEXATTRIBI3UIEXTPROC __glewVertexAttribI3uiEXT = NULL;
+PFNGLVERTEXATTRIBI3UIVEXTPROC __glewVertexAttribI3uivEXT = NULL;
+PFNGLVERTEXATTRIBI4BVEXTPROC __glewVertexAttribI4bvEXT = NULL;
+PFNGLVERTEXATTRIBI4IEXTPROC __glewVertexAttribI4iEXT = NULL;
+PFNGLVERTEXATTRIBI4IVEXTPROC __glewVertexAttribI4ivEXT = NULL;
+PFNGLVERTEXATTRIBI4SVEXTPROC __glewVertexAttribI4svEXT = NULL;
+PFNGLVERTEXATTRIBI4UBVEXTPROC __glewVertexAttribI4ubvEXT = NULL;
+PFNGLVERTEXATTRIBI4UIEXTPROC __glewVertexAttribI4uiEXT = NULL;
+PFNGLVERTEXATTRIBI4UIVEXTPROC __glewVertexAttribI4uivEXT = NULL;
+PFNGLVERTEXATTRIBI4USVEXTPROC __glewVertexAttribI4usvEXT = NULL;
+PFNGLVERTEXATTRIBIPOINTEREXTPROC __glewVertexAttribIPointerEXT = NULL;
+
+PFNGLGETHISTOGRAMEXTPROC __glewGetHistogramEXT = NULL;
+PFNGLGETHISTOGRAMPARAMETERFVEXTPROC __glewGetHistogramParameterfvEXT = NULL;
+PFNGLGETHISTOGRAMPARAMETERIVEXTPROC __glewGetHistogramParameterivEXT = NULL;
+PFNGLGETMINMAXEXTPROC __glewGetMinmaxEXT = NULL;
+PFNGLGETMINMAXPARAMETERFVEXTPROC __glewGetMinmaxParameterfvEXT = NULL;
+PFNGLGETMINMAXPARAMETERIVEXTPROC __glewGetMinmaxParameterivEXT = NULL;
+PFNGLHISTOGRAMEXTPROC __glewHistogramEXT = NULL;
+PFNGLMINMAXEXTPROC __glewMinmaxEXT = NULL;
+PFNGLRESETHISTOGRAMEXTPROC __glewResetHistogramEXT = NULL;
+PFNGLRESETMINMAXEXTPROC __glewResetMinmaxEXT = NULL;
+
+PFNGLINDEXFUNCEXTPROC __glewIndexFuncEXT = NULL;
+
+PFNGLINDEXMATERIALEXTPROC __glewIndexMaterialEXT = NULL;
+
+PFNGLAPPLYTEXTUREEXTPROC __glewApplyTextureEXT = NULL;
+PFNGLTEXTURELIGHTEXTPROC __glewTextureLightEXT = NULL;
+PFNGLTEXTUREMATERIALEXTPROC __glewTextureMaterialEXT = NULL;
+
+PFNGLMULTIDRAWARRAYSEXTPROC __glewMultiDrawArraysEXT = NULL;
+PFNGLMULTIDRAWELEMENTSEXTPROC __glewMultiDrawElementsEXT = NULL;
+
+PFNGLSAMPLEMASKEXTPROC __glewSampleMaskEXT = NULL;
+PFNGLSAMPLEPATTERNEXTPROC __glewSamplePatternEXT = NULL;
+
+PFNGLCOLORTABLEEXTPROC __glewColorTableEXT = NULL;
+PFNGLGETCOLORTABLEEXTPROC __glewGetColorTableEXT = NULL;
+PFNGLGETCOLORTABLEPARAMETERFVEXTPROC __glewGetColorTableParameterfvEXT = NULL;
+PFNGLGETCOLORTABLEPARAMETERIVEXTPROC __glewGetColorTableParameterivEXT = NULL;
+
+PFNGLGETPIXELTRANSFORMPARAMETERFVEXTPROC __glewGetPixelTransformParameterfvEXT = NULL;
+PFNGLGETPIXELTRANSFORMPARAMETERIVEXTPROC __glewGetPixelTransformParameterivEXT = NULL;
+PFNGLPIXELTRANSFORMPARAMETERFEXTPROC __glewPixelTransformParameterfEXT = NULL;
+PFNGLPIXELTRANSFORMPARAMETERFVEXTPROC __glewPixelTransformParameterfvEXT = NULL;
+PFNGLPIXELTRANSFORMPARAMETERIEXTPROC __glewPixelTransformParameteriEXT = NULL;
+PFNGLPIXELTRANSFORMPARAMETERIVEXTPROC __glewPixelTransformParameterivEXT = NULL;
+
+PFNGLPOINTPARAMETERFEXTPROC __glewPointParameterfEXT = NULL;
+PFNGLPOINTPARAMETERFVEXTPROC __glewPointParameterfvEXT = NULL;
+
+PFNGLPOLYGONOFFSETEXTPROC __glewPolygonOffsetEXT = NULL;
+
+PFNGLPROVOKINGVERTEXEXTPROC __glewProvokingVertexEXT = NULL;
+
+PFNGLBEGINSCENEEXTPROC __glewBeginSceneEXT = NULL;
+PFNGLENDSCENEEXTPROC __glewEndSceneEXT = NULL;
+
+PFNGLSECONDARYCOLOR3BEXTPROC __glewSecondaryColor3bEXT = NULL;
+PFNGLSECONDARYCOLOR3BVEXTPROC __glewSecondaryColor3bvEXT = NULL;
+PFNGLSECONDARYCOLOR3DEXTPROC __glewSecondaryColor3dEXT = NULL;
+PFNGLSECONDARYCOLOR3DVEXTPROC __glewSecondaryColor3dvEXT = NULL;
+PFNGLSECONDARYCOLOR3FEXTPROC __glewSecondaryColor3fEXT = NULL;
+PFNGLSECONDARYCOLOR3FVEXTPROC __glewSecondaryColor3fvEXT = NULL;
+PFNGLSECONDARYCOLOR3IEXTPROC __glewSecondaryColor3iEXT = NULL;
+PFNGLSECONDARYCOLOR3IVEXTPROC __glewSecondaryColor3ivEXT = NULL;
+PFNGLSECONDARYCOLOR3SEXTPROC __glewSecondaryColor3sEXT = NULL;
+PFNGLSECONDARYCOLOR3SVEXTPROC __glewSecondaryColor3svEXT = NULL;
+PFNGLSECONDARYCOLOR3UBEXTPROC __glewSecondaryColor3ubEXT = NULL;
+PFNGLSECONDARYCOLOR3UBVEXTPROC __glewSecondaryColor3ubvEXT = NULL;
+PFNGLSECONDARYCOLOR3UIEXTPROC __glewSecondaryColor3uiEXT = NULL;
+PFNGLSECONDARYCOLOR3UIVEXTPROC __glewSecondaryColor3uivEXT = NULL;
+PFNGLSECONDARYCOLOR3USEXTPROC __glewSecondaryColor3usEXT = NULL;
+PFNGLSECONDARYCOLOR3USVEXTPROC __glewSecondaryColor3usvEXT = NULL;
+PFNGLSECONDARYCOLORPOINTEREXTPROC __glewSecondaryColorPointerEXT = NULL;
+
+#if 0 // NOTE jwilkins: inconsistencies
+PFNGLACTIVEPROGRAMEXTPROC __glewActiveProgramEXT = NULL;
+PFNGLCREATESHADERPROGRAMEXTPROC __glewCreateShaderProgramEXT = NULL;
+PFNGLUSESHADERPROGRAMEXTPROC __glewUseShaderProgramEXT = NULL;
+#endif
+
+PFNGLBINDIMAGETEXTUREEXTPROC __glewBindImageTextureEXT = NULL;
+PFNGLMEMORYBARRIEREXTPROC __glewMemoryBarrierEXT = NULL;
+
+PFNGLACTIVESTENCILFACEEXTPROC __glewActiveStencilFaceEXT = NULL;
+
+PFNGLTEXSUBIMAGE1DEXTPROC __glewTexSubImage1DEXT = NULL;
+PFNGLTEXSUBIMAGE2DEXTPROC __glewTexSubImage2DEXT = NULL;
+PFNGLTEXSUBIMAGE3DEXTPROC __glewTexSubImage3DEXT = NULL;
+
+PFNGLTEXIMAGE3DEXTPROC __glewTexImage3DEXT = NULL;
+
+PFNGLFRAMEBUFFERTEXTURELAYEREXTPROC __glewFramebufferTextureLayerEXT = NULL;
+
+PFNGLTEXBUFFEREXTPROC __glewTexBufferEXT = NULL;
+
+PFNGLCLEARCOLORIIEXTPROC __glewClearColorIiEXT = NULL;
+PFNGLCLEARCOLORIUIEXTPROC __glewClearColorIuiEXT = NULL;
+PFNGLGETTEXPARAMETERIIVEXTPROC __glewGetTexParameterIivEXT = NULL;
+PFNGLGETTEXPARAMETERIUIVEXTPROC __glewGetTexParameterIuivEXT = NULL;
+PFNGLTEXPARAMETERIIVEXTPROC __glewTexParameterIivEXT = NULL;
+PFNGLTEXPARAMETERIUIVEXTPROC __glewTexParameterIuivEXT = NULL;
+
+PFNGLARETEXTURESRESIDENTEXTPROC __glewAreTexturesResidentEXT = NULL;
+PFNGLBINDTEXTUREEXTPROC __glewBindTextureEXT = NULL;
+PFNGLDELETETEXTURESEXTPROC __glewDeleteTexturesEXT = NULL;
+PFNGLGENTEXTURESEXTPROC __glewGenTexturesEXT = NULL;
+PFNGLISTEXTUREEXTPROC __glewIsTextureEXT = NULL;
+PFNGLPRIORITIZETEXTURESEXTPROC __glewPrioritizeTexturesEXT = NULL;
+
+PFNGLTEXTURENORMALEXTPROC __glewTextureNormalEXT = NULL;
+
+PFNGLGETQUERYOBJECTI64VEXTPROC __glewGetQueryObjecti64vEXT = NULL;
+PFNGLGETQUERYOBJECTUI64VEXTPROC __glewGetQueryObjectui64vEXT = NULL;
+
+PFNGLBEGINTRANSFORMFEEDBACKEXTPROC __glewBeginTransformFeedbackEXT = NULL;
+PFNGLBINDBUFFERBASEEXTPROC __glewBindBufferBaseEXT = NULL;
+PFNGLBINDBUFFEROFFSETEXTPROC __glewBindBufferOffsetEXT = NULL;
+PFNGLBINDBUFFERRANGEEXTPROC __glewBindBufferRangeEXT = NULL;
+PFNGLENDTRANSFORMFEEDBACKEXTPROC __glewEndTransformFeedbackEXT = NULL;
+PFNGLGETTRANSFORMFEEDBACKVARYINGEXTPROC __glewGetTransformFeedbackVaryingEXT = NULL;
+PFNGLTRANSFORMFEEDBACKVARYINGSEXTPROC __glewTransformFeedbackVaryingsEXT = NULL;
+
+PFNGLARRAYELEMENTEXTPROC __glewArrayElementEXT = NULL;
+PFNGLCOLORPOINTEREXTPROC __glewColorPointerEXT = NULL;
+PFNGLDRAWARRAYSEXTPROC __glewDrawArraysEXT = NULL;
+PFNGLEDGEFLAGPOINTEREXTPROC __glewEdgeFlagPointerEXT = NULL;
+PFNGLINDEXPOINTEREXTPROC __glewIndexPointerEXT = NULL;
+PFNGLNORMALPOINTEREXTPROC __glewNormalPointerEXT = NULL;
+PFNGLTEXCOORDPOINTEREXTPROC __glewTexCoordPointerEXT = NULL;
+PFNGLVERTEXPOINTEREXTPROC __glewVertexPointerEXT = NULL;
+
+PFNGLGETVERTEXATTRIBLDVEXTPROC __glewGetVertexAttribLdvEXT = NULL;
+PFNGLVERTEXARRAYVERTEXATTRIBLOFFSETEXTPROC __glewVertexArrayVertexAttribLOffsetEXT = NULL;
+PFNGLVERTEXATTRIBL1DEXTPROC __glewVertexAttribL1dEXT = NULL;
+PFNGLVERTEXATTRIBL1DVEXTPROC __glewVertexAttribL1dvEXT = NULL;
+PFNGLVERTEXATTRIBL2DEXTPROC __glewVertexAttribL2dEXT = NULL;
+PFNGLVERTEXATTRIBL2DVEXTPROC __glewVertexAttribL2dvEXT = NULL;
+PFNGLVERTEXATTRIBL3DEXTPROC __glewVertexAttribL3dEXT = NULL;
+PFNGLVERTEXATTRIBL3DVEXTPROC __glewVertexAttribL3dvEXT = NULL;
+PFNGLVERTEXATTRIBL4DEXTPROC __glewVertexAttribL4dEXT = NULL;
+PFNGLVERTEXATTRIBL4DVEXTPROC __glewVertexAttribL4dvEXT = NULL;
+PFNGLVERTEXATTRIBLPOINTEREXTPROC __glewVertexAttribLPointerEXT = NULL;
+
+PFNGLBEGINVERTEXSHADEREXTPROC __glewBeginVertexShaderEXT = NULL;
+PFNGLBINDLIGHTPARAMETEREXTPROC __glewBindLightParameterEXT = NULL;
+PFNGLBINDMATERIALPARAMETEREXTPROC __glewBindMaterialParameterEXT = NULL;
+PFNGLBINDPARAMETEREXTPROC __glewBindParameterEXT = NULL;
+PFNGLBINDTEXGENPARAMETEREXTPROC __glewBindTexGenParameterEXT = NULL;
+PFNGLBINDTEXTUREUNITPARAMETEREXTPROC __glewBindTextureUnitParameterEXT = NULL;
+PFNGLBINDVERTEXSHADEREXTPROC __glewBindVertexShaderEXT = NULL;
+PFNGLDELETEVERTEXSHADEREXTPROC __glewDeleteVertexShaderEXT = NULL;
+PFNGLDISABLEVARIANTCLIENTSTATEEXTPROC __glewDisableVariantClientStateEXT = NULL;
+PFNGLENABLEVARIANTCLIENTSTATEEXTPROC __glewEnableVariantClientStateEXT = NULL;
+PFNGLENDVERTEXSHADEREXTPROC __glewEndVertexShaderEXT = NULL;
+PFNGLEXTRACTCOMPONENTEXTPROC __glewExtractComponentEXT = NULL;
+PFNGLGENSYMBOLSEXTPROC __glewGenSymbolsEXT = NULL;
+PFNGLGENVERTEXSHADERSEXTPROC __glewGenVertexShadersEXT = NULL;
+PFNGLGETINVARIANTBOOLEANVEXTPROC __glewGetInvariantBooleanvEXT = NULL;
+PFNGLGETINVARIANTFLOATVEXTPROC __glewGetInvariantFloatvEXT = NULL;
+PFNGLGETINVARIANTINTEGERVEXTPROC __glewGetInvariantIntegervEXT = NULL;
+PFNGLGETLOCALCONSTANTBOOLEANVEXTPROC __glewGetLocalConstantBooleanvEXT = NULL;
+PFNGLGETLOCALCONSTANTFLOATVEXTPROC __glewGetLocalConstantFloatvEXT = NULL;
+PFNGLGETLOCALCONSTANTINTEGERVEXTPROC __glewGetLocalConstantIntegervEXT = NULL;
+PFNGLGETVARIANTBOOLEANVEXTPROC __glewGetVariantBooleanvEXT = NULL;
+PFNGLGETVARIANTFLOATVEXTPROC __glewGetVariantFloatvEXT = NULL;
+PFNGLGETVARIANTINTEGERVEXTPROC __glewGetVariantIntegervEXT = NULL;
+PFNGLGETVARIANTPOINTERVEXTPROC __glewGetVariantPointervEXT = NULL;
+PFNGLINSERTCOMPONENTEXTPROC __glewInsertComponentEXT = NULL;
+PFNGLISVARIANTENABLEDEXTPROC __glewIsVariantEnabledEXT = NULL;
+PFNGLSETINVARIANTEXTPROC __glewSetInvariantEXT = NULL;
+PFNGLSETLOCALCONSTANTEXTPROC __glewSetLocalConstantEXT = NULL;
+PFNGLSHADEROP1EXTPROC __glewShaderOp1EXT = NULL;
+PFNGLSHADEROP2EXTPROC __glewShaderOp2EXT = NULL;
+PFNGLSHADEROP3EXTPROC __glewShaderOp3EXT = NULL;
+PFNGLSWIZZLEEXTPROC __glewSwizzleEXT = NULL;
+PFNGLVARIANTPOINTEREXTPROC __glewVariantPointerEXT = NULL;
+PFNGLVARIANTBVEXTPROC __glewVariantbvEXT = NULL;
+PFNGLVARIANTDVEXTPROC __glewVariantdvEXT = NULL;
+PFNGLVARIANTFVEXTPROC __glewVariantfvEXT = NULL;
+PFNGLVARIANTIVEXTPROC __glewVariantivEXT = NULL;
+PFNGLVARIANTSVEXTPROC __glewVariantsvEXT = NULL;
+PFNGLVARIANTUBVEXTPROC __glewVariantubvEXT = NULL;
+PFNGLVARIANTUIVEXTPROC __glewVariantuivEXT = NULL;
+PFNGLVARIANTUSVEXTPROC __glewVariantusvEXT = NULL;
+PFNGLWRITEMASKEXTPROC __glewWriteMaskEXT = NULL;
+
+PFNGLVERTEXWEIGHTPOINTEREXTPROC __glewVertexWeightPointerEXT = NULL;
+PFNGLVERTEXWEIGHTFEXTPROC __glewVertexWeightfEXT = NULL;
+PFNGLVERTEXWEIGHTFVEXTPROC __glewVertexWeightfvEXT = NULL;
+
+PFNGLIMPORTSYNCEXTPROC __glewImportSyncEXT = NULL;
+
+PFNGLFRAMETERMINATORGREMEDYPROC __glewFrameTerminatorGREMEDY = NULL;
+
+PFNGLSTRINGMARKERGREMEDYPROC __glewStringMarkerGREMEDY = NULL;
+
+PFNGLGETIMAGETRANSFORMPARAMETERFVHPPROC __glewGetImageTransformParameterfvHP = NULL;
+PFNGLGETIMAGETRANSFORMPARAMETERIVHPPROC __glewGetImageTransformParameterivHP = NULL;
+PFNGLIMAGETRANSFORMPARAMETERFHPPROC __glewImageTransformParameterfHP = NULL;
+PFNGLIMAGETRANSFORMPARAMETERFVHPPROC __glewImageTransformParameterfvHP = NULL;
+PFNGLIMAGETRANSFORMPARAMETERIHPPROC __glewImageTransformParameteriHP = NULL;
+PFNGLIMAGETRANSFORMPARAMETERIVHPPROC __glewImageTransformParameterivHP = NULL;
+
+PFNGLMULTIMODEDRAWARRAYSIBMPROC __glewMultiModeDrawArraysIBM = NULL;
+PFNGLMULTIMODEDRAWELEMENTSIBMPROC __glewMultiModeDrawElementsIBM = NULL;
+
+PFNGLCOLORPOINTERLISTIBMPROC __glewColorPointerListIBM = NULL;
+PFNGLEDGEFLAGPOINTERLISTIBMPROC __glewEdgeFlagPointerListIBM = NULL;
+PFNGLFOGCOORDPOINTERLISTIBMPROC __glewFogCoordPointerListIBM = NULL;
+PFNGLINDEXPOINTERLISTIBMPROC __glewIndexPointerListIBM = NULL;
+PFNGLNORMALPOINTERLISTIBMPROC __glewNormalPointerListIBM = NULL;
+PFNGLSECONDARYCOLORPOINTERLISTIBMPROC __glewSecondaryColorPointerListIBM = NULL;
+PFNGLTEXCOORDPOINTERLISTIBMPROC __glewTexCoordPointerListIBM = NULL;
+PFNGLVERTEXPOINTERLISTIBMPROC __glewVertexPointerListIBM = NULL;
+
+PFNGLMAPTEXTURE2DINTELPROC __glewMapTexture2DINTEL = NULL;
+PFNGLSYNCTEXTUREINTELPROC __glewSyncTextureINTEL = NULL;
+PFNGLUNMAPTEXTURE2DINTELPROC __glewUnmapTexture2DINTEL = NULL;
+
+PFNGLCOLORPOINTERVINTELPROC __glewColorPointervINTEL = NULL;
+PFNGLNORMALPOINTERVINTELPROC __glewNormalPointervINTEL = NULL;
+PFNGLTEXCOORDPOINTERVINTELPROC __glewTexCoordPointervINTEL = NULL;
+PFNGLVERTEXPOINTERVINTELPROC __glewVertexPointervINTEL = NULL;
+
+PFNGLTEXSCISSORFUNCINTELPROC __glewTexScissorFuncINTEL = NULL;
+PFNGLTEXSCISSORINTELPROC __glewTexScissorINTEL = NULL;
+
+PFNGLDEBUGMESSAGECALLBACKPROC __glewDebugMessageCallback = NULL;
+PFNGLDEBUGMESSAGECONTROLPROC __glewDebugMessageControl = NULL;
+PFNGLDEBUGMESSAGEINSERTPROC __glewDebugMessageInsert = NULL;
+PFNGLGETDEBUGMESSAGELOGPROC __glewGetDebugMessageLog = NULL;
+PFNGLGETOBJECTLABELPROC __glewGetObjectLabel = NULL;
+PFNGLGETOBJECTPTRLABELPROC __glewGetObjectPtrLabel = NULL;
+//PFNGLGETPOINTERVPROC __glewGetPointerv = NULL; // NOTE jwilkins: not sure if I'm the one who commented this out
+PFNGLOBJECTLABELPROC __glewObjectLabel = NULL;
+PFNGLOBJECTPTRLABELPROC __glewObjectPtrLabel = NULL;
+PFNGLPOPDEBUGGROUPPROC __glewPopDebugGroup = NULL;
+PFNGLPUSHDEBUGGROUPPROC __glewPushDebugGroup = NULL;
+
+PFNGLBUFFERREGIONENABLEDPROC __glewBufferRegionEnabled = NULL;
+PFNGLDELETEBUFFERREGIONPROC __glewDeleteBufferRegion = NULL;
+PFNGLDRAWBUFFERREGIONPROC __glewDrawBufferRegion = NULL;
+PFNGLNEWBUFFERREGIONPROC __glewNewBufferRegion = NULL;
+PFNGLREADBUFFERREGIONPROC __glewReadBufferRegion = NULL;
+
+PFNGLRESIZEBUFFERSMESAPROC __glewResizeBuffersMESA = NULL;
+
+PFNGLWINDOWPOS2DMESAPROC __glewWindowPos2dMESA = NULL;
+PFNGLWINDOWPOS2DVMESAPROC __glewWindowPos2dvMESA = NULL;
+PFNGLWINDOWPOS2FMESAPROC __glewWindowPos2fMESA = NULL;
+PFNGLWINDOWPOS2FVMESAPROC __glewWindowPos2fvMESA = NULL;
+PFNGLWINDOWPOS2IMESAPROC __glewWindowPos2iMESA = NULL;
+PFNGLWINDOWPOS2IVMESAPROC __glewWindowPos2ivMESA = NULL;
+PFNGLWINDOWPOS2SMESAPROC __glewWindowPos2sMESA = NULL;
+PFNGLWINDOWPOS2SVMESAPROC __glewWindowPos2svMESA = NULL;
+PFNGLWINDOWPOS3DMESAPROC __glewWindowPos3dMESA = NULL;
+PFNGLWINDOWPOS3DVMESAPROC __glewWindowPos3dvMESA = NULL;
+PFNGLWINDOWPOS3FMESAPROC __glewWindowPos3fMESA = NULL;
+PFNGLWINDOWPOS3FVMESAPROC __glewWindowPos3fvMESA = NULL;
+PFNGLWINDOWPOS3IMESAPROC __glewWindowPos3iMESA = NULL;
+PFNGLWINDOWPOS3IVMESAPROC __glewWindowPos3ivMESA = NULL;
+PFNGLWINDOWPOS3SMESAPROC __glewWindowPos3sMESA = NULL;
+PFNGLWINDOWPOS3SVMESAPROC __glewWindowPos3svMESA = NULL;
+PFNGLWINDOWPOS4DMESAPROC __glewWindowPos4dMESA = NULL;
+PFNGLWINDOWPOS4DVMESAPROC __glewWindowPos4dvMESA = NULL;
+PFNGLWINDOWPOS4FMESAPROC __glewWindowPos4fMESA = NULL;
+PFNGLWINDOWPOS4FVMESAPROC __glewWindowPos4fvMESA = NULL;
+PFNGLWINDOWPOS4IMESAPROC __glewWindowPos4iMESA = NULL;
+PFNGLWINDOWPOS4IVMESAPROC __glewWindowPos4ivMESA = NULL;
+PFNGLWINDOWPOS4SMESAPROC __glewWindowPos4sMESA = NULL;
+PFNGLWINDOWPOS4SVMESAPROC __glewWindowPos4svMESA = NULL;
+
+PFNGLBEGINCONDITIONALRENDERNVXPROC __glewBeginConditionalRenderNVX = NULL;
+PFNGLENDCONDITIONALRENDERNVXPROC __glewEndConditionalRenderNVX = NULL;
+
+PFNGLGETIMAGEHANDLENVPROC __glewGetImageHandleNV = NULL;
+PFNGLGETTEXTUREHANDLENVPROC __glewGetTextureHandleNV = NULL;
+PFNGLGETTEXTURESAMPLERHANDLENVPROC __glewGetTextureSamplerHandleNV = NULL;
+PFNGLISIMAGEHANDLERESIDENTNVPROC __glewIsImageHandleResidentNV = NULL;
+PFNGLISTEXTUREHANDLERESIDENTNVPROC __glewIsTextureHandleResidentNV = NULL;
+PFNGLMAKEIMAGEHANDLENONRESIDENTNVPROC __glewMakeImageHandleNonResidentNV = NULL;
+PFNGLMAKEIMAGEHANDLERESIDENTNVPROC __glewMakeImageHandleResidentNV = NULL;
+PFNGLMAKETEXTUREHANDLENONRESIDENTNVPROC __glewMakeTextureHandleNonResidentNV = NULL;
+PFNGLMAKETEXTUREHANDLERESIDENTNVPROC __glewMakeTextureHandleResidentNV = NULL;
+PFNGLPROGRAMUNIFORMHANDLEUI64NVPROC __glewProgramUniformHandleui64NV = NULL;
+PFNGLPROGRAMUNIFORMHANDLEUI64VNVPROC __glewProgramUniformHandleui64vNV = NULL;
+PFNGLUNIFORMHANDLEUI64NVPROC __glewUniformHandleui64NV = NULL;
+PFNGLUNIFORMHANDLEUI64VNVPROC __glewUniformHandleui64vNV = NULL;
+
+PFNGLBEGINCONDITIONALRENDERNVPROC __glewBeginConditionalRenderNV = NULL;
+PFNGLENDCONDITIONALRENDERNVPROC __glewEndConditionalRenderNV = NULL;
+
+PFNGLCOPYIMAGESUBDATANVPROC __glewCopyImageSubDataNV = NULL;
+
+PFNGLCLEARDEPTHDNVPROC __glewClearDepthdNV = NULL;
+PFNGLDEPTHBOUNDSDNVPROC __glewDepthBoundsdNV = NULL;
+PFNGLDEPTHRANGEDNVPROC __glewDepthRangedNV = NULL;
+
+PFNGLDRAWTEXTURENVPROC __glewDrawTextureNV = NULL;
+
+PFNGLEVALMAPSNVPROC __glewEvalMapsNV = NULL;
+PFNGLGETMAPATTRIBPARAMETERFVNVPROC __glewGetMapAttribParameterfvNV = NULL;
+PFNGLGETMAPATTRIBPARAMETERIVNVPROC __glewGetMapAttribParameterivNV = NULL;
+PFNGLGETMAPCONTROLPOINTSNVPROC __glewGetMapControlPointsNV = NULL;
+PFNGLGETMAPPARAMETERFVNVPROC __glewGetMapParameterfvNV = NULL;
+PFNGLGETMAPPARAMETERIVNVPROC __glewGetMapParameterivNV = NULL;
+PFNGLMAPCONTROLPOINTSNVPROC __glewMapControlPointsNV = NULL;
+PFNGLMAPPARAMETERFVNVPROC __glewMapParameterfvNV = NULL;
+PFNGLMAPPARAMETERIVNVPROC __glewMapParameterivNV = NULL;
+
+PFNGLGETMULTISAMPLEFVNVPROC __glewGetMultisamplefvNV = NULL;
+PFNGLSAMPLEMASKINDEXEDNVPROC __glewSampleMaskIndexedNV = NULL;
+PFNGLTEXRENDERBUFFERNVPROC __glewTexRenderbufferNV = NULL;
+
+PFNGLDELETEFENCESNVPROC __glewDeleteFencesNV = NULL;
+PFNGLFINISHFENCENVPROC __glewFinishFenceNV = NULL;
+PFNGLGENFENCESNVPROC __glewGenFencesNV = NULL;
+PFNGLGETFENCEIVNVPROC __glewGetFenceivNV = NULL;
+PFNGLISFENCENVPROC __glewIsFenceNV = NULL;
+PFNGLSETFENCENVPROC __glewSetFenceNV = NULL;
+PFNGLTESTFENCENVPROC __glewTestFenceNV = NULL;
+
+PFNGLGETPROGRAMNAMEDPARAMETERDVNVPROC __glewGetProgramNamedParameterdvNV = NULL;
+PFNGLGETPROGRAMNAMEDPARAMETERFVNVPROC __glewGetProgramNamedParameterfvNV = NULL;
+PFNGLPROGRAMNAMEDPARAMETER4DNVPROC __glewProgramNamedParameter4dNV = NULL;
+PFNGLPROGRAMNAMEDPARAMETER4DVNVPROC __glewProgramNamedParameter4dvNV = NULL;
+PFNGLPROGRAMNAMEDPARAMETER4FNVPROC __glewProgramNamedParameter4fNV = NULL;
+PFNGLPROGRAMNAMEDPARAMETER4FVNVPROC __glewProgramNamedParameter4fvNV = NULL;
+
+PFNGLRENDERBUFFERSTORAGEMULTISAMPLECOVERAGENVPROC __glewRenderbufferStorageMultisampleCoverageNV = NULL;
+
+PFNGLPROGRAMVERTEXLIMITNVPROC __glewProgramVertexLimitNV = NULL;
+
+PFNGLPROGRAMENVPARAMETERI4INVPROC __glewProgramEnvParameterI4iNV = NULL;
+PFNGLPROGRAMENVPARAMETERI4IVNVPROC __glewProgramEnvParameterI4ivNV = NULL;
+PFNGLPROGRAMENVPARAMETERI4UINVPROC __glewProgramEnvParameterI4uiNV = NULL;
+PFNGLPROGRAMENVPARAMETERI4UIVNVPROC __glewProgramEnvParameterI4uivNV = NULL;
+PFNGLPROGRAMENVPARAMETERSI4IVNVPROC __glewProgramEnvParametersI4ivNV = NULL;
+PFNGLPROGRAMENVPARAMETERSI4UIVNVPROC __glewProgramEnvParametersI4uivNV = NULL;
+PFNGLPROGRAMLOCALPARAMETERI4INVPROC __glewProgramLocalParameterI4iNV = NULL;
+PFNGLPROGRAMLOCALPARAMETERI4IVNVPROC __glewProgramLocalParameterI4ivNV = NULL;
+PFNGLPROGRAMLOCALPARAMETERI4UINVPROC __glewProgramLocalParameterI4uiNV = NULL;
+PFNGLPROGRAMLOCALPARAMETERI4UIVNVPROC __glewProgramLocalParameterI4uivNV = NULL;
+PFNGLPROGRAMLOCALPARAMETERSI4IVNVPROC __glewProgramLocalParametersI4ivNV = NULL;
+PFNGLPROGRAMLOCALPARAMETERSI4UIVNVPROC __glewProgramLocalParametersI4uivNV = NULL;
+
+PFNGLGETUNIFORMI64VNVPROC __glewGetUniformi64vNV = NULL;
+PFNGLGETUNIFORMUI64VNVPROC __glewGetUniformui64vNV = NULL;
+PFNGLPROGRAMUNIFORM1I64NVPROC __glewProgramUniform1i64NV = NULL;
+PFNGLPROGRAMUNIFORM1I64VNVPROC __glewProgramUniform1i64vNV = NULL;
+PFNGLPROGRAMUNIFORM1UI64NVPROC __glewProgramUniform1ui64NV = NULL;
+PFNGLPROGRAMUNIFORM1UI64VNVPROC __glewProgramUniform1ui64vNV = NULL;
+PFNGLPROGRAMUNIFORM2I64NVPROC __glewProgramUniform2i64NV = NULL;
+PFNGLPROGRAMUNIFORM2I64VNVPROC __glewProgramUniform2i64vNV = NULL;
+PFNGLPROGRAMUNIFORM2UI64NVPROC __glewProgramUniform2ui64NV = NULL;
+PFNGLPROGRAMUNIFORM2UI64VNVPROC __glewProgramUniform2ui64vNV = NULL;
+PFNGLPROGRAMUNIFORM3I64NVPROC __glewProgramUniform3i64NV = NULL;
+PFNGLPROGRAMUNIFORM3I64VNVPROC __glewProgramUniform3i64vNV = NULL;
+PFNGLPROGRAMUNIFORM3UI64NVPROC __glewProgramUniform3ui64NV = NULL;
+PFNGLPROGRAMUNIFORM3UI64VNVPROC __glewProgramUniform3ui64vNV = NULL;
+PFNGLPROGRAMUNIFORM4I64NVPROC __glewProgramUniform4i64NV = NULL;
+PFNGLPROGRAMUNIFORM4I64VNVPROC __glewProgramUniform4i64vNV = NULL;
+PFNGLPROGRAMUNIFORM4UI64NVPROC __glewProgramUniform4ui64NV = NULL;
+PFNGLPROGRAMUNIFORM4UI64VNVPROC __glewProgramUniform4ui64vNV = NULL;
+PFNGLUNIFORM1I64NVPROC __glewUniform1i64NV = NULL;
+PFNGLUNIFORM1I64VNVPROC __glewUniform1i64vNV = NULL;
+PFNGLUNIFORM1UI64NVPROC __glewUniform1ui64NV = NULL;
+PFNGLUNIFORM1UI64VNVPROC __glewUniform1ui64vNV = NULL;
+PFNGLUNIFORM2I64NVPROC __glewUniform2i64NV = NULL;
+PFNGLUNIFORM2I64VNVPROC __glewUniform2i64vNV = NULL;
+PFNGLUNIFORM2UI64NVPROC __glewUniform2ui64NV = NULL;
+PFNGLUNIFORM2UI64VNVPROC __glewUniform2ui64vNV = NULL;
+PFNGLUNIFORM3I64NVPROC __glewUniform3i64NV = NULL;
+PFNGLUNIFORM3I64VNVPROC __glewUniform3i64vNV = NULL;
+PFNGLUNIFORM3UI64NVPROC __glewUniform3ui64NV = NULL;
+PFNGLUNIFORM3UI64VNVPROC __glewUniform3ui64vNV = NULL;
+PFNGLUNIFORM4I64NVPROC __glewUniform4i64NV = NULL;
+PFNGLUNIFORM4I64VNVPROC __glewUniform4i64vNV = NULL;
+PFNGLUNIFORM4UI64NVPROC __glewUniform4ui64NV = NULL;
+PFNGLUNIFORM4UI64VNVPROC __glewUniform4ui64vNV = NULL;
+
+PFNGLCOLOR3HNVPROC __glewColor3hNV = NULL;
+PFNGLCOLOR3HVNVPROC __glewColor3hvNV = NULL;
+PFNGLCOLOR4HNVPROC __glewColor4hNV = NULL;
+PFNGLCOLOR4HVNVPROC __glewColor4hvNV = NULL;
+PFNGLFOGCOORDHNVPROC __glewFogCoordhNV = NULL;
+PFNGLFOGCOORDHVNVPROC __glewFogCoordhvNV = NULL;
+PFNGLMULTITEXCOORD1HNVPROC __glewMultiTexCoord1hNV = NULL;
+PFNGLMULTITEXCOORD1HVNVPROC __glewMultiTexCoord1hvNV = NULL;
+PFNGLMULTITEXCOORD2HNVPROC __glewMultiTexCoord2hNV = NULL;
+PFNGLMULTITEXCOORD2HVNVPROC __glewMultiTexCoord2hvNV = NULL;
+PFNGLMULTITEXCOORD3HNVPROC __glewMultiTexCoord3hNV = NULL;
+PFNGLMULTITEXCOORD3HVNVPROC __glewMultiTexCoord3hvNV = NULL;
+PFNGLMULTITEXCOORD4HNVPROC __glewMultiTexCoord4hNV = NULL;
+PFNGLMULTITEXCOORD4HVNVPROC __glewMultiTexCoord4hvNV = NULL;
+PFNGLNORMAL3HNVPROC __glewNormal3hNV = NULL;
+PFNGLNORMAL3HVNVPROC __glewNormal3hvNV = NULL;
+PFNGLSECONDARYCOLOR3HNVPROC __glewSecondaryColor3hNV = NULL;
+PFNGLSECONDARYCOLOR3HVNVPROC __glewSecondaryColor3hvNV = NULL;
+PFNGLTEXCOORD1HNVPROC __glewTexCoord1hNV = NULL;
+PFNGLTEXCOORD1HVNVPROC __glewTexCoord1hvNV = NULL;
+PFNGLTEXCOORD2HNVPROC __glewTexCoord2hNV = NULL;
+PFNGLTEXCOORD2HVNVPROC __glewTexCoord2hvNV = NULL;
+PFNGLTEXCOORD3HNVPROC __glewTexCoord3hNV = NULL;
+PFNGLTEXCOORD3HVNVPROC __glewTexCoord3hvNV = NULL;
+PFNGLTEXCOORD4HNVPROC __glewTexCoord4hNV = NULL;
+PFNGLTEXCOORD4HVNVPROC __glewTexCoord4hvNV = NULL;
+PFNGLVERTEX2HNVPROC __glewVertex2hNV = NULL;
+PFNGLVERTEX2HVNVPROC __glewVertex2hvNV = NULL;
+PFNGLVERTEX3HNVPROC __glewVertex3hNV = NULL;
+PFNGLVERTEX3HVNVPROC __glewVertex3hvNV = NULL;
+PFNGLVERTEX4HNVPROC __glewVertex4hNV = NULL;
+PFNGLVERTEX4HVNVPROC __glewVertex4hvNV = NULL;
+PFNGLVERTEXATTRIB1HNVPROC __glewVertexAttrib1hNV = NULL;
+PFNGLVERTEXATTRIB1HVNVPROC __glewVertexAttrib1hvNV = NULL;
+PFNGLVERTEXATTRIB2HNVPROC __glewVertexAttrib2hNV = NULL;
+PFNGLVERTEXATTRIB2HVNVPROC __glewVertexAttrib2hvNV = NULL;
+PFNGLVERTEXATTRIB3HNVPROC __glewVertexAttrib3hNV = NULL;
+PFNGLVERTEXATTRIB3HVNVPROC __glewVertexAttrib3hvNV = NULL;
+PFNGLVERTEXATTRIB4HNVPROC __glewVertexAttrib4hNV = NULL;
+PFNGLVERTEXATTRIB4HVNVPROC __glewVertexAttrib4hvNV = NULL;
+PFNGLVERTEXATTRIBS1HVNVPROC __glewVertexAttribs1hvNV = NULL;
+PFNGLVERTEXATTRIBS2HVNVPROC __glewVertexAttribs2hvNV = NULL;
+PFNGLVERTEXATTRIBS3HVNVPROC __glewVertexAttribs3hvNV = NULL;
+PFNGLVERTEXATTRIBS4HVNVPROC __glewVertexAttribs4hvNV = NULL;
+PFNGLVERTEXWEIGHTHNVPROC __glewVertexWeighthNV = NULL;
+PFNGLVERTEXWEIGHTHVNVPROC __glewVertexWeighthvNV = NULL;
+
+PFNGLBEGINOCCLUSIONQUERYNVPROC __glewBeginOcclusionQueryNV = NULL;
+PFNGLDELETEOCCLUSIONQUERIESNVPROC __glewDeleteOcclusionQueriesNV = NULL;
+PFNGLENDOCCLUSIONQUERYNVPROC __glewEndOcclusionQueryNV = NULL;
+PFNGLGENOCCLUSIONQUERIESNVPROC __glewGenOcclusionQueriesNV = NULL;
+PFNGLGETOCCLUSIONQUERYIVNVPROC __glewGetOcclusionQueryivNV = NULL;
+PFNGLGETOCCLUSIONQUERYUIVNVPROC __glewGetOcclusionQueryuivNV = NULL;
+PFNGLISOCCLUSIONQUERYNVPROC __glewIsOcclusionQueryNV = NULL;
+
+PFNGLPROGRAMBUFFERPARAMETERSIIVNVPROC __glewProgramBufferParametersIivNV = NULL;
+PFNGLPROGRAMBUFFERPARAMETERSIUIVNVPROC __glewProgramBufferParametersIuivNV = NULL;
+PFNGLPROGRAMBUFFERPARAMETERSFVNVPROC __glewProgramBufferParametersfvNV = NULL;
+
+PFNGLCOPYPATHNVPROC __glewCopyPathNV = NULL;
+PFNGLCOVERFILLPATHINSTANCEDNVPROC __glewCoverFillPathInstancedNV = NULL;
+PFNGLCOVERFILLPATHNVPROC __glewCoverFillPathNV = NULL;
+PFNGLCOVERSTROKEPATHINSTANCEDNVPROC __glewCoverStrokePathInstancedNV = NULL;
+PFNGLCOVERSTROKEPATHNVPROC __glewCoverStrokePathNV = NULL;
+PFNGLDELETEPATHSNVPROC __glewDeletePathsNV = NULL;
+PFNGLGENPATHSNVPROC __glewGenPathsNV = NULL;
+PFNGLGETPATHCOLORGENFVNVPROC __glewGetPathColorGenfvNV = NULL;
+PFNGLGETPATHCOLORGENIVNVPROC __glewGetPathColorGenivNV = NULL;
+PFNGLGETPATHCOMMANDSNVPROC __glewGetPathCommandsNV = NULL;
+PFNGLGETPATHCOORDSNVPROC __glewGetPathCoordsNV = NULL;
+PFNGLGETPATHDASHARRAYNVPROC __glewGetPathDashArrayNV = NULL;
+PFNGLGETPATHLENGTHNVPROC __glewGetPathLengthNV = NULL;
+PFNGLGETPATHMETRICRANGENVPROC __glewGetPathMetricRangeNV = NULL;
+PFNGLGETPATHMETRICSNVPROC __glewGetPathMetricsNV = NULL;
+PFNGLGETPATHPARAMETERFVNVPROC __glewGetPathParameterfvNV = NULL;
+PFNGLGETPATHPARAMETERIVNVPROC __glewGetPathParameterivNV = NULL;
+PFNGLGETPATHSPACINGNVPROC __glewGetPathSpacingNV = NULL;
+PFNGLGETPATHTEXGENFVNVPROC __glewGetPathTexGenfvNV = NULL;
+PFNGLGETPATHTEXGENIVNVPROC __glewGetPathTexGenivNV = NULL;
+PFNGLINTERPOLATEPATHSNVPROC __glewInterpolatePathsNV = NULL;
+PFNGLISPATHNVPROC __glewIsPathNV = NULL;
+PFNGLISPOINTINFILLPATHNVPROC __glewIsPointInFillPathNV = NULL;
+PFNGLISPOINTINSTROKEPATHNVPROC __glewIsPointInStrokePathNV = NULL;
+PFNGLPATHCOLORGENNVPROC __glewPathColorGenNV = NULL;
+PFNGLPATHCOMMANDSNVPROC __glewPathCommandsNV = NULL;
+PFNGLPATHCOORDSNVPROC __glewPathCoordsNV = NULL;
+PFNGLPATHCOVERDEPTHFUNCNVPROC __glewPathCoverDepthFuncNV = NULL;
+PFNGLPATHDASHARRAYNVPROC __glewPathDashArrayNV = NULL;
+PFNGLPATHFOGGENNVPROC __glewPathFogGenNV = NULL;
+PFNGLPATHGLYPHRANGENVPROC __glewPathGlyphRangeNV = NULL;
+PFNGLPATHGLYPHSNVPROC __glewPathGlyphsNV = NULL;
+PFNGLPATHPARAMETERFNVPROC __glewPathParameterfNV = NULL;
+PFNGLPATHPARAMETERFVNVPROC __glewPathParameterfvNV = NULL;
+PFNGLPATHPARAMETERINVPROC __glewPathParameteriNV = NULL;
+PFNGLPATHPARAMETERIVNVPROC __glewPathParameterivNV = NULL;
+PFNGLPATHSTENCILDEPTHOFFSETNVPROC __glewPathStencilDepthOffsetNV = NULL;
+PFNGLPATHSTENCILFUNCNVPROC __glewPathStencilFuncNV = NULL;
+PFNGLPATHSTRINGNVPROC __glewPathStringNV = NULL;
+PFNGLPATHSUBCOMMANDSNVPROC __glewPathSubCommandsNV = NULL;
+PFNGLPATHSUBCOORDSNVPROC __glewPathSubCoordsNV = NULL;
+PFNGLPATHTEXGENNVPROC __glewPathTexGenNV = NULL;
+PFNGLPOINTALONGPATHNVPROC __glewPointAlongPathNV = NULL;
+PFNGLSTENCILFILLPATHINSTANCEDNVPROC __glewStencilFillPathInstancedNV = NULL;
+PFNGLSTENCILFILLPATHNVPROC __glewStencilFillPathNV = NULL;
+PFNGLSTENCILSTROKEPATHINSTANCEDNVPROC __glewStencilStrokePathInstancedNV = NULL;
+PFNGLSTENCILSTROKEPATHNVPROC __glewStencilStrokePathNV = NULL;
+PFNGLTRANSFORMPATHNVPROC __glewTransformPathNV = NULL;
+PFNGLWEIGHTPATHSNVPROC __glewWeightPathsNV = NULL;
+
+PFNGLFLUSHPIXELDATARANGENVPROC __glewFlushPixelDataRangeNV = NULL;
+PFNGLPIXELDATARANGENVPROC __glewPixelDataRangeNV = NULL;
+
+PFNGLPOINTPARAMETERINVPROC __glewPointParameteriNV = NULL;
+PFNGLPOINTPARAMETERIVNVPROC __glewPointParameterivNV = NULL;
+
+PFNGLGETVIDEOI64VNVPROC __glewGetVideoi64vNV = NULL;
+PFNGLGETVIDEOIVNVPROC __glewGetVideoivNV = NULL;
+PFNGLGETVIDEOUI64VNVPROC __glewGetVideoui64vNV = NULL;
+PFNGLGETVIDEOUIVNVPROC __glewGetVideouivNV = NULL;
+PFNGLPRESENTFRAMEDUALFILLNVPROC __glewPresentFrameDualFillNV = NULL;
+PFNGLPRESENTFRAMEKEYEDNVPROC __glewPresentFrameKeyedNV = NULL;
+
+PFNGLPRIMITIVERESTARTINDEXNVPROC __glewPrimitiveRestartIndexNV = NULL;
+PFNGLPRIMITIVERESTARTNVPROC __glewPrimitiveRestartNV = NULL;
+
+PFNGLCOMBINERINPUTNVPROC __glewCombinerInputNV = NULL;
+PFNGLCOMBINEROUTPUTNVPROC __glewCombinerOutputNV = NULL;
+PFNGLCOMBINERPARAMETERFNVPROC __glewCombinerParameterfNV = NULL;
+PFNGLCOMBINERPARAMETERFVNVPROC __glewCombinerParameterfvNV = NULL;
+PFNGLCOMBINERPARAMETERINVPROC __glewCombinerParameteriNV = NULL;
+PFNGLCOMBINERPARAMETERIVNVPROC __glewCombinerParameterivNV = NULL;
+PFNGLFINALCOMBINERINPUTNVPROC __glewFinalCombinerInputNV = NULL;
+PFNGLGETCOMBINERINPUTPARAMETERFVNVPROC __glewGetCombinerInputParameterfvNV = NULL;
+PFNGLGETCOMBINERINPUTPARAMETERIVNVPROC __glewGetCombinerInputParameterivNV = NULL;
+PFNGLGETCOMBINEROUTPUTPARAMETERFVNVPROC __glewGetCombinerOutputParameterfvNV = NULL;
+PFNGLGETCOMBINEROUTPUTPARAMETERIVNVPROC __glewGetCombinerOutputParameterivNV = NULL;
+PFNGLGETFINALCOMBINERINPUTPARAMETERFVNVPROC __glewGetFinalCombinerInputParameterfvNV = NULL;
+PFNGLGETFINALCOMBINERINPUTPARAMETERIVNVPROC __glewGetFinalCombinerInputParameterivNV = NULL;
+
+PFNGLCOMBINERSTAGEPARAMETERFVNVPROC __glewCombinerStageParameterfvNV = NULL;
+PFNGLGETCOMBINERSTAGEPARAMETERFVNVPROC __glewGetCombinerStageParameterfvNV = NULL;
+
+PFNGLGETBUFFERPARAMETERUI64VNVPROC __glewGetBufferParameterui64vNV = NULL;
+PFNGLGETINTEGERUI64VNVPROC __glewGetIntegerui64vNV = NULL;
+PFNGLGETNAMEDBUFFERPARAMETERUI64VNVPROC __glewGetNamedBufferParameterui64vNV = NULL;
+PFNGLISBUFFERRESIDENTNVPROC __glewIsBufferResidentNV = NULL;
+PFNGLISNAMEDBUFFERRESIDENTNVPROC __glewIsNamedBufferResidentNV = NULL;
+PFNGLMAKEBUFFERNONRESIDENTNVPROC __glewMakeBufferNonResidentNV = NULL;
+PFNGLMAKEBUFFERRESIDENTNVPROC __glewMakeBufferResidentNV = NULL;
+PFNGLMAKENAMEDBUFFERNONRESIDENTNVPROC __glewMakeNamedBufferNonResidentNV = NULL;
+PFNGLMAKENAMEDBUFFERRESIDENTNVPROC __glewMakeNamedBufferResidentNV = NULL;
+PFNGLPROGRAMUNIFORMUI64NVPROC __glewProgramUniformui64NV = NULL;
+PFNGLPROGRAMUNIFORMUI64VNVPROC __glewProgramUniformui64vNV = NULL;
+PFNGLUNIFORMUI64NVPROC __glewUniformui64NV = NULL;
+PFNGLUNIFORMUI64VNVPROC __glewUniformui64vNV = NULL;
+
+PFNGLTEXTUREBARRIERNVPROC __glewTextureBarrierNV = NULL;
+
+PFNGLTEXIMAGE2DMULTISAMPLECOVERAGENVPROC __glewTexImage2DMultisampleCoverageNV = NULL;
+PFNGLTEXIMAGE3DMULTISAMPLECOVERAGENVPROC __glewTexImage3DMultisampleCoverageNV = NULL;
+PFNGLTEXTUREIMAGE2DMULTISAMPLECOVERAGENVPROC __glewTextureImage2DMultisampleCoverageNV = NULL;
+PFNGLTEXTUREIMAGE2DMULTISAMPLENVPROC __glewTextureImage2DMultisampleNV = NULL;
+PFNGLTEXTUREIMAGE3DMULTISAMPLECOVERAGENVPROC __glewTextureImage3DMultisampleCoverageNV = NULL;
+PFNGLTEXTUREIMAGE3DMULTISAMPLENVPROC __glewTextureImage3DMultisampleNV = NULL;
+
+PFNGLACTIVEVARYINGNVPROC __glewActiveVaryingNV = NULL;
+PFNGLBEGINTRANSFORMFEEDBACKNVPROC __glewBeginTransformFeedbackNV = NULL;
+PFNGLBINDBUFFERBASENVPROC __glewBindBufferBaseNV = NULL;
+PFNGLBINDBUFFEROFFSETNVPROC __glewBindBufferOffsetNV = NULL;
+PFNGLBINDBUFFERRANGENVPROC __glewBindBufferRangeNV = NULL;
+PFNGLENDTRANSFORMFEEDBACKNVPROC __glewEndTransformFeedbackNV = NULL;
+PFNGLGETACTIVEVARYINGNVPROC __glewGetActiveVaryingNV = NULL;
+PFNGLGETTRANSFORMFEEDBACKVARYINGNVPROC __glewGetTransformFeedbackVaryingNV = NULL;
+PFNGLGETVARYINGLOCATIONNVPROC __glewGetVaryingLocationNV = NULL;
+PFNGLTRANSFORMFEEDBACKATTRIBSNVPROC __glewTransformFeedbackAttribsNV = NULL;
+PFNGLTRANSFORMFEEDBACKVARYINGSNVPROC __glewTransformFeedbackVaryingsNV = NULL;
+
+PFNGLBINDTRANSFORMFEEDBACKNVPROC __glewBindTransformFeedbackNV = NULL;
+PFNGLDELETETRANSFORMFEEDBACKSNVPROC __glewDeleteTransformFeedbacksNV = NULL;
+PFNGLDRAWTRANSFORMFEEDBACKNVPROC __glewDrawTransformFeedbackNV = NULL;
+PFNGLGENTRANSFORMFEEDBACKSNVPROC __glewGenTransformFeedbacksNV = NULL;
+PFNGLISTRANSFORMFEEDBACKNVPROC __glewIsTransformFeedbackNV = NULL;
+PFNGLPAUSETRANSFORMFEEDBACKNVPROC __glewPauseTransformFeedbackNV = NULL;
+PFNGLRESUMETRANSFORMFEEDBACKNVPROC __glewResumeTransformFeedbackNV = NULL;
+
+PFNGLVDPAUFININVPROC __glewVDPAUFiniNV = NULL;
+PFNGLVDPAUGETSURFACEIVNVPROC __glewVDPAUGetSurfaceivNV = NULL;
+PFNGLVDPAUINITNVPROC __glewVDPAUInitNV = NULL;
+PFNGLVDPAUISSURFACENVPROC __glewVDPAUIsSurfaceNV = NULL;
+PFNGLVDPAUMAPSURFACESNVPROC __glewVDPAUMapSurfacesNV = NULL;
+PFNGLVDPAUREGISTEROUTPUTSURFACENVPROC __glewVDPAURegisterOutputSurfaceNV = NULL;
+PFNGLVDPAUREGISTERVIDEOSURFACENVPROC __glewVDPAURegisterVideoSurfaceNV = NULL;
+PFNGLVDPAUSURFACEACCESSNVPROC __glewVDPAUSurfaceAccessNV = NULL;
+PFNGLVDPAUUNMAPSURFACESNVPROC __glewVDPAUUnmapSurfacesNV = NULL;
+PFNGLVDPAUUNREGISTERSURFACENVPROC __glewVDPAUUnregisterSurfaceNV = NULL;
+
+PFNGLFLUSHVERTEXARRAYRANGENVPROC __glewFlushVertexArrayRangeNV = NULL;
+PFNGLVERTEXARRAYRANGENVPROC __glewVertexArrayRangeNV = NULL;
+
+PFNGLGETVERTEXATTRIBLI64VNVPROC __glewGetVertexAttribLi64vNV = NULL;
+PFNGLGETVERTEXATTRIBLUI64VNVPROC __glewGetVertexAttribLui64vNV = NULL;
+PFNGLVERTEXATTRIBL1I64NVPROC __glewVertexAttribL1i64NV = NULL;
+PFNGLVERTEXATTRIBL1I64VNVPROC __glewVertexAttribL1i64vNV = NULL;
+PFNGLVERTEXATTRIBL1UI64NVPROC __glewVertexAttribL1ui64NV = NULL;
+PFNGLVERTEXATTRIBL1UI64VNVPROC __glewVertexAttribL1ui64vNV = NULL;
+PFNGLVERTEXATTRIBL2I64NVPROC __glewVertexAttribL2i64NV = NULL;
+PFNGLVERTEXATTRIBL2I64VNVPROC __glewVertexAttribL2i64vNV = NULL;
+PFNGLVERTEXATTRIBL2UI64NVPROC __glewVertexAttribL2ui64NV = NULL;
+PFNGLVERTEXATTRIBL2UI64VNVPROC __glewVertexAttribL2ui64vNV = NULL;
+PFNGLVERTEXATTRIBL3I64NVPROC __glewVertexAttribL3i64NV = NULL;
+PFNGLVERTEXATTRIBL3I64VNVPROC __glewVertexAttribL3i64vNV = NULL;
+PFNGLVERTEXATTRIBL3UI64NVPROC __glewVertexAttribL3ui64NV = NULL;
+PFNGLVERTEXATTRIBL3UI64VNVPROC __glewVertexAttribL3ui64vNV = NULL;
+PFNGLVERTEXATTRIBL4I64NVPROC __glewVertexAttribL4i64NV = NULL;
+PFNGLVERTEXATTRIBL4I64VNVPROC __glewVertexAttribL4i64vNV = NULL;
+PFNGLVERTEXATTRIBL4UI64NVPROC __glewVertexAttribL4ui64NV = NULL;
+PFNGLVERTEXATTRIBL4UI64VNVPROC __glewVertexAttribL4ui64vNV = NULL;
+PFNGLVERTEXATTRIBLFORMATNVPROC __glewVertexAttribLFormatNV = NULL;
+
+PFNGLBUFFERADDRESSRANGENVPROC __glewBufferAddressRangeNV = NULL;
+PFNGLCOLORFORMATNVPROC __glewColorFormatNV = NULL;
+PFNGLEDGEFLAGFORMATNVPROC __glewEdgeFlagFormatNV = NULL;
+PFNGLFOGCOORDFORMATNVPROC __glewFogCoordFormatNV = NULL;
+PFNGLGETINTEGERUI64I_VNVPROC __glewGetIntegerui64i_vNV = NULL;
+PFNGLINDEXFORMATNVPROC __glewIndexFormatNV = NULL;
+PFNGLNORMALFORMATNVPROC __glewNormalFormatNV = NULL;
+PFNGLSECONDARYCOLORFORMATNVPROC __glewSecondaryColorFormatNV = NULL;
+PFNGLTEXCOORDFORMATNVPROC __glewTexCoordFormatNV = NULL;
+PFNGLVERTEXATTRIBFORMATNVPROC __glewVertexAttribFormatNV = NULL;
+PFNGLVERTEXATTRIBIFORMATNVPROC __glewVertexAttribIFormatNV = NULL;
+PFNGLVERTEXFORMATNVPROC __glewVertexFormatNV = NULL;
+
+PFNGLAREPROGRAMSRESIDENTNVPROC __glewAreProgramsResidentNV = NULL;
+PFNGLBINDPROGRAMNVPROC __glewBindProgramNV = NULL;
+PFNGLDELETEPROGRAMSNVPROC __glewDeleteProgramsNV = NULL;
+PFNGLEXECUTEPROGRAMNVPROC __glewExecuteProgramNV = NULL;
+PFNGLGENPROGRAMSNVPROC __glewGenProgramsNV = NULL;
+PFNGLGETPROGRAMPARAMETERDVNVPROC __glewGetProgramParameterdvNV = NULL;
+PFNGLGETPROGRAMPARAMETERFVNVPROC __glewGetProgramParameterfvNV = NULL;
+PFNGLGETPROGRAMSTRINGNVPROC __glewGetProgramStringNV = NULL;
+PFNGLGETPROGRAMIVNVPROC __glewGetProgramivNV = NULL;
+PFNGLGETTRACKMATRIXIVNVPROC __glewGetTrackMatrixivNV = NULL;
+PFNGLGETVERTEXATTRIBPOINTERVNVPROC __glewGetVertexAttribPointervNV = NULL;
+PFNGLGETVERTEXATTRIBDVNVPROC __glewGetVertexAttribdvNV = NULL;
+PFNGLGETVERTEXATTRIBFVNVPROC __glewGetVertexAttribfvNV = NULL;
+PFNGLGETVERTEXATTRIBIVNVPROC __glewGetVertexAttribivNV = NULL;
+PFNGLISPROGRAMNVPROC __glewIsProgramNV = NULL;
+PFNGLLOADPROGRAMNVPROC __glewLoadProgramNV = NULL;
+PFNGLPROGRAMPARAMETER4DNVPROC __glewProgramParameter4dNV = NULL;
+PFNGLPROGRAMPARAMETER4DVNVPROC __glewProgramParameter4dvNV = NULL;
+PFNGLPROGRAMPARAMETER4FNVPROC __glewProgramParameter4fNV = NULL;
+PFNGLPROGRAMPARAMETER4FVNVPROC __glewProgramParameter4fvNV = NULL;
+PFNGLPROGRAMPARAMETERS4DVNVPROC __glewProgramParameters4dvNV = NULL;
+PFNGLPROGRAMPARAMETERS4FVNVPROC __glewProgramParameters4fvNV = NULL;
+PFNGLREQUESTRESIDENTPROGRAMSNVPROC __glewRequestResidentProgramsNV = NULL;
+PFNGLTRACKMATRIXNVPROC __glewTrackMatrixNV = NULL;
+PFNGLVERTEXATTRIB1DNVPROC __glewVertexAttrib1dNV = NULL;
+PFNGLVERTEXATTRIB1DVNVPROC __glewVertexAttrib1dvNV = NULL;
+PFNGLVERTEXATTRIB1FNVPROC __glewVertexAttrib1fNV = NULL;
+PFNGLVERTEXATTRIB1FVNVPROC __glewVertexAttrib1fvNV = NULL;
+PFNGLVERTEXATTRIB1SNVPROC __glewVertexAttrib1sNV = NULL;
+PFNGLVERTEXATTRIB1SVNVPROC __glewVertexAttrib1svNV = NULL;
+PFNGLVERTEXATTRIB2DNVPROC __glewVertexAttrib2dNV = NULL;
+PFNGLVERTEXATTRIB2DVNVPROC __glewVertexAttrib2dvNV = NULL;
+PFNGLVERTEXATTRIB2FNVPROC __glewVertexAttrib2fNV = NULL;
+PFNGLVERTEXATTRIB2FVNVPROC __glewVertexAttrib2fvNV = NULL;
+PFNGLVERTEXATTRIB2SNVPROC __glewVertexAttrib2sNV = NULL;
+PFNGLVERTEXATTRIB2SVNVPROC __glewVertexAttrib2svNV = NULL;
+PFNGLVERTEXATTRIB3DNVPROC __glewVertexAttrib3dNV = NULL;
+PFNGLVERTEXATTRIB3DVNVPROC __glewVertexAttrib3dvNV = NULL;
+PFNGLVERTEXATTRIB3FNVPROC __glewVertexAttrib3fNV = NULL;
+PFNGLVERTEXATTRIB3FVNVPROC __glewVertexAttrib3fvNV = NULL;
+PFNGLVERTEXATTRIB3SNVPROC __glewVertexAttrib3sNV = NULL;
+PFNGLVERTEXATTRIB3SVNVPROC __glewVertexAttrib3svNV = NULL;
+PFNGLVERTEXATTRIB4DNVPROC __glewVertexAttrib4dNV = NULL;
+PFNGLVERTEXATTRIB4DVNVPROC __glewVertexAttrib4dvNV = NULL;
+PFNGLVERTEXATTRIB4FNVPROC __glewVertexAttrib4fNV = NULL;
+PFNGLVERTEXATTRIB4FVNVPROC __glewVertexAttrib4fvNV = NULL;
+PFNGLVERTEXATTRIB4SNVPROC __glewVertexAttrib4sNV = NULL;
+PFNGLVERTEXATTRIB4SVNVPROC __glewVertexAttrib4svNV = NULL;
+PFNGLVERTEXATTRIB4UBNVPROC __glewVertexAttrib4ubNV = NULL;
+PFNGLVERTEXATTRIB4UBVNVPROC __glewVertexAttrib4ubvNV = NULL;
+PFNGLVERTEXATTRIBPOINTERNVPROC __glewVertexAttribPointerNV = NULL;
+PFNGLVERTEXATTRIBS1DVNVPROC __glewVertexAttribs1dvNV = NULL;
+PFNGLVERTEXATTRIBS1FVNVPROC __glewVertexAttribs1fvNV = NULL;
+PFNGLVERTEXATTRIBS1SVNVPROC __glewVertexAttribs1svNV = NULL;
+PFNGLVERTEXATTRIBS2DVNVPROC __glewVertexAttribs2dvNV = NULL;
+PFNGLVERTEXATTRIBS2FVNVPROC __glewVertexAttribs2fvNV = NULL;
+PFNGLVERTEXATTRIBS2SVNVPROC __glewVertexAttribs2svNV = NULL;
+PFNGLVERTEXATTRIBS3DVNVPROC __glewVertexAttribs3dvNV = NULL;
+PFNGLVERTEXATTRIBS3FVNVPROC __glewVertexAttribs3fvNV = NULL;
+PFNGLVERTEXATTRIBS3SVNVPROC __glewVertexAttribs3svNV = NULL;
+PFNGLVERTEXATTRIBS4DVNVPROC __glewVertexAttribs4dvNV = NULL;
+PFNGLVERTEXATTRIBS4FVNVPROC __glewVertexAttribs4fvNV = NULL;
+PFNGLVERTEXATTRIBS4SVNVPROC __glewVertexAttribs4svNV = NULL;
+PFNGLVERTEXATTRIBS4UBVNVPROC __glewVertexAttribs4ubvNV = NULL;
+
+PFNGLBEGINVIDEOCAPTURENVPROC __glewBeginVideoCaptureNV = NULL;
+PFNGLBINDVIDEOCAPTURESTREAMBUFFERNVPROC __glewBindVideoCaptureStreamBufferNV = NULL;
+PFNGLBINDVIDEOCAPTURESTREAMTEXTURENVPROC __glewBindVideoCaptureStreamTextureNV = NULL;
+PFNGLENDVIDEOCAPTURENVPROC __glewEndVideoCaptureNV = NULL;
+PFNGLGETVIDEOCAPTURESTREAMDVNVPROC __glewGetVideoCaptureStreamdvNV = NULL;
+PFNGLGETVIDEOCAPTURESTREAMFVNVPROC __glewGetVideoCaptureStreamfvNV = NULL;
+PFNGLGETVIDEOCAPTURESTREAMIVNVPROC __glewGetVideoCaptureStreamivNV = NULL;
+PFNGLGETVIDEOCAPTUREIVNVPROC __glewGetVideoCaptureivNV = NULL;
+PFNGLVIDEOCAPTURENVPROC __glewVideoCaptureNV = NULL;
+PFNGLVIDEOCAPTURESTREAMPARAMETERDVNVPROC __glewVideoCaptureStreamParameterdvNV = NULL;
+PFNGLVIDEOCAPTURESTREAMPARAMETERFVNVPROC __glewVideoCaptureStreamParameterfvNV = NULL;
+PFNGLVIDEOCAPTURESTREAMPARAMETERIVNVPROC __glewVideoCaptureStreamParameterivNV = NULL;
+
+PFNGLCLEARDEPTHFOESPROC __glewClearDepthfOES = NULL;
+PFNGLCLIPPLANEFOESPROC __glewClipPlanefOES = NULL;
+PFNGLDEPTHRANGEFOESPROC __glewDepthRangefOES = NULL;
+PFNGLFRUSTUMFOESPROC __glewFrustumfOES = NULL;
+PFNGLGETCLIPPLANEFOESPROC __glewGetClipPlanefOES = NULL;
+PFNGLORTHOFOESPROC __glewOrthofOES = NULL;
+
+PFNGLDETAILTEXFUNCSGISPROC __glewDetailTexFuncSGIS = NULL;
+PFNGLGETDETAILTEXFUNCSGISPROC __glewGetDetailTexFuncSGIS = NULL;
+
+PFNGLFOGFUNCSGISPROC __glewFogFuncSGIS = NULL;
+PFNGLGETFOGFUNCSGISPROC __glewGetFogFuncSGIS = NULL;
+
+PFNGLSAMPLEMASKSGISPROC __glewSampleMaskSGIS = NULL;
+PFNGLSAMPLEPATTERNSGISPROC __glewSamplePatternSGIS = NULL;
+
+PFNGLGETSHARPENTEXFUNCSGISPROC __glewGetSharpenTexFuncSGIS = NULL;
+PFNGLSHARPENTEXFUNCSGISPROC __glewSharpenTexFuncSGIS = NULL;
+
+PFNGLTEXIMAGE4DSGISPROC __glewTexImage4DSGIS = NULL;
+PFNGLTEXSUBIMAGE4DSGISPROC __glewTexSubImage4DSGIS = NULL;
+
+PFNGLGETTEXFILTERFUNCSGISPROC __glewGetTexFilterFuncSGIS = NULL;
+PFNGLTEXFILTERFUNCSGISPROC __glewTexFilterFuncSGIS = NULL;
+
+PFNGLASYNCMARKERSGIXPROC __glewAsyncMarkerSGIX = NULL;
+PFNGLDELETEASYNCMARKERSSGIXPROC __glewDeleteAsyncMarkersSGIX = NULL;
+PFNGLFINISHASYNCSGIXPROC __glewFinishAsyncSGIX = NULL;
+PFNGLGENASYNCMARKERSSGIXPROC __glewGenAsyncMarkersSGIX = NULL;
+PFNGLISASYNCMARKERSGIXPROC __glewIsAsyncMarkerSGIX = NULL;
+PFNGLPOLLASYNCSGIXPROC __glewPollAsyncSGIX = NULL;
+
+PFNGLFLUSHRASTERSGIXPROC __glewFlushRasterSGIX = NULL;
+
+PFNGLTEXTUREFOGSGIXPROC __glewTextureFogSGIX = NULL;
+
+PFNGLFRAGMENTCOLORMATERIALSGIXPROC __glewFragmentColorMaterialSGIX = NULL;
+PFNGLFRAGMENTLIGHTMODELFSGIXPROC __glewFragmentLightModelfSGIX = NULL;
+PFNGLFRAGMENTLIGHTMODELFVSGIXPROC __glewFragmentLightModelfvSGIX = NULL;
+PFNGLFRAGMENTLIGHTMODELISGIXPROC __glewFragmentLightModeliSGIX = NULL;
+PFNGLFRAGMENTLIGHTMODELIVSGIXPROC __glewFragmentLightModelivSGIX = NULL;
+PFNGLFRAGMENTLIGHTFSGIXPROC __glewFragmentLightfSGIX = NULL;
+PFNGLFRAGMENTLIGHTFVSGIXPROC __glewFragmentLightfvSGIX = NULL;
+PFNGLFRAGMENTLIGHTISGIXPROC __glewFragmentLightiSGIX = NULL;
+PFNGLFRAGMENTLIGHTIVSGIXPROC __glewFragmentLightivSGIX = NULL;
+PFNGLFRAGMENTMATERIALFSGIXPROC __glewFragmentMaterialfSGIX = NULL;
+PFNGLFRAGMENTMATERIALFVSGIXPROC __glewFragmentMaterialfvSGIX = NULL;
+PFNGLFRAGMENTMATERIALISGIXPROC __glewFragmentMaterialiSGIX = NULL;
+PFNGLFRAGMENTMATERIALIVSGIXPROC __glewFragmentMaterialivSGIX = NULL;
+PFNGLGETFRAGMENTLIGHTFVSGIXPROC __glewGetFragmentLightfvSGIX = NULL;
+PFNGLGETFRAGMENTLIGHTIVSGIXPROC __glewGetFragmentLightivSGIX = NULL;
+PFNGLGETFRAGMENTMATERIALFVSGIXPROC __glewGetFragmentMaterialfvSGIX = NULL;
+PFNGLGETFRAGMENTMATERIALIVSGIXPROC __glewGetFragmentMaterialivSGIX = NULL;
+
+PFNGLFRAMEZOOMSGIXPROC __glewFrameZoomSGIX = NULL;
+
+PFNGLPIXELTEXGENSGIXPROC __glewPixelTexGenSGIX = NULL;
+
+PFNGLREFERENCEPLANESGIXPROC __glewReferencePlaneSGIX = NULL;
+
+PFNGLSPRITEPARAMETERFSGIXPROC __glewSpriteParameterfSGIX = NULL;
+PFNGLSPRITEPARAMETERFVSGIXPROC __glewSpriteParameterfvSGIX = NULL;
+PFNGLSPRITEPARAMETERISGIXPROC __glewSpriteParameteriSGIX = NULL;
+PFNGLSPRITEPARAMETERIVSGIXPROC __glewSpriteParameterivSGIX = NULL;
+
+PFNGLTAGSAMPLEBUFFERSGIXPROC __glewTagSampleBufferSGIX = NULL;
+
+PFNGLCOLORTABLEPARAMETERFVSGIPROC __glewColorTableParameterfvSGI = NULL;
+PFNGLCOLORTABLEPARAMETERIVSGIPROC __glewColorTableParameterivSGI = NULL;
+PFNGLCOLORTABLESGIPROC __glewColorTableSGI = NULL;
+PFNGLCOPYCOLORTABLESGIPROC __glewCopyColorTableSGI = NULL;
+PFNGLGETCOLORTABLEPARAMETERFVSGIPROC __glewGetColorTableParameterfvSGI = NULL;
+PFNGLGETCOLORTABLEPARAMETERIVSGIPROC __glewGetColorTableParameterivSGI = NULL;
+PFNGLGETCOLORTABLESGIPROC __glewGetColorTableSGI = NULL;
+
+PFNGLFINISHTEXTURESUNXPROC __glewFinishTextureSUNX = NULL;
+
+PFNGLGLOBALALPHAFACTORBSUNPROC __glewGlobalAlphaFactorbSUN = NULL;
+PFNGLGLOBALALPHAFACTORDSUNPROC __glewGlobalAlphaFactordSUN = NULL;
+PFNGLGLOBALALPHAFACTORFSUNPROC __glewGlobalAlphaFactorfSUN = NULL;
+PFNGLGLOBALALPHAFACTORISUNPROC __glewGlobalAlphaFactoriSUN = NULL;
+PFNGLGLOBALALPHAFACTORSSUNPROC __glewGlobalAlphaFactorsSUN = NULL;
+PFNGLGLOBALALPHAFACTORUBSUNPROC __glewGlobalAlphaFactorubSUN = NULL;
+PFNGLGLOBALALPHAFACTORUISUNPROC __glewGlobalAlphaFactoruiSUN = NULL;
+PFNGLGLOBALALPHAFACTORUSSUNPROC __glewGlobalAlphaFactorusSUN = NULL;
+
+PFNGLREADVIDEOPIXELSSUNPROC __glewReadVideoPixelsSUN = NULL;
+
+PFNGLREPLACEMENTCODEPOINTERSUNPROC __glewReplacementCodePointerSUN = NULL;
+PFNGLREPLACEMENTCODEUBSUNPROC __glewReplacementCodeubSUN = NULL;
+PFNGLREPLACEMENTCODEUBVSUNPROC __glewReplacementCodeubvSUN = NULL;
+PFNGLREPLACEMENTCODEUISUNPROC __glewReplacementCodeuiSUN = NULL;
+PFNGLREPLACEMENTCODEUIVSUNPROC __glewReplacementCodeuivSUN = NULL;
+PFNGLREPLACEMENTCODEUSSUNPROC __glewReplacementCodeusSUN = NULL;
+PFNGLREPLACEMENTCODEUSVSUNPROC __glewReplacementCodeusvSUN = NULL;
+
+PFNGLCOLOR3FVERTEX3FSUNPROC __glewColor3fVertex3fSUN = NULL;
+PFNGLCOLOR3FVERTEX3FVSUNPROC __glewColor3fVertex3fvSUN = NULL;
+PFNGLCOLOR4FNORMAL3FVERTEX3FSUNPROC __glewColor4fNormal3fVertex3fSUN = NULL;
+PFNGLCOLOR4FNORMAL3FVERTEX3FVSUNPROC __glewColor4fNormal3fVertex3fvSUN = NULL;
+PFNGLCOLOR4UBVERTEX2FSUNPROC __glewColor4ubVertex2fSUN = NULL;
+PFNGLCOLOR4UBVERTEX2FVSUNPROC __glewColor4ubVertex2fvSUN = NULL;
+PFNGLCOLOR4UBVERTEX3FSUNPROC __glewColor4ubVertex3fSUN = NULL;
+PFNGLCOLOR4UBVERTEX3FVSUNPROC __glewColor4ubVertex3fvSUN = NULL;
+PFNGLNORMAL3FVERTEX3FSUNPROC __glewNormal3fVertex3fSUN = NULL;
+PFNGLNORMAL3FVERTEX3FVSUNPROC __glewNormal3fVertex3fvSUN = NULL;
+PFNGLREPLACEMENTCODEUICOLOR3FVERTEX3FSUNPROC __glewReplacementCodeuiColor3fVertex3fSUN = NULL;
+PFNGLREPLACEMENTCODEUICOLOR3FVERTEX3FVSUNPROC __glewReplacementCodeuiColor3fVertex3fvSUN = NULL;
+PFNGLREPLACEMENTCODEUICOLOR4FNORMAL3FVERTEX3FSUNPROC __glewReplacementCodeuiColor4fNormal3fVertex3fSUN = NULL;
+PFNGLREPLACEMENTCODEUICOLOR4FNORMAL3FVERTEX3FVSUNPROC __glewReplacementCodeuiColor4fNormal3fVertex3fvSUN = NULL;
+PFNGLREPLACEMENTCODEUICOLOR4UBVERTEX3FSUNPROC __glewReplacementCodeuiColor4ubVertex3fSUN = NULL;
+PFNGLREPLACEMENTCODEUICOLOR4UBVERTEX3FVSUNPROC __glewReplacementCodeuiColor4ubVertex3fvSUN = NULL;
+PFNGLREPLACEMENTCODEUINORMAL3FVERTEX3FSUNPROC __glewReplacementCodeuiNormal3fVertex3fSUN = NULL;
+PFNGLREPLACEMENTCODEUINORMAL3FVERTEX3FVSUNPROC __glewReplacementCodeuiNormal3fVertex3fvSUN = NULL;
+PFNGLREPLACEMENTCODEUITEXCOORD2FCOLOR4FNORMAL3FVERTEX3FSUNPROC __glewReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fSUN = NULL;
+PFNGLREPLACEMENTCODEUITEXCOORD2FCOLOR4FNORMAL3FVERTEX3FVSUNPROC __glewReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fvSUN = NULL;
+PFNGLREPLACEMENTCODEUITEXCOORD2FNORMAL3FVERTEX3FSUNPROC __glewReplacementCodeuiTexCoord2fNormal3fVertex3fSUN = NULL;
+PFNGLREPLACEMENTCODEUITEXCOORD2FNORMAL3FVERTEX3FVSUNPROC __glewReplacementCodeuiTexCoord2fNormal3fVertex3fvSUN = NULL;
+PFNGLREPLACEMENTCODEUITEXCOORD2FVERTEX3FSUNPROC __glewReplacementCodeuiTexCoord2fVertex3fSUN = NULL;
+PFNGLREPLACEMENTCODEUITEXCOORD2FVERTEX3FVSUNPROC __glewReplacementCodeuiTexCoord2fVertex3fvSUN = NULL;
+PFNGLREPLACEMENTCODEUIVERTEX3FSUNPROC __glewReplacementCodeuiVertex3fSUN = NULL;
+PFNGLREPLACEMENTCODEUIVERTEX3FVSUNPROC __glewReplacementCodeuiVertex3fvSUN = NULL;
+PFNGLTEXCOORD2FCOLOR3FVERTEX3FSUNPROC __glewTexCoord2fColor3fVertex3fSUN = NULL;
+PFNGLTEXCOORD2FCOLOR3FVERTEX3FVSUNPROC __glewTexCoord2fColor3fVertex3fvSUN = NULL;
+PFNGLTEXCOORD2FCOLOR4FNORMAL3FVERTEX3FSUNPROC __glewTexCoord2fColor4fNormal3fVertex3fSUN = NULL;
+PFNGLTEXCOORD2FCOLOR4FNORMAL3FVERTEX3FVSUNPROC __glewTexCoord2fColor4fNormal3fVertex3fvSUN = NULL;
+PFNGLTEXCOORD2FCOLOR4UBVERTEX3FSUNPROC __glewTexCoord2fColor4ubVertex3fSUN = NULL;
+PFNGLTEXCOORD2FCOLOR4UBVERTEX3FVSUNPROC __glewTexCoord2fColor4ubVertex3fvSUN = NULL;
+PFNGLTEXCOORD2FNORMAL3FVERTEX3FSUNPROC __glewTexCoord2fNormal3fVertex3fSUN = NULL;
+PFNGLTEXCOORD2FNORMAL3FVERTEX3FVSUNPROC __glewTexCoord2fNormal3fVertex3fvSUN = NULL;
+PFNGLTEXCOORD2FVERTEX3FSUNPROC __glewTexCoord2fVertex3fSUN = NULL;
+PFNGLTEXCOORD2FVERTEX3FVSUNPROC __glewTexCoord2fVertex3fvSUN = NULL;
+PFNGLTEXCOORD4FCOLOR4FNORMAL3FVERTEX4FSUNPROC __glewTexCoord4fColor4fNormal3fVertex4fSUN = NULL;
+PFNGLTEXCOORD4FCOLOR4FNORMAL3FVERTEX4FVSUNPROC __glewTexCoord4fColor4fNormal3fVertex4fvSUN = NULL;
+PFNGLTEXCOORD4FVERTEX4FSUNPROC __glewTexCoord4fVertex4fSUN = NULL;
+PFNGLTEXCOORD4FVERTEX4FVSUNPROC __glewTexCoord4fVertex4fvSUN = NULL;
+
+PFNGLADDSWAPHINTRECTWINPROC __glewAddSwapHintRectWIN = NULL;
+
+#if !defined(GLEW_NO_ES)
+
+PFNGLALPHAFUNCXPROC __glewAlphaFuncx = NULL;
+PFNGLCLEARCOLORXPROC __glewClearColorx = NULL;
+PFNGLCLEARDEPTHXPROC __glewClearDepthx = NULL;
+PFNGLCOLOR4XPROC __glewColor4x = NULL;
+PFNGLDEPTHRANGEXPROC __glewDepthRangex = NULL;
+PFNGLFOGXPROC __glewFogx = NULL;
+PFNGLFOGXVPROC __glewFogxv = NULL;
+PFNGLFRUSTUMFPROC __glewFrustumf = NULL;
+PFNGLFRUSTUMXPROC __glewFrustumx = NULL;
+PFNGLLIGHTMODELXPROC __glewLightModelx = NULL;
+PFNGLLIGHTMODELXVPROC __glewLightModelxv = NULL;
+PFNGLLIGHTXPROC __glewLightx = NULL;
+PFNGLLIGHTXVPROC __glewLightxv = NULL;
+PFNGLLINEWIDTHXPROC __glewLineWidthx = NULL;
+PFNGLLOADMATRIXXPROC __glewLoadMatrixx = NULL;
+PFNGLMATERIALXPROC __glewMaterialx = NULL;
+PFNGLMATERIALXVPROC __glewMaterialxv = NULL;
+PFNGLMULTMATRIXXPROC __glewMultMatrixx = NULL;
+PFNGLMULTITEXCOORD4XPROC __glewMultiTexCoord4x = NULL;
+PFNGLNORMAL3XPROC __glewNormal3x = NULL;
+PFNGLORTHOFPROC __glewOrthof = NULL;
+PFNGLORTHOXPROC __glewOrthox = NULL;
+PFNGLPOINTSIZEXPROC __glewPointSizex = NULL;
+PFNGLPOLYGONOFFSETXPROC __glewPolygonOffsetx = NULL;
+PFNGLROTATEXPROC __glewRotatex = NULL;
+PFNGLSAMPLECOVERAGEXPROC __glewSampleCoveragex = NULL;
+PFNGLSCALEXPROC __glewScalex = NULL;
+PFNGLTEXENVXPROC __glewTexEnvx = NULL;
+PFNGLTEXENVXVPROC __glewTexEnvxv = NULL;
+PFNGLTEXPARAMETERXPROC __glewTexParameterx = NULL;
+PFNGLTRANSLATEXPROC __glewTranslatex = NULL;
+
+PFNGLCLIPPLANEXPROC __glewClipPlanex = NULL;
+PFNGLGETCLIPPLANEXPROC __glewGetClipPlanex = NULL;
+PFNGLGETFIXEDVPROC __glewGetFixedv = NULL;
+PFNGLGETLIGHTXVPROC __glewGetLightxv = NULL;
+PFNGLGETMATERIALXVPROC __glewGetMaterialxv = NULL;
+PFNGLGETTEXENVXVPROC __glewGetTexEnvxv = NULL;
+PFNGLGETTEXPARAMETERXVPROC __glewGetTexParameterxv = NULL;
+PFNGLPOINTPARAMETERXPROC __glewPointParameterx = NULL;
+PFNGLPOINTPARAMETERXVPROC __glewPointParameterxv = NULL;
+PFNGLTEXPARAMETERXVPROC __glewTexParameterxv = NULL;
+
+PFNGLCLIPPLANEFPROC __glewClipPlanef = NULL;
+PFNGLGETCLIPPLANEFPROC __glewGetClipPlanef = NULL;
+
+PFNGLBLITFRAMEBUFFERANGLEPROC __glewBlitFramebufferANGLE = NULL;
+
+PFNGLRENDERBUFFERSTORAGEMULTISAMPLEANGLEPROC __glewRenderbufferStorageMultisampleANGLE = NULL;
+
+PFNGLDRAWARRAYSINSTANCEDANGLEPROC __glewDrawArraysInstancedANGLE = NULL;
+PFNGLDRAWELEMENTSINSTANCEDANGLEPROC __glewDrawElementsInstancedANGLE = NULL;
+PFNGLVERTEXATTRIBDIVISORANGLEPROC __glewVertexAttribDivisorANGLE = NULL;
+
+PFNGLGETTRANSLATEDSHADERSOURCEANGLEPROC __glewGetTranslatedShaderSourceANGLE = NULL;
+
+PFNGLCOPYTEXTURELEVELSAPPLEPROC __glewCopyTextureLevelsAPPLE = NULL;
+
+PFNGLRENDERBUFFERSTORAGEMULTISAMPLEAPPLEPROC __glewRenderbufferStorageMultisampleAPPLE = NULL;
+PFNGLRESOLVEMULTISAMPLEFRAMEBUFFERAPPLEPROC __glewResolveMultisampleFramebufferAPPLE = NULL;
+
+PFNGLCLIENTWAITSYNCAPPLEPROC __glewClientWaitSyncAPPLE = NULL;
+PFNGLDELETESYNCAPPLEPROC __glewDeleteSyncAPPLE = NULL;
+PFNGLFENCESYNCAPPLEPROC __glewFenceSyncAPPLE = NULL;
+PFNGLGETINTEGER64VAPPLEPROC __glewGetInteger64vAPPLE = NULL;
+PFNGLGETSYNCIVAPPLEPROC __glewGetSyncivAPPLE = NULL;
+PFNGLISSYNCAPPLEPROC __glewIsSyncAPPLE = NULL;
+PFNGLWAITSYNCAPPLEPROC __glewWaitSyncAPPLE = NULL;
+
+PFNGLGETOBJECTLABELEXTPROC __glewGetObjectLabelEXT = NULL;
+PFNGLLABELOBJECTEXTPROC __glewLabelObjectEXT = NULL;
+
+PFNGLINSERTEVENTMARKEREXTPROC __glewInsertEventMarkerEXT = NULL;
+PFNGLPUSHGROUPMARKEREXTPROC __glewPushGroupMarkerEXT = NULL;
+
+PFNGLDISCARDFRAMEBUFFEREXTPROC __glewDiscardFramebufferEXT = NULL;
+
+PFNGLFLUSHMAPPEDBUFFERRANGEEXTPROC __glewFlushMappedBufferRangeEXT = NULL;
+PFNGLMAPBUFFERRANGEEXTPROC __glewMapBufferRangeEXT = NULL;
+
+PFNGLFRAMEBUFFERTEXTURE2DMULTISAMPLEEXTPROC __glewFramebufferTexture2DMultisampleEXT = NULL;
+//PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC __glewRenderbufferStorageMultisampleEXT = NULL;
+
+PFNGLDRAWBUFFERSINDEXEDEXTPROC __glewDrawBuffersIndexedEXT = NULL;
+PFNGLGETINTEGERI_VEXTPROC __glewGetIntegeri_vEXT = NULL;
+PFNGLREADBUFFERINDEXEDEXTPROC __glewReadBufferIndexedEXT = NULL;
+
+PFNGLBEGINQUERYEXTPROC __glewBeginQueryEXT = NULL;
+PFNGLDELETEQUERIESEXTPROC __glewDeleteQueriesEXT = NULL;
+PFNGLENDQUERYEXTPROC __glewEndQueryEXT = NULL;
+PFNGLGENQUERIESEXTPROC __glewGenQueriesEXT = NULL;
+PFNGLGETQUERYOBJECTUIVEXTPROC __glewGetQueryObjectuivEXT = NULL;
+PFNGLGETQUERYIVEXTPROC __glewGetQueryivEXT = NULL;
+PFNGLISQUERYEXTPROC __glewIsQueryEXT = NULL;
+
+PFNGLGETNUNIFORMFVEXTPROC __glewGetnUniformfvEXT = NULL;
+PFNGLGETNUNIFORMIVEXTPROC __glewGetnUniformivEXT = NULL;
+PFNGLREADNPIXELSEXTPROC __glewReadnPixelsEXT = NULL;
+
+PFNGLTEXSTORAGE1DEXTPROC __glewTexStorage1DEXT = NULL;
+PFNGLTEXSTORAGE2DEXTPROC __glewTexStorage2DEXT = NULL;
+PFNGLTEXSTORAGE3DEXTPROC __glewTexStorage3DEXT = NULL;
+//PFNGLTEXTURESTORAGE1DEXTPROC __glewTextureStorage1DEXT = NULL;
+//PFNGLTEXTURESTORAGE2DEXTPROC __glewTextureStorage2DEXT = NULL;
+//PFNGLTEXTURESTORAGE3DEXTPROC __glewTextureStorage3DEXT = NULL;
+
+PFNGLFRAMEBUFFERTEXTURE2DMULTISAMPLEIMGPROC __glewFramebufferTexture2DMultisampleIMG = NULL;
+PFNGLRENDERBUFFERSTORAGEMULTISAMPLEIMGPROC __glewRenderbufferStorageMultisampleIMG = NULL;
+
+PFNGLCLIPPLANEFIMGPROC __glewClipPlanefIMG = NULL;
+
+PFNGLSTEREOPARAMETERFNVPROC __glewStereoParameterfNV = NULL;
+PFNGLSTEREOPARAMETERINVPROC __glewStereoParameteriNV = NULL;
+
+PFNGLCOVERAGEMASKNVPROC __glewCoverageMaskNV = NULL;
+PFNGLCOVERAGEOPERATIONNVPROC __glewCoverageOperationNV = NULL;
+
+PFNGLDRAWBUFFERSNVPROC __glewDrawBuffersNV = NULL;
+
+PFNGLREADBUFFERNVPROC __glewReadBufferNV = NULL;
+
+PFNGLCOMPRESSEDTEXIMAGE3DNVPROC __glewCompressedTexImage3DNV = NULL;
+PFNGLCOMPRESSEDTEXSUBIMAGE3DNVPROC __glewCompressedTexSubImage3DNV = NULL;
+PFNGLCOPYTEXSUBIMAGE3DNVPROC __glewCopyTexSubImage3DNV = NULL;
+PFNGLFRAMEBUFFERTEXTURELAYERNVPROC __glewFramebufferTextureLayerNV = NULL;
+PFNGLTEXIMAGE3DNVPROC __glewTexImage3DNV = NULL;
+PFNGLTEXSUBIMAGE3DNVPROC __glewTexSubImage3DNV = NULL;
+
+PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC __glewEGLImageTargetRenderbufferStorageOES = NULL;
+PFNGLEGLIMAGETARGETTEXTURE2DOESPROC __glewEGLImageTargetTexture2DOES = NULL;
+
+PFNGLBLENDEQUATIONSEPARATEOESPROC __glewBlendEquationSeparateOES = NULL;
+
+PFNGLBLENDFUNCSEPARATEOESPROC __glewBlendFuncSeparateOES = NULL;
+
+PFNGLBLENDEQUATIONOESPROC __glewBlendEquationOES = NULL;
+
+PFNGLBINDFRAMEBUFFEROESPROC __glewBindFramebufferOES = NULL;
+PFNGLBINDRENDERBUFFEROESPROC __glewBindRenderbufferOES = NULL;
+PFNGLCHECKFRAMEBUFFERSTATUSOESPROC __glewCheckFramebufferStatusOES = NULL;
+PFNGLDELETEFRAMEBUFFERSOESPROC __glewDeleteFramebuffersOES = NULL;
+PFNGLDELETERENDERBUFFERSOESPROC __glewDeleteRenderbuffersOES = NULL;
+PFNGLFRAMEBUFFERRENDERBUFFEROESPROC __glewFramebufferRenderbufferOES = NULL;
+PFNGLFRAMEBUFFERTEXTURE2DOESPROC __glewFramebufferTexture2DOES = NULL;
+PFNGLGENFRAMEBUFFERSOESPROC __glewGenFramebuffersOES = NULL;
+PFNGLGENRENDERBUFFERSOESPROC __glewGenRenderbuffersOES = NULL;
+PFNGLGENERATEMIPMAPOESPROC __glewGenerateMipmapOES = NULL;
+PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVOESPROC __glewGetFramebufferAttachmentParameterivOES = NULL;
+PFNGLGETRENDERBUFFERPARAMETERIVOESPROC __glewGetRenderbufferParameterivOES = NULL;
+PFNGLISFRAMEBUFFEROESPROC __glewIsFramebufferOES = NULL;
+PFNGLISRENDERBUFFEROESPROC __glewIsRenderbufferOES = NULL;
+PFNGLRENDERBUFFERSTORAGEOESPROC __glewRenderbufferStorageOES = NULL;
+
+PFNGLGETPROGRAMBINARYOESPROC __glewGetProgramBinaryOES = NULL;
+PFNGLPROGRAMBINARYOESPROC __glewProgramBinaryOES = NULL;
+
+PFNGLGETBUFFERPOINTERVOESPROC __glewGetBufferPointervOES = NULL;
+PFNGLMAPBUFFEROESPROC __glewMapBufferOES = NULL;
+PFNGLUNMAPBUFFEROESPROC __glewUnmapBufferOES = NULL;
+
+PFNGLCURRENTPALETTEMATRIXOESPROC __glewCurrentPaletteMatrixOES = NULL;
+PFNGLMATRIXINDEXPOINTEROESPROC __glewMatrixIndexPointerOES = NULL;
+PFNGLWEIGHTPOINTEROESPROC __glewWeightPointerOES = NULL;
+
+PFNGLPOINTSIZEPOINTEROESPROC __glewPointSizePointerOES = NULL;
+
+PFNGLCOMPRESSEDTEXIMAGE3DOESPROC __glewCompressedTexImage3DOES = NULL;
+PFNGLCOMPRESSEDTEXSUBIMAGE3DOESPROC __glewCompressedTexSubImage3DOES = NULL;
+PFNGLCOPYTEXSUBIMAGE3DOESPROC __glewCopyTexSubImage3DOES = NULL;
+PFNGLFRAMEBUFFERTEXTURE3DOESPROC __glewFramebufferTexture3DOES = NULL;
+PFNGLTEXIMAGE3DOESPROC __glewTexImage3DOES = NULL;
+PFNGLTEXSUBIMAGE3DOESPROC __glewTexSubImage3DOES = NULL;
+
+PFNGLGETTEXGENFVOESPROC __glewGetTexGenfvOES = NULL;
+PFNGLGETTEXGENIVOESPROC __glewGetTexGenivOES = NULL;
+PFNGLGETTEXGENXVOESPROC __glewGetTexGenxvOES = NULL;
+PFNGLTEXGENFOESPROC __glewTexGenfOES = NULL;
+PFNGLTEXGENFVOESPROC __glewTexGenfvOES = NULL;
+PFNGLTEXGENIOESPROC __glewTexGeniOES = NULL;
+PFNGLTEXGENIVOESPROC __glewTexGenivOES = NULL;
+PFNGLTEXGENXOESPROC __glewTexGenxOES = NULL;
+PFNGLTEXGENXVOESPROC __glewTexGenxvOES = NULL;
+
+PFNGLBINDVERTEXARRAYOESPROC __glewBindVertexArrayOES = NULL;
+PFNGLDELETEVERTEXARRAYSOESPROC __glewDeleteVertexArraysOES = NULL;
+PFNGLGENVERTEXARRAYSOESPROC __glewGenVertexArraysOES = NULL;
+PFNGLISVERTEXARRAYOESPROC __glewIsVertexArrayOES = NULL;
+
+PFNGLALPHAFUNCQCOMPROC __glewAlphaFuncQCOM = NULL;
+
+PFNGLDISABLEDRIVERCONTROLQCOMPROC __glewDisableDriverControlQCOM = NULL;
+PFNGLENABLEDRIVERCONTROLQCOMPROC __glewEnableDriverControlQCOM = NULL;
+PFNGLGETDRIVERCONTROLSTRINGQCOMPROC __glewGetDriverControlStringQCOM = NULL;
+PFNGLGETDRIVERCONTROLSQCOMPROC __glewGetDriverControlsQCOM = NULL;
+
+PFNGLEXTGETBUFFERPOINTERVQCOMPROC __glewExtGetBufferPointervQCOM = NULL;
+PFNGLEXTGETBUFFERSQCOMPROC __glewExtGetBuffersQCOM = NULL;
+PFNGLEXTGETFRAMEBUFFERSQCOMPROC __glewExtGetFramebuffersQCOM = NULL;
+PFNGLEXTGETRENDERBUFFERSQCOMPROC __glewExtGetRenderbuffersQCOM = NULL;
+PFNGLEXTGETTEXLEVELPARAMETERIVQCOMPROC __glewExtGetTexLevelParameterivQCOM = NULL;
+PFNGLEXTGETTEXSUBIMAGEQCOMPROC __glewExtGetTexSubImageQCOM = NULL;
+PFNGLEXTGETTEXTURESQCOMPROC __glewExtGetTexturesQCOM = NULL;
+PFNGLEXTTEXOBJECTSTATEOVERRIDEIQCOMPROC __glewExtTexObjectStateOverrideiQCOM = NULL;
+
+PFNGLEXTGETPROGRAMBINARYSOURCEQCOMPROC __glewExtGetProgramBinarySourceQCOM = NULL;
+PFNGLEXTGETPROGRAMSQCOMPROC __glewExtGetProgramsQCOM = NULL;
+PFNGLEXTGETSHADERSQCOMPROC __glewExtGetShadersQCOM = NULL;
+PFNGLEXTISPROGRAMBINARYQCOMPROC __glewExtIsProgramBinaryQCOM = NULL;
+
+PFNGLENDTILINGQCOMPROC __glewEndTilingQCOM = NULL;
+PFNGLSTARTTILINGQCOMPROC __glewStartTilingQCOM = NULL;
+
+PFNGLMULTIDRAWARRAYSSUNPROC __glewMultiDrawArraysSUN = NULL;
+PFNGLMULTIDRAWELEMENTSSUNPROC __glewMultiDrawElementsSUN = NULL;
+
+#endif /* !(GLEW_NO_ES) */
+
+#else
+
+#if GL_ES_VERSION_1_0 // NOTE jwilkins: glew doesn't actually seem to be designed to let you use the extension macros
+PFNGLACTIVETEXTUREPROC __glewActiveTexture = NULL;
+PFNGLALPHAFUNCXPROC __glewAlphaFuncx = NULL;
+PFNGLCLEARCOLORXPROC __glewClearColorx = NULL;
+PFNGLCLEARDEPTHFPROC __glewClearDepthf = NULL;
+PFNGLCLEARDEPTHXPROC __glewClearDepthx = NULL;
+PFNGLCLIENTACTIVETEXTUREPROC __glewClientActiveTexture = NULL;
+PFNGLCOLOR4XPROC __glewColor4x = NULL;
+PFNGLCOMPRESSEDTEXIMAGE2DPROC __glewCompressedTexImage2D = NULL;
+PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC __glewCompressedTexSubImage2D = NULL;
+PFNGLDEPTHRANGEFPROC __glewDepthRangef = NULL;
+PFNGLDEPTHRANGEXPROC __glewDepthRangex = NULL;
+PFNGLFOGXPROC __glewFogx = NULL;
+PFNGLFOGXVPROC __glewFogxv = NULL;
+PFNGLFRUSTUMFPROC __glewFrustumf = NULL;
+PFNGLFRUSTUMXPROC __glewFrustumx = NULL;
+PFNGLLIGHTMODELXPROC __glewLightModelx = NULL;
+PFNGLLIGHTMODELXVPROC __glewLightModelxv = NULL;
+PFNGLLIGHTXPROC __glewLightx = NULL;
+PFNGLLIGHTXVPROC __glewLightxv = NULL;
+PFNGLLINEWIDTHXPROC __glewLineWidthx = NULL;
+PFNGLLOADMATRIXXPROC __glewLoadMatrixx = NULL;
+PFNGLMATERIALXPROC __glewMaterialx = NULL;
+PFNGLMATERIALXVPROC __glewMaterialxv = NULL;
+PFNGLMULTMATRIXXPROC __glewMultMatrixx = NULL;
+PFNGLMULTITEXCOORD4FPROC __glewMultiTexCoord4f = NULL;
+PFNGLMULTITEXCOORD4XPROC __glewMultiTexCoord4x = NULL;
+PFNGLNORMAL3XPROC __glewNormal3x = NULL;
+PFNGLORTHOFPROC __glewOrthof = NULL;
+PFNGLORTHOXPROC __glewOrthox = NULL;
+PFNGLPOINTSIZEXPROC __glewPointSizex = NULL;
+PFNGLPOLYGONOFFSETXPROC __glewPolygonOffsetx = NULL;
+PFNGLROTATEXPROC __glewRotatex = NULL;
+PFNGLSAMPLECOVERAGEPROC __glewSampleCoverage = NULL;
+PFNGLSAMPLECOVERAGEXPROC __glewSampleCoveragex = NULL;
+PFNGLSCALEXPROC __glewScalex = NULL;
+PFNGLTEXENVXPROC __glewTexEnvx = NULL;
+PFNGLTEXENVXVPROC __glewTexEnvxv = NULL;
+PFNGLTEXPARAMETERXPROC __glewTexParameterx = NULL;
+PFNGLTRANSLATEXPROC __glewTranslatex = NULL;
+#endif // NOTE jwilkins
+
+#if GL_ES_VERSION_CL_1_1 // NOTE jwilkins
+PFNGLBINDBUFFERPROC __glewBindBuffer = NULL;
+PFNGLBUFFERDATAPROC __glewBufferData = NULL;
+PFNGLBUFFERSUBDATAPROC __glewBufferSubData = NULL;
+PFNGLCLIPPLANEXPROC __glewClipPlanex = NULL;
+PFNGLCOLOR4UBPROC __glewColor4ub = NULL;
+PFNGLDELETEBUFFERSPROC __glewDeleteBuffers = NULL;
+PFNGLGENBUFFERSPROC __glewGenBuffers = NULL;
+PFNGLGETBOOLEANVPROC __glewGetBooleanv = NULL;
+PFNGLGETBUFFERPARAMETERIVPROC __glewGetBufferParameteriv = NULL;
+PFNGLGETCLIPPLANEXPROC __glewGetClipPlanex = NULL;
+PFNGLGETFIXEDVPROC __glewGetFixedv = NULL;
+PFNGLGETLIGHTXVPROC __glewGetLightxv = NULL;
+PFNGLGETMATERIALXVPROC __glewGetMaterialxv = NULL;
+PFNGLGETPOINTERVPROC __glewGetPointerv = NULL;
+PFNGLGETTEXENVIVPROC __glewGetTexEnviv = NULL;
+PFNGLGETTEXENVXVPROC __glewGetTexEnvxv = NULL;
+PFNGLGETTEXPARAMETERIVPROC __glewGetTexParameteriv = NULL;
+PFNGLGETTEXPARAMETERXVPROC __glewGetTexParameterxv = NULL;
+PFNGLISBUFFERPROC __glewIsBuffer = NULL;
+PFNGLISENABLEDPROC __glewIsEnabled = NULL;
+PFNGLISTEXTUREPROC __glewIsTexture = NULL;
+PFNGLPOINTPARAMETERXPROC __glewPointParameterx = NULL;
+PFNGLPOINTPARAMETERXVPROC __glewPointParameterxv = NULL;
+PFNGLTEXENVIPROC __glewTexEnvi = NULL;
+PFNGLTEXENVIVPROC __glewTexEnviv = NULL;
+PFNGLTEXPARAMETERIPROC __glewTexParameteri = NULL;
+PFNGLTEXPARAMETERIVPROC __glewTexParameteriv = NULL;
+PFNGLTEXPARAMETERXVPROC __glewTexParameterxv = NULL;
+#endif // NOTE jwilkins
+
+#if GL_ES_VERSION_CM_1_1 // NOTE jwilkins
+PFNGLCLIPPLANEFPROC __glewClipPlanef = NULL;
+PFNGLGETCLIPPLANEFPROC __glewGetClipPlanef = NULL;
+PFNGLGETFLOATVPROC __glewGetFloatv = NULL;
+PFNGLGETLIGHTFVPROC __glewGetLightfv = NULL;
+PFNGLGETMATERIALFVPROC __glewGetMaterialfv = NULL;
+PFNGLGETTEXENVFVPROC __glewGetTexEnvfv = NULL;
+PFNGLGETTEXPARAMETERFVPROC __glewGetTexParameterfv = NULL;
+PFNGLPOINTPARAMETERFPROC __glewPointParameterf = NULL;
+PFNGLPOINTPARAMETERFVPROC __glewPointParameterfv = NULL;
+PFNGLTEXPARAMETERFVPROC __glewTexParameterfv = NULL;
+#endif
+
+PFNGLATTACHSHADERPROC __glewAttachShader = NULL;
+PFNGLBINDATTRIBLOCATIONPROC __glewBindAttribLocation = NULL;
+PFNGLBINDFRAMEBUFFERPROC __glewBindFramebuffer = NULL;
+PFNGLBINDRENDERBUFFERPROC __glewBindRenderbuffer = NULL;
+PFNGLBLENDCOLORPROC __glewBlendColor = NULL;
+PFNGLBLENDEQUATIONPROC __glewBlendEquation = NULL;
+PFNGLBLENDEQUATIONSEPARATEPROC __glewBlendEquationSeparate = NULL;
+PFNGLBLENDFUNCSEPARATEPROC __glewBlendFuncSeparate = NULL;
+PFNGLCHECKFRAMEBUFFERSTATUSPROC __glewCheckFramebufferStatus = NULL;
+PFNGLCOMPILESHADERPROC __glewCompileShader = NULL;
+PFNGLCREATEPROGRAMPROC __glewCreateProgram = NULL;
+PFNGLCREATESHADERPROC __glewCreateShader = NULL;
+PFNGLDELETEFRAMEBUFFERSPROC __glewDeleteFramebuffers = NULL;
+PFNGLDELETEPROGRAMPROC __glewDeleteProgram = NULL;
+PFNGLDELETERENDERBUFFERSPROC __glewDeleteRenderbuffers = NULL;
+PFNGLDELETESHADERPROC __glewDeleteShader = NULL;
+PFNGLDETACHSHADERPROC __glewDetachShader = NULL;
+PFNGLDISABLEVERTEXATTRIBARRAYPROC __glewDisableVertexAttribArray = NULL;
+PFNGLENABLEVERTEXATTRIBARRAYPROC __glewEnableVertexAttribArray = NULL;
+PFNGLFRAMEBUFFERRENDERBUFFERPROC __glewFramebufferRenderbuffer = NULL;
+PFNGLFRAMEBUFFERTEXTURE2DPROC __glewFramebufferTexture2D = NULL;
+PFNGLGENFRAMEBUFFERSPROC __glewGenFramebuffers = NULL;
+PFNGLGENRENDERBUFFERSPROC __glewGenRenderbuffers = NULL;
+PFNGLGENERATEMIPMAPPROC __glewGenerateMipmap = NULL;
+PFNGLGETACTIVEATTRIBPROC __glewGetActiveAttrib = NULL;
+PFNGLGETACTIVEUNIFORMPROC __glewGetActiveUniform = NULL;
+PFNGLGETATTACHEDSHADERSPROC __glewGetAttachedShaders = NULL;
+PFNGLGETATTRIBLOCATIONPROC __glewGetAttribLocation = NULL;
+PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC __glewGetFramebufferAttachmentParameteriv = NULL;
+PFNGLGETPROGRAMINFOLOGPROC __glewGetProgramInfoLog = NULL;
+PFNGLGETPROGRAMIVPROC __glewGetProgramiv = NULL;
+PFNGLGETRENDERBUFFERPARAMETERIVPROC __glewGetRenderbufferParameteriv = NULL;
+PFNGLGETSHADERINFOLOGPROC __glewGetShaderInfoLog = NULL;
+PFNGLGETSHADERPRECISIONFORMATPROC __glewGetShaderPrecisionFormat = NULL;
+PFNGLGETSHADERSOURCEPROC __glewGetShaderSource = NULL;
+PFNGLGETSHADERIVPROC __glewGetShaderiv = NULL;
+PFNGLGETUNIFORMLOCATIONPROC __glewGetUniformLocation = NULL;
+PFNGLGETUNIFORMFVPROC __glewGetUniformfv = NULL;
+PFNGLGETUNIFORMIVPROC __glewGetUniformiv = NULL;
+PFNGLGETVERTEXATTRIBPOINTERVPROC __glewGetVertexAttribPointerv = NULL;
+PFNGLGETVERTEXATTRIBFVPROC __glewGetVertexAttribfv = NULL;
+PFNGLGETVERTEXATTRIBIVPROC __glewGetVertexAttribiv = NULL;
+PFNGLISFRAMEBUFFERPROC __glewIsFramebuffer = NULL;
+PFNGLISPROGRAMPROC __glewIsProgram = NULL;
+PFNGLISRENDERBUFFERPROC __glewIsRenderbuffer = NULL;
+PFNGLISSHADERPROC __glewIsShader = NULL;
+PFNGLLINKPROGRAMPROC __glewLinkProgram = NULL;
+PFNGLRELEASESHADERCOMPILERPROC __glewReleaseShaderCompiler = NULL;
+PFNGLRENDERBUFFERSTORAGEPROC __glewRenderbufferStorage = NULL;
+PFNGLSHADERBINARYPROC __glewShaderBinary = NULL;
+PFNGLSHADERSOURCEPROC __glewShaderSource = NULL;
+PFNGLSTENCILFUNCSEPARATEPROC __glewStencilFuncSeparate = NULL;
+PFNGLSTENCILMASKSEPARATEPROC __glewStencilMaskSeparate = NULL;
+PFNGLSTENCILOPSEPARATEPROC __glewStencilOpSeparate = NULL;
+PFNGLUNIFORM1FPROC __glewUniform1f = NULL;
+PFNGLUNIFORM1FVPROC __glewUniform1fv = NULL;
+PFNGLUNIFORM1IPROC __glewUniform1i = NULL;
+PFNGLUNIFORM1IVPROC __glewUniform1iv = NULL;
+PFNGLUNIFORM2FPROC __glewUniform2f = NULL;
+PFNGLUNIFORM2FVPROC __glewUniform2fv = NULL;
+PFNGLUNIFORM2IPROC __glewUniform2i = NULL;
+PFNGLUNIFORM2IVPROC __glewUniform2iv = NULL;
+PFNGLUNIFORM3FPROC __glewUniform3f = NULL;
+PFNGLUNIFORM3FVPROC __glewUniform3fv = NULL;
+PFNGLUNIFORM3IPROC __glewUniform3i = NULL;
+PFNGLUNIFORM3IVPROC __glewUniform3iv = NULL;
+PFNGLUNIFORM4FPROC __glewUniform4f = NULL;
+PFNGLUNIFORM4FVPROC __glewUniform4fv = NULL;
+PFNGLUNIFORM4IPROC __glewUniform4i = NULL;
+PFNGLUNIFORM4IVPROC __glewUniform4iv = NULL;
+PFNGLUNIFORMMATRIX2FVPROC __glewUniformMatrix2fv = NULL;
+PFNGLUNIFORMMATRIX3FVPROC __glewUniformMatrix3fv = NULL;
+PFNGLUNIFORMMATRIX4FVPROC __glewUniformMatrix4fv = NULL;
+PFNGLUSEPROGRAMPROC __glewUseProgram = NULL;
+PFNGLVALIDATEPROGRAMPROC __glewValidateProgram = NULL;
+PFNGLVERTEXATTRIB1FPROC __glewVertexAttrib1f = NULL;
+PFNGLVERTEXATTRIB1FVPROC __glewVertexAttrib1fv = NULL;
+PFNGLVERTEXATTRIB2FPROC __glewVertexAttrib2f = NULL;
+PFNGLVERTEXATTRIB2FVPROC __glewVertexAttrib2fv = NULL;
+PFNGLVERTEXATTRIB3FPROC __glewVertexAttrib3f = NULL;
+PFNGLVERTEXATTRIB3FVPROC __glewVertexAttrib3fv = NULL;
+PFNGLVERTEXATTRIB4FPROC __glewVertexAttrib4f = NULL;
+PFNGLVERTEXATTRIB4FVPROC __glewVertexAttrib4fv = NULL;
+PFNGLVERTEXATTRIBPOINTERPROC __glewVertexAttribPointer = NULL;
+
+#if !GL_ES_VERSION_CL_1_1 // NOTE jwilkins: missing function
+PFNGLBINDBUFFERPROC __glewBindBuffer = NULL; // XXX
+PFNGLBUFFERDATAPROC __glewBufferData = NULL; // XXX
+PFNGLBUFFERSUBDATAPROC __glewBufferSubData = NULL; // XXX
+PFNGLGENBUFFERSPROC __glewGenBuffers = NULL; // XXX
+PFNGLDELETEBUFFERSPROC __glewDeleteBuffers = NULL; // XXX
+PFNGLTEXPARAMETERIPROC __glewTexParameteri = NULL; // XXX
+PFNGLISENABLEDPROC __glewIsEnabled = NULL; // XXX
+PFNGLGETFLOATVPROC __glewGetFloatv = NULL; // XXX
+PFNGLDEPTHRANGEFPROC __glewDepthRangef = NULL; // XXX
+PFNGLACTIVETEXTUREPROC __glewActiveTexture = NULL; // XXX
+PFNGLGETBOOLEANVPROC __glewGetBooleanv = NULL; // XXX
+#endif // XXX
+
+PFNGLBLITFRAMEBUFFERANGLEPROC __glewBlitFramebufferANGLE = NULL;
+
+PFNGLRENDERBUFFERSTORAGEMULTISAMPLEANGLEPROC __glewRenderbufferStorageMultisampleANGLE = NULL;
+
+PFNGLDRAWARRAYSINSTANCEDANGLEPROC __glewDrawArraysInstancedANGLE = NULL;
+PFNGLDRAWELEMENTSINSTANCEDANGLEPROC __glewDrawElementsInstancedANGLE = NULL;
+PFNGLVERTEXATTRIBDIVISORANGLEPROC __glewVertexAttribDivisorANGLE = NULL;
+
+PFNGLGETTRANSLATEDSHADERSOURCEANGLEPROC __glewGetTranslatedShaderSourceANGLE = NULL;
+
+PFNGLCOPYTEXTURELEVELSAPPLEPROC __glewCopyTextureLevelsAPPLE = NULL;
+
+PFNGLRENDERBUFFERSTORAGEMULTISAMPLEAPPLEPROC __glewRenderbufferStorageMultisampleAPPLE = NULL;
+PFNGLRESOLVEMULTISAMPLEFRAMEBUFFERAPPLEPROC __glewResolveMultisampleFramebufferAPPLE = NULL;
+
+PFNGLCLIENTWAITSYNCAPPLEPROC __glewClientWaitSyncAPPLE = NULL;
+PFNGLDELETESYNCAPPLEPROC __glewDeleteSyncAPPLE = NULL;
+PFNGLFENCESYNCAPPLEPROC __glewFenceSyncAPPLE = NULL;
+PFNGLGETINTEGER64VAPPLEPROC __glewGetInteger64vAPPLE = NULL;
+PFNGLGETSYNCIVAPPLEPROC __glewGetSyncivAPPLE = NULL;
+PFNGLISSYNCAPPLEPROC __glewIsSyncAPPLE = NULL;
+PFNGLWAITSYNCAPPLEPROC __glewWaitSyncAPPLE = NULL;
+
+PFNGLGETOBJECTLABELEXTPROC __glewGetObjectLabelEXT = NULL;
+PFNGLLABELOBJECTEXTPROC __glewLabelObjectEXT = NULL;
+
+PFNGLINSERTEVENTMARKEREXTPROC __glewInsertEventMarkerEXT = NULL;
+PFNGLPUSHGROUPMARKEREXTPROC __glewPushGroupMarkerEXT = NULL;
+
+PFNGLDISCARDFRAMEBUFFEREXTPROC __glewDiscardFramebufferEXT = NULL;
+
+PFNGLFLUSHMAPPEDBUFFERRANGEEXTPROC __glewFlushMappedBufferRangeEXT = NULL;
+PFNGLMAPBUFFERRANGEEXTPROC __glewMapBufferRangeEXT = NULL;
+
+PFNGLFRAMEBUFFERTEXTURE2DMULTISAMPLEEXTPROC __glewFramebufferTexture2DMultisampleEXT = NULL;
+PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC __glewRenderbufferStorageMultisampleEXT = NULL;
+
+PFNGLDRAWBUFFERSINDEXEDEXTPROC __glewDrawBuffersIndexedEXT = NULL;
+PFNGLGETINTEGERI_VEXTPROC __glewGetIntegeri_vEXT = NULL;
+PFNGLREADBUFFERINDEXEDEXTPROC __glewReadBufferIndexedEXT = NULL;
+
+PFNGLBEGINQUERYEXTPROC __glewBeginQueryEXT = NULL;
+PFNGLDELETEQUERIESEXTPROC __glewDeleteQueriesEXT = NULL;
+PFNGLENDQUERYEXTPROC __glewEndQueryEXT = NULL;
+PFNGLGENQUERIESEXTPROC __glewGenQueriesEXT = NULL;
+PFNGLGETQUERYOBJECTUIVEXTPROC __glewGetQueryObjectuivEXT = NULL;
+PFNGLGETQUERYIVEXTPROC __glewGetQueryivEXT = NULL;
+PFNGLISQUERYEXTPROC __glewIsQueryEXT = NULL;
+
+PFNGLGETNUNIFORMFVEXTPROC __glewGetnUniformfvEXT = NULL;
+PFNGLGETNUNIFORMIVEXTPROC __glewGetnUniformivEXT = NULL;
+PFNGLREADNPIXELSEXTPROC __glewReadnPixelsEXT = NULL;
+
+PFNGLTEXSTORAGE1DEXTPROC __glewTexStorage1DEXT = NULL;
+PFNGLTEXSTORAGE2DEXTPROC __glewTexStorage2DEXT = NULL;
+PFNGLTEXSTORAGE3DEXTPROC __glewTexStorage3DEXT = NULL;
+PFNGLTEXTURESTORAGE1DEXTPROC __glewTextureStorage1DEXT = NULL;
+PFNGLTEXTURESTORAGE2DEXTPROC __glewTextureStorage2DEXT = NULL;
+PFNGLTEXTURESTORAGE3DEXTPROC __glewTextureStorage3DEXT = NULL;
+
+PFNGLFRAMEBUFFERTEXTURE2DMULTISAMPLEIMGPROC __glewFramebufferTexture2DMultisampleIMG = NULL;
+PFNGLRENDERBUFFERSTORAGEMULTISAMPLEIMGPROC __glewRenderbufferStorageMultisampleIMG = NULL;
+
+PFNGLCLIPPLANEFIMGPROC __glewClipPlanefIMG = NULL;
+
+PFNGLSTEREOPARAMETERFNVPROC __glewStereoParameterfNV = NULL;
+PFNGLSTEREOPARAMETERINVPROC __glewStereoParameteriNV = NULL;
+
+PFNGLCOVERAGEMASKNVPROC __glewCoverageMaskNV = NULL;
+PFNGLCOVERAGEOPERATIONNVPROC __glewCoverageOperationNV = NULL;
+
+PFNGLDRAWBUFFERSNVPROC __glewDrawBuffersNV = NULL;
+
+PFNGLREADBUFFERNVPROC __glewReadBufferNV = NULL;
+
+PFNGLCOMPRESSEDTEXIMAGE3DNVPROC __glewCompressedTexImage3DNV = NULL;
+PFNGLCOMPRESSEDTEXSUBIMAGE3DNVPROC __glewCompressedTexSubImage3DNV = NULL;
+PFNGLCOPYTEXSUBIMAGE3DNVPROC __glewCopyTexSubImage3DNV = NULL;
+PFNGLFRAMEBUFFERTEXTURELAYERNVPROC __glewFramebufferTextureLayerNV = NULL;
+PFNGLTEXIMAGE3DNVPROC __glewTexImage3DNV = NULL;
+PFNGLTEXSUBIMAGE3DNVPROC __glewTexSubImage3DNV = NULL;
+
+PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC __glewEGLImageTargetRenderbufferStorageOES = NULL;
+PFNGLEGLIMAGETARGETTEXTURE2DOESPROC __glewEGLImageTargetTexture2DOES = NULL;
+
+PFNGLBLENDEQUATIONSEPARATEOESPROC __glewBlendEquationSeparateOES = NULL;
+
+PFNGLBLENDFUNCSEPARATEOESPROC __glewBlendFuncSeparateOES = NULL;
+
+PFNGLBLENDEQUATIONOESPROC __glewBlendEquationOES = NULL;
+
+PFNGLBINDFRAMEBUFFEROESPROC __glewBindFramebufferOES = NULL;
+PFNGLBINDRENDERBUFFEROESPROC __glewBindRenderbufferOES = NULL;
+PFNGLCHECKFRAMEBUFFERSTATUSOESPROC __glewCheckFramebufferStatusOES = NULL;
+PFNGLDELETEFRAMEBUFFERSOESPROC __glewDeleteFramebuffersOES = NULL;
+PFNGLDELETERENDERBUFFERSOESPROC __glewDeleteRenderbuffersOES = NULL;
+PFNGLFRAMEBUFFERRENDERBUFFEROESPROC __glewFramebufferRenderbufferOES = NULL;
+PFNGLFRAMEBUFFERTEXTURE2DOESPROC __glewFramebufferTexture2DOES = NULL;
+PFNGLGENFRAMEBUFFERSOESPROC __glewGenFramebuffersOES = NULL;
+PFNGLGENRENDERBUFFERSOESPROC __glewGenRenderbuffersOES = NULL;
+PFNGLGENERATEMIPMAPOESPROC __glewGenerateMipmapOES = NULL;
+PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVOESPROC __glewGetFramebufferAttachmentParameterivOES = NULL;
+PFNGLGETRENDERBUFFERPARAMETERIVOESPROC __glewGetRenderbufferParameterivOES = NULL;
+PFNGLISFRAMEBUFFEROESPROC __glewIsFramebufferOES = NULL;
+PFNGLISRENDERBUFFEROESPROC __glewIsRenderbufferOES = NULL;
+PFNGLRENDERBUFFERSTORAGEOESPROC __glewRenderbufferStorageOES = NULL;
+
+PFNGLGETPROGRAMBINARYOESPROC __glewGetProgramBinaryOES = NULL;
+PFNGLPROGRAMBINARYOESPROC __glewProgramBinaryOES = NULL;
+
+PFNGLGETBUFFERPOINTERVOESPROC __glewGetBufferPointervOES = NULL;
+PFNGLMAPBUFFEROESPROC __glewMapBufferOES = NULL;
+PFNGLUNMAPBUFFEROESPROC __glewUnmapBufferOES = NULL;
+
+PFNGLCURRENTPALETTEMATRIXOESPROC __glewCurrentPaletteMatrixOES = NULL;
+PFNGLMATRIXINDEXPOINTEROESPROC __glewMatrixIndexPointerOES = NULL;
+PFNGLWEIGHTPOINTEROESPROC __glewWeightPointerOES = NULL;
+
+PFNGLPOINTSIZEPOINTEROESPROC __glewPointSizePointerOES = NULL;
+
+PFNGLCOMPRESSEDTEXIMAGE3DOESPROC __glewCompressedTexImage3DOES = NULL;
+PFNGLCOMPRESSEDTEXSUBIMAGE3DOESPROC __glewCompressedTexSubImage3DOES = NULL;
+PFNGLCOPYTEXSUBIMAGE3DOESPROC __glewCopyTexSubImage3DOES = NULL;
+PFNGLFRAMEBUFFERTEXTURE3DOESPROC __glewFramebufferTexture3DOES = NULL;
+PFNGLTEXIMAGE3DOESPROC __glewTexImage3DOES = NULL;
+PFNGLTEXSUBIMAGE3DOESPROC __glewTexSubImage3DOES = NULL;
+
+PFNGLGETTEXGENFVOESPROC __glewGetTexGenfvOES = NULL;
+PFNGLGETTEXGENIVOESPROC __glewGetTexGenivOES = NULL;
+PFNGLGETTEXGENXVOESPROC __glewGetTexGenxvOES = NULL;
+PFNGLTEXGENFOESPROC __glewTexGenfOES = NULL;
+PFNGLTEXGENFVOESPROC __glewTexGenfvOES = NULL;
+PFNGLTEXGENIOESPROC __glewTexGeniOES = NULL;
+PFNGLTEXGENIVOESPROC __glewTexGenivOES = NULL;
+PFNGLTEXGENXOESPROC __glewTexGenxOES = NULL;
+PFNGLTEXGENXVOESPROC __glewTexGenxvOES = NULL;
+
+PFNGLBINDVERTEXARRAYOESPROC __glewBindVertexArrayOES = NULL;
+PFNGLDELETEVERTEXARRAYSOESPROC __glewDeleteVertexArraysOES = NULL;
+PFNGLGENVERTEXARRAYSOESPROC __glewGenVertexArraysOES = NULL;
+PFNGLISVERTEXARRAYOESPROC __glewIsVertexArrayOES = NULL;
+
+PFNGLALPHAFUNCQCOMPROC __glewAlphaFuncQCOM = NULL;
+
+PFNGLDISABLEDRIVERCONTROLQCOMPROC __glewDisableDriverControlQCOM = NULL;
+PFNGLENABLEDRIVERCONTROLQCOMPROC __glewEnableDriverControlQCOM = NULL;
+PFNGLGETDRIVERCONTROLSTRINGQCOMPROC __glewGetDriverControlStringQCOM = NULL;
+PFNGLGETDRIVERCONTROLSQCOMPROC __glewGetDriverControlsQCOM = NULL;
+
+PFNGLEXTGETBUFFERPOINTERVQCOMPROC __glewExtGetBufferPointervQCOM = NULL;
+PFNGLEXTGETBUFFERSQCOMPROC __glewExtGetBuffersQCOM = NULL;
+PFNGLEXTGETFRAMEBUFFERSQCOMPROC __glewExtGetFramebuffersQCOM = NULL;
+PFNGLEXTGETRENDERBUFFERSQCOMPROC __glewExtGetRenderbuffersQCOM = NULL;
+PFNGLEXTGETTEXLEVELPARAMETERIVQCOMPROC __glewExtGetTexLevelParameterivQCOM = NULL;
+PFNGLEXTGETTEXSUBIMAGEQCOMPROC __glewExtGetTexSubImageQCOM = NULL;
+PFNGLEXTGETTEXTURESQCOMPROC __glewExtGetTexturesQCOM = NULL;
+PFNGLEXTTEXOBJECTSTATEOVERRIDEIQCOMPROC __glewExtTexObjectStateOverrideiQCOM = NULL;
+
+PFNGLEXTGETPROGRAMBINARYSOURCEQCOMPROC __glewExtGetProgramBinarySourceQCOM = NULL;
+PFNGLEXTGETPROGRAMSQCOMPROC __glewExtGetProgramsQCOM = NULL;
+PFNGLEXTGETSHADERSQCOMPROC __glewExtGetShadersQCOM = NULL;
+PFNGLEXTISPROGRAMBINARYQCOMPROC __glewExtIsProgramBinaryQCOM = NULL;
+
+PFNGLENDTILINGQCOMPROC __glewEndTilingQCOM = NULL;
+PFNGLSTARTTILINGQCOMPROC __glewStartTilingQCOM = NULL;
+
+PFNGLMULTIDRAWARRAYSSUNPROC __glewMultiDrawArraysSUN = NULL;
+PFNGLMULTIDRAWELEMENTSSUNPROC __glewMultiDrawElementsSUN = NULL;
+
+PFNGLBEGINPERFMONITORAMDPROC __glewBeginPerfMonitorAMD = NULL;
+PFNGLDELETEPERFMONITORSAMDPROC __glewDeletePerfMonitorsAMD = NULL;
+PFNGLENDPERFMONITORAMDPROC __glewEndPerfMonitorAMD = NULL;
+PFNGLGENPERFMONITORSAMDPROC __glewGenPerfMonitorsAMD = NULL;
+PFNGLGETPERFMONITORCOUNTERDATAAMDPROC __glewGetPerfMonitorCounterDataAMD = NULL;
+PFNGLGETPERFMONITORCOUNTERINFOAMDPROC __glewGetPerfMonitorCounterInfoAMD = NULL;
+PFNGLGETPERFMONITORCOUNTERSTRINGAMDPROC __glewGetPerfMonitorCounterStringAMD = NULL;
+PFNGLGETPERFMONITORCOUNTERSAMDPROC __glewGetPerfMonitorCountersAMD = NULL;
+PFNGLGETPERFMONITORGROUPSTRINGAMDPROC __glewGetPerfMonitorGroupStringAMD = NULL;
+PFNGLGETPERFMONITORGROUPSAMDPROC __glewGetPerfMonitorGroupsAMD = NULL;
+PFNGLSELECTPERFMONITORCOUNTERSAMDPROC __glewSelectPerfMonitorCountersAMD = NULL;
+
+PFNGLBLENDEQUATIONEXTPROC __glewBlendEquationEXT = NULL;
+
+PFNGLMULTIDRAWARRAYSEXTPROC __glewMultiDrawArraysEXT = NULL;
+PFNGLMULTIDRAWELEMENTSEXTPROC __glewMultiDrawElementsEXT = NULL;
+
+#if 0 // NOTE jwilkins: there is an inconsistency between the ES and Non-ES versions of this extension??
+PFNGLACTIVESHADERPROGRAMEXTPROC __glewActiveShaderProgramEXT = NULL;
+PFNGLBINDPROGRAMPIPELINEEXTPROC __glewBindProgramPipelineEXT = NULL;
+PFNGLCREATESHADERPROGRAMVEXTPROC __glewCreateShaderProgramvEXT = NULL;
+PFNGLDELETEPROGRAMPIPELINESEXTPROC __glewDeleteProgramPipelinesEXT = NULL;
+PFNGLGENPROGRAMPIPELINESEXTPROC __glewGenProgramPipelinesEXT = NULL;
+PFNGLGETPROGRAMPIPELINEINFOLOGEXTPROC __glewGetProgramPipelineInfoLogEXT = NULL;
+PFNGLGETPROGRAMPIPELINEIVEXTPROC __glewGetProgramPipelineivEXT = NULL;
+PFNGLISPROGRAMPIPELINEEXTPROC __glewIsProgramPipelineEXT = NULL;
+PFNGLPROGRAMPARAMETERIEXTPROC __glewProgramParameteriEXT = NULL;
+PFNGLPROGRAMUNIFORM1FEXTPROC __glewProgramUniform1fEXT = NULL;
+PFNGLPROGRAMUNIFORM1FVEXTPROC __glewProgramUniform1fvEXT = NULL;
+PFNGLPROGRAMUNIFORM1IEXTPROC __glewProgramUniform1iEXT = NULL;
+PFNGLPROGRAMUNIFORM1IVEXTPROC __glewProgramUniform1ivEXT = NULL;
+PFNGLPROGRAMUNIFORM2FEXTPROC __glewProgramUniform2fEXT = NULL;
+PFNGLPROGRAMUNIFORM2FVEXTPROC __glewProgramUniform2fvEXT = NULL;
+PFNGLPROGRAMUNIFORM2IEXTPROC __glewProgramUniform2iEXT = NULL;
+PFNGLPROGRAMUNIFORM2IVEXTPROC __glewProgramUniform2ivEXT = NULL;
+PFNGLPROGRAMUNIFORM3FEXTPROC __glewProgramUniform3fEXT = NULL;
+PFNGLPROGRAMUNIFORM3FVEXTPROC __glewProgramUniform3fvEXT = NULL;
+PFNGLPROGRAMUNIFORM3IEXTPROC __glewProgramUniform3iEXT = NULL;
+PFNGLPROGRAMUNIFORM3IVEXTPROC __glewProgramUniform3ivEXT = NULL;
+PFNGLPROGRAMUNIFORM4FEXTPROC __glewProgramUniform4fEXT = NULL;
+PFNGLPROGRAMUNIFORM4FVEXTPROC __glewProgramUniform4fvEXT = NULL;
+PFNGLPROGRAMUNIFORM4IEXTPROC __glewProgramUniform4iEXT = NULL;
+PFNGLPROGRAMUNIFORM4IVEXTPROC __glewProgramUniform4ivEXT = NULL;
+PFNGLPROGRAMUNIFORMMATRIX2FVEXTPROC __glewProgramUniformMatrix2fvEXT = NULL;
+PFNGLPROGRAMUNIFORMMATRIX3FVEXTPROC __glewProgramUniformMatrix3fvEXT = NULL;
+PFNGLPROGRAMUNIFORMMATRIX4FVEXTPROC __glewProgramUniformMatrix4fvEXT = NULL;
+PFNGLUSEPROGRAMSTAGESEXTPROC __glewUseProgramStagesEXT = NULL;
+PFNGLVALIDATEPROGRAMPIPELINEEXTPROC __glewValidateProgramPipelineEXT = NULL;
+#endif
+
+PFNGLDEBUGMESSAGECALLBACKPROC __glewDebugMessageCallback = NULL;
+PFNGLDEBUGMESSAGECONTROLPROC __glewDebugMessageControl = NULL;
+PFNGLDEBUGMESSAGEINSERTPROC __glewDebugMessageInsert = NULL;
+PFNGLGETDEBUGMESSAGELOGPROC __glewGetDebugMessageLog = NULL;
+PFNGLGETOBJECTLABELPROC __glewGetObjectLabel = NULL;
+PFNGLGETOBJECTPTRLABELPROC __glewGetObjectPtrLabel = NULL;
+PFNGLGETPOINTERVPROC __glewGetPointerv = NULL; // NOTE jwilkins: multiple defs
+PFNGLOBJECTLABELPROC __glewObjectLabel = NULL;
+PFNGLOBJECTPTRLABELPROC __glewObjectPtrLabel = NULL;
+PFNGLPOPDEBUGGROUPPROC __glewPopDebugGroup = NULL;
+PFNGLPUSHDEBUGGROUPPROC __glewPushDebugGroup = NULL;
+
+PFNGLDRAWTEXTURENVPROC __glewDrawTextureNV = NULL;
+
+PFNGLDELETEFENCESNVPROC __glewDeleteFencesNV = NULL;
+PFNGLFINISHFENCENVPROC __glewFinishFenceNV = NULL;
+PFNGLGENFENCESNVPROC __glewGenFencesNV = NULL;
+PFNGLGETFENCEIVNVPROC __glewGetFenceivNV = NULL;
+PFNGLISFENCENVPROC __glewIsFenceNV = NULL;
+PFNGLSETFENCENVPROC __glewSetFenceNV = NULL;
+PFNGLTESTFENCENVPROC __glewTestFenceNV = NULL;
+
+PFNGLCLEARDEPTHFOESPROC __glewClearDepthfOES = NULL;
+PFNGLCLIPPLANEFOESPROC __glewClipPlanefOES = NULL;
+PFNGLDEPTHRANGEFOESPROC __glewDepthRangefOES = NULL;
+PFNGLFRUSTUMFOESPROC __glewFrustumfOES = NULL;
+PFNGLGETCLIPPLANEFOESPROC __glewGetClipPlanefOES = NULL;
+PFNGLORTHOFOESPROC __glewOrthofOES = NULL;
+
+#endif /* GLEW_ES_ONLY */
+
+#endif /* !WIN32 || !GLEW_MX */
+
+#if !defined(GLEW_MX)
+
+#ifndef GLEW_ES_ONLY
+
+GLboolean __GLEW_VERSION_1_1 = GL_FALSE;
+GLboolean __GLEW_VERSION_1_2 = GL_FALSE;
+GLboolean __GLEW_VERSION_1_2_1 = GL_FALSE;
+GLboolean __GLEW_VERSION_1_3 = GL_FALSE;
+GLboolean __GLEW_VERSION_1_4 = GL_FALSE;
+GLboolean __GLEW_VERSION_1_5 = GL_FALSE;
+GLboolean __GLEW_VERSION_2_0 = GL_FALSE;
+GLboolean __GLEW_VERSION_2_1 = GL_FALSE;
+GLboolean __GLEW_VERSION_3_0 = GL_FALSE;
+GLboolean __GLEW_VERSION_3_1 = GL_FALSE;
+GLboolean __GLEW_VERSION_3_2 = GL_FALSE;
+GLboolean __GLEW_VERSION_3_3 = GL_FALSE;
+GLboolean __GLEW_VERSION_4_0 = GL_FALSE;
+GLboolean __GLEW_VERSION_4_1 = GL_FALSE;
+GLboolean __GLEW_VERSION_4_2 = GL_FALSE;
+GLboolean __GLEW_3DFX_multisample = GL_FALSE;
+GLboolean __GLEW_3DFX_tbuffer = GL_FALSE;
+GLboolean __GLEW_3DFX_texture_compression_FXT1 = GL_FALSE;
+GLboolean __GLEW_AMD_blend_minmax_factor = GL_FALSE;
+GLboolean __GLEW_AMD_conservative_depth = GL_FALSE;
+GLboolean __GLEW_AMD_debug_output = GL_FALSE;
+GLboolean __GLEW_AMD_depth_clamp_separate = GL_FALSE;
+GLboolean __GLEW_AMD_draw_buffers_blend = GL_FALSE;
+GLboolean __GLEW_AMD_multi_draw_indirect = GL_FALSE;
+GLboolean __GLEW_AMD_name_gen_delete = GL_FALSE;
+GLboolean __GLEW_AMD_performance_monitor = GL_FALSE;
+GLboolean __GLEW_AMD_pinned_memory = GL_FALSE;
+GLboolean __GLEW_AMD_query_buffer_object = GL_FALSE;
+GLboolean __GLEW_AMD_sample_positions = GL_FALSE;
+GLboolean __GLEW_AMD_seamless_cubemap_per_texture = GL_FALSE;
+GLboolean __GLEW_AMD_shader_stencil_export = GL_FALSE;
+GLboolean __GLEW_AMD_shader_trinary_minmax = GL_FALSE;
+GLboolean __GLEW_AMD_sparse_texture = GL_FALSE;
+GLboolean __GLEW_AMD_stencil_operation_extended = GL_FALSE;
+GLboolean __GLEW_AMD_texture_texture4 = GL_FALSE;
+GLboolean __GLEW_AMD_transform_feedback3_lines_triangles = GL_FALSE;
+GLboolean __GLEW_AMD_vertex_shader_layer = GL_FALSE;
+GLboolean __GLEW_AMD_vertex_shader_tessellator = GL_FALSE;
+GLboolean __GLEW_AMD_vertex_shader_viewport_index = GL_FALSE;
+GLboolean __GLEW_APPLE_aux_depth_stencil = GL_FALSE;
+GLboolean __GLEW_APPLE_client_storage = GL_FALSE;
+GLboolean __GLEW_APPLE_element_array = GL_FALSE;
+GLboolean __GLEW_APPLE_fence = GL_FALSE;
+GLboolean __GLEW_APPLE_float_pixels = GL_FALSE;
+GLboolean __GLEW_APPLE_flush_buffer_range = GL_FALSE;
+GLboolean __GLEW_APPLE_object_purgeable = GL_FALSE;
+GLboolean __GLEW_APPLE_pixel_buffer = GL_FALSE;
+GLboolean __GLEW_APPLE_rgb_422 = GL_FALSE;
+GLboolean __GLEW_APPLE_row_bytes = GL_FALSE;
+GLboolean __GLEW_APPLE_specular_vector = GL_FALSE;
+GLboolean __GLEW_APPLE_texture_range = GL_FALSE;
+GLboolean __GLEW_APPLE_transform_hint = GL_FALSE;
+GLboolean __GLEW_APPLE_vertex_array_object = GL_FALSE;
+GLboolean __GLEW_APPLE_vertex_array_range = GL_FALSE;
+GLboolean __GLEW_APPLE_vertex_program_evaluators = GL_FALSE;
+GLboolean __GLEW_APPLE_ycbcr_422 = GL_FALSE;
+GLboolean __GLEW_ARB_ES2_compatibility = GL_FALSE;
+GLboolean __GLEW_ARB_ES3_compatibility = GL_FALSE;
+GLboolean __GLEW_ARB_arrays_of_arrays = GL_FALSE;
+GLboolean __GLEW_ARB_base_instance = GL_FALSE;
+GLboolean __GLEW_ARB_blend_func_extended = GL_FALSE;
+GLboolean __GLEW_ARB_cl_event = GL_FALSE;
+GLboolean __GLEW_ARB_clear_buffer_object = GL_FALSE;
+GLboolean __GLEW_ARB_color_buffer_float = GL_FALSE;
+GLboolean __GLEW_ARB_compatibility = GL_FALSE;
+GLboolean __GLEW_ARB_compressed_texture_pixel_storage = GL_FALSE;
+GLboolean __GLEW_ARB_compute_shader = GL_FALSE;
+GLboolean __GLEW_ARB_conservative_depth = GL_FALSE;
+GLboolean __GLEW_ARB_copy_buffer = GL_FALSE;
+GLboolean __GLEW_ARB_copy_image = GL_FALSE;
+GLboolean __GLEW_ARB_debug_output = GL_FALSE;
+GLboolean __GLEW_ARB_depth_buffer_float = GL_FALSE;
+GLboolean __GLEW_ARB_depth_clamp = GL_FALSE;
+GLboolean __GLEW_ARB_depth_texture = GL_FALSE;
+GLboolean __GLEW_ARB_draw_buffers = GL_FALSE;
+GLboolean __GLEW_ARB_draw_buffers_blend = GL_FALSE;
+GLboolean __GLEW_ARB_draw_elements_base_vertex = GL_FALSE;
+GLboolean __GLEW_ARB_draw_indirect = GL_FALSE;
+GLboolean __GLEW_ARB_draw_instanced = GL_FALSE;
+GLboolean __GLEW_ARB_explicit_attrib_location = GL_FALSE;
+GLboolean __GLEW_ARB_explicit_uniform_location = GL_FALSE;
+GLboolean __GLEW_ARB_fragment_coord_conventions = GL_FALSE;
+GLboolean __GLEW_ARB_fragment_layer_viewport = GL_FALSE;
+GLboolean __GLEW_ARB_fragment_program = GL_FALSE;
+GLboolean __GLEW_ARB_fragment_program_shadow = GL_FALSE;
+GLboolean __GLEW_ARB_fragment_shader = GL_FALSE;
+GLboolean __GLEW_ARB_framebuffer_no_attachments = GL_FALSE;
+GLboolean __GLEW_ARB_framebuffer_object = GL_FALSE;
+GLboolean __GLEW_ARB_framebuffer_sRGB = GL_FALSE;
+GLboolean __GLEW_ARB_geometry_shader4 = GL_FALSE;
+GLboolean __GLEW_ARB_get_program_binary = GL_FALSE;
+GLboolean __GLEW_ARB_gpu_shader5 = GL_FALSE;
+GLboolean __GLEW_ARB_gpu_shader_fp64 = GL_FALSE;
+GLboolean __GLEW_ARB_half_float_pixel = GL_FALSE;
+GLboolean __GLEW_ARB_half_float_vertex = GL_FALSE;
+GLboolean __GLEW_ARB_imaging = GL_FALSE;
+GLboolean __GLEW_ARB_instanced_arrays = GL_FALSE;
+GLboolean __GLEW_ARB_internalformat_query = GL_FALSE;
+GLboolean __GLEW_ARB_internalformat_query2 = GL_FALSE;
+GLboolean __GLEW_ARB_invalidate_subdata = GL_FALSE;
+GLboolean __GLEW_ARB_map_buffer_alignment = GL_FALSE;
+GLboolean __GLEW_ARB_map_buffer_range = GL_FALSE;
+GLboolean __GLEW_ARB_matrix_palette = GL_FALSE;
+GLboolean __GLEW_ARB_multi_draw_indirect = GL_FALSE;
+GLboolean __GLEW_ARB_multisample = GL_FALSE;
+GLboolean __GLEW_ARB_multitexture = GL_FALSE;
+GLboolean __GLEW_ARB_occlusion_query = GL_FALSE;
+GLboolean __GLEW_ARB_occlusion_query2 = GL_FALSE;
+GLboolean __GLEW_ARB_pixel_buffer_object = GL_FALSE;
+GLboolean __GLEW_ARB_point_parameters = GL_FALSE;
+GLboolean __GLEW_ARB_point_sprite = GL_FALSE;
+GLboolean __GLEW_ARB_program_interface_query = GL_FALSE;
+GLboolean __GLEW_ARB_provoking_vertex = GL_FALSE;
+GLboolean __GLEW_ARB_robust_buffer_access_behavior = GL_FALSE;
+GLboolean __GLEW_ARB_robustness = GL_FALSE;
+GLboolean __GLEW_ARB_robustness_application_isolation = GL_FALSE;
+GLboolean __GLEW_ARB_robustness_share_group_isolation = GL_FALSE;
+GLboolean __GLEW_ARB_sample_shading = GL_FALSE;
+GLboolean __GLEW_ARB_sampler_objects = GL_FALSE;
+GLboolean __GLEW_ARB_seamless_cube_map = GL_FALSE;
+#if 0 // NOTE jwilkins: there is an inconsistency between the ES and Non-ES versions of this extension??
+GLboolean __GLEW_ARB_separate_shader_objects = GL_FALSE;
+#endif
+GLboolean __GLEW_ARB_shader_atomic_counters = GL_FALSE;
+GLboolean __GLEW_ARB_shader_bit_encoding = GL_FALSE;
+GLboolean __GLEW_ARB_shader_image_load_store = GL_FALSE;
+GLboolean __GLEW_ARB_shader_image_size = GL_FALSE;
+GLboolean __GLEW_ARB_shader_objects = GL_FALSE;
+GLboolean __GLEW_ARB_shader_precision = GL_FALSE;
+GLboolean __GLEW_ARB_shader_stencil_export = GL_FALSE;
+GLboolean __GLEW_ARB_shader_storage_buffer_object = GL_FALSE;
+GLboolean __GLEW_ARB_shader_subroutine = GL_FALSE;
+GLboolean __GLEW_ARB_shader_texture_lod = GL_FALSE;
+GLboolean __GLEW_ARB_shading_language_100 = GL_FALSE;
+GLboolean __GLEW_ARB_shading_language_420pack = GL_FALSE;
+GLboolean __GLEW_ARB_shading_language_include = GL_FALSE;
+GLboolean __GLEW_ARB_shading_language_packing = GL_FALSE;
+GLboolean __GLEW_ARB_shadow = GL_FALSE;
+GLboolean __GLEW_ARB_shadow_ambient = GL_FALSE;
+GLboolean __GLEW_ARB_stencil_texturing = GL_FALSE;
+GLboolean __GLEW_ARB_sync = GL_FALSE;
+GLboolean __GLEW_ARB_tessellation_shader = GL_FALSE;
+GLboolean __GLEW_ARB_texture_border_clamp = GL_FALSE;
+GLboolean __GLEW_ARB_texture_buffer_object = GL_FALSE;
+GLboolean __GLEW_ARB_texture_buffer_object_rgb32 = GL_FALSE;
+GLboolean __GLEW_ARB_texture_buffer_range = GL_FALSE;
+GLboolean __GLEW_ARB_texture_compression = GL_FALSE;
+GLboolean __GLEW_ARB_texture_compression_bptc = GL_FALSE;
+GLboolean __GLEW_ARB_texture_compression_rgtc = GL_FALSE;
+GLboolean __GLEW_ARB_texture_cube_map = GL_FALSE;
+GLboolean __GLEW_ARB_texture_cube_map_array = GL_FALSE;
+GLboolean __GLEW_ARB_texture_env_add = GL_FALSE;
+GLboolean __GLEW_ARB_texture_env_combine = GL_FALSE;
+GLboolean __GLEW_ARB_texture_env_crossbar = GL_FALSE;
+GLboolean __GLEW_ARB_texture_env_dot3 = GL_FALSE;
+GLboolean __GLEW_ARB_texture_float = GL_FALSE;
+GLboolean __GLEW_ARB_texture_gather = GL_FALSE;
+GLboolean __GLEW_ARB_texture_mirrored_repeat = GL_FALSE;
+GLboolean __GLEW_ARB_texture_multisample = GL_FALSE;
+GLboolean __GLEW_ARB_texture_non_power_of_two = GL_FALSE;
+GLboolean __GLEW_ARB_texture_query_levels = GL_FALSE;
+GLboolean __GLEW_ARB_texture_query_lod = GL_FALSE;
+GLboolean __GLEW_ARB_texture_rectangle = GL_FALSE;
+GLboolean __GLEW_ARB_texture_rg = GL_FALSE;
+GLboolean __GLEW_ARB_texture_rgb10_a2ui = GL_FALSE;
+GLboolean __GLEW_ARB_texture_storage = GL_FALSE;
+GLboolean __GLEW_ARB_texture_storage_multisample = GL_FALSE;
+GLboolean __GLEW_ARB_texture_swizzle = GL_FALSE;
+GLboolean __GLEW_ARB_texture_view = GL_FALSE;
+GLboolean __GLEW_ARB_timer_query = GL_FALSE;
+GLboolean __GLEW_ARB_transform_feedback2 = GL_FALSE;
+GLboolean __GLEW_ARB_transform_feedback3 = GL_FALSE;
+GLboolean __GLEW_ARB_transform_feedback_instanced = GL_FALSE;
+GLboolean __GLEW_ARB_transpose_matrix = GL_FALSE;
+GLboolean __GLEW_ARB_uniform_buffer_object = GL_FALSE;
+GLboolean __GLEW_ARB_vertex_array_bgra = GL_FALSE;
+GLboolean __GLEW_ARB_vertex_array_object = GL_FALSE;
+GLboolean __GLEW_ARB_vertex_attrib_64bit = GL_FALSE;
+GLboolean __GLEW_ARB_vertex_attrib_binding = GL_FALSE;
+GLboolean __GLEW_ARB_vertex_blend = GL_FALSE;
+GLboolean __GLEW_ARB_vertex_buffer_object = GL_FALSE;
+GLboolean __GLEW_ARB_vertex_program = GL_FALSE;
+GLboolean __GLEW_ARB_vertex_shader = GL_FALSE;
+GLboolean __GLEW_ARB_vertex_type_2_10_10_10_rev = GL_FALSE;
+GLboolean __GLEW_ARB_viewport_array = GL_FALSE;
+GLboolean __GLEW_ARB_window_pos = GL_FALSE;
+GLboolean __GLEW_ATIX_point_sprites = GL_FALSE;
+GLboolean __GLEW_ATIX_texture_env_combine3 = GL_FALSE;
+GLboolean __GLEW_ATIX_texture_env_route = GL_FALSE;
+GLboolean __GLEW_ATIX_vertex_shader_output_point_size = GL_FALSE;
+GLboolean __GLEW_ATI_draw_buffers = GL_FALSE;
+GLboolean __GLEW_ATI_element_array = GL_FALSE;
+GLboolean __GLEW_ATI_envmap_bumpmap = GL_FALSE;
+GLboolean __GLEW_ATI_fragment_shader = GL_FALSE;
+GLboolean __GLEW_ATI_map_object_buffer = GL_FALSE;
+GLboolean __GLEW_ATI_meminfo = GL_FALSE;
+GLboolean __GLEW_ATI_pn_triangles = GL_FALSE;
+GLboolean __GLEW_ATI_separate_stencil = GL_FALSE;
+GLboolean __GLEW_ATI_shader_texture_lod = GL_FALSE;
+GLboolean __GLEW_ATI_text_fragment_shader = GL_FALSE;
+GLboolean __GLEW_ATI_texture_compression_3dc = GL_FALSE;
+GLboolean __GLEW_ATI_texture_env_combine3 = GL_FALSE;
+GLboolean __GLEW_ATI_texture_float = GL_FALSE;
+GLboolean __GLEW_ATI_texture_mirror_once = GL_FALSE;
+GLboolean __GLEW_ATI_vertex_array_object = GL_FALSE;
+GLboolean __GLEW_ATI_vertex_attrib_array_object = GL_FALSE;
+GLboolean __GLEW_ATI_vertex_streams = GL_FALSE;
+GLboolean __GLEW_EXT_422_pixels = GL_FALSE;
+GLboolean __GLEW_EXT_Cg_shader = GL_FALSE;
+GLboolean __GLEW_EXT_abgr = GL_FALSE;
+GLboolean __GLEW_EXT_bgra = GL_FALSE;
+GLboolean __GLEW_EXT_bindable_uniform = GL_FALSE;
+GLboolean __GLEW_EXT_blend_color = GL_FALSE;
+GLboolean __GLEW_EXT_blend_equation_separate = GL_FALSE;
+GLboolean __GLEW_EXT_blend_func_separate = GL_FALSE;
+GLboolean __GLEW_EXT_blend_logic_op = GL_FALSE;
+GLboolean __GLEW_EXT_blend_minmax = GL_FALSE;
+GLboolean __GLEW_EXT_blend_subtract = GL_FALSE;
+GLboolean __GLEW_EXT_clip_volume_hint = GL_FALSE;
+GLboolean __GLEW_EXT_cmyka = GL_FALSE;
+GLboolean __GLEW_EXT_color_subtable = GL_FALSE;
+GLboolean __GLEW_EXT_compiled_vertex_array = GL_FALSE;
+GLboolean __GLEW_EXT_convolution = GL_FALSE;
+GLboolean __GLEW_EXT_coordinate_frame = GL_FALSE;
+GLboolean __GLEW_EXT_copy_texture = GL_FALSE;
+GLboolean __GLEW_EXT_cull_vertex = GL_FALSE;
+GLboolean __GLEW_EXT_depth_bounds_test = GL_FALSE;
+GLboolean __GLEW_EXT_direct_state_access = GL_FALSE;
+GLboolean __GLEW_EXT_draw_buffers2 = GL_FALSE;
+GLboolean __GLEW_EXT_draw_instanced = GL_FALSE;
+GLboolean __GLEW_EXT_draw_range_elements = GL_FALSE;
+GLboolean __GLEW_EXT_fog_coord = GL_FALSE;
+GLboolean __GLEW_EXT_fragment_lighting = GL_FALSE;
+GLboolean __GLEW_EXT_framebuffer_blit = GL_FALSE;
+GLboolean __GLEW_EXT_framebuffer_multisample = GL_FALSE;
+GLboolean __GLEW_EXT_framebuffer_multisample_blit_scaled = GL_FALSE;
+GLboolean __GLEW_EXT_framebuffer_object = GL_FALSE;
+GLboolean __GLEW_EXT_framebuffer_sRGB = GL_FALSE;
+GLboolean __GLEW_EXT_geometry_shader4 = GL_FALSE;
+GLboolean __GLEW_EXT_gpu_program_parameters = GL_FALSE;
+GLboolean __GLEW_EXT_gpu_shader4 = GL_FALSE;
+GLboolean __GLEW_EXT_histogram = GL_FALSE;
+GLboolean __GLEW_EXT_index_array_formats = GL_FALSE;
+GLboolean __GLEW_EXT_index_func = GL_FALSE;
+GLboolean __GLEW_EXT_index_material = GL_FALSE;
+GLboolean __GLEW_EXT_index_texture = GL_FALSE;
+GLboolean __GLEW_EXT_light_texture = GL_FALSE;
+GLboolean __GLEW_EXT_misc_attribute = GL_FALSE;
+GLboolean __GLEW_EXT_multi_draw_arrays = GL_FALSE;
+GLboolean __GLEW_EXT_multisample = GL_FALSE;
+GLboolean __GLEW_EXT_packed_depth_stencil = GL_FALSE;
+GLboolean __GLEW_EXT_packed_float = GL_FALSE;
+GLboolean __GLEW_EXT_packed_pixels = GL_FALSE;
+GLboolean __GLEW_EXT_paletted_texture = GL_FALSE;
+GLboolean __GLEW_EXT_pixel_buffer_object = GL_FALSE;
+GLboolean __GLEW_EXT_pixel_transform = GL_FALSE;
+GLboolean __GLEW_EXT_pixel_transform_color_table = GL_FALSE;
+GLboolean __GLEW_EXT_point_parameters = GL_FALSE;
+GLboolean __GLEW_EXT_polygon_offset = GL_FALSE;
+GLboolean __GLEW_EXT_provoking_vertex = GL_FALSE;
+GLboolean __GLEW_EXT_rescale_normal = GL_FALSE;
+GLboolean __GLEW_EXT_scene_marker = GL_FALSE;
+GLboolean __GLEW_EXT_secondary_color = GL_FALSE;
+#if 0 // NOTE jwilkins: there is an inconsistency between the ES and Non-ES versions of this extension??
+GLboolean __GLEW_EXT_separate_shader_objects = GL_FALSE;
+#endif
+GLboolean __GLEW_EXT_separate_specular_color = GL_FALSE;
+GLboolean __GLEW_EXT_shader_image_load_store = GL_FALSE;
+GLboolean __GLEW_EXT_shadow_funcs = GL_FALSE;
+GLboolean __GLEW_EXT_shared_texture_palette = GL_FALSE;
+GLboolean __GLEW_EXT_stencil_clear_tag = GL_FALSE;
+GLboolean __GLEW_EXT_stencil_two_side = GL_FALSE;
+GLboolean __GLEW_EXT_stencil_wrap = GL_FALSE;
+GLboolean __GLEW_EXT_subtexture = GL_FALSE;
+GLboolean __GLEW_EXT_texture = GL_FALSE;
+GLboolean __GLEW_EXT_texture3D = GL_FALSE;
+GLboolean __GLEW_EXT_texture_array = GL_FALSE;
+GLboolean __GLEW_EXT_texture_buffer_object = GL_FALSE;
+GLboolean __GLEW_EXT_texture_compression_dxt1 = GL_FALSE;
+GLboolean __GLEW_EXT_texture_compression_latc = GL_FALSE;
+GLboolean __GLEW_EXT_texture_compression_rgtc = GL_FALSE;
+GLboolean __GLEW_EXT_texture_compression_s3tc = GL_FALSE;
+GLboolean __GLEW_EXT_texture_cube_map = GL_FALSE;
+GLboolean __GLEW_EXT_texture_edge_clamp = GL_FALSE;
+GLboolean __GLEW_EXT_texture_env = GL_FALSE;
+GLboolean __GLEW_EXT_texture_env_add = GL_FALSE;
+GLboolean __GLEW_EXT_texture_env_combine = GL_FALSE;
+GLboolean __GLEW_EXT_texture_env_dot3 = GL_FALSE;
+GLboolean __GLEW_EXT_texture_filter_anisotropic = GL_FALSE;
+GLboolean __GLEW_EXT_texture_integer = GL_FALSE;
+GLboolean __GLEW_EXT_texture_lod_bias = GL_FALSE;
+GLboolean __GLEW_EXT_texture_mirror_clamp = GL_FALSE;
+GLboolean __GLEW_EXT_texture_object = GL_FALSE;
+GLboolean __GLEW_EXT_texture_perturb_normal = GL_FALSE;
+GLboolean __GLEW_EXT_texture_rectangle = GL_FALSE;
+GLboolean __GLEW_EXT_texture_sRGB = GL_FALSE;
+GLboolean __GLEW_EXT_texture_sRGB_decode = GL_FALSE;
+GLboolean __GLEW_EXT_texture_shared_exponent = GL_FALSE;
+GLboolean __GLEW_EXT_texture_snorm = GL_FALSE;
+GLboolean __GLEW_EXT_texture_swizzle = GL_FALSE;
+GLboolean __GLEW_EXT_timer_query = GL_FALSE;
+GLboolean __GLEW_EXT_transform_feedback = GL_FALSE;
+GLboolean __GLEW_EXT_vertex_array = GL_FALSE;
+GLboolean __GLEW_EXT_vertex_array_bgra = GL_FALSE;
+GLboolean __GLEW_EXT_vertex_attrib_64bit = GL_FALSE;
+GLboolean __GLEW_EXT_vertex_shader = GL_FALSE;
+GLboolean __GLEW_EXT_vertex_weighting = GL_FALSE;
+GLboolean __GLEW_EXT_x11_sync_object = GL_FALSE;
+GLboolean __GLEW_GREMEDY_frame_terminator = GL_FALSE;
+GLboolean __GLEW_GREMEDY_string_marker = GL_FALSE;
+GLboolean __GLEW_HP_convolution_border_modes = GL_FALSE;
+GLboolean __GLEW_HP_image_transform = GL_FALSE;
+GLboolean __GLEW_HP_occlusion_test = GL_FALSE;
+GLboolean __GLEW_HP_texture_lighting = GL_FALSE;
+GLboolean __GLEW_IBM_cull_vertex = GL_FALSE;
+GLboolean __GLEW_IBM_multimode_draw_arrays = GL_FALSE;
+GLboolean __GLEW_IBM_rasterpos_clip = GL_FALSE;
+GLboolean __GLEW_IBM_static_data = GL_FALSE;
+GLboolean __GLEW_IBM_texture_mirrored_repeat = GL_FALSE;
+GLboolean __GLEW_IBM_vertex_array_lists = GL_FALSE;
+GLboolean __GLEW_INGR_color_clamp = GL_FALSE;
+GLboolean __GLEW_INGR_interlace_read = GL_FALSE;
+GLboolean __GLEW_INTEL_map_texture = GL_FALSE;
+GLboolean __GLEW_INTEL_parallel_arrays = GL_FALSE;
+GLboolean __GLEW_INTEL_texture_scissor = GL_FALSE;
+GLboolean __GLEW_KHR_debug = GL_FALSE;
+GLboolean __GLEW_KHR_texture_compression_astc_ldr = GL_FALSE;
+GLboolean __GLEW_KTX_buffer_region = GL_FALSE;
+GLboolean __GLEW_MESAX_texture_stack = GL_FALSE;
+GLboolean __GLEW_MESA_pack_invert = GL_FALSE;
+GLboolean __GLEW_MESA_resize_buffers = GL_FALSE;
+GLboolean __GLEW_MESA_window_pos = GL_FALSE;
+GLboolean __GLEW_MESA_ycbcr_texture = GL_FALSE;
+GLboolean __GLEW_NVX_conditional_render = GL_FALSE;
+GLboolean __GLEW_NVX_gpu_memory_info = GL_FALSE;
+GLboolean __GLEW_NV_bindless_texture = GL_FALSE;
+GLboolean __GLEW_NV_blend_square = GL_FALSE;
+GLboolean __GLEW_NV_compute_program5 = GL_FALSE;
+GLboolean __GLEW_NV_conditional_render = GL_FALSE;
+GLboolean __GLEW_NV_copy_depth_to_color = GL_FALSE;
+GLboolean __GLEW_NV_copy_image = GL_FALSE;
+GLboolean __GLEW_NV_deep_texture3D = GL_FALSE;
+GLboolean __GLEW_NV_depth_buffer_float = GL_FALSE;
+GLboolean __GLEW_NV_depth_clamp = GL_FALSE;
+GLboolean __GLEW_NV_depth_range_unclamped = GL_FALSE;
+GLboolean __GLEW_NV_draw_texture = GL_FALSE;
+GLboolean __GLEW_NV_evaluators = GL_FALSE;
+GLboolean __GLEW_NV_explicit_multisample = GL_FALSE;
+GLboolean __GLEW_NV_fence = GL_FALSE;
+GLboolean __GLEW_NV_float_buffer = GL_FALSE;
+GLboolean __GLEW_NV_fog_distance = GL_FALSE;
+GLboolean __GLEW_NV_fragment_program = GL_FALSE;
+GLboolean __GLEW_NV_fragment_program2 = GL_FALSE;
+GLboolean __GLEW_NV_fragment_program4 = GL_FALSE;
+GLboolean __GLEW_NV_fragment_program_option = GL_FALSE;
+GLboolean __GLEW_NV_framebuffer_multisample_coverage = GL_FALSE;
+GLboolean __GLEW_NV_geometry_program4 = GL_FALSE;
+GLboolean __GLEW_NV_geometry_shader4 = GL_FALSE;
+GLboolean __GLEW_NV_gpu_program4 = GL_FALSE;
+GLboolean __GLEW_NV_gpu_program5 = GL_FALSE;
+GLboolean __GLEW_NV_gpu_program_fp64 = GL_FALSE;
+GLboolean __GLEW_NV_gpu_shader5 = GL_FALSE;
+GLboolean __GLEW_NV_half_float = GL_FALSE;
+GLboolean __GLEW_NV_light_max_exponent = GL_FALSE;
+GLboolean __GLEW_NV_multisample_coverage = GL_FALSE;
+GLboolean __GLEW_NV_multisample_filter_hint = GL_FALSE;
+GLboolean __GLEW_NV_occlusion_query = GL_FALSE;
+GLboolean __GLEW_NV_packed_depth_stencil = GL_FALSE;
+GLboolean __GLEW_NV_parameter_buffer_object = GL_FALSE;
+GLboolean __GLEW_NV_parameter_buffer_object2 = GL_FALSE;
+GLboolean __GLEW_NV_path_rendering = GL_FALSE;
+GLboolean __GLEW_NV_pixel_data_range = GL_FALSE;
+GLboolean __GLEW_NV_point_sprite = GL_FALSE;
+GLboolean __GLEW_NV_present_video = GL_FALSE;
+GLboolean __GLEW_NV_primitive_restart = GL_FALSE;
+GLboolean __GLEW_NV_register_combiners = GL_FALSE;
+GLboolean __GLEW_NV_register_combiners2 = GL_FALSE;
+GLboolean __GLEW_NV_shader_atomic_counters = GL_FALSE;
+GLboolean __GLEW_NV_shader_atomic_float = GL_FALSE;
+GLboolean __GLEW_NV_shader_buffer_load = GL_FALSE;
+GLboolean __GLEW_NV_shader_storage_buffer_object = GL_FALSE;
+GLboolean __GLEW_NV_tessellation_program5 = GL_FALSE;
+GLboolean __GLEW_NV_texgen_emboss = GL_FALSE;
+GLboolean __GLEW_NV_texgen_reflection = GL_FALSE;
+GLboolean __GLEW_NV_texture_barrier = GL_FALSE;
+GLboolean __GLEW_NV_texture_compression_vtc = GL_FALSE;
+GLboolean __GLEW_NV_texture_env_combine4 = GL_FALSE;
+GLboolean __GLEW_NV_texture_expand_normal = GL_FALSE;
+GLboolean __GLEW_NV_texture_multisample = GL_FALSE;
+GLboolean __GLEW_NV_texture_rectangle = GL_FALSE;
+GLboolean __GLEW_NV_texture_shader = GL_FALSE;
+GLboolean __GLEW_NV_texture_shader2 = GL_FALSE;
+GLboolean __GLEW_NV_texture_shader3 = GL_FALSE;
+GLboolean __GLEW_NV_transform_feedback = GL_FALSE;
+GLboolean __GLEW_NV_transform_feedback2 = GL_FALSE;
+GLboolean __GLEW_NV_vdpau_interop = GL_FALSE;
+GLboolean __GLEW_NV_vertex_array_range = GL_FALSE;
+GLboolean __GLEW_NV_vertex_array_range2 = GL_FALSE;
+GLboolean __GLEW_NV_vertex_attrib_integer_64bit = GL_FALSE;
+GLboolean __GLEW_NV_vertex_buffer_unified_memory = GL_FALSE;
+GLboolean __GLEW_NV_vertex_program = GL_FALSE;
+GLboolean __GLEW_NV_vertex_program1_1 = GL_FALSE;
+GLboolean __GLEW_NV_vertex_program2 = GL_FALSE;
+GLboolean __GLEW_NV_vertex_program2_option = GL_FALSE;
+GLboolean __GLEW_NV_vertex_program3 = GL_FALSE;
+GLboolean __GLEW_NV_vertex_program4 = GL_FALSE;
+GLboolean __GLEW_NV_video_capture = GL_FALSE;
+GLboolean __GLEW_OES_byte_coordinates = GL_FALSE;
+GLboolean __GLEW_OES_compressed_paletted_texture = GL_FALSE;
+GLboolean __GLEW_OES_read_format = GL_FALSE;
+GLboolean __GLEW_OES_single_precision = GL_FALSE;
+GLboolean __GLEW_OML_interlace = GL_FALSE;
+GLboolean __GLEW_OML_resample = GL_FALSE;
+GLboolean __GLEW_OML_subsample = GL_FALSE;
+GLboolean __GLEW_PGI_misc_hints = GL_FALSE;
+GLboolean __GLEW_PGI_vertex_hints = GL_FALSE;
+GLboolean __GLEW_REND_screen_coordinates = GL_FALSE;
+GLboolean __GLEW_S3_s3tc = GL_FALSE;
+GLboolean __GLEW_SGIS_color_range = GL_FALSE;
+GLboolean __GLEW_SGIS_detail_texture = GL_FALSE;
+GLboolean __GLEW_SGIS_fog_function = GL_FALSE;
+GLboolean __GLEW_SGIS_generate_mipmap = GL_FALSE;
+GLboolean __GLEW_SGIS_multisample = GL_FALSE;
+GLboolean __GLEW_SGIS_pixel_texture = GL_FALSE;
+GLboolean __GLEW_SGIS_point_line_texgen = GL_FALSE;
+GLboolean __GLEW_SGIS_sharpen_texture = GL_FALSE;
+GLboolean __GLEW_SGIS_texture4D = GL_FALSE;
+GLboolean __GLEW_SGIS_texture_border_clamp = GL_FALSE;
+GLboolean __GLEW_SGIS_texture_edge_clamp = GL_FALSE;
+GLboolean __GLEW_SGIS_texture_filter4 = GL_FALSE;
+GLboolean __GLEW_SGIS_texture_lod = GL_FALSE;
+GLboolean __GLEW_SGIS_texture_select = GL_FALSE;
+GLboolean __GLEW_SGIX_async = GL_FALSE;
+GLboolean __GLEW_SGIX_async_histogram = GL_FALSE;
+GLboolean __GLEW_SGIX_async_pixel = GL_FALSE;
+GLboolean __GLEW_SGIX_blend_alpha_minmax = GL_FALSE;
+GLboolean __GLEW_SGIX_clipmap = GL_FALSE;
+GLboolean __GLEW_SGIX_convolution_accuracy = GL_FALSE;
+GLboolean __GLEW_SGIX_depth_texture = GL_FALSE;
+GLboolean __GLEW_SGIX_flush_raster = GL_FALSE;
+GLboolean __GLEW_SGIX_fog_offset = GL_FALSE;
+GLboolean __GLEW_SGIX_fog_texture = GL_FALSE;
+GLboolean __GLEW_SGIX_fragment_specular_lighting = GL_FALSE;
+GLboolean __GLEW_SGIX_framezoom = GL_FALSE;
+GLboolean __GLEW_SGIX_interlace = GL_FALSE;
+GLboolean __GLEW_SGIX_ir_instrument1 = GL_FALSE;
+GLboolean __GLEW_SGIX_list_priority = GL_FALSE;
+GLboolean __GLEW_SGIX_pixel_texture = GL_FALSE;
+GLboolean __GLEW_SGIX_pixel_texture_bits = GL_FALSE;
+GLboolean __GLEW_SGIX_reference_plane = GL_FALSE;
+GLboolean __GLEW_SGIX_resample = GL_FALSE;
+GLboolean __GLEW_SGIX_shadow = GL_FALSE;
+GLboolean __GLEW_SGIX_shadow_ambient = GL_FALSE;
+GLboolean __GLEW_SGIX_sprite = GL_FALSE;
+GLboolean __GLEW_SGIX_tag_sample_buffer = GL_FALSE;
+GLboolean __GLEW_SGIX_texture_add_env = GL_FALSE;
+GLboolean __GLEW_SGIX_texture_coordinate_clamp = GL_FALSE;
+GLboolean __GLEW_SGIX_texture_lod_bias = GL_FALSE;
+GLboolean __GLEW_SGIX_texture_multi_buffer = GL_FALSE;
+GLboolean __GLEW_SGIX_texture_range = GL_FALSE;
+GLboolean __GLEW_SGIX_texture_scale_bias = GL_FALSE;
+GLboolean __GLEW_SGIX_vertex_preclip = GL_FALSE;
+GLboolean __GLEW_SGIX_vertex_preclip_hint = GL_FALSE;
+GLboolean __GLEW_SGIX_ycrcb = GL_FALSE;
+GLboolean __GLEW_SGI_color_matrix = GL_FALSE;
+GLboolean __GLEW_SGI_color_table = GL_FALSE;
+GLboolean __GLEW_SGI_texture_color_table = GL_FALSE;
+GLboolean __GLEW_SUNX_constant_data = GL_FALSE;
+GLboolean __GLEW_SUN_convolution_border_modes = GL_FALSE;
+GLboolean __GLEW_SUN_global_alpha = GL_FALSE;
+GLboolean __GLEW_SUN_mesh_array = GL_FALSE;
+GLboolean __GLEW_SUN_read_video_pixels = GL_FALSE;
+GLboolean __GLEW_SUN_slice_accum = GL_FALSE;
+GLboolean __GLEW_SUN_triangle_list = GL_FALSE;
+GLboolean __GLEW_SUN_vertex = GL_FALSE;
+GLboolean __GLEW_WIN_phong_shading = GL_FALSE;
+GLboolean __GLEW_WIN_specular_fog = GL_FALSE;
+GLboolean __GLEW_WIN_swap_hint = GL_FALSE;
+
+#if !defined(GLEW_NO_ES)
+
+GLboolean __GLEW_ES_VERSION_1_0 = GL_FALSE;
+GLboolean __GLEW_ES_VERSION_CL_1_1 = GL_FALSE;
+GLboolean __GLEW_ES_VERSION_CM_1_1 = GL_FALSE;
+GLboolean __GLEW_ES_VERSION_2_0 = GL_FALSE;
+GLboolean __GLEW_AMD_compressed_3DC_texture = GL_FALSE;
+GLboolean __GLEW_AMD_compressed_ATC_texture = GL_FALSE;
+GLboolean __GLEW_AMD_program_binary_Z400 = GL_FALSE;
+GLboolean __GLEW_ANGLE_framebuffer_blit = GL_FALSE;
+GLboolean __GLEW_ANGLE_framebuffer_multisample = GL_FALSE;
+GLboolean __GLEW_ANGLE_instanced_arrays = GL_FALSE;
+GLboolean __GLEW_ANGLE_pack_reverse_row_order = GL_FALSE;
+GLboolean __GLEW_ANGLE_texture_compression_dxt3 = GL_FALSE;
+GLboolean __GLEW_ANGLE_texture_compression_dxt5 = GL_FALSE;
+GLboolean __GLEW_ANGLE_texture_usage = GL_FALSE;
+GLboolean __GLEW_ANGLE_translated_shader_source = GL_FALSE;
+GLboolean __GLEW_APPLE_copy_texture_levels = GL_FALSE;
+GLboolean __GLEW_APPLE_framebuffer_multisample = GL_FALSE;
+GLboolean __GLEW_APPLE_sync = GL_FALSE;
+GLboolean __GLEW_APPLE_texture_2D_limited_npot = GL_FALSE;
+GLboolean __GLEW_APPLE_texture_format_BGRA8888 = GL_FALSE;
+GLboolean __GLEW_APPLE_texture_max_level = GL_FALSE;
+GLboolean __GLEW_ARM_mali_program_binary = GL_FALSE;
+GLboolean __GLEW_ARM_mali_shader_binary = GL_FALSE;
+GLboolean __GLEW_ARM_rgba8 = GL_FALSE;
+GLboolean __GLEW_DMP_shader_binary = GL_FALSE;
+GLboolean __GLEW_EXT_color_buffer_half_float = GL_FALSE;
+GLboolean __GLEW_EXT_debug_label = GL_FALSE;
+GLboolean __GLEW_EXT_debug_marker = GL_FALSE;
+GLboolean __GLEW_EXT_discard_framebuffer = GL_FALSE;
+GLboolean __GLEW_EXT_frag_depth = GL_FALSE;
+GLboolean __GLEW_EXT_map_buffer_range = GL_FALSE;
+GLboolean __GLEW_EXT_multisampled_render_to_texture = GL_FALSE;
+GLboolean __GLEW_EXT_multiview_draw_buffers = GL_FALSE;
+GLboolean __GLEW_EXT_occlusion_query_boolean = GL_FALSE;
+GLboolean __GLEW_EXT_read_format_bgra = GL_FALSE;
+GLboolean __GLEW_EXT_robustness = GL_FALSE;
+GLboolean __GLEW_EXT_sRGB = GL_FALSE;
+GLboolean __GLEW_EXT_shader_framebuffer_fetch = GL_FALSE;
+GLboolean __GLEW_EXT_shader_texture_lod = GL_FALSE;
+GLboolean __GLEW_EXT_shadow_samplers = GL_FALSE;
+GLboolean __GLEW_EXT_texture_format_BGRA8888 = GL_FALSE;
+GLboolean __GLEW_EXT_texture_rg = GL_FALSE;
+GLboolean __GLEW_EXT_texture_storage = GL_FALSE;
+GLboolean __GLEW_EXT_texture_type_2_10_10_10_REV = GL_FALSE;
+GLboolean __GLEW_EXT_unpack_subimage = GL_FALSE;
+GLboolean __GLEW_FJ_shader_binary_GCCSO = GL_FALSE;
+GLboolean __GLEW_IMG_multisampled_render_to_texture = GL_FALSE;
+GLboolean __GLEW_IMG_program_binary = GL_FALSE;
+GLboolean __GLEW_IMG_read_format = GL_FALSE;
+GLboolean __GLEW_IMG_shader_binary = GL_FALSE;
+GLboolean __GLEW_IMG_texture_compression_pvrtc = GL_FALSE;
+GLboolean __GLEW_IMG_texture_env_enhanced_fixed_function = GL_FALSE;
+GLboolean __GLEW_IMG_user_clip_plane = GL_FALSE;
+GLboolean __GLEW_NV_3dvision_settings = GL_FALSE;
+GLboolean __GLEW_NV_EGL_stream_consumer_external = GL_FALSE;
+GLboolean __GLEW_NV_bgr = GL_FALSE;
+GLboolean __GLEW_NV_coverage_sample = GL_FALSE;
+GLboolean __GLEW_NV_depth_nonlinear = GL_FALSE;
+GLboolean __GLEW_NV_draw_buffers = GL_FALSE;
+GLboolean __GLEW_NV_fbo_color_attachments = GL_FALSE;
+GLboolean __GLEW_NV_pack_subimage = GL_FALSE;
+GLboolean __GLEW_NV_packed_float = GL_FALSE;
+GLboolean __GLEW_NV_packed_float_linear = GL_FALSE;
+GLboolean __GLEW_NV_pixel_buffer_object = GL_FALSE;
+GLboolean __GLEW_NV_platform_binary = GL_FALSE;
+GLboolean __GLEW_NV_read_buffer = GL_FALSE;
+GLboolean __GLEW_NV_read_buffer_front = GL_FALSE;
+GLboolean __GLEW_NV_read_depth = GL_FALSE;
+GLboolean __GLEW_NV_read_depth_stencil = GL_FALSE;
+GLboolean __GLEW_NV_read_stencil = GL_FALSE;
+GLboolean __GLEW_NV_texture_array = GL_FALSE;
+GLboolean __GLEW_NV_texture_compression_latc = GL_FALSE;
+GLboolean __GLEW_NV_texture_compression_s3tc = GL_FALSE;
+GLboolean __GLEW_NV_texture_compression_s3tc_update = GL_FALSE;
+GLboolean __GLEW_NV_texture_npot_2D_mipmap = GL_FALSE;
+GLboolean __GLEW_OES_EGL_image = GL_FALSE;
+GLboolean __GLEW_OES_EGL_image_external = GL_FALSE;
+GLboolean __GLEW_OES_EGL_sync = GL_FALSE;
+GLboolean __GLEW_OES_blend_equation_separate = GL_FALSE;
+GLboolean __GLEW_OES_blend_func_separate = GL_FALSE;
+GLboolean __GLEW_OES_blend_subtract = GL_FALSE;
+GLboolean __GLEW_OES_compressed_ETC1_RGB8_texture = GL_FALSE;
+GLboolean __GLEW_OES_depth24 = GL_FALSE;
+GLboolean __GLEW_OES_depth32 = GL_FALSE;
+GLboolean __GLEW_OES_depth_texture = GL_FALSE;
+GLboolean __GLEW_OES_depth_texture_cube_map = GL_FALSE;
+GLboolean __GLEW_OES_draw_texture = GL_FALSE;
+GLboolean __GLEW_OES_element_index_uint = GL_FALSE;
+GLboolean __GLEW_OES_extended_matrix_palette = GL_FALSE;
+GLboolean __GLEW_OES_fbo_render_mipmap = GL_FALSE;
+GLboolean __GLEW_OES_fragment_precision_high = GL_FALSE;
+GLboolean __GLEW_OES_framebuffer_object = GL_FALSE;
+GLboolean __GLEW_OES_get_program_binary = GL_FALSE;
+GLboolean __GLEW_OES_mapbuffer = GL_FALSE;
+GLboolean __GLEW_OES_matrix_get = GL_FALSE;
+GLboolean __GLEW_OES_matrix_palette = GL_FALSE;
+GLboolean __GLEW_OES_packed_depth_stencil = GL_FALSE;
+GLboolean __GLEW_OES_point_size_array = GL_FALSE;
+GLboolean __GLEW_OES_point_sprite = GL_FALSE;
+GLboolean __GLEW_OES_required_internalformat = GL_FALSE;
+GLboolean __GLEW_OES_rgb8_rgba8 = GL_FALSE;
+GLboolean __GLEW_OES_standard_derivatives = GL_FALSE;
+GLboolean __GLEW_OES_stencil1 = GL_FALSE;
+GLboolean __GLEW_OES_stencil4 = GL_FALSE;
+GLboolean __GLEW_OES_stencil8 = GL_FALSE;
+GLboolean __GLEW_OES_surfaceless_context = GL_FALSE;
+GLboolean __GLEW_OES_texture_3D = GL_FALSE;
+GLboolean __GLEW_OES_texture_cube_map = GL_FALSE;
+GLboolean __GLEW_OES_texture_env_crossbar = GL_FALSE;
+GLboolean __GLEW_OES_texture_mirrored_repeat = GL_FALSE;
+GLboolean __GLEW_OES_texture_npot = GL_FALSE;
+GLboolean __GLEW_OES_vertex_array_object = GL_FALSE;
+GLboolean __GLEW_OES_vertex_half_float = GL_FALSE;
+GLboolean __GLEW_OES_vertex_type_10_10_10_2 = GL_FALSE;
+GLboolean __GLEW_QCOM_alpha_test = GL_FALSE;
+GLboolean __GLEW_QCOM_binning_control = GL_FALSE;
+GLboolean __GLEW_QCOM_driver_control = GL_FALSE;
+GLboolean __GLEW_QCOM_extended_get = GL_FALSE;
+GLboolean __GLEW_QCOM_extended_get2 = GL_FALSE;
+GLboolean __GLEW_QCOM_perfmon_global_mode = GL_FALSE;
+GLboolean __GLEW_QCOM_tiled_rendering = GL_FALSE;
+GLboolean __GLEW_QCOM_writeonly_rendering = GL_FALSE;
+GLboolean __GLEW_SUN_multi_draw_arrays = GL_FALSE;
+GLboolean __GLEW_VG_KHR_EGL_sync = GL_FALSE;
+GLboolean __GLEW_VIV_shader_binary = GL_FALSE;
+
+#endif /* !(GLEW_NO_ES) */
+
+#else
+
+GLboolean __GLEW_ES_VERSION_1_0 = GL_FALSE;
+GLboolean __GLEW_ES_VERSION_CL_1_1 = GL_FALSE;
+GLboolean __GLEW_ES_VERSION_CM_1_1 = GL_FALSE;
+GLboolean __GLEW_ES_VERSION_2_0 = GL_FALSE;
+GLboolean __GLEW_AMD_compressed_3DC_texture = GL_FALSE;
+GLboolean __GLEW_AMD_compressed_ATC_texture = GL_FALSE;
+GLboolean __GLEW_AMD_program_binary_Z400 = GL_FALSE;
+GLboolean __GLEW_ANGLE_framebuffer_blit = GL_FALSE;
+GLboolean __GLEW_ANGLE_framebuffer_multisample = GL_FALSE;
+GLboolean __GLEW_ANGLE_instanced_arrays = GL_FALSE;
+GLboolean __GLEW_ANGLE_pack_reverse_row_order = GL_FALSE;
+GLboolean __GLEW_ANGLE_texture_compression_dxt3 = GL_FALSE;
+GLboolean __GLEW_ANGLE_texture_compression_dxt5 = GL_FALSE;
+GLboolean __GLEW_ANGLE_texture_usage = GL_FALSE;
+GLboolean __GLEW_ANGLE_translated_shader_source = GL_FALSE;
+GLboolean __GLEW_APPLE_copy_texture_levels = GL_FALSE;
+GLboolean __GLEW_APPLE_framebuffer_multisample = GL_FALSE;
+GLboolean __GLEW_APPLE_sync = GL_FALSE;
+GLboolean __GLEW_APPLE_texture_2D_limited_npot = GL_FALSE;
+GLboolean __GLEW_APPLE_texture_format_BGRA8888 = GL_FALSE;
+GLboolean __GLEW_APPLE_texture_max_level = GL_FALSE;
+GLboolean __GLEW_ARM_mali_program_binary = GL_FALSE;
+GLboolean __GLEW_ARM_mali_shader_binary = GL_FALSE;
+GLboolean __GLEW_ARM_rgba8 = GL_FALSE;
+GLboolean __GLEW_DMP_shader_binary = GL_FALSE;
+GLboolean __GLEW_EXT_color_buffer_half_float = GL_FALSE;
+GLboolean __GLEW_EXT_debug_label = GL_FALSE;
+GLboolean __GLEW_EXT_debug_marker = GL_FALSE;
+GLboolean __GLEW_EXT_discard_framebuffer = GL_FALSE;
+GLboolean __GLEW_EXT_frag_depth = GL_FALSE;
+GLboolean __GLEW_EXT_map_buffer_range = GL_FALSE;
+GLboolean __GLEW_EXT_multisampled_render_to_texture = GL_FALSE;
+GLboolean __GLEW_EXT_multiview_draw_buffers = GL_FALSE;
+GLboolean __GLEW_EXT_occlusion_query_boolean = GL_FALSE;
+GLboolean __GLEW_EXT_read_format_bgra = GL_FALSE;
+GLboolean __GLEW_EXT_robustness = GL_FALSE;
+GLboolean __GLEW_EXT_sRGB = GL_FALSE;
+GLboolean __GLEW_EXT_shader_framebuffer_fetch = GL_FALSE;
+GLboolean __GLEW_EXT_shader_texture_lod = GL_FALSE;
+GLboolean __GLEW_EXT_shadow_samplers = GL_FALSE;
+GLboolean __GLEW_EXT_texture_format_BGRA8888 = GL_FALSE;
+GLboolean __GLEW_EXT_texture_rg = GL_FALSE;
+GLboolean __GLEW_EXT_texture_storage = GL_FALSE;
+GLboolean __GLEW_EXT_texture_type_2_10_10_10_REV = GL_FALSE;
+GLboolean __GLEW_EXT_unpack_subimage = GL_FALSE;
+GLboolean __GLEW_FJ_shader_binary_GCCSO = GL_FALSE;
+GLboolean __GLEW_IMG_multisampled_render_to_texture = GL_FALSE;
+GLboolean __GLEW_IMG_program_binary = GL_FALSE;
+GLboolean __GLEW_IMG_read_format = GL_FALSE;
+GLboolean __GLEW_IMG_shader_binary = GL_FALSE;
+GLboolean __GLEW_IMG_texture_compression_pvrtc = GL_FALSE;
+GLboolean __GLEW_IMG_texture_env_enhanced_fixed_function = GL_FALSE;
+GLboolean __GLEW_IMG_user_clip_plane = GL_FALSE;
+GLboolean __GLEW_NV_3dvision_settings = GL_FALSE;
+GLboolean __GLEW_NV_EGL_stream_consumer_external = GL_FALSE;
+GLboolean __GLEW_NV_bgr = GL_FALSE;
+GLboolean __GLEW_NV_coverage_sample = GL_FALSE;
+GLboolean __GLEW_NV_depth_nonlinear = GL_FALSE;
+GLboolean __GLEW_NV_draw_buffers = GL_FALSE;
+GLboolean __GLEW_NV_fbo_color_attachments = GL_FALSE;
+GLboolean __GLEW_NV_pack_subimage = GL_FALSE;
+GLboolean __GLEW_NV_packed_float = GL_FALSE;
+GLboolean __GLEW_NV_packed_float_linear = GL_FALSE;
+GLboolean __GLEW_NV_pixel_buffer_object = GL_FALSE;
+GLboolean __GLEW_NV_platform_binary = GL_FALSE;
+GLboolean __GLEW_NV_read_buffer = GL_FALSE;
+GLboolean __GLEW_NV_read_buffer_front = GL_FALSE;
+GLboolean __GLEW_NV_read_depth = GL_FALSE;
+GLboolean __GLEW_NV_read_depth_stencil = GL_FALSE;
+GLboolean __GLEW_NV_read_stencil = GL_FALSE;
+GLboolean __GLEW_NV_texture_array = GL_FALSE;
+GLboolean __GLEW_NV_texture_compression_latc = GL_FALSE;
+GLboolean __GLEW_NV_texture_compression_s3tc = GL_FALSE;
+GLboolean __GLEW_NV_texture_compression_s3tc_update = GL_FALSE;
+GLboolean __GLEW_NV_texture_npot_2D_mipmap = GL_FALSE;
+GLboolean __GLEW_OES_EGL_image = GL_FALSE;
+GLboolean __GLEW_OES_EGL_image_external = GL_FALSE;
+GLboolean __GLEW_OES_EGL_sync = GL_FALSE;
+GLboolean __GLEW_OES_blend_equation_separate = GL_FALSE;
+GLboolean __GLEW_OES_blend_func_separate = GL_FALSE;
+GLboolean __GLEW_OES_blend_subtract = GL_FALSE;
+GLboolean __GLEW_OES_compressed_ETC1_RGB8_texture = GL_FALSE;
+GLboolean __GLEW_OES_depth24 = GL_FALSE;
+GLboolean __GLEW_OES_depth32 = GL_FALSE;
+GLboolean __GLEW_OES_depth_texture = GL_FALSE;
+GLboolean __GLEW_OES_depth_texture_cube_map = GL_FALSE;
+GLboolean __GLEW_OES_draw_texture = GL_FALSE;
+GLboolean __GLEW_OES_element_index_uint = GL_FALSE;
+GLboolean __GLEW_OES_extended_matrix_palette = GL_FALSE;
+GLboolean __GLEW_OES_fbo_render_mipmap = GL_FALSE;
+GLboolean __GLEW_OES_fragment_precision_high = GL_FALSE;
+GLboolean __GLEW_OES_framebuffer_object = GL_FALSE;
+GLboolean __GLEW_OES_get_program_binary = GL_FALSE;
+GLboolean __GLEW_OES_mapbuffer = GL_FALSE;
+GLboolean __GLEW_OES_matrix_get = GL_FALSE;
+GLboolean __GLEW_OES_matrix_palette = GL_FALSE;
+GLboolean __GLEW_OES_packed_depth_stencil = GL_FALSE;
+GLboolean __GLEW_OES_point_size_array = GL_FALSE;
+GLboolean __GLEW_OES_point_sprite = GL_FALSE;
+GLboolean __GLEW_OES_required_internalformat = GL_FALSE;
+GLboolean __GLEW_OES_rgb8_rgba8 = GL_FALSE;
+GLboolean __GLEW_OES_standard_derivatives = GL_FALSE;
+GLboolean __GLEW_OES_stencil1 = GL_FALSE;
+GLboolean __GLEW_OES_stencil4 = GL_FALSE;
+GLboolean __GLEW_OES_stencil8 = GL_FALSE;
+GLboolean __GLEW_OES_surfaceless_context = GL_FALSE;
+GLboolean __GLEW_OES_texture_3D = GL_FALSE;
+GLboolean __GLEW_OES_texture_cube_map = GL_FALSE;
+GLboolean __GLEW_OES_texture_env_crossbar = GL_FALSE;
+GLboolean __GLEW_OES_texture_mirrored_repeat = GL_FALSE;
+GLboolean __GLEW_OES_texture_npot = GL_FALSE;
+GLboolean __GLEW_OES_vertex_array_object = GL_FALSE;
+GLboolean __GLEW_OES_vertex_half_float = GL_FALSE;
+GLboolean __GLEW_OES_vertex_type_10_10_10_2 = GL_FALSE;
+GLboolean __GLEW_QCOM_alpha_test = GL_FALSE;
+GLboolean __GLEW_QCOM_binning_control = GL_FALSE;
+GLboolean __GLEW_QCOM_driver_control = GL_FALSE;
+GLboolean __GLEW_QCOM_extended_get = GL_FALSE;
+GLboolean __GLEW_QCOM_extended_get2 = GL_FALSE;
+GLboolean __GLEW_QCOM_perfmon_global_mode = GL_FALSE;
+GLboolean __GLEW_QCOM_tiled_rendering = GL_FALSE;
+GLboolean __GLEW_QCOM_writeonly_rendering = GL_FALSE;
+GLboolean __GLEW_SUN_multi_draw_arrays = GL_FALSE;
+GLboolean __GLEW_VG_KHR_EGL_sync = GL_FALSE;
+GLboolean __GLEW_VIV_shader_binary = GL_FALSE;
+GLboolean __GLEW_AMD_performance_monitor = GL_FALSE;
+GLboolean __GLEW_APPLE_rgb_422 = GL_FALSE;
+GLboolean __GLEW_EXT_blend_minmax = GL_FALSE;
+GLboolean __GLEW_EXT_multi_draw_arrays = GL_FALSE;
+#if 0 // NOTE jwilkins: there is an inconsistency between the ES and Non-ES versions of this extension??
+GLboolean __GLEW_EXT_separate_shader_objects = GL_FALSE;
+#endif // XXX
+GLboolean __GLEW_EXT_texture_compression_dxt1 = GL_FALSE;
+GLboolean __GLEW_EXT_texture_filter_anisotropic = GL_FALSE;
+GLboolean __GLEW_EXT_texture_lod_bias = GL_FALSE;
+GLboolean __GLEW_KHR_debug = GL_FALSE;
+GLboolean __GLEW_KHR_texture_compression_astc_ldr = GL_FALSE;
+GLboolean __GLEW_NV_draw_texture = GL_FALSE;
+GLboolean __GLEW_NV_fence = GL_FALSE;
+GLboolean __GLEW_OES_byte_coordinates = GL_FALSE;
+GLboolean __GLEW_OES_compressed_paletted_texture = GL_FALSE;
+GLboolean __GLEW_OES_read_format = GL_FALSE;
+GLboolean __GLEW_OES_single_precision = GL_FALSE;
+
+#endif /* GLEW_ES_ONLY */
+
+#endif /* !GLEW_MX */
+
+#ifdef GL_VERSION_1_1
+
+static GLboolean _glewInit_GL_VERSION_1_1 (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glAccum = (PFNGLACCUMPROC)glewGetProcAddress((const GLubyte*)"glAccum")) == NULL) || r;
+ r = ((glAreTexturesResident = (PFNGLARETEXTURESRESIDENTPROC)glewGetProcAddress((const GLubyte*)"glAreTexturesResident")) == NULL) || r;
+ r = ((glArrayElement = (PFNGLARRAYELEMENTPROC)glewGetProcAddress((const GLubyte*)"glArrayElement")) == NULL) || r;
+ r = ((glBegin = (PFNGLBEGINPROC)glewGetProcAddress((const GLubyte*)"glBegin")) == NULL) || r;
+ r = ((glBitmap = (PFNGLBITMAPPROC)glewGetProcAddress((const GLubyte*)"glBitmap")) == NULL) || r;
+ r = ((glCallList = (PFNGLCALLLISTPROC)glewGetProcAddress((const GLubyte*)"glCallList")) == NULL) || r;
+ r = ((glCallLists = (PFNGLCALLLISTSPROC)glewGetProcAddress((const GLubyte*)"glCallLists")) == NULL) || r;
+ r = ((glClearAccum = (PFNGLCLEARACCUMPROC)glewGetProcAddress((const GLubyte*)"glClearAccum")) == NULL) || r;
+ r = ((glClearDepth = (PFNGLCLEARDEPTHPROC)glewGetProcAddress((const GLubyte*)"glClearDepth")) == NULL) || r;
+ r = ((glClearIndex = (PFNGLCLEARINDEXPROC)glewGetProcAddress((const GLubyte*)"glClearIndex")) == NULL) || r;
+ r = ((glClipPlane = (PFNGLCLIPPLANEPROC)glewGetProcAddress((const GLubyte*)"glClipPlane")) == NULL) || r;
+ r = ((glColor3b = (PFNGLCOLOR3BPROC)glewGetProcAddress((const GLubyte*)"glColor3b")) == NULL) || r;
+ r = ((glColor3bv = (PFNGLCOLOR3BVPROC)glewGetProcAddress((const GLubyte*)"glColor3bv")) == NULL) || r;
+ r = ((glColor3d = (PFNGLCOLOR3DPROC)glewGetProcAddress((const GLubyte*)"glColor3d")) == NULL) || r;
+ r = ((glColor3dv = (PFNGLCOLOR3DVPROC)glewGetProcAddress((const GLubyte*)"glColor3dv")) == NULL) || r;
+ r = ((glColor3f = (PFNGLCOLOR3FPROC)glewGetProcAddress((const GLubyte*)"glColor3f")) == NULL) || r;
+ r = ((glColor3fv = (PFNGLCOLOR3FVPROC)glewGetProcAddress((const GLubyte*)"glColor3fv")) == NULL) || r;
+ r = ((glColor3i = (PFNGLCOLOR3IPROC)glewGetProcAddress((const GLubyte*)"glColor3i")) == NULL) || r;
+ r = ((glColor3iv = (PFNGLCOLOR3IVPROC)glewGetProcAddress((const GLubyte*)"glColor3iv")) == NULL) || r;
+ r = ((glColor3s = (PFNGLCOLOR3SPROC)glewGetProcAddress((const GLubyte*)"glColor3s")) == NULL) || r;
+ r = ((glColor3sv = (PFNGLCOLOR3SVPROC)glewGetProcAddress((const GLubyte*)"glColor3sv")) == NULL) || r;
+ r = ((glColor3ub = (PFNGLCOLOR3UBPROC)glewGetProcAddress((const GLubyte*)"glColor3ub")) == NULL) || r;
+ r = ((glColor3ubv = (PFNGLCOLOR3UBVPROC)glewGetProcAddress((const GLubyte*)"glColor3ubv")) == NULL) || r;
+ r = ((glColor3ui = (PFNGLCOLOR3UIPROC)glewGetProcAddress((const GLubyte*)"glColor3ui")) == NULL) || r;
+ r = ((glColor3uiv = (PFNGLCOLOR3UIVPROC)glewGetProcAddress((const GLubyte*)"glColor3uiv")) == NULL) || r;
+ r = ((glColor3us = (PFNGLCOLOR3USPROC)glewGetProcAddress((const GLubyte*)"glColor3us")) == NULL) || r;
+ r = ((glColor3usv = (PFNGLCOLOR3USVPROC)glewGetProcAddress((const GLubyte*)"glColor3usv")) == NULL) || r;
+ r = ((glColor4b = (PFNGLCOLOR4BPROC)glewGetProcAddress((const GLubyte*)"glColor4b")) == NULL) || r;
+ r = ((glColor4bv = (PFNGLCOLOR4BVPROC)glewGetProcAddress((const GLubyte*)"glColor4bv")) == NULL) || r;
+ r = ((glColor4d = (PFNGLCOLOR4DPROC)glewGetProcAddress((const GLubyte*)"glColor4d")) == NULL) || r;
+ r = ((glColor4dv = (PFNGLCOLOR4DVPROC)glewGetProcAddress((const GLubyte*)"glColor4dv")) == NULL) || r;
+ r = ((glColor4fv = (PFNGLCOLOR4FVPROC)glewGetProcAddress((const GLubyte*)"glColor4fv")) == NULL) || r;
+ r = ((glColor4i = (PFNGLCOLOR4IPROC)glewGetProcAddress((const GLubyte*)"glColor4i")) == NULL) || r;
+ r = ((glColor4iv = (PFNGLCOLOR4IVPROC)glewGetProcAddress((const GLubyte*)"glColor4iv")) == NULL) || r;
+ r = ((glColor4s = (PFNGLCOLOR4SPROC)glewGetProcAddress((const GLubyte*)"glColor4s")) == NULL) || r;
+ r = ((glColor4sv = (PFNGLCOLOR4SVPROC)glewGetProcAddress((const GLubyte*)"glColor4sv")) == NULL) || r;
+ r = ((glColor4ub = (PFNGLCOLOR4UBPROC)glewGetProcAddress((const GLubyte*)"glColor4ub")) == NULL) || r;
+ r = ((glColor4ubv = (PFNGLCOLOR4UBVPROC)glewGetProcAddress((const GLubyte*)"glColor4ubv")) == NULL) || r;
+ r = ((glColor4ui = (PFNGLCOLOR4UIPROC)glewGetProcAddress((const GLubyte*)"glColor4ui")) == NULL) || r;
+ r = ((glColor4uiv = (PFNGLCOLOR4UIVPROC)glewGetProcAddress((const GLubyte*)"glColor4uiv")) == NULL) || r;
+ r = ((glColor4us = (PFNGLCOLOR4USPROC)glewGetProcAddress((const GLubyte*)"glColor4us")) == NULL) || r;
+ r = ((glColor4usv = (PFNGLCOLOR4USVPROC)glewGetProcAddress((const GLubyte*)"glColor4usv")) == NULL) || r;
+ r = ((glColorMaterial = (PFNGLCOLORMATERIALPROC)glewGetProcAddress((const GLubyte*)"glColorMaterial")) == NULL) || r;
+ r = ((glCopyPixels = (PFNGLCOPYPIXELSPROC)glewGetProcAddress((const GLubyte*)"glCopyPixels")) == NULL) || r;
+ r = ((glCopyTexImage1D = (PFNGLCOPYTEXIMAGE1DPROC)glewGetProcAddress((const GLubyte*)"glCopyTexImage1D")) == NULL) || r;
+ r = ((glCopyTexSubImage1D = (PFNGLCOPYTEXSUBIMAGE1DPROC)glewGetProcAddress((const GLubyte*)"glCopyTexSubImage1D")) == NULL) || r;
+ r = ((glDeleteLists = (PFNGLDELETELISTSPROC)glewGetProcAddress((const GLubyte*)"glDeleteLists")) == NULL) || r;
+ r = ((glDepthRange = (PFNGLDEPTHRANGEPROC)glewGetProcAddress((const GLubyte*)"glDepthRange")) == NULL) || r;
+ r = ((glDrawBuffer = (PFNGLDRAWBUFFERPROC)glewGetProcAddress((const GLubyte*)"glDrawBuffer")) == NULL) || r;
+ r = ((glDrawPixels = (PFNGLDRAWPIXELSPROC)glewGetProcAddress((const GLubyte*)"glDrawPixels")) == NULL) || r;
+ r = ((glEdgeFlag = (PFNGLEDGEFLAGPROC)glewGetProcAddress((const GLubyte*)"glEdgeFlag")) == NULL) || r;
+ r = ((glEdgeFlagPointer = (PFNGLEDGEFLAGPOINTERPROC)glewGetProcAddress((const GLubyte*)"glEdgeFlagPointer")) == NULL) || r;
+ r = ((glEdgeFlagv = (PFNGLEDGEFLAGVPROC)glewGetProcAddress((const GLubyte*)"glEdgeFlagv")) == NULL) || r;
+ r = ((glEnd = (PFNGLENDPROC)glewGetProcAddress((const GLubyte*)"glEnd")) == NULL) || r;
+ r = ((glEndList = (PFNGLENDLISTPROC)glewGetProcAddress((const GLubyte*)"glEndList")) == NULL) || r;
+ r = ((glEvalCoord1d = (PFNGLEVALCOORD1DPROC)glewGetProcAddress((const GLubyte*)"glEvalCoord1d")) == NULL) || r;
+ r = ((glEvalCoord1dv = (PFNGLEVALCOORD1DVPROC)glewGetProcAddress((const GLubyte*)"glEvalCoord1dv")) == NULL) || r;
+ r = ((glEvalCoord1f = (PFNGLEVALCOORD1FPROC)glewGetProcAddress((const GLubyte*)"glEvalCoord1f")) == NULL) || r;
+ r = ((glEvalCoord1fv = (PFNGLEVALCOORD1FVPROC)glewGetProcAddress((const GLubyte*)"glEvalCoord1fv")) == NULL) || r;
+ r = ((glEvalCoord2d = (PFNGLEVALCOORD2DPROC)glewGetProcAddress((const GLubyte*)"glEvalCoord2d")) == NULL) || r;
+ r = ((glEvalCoord2dv = (PFNGLEVALCOORD2DVPROC)glewGetProcAddress((const GLubyte*)"glEvalCoord2dv")) == NULL) || r;
+ r = ((glEvalCoord2f = (PFNGLEVALCOORD2FPROC)glewGetProcAddress((const GLubyte*)"glEvalCoord2f")) == NULL) || r;
+ r = ((glEvalCoord2fv = (PFNGLEVALCOORD2FVPROC)glewGetProcAddress((const GLubyte*)"glEvalCoord2fv")) == NULL) || r;
+ r = ((glEvalMesh1 = (PFNGLEVALMESH1PROC)glewGetProcAddress((const GLubyte*)"glEvalMesh1")) == NULL) || r;
+ r = ((glEvalMesh2 = (PFNGLEVALMESH2PROC)glewGetProcAddress((const GLubyte*)"glEvalMesh2")) == NULL) || r;
+ r = ((glEvalPoint1 = (PFNGLEVALPOINT1PROC)glewGetProcAddress((const GLubyte*)"glEvalPoint1")) == NULL) || r;
+ r = ((glEvalPoint2 = (PFNGLEVALPOINT2PROC)glewGetProcAddress((const GLubyte*)"glEvalPoint2")) == NULL) || r;
+ r = ((glFeedbackBuffer = (PFNGLFEEDBACKBUFFERPROC)glewGetProcAddress((const GLubyte*)"glFeedbackBuffer")) == NULL) || r;
+ r = ((glFogi = (PFNGLFOGIPROC)glewGetProcAddress((const GLubyte*)"glFogi")) == NULL) || r;
+ r = ((glFogiv = (PFNGLFOGIVPROC)glewGetProcAddress((const GLubyte*)"glFogiv")) == NULL) || r;
+ r = ((glFrustum = (PFNGLFRUSTUMPROC)glewGetProcAddress((const GLubyte*)"glFrustum")) == NULL) || r;
+ r = ((glGenLists = (PFNGLGENLISTSPROC)glewGetProcAddress((const GLubyte*)"glGenLists")) == NULL) || r;
+ r = ((glGetBooleanv = (PFNGLGETBOOLEANVPROC)glewGetProcAddress((const GLubyte*)"glGetBooleanv")) == NULL) || r;
+ r = ((glGetClipPlane = (PFNGLGETCLIPPLANEPROC)glewGetProcAddress((const GLubyte*)"glGetClipPlane")) == NULL) || r;
+ r = ((glGetDoublev = (PFNGLGETDOUBLEVPROC)glewGetProcAddress((const GLubyte*)"glGetDoublev")) == NULL) || r;
+ r = ((glGetFloatv = (PFNGLGETFLOATVPROC)glewGetProcAddress((const GLubyte*)"glGetFloatv")) == NULL) || r;
+ r = ((glGetLightfv = (PFNGLGETLIGHTFVPROC)glewGetProcAddress((const GLubyte*)"glGetLightfv")) == NULL) || r;
+ r = ((glGetLightiv = (PFNGLGETLIGHTIVPROC)glewGetProcAddress((const GLubyte*)"glGetLightiv")) == NULL) || r;
+ r = ((glGetMapdv = (PFNGLGETMAPDVPROC)glewGetProcAddress((const GLubyte*)"glGetMapdv")) == NULL) || r;
+ r = ((glGetMapfv = (PFNGLGETMAPFVPROC)glewGetProcAddress((const GLubyte*)"glGetMapfv")) == NULL) || r;
+ r = ((glGetMapiv = (PFNGLGETMAPIVPROC)glewGetProcAddress((const GLubyte*)"glGetMapiv")) == NULL) || r;
+ r = ((glGetMaterialfv = (PFNGLGETMATERIALFVPROC)glewGetProcAddress((const GLubyte*)"glGetMaterialfv")) == NULL) || r;
+ r = ((glGetMaterialiv = (PFNGLGETMATERIALIVPROC)glewGetProcAddress((const GLubyte*)"glGetMaterialiv")) == NULL) || r;
+ r = ((glGetPixelMapfv = (PFNGLGETPIXELMAPFVPROC)glewGetProcAddress((const GLubyte*)"glGetPixelMapfv")) == NULL) || r;
+ r = ((glGetPixelMapuiv = (PFNGLGETPIXELMAPUIVPROC)glewGetProcAddress((const GLubyte*)"glGetPixelMapuiv")) == NULL) || r;
+ r = ((glGetPixelMapusv = (PFNGLGETPIXELMAPUSVPROC)glewGetProcAddress((const GLubyte*)"glGetPixelMapusv")) == NULL) || r;
+ r = ((glGetPointerv = (PFNGLGETPOINTERVPROC)glewGetProcAddress((const GLubyte*)"glGetPointerv")) == NULL) || r;
+ r = ((glGetPolygonStipple = (PFNGLGETPOLYGONSTIPPLEPROC)glewGetProcAddress((const GLubyte*)"glGetPolygonStipple")) == NULL) || r;
+ r = ((glGetTexEnvfv = (PFNGLGETTEXENVFVPROC)glewGetProcAddress((const GLubyte*)"glGetTexEnvfv")) == NULL) || r;
+ r = ((glGetTexEnviv = (PFNGLGETTEXENVIVPROC)glewGetProcAddress((const GLubyte*)"glGetTexEnviv")) == NULL) || r;
+ r = ((glGetTexGendv = (PFNGLGETTEXGENDVPROC)glewGetProcAddress((const GLubyte*)"glGetTexGendv")) == NULL) || r;
+ r = ((glGetTexGenfv = (PFNGLGETTEXGENFVPROC)glewGetProcAddress((const GLubyte*)"glGetTexGenfv")) == NULL) || r;
+ r = ((glGetTexGeniv = (PFNGLGETTEXGENIVPROC)glewGetProcAddress((const GLubyte*)"glGetTexGeniv")) == NULL) || r;
+ r = ((glGetTexImage = (PFNGLGETTEXIMAGEPROC)glewGetProcAddress((const GLubyte*)"glGetTexImage")) == NULL) || r;
+ r = ((glGetTexLevelParameterfv = (PFNGLGETTEXLEVELPARAMETERFVPROC)glewGetProcAddress((const GLubyte*)"glGetTexLevelParameterfv")) == NULL) || r;
+ r = ((glGetTexLevelParameteriv = (PFNGLGETTEXLEVELPARAMETERIVPROC)glewGetProcAddress((const GLubyte*)"glGetTexLevelParameteriv")) == NULL) || r;
+ r = ((glGetTexParameterfv = (PFNGLGETTEXPARAMETERFVPROC)glewGetProcAddress((const GLubyte*)"glGetTexParameterfv")) == NULL) || r;
+ r = ((glGetTexParameteriv = (PFNGLGETTEXPARAMETERIVPROC)glewGetProcAddress((const GLubyte*)"glGetTexParameteriv")) == NULL) || r;
+ r = ((glIndexMask = (PFNGLINDEXMASKPROC)glewGetProcAddress((const GLubyte*)"glIndexMask")) == NULL) || r;
+ r = ((glIndexPointer = (PFNGLINDEXPOINTERPROC)glewGetProcAddress((const GLubyte*)"glIndexPointer")) == NULL) || r;
+ r = ((glIndexd = (PFNGLINDEXDPROC)glewGetProcAddress((const GLubyte*)"glIndexd")) == NULL) || r;
+ r = ((glIndexdv = (PFNGLINDEXDVPROC)glewGetProcAddress((const GLubyte*)"glIndexdv")) == NULL) || r;
+ r = ((glIndexf = (PFNGLINDEXFPROC)glewGetProcAddress((const GLubyte*)"glIndexf")) == NULL) || r;
+ r = ((glIndexfv = (PFNGLINDEXFVPROC)glewGetProcAddress((const GLubyte*)"glIndexfv")) == NULL) || r;
+ r = ((glIndexi = (PFNGLINDEXIPROC)glewGetProcAddress((const GLubyte*)"glIndexi")) == NULL) || r;
+ r = ((glIndexiv = (PFNGLINDEXIVPROC)glewGetProcAddress((const GLubyte*)"glIndexiv")) == NULL) || r;
+ r = ((glIndexs = (PFNGLINDEXSPROC)glewGetProcAddress((const GLubyte*)"glIndexs")) == NULL) || r;
+ r = ((glIndexsv = (PFNGLINDEXSVPROC)glewGetProcAddress((const GLubyte*)"glIndexsv")) == NULL) || r;
+ r = ((glIndexub = (PFNGLINDEXUBPROC)glewGetProcAddress((const GLubyte*)"glIndexub")) == NULL) || r;
+ r = ((glIndexubv = (PFNGLINDEXUBVPROC)glewGetProcAddress((const GLubyte*)"glIndexubv")) == NULL) || r;
+ r = ((glInitNames = (PFNGLINITNAMESPROC)glewGetProcAddress((const GLubyte*)"glInitNames")) == NULL) || r;
+ r = ((glInterleavedArrays = (PFNGLINTERLEAVEDARRAYSPROC)glewGetProcAddress((const GLubyte*)"glInterleavedArrays")) == NULL) || r;
+ r = ((glIsEnabled = (PFNGLISENABLEDPROC)glewGetProcAddress((const GLubyte*)"glIsEnabled")) == NULL) || r;
+ r = ((glIsList = (PFNGLISLISTPROC)glewGetProcAddress((const GLubyte*)"glIsList")) == NULL) || r;
+ r = ((glIsTexture = (PFNGLISTEXTUREPROC)glewGetProcAddress((const GLubyte*)"glIsTexture")) == NULL) || r;
+ r = ((glLightModeli = (PFNGLLIGHTMODELIPROC)glewGetProcAddress((const GLubyte*)"glLightModeli")) == NULL) || r;
+ r = ((glLightModeliv = (PFNGLLIGHTMODELIVPROC)glewGetProcAddress((const GLubyte*)"glLightModeliv")) == NULL) || r;
+ r = ((glLighti = (PFNGLLIGHTIPROC)glewGetProcAddress((const GLubyte*)"glLighti")) == NULL) || r;
+ r = ((glLightiv = (PFNGLLIGHTIVPROC)glewGetProcAddress((const GLubyte*)"glLightiv")) == NULL) || r;
+ r = ((glLineStipple = (PFNGLLINESTIPPLEPROC)glewGetProcAddress((const GLubyte*)"glLineStipple")) == NULL) || r;
+ r = ((glListBase = (PFNGLLISTBASEPROC)glewGetProcAddress((const GLubyte*)"glListBase")) == NULL) || r;
+ r = ((glLoadMatrixd = (PFNGLLOADMATRIXDPROC)glewGetProcAddress((const GLubyte*)"glLoadMatrixd")) == NULL) || r;
+ r = ((glLoadName = (PFNGLLOADNAMEPROC)glewGetProcAddress((const GLubyte*)"glLoadName")) == NULL) || r;
+ r = ((glMap1d = (PFNGLMAP1DPROC)glewGetProcAddress((const GLubyte*)"glMap1d")) == NULL) || r;
+ r = ((glMap1f = (PFNGLMAP1FPROC)glewGetProcAddress((const GLubyte*)"glMap1f")) == NULL) || r;
+ r = ((glMap2d = (PFNGLMAP2DPROC)glewGetProcAddress((const GLubyte*)"glMap2d")) == NULL) || r;
+ r = ((glMap2f = (PFNGLMAP2FPROC)glewGetProcAddress((const GLubyte*)"glMap2f")) == NULL) || r;
+ r = ((glMapGrid1d = (PFNGLMAPGRID1DPROC)glewGetProcAddress((const GLubyte*)"glMapGrid1d")) == NULL) || r;
+ r = ((glMapGrid1f = (PFNGLMAPGRID1FPROC)glewGetProcAddress((const GLubyte*)"glMapGrid1f")) == NULL) || r;
+ r = ((glMapGrid2d = (PFNGLMAPGRID2DPROC)glewGetProcAddress((const GLubyte*)"glMapGrid2d")) == NULL) || r;
+ r = ((glMapGrid2f = (PFNGLMAPGRID2FPROC)glewGetProcAddress((const GLubyte*)"glMapGrid2f")) == NULL) || r;
+ r = ((glMateriali = (PFNGLMATERIALIPROC)glewGetProcAddress((const GLubyte*)"glMateriali")) == NULL) || r;
+ r = ((glMaterialiv = (PFNGLMATERIALIVPROC)glewGetProcAddress((const GLubyte*)"glMaterialiv")) == NULL) || r;
+ r = ((glMultMatrixd = (PFNGLMULTMATRIXDPROC)glewGetProcAddress((const GLubyte*)"glMultMatrixd")) == NULL) || r;
+ r = ((glNewList = (PFNGLNEWLISTPROC)glewGetProcAddress((const GLubyte*)"glNewList")) == NULL) || r;
+ r = ((glNormal3b = (PFNGLNORMAL3BPROC)glewGetProcAddress((const GLubyte*)"glNormal3b")) == NULL) || r;
+ r = ((glNormal3bv = (PFNGLNORMAL3BVPROC)glewGetProcAddress((const GLubyte*)"glNormal3bv")) == NULL) || r;
+ r = ((glNormal3d = (PFNGLNORMAL3DPROC)glewGetProcAddress((const GLubyte*)"glNormal3d")) == NULL) || r;
+ r = ((glNormal3dv = (PFNGLNORMAL3DVPROC)glewGetProcAddress((const GLubyte*)"glNormal3dv")) == NULL) || r;
+ r = ((glNormal3fv = (PFNGLNORMAL3FVPROC)glewGetProcAddress((const GLubyte*)"glNormal3fv")) == NULL) || r;
+ r = ((glNormal3i = (PFNGLNORMAL3IPROC)glewGetProcAddress((const GLubyte*)"glNormal3i")) == NULL) || r;
+ r = ((glNormal3iv = (PFNGLNORMAL3IVPROC)glewGetProcAddress((const GLubyte*)"glNormal3iv")) == NULL) || r;
+ r = ((glNormal3s = (PFNGLNORMAL3SPROC)glewGetProcAddress((const GLubyte*)"glNormal3s")) == NULL) || r;
+ r = ((glNormal3sv = (PFNGLNORMAL3SVPROC)glewGetProcAddress((const GLubyte*)"glNormal3sv")) == NULL) || r;
+ r = ((glOrtho = (PFNGLORTHOPROC)glewGetProcAddress((const GLubyte*)"glOrtho")) == NULL) || r;
+ r = ((glPassThrough = (PFNGLPASSTHROUGHPROC)glewGetProcAddress((const GLubyte*)"glPassThrough")) == NULL) || r;
+ r = ((glPixelMapfv = (PFNGLPIXELMAPFVPROC)glewGetProcAddress((const GLubyte*)"glPixelMapfv")) == NULL) || r;
+ r = ((glPixelMapuiv = (PFNGLPIXELMAPUIVPROC)glewGetProcAddress((const GLubyte*)"glPixelMapuiv")) == NULL) || r;
+ r = ((glPixelMapusv = (PFNGLPIXELMAPUSVPROC)glewGetProcAddress((const GLubyte*)"glPixelMapusv")) == NULL) || r;
+ r = ((glPixelStoref = (PFNGLPIXELSTOREFPROC)glewGetProcAddress((const GLubyte*)"glPixelStoref")) == NULL) || r;
+ r = ((glPixelTransferf = (PFNGLPIXELTRANSFERFPROC)glewGetProcAddress((const GLubyte*)"glPixelTransferf")) == NULL) || r;
+ r = ((glPixelTransferi = (PFNGLPIXELTRANSFERIPROC)glewGetProcAddress((const GLubyte*)"glPixelTransferi")) == NULL) || r;
+ r = ((glPixelZoom = (PFNGLPIXELZOOMPROC)glewGetProcAddress((const GLubyte*)"glPixelZoom")) == NULL) || r;
+ r = ((glPolygonMode = (PFNGLPOLYGONMODEPROC)glewGetProcAddress((const GLubyte*)"glPolygonMode")) == NULL) || r;
+ r = ((glPolygonStipple = (PFNGLPOLYGONSTIPPLEPROC)glewGetProcAddress((const GLubyte*)"glPolygonStipple")) == NULL) || r;
+ r = ((glPopAttrib = (PFNGLPOPATTRIBPROC)glewGetProcAddress((const GLubyte*)"glPopAttrib")) == NULL) || r;
+ r = ((glPopClientAttrib = (PFNGLPOPCLIENTATTRIBPROC)glewGetProcAddress((const GLubyte*)"glPopClientAttrib")) == NULL) || r;
+ r = ((glPopName = (PFNGLPOPNAMEPROC)glewGetProcAddress((const GLubyte*)"glPopName")) == NULL) || r;
+ r = ((glPrioritizeTextures = (PFNGLPRIORITIZETEXTURESPROC)glewGetProcAddress((const GLubyte*)"glPrioritizeTextures")) == NULL) || r;
+ r = ((glPushAttrib = (PFNGLPUSHATTRIBPROC)glewGetProcAddress((const GLubyte*)"glPushAttrib")) == NULL) || r;
+ r = ((glPushClientAttrib = (PFNGLPUSHCLIENTATTRIBPROC)glewGetProcAddress((const GLubyte*)"glPushClientAttrib")) == NULL) || r;
+ r = ((glPushName = (PFNGLPUSHNAMEPROC)glewGetProcAddress((const GLubyte*)"glPushName")) == NULL) || r;
+ r = ((glRasterPos2d = (PFNGLRASTERPOS2DPROC)glewGetProcAddress((const GLubyte*)"glRasterPos2d")) == NULL) || r;
+ r = ((glRasterPos2dv = (PFNGLRASTERPOS2DVPROC)glewGetProcAddress((const GLubyte*)"glRasterPos2dv")) == NULL) || r;
+ r = ((glRasterPos2f = (PFNGLRASTERPOS2FPROC)glewGetProcAddress((const GLubyte*)"glRasterPos2f")) == NULL) || r;
+ r = ((glRasterPos2fv = (PFNGLRASTERPOS2FVPROC)glewGetProcAddress((const GLubyte*)"glRasterPos2fv")) == NULL) || r;
+ r = ((glRasterPos2i = (PFNGLRASTERPOS2IPROC)glewGetProcAddress((const GLubyte*)"glRasterPos2i")) == NULL) || r;
+ r = ((glRasterPos2iv = (PFNGLRASTERPOS2IVPROC)glewGetProcAddress((const GLubyte*)"glRasterPos2iv")) == NULL) || r;
+ r = ((glRasterPos2s = (PFNGLRASTERPOS2SPROC)glewGetProcAddress((const GLubyte*)"glRasterPos2s")) == NULL) || r;
+ r = ((glRasterPos2sv = (PFNGLRASTERPOS2SVPROC)glewGetProcAddress((const GLubyte*)"glRasterPos2sv")) == NULL) || r;
+ r = ((glRasterPos3d = (PFNGLRASTERPOS3DPROC)glewGetProcAddress((const GLubyte*)"glRasterPos3d")) == NULL) || r;
+ r = ((glRasterPos3dv = (PFNGLRASTERPOS3DVPROC)glewGetProcAddress((const GLubyte*)"glRasterPos3dv")) == NULL) || r;
+ r = ((glRasterPos3f = (PFNGLRASTERPOS3FPROC)glewGetProcAddress((const GLubyte*)"glRasterPos3f")) == NULL) || r;
+ r = ((glRasterPos3fv = (PFNGLRASTERPOS3FVPROC)glewGetProcAddress((const GLubyte*)"glRasterPos3fv")) == NULL) || r;
+ r = ((glRasterPos3i = (PFNGLRASTERPOS3IPROC)glewGetProcAddress((const GLubyte*)"glRasterPos3i")) == NULL) || r;
+ r = ((glRasterPos3iv = (PFNGLRASTERPOS3IVPROC)glewGetProcAddress((const GLubyte*)"glRasterPos3iv")) == NULL) || r;
+ r = ((glRasterPos3s = (PFNGLRASTERPOS3SPROC)glewGetProcAddress((const GLubyte*)"glRasterPos3s")) == NULL) || r;
+ r = ((glRasterPos3sv = (PFNGLRASTERPOS3SVPROC)glewGetProcAddress((const GLubyte*)"glRasterPos3sv")) == NULL) || r;
+ r = ((glRasterPos4d = (PFNGLRASTERPOS4DPROC)glewGetProcAddress((const GLubyte*)"glRasterPos4d")) == NULL) || r;
+ r = ((glRasterPos4dv = (PFNGLRASTERPOS4DVPROC)glewGetProcAddress((const GLubyte*)"glRasterPos4dv")) == NULL) || r;
+ r = ((glRasterPos4f = (PFNGLRASTERPOS4FPROC)glewGetProcAddress((const GLubyte*)"glRasterPos4f")) == NULL) || r;
+ r = ((glRasterPos4fv = (PFNGLRASTERPOS4FVPROC)glewGetProcAddress((const GLubyte*)"glRasterPos4fv")) == NULL) || r;
+ r = ((glRasterPos4i = (PFNGLRASTERPOS4IPROC)glewGetProcAddress((const GLubyte*)"glRasterPos4i")) == NULL) || r;
+ r = ((glRasterPos4iv = (PFNGLRASTERPOS4IVPROC)glewGetProcAddress((const GLubyte*)"glRasterPos4iv")) == NULL) || r;
+ r = ((glRasterPos4s = (PFNGLRASTERPOS4SPROC)glewGetProcAddress((const GLubyte*)"glRasterPos4s")) == NULL) || r;
+ r = ((glRasterPos4sv = (PFNGLRASTERPOS4SVPROC)glewGetProcAddress((const GLubyte*)"glRasterPos4sv")) == NULL) || r;
+ r = ((glReadBuffer = (PFNGLREADBUFFERPROC)glewGetProcAddress((const GLubyte*)"glReadBuffer")) == NULL) || r;
+ r = ((glRectd = (PFNGLRECTDPROC)glewGetProcAddress((const GLubyte*)"glRectd")) == NULL) || r;
+ r = ((glRectdv = (PFNGLRECTDVPROC)glewGetProcAddress((const GLubyte*)"glRectdv")) == NULL) || r;
+ r = ((glRectf = (PFNGLRECTFPROC)glewGetProcAddress((const GLubyte*)"glRectf")) == NULL) || r;
+ r = ((glRectfv = (PFNGLRECTFVPROC)glewGetProcAddress((const GLubyte*)"glRectfv")) == NULL) || r;
+ r = ((glRecti = (PFNGLRECTIPROC)glewGetProcAddress((const GLubyte*)"glRecti")) == NULL) || r;
+ r = ((glRectiv = (PFNGLRECTIVPROC)glewGetProcAddress((const GLubyte*)"glRectiv")) == NULL) || r;
+ r = ((glRects = (PFNGLRECTSPROC)glewGetProcAddress((const GLubyte*)"glRects")) == NULL) || r;
+ r = ((glRectsv = (PFNGLRECTSVPROC)glewGetProcAddress((const GLubyte*)"glRectsv")) == NULL) || r;
+ r = ((glRenderMode = (PFNGLRENDERMODEPROC)glewGetProcAddress((const GLubyte*)"glRenderMode")) == NULL) || r;
+ r = ((glRotated = (PFNGLROTATEDPROC)glewGetProcAddress((const GLubyte*)"glRotated")) == NULL) || r;
+ r = ((glScaled = (PFNGLSCALEDPROC)glewGetProcAddress((const GLubyte*)"glScaled")) == NULL) || r;
+ r = ((glSelectBuffer = (PFNGLSELECTBUFFERPROC)glewGetProcAddress((const GLubyte*)"glSelectBuffer")) == NULL) || r;
+ r = ((glTexCoord1d = (PFNGLTEXCOORD1DPROC)glewGetProcAddress((const GLubyte*)"glTexCoord1d")) == NULL) || r;
+ r = ((glTexCoord1dv = (PFNGLTEXCOORD1DVPROC)glewGetProcAddress((const GLubyte*)"glTexCoord1dv")) == NULL) || r;
+ r = ((glTexCoord1f = (PFNGLTEXCOORD1FPROC)glewGetProcAddress((const GLubyte*)"glTexCoord1f")) == NULL) || r;
+ r = ((glTexCoord1fv = (PFNGLTEXCOORD1FVPROC)glewGetProcAddress((const GLubyte*)"glTexCoord1fv")) == NULL) || r;
+ r = ((glTexCoord1i = (PFNGLTEXCOORD1IPROC)glewGetProcAddress((const GLubyte*)"glTexCoord1i")) == NULL) || r;
+ r = ((glTexCoord1iv = (PFNGLTEXCOORD1IVPROC)glewGetProcAddress((const GLubyte*)"glTexCoord1iv")) == NULL) || r;
+ r = ((glTexCoord1s = (PFNGLTEXCOORD1SPROC)glewGetProcAddress((const GLubyte*)"glTexCoord1s")) == NULL) || r;
+ r = ((glTexCoord1sv = (PFNGLTEXCOORD1SVPROC)glewGetProcAddress((const GLubyte*)"glTexCoord1sv")) == NULL) || r;
+ r = ((glTexCoord2d = (PFNGLTEXCOORD2DPROC)glewGetProcAddress((const GLubyte*)"glTexCoord2d")) == NULL) || r;
+ r = ((glTexCoord2dv = (PFNGLTEXCOORD2DVPROC)glewGetProcAddress((const GLubyte*)"glTexCoord2dv")) == NULL) || r;
+ r = ((glTexCoord2f = (PFNGLTEXCOORD2FPROC)glewGetProcAddress((const GLubyte*)"glTexCoord2f")) == NULL) || r;
+ r = ((glTexCoord2fv = (PFNGLTEXCOORD2FVPROC)glewGetProcAddress((const GLubyte*)"glTexCoord2fv")) == NULL) || r;
+ r = ((glTexCoord2i = (PFNGLTEXCOORD2IPROC)glewGetProcAddress((const GLubyte*)"glTexCoord2i")) == NULL) || r;
+ r = ((glTexCoord2iv = (PFNGLTEXCOORD2IVPROC)glewGetProcAddress((const GLubyte*)"glTexCoord2iv")) == NULL) || r;
+ r = ((glTexCoord2s = (PFNGLTEXCOORD2SPROC)glewGetProcAddress((const GLubyte*)"glTexCoord2s")) == NULL) || r;
+ r = ((glTexCoord2sv = (PFNGLTEXCOORD2SVPROC)glewGetProcAddress((const GLubyte*)"glTexCoord2sv")) == NULL) || r;
+ r = ((glTexCoord3d = (PFNGLTEXCOORD3DPROC)glewGetProcAddress((const GLubyte*)"glTexCoord3d")) == NULL) || r;
+ r = ((glTexCoord3dv = (PFNGLTEXCOORD3DVPROC)glewGetProcAddress((const GLubyte*)"glTexCoord3dv")) == NULL) || r;
+ r = ((glTexCoord3f = (PFNGLTEXCOORD3FPROC)glewGetProcAddress((const GLubyte*)"glTexCoord3f")) == NULL) || r;
+ r = ((glTexCoord3fv = (PFNGLTEXCOORD3FVPROC)glewGetProcAddress((const GLubyte*)"glTexCoord3fv")) == NULL) || r;
+ r = ((glTexCoord3i = (PFNGLTEXCOORD3IPROC)glewGetProcAddress((const GLubyte*)"glTexCoord3i")) == NULL) || r;
+ r = ((glTexCoord3iv = (PFNGLTEXCOORD3IVPROC)glewGetProcAddress((const GLubyte*)"glTexCoord3iv")) == NULL) || r;
+ r = ((glTexCoord3s = (PFNGLTEXCOORD3SPROC)glewGetProcAddress((const GLubyte*)"glTexCoord3s")) == NULL) || r;
+ r = ((glTexCoord3sv = (PFNGLTEXCOORD3SVPROC)glewGetProcAddress((const GLubyte*)"glTexCoord3sv")) == NULL) || r;
+ r = ((glTexCoord4d = (PFNGLTEXCOORD4DPROC)glewGetProcAddress((const GLubyte*)"glTexCoord4d")) == NULL) || r;
+ r = ((glTexCoord4dv = (PFNGLTEXCOORD4DVPROC)glewGetProcAddress((const GLubyte*)"glTexCoord4dv")) == NULL) || r;
+ r = ((glTexCoord4f = (PFNGLTEXCOORD4FPROC)glewGetProcAddress((const GLubyte*)"glTexCoord4f")) == NULL) || r;
+ r = ((glTexCoord4fv = (PFNGLTEXCOORD4FVPROC)glewGetProcAddress((const GLubyte*)"glTexCoord4fv")) == NULL) || r;
+ r = ((glTexCoord4i = (PFNGLTEXCOORD4IPROC)glewGetProcAddress((const GLubyte*)"glTexCoord4i")) == NULL) || r;
+ r = ((glTexCoord4iv = (PFNGLTEXCOORD4IVPROC)glewGetProcAddress((const GLubyte*)"glTexCoord4iv")) == NULL) || r;
+ r = ((glTexCoord4s = (PFNGLTEXCOORD4SPROC)glewGetProcAddress((const GLubyte*)"glTexCoord4s")) == NULL) || r;
+ r = ((glTexCoord4sv = (PFNGLTEXCOORD4SVPROC)glewGetProcAddress((const GLubyte*)"glTexCoord4sv")) == NULL) || r;
+ r = ((glTexEnvi = (PFNGLTEXENVIPROC)glewGetProcAddress((const GLubyte*)"glTexEnvi")) == NULL) || r;
+ r = ((glTexEnviv = (PFNGLTEXENVIVPROC)glewGetProcAddress((const GLubyte*)"glTexEnviv")) == NULL) || r;
+ r = ((glTexGend = (PFNGLTEXGENDPROC)glewGetProcAddress((const GLubyte*)"glTexGend")) == NULL) || r;
+ r = ((glTexGendv = (PFNGLTEXGENDVPROC)glewGetProcAddress((const GLubyte*)"glTexGendv")) == NULL) || r;
+ r = ((glTexGenf = (PFNGLTEXGENFPROC)glewGetProcAddress((const GLubyte*)"glTexGenf")) == NULL) || r;
+ r = ((glTexGenfv = (PFNGLTEXGENFVPROC)glewGetProcAddress((const GLubyte*)"glTexGenfv")) == NULL) || r;
+ r = ((glTexGeni = (PFNGLTEXGENIPROC)glewGetProcAddress((const GLubyte*)"glTexGeni")) == NULL) || r;
+ r = ((glTexGeniv = (PFNGLTEXGENIVPROC)glewGetProcAddress((const GLubyte*)"glTexGeniv")) == NULL) || r;
+ r = ((glTexImage1D = (PFNGLTEXIMAGE1DPROC)glewGetProcAddress((const GLubyte*)"glTexImage1D")) == NULL) || r;
+ r = ((glTexParameterfv = (PFNGLTEXPARAMETERFVPROC)glewGetProcAddress((const GLubyte*)"glTexParameterfv")) == NULL) || r;
+ r = ((glTexParameteri = (PFNGLTEXPARAMETERIPROC)glewGetProcAddress((const GLubyte*)"glTexParameteri")) == NULL) || r;
+ r = ((glTexParameteriv = (PFNGLTEXPARAMETERIVPROC)glewGetProcAddress((const GLubyte*)"glTexParameteriv")) == NULL) || r;
+ r = ((glTexSubImage1D = (PFNGLTEXSUBIMAGE1DPROC)glewGetProcAddress((const GLubyte*)"glTexSubImage1D")) == NULL) || r;
+ r = ((glTranslated = (PFNGLTRANSLATEDPROC)glewGetProcAddress((const GLubyte*)"glTranslated")) == NULL) || r;
+ r = ((glVertex2d = (PFNGLVERTEX2DPROC)glewGetProcAddress((const GLubyte*)"glVertex2d")) == NULL) || r;
+ r = ((glVertex2dv = (PFNGLVERTEX2DVPROC)glewGetProcAddress((const GLubyte*)"glVertex2dv")) == NULL) || r;
+ r = ((glVertex2f = (PFNGLVERTEX2FPROC)glewGetProcAddress((const GLubyte*)"glVertex2f")) == NULL) || r;
+ r = ((glVertex2fv = (PFNGLVERTEX2FVPROC)glewGetProcAddress((const GLubyte*)"glVertex2fv")) == NULL) || r;
+ r = ((glVertex2i = (PFNGLVERTEX2IPROC)glewGetProcAddress((const GLubyte*)"glVertex2i")) == NULL) || r;
+ r = ((glVertex2iv = (PFNGLVERTEX2IVPROC)glewGetProcAddress((const GLubyte*)"glVertex2iv")) == NULL) || r;
+ r = ((glVertex2s = (PFNGLVERTEX2SPROC)glewGetProcAddress((const GLubyte*)"glVertex2s")) == NULL) || r;
+ r = ((glVertex2sv = (PFNGLVERTEX2SVPROC)glewGetProcAddress((const GLubyte*)"glVertex2sv")) == NULL) || r;
+ r = ((glVertex3d = (PFNGLVERTEX3DPROC)glewGetProcAddress((const GLubyte*)"glVertex3d")) == NULL) || r;
+ r = ((glVertex3dv = (PFNGLVERTEX3DVPROC)glewGetProcAddress((const GLubyte*)"glVertex3dv")) == NULL) || r;
+ r = ((glVertex3f = (PFNGLVERTEX3FPROC)glewGetProcAddress((const GLubyte*)"glVertex3f")) == NULL) || r;
+ r = ((glVertex3fv = (PFNGLVERTEX3FVPROC)glewGetProcAddress((const GLubyte*)"glVertex3fv")) == NULL) || r;
+ r = ((glVertex3i = (PFNGLVERTEX3IPROC)glewGetProcAddress((const GLubyte*)"glVertex3i")) == NULL) || r;
+ r = ((glVertex3iv = (PFNGLVERTEX3IVPROC)glewGetProcAddress((const GLubyte*)"glVertex3iv")) == NULL) || r;
+ r = ((glVertex3s = (PFNGLVERTEX3SPROC)glewGetProcAddress((const GLubyte*)"glVertex3s")) == NULL) || r;
+ r = ((glVertex3sv = (PFNGLVERTEX3SVPROC)glewGetProcAddress((const GLubyte*)"glVertex3sv")) == NULL) || r;
+ r = ((glVertex4d = (PFNGLVERTEX4DPROC)glewGetProcAddress((const GLubyte*)"glVertex4d")) == NULL) || r;
+ r = ((glVertex4dv = (PFNGLVERTEX4DVPROC)glewGetProcAddress((const GLubyte*)"glVertex4dv")) == NULL) || r;
+ r = ((glVertex4f = (PFNGLVERTEX4FPROC)glewGetProcAddress((const GLubyte*)"glVertex4f")) == NULL) || r;
+ r = ((glVertex4fv = (PFNGLVERTEX4FVPROC)glewGetProcAddress((const GLubyte*)"glVertex4fv")) == NULL) || r;
+ r = ((glVertex4i = (PFNGLVERTEX4IPROC)glewGetProcAddress((const GLubyte*)"glVertex4i")) == NULL) || r;
+ r = ((glVertex4iv = (PFNGLVERTEX4IVPROC)glewGetProcAddress((const GLubyte*)"glVertex4iv")) == NULL) || r;
+ r = ((glVertex4s = (PFNGLVERTEX4SPROC)glewGetProcAddress((const GLubyte*)"glVertex4s")) == NULL) || r;
+ r = ((glVertex4sv = (PFNGLVERTEX4SVPROC)glewGetProcAddress((const GLubyte*)"glVertex4sv")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_VERSION_1_1 */
+
+#ifdef GL_VERSION_1_2
+
+static GLboolean _glewInit_GL_VERSION_1_2 (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glCopyTexSubImage3D = (PFNGLCOPYTEXSUBIMAGE3DPROC)glewGetProcAddress((const GLubyte*)"glCopyTexSubImage3D")) == NULL) || r;
+ r = ((glDrawRangeElements = (PFNGLDRAWRANGEELEMENTSPROC)glewGetProcAddress((const GLubyte*)"glDrawRangeElements")) == NULL) || r;
+ r = ((glTexImage3D = (PFNGLTEXIMAGE3DPROC)glewGetProcAddress((const GLubyte*)"glTexImage3D")) == NULL) || r;
+ r = ((glTexSubImage3D = (PFNGLTEXSUBIMAGE3DPROC)glewGetProcAddress((const GLubyte*)"glTexSubImage3D")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_VERSION_1_2 */
+
+#ifdef GL_VERSION_1_2_1
+
+#endif /* GL_VERSION_1_2_1 */
+
+#ifdef GL_VERSION_1_3
+
+static GLboolean _glewInit_GL_VERSION_1_3 (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glActiveTexture = (PFNGLACTIVETEXTUREPROC)glewGetProcAddress((const GLubyte*)"glActiveTexture")) == NULL) || r;
+ r = ((glClientActiveTexture = (PFNGLCLIENTACTIVETEXTUREPROC)glewGetProcAddress((const GLubyte*)"glClientActiveTexture")) == NULL) || r;
+ r = ((glCompressedTexImage1D = (PFNGLCOMPRESSEDTEXIMAGE1DPROC)glewGetProcAddress((const GLubyte*)"glCompressedTexImage1D")) == NULL) || r;
+ r = ((glCompressedTexImage2D = (PFNGLCOMPRESSEDTEXIMAGE2DPROC)glewGetProcAddress((const GLubyte*)"glCompressedTexImage2D")) == NULL) || r;
+ r = ((glCompressedTexImage3D = (PFNGLCOMPRESSEDTEXIMAGE3DPROC)glewGetProcAddress((const GLubyte*)"glCompressedTexImage3D")) == NULL) || r;
+ r = ((glCompressedTexSubImage1D = (PFNGLCOMPRESSEDTEXSUBIMAGE1DPROC)glewGetProcAddress((const GLubyte*)"glCompressedTexSubImage1D")) == NULL) || r;
+ r = ((glCompressedTexSubImage2D = (PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC)glewGetProcAddress((const GLubyte*)"glCompressedTexSubImage2D")) == NULL) || r;
+ r = ((glCompressedTexSubImage3D = (PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC)glewGetProcAddress((const GLubyte*)"glCompressedTexSubImage3D")) == NULL) || r;
+ r = ((glGetCompressedTexImage = (PFNGLGETCOMPRESSEDTEXIMAGEPROC)glewGetProcAddress((const GLubyte*)"glGetCompressedTexImage")) == NULL) || r;
+ r = ((glLoadTransposeMatrixd = (PFNGLLOADTRANSPOSEMATRIXDPROC)glewGetProcAddress((const GLubyte*)"glLoadTransposeMatrixd")) == NULL) || r;
+ r = ((glLoadTransposeMatrixf = (PFNGLLOADTRANSPOSEMATRIXFPROC)glewGetProcAddress((const GLubyte*)"glLoadTransposeMatrixf")) == NULL) || r;
+ r = ((glMultTransposeMatrixd = (PFNGLMULTTRANSPOSEMATRIXDPROC)glewGetProcAddress((const GLubyte*)"glMultTransposeMatrixd")) == NULL) || r;
+ r = ((glMultTransposeMatrixf = (PFNGLMULTTRANSPOSEMATRIXFPROC)glewGetProcAddress((const GLubyte*)"glMultTransposeMatrixf")) == NULL) || r;
+ r = ((glMultiTexCoord1d = (PFNGLMULTITEXCOORD1DPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord1d")) == NULL) || r;
+ r = ((glMultiTexCoord1dv = (PFNGLMULTITEXCOORD1DVPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord1dv")) == NULL) || r;
+ r = ((glMultiTexCoord1f = (PFNGLMULTITEXCOORD1FPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord1f")) == NULL) || r;
+ r = ((glMultiTexCoord1fv = (PFNGLMULTITEXCOORD1FVPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord1fv")) == NULL) || r;
+ r = ((glMultiTexCoord1i = (PFNGLMULTITEXCOORD1IPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord1i")) == NULL) || r;
+ r = ((glMultiTexCoord1iv = (PFNGLMULTITEXCOORD1IVPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord1iv")) == NULL) || r;
+ r = ((glMultiTexCoord1s = (PFNGLMULTITEXCOORD1SPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord1s")) == NULL) || r;
+ r = ((glMultiTexCoord1sv = (PFNGLMULTITEXCOORD1SVPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord1sv")) == NULL) || r;
+ r = ((glMultiTexCoord2d = (PFNGLMULTITEXCOORD2DPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord2d")) == NULL) || r;
+ r = ((glMultiTexCoord2dv = (PFNGLMULTITEXCOORD2DVPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord2dv")) == NULL) || r;
+ r = ((glMultiTexCoord2f = (PFNGLMULTITEXCOORD2FPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord2f")) == NULL) || r;
+ r = ((glMultiTexCoord2fv = (PFNGLMULTITEXCOORD2FVPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord2fv")) == NULL) || r;
+ r = ((glMultiTexCoord2i = (PFNGLMULTITEXCOORD2IPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord2i")) == NULL) || r;
+ r = ((glMultiTexCoord2iv = (PFNGLMULTITEXCOORD2IVPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord2iv")) == NULL) || r;
+ r = ((glMultiTexCoord2s = (PFNGLMULTITEXCOORD2SPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord2s")) == NULL) || r;
+ r = ((glMultiTexCoord2sv = (PFNGLMULTITEXCOORD2SVPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord2sv")) == NULL) || r;
+ r = ((glMultiTexCoord3d = (PFNGLMULTITEXCOORD3DPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord3d")) == NULL) || r;
+ r = ((glMultiTexCoord3dv = (PFNGLMULTITEXCOORD3DVPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord3dv")) == NULL) || r;
+ r = ((glMultiTexCoord3f = (PFNGLMULTITEXCOORD3FPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord3f")) == NULL) || r;
+ r = ((glMultiTexCoord3fv = (PFNGLMULTITEXCOORD3FVPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord3fv")) == NULL) || r;
+ r = ((glMultiTexCoord3i = (PFNGLMULTITEXCOORD3IPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord3i")) == NULL) || r;
+ r = ((glMultiTexCoord3iv = (PFNGLMULTITEXCOORD3IVPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord3iv")) == NULL) || r;
+ r = ((glMultiTexCoord3s = (PFNGLMULTITEXCOORD3SPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord3s")) == NULL) || r;
+ r = ((glMultiTexCoord3sv = (PFNGLMULTITEXCOORD3SVPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord3sv")) == NULL) || r;
+ r = ((glMultiTexCoord4d = (PFNGLMULTITEXCOORD4DPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord4d")) == NULL) || r;
+ r = ((glMultiTexCoord4dv = (PFNGLMULTITEXCOORD4DVPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord4dv")) == NULL) || r;
+ r = ((glMultiTexCoord4f = (PFNGLMULTITEXCOORD4FPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord4f")) == NULL) || r;
+ r = ((glMultiTexCoord4fv = (PFNGLMULTITEXCOORD4FVPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord4fv")) == NULL) || r;
+ r = ((glMultiTexCoord4i = (PFNGLMULTITEXCOORD4IPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord4i")) == NULL) || r;
+ r = ((glMultiTexCoord4iv = (PFNGLMULTITEXCOORD4IVPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord4iv")) == NULL) || r;
+ r = ((glMultiTexCoord4s = (PFNGLMULTITEXCOORD4SPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord4s")) == NULL) || r;
+ r = ((glMultiTexCoord4sv = (PFNGLMULTITEXCOORD4SVPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord4sv")) == NULL) || r;
+ r = ((glSampleCoverage = (PFNGLSAMPLECOVERAGEPROC)glewGetProcAddress((const GLubyte*)"glSampleCoverage")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_VERSION_1_3 */
+
+#ifdef GL_VERSION_1_4
+
+static GLboolean _glewInit_GL_VERSION_1_4 (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glBlendColor = (PFNGLBLENDCOLORPROC)glewGetProcAddress((const GLubyte*)"glBlendColor")) == NULL) || r;
+ r = ((glBlendEquation = (PFNGLBLENDEQUATIONPROC)glewGetProcAddress((const GLubyte*)"glBlendEquation")) == NULL) || r;
+ r = ((glBlendFuncSeparate = (PFNGLBLENDFUNCSEPARATEPROC)glewGetProcAddress((const GLubyte*)"glBlendFuncSeparate")) == NULL) || r;
+ r = ((glFogCoordPointer = (PFNGLFOGCOORDPOINTERPROC)glewGetProcAddress((const GLubyte*)"glFogCoordPointer")) == NULL) || r;
+ r = ((glFogCoordd = (PFNGLFOGCOORDDPROC)glewGetProcAddress((const GLubyte*)"glFogCoordd")) == NULL) || r;
+ r = ((glFogCoorddv = (PFNGLFOGCOORDDVPROC)glewGetProcAddress((const GLubyte*)"glFogCoorddv")) == NULL) || r;
+ r = ((glFogCoordf = (PFNGLFOGCOORDFPROC)glewGetProcAddress((const GLubyte*)"glFogCoordf")) == NULL) || r;
+ r = ((glFogCoordfv = (PFNGLFOGCOORDFVPROC)glewGetProcAddress((const GLubyte*)"glFogCoordfv")) == NULL) || r;
+ r = ((glMultiDrawArrays = (PFNGLMULTIDRAWARRAYSPROC)glewGetProcAddress((const GLubyte*)"glMultiDrawArrays")) == NULL) || r;
+ r = ((glMultiDrawElements = (PFNGLMULTIDRAWELEMENTSPROC)glewGetProcAddress((const GLubyte*)"glMultiDrawElements")) == NULL) || r;
+ r = ((glPointParameterf = (PFNGLPOINTPARAMETERFPROC)glewGetProcAddress((const GLubyte*)"glPointParameterf")) == NULL) || r;
+ r = ((glPointParameterfv = (PFNGLPOINTPARAMETERFVPROC)glewGetProcAddress((const GLubyte*)"glPointParameterfv")) == NULL) || r;
+ r = ((glPointParameteri = (PFNGLPOINTPARAMETERIPROC)glewGetProcAddress((const GLubyte*)"glPointParameteri")) == NULL) || r;
+ r = ((glPointParameteriv = (PFNGLPOINTPARAMETERIVPROC)glewGetProcAddress((const GLubyte*)"glPointParameteriv")) == NULL) || r;
+ r = ((glSecondaryColor3b = (PFNGLSECONDARYCOLOR3BPROC)glewGetProcAddress((const GLubyte*)"glSecondaryColor3b")) == NULL) || r;
+ r = ((glSecondaryColor3bv = (PFNGLSECONDARYCOLOR3BVPROC)glewGetProcAddress((const GLubyte*)"glSecondaryColor3bv")) == NULL) || r;
+ r = ((glSecondaryColor3d = (PFNGLSECONDARYCOLOR3DPROC)glewGetProcAddress((const GLubyte*)"glSecondaryColor3d")) == NULL) || r;
+ r = ((glSecondaryColor3dv = (PFNGLSECONDARYCOLOR3DVPROC)glewGetProcAddress((const GLubyte*)"glSecondaryColor3dv")) == NULL) || r;
+ r = ((glSecondaryColor3f = (PFNGLSECONDARYCOLOR3FPROC)glewGetProcAddress((const GLubyte*)"glSecondaryColor3f")) == NULL) || r;
+ r = ((glSecondaryColor3fv = (PFNGLSECONDARYCOLOR3FVPROC)glewGetProcAddress((const GLubyte*)"glSecondaryColor3fv")) == NULL) || r;
+ r = ((glSecondaryColor3i = (PFNGLSECONDARYCOLOR3IPROC)glewGetProcAddress((const GLubyte*)"glSecondaryColor3i")) == NULL) || r;
+ r = ((glSecondaryColor3iv = (PFNGLSECONDARYCOLOR3IVPROC)glewGetProcAddress((const GLubyte*)"glSecondaryColor3iv")) == NULL) || r;
+ r = ((glSecondaryColor3s = (PFNGLSECONDARYCOLOR3SPROC)glewGetProcAddress((const GLubyte*)"glSecondaryColor3s")) == NULL) || r;
+ r = ((glSecondaryColor3sv = (PFNGLSECONDARYCOLOR3SVPROC)glewGetProcAddress((const GLubyte*)"glSecondaryColor3sv")) == NULL) || r;
+ r = ((glSecondaryColor3ub = (PFNGLSECONDARYCOLOR3UBPROC)glewGetProcAddress((const GLubyte*)"glSecondaryColor3ub")) == NULL) || r;
+ r = ((glSecondaryColor3ubv = (PFNGLSECONDARYCOLOR3UBVPROC)glewGetProcAddress((const GLubyte*)"glSecondaryColor3ubv")) == NULL) || r;
+ r = ((glSecondaryColor3ui = (PFNGLSECONDARYCOLOR3UIPROC)glewGetProcAddress((const GLubyte*)"glSecondaryColor3ui")) == NULL) || r;
+ r = ((glSecondaryColor3uiv = (PFNGLSECONDARYCOLOR3UIVPROC)glewGetProcAddress((const GLubyte*)"glSecondaryColor3uiv")) == NULL) || r;
+ r = ((glSecondaryColor3us = (PFNGLSECONDARYCOLOR3USPROC)glewGetProcAddress((const GLubyte*)"glSecondaryColor3us")) == NULL) || r;
+ r = ((glSecondaryColor3usv = (PFNGLSECONDARYCOLOR3USVPROC)glewGetProcAddress((const GLubyte*)"glSecondaryColor3usv")) == NULL) || r;
+ r = ((glSecondaryColorPointer = (PFNGLSECONDARYCOLORPOINTERPROC)glewGetProcAddress((const GLubyte*)"glSecondaryColorPointer")) == NULL) || r;
+ r = ((glWindowPos2d = (PFNGLWINDOWPOS2DPROC)glewGetProcAddress((const GLubyte*)"glWindowPos2d")) == NULL) || r;
+ r = ((glWindowPos2dv = (PFNGLWINDOWPOS2DVPROC)glewGetProcAddress((const GLubyte*)"glWindowPos2dv")) == NULL) || r;
+ r = ((glWindowPos2f = (PFNGLWINDOWPOS2FPROC)glewGetProcAddress((const GLubyte*)"glWindowPos2f")) == NULL) || r;
+ r = ((glWindowPos2fv = (PFNGLWINDOWPOS2FVPROC)glewGetProcAddress((const GLubyte*)"glWindowPos2fv")) == NULL) || r;
+ r = ((glWindowPos2i = (PFNGLWINDOWPOS2IPROC)glewGetProcAddress((const GLubyte*)"glWindowPos2i")) == NULL) || r;
+ r = ((glWindowPos2iv = (PFNGLWINDOWPOS2IVPROC)glewGetProcAddress((const GLubyte*)"glWindowPos2iv")) == NULL) || r;
+ r = ((glWindowPos2s = (PFNGLWINDOWPOS2SPROC)glewGetProcAddress((const GLubyte*)"glWindowPos2s")) == NULL) || r;
+ r = ((glWindowPos2sv = (PFNGLWINDOWPOS2SVPROC)glewGetProcAddress((const GLubyte*)"glWindowPos2sv")) == NULL) || r;
+ r = ((glWindowPos3d = (PFNGLWINDOWPOS3DPROC)glewGetProcAddress((const GLubyte*)"glWindowPos3d")) == NULL) || r;
+ r = ((glWindowPos3dv = (PFNGLWINDOWPOS3DVPROC)glewGetProcAddress((const GLubyte*)"glWindowPos3dv")) == NULL) || r;
+ r = ((glWindowPos3f = (PFNGLWINDOWPOS3FPROC)glewGetProcAddress((const GLubyte*)"glWindowPos3f")) == NULL) || r;
+ r = ((glWindowPos3fv = (PFNGLWINDOWPOS3FVPROC)glewGetProcAddress((const GLubyte*)"glWindowPos3fv")) == NULL) || r;
+ r = ((glWindowPos3i = (PFNGLWINDOWPOS3IPROC)glewGetProcAddress((const GLubyte*)"glWindowPos3i")) == NULL) || r;
+ r = ((glWindowPos3iv = (PFNGLWINDOWPOS3IVPROC)glewGetProcAddress((const GLubyte*)"glWindowPos3iv")) == NULL) || r;
+ r = ((glWindowPos3s = (PFNGLWINDOWPOS3SPROC)glewGetProcAddress((const GLubyte*)"glWindowPos3s")) == NULL) || r;
+ r = ((glWindowPos3sv = (PFNGLWINDOWPOS3SVPROC)glewGetProcAddress((const GLubyte*)"glWindowPos3sv")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_VERSION_1_4 */
+
+#ifdef GL_VERSION_1_5
+
+static GLboolean _glewInit_GL_VERSION_1_5 (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glBeginQuery = (PFNGLBEGINQUERYPROC)glewGetProcAddress((const GLubyte*)"glBeginQuery")) == NULL) || r;
+ r = ((glBindBuffer = (PFNGLBINDBUFFERPROC)glewGetProcAddress((const GLubyte*)"glBindBuffer")) == NULL) || r;
+ r = ((glBufferData = (PFNGLBUFFERDATAPROC)glewGetProcAddress((const GLubyte*)"glBufferData")) == NULL) || r;
+ r = ((glBufferSubData = (PFNGLBUFFERSUBDATAPROC)glewGetProcAddress((const GLubyte*)"glBufferSubData")) == NULL) || r;
+ r = ((glDeleteBuffers = (PFNGLDELETEBUFFERSPROC)glewGetProcAddress((const GLubyte*)"glDeleteBuffers")) == NULL) || r;
+ r = ((glDeleteQueries = (PFNGLDELETEQUERIESPROC)glewGetProcAddress((const GLubyte*)"glDeleteQueries")) == NULL) || r;
+ r = ((glEndQuery = (PFNGLENDQUERYPROC)glewGetProcAddress((const GLubyte*)"glEndQuery")) == NULL) || r;
+ r = ((glGenBuffers = (PFNGLGENBUFFERSPROC)glewGetProcAddress((const GLubyte*)"glGenBuffers")) == NULL) || r;
+ r = ((glGenQueries = (PFNGLGENQUERIESPROC)glewGetProcAddress((const GLubyte*)"glGenQueries")) == NULL) || r;
+ r = ((glGetBufferParameteriv = (PFNGLGETBUFFERPARAMETERIVPROC)glewGetProcAddress((const GLubyte*)"glGetBufferParameteriv")) == NULL) || r;
+ r = ((glGetBufferPointerv = (PFNGLGETBUFFERPOINTERVPROC)glewGetProcAddress((const GLubyte*)"glGetBufferPointerv")) == NULL) || r;
+ r = ((glGetBufferSubData = (PFNGLGETBUFFERSUBDATAPROC)glewGetProcAddress((const GLubyte*)"glGetBufferSubData")) == NULL) || r;
+ r = ((glGetQueryObjectiv = (PFNGLGETQUERYOBJECTIVPROC)glewGetProcAddress((const GLubyte*)"glGetQueryObjectiv")) == NULL) || r;
+ r = ((glGetQueryObjectuiv = (PFNGLGETQUERYOBJECTUIVPROC)glewGetProcAddress((const GLubyte*)"glGetQueryObjectuiv")) == NULL) || r;
+ r = ((glGetQueryiv = (PFNGLGETQUERYIVPROC)glewGetProcAddress((const GLubyte*)"glGetQueryiv")) == NULL) || r;
+ r = ((glIsBuffer = (PFNGLISBUFFERPROC)glewGetProcAddress((const GLubyte*)"glIsBuffer")) == NULL) || r;
+ r = ((glIsQuery = (PFNGLISQUERYPROC)glewGetProcAddress((const GLubyte*)"glIsQuery")) == NULL) || r;
+ r = ((glMapBuffer = (PFNGLMAPBUFFERPROC)glewGetProcAddress((const GLubyte*)"glMapBuffer")) == NULL) || r;
+ r = ((glUnmapBuffer = (PFNGLUNMAPBUFFERPROC)glewGetProcAddress((const GLubyte*)"glUnmapBuffer")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_VERSION_1_5 */
+
+#ifdef GL_VERSION_2_0
+
+static GLboolean _glewInit_GL_VERSION_2_0 (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glAttachShader = (PFNGLATTACHSHADERPROC)glewGetProcAddress((const GLubyte*)"glAttachShader")) == NULL) || r;
+ r = ((glBindAttribLocation = (PFNGLBINDATTRIBLOCATIONPROC)glewGetProcAddress((const GLubyte*)"glBindAttribLocation")) == NULL) || r;
+ r = ((glBlendEquationSeparate = (PFNGLBLENDEQUATIONSEPARATEPROC)glewGetProcAddress((const GLubyte*)"glBlendEquationSeparate")) == NULL) || r;
+ r = ((glCompileShader = (PFNGLCOMPILESHADERPROC)glewGetProcAddress((const GLubyte*)"glCompileShader")) == NULL) || r;
+ r = ((glCreateProgram = (PFNGLCREATEPROGRAMPROC)glewGetProcAddress((const GLubyte*)"glCreateProgram")) == NULL) || r;
+ r = ((glCreateShader = (PFNGLCREATESHADERPROC)glewGetProcAddress((const GLubyte*)"glCreateShader")) == NULL) || r;
+ r = ((glDeleteProgram = (PFNGLDELETEPROGRAMPROC)glewGetProcAddress((const GLubyte*)"glDeleteProgram")) == NULL) || r;
+ r = ((glDeleteShader = (PFNGLDELETESHADERPROC)glewGetProcAddress((const GLubyte*)"glDeleteShader")) == NULL) || r;
+ r = ((glDetachShader = (PFNGLDETACHSHADERPROC)glewGetProcAddress((const GLubyte*)"glDetachShader")) == NULL) || r;
+ r = ((glDisableVertexAttribArray = (PFNGLDISABLEVERTEXATTRIBARRAYPROC)glewGetProcAddress((const GLubyte*)"glDisableVertexAttribArray")) == NULL) || r;
+ r = ((glDrawBuffers = (PFNGLDRAWBUFFERSPROC)glewGetProcAddress((const GLubyte*)"glDrawBuffers")) == NULL) || r;
+ r = ((glEnableVertexAttribArray = (PFNGLENABLEVERTEXATTRIBARRAYPROC)glewGetProcAddress((const GLubyte*)"glEnableVertexAttribArray")) == NULL) || r;
+ r = ((glGetActiveAttrib = (PFNGLGETACTIVEATTRIBPROC)glewGetProcAddress((const GLubyte*)"glGetActiveAttrib")) == NULL) || r;
+ r = ((glGetActiveUniform = (PFNGLGETACTIVEUNIFORMPROC)glewGetProcAddress((const GLubyte*)"glGetActiveUniform")) == NULL) || r;
+ r = ((glGetAttachedShaders = (PFNGLGETATTACHEDSHADERSPROC)glewGetProcAddress((const GLubyte*)"glGetAttachedShaders")) == NULL) || r;
+ r = ((glGetAttribLocation = (PFNGLGETATTRIBLOCATIONPROC)glewGetProcAddress((const GLubyte*)"glGetAttribLocation")) == NULL) || r;
+ r = ((glGetProgramInfoLog = (PFNGLGETPROGRAMINFOLOGPROC)glewGetProcAddress((const GLubyte*)"glGetProgramInfoLog")) == NULL) || r;
+ r = ((glGetProgramiv = (PFNGLGETPROGRAMIVPROC)glewGetProcAddress((const GLubyte*)"glGetProgramiv")) == NULL) || r;
+ r = ((glGetShaderInfoLog = (PFNGLGETSHADERINFOLOGPROC)glewGetProcAddress((const GLubyte*)"glGetShaderInfoLog")) == NULL) || r;
+ r = ((glGetShaderSource = (PFNGLGETSHADERSOURCEPROC)glewGetProcAddress((const GLubyte*)"glGetShaderSource")) == NULL) || r;
+ r = ((glGetShaderiv = (PFNGLGETSHADERIVPROC)glewGetProcAddress((const GLubyte*)"glGetShaderiv")) == NULL) || r;
+ r = ((glGetUniformLocation = (PFNGLGETUNIFORMLOCATIONPROC)glewGetProcAddress((const GLubyte*)"glGetUniformLocation")) == NULL) || r;
+ r = ((glGetUniformfv = (PFNGLGETUNIFORMFVPROC)glewGetProcAddress((const GLubyte*)"glGetUniformfv")) == NULL) || r;
+ r = ((glGetUniformiv = (PFNGLGETUNIFORMIVPROC)glewGetProcAddress((const GLubyte*)"glGetUniformiv")) == NULL) || r;
+ r = ((glGetVertexAttribPointerv = (PFNGLGETVERTEXATTRIBPOINTERVPROC)glewGetProcAddress((const GLubyte*)"glGetVertexAttribPointerv")) == NULL) || r;
+ r = ((glGetVertexAttribdv = (PFNGLGETVERTEXATTRIBDVPROC)glewGetProcAddress((const GLubyte*)"glGetVertexAttribdv")) == NULL) || r;
+ r = ((glGetVertexAttribfv = (PFNGLGETVERTEXATTRIBFVPROC)glewGetProcAddress((const GLubyte*)"glGetVertexAttribfv")) == NULL) || r;
+ r = ((glGetVertexAttribiv = (PFNGLGETVERTEXATTRIBIVPROC)glewGetProcAddress((const GLubyte*)"glGetVertexAttribiv")) == NULL) || r;
+ r = ((glIsProgram = (PFNGLISPROGRAMPROC)glewGetProcAddress((const GLubyte*)"glIsProgram")) == NULL) || r;
+ r = ((glIsShader = (PFNGLISSHADERPROC)glewGetProcAddress((const GLubyte*)"glIsShader")) == NULL) || r;
+ r = ((glLinkProgram = (PFNGLLINKPROGRAMPROC)glewGetProcAddress((const GLubyte*)"glLinkProgram")) == NULL) || r;
+ r = ((glShaderSource = (PFNGLSHADERSOURCEPROC)glewGetProcAddress((const GLubyte*)"glShaderSource")) == NULL) || r;
+ r = ((glStencilFuncSeparate = (PFNGLSTENCILFUNCSEPARATEPROC)glewGetProcAddress((const GLubyte*)"glStencilFuncSeparate")) == NULL) || r;
+ r = ((glStencilMaskSeparate = (PFNGLSTENCILMASKSEPARATEPROC)glewGetProcAddress((const GLubyte*)"glStencilMaskSeparate")) == NULL) || r;
+ r = ((glStencilOpSeparate = (PFNGLSTENCILOPSEPARATEPROC)glewGetProcAddress((const GLubyte*)"glStencilOpSeparate")) == NULL) || r;
+ r = ((glUniform1f = (PFNGLUNIFORM1FPROC)glewGetProcAddress((const GLubyte*)"glUniform1f")) == NULL) || r;
+ r = ((glUniform1fv = (PFNGLUNIFORM1FVPROC)glewGetProcAddress((const GLubyte*)"glUniform1fv")) == NULL) || r;
+ r = ((glUniform1i = (PFNGLUNIFORM1IPROC)glewGetProcAddress((const GLubyte*)"glUniform1i")) == NULL) || r;
+ r = ((glUniform1iv = (PFNGLUNIFORM1IVPROC)glewGetProcAddress((const GLubyte*)"glUniform1iv")) == NULL) || r;
+ r = ((glUniform2f = (PFNGLUNIFORM2FPROC)glewGetProcAddress((const GLubyte*)"glUniform2f")) == NULL) || r;
+ r = ((glUniform2fv = (PFNGLUNIFORM2FVPROC)glewGetProcAddress((const GLubyte*)"glUniform2fv")) == NULL) || r;
+ r = ((glUniform2i = (PFNGLUNIFORM2IPROC)glewGetProcAddress((const GLubyte*)"glUniform2i")) == NULL) || r;
+ r = ((glUniform2iv = (PFNGLUNIFORM2IVPROC)glewGetProcAddress((const GLubyte*)"glUniform2iv")) == NULL) || r;
+ r = ((glUniform3f = (PFNGLUNIFORM3FPROC)glewGetProcAddress((const GLubyte*)"glUniform3f")) == NULL) || r;
+ r = ((glUniform3fv = (PFNGLUNIFORM3FVPROC)glewGetProcAddress((const GLubyte*)"glUniform3fv")) == NULL) || r;
+ r = ((glUniform3i = (PFNGLUNIFORM3IPROC)glewGetProcAddress((const GLubyte*)"glUniform3i")) == NULL) || r;
+ r = ((glUniform3iv = (PFNGLUNIFORM3IVPROC)glewGetProcAddress((const GLubyte*)"glUniform3iv")) == NULL) || r;
+ r = ((glUniform4f = (PFNGLUNIFORM4FPROC)glewGetProcAddress((const GLubyte*)"glUniform4f")) == NULL) || r;
+ r = ((glUniform4fv = (PFNGLUNIFORM4FVPROC)glewGetProcAddress((const GLubyte*)"glUniform4fv")) == NULL) || r;
+ r = ((glUniform4i = (PFNGLUNIFORM4IPROC)glewGetProcAddress((const GLubyte*)"glUniform4i")) == NULL) || r;
+ r = ((glUniform4iv = (PFNGLUNIFORM4IVPROC)glewGetProcAddress((const GLubyte*)"glUniform4iv")) == NULL) || r;
+ r = ((glUniformMatrix2fv = (PFNGLUNIFORMMATRIX2FVPROC)glewGetProcAddress((const GLubyte*)"glUniformMatrix2fv")) == NULL) || r;
+ r = ((glUniformMatrix3fv = (PFNGLUNIFORMMATRIX3FVPROC)glewGetProcAddress((const GLubyte*)"glUniformMatrix3fv")) == NULL) || r;
+ r = ((glUniformMatrix4fv = (PFNGLUNIFORMMATRIX4FVPROC)glewGetProcAddress((const GLubyte*)"glUniformMatrix4fv")) == NULL) || r;
+ r = ((glUseProgram = (PFNGLUSEPROGRAMPROC)glewGetProcAddress((const GLubyte*)"glUseProgram")) == NULL) || r;
+ r = ((glValidateProgram = (PFNGLVALIDATEPROGRAMPROC)glewGetProcAddress((const GLubyte*)"glValidateProgram")) == NULL) || r;
+ r = ((glVertexAttrib1d = (PFNGLVERTEXATTRIB1DPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib1d")) == NULL) || r;
+ r = ((glVertexAttrib1dv = (PFNGLVERTEXATTRIB1DVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib1dv")) == NULL) || r;
+ r = ((glVertexAttrib1f = (PFNGLVERTEXATTRIB1FPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib1f")) == NULL) || r;
+ r = ((glVertexAttrib1fv = (PFNGLVERTEXATTRIB1FVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib1fv")) == NULL) || r;
+ r = ((glVertexAttrib1s = (PFNGLVERTEXATTRIB1SPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib1s")) == NULL) || r;
+ r = ((glVertexAttrib1sv = (PFNGLVERTEXATTRIB1SVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib1sv")) == NULL) || r;
+ r = ((glVertexAttrib2d = (PFNGLVERTEXATTRIB2DPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib2d")) == NULL) || r;
+ r = ((glVertexAttrib2dv = (PFNGLVERTEXATTRIB2DVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib2dv")) == NULL) || r;
+ r = ((glVertexAttrib2f = (PFNGLVERTEXATTRIB2FPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib2f")) == NULL) || r;
+ r = ((glVertexAttrib2fv = (PFNGLVERTEXATTRIB2FVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib2fv")) == NULL) || r;
+ r = ((glVertexAttrib2s = (PFNGLVERTEXATTRIB2SPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib2s")) == NULL) || r;
+ r = ((glVertexAttrib2sv = (PFNGLVERTEXATTRIB2SVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib2sv")) == NULL) || r;
+ r = ((glVertexAttrib3d = (PFNGLVERTEXATTRIB3DPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib3d")) == NULL) || r;
+ r = ((glVertexAttrib3dv = (PFNGLVERTEXATTRIB3DVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib3dv")) == NULL) || r;
+ r = ((glVertexAttrib3f = (PFNGLVERTEXATTRIB3FPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib3f")) == NULL) || r;
+ r = ((glVertexAttrib3fv = (PFNGLVERTEXATTRIB3FVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib3fv")) == NULL) || r;
+ r = ((glVertexAttrib3s = (PFNGLVERTEXATTRIB3SPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib3s")) == NULL) || r;
+ r = ((glVertexAttrib3sv = (PFNGLVERTEXATTRIB3SVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib3sv")) == NULL) || r;
+ r = ((glVertexAttrib4Nbv = (PFNGLVERTEXATTRIB4NBVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4Nbv")) == NULL) || r;
+ r = ((glVertexAttrib4Niv = (PFNGLVERTEXATTRIB4NIVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4Niv")) == NULL) || r;
+ r = ((glVertexAttrib4Nsv = (PFNGLVERTEXATTRIB4NSVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4Nsv")) == NULL) || r;
+ r = ((glVertexAttrib4Nub = (PFNGLVERTEXATTRIB4NUBPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4Nub")) == NULL) || r;
+ r = ((glVertexAttrib4Nubv = (PFNGLVERTEXATTRIB4NUBVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4Nubv")) == NULL) || r;
+ r = ((glVertexAttrib4Nuiv = (PFNGLVERTEXATTRIB4NUIVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4Nuiv")) == NULL) || r;
+ r = ((glVertexAttrib4Nusv = (PFNGLVERTEXATTRIB4NUSVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4Nusv")) == NULL) || r;
+ r = ((glVertexAttrib4bv = (PFNGLVERTEXATTRIB4BVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4bv")) == NULL) || r;
+ r = ((glVertexAttrib4d = (PFNGLVERTEXATTRIB4DPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4d")) == NULL) || r;
+ r = ((glVertexAttrib4dv = (PFNGLVERTEXATTRIB4DVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4dv")) == NULL) || r;
+ r = ((glVertexAttrib4f = (PFNGLVERTEXATTRIB4FPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4f")) == NULL) || r;
+ r = ((glVertexAttrib4fv = (PFNGLVERTEXATTRIB4FVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4fv")) == NULL) || r;
+ r = ((glVertexAttrib4iv = (PFNGLVERTEXATTRIB4IVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4iv")) == NULL) || r;
+ r = ((glVertexAttrib4s = (PFNGLVERTEXATTRIB4SPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4s")) == NULL) || r;
+ r = ((glVertexAttrib4sv = (PFNGLVERTEXATTRIB4SVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4sv")) == NULL) || r;
+ r = ((glVertexAttrib4ubv = (PFNGLVERTEXATTRIB4UBVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4ubv")) == NULL) || r;
+ r = ((glVertexAttrib4uiv = (PFNGLVERTEXATTRIB4UIVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4uiv")) == NULL) || r;
+ r = ((glVertexAttrib4usv = (PFNGLVERTEXATTRIB4USVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4usv")) == NULL) || r;
+ r = ((glVertexAttribPointer = (PFNGLVERTEXATTRIBPOINTERPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribPointer")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_VERSION_2_0 */
+
+#ifdef GL_VERSION_2_1
+
+static GLboolean _glewInit_GL_VERSION_2_1 (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glUniformMatrix2x3fv = (PFNGLUNIFORMMATRIX2X3FVPROC)glewGetProcAddress((const GLubyte*)"glUniformMatrix2x3fv")) == NULL) || r;
+ r = ((glUniformMatrix2x4fv = (PFNGLUNIFORMMATRIX2X4FVPROC)glewGetProcAddress((const GLubyte*)"glUniformMatrix2x4fv")) == NULL) || r;
+ r = ((glUniformMatrix3x2fv = (PFNGLUNIFORMMATRIX3X2FVPROC)glewGetProcAddress((const GLubyte*)"glUniformMatrix3x2fv")) == NULL) || r;
+ r = ((glUniformMatrix3x4fv = (PFNGLUNIFORMMATRIX3X4FVPROC)glewGetProcAddress((const GLubyte*)"glUniformMatrix3x4fv")) == NULL) || r;
+ r = ((glUniformMatrix4x2fv = (PFNGLUNIFORMMATRIX4X2FVPROC)glewGetProcAddress((const GLubyte*)"glUniformMatrix4x2fv")) == NULL) || r;
+ r = ((glUniformMatrix4x3fv = (PFNGLUNIFORMMATRIX4X3FVPROC)glewGetProcAddress((const GLubyte*)"glUniformMatrix4x3fv")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_VERSION_2_1 */
+
+#ifdef GL_VERSION_3_0
+
+static GLboolean _glewInit_GL_VERSION_3_0 (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glBeginConditionalRender = (PFNGLBEGINCONDITIONALRENDERPROC)glewGetProcAddress((const GLubyte*)"glBeginConditionalRender")) == NULL) || r;
+ r = ((glBeginTransformFeedback = (PFNGLBEGINTRANSFORMFEEDBACKPROC)glewGetProcAddress((const GLubyte*)"glBeginTransformFeedback")) == NULL) || r;
+ r = ((glBindFragDataLocation = (PFNGLBINDFRAGDATALOCATIONPROC)glewGetProcAddress((const GLubyte*)"glBindFragDataLocation")) == NULL) || r;
+ r = ((glClampColor = (PFNGLCLAMPCOLORPROC)glewGetProcAddress((const GLubyte*)"glClampColor")) == NULL) || r;
+ r = ((glClearBufferfi = (PFNGLCLEARBUFFERFIPROC)glewGetProcAddress((const GLubyte*)"glClearBufferfi")) == NULL) || r;
+ r = ((glClearBufferfv = (PFNGLCLEARBUFFERFVPROC)glewGetProcAddress((const GLubyte*)"glClearBufferfv")) == NULL) || r;
+ r = ((glClearBufferiv = (PFNGLCLEARBUFFERIVPROC)glewGetProcAddress((const GLubyte*)"glClearBufferiv")) == NULL) || r;
+ r = ((glClearBufferuiv = (PFNGLCLEARBUFFERUIVPROC)glewGetProcAddress((const GLubyte*)"glClearBufferuiv")) == NULL) || r;
+ r = ((glColorMaski = (PFNGLCOLORMASKIPROC)glewGetProcAddress((const GLubyte*)"glColorMaski")) == NULL) || r;
+ r = ((glDisablei = (PFNGLDISABLEIPROC)glewGetProcAddress((const GLubyte*)"glDisablei")) == NULL) || r;
+ r = ((glEnablei = (PFNGLENABLEIPROC)glewGetProcAddress((const GLubyte*)"glEnablei")) == NULL) || r;
+ r = ((glEndConditionalRender = (PFNGLENDCONDITIONALRENDERPROC)glewGetProcAddress((const GLubyte*)"glEndConditionalRender")) == NULL) || r;
+ r = ((glEndTransformFeedback = (PFNGLENDTRANSFORMFEEDBACKPROC)glewGetProcAddress((const GLubyte*)"glEndTransformFeedback")) == NULL) || r;
+ r = ((glGetBooleani_v = (PFNGLGETBOOLEANI_VPROC)glewGetProcAddress((const GLubyte*)"glGetBooleani_v")) == NULL) || r;
+ r = ((glGetFragDataLocation = (PFNGLGETFRAGDATALOCATIONPROC)glewGetProcAddress((const GLubyte*)"glGetFragDataLocation")) == NULL) || r;
+ r = ((glGetStringi = (PFNGLGETSTRINGIPROC)glewGetProcAddress((const GLubyte*)"glGetStringi")) == NULL) || r;
+ r = ((glGetTexParameterIiv = (PFNGLGETTEXPARAMETERIIVPROC)glewGetProcAddress((const GLubyte*)"glGetTexParameterIiv")) == NULL) || r;
+ r = ((glGetTexParameterIuiv = (PFNGLGETTEXPARAMETERIUIVPROC)glewGetProcAddress((const GLubyte*)"glGetTexParameterIuiv")) == NULL) || r;
+ r = ((glGetTransformFeedbackVarying = (PFNGLGETTRANSFORMFEEDBACKVARYINGPROC)glewGetProcAddress((const GLubyte*)"glGetTransformFeedbackVarying")) == NULL) || r;
+ r = ((glGetUniformuiv = (PFNGLGETUNIFORMUIVPROC)glewGetProcAddress((const GLubyte*)"glGetUniformuiv")) == NULL) || r;
+ r = ((glGetVertexAttribIiv = (PFNGLGETVERTEXATTRIBIIVPROC)glewGetProcAddress((const GLubyte*)"glGetVertexAttribIiv")) == NULL) || r;
+ r = ((glGetVertexAttribIuiv = (PFNGLGETVERTEXATTRIBIUIVPROC)glewGetProcAddress((const GLubyte*)"glGetVertexAttribIuiv")) == NULL) || r;
+ r = ((glIsEnabledi = (PFNGLISENABLEDIPROC)glewGetProcAddress((const GLubyte*)"glIsEnabledi")) == NULL) || r;
+ r = ((glTexParameterIiv = (PFNGLTEXPARAMETERIIVPROC)glewGetProcAddress((const GLubyte*)"glTexParameterIiv")) == NULL) || r;
+ r = ((glTexParameterIuiv = (PFNGLTEXPARAMETERIUIVPROC)glewGetProcAddress((const GLubyte*)"glTexParameterIuiv")) == NULL) || r;
+ r = ((glTransformFeedbackVaryings = (PFNGLTRANSFORMFEEDBACKVARYINGSPROC)glewGetProcAddress((const GLubyte*)"glTransformFeedbackVaryings")) == NULL) || r;
+ r = ((glUniform1ui = (PFNGLUNIFORM1UIPROC)glewGetProcAddress((const GLubyte*)"glUniform1ui")) == NULL) || r;
+ r = ((glUniform1uiv = (PFNGLUNIFORM1UIVPROC)glewGetProcAddress((const GLubyte*)"glUniform1uiv")) == NULL) || r;
+ r = ((glUniform2ui = (PFNGLUNIFORM2UIPROC)glewGetProcAddress((const GLubyte*)"glUniform2ui")) == NULL) || r;
+ r = ((glUniform2uiv = (PFNGLUNIFORM2UIVPROC)glewGetProcAddress((const GLubyte*)"glUniform2uiv")) == NULL) || r;
+ r = ((glUniform3ui = (PFNGLUNIFORM3UIPROC)glewGetProcAddress((const GLubyte*)"glUniform3ui")) == NULL) || r;
+ r = ((glUniform3uiv = (PFNGLUNIFORM3UIVPROC)glewGetProcAddress((const GLubyte*)"glUniform3uiv")) == NULL) || r;
+ r = ((glUniform4ui = (PFNGLUNIFORM4UIPROC)glewGetProcAddress((const GLubyte*)"glUniform4ui")) == NULL) || r;
+ r = ((glUniform4uiv = (PFNGLUNIFORM4UIVPROC)glewGetProcAddress((const GLubyte*)"glUniform4uiv")) == NULL) || r;
+ r = ((glVertexAttribI1i = (PFNGLVERTEXATTRIBI1IPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribI1i")) == NULL) || r;
+ r = ((glVertexAttribI1iv = (PFNGLVERTEXATTRIBI1IVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribI1iv")) == NULL) || r;
+ r = ((glVertexAttribI1ui = (PFNGLVERTEXATTRIBI1UIPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribI1ui")) == NULL) || r;
+ r = ((glVertexAttribI1uiv = (PFNGLVERTEXATTRIBI1UIVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribI1uiv")) == NULL) || r;
+ r = ((glVertexAttribI2i = (PFNGLVERTEXATTRIBI2IPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribI2i")) == NULL) || r;
+ r = ((glVertexAttribI2iv = (PFNGLVERTEXATTRIBI2IVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribI2iv")) == NULL) || r;
+ r = ((glVertexAttribI2ui = (PFNGLVERTEXATTRIBI2UIPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribI2ui")) == NULL) || r;
+ r = ((glVertexAttribI2uiv = (PFNGLVERTEXATTRIBI2UIVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribI2uiv")) == NULL) || r;
+ r = ((glVertexAttribI3i = (PFNGLVERTEXATTRIBI3IPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribI3i")) == NULL) || r;
+ r = ((glVertexAttribI3iv = (PFNGLVERTEXATTRIBI3IVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribI3iv")) == NULL) || r;
+ r = ((glVertexAttribI3ui = (PFNGLVERTEXATTRIBI3UIPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribI3ui")) == NULL) || r;
+ r = ((glVertexAttribI3uiv = (PFNGLVERTEXATTRIBI3UIVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribI3uiv")) == NULL) || r;
+ r = ((glVertexAttribI4bv = (PFNGLVERTEXATTRIBI4BVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribI4bv")) == NULL) || r;
+ r = ((glVertexAttribI4i = (PFNGLVERTEXATTRIBI4IPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribI4i")) == NULL) || r;
+ r = ((glVertexAttribI4iv = (PFNGLVERTEXATTRIBI4IVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribI4iv")) == NULL) || r;
+ r = ((glVertexAttribI4sv = (PFNGLVERTEXATTRIBI4SVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribI4sv")) == NULL) || r;
+ r = ((glVertexAttribI4ubv = (PFNGLVERTEXATTRIBI4UBVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribI4ubv")) == NULL) || r;
+ r = ((glVertexAttribI4ui = (PFNGLVERTEXATTRIBI4UIPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribI4ui")) == NULL) || r;
+ r = ((glVertexAttribI4uiv = (PFNGLVERTEXATTRIBI4UIVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribI4uiv")) == NULL) || r;
+ r = ((glVertexAttribI4usv = (PFNGLVERTEXATTRIBI4USVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribI4usv")) == NULL) || r;
+ r = ((glVertexAttribIPointer = (PFNGLVERTEXATTRIBIPOINTERPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribIPointer")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_VERSION_3_0 */
+
+#ifdef GL_VERSION_3_1
+
+static GLboolean _glewInit_GL_VERSION_3_1 (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glDrawArraysInstanced = (PFNGLDRAWARRAYSINSTANCEDPROC)glewGetProcAddress((const GLubyte*)"glDrawArraysInstanced")) == NULL) || r;
+ r = ((glDrawElementsInstanced = (PFNGLDRAWELEMENTSINSTANCEDPROC)glewGetProcAddress((const GLubyte*)"glDrawElementsInstanced")) == NULL) || r;
+ r = ((glPrimitiveRestartIndex = (PFNGLPRIMITIVERESTARTINDEXPROC)glewGetProcAddress((const GLubyte*)"glPrimitiveRestartIndex")) == NULL) || r;
+ r = ((glTexBuffer = (PFNGLTEXBUFFERPROC)glewGetProcAddress((const GLubyte*)"glTexBuffer")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_VERSION_3_1 */
+
+#ifdef GL_VERSION_3_2
+
+static GLboolean _glewInit_GL_VERSION_3_2 (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glFramebufferTexture = (PFNGLFRAMEBUFFERTEXTUREPROC)glewGetProcAddress((const GLubyte*)"glFramebufferTexture")) == NULL) || r;
+ r = ((glGetBufferParameteri64v = (PFNGLGETBUFFERPARAMETERI64VPROC)glewGetProcAddress((const GLubyte*)"glGetBufferParameteri64v")) == NULL) || r;
+ r = ((glGetInteger64i_v = (PFNGLGETINTEGER64I_VPROC)glewGetProcAddress((const GLubyte*)"glGetInteger64i_v")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_VERSION_3_2 */
+
+#ifdef GL_VERSION_3_3
+
+static GLboolean _glewInit_GL_VERSION_3_3 (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glVertexAttribDivisor = (PFNGLVERTEXATTRIBDIVISORPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribDivisor")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_VERSION_3_3 */
+
+#ifdef GL_VERSION_4_0
+
+static GLboolean _glewInit_GL_VERSION_4_0 (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glBlendEquationSeparatei = (PFNGLBLENDEQUATIONSEPARATEIPROC)glewGetProcAddress((const GLubyte*)"glBlendEquationSeparatei")) == NULL) || r;
+ r = ((glBlendEquationi = (PFNGLBLENDEQUATIONIPROC)glewGetProcAddress((const GLubyte*)"glBlendEquationi")) == NULL) || r;
+ r = ((glBlendFuncSeparatei = (PFNGLBLENDFUNCSEPARATEIPROC)glewGetProcAddress((const GLubyte*)"glBlendFuncSeparatei")) == NULL) || r;
+ r = ((glBlendFunci = (PFNGLBLENDFUNCIPROC)glewGetProcAddress((const GLubyte*)"glBlendFunci")) == NULL) || r;
+ r = ((glMinSampleShading = (PFNGLMINSAMPLESHADINGPROC)glewGetProcAddress((const GLubyte*)"glMinSampleShading")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_VERSION_4_0 */
+
+#ifdef GL_VERSION_4_1
+
+#endif /* GL_VERSION_4_1 */
+
+#ifdef GL_VERSION_4_2
+
+#endif /* GL_VERSION_4_2 */
+
+#ifdef GL_3DFX_multisample
+
+#endif /* GL_3DFX_multisample */
+
+#ifdef GL_3DFX_tbuffer
+
+static GLboolean _glewInit_GL_3DFX_tbuffer (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glTbufferMask3DFX = (PFNGLTBUFFERMASK3DFXPROC)glewGetProcAddress((const GLubyte*)"glTbufferMask3DFX")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_3DFX_tbuffer */
+
+#ifdef GL_3DFX_texture_compression_FXT1
+
+#endif /* GL_3DFX_texture_compression_FXT1 */
+
+#ifdef GL_AMD_blend_minmax_factor
+
+#endif /* GL_AMD_blend_minmax_factor */
+
+#ifdef GL_AMD_conservative_depth
+
+#endif /* GL_AMD_conservative_depth */
+
+#ifdef GL_AMD_debug_output
+
+static GLboolean _glewInit_GL_AMD_debug_output (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glDebugMessageCallbackAMD = (PFNGLDEBUGMESSAGECALLBACKAMDPROC)glewGetProcAddress((const GLubyte*)"glDebugMessageCallbackAMD")) == NULL) || r;
+ r = ((glDebugMessageEnableAMD = (PFNGLDEBUGMESSAGEENABLEAMDPROC)glewGetProcAddress((const GLubyte*)"glDebugMessageEnableAMD")) == NULL) || r;
+ r = ((glDebugMessageInsertAMD = (PFNGLDEBUGMESSAGEINSERTAMDPROC)glewGetProcAddress((const GLubyte*)"glDebugMessageInsertAMD")) == NULL) || r;
+ r = ((glGetDebugMessageLogAMD = (PFNGLGETDEBUGMESSAGELOGAMDPROC)glewGetProcAddress((const GLubyte*)"glGetDebugMessageLogAMD")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_AMD_debug_output */
+
+#ifdef GL_AMD_depth_clamp_separate
+
+#endif /* GL_AMD_depth_clamp_separate */
+
+#ifdef GL_AMD_draw_buffers_blend
+
+static GLboolean _glewInit_GL_AMD_draw_buffers_blend (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glBlendEquationIndexedAMD = (PFNGLBLENDEQUATIONINDEXEDAMDPROC)glewGetProcAddress((const GLubyte*)"glBlendEquationIndexedAMD")) == NULL) || r;
+ r = ((glBlendEquationSeparateIndexedAMD = (PFNGLBLENDEQUATIONSEPARATEINDEXEDAMDPROC)glewGetProcAddress((const GLubyte*)"glBlendEquationSeparateIndexedAMD")) == NULL) || r;
+ r = ((glBlendFuncIndexedAMD = (PFNGLBLENDFUNCINDEXEDAMDPROC)glewGetProcAddress((const GLubyte*)"glBlendFuncIndexedAMD")) == NULL) || r;
+ r = ((glBlendFuncSeparateIndexedAMD = (PFNGLBLENDFUNCSEPARATEINDEXEDAMDPROC)glewGetProcAddress((const GLubyte*)"glBlendFuncSeparateIndexedAMD")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_AMD_draw_buffers_blend */
+
+#ifdef GL_AMD_multi_draw_indirect
+
+static GLboolean _glewInit_GL_AMD_multi_draw_indirect (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glMultiDrawArraysIndirectAMD = (PFNGLMULTIDRAWARRAYSINDIRECTAMDPROC)glewGetProcAddress((const GLubyte*)"glMultiDrawArraysIndirectAMD")) == NULL) || r;
+ r = ((glMultiDrawElementsIndirectAMD = (PFNGLMULTIDRAWELEMENTSINDIRECTAMDPROC)glewGetProcAddress((const GLubyte*)"glMultiDrawElementsIndirectAMD")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_AMD_multi_draw_indirect */
+
+#ifdef GL_AMD_name_gen_delete
+
+static GLboolean _glewInit_GL_AMD_name_gen_delete (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glDeleteNamesAMD = (PFNGLDELETENAMESAMDPROC)glewGetProcAddress((const GLubyte*)"glDeleteNamesAMD")) == NULL) || r;
+ r = ((glGenNamesAMD = (PFNGLGENNAMESAMDPROC)glewGetProcAddress((const GLubyte*)"glGenNamesAMD")) == NULL) || r;
+ r = ((glIsNameAMD = (PFNGLISNAMEAMDPROC)glewGetProcAddress((const GLubyte*)"glIsNameAMD")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_AMD_name_gen_delete */
+
+#ifdef GL_AMD_performance_monitor
+
+static GLboolean _glewInit_GL_AMD_performance_monitor (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glBeginPerfMonitorAMD = (PFNGLBEGINPERFMONITORAMDPROC)glewGetProcAddress((const GLubyte*)"glBeginPerfMonitorAMD")) == NULL) || r;
+ r = ((glDeletePerfMonitorsAMD = (PFNGLDELETEPERFMONITORSAMDPROC)glewGetProcAddress((const GLubyte*)"glDeletePerfMonitorsAMD")) == NULL) || r;
+ r = ((glEndPerfMonitorAMD = (PFNGLENDPERFMONITORAMDPROC)glewGetProcAddress((const GLubyte*)"glEndPerfMonitorAMD")) == NULL) || r;
+ r = ((glGenPerfMonitorsAMD = (PFNGLGENPERFMONITORSAMDPROC)glewGetProcAddress((const GLubyte*)"glGenPerfMonitorsAMD")) == NULL) || r;
+ r = ((glGetPerfMonitorCounterDataAMD = (PFNGLGETPERFMONITORCOUNTERDATAAMDPROC)glewGetProcAddress((const GLubyte*)"glGetPerfMonitorCounterDataAMD")) == NULL) || r;
+ r = ((glGetPerfMonitorCounterInfoAMD = (PFNGLGETPERFMONITORCOUNTERINFOAMDPROC)glewGetProcAddress((const GLubyte*)"glGetPerfMonitorCounterInfoAMD")) == NULL) || r;
+ r = ((glGetPerfMonitorCounterStringAMD = (PFNGLGETPERFMONITORCOUNTERSTRINGAMDPROC)glewGetProcAddress((const GLubyte*)"glGetPerfMonitorCounterStringAMD")) == NULL) || r;
+ r = ((glGetPerfMonitorCountersAMD = (PFNGLGETPERFMONITORCOUNTERSAMDPROC)glewGetProcAddress((const GLubyte*)"glGetPerfMonitorCountersAMD")) == NULL) || r;
+ r = ((glGetPerfMonitorGroupStringAMD = (PFNGLGETPERFMONITORGROUPSTRINGAMDPROC)glewGetProcAddress((const GLubyte*)"glGetPerfMonitorGroupStringAMD")) == NULL) || r;
+ r = ((glGetPerfMonitorGroupsAMD = (PFNGLGETPERFMONITORGROUPSAMDPROC)glewGetProcAddress((const GLubyte*)"glGetPerfMonitorGroupsAMD")) == NULL) || r;
+ r = ((glSelectPerfMonitorCountersAMD = (PFNGLSELECTPERFMONITORCOUNTERSAMDPROC)glewGetProcAddress((const GLubyte*)"glSelectPerfMonitorCountersAMD")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_AMD_performance_monitor */
+
+#ifdef GL_AMD_pinned_memory
+
+#endif /* GL_AMD_pinned_memory */
+
+#ifdef GL_AMD_query_buffer_object
+
+#endif /* GL_AMD_query_buffer_object */
+
+#ifdef GL_AMD_sample_positions
+
+static GLboolean _glewInit_GL_AMD_sample_positions (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glSetMultisamplefvAMD = (PFNGLSETMULTISAMPLEFVAMDPROC)glewGetProcAddress((const GLubyte*)"glSetMultisamplefvAMD")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_AMD_sample_positions */
+
+#ifdef GL_AMD_seamless_cubemap_per_texture
+
+#endif /* GL_AMD_seamless_cubemap_per_texture */
+
+#ifdef GL_AMD_shader_stencil_export
+
+#endif /* GL_AMD_shader_stencil_export */
+
+#ifdef GL_AMD_shader_trinary_minmax
+
+#endif /* GL_AMD_shader_trinary_minmax */
+
+#ifdef GL_AMD_sparse_texture
+
+static GLboolean _glewInit_GL_AMD_sparse_texture (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glTexStorageSparseAMD = (PFNGLTEXSTORAGESPARSEAMDPROC)glewGetProcAddress((const GLubyte*)"glTexStorageSparseAMD")) == NULL) || r;
+ r = ((glTextureStorageSparseAMD = (PFNGLTEXTURESTORAGESPARSEAMDPROC)glewGetProcAddress((const GLubyte*)"glTextureStorageSparseAMD")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_AMD_sparse_texture */
+
+#ifdef GL_AMD_stencil_operation_extended
+
+static GLboolean _glewInit_GL_AMD_stencil_operation_extended (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glStencilOpValueAMD = (PFNGLSTENCILOPVALUEAMDPROC)glewGetProcAddress((const GLubyte*)"glStencilOpValueAMD")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_AMD_stencil_operation_extended */
+
+#ifdef GL_AMD_texture_texture4
+
+#endif /* GL_AMD_texture_texture4 */
+
+#ifdef GL_AMD_transform_feedback3_lines_triangles
+
+#endif /* GL_AMD_transform_feedback3_lines_triangles */
+
+#ifdef GL_AMD_vertex_shader_layer
+
+#endif /* GL_AMD_vertex_shader_layer */
+
+#ifdef GL_AMD_vertex_shader_tessellator
+
+static GLboolean _glewInit_GL_AMD_vertex_shader_tessellator (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glTessellationFactorAMD = (PFNGLTESSELLATIONFACTORAMDPROC)glewGetProcAddress((const GLubyte*)"glTessellationFactorAMD")) == NULL) || r;
+ r = ((glTessellationModeAMD = (PFNGLTESSELLATIONMODEAMDPROC)glewGetProcAddress((const GLubyte*)"glTessellationModeAMD")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_AMD_vertex_shader_tessellator */
+
+#ifdef GL_AMD_vertex_shader_viewport_index
+
+#endif /* GL_AMD_vertex_shader_viewport_index */
+
+#ifdef GL_APPLE_aux_depth_stencil
+
+#endif /* GL_APPLE_aux_depth_stencil */
+
+#ifdef GL_APPLE_client_storage
+
+#endif /* GL_APPLE_client_storage */
+
+#ifdef GL_APPLE_element_array
+
+static GLboolean _glewInit_GL_APPLE_element_array (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glDrawElementArrayAPPLE = (PFNGLDRAWELEMENTARRAYAPPLEPROC)glewGetProcAddress((const GLubyte*)"glDrawElementArrayAPPLE")) == NULL) || r;
+ r = ((glDrawRangeElementArrayAPPLE = (PFNGLDRAWRANGEELEMENTARRAYAPPLEPROC)glewGetProcAddress((const GLubyte*)"glDrawRangeElementArrayAPPLE")) == NULL) || r;
+ r = ((glElementPointerAPPLE = (PFNGLELEMENTPOINTERAPPLEPROC)glewGetProcAddress((const GLubyte*)"glElementPointerAPPLE")) == NULL) || r;
+ r = ((glMultiDrawElementArrayAPPLE = (PFNGLMULTIDRAWELEMENTARRAYAPPLEPROC)glewGetProcAddress((const GLubyte*)"glMultiDrawElementArrayAPPLE")) == NULL) || r;
+ r = ((glMultiDrawRangeElementArrayAPPLE = (PFNGLMULTIDRAWRANGEELEMENTARRAYAPPLEPROC)glewGetProcAddress((const GLubyte*)"glMultiDrawRangeElementArrayAPPLE")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_APPLE_element_array */
+
+#ifdef GL_APPLE_fence
+
+static GLboolean _glewInit_GL_APPLE_fence (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glDeleteFencesAPPLE = (PFNGLDELETEFENCESAPPLEPROC)glewGetProcAddress((const GLubyte*)"glDeleteFencesAPPLE")) == NULL) || r;
+ r = ((glFinishFenceAPPLE = (PFNGLFINISHFENCEAPPLEPROC)glewGetProcAddress((const GLubyte*)"glFinishFenceAPPLE")) == NULL) || r;
+ r = ((glFinishObjectAPPLE = (PFNGLFINISHOBJECTAPPLEPROC)glewGetProcAddress((const GLubyte*)"glFinishObjectAPPLE")) == NULL) || r;
+ r = ((glGenFencesAPPLE = (PFNGLGENFENCESAPPLEPROC)glewGetProcAddress((const GLubyte*)"glGenFencesAPPLE")) == NULL) || r;
+ r = ((glIsFenceAPPLE = (PFNGLISFENCEAPPLEPROC)glewGetProcAddress((const GLubyte*)"glIsFenceAPPLE")) == NULL) || r;
+ r = ((glSetFenceAPPLE = (PFNGLSETFENCEAPPLEPROC)glewGetProcAddress((const GLubyte*)"glSetFenceAPPLE")) == NULL) || r;
+ r = ((glTestFenceAPPLE = (PFNGLTESTFENCEAPPLEPROC)glewGetProcAddress((const GLubyte*)"glTestFenceAPPLE")) == NULL) || r;
+ r = ((glTestObjectAPPLE = (PFNGLTESTOBJECTAPPLEPROC)glewGetProcAddress((const GLubyte*)"glTestObjectAPPLE")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_APPLE_fence */
+
+#ifdef GL_APPLE_float_pixels
+
+#endif /* GL_APPLE_float_pixels */
+
+#ifdef GL_APPLE_flush_buffer_range
+
+static GLboolean _glewInit_GL_APPLE_flush_buffer_range (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glBufferParameteriAPPLE = (PFNGLBUFFERPARAMETERIAPPLEPROC)glewGetProcAddress((const GLubyte*)"glBufferParameteriAPPLE")) == NULL) || r;
+ r = ((glFlushMappedBufferRangeAPPLE = (PFNGLFLUSHMAPPEDBUFFERRANGEAPPLEPROC)glewGetProcAddress((const GLubyte*)"glFlushMappedBufferRangeAPPLE")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_APPLE_flush_buffer_range */
+
+#ifdef GL_APPLE_object_purgeable
+
+static GLboolean _glewInit_GL_APPLE_object_purgeable (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glGetObjectParameterivAPPLE = (PFNGLGETOBJECTPARAMETERIVAPPLEPROC)glewGetProcAddress((const GLubyte*)"glGetObjectParameterivAPPLE")) == NULL) || r;
+ r = ((glObjectPurgeableAPPLE = (PFNGLOBJECTPURGEABLEAPPLEPROC)glewGetProcAddress((const GLubyte*)"glObjectPurgeableAPPLE")) == NULL) || r;
+ r = ((glObjectUnpurgeableAPPLE = (PFNGLOBJECTUNPURGEABLEAPPLEPROC)glewGetProcAddress((const GLubyte*)"glObjectUnpurgeableAPPLE")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_APPLE_object_purgeable */
+
+#ifdef GL_APPLE_pixel_buffer
+
+#endif /* GL_APPLE_pixel_buffer */
+
+#ifdef GL_APPLE_rgb_422
+
+#endif /* GL_APPLE_rgb_422 */
+
+#ifdef GL_APPLE_row_bytes
+
+#endif /* GL_APPLE_row_bytes */
+
+#ifdef GL_APPLE_specular_vector
+
+#endif /* GL_APPLE_specular_vector */
+
+#ifdef GL_APPLE_texture_range
+
+static GLboolean _glewInit_GL_APPLE_texture_range (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glGetTexParameterPointervAPPLE = (PFNGLGETTEXPARAMETERPOINTERVAPPLEPROC)glewGetProcAddress((const GLubyte*)"glGetTexParameterPointervAPPLE")) == NULL) || r;
+ r = ((glTextureRangeAPPLE = (PFNGLTEXTURERANGEAPPLEPROC)glewGetProcAddress((const GLubyte*)"glTextureRangeAPPLE")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_APPLE_texture_range */
+
+#ifdef GL_APPLE_transform_hint
+
+#endif /* GL_APPLE_transform_hint */
+
+#ifdef GL_APPLE_vertex_array_object
+
+static GLboolean _glewInit_GL_APPLE_vertex_array_object (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glBindVertexArrayAPPLE = (PFNGLBINDVERTEXARRAYAPPLEPROC)glewGetProcAddress((const GLubyte*)"glBindVertexArrayAPPLE")) == NULL) || r;
+ r = ((glDeleteVertexArraysAPPLE = (PFNGLDELETEVERTEXARRAYSAPPLEPROC)glewGetProcAddress((const GLubyte*)"glDeleteVertexArraysAPPLE")) == NULL) || r;
+ r = ((glGenVertexArraysAPPLE = (PFNGLGENVERTEXARRAYSAPPLEPROC)glewGetProcAddress((const GLubyte*)"glGenVertexArraysAPPLE")) == NULL) || r;
+ r = ((glIsVertexArrayAPPLE = (PFNGLISVERTEXARRAYAPPLEPROC)glewGetProcAddress((const GLubyte*)"glIsVertexArrayAPPLE")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_APPLE_vertex_array_object */
+
+#ifdef GL_APPLE_vertex_array_range
+
+static GLboolean _glewInit_GL_APPLE_vertex_array_range (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glFlushVertexArrayRangeAPPLE = (PFNGLFLUSHVERTEXARRAYRANGEAPPLEPROC)glewGetProcAddress((const GLubyte*)"glFlushVertexArrayRangeAPPLE")) == NULL) || r;
+ r = ((glVertexArrayParameteriAPPLE = (PFNGLVERTEXARRAYPARAMETERIAPPLEPROC)glewGetProcAddress((const GLubyte*)"glVertexArrayParameteriAPPLE")) == NULL) || r;
+ r = ((glVertexArrayRangeAPPLE = (PFNGLVERTEXARRAYRANGEAPPLEPROC)glewGetProcAddress((const GLubyte*)"glVertexArrayRangeAPPLE")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_APPLE_vertex_array_range */
+
+#ifdef GL_APPLE_vertex_program_evaluators
+
+static GLboolean _glewInit_GL_APPLE_vertex_program_evaluators (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glDisableVertexAttribAPPLE = (PFNGLDISABLEVERTEXATTRIBAPPLEPROC)glewGetProcAddress((const GLubyte*)"glDisableVertexAttribAPPLE")) == NULL) || r;
+ r = ((glEnableVertexAttribAPPLE = (PFNGLENABLEVERTEXATTRIBAPPLEPROC)glewGetProcAddress((const GLubyte*)"glEnableVertexAttribAPPLE")) == NULL) || r;
+ r = ((glIsVertexAttribEnabledAPPLE = (PFNGLISVERTEXATTRIBENABLEDAPPLEPROC)glewGetProcAddress((const GLubyte*)"glIsVertexAttribEnabledAPPLE")) == NULL) || r;
+ r = ((glMapVertexAttrib1dAPPLE = (PFNGLMAPVERTEXATTRIB1DAPPLEPROC)glewGetProcAddress((const GLubyte*)"glMapVertexAttrib1dAPPLE")) == NULL) || r;
+ r = ((glMapVertexAttrib1fAPPLE = (PFNGLMAPVERTEXATTRIB1FAPPLEPROC)glewGetProcAddress((const GLubyte*)"glMapVertexAttrib1fAPPLE")) == NULL) || r;
+ r = ((glMapVertexAttrib2dAPPLE = (PFNGLMAPVERTEXATTRIB2DAPPLEPROC)glewGetProcAddress((const GLubyte*)"glMapVertexAttrib2dAPPLE")) == NULL) || r;
+ r = ((glMapVertexAttrib2fAPPLE = (PFNGLMAPVERTEXATTRIB2FAPPLEPROC)glewGetProcAddress((const GLubyte*)"glMapVertexAttrib2fAPPLE")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_APPLE_vertex_program_evaluators */
+
+#ifdef GL_APPLE_ycbcr_422
+
+#endif /* GL_APPLE_ycbcr_422 */
+
+#ifdef GL_ARB_ES2_compatibility
+
+static GLboolean _glewInit_GL_ARB_ES2_compatibility (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glClearDepthf = (PFNGLCLEARDEPTHFPROC)glewGetProcAddress((const GLubyte*)"glClearDepthf")) == NULL) || r;
+ r = ((glDepthRangef = (PFNGLDEPTHRANGEFPROC)glewGetProcAddress((const GLubyte*)"glDepthRangef")) == NULL) || r;
+ r = ((glGetShaderPrecisionFormat = (PFNGLGETSHADERPRECISIONFORMATPROC)glewGetProcAddress((const GLubyte*)"glGetShaderPrecisionFormat")) == NULL) || r;
+ r = ((glReleaseShaderCompiler = (PFNGLRELEASESHADERCOMPILERPROC)glewGetProcAddress((const GLubyte*)"glReleaseShaderCompiler")) == NULL) || r;
+ r = ((glShaderBinary = (PFNGLSHADERBINARYPROC)glewGetProcAddress((const GLubyte*)"glShaderBinary")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_ARB_ES2_compatibility */
+
+#ifdef GL_ARB_ES3_compatibility
+
+#endif /* GL_ARB_ES3_compatibility */
+
+#ifdef GL_ARB_arrays_of_arrays
+
+#endif /* GL_ARB_arrays_of_arrays */
+
+#ifdef GL_ARB_base_instance
+
+static GLboolean _glewInit_GL_ARB_base_instance (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glDrawArraysInstancedBaseInstance = (PFNGLDRAWARRAYSINSTANCEDBASEINSTANCEPROC)glewGetProcAddress((const GLubyte*)"glDrawArraysInstancedBaseInstance")) == NULL) || r;
+ r = ((glDrawElementsInstancedBaseInstance = (PFNGLDRAWELEMENTSINSTANCEDBASEINSTANCEPROC)glewGetProcAddress((const GLubyte*)"glDrawElementsInstancedBaseInstance")) == NULL) || r;
+ r = ((glDrawElementsInstancedBaseVertexBaseInstance = (PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXBASEINSTANCEPROC)glewGetProcAddress((const GLubyte*)"glDrawElementsInstancedBaseVertexBaseInstance")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_ARB_base_instance */
+
+#ifdef GL_ARB_blend_func_extended
+
+static GLboolean _glewInit_GL_ARB_blend_func_extended (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glBindFragDataLocationIndexed = (PFNGLBINDFRAGDATALOCATIONINDEXEDPROC)glewGetProcAddress((const GLubyte*)"glBindFragDataLocationIndexed")) == NULL) || r;
+ r = ((glGetFragDataIndex = (PFNGLGETFRAGDATAINDEXPROC)glewGetProcAddress((const GLubyte*)"glGetFragDataIndex")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_ARB_blend_func_extended */
+
+#ifdef GL_ARB_cl_event
+
+static GLboolean _glewInit_GL_ARB_cl_event (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glCreateSyncFromCLeventARB = (PFNGLCREATESYNCFROMCLEVENTARBPROC)glewGetProcAddress((const GLubyte*)"glCreateSyncFromCLeventARB")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_ARB_cl_event */
+
+#ifdef GL_ARB_clear_buffer_object
+
+static GLboolean _glewInit_GL_ARB_clear_buffer_object (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glClearBufferData = (PFNGLCLEARBUFFERDATAPROC)glewGetProcAddress((const GLubyte*)"glClearBufferData")) == NULL) || r;
+ r = ((glClearBufferSubData = (PFNGLCLEARBUFFERSUBDATAPROC)glewGetProcAddress((const GLubyte*)"glClearBufferSubData")) == NULL) || r;
+ r = ((glClearNamedBufferDataEXT = (PFNGLCLEARNAMEDBUFFERDATAEXTPROC)glewGetProcAddress((const GLubyte*)"glClearNamedBufferDataEXT")) == NULL) || r;
+ r = ((glClearNamedBufferSubDataEXT = (PFNGLCLEARNAMEDBUFFERSUBDATAEXTPROC)glewGetProcAddress((const GLubyte*)"glClearNamedBufferSubDataEXT")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_ARB_clear_buffer_object */
+
+#ifdef GL_ARB_color_buffer_float
+
+static GLboolean _glewInit_GL_ARB_color_buffer_float (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glClampColorARB = (PFNGLCLAMPCOLORARBPROC)glewGetProcAddress((const GLubyte*)"glClampColorARB")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_ARB_color_buffer_float */
+
+#ifdef GL_ARB_compatibility
+
+#endif /* GL_ARB_compatibility */
+
+#ifdef GL_ARB_compressed_texture_pixel_storage
+
+#endif /* GL_ARB_compressed_texture_pixel_storage */
+
+#ifdef GL_ARB_compute_shader
+
+static GLboolean _glewInit_GL_ARB_compute_shader (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glDispatchCompute = (PFNGLDISPATCHCOMPUTEPROC)glewGetProcAddress((const GLubyte*)"glDispatchCompute")) == NULL) || r;
+ r = ((glDispatchComputeIndirect = (PFNGLDISPATCHCOMPUTEINDIRECTPROC)glewGetProcAddress((const GLubyte*)"glDispatchComputeIndirect")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_ARB_compute_shader */
+
+#ifdef GL_ARB_conservative_depth
+
+#endif /* GL_ARB_conservative_depth */
+
+#ifdef GL_ARB_copy_buffer
+
+static GLboolean _glewInit_GL_ARB_copy_buffer (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glCopyBufferSubData = (PFNGLCOPYBUFFERSUBDATAPROC)glewGetProcAddress((const GLubyte*)"glCopyBufferSubData")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_ARB_copy_buffer */
+
+#ifdef GL_ARB_copy_image
+
+static GLboolean _glewInit_GL_ARB_copy_image (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glCopyImageSubData = (PFNGLCOPYIMAGESUBDATAPROC)glewGetProcAddress((const GLubyte*)"glCopyImageSubData")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_ARB_copy_image */
+
+#ifdef GL_ARB_debug_output
+
+static GLboolean _glewInit_GL_ARB_debug_output (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glDebugMessageCallbackARB = (PFNGLDEBUGMESSAGECALLBACKARBPROC)glewGetProcAddress((const GLubyte*)"glDebugMessageCallbackARB")) == NULL) || r;
+ r = ((glDebugMessageControlARB = (PFNGLDEBUGMESSAGECONTROLARBPROC)glewGetProcAddress((const GLubyte*)"glDebugMessageControlARB")) == NULL) || r;
+ r = ((glDebugMessageInsertARB = (PFNGLDEBUGMESSAGEINSERTARBPROC)glewGetProcAddress((const GLubyte*)"glDebugMessageInsertARB")) == NULL) || r;
+ r = ((glGetDebugMessageLogARB = (PFNGLGETDEBUGMESSAGELOGARBPROC)glewGetProcAddress((const GLubyte*)"glGetDebugMessageLogARB")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_ARB_debug_output */
+
+#ifdef GL_ARB_depth_buffer_float
+
+#endif /* GL_ARB_depth_buffer_float */
+
+#ifdef GL_ARB_depth_clamp
+
+#endif /* GL_ARB_depth_clamp */
+
+#ifdef GL_ARB_depth_texture
+
+#endif /* GL_ARB_depth_texture */
+
+#ifdef GL_ARB_draw_buffers
+
+static GLboolean _glewInit_GL_ARB_draw_buffers (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glDrawBuffersARB = (PFNGLDRAWBUFFERSARBPROC)glewGetProcAddress((const GLubyte*)"glDrawBuffersARB")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_ARB_draw_buffers */
+
+#ifdef GL_ARB_draw_buffers_blend
+
+static GLboolean _glewInit_GL_ARB_draw_buffers_blend (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glBlendEquationSeparateiARB = (PFNGLBLENDEQUATIONSEPARATEIARBPROC)glewGetProcAddress((const GLubyte*)"glBlendEquationSeparateiARB")) == NULL) || r;
+ r = ((glBlendEquationiARB = (PFNGLBLENDEQUATIONIARBPROC)glewGetProcAddress((const GLubyte*)"glBlendEquationiARB")) == NULL) || r;
+ r = ((glBlendFuncSeparateiARB = (PFNGLBLENDFUNCSEPARATEIARBPROC)glewGetProcAddress((const GLubyte*)"glBlendFuncSeparateiARB")) == NULL) || r;
+ r = ((glBlendFunciARB = (PFNGLBLENDFUNCIARBPROC)glewGetProcAddress((const GLubyte*)"glBlendFunciARB")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_ARB_draw_buffers_blend */
+
+#ifdef GL_ARB_draw_elements_base_vertex
+
+static GLboolean _glewInit_GL_ARB_draw_elements_base_vertex (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glDrawElementsBaseVertex = (PFNGLDRAWELEMENTSBASEVERTEXPROC)glewGetProcAddress((const GLubyte*)"glDrawElementsBaseVertex")) == NULL) || r;
+ r = ((glDrawElementsInstancedBaseVertex = (PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXPROC)glewGetProcAddress((const GLubyte*)"glDrawElementsInstancedBaseVertex")) == NULL) || r;
+ r = ((glDrawRangeElementsBaseVertex = (PFNGLDRAWRANGEELEMENTSBASEVERTEXPROC)glewGetProcAddress((const GLubyte*)"glDrawRangeElementsBaseVertex")) == NULL) || r;
+ r = ((glMultiDrawElementsBaseVertex = (PFNGLMULTIDRAWELEMENTSBASEVERTEXPROC)glewGetProcAddress((const GLubyte*)"glMultiDrawElementsBaseVertex")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_ARB_draw_elements_base_vertex */
+
+#ifdef GL_ARB_draw_indirect
+
+static GLboolean _glewInit_GL_ARB_draw_indirect (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glDrawArraysIndirect = (PFNGLDRAWARRAYSINDIRECTPROC)glewGetProcAddress((const GLubyte*)"glDrawArraysIndirect")) == NULL) || r;
+ r = ((glDrawElementsIndirect = (PFNGLDRAWELEMENTSINDIRECTPROC)glewGetProcAddress((const GLubyte*)"glDrawElementsIndirect")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_ARB_draw_indirect */
+
+#ifdef GL_ARB_draw_instanced
+
+#endif /* GL_ARB_draw_instanced */
+
+#ifdef GL_ARB_explicit_attrib_location
+
+#endif /* GL_ARB_explicit_attrib_location */
+
+#ifdef GL_ARB_explicit_uniform_location
+
+#endif /* GL_ARB_explicit_uniform_location */
+
+#ifdef GL_ARB_fragment_coord_conventions
+
+#endif /* GL_ARB_fragment_coord_conventions */
+
+#ifdef GL_ARB_fragment_layer_viewport
+
+#endif /* GL_ARB_fragment_layer_viewport */
+
+#ifdef GL_ARB_fragment_program
+
+#endif /* GL_ARB_fragment_program */
+
+#ifdef GL_ARB_fragment_program_shadow
+
+#endif /* GL_ARB_fragment_program_shadow */
+
+#ifdef GL_ARB_fragment_shader
+
+#endif /* GL_ARB_fragment_shader */
+
+#ifdef GL_ARB_framebuffer_no_attachments
+
+static GLboolean _glewInit_GL_ARB_framebuffer_no_attachments (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glFramebufferParameteri = (PFNGLFRAMEBUFFERPARAMETERIPROC)glewGetProcAddress((const GLubyte*)"glFramebufferParameteri")) == NULL) || r;
+ r = ((glGetFramebufferParameteriv = (PFNGLGETFRAMEBUFFERPARAMETERIVPROC)glewGetProcAddress((const GLubyte*)"glGetFramebufferParameteriv")) == NULL) || r;
+ r = ((glGetNamedFramebufferParameterivEXT = (PFNGLGETNAMEDFRAMEBUFFERPARAMETERIVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetNamedFramebufferParameterivEXT")) == NULL) || r;
+ r = ((glNamedFramebufferParameteriEXT = (PFNGLNAMEDFRAMEBUFFERPARAMETERIEXTPROC)glewGetProcAddress((const GLubyte*)"glNamedFramebufferParameteriEXT")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_ARB_framebuffer_no_attachments */
+
+#ifdef GL_ARB_framebuffer_object
+
+static GLboolean _glewInit_GL_ARB_framebuffer_object (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glBindFramebuffer = (PFNGLBINDFRAMEBUFFERPROC)glewGetProcAddress((const GLubyte*)"glBindFramebuffer")) == NULL) || r;
+ r = ((glBindRenderbuffer = (PFNGLBINDRENDERBUFFERPROC)glewGetProcAddress((const GLubyte*)"glBindRenderbuffer")) == NULL) || r;
+ r = ((glBlitFramebuffer = (PFNGLBLITFRAMEBUFFERPROC)glewGetProcAddress((const GLubyte*)"glBlitFramebuffer")) == NULL) || r;
+ r = ((glCheckFramebufferStatus = (PFNGLCHECKFRAMEBUFFERSTATUSPROC)glewGetProcAddress((const GLubyte*)"glCheckFramebufferStatus")) == NULL) || r;
+ r = ((glDeleteFramebuffers = (PFNGLDELETEFRAMEBUFFERSPROC)glewGetProcAddress((const GLubyte*)"glDeleteFramebuffers")) == NULL) || r;
+ r = ((glDeleteRenderbuffers = (PFNGLDELETERENDERBUFFERSPROC)glewGetProcAddress((const GLubyte*)"glDeleteRenderbuffers")) == NULL) || r;
+ r = ((glFramebufferRenderbuffer = (PFNGLFRAMEBUFFERRENDERBUFFERPROC)glewGetProcAddress((const GLubyte*)"glFramebufferRenderbuffer")) == NULL) || r;
+ r = ((glFramebufferTexture1D = (PFNGLFRAMEBUFFERTEXTURE1DPROC)glewGetProcAddress((const GLubyte*)"glFramebufferTexture1D")) == NULL) || r;
+ r = ((glFramebufferTexture2D = (PFNGLFRAMEBUFFERTEXTURE2DPROC)glewGetProcAddress((const GLubyte*)"glFramebufferTexture2D")) == NULL) || r;
+ r = ((glFramebufferTexture3D = (PFNGLFRAMEBUFFERTEXTURE3DPROC)glewGetProcAddress((const GLubyte*)"glFramebufferTexture3D")) == NULL) || r;
+ r = ((glFramebufferTextureLayer = (PFNGLFRAMEBUFFERTEXTURELAYERPROC)glewGetProcAddress((const GLubyte*)"glFramebufferTextureLayer")) == NULL) || r;
+ r = ((glGenFramebuffers = (PFNGLGENFRAMEBUFFERSPROC)glewGetProcAddress((const GLubyte*)"glGenFramebuffers")) == NULL) || r;
+ r = ((glGenRenderbuffers = (PFNGLGENRENDERBUFFERSPROC)glewGetProcAddress((const GLubyte*)"glGenRenderbuffers")) == NULL) || r;
+ r = ((glGenerateMipmap = (PFNGLGENERATEMIPMAPPROC)glewGetProcAddress((const GLubyte*)"glGenerateMipmap")) == NULL) || r;
+ r = ((glGetFramebufferAttachmentParameteriv = (PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC)glewGetProcAddress((const GLubyte*)"glGetFramebufferAttachmentParameteriv")) == NULL) || r;
+ r = ((glGetRenderbufferParameteriv = (PFNGLGETRENDERBUFFERPARAMETERIVPROC)glewGetProcAddress((const GLubyte*)"glGetRenderbufferParameteriv")) == NULL) || r;
+ r = ((glIsFramebuffer = (PFNGLISFRAMEBUFFERPROC)glewGetProcAddress((const GLubyte*)"glIsFramebuffer")) == NULL) || r;
+ r = ((glIsRenderbuffer = (PFNGLISRENDERBUFFERPROC)glewGetProcAddress((const GLubyte*)"glIsRenderbuffer")) == NULL) || r;
+ r = ((glRenderbufferStorage = (PFNGLRENDERBUFFERSTORAGEPROC)glewGetProcAddress((const GLubyte*)"glRenderbufferStorage")) == NULL) || r;
+ r = ((glRenderbufferStorageMultisample = (PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC)glewGetProcAddress((const GLubyte*)"glRenderbufferStorageMultisample")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_ARB_framebuffer_object */
+
+#ifdef GL_ARB_framebuffer_sRGB
+
+#endif /* GL_ARB_framebuffer_sRGB */
+
+#ifdef GL_ARB_geometry_shader4
+
+static GLboolean _glewInit_GL_ARB_geometry_shader4 (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glFramebufferTextureARB = (PFNGLFRAMEBUFFERTEXTUREARBPROC)glewGetProcAddress((const GLubyte*)"glFramebufferTextureARB")) == NULL) || r;
+ r = ((glFramebufferTextureFaceARB = (PFNGLFRAMEBUFFERTEXTUREFACEARBPROC)glewGetProcAddress((const GLubyte*)"glFramebufferTextureFaceARB")) == NULL) || r;
+ r = ((glFramebufferTextureLayerARB = (PFNGLFRAMEBUFFERTEXTURELAYERARBPROC)glewGetProcAddress((const GLubyte*)"glFramebufferTextureLayerARB")) == NULL) || r;
+ r = ((glProgramParameteriARB = (PFNGLPROGRAMPARAMETERIARBPROC)glewGetProcAddress((const GLubyte*)"glProgramParameteriARB")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_ARB_geometry_shader4 */
+
+#ifdef GL_ARB_get_program_binary
+
+static GLboolean _glewInit_GL_ARB_get_program_binary (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glGetProgramBinary = (PFNGLGETPROGRAMBINARYPROC)glewGetProcAddress((const GLubyte*)"glGetProgramBinary")) == NULL) || r;
+ r = ((glProgramBinary = (PFNGLPROGRAMBINARYPROC)glewGetProcAddress((const GLubyte*)"glProgramBinary")) == NULL) || r;
+ r = ((glProgramParameteri = (PFNGLPROGRAMPARAMETERIPROC)glewGetProcAddress((const GLubyte*)"glProgramParameteri")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_ARB_get_program_binary */
+
+#ifdef GL_ARB_gpu_shader5
+
+#endif /* GL_ARB_gpu_shader5 */
+
+#ifdef GL_ARB_gpu_shader_fp64
+
+static GLboolean _glewInit_GL_ARB_gpu_shader_fp64 (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glGetUniformdv = (PFNGLGETUNIFORMDVPROC)glewGetProcAddress((const GLubyte*)"glGetUniformdv")) == NULL) || r;
+ r = ((glProgramUniform1dEXT = (PFNGLPROGRAMUNIFORM1DEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform1dEXT")) == NULL) || r;
+ r = ((glProgramUniform1dvEXT = (PFNGLPROGRAMUNIFORM1DVEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform1dvEXT")) == NULL) || r;
+ r = ((glProgramUniform2dEXT = (PFNGLPROGRAMUNIFORM2DEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform2dEXT")) == NULL) || r;
+ r = ((glProgramUniform2dvEXT = (PFNGLPROGRAMUNIFORM2DVEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform2dvEXT")) == NULL) || r;
+ r = ((glProgramUniform3dEXT = (PFNGLPROGRAMUNIFORM3DEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform3dEXT")) == NULL) || r;
+ r = ((glProgramUniform3dvEXT = (PFNGLPROGRAMUNIFORM3DVEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform3dvEXT")) == NULL) || r;
+ r = ((glProgramUniform4dEXT = (PFNGLPROGRAMUNIFORM4DEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform4dEXT")) == NULL) || r;
+ r = ((glProgramUniform4dvEXT = (PFNGLPROGRAMUNIFORM4DVEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform4dvEXT")) == NULL) || r;
+ r = ((glProgramUniformMatrix2dvEXT = (PFNGLPROGRAMUNIFORMMATRIX2DVEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramUniformMatrix2dvEXT")) == NULL) || r;
+ r = ((glProgramUniformMatrix2x3dvEXT = (PFNGLPROGRAMUNIFORMMATRIX2X3DVEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramUniformMatrix2x3dvEXT")) == NULL) || r;
+ r = ((glProgramUniformMatrix2x4dvEXT = (PFNGLPROGRAMUNIFORMMATRIX2X4DVEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramUniformMatrix2x4dvEXT")) == NULL) || r;
+ r = ((glProgramUniformMatrix3dvEXT = (PFNGLPROGRAMUNIFORMMATRIX3DVEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramUniformMatrix3dvEXT")) == NULL) || r;
+ r = ((glProgramUniformMatrix3x2dvEXT = (PFNGLPROGRAMUNIFORMMATRIX3X2DVEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramUniformMatrix3x2dvEXT")) == NULL) || r;
+ r = ((glProgramUniformMatrix3x4dvEXT = (PFNGLPROGRAMUNIFORMMATRIX3X4DVEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramUniformMatrix3x4dvEXT")) == NULL) || r;
+ r = ((glProgramUniformMatrix4dvEXT = (PFNGLPROGRAMUNIFORMMATRIX4DVEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramUniformMatrix4dvEXT")) == NULL) || r;
+ r = ((glProgramUniformMatrix4x2dvEXT = (PFNGLPROGRAMUNIFORMMATRIX4X2DVEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramUniformMatrix4x2dvEXT")) == NULL) || r;
+ r = ((glProgramUniformMatrix4x3dvEXT = (PFNGLPROGRAMUNIFORMMATRIX4X3DVEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramUniformMatrix4x3dvEXT")) == NULL) || r;
+ r = ((glUniform1d = (PFNGLUNIFORM1DPROC)glewGetProcAddress((const GLubyte*)"glUniform1d")) == NULL) || r;
+ r = ((glUniform1dv = (PFNGLUNIFORM1DVPROC)glewGetProcAddress((const GLubyte*)"glUniform1dv")) == NULL) || r;
+ r = ((glUniform2d = (PFNGLUNIFORM2DPROC)glewGetProcAddress((const GLubyte*)"glUniform2d")) == NULL) || r;
+ r = ((glUniform2dv = (PFNGLUNIFORM2DVPROC)glewGetProcAddress((const GLubyte*)"glUniform2dv")) == NULL) || r;
+ r = ((glUniform3d = (PFNGLUNIFORM3DPROC)glewGetProcAddress((const GLubyte*)"glUniform3d")) == NULL) || r;
+ r = ((glUniform3dv = (PFNGLUNIFORM3DVPROC)glewGetProcAddress((const GLubyte*)"glUniform3dv")) == NULL) || r;
+ r = ((glUniform4d = (PFNGLUNIFORM4DPROC)glewGetProcAddress((const GLubyte*)"glUniform4d")) == NULL) || r;
+ r = ((glUniform4dv = (PFNGLUNIFORM4DVPROC)glewGetProcAddress((const GLubyte*)"glUniform4dv")) == NULL) || r;
+ r = ((glUniformMatrix2dv = (PFNGLUNIFORMMATRIX2DVPROC)glewGetProcAddress((const GLubyte*)"glUniformMatrix2dv")) == NULL) || r;
+ r = ((glUniformMatrix2x3dv = (PFNGLUNIFORMMATRIX2X3DVPROC)glewGetProcAddress((const GLubyte*)"glUniformMatrix2x3dv")) == NULL) || r;
+ r = ((glUniformMatrix2x4dv = (PFNGLUNIFORMMATRIX2X4DVPROC)glewGetProcAddress((const GLubyte*)"glUniformMatrix2x4dv")) == NULL) || r;
+ r = ((glUniformMatrix3dv = (PFNGLUNIFORMMATRIX3DVPROC)glewGetProcAddress((const GLubyte*)"glUniformMatrix3dv")) == NULL) || r;
+ r = ((glUniformMatrix3x2dv = (PFNGLUNIFORMMATRIX3X2DVPROC)glewGetProcAddress((const GLubyte*)"glUniformMatrix3x2dv")) == NULL) || r;
+ r = ((glUniformMatrix3x4dv = (PFNGLUNIFORMMATRIX3X4DVPROC)glewGetProcAddress((const GLubyte*)"glUniformMatrix3x4dv")) == NULL) || r;
+ r = ((glUniformMatrix4dv = (PFNGLUNIFORMMATRIX4DVPROC)glewGetProcAddress((const GLubyte*)"glUniformMatrix4dv")) == NULL) || r;
+ r = ((glUniformMatrix4x2dv = (PFNGLUNIFORMMATRIX4X2DVPROC)glewGetProcAddress((const GLubyte*)"glUniformMatrix4x2dv")) == NULL) || r;
+ r = ((glUniformMatrix4x3dv = (PFNGLUNIFORMMATRIX4X3DVPROC)glewGetProcAddress((const GLubyte*)"glUniformMatrix4x3dv")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_ARB_gpu_shader_fp64 */
+
+#ifdef GL_ARB_half_float_pixel
+
+#endif /* GL_ARB_half_float_pixel */
+
+#ifdef GL_ARB_half_float_vertex
+
+#endif /* GL_ARB_half_float_vertex */
+
+#ifdef GL_ARB_imaging
+
+static GLboolean _glewInit_GL_ARB_imaging (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glBlendEquation = (PFNGLBLENDEQUATIONPROC)glewGetProcAddress((const GLubyte*)"glBlendEquation")) == NULL) || r;
+ r = ((glColorSubTable = (PFNGLCOLORSUBTABLEPROC)glewGetProcAddress((const GLubyte*)"glColorSubTable")) == NULL) || r;
+ r = ((glColorTable = (PFNGLCOLORTABLEPROC)glewGetProcAddress((const GLubyte*)"glColorTable")) == NULL) || r;
+ r = ((glColorTableParameterfv = (PFNGLCOLORTABLEPARAMETERFVPROC)glewGetProcAddress((const GLubyte*)"glColorTableParameterfv")) == NULL) || r;
+ r = ((glColorTableParameteriv = (PFNGLCOLORTABLEPARAMETERIVPROC)glewGetProcAddress((const GLubyte*)"glColorTableParameteriv")) == NULL) || r;
+ r = ((glConvolutionFilter1D = (PFNGLCONVOLUTIONFILTER1DPROC)glewGetProcAddress((const GLubyte*)"glConvolutionFilter1D")) == NULL) || r;
+ r = ((glConvolutionFilter2D = (PFNGLCONVOLUTIONFILTER2DPROC)glewGetProcAddress((const GLubyte*)"glConvolutionFilter2D")) == NULL) || r;
+ r = ((glConvolutionParameterf = (PFNGLCONVOLUTIONPARAMETERFPROC)glewGetProcAddress((const GLubyte*)"glConvolutionParameterf")) == NULL) || r;
+ r = ((glConvolutionParameterfv = (PFNGLCONVOLUTIONPARAMETERFVPROC)glewGetProcAddress((const GLubyte*)"glConvolutionParameterfv")) == NULL) || r;
+ r = ((glConvolutionParameteri = (PFNGLCONVOLUTIONPARAMETERIPROC)glewGetProcAddress((const GLubyte*)"glConvolutionParameteri")) == NULL) || r;
+ r = ((glConvolutionParameteriv = (PFNGLCONVOLUTIONPARAMETERIVPROC)glewGetProcAddress((const GLubyte*)"glConvolutionParameteriv")) == NULL) || r;
+ r = ((glCopyColorSubTable = (PFNGLCOPYCOLORSUBTABLEPROC)glewGetProcAddress((const GLubyte*)"glCopyColorSubTable")) == NULL) || r;
+ r = ((glCopyColorTable = (PFNGLCOPYCOLORTABLEPROC)glewGetProcAddress((const GLubyte*)"glCopyColorTable")) == NULL) || r;
+ r = ((glCopyConvolutionFilter1D = (PFNGLCOPYCONVOLUTIONFILTER1DPROC)glewGetProcAddress((const GLubyte*)"glCopyConvolutionFilter1D")) == NULL) || r;
+ r = ((glCopyConvolutionFilter2D = (PFNGLCOPYCONVOLUTIONFILTER2DPROC)glewGetProcAddress((const GLubyte*)"glCopyConvolutionFilter2D")) == NULL) || r;
+ r = ((glGetColorTable = (PFNGLGETCOLORTABLEPROC)glewGetProcAddress((const GLubyte*)"glGetColorTable")) == NULL) || r;
+ r = ((glGetColorTableParameterfv = (PFNGLGETCOLORTABLEPARAMETERFVPROC)glewGetProcAddress((const GLubyte*)"glGetColorTableParameterfv")) == NULL) || r;
+ r = ((glGetColorTableParameteriv = (PFNGLGETCOLORTABLEPARAMETERIVPROC)glewGetProcAddress((const GLubyte*)"glGetColorTableParameteriv")) == NULL) || r;
+ r = ((glGetConvolutionFilter = (PFNGLGETCONVOLUTIONFILTERPROC)glewGetProcAddress((const GLubyte*)"glGetConvolutionFilter")) == NULL) || r;
+ r = ((glGetConvolutionParameterfv = (PFNGLGETCONVOLUTIONPARAMETERFVPROC)glewGetProcAddress((const GLubyte*)"glGetConvolutionParameterfv")) == NULL) || r;
+ r = ((glGetConvolutionParameteriv = (PFNGLGETCONVOLUTIONPARAMETERIVPROC)glewGetProcAddress((const GLubyte*)"glGetConvolutionParameteriv")) == NULL) || r;
+ r = ((glGetHistogram = (PFNGLGETHISTOGRAMPROC)glewGetProcAddress((const GLubyte*)"glGetHistogram")) == NULL) || r;
+ r = ((glGetHistogramParameterfv = (PFNGLGETHISTOGRAMPARAMETERFVPROC)glewGetProcAddress((const GLubyte*)"glGetHistogramParameterfv")) == NULL) || r;
+ r = ((glGetHistogramParameteriv = (PFNGLGETHISTOGRAMPARAMETERIVPROC)glewGetProcAddress((const GLubyte*)"glGetHistogramParameteriv")) == NULL) || r;
+ r = ((glGetMinmax = (PFNGLGETMINMAXPROC)glewGetProcAddress((const GLubyte*)"glGetMinmax")) == NULL) || r;
+ r = ((glGetMinmaxParameterfv = (PFNGLGETMINMAXPARAMETERFVPROC)glewGetProcAddress((const GLubyte*)"glGetMinmaxParameterfv")) == NULL) || r;
+ r = ((glGetMinmaxParameteriv = (PFNGLGETMINMAXPARAMETERIVPROC)glewGetProcAddress((const GLubyte*)"glGetMinmaxParameteriv")) == NULL) || r;
+ r = ((glGetSeparableFilter = (PFNGLGETSEPARABLEFILTERPROC)glewGetProcAddress((const GLubyte*)"glGetSeparableFilter")) == NULL) || r;
+ r = ((glHistogram = (PFNGLHISTOGRAMPROC)glewGetProcAddress((const GLubyte*)"glHistogram")) == NULL) || r;
+ r = ((glMinmax = (PFNGLMINMAXPROC)glewGetProcAddress((const GLubyte*)"glMinmax")) == NULL) || r;
+ r = ((glResetHistogram = (PFNGLRESETHISTOGRAMPROC)glewGetProcAddress((const GLubyte*)"glResetHistogram")) == NULL) || r;
+ r = ((glResetMinmax = (PFNGLRESETMINMAXPROC)glewGetProcAddress((const GLubyte*)"glResetMinmax")) == NULL) || r;
+ r = ((glSeparableFilter2D = (PFNGLSEPARABLEFILTER2DPROC)glewGetProcAddress((const GLubyte*)"glSeparableFilter2D")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_ARB_imaging */
+
+#ifdef GL_ARB_instanced_arrays
+
+static GLboolean _glewInit_GL_ARB_instanced_arrays (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glDrawArraysInstancedARB = (PFNGLDRAWARRAYSINSTANCEDARBPROC)glewGetProcAddress((const GLubyte*)"glDrawArraysInstancedARB")) == NULL) || r;
+ r = ((glDrawElementsInstancedARB = (PFNGLDRAWELEMENTSINSTANCEDARBPROC)glewGetProcAddress((const GLubyte*)"glDrawElementsInstancedARB")) == NULL) || r;
+ r = ((glVertexAttribDivisorARB = (PFNGLVERTEXATTRIBDIVISORARBPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribDivisorARB")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_ARB_instanced_arrays */
+
+#ifdef GL_ARB_internalformat_query
+
+static GLboolean _glewInit_GL_ARB_internalformat_query (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glGetInternalformativ = (PFNGLGETINTERNALFORMATIVPROC)glewGetProcAddress((const GLubyte*)"glGetInternalformativ")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_ARB_internalformat_query */
+
+#ifdef GL_ARB_internalformat_query2
+
+static GLboolean _glewInit_GL_ARB_internalformat_query2 (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glGetInternalformati64v = (PFNGLGETINTERNALFORMATI64VPROC)glewGetProcAddress((const GLubyte*)"glGetInternalformati64v")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_ARB_internalformat_query2 */
+
+#ifdef GL_ARB_invalidate_subdata
+
+static GLboolean _glewInit_GL_ARB_invalidate_subdata (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glInvalidateBufferData = (PFNGLINVALIDATEBUFFERDATAPROC)glewGetProcAddress((const GLubyte*)"glInvalidateBufferData")) == NULL) || r;
+ r = ((glInvalidateBufferSubData = (PFNGLINVALIDATEBUFFERSUBDATAPROC)glewGetProcAddress((const GLubyte*)"glInvalidateBufferSubData")) == NULL) || r;
+ r = ((glInvalidateFramebuffer = (PFNGLINVALIDATEFRAMEBUFFERPROC)glewGetProcAddress((const GLubyte*)"glInvalidateFramebuffer")) == NULL) || r;
+ r = ((glInvalidateSubFramebuffer = (PFNGLINVALIDATESUBFRAMEBUFFERPROC)glewGetProcAddress((const GLubyte*)"glInvalidateSubFramebuffer")) == NULL) || r;
+ r = ((glInvalidateTexImage = (PFNGLINVALIDATETEXIMAGEPROC)glewGetProcAddress((const GLubyte*)"glInvalidateTexImage")) == NULL) || r;
+ r = ((glInvalidateTexSubImage = (PFNGLINVALIDATETEXSUBIMAGEPROC)glewGetProcAddress((const GLubyte*)"glInvalidateTexSubImage")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_ARB_invalidate_subdata */
+
+#ifdef GL_ARB_map_buffer_alignment
+
+#endif /* GL_ARB_map_buffer_alignment */
+
+#ifdef GL_ARB_map_buffer_range
+
+static GLboolean _glewInit_GL_ARB_map_buffer_range (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glFlushMappedBufferRange = (PFNGLFLUSHMAPPEDBUFFERRANGEPROC)glewGetProcAddress((const GLubyte*)"glFlushMappedBufferRange")) == NULL) || r;
+ r = ((glMapBufferRange = (PFNGLMAPBUFFERRANGEPROC)glewGetProcAddress((const GLubyte*)"glMapBufferRange")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_ARB_map_buffer_range */
+
+#ifdef GL_ARB_matrix_palette
+
+static GLboolean _glewInit_GL_ARB_matrix_palette (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glCurrentPaletteMatrixARB = (PFNGLCURRENTPALETTEMATRIXARBPROC)glewGetProcAddress((const GLubyte*)"glCurrentPaletteMatrixARB")) == NULL) || r;
+ r = ((glMatrixIndexPointerARB = (PFNGLMATRIXINDEXPOINTERARBPROC)glewGetProcAddress((const GLubyte*)"glMatrixIndexPointerARB")) == NULL) || r;
+ r = ((glMatrixIndexubvARB = (PFNGLMATRIXINDEXUBVARBPROC)glewGetProcAddress((const GLubyte*)"glMatrixIndexubvARB")) == NULL) || r;
+ r = ((glMatrixIndexuivARB = (PFNGLMATRIXINDEXUIVARBPROC)glewGetProcAddress((const GLubyte*)"glMatrixIndexuivARB")) == NULL) || r;
+ r = ((glMatrixIndexusvARB = (PFNGLMATRIXINDEXUSVARBPROC)glewGetProcAddress((const GLubyte*)"glMatrixIndexusvARB")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_ARB_matrix_palette */
+
+#ifdef GL_ARB_multi_draw_indirect
+
+static GLboolean _glewInit_GL_ARB_multi_draw_indirect (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glMultiDrawArraysIndirect = (PFNGLMULTIDRAWARRAYSINDIRECTPROC)glewGetProcAddress((const GLubyte*)"glMultiDrawArraysIndirect")) == NULL) || r;
+ r = ((glMultiDrawElementsIndirect = (PFNGLMULTIDRAWELEMENTSINDIRECTPROC)glewGetProcAddress((const GLubyte*)"glMultiDrawElementsIndirect")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_ARB_multi_draw_indirect */
+
+#ifdef GL_ARB_multisample
+
+static GLboolean _glewInit_GL_ARB_multisample (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glSampleCoverageARB = (PFNGLSAMPLECOVERAGEARBPROC)glewGetProcAddress((const GLubyte*)"glSampleCoverageARB")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_ARB_multisample */
+
+#ifdef GL_ARB_multitexture
+
+static GLboolean _glewInit_GL_ARB_multitexture (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glActiveTextureARB = (PFNGLACTIVETEXTUREARBPROC)glewGetProcAddress((const GLubyte*)"glActiveTextureARB")) == NULL) || r;
+ r = ((glClientActiveTextureARB = (PFNGLCLIENTACTIVETEXTUREARBPROC)glewGetProcAddress((const GLubyte*)"glClientActiveTextureARB")) == NULL) || r;
+ r = ((glMultiTexCoord1dARB = (PFNGLMULTITEXCOORD1DARBPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord1dARB")) == NULL) || r;
+ r = ((glMultiTexCoord1dvARB = (PFNGLMULTITEXCOORD1DVARBPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord1dvARB")) == NULL) || r;
+ r = ((glMultiTexCoord1fARB = (PFNGLMULTITEXCOORD1FARBPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord1fARB")) == NULL) || r;
+ r = ((glMultiTexCoord1fvARB = (PFNGLMULTITEXCOORD1FVARBPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord1fvARB")) == NULL) || r;
+ r = ((glMultiTexCoord1iARB = (PFNGLMULTITEXCOORD1IARBPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord1iARB")) == NULL) || r;
+ r = ((glMultiTexCoord1ivARB = (PFNGLMULTITEXCOORD1IVARBPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord1ivARB")) == NULL) || r;
+ r = ((glMultiTexCoord1sARB = (PFNGLMULTITEXCOORD1SARBPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord1sARB")) == NULL) || r;
+ r = ((glMultiTexCoord1svARB = (PFNGLMULTITEXCOORD1SVARBPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord1svARB")) == NULL) || r;
+ r = ((glMultiTexCoord2dARB = (PFNGLMULTITEXCOORD2DARBPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord2dARB")) == NULL) || r;
+ r = ((glMultiTexCoord2dvARB = (PFNGLMULTITEXCOORD2DVARBPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord2dvARB")) == NULL) || r;
+ r = ((glMultiTexCoord2fARB = (PFNGLMULTITEXCOORD2FARBPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord2fARB")) == NULL) || r;
+ r = ((glMultiTexCoord2fvARB = (PFNGLMULTITEXCOORD2FVARBPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord2fvARB")) == NULL) || r;
+ r = ((glMultiTexCoord2iARB = (PFNGLMULTITEXCOORD2IARBPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord2iARB")) == NULL) || r;
+ r = ((glMultiTexCoord2ivARB = (PFNGLMULTITEXCOORD2IVARBPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord2ivARB")) == NULL) || r;
+ r = ((glMultiTexCoord2sARB = (PFNGLMULTITEXCOORD2SARBPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord2sARB")) == NULL) || r;
+ r = ((glMultiTexCoord2svARB = (PFNGLMULTITEXCOORD2SVARBPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord2svARB")) == NULL) || r;
+ r = ((glMultiTexCoord3dARB = (PFNGLMULTITEXCOORD3DARBPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord3dARB")) == NULL) || r;
+ r = ((glMultiTexCoord3dvARB = (PFNGLMULTITEXCOORD3DVARBPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord3dvARB")) == NULL) || r;
+ r = ((glMultiTexCoord3fARB = (PFNGLMULTITEXCOORD3FARBPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord3fARB")) == NULL) || r;
+ r = ((glMultiTexCoord3fvARB = (PFNGLMULTITEXCOORD3FVARBPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord3fvARB")) == NULL) || r;
+ r = ((glMultiTexCoord3iARB = (PFNGLMULTITEXCOORD3IARBPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord3iARB")) == NULL) || r;
+ r = ((glMultiTexCoord3ivARB = (PFNGLMULTITEXCOORD3IVARBPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord3ivARB")) == NULL) || r;
+ r = ((glMultiTexCoord3sARB = (PFNGLMULTITEXCOORD3SARBPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord3sARB")) == NULL) || r;
+ r = ((glMultiTexCoord3svARB = (PFNGLMULTITEXCOORD3SVARBPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord3svARB")) == NULL) || r;
+ r = ((glMultiTexCoord4dARB = (PFNGLMULTITEXCOORD4DARBPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord4dARB")) == NULL) || r;
+ r = ((glMultiTexCoord4dvARB = (PFNGLMULTITEXCOORD4DVARBPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord4dvARB")) == NULL) || r;
+ r = ((glMultiTexCoord4fARB = (PFNGLMULTITEXCOORD4FARBPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord4fARB")) == NULL) || r;
+ r = ((glMultiTexCoord4fvARB = (PFNGLMULTITEXCOORD4FVARBPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord4fvARB")) == NULL) || r;
+ r = ((glMultiTexCoord4iARB = (PFNGLMULTITEXCOORD4IARBPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord4iARB")) == NULL) || r;
+ r = ((glMultiTexCoord4ivARB = (PFNGLMULTITEXCOORD4IVARBPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord4ivARB")) == NULL) || r;
+ r = ((glMultiTexCoord4sARB = (PFNGLMULTITEXCOORD4SARBPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord4sARB")) == NULL) || r;
+ r = ((glMultiTexCoord4svARB = (PFNGLMULTITEXCOORD4SVARBPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord4svARB")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_ARB_multitexture */
+
+#ifdef GL_ARB_occlusion_query
+
+static GLboolean _glewInit_GL_ARB_occlusion_query (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glBeginQueryARB = (PFNGLBEGINQUERYARBPROC)glewGetProcAddress((const GLubyte*)"glBeginQueryARB")) == NULL) || r;
+ r = ((glDeleteQueriesARB = (PFNGLDELETEQUERIESARBPROC)glewGetProcAddress((const GLubyte*)"glDeleteQueriesARB")) == NULL) || r;
+ r = ((glEndQueryARB = (PFNGLENDQUERYARBPROC)glewGetProcAddress((const GLubyte*)"glEndQueryARB")) == NULL) || r;
+ r = ((glGenQueriesARB = (PFNGLGENQUERIESARBPROC)glewGetProcAddress((const GLubyte*)"glGenQueriesARB")) == NULL) || r;
+ r = ((glGetQueryObjectivARB = (PFNGLGETQUERYOBJECTIVARBPROC)glewGetProcAddress((const GLubyte*)"glGetQueryObjectivARB")) == NULL) || r;
+ r = ((glGetQueryObjectuivARB = (PFNGLGETQUERYOBJECTUIVARBPROC)glewGetProcAddress((const GLubyte*)"glGetQueryObjectuivARB")) == NULL) || r;
+ r = ((glGetQueryivARB = (PFNGLGETQUERYIVARBPROC)glewGetProcAddress((const GLubyte*)"glGetQueryivARB")) == NULL) || r;
+ r = ((glIsQueryARB = (PFNGLISQUERYARBPROC)glewGetProcAddress((const GLubyte*)"glIsQueryARB")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_ARB_occlusion_query */
+
+#ifdef GL_ARB_occlusion_query2
+
+#endif /* GL_ARB_occlusion_query2 */
+
+#ifdef GL_ARB_pixel_buffer_object
+
+#endif /* GL_ARB_pixel_buffer_object */
+
+#ifdef GL_ARB_point_parameters
+
+static GLboolean _glewInit_GL_ARB_point_parameters (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glPointParameterfARB = (PFNGLPOINTPARAMETERFARBPROC)glewGetProcAddress((const GLubyte*)"glPointParameterfARB")) == NULL) || r;
+ r = ((glPointParameterfvARB = (PFNGLPOINTPARAMETERFVARBPROC)glewGetProcAddress((const GLubyte*)"glPointParameterfvARB")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_ARB_point_parameters */
+
+#ifdef GL_ARB_point_sprite
+
+#endif /* GL_ARB_point_sprite */
+
+#ifdef GL_ARB_program_interface_query
+
+static GLboolean _glewInit_GL_ARB_program_interface_query (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glGetProgramInterfaceiv = (PFNGLGETPROGRAMINTERFACEIVPROC)glewGetProcAddress((const GLubyte*)"glGetProgramInterfaceiv")) == NULL) || r;
+ r = ((glGetProgramResourceIndex = (PFNGLGETPROGRAMRESOURCEINDEXPROC)glewGetProcAddress((const GLubyte*)"glGetProgramResourceIndex")) == NULL) || r;
+ r = ((glGetProgramResourceLocation = (PFNGLGETPROGRAMRESOURCELOCATIONPROC)glewGetProcAddress((const GLubyte*)"glGetProgramResourceLocation")) == NULL) || r;
+ r = ((glGetProgramResourceLocationIndex = (PFNGLGETPROGRAMRESOURCELOCATIONINDEXPROC)glewGetProcAddress((const GLubyte*)"glGetProgramResourceLocationIndex")) == NULL) || r;
+ r = ((glGetProgramResourceName = (PFNGLGETPROGRAMRESOURCENAMEPROC)glewGetProcAddress((const GLubyte*)"glGetProgramResourceName")) == NULL) || r;
+ r = ((glGetProgramResourceiv = (PFNGLGETPROGRAMRESOURCEIVPROC)glewGetProcAddress((const GLubyte*)"glGetProgramResourceiv")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_ARB_program_interface_query */
+
+#ifdef GL_ARB_provoking_vertex
+
+static GLboolean _glewInit_GL_ARB_provoking_vertex (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glProvokingVertex = (PFNGLPROVOKINGVERTEXPROC)glewGetProcAddress((const GLubyte*)"glProvokingVertex")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_ARB_provoking_vertex */
+
+#ifdef GL_ARB_robust_buffer_access_behavior
+
+#endif /* GL_ARB_robust_buffer_access_behavior */
+
+#ifdef GL_ARB_robustness
+
+static GLboolean _glewInit_GL_ARB_robustness (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glGetGraphicsResetStatusARB = (PFNGLGETGRAPHICSRESETSTATUSARBPROC)glewGetProcAddress((const GLubyte*)"glGetGraphicsResetStatusARB")) == NULL) || r;
+ r = ((glGetnColorTableARB = (PFNGLGETNCOLORTABLEARBPROC)glewGetProcAddress((const GLubyte*)"glGetnColorTableARB")) == NULL) || r;
+ r = ((glGetnCompressedTexImageARB = (PFNGLGETNCOMPRESSEDTEXIMAGEARBPROC)glewGetProcAddress((const GLubyte*)"glGetnCompressedTexImageARB")) == NULL) || r;
+ r = ((glGetnConvolutionFilterARB = (PFNGLGETNCONVOLUTIONFILTERARBPROC)glewGetProcAddress((const GLubyte*)"glGetnConvolutionFilterARB")) == NULL) || r;
+ r = ((glGetnHistogramARB = (PFNGLGETNHISTOGRAMARBPROC)glewGetProcAddress((const GLubyte*)"glGetnHistogramARB")) == NULL) || r;
+ r = ((glGetnMapdvARB = (PFNGLGETNMAPDVARBPROC)glewGetProcAddress((const GLubyte*)"glGetnMapdvARB")) == NULL) || r;
+ r = ((glGetnMapfvARB = (PFNGLGETNMAPFVARBPROC)glewGetProcAddress((const GLubyte*)"glGetnMapfvARB")) == NULL) || r;
+ r = ((glGetnMapivARB = (PFNGLGETNMAPIVARBPROC)glewGetProcAddress((const GLubyte*)"glGetnMapivARB")) == NULL) || r;
+ r = ((glGetnMinmaxARB = (PFNGLGETNMINMAXARBPROC)glewGetProcAddress((const GLubyte*)"glGetnMinmaxARB")) == NULL) || r;
+ r = ((glGetnPixelMapfvARB = (PFNGLGETNPIXELMAPFVARBPROC)glewGetProcAddress((const GLubyte*)"glGetnPixelMapfvARB")) == NULL) || r;
+ r = ((glGetnPixelMapuivARB = (PFNGLGETNPIXELMAPUIVARBPROC)glewGetProcAddress((const GLubyte*)"glGetnPixelMapuivARB")) == NULL) || r;
+ r = ((glGetnPixelMapusvARB = (PFNGLGETNPIXELMAPUSVARBPROC)glewGetProcAddress((const GLubyte*)"glGetnPixelMapusvARB")) == NULL) || r;
+ r = ((glGetnPolygonStippleARB = (PFNGLGETNPOLYGONSTIPPLEARBPROC)glewGetProcAddress((const GLubyte*)"glGetnPolygonStippleARB")) == NULL) || r;
+ r = ((glGetnSeparableFilterARB = (PFNGLGETNSEPARABLEFILTERARBPROC)glewGetProcAddress((const GLubyte*)"glGetnSeparableFilterARB")) == NULL) || r;
+ r = ((glGetnTexImageARB = (PFNGLGETNTEXIMAGEARBPROC)glewGetProcAddress((const GLubyte*)"glGetnTexImageARB")) == NULL) || r;
+ r = ((glGetnUniformdvARB = (PFNGLGETNUNIFORMDVARBPROC)glewGetProcAddress((const GLubyte*)"glGetnUniformdvARB")) == NULL) || r;
+ r = ((glGetnUniformfvARB = (PFNGLGETNUNIFORMFVARBPROC)glewGetProcAddress((const GLubyte*)"glGetnUniformfvARB")) == NULL) || r;
+ r = ((glGetnUniformivARB = (PFNGLGETNUNIFORMIVARBPROC)glewGetProcAddress((const GLubyte*)"glGetnUniformivARB")) == NULL) || r;
+ r = ((glGetnUniformuivARB = (PFNGLGETNUNIFORMUIVARBPROC)glewGetProcAddress((const GLubyte*)"glGetnUniformuivARB")) == NULL) || r;
+ r = ((glReadnPixelsARB = (PFNGLREADNPIXELSARBPROC)glewGetProcAddress((const GLubyte*)"glReadnPixelsARB")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_ARB_robustness */
+
+#ifdef GL_ARB_robustness_application_isolation
+
+#endif /* GL_ARB_robustness_application_isolation */
+
+#ifdef GL_ARB_robustness_share_group_isolation
+
+#endif /* GL_ARB_robustness_share_group_isolation */
+
+#ifdef GL_ARB_sample_shading
+
+static GLboolean _glewInit_GL_ARB_sample_shading (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glMinSampleShadingARB = (PFNGLMINSAMPLESHADINGARBPROC)glewGetProcAddress((const GLubyte*)"glMinSampleShadingARB")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_ARB_sample_shading */
+
+#ifdef GL_ARB_sampler_objects
+
+static GLboolean _glewInit_GL_ARB_sampler_objects (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glBindSampler = (PFNGLBINDSAMPLERPROC)glewGetProcAddress((const GLubyte*)"glBindSampler")) == NULL) || r;
+ r = ((glDeleteSamplers = (PFNGLDELETESAMPLERSPROC)glewGetProcAddress((const GLubyte*)"glDeleteSamplers")) == NULL) || r;
+ r = ((glGenSamplers = (PFNGLGENSAMPLERSPROC)glewGetProcAddress((const GLubyte*)"glGenSamplers")) == NULL) || r;
+ r = ((glGetSamplerParameterIiv = (PFNGLGETSAMPLERPARAMETERIIVPROC)glewGetProcAddress((const GLubyte*)"glGetSamplerParameterIiv")) == NULL) || r;
+ r = ((glGetSamplerParameterIuiv = (PFNGLGETSAMPLERPARAMETERIUIVPROC)glewGetProcAddress((const GLubyte*)"glGetSamplerParameterIuiv")) == NULL) || r;
+ r = ((glGetSamplerParameterfv = (PFNGLGETSAMPLERPARAMETERFVPROC)glewGetProcAddress((const GLubyte*)"glGetSamplerParameterfv")) == NULL) || r;
+ r = ((glGetSamplerParameteriv = (PFNGLGETSAMPLERPARAMETERIVPROC)glewGetProcAddress((const GLubyte*)"glGetSamplerParameteriv")) == NULL) || r;
+ r = ((glIsSampler = (PFNGLISSAMPLERPROC)glewGetProcAddress((const GLubyte*)"glIsSampler")) == NULL) || r;
+ r = ((glSamplerParameterIiv = (PFNGLSAMPLERPARAMETERIIVPROC)glewGetProcAddress((const GLubyte*)"glSamplerParameterIiv")) == NULL) || r;
+ r = ((glSamplerParameterIuiv = (PFNGLSAMPLERPARAMETERIUIVPROC)glewGetProcAddress((const GLubyte*)"glSamplerParameterIuiv")) == NULL) || r;
+ r = ((glSamplerParameterf = (PFNGLSAMPLERPARAMETERFPROC)glewGetProcAddress((const GLubyte*)"glSamplerParameterf")) == NULL) || r;
+ r = ((glSamplerParameterfv = (PFNGLSAMPLERPARAMETERFVPROC)glewGetProcAddress((const GLubyte*)"glSamplerParameterfv")) == NULL) || r;
+ r = ((glSamplerParameteri = (PFNGLSAMPLERPARAMETERIPROC)glewGetProcAddress((const GLubyte*)"glSamplerParameteri")) == NULL) || r;
+ r = ((glSamplerParameteriv = (PFNGLSAMPLERPARAMETERIVPROC)glewGetProcAddress((const GLubyte*)"glSamplerParameteriv")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_ARB_sampler_objects */
+
+#ifdef GL_ARB_seamless_cube_map
+
+#endif /* GL_ARB_seamless_cube_map */
+
+#if 0 // NOTE jwilkins: there is an inconsistency between the ES and Non-ES versions of this extension??
+#ifdef GL_ARB_separate_shader_objects
+
+static GLboolean _glewInit_GL_ARB_separate_shader_objects (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glActiveShaderProgram = (PFNGLACTIVESHADERPROGRAMPROC)glewGetProcAddress((const GLubyte*)"glActiveShaderProgram")) == NULL) || r;
+ r = ((glBindProgramPipeline = (PFNGLBINDPROGRAMPIPELINEPROC)glewGetProcAddress((const GLubyte*)"glBindProgramPipeline")) == NULL) || r;
+ r = ((glCreateShaderProgramv = (PFNGLCREATESHADERPROGRAMVPROC)glewGetProcAddress((const GLubyte*)"glCreateShaderProgramv")) == NULL) || r;
+ r = ((glDeleteProgramPipelines = (PFNGLDELETEPROGRAMPIPELINESPROC)glewGetProcAddress((const GLubyte*)"glDeleteProgramPipelines")) == NULL) || r;
+ r = ((glGenProgramPipelines = (PFNGLGENPROGRAMPIPELINESPROC)glewGetProcAddress((const GLubyte*)"glGenProgramPipelines")) == NULL) || r;
+ r = ((glGetProgramPipelineInfoLog = (PFNGLGETPROGRAMPIPELINEINFOLOGPROC)glewGetProcAddress((const GLubyte*)"glGetProgramPipelineInfoLog")) == NULL) || r;
+ r = ((glGetProgramPipelineiv = (PFNGLGETPROGRAMPIPELINEIVPROC)glewGetProcAddress((const GLubyte*)"glGetProgramPipelineiv")) == NULL) || r;
+ r = ((glIsProgramPipeline = (PFNGLISPROGRAMPIPELINEPROC)glewGetProcAddress((const GLubyte*)"glIsProgramPipeline")) == NULL) || r;
+ r = ((glProgramUniform1d = (PFNGLPROGRAMUNIFORM1DPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform1d")) == NULL) || r;
+ r = ((glProgramUniform1dv = (PFNGLPROGRAMUNIFORM1DVPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform1dv")) == NULL) || r;
+ r = ((glProgramUniform1f = (PFNGLPROGRAMUNIFORM1FPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform1f")) == NULL) || r;
+ r = ((glProgramUniform1fv = (PFNGLPROGRAMUNIFORM1FVPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform1fv")) == NULL) || r;
+ r = ((glProgramUniform1i = (PFNGLPROGRAMUNIFORM1IPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform1i")) == NULL) || r;
+ r = ((glProgramUniform1iv = (PFNGLPROGRAMUNIFORM1IVPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform1iv")) == NULL) || r;
+ r = ((glProgramUniform1ui = (PFNGLPROGRAMUNIFORM1UIPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform1ui")) == NULL) || r;
+ r = ((glProgramUniform1uiv = (PFNGLPROGRAMUNIFORM1UIVPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform1uiv")) == NULL) || r;
+ r = ((glProgramUniform2d = (PFNGLPROGRAMUNIFORM2DPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform2d")) == NULL) || r;
+ r = ((glProgramUniform2dv = (PFNGLPROGRAMUNIFORM2DVPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform2dv")) == NULL) || r;
+ r = ((glProgramUniform2f = (PFNGLPROGRAMUNIFORM2FPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform2f")) == NULL) || r;
+ r = ((glProgramUniform2fv = (PFNGLPROGRAMUNIFORM2FVPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform2fv")) == NULL) || r;
+ r = ((glProgramUniform2i = (PFNGLPROGRAMUNIFORM2IPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform2i")) == NULL) || r;
+ r = ((glProgramUniform2iv = (PFNGLPROGRAMUNIFORM2IVPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform2iv")) == NULL) || r;
+ r = ((glProgramUniform2ui = (PFNGLPROGRAMUNIFORM2UIPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform2ui")) == NULL) || r;
+ r = ((glProgramUniform2uiv = (PFNGLPROGRAMUNIFORM2UIVPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform2uiv")) == NULL) || r;
+ r = ((glProgramUniform3d = (PFNGLPROGRAMUNIFORM3DPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform3d")) == NULL) || r;
+ r = ((glProgramUniform3dv = (PFNGLPROGRAMUNIFORM3DVPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform3dv")) == NULL) || r;
+ r = ((glProgramUniform3f = (PFNGLPROGRAMUNIFORM3FPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform3f")) == NULL) || r;
+ r = ((glProgramUniform3fv = (PFNGLPROGRAMUNIFORM3FVPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform3fv")) == NULL) || r;
+ r = ((glProgramUniform3i = (PFNGLPROGRAMUNIFORM3IPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform3i")) == NULL) || r;
+ r = ((glProgramUniform3iv = (PFNGLPROGRAMUNIFORM3IVPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform3iv")) == NULL) || r;
+ r = ((glProgramUniform3ui = (PFNGLPROGRAMUNIFORM3UIPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform3ui")) == NULL) || r;
+ r = ((glProgramUniform3uiv = (PFNGLPROGRAMUNIFORM3UIVPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform3uiv")) == NULL) || r;
+ r = ((glProgramUniform4d = (PFNGLPROGRAMUNIFORM4DPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform4d")) == NULL) || r;
+ r = ((glProgramUniform4dv = (PFNGLPROGRAMUNIFORM4DVPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform4dv")) == NULL) || r;
+ r = ((glProgramUniform4f = (PFNGLPROGRAMUNIFORM4FPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform4f")) == NULL) || r;
+ r = ((glProgramUniform4fv = (PFNGLPROGRAMUNIFORM4FVPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform4fv")) == NULL) || r;
+ r = ((glProgramUniform4i = (PFNGLPROGRAMUNIFORM4IPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform4i")) == NULL) || r;
+ r = ((glProgramUniform4iv = (PFNGLPROGRAMUNIFORM4IVPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform4iv")) == NULL) || r;
+ r = ((glProgramUniform4ui = (PFNGLPROGRAMUNIFORM4UIPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform4ui")) == NULL) || r;
+ r = ((glProgramUniform4uiv = (PFNGLPROGRAMUNIFORM4UIVPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform4uiv")) == NULL) || r;
+ r = ((glProgramUniformMatrix2dv = (PFNGLPROGRAMUNIFORMMATRIX2DVPROC)glewGetProcAddress((const GLubyte*)"glProgramUniformMatrix2dv")) == NULL) || r;
+ r = ((glProgramUniformMatrix2fv = (PFNGLPROGRAMUNIFORMMATRIX2FVPROC)glewGetProcAddress((const GLubyte*)"glProgramUniformMatrix2fv")) == NULL) || r;
+ r = ((glProgramUniformMatrix2x3dv = (PFNGLPROGRAMUNIFORMMATRIX2X3DVPROC)glewGetProcAddress((const GLubyte*)"glProgramUniformMatrix2x3dv")) == NULL) || r;
+ r = ((glProgramUniformMatrix2x3fv = (PFNGLPROGRAMUNIFORMMATRIX2X3FVPROC)glewGetProcAddress((const GLubyte*)"glProgramUniformMatrix2x3fv")) == NULL) || r;
+ r = ((glProgramUniformMatrix2x4dv = (PFNGLPROGRAMUNIFORMMATRIX2X4DVPROC)glewGetProcAddress((const GLubyte*)"glProgramUniformMatrix2x4dv")) == NULL) || r;
+ r = ((glProgramUniformMatrix2x4fv = (PFNGLPROGRAMUNIFORMMATRIX2X4FVPROC)glewGetProcAddress((const GLubyte*)"glProgramUniformMatrix2x4fv")) == NULL) || r;
+ r = ((glProgramUniformMatrix3dv = (PFNGLPROGRAMUNIFORMMATRIX3DVPROC)glewGetProcAddress((const GLubyte*)"glProgramUniformMatrix3dv")) == NULL) || r;
+ r = ((glProgramUniformMatrix3fv = (PFNGLPROGRAMUNIFORMMATRIX3FVPROC)glewGetProcAddress((const GLubyte*)"glProgramUniformMatrix3fv")) == NULL) || r;
+ r = ((glProgramUniformMatrix3x2dv = (PFNGLPROGRAMUNIFORMMATRIX3X2DVPROC)glewGetProcAddress((const GLubyte*)"glProgramUniformMatrix3x2dv")) == NULL) || r;
+ r = ((glProgramUniformMatrix3x2fv = (PFNGLPROGRAMUNIFORMMATRIX3X2FVPROC)glewGetProcAddress((const GLubyte*)"glProgramUniformMatrix3x2fv")) == NULL) || r;
+ r = ((glProgramUniformMatrix3x4dv = (PFNGLPROGRAMUNIFORMMATRIX3X4DVPROC)glewGetProcAddress((const GLubyte*)"glProgramUniformMatrix3x4dv")) == NULL) || r;
+ r = ((glProgramUniformMatrix3x4fv = (PFNGLPROGRAMUNIFORMMATRIX3X4FVPROC)glewGetProcAddress((const GLubyte*)"glProgramUniformMatrix3x4fv")) == NULL) || r;
+ r = ((glProgramUniformMatrix4dv = (PFNGLPROGRAMUNIFORMMATRIX4DVPROC)glewGetProcAddress((const GLubyte*)"glProgramUniformMatrix4dv")) == NULL) || r;
+ r = ((glProgramUniformMatrix4fv = (PFNGLPROGRAMUNIFORMMATRIX4FVPROC)glewGetProcAddress((const GLubyte*)"glProgramUniformMatrix4fv")) == NULL) || r;
+ r = ((glProgramUniformMatrix4x2dv = (PFNGLPROGRAMUNIFORMMATRIX4X2DVPROC)glewGetProcAddress((const GLubyte*)"glProgramUniformMatrix4x2dv")) == NULL) || r;
+ r = ((glProgramUniformMatrix4x2fv = (PFNGLPROGRAMUNIFORMMATRIX4X2FVPROC)glewGetProcAddress((const GLubyte*)"glProgramUniformMatrix4x2fv")) == NULL) || r;
+ r = ((glProgramUniformMatrix4x3dv = (PFNGLPROGRAMUNIFORMMATRIX4X3DVPROC)glewGetProcAddress((const GLubyte*)"glProgramUniformMatrix4x3dv")) == NULL) || r;
+ r = ((glProgramUniformMatrix4x3fv = (PFNGLPROGRAMUNIFORMMATRIX4X3FVPROC)glewGetProcAddress((const GLubyte*)"glProgramUniformMatrix4x3fv")) == NULL) || r;
+ r = ((glUseProgramStages = (PFNGLUSEPROGRAMSTAGESPROC)glewGetProcAddress((const GLubyte*)"glUseProgramStages")) == NULL) || r;
+ r = ((glValidateProgramPipeline = (PFNGLVALIDATEPROGRAMPIPELINEPROC)glewGetProcAddress((const GLubyte*)"glValidateProgramPipeline")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_ARB_separate_shader_objects */
+#endif
+
+#ifdef GL_ARB_shader_atomic_counters
+
+static GLboolean _glewInit_GL_ARB_shader_atomic_counters (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glGetActiveAtomicCounterBufferiv = (PFNGLGETACTIVEATOMICCOUNTERBUFFERIVPROC)glewGetProcAddress((const GLubyte*)"glGetActiveAtomicCounterBufferiv")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_ARB_shader_atomic_counters */
+
+#ifdef GL_ARB_shader_bit_encoding
+
+#endif /* GL_ARB_shader_bit_encoding */
+
+#ifdef GL_ARB_shader_image_load_store
+
+static GLboolean _glewInit_GL_ARB_shader_image_load_store (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glBindImageTexture = (PFNGLBINDIMAGETEXTUREPROC)glewGetProcAddress((const GLubyte*)"glBindImageTexture")) == NULL) || r;
+ r = ((glMemoryBarrier = (PFNGLMEMORYBARRIERPROC)glewGetProcAddress((const GLubyte*)"glMemoryBarrier")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_ARB_shader_image_load_store */
+
+#ifdef GL_ARB_shader_image_size
+
+#endif /* GL_ARB_shader_image_size */
+
+#ifdef GL_ARB_shader_objects
+
+static GLboolean _glewInit_GL_ARB_shader_objects (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glAttachObjectARB = (PFNGLATTACHOBJECTARBPROC)glewGetProcAddress((const GLubyte*)"glAttachObjectARB")) == NULL) || r;
+ r = ((glCompileShaderARB = (PFNGLCOMPILESHADERARBPROC)glewGetProcAddress((const GLubyte*)"glCompileShaderARB")) == NULL) || r;
+ r = ((glCreateProgramObjectARB = (PFNGLCREATEPROGRAMOBJECTARBPROC)glewGetProcAddress((const GLubyte*)"glCreateProgramObjectARB")) == NULL) || r;
+ r = ((glCreateShaderObjectARB = (PFNGLCREATESHADEROBJECTARBPROC)glewGetProcAddress((const GLubyte*)"glCreateShaderObjectARB")) == NULL) || r;
+ r = ((glDeleteObjectARB = (PFNGLDELETEOBJECTARBPROC)glewGetProcAddress((const GLubyte*)"glDeleteObjectARB")) == NULL) || r;
+ r = ((glDetachObjectARB = (PFNGLDETACHOBJECTARBPROC)glewGetProcAddress((const GLubyte*)"glDetachObjectARB")) == NULL) || r;
+ r = ((glGetActiveUniformARB = (PFNGLGETACTIVEUNIFORMARBPROC)glewGetProcAddress((const GLubyte*)"glGetActiveUniformARB")) == NULL) || r;
+ r = ((glGetAttachedObjectsARB = (PFNGLGETATTACHEDOBJECTSARBPROC)glewGetProcAddress((const GLubyte*)"glGetAttachedObjectsARB")) == NULL) || r;
+ r = ((glGetHandleARB = (PFNGLGETHANDLEARBPROC)glewGetProcAddress((const GLubyte*)"glGetHandleARB")) == NULL) || r;
+ r = ((glGetInfoLogARB = (PFNGLGETINFOLOGARBPROC)glewGetProcAddress((const GLubyte*)"glGetInfoLogARB")) == NULL) || r;
+ r = ((glGetObjectParameterfvARB = (PFNGLGETOBJECTPARAMETERFVARBPROC)glewGetProcAddress((const GLubyte*)"glGetObjectParameterfvARB")) == NULL) || r;
+ r = ((glGetObjectParameterivARB = (PFNGLGETOBJECTPARAMETERIVARBPROC)glewGetProcAddress((const GLubyte*)"glGetObjectParameterivARB")) == NULL) || r;
+ r = ((glGetShaderSourceARB = (PFNGLGETSHADERSOURCEARBPROC)glewGetProcAddress((const GLubyte*)"glGetShaderSourceARB")) == NULL) || r;
+ r = ((glGetUniformLocationARB = (PFNGLGETUNIFORMLOCATIONARBPROC)glewGetProcAddress((const GLubyte*)"glGetUniformLocationARB")) == NULL) || r;
+ r = ((glGetUniformfvARB = (PFNGLGETUNIFORMFVARBPROC)glewGetProcAddress((const GLubyte*)"glGetUniformfvARB")) == NULL) || r;
+ r = ((glGetUniformivARB = (PFNGLGETUNIFORMIVARBPROC)glewGetProcAddress((const GLubyte*)"glGetUniformivARB")) == NULL) || r;
+ r = ((glLinkProgramARB = (PFNGLLINKPROGRAMARBPROC)glewGetProcAddress((const GLubyte*)"glLinkProgramARB")) == NULL) || r;
+ r = ((glShaderSourceARB = (PFNGLSHADERSOURCEARBPROC)glewGetProcAddress((const GLubyte*)"glShaderSourceARB")) == NULL) || r;
+ r = ((glUniform1fARB = (PFNGLUNIFORM1FARBPROC)glewGetProcAddress((const GLubyte*)"glUniform1fARB")) == NULL) || r;
+ r = ((glUniform1fvARB = (PFNGLUNIFORM1FVARBPROC)glewGetProcAddress((const GLubyte*)"glUniform1fvARB")) == NULL) || r;
+ r = ((glUniform1iARB = (PFNGLUNIFORM1IARBPROC)glewGetProcAddress((const GLubyte*)"glUniform1iARB")) == NULL) || r;
+ r = ((glUniform1ivARB = (PFNGLUNIFORM1IVARBPROC)glewGetProcAddress((const GLubyte*)"glUniform1ivARB")) == NULL) || r;
+ r = ((glUniform2fARB = (PFNGLUNIFORM2FARBPROC)glewGetProcAddress((const GLubyte*)"glUniform2fARB")) == NULL) || r;
+ r = ((glUniform2fvARB = (PFNGLUNIFORM2FVARBPROC)glewGetProcAddress((const GLubyte*)"glUniform2fvARB")) == NULL) || r;
+ r = ((glUniform2iARB = (PFNGLUNIFORM2IARBPROC)glewGetProcAddress((const GLubyte*)"glUniform2iARB")) == NULL) || r;
+ r = ((glUniform2ivARB = (PFNGLUNIFORM2IVARBPROC)glewGetProcAddress((const GLubyte*)"glUniform2ivARB")) == NULL) || r;
+ r = ((glUniform3fARB = (PFNGLUNIFORM3FARBPROC)glewGetProcAddress((const GLubyte*)"glUniform3fARB")) == NULL) || r;
+ r = ((glUniform3fvARB = (PFNGLUNIFORM3FVARBPROC)glewGetProcAddress((const GLubyte*)"glUniform3fvARB")) == NULL) || r;
+ r = ((glUniform3iARB = (PFNGLUNIFORM3IARBPROC)glewGetProcAddress((const GLubyte*)"glUniform3iARB")) == NULL) || r;
+ r = ((glUniform3ivARB = (PFNGLUNIFORM3IVARBPROC)glewGetProcAddress((const GLubyte*)"glUniform3ivARB")) == NULL) || r;
+ r = ((glUniform4fARB = (PFNGLUNIFORM4FARBPROC)glewGetProcAddress((const GLubyte*)"glUniform4fARB")) == NULL) || r;
+ r = ((glUniform4fvARB = (PFNGLUNIFORM4FVARBPROC)glewGetProcAddress((const GLubyte*)"glUniform4fvARB")) == NULL) || r;
+ r = ((glUniform4iARB = (PFNGLUNIFORM4IARBPROC)glewGetProcAddress((const GLubyte*)"glUniform4iARB")) == NULL) || r;
+ r = ((glUniform4ivARB = (PFNGLUNIFORM4IVARBPROC)glewGetProcAddress((const GLubyte*)"glUniform4ivARB")) == NULL) || r;
+ r = ((glUniformMatrix2fvARB = (PFNGLUNIFORMMATRIX2FVARBPROC)glewGetProcAddress((const GLubyte*)"glUniformMatrix2fvARB")) == NULL) || r;
+ r = ((glUniformMatrix3fvARB = (PFNGLUNIFORMMATRIX3FVARBPROC)glewGetProcAddress((const GLubyte*)"glUniformMatrix3fvARB")) == NULL) || r;
+ r = ((glUniformMatrix4fvARB = (PFNGLUNIFORMMATRIX4FVARBPROC)glewGetProcAddress((const GLubyte*)"glUniformMatrix4fvARB")) == NULL) || r;
+ r = ((glUseProgramObjectARB = (PFNGLUSEPROGRAMOBJECTARBPROC)glewGetProcAddress((const GLubyte*)"glUseProgramObjectARB")) == NULL) || r;
+ r = ((glValidateProgramARB = (PFNGLVALIDATEPROGRAMARBPROC)glewGetProcAddress((const GLubyte*)"glValidateProgramARB")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_ARB_shader_objects */
+
+#ifdef GL_ARB_shader_precision
+
+#endif /* GL_ARB_shader_precision */
+
+#ifdef GL_ARB_shader_stencil_export
+
+#endif /* GL_ARB_shader_stencil_export */
+
+#ifdef GL_ARB_shader_storage_buffer_object
+
+static GLboolean _glewInit_GL_ARB_shader_storage_buffer_object (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glShaderStorageBlockBinding = (PFNGLSHADERSTORAGEBLOCKBINDINGPROC)glewGetProcAddress((const GLubyte*)"glShaderStorageBlockBinding")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_ARB_shader_storage_buffer_object */
+
+#ifdef GL_ARB_shader_subroutine
+
+static GLboolean _glewInit_GL_ARB_shader_subroutine (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glGetActiveSubroutineName = (PFNGLGETACTIVESUBROUTINENAMEPROC)glewGetProcAddress((const GLubyte*)"glGetActiveSubroutineName")) == NULL) || r;
+ r = ((glGetActiveSubroutineUniformName = (PFNGLGETACTIVESUBROUTINEUNIFORMNAMEPROC)glewGetProcAddress((const GLubyte*)"glGetActiveSubroutineUniformName")) == NULL) || r;
+ r = ((glGetActiveSubroutineUniformiv = (PFNGLGETACTIVESUBROUTINEUNIFORMIVPROC)glewGetProcAddress((const GLubyte*)"glGetActiveSubroutineUniformiv")) == NULL) || r;
+ r = ((glGetProgramStageiv = (PFNGLGETPROGRAMSTAGEIVPROC)glewGetProcAddress((const GLubyte*)"glGetProgramStageiv")) == NULL) || r;
+ r = ((glGetSubroutineIndex = (PFNGLGETSUBROUTINEINDEXPROC)glewGetProcAddress((const GLubyte*)"glGetSubroutineIndex")) == NULL) || r;
+ r = ((glGetSubroutineUniformLocation = (PFNGLGETSUBROUTINEUNIFORMLOCATIONPROC)glewGetProcAddress((const GLubyte*)"glGetSubroutineUniformLocation")) == NULL) || r;
+ r = ((glGetUniformSubroutineuiv = (PFNGLGETUNIFORMSUBROUTINEUIVPROC)glewGetProcAddress((const GLubyte*)"glGetUniformSubroutineuiv")) == NULL) || r;
+ r = ((glUniformSubroutinesuiv = (PFNGLUNIFORMSUBROUTINESUIVPROC)glewGetProcAddress((const GLubyte*)"glUniformSubroutinesuiv")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_ARB_shader_subroutine */
+
+#ifdef GL_ARB_shader_texture_lod
+
+#endif /* GL_ARB_shader_texture_lod */
+
+#ifdef GL_ARB_shading_language_100
+
+#endif /* GL_ARB_shading_language_100 */
+
+#ifdef GL_ARB_shading_language_420pack
+
+#endif /* GL_ARB_shading_language_420pack */
+
+#ifdef GL_ARB_shading_language_include
+
+static GLboolean _glewInit_GL_ARB_shading_language_include (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glCompileShaderIncludeARB = (PFNGLCOMPILESHADERINCLUDEARBPROC)glewGetProcAddress((const GLubyte*)"glCompileShaderIncludeARB")) == NULL) || r;
+ r = ((glDeleteNamedStringARB = (PFNGLDELETENAMEDSTRINGARBPROC)glewGetProcAddress((const GLubyte*)"glDeleteNamedStringARB")) == NULL) || r;
+ r = ((glGetNamedStringARB = (PFNGLGETNAMEDSTRINGARBPROC)glewGetProcAddress((const GLubyte*)"glGetNamedStringARB")) == NULL) || r;
+ r = ((glGetNamedStringivARB = (PFNGLGETNAMEDSTRINGIVARBPROC)glewGetProcAddress((const GLubyte*)"glGetNamedStringivARB")) == NULL) || r;
+ r = ((glIsNamedStringARB = (PFNGLISNAMEDSTRINGARBPROC)glewGetProcAddress((const GLubyte*)"glIsNamedStringARB")) == NULL) || r;
+ r = ((glNamedStringARB = (PFNGLNAMEDSTRINGARBPROC)glewGetProcAddress((const GLubyte*)"glNamedStringARB")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_ARB_shading_language_include */
+
+#ifdef GL_ARB_shading_language_packing
+
+#endif /* GL_ARB_shading_language_packing */
+
+#ifdef GL_ARB_shadow
+
+#endif /* GL_ARB_shadow */
+
+#ifdef GL_ARB_shadow_ambient
+
+#endif /* GL_ARB_shadow_ambient */
+
+#ifdef GL_ARB_stencil_texturing
+
+#endif /* GL_ARB_stencil_texturing */
+
+#ifdef GL_ARB_sync
+
+static GLboolean _glewInit_GL_ARB_sync (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glClientWaitSync = (PFNGLCLIENTWAITSYNCPROC)glewGetProcAddress((const GLubyte*)"glClientWaitSync")) == NULL) || r;
+ r = ((glDeleteSync = (PFNGLDELETESYNCPROC)glewGetProcAddress((const GLubyte*)"glDeleteSync")) == NULL) || r;
+ r = ((glFenceSync = (PFNGLFENCESYNCPROC)glewGetProcAddress((const GLubyte*)"glFenceSync")) == NULL) || r;
+ r = ((glGetInteger64v = (PFNGLGETINTEGER64VPROC)glewGetProcAddress((const GLubyte*)"glGetInteger64v")) == NULL) || r;
+ r = ((glGetSynciv = (PFNGLGETSYNCIVPROC)glewGetProcAddress((const GLubyte*)"glGetSynciv")) == NULL) || r;
+ r = ((glIsSync = (PFNGLISSYNCPROC)glewGetProcAddress((const GLubyte*)"glIsSync")) == NULL) || r;
+ r = ((glWaitSync = (PFNGLWAITSYNCPROC)glewGetProcAddress((const GLubyte*)"glWaitSync")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_ARB_sync */
+
+#ifdef GL_ARB_tessellation_shader
+
+static GLboolean _glewInit_GL_ARB_tessellation_shader (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glPatchParameterfv = (PFNGLPATCHPARAMETERFVPROC)glewGetProcAddress((const GLubyte*)"glPatchParameterfv")) == NULL) || r;
+ r = ((glPatchParameteri = (PFNGLPATCHPARAMETERIPROC)glewGetProcAddress((const GLubyte*)"glPatchParameteri")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_ARB_tessellation_shader */
+
+#ifdef GL_ARB_texture_border_clamp
+
+#endif /* GL_ARB_texture_border_clamp */
+
+#ifdef GL_ARB_texture_buffer_object
+
+static GLboolean _glewInit_GL_ARB_texture_buffer_object (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glTexBufferARB = (PFNGLTEXBUFFERARBPROC)glewGetProcAddress((const GLubyte*)"glTexBufferARB")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_ARB_texture_buffer_object */
+
+#ifdef GL_ARB_texture_buffer_object_rgb32
+
+#endif /* GL_ARB_texture_buffer_object_rgb32 */
+
+#ifdef GL_ARB_texture_buffer_range
+
+static GLboolean _glewInit_GL_ARB_texture_buffer_range (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glTexBufferRange = (PFNGLTEXBUFFERRANGEPROC)glewGetProcAddress((const GLubyte*)"glTexBufferRange")) == NULL) || r;
+ r = ((glTextureBufferRangeEXT = (PFNGLTEXTUREBUFFERRANGEEXTPROC)glewGetProcAddress((const GLubyte*)"glTextureBufferRangeEXT")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_ARB_texture_buffer_range */
+
+#ifdef GL_ARB_texture_compression
+
+static GLboolean _glewInit_GL_ARB_texture_compression (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glCompressedTexImage1DARB = (PFNGLCOMPRESSEDTEXIMAGE1DARBPROC)glewGetProcAddress((const GLubyte*)"glCompressedTexImage1DARB")) == NULL) || r;
+ r = ((glCompressedTexImage2DARB = (PFNGLCOMPRESSEDTEXIMAGE2DARBPROC)glewGetProcAddress((const GLubyte*)"glCompressedTexImage2DARB")) == NULL) || r;
+ r = ((glCompressedTexImage3DARB = (PFNGLCOMPRESSEDTEXIMAGE3DARBPROC)glewGetProcAddress((const GLubyte*)"glCompressedTexImage3DARB")) == NULL) || r;
+ r = ((glCompressedTexSubImage1DARB = (PFNGLCOMPRESSEDTEXSUBIMAGE1DARBPROC)glewGetProcAddress((const GLubyte*)"glCompressedTexSubImage1DARB")) == NULL) || r;
+ r = ((glCompressedTexSubImage2DARB = (PFNGLCOMPRESSEDTEXSUBIMAGE2DARBPROC)glewGetProcAddress((const GLubyte*)"glCompressedTexSubImage2DARB")) == NULL) || r;
+ r = ((glCompressedTexSubImage3DARB = (PFNGLCOMPRESSEDTEXSUBIMAGE3DARBPROC)glewGetProcAddress((const GLubyte*)"glCompressedTexSubImage3DARB")) == NULL) || r;
+ r = ((glGetCompressedTexImageARB = (PFNGLGETCOMPRESSEDTEXIMAGEARBPROC)glewGetProcAddress((const GLubyte*)"glGetCompressedTexImageARB")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_ARB_texture_compression */
+
+#ifdef GL_ARB_texture_compression_bptc
+
+#endif /* GL_ARB_texture_compression_bptc */
+
+#ifdef GL_ARB_texture_compression_rgtc
+
+#endif /* GL_ARB_texture_compression_rgtc */
+
+#ifdef GL_ARB_texture_cube_map
+
+#endif /* GL_ARB_texture_cube_map */
+
+#ifdef GL_ARB_texture_cube_map_array
+
+#endif /* GL_ARB_texture_cube_map_array */
+
+#ifdef GL_ARB_texture_env_add
+
+#endif /* GL_ARB_texture_env_add */
+
+#ifdef GL_ARB_texture_env_combine
+
+#endif /* GL_ARB_texture_env_combine */
+
+#ifdef GL_ARB_texture_env_crossbar
+
+#endif /* GL_ARB_texture_env_crossbar */
+
+#ifdef GL_ARB_texture_env_dot3
+
+#endif /* GL_ARB_texture_env_dot3 */
+
+#ifdef GL_ARB_texture_float
+
+#endif /* GL_ARB_texture_float */
+
+#ifdef GL_ARB_texture_gather
+
+#endif /* GL_ARB_texture_gather */
+
+#ifdef GL_ARB_texture_mirrored_repeat
+
+#endif /* GL_ARB_texture_mirrored_repeat */
+
+#ifdef GL_ARB_texture_multisample
+
+static GLboolean _glewInit_GL_ARB_texture_multisample (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glGetMultisamplefv = (PFNGLGETMULTISAMPLEFVPROC)glewGetProcAddress((const GLubyte*)"glGetMultisamplefv")) == NULL) || r;
+ r = ((glSampleMaski = (PFNGLSAMPLEMASKIPROC)glewGetProcAddress((const GLubyte*)"glSampleMaski")) == NULL) || r;
+ r = ((glTexImage2DMultisample = (PFNGLTEXIMAGE2DMULTISAMPLEPROC)glewGetProcAddress((const GLubyte*)"glTexImage2DMultisample")) == NULL) || r;
+ r = ((glTexImage3DMultisample = (PFNGLTEXIMAGE3DMULTISAMPLEPROC)glewGetProcAddress((const GLubyte*)"glTexImage3DMultisample")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_ARB_texture_multisample */
+
+#ifdef GL_ARB_texture_non_power_of_two
+
+#endif /* GL_ARB_texture_non_power_of_two */
+
+#ifdef GL_ARB_texture_query_levels
+
+#endif /* GL_ARB_texture_query_levels */
+
+#ifdef GL_ARB_texture_query_lod
+
+#endif /* GL_ARB_texture_query_lod */
+
+#ifdef GL_ARB_texture_rectangle
+
+#endif /* GL_ARB_texture_rectangle */
+
+#ifdef GL_ARB_texture_rg
+
+#endif /* GL_ARB_texture_rg */
+
+#ifdef GL_ARB_texture_rgb10_a2ui
+
+#endif /* GL_ARB_texture_rgb10_a2ui */
+
+#ifdef GL_ARB_texture_storage
+
+static GLboolean _glewInit_GL_ARB_texture_storage (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glTexStorage1D = (PFNGLTEXSTORAGE1DPROC)glewGetProcAddress((const GLubyte*)"glTexStorage1D")) == NULL) || r;
+ r = ((glTexStorage2D = (PFNGLTEXSTORAGE2DPROC)glewGetProcAddress((const GLubyte*)"glTexStorage2D")) == NULL) || r;
+ r = ((glTexStorage3D = (PFNGLTEXSTORAGE3DPROC)glewGetProcAddress((const GLubyte*)"glTexStorage3D")) == NULL) || r;
+ r = ((glTextureStorage1DEXT = (PFNGLTEXTURESTORAGE1DEXTPROC)glewGetProcAddress((const GLubyte*)"glTextureStorage1DEXT")) == NULL) || r;
+ r = ((glTextureStorage2DEXT = (PFNGLTEXTURESTORAGE2DEXTPROC)glewGetProcAddress((const GLubyte*)"glTextureStorage2DEXT")) == NULL) || r;
+ r = ((glTextureStorage3DEXT = (PFNGLTEXTURESTORAGE3DEXTPROC)glewGetProcAddress((const GLubyte*)"glTextureStorage3DEXT")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_ARB_texture_storage */
+
+#ifdef GL_ARB_texture_storage_multisample
+
+static GLboolean _glewInit_GL_ARB_texture_storage_multisample (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glTexStorage2DMultisample = (PFNGLTEXSTORAGE2DMULTISAMPLEPROC)glewGetProcAddress((const GLubyte*)"glTexStorage2DMultisample")) == NULL) || r;
+ r = ((glTexStorage3DMultisample = (PFNGLTEXSTORAGE3DMULTISAMPLEPROC)glewGetProcAddress((const GLubyte*)"glTexStorage3DMultisample")) == NULL) || r;
+ r = ((glTextureStorage2DMultisampleEXT = (PFNGLTEXTURESTORAGE2DMULTISAMPLEEXTPROC)glewGetProcAddress((const GLubyte*)"glTextureStorage2DMultisampleEXT")) == NULL) || r;
+ r = ((glTextureStorage3DMultisampleEXT = (PFNGLTEXTURESTORAGE3DMULTISAMPLEEXTPROC)glewGetProcAddress((const GLubyte*)"glTextureStorage3DMultisampleEXT")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_ARB_texture_storage_multisample */
+
+#ifdef GL_ARB_texture_swizzle
+
+#endif /* GL_ARB_texture_swizzle */
+
+#ifdef GL_ARB_texture_view
+
+static GLboolean _glewInit_GL_ARB_texture_view (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glTextureView = (PFNGLTEXTUREVIEWPROC)glewGetProcAddress((const GLubyte*)"glTextureView")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_ARB_texture_view */
+
+#ifdef GL_ARB_timer_query
+
+static GLboolean _glewInit_GL_ARB_timer_query (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glGetQueryObjecti64v = (PFNGLGETQUERYOBJECTI64VPROC)glewGetProcAddress((const GLubyte*)"glGetQueryObjecti64v")) == NULL) || r;
+ r = ((glGetQueryObjectui64v = (PFNGLGETQUERYOBJECTUI64VPROC)glewGetProcAddress((const GLubyte*)"glGetQueryObjectui64v")) == NULL) || r;
+ r = ((glQueryCounter = (PFNGLQUERYCOUNTERPROC)glewGetProcAddress((const GLubyte*)"glQueryCounter")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_ARB_timer_query */
+
+#ifdef GL_ARB_transform_feedback2
+
+static GLboolean _glewInit_GL_ARB_transform_feedback2 (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glBindTransformFeedback = (PFNGLBINDTRANSFORMFEEDBACKPROC)glewGetProcAddress((const GLubyte*)"glBindTransformFeedback")) == NULL) || r;
+ r = ((glDeleteTransformFeedbacks = (PFNGLDELETETRANSFORMFEEDBACKSPROC)glewGetProcAddress((const GLubyte*)"glDeleteTransformFeedbacks")) == NULL) || r;
+ r = ((glDrawTransformFeedback = (PFNGLDRAWTRANSFORMFEEDBACKPROC)glewGetProcAddress((const GLubyte*)"glDrawTransformFeedback")) == NULL) || r;
+ r = ((glGenTransformFeedbacks = (PFNGLGENTRANSFORMFEEDBACKSPROC)glewGetProcAddress((const GLubyte*)"glGenTransformFeedbacks")) == NULL) || r;
+ r = ((glIsTransformFeedback = (PFNGLISTRANSFORMFEEDBACKPROC)glewGetProcAddress((const GLubyte*)"glIsTransformFeedback")) == NULL) || r;
+ r = ((glPauseTransformFeedback = (PFNGLPAUSETRANSFORMFEEDBACKPROC)glewGetProcAddress((const GLubyte*)"glPauseTransformFeedback")) == NULL) || r;
+ r = ((glResumeTransformFeedback = (PFNGLRESUMETRANSFORMFEEDBACKPROC)glewGetProcAddress((const GLubyte*)"glResumeTransformFeedback")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_ARB_transform_feedback2 */
+
+#ifdef GL_ARB_transform_feedback3
+
+static GLboolean _glewInit_GL_ARB_transform_feedback3 (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glBeginQueryIndexed = (PFNGLBEGINQUERYINDEXEDPROC)glewGetProcAddress((const GLubyte*)"glBeginQueryIndexed")) == NULL) || r;
+ r = ((glDrawTransformFeedbackStream = (PFNGLDRAWTRANSFORMFEEDBACKSTREAMPROC)glewGetProcAddress((const GLubyte*)"glDrawTransformFeedbackStream")) == NULL) || r;
+ r = ((glEndQueryIndexed = (PFNGLENDQUERYINDEXEDPROC)glewGetProcAddress((const GLubyte*)"glEndQueryIndexed")) == NULL) || r;
+ r = ((glGetQueryIndexediv = (PFNGLGETQUERYINDEXEDIVPROC)glewGetProcAddress((const GLubyte*)"glGetQueryIndexediv")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_ARB_transform_feedback3 */
+
+#ifdef GL_ARB_transform_feedback_instanced
+
+static GLboolean _glewInit_GL_ARB_transform_feedback_instanced (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glDrawTransformFeedbackInstanced = (PFNGLDRAWTRANSFORMFEEDBACKINSTANCEDPROC)glewGetProcAddress((const GLubyte*)"glDrawTransformFeedbackInstanced")) == NULL) || r;
+ r = ((glDrawTransformFeedbackStreamInstanced = (PFNGLDRAWTRANSFORMFEEDBACKSTREAMINSTANCEDPROC)glewGetProcAddress((const GLubyte*)"glDrawTransformFeedbackStreamInstanced")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_ARB_transform_feedback_instanced */
+
+#ifdef GL_ARB_transpose_matrix
+
+static GLboolean _glewInit_GL_ARB_transpose_matrix (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glLoadTransposeMatrixdARB = (PFNGLLOADTRANSPOSEMATRIXDARBPROC)glewGetProcAddress((const GLubyte*)"glLoadTransposeMatrixdARB")) == NULL) || r;
+ r = ((glLoadTransposeMatrixfARB = (PFNGLLOADTRANSPOSEMATRIXFARBPROC)glewGetProcAddress((const GLubyte*)"glLoadTransposeMatrixfARB")) == NULL) || r;
+ r = ((glMultTransposeMatrixdARB = (PFNGLMULTTRANSPOSEMATRIXDARBPROC)glewGetProcAddress((const GLubyte*)"glMultTransposeMatrixdARB")) == NULL) || r;
+ r = ((glMultTransposeMatrixfARB = (PFNGLMULTTRANSPOSEMATRIXFARBPROC)glewGetProcAddress((const GLubyte*)"glMultTransposeMatrixfARB")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_ARB_transpose_matrix */
+
+#ifdef GL_ARB_uniform_buffer_object
+
+static GLboolean _glewInit_GL_ARB_uniform_buffer_object (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glBindBufferBase = (PFNGLBINDBUFFERBASEPROC)glewGetProcAddress((const GLubyte*)"glBindBufferBase")) == NULL) || r;
+ r = ((glBindBufferRange = (PFNGLBINDBUFFERRANGEPROC)glewGetProcAddress((const GLubyte*)"glBindBufferRange")) == NULL) || r;
+ r = ((glGetActiveUniformBlockName = (PFNGLGETACTIVEUNIFORMBLOCKNAMEPROC)glewGetProcAddress((const GLubyte*)"glGetActiveUniformBlockName")) == NULL) || r;
+ r = ((glGetActiveUniformBlockiv = (PFNGLGETACTIVEUNIFORMBLOCKIVPROC)glewGetProcAddress((const GLubyte*)"glGetActiveUniformBlockiv")) == NULL) || r;
+ r = ((glGetActiveUniformName = (PFNGLGETACTIVEUNIFORMNAMEPROC)glewGetProcAddress((const GLubyte*)"glGetActiveUniformName")) == NULL) || r;
+ r = ((glGetActiveUniformsiv = (PFNGLGETACTIVEUNIFORMSIVPROC)glewGetProcAddress((const GLubyte*)"glGetActiveUniformsiv")) == NULL) || r;
+ r = ((glGetIntegeri_v = (PFNGLGETINTEGERI_VPROC)glewGetProcAddress((const GLubyte*)"glGetIntegeri_v")) == NULL) || r;
+ r = ((glGetUniformBlockIndex = (PFNGLGETUNIFORMBLOCKINDEXPROC)glewGetProcAddress((const GLubyte*)"glGetUniformBlockIndex")) == NULL) || r;
+ r = ((glGetUniformIndices = (PFNGLGETUNIFORMINDICESPROC)glewGetProcAddress((const GLubyte*)"glGetUniformIndices")) == NULL) || r;
+ r = ((glUniformBlockBinding = (PFNGLUNIFORMBLOCKBINDINGPROC)glewGetProcAddress((const GLubyte*)"glUniformBlockBinding")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_ARB_uniform_buffer_object */
+
+#ifdef GL_ARB_vertex_array_bgra
+
+#endif /* GL_ARB_vertex_array_bgra */
+
+#ifdef GL_ARB_vertex_array_object
+
+static GLboolean _glewInit_GL_ARB_vertex_array_object (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glBindVertexArray = (PFNGLBINDVERTEXARRAYPROC)glewGetProcAddress((const GLubyte*)"glBindVertexArray")) == NULL) || r;
+ r = ((glDeleteVertexArrays = (PFNGLDELETEVERTEXARRAYSPROC)glewGetProcAddress((const GLubyte*)"glDeleteVertexArrays")) == NULL) || r;
+ r = ((glGenVertexArrays = (PFNGLGENVERTEXARRAYSPROC)glewGetProcAddress((const GLubyte*)"glGenVertexArrays")) == NULL) || r;
+ r = ((glIsVertexArray = (PFNGLISVERTEXARRAYPROC)glewGetProcAddress((const GLubyte*)"glIsVertexArray")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_ARB_vertex_array_object */
+
+#ifdef GL_ARB_vertex_attrib_64bit
+
+static GLboolean _glewInit_GL_ARB_vertex_attrib_64bit (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glGetVertexAttribLdv = (PFNGLGETVERTEXATTRIBLDVPROC)glewGetProcAddress((const GLubyte*)"glGetVertexAttribLdv")) == NULL) || r;
+ r = ((glVertexAttribL1d = (PFNGLVERTEXATTRIBL1DPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribL1d")) == NULL) || r;
+ r = ((glVertexAttribL1dv = (PFNGLVERTEXATTRIBL1DVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribL1dv")) == NULL) || r;
+ r = ((glVertexAttribL2d = (PFNGLVERTEXATTRIBL2DPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribL2d")) == NULL) || r;
+ r = ((glVertexAttribL2dv = (PFNGLVERTEXATTRIBL2DVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribL2dv")) == NULL) || r;
+ r = ((glVertexAttribL3d = (PFNGLVERTEXATTRIBL3DPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribL3d")) == NULL) || r;
+ r = ((glVertexAttribL3dv = (PFNGLVERTEXATTRIBL3DVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribL3dv")) == NULL) || r;
+ r = ((glVertexAttribL4d = (PFNGLVERTEXATTRIBL4DPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribL4d")) == NULL) || r;
+ r = ((glVertexAttribL4dv = (PFNGLVERTEXATTRIBL4DVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribL4dv")) == NULL) || r;
+ r = ((glVertexAttribLPointer = (PFNGLVERTEXATTRIBLPOINTERPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribLPointer")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_ARB_vertex_attrib_64bit */
+
+#ifdef GL_ARB_vertex_attrib_binding
+
+static GLboolean _glewInit_GL_ARB_vertex_attrib_binding (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glBindVertexBuffer = (PFNGLBINDVERTEXBUFFERPROC)glewGetProcAddress((const GLubyte*)"glBindVertexBuffer")) == NULL) || r;
+ r = ((glVertexAttribBinding = (PFNGLVERTEXATTRIBBINDINGPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribBinding")) == NULL) || r;
+ r = ((glVertexAttribFormat = (PFNGLVERTEXATTRIBFORMATPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribFormat")) == NULL) || r;
+ r = ((glVertexAttribIFormat = (PFNGLVERTEXATTRIBIFORMATPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribIFormat")) == NULL) || r;
+ r = ((glVertexAttribLFormat = (PFNGLVERTEXATTRIBLFORMATPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribLFormat")) == NULL) || r;
+ r = ((glVertexBindingDivisor = (PFNGLVERTEXBINDINGDIVISORPROC)glewGetProcAddress((const GLubyte*)"glVertexBindingDivisor")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_ARB_vertex_attrib_binding */
+
+#ifdef GL_ARB_vertex_blend
+
+static GLboolean _glewInit_GL_ARB_vertex_blend (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glVertexBlendARB = (PFNGLVERTEXBLENDARBPROC)glewGetProcAddress((const GLubyte*)"glVertexBlendARB")) == NULL) || r;
+ r = ((glWeightPointerARB = (PFNGLWEIGHTPOINTERARBPROC)glewGetProcAddress((const GLubyte*)"glWeightPointerARB")) == NULL) || r;
+ r = ((glWeightbvARB = (PFNGLWEIGHTBVARBPROC)glewGetProcAddress((const GLubyte*)"glWeightbvARB")) == NULL) || r;
+ r = ((glWeightdvARB = (PFNGLWEIGHTDVARBPROC)glewGetProcAddress((const GLubyte*)"glWeightdvARB")) == NULL) || r;
+ r = ((glWeightfvARB = (PFNGLWEIGHTFVARBPROC)glewGetProcAddress((const GLubyte*)"glWeightfvARB")) == NULL) || r;
+ r = ((glWeightivARB = (PFNGLWEIGHTIVARBPROC)glewGetProcAddress((const GLubyte*)"glWeightivARB")) == NULL) || r;
+ r = ((glWeightsvARB = (PFNGLWEIGHTSVARBPROC)glewGetProcAddress((const GLubyte*)"glWeightsvARB")) == NULL) || r;
+ r = ((glWeightubvARB = (PFNGLWEIGHTUBVARBPROC)glewGetProcAddress((const GLubyte*)"glWeightubvARB")) == NULL) || r;
+ r = ((glWeightuivARB = (PFNGLWEIGHTUIVARBPROC)glewGetProcAddress((const GLubyte*)"glWeightuivARB")) == NULL) || r;
+ r = ((glWeightusvARB = (PFNGLWEIGHTUSVARBPROC)glewGetProcAddress((const GLubyte*)"glWeightusvARB")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_ARB_vertex_blend */
+
+#ifdef GL_ARB_vertex_buffer_object
+
+static GLboolean _glewInit_GL_ARB_vertex_buffer_object (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glBindBufferARB = (PFNGLBINDBUFFERARBPROC)glewGetProcAddress((const GLubyte*)"glBindBufferARB")) == NULL) || r;
+ r = ((glBufferDataARB = (PFNGLBUFFERDATAARBPROC)glewGetProcAddress((const GLubyte*)"glBufferDataARB")) == NULL) || r;
+ r = ((glBufferSubDataARB = (PFNGLBUFFERSUBDATAARBPROC)glewGetProcAddress((const GLubyte*)"glBufferSubDataARB")) == NULL) || r;
+ r = ((glDeleteBuffersARB = (PFNGLDELETEBUFFERSARBPROC)glewGetProcAddress((const GLubyte*)"glDeleteBuffersARB")) == NULL) || r;
+ r = ((glGenBuffersARB = (PFNGLGENBUFFERSARBPROC)glewGetProcAddress((const GLubyte*)"glGenBuffersARB")) == NULL) || r;
+ r = ((glGetBufferParameterivARB = (PFNGLGETBUFFERPARAMETERIVARBPROC)glewGetProcAddress((const GLubyte*)"glGetBufferParameterivARB")) == NULL) || r;
+ r = ((glGetBufferPointervARB = (PFNGLGETBUFFERPOINTERVARBPROC)glewGetProcAddress((const GLubyte*)"glGetBufferPointervARB")) == NULL) || r;
+ r = ((glGetBufferSubDataARB = (PFNGLGETBUFFERSUBDATAARBPROC)glewGetProcAddress((const GLubyte*)"glGetBufferSubDataARB")) == NULL) || r;
+ r = ((glIsBufferARB = (PFNGLISBUFFERARBPROC)glewGetProcAddress((const GLubyte*)"glIsBufferARB")) == NULL) || r;
+ r = ((glMapBufferARB = (PFNGLMAPBUFFERARBPROC)glewGetProcAddress((const GLubyte*)"glMapBufferARB")) == NULL) || r;
+ r = ((glUnmapBufferARB = (PFNGLUNMAPBUFFERARBPROC)glewGetProcAddress((const GLubyte*)"glUnmapBufferARB")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_ARB_vertex_buffer_object */
+
+#ifdef GL_ARB_vertex_program
+
+static GLboolean _glewInit_GL_ARB_vertex_program (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glBindProgramARB = (PFNGLBINDPROGRAMARBPROC)glewGetProcAddress((const GLubyte*)"glBindProgramARB")) == NULL) || r;
+ r = ((glDeleteProgramsARB = (PFNGLDELETEPROGRAMSARBPROC)glewGetProcAddress((const GLubyte*)"glDeleteProgramsARB")) == NULL) || r;
+ r = ((glDisableVertexAttribArrayARB = (PFNGLDISABLEVERTEXATTRIBARRAYARBPROC)glewGetProcAddress((const GLubyte*)"glDisableVertexAttribArrayARB")) == NULL) || r;
+ r = ((glEnableVertexAttribArrayARB = (PFNGLENABLEVERTEXATTRIBARRAYARBPROC)glewGetProcAddress((const GLubyte*)"glEnableVertexAttribArrayARB")) == NULL) || r;
+ r = ((glGenProgramsARB = (PFNGLGENPROGRAMSARBPROC)glewGetProcAddress((const GLubyte*)"glGenProgramsARB")) == NULL) || r;
+ r = ((glGetProgramEnvParameterdvARB = (PFNGLGETPROGRAMENVPARAMETERDVARBPROC)glewGetProcAddress((const GLubyte*)"glGetProgramEnvParameterdvARB")) == NULL) || r;
+ r = ((glGetProgramEnvParameterfvARB = (PFNGLGETPROGRAMENVPARAMETERFVARBPROC)glewGetProcAddress((const GLubyte*)"glGetProgramEnvParameterfvARB")) == NULL) || r;
+ r = ((glGetProgramLocalParameterdvARB = (PFNGLGETPROGRAMLOCALPARAMETERDVARBPROC)glewGetProcAddress((const GLubyte*)"glGetProgramLocalParameterdvARB")) == NULL) || r;
+ r = ((glGetProgramLocalParameterfvARB = (PFNGLGETPROGRAMLOCALPARAMETERFVARBPROC)glewGetProcAddress((const GLubyte*)"glGetProgramLocalParameterfvARB")) == NULL) || r;
+ r = ((glGetProgramStringARB = (PFNGLGETPROGRAMSTRINGARBPROC)glewGetProcAddress((const GLubyte*)"glGetProgramStringARB")) == NULL) || r;
+ r = ((glGetProgramivARB = (PFNGLGETPROGRAMIVARBPROC)glewGetProcAddress((const GLubyte*)"glGetProgramivARB")) == NULL) || r;
+ r = ((glGetVertexAttribPointervARB = (PFNGLGETVERTEXATTRIBPOINTERVARBPROC)glewGetProcAddress((const GLubyte*)"glGetVertexAttribPointervARB")) == NULL) || r;
+ r = ((glGetVertexAttribdvARB = (PFNGLGETVERTEXATTRIBDVARBPROC)glewGetProcAddress((const GLubyte*)"glGetVertexAttribdvARB")) == NULL) || r;
+ r = ((glGetVertexAttribfvARB = (PFNGLGETVERTEXATTRIBFVARBPROC)glewGetProcAddress((const GLubyte*)"glGetVertexAttribfvARB")) == NULL) || r;
+ r = ((glGetVertexAttribivARB = (PFNGLGETVERTEXATTRIBIVARBPROC)glewGetProcAddress((const GLubyte*)"glGetVertexAttribivARB")) == NULL) || r;
+ r = ((glIsProgramARB = (PFNGLISPROGRAMARBPROC)glewGetProcAddress((const GLubyte*)"glIsProgramARB")) == NULL) || r;
+ r = ((glProgramEnvParameter4dARB = (PFNGLPROGRAMENVPARAMETER4DARBPROC)glewGetProcAddress((const GLubyte*)"glProgramEnvParameter4dARB")) == NULL) || r;
+ r = ((glProgramEnvParameter4dvARB = (PFNGLPROGRAMENVPARAMETER4DVARBPROC)glewGetProcAddress((const GLubyte*)"glProgramEnvParameter4dvARB")) == NULL) || r;
+ r = ((glProgramEnvParameter4fARB = (PFNGLPROGRAMENVPARAMETER4FARBPROC)glewGetProcAddress((const GLubyte*)"glProgramEnvParameter4fARB")) == NULL) || r;
+ r = ((glProgramEnvParameter4fvARB = (PFNGLPROGRAMENVPARAMETER4FVARBPROC)glewGetProcAddress((const GLubyte*)"glProgramEnvParameter4fvARB")) == NULL) || r;
+ r = ((glProgramLocalParameter4dARB = (PFNGLPROGRAMLOCALPARAMETER4DARBPROC)glewGetProcAddress((const GLubyte*)"glProgramLocalParameter4dARB")) == NULL) || r;
+ r = ((glProgramLocalParameter4dvARB = (PFNGLPROGRAMLOCALPARAMETER4DVARBPROC)glewGetProcAddress((const GLubyte*)"glProgramLocalParameter4dvARB")) == NULL) || r;
+ r = ((glProgramLocalParameter4fARB = (PFNGLPROGRAMLOCALPARAMETER4FARBPROC)glewGetProcAddress((const GLubyte*)"glProgramLocalParameter4fARB")) == NULL) || r;
+ r = ((glProgramLocalParameter4fvARB = (PFNGLPROGRAMLOCALPARAMETER4FVARBPROC)glewGetProcAddress((const GLubyte*)"glProgramLocalParameter4fvARB")) == NULL) || r;
+ r = ((glProgramStringARB = (PFNGLPROGRAMSTRINGARBPROC)glewGetProcAddress((const GLubyte*)"glProgramStringARB")) == NULL) || r;
+ r = ((glVertexAttrib1dARB = (PFNGLVERTEXATTRIB1DARBPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib1dARB")) == NULL) || r;
+ r = ((glVertexAttrib1dvARB = (PFNGLVERTEXATTRIB1DVARBPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib1dvARB")) == NULL) || r;
+ r = ((glVertexAttrib1fARB = (PFNGLVERTEXATTRIB1FARBPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib1fARB")) == NULL) || r;
+ r = ((glVertexAttrib1fvARB = (PFNGLVERTEXATTRIB1FVARBPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib1fvARB")) == NULL) || r;
+ r = ((glVertexAttrib1sARB = (PFNGLVERTEXATTRIB1SARBPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib1sARB")) == NULL) || r;
+ r = ((glVertexAttrib1svARB = (PFNGLVERTEXATTRIB1SVARBPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib1svARB")) == NULL) || r;
+ r = ((glVertexAttrib2dARB = (PFNGLVERTEXATTRIB2DARBPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib2dARB")) == NULL) || r;
+ r = ((glVertexAttrib2dvARB = (PFNGLVERTEXATTRIB2DVARBPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib2dvARB")) == NULL) || r;
+ r = ((glVertexAttrib2fARB = (PFNGLVERTEXATTRIB2FARBPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib2fARB")) == NULL) || r;
+ r = ((glVertexAttrib2fvARB = (PFNGLVERTEXATTRIB2FVARBPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib2fvARB")) == NULL) || r;
+ r = ((glVertexAttrib2sARB = (PFNGLVERTEXATTRIB2SARBPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib2sARB")) == NULL) || r;
+ r = ((glVertexAttrib2svARB = (PFNGLVERTEXATTRIB2SVARBPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib2svARB")) == NULL) || r;
+ r = ((glVertexAttrib3dARB = (PFNGLVERTEXATTRIB3DARBPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib3dARB")) == NULL) || r;
+ r = ((glVertexAttrib3dvARB = (PFNGLVERTEXATTRIB3DVARBPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib3dvARB")) == NULL) || r;
+ r = ((glVertexAttrib3fARB = (PFNGLVERTEXATTRIB3FARBPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib3fARB")) == NULL) || r;
+ r = ((glVertexAttrib3fvARB = (PFNGLVERTEXATTRIB3FVARBPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib3fvARB")) == NULL) || r;
+ r = ((glVertexAttrib3sARB = (PFNGLVERTEXATTRIB3SARBPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib3sARB")) == NULL) || r;
+ r = ((glVertexAttrib3svARB = (PFNGLVERTEXATTRIB3SVARBPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib3svARB")) == NULL) || r;
+ r = ((glVertexAttrib4NbvARB = (PFNGLVERTEXATTRIB4NBVARBPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4NbvARB")) == NULL) || r;
+ r = ((glVertexAttrib4NivARB = (PFNGLVERTEXATTRIB4NIVARBPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4NivARB")) == NULL) || r;
+ r = ((glVertexAttrib4NsvARB = (PFNGLVERTEXATTRIB4NSVARBPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4NsvARB")) == NULL) || r;
+ r = ((glVertexAttrib4NubARB = (PFNGLVERTEXATTRIB4NUBARBPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4NubARB")) == NULL) || r;
+ r = ((glVertexAttrib4NubvARB = (PFNGLVERTEXATTRIB4NUBVARBPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4NubvARB")) == NULL) || r;
+ r = ((glVertexAttrib4NuivARB = (PFNGLVERTEXATTRIB4NUIVARBPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4NuivARB")) == NULL) || r;
+ r = ((glVertexAttrib4NusvARB = (PFNGLVERTEXATTRIB4NUSVARBPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4NusvARB")) == NULL) || r;
+ r = ((glVertexAttrib4bvARB = (PFNGLVERTEXATTRIB4BVARBPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4bvARB")) == NULL) || r;
+ r = ((glVertexAttrib4dARB = (PFNGLVERTEXATTRIB4DARBPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4dARB")) == NULL) || r;
+ r = ((glVertexAttrib4dvARB = (PFNGLVERTEXATTRIB4DVARBPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4dvARB")) == NULL) || r;
+ r = ((glVertexAttrib4fARB = (PFNGLVERTEXATTRIB4FARBPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4fARB")) == NULL) || r;
+ r = ((glVertexAttrib4fvARB = (PFNGLVERTEXATTRIB4FVARBPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4fvARB")) == NULL) || r;
+ r = ((glVertexAttrib4ivARB = (PFNGLVERTEXATTRIB4IVARBPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4ivARB")) == NULL) || r;
+ r = ((glVertexAttrib4sARB = (PFNGLVERTEXATTRIB4SARBPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4sARB")) == NULL) || r;
+ r = ((glVertexAttrib4svARB = (PFNGLVERTEXATTRIB4SVARBPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4svARB")) == NULL) || r;
+ r = ((glVertexAttrib4ubvARB = (PFNGLVERTEXATTRIB4UBVARBPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4ubvARB")) == NULL) || r;
+ r = ((glVertexAttrib4uivARB = (PFNGLVERTEXATTRIB4UIVARBPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4uivARB")) == NULL) || r;
+ r = ((glVertexAttrib4usvARB = (PFNGLVERTEXATTRIB4USVARBPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4usvARB")) == NULL) || r;
+ r = ((glVertexAttribPointerARB = (PFNGLVERTEXATTRIBPOINTERARBPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribPointerARB")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_ARB_vertex_program */
+
+#ifdef GL_ARB_vertex_shader
+
+static GLboolean _glewInit_GL_ARB_vertex_shader (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glBindAttribLocationARB = (PFNGLBINDATTRIBLOCATIONARBPROC)glewGetProcAddress((const GLubyte*)"glBindAttribLocationARB")) == NULL) || r;
+ r = ((glGetActiveAttribARB = (PFNGLGETACTIVEATTRIBARBPROC)glewGetProcAddress((const GLubyte*)"glGetActiveAttribARB")) == NULL) || r;
+ r = ((glGetAttribLocationARB = (PFNGLGETATTRIBLOCATIONARBPROC)glewGetProcAddress((const GLubyte*)"glGetAttribLocationARB")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_ARB_vertex_shader */
+
+#ifdef GL_ARB_vertex_type_2_10_10_10_rev
+
+static GLboolean _glewInit_GL_ARB_vertex_type_2_10_10_10_rev (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glColorP3ui = (PFNGLCOLORP3UIPROC)glewGetProcAddress((const GLubyte*)"glColorP3ui")) == NULL) || r;
+ r = ((glColorP3uiv = (PFNGLCOLORP3UIVPROC)glewGetProcAddress((const GLubyte*)"glColorP3uiv")) == NULL) || r;
+ r = ((glColorP4ui = (PFNGLCOLORP4UIPROC)glewGetProcAddress((const GLubyte*)"glColorP4ui")) == NULL) || r;
+ r = ((glColorP4uiv = (PFNGLCOLORP4UIVPROC)glewGetProcAddress((const GLubyte*)"glColorP4uiv")) == NULL) || r;
+ r = ((glMultiTexCoordP1ui = (PFNGLMULTITEXCOORDP1UIPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoordP1ui")) == NULL) || r;
+ r = ((glMultiTexCoordP1uiv = (PFNGLMULTITEXCOORDP1UIVPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoordP1uiv")) == NULL) || r;
+ r = ((glMultiTexCoordP2ui = (PFNGLMULTITEXCOORDP2UIPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoordP2ui")) == NULL) || r;
+ r = ((glMultiTexCoordP2uiv = (PFNGLMULTITEXCOORDP2UIVPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoordP2uiv")) == NULL) || r;
+ r = ((glMultiTexCoordP3ui = (PFNGLMULTITEXCOORDP3UIPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoordP3ui")) == NULL) || r;
+ r = ((glMultiTexCoordP3uiv = (PFNGLMULTITEXCOORDP3UIVPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoordP3uiv")) == NULL) || r;
+ r = ((glMultiTexCoordP4ui = (PFNGLMULTITEXCOORDP4UIPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoordP4ui")) == NULL) || r;
+ r = ((glMultiTexCoordP4uiv = (PFNGLMULTITEXCOORDP4UIVPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoordP4uiv")) == NULL) || r;
+ r = ((glNormalP3ui = (PFNGLNORMALP3UIPROC)glewGetProcAddress((const GLubyte*)"glNormalP3ui")) == NULL) || r;
+ r = ((glNormalP3uiv = (PFNGLNORMALP3UIVPROC)glewGetProcAddress((const GLubyte*)"glNormalP3uiv")) == NULL) || r;
+ r = ((glSecondaryColorP3ui = (PFNGLSECONDARYCOLORP3UIPROC)glewGetProcAddress((const GLubyte*)"glSecondaryColorP3ui")) == NULL) || r;
+ r = ((glSecondaryColorP3uiv = (PFNGLSECONDARYCOLORP3UIVPROC)glewGetProcAddress((const GLubyte*)"glSecondaryColorP3uiv")) == NULL) || r;
+ r = ((glTexCoordP1ui = (PFNGLTEXCOORDP1UIPROC)glewGetProcAddress((const GLubyte*)"glTexCoordP1ui")) == NULL) || r;
+ r = ((glTexCoordP1uiv = (PFNGLTEXCOORDP1UIVPROC)glewGetProcAddress((const GLubyte*)"glTexCoordP1uiv")) == NULL) || r;
+ r = ((glTexCoordP2ui = (PFNGLTEXCOORDP2UIPROC)glewGetProcAddress((const GLubyte*)"glTexCoordP2ui")) == NULL) || r;
+ r = ((glTexCoordP2uiv = (PFNGLTEXCOORDP2UIVPROC)glewGetProcAddress((const GLubyte*)"glTexCoordP2uiv")) == NULL) || r;
+ r = ((glTexCoordP3ui = (PFNGLTEXCOORDP3UIPROC)glewGetProcAddress((const GLubyte*)"glTexCoordP3ui")) == NULL) || r;
+ r = ((glTexCoordP3uiv = (PFNGLTEXCOORDP3UIVPROC)glewGetProcAddress((const GLubyte*)"glTexCoordP3uiv")) == NULL) || r;
+ r = ((glTexCoordP4ui = (PFNGLTEXCOORDP4UIPROC)glewGetProcAddress((const GLubyte*)"glTexCoordP4ui")) == NULL) || r;
+ r = ((glTexCoordP4uiv = (PFNGLTEXCOORDP4UIVPROC)glewGetProcAddress((const GLubyte*)"glTexCoordP4uiv")) == NULL) || r;
+ r = ((glVertexAttribP1ui = (PFNGLVERTEXATTRIBP1UIPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribP1ui")) == NULL) || r;
+ r = ((glVertexAttribP1uiv = (PFNGLVERTEXATTRIBP1UIVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribP1uiv")) == NULL) || r;
+ r = ((glVertexAttribP2ui = (PFNGLVERTEXATTRIBP2UIPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribP2ui")) == NULL) || r;
+ r = ((glVertexAttribP2uiv = (PFNGLVERTEXATTRIBP2UIVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribP2uiv")) == NULL) || r;
+ r = ((glVertexAttribP3ui = (PFNGLVERTEXATTRIBP3UIPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribP3ui")) == NULL) || r;
+ r = ((glVertexAttribP3uiv = (PFNGLVERTEXATTRIBP3UIVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribP3uiv")) == NULL) || r;
+ r = ((glVertexAttribP4ui = (PFNGLVERTEXATTRIBP4UIPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribP4ui")) == NULL) || r;
+ r = ((glVertexAttribP4uiv = (PFNGLVERTEXATTRIBP4UIVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribP4uiv")) == NULL) || r;
+ r = ((glVertexP2ui = (PFNGLVERTEXP2UIPROC)glewGetProcAddress((const GLubyte*)"glVertexP2ui")) == NULL) || r;
+ r = ((glVertexP2uiv = (PFNGLVERTEXP2UIVPROC)glewGetProcAddress((const GLubyte*)"glVertexP2uiv")) == NULL) || r;
+ r = ((glVertexP3ui = (PFNGLVERTEXP3UIPROC)glewGetProcAddress((const GLubyte*)"glVertexP3ui")) == NULL) || r;
+ r = ((glVertexP3uiv = (PFNGLVERTEXP3UIVPROC)glewGetProcAddress((const GLubyte*)"glVertexP3uiv")) == NULL) || r;
+ r = ((glVertexP4ui = (PFNGLVERTEXP4UIPROC)glewGetProcAddress((const GLubyte*)"glVertexP4ui")) == NULL) || r;
+ r = ((glVertexP4uiv = (PFNGLVERTEXP4UIVPROC)glewGetProcAddress((const GLubyte*)"glVertexP4uiv")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_ARB_vertex_type_2_10_10_10_rev */
+
+#ifdef GL_ARB_viewport_array
+
+static GLboolean _glewInit_GL_ARB_viewport_array (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glDepthRangeArrayv = (PFNGLDEPTHRANGEARRAYVPROC)glewGetProcAddress((const GLubyte*)"glDepthRangeArrayv")) == NULL) || r;
+ r = ((glDepthRangeIndexed = (PFNGLDEPTHRANGEINDEXEDPROC)glewGetProcAddress((const GLubyte*)"glDepthRangeIndexed")) == NULL) || r;
+ r = ((glGetDoublei_v = (PFNGLGETDOUBLEI_VPROC)glewGetProcAddress((const GLubyte*)"glGetDoublei_v")) == NULL) || r;
+ r = ((glGetFloati_v = (PFNGLGETFLOATI_VPROC)glewGetProcAddress((const GLubyte*)"glGetFloati_v")) == NULL) || r;
+ r = ((glScissorArrayv = (PFNGLSCISSORARRAYVPROC)glewGetProcAddress((const GLubyte*)"glScissorArrayv")) == NULL) || r;
+ r = ((glScissorIndexed = (PFNGLSCISSORINDEXEDPROC)glewGetProcAddress((const GLubyte*)"glScissorIndexed")) == NULL) || r;
+ r = ((glScissorIndexedv = (PFNGLSCISSORINDEXEDVPROC)glewGetProcAddress((const GLubyte*)"glScissorIndexedv")) == NULL) || r;
+ r = ((glViewportArrayv = (PFNGLVIEWPORTARRAYVPROC)glewGetProcAddress((const GLubyte*)"glViewportArrayv")) == NULL) || r;
+ r = ((glViewportIndexedf = (PFNGLVIEWPORTINDEXEDFPROC)glewGetProcAddress((const GLubyte*)"glViewportIndexedf")) == NULL) || r;
+ r = ((glViewportIndexedfv = (PFNGLVIEWPORTINDEXEDFVPROC)glewGetProcAddress((const GLubyte*)"glViewportIndexedfv")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_ARB_viewport_array */
+
+#ifdef GL_ARB_window_pos
+
+static GLboolean _glewInit_GL_ARB_window_pos (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glWindowPos2dARB = (PFNGLWINDOWPOS2DARBPROC)glewGetProcAddress((const GLubyte*)"glWindowPos2dARB")) == NULL) || r;
+ r = ((glWindowPos2dvARB = (PFNGLWINDOWPOS2DVARBPROC)glewGetProcAddress((const GLubyte*)"glWindowPos2dvARB")) == NULL) || r;
+ r = ((glWindowPos2fARB = (PFNGLWINDOWPOS2FARBPROC)glewGetProcAddress((const GLubyte*)"glWindowPos2fARB")) == NULL) || r;
+ r = ((glWindowPos2fvARB = (PFNGLWINDOWPOS2FVARBPROC)glewGetProcAddress((const GLubyte*)"glWindowPos2fvARB")) == NULL) || r;
+ r = ((glWindowPos2iARB = (PFNGLWINDOWPOS2IARBPROC)glewGetProcAddress((const GLubyte*)"glWindowPos2iARB")) == NULL) || r;
+ r = ((glWindowPos2ivARB = (PFNGLWINDOWPOS2IVARBPROC)glewGetProcAddress((const GLubyte*)"glWindowPos2ivARB")) == NULL) || r;
+ r = ((glWindowPos2sARB = (PFNGLWINDOWPOS2SARBPROC)glewGetProcAddress((const GLubyte*)"glWindowPos2sARB")) == NULL) || r;
+ r = ((glWindowPos2svARB = (PFNGLWINDOWPOS2SVARBPROC)glewGetProcAddress((const GLubyte*)"glWindowPos2svARB")) == NULL) || r;
+ r = ((glWindowPos3dARB = (PFNGLWINDOWPOS3DARBPROC)glewGetProcAddress((const GLubyte*)"glWindowPos3dARB")) == NULL) || r;
+ r = ((glWindowPos3dvARB = (PFNGLWINDOWPOS3DVARBPROC)glewGetProcAddress((const GLubyte*)"glWindowPos3dvARB")) == NULL) || r;
+ r = ((glWindowPos3fARB = (PFNGLWINDOWPOS3FARBPROC)glewGetProcAddress((const GLubyte*)"glWindowPos3fARB")) == NULL) || r;
+ r = ((glWindowPos3fvARB = (PFNGLWINDOWPOS3FVARBPROC)glewGetProcAddress((const GLubyte*)"glWindowPos3fvARB")) == NULL) || r;
+ r = ((glWindowPos3iARB = (PFNGLWINDOWPOS3IARBPROC)glewGetProcAddress((const GLubyte*)"glWindowPos3iARB")) == NULL) || r;
+ r = ((glWindowPos3ivARB = (PFNGLWINDOWPOS3IVARBPROC)glewGetProcAddress((const GLubyte*)"glWindowPos3ivARB")) == NULL) || r;
+ r = ((glWindowPos3sARB = (PFNGLWINDOWPOS3SARBPROC)glewGetProcAddress((const GLubyte*)"glWindowPos3sARB")) == NULL) || r;
+ r = ((glWindowPos3svARB = (PFNGLWINDOWPOS3SVARBPROC)glewGetProcAddress((const GLubyte*)"glWindowPos3svARB")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_ARB_window_pos */
+
+#ifdef GL_ATIX_point_sprites
+
+#endif /* GL_ATIX_point_sprites */
+
+#ifdef GL_ATIX_texture_env_combine3
+
+#endif /* GL_ATIX_texture_env_combine3 */
+
+#ifdef GL_ATIX_texture_env_route
+
+#endif /* GL_ATIX_texture_env_route */
+
+#ifdef GL_ATIX_vertex_shader_output_point_size
+
+#endif /* GL_ATIX_vertex_shader_output_point_size */
+
+#ifdef GL_ATI_draw_buffers
+
+static GLboolean _glewInit_GL_ATI_draw_buffers (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glDrawBuffersATI = (PFNGLDRAWBUFFERSATIPROC)glewGetProcAddress((const GLubyte*)"glDrawBuffersATI")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_ATI_draw_buffers */
+
+#ifdef GL_ATI_element_array
+
+static GLboolean _glewInit_GL_ATI_element_array (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glDrawElementArrayATI = (PFNGLDRAWELEMENTARRAYATIPROC)glewGetProcAddress((const GLubyte*)"glDrawElementArrayATI")) == NULL) || r;
+ r = ((glDrawRangeElementArrayATI = (PFNGLDRAWRANGEELEMENTARRAYATIPROC)glewGetProcAddress((const GLubyte*)"glDrawRangeElementArrayATI")) == NULL) || r;
+ r = ((glElementPointerATI = (PFNGLELEMENTPOINTERATIPROC)glewGetProcAddress((const GLubyte*)"glElementPointerATI")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_ATI_element_array */
+
+#ifdef GL_ATI_envmap_bumpmap
+
+static GLboolean _glewInit_GL_ATI_envmap_bumpmap (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glGetTexBumpParameterfvATI = (PFNGLGETTEXBUMPPARAMETERFVATIPROC)glewGetProcAddress((const GLubyte*)"glGetTexBumpParameterfvATI")) == NULL) || r;
+ r = ((glGetTexBumpParameterivATI = (PFNGLGETTEXBUMPPARAMETERIVATIPROC)glewGetProcAddress((const GLubyte*)"glGetTexBumpParameterivATI")) == NULL) || r;
+ r = ((glTexBumpParameterfvATI = (PFNGLTEXBUMPPARAMETERFVATIPROC)glewGetProcAddress((const GLubyte*)"glTexBumpParameterfvATI")) == NULL) || r;
+ r = ((glTexBumpParameterivATI = (PFNGLTEXBUMPPARAMETERIVATIPROC)glewGetProcAddress((const GLubyte*)"glTexBumpParameterivATI")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_ATI_envmap_bumpmap */
+
+#ifdef GL_ATI_fragment_shader
+
+static GLboolean _glewInit_GL_ATI_fragment_shader (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glAlphaFragmentOp1ATI = (PFNGLALPHAFRAGMENTOP1ATIPROC)glewGetProcAddress((const GLubyte*)"glAlphaFragmentOp1ATI")) == NULL) || r;
+ r = ((glAlphaFragmentOp2ATI = (PFNGLALPHAFRAGMENTOP2ATIPROC)glewGetProcAddress((const GLubyte*)"glAlphaFragmentOp2ATI")) == NULL) || r;
+ r = ((glAlphaFragmentOp3ATI = (PFNGLALPHAFRAGMENTOP3ATIPROC)glewGetProcAddress((const GLubyte*)"glAlphaFragmentOp3ATI")) == NULL) || r;
+ r = ((glBeginFragmentShaderATI = (PFNGLBEGINFRAGMENTSHADERATIPROC)glewGetProcAddress((const GLubyte*)"glBeginFragmentShaderATI")) == NULL) || r;
+ r = ((glBindFragmentShaderATI = (PFNGLBINDFRAGMENTSHADERATIPROC)glewGetProcAddress((const GLubyte*)"glBindFragmentShaderATI")) == NULL) || r;
+ r = ((glColorFragmentOp1ATI = (PFNGLCOLORFRAGMENTOP1ATIPROC)glewGetProcAddress((const GLubyte*)"glColorFragmentOp1ATI")) == NULL) || r;
+ r = ((glColorFragmentOp2ATI = (PFNGLCOLORFRAGMENTOP2ATIPROC)glewGetProcAddress((const GLubyte*)"glColorFragmentOp2ATI")) == NULL) || r;
+ r = ((glColorFragmentOp3ATI = (PFNGLCOLORFRAGMENTOP3ATIPROC)glewGetProcAddress((const GLubyte*)"glColorFragmentOp3ATI")) == NULL) || r;
+ r = ((glDeleteFragmentShaderATI = (PFNGLDELETEFRAGMENTSHADERATIPROC)glewGetProcAddress((const GLubyte*)"glDeleteFragmentShaderATI")) == NULL) || r;
+ r = ((glEndFragmentShaderATI = (PFNGLENDFRAGMENTSHADERATIPROC)glewGetProcAddress((const GLubyte*)"glEndFragmentShaderATI")) == NULL) || r;
+ r = ((glGenFragmentShadersATI = (PFNGLGENFRAGMENTSHADERSATIPROC)glewGetProcAddress((const GLubyte*)"glGenFragmentShadersATI")) == NULL) || r;
+ r = ((glPassTexCoordATI = (PFNGLPASSTEXCOORDATIPROC)glewGetProcAddress((const GLubyte*)"glPassTexCoordATI")) == NULL) || r;
+ r = ((glSampleMapATI = (PFNGLSAMPLEMAPATIPROC)glewGetProcAddress((const GLubyte*)"glSampleMapATI")) == NULL) || r;
+ r = ((glSetFragmentShaderConstantATI = (PFNGLSETFRAGMENTSHADERCONSTANTATIPROC)glewGetProcAddress((const GLubyte*)"glSetFragmentShaderConstantATI")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_ATI_fragment_shader */
+
+#ifdef GL_ATI_map_object_buffer
+
+static GLboolean _glewInit_GL_ATI_map_object_buffer (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glMapObjectBufferATI = (PFNGLMAPOBJECTBUFFERATIPROC)glewGetProcAddress((const GLubyte*)"glMapObjectBufferATI")) == NULL) || r;
+ r = ((glUnmapObjectBufferATI = (PFNGLUNMAPOBJECTBUFFERATIPROC)glewGetProcAddress((const GLubyte*)"glUnmapObjectBufferATI")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_ATI_map_object_buffer */
+
+#ifdef GL_ATI_meminfo
+
+#endif /* GL_ATI_meminfo */
+
+#ifdef GL_ATI_pn_triangles
+
+static GLboolean _glewInit_GL_ATI_pn_triangles (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glPNTrianglesfATI = (PFNGLPNTRIANGLESFATIPROC)glewGetProcAddress((const GLubyte*)"glPNTrianglesfATI")) == NULL) || r;
+ r = ((glPNTrianglesiATI = (PFNGLPNTRIANGLESIATIPROC)glewGetProcAddress((const GLubyte*)"glPNTrianglesiATI")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_ATI_pn_triangles */
+
+#ifdef GL_ATI_separate_stencil
+
+static GLboolean _glewInit_GL_ATI_separate_stencil (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glStencilFuncSeparateATI = (PFNGLSTENCILFUNCSEPARATEATIPROC)glewGetProcAddress((const GLubyte*)"glStencilFuncSeparateATI")) == NULL) || r;
+ r = ((glStencilOpSeparateATI = (PFNGLSTENCILOPSEPARATEATIPROC)glewGetProcAddress((const GLubyte*)"glStencilOpSeparateATI")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_ATI_separate_stencil */
+
+#ifdef GL_ATI_shader_texture_lod
+
+#endif /* GL_ATI_shader_texture_lod */
+
+#ifdef GL_ATI_text_fragment_shader
+
+#endif /* GL_ATI_text_fragment_shader */
+
+#ifdef GL_ATI_texture_compression_3dc
+
+#endif /* GL_ATI_texture_compression_3dc */
+
+#ifdef GL_ATI_texture_env_combine3
+
+#endif /* GL_ATI_texture_env_combine3 */
+
+#ifdef GL_ATI_texture_float
+
+#endif /* GL_ATI_texture_float */
+
+#ifdef GL_ATI_texture_mirror_once
+
+#endif /* GL_ATI_texture_mirror_once */
+
+#ifdef GL_ATI_vertex_array_object
+
+static GLboolean _glewInit_GL_ATI_vertex_array_object (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glArrayObjectATI = (PFNGLARRAYOBJECTATIPROC)glewGetProcAddress((const GLubyte*)"glArrayObjectATI")) == NULL) || r;
+ r = ((glFreeObjectBufferATI = (PFNGLFREEOBJECTBUFFERATIPROC)glewGetProcAddress((const GLubyte*)"glFreeObjectBufferATI")) == NULL) || r;
+ r = ((glGetArrayObjectfvATI = (PFNGLGETARRAYOBJECTFVATIPROC)glewGetProcAddress((const GLubyte*)"glGetArrayObjectfvATI")) == NULL) || r;
+ r = ((glGetArrayObjectivATI = (PFNGLGETARRAYOBJECTIVATIPROC)glewGetProcAddress((const GLubyte*)"glGetArrayObjectivATI")) == NULL) || r;
+ r = ((glGetObjectBufferfvATI = (PFNGLGETOBJECTBUFFERFVATIPROC)glewGetProcAddress((const GLubyte*)"glGetObjectBufferfvATI")) == NULL) || r;
+ r = ((glGetObjectBufferivATI = (PFNGLGETOBJECTBUFFERIVATIPROC)glewGetProcAddress((const GLubyte*)"glGetObjectBufferivATI")) == NULL) || r;
+ r = ((glGetVariantArrayObjectfvATI = (PFNGLGETVARIANTARRAYOBJECTFVATIPROC)glewGetProcAddress((const GLubyte*)"glGetVariantArrayObjectfvATI")) == NULL) || r;
+ r = ((glGetVariantArrayObjectivATI = (PFNGLGETVARIANTARRAYOBJECTIVATIPROC)glewGetProcAddress((const GLubyte*)"glGetVariantArrayObjectivATI")) == NULL) || r;
+ r = ((glIsObjectBufferATI = (PFNGLISOBJECTBUFFERATIPROC)glewGetProcAddress((const GLubyte*)"glIsObjectBufferATI")) == NULL) || r;
+ r = ((glNewObjectBufferATI = (PFNGLNEWOBJECTBUFFERATIPROC)glewGetProcAddress((const GLubyte*)"glNewObjectBufferATI")) == NULL) || r;
+ r = ((glUpdateObjectBufferATI = (PFNGLUPDATEOBJECTBUFFERATIPROC)glewGetProcAddress((const GLubyte*)"glUpdateObjectBufferATI")) == NULL) || r;
+ r = ((glVariantArrayObjectATI = (PFNGLVARIANTARRAYOBJECTATIPROC)glewGetProcAddress((const GLubyte*)"glVariantArrayObjectATI")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_ATI_vertex_array_object */
+
+#ifdef GL_ATI_vertex_attrib_array_object
+
+static GLboolean _glewInit_GL_ATI_vertex_attrib_array_object (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glGetVertexAttribArrayObjectfvATI = (PFNGLGETVERTEXATTRIBARRAYOBJECTFVATIPROC)glewGetProcAddress((const GLubyte*)"glGetVertexAttribArrayObjectfvATI")) == NULL) || r;
+ r = ((glGetVertexAttribArrayObjectivATI = (PFNGLGETVERTEXATTRIBARRAYOBJECTIVATIPROC)glewGetProcAddress((const GLubyte*)"glGetVertexAttribArrayObjectivATI")) == NULL) || r;
+ r = ((glVertexAttribArrayObjectATI = (PFNGLVERTEXATTRIBARRAYOBJECTATIPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribArrayObjectATI")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_ATI_vertex_attrib_array_object */
+
+#ifdef GL_ATI_vertex_streams
+
+static GLboolean _glewInit_GL_ATI_vertex_streams (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glClientActiveVertexStreamATI = (PFNGLCLIENTACTIVEVERTEXSTREAMATIPROC)glewGetProcAddress((const GLubyte*)"glClientActiveVertexStreamATI")) == NULL) || r;
+ r = ((glNormalStream3bATI = (PFNGLNORMALSTREAM3BATIPROC)glewGetProcAddress((const GLubyte*)"glNormalStream3bATI")) == NULL) || r;
+ r = ((glNormalStream3bvATI = (PFNGLNORMALSTREAM3BVATIPROC)glewGetProcAddress((const GLubyte*)"glNormalStream3bvATI")) == NULL) || r;
+ r = ((glNormalStream3dATI = (PFNGLNORMALSTREAM3DATIPROC)glewGetProcAddress((const GLubyte*)"glNormalStream3dATI")) == NULL) || r;
+ r = ((glNormalStream3dvATI = (PFNGLNORMALSTREAM3DVATIPROC)glewGetProcAddress((const GLubyte*)"glNormalStream3dvATI")) == NULL) || r;
+ r = ((glNormalStream3fATI = (PFNGLNORMALSTREAM3FATIPROC)glewGetProcAddress((const GLubyte*)"glNormalStream3fATI")) == NULL) || r;
+ r = ((glNormalStream3fvATI = (PFNGLNORMALSTREAM3FVATIPROC)glewGetProcAddress((const GLubyte*)"glNormalStream3fvATI")) == NULL) || r;
+ r = ((glNormalStream3iATI = (PFNGLNORMALSTREAM3IATIPROC)glewGetProcAddress((const GLubyte*)"glNormalStream3iATI")) == NULL) || r;
+ r = ((glNormalStream3ivATI = (PFNGLNORMALSTREAM3IVATIPROC)glewGetProcAddress((const GLubyte*)"glNormalStream3ivATI")) == NULL) || r;
+ r = ((glNormalStream3sATI = (PFNGLNORMALSTREAM3SATIPROC)glewGetProcAddress((const GLubyte*)"glNormalStream3sATI")) == NULL) || r;
+ r = ((glNormalStream3svATI = (PFNGLNORMALSTREAM3SVATIPROC)glewGetProcAddress((const GLubyte*)"glNormalStream3svATI")) == NULL) || r;
+ r = ((glVertexBlendEnvfATI = (PFNGLVERTEXBLENDENVFATIPROC)glewGetProcAddress((const GLubyte*)"glVertexBlendEnvfATI")) == NULL) || r;
+ r = ((glVertexBlendEnviATI = (PFNGLVERTEXBLENDENVIATIPROC)glewGetProcAddress((const GLubyte*)"glVertexBlendEnviATI")) == NULL) || r;
+ r = ((glVertexStream2dATI = (PFNGLVERTEXSTREAM2DATIPROC)glewGetProcAddress((const GLubyte*)"glVertexStream2dATI")) == NULL) || r;
+ r = ((glVertexStream2dvATI = (PFNGLVERTEXSTREAM2DVATIPROC)glewGetProcAddress((const GLubyte*)"glVertexStream2dvATI")) == NULL) || r;
+ r = ((glVertexStream2fATI = (PFNGLVERTEXSTREAM2FATIPROC)glewGetProcAddress((const GLubyte*)"glVertexStream2fATI")) == NULL) || r;
+ r = ((glVertexStream2fvATI = (PFNGLVERTEXSTREAM2FVATIPROC)glewGetProcAddress((const GLubyte*)"glVertexStream2fvATI")) == NULL) || r;
+ r = ((glVertexStream2iATI = (PFNGLVERTEXSTREAM2IATIPROC)glewGetProcAddress((const GLubyte*)"glVertexStream2iATI")) == NULL) || r;
+ r = ((glVertexStream2ivATI = (PFNGLVERTEXSTREAM2IVATIPROC)glewGetProcAddress((const GLubyte*)"glVertexStream2ivATI")) == NULL) || r;
+ r = ((glVertexStream2sATI = (PFNGLVERTEXSTREAM2SATIPROC)glewGetProcAddress((const GLubyte*)"glVertexStream2sATI")) == NULL) || r;
+ r = ((glVertexStream2svATI = (PFNGLVERTEXSTREAM2SVATIPROC)glewGetProcAddress((const GLubyte*)"glVertexStream2svATI")) == NULL) || r;
+ r = ((glVertexStream3dATI = (PFNGLVERTEXSTREAM3DATIPROC)glewGetProcAddress((const GLubyte*)"glVertexStream3dATI")) == NULL) || r;
+ r = ((glVertexStream3dvATI = (PFNGLVERTEXSTREAM3DVATIPROC)glewGetProcAddress((const GLubyte*)"glVertexStream3dvATI")) == NULL) || r;
+ r = ((glVertexStream3fATI = (PFNGLVERTEXSTREAM3FATIPROC)glewGetProcAddress((const GLubyte*)"glVertexStream3fATI")) == NULL) || r;
+ r = ((glVertexStream3fvATI = (PFNGLVERTEXSTREAM3FVATIPROC)glewGetProcAddress((const GLubyte*)"glVertexStream3fvATI")) == NULL) || r;
+ r = ((glVertexStream3iATI = (PFNGLVERTEXSTREAM3IATIPROC)glewGetProcAddress((const GLubyte*)"glVertexStream3iATI")) == NULL) || r;
+ r = ((glVertexStream3ivATI = (PFNGLVERTEXSTREAM3IVATIPROC)glewGetProcAddress((const GLubyte*)"glVertexStream3ivATI")) == NULL) || r;
+ r = ((glVertexStream3sATI = (PFNGLVERTEXSTREAM3SATIPROC)glewGetProcAddress((const GLubyte*)"glVertexStream3sATI")) == NULL) || r;
+ r = ((glVertexStream3svATI = (PFNGLVERTEXSTREAM3SVATIPROC)glewGetProcAddress((const GLubyte*)"glVertexStream3svATI")) == NULL) || r;
+ r = ((glVertexStream4dATI = (PFNGLVERTEXSTREAM4DATIPROC)glewGetProcAddress((const GLubyte*)"glVertexStream4dATI")) == NULL) || r;
+ r = ((glVertexStream4dvATI = (PFNGLVERTEXSTREAM4DVATIPROC)glewGetProcAddress((const GLubyte*)"glVertexStream4dvATI")) == NULL) || r;
+ r = ((glVertexStream4fATI = (PFNGLVERTEXSTREAM4FATIPROC)glewGetProcAddress((const GLubyte*)"glVertexStream4fATI")) == NULL) || r;
+ r = ((glVertexStream4fvATI = (PFNGLVERTEXSTREAM4FVATIPROC)glewGetProcAddress((const GLubyte*)"glVertexStream4fvATI")) == NULL) || r;
+ r = ((glVertexStream4iATI = (PFNGLVERTEXSTREAM4IATIPROC)glewGetProcAddress((const GLubyte*)"glVertexStream4iATI")) == NULL) || r;
+ r = ((glVertexStream4ivATI = (PFNGLVERTEXSTREAM4IVATIPROC)glewGetProcAddress((const GLubyte*)"glVertexStream4ivATI")) == NULL) || r;
+ r = ((glVertexStream4sATI = (PFNGLVERTEXSTREAM4SATIPROC)glewGetProcAddress((const GLubyte*)"glVertexStream4sATI")) == NULL) || r;
+ r = ((glVertexStream4svATI = (PFNGLVERTEXSTREAM4SVATIPROC)glewGetProcAddress((const GLubyte*)"glVertexStream4svATI")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_ATI_vertex_streams */
+
+#ifdef GL_EXT_422_pixels
+
+#endif /* GL_EXT_422_pixels */
+
+#ifdef GL_EXT_Cg_shader
+
+#endif /* GL_EXT_Cg_shader */
+
+#ifdef GL_EXT_abgr
+
+#endif /* GL_EXT_abgr */
+
+#ifdef GL_EXT_bgra
+
+#endif /* GL_EXT_bgra */
+
+#ifdef GL_EXT_bindable_uniform
+
+static GLboolean _glewInit_GL_EXT_bindable_uniform (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glGetUniformBufferSizeEXT = (PFNGLGETUNIFORMBUFFERSIZEEXTPROC)glewGetProcAddress((const GLubyte*)"glGetUniformBufferSizeEXT")) == NULL) || r;
+ r = ((glGetUniformOffsetEXT = (PFNGLGETUNIFORMOFFSETEXTPROC)glewGetProcAddress((const GLubyte*)"glGetUniformOffsetEXT")) == NULL) || r;
+ r = ((glUniformBufferEXT = (PFNGLUNIFORMBUFFEREXTPROC)glewGetProcAddress((const GLubyte*)"glUniformBufferEXT")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_EXT_bindable_uniform */
+
+#ifdef GL_EXT_blend_color
+
+static GLboolean _glewInit_GL_EXT_blend_color (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glBlendColorEXT = (PFNGLBLENDCOLOREXTPROC)glewGetProcAddress((const GLubyte*)"glBlendColorEXT")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_EXT_blend_color */
+
+#ifdef GL_EXT_blend_equation_separate
+
+static GLboolean _glewInit_GL_EXT_blend_equation_separate (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glBlendEquationSeparateEXT = (PFNGLBLENDEQUATIONSEPARATEEXTPROC)glewGetProcAddress((const GLubyte*)"glBlendEquationSeparateEXT")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_EXT_blend_equation_separate */
+
+#ifdef GL_EXT_blend_func_separate
+
+static GLboolean _glewInit_GL_EXT_blend_func_separate (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glBlendFuncSeparateEXT = (PFNGLBLENDFUNCSEPARATEEXTPROC)glewGetProcAddress((const GLubyte*)"glBlendFuncSeparateEXT")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_EXT_blend_func_separate */
+
+#ifdef GL_EXT_blend_logic_op
+
+#endif /* GL_EXT_blend_logic_op */
+
+#ifdef GL_EXT_blend_minmax
+
+static GLboolean _glewInit_GL_EXT_blend_minmax (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glBlendEquationEXT = (PFNGLBLENDEQUATIONEXTPROC)glewGetProcAddress((const GLubyte*)"glBlendEquationEXT")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_EXT_blend_minmax */
+
+#ifdef GL_EXT_blend_subtract
+
+#endif /* GL_EXT_blend_subtract */
+
+#ifdef GL_EXT_clip_volume_hint
+
+#endif /* GL_EXT_clip_volume_hint */
+
+#ifdef GL_EXT_cmyka
+
+#endif /* GL_EXT_cmyka */
+
+#ifdef GL_EXT_color_subtable
+
+static GLboolean _glewInit_GL_EXT_color_subtable (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glColorSubTableEXT = (PFNGLCOLORSUBTABLEEXTPROC)glewGetProcAddress((const GLubyte*)"glColorSubTableEXT")) == NULL) || r;
+ r = ((glCopyColorSubTableEXT = (PFNGLCOPYCOLORSUBTABLEEXTPROC)glewGetProcAddress((const GLubyte*)"glCopyColorSubTableEXT")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_EXT_color_subtable */
+
+#ifdef GL_EXT_compiled_vertex_array
+
+static GLboolean _glewInit_GL_EXT_compiled_vertex_array (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glLockArraysEXT = (PFNGLLOCKARRAYSEXTPROC)glewGetProcAddress((const GLubyte*)"glLockArraysEXT")) == NULL) || r;
+ r = ((glUnlockArraysEXT = (PFNGLUNLOCKARRAYSEXTPROC)glewGetProcAddress((const GLubyte*)"glUnlockArraysEXT")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_EXT_compiled_vertex_array */
+
+#ifdef GL_EXT_convolution
+
+static GLboolean _glewInit_GL_EXT_convolution (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glConvolutionFilter1DEXT = (PFNGLCONVOLUTIONFILTER1DEXTPROC)glewGetProcAddress((const GLubyte*)"glConvolutionFilter1DEXT")) == NULL) || r;
+ r = ((glConvolutionFilter2DEXT = (PFNGLCONVOLUTIONFILTER2DEXTPROC)glewGetProcAddress((const GLubyte*)"glConvolutionFilter2DEXT")) == NULL) || r;
+ r = ((glConvolutionParameterfEXT = (PFNGLCONVOLUTIONPARAMETERFEXTPROC)glewGetProcAddress((const GLubyte*)"glConvolutionParameterfEXT")) == NULL) || r;
+ r = ((glConvolutionParameterfvEXT = (PFNGLCONVOLUTIONPARAMETERFVEXTPROC)glewGetProcAddress((const GLubyte*)"glConvolutionParameterfvEXT")) == NULL) || r;
+ r = ((glConvolutionParameteriEXT = (PFNGLCONVOLUTIONPARAMETERIEXTPROC)glewGetProcAddress((const GLubyte*)"glConvolutionParameteriEXT")) == NULL) || r;
+ r = ((glConvolutionParameterivEXT = (PFNGLCONVOLUTIONPARAMETERIVEXTPROC)glewGetProcAddress((const GLubyte*)"glConvolutionParameterivEXT")) == NULL) || r;
+ r = ((glCopyConvolutionFilter1DEXT = (PFNGLCOPYCONVOLUTIONFILTER1DEXTPROC)glewGetProcAddress((const GLubyte*)"glCopyConvolutionFilter1DEXT")) == NULL) || r;
+ r = ((glCopyConvolutionFilter2DEXT = (PFNGLCOPYCONVOLUTIONFILTER2DEXTPROC)glewGetProcAddress((const GLubyte*)"glCopyConvolutionFilter2DEXT")) == NULL) || r;
+ r = ((glGetConvolutionFilterEXT = (PFNGLGETCONVOLUTIONFILTEREXTPROC)glewGetProcAddress((const GLubyte*)"glGetConvolutionFilterEXT")) == NULL) || r;
+ r = ((glGetConvolutionParameterfvEXT = (PFNGLGETCONVOLUTIONPARAMETERFVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetConvolutionParameterfvEXT")) == NULL) || r;
+ r = ((glGetConvolutionParameterivEXT = (PFNGLGETCONVOLUTIONPARAMETERIVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetConvolutionParameterivEXT")) == NULL) || r;
+ r = ((glGetSeparableFilterEXT = (PFNGLGETSEPARABLEFILTEREXTPROC)glewGetProcAddress((const GLubyte*)"glGetSeparableFilterEXT")) == NULL) || r;
+ r = ((glSeparableFilter2DEXT = (PFNGLSEPARABLEFILTER2DEXTPROC)glewGetProcAddress((const GLubyte*)"glSeparableFilter2DEXT")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_EXT_convolution */
+
+#ifdef GL_EXT_coordinate_frame
+
+static GLboolean _glewInit_GL_EXT_coordinate_frame (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glBinormalPointerEXT = (PFNGLBINORMALPOINTEREXTPROC)glewGetProcAddress((const GLubyte*)"glBinormalPointerEXT")) == NULL) || r;
+ r = ((glTangentPointerEXT = (PFNGLTANGENTPOINTEREXTPROC)glewGetProcAddress((const GLubyte*)"glTangentPointerEXT")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_EXT_coordinate_frame */
+
+#ifdef GL_EXT_copy_texture
+
+static GLboolean _glewInit_GL_EXT_copy_texture (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glCopyTexImage1DEXT = (PFNGLCOPYTEXIMAGE1DEXTPROC)glewGetProcAddress((const GLubyte*)"glCopyTexImage1DEXT")) == NULL) || r;
+ r = ((glCopyTexImage2DEXT = (PFNGLCOPYTEXIMAGE2DEXTPROC)glewGetProcAddress((const GLubyte*)"glCopyTexImage2DEXT")) == NULL) || r;
+ r = ((glCopyTexSubImage1DEXT = (PFNGLCOPYTEXSUBIMAGE1DEXTPROC)glewGetProcAddress((const GLubyte*)"glCopyTexSubImage1DEXT")) == NULL) || r;
+ r = ((glCopyTexSubImage2DEXT = (PFNGLCOPYTEXSUBIMAGE2DEXTPROC)glewGetProcAddress((const GLubyte*)"glCopyTexSubImage2DEXT")) == NULL) || r;
+ r = ((glCopyTexSubImage3DEXT = (PFNGLCOPYTEXSUBIMAGE3DEXTPROC)glewGetProcAddress((const GLubyte*)"glCopyTexSubImage3DEXT")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_EXT_copy_texture */
+
+#ifdef GL_EXT_cull_vertex
+
+static GLboolean _glewInit_GL_EXT_cull_vertex (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glCullParameterdvEXT = (PFNGLCULLPARAMETERDVEXTPROC)glewGetProcAddress((const GLubyte*)"glCullParameterdvEXT")) == NULL) || r;
+ r = ((glCullParameterfvEXT = (PFNGLCULLPARAMETERFVEXTPROC)glewGetProcAddress((const GLubyte*)"glCullParameterfvEXT")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_EXT_cull_vertex */
+
+#ifdef GL_EXT_depth_bounds_test
+
+static GLboolean _glewInit_GL_EXT_depth_bounds_test (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glDepthBoundsEXT = (PFNGLDEPTHBOUNDSEXTPROC)glewGetProcAddress((const GLubyte*)"glDepthBoundsEXT")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_EXT_depth_bounds_test */
+
+#ifdef GL_EXT_direct_state_access
+
+static GLboolean _glewInit_GL_EXT_direct_state_access (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glBindMultiTextureEXT = (PFNGLBINDMULTITEXTUREEXTPROC)glewGetProcAddress((const GLubyte*)"glBindMultiTextureEXT")) == NULL) || r;
+ r = ((glCheckNamedFramebufferStatusEXT = (PFNGLCHECKNAMEDFRAMEBUFFERSTATUSEXTPROC)glewGetProcAddress((const GLubyte*)"glCheckNamedFramebufferStatusEXT")) == NULL) || r;
+ r = ((glClientAttribDefaultEXT = (PFNGLCLIENTATTRIBDEFAULTEXTPROC)glewGetProcAddress((const GLubyte*)"glClientAttribDefaultEXT")) == NULL) || r;
+ r = ((glCompressedMultiTexImage1DEXT = (PFNGLCOMPRESSEDMULTITEXIMAGE1DEXTPROC)glewGetProcAddress((const GLubyte*)"glCompressedMultiTexImage1DEXT")) == NULL) || r;
+ r = ((glCompressedMultiTexImage2DEXT = (PFNGLCOMPRESSEDMULTITEXIMAGE2DEXTPROC)glewGetProcAddress((const GLubyte*)"glCompressedMultiTexImage2DEXT")) == NULL) || r;
+ r = ((glCompressedMultiTexImage3DEXT = (PFNGLCOMPRESSEDMULTITEXIMAGE3DEXTPROC)glewGetProcAddress((const GLubyte*)"glCompressedMultiTexImage3DEXT")) == NULL) || r;
+ r = ((glCompressedMultiTexSubImage1DEXT = (PFNGLCOMPRESSEDMULTITEXSUBIMAGE1DEXTPROC)glewGetProcAddress((const GLubyte*)"glCompressedMultiTexSubImage1DEXT")) == NULL) || r;
+ r = ((glCompressedMultiTexSubImage2DEXT = (PFNGLCOMPRESSEDMULTITEXSUBIMAGE2DEXTPROC)glewGetProcAddress((const GLubyte*)"glCompressedMultiTexSubImage2DEXT")) == NULL) || r;
+ r = ((glCompressedMultiTexSubImage3DEXT = (PFNGLCOMPRESSEDMULTITEXSUBIMAGE3DEXTPROC)glewGetProcAddress((const GLubyte*)"glCompressedMultiTexSubImage3DEXT")) == NULL) || r;
+ r = ((glCompressedTextureImage1DEXT = (PFNGLCOMPRESSEDTEXTUREIMAGE1DEXTPROC)glewGetProcAddress((const GLubyte*)"glCompressedTextureImage1DEXT")) == NULL) || r;
+ r = ((glCompressedTextureImage2DEXT = (PFNGLCOMPRESSEDTEXTUREIMAGE2DEXTPROC)glewGetProcAddress((const GLubyte*)"glCompressedTextureImage2DEXT")) == NULL) || r;
+ r = ((glCompressedTextureImage3DEXT = (PFNGLCOMPRESSEDTEXTUREIMAGE3DEXTPROC)glewGetProcAddress((const GLubyte*)"glCompressedTextureImage3DEXT")) == NULL) || r;
+ r = ((glCompressedTextureSubImage1DEXT = (PFNGLCOMPRESSEDTEXTURESUBIMAGE1DEXTPROC)glewGetProcAddress((const GLubyte*)"glCompressedTextureSubImage1DEXT")) == NULL) || r;
+ r = ((glCompressedTextureSubImage2DEXT = (PFNGLCOMPRESSEDTEXTURESUBIMAGE2DEXTPROC)glewGetProcAddress((const GLubyte*)"glCompressedTextureSubImage2DEXT")) == NULL) || r;
+ r = ((glCompressedTextureSubImage3DEXT = (PFNGLCOMPRESSEDTEXTURESUBIMAGE3DEXTPROC)glewGetProcAddress((const GLubyte*)"glCompressedTextureSubImage3DEXT")) == NULL) || r;
+ r = ((glCopyMultiTexImage1DEXT = (PFNGLCOPYMULTITEXIMAGE1DEXTPROC)glewGetProcAddress((const GLubyte*)"glCopyMultiTexImage1DEXT")) == NULL) || r;
+ r = ((glCopyMultiTexImage2DEXT = (PFNGLCOPYMULTITEXIMAGE2DEXTPROC)glewGetProcAddress((const GLubyte*)"glCopyMultiTexImage2DEXT")) == NULL) || r;
+ r = ((glCopyMultiTexSubImage1DEXT = (PFNGLCOPYMULTITEXSUBIMAGE1DEXTPROC)glewGetProcAddress((const GLubyte*)"glCopyMultiTexSubImage1DEXT")) == NULL) || r;
+ r = ((glCopyMultiTexSubImage2DEXT = (PFNGLCOPYMULTITEXSUBIMAGE2DEXTPROC)glewGetProcAddress((const GLubyte*)"glCopyMultiTexSubImage2DEXT")) == NULL) || r;
+ r = ((glCopyMultiTexSubImage3DEXT = (PFNGLCOPYMULTITEXSUBIMAGE3DEXTPROC)glewGetProcAddress((const GLubyte*)"glCopyMultiTexSubImage3DEXT")) == NULL) || r;
+ r = ((glCopyTextureImage1DEXT = (PFNGLCOPYTEXTUREIMAGE1DEXTPROC)glewGetProcAddress((const GLubyte*)"glCopyTextureImage1DEXT")) == NULL) || r;
+ r = ((glCopyTextureImage2DEXT = (PFNGLCOPYTEXTUREIMAGE2DEXTPROC)glewGetProcAddress((const GLubyte*)"glCopyTextureImage2DEXT")) == NULL) || r;
+ r = ((glCopyTextureSubImage1DEXT = (PFNGLCOPYTEXTURESUBIMAGE1DEXTPROC)glewGetProcAddress((const GLubyte*)"glCopyTextureSubImage1DEXT")) == NULL) || r;
+ r = ((glCopyTextureSubImage2DEXT = (PFNGLCOPYTEXTURESUBIMAGE2DEXTPROC)glewGetProcAddress((const GLubyte*)"glCopyTextureSubImage2DEXT")) == NULL) || r;
+ r = ((glCopyTextureSubImage3DEXT = (PFNGLCOPYTEXTURESUBIMAGE3DEXTPROC)glewGetProcAddress((const GLubyte*)"glCopyTextureSubImage3DEXT")) == NULL) || r;
+ r = ((glDisableClientStateIndexedEXT = (PFNGLDISABLECLIENTSTATEINDEXEDEXTPROC)glewGetProcAddress((const GLubyte*)"glDisableClientStateIndexedEXT")) == NULL) || r;
+ r = ((glDisableClientStateiEXT = (PFNGLDISABLECLIENTSTATEIEXTPROC)glewGetProcAddress((const GLubyte*)"glDisableClientStateiEXT")) == NULL) || r;
+ r = ((glDisableVertexArrayAttribEXT = (PFNGLDISABLEVERTEXARRAYATTRIBEXTPROC)glewGetProcAddress((const GLubyte*)"glDisableVertexArrayAttribEXT")) == NULL) || r;
+ r = ((glDisableVertexArrayEXT = (PFNGLDISABLEVERTEXARRAYEXTPROC)glewGetProcAddress((const GLubyte*)"glDisableVertexArrayEXT")) == NULL) || r;
+ r = ((glEnableClientStateIndexedEXT = (PFNGLENABLECLIENTSTATEINDEXEDEXTPROC)glewGetProcAddress((const GLubyte*)"glEnableClientStateIndexedEXT")) == NULL) || r;
+ r = ((glEnableClientStateiEXT = (PFNGLENABLECLIENTSTATEIEXTPROC)glewGetProcAddress((const GLubyte*)"glEnableClientStateiEXT")) == NULL) || r;
+ r = ((glEnableVertexArrayAttribEXT = (PFNGLENABLEVERTEXARRAYATTRIBEXTPROC)glewGetProcAddress((const GLubyte*)"glEnableVertexArrayAttribEXT")) == NULL) || r;
+ r = ((glEnableVertexArrayEXT = (PFNGLENABLEVERTEXARRAYEXTPROC)glewGetProcAddress((const GLubyte*)"glEnableVertexArrayEXT")) == NULL) || r;
+ r = ((glFlushMappedNamedBufferRangeEXT = (PFNGLFLUSHMAPPEDNAMEDBUFFERRANGEEXTPROC)glewGetProcAddress((const GLubyte*)"glFlushMappedNamedBufferRangeEXT")) == NULL) || r;
+ r = ((glFramebufferDrawBufferEXT = (PFNGLFRAMEBUFFERDRAWBUFFEREXTPROC)glewGetProcAddress((const GLubyte*)"glFramebufferDrawBufferEXT")) == NULL) || r;
+ r = ((glFramebufferDrawBuffersEXT = (PFNGLFRAMEBUFFERDRAWBUFFERSEXTPROC)glewGetProcAddress((const GLubyte*)"glFramebufferDrawBuffersEXT")) == NULL) || r;
+ r = ((glFramebufferReadBufferEXT = (PFNGLFRAMEBUFFERREADBUFFEREXTPROC)glewGetProcAddress((const GLubyte*)"glFramebufferReadBufferEXT")) == NULL) || r;
+ r = ((glGenerateMultiTexMipmapEXT = (PFNGLGENERATEMULTITEXMIPMAPEXTPROC)glewGetProcAddress((const GLubyte*)"glGenerateMultiTexMipmapEXT")) == NULL) || r;
+ r = ((glGenerateTextureMipmapEXT = (PFNGLGENERATETEXTUREMIPMAPEXTPROC)glewGetProcAddress((const GLubyte*)"glGenerateTextureMipmapEXT")) == NULL) || r;
+ r = ((glGetCompressedMultiTexImageEXT = (PFNGLGETCOMPRESSEDMULTITEXIMAGEEXTPROC)glewGetProcAddress((const GLubyte*)"glGetCompressedMultiTexImageEXT")) == NULL) || r;
+ r = ((glGetCompressedTextureImageEXT = (PFNGLGETCOMPRESSEDTEXTUREIMAGEEXTPROC)glewGetProcAddress((const GLubyte*)"glGetCompressedTextureImageEXT")) == NULL) || r;
+ r = ((glGetDoubleIndexedvEXT = (PFNGLGETDOUBLEINDEXEDVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetDoubleIndexedvEXT")) == NULL) || r;
+ r = ((glGetDoublei_vEXT = (PFNGLGETDOUBLEI_VEXTPROC)glewGetProcAddress((const GLubyte*)"glGetDoublei_vEXT")) == NULL) || r;
+ r = ((glGetFloatIndexedvEXT = (PFNGLGETFLOATINDEXEDVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetFloatIndexedvEXT")) == NULL) || r;
+ r = ((glGetFloati_vEXT = (PFNGLGETFLOATI_VEXTPROC)glewGetProcAddress((const GLubyte*)"glGetFloati_vEXT")) == NULL) || r;
+ r = ((glGetFramebufferParameterivEXT = (PFNGLGETFRAMEBUFFERPARAMETERIVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetFramebufferParameterivEXT")) == NULL) || r;
+ r = ((glGetMultiTexEnvfvEXT = (PFNGLGETMULTITEXENVFVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetMultiTexEnvfvEXT")) == NULL) || r;
+ r = ((glGetMultiTexEnvivEXT = (PFNGLGETMULTITEXENVIVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetMultiTexEnvivEXT")) == NULL) || r;
+ r = ((glGetMultiTexGendvEXT = (PFNGLGETMULTITEXGENDVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetMultiTexGendvEXT")) == NULL) || r;
+ r = ((glGetMultiTexGenfvEXT = (PFNGLGETMULTITEXGENFVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetMultiTexGenfvEXT")) == NULL) || r;
+ r = ((glGetMultiTexGenivEXT = (PFNGLGETMULTITEXGENIVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetMultiTexGenivEXT")) == NULL) || r;
+ r = ((glGetMultiTexImageEXT = (PFNGLGETMULTITEXIMAGEEXTPROC)glewGetProcAddress((const GLubyte*)"glGetMultiTexImageEXT")) == NULL) || r;
+ r = ((glGetMultiTexLevelParameterfvEXT = (PFNGLGETMULTITEXLEVELPARAMETERFVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetMultiTexLevelParameterfvEXT")) == NULL) || r;
+ r = ((glGetMultiTexLevelParameterivEXT = (PFNGLGETMULTITEXLEVELPARAMETERIVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetMultiTexLevelParameterivEXT")) == NULL) || r;
+ r = ((glGetMultiTexParameterIivEXT = (PFNGLGETMULTITEXPARAMETERIIVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetMultiTexParameterIivEXT")) == NULL) || r;
+ r = ((glGetMultiTexParameterIuivEXT = (PFNGLGETMULTITEXPARAMETERIUIVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetMultiTexParameterIuivEXT")) == NULL) || r;
+ r = ((glGetMultiTexParameterfvEXT = (PFNGLGETMULTITEXPARAMETERFVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetMultiTexParameterfvEXT")) == NULL) || r;
+ r = ((glGetMultiTexParameterivEXT = (PFNGLGETMULTITEXPARAMETERIVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetMultiTexParameterivEXT")) == NULL) || r;
+ r = ((glGetNamedBufferParameterivEXT = (PFNGLGETNAMEDBUFFERPARAMETERIVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetNamedBufferParameterivEXT")) == NULL) || r;
+ r = ((glGetNamedBufferPointervEXT = (PFNGLGETNAMEDBUFFERPOINTERVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetNamedBufferPointervEXT")) == NULL) || r;
+ r = ((glGetNamedBufferSubDataEXT = (PFNGLGETNAMEDBUFFERSUBDATAEXTPROC)glewGetProcAddress((const GLubyte*)"glGetNamedBufferSubDataEXT")) == NULL) || r;
+ r = ((glGetNamedFramebufferAttachmentParameterivEXT = (PFNGLGETNAMEDFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetNamedFramebufferAttachmentParameterivEXT")) == NULL) || r;
+ r = ((glGetNamedProgramLocalParameterIivEXT = (PFNGLGETNAMEDPROGRAMLOCALPARAMETERIIVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetNamedProgramLocalParameterIivEXT")) == NULL) || r;
+ r = ((glGetNamedProgramLocalParameterIuivEXT = (PFNGLGETNAMEDPROGRAMLOCALPARAMETERIUIVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetNamedProgramLocalParameterIuivEXT")) == NULL) || r;
+ r = ((glGetNamedProgramLocalParameterdvEXT = (PFNGLGETNAMEDPROGRAMLOCALPARAMETERDVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetNamedProgramLocalParameterdvEXT")) == NULL) || r;
+ r = ((glGetNamedProgramLocalParameterfvEXT = (PFNGLGETNAMEDPROGRAMLOCALPARAMETERFVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetNamedProgramLocalParameterfvEXT")) == NULL) || r;
+ r = ((glGetNamedProgramStringEXT = (PFNGLGETNAMEDPROGRAMSTRINGEXTPROC)glewGetProcAddress((const GLubyte*)"glGetNamedProgramStringEXT")) == NULL) || r;
+ r = ((glGetNamedProgramivEXT = (PFNGLGETNAMEDPROGRAMIVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetNamedProgramivEXT")) == NULL) || r;
+ r = ((glGetNamedRenderbufferParameterivEXT = (PFNGLGETNAMEDRENDERBUFFERPARAMETERIVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetNamedRenderbufferParameterivEXT")) == NULL) || r;
+ r = ((glGetPointerIndexedvEXT = (PFNGLGETPOINTERINDEXEDVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetPointerIndexedvEXT")) == NULL) || r;
+ r = ((glGetPointeri_vEXT = (PFNGLGETPOINTERI_VEXTPROC)glewGetProcAddress((const GLubyte*)"glGetPointeri_vEXT")) == NULL) || r;
+ r = ((glGetTextureImageEXT = (PFNGLGETTEXTUREIMAGEEXTPROC)glewGetProcAddress((const GLubyte*)"glGetTextureImageEXT")) == NULL) || r;
+ r = ((glGetTextureLevelParameterfvEXT = (PFNGLGETTEXTURELEVELPARAMETERFVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetTextureLevelParameterfvEXT")) == NULL) || r;
+ r = ((glGetTextureLevelParameterivEXT = (PFNGLGETTEXTURELEVELPARAMETERIVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetTextureLevelParameterivEXT")) == NULL) || r;
+ r = ((glGetTextureParameterIivEXT = (PFNGLGETTEXTUREPARAMETERIIVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetTextureParameterIivEXT")) == NULL) || r;
+ r = ((glGetTextureParameterIuivEXT = (PFNGLGETTEXTUREPARAMETERIUIVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetTextureParameterIuivEXT")) == NULL) || r;
+ r = ((glGetTextureParameterfvEXT = (PFNGLGETTEXTUREPARAMETERFVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetTextureParameterfvEXT")) == NULL) || r;
+ r = ((glGetTextureParameterivEXT = (PFNGLGETTEXTUREPARAMETERIVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetTextureParameterivEXT")) == NULL) || r;
+ r = ((glGetVertexArrayIntegeri_vEXT = (PFNGLGETVERTEXARRAYINTEGERI_VEXTPROC)glewGetProcAddress((const GLubyte*)"glGetVertexArrayIntegeri_vEXT")) == NULL) || r;
+ r = ((glGetVertexArrayIntegervEXT = (PFNGLGETVERTEXARRAYINTEGERVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetVertexArrayIntegervEXT")) == NULL) || r;
+ r = ((glGetVertexArrayPointeri_vEXT = (PFNGLGETVERTEXARRAYPOINTERI_VEXTPROC)glewGetProcAddress((const GLubyte*)"glGetVertexArrayPointeri_vEXT")) == NULL) || r;
+ r = ((glGetVertexArrayPointervEXT = (PFNGLGETVERTEXARRAYPOINTERVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetVertexArrayPointervEXT")) == NULL) || r;
+ r = ((glMapNamedBufferEXT = (PFNGLMAPNAMEDBUFFEREXTPROC)glewGetProcAddress((const GLubyte*)"glMapNamedBufferEXT")) == NULL) || r;
+ r = ((glMapNamedBufferRangeEXT = (PFNGLMAPNAMEDBUFFERRANGEEXTPROC)glewGetProcAddress((const GLubyte*)"glMapNamedBufferRangeEXT")) == NULL) || r;
+ r = ((glMatrixFrustumEXT = (PFNGLMATRIXFRUSTUMEXTPROC)glewGetProcAddress((const GLubyte*)"glMatrixFrustumEXT")) == NULL) || r;
+ r = ((glMatrixLoadIdentityEXT = (PFNGLMATRIXLOADIDENTITYEXTPROC)glewGetProcAddress((const GLubyte*)"glMatrixLoadIdentityEXT")) == NULL) || r;
+ r = ((glMatrixLoadTransposedEXT = (PFNGLMATRIXLOADTRANSPOSEDEXTPROC)glewGetProcAddress((const GLubyte*)"glMatrixLoadTransposedEXT")) == NULL) || r;
+ r = ((glMatrixLoadTransposefEXT = (PFNGLMATRIXLOADTRANSPOSEFEXTPROC)glewGetProcAddress((const GLubyte*)"glMatrixLoadTransposefEXT")) == NULL) || r;
+ r = ((glMatrixLoaddEXT = (PFNGLMATRIXLOADDEXTPROC)glewGetProcAddress((const GLubyte*)"glMatrixLoaddEXT")) == NULL) || r;
+ r = ((glMatrixLoadfEXT = (PFNGLMATRIXLOADFEXTPROC)glewGetProcAddress((const GLubyte*)"glMatrixLoadfEXT")) == NULL) || r;
+ r = ((glMatrixMultTransposedEXT = (PFNGLMATRIXMULTTRANSPOSEDEXTPROC)glewGetProcAddress((const GLubyte*)"glMatrixMultTransposedEXT")) == NULL) || r;
+ r = ((glMatrixMultTransposefEXT = (PFNGLMATRIXMULTTRANSPOSEFEXTPROC)glewGetProcAddress((const GLubyte*)"glMatrixMultTransposefEXT")) == NULL) || r;
+ r = ((glMatrixMultdEXT = (PFNGLMATRIXMULTDEXTPROC)glewGetProcAddress((const GLubyte*)"glMatrixMultdEXT")) == NULL) || r;
+ r = ((glMatrixMultfEXT = (PFNGLMATRIXMULTFEXTPROC)glewGetProcAddress((const GLubyte*)"glMatrixMultfEXT")) == NULL) || r;
+ r = ((glMatrixOrthoEXT = (PFNGLMATRIXORTHOEXTPROC)glewGetProcAddress((const GLubyte*)"glMatrixOrthoEXT")) == NULL) || r;
+ r = ((glMatrixPopEXT = (PFNGLMATRIXPOPEXTPROC)glewGetProcAddress((const GLubyte*)"glMatrixPopEXT")) == NULL) || r;
+ r = ((glMatrixPushEXT = (PFNGLMATRIXPUSHEXTPROC)glewGetProcAddress((const GLubyte*)"glMatrixPushEXT")) == NULL) || r;
+ r = ((glMatrixRotatedEXT = (PFNGLMATRIXROTATEDEXTPROC)glewGetProcAddress((const GLubyte*)"glMatrixRotatedEXT")) == NULL) || r;
+ r = ((glMatrixRotatefEXT = (PFNGLMATRIXROTATEFEXTPROC)glewGetProcAddress((const GLubyte*)"glMatrixRotatefEXT")) == NULL) || r;
+ r = ((glMatrixScaledEXT = (PFNGLMATRIXSCALEDEXTPROC)glewGetProcAddress((const GLubyte*)"glMatrixScaledEXT")) == NULL) || r;
+ r = ((glMatrixScalefEXT = (PFNGLMATRIXSCALEFEXTPROC)glewGetProcAddress((const GLubyte*)"glMatrixScalefEXT")) == NULL) || r;
+ r = ((glMatrixTranslatedEXT = (PFNGLMATRIXTRANSLATEDEXTPROC)glewGetProcAddress((const GLubyte*)"glMatrixTranslatedEXT")) == NULL) || r;
+ r = ((glMatrixTranslatefEXT = (PFNGLMATRIXTRANSLATEFEXTPROC)glewGetProcAddress((const GLubyte*)"glMatrixTranslatefEXT")) == NULL) || r;
+ r = ((glMultiTexBufferEXT = (PFNGLMULTITEXBUFFEREXTPROC)glewGetProcAddress((const GLubyte*)"glMultiTexBufferEXT")) == NULL) || r;
+ r = ((glMultiTexCoordPointerEXT = (PFNGLMULTITEXCOORDPOINTEREXTPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoordPointerEXT")) == NULL) || r;
+ r = ((glMultiTexEnvfEXT = (PFNGLMULTITEXENVFEXTPROC)glewGetProcAddress((const GLubyte*)"glMultiTexEnvfEXT")) == NULL) || r;
+ r = ((glMultiTexEnvfvEXT = (PFNGLMULTITEXENVFVEXTPROC)glewGetProcAddress((const GLubyte*)"glMultiTexEnvfvEXT")) == NULL) || r;
+ r = ((glMultiTexEnviEXT = (PFNGLMULTITEXENVIEXTPROC)glewGetProcAddress((const GLubyte*)"glMultiTexEnviEXT")) == NULL) || r;
+ r = ((glMultiTexEnvivEXT = (PFNGLMULTITEXENVIVEXTPROC)glewGetProcAddress((const GLubyte*)"glMultiTexEnvivEXT")) == NULL) || r;
+ r = ((glMultiTexGendEXT = (PFNGLMULTITEXGENDEXTPROC)glewGetProcAddress((const GLubyte*)"glMultiTexGendEXT")) == NULL) || r;
+ r = ((glMultiTexGendvEXT = (PFNGLMULTITEXGENDVEXTPROC)glewGetProcAddress((const GLubyte*)"glMultiTexGendvEXT")) == NULL) || r;
+ r = ((glMultiTexGenfEXT = (PFNGLMULTITEXGENFEXTPROC)glewGetProcAddress((const GLubyte*)"glMultiTexGenfEXT")) == NULL) || r;
+ r = ((glMultiTexGenfvEXT = (PFNGLMULTITEXGENFVEXTPROC)glewGetProcAddress((const GLubyte*)"glMultiTexGenfvEXT")) == NULL) || r;
+ r = ((glMultiTexGeniEXT = (PFNGLMULTITEXGENIEXTPROC)glewGetProcAddress((const GLubyte*)"glMultiTexGeniEXT")) == NULL) || r;
+ r = ((glMultiTexGenivEXT = (PFNGLMULTITEXGENIVEXTPROC)glewGetProcAddress((const GLubyte*)"glMultiTexGenivEXT")) == NULL) || r;
+ r = ((glMultiTexImage1DEXT = (PFNGLMULTITEXIMAGE1DEXTPROC)glewGetProcAddress((const GLubyte*)"glMultiTexImage1DEXT")) == NULL) || r;
+ r = ((glMultiTexImage2DEXT = (PFNGLMULTITEXIMAGE2DEXTPROC)glewGetProcAddress((const GLubyte*)"glMultiTexImage2DEXT")) == NULL) || r;
+ r = ((glMultiTexImage3DEXT = (PFNGLMULTITEXIMAGE3DEXTPROC)glewGetProcAddress((const GLubyte*)"glMultiTexImage3DEXT")) == NULL) || r;
+ r = ((glMultiTexParameterIivEXT = (PFNGLMULTITEXPARAMETERIIVEXTPROC)glewGetProcAddress((const GLubyte*)"glMultiTexParameterIivEXT")) == NULL) || r;
+ r = ((glMultiTexParameterIuivEXT = (PFNGLMULTITEXPARAMETERIUIVEXTPROC)glewGetProcAddress((const GLubyte*)"glMultiTexParameterIuivEXT")) == NULL) || r;
+ r = ((glMultiTexParameterfEXT = (PFNGLMULTITEXPARAMETERFEXTPROC)glewGetProcAddress((const GLubyte*)"glMultiTexParameterfEXT")) == NULL) || r;
+ r = ((glMultiTexParameterfvEXT = (PFNGLMULTITEXPARAMETERFVEXTPROC)glewGetProcAddress((const GLubyte*)"glMultiTexParameterfvEXT")) == NULL) || r;
+ r = ((glMultiTexParameteriEXT = (PFNGLMULTITEXPARAMETERIEXTPROC)glewGetProcAddress((const GLubyte*)"glMultiTexParameteriEXT")) == NULL) || r;
+ r = ((glMultiTexParameterivEXT = (PFNGLMULTITEXPARAMETERIVEXTPROC)glewGetProcAddress((const GLubyte*)"glMultiTexParameterivEXT")) == NULL) || r;
+ r = ((glMultiTexRenderbufferEXT = (PFNGLMULTITEXRENDERBUFFEREXTPROC)glewGetProcAddress((const GLubyte*)"glMultiTexRenderbufferEXT")) == NULL) || r;
+ r = ((glMultiTexSubImage1DEXT = (PFNGLMULTITEXSUBIMAGE1DEXTPROC)glewGetProcAddress((const GLubyte*)"glMultiTexSubImage1DEXT")) == NULL) || r;
+ r = ((glMultiTexSubImage2DEXT = (PFNGLMULTITEXSUBIMAGE2DEXTPROC)glewGetProcAddress((const GLubyte*)"glMultiTexSubImage2DEXT")) == NULL) || r;
+ r = ((glMultiTexSubImage3DEXT = (PFNGLMULTITEXSUBIMAGE3DEXTPROC)glewGetProcAddress((const GLubyte*)"glMultiTexSubImage3DEXT")) == NULL) || r;
+ r = ((glNamedBufferDataEXT = (PFNGLNAMEDBUFFERDATAEXTPROC)glewGetProcAddress((const GLubyte*)"glNamedBufferDataEXT")) == NULL) || r;
+ r = ((glNamedBufferSubDataEXT = (PFNGLNAMEDBUFFERSUBDATAEXTPROC)glewGetProcAddress((const GLubyte*)"glNamedBufferSubDataEXT")) == NULL) || r;
+ r = ((glNamedCopyBufferSubDataEXT = (PFNGLNAMEDCOPYBUFFERSUBDATAEXTPROC)glewGetProcAddress((const GLubyte*)"glNamedCopyBufferSubDataEXT")) == NULL) || r;
+ r = ((glNamedFramebufferRenderbufferEXT = (PFNGLNAMEDFRAMEBUFFERRENDERBUFFEREXTPROC)glewGetProcAddress((const GLubyte*)"glNamedFramebufferRenderbufferEXT")) == NULL) || r;
+ r = ((glNamedFramebufferTexture1DEXT = (PFNGLNAMEDFRAMEBUFFERTEXTURE1DEXTPROC)glewGetProcAddress((const GLubyte*)"glNamedFramebufferTexture1DEXT")) == NULL) || r;
+ r = ((glNamedFramebufferTexture2DEXT = (PFNGLNAMEDFRAMEBUFFERTEXTURE2DEXTPROC)glewGetProcAddress((const GLubyte*)"glNamedFramebufferTexture2DEXT")) == NULL) || r;
+ r = ((glNamedFramebufferTexture3DEXT = (PFNGLNAMEDFRAMEBUFFERTEXTURE3DEXTPROC)glewGetProcAddress((const GLubyte*)"glNamedFramebufferTexture3DEXT")) == NULL) || r;
+ r = ((glNamedFramebufferTextureEXT = (PFNGLNAMEDFRAMEBUFFERTEXTUREEXTPROC)glewGetProcAddress((const GLubyte*)"glNamedFramebufferTextureEXT")) == NULL) || r;
+ r = ((glNamedFramebufferTextureFaceEXT = (PFNGLNAMEDFRAMEBUFFERTEXTUREFACEEXTPROC)glewGetProcAddress((const GLubyte*)"glNamedFramebufferTextureFaceEXT")) == NULL) || r;
+ r = ((glNamedFramebufferTextureLayerEXT = (PFNGLNAMEDFRAMEBUFFERTEXTURELAYEREXTPROC)glewGetProcAddress((const GLubyte*)"glNamedFramebufferTextureLayerEXT")) == NULL) || r;
+ r = ((glNamedProgramLocalParameter4dEXT = (PFNGLNAMEDPROGRAMLOCALPARAMETER4DEXTPROC)glewGetProcAddress((const GLubyte*)"glNamedProgramLocalParameter4dEXT")) == NULL) || r;
+ r = ((glNamedProgramLocalParameter4dvEXT = (PFNGLNAMEDPROGRAMLOCALPARAMETER4DVEXTPROC)glewGetProcAddress((const GLubyte*)"glNamedProgramLocalParameter4dvEXT")) == NULL) || r;
+ r = ((glNamedProgramLocalParameter4fEXT = (PFNGLNAMEDPROGRAMLOCALPARAMETER4FEXTPROC)glewGetProcAddress((const GLubyte*)"glNamedProgramLocalParameter4fEXT")) == NULL) || r;
+ r = ((glNamedProgramLocalParameter4fvEXT = (PFNGLNAMEDPROGRAMLOCALPARAMETER4FVEXTPROC)glewGetProcAddress((const GLubyte*)"glNamedProgramLocalParameter4fvEXT")) == NULL) || r;
+ r = ((glNamedProgramLocalParameterI4iEXT = (PFNGLNAMEDPROGRAMLOCALPARAMETERI4IEXTPROC)glewGetProcAddress((const GLubyte*)"glNamedProgramLocalParameterI4iEXT")) == NULL) || r;
+ r = ((glNamedProgramLocalParameterI4ivEXT = (PFNGLNAMEDPROGRAMLOCALPARAMETERI4IVEXTPROC)glewGetProcAddress((const GLubyte*)"glNamedProgramLocalParameterI4ivEXT")) == NULL) || r;
+ r = ((glNamedProgramLocalParameterI4uiEXT = (PFNGLNAMEDPROGRAMLOCALPARAMETERI4UIEXTPROC)glewGetProcAddress((const GLubyte*)"glNamedProgramLocalParameterI4uiEXT")) == NULL) || r;
+ r = ((glNamedProgramLocalParameterI4uivEXT = (PFNGLNAMEDPROGRAMLOCALPARAMETERI4UIVEXTPROC)glewGetProcAddress((const GLubyte*)"glNamedProgramLocalParameterI4uivEXT")) == NULL) || r;
+ r = ((glNamedProgramLocalParameters4fvEXT = (PFNGLNAMEDPROGRAMLOCALPARAMETERS4FVEXTPROC)glewGetProcAddress((const GLubyte*)"glNamedProgramLocalParameters4fvEXT")) == NULL) || r;
+ r = ((glNamedProgramLocalParametersI4ivEXT = (PFNGLNAMEDPROGRAMLOCALPARAMETERSI4IVEXTPROC)glewGetProcAddress((const GLubyte*)"glNamedProgramLocalParametersI4ivEXT")) == NULL) || r;
+ r = ((glNamedProgramLocalParametersI4uivEXT = (PFNGLNAMEDPROGRAMLOCALPARAMETERSI4UIVEXTPROC)glewGetProcAddress((const GLubyte*)"glNamedProgramLocalParametersI4uivEXT")) == NULL) || r;
+ r = ((glNamedProgramStringEXT = (PFNGLNAMEDPROGRAMSTRINGEXTPROC)glewGetProcAddress((const GLubyte*)"glNamedProgramStringEXT")) == NULL) || r;
+ r = ((glNamedRenderbufferStorageEXT = (PFNGLNAMEDRENDERBUFFERSTORAGEEXTPROC)glewGetProcAddress((const GLubyte*)"glNamedRenderbufferStorageEXT")) == NULL) || r;
+ r = ((glNamedRenderbufferStorageMultisampleCoverageEXT = (PFNGLNAMEDRENDERBUFFERSTORAGEMULTISAMPLECOVERAGEEXTPROC)glewGetProcAddress((const GLubyte*)"glNamedRenderbufferStorageMultisampleCoverageEXT")) == NULL) || r;
+ r = ((glNamedRenderbufferStorageMultisampleEXT = (PFNGLNAMEDRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC)glewGetProcAddress((const GLubyte*)"glNamedRenderbufferStorageMultisampleEXT")) == NULL) || r;
+ r = ((glProgramUniform1fEXT = (PFNGLPROGRAMUNIFORM1FEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform1fEXT")) == NULL) || r;
+ r = ((glProgramUniform1fvEXT = (PFNGLPROGRAMUNIFORM1FVEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform1fvEXT")) == NULL) || r;
+ r = ((glProgramUniform1iEXT = (PFNGLPROGRAMUNIFORM1IEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform1iEXT")) == NULL) || r;
+ r = ((glProgramUniform1ivEXT = (PFNGLPROGRAMUNIFORM1IVEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform1ivEXT")) == NULL) || r;
+ r = ((glProgramUniform1uiEXT = (PFNGLPROGRAMUNIFORM1UIEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform1uiEXT")) == NULL) || r;
+ r = ((glProgramUniform1uivEXT = (PFNGLPROGRAMUNIFORM1UIVEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform1uivEXT")) == NULL) || r;
+ r = ((glProgramUniform2fEXT = (PFNGLPROGRAMUNIFORM2FEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform2fEXT")) == NULL) || r;
+ r = ((glProgramUniform2fvEXT = (PFNGLPROGRAMUNIFORM2FVEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform2fvEXT")) == NULL) || r;
+ r = ((glProgramUniform2iEXT = (PFNGLPROGRAMUNIFORM2IEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform2iEXT")) == NULL) || r;
+ r = ((glProgramUniform2ivEXT = (PFNGLPROGRAMUNIFORM2IVEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform2ivEXT")) == NULL) || r;
+ r = ((glProgramUniform2uiEXT = (PFNGLPROGRAMUNIFORM2UIEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform2uiEXT")) == NULL) || r;
+ r = ((glProgramUniform2uivEXT = (PFNGLPROGRAMUNIFORM2UIVEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform2uivEXT")) == NULL) || r;
+ r = ((glProgramUniform3fEXT = (PFNGLPROGRAMUNIFORM3FEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform3fEXT")) == NULL) || r;
+ r = ((glProgramUniform3fvEXT = (PFNGLPROGRAMUNIFORM3FVEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform3fvEXT")) == NULL) || r;
+ r = ((glProgramUniform3iEXT = (PFNGLPROGRAMUNIFORM3IEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform3iEXT")) == NULL) || r;
+ r = ((glProgramUniform3ivEXT = (PFNGLPROGRAMUNIFORM3IVEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform3ivEXT")) == NULL) || r;
+ r = ((glProgramUniform3uiEXT = (PFNGLPROGRAMUNIFORM3UIEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform3uiEXT")) == NULL) || r;
+ r = ((glProgramUniform3uivEXT = (PFNGLPROGRAMUNIFORM3UIVEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform3uivEXT")) == NULL) || r;
+ r = ((glProgramUniform4fEXT = (PFNGLPROGRAMUNIFORM4FEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform4fEXT")) == NULL) || r;
+ r = ((glProgramUniform4fvEXT = (PFNGLPROGRAMUNIFORM4FVEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform4fvEXT")) == NULL) || r;
+ r = ((glProgramUniform4iEXT = (PFNGLPROGRAMUNIFORM4IEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform4iEXT")) == NULL) || r;
+ r = ((glProgramUniform4ivEXT = (PFNGLPROGRAMUNIFORM4IVEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform4ivEXT")) == NULL) || r;
+ r = ((glProgramUniform4uiEXT = (PFNGLPROGRAMUNIFORM4UIEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform4uiEXT")) == NULL) || r;
+ r = ((glProgramUniform4uivEXT = (PFNGLPROGRAMUNIFORM4UIVEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform4uivEXT")) == NULL) || r;
+ r = ((glProgramUniformMatrix2fvEXT = (PFNGLPROGRAMUNIFORMMATRIX2FVEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramUniformMatrix2fvEXT")) == NULL) || r;
+ r = ((glProgramUniformMatrix2x3fvEXT = (PFNGLPROGRAMUNIFORMMATRIX2X3FVEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramUniformMatrix2x3fvEXT")) == NULL) || r;
+ r = ((glProgramUniformMatrix2x4fvEXT = (PFNGLPROGRAMUNIFORMMATRIX2X4FVEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramUniformMatrix2x4fvEXT")) == NULL) || r;
+ r = ((glProgramUniformMatrix3fvEXT = (PFNGLPROGRAMUNIFORMMATRIX3FVEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramUniformMatrix3fvEXT")) == NULL) || r;
+ r = ((glProgramUniformMatrix3x2fvEXT = (PFNGLPROGRAMUNIFORMMATRIX3X2FVEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramUniformMatrix3x2fvEXT")) == NULL) || r;
+ r = ((glProgramUniformMatrix3x4fvEXT = (PFNGLPROGRAMUNIFORMMATRIX3X4FVEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramUniformMatrix3x4fvEXT")) == NULL) || r;
+ r = ((glProgramUniformMatrix4fvEXT = (PFNGLPROGRAMUNIFORMMATRIX4FVEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramUniformMatrix4fvEXT")) == NULL) || r;
+ r = ((glProgramUniformMatrix4x2fvEXT = (PFNGLPROGRAMUNIFORMMATRIX4X2FVEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramUniformMatrix4x2fvEXT")) == NULL) || r;
+ r = ((glProgramUniformMatrix4x3fvEXT = (PFNGLPROGRAMUNIFORMMATRIX4X3FVEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramUniformMatrix4x3fvEXT")) == NULL) || r;
+ r = ((glPushClientAttribDefaultEXT = (PFNGLPUSHCLIENTATTRIBDEFAULTEXTPROC)glewGetProcAddress((const GLubyte*)"glPushClientAttribDefaultEXT")) == NULL) || r;
+ r = ((glTextureBufferEXT = (PFNGLTEXTUREBUFFEREXTPROC)glewGetProcAddress((const GLubyte*)"glTextureBufferEXT")) == NULL) || r;
+ r = ((glTextureImage1DEXT = (PFNGLTEXTUREIMAGE1DEXTPROC)glewGetProcAddress((const GLubyte*)"glTextureImage1DEXT")) == NULL) || r;
+ r = ((glTextureImage2DEXT = (PFNGLTEXTUREIMAGE2DEXTPROC)glewGetProcAddress((const GLubyte*)"glTextureImage2DEXT")) == NULL) || r;
+ r = ((glTextureImage3DEXT = (PFNGLTEXTUREIMAGE3DEXTPROC)glewGetProcAddress((const GLubyte*)"glTextureImage3DEXT")) == NULL) || r;
+ r = ((glTextureParameterIivEXT = (PFNGLTEXTUREPARAMETERIIVEXTPROC)glewGetProcAddress((const GLubyte*)"glTextureParameterIivEXT")) == NULL) || r;
+ r = ((glTextureParameterIuivEXT = (PFNGLTEXTUREPARAMETERIUIVEXTPROC)glewGetProcAddress((const GLubyte*)"glTextureParameterIuivEXT")) == NULL) || r;
+ r = ((glTextureParameterfEXT = (PFNGLTEXTUREPARAMETERFEXTPROC)glewGetProcAddress((const GLubyte*)"glTextureParameterfEXT")) == NULL) || r;
+ r = ((glTextureParameterfvEXT = (PFNGLTEXTUREPARAMETERFVEXTPROC)glewGetProcAddress((const GLubyte*)"glTextureParameterfvEXT")) == NULL) || r;
+ r = ((glTextureParameteriEXT = (PFNGLTEXTUREPARAMETERIEXTPROC)glewGetProcAddress((const GLubyte*)"glTextureParameteriEXT")) == NULL) || r;
+ r = ((glTextureParameterivEXT = (PFNGLTEXTUREPARAMETERIVEXTPROC)glewGetProcAddress((const GLubyte*)"glTextureParameterivEXT")) == NULL) || r;
+ r = ((glTextureRenderbufferEXT = (PFNGLTEXTURERENDERBUFFEREXTPROC)glewGetProcAddress((const GLubyte*)"glTextureRenderbufferEXT")) == NULL) || r;
+ r = ((glTextureSubImage1DEXT = (PFNGLTEXTURESUBIMAGE1DEXTPROC)glewGetProcAddress((const GLubyte*)"glTextureSubImage1DEXT")) == NULL) || r;
+ r = ((glTextureSubImage2DEXT = (PFNGLTEXTURESUBIMAGE2DEXTPROC)glewGetProcAddress((const GLubyte*)"glTextureSubImage2DEXT")) == NULL) || r;
+ r = ((glTextureSubImage3DEXT = (PFNGLTEXTURESUBIMAGE3DEXTPROC)glewGetProcAddress((const GLubyte*)"glTextureSubImage3DEXT")) == NULL) || r;
+ r = ((glUnmapNamedBufferEXT = (PFNGLUNMAPNAMEDBUFFEREXTPROC)glewGetProcAddress((const GLubyte*)"glUnmapNamedBufferEXT")) == NULL) || r;
+ r = ((glVertexArrayColorOffsetEXT = (PFNGLVERTEXARRAYCOLOROFFSETEXTPROC)glewGetProcAddress((const GLubyte*)"glVertexArrayColorOffsetEXT")) == NULL) || r;
+ r = ((glVertexArrayEdgeFlagOffsetEXT = (PFNGLVERTEXARRAYEDGEFLAGOFFSETEXTPROC)glewGetProcAddress((const GLubyte*)"glVertexArrayEdgeFlagOffsetEXT")) == NULL) || r;
+ r = ((glVertexArrayFogCoordOffsetEXT = (PFNGLVERTEXARRAYFOGCOORDOFFSETEXTPROC)glewGetProcAddress((const GLubyte*)"glVertexArrayFogCoordOffsetEXT")) == NULL) || r;
+ r = ((glVertexArrayIndexOffsetEXT = (PFNGLVERTEXARRAYINDEXOFFSETEXTPROC)glewGetProcAddress((const GLubyte*)"glVertexArrayIndexOffsetEXT")) == NULL) || r;
+ r = ((glVertexArrayMultiTexCoordOffsetEXT = (PFNGLVERTEXARRAYMULTITEXCOORDOFFSETEXTPROC)glewGetProcAddress((const GLubyte*)"glVertexArrayMultiTexCoordOffsetEXT")) == NULL) || r;
+ r = ((glVertexArrayNormalOffsetEXT = (PFNGLVERTEXARRAYNORMALOFFSETEXTPROC)glewGetProcAddress((const GLubyte*)"glVertexArrayNormalOffsetEXT")) == NULL) || r;
+ r = ((glVertexArraySecondaryColorOffsetEXT = (PFNGLVERTEXARRAYSECONDARYCOLOROFFSETEXTPROC)glewGetProcAddress((const GLubyte*)"glVertexArraySecondaryColorOffsetEXT")) == NULL) || r;
+ r = ((glVertexArrayTexCoordOffsetEXT = (PFNGLVERTEXARRAYTEXCOORDOFFSETEXTPROC)glewGetProcAddress((const GLubyte*)"glVertexArrayTexCoordOffsetEXT")) == NULL) || r;
+ r = ((glVertexArrayVertexAttribIOffsetEXT = (PFNGLVERTEXARRAYVERTEXATTRIBIOFFSETEXTPROC)glewGetProcAddress((const GLubyte*)"glVertexArrayVertexAttribIOffsetEXT")) == NULL) || r;
+ r = ((glVertexArrayVertexAttribOffsetEXT = (PFNGLVERTEXARRAYVERTEXATTRIBOFFSETEXTPROC)glewGetProcAddress((const GLubyte*)"glVertexArrayVertexAttribOffsetEXT")) == NULL) || r;
+ r = ((glVertexArrayVertexOffsetEXT = (PFNGLVERTEXARRAYVERTEXOFFSETEXTPROC)glewGetProcAddress((const GLubyte*)"glVertexArrayVertexOffsetEXT")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_EXT_direct_state_access */
+
+#ifdef GL_EXT_draw_buffers2
+
+static GLboolean _glewInit_GL_EXT_draw_buffers2 (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glColorMaskIndexedEXT = (PFNGLCOLORMASKINDEXEDEXTPROC)glewGetProcAddress((const GLubyte*)"glColorMaskIndexedEXT")) == NULL) || r;
+ r = ((glDisableIndexedEXT = (PFNGLDISABLEINDEXEDEXTPROC)glewGetProcAddress((const GLubyte*)"glDisableIndexedEXT")) == NULL) || r;
+ r = ((glEnableIndexedEXT = (PFNGLENABLEINDEXEDEXTPROC)glewGetProcAddress((const GLubyte*)"glEnableIndexedEXT")) == NULL) || r;
+ r = ((glGetBooleanIndexedvEXT = (PFNGLGETBOOLEANINDEXEDVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetBooleanIndexedvEXT")) == NULL) || r;
+ r = ((glGetIntegerIndexedvEXT = (PFNGLGETINTEGERINDEXEDVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetIntegerIndexedvEXT")) == NULL) || r;
+ r = ((glIsEnabledIndexedEXT = (PFNGLISENABLEDINDEXEDEXTPROC)glewGetProcAddress((const GLubyte*)"glIsEnabledIndexedEXT")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_EXT_draw_buffers2 */
+
+#ifdef GL_EXT_draw_instanced
+
+static GLboolean _glewInit_GL_EXT_draw_instanced (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glDrawArraysInstancedEXT = (PFNGLDRAWARRAYSINSTANCEDEXTPROC)glewGetProcAddress((const GLubyte*)"glDrawArraysInstancedEXT")) == NULL) || r;
+ r = ((glDrawElementsInstancedEXT = (PFNGLDRAWELEMENTSINSTANCEDEXTPROC)glewGetProcAddress((const GLubyte*)"glDrawElementsInstancedEXT")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_EXT_draw_instanced */
+
+#ifdef GL_EXT_draw_range_elements
+
+static GLboolean _glewInit_GL_EXT_draw_range_elements (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glDrawRangeElementsEXT = (PFNGLDRAWRANGEELEMENTSEXTPROC)glewGetProcAddress((const GLubyte*)"glDrawRangeElementsEXT")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_EXT_draw_range_elements */
+
+#ifdef GL_EXT_fog_coord
+
+static GLboolean _glewInit_GL_EXT_fog_coord (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glFogCoordPointerEXT = (PFNGLFOGCOORDPOINTEREXTPROC)glewGetProcAddress((const GLubyte*)"glFogCoordPointerEXT")) == NULL) || r;
+ r = ((glFogCoorddEXT = (PFNGLFOGCOORDDEXTPROC)glewGetProcAddress((const GLubyte*)"glFogCoorddEXT")) == NULL) || r;
+ r = ((glFogCoorddvEXT = (PFNGLFOGCOORDDVEXTPROC)glewGetProcAddress((const GLubyte*)"glFogCoorddvEXT")) == NULL) || r;
+ r = ((glFogCoordfEXT = (PFNGLFOGCOORDFEXTPROC)glewGetProcAddress((const GLubyte*)"glFogCoordfEXT")) == NULL) || r;
+ r = ((glFogCoordfvEXT = (PFNGLFOGCOORDFVEXTPROC)glewGetProcAddress((const GLubyte*)"glFogCoordfvEXT")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_EXT_fog_coord */
+
+#ifdef GL_EXT_fragment_lighting
+
+static GLboolean _glewInit_GL_EXT_fragment_lighting (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glFragmentColorMaterialEXT = (PFNGLFRAGMENTCOLORMATERIALEXTPROC)glewGetProcAddress((const GLubyte*)"glFragmentColorMaterialEXT")) == NULL) || r;
+ r = ((glFragmentLightModelfEXT = (PFNGLFRAGMENTLIGHTMODELFEXTPROC)glewGetProcAddress((const GLubyte*)"glFragmentLightModelfEXT")) == NULL) || r;
+ r = ((glFragmentLightModelfvEXT = (PFNGLFRAGMENTLIGHTMODELFVEXTPROC)glewGetProcAddress((const GLubyte*)"glFragmentLightModelfvEXT")) == NULL) || r;
+ r = ((glFragmentLightModeliEXT = (PFNGLFRAGMENTLIGHTMODELIEXTPROC)glewGetProcAddress((const GLubyte*)"glFragmentLightModeliEXT")) == NULL) || r;
+ r = ((glFragmentLightModelivEXT = (PFNGLFRAGMENTLIGHTMODELIVEXTPROC)glewGetProcAddress((const GLubyte*)"glFragmentLightModelivEXT")) == NULL) || r;
+ r = ((glFragmentLightfEXT = (PFNGLFRAGMENTLIGHTFEXTPROC)glewGetProcAddress((const GLubyte*)"glFragmentLightfEXT")) == NULL) || r;
+ r = ((glFragmentLightfvEXT = (PFNGLFRAGMENTLIGHTFVEXTPROC)glewGetProcAddress((const GLubyte*)"glFragmentLightfvEXT")) == NULL) || r;
+ r = ((glFragmentLightiEXT = (PFNGLFRAGMENTLIGHTIEXTPROC)glewGetProcAddress((const GLubyte*)"glFragmentLightiEXT")) == NULL) || r;
+ r = ((glFragmentLightivEXT = (PFNGLFRAGMENTLIGHTIVEXTPROC)glewGetProcAddress((const GLubyte*)"glFragmentLightivEXT")) == NULL) || r;
+ r = ((glFragmentMaterialfEXT = (PFNGLFRAGMENTMATERIALFEXTPROC)glewGetProcAddress((const GLubyte*)"glFragmentMaterialfEXT")) == NULL) || r;
+ r = ((glFragmentMaterialfvEXT = (PFNGLFRAGMENTMATERIALFVEXTPROC)glewGetProcAddress((const GLubyte*)"glFragmentMaterialfvEXT")) == NULL) || r;
+ r = ((glFragmentMaterialiEXT = (PFNGLFRAGMENTMATERIALIEXTPROC)glewGetProcAddress((const GLubyte*)"glFragmentMaterialiEXT")) == NULL) || r;
+ r = ((glFragmentMaterialivEXT = (PFNGLFRAGMENTMATERIALIVEXTPROC)glewGetProcAddress((const GLubyte*)"glFragmentMaterialivEXT")) == NULL) || r;
+ r = ((glGetFragmentLightfvEXT = (PFNGLGETFRAGMENTLIGHTFVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetFragmentLightfvEXT")) == NULL) || r;
+ r = ((glGetFragmentLightivEXT = (PFNGLGETFRAGMENTLIGHTIVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetFragmentLightivEXT")) == NULL) || r;
+ r = ((glGetFragmentMaterialfvEXT = (PFNGLGETFRAGMENTMATERIALFVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetFragmentMaterialfvEXT")) == NULL) || r;
+ r = ((glGetFragmentMaterialivEXT = (PFNGLGETFRAGMENTMATERIALIVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetFragmentMaterialivEXT")) == NULL) || r;
+ r = ((glLightEnviEXT = (PFNGLLIGHTENVIEXTPROC)glewGetProcAddress((const GLubyte*)"glLightEnviEXT")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_EXT_fragment_lighting */
+
+#ifdef GL_EXT_framebuffer_blit
+
+static GLboolean _glewInit_GL_EXT_framebuffer_blit (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glBlitFramebufferEXT = (PFNGLBLITFRAMEBUFFEREXTPROC)glewGetProcAddress((const GLubyte*)"glBlitFramebufferEXT")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_EXT_framebuffer_blit */
+
+#ifdef GL_EXT_framebuffer_multisample
+
+static GLboolean _glewInit_GL_EXT_framebuffer_multisample (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glRenderbufferStorageMultisampleEXT = (PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC)glewGetProcAddress((const GLubyte*)"glRenderbufferStorageMultisampleEXT")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_EXT_framebuffer_multisample */
+
+#ifdef GL_EXT_framebuffer_multisample_blit_scaled
+
+#endif /* GL_EXT_framebuffer_multisample_blit_scaled */
+
+#ifdef GL_EXT_framebuffer_object
+
+static GLboolean _glewInit_GL_EXT_framebuffer_object (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glBindFramebufferEXT = (PFNGLBINDFRAMEBUFFEREXTPROC)glewGetProcAddress((const GLubyte*)"glBindFramebufferEXT")) == NULL) || r;
+ r = ((glBindRenderbufferEXT = (PFNGLBINDRENDERBUFFEREXTPROC)glewGetProcAddress((const GLubyte*)"glBindRenderbufferEXT")) == NULL) || r;
+ r = ((glCheckFramebufferStatusEXT = (PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC)glewGetProcAddress((const GLubyte*)"glCheckFramebufferStatusEXT")) == NULL) || r;
+ r = ((glDeleteFramebuffersEXT = (PFNGLDELETEFRAMEBUFFERSEXTPROC)glewGetProcAddress((const GLubyte*)"glDeleteFramebuffersEXT")) == NULL) || r;
+ r = ((glDeleteRenderbuffersEXT = (PFNGLDELETERENDERBUFFERSEXTPROC)glewGetProcAddress((const GLubyte*)"glDeleteRenderbuffersEXT")) == NULL) || r;
+ r = ((glFramebufferRenderbufferEXT = (PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC)glewGetProcAddress((const GLubyte*)"glFramebufferRenderbufferEXT")) == NULL) || r;
+ r = ((glFramebufferTexture1DEXT = (PFNGLFRAMEBUFFERTEXTURE1DEXTPROC)glewGetProcAddress((const GLubyte*)"glFramebufferTexture1DEXT")) == NULL) || r;
+ r = ((glFramebufferTexture2DEXT = (PFNGLFRAMEBUFFERTEXTURE2DEXTPROC)glewGetProcAddress((const GLubyte*)"glFramebufferTexture2DEXT")) == NULL) || r;
+ r = ((glFramebufferTexture3DEXT = (PFNGLFRAMEBUFFERTEXTURE3DEXTPROC)glewGetProcAddress((const GLubyte*)"glFramebufferTexture3DEXT")) == NULL) || r;
+ r = ((glGenFramebuffersEXT = (PFNGLGENFRAMEBUFFERSEXTPROC)glewGetProcAddress((const GLubyte*)"glGenFramebuffersEXT")) == NULL) || r;
+ r = ((glGenRenderbuffersEXT = (PFNGLGENRENDERBUFFERSEXTPROC)glewGetProcAddress((const GLubyte*)"glGenRenderbuffersEXT")) == NULL) || r;
+ r = ((glGenerateMipmapEXT = (PFNGLGENERATEMIPMAPEXTPROC)glewGetProcAddress((const GLubyte*)"glGenerateMipmapEXT")) == NULL) || r;
+ r = ((glGetFramebufferAttachmentParameterivEXT = (PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetFramebufferAttachmentParameterivEXT")) == NULL) || r;
+ r = ((glGetRenderbufferParameterivEXT = (PFNGLGETRENDERBUFFERPARAMETERIVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetRenderbufferParameterivEXT")) == NULL) || r;
+ r = ((glIsFramebufferEXT = (PFNGLISFRAMEBUFFEREXTPROC)glewGetProcAddress((const GLubyte*)"glIsFramebufferEXT")) == NULL) || r;
+ r = ((glIsRenderbufferEXT = (PFNGLISRENDERBUFFEREXTPROC)glewGetProcAddress((const GLubyte*)"glIsRenderbufferEXT")) == NULL) || r;
+ r = ((glRenderbufferStorageEXT = (PFNGLRENDERBUFFERSTORAGEEXTPROC)glewGetProcAddress((const GLubyte*)"glRenderbufferStorageEXT")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_EXT_framebuffer_object */
+
+#ifdef GL_EXT_framebuffer_sRGB
+
+#endif /* GL_EXT_framebuffer_sRGB */
+
+#ifdef GL_EXT_geometry_shader4
+
+static GLboolean _glewInit_GL_EXT_geometry_shader4 (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glFramebufferTextureEXT = (PFNGLFRAMEBUFFERTEXTUREEXTPROC)glewGetProcAddress((const GLubyte*)"glFramebufferTextureEXT")) == NULL) || r;
+ r = ((glFramebufferTextureFaceEXT = (PFNGLFRAMEBUFFERTEXTUREFACEEXTPROC)glewGetProcAddress((const GLubyte*)"glFramebufferTextureFaceEXT")) == NULL) || r;
+ r = ((glProgramParameteriEXT = (PFNGLPROGRAMPARAMETERIEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramParameteriEXT")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_EXT_geometry_shader4 */
+
+#ifdef GL_EXT_gpu_program_parameters
+
+static GLboolean _glewInit_GL_EXT_gpu_program_parameters (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glProgramEnvParameters4fvEXT = (PFNGLPROGRAMENVPARAMETERS4FVEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramEnvParameters4fvEXT")) == NULL) || r;
+ r = ((glProgramLocalParameters4fvEXT = (PFNGLPROGRAMLOCALPARAMETERS4FVEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramLocalParameters4fvEXT")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_EXT_gpu_program_parameters */
+
+#ifdef GL_EXT_gpu_shader4
+
+static GLboolean _glewInit_GL_EXT_gpu_shader4 (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glBindFragDataLocationEXT = (PFNGLBINDFRAGDATALOCATIONEXTPROC)glewGetProcAddress((const GLubyte*)"glBindFragDataLocationEXT")) == NULL) || r;
+ r = ((glGetFragDataLocationEXT = (PFNGLGETFRAGDATALOCATIONEXTPROC)glewGetProcAddress((const GLubyte*)"glGetFragDataLocationEXT")) == NULL) || r;
+ r = ((glGetUniformuivEXT = (PFNGLGETUNIFORMUIVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetUniformuivEXT")) == NULL) || r;
+ r = ((glGetVertexAttribIivEXT = (PFNGLGETVERTEXATTRIBIIVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetVertexAttribIivEXT")) == NULL) || r;
+ r = ((glGetVertexAttribIuivEXT = (PFNGLGETVERTEXATTRIBIUIVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetVertexAttribIuivEXT")) == NULL) || r;
+ r = ((glUniform1uiEXT = (PFNGLUNIFORM1UIEXTPROC)glewGetProcAddress((const GLubyte*)"glUniform1uiEXT")) == NULL) || r;
+ r = ((glUniform1uivEXT = (PFNGLUNIFORM1UIVEXTPROC)glewGetProcAddress((const GLubyte*)"glUniform1uivEXT")) == NULL) || r;
+ r = ((glUniform2uiEXT = (PFNGLUNIFORM2UIEXTPROC)glewGetProcAddress((const GLubyte*)"glUniform2uiEXT")) == NULL) || r;
+ r = ((glUniform2uivEXT = (PFNGLUNIFORM2UIVEXTPROC)glewGetProcAddress((const GLubyte*)"glUniform2uivEXT")) == NULL) || r;
+ r = ((glUniform3uiEXT = (PFNGLUNIFORM3UIEXTPROC)glewGetProcAddress((const GLubyte*)"glUniform3uiEXT")) == NULL) || r;
+ r = ((glUniform3uivEXT = (PFNGLUNIFORM3UIVEXTPROC)glewGetProcAddress((const GLubyte*)"glUniform3uivEXT")) == NULL) || r;
+ r = ((glUniform4uiEXT = (PFNGLUNIFORM4UIEXTPROC)glewGetProcAddress((const GLubyte*)"glUniform4uiEXT")) == NULL) || r;
+ r = ((glUniform4uivEXT = (PFNGLUNIFORM4UIVEXTPROC)glewGetProcAddress((const GLubyte*)"glUniform4uivEXT")) == NULL) || r;
+ r = ((glVertexAttribI1iEXT = (PFNGLVERTEXATTRIBI1IEXTPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribI1iEXT")) == NULL) || r;
+ r = ((glVertexAttribI1ivEXT = (PFNGLVERTEXATTRIBI1IVEXTPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribI1ivEXT")) == NULL) || r;
+ r = ((glVertexAttribI1uiEXT = (PFNGLVERTEXATTRIBI1UIEXTPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribI1uiEXT")) == NULL) || r;
+ r = ((glVertexAttribI1uivEXT = (PFNGLVERTEXATTRIBI1UIVEXTPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribI1uivEXT")) == NULL) || r;
+ r = ((glVertexAttribI2iEXT = (PFNGLVERTEXATTRIBI2IEXTPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribI2iEXT")) == NULL) || r;
+ r = ((glVertexAttribI2ivEXT = (PFNGLVERTEXATTRIBI2IVEXTPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribI2ivEXT")) == NULL) || r;
+ r = ((glVertexAttribI2uiEXT = (PFNGLVERTEXATTRIBI2UIEXTPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribI2uiEXT")) == NULL) || r;
+ r = ((glVertexAttribI2uivEXT = (PFNGLVERTEXATTRIBI2UIVEXTPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribI2uivEXT")) == NULL) || r;
+ r = ((glVertexAttribI3iEXT = (PFNGLVERTEXATTRIBI3IEXTPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribI3iEXT")) == NULL) || r;
+ r = ((glVertexAttribI3ivEXT = (PFNGLVERTEXATTRIBI3IVEXTPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribI3ivEXT")) == NULL) || r;
+ r = ((glVertexAttribI3uiEXT = (PFNGLVERTEXATTRIBI3UIEXTPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribI3uiEXT")) == NULL) || r;
+ r = ((glVertexAttribI3uivEXT = (PFNGLVERTEXATTRIBI3UIVEXTPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribI3uivEXT")) == NULL) || r;
+ r = ((glVertexAttribI4bvEXT = (PFNGLVERTEXATTRIBI4BVEXTPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribI4bvEXT")) == NULL) || r;
+ r = ((glVertexAttribI4iEXT = (PFNGLVERTEXATTRIBI4IEXTPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribI4iEXT")) == NULL) || r;
+ r = ((glVertexAttribI4ivEXT = (PFNGLVERTEXATTRIBI4IVEXTPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribI4ivEXT")) == NULL) || r;
+ r = ((glVertexAttribI4svEXT = (PFNGLVERTEXATTRIBI4SVEXTPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribI4svEXT")) == NULL) || r;
+ r = ((glVertexAttribI4ubvEXT = (PFNGLVERTEXATTRIBI4UBVEXTPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribI4ubvEXT")) == NULL) || r;
+ r = ((glVertexAttribI4uiEXT = (PFNGLVERTEXATTRIBI4UIEXTPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribI4uiEXT")) == NULL) || r;
+ r = ((glVertexAttribI4uivEXT = (PFNGLVERTEXATTRIBI4UIVEXTPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribI4uivEXT")) == NULL) || r;
+ r = ((glVertexAttribI4usvEXT = (PFNGLVERTEXATTRIBI4USVEXTPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribI4usvEXT")) == NULL) || r;
+ r = ((glVertexAttribIPointerEXT = (PFNGLVERTEXATTRIBIPOINTEREXTPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribIPointerEXT")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_EXT_gpu_shader4 */
+
+#ifdef GL_EXT_histogram
+
+static GLboolean _glewInit_GL_EXT_histogram (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glGetHistogramEXT = (PFNGLGETHISTOGRAMEXTPROC)glewGetProcAddress((const GLubyte*)"glGetHistogramEXT")) == NULL) || r;
+ r = ((glGetHistogramParameterfvEXT = (PFNGLGETHISTOGRAMPARAMETERFVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetHistogramParameterfvEXT")) == NULL) || r;
+ r = ((glGetHistogramParameterivEXT = (PFNGLGETHISTOGRAMPARAMETERIVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetHistogramParameterivEXT")) == NULL) || r;
+ r = ((glGetMinmaxEXT = (PFNGLGETMINMAXEXTPROC)glewGetProcAddress((const GLubyte*)"glGetMinmaxEXT")) == NULL) || r;
+ r = ((glGetMinmaxParameterfvEXT = (PFNGLGETMINMAXPARAMETERFVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetMinmaxParameterfvEXT")) == NULL) || r;
+ r = ((glGetMinmaxParameterivEXT = (PFNGLGETMINMAXPARAMETERIVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetMinmaxParameterivEXT")) == NULL) || r;
+ r = ((glHistogramEXT = (PFNGLHISTOGRAMEXTPROC)glewGetProcAddress((const GLubyte*)"glHistogramEXT")) == NULL) || r;
+ r = ((glMinmaxEXT = (PFNGLMINMAXEXTPROC)glewGetProcAddress((const GLubyte*)"glMinmaxEXT")) == NULL) || r;
+ r = ((glResetHistogramEXT = (PFNGLRESETHISTOGRAMEXTPROC)glewGetProcAddress((const GLubyte*)"glResetHistogramEXT")) == NULL) || r;
+ r = ((glResetMinmaxEXT = (PFNGLRESETMINMAXEXTPROC)glewGetProcAddress((const GLubyte*)"glResetMinmaxEXT")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_EXT_histogram */
+
+#ifdef GL_EXT_index_array_formats
+
+#endif /* GL_EXT_index_array_formats */
+
+#ifdef GL_EXT_index_func
+
+static GLboolean _glewInit_GL_EXT_index_func (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glIndexFuncEXT = (PFNGLINDEXFUNCEXTPROC)glewGetProcAddress((const GLubyte*)"glIndexFuncEXT")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_EXT_index_func */
+
+#ifdef GL_EXT_index_material
+
+static GLboolean _glewInit_GL_EXT_index_material (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glIndexMaterialEXT = (PFNGLINDEXMATERIALEXTPROC)glewGetProcAddress((const GLubyte*)"glIndexMaterialEXT")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_EXT_index_material */
+
+#ifdef GL_EXT_index_texture
+
+#endif /* GL_EXT_index_texture */
+
+#ifdef GL_EXT_light_texture
+
+static GLboolean _glewInit_GL_EXT_light_texture (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glApplyTextureEXT = (PFNGLAPPLYTEXTUREEXTPROC)glewGetProcAddress((const GLubyte*)"glApplyTextureEXT")) == NULL) || r;
+ r = ((glTextureLightEXT = (PFNGLTEXTURELIGHTEXTPROC)glewGetProcAddress((const GLubyte*)"glTextureLightEXT")) == NULL) || r;
+ r = ((glTextureMaterialEXT = (PFNGLTEXTUREMATERIALEXTPROC)glewGetProcAddress((const GLubyte*)"glTextureMaterialEXT")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_EXT_light_texture */
+
+#ifdef GL_EXT_misc_attribute
+
+#endif /* GL_EXT_misc_attribute */
+
+#ifdef GL_EXT_multi_draw_arrays
+
+static GLboolean _glewInit_GL_EXT_multi_draw_arrays (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glMultiDrawArraysEXT = (PFNGLMULTIDRAWARRAYSEXTPROC)glewGetProcAddress((const GLubyte*)"glMultiDrawArraysEXT")) == NULL) || r;
+ r = ((glMultiDrawElementsEXT = (PFNGLMULTIDRAWELEMENTSEXTPROC)glewGetProcAddress((const GLubyte*)"glMultiDrawElementsEXT")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_EXT_multi_draw_arrays */
+
+#ifdef GL_EXT_multisample
+
+static GLboolean _glewInit_GL_EXT_multisample (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glSampleMaskEXT = (PFNGLSAMPLEMASKEXTPROC)glewGetProcAddress((const GLubyte*)"glSampleMaskEXT")) == NULL) || r;
+ r = ((glSamplePatternEXT = (PFNGLSAMPLEPATTERNEXTPROC)glewGetProcAddress((const GLubyte*)"glSamplePatternEXT")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_EXT_multisample */
+
+#ifdef GL_EXT_packed_depth_stencil
+
+#endif /* GL_EXT_packed_depth_stencil */
+
+#ifdef GL_EXT_packed_float
+
+#endif /* GL_EXT_packed_float */
+
+#ifdef GL_EXT_packed_pixels
+
+#endif /* GL_EXT_packed_pixels */
+
+#ifdef GL_EXT_paletted_texture
+
+static GLboolean _glewInit_GL_EXT_paletted_texture (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glColorTableEXT = (PFNGLCOLORTABLEEXTPROC)glewGetProcAddress((const GLubyte*)"glColorTableEXT")) == NULL) || r;
+ r = ((glGetColorTableEXT = (PFNGLGETCOLORTABLEEXTPROC)glewGetProcAddress((const GLubyte*)"glGetColorTableEXT")) == NULL) || r;
+ r = ((glGetColorTableParameterfvEXT = (PFNGLGETCOLORTABLEPARAMETERFVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetColorTableParameterfvEXT")) == NULL) || r;
+ r = ((glGetColorTableParameterivEXT = (PFNGLGETCOLORTABLEPARAMETERIVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetColorTableParameterivEXT")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_EXT_paletted_texture */
+
+#ifdef GL_EXT_pixel_buffer_object
+
+#endif /* GL_EXT_pixel_buffer_object */
+
+#ifdef GL_EXT_pixel_transform
+
+static GLboolean _glewInit_GL_EXT_pixel_transform (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glGetPixelTransformParameterfvEXT = (PFNGLGETPIXELTRANSFORMPARAMETERFVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetPixelTransformParameterfvEXT")) == NULL) || r;
+ r = ((glGetPixelTransformParameterivEXT = (PFNGLGETPIXELTRANSFORMPARAMETERIVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetPixelTransformParameterivEXT")) == NULL) || r;
+ r = ((glPixelTransformParameterfEXT = (PFNGLPIXELTRANSFORMPARAMETERFEXTPROC)glewGetProcAddress((const GLubyte*)"glPixelTransformParameterfEXT")) == NULL) || r;
+ r = ((glPixelTransformParameterfvEXT = (PFNGLPIXELTRANSFORMPARAMETERFVEXTPROC)glewGetProcAddress((const GLubyte*)"glPixelTransformParameterfvEXT")) == NULL) || r;
+ r = ((glPixelTransformParameteriEXT = (PFNGLPIXELTRANSFORMPARAMETERIEXTPROC)glewGetProcAddress((const GLubyte*)"glPixelTransformParameteriEXT")) == NULL) || r;
+ r = ((glPixelTransformParameterivEXT = (PFNGLPIXELTRANSFORMPARAMETERIVEXTPROC)glewGetProcAddress((const GLubyte*)"glPixelTransformParameterivEXT")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_EXT_pixel_transform */
+
+#ifdef GL_EXT_pixel_transform_color_table
+
+#endif /* GL_EXT_pixel_transform_color_table */
+
+#ifdef GL_EXT_point_parameters
+
+static GLboolean _glewInit_GL_EXT_point_parameters (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glPointParameterfEXT = (PFNGLPOINTPARAMETERFEXTPROC)glewGetProcAddress((const GLubyte*)"glPointParameterfEXT")) == NULL) || r;
+ r = ((glPointParameterfvEXT = (PFNGLPOINTPARAMETERFVEXTPROC)glewGetProcAddress((const GLubyte*)"glPointParameterfvEXT")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_EXT_point_parameters */
+
+#ifdef GL_EXT_polygon_offset
+
+static GLboolean _glewInit_GL_EXT_polygon_offset (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glPolygonOffsetEXT = (PFNGLPOLYGONOFFSETEXTPROC)glewGetProcAddress((const GLubyte*)"glPolygonOffsetEXT")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_EXT_polygon_offset */
+
+#ifdef GL_EXT_provoking_vertex
+
+static GLboolean _glewInit_GL_EXT_provoking_vertex (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glProvokingVertexEXT = (PFNGLPROVOKINGVERTEXEXTPROC)glewGetProcAddress((const GLubyte*)"glProvokingVertexEXT")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_EXT_provoking_vertex */
+
+#ifdef GL_EXT_rescale_normal
+
+#endif /* GL_EXT_rescale_normal */
+
+#ifdef GL_EXT_scene_marker
+
+static GLboolean _glewInit_GL_EXT_scene_marker (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glBeginSceneEXT = (PFNGLBEGINSCENEEXTPROC)glewGetProcAddress((const GLubyte*)"glBeginSceneEXT")) == NULL) || r;
+ r = ((glEndSceneEXT = (PFNGLENDSCENEEXTPROC)glewGetProcAddress((const GLubyte*)"glEndSceneEXT")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_EXT_scene_marker */
+
+#ifdef GL_EXT_secondary_color
+
+static GLboolean _glewInit_GL_EXT_secondary_color (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glSecondaryColor3bEXT = (PFNGLSECONDARYCOLOR3BEXTPROC)glewGetProcAddress((const GLubyte*)"glSecondaryColor3bEXT")) == NULL) || r;
+ r = ((glSecondaryColor3bvEXT = (PFNGLSECONDARYCOLOR3BVEXTPROC)glewGetProcAddress((const GLubyte*)"glSecondaryColor3bvEXT")) == NULL) || r;
+ r = ((glSecondaryColor3dEXT = (PFNGLSECONDARYCOLOR3DEXTPROC)glewGetProcAddress((const GLubyte*)"glSecondaryColor3dEXT")) == NULL) || r;
+ r = ((glSecondaryColor3dvEXT = (PFNGLSECONDARYCOLOR3DVEXTPROC)glewGetProcAddress((const GLubyte*)"glSecondaryColor3dvEXT")) == NULL) || r;
+ r = ((glSecondaryColor3fEXT = (PFNGLSECONDARYCOLOR3FEXTPROC)glewGetProcAddress((const GLubyte*)"glSecondaryColor3fEXT")) == NULL) || r;
+ r = ((glSecondaryColor3fvEXT = (PFNGLSECONDARYCOLOR3FVEXTPROC)glewGetProcAddress((const GLubyte*)"glSecondaryColor3fvEXT")) == NULL) || r;
+ r = ((glSecondaryColor3iEXT = (PFNGLSECONDARYCOLOR3IEXTPROC)glewGetProcAddress((const GLubyte*)"glSecondaryColor3iEXT")) == NULL) || r;
+ r = ((glSecondaryColor3ivEXT = (PFNGLSECONDARYCOLOR3IVEXTPROC)glewGetProcAddress((const GLubyte*)"glSecondaryColor3ivEXT")) == NULL) || r;
+ r = ((glSecondaryColor3sEXT = (PFNGLSECONDARYCOLOR3SEXTPROC)glewGetProcAddress((const GLubyte*)"glSecondaryColor3sEXT")) == NULL) || r;
+ r = ((glSecondaryColor3svEXT = (PFNGLSECONDARYCOLOR3SVEXTPROC)glewGetProcAddress((const GLubyte*)"glSecondaryColor3svEXT")) == NULL) || r;
+ r = ((glSecondaryColor3ubEXT = (PFNGLSECONDARYCOLOR3UBEXTPROC)glewGetProcAddress((const GLubyte*)"glSecondaryColor3ubEXT")) == NULL) || r;
+ r = ((glSecondaryColor3ubvEXT = (PFNGLSECONDARYCOLOR3UBVEXTPROC)glewGetProcAddress((const GLubyte*)"glSecondaryColor3ubvEXT")) == NULL) || r;
+ r = ((glSecondaryColor3uiEXT = (PFNGLSECONDARYCOLOR3UIEXTPROC)glewGetProcAddress((const GLubyte*)"glSecondaryColor3uiEXT")) == NULL) || r;
+ r = ((glSecondaryColor3uivEXT = (PFNGLSECONDARYCOLOR3UIVEXTPROC)glewGetProcAddress((const GLubyte*)"glSecondaryColor3uivEXT")) == NULL) || r;
+ r = ((glSecondaryColor3usEXT = (PFNGLSECONDARYCOLOR3USEXTPROC)glewGetProcAddress((const GLubyte*)"glSecondaryColor3usEXT")) == NULL) || r;
+ r = ((glSecondaryColor3usvEXT = (PFNGLSECONDARYCOLOR3USVEXTPROC)glewGetProcAddress((const GLubyte*)"glSecondaryColor3usvEXT")) == NULL) || r;
+ r = ((glSecondaryColorPointerEXT = (PFNGLSECONDARYCOLORPOINTEREXTPROC)glewGetProcAddress((const GLubyte*)"glSecondaryColorPointerEXT")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_EXT_secondary_color */
+
+#if 0 // NOTE jwilkins: there is an inconsistency between the ES and Non-ES versions of this extension??
+#ifdef GL_EXT_separate_shader_objects
+
+static GLboolean _glewInit_GL_EXT_separate_shader_objects (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glActiveProgramEXT = (PFNGLACTIVEPROGRAMEXTPROC)glewGetProcAddress((const GLubyte*)"glActiveProgramEXT")) == NULL) || r; // NOTE jwilkins: may be modified
+ r = ((glCreateShaderProgramEXT = (PFNGLCREATESHADERPROGRAMEXTPROC)glewGetProcAddress((const GLubyte*)"glCreateShaderProgramEXT")) == NULL) || r; // NOTE jwilkins: may be modified
+ r = ((glUseShaderProgramEXT = (PFNGLUSESHADERPROGRAMEXTPROC)glewGetProcAddress((const GLubyte*)"glUseShaderProgramEXT")) == NULL) || r; // NOTE jwilkins: may be modified
+
+ return r;
+}
+#endif /* GL_EXT_separate_shader_objects */
+#endif // XXX
+
+#ifdef GL_EXT_separate_specular_color
+
+#endif /* GL_EXT_separate_specular_color */
+
+#ifdef GL_EXT_shader_image_load_store
+
+static GLboolean _glewInit_GL_EXT_shader_image_load_store (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glBindImageTextureEXT = (PFNGLBINDIMAGETEXTUREEXTPROC)glewGetProcAddress((const GLubyte*)"glBindImageTextureEXT")) == NULL) || r;
+ r = ((glMemoryBarrierEXT = (PFNGLMEMORYBARRIEREXTPROC)glewGetProcAddress((const GLubyte*)"glMemoryBarrierEXT")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_EXT_shader_image_load_store */
+
+#ifdef GL_EXT_shadow_funcs
+
+#endif /* GL_EXT_shadow_funcs */
+
+#ifdef GL_EXT_shared_texture_palette
+
+#endif /* GL_EXT_shared_texture_palette */
+
+#ifdef GL_EXT_stencil_clear_tag
+
+#endif /* GL_EXT_stencil_clear_tag */
+
+#ifdef GL_EXT_stencil_two_side
+
+static GLboolean _glewInit_GL_EXT_stencil_two_side (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glActiveStencilFaceEXT = (PFNGLACTIVESTENCILFACEEXTPROC)glewGetProcAddress((const GLubyte*)"glActiveStencilFaceEXT")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_EXT_stencil_two_side */
+
+#ifdef GL_EXT_stencil_wrap
+
+#endif /* GL_EXT_stencil_wrap */
+
+#ifdef GL_EXT_subtexture
+
+static GLboolean _glewInit_GL_EXT_subtexture (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glTexSubImage1DEXT = (PFNGLTEXSUBIMAGE1DEXTPROC)glewGetProcAddress((const GLubyte*)"glTexSubImage1DEXT")) == NULL) || r;
+ r = ((glTexSubImage2DEXT = (PFNGLTEXSUBIMAGE2DEXTPROC)glewGetProcAddress((const GLubyte*)"glTexSubImage2DEXT")) == NULL) || r;
+ r = ((glTexSubImage3DEXT = (PFNGLTEXSUBIMAGE3DEXTPROC)glewGetProcAddress((const GLubyte*)"glTexSubImage3DEXT")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_EXT_subtexture */
+
+#ifdef GL_EXT_texture
+
+#endif /* GL_EXT_texture */
+
+#ifdef GL_EXT_texture3D
+
+static GLboolean _glewInit_GL_EXT_texture3D (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glTexImage3DEXT = (PFNGLTEXIMAGE3DEXTPROC)glewGetProcAddress((const GLubyte*)"glTexImage3DEXT")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_EXT_texture3D */
+
+#ifdef GL_EXT_texture_array
+
+static GLboolean _glewInit_GL_EXT_texture_array (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glFramebufferTextureLayerEXT = (PFNGLFRAMEBUFFERTEXTURELAYEREXTPROC)glewGetProcAddress((const GLubyte*)"glFramebufferTextureLayerEXT")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_EXT_texture_array */
+
+#ifdef GL_EXT_texture_buffer_object
+
+static GLboolean _glewInit_GL_EXT_texture_buffer_object (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glTexBufferEXT = (PFNGLTEXBUFFEREXTPROC)glewGetProcAddress((const GLubyte*)"glTexBufferEXT")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_EXT_texture_buffer_object */
+
+#ifdef GL_EXT_texture_compression_dxt1
+
+#endif /* GL_EXT_texture_compression_dxt1 */
+
+#ifdef GL_EXT_texture_compression_latc
+
+#endif /* GL_EXT_texture_compression_latc */
+
+#ifdef GL_EXT_texture_compression_rgtc
+
+#endif /* GL_EXT_texture_compression_rgtc */
+
+#ifdef GL_EXT_texture_compression_s3tc
+
+#endif /* GL_EXT_texture_compression_s3tc */
+
+#ifdef GL_EXT_texture_cube_map
+
+#endif /* GL_EXT_texture_cube_map */
+
+#ifdef GL_EXT_texture_edge_clamp
+
+#endif /* GL_EXT_texture_edge_clamp */
+
+#ifdef GL_EXT_texture_env
+
+#endif /* GL_EXT_texture_env */
+
+#ifdef GL_EXT_texture_env_add
+
+#endif /* GL_EXT_texture_env_add */
+
+#ifdef GL_EXT_texture_env_combine
+
+#endif /* GL_EXT_texture_env_combine */
+
+#ifdef GL_EXT_texture_env_dot3
+
+#endif /* GL_EXT_texture_env_dot3 */
+
+#ifdef GL_EXT_texture_filter_anisotropic
+
+#endif /* GL_EXT_texture_filter_anisotropic */
+
+#ifdef GL_EXT_texture_integer
+
+static GLboolean _glewInit_GL_EXT_texture_integer (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glClearColorIiEXT = (PFNGLCLEARCOLORIIEXTPROC)glewGetProcAddress((const GLubyte*)"glClearColorIiEXT")) == NULL) || r;
+ r = ((glClearColorIuiEXT = (PFNGLCLEARCOLORIUIEXTPROC)glewGetProcAddress((const GLubyte*)"glClearColorIuiEXT")) == NULL) || r;
+ r = ((glGetTexParameterIivEXT = (PFNGLGETTEXPARAMETERIIVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetTexParameterIivEXT")) == NULL) || r;
+ r = ((glGetTexParameterIuivEXT = (PFNGLGETTEXPARAMETERIUIVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetTexParameterIuivEXT")) == NULL) || r;
+ r = ((glTexParameterIivEXT = (PFNGLTEXPARAMETERIIVEXTPROC)glewGetProcAddress((const GLubyte*)"glTexParameterIivEXT")) == NULL) || r;
+ r = ((glTexParameterIuivEXT = (PFNGLTEXPARAMETERIUIVEXTPROC)glewGetProcAddress((const GLubyte*)"glTexParameterIuivEXT")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_EXT_texture_integer */
+
+#ifdef GL_EXT_texture_lod_bias
+
+#endif /* GL_EXT_texture_lod_bias */
+
+#ifdef GL_EXT_texture_mirror_clamp
+
+#endif /* GL_EXT_texture_mirror_clamp */
+
+#ifdef GL_EXT_texture_object
+
+static GLboolean _glewInit_GL_EXT_texture_object (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glAreTexturesResidentEXT = (PFNGLARETEXTURESRESIDENTEXTPROC)glewGetProcAddress((const GLubyte*)"glAreTexturesResidentEXT")) == NULL) || r;
+ r = ((glBindTextureEXT = (PFNGLBINDTEXTUREEXTPROC)glewGetProcAddress((const GLubyte*)"glBindTextureEXT")) == NULL) || r;
+ r = ((glDeleteTexturesEXT = (PFNGLDELETETEXTURESEXTPROC)glewGetProcAddress((const GLubyte*)"glDeleteTexturesEXT")) == NULL) || r;
+ r = ((glGenTexturesEXT = (PFNGLGENTEXTURESEXTPROC)glewGetProcAddress((const GLubyte*)"glGenTexturesEXT")) == NULL) || r;
+ r = ((glIsTextureEXT = (PFNGLISTEXTUREEXTPROC)glewGetProcAddress((const GLubyte*)"glIsTextureEXT")) == NULL) || r;
+ r = ((glPrioritizeTexturesEXT = (PFNGLPRIORITIZETEXTURESEXTPROC)glewGetProcAddress((const GLubyte*)"glPrioritizeTexturesEXT")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_EXT_texture_object */
+
+#ifdef GL_EXT_texture_perturb_normal
+
+static GLboolean _glewInit_GL_EXT_texture_perturb_normal (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glTextureNormalEXT = (PFNGLTEXTURENORMALEXTPROC)glewGetProcAddress((const GLubyte*)"glTextureNormalEXT")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_EXT_texture_perturb_normal */
+
+#ifdef GL_EXT_texture_rectangle
+
+#endif /* GL_EXT_texture_rectangle */
+
+#ifdef GL_EXT_texture_sRGB
+
+#endif /* GL_EXT_texture_sRGB */
+
+#ifdef GL_EXT_texture_sRGB_decode
+
+#endif /* GL_EXT_texture_sRGB_decode */
+
+#ifdef GL_EXT_texture_shared_exponent
+
+#endif /* GL_EXT_texture_shared_exponent */
+
+#ifdef GL_EXT_texture_snorm
+
+#endif /* GL_EXT_texture_snorm */
+
+#ifdef GL_EXT_texture_swizzle
+
+#endif /* GL_EXT_texture_swizzle */
+
+#ifdef GL_EXT_timer_query
+
+static GLboolean _glewInit_GL_EXT_timer_query (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glGetQueryObjecti64vEXT = (PFNGLGETQUERYOBJECTI64VEXTPROC)glewGetProcAddress((const GLubyte*)"glGetQueryObjecti64vEXT")) == NULL) || r;
+ r = ((glGetQueryObjectui64vEXT = (PFNGLGETQUERYOBJECTUI64VEXTPROC)glewGetProcAddress((const GLubyte*)"glGetQueryObjectui64vEXT")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_EXT_timer_query */
+
+#ifdef GL_EXT_transform_feedback
+
+static GLboolean _glewInit_GL_EXT_transform_feedback (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glBeginTransformFeedbackEXT = (PFNGLBEGINTRANSFORMFEEDBACKEXTPROC)glewGetProcAddress((const GLubyte*)"glBeginTransformFeedbackEXT")) == NULL) || r;
+ r = ((glBindBufferBaseEXT = (PFNGLBINDBUFFERBASEEXTPROC)glewGetProcAddress((const GLubyte*)"glBindBufferBaseEXT")) == NULL) || r;
+ r = ((glBindBufferOffsetEXT = (PFNGLBINDBUFFEROFFSETEXTPROC)glewGetProcAddress((const GLubyte*)"glBindBufferOffsetEXT")) == NULL) || r;
+ r = ((glBindBufferRangeEXT = (PFNGLBINDBUFFERRANGEEXTPROC)glewGetProcAddress((const GLubyte*)"glBindBufferRangeEXT")) == NULL) || r;
+ r = ((glEndTransformFeedbackEXT = (PFNGLENDTRANSFORMFEEDBACKEXTPROC)glewGetProcAddress((const GLubyte*)"glEndTransformFeedbackEXT")) == NULL) || r;
+ r = ((glGetTransformFeedbackVaryingEXT = (PFNGLGETTRANSFORMFEEDBACKVARYINGEXTPROC)glewGetProcAddress((const GLubyte*)"glGetTransformFeedbackVaryingEXT")) == NULL) || r;
+ r = ((glTransformFeedbackVaryingsEXT = (PFNGLTRANSFORMFEEDBACKVARYINGSEXTPROC)glewGetProcAddress((const GLubyte*)"glTransformFeedbackVaryingsEXT")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_EXT_transform_feedback */
+
+#ifdef GL_EXT_vertex_array
+
+static GLboolean _glewInit_GL_EXT_vertex_array (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glArrayElementEXT = (PFNGLARRAYELEMENTEXTPROC)glewGetProcAddress((const GLubyte*)"glArrayElementEXT")) == NULL) || r;
+ r = ((glColorPointerEXT = (PFNGLCOLORPOINTEREXTPROC)glewGetProcAddress((const GLubyte*)"glColorPointerEXT")) == NULL) || r;
+ r = ((glDrawArraysEXT = (PFNGLDRAWARRAYSEXTPROC)glewGetProcAddress((const GLubyte*)"glDrawArraysEXT")) == NULL) || r;
+ r = ((glEdgeFlagPointerEXT = (PFNGLEDGEFLAGPOINTEREXTPROC)glewGetProcAddress((const GLubyte*)"glEdgeFlagPointerEXT")) == NULL) || r;
+ r = ((glIndexPointerEXT = (PFNGLINDEXPOINTEREXTPROC)glewGetProcAddress((const GLubyte*)"glIndexPointerEXT")) == NULL) || r;
+ r = ((glNormalPointerEXT = (PFNGLNORMALPOINTEREXTPROC)glewGetProcAddress((const GLubyte*)"glNormalPointerEXT")) == NULL) || r;
+ r = ((glTexCoordPointerEXT = (PFNGLTEXCOORDPOINTEREXTPROC)glewGetProcAddress((const GLubyte*)"glTexCoordPointerEXT")) == NULL) || r;
+ r = ((glVertexPointerEXT = (PFNGLVERTEXPOINTEREXTPROC)glewGetProcAddress((const GLubyte*)"glVertexPointerEXT")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_EXT_vertex_array */
+
+#ifdef GL_EXT_vertex_array_bgra
+
+#endif /* GL_EXT_vertex_array_bgra */
+
+#ifdef GL_EXT_vertex_attrib_64bit
+
+static GLboolean _glewInit_GL_EXT_vertex_attrib_64bit (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glGetVertexAttribLdvEXT = (PFNGLGETVERTEXATTRIBLDVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetVertexAttribLdvEXT")) == NULL) || r;
+ r = ((glVertexArrayVertexAttribLOffsetEXT = (PFNGLVERTEXARRAYVERTEXATTRIBLOFFSETEXTPROC)glewGetProcAddress((const GLubyte*)"glVertexArrayVertexAttribLOffsetEXT")) == NULL) || r;
+ r = ((glVertexAttribL1dEXT = (PFNGLVERTEXATTRIBL1DEXTPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribL1dEXT")) == NULL) || r;
+ r = ((glVertexAttribL1dvEXT = (PFNGLVERTEXATTRIBL1DVEXTPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribL1dvEXT")) == NULL) || r;
+ r = ((glVertexAttribL2dEXT = (PFNGLVERTEXATTRIBL2DEXTPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribL2dEXT")) == NULL) || r;
+ r = ((glVertexAttribL2dvEXT = (PFNGLVERTEXATTRIBL2DVEXTPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribL2dvEXT")) == NULL) || r;
+ r = ((glVertexAttribL3dEXT = (PFNGLVERTEXATTRIBL3DEXTPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribL3dEXT")) == NULL) || r;
+ r = ((glVertexAttribL3dvEXT = (PFNGLVERTEXATTRIBL3DVEXTPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribL3dvEXT")) == NULL) || r;
+ r = ((glVertexAttribL4dEXT = (PFNGLVERTEXATTRIBL4DEXTPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribL4dEXT")) == NULL) || r;
+ r = ((glVertexAttribL4dvEXT = (PFNGLVERTEXATTRIBL4DVEXTPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribL4dvEXT")) == NULL) || r;
+ r = ((glVertexAttribLPointerEXT = (PFNGLVERTEXATTRIBLPOINTEREXTPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribLPointerEXT")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_EXT_vertex_attrib_64bit */
+
+#ifdef GL_EXT_vertex_shader
+
+static GLboolean _glewInit_GL_EXT_vertex_shader (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glBeginVertexShaderEXT = (PFNGLBEGINVERTEXSHADEREXTPROC)glewGetProcAddress((const GLubyte*)"glBeginVertexShaderEXT")) == NULL) || r;
+ r = ((glBindLightParameterEXT = (PFNGLBINDLIGHTPARAMETEREXTPROC)glewGetProcAddress((const GLubyte*)"glBindLightParameterEXT")) == NULL) || r;
+ r = ((glBindMaterialParameterEXT = (PFNGLBINDMATERIALPARAMETEREXTPROC)glewGetProcAddress((const GLubyte*)"glBindMaterialParameterEXT")) == NULL) || r;
+ r = ((glBindParameterEXT = (PFNGLBINDPARAMETEREXTPROC)glewGetProcAddress((const GLubyte*)"glBindParameterEXT")) == NULL) || r;
+ r = ((glBindTexGenParameterEXT = (PFNGLBINDTEXGENPARAMETEREXTPROC)glewGetProcAddress((const GLubyte*)"glBindTexGenParameterEXT")) == NULL) || r;
+ r = ((glBindTextureUnitParameterEXT = (PFNGLBINDTEXTUREUNITPARAMETEREXTPROC)glewGetProcAddress((const GLubyte*)"glBindTextureUnitParameterEXT")) == NULL) || r;
+ r = ((glBindVertexShaderEXT = (PFNGLBINDVERTEXSHADEREXTPROC)glewGetProcAddress((const GLubyte*)"glBindVertexShaderEXT")) == NULL) || r;
+ r = ((glDeleteVertexShaderEXT = (PFNGLDELETEVERTEXSHADEREXTPROC)glewGetProcAddress((const GLubyte*)"glDeleteVertexShaderEXT")) == NULL) || r;
+ r = ((glDisableVariantClientStateEXT = (PFNGLDISABLEVARIANTCLIENTSTATEEXTPROC)glewGetProcAddress((const GLubyte*)"glDisableVariantClientStateEXT")) == NULL) || r;
+ r = ((glEnableVariantClientStateEXT = (PFNGLENABLEVARIANTCLIENTSTATEEXTPROC)glewGetProcAddress((const GLubyte*)"glEnableVariantClientStateEXT")) == NULL) || r;
+ r = ((glEndVertexShaderEXT = (PFNGLENDVERTEXSHADEREXTPROC)glewGetProcAddress((const GLubyte*)"glEndVertexShaderEXT")) == NULL) || r;
+ r = ((glExtractComponentEXT = (PFNGLEXTRACTCOMPONENTEXTPROC)glewGetProcAddress((const GLubyte*)"glExtractComponentEXT")) == NULL) || r;
+ r = ((glGenSymbolsEXT = (PFNGLGENSYMBOLSEXTPROC)glewGetProcAddress((const GLubyte*)"glGenSymbolsEXT")) == NULL) || r;
+ r = ((glGenVertexShadersEXT = (PFNGLGENVERTEXSHADERSEXTPROC)glewGetProcAddress((const GLubyte*)"glGenVertexShadersEXT")) == NULL) || r;
+ r = ((glGetInvariantBooleanvEXT = (PFNGLGETINVARIANTBOOLEANVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetInvariantBooleanvEXT")) == NULL) || r;
+ r = ((glGetInvariantFloatvEXT = (PFNGLGETINVARIANTFLOATVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetInvariantFloatvEXT")) == NULL) || r;
+ r = ((glGetInvariantIntegervEXT = (PFNGLGETINVARIANTINTEGERVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetInvariantIntegervEXT")) == NULL) || r;
+ r = ((glGetLocalConstantBooleanvEXT = (PFNGLGETLOCALCONSTANTBOOLEANVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetLocalConstantBooleanvEXT")) == NULL) || r;
+ r = ((glGetLocalConstantFloatvEXT = (PFNGLGETLOCALCONSTANTFLOATVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetLocalConstantFloatvEXT")) == NULL) || r;
+ r = ((glGetLocalConstantIntegervEXT = (PFNGLGETLOCALCONSTANTINTEGERVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetLocalConstantIntegervEXT")) == NULL) || r;
+ r = ((glGetVariantBooleanvEXT = (PFNGLGETVARIANTBOOLEANVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetVariantBooleanvEXT")) == NULL) || r;
+ r = ((glGetVariantFloatvEXT = (PFNGLGETVARIANTFLOATVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetVariantFloatvEXT")) == NULL) || r;
+ r = ((glGetVariantIntegervEXT = (PFNGLGETVARIANTINTEGERVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetVariantIntegervEXT")) == NULL) || r;
+ r = ((glGetVariantPointervEXT = (PFNGLGETVARIANTPOINTERVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetVariantPointervEXT")) == NULL) || r;
+ r = ((glInsertComponentEXT = (PFNGLINSERTCOMPONENTEXTPROC)glewGetProcAddress((const GLubyte*)"glInsertComponentEXT")) == NULL) || r;
+ r = ((glIsVariantEnabledEXT = (PFNGLISVARIANTENABLEDEXTPROC)glewGetProcAddress((const GLubyte*)"glIsVariantEnabledEXT")) == NULL) || r;
+ r = ((glSetInvariantEXT = (PFNGLSETINVARIANTEXTPROC)glewGetProcAddress((const GLubyte*)"glSetInvariantEXT")) == NULL) || r;
+ r = ((glSetLocalConstantEXT = (PFNGLSETLOCALCONSTANTEXTPROC)glewGetProcAddress((const GLubyte*)"glSetLocalConstantEXT")) == NULL) || r;
+ r = ((glShaderOp1EXT = (PFNGLSHADEROP1EXTPROC)glewGetProcAddress((const GLubyte*)"glShaderOp1EXT")) == NULL) || r;
+ r = ((glShaderOp2EXT = (PFNGLSHADEROP2EXTPROC)glewGetProcAddress((const GLubyte*)"glShaderOp2EXT")) == NULL) || r;
+ r = ((glShaderOp3EXT = (PFNGLSHADEROP3EXTPROC)glewGetProcAddress((const GLubyte*)"glShaderOp3EXT")) == NULL) || r;
+ r = ((glSwizzleEXT = (PFNGLSWIZZLEEXTPROC)glewGetProcAddress((const GLubyte*)"glSwizzleEXT")) == NULL) || r;
+ r = ((glVariantPointerEXT = (PFNGLVARIANTPOINTEREXTPROC)glewGetProcAddress((const GLubyte*)"glVariantPointerEXT")) == NULL) || r;
+ r = ((glVariantbvEXT = (PFNGLVARIANTBVEXTPROC)glewGetProcAddress((const GLubyte*)"glVariantbvEXT")) == NULL) || r;
+ r = ((glVariantdvEXT = (PFNGLVARIANTDVEXTPROC)glewGetProcAddress((const GLubyte*)"glVariantdvEXT")) == NULL) || r;
+ r = ((glVariantfvEXT = (PFNGLVARIANTFVEXTPROC)glewGetProcAddress((const GLubyte*)"glVariantfvEXT")) == NULL) || r;
+ r = ((glVariantivEXT = (PFNGLVARIANTIVEXTPROC)glewGetProcAddress((const GLubyte*)"glVariantivEXT")) == NULL) || r;
+ r = ((glVariantsvEXT = (PFNGLVARIANTSVEXTPROC)glewGetProcAddress((const GLubyte*)"glVariantsvEXT")) == NULL) || r;
+ r = ((glVariantubvEXT = (PFNGLVARIANTUBVEXTPROC)glewGetProcAddress((const GLubyte*)"glVariantubvEXT")) == NULL) || r;
+ r = ((glVariantuivEXT = (PFNGLVARIANTUIVEXTPROC)glewGetProcAddress((const GLubyte*)"glVariantuivEXT")) == NULL) || r;
+ r = ((glVariantusvEXT = (PFNGLVARIANTUSVEXTPROC)glewGetProcAddress((const GLubyte*)"glVariantusvEXT")) == NULL) || r;
+ r = ((glWriteMaskEXT = (PFNGLWRITEMASKEXTPROC)glewGetProcAddress((const GLubyte*)"glWriteMaskEXT")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_EXT_vertex_shader */
+
+#ifdef GL_EXT_vertex_weighting
+
+static GLboolean _glewInit_GL_EXT_vertex_weighting (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glVertexWeightPointerEXT = (PFNGLVERTEXWEIGHTPOINTEREXTPROC)glewGetProcAddress((const GLubyte*)"glVertexWeightPointerEXT")) == NULL) || r;
+ r = ((glVertexWeightfEXT = (PFNGLVERTEXWEIGHTFEXTPROC)glewGetProcAddress((const GLubyte*)"glVertexWeightfEXT")) == NULL) || r;
+ r = ((glVertexWeightfvEXT = (PFNGLVERTEXWEIGHTFVEXTPROC)glewGetProcAddress((const GLubyte*)"glVertexWeightfvEXT")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_EXT_vertex_weighting */
+
+#ifdef GL_EXT_x11_sync_object
+
+static GLboolean _glewInit_GL_EXT_x11_sync_object (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glImportSyncEXT = (PFNGLIMPORTSYNCEXTPROC)glewGetProcAddress((const GLubyte*)"glImportSyncEXT")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_EXT_x11_sync_object */
+
+#ifdef GL_GREMEDY_frame_terminator
+
+static GLboolean _glewInit_GL_GREMEDY_frame_terminator (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glFrameTerminatorGREMEDY = (PFNGLFRAMETERMINATORGREMEDYPROC)glewGetProcAddress((const GLubyte*)"glFrameTerminatorGREMEDY")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_GREMEDY_frame_terminator */
+
+#ifdef GL_GREMEDY_string_marker
+
+static GLboolean _glewInit_GL_GREMEDY_string_marker (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glStringMarkerGREMEDY = (PFNGLSTRINGMARKERGREMEDYPROC)glewGetProcAddress((const GLubyte*)"glStringMarkerGREMEDY")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_GREMEDY_string_marker */
+
+#ifdef GL_HP_convolution_border_modes
+
+#endif /* GL_HP_convolution_border_modes */
+
+#ifdef GL_HP_image_transform
+
+static GLboolean _glewInit_GL_HP_image_transform (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glGetImageTransformParameterfvHP = (PFNGLGETIMAGETRANSFORMPARAMETERFVHPPROC)glewGetProcAddress((const GLubyte*)"glGetImageTransformParameterfvHP")) == NULL) || r;
+ r = ((glGetImageTransformParameterivHP = (PFNGLGETIMAGETRANSFORMPARAMETERIVHPPROC)glewGetProcAddress((const GLubyte*)"glGetImageTransformParameterivHP")) == NULL) || r;
+ r = ((glImageTransformParameterfHP = (PFNGLIMAGETRANSFORMPARAMETERFHPPROC)glewGetProcAddress((const GLubyte*)"glImageTransformParameterfHP")) == NULL) || r;
+ r = ((glImageTransformParameterfvHP = (PFNGLIMAGETRANSFORMPARAMETERFVHPPROC)glewGetProcAddress((const GLubyte*)"glImageTransformParameterfvHP")) == NULL) || r;
+ r = ((glImageTransformParameteriHP = (PFNGLIMAGETRANSFORMPARAMETERIHPPROC)glewGetProcAddress((const GLubyte*)"glImageTransformParameteriHP")) == NULL) || r;
+ r = ((glImageTransformParameterivHP = (PFNGLIMAGETRANSFORMPARAMETERIVHPPROC)glewGetProcAddress((const GLubyte*)"glImageTransformParameterivHP")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_HP_image_transform */
+
+#ifdef GL_HP_occlusion_test
+
+#endif /* GL_HP_occlusion_test */
+
+#ifdef GL_HP_texture_lighting
+
+#endif /* GL_HP_texture_lighting */
+
+#ifdef GL_IBM_cull_vertex
+
+#endif /* GL_IBM_cull_vertex */
+
+#ifdef GL_IBM_multimode_draw_arrays
+
+static GLboolean _glewInit_GL_IBM_multimode_draw_arrays (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glMultiModeDrawArraysIBM = (PFNGLMULTIMODEDRAWARRAYSIBMPROC)glewGetProcAddress((const GLubyte*)"glMultiModeDrawArraysIBM")) == NULL) || r;
+ r = ((glMultiModeDrawElementsIBM = (PFNGLMULTIMODEDRAWELEMENTSIBMPROC)glewGetProcAddress((const GLubyte*)"glMultiModeDrawElementsIBM")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_IBM_multimode_draw_arrays */
+
+#ifdef GL_IBM_rasterpos_clip
+
+#endif /* GL_IBM_rasterpos_clip */
+
+#ifdef GL_IBM_static_data
+
+#endif /* GL_IBM_static_data */
+
+#ifdef GL_IBM_texture_mirrored_repeat
+
+#endif /* GL_IBM_texture_mirrored_repeat */
+
+#ifdef GL_IBM_vertex_array_lists
+
+static GLboolean _glewInit_GL_IBM_vertex_array_lists (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glColorPointerListIBM = (PFNGLCOLORPOINTERLISTIBMPROC)glewGetProcAddress((const GLubyte*)"glColorPointerListIBM")) == NULL) || r;
+ r = ((glEdgeFlagPointerListIBM = (PFNGLEDGEFLAGPOINTERLISTIBMPROC)glewGetProcAddress((const GLubyte*)"glEdgeFlagPointerListIBM")) == NULL) || r;
+ r = ((glFogCoordPointerListIBM = (PFNGLFOGCOORDPOINTERLISTIBMPROC)glewGetProcAddress((const GLubyte*)"glFogCoordPointerListIBM")) == NULL) || r;
+ r = ((glIndexPointerListIBM = (PFNGLINDEXPOINTERLISTIBMPROC)glewGetProcAddress((const GLubyte*)"glIndexPointerListIBM")) == NULL) || r;
+ r = ((glNormalPointerListIBM = (PFNGLNORMALPOINTERLISTIBMPROC)glewGetProcAddress((const GLubyte*)"glNormalPointerListIBM")) == NULL) || r;
+ r = ((glSecondaryColorPointerListIBM = (PFNGLSECONDARYCOLORPOINTERLISTIBMPROC)glewGetProcAddress((const GLubyte*)"glSecondaryColorPointerListIBM")) == NULL) || r;
+ r = ((glTexCoordPointerListIBM = (PFNGLTEXCOORDPOINTERLISTIBMPROC)glewGetProcAddress((const GLubyte*)"glTexCoordPointerListIBM")) == NULL) || r;
+ r = ((glVertexPointerListIBM = (PFNGLVERTEXPOINTERLISTIBMPROC)glewGetProcAddress((const GLubyte*)"glVertexPointerListIBM")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_IBM_vertex_array_lists */
+
+#ifdef GL_INGR_color_clamp
+
+#endif /* GL_INGR_color_clamp */
+
+#ifdef GL_INGR_interlace_read
+
+#endif /* GL_INGR_interlace_read */
+
+#ifdef GL_INTEL_map_texture
+
+static GLboolean _glewInit_GL_INTEL_map_texture (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glMapTexture2DINTEL = (PFNGLMAPTEXTURE2DINTELPROC)glewGetProcAddress((const GLubyte*)"glMapTexture2DINTEL")) == NULL) || r;
+ r = ((glSyncTextureINTEL = (PFNGLSYNCTEXTUREINTELPROC)glewGetProcAddress((const GLubyte*)"glSyncTextureINTEL")) == NULL) || r;
+ r = ((glUnmapTexture2DINTEL = (PFNGLUNMAPTEXTURE2DINTELPROC)glewGetProcAddress((const GLubyte*)"glUnmapTexture2DINTEL")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_INTEL_map_texture */
+
+#ifdef GL_INTEL_parallel_arrays
+
+static GLboolean _glewInit_GL_INTEL_parallel_arrays (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glColorPointervINTEL = (PFNGLCOLORPOINTERVINTELPROC)glewGetProcAddress((const GLubyte*)"glColorPointervINTEL")) == NULL) || r;
+ r = ((glNormalPointervINTEL = (PFNGLNORMALPOINTERVINTELPROC)glewGetProcAddress((const GLubyte*)"glNormalPointervINTEL")) == NULL) || r;
+ r = ((glTexCoordPointervINTEL = (PFNGLTEXCOORDPOINTERVINTELPROC)glewGetProcAddress((const GLubyte*)"glTexCoordPointervINTEL")) == NULL) || r;
+ r = ((glVertexPointervINTEL = (PFNGLVERTEXPOINTERVINTELPROC)glewGetProcAddress((const GLubyte*)"glVertexPointervINTEL")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_INTEL_parallel_arrays */
+
+#ifdef GL_INTEL_texture_scissor
+
+static GLboolean _glewInit_GL_INTEL_texture_scissor (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glTexScissorFuncINTEL = (PFNGLTEXSCISSORFUNCINTELPROC)glewGetProcAddress((const GLubyte*)"glTexScissorFuncINTEL")) == NULL) || r;
+ r = ((glTexScissorINTEL = (PFNGLTEXSCISSORINTELPROC)glewGetProcAddress((const GLubyte*)"glTexScissorINTEL")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_INTEL_texture_scissor */
+
+#ifdef GL_KHR_debug
+
+static GLboolean _glewInit_GL_KHR_debug (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glDebugMessageCallback = (PFNGLDEBUGMESSAGECALLBACKPROC)glewGetProcAddress((const GLubyte*)"glDebugMessageCallback")) == NULL) || r;
+ r = ((glDebugMessageControl = (PFNGLDEBUGMESSAGECONTROLPROC)glewGetProcAddress((const GLubyte*)"glDebugMessageControl")) == NULL) || r;
+ r = ((glDebugMessageInsert = (PFNGLDEBUGMESSAGEINSERTPROC)glewGetProcAddress((const GLubyte*)"glDebugMessageInsert")) == NULL) || r;
+ r = ((glGetDebugMessageLog = (PFNGLGETDEBUGMESSAGELOGPROC)glewGetProcAddress((const GLubyte*)"glGetDebugMessageLog")) == NULL) || r;
+ r = ((glGetObjectLabel = (PFNGLGETOBJECTLABELPROC)glewGetProcAddress((const GLubyte*)"glGetObjectLabel")) == NULL) || r;
+ r = ((glGetObjectPtrLabel = (PFNGLGETOBJECTPTRLABELPROC)glewGetProcAddress((const GLubyte*)"glGetObjectPtrLabel")) == NULL) || r;
+ r = ((glGetPointerv = (PFNGLGETPOINTERVPROC)glewGetProcAddress((const GLubyte*)"glGetPointerv")) == NULL) || r;
+ r = ((glObjectLabel = (PFNGLOBJECTLABELPROC)glewGetProcAddress((const GLubyte*)"glObjectLabel")) == NULL) || r;
+ r = ((glObjectPtrLabel = (PFNGLOBJECTPTRLABELPROC)glewGetProcAddress((const GLubyte*)"glObjectPtrLabel")) == NULL) || r;
+ r = ((glPopDebugGroup = (PFNGLPOPDEBUGGROUPPROC)glewGetProcAddress((const GLubyte*)"glPopDebugGroup")) == NULL) || r;
+ r = ((glPushDebugGroup = (PFNGLPUSHDEBUGGROUPPROC)glewGetProcAddress((const GLubyte*)"glPushDebugGroup")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_KHR_debug */
+
+#ifdef GL_KHR_texture_compression_astc_ldr
+
+#endif /* GL_KHR_texture_compression_astc_ldr */
+
+#ifdef GL_KTX_buffer_region
+
+static GLboolean _glewInit_GL_KTX_buffer_region (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glBufferRegionEnabled = (PFNGLBUFFERREGIONENABLEDPROC)glewGetProcAddress((const GLubyte*)"glBufferRegionEnabled")) == NULL) || r;
+ r = ((glDeleteBufferRegion = (PFNGLDELETEBUFFERREGIONPROC)glewGetProcAddress((const GLubyte*)"glDeleteBufferRegion")) == NULL) || r;
+ r = ((glDrawBufferRegion = (PFNGLDRAWBUFFERREGIONPROC)glewGetProcAddress((const GLubyte*)"glDrawBufferRegion")) == NULL) || r;
+ r = ((glNewBufferRegion = (PFNGLNEWBUFFERREGIONPROC)glewGetProcAddress((const GLubyte*)"glNewBufferRegion")) == NULL) || r;
+ r = ((glReadBufferRegion = (PFNGLREADBUFFERREGIONPROC)glewGetProcAddress((const GLubyte*)"glReadBufferRegion")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_KTX_buffer_region */
+
+#ifdef GL_MESAX_texture_stack
+
+#endif /* GL_MESAX_texture_stack */
+
+#ifdef GL_MESA_pack_invert
+
+#endif /* GL_MESA_pack_invert */
+
+#ifdef GL_MESA_resize_buffers
+
+static GLboolean _glewInit_GL_MESA_resize_buffers (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glResizeBuffersMESA = (PFNGLRESIZEBUFFERSMESAPROC)glewGetProcAddress((const GLubyte*)"glResizeBuffersMESA")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_MESA_resize_buffers */
+
+#ifdef GL_MESA_window_pos
+
+static GLboolean _glewInit_GL_MESA_window_pos (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glWindowPos2dMESA = (PFNGLWINDOWPOS2DMESAPROC)glewGetProcAddress((const GLubyte*)"glWindowPos2dMESA")) == NULL) || r;
+ r = ((glWindowPos2dvMESA = (PFNGLWINDOWPOS2DVMESAPROC)glewGetProcAddress((const GLubyte*)"glWindowPos2dvMESA")) == NULL) || r;
+ r = ((glWindowPos2fMESA = (PFNGLWINDOWPOS2FMESAPROC)glewGetProcAddress((const GLubyte*)"glWindowPos2fMESA")) == NULL) || r;
+ r = ((glWindowPos2fvMESA = (PFNGLWINDOWPOS2FVMESAPROC)glewGetProcAddress((const GLubyte*)"glWindowPos2fvMESA")) == NULL) || r;
+ r = ((glWindowPos2iMESA = (PFNGLWINDOWPOS2IMESAPROC)glewGetProcAddress((const GLubyte*)"glWindowPos2iMESA")) == NULL) || r;
+ r = ((glWindowPos2ivMESA = (PFNGLWINDOWPOS2IVMESAPROC)glewGetProcAddress((const GLubyte*)"glWindowPos2ivMESA")) == NULL) || r;
+ r = ((glWindowPos2sMESA = (PFNGLWINDOWPOS2SMESAPROC)glewGetProcAddress((const GLubyte*)"glWindowPos2sMESA")) == NULL) || r;
+ r = ((glWindowPos2svMESA = (PFNGLWINDOWPOS2SVMESAPROC)glewGetProcAddress((const GLubyte*)"glWindowPos2svMESA")) == NULL) || r;
+ r = ((glWindowPos3dMESA = (PFNGLWINDOWPOS3DMESAPROC)glewGetProcAddress((const GLubyte*)"glWindowPos3dMESA")) == NULL) || r;
+ r = ((glWindowPos3dvMESA = (PFNGLWINDOWPOS3DVMESAPROC)glewGetProcAddress((const GLubyte*)"glWindowPos3dvMESA")) == NULL) || r;
+ r = ((glWindowPos3fMESA = (PFNGLWINDOWPOS3FMESAPROC)glewGetProcAddress((const GLubyte*)"glWindowPos3fMESA")) == NULL) || r;
+ r = ((glWindowPos3fvMESA = (PFNGLWINDOWPOS3FVMESAPROC)glewGetProcAddress((const GLubyte*)"glWindowPos3fvMESA")) == NULL) || r;
+ r = ((glWindowPos3iMESA = (PFNGLWINDOWPOS3IMESAPROC)glewGetProcAddress((const GLubyte*)"glWindowPos3iMESA")) == NULL) || r;
+ r = ((glWindowPos3ivMESA = (PFNGLWINDOWPOS3IVMESAPROC)glewGetProcAddress((const GLubyte*)"glWindowPos3ivMESA")) == NULL) || r;
+ r = ((glWindowPos3sMESA = (PFNGLWINDOWPOS3SMESAPROC)glewGetProcAddress((const GLubyte*)"glWindowPos3sMESA")) == NULL) || r;
+ r = ((glWindowPos3svMESA = (PFNGLWINDOWPOS3SVMESAPROC)glewGetProcAddress((const GLubyte*)"glWindowPos3svMESA")) == NULL) || r;
+ r = ((glWindowPos4dMESA = (PFNGLWINDOWPOS4DMESAPROC)glewGetProcAddress((const GLubyte*)"glWindowPos4dMESA")) == NULL) || r;
+ r = ((glWindowPos4dvMESA = (PFNGLWINDOWPOS4DVMESAPROC)glewGetProcAddress((const GLubyte*)"glWindowPos4dvMESA")) == NULL) || r;
+ r = ((glWindowPos4fMESA = (PFNGLWINDOWPOS4FMESAPROC)glewGetProcAddress((const GLubyte*)"glWindowPos4fMESA")) == NULL) || r;
+ r = ((glWindowPos4fvMESA = (PFNGLWINDOWPOS4FVMESAPROC)glewGetProcAddress((const GLubyte*)"glWindowPos4fvMESA")) == NULL) || r;
+ r = ((glWindowPos4iMESA = (PFNGLWINDOWPOS4IMESAPROC)glewGetProcAddress((const GLubyte*)"glWindowPos4iMESA")) == NULL) || r;
+ r = ((glWindowPos4ivMESA = (PFNGLWINDOWPOS4IVMESAPROC)glewGetProcAddress((const GLubyte*)"glWindowPos4ivMESA")) == NULL) || r;
+ r = ((glWindowPos4sMESA = (PFNGLWINDOWPOS4SMESAPROC)glewGetProcAddress((const GLubyte*)"glWindowPos4sMESA")) == NULL) || r;
+ r = ((glWindowPos4svMESA = (PFNGLWINDOWPOS4SVMESAPROC)glewGetProcAddress((const GLubyte*)"glWindowPos4svMESA")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_MESA_window_pos */
+
+#ifdef GL_MESA_ycbcr_texture
+
+#endif /* GL_MESA_ycbcr_texture */
+
+#ifdef GL_NVX_conditional_render
+
+static GLboolean _glewInit_GL_NVX_conditional_render (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glBeginConditionalRenderNVX = (PFNGLBEGINCONDITIONALRENDERNVXPROC)glewGetProcAddress((const GLubyte*)"glBeginConditionalRenderNVX")) == NULL) || r;
+ r = ((glEndConditionalRenderNVX = (PFNGLENDCONDITIONALRENDERNVXPROC)glewGetProcAddress((const GLubyte*)"glEndConditionalRenderNVX")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_NVX_conditional_render */
+
+#ifdef GL_NVX_gpu_memory_info
+
+#endif /* GL_NVX_gpu_memory_info */
+
+#ifdef GL_NV_bindless_texture
+
+static GLboolean _glewInit_GL_NV_bindless_texture (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glGetImageHandleNV = (PFNGLGETIMAGEHANDLENVPROC)glewGetProcAddress((const GLubyte*)"glGetImageHandleNV")) == NULL) || r;
+ r = ((glGetTextureHandleNV = (PFNGLGETTEXTUREHANDLENVPROC)glewGetProcAddress((const GLubyte*)"glGetTextureHandleNV")) == NULL) || r;
+ r = ((glGetTextureSamplerHandleNV = (PFNGLGETTEXTURESAMPLERHANDLENVPROC)glewGetProcAddress((const GLubyte*)"glGetTextureSamplerHandleNV")) == NULL) || r;
+ r = ((glIsImageHandleResidentNV = (PFNGLISIMAGEHANDLERESIDENTNVPROC)glewGetProcAddress((const GLubyte*)"glIsImageHandleResidentNV")) == NULL) || r;
+ r = ((glIsTextureHandleResidentNV = (PFNGLISTEXTUREHANDLERESIDENTNVPROC)glewGetProcAddress((const GLubyte*)"glIsTextureHandleResidentNV")) == NULL) || r;
+ r = ((glMakeImageHandleNonResidentNV = (PFNGLMAKEIMAGEHANDLENONRESIDENTNVPROC)glewGetProcAddress((const GLubyte*)"glMakeImageHandleNonResidentNV")) == NULL) || r;
+ r = ((glMakeImageHandleResidentNV = (PFNGLMAKEIMAGEHANDLERESIDENTNVPROC)glewGetProcAddress((const GLubyte*)"glMakeImageHandleResidentNV")) == NULL) || r;
+ r = ((glMakeTextureHandleNonResidentNV = (PFNGLMAKETEXTUREHANDLENONRESIDENTNVPROC)glewGetProcAddress((const GLubyte*)"glMakeTextureHandleNonResidentNV")) == NULL) || r;
+ r = ((glMakeTextureHandleResidentNV = (PFNGLMAKETEXTUREHANDLERESIDENTNVPROC)glewGetProcAddress((const GLubyte*)"glMakeTextureHandleResidentNV")) == NULL) || r;
+ r = ((glProgramUniformHandleui64NV = (PFNGLPROGRAMUNIFORMHANDLEUI64NVPROC)glewGetProcAddress((const GLubyte*)"glProgramUniformHandleui64NV")) == NULL) || r;
+ r = ((glProgramUniformHandleui64vNV = (PFNGLPROGRAMUNIFORMHANDLEUI64VNVPROC)glewGetProcAddress((const GLubyte*)"glProgramUniformHandleui64vNV")) == NULL) || r;
+ r = ((glUniformHandleui64NV = (PFNGLUNIFORMHANDLEUI64NVPROC)glewGetProcAddress((const GLubyte*)"glUniformHandleui64NV")) == NULL) || r;
+ r = ((glUniformHandleui64vNV = (PFNGLUNIFORMHANDLEUI64VNVPROC)glewGetProcAddress((const GLubyte*)"glUniformHandleui64vNV")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_NV_bindless_texture */
+
+#ifdef GL_NV_blend_square
+
+#endif /* GL_NV_blend_square */
+
+#ifdef GL_NV_compute_program5
+
+#endif /* GL_NV_compute_program5 */
+
+#ifdef GL_NV_conditional_render
+
+static GLboolean _glewInit_GL_NV_conditional_render (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glBeginConditionalRenderNV = (PFNGLBEGINCONDITIONALRENDERNVPROC)glewGetProcAddress((const GLubyte*)"glBeginConditionalRenderNV")) == NULL) || r;
+ r = ((glEndConditionalRenderNV = (PFNGLENDCONDITIONALRENDERNVPROC)glewGetProcAddress((const GLubyte*)"glEndConditionalRenderNV")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_NV_conditional_render */
+
+#ifdef GL_NV_copy_depth_to_color
+
+#endif /* GL_NV_copy_depth_to_color */
+
+#ifdef GL_NV_copy_image
+
+static GLboolean _glewInit_GL_NV_copy_image (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glCopyImageSubDataNV = (PFNGLCOPYIMAGESUBDATANVPROC)glewGetProcAddress((const GLubyte*)"glCopyImageSubDataNV")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_NV_copy_image */
+
+#ifdef GL_NV_deep_texture3D
+
+#endif /* GL_NV_deep_texture3D */
+
+#ifdef GL_NV_depth_buffer_float
+
+static GLboolean _glewInit_GL_NV_depth_buffer_float (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glClearDepthdNV = (PFNGLCLEARDEPTHDNVPROC)glewGetProcAddress((const GLubyte*)"glClearDepthdNV")) == NULL) || r;
+ r = ((glDepthBoundsdNV = (PFNGLDEPTHBOUNDSDNVPROC)glewGetProcAddress((const GLubyte*)"glDepthBoundsdNV")) == NULL) || r;
+ r = ((glDepthRangedNV = (PFNGLDEPTHRANGEDNVPROC)glewGetProcAddress((const GLubyte*)"glDepthRangedNV")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_NV_depth_buffer_float */
+
+#ifdef GL_NV_depth_clamp
+
+#endif /* GL_NV_depth_clamp */
+
+#ifdef GL_NV_depth_range_unclamped
+
+#endif /* GL_NV_depth_range_unclamped */
+
+#ifdef GL_NV_draw_texture
+
+static GLboolean _glewInit_GL_NV_draw_texture (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glDrawTextureNV = (PFNGLDRAWTEXTURENVPROC)glewGetProcAddress((const GLubyte*)"glDrawTextureNV")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_NV_draw_texture */
+
+#ifdef GL_NV_evaluators
+
+static GLboolean _glewInit_GL_NV_evaluators (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glEvalMapsNV = (PFNGLEVALMAPSNVPROC)glewGetProcAddress((const GLubyte*)"glEvalMapsNV")) == NULL) || r;
+ r = ((glGetMapAttribParameterfvNV = (PFNGLGETMAPATTRIBPARAMETERFVNVPROC)glewGetProcAddress((const GLubyte*)"glGetMapAttribParameterfvNV")) == NULL) || r;
+ r = ((glGetMapAttribParameterivNV = (PFNGLGETMAPATTRIBPARAMETERIVNVPROC)glewGetProcAddress((const GLubyte*)"glGetMapAttribParameterivNV")) == NULL) || r;
+ r = ((glGetMapControlPointsNV = (PFNGLGETMAPCONTROLPOINTSNVPROC)glewGetProcAddress((const GLubyte*)"glGetMapControlPointsNV")) == NULL) || r;
+ r = ((glGetMapParameterfvNV = (PFNGLGETMAPPARAMETERFVNVPROC)glewGetProcAddress((const GLubyte*)"glGetMapParameterfvNV")) == NULL) || r;
+ r = ((glGetMapParameterivNV = (PFNGLGETMAPPARAMETERIVNVPROC)glewGetProcAddress((const GLubyte*)"glGetMapParameterivNV")) == NULL) || r;
+ r = ((glMapControlPointsNV = (PFNGLMAPCONTROLPOINTSNVPROC)glewGetProcAddress((const GLubyte*)"glMapControlPointsNV")) == NULL) || r;
+ r = ((glMapParameterfvNV = (PFNGLMAPPARAMETERFVNVPROC)glewGetProcAddress((const GLubyte*)"glMapParameterfvNV")) == NULL) || r;
+ r = ((glMapParameterivNV = (PFNGLMAPPARAMETERIVNVPROC)glewGetProcAddress((const GLubyte*)"glMapParameterivNV")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_NV_evaluators */
+
+#ifdef GL_NV_explicit_multisample
+
+static GLboolean _glewInit_GL_NV_explicit_multisample (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glGetMultisamplefvNV = (PFNGLGETMULTISAMPLEFVNVPROC)glewGetProcAddress((const GLubyte*)"glGetMultisamplefvNV")) == NULL) || r;
+ r = ((glSampleMaskIndexedNV = (PFNGLSAMPLEMASKINDEXEDNVPROC)glewGetProcAddress((const GLubyte*)"glSampleMaskIndexedNV")) == NULL) || r;
+ r = ((glTexRenderbufferNV = (PFNGLTEXRENDERBUFFERNVPROC)glewGetProcAddress((const GLubyte*)"glTexRenderbufferNV")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_NV_explicit_multisample */
+
+#ifdef GL_NV_fence
+
+static GLboolean _glewInit_GL_NV_fence (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glDeleteFencesNV = (PFNGLDELETEFENCESNVPROC)glewGetProcAddress((const GLubyte*)"glDeleteFencesNV")) == NULL) || r;
+ r = ((glFinishFenceNV = (PFNGLFINISHFENCENVPROC)glewGetProcAddress((const GLubyte*)"glFinishFenceNV")) == NULL) || r;
+ r = ((glGenFencesNV = (PFNGLGENFENCESNVPROC)glewGetProcAddress((const GLubyte*)"glGenFencesNV")) == NULL) || r;
+ r = ((glGetFenceivNV = (PFNGLGETFENCEIVNVPROC)glewGetProcAddress((const GLubyte*)"glGetFenceivNV")) == NULL) || r;
+ r = ((glIsFenceNV = (PFNGLISFENCENVPROC)glewGetProcAddress((const GLubyte*)"glIsFenceNV")) == NULL) || r;
+ r = ((glSetFenceNV = (PFNGLSETFENCENVPROC)glewGetProcAddress((const GLubyte*)"glSetFenceNV")) == NULL) || r;
+ r = ((glTestFenceNV = (PFNGLTESTFENCENVPROC)glewGetProcAddress((const GLubyte*)"glTestFenceNV")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_NV_fence */
+
+#ifdef GL_NV_float_buffer
+
+#endif /* GL_NV_float_buffer */
+
+#ifdef GL_NV_fog_distance
+
+#endif /* GL_NV_fog_distance */
+
+#ifdef GL_NV_fragment_program
+
+static GLboolean _glewInit_GL_NV_fragment_program (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glGetProgramNamedParameterdvNV = (PFNGLGETPROGRAMNAMEDPARAMETERDVNVPROC)glewGetProcAddress((const GLubyte*)"glGetProgramNamedParameterdvNV")) == NULL) || r;
+ r = ((glGetProgramNamedParameterfvNV = (PFNGLGETPROGRAMNAMEDPARAMETERFVNVPROC)glewGetProcAddress((const GLubyte*)"glGetProgramNamedParameterfvNV")) == NULL) || r;
+ r = ((glProgramNamedParameter4dNV = (PFNGLPROGRAMNAMEDPARAMETER4DNVPROC)glewGetProcAddress((const GLubyte*)"glProgramNamedParameter4dNV")) == NULL) || r;
+ r = ((glProgramNamedParameter4dvNV = (PFNGLPROGRAMNAMEDPARAMETER4DVNVPROC)glewGetProcAddress((const GLubyte*)"glProgramNamedParameter4dvNV")) == NULL) || r;
+ r = ((glProgramNamedParameter4fNV = (PFNGLPROGRAMNAMEDPARAMETER4FNVPROC)glewGetProcAddress((const GLubyte*)"glProgramNamedParameter4fNV")) == NULL) || r;
+ r = ((glProgramNamedParameter4fvNV = (PFNGLPROGRAMNAMEDPARAMETER4FVNVPROC)glewGetProcAddress((const GLubyte*)"glProgramNamedParameter4fvNV")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_NV_fragment_program */
+
+#ifdef GL_NV_fragment_program2
+
+#endif /* GL_NV_fragment_program2 */
+
+#ifdef GL_NV_fragment_program4
+
+#endif /* GL_NV_fragment_program4 */
+
+#ifdef GL_NV_fragment_program_option
+
+#endif /* GL_NV_fragment_program_option */
+
+#ifdef GL_NV_framebuffer_multisample_coverage
+
+static GLboolean _glewInit_GL_NV_framebuffer_multisample_coverage (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glRenderbufferStorageMultisampleCoverageNV = (PFNGLRENDERBUFFERSTORAGEMULTISAMPLECOVERAGENVPROC)glewGetProcAddress((const GLubyte*)"glRenderbufferStorageMultisampleCoverageNV")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_NV_framebuffer_multisample_coverage */
+
+#ifdef GL_NV_geometry_program4
+
+static GLboolean _glewInit_GL_NV_geometry_program4 (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glProgramVertexLimitNV = (PFNGLPROGRAMVERTEXLIMITNVPROC)glewGetProcAddress((const GLubyte*)"glProgramVertexLimitNV")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_NV_geometry_program4 */
+
+#ifdef GL_NV_geometry_shader4
+
+#endif /* GL_NV_geometry_shader4 */
+
+#ifdef GL_NV_gpu_program4
+
+static GLboolean _glewInit_GL_NV_gpu_program4 (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glProgramEnvParameterI4iNV = (PFNGLPROGRAMENVPARAMETERI4INVPROC)glewGetProcAddress((const GLubyte*)"glProgramEnvParameterI4iNV")) == NULL) || r;
+ r = ((glProgramEnvParameterI4ivNV = (PFNGLPROGRAMENVPARAMETERI4IVNVPROC)glewGetProcAddress((const GLubyte*)"glProgramEnvParameterI4ivNV")) == NULL) || r;
+ r = ((glProgramEnvParameterI4uiNV = (PFNGLPROGRAMENVPARAMETERI4UINVPROC)glewGetProcAddress((const GLubyte*)"glProgramEnvParameterI4uiNV")) == NULL) || r;
+ r = ((glProgramEnvParameterI4uivNV = (PFNGLPROGRAMENVPARAMETERI4UIVNVPROC)glewGetProcAddress((const GLubyte*)"glProgramEnvParameterI4uivNV")) == NULL) || r;
+ r = ((glProgramEnvParametersI4ivNV = (PFNGLPROGRAMENVPARAMETERSI4IVNVPROC)glewGetProcAddress((const GLubyte*)"glProgramEnvParametersI4ivNV")) == NULL) || r;
+ r = ((glProgramEnvParametersI4uivNV = (PFNGLPROGRAMENVPARAMETERSI4UIVNVPROC)glewGetProcAddress((const GLubyte*)"glProgramEnvParametersI4uivNV")) == NULL) || r;
+ r = ((glProgramLocalParameterI4iNV = (PFNGLPROGRAMLOCALPARAMETERI4INVPROC)glewGetProcAddress((const GLubyte*)"glProgramLocalParameterI4iNV")) == NULL) || r;
+ r = ((glProgramLocalParameterI4ivNV = (PFNGLPROGRAMLOCALPARAMETERI4IVNVPROC)glewGetProcAddress((const GLubyte*)"glProgramLocalParameterI4ivNV")) == NULL) || r;
+ r = ((glProgramLocalParameterI4uiNV = (PFNGLPROGRAMLOCALPARAMETERI4UINVPROC)glewGetProcAddress((const GLubyte*)"glProgramLocalParameterI4uiNV")) == NULL) || r;
+ r = ((glProgramLocalParameterI4uivNV = (PFNGLPROGRAMLOCALPARAMETERI4UIVNVPROC)glewGetProcAddress((const GLubyte*)"glProgramLocalParameterI4uivNV")) == NULL) || r;
+ r = ((glProgramLocalParametersI4ivNV = (PFNGLPROGRAMLOCALPARAMETERSI4IVNVPROC)glewGetProcAddress((const GLubyte*)"glProgramLocalParametersI4ivNV")) == NULL) || r;
+ r = ((glProgramLocalParametersI4uivNV = (PFNGLPROGRAMLOCALPARAMETERSI4UIVNVPROC)glewGetProcAddress((const GLubyte*)"glProgramLocalParametersI4uivNV")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_NV_gpu_program4 */
+
+#ifdef GL_NV_gpu_program5
+
+#endif /* GL_NV_gpu_program5 */
+
+#ifdef GL_NV_gpu_program_fp64
+
+#endif /* GL_NV_gpu_program_fp64 */
+
+#ifdef GL_NV_gpu_shader5
+
+static GLboolean _glewInit_GL_NV_gpu_shader5 (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glGetUniformi64vNV = (PFNGLGETUNIFORMI64VNVPROC)glewGetProcAddress((const GLubyte*)"glGetUniformi64vNV")) == NULL) || r;
+ r = ((glGetUniformui64vNV = (PFNGLGETUNIFORMUI64VNVPROC)glewGetProcAddress((const GLubyte*)"glGetUniformui64vNV")) == NULL) || r;
+ r = ((glProgramUniform1i64NV = (PFNGLPROGRAMUNIFORM1I64NVPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform1i64NV")) == NULL) || r;
+ r = ((glProgramUniform1i64vNV = (PFNGLPROGRAMUNIFORM1I64VNVPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform1i64vNV")) == NULL) || r;
+ r = ((glProgramUniform1ui64NV = (PFNGLPROGRAMUNIFORM1UI64NVPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform1ui64NV")) == NULL) || r;
+ r = ((glProgramUniform1ui64vNV = (PFNGLPROGRAMUNIFORM1UI64VNVPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform1ui64vNV")) == NULL) || r;
+ r = ((glProgramUniform2i64NV = (PFNGLPROGRAMUNIFORM2I64NVPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform2i64NV")) == NULL) || r;
+ r = ((glProgramUniform2i64vNV = (PFNGLPROGRAMUNIFORM2I64VNVPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform2i64vNV")) == NULL) || r;
+ r = ((glProgramUniform2ui64NV = (PFNGLPROGRAMUNIFORM2UI64NVPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform2ui64NV")) == NULL) || r;
+ r = ((glProgramUniform2ui64vNV = (PFNGLPROGRAMUNIFORM2UI64VNVPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform2ui64vNV")) == NULL) || r;
+ r = ((glProgramUniform3i64NV = (PFNGLPROGRAMUNIFORM3I64NVPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform3i64NV")) == NULL) || r;
+ r = ((glProgramUniform3i64vNV = (PFNGLPROGRAMUNIFORM3I64VNVPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform3i64vNV")) == NULL) || r;
+ r = ((glProgramUniform3ui64NV = (PFNGLPROGRAMUNIFORM3UI64NVPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform3ui64NV")) == NULL) || r;
+ r = ((glProgramUniform3ui64vNV = (PFNGLPROGRAMUNIFORM3UI64VNVPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform3ui64vNV")) == NULL) || r;
+ r = ((glProgramUniform4i64NV = (PFNGLPROGRAMUNIFORM4I64NVPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform4i64NV")) == NULL) || r;
+ r = ((glProgramUniform4i64vNV = (PFNGLPROGRAMUNIFORM4I64VNVPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform4i64vNV")) == NULL) || r;
+ r = ((glProgramUniform4ui64NV = (PFNGLPROGRAMUNIFORM4UI64NVPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform4ui64NV")) == NULL) || r;
+ r = ((glProgramUniform4ui64vNV = (PFNGLPROGRAMUNIFORM4UI64VNVPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform4ui64vNV")) == NULL) || r;
+ r = ((glUniform1i64NV = (PFNGLUNIFORM1I64NVPROC)glewGetProcAddress((const GLubyte*)"glUniform1i64NV")) == NULL) || r;
+ r = ((glUniform1i64vNV = (PFNGLUNIFORM1I64VNVPROC)glewGetProcAddress((const GLubyte*)"glUniform1i64vNV")) == NULL) || r;
+ r = ((glUniform1ui64NV = (PFNGLUNIFORM1UI64NVPROC)glewGetProcAddress((const GLubyte*)"glUniform1ui64NV")) == NULL) || r;
+ r = ((glUniform1ui64vNV = (PFNGLUNIFORM1UI64VNVPROC)glewGetProcAddress((const GLubyte*)"glUniform1ui64vNV")) == NULL) || r;
+ r = ((glUniform2i64NV = (PFNGLUNIFORM2I64NVPROC)glewGetProcAddress((const GLubyte*)"glUniform2i64NV")) == NULL) || r;
+ r = ((glUniform2i64vNV = (PFNGLUNIFORM2I64VNVPROC)glewGetProcAddress((const GLubyte*)"glUniform2i64vNV")) == NULL) || r;
+ r = ((glUniform2ui64NV = (PFNGLUNIFORM2UI64NVPROC)glewGetProcAddress((const GLubyte*)"glUniform2ui64NV")) == NULL) || r;
+ r = ((glUniform2ui64vNV = (PFNGLUNIFORM2UI64VNVPROC)glewGetProcAddress((const GLubyte*)"glUniform2ui64vNV")) == NULL) || r;
+ r = ((glUniform3i64NV = (PFNGLUNIFORM3I64NVPROC)glewGetProcAddress((const GLubyte*)"glUniform3i64NV")) == NULL) || r;
+ r = ((glUniform3i64vNV = (PFNGLUNIFORM3I64VNVPROC)glewGetProcAddress((const GLubyte*)"glUniform3i64vNV")) == NULL) || r;
+ r = ((glUniform3ui64NV = (PFNGLUNIFORM3UI64NVPROC)glewGetProcAddress((const GLubyte*)"glUniform3ui64NV")) == NULL) || r;
+ r = ((glUniform3ui64vNV = (PFNGLUNIFORM3UI64VNVPROC)glewGetProcAddress((const GLubyte*)"glUniform3ui64vNV")) == NULL) || r;
+ r = ((glUniform4i64NV = (PFNGLUNIFORM4I64NVPROC)glewGetProcAddress((const GLubyte*)"glUniform4i64NV")) == NULL) || r;
+ r = ((glUniform4i64vNV = (PFNGLUNIFORM4I64VNVPROC)glewGetProcAddress((const GLubyte*)"glUniform4i64vNV")) == NULL) || r;
+ r = ((glUniform4ui64NV = (PFNGLUNIFORM4UI64NVPROC)glewGetProcAddress((const GLubyte*)"glUniform4ui64NV")) == NULL) || r;
+ r = ((glUniform4ui64vNV = (PFNGLUNIFORM4UI64VNVPROC)glewGetProcAddress((const GLubyte*)"glUniform4ui64vNV")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_NV_gpu_shader5 */
+
+#ifdef GL_NV_half_float
+
+static GLboolean _glewInit_GL_NV_half_float (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glColor3hNV = (PFNGLCOLOR3HNVPROC)glewGetProcAddress((const GLubyte*)"glColor3hNV")) == NULL) || r;
+ r = ((glColor3hvNV = (PFNGLCOLOR3HVNVPROC)glewGetProcAddress((const GLubyte*)"glColor3hvNV")) == NULL) || r;
+ r = ((glColor4hNV = (PFNGLCOLOR4HNVPROC)glewGetProcAddress((const GLubyte*)"glColor4hNV")) == NULL) || r;
+ r = ((glColor4hvNV = (PFNGLCOLOR4HVNVPROC)glewGetProcAddress((const GLubyte*)"glColor4hvNV")) == NULL) || r;
+ r = ((glFogCoordhNV = (PFNGLFOGCOORDHNVPROC)glewGetProcAddress((const GLubyte*)"glFogCoordhNV")) == NULL) || r;
+ r = ((glFogCoordhvNV = (PFNGLFOGCOORDHVNVPROC)glewGetProcAddress((const GLubyte*)"glFogCoordhvNV")) == NULL) || r;
+ r = ((glMultiTexCoord1hNV = (PFNGLMULTITEXCOORD1HNVPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord1hNV")) == NULL) || r;
+ r = ((glMultiTexCoord1hvNV = (PFNGLMULTITEXCOORD1HVNVPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord1hvNV")) == NULL) || r;
+ r = ((glMultiTexCoord2hNV = (PFNGLMULTITEXCOORD2HNVPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord2hNV")) == NULL) || r;
+ r = ((glMultiTexCoord2hvNV = (PFNGLMULTITEXCOORD2HVNVPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord2hvNV")) == NULL) || r;
+ r = ((glMultiTexCoord3hNV = (PFNGLMULTITEXCOORD3HNVPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord3hNV")) == NULL) || r;
+ r = ((glMultiTexCoord3hvNV = (PFNGLMULTITEXCOORD3HVNVPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord3hvNV")) == NULL) || r;
+ r = ((glMultiTexCoord4hNV = (PFNGLMULTITEXCOORD4HNVPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord4hNV")) == NULL) || r;
+ r = ((glMultiTexCoord4hvNV = (PFNGLMULTITEXCOORD4HVNVPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord4hvNV")) == NULL) || r;
+ r = ((glNormal3hNV = (PFNGLNORMAL3HNVPROC)glewGetProcAddress((const GLubyte*)"glNormal3hNV")) == NULL) || r;
+ r = ((glNormal3hvNV = (PFNGLNORMAL3HVNVPROC)glewGetProcAddress((const GLubyte*)"glNormal3hvNV")) == NULL) || r;
+ r = ((glSecondaryColor3hNV = (PFNGLSECONDARYCOLOR3HNVPROC)glewGetProcAddress((const GLubyte*)"glSecondaryColor3hNV")) == NULL) || r;
+ r = ((glSecondaryColor3hvNV = (PFNGLSECONDARYCOLOR3HVNVPROC)glewGetProcAddress((const GLubyte*)"glSecondaryColor3hvNV")) == NULL) || r;
+ r = ((glTexCoord1hNV = (PFNGLTEXCOORD1HNVPROC)glewGetProcAddress((const GLubyte*)"glTexCoord1hNV")) == NULL) || r;
+ r = ((glTexCoord1hvNV = (PFNGLTEXCOORD1HVNVPROC)glewGetProcAddress((const GLubyte*)"glTexCoord1hvNV")) == NULL) || r;
+ r = ((glTexCoord2hNV = (PFNGLTEXCOORD2HNVPROC)glewGetProcAddress((const GLubyte*)"glTexCoord2hNV")) == NULL) || r;
+ r = ((glTexCoord2hvNV = (PFNGLTEXCOORD2HVNVPROC)glewGetProcAddress((const GLubyte*)"glTexCoord2hvNV")) == NULL) || r;
+ r = ((glTexCoord3hNV = (PFNGLTEXCOORD3HNVPROC)glewGetProcAddress((const GLubyte*)"glTexCoord3hNV")) == NULL) || r;
+ r = ((glTexCoord3hvNV = (PFNGLTEXCOORD3HVNVPROC)glewGetProcAddress((const GLubyte*)"glTexCoord3hvNV")) == NULL) || r;
+ r = ((glTexCoord4hNV = (PFNGLTEXCOORD4HNVPROC)glewGetProcAddress((const GLubyte*)"glTexCoord4hNV")) == NULL) || r;
+ r = ((glTexCoord4hvNV = (PFNGLTEXCOORD4HVNVPROC)glewGetProcAddress((const GLubyte*)"glTexCoord4hvNV")) == NULL) || r;
+ r = ((glVertex2hNV = (PFNGLVERTEX2HNVPROC)glewGetProcAddress((const GLubyte*)"glVertex2hNV")) == NULL) || r;
+ r = ((glVertex2hvNV = (PFNGLVERTEX2HVNVPROC)glewGetProcAddress((const GLubyte*)"glVertex2hvNV")) == NULL) || r;
+ r = ((glVertex3hNV = (PFNGLVERTEX3HNVPROC)glewGetProcAddress((const GLubyte*)"glVertex3hNV")) == NULL) || r;
+ r = ((glVertex3hvNV = (PFNGLVERTEX3HVNVPROC)glewGetProcAddress((const GLubyte*)"glVertex3hvNV")) == NULL) || r;
+ r = ((glVertex4hNV = (PFNGLVERTEX4HNVPROC)glewGetProcAddress((const GLubyte*)"glVertex4hNV")) == NULL) || r;
+ r = ((glVertex4hvNV = (PFNGLVERTEX4HVNVPROC)glewGetProcAddress((const GLubyte*)"glVertex4hvNV")) == NULL) || r;
+ r = ((glVertexAttrib1hNV = (PFNGLVERTEXATTRIB1HNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib1hNV")) == NULL) || r;
+ r = ((glVertexAttrib1hvNV = (PFNGLVERTEXATTRIB1HVNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib1hvNV")) == NULL) || r;
+ r = ((glVertexAttrib2hNV = (PFNGLVERTEXATTRIB2HNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib2hNV")) == NULL) || r;
+ r = ((glVertexAttrib2hvNV = (PFNGLVERTEXATTRIB2HVNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib2hvNV")) == NULL) || r;
+ r = ((glVertexAttrib3hNV = (PFNGLVERTEXATTRIB3HNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib3hNV")) == NULL) || r;
+ r = ((glVertexAttrib3hvNV = (PFNGLVERTEXATTRIB3HVNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib3hvNV")) == NULL) || r;
+ r = ((glVertexAttrib4hNV = (PFNGLVERTEXATTRIB4HNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4hNV")) == NULL) || r;
+ r = ((glVertexAttrib4hvNV = (PFNGLVERTEXATTRIB4HVNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4hvNV")) == NULL) || r;
+ r = ((glVertexAttribs1hvNV = (PFNGLVERTEXATTRIBS1HVNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribs1hvNV")) == NULL) || r;
+ r = ((glVertexAttribs2hvNV = (PFNGLVERTEXATTRIBS2HVNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribs2hvNV")) == NULL) || r;
+ r = ((glVertexAttribs3hvNV = (PFNGLVERTEXATTRIBS3HVNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribs3hvNV")) == NULL) || r;
+ r = ((glVertexAttribs4hvNV = (PFNGLVERTEXATTRIBS4HVNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribs4hvNV")) == NULL) || r;
+ r = ((glVertexWeighthNV = (PFNGLVERTEXWEIGHTHNVPROC)glewGetProcAddress((const GLubyte*)"glVertexWeighthNV")) == NULL) || r;
+ r = ((glVertexWeighthvNV = (PFNGLVERTEXWEIGHTHVNVPROC)glewGetProcAddress((const GLubyte*)"glVertexWeighthvNV")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_NV_half_float */
+
+#ifdef GL_NV_light_max_exponent
+
+#endif /* GL_NV_light_max_exponent */
+
+#ifdef GL_NV_multisample_coverage
+
+#endif /* GL_NV_multisample_coverage */
+
+#ifdef GL_NV_multisample_filter_hint
+
+#endif /* GL_NV_multisample_filter_hint */
+
+#ifdef GL_NV_occlusion_query
+
+static GLboolean _glewInit_GL_NV_occlusion_query (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glBeginOcclusionQueryNV = (PFNGLBEGINOCCLUSIONQUERYNVPROC)glewGetProcAddress((const GLubyte*)"glBeginOcclusionQueryNV")) == NULL) || r;
+ r = ((glDeleteOcclusionQueriesNV = (PFNGLDELETEOCCLUSIONQUERIESNVPROC)glewGetProcAddress((const GLubyte*)"glDeleteOcclusionQueriesNV")) == NULL) || r;
+ r = ((glEndOcclusionQueryNV = (PFNGLENDOCCLUSIONQUERYNVPROC)glewGetProcAddress((const GLubyte*)"glEndOcclusionQueryNV")) == NULL) || r;
+ r = ((glGenOcclusionQueriesNV = (PFNGLGENOCCLUSIONQUERIESNVPROC)glewGetProcAddress((const GLubyte*)"glGenOcclusionQueriesNV")) == NULL) || r;
+ r = ((glGetOcclusionQueryivNV = (PFNGLGETOCCLUSIONQUERYIVNVPROC)glewGetProcAddress((const GLubyte*)"glGetOcclusionQueryivNV")) == NULL) || r;
+ r = ((glGetOcclusionQueryuivNV = (PFNGLGETOCCLUSIONQUERYUIVNVPROC)glewGetProcAddress((const GLubyte*)"glGetOcclusionQueryuivNV")) == NULL) || r;
+ r = ((glIsOcclusionQueryNV = (PFNGLISOCCLUSIONQUERYNVPROC)glewGetProcAddress((const GLubyte*)"glIsOcclusionQueryNV")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_NV_occlusion_query */
+
+#ifdef GL_NV_packed_depth_stencil
+
+#endif /* GL_NV_packed_depth_stencil */
+
+#ifdef GL_NV_parameter_buffer_object
+
+static GLboolean _glewInit_GL_NV_parameter_buffer_object (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glProgramBufferParametersIivNV = (PFNGLPROGRAMBUFFERPARAMETERSIIVNVPROC)glewGetProcAddress((const GLubyte*)"glProgramBufferParametersIivNV")) == NULL) || r;
+ r = ((glProgramBufferParametersIuivNV = (PFNGLPROGRAMBUFFERPARAMETERSIUIVNVPROC)glewGetProcAddress((const GLubyte*)"glProgramBufferParametersIuivNV")) == NULL) || r;
+ r = ((glProgramBufferParametersfvNV = (PFNGLPROGRAMBUFFERPARAMETERSFVNVPROC)glewGetProcAddress((const GLubyte*)"glProgramBufferParametersfvNV")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_NV_parameter_buffer_object */
+
+#ifdef GL_NV_parameter_buffer_object2
+
+#endif /* GL_NV_parameter_buffer_object2 */
+
+#ifdef GL_NV_path_rendering
+
+static GLboolean _glewInit_GL_NV_path_rendering (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glCopyPathNV = (PFNGLCOPYPATHNVPROC)glewGetProcAddress((const GLubyte*)"glCopyPathNV")) == NULL) || r;
+ r = ((glCoverFillPathInstancedNV = (PFNGLCOVERFILLPATHINSTANCEDNVPROC)glewGetProcAddress((const GLubyte*)"glCoverFillPathInstancedNV")) == NULL) || r;
+ r = ((glCoverFillPathNV = (PFNGLCOVERFILLPATHNVPROC)glewGetProcAddress((const GLubyte*)"glCoverFillPathNV")) == NULL) || r;
+ r = ((glCoverStrokePathInstancedNV = (PFNGLCOVERSTROKEPATHINSTANCEDNVPROC)glewGetProcAddress((const GLubyte*)"glCoverStrokePathInstancedNV")) == NULL) || r;
+ r = ((glCoverStrokePathNV = (PFNGLCOVERSTROKEPATHNVPROC)glewGetProcAddress((const GLubyte*)"glCoverStrokePathNV")) == NULL) || r;
+ r = ((glDeletePathsNV = (PFNGLDELETEPATHSNVPROC)glewGetProcAddress((const GLubyte*)"glDeletePathsNV")) == NULL) || r;
+ r = ((glGenPathsNV = (PFNGLGENPATHSNVPROC)glewGetProcAddress((const GLubyte*)"glGenPathsNV")) == NULL) || r;
+ r = ((glGetPathColorGenfvNV = (PFNGLGETPATHCOLORGENFVNVPROC)glewGetProcAddress((const GLubyte*)"glGetPathColorGenfvNV")) == NULL) || r;
+ r = ((glGetPathColorGenivNV = (PFNGLGETPATHCOLORGENIVNVPROC)glewGetProcAddress((const GLubyte*)"glGetPathColorGenivNV")) == NULL) || r;
+ r = ((glGetPathCommandsNV = (PFNGLGETPATHCOMMANDSNVPROC)glewGetProcAddress((const GLubyte*)"glGetPathCommandsNV")) == NULL) || r;
+ r = ((glGetPathCoordsNV = (PFNGLGETPATHCOORDSNVPROC)glewGetProcAddress((const GLubyte*)"glGetPathCoordsNV")) == NULL) || r;
+ r = ((glGetPathDashArrayNV = (PFNGLGETPATHDASHARRAYNVPROC)glewGetProcAddress((const GLubyte*)"glGetPathDashArrayNV")) == NULL) || r;
+ r = ((glGetPathLengthNV = (PFNGLGETPATHLENGTHNVPROC)glewGetProcAddress((const GLubyte*)"glGetPathLengthNV")) == NULL) || r;
+ r = ((glGetPathMetricRangeNV = (PFNGLGETPATHMETRICRANGENVPROC)glewGetProcAddress((const GLubyte*)"glGetPathMetricRangeNV")) == NULL) || r;
+ r = ((glGetPathMetricsNV = (PFNGLGETPATHMETRICSNVPROC)glewGetProcAddress((const GLubyte*)"glGetPathMetricsNV")) == NULL) || r;
+ r = ((glGetPathParameterfvNV = (PFNGLGETPATHPARAMETERFVNVPROC)glewGetProcAddress((const GLubyte*)"glGetPathParameterfvNV")) == NULL) || r;
+ r = ((glGetPathParameterivNV = (PFNGLGETPATHPARAMETERIVNVPROC)glewGetProcAddress((const GLubyte*)"glGetPathParameterivNV")) == NULL) || r;
+ r = ((glGetPathSpacingNV = (PFNGLGETPATHSPACINGNVPROC)glewGetProcAddress((const GLubyte*)"glGetPathSpacingNV")) == NULL) || r;
+ r = ((glGetPathTexGenfvNV = (PFNGLGETPATHTEXGENFVNVPROC)glewGetProcAddress((const GLubyte*)"glGetPathTexGenfvNV")) == NULL) || r;
+ r = ((glGetPathTexGenivNV = (PFNGLGETPATHTEXGENIVNVPROC)glewGetProcAddress((const GLubyte*)"glGetPathTexGenivNV")) == NULL) || r;
+ r = ((glInterpolatePathsNV = (PFNGLINTERPOLATEPATHSNVPROC)glewGetProcAddress((const GLubyte*)"glInterpolatePathsNV")) == NULL) || r;
+ r = ((glIsPathNV = (PFNGLISPATHNVPROC)glewGetProcAddress((const GLubyte*)"glIsPathNV")) == NULL) || r;
+ r = ((glIsPointInFillPathNV = (PFNGLISPOINTINFILLPATHNVPROC)glewGetProcAddress((const GLubyte*)"glIsPointInFillPathNV")) == NULL) || r;
+ r = ((glIsPointInStrokePathNV = (PFNGLISPOINTINSTROKEPATHNVPROC)glewGetProcAddress((const GLubyte*)"glIsPointInStrokePathNV")) == NULL) || r;
+ r = ((glPathColorGenNV = (PFNGLPATHCOLORGENNVPROC)glewGetProcAddress((const GLubyte*)"glPathColorGenNV")) == NULL) || r;
+ r = ((glPathCommandsNV = (PFNGLPATHCOMMANDSNVPROC)glewGetProcAddress((const GLubyte*)"glPathCommandsNV")) == NULL) || r;
+ r = ((glPathCoordsNV = (PFNGLPATHCOORDSNVPROC)glewGetProcAddress((const GLubyte*)"glPathCoordsNV")) == NULL) || r;
+ r = ((glPathCoverDepthFuncNV = (PFNGLPATHCOVERDEPTHFUNCNVPROC)glewGetProcAddress((const GLubyte*)"glPathCoverDepthFuncNV")) == NULL) || r;
+ r = ((glPathDashArrayNV = (PFNGLPATHDASHARRAYNVPROC)glewGetProcAddress((const GLubyte*)"glPathDashArrayNV")) == NULL) || r;
+ r = ((glPathFogGenNV = (PFNGLPATHFOGGENNVPROC)glewGetProcAddress((const GLubyte*)"glPathFogGenNV")) == NULL) || r;
+ r = ((glPathGlyphRangeNV = (PFNGLPATHGLYPHRANGENVPROC)glewGetProcAddress((const GLubyte*)"glPathGlyphRangeNV")) == NULL) || r;
+ r = ((glPathGlyphsNV = (PFNGLPATHGLYPHSNVPROC)glewGetProcAddress((const GLubyte*)"glPathGlyphsNV")) == NULL) || r;
+ r = ((glPathParameterfNV = (PFNGLPATHPARAMETERFNVPROC)glewGetProcAddress((const GLubyte*)"glPathParameterfNV")) == NULL) || r;
+ r = ((glPathParameterfvNV = (PFNGLPATHPARAMETERFVNVPROC)glewGetProcAddress((const GLubyte*)"glPathParameterfvNV")) == NULL) || r;
+ r = ((glPathParameteriNV = (PFNGLPATHPARAMETERINVPROC)glewGetProcAddress((const GLubyte*)"glPathParameteriNV")) == NULL) || r;
+ r = ((glPathParameterivNV = (PFNGLPATHPARAMETERIVNVPROC)glewGetProcAddress((const GLubyte*)"glPathParameterivNV")) == NULL) || r;
+ r = ((glPathStencilDepthOffsetNV = (PFNGLPATHSTENCILDEPTHOFFSETNVPROC)glewGetProcAddress((const GLubyte*)"glPathStencilDepthOffsetNV")) == NULL) || r;
+ r = ((glPathStencilFuncNV = (PFNGLPATHSTENCILFUNCNVPROC)glewGetProcAddress((const GLubyte*)"glPathStencilFuncNV")) == NULL) || r;
+ r = ((glPathStringNV = (PFNGLPATHSTRINGNVPROC)glewGetProcAddress((const GLubyte*)"glPathStringNV")) == NULL) || r;
+ r = ((glPathSubCommandsNV = (PFNGLPATHSUBCOMMANDSNVPROC)glewGetProcAddress((const GLubyte*)"glPathSubCommandsNV")) == NULL) || r;
+ r = ((glPathSubCoordsNV = (PFNGLPATHSUBCOORDSNVPROC)glewGetProcAddress((const GLubyte*)"glPathSubCoordsNV")) == NULL) || r;
+ r = ((glPathTexGenNV = (PFNGLPATHTEXGENNVPROC)glewGetProcAddress((const GLubyte*)"glPathTexGenNV")) == NULL) || r;
+ r = ((glPointAlongPathNV = (PFNGLPOINTALONGPATHNVPROC)glewGetProcAddress((const GLubyte*)"glPointAlongPathNV")) == NULL) || r;
+ r = ((glStencilFillPathInstancedNV = (PFNGLSTENCILFILLPATHINSTANCEDNVPROC)glewGetProcAddress((const GLubyte*)"glStencilFillPathInstancedNV")) == NULL) || r;
+ r = ((glStencilFillPathNV = (PFNGLSTENCILFILLPATHNVPROC)glewGetProcAddress((const GLubyte*)"glStencilFillPathNV")) == NULL) || r;
+ r = ((glStencilStrokePathInstancedNV = (PFNGLSTENCILSTROKEPATHINSTANCEDNVPROC)glewGetProcAddress((const GLubyte*)"glStencilStrokePathInstancedNV")) == NULL) || r;
+ r = ((glStencilStrokePathNV = (PFNGLSTENCILSTROKEPATHNVPROC)glewGetProcAddress((const GLubyte*)"glStencilStrokePathNV")) == NULL) || r;
+ r = ((glTransformPathNV = (PFNGLTRANSFORMPATHNVPROC)glewGetProcAddress((const GLubyte*)"glTransformPathNV")) == NULL) || r;
+ r = ((glWeightPathsNV = (PFNGLWEIGHTPATHSNVPROC)glewGetProcAddress((const GLubyte*)"glWeightPathsNV")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_NV_path_rendering */
+
+#ifdef GL_NV_pixel_data_range
+
+static GLboolean _glewInit_GL_NV_pixel_data_range (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glFlushPixelDataRangeNV = (PFNGLFLUSHPIXELDATARANGENVPROC)glewGetProcAddress((const GLubyte*)"glFlushPixelDataRangeNV")) == NULL) || r;
+ r = ((glPixelDataRangeNV = (PFNGLPIXELDATARANGENVPROC)glewGetProcAddress((const GLubyte*)"glPixelDataRangeNV")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_NV_pixel_data_range */
+
+#ifdef GL_NV_point_sprite
+
+static GLboolean _glewInit_GL_NV_point_sprite (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glPointParameteriNV = (PFNGLPOINTPARAMETERINVPROC)glewGetProcAddress((const GLubyte*)"glPointParameteriNV")) == NULL) || r;
+ r = ((glPointParameterivNV = (PFNGLPOINTPARAMETERIVNVPROC)glewGetProcAddress((const GLubyte*)"glPointParameterivNV")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_NV_point_sprite */
+
+#ifdef GL_NV_present_video
+
+static GLboolean _glewInit_GL_NV_present_video (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glGetVideoi64vNV = (PFNGLGETVIDEOI64VNVPROC)glewGetProcAddress((const GLubyte*)"glGetVideoi64vNV")) == NULL) || r;
+ r = ((glGetVideoivNV = (PFNGLGETVIDEOIVNVPROC)glewGetProcAddress((const GLubyte*)"glGetVideoivNV")) == NULL) || r;
+ r = ((glGetVideoui64vNV = (PFNGLGETVIDEOUI64VNVPROC)glewGetProcAddress((const GLubyte*)"glGetVideoui64vNV")) == NULL) || r;
+ r = ((glGetVideouivNV = (PFNGLGETVIDEOUIVNVPROC)glewGetProcAddress((const GLubyte*)"glGetVideouivNV")) == NULL) || r;
+ r = ((glPresentFrameDualFillNV = (PFNGLPRESENTFRAMEDUALFILLNVPROC)glewGetProcAddress((const GLubyte*)"glPresentFrameDualFillNV")) == NULL) || r;
+ r = ((glPresentFrameKeyedNV = (PFNGLPRESENTFRAMEKEYEDNVPROC)glewGetProcAddress((const GLubyte*)"glPresentFrameKeyedNV")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_NV_present_video */
+
+#ifdef GL_NV_primitive_restart
+
+static GLboolean _glewInit_GL_NV_primitive_restart (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glPrimitiveRestartIndexNV = (PFNGLPRIMITIVERESTARTINDEXNVPROC)glewGetProcAddress((const GLubyte*)"glPrimitiveRestartIndexNV")) == NULL) || r;
+ r = ((glPrimitiveRestartNV = (PFNGLPRIMITIVERESTARTNVPROC)glewGetProcAddress((const GLubyte*)"glPrimitiveRestartNV")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_NV_primitive_restart */
+
+#ifdef GL_NV_register_combiners
+
+static GLboolean _glewInit_GL_NV_register_combiners (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glCombinerInputNV = (PFNGLCOMBINERINPUTNVPROC)glewGetProcAddress((const GLubyte*)"glCombinerInputNV")) == NULL) || r;
+ r = ((glCombinerOutputNV = (PFNGLCOMBINEROUTPUTNVPROC)glewGetProcAddress((const GLubyte*)"glCombinerOutputNV")) == NULL) || r;
+ r = ((glCombinerParameterfNV = (PFNGLCOMBINERPARAMETERFNVPROC)glewGetProcAddress((const GLubyte*)"glCombinerParameterfNV")) == NULL) || r;
+ r = ((glCombinerParameterfvNV = (PFNGLCOMBINERPARAMETERFVNVPROC)glewGetProcAddress((const GLubyte*)"glCombinerParameterfvNV")) == NULL) || r;
+ r = ((glCombinerParameteriNV = (PFNGLCOMBINERPARAMETERINVPROC)glewGetProcAddress((const GLubyte*)"glCombinerParameteriNV")) == NULL) || r;
+ r = ((glCombinerParameterivNV = (PFNGLCOMBINERPARAMETERIVNVPROC)glewGetProcAddress((const GLubyte*)"glCombinerParameterivNV")) == NULL) || r;
+ r = ((glFinalCombinerInputNV = (PFNGLFINALCOMBINERINPUTNVPROC)glewGetProcAddress((const GLubyte*)"glFinalCombinerInputNV")) == NULL) || r;
+ r = ((glGetCombinerInputParameterfvNV = (PFNGLGETCOMBINERINPUTPARAMETERFVNVPROC)glewGetProcAddress((const GLubyte*)"glGetCombinerInputParameterfvNV")) == NULL) || r;
+ r = ((glGetCombinerInputParameterivNV = (PFNGLGETCOMBINERINPUTPARAMETERIVNVPROC)glewGetProcAddress((const GLubyte*)"glGetCombinerInputParameterivNV")) == NULL) || r;
+ r = ((glGetCombinerOutputParameterfvNV = (PFNGLGETCOMBINEROUTPUTPARAMETERFVNVPROC)glewGetProcAddress((const GLubyte*)"glGetCombinerOutputParameterfvNV")) == NULL) || r;
+ r = ((glGetCombinerOutputParameterivNV = (PFNGLGETCOMBINEROUTPUTPARAMETERIVNVPROC)glewGetProcAddress((const GLubyte*)"glGetCombinerOutputParameterivNV")) == NULL) || r;
+ r = ((glGetFinalCombinerInputParameterfvNV = (PFNGLGETFINALCOMBINERINPUTPARAMETERFVNVPROC)glewGetProcAddress((const GLubyte*)"glGetFinalCombinerInputParameterfvNV")) == NULL) || r;
+ r = ((glGetFinalCombinerInputParameterivNV = (PFNGLGETFINALCOMBINERINPUTPARAMETERIVNVPROC)glewGetProcAddress((const GLubyte*)"glGetFinalCombinerInputParameterivNV")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_NV_register_combiners */
+
+#ifdef GL_NV_register_combiners2
+
+static GLboolean _glewInit_GL_NV_register_combiners2 (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glCombinerStageParameterfvNV = (PFNGLCOMBINERSTAGEPARAMETERFVNVPROC)glewGetProcAddress((const GLubyte*)"glCombinerStageParameterfvNV")) == NULL) || r;
+ r = ((glGetCombinerStageParameterfvNV = (PFNGLGETCOMBINERSTAGEPARAMETERFVNVPROC)glewGetProcAddress((const GLubyte*)"glGetCombinerStageParameterfvNV")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_NV_register_combiners2 */
+
+#ifdef GL_NV_shader_atomic_counters
+
+#endif /* GL_NV_shader_atomic_counters */
+
+#ifdef GL_NV_shader_atomic_float
+
+#endif /* GL_NV_shader_atomic_float */
+
+#ifdef GL_NV_shader_buffer_load
+
+static GLboolean _glewInit_GL_NV_shader_buffer_load (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glGetBufferParameterui64vNV = (PFNGLGETBUFFERPARAMETERUI64VNVPROC)glewGetProcAddress((const GLubyte*)"glGetBufferParameterui64vNV")) == NULL) || r;
+ r = ((glGetIntegerui64vNV = (PFNGLGETINTEGERUI64VNVPROC)glewGetProcAddress((const GLubyte*)"glGetIntegerui64vNV")) == NULL) || r;
+ r = ((glGetNamedBufferParameterui64vNV = (PFNGLGETNAMEDBUFFERPARAMETERUI64VNVPROC)glewGetProcAddress((const GLubyte*)"glGetNamedBufferParameterui64vNV")) == NULL) || r;
+ r = ((glIsBufferResidentNV = (PFNGLISBUFFERRESIDENTNVPROC)glewGetProcAddress((const GLubyte*)"glIsBufferResidentNV")) == NULL) || r;
+ r = ((glIsNamedBufferResidentNV = (PFNGLISNAMEDBUFFERRESIDENTNVPROC)glewGetProcAddress((const GLubyte*)"glIsNamedBufferResidentNV")) == NULL) || r;
+ r = ((glMakeBufferNonResidentNV = (PFNGLMAKEBUFFERNONRESIDENTNVPROC)glewGetProcAddress((const GLubyte*)"glMakeBufferNonResidentNV")) == NULL) || r;
+ r = ((glMakeBufferResidentNV = (PFNGLMAKEBUFFERRESIDENTNVPROC)glewGetProcAddress((const GLubyte*)"glMakeBufferResidentNV")) == NULL) || r;
+ r = ((glMakeNamedBufferNonResidentNV = (PFNGLMAKENAMEDBUFFERNONRESIDENTNVPROC)glewGetProcAddress((const GLubyte*)"glMakeNamedBufferNonResidentNV")) == NULL) || r;
+ r = ((glMakeNamedBufferResidentNV = (PFNGLMAKENAMEDBUFFERRESIDENTNVPROC)glewGetProcAddress((const GLubyte*)"glMakeNamedBufferResidentNV")) == NULL) || r;
+ r = ((glProgramUniformui64NV = (PFNGLPROGRAMUNIFORMUI64NVPROC)glewGetProcAddress((const GLubyte*)"glProgramUniformui64NV")) == NULL) || r;
+ r = ((glProgramUniformui64vNV = (PFNGLPROGRAMUNIFORMUI64VNVPROC)glewGetProcAddress((const GLubyte*)"glProgramUniformui64vNV")) == NULL) || r;
+ r = ((glUniformui64NV = (PFNGLUNIFORMUI64NVPROC)glewGetProcAddress((const GLubyte*)"glUniformui64NV")) == NULL) || r;
+ r = ((glUniformui64vNV = (PFNGLUNIFORMUI64VNVPROC)glewGetProcAddress((const GLubyte*)"glUniformui64vNV")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_NV_shader_buffer_load */
+
+#ifdef GL_NV_shader_storage_buffer_object
+
+#endif /* GL_NV_shader_storage_buffer_object */
+
+#ifdef GL_NV_tessellation_program5
+
+#endif /* GL_NV_tessellation_program5 */
+
+#ifdef GL_NV_texgen_emboss
+
+#endif /* GL_NV_texgen_emboss */
+
+#ifdef GL_NV_texgen_reflection
+
+#endif /* GL_NV_texgen_reflection */
+
+#ifdef GL_NV_texture_barrier
+
+static GLboolean _glewInit_GL_NV_texture_barrier (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glTextureBarrierNV = (PFNGLTEXTUREBARRIERNVPROC)glewGetProcAddress((const GLubyte*)"glTextureBarrierNV")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_NV_texture_barrier */
+
+#ifdef GL_NV_texture_compression_vtc
+
+#endif /* GL_NV_texture_compression_vtc */
+
+#ifdef GL_NV_texture_env_combine4
+
+#endif /* GL_NV_texture_env_combine4 */
+
+#ifdef GL_NV_texture_expand_normal
+
+#endif /* GL_NV_texture_expand_normal */
+
+#ifdef GL_NV_texture_multisample
+
+static GLboolean _glewInit_GL_NV_texture_multisample (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glTexImage2DMultisampleCoverageNV = (PFNGLTEXIMAGE2DMULTISAMPLECOVERAGENVPROC)glewGetProcAddress((const GLubyte*)"glTexImage2DMultisampleCoverageNV")) == NULL) || r;
+ r = ((glTexImage3DMultisampleCoverageNV = (PFNGLTEXIMAGE3DMULTISAMPLECOVERAGENVPROC)glewGetProcAddress((const GLubyte*)"glTexImage3DMultisampleCoverageNV")) == NULL) || r;
+ r = ((glTextureImage2DMultisampleCoverageNV = (PFNGLTEXTUREIMAGE2DMULTISAMPLECOVERAGENVPROC)glewGetProcAddress((const GLubyte*)"glTextureImage2DMultisampleCoverageNV")) == NULL) || r;
+ r = ((glTextureImage2DMultisampleNV = (PFNGLTEXTUREIMAGE2DMULTISAMPLENVPROC)glewGetProcAddress((const GLubyte*)"glTextureImage2DMultisampleNV")) == NULL) || r;
+ r = ((glTextureImage3DMultisampleCoverageNV = (PFNGLTEXTUREIMAGE3DMULTISAMPLECOVERAGENVPROC)glewGetProcAddress((const GLubyte*)"glTextureImage3DMultisampleCoverageNV")) == NULL) || r;
+ r = ((glTextureImage3DMultisampleNV = (PFNGLTEXTUREIMAGE3DMULTISAMPLENVPROC)glewGetProcAddress((const GLubyte*)"glTextureImage3DMultisampleNV")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_NV_texture_multisample */
+
+#ifdef GL_NV_texture_rectangle
+
+#endif /* GL_NV_texture_rectangle */
+
+#ifdef GL_NV_texture_shader
+
+#endif /* GL_NV_texture_shader */
+
+#ifdef GL_NV_texture_shader2
+
+#endif /* GL_NV_texture_shader2 */
+
+#ifdef GL_NV_texture_shader3
+
+#endif /* GL_NV_texture_shader3 */
+
+#ifdef GL_NV_transform_feedback
+
+static GLboolean _glewInit_GL_NV_transform_feedback (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glActiveVaryingNV = (PFNGLACTIVEVARYINGNVPROC)glewGetProcAddress((const GLubyte*)"glActiveVaryingNV")) == NULL) || r;
+ r = ((glBeginTransformFeedbackNV = (PFNGLBEGINTRANSFORMFEEDBACKNVPROC)glewGetProcAddress((const GLubyte*)"glBeginTransformFeedbackNV")) == NULL) || r;
+ r = ((glBindBufferBaseNV = (PFNGLBINDBUFFERBASENVPROC)glewGetProcAddress((const GLubyte*)"glBindBufferBaseNV")) == NULL) || r;
+ r = ((glBindBufferOffsetNV = (PFNGLBINDBUFFEROFFSETNVPROC)glewGetProcAddress((const GLubyte*)"glBindBufferOffsetNV")) == NULL) || r;
+ r = ((glBindBufferRangeNV = (PFNGLBINDBUFFERRANGENVPROC)glewGetProcAddress((const GLubyte*)"glBindBufferRangeNV")) == NULL) || r;
+ r = ((glEndTransformFeedbackNV = (PFNGLENDTRANSFORMFEEDBACKNVPROC)glewGetProcAddress((const GLubyte*)"glEndTransformFeedbackNV")) == NULL) || r;
+ r = ((glGetActiveVaryingNV = (PFNGLGETACTIVEVARYINGNVPROC)glewGetProcAddress((const GLubyte*)"glGetActiveVaryingNV")) == NULL) || r;
+ r = ((glGetTransformFeedbackVaryingNV = (PFNGLGETTRANSFORMFEEDBACKVARYINGNVPROC)glewGetProcAddress((const GLubyte*)"glGetTransformFeedbackVaryingNV")) == NULL) || r;
+ r = ((glGetVaryingLocationNV = (PFNGLGETVARYINGLOCATIONNVPROC)glewGetProcAddress((const GLubyte*)"glGetVaryingLocationNV")) == NULL) || r;
+ r = ((glTransformFeedbackAttribsNV = (PFNGLTRANSFORMFEEDBACKATTRIBSNVPROC)glewGetProcAddress((const GLubyte*)"glTransformFeedbackAttribsNV")) == NULL) || r;
+ r = ((glTransformFeedbackVaryingsNV = (PFNGLTRANSFORMFEEDBACKVARYINGSNVPROC)glewGetProcAddress((const GLubyte*)"glTransformFeedbackVaryingsNV")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_NV_transform_feedback */
+
+#ifdef GL_NV_transform_feedback2
+
+static GLboolean _glewInit_GL_NV_transform_feedback2 (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glBindTransformFeedbackNV = (PFNGLBINDTRANSFORMFEEDBACKNVPROC)glewGetProcAddress((const GLubyte*)"glBindTransformFeedbackNV")) == NULL) || r;
+ r = ((glDeleteTransformFeedbacksNV = (PFNGLDELETETRANSFORMFEEDBACKSNVPROC)glewGetProcAddress((const GLubyte*)"glDeleteTransformFeedbacksNV")) == NULL) || r;
+ r = ((glDrawTransformFeedbackNV = (PFNGLDRAWTRANSFORMFEEDBACKNVPROC)glewGetProcAddress((const GLubyte*)"glDrawTransformFeedbackNV")) == NULL) || r;
+ r = ((glGenTransformFeedbacksNV = (PFNGLGENTRANSFORMFEEDBACKSNVPROC)glewGetProcAddress((const GLubyte*)"glGenTransformFeedbacksNV")) == NULL) || r;
+ r = ((glIsTransformFeedbackNV = (PFNGLISTRANSFORMFEEDBACKNVPROC)glewGetProcAddress((const GLubyte*)"glIsTransformFeedbackNV")) == NULL) || r;
+ r = ((glPauseTransformFeedbackNV = (PFNGLPAUSETRANSFORMFEEDBACKNVPROC)glewGetProcAddress((const GLubyte*)"glPauseTransformFeedbackNV")) == NULL) || r;
+ r = ((glResumeTransformFeedbackNV = (PFNGLRESUMETRANSFORMFEEDBACKNVPROC)glewGetProcAddress((const GLubyte*)"glResumeTransformFeedbackNV")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_NV_transform_feedback2 */
+
+#ifdef GL_NV_vdpau_interop
+
+static GLboolean _glewInit_GL_NV_vdpau_interop (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glVDPAUFiniNV = (PFNGLVDPAUFININVPROC)glewGetProcAddress((const GLubyte*)"glVDPAUFiniNV")) == NULL) || r;
+ r = ((glVDPAUGetSurfaceivNV = (PFNGLVDPAUGETSURFACEIVNVPROC)glewGetProcAddress((const GLubyte*)"glVDPAUGetSurfaceivNV")) == NULL) || r;
+ r = ((glVDPAUInitNV = (PFNGLVDPAUINITNVPROC)glewGetProcAddress((const GLubyte*)"glVDPAUInitNV")) == NULL) || r;
+ r = ((glVDPAUIsSurfaceNV = (PFNGLVDPAUISSURFACENVPROC)glewGetProcAddress((const GLubyte*)"glVDPAUIsSurfaceNV")) == NULL) || r;
+ r = ((glVDPAUMapSurfacesNV = (PFNGLVDPAUMAPSURFACESNVPROC)glewGetProcAddress((const GLubyte*)"glVDPAUMapSurfacesNV")) == NULL) || r;
+ r = ((glVDPAURegisterOutputSurfaceNV = (PFNGLVDPAUREGISTEROUTPUTSURFACENVPROC)glewGetProcAddress((const GLubyte*)"glVDPAURegisterOutputSurfaceNV")) == NULL) || r;
+ r = ((glVDPAURegisterVideoSurfaceNV = (PFNGLVDPAUREGISTERVIDEOSURFACENVPROC)glewGetProcAddress((const GLubyte*)"glVDPAURegisterVideoSurfaceNV")) == NULL) || r;
+ r = ((glVDPAUSurfaceAccessNV = (PFNGLVDPAUSURFACEACCESSNVPROC)glewGetProcAddress((const GLubyte*)"glVDPAUSurfaceAccessNV")) == NULL) || r;
+ r = ((glVDPAUUnmapSurfacesNV = (PFNGLVDPAUUNMAPSURFACESNVPROC)glewGetProcAddress((const GLubyte*)"glVDPAUUnmapSurfacesNV")) == NULL) || r;
+ r = ((glVDPAUUnregisterSurfaceNV = (PFNGLVDPAUUNREGISTERSURFACENVPROC)glewGetProcAddress((const GLubyte*)"glVDPAUUnregisterSurfaceNV")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_NV_vdpau_interop */
+
+#ifdef GL_NV_vertex_array_range
+
+static GLboolean _glewInit_GL_NV_vertex_array_range (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glFlushVertexArrayRangeNV = (PFNGLFLUSHVERTEXARRAYRANGENVPROC)glewGetProcAddress((const GLubyte*)"glFlushVertexArrayRangeNV")) == NULL) || r;
+ r = ((glVertexArrayRangeNV = (PFNGLVERTEXARRAYRANGENVPROC)glewGetProcAddress((const GLubyte*)"glVertexArrayRangeNV")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_NV_vertex_array_range */
+
+#ifdef GL_NV_vertex_array_range2
+
+#endif /* GL_NV_vertex_array_range2 */
+
+#ifdef GL_NV_vertex_attrib_integer_64bit
+
+static GLboolean _glewInit_GL_NV_vertex_attrib_integer_64bit (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glGetVertexAttribLi64vNV = (PFNGLGETVERTEXATTRIBLI64VNVPROC)glewGetProcAddress((const GLubyte*)"glGetVertexAttribLi64vNV")) == NULL) || r;
+ r = ((glGetVertexAttribLui64vNV = (PFNGLGETVERTEXATTRIBLUI64VNVPROC)glewGetProcAddress((const GLubyte*)"glGetVertexAttribLui64vNV")) == NULL) || r;
+ r = ((glVertexAttribL1i64NV = (PFNGLVERTEXATTRIBL1I64NVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribL1i64NV")) == NULL) || r;
+ r = ((glVertexAttribL1i64vNV = (PFNGLVERTEXATTRIBL1I64VNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribL1i64vNV")) == NULL) || r;
+ r = ((glVertexAttribL1ui64NV = (PFNGLVERTEXATTRIBL1UI64NVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribL1ui64NV")) == NULL) || r;
+ r = ((glVertexAttribL1ui64vNV = (PFNGLVERTEXATTRIBL1UI64VNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribL1ui64vNV")) == NULL) || r;
+ r = ((glVertexAttribL2i64NV = (PFNGLVERTEXATTRIBL2I64NVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribL2i64NV")) == NULL) || r;
+ r = ((glVertexAttribL2i64vNV = (PFNGLVERTEXATTRIBL2I64VNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribL2i64vNV")) == NULL) || r;
+ r = ((glVertexAttribL2ui64NV = (PFNGLVERTEXATTRIBL2UI64NVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribL2ui64NV")) == NULL) || r;
+ r = ((glVertexAttribL2ui64vNV = (PFNGLVERTEXATTRIBL2UI64VNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribL2ui64vNV")) == NULL) || r;
+ r = ((glVertexAttribL3i64NV = (PFNGLVERTEXATTRIBL3I64NVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribL3i64NV")) == NULL) || r;
+ r = ((glVertexAttribL3i64vNV = (PFNGLVERTEXATTRIBL3I64VNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribL3i64vNV")) == NULL) || r;
+ r = ((glVertexAttribL3ui64NV = (PFNGLVERTEXATTRIBL3UI64NVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribL3ui64NV")) == NULL) || r;
+ r = ((glVertexAttribL3ui64vNV = (PFNGLVERTEXATTRIBL3UI64VNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribL3ui64vNV")) == NULL) || r;
+ r = ((glVertexAttribL4i64NV = (PFNGLVERTEXATTRIBL4I64NVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribL4i64NV")) == NULL) || r;
+ r = ((glVertexAttribL4i64vNV = (PFNGLVERTEXATTRIBL4I64VNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribL4i64vNV")) == NULL) || r;
+ r = ((glVertexAttribL4ui64NV = (PFNGLVERTEXATTRIBL4UI64NVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribL4ui64NV")) == NULL) || r;
+ r = ((glVertexAttribL4ui64vNV = (PFNGLVERTEXATTRIBL4UI64VNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribL4ui64vNV")) == NULL) || r;
+ r = ((glVertexAttribLFormatNV = (PFNGLVERTEXATTRIBLFORMATNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribLFormatNV")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_NV_vertex_attrib_integer_64bit */
+
+#ifdef GL_NV_vertex_buffer_unified_memory
+
+static GLboolean _glewInit_GL_NV_vertex_buffer_unified_memory (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glBufferAddressRangeNV = (PFNGLBUFFERADDRESSRANGENVPROC)glewGetProcAddress((const GLubyte*)"glBufferAddressRangeNV")) == NULL) || r;
+ r = ((glColorFormatNV = (PFNGLCOLORFORMATNVPROC)glewGetProcAddress((const GLubyte*)"glColorFormatNV")) == NULL) || r;
+ r = ((glEdgeFlagFormatNV = (PFNGLEDGEFLAGFORMATNVPROC)glewGetProcAddress((const GLubyte*)"glEdgeFlagFormatNV")) == NULL) || r;
+ r = ((glFogCoordFormatNV = (PFNGLFOGCOORDFORMATNVPROC)glewGetProcAddress((const GLubyte*)"glFogCoordFormatNV")) == NULL) || r;
+ r = ((glGetIntegerui64i_vNV = (PFNGLGETINTEGERUI64I_VNVPROC)glewGetProcAddress((const GLubyte*)"glGetIntegerui64i_vNV")) == NULL) || r;
+ r = ((glIndexFormatNV = (PFNGLINDEXFORMATNVPROC)glewGetProcAddress((const GLubyte*)"glIndexFormatNV")) == NULL) || r;
+ r = ((glNormalFormatNV = (PFNGLNORMALFORMATNVPROC)glewGetProcAddress((const GLubyte*)"glNormalFormatNV")) == NULL) || r;
+ r = ((glSecondaryColorFormatNV = (PFNGLSECONDARYCOLORFORMATNVPROC)glewGetProcAddress((const GLubyte*)"glSecondaryColorFormatNV")) == NULL) || r;
+ r = ((glTexCoordFormatNV = (PFNGLTEXCOORDFORMATNVPROC)glewGetProcAddress((const GLubyte*)"glTexCoordFormatNV")) == NULL) || r;
+ r = ((glVertexAttribFormatNV = (PFNGLVERTEXATTRIBFORMATNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribFormatNV")) == NULL) || r;
+ r = ((glVertexAttribIFormatNV = (PFNGLVERTEXATTRIBIFORMATNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribIFormatNV")) == NULL) || r;
+ r = ((glVertexFormatNV = (PFNGLVERTEXFORMATNVPROC)glewGetProcAddress((const GLubyte*)"glVertexFormatNV")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_NV_vertex_buffer_unified_memory */
+
+#ifdef GL_NV_vertex_program
+
+static GLboolean _glewInit_GL_NV_vertex_program (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glAreProgramsResidentNV = (PFNGLAREPROGRAMSRESIDENTNVPROC)glewGetProcAddress((const GLubyte*)"glAreProgramsResidentNV")) == NULL) || r;
+ r = ((glBindProgramNV = (PFNGLBINDPROGRAMNVPROC)glewGetProcAddress((const GLubyte*)"glBindProgramNV")) == NULL) || r;
+ r = ((glDeleteProgramsNV = (PFNGLDELETEPROGRAMSNVPROC)glewGetProcAddress((const GLubyte*)"glDeleteProgramsNV")) == NULL) || r;
+ r = ((glExecuteProgramNV = (PFNGLEXECUTEPROGRAMNVPROC)glewGetProcAddress((const GLubyte*)"glExecuteProgramNV")) == NULL) || r;
+ r = ((glGenProgramsNV = (PFNGLGENPROGRAMSNVPROC)glewGetProcAddress((const GLubyte*)"glGenProgramsNV")) == NULL) || r;
+ r = ((glGetProgramParameterdvNV = (PFNGLGETPROGRAMPARAMETERDVNVPROC)glewGetProcAddress((const GLubyte*)"glGetProgramParameterdvNV")) == NULL) || r;
+ r = ((glGetProgramParameterfvNV = (PFNGLGETPROGRAMPARAMETERFVNVPROC)glewGetProcAddress((const GLubyte*)"glGetProgramParameterfvNV")) == NULL) || r;
+ r = ((glGetProgramStringNV = (PFNGLGETPROGRAMSTRINGNVPROC)glewGetProcAddress((const GLubyte*)"glGetProgramStringNV")) == NULL) || r;
+ r = ((glGetProgramivNV = (PFNGLGETPROGRAMIVNVPROC)glewGetProcAddress((const GLubyte*)"glGetProgramivNV")) == NULL) || r;
+ r = ((glGetTrackMatrixivNV = (PFNGLGETTRACKMATRIXIVNVPROC)glewGetProcAddress((const GLubyte*)"glGetTrackMatrixivNV")) == NULL) || r;
+ r = ((glGetVertexAttribPointervNV = (PFNGLGETVERTEXATTRIBPOINTERVNVPROC)glewGetProcAddress((const GLubyte*)"glGetVertexAttribPointervNV")) == NULL) || r;
+ r = ((glGetVertexAttribdvNV = (PFNGLGETVERTEXATTRIBDVNVPROC)glewGetProcAddress((const GLubyte*)"glGetVertexAttribdvNV")) == NULL) || r;
+ r = ((glGetVertexAttribfvNV = (PFNGLGETVERTEXATTRIBFVNVPROC)glewGetProcAddress((const GLubyte*)"glGetVertexAttribfvNV")) == NULL) || r;
+ r = ((glGetVertexAttribivNV = (PFNGLGETVERTEXATTRIBIVNVPROC)glewGetProcAddress((const GLubyte*)"glGetVertexAttribivNV")) == NULL) || r;
+ r = ((glIsProgramNV = (PFNGLISPROGRAMNVPROC)glewGetProcAddress((const GLubyte*)"glIsProgramNV")) == NULL) || r;
+ r = ((glLoadProgramNV = (PFNGLLOADPROGRAMNVPROC)glewGetProcAddress((const GLubyte*)"glLoadProgramNV")) == NULL) || r;
+ r = ((glProgramParameter4dNV = (PFNGLPROGRAMPARAMETER4DNVPROC)glewGetProcAddress((const GLubyte*)"glProgramParameter4dNV")) == NULL) || r;
+ r = ((glProgramParameter4dvNV = (PFNGLPROGRAMPARAMETER4DVNVPROC)glewGetProcAddress((const GLubyte*)"glProgramParameter4dvNV")) == NULL) || r;
+ r = ((glProgramParameter4fNV = (PFNGLPROGRAMPARAMETER4FNVPROC)glewGetProcAddress((const GLubyte*)"glProgramParameter4fNV")) == NULL) || r;
+ r = ((glProgramParameter4fvNV = (PFNGLPROGRAMPARAMETER4FVNVPROC)glewGetProcAddress((const GLubyte*)"glProgramParameter4fvNV")) == NULL) || r;
+ r = ((glProgramParameters4dvNV = (PFNGLPROGRAMPARAMETERS4DVNVPROC)glewGetProcAddress((const GLubyte*)"glProgramParameters4dvNV")) == NULL) || r;
+ r = ((glProgramParameters4fvNV = (PFNGLPROGRAMPARAMETERS4FVNVPROC)glewGetProcAddress((const GLubyte*)"glProgramParameters4fvNV")) == NULL) || r;
+ r = ((glRequestResidentProgramsNV = (PFNGLREQUESTRESIDENTPROGRAMSNVPROC)glewGetProcAddress((const GLubyte*)"glRequestResidentProgramsNV")) == NULL) || r;
+ r = ((glTrackMatrixNV = (PFNGLTRACKMATRIXNVPROC)glewGetProcAddress((const GLubyte*)"glTrackMatrixNV")) == NULL) || r;
+ r = ((glVertexAttrib1dNV = (PFNGLVERTEXATTRIB1DNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib1dNV")) == NULL) || r;
+ r = ((glVertexAttrib1dvNV = (PFNGLVERTEXATTRIB1DVNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib1dvNV")) == NULL) || r;
+ r = ((glVertexAttrib1fNV = (PFNGLVERTEXATTRIB1FNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib1fNV")) == NULL) || r;
+ r = ((glVertexAttrib1fvNV = (PFNGLVERTEXATTRIB1FVNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib1fvNV")) == NULL) || r;
+ r = ((glVertexAttrib1sNV = (PFNGLVERTEXATTRIB1SNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib1sNV")) == NULL) || r;
+ r = ((glVertexAttrib1svNV = (PFNGLVERTEXATTRIB1SVNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib1svNV")) == NULL) || r;
+ r = ((glVertexAttrib2dNV = (PFNGLVERTEXATTRIB2DNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib2dNV")) == NULL) || r;
+ r = ((glVertexAttrib2dvNV = (PFNGLVERTEXATTRIB2DVNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib2dvNV")) == NULL) || r;
+ r = ((glVertexAttrib2fNV = (PFNGLVERTEXATTRIB2FNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib2fNV")) == NULL) || r;
+ r = ((glVertexAttrib2fvNV = (PFNGLVERTEXATTRIB2FVNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib2fvNV")) == NULL) || r;
+ r = ((glVertexAttrib2sNV = (PFNGLVERTEXATTRIB2SNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib2sNV")) == NULL) || r;
+ r = ((glVertexAttrib2svNV = (PFNGLVERTEXATTRIB2SVNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib2svNV")) == NULL) || r;
+ r = ((glVertexAttrib3dNV = (PFNGLVERTEXATTRIB3DNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib3dNV")) == NULL) || r;
+ r = ((glVertexAttrib3dvNV = (PFNGLVERTEXATTRIB3DVNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib3dvNV")) == NULL) || r;
+ r = ((glVertexAttrib3fNV = (PFNGLVERTEXATTRIB3FNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib3fNV")) == NULL) || r;
+ r = ((glVertexAttrib3fvNV = (PFNGLVERTEXATTRIB3FVNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib3fvNV")) == NULL) || r;
+ r = ((glVertexAttrib3sNV = (PFNGLVERTEXATTRIB3SNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib3sNV")) == NULL) || r;
+ r = ((glVertexAttrib3svNV = (PFNGLVERTEXATTRIB3SVNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib3svNV")) == NULL) || r;
+ r = ((glVertexAttrib4dNV = (PFNGLVERTEXATTRIB4DNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4dNV")) == NULL) || r;
+ r = ((glVertexAttrib4dvNV = (PFNGLVERTEXATTRIB4DVNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4dvNV")) == NULL) || r;
+ r = ((glVertexAttrib4fNV = (PFNGLVERTEXATTRIB4FNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4fNV")) == NULL) || r;
+ r = ((glVertexAttrib4fvNV = (PFNGLVERTEXATTRIB4FVNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4fvNV")) == NULL) || r;
+ r = ((glVertexAttrib4sNV = (PFNGLVERTEXATTRIB4SNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4sNV")) == NULL) || r;
+ r = ((glVertexAttrib4svNV = (PFNGLVERTEXATTRIB4SVNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4svNV")) == NULL) || r;
+ r = ((glVertexAttrib4ubNV = (PFNGLVERTEXATTRIB4UBNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4ubNV")) == NULL) || r;
+ r = ((glVertexAttrib4ubvNV = (PFNGLVERTEXATTRIB4UBVNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4ubvNV")) == NULL) || r;
+ r = ((glVertexAttribPointerNV = (PFNGLVERTEXATTRIBPOINTERNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribPointerNV")) == NULL) || r;
+ r = ((glVertexAttribs1dvNV = (PFNGLVERTEXATTRIBS1DVNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribs1dvNV")) == NULL) || r;
+ r = ((glVertexAttribs1fvNV = (PFNGLVERTEXATTRIBS1FVNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribs1fvNV")) == NULL) || r;
+ r = ((glVertexAttribs1svNV = (PFNGLVERTEXATTRIBS1SVNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribs1svNV")) == NULL) || r;
+ r = ((glVertexAttribs2dvNV = (PFNGLVERTEXATTRIBS2DVNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribs2dvNV")) == NULL) || r;
+ r = ((glVertexAttribs2fvNV = (PFNGLVERTEXATTRIBS2FVNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribs2fvNV")) == NULL) || r;
+ r = ((glVertexAttribs2svNV = (PFNGLVERTEXATTRIBS2SVNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribs2svNV")) == NULL) || r;
+ r = ((glVertexAttribs3dvNV = (PFNGLVERTEXATTRIBS3DVNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribs3dvNV")) == NULL) || r;
+ r = ((glVertexAttribs3fvNV = (PFNGLVERTEXATTRIBS3FVNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribs3fvNV")) == NULL) || r;
+ r = ((glVertexAttribs3svNV = (PFNGLVERTEXATTRIBS3SVNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribs3svNV")) == NULL) || r;
+ r = ((glVertexAttribs4dvNV = (PFNGLVERTEXATTRIBS4DVNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribs4dvNV")) == NULL) || r;
+ r = ((glVertexAttribs4fvNV = (PFNGLVERTEXATTRIBS4FVNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribs4fvNV")) == NULL) || r;
+ r = ((glVertexAttribs4svNV = (PFNGLVERTEXATTRIBS4SVNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribs4svNV")) == NULL) || r;
+ r = ((glVertexAttribs4ubvNV = (PFNGLVERTEXATTRIBS4UBVNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribs4ubvNV")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_NV_vertex_program */
+
+#ifdef GL_NV_vertex_program1_1
+
+#endif /* GL_NV_vertex_program1_1 */
+
+#ifdef GL_NV_vertex_program2
+
+#endif /* GL_NV_vertex_program2 */
+
+#ifdef GL_NV_vertex_program2_option
+
+#endif /* GL_NV_vertex_program2_option */
+
+#ifdef GL_NV_vertex_program3
+
+#endif /* GL_NV_vertex_program3 */
+
+#ifdef GL_NV_vertex_program4
+
+#endif /* GL_NV_vertex_program4 */
+
+#ifdef GL_NV_video_capture
+
+static GLboolean _glewInit_GL_NV_video_capture (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glBeginVideoCaptureNV = (PFNGLBEGINVIDEOCAPTURENVPROC)glewGetProcAddress((const GLubyte*)"glBeginVideoCaptureNV")) == NULL) || r;
+ r = ((glBindVideoCaptureStreamBufferNV = (PFNGLBINDVIDEOCAPTURESTREAMBUFFERNVPROC)glewGetProcAddress((const GLubyte*)"glBindVideoCaptureStreamBufferNV")) == NULL) || r;
+ r = ((glBindVideoCaptureStreamTextureNV = (PFNGLBINDVIDEOCAPTURESTREAMTEXTURENVPROC)glewGetProcAddress((const GLubyte*)"glBindVideoCaptureStreamTextureNV")) == NULL) || r;
+ r = ((glEndVideoCaptureNV = (PFNGLENDVIDEOCAPTURENVPROC)glewGetProcAddress((const GLubyte*)"glEndVideoCaptureNV")) == NULL) || r;
+ r = ((glGetVideoCaptureStreamdvNV = (PFNGLGETVIDEOCAPTURESTREAMDVNVPROC)glewGetProcAddress((const GLubyte*)"glGetVideoCaptureStreamdvNV")) == NULL) || r;
+ r = ((glGetVideoCaptureStreamfvNV = (PFNGLGETVIDEOCAPTURESTREAMFVNVPROC)glewGetProcAddress((const GLubyte*)"glGetVideoCaptureStreamfvNV")) == NULL) || r;
+ r = ((glGetVideoCaptureStreamivNV = (PFNGLGETVIDEOCAPTURESTREAMIVNVPROC)glewGetProcAddress((const GLubyte*)"glGetVideoCaptureStreamivNV")) == NULL) || r;
+ r = ((glGetVideoCaptureivNV = (PFNGLGETVIDEOCAPTUREIVNVPROC)glewGetProcAddress((const GLubyte*)"glGetVideoCaptureivNV")) == NULL) || r;
+ r = ((glVideoCaptureNV = (PFNGLVIDEOCAPTURENVPROC)glewGetProcAddress((const GLubyte*)"glVideoCaptureNV")) == NULL) || r;
+ r = ((glVideoCaptureStreamParameterdvNV = (PFNGLVIDEOCAPTURESTREAMPARAMETERDVNVPROC)glewGetProcAddress((const GLubyte*)"glVideoCaptureStreamParameterdvNV")) == NULL) || r;
+ r = ((glVideoCaptureStreamParameterfvNV = (PFNGLVIDEOCAPTURESTREAMPARAMETERFVNVPROC)glewGetProcAddress((const GLubyte*)"glVideoCaptureStreamParameterfvNV")) == NULL) || r;
+ r = ((glVideoCaptureStreamParameterivNV = (PFNGLVIDEOCAPTURESTREAMPARAMETERIVNVPROC)glewGetProcAddress((const GLubyte*)"glVideoCaptureStreamParameterivNV")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_NV_video_capture */
+
+#ifdef GL_OES_byte_coordinates
+
+#endif /* GL_OES_byte_coordinates */
+
+#ifdef GL_OES_compressed_paletted_texture
+
+#endif /* GL_OES_compressed_paletted_texture */
+
+#ifdef GL_OES_read_format
+
+#endif /* GL_OES_read_format */
+
+#ifdef GL_OES_single_precision
+
+static GLboolean _glewInit_GL_OES_single_precision (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glClearDepthfOES = (PFNGLCLEARDEPTHFOESPROC)glewGetProcAddress((const GLubyte*)"glClearDepthfOES")) == NULL) || r;
+ r = ((glClipPlanefOES = (PFNGLCLIPPLANEFOESPROC)glewGetProcAddress((const GLubyte*)"glClipPlanefOES")) == NULL) || r;
+ r = ((glDepthRangefOES = (PFNGLDEPTHRANGEFOESPROC)glewGetProcAddress((const GLubyte*)"glDepthRangefOES")) == NULL) || r;
+ r = ((glFrustumfOES = (PFNGLFRUSTUMFOESPROC)glewGetProcAddress((const GLubyte*)"glFrustumfOES")) == NULL) || r;
+ r = ((glGetClipPlanefOES = (PFNGLGETCLIPPLANEFOESPROC)glewGetProcAddress((const GLubyte*)"glGetClipPlanefOES")) == NULL) || r;
+ r = ((glOrthofOES = (PFNGLORTHOFOESPROC)glewGetProcAddress((const GLubyte*)"glOrthofOES")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_OES_single_precision */
+
+#ifdef GL_OML_interlace
+
+#endif /* GL_OML_interlace */
+
+#ifdef GL_OML_resample
+
+#endif /* GL_OML_resample */
+
+#ifdef GL_OML_subsample
+
+#endif /* GL_OML_subsample */
+
+#ifdef GL_PGI_misc_hints
+
+#endif /* GL_PGI_misc_hints */
+
+#ifdef GL_PGI_vertex_hints
+
+#endif /* GL_PGI_vertex_hints */
+
+#ifdef GL_REND_screen_coordinates
+
+#endif /* GL_REND_screen_coordinates */
+
+#ifdef GL_S3_s3tc
+
+#endif /* GL_S3_s3tc */
+
+#ifdef GL_SGIS_color_range
+
+#endif /* GL_SGIS_color_range */
+
+#ifdef GL_SGIS_detail_texture
+
+static GLboolean _glewInit_GL_SGIS_detail_texture (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glDetailTexFuncSGIS = (PFNGLDETAILTEXFUNCSGISPROC)glewGetProcAddress((const GLubyte*)"glDetailTexFuncSGIS")) == NULL) || r;
+ r = ((glGetDetailTexFuncSGIS = (PFNGLGETDETAILTEXFUNCSGISPROC)glewGetProcAddress((const GLubyte*)"glGetDetailTexFuncSGIS")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_SGIS_detail_texture */
+
+#ifdef GL_SGIS_fog_function
+
+static GLboolean _glewInit_GL_SGIS_fog_function (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glFogFuncSGIS = (PFNGLFOGFUNCSGISPROC)glewGetProcAddress((const GLubyte*)"glFogFuncSGIS")) == NULL) || r;
+ r = ((glGetFogFuncSGIS = (PFNGLGETFOGFUNCSGISPROC)glewGetProcAddress((const GLubyte*)"glGetFogFuncSGIS")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_SGIS_fog_function */
+
+#ifdef GL_SGIS_generate_mipmap
+
+#endif /* GL_SGIS_generate_mipmap */
+
+#ifdef GL_SGIS_multisample
+
+static GLboolean _glewInit_GL_SGIS_multisample (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glSampleMaskSGIS = (PFNGLSAMPLEMASKSGISPROC)glewGetProcAddress((const GLubyte*)"glSampleMaskSGIS")) == NULL) || r;
+ r = ((glSamplePatternSGIS = (PFNGLSAMPLEPATTERNSGISPROC)glewGetProcAddress((const GLubyte*)"glSamplePatternSGIS")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_SGIS_multisample */
+
+#ifdef GL_SGIS_pixel_texture
+
+#endif /* GL_SGIS_pixel_texture */
+
+#ifdef GL_SGIS_point_line_texgen
+
+#endif /* GL_SGIS_point_line_texgen */
+
+#ifdef GL_SGIS_sharpen_texture
+
+static GLboolean _glewInit_GL_SGIS_sharpen_texture (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glGetSharpenTexFuncSGIS = (PFNGLGETSHARPENTEXFUNCSGISPROC)glewGetProcAddress((const GLubyte*)"glGetSharpenTexFuncSGIS")) == NULL) || r;
+ r = ((glSharpenTexFuncSGIS = (PFNGLSHARPENTEXFUNCSGISPROC)glewGetProcAddress((const GLubyte*)"glSharpenTexFuncSGIS")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_SGIS_sharpen_texture */
+
+#ifdef GL_SGIS_texture4D
+
+static GLboolean _glewInit_GL_SGIS_texture4D (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glTexImage4DSGIS = (PFNGLTEXIMAGE4DSGISPROC)glewGetProcAddress((const GLubyte*)"glTexImage4DSGIS")) == NULL) || r;
+ r = ((glTexSubImage4DSGIS = (PFNGLTEXSUBIMAGE4DSGISPROC)glewGetProcAddress((const GLubyte*)"glTexSubImage4DSGIS")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_SGIS_texture4D */
+
+#ifdef GL_SGIS_texture_border_clamp
+
+#endif /* GL_SGIS_texture_border_clamp */
+
+#ifdef GL_SGIS_texture_edge_clamp
+
+#endif /* GL_SGIS_texture_edge_clamp */
+
+#ifdef GL_SGIS_texture_filter4
+
+static GLboolean _glewInit_GL_SGIS_texture_filter4 (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glGetTexFilterFuncSGIS = (PFNGLGETTEXFILTERFUNCSGISPROC)glewGetProcAddress((const GLubyte*)"glGetTexFilterFuncSGIS")) == NULL) || r;
+ r = ((glTexFilterFuncSGIS = (PFNGLTEXFILTERFUNCSGISPROC)glewGetProcAddress((const GLubyte*)"glTexFilterFuncSGIS")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_SGIS_texture_filter4 */
+
+#ifdef GL_SGIS_texture_lod
+
+#endif /* GL_SGIS_texture_lod */
+
+#ifdef GL_SGIS_texture_select
+
+#endif /* GL_SGIS_texture_select */
+
+#ifdef GL_SGIX_async
+
+static GLboolean _glewInit_GL_SGIX_async (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glAsyncMarkerSGIX = (PFNGLASYNCMARKERSGIXPROC)glewGetProcAddress((const GLubyte*)"glAsyncMarkerSGIX")) == NULL) || r;
+ r = ((glDeleteAsyncMarkersSGIX = (PFNGLDELETEASYNCMARKERSSGIXPROC)glewGetProcAddress((const GLubyte*)"glDeleteAsyncMarkersSGIX")) == NULL) || r;
+ r = ((glFinishAsyncSGIX = (PFNGLFINISHASYNCSGIXPROC)glewGetProcAddress((const GLubyte*)"glFinishAsyncSGIX")) == NULL) || r;
+ r = ((glGenAsyncMarkersSGIX = (PFNGLGENASYNCMARKERSSGIXPROC)glewGetProcAddress((const GLubyte*)"glGenAsyncMarkersSGIX")) == NULL) || r;
+ r = ((glIsAsyncMarkerSGIX = (PFNGLISASYNCMARKERSGIXPROC)glewGetProcAddress((const GLubyte*)"glIsAsyncMarkerSGIX")) == NULL) || r;
+ r = ((glPollAsyncSGIX = (PFNGLPOLLASYNCSGIXPROC)glewGetProcAddress((const GLubyte*)"glPollAsyncSGIX")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_SGIX_async */
+
+#ifdef GL_SGIX_async_histogram
+
+#endif /* GL_SGIX_async_histogram */
+
+#ifdef GL_SGIX_async_pixel
+
+#endif /* GL_SGIX_async_pixel */
+
+#ifdef GL_SGIX_blend_alpha_minmax
+
+#endif /* GL_SGIX_blend_alpha_minmax */
+
+#ifdef GL_SGIX_clipmap
+
+#endif /* GL_SGIX_clipmap */
+
+#ifdef GL_SGIX_convolution_accuracy
+
+#endif /* GL_SGIX_convolution_accuracy */
+
+#ifdef GL_SGIX_depth_texture
+
+#endif /* GL_SGIX_depth_texture */
+
+#ifdef GL_SGIX_flush_raster
+
+static GLboolean _glewInit_GL_SGIX_flush_raster (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glFlushRasterSGIX = (PFNGLFLUSHRASTERSGIXPROC)glewGetProcAddress((const GLubyte*)"glFlushRasterSGIX")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_SGIX_flush_raster */
+
+#ifdef GL_SGIX_fog_offset
+
+#endif /* GL_SGIX_fog_offset */
+
+#ifdef GL_SGIX_fog_texture
+
+static GLboolean _glewInit_GL_SGIX_fog_texture (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glTextureFogSGIX = (PFNGLTEXTUREFOGSGIXPROC)glewGetProcAddress((const GLubyte*)"glTextureFogSGIX")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_SGIX_fog_texture */
+
+#ifdef GL_SGIX_fragment_specular_lighting
+
+static GLboolean _glewInit_GL_SGIX_fragment_specular_lighting (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glFragmentColorMaterialSGIX = (PFNGLFRAGMENTCOLORMATERIALSGIXPROC)glewGetProcAddress((const GLubyte*)"glFragmentColorMaterialSGIX")) == NULL) || r;
+ r = ((glFragmentLightModelfSGIX = (PFNGLFRAGMENTLIGHTMODELFSGIXPROC)glewGetProcAddress((const GLubyte*)"glFragmentLightModelfSGIX")) == NULL) || r;
+ r = ((glFragmentLightModelfvSGIX = (PFNGLFRAGMENTLIGHTMODELFVSGIXPROC)glewGetProcAddress((const GLubyte*)"glFragmentLightModelfvSGIX")) == NULL) || r;
+ r = ((glFragmentLightModeliSGIX = (PFNGLFRAGMENTLIGHTMODELISGIXPROC)glewGetProcAddress((const GLubyte*)"glFragmentLightModeliSGIX")) == NULL) || r;
+ r = ((glFragmentLightModelivSGIX = (PFNGLFRAGMENTLIGHTMODELIVSGIXPROC)glewGetProcAddress((const GLubyte*)"glFragmentLightModelivSGIX")) == NULL) || r;
+ r = ((glFragmentLightfSGIX = (PFNGLFRAGMENTLIGHTFSGIXPROC)glewGetProcAddress((const GLubyte*)"glFragmentLightfSGIX")) == NULL) || r;
+ r = ((glFragmentLightfvSGIX = (PFNGLFRAGMENTLIGHTFVSGIXPROC)glewGetProcAddress((const GLubyte*)"glFragmentLightfvSGIX")) == NULL) || r;
+ r = ((glFragmentLightiSGIX = (PFNGLFRAGMENTLIGHTISGIXPROC)glewGetProcAddress((const GLubyte*)"glFragmentLightiSGIX")) == NULL) || r;
+ r = ((glFragmentLightivSGIX = (PFNGLFRAGMENTLIGHTIVSGIXPROC)glewGetProcAddress((const GLubyte*)"glFragmentLightivSGIX")) == NULL) || r;
+ r = ((glFragmentMaterialfSGIX = (PFNGLFRAGMENTMATERIALFSGIXPROC)glewGetProcAddress((const GLubyte*)"glFragmentMaterialfSGIX")) == NULL) || r;
+ r = ((glFragmentMaterialfvSGIX = (PFNGLFRAGMENTMATERIALFVSGIXPROC)glewGetProcAddress((const GLubyte*)"glFragmentMaterialfvSGIX")) == NULL) || r;
+ r = ((glFragmentMaterialiSGIX = (PFNGLFRAGMENTMATERIALISGIXPROC)glewGetProcAddress((const GLubyte*)"glFragmentMaterialiSGIX")) == NULL) || r;
+ r = ((glFragmentMaterialivSGIX = (PFNGLFRAGMENTMATERIALIVSGIXPROC)glewGetProcAddress((const GLubyte*)"glFragmentMaterialivSGIX")) == NULL) || r;
+ r = ((glGetFragmentLightfvSGIX = (PFNGLGETFRAGMENTLIGHTFVSGIXPROC)glewGetProcAddress((const GLubyte*)"glGetFragmentLightfvSGIX")) == NULL) || r;
+ r = ((glGetFragmentLightivSGIX = (PFNGLGETFRAGMENTLIGHTIVSGIXPROC)glewGetProcAddress((const GLubyte*)"glGetFragmentLightivSGIX")) == NULL) || r;
+ r = ((glGetFragmentMaterialfvSGIX = (PFNGLGETFRAGMENTMATERIALFVSGIXPROC)glewGetProcAddress((const GLubyte*)"glGetFragmentMaterialfvSGIX")) == NULL) || r;
+ r = ((glGetFragmentMaterialivSGIX = (PFNGLGETFRAGMENTMATERIALIVSGIXPROC)glewGetProcAddress((const GLubyte*)"glGetFragmentMaterialivSGIX")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_SGIX_fragment_specular_lighting */
+
+#ifdef GL_SGIX_framezoom
+
+static GLboolean _glewInit_GL_SGIX_framezoom (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glFrameZoomSGIX = (PFNGLFRAMEZOOMSGIXPROC)glewGetProcAddress((const GLubyte*)"glFrameZoomSGIX")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_SGIX_framezoom */
+
+#ifdef GL_SGIX_interlace
+
+#endif /* GL_SGIX_interlace */
+
+#ifdef GL_SGIX_ir_instrument1
+
+#endif /* GL_SGIX_ir_instrument1 */
+
+#ifdef GL_SGIX_list_priority
+
+#endif /* GL_SGIX_list_priority */
+
+#ifdef GL_SGIX_pixel_texture
+
+static GLboolean _glewInit_GL_SGIX_pixel_texture (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glPixelTexGenSGIX = (PFNGLPIXELTEXGENSGIXPROC)glewGetProcAddress((const GLubyte*)"glPixelTexGenSGIX")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_SGIX_pixel_texture */
+
+#ifdef GL_SGIX_pixel_texture_bits
+
+#endif /* GL_SGIX_pixel_texture_bits */
+
+#ifdef GL_SGIX_reference_plane
+
+static GLboolean _glewInit_GL_SGIX_reference_plane (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glReferencePlaneSGIX = (PFNGLREFERENCEPLANESGIXPROC)glewGetProcAddress((const GLubyte*)"glReferencePlaneSGIX")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_SGIX_reference_plane */
+
+#ifdef GL_SGIX_resample
+
+#endif /* GL_SGIX_resample */
+
+#ifdef GL_SGIX_shadow
+
+#endif /* GL_SGIX_shadow */
+
+#ifdef GL_SGIX_shadow_ambient
+
+#endif /* GL_SGIX_shadow_ambient */
+
+#ifdef GL_SGIX_sprite
+
+static GLboolean _glewInit_GL_SGIX_sprite (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glSpriteParameterfSGIX = (PFNGLSPRITEPARAMETERFSGIXPROC)glewGetProcAddress((const GLubyte*)"glSpriteParameterfSGIX")) == NULL) || r;
+ r = ((glSpriteParameterfvSGIX = (PFNGLSPRITEPARAMETERFVSGIXPROC)glewGetProcAddress((const GLubyte*)"glSpriteParameterfvSGIX")) == NULL) || r;
+ r = ((glSpriteParameteriSGIX = (PFNGLSPRITEPARAMETERISGIXPROC)glewGetProcAddress((const GLubyte*)"glSpriteParameteriSGIX")) == NULL) || r;
+ r = ((glSpriteParameterivSGIX = (PFNGLSPRITEPARAMETERIVSGIXPROC)glewGetProcAddress((const GLubyte*)"glSpriteParameterivSGIX")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_SGIX_sprite */
+
+#ifdef GL_SGIX_tag_sample_buffer
+
+static GLboolean _glewInit_GL_SGIX_tag_sample_buffer (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glTagSampleBufferSGIX = (PFNGLTAGSAMPLEBUFFERSGIXPROC)glewGetProcAddress((const GLubyte*)"glTagSampleBufferSGIX")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_SGIX_tag_sample_buffer */
+
+#ifdef GL_SGIX_texture_add_env
+
+#endif /* GL_SGIX_texture_add_env */
+
+#ifdef GL_SGIX_texture_coordinate_clamp
+
+#endif /* GL_SGIX_texture_coordinate_clamp */
+
+#ifdef GL_SGIX_texture_lod_bias
+
+#endif /* GL_SGIX_texture_lod_bias */
+
+#ifdef GL_SGIX_texture_multi_buffer
+
+#endif /* GL_SGIX_texture_multi_buffer */
+
+#ifdef GL_SGIX_texture_range
+
+#endif /* GL_SGIX_texture_range */
+
+#ifdef GL_SGIX_texture_scale_bias
+
+#endif /* GL_SGIX_texture_scale_bias */
+
+#ifdef GL_SGIX_vertex_preclip
+
+#endif /* GL_SGIX_vertex_preclip */
+
+#ifdef GL_SGIX_vertex_preclip_hint
+
+#endif /* GL_SGIX_vertex_preclip_hint */
+
+#ifdef GL_SGIX_ycrcb
+
+#endif /* GL_SGIX_ycrcb */
+
+#ifdef GL_SGI_color_matrix
+
+#endif /* GL_SGI_color_matrix */
+
+#ifdef GL_SGI_color_table
+
+static GLboolean _glewInit_GL_SGI_color_table (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glColorTableParameterfvSGI = (PFNGLCOLORTABLEPARAMETERFVSGIPROC)glewGetProcAddress((const GLubyte*)"glColorTableParameterfvSGI")) == NULL) || r;
+ r = ((glColorTableParameterivSGI = (PFNGLCOLORTABLEPARAMETERIVSGIPROC)glewGetProcAddress((const GLubyte*)"glColorTableParameterivSGI")) == NULL) || r;
+ r = ((glColorTableSGI = (PFNGLCOLORTABLESGIPROC)glewGetProcAddress((const GLubyte*)"glColorTableSGI")) == NULL) || r;
+ r = ((glCopyColorTableSGI = (PFNGLCOPYCOLORTABLESGIPROC)glewGetProcAddress((const GLubyte*)"glCopyColorTableSGI")) == NULL) || r;
+ r = ((glGetColorTableParameterfvSGI = (PFNGLGETCOLORTABLEPARAMETERFVSGIPROC)glewGetProcAddress((const GLubyte*)"glGetColorTableParameterfvSGI")) == NULL) || r;
+ r = ((glGetColorTableParameterivSGI = (PFNGLGETCOLORTABLEPARAMETERIVSGIPROC)glewGetProcAddress((const GLubyte*)"glGetColorTableParameterivSGI")) == NULL) || r;
+ r = ((glGetColorTableSGI = (PFNGLGETCOLORTABLESGIPROC)glewGetProcAddress((const GLubyte*)"glGetColorTableSGI")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_SGI_color_table */
+
+#ifdef GL_SGI_texture_color_table
+
+#endif /* GL_SGI_texture_color_table */
+
+#ifdef GL_SUNX_constant_data
+
+static GLboolean _glewInit_GL_SUNX_constant_data (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glFinishTextureSUNX = (PFNGLFINISHTEXTURESUNXPROC)glewGetProcAddress((const GLubyte*)"glFinishTextureSUNX")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_SUNX_constant_data */
+
+#ifdef GL_SUN_convolution_border_modes
+
+#endif /* GL_SUN_convolution_border_modes */
+
+#ifdef GL_SUN_global_alpha
+
+static GLboolean _glewInit_GL_SUN_global_alpha (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glGlobalAlphaFactorbSUN = (PFNGLGLOBALALPHAFACTORBSUNPROC)glewGetProcAddress((const GLubyte*)"glGlobalAlphaFactorbSUN")) == NULL) || r;
+ r = ((glGlobalAlphaFactordSUN = (PFNGLGLOBALALPHAFACTORDSUNPROC)glewGetProcAddress((const GLubyte*)"glGlobalAlphaFactordSUN")) == NULL) || r;
+ r = ((glGlobalAlphaFactorfSUN = (PFNGLGLOBALALPHAFACTORFSUNPROC)glewGetProcAddress((const GLubyte*)"glGlobalAlphaFactorfSUN")) == NULL) || r;
+ r = ((glGlobalAlphaFactoriSUN = (PFNGLGLOBALALPHAFACTORISUNPROC)glewGetProcAddress((const GLubyte*)"glGlobalAlphaFactoriSUN")) == NULL) || r;
+ r = ((glGlobalAlphaFactorsSUN = (PFNGLGLOBALALPHAFACTORSSUNPROC)glewGetProcAddress((const GLubyte*)"glGlobalAlphaFactorsSUN")) == NULL) || r;
+ r = ((glGlobalAlphaFactorubSUN = (PFNGLGLOBALALPHAFACTORUBSUNPROC)glewGetProcAddress((const GLubyte*)"glGlobalAlphaFactorubSUN")) == NULL) || r;
+ r = ((glGlobalAlphaFactoruiSUN = (PFNGLGLOBALALPHAFACTORUISUNPROC)glewGetProcAddress((const GLubyte*)"glGlobalAlphaFactoruiSUN")) == NULL) || r;
+ r = ((glGlobalAlphaFactorusSUN = (PFNGLGLOBALALPHAFACTORUSSUNPROC)glewGetProcAddress((const GLubyte*)"glGlobalAlphaFactorusSUN")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_SUN_global_alpha */
+
+#ifdef GL_SUN_mesh_array
+
+#endif /* GL_SUN_mesh_array */
+
+#ifdef GL_SUN_read_video_pixels
+
+static GLboolean _glewInit_GL_SUN_read_video_pixels (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glReadVideoPixelsSUN = (PFNGLREADVIDEOPIXELSSUNPROC)glewGetProcAddress((const GLubyte*)"glReadVideoPixelsSUN")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_SUN_read_video_pixels */
+
+#ifdef GL_SUN_slice_accum
+
+#endif /* GL_SUN_slice_accum */
+
+#ifdef GL_SUN_triangle_list
+
+static GLboolean _glewInit_GL_SUN_triangle_list (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glReplacementCodePointerSUN = (PFNGLREPLACEMENTCODEPOINTERSUNPROC)glewGetProcAddress((const GLubyte*)"glReplacementCodePointerSUN")) == NULL) || r;
+ r = ((glReplacementCodeubSUN = (PFNGLREPLACEMENTCODEUBSUNPROC)glewGetProcAddress((const GLubyte*)"glReplacementCodeubSUN")) == NULL) || r;
+ r = ((glReplacementCodeubvSUN = (PFNGLREPLACEMENTCODEUBVSUNPROC)glewGetProcAddress((const GLubyte*)"glReplacementCodeubvSUN")) == NULL) || r;
+ r = ((glReplacementCodeuiSUN = (PFNGLREPLACEMENTCODEUISUNPROC)glewGetProcAddress((const GLubyte*)"glReplacementCodeuiSUN")) == NULL) || r;
+ r = ((glReplacementCodeuivSUN = (PFNGLREPLACEMENTCODEUIVSUNPROC)glewGetProcAddress((const GLubyte*)"glReplacementCodeuivSUN")) == NULL) || r;
+ r = ((glReplacementCodeusSUN = (PFNGLREPLACEMENTCODEUSSUNPROC)glewGetProcAddress((const GLubyte*)"glReplacementCodeusSUN")) == NULL) || r;
+ r = ((glReplacementCodeusvSUN = (PFNGLREPLACEMENTCODEUSVSUNPROC)glewGetProcAddress((const GLubyte*)"glReplacementCodeusvSUN")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_SUN_triangle_list */
+
+#ifdef GL_SUN_vertex
+
+static GLboolean _glewInit_GL_SUN_vertex (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glColor3fVertex3fSUN = (PFNGLCOLOR3FVERTEX3FSUNPROC)glewGetProcAddress((const GLubyte*)"glColor3fVertex3fSUN")) == NULL) || r;
+ r = ((glColor3fVertex3fvSUN = (PFNGLCOLOR3FVERTEX3FVSUNPROC)glewGetProcAddress((const GLubyte*)"glColor3fVertex3fvSUN")) == NULL) || r;
+ r = ((glColor4fNormal3fVertex3fSUN = (PFNGLCOLOR4FNORMAL3FVERTEX3FSUNPROC)glewGetProcAddress((const GLubyte*)"glColor4fNormal3fVertex3fSUN")) == NULL) || r;
+ r = ((glColor4fNormal3fVertex3fvSUN = (PFNGLCOLOR4FNORMAL3FVERTEX3FVSUNPROC)glewGetProcAddress((const GLubyte*)"glColor4fNormal3fVertex3fvSUN")) == NULL) || r;
+ r = ((glColor4ubVertex2fSUN = (PFNGLCOLOR4UBVERTEX2FSUNPROC)glewGetProcAddress((const GLubyte*)"glColor4ubVertex2fSUN")) == NULL) || r;
+ r = ((glColor4ubVertex2fvSUN = (PFNGLCOLOR4UBVERTEX2FVSUNPROC)glewGetProcAddress((const GLubyte*)"glColor4ubVertex2fvSUN")) == NULL) || r;
+ r = ((glColor4ubVertex3fSUN = (PFNGLCOLOR4UBVERTEX3FSUNPROC)glewGetProcAddress((const GLubyte*)"glColor4ubVertex3fSUN")) == NULL) || r;
+ r = ((glColor4ubVertex3fvSUN = (PFNGLCOLOR4UBVERTEX3FVSUNPROC)glewGetProcAddress((const GLubyte*)"glColor4ubVertex3fvSUN")) == NULL) || r;
+ r = ((glNormal3fVertex3fSUN = (PFNGLNORMAL3FVERTEX3FSUNPROC)glewGetProcAddress((const GLubyte*)"glNormal3fVertex3fSUN")) == NULL) || r;
+ r = ((glNormal3fVertex3fvSUN = (PFNGLNORMAL3FVERTEX3FVSUNPROC)glewGetProcAddress((const GLubyte*)"glNormal3fVertex3fvSUN")) == NULL) || r;
+ r = ((glReplacementCodeuiColor3fVertex3fSUN = (PFNGLREPLACEMENTCODEUICOLOR3FVERTEX3FSUNPROC)glewGetProcAddress((const GLubyte*)"glReplacementCodeuiColor3fVertex3fSUN")) == NULL) || r;
+ r = ((glReplacementCodeuiColor3fVertex3fvSUN = (PFNGLREPLACEMENTCODEUICOLOR3FVERTEX3FVSUNPROC)glewGetProcAddress((const GLubyte*)"glReplacementCodeuiColor3fVertex3fvSUN")) == NULL) || r;
+ r = ((glReplacementCodeuiColor4fNormal3fVertex3fSUN = (PFNGLREPLACEMENTCODEUICOLOR4FNORMAL3FVERTEX3FSUNPROC)glewGetProcAddress((const GLubyte*)"glReplacementCodeuiColor4fNormal3fVertex3fSUN")) == NULL) || r;
+ r = ((glReplacementCodeuiColor4fNormal3fVertex3fvSUN = (PFNGLREPLACEMENTCODEUICOLOR4FNORMAL3FVERTEX3FVSUNPROC)glewGetProcAddress((const GLubyte*)"glReplacementCodeuiColor4fNormal3fVertex3fvSUN")) == NULL) || r;
+ r = ((glReplacementCodeuiColor4ubVertex3fSUN = (PFNGLREPLACEMENTCODEUICOLOR4UBVERTEX3FSUNPROC)glewGetProcAddress((const GLubyte*)"glReplacementCodeuiColor4ubVertex3fSUN")) == NULL) || r;
+ r = ((glReplacementCodeuiColor4ubVertex3fvSUN = (PFNGLREPLACEMENTCODEUICOLOR4UBVERTEX3FVSUNPROC)glewGetProcAddress((const GLubyte*)"glReplacementCodeuiColor4ubVertex3fvSUN")) == NULL) || r;
+ r = ((glReplacementCodeuiNormal3fVertex3fSUN = (PFNGLREPLACEMENTCODEUINORMAL3FVERTEX3FSUNPROC)glewGetProcAddress((const GLubyte*)"glReplacementCodeuiNormal3fVertex3fSUN")) == NULL) || r;
+ r = ((glReplacementCodeuiNormal3fVertex3fvSUN = (PFNGLREPLACEMENTCODEUINORMAL3FVERTEX3FVSUNPROC)glewGetProcAddress((const GLubyte*)"glReplacementCodeuiNormal3fVertex3fvSUN")) == NULL) || r;
+ r = ((glReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fSUN = (PFNGLREPLACEMENTCODEUITEXCOORD2FCOLOR4FNORMAL3FVERTEX3FSUNPROC)glewGetProcAddress((const GLubyte*)"glReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fSUN")) == NULL) || r;
+ r = ((glReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fvSUN = (PFNGLREPLACEMENTCODEUITEXCOORD2FCOLOR4FNORMAL3FVERTEX3FVSUNPROC)glewGetProcAddress((const GLubyte*)"glReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fvSUN")) == NULL) || r;
+ r = ((glReplacementCodeuiTexCoord2fNormal3fVertex3fSUN = (PFNGLREPLACEMENTCODEUITEXCOORD2FNORMAL3FVERTEX3FSUNPROC)glewGetProcAddress((const GLubyte*)"glReplacementCodeuiTexCoord2fNormal3fVertex3fSUN")) == NULL) || r;
+ r = ((glReplacementCodeuiTexCoord2fNormal3fVertex3fvSUN = (PFNGLREPLACEMENTCODEUITEXCOORD2FNORMAL3FVERTEX3FVSUNPROC)glewGetProcAddress((const GLubyte*)"glReplacementCodeuiTexCoord2fNormal3fVertex3fvSUN")) == NULL) || r;
+ r = ((glReplacementCodeuiTexCoord2fVertex3fSUN = (PFNGLREPLACEMENTCODEUITEXCOORD2FVERTEX3FSUNPROC)glewGetProcAddress((const GLubyte*)"glReplacementCodeuiTexCoord2fVertex3fSUN")) == NULL) || r;
+ r = ((glReplacementCodeuiTexCoord2fVertex3fvSUN = (PFNGLREPLACEMENTCODEUITEXCOORD2FVERTEX3FVSUNPROC)glewGetProcAddress((const GLubyte*)"glReplacementCodeuiTexCoord2fVertex3fvSUN")) == NULL) || r;
+ r = ((glReplacementCodeuiVertex3fSUN = (PFNGLREPLACEMENTCODEUIVERTEX3FSUNPROC)glewGetProcAddress((const GLubyte*)"glReplacementCodeuiVertex3fSUN")) == NULL) || r;
+ r = ((glReplacementCodeuiVertex3fvSUN = (PFNGLREPLACEMENTCODEUIVERTEX3FVSUNPROC)glewGetProcAddress((const GLubyte*)"glReplacementCodeuiVertex3fvSUN")) == NULL) || r;
+ r = ((glTexCoord2fColor3fVertex3fSUN = (PFNGLTEXCOORD2FCOLOR3FVERTEX3FSUNPROC)glewGetProcAddress((const GLubyte*)"glTexCoord2fColor3fVertex3fSUN")) == NULL) || r;
+ r = ((glTexCoord2fColor3fVertex3fvSUN = (PFNGLTEXCOORD2FCOLOR3FVERTEX3FVSUNPROC)glewGetProcAddress((const GLubyte*)"glTexCoord2fColor3fVertex3fvSUN")) == NULL) || r;
+ r = ((glTexCoord2fColor4fNormal3fVertex3fSUN = (PFNGLTEXCOORD2FCOLOR4FNORMAL3FVERTEX3FSUNPROC)glewGetProcAddress((const GLubyte*)"glTexCoord2fColor4fNormal3fVertex3fSUN")) == NULL) || r;
+ r = ((glTexCoord2fColor4fNormal3fVertex3fvSUN = (PFNGLTEXCOORD2FCOLOR4FNORMAL3FVERTEX3FVSUNPROC)glewGetProcAddress((const GLubyte*)"glTexCoord2fColor4fNormal3fVertex3fvSUN")) == NULL) || r;
+ r = ((glTexCoord2fColor4ubVertex3fSUN = (PFNGLTEXCOORD2FCOLOR4UBVERTEX3FSUNPROC)glewGetProcAddress((const GLubyte*)"glTexCoord2fColor4ubVertex3fSUN")) == NULL) || r;
+ r = ((glTexCoord2fColor4ubVertex3fvSUN = (PFNGLTEXCOORD2FCOLOR4UBVERTEX3FVSUNPROC)glewGetProcAddress((const GLubyte*)"glTexCoord2fColor4ubVertex3fvSUN")) == NULL) || r;
+ r = ((glTexCoord2fNormal3fVertex3fSUN = (PFNGLTEXCOORD2FNORMAL3FVERTEX3FSUNPROC)glewGetProcAddress((const GLubyte*)"glTexCoord2fNormal3fVertex3fSUN")) == NULL) || r;
+ r = ((glTexCoord2fNormal3fVertex3fvSUN = (PFNGLTEXCOORD2FNORMAL3FVERTEX3FVSUNPROC)glewGetProcAddress((const GLubyte*)"glTexCoord2fNormal3fVertex3fvSUN")) == NULL) || r;
+ r = ((glTexCoord2fVertex3fSUN = (PFNGLTEXCOORD2FVERTEX3FSUNPROC)glewGetProcAddress((const GLubyte*)"glTexCoord2fVertex3fSUN")) == NULL) || r;
+ r = ((glTexCoord2fVertex3fvSUN = (PFNGLTEXCOORD2FVERTEX3FVSUNPROC)glewGetProcAddress((const GLubyte*)"glTexCoord2fVertex3fvSUN")) == NULL) || r;
+ r = ((glTexCoord4fColor4fNormal3fVertex4fSUN = (PFNGLTEXCOORD4FCOLOR4FNORMAL3FVERTEX4FSUNPROC)glewGetProcAddress((const GLubyte*)"glTexCoord4fColor4fNormal3fVertex4fSUN")) == NULL) || r;
+ r = ((glTexCoord4fColor4fNormal3fVertex4fvSUN = (PFNGLTEXCOORD4FCOLOR4FNORMAL3FVERTEX4FVSUNPROC)glewGetProcAddress((const GLubyte*)"glTexCoord4fColor4fNormal3fVertex4fvSUN")) == NULL) || r;
+ r = ((glTexCoord4fVertex4fSUN = (PFNGLTEXCOORD4FVERTEX4FSUNPROC)glewGetProcAddress((const GLubyte*)"glTexCoord4fVertex4fSUN")) == NULL) || r;
+ r = ((glTexCoord4fVertex4fvSUN = (PFNGLTEXCOORD4FVERTEX4FVSUNPROC)glewGetProcAddress((const GLubyte*)"glTexCoord4fVertex4fvSUN")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_SUN_vertex */
+
+#ifdef GL_WIN_phong_shading
+
+#endif /* GL_WIN_phong_shading */
+
+#ifdef GL_WIN_specular_fog
+
+#endif /* GL_WIN_specular_fog */
+
+#ifdef GL_WIN_swap_hint
+
+static GLboolean _glewInit_GL_WIN_swap_hint (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glAddSwapHintRectWIN = (PFNGLADDSWAPHINTRECTWINPROC)glewGetProcAddress((const GLubyte*)"glAddSwapHintRectWIN")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_WIN_swap_hint */
+
+#if GL_ES_VERSION_1_0 // NOTE jwilkins: changed from ifdef
+
+static GLboolean _glewInit_GL_ES_VERSION_1_0 (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glActiveTexture = (PFNGLACTIVETEXTUREPROC)glewGetProcAddress((const GLubyte*)"glActiveTexture")) == NULL) || r;
+ r = ((glAlphaFuncx = (PFNGLALPHAFUNCXPROC)glewGetProcAddress((const GLubyte*)"glAlphaFuncx")) == NULL) || r;
+ r = ((glClearColorx = (PFNGLCLEARCOLORXPROC)glewGetProcAddress((const GLubyte*)"glClearColorx")) == NULL) || r;
+ r = ((glClearDepthf = (PFNGLCLEARDEPTHFPROC)glewGetProcAddress((const GLubyte*)"glClearDepthf")) == NULL) || r;
+ r = ((glClearDepthx = (PFNGLCLEARDEPTHXPROC)glewGetProcAddress((const GLubyte*)"glClearDepthx")) == NULL) || r;
+ r = ((glClientActiveTexture = (PFNGLCLIENTACTIVETEXTUREPROC)glewGetProcAddress((const GLubyte*)"glClientActiveTexture")) == NULL) || r;
+ r = ((glColor4x = (PFNGLCOLOR4XPROC)glewGetProcAddress((const GLubyte*)"glColor4x")) == NULL) || r;
+ r = ((glCompressedTexImage2D = (PFNGLCOMPRESSEDTEXIMAGE2DPROC)glewGetProcAddress((const GLubyte*)"glCompressedTexImage2D")) == NULL) || r;
+ r = ((glCompressedTexSubImage2D = (PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC)glewGetProcAddress((const GLubyte*)"glCompressedTexSubImage2D")) == NULL) || r;
+ r = ((glDepthRangef = (PFNGLDEPTHRANGEFPROC)glewGetProcAddress((const GLubyte*)"glDepthRangef")) == NULL) || r;
+ r = ((glDepthRangex = (PFNGLDEPTHRANGEXPROC)glewGetProcAddress((const GLubyte*)"glDepthRangex")) == NULL) || r;
+ r = ((glFogx = (PFNGLFOGXPROC)glewGetProcAddress((const GLubyte*)"glFogx")) == NULL) || r;
+ r = ((glFogxv = (PFNGLFOGXVPROC)glewGetProcAddress((const GLubyte*)"glFogxv")) == NULL) || r;
+ r = ((glFrustumf = (PFNGLFRUSTUMFPROC)glewGetProcAddress((const GLubyte*)"glFrustumf")) == NULL) || r;
+ r = ((glFrustumx = (PFNGLFRUSTUMXPROC)glewGetProcAddress((const GLubyte*)"glFrustumx")) == NULL) || r;
+ r = ((glLightModelx = (PFNGLLIGHTMODELXPROC)glewGetProcAddress((const GLubyte*)"glLightModelx")) == NULL) || r;
+ r = ((glLightModelxv = (PFNGLLIGHTMODELXVPROC)glewGetProcAddress((const GLubyte*)"glLightModelxv")) == NULL) || r;
+ r = ((glLightx = (PFNGLLIGHTXPROC)glewGetProcAddress((const GLubyte*)"glLightx")) == NULL) || r;
+ r = ((glLightxv = (PFNGLLIGHTXVPROC)glewGetProcAddress((const GLubyte*)"glLightxv")) == NULL) || r;
+ r = ((glLineWidthx = (PFNGLLINEWIDTHXPROC)glewGetProcAddress((const GLubyte*)"glLineWidthx")) == NULL) || r;
+ r = ((glLoadMatrixx = (PFNGLLOADMATRIXXPROC)glewGetProcAddress((const GLubyte*)"glLoadMatrixx")) == NULL) || r;
+ r = ((glMaterialx = (PFNGLMATERIALXPROC)glewGetProcAddress((const GLubyte*)"glMaterialx")) == NULL) || r;
+ r = ((glMaterialxv = (PFNGLMATERIALXVPROC)glewGetProcAddress((const GLubyte*)"glMaterialxv")) == NULL) || r;
+ r = ((glMultMatrixx = (PFNGLMULTMATRIXXPROC)glewGetProcAddress((const GLubyte*)"glMultMatrixx")) == NULL) || r;
+ r = ((glMultiTexCoord4f = (PFNGLMULTITEXCOORD4FPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord4f")) == NULL) || r;
+ r = ((glMultiTexCoord4x = (PFNGLMULTITEXCOORD4XPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord4x")) == NULL) || r;
+ r = ((glNormal3x = (PFNGLNORMAL3XPROC)glewGetProcAddress((const GLubyte*)"glNormal3x")) == NULL) || r;
+ r = ((glOrthof = (PFNGLORTHOFPROC)glewGetProcAddress((const GLubyte*)"glOrthof")) == NULL) || r;
+ r = ((glOrthox = (PFNGLORTHOXPROC)glewGetProcAddress((const GLubyte*)"glOrthox")) == NULL) || r;
+ r = ((glPointSizex = (PFNGLPOINTSIZEXPROC)glewGetProcAddress((const GLubyte*)"glPointSizex")) == NULL) || r;
+ r = ((glPolygonOffsetx = (PFNGLPOLYGONOFFSETXPROC)glewGetProcAddress((const GLubyte*)"glPolygonOffsetx")) == NULL) || r;
+ r = ((glRotatex = (PFNGLROTATEXPROC)glewGetProcAddress((const GLubyte*)"glRotatex")) == NULL) || r;
+ r = ((glSampleCoverage = (PFNGLSAMPLECOVERAGEPROC)glewGetProcAddress((const GLubyte*)"glSampleCoverage")) == NULL) || r;
+ r = ((glSampleCoveragex = (PFNGLSAMPLECOVERAGEXPROC)glewGetProcAddress((const GLubyte*)"glSampleCoveragex")) == NULL) || r;
+ r = ((glScalex = (PFNGLSCALEXPROC)glewGetProcAddress((const GLubyte*)"glScalex")) == NULL) || r;
+ r = ((glTexEnvx = (PFNGLTEXENVXPROC)glewGetProcAddress((const GLubyte*)"glTexEnvx")) == NULL) || r;
+ r = ((glTexEnvxv = (PFNGLTEXENVXVPROC)glewGetProcAddress((const GLubyte*)"glTexEnvxv")) == NULL) || r;
+ r = ((glTexParameterx = (PFNGLTEXPARAMETERXPROC)glewGetProcAddress((const GLubyte*)"glTexParameterx")) == NULL) || r;
+ r = ((glTranslatex = (PFNGLTRANSLATEXPROC)glewGetProcAddress((const GLubyte*)"glTranslatex")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_ES_VERSION_1_0 */
+
+#if GL_ES_VERSION_CL_1_1 // NOTE jwilkins: should be 'if' not 'ifdef'
+
+static GLboolean _glewInit_GL_ES_VERSION_CL_1_1 (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glBindBuffer = (PFNGLBINDBUFFERPROC)glewGetProcAddress((const GLubyte*)"glBindBuffer")) == NULL) || r;
+ r = ((glBufferData = (PFNGLBUFFERDATAPROC)glewGetProcAddress((const GLubyte*)"glBufferData")) == NULL) || r;
+ r = ((glBufferSubData = (PFNGLBUFFERSUBDATAPROC)glewGetProcAddress((const GLubyte*)"glBufferSubData")) == NULL) || r;
+ r = ((glClipPlanex = (PFNGLCLIPPLANEXPROC)glewGetProcAddress((const GLubyte*)"glClipPlanex")) == NULL) || r;
+ r = ((glColor4ub = (PFNGLCOLOR4UBPROC)glewGetProcAddress((const GLubyte*)"glColor4ub")) == NULL) || r;
+ r = ((glDeleteBuffers = (PFNGLDELETEBUFFERSPROC)glewGetProcAddress((const GLubyte*)"glDeleteBuffers")) == NULL) || r;
+ r = ((glGenBuffers = (PFNGLGENBUFFERSPROC)glewGetProcAddress((const GLubyte*)"glGenBuffers")) == NULL) || r;
+ r = ((glGetBooleanv = (PFNGLGETBOOLEANVPROC)glewGetProcAddress((const GLubyte*)"glGetBooleanv")) == NULL) || r;
+ r = ((glGetBufferParameteriv = (PFNGLGETBUFFERPARAMETERIVPROC)glewGetProcAddress((const GLubyte*)"glGetBufferParameteriv")) == NULL) || r;
+ r = ((glGetClipPlanex = (PFNGLGETCLIPPLANEXPROC)glewGetProcAddress((const GLubyte*)"glGetClipPlanex")) == NULL) || r;
+ r = ((glGetFixedv = (PFNGLGETFIXEDVPROC)glewGetProcAddress((const GLubyte*)"glGetFixedv")) == NULL) || r;
+ r = ((glGetLightxv = (PFNGLGETLIGHTXVPROC)glewGetProcAddress((const GLubyte*)"glGetLightxv")) == NULL) || r;
+ r = ((glGetMaterialxv = (PFNGLGETMATERIALXVPROC)glewGetProcAddress((const GLubyte*)"glGetMaterialxv")) == NULL) || r;
+ r = ((glGetPointerv = (PFNGLGETPOINTERVPROC)glewGetProcAddress((const GLubyte*)"glGetPointerv")) == NULL) || r;
+ r = ((glGetTexEnviv = (PFNGLGETTEXENVIVPROC)glewGetProcAddress((const GLubyte*)"glGetTexEnviv")) == NULL) || r;
+ r = ((glGetTexEnvxv = (PFNGLGETTEXENVXVPROC)glewGetProcAddress((const GLubyte*)"glGetTexEnvxv")) == NULL) || r;
+ r = ((glGetTexParameteriv = (PFNGLGETTEXPARAMETERIVPROC)glewGetProcAddress((const GLubyte*)"glGetTexParameteriv")) == NULL) || r;
+ r = ((glGetTexParameterxv = (PFNGLGETTEXPARAMETERXVPROC)glewGetProcAddress((const GLubyte*)"glGetTexParameterxv")) == NULL) || r;
+ r = ((glIsBuffer = (PFNGLISBUFFERPROC)glewGetProcAddress((const GLubyte*)"glIsBuffer")) == NULL) || r;
+ r = ((glIsEnabled = (PFNGLISENABLEDPROC)glewGetProcAddress((const GLubyte*)"glIsEnabled")) == NULL) || r;
+ r = ((glIsTexture = (PFNGLISTEXTUREPROC)glewGetProcAddress((const GLubyte*)"glIsTexture")) == NULL) || r;
+ r = ((glPointParameterx = (PFNGLPOINTPARAMETERXPROC)glewGetProcAddress((const GLubyte*)"glPointParameterx")) == NULL) || r;
+ r = ((glPointParameterxv = (PFNGLPOINTPARAMETERXVPROC)glewGetProcAddress((const GLubyte*)"glPointParameterxv")) == NULL) || r;
+ r = ((glTexEnvi = (PFNGLTEXENVIPROC)glewGetProcAddress((const GLubyte*)"glTexEnvi")) == NULL) || r;
+ r = ((glTexEnviv = (PFNGLTEXENVIVPROC)glewGetProcAddress((const GLubyte*)"glTexEnviv")) == NULL) || r;
+ r = ((glTexParameteri = (PFNGLTEXPARAMETERIPROC)glewGetProcAddress((const GLubyte*)"glTexParameteri")) == NULL) || r;
+ r = ((glTexParameteriv = (PFNGLTEXPARAMETERIVPROC)glewGetProcAddress((const GLubyte*)"glTexParameteriv")) == NULL) || r;
+ r = ((glTexParameterxv = (PFNGLTEXPARAMETERXVPROC)glewGetProcAddress((const GLubyte*)"glTexParameterxv")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_ES_VERSION_CL_1_1 */
+
+#if GL_ES_VERSION_CM_1_1 // NOTE jwilkins: should be 'if' not 'ifdef'
+
+static GLboolean _glewInit_GL_ES_VERSION_CM_1_1 (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glClipPlanef = (PFNGLCLIPPLANEFPROC)glewGetProcAddress((const GLubyte*)"glClipPlanef")) == NULL) || r;
+ r = ((glGetClipPlanef = (PFNGLGETCLIPPLANEFPROC)glewGetProcAddress((const GLubyte*)"glGetClipPlanef")) == NULL) || r;
+ r = ((glGetFloatv = (PFNGLGETFLOATVPROC)glewGetProcAddress((const GLubyte*)"glGetFloatv")) == NULL) || r;
+ r = ((glGetLightfv = (PFNGLGETLIGHTFVPROC)glewGetProcAddress((const GLubyte*)"glGetLightfv")) == NULL) || r;
+ r = ((glGetMaterialfv = (PFNGLGETMATERIALFVPROC)glewGetProcAddress((const GLubyte*)"glGetMaterialfv")) == NULL) || r;
+ r = ((glGetTexEnvfv = (PFNGLGETTEXENVFVPROC)glewGetProcAddress((const GLubyte*)"glGetTexEnvfv")) == NULL) || r;
+ r = ((glGetTexParameterfv = (PFNGLGETTEXPARAMETERFVPROC)glewGetProcAddress((const GLubyte*)"glGetTexParameterfv")) == NULL) || r;
+ r = ((glPointParameterf = (PFNGLPOINTPARAMETERFPROC)glewGetProcAddress((const GLubyte*)"glPointParameterf")) == NULL) || r;
+ r = ((glPointParameterfv = (PFNGLPOINTPARAMETERFVPROC)glewGetProcAddress((const GLubyte*)"glPointParameterfv")) == NULL) || r;
+ r = ((glTexParameterfv = (PFNGLTEXPARAMETERFVPROC)glewGetProcAddress((const GLubyte*)"glTexParameterfv")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_ES_VERSION_CM_1_1 */
+
+#ifdef GL_ES_VERSION_2_0
+
+static GLboolean _glewInit_GL_ES_VERSION_2_0 (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glAttachShader = (PFNGLATTACHSHADERPROC)glewGetProcAddress((const GLubyte*)"glAttachShader")) == NULL) || r;
+ r = ((glBindAttribLocation = (PFNGLBINDATTRIBLOCATIONPROC)glewGetProcAddress((const GLubyte*)"glBindAttribLocation")) == NULL) || r;
+ r = ((glBindFramebuffer = (PFNGLBINDFRAMEBUFFERPROC)glewGetProcAddress((const GLubyte*)"glBindFramebuffer")) == NULL) || r;
+ r = ((glBindRenderbuffer = (PFNGLBINDRENDERBUFFERPROC)glewGetProcAddress((const GLubyte*)"glBindRenderbuffer")) == NULL) || r;
+ r = ((glBlendColor = (PFNGLBLENDCOLORPROC)glewGetProcAddress((const GLubyte*)"glBlendColor")) == NULL) || r;
+ r = ((glBlendEquation = (PFNGLBLENDEQUATIONPROC)glewGetProcAddress((const GLubyte*)"glBlendEquation")) == NULL) || r;
+ r = ((glBlendEquationSeparate = (PFNGLBLENDEQUATIONSEPARATEPROC)glewGetProcAddress((const GLubyte*)"glBlendEquationSeparate")) == NULL) || r;
+ r = ((glBlendFuncSeparate = (PFNGLBLENDFUNCSEPARATEPROC)glewGetProcAddress((const GLubyte*)"glBlendFuncSeparate")) == NULL) || r;
+ r = ((glCheckFramebufferStatus = (PFNGLCHECKFRAMEBUFFERSTATUSPROC)glewGetProcAddress((const GLubyte*)"glCheckFramebufferStatus")) == NULL) || r;
+ r = ((glCompileShader = (PFNGLCOMPILESHADERPROC)glewGetProcAddress((const GLubyte*)"glCompileShader")) == NULL) || r;
+ r = ((glCreateProgram = (PFNGLCREATEPROGRAMPROC)glewGetProcAddress((const GLubyte*)"glCreateProgram")) == NULL) || r;
+ r = ((glCreateShader = (PFNGLCREATESHADERPROC)glewGetProcAddress((const GLubyte*)"glCreateShader")) == NULL) || r;
+ r = ((glDeleteFramebuffers = (PFNGLDELETEFRAMEBUFFERSPROC)glewGetProcAddress((const GLubyte*)"glDeleteFramebuffers")) == NULL) || r;
+ r = ((glDeleteProgram = (PFNGLDELETEPROGRAMPROC)glewGetProcAddress((const GLubyte*)"glDeleteProgram")) == NULL) || r;
+ r = ((glDeleteRenderbuffers = (PFNGLDELETERENDERBUFFERSPROC)glewGetProcAddress((const GLubyte*)"glDeleteRenderbuffers")) == NULL) || r;
+ r = ((glDeleteShader = (PFNGLDELETESHADERPROC)glewGetProcAddress((const GLubyte*)"glDeleteShader")) == NULL) || r;
+ r = ((glDetachShader = (PFNGLDETACHSHADERPROC)glewGetProcAddress((const GLubyte*)"glDetachShader")) == NULL) || r;
+ r = ((glDisableVertexAttribArray = (PFNGLDISABLEVERTEXATTRIBARRAYPROC)glewGetProcAddress((const GLubyte*)"glDisableVertexAttribArray")) == NULL) || r;
+ r = ((glEnableVertexAttribArray = (PFNGLENABLEVERTEXATTRIBARRAYPROC)glewGetProcAddress((const GLubyte*)"glEnableVertexAttribArray")) == NULL) || r;
+ r = ((glFramebufferRenderbuffer = (PFNGLFRAMEBUFFERRENDERBUFFERPROC)glewGetProcAddress((const GLubyte*)"glFramebufferRenderbuffer")) == NULL) || r;
+ r = ((glFramebufferTexture2D = (PFNGLFRAMEBUFFERTEXTURE2DPROC)glewGetProcAddress((const GLubyte*)"glFramebufferTexture2D")) == NULL) || r;
+ r = ((glGenFramebuffers = (PFNGLGENFRAMEBUFFERSPROC)glewGetProcAddress((const GLubyte*)"glGenFramebuffers")) == NULL) || r;
+ r = ((glGenRenderbuffers = (PFNGLGENRENDERBUFFERSPROC)glewGetProcAddress((const GLubyte*)"glGenRenderbuffers")) == NULL) || r;
+ r = ((glGenerateMipmap = (PFNGLGENERATEMIPMAPPROC)glewGetProcAddress((const GLubyte*)"glGenerateMipmap")) == NULL) || r;
+ r = ((glGetActiveAttrib = (PFNGLGETACTIVEATTRIBPROC)glewGetProcAddress((const GLubyte*)"glGetActiveAttrib")) == NULL) || r;
+ r = ((glGetActiveUniform = (PFNGLGETACTIVEUNIFORMPROC)glewGetProcAddress((const GLubyte*)"glGetActiveUniform")) == NULL) || r;
+ r = ((glGetAttachedShaders = (PFNGLGETATTACHEDSHADERSPROC)glewGetProcAddress((const GLubyte*)"glGetAttachedShaders")) == NULL) || r;
+ r = ((glGetAttribLocation = (PFNGLGETATTRIBLOCATIONPROC)glewGetProcAddress((const GLubyte*)"glGetAttribLocation")) == NULL) || r;
+ r = ((glGetFramebufferAttachmentParameteriv = (PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC)glewGetProcAddress((const GLubyte*)"glGetFramebufferAttachmentParameteriv")) == NULL) || r;
+ r = ((glGetProgramInfoLog = (PFNGLGETPROGRAMINFOLOGPROC)glewGetProcAddress((const GLubyte*)"glGetProgramInfoLog")) == NULL) || r;
+ r = ((glGetProgramiv = (PFNGLGETPROGRAMIVPROC)glewGetProcAddress((const GLubyte*)"glGetProgramiv")) == NULL) || r;
+ r = ((glGetRenderbufferParameteriv = (PFNGLGETRENDERBUFFERPARAMETERIVPROC)glewGetProcAddress((const GLubyte*)"glGetRenderbufferParameteriv")) == NULL) || r;
+ r = ((glGetShaderInfoLog = (PFNGLGETSHADERINFOLOGPROC)glewGetProcAddress((const GLubyte*)"glGetShaderInfoLog")) == NULL) || r;
+ r = ((glGetShaderPrecisionFormat = (PFNGLGETSHADERPRECISIONFORMATPROC)glewGetProcAddress((const GLubyte*)"glGetShaderPrecisionFormat")) == NULL) || r;
+ r = ((glGetShaderSource = (PFNGLGETSHADERSOURCEPROC)glewGetProcAddress((const GLubyte*)"glGetShaderSource")) == NULL) || r;
+ r = ((glGetShaderiv = (PFNGLGETSHADERIVPROC)glewGetProcAddress((const GLubyte*)"glGetShaderiv")) == NULL) || r;
+ r = ((glGetUniformLocation = (PFNGLGETUNIFORMLOCATIONPROC)glewGetProcAddress((const GLubyte*)"glGetUniformLocation")) == NULL) || r;
+ r = ((glGetUniformfv = (PFNGLGETUNIFORMFVPROC)glewGetProcAddress((const GLubyte*)"glGetUniformfv")) == NULL) || r;
+ r = ((glGetUniformiv = (PFNGLGETUNIFORMIVPROC)glewGetProcAddress((const GLubyte*)"glGetUniformiv")) == NULL) || r;
+ r = ((glGetVertexAttribPointerv = (PFNGLGETVERTEXATTRIBPOINTERVPROC)glewGetProcAddress((const GLubyte*)"glGetVertexAttribPointerv")) == NULL) || r;
+ r = ((glGetVertexAttribfv = (PFNGLGETVERTEXATTRIBFVPROC)glewGetProcAddress((const GLubyte*)"glGetVertexAttribfv")) == NULL) || r;
+ r = ((glGetVertexAttribiv = (PFNGLGETVERTEXATTRIBIVPROC)glewGetProcAddress((const GLubyte*)"glGetVertexAttribiv")) == NULL) || r;
+ r = ((glIsFramebuffer = (PFNGLISFRAMEBUFFERPROC)glewGetProcAddress((const GLubyte*)"glIsFramebuffer")) == NULL) || r;
+ r = ((glIsProgram = (PFNGLISPROGRAMPROC)glewGetProcAddress((const GLubyte*)"glIsProgram")) == NULL) || r;
+ r = ((glIsRenderbuffer = (PFNGLISRENDERBUFFERPROC)glewGetProcAddress((const GLubyte*)"glIsRenderbuffer")) == NULL) || r;
+ r = ((glIsShader = (PFNGLISSHADERPROC)glewGetProcAddress((const GLubyte*)"glIsShader")) == NULL) || r;
+ r = ((glLinkProgram = (PFNGLLINKPROGRAMPROC)glewGetProcAddress((const GLubyte*)"glLinkProgram")) == NULL) || r;
+ r = ((glReleaseShaderCompiler = (PFNGLRELEASESHADERCOMPILERPROC)glewGetProcAddress((const GLubyte*)"glReleaseShaderCompiler")) == NULL) || r;
+ r = ((glRenderbufferStorage = (PFNGLRENDERBUFFERSTORAGEPROC)glewGetProcAddress((const GLubyte*)"glRenderbufferStorage")) == NULL) || r;
+ r = ((glShaderBinary = (PFNGLSHADERBINARYPROC)glewGetProcAddress((const GLubyte*)"glShaderBinary")) == NULL) || r;
+ r = ((glShaderSource = (PFNGLSHADERSOURCEPROC)glewGetProcAddress((const GLubyte*)"glShaderSource")) == NULL) || r;
+ r = ((glStencilFuncSeparate = (PFNGLSTENCILFUNCSEPARATEPROC)glewGetProcAddress((const GLubyte*)"glStencilFuncSeparate")) == NULL) || r;
+ r = ((glStencilMaskSeparate = (PFNGLSTENCILMASKSEPARATEPROC)glewGetProcAddress((const GLubyte*)"glStencilMaskSeparate")) == NULL) || r;
+ r = ((glStencilOpSeparate = (PFNGLSTENCILOPSEPARATEPROC)glewGetProcAddress((const GLubyte*)"glStencilOpSeparate")) == NULL) || r;
+ r = ((glUniform1f = (PFNGLUNIFORM1FPROC)glewGetProcAddress((const GLubyte*)"glUniform1f")) == NULL) || r;
+ r = ((glUniform1fv = (PFNGLUNIFORM1FVPROC)glewGetProcAddress((const GLubyte*)"glUniform1fv")) == NULL) || r;
+ r = ((glUniform1i = (PFNGLUNIFORM1IPROC)glewGetProcAddress((const GLubyte*)"glUniform1i")) == NULL) || r;
+ r = ((glUniform1iv = (PFNGLUNIFORM1IVPROC)glewGetProcAddress((const GLubyte*)"glUniform1iv")) == NULL) || r;
+ r = ((glUniform2f = (PFNGLUNIFORM2FPROC)glewGetProcAddress((const GLubyte*)"glUniform2f")) == NULL) || r;
+ r = ((glUniform2fv = (PFNGLUNIFORM2FVPROC)glewGetProcAddress((const GLubyte*)"glUniform2fv")) == NULL) || r;
+ r = ((glUniform2i = (PFNGLUNIFORM2IPROC)glewGetProcAddress((const GLubyte*)"glUniform2i")) == NULL) || r;
+ r = ((glUniform2iv = (PFNGLUNIFORM2IVPROC)glewGetProcAddress((const GLubyte*)"glUniform2iv")) == NULL) || r;
+ r = ((glUniform3f = (PFNGLUNIFORM3FPROC)glewGetProcAddress((const GLubyte*)"glUniform3f")) == NULL) || r;
+ r = ((glUniform3fv = (PFNGLUNIFORM3FVPROC)glewGetProcAddress((const GLubyte*)"glUniform3fv")) == NULL) || r;
+ r = ((glUniform3i = (PFNGLUNIFORM3IPROC)glewGetProcAddress((const GLubyte*)"glUniform3i")) == NULL) || r;
+ r = ((glUniform3iv = (PFNGLUNIFORM3IVPROC)glewGetProcAddress((const GLubyte*)"glUniform3iv")) == NULL) || r;
+ r = ((glUniform4f = (PFNGLUNIFORM4FPROC)glewGetProcAddress((const GLubyte*)"glUniform4f")) == NULL) || r;
+ r = ((glUniform4fv = (PFNGLUNIFORM4FVPROC)glewGetProcAddress((const GLubyte*)"glUniform4fv")) == NULL) || r;
+ r = ((glUniform4i = (PFNGLUNIFORM4IPROC)glewGetProcAddress((const GLubyte*)"glUniform4i")) == NULL) || r;
+ r = ((glUniform4iv = (PFNGLUNIFORM4IVPROC)glewGetProcAddress((const GLubyte*)"glUniform4iv")) == NULL) || r;
+ r = ((glUniformMatrix2fv = (PFNGLUNIFORMMATRIX2FVPROC)glewGetProcAddress((const GLubyte*)"glUniformMatrix2fv")) == NULL) || r;
+ r = ((glUniformMatrix3fv = (PFNGLUNIFORMMATRIX3FVPROC)glewGetProcAddress((const GLubyte*)"glUniformMatrix3fv")) == NULL) || r;
+ r = ((glUniformMatrix4fv = (PFNGLUNIFORMMATRIX4FVPROC)glewGetProcAddress((const GLubyte*)"glUniformMatrix4fv")) == NULL) || r;
+ r = ((glUseProgram = (PFNGLUSEPROGRAMPROC)glewGetProcAddress((const GLubyte*)"glUseProgram")) == NULL) || r;
+ r = ((glValidateProgram = (PFNGLVALIDATEPROGRAMPROC)glewGetProcAddress((const GLubyte*)"glValidateProgram")) == NULL) || r;
+ r = ((glVertexAttrib1f = (PFNGLVERTEXATTRIB1FPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib1f")) == NULL) || r;
+ r = ((glVertexAttrib1fv = (PFNGLVERTEXATTRIB1FVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib1fv")) == NULL) || r;
+ r = ((glVertexAttrib2f = (PFNGLVERTEXATTRIB2FPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib2f")) == NULL) || r;
+ r = ((glVertexAttrib2fv = (PFNGLVERTEXATTRIB2FVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib2fv")) == NULL) || r;
+ r = ((glVertexAttrib3f = (PFNGLVERTEXATTRIB3FPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib3f")) == NULL) || r;
+ r = ((glVertexAttrib3fv = (PFNGLVERTEXATTRIB3FVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib3fv")) == NULL) || r;
+ r = ((glVertexAttrib4f = (PFNGLVERTEXATTRIB4FPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4f")) == NULL) || r;
+ r = ((glVertexAttrib4fv = (PFNGLVERTEXATTRIB4FVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4fv")) == NULL) || r;
+ r = ((glVertexAttribPointer = (PFNGLVERTEXATTRIBPOINTERPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribPointer")) == NULL) || r;
+
+ r = ((glBindBuffer = (PFNGLBINDBUFFERPROC)glewGetProcAddress((const GLubyte*)"glBindBuffer")) == NULL) || r; // NOTE jwilkins: missing function
+ r = ((glBufferData = (PFNGLBUFFERDATAPROC)glewGetProcAddress((const GLubyte*)"glBufferData")) == NULL) || r; // NOTE jwilkins: missing function
+ r = ((glBufferSubData = (PFNGLBUFFERSUBDATAPROC)glewGetProcAddress((const GLubyte*)"glBufferSubData")) == NULL) || r; // NOTE jwilkins: missing function
+ r = ((glDeleteBuffers = (PFNGLDELETEBUFFERSPROC)glewGetProcAddress((const GLubyte*)"glDeleteBuffers")) == NULL) || r; // NOTE jwilkins: missing function
+ r = ((glGenBuffers = (PFNGLGENBUFFERSPROC)glewGetProcAddress((const GLubyte*)"glGenBuffers")) == NULL) || r; // NOTE jwilkins: missing function
+ r = ((glTexParameteri = (PFNGLTEXPARAMETERIPROC)glewGetProcAddress((const GLubyte*)"glTexParameteri")) == NULL) || r; // NOTE jwilkins: missing function
+ r = ((glIsEnabled = (PFNGLISENABLEDPROC)glewGetProcAddress((const GLubyte*)"glIsEnabled")) == NULL) || r; // NOTE jwilkins: missing function
+ r = ((glGetFloatv = (PFNGLGETFLOATVPROC)glewGetProcAddress((const GLubyte*)"glGetFloatv")) == NULL) || r; // NOTE jwilkins: missing function
+ r = ((glDepthRangef = (PFNGLDEPTHRANGEFPROC)glewGetProcAddress((const GLubyte*)"glDepthRangef")) == NULL) || r; // NOTE jwilkins: missing function
+ r = ((glActiveTexture = (PFNGLACTIVETEXTUREPROC)glewGetProcAddress((const GLubyte*)"glActiveTexture")) == NULL) || r; // NOTE jwilkins: missing function
+ r = ((glGetBooleanv = (PFNGLGETBOOLEANVPROC)glewGetProcAddress((const GLubyte*)"glGetBooleanv")) == NULL) || r; // NOTE jwilkins: missing function
+
+ return r;
+}
+
+#endif /* GL_ES_VERSION_2_0 */
+
+#ifdef GL_AMD_compressed_3DC_texture
+
+#endif /* GL_AMD_compressed_3DC_texture */
+
+#ifdef GL_AMD_compressed_ATC_texture
+
+#endif /* GL_AMD_compressed_ATC_texture */
+
+#ifdef GL_AMD_program_binary_Z400
+
+#endif /* GL_AMD_program_binary_Z400 */
+
+#ifdef GL_ANGLE_framebuffer_blit
+
+static GLboolean _glewInit_GL_ANGLE_framebuffer_blit (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glBlitFramebufferANGLE = (PFNGLBLITFRAMEBUFFERANGLEPROC)glewGetProcAddress((const GLubyte*)"glBlitFramebufferANGLE")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_ANGLE_framebuffer_blit */
+
+#ifdef GL_ANGLE_framebuffer_multisample
+
+static GLboolean _glewInit_GL_ANGLE_framebuffer_multisample (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glRenderbufferStorageMultisampleANGLE = (PFNGLRENDERBUFFERSTORAGEMULTISAMPLEANGLEPROC)glewGetProcAddress((const GLubyte*)"glRenderbufferStorageMultisampleANGLE")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_ANGLE_framebuffer_multisample */
+
+#ifdef GL_ANGLE_instanced_arrays
+
+static GLboolean _glewInit_GL_ANGLE_instanced_arrays (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glDrawArraysInstancedANGLE = (PFNGLDRAWARRAYSINSTANCEDANGLEPROC)glewGetProcAddress((const GLubyte*)"glDrawArraysInstancedANGLE")) == NULL) || r;
+ r = ((glDrawElementsInstancedANGLE = (PFNGLDRAWELEMENTSINSTANCEDANGLEPROC)glewGetProcAddress((const GLubyte*)"glDrawElementsInstancedANGLE")) == NULL) || r;
+ r = ((glVertexAttribDivisorANGLE = (PFNGLVERTEXATTRIBDIVISORANGLEPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribDivisorANGLE")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_ANGLE_instanced_arrays */
+
+#ifdef GL_ANGLE_pack_reverse_row_order
+
+#endif /* GL_ANGLE_pack_reverse_row_order */
+
+#ifdef GL_ANGLE_texture_compression_dxt3
+
+#endif /* GL_ANGLE_texture_compression_dxt3 */
+
+#ifdef GL_ANGLE_texture_compression_dxt5
+
+#endif /* GL_ANGLE_texture_compression_dxt5 */
+
+#ifdef GL_ANGLE_texture_usage
+
+#endif /* GL_ANGLE_texture_usage */
+
+#ifdef GL_ANGLE_translated_shader_source
+
+static GLboolean _glewInit_GL_ANGLE_translated_shader_source (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glGetTranslatedShaderSourceANGLE = (PFNGLGETTRANSLATEDSHADERSOURCEANGLEPROC)glewGetProcAddress((const GLubyte*)"glGetTranslatedShaderSourceANGLE")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_ANGLE_translated_shader_source */
+
+#ifdef GL_APPLE_copy_texture_levels
+
+static GLboolean _glewInit_GL_APPLE_copy_texture_levels (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glCopyTextureLevelsAPPLE = (PFNGLCOPYTEXTURELEVELSAPPLEPROC)glewGetProcAddress((const GLubyte*)"glCopyTextureLevelsAPPLE")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_APPLE_copy_texture_levels */
+
+#ifdef GL_APPLE_framebuffer_multisample
+
+static GLboolean _glewInit_GL_APPLE_framebuffer_multisample (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glRenderbufferStorageMultisampleAPPLE = (PFNGLRENDERBUFFERSTORAGEMULTISAMPLEAPPLEPROC)glewGetProcAddress((const GLubyte*)"glRenderbufferStorageMultisampleAPPLE")) == NULL) || r;
+ r = ((glResolveMultisampleFramebufferAPPLE = (PFNGLRESOLVEMULTISAMPLEFRAMEBUFFERAPPLEPROC)glewGetProcAddress((const GLubyte*)"glResolveMultisampleFramebufferAPPLE")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_APPLE_framebuffer_multisample */
+
+#ifdef GL_APPLE_sync
+
+static GLboolean _glewInit_GL_APPLE_sync (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glClientWaitSyncAPPLE = (PFNGLCLIENTWAITSYNCAPPLEPROC)glewGetProcAddress((const GLubyte*)"glClientWaitSyncAPPLE")) == NULL) || r;
+ r = ((glDeleteSyncAPPLE = (PFNGLDELETESYNCAPPLEPROC)glewGetProcAddress((const GLubyte*)"glDeleteSyncAPPLE")) == NULL) || r;
+ r = ((glFenceSyncAPPLE = (PFNGLFENCESYNCAPPLEPROC)glewGetProcAddress((const GLubyte*)"glFenceSyncAPPLE")) == NULL) || r;
+ r = ((glGetInteger64vAPPLE = (PFNGLGETINTEGER64VAPPLEPROC)glewGetProcAddress((const GLubyte*)"glGetInteger64vAPPLE")) == NULL) || r;
+ r = ((glGetSyncivAPPLE = (PFNGLGETSYNCIVAPPLEPROC)glewGetProcAddress((const GLubyte*)"glGetSyncivAPPLE")) == NULL) || r;
+ r = ((glIsSyncAPPLE = (PFNGLISSYNCAPPLEPROC)glewGetProcAddress((const GLubyte*)"glIsSyncAPPLE")) == NULL) || r;
+ r = ((glWaitSyncAPPLE = (PFNGLWAITSYNCAPPLEPROC)glewGetProcAddress((const GLubyte*)"glWaitSyncAPPLE")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_APPLE_sync */
+
+#ifdef GL_APPLE_texture_2D_limited_npot
+
+#endif /* GL_APPLE_texture_2D_limited_npot */
+
+#ifdef GL_APPLE_texture_format_BGRA8888
+
+#endif /* GL_APPLE_texture_format_BGRA8888 */
+
+#ifdef GL_APPLE_texture_max_level
+
+#endif /* GL_APPLE_texture_max_level */
+
+#ifdef GL_ARM_mali_program_binary
+
+#endif /* GL_ARM_mali_program_binary */
+
+#ifdef GL_ARM_mali_shader_binary
+
+#endif /* GL_ARM_mali_shader_binary */
+
+#ifdef GL_ARM_rgba8
+
+#endif /* GL_ARM_rgba8 */
+
+#ifdef GL_DMP_shader_binary
+
+#endif /* GL_DMP_shader_binary */
+
+#ifdef GL_EXT_color_buffer_half_float
+
+#endif /* GL_EXT_color_buffer_half_float */
+
+#ifdef GL_EXT_debug_label
+
+static GLboolean _glewInit_GL_EXT_debug_label (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glGetObjectLabelEXT = (PFNGLGETOBJECTLABELEXTPROC)glewGetProcAddress((const GLubyte*)"glGetObjectLabelEXT")) == NULL) || r;
+ r = ((glLabelObjectEXT = (PFNGLLABELOBJECTEXTPROC)glewGetProcAddress((const GLubyte*)"glLabelObjectEXT")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_EXT_debug_label */
+
+#ifdef GL_EXT_debug_marker
+
+static GLboolean _glewInit_GL_EXT_debug_marker (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glInsertEventMarkerEXT = (PFNGLINSERTEVENTMARKEREXTPROC)glewGetProcAddress((const GLubyte*)"glInsertEventMarkerEXT")) == NULL) || r;
+ r = ((glPushGroupMarkerEXT = (PFNGLPUSHGROUPMARKEREXTPROC)glewGetProcAddress((const GLubyte*)"glPushGroupMarkerEXT")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_EXT_debug_marker */
+
+#ifdef GL_EXT_discard_framebuffer
+
+static GLboolean _glewInit_GL_EXT_discard_framebuffer (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glDiscardFramebufferEXT = (PFNGLDISCARDFRAMEBUFFEREXTPROC)glewGetProcAddress((const GLubyte*)"glDiscardFramebufferEXT")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_EXT_discard_framebuffer */
+
+#ifdef GL_EXT_frag_depth
+
+#endif /* GL_EXT_frag_depth */
+
+#ifdef GL_EXT_map_buffer_range
+
+static GLboolean _glewInit_GL_EXT_map_buffer_range (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glFlushMappedBufferRangeEXT = (PFNGLFLUSHMAPPEDBUFFERRANGEEXTPROC)glewGetProcAddress((const GLubyte*)"glFlushMappedBufferRangeEXT")) == NULL) || r;
+ r = ((glMapBufferRangeEXT = (PFNGLMAPBUFFERRANGEEXTPROC)glewGetProcAddress((const GLubyte*)"glMapBufferRangeEXT")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_EXT_map_buffer_range */
+
+#ifdef GL_EXT_multisampled_render_to_texture
+
+static GLboolean _glewInit_GL_EXT_multisampled_render_to_texture (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glFramebufferTexture2DMultisampleEXT = (PFNGLFRAMEBUFFERTEXTURE2DMULTISAMPLEEXTPROC)glewGetProcAddress((const GLubyte*)"glFramebufferTexture2DMultisampleEXT")) == NULL) || r;
+ r = ((glRenderbufferStorageMultisampleEXT = (PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC)glewGetProcAddress((const GLubyte*)"glRenderbufferStorageMultisampleEXT")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_EXT_multisampled_render_to_texture */
+
+#ifdef GL_EXT_multiview_draw_buffers
+
+static GLboolean _glewInit_GL_EXT_multiview_draw_buffers (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glDrawBuffersIndexedEXT = (PFNGLDRAWBUFFERSINDEXEDEXTPROC)glewGetProcAddress((const GLubyte*)"glDrawBuffersIndexedEXT")) == NULL) || r;
+ r = ((glGetIntegeri_vEXT = (PFNGLGETINTEGERI_VEXTPROC)glewGetProcAddress((const GLubyte*)"glGetIntegeri_vEXT")) == NULL) || r;
+ r = ((glReadBufferIndexedEXT = (PFNGLREADBUFFERINDEXEDEXTPROC)glewGetProcAddress((const GLubyte*)"glReadBufferIndexedEXT")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_EXT_multiview_draw_buffers */
+
+#ifdef GL_EXT_occlusion_query_boolean
+
+static GLboolean _glewInit_GL_EXT_occlusion_query_boolean (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glBeginQueryEXT = (PFNGLBEGINQUERYEXTPROC)glewGetProcAddress((const GLubyte*)"glBeginQueryEXT")) == NULL) || r;
+ r = ((glDeleteQueriesEXT = (PFNGLDELETEQUERIESEXTPROC)glewGetProcAddress((const GLubyte*)"glDeleteQueriesEXT")) == NULL) || r;
+ r = ((glEndQueryEXT = (PFNGLENDQUERYEXTPROC)glewGetProcAddress((const GLubyte*)"glEndQueryEXT")) == NULL) || r;
+ r = ((glGenQueriesEXT = (PFNGLGENQUERIESEXTPROC)glewGetProcAddress((const GLubyte*)"glGenQueriesEXT")) == NULL) || r;
+ r = ((glGetQueryObjectuivEXT = (PFNGLGETQUERYOBJECTUIVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetQueryObjectuivEXT")) == NULL) || r;
+ r = ((glGetQueryivEXT = (PFNGLGETQUERYIVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetQueryivEXT")) == NULL) || r;
+ r = ((glIsQueryEXT = (PFNGLISQUERYEXTPROC)glewGetProcAddress((const GLubyte*)"glIsQueryEXT")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_EXT_occlusion_query_boolean */
+
+#ifdef GL_EXT_read_format_bgra
+
+#endif /* GL_EXT_read_format_bgra */
+
+#ifdef GL_EXT_robustness
+
+static GLboolean _glewInit_GL_EXT_robustness (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glGetnUniformfvEXT = (PFNGLGETNUNIFORMFVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetnUniformfvEXT")) == NULL) || r;
+ r = ((glGetnUniformivEXT = (PFNGLGETNUNIFORMIVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetnUniformivEXT")) == NULL) || r;
+ r = ((glReadnPixelsEXT = (PFNGLREADNPIXELSEXTPROC)glewGetProcAddress((const GLubyte*)"glReadnPixelsEXT")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_EXT_robustness */
+
+#ifdef GL_EXT_sRGB
+
+#endif /* GL_EXT_sRGB */
+
+#ifdef GL_EXT_shader_framebuffer_fetch
+
+#endif /* GL_EXT_shader_framebuffer_fetch */
+
+#ifdef GL_EXT_shader_texture_lod
+
+#endif /* GL_EXT_shader_texture_lod */
+
+#ifdef GL_EXT_shadow_samplers
+
+#endif /* GL_EXT_shadow_samplers */
+
+#ifdef GL_EXT_texture_format_BGRA8888
+
+#endif /* GL_EXT_texture_format_BGRA8888 */
+
+#ifdef GL_EXT_texture_rg
+
+#endif /* GL_EXT_texture_rg */
+
+#ifdef GL_EXT_texture_storage
+
+static GLboolean _glewInit_GL_EXT_texture_storage (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glTexStorage1DEXT = (PFNGLTEXSTORAGE1DEXTPROC)glewGetProcAddress((const GLubyte*)"glTexStorage1DEXT")) == NULL) || r;
+ r = ((glTexStorage2DEXT = (PFNGLTEXSTORAGE2DEXTPROC)glewGetProcAddress((const GLubyte*)"glTexStorage2DEXT")) == NULL) || r;
+ r = ((glTexStorage3DEXT = (PFNGLTEXSTORAGE3DEXTPROC)glewGetProcAddress((const GLubyte*)"glTexStorage3DEXT")) == NULL) || r;
+ r = ((glTextureStorage1DEXT = (PFNGLTEXTURESTORAGE1DEXTPROC)glewGetProcAddress((const GLubyte*)"glTextureStorage1DEXT")) == NULL) || r;
+ r = ((glTextureStorage2DEXT = (PFNGLTEXTURESTORAGE2DEXTPROC)glewGetProcAddress((const GLubyte*)"glTextureStorage2DEXT")) == NULL) || r;
+ r = ((glTextureStorage3DEXT = (PFNGLTEXTURESTORAGE3DEXTPROC)glewGetProcAddress((const GLubyte*)"glTextureStorage3DEXT")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_EXT_texture_storage */
+
+#ifdef GL_EXT_texture_type_2_10_10_10_REV
+
+#endif /* GL_EXT_texture_type_2_10_10_10_REV */
+
+#ifdef GL_EXT_unpack_subimage
+
+#endif /* GL_EXT_unpack_subimage */
+
+#ifdef GL_FJ_shader_binary_GCCSO
+
+#endif /* GL_FJ_shader_binary_GCCSO */
+
+#ifdef GL_IMG_multisampled_render_to_texture
+
+static GLboolean _glewInit_GL_IMG_multisampled_render_to_texture (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glFramebufferTexture2DMultisampleIMG = (PFNGLFRAMEBUFFERTEXTURE2DMULTISAMPLEIMGPROC)glewGetProcAddress((const GLubyte*)"glFramebufferTexture2DMultisampleIMG")) == NULL) || r;
+ r = ((glRenderbufferStorageMultisampleIMG = (PFNGLRENDERBUFFERSTORAGEMULTISAMPLEIMGPROC)glewGetProcAddress((const GLubyte*)"glRenderbufferStorageMultisampleIMG")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_IMG_multisampled_render_to_texture */
+
+#ifdef GL_IMG_program_binary
+
+#endif /* GL_IMG_program_binary */
+
+#ifdef GL_IMG_read_format
+
+#endif /* GL_IMG_read_format */
+
+#ifdef GL_IMG_shader_binary
+
+#endif /* GL_IMG_shader_binary */
+
+#ifdef GL_IMG_texture_compression_pvrtc
+
+#endif /* GL_IMG_texture_compression_pvrtc */
+
+#ifdef GL_IMG_texture_env_enhanced_fixed_function
+
+#endif /* GL_IMG_texture_env_enhanced_fixed_function */
+
+#ifdef GL_IMG_user_clip_plane
+
+static GLboolean _glewInit_GL_IMG_user_clip_plane (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glClipPlanefIMG = (PFNGLCLIPPLANEFIMGPROC)glewGetProcAddress((const GLubyte*)"glClipPlanefIMG")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_IMG_user_clip_plane */
+
+#ifdef GL_NV_3dvision_settings
+
+static GLboolean _glewInit_GL_NV_3dvision_settings (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glStereoParameterfNV = (PFNGLSTEREOPARAMETERFNVPROC)glewGetProcAddress((const GLubyte*)"glStereoParameterfNV")) == NULL) || r;
+ r = ((glStereoParameteriNV = (PFNGLSTEREOPARAMETERINVPROC)glewGetProcAddress((const GLubyte*)"glStereoParameteriNV")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_NV_3dvision_settings */
+
+#ifdef GL_NV_EGL_stream_consumer_external
+
+#endif /* GL_NV_EGL_stream_consumer_external */
+
+#ifdef GL_NV_bgr
+
+#endif /* GL_NV_bgr */
+
+#ifdef GL_NV_coverage_sample
+
+static GLboolean _glewInit_GL_NV_coverage_sample (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glCoverageMaskNV = (PFNGLCOVERAGEMASKNVPROC)glewGetProcAddress((const GLubyte*)"glCoverageMaskNV")) == NULL) || r;
+ r = ((glCoverageOperationNV = (PFNGLCOVERAGEOPERATIONNVPROC)glewGetProcAddress((const GLubyte*)"glCoverageOperationNV")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_NV_coverage_sample */
+
+#ifdef GL_NV_depth_nonlinear
+
+#endif /* GL_NV_depth_nonlinear */
+
+#ifdef GL_NV_draw_buffers
+
+static GLboolean _glewInit_GL_NV_draw_buffers (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glDrawBuffersNV = (PFNGLDRAWBUFFERSNVPROC)glewGetProcAddress((const GLubyte*)"glDrawBuffersNV")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_NV_draw_buffers */
+
+#ifdef GL_NV_fbo_color_attachments
+
+#endif /* GL_NV_fbo_color_attachments */
+
+#ifdef GL_NV_pack_subimage
+
+#endif /* GL_NV_pack_subimage */
+
+#ifdef GL_NV_packed_float
+
+#endif /* GL_NV_packed_float */
+
+#ifdef GL_NV_packed_float_linear
+
+#endif /* GL_NV_packed_float_linear */
+
+#ifdef GL_NV_pixel_buffer_object
+
+#endif /* GL_NV_pixel_buffer_object */
+
+#ifdef GL_NV_platform_binary
+
+#endif /* GL_NV_platform_binary */
+
+#ifdef GL_NV_read_buffer
+
+static GLboolean _glewInit_GL_NV_read_buffer (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glReadBufferNV = (PFNGLREADBUFFERNVPROC)glewGetProcAddress((const GLubyte*)"glReadBufferNV")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_NV_read_buffer */
+
+#ifdef GL_NV_read_buffer_front
+
+#endif /* GL_NV_read_buffer_front */
+
+#ifdef GL_NV_read_depth
+
+#endif /* GL_NV_read_depth */
+
+#ifdef GL_NV_read_depth_stencil
+
+#endif /* GL_NV_read_depth_stencil */
+
+#ifdef GL_NV_read_stencil
+
+#endif /* GL_NV_read_stencil */
+
+#ifdef GL_NV_texture_array
+
+static GLboolean _glewInit_GL_NV_texture_array (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glCompressedTexImage3DNV = (PFNGLCOMPRESSEDTEXIMAGE3DNVPROC)glewGetProcAddress((const GLubyte*)"glCompressedTexImage3DNV")) == NULL) || r;
+ r = ((glCompressedTexSubImage3DNV = (PFNGLCOMPRESSEDTEXSUBIMAGE3DNVPROC)glewGetProcAddress((const GLubyte*)"glCompressedTexSubImage3DNV")) == NULL) || r;
+ r = ((glCopyTexSubImage3DNV = (PFNGLCOPYTEXSUBIMAGE3DNVPROC)glewGetProcAddress((const GLubyte*)"glCopyTexSubImage3DNV")) == NULL) || r;
+ r = ((glFramebufferTextureLayerNV = (PFNGLFRAMEBUFFERTEXTURELAYERNVPROC)glewGetProcAddress((const GLubyte*)"glFramebufferTextureLayerNV")) == NULL) || r;
+ r = ((glTexImage3DNV = (PFNGLTEXIMAGE3DNVPROC)glewGetProcAddress((const GLubyte*)"glTexImage3DNV")) == NULL) || r;
+ r = ((glTexSubImage3DNV = (PFNGLTEXSUBIMAGE3DNVPROC)glewGetProcAddress((const GLubyte*)"glTexSubImage3DNV")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_NV_texture_array */
+
+#ifdef GL_NV_texture_compression_latc
+
+#endif /* GL_NV_texture_compression_latc */
+
+#ifdef GL_NV_texture_compression_s3tc
+
+#endif /* GL_NV_texture_compression_s3tc */
+
+#ifdef GL_NV_texture_compression_s3tc_update
+
+#endif /* GL_NV_texture_compression_s3tc_update */
+
+#ifdef GL_NV_texture_npot_2D_mipmap
+
+#endif /* GL_NV_texture_npot_2D_mipmap */
+
+#ifdef GL_OES_EGL_image
+
+static GLboolean _glewInit_GL_OES_EGL_image (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glEGLImageTargetRenderbufferStorageOES = (PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC)glewGetProcAddress((const GLubyte*)"glEGLImageTargetRenderbufferStorageOES")) == NULL) || r;
+ r = ((glEGLImageTargetTexture2DOES = (PFNGLEGLIMAGETARGETTEXTURE2DOESPROC)glewGetProcAddress((const GLubyte*)"glEGLImageTargetTexture2DOES")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_OES_EGL_image */
+
+#ifdef GL_OES_EGL_image_external
+
+static GLboolean _glewInit_GL_OES_EGL_image_external(GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+ r = ((glEGLImageTargetTexture2DOES = (PFNGLEGLIMAGETARGETTEXTURE2DOESPROC)glewGetProcAddress((const GLubyte*)"glEGLImageTargetTexture2DOES")) == NULL) || r;
+ return r;
+}
+#endif /* GL_OES_EGL_image_external */
+
+#ifdef GL_OES_EGL_sync
+
+#endif /* GL_OES_EGL_sync */
+
+#ifdef GL_OES_blend_equation_separate
+
+static GLboolean _glewInit_GL_OES_blend_equation_separate (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glBlendEquationSeparateOES = (PFNGLBLENDEQUATIONSEPARATEOESPROC)glewGetProcAddress((const GLubyte*)"glBlendEquationSeparateOES")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_OES_blend_equation_separate */
+
+#ifdef GL_OES_blend_func_separate
+
+static GLboolean _glewInit_GL_OES_blend_func_separate (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glBlendFuncSeparateOES = (PFNGLBLENDFUNCSEPARATEOESPROC)glewGetProcAddress((const GLubyte*)"glBlendFuncSeparateOES")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_OES_blend_func_separate */
+
+#ifdef GL_OES_blend_subtract
+
+static GLboolean _glewInit_GL_OES_blend_subtract (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glBlendEquationOES = (PFNGLBLENDEQUATIONOESPROC)glewGetProcAddress((const GLubyte*)"glBlendEquationOES")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_OES_blend_subtract */
+
+#ifdef GL_OES_compressed_ETC1_RGB8_texture
+
+#endif /* GL_OES_compressed_ETC1_RGB8_texture */
+
+#ifdef GL_OES_depth24
+
+#endif /* GL_OES_depth24 */
+
+#ifdef GL_OES_depth32
+
+#endif /* GL_OES_depth32 */
+
+#ifdef GL_OES_depth_texture
+
+#endif /* GL_OES_depth_texture */
+
+#ifdef GL_OES_depth_texture_cube_map
+
+#endif /* GL_OES_depth_texture_cube_map */
+
+#ifdef GL_OES_draw_texture
+
+#endif /* GL_OES_draw_texture */
+
+#ifdef GL_OES_element_index_uint
+
+#endif /* GL_OES_element_index_uint */
+
+#ifdef GL_OES_extended_matrix_palette
+
+#endif /* GL_OES_extended_matrix_palette */
+
+#ifdef GL_OES_fbo_render_mipmap
+
+#endif /* GL_OES_fbo_render_mipmap */
+
+#ifdef GL_OES_fragment_precision_high
+
+#endif /* GL_OES_fragment_precision_high */
+
+#ifdef GL_OES_framebuffer_object
+
+static GLboolean _glewInit_GL_OES_framebuffer_object (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glBindFramebufferOES = (PFNGLBINDFRAMEBUFFEROESPROC)glewGetProcAddress((const GLubyte*)"glBindFramebufferOES")) == NULL) || r;
+ r = ((glBindRenderbufferOES = (PFNGLBINDRENDERBUFFEROESPROC)glewGetProcAddress((const GLubyte*)"glBindRenderbufferOES")) == NULL) || r;
+ r = ((glCheckFramebufferStatusOES = (PFNGLCHECKFRAMEBUFFERSTATUSOESPROC)glewGetProcAddress((const GLubyte*)"glCheckFramebufferStatusOES")) == NULL) || r;
+ r = ((glDeleteFramebuffersOES = (PFNGLDELETEFRAMEBUFFERSOESPROC)glewGetProcAddress((const GLubyte*)"glDeleteFramebuffersOES")) == NULL) || r;
+ r = ((glDeleteRenderbuffersOES = (PFNGLDELETERENDERBUFFERSOESPROC)glewGetProcAddress((const GLubyte*)"glDeleteRenderbuffersOES")) == NULL) || r;
+ r = ((glFramebufferRenderbufferOES = (PFNGLFRAMEBUFFERRENDERBUFFEROESPROC)glewGetProcAddress((const GLubyte*)"glFramebufferRenderbufferOES")) == NULL) || r;
+ r = ((glFramebufferTexture2DOES = (PFNGLFRAMEBUFFERTEXTURE2DOESPROC)glewGetProcAddress((const GLubyte*)"glFramebufferTexture2DOES")) == NULL) || r;
+ r = ((glGenFramebuffersOES = (PFNGLGENFRAMEBUFFERSOESPROC)glewGetProcAddress((const GLubyte*)"glGenFramebuffersOES")) == NULL) || r;
+ r = ((glGenRenderbuffersOES = (PFNGLGENRENDERBUFFERSOESPROC)glewGetProcAddress((const GLubyte*)"glGenRenderbuffersOES")) == NULL) || r;
+ r = ((glGenerateMipmapOES = (PFNGLGENERATEMIPMAPOESPROC)glewGetProcAddress((const GLubyte*)"glGenerateMipmapOES")) == NULL) || r;
+ r = ((glGetFramebufferAttachmentParameterivOES = (PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVOESPROC)glewGetProcAddress((const GLubyte*)"glGetFramebufferAttachmentParameterivOES")) == NULL) || r;
+ r = ((glGetRenderbufferParameterivOES = (PFNGLGETRENDERBUFFERPARAMETERIVOESPROC)glewGetProcAddress((const GLubyte*)"glGetRenderbufferParameterivOES")) == NULL) || r;
+ r = ((glIsFramebufferOES = (PFNGLISFRAMEBUFFEROESPROC)glewGetProcAddress((const GLubyte*)"glIsFramebufferOES")) == NULL) || r;
+ r = ((glIsRenderbufferOES = (PFNGLISRENDERBUFFEROESPROC)glewGetProcAddress((const GLubyte*)"glIsRenderbufferOES")) == NULL) || r;
+ r = ((glRenderbufferStorageOES = (PFNGLRENDERBUFFERSTORAGEOESPROC)glewGetProcAddress((const GLubyte*)"glRenderbufferStorageOES")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_OES_framebuffer_object */
+
+#ifdef GL_OES_get_program_binary
+
+static GLboolean _glewInit_GL_OES_get_program_binary (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glGetProgramBinaryOES = (PFNGLGETPROGRAMBINARYOESPROC)glewGetProcAddress((const GLubyte*)"glGetProgramBinaryOES")) == NULL) || r;
+ r = ((glProgramBinaryOES = (PFNGLPROGRAMBINARYOESPROC)glewGetProcAddress((const GLubyte*)"glProgramBinaryOES")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_OES_get_program_binary */
+
+#ifdef GL_OES_mapbuffer
+
+static GLboolean _glewInit_GL_OES_mapbuffer (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glGetBufferPointervOES = (PFNGLGETBUFFERPOINTERVOESPROC)glewGetProcAddress((const GLubyte*)"glGetBufferPointervOES")) == NULL) || r;
+ r = ((glMapBufferOES = (PFNGLMAPBUFFEROESPROC)glewGetProcAddress((const GLubyte*)"glMapBufferOES")) == NULL) || r;
+ r = ((glUnmapBufferOES = (PFNGLUNMAPBUFFEROESPROC)glewGetProcAddress((const GLubyte*)"glUnmapBufferOES")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_OES_mapbuffer */
+
+#ifdef GL_OES_matrix_get
+
+#endif /* GL_OES_matrix_get */
+
+#ifdef GL_OES_matrix_palette
+
+static GLboolean _glewInit_GL_OES_matrix_palette (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glCurrentPaletteMatrixOES = (PFNGLCURRENTPALETTEMATRIXOESPROC)glewGetProcAddress((const GLubyte*)"glCurrentPaletteMatrixOES")) == NULL) || r;
+ r = ((glMatrixIndexPointerOES = (PFNGLMATRIXINDEXPOINTEROESPROC)glewGetProcAddress((const GLubyte*)"glMatrixIndexPointerOES")) == NULL) || r;
+ r = ((glWeightPointerOES = (PFNGLWEIGHTPOINTEROESPROC)glewGetProcAddress((const GLubyte*)"glWeightPointerOES")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_OES_matrix_palette */
+
+#ifdef GL_OES_packed_depth_stencil
+
+#endif /* GL_OES_packed_depth_stencil */
+
+#ifdef GL_OES_point_size_array
+
+static GLboolean _glewInit_GL_OES_point_size_array (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glPointSizePointerOES = (PFNGLPOINTSIZEPOINTEROESPROC)glewGetProcAddress((const GLubyte*)"glPointSizePointerOES")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_OES_point_size_array */
+
+#ifdef GL_OES_point_sprite
+
+#endif /* GL_OES_point_sprite */
+
+#ifdef GL_OES_required_internalformat
+
+#endif /* GL_OES_required_internalformat */
+
+#ifdef GL_OES_rgb8_rgba8
+
+#endif /* GL_OES_rgb8_rgba8 */
+
+#ifdef GL_OES_standard_derivatives
+
+#endif /* GL_OES_standard_derivatives */
+
+#ifdef GL_OES_stencil1
+
+#endif /* GL_OES_stencil1 */
+
+#ifdef GL_OES_stencil4
+
+#endif /* GL_OES_stencil4 */
+
+#ifdef GL_OES_stencil8
+
+#endif /* GL_OES_stencil8 */
+
+#ifdef GL_OES_surfaceless_context
+
+#endif /* GL_OES_surfaceless_context */
+
+#ifdef GL_OES_texture_3D
+
+static GLboolean _glewInit_GL_OES_texture_3D (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glCompressedTexImage3DOES = (PFNGLCOMPRESSEDTEXIMAGE3DOESPROC)glewGetProcAddress((const GLubyte*)"glCompressedTexImage3DOES")) == NULL) || r;
+ r = ((glCompressedTexSubImage3DOES = (PFNGLCOMPRESSEDTEXSUBIMAGE3DOESPROC)glewGetProcAddress((const GLubyte*)"glCompressedTexSubImage3DOES")) == NULL) || r;
+ r = ((glCopyTexSubImage3DOES = (PFNGLCOPYTEXSUBIMAGE3DOESPROC)glewGetProcAddress((const GLubyte*)"glCopyTexSubImage3DOES")) == NULL) || r;
+ r = ((glFramebufferTexture3DOES = (PFNGLFRAMEBUFFERTEXTURE3DOESPROC)glewGetProcAddress((const GLubyte*)"glFramebufferTexture3DOES")) == NULL) || r;
+ r = ((glTexImage3DOES = (PFNGLTEXIMAGE3DOESPROC)glewGetProcAddress((const GLubyte*)"glTexImage3DOES")) == NULL) || r;
+ r = ((glTexSubImage3DOES = (PFNGLTEXSUBIMAGE3DOESPROC)glewGetProcAddress((const GLubyte*)"glTexSubImage3DOES")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_OES_texture_3D */
+
+#ifdef GL_OES_texture_cube_map
+
+static GLboolean _glewInit_GL_OES_texture_cube_map (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glGetTexGenfvOES = (PFNGLGETTEXGENFVOESPROC)glewGetProcAddress((const GLubyte*)"glGetTexGenfvOES")) == NULL) || r;
+ r = ((glGetTexGenivOES = (PFNGLGETTEXGENIVOESPROC)glewGetProcAddress((const GLubyte*)"glGetTexGenivOES")) == NULL) || r;
+ r = ((glGetTexGenxvOES = (PFNGLGETTEXGENXVOESPROC)glewGetProcAddress((const GLubyte*)"glGetTexGenxvOES")) == NULL) || r;
+ r = ((glTexGenfOES = (PFNGLTEXGENFOESPROC)glewGetProcAddress((const GLubyte*)"glTexGenfOES")) == NULL) || r;
+ r = ((glTexGenfvOES = (PFNGLTEXGENFVOESPROC)glewGetProcAddress((const GLubyte*)"glTexGenfvOES")) == NULL) || r;
+ r = ((glTexGeniOES = (PFNGLTEXGENIOESPROC)glewGetProcAddress((const GLubyte*)"glTexGeniOES")) == NULL) || r;
+ r = ((glTexGenivOES = (PFNGLTEXGENIVOESPROC)glewGetProcAddress((const GLubyte*)"glTexGenivOES")) == NULL) || r;
+ r = ((glTexGenxOES = (PFNGLTEXGENXOESPROC)glewGetProcAddress((const GLubyte*)"glTexGenxOES")) == NULL) || r;
+ r = ((glTexGenxvOES = (PFNGLTEXGENXVOESPROC)glewGetProcAddress((const GLubyte*)"glTexGenxvOES")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_OES_texture_cube_map */
+
+#ifdef GL_OES_texture_env_crossbar
+
+#endif /* GL_OES_texture_env_crossbar */
+
+#ifdef GL_OES_texture_mirrored_repeat
+
+#endif /* GL_OES_texture_mirrored_repeat */
+
+#ifdef GL_OES_texture_npot
+
+#endif /* GL_OES_texture_npot */
+
+#ifdef GL_OES_vertex_array_object
+
+static GLboolean _glewInit_GL_OES_vertex_array_object (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glBindVertexArrayOES = (PFNGLBINDVERTEXARRAYOESPROC)glewGetProcAddress((const GLubyte*)"glBindVertexArrayOES")) == NULL) || r;
+ r = ((glDeleteVertexArraysOES = (PFNGLDELETEVERTEXARRAYSOESPROC)glewGetProcAddress((const GLubyte*)"glDeleteVertexArraysOES")) == NULL) || r;
+ r = ((glGenVertexArraysOES = (PFNGLGENVERTEXARRAYSOESPROC)glewGetProcAddress((const GLubyte*)"glGenVertexArraysOES")) == NULL) || r;
+ r = ((glIsVertexArrayOES = (PFNGLISVERTEXARRAYOESPROC)glewGetProcAddress((const GLubyte*)"glIsVertexArrayOES")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_OES_vertex_array_object */
+
+#ifdef GL_OES_vertex_half_float
+
+#endif /* GL_OES_vertex_half_float */
+
+#ifdef GL_OES_vertex_type_10_10_10_2
+
+#endif /* GL_OES_vertex_type_10_10_10_2 */
+
+#ifdef GL_QCOM_alpha_test
+
+static GLboolean _glewInit_GL_QCOM_alpha_test (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glAlphaFuncQCOM = (PFNGLALPHAFUNCQCOMPROC)glewGetProcAddress((const GLubyte*)"glAlphaFuncQCOM")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_QCOM_alpha_test */
+
+#ifdef GL_QCOM_binning_control
+
+#endif /* GL_QCOM_binning_control */
+
+#ifdef GL_QCOM_driver_control
+
+static GLboolean _glewInit_GL_QCOM_driver_control (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glDisableDriverControlQCOM = (PFNGLDISABLEDRIVERCONTROLQCOMPROC)glewGetProcAddress((const GLubyte*)"glDisableDriverControlQCOM")) == NULL) || r;
+ r = ((glEnableDriverControlQCOM = (PFNGLENABLEDRIVERCONTROLQCOMPROC)glewGetProcAddress((const GLubyte*)"glEnableDriverControlQCOM")) == NULL) || r;
+ r = ((glGetDriverControlStringQCOM = (PFNGLGETDRIVERCONTROLSTRINGQCOMPROC)glewGetProcAddress((const GLubyte*)"glGetDriverControlStringQCOM")) == NULL) || r;
+ r = ((glGetDriverControlsQCOM = (PFNGLGETDRIVERCONTROLSQCOMPROC)glewGetProcAddress((const GLubyte*)"glGetDriverControlsQCOM")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_QCOM_driver_control */
+
+#ifdef GL_QCOM_extended_get
+
+static GLboolean _glewInit_GL_QCOM_extended_get (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glExtGetBufferPointervQCOM = (PFNGLEXTGETBUFFERPOINTERVQCOMPROC)glewGetProcAddress((const GLubyte*)"glExtGetBufferPointervQCOM")) == NULL) || r;
+ r = ((glExtGetBuffersQCOM = (PFNGLEXTGETBUFFERSQCOMPROC)glewGetProcAddress((const GLubyte*)"glExtGetBuffersQCOM")) == NULL) || r;
+ r = ((glExtGetFramebuffersQCOM = (PFNGLEXTGETFRAMEBUFFERSQCOMPROC)glewGetProcAddress((const GLubyte*)"glExtGetFramebuffersQCOM")) == NULL) || r;
+ r = ((glExtGetRenderbuffersQCOM = (PFNGLEXTGETRENDERBUFFERSQCOMPROC)glewGetProcAddress((const GLubyte*)"glExtGetRenderbuffersQCOM")) == NULL) || r;
+ r = ((glExtGetTexLevelParameterivQCOM = (PFNGLEXTGETTEXLEVELPARAMETERIVQCOMPROC)glewGetProcAddress((const GLubyte*)"glExtGetTexLevelParameterivQCOM")) == NULL) || r;
+ r = ((glExtGetTexSubImageQCOM = (PFNGLEXTGETTEXSUBIMAGEQCOMPROC)glewGetProcAddress((const GLubyte*)"glExtGetTexSubImageQCOM")) == NULL) || r;
+ r = ((glExtGetTexturesQCOM = (PFNGLEXTGETTEXTURESQCOMPROC)glewGetProcAddress((const GLubyte*)"glExtGetTexturesQCOM")) == NULL) || r;
+ r = ((glExtTexObjectStateOverrideiQCOM = (PFNGLEXTTEXOBJECTSTATEOVERRIDEIQCOMPROC)glewGetProcAddress((const GLubyte*)"glExtTexObjectStateOverrideiQCOM")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_QCOM_extended_get */
+
+#ifdef GL_QCOM_extended_get2
+
+static GLboolean _glewInit_GL_QCOM_extended_get2 (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glExtGetProgramBinarySourceQCOM = (PFNGLEXTGETPROGRAMBINARYSOURCEQCOMPROC)glewGetProcAddress((const GLubyte*)"glExtGetProgramBinarySourceQCOM")) == NULL) || r;
+ r = ((glExtGetProgramsQCOM = (PFNGLEXTGETPROGRAMSQCOMPROC)glewGetProcAddress((const GLubyte*)"glExtGetProgramsQCOM")) == NULL) || r;
+ r = ((glExtGetShadersQCOM = (PFNGLEXTGETSHADERSQCOMPROC)glewGetProcAddress((const GLubyte*)"glExtGetShadersQCOM")) == NULL) || r;
+ r = ((glExtIsProgramBinaryQCOM = (PFNGLEXTISPROGRAMBINARYQCOMPROC)glewGetProcAddress((const GLubyte*)"glExtIsProgramBinaryQCOM")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_QCOM_extended_get2 */
+
+#ifdef GL_QCOM_perfmon_global_mode
+
+#endif /* GL_QCOM_perfmon_global_mode */
+
+#ifdef GL_QCOM_tiled_rendering
+
+static GLboolean _glewInit_GL_QCOM_tiled_rendering (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glEndTilingQCOM = (PFNGLENDTILINGQCOMPROC)glewGetProcAddress((const GLubyte*)"glEndTilingQCOM")) == NULL) || r;
+ r = ((glStartTilingQCOM = (PFNGLSTARTTILINGQCOMPROC)glewGetProcAddress((const GLubyte*)"glStartTilingQCOM")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_QCOM_tiled_rendering */
+
+#ifdef GL_QCOM_writeonly_rendering
+
+#endif /* GL_QCOM_writeonly_rendering */
+
+#ifdef GL_SUN_multi_draw_arrays
+
+static GLboolean _glewInit_GL_SUN_multi_draw_arrays (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glMultiDrawArraysSUN = (PFNGLMULTIDRAWARRAYSSUNPROC)glewGetProcAddress((const GLubyte*)"glMultiDrawArraysSUN")) == NULL) || r;
+ r = ((glMultiDrawElementsSUN = (PFNGLMULTIDRAWELEMENTSSUNPROC)glewGetProcAddress((const GLubyte*)"glMultiDrawElementsSUN")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_SUN_multi_draw_arrays */
+
+#ifdef GL_VG_KHR_EGL_sync
+
+#endif /* GL_VG_KHR_EGL_sync */
+
+#ifdef GL_VIV_shader_binary
+
+#endif /* GL_VIV_shader_binary */
+
+/* ------------------------------------------------------------------------- */
+
+GLboolean glewGetExtension (const char* name)
+{
+ const GLubyte* start;
+ const GLubyte* end;
+ start = (const GLubyte*)glGetString(GL_EXTENSIONS);
+ if (start == 0)
+ return GL_FALSE;
+ end = start + _glewStrLen(start);
+ return _glewSearchExtension(name, start, end);
+}
+
+/* ------------------------------------------------------------------------- */
+
+#ifndef GLEW_MX
+static
+#endif
+GLenum glewContextInit (GLEW_CONTEXT_ARG_DEF_LIST)
+{
+ const GLubyte* s;
+ GLuint dot;
+ GLint major, minor;
+ const GLubyte* extStart;
+ const GLubyte* extEnd;
+ GLboolean esLib;
+ /* query opengl version */
+ s = glGetString(GL_VERSION);
+ dot = _glewStrCLen(s, '.');
+ if (dot == 0)
+ return GLEW_ERROR_NO_GL_VERSION;
+
+ major = s[dot-1]-'0';
+ minor = s[dot+1]-'0';
+
+ if (minor < 0 || minor > 9)
+ minor = 0;
+ if (major<0 || major>9)
+ return GLEW_ERROR_NO_GL_VERSION;
+
+ /* All openGL ES lib versions string start with "OpenGL ES" */
+ esLib = _glewStrSame((const GLubyte*)"OpenGL ES", s, 9);
+
+ if(esLib != GL_TRUE)
+ {
+#ifdef GLEW_ES_ONLY
+ return GLEW_ERROR_NOT_GLES_VERSION;
+#else
+ if (major == 1 && minor == 0)
+ {
+ return GLEW_ERROR_GL_VERSION_10_ONLY;
+ }
+ else
+ {
+ CONST_CAST(GLEW_VERSION_4_1) = ( major > 4 ) || ( major == 4 && minor >= 1 ) ? GL_TRUE : GL_FALSE;
+ CONST_CAST(GLEW_VERSION_4_0) = GLEW_VERSION_4_1 == GL_TRUE || ( major == 4 ) ? GL_TRUE : GL_FALSE;
+ CONST_CAST(GLEW_VERSION_3_3) = GLEW_VERSION_4_0 == GL_TRUE || ( major == 3 && minor >= 3 ) ? GL_TRUE : GL_FALSE;
+ CONST_CAST(GLEW_VERSION_3_2) = GLEW_VERSION_3_3 == GL_TRUE || ( major == 3 && minor >= 2 ) ? GL_TRUE : GL_FALSE;
+ CONST_CAST(GLEW_VERSION_3_1) = GLEW_VERSION_3_2 == GL_TRUE || ( major == 3 && minor >= 1 ) ? GL_TRUE : GL_FALSE;
+ CONST_CAST(GLEW_VERSION_3_0) = GLEW_VERSION_3_1 == GL_TRUE || ( major == 3 ) ? GL_TRUE : GL_FALSE;
+ CONST_CAST(GLEW_VERSION_2_1) = GLEW_VERSION_3_0 == GL_TRUE || ( major == 2 && minor >= 1 ) ? GL_TRUE : GL_FALSE;
+ CONST_CAST(GLEW_VERSION_2_0) = GLEW_VERSION_2_1 == GL_TRUE || ( major == 2 ) ? GL_TRUE : GL_FALSE;
+ CONST_CAST(GLEW_VERSION_1_5) = GLEW_VERSION_2_0 == GL_TRUE || ( major == 1 && minor >= 5 ) ? GL_TRUE : GL_FALSE;
+ CONST_CAST(GLEW_VERSION_1_4) = GLEW_VERSION_1_5 == GL_TRUE || ( major == 1 && minor >= 4 ) ? GL_TRUE : GL_FALSE;
+ CONST_CAST(GLEW_VERSION_1_3) = GLEW_VERSION_1_4 == GL_TRUE || ( major == 1 && minor >= 3 ) ? GL_TRUE : GL_FALSE;
+ CONST_CAST(GLEW_VERSION_1_2_1) = GLEW_VERSION_1_3 == GL_TRUE ? GL_TRUE : GL_FALSE;
+ CONST_CAST(GLEW_VERSION_1_2) = GLEW_VERSION_1_2_1 == GL_TRUE || ( major == 1 && minor >= 2 ) ? GL_TRUE : GL_FALSE;
+ CONST_CAST(GLEW_VERSION_1_1) = GLEW_VERSION_1_2 == GL_TRUE || ( major == 1 && minor >= 1 ) ? GL_TRUE : GL_FALSE;
+ }
+#endif /* GLEW_ES_ONLY */
+ }
+ else
+ {
+#ifdef GLEW_NO_ES
+ return GLEW_ERROR_GLES_VERSION;
+#else
+ CONST_CAST(GLEW_ES_VERSION_2_0) = ( major > 2 ) || ( major == 2 && minor >= 0 ) ? GL_TRUE :GL_FALSE;
+ CONST_CAST(GLEW_ES_VERSION_CL_1_1) = GLEW_ES_VERSION_2_0 == GL_TRUE || ( major == 1 && minor >= 1 ) ? GL_TRUE :GL_FALSE;
+ CONST_CAST(GLEW_ES_VERSION_CM_1_1) = GLEW_ES_VERSION_2_0 == GL_TRUE || ( major == 1 && minor >= 1 ) ? GL_TRUE :GL_FALSE;
+ CONST_CAST(GLEW_ES_VERSION_1_0) = GLEW_ES_VERSION_CL_1_1 == GL_TRUE || ( major == 1 && minor >= 0 ) ? GL_TRUE :GL_FALSE;
+#endif
+ }
+
+ /* query opengl extensions string */
+#ifndef GLEW_ES_ONLY
+ if (!GLEW_VERSION_3_0) {
+#endif
+ extStart = glGetString(GL_EXTENSIONS);
+ if (extStart == 0)
+ extStart = (const GLubyte*)"";
+ extEnd = extStart + _glewStrLen(extStart);
+#ifndef GLEW_ES_ONLY
+ }
+ else { // NOTE jwilkins: unified extension string is deprecated
+ extStart = 0;
+ extEnd = 0;
+ }
+#endif
+
+ /* initialize extensions */
+#ifdef GL_VERSION_1_1
+ if (glewExperimental || GLEW_VERSION_1_1) CONST_CAST(GLEW_VERSION_1_1) = !_glewInit_GL_VERSION_1_1(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_VERSION_1_1 */
+#ifdef GL_VERSION_1_2
+ if (glewExperimental || GLEW_VERSION_1_2) CONST_CAST(GLEW_VERSION_1_2) = !_glewInit_GL_VERSION_1_2(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_VERSION_1_2 */
+#ifdef GL_VERSION_1_2_1
+#endif /* GL_VERSION_1_2_1 */
+#ifdef GL_VERSION_1_3
+ if (glewExperimental || GLEW_VERSION_1_3) CONST_CAST(GLEW_VERSION_1_3) = !_glewInit_GL_VERSION_1_3(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_VERSION_1_3 */
+#ifdef GL_VERSION_1_4
+ if (glewExperimental || GLEW_VERSION_1_4) CONST_CAST(GLEW_VERSION_1_4) = !_glewInit_GL_VERSION_1_4(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_VERSION_1_4 */
+#ifdef GL_VERSION_1_5
+ if (glewExperimental || GLEW_VERSION_1_5) CONST_CAST(GLEW_VERSION_1_5) = !_glewInit_GL_VERSION_1_5(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_VERSION_1_5 */
+#ifdef GL_VERSION_2_0
+ if (glewExperimental || GLEW_VERSION_2_0) CONST_CAST(GLEW_VERSION_2_0) = !_glewInit_GL_VERSION_2_0(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_VERSION_2_0 */
+#ifdef GL_VERSION_2_1
+ if (glewExperimental || GLEW_VERSION_2_1) CONST_CAST(GLEW_VERSION_2_1) = !_glewInit_GL_VERSION_2_1(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_VERSION_2_1 */
+#ifdef GL_VERSION_3_0
+ if (glewExperimental || GLEW_VERSION_3_0) CONST_CAST(GLEW_VERSION_3_0) = !_glewInit_GL_VERSION_3_0(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_VERSION_3_0 */
+#ifdef GL_VERSION_3_1
+ if (glewExperimental || GLEW_VERSION_3_1) CONST_CAST(GLEW_VERSION_3_1) = !_glewInit_GL_VERSION_3_1(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_VERSION_3_1 */
+#ifdef GL_VERSION_3_2
+ if (glewExperimental || GLEW_VERSION_3_2) CONST_CAST(GLEW_VERSION_3_2) = !_glewInit_GL_VERSION_3_2(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_VERSION_3_2 */
+#ifdef GL_VERSION_3_3
+ if (glewExperimental || GLEW_VERSION_3_3) CONST_CAST(GLEW_VERSION_3_3) = !_glewInit_GL_VERSION_3_3(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_VERSION_3_3 */
+#ifdef GL_VERSION_4_0
+ if (glewExperimental || GLEW_VERSION_4_0) CONST_CAST(GLEW_VERSION_4_0) = !_glewInit_GL_VERSION_4_0(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_VERSION_4_0 */
+#ifdef GL_VERSION_4_1
+#endif /* GL_VERSION_4_1 */
+#ifdef GL_VERSION_4_2
+#endif /* GL_VERSION_4_2 */
+#ifdef GL_3DFX_multisample
+ CONST_CAST(GLEW_3DFX_multisample) = _glewSearchExtension("GL_3DFX_multisample", extStart, extEnd);
+#endif /* GL_3DFX_multisample */
+#ifdef GL_3DFX_tbuffer
+ CONST_CAST(GLEW_3DFX_tbuffer) = _glewSearchExtension("GL_3DFX_tbuffer", extStart, extEnd);
+ if (glewExperimental || GLEW_3DFX_tbuffer) CONST_CAST(GLEW_3DFX_tbuffer) = !_glewInit_GL_3DFX_tbuffer(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_3DFX_tbuffer */
+#ifdef GL_3DFX_texture_compression_FXT1
+ CONST_CAST(GLEW_3DFX_texture_compression_FXT1) = _glewSearchExtension("GL_3DFX_texture_compression_FXT1", extStart, extEnd);
+#endif /* GL_3DFX_texture_compression_FXT1 */
+#ifdef GL_AMD_blend_minmax_factor
+ CONST_CAST(GLEW_AMD_blend_minmax_factor) = _glewSearchExtension("GL_AMD_blend_minmax_factor", extStart, extEnd);
+#endif /* GL_AMD_blend_minmax_factor */
+#ifdef GL_AMD_conservative_depth
+ CONST_CAST(GLEW_AMD_conservative_depth) = _glewSearchExtension("GL_AMD_conservative_depth", extStart, extEnd);
+#endif /* GL_AMD_conservative_depth */
+#ifdef GL_AMD_debug_output
+ CONST_CAST(GLEW_AMD_debug_output) = _glewSearchExtension("GL_AMD_debug_output", extStart, extEnd);
+ if (glewExperimental || GLEW_AMD_debug_output) CONST_CAST(GLEW_AMD_debug_output) = !_glewInit_GL_AMD_debug_output(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_AMD_debug_output */
+#ifdef GL_AMD_depth_clamp_separate
+ CONST_CAST(GLEW_AMD_depth_clamp_separate) = _glewSearchExtension("GL_AMD_depth_clamp_separate", extStart, extEnd);
+#endif /* GL_AMD_depth_clamp_separate */
+#ifdef GL_AMD_draw_buffers_blend
+ CONST_CAST(GLEW_AMD_draw_buffers_blend) = _glewSearchExtension("GL_AMD_draw_buffers_blend", extStart, extEnd);
+ if (glewExperimental || GLEW_AMD_draw_buffers_blend) CONST_CAST(GLEW_AMD_draw_buffers_blend) = !_glewInit_GL_AMD_draw_buffers_blend(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_AMD_draw_buffers_blend */
+#ifdef GL_AMD_multi_draw_indirect
+ CONST_CAST(GLEW_AMD_multi_draw_indirect) = _glewSearchExtension("GL_AMD_multi_draw_indirect", extStart, extEnd);
+ if (glewExperimental || GLEW_AMD_multi_draw_indirect) CONST_CAST(GLEW_AMD_multi_draw_indirect) = !_glewInit_GL_AMD_multi_draw_indirect(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_AMD_multi_draw_indirect */
+#ifdef GL_AMD_name_gen_delete
+ CONST_CAST(GLEW_AMD_name_gen_delete) = _glewSearchExtension("GL_AMD_name_gen_delete", extStart, extEnd);
+ if (glewExperimental || GLEW_AMD_name_gen_delete) CONST_CAST(GLEW_AMD_name_gen_delete) = !_glewInit_GL_AMD_name_gen_delete(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_AMD_name_gen_delete */
+#ifdef GL_AMD_performance_monitor
+ CONST_CAST(GLEW_AMD_performance_monitor) = _glewSearchExtension("GL_AMD_performance_monitor", extStart, extEnd);
+ if (glewExperimental || GLEW_AMD_performance_monitor) CONST_CAST(GLEW_AMD_performance_monitor) = !_glewInit_GL_AMD_performance_monitor(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_AMD_performance_monitor */
+#ifdef GL_AMD_pinned_memory
+ CONST_CAST(GLEW_AMD_pinned_memory) = _glewSearchExtension("GL_AMD_pinned_memory", extStart, extEnd);
+#endif /* GL_AMD_pinned_memory */
+#ifdef GL_AMD_query_buffer_object
+ CONST_CAST(GLEW_AMD_query_buffer_object) = _glewSearchExtension("GL_AMD_query_buffer_object", extStart, extEnd);
+#endif /* GL_AMD_query_buffer_object */
+#ifdef GL_AMD_sample_positions
+ CONST_CAST(GLEW_AMD_sample_positions) = _glewSearchExtension("GL_AMD_sample_positions", extStart, extEnd);
+ if (glewExperimental || GLEW_AMD_sample_positions) CONST_CAST(GLEW_AMD_sample_positions) = !_glewInit_GL_AMD_sample_positions(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_AMD_sample_positions */
+#ifdef GL_AMD_seamless_cubemap_per_texture
+ CONST_CAST(GLEW_AMD_seamless_cubemap_per_texture) = _glewSearchExtension("GL_AMD_seamless_cubemap_per_texture", extStart, extEnd);
+#endif /* GL_AMD_seamless_cubemap_per_texture */
+#ifdef GL_AMD_shader_stencil_export
+ CONST_CAST(GLEW_AMD_shader_stencil_export) = _glewSearchExtension("GL_AMD_shader_stencil_export", extStart, extEnd);
+#endif /* GL_AMD_shader_stencil_export */
+#ifdef GL_AMD_shader_trinary_minmax
+ CONST_CAST(GLEW_AMD_shader_trinary_minmax) = _glewSearchExtension("GL_AMD_shader_trinary_minmax", extStart, extEnd);
+#endif /* GL_AMD_shader_trinary_minmax */
+#ifdef GL_AMD_sparse_texture
+ CONST_CAST(GLEW_AMD_sparse_texture) = _glewSearchExtension("GL_AMD_sparse_texture", extStart, extEnd);
+ if (glewExperimental || GLEW_AMD_sparse_texture) CONST_CAST(GLEW_AMD_sparse_texture) = !_glewInit_GL_AMD_sparse_texture(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_AMD_sparse_texture */
+#ifdef GL_AMD_stencil_operation_extended
+ CONST_CAST(GLEW_AMD_stencil_operation_extended) = _glewSearchExtension("GL_AMD_stencil_operation_extended", extStart, extEnd);
+ if (glewExperimental || GLEW_AMD_stencil_operation_extended) CONST_CAST(GLEW_AMD_stencil_operation_extended) = !_glewInit_GL_AMD_stencil_operation_extended(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_AMD_stencil_operation_extended */
+#ifdef GL_AMD_texture_texture4
+ CONST_CAST(GLEW_AMD_texture_texture4) = _glewSearchExtension("GL_AMD_texture_texture4", extStart, extEnd);
+#endif /* GL_AMD_texture_texture4 */
+#ifdef GL_AMD_transform_feedback3_lines_triangles
+ CONST_CAST(GLEW_AMD_transform_feedback3_lines_triangles) = _glewSearchExtension("GL_AMD_transform_feedback3_lines_triangles", extStart, extEnd);
+#endif /* GL_AMD_transform_feedback3_lines_triangles */
+#ifdef GL_AMD_vertex_shader_layer
+ CONST_CAST(GLEW_AMD_vertex_shader_layer) = _glewSearchExtension("GL_AMD_vertex_shader_layer", extStart, extEnd);
+#endif /* GL_AMD_vertex_shader_layer */
+#ifdef GL_AMD_vertex_shader_tessellator
+ CONST_CAST(GLEW_AMD_vertex_shader_tessellator) = _glewSearchExtension("GL_AMD_vertex_shader_tessellator", extStart, extEnd);
+ if (glewExperimental || GLEW_AMD_vertex_shader_tessellator) CONST_CAST(GLEW_AMD_vertex_shader_tessellator) = !_glewInit_GL_AMD_vertex_shader_tessellator(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_AMD_vertex_shader_tessellator */
+#ifdef GL_AMD_vertex_shader_viewport_index
+ CONST_CAST(GLEW_AMD_vertex_shader_viewport_index) = _glewSearchExtension("GL_AMD_vertex_shader_viewport_index", extStart, extEnd);
+#endif /* GL_AMD_vertex_shader_viewport_index */
+#ifdef GL_APPLE_aux_depth_stencil
+ CONST_CAST(GLEW_APPLE_aux_depth_stencil) = _glewSearchExtension("GL_APPLE_aux_depth_stencil", extStart, extEnd);
+#endif /* GL_APPLE_aux_depth_stencil */
+#ifdef GL_APPLE_client_storage
+ CONST_CAST(GLEW_APPLE_client_storage) = _glewSearchExtension("GL_APPLE_client_storage", extStart, extEnd);
+#endif /* GL_APPLE_client_storage */
+#ifdef GL_APPLE_element_array
+ CONST_CAST(GLEW_APPLE_element_array) = _glewSearchExtension("GL_APPLE_element_array", extStart, extEnd);
+ if (glewExperimental || GLEW_APPLE_element_array) CONST_CAST(GLEW_APPLE_element_array) = !_glewInit_GL_APPLE_element_array(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_APPLE_element_array */
+#ifdef GL_APPLE_fence
+ CONST_CAST(GLEW_APPLE_fence) = _glewSearchExtension("GL_APPLE_fence", extStart, extEnd);
+ if (glewExperimental || GLEW_APPLE_fence) CONST_CAST(GLEW_APPLE_fence) = !_glewInit_GL_APPLE_fence(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_APPLE_fence */
+#ifdef GL_APPLE_float_pixels
+ CONST_CAST(GLEW_APPLE_float_pixels) = _glewSearchExtension("GL_APPLE_float_pixels", extStart, extEnd);
+#endif /* GL_APPLE_float_pixels */
+#ifdef GL_APPLE_flush_buffer_range
+ CONST_CAST(GLEW_APPLE_flush_buffer_range) = _glewSearchExtension("GL_APPLE_flush_buffer_range", extStart, extEnd);
+ if (glewExperimental || GLEW_APPLE_flush_buffer_range) CONST_CAST(GLEW_APPLE_flush_buffer_range) = !_glewInit_GL_APPLE_flush_buffer_range(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_APPLE_flush_buffer_range */
+#ifdef GL_APPLE_object_purgeable
+ CONST_CAST(GLEW_APPLE_object_purgeable) = _glewSearchExtension("GL_APPLE_object_purgeable", extStart, extEnd);
+ if (glewExperimental || GLEW_APPLE_object_purgeable) CONST_CAST(GLEW_APPLE_object_purgeable) = !_glewInit_GL_APPLE_object_purgeable(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_APPLE_object_purgeable */
+#ifdef GL_APPLE_pixel_buffer
+ CONST_CAST(GLEW_APPLE_pixel_buffer) = _glewSearchExtension("GL_APPLE_pixel_buffer", extStart, extEnd);
+#endif /* GL_APPLE_pixel_buffer */
+#ifdef GL_APPLE_rgb_422
+ CONST_CAST(GLEW_APPLE_rgb_422) = _glewSearchExtension("GL_APPLE_rgb_422", extStart, extEnd);
+#endif /* GL_APPLE_rgb_422 */
+#ifdef GL_APPLE_row_bytes
+ CONST_CAST(GLEW_APPLE_row_bytes) = _glewSearchExtension("GL_APPLE_row_bytes", extStart, extEnd);
+#endif /* GL_APPLE_row_bytes */
+#ifdef GL_APPLE_specular_vector
+ CONST_CAST(GLEW_APPLE_specular_vector) = _glewSearchExtension("GL_APPLE_specular_vector", extStart, extEnd);
+#endif /* GL_APPLE_specular_vector */
+#ifdef GL_APPLE_texture_range
+ CONST_CAST(GLEW_APPLE_texture_range) = _glewSearchExtension("GL_APPLE_texture_range", extStart, extEnd);
+ if (glewExperimental || GLEW_APPLE_texture_range) CONST_CAST(GLEW_APPLE_texture_range) = !_glewInit_GL_APPLE_texture_range(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_APPLE_texture_range */
+#ifdef GL_APPLE_transform_hint
+ CONST_CAST(GLEW_APPLE_transform_hint) = _glewSearchExtension("GL_APPLE_transform_hint", extStart, extEnd);
+#endif /* GL_APPLE_transform_hint */
+#ifdef GL_APPLE_vertex_array_object
+ CONST_CAST(GLEW_APPLE_vertex_array_object) = _glewSearchExtension("GL_APPLE_vertex_array_object", extStart, extEnd);
+ if (glewExperimental || GLEW_APPLE_vertex_array_object) CONST_CAST(GLEW_APPLE_vertex_array_object) = !_glewInit_GL_APPLE_vertex_array_object(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_APPLE_vertex_array_object */
+#ifdef GL_APPLE_vertex_array_range
+ CONST_CAST(GLEW_APPLE_vertex_array_range) = _glewSearchExtension("GL_APPLE_vertex_array_range", extStart, extEnd);
+ if (glewExperimental || GLEW_APPLE_vertex_array_range) CONST_CAST(GLEW_APPLE_vertex_array_range) = !_glewInit_GL_APPLE_vertex_array_range(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_APPLE_vertex_array_range */
+#ifdef GL_APPLE_vertex_program_evaluators
+ CONST_CAST(GLEW_APPLE_vertex_program_evaluators) = _glewSearchExtension("GL_APPLE_vertex_program_evaluators", extStart, extEnd);
+ if (glewExperimental || GLEW_APPLE_vertex_program_evaluators) CONST_CAST(GLEW_APPLE_vertex_program_evaluators) = !_glewInit_GL_APPLE_vertex_program_evaluators(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_APPLE_vertex_program_evaluators */
+#ifdef GL_APPLE_ycbcr_422
+ CONST_CAST(GLEW_APPLE_ycbcr_422) = _glewSearchExtension("GL_APPLE_ycbcr_422", extStart, extEnd);
+#endif /* GL_APPLE_ycbcr_422 */
+#ifdef GL_ARB_ES2_compatibility
+ CONST_CAST(GLEW_ARB_ES2_compatibility) = _glewSearchExtension("GL_ARB_ES2_compatibility", extStart, extEnd);
+ if (glewExperimental || GLEW_ARB_ES2_compatibility) CONST_CAST(GLEW_ARB_ES2_compatibility) = !_glewInit_GL_ARB_ES2_compatibility(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_ARB_ES2_compatibility */
+#ifdef GL_ARB_ES3_compatibility
+ CONST_CAST(GLEW_ARB_ES3_compatibility) = _glewSearchExtension("GL_ARB_ES3_compatibility", extStart, extEnd);
+#endif /* GL_ARB_ES3_compatibility */
+#ifdef GL_ARB_arrays_of_arrays
+ CONST_CAST(GLEW_ARB_arrays_of_arrays) = _glewSearchExtension("GL_ARB_arrays_of_arrays", extStart, extEnd);
+#endif /* GL_ARB_arrays_of_arrays */
+#ifdef GL_ARB_base_instance
+ CONST_CAST(GLEW_ARB_base_instance) = _glewSearchExtension("GL_ARB_base_instance", extStart, extEnd);
+ if (glewExperimental || GLEW_ARB_base_instance) CONST_CAST(GLEW_ARB_base_instance) = !_glewInit_GL_ARB_base_instance(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_ARB_base_instance */
+#ifdef GL_ARB_blend_func_extended
+ CONST_CAST(GLEW_ARB_blend_func_extended) = _glewSearchExtension("GL_ARB_blend_func_extended", extStart, extEnd);
+ if (glewExperimental || GLEW_ARB_blend_func_extended) CONST_CAST(GLEW_ARB_blend_func_extended) = !_glewInit_GL_ARB_blend_func_extended(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_ARB_blend_func_extended */
+#ifdef GL_ARB_cl_event
+ CONST_CAST(GLEW_ARB_cl_event) = _glewSearchExtension("GL_ARB_cl_event", extStart, extEnd);
+ if (glewExperimental || GLEW_ARB_cl_event) CONST_CAST(GLEW_ARB_cl_event) = !_glewInit_GL_ARB_cl_event(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_ARB_cl_event */
+#ifdef GL_ARB_clear_buffer_object
+ CONST_CAST(GLEW_ARB_clear_buffer_object) = _glewSearchExtension("GL_ARB_clear_buffer_object", extStart, extEnd);
+ if (glewExperimental || GLEW_ARB_clear_buffer_object) CONST_CAST(GLEW_ARB_clear_buffer_object) = !_glewInit_GL_ARB_clear_buffer_object(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_ARB_clear_buffer_object */
+#ifdef GL_ARB_color_buffer_float
+ CONST_CAST(GLEW_ARB_color_buffer_float) = _glewSearchExtension("GL_ARB_color_buffer_float", extStart, extEnd);
+ if (glewExperimental || GLEW_ARB_color_buffer_float) CONST_CAST(GLEW_ARB_color_buffer_float) = !_glewInit_GL_ARB_color_buffer_float(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_ARB_color_buffer_float */
+#ifdef GL_ARB_compatibility
+ CONST_CAST(GLEW_ARB_compatibility) = _glewSearchExtension("GL_ARB_compatibility", extStart, extEnd);
+#endif /* GL_ARB_compatibility */
+#ifdef GL_ARB_compressed_texture_pixel_storage
+ CONST_CAST(GLEW_ARB_compressed_texture_pixel_storage) = _glewSearchExtension("GL_ARB_compressed_texture_pixel_storage", extStart, extEnd);
+#endif /* GL_ARB_compressed_texture_pixel_storage */
+#ifdef GL_ARB_compute_shader
+ CONST_CAST(GLEW_ARB_compute_shader) = _glewSearchExtension("GL_ARB_compute_shader", extStart, extEnd);
+ if (glewExperimental || GLEW_ARB_compute_shader) CONST_CAST(GLEW_ARB_compute_shader) = !_glewInit_GL_ARB_compute_shader(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_ARB_compute_shader */
+#ifdef GL_ARB_conservative_depth
+ CONST_CAST(GLEW_ARB_conservative_depth) = _glewSearchExtension("GL_ARB_conservative_depth", extStart, extEnd);
+#endif /* GL_ARB_conservative_depth */
+#ifdef GL_ARB_copy_buffer
+ CONST_CAST(GLEW_ARB_copy_buffer) = _glewSearchExtension("GL_ARB_copy_buffer", extStart, extEnd);
+ if (glewExperimental || GLEW_ARB_copy_buffer) CONST_CAST(GLEW_ARB_copy_buffer) = !_glewInit_GL_ARB_copy_buffer(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_ARB_copy_buffer */
+#ifdef GL_ARB_copy_image
+ CONST_CAST(GLEW_ARB_copy_image) = _glewSearchExtension("GL_ARB_copy_image", extStart, extEnd);
+ if (glewExperimental || GLEW_ARB_copy_image) CONST_CAST(GLEW_ARB_copy_image) = !_glewInit_GL_ARB_copy_image(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_ARB_copy_image */
+#ifdef GL_ARB_debug_output
+ CONST_CAST(GLEW_ARB_debug_output) = _glewSearchExtension("GL_ARB_debug_output", extStart, extEnd);
+ if (glewExperimental || GLEW_ARB_debug_output) CONST_CAST(GLEW_ARB_debug_output) = !_glewInit_GL_ARB_debug_output(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_ARB_debug_output */
+#ifdef GL_ARB_depth_buffer_float
+ CONST_CAST(GLEW_ARB_depth_buffer_float) = _glewSearchExtension("GL_ARB_depth_buffer_float", extStart, extEnd);
+#endif /* GL_ARB_depth_buffer_float */
+#ifdef GL_ARB_depth_clamp
+ CONST_CAST(GLEW_ARB_depth_clamp) = _glewSearchExtension("GL_ARB_depth_clamp", extStart, extEnd);
+#endif /* GL_ARB_depth_clamp */
+#ifdef GL_ARB_depth_texture
+ CONST_CAST(GLEW_ARB_depth_texture) = _glewSearchExtension("GL_ARB_depth_texture", extStart, extEnd);
+#endif /* GL_ARB_depth_texture */
+#ifdef GL_ARB_draw_buffers
+ CONST_CAST(GLEW_ARB_draw_buffers) = _glewSearchExtension("GL_ARB_draw_buffers", extStart, extEnd);
+ if (glewExperimental || GLEW_ARB_draw_buffers) CONST_CAST(GLEW_ARB_draw_buffers) = !_glewInit_GL_ARB_draw_buffers(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_ARB_draw_buffers */
+#ifdef GL_ARB_draw_buffers_blend
+ CONST_CAST(GLEW_ARB_draw_buffers_blend) = _glewSearchExtension("GL_ARB_draw_buffers_blend", extStart, extEnd);
+ if (glewExperimental || GLEW_ARB_draw_buffers_blend) CONST_CAST(GLEW_ARB_draw_buffers_blend) = !_glewInit_GL_ARB_draw_buffers_blend(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_ARB_draw_buffers_blend */
+#ifdef GL_ARB_draw_elements_base_vertex
+ CONST_CAST(GLEW_ARB_draw_elements_base_vertex) = _glewSearchExtension("GL_ARB_draw_elements_base_vertex", extStart, extEnd);
+ if (glewExperimental || GLEW_ARB_draw_elements_base_vertex) CONST_CAST(GLEW_ARB_draw_elements_base_vertex) = !_glewInit_GL_ARB_draw_elements_base_vertex(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_ARB_draw_elements_base_vertex */
+#ifdef GL_ARB_draw_indirect
+ CONST_CAST(GLEW_ARB_draw_indirect) = _glewSearchExtension("GL_ARB_draw_indirect", extStart, extEnd);
+ if (glewExperimental || GLEW_ARB_draw_indirect) CONST_CAST(GLEW_ARB_draw_indirect) = !_glewInit_GL_ARB_draw_indirect(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_ARB_draw_indirect */
+#ifdef GL_ARB_draw_instanced
+ CONST_CAST(GLEW_ARB_draw_instanced) = _glewSearchExtension("GL_ARB_draw_instanced", extStart, extEnd);
+#endif /* GL_ARB_draw_instanced */
+#ifdef GL_ARB_explicit_attrib_location
+ CONST_CAST(GLEW_ARB_explicit_attrib_location) = _glewSearchExtension("GL_ARB_explicit_attrib_location", extStart, extEnd);
+#endif /* GL_ARB_explicit_attrib_location */
+#ifdef GL_ARB_explicit_uniform_location
+ CONST_CAST(GLEW_ARB_explicit_uniform_location) = _glewSearchExtension("GL_ARB_explicit_uniform_location", extStart, extEnd);
+#endif /* GL_ARB_explicit_uniform_location */
+#ifdef GL_ARB_fragment_coord_conventions
+ CONST_CAST(GLEW_ARB_fragment_coord_conventions) = _glewSearchExtension("GL_ARB_fragment_coord_conventions", extStart, extEnd);
+#endif /* GL_ARB_fragment_coord_conventions */
+#ifdef GL_ARB_fragment_layer_viewport
+ CONST_CAST(GLEW_ARB_fragment_layer_viewport) = _glewSearchExtension("GL_ARB_fragment_layer_viewport", extStart, extEnd);
+#endif /* GL_ARB_fragment_layer_viewport */
+#ifdef GL_ARB_fragment_program
+ CONST_CAST(GLEW_ARB_fragment_program) = _glewSearchExtension("GL_ARB_fragment_program", extStart, extEnd);
+#endif /* GL_ARB_fragment_program */
+#ifdef GL_ARB_fragment_program_shadow
+ CONST_CAST(GLEW_ARB_fragment_program_shadow) = _glewSearchExtension("GL_ARB_fragment_program_shadow", extStart, extEnd);
+#endif /* GL_ARB_fragment_program_shadow */
+#ifdef GL_ARB_fragment_shader
+ CONST_CAST(GLEW_ARB_fragment_shader) = _glewSearchExtension("GL_ARB_fragment_shader", extStart, extEnd);
+#endif /* GL_ARB_fragment_shader */
+#ifdef GL_ARB_framebuffer_no_attachments
+ CONST_CAST(GLEW_ARB_framebuffer_no_attachments) = _glewSearchExtension("GL_ARB_framebuffer_no_attachments", extStart, extEnd);
+ if (glewExperimental || GLEW_ARB_framebuffer_no_attachments) CONST_CAST(GLEW_ARB_framebuffer_no_attachments) = !_glewInit_GL_ARB_framebuffer_no_attachments(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_ARB_framebuffer_no_attachments */
+#ifdef GL_ARB_framebuffer_object
+ CONST_CAST(GLEW_ARB_framebuffer_object) = _glewSearchExtension("GL_ARB_framebuffer_object", extStart, extEnd);
+ if (glewExperimental || GLEW_ARB_framebuffer_object) CONST_CAST(GLEW_ARB_framebuffer_object) = !_glewInit_GL_ARB_framebuffer_object(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_ARB_framebuffer_object */
+#ifdef GL_ARB_framebuffer_sRGB
+ CONST_CAST(GLEW_ARB_framebuffer_sRGB) = _glewSearchExtension("GL_ARB_framebuffer_sRGB", extStart, extEnd);
+#endif /* GL_ARB_framebuffer_sRGB */
+#ifdef GL_ARB_geometry_shader4
+ CONST_CAST(GLEW_ARB_geometry_shader4) = _glewSearchExtension("GL_ARB_geometry_shader4", extStart, extEnd);
+ if (glewExperimental || GLEW_ARB_geometry_shader4) CONST_CAST(GLEW_ARB_geometry_shader4) = !_glewInit_GL_ARB_geometry_shader4(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_ARB_geometry_shader4 */
+#ifdef GL_ARB_get_program_binary
+ CONST_CAST(GLEW_ARB_get_program_binary) = _glewSearchExtension("GL_ARB_get_program_binary", extStart, extEnd);
+ if (glewExperimental || GLEW_ARB_get_program_binary) CONST_CAST(GLEW_ARB_get_program_binary) = !_glewInit_GL_ARB_get_program_binary(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_ARB_get_program_binary */
+#ifdef GL_ARB_gpu_shader5
+ CONST_CAST(GLEW_ARB_gpu_shader5) = _glewSearchExtension("GL_ARB_gpu_shader5", extStart, extEnd);
+#endif /* GL_ARB_gpu_shader5 */
+#ifdef GL_ARB_gpu_shader_fp64
+ CONST_CAST(GLEW_ARB_gpu_shader_fp64) = _glewSearchExtension("GL_ARB_gpu_shader_fp64", extStart, extEnd);
+ if (glewExperimental || GLEW_ARB_gpu_shader_fp64) CONST_CAST(GLEW_ARB_gpu_shader_fp64) = !_glewInit_GL_ARB_gpu_shader_fp64(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_ARB_gpu_shader_fp64 */
+#ifdef GL_ARB_half_float_pixel
+ CONST_CAST(GLEW_ARB_half_float_pixel) = _glewSearchExtension("GL_ARB_half_float_pixel", extStart, extEnd);
+#endif /* GL_ARB_half_float_pixel */
+#ifdef GL_ARB_half_float_vertex
+ CONST_CAST(GLEW_ARB_half_float_vertex) = _glewSearchExtension("GL_ARB_half_float_vertex", extStart, extEnd);
+#endif /* GL_ARB_half_float_vertex */
+#ifdef GL_ARB_imaging
+ CONST_CAST(GLEW_ARB_imaging) = _glewSearchExtension("GL_ARB_imaging", extStart, extEnd);
+ if (glewExperimental || GLEW_ARB_imaging) CONST_CAST(GLEW_ARB_imaging) = !_glewInit_GL_ARB_imaging(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_ARB_imaging */
+#ifdef GL_ARB_instanced_arrays
+ CONST_CAST(GLEW_ARB_instanced_arrays) = _glewSearchExtension("GL_ARB_instanced_arrays", extStart, extEnd);
+ if (glewExperimental || GLEW_ARB_instanced_arrays) CONST_CAST(GLEW_ARB_instanced_arrays) = !_glewInit_GL_ARB_instanced_arrays(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_ARB_instanced_arrays */
+#ifdef GL_ARB_internalformat_query
+ CONST_CAST(GLEW_ARB_internalformat_query) = _glewSearchExtension("GL_ARB_internalformat_query", extStart, extEnd);
+ if (glewExperimental || GLEW_ARB_internalformat_query) CONST_CAST(GLEW_ARB_internalformat_query) = !_glewInit_GL_ARB_internalformat_query(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_ARB_internalformat_query */
+#ifdef GL_ARB_internalformat_query2
+ CONST_CAST(GLEW_ARB_internalformat_query2) = _glewSearchExtension("GL_ARB_internalformat_query2", extStart, extEnd);
+ if (glewExperimental || GLEW_ARB_internalformat_query2) CONST_CAST(GLEW_ARB_internalformat_query2) = !_glewInit_GL_ARB_internalformat_query2(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_ARB_internalformat_query2 */
+#ifdef GL_ARB_invalidate_subdata
+ CONST_CAST(GLEW_ARB_invalidate_subdata) = _glewSearchExtension("GL_ARB_invalidate_subdata", extStart, extEnd);
+ if (glewExperimental || GLEW_ARB_invalidate_subdata) CONST_CAST(GLEW_ARB_invalidate_subdata) = !_glewInit_GL_ARB_invalidate_subdata(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_ARB_invalidate_subdata */
+#ifdef GL_ARB_map_buffer_alignment
+ CONST_CAST(GLEW_ARB_map_buffer_alignment) = _glewSearchExtension("GL_ARB_map_buffer_alignment", extStart, extEnd);
+#endif /* GL_ARB_map_buffer_alignment */
+#ifdef GL_ARB_map_buffer_range
+ CONST_CAST(GLEW_ARB_map_buffer_range) = _glewSearchExtension("GL_ARB_map_buffer_range", extStart, extEnd);
+ if (glewExperimental || GLEW_ARB_map_buffer_range) CONST_CAST(GLEW_ARB_map_buffer_range) = !_glewInit_GL_ARB_map_buffer_range(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_ARB_map_buffer_range */
+#ifdef GL_ARB_matrix_palette
+ CONST_CAST(GLEW_ARB_matrix_palette) = _glewSearchExtension("GL_ARB_matrix_palette", extStart, extEnd);
+ if (glewExperimental || GLEW_ARB_matrix_palette) CONST_CAST(GLEW_ARB_matrix_palette) = !_glewInit_GL_ARB_matrix_palette(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_ARB_matrix_palette */
+#ifdef GL_ARB_multi_draw_indirect
+ CONST_CAST(GLEW_ARB_multi_draw_indirect) = _glewSearchExtension("GL_ARB_multi_draw_indirect", extStart, extEnd);
+ if (glewExperimental || GLEW_ARB_multi_draw_indirect) CONST_CAST(GLEW_ARB_multi_draw_indirect) = !_glewInit_GL_ARB_multi_draw_indirect(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_ARB_multi_draw_indirect */
+#ifdef GL_ARB_multisample
+ CONST_CAST(GLEW_ARB_multisample) = _glewSearchExtension("GL_ARB_multisample", extStart, extEnd);
+ if (glewExperimental || GLEW_ARB_multisample) CONST_CAST(GLEW_ARB_multisample) = !_glewInit_GL_ARB_multisample(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_ARB_multisample */
+#ifdef GL_ARB_multitexture
+ CONST_CAST(GLEW_ARB_multitexture) = _glewSearchExtension("GL_ARB_multitexture", extStart, extEnd);
+ if (glewExperimental || GLEW_ARB_multitexture) CONST_CAST(GLEW_ARB_multitexture) = !_glewInit_GL_ARB_multitexture(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_ARB_multitexture */
+#ifdef GL_ARB_occlusion_query
+ CONST_CAST(GLEW_ARB_occlusion_query) = _glewSearchExtension("GL_ARB_occlusion_query", extStart, extEnd);
+ if (glewExperimental || GLEW_ARB_occlusion_query) CONST_CAST(GLEW_ARB_occlusion_query) = !_glewInit_GL_ARB_occlusion_query(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_ARB_occlusion_query */
+#ifdef GL_ARB_occlusion_query2
+ CONST_CAST(GLEW_ARB_occlusion_query2) = _glewSearchExtension("GL_ARB_occlusion_query2", extStart, extEnd);
+#endif /* GL_ARB_occlusion_query2 */
+#ifdef GL_ARB_pixel_buffer_object
+ CONST_CAST(GLEW_ARB_pixel_buffer_object) = _glewSearchExtension("GL_ARB_pixel_buffer_object", extStart, extEnd);
+#endif /* GL_ARB_pixel_buffer_object */
+#ifdef GL_ARB_point_parameters
+ CONST_CAST(GLEW_ARB_point_parameters) = _glewSearchExtension("GL_ARB_point_parameters", extStart, extEnd);
+ if (glewExperimental || GLEW_ARB_point_parameters) CONST_CAST(GLEW_ARB_point_parameters) = !_glewInit_GL_ARB_point_parameters(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_ARB_point_parameters */
+#ifdef GL_ARB_point_sprite
+ CONST_CAST(GLEW_ARB_point_sprite) = _glewSearchExtension("GL_ARB_point_sprite", extStart, extEnd);
+#endif /* GL_ARB_point_sprite */
+#ifdef GL_ARB_program_interface_query
+ CONST_CAST(GLEW_ARB_program_interface_query) = _glewSearchExtension("GL_ARB_program_interface_query", extStart, extEnd);
+ if (glewExperimental || GLEW_ARB_program_interface_query) CONST_CAST(GLEW_ARB_program_interface_query) = !_glewInit_GL_ARB_program_interface_query(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_ARB_program_interface_query */
+#ifdef GL_ARB_provoking_vertex
+ CONST_CAST(GLEW_ARB_provoking_vertex) = _glewSearchExtension("GL_ARB_provoking_vertex", extStart, extEnd);
+ if (glewExperimental || GLEW_ARB_provoking_vertex) CONST_CAST(GLEW_ARB_provoking_vertex) = !_glewInit_GL_ARB_provoking_vertex(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_ARB_provoking_vertex */
+#ifdef GL_ARB_robust_buffer_access_behavior
+ CONST_CAST(GLEW_ARB_robust_buffer_access_behavior) = _glewSearchExtension("GL_ARB_robust_buffer_access_behavior", extStart, extEnd);
+#endif /* GL_ARB_robust_buffer_access_behavior */
+#ifdef GL_ARB_robustness
+ CONST_CAST(GLEW_ARB_robustness) = _glewSearchExtension("GL_ARB_robustness", extStart, extEnd);
+ if (glewExperimental || GLEW_ARB_robustness) CONST_CAST(GLEW_ARB_robustness) = !_glewInit_GL_ARB_robustness(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_ARB_robustness */
+#ifdef GL_ARB_robustness_application_isolation
+ CONST_CAST(GLEW_ARB_robustness_application_isolation) = _glewSearchExtension("GL_ARB_robustness_application_isolation", extStart, extEnd);
+#endif /* GL_ARB_robustness_application_isolation */
+#ifdef GL_ARB_robustness_share_group_isolation
+ CONST_CAST(GLEW_ARB_robustness_share_group_isolation) = _glewSearchExtension("GL_ARB_robustness_share_group_isolation", extStart, extEnd);
+#endif /* GL_ARB_robustness_share_group_isolation */
+#ifdef GL_ARB_sample_shading
+ CONST_CAST(GLEW_ARB_sample_shading) = _glewSearchExtension("GL_ARB_sample_shading", extStart, extEnd);
+ if (glewExperimental || GLEW_ARB_sample_shading) CONST_CAST(GLEW_ARB_sample_shading) = !_glewInit_GL_ARB_sample_shading(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_ARB_sample_shading */
+#ifdef GL_ARB_sampler_objects
+ CONST_CAST(GLEW_ARB_sampler_objects) = _glewSearchExtension("GL_ARB_sampler_objects", extStart, extEnd);
+ if (glewExperimental || GLEW_ARB_sampler_objects) CONST_CAST(GLEW_ARB_sampler_objects) = !_glewInit_GL_ARB_sampler_objects(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_ARB_sampler_objects */
+#ifdef GL_ARB_seamless_cube_map
+ CONST_CAST(GLEW_ARB_seamless_cube_map) = _glewSearchExtension("GL_ARB_seamless_cube_map", extStart, extEnd);
+#endif /* GL_ARB_seamless_cube_map */
+#if 0 // NOTE jwilkins: there is an inconsistency between the ES and Non-ES versions of this extension??
+#ifdef GL_ARB_separate_shader_objects
+ CONST_CAST(GLEW_ARB_separate_shader_objects) = _glewSearchExtension("GL_ARB_separate_shader_objects", extStart, extEnd);
+ if (glewExperimental || GLEW_ARB_separate_shader_objects) CONST_CAST(GLEW_ARB_separate_shader_objects) = !_glewInit_GL_ARB_separate_shader_objects(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_ARB_separate_shader_objects */
+#endif // XXX
+#ifdef GL_ARB_shader_atomic_counters
+ CONST_CAST(GLEW_ARB_shader_atomic_counters) = _glewSearchExtension("GL_ARB_shader_atomic_counters", extStart, extEnd);
+ if (glewExperimental || GLEW_ARB_shader_atomic_counters) CONST_CAST(GLEW_ARB_shader_atomic_counters) = !_glewInit_GL_ARB_shader_atomic_counters(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_ARB_shader_atomic_counters */
+#ifdef GL_ARB_shader_bit_encoding
+ CONST_CAST(GLEW_ARB_shader_bit_encoding) = _glewSearchExtension("GL_ARB_shader_bit_encoding", extStart, extEnd);
+#endif /* GL_ARB_shader_bit_encoding */
+#ifdef GL_ARB_shader_image_load_store
+ CONST_CAST(GLEW_ARB_shader_image_load_store) = _glewSearchExtension("GL_ARB_shader_image_load_store", extStart, extEnd);
+ if (glewExperimental || GLEW_ARB_shader_image_load_store) CONST_CAST(GLEW_ARB_shader_image_load_store) = !_glewInit_GL_ARB_shader_image_load_store(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_ARB_shader_image_load_store */
+#ifdef GL_ARB_shader_image_size
+ CONST_CAST(GLEW_ARB_shader_image_size) = _glewSearchExtension("GL_ARB_shader_image_size", extStart, extEnd);
+#endif /* GL_ARB_shader_image_size */
+#ifdef GL_ARB_shader_objects
+ CONST_CAST(GLEW_ARB_shader_objects) = _glewSearchExtension("GL_ARB_shader_objects", extStart, extEnd);
+ if (glewExperimental || GLEW_ARB_shader_objects) CONST_CAST(GLEW_ARB_shader_objects) = !_glewInit_GL_ARB_shader_objects(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_ARB_shader_objects */
+#ifdef GL_ARB_shader_precision
+ CONST_CAST(GLEW_ARB_shader_precision) = _glewSearchExtension("GL_ARB_shader_precision", extStart, extEnd);
+#endif /* GL_ARB_shader_precision */
+#ifdef GL_ARB_shader_stencil_export
+ CONST_CAST(GLEW_ARB_shader_stencil_export) = _glewSearchExtension("GL_ARB_shader_stencil_export", extStart, extEnd);
+#endif /* GL_ARB_shader_stencil_export */
+#ifdef GL_ARB_shader_storage_buffer_object
+ CONST_CAST(GLEW_ARB_shader_storage_buffer_object) = _glewSearchExtension("GL_ARB_shader_storage_buffer_object", extStart, extEnd);
+ if (glewExperimental || GLEW_ARB_shader_storage_buffer_object) CONST_CAST(GLEW_ARB_shader_storage_buffer_object) = !_glewInit_GL_ARB_shader_storage_buffer_object(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_ARB_shader_storage_buffer_object */
+#ifdef GL_ARB_shader_subroutine
+ CONST_CAST(GLEW_ARB_shader_subroutine) = _glewSearchExtension("GL_ARB_shader_subroutine", extStart, extEnd);
+ if (glewExperimental || GLEW_ARB_shader_subroutine) CONST_CAST(GLEW_ARB_shader_subroutine) = !_glewInit_GL_ARB_shader_subroutine(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_ARB_shader_subroutine */
+#ifdef GL_ARB_shader_texture_lod
+ CONST_CAST(GLEW_ARB_shader_texture_lod) = _glewSearchExtension("GL_ARB_shader_texture_lod", extStart, extEnd);
+#endif /* GL_ARB_shader_texture_lod */
+#ifdef GL_ARB_shading_language_100
+ CONST_CAST(GLEW_ARB_shading_language_100) = _glewSearchExtension("GL_ARB_shading_language_100", extStart, extEnd);
+#endif /* GL_ARB_shading_language_100 */
+#ifdef GL_ARB_shading_language_420pack
+ CONST_CAST(GLEW_ARB_shading_language_420pack) = _glewSearchExtension("GL_ARB_shading_language_420pack", extStart, extEnd);
+#endif /* GL_ARB_shading_language_420pack */
+#ifdef GL_ARB_shading_language_include
+ CONST_CAST(GLEW_ARB_shading_language_include) = _glewSearchExtension("GL_ARB_shading_language_include", extStart, extEnd);
+ if (glewExperimental || GLEW_ARB_shading_language_include) CONST_CAST(GLEW_ARB_shading_language_include) = !_glewInit_GL_ARB_shading_language_include(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_ARB_shading_language_include */
+#ifdef GL_ARB_shading_language_packing
+ CONST_CAST(GLEW_ARB_shading_language_packing) = _glewSearchExtension("GL_ARB_shading_language_packing", extStart, extEnd);
+#endif /* GL_ARB_shading_language_packing */
+#ifdef GL_ARB_shadow
+ CONST_CAST(GLEW_ARB_shadow) = _glewSearchExtension("GL_ARB_shadow", extStart, extEnd);
+#endif /* GL_ARB_shadow */
+#ifdef GL_ARB_shadow_ambient
+ CONST_CAST(GLEW_ARB_shadow_ambient) = _glewSearchExtension("GL_ARB_shadow_ambient", extStart, extEnd);
+#endif /* GL_ARB_shadow_ambient */
+#ifdef GL_ARB_stencil_texturing
+ CONST_CAST(GLEW_ARB_stencil_texturing) = _glewSearchExtension("GL_ARB_stencil_texturing", extStart, extEnd);
+#endif /* GL_ARB_stencil_texturing */
+#ifdef GL_ARB_sync
+ CONST_CAST(GLEW_ARB_sync) = _glewSearchExtension("GL_ARB_sync", extStart, extEnd);
+ if (glewExperimental || GLEW_ARB_sync) CONST_CAST(GLEW_ARB_sync) = !_glewInit_GL_ARB_sync(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_ARB_sync */
+#ifdef GL_ARB_tessellation_shader
+ CONST_CAST(GLEW_ARB_tessellation_shader) = _glewSearchExtension("GL_ARB_tessellation_shader", extStart, extEnd);
+ if (glewExperimental || GLEW_ARB_tessellation_shader) CONST_CAST(GLEW_ARB_tessellation_shader) = !_glewInit_GL_ARB_tessellation_shader(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_ARB_tessellation_shader */
+#ifdef GL_ARB_texture_border_clamp
+ CONST_CAST(GLEW_ARB_texture_border_clamp) = _glewSearchExtension("GL_ARB_texture_border_clamp", extStart, extEnd);
+#endif /* GL_ARB_texture_border_clamp */
+#ifdef GL_ARB_texture_buffer_object
+ CONST_CAST(GLEW_ARB_texture_buffer_object) = _glewSearchExtension("GL_ARB_texture_buffer_object", extStart, extEnd);
+ if (glewExperimental || GLEW_ARB_texture_buffer_object) CONST_CAST(GLEW_ARB_texture_buffer_object) = !_glewInit_GL_ARB_texture_buffer_object(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_ARB_texture_buffer_object */
+#ifdef GL_ARB_texture_buffer_object_rgb32
+ CONST_CAST(GLEW_ARB_texture_buffer_object_rgb32) = _glewSearchExtension("GL_ARB_texture_buffer_object_rgb32", extStart, extEnd);
+#endif /* GL_ARB_texture_buffer_object_rgb32 */
+#ifdef GL_ARB_texture_buffer_range
+ CONST_CAST(GLEW_ARB_texture_buffer_range) = _glewSearchExtension("GL_ARB_texture_buffer_range", extStart, extEnd);
+ if (glewExperimental || GLEW_ARB_texture_buffer_range) CONST_CAST(GLEW_ARB_texture_buffer_range) = !_glewInit_GL_ARB_texture_buffer_range(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_ARB_texture_buffer_range */
+#ifdef GL_ARB_texture_compression
+ CONST_CAST(GLEW_ARB_texture_compression) = _glewSearchExtension("GL_ARB_texture_compression", extStart, extEnd);
+ if (glewExperimental || GLEW_ARB_texture_compression) CONST_CAST(GLEW_ARB_texture_compression) = !_glewInit_GL_ARB_texture_compression(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_ARB_texture_compression */
+#ifdef GL_ARB_texture_compression_bptc
+ CONST_CAST(GLEW_ARB_texture_compression_bptc) = _glewSearchExtension("GL_ARB_texture_compression_bptc", extStart, extEnd);
+#endif /* GL_ARB_texture_compression_bptc */
+#ifdef GL_ARB_texture_compression_rgtc
+ CONST_CAST(GLEW_ARB_texture_compression_rgtc) = _glewSearchExtension("GL_ARB_texture_compression_rgtc", extStart, extEnd);
+#endif /* GL_ARB_texture_compression_rgtc */
+#ifdef GL_ARB_texture_cube_map
+ CONST_CAST(GLEW_ARB_texture_cube_map) = _glewSearchExtension("GL_ARB_texture_cube_map", extStart, extEnd);
+#endif /* GL_ARB_texture_cube_map */
+#ifdef GL_ARB_texture_cube_map_array
+ CONST_CAST(GLEW_ARB_texture_cube_map_array) = _glewSearchExtension("GL_ARB_texture_cube_map_array", extStart, extEnd);
+#endif /* GL_ARB_texture_cube_map_array */
+#ifdef GL_ARB_texture_env_add
+ CONST_CAST(GLEW_ARB_texture_env_add) = _glewSearchExtension("GL_ARB_texture_env_add", extStart, extEnd);
+#endif /* GL_ARB_texture_env_add */
+#ifdef GL_ARB_texture_env_combine
+ CONST_CAST(GLEW_ARB_texture_env_combine) = _glewSearchExtension("GL_ARB_texture_env_combine", extStart, extEnd);
+#endif /* GL_ARB_texture_env_combine */
+#ifdef GL_ARB_texture_env_crossbar
+ CONST_CAST(GLEW_ARB_texture_env_crossbar) = _glewSearchExtension("GL_ARB_texture_env_crossbar", extStart, extEnd);
+#endif /* GL_ARB_texture_env_crossbar */
+#ifdef GL_ARB_texture_env_dot3
+ CONST_CAST(GLEW_ARB_texture_env_dot3) = _glewSearchExtension("GL_ARB_texture_env_dot3", extStart, extEnd);
+#endif /* GL_ARB_texture_env_dot3 */
+#ifdef GL_ARB_texture_float
+ CONST_CAST(GLEW_ARB_texture_float) = _glewSearchExtension("GL_ARB_texture_float", extStart, extEnd);
+#endif /* GL_ARB_texture_float */
+#ifdef GL_ARB_texture_gather
+ CONST_CAST(GLEW_ARB_texture_gather) = _glewSearchExtension("GL_ARB_texture_gather", extStart, extEnd);
+#endif /* GL_ARB_texture_gather */
+#ifdef GL_ARB_texture_mirrored_repeat
+ CONST_CAST(GLEW_ARB_texture_mirrored_repeat) = _glewSearchExtension("GL_ARB_texture_mirrored_repeat", extStart, extEnd);
+#endif /* GL_ARB_texture_mirrored_repeat */
+#ifdef GL_ARB_texture_multisample
+ CONST_CAST(GLEW_ARB_texture_multisample) = _glewSearchExtension("GL_ARB_texture_multisample", extStart, extEnd);
+ if (glewExperimental || GLEW_ARB_texture_multisample) CONST_CAST(GLEW_ARB_texture_multisample) = !_glewInit_GL_ARB_texture_multisample(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_ARB_texture_multisample */
+#ifdef GL_ARB_texture_non_power_of_two
+ CONST_CAST(GLEW_ARB_texture_non_power_of_two) = _glewSearchExtension("GL_ARB_texture_non_power_of_two", extStart, extEnd);
+#endif /* GL_ARB_texture_non_power_of_two */
+#ifdef GL_ARB_texture_query_levels
+ CONST_CAST(GLEW_ARB_texture_query_levels) = _glewSearchExtension("GL_ARB_texture_query_levels", extStart, extEnd);
+#endif /* GL_ARB_texture_query_levels */
+#ifdef GL_ARB_texture_query_lod
+ CONST_CAST(GLEW_ARB_texture_query_lod) = _glewSearchExtension("GL_ARB_texture_query_lod", extStart, extEnd);
+#endif /* GL_ARB_texture_query_lod */
+#ifdef GL_ARB_texture_rectangle
+ CONST_CAST(GLEW_ARB_texture_rectangle) = _glewSearchExtension("GL_ARB_texture_rectangle", extStart, extEnd);
+#endif /* GL_ARB_texture_rectangle */
+#ifdef GL_ARB_texture_rg
+ CONST_CAST(GLEW_ARB_texture_rg) = _glewSearchExtension("GL_ARB_texture_rg", extStart, extEnd);
+#endif /* GL_ARB_texture_rg */
+#ifdef GL_ARB_texture_rgb10_a2ui
+ CONST_CAST(GLEW_ARB_texture_rgb10_a2ui) = _glewSearchExtension("GL_ARB_texture_rgb10_a2ui", extStart, extEnd);
+#endif /* GL_ARB_texture_rgb10_a2ui */
+#ifdef GL_ARB_texture_storage
+ CONST_CAST(GLEW_ARB_texture_storage) = _glewSearchExtension("GL_ARB_texture_storage", extStart, extEnd);
+ if (glewExperimental || GLEW_ARB_texture_storage) CONST_CAST(GLEW_ARB_texture_storage) = !_glewInit_GL_ARB_texture_storage(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_ARB_texture_storage */
+#ifdef GL_ARB_texture_storage_multisample
+ CONST_CAST(GLEW_ARB_texture_storage_multisample) = _glewSearchExtension("GL_ARB_texture_storage_multisample", extStart, extEnd);
+ if (glewExperimental || GLEW_ARB_texture_storage_multisample) CONST_CAST(GLEW_ARB_texture_storage_multisample) = !_glewInit_GL_ARB_texture_storage_multisample(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_ARB_texture_storage_multisample */
+#ifdef GL_ARB_texture_swizzle
+ CONST_CAST(GLEW_ARB_texture_swizzle) = _glewSearchExtension("GL_ARB_texture_swizzle", extStart, extEnd);
+#endif /* GL_ARB_texture_swizzle */
+#ifdef GL_ARB_texture_view
+ CONST_CAST(GLEW_ARB_texture_view) = _glewSearchExtension("GL_ARB_texture_view", extStart, extEnd);
+ if (glewExperimental || GLEW_ARB_texture_view) CONST_CAST(GLEW_ARB_texture_view) = !_glewInit_GL_ARB_texture_view(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_ARB_texture_view */
+#ifdef GL_ARB_timer_query
+ CONST_CAST(GLEW_ARB_timer_query) = _glewSearchExtension("GL_ARB_timer_query", extStart, extEnd);
+ if (glewExperimental || GLEW_ARB_timer_query) CONST_CAST(GLEW_ARB_timer_query) = !_glewInit_GL_ARB_timer_query(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_ARB_timer_query */
+#ifdef GL_ARB_transform_feedback2
+ CONST_CAST(GLEW_ARB_transform_feedback2) = _glewSearchExtension("GL_ARB_transform_feedback2", extStart, extEnd);
+ if (glewExperimental || GLEW_ARB_transform_feedback2) CONST_CAST(GLEW_ARB_transform_feedback2) = !_glewInit_GL_ARB_transform_feedback2(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_ARB_transform_feedback2 */
+#ifdef GL_ARB_transform_feedback3
+ CONST_CAST(GLEW_ARB_transform_feedback3) = _glewSearchExtension("GL_ARB_transform_feedback3", extStart, extEnd);
+ if (glewExperimental || GLEW_ARB_transform_feedback3) CONST_CAST(GLEW_ARB_transform_feedback3) = !_glewInit_GL_ARB_transform_feedback3(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_ARB_transform_feedback3 */
+#ifdef GL_ARB_transform_feedback_instanced
+ CONST_CAST(GLEW_ARB_transform_feedback_instanced) = _glewSearchExtension("GL_ARB_transform_feedback_instanced", extStart, extEnd);
+ if (glewExperimental || GLEW_ARB_transform_feedback_instanced) CONST_CAST(GLEW_ARB_transform_feedback_instanced) = !_glewInit_GL_ARB_transform_feedback_instanced(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_ARB_transform_feedback_instanced */
+#ifdef GL_ARB_transpose_matrix
+ CONST_CAST(GLEW_ARB_transpose_matrix) = _glewSearchExtension("GL_ARB_transpose_matrix", extStart, extEnd);
+ if (glewExperimental || GLEW_ARB_transpose_matrix) CONST_CAST(GLEW_ARB_transpose_matrix) = !_glewInit_GL_ARB_transpose_matrix(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_ARB_transpose_matrix */
+#ifdef GL_ARB_uniform_buffer_object
+ CONST_CAST(GLEW_ARB_uniform_buffer_object) = _glewSearchExtension("GL_ARB_uniform_buffer_object", extStart, extEnd);
+ if (glewExperimental || GLEW_ARB_uniform_buffer_object) CONST_CAST(GLEW_ARB_uniform_buffer_object) = !_glewInit_GL_ARB_uniform_buffer_object(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_ARB_uniform_buffer_object */
+#ifdef GL_ARB_vertex_array_bgra
+ CONST_CAST(GLEW_ARB_vertex_array_bgra) = _glewSearchExtension("GL_ARB_vertex_array_bgra", extStart, extEnd);
+#endif /* GL_ARB_vertex_array_bgra */
+#ifdef GL_ARB_vertex_array_object
+ CONST_CAST(GLEW_ARB_vertex_array_object) = _glewSearchExtension("GL_ARB_vertex_array_object", extStart, extEnd);
+ if (glewExperimental || GLEW_ARB_vertex_array_object) CONST_CAST(GLEW_ARB_vertex_array_object) = !_glewInit_GL_ARB_vertex_array_object(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_ARB_vertex_array_object */
+#ifdef GL_ARB_vertex_attrib_64bit
+ CONST_CAST(GLEW_ARB_vertex_attrib_64bit) = _glewSearchExtension("GL_ARB_vertex_attrib_64bit", extStart, extEnd);
+ if (glewExperimental || GLEW_ARB_vertex_attrib_64bit) CONST_CAST(GLEW_ARB_vertex_attrib_64bit) = !_glewInit_GL_ARB_vertex_attrib_64bit(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_ARB_vertex_attrib_64bit */
+#ifdef GL_ARB_vertex_attrib_binding
+ CONST_CAST(GLEW_ARB_vertex_attrib_binding) = _glewSearchExtension("GL_ARB_vertex_attrib_binding", extStart, extEnd);
+ if (glewExperimental || GLEW_ARB_vertex_attrib_binding) CONST_CAST(GLEW_ARB_vertex_attrib_binding) = !_glewInit_GL_ARB_vertex_attrib_binding(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_ARB_vertex_attrib_binding */
+#ifdef GL_ARB_vertex_blend
+ CONST_CAST(GLEW_ARB_vertex_blend) = _glewSearchExtension("GL_ARB_vertex_blend", extStart, extEnd);
+ if (glewExperimental || GLEW_ARB_vertex_blend) CONST_CAST(GLEW_ARB_vertex_blend) = !_glewInit_GL_ARB_vertex_blend(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_ARB_vertex_blend */
+#ifdef GL_ARB_vertex_buffer_object
+ CONST_CAST(GLEW_ARB_vertex_buffer_object) = _glewSearchExtension("GL_ARB_vertex_buffer_object", extStart, extEnd);
+ if (glewExperimental || GLEW_ARB_vertex_buffer_object) CONST_CAST(GLEW_ARB_vertex_buffer_object) = !_glewInit_GL_ARB_vertex_buffer_object(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_ARB_vertex_buffer_object */
+#ifdef GL_ARB_vertex_program
+ CONST_CAST(GLEW_ARB_vertex_program) = _glewSearchExtension("GL_ARB_vertex_program", extStart, extEnd);
+ if (glewExperimental || GLEW_ARB_vertex_program) CONST_CAST(GLEW_ARB_vertex_program) = !_glewInit_GL_ARB_vertex_program(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_ARB_vertex_program */
+#ifdef GL_ARB_vertex_shader
+ CONST_CAST(GLEW_ARB_vertex_shader) = _glewSearchExtension("GL_ARB_vertex_shader", extStart, extEnd);
+ if (glewExperimental || GLEW_ARB_vertex_shader) CONST_CAST(GLEW_ARB_vertex_shader) = !_glewInit_GL_ARB_vertex_shader(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_ARB_vertex_shader */
+#ifdef GL_ARB_vertex_type_2_10_10_10_rev
+ CONST_CAST(GLEW_ARB_vertex_type_2_10_10_10_rev) = _glewSearchExtension("GL_ARB_vertex_type_2_10_10_10_rev", extStart, extEnd);
+ if (glewExperimental || GLEW_ARB_vertex_type_2_10_10_10_rev) CONST_CAST(GLEW_ARB_vertex_type_2_10_10_10_rev) = !_glewInit_GL_ARB_vertex_type_2_10_10_10_rev(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_ARB_vertex_type_2_10_10_10_rev */
+#ifdef GL_ARB_viewport_array
+ CONST_CAST(GLEW_ARB_viewport_array) = _glewSearchExtension("GL_ARB_viewport_array", extStart, extEnd);
+ if (glewExperimental || GLEW_ARB_viewport_array) CONST_CAST(GLEW_ARB_viewport_array) = !_glewInit_GL_ARB_viewport_array(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_ARB_viewport_array */
+#ifdef GL_ARB_window_pos
+ CONST_CAST(GLEW_ARB_window_pos) = _glewSearchExtension("GL_ARB_window_pos", extStart, extEnd);
+ if (glewExperimental || GLEW_ARB_window_pos) CONST_CAST(GLEW_ARB_window_pos) = !_glewInit_GL_ARB_window_pos(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_ARB_window_pos */
+#ifdef GL_ATIX_point_sprites
+ CONST_CAST(GLEW_ATIX_point_sprites) = _glewSearchExtension("GL_ATIX_point_sprites", extStart, extEnd);
+#endif /* GL_ATIX_point_sprites */
+#ifdef GL_ATIX_texture_env_combine3
+ CONST_CAST(GLEW_ATIX_texture_env_combine3) = _glewSearchExtension("GL_ATIX_texture_env_combine3", extStart, extEnd);
+#endif /* GL_ATIX_texture_env_combine3 */
+#ifdef GL_ATIX_texture_env_route
+ CONST_CAST(GLEW_ATIX_texture_env_route) = _glewSearchExtension("GL_ATIX_texture_env_route", extStart, extEnd);
+#endif /* GL_ATIX_texture_env_route */
+#ifdef GL_ATIX_vertex_shader_output_point_size
+ CONST_CAST(GLEW_ATIX_vertex_shader_output_point_size) = _glewSearchExtension("GL_ATIX_vertex_shader_output_point_size", extStart, extEnd);
+#endif /* GL_ATIX_vertex_shader_output_point_size */
+#ifdef GL_ATI_draw_buffers
+ CONST_CAST(GLEW_ATI_draw_buffers) = _glewSearchExtension("GL_ATI_draw_buffers", extStart, extEnd);
+ if (glewExperimental || GLEW_ATI_draw_buffers) CONST_CAST(GLEW_ATI_draw_buffers) = !_glewInit_GL_ATI_draw_buffers(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_ATI_draw_buffers */
+#ifdef GL_ATI_element_array
+ CONST_CAST(GLEW_ATI_element_array) = _glewSearchExtension("GL_ATI_element_array", extStart, extEnd);
+ if (glewExperimental || GLEW_ATI_element_array) CONST_CAST(GLEW_ATI_element_array) = !_glewInit_GL_ATI_element_array(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_ATI_element_array */
+#ifdef GL_ATI_envmap_bumpmap
+ CONST_CAST(GLEW_ATI_envmap_bumpmap) = _glewSearchExtension("GL_ATI_envmap_bumpmap", extStart, extEnd);
+ if (glewExperimental || GLEW_ATI_envmap_bumpmap) CONST_CAST(GLEW_ATI_envmap_bumpmap) = !_glewInit_GL_ATI_envmap_bumpmap(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_ATI_envmap_bumpmap */
+#ifdef GL_ATI_fragment_shader
+ CONST_CAST(GLEW_ATI_fragment_shader) = _glewSearchExtension("GL_ATI_fragment_shader", extStart, extEnd);
+ if (glewExperimental || GLEW_ATI_fragment_shader) CONST_CAST(GLEW_ATI_fragment_shader) = !_glewInit_GL_ATI_fragment_shader(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_ATI_fragment_shader */
+#ifdef GL_ATI_map_object_buffer
+ CONST_CAST(GLEW_ATI_map_object_buffer) = _glewSearchExtension("GL_ATI_map_object_buffer", extStart, extEnd);
+ if (glewExperimental || GLEW_ATI_map_object_buffer) CONST_CAST(GLEW_ATI_map_object_buffer) = !_glewInit_GL_ATI_map_object_buffer(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_ATI_map_object_buffer */
+#ifdef GL_ATI_meminfo
+ CONST_CAST(GLEW_ATI_meminfo) = _glewSearchExtension("GL_ATI_meminfo", extStart, extEnd);
+#endif /* GL_ATI_meminfo */
+#ifdef GL_ATI_pn_triangles
+ CONST_CAST(GLEW_ATI_pn_triangles) = _glewSearchExtension("GL_ATI_pn_triangles", extStart, extEnd);
+ if (glewExperimental || GLEW_ATI_pn_triangles) CONST_CAST(GLEW_ATI_pn_triangles) = !_glewInit_GL_ATI_pn_triangles(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_ATI_pn_triangles */
+#ifdef GL_ATI_separate_stencil
+ CONST_CAST(GLEW_ATI_separate_stencil) = _glewSearchExtension("GL_ATI_separate_stencil", extStart, extEnd);
+ if (glewExperimental || GLEW_ATI_separate_stencil) CONST_CAST(GLEW_ATI_separate_stencil) = !_glewInit_GL_ATI_separate_stencil(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_ATI_separate_stencil */
+#ifdef GL_ATI_shader_texture_lod
+ CONST_CAST(GLEW_ATI_shader_texture_lod) = _glewSearchExtension("GL_ATI_shader_texture_lod", extStart, extEnd);
+#endif /* GL_ATI_shader_texture_lod */
+#ifdef GL_ATI_text_fragment_shader
+ CONST_CAST(GLEW_ATI_text_fragment_shader) = _glewSearchExtension("GL_ATI_text_fragment_shader", extStart, extEnd);
+#endif /* GL_ATI_text_fragment_shader */
+#ifdef GL_ATI_texture_compression_3dc
+ CONST_CAST(GLEW_ATI_texture_compression_3dc) = _glewSearchExtension("GL_ATI_texture_compression_3dc", extStart, extEnd);
+#endif /* GL_ATI_texture_compression_3dc */
+#ifdef GL_ATI_texture_env_combine3
+ CONST_CAST(GLEW_ATI_texture_env_combine3) = _glewSearchExtension("GL_ATI_texture_env_combine3", extStart, extEnd);
+#endif /* GL_ATI_texture_env_combine3 */
+#ifdef GL_ATI_texture_float
+ CONST_CAST(GLEW_ATI_texture_float) = _glewSearchExtension("GL_ATI_texture_float", extStart, extEnd);
+#endif /* GL_ATI_texture_float */
+#ifdef GL_ATI_texture_mirror_once
+ CONST_CAST(GLEW_ATI_texture_mirror_once) = _glewSearchExtension("GL_ATI_texture_mirror_once", extStart, extEnd);
+#endif /* GL_ATI_texture_mirror_once */
+#ifdef GL_ATI_vertex_array_object
+ CONST_CAST(GLEW_ATI_vertex_array_object) = _glewSearchExtension("GL_ATI_vertex_array_object", extStart, extEnd);
+ if (glewExperimental || GLEW_ATI_vertex_array_object) CONST_CAST(GLEW_ATI_vertex_array_object) = !_glewInit_GL_ATI_vertex_array_object(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_ATI_vertex_array_object */
+#ifdef GL_ATI_vertex_attrib_array_object
+ CONST_CAST(GLEW_ATI_vertex_attrib_array_object) = _glewSearchExtension("GL_ATI_vertex_attrib_array_object", extStart, extEnd);
+ if (glewExperimental || GLEW_ATI_vertex_attrib_array_object) CONST_CAST(GLEW_ATI_vertex_attrib_array_object) = !_glewInit_GL_ATI_vertex_attrib_array_object(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_ATI_vertex_attrib_array_object */
+#ifdef GL_ATI_vertex_streams
+ CONST_CAST(GLEW_ATI_vertex_streams) = _glewSearchExtension("GL_ATI_vertex_streams", extStart, extEnd);
+ if (glewExperimental || GLEW_ATI_vertex_streams) CONST_CAST(GLEW_ATI_vertex_streams) = !_glewInit_GL_ATI_vertex_streams(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_ATI_vertex_streams */
+#ifdef GL_EXT_422_pixels
+ CONST_CAST(GLEW_EXT_422_pixels) = _glewSearchExtension("GL_EXT_422_pixels", extStart, extEnd);
+#endif /* GL_EXT_422_pixels */
+#ifdef GL_EXT_Cg_shader
+ CONST_CAST(GLEW_EXT_Cg_shader) = _glewSearchExtension("GL_EXT_Cg_shader", extStart, extEnd);
+#endif /* GL_EXT_Cg_shader */
+#ifdef GL_EXT_abgr
+ CONST_CAST(GLEW_EXT_abgr) = _glewSearchExtension("GL_EXT_abgr", extStart, extEnd);
+#endif /* GL_EXT_abgr */
+#ifdef GL_EXT_bgra
+ CONST_CAST(GLEW_EXT_bgra) = _glewSearchExtension("GL_EXT_bgra", extStart, extEnd);
+#endif /* GL_EXT_bgra */
+#ifdef GL_EXT_bindable_uniform
+ CONST_CAST(GLEW_EXT_bindable_uniform) = _glewSearchExtension("GL_EXT_bindable_uniform", extStart, extEnd);
+ if (glewExperimental || GLEW_EXT_bindable_uniform) CONST_CAST(GLEW_EXT_bindable_uniform) = !_glewInit_GL_EXT_bindable_uniform(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_EXT_bindable_uniform */
+#ifdef GL_EXT_blend_color
+ CONST_CAST(GLEW_EXT_blend_color) = _glewSearchExtension("GL_EXT_blend_color", extStart, extEnd);
+ if (glewExperimental || GLEW_EXT_blend_color) CONST_CAST(GLEW_EXT_blend_color) = !_glewInit_GL_EXT_blend_color(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_EXT_blend_color */
+#ifdef GL_EXT_blend_equation_separate
+ CONST_CAST(GLEW_EXT_blend_equation_separate) = _glewSearchExtension("GL_EXT_blend_equation_separate", extStart, extEnd);
+ if (glewExperimental || GLEW_EXT_blend_equation_separate) CONST_CAST(GLEW_EXT_blend_equation_separate) = !_glewInit_GL_EXT_blend_equation_separate(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_EXT_blend_equation_separate */
+#ifdef GL_EXT_blend_func_separate
+ CONST_CAST(GLEW_EXT_blend_func_separate) = _glewSearchExtension("GL_EXT_blend_func_separate", extStart, extEnd);
+ if (glewExperimental || GLEW_EXT_blend_func_separate) CONST_CAST(GLEW_EXT_blend_func_separate) = !_glewInit_GL_EXT_blend_func_separate(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_EXT_blend_func_separate */
+#ifdef GL_EXT_blend_logic_op
+ CONST_CAST(GLEW_EXT_blend_logic_op) = _glewSearchExtension("GL_EXT_blend_logic_op", extStart, extEnd);
+#endif /* GL_EXT_blend_logic_op */
+#ifdef GL_EXT_blend_minmax
+ CONST_CAST(GLEW_EXT_blend_minmax) = _glewSearchExtension("GL_EXT_blend_minmax", extStart, extEnd);
+ if (glewExperimental || GLEW_EXT_blend_minmax) CONST_CAST(GLEW_EXT_blend_minmax) = !_glewInit_GL_EXT_blend_minmax(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_EXT_blend_minmax */
+#ifdef GL_EXT_blend_subtract
+ CONST_CAST(GLEW_EXT_blend_subtract) = _glewSearchExtension("GL_EXT_blend_subtract", extStart, extEnd);
+#endif /* GL_EXT_blend_subtract */
+#ifdef GL_EXT_clip_volume_hint
+ CONST_CAST(GLEW_EXT_clip_volume_hint) = _glewSearchExtension("GL_EXT_clip_volume_hint", extStart, extEnd);
+#endif /* GL_EXT_clip_volume_hint */
+#ifdef GL_EXT_cmyka
+ CONST_CAST(GLEW_EXT_cmyka) = _glewSearchExtension("GL_EXT_cmyka", extStart, extEnd);
+#endif /* GL_EXT_cmyka */
+#ifdef GL_EXT_color_subtable
+ CONST_CAST(GLEW_EXT_color_subtable) = _glewSearchExtension("GL_EXT_color_subtable", extStart, extEnd);
+ if (glewExperimental || GLEW_EXT_color_subtable) CONST_CAST(GLEW_EXT_color_subtable) = !_glewInit_GL_EXT_color_subtable(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_EXT_color_subtable */
+#ifdef GL_EXT_compiled_vertex_array
+ CONST_CAST(GLEW_EXT_compiled_vertex_array) = _glewSearchExtension("GL_EXT_compiled_vertex_array", extStart, extEnd);
+ if (glewExperimental || GLEW_EXT_compiled_vertex_array) CONST_CAST(GLEW_EXT_compiled_vertex_array) = !_glewInit_GL_EXT_compiled_vertex_array(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_EXT_compiled_vertex_array */
+#ifdef GL_EXT_convolution
+ CONST_CAST(GLEW_EXT_convolution) = _glewSearchExtension("GL_EXT_convolution", extStart, extEnd);
+ if (glewExperimental || GLEW_EXT_convolution) CONST_CAST(GLEW_EXT_convolution) = !_glewInit_GL_EXT_convolution(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_EXT_convolution */
+#ifdef GL_EXT_coordinate_frame
+ CONST_CAST(GLEW_EXT_coordinate_frame) = _glewSearchExtension("GL_EXT_coordinate_frame", extStart, extEnd);
+ if (glewExperimental || GLEW_EXT_coordinate_frame) CONST_CAST(GLEW_EXT_coordinate_frame) = !_glewInit_GL_EXT_coordinate_frame(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_EXT_coordinate_frame */
+#ifdef GL_EXT_copy_texture
+ CONST_CAST(GLEW_EXT_copy_texture) = _glewSearchExtension("GL_EXT_copy_texture", extStart, extEnd);
+ if (glewExperimental || GLEW_EXT_copy_texture) CONST_CAST(GLEW_EXT_copy_texture) = !_glewInit_GL_EXT_copy_texture(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_EXT_copy_texture */
+#ifdef GL_EXT_cull_vertex
+ CONST_CAST(GLEW_EXT_cull_vertex) = _glewSearchExtension("GL_EXT_cull_vertex", extStart, extEnd);
+ if (glewExperimental || GLEW_EXT_cull_vertex) CONST_CAST(GLEW_EXT_cull_vertex) = !_glewInit_GL_EXT_cull_vertex(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_EXT_cull_vertex */
+#ifdef GL_EXT_depth_bounds_test
+ CONST_CAST(GLEW_EXT_depth_bounds_test) = _glewSearchExtension("GL_EXT_depth_bounds_test", extStart, extEnd);
+ if (glewExperimental || GLEW_EXT_depth_bounds_test) CONST_CAST(GLEW_EXT_depth_bounds_test) = !_glewInit_GL_EXT_depth_bounds_test(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_EXT_depth_bounds_test */
+#ifdef GL_EXT_direct_state_access
+ CONST_CAST(GLEW_EXT_direct_state_access) = _glewSearchExtension("GL_EXT_direct_state_access", extStart, extEnd);
+ if (glewExperimental || GLEW_EXT_direct_state_access) CONST_CAST(GLEW_EXT_direct_state_access) = !_glewInit_GL_EXT_direct_state_access(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_EXT_direct_state_access */
+#ifdef GL_EXT_draw_buffers2
+ CONST_CAST(GLEW_EXT_draw_buffers2) = _glewSearchExtension("GL_EXT_draw_buffers2", extStart, extEnd);
+ if (glewExperimental || GLEW_EXT_draw_buffers2) CONST_CAST(GLEW_EXT_draw_buffers2) = !_glewInit_GL_EXT_draw_buffers2(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_EXT_draw_buffers2 */
+#ifdef GL_EXT_draw_instanced
+ CONST_CAST(GLEW_EXT_draw_instanced) = _glewSearchExtension("GL_EXT_draw_instanced", extStart, extEnd);
+ if (glewExperimental || GLEW_EXT_draw_instanced) CONST_CAST(GLEW_EXT_draw_instanced) = !_glewInit_GL_EXT_draw_instanced(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_EXT_draw_instanced */
+#ifdef GL_EXT_draw_range_elements
+ CONST_CAST(GLEW_EXT_draw_range_elements) = _glewSearchExtension("GL_EXT_draw_range_elements", extStart, extEnd);
+ if (glewExperimental || GLEW_EXT_draw_range_elements) CONST_CAST(GLEW_EXT_draw_range_elements) = !_glewInit_GL_EXT_draw_range_elements(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_EXT_draw_range_elements */
+#ifdef GL_EXT_fog_coord
+ CONST_CAST(GLEW_EXT_fog_coord) = _glewSearchExtension("GL_EXT_fog_coord", extStart, extEnd);
+ if (glewExperimental || GLEW_EXT_fog_coord) CONST_CAST(GLEW_EXT_fog_coord) = !_glewInit_GL_EXT_fog_coord(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_EXT_fog_coord */
+#ifdef GL_EXT_fragment_lighting
+ CONST_CAST(GLEW_EXT_fragment_lighting) = _glewSearchExtension("GL_EXT_fragment_lighting", extStart, extEnd);
+ if (glewExperimental || GLEW_EXT_fragment_lighting) CONST_CAST(GLEW_EXT_fragment_lighting) = !_glewInit_GL_EXT_fragment_lighting(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_EXT_fragment_lighting */
+#ifdef GL_EXT_framebuffer_blit
+ CONST_CAST(GLEW_EXT_framebuffer_blit) = _glewSearchExtension("GL_EXT_framebuffer_blit", extStart, extEnd);
+ if (glewExperimental || GLEW_EXT_framebuffer_blit) CONST_CAST(GLEW_EXT_framebuffer_blit) = !_glewInit_GL_EXT_framebuffer_blit(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_EXT_framebuffer_blit */
+#ifdef GL_EXT_framebuffer_multisample
+ CONST_CAST(GLEW_EXT_framebuffer_multisample) = _glewSearchExtension("GL_EXT_framebuffer_multisample", extStart, extEnd);
+ if (glewExperimental || GLEW_EXT_framebuffer_multisample) CONST_CAST(GLEW_EXT_framebuffer_multisample) = !_glewInit_GL_EXT_framebuffer_multisample(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_EXT_framebuffer_multisample */
+#ifdef GL_EXT_framebuffer_multisample_blit_scaled
+ CONST_CAST(GLEW_EXT_framebuffer_multisample_blit_scaled) = _glewSearchExtension("GL_EXT_framebuffer_multisample_blit_scaled", extStart, extEnd);
+#endif /* GL_EXT_framebuffer_multisample_blit_scaled */
+#ifdef GL_EXT_framebuffer_object
+ CONST_CAST(GLEW_EXT_framebuffer_object) = _glewSearchExtension("GL_EXT_framebuffer_object", extStart, extEnd);
+ if (glewExperimental || GLEW_EXT_framebuffer_object) CONST_CAST(GLEW_EXT_framebuffer_object) = !_glewInit_GL_EXT_framebuffer_object(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_EXT_framebuffer_object */
+#ifdef GL_EXT_framebuffer_sRGB
+ CONST_CAST(GLEW_EXT_framebuffer_sRGB) = _glewSearchExtension("GL_EXT_framebuffer_sRGB", extStart, extEnd);
+#endif /* GL_EXT_framebuffer_sRGB */
+#ifdef GL_EXT_geometry_shader4
+ CONST_CAST(GLEW_EXT_geometry_shader4) = _glewSearchExtension("GL_EXT_geometry_shader4", extStart, extEnd);
+ if (glewExperimental || GLEW_EXT_geometry_shader4) CONST_CAST(GLEW_EXT_geometry_shader4) = !_glewInit_GL_EXT_geometry_shader4(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_EXT_geometry_shader4 */
+#ifdef GL_EXT_gpu_program_parameters
+ CONST_CAST(GLEW_EXT_gpu_program_parameters) = _glewSearchExtension("GL_EXT_gpu_program_parameters", extStart, extEnd);
+ if (glewExperimental || GLEW_EXT_gpu_program_parameters) CONST_CAST(GLEW_EXT_gpu_program_parameters) = !_glewInit_GL_EXT_gpu_program_parameters(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_EXT_gpu_program_parameters */
+#ifdef GL_EXT_gpu_shader4
+ CONST_CAST(GLEW_EXT_gpu_shader4) = _glewSearchExtension("GL_EXT_gpu_shader4", extStart, extEnd);
+ if (glewExperimental || GLEW_EXT_gpu_shader4) CONST_CAST(GLEW_EXT_gpu_shader4) = !_glewInit_GL_EXT_gpu_shader4(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_EXT_gpu_shader4 */
+#ifdef GL_EXT_histogram
+ CONST_CAST(GLEW_EXT_histogram) = _glewSearchExtension("GL_EXT_histogram", extStart, extEnd);
+ if (glewExperimental || GLEW_EXT_histogram) CONST_CAST(GLEW_EXT_histogram) = !_glewInit_GL_EXT_histogram(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_EXT_histogram */
+#ifdef GL_EXT_index_array_formats
+ CONST_CAST(GLEW_EXT_index_array_formats) = _glewSearchExtension("GL_EXT_index_array_formats", extStart, extEnd);
+#endif /* GL_EXT_index_array_formats */
+#ifdef GL_EXT_index_func
+ CONST_CAST(GLEW_EXT_index_func) = _glewSearchExtension("GL_EXT_index_func", extStart, extEnd);
+ if (glewExperimental || GLEW_EXT_index_func) CONST_CAST(GLEW_EXT_index_func) = !_glewInit_GL_EXT_index_func(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_EXT_index_func */
+#ifdef GL_EXT_index_material
+ CONST_CAST(GLEW_EXT_index_material) = _glewSearchExtension("GL_EXT_index_material", extStart, extEnd);
+ if (glewExperimental || GLEW_EXT_index_material) CONST_CAST(GLEW_EXT_index_material) = !_glewInit_GL_EXT_index_material(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_EXT_index_material */
+#ifdef GL_EXT_index_texture
+ CONST_CAST(GLEW_EXT_index_texture) = _glewSearchExtension("GL_EXT_index_texture", extStart, extEnd);
+#endif /* GL_EXT_index_texture */
+#ifdef GL_EXT_light_texture
+ CONST_CAST(GLEW_EXT_light_texture) = _glewSearchExtension("GL_EXT_light_texture", extStart, extEnd);
+ if (glewExperimental || GLEW_EXT_light_texture) CONST_CAST(GLEW_EXT_light_texture) = !_glewInit_GL_EXT_light_texture(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_EXT_light_texture */
+#ifdef GL_EXT_misc_attribute
+ CONST_CAST(GLEW_EXT_misc_attribute) = _glewSearchExtension("GL_EXT_misc_attribute", extStart, extEnd);
+#endif /* GL_EXT_misc_attribute */
+#ifdef GL_EXT_multi_draw_arrays
+ CONST_CAST(GLEW_EXT_multi_draw_arrays) = _glewSearchExtension("GL_EXT_multi_draw_arrays", extStart, extEnd);
+ if (glewExperimental || GLEW_EXT_multi_draw_arrays) CONST_CAST(GLEW_EXT_multi_draw_arrays) = !_glewInit_GL_EXT_multi_draw_arrays(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_EXT_multi_draw_arrays */
+#ifdef GL_EXT_multisample
+ CONST_CAST(GLEW_EXT_multisample) = _glewSearchExtension("GL_EXT_multisample", extStart, extEnd);
+ if (glewExperimental || GLEW_EXT_multisample) CONST_CAST(GLEW_EXT_multisample) = !_glewInit_GL_EXT_multisample(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_EXT_multisample */
+#ifdef GL_EXT_packed_depth_stencil
+ CONST_CAST(GLEW_EXT_packed_depth_stencil) = _glewSearchExtension("GL_EXT_packed_depth_stencil", extStart, extEnd);
+#endif /* GL_EXT_packed_depth_stencil */
+#ifdef GL_EXT_packed_float
+ CONST_CAST(GLEW_EXT_packed_float) = _glewSearchExtension("GL_EXT_packed_float", extStart, extEnd);
+#endif /* GL_EXT_packed_float */
+#ifdef GL_EXT_packed_pixels
+ CONST_CAST(GLEW_EXT_packed_pixels) = _glewSearchExtension("GL_EXT_packed_pixels", extStart, extEnd);
+#endif /* GL_EXT_packed_pixels */
+#ifdef GL_EXT_paletted_texture
+ CONST_CAST(GLEW_EXT_paletted_texture) = _glewSearchExtension("GL_EXT_paletted_texture", extStart, extEnd);
+ if (glewExperimental || GLEW_EXT_paletted_texture) CONST_CAST(GLEW_EXT_paletted_texture) = !_glewInit_GL_EXT_paletted_texture(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_EXT_paletted_texture */
+#ifdef GL_EXT_pixel_buffer_object
+ CONST_CAST(GLEW_EXT_pixel_buffer_object) = _glewSearchExtension("GL_EXT_pixel_buffer_object", extStart, extEnd);
+#endif /* GL_EXT_pixel_buffer_object */
+#ifdef GL_EXT_pixel_transform
+ CONST_CAST(GLEW_EXT_pixel_transform) = _glewSearchExtension("GL_EXT_pixel_transform", extStart, extEnd);
+ if (glewExperimental || GLEW_EXT_pixel_transform) CONST_CAST(GLEW_EXT_pixel_transform) = !_glewInit_GL_EXT_pixel_transform(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_EXT_pixel_transform */
+#ifdef GL_EXT_pixel_transform_color_table
+ CONST_CAST(GLEW_EXT_pixel_transform_color_table) = _glewSearchExtension("GL_EXT_pixel_transform_color_table", extStart, extEnd);
+#endif /* GL_EXT_pixel_transform_color_table */
+#ifdef GL_EXT_point_parameters
+ CONST_CAST(GLEW_EXT_point_parameters) = _glewSearchExtension("GL_EXT_point_parameters", extStart, extEnd);
+ if (glewExperimental || GLEW_EXT_point_parameters) CONST_CAST(GLEW_EXT_point_parameters) = !_glewInit_GL_EXT_point_parameters(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_EXT_point_parameters */
+#ifdef GL_EXT_polygon_offset
+ CONST_CAST(GLEW_EXT_polygon_offset) = _glewSearchExtension("GL_EXT_polygon_offset", extStart, extEnd);
+ if (glewExperimental || GLEW_EXT_polygon_offset) CONST_CAST(GLEW_EXT_polygon_offset) = !_glewInit_GL_EXT_polygon_offset(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_EXT_polygon_offset */
+#ifdef GL_EXT_provoking_vertex
+ CONST_CAST(GLEW_EXT_provoking_vertex) = _glewSearchExtension("GL_EXT_provoking_vertex", extStart, extEnd);
+ if (glewExperimental || GLEW_EXT_provoking_vertex) CONST_CAST(GLEW_EXT_provoking_vertex) = !_glewInit_GL_EXT_provoking_vertex(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_EXT_provoking_vertex */
+#ifdef GL_EXT_rescale_normal
+ CONST_CAST(GLEW_EXT_rescale_normal) = _glewSearchExtension("GL_EXT_rescale_normal", extStart, extEnd);
+#endif /* GL_EXT_rescale_normal */
+#ifdef GL_EXT_scene_marker
+ CONST_CAST(GLEW_EXT_scene_marker) = _glewSearchExtension("GL_EXT_scene_marker", extStart, extEnd);
+ if (glewExperimental || GLEW_EXT_scene_marker) CONST_CAST(GLEW_EXT_scene_marker) = !_glewInit_GL_EXT_scene_marker(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_EXT_scene_marker */
+#ifdef GL_EXT_secondary_color
+ CONST_CAST(GLEW_EXT_secondary_color) = _glewSearchExtension("GL_EXT_secondary_color", extStart, extEnd);
+ if (glewExperimental || GLEW_EXT_secondary_color) CONST_CAST(GLEW_EXT_secondary_color) = !_glewInit_GL_EXT_secondary_color(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_EXT_secondary_color */
+#if 0 // NOTE jwilkins: there is an inconsistency between the ES and Non-ES versions of this extension??
+#ifdef GL_EXT_separate_shader_objects
+ CONST_CAST(GLEW_EXT_separate_shader_objects) = _glewSearchExtension("GL_EXT_separate_shader_objects", extStart, extEnd);
+ if (glewExperimental || GLEW_EXT_separate_shader_objects) CONST_CAST(GLEW_EXT_separate_shader_objects) = !_glewInit_GL_EXT_separate_shader_objects(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_EXT_separate_shader_objects */
+#endif // XXX
+#ifdef GL_EXT_separate_specular_color
+ CONST_CAST(GLEW_EXT_separate_specular_color) = _glewSearchExtension("GL_EXT_separate_specular_color", extStart, extEnd);
+#endif /* GL_EXT_separate_specular_color */
+#ifdef GL_EXT_shader_image_load_store
+ CONST_CAST(GLEW_EXT_shader_image_load_store) = _glewSearchExtension("GL_EXT_shader_image_load_store", extStart, extEnd);
+ if (glewExperimental || GLEW_EXT_shader_image_load_store) CONST_CAST(GLEW_EXT_shader_image_load_store) = !_glewInit_GL_EXT_shader_image_load_store(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_EXT_shader_image_load_store */
+#ifdef GL_EXT_shadow_funcs
+ CONST_CAST(GLEW_EXT_shadow_funcs) = _glewSearchExtension("GL_EXT_shadow_funcs", extStart, extEnd);
+#endif /* GL_EXT_shadow_funcs */
+#ifdef GL_EXT_shared_texture_palette
+ CONST_CAST(GLEW_EXT_shared_texture_palette) = _glewSearchExtension("GL_EXT_shared_texture_palette", extStart, extEnd);
+#endif /* GL_EXT_shared_texture_palette */
+#ifdef GL_EXT_stencil_clear_tag
+ CONST_CAST(GLEW_EXT_stencil_clear_tag) = _glewSearchExtension("GL_EXT_stencil_clear_tag", extStart, extEnd);
+#endif /* GL_EXT_stencil_clear_tag */
+#ifdef GL_EXT_stencil_two_side
+ CONST_CAST(GLEW_EXT_stencil_two_side) = _glewSearchExtension("GL_EXT_stencil_two_side", extStart, extEnd);
+ if (glewExperimental || GLEW_EXT_stencil_two_side) CONST_CAST(GLEW_EXT_stencil_two_side) = !_glewInit_GL_EXT_stencil_two_side(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_EXT_stencil_two_side */
+#ifdef GL_EXT_stencil_wrap
+ CONST_CAST(GLEW_EXT_stencil_wrap) = _glewSearchExtension("GL_EXT_stencil_wrap", extStart, extEnd);
+#endif /* GL_EXT_stencil_wrap */
+#ifdef GL_EXT_subtexture
+ CONST_CAST(GLEW_EXT_subtexture) = _glewSearchExtension("GL_EXT_subtexture", extStart, extEnd);
+ if (glewExperimental || GLEW_EXT_subtexture) CONST_CAST(GLEW_EXT_subtexture) = !_glewInit_GL_EXT_subtexture(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_EXT_subtexture */
+#ifdef GL_EXT_texture
+ CONST_CAST(GLEW_EXT_texture) = _glewSearchExtension("GL_EXT_texture", extStart, extEnd);
+#endif /* GL_EXT_texture */
+#ifdef GL_EXT_texture3D
+ CONST_CAST(GLEW_EXT_texture3D) = _glewSearchExtension("GL_EXT_texture3D", extStart, extEnd);
+ if (glewExperimental || GLEW_EXT_texture3D) CONST_CAST(GLEW_EXT_texture3D) = !_glewInit_GL_EXT_texture3D(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_EXT_texture3D */
+#ifdef GL_EXT_texture_array
+ CONST_CAST(GLEW_EXT_texture_array) = _glewSearchExtension("GL_EXT_texture_array", extStart, extEnd);
+ if (glewExperimental || GLEW_EXT_texture_array) CONST_CAST(GLEW_EXT_texture_array) = !_glewInit_GL_EXT_texture_array(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_EXT_texture_array */
+#ifdef GL_EXT_texture_buffer_object
+ CONST_CAST(GLEW_EXT_texture_buffer_object) = _glewSearchExtension("GL_EXT_texture_buffer_object", extStart, extEnd);
+ if (glewExperimental || GLEW_EXT_texture_buffer_object) CONST_CAST(GLEW_EXT_texture_buffer_object) = !_glewInit_GL_EXT_texture_buffer_object(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_EXT_texture_buffer_object */
+#ifdef GL_EXT_texture_compression_dxt1
+ CONST_CAST(GLEW_EXT_texture_compression_dxt1) = _glewSearchExtension("GL_EXT_texture_compression_dxt1", extStart, extEnd);
+#endif /* GL_EXT_texture_compression_dxt1 */
+#ifdef GL_EXT_texture_compression_latc
+ CONST_CAST(GLEW_EXT_texture_compression_latc) = _glewSearchExtension("GL_EXT_texture_compression_latc", extStart, extEnd);
+#endif /* GL_EXT_texture_compression_latc */
+#ifdef GL_EXT_texture_compression_rgtc
+ CONST_CAST(GLEW_EXT_texture_compression_rgtc) = _glewSearchExtension("GL_EXT_texture_compression_rgtc", extStart, extEnd);
+#endif /* GL_EXT_texture_compression_rgtc */
+#ifdef GL_EXT_texture_compression_s3tc
+ CONST_CAST(GLEW_EXT_texture_compression_s3tc) = _glewSearchExtension("GL_EXT_texture_compression_s3tc", extStart, extEnd);
+#endif /* GL_EXT_texture_compression_s3tc */
+#ifdef GL_EXT_texture_cube_map
+ CONST_CAST(GLEW_EXT_texture_cube_map) = _glewSearchExtension("GL_EXT_texture_cube_map", extStart, extEnd);
+#endif /* GL_EXT_texture_cube_map */
+#ifdef GL_EXT_texture_edge_clamp
+ CONST_CAST(GLEW_EXT_texture_edge_clamp) = _glewSearchExtension("GL_EXT_texture_edge_clamp", extStart, extEnd);
+#endif /* GL_EXT_texture_edge_clamp */
+#ifdef GL_EXT_texture_env
+ CONST_CAST(GLEW_EXT_texture_env) = _glewSearchExtension("GL_EXT_texture_env", extStart, extEnd);
+#endif /* GL_EXT_texture_env */
+#ifdef GL_EXT_texture_env_add
+ CONST_CAST(GLEW_EXT_texture_env_add) = _glewSearchExtension("GL_EXT_texture_env_add", extStart, extEnd);
+#endif /* GL_EXT_texture_env_add */
+#ifdef GL_EXT_texture_env_combine
+ CONST_CAST(GLEW_EXT_texture_env_combine) = _glewSearchExtension("GL_EXT_texture_env_combine", extStart, extEnd);
+#endif /* GL_EXT_texture_env_combine */
+#ifdef GL_EXT_texture_env_dot3
+ CONST_CAST(GLEW_EXT_texture_env_dot3) = _glewSearchExtension("GL_EXT_texture_env_dot3", extStart, extEnd);
+#endif /* GL_EXT_texture_env_dot3 */
+#ifdef GL_EXT_texture_filter_anisotropic
+ CONST_CAST(GLEW_EXT_texture_filter_anisotropic) = _glewSearchExtension("GL_EXT_texture_filter_anisotropic", extStart, extEnd);
+#endif /* GL_EXT_texture_filter_anisotropic */
+#ifdef GL_EXT_texture_integer
+ CONST_CAST(GLEW_EXT_texture_integer) = _glewSearchExtension("GL_EXT_texture_integer", extStart, extEnd);
+ if (glewExperimental || GLEW_EXT_texture_integer) CONST_CAST(GLEW_EXT_texture_integer) = !_glewInit_GL_EXT_texture_integer(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_EXT_texture_integer */
+#ifdef GL_EXT_texture_lod_bias
+ CONST_CAST(GLEW_EXT_texture_lod_bias) = _glewSearchExtension("GL_EXT_texture_lod_bias", extStart, extEnd);
+#endif /* GL_EXT_texture_lod_bias */
+#ifdef GL_EXT_texture_mirror_clamp
+ CONST_CAST(GLEW_EXT_texture_mirror_clamp) = _glewSearchExtension("GL_EXT_texture_mirror_clamp", extStart, extEnd);
+#endif /* GL_EXT_texture_mirror_clamp */
+#ifdef GL_EXT_texture_object
+ CONST_CAST(GLEW_EXT_texture_object) = _glewSearchExtension("GL_EXT_texture_object", extStart, extEnd);
+ if (glewExperimental || GLEW_EXT_texture_object) CONST_CAST(GLEW_EXT_texture_object) = !_glewInit_GL_EXT_texture_object(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_EXT_texture_object */
+#ifdef GL_EXT_texture_perturb_normal
+ CONST_CAST(GLEW_EXT_texture_perturb_normal) = _glewSearchExtension("GL_EXT_texture_perturb_normal", extStart, extEnd);
+ if (glewExperimental || GLEW_EXT_texture_perturb_normal) CONST_CAST(GLEW_EXT_texture_perturb_normal) = !_glewInit_GL_EXT_texture_perturb_normal(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_EXT_texture_perturb_normal */
+#ifdef GL_EXT_texture_rectangle
+ CONST_CAST(GLEW_EXT_texture_rectangle) = _glewSearchExtension("GL_EXT_texture_rectangle", extStart, extEnd);
+#endif /* GL_EXT_texture_rectangle */
+#ifdef GL_EXT_texture_sRGB
+ CONST_CAST(GLEW_EXT_texture_sRGB) = _glewSearchExtension("GL_EXT_texture_sRGB", extStart, extEnd);
+#endif /* GL_EXT_texture_sRGB */
+#ifdef GL_EXT_texture_sRGB_decode
+ CONST_CAST(GLEW_EXT_texture_sRGB_decode) = _glewSearchExtension("GL_EXT_texture_sRGB_decode", extStart, extEnd);
+#endif /* GL_EXT_texture_sRGB_decode */
+#ifdef GL_EXT_texture_shared_exponent
+ CONST_CAST(GLEW_EXT_texture_shared_exponent) = _glewSearchExtension("GL_EXT_texture_shared_exponent", extStart, extEnd);
+#endif /* GL_EXT_texture_shared_exponent */
+#ifdef GL_EXT_texture_snorm
+ CONST_CAST(GLEW_EXT_texture_snorm) = _glewSearchExtension("GL_EXT_texture_snorm", extStart, extEnd);
+#endif /* GL_EXT_texture_snorm */
+#ifdef GL_EXT_texture_swizzle
+ CONST_CAST(GLEW_EXT_texture_swizzle) = _glewSearchExtension("GL_EXT_texture_swizzle", extStart, extEnd);
+#endif /* GL_EXT_texture_swizzle */
+#ifdef GL_EXT_timer_query
+ CONST_CAST(GLEW_EXT_timer_query) = _glewSearchExtension("GL_EXT_timer_query", extStart, extEnd);
+ if (glewExperimental || GLEW_EXT_timer_query) CONST_CAST(GLEW_EXT_timer_query) = !_glewInit_GL_EXT_timer_query(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_EXT_timer_query */
+#ifdef GL_EXT_transform_feedback
+ CONST_CAST(GLEW_EXT_transform_feedback) = _glewSearchExtension("GL_EXT_transform_feedback", extStart, extEnd);
+ if (glewExperimental || GLEW_EXT_transform_feedback) CONST_CAST(GLEW_EXT_transform_feedback) = !_glewInit_GL_EXT_transform_feedback(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_EXT_transform_feedback */
+#ifdef GL_EXT_vertex_array
+ CONST_CAST(GLEW_EXT_vertex_array) = _glewSearchExtension("GL_EXT_vertex_array", extStart, extEnd);
+ if (glewExperimental || GLEW_EXT_vertex_array) CONST_CAST(GLEW_EXT_vertex_array) = !_glewInit_GL_EXT_vertex_array(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_EXT_vertex_array */
+#ifdef GL_EXT_vertex_array_bgra
+ CONST_CAST(GLEW_EXT_vertex_array_bgra) = _glewSearchExtension("GL_EXT_vertex_array_bgra", extStart, extEnd);
+#endif /* GL_EXT_vertex_array_bgra */
+#ifdef GL_EXT_vertex_attrib_64bit
+ CONST_CAST(GLEW_EXT_vertex_attrib_64bit) = _glewSearchExtension("GL_EXT_vertex_attrib_64bit", extStart, extEnd);
+ if (glewExperimental || GLEW_EXT_vertex_attrib_64bit) CONST_CAST(GLEW_EXT_vertex_attrib_64bit) = !_glewInit_GL_EXT_vertex_attrib_64bit(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_EXT_vertex_attrib_64bit */
+#ifdef GL_EXT_vertex_shader
+ CONST_CAST(GLEW_EXT_vertex_shader) = _glewSearchExtension("GL_EXT_vertex_shader", extStart, extEnd);
+ if (glewExperimental || GLEW_EXT_vertex_shader) CONST_CAST(GLEW_EXT_vertex_shader) = !_glewInit_GL_EXT_vertex_shader(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_EXT_vertex_shader */
+#ifdef GL_EXT_vertex_weighting
+ CONST_CAST(GLEW_EXT_vertex_weighting) = _glewSearchExtension("GL_EXT_vertex_weighting", extStart, extEnd);
+ if (glewExperimental || GLEW_EXT_vertex_weighting) CONST_CAST(GLEW_EXT_vertex_weighting) = !_glewInit_GL_EXT_vertex_weighting(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_EXT_vertex_weighting */
+#ifdef GL_EXT_x11_sync_object
+ CONST_CAST(GLEW_EXT_x11_sync_object) = _glewSearchExtension("GL_EXT_x11_sync_object", extStart, extEnd);
+ if (glewExperimental || GLEW_EXT_x11_sync_object) CONST_CAST(GLEW_EXT_x11_sync_object) = !_glewInit_GL_EXT_x11_sync_object(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_EXT_x11_sync_object */
+#ifdef GL_GREMEDY_frame_terminator
+ CONST_CAST(GLEW_GREMEDY_frame_terminator) = _glewSearchExtension("GL_GREMEDY_frame_terminator", extStart, extEnd);
+ if (glewExperimental || GLEW_GREMEDY_frame_terminator) CONST_CAST(GLEW_GREMEDY_frame_terminator) = !_glewInit_GL_GREMEDY_frame_terminator(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_GREMEDY_frame_terminator */
+#ifdef GL_GREMEDY_string_marker
+ CONST_CAST(GLEW_GREMEDY_string_marker) = _glewSearchExtension("GL_GREMEDY_string_marker", extStart, extEnd);
+ if (glewExperimental || GLEW_GREMEDY_string_marker) CONST_CAST(GLEW_GREMEDY_string_marker) = !_glewInit_GL_GREMEDY_string_marker(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_GREMEDY_string_marker */
+#ifdef GL_HP_convolution_border_modes
+ CONST_CAST(GLEW_HP_convolution_border_modes) = _glewSearchExtension("GL_HP_convolution_border_modes", extStart, extEnd);
+#endif /* GL_HP_convolution_border_modes */
+#ifdef GL_HP_image_transform
+ CONST_CAST(GLEW_HP_image_transform) = _glewSearchExtension("GL_HP_image_transform", extStart, extEnd);
+ if (glewExperimental || GLEW_HP_image_transform) CONST_CAST(GLEW_HP_image_transform) = !_glewInit_GL_HP_image_transform(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_HP_image_transform */
+#ifdef GL_HP_occlusion_test
+ CONST_CAST(GLEW_HP_occlusion_test) = _glewSearchExtension("GL_HP_occlusion_test", extStart, extEnd);
+#endif /* GL_HP_occlusion_test */
+#ifdef GL_HP_texture_lighting
+ CONST_CAST(GLEW_HP_texture_lighting) = _glewSearchExtension("GL_HP_texture_lighting", extStart, extEnd);
+#endif /* GL_HP_texture_lighting */
+#ifdef GL_IBM_cull_vertex
+ CONST_CAST(GLEW_IBM_cull_vertex) = _glewSearchExtension("GL_IBM_cull_vertex", extStart, extEnd);
+#endif /* GL_IBM_cull_vertex */
+#ifdef GL_IBM_multimode_draw_arrays
+ CONST_CAST(GLEW_IBM_multimode_draw_arrays) = _glewSearchExtension("GL_IBM_multimode_draw_arrays", extStart, extEnd);
+ if (glewExperimental || GLEW_IBM_multimode_draw_arrays) CONST_CAST(GLEW_IBM_multimode_draw_arrays) = !_glewInit_GL_IBM_multimode_draw_arrays(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_IBM_multimode_draw_arrays */
+#ifdef GL_IBM_rasterpos_clip
+ CONST_CAST(GLEW_IBM_rasterpos_clip) = _glewSearchExtension("GL_IBM_rasterpos_clip", extStart, extEnd);
+#endif /* GL_IBM_rasterpos_clip */
+#ifdef GL_IBM_static_data
+ CONST_CAST(GLEW_IBM_static_data) = _glewSearchExtension("GL_IBM_static_data", extStart, extEnd);
+#endif /* GL_IBM_static_data */
+#ifdef GL_IBM_texture_mirrored_repeat
+ CONST_CAST(GLEW_IBM_texture_mirrored_repeat) = _glewSearchExtension("GL_IBM_texture_mirrored_repeat", extStart, extEnd);
+#endif /* GL_IBM_texture_mirrored_repeat */
+#ifdef GL_IBM_vertex_array_lists
+ CONST_CAST(GLEW_IBM_vertex_array_lists) = _glewSearchExtension("GL_IBM_vertex_array_lists", extStart, extEnd);
+ if (glewExperimental || GLEW_IBM_vertex_array_lists) CONST_CAST(GLEW_IBM_vertex_array_lists) = !_glewInit_GL_IBM_vertex_array_lists(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_IBM_vertex_array_lists */
+#ifdef GL_INGR_color_clamp
+ CONST_CAST(GLEW_INGR_color_clamp) = _glewSearchExtension("GL_INGR_color_clamp", extStart, extEnd);
+#endif /* GL_INGR_color_clamp */
+#ifdef GL_INGR_interlace_read
+ CONST_CAST(GLEW_INGR_interlace_read) = _glewSearchExtension("GL_INGR_interlace_read", extStart, extEnd);
+#endif /* GL_INGR_interlace_read */
+#ifdef GL_INTEL_map_texture
+ CONST_CAST(GLEW_INTEL_map_texture) = _glewSearchExtension("GL_INTEL_map_texture", extStart, extEnd);
+ if (glewExperimental || GLEW_INTEL_map_texture) CONST_CAST(GLEW_INTEL_map_texture) = !_glewInit_GL_INTEL_map_texture(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_INTEL_map_texture */
+#ifdef GL_INTEL_parallel_arrays
+ CONST_CAST(GLEW_INTEL_parallel_arrays) = _glewSearchExtension("GL_INTEL_parallel_arrays", extStart, extEnd);
+ if (glewExperimental || GLEW_INTEL_parallel_arrays) CONST_CAST(GLEW_INTEL_parallel_arrays) = !_glewInit_GL_INTEL_parallel_arrays(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_INTEL_parallel_arrays */
+#ifdef GL_INTEL_texture_scissor
+ CONST_CAST(GLEW_INTEL_texture_scissor) = _glewSearchExtension("GL_INTEL_texture_scissor", extStart, extEnd);
+ if (glewExperimental || GLEW_INTEL_texture_scissor) CONST_CAST(GLEW_INTEL_texture_scissor) = !_glewInit_GL_INTEL_texture_scissor(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_INTEL_texture_scissor */
+#ifdef GL_KHR_debug
+ CONST_CAST(GLEW_KHR_debug) = _glewSearchExtension("GL_KHR_debug", extStart, extEnd);
+ if (glewExperimental || GLEW_KHR_debug) CONST_CAST(GLEW_KHR_debug) = !_glewInit_GL_KHR_debug(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_KHR_debug */
+#ifdef GL_KHR_texture_compression_astc_ldr
+ CONST_CAST(GLEW_KHR_texture_compression_astc_ldr) = _glewSearchExtension("GL_KHR_texture_compression_astc_ldr", extStart, extEnd);
+#endif /* GL_KHR_texture_compression_astc_ldr */
+#ifdef GL_KTX_buffer_region
+ CONST_CAST(GLEW_KTX_buffer_region) = _glewSearchExtension("GL_KTX_buffer_region", extStart, extEnd);
+ if (glewExperimental || GLEW_KTX_buffer_region) CONST_CAST(GLEW_KTX_buffer_region) = !_glewInit_GL_KTX_buffer_region(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_KTX_buffer_region */
+#ifdef GL_MESAX_texture_stack
+ CONST_CAST(GLEW_MESAX_texture_stack) = _glewSearchExtension("GL_MESAX_texture_stack", extStart, extEnd);
+#endif /* GL_MESAX_texture_stack */
+#ifdef GL_MESA_pack_invert
+ CONST_CAST(GLEW_MESA_pack_invert) = _glewSearchExtension("GL_MESA_pack_invert", extStart, extEnd);
+#endif /* GL_MESA_pack_invert */
+#ifdef GL_MESA_resize_buffers
+ CONST_CAST(GLEW_MESA_resize_buffers) = _glewSearchExtension("GL_MESA_resize_buffers", extStart, extEnd);
+ if (glewExperimental || GLEW_MESA_resize_buffers) CONST_CAST(GLEW_MESA_resize_buffers) = !_glewInit_GL_MESA_resize_buffers(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_MESA_resize_buffers */
+#ifdef GL_MESA_window_pos
+ CONST_CAST(GLEW_MESA_window_pos) = _glewSearchExtension("GL_MESA_window_pos", extStart, extEnd);
+ if (glewExperimental || GLEW_MESA_window_pos) CONST_CAST(GLEW_MESA_window_pos) = !_glewInit_GL_MESA_window_pos(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_MESA_window_pos */
+#ifdef GL_MESA_ycbcr_texture
+ CONST_CAST(GLEW_MESA_ycbcr_texture) = _glewSearchExtension("GL_MESA_ycbcr_texture", extStart, extEnd);
+#endif /* GL_MESA_ycbcr_texture */
+#ifdef GL_NVX_conditional_render
+ CONST_CAST(GLEW_NVX_conditional_render) = _glewSearchExtension("GL_NVX_conditional_render", extStart, extEnd);
+ if (glewExperimental || GLEW_NVX_conditional_render) CONST_CAST(GLEW_NVX_conditional_render) = !_glewInit_GL_NVX_conditional_render(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_NVX_conditional_render */
+#ifdef GL_NVX_gpu_memory_info
+ CONST_CAST(GLEW_NVX_gpu_memory_info) = _glewSearchExtension("GL_NVX_gpu_memory_info", extStart, extEnd);
+#endif /* GL_NVX_gpu_memory_info */
+#ifdef GL_NV_bindless_texture
+ CONST_CAST(GLEW_NV_bindless_texture) = _glewSearchExtension("GL_NV_bindless_texture", extStart, extEnd);
+ if (glewExperimental || GLEW_NV_bindless_texture) CONST_CAST(GLEW_NV_bindless_texture) = !_glewInit_GL_NV_bindless_texture(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_NV_bindless_texture */
+#ifdef GL_NV_blend_square
+ CONST_CAST(GLEW_NV_blend_square) = _glewSearchExtension("GL_NV_blend_square", extStart, extEnd);
+#endif /* GL_NV_blend_square */
+#ifdef GL_NV_compute_program5
+ CONST_CAST(GLEW_NV_compute_program5) = _glewSearchExtension("GL_NV_compute_program5", extStart, extEnd);
+#endif /* GL_NV_compute_program5 */
+#ifdef GL_NV_conditional_render
+ CONST_CAST(GLEW_NV_conditional_render) = _glewSearchExtension("GL_NV_conditional_render", extStart, extEnd);
+ if (glewExperimental || GLEW_NV_conditional_render) CONST_CAST(GLEW_NV_conditional_render) = !_glewInit_GL_NV_conditional_render(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_NV_conditional_render */
+#ifdef GL_NV_copy_depth_to_color
+ CONST_CAST(GLEW_NV_copy_depth_to_color) = _glewSearchExtension("GL_NV_copy_depth_to_color", extStart, extEnd);
+#endif /* GL_NV_copy_depth_to_color */
+#ifdef GL_NV_copy_image
+ CONST_CAST(GLEW_NV_copy_image) = _glewSearchExtension("GL_NV_copy_image", extStart, extEnd);
+ if (glewExperimental || GLEW_NV_copy_image) CONST_CAST(GLEW_NV_copy_image) = !_glewInit_GL_NV_copy_image(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_NV_copy_image */
+#ifdef GL_NV_deep_texture3D
+ CONST_CAST(GLEW_NV_deep_texture3D) = _glewSearchExtension("GL_NV_deep_texture3D", extStart, extEnd);
+#endif /* GL_NV_deep_texture3D */
+#ifdef GL_NV_depth_buffer_float
+ CONST_CAST(GLEW_NV_depth_buffer_float) = _glewSearchExtension("GL_NV_depth_buffer_float", extStart, extEnd);
+ if (glewExperimental || GLEW_NV_depth_buffer_float) CONST_CAST(GLEW_NV_depth_buffer_float) = !_glewInit_GL_NV_depth_buffer_float(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_NV_depth_buffer_float */
+#ifdef GL_NV_depth_clamp
+ CONST_CAST(GLEW_NV_depth_clamp) = _glewSearchExtension("GL_NV_depth_clamp", extStart, extEnd);
+#endif /* GL_NV_depth_clamp */
+#ifdef GL_NV_depth_range_unclamped
+ CONST_CAST(GLEW_NV_depth_range_unclamped) = _glewSearchExtension("GL_NV_depth_range_unclamped", extStart, extEnd);
+#endif /* GL_NV_depth_range_unclamped */
+#ifdef GL_NV_draw_texture
+ CONST_CAST(GLEW_NV_draw_texture) = _glewSearchExtension("GL_NV_draw_texture", extStart, extEnd);
+ if (glewExperimental || GLEW_NV_draw_texture) CONST_CAST(GLEW_NV_draw_texture) = !_glewInit_GL_NV_draw_texture(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_NV_draw_texture */
+#ifdef GL_NV_evaluators
+ CONST_CAST(GLEW_NV_evaluators) = _glewSearchExtension("GL_NV_evaluators", extStart, extEnd);
+ if (glewExperimental || GLEW_NV_evaluators) CONST_CAST(GLEW_NV_evaluators) = !_glewInit_GL_NV_evaluators(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_NV_evaluators */
+#ifdef GL_NV_explicit_multisample
+ CONST_CAST(GLEW_NV_explicit_multisample) = _glewSearchExtension("GL_NV_explicit_multisample", extStart, extEnd);
+ if (glewExperimental || GLEW_NV_explicit_multisample) CONST_CAST(GLEW_NV_explicit_multisample) = !_glewInit_GL_NV_explicit_multisample(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_NV_explicit_multisample */
+#ifdef GL_NV_fence
+ CONST_CAST(GLEW_NV_fence) = _glewSearchExtension("GL_NV_fence", extStart, extEnd);
+ if (glewExperimental || GLEW_NV_fence) CONST_CAST(GLEW_NV_fence) = !_glewInit_GL_NV_fence(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_NV_fence */
+#ifdef GL_NV_float_buffer
+ CONST_CAST(GLEW_NV_float_buffer) = _glewSearchExtension("GL_NV_float_buffer", extStart, extEnd);
+#endif /* GL_NV_float_buffer */
+#ifdef GL_NV_fog_distance
+ CONST_CAST(GLEW_NV_fog_distance) = _glewSearchExtension("GL_NV_fog_distance", extStart, extEnd);
+#endif /* GL_NV_fog_distance */
+#ifdef GL_NV_fragment_program
+ CONST_CAST(GLEW_NV_fragment_program) = _glewSearchExtension("GL_NV_fragment_program", extStart, extEnd);
+ if (glewExperimental || GLEW_NV_fragment_program) CONST_CAST(GLEW_NV_fragment_program) = !_glewInit_GL_NV_fragment_program(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_NV_fragment_program */
+#ifdef GL_NV_fragment_program2
+ CONST_CAST(GLEW_NV_fragment_program2) = _glewSearchExtension("GL_NV_fragment_program2", extStart, extEnd);
+#endif /* GL_NV_fragment_program2 */
+#ifdef GL_NV_fragment_program4
+ CONST_CAST(GLEW_NV_fragment_program4) = _glewSearchExtension("GL_NV_gpu_program4", extStart, extEnd);
+#endif /* GL_NV_fragment_program4 */
+#ifdef GL_NV_fragment_program_option
+ CONST_CAST(GLEW_NV_fragment_program_option) = _glewSearchExtension("GL_NV_fragment_program_option", extStart, extEnd);
+#endif /* GL_NV_fragment_program_option */
+#ifdef GL_NV_framebuffer_multisample_coverage
+ CONST_CAST(GLEW_NV_framebuffer_multisample_coverage) = _glewSearchExtension("GL_NV_framebuffer_multisample_coverage", extStart, extEnd);
+ if (glewExperimental || GLEW_NV_framebuffer_multisample_coverage) CONST_CAST(GLEW_NV_framebuffer_multisample_coverage) = !_glewInit_GL_NV_framebuffer_multisample_coverage(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_NV_framebuffer_multisample_coverage */
+#ifdef GL_NV_geometry_program4
+ CONST_CAST(GLEW_NV_geometry_program4) = _glewSearchExtension("GL_NV_gpu_program4", extStart, extEnd);
+ if (glewExperimental || GLEW_NV_geometry_program4) CONST_CAST(GLEW_NV_geometry_program4) = !_glewInit_GL_NV_geometry_program4(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_NV_geometry_program4 */
+#ifdef GL_NV_geometry_shader4
+ CONST_CAST(GLEW_NV_geometry_shader4) = _glewSearchExtension("GL_NV_geometry_shader4", extStart, extEnd);
+#endif /* GL_NV_geometry_shader4 */
+#ifdef GL_NV_gpu_program4
+ CONST_CAST(GLEW_NV_gpu_program4) = _glewSearchExtension("GL_NV_gpu_program4", extStart, extEnd);
+ if (glewExperimental || GLEW_NV_gpu_program4) CONST_CAST(GLEW_NV_gpu_program4) = !_glewInit_GL_NV_gpu_program4(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_NV_gpu_program4 */
+#ifdef GL_NV_gpu_program5
+ CONST_CAST(GLEW_NV_gpu_program5) = _glewSearchExtension("GL_NV_gpu_program5", extStart, extEnd);
+#endif /* GL_NV_gpu_program5 */
+#ifdef GL_NV_gpu_program_fp64
+ CONST_CAST(GLEW_NV_gpu_program_fp64) = _glewSearchExtension("GL_NV_gpu_program_fp64", extStart, extEnd);
+#endif /* GL_NV_gpu_program_fp64 */
+#ifdef GL_NV_gpu_shader5
+ CONST_CAST(GLEW_NV_gpu_shader5) = _glewSearchExtension("GL_NV_gpu_shader5", extStart, extEnd);
+ if (glewExperimental || GLEW_NV_gpu_shader5) CONST_CAST(GLEW_NV_gpu_shader5) = !_glewInit_GL_NV_gpu_shader5(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_NV_gpu_shader5 */
+#ifdef GL_NV_half_float
+ CONST_CAST(GLEW_NV_half_float) = _glewSearchExtension("GL_NV_half_float", extStart, extEnd);
+ if (glewExperimental || GLEW_NV_half_float) CONST_CAST(GLEW_NV_half_float) = !_glewInit_GL_NV_half_float(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_NV_half_float */
+#ifdef GL_NV_light_max_exponent
+ CONST_CAST(GLEW_NV_light_max_exponent) = _glewSearchExtension("GL_NV_light_max_exponent", extStart, extEnd);
+#endif /* GL_NV_light_max_exponent */
+#ifdef GL_NV_multisample_coverage
+ CONST_CAST(GLEW_NV_multisample_coverage) = _glewSearchExtension("GL_NV_multisample_coverage", extStart, extEnd);
+#endif /* GL_NV_multisample_coverage */
+#ifdef GL_NV_multisample_filter_hint
+ CONST_CAST(GLEW_NV_multisample_filter_hint) = _glewSearchExtension("GL_NV_multisample_filter_hint", extStart, extEnd);
+#endif /* GL_NV_multisample_filter_hint */
+#ifdef GL_NV_occlusion_query
+ CONST_CAST(GLEW_NV_occlusion_query) = _glewSearchExtension("GL_NV_occlusion_query", extStart, extEnd);
+ if (glewExperimental || GLEW_NV_occlusion_query) CONST_CAST(GLEW_NV_occlusion_query) = !_glewInit_GL_NV_occlusion_query(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_NV_occlusion_query */
+#ifdef GL_NV_packed_depth_stencil
+ CONST_CAST(GLEW_NV_packed_depth_stencil) = _glewSearchExtension("GL_NV_packed_depth_stencil", extStart, extEnd);
+#endif /* GL_NV_packed_depth_stencil */
+#ifdef GL_NV_parameter_buffer_object
+ CONST_CAST(GLEW_NV_parameter_buffer_object) = _glewSearchExtension("GL_NV_parameter_buffer_object", extStart, extEnd);
+ if (glewExperimental || GLEW_NV_parameter_buffer_object) CONST_CAST(GLEW_NV_parameter_buffer_object) = !_glewInit_GL_NV_parameter_buffer_object(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_NV_parameter_buffer_object */
+#ifdef GL_NV_parameter_buffer_object2
+ CONST_CAST(GLEW_NV_parameter_buffer_object2) = _glewSearchExtension("GL_NV_parameter_buffer_object2", extStart, extEnd);
+#endif /* GL_NV_parameter_buffer_object2 */
+#ifdef GL_NV_path_rendering
+ CONST_CAST(GLEW_NV_path_rendering) = _glewSearchExtension("GL_NV_path_rendering", extStart, extEnd);
+ if (glewExperimental || GLEW_NV_path_rendering) CONST_CAST(GLEW_NV_path_rendering) = !_glewInit_GL_NV_path_rendering(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_NV_path_rendering */
+#ifdef GL_NV_pixel_data_range
+ CONST_CAST(GLEW_NV_pixel_data_range) = _glewSearchExtension("GL_NV_pixel_data_range", extStart, extEnd);
+ if (glewExperimental || GLEW_NV_pixel_data_range) CONST_CAST(GLEW_NV_pixel_data_range) = !_glewInit_GL_NV_pixel_data_range(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_NV_pixel_data_range */
+#ifdef GL_NV_point_sprite
+ CONST_CAST(GLEW_NV_point_sprite) = _glewSearchExtension("GL_NV_point_sprite", extStart, extEnd);
+ if (glewExperimental || GLEW_NV_point_sprite) CONST_CAST(GLEW_NV_point_sprite) = !_glewInit_GL_NV_point_sprite(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_NV_point_sprite */
+#ifdef GL_NV_present_video
+ CONST_CAST(GLEW_NV_present_video) = _glewSearchExtension("GL_NV_present_video", extStart, extEnd);
+ if (glewExperimental || GLEW_NV_present_video) CONST_CAST(GLEW_NV_present_video) = !_glewInit_GL_NV_present_video(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_NV_present_video */
+#ifdef GL_NV_primitive_restart
+ CONST_CAST(GLEW_NV_primitive_restart) = _glewSearchExtension("GL_NV_primitive_restart", extStart, extEnd);
+ if (glewExperimental || GLEW_NV_primitive_restart) CONST_CAST(GLEW_NV_primitive_restart) = !_glewInit_GL_NV_primitive_restart(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_NV_primitive_restart */
+#ifdef GL_NV_register_combiners
+ CONST_CAST(GLEW_NV_register_combiners) = _glewSearchExtension("GL_NV_register_combiners", extStart, extEnd);
+ if (glewExperimental || GLEW_NV_register_combiners) CONST_CAST(GLEW_NV_register_combiners) = !_glewInit_GL_NV_register_combiners(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_NV_register_combiners */
+#ifdef GL_NV_register_combiners2
+ CONST_CAST(GLEW_NV_register_combiners2) = _glewSearchExtension("GL_NV_register_combiners2", extStart, extEnd);
+ if (glewExperimental || GLEW_NV_register_combiners2) CONST_CAST(GLEW_NV_register_combiners2) = !_glewInit_GL_NV_register_combiners2(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_NV_register_combiners2 */
+#ifdef GL_NV_shader_atomic_counters
+ CONST_CAST(GLEW_NV_shader_atomic_counters) = _glewSearchExtension("GL_NV_shader_atomic_counters", extStart, extEnd);
+#endif /* GL_NV_shader_atomic_counters */
+#ifdef GL_NV_shader_atomic_float
+ CONST_CAST(GLEW_NV_shader_atomic_float) = _glewSearchExtension("GL_NV_shader_atomic_float", extStart, extEnd);
+#endif /* GL_NV_shader_atomic_float */
+#ifdef GL_NV_shader_buffer_load
+ CONST_CAST(GLEW_NV_shader_buffer_load) = _glewSearchExtension("GL_NV_shader_buffer_load", extStart, extEnd);
+ if (glewExperimental || GLEW_NV_shader_buffer_load) CONST_CAST(GLEW_NV_shader_buffer_load) = !_glewInit_GL_NV_shader_buffer_load(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_NV_shader_buffer_load */
+#ifdef GL_NV_shader_storage_buffer_object
+ CONST_CAST(GLEW_NV_shader_storage_buffer_object) = _glewSearchExtension("GL_NV_shader_storage_buffer_object", extStart, extEnd);
+#endif /* GL_NV_shader_storage_buffer_object */
+#ifdef GL_NV_tessellation_program5
+ CONST_CAST(GLEW_NV_tessellation_program5) = _glewSearchExtension("GL_NV_gpu_program5", extStart, extEnd);
+#endif /* GL_NV_tessellation_program5 */
+#ifdef GL_NV_texgen_emboss
+ CONST_CAST(GLEW_NV_texgen_emboss) = _glewSearchExtension("GL_NV_texgen_emboss", extStart, extEnd);
+#endif /* GL_NV_texgen_emboss */
+#ifdef GL_NV_texgen_reflection
+ CONST_CAST(GLEW_NV_texgen_reflection) = _glewSearchExtension("GL_NV_texgen_reflection", extStart, extEnd);
+#endif /* GL_NV_texgen_reflection */
+#ifdef GL_NV_texture_barrier
+ CONST_CAST(GLEW_NV_texture_barrier) = _glewSearchExtension("GL_NV_texture_barrier", extStart, extEnd);
+ if (glewExperimental || GLEW_NV_texture_barrier) CONST_CAST(GLEW_NV_texture_barrier) = !_glewInit_GL_NV_texture_barrier(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_NV_texture_barrier */
+#ifdef GL_NV_texture_compression_vtc
+ CONST_CAST(GLEW_NV_texture_compression_vtc) = _glewSearchExtension("GL_NV_texture_compression_vtc", extStart, extEnd);
+#endif /* GL_NV_texture_compression_vtc */
+#ifdef GL_NV_texture_env_combine4
+ CONST_CAST(GLEW_NV_texture_env_combine4) = _glewSearchExtension("GL_NV_texture_env_combine4", extStart, extEnd);
+#endif /* GL_NV_texture_env_combine4 */
+#ifdef GL_NV_texture_expand_normal
+ CONST_CAST(GLEW_NV_texture_expand_normal) = _glewSearchExtension("GL_NV_texture_expand_normal", extStart, extEnd);
+#endif /* GL_NV_texture_expand_normal */
+#ifdef GL_NV_texture_multisample
+ CONST_CAST(GLEW_NV_texture_multisample) = _glewSearchExtension("GL_NV_texture_multisample", extStart, extEnd);
+ if (glewExperimental || GLEW_NV_texture_multisample) CONST_CAST(GLEW_NV_texture_multisample) = !_glewInit_GL_NV_texture_multisample(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_NV_texture_multisample */
+#ifdef GL_NV_texture_rectangle
+ CONST_CAST(GLEW_NV_texture_rectangle) = _glewSearchExtension("GL_NV_texture_rectangle", extStart, extEnd);
+#endif /* GL_NV_texture_rectangle */
+#ifdef GL_NV_texture_shader
+ CONST_CAST(GLEW_NV_texture_shader) = _glewSearchExtension("GL_NV_texture_shader", extStart, extEnd);
+#endif /* GL_NV_texture_shader */
+#ifdef GL_NV_texture_shader2
+ CONST_CAST(GLEW_NV_texture_shader2) = _glewSearchExtension("GL_NV_texture_shader2", extStart, extEnd);
+#endif /* GL_NV_texture_shader2 */
+#ifdef GL_NV_texture_shader3
+ CONST_CAST(GLEW_NV_texture_shader3) = _glewSearchExtension("GL_NV_texture_shader3", extStart, extEnd);
+#endif /* GL_NV_texture_shader3 */
+#ifdef GL_NV_transform_feedback
+ CONST_CAST(GLEW_NV_transform_feedback) = _glewSearchExtension("GL_NV_transform_feedback", extStart, extEnd);
+ if (glewExperimental || GLEW_NV_transform_feedback) CONST_CAST(GLEW_NV_transform_feedback) = !_glewInit_GL_NV_transform_feedback(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_NV_transform_feedback */
+#ifdef GL_NV_transform_feedback2
+ CONST_CAST(GLEW_NV_transform_feedback2) = _glewSearchExtension("GL_NV_transform_feedback2", extStart, extEnd);
+ if (glewExperimental || GLEW_NV_transform_feedback2) CONST_CAST(GLEW_NV_transform_feedback2) = !_glewInit_GL_NV_transform_feedback2(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_NV_transform_feedback2 */
+#ifdef GL_NV_vdpau_interop
+ CONST_CAST(GLEW_NV_vdpau_interop) = _glewSearchExtension("GL_NV_vdpau_interop", extStart, extEnd);
+ if (glewExperimental || GLEW_NV_vdpau_interop) CONST_CAST(GLEW_NV_vdpau_interop) = !_glewInit_GL_NV_vdpau_interop(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_NV_vdpau_interop */
+#ifdef GL_NV_vertex_array_range
+ CONST_CAST(GLEW_NV_vertex_array_range) = _glewSearchExtension("GL_NV_vertex_array_range", extStart, extEnd);
+ if (glewExperimental || GLEW_NV_vertex_array_range) CONST_CAST(GLEW_NV_vertex_array_range) = !_glewInit_GL_NV_vertex_array_range(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_NV_vertex_array_range */
+#ifdef GL_NV_vertex_array_range2
+ CONST_CAST(GLEW_NV_vertex_array_range2) = _glewSearchExtension("GL_NV_vertex_array_range2", extStart, extEnd);
+#endif /* GL_NV_vertex_array_range2 */
+#ifdef GL_NV_vertex_attrib_integer_64bit
+ CONST_CAST(GLEW_NV_vertex_attrib_integer_64bit) = _glewSearchExtension("GL_NV_vertex_attrib_integer_64bit", extStart, extEnd);
+ if (glewExperimental || GLEW_NV_vertex_attrib_integer_64bit) CONST_CAST(GLEW_NV_vertex_attrib_integer_64bit) = !_glewInit_GL_NV_vertex_attrib_integer_64bit(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_NV_vertex_attrib_integer_64bit */
+#ifdef GL_NV_vertex_buffer_unified_memory
+ CONST_CAST(GLEW_NV_vertex_buffer_unified_memory) = _glewSearchExtension("GL_NV_vertex_buffer_unified_memory", extStart, extEnd);
+ if (glewExperimental || GLEW_NV_vertex_buffer_unified_memory) CONST_CAST(GLEW_NV_vertex_buffer_unified_memory) = !_glewInit_GL_NV_vertex_buffer_unified_memory(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_NV_vertex_buffer_unified_memory */
+#ifdef GL_NV_vertex_program
+ CONST_CAST(GLEW_NV_vertex_program) = _glewSearchExtension("GL_NV_vertex_program", extStart, extEnd);
+ if (glewExperimental || GLEW_NV_vertex_program) CONST_CAST(GLEW_NV_vertex_program) = !_glewInit_GL_NV_vertex_program(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_NV_vertex_program */
+#ifdef GL_NV_vertex_program1_1
+ CONST_CAST(GLEW_NV_vertex_program1_1) = _glewSearchExtension("GL_NV_vertex_program1_1", extStart, extEnd);
+#endif /* GL_NV_vertex_program1_1 */
+#ifdef GL_NV_vertex_program2
+ CONST_CAST(GLEW_NV_vertex_program2) = _glewSearchExtension("GL_NV_vertex_program2", extStart, extEnd);
+#endif /* GL_NV_vertex_program2 */
+#ifdef GL_NV_vertex_program2_option
+ CONST_CAST(GLEW_NV_vertex_program2_option) = _glewSearchExtension("GL_NV_vertex_program2_option", extStart, extEnd);
+#endif /* GL_NV_vertex_program2_option */
+#ifdef GL_NV_vertex_program3
+ CONST_CAST(GLEW_NV_vertex_program3) = _glewSearchExtension("GL_NV_vertex_program3", extStart, extEnd);
+#endif /* GL_NV_vertex_program3 */
+#ifdef GL_NV_vertex_program4
+ CONST_CAST(GLEW_NV_vertex_program4) = _glewSearchExtension("GL_NV_gpu_program4", extStart, extEnd);
+#endif /* GL_NV_vertex_program4 */
+#ifdef GL_NV_video_capture
+ CONST_CAST(GLEW_NV_video_capture) = _glewSearchExtension("GL_NV_video_capture", extStart, extEnd);
+ if (glewExperimental || GLEW_NV_video_capture) CONST_CAST(GLEW_NV_video_capture) = !_glewInit_GL_NV_video_capture(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_NV_video_capture */
+#ifdef GL_OES_byte_coordinates
+ CONST_CAST(GLEW_OES_byte_coordinates) = _glewSearchExtension("GL_OES_byte_coordinates", extStart, extEnd);
+#endif /* GL_OES_byte_coordinates */
+#ifdef GL_OES_compressed_paletted_texture
+ CONST_CAST(GLEW_OES_compressed_paletted_texture) = _glewSearchExtension("GL_OES_compressed_paletted_texture", extStart, extEnd);
+#endif /* GL_OES_compressed_paletted_texture */
+#ifdef GL_OES_read_format
+ CONST_CAST(GLEW_OES_read_format) = _glewSearchExtension("GL_OES_read_format", extStart, extEnd);
+#endif /* GL_OES_read_format */
+#ifdef GL_OES_single_precision
+ CONST_CAST(GLEW_OES_single_precision) = _glewSearchExtension("GL_OES_single_precision", extStart, extEnd);
+ if (glewExperimental || GLEW_OES_single_precision) CONST_CAST(GLEW_OES_single_precision) = !_glewInit_GL_OES_single_precision(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_OES_single_precision */
+#ifdef GL_OML_interlace
+ CONST_CAST(GLEW_OML_interlace) = _glewSearchExtension("GL_OML_interlace", extStart, extEnd);
+#endif /* GL_OML_interlace */
+#ifdef GL_OML_resample
+ CONST_CAST(GLEW_OML_resample) = _glewSearchExtension("GL_OML_resample", extStart, extEnd);
+#endif /* GL_OML_resample */
+#ifdef GL_OML_subsample
+ CONST_CAST(GLEW_OML_subsample) = _glewSearchExtension("GL_OML_subsample", extStart, extEnd);
+#endif /* GL_OML_subsample */
+#ifdef GL_PGI_misc_hints
+ CONST_CAST(GLEW_PGI_misc_hints) = _glewSearchExtension("GL_PGI_misc_hints", extStart, extEnd);
+#endif /* GL_PGI_misc_hints */
+#ifdef GL_PGI_vertex_hints
+ CONST_CAST(GLEW_PGI_vertex_hints) = _glewSearchExtension("GL_PGI_vertex_hints", extStart, extEnd);
+#endif /* GL_PGI_vertex_hints */
+#ifdef GL_REND_screen_coordinates
+ CONST_CAST(GLEW_REND_screen_coordinates) = _glewSearchExtension("GL_REND_screen_coordinates", extStart, extEnd);
+#endif /* GL_REND_screen_coordinates */
+#ifdef GL_S3_s3tc
+ CONST_CAST(GLEW_S3_s3tc) = _glewSearchExtension("GL_S3_s3tc", extStart, extEnd);
+#endif /* GL_S3_s3tc */
+#ifdef GL_SGIS_color_range
+ CONST_CAST(GLEW_SGIS_color_range) = _glewSearchExtension("GL_SGIS_color_range", extStart, extEnd);
+#endif /* GL_SGIS_color_range */
+#ifdef GL_SGIS_detail_texture
+ CONST_CAST(GLEW_SGIS_detail_texture) = _glewSearchExtension("GL_SGIS_detail_texture", extStart, extEnd);
+ if (glewExperimental || GLEW_SGIS_detail_texture) CONST_CAST(GLEW_SGIS_detail_texture) = !_glewInit_GL_SGIS_detail_texture(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_SGIS_detail_texture */
+#ifdef GL_SGIS_fog_function
+ CONST_CAST(GLEW_SGIS_fog_function) = _glewSearchExtension("GL_SGIS_fog_function", extStart, extEnd);
+ if (glewExperimental || GLEW_SGIS_fog_function) CONST_CAST(GLEW_SGIS_fog_function) = !_glewInit_GL_SGIS_fog_function(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_SGIS_fog_function */
+#ifdef GL_SGIS_generate_mipmap
+ CONST_CAST(GLEW_SGIS_generate_mipmap) = _glewSearchExtension("GL_SGIS_generate_mipmap", extStart, extEnd);
+#endif /* GL_SGIS_generate_mipmap */
+#ifdef GL_SGIS_multisample
+ CONST_CAST(GLEW_SGIS_multisample) = _glewSearchExtension("GL_SGIS_multisample", extStart, extEnd);
+ if (glewExperimental || GLEW_SGIS_multisample) CONST_CAST(GLEW_SGIS_multisample) = !_glewInit_GL_SGIS_multisample(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_SGIS_multisample */
+#ifdef GL_SGIS_pixel_texture
+ CONST_CAST(GLEW_SGIS_pixel_texture) = _glewSearchExtension("GL_SGIS_pixel_texture", extStart, extEnd);
+#endif /* GL_SGIS_pixel_texture */
+#ifdef GL_SGIS_point_line_texgen
+ CONST_CAST(GLEW_SGIS_point_line_texgen) = _glewSearchExtension("GL_SGIS_point_line_texgen", extStart, extEnd);
+#endif /* GL_SGIS_point_line_texgen */
+#ifdef GL_SGIS_sharpen_texture
+ CONST_CAST(GLEW_SGIS_sharpen_texture) = _glewSearchExtension("GL_SGIS_sharpen_texture", extStart, extEnd);
+ if (glewExperimental || GLEW_SGIS_sharpen_texture) CONST_CAST(GLEW_SGIS_sharpen_texture) = !_glewInit_GL_SGIS_sharpen_texture(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_SGIS_sharpen_texture */
+#ifdef GL_SGIS_texture4D
+ CONST_CAST(GLEW_SGIS_texture4D) = _glewSearchExtension("GL_SGIS_texture4D", extStart, extEnd);
+ if (glewExperimental || GLEW_SGIS_texture4D) CONST_CAST(GLEW_SGIS_texture4D) = !_glewInit_GL_SGIS_texture4D(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_SGIS_texture4D */
+#ifdef GL_SGIS_texture_border_clamp
+ CONST_CAST(GLEW_SGIS_texture_border_clamp) = _glewSearchExtension("GL_SGIS_texture_border_clamp", extStart, extEnd);
+#endif /* GL_SGIS_texture_border_clamp */
+#ifdef GL_SGIS_texture_edge_clamp
+ CONST_CAST(GLEW_SGIS_texture_edge_clamp) = _glewSearchExtension("GL_SGIS_texture_edge_clamp", extStart, extEnd);
+#endif /* GL_SGIS_texture_edge_clamp */
+#ifdef GL_SGIS_texture_filter4
+ CONST_CAST(GLEW_SGIS_texture_filter4) = _glewSearchExtension("GL_SGIS_texture_filter4", extStart, extEnd);
+ if (glewExperimental || GLEW_SGIS_texture_filter4) CONST_CAST(GLEW_SGIS_texture_filter4) = !_glewInit_GL_SGIS_texture_filter4(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_SGIS_texture_filter4 */
+#ifdef GL_SGIS_texture_lod
+ CONST_CAST(GLEW_SGIS_texture_lod) = _glewSearchExtension("GL_SGIS_texture_lod", extStart, extEnd);
+#endif /* GL_SGIS_texture_lod */
+#ifdef GL_SGIS_texture_select
+ CONST_CAST(GLEW_SGIS_texture_select) = _glewSearchExtension("GL_SGIS_texture_select", extStart, extEnd);
+#endif /* GL_SGIS_texture_select */
+#ifdef GL_SGIX_async
+ CONST_CAST(GLEW_SGIX_async) = _glewSearchExtension("GL_SGIX_async", extStart, extEnd);
+ if (glewExperimental || GLEW_SGIX_async) CONST_CAST(GLEW_SGIX_async) = !_glewInit_GL_SGIX_async(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_SGIX_async */
+#ifdef GL_SGIX_async_histogram
+ CONST_CAST(GLEW_SGIX_async_histogram) = _glewSearchExtension("GL_SGIX_async_histogram", extStart, extEnd);
+#endif /* GL_SGIX_async_histogram */
+#ifdef GL_SGIX_async_pixel
+ CONST_CAST(GLEW_SGIX_async_pixel) = _glewSearchExtension("GL_SGIX_async_pixel", extStart, extEnd);
+#endif /* GL_SGIX_async_pixel */
+#ifdef GL_SGIX_blend_alpha_minmax
+ CONST_CAST(GLEW_SGIX_blend_alpha_minmax) = _glewSearchExtension("GL_SGIX_blend_alpha_minmax", extStart, extEnd);
+#endif /* GL_SGIX_blend_alpha_minmax */
+#ifdef GL_SGIX_clipmap
+ CONST_CAST(GLEW_SGIX_clipmap) = _glewSearchExtension("GL_SGIX_clipmap", extStart, extEnd);
+#endif /* GL_SGIX_clipmap */
+#ifdef GL_SGIX_convolution_accuracy
+ CONST_CAST(GLEW_SGIX_convolution_accuracy) = _glewSearchExtension("GL_SGIX_convolution_accuracy", extStart, extEnd);
+#endif /* GL_SGIX_convolution_accuracy */
+#ifdef GL_SGIX_depth_texture
+ CONST_CAST(GLEW_SGIX_depth_texture) = _glewSearchExtension("GL_SGIX_depth_texture", extStart, extEnd);
+#endif /* GL_SGIX_depth_texture */
+#ifdef GL_SGIX_flush_raster
+ CONST_CAST(GLEW_SGIX_flush_raster) = _glewSearchExtension("GL_SGIX_flush_raster", extStart, extEnd);
+ if (glewExperimental || GLEW_SGIX_flush_raster) CONST_CAST(GLEW_SGIX_flush_raster) = !_glewInit_GL_SGIX_flush_raster(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_SGIX_flush_raster */
+#ifdef GL_SGIX_fog_offset
+ CONST_CAST(GLEW_SGIX_fog_offset) = _glewSearchExtension("GL_SGIX_fog_offset", extStart, extEnd);
+#endif /* GL_SGIX_fog_offset */
+#ifdef GL_SGIX_fog_texture
+ CONST_CAST(GLEW_SGIX_fog_texture) = _glewSearchExtension("GL_SGIX_fog_texture", extStart, extEnd);
+ if (glewExperimental || GLEW_SGIX_fog_texture) CONST_CAST(GLEW_SGIX_fog_texture) = !_glewInit_GL_SGIX_fog_texture(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_SGIX_fog_texture */
+#ifdef GL_SGIX_fragment_specular_lighting
+ CONST_CAST(GLEW_SGIX_fragment_specular_lighting) = _glewSearchExtension("GL_SGIX_fragment_specular_lighting", extStart, extEnd);
+ if (glewExperimental || GLEW_SGIX_fragment_specular_lighting) CONST_CAST(GLEW_SGIX_fragment_specular_lighting) = !_glewInit_GL_SGIX_fragment_specular_lighting(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_SGIX_fragment_specular_lighting */
+#ifdef GL_SGIX_framezoom
+ CONST_CAST(GLEW_SGIX_framezoom) = _glewSearchExtension("GL_SGIX_framezoom", extStart, extEnd);
+ if (glewExperimental || GLEW_SGIX_framezoom) CONST_CAST(GLEW_SGIX_framezoom) = !_glewInit_GL_SGIX_framezoom(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_SGIX_framezoom */
+#ifdef GL_SGIX_interlace
+ CONST_CAST(GLEW_SGIX_interlace) = _glewSearchExtension("GL_SGIX_interlace", extStart, extEnd);
+#endif /* GL_SGIX_interlace */
+#ifdef GL_SGIX_ir_instrument1
+ CONST_CAST(GLEW_SGIX_ir_instrument1) = _glewSearchExtension("GL_SGIX_ir_instrument1", extStart, extEnd);
+#endif /* GL_SGIX_ir_instrument1 */
+#ifdef GL_SGIX_list_priority
+ CONST_CAST(GLEW_SGIX_list_priority) = _glewSearchExtension("GL_SGIX_list_priority", extStart, extEnd);
+#endif /* GL_SGIX_list_priority */
+#ifdef GL_SGIX_pixel_texture
+ CONST_CAST(GLEW_SGIX_pixel_texture) = _glewSearchExtension("GL_SGIX_pixel_texture", extStart, extEnd);
+ if (glewExperimental || GLEW_SGIX_pixel_texture) CONST_CAST(GLEW_SGIX_pixel_texture) = !_glewInit_GL_SGIX_pixel_texture(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_SGIX_pixel_texture */
+#ifdef GL_SGIX_pixel_texture_bits
+ CONST_CAST(GLEW_SGIX_pixel_texture_bits) = _glewSearchExtension("GL_SGIX_pixel_texture_bits", extStart, extEnd);
+#endif /* GL_SGIX_pixel_texture_bits */
+#ifdef GL_SGIX_reference_plane
+ CONST_CAST(GLEW_SGIX_reference_plane) = _glewSearchExtension("GL_SGIX_reference_plane", extStart, extEnd);
+ if (glewExperimental || GLEW_SGIX_reference_plane) CONST_CAST(GLEW_SGIX_reference_plane) = !_glewInit_GL_SGIX_reference_plane(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_SGIX_reference_plane */
+#ifdef GL_SGIX_resample
+ CONST_CAST(GLEW_SGIX_resample) = _glewSearchExtension("GL_SGIX_resample", extStart, extEnd);
+#endif /* GL_SGIX_resample */
+#ifdef GL_SGIX_shadow
+ CONST_CAST(GLEW_SGIX_shadow) = _glewSearchExtension("GL_SGIX_shadow", extStart, extEnd);
+#endif /* GL_SGIX_shadow */
+#ifdef GL_SGIX_shadow_ambient
+ CONST_CAST(GLEW_SGIX_shadow_ambient) = _glewSearchExtension("GL_SGIX_shadow_ambient", extStart, extEnd);
+#endif /* GL_SGIX_shadow_ambient */
+#ifdef GL_SGIX_sprite
+ CONST_CAST(GLEW_SGIX_sprite) = _glewSearchExtension("GL_SGIX_sprite", extStart, extEnd);
+ if (glewExperimental || GLEW_SGIX_sprite) CONST_CAST(GLEW_SGIX_sprite) = !_glewInit_GL_SGIX_sprite(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_SGIX_sprite */
+#ifdef GL_SGIX_tag_sample_buffer
+ CONST_CAST(GLEW_SGIX_tag_sample_buffer) = _glewSearchExtension("GL_SGIX_tag_sample_buffer", extStart, extEnd);
+ if (glewExperimental || GLEW_SGIX_tag_sample_buffer) CONST_CAST(GLEW_SGIX_tag_sample_buffer) = !_glewInit_GL_SGIX_tag_sample_buffer(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_SGIX_tag_sample_buffer */
+#ifdef GL_SGIX_texture_add_env
+ CONST_CAST(GLEW_SGIX_texture_add_env) = _glewSearchExtension("GL_SGIX_texture_add_env", extStart, extEnd);
+#endif /* GL_SGIX_texture_add_env */
+#ifdef GL_SGIX_texture_coordinate_clamp
+ CONST_CAST(GLEW_SGIX_texture_coordinate_clamp) = _glewSearchExtension("GL_SGIX_texture_coordinate_clamp", extStart, extEnd);
+#endif /* GL_SGIX_texture_coordinate_clamp */
+#ifdef GL_SGIX_texture_lod_bias
+ CONST_CAST(GLEW_SGIX_texture_lod_bias) = _glewSearchExtension("GL_SGIX_texture_lod_bias", extStart, extEnd);
+#endif /* GL_SGIX_texture_lod_bias */
+#ifdef GL_SGIX_texture_multi_buffer
+ CONST_CAST(GLEW_SGIX_texture_multi_buffer) = _glewSearchExtension("GL_SGIX_texture_multi_buffer", extStart, extEnd);
+#endif /* GL_SGIX_texture_multi_buffer */
+#ifdef GL_SGIX_texture_range
+ CONST_CAST(GLEW_SGIX_texture_range) = _glewSearchExtension("GL_SGIX_texture_range", extStart, extEnd);
+#endif /* GL_SGIX_texture_range */
+#ifdef GL_SGIX_texture_scale_bias
+ CONST_CAST(GLEW_SGIX_texture_scale_bias) = _glewSearchExtension("GL_SGIX_texture_scale_bias", extStart, extEnd);
+#endif /* GL_SGIX_texture_scale_bias */
+#ifdef GL_SGIX_vertex_preclip
+ CONST_CAST(GLEW_SGIX_vertex_preclip) = _glewSearchExtension("GL_SGIX_vertex_preclip", extStart, extEnd);
+#endif /* GL_SGIX_vertex_preclip */
+#ifdef GL_SGIX_vertex_preclip_hint
+ CONST_CAST(GLEW_SGIX_vertex_preclip_hint) = _glewSearchExtension("GL_SGIX_vertex_preclip_hint", extStart, extEnd);
+#endif /* GL_SGIX_vertex_preclip_hint */
+#ifdef GL_SGIX_ycrcb
+ CONST_CAST(GLEW_SGIX_ycrcb) = _glewSearchExtension("GL_SGIX_ycrcb", extStart, extEnd);
+#endif /* GL_SGIX_ycrcb */
+#ifdef GL_SGI_color_matrix
+ CONST_CAST(GLEW_SGI_color_matrix) = _glewSearchExtension("GL_SGI_color_matrix", extStart, extEnd);
+#endif /* GL_SGI_color_matrix */
+#ifdef GL_SGI_color_table
+ CONST_CAST(GLEW_SGI_color_table) = _glewSearchExtension("GL_SGI_color_table", extStart, extEnd);
+ if (glewExperimental || GLEW_SGI_color_table) CONST_CAST(GLEW_SGI_color_table) = !_glewInit_GL_SGI_color_table(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_SGI_color_table */
+#ifdef GL_SGI_texture_color_table
+ CONST_CAST(GLEW_SGI_texture_color_table) = _glewSearchExtension("GL_SGI_texture_color_table", extStart, extEnd);
+#endif /* GL_SGI_texture_color_table */
+#ifdef GL_SUNX_constant_data
+ CONST_CAST(GLEW_SUNX_constant_data) = _glewSearchExtension("GL_SUNX_constant_data", extStart, extEnd);
+ if (glewExperimental || GLEW_SUNX_constant_data) CONST_CAST(GLEW_SUNX_constant_data) = !_glewInit_GL_SUNX_constant_data(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_SUNX_constant_data */
+#ifdef GL_SUN_convolution_border_modes
+ CONST_CAST(GLEW_SUN_convolution_border_modes) = _glewSearchExtension("GL_SUN_convolution_border_modes", extStart, extEnd);
+#endif /* GL_SUN_convolution_border_modes */
+#ifdef GL_SUN_global_alpha
+ CONST_CAST(GLEW_SUN_global_alpha) = _glewSearchExtension("GL_SUN_global_alpha", extStart, extEnd);
+ if (glewExperimental || GLEW_SUN_global_alpha) CONST_CAST(GLEW_SUN_global_alpha) = !_glewInit_GL_SUN_global_alpha(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_SUN_global_alpha */
+#ifdef GL_SUN_mesh_array
+ CONST_CAST(GLEW_SUN_mesh_array) = _glewSearchExtension("GL_SUN_mesh_array", extStart, extEnd);
+#endif /* GL_SUN_mesh_array */
+#ifdef GL_SUN_read_video_pixels
+ CONST_CAST(GLEW_SUN_read_video_pixels) = _glewSearchExtension("GL_SUN_read_video_pixels", extStart, extEnd);
+ if (glewExperimental || GLEW_SUN_read_video_pixels) CONST_CAST(GLEW_SUN_read_video_pixels) = !_glewInit_GL_SUN_read_video_pixels(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_SUN_read_video_pixels */
+#ifdef GL_SUN_slice_accum
+ CONST_CAST(GLEW_SUN_slice_accum) = _glewSearchExtension("GL_SUN_slice_accum", extStart, extEnd);
+#endif /* GL_SUN_slice_accum */
+#ifdef GL_SUN_triangle_list
+ CONST_CAST(GLEW_SUN_triangle_list) = _glewSearchExtension("GL_SUN_triangle_list", extStart, extEnd);
+ if (glewExperimental || GLEW_SUN_triangle_list) CONST_CAST(GLEW_SUN_triangle_list) = !_glewInit_GL_SUN_triangle_list(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_SUN_triangle_list */
+#ifdef GL_SUN_vertex
+ CONST_CAST(GLEW_SUN_vertex) = _glewSearchExtension("GL_SUN_vertex", extStart, extEnd);
+ if (glewExperimental || GLEW_SUN_vertex) CONST_CAST(GLEW_SUN_vertex) = !_glewInit_GL_SUN_vertex(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_SUN_vertex */
+#ifdef GL_WIN_phong_shading
+ CONST_CAST(GLEW_WIN_phong_shading) = _glewSearchExtension("GL_WIN_phong_shading", extStart, extEnd);
+#endif /* GL_WIN_phong_shading */
+#ifdef GL_WIN_specular_fog
+ CONST_CAST(GLEW_WIN_specular_fog) = _glewSearchExtension("GL_WIN_specular_fog", extStart, extEnd);
+#endif /* GL_WIN_specular_fog */
+#ifdef GL_WIN_swap_hint
+ CONST_CAST(GLEW_WIN_swap_hint) = _glewSearchExtension("GL_WIN_swap_hint", extStart, extEnd);
+ if (glewExperimental || GLEW_WIN_swap_hint) CONST_CAST(GLEW_WIN_swap_hint) = !_glewInit_GL_WIN_swap_hint(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_WIN_swap_hint */
+#if GL_ES_VERSION_1_0 // NOTE jwilkins: should be 'if' not 'ifdef'
+ if (glewExperimental || GLEW_ES_VERSION_1_0) CONST_CAST(GLEW_ES_VERSION_1_0) = !_glewInit_GL_ES_VERSION_1_0(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_ES_VERSION_1_0 */
+#if GL_ES_VERSION_CL_1_1 // NOTE jwilkins: should be 'if' not 'ifdef'
+ if (glewExperimental || GLEW_ES_VERSION_CL_1_1) CONST_CAST(GLEW_ES_VERSION_CL_1_1) = !_glewInit_GL_ES_VERSION_CL_1_1(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_ES_VERSION_CL_1_1 */
+#if GL_ES_VERSION_CM_1_1 // NOTE jwilkins: should be 'if' not 'ifdef'
+ if (glewExperimental || GLEW_ES_VERSION_CM_1_1) CONST_CAST(GLEW_ES_VERSION_CM_1_1) = !_glewInit_GL_ES_VERSION_CM_1_1(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_ES_VERSION_CM_1_1 */
+#ifdef GL_ES_VERSION_2_0
+ if (glewExperimental || GLEW_ES_VERSION_2_0) CONST_CAST(GLEW_ES_VERSION_2_0) = !_glewInit_GL_ES_VERSION_2_0(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_ES_VERSION_2_0 */
+#ifdef GL_AMD_compressed_3DC_texture
+ CONST_CAST(GLEW_AMD_compressed_3DC_texture) = _glewSearchExtension("GL_AMD_compressed_3DC_texture", extStart, extEnd);
+#endif /* GL_AMD_compressed_3DC_texture */
+#ifdef GL_AMD_compressed_ATC_texture
+ CONST_CAST(GLEW_AMD_compressed_ATC_texture) = _glewSearchExtension("GL_AMD_compressed_ATC_texture", extStart, extEnd);
+#endif /* GL_AMD_compressed_ATC_texture */
+#ifdef GL_AMD_program_binary_Z400
+ CONST_CAST(GLEW_AMD_program_binary_Z400) = _glewSearchExtension("GL_AMD_program_binary_Z400", extStart, extEnd);
+#endif /* GL_AMD_program_binary_Z400 */
+#ifdef GL_ANGLE_framebuffer_blit
+ CONST_CAST(GLEW_ANGLE_framebuffer_blit) = _glewSearchExtension("GL_ANGLE_framebuffer_blit", extStart, extEnd);
+ if (glewExperimental || GLEW_ANGLE_framebuffer_blit) CONST_CAST(GLEW_ANGLE_framebuffer_blit) = !_glewInit_GL_ANGLE_framebuffer_blit(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_ANGLE_framebuffer_blit */
+#ifdef GL_ANGLE_framebuffer_multisample
+ CONST_CAST(GLEW_ANGLE_framebuffer_multisample) = _glewSearchExtension("GL_ANGLE_framebuffer_multisample", extStart, extEnd);
+ if (glewExperimental || GLEW_ANGLE_framebuffer_multisample) CONST_CAST(GLEW_ANGLE_framebuffer_multisample) = !_glewInit_GL_ANGLE_framebuffer_multisample(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_ANGLE_framebuffer_multisample */
+#ifdef GL_ANGLE_instanced_arrays
+ CONST_CAST(GLEW_ANGLE_instanced_arrays) = _glewSearchExtension("GL_ANGLE_instanced_arrays", extStart, extEnd);
+ if (glewExperimental || GLEW_ANGLE_instanced_arrays) CONST_CAST(GLEW_ANGLE_instanced_arrays) = !_glewInit_GL_ANGLE_instanced_arrays(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_ANGLE_instanced_arrays */
+#ifdef GL_ANGLE_pack_reverse_row_order
+ CONST_CAST(GLEW_ANGLE_pack_reverse_row_order) = _glewSearchExtension("GL_ANGLE_pack_reverse_row_order", extStart, extEnd);
+#endif /* GL_ANGLE_pack_reverse_row_order */
+#ifdef GL_ANGLE_texture_compression_dxt3
+ CONST_CAST(GLEW_ANGLE_texture_compression_dxt3) = _glewSearchExtension("GL_ANGLE_texture_compression_dxt3", extStart, extEnd);
+#endif /* GL_ANGLE_texture_compression_dxt3 */
+#ifdef GL_ANGLE_texture_compression_dxt5
+ CONST_CAST(GLEW_ANGLE_texture_compression_dxt5) = _glewSearchExtension("GL_ANGLE_texture_compression_dxt5", extStart, extEnd);
+#endif /* GL_ANGLE_texture_compression_dxt5 */
+#ifdef GL_ANGLE_texture_usage
+ CONST_CAST(GLEW_ANGLE_texture_usage) = _glewSearchExtension("GL_ANGLE_texture_usage", extStart, extEnd);
+#endif /* GL_ANGLE_texture_usage */
+#ifdef GL_ANGLE_translated_shader_source
+ CONST_CAST(GLEW_ANGLE_translated_shader_source) = _glewSearchExtension("GL_ANGLE_translated_shader_source", extStart, extEnd);
+ if (glewExperimental || GLEW_ANGLE_translated_shader_source) CONST_CAST(GLEW_ANGLE_translated_shader_source) = !_glewInit_GL_ANGLE_translated_shader_source(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_ANGLE_translated_shader_source */
+#ifdef GL_APPLE_copy_texture_levels
+ CONST_CAST(GLEW_APPLE_copy_texture_levels) = _glewSearchExtension("GL_APPLE_copy_texture_levels", extStart, extEnd);
+ if (glewExperimental || GLEW_APPLE_copy_texture_levels) CONST_CAST(GLEW_APPLE_copy_texture_levels) = !_glewInit_GL_APPLE_copy_texture_levels(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_APPLE_copy_texture_levels */
+#ifdef GL_APPLE_framebuffer_multisample
+ CONST_CAST(GLEW_APPLE_framebuffer_multisample) = _glewSearchExtension("GL_APPLE_framebuffer_multisample", extStart, extEnd);
+ if (glewExperimental || GLEW_APPLE_framebuffer_multisample) CONST_CAST(GLEW_APPLE_framebuffer_multisample) = !_glewInit_GL_APPLE_framebuffer_multisample(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_APPLE_framebuffer_multisample */
+#ifdef GL_APPLE_sync
+ CONST_CAST(GLEW_APPLE_sync) = _glewSearchExtension("GL_APPLE_sync", extStart, extEnd);
+ if (glewExperimental || GLEW_APPLE_sync) CONST_CAST(GLEW_APPLE_sync) = !_glewInit_GL_APPLE_sync(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_APPLE_sync */
+#ifdef GL_APPLE_texture_2D_limited_npot
+ CONST_CAST(GLEW_APPLE_texture_2D_limited_npot) = _glewSearchExtension("GL_APPLE_texture_2D_limited_npot", extStart, extEnd);
+#endif /* GL_APPLE_texture_2D_limited_npot */
+#ifdef GL_APPLE_texture_format_BGRA8888
+ CONST_CAST(GLEW_APPLE_texture_format_BGRA8888) = _glewSearchExtension("GL_APPLE_texture_format_BGRA8888", extStart, extEnd);
+#endif /* GL_APPLE_texture_format_BGRA8888 */
+#ifdef GL_APPLE_texture_max_level
+ CONST_CAST(GLEW_APPLE_texture_max_level) = _glewSearchExtension("GL_APPLE_texture_max_level", extStart, extEnd);
+#endif /* GL_APPLE_texture_max_level */
+#ifdef GL_ARM_mali_program_binary
+ CONST_CAST(GLEW_ARM_mali_program_binary) = _glewSearchExtension("GL_ARM_mali_program_binary", extStart, extEnd);
+#endif /* GL_ARM_mali_program_binary */
+#ifdef GL_ARM_mali_shader_binary
+ CONST_CAST(GLEW_ARM_mali_shader_binary) = _glewSearchExtension("GL_ARM_mali_shader_binary", extStart, extEnd);
+#endif /* GL_ARM_mali_shader_binary */
+#ifdef GL_ARM_rgba8
+ CONST_CAST(GLEW_ARM_rgba8) = _glewSearchExtension("GL_ARM_rgba8", extStart, extEnd);
+#endif /* GL_ARM_rgba8 */
+#ifdef GL_DMP_shader_binary
+ CONST_CAST(GLEW_DMP_shader_binary) = _glewSearchExtension("GL_DMP_shader_binary", extStart, extEnd);
+#endif /* GL_DMP_shader_binary */
+#ifdef GL_EXT_color_buffer_half_float
+ CONST_CAST(GLEW_EXT_color_buffer_half_float) = _glewSearchExtension("GL_EXT_color_buffer_half_float", extStart, extEnd);
+#endif /* GL_EXT_color_buffer_half_float */
+#ifdef GL_EXT_debug_label
+ CONST_CAST(GLEW_EXT_debug_label) = _glewSearchExtension("GL_EXT_debug_label", extStart, extEnd);
+ if (glewExperimental || GLEW_EXT_debug_label) CONST_CAST(GLEW_EXT_debug_label) = !_glewInit_GL_EXT_debug_label(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_EXT_debug_label */
+#ifdef GL_EXT_debug_marker
+ CONST_CAST(GLEW_EXT_debug_marker) = _glewSearchExtension("GL_EXT_debug_marker", extStart, extEnd);
+ if (glewExperimental || GLEW_EXT_debug_marker) CONST_CAST(GLEW_EXT_debug_marker) = !_glewInit_GL_EXT_debug_marker(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_EXT_debug_marker */
+#ifdef GL_EXT_discard_framebuffer
+ CONST_CAST(GLEW_EXT_discard_framebuffer) = _glewSearchExtension("GL_EXT_discard_framebuffer", extStart, extEnd);
+ if (glewExperimental || GLEW_EXT_discard_framebuffer) CONST_CAST(GLEW_EXT_discard_framebuffer) = !_glewInit_GL_EXT_discard_framebuffer(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_EXT_discard_framebuffer */
+#ifdef GL_EXT_frag_depth
+ CONST_CAST(GLEW_EXT_frag_depth) = _glewSearchExtension("GL_EXT_frag_depth", extStart, extEnd);
+#endif /* GL_EXT_frag_depth */
+#ifdef GL_EXT_map_buffer_range
+ CONST_CAST(GLEW_EXT_map_buffer_range) = _glewSearchExtension("GL_EXT_map_buffer_range", extStart, extEnd);
+ if (glewExperimental || GLEW_EXT_map_buffer_range) CONST_CAST(GLEW_EXT_map_buffer_range) = !_glewInit_GL_EXT_map_buffer_range(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_EXT_map_buffer_range */
+#ifdef GL_EXT_multisampled_render_to_texture
+ CONST_CAST(GLEW_EXT_multisampled_render_to_texture) = _glewSearchExtension("GL_EXT_multisampled_render_to_texture", extStart, extEnd);
+ if (glewExperimental || GLEW_EXT_multisampled_render_to_texture) CONST_CAST(GLEW_EXT_multisampled_render_to_texture) = !_glewInit_GL_EXT_multisampled_render_to_texture(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_EXT_multisampled_render_to_texture */
+#ifdef GL_EXT_multiview_draw_buffers
+ CONST_CAST(GLEW_EXT_multiview_draw_buffers) = _glewSearchExtension("GL_EXT_multiview_draw_buffers", extStart, extEnd);
+ if (glewExperimental || GLEW_EXT_multiview_draw_buffers) CONST_CAST(GLEW_EXT_multiview_draw_buffers) = !_glewInit_GL_EXT_multiview_draw_buffers(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_EXT_multiview_draw_buffers */
+#ifdef GL_EXT_occlusion_query_boolean
+ CONST_CAST(GLEW_EXT_occlusion_query_boolean) = _glewSearchExtension("GL_EXT_occlusion_query_boolean", extStart, extEnd);
+ if (glewExperimental || GLEW_EXT_occlusion_query_boolean) CONST_CAST(GLEW_EXT_occlusion_query_boolean) = !_glewInit_GL_EXT_occlusion_query_boolean(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_EXT_occlusion_query_boolean */
+#ifdef GL_EXT_read_format_bgra
+ CONST_CAST(GLEW_EXT_read_format_bgra) = _glewSearchExtension("GL_EXT_read_format_bgra", extStart, extEnd);
+#endif /* GL_EXT_read_format_bgra */
+#ifdef GL_EXT_robustness
+ CONST_CAST(GLEW_EXT_robustness) = _glewSearchExtension("GL_EXT_robustness", extStart, extEnd);
+ if (glewExperimental || GLEW_EXT_robustness) CONST_CAST(GLEW_EXT_robustness) = !_glewInit_GL_EXT_robustness(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_EXT_robustness */
+#ifdef GL_EXT_sRGB
+ CONST_CAST(GLEW_EXT_sRGB) = _glewSearchExtension("GL_EXT_sRGB", extStart, extEnd);
+#endif /* GL_EXT_sRGB */
+#ifdef GL_EXT_shader_framebuffer_fetch
+ CONST_CAST(GLEW_EXT_shader_framebuffer_fetch) = _glewSearchExtension("GL_EXT_shader_framebuffer_fetch", extStart, extEnd);
+#endif /* GL_EXT_shader_framebuffer_fetch */
+#ifdef GL_EXT_shader_texture_lod
+ CONST_CAST(GLEW_EXT_shader_texture_lod) = _glewSearchExtension("GL_EXT_shader_texture_lod", extStart, extEnd);
+#endif /* GL_EXT_shader_texture_lod */
+#ifdef GL_EXT_shadow_samplers
+ CONST_CAST(GLEW_EXT_shadow_samplers) = _glewSearchExtension("GL_EXT_shadow_samplers", extStart, extEnd);
+#endif /* GL_EXT_shadow_samplers */
+#ifdef GL_EXT_texture_format_BGRA8888
+ CONST_CAST(GLEW_EXT_texture_format_BGRA8888) = _glewSearchExtension("GL_EXT_texture_format_BGRA8888", extStart, extEnd);
+#endif /* GL_EXT_texture_format_BGRA8888 */
+#ifdef GL_EXT_texture_rg
+ CONST_CAST(GLEW_EXT_texture_rg) = _glewSearchExtension("GL_EXT_texture_rg", extStart, extEnd);
+#endif /* GL_EXT_texture_rg */
+#ifdef GL_EXT_texture_storage
+ CONST_CAST(GLEW_EXT_texture_storage) = _glewSearchExtension("GL_EXT_texture_storage", extStart, extEnd);
+ if (glewExperimental || GLEW_EXT_texture_storage) CONST_CAST(GLEW_EXT_texture_storage) = !_glewInit_GL_EXT_texture_storage(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_EXT_texture_storage */
+#ifdef GL_EXT_texture_type_2_10_10_10_REV
+ CONST_CAST(GLEW_EXT_texture_type_2_10_10_10_REV) = _glewSearchExtension("GL_EXT_texture_type_2_10_10_10_REV", extStart, extEnd);
+#endif /* GL_EXT_texture_type_2_10_10_10_REV */
+#ifdef GL_EXT_unpack_subimage
+ CONST_CAST(GLEW_EXT_unpack_subimage) = _glewSearchExtension("GL_EXT_unpack_subimage", extStart, extEnd);
+#endif /* GL_EXT_unpack_subimage */
+#ifdef GL_FJ_shader_binary_GCCSO
+ CONST_CAST(GLEW_FJ_shader_binary_GCCSO) = _glewSearchExtension("GL_FJ_shader_binary_GCCSO", extStart, extEnd);
+#endif /* GL_FJ_shader_binary_GCCSO */
+#ifdef GL_IMG_multisampled_render_to_texture
+ CONST_CAST(GLEW_IMG_multisampled_render_to_texture) = _glewSearchExtension("GL_IMG_multisampled_render_to_texture", extStart, extEnd);
+ if (glewExperimental || GLEW_IMG_multisampled_render_to_texture) CONST_CAST(GLEW_IMG_multisampled_render_to_texture) = !_glewInit_GL_IMG_multisampled_render_to_texture(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_IMG_multisampled_render_to_texture */
+#ifdef GL_IMG_program_binary
+ CONST_CAST(GLEW_IMG_program_binary) = _glewSearchExtension("GL_IMG_program_binary", extStart, extEnd);
+#endif /* GL_IMG_program_binary */
+#ifdef GL_IMG_read_format
+ CONST_CAST(GLEW_IMG_read_format) = _glewSearchExtension("GL_IMG_read_format", extStart, extEnd);
+#endif /* GL_IMG_read_format */
+#ifdef GL_IMG_shader_binary
+ CONST_CAST(GLEW_IMG_shader_binary) = _glewSearchExtension("GL_IMG_shader_binary", extStart, extEnd);
+#endif /* GL_IMG_shader_binary */
+#ifdef GL_IMG_texture_compression_pvrtc
+ CONST_CAST(GLEW_IMG_texture_compression_pvrtc) = _glewSearchExtension("GL_IMG_texture_compression_pvrtc", extStart, extEnd);
+#endif /* GL_IMG_texture_compression_pvrtc */
+#ifdef GL_IMG_texture_env_enhanced_fixed_function
+ CONST_CAST(GLEW_IMG_texture_env_enhanced_fixed_function) = _glewSearchExtension("GL_IMG_texture_env_enhanced_fixed_function", extStart, extEnd);
+#endif /* GL_IMG_texture_env_enhanced_fixed_function */
+#ifdef GL_IMG_user_clip_plane
+ CONST_CAST(GLEW_IMG_user_clip_plane) = _glewSearchExtension("GL_IMG_user_clip_plane", extStart, extEnd);
+ if (glewExperimental || GLEW_IMG_user_clip_plane) CONST_CAST(GLEW_IMG_user_clip_plane) = !_glewInit_GL_IMG_user_clip_plane(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_IMG_user_clip_plane */
+#ifdef GL_NV_3dvision_settings
+ CONST_CAST(GLEW_NV_3dvision_settings) = _glewSearchExtension("GL_NV_3dvision_settings", extStart, extEnd);
+ if (glewExperimental || GLEW_NV_3dvision_settings) CONST_CAST(GLEW_NV_3dvision_settings) = !_glewInit_GL_NV_3dvision_settings(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_NV_3dvision_settings */
+#ifdef GL_NV_EGL_stream_consumer_external
+ CONST_CAST(GLEW_NV_EGL_stream_consumer_external) = _glewSearchExtension("GL_NV_EGL_stream_consumer_external", extStart, extEnd);
+#endif /* GL_NV_EGL_stream_consumer_external */
+#ifdef GL_NV_bgr
+ CONST_CAST(GLEW_NV_bgr) = _glewSearchExtension("GL_NV_bgr", extStart, extEnd);
+#endif /* GL_NV_bgr */
+#ifdef GL_NV_coverage_sample
+ CONST_CAST(GLEW_NV_coverage_sample) = _glewSearchExtension("GL_NV_coverage_sample", extStart, extEnd);
+ if (glewExperimental || GLEW_NV_coverage_sample) CONST_CAST(GLEW_NV_coverage_sample) = !_glewInit_GL_NV_coverage_sample(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_NV_coverage_sample */
+#ifdef GL_NV_depth_nonlinear
+ CONST_CAST(GLEW_NV_depth_nonlinear) = _glewSearchExtension("GL_NV_depth_nonlinear", extStart, extEnd);
+#endif /* GL_NV_depth_nonlinear */
+#ifdef GL_NV_draw_buffers
+ CONST_CAST(GLEW_NV_draw_buffers) = _glewSearchExtension("GL_NV_draw_buffers", extStart, extEnd);
+ if (glewExperimental || GLEW_NV_draw_buffers) CONST_CAST(GLEW_NV_draw_buffers) = !_glewInit_GL_NV_draw_buffers(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_NV_draw_buffers */
+#ifdef GL_NV_fbo_color_attachments
+ CONST_CAST(GLEW_NV_fbo_color_attachments) = _glewSearchExtension("GL_NV_fbo_color_attachments", extStart, extEnd);
+#endif /* GL_NV_fbo_color_attachments */
+#ifdef GL_NV_pack_subimage
+ CONST_CAST(GLEW_NV_pack_subimage) = _glewSearchExtension("GL_NV_pack_subimage", extStart, extEnd);
+#endif /* GL_NV_pack_subimage */
+#ifdef GL_NV_packed_float
+ CONST_CAST(GLEW_NV_packed_float) = _glewSearchExtension("GL_NV_packed_float", extStart, extEnd);
+#endif /* GL_NV_packed_float */
+#ifdef GL_NV_packed_float_linear
+ CONST_CAST(GLEW_NV_packed_float_linear) = _glewSearchExtension("GL_NV_packed_float_linear", extStart, extEnd);
+#endif /* GL_NV_packed_float_linear */
+#ifdef GL_NV_pixel_buffer_object
+ CONST_CAST(GLEW_NV_pixel_buffer_object) = _glewSearchExtension("GL_NV_pixel_buffer_object", extStart, extEnd);
+#endif /* GL_NV_pixel_buffer_object */
+#ifdef GL_NV_platform_binary
+ CONST_CAST(GLEW_NV_platform_binary) = _glewSearchExtension("GL_NV_platform_binary", extStart, extEnd);
+#endif /* GL_NV_platform_binary */
+#ifdef GL_NV_read_buffer
+ CONST_CAST(GLEW_NV_read_buffer) = _glewSearchExtension("GL_NV_read_buffer", extStart, extEnd);
+ if (glewExperimental || GLEW_NV_read_buffer) CONST_CAST(GLEW_NV_read_buffer) = !_glewInit_GL_NV_read_buffer(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_NV_read_buffer */
+#ifdef GL_NV_read_buffer_front
+ CONST_CAST(GLEW_NV_read_buffer_front) = _glewSearchExtension("GL_NV_read_buffer_front", extStart, extEnd);
+#endif /* GL_NV_read_buffer_front */
+#ifdef GL_NV_read_depth
+ CONST_CAST(GLEW_NV_read_depth) = _glewSearchExtension("GL_NV_read_depth", extStart, extEnd);
+#endif /* GL_NV_read_depth */
+#ifdef GL_NV_read_depth_stencil
+ CONST_CAST(GLEW_NV_read_depth_stencil) = _glewSearchExtension("GL_NV_read_depth_stencil", extStart, extEnd);
+#endif /* GL_NV_read_depth_stencil */
+#ifdef GL_NV_read_stencil
+ CONST_CAST(GLEW_NV_read_stencil) = _glewSearchExtension("GL_NV_read_stencil", extStart, extEnd);
+#endif /* GL_NV_read_stencil */
+#ifdef GL_NV_texture_array
+ CONST_CAST(GLEW_NV_texture_array) = _glewSearchExtension("GL_NV_texture_array", extStart, extEnd);
+ if (glewExperimental || GLEW_NV_texture_array) CONST_CAST(GLEW_NV_texture_array) = !_glewInit_GL_NV_texture_array(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_NV_texture_array */
+#ifdef GL_NV_texture_compression_latc
+ CONST_CAST(GLEW_NV_texture_compression_latc) = _glewSearchExtension("GL_NV_texture_compression_latc", extStart, extEnd);
+#endif /* GL_NV_texture_compression_latc */
+#ifdef GL_NV_texture_compression_s3tc
+ CONST_CAST(GLEW_NV_texture_compression_s3tc) = _glewSearchExtension("GL_NV_texture_compression_s3tc", extStart, extEnd);
+#endif /* GL_NV_texture_compression_s3tc */
+#ifdef GL_NV_texture_compression_s3tc_update
+ CONST_CAST(GLEW_NV_texture_compression_s3tc_update) = _glewSearchExtension("GL_NV_texture_compression_s3tc_update", extStart, extEnd);
+#endif /* GL_NV_texture_compression_s3tc_update */
+#ifdef GL_NV_texture_npot_2D_mipmap
+ CONST_CAST(GLEW_NV_texture_npot_2D_mipmap) = _glewSearchExtension("GL_NV_texture_npot_2D_mipmap", extStart, extEnd);
+#endif /* GL_NV_texture_npot_2D_mipmap */
+#ifdef GL_OES_EGL_image
+ CONST_CAST(GLEW_OES_EGL_image) = _glewSearchExtension("GL_OES_EGL_image", extStart, extEnd);
+ if (glewExperimental || GLEW_OES_EGL_image) CONST_CAST(GLEW_OES_EGL_image) = !_glewInit_GL_OES_EGL_image(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_OES_EGL_image */
+#ifdef GL_OES_EGL_image_external
+ CONST_CAST(GLEW_OES_EGL_image_external) = _glewSearchExtension("GL_OES_EGL_image_external ", extStart, extEnd);
+ if (glewExperimental || GLEW_OES_EGL_image_external) CONST_CAST(GLEW_OES_EGL_image_external) = !_glewInit_GL_OES_EGL_image_external(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_OES_EGL_image_external */
+#ifdef GL_OES_EGL_sync
+ CONST_CAST(GLEW_OES_EGL_sync) = _glewSearchExtension("GL_OES_EGL_sync", extStart, extEnd);
+#endif /* GL_OES_EGL_sync */
+#ifdef GL_OES_blend_equation_separate
+ CONST_CAST(GLEW_OES_blend_equation_separate) = _glewSearchExtension("GL_OES_blend_equation_separate", extStart, extEnd);
+ if (glewExperimental || GLEW_OES_blend_equation_separate) CONST_CAST(GLEW_OES_blend_equation_separate) = !_glewInit_GL_OES_blend_equation_separate(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_OES_blend_equation_separate */
+#ifdef GL_OES_blend_func_separate
+ CONST_CAST(GLEW_OES_blend_func_separate) = _glewSearchExtension("GL_OES_blend_func_separate", extStart, extEnd);
+ if (glewExperimental || GLEW_OES_blend_func_separate) CONST_CAST(GLEW_OES_blend_func_separate) = !_glewInit_GL_OES_blend_func_separate(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_OES_blend_func_separate */
+#ifdef GL_OES_blend_subtract
+ CONST_CAST(GLEW_OES_blend_subtract) = _glewSearchExtension("GL_OES_blend_subtract", extStart, extEnd);
+ if (glewExperimental || GLEW_OES_blend_subtract) CONST_CAST(GLEW_OES_blend_subtract) = !_glewInit_GL_OES_blend_subtract(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_OES_blend_subtract */
+#ifdef GL_OES_compressed_ETC1_RGB8_texture
+ CONST_CAST(GLEW_OES_compressed_ETC1_RGB8_texture) = _glewSearchExtension("GL_OES_compressed_ETC1_RGB8_texture", extStart, extEnd);
+#endif /* GL_OES_compressed_ETC1_RGB8_texture */
+#ifdef GL_OES_depth24
+ CONST_CAST(GLEW_OES_depth24) = _glewSearchExtension("GL_OES_depth24", extStart, extEnd);
+#endif /* GL_OES_depth24 */
+#ifdef GL_OES_depth32
+ CONST_CAST(GLEW_OES_depth32) = _glewSearchExtension("GL_OES_depth32", extStart, extEnd);
+#endif /* GL_OES_depth32 */
+#ifdef GL_OES_depth_texture
+ CONST_CAST(GLEW_OES_depth_texture) = _glewSearchExtension("GL_OES_depth_texture", extStart, extEnd);
+#endif /* GL_OES_depth_texture */
+#ifdef GL_OES_depth_texture_cube_map
+ CONST_CAST(GLEW_OES_depth_texture_cube_map) = _glewSearchExtension("GL_OES_depth_texture_cube_map", extStart, extEnd);
+#endif /* GL_OES_depth_texture_cube_map */
+#ifdef GL_OES_draw_texture
+ CONST_CAST(GLEW_OES_draw_texture) = _glewSearchExtension("GL_OES_draw_texture", extStart, extEnd);
+#endif /* GL_OES_draw_texture */
+#ifdef GL_OES_element_index_uint
+ CONST_CAST(GLEW_OES_element_index_uint) = _glewSearchExtension("GL_OES_element_index_uint", extStart, extEnd);
+#endif /* GL_OES_element_index_uint */
+#ifdef GL_OES_extended_matrix_palette
+ CONST_CAST(GLEW_OES_extended_matrix_palette) = _glewSearchExtension("GL_OES_extended_matrix_palette", extStart, extEnd);
+#endif /* GL_OES_extended_matrix_palette */
+#ifdef GL_OES_fbo_render_mipmap
+ CONST_CAST(GLEW_OES_fbo_render_mipmap) = _glewSearchExtension("GL_OES_fbo_render_mipmap", extStart, extEnd);
+#endif /* GL_OES_fbo_render_mipmap */
+#ifdef GL_OES_fragment_precision_high
+ CONST_CAST(GLEW_OES_fragment_precision_high) = _glewSearchExtension("GL_OES_fragment_precision_high", extStart, extEnd);
+#endif /* GL_OES_fragment_precision_high */
+#ifdef GL_OES_framebuffer_object
+ CONST_CAST(GLEW_OES_framebuffer_object) = _glewSearchExtension("GL_OES_framebuffer_object", extStart, extEnd);
+ if (glewExperimental || GLEW_OES_framebuffer_object) CONST_CAST(GLEW_OES_framebuffer_object) = !_glewInit_GL_OES_framebuffer_object(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_OES_framebuffer_object */
+#ifdef GL_OES_get_program_binary
+ CONST_CAST(GLEW_OES_get_program_binary) = _glewSearchExtension("GL_OES_get_program_binary", extStart, extEnd);
+ if (glewExperimental || GLEW_OES_get_program_binary) CONST_CAST(GLEW_OES_get_program_binary) = !_glewInit_GL_OES_get_program_binary(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_OES_get_program_binary */
+#ifdef GL_OES_mapbuffer
+ CONST_CAST(GLEW_OES_mapbuffer) = _glewSearchExtension("GL_OES_mapbuffer", extStart, extEnd);
+ if (glewExperimental || GLEW_OES_mapbuffer) CONST_CAST(GLEW_OES_mapbuffer) = !_glewInit_GL_OES_mapbuffer(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_OES_mapbuffer */
+#ifdef GL_OES_matrix_get
+ CONST_CAST(GLEW_OES_matrix_get) = _glewSearchExtension("GL_OES_matrix_get", extStart, extEnd);
+#endif /* GL_OES_matrix_get */
+#ifdef GL_OES_matrix_palette
+ CONST_CAST(GLEW_OES_matrix_palette) = _glewSearchExtension("GL_OES_matrix_palette", extStart, extEnd);
+ if (glewExperimental || GLEW_OES_matrix_palette) CONST_CAST(GLEW_OES_matrix_palette) = !_glewInit_GL_OES_matrix_palette(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_OES_matrix_palette */
+#ifdef GL_OES_packed_depth_stencil
+ CONST_CAST(GLEW_OES_packed_depth_stencil) = _glewSearchExtension("GL_OES_packed_depth_stencil", extStart, extEnd);
+#endif /* GL_OES_packed_depth_stencil */
+#ifdef GL_OES_point_size_array
+ CONST_CAST(GLEW_OES_point_size_array) = _glewSearchExtension("GL_OES_point_size_array", extStart, extEnd);
+ if (glewExperimental || GLEW_OES_point_size_array) CONST_CAST(GLEW_OES_point_size_array) = !_glewInit_GL_OES_point_size_array(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_OES_point_size_array */
+#ifdef GL_OES_point_sprite
+ CONST_CAST(GLEW_OES_point_sprite) = _glewSearchExtension("GL_OES_point_sprite", extStart, extEnd);
+#endif /* GL_OES_point_sprite */
+#ifdef GL_OES_required_internalformat
+ CONST_CAST(GLEW_OES_required_internalformat) = _glewSearchExtension("GL_OES_required_internalformat", extStart, extEnd);
+#endif /* GL_OES_required_internalformat */
+#ifdef GL_OES_rgb8_rgba8
+ CONST_CAST(GLEW_OES_rgb8_rgba8) = _glewSearchExtension("GL_OES_rgb8_rgba8", extStart, extEnd);
+#endif /* GL_OES_rgb8_rgba8 */
+#ifdef GL_OES_standard_derivatives
+ CONST_CAST(GLEW_OES_standard_derivatives) = _glewSearchExtension("GL_OES_standard_derivatives", extStart, extEnd);
+#endif /* GL_OES_standard_derivatives */
+#ifdef GL_OES_stencil1
+ CONST_CAST(GLEW_OES_stencil1) = _glewSearchExtension("GL_OES_stencil1", extStart, extEnd);
+#endif /* GL_OES_stencil1 */
+#ifdef GL_OES_stencil4
+ CONST_CAST(GLEW_OES_stencil4) = _glewSearchExtension("GL_OES_stencil4", extStart, extEnd);
+#endif /* GL_OES_stencil4 */
+#ifdef GL_OES_stencil8
+ CONST_CAST(GLEW_OES_stencil8) = _glewSearchExtension("GL_OES_stencil8", extStart, extEnd);
+#endif /* GL_OES_stencil8 */
+#ifdef GL_OES_surfaceless_context
+ CONST_CAST(GLEW_OES_surfaceless_context) = _glewSearchExtension("GL_OES_surfaceless_context", extStart, extEnd);
+#endif /* GL_OES_surfaceless_context */
+#ifdef GL_OES_texture_3D
+ CONST_CAST(GLEW_OES_texture_3D) = _glewSearchExtension("GL_OES_texture_3D", extStart, extEnd);
+ if (glewExperimental || GLEW_OES_texture_3D) CONST_CAST(GLEW_OES_texture_3D) = !_glewInit_GL_OES_texture_3D(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_OES_texture_3D */
+#ifdef GL_OES_texture_cube_map
+ CONST_CAST(GLEW_OES_texture_cube_map) = _glewSearchExtension("GL_OES_texture_cube_map", extStart, extEnd);
+ if (glewExperimental || GLEW_OES_texture_cube_map) CONST_CAST(GLEW_OES_texture_cube_map) = !_glewInit_GL_OES_texture_cube_map(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_OES_texture_cube_map */
+#ifdef GL_OES_texture_env_crossbar
+ CONST_CAST(GLEW_OES_texture_env_crossbar) = _glewSearchExtension("GL_OES_texture_env_crossbar", extStart, extEnd);
+#endif /* GL_OES_texture_env_crossbar */
+#ifdef GL_OES_texture_mirrored_repeat
+ CONST_CAST(GLEW_OES_texture_mirrored_repeat) = _glewSearchExtension("GL_OES_texture_mirrored_repeat", extStart, extEnd);
+#endif /* GL_OES_texture_mirrored_repeat */
+#ifdef GL_OES_texture_npot
+ CONST_CAST(GLEW_OES_texture_npot) = _glewSearchExtension("GL_OES_texture_npot", extStart, extEnd);
+#endif /* GL_OES_texture_npot */
+#ifdef GL_OES_vertex_array_object
+ CONST_CAST(GLEW_OES_vertex_array_object) = _glewSearchExtension("GL_OES_vertex_array_object", extStart, extEnd);
+ if (glewExperimental || GLEW_OES_vertex_array_object) CONST_CAST(GLEW_OES_vertex_array_object) = !_glewInit_GL_OES_vertex_array_object(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_OES_vertex_array_object */
+#ifdef GL_OES_vertex_half_float
+ CONST_CAST(GLEW_OES_vertex_half_float) = _glewSearchExtension("GL_OES_vertex_half_float", extStart, extEnd);
+#endif /* GL_OES_vertex_half_float */
+#ifdef GL_OES_vertex_type_10_10_10_2
+ CONST_CAST(GLEW_OES_vertex_type_10_10_10_2) = _glewSearchExtension("GL_OES_vertex_type_10_10_10_2", extStart, extEnd);
+#endif /* GL_OES_vertex_type_10_10_10_2 */
+#ifdef GL_QCOM_alpha_test
+ CONST_CAST(GLEW_QCOM_alpha_test) = _glewSearchExtension("GL_QCOM_alpha_test", extStart, extEnd);
+ if (glewExperimental || GLEW_QCOM_alpha_test) CONST_CAST(GLEW_QCOM_alpha_test) = !_glewInit_GL_QCOM_alpha_test(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_QCOM_alpha_test */
+#ifdef GL_QCOM_binning_control
+ CONST_CAST(GLEW_QCOM_binning_control) = _glewSearchExtension("GL_QCOM_binning_control", extStart, extEnd);
+#endif /* GL_QCOM_binning_control */
+#ifdef GL_QCOM_driver_control
+ CONST_CAST(GLEW_QCOM_driver_control) = _glewSearchExtension("GL_QCOM_driver_control", extStart, extEnd);
+ if (glewExperimental || GLEW_QCOM_driver_control) CONST_CAST(GLEW_QCOM_driver_control) = !_glewInit_GL_QCOM_driver_control(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_QCOM_driver_control */
+#ifdef GL_QCOM_extended_get
+ CONST_CAST(GLEW_QCOM_extended_get) = _glewSearchExtension("GL_QCOM_extended_get", extStart, extEnd);
+ if (glewExperimental || GLEW_QCOM_extended_get) CONST_CAST(GLEW_QCOM_extended_get) = !_glewInit_GL_QCOM_extended_get(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_QCOM_extended_get */
+#ifdef GL_QCOM_extended_get2
+ CONST_CAST(GLEW_QCOM_extended_get2) = _glewSearchExtension("GL_QCOM_extended_get2", extStart, extEnd);
+ if (glewExperimental || GLEW_QCOM_extended_get2) CONST_CAST(GLEW_QCOM_extended_get2) = !_glewInit_GL_QCOM_extended_get2(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_QCOM_extended_get2 */
+#ifdef GL_QCOM_perfmon_global_mode
+ CONST_CAST(GLEW_QCOM_perfmon_global_mode) = _glewSearchExtension("GL_QCOM_perfmon_global_mode", extStart, extEnd);
+#endif /* GL_QCOM_perfmon_global_mode */
+#ifdef GL_QCOM_tiled_rendering
+ CONST_CAST(GLEW_QCOM_tiled_rendering) = _glewSearchExtension("GL_QCOM_tiled_rendering", extStart, extEnd);
+ if (glewExperimental || GLEW_QCOM_tiled_rendering) CONST_CAST(GLEW_QCOM_tiled_rendering) = !_glewInit_GL_QCOM_tiled_rendering(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_QCOM_tiled_rendering */
+#ifdef GL_QCOM_writeonly_rendering
+ CONST_CAST(GLEW_QCOM_writeonly_rendering) = _glewSearchExtension("GL_QCOM_writeonly_rendering", extStart, extEnd);
+#endif /* GL_QCOM_writeonly_rendering */
+#ifdef GL_SUN_multi_draw_arrays
+ CONST_CAST(GLEW_SUN_multi_draw_arrays) = _glewSearchExtension("GL_SUN_multi_draw_arrays", extStart, extEnd);
+ if (glewExperimental || GLEW_SUN_multi_draw_arrays) CONST_CAST(GLEW_SUN_multi_draw_arrays) = !_glewInit_GL_SUN_multi_draw_arrays(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_SUN_multi_draw_arrays */
+#ifdef GL_VG_KHR_EGL_sync
+ CONST_CAST(GLEW_VG_KHR_EGL_sync) = _glewSearchExtension("GL_VG_KHR_EGL_sync", extStart, extEnd);
+#endif /* GL_VG_KHR_EGL_sync */
+#ifdef GL_VIV_shader_binary
+ CONST_CAST(GLEW_VIV_shader_binary) = _glewSearchExtension("GL_VIV_shader_binary", extStart, extEnd);
+#endif /* GL_VIV_shader_binary */
+
+ return GLEW_OK;
+}
+
+#if defined (GLEW_INC_EGL)
+
+#if !defined(_WIN32) || !defined(GLEW_MX)
+
+PFNCREATESYNC __eglewCreateSync = NULL;
+PFNDESTROYSYNC __eglewDestroySync = NULL;
+PFNCLIENTWAITSYNC __eglewClientWaitSync = NULL;
+PFNGETSYNCATTRIB __eglewGetSyncAttrib = NULL;
+PFNGETPLATFORMDISPLAY __eglewGetPlatformDisplay = NULL;
+PFNCREATEPLATFORMWINDOWSURFACE __eglewCreatePlatformWindowSurface = NULL;
+PFNCREATEPLATFORMPIXMAPSURFACE __eglewCreatePlatformPixmapSurface = NULL;
+PFNWAITSYNC __eglewWaitSync = NULL;
+
+PFNEGLBINDAPIPROC __eglewBindAPI = NULL;
+PFNEGLCREATEPBUFFERFROMCLIENTBUFFERPROC __eglewCreatePbufferFromClientBuffer = NULL;
+PFNEGLQUERYAPIPROC __eglewQueryAPI = NULL;
+PFNEGLRELEASETHREADPROC __eglewReleaseThread = NULL;
+PFNEGLWAITCLIENTPROC __eglewWaitClient = NULL;
+
+PFNEGLSETBLOBCACHEFUNCSANDROIDPROC __eglewSetBlobCacheFuncsANDROID = NULL;
+
+PFNEGLDUPNATIVEFENCEFDANDROIDPROC __eglewDupNativeFenceFDANDROID = NULL;
+
+PFNEGLQUERYSURFACEPOINTERANGLEPROC __eglewQuerySurfacePointerANGLE = NULL;
+
+PFNEGLCREATEIMAGEKHRPROC __eglewCreateImageKHR = NULL;
+PFNEGLDESTROYIMAGEKHRPROC __eglewDestroyImageKHR = NULL;
+
+PFNEGLLOCKSURFACEKHRPROC __eglewLockSurfaceKHR = NULL;
+PFNEGLUNLOCKSURFACEKHRPROC __eglewUnlockSurfaceKHR = NULL;
+
+PFNEGLCLIENTWAITSYNCKHRPROC __eglewClientWaitSyncKHR = NULL;
+PFNEGLCREATESYNCKHRPROC __eglewCreateSyncKHR = NULL;
+PFNEGLDESTROYSYNCKHRPROC __eglewDestroySyncKHR = NULL;
+PFNEGLGETSYNCATTRIBKHRPROC __eglewGetSyncAttribKHR = NULL;
+PFNEGLSIGNALSYNCKHRPROC __eglewSignalSyncKHR = NULL;
+
+PFNEGLSTREAMCONSUMERACQUIREKHRPROC __eglewStreamConsumerAcquireKHR = NULL;
+PFNEGLSTREAMCONSUMERGLTEXTUREEXTERNALKHRPROC __eglewStreamConsumerGLTextureExternalKHR = NULL;
+PFNEGLSTREAMCONSUMERRELEASEKHRPROC __eglewStreamConsumerReleaseKHR = NULL;
+
+PFNEGLCREATESTREAMFROMFILEDESCRIPTORKHRPROC __eglewCreateStreamFromFileDescriptorKHR = NULL;
+PFNEGLGETSTREAMFILEDESCRIPTORKHRPROC __eglewGetStreamFileDescriptorKHR = NULL;
+
+PFNEGLCREATESTREAMPRODUCERSURFACEKHRPROC __eglewCreateStreamProducerSurfaceKHR = NULL;
+
+PFNEGLWAITSYNCKHRPROC __eglewWaitSyncKHR = NULL;
+
+PFNEGLCREATEDRMIMAGEMESAPROC __eglewCreateDRMImageMESA = NULL;
+PFNEGLEXPORTDRMIMAGEMESAPROC __eglewExportDRMImageMESA = NULL;
+
+PFNEGLQUERYNATIVEDISPLAYNVPROC __eglewQueryNativeDisplayNV = NULL;
+PFNEGLQUERYNATIVEPIXMAPNVPROC __eglewQueryNativePixmapNV = NULL;
+PFNEGLQUERYNATIVEWINDOWNVPROC __eglewQueryNativeWindowNV = NULL;
+
+PFNEGLPOSTSUBBUFFERNVPROC __eglewPostSubBufferNV = NULL;
+
+PFNEGLCLIENTWAITSYNCNVPROC __eglewClientWaitSyncNV = NULL;
+PFNEGLCREATEFENCESYNCNVPROC __eglewCreateFenceSyncNV = NULL;
+PFNEGLDESTROYSYNCNVPROC __eglewDestroySyncNV = NULL;
+PFNEGLFENCENVPROC __eglewFenceNV = NULL;
+PFNEGLGETSYNCATTRIBNVPROC __eglewGetSyncAttribNV = NULL;
+PFNEGLSIGNALSYNCNVPROC __eglewSignalSyncNV = NULL;
+
+PFNEGLGETSYSTEMTIMEFREQUENCYNVPROC __eglewGetSystemTimeFrequencyNV = NULL;
+PFNEGLGETSYSTEMTIMENVPROC __eglewGetSystemTimeNV = NULL;
+
+#endif /* !WIN32 || !GLEW_MX */
+
+#if !defined(GLEW_MX)
+
+GLboolean __EGLEW_VERSION_1_1 = GL_FALSE;
+GLboolean __EGLEW_VERSION_1_2 = GL_FALSE;
+GLboolean __EGLEW_VERSION_1_3 = GL_FALSE;
+GLboolean __EGLEW_VERSION_1_4 = GL_FALSE;
+GLboolean __EGLEW_VERSION_1_5 = GL_FALSE;
+GLboolean __EGLEW_ANDROID_blob_cache = GL_FALSE;
+GLboolean __EGLEW_ANDROID_framebuffer_target = GL_FALSE;
+GLboolean __EGLEW_ANDROID_image_native_buffer = GL_FALSE;
+GLboolean __EGLEW_ANDROID_native_fence_sync = GL_FALSE;
+GLboolean __EGLEW_ANDROID_recordable = GL_FALSE;
+GLboolean __EGLEW_ANGLE_d3d_share_handle_client_buffer = GL_FALSE;
+GLboolean __EGLEW_ANGLE_query_surface_pointer = GL_FALSE;
+GLboolean __EGLEW_ANGLE_surface_d3d_texture_2d_share_handle = GL_FALSE;
+GLboolean __EGLEW_EXT_buffer_age = GL_FALSE;
+GLboolean __EGLEW_EXT_create_context_robustness = GL_FALSE;
+GLboolean __EGLEW_EXT_multiview_window = GL_FALSE;
+GLboolean __EGLEW_HI_clientpixmap = GL_FALSE;
+GLboolean __EGLEW_HI_colorformats = GL_FALSE;
+GLboolean __EGLEW_IMG_context_priority = GL_FALSE;
+GLboolean __EGLEW_KHR_config_attribs = GL_FALSE;
+GLboolean __EGLEW_KHR_create_context = GL_FALSE;
+GLboolean __EGLEW_KHR_fence_sync = GL_FALSE;
+GLboolean __EGLEW_KHR_gl_renderbuffer_image = GL_FALSE;
+GLboolean __EGLEW_KHR_gl_texture_2D_image = GL_FALSE;
+GLboolean __EGLEW_KHR_gl_texture_3D_image = GL_FALSE;
+GLboolean __EGLEW_KHR_gl_texture_cubemap_image = GL_FALSE;
+GLboolean __EGLEW_KHR_image = GL_FALSE;
+GLboolean __EGLEW_KHR_image_base = GL_FALSE;
+GLboolean __EGLEW_KHR_image_pixmap = GL_FALSE;
+GLboolean __EGLEW_KHR_lock_surface = GL_FALSE;
+GLboolean __EGLEW_KHR_lock_surface2 = GL_FALSE;
+GLboolean __EGLEW_KHR_reusable_sync = GL_FALSE;
+GLboolean __EGLEW_KHR_stream = GL_FALSE;
+GLboolean __EGLEW_KHR_stream_consumer_gltexture = GL_FALSE;
+GLboolean __EGLEW_KHR_stream_cross_process_fd = GL_FALSE;
+GLboolean __EGLEW_KHR_stream_fifo = GL_FALSE;
+GLboolean __EGLEW_KHR_stream_producer_aldatalocator = GL_FALSE;
+GLboolean __EGLEW_KHR_stream_producer_eglsurface = GL_FALSE;
+GLboolean __EGLEW_KHR_surfaceless_context = GL_FALSE;
+GLboolean __EGLEW_KHR_vg_parent_image = GL_FALSE;
+GLboolean __EGLEW_KHR_wait_sync = GL_FALSE;
+GLboolean __EGLEW_MESA_drm_image = GL_FALSE;
+GLboolean __EGLEW_NV_3dvision_surface = GL_FALSE;
+GLboolean __EGLEW_NV_coverage_sample = GL_FALSE;
+GLboolean __EGLEW_NV_coverage_sample_resolve = GL_FALSE;
+GLboolean __EGLEW_NV_depth_nonlinear = GL_FALSE;
+GLboolean __EGLEW_NV_native_query = GL_FALSE;
+GLboolean __EGLEW_NV_post_convert_rounding = GL_FALSE;
+GLboolean __EGLEW_NV_post_sub_buffer = GL_FALSE;
+GLboolean __EGLEW_NV_sync = GL_FALSE;
+GLboolean __EGLEW_NV_system_time = GL_FALSE;
+
+#endif /* !GLEW_MX */
+
+#ifdef EGL_VERSION_1_2
+
+static GLboolean _glewInit_EGL_VERSION_1_2 (EGLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((eglBindAPI = (PFNEGLBINDAPIPROC)glewGetProcAddress((const GLubyte*)"eglBindAPI")) == NULL) || r;
+ r = ((eglCreatePbufferFromClientBuffer = (PFNEGLCREATEPBUFFERFROMCLIENTBUFFERPROC)glewGetProcAddress((const GLubyte*)"eglCreatePbufferFromClientBuffer")) == NULL) || r;
+ r = ((eglQueryAPI = (PFNEGLQUERYAPIPROC)glewGetProcAddress((const GLubyte*)"eglQueryAPI")) == NULL) || r;
+ r = ((eglReleaseThread = (PFNEGLRELEASETHREADPROC)glewGetProcAddress((const GLubyte*)"eglReleaseThread")) == NULL) || r;
+ r = ((eglWaitClient = (PFNEGLWAITCLIENTPROC)glewGetProcAddress((const GLubyte*)"eglWaitClient")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* EGL_VERSION_1_2 */
+
+#ifdef EGL_VERSION_1_3
+
+#endif /* EGL_VERSION_1_3 */
+
+#ifdef EGL_VERSION_1_4
+
+#endif /* EGL_VERSION_1_4 */
+
+#ifdef EGL_ANDROID_blob_cache
+
+static GLboolean _glewInit_EGL_ANDROID_blob_cache (EGLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((eglSetBlobCacheFuncsANDROID = (PFNEGLSETBLOBCACHEFUNCSANDROIDPROC)glewGetProcAddress((const GLubyte*)"eglSetBlobCacheFuncsANDROID")) == NULL) || r;
+
+ return r;
+}
+
+#ifdef EGL_VERSION_1_5
+
+static GLboolean _glewInit_EGL_VERSION_1_5 (EGLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((eglCreateSync = (PFNCREATESYNC )glewGetProcAddress((const GLubyte*)"eglCreateSync" )) == NULL) || r;
+ r = ((eglDestroySync = (PFNDESTROYSYNC )glewGetProcAddress((const GLubyte*)"eglDestroySync" )) == NULL) || r;
+ r = ((eglClientWaitSync = (PFNCLIENTWAITSYNC )glewGetProcAddress((const GLubyte*)"eglClientWaitSync" )) == NULL) || r;
+ r = ((eglGetSyncAttrib = (PFNGETSYNCATTRIB )glewGetProcAddress((const GLubyte*)"eglGetSyncAttrib" )) == NULL) || r;
+ r = ((eglGetPlatformDisplay = (PFNGETPLATFORMDISPLAY )glewGetProcAddress((const GLubyte*)"eglGetPlatformDisplay" )) == NULL) || r;
+ r = ((eglCreatePlatformWindowSurface = (PFNCREATEPLATFORMWINDOWSURFACE)glewGetProcAddress((const GLubyte*)"eglCreatePlatformWindowSurface")) == NULL) || r;
+ r = ((eglCreatePlatformPixmapSurface = (PFNCREATEPLATFORMPIXMAPSURFACE)glewGetProcAddress((const GLubyte*)"eglCreatePlatformPixmapSurface")) == NULL) || r;
+ r = ((eglWaitSync = (PFNWAITSYNC )glewGetProcAddress((const GLubyte*)"eglWaitSync" )) == NULL) || r;
+
+return r;
+}
+
+#endif /* EGL_VERSION_1_5 */
+
+#endif /* EGL_ANDROID_blob_cache */
+
+#ifdef EGL_ANDROID_framebuffer_target
+
+#endif /* EGL_ANDROID_framebuffer_target */
+
+#ifdef EGL_ANDROID_image_native_buffer
+
+#endif /* EGL_ANDROID_image_native_buffer */
+
+#ifdef EGL_ANDROID_native_fence_sync
+
+static GLboolean _glewInit_EGL_ANDROID_native_fence_sync (EGLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((eglDupNativeFenceFDANDROID = (PFNEGLDUPNATIVEFENCEFDANDROIDPROC)glewGetProcAddress((const GLubyte*)"eglDupNativeFenceFDANDROID")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* EGL_ANDROID_native_fence_sync */
+
+#ifdef EGL_ANDROID_recordable
+
+#endif /* EGL_ANDROID_recordable */
+
+#ifdef EGL_ANGLE_d3d_share_handle_client_buffer
+
+#endif /* EGL_ANGLE_d3d_share_handle_client_buffer */
+
+#ifdef EGL_ANGLE_query_surface_pointer
+
+static GLboolean _glewInit_EGL_ANGLE_query_surface_pointer (EGLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((eglQuerySurfacePointerANGLE = (PFNEGLQUERYSURFACEPOINTERANGLEPROC)glewGetProcAddress((const GLubyte*)"eglQuerySurfacePointerANGLE")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* EGL_ANGLE_query_surface_pointer */
+
+#ifdef EGL_ANGLE_surface_d3d_texture_2d_share_handle
+
+#endif /* EGL_ANGLE_surface_d3d_texture_2d_share_handle */
+
+#ifdef EGL_EXT_buffer_age
+
+#endif /* EGL_EXT_buffer_age */
+
+#ifdef EGL_EXT_create_context_robustness
+
+#endif /* EGL_EXT_create_context_robustness */
+
+#ifdef EGL_EXT_multiview_window
+
+#endif /* EGL_EXT_multiview_window */
+
+#ifdef EGL_HI_clientpixmap
+
+#endif /* EGL_HI_clientpixmap */
+
+#ifdef EGL_HI_colorformats
+
+#endif /* EGL_HI_colorformats */
+
+#ifdef EGL_IMG_context_priority
+
+#endif /* EGL_IMG_context_priority */
+
+#ifdef EGL_KHR_config_attribs
+
+#endif /* EGL_KHR_config_attribs */
+
+#ifdef EGL_KHR_create_context
+
+#endif /* EGL_KHR_create_context */
+
+#ifdef EGL_KHR_fence_sync
+
+static GLboolean _glewInit_EGL_KHR_fence_sync (EGLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+ r = ((eglClientWaitSyncKHR = (PFNEGLCLIENTWAITSYNCKHRPROC)glewGetProcAddress((const GLubyte*)"eglClientWaitSyncKHR")) == NULL) || r;
+ r = ((eglCreateSyncKHR = (PFNEGLCREATESYNCKHRPROC)glewGetProcAddress((const GLubyte*)"eglCreateSyncKHR")) == NULL) || r;
+ r = ((eglDestroySyncKHR = (PFNEGLDESTROYSYNCKHRPROC)glewGetProcAddress((const GLubyte*)"eglDestroySyncKHR")) == NULL) || r;
+ r = ((eglGetSyncAttribKHR = (PFNEGLGETSYNCATTRIBKHRPROC)glewGetProcAddress((const GLubyte*)"eglGetSyncAttribKHR")) == NULL) || r;
+ return r;
+}
+#endif /* EGL_KHR_fence_sync */
+
+#ifdef EGL_KHR_gl_renderbuffer_image
+
+#endif /* EGL_KHR_gl_renderbuffer_image */
+
+#ifdef EGL_KHR_gl_texture_2D_image
+
+#endif /* EGL_KHR_gl_texture_2D_image */
+
+#ifdef EGL_KHR_gl_texture_3D_image
+
+#endif /* EGL_KHR_gl_texture_3D_image */
+
+#ifdef EGL_KHR_gl_texture_cubemap_image
+
+#endif /* EGL_KHR_gl_texture_cubemap_image */
+
+#ifdef EGL_KHR_image
+
+#endif /* EGL_KHR_image */
+
+#ifdef EGL_KHR_image_base
+
+static GLboolean _glewInit_EGL_KHR_image_base (EGLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((eglCreateImageKHR = (PFNEGLCREATEIMAGEKHRPROC)glewGetProcAddress((const GLubyte*)"eglCreateImageKHR")) == NULL) || r;
+ r = ((eglDestroyImageKHR = (PFNEGLDESTROYIMAGEKHRPROC)glewGetProcAddress((const GLubyte*)"eglDestroyImageKHR")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* EGL_KHR_image_base */
+
+#ifdef EGL_KHR_image_pixmap
+
+#endif /* EGL_KHR_image_pixmap */
+
+#ifdef EGL_KHR_lock_surface
+
+static GLboolean _glewInit_EGL_KHR_lock_surface (EGLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((eglLockSurfaceKHR = (PFNEGLLOCKSURFACEKHRPROC)glewGetProcAddress((const GLubyte*)"eglLockSurfaceKHR")) == NULL) || r;
+ r = ((eglUnlockSurfaceKHR = (PFNEGLUNLOCKSURFACEKHRPROC)glewGetProcAddress((const GLubyte*)"eglUnlockSurfaceKHR")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* EGL_KHR_lock_surface */
+
+#ifdef EGL_KHR_lock_surface2
+
+#endif /* EGL_KHR_lock_surface2 */
+
+#ifdef EGL_KHR_reusable_sync
+
+static GLboolean _glewInit_EGL_KHR_reusable_sync (EGLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((eglClientWaitSyncKHR = (PFNEGLCLIENTWAITSYNCKHRPROC)glewGetProcAddress((const GLubyte*)"eglClientWaitSyncKHR")) == NULL) || r;
+ r = ((eglCreateSyncKHR = (PFNEGLCREATESYNCKHRPROC)glewGetProcAddress((const GLubyte*)"eglCreateSyncKHR")) == NULL) || r;
+ r = ((eglDestroySyncKHR = (PFNEGLDESTROYSYNCKHRPROC)glewGetProcAddress((const GLubyte*)"eglDestroySyncKHR")) == NULL) || r;
+ r = ((eglGetSyncAttribKHR = (PFNEGLGETSYNCATTRIBKHRPROC)glewGetProcAddress((const GLubyte*)"eglGetSyncAttribKHR")) == NULL) || r;
+ r = ((eglSignalSyncKHR = (PFNEGLSIGNALSYNCKHRPROC)glewGetProcAddress((const GLubyte*)"eglSignalSyncKHR")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* EGL_KHR_reusable_sync */
+
+#ifdef EGL_KHR_stream
+
+#endif /* EGL_KHR_stream */
+
+#ifdef EGL_KHR_stream_consumer_gltexture
+
+static GLboolean _glewInit_EGL_KHR_stream_consumer_gltexture (EGLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((eglStreamConsumerAcquireKHR = (PFNEGLSTREAMCONSUMERACQUIREKHRPROC)glewGetProcAddress((const GLubyte*)"eglStreamConsumerAcquireKHR")) == NULL) || r;
+ r = ((eglStreamConsumerGLTextureExternalKHR = (PFNEGLSTREAMCONSUMERGLTEXTUREEXTERNALKHRPROC)glewGetProcAddress((const GLubyte*)"eglStreamConsumerGLTextureExternalKHR")) == NULL) || r;
+ r = ((eglStreamConsumerReleaseKHR = (PFNEGLSTREAMCONSUMERRELEASEKHRPROC)glewGetProcAddress((const GLubyte*)"eglStreamConsumerReleaseKHR")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* EGL_KHR_stream_consumer_gltexture */
+
+#ifdef EGL_KHR_stream_cross_process_fd
+
+static GLboolean _glewInit_EGL_KHR_stream_cross_process_fd (EGLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((eglCreateStreamFromFileDescriptorKHR = (PFNEGLCREATESTREAMFROMFILEDESCRIPTORKHRPROC)glewGetProcAddress((const GLubyte*)"eglCreateStreamFromFileDescriptorKHR")) == NULL) || r;
+ r = ((eglGetStreamFileDescriptorKHR = (PFNEGLGETSTREAMFILEDESCRIPTORKHRPROC)glewGetProcAddress((const GLubyte*)"eglGetStreamFileDescriptorKHR")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* EGL_KHR_stream_cross_process_fd */
+
+#ifdef EGL_KHR_stream_fifo
+
+#endif /* EGL_KHR_stream_fifo */
+
+#ifdef EGL_KHR_stream_producer_aldatalocator
+
+#endif /* EGL_KHR_stream_producer_aldatalocator */
+
+#ifdef EGL_KHR_stream_producer_eglsurface
+
+static GLboolean _glewInit_EGL_KHR_stream_producer_eglsurface (EGLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((eglCreateStreamProducerSurfaceKHR = (PFNEGLCREATESTREAMPRODUCERSURFACEKHRPROC)glewGetProcAddress((const GLubyte*)"eglCreateStreamProducerSurfaceKHR")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* EGL_KHR_stream_producer_eglsurface */
+
+#ifdef EGL_KHR_surfaceless_context
+
+#endif /* EGL_KHR_surfaceless_context */
+
+#ifdef EGL_KHR_vg_parent_image
+
+#endif /* EGL_KHR_vg_parent_image */
+
+#ifdef EGL_KHR_wait_sync
+
+static GLboolean _glewInit_EGL_KHR_wait_sync (EGLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((eglWaitSyncKHR = (PFNEGLWAITSYNCKHRPROC)glewGetProcAddress((const GLubyte*)"eglWaitSyncKHR")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* EGL_KHR_wait_sync */
+
+#ifdef EGL_MESA_drm_image
+
+static GLboolean _glewInit_EGL_MESA_drm_image (EGLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((eglCreateDRMImageMESA = (PFNEGLCREATEDRMIMAGEMESAPROC)glewGetProcAddress((const GLubyte*)"eglCreateDRMImageMESA")) == NULL) || r;
+ r = ((eglExportDRMImageMESA = (PFNEGLEXPORTDRMIMAGEMESAPROC)glewGetProcAddress((const GLubyte*)"eglExportDRMImageMESA")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* EGL_MESA_drm_image */
+
+#ifdef EGL_NV_3dvision_surface
+
+#endif /* EGL_NV_3dvision_surface */
+
+#ifdef EGL_NV_coverage_sample
+
+#endif /* EGL_NV_coverage_sample */
+
+#ifdef EGL_NV_coverage_sample_resolve
+
+#endif /* EGL_NV_coverage_sample_resolve */
+
+#ifdef EGL_NV_depth_nonlinear
+
+#endif /* EGL_NV_depth_nonlinear */
+
+#ifdef EGL_NV_native_query
+
+static GLboolean _glewInit_EGL_NV_native_query (EGLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((eglQueryNativeDisplayNV = (PFNEGLQUERYNATIVEDISPLAYNVPROC)glewGetProcAddress((const GLubyte*)"eglQueryNativeDisplayNV")) == NULL) || r;
+ r = ((eglQueryNativePixmapNV = (PFNEGLQUERYNATIVEPIXMAPNVPROC)glewGetProcAddress((const GLubyte*)"eglQueryNativePixmapNV")) == NULL) || r;
+ r = ((eglQueryNativeWindowNV = (PFNEGLQUERYNATIVEWINDOWNVPROC)glewGetProcAddress((const GLubyte*)"eglQueryNativeWindowNV")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* EGL_NV_native_query */
+
+#ifdef EGL_NV_post_convert_rounding
+
+#endif /* EGL_NV_post_convert_rounding */
+
+#ifdef EGL_NV_post_sub_buffer
+
+static GLboolean _glewInit_EGL_NV_post_sub_buffer (EGLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((eglPostSubBufferNV = (PFNEGLPOSTSUBBUFFERNVPROC)glewGetProcAddress((const GLubyte*)"eglPostSubBufferNV")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* EGL_NV_post_sub_buffer */
+
+#ifdef EGL_NV_sync
+
+static GLboolean _glewInit_EGL_NV_sync (EGLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((eglClientWaitSyncNV = (PFNEGLCLIENTWAITSYNCNVPROC)glewGetProcAddress((const GLubyte*)"eglClientWaitSyncNV")) == NULL) || r;
+ r = ((eglCreateFenceSyncNV = (PFNEGLCREATEFENCESYNCNVPROC)glewGetProcAddress((const GLubyte*)"eglCreateFenceSyncNV")) == NULL) || r;
+ r = ((eglDestroySyncNV = (PFNEGLDESTROYSYNCNVPROC)glewGetProcAddress((const GLubyte*)"eglDestroySyncNV")) == NULL) || r;
+ r = ((eglFenceNV = (PFNEGLFENCENVPROC)glewGetProcAddress((const GLubyte*)"eglFenceNV")) == NULL) || r;
+ r = ((eglGetSyncAttribNV = (PFNEGLGETSYNCATTRIBNVPROC)glewGetProcAddress((const GLubyte*)"eglGetSyncAttribNV")) == NULL) || r;
+ r = ((eglSignalSyncNV = (PFNEGLSIGNALSYNCNVPROC)glewGetProcAddress((const GLubyte*)"eglSignalSyncNV")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* EGL_NV_sync */
+
+#ifdef EGL_NV_system_time
+
+static GLboolean _glewInit_EGL_NV_system_time (EGLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((eglGetSystemTimeFrequencyNV = (PFNEGLGETSYSTEMTIMEFREQUENCYNVPROC)glewGetProcAddress((const GLubyte*)"eglGetSystemTimeFrequencyNV")) == NULL) || r;
+ r = ((eglGetSystemTimeNV = (PFNEGLGETSYSTEMTIMENVPROC)glewGetProcAddress((const GLubyte*)"eglGetSystemTimeNV")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* EGL_NV_system_time */
+
+/* ------------------------------------------------------------------------ */
+
+GLboolean eglewGetExtension(const char* name)
+{
+ const GLubyte* start;
+ const GLubyte* end;
+
+ start = (GLubyte*)eglQueryString( eglGetCurrentDisplay() , EGL_EXTENSIONS);
+ if (0 == start) return GL_FALSE;
+ end = start + _glewStrLen(start);
+ return _glewSearchExtension(name, start, end);
+}
+
+GLenum eglewContextInit (EGLEW_CONTEXT_ARG_DEF_LIST)
+{
+ const GLubyte* s;
+ GLuint dot;
+ GLint major, minor;
+ const GLubyte* extStart;
+ const GLubyte* extEnd;
+ s = (GLubyte*)eglQueryString(display , EGL_VERSION);
+ dot = _glewStrCLen(s, '.');
+ if (dot == 0)
+ return GLEW_ERROR_NO_EGL_VERSION;
+
+ major = s[dot-1]-'0';
+ minor = s[dot+1]-'0';
+
+ if (minor < 0 || minor > 9)
+ minor = 0;
+ if (major<0 || major>9)
+ return GLEW_ERROR_NO_EGL_VERSION;
+
+
+ if (major == 1 && minor == 0)
+ {
+ return GLEW_ERROR_EGL_VERSION_10_ONLY;
+ }
+ else
+ {
+ CONST_CAST(EGLEW_VERSION_1_5) = ( major > 1 ) || ( major == 1 && minor >= 5 ) ? GL_TRUE : GL_FALSE;
+ CONST_CAST(EGLEW_VERSION_1_4) = EGLEW_VERSION_1_5 || ( major == 1 && minor >= 4 ) ? GL_TRUE : GL_FALSE;
+ CONST_CAST(EGLEW_VERSION_1_3) = EGLEW_VERSION_1_4 == GL_TRUE || ( major == 1 && minor >= 3 ) ? GL_TRUE : GL_FALSE;
+ CONST_CAST(EGLEW_VERSION_1_2) = EGLEW_VERSION_1_3 == GL_TRUE || ( major == 1 && minor >= 2 ) ? GL_TRUE : GL_FALSE;
+ CONST_CAST(EGLEW_VERSION_1_1) = EGLEW_VERSION_1_2 == GL_TRUE || ( major == 1 && minor >= 1 ) ? GL_TRUE : GL_FALSE;
+ }
+
+ /* query opengl extensions string */
+ extStart = (GLubyte*)eglQueryString( eglGetCurrentDisplay() , EGL_EXTENSIONS);
+ if (extStart == 0)
+ extStart = (const GLubyte*)"";
+ extEnd = extStart + _glewStrLen(extStart);
+
+ /* initialize extensions */
+
+#ifdef EGL_VERSION_1_2
+ if (glewExperimental || EGLEW_VERSION_1_2) CONST_CAST(EGLEW_VERSION_1_2) = !_glewInit_EGL_VERSION_1_2(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* EGL_VERSION_1_2 */
+#ifdef EGL_VERSION_1_3
+#endif /* EGL_VERSION_1_3 */
+#ifdef EGL_VERSION_1_4
+#endif /* EGL_VERSION_1_4 */
+#ifdef EGL_VERSION_1_5
+ if (glewExperimental || EGLEW_VERSION_1_5) CONST_CAST(EGLEW_VERSION_1_5) = !_glewInit_EGL_VERSION_1_5(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* EGL_VERSION_1_5 */
+#ifdef EGL_ANDROID_blob_cache
+ CONST_CAST(EGLEW_ANDROID_blob_cache) = _glewSearchExtension("EGL_ANDROID_blob_cache", extStart, extEnd);
+ if (glewExperimental || EGLEW_ANDROID_blob_cache) CONST_CAST(EGLEW_ANDROID_blob_cache) = !_glewInit_EGL_ANDROID_blob_cache(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* EGL_ANDROID_blob_cache */
+#ifdef EGL_ANDROID_framebuffer_target
+ CONST_CAST(EGLEW_ANDROID_framebuffer_target) = _glewSearchExtension("EGL_ANDROID_framebuffer_target", extStart, extEnd);
+#endif /* EGL_ANDROID_framebuffer_target */
+#ifdef EGL_ANDROID_image_native_buffer
+ CONST_CAST(EGLEW_ANDROID_image_native_buffer) = _glewSearchExtension("EGL_ANDROID_image_native_buffer", extStart, extEnd);
+#endif /* EGL_ANDROID_image_native_buffer */
+#ifdef EGL_ANDROID_native_fence_sync
+ CONST_CAST(EGLEW_ANDROID_native_fence_sync) = _glewSearchExtension("EGL_ANDROID_native_fence_sync", extStart, extEnd);
+ if (glewExperimental || EGLEW_ANDROID_native_fence_sync) CONST_CAST(EGLEW_ANDROID_native_fence_sync) = !_glewInit_EGL_ANDROID_native_fence_sync(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* EGL_ANDROID_native_fence_sync */
+#ifdef EGL_ANDROID_recordable
+ CONST_CAST(EGLEW_ANDROID_recordable) = _glewSearchExtension("EGL_ANDROID_recordable", extStart, extEnd);
+#endif /* EGL_ANDROID_recordable */
+#ifdef EGL_ANGLE_d3d_share_handle_client_buffer
+ CONST_CAST(EGLEW_ANGLE_d3d_share_handle_client_buffer) = _glewSearchExtension("EGL_ANGLE_d3d_share_handle_client_buffer", extStart, extEnd);
+#endif /* EGL_ANGLE_d3d_share_handle_client_buffer */
+#ifdef EGL_ANGLE_query_surface_pointer
+ CONST_CAST(EGLEW_ANGLE_query_surface_pointer) = _glewSearchExtension("EGL_ANGLE_query_surface_pointer", extStart, extEnd);
+ if (glewExperimental || EGLEW_ANGLE_query_surface_pointer) CONST_CAST(EGLEW_ANGLE_query_surface_pointer) = !_glewInit_EGL_ANGLE_query_surface_pointer(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* EGL_ANGLE_query_surface_pointer */
+#ifdef EGL_ANGLE_surface_d3d_texture_2d_share_handle
+ CONST_CAST(EGLEW_ANGLE_surface_d3d_texture_2d_share_handle) = _glewSearchExtension("EGL_ANGLE_surface_d3d_texture_2d_share_handle", extStart, extEnd);
+#endif /* EGL_ANGLE_surface_d3d_texture_2d_share_handle */
+#ifdef EGL_EXT_buffer_age
+ CONST_CAST(EGLEW_EXT_buffer_age) = _glewSearchExtension("EGL_EXT_buffer_age", extStart, extEnd);
+#endif /* EGL_EXT_buffer_age */
+#ifdef EGL_EXT_create_context_robustness
+ CONST_CAST(EGLEW_EXT_create_context_robustness) = _glewSearchExtension("EGL_EXT_create_context_robustness", extStart, extEnd);
+#endif /* EGL_EXT_create_context_robustness */
+#ifdef EGL_EXT_multiview_window
+ CONST_CAST(EGLEW_EXT_multiview_window) = _glewSearchExtension("EGL_EXT_multiview_window", extStart, extEnd);
+#endif /* EGL_EXT_multiview_window */
+#ifdef EGL_HI_clientpixmap
+ CONST_CAST(EGLEW_HI_clientpixmap) = _glewSearchExtension("EGL_HI_clientpixmap", extStart, extEnd);
+#endif /* EGL_HI_clientpixmap */
+#ifdef EGL_HI_colorformats
+ CONST_CAST(EGLEW_HI_colorformats) = _glewSearchExtension("EGL_HI_colorformats", extStart, extEnd);
+#endif /* EGL_HI_colorformats */
+#ifdef EGL_IMG_context_priority
+ CONST_CAST(EGLEW_IMG_context_priority) = _glewSearchExtension("EGL_IMG_context_priority", extStart, extEnd);
+#endif /* EGL_IMG_context_priority */
+#ifdef EGL_KHR_config_attribs
+ CONST_CAST(EGLEW_KHR_config_attribs) = _glewSearchExtension("EGL_KHR_config_attribs", extStart, extEnd);
+#endif /* EGL_KHR_config_attribs */
+#ifdef EGL_KHR_create_context
+ CONST_CAST(EGLEW_KHR_create_context) = _glewSearchExtension("EGL_KHR_create_context", extStart, extEnd);
+#endif /* EGL_KHR_create_context */
+#ifdef EGL_KHR_fence_sync
+ CONST_CAST(EGLEW_KHR_fence_sync) = _glewSearchExtension("EGL_KHR_fence_sync", extStart, extEnd);
+ if (glewExperimental || EGLEW_KHR_fence_sync) CONST_CAST(EGLEW_KHR_fence_sync) = !_glewInit_EGL_KHR_fence_sync(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* EGL_KHR_fence_sync */
+#ifdef EGL_KHR_gl_renderbuffer_image
+ CONST_CAST(EGLEW_KHR_gl_renderbuffer_image) = _glewSearchExtension("EGL_KHR_gl_renderbuffer_image", extStart, extEnd);
+#endif /* EGL_KHR_gl_renderbuffer_image */
+#ifdef EGL_KHR_gl_texture_2D_image
+ CONST_CAST(EGLEW_KHR_gl_texture_2D_image) = _glewSearchExtension("EGL_KHR_gl_texture_2D_image", extStart, extEnd);
+#endif /* EGL_KHR_gl_texture_2D_image */
+#ifdef EGL_KHR_gl_texture_3D_image
+ CONST_CAST(EGLEW_KHR_gl_texture_3D_image) = _glewSearchExtension("EGL_KHR_gl_texture_3D_image", extStart, extEnd);
+#endif /* EGL_KHR_gl_texture_3D_image */
+#ifdef EGL_KHR_gl_texture_cubemap_image
+ CONST_CAST(EGLEW_KHR_gl_texture_cubemap_image) = _glewSearchExtension("EGL_KHR_gl_texture_cubemap_image", extStart, extEnd);
+#endif /* EGL_KHR_gl_texture_cubemap_image */
+#ifdef EGL_KHR_image
+ CONST_CAST(EGLEW_KHR_image) = _glewSearchExtension("EGL_KHR_image", extStart, extEnd);
+#endif /* EGL_KHR_image */
+#ifdef EGL_KHR_image_base
+ CONST_CAST(EGLEW_KHR_image_base) = _glewSearchExtension("EGL_KHR_image_base", extStart, extEnd);
+ if (glewExperimental || EGLEW_KHR_image_base) CONST_CAST(EGLEW_KHR_image_base) = !_glewInit_EGL_KHR_image_base(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* EGL_KHR_image_base */
+#ifdef EGL_KHR_image_pixmap
+ CONST_CAST(EGLEW_KHR_image_pixmap) = _glewSearchExtension("EGL_KHR_image_pixmap", extStart, extEnd);
+#endif /* EGL_KHR_image_pixmap */
+#ifdef EGL_KHR_lock_surface
+ CONST_CAST(EGLEW_KHR_lock_surface) = _glewSearchExtension("EGL_KHR_lock_surface", extStart, extEnd);
+ if (glewExperimental || EGLEW_KHR_lock_surface) CONST_CAST(EGLEW_KHR_lock_surface) = !_glewInit_EGL_KHR_lock_surface(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* EGL_KHR_lock_surface */
+#ifdef EGL_KHR_lock_surface2
+ CONST_CAST(EGLEW_KHR_lock_surface2) = _glewSearchExtension("EGL_KHR_lock_surface2", extStart, extEnd);
+#endif /* EGL_KHR_lock_surface2 */
+#ifdef EGL_KHR_reusable_sync
+ CONST_CAST(EGLEW_KHR_reusable_sync) = _glewSearchExtension("EGL_KHR_reusable_sync", extStart, extEnd);
+ if (glewExperimental || EGLEW_KHR_reusable_sync) CONST_CAST(EGLEW_KHR_reusable_sync) = !_glewInit_EGL_KHR_reusable_sync(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* EGL_KHR_reusable_sync */
+#ifdef EGL_KHR_stream
+ CONST_CAST(EGLEW_KHR_stream) = _glewSearchExtension("EGL_KHR_stream", extStart, extEnd);
+#endif /* EGL_KHR_stream */
+#ifdef EGL_KHR_stream_consumer_gltexture
+ CONST_CAST(EGLEW_KHR_stream_consumer_gltexture) = _glewSearchExtension("EGL_KHR_stream_consumer_gltexture", extStart, extEnd);
+ if (glewExperimental || EGLEW_KHR_stream_consumer_gltexture) CONST_CAST(EGLEW_KHR_stream_consumer_gltexture) = !_glewInit_EGL_KHR_stream_consumer_gltexture(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* EGL_KHR_stream_consumer_gltexture */
+#ifdef EGL_KHR_stream_cross_process_fd
+ CONST_CAST(EGLEW_KHR_stream_cross_process_fd) = _glewSearchExtension("EGL_KHR_stream_cross_process_fd", extStart, extEnd);
+ if (glewExperimental || EGLEW_KHR_stream_cross_process_fd) CONST_CAST(EGLEW_KHR_stream_cross_process_fd) = !_glewInit_EGL_KHR_stream_cross_process_fd(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* EGL_KHR_stream_cross_process_fd */
+#ifdef EGL_KHR_stream_fifo
+ CONST_CAST(EGLEW_KHR_stream_fifo) = _glewSearchExtension("EGL_KHR_stream_fifo", extStart, extEnd);
+#endif /* EGL_KHR_stream_fifo */
+#ifdef EGL_KHR_stream_producer_aldatalocator
+ CONST_CAST(EGLEW_KHR_stream_producer_aldatalocator) = _glewSearchExtension("EGL_KHR_stream_producer_aldatalocator", extStart, extEnd);
+#endif /* EGL_KHR_stream_producer_aldatalocator */
+#ifdef EGL_KHR_stream_producer_eglsurface
+ CONST_CAST(EGLEW_KHR_stream_producer_eglsurface) = _glewSearchExtension("EGL_KHR_stream_producer_eglsurface", extStart, extEnd);
+ if (glewExperimental || EGLEW_KHR_stream_producer_eglsurface) CONST_CAST(EGLEW_KHR_stream_producer_eglsurface) = !_glewInit_EGL_KHR_stream_producer_eglsurface(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* EGL_KHR_stream_producer_eglsurface */
+#ifdef EGL_KHR_surfaceless_context
+ CONST_CAST(EGLEW_KHR_surfaceless_context) = _glewSearchExtension("EGL_KHR_surfaceless_context", extStart, extEnd);
+#endif /* EGL_KHR_surfaceless_context */
+#ifdef EGL_KHR_vg_parent_image
+ CONST_CAST(EGLEW_KHR_vg_parent_image) = _glewSearchExtension("EGL_KHR_vg_parent_image", extStart, extEnd);
+#endif /* EGL_KHR_vg_parent_image */
+#ifdef EGL_KHR_wait_sync
+ CONST_CAST(EGLEW_KHR_wait_sync) = _glewSearchExtension("EGL_KHR_wait_sync", extStart, extEnd);
+ if (glewExperimental || EGLEW_KHR_wait_sync) CONST_CAST(EGLEW_KHR_wait_sync) = !_glewInit_EGL_KHR_wait_sync(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* EGL_KHR_wait_sync */
+#ifdef EGL_MESA_drm_image
+ CONST_CAST(EGLEW_MESA_drm_image) = _glewSearchExtension("EGL_MESA_drm_image", extStart, extEnd);
+ if (glewExperimental || EGLEW_MESA_drm_image) CONST_CAST(EGLEW_MESA_drm_image) = !_glewInit_EGL_MESA_drm_image(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* EGL_MESA_drm_image */
+#ifdef EGL_NV_3dvision_surface
+ CONST_CAST(EGLEW_NV_3dvision_surface) = _glewSearchExtension("EGL_NV_3dvision_surface", extStart, extEnd);
+#endif /* EGL_NV_3dvision_surface */
+#ifdef EGL_NV_coverage_sample
+ CONST_CAST(EGLEW_NV_coverage_sample) = _glewSearchExtension("EGL_NV_coverage_sample", extStart, extEnd);
+#endif /* EGL_NV_coverage_sample */
+#ifdef EGL_NV_coverage_sample_resolve
+ CONST_CAST(EGLEW_NV_coverage_sample_resolve) = _glewSearchExtension("EGL_NV_coverage_sample_resolve", extStart, extEnd);
+#endif /* EGL_NV_coverage_sample_resolve */
+#ifdef EGL_NV_depth_nonlinear
+ CONST_CAST(EGLEW_NV_depth_nonlinear) = _glewSearchExtension("EGL_NV_depth_nonlinear", extStart, extEnd);
+#endif /* EGL_NV_depth_nonlinear */
+#ifdef EGL_NV_native_query
+ CONST_CAST(EGLEW_NV_native_query) = _glewSearchExtension("EGL_NV_native_query", extStart, extEnd);
+ if (glewExperimental || EGLEW_NV_native_query) CONST_CAST(EGLEW_NV_native_query) = !_glewInit_EGL_NV_native_query(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* EGL_NV_native_query */
+#ifdef EGL_NV_post_convert_rounding
+ CONST_CAST(EGLEW_NV_post_convert_rounding) = _glewSearchExtension("EGL_NV_post_convert_rounding", extStart, extEnd);
+#endif /* EGL_NV_post_convert_rounding */
+#ifdef EGL_NV_post_sub_buffer
+ CONST_CAST(EGLEW_NV_post_sub_buffer) = _glewSearchExtension("EGL_NV_post_sub_buffer", extStart, extEnd);
+ if (glewExperimental || EGLEW_NV_post_sub_buffer) CONST_CAST(EGLEW_NV_post_sub_buffer) = !_glewInit_EGL_NV_post_sub_buffer(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* EGL_NV_post_sub_buffer */
+#ifdef EGL_NV_sync
+ CONST_CAST(EGLEW_NV_sync) = _glewSearchExtension("EGL_NV_sync", extStart, extEnd);
+ if (glewExperimental || EGLEW_NV_sync) CONST_CAST(EGLEW_NV_sync) = !_glewInit_EGL_NV_sync(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* EGL_NV_sync */
+#ifdef EGL_NV_system_time
+ CONST_CAST(EGLEW_NV_system_time) = _glewSearchExtension("EGL_NV_system_time", extStart, extEnd);
+ if (glewExperimental || EGLEW_NV_system_time) CONST_CAST(EGLEW_NV_system_time) = !_glewInit_EGL_NV_system_time(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* EGL_NV_system_time */
+
+ return GLEW_OK;
+}
+
+#elif defined(_WIN32)
+
+#if !defined(GLEW_MX)
+
+PFNWGLSETSTEREOEMITTERSTATE3DLPROC __wglewSetStereoEmitterState3DL = NULL;
+
+PFNWGLBLITCONTEXTFRAMEBUFFERAMDPROC __wglewBlitContextFramebufferAMD = NULL;
+PFNWGLCREATEASSOCIATEDCONTEXTAMDPROC __wglewCreateAssociatedContextAMD = NULL;
+PFNWGLCREATEASSOCIATEDCONTEXTATTRIBSAMDPROC __wglewCreateAssociatedContextAttribsAMD = NULL;
+PFNWGLDELETEASSOCIATEDCONTEXTAMDPROC __wglewDeleteAssociatedContextAMD = NULL;
+PFNWGLGETCONTEXTGPUIDAMDPROC __wglewGetContextGPUIDAMD = NULL;
+PFNWGLGETCURRENTASSOCIATEDCONTEXTAMDPROC __wglewGetCurrentAssociatedContextAMD = NULL;
+PFNWGLGETGPUIDSAMDPROC __wglewGetGPUIDsAMD = NULL;
+PFNWGLGETGPUINFOAMDPROC __wglewGetGPUInfoAMD = NULL;
+PFNWGLMAKEASSOCIATEDCONTEXTCURRENTAMDPROC __wglewMakeAssociatedContextCurrentAMD = NULL;
+
+PFNWGLCREATEBUFFERREGIONARBPROC __wglewCreateBufferRegionARB = NULL;
+PFNWGLDELETEBUFFERREGIONARBPROC __wglewDeleteBufferRegionARB = NULL;
+PFNWGLRESTOREBUFFERREGIONARBPROC __wglewRestoreBufferRegionARB = NULL;
+PFNWGLSAVEBUFFERREGIONARBPROC __wglewSaveBufferRegionARB = NULL;
+
+PFNWGLCREATECONTEXTATTRIBSARBPROC __wglewCreateContextAttribsARB = NULL;
+
+PFNWGLGETEXTENSIONSSTRINGARBPROC __wglewGetExtensionsStringARB = NULL;
+
+PFNWGLGETCURRENTREADDCARBPROC __wglewGetCurrentReadDCARB = NULL;
+PFNWGLMAKECONTEXTCURRENTARBPROC __wglewMakeContextCurrentARB = NULL;
+
+PFNWGLCREATEPBUFFERARBPROC __wglewCreatePbufferARB = NULL;
+PFNWGLDESTROYPBUFFERARBPROC __wglewDestroyPbufferARB = NULL;
+PFNWGLGETPBUFFERDCARBPROC __wglewGetPbufferDCARB = NULL;
+PFNWGLQUERYPBUFFERARBPROC __wglewQueryPbufferARB = NULL;
+PFNWGLRELEASEPBUFFERDCARBPROC __wglewReleasePbufferDCARB = NULL;
+
+PFNWGLCHOOSEPIXELFORMATARBPROC __wglewChoosePixelFormatARB = NULL;
+PFNWGLGETPIXELFORMATATTRIBFVARBPROC __wglewGetPixelFormatAttribfvARB = NULL;
+PFNWGLGETPIXELFORMATATTRIBIVARBPROC __wglewGetPixelFormatAttribivARB = NULL;
+
+PFNWGLBINDTEXIMAGEARBPROC __wglewBindTexImageARB = NULL;
+PFNWGLRELEASETEXIMAGEARBPROC __wglewReleaseTexImageARB = NULL;
+PFNWGLSETPBUFFERATTRIBARBPROC __wglewSetPbufferAttribARB = NULL;
+
+PFNWGLBINDDISPLAYCOLORTABLEEXTPROC __wglewBindDisplayColorTableEXT = NULL;
+PFNWGLCREATEDISPLAYCOLORTABLEEXTPROC __wglewCreateDisplayColorTableEXT = NULL;
+PFNWGLDESTROYDISPLAYCOLORTABLEEXTPROC __wglewDestroyDisplayColorTableEXT = NULL;
+PFNWGLLOADDISPLAYCOLORTABLEEXTPROC __wglewLoadDisplayColorTableEXT = NULL;
+
+PFNWGLGETEXTENSIONSSTRINGEXTPROC __wglewGetExtensionsStringEXT = NULL;
+
+PFNWGLGETCURRENTREADDCEXTPROC __wglewGetCurrentReadDCEXT = NULL;
+PFNWGLMAKECONTEXTCURRENTEXTPROC __wglewMakeContextCurrentEXT = NULL;
+
+PFNWGLCREATEPBUFFEREXTPROC __wglewCreatePbufferEXT = NULL;
+PFNWGLDESTROYPBUFFEREXTPROC __wglewDestroyPbufferEXT = NULL;
+PFNWGLGETPBUFFERDCEXTPROC __wglewGetPbufferDCEXT = NULL;
+PFNWGLQUERYPBUFFEREXTPROC __wglewQueryPbufferEXT = NULL;
+PFNWGLRELEASEPBUFFERDCEXTPROC __wglewReleasePbufferDCEXT = NULL;
+
+PFNWGLCHOOSEPIXELFORMATEXTPROC __wglewChoosePixelFormatEXT = NULL;
+PFNWGLGETPIXELFORMATATTRIBFVEXTPROC __wglewGetPixelFormatAttribfvEXT = NULL;
+PFNWGLGETPIXELFORMATATTRIBIVEXTPROC __wglewGetPixelFormatAttribivEXT = NULL;
+
+PFNWGLGETSWAPINTERVALEXTPROC __wglewGetSwapIntervalEXT = NULL;
+PFNWGLSWAPINTERVALEXTPROC __wglewSwapIntervalEXT = NULL;
+
+PFNWGLGETDIGITALVIDEOPARAMETERSI3DPROC __wglewGetDigitalVideoParametersI3D = NULL;
+PFNWGLSETDIGITALVIDEOPARAMETERSI3DPROC __wglewSetDigitalVideoParametersI3D = NULL;
+
+PFNWGLGETGAMMATABLEI3DPROC __wglewGetGammaTableI3D = NULL;
+PFNWGLGETGAMMATABLEPARAMETERSI3DPROC __wglewGetGammaTableParametersI3D = NULL;
+PFNWGLSETGAMMATABLEI3DPROC __wglewSetGammaTableI3D = NULL;
+PFNWGLSETGAMMATABLEPARAMETERSI3DPROC __wglewSetGammaTableParametersI3D = NULL;
+
+PFNWGLDISABLEGENLOCKI3DPROC __wglewDisableGenlockI3D = NULL;
+PFNWGLENABLEGENLOCKI3DPROC __wglewEnableGenlockI3D = NULL;
+PFNWGLGENLOCKSAMPLERATEI3DPROC __wglewGenlockSampleRateI3D = NULL;
+PFNWGLGENLOCKSOURCEDELAYI3DPROC __wglewGenlockSourceDelayI3D = NULL;
+PFNWGLGENLOCKSOURCEEDGEI3DPROC __wglewGenlockSourceEdgeI3D = NULL;
+PFNWGLGENLOCKSOURCEI3DPROC __wglewGenlockSourceI3D = NULL;
+PFNWGLGETGENLOCKSAMPLERATEI3DPROC __wglewGetGenlockSampleRateI3D = NULL;
+PFNWGLGETGENLOCKSOURCEDELAYI3DPROC __wglewGetGenlockSourceDelayI3D = NULL;
+PFNWGLGETGENLOCKSOURCEEDGEI3DPROC __wglewGetGenlockSourceEdgeI3D = NULL;
+PFNWGLGETGENLOCKSOURCEI3DPROC __wglewGetGenlockSourceI3D = NULL;
+PFNWGLISENABLEDGENLOCKI3DPROC __wglewIsEnabledGenlockI3D = NULL;
+PFNWGLQUERYGENLOCKMAXSOURCEDELAYI3DPROC __wglewQueryGenlockMaxSourceDelayI3D = NULL;
+
+PFNWGLASSOCIATEIMAGEBUFFEREVENTSI3DPROC __wglewAssociateImageBufferEventsI3D = NULL;
+PFNWGLCREATEIMAGEBUFFERI3DPROC __wglewCreateImageBufferI3D = NULL;
+PFNWGLDESTROYIMAGEBUFFERI3DPROC __wglewDestroyImageBufferI3D = NULL;
+PFNWGLRELEASEIMAGEBUFFEREVENTSI3DPROC __wglewReleaseImageBufferEventsI3D = NULL;
+
+PFNWGLDISABLEFRAMELOCKI3DPROC __wglewDisableFrameLockI3D = NULL;
+PFNWGLENABLEFRAMELOCKI3DPROC __wglewEnableFrameLockI3D = NULL;
+PFNWGLISENABLEDFRAMELOCKI3DPROC __wglewIsEnabledFrameLockI3D = NULL;
+PFNWGLQUERYFRAMELOCKMASTERI3DPROC __wglewQueryFrameLockMasterI3D = NULL;
+
+PFNWGLBEGINFRAMETRACKINGI3DPROC __wglewBeginFrameTrackingI3D = NULL;
+PFNWGLENDFRAMETRACKINGI3DPROC __wglewEndFrameTrackingI3D = NULL;
+PFNWGLGETFRAMEUSAGEI3DPROC __wglewGetFrameUsageI3D = NULL;
+PFNWGLQUERYFRAMETRACKINGI3DPROC __wglewQueryFrameTrackingI3D = NULL;
+
+PFNWGLDXCLOSEDEVICENVPROC __wglewDXCloseDeviceNV = NULL;
+PFNWGLDXLOCKOBJECTSNVPROC __wglewDXLockObjectsNV = NULL;
+PFNWGLDXOBJECTACCESSNVPROC __wglewDXObjectAccessNV = NULL;
+PFNWGLDXOPENDEVICENVPROC __wglewDXOpenDeviceNV = NULL;
+PFNWGLDXREGISTEROBJECTNVPROC __wglewDXRegisterObjectNV = NULL;
+PFNWGLDXSETRESOURCESHAREHANDLENVPROC __wglewDXSetResourceShareHandleNV = NULL;
+PFNWGLDXUNLOCKOBJECTSNVPROC __wglewDXUnlockObjectsNV = NULL;
+PFNWGLDXUNREGISTEROBJECTNVPROC __wglewDXUnregisterObjectNV = NULL;
+
+PFNWGLCOPYIMAGESUBDATANVPROC __wglewCopyImageSubDataNV = NULL;
+
+PFNWGLCREATEAFFINITYDCNVPROC __wglewCreateAffinityDCNV = NULL;
+PFNWGLDELETEDCNVPROC __wglewDeleteDCNV = NULL;
+PFNWGLENUMGPUDEVICESNVPROC __wglewEnumGpuDevicesNV = NULL;
+PFNWGLENUMGPUSFROMAFFINITYDCNVPROC __wglewEnumGpusFromAffinityDCNV = NULL;
+PFNWGLENUMGPUSNVPROC __wglewEnumGpusNV = NULL;
+
+PFNWGLBINDVIDEODEVICENVPROC __wglewBindVideoDeviceNV = NULL;
+PFNWGLENUMERATEVIDEODEVICESNVPROC __wglewEnumerateVideoDevicesNV = NULL;
+PFNWGLQUERYCURRENTCONTEXTNVPROC __wglewQueryCurrentContextNV = NULL;
+
+PFNWGLBINDSWAPBARRIERNVPROC __wglewBindSwapBarrierNV = NULL;
+PFNWGLJOINSWAPGROUPNVPROC __wglewJoinSwapGroupNV = NULL;
+PFNWGLQUERYFRAMECOUNTNVPROC __wglewQueryFrameCountNV = NULL;
+PFNWGLQUERYMAXSWAPGROUPSNVPROC __wglewQueryMaxSwapGroupsNV = NULL;
+PFNWGLQUERYSWAPGROUPNVPROC __wglewQuerySwapGroupNV = NULL;
+PFNWGLRESETFRAMECOUNTNVPROC __wglewResetFrameCountNV = NULL;
+
+PFNWGLALLOCATEMEMORYNVPROC __wglewAllocateMemoryNV = NULL;
+PFNWGLFREEMEMORYNVPROC __wglewFreeMemoryNV = NULL;
+
+PFNWGLBINDVIDEOCAPTUREDEVICENVPROC __wglewBindVideoCaptureDeviceNV = NULL;
+PFNWGLENUMERATEVIDEOCAPTUREDEVICESNVPROC __wglewEnumerateVideoCaptureDevicesNV = NULL;
+PFNWGLLOCKVIDEOCAPTUREDEVICENVPROC __wglewLockVideoCaptureDeviceNV = NULL;
+PFNWGLQUERYVIDEOCAPTUREDEVICENVPROC __wglewQueryVideoCaptureDeviceNV = NULL;
+PFNWGLRELEASEVIDEOCAPTUREDEVICENVPROC __wglewReleaseVideoCaptureDeviceNV = NULL;
+
+PFNWGLBINDVIDEOIMAGENVPROC __wglewBindVideoImageNV = NULL;
+PFNWGLGETVIDEODEVICENVPROC __wglewGetVideoDeviceNV = NULL;
+PFNWGLGETVIDEOINFONVPROC __wglewGetVideoInfoNV = NULL;
+PFNWGLRELEASEVIDEODEVICENVPROC __wglewReleaseVideoDeviceNV = NULL;
+PFNWGLRELEASEVIDEOIMAGENVPROC __wglewReleaseVideoImageNV = NULL;
+PFNWGLSENDPBUFFERTOVIDEONVPROC __wglewSendPbufferToVideoNV = NULL;
+
+PFNWGLGETMSCRATEOMLPROC __wglewGetMscRateOML = NULL;
+PFNWGLGETSYNCVALUESOMLPROC __wglewGetSyncValuesOML = NULL;
+PFNWGLSWAPBUFFERSMSCOMLPROC __wglewSwapBuffersMscOML = NULL;
+PFNWGLSWAPLAYERBUFFERSMSCOMLPROC __wglewSwapLayerBuffersMscOML = NULL;
+PFNWGLWAITFORMSCOMLPROC __wglewWaitForMscOML = NULL;
+PFNWGLWAITFORSBCOMLPROC __wglewWaitForSbcOML = NULL;
+GLboolean __WGLEW_3DFX_multisample = GL_FALSE;
+GLboolean __WGLEW_3DL_stereo_control = GL_FALSE;
+GLboolean __WGLEW_AMD_gpu_association = GL_FALSE;
+GLboolean __WGLEW_ARB_buffer_region = GL_FALSE;
+GLboolean __WGLEW_ARB_create_context = GL_FALSE;
+GLboolean __WGLEW_ARB_create_context_profile = GL_FALSE;
+GLboolean __WGLEW_ARB_create_context_robustness = GL_FALSE;
+GLboolean __WGLEW_ARB_extensions_string = GL_FALSE;
+GLboolean __WGLEW_ARB_framebuffer_sRGB = GL_FALSE;
+GLboolean __WGLEW_ARB_make_current_read = GL_FALSE;
+GLboolean __WGLEW_ARB_multisample = GL_FALSE;
+GLboolean __WGLEW_ARB_pbuffer = GL_FALSE;
+GLboolean __WGLEW_ARB_pixel_format = GL_FALSE;
+GLboolean __WGLEW_ARB_pixel_format_float = GL_FALSE;
+GLboolean __WGLEW_ARB_render_texture = GL_FALSE;
+GLboolean __WGLEW_ARB_robustness_application_isolation = GL_FALSE;
+GLboolean __WGLEW_ARB_robustness_share_group_isolation = GL_FALSE;
+GLboolean __WGLEW_ATI_pixel_format_float = GL_FALSE;
+GLboolean __WGLEW_ATI_render_texture_rectangle = GL_FALSE;
+GLboolean __WGLEW_EXT_create_context_es2_profile = GL_FALSE;
+GLboolean __WGLEW_EXT_create_context_es_profile = GL_FALSE;
+GLboolean __WGLEW_EXT_depth_float = GL_FALSE;
+GLboolean __WGLEW_EXT_display_color_table = GL_FALSE;
+GLboolean __WGLEW_EXT_extensions_string = GL_FALSE;
+GLboolean __WGLEW_EXT_framebuffer_sRGB = GL_FALSE;
+GLboolean __WGLEW_EXT_make_current_read = GL_FALSE;
+GLboolean __WGLEW_EXT_multisample = GL_FALSE;
+GLboolean __WGLEW_EXT_pbuffer = GL_FALSE;
+GLboolean __WGLEW_EXT_pixel_format = GL_FALSE;
+GLboolean __WGLEW_EXT_pixel_format_packed_float = GL_FALSE;
+GLboolean __WGLEW_EXT_swap_control = GL_FALSE;
+GLboolean __WGLEW_EXT_swap_control_tear = GL_FALSE;
+GLboolean __WGLEW_I3D_digital_video_control = GL_FALSE;
+GLboolean __WGLEW_I3D_gamma = GL_FALSE;
+GLboolean __WGLEW_I3D_genlock = GL_FALSE;
+GLboolean __WGLEW_I3D_image_buffer = GL_FALSE;
+GLboolean __WGLEW_I3D_swap_frame_lock = GL_FALSE;
+GLboolean __WGLEW_I3D_swap_frame_usage = GL_FALSE;
+GLboolean __WGLEW_NV_DX_interop = GL_FALSE;
+GLboolean __WGLEW_NV_DX_interop2 = GL_FALSE;
+GLboolean __WGLEW_NV_copy_image = GL_FALSE;
+GLboolean __WGLEW_NV_float_buffer = GL_FALSE;
+GLboolean __WGLEW_NV_gpu_affinity = GL_FALSE;
+GLboolean __WGLEW_NV_multisample_coverage = GL_FALSE;
+GLboolean __WGLEW_NV_present_video = GL_FALSE;
+GLboolean __WGLEW_NV_render_depth_texture = GL_FALSE;
+GLboolean __WGLEW_NV_render_texture_rectangle = GL_FALSE;
+GLboolean __WGLEW_NV_swap_group = GL_FALSE;
+GLboolean __WGLEW_NV_vertex_array_range = GL_FALSE;
+GLboolean __WGLEW_NV_video_capture = GL_FALSE;
+GLboolean __WGLEW_NV_video_output = GL_FALSE;
+GLboolean __WGLEW_OML_sync_control = GL_FALSE;
+
+#endif /* !GLEW_MX */
+
+#ifdef WGL_3DFX_multisample
+
+#endif /* WGL_3DFX_multisample */
+
+#ifdef WGL_3DL_stereo_control
+
+static GLboolean _glewInit_WGL_3DL_stereo_control (WGLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((wglSetStereoEmitterState3DL = (PFNWGLSETSTEREOEMITTERSTATE3DLPROC)glewGetProcAddress((const GLubyte*)"wglSetStereoEmitterState3DL")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* WGL_3DL_stereo_control */
+
+#ifdef WGL_AMD_gpu_association
+
+static GLboolean _glewInit_WGL_AMD_gpu_association (WGLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((wglBlitContextFramebufferAMD = (PFNWGLBLITCONTEXTFRAMEBUFFERAMDPROC)glewGetProcAddress((const GLubyte*)"wglBlitContextFramebufferAMD")) == NULL) || r;
+ r = ((wglCreateAssociatedContextAMD = (PFNWGLCREATEASSOCIATEDCONTEXTAMDPROC)glewGetProcAddress((const GLubyte*)"wglCreateAssociatedContextAMD")) == NULL) || r;
+ r = ((wglCreateAssociatedContextAttribsAMD = (PFNWGLCREATEASSOCIATEDCONTEXTATTRIBSAMDPROC)glewGetProcAddress((const GLubyte*)"wglCreateAssociatedContextAttribsAMD")) == NULL) || r;
+ r = ((wglDeleteAssociatedContextAMD = (PFNWGLDELETEASSOCIATEDCONTEXTAMDPROC)glewGetProcAddress((const GLubyte*)"wglDeleteAssociatedContextAMD")) == NULL) || r;
+ r = ((wglGetContextGPUIDAMD = (PFNWGLGETCONTEXTGPUIDAMDPROC)glewGetProcAddress((const GLubyte*)"wglGetContextGPUIDAMD")) == NULL) || r;
+ r = ((wglGetCurrentAssociatedContextAMD = (PFNWGLGETCURRENTASSOCIATEDCONTEXTAMDPROC)glewGetProcAddress((const GLubyte*)"wglGetCurrentAssociatedContextAMD")) == NULL) || r;
+ r = ((wglGetGPUIDsAMD = (PFNWGLGETGPUIDSAMDPROC)glewGetProcAddress((const GLubyte*)"wglGetGPUIDsAMD")) == NULL) || r;
+ r = ((wglGetGPUInfoAMD = (PFNWGLGETGPUINFOAMDPROC)glewGetProcAddress((const GLubyte*)"wglGetGPUInfoAMD")) == NULL) || r;
+ r = ((wglMakeAssociatedContextCurrentAMD = (PFNWGLMAKEASSOCIATEDCONTEXTCURRENTAMDPROC)glewGetProcAddress((const GLubyte*)"wglMakeAssociatedContextCurrentAMD")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* WGL_AMD_gpu_association */
+
+#ifdef WGL_ARB_buffer_region
+
+static GLboolean _glewInit_WGL_ARB_buffer_region (WGLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((wglCreateBufferRegionARB = (PFNWGLCREATEBUFFERREGIONARBPROC)glewGetProcAddress((const GLubyte*)"wglCreateBufferRegionARB")) == NULL) || r;
+ r = ((wglDeleteBufferRegionARB = (PFNWGLDELETEBUFFERREGIONARBPROC)glewGetProcAddress((const GLubyte*)"wglDeleteBufferRegionARB")) == NULL) || r;
+ r = ((wglRestoreBufferRegionARB = (PFNWGLRESTOREBUFFERREGIONARBPROC)glewGetProcAddress((const GLubyte*)"wglRestoreBufferRegionARB")) == NULL) || r;
+ r = ((wglSaveBufferRegionARB = (PFNWGLSAVEBUFFERREGIONARBPROC)glewGetProcAddress((const GLubyte*)"wglSaveBufferRegionARB")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* WGL_ARB_buffer_region */
+
+#ifdef WGL_ARB_create_context
+
+static GLboolean _glewInit_WGL_ARB_create_context (WGLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((wglCreateContextAttribsARB = (PFNWGLCREATECONTEXTATTRIBSARBPROC)glewGetProcAddress((const GLubyte*)"wglCreateContextAttribsARB")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* WGL_ARB_create_context */
+
+#ifdef WGL_ARB_create_context_profile
+
+#endif /* WGL_ARB_create_context_profile */
+
+#ifdef WGL_ARB_create_context_robustness
+
+#endif /* WGL_ARB_create_context_robustness */
+
+#ifdef WGL_ARB_extensions_string
+
+static GLboolean _glewInit_WGL_ARB_extensions_string (WGLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((wglGetExtensionsStringARB = (PFNWGLGETEXTENSIONSSTRINGARBPROC)glewGetProcAddress((const GLubyte*)"wglGetExtensionsStringARB")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* WGL_ARB_extensions_string */
+
+#ifdef WGL_ARB_framebuffer_sRGB
+
+#endif /* WGL_ARB_framebuffer_sRGB */
+
+#ifdef WGL_ARB_make_current_read
+
+static GLboolean _glewInit_WGL_ARB_make_current_read (WGLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((wglGetCurrentReadDCARB = (PFNWGLGETCURRENTREADDCARBPROC)glewGetProcAddress((const GLubyte*)"wglGetCurrentReadDCARB")) == NULL) || r;
+ r = ((wglMakeContextCurrentARB = (PFNWGLMAKECONTEXTCURRENTARBPROC)glewGetProcAddress((const GLubyte*)"wglMakeContextCurrentARB")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* WGL_ARB_make_current_read */
+
+#ifdef WGL_ARB_multisample
+
+#endif /* WGL_ARB_multisample */
+
+#ifdef WGL_ARB_pbuffer
+
+static GLboolean _glewInit_WGL_ARB_pbuffer (WGLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((wglCreatePbufferARB = (PFNWGLCREATEPBUFFERARBPROC)glewGetProcAddress((const GLubyte*)"wglCreatePbufferARB")) == NULL) || r;
+ r = ((wglDestroyPbufferARB = (PFNWGLDESTROYPBUFFERARBPROC)glewGetProcAddress((const GLubyte*)"wglDestroyPbufferARB")) == NULL) || r;
+ r = ((wglGetPbufferDCARB = (PFNWGLGETPBUFFERDCARBPROC)glewGetProcAddress((const GLubyte*)"wglGetPbufferDCARB")) == NULL) || r;
+ r = ((wglQueryPbufferARB = (PFNWGLQUERYPBUFFERARBPROC)glewGetProcAddress((const GLubyte*)"wglQueryPbufferARB")) == NULL) || r;
+ r = ((wglReleasePbufferDCARB = (PFNWGLRELEASEPBUFFERDCARBPROC)glewGetProcAddress((const GLubyte*)"wglReleasePbufferDCARB")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* WGL_ARB_pbuffer */
+
+#ifdef WGL_ARB_pixel_format
+
+static GLboolean _glewInit_WGL_ARB_pixel_format (WGLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((wglChoosePixelFormatARB = (PFNWGLCHOOSEPIXELFORMATARBPROC)glewGetProcAddress((const GLubyte*)"wglChoosePixelFormatARB")) == NULL) || r;
+ r = ((wglGetPixelFormatAttribfvARB = (PFNWGLGETPIXELFORMATATTRIBFVARBPROC)glewGetProcAddress((const GLubyte*)"wglGetPixelFormatAttribfvARB")) == NULL) || r;
+ r = ((wglGetPixelFormatAttribivARB = (PFNWGLGETPIXELFORMATATTRIBIVARBPROC)glewGetProcAddress((const GLubyte*)"wglGetPixelFormatAttribivARB")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* WGL_ARB_pixel_format */
+
+#ifdef WGL_ARB_pixel_format_float
+
+#endif /* WGL_ARB_pixel_format_float */
+
+#ifdef WGL_ARB_render_texture
+
+static GLboolean _glewInit_WGL_ARB_render_texture (WGLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((wglBindTexImageARB = (PFNWGLBINDTEXIMAGEARBPROC)glewGetProcAddress((const GLubyte*)"wglBindTexImageARB")) == NULL) || r;
+ r = ((wglReleaseTexImageARB = (PFNWGLRELEASETEXIMAGEARBPROC)glewGetProcAddress((const GLubyte*)"wglReleaseTexImageARB")) == NULL) || r;
+ r = ((wglSetPbufferAttribARB = (PFNWGLSETPBUFFERATTRIBARBPROC)glewGetProcAddress((const GLubyte*)"wglSetPbufferAttribARB")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* WGL_ARB_render_texture */
+
+#ifdef WGL_ARB_robustness_application_isolation
+
+#endif /* WGL_ARB_robustness_application_isolation */
+
+#ifdef WGL_ARB_robustness_share_group_isolation
+
+#endif /* WGL_ARB_robustness_share_group_isolation */
+
+#ifdef WGL_ATI_pixel_format_float
+
+#endif /* WGL_ATI_pixel_format_float */
+
+#ifdef WGL_ATI_render_texture_rectangle
+
+#endif /* WGL_ATI_render_texture_rectangle */
+
+#ifdef WGL_EXT_create_context_es2_profile
+
+#endif /* WGL_EXT_create_context_es2_profile */
+
+#ifdef WGL_EXT_create_context_es_profile
+
+#endif /* WGL_EXT_create_context_es_profile */
+
+#ifdef WGL_EXT_depth_float
+
+#endif /* WGL_EXT_depth_float */
+
+#ifdef WGL_EXT_display_color_table
+
+static GLboolean _glewInit_WGL_EXT_display_color_table (WGLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((wglBindDisplayColorTableEXT = (PFNWGLBINDDISPLAYCOLORTABLEEXTPROC)glewGetProcAddress((const GLubyte*)"wglBindDisplayColorTableEXT")) == NULL) || r;
+ r = ((wglCreateDisplayColorTableEXT = (PFNWGLCREATEDISPLAYCOLORTABLEEXTPROC)glewGetProcAddress((const GLubyte*)"wglCreateDisplayColorTableEXT")) == NULL) || r;
+ r = ((wglDestroyDisplayColorTableEXT = (PFNWGLDESTROYDISPLAYCOLORTABLEEXTPROC)glewGetProcAddress((const GLubyte*)"wglDestroyDisplayColorTableEXT")) == NULL) || r;
+ r = ((wglLoadDisplayColorTableEXT = (PFNWGLLOADDISPLAYCOLORTABLEEXTPROC)glewGetProcAddress((const GLubyte*)"wglLoadDisplayColorTableEXT")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* WGL_EXT_display_color_table */
+
+#ifdef WGL_EXT_extensions_string
+
+static GLboolean _glewInit_WGL_EXT_extensions_string (WGLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((wglGetExtensionsStringEXT = (PFNWGLGETEXTENSIONSSTRINGEXTPROC)glewGetProcAddress((const GLubyte*)"wglGetExtensionsStringEXT")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* WGL_EXT_extensions_string */
+
+#ifdef WGL_EXT_framebuffer_sRGB
+
+#endif /* WGL_EXT_framebuffer_sRGB */
+
+#ifdef WGL_EXT_make_current_read
+
+static GLboolean _glewInit_WGL_EXT_make_current_read (WGLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((wglGetCurrentReadDCEXT = (PFNWGLGETCURRENTREADDCEXTPROC)glewGetProcAddress((const GLubyte*)"wglGetCurrentReadDCEXT")) == NULL) || r;
+ r = ((wglMakeContextCurrentEXT = (PFNWGLMAKECONTEXTCURRENTEXTPROC)glewGetProcAddress((const GLubyte*)"wglMakeContextCurrentEXT")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* WGL_EXT_make_current_read */
+
+#ifdef WGL_EXT_multisample
+
+#endif /* WGL_EXT_multisample */
+
+#ifdef WGL_EXT_pbuffer
+
+static GLboolean _glewInit_WGL_EXT_pbuffer (WGLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((wglCreatePbufferEXT = (PFNWGLCREATEPBUFFEREXTPROC)glewGetProcAddress((const GLubyte*)"wglCreatePbufferEXT")) == NULL) || r;
+ r = ((wglDestroyPbufferEXT = (PFNWGLDESTROYPBUFFEREXTPROC)glewGetProcAddress((const GLubyte*)"wglDestroyPbufferEXT")) == NULL) || r;
+ r = ((wglGetPbufferDCEXT = (PFNWGLGETPBUFFERDCEXTPROC)glewGetProcAddress((const GLubyte*)"wglGetPbufferDCEXT")) == NULL) || r;
+ r = ((wglQueryPbufferEXT = (PFNWGLQUERYPBUFFEREXTPROC)glewGetProcAddress((const GLubyte*)"wglQueryPbufferEXT")) == NULL) || r;
+ r = ((wglReleasePbufferDCEXT = (PFNWGLRELEASEPBUFFERDCEXTPROC)glewGetProcAddress((const GLubyte*)"wglReleasePbufferDCEXT")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* WGL_EXT_pbuffer */
+
+#ifdef WGL_EXT_pixel_format
+
+static GLboolean _glewInit_WGL_EXT_pixel_format (WGLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((wglChoosePixelFormatEXT = (PFNWGLCHOOSEPIXELFORMATEXTPROC)glewGetProcAddress((const GLubyte*)"wglChoosePixelFormatEXT")) == NULL) || r;
+ r = ((wglGetPixelFormatAttribfvEXT = (PFNWGLGETPIXELFORMATATTRIBFVEXTPROC)glewGetProcAddress((const GLubyte*)"wglGetPixelFormatAttribfvEXT")) == NULL) || r;
+ r = ((wglGetPixelFormatAttribivEXT = (PFNWGLGETPIXELFORMATATTRIBIVEXTPROC)glewGetProcAddress((const GLubyte*)"wglGetPixelFormatAttribivEXT")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* WGL_EXT_pixel_format */
+
+#ifdef WGL_EXT_pixel_format_packed_float
+
+#endif /* WGL_EXT_pixel_format_packed_float */
+
+#ifdef WGL_EXT_swap_control
+
+static GLboolean _glewInit_WGL_EXT_swap_control (WGLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((wglGetSwapIntervalEXT = (PFNWGLGETSWAPINTERVALEXTPROC)glewGetProcAddress((const GLubyte*)"wglGetSwapIntervalEXT")) == NULL) || r;
+ r = ((wglSwapIntervalEXT = (PFNWGLSWAPINTERVALEXTPROC)glewGetProcAddress((const GLubyte*)"wglSwapIntervalEXT")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* WGL_EXT_swap_control */
+
+#ifdef WGL_EXT_swap_control_tear
+
+#endif /* WGL_EXT_swap_control_tear */
+
+#ifdef WGL_I3D_digital_video_control
+
+static GLboolean _glewInit_WGL_I3D_digital_video_control (WGLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((wglGetDigitalVideoParametersI3D = (PFNWGLGETDIGITALVIDEOPARAMETERSI3DPROC)glewGetProcAddress((const GLubyte*)"wglGetDigitalVideoParametersI3D")) == NULL) || r;
+ r = ((wglSetDigitalVideoParametersI3D = (PFNWGLSETDIGITALVIDEOPARAMETERSI3DPROC)glewGetProcAddress((const GLubyte*)"wglSetDigitalVideoParametersI3D")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* WGL_I3D_digital_video_control */
+
+#ifdef WGL_I3D_gamma
+
+static GLboolean _glewInit_WGL_I3D_gamma (WGLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((wglGetGammaTableI3D = (PFNWGLGETGAMMATABLEI3DPROC)glewGetProcAddress((const GLubyte*)"wglGetGammaTableI3D")) == NULL) || r;
+ r = ((wglGetGammaTableParametersI3D = (PFNWGLGETGAMMATABLEPARAMETERSI3DPROC)glewGetProcAddress((const GLubyte*)"wglGetGammaTableParametersI3D")) == NULL) || r;
+ r = ((wglSetGammaTableI3D = (PFNWGLSETGAMMATABLEI3DPROC)glewGetProcAddress((const GLubyte*)"wglSetGammaTableI3D")) == NULL) || r;
+ r = ((wglSetGammaTableParametersI3D = (PFNWGLSETGAMMATABLEPARAMETERSI3DPROC)glewGetProcAddress((const GLubyte*)"wglSetGammaTableParametersI3D")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* WGL_I3D_gamma */
+
+#ifdef WGL_I3D_genlock
+
+static GLboolean _glewInit_WGL_I3D_genlock (WGLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((wglDisableGenlockI3D = (PFNWGLDISABLEGENLOCKI3DPROC)glewGetProcAddress((const GLubyte*)"wglDisableGenlockI3D")) == NULL) || r;
+ r = ((wglEnableGenlockI3D = (PFNWGLENABLEGENLOCKI3DPROC)glewGetProcAddress((const GLubyte*)"wglEnableGenlockI3D")) == NULL) || r;
+ r = ((wglGenlockSampleRateI3D = (PFNWGLGENLOCKSAMPLERATEI3DPROC)glewGetProcAddress((const GLubyte*)"wglGenlockSampleRateI3D")) == NULL) || r;
+ r = ((wglGenlockSourceDelayI3D = (PFNWGLGENLOCKSOURCEDELAYI3DPROC)glewGetProcAddress((const GLubyte*)"wglGenlockSourceDelayI3D")) == NULL) || r;
+ r = ((wglGenlockSourceEdgeI3D = (PFNWGLGENLOCKSOURCEEDGEI3DPROC)glewGetProcAddress((const GLubyte*)"wglGenlockSourceEdgeI3D")) == NULL) || r;
+ r = ((wglGenlockSourceI3D = (PFNWGLGENLOCKSOURCEI3DPROC)glewGetProcAddress((const GLubyte*)"wglGenlockSourceI3D")) == NULL) || r;
+ r = ((wglGetGenlockSampleRateI3D = (PFNWGLGETGENLOCKSAMPLERATEI3DPROC)glewGetProcAddress((const GLubyte*)"wglGetGenlockSampleRateI3D")) == NULL) || r;
+ r = ((wglGetGenlockSourceDelayI3D = (PFNWGLGETGENLOCKSOURCEDELAYI3DPROC)glewGetProcAddress((const GLubyte*)"wglGetGenlockSourceDelayI3D")) == NULL) || r;
+ r = ((wglGetGenlockSourceEdgeI3D = (PFNWGLGETGENLOCKSOURCEEDGEI3DPROC)glewGetProcAddress((const GLubyte*)"wglGetGenlockSourceEdgeI3D")) == NULL) || r;
+ r = ((wglGetGenlockSourceI3D = (PFNWGLGETGENLOCKSOURCEI3DPROC)glewGetProcAddress((const GLubyte*)"wglGetGenlockSourceI3D")) == NULL) || r;
+ r = ((wglIsEnabledGenlockI3D = (PFNWGLISENABLEDGENLOCKI3DPROC)glewGetProcAddress((const GLubyte*)"wglIsEnabledGenlockI3D")) == NULL) || r;
+ r = ((wglQueryGenlockMaxSourceDelayI3D = (PFNWGLQUERYGENLOCKMAXSOURCEDELAYI3DPROC)glewGetProcAddress((const GLubyte*)"wglQueryGenlockMaxSourceDelayI3D")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* WGL_I3D_genlock */
+
+#ifdef WGL_I3D_image_buffer
+
+static GLboolean _glewInit_WGL_I3D_image_buffer (WGLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((wglAssociateImageBufferEventsI3D = (PFNWGLASSOCIATEIMAGEBUFFEREVENTSI3DPROC)glewGetProcAddress((const GLubyte*)"wglAssociateImageBufferEventsI3D")) == NULL) || r;
+ r = ((wglCreateImageBufferI3D = (PFNWGLCREATEIMAGEBUFFERI3DPROC)glewGetProcAddress((const GLubyte*)"wglCreateImageBufferI3D")) == NULL) || r;
+ r = ((wglDestroyImageBufferI3D = (PFNWGLDESTROYIMAGEBUFFERI3DPROC)glewGetProcAddress((const GLubyte*)"wglDestroyImageBufferI3D")) == NULL) || r;
+ r = ((wglReleaseImageBufferEventsI3D = (PFNWGLRELEASEIMAGEBUFFEREVENTSI3DPROC)glewGetProcAddress((const GLubyte*)"wglReleaseImageBufferEventsI3D")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* WGL_I3D_image_buffer */
+
+#ifdef WGL_I3D_swap_frame_lock
+
+static GLboolean _glewInit_WGL_I3D_swap_frame_lock (WGLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((wglDisableFrameLockI3D = (PFNWGLDISABLEFRAMELOCKI3DPROC)glewGetProcAddress((const GLubyte*)"wglDisableFrameLockI3D")) == NULL) || r;
+ r = ((wglEnableFrameLockI3D = (PFNWGLENABLEFRAMELOCKI3DPROC)glewGetProcAddress((const GLubyte*)"wglEnableFrameLockI3D")) == NULL) || r;
+ r = ((wglIsEnabledFrameLockI3D = (PFNWGLISENABLEDFRAMELOCKI3DPROC)glewGetProcAddress((const GLubyte*)"wglIsEnabledFrameLockI3D")) == NULL) || r;
+ r = ((wglQueryFrameLockMasterI3D = (PFNWGLQUERYFRAMELOCKMASTERI3DPROC)glewGetProcAddress((const GLubyte*)"wglQueryFrameLockMasterI3D")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* WGL_I3D_swap_frame_lock */
+
+#ifdef WGL_I3D_swap_frame_usage
+
+static GLboolean _glewInit_WGL_I3D_swap_frame_usage (WGLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((wglBeginFrameTrackingI3D = (PFNWGLBEGINFRAMETRACKINGI3DPROC)glewGetProcAddress((const GLubyte*)"wglBeginFrameTrackingI3D")) == NULL) || r;
+ r = ((wglEndFrameTrackingI3D = (PFNWGLENDFRAMETRACKINGI3DPROC)glewGetProcAddress((const GLubyte*)"wglEndFrameTrackingI3D")) == NULL) || r;
+ r = ((wglGetFrameUsageI3D = (PFNWGLGETFRAMEUSAGEI3DPROC)glewGetProcAddress((const GLubyte*)"wglGetFrameUsageI3D")) == NULL) || r;
+ r = ((wglQueryFrameTrackingI3D = (PFNWGLQUERYFRAMETRACKINGI3DPROC)glewGetProcAddress((const GLubyte*)"wglQueryFrameTrackingI3D")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* WGL_I3D_swap_frame_usage */
+
+#ifdef WGL_NV_DX_interop
+
+static GLboolean _glewInit_WGL_NV_DX_interop (WGLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((wglDXCloseDeviceNV = (PFNWGLDXCLOSEDEVICENVPROC)glewGetProcAddress((const GLubyte*)"wglDXCloseDeviceNV")) == NULL) || r;
+ r = ((wglDXLockObjectsNV = (PFNWGLDXLOCKOBJECTSNVPROC)glewGetProcAddress((const GLubyte*)"wglDXLockObjectsNV")) == NULL) || r;
+ r = ((wglDXObjectAccessNV = (PFNWGLDXOBJECTACCESSNVPROC)glewGetProcAddress((const GLubyte*)"wglDXObjectAccessNV")) == NULL) || r;
+ r = ((wglDXOpenDeviceNV = (PFNWGLDXOPENDEVICENVPROC)glewGetProcAddress((const GLubyte*)"wglDXOpenDeviceNV")) == NULL) || r;
+ r = ((wglDXRegisterObjectNV = (PFNWGLDXREGISTEROBJECTNVPROC)glewGetProcAddress((const GLubyte*)"wglDXRegisterObjectNV")) == NULL) || r;
+ r = ((wglDXSetResourceShareHandleNV = (PFNWGLDXSETRESOURCESHAREHANDLENVPROC)glewGetProcAddress((const GLubyte*)"wglDXSetResourceShareHandleNV")) == NULL) || r;
+ r = ((wglDXUnlockObjectsNV = (PFNWGLDXUNLOCKOBJECTSNVPROC)glewGetProcAddress((const GLubyte*)"wglDXUnlockObjectsNV")) == NULL) || r;
+ r = ((wglDXUnregisterObjectNV = (PFNWGLDXUNREGISTEROBJECTNVPROC)glewGetProcAddress((const GLubyte*)"wglDXUnregisterObjectNV")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* WGL_NV_DX_interop */
+
+#ifdef WGL_NV_DX_interop2
+
+#endif /* WGL_NV_DX_interop2 */
+
+#ifdef WGL_NV_copy_image
+
+static GLboolean _glewInit_WGL_NV_copy_image (WGLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((wglCopyImageSubDataNV = (PFNWGLCOPYIMAGESUBDATANVPROC)glewGetProcAddress((const GLubyte*)"wglCopyImageSubDataNV")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* WGL_NV_copy_image */
+
+#ifdef WGL_NV_float_buffer
+
+#endif /* WGL_NV_float_buffer */
+
+#ifdef WGL_NV_gpu_affinity
+
+static GLboolean _glewInit_WGL_NV_gpu_affinity (WGLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((wglCreateAffinityDCNV = (PFNWGLCREATEAFFINITYDCNVPROC)glewGetProcAddress((const GLubyte*)"wglCreateAffinityDCNV")) == NULL) || r;
+ r = ((wglDeleteDCNV = (PFNWGLDELETEDCNVPROC)glewGetProcAddress((const GLubyte*)"wglDeleteDCNV")) == NULL) || r;
+ r = ((wglEnumGpuDevicesNV = (PFNWGLENUMGPUDEVICESNVPROC)glewGetProcAddress((const GLubyte*)"wglEnumGpuDevicesNV")) == NULL) || r;
+ r = ((wglEnumGpusFromAffinityDCNV = (PFNWGLENUMGPUSFROMAFFINITYDCNVPROC)glewGetProcAddress((const GLubyte*)"wglEnumGpusFromAffinityDCNV")) == NULL) || r;
+ r = ((wglEnumGpusNV = (PFNWGLENUMGPUSNVPROC)glewGetProcAddress((const GLubyte*)"wglEnumGpusNV")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* WGL_NV_gpu_affinity */
+
+#ifdef WGL_NV_multisample_coverage
+
+#endif /* WGL_NV_multisample_coverage */
+
+#ifdef WGL_NV_present_video
+
+static GLboolean _glewInit_WGL_NV_present_video (WGLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((wglBindVideoDeviceNV = (PFNWGLBINDVIDEODEVICENVPROC)glewGetProcAddress((const GLubyte*)"wglBindVideoDeviceNV")) == NULL) || r;
+ r = ((wglEnumerateVideoDevicesNV = (PFNWGLENUMERATEVIDEODEVICESNVPROC)glewGetProcAddress((const GLubyte*)"wglEnumerateVideoDevicesNV")) == NULL) || r;
+ r = ((wglQueryCurrentContextNV = (PFNWGLQUERYCURRENTCONTEXTNVPROC)glewGetProcAddress((const GLubyte*)"wglQueryCurrentContextNV")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* WGL_NV_present_video */
+
+#ifdef WGL_NV_render_depth_texture
+
+#endif /* WGL_NV_render_depth_texture */
+
+#ifdef WGL_NV_render_texture_rectangle
+
+#endif /* WGL_NV_render_texture_rectangle */
+
+#ifdef WGL_NV_swap_group
+
+static GLboolean _glewInit_WGL_NV_swap_group (WGLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((wglBindSwapBarrierNV = (PFNWGLBINDSWAPBARRIERNVPROC)glewGetProcAddress((const GLubyte*)"wglBindSwapBarrierNV")) == NULL) || r;
+ r = ((wglJoinSwapGroupNV = (PFNWGLJOINSWAPGROUPNVPROC)glewGetProcAddress((const GLubyte*)"wglJoinSwapGroupNV")) == NULL) || r;
+ r = ((wglQueryFrameCountNV = (PFNWGLQUERYFRAMECOUNTNVPROC)glewGetProcAddress((const GLubyte*)"wglQueryFrameCountNV")) == NULL) || r;
+ r = ((wglQueryMaxSwapGroupsNV = (PFNWGLQUERYMAXSWAPGROUPSNVPROC)glewGetProcAddress((const GLubyte*)"wglQueryMaxSwapGroupsNV")) == NULL) || r;
+ r = ((wglQuerySwapGroupNV = (PFNWGLQUERYSWAPGROUPNVPROC)glewGetProcAddress((const GLubyte*)"wglQuerySwapGroupNV")) == NULL) || r;
+ r = ((wglResetFrameCountNV = (PFNWGLRESETFRAMECOUNTNVPROC)glewGetProcAddress((const GLubyte*)"wglResetFrameCountNV")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* WGL_NV_swap_group */
+
+#ifdef WGL_NV_vertex_array_range
+
+static GLboolean _glewInit_WGL_NV_vertex_array_range (WGLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((wglAllocateMemoryNV = (PFNWGLALLOCATEMEMORYNVPROC)glewGetProcAddress((const GLubyte*)"wglAllocateMemoryNV")) == NULL) || r;
+ r = ((wglFreeMemoryNV = (PFNWGLFREEMEMORYNVPROC)glewGetProcAddress((const GLubyte*)"wglFreeMemoryNV")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* WGL_NV_vertex_array_range */
+
+#ifdef WGL_NV_video_capture
+
+static GLboolean _glewInit_WGL_NV_video_capture (WGLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((wglBindVideoCaptureDeviceNV = (PFNWGLBINDVIDEOCAPTUREDEVICENVPROC)glewGetProcAddress((const GLubyte*)"wglBindVideoCaptureDeviceNV")) == NULL) || r;
+ r = ((wglEnumerateVideoCaptureDevicesNV = (PFNWGLENUMERATEVIDEOCAPTUREDEVICESNVPROC)glewGetProcAddress((const GLubyte*)"wglEnumerateVideoCaptureDevicesNV")) == NULL) || r;
+ r = ((wglLockVideoCaptureDeviceNV = (PFNWGLLOCKVIDEOCAPTUREDEVICENVPROC)glewGetProcAddress((const GLubyte*)"wglLockVideoCaptureDeviceNV")) == NULL) || r;
+ r = ((wglQueryVideoCaptureDeviceNV = (PFNWGLQUERYVIDEOCAPTUREDEVICENVPROC)glewGetProcAddress((const GLubyte*)"wglQueryVideoCaptureDeviceNV")) == NULL) || r;
+ r = ((wglReleaseVideoCaptureDeviceNV = (PFNWGLRELEASEVIDEOCAPTUREDEVICENVPROC)glewGetProcAddress((const GLubyte*)"wglReleaseVideoCaptureDeviceNV")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* WGL_NV_video_capture */
+
+#ifdef WGL_NV_video_output
+
+static GLboolean _glewInit_WGL_NV_video_output (WGLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((wglBindVideoImageNV = (PFNWGLBINDVIDEOIMAGENVPROC)glewGetProcAddress((const GLubyte*)"wglBindVideoImageNV")) == NULL) || r;
+ r = ((wglGetVideoDeviceNV = (PFNWGLGETVIDEODEVICENVPROC)glewGetProcAddress((const GLubyte*)"wglGetVideoDeviceNV")) == NULL) || r;
+ r = ((wglGetVideoInfoNV = (PFNWGLGETVIDEOINFONVPROC)glewGetProcAddress((const GLubyte*)"wglGetVideoInfoNV")) == NULL) || r;
+ r = ((wglReleaseVideoDeviceNV = (PFNWGLRELEASEVIDEODEVICENVPROC)glewGetProcAddress((const GLubyte*)"wglReleaseVideoDeviceNV")) == NULL) || r;
+ r = ((wglReleaseVideoImageNV = (PFNWGLRELEASEVIDEOIMAGENVPROC)glewGetProcAddress((const GLubyte*)"wglReleaseVideoImageNV")) == NULL) || r;
+ r = ((wglSendPbufferToVideoNV = (PFNWGLSENDPBUFFERTOVIDEONVPROC)glewGetProcAddress((const GLubyte*)"wglSendPbufferToVideoNV")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* WGL_NV_video_output */
+
+#ifdef WGL_OML_sync_control
+
+static GLboolean _glewInit_WGL_OML_sync_control (WGLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((wglGetMscRateOML = (PFNWGLGETMSCRATEOMLPROC)glewGetProcAddress((const GLubyte*)"wglGetMscRateOML")) == NULL) || r;
+ r = ((wglGetSyncValuesOML = (PFNWGLGETSYNCVALUESOMLPROC)glewGetProcAddress((const GLubyte*)"wglGetSyncValuesOML")) == NULL) || r;
+ r = ((wglSwapBuffersMscOML = (PFNWGLSWAPBUFFERSMSCOMLPROC)glewGetProcAddress((const GLubyte*)"wglSwapBuffersMscOML")) == NULL) || r;
+ r = ((wglSwapLayerBuffersMscOML = (PFNWGLSWAPLAYERBUFFERSMSCOMLPROC)glewGetProcAddress((const GLubyte*)"wglSwapLayerBuffersMscOML")) == NULL) || r;
+ r = ((wglWaitForMscOML = (PFNWGLWAITFORMSCOMLPROC)glewGetProcAddress((const GLubyte*)"wglWaitForMscOML")) == NULL) || r;
+ r = ((wglWaitForSbcOML = (PFNWGLWAITFORSBCOMLPROC)glewGetProcAddress((const GLubyte*)"wglWaitForSbcOML")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* WGL_OML_sync_control */
+
+/* ------------------------------------------------------------------------- */
+
+static PFNWGLGETEXTENSIONSSTRINGARBPROC _wglewGetExtensionsStringARB = NULL;
+static PFNWGLGETEXTENSIONSSTRINGEXTPROC _wglewGetExtensionsStringEXT = NULL;
+
+GLboolean wglewGetExtension (const char* name)
+{
+ const GLubyte* start;
+ const GLubyte* end;
+ if (_wglewGetExtensionsStringARB == NULL)
+ if (_wglewGetExtensionsStringEXT == NULL)
+ return GL_FALSE;
+ else
+ start = (const GLubyte*)_wglewGetExtensionsStringEXT();
+ else
+ start = (const GLubyte*)_wglewGetExtensionsStringARB(wglGetCurrentDC());
+ if (start == 0)
+ return GL_FALSE;
+ end = start + _glewStrLen(start);
+ return _glewSearchExtension(name, start, end);
+}
+
+GLenum wglewContextInit (WGLEW_CONTEXT_ARG_DEF_LIST)
+{
+ GLboolean crippled;
+ const GLubyte* extStart;
+ const GLubyte* extEnd;
+ /* find wgl extension string query functions */
+ _wglewGetExtensionsStringARB = (PFNWGLGETEXTENSIONSSTRINGARBPROC)glewGetProcAddress((const GLubyte*)"wglGetExtensionsStringARB");
+ _wglewGetExtensionsStringEXT = (PFNWGLGETEXTENSIONSSTRINGEXTPROC)glewGetProcAddress((const GLubyte*)"wglGetExtensionsStringEXT");
+ /* query wgl extension string */
+ if (_wglewGetExtensionsStringARB == NULL)
+ if (_wglewGetExtensionsStringEXT == NULL)
+ extStart = (const GLubyte*)"";
+ else
+ extStart = (const GLubyte*)_wglewGetExtensionsStringEXT();
+ else
+ extStart = (const GLubyte*)_wglewGetExtensionsStringARB(wglGetCurrentDC());
+ extEnd = extStart + _glewStrLen(extStart);
+ /* initialize extensions */
+ crippled = _wglewGetExtensionsStringARB == NULL && _wglewGetExtensionsStringEXT == NULL;
+#ifdef WGL_3DFX_multisample
+ CONST_CAST(WGLEW_3DFX_multisample) = _glewSearchExtension("WGL_3DFX_multisample", extStart, extEnd);
+#endif /* WGL_3DFX_multisample */
+#ifdef WGL_3DL_stereo_control
+ CONST_CAST(WGLEW_3DL_stereo_control) = _glewSearchExtension("WGL_3DL_stereo_control", extStart, extEnd);
+ if (glewExperimental || WGLEW_3DL_stereo_control|| crippled) CONST_CAST(WGLEW_3DL_stereo_control)= !_glewInit_WGL_3DL_stereo_control(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* WGL_3DL_stereo_control */
+#ifdef WGL_AMD_gpu_association
+ CONST_CAST(WGLEW_AMD_gpu_association) = _glewSearchExtension("WGL_AMD_gpu_association", extStart, extEnd);
+ if (glewExperimental || WGLEW_AMD_gpu_association|| crippled) CONST_CAST(WGLEW_AMD_gpu_association)= !_glewInit_WGL_AMD_gpu_association(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* WGL_AMD_gpu_association */
+#ifdef WGL_ARB_buffer_region
+ CONST_CAST(WGLEW_ARB_buffer_region) = _glewSearchExtension("WGL_ARB_buffer_region", extStart, extEnd);
+ if (glewExperimental || WGLEW_ARB_buffer_region|| crippled) CONST_CAST(WGLEW_ARB_buffer_region)= !_glewInit_WGL_ARB_buffer_region(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* WGL_ARB_buffer_region */
+#ifdef WGL_ARB_create_context
+ CONST_CAST(WGLEW_ARB_create_context) = _glewSearchExtension("WGL_ARB_create_context", extStart, extEnd);
+ if (glewExperimental || WGLEW_ARB_create_context|| crippled) CONST_CAST(WGLEW_ARB_create_context)= !_glewInit_WGL_ARB_create_context(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* WGL_ARB_create_context */
+#ifdef WGL_ARB_create_context_profile
+ CONST_CAST(WGLEW_ARB_create_context_profile) = _glewSearchExtension("WGL_ARB_create_context_profile", extStart, extEnd);
+#endif /* WGL_ARB_create_context_profile */
+#ifdef WGL_ARB_create_context_robustness
+ CONST_CAST(WGLEW_ARB_create_context_robustness) = _glewSearchExtension("WGL_ARB_create_context_robustness", extStart, extEnd);
+#endif /* WGL_ARB_create_context_robustness */
+#ifdef WGL_ARB_extensions_string
+ CONST_CAST(WGLEW_ARB_extensions_string) = _glewSearchExtension("WGL_ARB_extensions_string", extStart, extEnd);
+ if (glewExperimental || WGLEW_ARB_extensions_string|| crippled) CONST_CAST(WGLEW_ARB_extensions_string)= !_glewInit_WGL_ARB_extensions_string(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* WGL_ARB_extensions_string */
+#ifdef WGL_ARB_framebuffer_sRGB
+ CONST_CAST(WGLEW_ARB_framebuffer_sRGB) = _glewSearchExtension("WGL_ARB_framebuffer_sRGB", extStart, extEnd);
+#endif /* WGL_ARB_framebuffer_sRGB */
+#ifdef WGL_ARB_make_current_read
+ CONST_CAST(WGLEW_ARB_make_current_read) = _glewSearchExtension("WGL_ARB_make_current_read", extStart, extEnd);
+ if (glewExperimental || WGLEW_ARB_make_current_read|| crippled) CONST_CAST(WGLEW_ARB_make_current_read)= !_glewInit_WGL_ARB_make_current_read(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* WGL_ARB_make_current_read */
+#ifdef WGL_ARB_multisample
+ CONST_CAST(WGLEW_ARB_multisample) = _glewSearchExtension("WGL_ARB_multisample", extStart, extEnd);
+#endif /* WGL_ARB_multisample */
+#ifdef WGL_ARB_pbuffer
+ CONST_CAST(WGLEW_ARB_pbuffer) = _glewSearchExtension("WGL_ARB_pbuffer", extStart, extEnd);
+ if (glewExperimental || WGLEW_ARB_pbuffer|| crippled) CONST_CAST(WGLEW_ARB_pbuffer)= !_glewInit_WGL_ARB_pbuffer(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* WGL_ARB_pbuffer */
+#ifdef WGL_ARB_pixel_format
+ CONST_CAST(WGLEW_ARB_pixel_format) = _glewSearchExtension("WGL_ARB_pixel_format", extStart, extEnd);
+ if (glewExperimental || WGLEW_ARB_pixel_format|| crippled) CONST_CAST(WGLEW_ARB_pixel_format)= !_glewInit_WGL_ARB_pixel_format(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* WGL_ARB_pixel_format */
+#ifdef WGL_ARB_pixel_format_float
+ CONST_CAST(WGLEW_ARB_pixel_format_float) = _glewSearchExtension("WGL_ARB_pixel_format_float", extStart, extEnd);
+#endif /* WGL_ARB_pixel_format_float */
+#ifdef WGL_ARB_render_texture
+ CONST_CAST(WGLEW_ARB_render_texture) = _glewSearchExtension("WGL_ARB_render_texture", extStart, extEnd);
+ if (glewExperimental || WGLEW_ARB_render_texture|| crippled) CONST_CAST(WGLEW_ARB_render_texture)= !_glewInit_WGL_ARB_render_texture(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* WGL_ARB_render_texture */
+#ifdef WGL_ARB_robustness_application_isolation
+ CONST_CAST(WGLEW_ARB_robustness_application_isolation) = _glewSearchExtension("WGL_ARB_robustness_application_isolation", extStart, extEnd);
+#endif /* WGL_ARB_robustness_application_isolation */
+#ifdef WGL_ARB_robustness_share_group_isolation
+ CONST_CAST(WGLEW_ARB_robustness_share_group_isolation) = _glewSearchExtension("WGL_ARB_robustness_share_group_isolation", extStart, extEnd);
+#endif /* WGL_ARB_robustness_share_group_isolation */
+#ifdef WGL_ATI_pixel_format_float
+ CONST_CAST(WGLEW_ATI_pixel_format_float) = _glewSearchExtension("WGL_ATI_pixel_format_float", extStart, extEnd);
+#endif /* WGL_ATI_pixel_format_float */
+#ifdef WGL_ATI_render_texture_rectangle
+ CONST_CAST(WGLEW_ATI_render_texture_rectangle) = _glewSearchExtension("WGL_ATI_render_texture_rectangle", extStart, extEnd);
+#endif /* WGL_ATI_render_texture_rectangle */
+#ifdef WGL_EXT_create_context_es2_profile
+ CONST_CAST(WGLEW_EXT_create_context_es2_profile) = _glewSearchExtension("WGL_EXT_create_context_es2_profile", extStart, extEnd);
+#endif /* WGL_EXT_create_context_es2_profile */
+#ifdef WGL_EXT_create_context_es_profile
+ CONST_CAST(WGLEW_EXT_create_context_es_profile) = _glewSearchExtension("WGL_EXT_create_context_es_profile", extStart, extEnd);
+#endif /* WGL_EXT_create_context_es_profile */
+#ifdef WGL_EXT_depth_float
+ CONST_CAST(WGLEW_EXT_depth_float) = _glewSearchExtension("WGL_EXT_depth_float", extStart, extEnd);
+#endif /* WGL_EXT_depth_float */
+#ifdef WGL_EXT_display_color_table
+ CONST_CAST(WGLEW_EXT_display_color_table) = _glewSearchExtension("WGL_EXT_display_color_table", extStart, extEnd);
+ if (glewExperimental || WGLEW_EXT_display_color_table|| crippled) CONST_CAST(WGLEW_EXT_display_color_table)= !_glewInit_WGL_EXT_display_color_table(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* WGL_EXT_display_color_table */
+#ifdef WGL_EXT_extensions_string
+ CONST_CAST(WGLEW_EXT_extensions_string) = _glewSearchExtension("WGL_EXT_extensions_string", extStart, extEnd);
+ if (glewExperimental || WGLEW_EXT_extensions_string|| crippled) CONST_CAST(WGLEW_EXT_extensions_string)= !_glewInit_WGL_EXT_extensions_string(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* WGL_EXT_extensions_string */
+#ifdef WGL_EXT_framebuffer_sRGB
+ CONST_CAST(WGLEW_EXT_framebuffer_sRGB) = _glewSearchExtension("WGL_EXT_framebuffer_sRGB", extStart, extEnd);
+#endif /* WGL_EXT_framebuffer_sRGB */
+#ifdef WGL_EXT_make_current_read
+ CONST_CAST(WGLEW_EXT_make_current_read) = _glewSearchExtension("WGL_EXT_make_current_read", extStart, extEnd);
+ if (glewExperimental || WGLEW_EXT_make_current_read|| crippled) CONST_CAST(WGLEW_EXT_make_current_read)= !_glewInit_WGL_EXT_make_current_read(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* WGL_EXT_make_current_read */
+#ifdef WGL_EXT_multisample
+ CONST_CAST(WGLEW_EXT_multisample) = _glewSearchExtension("WGL_EXT_multisample", extStart, extEnd);
+#endif /* WGL_EXT_multisample */
+#ifdef WGL_EXT_pbuffer
+ CONST_CAST(WGLEW_EXT_pbuffer) = _glewSearchExtension("WGL_EXT_pbuffer", extStart, extEnd);
+ if (glewExperimental || WGLEW_EXT_pbuffer|| crippled) CONST_CAST(WGLEW_EXT_pbuffer)= !_glewInit_WGL_EXT_pbuffer(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* WGL_EXT_pbuffer */
+#ifdef WGL_EXT_pixel_format
+ CONST_CAST(WGLEW_EXT_pixel_format) = _glewSearchExtension("WGL_EXT_pixel_format", extStart, extEnd);
+ if (glewExperimental || WGLEW_EXT_pixel_format|| crippled) CONST_CAST(WGLEW_EXT_pixel_format)= !_glewInit_WGL_EXT_pixel_format(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* WGL_EXT_pixel_format */
+#ifdef WGL_EXT_pixel_format_packed_float
+ CONST_CAST(WGLEW_EXT_pixel_format_packed_float) = _glewSearchExtension("WGL_EXT_pixel_format_packed_float", extStart, extEnd);
+#endif /* WGL_EXT_pixel_format_packed_float */
+#ifdef WGL_EXT_swap_control
+ CONST_CAST(WGLEW_EXT_swap_control) = _glewSearchExtension("WGL_EXT_swap_control", extStart, extEnd);
+ if (glewExperimental || WGLEW_EXT_swap_control|| crippled) CONST_CAST(WGLEW_EXT_swap_control)= !_glewInit_WGL_EXT_swap_control(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* WGL_EXT_swap_control */
+#ifdef WGL_EXT_swap_control_tear
+ CONST_CAST(WGLEW_EXT_swap_control_tear) = _glewSearchExtension("WGL_EXT_swap_control_tear", extStart, extEnd);
+#endif /* WGL_EXT_swap_control_tear */
+#ifdef WGL_I3D_digital_video_control
+ CONST_CAST(WGLEW_I3D_digital_video_control) = _glewSearchExtension("WGL_I3D_digital_video_control", extStart, extEnd);
+ if (glewExperimental || WGLEW_I3D_digital_video_control|| crippled) CONST_CAST(WGLEW_I3D_digital_video_control)= !_glewInit_WGL_I3D_digital_video_control(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* WGL_I3D_digital_video_control */
+#ifdef WGL_I3D_gamma
+ CONST_CAST(WGLEW_I3D_gamma) = _glewSearchExtension("WGL_I3D_gamma", extStart, extEnd);
+ if (glewExperimental || WGLEW_I3D_gamma|| crippled) CONST_CAST(WGLEW_I3D_gamma)= !_glewInit_WGL_I3D_gamma(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* WGL_I3D_gamma */
+#ifdef WGL_I3D_genlock
+ CONST_CAST(WGLEW_I3D_genlock) = _glewSearchExtension("WGL_I3D_genlock", extStart, extEnd);
+ if (glewExperimental || WGLEW_I3D_genlock|| crippled) CONST_CAST(WGLEW_I3D_genlock)= !_glewInit_WGL_I3D_genlock(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* WGL_I3D_genlock */
+#ifdef WGL_I3D_image_buffer
+ CONST_CAST(WGLEW_I3D_image_buffer) = _glewSearchExtension("WGL_I3D_image_buffer", extStart, extEnd);
+ if (glewExperimental || WGLEW_I3D_image_buffer|| crippled) CONST_CAST(WGLEW_I3D_image_buffer)= !_glewInit_WGL_I3D_image_buffer(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* WGL_I3D_image_buffer */
+#ifdef WGL_I3D_swap_frame_lock
+ CONST_CAST(WGLEW_I3D_swap_frame_lock) = _glewSearchExtension("WGL_I3D_swap_frame_lock", extStart, extEnd);
+ if (glewExperimental || WGLEW_I3D_swap_frame_lock|| crippled) CONST_CAST(WGLEW_I3D_swap_frame_lock)= !_glewInit_WGL_I3D_swap_frame_lock(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* WGL_I3D_swap_frame_lock */
+#ifdef WGL_I3D_swap_frame_usage
+ CONST_CAST(WGLEW_I3D_swap_frame_usage) = _glewSearchExtension("WGL_I3D_swap_frame_usage", extStart, extEnd);
+ if (glewExperimental || WGLEW_I3D_swap_frame_usage|| crippled) CONST_CAST(WGLEW_I3D_swap_frame_usage)= !_glewInit_WGL_I3D_swap_frame_usage(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* WGL_I3D_swap_frame_usage */
+#ifdef WGL_NV_DX_interop
+ CONST_CAST(WGLEW_NV_DX_interop) = _glewSearchExtension("WGL_NV_DX_interop", extStart, extEnd);
+ if (glewExperimental || WGLEW_NV_DX_interop|| crippled) CONST_CAST(WGLEW_NV_DX_interop)= !_glewInit_WGL_NV_DX_interop(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* WGL_NV_DX_interop */
+#ifdef WGL_NV_DX_interop2
+ CONST_CAST(WGLEW_NV_DX_interop2) = _glewSearchExtension("WGL_NV_DX_interop2", extStart, extEnd);
+#endif /* WGL_NV_DX_interop2 */
+#ifdef WGL_NV_copy_image
+ CONST_CAST(WGLEW_NV_copy_image) = _glewSearchExtension("WGL_NV_copy_image", extStart, extEnd);
+ if (glewExperimental || WGLEW_NV_copy_image|| crippled) CONST_CAST(WGLEW_NV_copy_image)= !_glewInit_WGL_NV_copy_image(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* WGL_NV_copy_image */
+#ifdef WGL_NV_float_buffer
+ CONST_CAST(WGLEW_NV_float_buffer) = _glewSearchExtension("WGL_NV_float_buffer", extStart, extEnd);
+#endif /* WGL_NV_float_buffer */
+#ifdef WGL_NV_gpu_affinity
+ CONST_CAST(WGLEW_NV_gpu_affinity) = _glewSearchExtension("WGL_NV_gpu_affinity", extStart, extEnd);
+ if (glewExperimental || WGLEW_NV_gpu_affinity|| crippled) CONST_CAST(WGLEW_NV_gpu_affinity)= !_glewInit_WGL_NV_gpu_affinity(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* WGL_NV_gpu_affinity */
+#ifdef WGL_NV_multisample_coverage
+ CONST_CAST(WGLEW_NV_multisample_coverage) = _glewSearchExtension("WGL_NV_multisample_coverage", extStart, extEnd);
+#endif /* WGL_NV_multisample_coverage */
+#ifdef WGL_NV_present_video
+ CONST_CAST(WGLEW_NV_present_video) = _glewSearchExtension("WGL_NV_present_video", extStart, extEnd);
+ if (glewExperimental || WGLEW_NV_present_video|| crippled) CONST_CAST(WGLEW_NV_present_video)= !_glewInit_WGL_NV_present_video(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* WGL_NV_present_video */
+#ifdef WGL_NV_render_depth_texture
+ CONST_CAST(WGLEW_NV_render_depth_texture) = _glewSearchExtension("WGL_NV_render_depth_texture", extStart, extEnd);
+#endif /* WGL_NV_render_depth_texture */
+#ifdef WGL_NV_render_texture_rectangle
+ CONST_CAST(WGLEW_NV_render_texture_rectangle) = _glewSearchExtension("WGL_NV_render_texture_rectangle", extStart, extEnd);
+#endif /* WGL_NV_render_texture_rectangle */
+#ifdef WGL_NV_swap_group
+ CONST_CAST(WGLEW_NV_swap_group) = _glewSearchExtension("WGL_NV_swap_group", extStart, extEnd);
+ if (glewExperimental || WGLEW_NV_swap_group|| crippled) CONST_CAST(WGLEW_NV_swap_group)= !_glewInit_WGL_NV_swap_group(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* WGL_NV_swap_group */
+#ifdef WGL_NV_vertex_array_range
+ CONST_CAST(WGLEW_NV_vertex_array_range) = _glewSearchExtension("WGL_NV_vertex_array_range", extStart, extEnd);
+ if (glewExperimental || WGLEW_NV_vertex_array_range|| crippled) CONST_CAST(WGLEW_NV_vertex_array_range)= !_glewInit_WGL_NV_vertex_array_range(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* WGL_NV_vertex_array_range */
+#ifdef WGL_NV_video_capture
+ CONST_CAST(WGLEW_NV_video_capture) = _glewSearchExtension("WGL_NV_video_capture", extStart, extEnd);
+ if (glewExperimental || WGLEW_NV_video_capture|| crippled) CONST_CAST(WGLEW_NV_video_capture)= !_glewInit_WGL_NV_video_capture(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* WGL_NV_video_capture */
+#ifdef WGL_NV_video_output
+ CONST_CAST(WGLEW_NV_video_output) = _glewSearchExtension("WGL_NV_video_output", extStart, extEnd);
+ if (glewExperimental || WGLEW_NV_video_output|| crippled) CONST_CAST(WGLEW_NV_video_output)= !_glewInit_WGL_NV_video_output(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* WGL_NV_video_output */
+#ifdef WGL_OML_sync_control
+ CONST_CAST(WGLEW_OML_sync_control) = _glewSearchExtension("WGL_OML_sync_control", extStart, extEnd);
+ if (glewExperimental || WGLEW_OML_sync_control|| crippled) CONST_CAST(WGLEW_OML_sync_control)= !_glewInit_WGL_OML_sync_control(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* WGL_OML_sync_control */
+
+ return GLEW_OK;
+}
+
+#elif !defined(__APPLE__) || defined(GLEW_APPLE_GLX)
+
+PFNGLXGETCURRENTDISPLAYPROC __glewXGetCurrentDisplay = NULL;
+
+PFNGLXCHOOSEFBCONFIGPROC __glewXChooseFBConfig = NULL;
+PFNGLXCREATENEWCONTEXTPROC __glewXCreateNewContext = NULL;
+PFNGLXCREATEPBUFFERPROC __glewXCreatePbuffer = NULL;
+PFNGLXCREATEPIXMAPPROC __glewXCreatePixmap = NULL;
+PFNGLXCREATEWINDOWPROC __glewXCreateWindow = NULL;
+PFNGLXDESTROYPBUFFERPROC __glewXDestroyPbuffer = NULL;
+PFNGLXDESTROYPIXMAPPROC __glewXDestroyPixmap = NULL;
+PFNGLXDESTROYWINDOWPROC __glewXDestroyWindow = NULL;
+PFNGLXGETCURRENTREADDRAWABLEPROC __glewXGetCurrentReadDrawable = NULL;
+PFNGLXGETFBCONFIGATTRIBPROC __glewXGetFBConfigAttrib = NULL;
+PFNGLXGETFBCONFIGSPROC __glewXGetFBConfigs = NULL;
+PFNGLXGETSELECTEDEVENTPROC __glewXGetSelectedEvent = NULL;
+PFNGLXGETVISUALFROMFBCONFIGPROC __glewXGetVisualFromFBConfig = NULL;
+PFNGLXMAKECONTEXTCURRENTPROC __glewXMakeContextCurrent = NULL;
+PFNGLXQUERYCONTEXTPROC __glewXQueryContext = NULL;
+PFNGLXQUERYDRAWABLEPROC __glewXQueryDrawable = NULL;
+PFNGLXSELECTEVENTPROC __glewXSelectEvent = NULL;
+
+PFNGLXCREATECONTEXTATTRIBSARBPROC __glewXCreateContextAttribsARB = NULL;
+
+PFNGLXBINDTEXIMAGEATIPROC __glewXBindTexImageATI = NULL;
+PFNGLXDRAWABLEATTRIBATIPROC __glewXDrawableAttribATI = NULL;
+PFNGLXRELEASETEXIMAGEATIPROC __glewXReleaseTexImageATI = NULL;
+
+PFNGLXFREECONTEXTEXTPROC __glewXFreeContextEXT = NULL;
+PFNGLXGETCONTEXTIDEXTPROC __glewXGetContextIDEXT = NULL;
+PFNGLXIMPORTCONTEXTEXTPROC __glewXImportContextEXT = NULL;
+PFNGLXQUERYCONTEXTINFOEXTPROC __glewXQueryContextInfoEXT = NULL;
+
+PFNGLXSWAPINTERVALEXTPROC __glewXSwapIntervalEXT = NULL;
+
+PFNGLXBINDTEXIMAGEEXTPROC __glewXBindTexImageEXT = NULL;
+PFNGLXRELEASETEXIMAGEEXTPROC __glewXReleaseTexImageEXT = NULL;
+
+PFNGLXGETAGPOFFSETMESAPROC __glewXGetAGPOffsetMESA = NULL;
+
+PFNGLXCOPYSUBBUFFERMESAPROC __glewXCopySubBufferMESA = NULL;
+
+PFNGLXCREATEGLXPIXMAPMESAPROC __glewXCreateGLXPixmapMESA = NULL;
+
+PFNGLXRELEASEBUFFERSMESAPROC __glewXReleaseBuffersMESA = NULL;
+
+PFNGLXSET3DFXMODEMESAPROC __glewXSet3DfxModeMESA = NULL;
+
+PFNGLXGETSWAPINTERVALMESAPROC __glewXGetSwapIntervalMESA = NULL;
+PFNGLXSWAPINTERVALMESAPROC __glewXSwapIntervalMESA = NULL;
+
+PFNGLXCOPYIMAGESUBDATANVPROC __glewXCopyImageSubDataNV = NULL;
+
+PFNGLXBINDVIDEODEVICENVPROC __glewXBindVideoDeviceNV = NULL;
+PFNGLXENUMERATEVIDEODEVICESNVPROC __glewXEnumerateVideoDevicesNV = NULL;
+
+PFNGLXBINDSWAPBARRIERNVPROC __glewXBindSwapBarrierNV = NULL;
+PFNGLXJOINSWAPGROUPNVPROC __glewXJoinSwapGroupNV = NULL;
+PFNGLXQUERYFRAMECOUNTNVPROC __glewXQueryFrameCountNV = NULL;
+PFNGLXQUERYMAXSWAPGROUPSNVPROC __glewXQueryMaxSwapGroupsNV = NULL;
+PFNGLXQUERYSWAPGROUPNVPROC __glewXQuerySwapGroupNV = NULL;
+PFNGLXRESETFRAMECOUNTNVPROC __glewXResetFrameCountNV = NULL;
+
+PFNGLXALLOCATEMEMORYNVPROC __glewXAllocateMemoryNV = NULL;
+PFNGLXFREEMEMORYNVPROC __glewXFreeMemoryNV = NULL;
+
+PFNGLXBINDVIDEOCAPTUREDEVICENVPROC __glewXBindVideoCaptureDeviceNV = NULL;
+PFNGLXENUMERATEVIDEOCAPTUREDEVICESNVPROC __glewXEnumerateVideoCaptureDevicesNV = NULL;
+PFNGLXLOCKVIDEOCAPTUREDEVICENVPROC __glewXLockVideoCaptureDeviceNV = NULL;
+PFNGLXQUERYVIDEOCAPTUREDEVICENVPROC __glewXQueryVideoCaptureDeviceNV = NULL;
+PFNGLXRELEASEVIDEOCAPTUREDEVICENVPROC __glewXReleaseVideoCaptureDeviceNV = NULL;
+
+PFNGLXBINDVIDEOIMAGENVPROC __glewXBindVideoImageNV = NULL;
+PFNGLXGETVIDEODEVICENVPROC __glewXGetVideoDeviceNV = NULL;
+PFNGLXGETVIDEOINFONVPROC __glewXGetVideoInfoNV = NULL;
+PFNGLXRELEASEVIDEODEVICENVPROC __glewXReleaseVideoDeviceNV = NULL;
+PFNGLXRELEASEVIDEOIMAGENVPROC __glewXReleaseVideoImageNV = NULL;
+PFNGLXSENDPBUFFERTOVIDEONVPROC __glewXSendPbufferToVideoNV = NULL;
+
+PFNGLXGETMSCRATEOMLPROC __glewXGetMscRateOML = NULL;
+PFNGLXGETSYNCVALUESOMLPROC __glewXGetSyncValuesOML = NULL;
+PFNGLXSWAPBUFFERSMSCOMLPROC __glewXSwapBuffersMscOML = NULL;
+PFNGLXWAITFORMSCOMLPROC __glewXWaitForMscOML = NULL;
+PFNGLXWAITFORSBCOMLPROC __glewXWaitForSbcOML = NULL;
+
+PFNGLXCHOOSEFBCONFIGSGIXPROC __glewXChooseFBConfigSGIX = NULL;
+PFNGLXCREATECONTEXTWITHCONFIGSGIXPROC __glewXCreateContextWithConfigSGIX = NULL;
+PFNGLXCREATEGLXPIXMAPWITHCONFIGSGIXPROC __glewXCreateGLXPixmapWithConfigSGIX = NULL;
+PFNGLXGETFBCONFIGATTRIBSGIXPROC __glewXGetFBConfigAttribSGIX = NULL;
+PFNGLXGETFBCONFIGFROMVISUALSGIXPROC __glewXGetFBConfigFromVisualSGIX = NULL;
+PFNGLXGETVISUALFROMFBCONFIGSGIXPROC __glewXGetVisualFromFBConfigSGIX = NULL;
+
+PFNGLXBINDHYPERPIPESGIXPROC __glewXBindHyperpipeSGIX = NULL;
+PFNGLXDESTROYHYPERPIPECONFIGSGIXPROC __glewXDestroyHyperpipeConfigSGIX = NULL;
+PFNGLXHYPERPIPEATTRIBSGIXPROC __glewXHyperpipeAttribSGIX = NULL;
+PFNGLXHYPERPIPECONFIGSGIXPROC __glewXHyperpipeConfigSGIX = NULL;
+PFNGLXQUERYHYPERPIPEATTRIBSGIXPROC __glewXQueryHyperpipeAttribSGIX = NULL;
+PFNGLXQUERYHYPERPIPEBESTATTRIBSGIXPROC __glewXQueryHyperpipeBestAttribSGIX = NULL;
+PFNGLXQUERYHYPERPIPECONFIGSGIXPROC __glewXQueryHyperpipeConfigSGIX = NULL;
+PFNGLXQUERYHYPERPIPENETWORKSGIXPROC __glewXQueryHyperpipeNetworkSGIX = NULL;
+
+PFNGLXCREATEGLXPBUFFERSGIXPROC __glewXCreateGLXPbufferSGIX = NULL;
+PFNGLXDESTROYGLXPBUFFERSGIXPROC __glewXDestroyGLXPbufferSGIX = NULL;
+PFNGLXGETSELECTEDEVENTSGIXPROC __glewXGetSelectedEventSGIX = NULL;
+PFNGLXQUERYGLXPBUFFERSGIXPROC __glewXQueryGLXPbufferSGIX = NULL;
+PFNGLXSELECTEVENTSGIXPROC __glewXSelectEventSGIX = NULL;
+
+PFNGLXBINDSWAPBARRIERSGIXPROC __glewXBindSwapBarrierSGIX = NULL;
+PFNGLXQUERYMAXSWAPBARRIERSSGIXPROC __glewXQueryMaxSwapBarriersSGIX = NULL;
+
+PFNGLXJOINSWAPGROUPSGIXPROC __glewXJoinSwapGroupSGIX = NULL;
+
+PFNGLXBINDCHANNELTOWINDOWSGIXPROC __glewXBindChannelToWindowSGIX = NULL;
+PFNGLXCHANNELRECTSGIXPROC __glewXChannelRectSGIX = NULL;
+PFNGLXCHANNELRECTSYNCSGIXPROC __glewXChannelRectSyncSGIX = NULL;
+PFNGLXQUERYCHANNELDELTASSGIXPROC __glewXQueryChannelDeltasSGIX = NULL;
+PFNGLXQUERYCHANNELRECTSGIXPROC __glewXQueryChannelRectSGIX = NULL;
+
+PFNGLXCUSHIONSGIPROC __glewXCushionSGI = NULL;
+
+PFNGLXGETCURRENTREADDRAWABLESGIPROC __glewXGetCurrentReadDrawableSGI = NULL;
+PFNGLXMAKECURRENTREADSGIPROC __glewXMakeCurrentReadSGI = NULL;
+
+PFNGLXSWAPINTERVALSGIPROC __glewXSwapIntervalSGI = NULL;
+
+PFNGLXGETVIDEOSYNCSGIPROC __glewXGetVideoSyncSGI = NULL;
+PFNGLXWAITVIDEOSYNCSGIPROC __glewXWaitVideoSyncSGI = NULL;
+
+PFNGLXGETTRANSPARENTINDEXSUNPROC __glewXGetTransparentIndexSUN = NULL;
+
+PFNGLXGETVIDEORESIZESUNPROC __glewXGetVideoResizeSUN = NULL;
+PFNGLXVIDEORESIZESUNPROC __glewXVideoResizeSUN = NULL;
+
+#if !defined(GLEW_MX)
+
+GLboolean __GLXEW_VERSION_1_0 = GL_FALSE;
+GLboolean __GLXEW_VERSION_1_1 = GL_FALSE;
+GLboolean __GLXEW_VERSION_1_2 = GL_FALSE;
+GLboolean __GLXEW_VERSION_1_3 = GL_FALSE;
+GLboolean __GLXEW_VERSION_1_4 = GL_FALSE;
+GLboolean __GLXEW_3DFX_multisample = GL_FALSE;
+GLboolean __GLXEW_AMD_gpu_association = GL_FALSE;
+GLboolean __GLXEW_ARB_create_context = GL_FALSE;
+GLboolean __GLXEW_ARB_create_context_profile = GL_FALSE;
+GLboolean __GLXEW_ARB_create_context_robustness = GL_FALSE;
+GLboolean __GLXEW_ARB_fbconfig_float = GL_FALSE;
+GLboolean __GLXEW_ARB_framebuffer_sRGB = GL_FALSE;
+GLboolean __GLXEW_ARB_get_proc_address = GL_FALSE;
+GLboolean __GLXEW_ARB_multisample = GL_FALSE;
+GLboolean __GLXEW_ARB_robustness_application_isolation = GL_FALSE;
+GLboolean __GLXEW_ARB_robustness_share_group_isolation = GL_FALSE;
+GLboolean __GLXEW_ARB_vertex_buffer_object = GL_FALSE;
+GLboolean __GLXEW_ATI_pixel_format_float = GL_FALSE;
+GLboolean __GLXEW_ATI_render_texture = GL_FALSE;
+GLboolean __GLXEW_EXT_buffer_age = GL_FALSE;
+GLboolean __GLXEW_EXT_create_context_es2_profile = GL_FALSE;
+GLboolean __GLXEW_EXT_create_context_es_profile = GL_FALSE;
+GLboolean __GLXEW_EXT_fbconfig_packed_float = GL_FALSE;
+GLboolean __GLXEW_EXT_framebuffer_sRGB = GL_FALSE;
+GLboolean __GLXEW_EXT_import_context = GL_FALSE;
+GLboolean __GLXEW_EXT_scene_marker = GL_FALSE;
+GLboolean __GLXEW_EXT_swap_control = GL_FALSE;
+GLboolean __GLXEW_EXT_swap_control_tear = GL_FALSE;
+GLboolean __GLXEW_EXT_texture_from_pixmap = GL_FALSE;
+GLboolean __GLXEW_EXT_visual_info = GL_FALSE;
+GLboolean __GLXEW_EXT_visual_rating = GL_FALSE;
+GLboolean __GLXEW_INTEL_swap_event = GL_FALSE;
+GLboolean __GLXEW_MESA_agp_offset = GL_FALSE;
+GLboolean __GLXEW_MESA_copy_sub_buffer = GL_FALSE;
+GLboolean __GLXEW_MESA_pixmap_colormap = GL_FALSE;
+GLboolean __GLXEW_MESA_release_buffers = GL_FALSE;
+GLboolean __GLXEW_MESA_set_3dfx_mode = GL_FALSE;
+GLboolean __GLXEW_MESA_swap_control = GL_FALSE;
+GLboolean __GLXEW_NV_copy_image = GL_FALSE;
+GLboolean __GLXEW_NV_float_buffer = GL_FALSE;
+GLboolean __GLXEW_NV_multisample_coverage = GL_FALSE;
+GLboolean __GLXEW_NV_present_video = GL_FALSE;
+GLboolean __GLXEW_NV_swap_group = GL_FALSE;
+GLboolean __GLXEW_NV_vertex_array_range = GL_FALSE;
+GLboolean __GLXEW_NV_video_capture = GL_FALSE;
+GLboolean __GLXEW_NV_video_output = GL_FALSE;
+GLboolean __GLXEW_OML_swap_method = GL_FALSE;
+GLboolean __GLXEW_OML_sync_control = GL_FALSE;
+GLboolean __GLXEW_SGIS_blended_overlay = GL_FALSE;
+GLboolean __GLXEW_SGIS_color_range = GL_FALSE;
+GLboolean __GLXEW_SGIS_multisample = GL_FALSE;
+GLboolean __GLXEW_SGIS_shared_multisample = GL_FALSE;
+GLboolean __GLXEW_SGIX_fbconfig = GL_FALSE;
+GLboolean __GLXEW_SGIX_hyperpipe = GL_FALSE;
+GLboolean __GLXEW_SGIX_pbuffer = GL_FALSE;
+GLboolean __GLXEW_SGIX_swap_barrier = GL_FALSE;
+GLboolean __GLXEW_SGIX_swap_group = GL_FALSE;
+GLboolean __GLXEW_SGIX_video_resize = GL_FALSE;
+GLboolean __GLXEW_SGIX_visual_select_group = GL_FALSE;
+GLboolean __GLXEW_SGI_cushion = GL_FALSE;
+GLboolean __GLXEW_SGI_make_current_read = GL_FALSE;
+GLboolean __GLXEW_SGI_swap_control = GL_FALSE;
+GLboolean __GLXEW_SGI_video_sync = GL_FALSE;
+GLboolean __GLXEW_SUN_get_transparent_index = GL_FALSE;
+GLboolean __GLXEW_SUN_video_resize = GL_FALSE;
+
+#endif /* !GLEW_MX */
+
+#ifdef GLX_VERSION_1_2
+
+static GLboolean _glewInit_GLX_VERSION_1_2 (GLXEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glXGetCurrentDisplay = (PFNGLXGETCURRENTDISPLAYPROC)glewGetProcAddress((const GLubyte*)"glXGetCurrentDisplay")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GLX_VERSION_1_2 */
+
+#ifdef GLX_VERSION_1_3
+
+static GLboolean _glewInit_GLX_VERSION_1_3 (GLXEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glXChooseFBConfig = (PFNGLXCHOOSEFBCONFIGPROC)glewGetProcAddress((const GLubyte*)"glXChooseFBConfig")) == NULL) || r;
+ r = ((glXCreateNewContext = (PFNGLXCREATENEWCONTEXTPROC)glewGetProcAddress((const GLubyte*)"glXCreateNewContext")) == NULL) || r;
+ r = ((glXCreatePbuffer = (PFNGLXCREATEPBUFFERPROC)glewGetProcAddress((const GLubyte*)"glXCreatePbuffer")) == NULL) || r;
+ r = ((glXCreatePixmap = (PFNGLXCREATEPIXMAPPROC)glewGetProcAddress((const GLubyte*)"glXCreatePixmap")) == NULL) || r;
+ r = ((glXCreateWindow = (PFNGLXCREATEWINDOWPROC)glewGetProcAddress((const GLubyte*)"glXCreateWindow")) == NULL) || r;
+ r = ((glXDestroyPbuffer = (PFNGLXDESTROYPBUFFERPROC)glewGetProcAddress((const GLubyte*)"glXDestroyPbuffer")) == NULL) || r;
+ r = ((glXDestroyPixmap = (PFNGLXDESTROYPIXMAPPROC)glewGetProcAddress((const GLubyte*)"glXDestroyPixmap")) == NULL) || r;
+ r = ((glXDestroyWindow = (PFNGLXDESTROYWINDOWPROC)glewGetProcAddress((const GLubyte*)"glXDestroyWindow")) == NULL) || r;
+ r = ((glXGetCurrentReadDrawable = (PFNGLXGETCURRENTREADDRAWABLEPROC)glewGetProcAddress((const GLubyte*)"glXGetCurrentReadDrawable")) == NULL) || r;
+ r = ((glXGetFBConfigAttrib = (PFNGLXGETFBCONFIGATTRIBPROC)glewGetProcAddress((const GLubyte*)"glXGetFBConfigAttrib")) == NULL) || r;
+ r = ((glXGetFBConfigs = (PFNGLXGETFBCONFIGSPROC)glewGetProcAddress((const GLubyte*)"glXGetFBConfigs")) == NULL) || r;
+ r = ((glXGetSelectedEvent = (PFNGLXGETSELECTEDEVENTPROC)glewGetProcAddress((const GLubyte*)"glXGetSelectedEvent")) == NULL) || r;
+ r = ((glXGetVisualFromFBConfig = (PFNGLXGETVISUALFROMFBCONFIGPROC)glewGetProcAddress((const GLubyte*)"glXGetVisualFromFBConfig")) == NULL) || r;
+ r = ((glXMakeContextCurrent = (PFNGLXMAKECONTEXTCURRENTPROC)glewGetProcAddress((const GLubyte*)"glXMakeContextCurrent")) == NULL) || r;
+ r = ((glXQueryContext = (PFNGLXQUERYCONTEXTPROC)glewGetProcAddress((const GLubyte*)"glXQueryContext")) == NULL) || r;
+ r = ((glXQueryDrawable = (PFNGLXQUERYDRAWABLEPROC)glewGetProcAddress((const GLubyte*)"glXQueryDrawable")) == NULL) || r;
+ r = ((glXSelectEvent = (PFNGLXSELECTEVENTPROC)glewGetProcAddress((const GLubyte*)"glXSelectEvent")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GLX_VERSION_1_3 */
+
+#ifdef GLX_VERSION_1_4
+
+#endif /* GLX_VERSION_1_4 */
+
+#ifdef GLX_3DFX_multisample
+
+#endif /* GLX_3DFX_multisample */
+
+#ifdef GLX_AMD_gpu_association
+
+#endif /* GLX_AMD_gpu_association */
+
+#ifdef GLX_ARB_create_context
+
+static GLboolean _glewInit_GLX_ARB_create_context (GLXEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glXCreateContextAttribsARB = (PFNGLXCREATECONTEXTATTRIBSARBPROC)glewGetProcAddress((const GLubyte*)"glXCreateContextAttribsARB")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GLX_ARB_create_context */
+
+#ifdef GLX_ARB_create_context_profile
+
+#endif /* GLX_ARB_create_context_profile */
+
+#ifdef GLX_ARB_create_context_robustness
+
+#endif /* GLX_ARB_create_context_robustness */
+
+#ifdef GLX_ARB_fbconfig_float
+
+#endif /* GLX_ARB_fbconfig_float */
+
+#ifdef GLX_ARB_framebuffer_sRGB
+
+#endif /* GLX_ARB_framebuffer_sRGB */
+
+#ifdef GLX_ARB_get_proc_address
+
+#endif /* GLX_ARB_get_proc_address */
+
+#ifdef GLX_ARB_multisample
+
+#endif /* GLX_ARB_multisample */
+
+#ifdef GLX_ARB_robustness_application_isolation
+
+#endif /* GLX_ARB_robustness_application_isolation */
+
+#ifdef GLX_ARB_robustness_share_group_isolation
+
+#endif /* GLX_ARB_robustness_share_group_isolation */
+
+#ifdef GLX_ARB_vertex_buffer_object
+
+#endif /* GLX_ARB_vertex_buffer_object */
+
+#ifdef GLX_ATI_pixel_format_float
+
+#endif /* GLX_ATI_pixel_format_float */
+
+#ifdef GLX_ATI_render_texture
+
+static GLboolean _glewInit_GLX_ATI_render_texture (GLXEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glXBindTexImageATI = (PFNGLXBINDTEXIMAGEATIPROC)glewGetProcAddress((const GLubyte*)"glXBindTexImageATI")) == NULL) || r;
+ r = ((glXDrawableAttribATI = (PFNGLXDRAWABLEATTRIBATIPROC)glewGetProcAddress((const GLubyte*)"glXDrawableAttribATI")) == NULL) || r;
+ r = ((glXReleaseTexImageATI = (PFNGLXRELEASETEXIMAGEATIPROC)glewGetProcAddress((const GLubyte*)"glXReleaseTexImageATI")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GLX_ATI_render_texture */
+
+#ifdef GLX_EXT_buffer_age
+
+#endif /* GLX_EXT_buffer_age */
+
+#ifdef GLX_EXT_create_context_es2_profile
+
+#endif /* GLX_EXT_create_context_es2_profile */
+
+#ifdef GLX_EXT_create_context_es_profile
+
+#endif /* GLX_EXT_create_context_es_profile */
+
+#ifdef GLX_EXT_fbconfig_packed_float
+
+#endif /* GLX_EXT_fbconfig_packed_float */
+
+#ifdef GLX_EXT_framebuffer_sRGB
+
+#endif /* GLX_EXT_framebuffer_sRGB */
+
+#ifdef GLX_EXT_import_context
+
+static GLboolean _glewInit_GLX_EXT_import_context (GLXEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glXFreeContextEXT = (PFNGLXFREECONTEXTEXTPROC)glewGetProcAddress((const GLubyte*)"glXFreeContextEXT")) == NULL) || r;
+ r = ((glXGetContextIDEXT = (PFNGLXGETCONTEXTIDEXTPROC)glewGetProcAddress((const GLubyte*)"glXGetContextIDEXT")) == NULL) || r;
+ r = ((glXImportContextEXT = (PFNGLXIMPORTCONTEXTEXTPROC)glewGetProcAddress((const GLubyte*)"glXImportContextEXT")) == NULL) || r;
+ r = ((glXQueryContextInfoEXT = (PFNGLXQUERYCONTEXTINFOEXTPROC)glewGetProcAddress((const GLubyte*)"glXQueryContextInfoEXT")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GLX_EXT_import_context */
+
+#ifdef GLX_EXT_scene_marker
+
+#endif /* GLX_EXT_scene_marker */
+
+#ifdef GLX_EXT_swap_control
+
+static GLboolean _glewInit_GLX_EXT_swap_control (GLXEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glXSwapIntervalEXT = (PFNGLXSWAPINTERVALEXTPROC)glewGetProcAddress((const GLubyte*)"glXSwapIntervalEXT")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GLX_EXT_swap_control */
+
+#ifdef GLX_EXT_swap_control_tear
+
+#endif /* GLX_EXT_swap_control_tear */
+
+#ifdef GLX_EXT_texture_from_pixmap
+
+static GLboolean _glewInit_GLX_EXT_texture_from_pixmap (GLXEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glXBindTexImageEXT = (PFNGLXBINDTEXIMAGEEXTPROC)glewGetProcAddress((const GLubyte*)"glXBindTexImageEXT")) == NULL) || r;
+ r = ((glXReleaseTexImageEXT = (PFNGLXRELEASETEXIMAGEEXTPROC)glewGetProcAddress((const GLubyte*)"glXReleaseTexImageEXT")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GLX_EXT_texture_from_pixmap */
+
+#ifdef GLX_EXT_visual_info
+
+#endif /* GLX_EXT_visual_info */
+
+#ifdef GLX_EXT_visual_rating
+
+#endif /* GLX_EXT_visual_rating */
+
+#ifdef GLX_INTEL_swap_event
+
+#endif /* GLX_INTEL_swap_event */
+
+#ifdef GLX_MESA_agp_offset
+
+static GLboolean _glewInit_GLX_MESA_agp_offset (GLXEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glXGetAGPOffsetMESA = (PFNGLXGETAGPOFFSETMESAPROC)glewGetProcAddress((const GLubyte*)"glXGetAGPOffsetMESA")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GLX_MESA_agp_offset */
+
+#ifdef GLX_MESA_copy_sub_buffer
+
+static GLboolean _glewInit_GLX_MESA_copy_sub_buffer (GLXEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glXCopySubBufferMESA = (PFNGLXCOPYSUBBUFFERMESAPROC)glewGetProcAddress((const GLubyte*)"glXCopySubBufferMESA")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GLX_MESA_copy_sub_buffer */
+
+#ifdef GLX_MESA_pixmap_colormap
+
+static GLboolean _glewInit_GLX_MESA_pixmap_colormap (GLXEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glXCreateGLXPixmapMESA = (PFNGLXCREATEGLXPIXMAPMESAPROC)glewGetProcAddress((const GLubyte*)"glXCreateGLXPixmapMESA")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GLX_MESA_pixmap_colormap */
+
+#ifdef GLX_MESA_release_buffers
+
+static GLboolean _glewInit_GLX_MESA_release_buffers (GLXEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glXReleaseBuffersMESA = (PFNGLXRELEASEBUFFERSMESAPROC)glewGetProcAddress((const GLubyte*)"glXReleaseBuffersMESA")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GLX_MESA_release_buffers */
+
+#ifdef GLX_MESA_set_3dfx_mode
+
+static GLboolean _glewInit_GLX_MESA_set_3dfx_mode (GLXEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glXSet3DfxModeMESA = (PFNGLXSET3DFXMODEMESAPROC)glewGetProcAddress((const GLubyte*)"glXSet3DfxModeMESA")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GLX_MESA_set_3dfx_mode */
+
+#ifdef GLX_MESA_swap_control
+
+static GLboolean _glewInit_GLX_MESA_swap_control (GLXEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glXGetSwapIntervalMESA = (PFNGLXGETSWAPINTERVALMESAPROC)glewGetProcAddress((const GLubyte*)"glXGetSwapIntervalMESA")) == NULL) || r;
+ r = ((glXSwapIntervalMESA = (PFNGLXSWAPINTERVALMESAPROC)glewGetProcAddress((const GLubyte*)"glXSwapIntervalMESA")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GLX_MESA_swap_control */
+
+#ifdef GLX_NV_copy_image
+
+static GLboolean _glewInit_GLX_NV_copy_image (GLXEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glXCopyImageSubDataNV = (PFNGLXCOPYIMAGESUBDATANVPROC)glewGetProcAddress((const GLubyte*)"glXCopyImageSubDataNV")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GLX_NV_copy_image */
+
+#ifdef GLX_NV_float_buffer
+
+#endif /* GLX_NV_float_buffer */
+
+#ifdef GLX_NV_multisample_coverage
+
+#endif /* GLX_NV_multisample_coverage */
+
+#ifdef GLX_NV_present_video
+
+static GLboolean _glewInit_GLX_NV_present_video (GLXEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glXBindVideoDeviceNV = (PFNGLXBINDVIDEODEVICENVPROC)glewGetProcAddress((const GLubyte*)"glXBindVideoDeviceNV")) == NULL) || r;
+ r = ((glXEnumerateVideoDevicesNV = (PFNGLXENUMERATEVIDEODEVICESNVPROC)glewGetProcAddress((const GLubyte*)"glXEnumerateVideoDevicesNV")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GLX_NV_present_video */
+
+#ifdef GLX_NV_swap_group
+
+static GLboolean _glewInit_GLX_NV_swap_group (GLXEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glXBindSwapBarrierNV = (PFNGLXBINDSWAPBARRIERNVPROC)glewGetProcAddress((const GLubyte*)"glXBindSwapBarrierNV")) == NULL) || r;
+ r = ((glXJoinSwapGroupNV = (PFNGLXJOINSWAPGROUPNVPROC)glewGetProcAddress((const GLubyte*)"glXJoinSwapGroupNV")) == NULL) || r;
+ r = ((glXQueryFrameCountNV = (PFNGLXQUERYFRAMECOUNTNVPROC)glewGetProcAddress((const GLubyte*)"glXQueryFrameCountNV")) == NULL) || r;
+ r = ((glXQueryMaxSwapGroupsNV = (PFNGLXQUERYMAXSWAPGROUPSNVPROC)glewGetProcAddress((const GLubyte*)"glXQueryMaxSwapGroupsNV")) == NULL) || r;
+ r = ((glXQuerySwapGroupNV = (PFNGLXQUERYSWAPGROUPNVPROC)glewGetProcAddress((const GLubyte*)"glXQuerySwapGroupNV")) == NULL) || r;
+ r = ((glXResetFrameCountNV = (PFNGLXRESETFRAMECOUNTNVPROC)glewGetProcAddress((const GLubyte*)"glXResetFrameCountNV")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GLX_NV_swap_group */
+
+#ifdef GLX_NV_vertex_array_range
+
+static GLboolean _glewInit_GLX_NV_vertex_array_range (GLXEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glXAllocateMemoryNV = (PFNGLXALLOCATEMEMORYNVPROC)glewGetProcAddress((const GLubyte*)"glXAllocateMemoryNV")) == NULL) || r;
+ r = ((glXFreeMemoryNV = (PFNGLXFREEMEMORYNVPROC)glewGetProcAddress((const GLubyte*)"glXFreeMemoryNV")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GLX_NV_vertex_array_range */
+
+#ifdef GLX_NV_video_capture
+
+static GLboolean _glewInit_GLX_NV_video_capture (GLXEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glXBindVideoCaptureDeviceNV = (PFNGLXBINDVIDEOCAPTUREDEVICENVPROC)glewGetProcAddress((const GLubyte*)"glXBindVideoCaptureDeviceNV")) == NULL) || r;
+ r = ((glXEnumerateVideoCaptureDevicesNV = (PFNGLXENUMERATEVIDEOCAPTUREDEVICESNVPROC)glewGetProcAddress((const GLubyte*)"glXEnumerateVideoCaptureDevicesNV")) == NULL) || r;
+ r = ((glXLockVideoCaptureDeviceNV = (PFNGLXLOCKVIDEOCAPTUREDEVICENVPROC)glewGetProcAddress((const GLubyte*)"glXLockVideoCaptureDeviceNV")) == NULL) || r;
+ r = ((glXQueryVideoCaptureDeviceNV = (PFNGLXQUERYVIDEOCAPTUREDEVICENVPROC)glewGetProcAddress((const GLubyte*)"glXQueryVideoCaptureDeviceNV")) == NULL) || r;
+ r = ((glXReleaseVideoCaptureDeviceNV = (PFNGLXRELEASEVIDEOCAPTUREDEVICENVPROC)glewGetProcAddress((const GLubyte*)"glXReleaseVideoCaptureDeviceNV")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GLX_NV_video_capture */
+
+#ifdef GLX_NV_video_output
+
+static GLboolean _glewInit_GLX_NV_video_output (GLXEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glXBindVideoImageNV = (PFNGLXBINDVIDEOIMAGENVPROC)glewGetProcAddress((const GLubyte*)"glXBindVideoImageNV")) == NULL) || r;
+ r = ((glXGetVideoDeviceNV = (PFNGLXGETVIDEODEVICENVPROC)glewGetProcAddress((const GLubyte*)"glXGetVideoDeviceNV")) == NULL) || r;
+ r = ((glXGetVideoInfoNV = (PFNGLXGETVIDEOINFONVPROC)glewGetProcAddress((const GLubyte*)"glXGetVideoInfoNV")) == NULL) || r;
+ r = ((glXReleaseVideoDeviceNV = (PFNGLXRELEASEVIDEODEVICENVPROC)glewGetProcAddress((const GLubyte*)"glXReleaseVideoDeviceNV")) == NULL) || r;
+ r = ((glXReleaseVideoImageNV = (PFNGLXRELEASEVIDEOIMAGENVPROC)glewGetProcAddress((const GLubyte*)"glXReleaseVideoImageNV")) == NULL) || r;
+ r = ((glXSendPbufferToVideoNV = (PFNGLXSENDPBUFFERTOVIDEONVPROC)glewGetProcAddress((const GLubyte*)"glXSendPbufferToVideoNV")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GLX_NV_video_output */
+
+#ifdef GLX_OML_swap_method
+
+#endif /* GLX_OML_swap_method */
+
+#ifdef GLX_OML_sync_control
+
+static GLboolean _glewInit_GLX_OML_sync_control (GLXEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glXGetMscRateOML = (PFNGLXGETMSCRATEOMLPROC)glewGetProcAddress((const GLubyte*)"glXGetMscRateOML")) == NULL) || r;
+ r = ((glXGetSyncValuesOML = (PFNGLXGETSYNCVALUESOMLPROC)glewGetProcAddress((const GLubyte*)"glXGetSyncValuesOML")) == NULL) || r;
+ r = ((glXSwapBuffersMscOML = (PFNGLXSWAPBUFFERSMSCOMLPROC)glewGetProcAddress((const GLubyte*)"glXSwapBuffersMscOML")) == NULL) || r;
+ r = ((glXWaitForMscOML = (PFNGLXWAITFORMSCOMLPROC)glewGetProcAddress((const GLubyte*)"glXWaitForMscOML")) == NULL) || r;
+ r = ((glXWaitForSbcOML = (PFNGLXWAITFORSBCOMLPROC)glewGetProcAddress((const GLubyte*)"glXWaitForSbcOML")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GLX_OML_sync_control */
+
+#ifdef GLX_SGIS_blended_overlay
+
+#endif /* GLX_SGIS_blended_overlay */
+
+#ifdef GLX_SGIS_color_range
+
+#endif /* GLX_SGIS_color_range */
+
+#ifdef GLX_SGIS_multisample
+
+#endif /* GLX_SGIS_multisample */
+
+#ifdef GLX_SGIS_shared_multisample
+
+#endif /* GLX_SGIS_shared_multisample */
+
+#ifdef GLX_SGIX_fbconfig
+
+static GLboolean _glewInit_GLX_SGIX_fbconfig (GLXEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glXChooseFBConfigSGIX = (PFNGLXCHOOSEFBCONFIGSGIXPROC)glewGetProcAddress((const GLubyte*)"glXChooseFBConfigSGIX")) == NULL) || r;
+ r = ((glXCreateContextWithConfigSGIX = (PFNGLXCREATECONTEXTWITHCONFIGSGIXPROC)glewGetProcAddress((const GLubyte*)"glXCreateContextWithConfigSGIX")) == NULL) || r;
+ r = ((glXCreateGLXPixmapWithConfigSGIX = (PFNGLXCREATEGLXPIXMAPWITHCONFIGSGIXPROC)glewGetProcAddress((const GLubyte*)"glXCreateGLXPixmapWithConfigSGIX")) == NULL) || r;
+ r = ((glXGetFBConfigAttribSGIX = (PFNGLXGETFBCONFIGATTRIBSGIXPROC)glewGetProcAddress((const GLubyte*)"glXGetFBConfigAttribSGIX")) == NULL) || r;
+ r = ((glXGetFBConfigFromVisualSGIX = (PFNGLXGETFBCONFIGFROMVISUALSGIXPROC)glewGetProcAddress((const GLubyte*)"glXGetFBConfigFromVisualSGIX")) == NULL) || r;
+ r = ((glXGetVisualFromFBConfigSGIX = (PFNGLXGETVISUALFROMFBCONFIGSGIXPROC)glewGetProcAddress((const GLubyte*)"glXGetVisualFromFBConfigSGIX")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GLX_SGIX_fbconfig */
+
+#ifdef GLX_SGIX_hyperpipe
+
+static GLboolean _glewInit_GLX_SGIX_hyperpipe (GLXEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glXBindHyperpipeSGIX = (PFNGLXBINDHYPERPIPESGIXPROC)glewGetProcAddress((const GLubyte*)"glXBindHyperpipeSGIX")) == NULL) || r;
+ r = ((glXDestroyHyperpipeConfigSGIX = (PFNGLXDESTROYHYPERPIPECONFIGSGIXPROC)glewGetProcAddress((const GLubyte*)"glXDestroyHyperpipeConfigSGIX")) == NULL) || r;
+ r = ((glXHyperpipeAttribSGIX = (PFNGLXHYPERPIPEATTRIBSGIXPROC)glewGetProcAddress((const GLubyte*)"glXHyperpipeAttribSGIX")) == NULL) || r;
+ r = ((glXHyperpipeConfigSGIX = (PFNGLXHYPERPIPECONFIGSGIXPROC)glewGetProcAddress((const GLubyte*)"glXHyperpipeConfigSGIX")) == NULL) || r;
+ r = ((glXQueryHyperpipeAttribSGIX = (PFNGLXQUERYHYPERPIPEATTRIBSGIXPROC)glewGetProcAddress((const GLubyte*)"glXQueryHyperpipeAttribSGIX")) == NULL) || r;
+ r = ((glXQueryHyperpipeBestAttribSGIX = (PFNGLXQUERYHYPERPIPEBESTATTRIBSGIXPROC)glewGetProcAddress((const GLubyte*)"glXQueryHyperpipeBestAttribSGIX")) == NULL) || r;
+ r = ((glXQueryHyperpipeConfigSGIX = (PFNGLXQUERYHYPERPIPECONFIGSGIXPROC)glewGetProcAddress((const GLubyte*)"glXQueryHyperpipeConfigSGIX")) == NULL) || r;
+ r = ((glXQueryHyperpipeNetworkSGIX = (PFNGLXQUERYHYPERPIPENETWORKSGIXPROC)glewGetProcAddress((const GLubyte*)"glXQueryHyperpipeNetworkSGIX")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GLX_SGIX_hyperpipe */
+
+#ifdef GLX_SGIX_pbuffer
+
+static GLboolean _glewInit_GLX_SGIX_pbuffer (GLXEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glXCreateGLXPbufferSGIX = (PFNGLXCREATEGLXPBUFFERSGIXPROC)glewGetProcAddress((const GLubyte*)"glXCreateGLXPbufferSGIX")) == NULL) || r;
+ r = ((glXDestroyGLXPbufferSGIX = (PFNGLXDESTROYGLXPBUFFERSGIXPROC)glewGetProcAddress((const GLubyte*)"glXDestroyGLXPbufferSGIX")) == NULL) || r;
+ r = ((glXGetSelectedEventSGIX = (PFNGLXGETSELECTEDEVENTSGIXPROC)glewGetProcAddress((const GLubyte*)"glXGetSelectedEventSGIX")) == NULL) || r;
+ r = ((glXQueryGLXPbufferSGIX = (PFNGLXQUERYGLXPBUFFERSGIXPROC)glewGetProcAddress((const GLubyte*)"glXQueryGLXPbufferSGIX")) == NULL) || r;
+ r = ((glXSelectEventSGIX = (PFNGLXSELECTEVENTSGIXPROC)glewGetProcAddress((const GLubyte*)"glXSelectEventSGIX")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GLX_SGIX_pbuffer */
+
+#ifdef GLX_SGIX_swap_barrier
+
+static GLboolean _glewInit_GLX_SGIX_swap_barrier (GLXEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glXBindSwapBarrierSGIX = (PFNGLXBINDSWAPBARRIERSGIXPROC)glewGetProcAddress((const GLubyte*)"glXBindSwapBarrierSGIX")) == NULL) || r;
+ r = ((glXQueryMaxSwapBarriersSGIX = (PFNGLXQUERYMAXSWAPBARRIERSSGIXPROC)glewGetProcAddress((const GLubyte*)"glXQueryMaxSwapBarriersSGIX")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GLX_SGIX_swap_barrier */
+
+#ifdef GLX_SGIX_swap_group
+
+static GLboolean _glewInit_GLX_SGIX_swap_group (GLXEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glXJoinSwapGroupSGIX = (PFNGLXJOINSWAPGROUPSGIXPROC)glewGetProcAddress((const GLubyte*)"glXJoinSwapGroupSGIX")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GLX_SGIX_swap_group */
+
+#ifdef GLX_SGIX_video_resize
+
+static GLboolean _glewInit_GLX_SGIX_video_resize (GLXEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glXBindChannelToWindowSGIX = (PFNGLXBINDCHANNELTOWINDOWSGIXPROC)glewGetProcAddress((const GLubyte*)"glXBindChannelToWindowSGIX")) == NULL) || r;
+ r = ((glXChannelRectSGIX = (PFNGLXCHANNELRECTSGIXPROC)glewGetProcAddress((const GLubyte*)"glXChannelRectSGIX")) == NULL) || r;
+ r = ((glXChannelRectSyncSGIX = (PFNGLXCHANNELRECTSYNCSGIXPROC)glewGetProcAddress((const GLubyte*)"glXChannelRectSyncSGIX")) == NULL) || r;
+ r = ((glXQueryChannelDeltasSGIX = (PFNGLXQUERYCHANNELDELTASSGIXPROC)glewGetProcAddress((const GLubyte*)"glXQueryChannelDeltasSGIX")) == NULL) || r;
+ r = ((glXQueryChannelRectSGIX = (PFNGLXQUERYCHANNELRECTSGIXPROC)glewGetProcAddress((const GLubyte*)"glXQueryChannelRectSGIX")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GLX_SGIX_video_resize */
+
+#ifdef GLX_SGIX_visual_select_group
+
+#endif /* GLX_SGIX_visual_select_group */
+
+#ifdef GLX_SGI_cushion
+
+static GLboolean _glewInit_GLX_SGI_cushion (GLXEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glXCushionSGI = (PFNGLXCUSHIONSGIPROC)glewGetProcAddress((const GLubyte*)"glXCushionSGI")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GLX_SGI_cushion */
+
+#ifdef GLX_SGI_make_current_read
+
+static GLboolean _glewInit_GLX_SGI_make_current_read (GLXEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glXGetCurrentReadDrawableSGI = (PFNGLXGETCURRENTREADDRAWABLESGIPROC)glewGetProcAddress((const GLubyte*)"glXGetCurrentReadDrawableSGI")) == NULL) || r;
+ r = ((glXMakeCurrentReadSGI = (PFNGLXMAKECURRENTREADSGIPROC)glewGetProcAddress((const GLubyte*)"glXMakeCurrentReadSGI")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GLX_SGI_make_current_read */
+
+#ifdef GLX_SGI_swap_control
+
+static GLboolean _glewInit_GLX_SGI_swap_control (GLXEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glXSwapIntervalSGI = (PFNGLXSWAPINTERVALSGIPROC)glewGetProcAddress((const GLubyte*)"glXSwapIntervalSGI")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GLX_SGI_swap_control */
+
+#ifdef GLX_SGI_video_sync
+
+static GLboolean _glewInit_GLX_SGI_video_sync (GLXEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glXGetVideoSyncSGI = (PFNGLXGETVIDEOSYNCSGIPROC)glewGetProcAddress((const GLubyte*)"glXGetVideoSyncSGI")) == NULL) || r;
+ r = ((glXWaitVideoSyncSGI = (PFNGLXWAITVIDEOSYNCSGIPROC)glewGetProcAddress((const GLubyte*)"glXWaitVideoSyncSGI")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GLX_SGI_video_sync */
+
+#ifdef GLX_SUN_get_transparent_index
+
+static GLboolean _glewInit_GLX_SUN_get_transparent_index (GLXEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glXGetTransparentIndexSUN = (PFNGLXGETTRANSPARENTINDEXSUNPROC)glewGetProcAddress((const GLubyte*)"glXGetTransparentIndexSUN")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GLX_SUN_get_transparent_index */
+
+#ifdef GLX_SUN_video_resize
+
+static GLboolean _glewInit_GLX_SUN_video_resize (GLXEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glXGetVideoResizeSUN = (PFNGLXGETVIDEORESIZESUNPROC)glewGetProcAddress((const GLubyte*)"glXGetVideoResizeSUN")) == NULL) || r;
+ r = ((glXVideoResizeSUN = (PFNGLXVIDEORESIZESUNPROC)glewGetProcAddress((const GLubyte*)"glXVideoResizeSUN")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GLX_SUN_video_resize */
+
+/* ------------------------------------------------------------------------ */
+
+GLboolean glxewGetExtension (const char* name)
+{
+ const GLubyte* start;
+ const GLubyte* end;
+
+ if (glXGetCurrentDisplay == NULL) return GL_FALSE;
+ start = (const GLubyte*)glXGetClientString(glXGetCurrentDisplay(), GLX_EXTENSIONS);
+ if (0 == start) return GL_FALSE;
+ end = start + _glewStrLen(start);
+ return _glewSearchExtension(name, start, end);
+}
+
+GLenum glxewContextInit (GLXEW_CONTEXT_ARG_DEF_LIST)
+{
+ int major, minor;
+ const GLubyte* extStart;
+ const GLubyte* extEnd;
+ /* initialize core GLX 1.2 */
+ if (_glewInit_GLX_VERSION_1_2(GLEW_CONTEXT_ARG_VAR_INIT)) return GLEW_ERROR_GLX_VERSION_11_ONLY;
+ /* initialize flags */
+ CONST_CAST(GLXEW_VERSION_1_0) = GL_TRUE;
+ CONST_CAST(GLXEW_VERSION_1_1) = GL_TRUE;
+ CONST_CAST(GLXEW_VERSION_1_2) = GL_TRUE;
+ CONST_CAST(GLXEW_VERSION_1_3) = GL_TRUE;
+ CONST_CAST(GLXEW_VERSION_1_4) = GL_TRUE;
+ /* query GLX version */
+ glXQueryVersion(glXGetCurrentDisplay(), &major, &minor);
+ if (major == 1 && minor <= 3)
+ {
+ switch (minor)
+ {
+ case 3:
+ CONST_CAST(GLXEW_VERSION_1_4) = GL_FALSE;
+ break;
+ case 2:
+ CONST_CAST(GLXEW_VERSION_1_4) = GL_FALSE;
+ CONST_CAST(GLXEW_VERSION_1_3) = GL_FALSE;
+ break;
+ default:
+ return GLEW_ERROR_GLX_VERSION_11_ONLY;
+ break;
+ }
+ }
+ /* query GLX extension string */
+ extStart = 0;
+ if (glXGetCurrentDisplay != NULL)
+ extStart = (const GLubyte*)glXGetClientString(glXGetCurrentDisplay(), GLX_EXTENSIONS);
+ if (extStart == 0)
+ extStart = (const GLubyte *)"";
+ extEnd = extStart + _glewStrLen(extStart);
+ /* initialize extensions */
+#ifdef GLX_VERSION_1_3
+ if (glewExperimental || GLXEW_VERSION_1_3) CONST_CAST(GLXEW_VERSION_1_3) = !_glewInit_GLX_VERSION_1_3(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GLX_VERSION_1_3 */
+#ifdef GLX_3DFX_multisample
+ CONST_CAST(GLXEW_3DFX_multisample) = _glewSearchExtension("GLX_3DFX_multisample", extStart, extEnd);
+#endif /* GLX_3DFX_multisample */
+#ifdef GLX_AMD_gpu_association
+ CONST_CAST(GLXEW_AMD_gpu_association) = _glewSearchExtension("GLX_AMD_gpu_association", extStart, extEnd);
+#endif /* GLX_AMD_gpu_association */
+#ifdef GLX_ARB_create_context
+ CONST_CAST(GLXEW_ARB_create_context) = _glewSearchExtension("GLX_ARB_create_context", extStart, extEnd);
+ if (glewExperimental || GLXEW_ARB_create_context) CONST_CAST(GLXEW_ARB_create_context) = !_glewInit_GLX_ARB_create_context(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GLX_ARB_create_context */
+#ifdef GLX_ARB_create_context_profile
+ CONST_CAST(GLXEW_ARB_create_context_profile) = _glewSearchExtension("GLX_ARB_create_context_profile", extStart, extEnd);
+#endif /* GLX_ARB_create_context_profile */
+#ifdef GLX_ARB_create_context_robustness
+ CONST_CAST(GLXEW_ARB_create_context_robustness) = _glewSearchExtension("GLX_ARB_create_context_robustness", extStart, extEnd);
+#endif /* GLX_ARB_create_context_robustness */
+#ifdef GLX_ARB_fbconfig_float
+ CONST_CAST(GLXEW_ARB_fbconfig_float) = _glewSearchExtension("GLX_ARB_fbconfig_float", extStart, extEnd);
+#endif /* GLX_ARB_fbconfig_float */
+#ifdef GLX_ARB_framebuffer_sRGB
+ CONST_CAST(GLXEW_ARB_framebuffer_sRGB) = _glewSearchExtension("GLX_ARB_framebuffer_sRGB", extStart, extEnd);
+#endif /* GLX_ARB_framebuffer_sRGB */
+#ifdef GLX_ARB_get_proc_address
+ CONST_CAST(GLXEW_ARB_get_proc_address) = _glewSearchExtension("GLX_ARB_get_proc_address", extStart, extEnd);
+#endif /* GLX_ARB_get_proc_address */
+#ifdef GLX_ARB_multisample
+ CONST_CAST(GLXEW_ARB_multisample) = _glewSearchExtension("GLX_ARB_multisample", extStart, extEnd);
+#endif /* GLX_ARB_multisample */
+#ifdef GLX_ARB_robustness_application_isolation
+ CONST_CAST(GLXEW_ARB_robustness_application_isolation) = _glewSearchExtension("GLX_ARB_robustness_application_isolation", extStart, extEnd);
+#endif /* GLX_ARB_robustness_application_isolation */
+#ifdef GLX_ARB_robustness_share_group_isolation
+ CONST_CAST(GLXEW_ARB_robustness_share_group_isolation) = _glewSearchExtension("GLX_ARB_robustness_share_group_isolation", extStart, extEnd);
+#endif /* GLX_ARB_robustness_share_group_isolation */
+#ifdef GLX_ARB_vertex_buffer_object
+ CONST_CAST(GLXEW_ARB_vertex_buffer_object) = _glewSearchExtension("GLX_ARB_vertex_buffer_object", extStart, extEnd);
+#endif /* GLX_ARB_vertex_buffer_object */
+#ifdef GLX_ATI_pixel_format_float
+ CONST_CAST(GLXEW_ATI_pixel_format_float) = _glewSearchExtension("GLX_ATI_pixel_format_float", extStart, extEnd);
+#endif /* GLX_ATI_pixel_format_float */
+#ifdef GLX_ATI_render_texture
+ CONST_CAST(GLXEW_ATI_render_texture) = _glewSearchExtension("GLX_ATI_render_texture", extStart, extEnd);
+ if (glewExperimental || GLXEW_ATI_render_texture) CONST_CAST(GLXEW_ATI_render_texture) = !_glewInit_GLX_ATI_render_texture(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GLX_ATI_render_texture */
+#ifdef GLX_EXT_buffer_age
+ CONST_CAST(GLXEW_EXT_buffer_age) = _glewSearchExtension("GLX_EXT_buffer_age", extStart, extEnd);
+#endif /* GLX_EXT_buffer_age */
+#ifdef GLX_EXT_create_context_es2_profile
+ CONST_CAST(GLXEW_EXT_create_context_es2_profile) = _glewSearchExtension("GLX_EXT_create_context_es2_profile", extStart, extEnd);
+#endif /* GLX_EXT_create_context_es2_profile */
+#ifdef GLX_EXT_create_context_es_profile
+ CONST_CAST(GLXEW_EXT_create_context_es_profile) = _glewSearchExtension("GLX_EXT_create_context_es_profile", extStart, extEnd);
+#endif /* GLX_EXT_create_context_es_profile */
+#ifdef GLX_EXT_fbconfig_packed_float
+ CONST_CAST(GLXEW_EXT_fbconfig_packed_float) = _glewSearchExtension("GLX_EXT_fbconfig_packed_float", extStart, extEnd);
+#endif /* GLX_EXT_fbconfig_packed_float */
+#ifdef GLX_EXT_framebuffer_sRGB
+ CONST_CAST(GLXEW_EXT_framebuffer_sRGB) = _glewSearchExtension("GLX_EXT_framebuffer_sRGB", extStart, extEnd);
+#endif /* GLX_EXT_framebuffer_sRGB */
+#ifdef GLX_EXT_import_context
+ CONST_CAST(GLXEW_EXT_import_context) = _glewSearchExtension("GLX_EXT_import_context", extStart, extEnd);
+ if (glewExperimental || GLXEW_EXT_import_context) CONST_CAST(GLXEW_EXT_import_context) = !_glewInit_GLX_EXT_import_context(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GLX_EXT_import_context */
+#ifdef GLX_EXT_scene_marker
+ CONST_CAST(GLXEW_EXT_scene_marker) = _glewSearchExtension("GLX_EXT_scene_marker", extStart, extEnd);
+#endif /* GLX_EXT_scene_marker */
+#ifdef GLX_EXT_swap_control
+ CONST_CAST(GLXEW_EXT_swap_control) = _glewSearchExtension("GLX_EXT_swap_control", extStart, extEnd);
+ if (glewExperimental || GLXEW_EXT_swap_control) CONST_CAST(GLXEW_EXT_swap_control) = !_glewInit_GLX_EXT_swap_control(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GLX_EXT_swap_control */
+#ifdef GLX_EXT_swap_control_tear
+ CONST_CAST(GLXEW_EXT_swap_control_tear) = _glewSearchExtension("GLX_EXT_swap_control_tear", extStart, extEnd);
+#endif /* GLX_EXT_swap_control_tear */
+#ifdef GLX_EXT_texture_from_pixmap
+ CONST_CAST(GLXEW_EXT_texture_from_pixmap) = _glewSearchExtension("GLX_EXT_texture_from_pixmap", extStart, extEnd);
+ if (glewExperimental || GLXEW_EXT_texture_from_pixmap) CONST_CAST(GLXEW_EXT_texture_from_pixmap) = !_glewInit_GLX_EXT_texture_from_pixmap(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GLX_EXT_texture_from_pixmap */
+#ifdef GLX_EXT_visual_info
+ CONST_CAST(GLXEW_EXT_visual_info) = _glewSearchExtension("GLX_EXT_visual_info", extStart, extEnd);
+#endif /* GLX_EXT_visual_info */
+#ifdef GLX_EXT_visual_rating
+ CONST_CAST(GLXEW_EXT_visual_rating) = _glewSearchExtension("GLX_EXT_visual_rating", extStart, extEnd);
+#endif /* GLX_EXT_visual_rating */
+#ifdef GLX_INTEL_swap_event
+ CONST_CAST(GLXEW_INTEL_swap_event) = _glewSearchExtension("GLX_INTEL_swap_event", extStart, extEnd);
+#endif /* GLX_INTEL_swap_event */
+#ifdef GLX_MESA_agp_offset
+ CONST_CAST(GLXEW_MESA_agp_offset) = _glewSearchExtension("GLX_MESA_agp_offset", extStart, extEnd);
+ if (glewExperimental || GLXEW_MESA_agp_offset) CONST_CAST(GLXEW_MESA_agp_offset) = !_glewInit_GLX_MESA_agp_offset(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GLX_MESA_agp_offset */
+#ifdef GLX_MESA_copy_sub_buffer
+ CONST_CAST(GLXEW_MESA_copy_sub_buffer) = _glewSearchExtension("GLX_MESA_copy_sub_buffer", extStart, extEnd);
+ if (glewExperimental || GLXEW_MESA_copy_sub_buffer) CONST_CAST(GLXEW_MESA_copy_sub_buffer) = !_glewInit_GLX_MESA_copy_sub_buffer(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GLX_MESA_copy_sub_buffer */
+#ifdef GLX_MESA_pixmap_colormap
+ CONST_CAST(GLXEW_MESA_pixmap_colormap) = _glewSearchExtension("GLX_MESA_pixmap_colormap", extStart, extEnd);
+ if (glewExperimental || GLXEW_MESA_pixmap_colormap) CONST_CAST(GLXEW_MESA_pixmap_colormap) = !_glewInit_GLX_MESA_pixmap_colormap(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GLX_MESA_pixmap_colormap */
+#ifdef GLX_MESA_release_buffers
+ CONST_CAST(GLXEW_MESA_release_buffers) = _glewSearchExtension("GLX_MESA_release_buffers", extStart, extEnd);
+ if (glewExperimental || GLXEW_MESA_release_buffers) CONST_CAST(GLXEW_MESA_release_buffers) = !_glewInit_GLX_MESA_release_buffers(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GLX_MESA_release_buffers */
+#ifdef GLX_MESA_set_3dfx_mode
+ CONST_CAST(GLXEW_MESA_set_3dfx_mode) = _glewSearchExtension("GLX_MESA_set_3dfx_mode", extStart, extEnd);
+ if (glewExperimental || GLXEW_MESA_set_3dfx_mode) CONST_CAST(GLXEW_MESA_set_3dfx_mode) = !_glewInit_GLX_MESA_set_3dfx_mode(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GLX_MESA_set_3dfx_mode */
+#ifdef GLX_MESA_swap_control
+ CONST_CAST(GLXEW_MESA_swap_control) = _glewSearchExtension("GLX_MESA_swap_control", extStart, extEnd);
+ if (glewExperimental || GLXEW_MESA_swap_control) CONST_CAST(GLXEW_MESA_swap_control) = !_glewInit_GLX_MESA_swap_control(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GLX_MESA_swap_control */
+#ifdef GLX_NV_copy_image
+ CONST_CAST(GLXEW_NV_copy_image) = _glewSearchExtension("GLX_NV_copy_image", extStart, extEnd);
+ if (glewExperimental || GLXEW_NV_copy_image) CONST_CAST(GLXEW_NV_copy_image) = !_glewInit_GLX_NV_copy_image(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GLX_NV_copy_image */
+#ifdef GLX_NV_float_buffer
+ CONST_CAST(GLXEW_NV_float_buffer) = _glewSearchExtension("GLX_NV_float_buffer", extStart, extEnd);
+#endif /* GLX_NV_float_buffer */
+#ifdef GLX_NV_multisample_coverage
+ CONST_CAST(GLXEW_NV_multisample_coverage) = _glewSearchExtension("GLX_NV_multisample_coverage", extStart, extEnd);
+#endif /* GLX_NV_multisample_coverage */
+#ifdef GLX_NV_present_video
+ CONST_CAST(GLXEW_NV_present_video) = _glewSearchExtension("GLX_NV_present_video", extStart, extEnd);
+ if (glewExperimental || GLXEW_NV_present_video) CONST_CAST(GLXEW_NV_present_video) = !_glewInit_GLX_NV_present_video(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GLX_NV_present_video */
+#ifdef GLX_NV_swap_group
+ CONST_CAST(GLXEW_NV_swap_group) = _glewSearchExtension("GLX_NV_swap_group", extStart, extEnd);
+ if (glewExperimental || GLXEW_NV_swap_group) CONST_CAST(GLXEW_NV_swap_group) = !_glewInit_GLX_NV_swap_group(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GLX_NV_swap_group */
+#ifdef GLX_NV_vertex_array_range
+ CONST_CAST(GLXEW_NV_vertex_array_range) = _glewSearchExtension("GLX_NV_vertex_array_range", extStart, extEnd);
+ if (glewExperimental || GLXEW_NV_vertex_array_range) CONST_CAST(GLXEW_NV_vertex_array_range) = !_glewInit_GLX_NV_vertex_array_range(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GLX_NV_vertex_array_range */
+#ifdef GLX_NV_video_capture
+ CONST_CAST(GLXEW_NV_video_capture) = _glewSearchExtension("GLX_NV_video_capture", extStart, extEnd);
+ if (glewExperimental || GLXEW_NV_video_capture) CONST_CAST(GLXEW_NV_video_capture) = !_glewInit_GLX_NV_video_capture(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GLX_NV_video_capture */
+#ifdef GLX_NV_video_output
+ CONST_CAST(GLXEW_NV_video_output) = _glewSearchExtension("GLX_NV_video_output", extStart, extEnd);
+ if (glewExperimental || GLXEW_NV_video_output) CONST_CAST(GLXEW_NV_video_output) = !_glewInit_GLX_NV_video_output(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GLX_NV_video_output */
+#ifdef GLX_OML_swap_method
+ CONST_CAST(GLXEW_OML_swap_method) = _glewSearchExtension("GLX_OML_swap_method", extStart, extEnd);
+#endif /* GLX_OML_swap_method */
+#ifdef GLX_OML_sync_control
+ CONST_CAST(GLXEW_OML_sync_control) = _glewSearchExtension("GLX_OML_sync_control", extStart, extEnd);
+ if (glewExperimental || GLXEW_OML_sync_control) CONST_CAST(GLXEW_OML_sync_control) = !_glewInit_GLX_OML_sync_control(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GLX_OML_sync_control */
+#ifdef GLX_SGIS_blended_overlay
+ CONST_CAST(GLXEW_SGIS_blended_overlay) = _glewSearchExtension("GLX_SGIS_blended_overlay", extStart, extEnd);
+#endif /* GLX_SGIS_blended_overlay */
+#ifdef GLX_SGIS_color_range
+ CONST_CAST(GLXEW_SGIS_color_range) = _glewSearchExtension("GLX_SGIS_color_range", extStart, extEnd);
+#endif /* GLX_SGIS_color_range */
+#ifdef GLX_SGIS_multisample
+ CONST_CAST(GLXEW_SGIS_multisample) = _glewSearchExtension("GLX_SGIS_multisample", extStart, extEnd);
+#endif /* GLX_SGIS_multisample */
+#ifdef GLX_SGIS_shared_multisample
+ CONST_CAST(GLXEW_SGIS_shared_multisample) = _glewSearchExtension("GLX_SGIS_shared_multisample", extStart, extEnd);
+#endif /* GLX_SGIS_shared_multisample */
+#ifdef GLX_SGIX_fbconfig
+ CONST_CAST(GLXEW_SGIX_fbconfig) = _glewSearchExtension("GLX_SGIX_fbconfig", extStart, extEnd);
+ if (glewExperimental || GLXEW_SGIX_fbconfig) CONST_CAST(GLXEW_SGIX_fbconfig) = !_glewInit_GLX_SGIX_fbconfig(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GLX_SGIX_fbconfig */
+#ifdef GLX_SGIX_hyperpipe
+ CONST_CAST(GLXEW_SGIX_hyperpipe) = _glewSearchExtension("GLX_SGIX_hyperpipe", extStart, extEnd);
+ if (glewExperimental || GLXEW_SGIX_hyperpipe) CONST_CAST(GLXEW_SGIX_hyperpipe) = !_glewInit_GLX_SGIX_hyperpipe(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GLX_SGIX_hyperpipe */
+#ifdef GLX_SGIX_pbuffer
+ CONST_CAST(GLXEW_SGIX_pbuffer) = _glewSearchExtension("GLX_SGIX_pbuffer", extStart, extEnd);
+ if (glewExperimental || GLXEW_SGIX_pbuffer) CONST_CAST(GLXEW_SGIX_pbuffer) = !_glewInit_GLX_SGIX_pbuffer(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GLX_SGIX_pbuffer */
+#ifdef GLX_SGIX_swap_barrier
+ CONST_CAST(GLXEW_SGIX_swap_barrier) = _glewSearchExtension("GLX_SGIX_swap_barrier", extStart, extEnd);
+ if (glewExperimental || GLXEW_SGIX_swap_barrier) CONST_CAST(GLXEW_SGIX_swap_barrier) = !_glewInit_GLX_SGIX_swap_barrier(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GLX_SGIX_swap_barrier */
+#ifdef GLX_SGIX_swap_group
+ CONST_CAST(GLXEW_SGIX_swap_group) = _glewSearchExtension("GLX_SGIX_swap_group", extStart, extEnd);
+ if (glewExperimental || GLXEW_SGIX_swap_group) CONST_CAST(GLXEW_SGIX_swap_group) = !_glewInit_GLX_SGIX_swap_group(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GLX_SGIX_swap_group */
+#ifdef GLX_SGIX_video_resize
+ CONST_CAST(GLXEW_SGIX_video_resize) = _glewSearchExtension("GLX_SGIX_video_resize", extStart, extEnd);
+ if (glewExperimental || GLXEW_SGIX_video_resize) CONST_CAST(GLXEW_SGIX_video_resize) = !_glewInit_GLX_SGIX_video_resize(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GLX_SGIX_video_resize */
+#ifdef GLX_SGIX_visual_select_group
+ CONST_CAST(GLXEW_SGIX_visual_select_group) = _glewSearchExtension("GLX_SGIX_visual_select_group", extStart, extEnd);
+#endif /* GLX_SGIX_visual_select_group */
+#ifdef GLX_SGI_cushion
+ CONST_CAST(GLXEW_SGI_cushion) = _glewSearchExtension("GLX_SGI_cushion", extStart, extEnd);
+ if (glewExperimental || GLXEW_SGI_cushion) CONST_CAST(GLXEW_SGI_cushion) = !_glewInit_GLX_SGI_cushion(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GLX_SGI_cushion */
+#ifdef GLX_SGI_make_current_read
+ CONST_CAST(GLXEW_SGI_make_current_read) = _glewSearchExtension("GLX_SGI_make_current_read", extStart, extEnd);
+ if (glewExperimental || GLXEW_SGI_make_current_read) CONST_CAST(GLXEW_SGI_make_current_read) = !_glewInit_GLX_SGI_make_current_read(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GLX_SGI_make_current_read */
+#ifdef GLX_SGI_swap_control
+ CONST_CAST(GLXEW_SGI_swap_control) = _glewSearchExtension("GLX_SGI_swap_control", extStart, extEnd);
+ if (glewExperimental || GLXEW_SGI_swap_control) CONST_CAST(GLXEW_SGI_swap_control) = !_glewInit_GLX_SGI_swap_control(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GLX_SGI_swap_control */
+#ifdef GLX_SGI_video_sync
+ CONST_CAST(GLXEW_SGI_video_sync) = _glewSearchExtension("GLX_SGI_video_sync", extStart, extEnd);
+ if (glewExperimental || GLXEW_SGI_video_sync) CONST_CAST(GLXEW_SGI_video_sync) = !_glewInit_GLX_SGI_video_sync(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GLX_SGI_video_sync */
+#ifdef GLX_SUN_get_transparent_index
+ CONST_CAST(GLXEW_SUN_get_transparent_index) = _glewSearchExtension("GLX_SUN_get_transparent_index", extStart, extEnd);
+ if (glewExperimental || GLXEW_SUN_get_transparent_index) CONST_CAST(GLXEW_SUN_get_transparent_index) = !_glewInit_GLX_SUN_get_transparent_index(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GLX_SUN_get_transparent_index */
+#ifdef GLX_SUN_video_resize
+ CONST_CAST(GLXEW_SUN_video_resize) = _glewSearchExtension("GLX_SUN_video_resize", extStart, extEnd);
+ if (glewExperimental || GLXEW_SUN_video_resize) CONST_CAST(GLXEW_SUN_video_resize) = !_glewInit_GLX_SUN_video_resize(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GLX_SUN_video_resize */
+
+ return GLEW_OK;
+}
+
+#endif /* !__APPLE__ || GLEW_APPLE_GLX */
+
+/* ------------------------------------------------------------------------ */
+
+const GLubyte* glewGetErrorString (GLenum error)
+{
+ static const GLubyte* _glewErrorString[] =
+ {
+ (const GLubyte*)"No error",
+ (const GLubyte*)"Missing GL version",
+ (const GLubyte*)"GL 1.1 and up are supported",
+ (const GLubyte*)"GLX 1.2 and up are supported",
+ (const GLubyte*)"OpenGL ES lib expected, found OpenGL lib",
+ (const GLubyte*)"OpenGL lib expected, found OpenGL ES lib",
+ (const GLubyte*)"Missing EGL version",
+ (const GLubyte*)"EGL 1.1 and up are supported",
+ (const GLubyte*)"Unknown error"
+ };
+ const int max_error = sizeof(_glewErrorString)/sizeof(*_glewErrorString) - 1;
+ return _glewErrorString[(int)error > max_error ? max_error : (int)error];
+}
+
+const GLubyte* glewGetString (GLenum name)
+{
+ static const GLubyte* _glewString[] =
+ {
+ (const GLubyte*)NULL,
+ (const GLubyte*)"1.7.0",
+ (const GLubyte*)"1",
+ (const GLubyte*)"7",
+ (const GLubyte*)"0"
+ };
+ const int max_string = sizeof(_glewString)/sizeof(*_glewString) - 1;
+ return _glewString[(int)name > max_string ? 0 : (int)name];
+}
+
+/* ------------------------------------------------------------------------ */
+
+GLboolean glewExperimental = GL_FALSE;
+
+#if !defined(GLEW_MX)
+
+#if defined (GLEW_INC_EGL)
+extern GLenum eglewContextInit (EGLDisplay display);
+#elif defined(_WIN32)
+extern GLenum wglewContextInit (void);
+#elif !defined(__APPLE__) || defined(GLEW_APPLE_GLX) /* _UNIX */
+extern GLenum glxewContextInit (void);
+#endif /* _WIN32 */
+
+GLenum glewInit ()
+{
+ GLenum r;
+ if ( (r = glewContextInit()) ) return r;
+#if defined (GLEW_INC_EGL)
+ return eglewContextInit(eglGetCurrentDisplay());
+#elif defined(_WIN32)
+ return wglewContextInit();
+#elif !defined(__APPLE__) || defined(GLEW_APPLE_GLX) /* _UNIX */
+ return glxewContextInit();
+#endif /* GLEW_INC_EGL */
+ return r;
+}
+
+#endif /* !GLEW_MX */
+#ifdef GLEW_MX
+GLboolean glewContextIsSupported (const GLEWContext* ctx, const char* name)
+#else
+GLboolean glewIsSupported (const char* name)
+#endif
+{
+ GLubyte* pos = (GLubyte*)name;
+ GLuint len = _glewStrLen(pos);
+ GLboolean ret = GL_TRUE;
+ while (ret && len > 0)
+ {
+ if (_glewStrSame1(&pos, &len, (const GLubyte*)"GL_", 3))
+ {
+ if (_glewStrSame2(&pos, &len, (const GLubyte*)"3DFX_", 5))
+ {
+#ifdef GL_3DFX_multisample
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"multisample", 11))
+ {
+ ret = GLEW_3DFX_multisample;
+ continue;
+ }
+#endif
+#ifdef GL_3DFX_tbuffer
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"tbuffer", 7))
+ {
+ ret = GLEW_3DFX_tbuffer;
+ continue;
+ }
+#endif
+#ifdef GL_3DFX_texture_compression_FXT1
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_compression_FXT1", 24))
+ {
+ ret = GLEW_3DFX_texture_compression_FXT1;
+ continue;
+ }
+#endif
+ }
+ if (_glewStrSame2(&pos, &len, (const GLubyte*)"AMD_", 4))
+ {
+#ifdef GL_AMD_blend_minmax_factor
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"blend_minmax_factor", 19))
+ {
+ ret = GLEW_AMD_blend_minmax_factor;
+ continue;
+ }
+#endif
+#ifdef GL_AMD_compressed_3DC_texture
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"compressed_3DC_texture", 22))
+ {
+ ret = GLEW_AMD_compressed_3DC_texture;
+ continue;
+ }
+#endif
+#ifdef GL_AMD_compressed_ATC_texture
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"compressed_ATC_texture", 22))
+ {
+ ret = GLEW_AMD_compressed_ATC_texture;
+ continue;
+ }
+#endif
+#ifdef GL_AMD_conservative_depth
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"conservative_depth", 18))
+ {
+ ret = GLEW_AMD_conservative_depth;
+ continue;
+ }
+#endif
+#ifdef GL_AMD_debug_output
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"debug_output", 12))
+ {
+ ret = GLEW_AMD_debug_output;
+ continue;
+ }
+#endif
+#ifdef GL_AMD_depth_clamp_separate
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"depth_clamp_separate", 20))
+ {
+ ret = GLEW_AMD_depth_clamp_separate;
+ continue;
+ }
+#endif
+#ifdef GL_AMD_draw_buffers_blend
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"draw_buffers_blend", 18))
+ {
+ ret = GLEW_AMD_draw_buffers_blend;
+ continue;
+ }
+#endif
+#ifdef GL_AMD_multi_draw_indirect
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"multi_draw_indirect", 19))
+ {
+ ret = GLEW_AMD_multi_draw_indirect;
+ continue;
+ }
+#endif
+#ifdef GL_AMD_name_gen_delete
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"name_gen_delete", 15))
+ {
+ ret = GLEW_AMD_name_gen_delete;
+ continue;
+ }
+#endif
+#ifdef GL_AMD_performance_monitor
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"performance_monitor", 19))
+ {
+ ret = GLEW_AMD_performance_monitor;
+ continue;
+ }
+#endif
+#ifdef GL_AMD_pinned_memory
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"pinned_memory", 13))
+ {
+ ret = GLEW_AMD_pinned_memory;
+ continue;
+ }
+#endif
+#ifdef GL_AMD_program_binary_Z400
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"program_binary_Z400", 19))
+ {
+ ret = GLEW_AMD_program_binary_Z400;
+ continue;
+ }
+#endif
+#ifdef GL_AMD_query_buffer_object
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"query_buffer_object", 19))
+ {
+ ret = GLEW_AMD_query_buffer_object;
+ continue;
+ }
+#endif
+#ifdef GL_AMD_sample_positions
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"sample_positions", 16))
+ {
+ ret = GLEW_AMD_sample_positions;
+ continue;
+ }
+#endif
+#ifdef GL_AMD_seamless_cubemap_per_texture
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"seamless_cubemap_per_texture", 28))
+ {
+ ret = GLEW_AMD_seamless_cubemap_per_texture;
+ continue;
+ }
+#endif
+#ifdef GL_AMD_shader_stencil_export
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"shader_stencil_export", 21))
+ {
+ ret = GLEW_AMD_shader_stencil_export;
+ continue;
+ }
+#endif
+#ifdef GL_AMD_shader_trinary_minmax
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"shader_trinary_minmax", 21))
+ {
+ ret = GLEW_AMD_shader_trinary_minmax;
+ continue;
+ }
+#endif
+#ifdef GL_AMD_sparse_texture
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"sparse_texture", 14))
+ {
+ ret = GLEW_AMD_sparse_texture;
+ continue;
+ }
+#endif
+#ifdef GL_AMD_stencil_operation_extended
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"stencil_operation_extended", 26))
+ {
+ ret = GLEW_AMD_stencil_operation_extended;
+ continue;
+ }
+#endif
+#ifdef GL_AMD_texture_texture4
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_texture4", 16))
+ {
+ ret = GLEW_AMD_texture_texture4;
+ continue;
+ }
+#endif
+#ifdef GL_AMD_transform_feedback3_lines_triangles
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"transform_feedback3_lines_triangles", 35))
+ {
+ ret = GLEW_AMD_transform_feedback3_lines_triangles;
+ continue;
+ }
+#endif
+#ifdef GL_AMD_vertex_shader_layer
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"vertex_shader_layer", 19))
+ {
+ ret = GLEW_AMD_vertex_shader_layer;
+ continue;
+ }
+#endif
+#ifdef GL_AMD_vertex_shader_tessellator
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"vertex_shader_tessellator", 25))
+ {
+ ret = GLEW_AMD_vertex_shader_tessellator;
+ continue;
+ }
+#endif
+#ifdef GL_AMD_vertex_shader_viewport_index
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"vertex_shader_viewport_index", 28))
+ {
+ ret = GLEW_AMD_vertex_shader_viewport_index;
+ continue;
+ }
+#endif
+ }
+ if (_glewStrSame2(&pos, &len, (const GLubyte*)"ANGLE_", 6))
+ {
+#ifdef GL_ANGLE_framebuffer_blit
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"framebuffer_blit", 16))
+ {
+ ret = GLEW_ANGLE_framebuffer_blit;
+ continue;
+ }
+#endif
+#ifdef GL_ANGLE_framebuffer_multisample
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"framebuffer_multisample", 23))
+ {
+ ret = GLEW_ANGLE_framebuffer_multisample;
+ continue;
+ }
+#endif
+#ifdef GL_ANGLE_instanced_arrays
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"instanced_arrays", 16))
+ {
+ ret = GLEW_ANGLE_instanced_arrays;
+ continue;
+ }
+#endif
+#ifdef GL_ANGLE_pack_reverse_row_order
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"pack_reverse_row_order", 22))
+ {
+ ret = GLEW_ANGLE_pack_reverse_row_order;
+ continue;
+ }
+#endif
+#ifdef GL_ANGLE_texture_compression_dxt3
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_compression_dxt3", 24))
+ {
+ ret = GLEW_ANGLE_texture_compression_dxt3;
+ continue;
+ }
+#endif
+#ifdef GL_ANGLE_texture_compression_dxt5
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_compression_dxt5", 24))
+ {
+ ret = GLEW_ANGLE_texture_compression_dxt5;
+ continue;
+ }
+#endif
+#ifdef GL_ANGLE_texture_usage
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_usage", 13))
+ {
+ ret = GLEW_ANGLE_texture_usage;
+ continue;
+ }
+#endif
+#ifdef GL_ANGLE_translated_shader_source
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"translated_shader_source", 24))
+ {
+ ret = GLEW_ANGLE_translated_shader_source;
+ continue;
+ }
+#endif
+ }
+ if (_glewStrSame2(&pos, &len, (const GLubyte*)"APPLE_", 6))
+ {
+#ifdef GL_APPLE_aux_depth_stencil
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"aux_depth_stencil", 17))
+ {
+ ret = GLEW_APPLE_aux_depth_stencil;
+ continue;
+ }
+#endif
+#ifdef GL_APPLE_client_storage
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"client_storage", 14))
+ {
+ ret = GLEW_APPLE_client_storage;
+ continue;
+ }
+#endif
+#ifdef GL_APPLE_copy_texture_levels
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"copy_texture_levels", 19))
+ {
+ ret = GLEW_APPLE_copy_texture_levels;
+ continue;
+ }
+#endif
+#ifdef GL_APPLE_element_array
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"element_array", 13))
+ {
+ ret = GLEW_APPLE_element_array;
+ continue;
+ }
+#endif
+#ifdef GL_APPLE_fence
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"fence", 5))
+ {
+ ret = GLEW_APPLE_fence;
+ continue;
+ }
+#endif
+#ifdef GL_APPLE_float_pixels
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"float_pixels", 12))
+ {
+ ret = GLEW_APPLE_float_pixels;
+ continue;
+ }
+#endif
+#ifdef GL_APPLE_flush_buffer_range
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"flush_buffer_range", 18))
+ {
+ ret = GLEW_APPLE_flush_buffer_range;
+ continue;
+ }
+#endif
+#ifdef GL_APPLE_framebuffer_multisample
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"framebuffer_multisample", 23))
+ {
+ ret = GLEW_APPLE_framebuffer_multisample;
+ continue;
+ }
+#endif
+#ifdef GL_APPLE_object_purgeable
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"object_purgeable", 16))
+ {
+ ret = GLEW_APPLE_object_purgeable;
+ continue;
+ }
+#endif
+#ifdef GL_APPLE_pixel_buffer
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"pixel_buffer", 12))
+ {
+ ret = GLEW_APPLE_pixel_buffer;
+ continue;
+ }
+#endif
+#ifdef GL_APPLE_rgb_422
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"rgb_422", 7))
+ {
+ ret = GLEW_APPLE_rgb_422;
+ continue;
+ }
+#endif
+#ifdef GL_APPLE_row_bytes
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"row_bytes", 9))
+ {
+ ret = GLEW_APPLE_row_bytes;
+ continue;
+ }
+#endif
+#ifdef GL_APPLE_specular_vector
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"specular_vector", 15))
+ {
+ ret = GLEW_APPLE_specular_vector;
+ continue;
+ }
+#endif
+#ifdef GL_APPLE_sync
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"sync", 4))
+ {
+ ret = GLEW_APPLE_sync;
+ continue;
+ }
+#endif
+#ifdef GL_APPLE_texture_2D_limited_npot
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_2D_limited_npot", 23))
+ {
+ ret = GLEW_APPLE_texture_2D_limited_npot;
+ continue;
+ }
+#endif
+#ifdef GL_APPLE_texture_format_BGRA8888
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_format_BGRA8888", 23))
+ {
+ ret = GLEW_APPLE_texture_format_BGRA8888;
+ continue;
+ }
+#endif
+#ifdef GL_APPLE_texture_max_level
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_max_level", 17))
+ {
+ ret = GLEW_APPLE_texture_max_level;
+ continue;
+ }
+#endif
+#ifdef GL_APPLE_texture_range
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_range", 13))
+ {
+ ret = GLEW_APPLE_texture_range;
+ continue;
+ }
+#endif
+#ifdef GL_APPLE_transform_hint
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"transform_hint", 14))
+ {
+ ret = GLEW_APPLE_transform_hint;
+ continue;
+ }
+#endif
+#ifdef GL_APPLE_vertex_array_object
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"vertex_array_object", 19))
+ {
+ ret = GLEW_APPLE_vertex_array_object;
+ continue;
+ }
+#endif
+#ifdef GL_APPLE_vertex_array_range
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"vertex_array_range", 18))
+ {
+ ret = GLEW_APPLE_vertex_array_range;
+ continue;
+ }
+#endif
+#ifdef GL_APPLE_vertex_program_evaluators
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"vertex_program_evaluators", 25))
+ {
+ ret = GLEW_APPLE_vertex_program_evaluators;
+ continue;
+ }
+#endif
+#ifdef GL_APPLE_ycbcr_422
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"ycbcr_422", 9))
+ {
+ ret = GLEW_APPLE_ycbcr_422;
+ continue;
+ }
+#endif
+ }
+ if (_glewStrSame2(&pos, &len, (const GLubyte*)"ARB_", 4))
+ {
+#ifdef GL_ARB_ES2_compatibility
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"ES2_compatibility", 17))
+ {
+ ret = GLEW_ARB_ES2_compatibility;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_ES3_compatibility
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"ES3_compatibility", 17))
+ {
+ ret = GLEW_ARB_ES3_compatibility;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_arrays_of_arrays
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"arrays_of_arrays", 16))
+ {
+ ret = GLEW_ARB_arrays_of_arrays;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_base_instance
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"base_instance", 13))
+ {
+ ret = GLEW_ARB_base_instance;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_blend_func_extended
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"blend_func_extended", 19))
+ {
+ ret = GLEW_ARB_blend_func_extended;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_cl_event
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"cl_event", 8))
+ {
+ ret = GLEW_ARB_cl_event;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_clear_buffer_object
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"clear_buffer_object", 19))
+ {
+ ret = GLEW_ARB_clear_buffer_object;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_color_buffer_float
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"color_buffer_float", 18))
+ {
+ ret = GLEW_ARB_color_buffer_float;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_compatibility
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"compatibility", 13))
+ {
+ ret = GLEW_ARB_compatibility;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_compressed_texture_pixel_storage
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"compressed_texture_pixel_storage", 32))
+ {
+ ret = GLEW_ARB_compressed_texture_pixel_storage;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_compute_shader
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"compute_shader", 14))
+ {
+ ret = GLEW_ARB_compute_shader;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_conservative_depth
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"conservative_depth", 18))
+ {
+ ret = GLEW_ARB_conservative_depth;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_copy_buffer
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"copy_buffer", 11))
+ {
+ ret = GLEW_ARB_copy_buffer;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_copy_image
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"copy_image", 10))
+ {
+ ret = GLEW_ARB_copy_image;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_debug_output
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"debug_output", 12))
+ {
+ ret = GLEW_ARB_debug_output;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_depth_buffer_float
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"depth_buffer_float", 18))
+ {
+ ret = GLEW_ARB_depth_buffer_float;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_depth_clamp
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"depth_clamp", 11))
+ {
+ ret = GLEW_ARB_depth_clamp;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_depth_texture
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"depth_texture", 13))
+ {
+ ret = GLEW_ARB_depth_texture;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_draw_buffers
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"draw_buffers", 12))
+ {
+ ret = GLEW_ARB_draw_buffers;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_draw_buffers_blend
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"draw_buffers_blend", 18))
+ {
+ ret = GLEW_ARB_draw_buffers_blend;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_draw_elements_base_vertex
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"draw_elements_base_vertex", 25))
+ {
+ ret = GLEW_ARB_draw_elements_base_vertex;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_draw_indirect
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"draw_indirect", 13))
+ {
+ ret = GLEW_ARB_draw_indirect;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_draw_instanced
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"draw_instanced", 14))
+ {
+ ret = GLEW_ARB_draw_instanced;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_explicit_attrib_location
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"explicit_attrib_location", 24))
+ {
+ ret = GLEW_ARB_explicit_attrib_location;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_explicit_uniform_location
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"explicit_uniform_location", 25))
+ {
+ ret = GLEW_ARB_explicit_uniform_location;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_fragment_coord_conventions
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"fragment_coord_conventions", 26))
+ {
+ ret = GLEW_ARB_fragment_coord_conventions;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_fragment_layer_viewport
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"fragment_layer_viewport", 23))
+ {
+ ret = GLEW_ARB_fragment_layer_viewport;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_fragment_program
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"fragment_program", 16))
+ {
+ ret = GLEW_ARB_fragment_program;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_fragment_program_shadow
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"fragment_program_shadow", 23))
+ {
+ ret = GLEW_ARB_fragment_program_shadow;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_fragment_shader
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"fragment_shader", 15))
+ {
+ ret = GLEW_ARB_fragment_shader;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_framebuffer_no_attachments
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"framebuffer_no_attachments", 26))
+ {
+ ret = GLEW_ARB_framebuffer_no_attachments;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_framebuffer_object
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"framebuffer_object", 18))
+ {
+ ret = GLEW_ARB_framebuffer_object;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_framebuffer_sRGB
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"framebuffer_sRGB", 16))
+ {
+ ret = GLEW_ARB_framebuffer_sRGB;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_geometry_shader4
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"geometry_shader4", 16))
+ {
+ ret = GLEW_ARB_geometry_shader4;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_get_program_binary
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"get_program_binary", 18))
+ {
+ ret = GLEW_ARB_get_program_binary;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_gpu_shader5
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"gpu_shader5", 11))
+ {
+ ret = GLEW_ARB_gpu_shader5;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_gpu_shader_fp64
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"gpu_shader_fp64", 15))
+ {
+ ret = GLEW_ARB_gpu_shader_fp64;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_half_float_pixel
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"half_float_pixel", 16))
+ {
+ ret = GLEW_ARB_half_float_pixel;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_half_float_vertex
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"half_float_vertex", 17))
+ {
+ ret = GLEW_ARB_half_float_vertex;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_imaging
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"imaging", 7))
+ {
+ ret = GLEW_ARB_imaging;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_instanced_arrays
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"instanced_arrays", 16))
+ {
+ ret = GLEW_ARB_instanced_arrays;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_internalformat_query
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"internalformat_query", 20))
+ {
+ ret = GLEW_ARB_internalformat_query;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_internalformat_query2
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"internalformat_query2", 21))
+ {
+ ret = GLEW_ARB_internalformat_query2;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_invalidate_subdata
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"invalidate_subdata", 18))
+ {
+ ret = GLEW_ARB_invalidate_subdata;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_map_buffer_alignment
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"map_buffer_alignment", 20))
+ {
+ ret = GLEW_ARB_map_buffer_alignment;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_map_buffer_range
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"map_buffer_range", 16))
+ {
+ ret = GLEW_ARB_map_buffer_range;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_matrix_palette
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"matrix_palette", 14))
+ {
+ ret = GLEW_ARB_matrix_palette;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_multi_draw_indirect
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"multi_draw_indirect", 19))
+ {
+ ret = GLEW_ARB_multi_draw_indirect;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_multisample
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"multisample", 11))
+ {
+ ret = GLEW_ARB_multisample;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_multitexture
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"multitexture", 12))
+ {
+ ret = GLEW_ARB_multitexture;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_occlusion_query
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"occlusion_query", 15))
+ {
+ ret = GLEW_ARB_occlusion_query;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_occlusion_query2
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"occlusion_query2", 16))
+ {
+ ret = GLEW_ARB_occlusion_query2;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_pixel_buffer_object
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"pixel_buffer_object", 19))
+ {
+ ret = GLEW_ARB_pixel_buffer_object;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_point_parameters
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"point_parameters", 16))
+ {
+ ret = GLEW_ARB_point_parameters;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_point_sprite
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"point_sprite", 12))
+ {
+ ret = GLEW_ARB_point_sprite;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_program_interface_query
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"program_interface_query", 23))
+ {
+ ret = GLEW_ARB_program_interface_query;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_provoking_vertex
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"provoking_vertex", 16))
+ {
+ ret = GLEW_ARB_provoking_vertex;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_robust_buffer_access_behavior
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"robust_buffer_access_behavior", 29))
+ {
+ ret = GLEW_ARB_robust_buffer_access_behavior;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_robustness
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"robustness", 10))
+ {
+ ret = GLEW_ARB_robustness;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_robustness_application_isolation
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"robustness_application_isolation", 32))
+ {
+ ret = GLEW_ARB_robustness_application_isolation;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_robustness_share_group_isolation
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"robustness_share_group_isolation", 32))
+ {
+ ret = GLEW_ARB_robustness_share_group_isolation;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_sample_shading
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"sample_shading", 14))
+ {
+ ret = GLEW_ARB_sample_shading;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_sampler_objects
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"sampler_objects", 15))
+ {
+ ret = GLEW_ARB_sampler_objects;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_seamless_cube_map
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"seamless_cube_map", 17))
+ {
+ ret = GLEW_ARB_seamless_cube_map;
+ continue;
+ }
+#endif
+#if 0 // NOTE jwilkins: there is an inconsistency between the ES and Non-ES versions of this extension??
+#ifdef GL_ARB_separate_shader_objects
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"separate_shader_objects", 23))
+ {
+ ret = GLEW_ARB_separate_shader_objects;
+ continue;
+ }
+#endif
+#endif // XXX
+#ifdef GL_ARB_shader_atomic_counters
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"shader_atomic_counters", 22))
+ {
+ ret = GLEW_ARB_shader_atomic_counters;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_shader_bit_encoding
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"shader_bit_encoding", 19))
+ {
+ ret = GLEW_ARB_shader_bit_encoding;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_shader_image_load_store
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"shader_image_load_store", 23))
+ {
+ ret = GLEW_ARB_shader_image_load_store;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_shader_image_size
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"shader_image_size", 17))
+ {
+ ret = GLEW_ARB_shader_image_size;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_shader_objects
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"shader_objects", 14))
+ {
+ ret = GLEW_ARB_shader_objects;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_shader_precision
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"shader_precision", 16))
+ {
+ ret = GLEW_ARB_shader_precision;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_shader_stencil_export
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"shader_stencil_export", 21))
+ {
+ ret = GLEW_ARB_shader_stencil_export;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_shader_storage_buffer_object
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"shader_storage_buffer_object", 28))
+ {
+ ret = GLEW_ARB_shader_storage_buffer_object;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_shader_subroutine
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"shader_subroutine", 17))
+ {
+ ret = GLEW_ARB_shader_subroutine;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_shader_texture_lod
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"shader_texture_lod", 18))
+ {
+ ret = GLEW_ARB_shader_texture_lod;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_shading_language_100
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"shading_language_100", 20))
+ {
+ ret = GLEW_ARB_shading_language_100;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_shading_language_420pack
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"shading_language_420pack", 24))
+ {
+ ret = GLEW_ARB_shading_language_420pack;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_shading_language_include
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"shading_language_include", 24))
+ {
+ ret = GLEW_ARB_shading_language_include;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_shading_language_packing
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"shading_language_packing", 24))
+ {
+ ret = GLEW_ARB_shading_language_packing;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_shadow
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"shadow", 6))
+ {
+ ret = GLEW_ARB_shadow;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_shadow_ambient
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"shadow_ambient", 14))
+ {
+ ret = GLEW_ARB_shadow_ambient;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_stencil_texturing
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"stencil_texturing", 17))
+ {
+ ret = GLEW_ARB_stencil_texturing;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_sync
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"sync", 4))
+ {
+ ret = GLEW_ARB_sync;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_tessellation_shader
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"tessellation_shader", 19))
+ {
+ ret = GLEW_ARB_tessellation_shader;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_texture_border_clamp
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_border_clamp", 20))
+ {
+ ret = GLEW_ARB_texture_border_clamp;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_texture_buffer_object
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_buffer_object", 21))
+ {
+ ret = GLEW_ARB_texture_buffer_object;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_texture_buffer_object_rgb32
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_buffer_object_rgb32", 27))
+ {
+ ret = GLEW_ARB_texture_buffer_object_rgb32;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_texture_buffer_range
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_buffer_range", 20))
+ {
+ ret = GLEW_ARB_texture_buffer_range;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_texture_compression
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_compression", 19))
+ {
+ ret = GLEW_ARB_texture_compression;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_texture_compression_bptc
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_compression_bptc", 24))
+ {
+ ret = GLEW_ARB_texture_compression_bptc;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_texture_compression_rgtc
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_compression_rgtc", 24))
+ {
+ ret = GLEW_ARB_texture_compression_rgtc;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_texture_cube_map
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_cube_map", 16))
+ {
+ ret = GLEW_ARB_texture_cube_map;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_texture_cube_map_array
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_cube_map_array", 22))
+ {
+ ret = GLEW_ARB_texture_cube_map_array;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_texture_env_add
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_env_add", 15))
+ {
+ ret = GLEW_ARB_texture_env_add;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_texture_env_combine
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_env_combine", 19))
+ {
+ ret = GLEW_ARB_texture_env_combine;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_texture_env_crossbar
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_env_crossbar", 20))
+ {
+ ret = GLEW_ARB_texture_env_crossbar;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_texture_env_dot3
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_env_dot3", 16))
+ {
+ ret = GLEW_ARB_texture_env_dot3;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_texture_float
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_float", 13))
+ {
+ ret = GLEW_ARB_texture_float;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_texture_gather
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_gather", 14))
+ {
+ ret = GLEW_ARB_texture_gather;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_texture_mirrored_repeat
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_mirrored_repeat", 23))
+ {
+ ret = GLEW_ARB_texture_mirrored_repeat;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_texture_multisample
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_multisample", 19))
+ {
+ ret = GLEW_ARB_texture_multisample;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_texture_non_power_of_two
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_non_power_of_two", 24))
+ {
+ ret = GLEW_ARB_texture_non_power_of_two;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_texture_query_levels
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_query_levels", 20))
+ {
+ ret = GLEW_ARB_texture_query_levels;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_texture_query_lod
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_query_lod", 17))
+ {
+ ret = GLEW_ARB_texture_query_lod;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_texture_rectangle
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_rectangle", 17))
+ {
+ ret = GLEW_ARB_texture_rectangle;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_texture_rg
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_rg", 10))
+ {
+ ret = GLEW_ARB_texture_rg;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_texture_rgb10_a2ui
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_rgb10_a2ui", 18))
+ {
+ ret = GLEW_ARB_texture_rgb10_a2ui;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_texture_storage
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_storage", 15))
+ {
+ ret = GLEW_ARB_texture_storage;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_texture_storage_multisample
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_storage_multisample", 27))
+ {
+ ret = GLEW_ARB_texture_storage_multisample;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_texture_swizzle
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_swizzle", 15))
+ {
+ ret = GLEW_ARB_texture_swizzle;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_texture_view
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_view", 12))
+ {
+ ret = GLEW_ARB_texture_view;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_timer_query
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"timer_query", 11))
+ {
+ ret = GLEW_ARB_timer_query;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_transform_feedback2
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"transform_feedback2", 19))
+ {
+ ret = GLEW_ARB_transform_feedback2;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_transform_feedback3
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"transform_feedback3", 19))
+ {
+ ret = GLEW_ARB_transform_feedback3;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_transform_feedback_instanced
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"transform_feedback_instanced", 28))
+ {
+ ret = GLEW_ARB_transform_feedback_instanced;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_transpose_matrix
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"transpose_matrix", 16))
+ {
+ ret = GLEW_ARB_transpose_matrix;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_uniform_buffer_object
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"uniform_buffer_object", 21))
+ {
+ ret = GLEW_ARB_uniform_buffer_object;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_vertex_array_bgra
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"vertex_array_bgra", 17))
+ {
+ ret = GLEW_ARB_vertex_array_bgra;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_vertex_array_object
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"vertex_array_object", 19))
+ {
+ ret = GLEW_ARB_vertex_array_object;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_vertex_attrib_64bit
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"vertex_attrib_64bit", 19))
+ {
+ ret = GLEW_ARB_vertex_attrib_64bit;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_vertex_attrib_binding
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"vertex_attrib_binding", 21))
+ {
+ ret = GLEW_ARB_vertex_attrib_binding;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_vertex_blend
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"vertex_blend", 12))
+ {
+ ret = GLEW_ARB_vertex_blend;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_vertex_buffer_object
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"vertex_buffer_object", 20))
+ {
+ ret = GLEW_ARB_vertex_buffer_object;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_vertex_program
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"vertex_program", 14))
+ {
+ ret = GLEW_ARB_vertex_program;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_vertex_shader
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"vertex_shader", 13))
+ {
+ ret = GLEW_ARB_vertex_shader;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_vertex_type_2_10_10_10_rev
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"vertex_type_2_10_10_10_rev", 26))
+ {
+ ret = GLEW_ARB_vertex_type_2_10_10_10_rev;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_viewport_array
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"viewport_array", 14))
+ {
+ ret = GLEW_ARB_viewport_array;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_window_pos
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"window_pos", 10))
+ {
+ ret = GLEW_ARB_window_pos;
+ continue;
+ }
+#endif
+ }
+ if (_glewStrSame2(&pos, &len, (const GLubyte*)"ARM_", 4))
+ {
+#ifdef GL_ARM_mali_program_binary
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"mali_program_binary", 19))
+ {
+ ret = GLEW_ARM_mali_program_binary;
+ continue;
+ }
+#endif
+#ifdef GL_ARM_mali_shader_binary
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"mali_shader_binary", 18))
+ {
+ ret = GLEW_ARM_mali_shader_binary;
+ continue;
+ }
+#endif
+#ifdef GL_ARM_rgba8
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"rgba8", 5))
+ {
+ ret = GLEW_ARM_rgba8;
+ continue;
+ }
+#endif
+ }
+ if (_glewStrSame2(&pos, &len, (const GLubyte*)"ATIX_", 5))
+ {
+#ifdef GL_ATIX_point_sprites
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"point_sprites", 13))
+ {
+ ret = GLEW_ATIX_point_sprites;
+ continue;
+ }
+#endif
+#ifdef GL_ATIX_texture_env_combine3
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_env_combine3", 20))
+ {
+ ret = GLEW_ATIX_texture_env_combine3;
+ continue;
+ }
+#endif
+#ifdef GL_ATIX_texture_env_route
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_env_route", 17))
+ {
+ ret = GLEW_ATIX_texture_env_route;
+ continue;
+ }
+#endif
+#ifdef GL_ATIX_vertex_shader_output_point_size
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"vertex_shader_output_point_size", 31))
+ {
+ ret = GLEW_ATIX_vertex_shader_output_point_size;
+ continue;
+ }
+#endif
+ }
+ if (_glewStrSame2(&pos, &len, (const GLubyte*)"ATI_", 4))
+ {
+#ifdef GL_ATI_draw_buffers
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"draw_buffers", 12))
+ {
+ ret = GLEW_ATI_draw_buffers;
+ continue;
+ }
+#endif
+#ifdef GL_ATI_element_array
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"element_array", 13))
+ {
+ ret = GLEW_ATI_element_array;
+ continue;
+ }
+#endif
+#ifdef GL_ATI_envmap_bumpmap
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"envmap_bumpmap", 14))
+ {
+ ret = GLEW_ATI_envmap_bumpmap;
+ continue;
+ }
+#endif
+#ifdef GL_ATI_fragment_shader
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"fragment_shader", 15))
+ {
+ ret = GLEW_ATI_fragment_shader;
+ continue;
+ }
+#endif
+#ifdef GL_ATI_map_object_buffer
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"map_object_buffer", 17))
+ {
+ ret = GLEW_ATI_map_object_buffer;
+ continue;
+ }
+#endif
+#ifdef GL_ATI_meminfo
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"meminfo", 7))
+ {
+ ret = GLEW_ATI_meminfo;
+ continue;
+ }
+#endif
+#ifdef GL_ATI_pn_triangles
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"pn_triangles", 12))
+ {
+ ret = GLEW_ATI_pn_triangles;
+ continue;
+ }
+#endif
+#ifdef GL_ATI_separate_stencil
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"separate_stencil", 16))
+ {
+ ret = GLEW_ATI_separate_stencil;
+ continue;
+ }
+#endif
+#ifdef GL_ATI_shader_texture_lod
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"shader_texture_lod", 18))
+ {
+ ret = GLEW_ATI_shader_texture_lod;
+ continue;
+ }
+#endif
+#ifdef GL_ATI_text_fragment_shader
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"text_fragment_shader", 20))
+ {
+ ret = GLEW_ATI_text_fragment_shader;
+ continue;
+ }
+#endif
+#ifdef GL_ATI_texture_compression_3dc
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_compression_3dc", 23))
+ {
+ ret = GLEW_ATI_texture_compression_3dc;
+ continue;
+ }
+#endif
+#ifdef GL_ATI_texture_env_combine3
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_env_combine3", 20))
+ {
+ ret = GLEW_ATI_texture_env_combine3;
+ continue;
+ }
+#endif
+#ifdef GL_ATI_texture_float
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_float", 13))
+ {
+ ret = GLEW_ATI_texture_float;
+ continue;
+ }
+#endif
+#ifdef GL_ATI_texture_mirror_once
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_mirror_once", 19))
+ {
+ ret = GLEW_ATI_texture_mirror_once;
+ continue;
+ }
+#endif
+#ifdef GL_ATI_vertex_array_object
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"vertex_array_object", 19))
+ {
+ ret = GLEW_ATI_vertex_array_object;
+ continue;
+ }
+#endif
+#ifdef GL_ATI_vertex_attrib_array_object
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"vertex_attrib_array_object", 26))
+ {
+ ret = GLEW_ATI_vertex_attrib_array_object;
+ continue;
+ }
+#endif
+#ifdef GL_ATI_vertex_streams
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"vertex_streams", 14))
+ {
+ ret = GLEW_ATI_vertex_streams;
+ continue;
+ }
+#endif
+ }
+ if (_glewStrSame2(&pos, &len, (const GLubyte*)"DMP_", 4))
+ {
+#ifdef GL_DMP_shader_binary
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"shader_binary", 13))
+ {
+ ret = GLEW_DMP_shader_binary;
+ continue;
+ }
+#endif
+ }
+ if (_glewStrSame2(&pos, &len, (const GLubyte*)"ES_", 3))
+ {
+#ifdef GL_ES_VERSION_1_0
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"VERSION_1_0", 11))
+ {
+ ret = GLEW_ES_VERSION_1_0;
+ continue;
+ }
+#endif
+#ifdef GL_ES_VERSION_CL_1_1
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"VERSION_CL_1_1", 14))
+ {
+ ret = GLEW_ES_VERSION_CL_1_1;
+ continue;
+ }
+#endif
+#ifdef GL_ES_VERSION_CM_1_1
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"VERSION_CM_1_1", 14))
+ {
+ ret = GLEW_ES_VERSION_CM_1_1;
+ continue;
+ }
+#endif
+#ifdef GL_ES_VERSION_2_0
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"VERSION_2_0", 11))
+ {
+ ret = GLEW_ES_VERSION_2_0;
+ continue;
+ }
+#endif
+ }
+ if (_glewStrSame2(&pos, &len, (const GLubyte*)"EXT_", 4))
+ {
+#ifdef GL_EXT_422_pixels
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"422_pixels", 10))
+ {
+ ret = GLEW_EXT_422_pixels;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_Cg_shader
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"Cg_shader", 9))
+ {
+ ret = GLEW_EXT_Cg_shader;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_abgr
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"abgr", 4))
+ {
+ ret = GLEW_EXT_abgr;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_bgra
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"bgra", 4))
+ {
+ ret = GLEW_EXT_bgra;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_bindable_uniform
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"bindable_uniform", 16))
+ {
+ ret = GLEW_EXT_bindable_uniform;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_blend_color
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"blend_color", 11))
+ {
+ ret = GLEW_EXT_blend_color;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_blend_equation_separate
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"blend_equation_separate", 23))
+ {
+ ret = GLEW_EXT_blend_equation_separate;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_blend_func_separate
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"blend_func_separate", 19))
+ {
+ ret = GLEW_EXT_blend_func_separate;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_blend_logic_op
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"blend_logic_op", 14))
+ {
+ ret = GLEW_EXT_blend_logic_op;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_blend_minmax
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"blend_minmax", 12))
+ {
+ ret = GLEW_EXT_blend_minmax;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_blend_subtract
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"blend_subtract", 14))
+ {
+ ret = GLEW_EXT_blend_subtract;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_clip_volume_hint
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"clip_volume_hint", 16))
+ {
+ ret = GLEW_EXT_clip_volume_hint;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_cmyka
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"cmyka", 5))
+ {
+ ret = GLEW_EXT_cmyka;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_color_buffer_half_float
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"color_buffer_half_float", 23))
+ {
+ ret = GLEW_EXT_color_buffer_half_float;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_color_subtable
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"color_subtable", 14))
+ {
+ ret = GLEW_EXT_color_subtable;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_compiled_vertex_array
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"compiled_vertex_array", 21))
+ {
+ ret = GLEW_EXT_compiled_vertex_array;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_convolution
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"convolution", 11))
+ {
+ ret = GLEW_EXT_convolution;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_coordinate_frame
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"coordinate_frame", 16))
+ {
+ ret = GLEW_EXT_coordinate_frame;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_copy_texture
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"copy_texture", 12))
+ {
+ ret = GLEW_EXT_copy_texture;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_cull_vertex
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"cull_vertex", 11))
+ {
+ ret = GLEW_EXT_cull_vertex;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_debug_label
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"debug_label", 11))
+ {
+ ret = GLEW_EXT_debug_label;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_debug_marker
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"debug_marker", 12))
+ {
+ ret = GLEW_EXT_debug_marker;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_depth_bounds_test
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"depth_bounds_test", 17))
+ {
+ ret = GLEW_EXT_depth_bounds_test;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_direct_state_access
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"direct_state_access", 19))
+ {
+ ret = GLEW_EXT_direct_state_access;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_discard_framebuffer
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"discard_framebuffer", 19))
+ {
+ ret = GLEW_EXT_discard_framebuffer;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_draw_buffers2
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"draw_buffers2", 13))
+ {
+ ret = GLEW_EXT_draw_buffers2;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_draw_instanced
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"draw_instanced", 14))
+ {
+ ret = GLEW_EXT_draw_instanced;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_draw_range_elements
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"draw_range_elements", 19))
+ {
+ ret = GLEW_EXT_draw_range_elements;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_fog_coord
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"fog_coord", 9))
+ {
+ ret = GLEW_EXT_fog_coord;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_frag_depth
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"frag_depth", 10))
+ {
+ ret = GLEW_EXT_frag_depth;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_fragment_lighting
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"fragment_lighting", 17))
+ {
+ ret = GLEW_EXT_fragment_lighting;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_framebuffer_blit
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"framebuffer_blit", 16))
+ {
+ ret = GLEW_EXT_framebuffer_blit;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_framebuffer_multisample
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"framebuffer_multisample", 23))
+ {
+ ret = GLEW_EXT_framebuffer_multisample;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_framebuffer_multisample_blit_scaled
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"framebuffer_multisample_blit_scaled", 35))
+ {
+ ret = GLEW_EXT_framebuffer_multisample_blit_scaled;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_framebuffer_object
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"framebuffer_object", 18))
+ {
+ ret = GLEW_EXT_framebuffer_object;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_framebuffer_sRGB
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"framebuffer_sRGB", 16))
+ {
+ ret = GLEW_EXT_framebuffer_sRGB;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_geometry_shader4
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"geometry_shader4", 16))
+ {
+ ret = GLEW_EXT_geometry_shader4;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_gpu_program_parameters
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"gpu_program_parameters", 22))
+ {
+ ret = GLEW_EXT_gpu_program_parameters;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_gpu_shader4
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"gpu_shader4", 11))
+ {
+ ret = GLEW_EXT_gpu_shader4;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_histogram
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"histogram", 9))
+ {
+ ret = GLEW_EXT_histogram;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_index_array_formats
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"index_array_formats", 19))
+ {
+ ret = GLEW_EXT_index_array_formats;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_index_func
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"index_func", 10))
+ {
+ ret = GLEW_EXT_index_func;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_index_material
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"index_material", 14))
+ {
+ ret = GLEW_EXT_index_material;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_index_texture
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"index_texture", 13))
+ {
+ ret = GLEW_EXT_index_texture;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_light_texture
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"light_texture", 13))
+ {
+ ret = GLEW_EXT_light_texture;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_map_buffer_range
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"map_buffer_range", 16))
+ {
+ ret = GLEW_EXT_map_buffer_range;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_misc_attribute
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"misc_attribute", 14))
+ {
+ ret = GLEW_EXT_misc_attribute;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_multi_draw_arrays
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"multi_draw_arrays", 17))
+ {
+ ret = GLEW_EXT_multi_draw_arrays;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_multisample
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"multisample", 11))
+ {
+ ret = GLEW_EXT_multisample;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_multisampled_render_to_texture
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"multisampled_render_to_texture", 30))
+ {
+ ret = GLEW_EXT_multisampled_render_to_texture;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_multiview_draw_buffers
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"multiview_draw_buffers", 22))
+ {
+ ret = GLEW_EXT_multiview_draw_buffers;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_occlusion_query_boolean
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"occlusion_query_boolean", 23))
+ {
+ ret = GLEW_EXT_occlusion_query_boolean;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_packed_depth_stencil
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"packed_depth_stencil", 20))
+ {
+ ret = GLEW_EXT_packed_depth_stencil;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_packed_float
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"packed_float", 12))
+ {
+ ret = GLEW_EXT_packed_float;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_packed_pixels
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"packed_pixels", 13))
+ {
+ ret = GLEW_EXT_packed_pixels;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_paletted_texture
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"paletted_texture", 16))
+ {
+ ret = GLEW_EXT_paletted_texture;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_pixel_buffer_object
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"pixel_buffer_object", 19))
+ {
+ ret = GLEW_EXT_pixel_buffer_object;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_pixel_transform
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"pixel_transform", 15))
+ {
+ ret = GLEW_EXT_pixel_transform;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_pixel_transform_color_table
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"pixel_transform_color_table", 27))
+ {
+ ret = GLEW_EXT_pixel_transform_color_table;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_point_parameters
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"point_parameters", 16))
+ {
+ ret = GLEW_EXT_point_parameters;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_polygon_offset
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"polygon_offset", 14))
+ {
+ ret = GLEW_EXT_polygon_offset;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_provoking_vertex
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"provoking_vertex", 16))
+ {
+ ret = GLEW_EXT_provoking_vertex;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_read_format_bgra
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"read_format_bgra", 16))
+ {
+ ret = GLEW_EXT_read_format_bgra;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_rescale_normal
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"rescale_normal", 14))
+ {
+ ret = GLEW_EXT_rescale_normal;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_robustness
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"robustness", 10))
+ {
+ ret = GLEW_EXT_robustness;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_sRGB
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"sRGB", 4))
+ {
+ ret = GLEW_EXT_sRGB;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_scene_marker
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"scene_marker", 12))
+ {
+ ret = GLEW_EXT_scene_marker;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_secondary_color
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"secondary_color", 15))
+ {
+ ret = GLEW_EXT_secondary_color;
+ continue;
+ }
+#endif
+#if 0 // NOTE jwilkins: there is an inconsistency between the ES and Non-ES versions of this extension??
+#ifdef GL_EXT_separate_shader_objects
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"separate_shader_objects", 23))
+ {
+ ret = GLEW_EXT_separate_shader_objects;
+ continue;
+ }
+#endif
+#endif
+#ifdef GL_EXT_separate_specular_color
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"separate_specular_color", 23))
+ {
+ ret = GLEW_EXT_separate_specular_color;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_shader_framebuffer_fetch
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"shader_framebuffer_fetch", 24))
+ {
+ ret = GLEW_EXT_shader_framebuffer_fetch;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_shader_image_load_store
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"shader_image_load_store", 23))
+ {
+ ret = GLEW_EXT_shader_image_load_store;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_shader_texture_lod
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"shader_texture_lod", 18))
+ {
+ ret = GLEW_EXT_shader_texture_lod;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_shadow_funcs
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"shadow_funcs", 12))
+ {
+ ret = GLEW_EXT_shadow_funcs;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_shadow_samplers
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"shadow_samplers", 15))
+ {
+ ret = GLEW_EXT_shadow_samplers;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_shared_texture_palette
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"shared_texture_palette", 22))
+ {
+ ret = GLEW_EXT_shared_texture_palette;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_stencil_clear_tag
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"stencil_clear_tag", 17))
+ {
+ ret = GLEW_EXT_stencil_clear_tag;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_stencil_two_side
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"stencil_two_side", 16))
+ {
+ ret = GLEW_EXT_stencil_two_side;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_stencil_wrap
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"stencil_wrap", 12))
+ {
+ ret = GLEW_EXT_stencil_wrap;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_subtexture
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"subtexture", 10))
+ {
+ ret = GLEW_EXT_subtexture;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_texture
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture", 7))
+ {
+ ret = GLEW_EXT_texture;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_texture3D
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture3D", 9))
+ {
+ ret = GLEW_EXT_texture3D;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_texture_array
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_array", 13))
+ {
+ ret = GLEW_EXT_texture_array;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_texture_buffer_object
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_buffer_object", 21))
+ {
+ ret = GLEW_EXT_texture_buffer_object;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_texture_compression_dxt1
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_compression_dxt1", 24))
+ {
+ ret = GLEW_EXT_texture_compression_dxt1;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_texture_compression_latc
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_compression_latc", 24))
+ {
+ ret = GLEW_EXT_texture_compression_latc;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_texture_compression_rgtc
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_compression_rgtc", 24))
+ {
+ ret = GLEW_EXT_texture_compression_rgtc;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_texture_compression_s3tc
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_compression_s3tc", 24))
+ {
+ ret = GLEW_EXT_texture_compression_s3tc;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_texture_cube_map
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_cube_map", 16))
+ {
+ ret = GLEW_EXT_texture_cube_map;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_texture_edge_clamp
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_edge_clamp", 18))
+ {
+ ret = GLEW_EXT_texture_edge_clamp;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_texture_env
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_env", 11))
+ {
+ ret = GLEW_EXT_texture_env;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_texture_env_add
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_env_add", 15))
+ {
+ ret = GLEW_EXT_texture_env_add;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_texture_env_combine
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_env_combine", 19))
+ {
+ ret = GLEW_EXT_texture_env_combine;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_texture_env_dot3
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_env_dot3", 16))
+ {
+ ret = GLEW_EXT_texture_env_dot3;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_texture_filter_anisotropic
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_filter_anisotropic", 26))
+ {
+ ret = GLEW_EXT_texture_filter_anisotropic;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_texture_format_BGRA8888
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_format_BGRA8888", 23))
+ {
+ ret = GLEW_EXT_texture_format_BGRA8888;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_texture_integer
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_integer", 15))
+ {
+ ret = GLEW_EXT_texture_integer;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_texture_lod_bias
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_lod_bias", 16))
+ {
+ ret = GLEW_EXT_texture_lod_bias;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_texture_mirror_clamp
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_mirror_clamp", 20))
+ {
+ ret = GLEW_EXT_texture_mirror_clamp;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_texture_object
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_object", 14))
+ {
+ ret = GLEW_EXT_texture_object;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_texture_perturb_normal
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_perturb_normal", 22))
+ {
+ ret = GLEW_EXT_texture_perturb_normal;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_texture_rectangle
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_rectangle", 17))
+ {
+ ret = GLEW_EXT_texture_rectangle;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_texture_rg
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_rg", 10))
+ {
+ ret = GLEW_EXT_texture_rg;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_texture_sRGB
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_sRGB", 12))
+ {
+ ret = GLEW_EXT_texture_sRGB;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_texture_sRGB_decode
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_sRGB_decode", 19))
+ {
+ ret = GLEW_EXT_texture_sRGB_decode;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_texture_shared_exponent
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_shared_exponent", 23))
+ {
+ ret = GLEW_EXT_texture_shared_exponent;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_texture_snorm
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_snorm", 13))
+ {
+ ret = GLEW_EXT_texture_snorm;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_texture_storage
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_storage", 15))
+ {
+ ret = GLEW_EXT_texture_storage;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_texture_swizzle
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_swizzle", 15))
+ {
+ ret = GLEW_EXT_texture_swizzle;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_texture_type_2_10_10_10_REV
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_type_2_10_10_10_REV", 27))
+ {
+ ret = GLEW_EXT_texture_type_2_10_10_10_REV;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_timer_query
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"timer_query", 11))
+ {
+ ret = GLEW_EXT_timer_query;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_transform_feedback
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"transform_feedback", 18))
+ {
+ ret = GLEW_EXT_transform_feedback;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_unpack_subimage
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"unpack_subimage", 15))
+ {
+ ret = GLEW_EXT_unpack_subimage;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_vertex_array
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"vertex_array", 12))
+ {
+ ret = GLEW_EXT_vertex_array;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_vertex_array_bgra
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"vertex_array_bgra", 17))
+ {
+ ret = GLEW_EXT_vertex_array_bgra;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_vertex_attrib_64bit
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"vertex_attrib_64bit", 19))
+ {
+ ret = GLEW_EXT_vertex_attrib_64bit;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_vertex_shader
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"vertex_shader", 13))
+ {
+ ret = GLEW_EXT_vertex_shader;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_vertex_weighting
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"vertex_weighting", 16))
+ {
+ ret = GLEW_EXT_vertex_weighting;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_x11_sync_object
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"x11_sync_object", 15))
+ {
+ ret = GLEW_EXT_x11_sync_object;
+ continue;
+ }
+#endif
+ }
+ if (_glewStrSame2(&pos, &len, (const GLubyte*)"FJ_", 3))
+ {
+#ifdef GL_FJ_shader_binary_GCCSO
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"shader_binary_GCCSO", 19))
+ {
+ ret = GLEW_FJ_shader_binary_GCCSO;
+ continue;
+ }
+#endif
+ }
+ if (_glewStrSame2(&pos, &len, (const GLubyte*)"GREMEDY_", 8))
+ {
+#ifdef GL_GREMEDY_frame_terminator
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"frame_terminator", 16))
+ {
+ ret = GLEW_GREMEDY_frame_terminator;
+ continue;
+ }
+#endif
+#ifdef GL_GREMEDY_string_marker
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"string_marker", 13))
+ {
+ ret = GLEW_GREMEDY_string_marker;
+ continue;
+ }
+#endif
+ }
+ if (_glewStrSame2(&pos, &len, (const GLubyte*)"HP_", 3))
+ {
+#ifdef GL_HP_convolution_border_modes
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"convolution_border_modes", 24))
+ {
+ ret = GLEW_HP_convolution_border_modes;
+ continue;
+ }
+#endif
+#ifdef GL_HP_image_transform
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"image_transform", 15))
+ {
+ ret = GLEW_HP_image_transform;
+ continue;
+ }
+#endif
+#ifdef GL_HP_occlusion_test
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"occlusion_test", 14))
+ {
+ ret = GLEW_HP_occlusion_test;
+ continue;
+ }
+#endif
+#ifdef GL_HP_texture_lighting
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_lighting", 16))
+ {
+ ret = GLEW_HP_texture_lighting;
+ continue;
+ }
+#endif
+ }
+ if (_glewStrSame2(&pos, &len, (const GLubyte*)"IBM_", 4))
+ {
+#ifdef GL_IBM_cull_vertex
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"cull_vertex", 11))
+ {
+ ret = GLEW_IBM_cull_vertex;
+ continue;
+ }
+#endif
+#ifdef GL_IBM_multimode_draw_arrays
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"multimode_draw_arrays", 21))
+ {
+ ret = GLEW_IBM_multimode_draw_arrays;
+ continue;
+ }
+#endif
+#ifdef GL_IBM_rasterpos_clip
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"rasterpos_clip", 14))
+ {
+ ret = GLEW_IBM_rasterpos_clip;
+ continue;
+ }
+#endif
+#ifdef GL_IBM_static_data
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"static_data", 11))
+ {
+ ret = GLEW_IBM_static_data;
+ continue;
+ }
+#endif
+#ifdef GL_IBM_texture_mirrored_repeat
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_mirrored_repeat", 23))
+ {
+ ret = GLEW_IBM_texture_mirrored_repeat;
+ continue;
+ }
+#endif
+#ifdef GL_IBM_vertex_array_lists
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"vertex_array_lists", 18))
+ {
+ ret = GLEW_IBM_vertex_array_lists;
+ continue;
+ }
+#endif
+ }
+ if (_glewStrSame2(&pos, &len, (const GLubyte*)"IMG_", 4))
+ {
+#ifdef GL_IMG_multisampled_render_to_texture
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"multisampled_render_to_texture", 30))
+ {
+ ret = GLEW_IMG_multisampled_render_to_texture;
+ continue;
+ }
+#endif
+#ifdef GL_IMG_program_binary
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"program_binary", 14))
+ {
+ ret = GLEW_IMG_program_binary;
+ continue;
+ }
+#endif
+#ifdef GL_IMG_read_format
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"read_format", 11))
+ {
+ ret = GLEW_IMG_read_format;
+ continue;
+ }
+#endif
+#ifdef GL_IMG_shader_binary
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"shader_binary", 13))
+ {
+ ret = GLEW_IMG_shader_binary;
+ continue;
+ }
+#endif
+#ifdef GL_IMG_texture_compression_pvrtc
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_compression_pvrtc", 25))
+ {
+ ret = GLEW_IMG_texture_compression_pvrtc;
+ continue;
+ }
+#endif
+#ifdef GL_IMG_texture_env_enhanced_fixed_function
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_env_enhanced_fixed_function", 35))
+ {
+ ret = GLEW_IMG_texture_env_enhanced_fixed_function;
+ continue;
+ }
+#endif
+#ifdef GL_IMG_user_clip_plane
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"user_clip_plane", 15))
+ {
+ ret = GLEW_IMG_user_clip_plane;
+ continue;
+ }
+#endif
+ }
+ if (_glewStrSame2(&pos, &len, (const GLubyte*)"INGR_", 5))
+ {
+#ifdef GL_INGR_color_clamp
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"color_clamp", 11))
+ {
+ ret = GLEW_INGR_color_clamp;
+ continue;
+ }
+#endif
+#ifdef GL_INGR_interlace_read
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"interlace_read", 14))
+ {
+ ret = GLEW_INGR_interlace_read;
+ continue;
+ }
+#endif
+ }
+ if (_glewStrSame2(&pos, &len, (const GLubyte*)"INTEL_", 6))
+ {
+#ifdef GL_INTEL_map_texture
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"map_texture", 11))
+ {
+ ret = GLEW_INTEL_map_texture;
+ continue;
+ }
+#endif
+#ifdef GL_INTEL_parallel_arrays
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"parallel_arrays", 15))
+ {
+ ret = GLEW_INTEL_parallel_arrays;
+ continue;
+ }
+#endif
+#ifdef GL_INTEL_texture_scissor
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_scissor", 15))
+ {
+ ret = GLEW_INTEL_texture_scissor;
+ continue;
+ }
+#endif
+ }
+ if (_glewStrSame2(&pos, &len, (const GLubyte*)"KHR_", 4))
+ {
+#ifdef GL_KHR_debug
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"debug", 5))
+ {
+ ret = GLEW_KHR_debug;
+ continue;
+ }
+#endif
+#ifdef GL_KHR_texture_compression_astc_ldr
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_compression_astc_ldr", 28))
+ {
+ ret = GLEW_KHR_texture_compression_astc_ldr;
+ continue;
+ }
+#endif
+ }
+ if (_glewStrSame2(&pos, &len, (const GLubyte*)"KTX_", 4))
+ {
+#ifdef GL_KTX_buffer_region
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"buffer_region", 13))
+ {
+ ret = GLEW_KTX_buffer_region;
+ continue;
+ }
+#endif
+ }
+ if (_glewStrSame2(&pos, &len, (const GLubyte*)"MESAX_", 6))
+ {
+#ifdef GL_MESAX_texture_stack
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_stack", 13))
+ {
+ ret = GLEW_MESAX_texture_stack;
+ continue;
+ }
+#endif
+ }
+ if (_glewStrSame2(&pos, &len, (const GLubyte*)"MESA_", 5))
+ {
+#ifdef GL_MESA_pack_invert
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"pack_invert", 11))
+ {
+ ret = GLEW_MESA_pack_invert;
+ continue;
+ }
+#endif
+#ifdef GL_MESA_resize_buffers
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"resize_buffers", 14))
+ {
+ ret = GLEW_MESA_resize_buffers;
+ continue;
+ }
+#endif
+#ifdef GL_MESA_window_pos
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"window_pos", 10))
+ {
+ ret = GLEW_MESA_window_pos;
+ continue;
+ }
+#endif
+#ifdef GL_MESA_ycbcr_texture
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"ycbcr_texture", 13))
+ {
+ ret = GLEW_MESA_ycbcr_texture;
+ continue;
+ }
+#endif
+ }
+ if (_glewStrSame2(&pos, &len, (const GLubyte*)"NVX_", 4))
+ {
+#ifdef GL_NVX_conditional_render
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"conditional_render", 18))
+ {
+ ret = GLEW_NVX_conditional_render;
+ continue;
+ }
+#endif
+#ifdef GL_NVX_gpu_memory_info
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"gpu_memory_info", 15))
+ {
+ ret = GLEW_NVX_gpu_memory_info;
+ continue;
+ }
+#endif
+ }
+ if (_glewStrSame2(&pos, &len, (const GLubyte*)"NV_", 3))
+ {
+#ifdef GL_NV_3dvision_settings
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"3dvision_settings", 17))
+ {
+ ret = GLEW_NV_3dvision_settings;
+ continue;
+ }
+#endif
+#ifdef GL_NV_EGL_stream_consumer_external
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"EGL_stream_consumer_external", 28))
+ {
+ ret = GLEW_NV_EGL_stream_consumer_external;
+ continue;
+ }
+#endif
+#ifdef GL_NV_bgr
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"bgr", 3))
+ {
+ ret = GLEW_NV_bgr;
+ continue;
+ }
+#endif
+#ifdef GL_NV_bindless_texture
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"bindless_texture", 16))
+ {
+ ret = GLEW_NV_bindless_texture;
+ continue;
+ }
+#endif
+#ifdef GL_NV_blend_square
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"blend_square", 12))
+ {
+ ret = GLEW_NV_blend_square;
+ continue;
+ }
+#endif
+#ifdef GL_NV_compute_program5
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"compute_program5", 16))
+ {
+ ret = GLEW_NV_compute_program5;
+ continue;
+ }
+#endif
+#ifdef GL_NV_conditional_render
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"conditional_render", 18))
+ {
+ ret = GLEW_NV_conditional_render;
+ continue;
+ }
+#endif
+#ifdef GL_NV_copy_depth_to_color
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"copy_depth_to_color", 19))
+ {
+ ret = GLEW_NV_copy_depth_to_color;
+ continue;
+ }
+#endif
+#ifdef GL_NV_copy_image
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"copy_image", 10))
+ {
+ ret = GLEW_NV_copy_image;
+ continue;
+ }
+#endif
+#ifdef GL_NV_coverage_sample
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"coverage_sample", 15))
+ {
+ ret = GLEW_NV_coverage_sample;
+ continue;
+ }
+#endif
+#ifdef GL_NV_deep_texture3D
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"deep_texture3D", 14))
+ {
+ ret = GLEW_NV_deep_texture3D;
+ continue;
+ }
+#endif
+#ifdef GL_NV_depth_buffer_float
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"depth_buffer_float", 18))
+ {
+ ret = GLEW_NV_depth_buffer_float;
+ continue;
+ }
+#endif
+#ifdef GL_NV_depth_clamp
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"depth_clamp", 11))
+ {
+ ret = GLEW_NV_depth_clamp;
+ continue;
+ }
+#endif
+#ifdef GL_NV_depth_nonlinear
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"depth_nonlinear", 15))
+ {
+ ret = GLEW_NV_depth_nonlinear;
+ continue;
+ }
+#endif
+#ifdef GL_NV_depth_range_unclamped
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"depth_range_unclamped", 21))
+ {
+ ret = GLEW_NV_depth_range_unclamped;
+ continue;
+ }
+#endif
+#ifdef GL_NV_draw_buffers
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"draw_buffers", 12))
+ {
+ ret = GLEW_NV_draw_buffers;
+ continue;
+ }
+#endif
+#ifdef GL_NV_draw_texture
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"draw_texture", 12))
+ {
+ ret = GLEW_NV_draw_texture;
+ continue;
+ }
+#endif
+#ifdef GL_NV_evaluators
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"evaluators", 10))
+ {
+ ret = GLEW_NV_evaluators;
+ continue;
+ }
+#endif
+#ifdef GL_NV_explicit_multisample
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"explicit_multisample", 20))
+ {
+ ret = GLEW_NV_explicit_multisample;
+ continue;
+ }
+#endif
+#ifdef GL_NV_fbo_color_attachments
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"fbo_color_attachments", 21))
+ {
+ ret = GLEW_NV_fbo_color_attachments;
+ continue;
+ }
+#endif
+#ifdef GL_NV_fence
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"fence", 5))
+ {
+ ret = GLEW_NV_fence;
+ continue;
+ }
+#endif
+#ifdef GL_NV_float_buffer
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"float_buffer", 12))
+ {
+ ret = GLEW_NV_float_buffer;
+ continue;
+ }
+#endif
+#ifdef GL_NV_fog_distance
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"fog_distance", 12))
+ {
+ ret = GLEW_NV_fog_distance;
+ continue;
+ }
+#endif
+#ifdef GL_NV_fragment_program
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"fragment_program", 16))
+ {
+ ret = GLEW_NV_fragment_program;
+ continue;
+ }
+#endif
+#ifdef GL_NV_fragment_program2
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"fragment_program2", 17))
+ {
+ ret = GLEW_NV_fragment_program2;
+ continue;
+ }
+#endif
+#ifdef GL_NV_fragment_program4
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"fragment_program4", 17))
+ {
+ ret = GLEW_NV_fragment_program4;
+ continue;
+ }
+#endif
+#ifdef GL_NV_fragment_program_option
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"fragment_program_option", 23))
+ {
+ ret = GLEW_NV_fragment_program_option;
+ continue;
+ }
+#endif
+#ifdef GL_NV_framebuffer_multisample_coverage
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"framebuffer_multisample_coverage", 32))
+ {
+ ret = GLEW_NV_framebuffer_multisample_coverage;
+ continue;
+ }
+#endif
+#ifdef GL_NV_geometry_program4
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"geometry_program4", 17))
+ {
+ ret = GLEW_NV_geometry_program4;
+ continue;
+ }
+#endif
+#ifdef GL_NV_geometry_shader4
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"geometry_shader4", 16))
+ {
+ ret = GLEW_NV_geometry_shader4;
+ continue;
+ }
+#endif
+#ifdef GL_NV_gpu_program4
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"gpu_program4", 12))
+ {
+ ret = GLEW_NV_gpu_program4;
+ continue;
+ }
+#endif
+#ifdef GL_NV_gpu_program5
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"gpu_program5", 12))
+ {
+ ret = GLEW_NV_gpu_program5;
+ continue;
+ }
+#endif
+#ifdef GL_NV_gpu_program_fp64
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"gpu_program_fp64", 16))
+ {
+ ret = GLEW_NV_gpu_program_fp64;
+ continue;
+ }
+#endif
+#ifdef GL_NV_gpu_shader5
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"gpu_shader5", 11))
+ {
+ ret = GLEW_NV_gpu_shader5;
+ continue;
+ }
+#endif
+#ifdef GL_NV_half_float
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"half_float", 10))
+ {
+ ret = GLEW_NV_half_float;
+ continue;
+ }
+#endif
+#ifdef GL_NV_light_max_exponent
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"light_max_exponent", 18))
+ {
+ ret = GLEW_NV_light_max_exponent;
+ continue;
+ }
+#endif
+#ifdef GL_NV_multisample_coverage
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"multisample_coverage", 20))
+ {
+ ret = GLEW_NV_multisample_coverage;
+ continue;
+ }
+#endif
+#ifdef GL_NV_multisample_filter_hint
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"multisample_filter_hint", 23))
+ {
+ ret = GLEW_NV_multisample_filter_hint;
+ continue;
+ }
+#endif
+#ifdef GL_NV_occlusion_query
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"occlusion_query", 15))
+ {
+ ret = GLEW_NV_occlusion_query;
+ continue;
+ }
+#endif
+#ifdef GL_NV_pack_subimage
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"pack_subimage", 13))
+ {
+ ret = GLEW_NV_pack_subimage;
+ continue;
+ }
+#endif
+#ifdef GL_NV_packed_depth_stencil
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"packed_depth_stencil", 20))
+ {
+ ret = GLEW_NV_packed_depth_stencil;
+ continue;
+ }
+#endif
+#ifdef GL_NV_packed_float
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"packed_float", 12))
+ {
+ ret = GLEW_NV_packed_float;
+ continue;
+ }
+#endif
+#ifdef GL_NV_packed_float_linear
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"packed_float_linear", 19))
+ {
+ ret = GLEW_NV_packed_float_linear;
+ continue;
+ }
+#endif
+#ifdef GL_NV_parameter_buffer_object
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"parameter_buffer_object", 23))
+ {
+ ret = GLEW_NV_parameter_buffer_object;
+ continue;
+ }
+#endif
+#ifdef GL_NV_parameter_buffer_object2
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"parameter_buffer_object2", 24))
+ {
+ ret = GLEW_NV_parameter_buffer_object2;
+ continue;
+ }
+#endif
+#ifdef GL_NV_path_rendering
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"path_rendering", 14))
+ {
+ ret = GLEW_NV_path_rendering;
+ continue;
+ }
+#endif
+#ifdef GL_NV_pixel_buffer_object
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"pixel_buffer_object", 19))
+ {
+ ret = GLEW_NV_pixel_buffer_object;
+ continue;
+ }
+#endif
+#ifdef GL_NV_pixel_data_range
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"pixel_data_range", 16))
+ {
+ ret = GLEW_NV_pixel_data_range;
+ continue;
+ }
+#endif
+#ifdef GL_NV_platform_binary
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"platform_binary", 15))
+ {
+ ret = GLEW_NV_platform_binary;
+ continue;
+ }
+#endif
+#ifdef GL_NV_point_sprite
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"point_sprite", 12))
+ {
+ ret = GLEW_NV_point_sprite;
+ continue;
+ }
+#endif
+#ifdef GL_NV_present_video
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"present_video", 13))
+ {
+ ret = GLEW_NV_present_video;
+ continue;
+ }
+#endif
+#ifdef GL_NV_primitive_restart
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"primitive_restart", 17))
+ {
+ ret = GLEW_NV_primitive_restart;
+ continue;
+ }
+#endif
+#ifdef GL_NV_read_buffer
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"read_buffer", 11))
+ {
+ ret = GLEW_NV_read_buffer;
+ continue;
+ }
+#endif
+#ifdef GL_NV_read_buffer_front
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"read_buffer_front", 17))
+ {
+ ret = GLEW_NV_read_buffer_front;
+ continue;
+ }
+#endif
+#ifdef GL_NV_read_depth
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"read_depth", 10))
+ {
+ ret = GLEW_NV_read_depth;
+ continue;
+ }
+#endif
+#ifdef GL_NV_read_depth_stencil
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"read_depth_stencil", 18))
+ {
+ ret = GLEW_NV_read_depth_stencil;
+ continue;
+ }
+#endif
+#ifdef GL_NV_read_stencil
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"read_stencil", 12))
+ {
+ ret = GLEW_NV_read_stencil;
+ continue;
+ }
+#endif
+#ifdef GL_NV_register_combiners
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"register_combiners", 18))
+ {
+ ret = GLEW_NV_register_combiners;
+ continue;
+ }
+#endif
+#ifdef GL_NV_register_combiners2
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"register_combiners2", 19))
+ {
+ ret = GLEW_NV_register_combiners2;
+ continue;
+ }
+#endif
+#ifdef GL_NV_shader_atomic_counters
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"shader_atomic_counters", 22))
+ {
+ ret = GLEW_NV_shader_atomic_counters;
+ continue;
+ }
+#endif
+#ifdef GL_NV_shader_atomic_float
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"shader_atomic_float", 19))
+ {
+ ret = GLEW_NV_shader_atomic_float;
+ continue;
+ }
+#endif
+#ifdef GL_NV_shader_buffer_load
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"shader_buffer_load", 18))
+ {
+ ret = GLEW_NV_shader_buffer_load;
+ continue;
+ }
+#endif
+#ifdef GL_NV_shader_storage_buffer_object
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"shader_storage_buffer_object", 28))
+ {
+ ret = GLEW_NV_shader_storage_buffer_object;
+ continue;
+ }
+#endif
+#ifdef GL_NV_tessellation_program5
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"tessellation_program5", 21))
+ {
+ ret = GLEW_NV_tessellation_program5;
+ continue;
+ }
+#endif
+#ifdef GL_NV_texgen_emboss
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texgen_emboss", 13))
+ {
+ ret = GLEW_NV_texgen_emboss;
+ continue;
+ }
+#endif
+#ifdef GL_NV_texgen_reflection
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texgen_reflection", 17))
+ {
+ ret = GLEW_NV_texgen_reflection;
+ continue;
+ }
+#endif
+#ifdef GL_NV_texture_array
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_array", 13))
+ {
+ ret = GLEW_NV_texture_array;
+ continue;
+ }
+#endif
+#ifdef GL_NV_texture_barrier
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_barrier", 15))
+ {
+ ret = GLEW_NV_texture_barrier;
+ continue;
+ }
+#endif
+#ifdef GL_NV_texture_compression_latc
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_compression_latc", 24))
+ {
+ ret = GLEW_NV_texture_compression_latc;
+ continue;
+ }
+#endif
+#ifdef GL_NV_texture_compression_s3tc
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_compression_s3tc", 24))
+ {
+ ret = GLEW_NV_texture_compression_s3tc;
+ continue;
+ }
+#endif
+#ifdef GL_NV_texture_compression_s3tc_update
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_compression_s3tc_update", 31))
+ {
+ ret = GLEW_NV_texture_compression_s3tc_update;
+ continue;
+ }
+#endif
+#ifdef GL_NV_texture_compression_vtc
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_compression_vtc", 23))
+ {
+ ret = GLEW_NV_texture_compression_vtc;
+ continue;
+ }
+#endif
+#ifdef GL_NV_texture_env_combine4
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_env_combine4", 20))
+ {
+ ret = GLEW_NV_texture_env_combine4;
+ continue;
+ }
+#endif
+#ifdef GL_NV_texture_expand_normal
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_expand_normal", 21))
+ {
+ ret = GLEW_NV_texture_expand_normal;
+ continue;
+ }
+#endif
+#ifdef GL_NV_texture_multisample
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_multisample", 19))
+ {
+ ret = GLEW_NV_texture_multisample;
+ continue;
+ }
+#endif
+#ifdef GL_NV_texture_npot_2D_mipmap
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_npot_2D_mipmap", 22))
+ {
+ ret = GLEW_NV_texture_npot_2D_mipmap;
+ continue;
+ }
+#endif
+#ifdef GL_NV_texture_rectangle
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_rectangle", 17))
+ {
+ ret = GLEW_NV_texture_rectangle;
+ continue;
+ }
+#endif
+#ifdef GL_NV_texture_shader
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_shader", 14))
+ {
+ ret = GLEW_NV_texture_shader;
+ continue;
+ }
+#endif
+#ifdef GL_NV_texture_shader2
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_shader2", 15))
+ {
+ ret = GLEW_NV_texture_shader2;
+ continue;
+ }
+#endif
+#ifdef GL_NV_texture_shader3
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_shader3", 15))
+ {
+ ret = GLEW_NV_texture_shader3;
+ continue;
+ }
+#endif
+#ifdef GL_NV_transform_feedback
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"transform_feedback", 18))
+ {
+ ret = GLEW_NV_transform_feedback;
+ continue;
+ }
+#endif
+#ifdef GL_NV_transform_feedback2
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"transform_feedback2", 19))
+ {
+ ret = GLEW_NV_transform_feedback2;
+ continue;
+ }
+#endif
+#ifdef GL_NV_vdpau_interop
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"vdpau_interop", 13))
+ {
+ ret = GLEW_NV_vdpau_interop;
+ continue;
+ }
+#endif
+#ifdef GL_NV_vertex_array_range
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"vertex_array_range", 18))
+ {
+ ret = GLEW_NV_vertex_array_range;
+ continue;
+ }
+#endif
+#ifdef GL_NV_vertex_array_range2
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"vertex_array_range2", 19))
+ {
+ ret = GLEW_NV_vertex_array_range2;
+ continue;
+ }
+#endif
+#ifdef GL_NV_vertex_attrib_integer_64bit
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"vertex_attrib_integer_64bit", 27))
+ {
+ ret = GLEW_NV_vertex_attrib_integer_64bit;
+ continue;
+ }
+#endif
+#ifdef GL_NV_vertex_buffer_unified_memory
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"vertex_buffer_unified_memory", 28))
+ {
+ ret = GLEW_NV_vertex_buffer_unified_memory;
+ continue;
+ }
+#endif
+#ifdef GL_NV_vertex_program
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"vertex_program", 14))
+ {
+ ret = GLEW_NV_vertex_program;
+ continue;
+ }
+#endif
+#ifdef GL_NV_vertex_program1_1
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"vertex_program1_1", 17))
+ {
+ ret = GLEW_NV_vertex_program1_1;
+ continue;
+ }
+#endif
+#ifdef GL_NV_vertex_program2
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"vertex_program2", 15))
+ {
+ ret = GLEW_NV_vertex_program2;
+ continue;
+ }
+#endif
+#ifdef GL_NV_vertex_program2_option
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"vertex_program2_option", 22))
+ {
+ ret = GLEW_NV_vertex_program2_option;
+ continue;
+ }
+#endif
+#ifdef GL_NV_vertex_program3
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"vertex_program3", 15))
+ {
+ ret = GLEW_NV_vertex_program3;
+ continue;
+ }
+#endif
+#ifdef GL_NV_vertex_program4
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"vertex_program4", 15))
+ {
+ ret = GLEW_NV_vertex_program4;
+ continue;
+ }
+#endif
+#ifdef GL_NV_video_capture
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"video_capture", 13))
+ {
+ ret = GLEW_NV_video_capture;
+ continue;
+ }
+#endif
+ }
+ if (_glewStrSame2(&pos, &len, (const GLubyte*)"OES_", 4))
+ {
+#ifdef GL_OES_EGL_image
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"EGL_image", 9))
+ {
+ ret = GLEW_OES_EGL_image;
+ continue;
+ }
+#endif
+#ifdef GL_OES_EGL_image_external
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"EGL_image_external", 18))
+ {
+ ret = GLEW_OES_EGL_image_external;
+ continue;
+ }
+#endif
+#ifdef GL_OES_EGL_sync
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"EGL_sync", 8))
+ {
+ ret = GLEW_OES_EGL_sync;
+ continue;
+ }
+#endif
+#ifdef GL_OES_blend_equation_separate
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"blend_equation_separate", 23))
+ {
+ ret = GLEW_OES_blend_equation_separate;
+ continue;
+ }
+#endif
+#ifdef GL_OES_blend_func_separate
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"blend_func_separate", 19))
+ {
+ ret = GLEW_OES_blend_func_separate;
+ continue;
+ }
+#endif
+#ifdef GL_OES_blend_subtract
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"blend_subtract", 14))
+ {
+ ret = GLEW_OES_blend_subtract;
+ continue;
+ }
+#endif
+#ifdef GL_OES_byte_coordinates
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"byte_coordinates", 16))
+ {
+ ret = GLEW_OES_byte_coordinates;
+ continue;
+ }
+#endif
+#ifdef GL_OES_compressed_ETC1_RGB8_texture
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"compressed_ETC1_RGB8_texture", 28))
+ {
+ ret = GLEW_OES_compressed_ETC1_RGB8_texture;
+ continue;
+ }
+#endif
+#ifdef GL_OES_compressed_paletted_texture
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"compressed_paletted_texture", 27))
+ {
+ ret = GLEW_OES_compressed_paletted_texture;
+ continue;
+ }
+#endif
+#ifdef GL_OES_depth24
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"depth24", 7))
+ {
+ ret = GLEW_OES_depth24;
+ continue;
+ }
+#endif
+#ifdef GL_OES_depth32
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"depth32", 7))
+ {
+ ret = GLEW_OES_depth32;
+ continue;
+ }
+#endif
+#ifdef GL_OES_depth_texture
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"depth_texture", 13))
+ {
+ ret = GLEW_OES_depth_texture;
+ continue;
+ }
+#endif
+#ifdef GL_OES_depth_texture_cube_map
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"depth_texture_cube_map", 22))
+ {
+ ret = GLEW_OES_depth_texture_cube_map;
+ continue;
+ }
+#endif
+#ifdef GL_OES_draw_texture
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"draw_texture", 12))
+ {
+ ret = GLEW_OES_draw_texture;
+ continue;
+ }
+#endif
+#ifdef GL_OES_element_index_uint
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"element_index_uint", 18))
+ {
+ ret = GLEW_OES_element_index_uint;
+ continue;
+ }
+#endif
+#ifdef GL_OES_extended_matrix_palette
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"extended_matrix_palette", 23))
+ {
+ ret = GLEW_OES_extended_matrix_palette;
+ continue;
+ }
+#endif
+#ifdef GL_OES_fbo_render_mipmap
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"fbo_render_mipmap", 17))
+ {
+ ret = GLEW_OES_fbo_render_mipmap;
+ continue;
+ }
+#endif
+#ifdef GL_OES_fragment_precision_high
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"fragment_precision_high", 23))
+ {
+ ret = GLEW_OES_fragment_precision_high;
+ continue;
+ }
+#endif
+#ifdef GL_OES_framebuffer_object
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"framebuffer_object", 18))
+ {
+ ret = GLEW_OES_framebuffer_object;
+ continue;
+ }
+#endif
+#ifdef GL_OES_get_program_binary
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"get_program_binary", 18))
+ {
+ ret = GLEW_OES_get_program_binary;
+ continue;
+ }
+#endif
+#ifdef GL_OES_mapbuffer
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"mapbuffer", 9))
+ {
+ ret = GLEW_OES_mapbuffer;
+ continue;
+ }
+#endif
+#ifdef GL_OES_matrix_get
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"matrix_get", 10))
+ {
+ ret = GLEW_OES_matrix_get;
+ continue;
+ }
+#endif
+#ifdef GL_OES_matrix_palette
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"matrix_palette", 14))
+ {
+ ret = GLEW_OES_matrix_palette;
+ continue;
+ }
+#endif
+#ifdef GL_OES_packed_depth_stencil
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"packed_depth_stencil", 20))
+ {
+ ret = GLEW_OES_packed_depth_stencil;
+ continue;
+ }
+#endif
+#ifdef GL_OES_point_size_array
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"point_size_array", 16))
+ {
+ ret = GLEW_OES_point_size_array;
+ continue;
+ }
+#endif
+#ifdef GL_OES_point_sprite
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"point_sprite", 12))
+ {
+ ret = GLEW_OES_point_sprite;
+ continue;
+ }
+#endif
+#ifdef GL_OES_read_format
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"read_format", 11))
+ {
+ ret = GLEW_OES_read_format;
+ continue;
+ }
+#endif
+#ifdef GL_OES_required_internalformat
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"required_internalformat", 23))
+ {
+ ret = GLEW_OES_required_internalformat;
+ continue;
+ }
+#endif
+#ifdef GL_OES_rgb8_rgba8
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"rgb8_rgba8", 10))
+ {
+ ret = GLEW_OES_rgb8_rgba8;
+ continue;
+ }
+#endif
+#ifdef GL_OES_single_precision
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"single_precision", 16))
+ {
+ ret = GLEW_OES_single_precision;
+ continue;
+ }
+#endif
+#ifdef GL_OES_standard_derivatives
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"standard_derivatives", 20))
+ {
+ ret = GLEW_OES_standard_derivatives;
+ continue;
+ }
+#endif
+#ifdef GL_OES_stencil1
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"stencil1", 8))
+ {
+ ret = GLEW_OES_stencil1;
+ continue;
+ }
+#endif
+#ifdef GL_OES_stencil4
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"stencil4", 8))
+ {
+ ret = GLEW_OES_stencil4;
+ continue;
+ }
+#endif
+#ifdef GL_OES_stencil8
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"stencil8", 8))
+ {
+ ret = GLEW_OES_stencil8;
+ continue;
+ }
+#endif
+#ifdef GL_OES_surfaceless_context
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"surfaceless_context", 19))
+ {
+ ret = GLEW_OES_surfaceless_context;
+ continue;
+ }
+#endif
+#ifdef GL_OES_texture_3D
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_3D", 10))
+ {
+ ret = GLEW_OES_texture_3D;
+ continue;
+ }
+#endif
+#ifdef GL_OES_texture_cube_map
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_cube_map", 16))
+ {
+ ret = GLEW_OES_texture_cube_map;
+ continue;
+ }
+#endif
+#ifdef GL_OES_texture_env_crossbar
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_env_crossbar", 20))
+ {
+ ret = GLEW_OES_texture_env_crossbar;
+ continue;
+ }
+#endif
+#ifdef GL_OES_texture_mirrored_repeat
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_mirrored_repeat", 23))
+ {
+ ret = GLEW_OES_texture_mirrored_repeat;
+ continue;
+ }
+#endif
+#ifdef GL_OES_texture_npot
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_npot", 12))
+ {
+ ret = GLEW_OES_texture_npot;
+ continue;
+ }
+#endif
+#ifdef GL_OES_vertex_array_object
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"vertex_array_object", 19))
+ {
+ ret = GLEW_OES_vertex_array_object;
+ continue;
+ }
+#endif
+#ifdef GL_OES_vertex_half_float
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"vertex_half_float", 17))
+ {
+ ret = GLEW_OES_vertex_half_float;
+ continue;
+ }
+#endif
+#ifdef GL_OES_vertex_type_10_10_10_2
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"vertex_type_10_10_10_2", 22))
+ {
+ ret = GLEW_OES_vertex_type_10_10_10_2;
+ continue;
+ }
+#endif
+ }
+ if (_glewStrSame2(&pos, &len, (const GLubyte*)"OML_", 4))
+ {
+#ifdef GL_OML_interlace
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"interlace", 9))
+ {
+ ret = GLEW_OML_interlace;
+ continue;
+ }
+#endif
+#ifdef GL_OML_resample
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"resample", 8))
+ {
+ ret = GLEW_OML_resample;
+ continue;
+ }
+#endif
+#ifdef GL_OML_subsample
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"subsample", 9))
+ {
+ ret = GLEW_OML_subsample;
+ continue;
+ }
+#endif
+ }
+ if (_glewStrSame2(&pos, &len, (const GLubyte*)"PGI_", 4))
+ {
+#ifdef GL_PGI_misc_hints
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"misc_hints", 10))
+ {
+ ret = GLEW_PGI_misc_hints;
+ continue;
+ }
+#endif
+#ifdef GL_PGI_vertex_hints
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"vertex_hints", 12))
+ {
+ ret = GLEW_PGI_vertex_hints;
+ continue;
+ }
+#endif
+ }
+ if (_glewStrSame2(&pos, &len, (const GLubyte*)"QCOM_", 5))
+ {
+#ifdef GL_QCOM_alpha_test
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"alpha_test", 10))
+ {
+ ret = GLEW_QCOM_alpha_test;
+ continue;
+ }
+#endif
+#ifdef GL_QCOM_binning_control
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"binning_control", 15))
+ {
+ ret = GLEW_QCOM_binning_control;
+ continue;
+ }
+#endif
+#ifdef GL_QCOM_driver_control
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"driver_control", 14))
+ {
+ ret = GLEW_QCOM_driver_control;
+ continue;
+ }
+#endif
+#ifdef GL_QCOM_extended_get
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"extended_get", 12))
+ {
+ ret = GLEW_QCOM_extended_get;
+ continue;
+ }
+#endif
+#ifdef GL_QCOM_extended_get2
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"extended_get2", 13))
+ {
+ ret = GLEW_QCOM_extended_get2;
+ continue;
+ }
+#endif
+#ifdef GL_QCOM_perfmon_global_mode
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"perfmon_global_mode", 19))
+ {
+ ret = GLEW_QCOM_perfmon_global_mode;
+ continue;
+ }
+#endif
+#ifdef GL_QCOM_tiled_rendering
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"tiled_rendering", 15))
+ {
+ ret = GLEW_QCOM_tiled_rendering;
+ continue;
+ }
+#endif
+#ifdef GL_QCOM_writeonly_rendering
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"writeonly_rendering", 19))
+ {
+ ret = GLEW_QCOM_writeonly_rendering;
+ continue;
+ }
+#endif
+ }
+ if (_glewStrSame2(&pos, &len, (const GLubyte*)"REND_", 5))
+ {
+#ifdef GL_REND_screen_coordinates
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"screen_coordinates", 18))
+ {
+ ret = GLEW_REND_screen_coordinates;
+ continue;
+ }
+#endif
+ }
+ if (_glewStrSame2(&pos, &len, (const GLubyte*)"S3_", 3))
+ {
+#ifdef GL_S3_s3tc
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"s3tc", 4))
+ {
+ ret = GLEW_S3_s3tc;
+ continue;
+ }
+#endif
+ }
+ if (_glewStrSame2(&pos, &len, (const GLubyte*)"SGIS_", 5))
+ {
+#ifdef GL_SGIS_color_range
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"color_range", 11))
+ {
+ ret = GLEW_SGIS_color_range;
+ continue;
+ }
+#endif
+#ifdef GL_SGIS_detail_texture
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"detail_texture", 14))
+ {
+ ret = GLEW_SGIS_detail_texture;
+ continue;
+ }
+#endif
+#ifdef GL_SGIS_fog_function
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"fog_function", 12))
+ {
+ ret = GLEW_SGIS_fog_function;
+ continue;
+ }
+#endif
+#ifdef GL_SGIS_generate_mipmap
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"generate_mipmap", 15))
+ {
+ ret = GLEW_SGIS_generate_mipmap;
+ continue;
+ }
+#endif
+#ifdef GL_SGIS_multisample
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"multisample", 11))
+ {
+ ret = GLEW_SGIS_multisample;
+ continue;
+ }
+#endif
+#ifdef GL_SGIS_pixel_texture
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"pixel_texture", 13))
+ {
+ ret = GLEW_SGIS_pixel_texture;
+ continue;
+ }
+#endif
+#ifdef GL_SGIS_point_line_texgen
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"point_line_texgen", 17))
+ {
+ ret = GLEW_SGIS_point_line_texgen;
+ continue;
+ }
+#endif
+#ifdef GL_SGIS_sharpen_texture
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"sharpen_texture", 15))
+ {
+ ret = GLEW_SGIS_sharpen_texture;
+ continue;
+ }
+#endif
+#ifdef GL_SGIS_texture4D
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture4D", 9))
+ {
+ ret = GLEW_SGIS_texture4D;
+ continue;
+ }
+#endif
+#ifdef GL_SGIS_texture_border_clamp
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_border_clamp", 20))
+ {
+ ret = GLEW_SGIS_texture_border_clamp;
+ continue;
+ }
+#endif
+#ifdef GL_SGIS_texture_edge_clamp
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_edge_clamp", 18))
+ {
+ ret = GLEW_SGIS_texture_edge_clamp;
+ continue;
+ }
+#endif
+#ifdef GL_SGIS_texture_filter4
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_filter4", 15))
+ {
+ ret = GLEW_SGIS_texture_filter4;
+ continue;
+ }
+#endif
+#ifdef GL_SGIS_texture_lod
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_lod", 11))
+ {
+ ret = GLEW_SGIS_texture_lod;
+ continue;
+ }
+#endif
+#ifdef GL_SGIS_texture_select
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_select", 14))
+ {
+ ret = GLEW_SGIS_texture_select;
+ continue;
+ }
+#endif
+ }
+ if (_glewStrSame2(&pos, &len, (const GLubyte*)"SGIX_", 5))
+ {
+#ifdef GL_SGIX_async
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"async", 5))
+ {
+ ret = GLEW_SGIX_async;
+ continue;
+ }
+#endif
+#ifdef GL_SGIX_async_histogram
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"async_histogram", 15))
+ {
+ ret = GLEW_SGIX_async_histogram;
+ continue;
+ }
+#endif
+#ifdef GL_SGIX_async_pixel
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"async_pixel", 11))
+ {
+ ret = GLEW_SGIX_async_pixel;
+ continue;
+ }
+#endif
+#ifdef GL_SGIX_blend_alpha_minmax
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"blend_alpha_minmax", 18))
+ {
+ ret = GLEW_SGIX_blend_alpha_minmax;
+ continue;
+ }
+#endif
+#ifdef GL_SGIX_clipmap
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"clipmap", 7))
+ {
+ ret = GLEW_SGIX_clipmap;
+ continue;
+ }
+#endif
+#ifdef GL_SGIX_convolution_accuracy
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"convolution_accuracy", 20))
+ {
+ ret = GLEW_SGIX_convolution_accuracy;
+ continue;
+ }
+#endif
+#ifdef GL_SGIX_depth_texture
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"depth_texture", 13))
+ {
+ ret = GLEW_SGIX_depth_texture;
+ continue;
+ }
+#endif
+#ifdef GL_SGIX_flush_raster
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"flush_raster", 12))
+ {
+ ret = GLEW_SGIX_flush_raster;
+ continue;
+ }
+#endif
+#ifdef GL_SGIX_fog_offset
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"fog_offset", 10))
+ {
+ ret = GLEW_SGIX_fog_offset;
+ continue;
+ }
+#endif
+#ifdef GL_SGIX_fog_texture
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"fog_texture", 11))
+ {
+ ret = GLEW_SGIX_fog_texture;
+ continue;
+ }
+#endif
+#ifdef GL_SGIX_fragment_specular_lighting
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"fragment_specular_lighting", 26))
+ {
+ ret = GLEW_SGIX_fragment_specular_lighting;
+ continue;
+ }
+#endif
+#ifdef GL_SGIX_framezoom
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"framezoom", 9))
+ {
+ ret = GLEW_SGIX_framezoom;
+ continue;
+ }
+#endif
+#ifdef GL_SGIX_interlace
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"interlace", 9))
+ {
+ ret = GLEW_SGIX_interlace;
+ continue;
+ }
+#endif
+#ifdef GL_SGIX_ir_instrument1
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"ir_instrument1", 14))
+ {
+ ret = GLEW_SGIX_ir_instrument1;
+ continue;
+ }
+#endif
+#ifdef GL_SGIX_list_priority
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"list_priority", 13))
+ {
+ ret = GLEW_SGIX_list_priority;
+ continue;
+ }
+#endif
+#ifdef GL_SGIX_pixel_texture
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"pixel_texture", 13))
+ {
+ ret = GLEW_SGIX_pixel_texture;
+ continue;
+ }
+#endif
+#ifdef GL_SGIX_pixel_texture_bits
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"pixel_texture_bits", 18))
+ {
+ ret = GLEW_SGIX_pixel_texture_bits;
+ continue;
+ }
+#endif
+#ifdef GL_SGIX_reference_plane
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"reference_plane", 15))
+ {
+ ret = GLEW_SGIX_reference_plane;
+ continue;
+ }
+#endif
+#ifdef GL_SGIX_resample
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"resample", 8))
+ {
+ ret = GLEW_SGIX_resample;
+ continue;
+ }
+#endif
+#ifdef GL_SGIX_shadow
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"shadow", 6))
+ {
+ ret = GLEW_SGIX_shadow;
+ continue;
+ }
+#endif
+#ifdef GL_SGIX_shadow_ambient
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"shadow_ambient", 14))
+ {
+ ret = GLEW_SGIX_shadow_ambient;
+ continue;
+ }
+#endif
+#ifdef GL_SGIX_sprite
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"sprite", 6))
+ {
+ ret = GLEW_SGIX_sprite;
+ continue;
+ }
+#endif
+#ifdef GL_SGIX_tag_sample_buffer
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"tag_sample_buffer", 17))
+ {
+ ret = GLEW_SGIX_tag_sample_buffer;
+ continue;
+ }
+#endif
+#ifdef GL_SGIX_texture_add_env
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_add_env", 15))
+ {
+ ret = GLEW_SGIX_texture_add_env;
+ continue;
+ }
+#endif
+#ifdef GL_SGIX_texture_coordinate_clamp
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_coordinate_clamp", 24))
+ {
+ ret = GLEW_SGIX_texture_coordinate_clamp;
+ continue;
+ }
+#endif
+#ifdef GL_SGIX_texture_lod_bias
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_lod_bias", 16))
+ {
+ ret = GLEW_SGIX_texture_lod_bias;
+ continue;
+ }
+#endif
+#ifdef GL_SGIX_texture_multi_buffer
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_multi_buffer", 20))
+ {
+ ret = GLEW_SGIX_texture_multi_buffer;
+ continue;
+ }
+#endif
+#ifdef GL_SGIX_texture_range
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_range", 13))
+ {
+ ret = GLEW_SGIX_texture_range;
+ continue;
+ }
+#endif
+#ifdef GL_SGIX_texture_scale_bias
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_scale_bias", 18))
+ {
+ ret = GLEW_SGIX_texture_scale_bias;
+ continue;
+ }
+#endif
+#ifdef GL_SGIX_vertex_preclip
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"vertex_preclip", 14))
+ {
+ ret = GLEW_SGIX_vertex_preclip;
+ continue;
+ }
+#endif
+#ifdef GL_SGIX_vertex_preclip_hint
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"vertex_preclip_hint", 19))
+ {
+ ret = GLEW_SGIX_vertex_preclip_hint;
+ continue;
+ }
+#endif
+#ifdef GL_SGIX_ycrcb
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"ycrcb", 5))
+ {
+ ret = GLEW_SGIX_ycrcb;
+ continue;
+ }
+#endif
+ }
+ if (_glewStrSame2(&pos, &len, (const GLubyte*)"SGI_", 4))
+ {
+#ifdef GL_SGI_color_matrix
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"color_matrix", 12))
+ {
+ ret = GLEW_SGI_color_matrix;
+ continue;
+ }
+#endif
+#ifdef GL_SGI_color_table
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"color_table", 11))
+ {
+ ret = GLEW_SGI_color_table;
+ continue;
+ }
+#endif
+#ifdef GL_SGI_texture_color_table
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_color_table", 19))
+ {
+ ret = GLEW_SGI_texture_color_table;
+ continue;
+ }
+#endif
+ }
+ if (_glewStrSame2(&pos, &len, (const GLubyte*)"SUNX_", 5))
+ {
+#ifdef GL_SUNX_constant_data
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"constant_data", 13))
+ {
+ ret = GLEW_SUNX_constant_data;
+ continue;
+ }
+#endif
+ }
+ if (_glewStrSame2(&pos, &len, (const GLubyte*)"SUN_", 4))
+ {
+#ifdef GL_SUN_convolution_border_modes
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"convolution_border_modes", 24))
+ {
+ ret = GLEW_SUN_convolution_border_modes;
+ continue;
+ }
+#endif
+#ifdef GL_SUN_global_alpha
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"global_alpha", 12))
+ {
+ ret = GLEW_SUN_global_alpha;
+ continue;
+ }
+#endif
+#ifdef GL_SUN_mesh_array
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"mesh_array", 10))
+ {
+ ret = GLEW_SUN_mesh_array;
+ continue;
+ }
+#endif
+#ifdef GL_SUN_multi_draw_arrays
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"multi_draw_arrays", 17))
+ {
+ ret = GLEW_SUN_multi_draw_arrays;
+ continue;
+ }
+#endif
+#ifdef GL_SUN_read_video_pixels
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"read_video_pixels", 17))
+ {
+ ret = GLEW_SUN_read_video_pixels;
+ continue;
+ }
+#endif
+#ifdef GL_SUN_slice_accum
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"slice_accum", 11))
+ {
+ ret = GLEW_SUN_slice_accum;
+ continue;
+ }
+#endif
+#ifdef GL_SUN_triangle_list
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"triangle_list", 13))
+ {
+ ret = GLEW_SUN_triangle_list;
+ continue;
+ }
+#endif
+#ifdef GL_SUN_vertex
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"vertex", 6))
+ {
+ ret = GLEW_SUN_vertex;
+ continue;
+ }
+#endif
+ }
+ if (_glewStrSame2(&pos, &len, (const GLubyte*)"VERSION_", 8))
+ {
+#ifdef GL_VERSION_1_1
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"1_1", 3))
+ {
+ ret = GLEW_VERSION_1_1;
+ continue;
+ }
+#endif
+#ifdef GL_VERSION_1_2
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"1_2", 3))
+ {
+ ret = GLEW_VERSION_1_2;
+ continue;
+ }
+#endif
+#ifdef GL_VERSION_1_2_1
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"1_2_1", 5))
+ {
+ ret = GLEW_VERSION_1_2_1;
+ continue;
+ }
+#endif
+#ifdef GL_VERSION_1_3
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"1_3", 3))
+ {
+ ret = GLEW_VERSION_1_3;
+ continue;
+ }
+#endif
+#ifdef GL_VERSION_1_4
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"1_4", 3))
+ {
+ ret = GLEW_VERSION_1_4;
+ continue;
+ }
+#endif
+#ifdef GL_VERSION_1_5
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"1_5", 3))
+ {
+ ret = GLEW_VERSION_1_5;
+ continue;
+ }
+#endif
+#ifdef GL_VERSION_2_0
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"2_0", 3))
+ {
+ ret = GLEW_VERSION_2_0;
+ continue;
+ }
+#endif
+#ifdef GL_VERSION_2_1
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"2_1", 3))
+ {
+ ret = GLEW_VERSION_2_1;
+ continue;
+ }
+#endif
+#ifdef GL_VERSION_3_0
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"3_0", 3))
+ {
+ ret = GLEW_VERSION_3_0;
+ continue;
+ }
+#endif
+#ifdef GL_VERSION_3_1
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"3_1", 3))
+ {
+ ret = GLEW_VERSION_3_1;
+ continue;
+ }
+#endif
+#ifdef GL_VERSION_3_2
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"3_2", 3))
+ {
+ ret = GLEW_VERSION_3_2;
+ continue;
+ }
+#endif
+#ifdef GL_VERSION_3_3
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"3_3", 3))
+ {
+ ret = GLEW_VERSION_3_3;
+ continue;
+ }
+#endif
+#ifdef GL_VERSION_4_0
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"4_0", 3))
+ {
+ ret = GLEW_VERSION_4_0;
+ continue;
+ }
+#endif
+#ifdef GL_VERSION_4_1
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"4_1", 3))
+ {
+ ret = GLEW_VERSION_4_1;
+ continue;
+ }
+#endif
+#ifdef GL_VERSION_4_2
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"4_2", 3))
+ {
+ ret = GLEW_VERSION_4_2;
+ continue;
+ }
+#endif
+ }
+ if (_glewStrSame2(&pos, &len, (const GLubyte*)"VG_", 3))
+ {
+#ifdef GL_VG_KHR_EGL_sync
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"KHR_EGL_sync", 12))
+ {
+ ret = GLEW_VG_KHR_EGL_sync;
+ continue;
+ }
+#endif
+ }
+ if (_glewStrSame2(&pos, &len, (const GLubyte*)"VIV_", 4))
+ {
+#ifdef GL_VIV_shader_binary
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"shader_binary", 13))
+ {
+ ret = GLEW_VIV_shader_binary;
+ continue;
+ }
+#endif
+ }
+ if (_glewStrSame2(&pos, &len, (const GLubyte*)"WIN_", 4))
+ {
+#ifdef GL_WIN_phong_shading
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"phong_shading", 13))
+ {
+ ret = GLEW_WIN_phong_shading;
+ continue;
+ }
+#endif
+#ifdef GL_WIN_specular_fog
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"specular_fog", 12))
+ {
+ ret = GLEW_WIN_specular_fog;
+ continue;
+ }
+#endif
+#ifdef GL_WIN_swap_hint
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"swap_hint", 9))
+ {
+ ret = GLEW_WIN_swap_hint;
+ continue;
+ }
+#endif
+ }
+ }
+ ret = (len == 0);
+ }
+ return ret;
+}
+
+#if defined(GLEW_INC_EGL)
+
+#if defined(GLEW_MX)
+GLboolean eglewContextIsSupported (const EGLEWContext* ctx, const char* name)
+#else
+GLboolean eglewIsSupported (const char* name)
+#endif
+{
+ GLubyte* pos = (GLubyte*)name;
+ GLuint len = _glewStrLen(pos);
+ GLboolean ret = GL_TRUE;
+ while (ret && len > 0)
+ {
+ if (_glewStrSame1(&pos, &len, (const GLubyte*)"EGL_", 4))
+ {
+ if (_glewStrSame2(&pos, &len, (const GLubyte*)"ANDROID_", 8))
+ {
+#ifdef EGL_ANDROID_blob_cache
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"blob_cache", 10))
+ {
+ ret = EGLEW_ANDROID_blob_cache;
+ continue;
+ }
+#endif
+#ifdef EGL_ANDROID_framebuffer_target
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"framebuffer_target", 18))
+ {
+ ret = EGLEW_ANDROID_framebuffer_target;
+ continue;
+ }
+#endif
+#ifdef EGL_ANDROID_image_native_buffer
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"image_native_buffer", 19))
+ {
+ ret = EGLEW_ANDROID_image_native_buffer;
+ continue;
+ }
+#endif
+#ifdef EGL_ANDROID_native_fence_sync
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"native_fence_sync", 17))
+ {
+ ret = EGLEW_ANDROID_native_fence_sync;
+ continue;
+ }
+#endif
+#ifdef EGL_ANDROID_recordable
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"recordable", 10))
+ {
+ ret = EGLEW_ANDROID_recordable;
+ continue;
+ }
+#endif
+ }
+ if (_glewStrSame2(&pos, &len, (const GLubyte*)"ANGLE_", 6))
+ {
+#ifdef EGL_ANGLE_d3d_share_handle_client_buffer
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"d3d_share_handle_client_buffer", 30))
+ {
+ ret = EGLEW_ANGLE_d3d_share_handle_client_buffer;
+ continue;
+ }
+#endif
+#ifdef EGL_ANGLE_query_surface_pointer
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"query_surface_pointer", 21))
+ {
+ ret = EGLEW_ANGLE_query_surface_pointer;
+ continue;
+ }
+#endif
+#ifdef EGL_ANGLE_surface_d3d_texture_2d_share_handle
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"surface_d3d_texture_2d_share_handle", 35))
+ {
+ ret = EGLEW_ANGLE_surface_d3d_texture_2d_share_handle;
+ continue;
+ }
+#endif
+ }
+ if (_glewStrSame2(&pos, &len, (const GLubyte*)"EXT_", 4))
+ {
+#ifdef EGL_EXT_buffer_age
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"buffer_age", 10))
+ {
+ ret = EGLEW_EXT_buffer_age;
+ continue;
+ }
+#endif
+#ifdef EGL_EXT_create_context_robustness
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"create_context_robustness", 25))
+ {
+ ret = EGLEW_EXT_create_context_robustness;
+ continue;
+ }
+#endif
+#ifdef EGL_EXT_multiview_window
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"multiview_window", 16))
+ {
+ ret = EGLEW_EXT_multiview_window;
+ continue;
+ }
+#endif
+ }
+ if (_glewStrSame2(&pos, &len, (const GLubyte*)"HI_", 3))
+ {
+#ifdef EGL_HI_clientpixmap
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"clientpixmap", 12))
+ {
+ ret = EGLEW_HI_clientpixmap;
+ continue;
+ }
+#endif
+#ifdef EGL_HI_colorformats
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"colorformats", 12))
+ {
+ ret = EGLEW_HI_colorformats;
+ continue;
+ }
+#endif
+ }
+ if (_glewStrSame2(&pos, &len, (const GLubyte*)"IMG_", 4))
+ {
+#ifdef EGL_IMG_context_priority
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"context_priority", 16))
+ {
+ ret = EGLEW_IMG_context_priority;
+ continue;
+ }
+#endif
+ }
+ if (_glewStrSame2(&pos, &len, (const GLubyte*)"KHR_", 4))
+ {
+#ifdef EGL_KHR_config_attribs
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"config_attribs", 14))
+ {
+ ret = EGLEW_KHR_config_attribs;
+ continue;
+ }
+#endif
+#ifdef EGL_KHR_create_context
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"create_context", 14))
+ {
+ ret = EGLEW_KHR_create_context;
+ continue;
+ }
+#endif
+#ifdef EGL_KHR_fence_sync
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"fence_sync", 10))
+ {
+ ret = EGLEW_KHR_fence_sync;
+ continue;
+ }
+#endif
+#ifdef EGL_KHR_gl_renderbuffer_image
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"gl_renderbuffer_image", 21))
+ {
+ ret = EGLEW_KHR_gl_renderbuffer_image;
+ continue;
+ }
+#endif
+#ifdef EGL_KHR_gl_texture_2D_image
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"gl_texture_2D_image", 19))
+ {
+ ret = EGLEW_KHR_gl_texture_2D_image;
+ continue;
+ }
+#endif
+#ifdef EGL_KHR_gl_texture_3D_image
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"gl_texture_3D_image", 19))
+ {
+ ret = EGLEW_KHR_gl_texture_3D_image;
+ continue;
+ }
+#endif
+#ifdef EGL_KHR_gl_texture_cubemap_image
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"gl_texture_cubemap_image", 24))
+ {
+ ret = EGLEW_KHR_gl_texture_cubemap_image;
+ continue;
+ }
+#endif
+#ifdef EGL_KHR_image
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"image", 5))
+ {
+ ret = EGLEW_KHR_image;
+ continue;
+ }
+#endif
+#ifdef EGL_KHR_image_base
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"image_base", 10))
+ {
+ ret = EGLEW_KHR_image_base;
+ continue;
+ }
+#endif
+#ifdef EGL_KHR_image_pixmap
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"image_pixmap", 12))
+ {
+ ret = EGLEW_KHR_image_pixmap;
+ continue;
+ }
+#endif
+#ifdef EGL_KHR_lock_surface
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"lock_surface", 12))
+ {
+ ret = EGLEW_KHR_lock_surface;
+ continue;
+ }
+#endif
+#ifdef EGL_KHR_lock_surface2
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"lock_surface2", 13))
+ {
+ ret = EGLEW_KHR_lock_surface2;
+ continue;
+ }
+#endif
+#ifdef EGL_KHR_reusable_sync
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"reusable_sync", 13))
+ {
+ ret = EGLEW_KHR_reusable_sync;
+ continue;
+ }
+#endif
+#ifdef EGL_KHR_stream
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"stream", 6))
+ {
+ ret = EGLEW_KHR_stream;
+ continue;
+ }
+#endif
+#ifdef EGL_KHR_stream_consumer_gltexture
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"stream_consumer_gltexture", 25))
+ {
+ ret = EGLEW_KHR_stream_consumer_gltexture;
+ continue;
+ }
+#endif
+#ifdef EGL_KHR_stream_cross_process_fd
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"stream_cross_process_fd", 23))
+ {
+ ret = EGLEW_KHR_stream_cross_process_fd;
+ continue;
+ }
+#endif
+#ifdef EGL_KHR_stream_fifo
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"stream_fifo", 11))
+ {
+ ret = EGLEW_KHR_stream_fifo;
+ continue;
+ }
+#endif
+#ifdef EGL_KHR_stream_producer_aldatalocator
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"stream_producer_aldatalocator", 29))
+ {
+ ret = EGLEW_KHR_stream_producer_aldatalocator;
+ continue;
+ }
+#endif
+#ifdef EGL_KHR_stream_producer_eglsurface
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"stream_producer_eglsurface", 26))
+ {
+ ret = EGLEW_KHR_stream_producer_eglsurface;
+ continue;
+ }
+#endif
+#ifdef EGL_KHR_surfaceless_context
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"surfaceless_context", 19))
+ {
+ ret = EGLEW_KHR_surfaceless_context;
+ continue;
+ }
+#endif
+#ifdef EGL_KHR_vg_parent_image
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"vg_parent_image", 15))
+ {
+ ret = EGLEW_KHR_vg_parent_image;
+ continue;
+ }
+#endif
+#ifdef EGL_KHR_wait_sync
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"wait_sync", 9))
+ {
+ ret = EGLEW_KHR_wait_sync;
+ continue;
+ }
+#endif
+ }
+ if (_glewStrSame2(&pos, &len, (const GLubyte*)"MESA_", 5))
+ {
+#ifdef EGL_MESA_drm_image
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"drm_image", 9))
+ {
+ ret = EGLEW_MESA_drm_image;
+ continue;
+ }
+#endif
+ }
+ if (_glewStrSame2(&pos, &len, (const GLubyte*)"NV_", 3))
+ {
+#ifdef EGL_NV_3dvision_surface
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"3dvision_surface", 16))
+ {
+ ret = EGLEW_NV_3dvision_surface;
+ continue;
+ }
+#endif
+#ifdef EGL_NV_coverage_sample
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"coverage_sample", 15))
+ {
+ ret = EGLEW_NV_coverage_sample;
+ continue;
+ }
+#endif
+#ifdef EGL_NV_coverage_sample_resolve
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"coverage_sample_resolve", 23))
+ {
+ ret = EGLEW_NV_coverage_sample_resolve;
+ continue;
+ }
+#endif
+#ifdef EGL_NV_depth_nonlinear
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"depth_nonlinear", 15))
+ {
+ ret = EGLEW_NV_depth_nonlinear;
+ continue;
+ }
+#endif
+#ifdef EGL_NV_native_query
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"native_query", 12))
+ {
+ ret = EGLEW_NV_native_query;
+ continue;
+ }
+#endif
+#ifdef EGL_NV_post_convert_rounding
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"post_convert_rounding", 21))
+ {
+ ret = EGLEW_NV_post_convert_rounding;
+ continue;
+ }
+#endif
+#ifdef EGL_NV_post_sub_buffer
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"post_sub_buffer", 15))
+ {
+ ret = EGLEW_NV_post_sub_buffer;
+ continue;
+ }
+#endif
+#ifdef EGL_NV_sync
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"sync", 4))
+ {
+ ret = EGLEW_NV_sync;
+ continue;
+ }
+#endif
+#ifdef EGL_NV_system_time
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"system_time", 11))
+ {
+ ret = EGLEW_NV_system_time;
+ continue;
+ }
+#endif
+ }
+ if (_glewStrSame2(&pos, &len, (const GLubyte*)"VERSION_", 8))
+ {
+#ifdef EGL_VERSION_1_2
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"1_2", 3))
+ {
+ ret = EGLEW_VERSION_1_2;
+ continue;
+ }
+#endif
+#ifdef EGL_VERSION_1_3
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"1_3", 3))
+ {
+ ret = EGLEW_VERSION_1_3;
+ continue;
+ }
+#endif
+#ifdef EGL_VERSION_1_4
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"1_4", 3))
+ {
+ ret = EGLEW_VERSION_1_4;
+ continue;
+ }
+#endif
+ }
+ }
+ ret = (len == 0);
+ }
+ return ret;
+}
+
+#elif defined(_WIN32)
+
+#if defined(GLEW_MX)
+GLboolean wglewContextIsSupported (const WGLEWContext* ctx, const char* name)
+#else
+GLboolean wglewIsSupported (const char* name)
+#endif
+{
+ GLubyte* pos = (GLubyte*)name;
+ GLuint len = _glewStrLen(pos);
+ GLboolean ret = GL_TRUE;
+ while (ret && len > 0)
+ {
+ if (_glewStrSame1(&pos, &len, (const GLubyte*)"WGL_", 4))
+ {
+ if (_glewStrSame2(&pos, &len, (const GLubyte*)"3DFX_", 5))
+ {
+#ifdef WGL_3DFX_multisample
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"multisample", 11))
+ {
+ ret = WGLEW_3DFX_multisample;
+ continue;
+ }
+#endif
+ }
+ if (_glewStrSame2(&pos, &len, (const GLubyte*)"3DL_", 4))
+ {
+#ifdef WGL_3DL_stereo_control
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"stereo_control", 14))
+ {
+ ret = WGLEW_3DL_stereo_control;
+ continue;
+ }
+#endif
+ }
+ if (_glewStrSame2(&pos, &len, (const GLubyte*)"AMD_", 4))
+ {
+#ifdef WGL_AMD_gpu_association
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"gpu_association", 15))
+ {
+ ret = WGLEW_AMD_gpu_association;
+ continue;
+ }
+#endif
+ }
+ if (_glewStrSame2(&pos, &len, (const GLubyte*)"ARB_", 4))
+ {
+#ifdef WGL_ARB_buffer_region
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"buffer_region", 13))
+ {
+ ret = WGLEW_ARB_buffer_region;
+ continue;
+ }
+#endif
+#ifdef WGL_ARB_create_context
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"create_context", 14))
+ {
+ ret = WGLEW_ARB_create_context;
+ continue;
+ }
+#endif
+#ifdef WGL_ARB_create_context_profile
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"create_context_profile", 22))
+ {
+ ret = WGLEW_ARB_create_context_profile;
+ continue;
+ }
+#endif
+#ifdef WGL_ARB_create_context_robustness
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"create_context_robustness", 25))
+ {
+ ret = WGLEW_ARB_create_context_robustness;
+ continue;
+ }
+#endif
+#ifdef WGL_ARB_extensions_string
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"extensions_string", 17))
+ {
+ ret = WGLEW_ARB_extensions_string;
+ continue;
+ }
+#endif
+#ifdef WGL_ARB_framebuffer_sRGB
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"framebuffer_sRGB", 16))
+ {
+ ret = WGLEW_ARB_framebuffer_sRGB;
+ continue;
+ }
+#endif
+#ifdef WGL_ARB_make_current_read
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"make_current_read", 17))
+ {
+ ret = WGLEW_ARB_make_current_read;
+ continue;
+ }
+#endif
+#ifdef WGL_ARB_multisample
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"multisample", 11))
+ {
+ ret = WGLEW_ARB_multisample;
+ continue;
+ }
+#endif
+#ifdef WGL_ARB_pbuffer
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"pbuffer", 7))
+ {
+ ret = WGLEW_ARB_pbuffer;
+ continue;
+ }
+#endif
+#ifdef WGL_ARB_pixel_format
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"pixel_format", 12))
+ {
+ ret = WGLEW_ARB_pixel_format;
+ continue;
+ }
+#endif
+#ifdef WGL_ARB_pixel_format_float
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"pixel_format_float", 18))
+ {
+ ret = WGLEW_ARB_pixel_format_float;
+ continue;
+ }
+#endif
+#ifdef WGL_ARB_render_texture
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"render_texture", 14))
+ {
+ ret = WGLEW_ARB_render_texture;
+ continue;
+ }
+#endif
+#ifdef WGL_ARB_robustness_application_isolation
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"robustness_application_isolation", 32))
+ {
+ ret = WGLEW_ARB_robustness_application_isolation;
+ continue;
+ }
+#endif
+#ifdef WGL_ARB_robustness_share_group_isolation
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"robustness_share_group_isolation", 32))
+ {
+ ret = WGLEW_ARB_robustness_share_group_isolation;
+ continue;
+ }
+#endif
+ }
+ if (_glewStrSame2(&pos, &len, (const GLubyte*)"ATI_", 4))
+ {
+#ifdef WGL_ATI_pixel_format_float
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"pixel_format_float", 18))
+ {
+ ret = WGLEW_ATI_pixel_format_float;
+ continue;
+ }
+#endif
+#ifdef WGL_ATI_render_texture_rectangle
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"render_texture_rectangle", 24))
+ {
+ ret = WGLEW_ATI_render_texture_rectangle;
+ continue;
+ }
+#endif
+ }
+ if (_glewStrSame2(&pos, &len, (const GLubyte*)"EXT_", 4))
+ {
+#ifdef WGL_EXT_create_context_es2_profile
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"create_context_es2_profile", 26))
+ {
+ ret = WGLEW_EXT_create_context_es2_profile;
+ continue;
+ }
+#endif
+#ifdef WGL_EXT_create_context_es_profile
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"create_context_es_profile", 25))
+ {
+ ret = WGLEW_EXT_create_context_es_profile;
+ continue;
+ }
+#endif
+#ifdef WGL_EXT_depth_float
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"depth_float", 11))
+ {
+ ret = WGLEW_EXT_depth_float;
+ continue;
+ }
+#endif
+#ifdef WGL_EXT_display_color_table
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"display_color_table", 19))
+ {
+ ret = WGLEW_EXT_display_color_table;
+ continue;
+ }
+#endif
+#ifdef WGL_EXT_extensions_string
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"extensions_string", 17))
+ {
+ ret = WGLEW_EXT_extensions_string;
+ continue;
+ }
+#endif
+#ifdef WGL_EXT_framebuffer_sRGB
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"framebuffer_sRGB", 16))
+ {
+ ret = WGLEW_EXT_framebuffer_sRGB;
+ continue;
+ }
+#endif
+#ifdef WGL_EXT_make_current_read
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"make_current_read", 17))
+ {
+ ret = WGLEW_EXT_make_current_read;
+ continue;
+ }
+#endif
+#ifdef WGL_EXT_multisample
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"multisample", 11))
+ {
+ ret = WGLEW_EXT_multisample;
+ continue;
+ }
+#endif
+#ifdef WGL_EXT_pbuffer
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"pbuffer", 7))
+ {
+ ret = WGLEW_EXT_pbuffer;
+ continue;
+ }
+#endif
+#ifdef WGL_EXT_pixel_format
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"pixel_format", 12))
+ {
+ ret = WGLEW_EXT_pixel_format;
+ continue;
+ }
+#endif
+#ifdef WGL_EXT_pixel_format_packed_float
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"pixel_format_packed_float", 25))
+ {
+ ret = WGLEW_EXT_pixel_format_packed_float;
+ continue;
+ }
+#endif
+#ifdef WGL_EXT_swap_control
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"swap_control", 12))
+ {
+ ret = WGLEW_EXT_swap_control;
+ continue;
+ }
+#endif
+#ifdef WGL_EXT_swap_control_tear
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"swap_control_tear", 17))
+ {
+ ret = WGLEW_EXT_swap_control_tear;
+ continue;
+ }
+#endif
+ }
+ if (_glewStrSame2(&pos, &len, (const GLubyte*)"I3D_", 4))
+ {
+#ifdef WGL_I3D_digital_video_control
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"digital_video_control", 21))
+ {
+ ret = WGLEW_I3D_digital_video_control;
+ continue;
+ }
+#endif
+#ifdef WGL_I3D_gamma
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"gamma", 5))
+ {
+ ret = WGLEW_I3D_gamma;
+ continue;
+ }
+#endif
+#ifdef WGL_I3D_genlock
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"genlock", 7))
+ {
+ ret = WGLEW_I3D_genlock;
+ continue;
+ }
+#endif
+#ifdef WGL_I3D_image_buffer
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"image_buffer", 12))
+ {
+ ret = WGLEW_I3D_image_buffer;
+ continue;
+ }
+#endif
+#ifdef WGL_I3D_swap_frame_lock
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"swap_frame_lock", 15))
+ {
+ ret = WGLEW_I3D_swap_frame_lock;
+ continue;
+ }
+#endif
+#ifdef WGL_I3D_swap_frame_usage
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"swap_frame_usage", 16))
+ {
+ ret = WGLEW_I3D_swap_frame_usage;
+ continue;
+ }
+#endif
+ }
+ if (_glewStrSame2(&pos, &len, (const GLubyte*)"NV_", 3))
+ {
+#ifdef WGL_NV_DX_interop
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"DX_interop", 10))
+ {
+ ret = WGLEW_NV_DX_interop;
+ continue;
+ }
+#endif
+#ifdef WGL_NV_DX_interop2
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"DX_interop2", 11))
+ {
+ ret = WGLEW_NV_DX_interop2;
+ continue;
+ }
+#endif
+#ifdef WGL_NV_copy_image
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"copy_image", 10))
+ {
+ ret = WGLEW_NV_copy_image;
+ continue;
+ }
+#endif
+#ifdef WGL_NV_float_buffer
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"float_buffer", 12))
+ {
+ ret = WGLEW_NV_float_buffer;
+ continue;
+ }
+#endif
+#ifdef WGL_NV_gpu_affinity
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"gpu_affinity", 12))
+ {
+ ret = WGLEW_NV_gpu_affinity;
+ continue;
+ }
+#endif
+#ifdef WGL_NV_multisample_coverage
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"multisample_coverage", 20))
+ {
+ ret = WGLEW_NV_multisample_coverage;
+ continue;
+ }
+#endif
+#ifdef WGL_NV_present_video
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"present_video", 13))
+ {
+ ret = WGLEW_NV_present_video;
+ continue;
+ }
+#endif
+#ifdef WGL_NV_render_depth_texture
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"render_depth_texture", 20))
+ {
+ ret = WGLEW_NV_render_depth_texture;
+ continue;
+ }
+#endif
+#ifdef WGL_NV_render_texture_rectangle
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"render_texture_rectangle", 24))
+ {
+ ret = WGLEW_NV_render_texture_rectangle;
+ continue;
+ }
+#endif
+#ifdef WGL_NV_swap_group
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"swap_group", 10))
+ {
+ ret = WGLEW_NV_swap_group;
+ continue;
+ }
+#endif
+#ifdef WGL_NV_vertex_array_range
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"vertex_array_range", 18))
+ {
+ ret = WGLEW_NV_vertex_array_range;
+ continue;
+ }
+#endif
+#ifdef WGL_NV_video_capture
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"video_capture", 13))
+ {
+ ret = WGLEW_NV_video_capture;
+ continue;
+ }
+#endif
+#ifdef WGL_NV_video_output
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"video_output", 12))
+ {
+ ret = WGLEW_NV_video_output;
+ continue;
+ }
+#endif
+ }
+ if (_glewStrSame2(&pos, &len, (const GLubyte*)"OML_", 4))
+ {
+#ifdef WGL_OML_sync_control
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"sync_control", 12))
+ {
+ ret = WGLEW_OML_sync_control;
+ continue;
+ }
+#endif
+ }
+ }
+ ret = (len == 0);
+ }
+ return ret;
+}
+
+#elif !defined(__APPLE__) || defined(GLEW_APPLE_GLX)
+
+#if defined(GLEW_MX)
+GLboolean glxewContextIsSupported (const GLXEWContext* ctx, const char* name)
+#else
+GLboolean glxewIsSupported (const char* name)
+#endif
+{
+ GLubyte* pos = (GLubyte*)name;
+ GLuint len = _glewStrLen(pos);
+ GLboolean ret = GL_TRUE;
+ while (ret && len > 0)
+ {
+ if(_glewStrSame1(&pos, &len, (const GLubyte*)"GLX_", 4))
+ {
+ if (_glewStrSame2(&pos, &len, (const GLubyte*)"3DFX_", 5))
+ {
+#ifdef GLX_3DFX_multisample
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"multisample", 11))
+ {
+ ret = GLXEW_3DFX_multisample;
+ continue;
+ }
+#endif
+ }
+ if (_glewStrSame2(&pos, &len, (const GLubyte*)"AMD_", 4))
+ {
+#ifdef GLX_AMD_gpu_association
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"gpu_association", 15))
+ {
+ ret = GLXEW_AMD_gpu_association;
+ continue;
+ }
+#endif
+ }
+ if (_glewStrSame2(&pos, &len, (const GLubyte*)"ARB_", 4))
+ {
+#ifdef GLX_ARB_create_context
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"create_context", 14))
+ {
+ ret = GLXEW_ARB_create_context;
+ continue;
+ }
+#endif
+#ifdef GLX_ARB_create_context_profile
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"create_context_profile", 22))
+ {
+ ret = GLXEW_ARB_create_context_profile;
+ continue;
+ }
+#endif
+#ifdef GLX_ARB_create_context_robustness
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"create_context_robustness", 25))
+ {
+ ret = GLXEW_ARB_create_context_robustness;
+ continue;
+ }
+#endif
+#ifdef GLX_ARB_fbconfig_float
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"fbconfig_float", 14))
+ {
+ ret = GLXEW_ARB_fbconfig_float;
+ continue;
+ }
+#endif
+#ifdef GLX_ARB_framebuffer_sRGB
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"framebuffer_sRGB", 16))
+ {
+ ret = GLXEW_ARB_framebuffer_sRGB;
+ continue;
+ }
+#endif
+#ifdef GLX_ARB_get_proc_address
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"get_proc_address", 16))
+ {
+ ret = GLXEW_ARB_get_proc_address;
+ continue;
+ }
+#endif
+#ifdef GLX_ARB_multisample
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"multisample", 11))
+ {
+ ret = GLXEW_ARB_multisample;
+ continue;
+ }
+#endif
+#ifdef GLX_ARB_robustness_application_isolation
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"robustness_application_isolation", 32))
+ {
+ ret = GLXEW_ARB_robustness_application_isolation;
+ continue;
+ }
+#endif
+#ifdef GLX_ARB_robustness_share_group_isolation
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"robustness_share_group_isolation", 32))
+ {
+ ret = GLXEW_ARB_robustness_share_group_isolation;
+ continue;
+ }
+#endif
+#ifdef GLX_ARB_vertex_buffer_object
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"vertex_buffer_object", 20))
+ {
+ ret = GLXEW_ARB_vertex_buffer_object;
+ continue;
+ }
+#endif
+ }
+ if (_glewStrSame2(&pos, &len, (const GLubyte*)"ATI_", 4))
+ {
+#ifdef GLX_ATI_pixel_format_float
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"pixel_format_float", 18))
+ {
+ ret = GLXEW_ATI_pixel_format_float;
+ continue;
+ }
+#endif
+#ifdef GLX_ATI_render_texture
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"render_texture", 14))
+ {
+ ret = GLXEW_ATI_render_texture;
+ continue;
+ }
+#endif
+ }
+ if (_glewStrSame2(&pos, &len, (const GLubyte*)"EXT_", 4))
+ {
+#ifdef GLX_EXT_buffer_age
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"buffer_age", 10))
+ {
+ ret = GLXEW_EXT_buffer_age;
+ continue;
+ }
+#endif
+#ifdef GLX_EXT_create_context_es2_profile
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"create_context_es2_profile", 26))
+ {
+ ret = GLXEW_EXT_create_context_es2_profile;
+ continue;
+ }
+#endif
+#ifdef GLX_EXT_create_context_es_profile
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"create_context_es_profile", 25))
+ {
+ ret = GLXEW_EXT_create_context_es_profile;
+ continue;
+ }
+#endif
+#ifdef GLX_EXT_fbconfig_packed_float
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"fbconfig_packed_float", 21))
+ {
+ ret = GLXEW_EXT_fbconfig_packed_float;
+ continue;
+ }
+#endif
+#ifdef GLX_EXT_framebuffer_sRGB
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"framebuffer_sRGB", 16))
+ {
+ ret = GLXEW_EXT_framebuffer_sRGB;
+ continue;
+ }
+#endif
+#ifdef GLX_EXT_import_context
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"import_context", 14))
+ {
+ ret = GLXEW_EXT_import_context;
+ continue;
+ }
+#endif
+#ifdef GLX_EXT_scene_marker
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"scene_marker", 12))
+ {
+ ret = GLXEW_EXT_scene_marker;
+ continue;
+ }
+#endif
+#ifdef GLX_EXT_swap_control
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"swap_control", 12))
+ {
+ ret = GLXEW_EXT_swap_control;
+ continue;
+ }
+#endif
+#ifdef GLX_EXT_swap_control_tear
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"swap_control_tear", 17))
+ {
+ ret = GLXEW_EXT_swap_control_tear;
+ continue;
+ }
+#endif
+#ifdef GLX_EXT_texture_from_pixmap
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_from_pixmap", 19))
+ {
+ ret = GLXEW_EXT_texture_from_pixmap;
+ continue;
+ }
+#endif
+#ifdef GLX_EXT_visual_info
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"visual_info", 11))
+ {
+ ret = GLXEW_EXT_visual_info;
+ continue;
+ }
+#endif
+#ifdef GLX_EXT_visual_rating
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"visual_rating", 13))
+ {
+ ret = GLXEW_EXT_visual_rating;
+ continue;
+ }
+#endif
+ }
+ if (_glewStrSame2(&pos, &len, (const GLubyte*)"INTEL_", 6))
+ {
+#ifdef GLX_INTEL_swap_event
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"swap_event", 10))
+ {
+ ret = GLXEW_INTEL_swap_event;
+ continue;
+ }
+#endif
+ }
+ if (_glewStrSame2(&pos, &len, (const GLubyte*)"MESA_", 5))
+ {
+#ifdef GLX_MESA_agp_offset
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"agp_offset", 10))
+ {
+ ret = GLXEW_MESA_agp_offset;
+ continue;
+ }
+#endif
+#ifdef GLX_MESA_copy_sub_buffer
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"copy_sub_buffer", 15))
+ {
+ ret = GLXEW_MESA_copy_sub_buffer;
+ continue;
+ }
+#endif
+#ifdef GLX_MESA_pixmap_colormap
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"pixmap_colormap", 15))
+ {
+ ret = GLXEW_MESA_pixmap_colormap;
+ continue;
+ }
+#endif
+#ifdef GLX_MESA_release_buffers
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"release_buffers", 15))
+ {
+ ret = GLXEW_MESA_release_buffers;
+ continue;
+ }
+#endif
+#ifdef GLX_MESA_set_3dfx_mode
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"set_3dfx_mode", 13))
+ {
+ ret = GLXEW_MESA_set_3dfx_mode;
+ continue;
+ }
+#endif
+#ifdef GLX_MESA_swap_control
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"swap_control", 12))
+ {
+ ret = GLXEW_MESA_swap_control;
+ continue;
+ }
+#endif
+ }
+ if (_glewStrSame2(&pos, &len, (const GLubyte*)"NV_", 3))
+ {
+#ifdef GLX_NV_copy_image
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"copy_image", 10))
+ {
+ ret = GLXEW_NV_copy_image;
+ continue;
+ }
+#endif
+#ifdef GLX_NV_float_buffer
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"float_buffer", 12))
+ {
+ ret = GLXEW_NV_float_buffer;
+ continue;
+ }
+#endif
+#ifdef GLX_NV_multisample_coverage
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"multisample_coverage", 20))
+ {
+ ret = GLXEW_NV_multisample_coverage;
+ continue;
+ }
+#endif
+#ifdef GLX_NV_present_video
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"present_video", 13))
+ {
+ ret = GLXEW_NV_present_video;
+ continue;
+ }
+#endif
+#ifdef GLX_NV_swap_group
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"swap_group", 10))
+ {
+ ret = GLXEW_NV_swap_group;
+ continue;
+ }
+#endif
+#ifdef GLX_NV_vertex_array_range
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"vertex_array_range", 18))
+ {
+ ret = GLXEW_NV_vertex_array_range;
+ continue;
+ }
+#endif
+#ifdef GLX_NV_video_capture
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"video_capture", 13))
+ {
+ ret = GLXEW_NV_video_capture;
+ continue;
+ }
+#endif
+#ifdef GLX_NV_video_output
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"video_output", 12))
+ {
+ ret = GLXEW_NV_video_output;
+ continue;
+ }
+#endif
+ }
+ if (_glewStrSame2(&pos, &len, (const GLubyte*)"OML_", 4))
+ {
+#ifdef GLX_OML_swap_method
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"swap_method", 11))
+ {
+ ret = GLXEW_OML_swap_method;
+ continue;
+ }
+#endif
+#ifdef GLX_OML_sync_control
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"sync_control", 12))
+ {
+ ret = GLXEW_OML_sync_control;
+ continue;
+ }
+#endif
+ }
+ if (_glewStrSame2(&pos, &len, (const GLubyte*)"SGIS_", 5))
+ {
+#ifdef GLX_SGIS_blended_overlay
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"blended_overlay", 15))
+ {
+ ret = GLXEW_SGIS_blended_overlay;
+ continue;
+ }
+#endif
+#ifdef GLX_SGIS_color_range
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"color_range", 11))
+ {
+ ret = GLXEW_SGIS_color_range;
+ continue;
+ }
+#endif
+#ifdef GLX_SGIS_multisample
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"multisample", 11))
+ {
+ ret = GLXEW_SGIS_multisample;
+ continue;
+ }
+#endif
+#ifdef GLX_SGIS_shared_multisample
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"shared_multisample", 18))
+ {
+ ret = GLXEW_SGIS_shared_multisample;
+ continue;
+ }
+#endif
+ }
+ if (_glewStrSame2(&pos, &len, (const GLubyte*)"SGIX_", 5))
+ {
+#ifdef GLX_SGIX_fbconfig
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"fbconfig", 8))
+ {
+ ret = GLXEW_SGIX_fbconfig;
+ continue;
+ }
+#endif
+#ifdef GLX_SGIX_hyperpipe
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"hyperpipe", 9))
+ {
+ ret = GLXEW_SGIX_hyperpipe;
+ continue;
+ }
+#endif
+#ifdef GLX_SGIX_pbuffer
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"pbuffer", 7))
+ {
+ ret = GLXEW_SGIX_pbuffer;
+ continue;
+ }
+#endif
+#ifdef GLX_SGIX_swap_barrier
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"swap_barrier", 12))
+ {
+ ret = GLXEW_SGIX_swap_barrier;
+ continue;
+ }
+#endif
+#ifdef GLX_SGIX_swap_group
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"swap_group", 10))
+ {
+ ret = GLXEW_SGIX_swap_group;
+ continue;
+ }
+#endif
+#ifdef GLX_SGIX_video_resize
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"video_resize", 12))
+ {
+ ret = GLXEW_SGIX_video_resize;
+ continue;
+ }
+#endif
+#ifdef GLX_SGIX_visual_select_group
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"visual_select_group", 19))
+ {
+ ret = GLXEW_SGIX_visual_select_group;
+ continue;
+ }
+#endif
+ }
+ if (_glewStrSame2(&pos, &len, (const GLubyte*)"SGI_", 4))
+ {
+#ifdef GLX_SGI_cushion
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"cushion", 7))
+ {
+ ret = GLXEW_SGI_cushion;
+ continue;
+ }
+#endif
+#ifdef GLX_SGI_make_current_read
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"make_current_read", 17))
+ {
+ ret = GLXEW_SGI_make_current_read;
+ continue;
+ }
+#endif
+#ifdef GLX_SGI_swap_control
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"swap_control", 12))
+ {
+ ret = GLXEW_SGI_swap_control;
+ continue;
+ }
+#endif
+#ifdef GLX_SGI_video_sync
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"video_sync", 10))
+ {
+ ret = GLXEW_SGI_video_sync;
+ continue;
+ }
+#endif
+ }
+ if (_glewStrSame2(&pos, &len, (const GLubyte*)"SUN_", 4))
+ {
+#ifdef GLX_SUN_get_transparent_index
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"get_transparent_index", 21))
+ {
+ ret = GLXEW_SUN_get_transparent_index;
+ continue;
+ }
+#endif
+#ifdef GLX_SUN_video_resize
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"video_resize", 12))
+ {
+ ret = GLXEW_SUN_video_resize;
+ continue;
+ }
+#endif
+ }
+ if (_glewStrSame2(&pos, &len, (const GLubyte*)"VERSION_", 8))
+ {
+#ifdef GLX_VERSION_1_2
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"1_2", 3))
+ {
+ ret = GLXEW_VERSION_1_2;
+ continue;
+ }
+#endif
+#ifdef GLX_VERSION_1_3
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"1_3", 3))
+ {
+ ret = GLXEW_VERSION_1_3;
+ continue;
+ }
+#endif
+#ifdef GLX_VERSION_1_4
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"1_4", 3))
+ {
+ ret = GLXEW_VERSION_1_4;
+ continue;
+ }
+#endif
+ }
+ }
+ ret = (len == 0);
+ }
+ return ret;
+}
+
+#endif /* GLEW_USE_LIB_ES */
diff --git a/extern/glew/CMakeLists.txt b/extern/glew/CMakeLists.txt
index 34f6707398d..f264b3905be 100644
--- a/extern/glew/CMakeLists.txt
+++ b/extern/glew/CMakeLists.txt
@@ -45,6 +45,10 @@ set(SRC
include/GL/wglew.h
)
-add_definitions(-DGLEW_STATIC)
+add_definitions(${GL_DEFINITIONS})
+
+if(WITH_GLEW_MX)
+ add_definitions(-DGLEW_MX)
+endif()
blender_add_lib(extern_glew "${SRC}" "${INC}" "${INC_SYS}")
diff --git a/extern/glew/SConscript b/extern/glew/SConscript
index 84e2ba65cc2..a9687383a0c 100644
--- a/extern/glew/SConscript
+++ b/extern/glew/SConscript
@@ -6,7 +6,12 @@ Import('env')
sources = ['src/glew.c']
-defs = 'GLEW_STATIC'
-incs = 'include'
+defs = []
+defs += env['BF_GL_DEFINITIONS']
-env.BlenderLib ( 'extern_glew', sources, Split(incs), Split(defs), libtype=['extern','player'], priority=[50,230])
+if env['WITH_BF_GLEW_MX']:
+ defs += ['GLEW_MX']
+
+incs = ['include']
+
+env.BlenderLib ( 'extern_glew', sources, incs, defs, libtype=['extern','player'], priority=[50,230] )
diff --git a/extern/glew/include/GL/glew.h b/extern/glew/include/GL/glew.h
index cdf5b70db59..51a29ef8b91 100644
--- a/extern/glew/include/GL/glew.h
+++ b/extern/glew/include/GL/glew.h
@@ -83,6 +83,15 @@
#if defined(__gl_h_) || defined(__GL_H__) || defined(__X_GL_H)
#error gl.h included before glew.h
#endif
+#if defined(__gl2_h_)
+#error gl2.h included before glew.h
+#endif
+#if defined(__gltypes_h_)
+#error gltypes.h included before glew.h
+#endif
+#if defined(__REGAL_H__)
+#error Regal.h included before glew.h
+#endif
#if defined(__glext_h_) || defined(__GLEXT_H_)
#error glext.h included before glew.h
#endif
@@ -91,7 +100,10 @@
#endif
#define __gl_h_
+#define __gl2_h_
#define __GL_H__
+#define __gltypes_h_
+#define __REGAL_H__
#define __X_GL_H
#define __glext_h_
#define __GLEXT_H_
@@ -171,6 +183,10 @@ typedef _W64 int ptrdiff_t;
#define GLAPIENTRY APIENTRY
#endif
+#ifndef GLEWAPIENTRY
+#define GLEWAPIENTRY APIENTRY
+#endif
+
/*
* GLEW_STATIC is defined for static library.
* GLEW_BUILD is defined for building the DLL library.
@@ -231,10 +247,15 @@ typedef _W64 int ptrdiff_t;
#ifndef GLAPI
#define GLAPI extern
#endif
+
#ifndef GLAPIENTRY
#define GLAPIENTRY
#endif
+#ifndef GLEWAPIENTRY
+#define GLEWAPIENTRY
+#endif
+
#endif /* _WIN32 */
#ifdef __cplusplus
@@ -1211,7 +1232,6 @@ GLAPI void GLAPIENTRY glViewport (GLint x, GLint y, GLsizei width, GLsizei heigh
#define GL_UNSIGNED_SHORT_4_4_4_4_REV 0x8365
#define GL_UNSIGNED_SHORT_1_5_5_5_REV 0x8366
#define GL_UNSIGNED_INT_8_8_8_8_REV 0x8367
-#define GL_UNSIGNED_INT_2_10_10_10_REV 0x8368
#define GL_ALIASED_POINT_SIZE_RANGE 0x846D
#define GL_ALIASED_LINE_WIDTH_RANGE 0x846E
@@ -1491,8 +1511,8 @@ typedef void (GLAPIENTRY * PFNGLFOGCOORDDPROC) (GLdouble coord);
typedef void (GLAPIENTRY * PFNGLFOGCOORDDVPROC) (const GLdouble *coord);
typedef void (GLAPIENTRY * PFNGLFOGCOORDFPROC) (GLfloat coord);
typedef void (GLAPIENTRY * PFNGLFOGCOORDFVPROC) (const GLfloat *coord);
-typedef void (GLAPIENTRY * PFNGLMULTIDRAWARRAYSPROC) (GLenum mode, const GLint *first, const GLsizei *count, GLsizei primcount);
-typedef void (GLAPIENTRY * PFNGLMULTIDRAWELEMENTSPROC) (GLenum mode, const GLsizei *count, GLenum type, const GLvoid **indices, GLsizei primcount);
+typedef void (GLAPIENTRY * PFNGLMULTIDRAWARRAYSPROC) (GLenum mode, const GLint *first, const GLsizei *count, GLsizei drawcount);
+typedef void (GLAPIENTRY * PFNGLMULTIDRAWELEMENTSPROC) (GLenum mode, const GLsizei *count, GLenum type, const GLvoid **indices, GLsizei drawcount);
typedef void (GLAPIENTRY * PFNGLPOINTPARAMETERFPROC) (GLenum pname, GLfloat param);
typedef void (GLAPIENTRY * PFNGLPOINTPARAMETERFVPROC) (GLenum pname, const GLfloat *params);
typedef void (GLAPIENTRY * PFNGLPOINTPARAMETERIPROC) (GLenum pname, GLint param);
@@ -2036,8 +2056,6 @@ typedef void (GLAPIENTRY * PFNGLUNIFORMMATRIX4X3FVPROC) (GLint location, GLsizei
#define GL_CONTEXT_FLAGS 0x821E
#define GL_DEPTH_BUFFER 0x8223
#define GL_STENCIL_BUFFER 0x8224
-#define GL_COMPRESSED_RED 0x8225
-#define GL_COMPRESSED_RG 0x8226
#define GL_RGBA32F 0x8814
#define GL_RGB32F 0x8815
#define GL_RGBA16F 0x881A
@@ -2057,7 +2075,6 @@ typedef void (GLAPIENTRY * PFNGLUNIFORMMATRIX4X3FVPROC) (GLint location, GLsizei
#define GL_TEXTURE_LUMINANCE_TYPE 0x8C14
#define GL_TEXTURE_INTENSITY_TYPE 0x8C15
#define GL_TEXTURE_DEPTH_TYPE 0x8C16
-#define GL_UNSIGNED_NORMALIZED 0x8C17
#define GL_TEXTURE_1D_ARRAY 0x8C18
#define GL_PROXY_TEXTURE_1D_ARRAY 0x8C19
#define GL_TEXTURE_2D_ARRAY 0x8C1A
@@ -2345,12 +2362,6 @@ typedef void (GLAPIENTRY * PFNGLGETINTEGER64I_VPROC) (GLenum, GLuint, GLint64 *)
#define GL_VERSION_3_3 1
#define GL_VERTEX_ATTRIB_ARRAY_DIVISOR 0x88FE
-#define GL_ANY_SAMPLES_PASSED 0x8C2F
-#define GL_TEXTURE_SWIZZLE_R 0x8E42
-#define GL_TEXTURE_SWIZZLE_G 0x8E43
-#define GL_TEXTURE_SWIZZLE_B 0x8E44
-#define GL_TEXTURE_SWIZZLE_A 0x8E45
-#define GL_TEXTURE_SWIZZLE_RGBA 0x8E46
#define GL_RGB10_A2UI 0x906F
typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBDIVISORPROC) (GLuint index, GLuint divisor);
@@ -2366,13 +2377,8 @@ typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBDIVISORPROC) (GLuint index, GLuint d
#ifndef GL_VERSION_4_0
#define GL_VERSION_4_0 1
-#define GL_GEOMETRY_SHADER_INVOCATIONS 0x887F
#define GL_SAMPLE_SHADING 0x8C36
#define GL_MIN_SAMPLE_SHADING_VALUE 0x8C37
-#define GL_MAX_GEOMETRY_SHADER_INVOCATIONS 0x8E5A
-#define GL_MIN_FRAGMENT_INTERPOLATION_OFFSET 0x8E5B
-#define GL_MAX_FRAGMENT_INTERPOLATION_OFFSET 0x8E5C
-#define GL_FRAGMENT_INTERPOLATION_OFFSET_BITS 0x8E5D
#define GL_MIN_PROGRAM_TEXTURE_GATHER_OFFSET 0x8E5E
#define GL_MAX_PROGRAM_TEXTURE_GATHER_OFFSET 0x8E5F
#define GL_MAX_PROGRAM_TEXTURE_GATHER_COMPONENTS 0x8F9F
@@ -2414,10 +2420,38 @@ typedef void (GLAPIENTRY * PFNGLMINSAMPLESHADINGPROC) (GLclampf value);
#ifndef GL_VERSION_4_2
#define GL_VERSION_4_2 1
+#define GL_COMPRESSED_RGBA_BPTC_UNORM 0x8E8C
+#define GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM 0x8E8D
+#define GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT 0x8E8E
+#define GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT 0x8E8F
+
#define GLEW_VERSION_4_2 GLEW_GET_VAR(__GLEW_VERSION_4_2)
#endif /* GL_VERSION_4_2 */
+/* ----------------------------- GL_VERSION_4_3 ---------------------------- */
+
+#ifndef GL_VERSION_4_3
+#define GL_VERSION_4_3 1
+
+#define GL_NUM_SHADING_LANGUAGE_VERSIONS 0x82E9
+#define GL_VERTEX_ATTRIB_ARRAY_LONG 0x874E
+
+#define GLEW_VERSION_4_3 GLEW_GET_VAR(__GLEW_VERSION_4_3)
+
+#endif /* GL_VERSION_4_3 */
+
+/* ----------------------------- GL_VERSION_4_4 ---------------------------- */
+
+#ifndef GL_VERSION_4_4
+#define GL_VERSION_4_4 1
+
+#define GL_MAX_VERTEX_ATTRIB_STRIDE 0x82E5
+
+#define GLEW_VERSION_4_4 GLEW_GET_VAR(__GLEW_VERSION_4_4)
+
+#endif /* GL_VERSION_4_4 */
+
/* -------------------------- GL_3DFX_multisample -------------------------- */
#ifndef GL_3DFX_multisample
@@ -2500,10 +2534,10 @@ typedef void (GLAPIENTRY * PFNGLTBUFFERMASK3DFXPROC) (GLuint mask);
typedef void (APIENTRY *GLDEBUGPROCAMD)(GLuint id, GLenum category, GLenum severity, GLsizei length, const GLchar* message, GLvoid* userParam);
-typedef void (GLAPIENTRY * PFNGLDEBUGMESSAGECALLBACKAMDPROC) (GLDEBUGPROCAMD callback, void* userParam);
+typedef void (GLAPIENTRY * PFNGLDEBUGMESSAGECALLBACKAMDPROC) (GLDEBUGPROCAMD callback, GLvoid *userParam);
typedef void (GLAPIENTRY * PFNGLDEBUGMESSAGEENABLEAMDPROC) (GLenum category, GLenum severity, GLsizei count, const GLuint* ids, GLboolean enabled);
-typedef void (GLAPIENTRY * PFNGLDEBUGMESSAGEINSERTAMDPROC) (GLenum category, GLenum severity, GLuint id, GLsizei length, const char* buf);
-typedef GLuint (GLAPIENTRY * PFNGLGETDEBUGMESSAGELOGAMDPROC) (GLuint count, GLsizei bufsize, GLenum* categories, GLuint* severities, GLuint* ids, GLsizei* lengths, char* message);
+typedef void (GLAPIENTRY * PFNGLDEBUGMESSAGEINSERTAMDPROC) (GLenum category, GLenum severity, GLuint id, GLsizei length, const GLchar* buf);
+typedef GLuint (GLAPIENTRY * PFNGLGETDEBUGMESSAGELOGAMDPROC) (GLuint count, GLsizei bufsize, GLenum* categories, GLuint* severities, GLuint* ids, GLsizei* lengths, GLchar* message);
#define glDebugMessageCallbackAMD GLEW_GET_FUN(__glewDebugMessageCallbackAMD)
#define glDebugMessageEnableAMD GLEW_GET_FUN(__glewDebugMessageEnableAMD)
@@ -2545,13 +2579,36 @@ typedef void (GLAPIENTRY * PFNGLBLENDFUNCSEPARATEINDEXEDAMDPROC) (GLuint buf, GL
#endif /* GL_AMD_draw_buffers_blend */
+/* ---------------------- GL_AMD_interleaved_elements ---------------------- */
+
+#ifndef GL_AMD_interleaved_elements
+#define GL_AMD_interleaved_elements 1
+
+#define GL_RED 0x1903
+#define GL_GREEN 0x1904
+#define GL_BLUE 0x1905
+#define GL_ALPHA 0x1906
+#define GL_RG8UI 0x8238
+#define GL_RG16UI 0x823A
+#define GL_RGBA8UI 0x8D7C
+#define GL_VERTEX_ELEMENT_SWIZZLE_AMD 0x91A4
+#define GL_VERTEX_ID_SWIZZLE_AMD 0x91A5
+
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBPARAMETERIAMDPROC) (GLuint index, GLenum pname, GLint param);
+
+#define glVertexAttribParameteriAMD GLEW_GET_FUN(__glewVertexAttribParameteriAMD)
+
+#define GLEW_AMD_interleaved_elements GLEW_GET_VAR(__GLEW_AMD_interleaved_elements)
+
+#endif /* GL_AMD_interleaved_elements */
+
/* ----------------------- GL_AMD_multi_draw_indirect ---------------------- */
#ifndef GL_AMD_multi_draw_indirect
#define GL_AMD_multi_draw_indirect 1
-typedef void (GLAPIENTRY * PFNGLMULTIDRAWARRAYSINDIRECTAMDPROC) (GLenum mode, const void* indirect, GLsizei primcount, GLsizei stride);
-typedef void (GLAPIENTRY * PFNGLMULTIDRAWELEMENTSINDIRECTAMDPROC) (GLenum mode, GLenum type, const void* indirect, GLsizei primcount, GLsizei stride);
+typedef void (GLAPIENTRY * PFNGLMULTIDRAWARRAYSINDIRECTAMDPROC) (GLenum mode, const GLvoid *indirect, GLsizei primcount, GLsizei stride);
+typedef void (GLAPIENTRY * PFNGLMULTIDRAWELEMENTSINDIRECTAMDPROC) (GLenum mode, GLenum type, const GLvoid *indirect, GLsizei primcount, GLsizei stride);
#define glMultiDrawArraysIndirectAMD GLEW_GET_FUN(__glewMultiDrawArraysIndirectAMD)
#define glMultiDrawElementsIndirectAMD GLEW_GET_FUN(__glewMultiDrawElementsIndirectAMD)
@@ -2588,8 +2645,6 @@ typedef GLboolean (GLAPIENTRY * PFNGLISNAMEAMDPROC) (GLenum identifier, GLuint n
#ifndef GL_AMD_performance_monitor
#define GL_AMD_performance_monitor 1
-#define GL_UNSIGNED_INT 0x1405
-#define GL_FLOAT 0x1406
#define GL_COUNTER_TYPE_AMD 0x8BC0
#define GL_COUNTER_RANGE_AMD 0x8BC1
#define GL_UNSIGNED_INT64_AMD 0x8BC2
@@ -2603,10 +2658,10 @@ typedef void (GLAPIENTRY * PFNGLDELETEPERFMONITORSAMDPROC) (GLsizei n, GLuint* m
typedef void (GLAPIENTRY * PFNGLENDPERFMONITORAMDPROC) (GLuint monitor);
typedef void (GLAPIENTRY * PFNGLGENPERFMONITORSAMDPROC) (GLsizei n, GLuint* monitors);
typedef void (GLAPIENTRY * PFNGLGETPERFMONITORCOUNTERDATAAMDPROC) (GLuint monitor, GLenum pname, GLsizei dataSize, GLuint* data, GLint *bytesWritten);
-typedef void (GLAPIENTRY * PFNGLGETPERFMONITORCOUNTERINFOAMDPROC) (GLuint group, GLuint counter, GLenum pname, void* data);
-typedef void (GLAPIENTRY * PFNGLGETPERFMONITORCOUNTERSTRINGAMDPROC) (GLuint group, GLuint counter, GLsizei bufSize, GLsizei* length, char *counterString);
+typedef void (GLAPIENTRY * PFNGLGETPERFMONITORCOUNTERINFOAMDPROC) (GLuint group, GLuint counter, GLenum pname, GLvoid *data);
+typedef void (GLAPIENTRY * PFNGLGETPERFMONITORCOUNTERSTRINGAMDPROC) (GLuint group, GLuint counter, GLsizei bufSize, GLsizei* length, GLchar *counterString);
typedef void (GLAPIENTRY * PFNGLGETPERFMONITORCOUNTERSAMDPROC) (GLuint group, GLint* numCounters, GLint *maxActiveCounters, GLsizei countersSize, GLuint *counters);
-typedef void (GLAPIENTRY * PFNGLGETPERFMONITORGROUPSTRINGAMDPROC) (GLuint group, GLsizei bufSize, GLsizei* length, char *groupString);
+typedef void (GLAPIENTRY * PFNGLGETPERFMONITORGROUPSTRINGAMDPROC) (GLuint group, GLsizei bufSize, GLsizei* length, GLchar *groupString);
typedef void (GLAPIENTRY * PFNGLGETPERFMONITORGROUPSAMDPROC) (GLint* numGroups, GLsizei groupsSize, GLuint *groups);
typedef void (GLAPIENTRY * PFNGLSELECTPERFMONITORCOUNTERSAMDPROC) (GLuint monitor, GLboolean enable, GLuint group, GLint numCounters, GLuint* counterList);
@@ -2626,6 +2681,30 @@ typedef void (GLAPIENTRY * PFNGLSELECTPERFMONITORCOUNTERSAMDPROC) (GLuint monito
#endif /* GL_AMD_performance_monitor */
+/* -------------------------- GL_AMD_pinned_memory ------------------------- */
+
+#ifndef GL_AMD_pinned_memory
+#define GL_AMD_pinned_memory 1
+
+#define GL_EXTERNAL_VIRTUAL_MEMORY_BUFFER_AMD 0x9160
+
+#define GLEW_AMD_pinned_memory GLEW_GET_VAR(__GLEW_AMD_pinned_memory)
+
+#endif /* GL_AMD_pinned_memory */
+
+/* ----------------------- GL_AMD_query_buffer_object ---------------------- */
+
+#ifndef GL_AMD_query_buffer_object
+#define GL_AMD_query_buffer_object 1
+
+#define GL_QUERY_BUFFER_AMD 0x9192
+#define GL_QUERY_BUFFER_BINDING_AMD 0x9193
+#define GL_QUERY_RESULT_NO_WAIT_AMD 0x9194
+
+#define GLEW_AMD_query_buffer_object GLEW_GET_VAR(__GLEW_AMD_query_buffer_object)
+
+#endif /* GL_AMD_query_buffer_object */
+
/* ------------------------ GL_AMD_sample_positions ------------------------ */
#ifndef GL_AMD_sample_positions
@@ -2661,6 +2740,58 @@ typedef void (GLAPIENTRY * PFNGLSETMULTISAMPLEFVAMDPROC) (GLenum pname, GLuint i
#endif /* GL_AMD_shader_stencil_export */
+/* ---------------------- GL_AMD_shader_trinary_minmax --------------------- */
+
+#ifndef GL_AMD_shader_trinary_minmax
+#define GL_AMD_shader_trinary_minmax 1
+
+#define GLEW_AMD_shader_trinary_minmax GLEW_GET_VAR(__GLEW_AMD_shader_trinary_minmax)
+
+#endif /* GL_AMD_shader_trinary_minmax */
+
+/* ------------------------- GL_AMD_sparse_texture ------------------------- */
+
+#ifndef GL_AMD_sparse_texture
+#define GL_AMD_sparse_texture 1
+
+#define GL_TEXTURE_STORAGE_SPARSE_BIT_AMD 0x00000001
+#define GL_VIRTUAL_PAGE_SIZE_X_AMD 0x9195
+#define GL_VIRTUAL_PAGE_SIZE_Y_AMD 0x9196
+#define GL_VIRTUAL_PAGE_SIZE_Z_AMD 0x9197
+#define GL_MAX_SPARSE_TEXTURE_SIZE_AMD 0x9198
+#define GL_MAX_SPARSE_3D_TEXTURE_SIZE_AMD 0x9199
+#define GL_MAX_SPARSE_ARRAY_TEXTURE_LAYERS 0x919A
+#define GL_MIN_SPARSE_LEVEL_AMD 0x919B
+#define GL_MIN_LOD_WARNING_AMD 0x919C
+
+typedef void (GLAPIENTRY * PFNGLTEXSTORAGESPARSEAMDPROC) (GLenum target, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLsizei layers, GLbitfield flags);
+typedef void (GLAPIENTRY * PFNGLTEXTURESTORAGESPARSEAMDPROC) (GLuint texture, GLenum target, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLsizei layers, GLbitfield flags);
+
+#define glTexStorageSparseAMD GLEW_GET_FUN(__glewTexStorageSparseAMD)
+#define glTextureStorageSparseAMD GLEW_GET_FUN(__glewTextureStorageSparseAMD)
+
+#define GLEW_AMD_sparse_texture GLEW_GET_VAR(__GLEW_AMD_sparse_texture)
+
+#endif /* GL_AMD_sparse_texture */
+
+/* ------------------- GL_AMD_stencil_operation_extended ------------------- */
+
+#ifndef GL_AMD_stencil_operation_extended
+#define GL_AMD_stencil_operation_extended 1
+
+#define GL_SET_AMD 0x874A
+#define GL_REPLACE_VALUE_AMD 0x874B
+#define GL_STENCIL_OP_VALUE_AMD 0x874C
+#define GL_STENCIL_BACK_OP_VALUE_AMD 0x874D
+
+typedef void (GLAPIENTRY * PFNGLSTENCILOPVALUEAMDPROC) (GLenum face, GLuint value);
+
+#define glStencilOpValueAMD GLEW_GET_FUN(__glewStencilOpValueAMD)
+
+#define GLEW_AMD_stencil_operation_extended GLEW_GET_VAR(__GLEW_AMD_stencil_operation_extended)
+
+#endif /* GL_AMD_stencil_operation_extended */
+
/* ------------------------ GL_AMD_texture_texture4 ------------------------ */
#ifndef GL_AMD_texture_texture4
@@ -2679,6 +2810,15 @@ typedef void (GLAPIENTRY * PFNGLSETMULTISAMPLEFVAMDPROC) (GLenum pname, GLuint i
#endif /* GL_AMD_transform_feedback3_lines_triangles */
+/* ----------------------- GL_AMD_vertex_shader_layer ---------------------- */
+
+#ifndef GL_AMD_vertex_shader_layer
+#define GL_AMD_vertex_shader_layer 1
+
+#define GLEW_AMD_vertex_shader_layer GLEW_GET_VAR(__GLEW_AMD_vertex_shader_layer)
+
+#endif /* GL_AMD_vertex_shader_layer */
+
/* -------------------- GL_AMD_vertex_shader_tessellator ------------------- */
#ifndef GL_AMD_vertex_shader_tessellator
@@ -2702,6 +2842,209 @@ typedef void (GLAPIENTRY * PFNGLTESSELLATIONMODEAMDPROC) (GLenum mode);
#endif /* GL_AMD_vertex_shader_tessellator */
+/* ------------------ GL_AMD_vertex_shader_viewport_index ------------------ */
+
+#ifndef GL_AMD_vertex_shader_viewport_index
+#define GL_AMD_vertex_shader_viewport_index 1
+
+#define GLEW_AMD_vertex_shader_viewport_index GLEW_GET_VAR(__GLEW_AMD_vertex_shader_viewport_index)
+
+#endif /* GL_AMD_vertex_shader_viewport_index */
+
+/* ------------------------- GL_ANGLE_depth_texture ------------------------ */
+
+#ifndef GL_ANGLE_depth_texture
+#define GL_ANGLE_depth_texture 1
+
+#define GLEW_ANGLE_depth_texture GLEW_GET_VAR(__GLEW_ANGLE_depth_texture)
+
+#endif /* GL_ANGLE_depth_texture */
+
+/* ----------------------- GL_ANGLE_framebuffer_blit ----------------------- */
+
+#ifndef GL_ANGLE_framebuffer_blit
+#define GL_ANGLE_framebuffer_blit 1
+
+#define GL_DRAW_FRAMEBUFFER_BINDING_ANGLE 0x8CA6
+#define GL_READ_FRAMEBUFFER_ANGLE 0x8CA8
+#define GL_DRAW_FRAMEBUFFER_ANGLE 0x8CA9
+#define GL_READ_FRAMEBUFFER_BINDING_ANGLE 0x8CAA
+
+typedef void (GLAPIENTRY * PFNGLBLITFRAMEBUFFERANGLEPROC) (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter);
+
+#define glBlitFramebufferANGLE GLEW_GET_FUN(__glewBlitFramebufferANGLE)
+
+#define GLEW_ANGLE_framebuffer_blit GLEW_GET_VAR(__GLEW_ANGLE_framebuffer_blit)
+
+#endif /* GL_ANGLE_framebuffer_blit */
+
+/* -------------------- GL_ANGLE_framebuffer_multisample ------------------- */
+
+#ifndef GL_ANGLE_framebuffer_multisample
+#define GL_ANGLE_framebuffer_multisample 1
+
+#define GL_RENDERBUFFER_SAMPLES_ANGLE 0x8CAB
+#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE 0x8D56
+#define GL_MAX_SAMPLES_ANGLE 0x8D57
+
+typedef void (GLAPIENTRY * PFNGLRENDERBUFFERSTORAGEMULTISAMPLEANGLEPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
+
+#define glRenderbufferStorageMultisampleANGLE GLEW_GET_FUN(__glewRenderbufferStorageMultisampleANGLE)
+
+#define GLEW_ANGLE_framebuffer_multisample GLEW_GET_VAR(__GLEW_ANGLE_framebuffer_multisample)
+
+#endif /* GL_ANGLE_framebuffer_multisample */
+
+/* ----------------------- GL_ANGLE_instanced_arrays ----------------------- */
+
+#ifndef GL_ANGLE_instanced_arrays
+#define GL_ANGLE_instanced_arrays 1
+
+#define GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE 0x88FE
+
+typedef void (GLAPIENTRY * PFNGLDRAWARRAYSINSTANCEDANGLEPROC) (GLenum mode, GLint first, GLsizei count, GLsizei primcount);
+typedef void (GLAPIENTRY * PFNGLDRAWELEMENTSINSTANCEDANGLEPROC) (GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLsizei primcount);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBDIVISORANGLEPROC) (GLuint index, GLuint divisor);
+
+#define glDrawArraysInstancedANGLE GLEW_GET_FUN(__glewDrawArraysInstancedANGLE)
+#define glDrawElementsInstancedANGLE GLEW_GET_FUN(__glewDrawElementsInstancedANGLE)
+#define glVertexAttribDivisorANGLE GLEW_GET_FUN(__glewVertexAttribDivisorANGLE)
+
+#define GLEW_ANGLE_instanced_arrays GLEW_GET_VAR(__GLEW_ANGLE_instanced_arrays)
+
+#endif /* GL_ANGLE_instanced_arrays */
+
+/* -------------------- GL_ANGLE_pack_reverse_row_order -------------------- */
+
+#ifndef GL_ANGLE_pack_reverse_row_order
+#define GL_ANGLE_pack_reverse_row_order 1
+
+#define GL_PACK_REVERSE_ROW_ORDER_ANGLE 0x93A4
+
+#define GLEW_ANGLE_pack_reverse_row_order GLEW_GET_VAR(__GLEW_ANGLE_pack_reverse_row_order)
+
+#endif /* GL_ANGLE_pack_reverse_row_order */
+
+/* ------------------------ GL_ANGLE_program_binary ------------------------ */
+
+#ifndef GL_ANGLE_program_binary
+#define GL_ANGLE_program_binary 1
+
+#define GL_PROGRAM_BINARY_ANGLE 0x93A6
+
+#define GLEW_ANGLE_program_binary GLEW_GET_VAR(__GLEW_ANGLE_program_binary)
+
+#endif /* GL_ANGLE_program_binary */
+
+/* ------------------- GL_ANGLE_texture_compression_dxt1 ------------------- */
+
+#ifndef GL_ANGLE_texture_compression_dxt1
+#define GL_ANGLE_texture_compression_dxt1 1
+
+#define GL_COMPRESSED_RGB_S3TC_DXT1_ANGLE 0x83F0
+#define GL_COMPRESSED_RGBA_S3TC_DXT1_ANGLE 0x83F1
+#define GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE 0x83F2
+#define GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE 0x83F3
+
+#define GLEW_ANGLE_texture_compression_dxt1 GLEW_GET_VAR(__GLEW_ANGLE_texture_compression_dxt1)
+
+#endif /* GL_ANGLE_texture_compression_dxt1 */
+
+/* ------------------- GL_ANGLE_texture_compression_dxt3 ------------------- */
+
+#ifndef GL_ANGLE_texture_compression_dxt3
+#define GL_ANGLE_texture_compression_dxt3 1
+
+#define GL_COMPRESSED_RGB_S3TC_DXT1_ANGLE 0x83F0
+#define GL_COMPRESSED_RGBA_S3TC_DXT1_ANGLE 0x83F1
+#define GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE 0x83F2
+#define GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE 0x83F3
+
+#define GLEW_ANGLE_texture_compression_dxt3 GLEW_GET_VAR(__GLEW_ANGLE_texture_compression_dxt3)
+
+#endif /* GL_ANGLE_texture_compression_dxt3 */
+
+/* ------------------- GL_ANGLE_texture_compression_dxt5 ------------------- */
+
+#ifndef GL_ANGLE_texture_compression_dxt5
+#define GL_ANGLE_texture_compression_dxt5 1
+
+#define GL_COMPRESSED_RGB_S3TC_DXT1_ANGLE 0x83F0
+#define GL_COMPRESSED_RGBA_S3TC_DXT1_ANGLE 0x83F1
+#define GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE 0x83F2
+#define GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE 0x83F3
+
+#define GLEW_ANGLE_texture_compression_dxt5 GLEW_GET_VAR(__GLEW_ANGLE_texture_compression_dxt5)
+
+#endif /* GL_ANGLE_texture_compression_dxt5 */
+
+/* ------------------------- GL_ANGLE_texture_usage ------------------------ */
+
+#ifndef GL_ANGLE_texture_usage
+#define GL_ANGLE_texture_usage 1
+
+#define GL_TEXTURE_USAGE_ANGLE 0x93A2
+#define GL_FRAMEBUFFER_ATTACHMENT_ANGLE 0x93A3
+
+#define GLEW_ANGLE_texture_usage GLEW_GET_VAR(__GLEW_ANGLE_texture_usage)
+
+#endif /* GL_ANGLE_texture_usage */
+
+/* -------------------------- GL_ANGLE_timer_query ------------------------- */
+
+#ifndef GL_ANGLE_timer_query
+#define GL_ANGLE_timer_query 1
+
+#define GL_QUERY_COUNTER_BITS_ANGLE 0x8864
+#define GL_CURRENT_QUERY_ANGLE 0x8865
+#define GL_QUERY_RESULT_ANGLE 0x8866
+#define GL_QUERY_RESULT_AVAILABLE_ANGLE 0x8867
+#define GL_TIME_ELAPSED_ANGLE 0x88BF
+#define GL_TIMESTAMP_ANGLE 0x8E28
+
+typedef void (GLAPIENTRY * PFNGLBEGINQUERYANGLEPROC) (GLenum target, GLuint id);
+typedef void (GLAPIENTRY * PFNGLDELETEQUERIESANGLEPROC) (GLsizei n, const GLuint* ids);
+typedef void (GLAPIENTRY * PFNGLENDQUERYANGLEPROC) (GLenum target);
+typedef void (GLAPIENTRY * PFNGLGENQUERIESANGLEPROC) (GLsizei n, GLuint* ids);
+typedef void (GLAPIENTRY * PFNGLGETQUERYOBJECTI64VANGLEPROC) (GLuint id, GLenum pname, GLint64* params);
+typedef void (GLAPIENTRY * PFNGLGETQUERYOBJECTIVANGLEPROC) (GLuint id, GLenum pname, GLint* params);
+typedef void (GLAPIENTRY * PFNGLGETQUERYOBJECTUI64VANGLEPROC) (GLuint id, GLenum pname, GLuint64* params);
+typedef void (GLAPIENTRY * PFNGLGETQUERYOBJECTUIVANGLEPROC) (GLuint id, GLenum pname, GLuint* params);
+typedef void (GLAPIENTRY * PFNGLGETQUERYIVANGLEPROC) (GLenum target, GLenum pname, GLint* params);
+typedef GLboolean (GLAPIENTRY * PFNGLISQUERYANGLEPROC) (GLuint id);
+typedef void (GLAPIENTRY * PFNGLQUERYCOUNTERANGLEPROC) (GLuint id, GLenum target);
+
+#define glBeginQueryANGLE GLEW_GET_FUN(__glewBeginQueryANGLE)
+#define glDeleteQueriesANGLE GLEW_GET_FUN(__glewDeleteQueriesANGLE)
+#define glEndQueryANGLE GLEW_GET_FUN(__glewEndQueryANGLE)
+#define glGenQueriesANGLE GLEW_GET_FUN(__glewGenQueriesANGLE)
+#define glGetQueryObjecti64vANGLE GLEW_GET_FUN(__glewGetQueryObjecti64vANGLE)
+#define glGetQueryObjectivANGLE GLEW_GET_FUN(__glewGetQueryObjectivANGLE)
+#define glGetQueryObjectui64vANGLE GLEW_GET_FUN(__glewGetQueryObjectui64vANGLE)
+#define glGetQueryObjectuivANGLE GLEW_GET_FUN(__glewGetQueryObjectuivANGLE)
+#define glGetQueryivANGLE GLEW_GET_FUN(__glewGetQueryivANGLE)
+#define glIsQueryANGLE GLEW_GET_FUN(__glewIsQueryANGLE)
+#define glQueryCounterANGLE GLEW_GET_FUN(__glewQueryCounterANGLE)
+
+#define GLEW_ANGLE_timer_query GLEW_GET_VAR(__GLEW_ANGLE_timer_query)
+
+#endif /* GL_ANGLE_timer_query */
+
+/* ------------------- GL_ANGLE_translated_shader_source ------------------- */
+
+#ifndef GL_ANGLE_translated_shader_source
+#define GL_ANGLE_translated_shader_source 1
+
+#define GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE 0x93A0
+
+typedef void (GLAPIENTRY * PFNGLGETTRANSLATEDSHADERSOURCEANGLEPROC) (GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* source);
+
+#define glGetTranslatedShaderSourceANGLE GLEW_GET_FUN(__glewGetTranslatedShaderSourceANGLE)
+
+#define GLEW_ANGLE_translated_shader_source GLEW_GET_VAR(__GLEW_ANGLE_translated_shader_source)
+
+#endif /* GL_ANGLE_translated_shader_source */
+
/* ----------------------- GL_APPLE_aux_depth_stencil ---------------------- */
#ifndef GL_APPLE_aux_depth_stencil
@@ -2735,7 +3078,7 @@ typedef void (GLAPIENTRY * PFNGLTESSELLATIONMODEAMDPROC) (GLenum mode);
typedef void (GLAPIENTRY * PFNGLDRAWELEMENTARRAYAPPLEPROC) (GLenum mode, GLint first, GLsizei count);
typedef void (GLAPIENTRY * PFNGLDRAWRANGEELEMENTARRAYAPPLEPROC) (GLenum mode, GLuint start, GLuint end, GLint first, GLsizei count);
-typedef void (GLAPIENTRY * PFNGLELEMENTPOINTERAPPLEPROC) (GLenum type, const void* pointer);
+typedef void (GLAPIENTRY * PFNGLELEMENTPOINTERAPPLEPROC) (GLenum type, const GLvoid *pointer);
typedef void (GLAPIENTRY * PFNGLMULTIDRAWELEMENTARRAYAPPLEPROC) (GLenum mode, const GLint* first, const GLsizei *count, GLsizei primcount);
typedef void (GLAPIENTRY * PFNGLMULTIDRAWRANGEELEMENTARRAYAPPLEPROC) (GLenum mode, GLuint start, GLuint end, const GLint* first, const GLsizei *count, GLsizei primcount);
@@ -2960,9 +3303,9 @@ typedef GLboolean (GLAPIENTRY * PFNGLISVERTEXARRAYAPPLEPROC) (GLuint array);
#define GL_STORAGE_CACHED_APPLE 0x85BE
#define GL_STORAGE_SHARED_APPLE 0x85BF
-typedef void (GLAPIENTRY * PFNGLFLUSHVERTEXARRAYRANGEAPPLEPROC) (GLsizei length, void* pointer);
+typedef void (GLAPIENTRY * PFNGLFLUSHVERTEXARRAYRANGEAPPLEPROC) (GLsizei length, GLvoid *pointer);
typedef void (GLAPIENTRY * PFNGLVERTEXARRAYPARAMETERIAPPLEPROC) (GLenum pname, GLint param);
-typedef void (GLAPIENTRY * PFNGLVERTEXARRAYRANGEAPPLEPROC) (GLsizei length, void* pointer);
+typedef void (GLAPIENTRY * PFNGLVERTEXARRAYRANGEAPPLEPROC) (GLsizei length, GLvoid *pointer);
#define glFlushVertexArrayRangeAPPLE GLEW_GET_FUN(__glewFlushVertexArrayRangeAPPLE)
#define glVertexArrayParameteriAPPLE GLEW_GET_FUN(__glewVertexArrayParameteriAPPLE)
@@ -3014,8 +3357,6 @@ typedef void (GLAPIENTRY * PFNGLMAPVERTEXATTRIB2FAPPLEPROC) (GLuint index, GLuin
#define GL_APPLE_ycbcr_422 1
#define GL_YCBCR_422_APPLE 0x85B9
-#define GL_UNSIGNED_SHORT_8_8_APPLE 0x85BA
-#define GL_UNSIGNED_SHORT_8_8_REV_APPLE 0x85BB
#define GLEW_APPLE_ycbcr_422 GLEW_GET_VAR(__GLEW_APPLE_ycbcr_422)
@@ -3029,6 +3370,7 @@ typedef void (GLAPIENTRY * PFNGLMAPVERTEXATTRIB2FAPPLEPROC) (GLuint index, GLuin
#define GL_FIXED 0x140C
#define GL_IMPLEMENTATION_COLOR_READ_TYPE 0x8B9A
#define GL_IMPLEMENTATION_COLOR_READ_FORMAT 0x8B9B
+#define GL_RGB565 0x8D62
#define GL_LOW_FLOAT 0x8DF0
#define GL_MEDIUM_FLOAT 0x8DF1
#define GL_HIGH_FLOAT 0x8DF2
@@ -3042,6 +3384,8 @@ typedef void (GLAPIENTRY * PFNGLMAPVERTEXATTRIB2FAPPLEPROC) (GLuint index, GLuin
#define GL_MAX_VARYING_VECTORS 0x8DFC
#define GL_MAX_FRAGMENT_UNIFORM_VECTORS 0x8DFD
+typedef int GLfixed;
+
typedef void (GLAPIENTRY * PFNGLCLEARDEPTHFPROC) (GLclampf d);
typedef void (GLAPIENTRY * PFNGLDEPTHRANGEFPROC) (GLclampf n, GLclampf f);
typedef void (GLAPIENTRY * PFNGLGETSHADERPRECISIONFORMATPROC) (GLenum shadertype, GLenum precisiontype, GLint* range, GLint *precision);
@@ -3058,14 +3402,47 @@ typedef void (GLAPIENTRY * PFNGLSHADERBINARYPROC) (GLsizei count, const GLuint*
#endif /* GL_ARB_ES2_compatibility */
+/* ------------------------ GL_ARB_ES3_compatibility ----------------------- */
+
+#ifndef GL_ARB_ES3_compatibility
+#define GL_ARB_ES3_compatibility 1
+
+#define GL_TEXTURE_IMMUTABLE_LEVELS 0x82DF
+#define GL_PRIMITIVE_RESTART_FIXED_INDEX 0x8D69
+#define GL_ANY_SAMPLES_PASSED_CONSERVATIVE 0x8D6A
+#define GL_MAX_ELEMENT_INDEX 0x8D6B
+#define GL_COMPRESSED_R11_EAC 0x9270
+#define GL_COMPRESSED_SIGNED_R11_EAC 0x9271
+#define GL_COMPRESSED_RG11_EAC 0x9272
+#define GL_COMPRESSED_SIGNED_RG11_EAC 0x9273
+#define GL_COMPRESSED_RGB8_ETC2 0x9274
+#define GL_COMPRESSED_SRGB8_ETC2 0x9275
+#define GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2 0x9276
+#define GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2 0x9277
+#define GL_COMPRESSED_RGBA8_ETC2_EAC 0x9278
+#define GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC 0x9279
+
+#define GLEW_ARB_ES3_compatibility GLEW_GET_VAR(__GLEW_ARB_ES3_compatibility)
+
+#endif /* GL_ARB_ES3_compatibility */
+
+/* ------------------------ GL_ARB_arrays_of_arrays ------------------------ */
+
+#ifndef GL_ARB_arrays_of_arrays
+#define GL_ARB_arrays_of_arrays 1
+
+#define GLEW_ARB_arrays_of_arrays GLEW_GET_VAR(__GLEW_ARB_arrays_of_arrays)
+
+#endif /* GL_ARB_arrays_of_arrays */
+
/* -------------------------- GL_ARB_base_instance ------------------------- */
#ifndef GL_ARB_base_instance
#define GL_ARB_base_instance 1
typedef void (GLAPIENTRY * PFNGLDRAWARRAYSINSTANCEDBASEINSTANCEPROC) (GLenum mode, GLint first, GLsizei count, GLsizei primcount, GLuint baseinstance);
-typedef void (GLAPIENTRY * PFNGLDRAWELEMENTSINSTANCEDBASEINSTANCEPROC) (GLenum mode, GLsizei count, GLenum type, const void* indices, GLsizei primcount, GLuint baseinstance);
-typedef void (GLAPIENTRY * PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXBASEINSTANCEPROC) (GLenum mode, GLsizei count, GLenum type, const void* indices, GLsizei primcount, GLint basevertex, GLuint baseinstance);
+typedef void (GLAPIENTRY * PFNGLDRAWELEMENTSINSTANCEDBASEINSTANCEPROC) (GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLsizei primcount, GLuint baseinstance);
+typedef void (GLAPIENTRY * PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXBASEINSTANCEPROC) (GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLsizei primcount, GLint basevertex, GLuint baseinstance);
#define glDrawArraysInstancedBaseInstance GLEW_GET_FUN(__glewDrawArraysInstancedBaseInstance)
#define glDrawElementsInstancedBaseInstance GLEW_GET_FUN(__glewDrawElementsInstancedBaseInstance)
@@ -3075,6 +3452,51 @@ typedef void (GLAPIENTRY * PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXBASEINSTANCEPROC)
#endif /* GL_ARB_base_instance */
+/* ------------------------ GL_ARB_bindless_texture ------------------------ */
+
+#ifndef GL_ARB_bindless_texture
+#define GL_ARB_bindless_texture 1
+
+#define GL_UNSIGNED_INT64_ARB 0x140F
+
+typedef GLuint64 (GLAPIENTRY * PFNGLGETIMAGEHANDLEARBPROC) (GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum format);
+typedef GLuint64 (GLAPIENTRY * PFNGLGETTEXTUREHANDLEARBPROC) (GLuint texture);
+typedef GLuint64 (GLAPIENTRY * PFNGLGETTEXTURESAMPLERHANDLEARBPROC) (GLuint texture, GLuint sampler);
+typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBLUI64VARBPROC) (GLuint index, GLenum pname, GLuint64EXT* params);
+typedef GLboolean (GLAPIENTRY * PFNGLISIMAGEHANDLERESIDENTARBPROC) (GLuint64 handle);
+typedef GLboolean (GLAPIENTRY * PFNGLISTEXTUREHANDLERESIDENTARBPROC) (GLuint64 handle);
+typedef void (GLAPIENTRY * PFNGLMAKEIMAGEHANDLENONRESIDENTARBPROC) (GLuint64 handle);
+typedef void (GLAPIENTRY * PFNGLMAKEIMAGEHANDLERESIDENTARBPROC) (GLuint64 handle, GLenum access);
+typedef void (GLAPIENTRY * PFNGLMAKETEXTUREHANDLENONRESIDENTARBPROC) (GLuint64 handle);
+typedef void (GLAPIENTRY * PFNGLMAKETEXTUREHANDLERESIDENTARBPROC) (GLuint64 handle);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMHANDLEUI64ARBPROC) (GLuint program, GLint location, GLuint64 value);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMHANDLEUI64VARBPROC) (GLuint program, GLint location, GLsizei count, const GLuint64* values);
+typedef void (GLAPIENTRY * PFNGLUNIFORMHANDLEUI64ARBPROC) (GLint location, GLuint64 value);
+typedef void (GLAPIENTRY * PFNGLUNIFORMHANDLEUI64VARBPROC) (GLint location, GLsizei count, const GLuint64* value);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL1UI64ARBPROC) (GLuint index, GLuint64EXT x);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL1UI64VARBPROC) (GLuint index, const GLuint64EXT* v);
+
+#define glGetImageHandleARB GLEW_GET_FUN(__glewGetImageHandleARB)
+#define glGetTextureHandleARB GLEW_GET_FUN(__glewGetTextureHandleARB)
+#define glGetTextureSamplerHandleARB GLEW_GET_FUN(__glewGetTextureSamplerHandleARB)
+#define glGetVertexAttribLui64vARB GLEW_GET_FUN(__glewGetVertexAttribLui64vARB)
+#define glIsImageHandleResidentARB GLEW_GET_FUN(__glewIsImageHandleResidentARB)
+#define glIsTextureHandleResidentARB GLEW_GET_FUN(__glewIsTextureHandleResidentARB)
+#define glMakeImageHandleNonResidentARB GLEW_GET_FUN(__glewMakeImageHandleNonResidentARB)
+#define glMakeImageHandleResidentARB GLEW_GET_FUN(__glewMakeImageHandleResidentARB)
+#define glMakeTextureHandleNonResidentARB GLEW_GET_FUN(__glewMakeTextureHandleNonResidentARB)
+#define glMakeTextureHandleResidentARB GLEW_GET_FUN(__glewMakeTextureHandleResidentARB)
+#define glProgramUniformHandleui64ARB GLEW_GET_FUN(__glewProgramUniformHandleui64ARB)
+#define glProgramUniformHandleui64vARB GLEW_GET_FUN(__glewProgramUniformHandleui64vARB)
+#define glUniformHandleui64ARB GLEW_GET_FUN(__glewUniformHandleui64ARB)
+#define glUniformHandleui64vARB GLEW_GET_FUN(__glewUniformHandleui64vARB)
+#define glVertexAttribL1ui64ARB GLEW_GET_FUN(__glewVertexAttribL1ui64ARB)
+#define glVertexAttribL1ui64vARB GLEW_GET_FUN(__glewVertexAttribL1ui64vARB)
+
+#define GLEW_ARB_bindless_texture GLEW_GET_VAR(__GLEW_ARB_bindless_texture)
+
+#endif /* GL_ARB_bindless_texture */
+
/* ----------------------- GL_ARB_blend_func_extended ---------------------- */
#ifndef GL_ARB_blend_func_extended
@@ -3085,8 +3507,8 @@ typedef void (GLAPIENTRY * PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXBASEINSTANCEPROC)
#define GL_ONE_MINUS_SRC1_ALPHA 0x88FB
#define GL_MAX_DUAL_SOURCE_DRAW_BUFFERS 0x88FC
-typedef void (GLAPIENTRY * PFNGLBINDFRAGDATALOCATIONINDEXEDPROC) (GLuint program, GLuint colorNumber, GLuint index, const char * name);
-typedef GLint (GLAPIENTRY * PFNGLGETFRAGDATAINDEXPROC) (GLuint program, const char * name);
+typedef void (GLAPIENTRY * PFNGLBINDFRAGDATALOCATIONINDEXEDPROC) (GLuint program, GLuint colorNumber, GLuint index, const GLchar * name);
+typedef GLint (GLAPIENTRY * PFNGLGETFRAGDATAINDEXPROC) (GLuint program, const GLchar * name);
#define glBindFragDataLocationIndexed GLEW_GET_FUN(__glewBindFragDataLocationIndexed)
#define glGetFragDataIndex GLEW_GET_FUN(__glewGetFragDataIndex)
@@ -3095,6 +3517,31 @@ typedef GLint (GLAPIENTRY * PFNGLGETFRAGDATAINDEXPROC) (GLuint program, const ch
#endif /* GL_ARB_blend_func_extended */
+/* ------------------------- GL_ARB_buffer_storage ------------------------- */
+
+#ifndef GL_ARB_buffer_storage
+#define GL_ARB_buffer_storage 1
+
+#define GL_MAP_READ_BIT 0x0001
+#define GL_MAP_WRITE_BIT 0x0002
+#define GL_MAP_PERSISTENT_BIT 0x00000040
+#define GL_MAP_COHERENT_BIT 0x00000080
+#define GL_DYNAMIC_STORAGE_BIT 0x0100
+#define GL_CLIENT_STORAGE_BIT 0x0200
+#define GL_CLIENT_MAPPED_BUFFER_BARRIER_BIT 0x00004000
+#define GL_BUFFER_IMMUTABLE_STORAGE 0x821F
+#define GL_BUFFER_STORAGE_FLAGS 0x8220
+
+typedef void (GLAPIENTRY * PFNGLBUFFERSTORAGEPROC) (GLenum target, GLsizeiptr size, const GLvoid* data, GLbitfield flags);
+typedef void (GLAPIENTRY * PFNGLNAMEDBUFFERSTORAGEEXTPROC) (GLuint buffer, GLsizeiptr size, const GLvoid* data, GLbitfield flags);
+
+#define glBufferStorage GLEW_GET_FUN(__glewBufferStorage)
+#define glNamedBufferStorageEXT GLEW_GET_FUN(__glewNamedBufferStorageEXT)
+
+#define GLEW_ARB_buffer_storage GLEW_GET_VAR(__GLEW_ARB_buffer_storage)
+
+#endif /* GL_ARB_buffer_storage */
+
/* ---------------------------- GL_ARB_cl_event ---------------------------- */
#ifndef GL_ARB_cl_event
@@ -3114,6 +3561,42 @@ typedef GLsync (GLAPIENTRY * PFNGLCREATESYNCFROMCLEVENTARBPROC) (cl_context cont
#endif /* GL_ARB_cl_event */
+/* ----------------------- GL_ARB_clear_buffer_object ---------------------- */
+
+#ifndef GL_ARB_clear_buffer_object
+#define GL_ARB_clear_buffer_object 1
+
+typedef void (GLAPIENTRY * PFNGLCLEARBUFFERDATAPROC) (GLenum target, GLenum internalformat, GLenum format, GLenum type, const GLvoid* data);
+typedef void (GLAPIENTRY * PFNGLCLEARBUFFERSUBDATAPROC) (GLenum target, GLenum internalformat, GLintptr offset, GLsizeiptr size, GLenum format, GLenum type, const GLvoid* data);
+typedef void (GLAPIENTRY * PFNGLCLEARNAMEDBUFFERDATAEXTPROC) (GLuint buffer, GLenum internalformat, GLenum format, GLenum type, const GLvoid* data);
+typedef void (GLAPIENTRY * PFNGLCLEARNAMEDBUFFERSUBDATAEXTPROC) (GLuint buffer, GLenum internalformat, GLintptr offset, GLsizeiptr size, GLenum format, GLenum type, const GLvoid* data);
+
+#define glClearBufferData GLEW_GET_FUN(__glewClearBufferData)
+#define glClearBufferSubData GLEW_GET_FUN(__glewClearBufferSubData)
+#define glClearNamedBufferDataEXT GLEW_GET_FUN(__glewClearNamedBufferDataEXT)
+#define glClearNamedBufferSubDataEXT GLEW_GET_FUN(__glewClearNamedBufferSubDataEXT)
+
+#define GLEW_ARB_clear_buffer_object GLEW_GET_VAR(__GLEW_ARB_clear_buffer_object)
+
+#endif /* GL_ARB_clear_buffer_object */
+
+/* -------------------------- GL_ARB_clear_texture ------------------------- */
+
+#ifndef GL_ARB_clear_texture
+#define GL_ARB_clear_texture 1
+
+#define GL_CLEAR_TEXTURE 0x9365
+
+typedef void (GLAPIENTRY * PFNGLCLEARTEXIMAGEPROC) (GLuint texture, GLint level, GLenum format, GLenum type, const GLvoid* data);
+typedef void (GLAPIENTRY * PFNGLCLEARTEXSUBIMAGEPROC) (GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid* data);
+
+#define glClearTexImage GLEW_GET_FUN(__glewClearTexImage)
+#define glClearTexSubImage GLEW_GET_FUN(__glewClearTexSubImage)
+
+#define GLEW_ARB_clear_texture GLEW_GET_VAR(__GLEW_ARB_clear_texture)
+
+#endif /* GL_ARB_clear_texture */
+
/* ----------------------- GL_ARB_color_buffer_float ----------------------- */
#ifndef GL_ARB_color_buffer_float
@@ -3160,6 +3643,58 @@ typedef void (GLAPIENTRY * PFNGLCLAMPCOLORARBPROC) (GLenum target, GLenum clamp)
#endif /* GL_ARB_compressed_texture_pixel_storage */
+/* ------------------------- GL_ARB_compute_shader ------------------------- */
+
+#ifndef GL_ARB_compute_shader
+#define GL_ARB_compute_shader 1
+
+#define GL_COMPUTE_SHADER_BIT 0x00000020
+#define GL_MAX_COMPUTE_SHARED_MEMORY_SIZE 0x8262
+#define GL_MAX_COMPUTE_UNIFORM_COMPONENTS 0x8263
+#define GL_MAX_COMPUTE_ATOMIC_COUNTER_BUFFERS 0x8264
+#define GL_MAX_COMPUTE_ATOMIC_COUNTERS 0x8265
+#define GL_MAX_COMBINED_COMPUTE_UNIFORM_COMPONENTS 0x8266
+#define GL_COMPUTE_WORK_GROUP_SIZE 0x8267
+#define GL_MAX_COMPUTE_WORK_GROUP_INVOCATIONS 0x90EB
+#define GL_UNIFORM_BLOCK_REFERENCED_BY_COMPUTE_SHADER 0x90EC
+#define GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_COMPUTE_SHADER 0x90ED
+#define GL_DISPATCH_INDIRECT_BUFFER 0x90EE
+#define GL_DISPATCH_INDIRECT_BUFFER_BINDING 0x90EF
+#define GL_COMPUTE_SHADER 0x91B9
+#define GL_MAX_COMPUTE_UNIFORM_BLOCKS 0x91BB
+#define GL_MAX_COMPUTE_TEXTURE_IMAGE_UNITS 0x91BC
+#define GL_MAX_COMPUTE_IMAGE_UNIFORMS 0x91BD
+#define GL_MAX_COMPUTE_WORK_GROUP_COUNT 0x91BE
+#define GL_MAX_COMPUTE_WORK_GROUP_SIZE 0x91BF
+
+typedef void (GLAPIENTRY * PFNGLDISPATCHCOMPUTEPROC) (GLuint num_groups_x, GLuint num_groups_y, GLuint num_groups_z);
+typedef void (GLAPIENTRY * PFNGLDISPATCHCOMPUTEINDIRECTPROC) (GLintptr indirect);
+
+#define glDispatchCompute GLEW_GET_FUN(__glewDispatchCompute)
+#define glDispatchComputeIndirect GLEW_GET_FUN(__glewDispatchComputeIndirect)
+
+#define GLEW_ARB_compute_shader GLEW_GET_VAR(__GLEW_ARB_compute_shader)
+
+#endif /* GL_ARB_compute_shader */
+
+/* ------------------- GL_ARB_compute_variable_group_size ------------------ */
+
+#ifndef GL_ARB_compute_variable_group_size
+#define GL_ARB_compute_variable_group_size 1
+
+#define GL_MAX_COMPUTE_FIXED_GROUP_INVOCATIONS_ARB 0x90EB
+#define GL_MAX_COMPUTE_FIXED_GROUP_SIZE_ARB 0x91BF
+#define GL_MAX_COMPUTE_VARIABLE_GROUP_INVOCATIONS_ARB 0x9344
+#define GL_MAX_COMPUTE_VARIABLE_GROUP_SIZE_ARB 0x9345
+
+typedef void (GLAPIENTRY * PFNGLDISPATCHCOMPUTEGROUPSIZEARBPROC) (GLuint num_groups_x, GLuint num_groups_y, GLuint num_groups_z, GLuint group_size_x, GLuint group_size_y, GLuint group_size_z);
+
+#define glDispatchComputeGroupSizeARB GLEW_GET_FUN(__glewDispatchComputeGroupSizeARB)
+
+#define GLEW_ARB_compute_variable_group_size GLEW_GET_VAR(__GLEW_ARB_compute_variable_group_size)
+
+#endif /* GL_ARB_compute_variable_group_size */
+
/* ----------------------- GL_ARB_conservative_depth ----------------------- */
#ifndef GL_ARB_conservative_depth
@@ -3185,6 +3720,19 @@ typedef void (GLAPIENTRY * PFNGLCOPYBUFFERSUBDATAPROC) (GLenum readtarget, GLenu
#endif /* GL_ARB_copy_buffer */
+/* --------------------------- GL_ARB_copy_image --------------------------- */
+
+#ifndef GL_ARB_copy_image
+#define GL_ARB_copy_image 1
+
+typedef void (GLAPIENTRY * PFNGLCOPYIMAGESUBDATAPROC) (GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei srcWidth, GLsizei srcHeight, GLsizei srcDepth);
+
+#define glCopyImageSubData GLEW_GET_FUN(__glewCopyImageSubData)
+
+#define GLEW_ARB_copy_image GLEW_GET_VAR(__GLEW_ARB_copy_image)
+
+#endif /* GL_ARB_copy_image */
+
/* -------------------------- GL_ARB_debug_output -------------------------- */
#ifndef GL_ARB_debug_output
@@ -3215,10 +3763,10 @@ typedef void (GLAPIENTRY * PFNGLCOPYBUFFERSUBDATAPROC) (GLenum readtarget, GLenu
typedef void (APIENTRY *GLDEBUGPROCARB)(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar* message, GLvoid* userParam);
-typedef void (GLAPIENTRY * PFNGLDEBUGMESSAGECALLBACKARBPROC) (GLDEBUGPROCARB callback, void* userParam);
+typedef void (GLAPIENTRY * PFNGLDEBUGMESSAGECALLBACKARBPROC) (GLDEBUGPROCARB callback, const GLvoid *userParam);
typedef void (GLAPIENTRY * PFNGLDEBUGMESSAGECONTROLARBPROC) (GLenum source, GLenum type, GLenum severity, GLsizei count, const GLuint* ids, GLboolean enabled);
-typedef void (GLAPIENTRY * PFNGLDEBUGMESSAGEINSERTARBPROC) (GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const char* buf);
-typedef GLuint (GLAPIENTRY * PFNGLGETDEBUGMESSAGELOGARBPROC) (GLuint count, GLsizei bufsize, GLenum* sources, GLenum* types, GLuint* ids, GLenum* severities, GLsizei* lengths, char* messageLog);
+typedef void (GLAPIENTRY * PFNGLDEBUGMESSAGEINSERTARBPROC) (GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar* buf);
+typedef GLuint (GLAPIENTRY * PFNGLGETDEBUGMESSAGELOGARBPROC) (GLuint count, GLsizei bufsize, GLenum* sources, GLenum* types, GLuint* ids, GLenum* severities, GLsizei* lengths, GLchar* messageLog);
#define glDebugMessageCallbackARB GLEW_GET_FUN(__glewDebugMessageCallbackARB)
#define glDebugMessageControlARB GLEW_GET_FUN(__glewDebugMessageControlARB)
@@ -3323,10 +3871,10 @@ typedef void (GLAPIENTRY * PFNGLBLENDFUNCIARBPROC) (GLuint buf, GLenum src, GLen
#ifndef GL_ARB_draw_elements_base_vertex
#define GL_ARB_draw_elements_base_vertex 1
-typedef void (GLAPIENTRY * PFNGLDRAWELEMENTSBASEVERTEXPROC) (GLenum mode, GLsizei count, GLenum type, void* indices, GLint basevertex);
-typedef void (GLAPIENTRY * PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXPROC) (GLenum mode, GLsizei count, GLenum type, const void* indices, GLsizei primcount, GLint basevertex);
-typedef void (GLAPIENTRY * PFNGLDRAWRANGEELEMENTSBASEVERTEXPROC) (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, void* indices, GLint basevertex);
-typedef void (GLAPIENTRY * PFNGLMULTIDRAWELEMENTSBASEVERTEXPROC) (GLenum mode, GLsizei* count, GLenum type, GLvoid**indices, GLsizei primcount, GLint *basevertex);
+typedef void (GLAPIENTRY * PFNGLDRAWELEMENTSBASEVERTEXPROC) (GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLint basevertex);
+typedef void (GLAPIENTRY * PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXPROC) (GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLsizei primcount, GLint basevertex);
+typedef void (GLAPIENTRY * PFNGLDRAWRANGEELEMENTSBASEVERTEXPROC) (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid *indices, GLint basevertex);
+typedef void (GLAPIENTRY * PFNGLMULTIDRAWELEMENTSBASEVERTEXPROC) (GLenum mode, const GLsizei* count, GLenum type, const GLvoid* const *indices, GLsizei primcount, const GLint *basevertex);
#define glDrawElementsBaseVertex GLEW_GET_FUN(__glewDrawElementsBaseVertex)
#define glDrawElementsInstancedBaseVertex GLEW_GET_FUN(__glewDrawElementsInstancedBaseVertex)
@@ -3345,8 +3893,8 @@ typedef void (GLAPIENTRY * PFNGLMULTIDRAWELEMENTSBASEVERTEXPROC) (GLenum mode, G
#define GL_DRAW_INDIRECT_BUFFER 0x8F3F
#define GL_DRAW_INDIRECT_BUFFER_BINDING 0x8F43
-typedef void (GLAPIENTRY * PFNGLDRAWARRAYSINDIRECTPROC) (GLenum mode, const void* indirect);
-typedef void (GLAPIENTRY * PFNGLDRAWELEMENTSINDIRECTPROC) (GLenum mode, GLenum type, const void* indirect);
+typedef void (GLAPIENTRY * PFNGLDRAWARRAYSINDIRECTPROC) (GLenum mode, const GLvoid *indirect);
+typedef void (GLAPIENTRY * PFNGLDRAWELEMENTSINDIRECTPROC) (GLenum mode, GLenum type, const GLvoid *indirect);
#define glDrawArraysIndirect GLEW_GET_FUN(__glewDrawArraysIndirect)
#define glDrawElementsIndirect GLEW_GET_FUN(__glewDrawElementsIndirect)
@@ -3364,6 +3912,19 @@ typedef void (GLAPIENTRY * PFNGLDRAWELEMENTSINDIRECTPROC) (GLenum mode, GLenum t
#endif /* GL_ARB_draw_instanced */
+/* ------------------------ GL_ARB_enhanced_layouts ------------------------ */
+
+#ifndef GL_ARB_enhanced_layouts
+#define GL_ARB_enhanced_layouts 1
+
+#define GL_LOCATION_COMPONENT 0x934A
+#define GL_TRANSFORM_FEEDBACK_BUFFER_INDEX 0x934B
+#define GL_TRANSFORM_FEEDBACK_BUFFER_STRIDE 0x934C
+
+#define GLEW_ARB_enhanced_layouts GLEW_GET_VAR(__GLEW_ARB_enhanced_layouts)
+
+#endif /* GL_ARB_enhanced_layouts */
+
/* -------------------- GL_ARB_explicit_attrib_location -------------------- */
#ifndef GL_ARB_explicit_attrib_location
@@ -3373,6 +3934,17 @@ typedef void (GLAPIENTRY * PFNGLDRAWELEMENTSINDIRECTPROC) (GLenum mode, GLenum t
#endif /* GL_ARB_explicit_attrib_location */
+/* -------------------- GL_ARB_explicit_uniform_location ------------------- */
+
+#ifndef GL_ARB_explicit_uniform_location
+#define GL_ARB_explicit_uniform_location 1
+
+#define GL_MAX_UNIFORM_LOCATIONS 0x826E
+
+#define GLEW_ARB_explicit_uniform_location GLEW_GET_VAR(__GLEW_ARB_explicit_uniform_location)
+
+#endif /* GL_ARB_explicit_uniform_location */
+
/* ------------------- GL_ARB_fragment_coord_conventions ------------------- */
#ifndef GL_ARB_fragment_coord_conventions
@@ -3382,6 +3954,15 @@ typedef void (GLAPIENTRY * PFNGLDRAWELEMENTSINDIRECTPROC) (GLenum mode, GLenum t
#endif /* GL_ARB_fragment_coord_conventions */
+/* --------------------- GL_ARB_fragment_layer_viewport -------------------- */
+
+#ifndef GL_ARB_fragment_layer_viewport
+#define GL_ARB_fragment_layer_viewport 1
+
+#define GLEW_ARB_fragment_layer_viewport GLEW_GET_VAR(__GLEW_ARB_fragment_layer_viewport)
+
+#endif /* GL_ARB_fragment_layer_viewport */
+
/* ------------------------ GL_ARB_fragment_program ------------------------ */
#ifndef GL_ARB_fragment_program
@@ -3429,6 +4010,35 @@ typedef void (GLAPIENTRY * PFNGLDRAWELEMENTSINDIRECTPROC) (GLenum mode, GLenum t
#endif /* GL_ARB_fragment_shader */
+/* ------------------- GL_ARB_framebuffer_no_attachments ------------------- */
+
+#ifndef GL_ARB_framebuffer_no_attachments
+#define GL_ARB_framebuffer_no_attachments 1
+
+#define GL_FRAMEBUFFER_DEFAULT_WIDTH 0x9310
+#define GL_FRAMEBUFFER_DEFAULT_HEIGHT 0x9311
+#define GL_FRAMEBUFFER_DEFAULT_LAYERS 0x9312
+#define GL_FRAMEBUFFER_DEFAULT_SAMPLES 0x9313
+#define GL_FRAMEBUFFER_DEFAULT_FIXED_SAMPLE_LOCATIONS 0x9314
+#define GL_MAX_FRAMEBUFFER_WIDTH 0x9315
+#define GL_MAX_FRAMEBUFFER_HEIGHT 0x9316
+#define GL_MAX_FRAMEBUFFER_LAYERS 0x9317
+#define GL_MAX_FRAMEBUFFER_SAMPLES 0x9318
+
+typedef void (GLAPIENTRY * PFNGLFRAMEBUFFERPARAMETERIPROC) (GLenum target, GLenum pname, GLint param);
+typedef void (GLAPIENTRY * PFNGLGETFRAMEBUFFERPARAMETERIVPROC) (GLenum target, GLenum pname, GLint* params);
+typedef void (GLAPIENTRY * PFNGLGETNAMEDFRAMEBUFFERPARAMETERIVEXTPROC) (GLuint framebuffer, GLenum pname, GLint* params);
+typedef void (GLAPIENTRY * PFNGLNAMEDFRAMEBUFFERPARAMETERIEXTPROC) (GLuint framebuffer, GLenum pname, GLint param);
+
+#define glFramebufferParameteri GLEW_GET_FUN(__glewFramebufferParameteri)
+#define glGetFramebufferParameteriv GLEW_GET_FUN(__glewGetFramebufferParameteriv)
+#define glGetNamedFramebufferParameterivEXT GLEW_GET_FUN(__glewGetNamedFramebufferParameterivEXT)
+#define glNamedFramebufferParameteriEXT GLEW_GET_FUN(__glewNamedFramebufferParameteriEXT)
+
+#define GLEW_ARB_framebuffer_no_attachments GLEW_GET_VAR(__GLEW_ARB_framebuffer_no_attachments)
+
+#endif /* GL_ARB_framebuffer_no_attachments */
+
/* ----------------------- GL_ARB_framebuffer_object ----------------------- */
#ifndef GL_ARB_framebuffer_object
@@ -3616,7 +4226,7 @@ typedef void (GLAPIENTRY * PFNGLPROGRAMPARAMETERIARBPROC) (GLuint program, GLenu
#define GL_PROGRAM_BINARY_FORMATS 0x87FF
typedef void (GLAPIENTRY * PFNGLGETPROGRAMBINARYPROC) (GLuint program, GLsizei bufSize, GLsizei* length, GLenum *binaryFormat, GLvoid*binary);
-typedef void (GLAPIENTRY * PFNGLPROGRAMBINARYPROC) (GLuint program, GLenum binaryFormat, const void* binary, GLsizei length);
+typedef void (GLAPIENTRY * PFNGLPROGRAMBINARYPROC) (GLuint program, GLenum binaryFormat, const GLvoid *binary, GLsizei length);
typedef void (GLAPIENTRY * PFNGLPROGRAMPARAMETERIPROC) (GLuint program, GLenum pname, GLint value);
#define glGetProgramBinary GLEW_GET_FUN(__glewGetProgramBinary)
@@ -3662,23 +4272,6 @@ typedef void (GLAPIENTRY * PFNGLPROGRAMPARAMETERIPROC) (GLuint program, GLenum p
#define GL_DOUBLE_VEC4 0x8FFE
typedef void (GLAPIENTRY * PFNGLGETUNIFORMDVPROC) (GLuint program, GLint location, GLdouble* params);
-typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM1DEXTPROC) (GLuint program, GLint location, GLdouble x);
-typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM1DVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLdouble* value);
-typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM2DEXTPROC) (GLuint program, GLint location, GLdouble x, GLdouble y);
-typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM2DVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLdouble* value);
-typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM3DEXTPROC) (GLuint program, GLint location, GLdouble x, GLdouble y, GLdouble z);
-typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM3DVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLdouble* value);
-typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM4DEXTPROC) (GLuint program, GLint location, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
-typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM4DVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLdouble* value);
-typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX2DVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value);
-typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX2X3DVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value);
-typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX2X4DVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value);
-typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX3DVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value);
-typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX3X2DVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value);
-typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX3X4DVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value);
-typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX4DVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value);
-typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX4X2DVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value);
-typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX4X3DVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value);
typedef void (GLAPIENTRY * PFNGLUNIFORM1DPROC) (GLint location, GLdouble x);
typedef void (GLAPIENTRY * PFNGLUNIFORM1DVPROC) (GLint location, GLsizei count, const GLdouble* value);
typedef void (GLAPIENTRY * PFNGLUNIFORM2DPROC) (GLint location, GLdouble x, GLdouble y);
@@ -3698,23 +4291,6 @@ typedef void (GLAPIENTRY * PFNGLUNIFORMMATRIX4X2DVPROC) (GLint location, GLsizei
typedef void (GLAPIENTRY * PFNGLUNIFORMMATRIX4X3DVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLdouble* value);
#define glGetUniformdv GLEW_GET_FUN(__glewGetUniformdv)
-#define glProgramUniform1dEXT GLEW_GET_FUN(__glewProgramUniform1dEXT)
-#define glProgramUniform1dvEXT GLEW_GET_FUN(__glewProgramUniform1dvEXT)
-#define glProgramUniform2dEXT GLEW_GET_FUN(__glewProgramUniform2dEXT)
-#define glProgramUniform2dvEXT GLEW_GET_FUN(__glewProgramUniform2dvEXT)
-#define glProgramUniform3dEXT GLEW_GET_FUN(__glewProgramUniform3dEXT)
-#define glProgramUniform3dvEXT GLEW_GET_FUN(__glewProgramUniform3dvEXT)
-#define glProgramUniform4dEXT GLEW_GET_FUN(__glewProgramUniform4dEXT)
-#define glProgramUniform4dvEXT GLEW_GET_FUN(__glewProgramUniform4dvEXT)
-#define glProgramUniformMatrix2dvEXT GLEW_GET_FUN(__glewProgramUniformMatrix2dvEXT)
-#define glProgramUniformMatrix2x3dvEXT GLEW_GET_FUN(__glewProgramUniformMatrix2x3dvEXT)
-#define glProgramUniformMatrix2x4dvEXT GLEW_GET_FUN(__glewProgramUniformMatrix2x4dvEXT)
-#define glProgramUniformMatrix3dvEXT GLEW_GET_FUN(__glewProgramUniformMatrix3dvEXT)
-#define glProgramUniformMatrix3x2dvEXT GLEW_GET_FUN(__glewProgramUniformMatrix3x2dvEXT)
-#define glProgramUniformMatrix3x4dvEXT GLEW_GET_FUN(__glewProgramUniformMatrix3x4dvEXT)
-#define glProgramUniformMatrix4dvEXT GLEW_GET_FUN(__glewProgramUniformMatrix4dvEXT)
-#define glProgramUniformMatrix4x2dvEXT GLEW_GET_FUN(__glewProgramUniformMatrix4x2dvEXT)
-#define glProgramUniformMatrix4x3dvEXT GLEW_GET_FUN(__glewProgramUniformMatrix4x3dvEXT)
#define glUniform1d GLEW_GET_FUN(__glewUniform1d)
#define glUniform1dv GLEW_GET_FUN(__glewUniform1dv)
#define glUniform2d GLEW_GET_FUN(__glewUniform2d)
@@ -3912,6 +4488,24 @@ typedef void (GLAPIENTRY * PFNGLSEPARABLEFILTER2DPROC) (GLenum target, GLenum in
#endif /* GL_ARB_imaging */
+/* ----------------------- GL_ARB_indirect_parameters ---------------------- */
+
+#ifndef GL_ARB_indirect_parameters
+#define GL_ARB_indirect_parameters 1
+
+#define GL_PARAMETER_BUFFER_ARB 0x80EE
+#define GL_PARAMETER_BUFFER_BINDING_ARB 0x80EF
+
+typedef void (GLAPIENTRY * PFNGLMULTIDRAWARRAYSINDIRECTCOUNTARBPROC) (GLenum mode, const GLvoid *indirect, GLintptr drawcount, GLsizei maxdrawcount, GLsizei stride);
+typedef void (GLAPIENTRY * PFNGLMULTIDRAWELEMENTSINDIRECTCOUNTARBPROC) (GLenum mode, GLenum type, const GLvoid *indirect, GLintptr drawcount, GLsizei maxdrawcount, GLsizei stride);
+
+#define glMultiDrawArraysIndirectCountARB GLEW_GET_FUN(__glewMultiDrawArraysIndirectCountARB)
+#define glMultiDrawElementsIndirectCountARB GLEW_GET_FUN(__glewMultiDrawElementsIndirectCountARB)
+
+#define GLEW_ARB_indirect_parameters GLEW_GET_VAR(__GLEW_ARB_indirect_parameters)
+
+#endif /* GL_ARB_indirect_parameters */
+
/* ------------------------ GL_ARB_instanced_arrays ------------------------ */
#ifndef GL_ARB_instanced_arrays
@@ -3946,6 +4540,142 @@ typedef void (GLAPIENTRY * PFNGLGETINTERNALFORMATIVPROC) (GLenum target, GLenum
#endif /* GL_ARB_internalformat_query */
+/* ---------------------- GL_ARB_internalformat_query2 --------------------- */
+
+#ifndef GL_ARB_internalformat_query2
+#define GL_ARB_internalformat_query2 1
+
+#define GL_INTERNALFORMAT_SUPPORTED 0x826F
+#define GL_INTERNALFORMAT_PREFERRED 0x8270
+#define GL_INTERNALFORMAT_RED_SIZE 0x8271
+#define GL_INTERNALFORMAT_GREEN_SIZE 0x8272
+#define GL_INTERNALFORMAT_BLUE_SIZE 0x8273
+#define GL_INTERNALFORMAT_ALPHA_SIZE 0x8274
+#define GL_INTERNALFORMAT_DEPTH_SIZE 0x8275
+#define GL_INTERNALFORMAT_STENCIL_SIZE 0x8276
+#define GL_INTERNALFORMAT_SHARED_SIZE 0x8277
+#define GL_INTERNALFORMAT_RED_TYPE 0x8278
+#define GL_INTERNALFORMAT_GREEN_TYPE 0x8279
+#define GL_INTERNALFORMAT_BLUE_TYPE 0x827A
+#define GL_INTERNALFORMAT_ALPHA_TYPE 0x827B
+#define GL_INTERNALFORMAT_DEPTH_TYPE 0x827C
+#define GL_INTERNALFORMAT_STENCIL_TYPE 0x827D
+#define GL_MAX_WIDTH 0x827E
+#define GL_MAX_HEIGHT 0x827F
+#define GL_MAX_DEPTH 0x8280
+#define GL_MAX_LAYERS 0x8281
+#define GL_MAX_COMBINED_DIMENSIONS 0x8282
+#define GL_COLOR_COMPONENTS 0x8283
+#define GL_DEPTH_COMPONENTS 0x8284
+#define GL_STENCIL_COMPONENTS 0x8285
+#define GL_COLOR_RENDERABLE 0x8286
+#define GL_DEPTH_RENDERABLE 0x8287
+#define GL_STENCIL_RENDERABLE 0x8288
+#define GL_FRAMEBUFFER_RENDERABLE 0x8289
+#define GL_FRAMEBUFFER_RENDERABLE_LAYERED 0x828A
+#define GL_FRAMEBUFFER_BLEND 0x828B
+#define GL_READ_PIXELS 0x828C
+#define GL_READ_PIXELS_FORMAT 0x828D
+#define GL_READ_PIXELS_TYPE 0x828E
+#define GL_TEXTURE_IMAGE_FORMAT 0x828F
+#define GL_TEXTURE_IMAGE_TYPE 0x8290
+#define GL_GET_TEXTURE_IMAGE_FORMAT 0x8291
+#define GL_GET_TEXTURE_IMAGE_TYPE 0x8292
+#define GL_MIPMAP 0x8293
+#define GL_MANUAL_GENERATE_MIPMAP 0x8294
+#define GL_AUTO_GENERATE_MIPMAP 0x8295
+#define GL_COLOR_ENCODING 0x8296
+#define GL_SRGB_READ 0x8297
+#define GL_SRGB_WRITE 0x8298
+#define GL_SRGB_DECODE_ARB 0x8299
+#define GL_FILTER 0x829A
+#define GL_VERTEX_TEXTURE 0x829B
+#define GL_TESS_CONTROL_TEXTURE 0x829C
+#define GL_TESS_EVALUATION_TEXTURE 0x829D
+#define GL_GEOMETRY_TEXTURE 0x829E
+#define GL_FRAGMENT_TEXTURE 0x829F
+#define GL_COMPUTE_TEXTURE 0x82A0
+#define GL_TEXTURE_SHADOW 0x82A1
+#define GL_TEXTURE_GATHER 0x82A2
+#define GL_TEXTURE_GATHER_SHADOW 0x82A3
+#define GL_SHADER_IMAGE_LOAD 0x82A4
+#define GL_SHADER_IMAGE_STORE 0x82A5
+#define GL_SHADER_IMAGE_ATOMIC 0x82A6
+#define GL_IMAGE_TEXEL_SIZE 0x82A7
+#define GL_IMAGE_COMPATIBILITY_CLASS 0x82A8
+#define GL_IMAGE_PIXEL_FORMAT 0x82A9
+#define GL_IMAGE_PIXEL_TYPE 0x82AA
+#define GL_SIMULTANEOUS_TEXTURE_AND_DEPTH_TEST 0x82AC
+#define GL_SIMULTANEOUS_TEXTURE_AND_STENCIL_TEST 0x82AD
+#define GL_SIMULTANEOUS_TEXTURE_AND_DEPTH_WRITE 0x82AE
+#define GL_SIMULTANEOUS_TEXTURE_AND_STENCIL_WRITE 0x82AF
+#define GL_TEXTURE_COMPRESSED_BLOCK_WIDTH 0x82B1
+#define GL_TEXTURE_COMPRESSED_BLOCK_HEIGHT 0x82B2
+#define GL_TEXTURE_COMPRESSED_BLOCK_SIZE 0x82B3
+#define GL_CLEAR_BUFFER 0x82B4
+#define GL_TEXTURE_VIEW 0x82B5
+#define GL_VIEW_COMPATIBILITY_CLASS 0x82B6
+#define GL_FULL_SUPPORT 0x82B7
+#define GL_CAVEAT_SUPPORT 0x82B8
+#define GL_IMAGE_CLASS_4_X_32 0x82B9
+#define GL_IMAGE_CLASS_2_X_32 0x82BA
+#define GL_IMAGE_CLASS_1_X_32 0x82BB
+#define GL_IMAGE_CLASS_4_X_16 0x82BC
+#define GL_IMAGE_CLASS_2_X_16 0x82BD
+#define GL_IMAGE_CLASS_1_X_16 0x82BE
+#define GL_IMAGE_CLASS_4_X_8 0x82BF
+#define GL_IMAGE_CLASS_2_X_8 0x82C0
+#define GL_IMAGE_CLASS_1_X_8 0x82C1
+#define GL_IMAGE_CLASS_11_11_10 0x82C2
+#define GL_IMAGE_CLASS_10_10_10_2 0x82C3
+#define GL_VIEW_CLASS_128_BITS 0x82C4
+#define GL_VIEW_CLASS_96_BITS 0x82C5
+#define GL_VIEW_CLASS_64_BITS 0x82C6
+#define GL_VIEW_CLASS_48_BITS 0x82C7
+#define GL_VIEW_CLASS_32_BITS 0x82C8
+#define GL_VIEW_CLASS_24_BITS 0x82C9
+#define GL_VIEW_CLASS_16_BITS 0x82CA
+#define GL_VIEW_CLASS_8_BITS 0x82CB
+#define GL_VIEW_CLASS_S3TC_DXT1_RGB 0x82CC
+#define GL_VIEW_CLASS_S3TC_DXT1_RGBA 0x82CD
+#define GL_VIEW_CLASS_S3TC_DXT3_RGBA 0x82CE
+#define GL_VIEW_CLASS_S3TC_DXT5_RGBA 0x82CF
+#define GL_VIEW_CLASS_RGTC1_RED 0x82D0
+#define GL_VIEW_CLASS_RGTC2_RG 0x82D1
+#define GL_VIEW_CLASS_BPTC_UNORM 0x82D2
+#define GL_VIEW_CLASS_BPTC_FLOAT 0x82D3
+
+typedef void (GLAPIENTRY * PFNGLGETINTERNALFORMATI64VPROC) (GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLint64* params);
+
+#define glGetInternalformati64v GLEW_GET_FUN(__glewGetInternalformati64v)
+
+#define GLEW_ARB_internalformat_query2 GLEW_GET_VAR(__GLEW_ARB_internalformat_query2)
+
+#endif /* GL_ARB_internalformat_query2 */
+
+/* ----------------------- GL_ARB_invalidate_subdata ----------------------- */
+
+#ifndef GL_ARB_invalidate_subdata
+#define GL_ARB_invalidate_subdata 1
+
+typedef void (GLAPIENTRY * PFNGLINVALIDATEBUFFERDATAPROC) (GLuint buffer);
+typedef void (GLAPIENTRY * PFNGLINVALIDATEBUFFERSUBDATAPROC) (GLuint buffer, GLintptr offset, GLsizeiptr length);
+typedef void (GLAPIENTRY * PFNGLINVALIDATEFRAMEBUFFERPROC) (GLenum target, GLsizei numAttachments, const GLenum* attachments);
+typedef void (GLAPIENTRY * PFNGLINVALIDATESUBFRAMEBUFFERPROC) (GLenum target, GLsizei numAttachments, const GLenum* attachments, GLint x, GLint y, GLsizei width, GLsizei height);
+typedef void (GLAPIENTRY * PFNGLINVALIDATETEXIMAGEPROC) (GLuint texture, GLint level);
+typedef void (GLAPIENTRY * PFNGLINVALIDATETEXSUBIMAGEPROC) (GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth);
+
+#define glInvalidateBufferData GLEW_GET_FUN(__glewInvalidateBufferData)
+#define glInvalidateBufferSubData GLEW_GET_FUN(__glewInvalidateBufferSubData)
+#define glInvalidateFramebuffer GLEW_GET_FUN(__glewInvalidateFramebuffer)
+#define glInvalidateSubFramebuffer GLEW_GET_FUN(__glewInvalidateSubFramebuffer)
+#define glInvalidateTexImage GLEW_GET_FUN(__glewInvalidateTexImage)
+#define glInvalidateTexSubImage GLEW_GET_FUN(__glewInvalidateTexSubImage)
+
+#define GLEW_ARB_invalidate_subdata GLEW_GET_VAR(__GLEW_ARB_invalidate_subdata)
+
+#endif /* GL_ARB_invalidate_subdata */
+
/* ---------------------- GL_ARB_map_buffer_alignment ---------------------- */
#ifndef GL_ARB_map_buffer_alignment
@@ -4011,6 +4741,44 @@ typedef void (GLAPIENTRY * PFNGLMATRIXINDEXUSVARBPROC) (GLint size, GLushort *in
#endif /* GL_ARB_matrix_palette */
+/* --------------------------- GL_ARB_multi_bind --------------------------- */
+
+#ifndef GL_ARB_multi_bind
+#define GL_ARB_multi_bind 1
+
+typedef void (GLAPIENTRY * PFNGLBINDBUFFERSBASEPROC) (GLenum target, GLuint first, GLsizei count, const GLuint* buffers);
+typedef void (GLAPIENTRY * PFNGLBINDBUFFERSRANGEPROC) (GLenum target, GLuint first, GLsizei count, const GLuint* buffers, const GLintptr *offsets, const GLsizeiptr *sizes);
+typedef void (GLAPIENTRY * PFNGLBINDIMAGETEXTURESPROC) (GLuint first, GLsizei count, const GLuint* textures);
+typedef void (GLAPIENTRY * PFNGLBINDSAMPLERSPROC) (GLuint first, GLsizei count, const GLuint* samplers);
+typedef void (GLAPIENTRY * PFNGLBINDTEXTURESPROC) (GLuint first, GLsizei count, const GLuint* textures);
+typedef void (GLAPIENTRY * PFNGLBINDVERTEXBUFFERSPROC) (GLuint first, GLsizei count, const GLuint* buffers, const GLintptr *offsets, const GLsizei *strides);
+
+#define glBindBuffersBase GLEW_GET_FUN(__glewBindBuffersBase)
+#define glBindBuffersRange GLEW_GET_FUN(__glewBindBuffersRange)
+#define glBindImageTextures GLEW_GET_FUN(__glewBindImageTextures)
+#define glBindSamplers GLEW_GET_FUN(__glewBindSamplers)
+#define glBindTextures GLEW_GET_FUN(__glewBindTextures)
+#define glBindVertexBuffers GLEW_GET_FUN(__glewBindVertexBuffers)
+
+#define GLEW_ARB_multi_bind GLEW_GET_VAR(__GLEW_ARB_multi_bind)
+
+#endif /* GL_ARB_multi_bind */
+
+/* ----------------------- GL_ARB_multi_draw_indirect ---------------------- */
+
+#ifndef GL_ARB_multi_draw_indirect
+#define GL_ARB_multi_draw_indirect 1
+
+typedef void (GLAPIENTRY * PFNGLMULTIDRAWARRAYSINDIRECTPROC) (GLenum mode, const GLvoid *indirect, GLsizei primcount, GLsizei stride);
+typedef void (GLAPIENTRY * PFNGLMULTIDRAWELEMENTSINDIRECTPROC) (GLenum mode, GLenum type, const GLvoid *indirect, GLsizei primcount, GLsizei stride);
+
+#define glMultiDrawArraysIndirect GLEW_GET_FUN(__glewMultiDrawArraysIndirect)
+#define glMultiDrawElementsIndirect GLEW_GET_FUN(__glewMultiDrawElementsIndirect)
+
+#define GLEW_ARB_multi_draw_indirect GLEW_GET_VAR(__GLEW_ARB_multi_draw_indirect)
+
+#endif /* GL_ARB_multi_draw_indirect */
+
/* --------------------------- GL_ARB_multisample -------------------------- */
#ifndef GL_ARB_multisample
@@ -4239,6 +5007,77 @@ typedef void (GLAPIENTRY * PFNGLPOINTPARAMETERFVARBPROC) (GLenum pname, const GL
#endif /* GL_ARB_point_sprite */
+/* --------------------- GL_ARB_program_interface_query -------------------- */
+
+#ifndef GL_ARB_program_interface_query
+#define GL_ARB_program_interface_query 1
+
+#define GL_UNIFORM 0x92E1
+#define GL_UNIFORM_BLOCK 0x92E2
+#define GL_PROGRAM_INPUT 0x92E3
+#define GL_PROGRAM_OUTPUT 0x92E4
+#define GL_BUFFER_VARIABLE 0x92E5
+#define GL_SHADER_STORAGE_BLOCK 0x92E6
+#define GL_IS_PER_PATCH 0x92E7
+#define GL_VERTEX_SUBROUTINE 0x92E8
+#define GL_TESS_CONTROL_SUBROUTINE 0x92E9
+#define GL_TESS_EVALUATION_SUBROUTINE 0x92EA
+#define GL_GEOMETRY_SUBROUTINE 0x92EB
+#define GL_FRAGMENT_SUBROUTINE 0x92EC
+#define GL_COMPUTE_SUBROUTINE 0x92ED
+#define GL_VERTEX_SUBROUTINE_UNIFORM 0x92EE
+#define GL_TESS_CONTROL_SUBROUTINE_UNIFORM 0x92EF
+#define GL_TESS_EVALUATION_SUBROUTINE_UNIFORM 0x92F0
+#define GL_GEOMETRY_SUBROUTINE_UNIFORM 0x92F1
+#define GL_FRAGMENT_SUBROUTINE_UNIFORM 0x92F2
+#define GL_COMPUTE_SUBROUTINE_UNIFORM 0x92F3
+#define GL_TRANSFORM_FEEDBACK_VARYING 0x92F4
+#define GL_ACTIVE_RESOURCES 0x92F5
+#define GL_MAX_NAME_LENGTH 0x92F6
+#define GL_MAX_NUM_ACTIVE_VARIABLES 0x92F7
+#define GL_MAX_NUM_COMPATIBLE_SUBROUTINES 0x92F8
+#define GL_NAME_LENGTH 0x92F9
+#define GL_TYPE 0x92FA
+#define GL_ARRAY_SIZE 0x92FB
+#define GL_OFFSET 0x92FC
+#define GL_BLOCK_INDEX 0x92FD
+#define GL_ARRAY_STRIDE 0x92FE
+#define GL_MATRIX_STRIDE 0x92FF
+#define GL_IS_ROW_MAJOR 0x9300
+#define GL_ATOMIC_COUNTER_BUFFER_INDEX 0x9301
+#define GL_BUFFER_BINDING 0x9302
+#define GL_BUFFER_DATA_SIZE 0x9303
+#define GL_NUM_ACTIVE_VARIABLES 0x9304
+#define GL_ACTIVE_VARIABLES 0x9305
+#define GL_REFERENCED_BY_VERTEX_SHADER 0x9306
+#define GL_REFERENCED_BY_TESS_CONTROL_SHADER 0x9307
+#define GL_REFERENCED_BY_TESS_EVALUATION_SHADER 0x9308
+#define GL_REFERENCED_BY_GEOMETRY_SHADER 0x9309
+#define GL_REFERENCED_BY_FRAGMENT_SHADER 0x930A
+#define GL_REFERENCED_BY_COMPUTE_SHADER 0x930B
+#define GL_TOP_LEVEL_ARRAY_SIZE 0x930C
+#define GL_TOP_LEVEL_ARRAY_STRIDE 0x930D
+#define GL_LOCATION 0x930E
+#define GL_LOCATION_INDEX 0x930F
+
+typedef void (GLAPIENTRY * PFNGLGETPROGRAMINTERFACEIVPROC) (GLuint program, GLenum programInterface, GLenum pname, GLint* params);
+typedef GLuint (GLAPIENTRY * PFNGLGETPROGRAMRESOURCEINDEXPROC) (GLuint program, GLenum programInterface, const GLchar* name);
+typedef GLint (GLAPIENTRY * PFNGLGETPROGRAMRESOURCELOCATIONPROC) (GLuint program, GLenum programInterface, const GLchar* name);
+typedef GLint (GLAPIENTRY * PFNGLGETPROGRAMRESOURCELOCATIONINDEXPROC) (GLuint program, GLenum programInterface, const GLchar* name);
+typedef void (GLAPIENTRY * PFNGLGETPROGRAMRESOURCENAMEPROC) (GLuint program, GLenum programInterface, GLuint index, GLsizei bufSize, GLsizei* length, GLchar *name);
+typedef void (GLAPIENTRY * PFNGLGETPROGRAMRESOURCEIVPROC) (GLuint program, GLenum programInterface, GLuint index, GLsizei propCount, const GLenum* props, GLsizei bufSize, GLsizei *length, GLint *params);
+
+#define glGetProgramInterfaceiv GLEW_GET_FUN(__glewGetProgramInterfaceiv)
+#define glGetProgramResourceIndex GLEW_GET_FUN(__glewGetProgramResourceIndex)
+#define glGetProgramResourceLocation GLEW_GET_FUN(__glewGetProgramResourceLocation)
+#define glGetProgramResourceLocationIndex GLEW_GET_FUN(__glewGetProgramResourceLocationIndex)
+#define glGetProgramResourceName GLEW_GET_FUN(__glewGetProgramResourceName)
+#define glGetProgramResourceiv GLEW_GET_FUN(__glewGetProgramResourceiv)
+
+#define GLEW_ARB_program_interface_query GLEW_GET_VAR(__GLEW_ARB_program_interface_query)
+
+#endif /* GL_ARB_program_interface_query */
+
/* ------------------------ GL_ARB_provoking_vertex ------------------------ */
#ifndef GL_ARB_provoking_vertex
@@ -4257,6 +5096,29 @@ typedef void (GLAPIENTRY * PFNGLPROVOKINGVERTEXPROC) (GLenum mode);
#endif /* GL_ARB_provoking_vertex */
+/* ----------------------- GL_ARB_query_buffer_object ---------------------- */
+
+#ifndef GL_ARB_query_buffer_object
+#define GL_ARB_query_buffer_object 1
+
+#define GL_QUERY_BUFFER_BARRIER_BIT 0x00008000
+#define GL_QUERY_BUFFER 0x9192
+#define GL_QUERY_BUFFER_BINDING 0x9193
+#define GL_QUERY_RESULT_NO_WAIT 0x9194
+
+#define GLEW_ARB_query_buffer_object GLEW_GET_VAR(__GLEW_ARB_query_buffer_object)
+
+#endif /* GL_ARB_query_buffer_object */
+
+/* ------------------ GL_ARB_robust_buffer_access_behavior ----------------- */
+
+#ifndef GL_ARB_robust_buffer_access_behavior
+#define GL_ARB_robust_buffer_access_behavior 1
+
+#define GLEW_ARB_robust_buffer_access_behavior GLEW_GET_VAR(__GLEW_ARB_robust_buffer_access_behavior)
+
+#endif /* GL_ARB_robust_buffer_access_behavior */
+
/* --------------------------- GL_ARB_robustness --------------------------- */
#ifndef GL_ARB_robustness
@@ -4316,6 +5178,24 @@ typedef void (GLAPIENTRY * PFNGLREADNPIXELSARBPROC) (GLint x, GLint y, GLsizei w
#endif /* GL_ARB_robustness */
+/* ---------------- GL_ARB_robustness_application_isolation ---------------- */
+
+#ifndef GL_ARB_robustness_application_isolation
+#define GL_ARB_robustness_application_isolation 1
+
+#define GLEW_ARB_robustness_application_isolation GLEW_GET_VAR(__GLEW_ARB_robustness_application_isolation)
+
+#endif /* GL_ARB_robustness_application_isolation */
+
+/* ---------------- GL_ARB_robustness_share_group_isolation ---------------- */
+
+#ifndef GL_ARB_robustness_share_group_isolation
+#define GL_ARB_robustness_share_group_isolation 1
+
+#define GLEW_ARB_robustness_share_group_isolation GLEW_GET_VAR(__GLEW_ARB_robustness_share_group_isolation)
+
+#endif /* GL_ARB_robustness_share_group_isolation */
+
/* ------------------------- GL_ARB_sample_shading ------------------------- */
#ifndef GL_ARB_sample_shading
@@ -4384,6 +5264,17 @@ typedef void (GLAPIENTRY * PFNGLSAMPLERPARAMETERIVPROC) (GLuint sampler, GLenum
#endif /* GL_ARB_seamless_cube_map */
+/* ------------------ GL_ARB_seamless_cubemap_per_texture ------------------ */
+
+#ifndef GL_ARB_seamless_cubemap_per_texture
+#define GL_ARB_seamless_cubemap_per_texture 1
+
+#define GL_TEXTURE_CUBE_MAP_SEAMLESS 0x884F
+
+#define GLEW_ARB_seamless_cubemap_per_texture GLEW_GET_VAR(__GLEW_ARB_seamless_cubemap_per_texture)
+
+#endif /* GL_ARB_seamless_cubemap_per_texture */
+
/* --------------------- GL_ARB_separate_shader_objects -------------------- */
#ifndef GL_ARB_separate_shader_objects
@@ -4401,10 +5292,10 @@ typedef void (GLAPIENTRY * PFNGLSAMPLERPARAMETERIVPROC) (GLuint sampler, GLenum
typedef void (GLAPIENTRY * PFNGLACTIVESHADERPROGRAMPROC) (GLuint pipeline, GLuint program);
typedef void (GLAPIENTRY * PFNGLBINDPROGRAMPIPELINEPROC) (GLuint pipeline);
-typedef GLuint (GLAPIENTRY * PFNGLCREATESHADERPROGRAMVPROC) (GLenum type, GLsizei count, const char ** strings);
+typedef GLuint (GLAPIENTRY * PFNGLCREATESHADERPROGRAMVPROC) (GLenum type, GLsizei count, const GLchar ** strings);
typedef void (GLAPIENTRY * PFNGLDELETEPROGRAMPIPELINESPROC) (GLsizei n, const GLuint* pipelines);
typedef void (GLAPIENTRY * PFNGLGENPROGRAMPIPELINESPROC) (GLsizei n, GLuint* pipelines);
-typedef void (GLAPIENTRY * PFNGLGETPROGRAMPIPELINEINFOLOGPROC) (GLuint pipeline, GLsizei bufSize, GLsizei* length, char *infoLog);
+typedef void (GLAPIENTRY * PFNGLGETPROGRAMPIPELINEINFOLOGPROC) (GLuint pipeline, GLsizei bufSize, GLsizei* length, GLchar *infoLog);
typedef void (GLAPIENTRY * PFNGLGETPROGRAMPIPELINEIVPROC) (GLuint pipeline, GLenum pname, GLint* params);
typedef GLboolean (GLAPIENTRY * PFNGLISPROGRAMPIPELINEPROC) (GLuint pipeline);
typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM1DPROC) (GLuint program, GLint location, GLdouble x);
@@ -4577,6 +5468,24 @@ typedef void (GLAPIENTRY * PFNGLGETACTIVEATOMICCOUNTERBUFFERIVPROC) (GLuint prog
#endif /* GL_ARB_shader_bit_encoding */
+/* --------------------- GL_ARB_shader_draw_parameters --------------------- */
+
+#ifndef GL_ARB_shader_draw_parameters
+#define GL_ARB_shader_draw_parameters 1
+
+#define GLEW_ARB_shader_draw_parameters GLEW_GET_VAR(__GLEW_ARB_shader_draw_parameters)
+
+#endif /* GL_ARB_shader_draw_parameters */
+
+/* ------------------------ GL_ARB_shader_group_vote ----------------------- */
+
+#ifndef GL_ARB_shader_group_vote
+#define GL_ARB_shader_group_vote 1
+
+#define GLEW_ARB_shader_group_vote GLEW_GET_VAR(__GLEW_ARB_shader_group_vote)
+
+#endif /* GL_ARB_shader_group_vote */
+
/* --------------------- GL_ARB_shader_image_load_store -------------------- */
#ifndef GL_ARB_shader_image_load_store
@@ -4657,6 +5566,15 @@ typedef void (GLAPIENTRY * PFNGLMEMORYBARRIERPROC) (GLbitfield barriers);
#endif /* GL_ARB_shader_image_load_store */
+/* ------------------------ GL_ARB_shader_image_size ----------------------- */
+
+#ifndef GL_ARB_shader_image_size
+#define GL_ARB_shader_image_size 1
+
+#define GLEW_ARB_shader_image_size GLEW_GET_VAR(__GLEW_ARB_shader_image_size)
+
+#endif /* GL_ARB_shader_image_size */
+
/* ------------------------- GL_ARB_shader_objects ------------------------- */
#ifndef GL_ARB_shader_objects
@@ -4802,6 +5720,36 @@ typedef void (GLAPIENTRY * PFNGLVALIDATEPROGRAMARBPROC) (GLhandleARB programObj)
#endif /* GL_ARB_shader_stencil_export */
+/* ------------------ GL_ARB_shader_storage_buffer_object ------------------ */
+
+#ifndef GL_ARB_shader_storage_buffer_object
+#define GL_ARB_shader_storage_buffer_object 1
+
+#define GL_SHADER_STORAGE_BARRIER_BIT 0x2000
+#define GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES 0x8F39
+#define GL_SHADER_STORAGE_BUFFER 0x90D2
+#define GL_SHADER_STORAGE_BUFFER_BINDING 0x90D3
+#define GL_SHADER_STORAGE_BUFFER_START 0x90D4
+#define GL_SHADER_STORAGE_BUFFER_SIZE 0x90D5
+#define GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS 0x90D6
+#define GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS 0x90D7
+#define GL_MAX_TESS_CONTROL_SHADER_STORAGE_BLOCKS 0x90D8
+#define GL_MAX_TESS_EVALUATION_SHADER_STORAGE_BLOCKS 0x90D9
+#define GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS 0x90DA
+#define GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS 0x90DB
+#define GL_MAX_COMBINED_SHADER_STORAGE_BLOCKS 0x90DC
+#define GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS 0x90DD
+#define GL_MAX_SHADER_STORAGE_BLOCK_SIZE 0x90DE
+#define GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT 0x90DF
+
+typedef void (GLAPIENTRY * PFNGLSHADERSTORAGEBLOCKBINDINGPROC) (GLuint program, GLuint storageBlockIndex, GLuint storageBlockBinding);
+
+#define glShaderStorageBlockBinding GLEW_GET_FUN(__glewShaderStorageBlockBinding)
+
+#define GLEW_ARB_shader_storage_buffer_object GLEW_GET_VAR(__GLEW_ARB_shader_storage_buffer_object)
+
+#endif /* GL_ARB_shader_storage_buffer_object */
+
/* ------------------------ GL_ARB_shader_subroutine ----------------------- */
#ifndef GL_ARB_shader_subroutine
@@ -4817,12 +5765,12 @@ typedef void (GLAPIENTRY * PFNGLVALIDATEPROGRAMARBPROC) (GLhandleARB programObj)
#define GL_NUM_COMPATIBLE_SUBROUTINES 0x8E4A
#define GL_COMPATIBLE_SUBROUTINES 0x8E4B
-typedef void (GLAPIENTRY * PFNGLGETACTIVESUBROUTINENAMEPROC) (GLuint program, GLenum shadertype, GLuint index, GLsizei bufsize, GLsizei* length, char *name);
-typedef void (GLAPIENTRY * PFNGLGETACTIVESUBROUTINEUNIFORMNAMEPROC) (GLuint program, GLenum shadertype, GLuint index, GLsizei bufsize, GLsizei* length, char *name);
+typedef void (GLAPIENTRY * PFNGLGETACTIVESUBROUTINENAMEPROC) (GLuint program, GLenum shadertype, GLuint index, GLsizei bufsize, GLsizei* length, GLchar *name);
+typedef void (GLAPIENTRY * PFNGLGETACTIVESUBROUTINEUNIFORMNAMEPROC) (GLuint program, GLenum shadertype, GLuint index, GLsizei bufsize, GLsizei* length, GLchar *name);
typedef void (GLAPIENTRY * PFNGLGETACTIVESUBROUTINEUNIFORMIVPROC) (GLuint program, GLenum shadertype, GLuint index, GLenum pname, GLint* values);
typedef void (GLAPIENTRY * PFNGLGETPROGRAMSTAGEIVPROC) (GLuint program, GLenum shadertype, GLenum pname, GLint* values);
-typedef GLuint (GLAPIENTRY * PFNGLGETSUBROUTINEINDEXPROC) (GLuint program, GLenum shadertype, const char* name);
-typedef GLint (GLAPIENTRY * PFNGLGETSUBROUTINEUNIFORMLOCATIONPROC) (GLuint program, GLenum shadertype, const char* name);
+typedef GLuint (GLAPIENTRY * PFNGLGETSUBROUTINEINDEXPROC) (GLuint program, GLenum shadertype, const GLchar* name);
+typedef GLint (GLAPIENTRY * PFNGLGETSUBROUTINEUNIFORMLOCATIONPROC) (GLuint program, GLenum shadertype, const GLchar* name);
typedef void (GLAPIENTRY * PFNGLGETUNIFORMSUBROUTINEUIVPROC) (GLenum shadertype, GLint location, GLuint* params);
typedef void (GLAPIENTRY * PFNGLUNIFORMSUBROUTINESUIVPROC) (GLenum shadertype, GLsizei count, const GLuint* indices);
@@ -4877,12 +5825,12 @@ typedef void (GLAPIENTRY * PFNGLUNIFORMSUBROUTINESUIVPROC) (GLenum shadertype, G
#define GL_NAMED_STRING_LENGTH_ARB 0x8DE9
#define GL_NAMED_STRING_TYPE_ARB 0x8DEA
-typedef void (GLAPIENTRY * PFNGLCOMPILESHADERINCLUDEARBPROC) (GLuint shader, GLsizei count, const char ** path, const GLint *length);
-typedef void (GLAPIENTRY * PFNGLDELETENAMEDSTRINGARBPROC) (GLint namelen, const char* name);
-typedef void (GLAPIENTRY * PFNGLGETNAMEDSTRINGARBPROC) (GLint namelen, const char* name, GLsizei bufSize, GLint *stringlen, char *string);
-typedef void (GLAPIENTRY * PFNGLGETNAMEDSTRINGIVARBPROC) (GLint namelen, const char* name, GLenum pname, GLint *params);
-typedef GLboolean (GLAPIENTRY * PFNGLISNAMEDSTRINGARBPROC) (GLint namelen, const char* name);
-typedef void (GLAPIENTRY * PFNGLNAMEDSTRINGARBPROC) (GLenum type, GLint namelen, const char* name, GLint stringlen, const char *string);
+typedef void (GLAPIENTRY * PFNGLCOMPILESHADERINCLUDEARBPROC) (GLuint shader, GLsizei count, const GLchar* const *path, const GLint *length);
+typedef void (GLAPIENTRY * PFNGLDELETENAMEDSTRINGARBPROC) (GLint namelen, const GLchar* name);
+typedef void (GLAPIENTRY * PFNGLGETNAMEDSTRINGARBPROC) (GLint namelen, const GLchar* name, GLsizei bufSize, GLint *stringlen, GLchar *string);
+typedef void (GLAPIENTRY * PFNGLGETNAMEDSTRINGIVARBPROC) (GLint namelen, const GLchar* name, GLenum pname, GLint *params);
+typedef GLboolean (GLAPIENTRY * PFNGLISNAMEDSTRINGARBPROC) (GLint namelen, const GLchar* name);
+typedef void (GLAPIENTRY * PFNGLNAMEDSTRINGARBPROC) (GLenum type, GLint namelen, const GLchar* name, GLint stringlen, const GLchar *string);
#define glCompileShaderIncludeARB GLEW_GET_FUN(__glewCompileShaderIncludeARB)
#define glDeleteNamedStringARB GLEW_GET_FUN(__glewDeleteNamedStringARB)
@@ -4928,6 +5876,44 @@ typedef void (GLAPIENTRY * PFNGLNAMEDSTRINGARBPROC) (GLenum type, GLint namelen,
#endif /* GL_ARB_shadow_ambient */
+/* ------------------------- GL_ARB_sparse_texture ------------------------- */
+
+#ifndef GL_ARB_sparse_texture
+#define GL_ARB_sparse_texture 1
+
+#define GL_VIRTUAL_PAGE_SIZE_X_ARB 0x9195
+#define GL_VIRTUAL_PAGE_SIZE_Y_ARB 0x9196
+#define GL_VIRTUAL_PAGE_SIZE_Z_ARB 0x9197
+#define GL_MAX_SPARSE_TEXTURE_SIZE_ARB 0x9198
+#define GL_MAX_SPARSE_3D_TEXTURE_SIZE_ARB 0x9199
+#define GL_MAX_SPARSE_ARRAY_TEXTURE_LAYERS_ARB 0x919A
+#define GL_TEXTURE_SPARSE_ARB 0x91A6
+#define GL_VIRTUAL_PAGE_SIZE_INDEX_ARB 0x91A7
+#define GL_NUM_VIRTUAL_PAGE_SIZES_ARB 0x91A8
+#define GL_SPARSE_TEXTURE_FULL_ARRAY_CUBE_MIPMAPS_ARB 0x91A9
+#define GL_NUM_SPARSE_LEVELS_ARB 0x91AA
+
+typedef void (GLAPIENTRY * PFNGLTEXPAGECOMMITMENTARBPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLboolean commit);
+typedef void (GLAPIENTRY * PFNGLTEXTUREPAGECOMMITMENTEXTPROC) (GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLboolean commit);
+
+#define glTexPageCommitmentARB GLEW_GET_FUN(__glewTexPageCommitmentARB)
+#define glTexturePageCommitmentEXT GLEW_GET_FUN(__glewTexturePageCommitmentEXT)
+
+#define GLEW_ARB_sparse_texture GLEW_GET_VAR(__GLEW_ARB_sparse_texture)
+
+#endif /* GL_ARB_sparse_texture */
+
+/* ------------------------ GL_ARB_stencil_texturing ----------------------- */
+
+#ifndef GL_ARB_stencil_texturing
+#define GL_ARB_stencil_texturing 1
+
+#define GL_DEPTH_STENCIL_TEXTURE_MODE 0x90EA
+
+#define GLEW_ARB_stencil_texturing GLEW_GET_VAR(__GLEW_ARB_stencil_texturing)
+
+#endif /* GL_ARB_stencil_texturing */
+
/* ------------------------------ GL_ARB_sync ------------------------------ */
#ifndef GL_ARB_sync
@@ -5056,6 +6042,25 @@ typedef void (GLAPIENTRY * PFNGLTEXBUFFERARBPROC) (GLenum target, GLenum interna
#endif /* GL_ARB_texture_buffer_object_rgb32 */
+/* ---------------------- GL_ARB_texture_buffer_range ---------------------- */
+
+#ifndef GL_ARB_texture_buffer_range
+#define GL_ARB_texture_buffer_range 1
+
+#define GL_TEXTURE_BUFFER_OFFSET 0x919D
+#define GL_TEXTURE_BUFFER_SIZE 0x919E
+#define GL_TEXTURE_BUFFER_OFFSET_ALIGNMENT 0x919F
+
+typedef void (GLAPIENTRY * PFNGLTEXBUFFERRANGEPROC) (GLenum target, GLenum internalformat, GLuint buffer, GLintptr offset, GLsizeiptr size);
+typedef void (GLAPIENTRY * PFNGLTEXTUREBUFFERRANGEEXTPROC) (GLuint texture, GLenum target, GLenum internalformat, GLuint buffer, GLintptr offset, GLsizeiptr size);
+
+#define glTexBufferRange GLEW_GET_FUN(__glewTexBufferRange)
+#define glTextureBufferRangeEXT GLEW_GET_FUN(__glewTextureBufferRangeEXT)
+
+#define GLEW_ARB_texture_buffer_range GLEW_GET_VAR(__GLEW_ARB_texture_buffer_range)
+
+#endif /* GL_ARB_texture_buffer_range */
+
/* ----------------------- GL_ARB_texture_compression ---------------------- */
#ifndef GL_ARB_texture_compression
@@ -5073,13 +6078,13 @@ typedef void (GLAPIENTRY * PFNGLTEXBUFFERARBPROC) (GLenum target, GLenum interna
#define GL_NUM_COMPRESSED_TEXTURE_FORMATS_ARB 0x86A2
#define GL_COMPRESSED_TEXTURE_FORMATS_ARB 0x86A3
-typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXIMAGE1DARBPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const void* data);
-typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXIMAGE2DARBPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void* data);
-typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXIMAGE3DARBPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void* data);
-typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXSUBIMAGE1DARBPROC) (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const void* data);
-typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXSUBIMAGE2DARBPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void* data);
-typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXSUBIMAGE3DARBPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void* data);
-typedef void (GLAPIENTRY * PFNGLGETCOMPRESSEDTEXIMAGEARBPROC) (GLenum target, GLint lod, void* img);
+typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXIMAGE1DARBPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const GLvoid *data);
+typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXIMAGE2DARBPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *data);
+typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXIMAGE3DARBPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid *data);
+typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXSUBIMAGE1DARBPROC) (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const GLvoid *data);
+typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXSUBIMAGE2DARBPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid *data);
+typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXSUBIMAGE3DARBPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid *data);
+typedef void (GLAPIENTRY * PFNGLGETCOMPRESSEDTEXIMAGEARBPROC) (GLenum target, GLint lod, GLvoid *img);
#define glCompressedTexImage1DARB GLEW_GET_FUN(__glewCompressedTexImage1DARB)
#define glCompressedTexImage2DARB GLEW_GET_FUN(__glewCompressedTexImage2DARB)
@@ -5265,6 +6270,17 @@ typedef void (GLAPIENTRY * PFNGLGETCOMPRESSEDTEXIMAGEARBPROC) (GLenum target, GL
#endif /* GL_ARB_texture_gather */
+/* ------------------ GL_ARB_texture_mirror_clamp_to_edge ------------------ */
+
+#ifndef GL_ARB_texture_mirror_clamp_to_edge
+#define GL_ARB_texture_mirror_clamp_to_edge 1
+
+#define GL_MIRROR_CLAMP_TO_EDGE 0x8743
+
+#define GLEW_ARB_texture_mirror_clamp_to_edge GLEW_GET_VAR(__GLEW_ARB_texture_mirror_clamp_to_edge)
+
+#endif /* GL_ARB_texture_mirror_clamp_to_edge */
+
/* --------------------- GL_ARB_texture_mirrored_repeat -------------------- */
#ifndef GL_ARB_texture_mirrored_repeat
@@ -5326,6 +6342,15 @@ typedef void (GLAPIENTRY * PFNGLTEXIMAGE3DMULTISAMPLEPROC) (GLenum target, GLsiz
#endif /* GL_ARB_texture_non_power_of_two */
+/* ---------------------- GL_ARB_texture_query_levels ---------------------- */
+
+#ifndef GL_ARB_texture_query_levels
+#define GL_ARB_texture_query_levels 1
+
+#define GLEW_ARB_texture_query_levels GLEW_GET_VAR(__GLEW_ARB_texture_query_levels)
+
+#endif /* GL_ARB_texture_query_levels */
+
/* ------------------------ GL_ARB_texture_query_lod ----------------------- */
#ifndef GL_ARB_texture_query_lod
@@ -5356,7 +6381,6 @@ typedef void (GLAPIENTRY * PFNGLTEXIMAGE3DMULTISAMPLEPROC) (GLenum target, GLsiz
#ifndef GL_ARB_texture_rg
#define GL_ARB_texture_rg 1
-#define GL_RED 0x1903
#define GL_COMPRESSED_RED 0x8225
#define GL_COMPRESSED_RG 0x8226
#define GL_RG 0x8227
@@ -5397,14 +6421,23 @@ typedef void (GLAPIENTRY * PFNGLTEXIMAGE3DMULTISAMPLEPROC) (GLenum target, GLsiz
#endif /* GL_ARB_texture_rgb10_a2ui */
+/* ------------------------ GL_ARB_texture_stencil8 ------------------------ */
+
+#ifndef GL_ARB_texture_stencil8
+#define GL_ARB_texture_stencil8 1
+
+#define GL_STENCIL_INDEX 0x1901
+#define GL_STENCIL_INDEX8 0x8D48
+
+#define GLEW_ARB_texture_stencil8 GLEW_GET_VAR(__GLEW_ARB_texture_stencil8)
+
+#endif /* GL_ARB_texture_stencil8 */
+
/* ------------------------- GL_ARB_texture_storage ------------------------ */
#ifndef GL_ARB_texture_storage
#define GL_ARB_texture_storage 1
-#define GL_ALPHA8_EXT 0x803C
-#define GL_LUMINANCE8_EXT 0x8040
-#define GL_LUMINANCE8_ALPHA8_EXT 0x8045
#define GL_TEXTURE_IMMUTABLE_FORMAT 0x912F
typedef void (GLAPIENTRY * PFNGLTEXSTORAGE1DPROC) (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width);
@@ -5425,6 +6458,25 @@ typedef void (GLAPIENTRY * PFNGLTEXTURESTORAGE3DEXTPROC) (GLuint texture, GLenum
#endif /* GL_ARB_texture_storage */
+/* ------------------- GL_ARB_texture_storage_multisample ------------------ */
+
+#ifndef GL_ARB_texture_storage_multisample
+#define GL_ARB_texture_storage_multisample 1
+
+typedef void (GLAPIENTRY * PFNGLTEXSTORAGE2DMULTISAMPLEPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations);
+typedef void (GLAPIENTRY * PFNGLTEXSTORAGE3DMULTISAMPLEPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedsamplelocations);
+typedef void (GLAPIENTRY * PFNGLTEXTURESTORAGE2DMULTISAMPLEEXTPROC) (GLuint texture, GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations);
+typedef void (GLAPIENTRY * PFNGLTEXTURESTORAGE3DMULTISAMPLEEXTPROC) (GLuint texture, GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedsamplelocations);
+
+#define glTexStorage2DMultisample GLEW_GET_FUN(__glewTexStorage2DMultisample)
+#define glTexStorage3DMultisample GLEW_GET_FUN(__glewTexStorage3DMultisample)
+#define glTextureStorage2DMultisampleEXT GLEW_GET_FUN(__glewTextureStorage2DMultisampleEXT)
+#define glTextureStorage3DMultisampleEXT GLEW_GET_FUN(__glewTextureStorage3DMultisampleEXT)
+
+#define GLEW_ARB_texture_storage_multisample GLEW_GET_VAR(__GLEW_ARB_texture_storage_multisample)
+
+#endif /* GL_ARB_texture_storage_multisample */
+
/* ------------------------- GL_ARB_texture_swizzle ------------------------ */
#ifndef GL_ARB_texture_swizzle
@@ -5440,6 +6492,25 @@ typedef void (GLAPIENTRY * PFNGLTEXTURESTORAGE3DEXTPROC) (GLuint texture, GLenum
#endif /* GL_ARB_texture_swizzle */
+/* -------------------------- GL_ARB_texture_view -------------------------- */
+
+#ifndef GL_ARB_texture_view
+#define GL_ARB_texture_view 1
+
+#define GL_TEXTURE_VIEW_MIN_LEVEL 0x82DB
+#define GL_TEXTURE_VIEW_NUM_LEVELS 0x82DC
+#define GL_TEXTURE_VIEW_MIN_LAYER 0x82DD
+#define GL_TEXTURE_VIEW_NUM_LAYERS 0x82DE
+#define GL_TEXTURE_IMMUTABLE_LEVELS 0x82DF
+
+typedef void (GLAPIENTRY * PFNGLTEXTUREVIEWPROC) (GLuint texture, GLenum target, GLuint origtexture, GLenum internalformat, GLuint minlevel, GLuint numlevels, GLuint minlayer, GLuint numlayers);
+
+#define glTextureView GLEW_GET_FUN(__glewTextureView)
+
+#define GLEW_ARB_texture_view GLEW_GET_VAR(__GLEW_ARB_texture_view)
+
+#endif /* GL_ARB_texture_view */
+
/* --------------------------- GL_ARB_timer_query -------------------------- */
#ifndef GL_ARB_timer_query
@@ -5592,13 +6663,13 @@ typedef void (GLAPIENTRY * PFNGLMULTTRANSPOSEMATRIXFARBPROC) (GLfloat m[16]);
typedef void (GLAPIENTRY * PFNGLBINDBUFFERBASEPROC) (GLenum target, GLuint index, GLuint buffer);
typedef void (GLAPIENTRY * PFNGLBINDBUFFERRANGEPROC) (GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size);
-typedef void (GLAPIENTRY * PFNGLGETACTIVEUNIFORMBLOCKNAMEPROC) (GLuint program, GLuint uniformBlockIndex, GLsizei bufSize, GLsizei* length, char* uniformBlockName);
+typedef void (GLAPIENTRY * PFNGLGETACTIVEUNIFORMBLOCKNAMEPROC) (GLuint program, GLuint uniformBlockIndex, GLsizei bufSize, GLsizei* length, GLchar* uniformBlockName);
typedef void (GLAPIENTRY * PFNGLGETACTIVEUNIFORMBLOCKIVPROC) (GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint* params);
-typedef void (GLAPIENTRY * PFNGLGETACTIVEUNIFORMNAMEPROC) (GLuint program, GLuint uniformIndex, GLsizei bufSize, GLsizei* length, char* uniformName);
+typedef void (GLAPIENTRY * PFNGLGETACTIVEUNIFORMNAMEPROC) (GLuint program, GLuint uniformIndex, GLsizei bufSize, GLsizei* length, GLchar* uniformName);
typedef void (GLAPIENTRY * PFNGLGETACTIVEUNIFORMSIVPROC) (GLuint program, GLsizei uniformCount, const GLuint* uniformIndices, GLenum pname, GLint* params);
typedef void (GLAPIENTRY * PFNGLGETINTEGERI_VPROC) (GLenum target, GLuint index, GLint* data);
-typedef GLuint (GLAPIENTRY * PFNGLGETUNIFORMBLOCKINDEXPROC) (GLuint program, const char* uniformBlockName);
-typedef void (GLAPIENTRY * PFNGLGETUNIFORMINDICESPROC) (GLuint program, GLsizei uniformCount, const char** uniformNames, GLuint* uniformIndices);
+typedef GLuint (GLAPIENTRY * PFNGLGETUNIFORMBLOCKINDEXPROC) (GLuint program, const GLchar* uniformBlockName);
+typedef void (GLAPIENTRY * PFNGLGETUNIFORMINDICESPROC) (GLuint program, GLsizei uniformCount, const GLchar** uniformNames, GLuint* uniformIndices);
typedef void (GLAPIENTRY * PFNGLUNIFORMBLOCKBINDINGPROC) (GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding);
#define glBindBufferBase GLEW_GET_FUN(__glewBindBufferBase)
@@ -5653,13 +6724,6 @@ typedef GLboolean (GLAPIENTRY * PFNGLISVERTEXARRAYPROC) (GLuint array);
#ifndef GL_ARB_vertex_attrib_64bit
#define GL_ARB_vertex_attrib_64bit 1
-#define GL_DOUBLE_MAT2 0x8F46
-#define GL_DOUBLE_MAT3 0x8F47
-#define GL_DOUBLE_MAT4 0x8F48
-#define GL_DOUBLE_VEC2 0x8FFC
-#define GL_DOUBLE_VEC3 0x8FFD
-#define GL_DOUBLE_VEC4 0x8FFE
-
typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBLDVPROC) (GLuint index, GLenum pname, GLdouble* params);
typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL1DPROC) (GLuint index, GLdouble x);
typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL1DVPROC) (GLuint index, const GLdouble* v);
@@ -5686,6 +6750,37 @@ typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBLPOINTERPROC) (GLuint index, GLint s
#endif /* GL_ARB_vertex_attrib_64bit */
+/* ---------------------- GL_ARB_vertex_attrib_binding --------------------- */
+
+#ifndef GL_ARB_vertex_attrib_binding
+#define GL_ARB_vertex_attrib_binding 1
+
+#define GL_VERTEX_ATTRIB_BINDING 0x82D4
+#define GL_VERTEX_ATTRIB_RELATIVE_OFFSET 0x82D5
+#define GL_VERTEX_BINDING_DIVISOR 0x82D6
+#define GL_VERTEX_BINDING_OFFSET 0x82D7
+#define GL_VERTEX_BINDING_STRIDE 0x82D8
+#define GL_MAX_VERTEX_ATTRIB_RELATIVE_OFFSET 0x82D9
+#define GL_MAX_VERTEX_ATTRIB_BINDINGS 0x82DA
+
+typedef void (GLAPIENTRY * PFNGLBINDVERTEXBUFFERPROC) (GLuint bindingindex, GLuint buffer, GLintptr offset, GLsizei stride);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBBINDINGPROC) (GLuint attribindex, GLuint bindingindex);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBFORMATPROC) (GLuint attribindex, GLint size, GLenum type, GLboolean normalized, GLuint relativeoffset);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBIFORMATPROC) (GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBLFORMATPROC) (GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset);
+typedef void (GLAPIENTRY * PFNGLVERTEXBINDINGDIVISORPROC) (GLuint bindingindex, GLuint divisor);
+
+#define glBindVertexBuffer GLEW_GET_FUN(__glewBindVertexBuffer)
+#define glVertexAttribBinding GLEW_GET_FUN(__glewVertexAttribBinding)
+#define glVertexAttribFormat GLEW_GET_FUN(__glewVertexAttribFormat)
+#define glVertexAttribIFormat GLEW_GET_FUN(__glewVertexAttribIFormat)
+#define glVertexAttribLFormat GLEW_GET_FUN(__glewVertexAttribLFormat)
+#define glVertexBindingDivisor GLEW_GET_FUN(__glewVertexBindingDivisor)
+
+#define GLEW_ARB_vertex_attrib_binding GLEW_GET_VAR(__GLEW_ARB_vertex_attrib_binding)
+
+#endif /* GL_ARB_vertex_attrib_binding */
+
/* -------------------------- GL_ARB_vertex_blend -------------------------- */
#ifndef GL_ARB_vertex_blend
@@ -5801,13 +6896,13 @@ typedef ptrdiff_t GLintptrARB;
typedef ptrdiff_t GLsizeiptrARB;
typedef void (GLAPIENTRY * PFNGLBINDBUFFERARBPROC) (GLenum target, GLuint buffer);
-typedef void (GLAPIENTRY * PFNGLBUFFERDATAARBPROC) (GLenum target, GLsizeiptrARB size, const GLvoid* data, GLenum usage);
-typedef void (GLAPIENTRY * PFNGLBUFFERSUBDATAARBPROC) (GLenum target, GLintptrARB offset, GLsizeiptrARB size, const GLvoid* data);
+typedef void (GLAPIENTRY * PFNGLBUFFERDATAARBPROC) (GLenum target, GLsizeiptrARB size, const GLvoid *data, GLenum usage);
+typedef void (GLAPIENTRY * PFNGLBUFFERSUBDATAARBPROC) (GLenum target, GLintptrARB offset, GLsizeiptrARB size, const GLvoid *data);
typedef void (GLAPIENTRY * PFNGLDELETEBUFFERSARBPROC) (GLsizei n, const GLuint* buffers);
typedef void (GLAPIENTRY * PFNGLGENBUFFERSARBPROC) (GLsizei n, GLuint* buffers);
typedef void (GLAPIENTRY * PFNGLGETBUFFERPARAMETERIVARBPROC) (GLenum target, GLenum pname, GLint* params);
typedef void (GLAPIENTRY * PFNGLGETBUFFERPOINTERVARBPROC) (GLenum target, GLenum pname, GLvoid** params);
-typedef void (GLAPIENTRY * PFNGLGETBUFFERSUBDATAARBPROC) (GLenum target, GLintptrARB offset, GLsizeiptrARB size, GLvoid* data);
+typedef void (GLAPIENTRY * PFNGLGETBUFFERSUBDATAARBPROC) (GLenum target, GLintptrARB offset, GLsizeiptrARB size, GLvoid *data);
typedef GLboolean (GLAPIENTRY * PFNGLISBUFFERARBPROC) (GLuint buffer);
typedef GLvoid * (GLAPIENTRY * PFNGLMAPBUFFERARBPROC) (GLenum target, GLenum access);
typedef GLboolean (GLAPIENTRY * PFNGLUNMAPBUFFERARBPROC) (GLenum target);
@@ -5922,7 +7017,7 @@ typedef void (GLAPIENTRY * PFNGLGETPROGRAMENVPARAMETERDVARBPROC) (GLenum target,
typedef void (GLAPIENTRY * PFNGLGETPROGRAMENVPARAMETERFVARBPROC) (GLenum target, GLuint index, GLfloat* params);
typedef void (GLAPIENTRY * PFNGLGETPROGRAMLOCALPARAMETERDVARBPROC) (GLenum target, GLuint index, GLdouble* params);
typedef void (GLAPIENTRY * PFNGLGETPROGRAMLOCALPARAMETERFVARBPROC) (GLenum target, GLuint index, GLfloat* params);
-typedef void (GLAPIENTRY * PFNGLGETPROGRAMSTRINGARBPROC) (GLenum target, GLenum pname, void* string);
+typedef void (GLAPIENTRY * PFNGLGETPROGRAMSTRINGARBPROC) (GLenum target, GLenum pname, GLvoid *string);
typedef void (GLAPIENTRY * PFNGLGETPROGRAMIVARBPROC) (GLenum target, GLenum pname, GLint* params);
typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBPOINTERVARBPROC) (GLuint index, GLenum pname, GLvoid** pointer);
typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBDVARBPROC) (GLuint index, GLenum pname, GLdouble* params);
@@ -5937,7 +7032,7 @@ typedef void (GLAPIENTRY * PFNGLPROGRAMLOCALPARAMETER4DARBPROC) (GLenum target,
typedef void (GLAPIENTRY * PFNGLPROGRAMLOCALPARAMETER4DVARBPROC) (GLenum target, GLuint index, const GLdouble* params);
typedef void (GLAPIENTRY * PFNGLPROGRAMLOCALPARAMETER4FARBPROC) (GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
typedef void (GLAPIENTRY * PFNGLPROGRAMLOCALPARAMETER4FVARBPROC) (GLenum target, GLuint index, const GLfloat* params);
-typedef void (GLAPIENTRY * PFNGLPROGRAMSTRINGARBPROC) (GLenum target, GLenum format, GLsizei len, const void* string);
+typedef void (GLAPIENTRY * PFNGLPROGRAMSTRINGARBPROC) (GLenum target, GLenum format, GLsizei len, const GLvoid *string);
typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB1DARBPROC) (GLuint index, GLdouble x);
typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB1DVARBPROC) (GLuint index, const GLdouble* v);
typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB1FARBPROC) (GLuint index, GLfloat x);
@@ -5974,7 +7069,7 @@ typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4SVARBPROC) (GLuint index, const GLs
typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4UBVARBPROC) (GLuint index, const GLubyte* v);
typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4UIVARBPROC) (GLuint index, const GLuint* v);
typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4USVARBPROC) (GLuint index, const GLushort* v);
-typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBPOINTERARBPROC) (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void* pointer);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBPOINTERARBPROC) (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid *pointer);
#define glBindProgramARB GLEW_GET_FUN(__glewBindProgramARB)
#define glDeleteProgramsARB GLEW_GET_FUN(__glewDeleteProgramsARB)
@@ -6068,6 +7163,17 @@ typedef GLint (GLAPIENTRY * PFNGLGETATTRIBLOCATIONARBPROC) (GLhandleARB programO
#endif /* GL_ARB_vertex_shader */
+/* ------------------- GL_ARB_vertex_type_10f_11f_11f_rev ------------------ */
+
+#ifndef GL_ARB_vertex_type_10f_11f_11f_rev
+#define GL_ARB_vertex_type_10f_11f_11f_rev 1
+
+#define GL_UNSIGNED_INT_10F_11F_11F_REV 0x8C3B
+
+#define GLEW_ARB_vertex_type_10f_11f_11f_rev GLEW_GET_VAR(__GLEW_ARB_vertex_type_10f_11f_11f_rev)
+
+#endif /* GL_ARB_vertex_type_10f_11f_11f_rev */
+
/* ------------------- GL_ARB_vertex_type_2_10_10_10_rev ------------------- */
#ifndef GL_ARB_vertex_type_2_10_10_10_rev
@@ -6341,7 +7447,7 @@ typedef void (GLAPIENTRY * PFNGLDRAWBUFFERSATIPROC) (GLsizei n, const GLenum* bu
typedef void (GLAPIENTRY * PFNGLDRAWELEMENTARRAYATIPROC) (GLenum mode, GLsizei count);
typedef void (GLAPIENTRY * PFNGLDRAWRANGEELEMENTARRAYATIPROC) (GLenum mode, GLuint start, GLuint end, GLsizei count);
-typedef void (GLAPIENTRY * PFNGLELEMENTPOINTERATIPROC) (GLenum type, const void* pointer);
+typedef void (GLAPIENTRY * PFNGLELEMENTPOINTERATIPROC) (GLenum type, const GLvoid *pointer);
#define glDrawElementArrayATI GLEW_GET_FUN(__glewDrawElementArrayATI)
#define glDrawRangeElementArrayATI GLEW_GET_FUN(__glewDrawRangeElementArrayATI)
@@ -6478,7 +7584,7 @@ typedef void (GLAPIENTRY * PFNGLSETFRAGMENTSHADERCONSTANTATIPROC) (GLuint dst, c
#ifndef GL_ATI_map_object_buffer
#define GL_ATI_map_object_buffer 1
-typedef void* (GLAPIENTRY * PFNGLMAPOBJECTBUFFERATIPROC) (GLuint buffer);
+typedef GLvoid * (GLAPIENTRY * PFNGLMAPOBJECTBUFFERATIPROC) (GLuint buffer);
typedef void (GLAPIENTRY * PFNGLUNMAPOBJECTBUFFERATIPROC) (GLuint buffer);
#define glMapObjectBufferATI GLEW_GET_FUN(__glewMapObjectBufferATI)
@@ -6647,8 +7753,8 @@ typedef void (GLAPIENTRY * PFNGLGETOBJECTBUFFERIVATIPROC) (GLuint buffer, GLenum
typedef void (GLAPIENTRY * PFNGLGETVARIANTARRAYOBJECTFVATIPROC) (GLuint id, GLenum pname, GLfloat* params);
typedef void (GLAPIENTRY * PFNGLGETVARIANTARRAYOBJECTIVATIPROC) (GLuint id, GLenum pname, GLint* params);
typedef GLboolean (GLAPIENTRY * PFNGLISOBJECTBUFFERATIPROC) (GLuint buffer);
-typedef GLuint (GLAPIENTRY * PFNGLNEWOBJECTBUFFERATIPROC) (GLsizei size, const void* pointer, GLenum usage);
-typedef void (GLAPIENTRY * PFNGLUPDATEOBJECTBUFFERATIPROC) (GLuint buffer, GLuint offset, GLsizei size, const void* pointer, GLenum preserve);
+typedef GLuint (GLAPIENTRY * PFNGLNEWOBJECTBUFFERATIPROC) (GLsizei size, const GLvoid *pointer, GLenum usage);
+typedef void (GLAPIENTRY * PFNGLUPDATEOBJECTBUFFERATIPROC) (GLuint buffer, GLuint offset, GLsizei size, const GLvoid *pointer, GLenum preserve);
typedef void (GLAPIENTRY * PFNGLVARIANTARRAYOBJECTATIPROC) (GLuint id, GLenum type, GLsizei stride, GLuint buffer, GLuint offset);
#define glArrayObjectATI GLEW_GET_FUN(__glewArrayObjectATI)
@@ -6703,41 +7809,49 @@ typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBARRAYOBJECTATIPROC) (GLuint index, G
typedef void (GLAPIENTRY * PFNGLCLIENTACTIVEVERTEXSTREAMATIPROC) (GLenum stream);
typedef void (GLAPIENTRY * PFNGLNORMALSTREAM3BATIPROC) (GLenum stream, GLbyte x, GLbyte y, GLbyte z);
-typedef void (GLAPIENTRY * PFNGLNORMALSTREAM3BVATIPROC) (GLenum stream, const GLbyte *v);
+typedef void (GLAPIENTRY * PFNGLNORMALSTREAM3BVATIPROC) (GLenum stream, const GLbyte *coords);
typedef void (GLAPIENTRY * PFNGLNORMALSTREAM3DATIPROC) (GLenum stream, GLdouble x, GLdouble y, GLdouble z);
-typedef void (GLAPIENTRY * PFNGLNORMALSTREAM3DVATIPROC) (GLenum stream, const GLdouble *v);
+typedef void (GLAPIENTRY * PFNGLNORMALSTREAM3DVATIPROC) (GLenum stream, const GLdouble *coords);
typedef void (GLAPIENTRY * PFNGLNORMALSTREAM3FATIPROC) (GLenum stream, GLfloat x, GLfloat y, GLfloat z);
-typedef void (GLAPIENTRY * PFNGLNORMALSTREAM3FVATIPROC) (GLenum stream, const GLfloat *v);
+typedef void (GLAPIENTRY * PFNGLNORMALSTREAM3FVATIPROC) (GLenum stream, const GLfloat *coords);
typedef void (GLAPIENTRY * PFNGLNORMALSTREAM3IATIPROC) (GLenum stream, GLint x, GLint y, GLint z);
-typedef void (GLAPIENTRY * PFNGLNORMALSTREAM3IVATIPROC) (GLenum stream, const GLint *v);
+typedef void (GLAPIENTRY * PFNGLNORMALSTREAM3IVATIPROC) (GLenum stream, const GLint *coords);
typedef void (GLAPIENTRY * PFNGLNORMALSTREAM3SATIPROC) (GLenum stream, GLshort x, GLshort y, GLshort z);
-typedef void (GLAPIENTRY * PFNGLNORMALSTREAM3SVATIPROC) (GLenum stream, const GLshort *v);
+typedef void (GLAPIENTRY * PFNGLNORMALSTREAM3SVATIPROC) (GLenum stream, const GLshort *coords);
typedef void (GLAPIENTRY * PFNGLVERTEXBLENDENVFATIPROC) (GLenum pname, GLfloat param);
typedef void (GLAPIENTRY * PFNGLVERTEXBLENDENVIATIPROC) (GLenum pname, GLint param);
+typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM1DATIPROC) (GLenum stream, GLdouble x);
+typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM1DVATIPROC) (GLenum stream, const GLdouble *coords);
+typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM1FATIPROC) (GLenum stream, GLfloat x);
+typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM1FVATIPROC) (GLenum stream, const GLfloat *coords);
+typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM1IATIPROC) (GLenum stream, GLint x);
+typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM1IVATIPROC) (GLenum stream, const GLint *coords);
+typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM1SATIPROC) (GLenum stream, GLshort x);
+typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM1SVATIPROC) (GLenum stream, const GLshort *coords);
typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM2DATIPROC) (GLenum stream, GLdouble x, GLdouble y);
-typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM2DVATIPROC) (GLenum stream, const GLdouble *v);
+typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM2DVATIPROC) (GLenum stream, const GLdouble *coords);
typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM2FATIPROC) (GLenum stream, GLfloat x, GLfloat y);
-typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM2FVATIPROC) (GLenum stream, const GLfloat *v);
+typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM2FVATIPROC) (GLenum stream, const GLfloat *coords);
typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM2IATIPROC) (GLenum stream, GLint x, GLint y);
-typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM2IVATIPROC) (GLenum stream, const GLint *v);
+typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM2IVATIPROC) (GLenum stream, const GLint *coords);
typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM2SATIPROC) (GLenum stream, GLshort x, GLshort y);
-typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM2SVATIPROC) (GLenum stream, const GLshort *v);
+typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM2SVATIPROC) (GLenum stream, const GLshort *coords);
typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM3DATIPROC) (GLenum stream, GLdouble x, GLdouble y, GLdouble z);
-typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM3DVATIPROC) (GLenum stream, const GLdouble *v);
+typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM3DVATIPROC) (GLenum stream, const GLdouble *coords);
typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM3FATIPROC) (GLenum stream, GLfloat x, GLfloat y, GLfloat z);
-typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM3FVATIPROC) (GLenum stream, const GLfloat *v);
+typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM3FVATIPROC) (GLenum stream, const GLfloat *coords);
typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM3IATIPROC) (GLenum stream, GLint x, GLint y, GLint z);
-typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM3IVATIPROC) (GLenum stream, const GLint *v);
+typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM3IVATIPROC) (GLenum stream, const GLint *coords);
typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM3SATIPROC) (GLenum stream, GLshort x, GLshort y, GLshort z);
-typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM3SVATIPROC) (GLenum stream, const GLshort *v);
+typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM3SVATIPROC) (GLenum stream, const GLshort *coords);
typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM4DATIPROC) (GLenum stream, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
-typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM4DVATIPROC) (GLenum stream, const GLdouble *v);
+typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM4DVATIPROC) (GLenum stream, const GLdouble *coords);
typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM4FATIPROC) (GLenum stream, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
-typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM4FVATIPROC) (GLenum stream, const GLfloat *v);
+typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM4FVATIPROC) (GLenum stream, const GLfloat *coords);
typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM4IATIPROC) (GLenum stream, GLint x, GLint y, GLint z, GLint w);
-typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM4IVATIPROC) (GLenum stream, const GLint *v);
+typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM4IVATIPROC) (GLenum stream, const GLint *coords);
typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM4SATIPROC) (GLenum stream, GLshort x, GLshort y, GLshort z, GLshort w);
-typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM4SVATIPROC) (GLenum stream, const GLshort *v);
+typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM4SVATIPROC) (GLenum stream, const GLshort *coords);
#define glClientActiveVertexStreamATI GLEW_GET_FUN(__glewClientActiveVertexStreamATI)
#define glNormalStream3bATI GLEW_GET_FUN(__glewNormalStream3bATI)
@@ -6752,6 +7866,14 @@ typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM4SVATIPROC) (GLenum stream, const GL
#define glNormalStream3svATI GLEW_GET_FUN(__glewNormalStream3svATI)
#define glVertexBlendEnvfATI GLEW_GET_FUN(__glewVertexBlendEnvfATI)
#define glVertexBlendEnviATI GLEW_GET_FUN(__glewVertexBlendEnviATI)
+#define glVertexStream1dATI GLEW_GET_FUN(__glewVertexStream1dATI)
+#define glVertexStream1dvATI GLEW_GET_FUN(__glewVertexStream1dvATI)
+#define glVertexStream1fATI GLEW_GET_FUN(__glewVertexStream1fATI)
+#define glVertexStream1fvATI GLEW_GET_FUN(__glewVertexStream1fvATI)
+#define glVertexStream1iATI GLEW_GET_FUN(__glewVertexStream1iATI)
+#define glVertexStream1ivATI GLEW_GET_FUN(__glewVertexStream1ivATI)
+#define glVertexStream1sATI GLEW_GET_FUN(__glewVertexStream1sATI)
+#define glVertexStream1svATI GLEW_GET_FUN(__glewVertexStream1svATI)
#define glVertexStream2dATI GLEW_GET_FUN(__glewVertexStream2dATI)
#define glVertexStream2dvATI GLEW_GET_FUN(__glewVertexStream2dvATI)
#define glVertexStream2fATI GLEW_GET_FUN(__glewVertexStream2fATI)
@@ -6976,7 +8098,7 @@ typedef void (GLAPIENTRY * PFNGLBLENDEQUATIONEXTPROC) (GLenum mode);
#ifndef GL_EXT_color_subtable
#define GL_EXT_color_subtable 1
-typedef void (GLAPIENTRY * PFNGLCOLORSUBTABLEEXTPROC) (GLenum target, GLsizei start, GLsizei count, GLenum format, GLenum type, const void* data);
+typedef void (GLAPIENTRY * PFNGLCOLORSUBTABLEEXTPROC) (GLenum target, GLsizei start, GLsizei count, GLenum format, GLenum type, const GLvoid *data);
typedef void (GLAPIENTRY * PFNGLCOPYCOLORSUBTABLEEXTPROC) (GLenum target, GLsizei start, GLint x, GLint y, GLsizei width);
#define glColorSubTableEXT GLEW_GET_FUN(__glewColorSubTableEXT)
@@ -7030,19 +8152,19 @@ typedef void (GLAPIENTRY * PFNGLUNLOCKARRAYSEXTPROC) (void);
#define GL_POST_CONVOLUTION_BLUE_BIAS_EXT 0x8022
#define GL_POST_CONVOLUTION_ALPHA_BIAS_EXT 0x8023
-typedef void (GLAPIENTRY * PFNGLCONVOLUTIONFILTER1DEXTPROC) (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const void* image);
-typedef void (GLAPIENTRY * PFNGLCONVOLUTIONFILTER2DEXTPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const void* image);
+typedef void (GLAPIENTRY * PFNGLCONVOLUTIONFILTER1DEXTPROC) (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const GLvoid *image);
+typedef void (GLAPIENTRY * PFNGLCONVOLUTIONFILTER2DEXTPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *image);
typedef void (GLAPIENTRY * PFNGLCONVOLUTIONPARAMETERFEXTPROC) (GLenum target, GLenum pname, GLfloat param);
typedef void (GLAPIENTRY * PFNGLCONVOLUTIONPARAMETERFVEXTPROC) (GLenum target, GLenum pname, const GLfloat* params);
typedef void (GLAPIENTRY * PFNGLCONVOLUTIONPARAMETERIEXTPROC) (GLenum target, GLenum pname, GLint param);
typedef void (GLAPIENTRY * PFNGLCONVOLUTIONPARAMETERIVEXTPROC) (GLenum target, GLenum pname, const GLint* params);
typedef void (GLAPIENTRY * PFNGLCOPYCONVOLUTIONFILTER1DEXTPROC) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width);
typedef void (GLAPIENTRY * PFNGLCOPYCONVOLUTIONFILTER2DEXTPROC) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height);
-typedef void (GLAPIENTRY * PFNGLGETCONVOLUTIONFILTEREXTPROC) (GLenum target, GLenum format, GLenum type, void* image);
+typedef void (GLAPIENTRY * PFNGLGETCONVOLUTIONFILTEREXTPROC) (GLenum target, GLenum format, GLenum type, GLvoid *image);
typedef void (GLAPIENTRY * PFNGLGETCONVOLUTIONPARAMETERFVEXTPROC) (GLenum target, GLenum pname, GLfloat* params);
typedef void (GLAPIENTRY * PFNGLGETCONVOLUTIONPARAMETERIVEXTPROC) (GLenum target, GLenum pname, GLint* params);
-typedef void (GLAPIENTRY * PFNGLGETSEPARABLEFILTEREXTPROC) (GLenum target, GLenum format, GLenum type, void* row, void* column, void* span);
-typedef void (GLAPIENTRY * PFNGLSEPARABLEFILTER2DEXTPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const void* row, const void* column);
+typedef void (GLAPIENTRY * PFNGLGETSEPARABLEFILTEREXTPROC) (GLenum target, GLenum format, GLenum type, GLvoid *row, GLvoid *column, GLvoid *span);
+typedef void (GLAPIENTRY * PFNGLSEPARABLEFILTER2DEXTPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *row, const GLvoid *column);
#define glConvolutionFilter1DEXT GLEW_GET_FUN(__glewConvolutionFilter1DEXT)
#define glConvolutionFilter2DEXT GLEW_GET_FUN(__glewConvolutionFilter2DEXT)
@@ -7082,8 +8204,8 @@ typedef void (GLAPIENTRY * PFNGLSEPARABLEFILTER2DEXTPROC) (GLenum target, GLenum
#define GL_MAP1_BINORMAL_EXT 0x8446
#define GL_MAP2_BINORMAL_EXT 0x8447
-typedef void (GLAPIENTRY * PFNGLBINORMALPOINTEREXTPROC) (GLenum type, GLsizei stride, void* pointer);
-typedef void (GLAPIENTRY * PFNGLTANGENTPOINTEREXTPROC) (GLenum type, GLsizei stride, void* pointer);
+typedef void (GLAPIENTRY * PFNGLBINORMALPOINTEREXTPROC) (GLenum type, GLsizei stride, GLvoid *pointer);
+typedef void (GLAPIENTRY * PFNGLTANGENTPOINTEREXTPROC) (GLenum type, GLsizei stride, GLvoid *pointer);
#define glBinormalPointerEXT GLEW_GET_FUN(__glewBinormalPointerEXT)
#define glTangentPointerEXT GLEW_GET_FUN(__glewTangentPointerEXT)
@@ -7132,6 +8254,23 @@ typedef void (GLAPIENTRY * PFNGLCULLPARAMETERFVEXTPROC) (GLenum pname, GLfloat*
#endif /* GL_EXT_cull_vertex */
+/* -------------------------- GL_EXT_debug_marker -------------------------- */
+
+#ifndef GL_EXT_debug_marker
+#define GL_EXT_debug_marker 1
+
+typedef void (GLAPIENTRY * PFNGLINSERTEVENTMARKEREXTPROC) (GLsizei length, const GLchar* marker);
+typedef void (GLAPIENTRY * PFNGLPOPGROUPMARKEREXTPROC) (void);
+typedef void (GLAPIENTRY * PFNGLPUSHGROUPMARKEREXTPROC) (GLsizei length, const GLchar* marker);
+
+#define glInsertEventMarkerEXT GLEW_GET_FUN(__glewInsertEventMarkerEXT)
+#define glPopGroupMarkerEXT GLEW_GET_FUN(__glewPopGroupMarkerEXT)
+#define glPushGroupMarkerEXT GLEW_GET_FUN(__glewPushGroupMarkerEXT)
+
+#define GLEW_EXT_debug_marker GLEW_GET_VAR(__GLEW_EXT_debug_marker)
+
+#endif /* GL_EXT_debug_marker */
+
/* ------------------------ GL_EXT_depth_bounds_test ----------------------- */
#ifndef GL_EXT_depth_bounds_test
@@ -7160,18 +8299,18 @@ typedef void (GLAPIENTRY * PFNGLDEPTHBOUNDSEXTPROC) (GLclampd zmin, GLclampd zma
typedef void (GLAPIENTRY * PFNGLBINDMULTITEXTUREEXTPROC) (GLenum texunit, GLenum target, GLuint texture);
typedef GLenum (GLAPIENTRY * PFNGLCHECKNAMEDFRAMEBUFFERSTATUSEXTPROC) (GLuint framebuffer, GLenum target);
typedef void (GLAPIENTRY * PFNGLCLIENTATTRIBDEFAULTEXTPROC) (GLbitfield mask);
-typedef void (GLAPIENTRY * PFNGLCOMPRESSEDMULTITEXIMAGE1DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const void* data);
-typedef void (GLAPIENTRY * PFNGLCOMPRESSEDMULTITEXIMAGE2DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void* data);
-typedef void (GLAPIENTRY * PFNGLCOMPRESSEDMULTITEXIMAGE3DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void* data);
-typedef void (GLAPIENTRY * PFNGLCOMPRESSEDMULTITEXSUBIMAGE1DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const void* data);
-typedef void (GLAPIENTRY * PFNGLCOMPRESSEDMULTITEXSUBIMAGE2DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void* data);
-typedef void (GLAPIENTRY * PFNGLCOMPRESSEDMULTITEXSUBIMAGE3DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void* data);
-typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXTUREIMAGE1DEXTPROC) (GLuint texture, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const void* data);
-typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXTUREIMAGE2DEXTPROC) (GLuint texture, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void* data);
-typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXTUREIMAGE3DEXTPROC) (GLuint texture, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void* data);
-typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXTURESUBIMAGE1DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const void* data);
-typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXTURESUBIMAGE2DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void* data);
-typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXTURESUBIMAGE3DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void* data);
+typedef void (GLAPIENTRY * PFNGLCOMPRESSEDMULTITEXIMAGE1DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const GLvoid *data);
+typedef void (GLAPIENTRY * PFNGLCOMPRESSEDMULTITEXIMAGE2DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *data);
+typedef void (GLAPIENTRY * PFNGLCOMPRESSEDMULTITEXIMAGE3DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid *data);
+typedef void (GLAPIENTRY * PFNGLCOMPRESSEDMULTITEXSUBIMAGE1DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const GLvoid *data);
+typedef void (GLAPIENTRY * PFNGLCOMPRESSEDMULTITEXSUBIMAGE2DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid *data);
+typedef void (GLAPIENTRY * PFNGLCOMPRESSEDMULTITEXSUBIMAGE3DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid *data);
+typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXTUREIMAGE1DEXTPROC) (GLuint texture, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const GLvoid *data);
+typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXTUREIMAGE2DEXTPROC) (GLuint texture, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *data);
+typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXTUREIMAGE3DEXTPROC) (GLuint texture, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid *data);
+typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXTURESUBIMAGE1DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const GLvoid *data);
+typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXTURESUBIMAGE2DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid *data);
+typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXTURESUBIMAGE3DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid *data);
typedef void (GLAPIENTRY * PFNGLCOPYMULTITEXIMAGE1DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLint border);
typedef void (GLAPIENTRY * PFNGLCOPYMULTITEXIMAGE2DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border);
typedef void (GLAPIENTRY * PFNGLCOPYMULTITEXSUBIMAGE1DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width);
@@ -7196,8 +8335,8 @@ typedef void (GLAPIENTRY * PFNGLFRAMEBUFFERDRAWBUFFERSEXTPROC) (GLuint framebuff
typedef void (GLAPIENTRY * PFNGLFRAMEBUFFERREADBUFFEREXTPROC) (GLuint framebuffer, GLenum mode);
typedef void (GLAPIENTRY * PFNGLGENERATEMULTITEXMIPMAPEXTPROC) (GLenum texunit, GLenum target);
typedef void (GLAPIENTRY * PFNGLGENERATETEXTUREMIPMAPEXTPROC) (GLuint texture, GLenum target);
-typedef void (GLAPIENTRY * PFNGLGETCOMPRESSEDMULTITEXIMAGEEXTPROC) (GLenum texunit, GLenum target, GLint level, void* img);
-typedef void (GLAPIENTRY * PFNGLGETCOMPRESSEDTEXTUREIMAGEEXTPROC) (GLuint texture, GLenum target, GLint level, void* img);
+typedef void (GLAPIENTRY * PFNGLGETCOMPRESSEDMULTITEXIMAGEEXTPROC) (GLenum texunit, GLenum target, GLint level, GLvoid *img);
+typedef void (GLAPIENTRY * PFNGLGETCOMPRESSEDTEXTUREIMAGEEXTPROC) (GLuint texture, GLenum target, GLint level, GLvoid *img);
typedef void (GLAPIENTRY * PFNGLGETDOUBLEINDEXEDVEXTPROC) (GLenum target, GLuint index, GLdouble* params);
typedef void (GLAPIENTRY * PFNGLGETDOUBLEI_VEXTPROC) (GLenum pname, GLuint index, GLdouble* params);
typedef void (GLAPIENTRY * PFNGLGETFLOATINDEXEDVEXTPROC) (GLenum target, GLuint index, GLfloat* params);
@@ -7208,7 +8347,7 @@ typedef void (GLAPIENTRY * PFNGLGETMULTITEXENVIVEXTPROC) (GLenum texunit, GLenum
typedef void (GLAPIENTRY * PFNGLGETMULTITEXGENDVEXTPROC) (GLenum texunit, GLenum coord, GLenum pname, GLdouble* params);
typedef void (GLAPIENTRY * PFNGLGETMULTITEXGENFVEXTPROC) (GLenum texunit, GLenum coord, GLenum pname, GLfloat* params);
typedef void (GLAPIENTRY * PFNGLGETMULTITEXGENIVEXTPROC) (GLenum texunit, GLenum coord, GLenum pname, GLint* params);
-typedef void (GLAPIENTRY * PFNGLGETMULTITEXIMAGEEXTPROC) (GLenum texunit, GLenum target, GLint level, GLenum format, GLenum type, void* pixels);
+typedef void (GLAPIENTRY * PFNGLGETMULTITEXIMAGEEXTPROC) (GLenum texunit, GLenum target, GLint level, GLenum format, GLenum type, GLvoid *pixels);
typedef void (GLAPIENTRY * PFNGLGETMULTITEXLEVELPARAMETERFVEXTPROC) (GLenum texunit, GLenum target, GLint level, GLenum pname, GLfloat* params);
typedef void (GLAPIENTRY * PFNGLGETMULTITEXLEVELPARAMETERIVEXTPROC) (GLenum texunit, GLenum target, GLint level, GLenum pname, GLint* params);
typedef void (GLAPIENTRY * PFNGLGETMULTITEXPARAMETERIIVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, GLint* params);
@@ -7217,18 +8356,18 @@ typedef void (GLAPIENTRY * PFNGLGETMULTITEXPARAMETERFVEXTPROC) (GLenum texunit,
typedef void (GLAPIENTRY * PFNGLGETMULTITEXPARAMETERIVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, GLint* params);
typedef void (GLAPIENTRY * PFNGLGETNAMEDBUFFERPARAMETERIVEXTPROC) (GLuint buffer, GLenum pname, GLint* params);
typedef void (GLAPIENTRY * PFNGLGETNAMEDBUFFERPOINTERVEXTPROC) (GLuint buffer, GLenum pname, void** params);
-typedef void (GLAPIENTRY * PFNGLGETNAMEDBUFFERSUBDATAEXTPROC) (GLuint buffer, GLintptr offset, GLsizeiptr size, void* data);
+typedef void (GLAPIENTRY * PFNGLGETNAMEDBUFFERSUBDATAEXTPROC) (GLuint buffer, GLintptr offset, GLsizeiptr size, GLvoid *data);
typedef void (GLAPIENTRY * PFNGLGETNAMEDFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC) (GLuint framebuffer, GLenum attachment, GLenum pname, GLint* params);
typedef void (GLAPIENTRY * PFNGLGETNAMEDPROGRAMLOCALPARAMETERIIVEXTPROC) (GLuint program, GLenum target, GLuint index, GLint* params);
typedef void (GLAPIENTRY * PFNGLGETNAMEDPROGRAMLOCALPARAMETERIUIVEXTPROC) (GLuint program, GLenum target, GLuint index, GLuint* params);
typedef void (GLAPIENTRY * PFNGLGETNAMEDPROGRAMLOCALPARAMETERDVEXTPROC) (GLuint program, GLenum target, GLuint index, GLdouble* params);
typedef void (GLAPIENTRY * PFNGLGETNAMEDPROGRAMLOCALPARAMETERFVEXTPROC) (GLuint program, GLenum target, GLuint index, GLfloat* params);
-typedef void (GLAPIENTRY * PFNGLGETNAMEDPROGRAMSTRINGEXTPROC) (GLuint program, GLenum target, GLenum pname, void* string);
+typedef void (GLAPIENTRY * PFNGLGETNAMEDPROGRAMSTRINGEXTPROC) (GLuint program, GLenum target, GLenum pname, GLvoid *string);
typedef void (GLAPIENTRY * PFNGLGETNAMEDPROGRAMIVEXTPROC) (GLuint program, GLenum target, GLenum pname, GLint* params);
typedef void (GLAPIENTRY * PFNGLGETNAMEDRENDERBUFFERPARAMETERIVEXTPROC) (GLuint renderbuffer, GLenum pname, GLint* params);
typedef void (GLAPIENTRY * PFNGLGETPOINTERINDEXEDVEXTPROC) (GLenum target, GLuint index, GLvoid** params);
typedef void (GLAPIENTRY * PFNGLGETPOINTERI_VEXTPROC) (GLenum pname, GLuint index, GLvoid** params);
-typedef void (GLAPIENTRY * PFNGLGETTEXTUREIMAGEEXTPROC) (GLuint texture, GLenum target, GLint level, GLenum format, GLenum type, void* pixels);
+typedef void (GLAPIENTRY * PFNGLGETTEXTUREIMAGEEXTPROC) (GLuint texture, GLenum target, GLint level, GLenum format, GLenum type, GLvoid *pixels);
typedef void (GLAPIENTRY * PFNGLGETTEXTURELEVELPARAMETERFVEXTPROC) (GLuint texture, GLenum target, GLint level, GLenum pname, GLfloat* params);
typedef void (GLAPIENTRY * PFNGLGETTEXTURELEVELPARAMETERIVEXTPROC) (GLuint texture, GLenum target, GLint level, GLenum pname, GLint* params);
typedef void (GLAPIENTRY * PFNGLGETTEXTUREPARAMETERIIVEXTPROC) (GLuint texture, GLenum target, GLenum pname, GLint* params);
@@ -7261,7 +8400,7 @@ typedef void (GLAPIENTRY * PFNGLMATRIXSCALEFEXTPROC) (GLenum matrixMode, GLfloat
typedef void (GLAPIENTRY * PFNGLMATRIXTRANSLATEDEXTPROC) (GLenum matrixMode, GLdouble x, GLdouble y, GLdouble z);
typedef void (GLAPIENTRY * PFNGLMATRIXTRANSLATEFEXTPROC) (GLenum matrixMode, GLfloat x, GLfloat y, GLfloat z);
typedef void (GLAPIENTRY * PFNGLMULTITEXBUFFEREXTPROC) (GLenum texunit, GLenum target, GLenum internalformat, GLuint buffer);
-typedef void (GLAPIENTRY * PFNGLMULTITEXCOORDPOINTEREXTPROC) (GLenum texunit, GLint size, GLenum type, GLsizei stride, const void* pointer);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORDPOINTEREXTPROC) (GLenum texunit, GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);
typedef void (GLAPIENTRY * PFNGLMULTITEXENVFEXTPROC) (GLenum texunit, GLenum target, GLenum pname, GLfloat param);
typedef void (GLAPIENTRY * PFNGLMULTITEXENVFVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, const GLfloat* params);
typedef void (GLAPIENTRY * PFNGLMULTITEXENVIEXTPROC) (GLenum texunit, GLenum target, GLenum pname, GLint param);
@@ -7272,9 +8411,9 @@ typedef void (GLAPIENTRY * PFNGLMULTITEXGENFEXTPROC) (GLenum texunit, GLenum coo
typedef void (GLAPIENTRY * PFNGLMULTITEXGENFVEXTPROC) (GLenum texunit, GLenum coord, GLenum pname, const GLfloat* params);
typedef void (GLAPIENTRY * PFNGLMULTITEXGENIEXTPROC) (GLenum texunit, GLenum coord, GLenum pname, GLint param);
typedef void (GLAPIENTRY * PFNGLMULTITEXGENIVEXTPROC) (GLenum texunit, GLenum coord, GLenum pname, const GLint* params);
-typedef void (GLAPIENTRY * PFNGLMULTITEXIMAGE1DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint internalformat, GLsizei width, GLint border, GLenum format, GLenum type, const void* pixels);
-typedef void (GLAPIENTRY * PFNGLMULTITEXIMAGE2DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void* pixels);
-typedef void (GLAPIENTRY * PFNGLMULTITEXIMAGE3DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void* pixels);
+typedef void (GLAPIENTRY * PFNGLMULTITEXIMAGE1DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint internalformat, GLsizei width, GLint border, GLenum format, GLenum type, const GLvoid *pixels);
+typedef void (GLAPIENTRY * PFNGLMULTITEXIMAGE2DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels);
+typedef void (GLAPIENTRY * PFNGLMULTITEXIMAGE3DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid *pixels);
typedef void (GLAPIENTRY * PFNGLMULTITEXPARAMETERIIVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, const GLint* params);
typedef void (GLAPIENTRY * PFNGLMULTITEXPARAMETERIUIVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, const GLuint* params);
typedef void (GLAPIENTRY * PFNGLMULTITEXPARAMETERFEXTPROC) (GLenum texunit, GLenum target, GLenum pname, GLfloat param);
@@ -7282,11 +8421,11 @@ typedef void (GLAPIENTRY * PFNGLMULTITEXPARAMETERFVEXTPROC) (GLenum texunit, GLe
typedef void (GLAPIENTRY * PFNGLMULTITEXPARAMETERIEXTPROC) (GLenum texunit, GLenum target, GLenum pname, GLint param);
typedef void (GLAPIENTRY * PFNGLMULTITEXPARAMETERIVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, const GLint* param);
typedef void (GLAPIENTRY * PFNGLMULTITEXRENDERBUFFEREXTPROC) (GLenum texunit, GLenum target, GLuint renderbuffer);
-typedef void (GLAPIENTRY * PFNGLMULTITEXSUBIMAGE1DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const void* pixels);
-typedef void (GLAPIENTRY * PFNGLMULTITEXSUBIMAGE2DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void* pixels);
-typedef void (GLAPIENTRY * PFNGLMULTITEXSUBIMAGE3DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void* pixels);
-typedef void (GLAPIENTRY * PFNGLNAMEDBUFFERDATAEXTPROC) (GLuint buffer, GLsizeiptr size, const void* data, GLenum usage);
-typedef void (GLAPIENTRY * PFNGLNAMEDBUFFERSUBDATAEXTPROC) (GLuint buffer, GLintptr offset, GLsizeiptr size, const void* data);
+typedef void (GLAPIENTRY * PFNGLMULTITEXSUBIMAGE1DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const GLvoid *pixels);
+typedef void (GLAPIENTRY * PFNGLMULTITEXSUBIMAGE2DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels);
+typedef void (GLAPIENTRY * PFNGLMULTITEXSUBIMAGE3DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid *pixels);
+typedef void (GLAPIENTRY * PFNGLNAMEDBUFFERDATAEXTPROC) (GLuint buffer, GLsizeiptr size, const GLvoid *data, GLenum usage);
+typedef void (GLAPIENTRY * PFNGLNAMEDBUFFERSUBDATAEXTPROC) (GLuint buffer, GLintptr offset, GLsizeiptr size, const GLvoid *data);
typedef void (GLAPIENTRY * PFNGLNAMEDCOPYBUFFERSUBDATAEXTPROC) (GLuint readBuffer, GLuint writeBuffer, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size);
typedef void (GLAPIENTRY * PFNGLNAMEDFRAMEBUFFERRENDERBUFFEREXTPROC) (GLuint framebuffer, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer);
typedef void (GLAPIENTRY * PFNGLNAMEDFRAMEBUFFERTEXTURE1DEXTPROC) (GLuint framebuffer, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
@@ -7306,7 +8445,7 @@ typedef void (GLAPIENTRY * PFNGLNAMEDPROGRAMLOCALPARAMETERI4UIVEXTPROC) (GLuint
typedef void (GLAPIENTRY * PFNGLNAMEDPROGRAMLOCALPARAMETERS4FVEXTPROC) (GLuint program, GLenum target, GLuint index, GLsizei count, const GLfloat* params);
typedef void (GLAPIENTRY * PFNGLNAMEDPROGRAMLOCALPARAMETERSI4IVEXTPROC) (GLuint program, GLenum target, GLuint index, GLsizei count, const GLint* params);
typedef void (GLAPIENTRY * PFNGLNAMEDPROGRAMLOCALPARAMETERSI4UIVEXTPROC) (GLuint program, GLenum target, GLuint index, GLsizei count, const GLuint* params);
-typedef void (GLAPIENTRY * PFNGLNAMEDPROGRAMSTRINGEXTPROC) (GLuint program, GLenum target, GLenum format, GLsizei len, const void* string);
+typedef void (GLAPIENTRY * PFNGLNAMEDPROGRAMSTRINGEXTPROC) (GLuint program, GLenum target, GLenum format, GLsizei len, const GLvoid *string);
typedef void (GLAPIENTRY * PFNGLNAMEDRENDERBUFFERSTORAGEEXTPROC) (GLuint renderbuffer, GLenum internalformat, GLsizei width, GLsizei height);
typedef void (GLAPIENTRY * PFNGLNAMEDRENDERBUFFERSTORAGEMULTISAMPLECOVERAGEEXTPROC) (GLuint renderbuffer, GLsizei coverageSamples, GLsizei colorSamples, GLenum internalformat, GLsizei width, GLsizei height);
typedef void (GLAPIENTRY * PFNGLNAMEDRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC) (GLuint renderbuffer, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
@@ -7345,9 +8484,9 @@ typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX4X2FVEXTPROC) (GLuint progra
typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX4X3FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
typedef void (GLAPIENTRY * PFNGLPUSHCLIENTATTRIBDEFAULTEXTPROC) (GLbitfield mask);
typedef void (GLAPIENTRY * PFNGLTEXTUREBUFFEREXTPROC) (GLuint texture, GLenum target, GLenum internalformat, GLuint buffer);
-typedef void (GLAPIENTRY * PFNGLTEXTUREIMAGE1DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint internalformat, GLsizei width, GLint border, GLenum format, GLenum type, const void* pixels);
-typedef void (GLAPIENTRY * PFNGLTEXTUREIMAGE2DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void* pixels);
-typedef void (GLAPIENTRY * PFNGLTEXTUREIMAGE3DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void* pixels);
+typedef void (GLAPIENTRY * PFNGLTEXTUREIMAGE1DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint internalformat, GLsizei width, GLint border, GLenum format, GLenum type, const GLvoid *pixels);
+typedef void (GLAPIENTRY * PFNGLTEXTUREIMAGE2DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels);
+typedef void (GLAPIENTRY * PFNGLTEXTUREIMAGE3DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid *pixels);
typedef void (GLAPIENTRY * PFNGLTEXTUREPARAMETERIIVEXTPROC) (GLuint texture, GLenum target, GLenum pname, const GLint* params);
typedef void (GLAPIENTRY * PFNGLTEXTUREPARAMETERIUIVEXTPROC) (GLuint texture, GLenum target, GLenum pname, const GLuint* params);
typedef void (GLAPIENTRY * PFNGLTEXTUREPARAMETERFEXTPROC) (GLuint texture, GLenum target, GLenum pname, GLfloat param);
@@ -7355,9 +8494,9 @@ typedef void (GLAPIENTRY * PFNGLTEXTUREPARAMETERFVEXTPROC) (GLuint texture, GLen
typedef void (GLAPIENTRY * PFNGLTEXTUREPARAMETERIEXTPROC) (GLuint texture, GLenum target, GLenum pname, GLint param);
typedef void (GLAPIENTRY * PFNGLTEXTUREPARAMETERIVEXTPROC) (GLuint texture, GLenum target, GLenum pname, const GLint* param);
typedef void (GLAPIENTRY * PFNGLTEXTURERENDERBUFFEREXTPROC) (GLuint texture, GLenum target, GLuint renderbuffer);
-typedef void (GLAPIENTRY * PFNGLTEXTURESUBIMAGE1DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const void* pixels);
-typedef void (GLAPIENTRY * PFNGLTEXTURESUBIMAGE2DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void* pixels);
-typedef void (GLAPIENTRY * PFNGLTEXTURESUBIMAGE3DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void* pixels);
+typedef void (GLAPIENTRY * PFNGLTEXTURESUBIMAGE1DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const GLvoid *pixels);
+typedef void (GLAPIENTRY * PFNGLTEXTURESUBIMAGE2DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels);
+typedef void (GLAPIENTRY * PFNGLTEXTURESUBIMAGE3DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid *pixels);
typedef GLboolean (GLAPIENTRY * PFNGLUNMAPNAMEDBUFFEREXTPROC) (GLuint buffer);
typedef void (GLAPIENTRY * PFNGLVERTEXARRAYCOLOROFFSETEXTPROC) (GLuint vaobj, GLuint buffer, GLint size, GLenum type, GLsizei stride, GLintptr offset);
typedef void (GLAPIENTRY * PFNGLVERTEXARRAYEDGEFLAGOFFSETEXTPROC) (GLuint vaobj, GLuint buffer, GLsizei stride, GLintptr offset);
@@ -8069,10 +9208,10 @@ typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBIPOINTEREXTPROC) (GLuint index, GLin
#define GL_MINMAX_FORMAT_EXT 0x802F
#define GL_MINMAX_SINK_EXT 0x8030
-typedef void (GLAPIENTRY * PFNGLGETHISTOGRAMEXTPROC) (GLenum target, GLboolean reset, GLenum format, GLenum type, void* values);
+typedef void (GLAPIENTRY * PFNGLGETHISTOGRAMEXTPROC) (GLenum target, GLboolean reset, GLenum format, GLenum type, GLvoid *values);
typedef void (GLAPIENTRY * PFNGLGETHISTOGRAMPARAMETERFVEXTPROC) (GLenum target, GLenum pname, GLfloat* params);
typedef void (GLAPIENTRY * PFNGLGETHISTOGRAMPARAMETERIVEXTPROC) (GLenum target, GLenum pname, GLint* params);
-typedef void (GLAPIENTRY * PFNGLGETMINMAXEXTPROC) (GLenum target, GLboolean reset, GLenum format, GLenum type, void* values);
+typedef void (GLAPIENTRY * PFNGLGETMINMAXEXTPROC) (GLenum target, GLboolean reset, GLenum format, GLenum type, GLvoid *values);
typedef void (GLAPIENTRY * PFNGLGETMINMAXPARAMETERFVEXTPROC) (GLenum target, GLenum pname, GLfloat* params);
typedef void (GLAPIENTRY * PFNGLGETMINMAXPARAMETERIVEXTPROC) (GLenum target, GLenum pname, GLint* params);
typedef void (GLAPIENTRY * PFNGLHISTOGRAMEXTPROC) (GLenum target, GLsizei width, GLenum internalformat, GLboolean sink);
@@ -8153,7 +9292,6 @@ typedef void (GLAPIENTRY * PFNGLINDEXMATERIALEXTPROC) (GLenum face, GLenum mode)
#define GL_TEXTURE_LIGHT_EXT 0x8350
#define GL_TEXTURE_MATERIAL_FACE_EXT 0x8351
#define GL_TEXTURE_MATERIAL_PARAMETER_EXT 0x8352
-#define GL_FRAGMENT_DEPTH_EXT 0x8452
typedef void (GLAPIENTRY * PFNGLAPPLYTEXTUREEXTPROC) (GLenum mode);
typedef void (GLAPIENTRY * PFNGLTEXTURELIGHTEXTPROC) (GLenum pname);
@@ -8182,7 +9320,7 @@ typedef void (GLAPIENTRY * PFNGLTEXTUREMATERIALEXTPROC) (GLenum face, GLenum mod
#define GL_EXT_multi_draw_arrays 1
typedef void (GLAPIENTRY * PFNGLMULTIDRAWARRAYSEXTPROC) (GLenum mode, const GLint* first, const GLsizei *count, GLsizei primcount);
-typedef void (GLAPIENTRY * PFNGLMULTIDRAWELEMENTSEXTPROC) (GLenum mode, GLsizei* count, GLenum type, const GLvoid **indices, GLsizei primcount);
+typedef void (GLAPIENTRY * PFNGLMULTIDRAWELEMENTSEXTPROC) (GLenum mode, GLsizei* count, GLenum type, const GLvoid * const *indices, GLsizei primcount);
#define glMultiDrawArraysEXT GLEW_GET_FUN(__glewMultiDrawArraysEXT)
#define glMultiDrawElementsEXT GLEW_GET_FUN(__glewMultiDrawElementsEXT)
@@ -8275,8 +9413,6 @@ typedef void (GLAPIENTRY * PFNGLSAMPLEPATTERNEXTPROC) (GLenum pattern);
#define GL_TEXTURE_2D 0x0DE1
#define GL_PROXY_TEXTURE_1D 0x8063
#define GL_PROXY_TEXTURE_2D 0x8064
-#define GL_TEXTURE_3D_EXT 0x806F
-#define GL_PROXY_TEXTURE_3D_EXT 0x8070
#define GL_COLOR_TABLE_FORMAT_EXT 0x80D8
#define GL_COLOR_TABLE_WIDTH_EXT 0x80D9
#define GL_COLOR_TABLE_RED_SIZE_EXT 0x80DA
@@ -8295,8 +9431,8 @@ typedef void (GLAPIENTRY * PFNGLSAMPLEPATTERNEXTPROC) (GLenum pattern);
#define GL_TEXTURE_CUBE_MAP_ARB 0x8513
#define GL_PROXY_TEXTURE_CUBE_MAP_ARB 0x851B
-typedef void (GLAPIENTRY * PFNGLCOLORTABLEEXTPROC) (GLenum target, GLenum internalFormat, GLsizei width, GLenum format, GLenum type, const void* data);
-typedef void (GLAPIENTRY * PFNGLGETCOLORTABLEEXTPROC) (GLenum target, GLenum format, GLenum type, void* data);
+typedef void (GLAPIENTRY * PFNGLCOLORTABLEEXTPROC) (GLenum target, GLenum internalFormat, GLsizei width, GLenum format, GLenum type, const GLvoid *data);
+typedef void (GLAPIENTRY * PFNGLGETCOLORTABLEEXTPROC) (GLenum target, GLenum format, GLenum type, GLvoid *data);
typedef void (GLAPIENTRY * PFNGLGETCOLORTABLEPARAMETERFVEXTPROC) (GLenum target, GLenum pname, GLfloat* params);
typedef void (GLAPIENTRY * PFNGLGETCOLORTABLEPARAMETERIVEXTPROC) (GLenum target, GLenum pname, GLint* params);
@@ -8507,7 +9643,7 @@ typedef void (GLAPIENTRY * PFNGLSECONDARYCOLORPOINTEREXTPROC) (GLint size, GLenu
#define GL_ACTIVE_PROGRAM_EXT 0x8B8D
typedef void (GLAPIENTRY * PFNGLACTIVEPROGRAMEXTPROC) (GLuint program);
-typedef GLuint (GLAPIENTRY * PFNGLCREATESHADERPROGRAMEXTPROC) (GLenum type, const char* string);
+typedef GLuint (GLAPIENTRY * PFNGLCREATESHADERPROGRAMEXTPROC) (GLenum type, const GLchar* string);
typedef void (GLAPIENTRY * PFNGLUSESHADERPROGRAMEXTPROC) (GLenum type, GLuint program);
#define glActiveProgramEXT GLEW_GET_FUN(__glewActiveProgramEXT)
@@ -8667,9 +9803,9 @@ typedef void (GLAPIENTRY * PFNGLACTIVESTENCILFACEEXTPROC) (GLenum face);
#ifndef GL_EXT_subtexture
#define GL_EXT_subtexture 1
-typedef void (GLAPIENTRY * PFNGLTEXSUBIMAGE1DEXTPROC) (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const void* pixels);
-typedef void (GLAPIENTRY * PFNGLTEXSUBIMAGE2DEXTPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void* pixels);
-typedef void (GLAPIENTRY * PFNGLTEXSUBIMAGE3DEXTPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void* pixels);
+typedef void (GLAPIENTRY * PFNGLTEXSUBIMAGE1DEXTPROC) (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const GLvoid *pixels);
+typedef void (GLAPIENTRY * PFNGLTEXSUBIMAGE2DEXTPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels);
+typedef void (GLAPIENTRY * PFNGLTEXSUBIMAGE3DEXTPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid *pixels);
#define glTexSubImage1DEXT GLEW_GET_FUN(__glewTexSubImage1DEXT)
#define glTexSubImage2DEXT GLEW_GET_FUN(__glewTexSubImage2DEXT)
@@ -8746,7 +9882,7 @@ typedef void (GLAPIENTRY * PFNGLTEXSUBIMAGE3DEXTPROC) (GLenum target, GLint leve
#define GL_TEXTURE_WRAP_R_EXT 0x8072
#define GL_MAX_3D_TEXTURE_SIZE_EXT 0x8073
-typedef void (GLAPIENTRY * PFNGLTEXIMAGE3DEXTPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void* pixels);
+typedef void (GLAPIENTRY * PFNGLTEXIMAGE3DEXTPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid *pixels);
#define glTexImage3DEXT GLEW_GET_FUN(__glewTexImage3DEXT)
@@ -8800,9 +9936,6 @@ typedef void (GLAPIENTRY * PFNGLTEXBUFFEREXTPROC) (GLenum target, GLenum interna
#ifndef GL_EXT_texture_compression_dxt1
#define GL_EXT_texture_compression_dxt1 1
-#define GL_COMPRESSED_RGB_S3TC_DXT1_EXT 0x83F0
-#define GL_COMPRESSED_RGBA_S3TC_DXT1_EXT 0x83F1
-
#define GLEW_EXT_texture_compression_dxt1 GLEW_GET_VAR(__GLEW_EXT_texture_compression_dxt1)
#endif /* GL_EXT_texture_compression_dxt1 */
@@ -8887,18 +10020,6 @@ typedef void (GLAPIENTRY * PFNGLTEXBUFFEREXTPROC) (GLenum target, GLenum interna
#ifndef GL_EXT_texture_env
#define GL_EXT_texture_env 1
-#define GL_TEXTURE_ENV0_EXT 0
-#define GL_ENV_BLEND_EXT 0
-#define GL_TEXTURE_ENV_SHIFT_EXT 0
-#define GL_ENV_REPLACE_EXT 0
-#define GL_ENV_ADD_EXT 0
-#define GL_ENV_SUBTRACT_EXT 0
-#define GL_TEXTURE_ENV_MODE_ALPHA_EXT 0
-#define GL_ENV_REVERSE_SUBTRACT_EXT 0
-#define GL_ENV_REVERSE_BLEND_EXT 0
-#define GL_ENV_COPY_EXT 0
-#define GL_ENV_MODULATE_EXT 0
-
#define GLEW_EXT_texture_env GLEW_GET_VAR(__GLEW_EXT_texture_env)
#endif /* GL_EXT_texture_env */
@@ -9268,8 +10389,8 @@ typedef void (GLAPIENTRY * PFNGLBINDBUFFERBASEEXTPROC) (GLenum target, GLuint in
typedef void (GLAPIENTRY * PFNGLBINDBUFFEROFFSETEXTPROC) (GLenum target, GLuint index, GLuint buffer, GLintptr offset);
typedef void (GLAPIENTRY * PFNGLBINDBUFFERRANGEEXTPROC) (GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size);
typedef void (GLAPIENTRY * PFNGLENDTRANSFORMFEEDBACKEXTPROC) (void);
-typedef void (GLAPIENTRY * PFNGLGETTRANSFORMFEEDBACKVARYINGEXTPROC) (GLuint program, GLuint index, GLsizei bufSize, GLsizei* length, GLsizei *size, GLenum *type, char *name);
-typedef void (GLAPIENTRY * PFNGLTRANSFORMFEEDBACKVARYINGSEXTPROC) (GLuint program, GLsizei count, const char ** varyings, GLenum bufferMode);
+typedef void (GLAPIENTRY * PFNGLGETTRANSFORMFEEDBACKVARYINGEXTPROC) (GLuint program, GLuint index, GLsizei bufSize, GLsizei* length, GLsizei *size, GLenum *type, GLchar *name);
+typedef void (GLAPIENTRY * PFNGLTRANSFORMFEEDBACKVARYINGSEXTPROC) (GLuint program, GLsizei count, const GLchar * const* varyings, GLenum bufferMode);
#define glBeginTransformFeedbackEXT GLEW_GET_FUN(__glewBeginTransformFeedbackEXT)
#define glBindBufferBaseEXT GLEW_GET_FUN(__glewBindBufferBaseEXT)
@@ -9323,13 +10444,13 @@ typedef void (GLAPIENTRY * PFNGLTRANSFORMFEEDBACKVARYINGSEXTPROC) (GLuint progra
#define GL_EDGE_FLAG_ARRAY_POINTER_EXT 0x8093
typedef void (GLAPIENTRY * PFNGLARRAYELEMENTEXTPROC) (GLint i);
-typedef void (GLAPIENTRY * PFNGLCOLORPOINTEREXTPROC) (GLint size, GLenum type, GLsizei stride, GLsizei count, const void* pointer);
+typedef void (GLAPIENTRY * PFNGLCOLORPOINTEREXTPROC) (GLint size, GLenum type, GLsizei stride, GLsizei count, const GLvoid *pointer);
typedef void (GLAPIENTRY * PFNGLDRAWARRAYSEXTPROC) (GLenum mode, GLint first, GLsizei count);
typedef void (GLAPIENTRY * PFNGLEDGEFLAGPOINTEREXTPROC) (GLsizei stride, GLsizei count, const GLboolean* pointer);
-typedef void (GLAPIENTRY * PFNGLINDEXPOINTEREXTPROC) (GLenum type, GLsizei stride, GLsizei count, const void* pointer);
-typedef void (GLAPIENTRY * PFNGLNORMALPOINTEREXTPROC) (GLenum type, GLsizei stride, GLsizei count, const void* pointer);
-typedef void (GLAPIENTRY * PFNGLTEXCOORDPOINTEREXTPROC) (GLint size, GLenum type, GLsizei stride, GLsizei count, const void* pointer);
-typedef void (GLAPIENTRY * PFNGLVERTEXPOINTEREXTPROC) (GLint size, GLenum type, GLsizei stride, GLsizei count, const void* pointer);
+typedef void (GLAPIENTRY * PFNGLINDEXPOINTEREXTPROC) (GLenum type, GLsizei stride, GLsizei count, const GLvoid *pointer);
+typedef void (GLAPIENTRY * PFNGLNORMALPOINTEREXTPROC) (GLenum type, GLsizei stride, GLsizei count, const GLvoid *pointer);
+typedef void (GLAPIENTRY * PFNGLTEXCOORDPOINTEREXTPROC) (GLint size, GLenum type, GLsizei stride, GLsizei count, const GLvoid *pointer);
+typedef void (GLAPIENTRY * PFNGLVERTEXPOINTEREXTPROC) (GLint size, GLenum type, GLsizei stride, GLsizei count, const GLvoid *pointer);
#define glArrayElementEXT GLEW_GET_FUN(__glewArrayElementEXT)
#define glColorPointerEXT GLEW_GET_FUN(__glewColorPointerEXT)
@@ -9383,7 +10504,7 @@ typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL3DEXTPROC) (GLuint index, GLdouble
typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL3DVEXTPROC) (GLuint index, const GLdouble* v);
typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL4DEXTPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL4DVEXTPROC) (GLuint index, const GLdouble* v);
-typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBLPOINTEREXTPROC) (GLuint index, GLint size, GLenum type, GLsizei stride, const void* pointer);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBLPOINTEREXTPROC) (GLuint index, GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);
#define glGetVertexAttribLdvEXT GLEW_GET_FUN(__glewGetVertexAttribLdvEXT)
#define glVertexArrayVertexAttribLOffsetEXT GLEW_GET_FUN(__glewVertexArrayVertexAttribLOffsetEXT)
@@ -9626,7 +10747,7 @@ typedef void (GLAPIENTRY * PFNGLWRITEMASKEXTPROC) (GLuint res, GLuint in, GLenum
#define GL_VERTEX_WEIGHT_ARRAY_STRIDE_EXT 0x850F
#define GL_VERTEX_WEIGHT_ARRAY_POINTER_EXT 0x8510
-typedef void (GLAPIENTRY * PFNGLVERTEXWEIGHTPOINTEREXTPROC) (GLint size, GLenum type, GLsizei stride, void* pointer);
+typedef void (GLAPIENTRY * PFNGLVERTEXWEIGHTPOINTEREXTPROC) (GLint size, GLenum type, GLsizei stride, GLvoid *pointer);
typedef void (GLAPIENTRY * PFNGLVERTEXWEIGHTFEXTPROC) (GLfloat weight);
typedef void (GLAPIENTRY * PFNGLVERTEXWEIGHTFVEXTPROC) (GLfloat* weight);
@@ -9671,7 +10792,7 @@ typedef void (GLAPIENTRY * PFNGLFRAMETERMINATORGREMEDYPROC) (void);
#ifndef GL_GREMEDY_string_marker
#define GL_GREMEDY_string_marker 1
-typedef void (GLAPIENTRY * PFNGLSTRINGMARKERGREMEDYPROC) (GLsizei len, const void* string);
+typedef void (GLAPIENTRY * PFNGLSTRINGMARKERGREMEDYPROC) (GLsizei len, const GLvoid *string);
#define glStringMarkerGREMEDY GLEW_GET_FUN(__glewStringMarkerGREMEDY)
@@ -9716,9 +10837,6 @@ typedef void (GLAPIENTRY * PFNGLIMAGETRANSFORMPARAMETERIVHPPROC) (GLenum target,
#ifndef GL_HP_occlusion_test
#define GL_HP_occlusion_test 1
-#define GL_OCCLUSION_TEST_HP 0x8165
-#define GL_OCCLUSION_TEST_RESULT_HP 0x8166
-
#define GLEW_HP_occlusion_test GLEW_GET_VAR(__GLEW_HP_occlusion_test)
#endif /* GL_HP_occlusion_test */
@@ -9865,6 +10983,28 @@ typedef void (GLAPIENTRY * PFNGLVERTEXPOINTERLISTIBMPROC) (GLint size, GLenum ty
#endif /* GL_INGR_interlace_read */
+/* -------------------------- GL_INTEL_map_texture ------------------------- */
+
+#ifndef GL_INTEL_map_texture
+#define GL_INTEL_map_texture 1
+
+#define GL_LAYOUT_DEFAULT_INTEL 0
+#define GL_LAYOUT_LINEAR_INTEL 1
+#define GL_LAYOUT_LINEAR_CPU_CACHED_INTEL 2
+#define GL_TEXTURE_MEMORY_LAYOUT_INTEL 0x83FF
+
+typedef GLvoid * (GLAPIENTRY * PFNGLMAPTEXTURE2DINTELPROC) (GLuint texture, GLint level, GLbitfield access, GLint* stride, GLenum *layout);
+typedef void (GLAPIENTRY * PFNGLSYNCTEXTUREINTELPROC) (GLuint texture);
+typedef void (GLAPIENTRY * PFNGLUNMAPTEXTURE2DINTELPROC) (GLuint texture, GLint level);
+
+#define glMapTexture2DINTEL GLEW_GET_FUN(__glewMapTexture2DINTEL)
+#define glSyncTextureINTEL GLEW_GET_FUN(__glewSyncTextureINTEL)
+#define glUnmapTexture2DINTEL GLEW_GET_FUN(__glewUnmapTexture2DINTEL)
+
+#define GLEW_INTEL_map_texture GLEW_GET_VAR(__GLEW_INTEL_map_texture)
+
+#endif /* GL_INTEL_map_texture */
+
/* ------------------------ GL_INTEL_parallel_arrays ----------------------- */
#ifndef GL_INTEL_parallel_arrays
@@ -9905,6 +11045,118 @@ typedef void (GLAPIENTRY * PFNGLTEXSCISSORINTELPROC) (GLenum target, GLclampf tl
#endif /* GL_INTEL_texture_scissor */
+/* ------------------------------ GL_KHR_debug ----------------------------- */
+
+#ifndef GL_KHR_debug
+#define GL_KHR_debug 1
+
+#define GL_CONTEXT_FLAG_DEBUG_BIT 0x00000002
+#define GL_STACK_OVERFLOW 0x0503
+#define GL_STACK_UNDERFLOW 0x0504
+#define GL_DEBUG_OUTPUT_SYNCHRONOUS 0x8242
+#define GL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH 0x8243
+#define GL_DEBUG_CALLBACK_FUNCTION 0x8244
+#define GL_DEBUG_CALLBACK_USER_PARAM 0x8245
+#define GL_DEBUG_SOURCE_API 0x8246
+#define GL_DEBUG_SOURCE_WINDOW_SYSTEM 0x8247
+#define GL_DEBUG_SOURCE_SHADER_COMPILER 0x8248
+#define GL_DEBUG_SOURCE_THIRD_PARTY 0x8249
+#define GL_DEBUG_SOURCE_APPLICATION 0x824A
+#define GL_DEBUG_SOURCE_OTHER 0x824B
+#define GL_DEBUG_TYPE_ERROR 0x824C
+#define GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR 0x824D
+#define GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR 0x824E
+#define GL_DEBUG_TYPE_PORTABILITY 0x824F
+#define GL_DEBUG_TYPE_PERFORMANCE 0x8250
+#define GL_DEBUG_TYPE_OTHER 0x8251
+#define GL_DEBUG_TYPE_MARKER 0x8268
+#define GL_DEBUG_TYPE_PUSH_GROUP 0x8269
+#define GL_DEBUG_TYPE_POP_GROUP 0x826A
+#define GL_DEBUG_SEVERITY_NOTIFICATION 0x826B
+#define GL_MAX_DEBUG_GROUP_STACK_DEPTH 0x826C
+#define GL_DEBUG_GROUP_STACK_DEPTH 0x826D
+#define GL_BUFFER 0x82E0
+#define GL_SHADER 0x82E1
+#define GL_PROGRAM 0x82E2
+#define GL_QUERY 0x82E3
+#define GL_PROGRAM_PIPELINE 0x82E4
+#define GL_SAMPLER 0x82E6
+#define GL_DISPLAY_LIST 0x82E7
+#define GL_MAX_LABEL_LENGTH 0x82E8
+#define GL_MAX_DEBUG_MESSAGE_LENGTH 0x9143
+#define GL_MAX_DEBUG_LOGGED_MESSAGES 0x9144
+#define GL_DEBUG_LOGGED_MESSAGES 0x9145
+#define GL_DEBUG_SEVERITY_HIGH 0x9146
+#define GL_DEBUG_SEVERITY_MEDIUM 0x9147
+#define GL_DEBUG_SEVERITY_LOW 0x9148
+#define GL_DEBUG_OUTPUT 0x92E0
+
+typedef void (APIENTRY *GLDEBUGPROC)(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar* message, GLvoid* userParam);
+
+typedef void (GLAPIENTRY * PFNGLDEBUGMESSAGECALLBACKPROC) (GLDEBUGPROC callback, const GLvoid *userParam);
+typedef void (GLAPIENTRY * PFNGLDEBUGMESSAGECONTROLPROC) (GLenum source, GLenum type, GLenum severity, GLsizei count, const GLuint* ids, GLboolean enabled);
+typedef void (GLAPIENTRY * PFNGLDEBUGMESSAGEINSERTPROC) (GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar* buf);
+typedef GLuint (GLAPIENTRY * PFNGLGETDEBUGMESSAGELOGPROC) (GLuint count, GLsizei bufsize, GLenum* sources, GLenum* types, GLuint* ids, GLenum* severities, GLsizei* lengths, GLchar* messageLog);
+typedef void (GLAPIENTRY * PFNGLGETOBJECTLABELPROC) (GLenum identifier, GLuint name, GLsizei bufSize, GLsizei* length, GLchar *label);
+typedef void (GLAPIENTRY * PFNGLGETOBJECTPTRLABELPROC) (void* ptr, GLsizei bufSize, GLsizei* length, GLchar *label);
+typedef void (GLAPIENTRY * PFNGLOBJECTLABELPROC) (GLenum identifier, GLuint name, GLsizei length, const GLchar* label);
+typedef void (GLAPIENTRY * PFNGLOBJECTPTRLABELPROC) (void* ptr, GLsizei length, const GLchar* label);
+typedef void (GLAPIENTRY * PFNGLPOPDEBUGGROUPPROC) (void);
+typedef void (GLAPIENTRY * PFNGLPUSHDEBUGGROUPPROC) (GLenum source, GLuint id, GLsizei length, const GLchar * message);
+
+#define glDebugMessageCallback GLEW_GET_FUN(__glewDebugMessageCallback)
+#define glDebugMessageControl GLEW_GET_FUN(__glewDebugMessageControl)
+#define glDebugMessageInsert GLEW_GET_FUN(__glewDebugMessageInsert)
+#define glGetDebugMessageLog GLEW_GET_FUN(__glewGetDebugMessageLog)
+#define glGetObjectLabel GLEW_GET_FUN(__glewGetObjectLabel)
+#define glGetObjectPtrLabel GLEW_GET_FUN(__glewGetObjectPtrLabel)
+#define glObjectLabel GLEW_GET_FUN(__glewObjectLabel)
+#define glObjectPtrLabel GLEW_GET_FUN(__glewObjectPtrLabel)
+#define glPopDebugGroup GLEW_GET_FUN(__glewPopDebugGroup)
+#define glPushDebugGroup GLEW_GET_FUN(__glewPushDebugGroup)
+
+#define GLEW_KHR_debug GLEW_GET_VAR(__GLEW_KHR_debug)
+
+#endif /* GL_KHR_debug */
+
+/* ------------------ GL_KHR_texture_compression_astc_ldr ------------------ */
+
+#ifndef GL_KHR_texture_compression_astc_ldr
+#define GL_KHR_texture_compression_astc_ldr 1
+
+#define GL_COMPRESSED_RGBA_ASTC_4x4_KHR 0x93B0
+#define GL_COMPRESSED_RGBA_ASTC_5x4_KHR 0x93B1
+#define GL_COMPRESSED_RGBA_ASTC_5x5_KHR 0x93B2
+#define GL_COMPRESSED_RGBA_ASTC_6x5_KHR 0x93B3
+#define GL_COMPRESSED_RGBA_ASTC_6x6_KHR 0x93B4
+#define GL_COMPRESSED_RGBA_ASTC_8x5_KHR 0x93B5
+#define GL_COMPRESSED_RGBA_ASTC_8x6_KHR 0x93B6
+#define GL_COMPRESSED_RGBA_ASTC_8x8_KHR 0x93B7
+#define GL_COMPRESSED_RGBA_ASTC_10x5_KHR 0x93B8
+#define GL_COMPRESSED_RGBA_ASTC_10x6_KHR 0x93B9
+#define GL_COMPRESSED_RGBA_ASTC_10x8_KHR 0x93BA
+#define GL_COMPRESSED_RGBA_ASTC_10x10_KHR 0x93BB
+#define GL_COMPRESSED_RGBA_ASTC_12x10_KHR 0x93BC
+#define GL_COMPRESSED_RGBA_ASTC_12x12_KHR 0x93BD
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR 0x93D0
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR 0x93D1
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR 0x93D2
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR 0x93D3
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR 0x93D4
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR 0x93D5
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR 0x93D6
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR 0x93D7
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR 0x93D8
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR 0x93D9
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR 0x93DA
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR 0x93DB
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR 0x93DC
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR 0x93DD
+
+#define GLEW_KHR_texture_compression_astc_ldr GLEW_GET_VAR(__GLEW_KHR_texture_compression_astc_ldr)
+
+#endif /* GL_KHR_texture_compression_astc_ldr */
+
/* -------------------------- GL_KTX_buffer_region ------------------------- */
#ifndef GL_KTX_buffer_region
@@ -10043,6 +11295,21 @@ typedef void (GLAPIENTRY * PFNGLWINDOWPOS4SVMESAPROC) (const GLshort* p);
#endif /* GL_MESA_ycbcr_texture */
+/* ----------------------- GL_NVX_conditional_render ----------------------- */
+
+#ifndef GL_NVX_conditional_render
+#define GL_NVX_conditional_render 1
+
+typedef void (GLAPIENTRY * PFNGLBEGINCONDITIONALRENDERNVXPROC) (GLuint id);
+typedef void (GLAPIENTRY * PFNGLENDCONDITIONALRENDERNVXPROC) (void);
+
+#define glBeginConditionalRenderNVX GLEW_GET_FUN(__glewBeginConditionalRenderNVX)
+#define glEndConditionalRenderNVX GLEW_GET_FUN(__glewEndConditionalRenderNVX)
+
+#define GLEW_NVX_conditional_render GLEW_GET_VAR(__GLEW_NVX_conditional_render)
+
+#endif /* GL_NVX_conditional_render */
+
/* ------------------------- GL_NVX_gpu_memory_info ------------------------ */
#ifndef GL_NVX_gpu_memory_info
@@ -10058,6 +11325,129 @@ typedef void (GLAPIENTRY * PFNGLWINDOWPOS4SVMESAPROC) (const GLshort* p);
#endif /* GL_NVX_gpu_memory_info */
+/* ------------------- GL_NV_bindless_multi_draw_indirect ------------------ */
+
+#ifndef GL_NV_bindless_multi_draw_indirect
+#define GL_NV_bindless_multi_draw_indirect 1
+
+typedef void (GLAPIENTRY * PFNGLMULTIDRAWARRAYSINDIRECTBINDLESSNVPROC) (GLenum mode, const GLvoid *indirect, GLsizei drawCount, GLsizei stride, GLint vertexBufferCount);
+typedef void (GLAPIENTRY * PFNGLMULTIDRAWELEMENTSINDIRECTBINDLESSNVPROC) (GLenum mode, GLenum type, const GLvoid *indirect, GLsizei drawCount, GLsizei stride, GLint vertexBufferCount);
+
+#define glMultiDrawArraysIndirectBindlessNV GLEW_GET_FUN(__glewMultiDrawArraysIndirectBindlessNV)
+#define glMultiDrawElementsIndirectBindlessNV GLEW_GET_FUN(__glewMultiDrawElementsIndirectBindlessNV)
+
+#define GLEW_NV_bindless_multi_draw_indirect GLEW_GET_VAR(__GLEW_NV_bindless_multi_draw_indirect)
+
+#endif /* GL_NV_bindless_multi_draw_indirect */
+
+/* ------------------------- GL_NV_bindless_texture ------------------------ */
+
+#ifndef GL_NV_bindless_texture
+#define GL_NV_bindless_texture 1
+
+typedef GLuint64 (GLAPIENTRY * PFNGLGETIMAGEHANDLENVPROC) (GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum format);
+typedef GLuint64 (GLAPIENTRY * PFNGLGETTEXTUREHANDLENVPROC) (GLuint texture);
+typedef GLuint64 (GLAPIENTRY * PFNGLGETTEXTURESAMPLERHANDLENVPROC) (GLuint texture, GLuint sampler);
+typedef GLboolean (GLAPIENTRY * PFNGLISIMAGEHANDLERESIDENTNVPROC) (GLuint64 handle);
+typedef GLboolean (GLAPIENTRY * PFNGLISTEXTUREHANDLERESIDENTNVPROC) (GLuint64 handle);
+typedef void (GLAPIENTRY * PFNGLMAKEIMAGEHANDLENONRESIDENTNVPROC) (GLuint64 handle);
+typedef void (GLAPIENTRY * PFNGLMAKEIMAGEHANDLERESIDENTNVPROC) (GLuint64 handle, GLenum access);
+typedef void (GLAPIENTRY * PFNGLMAKETEXTUREHANDLENONRESIDENTNVPROC) (GLuint64 handle);
+typedef void (GLAPIENTRY * PFNGLMAKETEXTUREHANDLERESIDENTNVPROC) (GLuint64 handle);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMHANDLEUI64NVPROC) (GLuint program, GLint location, GLuint64 value);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMHANDLEUI64VNVPROC) (GLuint program, GLint location, GLsizei count, const GLuint64* values);
+typedef void (GLAPIENTRY * PFNGLUNIFORMHANDLEUI64NVPROC) (GLint location, GLuint64 value);
+typedef void (GLAPIENTRY * PFNGLUNIFORMHANDLEUI64VNVPROC) (GLint location, GLsizei count, const GLuint64* value);
+
+#define glGetImageHandleNV GLEW_GET_FUN(__glewGetImageHandleNV)
+#define glGetTextureHandleNV GLEW_GET_FUN(__glewGetTextureHandleNV)
+#define glGetTextureSamplerHandleNV GLEW_GET_FUN(__glewGetTextureSamplerHandleNV)
+#define glIsImageHandleResidentNV GLEW_GET_FUN(__glewIsImageHandleResidentNV)
+#define glIsTextureHandleResidentNV GLEW_GET_FUN(__glewIsTextureHandleResidentNV)
+#define glMakeImageHandleNonResidentNV GLEW_GET_FUN(__glewMakeImageHandleNonResidentNV)
+#define glMakeImageHandleResidentNV GLEW_GET_FUN(__glewMakeImageHandleResidentNV)
+#define glMakeTextureHandleNonResidentNV GLEW_GET_FUN(__glewMakeTextureHandleNonResidentNV)
+#define glMakeTextureHandleResidentNV GLEW_GET_FUN(__glewMakeTextureHandleResidentNV)
+#define glProgramUniformHandleui64NV GLEW_GET_FUN(__glewProgramUniformHandleui64NV)
+#define glProgramUniformHandleui64vNV GLEW_GET_FUN(__glewProgramUniformHandleui64vNV)
+#define glUniformHandleui64NV GLEW_GET_FUN(__glewUniformHandleui64NV)
+#define glUniformHandleui64vNV GLEW_GET_FUN(__glewUniformHandleui64vNV)
+
+#define GLEW_NV_bindless_texture GLEW_GET_VAR(__GLEW_NV_bindless_texture)
+
+#endif /* GL_NV_bindless_texture */
+
+/* --------------------- GL_NV_blend_equation_advanced --------------------- */
+
+#ifndef GL_NV_blend_equation_advanced
+#define GL_NV_blend_equation_advanced 1
+
+#define GL_BLEND_PREMULTIPLIED_SRC_NV 0x9280
+#define GL_BLEND_OVERLAP_NV 0x9281
+#define GL_UNCORRELATED_NV 0x9282
+#define GL_DISJOINT_NV 0x9283
+#define GL_CONJOINT_NV 0x9284
+#define GL_BLEND_ADVANCED_COHERENT_NV 0x9285
+#define GL_SRC_NV 0x9286
+#define GL_DST_NV 0x9287
+#define GL_SRC_OVER_NV 0x9288
+#define GL_DST_OVER_NV 0x9289
+#define GL_SRC_IN_NV 0x928A
+#define GL_DST_IN_NV 0x928B
+#define GL_SRC_OUT_NV 0x928C
+#define GL_DST_OUT_NV 0x928D
+#define GL_SRC_ATOP_NV 0x928E
+#define GL_DST_ATOP_NV 0x928F
+#define GL_PLUS_NV 0x9291
+#define GL_PLUS_DARKER_NV 0x9292
+#define GL_MULTIPLY_NV 0x9294
+#define GL_SCREEN_NV 0x9295
+#define GL_OVERLAY_NV 0x9296
+#define GL_DARKEN_NV 0x9297
+#define GL_LIGHTEN_NV 0x9298
+#define GL_COLORDODGE_NV 0x9299
+#define GL_COLORBURN_NV 0x929A
+#define GL_HARDLIGHT_NV 0x929B
+#define GL_SOFTLIGHT_NV 0x929C
+#define GL_DIFFERENCE_NV 0x929E
+#define GL_MINUS_NV 0x929F
+#define GL_EXCLUSION_NV 0x92A0
+#define GL_CONTRAST_NV 0x92A1
+#define GL_INVERT_RGB_NV 0x92A3
+#define GL_LINEARDODGE_NV 0x92A4
+#define GL_LINEARBURN_NV 0x92A5
+#define GL_VIVIDLIGHT_NV 0x92A6
+#define GL_LINEARLIGHT_NV 0x92A7
+#define GL_PINLIGHT_NV 0x92A8
+#define GL_HARDMIX_NV 0x92A9
+#define GL_HSL_HUE_NV 0x92AD
+#define GL_HSL_SATURATION_NV 0x92AE
+#define GL_HSL_COLOR_NV 0x92AF
+#define GL_HSL_LUMINOSITY_NV 0x92B0
+#define GL_PLUS_CLAMPED_NV 0x92B1
+#define GL_PLUS_CLAMPED_ALPHA_NV 0x92B2
+#define GL_MINUS_CLAMPED_NV 0x92B3
+#define GL_INVERT_OVG_NV 0x92B4
+
+typedef void (GLAPIENTRY * PFNGLBLENDBARRIERNVPROC) (void);
+typedef void (GLAPIENTRY * PFNGLBLENDPARAMETERINVPROC) (GLenum pname, GLint value);
+
+#define glBlendBarrierNV GLEW_GET_FUN(__glewBlendBarrierNV)
+#define glBlendParameteriNV GLEW_GET_FUN(__glewBlendParameteriNV)
+
+#define GLEW_NV_blend_equation_advanced GLEW_GET_VAR(__GLEW_NV_blend_equation_advanced)
+
+#endif /* GL_NV_blend_equation_advanced */
+
+/* ----------------- GL_NV_blend_equation_advanced_coherent ---------------- */
+
+#ifndef GL_NV_blend_equation_advanced_coherent
+#define GL_NV_blend_equation_advanced_coherent 1
+
+#define GLEW_NV_blend_equation_advanced_coherent GLEW_GET_VAR(__GLEW_NV_blend_equation_advanced_coherent)
+
+#endif /* GL_NV_blend_equation_advanced_coherent */
+
/* --------------------------- GL_NV_blend_square -------------------------- */
#ifndef GL_NV_blend_square
@@ -10067,6 +11457,18 @@ typedef void (GLAPIENTRY * PFNGLWINDOWPOS4SVMESAPROC) (const GLshort* p);
#endif /* GL_NV_blend_square */
+/* ------------------------- GL_NV_compute_program5 ------------------------ */
+
+#ifndef GL_NV_compute_program5
+#define GL_NV_compute_program5 1
+
+#define GL_COMPUTE_PROGRAM_NV 0x90FB
+#define GL_COMPUTE_PROGRAM_PARAMETER_BUFFER_NV 0x90FC
+
+#define GLEW_NV_compute_program5 GLEW_GET_VAR(__GLEW_NV_compute_program5)
+
+#endif /* GL_NV_compute_program5 */
+
/* ------------------------ GL_NV_conditional_render ----------------------- */
#ifndef GL_NV_conditional_render
@@ -10112,6 +11514,18 @@ typedef void (GLAPIENTRY * PFNGLCOPYIMAGESUBDATANVPROC) (GLuint srcName, GLenum
#endif /* GL_NV_copy_image */
+/* -------------------------- GL_NV_deep_texture3D ------------------------- */
+
+#ifndef GL_NV_deep_texture3D
+#define GL_NV_deep_texture3D 1
+
+#define GL_MAX_DEEP_3D_TEXTURE_WIDTH_HEIGHT_NV 0x90D0
+#define GL_MAX_DEEP_3D_TEXTURE_DEPTH_NV 0x90D1
+
+#define GLEW_NV_deep_texture3D GLEW_GET_VAR(__GLEW_NV_deep_texture3D)
+
+#endif /* GL_NV_deep_texture3D */
+
/* ------------------------ GL_NV_depth_buffer_float ----------------------- */
#ifndef GL_NV_depth_buffer_float
@@ -10160,6 +11574,19 @@ typedef void (GLAPIENTRY * PFNGLDEPTHRANGEDNVPROC) (GLdouble zNear, GLdouble zFa
#endif /* GL_NV_depth_range_unclamped */
+/* --------------------------- GL_NV_draw_texture -------------------------- */
+
+#ifndef GL_NV_draw_texture
+#define GL_NV_draw_texture 1
+
+typedef void (GLAPIENTRY * PFNGLDRAWTEXTURENVPROC) (GLuint texture, GLuint sampler, GLfloat x0, GLfloat y0, GLfloat x1, GLfloat y1, GLfloat z, GLfloat s0, GLfloat t0, GLfloat s1, GLfloat t1);
+
+#define glDrawTextureNV GLEW_GET_FUN(__glewDrawTextureNV)
+
+#define GLEW_NV_draw_texture GLEW_GET_VAR(__GLEW_NV_draw_texture)
+
+#endif /* GL_NV_draw_texture */
+
/* ---------------------------- GL_NV_evaluators --------------------------- */
#ifndef GL_NV_evaluators
@@ -10193,10 +11620,10 @@ typedef void (GLAPIENTRY * PFNGLDEPTHRANGEDNVPROC) (GLdouble zNear, GLdouble zFa
typedef void (GLAPIENTRY * PFNGLEVALMAPSNVPROC) (GLenum target, GLenum mode);
typedef void (GLAPIENTRY * PFNGLGETMAPATTRIBPARAMETERFVNVPROC) (GLenum target, GLuint index, GLenum pname, GLfloat* params);
typedef void (GLAPIENTRY * PFNGLGETMAPATTRIBPARAMETERIVNVPROC) (GLenum target, GLuint index, GLenum pname, GLint* params);
-typedef void (GLAPIENTRY * PFNGLGETMAPCONTROLPOINTSNVPROC) (GLenum target, GLuint index, GLenum type, GLsizei ustride, GLsizei vstride, GLboolean packed, void* points);
+typedef void (GLAPIENTRY * PFNGLGETMAPCONTROLPOINTSNVPROC) (GLenum target, GLuint index, GLenum type, GLsizei ustride, GLsizei vstride, GLboolean packed, GLvoid *points);
typedef void (GLAPIENTRY * PFNGLGETMAPPARAMETERFVNVPROC) (GLenum target, GLenum pname, GLfloat* params);
typedef void (GLAPIENTRY * PFNGLGETMAPPARAMETERIVNVPROC) (GLenum target, GLenum pname, GLint* params);
-typedef void (GLAPIENTRY * PFNGLMAPCONTROLPOINTSNVPROC) (GLenum target, GLuint index, GLenum type, GLsizei ustride, GLsizei vstride, GLint uorder, GLint vorder, GLboolean packed, const void* points);
+typedef void (GLAPIENTRY * PFNGLMAPCONTROLPOINTSNVPROC) (GLenum target, GLuint index, GLenum type, GLsizei ustride, GLsizei vstride, GLint uorder, GLint vorder, GLboolean packed, const GLvoid *points);
typedef void (GLAPIENTRY * PFNGLMAPPARAMETERFVNVPROC) (GLenum target, GLenum pname, const GLfloat* params);
typedef void (GLAPIENTRY * PFNGLMAPPARAMETERIVNVPROC) (GLenum target, GLenum pname, const GLint* params);
@@ -10476,6 +11903,15 @@ typedef void (GLAPIENTRY * PFNGLPROGRAMLOCALPARAMETERSI4UIVNVPROC) (GLenum targe
#endif /* GL_NV_gpu_program5 */
+/* -------------------- GL_NV_gpu_program5_mem_extended -------------------- */
+
+#ifndef GL_NV_gpu_program5_mem_extended
+#define GL_NV_gpu_program5_mem_extended 1
+
+#define GLEW_NV_gpu_program5_mem_extended GLEW_GET_VAR(__GLEW_NV_gpu_program5_mem_extended)
+
+#endif /* GL_NV_gpu_program5_mem_extended */
+
/* ------------------------- GL_NV_gpu_program_fp64 ------------------------ */
#ifndef GL_NV_gpu_program_fp64
@@ -10717,7 +12153,6 @@ typedef void (GLAPIENTRY * PFNGLVERTEXWEIGHTHVNVPROC) (const GLhalf* weight);
#ifndef GL_NV_multisample_coverage
#define GL_NV_multisample_coverage 1
-#define GL_COVERAGE_SAMPLES_NV 0x80A9
#define GL_COLOR_SAMPLES_NV 0x8E20
#define GLEW_NV_multisample_coverage GLEW_GET_VAR(__GLEW_NV_multisample_coverage)
@@ -10817,9 +12252,9 @@ typedef void (GLAPIENTRY * PFNGLPROGRAMBUFFERPARAMETERSFVNVPROC) (GLenum target,
#define GL_CLOSE_PATH_NV 0x00
#define GL_BOLD_BIT_NV 0x01
#define GL_GLYPH_WIDTH_BIT_NV 0x01
-#define GL_MOVE_TO_NV 0x02
#define GL_GLYPH_HEIGHT_BIT_NV 0x02
#define GL_ITALIC_BIT_NV 0x02
+#define GL_MOVE_TO_NV 0x02
#define GL_RELATIVE_MOVE_TO_NV 0x03
#define GL_LINE_TO_NV 0x04
#define GL_GLYPH_HORIZONTAL_BEARING_X_BIT_NV 0x04
@@ -10849,14 +12284,16 @@ typedef void (GLAPIENTRY * PFNGLPROGRAMBUFFERPARAMETERSFVNVPROC) (GLenum target,
#define GL_GLYPH_VERTICAL_BEARING_X_BIT_NV 0x20
#define GL_GLYPH_VERTICAL_BEARING_Y_BIT_NV 0x40
#define GL_GLYPH_VERTICAL_BEARING_ADVANCE_BIT_NV 0x80
+#define GL_RESTART_PATH_NV 0xF0
+#define GL_DUP_FIRST_CUBIC_CURVE_TO_NV 0xF2
+#define GL_DUP_LAST_CUBIC_CURVE_TO_NV 0xF4
+#define GL_RECT_NV 0xF6
#define GL_CIRCULAR_CCW_ARC_TO_NV 0xF8
#define GL_CIRCULAR_CW_ARC_TO_NV 0xFA
#define GL_CIRCULAR_TANGENT_ARC_TO_NV 0xFC
#define GL_ARC_TO_NV 0xFE
#define GL_RELATIVE_ARC_TO_NV 0xFF
-#define GL_GLYPH_HAS_KERNING_NV 0x100
-#define GL_PRIMARY_COLOR_NV 0x852C
-#define GL_SECONDARY_COLOR_NV 0x852D
+#define GL_GLYPH_HAS_KERNING_BIT_NV 0x100
#define GL_PRIMARY_COLOR 0x8577
#define GL_PATH_FORMAT_SVG_NV 0x9070
#define GL_PATH_FORMAT_PS_NV 0x9071
@@ -10927,19 +12364,19 @@ typedef void (GLAPIENTRY * PFNGLPROGRAMBUFFERPARAMETERSFVNVPROC) (GLenum target,
#define GL_PATH_STENCIL_DEPTH_OFFSET_FACTOR_NV 0x90BD
#define GL_PATH_STENCIL_DEPTH_OFFSET_UNITS_NV 0x90BE
#define GL_PATH_COVER_DEPTH_FUNC_NV 0x90BF
-#define GL_FONT_X_MIN_BOUNDS_NV 0x00010000
-#define GL_FONT_Y_MIN_BOUNDS_NV 0x00020000
-#define GL_FONT_X_MAX_BOUNDS_NV 0x00040000
-#define GL_FONT_Y_MAX_BOUNDS_NV 0x00080000
-#define GL_FONT_UNITS_PER_EM_NV 0x00100000
-#define GL_FONT_ASCENDER_NV 0x00200000
-#define GL_FONT_DESCENDER_NV 0x00400000
-#define GL_FONT_HEIGHT_NV 0x00800000
-#define GL_FONT_MAX_ADVANCE_WIDTH_NV 0x01000000
-#define GL_FONT_MAX_ADVANCE_HEIGHT_NV 0x02000000
-#define GL_FONT_UNDERLINE_POSITION_NV 0x04000000
-#define GL_FONT_UNDERLINE_THICKNESS_NV 0x08000000
-#define GL_FONT_HAS_KERNING_NV 0x10000000
+#define GL_FONT_X_MIN_BOUNDS_BIT_NV 0x00010000
+#define GL_FONT_Y_MIN_BOUNDS_BIT_NV 0x00020000
+#define GL_FONT_X_MAX_BOUNDS_BIT_NV 0x00040000
+#define GL_FONT_Y_MAX_BOUNDS_BIT_NV 0x00080000
+#define GL_FONT_UNITS_PER_EM_BIT_NV 0x00100000
+#define GL_FONT_ASCENDER_BIT_NV 0x00200000
+#define GL_FONT_DESCENDER_BIT_NV 0x00400000
+#define GL_FONT_HEIGHT_BIT_NV 0x00800000
+#define GL_FONT_MAX_ADVANCE_WIDTH_BIT_NV 0x01000000
+#define GL_FONT_MAX_ADVANCE_HEIGHT_BIT_NV 0x02000000
+#define GL_FONT_UNDERLINE_POSITION_BIT_NV 0x04000000
+#define GL_FONT_UNDERLINE_THICKNESS_BIT_NV 0x08000000
+#define GL_FONT_HAS_KERNING_BIT_NV 0x10000000
typedef void (GLAPIENTRY * PFNGLCOPYPATHNVPROC) (GLuint resultPath, GLuint srcPath);
typedef void (GLAPIENTRY * PFNGLCOVERFILLPATHINSTANCEDNVPROC) (GLsizei numPaths, GLenum pathNameType, const void* paths, GLuint pathBase, GLenum coverMode, GLenum transformType, const GLfloat *transformValues);
@@ -10977,7 +12414,7 @@ typedef void (GLAPIENTRY * PFNGLPATHPARAMETERFNVPROC) (GLuint path, GLenum pname
typedef void (GLAPIENTRY * PFNGLPATHPARAMETERFVNVPROC) (GLuint path, GLenum pname, const GLfloat* value);
typedef void (GLAPIENTRY * PFNGLPATHPARAMETERINVPROC) (GLuint path, GLenum pname, GLint value);
typedef void (GLAPIENTRY * PFNGLPATHPARAMETERIVNVPROC) (GLuint path, GLenum pname, const GLint* value);
-typedef void (GLAPIENTRY * PFNGLPATHSTENCILDEPTHOFFSETNVPROC) (GLfloat factor, GLint units);
+typedef void (GLAPIENTRY * PFNGLPATHSTENCILDEPTHOFFSETNVPROC) (GLfloat factor, GLfloat units);
typedef void (GLAPIENTRY * PFNGLPATHSTENCILFUNCNVPROC) (GLenum func, GLint ref, GLuint mask);
typedef void (GLAPIENTRY * PFNGLPATHSTRINGNVPROC) (GLuint path, GLenum format, GLsizei length, const void* pathString);
typedef void (GLAPIENTRY * PFNGLPATHSUBCOMMANDSNVPROC) (GLuint path, GLsizei commandStart, GLsizei commandsToDelete, GLsizei numCommands, const GLubyte* commands, GLsizei numCoords, GLenum coordType, const GLvoid*coords);
@@ -11058,7 +12495,7 @@ typedef void (GLAPIENTRY * PFNGLWEIGHTPATHSNVPROC) (GLuint resultPath, GLsizei n
#define GL_READ_PIXEL_DATA_RANGE_POINTER_NV 0x887D
typedef void (GLAPIENTRY * PFNGLFLUSHPIXELDATARANGENVPROC) (GLenum target);
-typedef void (GLAPIENTRY * PFNGLPIXELDATARANGENVPROC) (GLenum target, GLsizei length, void* pointer);
+typedef void (GLAPIENTRY * PFNGLPIXELDATARANGENVPROC) (GLenum target, GLsizei length, GLvoid *pointer);
#define glFlushPixelDataRangeNV GLEW_GET_FUN(__glewFlushPixelDataRangeNV)
#define glPixelDataRangeNV GLEW_GET_FUN(__glewPixelDataRangeNV)
@@ -11240,6 +12677,24 @@ typedef void (GLAPIENTRY * PFNGLGETCOMBINERSTAGEPARAMETERFVNVPROC) (GLenum stage
#endif /* GL_NV_register_combiners2 */
+/* ---------------------- GL_NV_shader_atomic_counters --------------------- */
+
+#ifndef GL_NV_shader_atomic_counters
+#define GL_NV_shader_atomic_counters 1
+
+#define GLEW_NV_shader_atomic_counters GLEW_GET_VAR(__GLEW_NV_shader_atomic_counters)
+
+#endif /* GL_NV_shader_atomic_counters */
+
+/* ----------------------- GL_NV_shader_atomic_float ----------------------- */
+
+#ifndef GL_NV_shader_atomic_float
+#define GL_NV_shader_atomic_float 1
+
+#define GLEW_NV_shader_atomic_float GLEW_GET_VAR(__GLEW_NV_shader_atomic_float)
+
+#endif /* GL_NV_shader_atomic_float */
+
/* ------------------------ GL_NV_shader_buffer_load ----------------------- */
#ifndef GL_NV_shader_buffer_load
@@ -11281,6 +12736,15 @@ typedef void (GLAPIENTRY * PFNGLUNIFORMUI64VNVPROC) (GLint location, GLsizei cou
#endif /* GL_NV_shader_buffer_load */
+/* ------------------- GL_NV_shader_storage_buffer_object ------------------ */
+
+#ifndef GL_NV_shader_storage_buffer_object
+#define GL_NV_shader_storage_buffer_object 1
+
+#define GLEW_NV_shader_storage_buffer_object GLEW_GET_VAR(__GLEW_NV_shader_storage_buffer_object)
+
+#endif /* GL_NV_shader_storage_buffer_object */
+
/* ---------------------- GL_NV_tessellation_program5 ---------------------- */
#ifndef GL_NV_tessellation_program5
@@ -11696,7 +13160,7 @@ typedef void (GLAPIENTRY * PFNGLVDPAUUNREGISTERSURFACENVPROC) (GLvdpauSurfaceNV
#define GL_VERTEX_ARRAY_RANGE_POINTER_NV 0x8521
typedef void (GLAPIENTRY * PFNGLFLUSHVERTEXARRAYRANGENVPROC) (void);
-typedef void (GLAPIENTRY * PFNGLVERTEXARRAYRANGENVPROC) (GLsizei length, void* pointer);
+typedef void (GLAPIENTRY * PFNGLVERTEXARRAYRANGENVPROC) (GLsizei length, GLvoid *pointer);
#define glFlushVertexArrayRangeNV GLEW_GET_FUN(__glewFlushVertexArrayRangeNV)
#define glVertexArrayRangeNV GLEW_GET_FUN(__glewVertexArrayRangeNV)
@@ -11968,7 +13432,7 @@ typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4SNVPROC) (GLuint index, GLshort x,
typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4SVNVPROC) (GLuint index, const GLshort* v);
typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4UBNVPROC) (GLuint index, GLubyte x, GLubyte y, GLubyte z, GLubyte w);
typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4UBVNVPROC) (GLuint index, const GLubyte* v);
-typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBPOINTERNVPROC) (GLuint index, GLint size, GLenum type, GLsizei stride, const void* pointer);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBPOINTERNVPROC) (GLuint index, GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);
typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBS1DVNVPROC) (GLuint index, GLsizei n, const GLdouble* v);
typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBS1FVNVPROC) (GLuint index, GLsizei n, const GLfloat* v);
typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBS1SVNVPROC) (GLuint index, GLsizei n, const GLshort* v);
@@ -12174,8 +13638,6 @@ typedef void (GLAPIENTRY * PFNGLVIDEOCAPTURESTREAMPARAMETERIVNVPROC) (GLuint vid
#ifndef GL_OES_byte_coordinates
#define GL_OES_byte_coordinates 1
-#define GL_BYTE 0x1400
-
#define GLEW_OES_byte_coordinates GLEW_GET_VAR(__GLEW_OES_byte_coordinates)
#endif /* GL_OES_byte_coordinates */
@@ -12337,6 +13799,191 @@ typedef void (GLAPIENTRY * PFNGLORTHOFOESPROC) (GLfloat l, GLfloat r, GLfloat b,
#endif /* GL_PGI_vertex_hints */
+/* ---------------------- GL_REGAL_ES1_0_compatibility --------------------- */
+
+#ifndef GL_REGAL_ES1_0_compatibility
+#define GL_REGAL_ES1_0_compatibility 1
+
+typedef int GLclampx;
+
+typedef void (GLAPIENTRY * PFNGLALPHAFUNCXPROC) (GLenum func, GLclampx ref);
+typedef void (GLAPIENTRY * PFNGLCLEARCOLORXPROC) (GLclampx red, GLclampx green, GLclampx blue, GLclampx alpha);
+typedef void (GLAPIENTRY * PFNGLCLEARDEPTHXPROC) (GLclampx depth);
+typedef void (GLAPIENTRY * PFNGLCOLOR4XPROC) (GLfixed red, GLfixed green, GLfixed blue, GLfixed alpha);
+typedef void (GLAPIENTRY * PFNGLDEPTHRANGEXPROC) (GLclampx zNear, GLclampx zFar);
+typedef void (GLAPIENTRY * PFNGLFOGXPROC) (GLenum pname, GLfixed param);
+typedef void (GLAPIENTRY * PFNGLFOGXVPROC) (GLenum pname, const GLfixed* params);
+typedef void (GLAPIENTRY * PFNGLFRUSTUMFPROC) (GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat zNear, GLfloat zFar);
+typedef void (GLAPIENTRY * PFNGLFRUSTUMXPROC) (GLfixed left, GLfixed right, GLfixed bottom, GLfixed top, GLfixed zNear, GLfixed zFar);
+typedef void (GLAPIENTRY * PFNGLLIGHTMODELXPROC) (GLenum pname, GLfixed param);
+typedef void (GLAPIENTRY * PFNGLLIGHTMODELXVPROC) (GLenum pname, const GLfixed* params);
+typedef void (GLAPIENTRY * PFNGLLIGHTXPROC) (GLenum light, GLenum pname, GLfixed param);
+typedef void (GLAPIENTRY * PFNGLLIGHTXVPROC) (GLenum light, GLenum pname, const GLfixed* params);
+typedef void (GLAPIENTRY * PFNGLLINEWIDTHXPROC) (GLfixed width);
+typedef void (GLAPIENTRY * PFNGLLOADMATRIXXPROC) (const GLfixed* m);
+typedef void (GLAPIENTRY * PFNGLMATERIALXPROC) (GLenum face, GLenum pname, GLfixed param);
+typedef void (GLAPIENTRY * PFNGLMATERIALXVPROC) (GLenum face, GLenum pname, const GLfixed* params);
+typedef void (GLAPIENTRY * PFNGLMULTMATRIXXPROC) (const GLfixed* m);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD4XPROC) (GLenum target, GLfixed s, GLfixed t, GLfixed r, GLfixed q);
+typedef void (GLAPIENTRY * PFNGLNORMAL3XPROC) (GLfixed nx, GLfixed ny, GLfixed nz);
+typedef void (GLAPIENTRY * PFNGLORTHOFPROC) (GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat zNear, GLfloat zFar);
+typedef void (GLAPIENTRY * PFNGLORTHOXPROC) (GLfixed left, GLfixed right, GLfixed bottom, GLfixed top, GLfixed zNear, GLfixed zFar);
+typedef void (GLAPIENTRY * PFNGLPOINTSIZEXPROC) (GLfixed size);
+typedef void (GLAPIENTRY * PFNGLPOLYGONOFFSETXPROC) (GLfixed factor, GLfixed units);
+typedef void (GLAPIENTRY * PFNGLROTATEXPROC) (GLfixed angle, GLfixed x, GLfixed y, GLfixed z);
+typedef void (GLAPIENTRY * PFNGLSAMPLECOVERAGEXPROC) (GLclampx value, GLboolean invert);
+typedef void (GLAPIENTRY * PFNGLSCALEXPROC) (GLfixed x, GLfixed y, GLfixed z);
+typedef void (GLAPIENTRY * PFNGLTEXENVXPROC) (GLenum target, GLenum pname, GLfixed param);
+typedef void (GLAPIENTRY * PFNGLTEXENVXVPROC) (GLenum target, GLenum pname, const GLfixed* params);
+typedef void (GLAPIENTRY * PFNGLTEXPARAMETERXPROC) (GLenum target, GLenum pname, GLfixed param);
+typedef void (GLAPIENTRY * PFNGLTRANSLATEXPROC) (GLfixed x, GLfixed y, GLfixed z);
+
+#define glAlphaFuncx GLEW_GET_FUN(__glewAlphaFuncx)
+#define glClearColorx GLEW_GET_FUN(__glewClearColorx)
+#define glClearDepthx GLEW_GET_FUN(__glewClearDepthx)
+#define glColor4x GLEW_GET_FUN(__glewColor4x)
+#define glDepthRangex GLEW_GET_FUN(__glewDepthRangex)
+#define glFogx GLEW_GET_FUN(__glewFogx)
+#define glFogxv GLEW_GET_FUN(__glewFogxv)
+#define glFrustumf GLEW_GET_FUN(__glewFrustumf)
+#define glFrustumx GLEW_GET_FUN(__glewFrustumx)
+#define glLightModelx GLEW_GET_FUN(__glewLightModelx)
+#define glLightModelxv GLEW_GET_FUN(__glewLightModelxv)
+#define glLightx GLEW_GET_FUN(__glewLightx)
+#define glLightxv GLEW_GET_FUN(__glewLightxv)
+#define glLineWidthx GLEW_GET_FUN(__glewLineWidthx)
+#define glLoadMatrixx GLEW_GET_FUN(__glewLoadMatrixx)
+#define glMaterialx GLEW_GET_FUN(__glewMaterialx)
+#define glMaterialxv GLEW_GET_FUN(__glewMaterialxv)
+#define glMultMatrixx GLEW_GET_FUN(__glewMultMatrixx)
+#define glMultiTexCoord4x GLEW_GET_FUN(__glewMultiTexCoord4x)
+#define glNormal3x GLEW_GET_FUN(__glewNormal3x)
+#define glOrthof GLEW_GET_FUN(__glewOrthof)
+#define glOrthox GLEW_GET_FUN(__glewOrthox)
+#define glPointSizex GLEW_GET_FUN(__glewPointSizex)
+#define glPolygonOffsetx GLEW_GET_FUN(__glewPolygonOffsetx)
+#define glRotatex GLEW_GET_FUN(__glewRotatex)
+#define glSampleCoveragex GLEW_GET_FUN(__glewSampleCoveragex)
+#define glScalex GLEW_GET_FUN(__glewScalex)
+#define glTexEnvx GLEW_GET_FUN(__glewTexEnvx)
+#define glTexEnvxv GLEW_GET_FUN(__glewTexEnvxv)
+#define glTexParameterx GLEW_GET_FUN(__glewTexParameterx)
+#define glTranslatex GLEW_GET_FUN(__glewTranslatex)
+
+#define GLEW_REGAL_ES1_0_compatibility GLEW_GET_VAR(__GLEW_REGAL_ES1_0_compatibility)
+
+#endif /* GL_REGAL_ES1_0_compatibility */
+
+/* ---------------------- GL_REGAL_ES1_1_compatibility --------------------- */
+
+#ifndef GL_REGAL_ES1_1_compatibility
+#define GL_REGAL_ES1_1_compatibility 1
+
+typedef void (GLAPIENTRY * PFNGLCLIPPLANEFPROC) (GLenum plane, const GLfloat* equation);
+typedef void (GLAPIENTRY * PFNGLCLIPPLANEXPROC) (GLenum plane, const GLfixed* equation);
+typedef void (GLAPIENTRY * PFNGLGETCLIPPLANEFPROC) (GLenum pname, GLfloat eqn[4]);
+typedef void (GLAPIENTRY * PFNGLGETCLIPPLANEXPROC) (GLenum pname, GLfixed eqn[4]);
+typedef void (GLAPIENTRY * PFNGLGETFIXEDVPROC) (GLenum pname, GLfixed* params);
+typedef void (GLAPIENTRY * PFNGLGETLIGHTXVPROC) (GLenum light, GLenum pname, GLfixed* params);
+typedef void (GLAPIENTRY * PFNGLGETMATERIALXVPROC) (GLenum face, GLenum pname, GLfixed* params);
+typedef void (GLAPIENTRY * PFNGLGETTEXENVXVPROC) (GLenum env, GLenum pname, GLfixed* params);
+typedef void (GLAPIENTRY * PFNGLGETTEXPARAMETERXVPROC) (GLenum target, GLenum pname, GLfixed* params);
+typedef void (GLAPIENTRY * PFNGLPOINTPARAMETERXPROC) (GLenum pname, GLfixed param);
+typedef void (GLAPIENTRY * PFNGLPOINTPARAMETERXVPROC) (GLenum pname, const GLfixed* params);
+typedef void (GLAPIENTRY * PFNGLPOINTSIZEPOINTEROESPROC) (GLenum type, GLsizei stride, const GLvoid* pointer);
+typedef void (GLAPIENTRY * PFNGLTEXPARAMETERXVPROC) (GLenum target, GLenum pname, const GLfixed* params);
+
+#define glClipPlanef GLEW_GET_FUN(__glewClipPlanef)
+#define glClipPlanex GLEW_GET_FUN(__glewClipPlanex)
+#define glGetClipPlanef GLEW_GET_FUN(__glewGetClipPlanef)
+#define glGetClipPlanex GLEW_GET_FUN(__glewGetClipPlanex)
+#define glGetFixedv GLEW_GET_FUN(__glewGetFixedv)
+#define glGetLightxv GLEW_GET_FUN(__glewGetLightxv)
+#define glGetMaterialxv GLEW_GET_FUN(__glewGetMaterialxv)
+#define glGetTexEnvxv GLEW_GET_FUN(__glewGetTexEnvxv)
+#define glGetTexParameterxv GLEW_GET_FUN(__glewGetTexParameterxv)
+#define glPointParameterx GLEW_GET_FUN(__glewPointParameterx)
+#define glPointParameterxv GLEW_GET_FUN(__glewPointParameterxv)
+#define glPointSizePointerOES GLEW_GET_FUN(__glewPointSizePointerOES)
+#define glTexParameterxv GLEW_GET_FUN(__glewTexParameterxv)
+
+#define GLEW_REGAL_ES1_1_compatibility GLEW_GET_VAR(__GLEW_REGAL_ES1_1_compatibility)
+
+#endif /* GL_REGAL_ES1_1_compatibility */
+
+/* ---------------------------- GL_REGAL_enable ---------------------------- */
+
+#ifndef GL_REGAL_enable
+#define GL_REGAL_enable 1
+
+#define GL_ERROR_REGAL 0x9322
+#define GL_DEBUG_REGAL 0x9323
+#define GL_LOG_REGAL 0x9324
+#define GL_EMULATION_REGAL 0x9325
+#define GL_DRIVER_REGAL 0x9326
+#define GL_MISSING_REGAL 0x9360
+#define GL_TRACE_REGAL 0x9361
+#define GL_CACHE_REGAL 0x9362
+#define GL_CODE_REGAL 0x9363
+#define GL_STATISTICS_REGAL 0x9364
+
+#define GLEW_REGAL_enable GLEW_GET_VAR(__GLEW_REGAL_enable)
+
+#endif /* GL_REGAL_enable */
+
+/* ------------------------- GL_REGAL_error_string ------------------------- */
+
+#ifndef GL_REGAL_error_string
+#define GL_REGAL_error_string 1
+
+typedef const GLchar* (GLAPIENTRY * PFNGLERRORSTRINGREGALPROC) (GLenum error);
+
+#define glErrorStringREGAL GLEW_GET_FUN(__glewErrorStringREGAL)
+
+#define GLEW_REGAL_error_string GLEW_GET_VAR(__GLEW_REGAL_error_string)
+
+#endif /* GL_REGAL_error_string */
+
+/* ------------------------ GL_REGAL_extension_query ----------------------- */
+
+#ifndef GL_REGAL_extension_query
+#define GL_REGAL_extension_query 1
+
+typedef GLboolean (GLAPIENTRY * PFNGLGETEXTENSIONREGALPROC) (const GLchar* ext);
+typedef GLboolean (GLAPIENTRY * PFNGLISSUPPORTEDREGALPROC) (const GLchar* ext);
+
+#define glGetExtensionREGAL GLEW_GET_FUN(__glewGetExtensionREGAL)
+#define glIsSupportedREGAL GLEW_GET_FUN(__glewIsSupportedREGAL)
+
+#define GLEW_REGAL_extension_query GLEW_GET_VAR(__GLEW_REGAL_extension_query)
+
+#endif /* GL_REGAL_extension_query */
+
+/* ------------------------------ GL_REGAL_log ----------------------------- */
+
+#ifndef GL_REGAL_log
+#define GL_REGAL_log 1
+
+#define GL_LOG_ERROR_REGAL 0x9319
+#define GL_LOG_WARNING_REGAL 0x931A
+#define GL_LOG_INFO_REGAL 0x931B
+#define GL_LOG_APP_REGAL 0x931C
+#define GL_LOG_DRIVER_REGAL 0x931D
+#define GL_LOG_INTERNAL_REGAL 0x931E
+#define GL_LOG_DEBUG_REGAL 0x931F
+#define GL_LOG_STATUS_REGAL 0x9320
+#define GL_LOG_HTTP_REGAL 0x9321
+
+typedef void (APIENTRY *GLLOGPROCREGAL)(GLenum stream, GLsizei length, const GLchar *message, GLvoid *context);
+
+typedef void (GLAPIENTRY * PFNGLLOGMESSAGECALLBACKREGALPROC) (GLLOGPROCREGAL callback);
+
+#define glLogMessageCallbackREGAL GLEW_GET_FUN(__glewLogMessageCallbackREGAL)
+
+#define GLEW_REGAL_log GLEW_GET_VAR(__GLEW_REGAL_log)
+
+#endif /* GL_REGAL_log */
+
/* ----------------------- GL_REND_screen_coordinates ---------------------- */
#ifndef GL_REND_screen_coordinates
@@ -12447,7 +14094,6 @@ typedef void (GLAPIENTRY * PFNGLGETFOGFUNCSGISPROC) (GLfloat* points);
#define GL_SAMPLE_MASK_VALUE_SGIS 0x80AA
#define GL_SAMPLE_MASK_INVERT_SGIS 0x80AB
#define GL_SAMPLE_PATTERN_SGIS 0x80AC
-#define GL_MULTISAMPLE_BIT_EXT 0x20000000
typedef void (GLAPIENTRY * PFNGLSAMPLEMASKSGISPROC) (GLclampf value, GLboolean invert);
typedef void (GLAPIENTRY * PFNGLSAMPLEPATTERNSGISPROC) (GLenum pattern);
@@ -12506,8 +14152,8 @@ typedef void (GLAPIENTRY * PFNGLSHARPENTEXFUNCSGISPROC) (GLenum target, GLsizei
#ifndef GL_SGIS_texture4D
#define GL_SGIS_texture4D 1
-typedef void (GLAPIENTRY * PFNGLTEXIMAGE4DSGISPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLsizei extent, GLint border, GLenum format, GLenum type, const void* pixels);
-typedef void (GLAPIENTRY * PFNGLTEXSUBIMAGE4DSGISPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint woffset, GLsizei width, GLsizei height, GLsizei depth, GLsizei extent, GLenum format, GLenum type, const void* pixels);
+typedef void (GLAPIENTRY * PFNGLTEXIMAGE4DSGISPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLsizei extent, GLint border, GLenum format, GLenum type, const GLvoid *pixels);
+typedef void (GLAPIENTRY * PFNGLTEXSUBIMAGE4DSGISPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint woffset, GLsizei width, GLsizei height, GLsizei depth, GLsizei extent, GLenum format, GLenum type, const GLvoid *pixels);
#define glTexImage4DSGIS GLEW_GET_FUN(__glewTexImage4DSGIS)
#define glTexSubImage4DSGIS GLEW_GET_FUN(__glewTexSubImage4DSGIS)
@@ -13082,11 +14728,11 @@ typedef void (GLAPIENTRY * PFNGLTAGSAMPLEBUFFERSGIXPROC) (void);
typedef void (GLAPIENTRY * PFNGLCOLORTABLEPARAMETERFVSGIPROC) (GLenum target, GLenum pname, const GLfloat* params);
typedef void (GLAPIENTRY * PFNGLCOLORTABLEPARAMETERIVSGIPROC) (GLenum target, GLenum pname, const GLint* params);
-typedef void (GLAPIENTRY * PFNGLCOLORTABLESGIPROC) (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const void* table);
+typedef void (GLAPIENTRY * PFNGLCOLORTABLESGIPROC) (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const GLvoid *table);
typedef void (GLAPIENTRY * PFNGLCOPYCOLORTABLESGIPROC) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width);
typedef void (GLAPIENTRY * PFNGLGETCOLORTABLEPARAMETERFVSGIPROC) (GLenum target, GLenum pname, GLfloat* params);
typedef void (GLAPIENTRY * PFNGLGETCOLORTABLEPARAMETERIVSGIPROC) (GLenum target, GLenum pname, GLint* params);
-typedef void (GLAPIENTRY * PFNGLGETCOLORTABLESGIPROC) (GLenum target, GLenum format, GLenum type, void* table);
+typedef void (GLAPIENTRY * PFNGLGETCOLORTABLESGIPROC) (GLenum target, GLenum format, GLenum type, GLvoid *table);
#define glColorTableParameterfvSGI GLEW_GET_FUN(__glewColorTableParameterfvSGI)
#define glColorTableParameterivSGI GLEW_GET_FUN(__glewColorTableParameterivSGI)
@@ -13228,7 +14874,7 @@ typedef void (GLAPIENTRY * PFNGLREADVIDEOPIXELSSUNPROC) (GLint x, GLint y, GLsiz
#define GL_R1UI_T2F_N3F_V3F_SUN 0x85CA
#define GL_R1UI_T2F_C4F_N3F_V3F_SUN 0x85CB
-typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEPOINTERSUNPROC) (GLenum type, GLsizei stride, const void* pointer);
+typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEPOINTERSUNPROC) (GLenum type, GLsizei stride, const GLvoid *pointer);
typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUBSUNPROC) (GLubyte code);
typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUBVSUNPROC) (const GLubyte* code);
typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUISUNPROC) (GLuint code);
@@ -13700,6 +15346,8 @@ GLEW_FUN_EXPORT PFNGLBLENDEQUATIONSEPARATEINDEXEDAMDPROC __glewBlendEquationSepa
GLEW_FUN_EXPORT PFNGLBLENDFUNCINDEXEDAMDPROC __glewBlendFuncIndexedAMD;
GLEW_FUN_EXPORT PFNGLBLENDFUNCSEPARATEINDEXEDAMDPROC __glewBlendFuncSeparateIndexedAMD;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBPARAMETERIAMDPROC __glewVertexAttribParameteriAMD;
+
GLEW_FUN_EXPORT PFNGLMULTIDRAWARRAYSINDIRECTAMDPROC __glewMultiDrawArraysIndirectAMD;
GLEW_FUN_EXPORT PFNGLMULTIDRAWELEMENTSINDIRECTAMDPROC __glewMultiDrawElementsIndirectAMD;
@@ -13721,9 +15369,36 @@ GLEW_FUN_EXPORT PFNGLSELECTPERFMONITORCOUNTERSAMDPROC __glewSelectPerfMonitorCou
GLEW_FUN_EXPORT PFNGLSETMULTISAMPLEFVAMDPROC __glewSetMultisamplefvAMD;
+GLEW_FUN_EXPORT PFNGLTEXSTORAGESPARSEAMDPROC __glewTexStorageSparseAMD;
+GLEW_FUN_EXPORT PFNGLTEXTURESTORAGESPARSEAMDPROC __glewTextureStorageSparseAMD;
+
+GLEW_FUN_EXPORT PFNGLSTENCILOPVALUEAMDPROC __glewStencilOpValueAMD;
+
GLEW_FUN_EXPORT PFNGLTESSELLATIONFACTORAMDPROC __glewTessellationFactorAMD;
GLEW_FUN_EXPORT PFNGLTESSELLATIONMODEAMDPROC __glewTessellationModeAMD;
+GLEW_FUN_EXPORT PFNGLBLITFRAMEBUFFERANGLEPROC __glewBlitFramebufferANGLE;
+
+GLEW_FUN_EXPORT PFNGLRENDERBUFFERSTORAGEMULTISAMPLEANGLEPROC __glewRenderbufferStorageMultisampleANGLE;
+
+GLEW_FUN_EXPORT PFNGLDRAWARRAYSINSTANCEDANGLEPROC __glewDrawArraysInstancedANGLE;
+GLEW_FUN_EXPORT PFNGLDRAWELEMENTSINSTANCEDANGLEPROC __glewDrawElementsInstancedANGLE;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBDIVISORANGLEPROC __glewVertexAttribDivisorANGLE;
+
+GLEW_FUN_EXPORT PFNGLBEGINQUERYANGLEPROC __glewBeginQueryANGLE;
+GLEW_FUN_EXPORT PFNGLDELETEQUERIESANGLEPROC __glewDeleteQueriesANGLE;
+GLEW_FUN_EXPORT PFNGLENDQUERYANGLEPROC __glewEndQueryANGLE;
+GLEW_FUN_EXPORT PFNGLGENQUERIESANGLEPROC __glewGenQueriesANGLE;
+GLEW_FUN_EXPORT PFNGLGETQUERYOBJECTI64VANGLEPROC __glewGetQueryObjecti64vANGLE;
+GLEW_FUN_EXPORT PFNGLGETQUERYOBJECTIVANGLEPROC __glewGetQueryObjectivANGLE;
+GLEW_FUN_EXPORT PFNGLGETQUERYOBJECTUI64VANGLEPROC __glewGetQueryObjectui64vANGLE;
+GLEW_FUN_EXPORT PFNGLGETQUERYOBJECTUIVANGLEPROC __glewGetQueryObjectuivANGLE;
+GLEW_FUN_EXPORT PFNGLGETQUERYIVANGLEPROC __glewGetQueryivANGLE;
+GLEW_FUN_EXPORT PFNGLISQUERYANGLEPROC __glewIsQueryANGLE;
+GLEW_FUN_EXPORT PFNGLQUERYCOUNTERANGLEPROC __glewQueryCounterANGLE;
+
+GLEW_FUN_EXPORT PFNGLGETTRANSLATEDSHADERSOURCEANGLEPROC __glewGetTranslatedShaderSourceANGLE;
+
GLEW_FUN_EXPORT PFNGLDRAWELEMENTARRAYAPPLEPROC __glewDrawElementArrayAPPLE;
GLEW_FUN_EXPORT PFNGLDRAWRANGEELEMENTARRAYAPPLEPROC __glewDrawRangeElementArrayAPPLE;
GLEW_FUN_EXPORT PFNGLELEMENTPOINTERAPPLEPROC __glewElementPointerAPPLE;
@@ -13776,15 +15451,50 @@ GLEW_FUN_EXPORT PFNGLDRAWARRAYSINSTANCEDBASEINSTANCEPROC __glewDrawArraysInstanc
GLEW_FUN_EXPORT PFNGLDRAWELEMENTSINSTANCEDBASEINSTANCEPROC __glewDrawElementsInstancedBaseInstance;
GLEW_FUN_EXPORT PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXBASEINSTANCEPROC __glewDrawElementsInstancedBaseVertexBaseInstance;
+GLEW_FUN_EXPORT PFNGLGETIMAGEHANDLEARBPROC __glewGetImageHandleARB;
+GLEW_FUN_EXPORT PFNGLGETTEXTUREHANDLEARBPROC __glewGetTextureHandleARB;
+GLEW_FUN_EXPORT PFNGLGETTEXTURESAMPLERHANDLEARBPROC __glewGetTextureSamplerHandleARB;
+GLEW_FUN_EXPORT PFNGLGETVERTEXATTRIBLUI64VARBPROC __glewGetVertexAttribLui64vARB;
+GLEW_FUN_EXPORT PFNGLISIMAGEHANDLERESIDENTARBPROC __glewIsImageHandleResidentARB;
+GLEW_FUN_EXPORT PFNGLISTEXTUREHANDLERESIDENTARBPROC __glewIsTextureHandleResidentARB;
+GLEW_FUN_EXPORT PFNGLMAKEIMAGEHANDLENONRESIDENTARBPROC __glewMakeImageHandleNonResidentARB;
+GLEW_FUN_EXPORT PFNGLMAKEIMAGEHANDLERESIDENTARBPROC __glewMakeImageHandleResidentARB;
+GLEW_FUN_EXPORT PFNGLMAKETEXTUREHANDLENONRESIDENTARBPROC __glewMakeTextureHandleNonResidentARB;
+GLEW_FUN_EXPORT PFNGLMAKETEXTUREHANDLERESIDENTARBPROC __glewMakeTextureHandleResidentARB;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMHANDLEUI64ARBPROC __glewProgramUniformHandleui64ARB;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMHANDLEUI64VARBPROC __glewProgramUniformHandleui64vARB;
+GLEW_FUN_EXPORT PFNGLUNIFORMHANDLEUI64ARBPROC __glewUniformHandleui64ARB;
+GLEW_FUN_EXPORT PFNGLUNIFORMHANDLEUI64VARBPROC __glewUniformHandleui64vARB;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL1UI64ARBPROC __glewVertexAttribL1ui64ARB;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL1UI64VARBPROC __glewVertexAttribL1ui64vARB;
+
GLEW_FUN_EXPORT PFNGLBINDFRAGDATALOCATIONINDEXEDPROC __glewBindFragDataLocationIndexed;
GLEW_FUN_EXPORT PFNGLGETFRAGDATAINDEXPROC __glewGetFragDataIndex;
+GLEW_FUN_EXPORT PFNGLBUFFERSTORAGEPROC __glewBufferStorage;
+GLEW_FUN_EXPORT PFNGLNAMEDBUFFERSTORAGEEXTPROC __glewNamedBufferStorageEXT;
+
GLEW_FUN_EXPORT PFNGLCREATESYNCFROMCLEVENTARBPROC __glewCreateSyncFromCLeventARB;
+GLEW_FUN_EXPORT PFNGLCLEARBUFFERDATAPROC __glewClearBufferData;
+GLEW_FUN_EXPORT PFNGLCLEARBUFFERSUBDATAPROC __glewClearBufferSubData;
+GLEW_FUN_EXPORT PFNGLCLEARNAMEDBUFFERDATAEXTPROC __glewClearNamedBufferDataEXT;
+GLEW_FUN_EXPORT PFNGLCLEARNAMEDBUFFERSUBDATAEXTPROC __glewClearNamedBufferSubDataEXT;
+
+GLEW_FUN_EXPORT PFNGLCLEARTEXIMAGEPROC __glewClearTexImage;
+GLEW_FUN_EXPORT PFNGLCLEARTEXSUBIMAGEPROC __glewClearTexSubImage;
+
GLEW_FUN_EXPORT PFNGLCLAMPCOLORARBPROC __glewClampColorARB;
+GLEW_FUN_EXPORT PFNGLDISPATCHCOMPUTEPROC __glewDispatchCompute;
+GLEW_FUN_EXPORT PFNGLDISPATCHCOMPUTEINDIRECTPROC __glewDispatchComputeIndirect;
+
+GLEW_FUN_EXPORT PFNGLDISPATCHCOMPUTEGROUPSIZEARBPROC __glewDispatchComputeGroupSizeARB;
+
GLEW_FUN_EXPORT PFNGLCOPYBUFFERSUBDATAPROC __glewCopyBufferSubData;
+GLEW_FUN_EXPORT PFNGLCOPYIMAGESUBDATAPROC __glewCopyImageSubData;
+
GLEW_FUN_EXPORT PFNGLDEBUGMESSAGECALLBACKARBPROC __glewDebugMessageCallbackARB;
GLEW_FUN_EXPORT PFNGLDEBUGMESSAGECONTROLARBPROC __glewDebugMessageControlARB;
GLEW_FUN_EXPORT PFNGLDEBUGMESSAGEINSERTARBPROC __glewDebugMessageInsertARB;
@@ -13805,6 +15515,11 @@ GLEW_FUN_EXPORT PFNGLMULTIDRAWELEMENTSBASEVERTEXPROC __glewMultiDrawElementsBase
GLEW_FUN_EXPORT PFNGLDRAWARRAYSINDIRECTPROC __glewDrawArraysIndirect;
GLEW_FUN_EXPORT PFNGLDRAWELEMENTSINDIRECTPROC __glewDrawElementsIndirect;
+GLEW_FUN_EXPORT PFNGLFRAMEBUFFERPARAMETERIPROC __glewFramebufferParameteri;
+GLEW_FUN_EXPORT PFNGLGETFRAMEBUFFERPARAMETERIVPROC __glewGetFramebufferParameteriv;
+GLEW_FUN_EXPORT PFNGLGETNAMEDFRAMEBUFFERPARAMETERIVEXTPROC __glewGetNamedFramebufferParameterivEXT;
+GLEW_FUN_EXPORT PFNGLNAMEDFRAMEBUFFERPARAMETERIEXTPROC __glewNamedFramebufferParameteriEXT;
+
GLEW_FUN_EXPORT PFNGLBINDFRAMEBUFFERPROC __glewBindFramebuffer;
GLEW_FUN_EXPORT PFNGLBINDRENDERBUFFERPROC __glewBindRenderbuffer;
GLEW_FUN_EXPORT PFNGLBLITFRAMEBUFFERPROC __glewBlitFramebuffer;
@@ -13836,23 +15551,6 @@ GLEW_FUN_EXPORT PFNGLPROGRAMBINARYPROC __glewProgramBinary;
GLEW_FUN_EXPORT PFNGLPROGRAMPARAMETERIPROC __glewProgramParameteri;
GLEW_FUN_EXPORT PFNGLGETUNIFORMDVPROC __glewGetUniformdv;
-GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM1DEXTPROC __glewProgramUniform1dEXT;
-GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM1DVEXTPROC __glewProgramUniform1dvEXT;
-GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM2DEXTPROC __glewProgramUniform2dEXT;
-GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM2DVEXTPROC __glewProgramUniform2dvEXT;
-GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM3DEXTPROC __glewProgramUniform3dEXT;
-GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM3DVEXTPROC __glewProgramUniform3dvEXT;
-GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM4DEXTPROC __glewProgramUniform4dEXT;
-GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM4DVEXTPROC __glewProgramUniform4dvEXT;
-GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX2DVEXTPROC __glewProgramUniformMatrix2dvEXT;
-GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX2X3DVEXTPROC __glewProgramUniformMatrix2x3dvEXT;
-GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX2X4DVEXTPROC __glewProgramUniformMatrix2x4dvEXT;
-GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX3DVEXTPROC __glewProgramUniformMatrix3dvEXT;
-GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX3X2DVEXTPROC __glewProgramUniformMatrix3x2dvEXT;
-GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX3X4DVEXTPROC __glewProgramUniformMatrix3x4dvEXT;
-GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX4DVEXTPROC __glewProgramUniformMatrix4dvEXT;
-GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX4X2DVEXTPROC __glewProgramUniformMatrix4x2dvEXT;
-GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX4X3DVEXTPROC __glewProgramUniformMatrix4x3dvEXT;
GLEW_FUN_EXPORT PFNGLUNIFORM1DPROC __glewUniform1d;
GLEW_FUN_EXPORT PFNGLUNIFORM1DVPROC __glewUniform1dv;
GLEW_FUN_EXPORT PFNGLUNIFORM2DPROC __glewUniform2d;
@@ -13904,12 +15602,24 @@ GLEW_FUN_EXPORT PFNGLRESETHISTOGRAMPROC __glewResetHistogram;
GLEW_FUN_EXPORT PFNGLRESETMINMAXPROC __glewResetMinmax;
GLEW_FUN_EXPORT PFNGLSEPARABLEFILTER2DPROC __glewSeparableFilter2D;
+GLEW_FUN_EXPORT PFNGLMULTIDRAWARRAYSINDIRECTCOUNTARBPROC __glewMultiDrawArraysIndirectCountARB;
+GLEW_FUN_EXPORT PFNGLMULTIDRAWELEMENTSINDIRECTCOUNTARBPROC __glewMultiDrawElementsIndirectCountARB;
+
GLEW_FUN_EXPORT PFNGLDRAWARRAYSINSTANCEDARBPROC __glewDrawArraysInstancedARB;
GLEW_FUN_EXPORT PFNGLDRAWELEMENTSINSTANCEDARBPROC __glewDrawElementsInstancedARB;
GLEW_FUN_EXPORT PFNGLVERTEXATTRIBDIVISORARBPROC __glewVertexAttribDivisorARB;
GLEW_FUN_EXPORT PFNGLGETINTERNALFORMATIVPROC __glewGetInternalformativ;
+GLEW_FUN_EXPORT PFNGLGETINTERNALFORMATI64VPROC __glewGetInternalformati64v;
+
+GLEW_FUN_EXPORT PFNGLINVALIDATEBUFFERDATAPROC __glewInvalidateBufferData;
+GLEW_FUN_EXPORT PFNGLINVALIDATEBUFFERSUBDATAPROC __glewInvalidateBufferSubData;
+GLEW_FUN_EXPORT PFNGLINVALIDATEFRAMEBUFFERPROC __glewInvalidateFramebuffer;
+GLEW_FUN_EXPORT PFNGLINVALIDATESUBFRAMEBUFFERPROC __glewInvalidateSubFramebuffer;
+GLEW_FUN_EXPORT PFNGLINVALIDATETEXIMAGEPROC __glewInvalidateTexImage;
+GLEW_FUN_EXPORT PFNGLINVALIDATETEXSUBIMAGEPROC __glewInvalidateTexSubImage;
+
GLEW_FUN_EXPORT PFNGLFLUSHMAPPEDBUFFERRANGEPROC __glewFlushMappedBufferRange;
GLEW_FUN_EXPORT PFNGLMAPBUFFERRANGEPROC __glewMapBufferRange;
@@ -13919,6 +15629,16 @@ GLEW_FUN_EXPORT PFNGLMATRIXINDEXUBVARBPROC __glewMatrixIndexubvARB;
GLEW_FUN_EXPORT PFNGLMATRIXINDEXUIVARBPROC __glewMatrixIndexuivARB;
GLEW_FUN_EXPORT PFNGLMATRIXINDEXUSVARBPROC __glewMatrixIndexusvARB;
+GLEW_FUN_EXPORT PFNGLBINDBUFFERSBASEPROC __glewBindBuffersBase;
+GLEW_FUN_EXPORT PFNGLBINDBUFFERSRANGEPROC __glewBindBuffersRange;
+GLEW_FUN_EXPORT PFNGLBINDIMAGETEXTURESPROC __glewBindImageTextures;
+GLEW_FUN_EXPORT PFNGLBINDSAMPLERSPROC __glewBindSamplers;
+GLEW_FUN_EXPORT PFNGLBINDTEXTURESPROC __glewBindTextures;
+GLEW_FUN_EXPORT PFNGLBINDVERTEXBUFFERSPROC __glewBindVertexBuffers;
+
+GLEW_FUN_EXPORT PFNGLMULTIDRAWARRAYSINDIRECTPROC __glewMultiDrawArraysIndirect;
+GLEW_FUN_EXPORT PFNGLMULTIDRAWELEMENTSINDIRECTPROC __glewMultiDrawElementsIndirect;
+
GLEW_FUN_EXPORT PFNGLSAMPLECOVERAGEARBPROC __glewSampleCoverageARB;
GLEW_FUN_EXPORT PFNGLACTIVETEXTUREARBPROC __glewActiveTextureARB;
@@ -13968,6 +15688,13 @@ GLEW_FUN_EXPORT PFNGLISQUERYARBPROC __glewIsQueryARB;
GLEW_FUN_EXPORT PFNGLPOINTPARAMETERFARBPROC __glewPointParameterfARB;
GLEW_FUN_EXPORT PFNGLPOINTPARAMETERFVARBPROC __glewPointParameterfvARB;
+GLEW_FUN_EXPORT PFNGLGETPROGRAMINTERFACEIVPROC __glewGetProgramInterfaceiv;
+GLEW_FUN_EXPORT PFNGLGETPROGRAMRESOURCEINDEXPROC __glewGetProgramResourceIndex;
+GLEW_FUN_EXPORT PFNGLGETPROGRAMRESOURCELOCATIONPROC __glewGetProgramResourceLocation;
+GLEW_FUN_EXPORT PFNGLGETPROGRAMRESOURCELOCATIONINDEXPROC __glewGetProgramResourceLocationIndex;
+GLEW_FUN_EXPORT PFNGLGETPROGRAMRESOURCENAMEPROC __glewGetProgramResourceName;
+GLEW_FUN_EXPORT PFNGLGETPROGRAMRESOURCEIVPROC __glewGetProgramResourceiv;
+
GLEW_FUN_EXPORT PFNGLPROVOKINGVERTEXPROC __glewProvokingVertex;
GLEW_FUN_EXPORT PFNGLGETGRAPHICSRESETSTATUSARBPROC __glewGetGraphicsResetStatusARB;
@@ -14114,6 +15841,8 @@ GLEW_FUN_EXPORT PFNGLUNIFORMMATRIX4FVARBPROC __glewUniformMatrix4fvARB;
GLEW_FUN_EXPORT PFNGLUSEPROGRAMOBJECTARBPROC __glewUseProgramObjectARB;
GLEW_FUN_EXPORT PFNGLVALIDATEPROGRAMARBPROC __glewValidateProgramARB;
+GLEW_FUN_EXPORT PFNGLSHADERSTORAGEBLOCKBINDINGPROC __glewShaderStorageBlockBinding;
+
GLEW_FUN_EXPORT PFNGLGETACTIVESUBROUTINENAMEPROC __glewGetActiveSubroutineName;
GLEW_FUN_EXPORT PFNGLGETACTIVESUBROUTINEUNIFORMNAMEPROC __glewGetActiveSubroutineUniformName;
GLEW_FUN_EXPORT PFNGLGETACTIVESUBROUTINEUNIFORMIVPROC __glewGetActiveSubroutineUniformiv;
@@ -14130,6 +15859,9 @@ GLEW_FUN_EXPORT PFNGLGETNAMEDSTRINGIVARBPROC __glewGetNamedStringivARB;
GLEW_FUN_EXPORT PFNGLISNAMEDSTRINGARBPROC __glewIsNamedStringARB;
GLEW_FUN_EXPORT PFNGLNAMEDSTRINGARBPROC __glewNamedStringARB;
+GLEW_FUN_EXPORT PFNGLTEXPAGECOMMITMENTARBPROC __glewTexPageCommitmentARB;
+GLEW_FUN_EXPORT PFNGLTEXTUREPAGECOMMITMENTEXTPROC __glewTexturePageCommitmentEXT;
+
GLEW_FUN_EXPORT PFNGLCLIENTWAITSYNCPROC __glewClientWaitSync;
GLEW_FUN_EXPORT PFNGLDELETESYNCPROC __glewDeleteSync;
GLEW_FUN_EXPORT PFNGLFENCESYNCPROC __glewFenceSync;
@@ -14143,6 +15875,9 @@ GLEW_FUN_EXPORT PFNGLPATCHPARAMETERIPROC __glewPatchParameteri;
GLEW_FUN_EXPORT PFNGLTEXBUFFERARBPROC __glewTexBufferARB;
+GLEW_FUN_EXPORT PFNGLTEXBUFFERRANGEPROC __glewTexBufferRange;
+GLEW_FUN_EXPORT PFNGLTEXTUREBUFFERRANGEEXTPROC __glewTextureBufferRangeEXT;
+
GLEW_FUN_EXPORT PFNGLCOMPRESSEDTEXIMAGE1DARBPROC __glewCompressedTexImage1DARB;
GLEW_FUN_EXPORT PFNGLCOMPRESSEDTEXIMAGE2DARBPROC __glewCompressedTexImage2DARB;
GLEW_FUN_EXPORT PFNGLCOMPRESSEDTEXIMAGE3DARBPROC __glewCompressedTexImage3DARB;
@@ -14163,6 +15898,13 @@ GLEW_FUN_EXPORT PFNGLTEXTURESTORAGE1DEXTPROC __glewTextureStorage1DEXT;
GLEW_FUN_EXPORT PFNGLTEXTURESTORAGE2DEXTPROC __glewTextureStorage2DEXT;
GLEW_FUN_EXPORT PFNGLTEXTURESTORAGE3DEXTPROC __glewTextureStorage3DEXT;
+GLEW_FUN_EXPORT PFNGLTEXSTORAGE2DMULTISAMPLEPROC __glewTexStorage2DMultisample;
+GLEW_FUN_EXPORT PFNGLTEXSTORAGE3DMULTISAMPLEPROC __glewTexStorage3DMultisample;
+GLEW_FUN_EXPORT PFNGLTEXTURESTORAGE2DMULTISAMPLEEXTPROC __glewTextureStorage2DMultisampleEXT;
+GLEW_FUN_EXPORT PFNGLTEXTURESTORAGE3DMULTISAMPLEEXTPROC __glewTextureStorage3DMultisampleEXT;
+
+GLEW_FUN_EXPORT PFNGLTEXTUREVIEWPROC __glewTextureView;
+
GLEW_FUN_EXPORT PFNGLGETQUERYOBJECTI64VPROC __glewGetQueryObjecti64v;
GLEW_FUN_EXPORT PFNGLGETQUERYOBJECTUI64VPROC __glewGetQueryObjectui64v;
GLEW_FUN_EXPORT PFNGLQUERYCOUNTERPROC __glewQueryCounter;
@@ -14215,6 +15957,13 @@ GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL4DPROC __glewVertexAttribL4d;
GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL4DVPROC __glewVertexAttribL4dv;
GLEW_FUN_EXPORT PFNGLVERTEXATTRIBLPOINTERPROC __glewVertexAttribLPointer;
+GLEW_FUN_EXPORT PFNGLBINDVERTEXBUFFERPROC __glewBindVertexBuffer;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBBINDINGPROC __glewVertexAttribBinding;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBFORMATPROC __glewVertexAttribFormat;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBIFORMATPROC __glewVertexAttribIFormat;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBLFORMATPROC __glewVertexAttribLFormat;
+GLEW_FUN_EXPORT PFNGLVERTEXBINDINGDIVISORPROC __glewVertexBindingDivisor;
+
GLEW_FUN_EXPORT PFNGLVERTEXBLENDARBPROC __glewVertexBlendARB;
GLEW_FUN_EXPORT PFNGLWEIGHTPOINTERARBPROC __glewWeightPointerARB;
GLEW_FUN_EXPORT PFNGLWEIGHTBVARBPROC __glewWeightbvARB;
@@ -14437,6 +16186,14 @@ GLEW_FUN_EXPORT PFNGLNORMALSTREAM3SATIPROC __glewNormalStream3sATI;
GLEW_FUN_EXPORT PFNGLNORMALSTREAM3SVATIPROC __glewNormalStream3svATI;
GLEW_FUN_EXPORT PFNGLVERTEXBLENDENVFATIPROC __glewVertexBlendEnvfATI;
GLEW_FUN_EXPORT PFNGLVERTEXBLENDENVIATIPROC __glewVertexBlendEnviATI;
+GLEW_FUN_EXPORT PFNGLVERTEXSTREAM1DATIPROC __glewVertexStream1dATI;
+GLEW_FUN_EXPORT PFNGLVERTEXSTREAM1DVATIPROC __glewVertexStream1dvATI;
+GLEW_FUN_EXPORT PFNGLVERTEXSTREAM1FATIPROC __glewVertexStream1fATI;
+GLEW_FUN_EXPORT PFNGLVERTEXSTREAM1FVATIPROC __glewVertexStream1fvATI;
+GLEW_FUN_EXPORT PFNGLVERTEXSTREAM1IATIPROC __glewVertexStream1iATI;
+GLEW_FUN_EXPORT PFNGLVERTEXSTREAM1IVATIPROC __glewVertexStream1ivATI;
+GLEW_FUN_EXPORT PFNGLVERTEXSTREAM1SATIPROC __glewVertexStream1sATI;
+GLEW_FUN_EXPORT PFNGLVERTEXSTREAM1SVATIPROC __glewVertexStream1svATI;
GLEW_FUN_EXPORT PFNGLVERTEXSTREAM2DATIPROC __glewVertexStream2dATI;
GLEW_FUN_EXPORT PFNGLVERTEXSTREAM2DVATIPROC __glewVertexStream2dvATI;
GLEW_FUN_EXPORT PFNGLVERTEXSTREAM2FATIPROC __glewVertexStream2fATI;
@@ -14506,6 +16263,10 @@ GLEW_FUN_EXPORT PFNGLCOPYTEXSUBIMAGE3DEXTPROC __glewCopyTexSubImage3DEXT;
GLEW_FUN_EXPORT PFNGLCULLPARAMETERDVEXTPROC __glewCullParameterdvEXT;
GLEW_FUN_EXPORT PFNGLCULLPARAMETERFVEXTPROC __glewCullParameterfvEXT;
+GLEW_FUN_EXPORT PFNGLINSERTEVENTMARKEREXTPROC __glewInsertEventMarkerEXT;
+GLEW_FUN_EXPORT PFNGLPOPGROUPMARKEREXTPROC __glewPopGroupMarkerEXT;
+GLEW_FUN_EXPORT PFNGLPUSHGROUPMARKEREXTPROC __glewPushGroupMarkerEXT;
+
GLEW_FUN_EXPORT PFNGLDEPTHBOUNDSEXTPROC __glewDepthBoundsEXT;
GLEW_FUN_EXPORT PFNGLBINDMULTITEXTUREEXTPROC __glewBindMultiTextureEXT;
@@ -15027,6 +16788,10 @@ GLEW_FUN_EXPORT PFNGLSECONDARYCOLORPOINTERLISTIBMPROC __glewSecondaryColorPointe
GLEW_FUN_EXPORT PFNGLTEXCOORDPOINTERLISTIBMPROC __glewTexCoordPointerListIBM;
GLEW_FUN_EXPORT PFNGLVERTEXPOINTERLISTIBMPROC __glewVertexPointerListIBM;
+GLEW_FUN_EXPORT PFNGLMAPTEXTURE2DINTELPROC __glewMapTexture2DINTEL;
+GLEW_FUN_EXPORT PFNGLSYNCTEXTUREINTELPROC __glewSyncTextureINTEL;
+GLEW_FUN_EXPORT PFNGLUNMAPTEXTURE2DINTELPROC __glewUnmapTexture2DINTEL;
+
GLEW_FUN_EXPORT PFNGLCOLORPOINTERVINTELPROC __glewColorPointervINTEL;
GLEW_FUN_EXPORT PFNGLNORMALPOINTERVINTELPROC __glewNormalPointervINTEL;
GLEW_FUN_EXPORT PFNGLTEXCOORDPOINTERVINTELPROC __glewTexCoordPointervINTEL;
@@ -15035,6 +16800,17 @@ GLEW_FUN_EXPORT PFNGLVERTEXPOINTERVINTELPROC __glewVertexPointervINTEL;
GLEW_FUN_EXPORT PFNGLTEXSCISSORFUNCINTELPROC __glewTexScissorFuncINTEL;
GLEW_FUN_EXPORT PFNGLTEXSCISSORINTELPROC __glewTexScissorINTEL;
+GLEW_FUN_EXPORT PFNGLDEBUGMESSAGECALLBACKPROC __glewDebugMessageCallback;
+GLEW_FUN_EXPORT PFNGLDEBUGMESSAGECONTROLPROC __glewDebugMessageControl;
+GLEW_FUN_EXPORT PFNGLDEBUGMESSAGEINSERTPROC __glewDebugMessageInsert;
+GLEW_FUN_EXPORT PFNGLGETDEBUGMESSAGELOGPROC __glewGetDebugMessageLog;
+GLEW_FUN_EXPORT PFNGLGETOBJECTLABELPROC __glewGetObjectLabel;
+GLEW_FUN_EXPORT PFNGLGETOBJECTPTRLABELPROC __glewGetObjectPtrLabel;
+GLEW_FUN_EXPORT PFNGLOBJECTLABELPROC __glewObjectLabel;
+GLEW_FUN_EXPORT PFNGLOBJECTPTRLABELPROC __glewObjectPtrLabel;
+GLEW_FUN_EXPORT PFNGLPOPDEBUGGROUPPROC __glewPopDebugGroup;
+GLEW_FUN_EXPORT PFNGLPUSHDEBUGGROUPPROC __glewPushDebugGroup;
+
GLEW_FUN_EXPORT PFNGLBUFFERREGIONENABLEDPROC __glewBufferRegionEnabled;
GLEW_FUN_EXPORT PFNGLDELETEBUFFERREGIONPROC __glewDeleteBufferRegion;
GLEW_FUN_EXPORT PFNGLDRAWBUFFERREGIONPROC __glewDrawBufferRegion;
@@ -15068,6 +16844,29 @@ GLEW_FUN_EXPORT PFNGLWINDOWPOS4IVMESAPROC __glewWindowPos4ivMESA;
GLEW_FUN_EXPORT PFNGLWINDOWPOS4SMESAPROC __glewWindowPos4sMESA;
GLEW_FUN_EXPORT PFNGLWINDOWPOS4SVMESAPROC __glewWindowPos4svMESA;
+GLEW_FUN_EXPORT PFNGLBEGINCONDITIONALRENDERNVXPROC __glewBeginConditionalRenderNVX;
+GLEW_FUN_EXPORT PFNGLENDCONDITIONALRENDERNVXPROC __glewEndConditionalRenderNVX;
+
+GLEW_FUN_EXPORT PFNGLMULTIDRAWARRAYSINDIRECTBINDLESSNVPROC __glewMultiDrawArraysIndirectBindlessNV;
+GLEW_FUN_EXPORT PFNGLMULTIDRAWELEMENTSINDIRECTBINDLESSNVPROC __glewMultiDrawElementsIndirectBindlessNV;
+
+GLEW_FUN_EXPORT PFNGLGETIMAGEHANDLENVPROC __glewGetImageHandleNV;
+GLEW_FUN_EXPORT PFNGLGETTEXTUREHANDLENVPROC __glewGetTextureHandleNV;
+GLEW_FUN_EXPORT PFNGLGETTEXTURESAMPLERHANDLENVPROC __glewGetTextureSamplerHandleNV;
+GLEW_FUN_EXPORT PFNGLISIMAGEHANDLERESIDENTNVPROC __glewIsImageHandleResidentNV;
+GLEW_FUN_EXPORT PFNGLISTEXTUREHANDLERESIDENTNVPROC __glewIsTextureHandleResidentNV;
+GLEW_FUN_EXPORT PFNGLMAKEIMAGEHANDLENONRESIDENTNVPROC __glewMakeImageHandleNonResidentNV;
+GLEW_FUN_EXPORT PFNGLMAKEIMAGEHANDLERESIDENTNVPROC __glewMakeImageHandleResidentNV;
+GLEW_FUN_EXPORT PFNGLMAKETEXTUREHANDLENONRESIDENTNVPROC __glewMakeTextureHandleNonResidentNV;
+GLEW_FUN_EXPORT PFNGLMAKETEXTUREHANDLERESIDENTNVPROC __glewMakeTextureHandleResidentNV;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMHANDLEUI64NVPROC __glewProgramUniformHandleui64NV;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMHANDLEUI64VNVPROC __glewProgramUniformHandleui64vNV;
+GLEW_FUN_EXPORT PFNGLUNIFORMHANDLEUI64NVPROC __glewUniformHandleui64NV;
+GLEW_FUN_EXPORT PFNGLUNIFORMHANDLEUI64VNVPROC __glewUniformHandleui64vNV;
+
+GLEW_FUN_EXPORT PFNGLBLENDBARRIERNVPROC __glewBlendBarrierNV;
+GLEW_FUN_EXPORT PFNGLBLENDPARAMETERINVPROC __glewBlendParameteriNV;
+
GLEW_FUN_EXPORT PFNGLBEGINCONDITIONALRENDERNVPROC __glewBeginConditionalRenderNV;
GLEW_FUN_EXPORT PFNGLENDCONDITIONALRENDERNVPROC __glewEndConditionalRenderNV;
@@ -15077,6 +16876,8 @@ GLEW_FUN_EXPORT PFNGLCLEARDEPTHDNVPROC __glewClearDepthdNV;
GLEW_FUN_EXPORT PFNGLDEPTHBOUNDSDNVPROC __glewDepthBoundsdNV;
GLEW_FUN_EXPORT PFNGLDEPTHRANGEDNVPROC __glewDepthRangedNV;
+GLEW_FUN_EXPORT PFNGLDRAWTEXTURENVPROC __glewDrawTextureNV;
+
GLEW_FUN_EXPORT PFNGLEVALMAPSNVPROC __glewEvalMapsNV;
GLEW_FUN_EXPORT PFNGLGETMAPATTRIBPARAMETERFVNVPROC __glewGetMapAttribParameterfvNV;
GLEW_FUN_EXPORT PFNGLGETMAPATTRIBPARAMETERIVNVPROC __glewGetMapAttribParameterivNV;
@@ -15475,6 +17276,59 @@ GLEW_FUN_EXPORT PFNGLFRUSTUMFOESPROC __glewFrustumfOES;
GLEW_FUN_EXPORT PFNGLGETCLIPPLANEFOESPROC __glewGetClipPlanefOES;
GLEW_FUN_EXPORT PFNGLORTHOFOESPROC __glewOrthofOES;
+GLEW_FUN_EXPORT PFNGLALPHAFUNCXPROC __glewAlphaFuncx;
+GLEW_FUN_EXPORT PFNGLCLEARCOLORXPROC __glewClearColorx;
+GLEW_FUN_EXPORT PFNGLCLEARDEPTHXPROC __glewClearDepthx;
+GLEW_FUN_EXPORT PFNGLCOLOR4XPROC __glewColor4x;
+GLEW_FUN_EXPORT PFNGLDEPTHRANGEXPROC __glewDepthRangex;
+GLEW_FUN_EXPORT PFNGLFOGXPROC __glewFogx;
+GLEW_FUN_EXPORT PFNGLFOGXVPROC __glewFogxv;
+GLEW_FUN_EXPORT PFNGLFRUSTUMFPROC __glewFrustumf;
+GLEW_FUN_EXPORT PFNGLFRUSTUMXPROC __glewFrustumx;
+GLEW_FUN_EXPORT PFNGLLIGHTMODELXPROC __glewLightModelx;
+GLEW_FUN_EXPORT PFNGLLIGHTMODELXVPROC __glewLightModelxv;
+GLEW_FUN_EXPORT PFNGLLIGHTXPROC __glewLightx;
+GLEW_FUN_EXPORT PFNGLLIGHTXVPROC __glewLightxv;
+GLEW_FUN_EXPORT PFNGLLINEWIDTHXPROC __glewLineWidthx;
+GLEW_FUN_EXPORT PFNGLLOADMATRIXXPROC __glewLoadMatrixx;
+GLEW_FUN_EXPORT PFNGLMATERIALXPROC __glewMaterialx;
+GLEW_FUN_EXPORT PFNGLMATERIALXVPROC __glewMaterialxv;
+GLEW_FUN_EXPORT PFNGLMULTMATRIXXPROC __glewMultMatrixx;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD4XPROC __glewMultiTexCoord4x;
+GLEW_FUN_EXPORT PFNGLNORMAL3XPROC __glewNormal3x;
+GLEW_FUN_EXPORT PFNGLORTHOFPROC __glewOrthof;
+GLEW_FUN_EXPORT PFNGLORTHOXPROC __glewOrthox;
+GLEW_FUN_EXPORT PFNGLPOINTSIZEXPROC __glewPointSizex;
+GLEW_FUN_EXPORT PFNGLPOLYGONOFFSETXPROC __glewPolygonOffsetx;
+GLEW_FUN_EXPORT PFNGLROTATEXPROC __glewRotatex;
+GLEW_FUN_EXPORT PFNGLSAMPLECOVERAGEXPROC __glewSampleCoveragex;
+GLEW_FUN_EXPORT PFNGLSCALEXPROC __glewScalex;
+GLEW_FUN_EXPORT PFNGLTEXENVXPROC __glewTexEnvx;
+GLEW_FUN_EXPORT PFNGLTEXENVXVPROC __glewTexEnvxv;
+GLEW_FUN_EXPORT PFNGLTEXPARAMETERXPROC __glewTexParameterx;
+GLEW_FUN_EXPORT PFNGLTRANSLATEXPROC __glewTranslatex;
+
+GLEW_FUN_EXPORT PFNGLCLIPPLANEFPROC __glewClipPlanef;
+GLEW_FUN_EXPORT PFNGLCLIPPLANEXPROC __glewClipPlanex;
+GLEW_FUN_EXPORT PFNGLGETCLIPPLANEFPROC __glewGetClipPlanef;
+GLEW_FUN_EXPORT PFNGLGETCLIPPLANEXPROC __glewGetClipPlanex;
+GLEW_FUN_EXPORT PFNGLGETFIXEDVPROC __glewGetFixedv;
+GLEW_FUN_EXPORT PFNGLGETLIGHTXVPROC __glewGetLightxv;
+GLEW_FUN_EXPORT PFNGLGETMATERIALXVPROC __glewGetMaterialxv;
+GLEW_FUN_EXPORT PFNGLGETTEXENVXVPROC __glewGetTexEnvxv;
+GLEW_FUN_EXPORT PFNGLGETTEXPARAMETERXVPROC __glewGetTexParameterxv;
+GLEW_FUN_EXPORT PFNGLPOINTPARAMETERXPROC __glewPointParameterx;
+GLEW_FUN_EXPORT PFNGLPOINTPARAMETERXVPROC __glewPointParameterxv;
+GLEW_FUN_EXPORT PFNGLPOINTSIZEPOINTEROESPROC __glewPointSizePointerOES;
+GLEW_FUN_EXPORT PFNGLTEXPARAMETERXVPROC __glewTexParameterxv;
+
+GLEW_FUN_EXPORT PFNGLERRORSTRINGREGALPROC __glewErrorStringREGAL;
+
+GLEW_FUN_EXPORT PFNGLGETEXTENSIONREGALPROC __glewGetExtensionREGAL;
+GLEW_FUN_EXPORT PFNGLISSUPPORTEDREGALPROC __glewIsSupportedREGAL;
+
+GLEW_FUN_EXPORT PFNGLLOGMESSAGECALLBACKREGALPROC __glewLogMessageCallbackREGAL;
+
GLEW_FUN_EXPORT PFNGLDETAILTEXFUNCSGISPROC __glewDetailTexFuncSGIS;
GLEW_FUN_EXPORT PFNGLGETDETAILTEXFUNCSGISPROC __glewGetDetailTexFuncSGIS;
@@ -15627,6 +17481,8 @@ GLEW_VAR_EXPORT GLboolean __GLEW_VERSION_3_3;
GLEW_VAR_EXPORT GLboolean __GLEW_VERSION_4_0;
GLEW_VAR_EXPORT GLboolean __GLEW_VERSION_4_1;
GLEW_VAR_EXPORT GLboolean __GLEW_VERSION_4_2;
+GLEW_VAR_EXPORT GLboolean __GLEW_VERSION_4_3;
+GLEW_VAR_EXPORT GLboolean __GLEW_VERSION_4_4;
GLEW_VAR_EXPORT GLboolean __GLEW_3DFX_multisample;
GLEW_VAR_EXPORT GLboolean __GLEW_3DFX_tbuffer;
GLEW_VAR_EXPORT GLboolean __GLEW_3DFX_texture_compression_FXT1;
@@ -15635,15 +17491,35 @@ GLEW_VAR_EXPORT GLboolean __GLEW_AMD_conservative_depth;
GLEW_VAR_EXPORT GLboolean __GLEW_AMD_debug_output;
GLEW_VAR_EXPORT GLboolean __GLEW_AMD_depth_clamp_separate;
GLEW_VAR_EXPORT GLboolean __GLEW_AMD_draw_buffers_blend;
+GLEW_VAR_EXPORT GLboolean __GLEW_AMD_interleaved_elements;
GLEW_VAR_EXPORT GLboolean __GLEW_AMD_multi_draw_indirect;
GLEW_VAR_EXPORT GLboolean __GLEW_AMD_name_gen_delete;
GLEW_VAR_EXPORT GLboolean __GLEW_AMD_performance_monitor;
+GLEW_VAR_EXPORT GLboolean __GLEW_AMD_pinned_memory;
+GLEW_VAR_EXPORT GLboolean __GLEW_AMD_query_buffer_object;
GLEW_VAR_EXPORT GLboolean __GLEW_AMD_sample_positions;
GLEW_VAR_EXPORT GLboolean __GLEW_AMD_seamless_cubemap_per_texture;
GLEW_VAR_EXPORT GLboolean __GLEW_AMD_shader_stencil_export;
+GLEW_VAR_EXPORT GLboolean __GLEW_AMD_shader_trinary_minmax;
+GLEW_VAR_EXPORT GLboolean __GLEW_AMD_sparse_texture;
+GLEW_VAR_EXPORT GLboolean __GLEW_AMD_stencil_operation_extended;
GLEW_VAR_EXPORT GLboolean __GLEW_AMD_texture_texture4;
GLEW_VAR_EXPORT GLboolean __GLEW_AMD_transform_feedback3_lines_triangles;
+GLEW_VAR_EXPORT GLboolean __GLEW_AMD_vertex_shader_layer;
GLEW_VAR_EXPORT GLboolean __GLEW_AMD_vertex_shader_tessellator;
+GLEW_VAR_EXPORT GLboolean __GLEW_AMD_vertex_shader_viewport_index;
+GLEW_VAR_EXPORT GLboolean __GLEW_ANGLE_depth_texture;
+GLEW_VAR_EXPORT GLboolean __GLEW_ANGLE_framebuffer_blit;
+GLEW_VAR_EXPORT GLboolean __GLEW_ANGLE_framebuffer_multisample;
+GLEW_VAR_EXPORT GLboolean __GLEW_ANGLE_instanced_arrays;
+GLEW_VAR_EXPORT GLboolean __GLEW_ANGLE_pack_reverse_row_order;
+GLEW_VAR_EXPORT GLboolean __GLEW_ANGLE_program_binary;
+GLEW_VAR_EXPORT GLboolean __GLEW_ANGLE_texture_compression_dxt1;
+GLEW_VAR_EXPORT GLboolean __GLEW_ANGLE_texture_compression_dxt3;
+GLEW_VAR_EXPORT GLboolean __GLEW_ANGLE_texture_compression_dxt5;
+GLEW_VAR_EXPORT GLboolean __GLEW_ANGLE_texture_usage;
+GLEW_VAR_EXPORT GLboolean __GLEW_ANGLE_timer_query;
+GLEW_VAR_EXPORT GLboolean __GLEW_ANGLE_translated_shader_source;
GLEW_VAR_EXPORT GLboolean __GLEW_APPLE_aux_depth_stencil;
GLEW_VAR_EXPORT GLboolean __GLEW_APPLE_client_storage;
GLEW_VAR_EXPORT GLboolean __GLEW_APPLE_element_array;
@@ -15662,14 +17538,23 @@ GLEW_VAR_EXPORT GLboolean __GLEW_APPLE_vertex_array_range;
GLEW_VAR_EXPORT GLboolean __GLEW_APPLE_vertex_program_evaluators;
GLEW_VAR_EXPORT GLboolean __GLEW_APPLE_ycbcr_422;
GLEW_VAR_EXPORT GLboolean __GLEW_ARB_ES2_compatibility;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_ES3_compatibility;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_arrays_of_arrays;
GLEW_VAR_EXPORT GLboolean __GLEW_ARB_base_instance;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_bindless_texture;
GLEW_VAR_EXPORT GLboolean __GLEW_ARB_blend_func_extended;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_buffer_storage;
GLEW_VAR_EXPORT GLboolean __GLEW_ARB_cl_event;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_clear_buffer_object;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_clear_texture;
GLEW_VAR_EXPORT GLboolean __GLEW_ARB_color_buffer_float;
GLEW_VAR_EXPORT GLboolean __GLEW_ARB_compatibility;
GLEW_VAR_EXPORT GLboolean __GLEW_ARB_compressed_texture_pixel_storage;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_compute_shader;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_compute_variable_group_size;
GLEW_VAR_EXPORT GLboolean __GLEW_ARB_conservative_depth;
GLEW_VAR_EXPORT GLboolean __GLEW_ARB_copy_buffer;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_copy_image;
GLEW_VAR_EXPORT GLboolean __GLEW_ARB_debug_output;
GLEW_VAR_EXPORT GLboolean __GLEW_ARB_depth_buffer_float;
GLEW_VAR_EXPORT GLboolean __GLEW_ARB_depth_clamp;
@@ -15679,11 +17564,15 @@ GLEW_VAR_EXPORT GLboolean __GLEW_ARB_draw_buffers_blend;
GLEW_VAR_EXPORT GLboolean __GLEW_ARB_draw_elements_base_vertex;
GLEW_VAR_EXPORT GLboolean __GLEW_ARB_draw_indirect;
GLEW_VAR_EXPORT GLboolean __GLEW_ARB_draw_instanced;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_enhanced_layouts;
GLEW_VAR_EXPORT GLboolean __GLEW_ARB_explicit_attrib_location;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_explicit_uniform_location;
GLEW_VAR_EXPORT GLboolean __GLEW_ARB_fragment_coord_conventions;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_fragment_layer_viewport;
GLEW_VAR_EXPORT GLboolean __GLEW_ARB_fragment_program;
GLEW_VAR_EXPORT GLboolean __GLEW_ARB_fragment_program_shadow;
GLEW_VAR_EXPORT GLboolean __GLEW_ARB_fragment_shader;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_framebuffer_no_attachments;
GLEW_VAR_EXPORT GLboolean __GLEW_ARB_framebuffer_object;
GLEW_VAR_EXPORT GLboolean __GLEW_ARB_framebuffer_sRGB;
GLEW_VAR_EXPORT GLboolean __GLEW_ARB_geometry_shader4;
@@ -15693,11 +17582,16 @@ GLEW_VAR_EXPORT GLboolean __GLEW_ARB_gpu_shader_fp64;
GLEW_VAR_EXPORT GLboolean __GLEW_ARB_half_float_pixel;
GLEW_VAR_EXPORT GLboolean __GLEW_ARB_half_float_vertex;
GLEW_VAR_EXPORT GLboolean __GLEW_ARB_imaging;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_indirect_parameters;
GLEW_VAR_EXPORT GLboolean __GLEW_ARB_instanced_arrays;
GLEW_VAR_EXPORT GLboolean __GLEW_ARB_internalformat_query;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_internalformat_query2;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_invalidate_subdata;
GLEW_VAR_EXPORT GLboolean __GLEW_ARB_map_buffer_alignment;
GLEW_VAR_EXPORT GLboolean __GLEW_ARB_map_buffer_range;
GLEW_VAR_EXPORT GLboolean __GLEW_ARB_matrix_palette;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_multi_bind;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_multi_draw_indirect;
GLEW_VAR_EXPORT GLboolean __GLEW_ARB_multisample;
GLEW_VAR_EXPORT GLboolean __GLEW_ARB_multitexture;
GLEW_VAR_EXPORT GLboolean __GLEW_ARB_occlusion_query;
@@ -15705,18 +17599,28 @@ GLEW_VAR_EXPORT GLboolean __GLEW_ARB_occlusion_query2;
GLEW_VAR_EXPORT GLboolean __GLEW_ARB_pixel_buffer_object;
GLEW_VAR_EXPORT GLboolean __GLEW_ARB_point_parameters;
GLEW_VAR_EXPORT GLboolean __GLEW_ARB_point_sprite;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_program_interface_query;
GLEW_VAR_EXPORT GLboolean __GLEW_ARB_provoking_vertex;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_query_buffer_object;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_robust_buffer_access_behavior;
GLEW_VAR_EXPORT GLboolean __GLEW_ARB_robustness;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_robustness_application_isolation;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_robustness_share_group_isolation;
GLEW_VAR_EXPORT GLboolean __GLEW_ARB_sample_shading;
GLEW_VAR_EXPORT GLboolean __GLEW_ARB_sampler_objects;
GLEW_VAR_EXPORT GLboolean __GLEW_ARB_seamless_cube_map;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_seamless_cubemap_per_texture;
GLEW_VAR_EXPORT GLboolean __GLEW_ARB_separate_shader_objects;
GLEW_VAR_EXPORT GLboolean __GLEW_ARB_shader_atomic_counters;
GLEW_VAR_EXPORT GLboolean __GLEW_ARB_shader_bit_encoding;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_shader_draw_parameters;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_shader_group_vote;
GLEW_VAR_EXPORT GLboolean __GLEW_ARB_shader_image_load_store;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_shader_image_size;
GLEW_VAR_EXPORT GLboolean __GLEW_ARB_shader_objects;
GLEW_VAR_EXPORT GLboolean __GLEW_ARB_shader_precision;
GLEW_VAR_EXPORT GLboolean __GLEW_ARB_shader_stencil_export;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_shader_storage_buffer_object;
GLEW_VAR_EXPORT GLboolean __GLEW_ARB_shader_subroutine;
GLEW_VAR_EXPORT GLboolean __GLEW_ARB_shader_texture_lod;
GLEW_VAR_EXPORT GLboolean __GLEW_ARB_shading_language_100;
@@ -15725,11 +17629,14 @@ GLEW_VAR_EXPORT GLboolean __GLEW_ARB_shading_language_include;
GLEW_VAR_EXPORT GLboolean __GLEW_ARB_shading_language_packing;
GLEW_VAR_EXPORT GLboolean __GLEW_ARB_shadow;
GLEW_VAR_EXPORT GLboolean __GLEW_ARB_shadow_ambient;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_sparse_texture;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_stencil_texturing;
GLEW_VAR_EXPORT GLboolean __GLEW_ARB_sync;
GLEW_VAR_EXPORT GLboolean __GLEW_ARB_tessellation_shader;
GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_border_clamp;
GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_buffer_object;
GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_buffer_object_rgb32;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_buffer_range;
GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_compression;
GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_compression_bptc;
GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_compression_rgtc;
@@ -15741,15 +17648,20 @@ GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_env_crossbar;
GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_env_dot3;
GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_float;
GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_gather;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_mirror_clamp_to_edge;
GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_mirrored_repeat;
GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_multisample;
GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_non_power_of_two;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_query_levels;
GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_query_lod;
GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_rectangle;
GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_rg;
GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_rgb10_a2ui;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_stencil8;
GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_storage;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_storage_multisample;
GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_swizzle;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_view;
GLEW_VAR_EXPORT GLboolean __GLEW_ARB_timer_query;
GLEW_VAR_EXPORT GLboolean __GLEW_ARB_transform_feedback2;
GLEW_VAR_EXPORT GLboolean __GLEW_ARB_transform_feedback3;
@@ -15759,10 +17671,12 @@ GLEW_VAR_EXPORT GLboolean __GLEW_ARB_uniform_buffer_object;
GLEW_VAR_EXPORT GLboolean __GLEW_ARB_vertex_array_bgra;
GLEW_VAR_EXPORT GLboolean __GLEW_ARB_vertex_array_object;
GLEW_VAR_EXPORT GLboolean __GLEW_ARB_vertex_attrib_64bit;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_vertex_attrib_binding;
GLEW_VAR_EXPORT GLboolean __GLEW_ARB_vertex_blend;
GLEW_VAR_EXPORT GLboolean __GLEW_ARB_vertex_buffer_object;
GLEW_VAR_EXPORT GLboolean __GLEW_ARB_vertex_program;
GLEW_VAR_EXPORT GLboolean __GLEW_ARB_vertex_shader;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_vertex_type_10f_11f_11f_rev;
GLEW_VAR_EXPORT GLboolean __GLEW_ARB_vertex_type_2_10_10_10_rev;
GLEW_VAR_EXPORT GLboolean __GLEW_ARB_viewport_array;
GLEW_VAR_EXPORT GLboolean __GLEW_ARB_window_pos;
@@ -15806,6 +17720,7 @@ GLEW_VAR_EXPORT GLboolean __GLEW_EXT_convolution;
GLEW_VAR_EXPORT GLboolean __GLEW_EXT_coordinate_frame;
GLEW_VAR_EXPORT GLboolean __GLEW_EXT_copy_texture;
GLEW_VAR_EXPORT GLboolean __GLEW_EXT_cull_vertex;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_debug_marker;
GLEW_VAR_EXPORT GLboolean __GLEW_EXT_depth_bounds_test;
GLEW_VAR_EXPORT GLboolean __GLEW_EXT_direct_state_access;
GLEW_VAR_EXPORT GLboolean __GLEW_EXT_draw_buffers2;
@@ -15900,22 +17815,33 @@ GLEW_VAR_EXPORT GLboolean __GLEW_IBM_texture_mirrored_repeat;
GLEW_VAR_EXPORT GLboolean __GLEW_IBM_vertex_array_lists;
GLEW_VAR_EXPORT GLboolean __GLEW_INGR_color_clamp;
GLEW_VAR_EXPORT GLboolean __GLEW_INGR_interlace_read;
+GLEW_VAR_EXPORT GLboolean __GLEW_INTEL_map_texture;
GLEW_VAR_EXPORT GLboolean __GLEW_INTEL_parallel_arrays;
GLEW_VAR_EXPORT GLboolean __GLEW_INTEL_texture_scissor;
+GLEW_VAR_EXPORT GLboolean __GLEW_KHR_debug;
+GLEW_VAR_EXPORT GLboolean __GLEW_KHR_texture_compression_astc_ldr;
GLEW_VAR_EXPORT GLboolean __GLEW_KTX_buffer_region;
GLEW_VAR_EXPORT GLboolean __GLEW_MESAX_texture_stack;
GLEW_VAR_EXPORT GLboolean __GLEW_MESA_pack_invert;
GLEW_VAR_EXPORT GLboolean __GLEW_MESA_resize_buffers;
GLEW_VAR_EXPORT GLboolean __GLEW_MESA_window_pos;
GLEW_VAR_EXPORT GLboolean __GLEW_MESA_ycbcr_texture;
+GLEW_VAR_EXPORT GLboolean __GLEW_NVX_conditional_render;
GLEW_VAR_EXPORT GLboolean __GLEW_NVX_gpu_memory_info;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_bindless_multi_draw_indirect;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_bindless_texture;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_blend_equation_advanced;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_blend_equation_advanced_coherent;
GLEW_VAR_EXPORT GLboolean __GLEW_NV_blend_square;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_compute_program5;
GLEW_VAR_EXPORT GLboolean __GLEW_NV_conditional_render;
GLEW_VAR_EXPORT GLboolean __GLEW_NV_copy_depth_to_color;
GLEW_VAR_EXPORT GLboolean __GLEW_NV_copy_image;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_deep_texture3D;
GLEW_VAR_EXPORT GLboolean __GLEW_NV_depth_buffer_float;
GLEW_VAR_EXPORT GLboolean __GLEW_NV_depth_clamp;
GLEW_VAR_EXPORT GLboolean __GLEW_NV_depth_range_unclamped;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_draw_texture;
GLEW_VAR_EXPORT GLboolean __GLEW_NV_evaluators;
GLEW_VAR_EXPORT GLboolean __GLEW_NV_explicit_multisample;
GLEW_VAR_EXPORT GLboolean __GLEW_NV_fence;
@@ -15930,6 +17856,7 @@ GLEW_VAR_EXPORT GLboolean __GLEW_NV_geometry_program4;
GLEW_VAR_EXPORT GLboolean __GLEW_NV_geometry_shader4;
GLEW_VAR_EXPORT GLboolean __GLEW_NV_gpu_program4;
GLEW_VAR_EXPORT GLboolean __GLEW_NV_gpu_program5;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_gpu_program5_mem_extended;
GLEW_VAR_EXPORT GLboolean __GLEW_NV_gpu_program_fp64;
GLEW_VAR_EXPORT GLboolean __GLEW_NV_gpu_shader5;
GLEW_VAR_EXPORT GLboolean __GLEW_NV_half_float;
@@ -15947,7 +17874,10 @@ GLEW_VAR_EXPORT GLboolean __GLEW_NV_present_video;
GLEW_VAR_EXPORT GLboolean __GLEW_NV_primitive_restart;
GLEW_VAR_EXPORT GLboolean __GLEW_NV_register_combiners;
GLEW_VAR_EXPORT GLboolean __GLEW_NV_register_combiners2;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_shader_atomic_counters;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_shader_atomic_float;
GLEW_VAR_EXPORT GLboolean __GLEW_NV_shader_buffer_load;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_shader_storage_buffer_object;
GLEW_VAR_EXPORT GLboolean __GLEW_NV_tessellation_program5;
GLEW_VAR_EXPORT GLboolean __GLEW_NV_texgen_emboss;
GLEW_VAR_EXPORT GLboolean __GLEW_NV_texgen_reflection;
@@ -15983,6 +17913,12 @@ GLEW_VAR_EXPORT GLboolean __GLEW_OML_resample;
GLEW_VAR_EXPORT GLboolean __GLEW_OML_subsample;
GLEW_VAR_EXPORT GLboolean __GLEW_PGI_misc_hints;
GLEW_VAR_EXPORT GLboolean __GLEW_PGI_vertex_hints;
+GLEW_VAR_EXPORT GLboolean __GLEW_REGAL_ES1_0_compatibility;
+GLEW_VAR_EXPORT GLboolean __GLEW_REGAL_ES1_1_compatibility;
+GLEW_VAR_EXPORT GLboolean __GLEW_REGAL_enable;
+GLEW_VAR_EXPORT GLboolean __GLEW_REGAL_error_string;
+GLEW_VAR_EXPORT GLboolean __GLEW_REGAL_extension_query;
+GLEW_VAR_EXPORT GLboolean __GLEW_REGAL_log;
GLEW_VAR_EXPORT GLboolean __GLEW_REND_screen_coordinates;
GLEW_VAR_EXPORT GLboolean __GLEW_S3_s3tc;
GLEW_VAR_EXPORT GLboolean __GLEW_SGIS_color_range;
@@ -16069,8 +18005,8 @@ GLEW_VAR_EXPORT GLboolean __GLEW_WIN_swap_hint;
#ifdef GLEW_MX
typedef struct GLEWContextStruct GLEWContext;
-GLEWAPI GLenum glewContextInit (GLEWContext* ctx);
-GLEWAPI GLboolean glewContextIsSupported (const GLEWContext* ctx, const char* name);
+GLEWAPI GLenum GLEWAPIENTRY glewContextInit (GLEWContext *ctx);
+GLEWAPI GLboolean GLEWAPIENTRY glewContextIsSupported (const GLEWContext *ctx, const char *name);
#define glewInit() glewContextInit(glewGetContext())
#define glewIsSupported(x) glewContextIsSupported(glewGetContext(), x)
@@ -16085,8 +18021,8 @@ GLEWAPI GLboolean glewContextIsSupported (const GLEWContext* ctx, const char* na
#else /* GLEW_MX */
-GLEWAPI GLenum glewInit (void);
-GLEWAPI GLboolean glewIsSupported (const char* name);
+GLEWAPI GLenum GLEWAPIENTRY glewInit (void);
+GLEWAPI GLboolean GLEWAPIENTRY glewIsSupported (const char *name);
#define glewIsExtensionSupported(x) glewIsSupported(x)
#define GLEW_GET_VAR(x) (*(const GLboolean*)&x)
@@ -16095,9 +18031,9 @@ GLEWAPI GLboolean glewIsSupported (const char* name);
#endif /* GLEW_MX */
GLEWAPI GLboolean glewExperimental;
-GLEWAPI GLboolean glewGetExtension (const char* name);
-GLEWAPI const GLubyte* glewGetErrorString (GLenum error);
-GLEWAPI const GLubyte* glewGetString (GLenum name);
+GLEWAPI GLboolean GLEWAPIENTRY glewGetExtension (const char *name);
+GLEWAPI const GLubyte * GLEWAPIENTRY glewGetErrorString (GLenum error);
+GLEWAPI const GLubyte * GLEWAPIENTRY glewGetString (GLenum name);
#ifdef __cplusplus
}
diff --git a/extern/glew/include/GL/glxew.h b/extern/glew/include/GL/glxew.h
index 6d249f73eaa..76a5f0d82ae 100644
--- a/extern/glew/include/GL/glxew.h
+++ b/extern/glew/include/GL/glxew.h
@@ -362,6 +362,26 @@ extern void ( * glXGetProcAddress (const GLubyte *procName)) (void);
#define GLX_GPU_NUM_RB_AMD 0x21A7
#define GLX_GPU_NUM_SPI_AMD 0x21A8
+typedef void ( * PFNGLXBLITCONTEXTFRAMEBUFFERAMDPROC) (GLXContext dstCtx, GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter);
+typedef GLXContext ( * PFNGLXCREATEASSOCIATEDCONTEXTAMDPROC) (unsigned int id, GLXContext share_list);
+typedef GLXContext ( * PFNGLXCREATEASSOCIATEDCONTEXTATTRIBSAMDPROC) (unsigned int id, GLXContext share_context, const int* attribList);
+typedef Bool ( * PFNGLXDELETEASSOCIATEDCONTEXTAMDPROC) (GLXContext ctx);
+typedef unsigned int ( * PFNGLXGETCONTEXTGPUIDAMDPROC) (GLXContext ctx);
+typedef GLXContext ( * PFNGLXGETCURRENTASSOCIATEDCONTEXTAMDPROC) (void);
+typedef unsigned int ( * PFNGLXGETGPUIDSAMDPROC) (unsigned int maxCount, unsigned int* ids);
+typedef int ( * PFNGLXGETGPUINFOAMDPROC) (unsigned int id, int property, GLenum dataType, unsigned int size, void* data);
+typedef Bool ( * PFNGLXMAKEASSOCIATEDCONTEXTCURRENTAMDPROC) (GLXContext ctx);
+
+#define glXBlitContextFramebufferAMD GLXEW_GET_FUN(__glewXBlitContextFramebufferAMD)
+#define glXCreateAssociatedContextAMD GLXEW_GET_FUN(__glewXCreateAssociatedContextAMD)
+#define glXCreateAssociatedContextAttribsAMD GLXEW_GET_FUN(__glewXCreateAssociatedContextAttribsAMD)
+#define glXDeleteAssociatedContextAMD GLXEW_GET_FUN(__glewXDeleteAssociatedContextAMD)
+#define glXGetContextGPUIDAMD GLXEW_GET_FUN(__glewXGetContextGPUIDAMD)
+#define glXGetCurrentAssociatedContextAMD GLXEW_GET_FUN(__glewXGetCurrentAssociatedContextAMD)
+#define glXGetGPUIDsAMD GLXEW_GET_FUN(__glewXGetGPUIDsAMD)
+#define glXGetGPUInfoAMD GLXEW_GET_FUN(__glewXGetGPUInfoAMD)
+#define glXMakeAssociatedContextCurrentAMD GLXEW_GET_FUN(__glewXMakeAssociatedContextCurrentAMD)
+
#define GLXEW_AMD_gpu_association GLXEW_GET_VAR(__GLXEW_AMD_gpu_association)
#endif /* GLX_AMD_gpu_association */
@@ -458,6 +478,28 @@ extern void ( * glXGetProcAddressARB (const GLubyte *procName)) (void);
#endif /* GLX_ARB_multisample */
+/* ---------------- GLX_ARB_robustness_application_isolation --------------- */
+
+#ifndef GLX_ARB_robustness_application_isolation
+#define GLX_ARB_robustness_application_isolation 1
+
+#define GLX_CONTEXT_RESET_ISOLATION_BIT_ARB 0x00000008
+
+#define GLXEW_ARB_robustness_application_isolation GLXEW_GET_VAR(__GLXEW_ARB_robustness_application_isolation)
+
+#endif /* GLX_ARB_robustness_application_isolation */
+
+/* ---------------- GLX_ARB_robustness_share_group_isolation --------------- */
+
+#ifndef GLX_ARB_robustness_share_group_isolation
+#define GLX_ARB_robustness_share_group_isolation 1
+
+#define GLX_CONTEXT_RESET_ISOLATION_BIT_ARB 0x00000008
+
+#define GLXEW_ARB_robustness_share_group_isolation GLXEW_GET_VAR(__GLXEW_ARB_robustness_share_group_isolation)
+
+#endif /* GLX_ARB_robustness_share_group_isolation */
+
/* ---------------------- GLX_ARB_vertex_buffer_object --------------------- */
#ifndef GLX_ARB_vertex_buffer_object
@@ -533,6 +575,17 @@ typedef void ( * PFNGLXRELEASETEXIMAGEATIPROC) (Display *dpy, GLXPbuffer pbuf, i
#endif /* GLX_ATI_render_texture */
+/* --------------------------- GLX_EXT_buffer_age -------------------------- */
+
+#ifndef GLX_EXT_buffer_age
+#define GLX_EXT_buffer_age 1
+
+#define GLX_BACK_BUFFER_AGE_EXT 0x20F4
+
+#define GLXEW_EXT_buffer_age GLXEW_GET_VAR(__GLXEW_EXT_buffer_age)
+
+#endif /* GLX_EXT_buffer_age */
+
/* ------------------- GLX_EXT_create_context_es2_profile ------------------ */
#ifndef GLX_EXT_create_context_es2_profile
@@ -544,6 +597,17 @@ typedef void ( * PFNGLXRELEASETEXIMAGEATIPROC) (Display *dpy, GLXPbuffer pbuf, i
#endif /* GLX_EXT_create_context_es2_profile */
+/* ------------------- GLX_EXT_create_context_es_profile ------------------- */
+
+#ifndef GLX_EXT_create_context_es_profile
+#define GLX_EXT_create_context_es_profile 1
+
+#define GLX_CONTEXT_ES_PROFILE_BIT_EXT 0x00000004
+
+#define GLXEW_EXT_create_context_es_profile GLXEW_GET_VAR(__GLXEW_EXT_create_context_es_profile)
+
+#endif /* GLX_EXT_create_context_es_profile */
+
/* --------------------- GLX_EXT_fbconfig_packed_float --------------------- */
#ifndef GLX_EXT_fbconfig_packed_float
@@ -617,6 +681,17 @@ typedef void ( * PFNGLXSWAPINTERVALEXTPROC) (Display* dpy, GLXDrawable drawable,
#endif /* GLX_EXT_swap_control */
+/* ----------------------- GLX_EXT_swap_control_tear ----------------------- */
+
+#ifndef GLX_EXT_swap_control_tear
+#define GLX_EXT_swap_control_tear 1
+
+#define GLX_LATE_SWAPS_TEAR_EXT 0x20F3
+
+#define GLXEW_EXT_swap_control_tear GLXEW_GET_VAR(__GLXEW_EXT_swap_control_tear)
+
+#endif /* GLX_EXT_swap_control_tear */
+
/* ---------------------- GLX_EXT_texture_from_pixmap ---------------------- */
#ifndef GLX_EXT_texture_from_pixmap
@@ -1003,16 +1078,6 @@ typedef Bool ( * PFNGLXWAITFORSBCOMLPROC) (Display* dpy, GLXDrawable drawable, i
#ifndef GLX_SGIS_color_range
#define GLX_SGIS_color_range 1
-#define GLX_MIN_RED_SGIS 0
-#define GLX_MAX_GREEN_SGIS 0
-#define GLX_MIN_BLUE_SGIS 0
-#define GLX_MAX_ALPHA_SGIS 0
-#define GLX_MIN_GREEN_SGIS 0
-#define GLX_MIN_ALPHA_SGIS 0
-#define GLX_MAX_RED_SGIS 0
-#define GLX_EXTENDED_RANGE_SGIS 0
-#define GLX_MAX_BLUE_SGIS 0
-
#define GLXEW_SGIS_color_range GLXEW_GET_VAR(__GLXEW_SGIS_color_range)
#endif /* GLX_SGIS_color_range */
@@ -1349,207 +1414,224 @@ typedef int ( * PFNGLXVIDEORESIZESUNPROC) (Display* display, GLXDrawable window,
/* ------------------------------------------------------------------------- */
#ifdef GLEW_MX
-#define GLXEW_EXPORT
+#define GLXEW_FUN_EXPORT GLEW_FUN_EXPORT
+#define GLXEW_VAR_EXPORT
#else
-#define GLXEW_EXPORT extern
+#define GLXEW_FUN_EXPORT GLEW_FUN_EXPORT
+#define GLXEW_VAR_EXPORT GLEW_VAR_EXPORT
#endif /* GLEW_MX */
-extern PFNGLXGETCURRENTDISPLAYPROC __glewXGetCurrentDisplay;
-
-extern PFNGLXCHOOSEFBCONFIGPROC __glewXChooseFBConfig;
-extern PFNGLXCREATENEWCONTEXTPROC __glewXCreateNewContext;
-extern PFNGLXCREATEPBUFFERPROC __glewXCreatePbuffer;
-extern PFNGLXCREATEPIXMAPPROC __glewXCreatePixmap;
-extern PFNGLXCREATEWINDOWPROC __glewXCreateWindow;
-extern PFNGLXDESTROYPBUFFERPROC __glewXDestroyPbuffer;
-extern PFNGLXDESTROYPIXMAPPROC __glewXDestroyPixmap;
-extern PFNGLXDESTROYWINDOWPROC __glewXDestroyWindow;
-extern PFNGLXGETCURRENTREADDRAWABLEPROC __glewXGetCurrentReadDrawable;
-extern PFNGLXGETFBCONFIGATTRIBPROC __glewXGetFBConfigAttrib;
-extern PFNGLXGETFBCONFIGSPROC __glewXGetFBConfigs;
-extern PFNGLXGETSELECTEDEVENTPROC __glewXGetSelectedEvent;
-extern PFNGLXGETVISUALFROMFBCONFIGPROC __glewXGetVisualFromFBConfig;
-extern PFNGLXMAKECONTEXTCURRENTPROC __glewXMakeContextCurrent;
-extern PFNGLXQUERYCONTEXTPROC __glewXQueryContext;
-extern PFNGLXQUERYDRAWABLEPROC __glewXQueryDrawable;
-extern PFNGLXSELECTEVENTPROC __glewXSelectEvent;
-
-extern PFNGLXCREATECONTEXTATTRIBSARBPROC __glewXCreateContextAttribsARB;
-
-extern PFNGLXBINDTEXIMAGEATIPROC __glewXBindTexImageATI;
-extern PFNGLXDRAWABLEATTRIBATIPROC __glewXDrawableAttribATI;
-extern PFNGLXRELEASETEXIMAGEATIPROC __glewXReleaseTexImageATI;
-
-extern PFNGLXFREECONTEXTEXTPROC __glewXFreeContextEXT;
-extern PFNGLXGETCONTEXTIDEXTPROC __glewXGetContextIDEXT;
-extern PFNGLXIMPORTCONTEXTEXTPROC __glewXImportContextEXT;
-extern PFNGLXQUERYCONTEXTINFOEXTPROC __glewXQueryContextInfoEXT;
-
-extern PFNGLXSWAPINTERVALEXTPROC __glewXSwapIntervalEXT;
-
-extern PFNGLXBINDTEXIMAGEEXTPROC __glewXBindTexImageEXT;
-extern PFNGLXRELEASETEXIMAGEEXTPROC __glewXReleaseTexImageEXT;
-
-extern PFNGLXGETAGPOFFSETMESAPROC __glewXGetAGPOffsetMESA;
-
-extern PFNGLXCOPYSUBBUFFERMESAPROC __glewXCopySubBufferMESA;
-
-extern PFNGLXCREATEGLXPIXMAPMESAPROC __glewXCreateGLXPixmapMESA;
-
-extern PFNGLXRELEASEBUFFERSMESAPROC __glewXReleaseBuffersMESA;
-
-extern PFNGLXSET3DFXMODEMESAPROC __glewXSet3DfxModeMESA;
-
-extern PFNGLXGETSWAPINTERVALMESAPROC __glewXGetSwapIntervalMESA;
-extern PFNGLXSWAPINTERVALMESAPROC __glewXSwapIntervalMESA;
-
-extern PFNGLXCOPYIMAGESUBDATANVPROC __glewXCopyImageSubDataNV;
-
-extern PFNGLXBINDVIDEODEVICENVPROC __glewXBindVideoDeviceNV;
-extern PFNGLXENUMERATEVIDEODEVICESNVPROC __glewXEnumerateVideoDevicesNV;
-
-extern PFNGLXBINDSWAPBARRIERNVPROC __glewXBindSwapBarrierNV;
-extern PFNGLXJOINSWAPGROUPNVPROC __glewXJoinSwapGroupNV;
-extern PFNGLXQUERYFRAMECOUNTNVPROC __glewXQueryFrameCountNV;
-extern PFNGLXQUERYMAXSWAPGROUPSNVPROC __glewXQueryMaxSwapGroupsNV;
-extern PFNGLXQUERYSWAPGROUPNVPROC __glewXQuerySwapGroupNV;
-extern PFNGLXRESETFRAMECOUNTNVPROC __glewXResetFrameCountNV;
-
-extern PFNGLXALLOCATEMEMORYNVPROC __glewXAllocateMemoryNV;
-extern PFNGLXFREEMEMORYNVPROC __glewXFreeMemoryNV;
-
-extern PFNGLXBINDVIDEOCAPTUREDEVICENVPROC __glewXBindVideoCaptureDeviceNV;
-extern PFNGLXENUMERATEVIDEOCAPTUREDEVICESNVPROC __glewXEnumerateVideoCaptureDevicesNV;
-extern PFNGLXLOCKVIDEOCAPTUREDEVICENVPROC __glewXLockVideoCaptureDeviceNV;
-extern PFNGLXQUERYVIDEOCAPTUREDEVICENVPROC __glewXQueryVideoCaptureDeviceNV;
-extern PFNGLXRELEASEVIDEOCAPTUREDEVICENVPROC __glewXReleaseVideoCaptureDeviceNV;
-
-extern PFNGLXBINDVIDEOIMAGENVPROC __glewXBindVideoImageNV;
-extern PFNGLXGETVIDEODEVICENVPROC __glewXGetVideoDeviceNV;
-extern PFNGLXGETVIDEOINFONVPROC __glewXGetVideoInfoNV;
-extern PFNGLXRELEASEVIDEODEVICENVPROC __glewXReleaseVideoDeviceNV;
-extern PFNGLXRELEASEVIDEOIMAGENVPROC __glewXReleaseVideoImageNV;
-extern PFNGLXSENDPBUFFERTOVIDEONVPROC __glewXSendPbufferToVideoNV;
-
-extern PFNGLXGETMSCRATEOMLPROC __glewXGetMscRateOML;
-extern PFNGLXGETSYNCVALUESOMLPROC __glewXGetSyncValuesOML;
-extern PFNGLXSWAPBUFFERSMSCOMLPROC __glewXSwapBuffersMscOML;
-extern PFNGLXWAITFORMSCOMLPROC __glewXWaitForMscOML;
-extern PFNGLXWAITFORSBCOMLPROC __glewXWaitForSbcOML;
-
-extern PFNGLXCHOOSEFBCONFIGSGIXPROC __glewXChooseFBConfigSGIX;
-extern PFNGLXCREATECONTEXTWITHCONFIGSGIXPROC __glewXCreateContextWithConfigSGIX;
-extern PFNGLXCREATEGLXPIXMAPWITHCONFIGSGIXPROC __glewXCreateGLXPixmapWithConfigSGIX;
-extern PFNGLXGETFBCONFIGATTRIBSGIXPROC __glewXGetFBConfigAttribSGIX;
-extern PFNGLXGETFBCONFIGFROMVISUALSGIXPROC __glewXGetFBConfigFromVisualSGIX;
-extern PFNGLXGETVISUALFROMFBCONFIGSGIXPROC __glewXGetVisualFromFBConfigSGIX;
-
-extern PFNGLXBINDHYPERPIPESGIXPROC __glewXBindHyperpipeSGIX;
-extern PFNGLXDESTROYHYPERPIPECONFIGSGIXPROC __glewXDestroyHyperpipeConfigSGIX;
-extern PFNGLXHYPERPIPEATTRIBSGIXPROC __glewXHyperpipeAttribSGIX;
-extern PFNGLXHYPERPIPECONFIGSGIXPROC __glewXHyperpipeConfigSGIX;
-extern PFNGLXQUERYHYPERPIPEATTRIBSGIXPROC __glewXQueryHyperpipeAttribSGIX;
-extern PFNGLXQUERYHYPERPIPEBESTATTRIBSGIXPROC __glewXQueryHyperpipeBestAttribSGIX;
-extern PFNGLXQUERYHYPERPIPECONFIGSGIXPROC __glewXQueryHyperpipeConfigSGIX;
-extern PFNGLXQUERYHYPERPIPENETWORKSGIXPROC __glewXQueryHyperpipeNetworkSGIX;
-
-extern PFNGLXCREATEGLXPBUFFERSGIXPROC __glewXCreateGLXPbufferSGIX;
-extern PFNGLXDESTROYGLXPBUFFERSGIXPROC __glewXDestroyGLXPbufferSGIX;
-extern PFNGLXGETSELECTEDEVENTSGIXPROC __glewXGetSelectedEventSGIX;
-extern PFNGLXQUERYGLXPBUFFERSGIXPROC __glewXQueryGLXPbufferSGIX;
-extern PFNGLXSELECTEVENTSGIXPROC __glewXSelectEventSGIX;
+GLXEW_FUN_EXPORT PFNGLXGETCURRENTDISPLAYPROC __glewXGetCurrentDisplay;
+
+GLXEW_FUN_EXPORT PFNGLXCHOOSEFBCONFIGPROC __glewXChooseFBConfig;
+GLXEW_FUN_EXPORT PFNGLXCREATENEWCONTEXTPROC __glewXCreateNewContext;
+GLXEW_FUN_EXPORT PFNGLXCREATEPBUFFERPROC __glewXCreatePbuffer;
+GLXEW_FUN_EXPORT PFNGLXCREATEPIXMAPPROC __glewXCreatePixmap;
+GLXEW_FUN_EXPORT PFNGLXCREATEWINDOWPROC __glewXCreateWindow;
+GLXEW_FUN_EXPORT PFNGLXDESTROYPBUFFERPROC __glewXDestroyPbuffer;
+GLXEW_FUN_EXPORT PFNGLXDESTROYPIXMAPPROC __glewXDestroyPixmap;
+GLXEW_FUN_EXPORT PFNGLXDESTROYWINDOWPROC __glewXDestroyWindow;
+GLXEW_FUN_EXPORT PFNGLXGETCURRENTREADDRAWABLEPROC __glewXGetCurrentReadDrawable;
+GLXEW_FUN_EXPORT PFNGLXGETFBCONFIGATTRIBPROC __glewXGetFBConfigAttrib;
+GLXEW_FUN_EXPORT PFNGLXGETFBCONFIGSPROC __glewXGetFBConfigs;
+GLXEW_FUN_EXPORT PFNGLXGETSELECTEDEVENTPROC __glewXGetSelectedEvent;
+GLXEW_FUN_EXPORT PFNGLXGETVISUALFROMFBCONFIGPROC __glewXGetVisualFromFBConfig;
+GLXEW_FUN_EXPORT PFNGLXMAKECONTEXTCURRENTPROC __glewXMakeContextCurrent;
+GLXEW_FUN_EXPORT PFNGLXQUERYCONTEXTPROC __glewXQueryContext;
+GLXEW_FUN_EXPORT PFNGLXQUERYDRAWABLEPROC __glewXQueryDrawable;
+GLXEW_FUN_EXPORT PFNGLXSELECTEVENTPROC __glewXSelectEvent;
+
+GLXEW_FUN_EXPORT PFNGLXBLITCONTEXTFRAMEBUFFERAMDPROC __glewXBlitContextFramebufferAMD;
+GLXEW_FUN_EXPORT PFNGLXCREATEASSOCIATEDCONTEXTAMDPROC __glewXCreateAssociatedContextAMD;
+GLXEW_FUN_EXPORT PFNGLXCREATEASSOCIATEDCONTEXTATTRIBSAMDPROC __glewXCreateAssociatedContextAttribsAMD;
+GLXEW_FUN_EXPORT PFNGLXDELETEASSOCIATEDCONTEXTAMDPROC __glewXDeleteAssociatedContextAMD;
+GLXEW_FUN_EXPORT PFNGLXGETCONTEXTGPUIDAMDPROC __glewXGetContextGPUIDAMD;
+GLXEW_FUN_EXPORT PFNGLXGETCURRENTASSOCIATEDCONTEXTAMDPROC __glewXGetCurrentAssociatedContextAMD;
+GLXEW_FUN_EXPORT PFNGLXGETGPUIDSAMDPROC __glewXGetGPUIDsAMD;
+GLXEW_FUN_EXPORT PFNGLXGETGPUINFOAMDPROC __glewXGetGPUInfoAMD;
+GLXEW_FUN_EXPORT PFNGLXMAKEASSOCIATEDCONTEXTCURRENTAMDPROC __glewXMakeAssociatedContextCurrentAMD;
+
+GLXEW_FUN_EXPORT PFNGLXCREATECONTEXTATTRIBSARBPROC __glewXCreateContextAttribsARB;
+
+GLXEW_FUN_EXPORT PFNGLXBINDTEXIMAGEATIPROC __glewXBindTexImageATI;
+GLXEW_FUN_EXPORT PFNGLXDRAWABLEATTRIBATIPROC __glewXDrawableAttribATI;
+GLXEW_FUN_EXPORT PFNGLXRELEASETEXIMAGEATIPROC __glewXReleaseTexImageATI;
+
+GLXEW_FUN_EXPORT PFNGLXFREECONTEXTEXTPROC __glewXFreeContextEXT;
+GLXEW_FUN_EXPORT PFNGLXGETCONTEXTIDEXTPROC __glewXGetContextIDEXT;
+GLXEW_FUN_EXPORT PFNGLXIMPORTCONTEXTEXTPROC __glewXImportContextEXT;
+GLXEW_FUN_EXPORT PFNGLXQUERYCONTEXTINFOEXTPROC __glewXQueryContextInfoEXT;
+
+GLXEW_FUN_EXPORT PFNGLXSWAPINTERVALEXTPROC __glewXSwapIntervalEXT;
+
+GLXEW_FUN_EXPORT PFNGLXBINDTEXIMAGEEXTPROC __glewXBindTexImageEXT;
+GLXEW_FUN_EXPORT PFNGLXRELEASETEXIMAGEEXTPROC __glewXReleaseTexImageEXT;
+
+GLXEW_FUN_EXPORT PFNGLXGETAGPOFFSETMESAPROC __glewXGetAGPOffsetMESA;
+
+GLXEW_FUN_EXPORT PFNGLXCOPYSUBBUFFERMESAPROC __glewXCopySubBufferMESA;
+
+GLXEW_FUN_EXPORT PFNGLXCREATEGLXPIXMAPMESAPROC __glewXCreateGLXPixmapMESA;
+
+GLXEW_FUN_EXPORT PFNGLXRELEASEBUFFERSMESAPROC __glewXReleaseBuffersMESA;
+
+GLXEW_FUN_EXPORT PFNGLXSET3DFXMODEMESAPROC __glewXSet3DfxModeMESA;
+
+GLXEW_FUN_EXPORT PFNGLXGETSWAPINTERVALMESAPROC __glewXGetSwapIntervalMESA;
+GLXEW_FUN_EXPORT PFNGLXSWAPINTERVALMESAPROC __glewXSwapIntervalMESA;
+
+GLXEW_FUN_EXPORT PFNGLXCOPYIMAGESUBDATANVPROC __glewXCopyImageSubDataNV;
+
+GLXEW_FUN_EXPORT PFNGLXBINDVIDEODEVICENVPROC __glewXBindVideoDeviceNV;
+GLXEW_FUN_EXPORT PFNGLXENUMERATEVIDEODEVICESNVPROC __glewXEnumerateVideoDevicesNV;
+
+GLXEW_FUN_EXPORT PFNGLXBINDSWAPBARRIERNVPROC __glewXBindSwapBarrierNV;
+GLXEW_FUN_EXPORT PFNGLXJOINSWAPGROUPNVPROC __glewXJoinSwapGroupNV;
+GLXEW_FUN_EXPORT PFNGLXQUERYFRAMECOUNTNVPROC __glewXQueryFrameCountNV;
+GLXEW_FUN_EXPORT PFNGLXQUERYMAXSWAPGROUPSNVPROC __glewXQueryMaxSwapGroupsNV;
+GLXEW_FUN_EXPORT PFNGLXQUERYSWAPGROUPNVPROC __glewXQuerySwapGroupNV;
+GLXEW_FUN_EXPORT PFNGLXRESETFRAMECOUNTNVPROC __glewXResetFrameCountNV;
+
+GLXEW_FUN_EXPORT PFNGLXALLOCATEMEMORYNVPROC __glewXAllocateMemoryNV;
+GLXEW_FUN_EXPORT PFNGLXFREEMEMORYNVPROC __glewXFreeMemoryNV;
+
+GLXEW_FUN_EXPORT PFNGLXBINDVIDEOCAPTUREDEVICENVPROC __glewXBindVideoCaptureDeviceNV;
+GLXEW_FUN_EXPORT PFNGLXENUMERATEVIDEOCAPTUREDEVICESNVPROC __glewXEnumerateVideoCaptureDevicesNV;
+GLXEW_FUN_EXPORT PFNGLXLOCKVIDEOCAPTUREDEVICENVPROC __glewXLockVideoCaptureDeviceNV;
+GLXEW_FUN_EXPORT PFNGLXQUERYVIDEOCAPTUREDEVICENVPROC __glewXQueryVideoCaptureDeviceNV;
+GLXEW_FUN_EXPORT PFNGLXRELEASEVIDEOCAPTUREDEVICENVPROC __glewXReleaseVideoCaptureDeviceNV;
+
+GLXEW_FUN_EXPORT PFNGLXBINDVIDEOIMAGENVPROC __glewXBindVideoImageNV;
+GLXEW_FUN_EXPORT PFNGLXGETVIDEODEVICENVPROC __glewXGetVideoDeviceNV;
+GLXEW_FUN_EXPORT PFNGLXGETVIDEOINFONVPROC __glewXGetVideoInfoNV;
+GLXEW_FUN_EXPORT PFNGLXRELEASEVIDEODEVICENVPROC __glewXReleaseVideoDeviceNV;
+GLXEW_FUN_EXPORT PFNGLXRELEASEVIDEOIMAGENVPROC __glewXReleaseVideoImageNV;
+GLXEW_FUN_EXPORT PFNGLXSENDPBUFFERTOVIDEONVPROC __glewXSendPbufferToVideoNV;
+
+GLXEW_FUN_EXPORT PFNGLXGETMSCRATEOMLPROC __glewXGetMscRateOML;
+GLXEW_FUN_EXPORT PFNGLXGETSYNCVALUESOMLPROC __glewXGetSyncValuesOML;
+GLXEW_FUN_EXPORT PFNGLXSWAPBUFFERSMSCOMLPROC __glewXSwapBuffersMscOML;
+GLXEW_FUN_EXPORT PFNGLXWAITFORMSCOMLPROC __glewXWaitForMscOML;
+GLXEW_FUN_EXPORT PFNGLXWAITFORSBCOMLPROC __glewXWaitForSbcOML;
+
+GLXEW_FUN_EXPORT PFNGLXCHOOSEFBCONFIGSGIXPROC __glewXChooseFBConfigSGIX;
+GLXEW_FUN_EXPORT PFNGLXCREATECONTEXTWITHCONFIGSGIXPROC __glewXCreateContextWithConfigSGIX;
+GLXEW_FUN_EXPORT PFNGLXCREATEGLXPIXMAPWITHCONFIGSGIXPROC __glewXCreateGLXPixmapWithConfigSGIX;
+GLXEW_FUN_EXPORT PFNGLXGETFBCONFIGATTRIBSGIXPROC __glewXGetFBConfigAttribSGIX;
+GLXEW_FUN_EXPORT PFNGLXGETFBCONFIGFROMVISUALSGIXPROC __glewXGetFBConfigFromVisualSGIX;
+GLXEW_FUN_EXPORT PFNGLXGETVISUALFROMFBCONFIGSGIXPROC __glewXGetVisualFromFBConfigSGIX;
+
+GLXEW_FUN_EXPORT PFNGLXBINDHYPERPIPESGIXPROC __glewXBindHyperpipeSGIX;
+GLXEW_FUN_EXPORT PFNGLXDESTROYHYPERPIPECONFIGSGIXPROC __glewXDestroyHyperpipeConfigSGIX;
+GLXEW_FUN_EXPORT PFNGLXHYPERPIPEATTRIBSGIXPROC __glewXHyperpipeAttribSGIX;
+GLXEW_FUN_EXPORT PFNGLXHYPERPIPECONFIGSGIXPROC __glewXHyperpipeConfigSGIX;
+GLXEW_FUN_EXPORT PFNGLXQUERYHYPERPIPEATTRIBSGIXPROC __glewXQueryHyperpipeAttribSGIX;
+GLXEW_FUN_EXPORT PFNGLXQUERYHYPERPIPEBESTATTRIBSGIXPROC __glewXQueryHyperpipeBestAttribSGIX;
+GLXEW_FUN_EXPORT PFNGLXQUERYHYPERPIPECONFIGSGIXPROC __glewXQueryHyperpipeConfigSGIX;
+GLXEW_FUN_EXPORT PFNGLXQUERYHYPERPIPENETWORKSGIXPROC __glewXQueryHyperpipeNetworkSGIX;
+
+GLXEW_FUN_EXPORT PFNGLXCREATEGLXPBUFFERSGIXPROC __glewXCreateGLXPbufferSGIX;
+GLXEW_FUN_EXPORT PFNGLXDESTROYGLXPBUFFERSGIXPROC __glewXDestroyGLXPbufferSGIX;
+GLXEW_FUN_EXPORT PFNGLXGETSELECTEDEVENTSGIXPROC __glewXGetSelectedEventSGIX;
+GLXEW_FUN_EXPORT PFNGLXQUERYGLXPBUFFERSGIXPROC __glewXQueryGLXPbufferSGIX;
+GLXEW_FUN_EXPORT PFNGLXSELECTEVENTSGIXPROC __glewXSelectEventSGIX;
-extern PFNGLXBINDSWAPBARRIERSGIXPROC __glewXBindSwapBarrierSGIX;
-extern PFNGLXQUERYMAXSWAPBARRIERSSGIXPROC __glewXQueryMaxSwapBarriersSGIX;
+GLXEW_FUN_EXPORT PFNGLXBINDSWAPBARRIERSGIXPROC __glewXBindSwapBarrierSGIX;
+GLXEW_FUN_EXPORT PFNGLXQUERYMAXSWAPBARRIERSSGIXPROC __glewXQueryMaxSwapBarriersSGIX;
-extern PFNGLXJOINSWAPGROUPSGIXPROC __glewXJoinSwapGroupSGIX;
+GLXEW_FUN_EXPORT PFNGLXJOINSWAPGROUPSGIXPROC __glewXJoinSwapGroupSGIX;
-extern PFNGLXBINDCHANNELTOWINDOWSGIXPROC __glewXBindChannelToWindowSGIX;
-extern PFNGLXCHANNELRECTSGIXPROC __glewXChannelRectSGIX;
-extern PFNGLXCHANNELRECTSYNCSGIXPROC __glewXChannelRectSyncSGIX;
-extern PFNGLXQUERYCHANNELDELTASSGIXPROC __glewXQueryChannelDeltasSGIX;
-extern PFNGLXQUERYCHANNELRECTSGIXPROC __glewXQueryChannelRectSGIX;
+GLXEW_FUN_EXPORT PFNGLXBINDCHANNELTOWINDOWSGIXPROC __glewXBindChannelToWindowSGIX;
+GLXEW_FUN_EXPORT PFNGLXCHANNELRECTSGIXPROC __glewXChannelRectSGIX;
+GLXEW_FUN_EXPORT PFNGLXCHANNELRECTSYNCSGIXPROC __glewXChannelRectSyncSGIX;
+GLXEW_FUN_EXPORT PFNGLXQUERYCHANNELDELTASSGIXPROC __glewXQueryChannelDeltasSGIX;
+GLXEW_FUN_EXPORT PFNGLXQUERYCHANNELRECTSGIXPROC __glewXQueryChannelRectSGIX;
-extern PFNGLXCUSHIONSGIPROC __glewXCushionSGI;
+GLXEW_FUN_EXPORT PFNGLXCUSHIONSGIPROC __glewXCushionSGI;
-extern PFNGLXGETCURRENTREADDRAWABLESGIPROC __glewXGetCurrentReadDrawableSGI;
-extern PFNGLXMAKECURRENTREADSGIPROC __glewXMakeCurrentReadSGI;
+GLXEW_FUN_EXPORT PFNGLXGETCURRENTREADDRAWABLESGIPROC __glewXGetCurrentReadDrawableSGI;
+GLXEW_FUN_EXPORT PFNGLXMAKECURRENTREADSGIPROC __glewXMakeCurrentReadSGI;
-extern PFNGLXSWAPINTERVALSGIPROC __glewXSwapIntervalSGI;
+GLXEW_FUN_EXPORT PFNGLXSWAPINTERVALSGIPROC __glewXSwapIntervalSGI;
-extern PFNGLXGETVIDEOSYNCSGIPROC __glewXGetVideoSyncSGI;
-extern PFNGLXWAITVIDEOSYNCSGIPROC __glewXWaitVideoSyncSGI;
+GLXEW_FUN_EXPORT PFNGLXGETVIDEOSYNCSGIPROC __glewXGetVideoSyncSGI;
+GLXEW_FUN_EXPORT PFNGLXWAITVIDEOSYNCSGIPROC __glewXWaitVideoSyncSGI;
-extern PFNGLXGETTRANSPARENTINDEXSUNPROC __glewXGetTransparentIndexSUN;
+GLXEW_FUN_EXPORT PFNGLXGETTRANSPARENTINDEXSUNPROC __glewXGetTransparentIndexSUN;
-extern PFNGLXGETVIDEORESIZESUNPROC __glewXGetVideoResizeSUN;
-extern PFNGLXVIDEORESIZESUNPROC __glewXVideoResizeSUN;
+GLXEW_FUN_EXPORT PFNGLXGETVIDEORESIZESUNPROC __glewXGetVideoResizeSUN;
+GLXEW_FUN_EXPORT PFNGLXVIDEORESIZESUNPROC __glewXVideoResizeSUN;
#if defined(GLEW_MX)
struct GLXEWContextStruct
{
#endif /* GLEW_MX */
-GLXEW_EXPORT GLboolean __GLXEW_VERSION_1_0;
-GLXEW_EXPORT GLboolean __GLXEW_VERSION_1_1;
-GLXEW_EXPORT GLboolean __GLXEW_VERSION_1_2;
-GLXEW_EXPORT GLboolean __GLXEW_VERSION_1_3;
-GLXEW_EXPORT GLboolean __GLXEW_VERSION_1_4;
-GLXEW_EXPORT GLboolean __GLXEW_3DFX_multisample;
-GLXEW_EXPORT GLboolean __GLXEW_AMD_gpu_association;
-GLXEW_EXPORT GLboolean __GLXEW_ARB_create_context;
-GLXEW_EXPORT GLboolean __GLXEW_ARB_create_context_profile;
-GLXEW_EXPORT GLboolean __GLXEW_ARB_create_context_robustness;
-GLXEW_EXPORT GLboolean __GLXEW_ARB_fbconfig_float;
-GLXEW_EXPORT GLboolean __GLXEW_ARB_framebuffer_sRGB;
-GLXEW_EXPORT GLboolean __GLXEW_ARB_get_proc_address;
-GLXEW_EXPORT GLboolean __GLXEW_ARB_multisample;
-GLXEW_EXPORT GLboolean __GLXEW_ARB_vertex_buffer_object;
-GLXEW_EXPORT GLboolean __GLXEW_ATI_pixel_format_float;
-GLXEW_EXPORT GLboolean __GLXEW_ATI_render_texture;
-GLXEW_EXPORT GLboolean __GLXEW_EXT_create_context_es2_profile;
-GLXEW_EXPORT GLboolean __GLXEW_EXT_fbconfig_packed_float;
-GLXEW_EXPORT GLboolean __GLXEW_EXT_framebuffer_sRGB;
-GLXEW_EXPORT GLboolean __GLXEW_EXT_import_context;
-GLXEW_EXPORT GLboolean __GLXEW_EXT_scene_marker;
-GLXEW_EXPORT GLboolean __GLXEW_EXT_swap_control;
-GLXEW_EXPORT GLboolean __GLXEW_EXT_texture_from_pixmap;
-GLXEW_EXPORT GLboolean __GLXEW_EXT_visual_info;
-GLXEW_EXPORT GLboolean __GLXEW_EXT_visual_rating;
-GLXEW_EXPORT GLboolean __GLXEW_INTEL_swap_event;
-GLXEW_EXPORT GLboolean __GLXEW_MESA_agp_offset;
-GLXEW_EXPORT GLboolean __GLXEW_MESA_copy_sub_buffer;
-GLXEW_EXPORT GLboolean __GLXEW_MESA_pixmap_colormap;
-GLXEW_EXPORT GLboolean __GLXEW_MESA_release_buffers;
-GLXEW_EXPORT GLboolean __GLXEW_MESA_set_3dfx_mode;
-GLXEW_EXPORT GLboolean __GLXEW_MESA_swap_control;
-GLXEW_EXPORT GLboolean __GLXEW_NV_copy_image;
-GLXEW_EXPORT GLboolean __GLXEW_NV_float_buffer;
-GLXEW_EXPORT GLboolean __GLXEW_NV_multisample_coverage;
-GLXEW_EXPORT GLboolean __GLXEW_NV_present_video;
-GLXEW_EXPORT GLboolean __GLXEW_NV_swap_group;
-GLXEW_EXPORT GLboolean __GLXEW_NV_vertex_array_range;
-GLXEW_EXPORT GLboolean __GLXEW_NV_video_capture;
-GLXEW_EXPORT GLboolean __GLXEW_NV_video_output;
-GLXEW_EXPORT GLboolean __GLXEW_OML_swap_method;
-GLXEW_EXPORT GLboolean __GLXEW_OML_sync_control;
-GLXEW_EXPORT GLboolean __GLXEW_SGIS_blended_overlay;
-GLXEW_EXPORT GLboolean __GLXEW_SGIS_color_range;
-GLXEW_EXPORT GLboolean __GLXEW_SGIS_multisample;
-GLXEW_EXPORT GLboolean __GLXEW_SGIS_shared_multisample;
-GLXEW_EXPORT GLboolean __GLXEW_SGIX_fbconfig;
-GLXEW_EXPORT GLboolean __GLXEW_SGIX_hyperpipe;
-GLXEW_EXPORT GLboolean __GLXEW_SGIX_pbuffer;
-GLXEW_EXPORT GLboolean __GLXEW_SGIX_swap_barrier;
-GLXEW_EXPORT GLboolean __GLXEW_SGIX_swap_group;
-GLXEW_EXPORT GLboolean __GLXEW_SGIX_video_resize;
-GLXEW_EXPORT GLboolean __GLXEW_SGIX_visual_select_group;
-GLXEW_EXPORT GLboolean __GLXEW_SGI_cushion;
-GLXEW_EXPORT GLboolean __GLXEW_SGI_make_current_read;
-GLXEW_EXPORT GLboolean __GLXEW_SGI_swap_control;
-GLXEW_EXPORT GLboolean __GLXEW_SGI_video_sync;
-GLXEW_EXPORT GLboolean __GLXEW_SUN_get_transparent_index;
-GLXEW_EXPORT GLboolean __GLXEW_SUN_video_resize;
+GLXEW_VAR_EXPORT GLboolean __GLXEW_VERSION_1_0;
+GLXEW_VAR_EXPORT GLboolean __GLXEW_VERSION_1_1;
+GLXEW_VAR_EXPORT GLboolean __GLXEW_VERSION_1_2;
+GLXEW_VAR_EXPORT GLboolean __GLXEW_VERSION_1_3;
+GLXEW_VAR_EXPORT GLboolean __GLXEW_VERSION_1_4;
+GLXEW_VAR_EXPORT GLboolean __GLXEW_3DFX_multisample;
+GLXEW_VAR_EXPORT GLboolean __GLXEW_AMD_gpu_association;
+GLXEW_VAR_EXPORT GLboolean __GLXEW_ARB_create_context;
+GLXEW_VAR_EXPORT GLboolean __GLXEW_ARB_create_context_profile;
+GLXEW_VAR_EXPORT GLboolean __GLXEW_ARB_create_context_robustness;
+GLXEW_VAR_EXPORT GLboolean __GLXEW_ARB_fbconfig_float;
+GLXEW_VAR_EXPORT GLboolean __GLXEW_ARB_framebuffer_sRGB;
+GLXEW_VAR_EXPORT GLboolean __GLXEW_ARB_get_proc_address;
+GLXEW_VAR_EXPORT GLboolean __GLXEW_ARB_multisample;
+GLXEW_VAR_EXPORT GLboolean __GLXEW_ARB_robustness_application_isolation;
+GLXEW_VAR_EXPORT GLboolean __GLXEW_ARB_robustness_share_group_isolation;
+GLXEW_VAR_EXPORT GLboolean __GLXEW_ARB_vertex_buffer_object;
+GLXEW_VAR_EXPORT GLboolean __GLXEW_ATI_pixel_format_float;
+GLXEW_VAR_EXPORT GLboolean __GLXEW_ATI_render_texture;
+GLXEW_VAR_EXPORT GLboolean __GLXEW_EXT_buffer_age;
+GLXEW_VAR_EXPORT GLboolean __GLXEW_EXT_create_context_es2_profile;
+GLXEW_VAR_EXPORT GLboolean __GLXEW_EXT_create_context_es_profile;
+GLXEW_VAR_EXPORT GLboolean __GLXEW_EXT_fbconfig_packed_float;
+GLXEW_VAR_EXPORT GLboolean __GLXEW_EXT_framebuffer_sRGB;
+GLXEW_VAR_EXPORT GLboolean __GLXEW_EXT_import_context;
+GLXEW_VAR_EXPORT GLboolean __GLXEW_EXT_scene_marker;
+GLXEW_VAR_EXPORT GLboolean __GLXEW_EXT_swap_control;
+GLXEW_VAR_EXPORT GLboolean __GLXEW_EXT_swap_control_tear;
+GLXEW_VAR_EXPORT GLboolean __GLXEW_EXT_texture_from_pixmap;
+GLXEW_VAR_EXPORT GLboolean __GLXEW_EXT_visual_info;
+GLXEW_VAR_EXPORT GLboolean __GLXEW_EXT_visual_rating;
+GLXEW_VAR_EXPORT GLboolean __GLXEW_INTEL_swap_event;
+GLXEW_VAR_EXPORT GLboolean __GLXEW_MESA_agp_offset;
+GLXEW_VAR_EXPORT GLboolean __GLXEW_MESA_copy_sub_buffer;
+GLXEW_VAR_EXPORT GLboolean __GLXEW_MESA_pixmap_colormap;
+GLXEW_VAR_EXPORT GLboolean __GLXEW_MESA_release_buffers;
+GLXEW_VAR_EXPORT GLboolean __GLXEW_MESA_set_3dfx_mode;
+GLXEW_VAR_EXPORT GLboolean __GLXEW_MESA_swap_control;
+GLXEW_VAR_EXPORT GLboolean __GLXEW_NV_copy_image;
+GLXEW_VAR_EXPORT GLboolean __GLXEW_NV_float_buffer;
+GLXEW_VAR_EXPORT GLboolean __GLXEW_NV_multisample_coverage;
+GLXEW_VAR_EXPORT GLboolean __GLXEW_NV_present_video;
+GLXEW_VAR_EXPORT GLboolean __GLXEW_NV_swap_group;
+GLXEW_VAR_EXPORT GLboolean __GLXEW_NV_vertex_array_range;
+GLXEW_VAR_EXPORT GLboolean __GLXEW_NV_video_capture;
+GLXEW_VAR_EXPORT GLboolean __GLXEW_NV_video_output;
+GLXEW_VAR_EXPORT GLboolean __GLXEW_OML_swap_method;
+GLXEW_VAR_EXPORT GLboolean __GLXEW_OML_sync_control;
+GLXEW_VAR_EXPORT GLboolean __GLXEW_SGIS_blended_overlay;
+GLXEW_VAR_EXPORT GLboolean __GLXEW_SGIS_color_range;
+GLXEW_VAR_EXPORT GLboolean __GLXEW_SGIS_multisample;
+GLXEW_VAR_EXPORT GLboolean __GLXEW_SGIS_shared_multisample;
+GLXEW_VAR_EXPORT GLboolean __GLXEW_SGIX_fbconfig;
+GLXEW_VAR_EXPORT GLboolean __GLXEW_SGIX_hyperpipe;
+GLXEW_VAR_EXPORT GLboolean __GLXEW_SGIX_pbuffer;
+GLXEW_VAR_EXPORT GLboolean __GLXEW_SGIX_swap_barrier;
+GLXEW_VAR_EXPORT GLboolean __GLXEW_SGIX_swap_group;
+GLXEW_VAR_EXPORT GLboolean __GLXEW_SGIX_video_resize;
+GLXEW_VAR_EXPORT GLboolean __GLXEW_SGIX_visual_select_group;
+GLXEW_VAR_EXPORT GLboolean __GLXEW_SGI_cushion;
+GLXEW_VAR_EXPORT GLboolean __GLXEW_SGI_make_current_read;
+GLXEW_VAR_EXPORT GLboolean __GLXEW_SGI_swap_control;
+GLXEW_VAR_EXPORT GLboolean __GLXEW_SGI_video_sync;
+GLXEW_VAR_EXPORT GLboolean __GLXEW_SUN_get_transparent_index;
+GLXEW_VAR_EXPORT GLboolean __GLXEW_SUN_video_resize;
#ifdef GLEW_MX
}; /* GLXEWContextStruct */
@@ -1560,8 +1642,8 @@ GLXEW_EXPORT GLboolean __GLXEW_SUN_video_resize;
#ifdef GLEW_MX
typedef struct GLXEWContextStruct GLXEWContext;
-extern GLenum glxewContextInit (GLXEWContext* ctx);
-extern GLboolean glxewContextIsSupported (const GLXEWContext* ctx, const char* name);
+GLEWAPI GLenum GLEWAPIENTRY glxewContextInit (GLXEWContext *ctx);
+GLEWAPI GLboolean GLEWAPIENTRY glxewContextIsSupported (const GLXEWContext *ctx, const char *name);
#define glxewInit() glxewContextInit(glxewGetContext())
#define glxewIsSupported(x) glxewContextIsSupported(glxewGetContext(), x)
@@ -1574,11 +1656,11 @@ extern GLboolean glxewContextIsSupported (const GLXEWContext* ctx, const char* n
#define GLXEW_GET_VAR(x) (*(const GLboolean*)&x)
#define GLXEW_GET_FUN(x) x
-extern GLboolean glxewIsSupported (const char* name);
+GLEWAPI GLboolean GLEWAPIENTRY glxewIsSupported (const char *name);
#endif /* GLEW_MX */
-extern GLboolean glxewGetExtension (const char* name);
+GLEWAPI GLboolean GLEWAPIENTRY glxewGetExtension (const char *name);
#ifdef __cplusplus
}
diff --git a/extern/glew/include/GL/wglew.h b/extern/glew/include/GL/wglew.h
index 05f054fc855..8659841d359 100644
--- a/extern/glew/include/GL/wglew.h
+++ b/extern/glew/include/GL/wglew.h
@@ -446,6 +446,28 @@ typedef BOOL (WINAPI * PFNWGLSETPBUFFERATTRIBARBPROC) (HPBUFFERARB hPbuffer, con
#endif /* WGL_ARB_render_texture */
+/* ---------------- WGL_ARB_robustness_application_isolation --------------- */
+
+#ifndef WGL_ARB_robustness_application_isolation
+#define WGL_ARB_robustness_application_isolation 1
+
+#define WGL_CONTEXT_RESET_ISOLATION_BIT_ARB 0x00000008
+
+#define WGLEW_ARB_robustness_application_isolation WGLEW_GET_VAR(__WGLEW_ARB_robustness_application_isolation)
+
+#endif /* WGL_ARB_robustness_application_isolation */
+
+/* ---------------- WGL_ARB_robustness_share_group_isolation --------------- */
+
+#ifndef WGL_ARB_robustness_share_group_isolation
+#define WGL_ARB_robustness_share_group_isolation 1
+
+#define WGL_CONTEXT_RESET_ISOLATION_BIT_ARB 0x00000008
+
+#define WGLEW_ARB_robustness_share_group_isolation WGLEW_GET_VAR(__WGLEW_ARB_robustness_share_group_isolation)
+
+#endif /* WGL_ARB_robustness_share_group_isolation */
+
/* ----------------------- WGL_ATI_pixel_format_float ---------------------- */
#ifndef WGL_ATI_pixel_format_float
@@ -481,6 +503,17 @@ typedef BOOL (WINAPI * PFNWGLSETPBUFFERATTRIBARBPROC) (HPBUFFERARB hPbuffer, con
#endif /* WGL_EXT_create_context_es2_profile */
+/* ------------------- WGL_EXT_create_context_es_profile ------------------- */
+
+#ifndef WGL_EXT_create_context_es_profile
+#define WGL_EXT_create_context_es_profile 1
+
+#define WGL_CONTEXT_ES_PROFILE_BIT_EXT 0x00000004
+
+#define WGLEW_EXT_create_context_es_profile WGLEW_GET_VAR(__WGLEW_EXT_create_context_es_profile)
+
+#endif /* WGL_EXT_create_context_es_profile */
+
/* -------------------------- WGL_EXT_depth_float -------------------------- */
#ifndef WGL_EXT_depth_float
@@ -686,6 +719,15 @@ typedef BOOL (WINAPI * PFNWGLSWAPINTERVALEXTPROC) (int interval);
#endif /* WGL_EXT_swap_control */
+/* ----------------------- WGL_EXT_swap_control_tear ----------------------- */
+
+#ifndef WGL_EXT_swap_control_tear
+#define WGL_EXT_swap_control_tear 1
+
+#define WGLEW_EXT_swap_control_tear WGLEW_GET_VAR(__WGLEW_EXT_swap_control_tear)
+
+#endif /* WGL_EXT_swap_control_tear */
+
/* --------------------- WGL_I3D_digital_video_control --------------------- */
#ifndef WGL_I3D_digital_video_control
@@ -864,6 +906,15 @@ typedef BOOL (WINAPI * PFNWGLDXUNREGISTEROBJECTNVPROC) (HANDLE hDevice, HANDLE h
#endif /* WGL_NV_DX_interop */
+/* --------------------------- WGL_NV_DX_interop2 -------------------------- */
+
+#ifndef WGL_NV_DX_interop2
+#define WGL_NV_DX_interop2 1
+
+#define WGLEW_NV_DX_interop2 WGLEW_GET_VAR(__WGLEW_NV_DX_interop2)
+
+#endif /* WGL_NV_DX_interop2 */
+
/* --------------------------- WGL_NV_copy_image --------------------------- */
#ifndef WGL_NV_copy_image
@@ -1120,9 +1171,11 @@ typedef BOOL (WINAPI * PFNWGLWAITFORSBCOMLPROC) (HDC hdc, INT64 target_sbc, INT6
/* ------------------------------------------------------------------------- */
#ifdef GLEW_MX
-#define WGLEW_EXPORT
+#define WGLEW_FUN_EXPORT
+#define WGLEW_VAR_EXPORT
#else
-#define WGLEW_EXPORT GLEWAPI
+#define WGLEW_FUN_EXPORT GLEW_FUN_EXPORT
+#define WGLEW_VAR_EXPORT GLEW_VAR_EXPORT
#endif /* GLEW_MX */
#ifdef GLEW_MX
@@ -1130,200 +1183,205 @@ struct WGLEWContextStruct
{
#endif /* GLEW_MX */
-WGLEW_EXPORT PFNWGLSETSTEREOEMITTERSTATE3DLPROC __wglewSetStereoEmitterState3DL;
-
-WGLEW_EXPORT PFNWGLBLITCONTEXTFRAMEBUFFERAMDPROC __wglewBlitContextFramebufferAMD;
-WGLEW_EXPORT PFNWGLCREATEASSOCIATEDCONTEXTAMDPROC __wglewCreateAssociatedContextAMD;
-WGLEW_EXPORT PFNWGLCREATEASSOCIATEDCONTEXTATTRIBSAMDPROC __wglewCreateAssociatedContextAttribsAMD;
-WGLEW_EXPORT PFNWGLDELETEASSOCIATEDCONTEXTAMDPROC __wglewDeleteAssociatedContextAMD;
-WGLEW_EXPORT PFNWGLGETCONTEXTGPUIDAMDPROC __wglewGetContextGPUIDAMD;
-WGLEW_EXPORT PFNWGLGETCURRENTASSOCIATEDCONTEXTAMDPROC __wglewGetCurrentAssociatedContextAMD;
-WGLEW_EXPORT PFNWGLGETGPUIDSAMDPROC __wglewGetGPUIDsAMD;
-WGLEW_EXPORT PFNWGLGETGPUINFOAMDPROC __wglewGetGPUInfoAMD;
-WGLEW_EXPORT PFNWGLMAKEASSOCIATEDCONTEXTCURRENTAMDPROC __wglewMakeAssociatedContextCurrentAMD;
-
-WGLEW_EXPORT PFNWGLCREATEBUFFERREGIONARBPROC __wglewCreateBufferRegionARB;
-WGLEW_EXPORT PFNWGLDELETEBUFFERREGIONARBPROC __wglewDeleteBufferRegionARB;
-WGLEW_EXPORT PFNWGLRESTOREBUFFERREGIONARBPROC __wglewRestoreBufferRegionARB;
-WGLEW_EXPORT PFNWGLSAVEBUFFERREGIONARBPROC __wglewSaveBufferRegionARB;
-
-WGLEW_EXPORT PFNWGLCREATECONTEXTATTRIBSARBPROC __wglewCreateContextAttribsARB;
-
-WGLEW_EXPORT PFNWGLGETEXTENSIONSSTRINGARBPROC __wglewGetExtensionsStringARB;
-
-WGLEW_EXPORT PFNWGLGETCURRENTREADDCARBPROC __wglewGetCurrentReadDCARB;
-WGLEW_EXPORT PFNWGLMAKECONTEXTCURRENTARBPROC __wglewMakeContextCurrentARB;
-
-WGLEW_EXPORT PFNWGLCREATEPBUFFERARBPROC __wglewCreatePbufferARB;
-WGLEW_EXPORT PFNWGLDESTROYPBUFFERARBPROC __wglewDestroyPbufferARB;
-WGLEW_EXPORT PFNWGLGETPBUFFERDCARBPROC __wglewGetPbufferDCARB;
-WGLEW_EXPORT PFNWGLQUERYPBUFFERARBPROC __wglewQueryPbufferARB;
-WGLEW_EXPORT PFNWGLRELEASEPBUFFERDCARBPROC __wglewReleasePbufferDCARB;
-
-WGLEW_EXPORT PFNWGLCHOOSEPIXELFORMATARBPROC __wglewChoosePixelFormatARB;
-WGLEW_EXPORT PFNWGLGETPIXELFORMATATTRIBFVARBPROC __wglewGetPixelFormatAttribfvARB;
-WGLEW_EXPORT PFNWGLGETPIXELFORMATATTRIBIVARBPROC __wglewGetPixelFormatAttribivARB;
-
-WGLEW_EXPORT PFNWGLBINDTEXIMAGEARBPROC __wglewBindTexImageARB;
-WGLEW_EXPORT PFNWGLRELEASETEXIMAGEARBPROC __wglewReleaseTexImageARB;
-WGLEW_EXPORT PFNWGLSETPBUFFERATTRIBARBPROC __wglewSetPbufferAttribARB;
-
-WGLEW_EXPORT PFNWGLBINDDISPLAYCOLORTABLEEXTPROC __wglewBindDisplayColorTableEXT;
-WGLEW_EXPORT PFNWGLCREATEDISPLAYCOLORTABLEEXTPROC __wglewCreateDisplayColorTableEXT;
-WGLEW_EXPORT PFNWGLDESTROYDISPLAYCOLORTABLEEXTPROC __wglewDestroyDisplayColorTableEXT;
-WGLEW_EXPORT PFNWGLLOADDISPLAYCOLORTABLEEXTPROC __wglewLoadDisplayColorTableEXT;
-
-WGLEW_EXPORT PFNWGLGETEXTENSIONSSTRINGEXTPROC __wglewGetExtensionsStringEXT;
-
-WGLEW_EXPORT PFNWGLGETCURRENTREADDCEXTPROC __wglewGetCurrentReadDCEXT;
-WGLEW_EXPORT PFNWGLMAKECONTEXTCURRENTEXTPROC __wglewMakeContextCurrentEXT;
-
-WGLEW_EXPORT PFNWGLCREATEPBUFFEREXTPROC __wglewCreatePbufferEXT;
-WGLEW_EXPORT PFNWGLDESTROYPBUFFEREXTPROC __wglewDestroyPbufferEXT;
-WGLEW_EXPORT PFNWGLGETPBUFFERDCEXTPROC __wglewGetPbufferDCEXT;
-WGLEW_EXPORT PFNWGLQUERYPBUFFEREXTPROC __wglewQueryPbufferEXT;
-WGLEW_EXPORT PFNWGLRELEASEPBUFFERDCEXTPROC __wglewReleasePbufferDCEXT;
-
-WGLEW_EXPORT PFNWGLCHOOSEPIXELFORMATEXTPROC __wglewChoosePixelFormatEXT;
-WGLEW_EXPORT PFNWGLGETPIXELFORMATATTRIBFVEXTPROC __wglewGetPixelFormatAttribfvEXT;
-WGLEW_EXPORT PFNWGLGETPIXELFORMATATTRIBIVEXTPROC __wglewGetPixelFormatAttribivEXT;
-
-WGLEW_EXPORT PFNWGLGETSWAPINTERVALEXTPROC __wglewGetSwapIntervalEXT;
-WGLEW_EXPORT PFNWGLSWAPINTERVALEXTPROC __wglewSwapIntervalEXT;
-
-WGLEW_EXPORT PFNWGLGETDIGITALVIDEOPARAMETERSI3DPROC __wglewGetDigitalVideoParametersI3D;
-WGLEW_EXPORT PFNWGLSETDIGITALVIDEOPARAMETERSI3DPROC __wglewSetDigitalVideoParametersI3D;
-
-WGLEW_EXPORT PFNWGLGETGAMMATABLEI3DPROC __wglewGetGammaTableI3D;
-WGLEW_EXPORT PFNWGLGETGAMMATABLEPARAMETERSI3DPROC __wglewGetGammaTableParametersI3D;
-WGLEW_EXPORT PFNWGLSETGAMMATABLEI3DPROC __wglewSetGammaTableI3D;
-WGLEW_EXPORT PFNWGLSETGAMMATABLEPARAMETERSI3DPROC __wglewSetGammaTableParametersI3D;
-
-WGLEW_EXPORT PFNWGLDISABLEGENLOCKI3DPROC __wglewDisableGenlockI3D;
-WGLEW_EXPORT PFNWGLENABLEGENLOCKI3DPROC __wglewEnableGenlockI3D;
-WGLEW_EXPORT PFNWGLGENLOCKSAMPLERATEI3DPROC __wglewGenlockSampleRateI3D;
-WGLEW_EXPORT PFNWGLGENLOCKSOURCEDELAYI3DPROC __wglewGenlockSourceDelayI3D;
-WGLEW_EXPORT PFNWGLGENLOCKSOURCEEDGEI3DPROC __wglewGenlockSourceEdgeI3D;
-WGLEW_EXPORT PFNWGLGENLOCKSOURCEI3DPROC __wglewGenlockSourceI3D;
-WGLEW_EXPORT PFNWGLGETGENLOCKSAMPLERATEI3DPROC __wglewGetGenlockSampleRateI3D;
-WGLEW_EXPORT PFNWGLGETGENLOCKSOURCEDELAYI3DPROC __wglewGetGenlockSourceDelayI3D;
-WGLEW_EXPORT PFNWGLGETGENLOCKSOURCEEDGEI3DPROC __wglewGetGenlockSourceEdgeI3D;
-WGLEW_EXPORT PFNWGLGETGENLOCKSOURCEI3DPROC __wglewGetGenlockSourceI3D;
-WGLEW_EXPORT PFNWGLISENABLEDGENLOCKI3DPROC __wglewIsEnabledGenlockI3D;
-WGLEW_EXPORT PFNWGLQUERYGENLOCKMAXSOURCEDELAYI3DPROC __wglewQueryGenlockMaxSourceDelayI3D;
-
-WGLEW_EXPORT PFNWGLASSOCIATEIMAGEBUFFEREVENTSI3DPROC __wglewAssociateImageBufferEventsI3D;
-WGLEW_EXPORT PFNWGLCREATEIMAGEBUFFERI3DPROC __wglewCreateImageBufferI3D;
-WGLEW_EXPORT PFNWGLDESTROYIMAGEBUFFERI3DPROC __wglewDestroyImageBufferI3D;
-WGLEW_EXPORT PFNWGLRELEASEIMAGEBUFFEREVENTSI3DPROC __wglewReleaseImageBufferEventsI3D;
-
-WGLEW_EXPORT PFNWGLDISABLEFRAMELOCKI3DPROC __wglewDisableFrameLockI3D;
-WGLEW_EXPORT PFNWGLENABLEFRAMELOCKI3DPROC __wglewEnableFrameLockI3D;
-WGLEW_EXPORT PFNWGLISENABLEDFRAMELOCKI3DPROC __wglewIsEnabledFrameLockI3D;
-WGLEW_EXPORT PFNWGLQUERYFRAMELOCKMASTERI3DPROC __wglewQueryFrameLockMasterI3D;
-
-WGLEW_EXPORT PFNWGLBEGINFRAMETRACKINGI3DPROC __wglewBeginFrameTrackingI3D;
-WGLEW_EXPORT PFNWGLENDFRAMETRACKINGI3DPROC __wglewEndFrameTrackingI3D;
-WGLEW_EXPORT PFNWGLGETFRAMEUSAGEI3DPROC __wglewGetFrameUsageI3D;
-WGLEW_EXPORT PFNWGLQUERYFRAMETRACKINGI3DPROC __wglewQueryFrameTrackingI3D;
-
-WGLEW_EXPORT PFNWGLDXCLOSEDEVICENVPROC __wglewDXCloseDeviceNV;
-WGLEW_EXPORT PFNWGLDXLOCKOBJECTSNVPROC __wglewDXLockObjectsNV;
-WGLEW_EXPORT PFNWGLDXOBJECTACCESSNVPROC __wglewDXObjectAccessNV;
-WGLEW_EXPORT PFNWGLDXOPENDEVICENVPROC __wglewDXOpenDeviceNV;
-WGLEW_EXPORT PFNWGLDXREGISTEROBJECTNVPROC __wglewDXRegisterObjectNV;
-WGLEW_EXPORT PFNWGLDXSETRESOURCESHAREHANDLENVPROC __wglewDXSetResourceShareHandleNV;
-WGLEW_EXPORT PFNWGLDXUNLOCKOBJECTSNVPROC __wglewDXUnlockObjectsNV;
-WGLEW_EXPORT PFNWGLDXUNREGISTEROBJECTNVPROC __wglewDXUnregisterObjectNV;
-
-WGLEW_EXPORT PFNWGLCOPYIMAGESUBDATANVPROC __wglewCopyImageSubDataNV;
-
-WGLEW_EXPORT PFNWGLCREATEAFFINITYDCNVPROC __wglewCreateAffinityDCNV;
-WGLEW_EXPORT PFNWGLDELETEDCNVPROC __wglewDeleteDCNV;
-WGLEW_EXPORT PFNWGLENUMGPUDEVICESNVPROC __wglewEnumGpuDevicesNV;
-WGLEW_EXPORT PFNWGLENUMGPUSFROMAFFINITYDCNVPROC __wglewEnumGpusFromAffinityDCNV;
-WGLEW_EXPORT PFNWGLENUMGPUSNVPROC __wglewEnumGpusNV;
-
-WGLEW_EXPORT PFNWGLBINDVIDEODEVICENVPROC __wglewBindVideoDeviceNV;
-WGLEW_EXPORT PFNWGLENUMERATEVIDEODEVICESNVPROC __wglewEnumerateVideoDevicesNV;
-WGLEW_EXPORT PFNWGLQUERYCURRENTCONTEXTNVPROC __wglewQueryCurrentContextNV;
-
-WGLEW_EXPORT PFNWGLBINDSWAPBARRIERNVPROC __wglewBindSwapBarrierNV;
-WGLEW_EXPORT PFNWGLJOINSWAPGROUPNVPROC __wglewJoinSwapGroupNV;
-WGLEW_EXPORT PFNWGLQUERYFRAMECOUNTNVPROC __wglewQueryFrameCountNV;
-WGLEW_EXPORT PFNWGLQUERYMAXSWAPGROUPSNVPROC __wglewQueryMaxSwapGroupsNV;
-WGLEW_EXPORT PFNWGLQUERYSWAPGROUPNVPROC __wglewQuerySwapGroupNV;
-WGLEW_EXPORT PFNWGLRESETFRAMECOUNTNVPROC __wglewResetFrameCountNV;
-
-WGLEW_EXPORT PFNWGLALLOCATEMEMORYNVPROC __wglewAllocateMemoryNV;
-WGLEW_EXPORT PFNWGLFREEMEMORYNVPROC __wglewFreeMemoryNV;
-
-WGLEW_EXPORT PFNWGLBINDVIDEOCAPTUREDEVICENVPROC __wglewBindVideoCaptureDeviceNV;
-WGLEW_EXPORT PFNWGLENUMERATEVIDEOCAPTUREDEVICESNVPROC __wglewEnumerateVideoCaptureDevicesNV;
-WGLEW_EXPORT PFNWGLLOCKVIDEOCAPTUREDEVICENVPROC __wglewLockVideoCaptureDeviceNV;
-WGLEW_EXPORT PFNWGLQUERYVIDEOCAPTUREDEVICENVPROC __wglewQueryVideoCaptureDeviceNV;
-WGLEW_EXPORT PFNWGLRELEASEVIDEOCAPTUREDEVICENVPROC __wglewReleaseVideoCaptureDeviceNV;
-
-WGLEW_EXPORT PFNWGLBINDVIDEOIMAGENVPROC __wglewBindVideoImageNV;
-WGLEW_EXPORT PFNWGLGETVIDEODEVICENVPROC __wglewGetVideoDeviceNV;
-WGLEW_EXPORT PFNWGLGETVIDEOINFONVPROC __wglewGetVideoInfoNV;
-WGLEW_EXPORT PFNWGLRELEASEVIDEODEVICENVPROC __wglewReleaseVideoDeviceNV;
-WGLEW_EXPORT PFNWGLRELEASEVIDEOIMAGENVPROC __wglewReleaseVideoImageNV;
-WGLEW_EXPORT PFNWGLSENDPBUFFERTOVIDEONVPROC __wglewSendPbufferToVideoNV;
-
-WGLEW_EXPORT PFNWGLGETMSCRATEOMLPROC __wglewGetMscRateOML;
-WGLEW_EXPORT PFNWGLGETSYNCVALUESOMLPROC __wglewGetSyncValuesOML;
-WGLEW_EXPORT PFNWGLSWAPBUFFERSMSCOMLPROC __wglewSwapBuffersMscOML;
-WGLEW_EXPORT PFNWGLSWAPLAYERBUFFERSMSCOMLPROC __wglewSwapLayerBuffersMscOML;
-WGLEW_EXPORT PFNWGLWAITFORMSCOMLPROC __wglewWaitForMscOML;
-WGLEW_EXPORT PFNWGLWAITFORSBCOMLPROC __wglewWaitForSbcOML;
-WGLEW_EXPORT GLboolean __WGLEW_3DFX_multisample;
-WGLEW_EXPORT GLboolean __WGLEW_3DL_stereo_control;
-WGLEW_EXPORT GLboolean __WGLEW_AMD_gpu_association;
-WGLEW_EXPORT GLboolean __WGLEW_ARB_buffer_region;
-WGLEW_EXPORT GLboolean __WGLEW_ARB_create_context;
-WGLEW_EXPORT GLboolean __WGLEW_ARB_create_context_profile;
-WGLEW_EXPORT GLboolean __WGLEW_ARB_create_context_robustness;
-WGLEW_EXPORT GLboolean __WGLEW_ARB_extensions_string;
-WGLEW_EXPORT GLboolean __WGLEW_ARB_framebuffer_sRGB;
-WGLEW_EXPORT GLboolean __WGLEW_ARB_make_current_read;
-WGLEW_EXPORT GLboolean __WGLEW_ARB_multisample;
-WGLEW_EXPORT GLboolean __WGLEW_ARB_pbuffer;
-WGLEW_EXPORT GLboolean __WGLEW_ARB_pixel_format;
-WGLEW_EXPORT GLboolean __WGLEW_ARB_pixel_format_float;
-WGLEW_EXPORT GLboolean __WGLEW_ARB_render_texture;
-WGLEW_EXPORT GLboolean __WGLEW_ATI_pixel_format_float;
-WGLEW_EXPORT GLboolean __WGLEW_ATI_render_texture_rectangle;
-WGLEW_EXPORT GLboolean __WGLEW_EXT_create_context_es2_profile;
-WGLEW_EXPORT GLboolean __WGLEW_EXT_depth_float;
-WGLEW_EXPORT GLboolean __WGLEW_EXT_display_color_table;
-WGLEW_EXPORT GLboolean __WGLEW_EXT_extensions_string;
-WGLEW_EXPORT GLboolean __WGLEW_EXT_framebuffer_sRGB;
-WGLEW_EXPORT GLboolean __WGLEW_EXT_make_current_read;
-WGLEW_EXPORT GLboolean __WGLEW_EXT_multisample;
-WGLEW_EXPORT GLboolean __WGLEW_EXT_pbuffer;
-WGLEW_EXPORT GLboolean __WGLEW_EXT_pixel_format;
-WGLEW_EXPORT GLboolean __WGLEW_EXT_pixel_format_packed_float;
-WGLEW_EXPORT GLboolean __WGLEW_EXT_swap_control;
-WGLEW_EXPORT GLboolean __WGLEW_I3D_digital_video_control;
-WGLEW_EXPORT GLboolean __WGLEW_I3D_gamma;
-WGLEW_EXPORT GLboolean __WGLEW_I3D_genlock;
-WGLEW_EXPORT GLboolean __WGLEW_I3D_image_buffer;
-WGLEW_EXPORT GLboolean __WGLEW_I3D_swap_frame_lock;
-WGLEW_EXPORT GLboolean __WGLEW_I3D_swap_frame_usage;
-WGLEW_EXPORT GLboolean __WGLEW_NV_DX_interop;
-WGLEW_EXPORT GLboolean __WGLEW_NV_copy_image;
-WGLEW_EXPORT GLboolean __WGLEW_NV_float_buffer;
-WGLEW_EXPORT GLboolean __WGLEW_NV_gpu_affinity;
-WGLEW_EXPORT GLboolean __WGLEW_NV_multisample_coverage;
-WGLEW_EXPORT GLboolean __WGLEW_NV_present_video;
-WGLEW_EXPORT GLboolean __WGLEW_NV_render_depth_texture;
-WGLEW_EXPORT GLboolean __WGLEW_NV_render_texture_rectangle;
-WGLEW_EXPORT GLboolean __WGLEW_NV_swap_group;
-WGLEW_EXPORT GLboolean __WGLEW_NV_vertex_array_range;
-WGLEW_EXPORT GLboolean __WGLEW_NV_video_capture;
-WGLEW_EXPORT GLboolean __WGLEW_NV_video_output;
-WGLEW_EXPORT GLboolean __WGLEW_OML_sync_control;
+WGLEW_FUN_EXPORT PFNWGLSETSTEREOEMITTERSTATE3DLPROC __wglewSetStereoEmitterState3DL;
+
+WGLEW_FUN_EXPORT PFNWGLBLITCONTEXTFRAMEBUFFERAMDPROC __wglewBlitContextFramebufferAMD;
+WGLEW_FUN_EXPORT PFNWGLCREATEASSOCIATEDCONTEXTAMDPROC __wglewCreateAssociatedContextAMD;
+WGLEW_FUN_EXPORT PFNWGLCREATEASSOCIATEDCONTEXTATTRIBSAMDPROC __wglewCreateAssociatedContextAttribsAMD;
+WGLEW_FUN_EXPORT PFNWGLDELETEASSOCIATEDCONTEXTAMDPROC __wglewDeleteAssociatedContextAMD;
+WGLEW_FUN_EXPORT PFNWGLGETCONTEXTGPUIDAMDPROC __wglewGetContextGPUIDAMD;
+WGLEW_FUN_EXPORT PFNWGLGETCURRENTASSOCIATEDCONTEXTAMDPROC __wglewGetCurrentAssociatedContextAMD;
+WGLEW_FUN_EXPORT PFNWGLGETGPUIDSAMDPROC __wglewGetGPUIDsAMD;
+WGLEW_FUN_EXPORT PFNWGLGETGPUINFOAMDPROC __wglewGetGPUInfoAMD;
+WGLEW_FUN_EXPORT PFNWGLMAKEASSOCIATEDCONTEXTCURRENTAMDPROC __wglewMakeAssociatedContextCurrentAMD;
+
+WGLEW_FUN_EXPORT PFNWGLCREATEBUFFERREGIONARBPROC __wglewCreateBufferRegionARB;
+WGLEW_FUN_EXPORT PFNWGLDELETEBUFFERREGIONARBPROC __wglewDeleteBufferRegionARB;
+WGLEW_FUN_EXPORT PFNWGLRESTOREBUFFERREGIONARBPROC __wglewRestoreBufferRegionARB;
+WGLEW_FUN_EXPORT PFNWGLSAVEBUFFERREGIONARBPROC __wglewSaveBufferRegionARB;
+
+WGLEW_FUN_EXPORT PFNWGLCREATECONTEXTATTRIBSARBPROC __wglewCreateContextAttribsARB;
+
+WGLEW_FUN_EXPORT PFNWGLGETEXTENSIONSSTRINGARBPROC __wglewGetExtensionsStringARB;
+
+WGLEW_FUN_EXPORT PFNWGLGETCURRENTREADDCARBPROC __wglewGetCurrentReadDCARB;
+WGLEW_FUN_EXPORT PFNWGLMAKECONTEXTCURRENTARBPROC __wglewMakeContextCurrentARB;
+
+WGLEW_FUN_EXPORT PFNWGLCREATEPBUFFERARBPROC __wglewCreatePbufferARB;
+WGLEW_FUN_EXPORT PFNWGLDESTROYPBUFFERARBPROC __wglewDestroyPbufferARB;
+WGLEW_FUN_EXPORT PFNWGLGETPBUFFERDCARBPROC __wglewGetPbufferDCARB;
+WGLEW_FUN_EXPORT PFNWGLQUERYPBUFFERARBPROC __wglewQueryPbufferARB;
+WGLEW_FUN_EXPORT PFNWGLRELEASEPBUFFERDCARBPROC __wglewReleasePbufferDCARB;
+
+WGLEW_FUN_EXPORT PFNWGLCHOOSEPIXELFORMATARBPROC __wglewChoosePixelFormatARB;
+WGLEW_FUN_EXPORT PFNWGLGETPIXELFORMATATTRIBFVARBPROC __wglewGetPixelFormatAttribfvARB;
+WGLEW_FUN_EXPORT PFNWGLGETPIXELFORMATATTRIBIVARBPROC __wglewGetPixelFormatAttribivARB;
+
+WGLEW_FUN_EXPORT PFNWGLBINDTEXIMAGEARBPROC __wglewBindTexImageARB;
+WGLEW_FUN_EXPORT PFNWGLRELEASETEXIMAGEARBPROC __wglewReleaseTexImageARB;
+WGLEW_FUN_EXPORT PFNWGLSETPBUFFERATTRIBARBPROC __wglewSetPbufferAttribARB;
+
+WGLEW_FUN_EXPORT PFNWGLBINDDISPLAYCOLORTABLEEXTPROC __wglewBindDisplayColorTableEXT;
+WGLEW_FUN_EXPORT PFNWGLCREATEDISPLAYCOLORTABLEEXTPROC __wglewCreateDisplayColorTableEXT;
+WGLEW_FUN_EXPORT PFNWGLDESTROYDISPLAYCOLORTABLEEXTPROC __wglewDestroyDisplayColorTableEXT;
+WGLEW_FUN_EXPORT PFNWGLLOADDISPLAYCOLORTABLEEXTPROC __wglewLoadDisplayColorTableEXT;
+
+WGLEW_FUN_EXPORT PFNWGLGETEXTENSIONSSTRINGEXTPROC __wglewGetExtensionsStringEXT;
+
+WGLEW_FUN_EXPORT PFNWGLGETCURRENTREADDCEXTPROC __wglewGetCurrentReadDCEXT;
+WGLEW_FUN_EXPORT PFNWGLMAKECONTEXTCURRENTEXTPROC __wglewMakeContextCurrentEXT;
+
+WGLEW_FUN_EXPORT PFNWGLCREATEPBUFFEREXTPROC __wglewCreatePbufferEXT;
+WGLEW_FUN_EXPORT PFNWGLDESTROYPBUFFEREXTPROC __wglewDestroyPbufferEXT;
+WGLEW_FUN_EXPORT PFNWGLGETPBUFFERDCEXTPROC __wglewGetPbufferDCEXT;
+WGLEW_FUN_EXPORT PFNWGLQUERYPBUFFEREXTPROC __wglewQueryPbufferEXT;
+WGLEW_FUN_EXPORT PFNWGLRELEASEPBUFFERDCEXTPROC __wglewReleasePbufferDCEXT;
+
+WGLEW_FUN_EXPORT PFNWGLCHOOSEPIXELFORMATEXTPROC __wglewChoosePixelFormatEXT;
+WGLEW_FUN_EXPORT PFNWGLGETPIXELFORMATATTRIBFVEXTPROC __wglewGetPixelFormatAttribfvEXT;
+WGLEW_FUN_EXPORT PFNWGLGETPIXELFORMATATTRIBIVEXTPROC __wglewGetPixelFormatAttribivEXT;
+
+WGLEW_FUN_EXPORT PFNWGLGETSWAPINTERVALEXTPROC __wglewGetSwapIntervalEXT;
+WGLEW_FUN_EXPORT PFNWGLSWAPINTERVALEXTPROC __wglewSwapIntervalEXT;
+
+WGLEW_FUN_EXPORT PFNWGLGETDIGITALVIDEOPARAMETERSI3DPROC __wglewGetDigitalVideoParametersI3D;
+WGLEW_FUN_EXPORT PFNWGLSETDIGITALVIDEOPARAMETERSI3DPROC __wglewSetDigitalVideoParametersI3D;
+
+WGLEW_FUN_EXPORT PFNWGLGETGAMMATABLEI3DPROC __wglewGetGammaTableI3D;
+WGLEW_FUN_EXPORT PFNWGLGETGAMMATABLEPARAMETERSI3DPROC __wglewGetGammaTableParametersI3D;
+WGLEW_FUN_EXPORT PFNWGLSETGAMMATABLEI3DPROC __wglewSetGammaTableI3D;
+WGLEW_FUN_EXPORT PFNWGLSETGAMMATABLEPARAMETERSI3DPROC __wglewSetGammaTableParametersI3D;
+
+WGLEW_FUN_EXPORT PFNWGLDISABLEGENLOCKI3DPROC __wglewDisableGenlockI3D;
+WGLEW_FUN_EXPORT PFNWGLENABLEGENLOCKI3DPROC __wglewEnableGenlockI3D;
+WGLEW_FUN_EXPORT PFNWGLGENLOCKSAMPLERATEI3DPROC __wglewGenlockSampleRateI3D;
+WGLEW_FUN_EXPORT PFNWGLGENLOCKSOURCEDELAYI3DPROC __wglewGenlockSourceDelayI3D;
+WGLEW_FUN_EXPORT PFNWGLGENLOCKSOURCEEDGEI3DPROC __wglewGenlockSourceEdgeI3D;
+WGLEW_FUN_EXPORT PFNWGLGENLOCKSOURCEI3DPROC __wglewGenlockSourceI3D;
+WGLEW_FUN_EXPORT PFNWGLGETGENLOCKSAMPLERATEI3DPROC __wglewGetGenlockSampleRateI3D;
+WGLEW_FUN_EXPORT PFNWGLGETGENLOCKSOURCEDELAYI3DPROC __wglewGetGenlockSourceDelayI3D;
+WGLEW_FUN_EXPORT PFNWGLGETGENLOCKSOURCEEDGEI3DPROC __wglewGetGenlockSourceEdgeI3D;
+WGLEW_FUN_EXPORT PFNWGLGETGENLOCKSOURCEI3DPROC __wglewGetGenlockSourceI3D;
+WGLEW_FUN_EXPORT PFNWGLISENABLEDGENLOCKI3DPROC __wglewIsEnabledGenlockI3D;
+WGLEW_FUN_EXPORT PFNWGLQUERYGENLOCKMAXSOURCEDELAYI3DPROC __wglewQueryGenlockMaxSourceDelayI3D;
+
+WGLEW_FUN_EXPORT PFNWGLASSOCIATEIMAGEBUFFEREVENTSI3DPROC __wglewAssociateImageBufferEventsI3D;
+WGLEW_FUN_EXPORT PFNWGLCREATEIMAGEBUFFERI3DPROC __wglewCreateImageBufferI3D;
+WGLEW_FUN_EXPORT PFNWGLDESTROYIMAGEBUFFERI3DPROC __wglewDestroyImageBufferI3D;
+WGLEW_FUN_EXPORT PFNWGLRELEASEIMAGEBUFFEREVENTSI3DPROC __wglewReleaseImageBufferEventsI3D;
+
+WGLEW_FUN_EXPORT PFNWGLDISABLEFRAMELOCKI3DPROC __wglewDisableFrameLockI3D;
+WGLEW_FUN_EXPORT PFNWGLENABLEFRAMELOCKI3DPROC __wglewEnableFrameLockI3D;
+WGLEW_FUN_EXPORT PFNWGLISENABLEDFRAMELOCKI3DPROC __wglewIsEnabledFrameLockI3D;
+WGLEW_FUN_EXPORT PFNWGLQUERYFRAMELOCKMASTERI3DPROC __wglewQueryFrameLockMasterI3D;
+
+WGLEW_FUN_EXPORT PFNWGLBEGINFRAMETRACKINGI3DPROC __wglewBeginFrameTrackingI3D;
+WGLEW_FUN_EXPORT PFNWGLENDFRAMETRACKINGI3DPROC __wglewEndFrameTrackingI3D;
+WGLEW_FUN_EXPORT PFNWGLGETFRAMEUSAGEI3DPROC __wglewGetFrameUsageI3D;
+WGLEW_FUN_EXPORT PFNWGLQUERYFRAMETRACKINGI3DPROC __wglewQueryFrameTrackingI3D;
+
+WGLEW_FUN_EXPORT PFNWGLDXCLOSEDEVICENVPROC __wglewDXCloseDeviceNV;
+WGLEW_FUN_EXPORT PFNWGLDXLOCKOBJECTSNVPROC __wglewDXLockObjectsNV;
+WGLEW_FUN_EXPORT PFNWGLDXOBJECTACCESSNVPROC __wglewDXObjectAccessNV;
+WGLEW_FUN_EXPORT PFNWGLDXOPENDEVICENVPROC __wglewDXOpenDeviceNV;
+WGLEW_FUN_EXPORT PFNWGLDXREGISTEROBJECTNVPROC __wglewDXRegisterObjectNV;
+WGLEW_FUN_EXPORT PFNWGLDXSETRESOURCESHAREHANDLENVPROC __wglewDXSetResourceShareHandleNV;
+WGLEW_FUN_EXPORT PFNWGLDXUNLOCKOBJECTSNVPROC __wglewDXUnlockObjectsNV;
+WGLEW_FUN_EXPORT PFNWGLDXUNREGISTEROBJECTNVPROC __wglewDXUnregisterObjectNV;
+
+WGLEW_FUN_EXPORT PFNWGLCOPYIMAGESUBDATANVPROC __wglewCopyImageSubDataNV;
+
+WGLEW_FUN_EXPORT PFNWGLCREATEAFFINITYDCNVPROC __wglewCreateAffinityDCNV;
+WGLEW_FUN_EXPORT PFNWGLDELETEDCNVPROC __wglewDeleteDCNV;
+WGLEW_FUN_EXPORT PFNWGLENUMGPUDEVICESNVPROC __wglewEnumGpuDevicesNV;
+WGLEW_FUN_EXPORT PFNWGLENUMGPUSFROMAFFINITYDCNVPROC __wglewEnumGpusFromAffinityDCNV;
+WGLEW_FUN_EXPORT PFNWGLENUMGPUSNVPROC __wglewEnumGpusNV;
+
+WGLEW_FUN_EXPORT PFNWGLBINDVIDEODEVICENVPROC __wglewBindVideoDeviceNV;
+WGLEW_FUN_EXPORT PFNWGLENUMERATEVIDEODEVICESNVPROC __wglewEnumerateVideoDevicesNV;
+WGLEW_FUN_EXPORT PFNWGLQUERYCURRENTCONTEXTNVPROC __wglewQueryCurrentContextNV;
+
+WGLEW_FUN_EXPORT PFNWGLBINDSWAPBARRIERNVPROC __wglewBindSwapBarrierNV;
+WGLEW_FUN_EXPORT PFNWGLJOINSWAPGROUPNVPROC __wglewJoinSwapGroupNV;
+WGLEW_FUN_EXPORT PFNWGLQUERYFRAMECOUNTNVPROC __wglewQueryFrameCountNV;
+WGLEW_FUN_EXPORT PFNWGLQUERYMAXSWAPGROUPSNVPROC __wglewQueryMaxSwapGroupsNV;
+WGLEW_FUN_EXPORT PFNWGLQUERYSWAPGROUPNVPROC __wglewQuerySwapGroupNV;
+WGLEW_FUN_EXPORT PFNWGLRESETFRAMECOUNTNVPROC __wglewResetFrameCountNV;
+
+WGLEW_FUN_EXPORT PFNWGLALLOCATEMEMORYNVPROC __wglewAllocateMemoryNV;
+WGLEW_FUN_EXPORT PFNWGLFREEMEMORYNVPROC __wglewFreeMemoryNV;
+
+WGLEW_FUN_EXPORT PFNWGLBINDVIDEOCAPTUREDEVICENVPROC __wglewBindVideoCaptureDeviceNV;
+WGLEW_FUN_EXPORT PFNWGLENUMERATEVIDEOCAPTUREDEVICESNVPROC __wglewEnumerateVideoCaptureDevicesNV;
+WGLEW_FUN_EXPORT PFNWGLLOCKVIDEOCAPTUREDEVICENVPROC __wglewLockVideoCaptureDeviceNV;
+WGLEW_FUN_EXPORT PFNWGLQUERYVIDEOCAPTUREDEVICENVPROC __wglewQueryVideoCaptureDeviceNV;
+WGLEW_FUN_EXPORT PFNWGLRELEASEVIDEOCAPTUREDEVICENVPROC __wglewReleaseVideoCaptureDeviceNV;
+
+WGLEW_FUN_EXPORT PFNWGLBINDVIDEOIMAGENVPROC __wglewBindVideoImageNV;
+WGLEW_FUN_EXPORT PFNWGLGETVIDEODEVICENVPROC __wglewGetVideoDeviceNV;
+WGLEW_FUN_EXPORT PFNWGLGETVIDEOINFONVPROC __wglewGetVideoInfoNV;
+WGLEW_FUN_EXPORT PFNWGLRELEASEVIDEODEVICENVPROC __wglewReleaseVideoDeviceNV;
+WGLEW_FUN_EXPORT PFNWGLRELEASEVIDEOIMAGENVPROC __wglewReleaseVideoImageNV;
+WGLEW_FUN_EXPORT PFNWGLSENDPBUFFERTOVIDEONVPROC __wglewSendPbufferToVideoNV;
+
+WGLEW_FUN_EXPORT PFNWGLGETMSCRATEOMLPROC __wglewGetMscRateOML;
+WGLEW_FUN_EXPORT PFNWGLGETSYNCVALUESOMLPROC __wglewGetSyncValuesOML;
+WGLEW_FUN_EXPORT PFNWGLSWAPBUFFERSMSCOMLPROC __wglewSwapBuffersMscOML;
+WGLEW_FUN_EXPORT PFNWGLSWAPLAYERBUFFERSMSCOMLPROC __wglewSwapLayerBuffersMscOML;
+WGLEW_FUN_EXPORT PFNWGLWAITFORMSCOMLPROC __wglewWaitForMscOML;
+WGLEW_FUN_EXPORT PFNWGLWAITFORSBCOMLPROC __wglewWaitForSbcOML;
+WGLEW_VAR_EXPORT GLboolean __WGLEW_3DFX_multisample;
+WGLEW_VAR_EXPORT GLboolean __WGLEW_3DL_stereo_control;
+WGLEW_VAR_EXPORT GLboolean __WGLEW_AMD_gpu_association;
+WGLEW_VAR_EXPORT GLboolean __WGLEW_ARB_buffer_region;
+WGLEW_VAR_EXPORT GLboolean __WGLEW_ARB_create_context;
+WGLEW_VAR_EXPORT GLboolean __WGLEW_ARB_create_context_profile;
+WGLEW_VAR_EXPORT GLboolean __WGLEW_ARB_create_context_robustness;
+WGLEW_VAR_EXPORT GLboolean __WGLEW_ARB_extensions_string;
+WGLEW_VAR_EXPORT GLboolean __WGLEW_ARB_framebuffer_sRGB;
+WGLEW_VAR_EXPORT GLboolean __WGLEW_ARB_make_current_read;
+WGLEW_VAR_EXPORT GLboolean __WGLEW_ARB_multisample;
+WGLEW_VAR_EXPORT GLboolean __WGLEW_ARB_pbuffer;
+WGLEW_VAR_EXPORT GLboolean __WGLEW_ARB_pixel_format;
+WGLEW_VAR_EXPORT GLboolean __WGLEW_ARB_pixel_format_float;
+WGLEW_VAR_EXPORT GLboolean __WGLEW_ARB_render_texture;
+WGLEW_VAR_EXPORT GLboolean __WGLEW_ARB_robustness_application_isolation;
+WGLEW_VAR_EXPORT GLboolean __WGLEW_ARB_robustness_share_group_isolation;
+WGLEW_VAR_EXPORT GLboolean __WGLEW_ATI_pixel_format_float;
+WGLEW_VAR_EXPORT GLboolean __WGLEW_ATI_render_texture_rectangle;
+WGLEW_VAR_EXPORT GLboolean __WGLEW_EXT_create_context_es2_profile;
+WGLEW_VAR_EXPORT GLboolean __WGLEW_EXT_create_context_es_profile;
+WGLEW_VAR_EXPORT GLboolean __WGLEW_EXT_depth_float;
+WGLEW_VAR_EXPORT GLboolean __WGLEW_EXT_display_color_table;
+WGLEW_VAR_EXPORT GLboolean __WGLEW_EXT_extensions_string;
+WGLEW_VAR_EXPORT GLboolean __WGLEW_EXT_framebuffer_sRGB;
+WGLEW_VAR_EXPORT GLboolean __WGLEW_EXT_make_current_read;
+WGLEW_VAR_EXPORT GLboolean __WGLEW_EXT_multisample;
+WGLEW_VAR_EXPORT GLboolean __WGLEW_EXT_pbuffer;
+WGLEW_VAR_EXPORT GLboolean __WGLEW_EXT_pixel_format;
+WGLEW_VAR_EXPORT GLboolean __WGLEW_EXT_pixel_format_packed_float;
+WGLEW_VAR_EXPORT GLboolean __WGLEW_EXT_swap_control;
+WGLEW_VAR_EXPORT GLboolean __WGLEW_EXT_swap_control_tear;
+WGLEW_VAR_EXPORT GLboolean __WGLEW_I3D_digital_video_control;
+WGLEW_VAR_EXPORT GLboolean __WGLEW_I3D_gamma;
+WGLEW_VAR_EXPORT GLboolean __WGLEW_I3D_genlock;
+WGLEW_VAR_EXPORT GLboolean __WGLEW_I3D_image_buffer;
+WGLEW_VAR_EXPORT GLboolean __WGLEW_I3D_swap_frame_lock;
+WGLEW_VAR_EXPORT GLboolean __WGLEW_I3D_swap_frame_usage;
+WGLEW_VAR_EXPORT GLboolean __WGLEW_NV_DX_interop;
+WGLEW_VAR_EXPORT GLboolean __WGLEW_NV_DX_interop2;
+WGLEW_VAR_EXPORT GLboolean __WGLEW_NV_copy_image;
+WGLEW_VAR_EXPORT GLboolean __WGLEW_NV_float_buffer;
+WGLEW_VAR_EXPORT GLboolean __WGLEW_NV_gpu_affinity;
+WGLEW_VAR_EXPORT GLboolean __WGLEW_NV_multisample_coverage;
+WGLEW_VAR_EXPORT GLboolean __WGLEW_NV_present_video;
+WGLEW_VAR_EXPORT GLboolean __WGLEW_NV_render_depth_texture;
+WGLEW_VAR_EXPORT GLboolean __WGLEW_NV_render_texture_rectangle;
+WGLEW_VAR_EXPORT GLboolean __WGLEW_NV_swap_group;
+WGLEW_VAR_EXPORT GLboolean __WGLEW_NV_vertex_array_range;
+WGLEW_VAR_EXPORT GLboolean __WGLEW_NV_video_capture;
+WGLEW_VAR_EXPORT GLboolean __WGLEW_NV_video_output;
+WGLEW_VAR_EXPORT GLboolean __WGLEW_OML_sync_control;
#ifdef GLEW_MX
}; /* WGLEWContextStruct */
@@ -1334,8 +1392,8 @@ WGLEW_EXPORT GLboolean __WGLEW_OML_sync_control;
#ifdef GLEW_MX
typedef struct WGLEWContextStruct WGLEWContext;
-GLEWAPI GLenum wglewContextInit (WGLEWContext* ctx);
-GLEWAPI GLboolean wglewContextIsSupported (const WGLEWContext* ctx, const char* name);
+GLEWAPI GLenum GLEWAPIENTRY wglewContextInit (WGLEWContext *ctx);
+GLEWAPI GLboolean GLEWAPIENTRY wglewContextIsSupported (const WGLEWContext *ctx, const char *name);
#define wglewInit() wglewContextInit(wglewGetContext())
#define wglewIsSupported(x) wglewContextIsSupported(wglewGetContext(), x)
@@ -1348,11 +1406,11 @@ GLEWAPI GLboolean wglewContextIsSupported (const WGLEWContext* ctx, const char*
#define WGLEW_GET_VAR(x) (*(const GLboolean*)&x)
#define WGLEW_GET_FUN(x) x
-GLEWAPI GLboolean wglewIsSupported (const char* name);
+GLEWAPI GLboolean GLEWAPIENTRY wglewIsSupported (const char *name);
#endif /* GLEW_MX */
-GLEWAPI GLboolean wglewGetExtension (const char* name);
+GLEWAPI GLboolean GLEWAPIENTRY wglewGetExtension (const char *name);
#ifdef __cplusplus
}
diff --git a/extern/glew/src/glew.c b/extern/glew/src/glew.c
index 833d3999268..d075b524883 100644
--- a/extern/glew/src/glew.c
+++ b/extern/glew/src/glew.c
@@ -30,9 +30,10 @@
*/
#include <GL/glew.h>
+
#if defined(_WIN32)
# include <GL/wglew.h>
-#elif !defined(__APPLE__) || defined(GLEW_APPLE_GLX)
+#elif !defined(__ANDROID__) && !defined(__native_client__) && (!defined(__APPLE__) || defined(GLEW_APPLE_GLX))
# include <GL/glxew.h>
#endif
@@ -93,19 +94,24 @@ void* dlGetProcAddress (const GLubyte* name)
#include <string.h>
#include <AvailabilityMacros.h>
-#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_3
+#ifdef MAC_OS_X_VERSION_10_3
#include <dlfcn.h>
void* NSGLGetProcAddress (const GLubyte *name)
{
static void* image = NULL;
+ void* addr;
if (NULL == image)
{
+#ifdef GLEW_REGAL
+ image = dlopen("libRegal.dylib", RTLD_LAZY);
+#else
image = dlopen("/System/Library/Frameworks/OpenGL.framework/Versions/Current/OpenGL", RTLD_LAZY);
+#endif
}
if( !image ) return NULL;
- void* addr = dlsym(image, (const char*)name);
+ addr = dlsym(image, (const char*)name);
if( addr ) return addr;
#ifdef GLEW_APPLE_GLX
return dlGetProcAddress( name ); // try next for glx symbols
@@ -124,7 +130,11 @@ void* NSGLGetProcAddress (const GLubyte *name)
char* symbolName;
if (NULL == image)
{
+#ifdef GLEW_REGAL
+ image = NSAddImage("libRegal.dylib", NSADDIMAGE_OPTION_RETURN_ON_ERROR);
+#else
image = NSAddImage("/System/Library/Frameworks/OpenGL.framework/Versions/Current/OpenGL", NSADDIMAGE_OPTION_RETURN_ON_ERROR);
+#endif
}
/* prepend a '_' for the Unix C symbol mangling convention */
symbolName = malloc(strlen((const char*)name) + 2);
@@ -142,7 +152,7 @@ void* NSGLGetProcAddress (const GLubyte *name)
return NULL;
#endif
}
-#endif /* MAC_OS_X_VERSION_MIN_REQUIRED */
+#endif /* MAC_OS_X_VERSION_10_3 */
#endif /* __APPLE__ */
/*
@@ -150,16 +160,16 @@ void* NSGLGetProcAddress (const GLubyte *name)
*/
#if defined(_WIN32)
# define glewGetProcAddress(name) wglGetProcAddress((LPCSTR)name)
-#else
-# if defined(__APPLE__)
-# define glewGetProcAddress(name) NSGLGetProcAddress(name)
-# else
-# if defined(__sgi) || defined(__sun)
-# define glewGetProcAddress(name) dlGetProcAddress(name)
-# else /* __linux */
-# define glewGetProcAddress(name) (*glXGetProcAddressARB)(name)
-# endif
-# endif
+#elif defined(__APPLE__) && !defined(GLEW_APPLE_GLX)
+# define glewGetProcAddress(name) NSGLGetProcAddress(name)
+#elif defined(__sgi) || defined(__sun)
+# define glewGetProcAddress(name) dlGetProcAddress(name)
+#elif defined(__ANDROID__)
+# define glewGetProcAddress(name) NULL /* TODO */
+#elif defined(__native_client__)
+# define glewGetProcAddress(name) NULL /* TODO */
+#else /* __linux */
+# define glewGetProcAddress(name) (*glXGetProcAddressARB)(name)
#endif
/*
@@ -577,6 +587,8 @@ PFNGLBLENDEQUATIONSEPARATEINDEXEDAMDPROC __glewBlendEquationSeparateIndexedAMD =
PFNGLBLENDFUNCINDEXEDAMDPROC __glewBlendFuncIndexedAMD = NULL;
PFNGLBLENDFUNCSEPARATEINDEXEDAMDPROC __glewBlendFuncSeparateIndexedAMD = NULL;
+PFNGLVERTEXATTRIBPARAMETERIAMDPROC __glewVertexAttribParameteriAMD = NULL;
+
PFNGLMULTIDRAWARRAYSINDIRECTAMDPROC __glewMultiDrawArraysIndirectAMD = NULL;
PFNGLMULTIDRAWELEMENTSINDIRECTAMDPROC __glewMultiDrawElementsIndirectAMD = NULL;
@@ -598,9 +610,36 @@ PFNGLSELECTPERFMONITORCOUNTERSAMDPROC __glewSelectPerfMonitorCountersAMD = NULL;
PFNGLSETMULTISAMPLEFVAMDPROC __glewSetMultisamplefvAMD = NULL;
+PFNGLTEXSTORAGESPARSEAMDPROC __glewTexStorageSparseAMD = NULL;
+PFNGLTEXTURESTORAGESPARSEAMDPROC __glewTextureStorageSparseAMD = NULL;
+
+PFNGLSTENCILOPVALUEAMDPROC __glewStencilOpValueAMD = NULL;
+
PFNGLTESSELLATIONFACTORAMDPROC __glewTessellationFactorAMD = NULL;
PFNGLTESSELLATIONMODEAMDPROC __glewTessellationModeAMD = NULL;
+PFNGLBLITFRAMEBUFFERANGLEPROC __glewBlitFramebufferANGLE = NULL;
+
+PFNGLRENDERBUFFERSTORAGEMULTISAMPLEANGLEPROC __glewRenderbufferStorageMultisampleANGLE = NULL;
+
+PFNGLDRAWARRAYSINSTANCEDANGLEPROC __glewDrawArraysInstancedANGLE = NULL;
+PFNGLDRAWELEMENTSINSTANCEDANGLEPROC __glewDrawElementsInstancedANGLE = NULL;
+PFNGLVERTEXATTRIBDIVISORANGLEPROC __glewVertexAttribDivisorANGLE = NULL;
+
+PFNGLBEGINQUERYANGLEPROC __glewBeginQueryANGLE = NULL;
+PFNGLDELETEQUERIESANGLEPROC __glewDeleteQueriesANGLE = NULL;
+PFNGLENDQUERYANGLEPROC __glewEndQueryANGLE = NULL;
+PFNGLGENQUERIESANGLEPROC __glewGenQueriesANGLE = NULL;
+PFNGLGETQUERYOBJECTI64VANGLEPROC __glewGetQueryObjecti64vANGLE = NULL;
+PFNGLGETQUERYOBJECTIVANGLEPROC __glewGetQueryObjectivANGLE = NULL;
+PFNGLGETQUERYOBJECTUI64VANGLEPROC __glewGetQueryObjectui64vANGLE = NULL;
+PFNGLGETQUERYOBJECTUIVANGLEPROC __glewGetQueryObjectuivANGLE = NULL;
+PFNGLGETQUERYIVANGLEPROC __glewGetQueryivANGLE = NULL;
+PFNGLISQUERYANGLEPROC __glewIsQueryANGLE = NULL;
+PFNGLQUERYCOUNTERANGLEPROC __glewQueryCounterANGLE = NULL;
+
+PFNGLGETTRANSLATEDSHADERSOURCEANGLEPROC __glewGetTranslatedShaderSourceANGLE = NULL;
+
PFNGLDRAWELEMENTARRAYAPPLEPROC __glewDrawElementArrayAPPLE = NULL;
PFNGLDRAWRANGEELEMENTARRAYAPPLEPROC __glewDrawRangeElementArrayAPPLE = NULL;
PFNGLELEMENTPOINTERAPPLEPROC __glewElementPointerAPPLE = NULL;
@@ -653,15 +692,50 @@ PFNGLDRAWARRAYSINSTANCEDBASEINSTANCEPROC __glewDrawArraysInstancedBaseInstance =
PFNGLDRAWELEMENTSINSTANCEDBASEINSTANCEPROC __glewDrawElementsInstancedBaseInstance = NULL;
PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXBASEINSTANCEPROC __glewDrawElementsInstancedBaseVertexBaseInstance = NULL;
+PFNGLGETIMAGEHANDLEARBPROC __glewGetImageHandleARB = NULL;
+PFNGLGETTEXTUREHANDLEARBPROC __glewGetTextureHandleARB = NULL;
+PFNGLGETTEXTURESAMPLERHANDLEARBPROC __glewGetTextureSamplerHandleARB = NULL;
+PFNGLGETVERTEXATTRIBLUI64VARBPROC __glewGetVertexAttribLui64vARB = NULL;
+PFNGLISIMAGEHANDLERESIDENTARBPROC __glewIsImageHandleResidentARB = NULL;
+PFNGLISTEXTUREHANDLERESIDENTARBPROC __glewIsTextureHandleResidentARB = NULL;
+PFNGLMAKEIMAGEHANDLENONRESIDENTARBPROC __glewMakeImageHandleNonResidentARB = NULL;
+PFNGLMAKEIMAGEHANDLERESIDENTARBPROC __glewMakeImageHandleResidentARB = NULL;
+PFNGLMAKETEXTUREHANDLENONRESIDENTARBPROC __glewMakeTextureHandleNonResidentARB = NULL;
+PFNGLMAKETEXTUREHANDLERESIDENTARBPROC __glewMakeTextureHandleResidentARB = NULL;
+PFNGLPROGRAMUNIFORMHANDLEUI64ARBPROC __glewProgramUniformHandleui64ARB = NULL;
+PFNGLPROGRAMUNIFORMHANDLEUI64VARBPROC __glewProgramUniformHandleui64vARB = NULL;
+PFNGLUNIFORMHANDLEUI64ARBPROC __glewUniformHandleui64ARB = NULL;
+PFNGLUNIFORMHANDLEUI64VARBPROC __glewUniformHandleui64vARB = NULL;
+PFNGLVERTEXATTRIBL1UI64ARBPROC __glewVertexAttribL1ui64ARB = NULL;
+PFNGLVERTEXATTRIBL1UI64VARBPROC __glewVertexAttribL1ui64vARB = NULL;
+
PFNGLBINDFRAGDATALOCATIONINDEXEDPROC __glewBindFragDataLocationIndexed = NULL;
PFNGLGETFRAGDATAINDEXPROC __glewGetFragDataIndex = NULL;
+PFNGLBUFFERSTORAGEPROC __glewBufferStorage = NULL;
+PFNGLNAMEDBUFFERSTORAGEEXTPROC __glewNamedBufferStorageEXT = NULL;
+
PFNGLCREATESYNCFROMCLEVENTARBPROC __glewCreateSyncFromCLeventARB = NULL;
+PFNGLCLEARBUFFERDATAPROC __glewClearBufferData = NULL;
+PFNGLCLEARBUFFERSUBDATAPROC __glewClearBufferSubData = NULL;
+PFNGLCLEARNAMEDBUFFERDATAEXTPROC __glewClearNamedBufferDataEXT = NULL;
+PFNGLCLEARNAMEDBUFFERSUBDATAEXTPROC __glewClearNamedBufferSubDataEXT = NULL;
+
+PFNGLCLEARTEXIMAGEPROC __glewClearTexImage = NULL;
+PFNGLCLEARTEXSUBIMAGEPROC __glewClearTexSubImage = NULL;
+
PFNGLCLAMPCOLORARBPROC __glewClampColorARB = NULL;
+PFNGLDISPATCHCOMPUTEPROC __glewDispatchCompute = NULL;
+PFNGLDISPATCHCOMPUTEINDIRECTPROC __glewDispatchComputeIndirect = NULL;
+
+PFNGLDISPATCHCOMPUTEGROUPSIZEARBPROC __glewDispatchComputeGroupSizeARB = NULL;
+
PFNGLCOPYBUFFERSUBDATAPROC __glewCopyBufferSubData = NULL;
+PFNGLCOPYIMAGESUBDATAPROC __glewCopyImageSubData = NULL;
+
PFNGLDEBUGMESSAGECALLBACKARBPROC __glewDebugMessageCallbackARB = NULL;
PFNGLDEBUGMESSAGECONTROLARBPROC __glewDebugMessageControlARB = NULL;
PFNGLDEBUGMESSAGEINSERTARBPROC __glewDebugMessageInsertARB = NULL;
@@ -682,6 +756,11 @@ PFNGLMULTIDRAWELEMENTSBASEVERTEXPROC __glewMultiDrawElementsBaseVertex = NULL;
PFNGLDRAWARRAYSINDIRECTPROC __glewDrawArraysIndirect = NULL;
PFNGLDRAWELEMENTSINDIRECTPROC __glewDrawElementsIndirect = NULL;
+PFNGLFRAMEBUFFERPARAMETERIPROC __glewFramebufferParameteri = NULL;
+PFNGLGETFRAMEBUFFERPARAMETERIVPROC __glewGetFramebufferParameteriv = NULL;
+PFNGLGETNAMEDFRAMEBUFFERPARAMETERIVEXTPROC __glewGetNamedFramebufferParameterivEXT = NULL;
+PFNGLNAMEDFRAMEBUFFERPARAMETERIEXTPROC __glewNamedFramebufferParameteriEXT = NULL;
+
PFNGLBINDFRAMEBUFFERPROC __glewBindFramebuffer = NULL;
PFNGLBINDRENDERBUFFERPROC __glewBindRenderbuffer = NULL;
PFNGLBLITFRAMEBUFFERPROC __glewBlitFramebuffer = NULL;
@@ -713,23 +792,6 @@ PFNGLPROGRAMBINARYPROC __glewProgramBinary = NULL;
PFNGLPROGRAMPARAMETERIPROC __glewProgramParameteri = NULL;
PFNGLGETUNIFORMDVPROC __glewGetUniformdv = NULL;
-PFNGLPROGRAMUNIFORM1DEXTPROC __glewProgramUniform1dEXT = NULL;
-PFNGLPROGRAMUNIFORM1DVEXTPROC __glewProgramUniform1dvEXT = NULL;
-PFNGLPROGRAMUNIFORM2DEXTPROC __glewProgramUniform2dEXT = NULL;
-PFNGLPROGRAMUNIFORM2DVEXTPROC __glewProgramUniform2dvEXT = NULL;
-PFNGLPROGRAMUNIFORM3DEXTPROC __glewProgramUniform3dEXT = NULL;
-PFNGLPROGRAMUNIFORM3DVEXTPROC __glewProgramUniform3dvEXT = NULL;
-PFNGLPROGRAMUNIFORM4DEXTPROC __glewProgramUniform4dEXT = NULL;
-PFNGLPROGRAMUNIFORM4DVEXTPROC __glewProgramUniform4dvEXT = NULL;
-PFNGLPROGRAMUNIFORMMATRIX2DVEXTPROC __glewProgramUniformMatrix2dvEXT = NULL;
-PFNGLPROGRAMUNIFORMMATRIX2X3DVEXTPROC __glewProgramUniformMatrix2x3dvEXT = NULL;
-PFNGLPROGRAMUNIFORMMATRIX2X4DVEXTPROC __glewProgramUniformMatrix2x4dvEXT = NULL;
-PFNGLPROGRAMUNIFORMMATRIX3DVEXTPROC __glewProgramUniformMatrix3dvEXT = NULL;
-PFNGLPROGRAMUNIFORMMATRIX3X2DVEXTPROC __glewProgramUniformMatrix3x2dvEXT = NULL;
-PFNGLPROGRAMUNIFORMMATRIX3X4DVEXTPROC __glewProgramUniformMatrix3x4dvEXT = NULL;
-PFNGLPROGRAMUNIFORMMATRIX4DVEXTPROC __glewProgramUniformMatrix4dvEXT = NULL;
-PFNGLPROGRAMUNIFORMMATRIX4X2DVEXTPROC __glewProgramUniformMatrix4x2dvEXT = NULL;
-PFNGLPROGRAMUNIFORMMATRIX4X3DVEXTPROC __glewProgramUniformMatrix4x3dvEXT = NULL;
PFNGLUNIFORM1DPROC __glewUniform1d = NULL;
PFNGLUNIFORM1DVPROC __glewUniform1dv = NULL;
PFNGLUNIFORM2DPROC __glewUniform2d = NULL;
@@ -781,12 +843,24 @@ PFNGLRESETHISTOGRAMPROC __glewResetHistogram = NULL;
PFNGLRESETMINMAXPROC __glewResetMinmax = NULL;
PFNGLSEPARABLEFILTER2DPROC __glewSeparableFilter2D = NULL;
+PFNGLMULTIDRAWARRAYSINDIRECTCOUNTARBPROC __glewMultiDrawArraysIndirectCountARB = NULL;
+PFNGLMULTIDRAWELEMENTSINDIRECTCOUNTARBPROC __glewMultiDrawElementsIndirectCountARB = NULL;
+
PFNGLDRAWARRAYSINSTANCEDARBPROC __glewDrawArraysInstancedARB = NULL;
PFNGLDRAWELEMENTSINSTANCEDARBPROC __glewDrawElementsInstancedARB = NULL;
PFNGLVERTEXATTRIBDIVISORARBPROC __glewVertexAttribDivisorARB = NULL;
PFNGLGETINTERNALFORMATIVPROC __glewGetInternalformativ = NULL;
+PFNGLGETINTERNALFORMATI64VPROC __glewGetInternalformati64v = NULL;
+
+PFNGLINVALIDATEBUFFERDATAPROC __glewInvalidateBufferData = NULL;
+PFNGLINVALIDATEBUFFERSUBDATAPROC __glewInvalidateBufferSubData = NULL;
+PFNGLINVALIDATEFRAMEBUFFERPROC __glewInvalidateFramebuffer = NULL;
+PFNGLINVALIDATESUBFRAMEBUFFERPROC __glewInvalidateSubFramebuffer = NULL;
+PFNGLINVALIDATETEXIMAGEPROC __glewInvalidateTexImage = NULL;
+PFNGLINVALIDATETEXSUBIMAGEPROC __glewInvalidateTexSubImage = NULL;
+
PFNGLFLUSHMAPPEDBUFFERRANGEPROC __glewFlushMappedBufferRange = NULL;
PFNGLMAPBUFFERRANGEPROC __glewMapBufferRange = NULL;
@@ -796,6 +870,16 @@ PFNGLMATRIXINDEXUBVARBPROC __glewMatrixIndexubvARB = NULL;
PFNGLMATRIXINDEXUIVARBPROC __glewMatrixIndexuivARB = NULL;
PFNGLMATRIXINDEXUSVARBPROC __glewMatrixIndexusvARB = NULL;
+PFNGLBINDBUFFERSBASEPROC __glewBindBuffersBase = NULL;
+PFNGLBINDBUFFERSRANGEPROC __glewBindBuffersRange = NULL;
+PFNGLBINDIMAGETEXTURESPROC __glewBindImageTextures = NULL;
+PFNGLBINDSAMPLERSPROC __glewBindSamplers = NULL;
+PFNGLBINDTEXTURESPROC __glewBindTextures = NULL;
+PFNGLBINDVERTEXBUFFERSPROC __glewBindVertexBuffers = NULL;
+
+PFNGLMULTIDRAWARRAYSINDIRECTPROC __glewMultiDrawArraysIndirect = NULL;
+PFNGLMULTIDRAWELEMENTSINDIRECTPROC __glewMultiDrawElementsIndirect = NULL;
+
PFNGLSAMPLECOVERAGEARBPROC __glewSampleCoverageARB = NULL;
PFNGLACTIVETEXTUREARBPROC __glewActiveTextureARB = NULL;
@@ -845,6 +929,13 @@ PFNGLISQUERYARBPROC __glewIsQueryARB = NULL;
PFNGLPOINTPARAMETERFARBPROC __glewPointParameterfARB = NULL;
PFNGLPOINTPARAMETERFVARBPROC __glewPointParameterfvARB = NULL;
+PFNGLGETPROGRAMINTERFACEIVPROC __glewGetProgramInterfaceiv = NULL;
+PFNGLGETPROGRAMRESOURCEINDEXPROC __glewGetProgramResourceIndex = NULL;
+PFNGLGETPROGRAMRESOURCELOCATIONPROC __glewGetProgramResourceLocation = NULL;
+PFNGLGETPROGRAMRESOURCELOCATIONINDEXPROC __glewGetProgramResourceLocationIndex = NULL;
+PFNGLGETPROGRAMRESOURCENAMEPROC __glewGetProgramResourceName = NULL;
+PFNGLGETPROGRAMRESOURCEIVPROC __glewGetProgramResourceiv = NULL;
+
PFNGLPROVOKINGVERTEXPROC __glewProvokingVertex = NULL;
PFNGLGETGRAPHICSRESETSTATUSARBPROC __glewGetGraphicsResetStatusARB = NULL;
@@ -991,6 +1082,8 @@ PFNGLUNIFORMMATRIX4FVARBPROC __glewUniformMatrix4fvARB = NULL;
PFNGLUSEPROGRAMOBJECTARBPROC __glewUseProgramObjectARB = NULL;
PFNGLVALIDATEPROGRAMARBPROC __glewValidateProgramARB = NULL;
+PFNGLSHADERSTORAGEBLOCKBINDINGPROC __glewShaderStorageBlockBinding = NULL;
+
PFNGLGETACTIVESUBROUTINENAMEPROC __glewGetActiveSubroutineName = NULL;
PFNGLGETACTIVESUBROUTINEUNIFORMNAMEPROC __glewGetActiveSubroutineUniformName = NULL;
PFNGLGETACTIVESUBROUTINEUNIFORMIVPROC __glewGetActiveSubroutineUniformiv = NULL;
@@ -1007,6 +1100,9 @@ PFNGLGETNAMEDSTRINGIVARBPROC __glewGetNamedStringivARB = NULL;
PFNGLISNAMEDSTRINGARBPROC __glewIsNamedStringARB = NULL;
PFNGLNAMEDSTRINGARBPROC __glewNamedStringARB = NULL;
+PFNGLTEXPAGECOMMITMENTARBPROC __glewTexPageCommitmentARB = NULL;
+PFNGLTEXTUREPAGECOMMITMENTEXTPROC __glewTexturePageCommitmentEXT = NULL;
+
PFNGLCLIENTWAITSYNCPROC __glewClientWaitSync = NULL;
PFNGLDELETESYNCPROC __glewDeleteSync = NULL;
PFNGLFENCESYNCPROC __glewFenceSync = NULL;
@@ -1020,6 +1116,9 @@ PFNGLPATCHPARAMETERIPROC __glewPatchParameteri = NULL;
PFNGLTEXBUFFERARBPROC __glewTexBufferARB = NULL;
+PFNGLTEXBUFFERRANGEPROC __glewTexBufferRange = NULL;
+PFNGLTEXTUREBUFFERRANGEEXTPROC __glewTextureBufferRangeEXT = NULL;
+
PFNGLCOMPRESSEDTEXIMAGE1DARBPROC __glewCompressedTexImage1DARB = NULL;
PFNGLCOMPRESSEDTEXIMAGE2DARBPROC __glewCompressedTexImage2DARB = NULL;
PFNGLCOMPRESSEDTEXIMAGE3DARBPROC __glewCompressedTexImage3DARB = NULL;
@@ -1040,6 +1139,13 @@ PFNGLTEXTURESTORAGE1DEXTPROC __glewTextureStorage1DEXT = NULL;
PFNGLTEXTURESTORAGE2DEXTPROC __glewTextureStorage2DEXT = NULL;
PFNGLTEXTURESTORAGE3DEXTPROC __glewTextureStorage3DEXT = NULL;
+PFNGLTEXSTORAGE2DMULTISAMPLEPROC __glewTexStorage2DMultisample = NULL;
+PFNGLTEXSTORAGE3DMULTISAMPLEPROC __glewTexStorage3DMultisample = NULL;
+PFNGLTEXTURESTORAGE2DMULTISAMPLEEXTPROC __glewTextureStorage2DMultisampleEXT = NULL;
+PFNGLTEXTURESTORAGE3DMULTISAMPLEEXTPROC __glewTextureStorage3DMultisampleEXT = NULL;
+
+PFNGLTEXTUREVIEWPROC __glewTextureView = NULL;
+
PFNGLGETQUERYOBJECTI64VPROC __glewGetQueryObjecti64v = NULL;
PFNGLGETQUERYOBJECTUI64VPROC __glewGetQueryObjectui64v = NULL;
PFNGLQUERYCOUNTERPROC __glewQueryCounter = NULL;
@@ -1092,6 +1198,13 @@ PFNGLVERTEXATTRIBL4DPROC __glewVertexAttribL4d = NULL;
PFNGLVERTEXATTRIBL4DVPROC __glewVertexAttribL4dv = NULL;
PFNGLVERTEXATTRIBLPOINTERPROC __glewVertexAttribLPointer = NULL;
+PFNGLBINDVERTEXBUFFERPROC __glewBindVertexBuffer = NULL;
+PFNGLVERTEXATTRIBBINDINGPROC __glewVertexAttribBinding = NULL;
+PFNGLVERTEXATTRIBFORMATPROC __glewVertexAttribFormat = NULL;
+PFNGLVERTEXATTRIBIFORMATPROC __glewVertexAttribIFormat = NULL;
+PFNGLVERTEXATTRIBLFORMATPROC __glewVertexAttribLFormat = NULL;
+PFNGLVERTEXBINDINGDIVISORPROC __glewVertexBindingDivisor = NULL;
+
PFNGLVERTEXBLENDARBPROC __glewVertexBlendARB = NULL;
PFNGLWEIGHTPOINTERARBPROC __glewWeightPointerARB = NULL;
PFNGLWEIGHTBVARBPROC __glewWeightbvARB = NULL;
@@ -1314,6 +1427,14 @@ PFNGLNORMALSTREAM3SATIPROC __glewNormalStream3sATI = NULL;
PFNGLNORMALSTREAM3SVATIPROC __glewNormalStream3svATI = NULL;
PFNGLVERTEXBLENDENVFATIPROC __glewVertexBlendEnvfATI = NULL;
PFNGLVERTEXBLENDENVIATIPROC __glewVertexBlendEnviATI = NULL;
+PFNGLVERTEXSTREAM1DATIPROC __glewVertexStream1dATI = NULL;
+PFNGLVERTEXSTREAM1DVATIPROC __glewVertexStream1dvATI = NULL;
+PFNGLVERTEXSTREAM1FATIPROC __glewVertexStream1fATI = NULL;
+PFNGLVERTEXSTREAM1FVATIPROC __glewVertexStream1fvATI = NULL;
+PFNGLVERTEXSTREAM1IATIPROC __glewVertexStream1iATI = NULL;
+PFNGLVERTEXSTREAM1IVATIPROC __glewVertexStream1ivATI = NULL;
+PFNGLVERTEXSTREAM1SATIPROC __glewVertexStream1sATI = NULL;
+PFNGLVERTEXSTREAM1SVATIPROC __glewVertexStream1svATI = NULL;
PFNGLVERTEXSTREAM2DATIPROC __glewVertexStream2dATI = NULL;
PFNGLVERTEXSTREAM2DVATIPROC __glewVertexStream2dvATI = NULL;
PFNGLVERTEXSTREAM2FATIPROC __glewVertexStream2fATI = NULL;
@@ -1383,6 +1504,10 @@ PFNGLCOPYTEXSUBIMAGE3DEXTPROC __glewCopyTexSubImage3DEXT = NULL;
PFNGLCULLPARAMETERDVEXTPROC __glewCullParameterdvEXT = NULL;
PFNGLCULLPARAMETERFVEXTPROC __glewCullParameterfvEXT = NULL;
+PFNGLINSERTEVENTMARKEREXTPROC __glewInsertEventMarkerEXT = NULL;
+PFNGLPOPGROUPMARKEREXTPROC __glewPopGroupMarkerEXT = NULL;
+PFNGLPUSHGROUPMARKEREXTPROC __glewPushGroupMarkerEXT = NULL;
+
PFNGLDEPTHBOUNDSEXTPROC __glewDepthBoundsEXT = NULL;
PFNGLBINDMULTITEXTUREEXTPROC __glewBindMultiTextureEXT = NULL;
@@ -1904,6 +2029,10 @@ PFNGLSECONDARYCOLORPOINTERLISTIBMPROC __glewSecondaryColorPointerListIBM = NULL;
PFNGLTEXCOORDPOINTERLISTIBMPROC __glewTexCoordPointerListIBM = NULL;
PFNGLVERTEXPOINTERLISTIBMPROC __glewVertexPointerListIBM = NULL;
+PFNGLMAPTEXTURE2DINTELPROC __glewMapTexture2DINTEL = NULL;
+PFNGLSYNCTEXTUREINTELPROC __glewSyncTextureINTEL = NULL;
+PFNGLUNMAPTEXTURE2DINTELPROC __glewUnmapTexture2DINTEL = NULL;
+
PFNGLCOLORPOINTERVINTELPROC __glewColorPointervINTEL = NULL;
PFNGLNORMALPOINTERVINTELPROC __glewNormalPointervINTEL = NULL;
PFNGLTEXCOORDPOINTERVINTELPROC __glewTexCoordPointervINTEL = NULL;
@@ -1912,6 +2041,17 @@ PFNGLVERTEXPOINTERVINTELPROC __glewVertexPointervINTEL = NULL;
PFNGLTEXSCISSORFUNCINTELPROC __glewTexScissorFuncINTEL = NULL;
PFNGLTEXSCISSORINTELPROC __glewTexScissorINTEL = NULL;
+PFNGLDEBUGMESSAGECALLBACKPROC __glewDebugMessageCallback = NULL;
+PFNGLDEBUGMESSAGECONTROLPROC __glewDebugMessageControl = NULL;
+PFNGLDEBUGMESSAGEINSERTPROC __glewDebugMessageInsert = NULL;
+PFNGLGETDEBUGMESSAGELOGPROC __glewGetDebugMessageLog = NULL;
+PFNGLGETOBJECTLABELPROC __glewGetObjectLabel = NULL;
+PFNGLGETOBJECTPTRLABELPROC __glewGetObjectPtrLabel = NULL;
+PFNGLOBJECTLABELPROC __glewObjectLabel = NULL;
+PFNGLOBJECTPTRLABELPROC __glewObjectPtrLabel = NULL;
+PFNGLPOPDEBUGGROUPPROC __glewPopDebugGroup = NULL;
+PFNGLPUSHDEBUGGROUPPROC __glewPushDebugGroup = NULL;
+
PFNGLBUFFERREGIONENABLEDPROC __glewBufferRegionEnabled = NULL;
PFNGLDELETEBUFFERREGIONPROC __glewDeleteBufferRegion = NULL;
PFNGLDRAWBUFFERREGIONPROC __glewDrawBufferRegion = NULL;
@@ -1945,6 +2085,29 @@ PFNGLWINDOWPOS4IVMESAPROC __glewWindowPos4ivMESA = NULL;
PFNGLWINDOWPOS4SMESAPROC __glewWindowPos4sMESA = NULL;
PFNGLWINDOWPOS4SVMESAPROC __glewWindowPos4svMESA = NULL;
+PFNGLBEGINCONDITIONALRENDERNVXPROC __glewBeginConditionalRenderNVX = NULL;
+PFNGLENDCONDITIONALRENDERNVXPROC __glewEndConditionalRenderNVX = NULL;
+
+PFNGLMULTIDRAWARRAYSINDIRECTBINDLESSNVPROC __glewMultiDrawArraysIndirectBindlessNV = NULL;
+PFNGLMULTIDRAWELEMENTSINDIRECTBINDLESSNVPROC __glewMultiDrawElementsIndirectBindlessNV = NULL;
+
+PFNGLGETIMAGEHANDLENVPROC __glewGetImageHandleNV = NULL;
+PFNGLGETTEXTUREHANDLENVPROC __glewGetTextureHandleNV = NULL;
+PFNGLGETTEXTURESAMPLERHANDLENVPROC __glewGetTextureSamplerHandleNV = NULL;
+PFNGLISIMAGEHANDLERESIDENTNVPROC __glewIsImageHandleResidentNV = NULL;
+PFNGLISTEXTUREHANDLERESIDENTNVPROC __glewIsTextureHandleResidentNV = NULL;
+PFNGLMAKEIMAGEHANDLENONRESIDENTNVPROC __glewMakeImageHandleNonResidentNV = NULL;
+PFNGLMAKEIMAGEHANDLERESIDENTNVPROC __glewMakeImageHandleResidentNV = NULL;
+PFNGLMAKETEXTUREHANDLENONRESIDENTNVPROC __glewMakeTextureHandleNonResidentNV = NULL;
+PFNGLMAKETEXTUREHANDLERESIDENTNVPROC __glewMakeTextureHandleResidentNV = NULL;
+PFNGLPROGRAMUNIFORMHANDLEUI64NVPROC __glewProgramUniformHandleui64NV = NULL;
+PFNGLPROGRAMUNIFORMHANDLEUI64VNVPROC __glewProgramUniformHandleui64vNV = NULL;
+PFNGLUNIFORMHANDLEUI64NVPROC __glewUniformHandleui64NV = NULL;
+PFNGLUNIFORMHANDLEUI64VNVPROC __glewUniformHandleui64vNV = NULL;
+
+PFNGLBLENDBARRIERNVPROC __glewBlendBarrierNV = NULL;
+PFNGLBLENDPARAMETERINVPROC __glewBlendParameteriNV = NULL;
+
PFNGLBEGINCONDITIONALRENDERNVPROC __glewBeginConditionalRenderNV = NULL;
PFNGLENDCONDITIONALRENDERNVPROC __glewEndConditionalRenderNV = NULL;
@@ -1954,6 +2117,8 @@ PFNGLCLEARDEPTHDNVPROC __glewClearDepthdNV = NULL;
PFNGLDEPTHBOUNDSDNVPROC __glewDepthBoundsdNV = NULL;
PFNGLDEPTHRANGEDNVPROC __glewDepthRangedNV = NULL;
+PFNGLDRAWTEXTURENVPROC __glewDrawTextureNV = NULL;
+
PFNGLEVALMAPSNVPROC __glewEvalMapsNV = NULL;
PFNGLGETMAPATTRIBPARAMETERFVNVPROC __glewGetMapAttribParameterfvNV = NULL;
PFNGLGETMAPATTRIBPARAMETERIVNVPROC __glewGetMapAttribParameterivNV = NULL;
@@ -2352,6 +2517,59 @@ PFNGLFRUSTUMFOESPROC __glewFrustumfOES = NULL;
PFNGLGETCLIPPLANEFOESPROC __glewGetClipPlanefOES = NULL;
PFNGLORTHOFOESPROC __glewOrthofOES = NULL;
+PFNGLALPHAFUNCXPROC __glewAlphaFuncx = NULL;
+PFNGLCLEARCOLORXPROC __glewClearColorx = NULL;
+PFNGLCLEARDEPTHXPROC __glewClearDepthx = NULL;
+PFNGLCOLOR4XPROC __glewColor4x = NULL;
+PFNGLDEPTHRANGEXPROC __glewDepthRangex = NULL;
+PFNGLFOGXPROC __glewFogx = NULL;
+PFNGLFOGXVPROC __glewFogxv = NULL;
+PFNGLFRUSTUMFPROC __glewFrustumf = NULL;
+PFNGLFRUSTUMXPROC __glewFrustumx = NULL;
+PFNGLLIGHTMODELXPROC __glewLightModelx = NULL;
+PFNGLLIGHTMODELXVPROC __glewLightModelxv = NULL;
+PFNGLLIGHTXPROC __glewLightx = NULL;
+PFNGLLIGHTXVPROC __glewLightxv = NULL;
+PFNGLLINEWIDTHXPROC __glewLineWidthx = NULL;
+PFNGLLOADMATRIXXPROC __glewLoadMatrixx = NULL;
+PFNGLMATERIALXPROC __glewMaterialx = NULL;
+PFNGLMATERIALXVPROC __glewMaterialxv = NULL;
+PFNGLMULTMATRIXXPROC __glewMultMatrixx = NULL;
+PFNGLMULTITEXCOORD4XPROC __glewMultiTexCoord4x = NULL;
+PFNGLNORMAL3XPROC __glewNormal3x = NULL;
+PFNGLORTHOFPROC __glewOrthof = NULL;
+PFNGLORTHOXPROC __glewOrthox = NULL;
+PFNGLPOINTSIZEXPROC __glewPointSizex = NULL;
+PFNGLPOLYGONOFFSETXPROC __glewPolygonOffsetx = NULL;
+PFNGLROTATEXPROC __glewRotatex = NULL;
+PFNGLSAMPLECOVERAGEXPROC __glewSampleCoveragex = NULL;
+PFNGLSCALEXPROC __glewScalex = NULL;
+PFNGLTEXENVXPROC __glewTexEnvx = NULL;
+PFNGLTEXENVXVPROC __glewTexEnvxv = NULL;
+PFNGLTEXPARAMETERXPROC __glewTexParameterx = NULL;
+PFNGLTRANSLATEXPROC __glewTranslatex = NULL;
+
+PFNGLCLIPPLANEFPROC __glewClipPlanef = NULL;
+PFNGLCLIPPLANEXPROC __glewClipPlanex = NULL;
+PFNGLGETCLIPPLANEFPROC __glewGetClipPlanef = NULL;
+PFNGLGETCLIPPLANEXPROC __glewGetClipPlanex = NULL;
+PFNGLGETFIXEDVPROC __glewGetFixedv = NULL;
+PFNGLGETLIGHTXVPROC __glewGetLightxv = NULL;
+PFNGLGETMATERIALXVPROC __glewGetMaterialxv = NULL;
+PFNGLGETTEXENVXVPROC __glewGetTexEnvxv = NULL;
+PFNGLGETTEXPARAMETERXVPROC __glewGetTexParameterxv = NULL;
+PFNGLPOINTPARAMETERXPROC __glewPointParameterx = NULL;
+PFNGLPOINTPARAMETERXVPROC __glewPointParameterxv = NULL;
+PFNGLPOINTSIZEPOINTEROESPROC __glewPointSizePointerOES = NULL;
+PFNGLTEXPARAMETERXVPROC __glewTexParameterxv = NULL;
+
+PFNGLERRORSTRINGREGALPROC __glewErrorStringREGAL = NULL;
+
+PFNGLGETEXTENSIONREGALPROC __glewGetExtensionREGAL = NULL;
+PFNGLISSUPPORTEDREGALPROC __glewIsSupportedREGAL = NULL;
+
+PFNGLLOGMESSAGECALLBACKREGALPROC __glewLogMessageCallbackREGAL = NULL;
+
PFNGLDETAILTEXFUNCSGISPROC __glewDetailTexFuncSGIS = NULL;
PFNGLGETDETAILTEXFUNCSGISPROC __glewGetDetailTexFuncSGIS = NULL;
@@ -2503,6 +2721,8 @@ GLboolean __GLEW_VERSION_3_3 = GL_FALSE;
GLboolean __GLEW_VERSION_4_0 = GL_FALSE;
GLboolean __GLEW_VERSION_4_1 = GL_FALSE;
GLboolean __GLEW_VERSION_4_2 = GL_FALSE;
+GLboolean __GLEW_VERSION_4_3 = GL_FALSE;
+GLboolean __GLEW_VERSION_4_4 = GL_FALSE;
GLboolean __GLEW_3DFX_multisample = GL_FALSE;
GLboolean __GLEW_3DFX_tbuffer = GL_FALSE;
GLboolean __GLEW_3DFX_texture_compression_FXT1 = GL_FALSE;
@@ -2511,15 +2731,35 @@ GLboolean __GLEW_AMD_conservative_depth = GL_FALSE;
GLboolean __GLEW_AMD_debug_output = GL_FALSE;
GLboolean __GLEW_AMD_depth_clamp_separate = GL_FALSE;
GLboolean __GLEW_AMD_draw_buffers_blend = GL_FALSE;
+GLboolean __GLEW_AMD_interleaved_elements = GL_FALSE;
GLboolean __GLEW_AMD_multi_draw_indirect = GL_FALSE;
GLboolean __GLEW_AMD_name_gen_delete = GL_FALSE;
GLboolean __GLEW_AMD_performance_monitor = GL_FALSE;
+GLboolean __GLEW_AMD_pinned_memory = GL_FALSE;
+GLboolean __GLEW_AMD_query_buffer_object = GL_FALSE;
GLboolean __GLEW_AMD_sample_positions = GL_FALSE;
GLboolean __GLEW_AMD_seamless_cubemap_per_texture = GL_FALSE;
GLboolean __GLEW_AMD_shader_stencil_export = GL_FALSE;
+GLboolean __GLEW_AMD_shader_trinary_minmax = GL_FALSE;
+GLboolean __GLEW_AMD_sparse_texture = GL_FALSE;
+GLboolean __GLEW_AMD_stencil_operation_extended = GL_FALSE;
GLboolean __GLEW_AMD_texture_texture4 = GL_FALSE;
GLboolean __GLEW_AMD_transform_feedback3_lines_triangles = GL_FALSE;
+GLboolean __GLEW_AMD_vertex_shader_layer = GL_FALSE;
GLboolean __GLEW_AMD_vertex_shader_tessellator = GL_FALSE;
+GLboolean __GLEW_AMD_vertex_shader_viewport_index = GL_FALSE;
+GLboolean __GLEW_ANGLE_depth_texture = GL_FALSE;
+GLboolean __GLEW_ANGLE_framebuffer_blit = GL_FALSE;
+GLboolean __GLEW_ANGLE_framebuffer_multisample = GL_FALSE;
+GLboolean __GLEW_ANGLE_instanced_arrays = GL_FALSE;
+GLboolean __GLEW_ANGLE_pack_reverse_row_order = GL_FALSE;
+GLboolean __GLEW_ANGLE_program_binary = GL_FALSE;
+GLboolean __GLEW_ANGLE_texture_compression_dxt1 = GL_FALSE;
+GLboolean __GLEW_ANGLE_texture_compression_dxt3 = GL_FALSE;
+GLboolean __GLEW_ANGLE_texture_compression_dxt5 = GL_FALSE;
+GLboolean __GLEW_ANGLE_texture_usage = GL_FALSE;
+GLboolean __GLEW_ANGLE_timer_query = GL_FALSE;
+GLboolean __GLEW_ANGLE_translated_shader_source = GL_FALSE;
GLboolean __GLEW_APPLE_aux_depth_stencil = GL_FALSE;
GLboolean __GLEW_APPLE_client_storage = GL_FALSE;
GLboolean __GLEW_APPLE_element_array = GL_FALSE;
@@ -2538,14 +2778,23 @@ GLboolean __GLEW_APPLE_vertex_array_range = GL_FALSE;
GLboolean __GLEW_APPLE_vertex_program_evaluators = GL_FALSE;
GLboolean __GLEW_APPLE_ycbcr_422 = GL_FALSE;
GLboolean __GLEW_ARB_ES2_compatibility = GL_FALSE;
+GLboolean __GLEW_ARB_ES3_compatibility = GL_FALSE;
+GLboolean __GLEW_ARB_arrays_of_arrays = GL_FALSE;
GLboolean __GLEW_ARB_base_instance = GL_FALSE;
+GLboolean __GLEW_ARB_bindless_texture = GL_FALSE;
GLboolean __GLEW_ARB_blend_func_extended = GL_FALSE;
+GLboolean __GLEW_ARB_buffer_storage = GL_FALSE;
GLboolean __GLEW_ARB_cl_event = GL_FALSE;
+GLboolean __GLEW_ARB_clear_buffer_object = GL_FALSE;
+GLboolean __GLEW_ARB_clear_texture = GL_FALSE;
GLboolean __GLEW_ARB_color_buffer_float = GL_FALSE;
GLboolean __GLEW_ARB_compatibility = GL_FALSE;
GLboolean __GLEW_ARB_compressed_texture_pixel_storage = GL_FALSE;
+GLboolean __GLEW_ARB_compute_shader = GL_FALSE;
+GLboolean __GLEW_ARB_compute_variable_group_size = GL_FALSE;
GLboolean __GLEW_ARB_conservative_depth = GL_FALSE;
GLboolean __GLEW_ARB_copy_buffer = GL_FALSE;
+GLboolean __GLEW_ARB_copy_image = GL_FALSE;
GLboolean __GLEW_ARB_debug_output = GL_FALSE;
GLboolean __GLEW_ARB_depth_buffer_float = GL_FALSE;
GLboolean __GLEW_ARB_depth_clamp = GL_FALSE;
@@ -2555,11 +2804,15 @@ GLboolean __GLEW_ARB_draw_buffers_blend = GL_FALSE;
GLboolean __GLEW_ARB_draw_elements_base_vertex = GL_FALSE;
GLboolean __GLEW_ARB_draw_indirect = GL_FALSE;
GLboolean __GLEW_ARB_draw_instanced = GL_FALSE;
+GLboolean __GLEW_ARB_enhanced_layouts = GL_FALSE;
GLboolean __GLEW_ARB_explicit_attrib_location = GL_FALSE;
+GLboolean __GLEW_ARB_explicit_uniform_location = GL_FALSE;
GLboolean __GLEW_ARB_fragment_coord_conventions = GL_FALSE;
+GLboolean __GLEW_ARB_fragment_layer_viewport = GL_FALSE;
GLboolean __GLEW_ARB_fragment_program = GL_FALSE;
GLboolean __GLEW_ARB_fragment_program_shadow = GL_FALSE;
GLboolean __GLEW_ARB_fragment_shader = GL_FALSE;
+GLboolean __GLEW_ARB_framebuffer_no_attachments = GL_FALSE;
GLboolean __GLEW_ARB_framebuffer_object = GL_FALSE;
GLboolean __GLEW_ARB_framebuffer_sRGB = GL_FALSE;
GLboolean __GLEW_ARB_geometry_shader4 = GL_FALSE;
@@ -2569,11 +2822,16 @@ GLboolean __GLEW_ARB_gpu_shader_fp64 = GL_FALSE;
GLboolean __GLEW_ARB_half_float_pixel = GL_FALSE;
GLboolean __GLEW_ARB_half_float_vertex = GL_FALSE;
GLboolean __GLEW_ARB_imaging = GL_FALSE;
+GLboolean __GLEW_ARB_indirect_parameters = GL_FALSE;
GLboolean __GLEW_ARB_instanced_arrays = GL_FALSE;
GLboolean __GLEW_ARB_internalformat_query = GL_FALSE;
+GLboolean __GLEW_ARB_internalformat_query2 = GL_FALSE;
+GLboolean __GLEW_ARB_invalidate_subdata = GL_FALSE;
GLboolean __GLEW_ARB_map_buffer_alignment = GL_FALSE;
GLboolean __GLEW_ARB_map_buffer_range = GL_FALSE;
GLboolean __GLEW_ARB_matrix_palette = GL_FALSE;
+GLboolean __GLEW_ARB_multi_bind = GL_FALSE;
+GLboolean __GLEW_ARB_multi_draw_indirect = GL_FALSE;
GLboolean __GLEW_ARB_multisample = GL_FALSE;
GLboolean __GLEW_ARB_multitexture = GL_FALSE;
GLboolean __GLEW_ARB_occlusion_query = GL_FALSE;
@@ -2581,18 +2839,28 @@ GLboolean __GLEW_ARB_occlusion_query2 = GL_FALSE;
GLboolean __GLEW_ARB_pixel_buffer_object = GL_FALSE;
GLboolean __GLEW_ARB_point_parameters = GL_FALSE;
GLboolean __GLEW_ARB_point_sprite = GL_FALSE;
+GLboolean __GLEW_ARB_program_interface_query = GL_FALSE;
GLboolean __GLEW_ARB_provoking_vertex = GL_FALSE;
+GLboolean __GLEW_ARB_query_buffer_object = GL_FALSE;
+GLboolean __GLEW_ARB_robust_buffer_access_behavior = GL_FALSE;
GLboolean __GLEW_ARB_robustness = GL_FALSE;
+GLboolean __GLEW_ARB_robustness_application_isolation = GL_FALSE;
+GLboolean __GLEW_ARB_robustness_share_group_isolation = GL_FALSE;
GLboolean __GLEW_ARB_sample_shading = GL_FALSE;
GLboolean __GLEW_ARB_sampler_objects = GL_FALSE;
GLboolean __GLEW_ARB_seamless_cube_map = GL_FALSE;
+GLboolean __GLEW_ARB_seamless_cubemap_per_texture = GL_FALSE;
GLboolean __GLEW_ARB_separate_shader_objects = GL_FALSE;
GLboolean __GLEW_ARB_shader_atomic_counters = GL_FALSE;
GLboolean __GLEW_ARB_shader_bit_encoding = GL_FALSE;
+GLboolean __GLEW_ARB_shader_draw_parameters = GL_FALSE;
+GLboolean __GLEW_ARB_shader_group_vote = GL_FALSE;
GLboolean __GLEW_ARB_shader_image_load_store = GL_FALSE;
+GLboolean __GLEW_ARB_shader_image_size = GL_FALSE;
GLboolean __GLEW_ARB_shader_objects = GL_FALSE;
GLboolean __GLEW_ARB_shader_precision = GL_FALSE;
GLboolean __GLEW_ARB_shader_stencil_export = GL_FALSE;
+GLboolean __GLEW_ARB_shader_storage_buffer_object = GL_FALSE;
GLboolean __GLEW_ARB_shader_subroutine = GL_FALSE;
GLboolean __GLEW_ARB_shader_texture_lod = GL_FALSE;
GLboolean __GLEW_ARB_shading_language_100 = GL_FALSE;
@@ -2601,11 +2869,14 @@ GLboolean __GLEW_ARB_shading_language_include = GL_FALSE;
GLboolean __GLEW_ARB_shading_language_packing = GL_FALSE;
GLboolean __GLEW_ARB_shadow = GL_FALSE;
GLboolean __GLEW_ARB_shadow_ambient = GL_FALSE;
+GLboolean __GLEW_ARB_sparse_texture = GL_FALSE;
+GLboolean __GLEW_ARB_stencil_texturing = GL_FALSE;
GLboolean __GLEW_ARB_sync = GL_FALSE;
GLboolean __GLEW_ARB_tessellation_shader = GL_FALSE;
GLboolean __GLEW_ARB_texture_border_clamp = GL_FALSE;
GLboolean __GLEW_ARB_texture_buffer_object = GL_FALSE;
GLboolean __GLEW_ARB_texture_buffer_object_rgb32 = GL_FALSE;
+GLboolean __GLEW_ARB_texture_buffer_range = GL_FALSE;
GLboolean __GLEW_ARB_texture_compression = GL_FALSE;
GLboolean __GLEW_ARB_texture_compression_bptc = GL_FALSE;
GLboolean __GLEW_ARB_texture_compression_rgtc = GL_FALSE;
@@ -2617,15 +2888,20 @@ GLboolean __GLEW_ARB_texture_env_crossbar = GL_FALSE;
GLboolean __GLEW_ARB_texture_env_dot3 = GL_FALSE;
GLboolean __GLEW_ARB_texture_float = GL_FALSE;
GLboolean __GLEW_ARB_texture_gather = GL_FALSE;
+GLboolean __GLEW_ARB_texture_mirror_clamp_to_edge = GL_FALSE;
GLboolean __GLEW_ARB_texture_mirrored_repeat = GL_FALSE;
GLboolean __GLEW_ARB_texture_multisample = GL_FALSE;
GLboolean __GLEW_ARB_texture_non_power_of_two = GL_FALSE;
+GLboolean __GLEW_ARB_texture_query_levels = GL_FALSE;
GLboolean __GLEW_ARB_texture_query_lod = GL_FALSE;
GLboolean __GLEW_ARB_texture_rectangle = GL_FALSE;
GLboolean __GLEW_ARB_texture_rg = GL_FALSE;
GLboolean __GLEW_ARB_texture_rgb10_a2ui = GL_FALSE;
+GLboolean __GLEW_ARB_texture_stencil8 = GL_FALSE;
GLboolean __GLEW_ARB_texture_storage = GL_FALSE;
+GLboolean __GLEW_ARB_texture_storage_multisample = GL_FALSE;
GLboolean __GLEW_ARB_texture_swizzle = GL_FALSE;
+GLboolean __GLEW_ARB_texture_view = GL_FALSE;
GLboolean __GLEW_ARB_timer_query = GL_FALSE;
GLboolean __GLEW_ARB_transform_feedback2 = GL_FALSE;
GLboolean __GLEW_ARB_transform_feedback3 = GL_FALSE;
@@ -2635,10 +2911,12 @@ GLboolean __GLEW_ARB_uniform_buffer_object = GL_FALSE;
GLboolean __GLEW_ARB_vertex_array_bgra = GL_FALSE;
GLboolean __GLEW_ARB_vertex_array_object = GL_FALSE;
GLboolean __GLEW_ARB_vertex_attrib_64bit = GL_FALSE;
+GLboolean __GLEW_ARB_vertex_attrib_binding = GL_FALSE;
GLboolean __GLEW_ARB_vertex_blend = GL_FALSE;
GLboolean __GLEW_ARB_vertex_buffer_object = GL_FALSE;
GLboolean __GLEW_ARB_vertex_program = GL_FALSE;
GLboolean __GLEW_ARB_vertex_shader = GL_FALSE;
+GLboolean __GLEW_ARB_vertex_type_10f_11f_11f_rev = GL_FALSE;
GLboolean __GLEW_ARB_vertex_type_2_10_10_10_rev = GL_FALSE;
GLboolean __GLEW_ARB_viewport_array = GL_FALSE;
GLboolean __GLEW_ARB_window_pos = GL_FALSE;
@@ -2682,6 +2960,7 @@ GLboolean __GLEW_EXT_convolution = GL_FALSE;
GLboolean __GLEW_EXT_coordinate_frame = GL_FALSE;
GLboolean __GLEW_EXT_copy_texture = GL_FALSE;
GLboolean __GLEW_EXT_cull_vertex = GL_FALSE;
+GLboolean __GLEW_EXT_debug_marker = GL_FALSE;
GLboolean __GLEW_EXT_depth_bounds_test = GL_FALSE;
GLboolean __GLEW_EXT_direct_state_access = GL_FALSE;
GLboolean __GLEW_EXT_draw_buffers2 = GL_FALSE;
@@ -2776,22 +3055,33 @@ GLboolean __GLEW_IBM_texture_mirrored_repeat = GL_FALSE;
GLboolean __GLEW_IBM_vertex_array_lists = GL_FALSE;
GLboolean __GLEW_INGR_color_clamp = GL_FALSE;
GLboolean __GLEW_INGR_interlace_read = GL_FALSE;
+GLboolean __GLEW_INTEL_map_texture = GL_FALSE;
GLboolean __GLEW_INTEL_parallel_arrays = GL_FALSE;
GLboolean __GLEW_INTEL_texture_scissor = GL_FALSE;
+GLboolean __GLEW_KHR_debug = GL_FALSE;
+GLboolean __GLEW_KHR_texture_compression_astc_ldr = GL_FALSE;
GLboolean __GLEW_KTX_buffer_region = GL_FALSE;
GLboolean __GLEW_MESAX_texture_stack = GL_FALSE;
GLboolean __GLEW_MESA_pack_invert = GL_FALSE;
GLboolean __GLEW_MESA_resize_buffers = GL_FALSE;
GLboolean __GLEW_MESA_window_pos = GL_FALSE;
GLboolean __GLEW_MESA_ycbcr_texture = GL_FALSE;
+GLboolean __GLEW_NVX_conditional_render = GL_FALSE;
GLboolean __GLEW_NVX_gpu_memory_info = GL_FALSE;
+GLboolean __GLEW_NV_bindless_multi_draw_indirect = GL_FALSE;
+GLboolean __GLEW_NV_bindless_texture = GL_FALSE;
+GLboolean __GLEW_NV_blend_equation_advanced = GL_FALSE;
+GLboolean __GLEW_NV_blend_equation_advanced_coherent = GL_FALSE;
GLboolean __GLEW_NV_blend_square = GL_FALSE;
+GLboolean __GLEW_NV_compute_program5 = GL_FALSE;
GLboolean __GLEW_NV_conditional_render = GL_FALSE;
GLboolean __GLEW_NV_copy_depth_to_color = GL_FALSE;
GLboolean __GLEW_NV_copy_image = GL_FALSE;
+GLboolean __GLEW_NV_deep_texture3D = GL_FALSE;
GLboolean __GLEW_NV_depth_buffer_float = GL_FALSE;
GLboolean __GLEW_NV_depth_clamp = GL_FALSE;
GLboolean __GLEW_NV_depth_range_unclamped = GL_FALSE;
+GLboolean __GLEW_NV_draw_texture = GL_FALSE;
GLboolean __GLEW_NV_evaluators = GL_FALSE;
GLboolean __GLEW_NV_explicit_multisample = GL_FALSE;
GLboolean __GLEW_NV_fence = GL_FALSE;
@@ -2806,6 +3096,7 @@ GLboolean __GLEW_NV_geometry_program4 = GL_FALSE;
GLboolean __GLEW_NV_geometry_shader4 = GL_FALSE;
GLboolean __GLEW_NV_gpu_program4 = GL_FALSE;
GLboolean __GLEW_NV_gpu_program5 = GL_FALSE;
+GLboolean __GLEW_NV_gpu_program5_mem_extended = GL_FALSE;
GLboolean __GLEW_NV_gpu_program_fp64 = GL_FALSE;
GLboolean __GLEW_NV_gpu_shader5 = GL_FALSE;
GLboolean __GLEW_NV_half_float = GL_FALSE;
@@ -2823,7 +3114,10 @@ GLboolean __GLEW_NV_present_video = GL_FALSE;
GLboolean __GLEW_NV_primitive_restart = GL_FALSE;
GLboolean __GLEW_NV_register_combiners = GL_FALSE;
GLboolean __GLEW_NV_register_combiners2 = GL_FALSE;
+GLboolean __GLEW_NV_shader_atomic_counters = GL_FALSE;
+GLboolean __GLEW_NV_shader_atomic_float = GL_FALSE;
GLboolean __GLEW_NV_shader_buffer_load = GL_FALSE;
+GLboolean __GLEW_NV_shader_storage_buffer_object = GL_FALSE;
GLboolean __GLEW_NV_tessellation_program5 = GL_FALSE;
GLboolean __GLEW_NV_texgen_emboss = GL_FALSE;
GLboolean __GLEW_NV_texgen_reflection = GL_FALSE;
@@ -2859,6 +3153,12 @@ GLboolean __GLEW_OML_resample = GL_FALSE;
GLboolean __GLEW_OML_subsample = GL_FALSE;
GLboolean __GLEW_PGI_misc_hints = GL_FALSE;
GLboolean __GLEW_PGI_vertex_hints = GL_FALSE;
+GLboolean __GLEW_REGAL_ES1_0_compatibility = GL_FALSE;
+GLboolean __GLEW_REGAL_ES1_1_compatibility = GL_FALSE;
+GLboolean __GLEW_REGAL_enable = GL_FALSE;
+GLboolean __GLEW_REGAL_error_string = GL_FALSE;
+GLboolean __GLEW_REGAL_extension_query = GL_FALSE;
+GLboolean __GLEW_REGAL_log = GL_FALSE;
GLboolean __GLEW_REND_screen_coordinates = GL_FALSE;
GLboolean __GLEW_S3_s3tc = GL_FALSE;
GLboolean __GLEW_SGIS_color_range = GL_FALSE;
@@ -3351,6 +3651,14 @@ static GLboolean _glewInit_GL_VERSION_4_0 (GLEW_CONTEXT_ARG_DEF_INIT)
#endif /* GL_VERSION_4_2 */
+#ifdef GL_VERSION_4_3
+
+#endif /* GL_VERSION_4_3 */
+
+#ifdef GL_VERSION_4_4
+
+#endif /* GL_VERSION_4_4 */
+
#ifdef GL_3DFX_multisample
#endif /* GL_3DFX_multisample */
@@ -3416,6 +3724,19 @@ static GLboolean _glewInit_GL_AMD_draw_buffers_blend (GLEW_CONTEXT_ARG_DEF_INIT)
#endif /* GL_AMD_draw_buffers_blend */
+#ifdef GL_AMD_interleaved_elements
+
+static GLboolean _glewInit_GL_AMD_interleaved_elements (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glVertexAttribParameteriAMD = (PFNGLVERTEXATTRIBPARAMETERIAMDPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribParameteriAMD")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_AMD_interleaved_elements */
+
#ifdef GL_AMD_multi_draw_indirect
static GLboolean _glewInit_GL_AMD_multi_draw_indirect (GLEW_CONTEXT_ARG_DEF_INIT)
@@ -3468,6 +3789,14 @@ static GLboolean _glewInit_GL_AMD_performance_monitor (GLEW_CONTEXT_ARG_DEF_INIT
#endif /* GL_AMD_performance_monitor */
+#ifdef GL_AMD_pinned_memory
+
+#endif /* GL_AMD_pinned_memory */
+
+#ifdef GL_AMD_query_buffer_object
+
+#endif /* GL_AMD_query_buffer_object */
+
#ifdef GL_AMD_sample_positions
static GLboolean _glewInit_GL_AMD_sample_positions (GLEW_CONTEXT_ARG_DEF_INIT)
@@ -3489,6 +3818,37 @@ static GLboolean _glewInit_GL_AMD_sample_positions (GLEW_CONTEXT_ARG_DEF_INIT)
#endif /* GL_AMD_shader_stencil_export */
+#ifdef GL_AMD_shader_trinary_minmax
+
+#endif /* GL_AMD_shader_trinary_minmax */
+
+#ifdef GL_AMD_sparse_texture
+
+static GLboolean _glewInit_GL_AMD_sparse_texture (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glTexStorageSparseAMD = (PFNGLTEXSTORAGESPARSEAMDPROC)glewGetProcAddress((const GLubyte*)"glTexStorageSparseAMD")) == NULL) || r;
+ r = ((glTextureStorageSparseAMD = (PFNGLTEXTURESTORAGESPARSEAMDPROC)glewGetProcAddress((const GLubyte*)"glTextureStorageSparseAMD")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_AMD_sparse_texture */
+
+#ifdef GL_AMD_stencil_operation_extended
+
+static GLboolean _glewInit_GL_AMD_stencil_operation_extended (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glStencilOpValueAMD = (PFNGLSTENCILOPVALUEAMDPROC)glewGetProcAddress((const GLubyte*)"glStencilOpValueAMD")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_AMD_stencil_operation_extended */
+
#ifdef GL_AMD_texture_texture4
#endif /* GL_AMD_texture_texture4 */
@@ -3497,6 +3857,10 @@ static GLboolean _glewInit_GL_AMD_sample_positions (GLEW_CONTEXT_ARG_DEF_INIT)
#endif /* GL_AMD_transform_feedback3_lines_triangles */
+#ifdef GL_AMD_vertex_shader_layer
+
+#endif /* GL_AMD_vertex_shader_layer */
+
#ifdef GL_AMD_vertex_shader_tessellator
static GLboolean _glewInit_GL_AMD_vertex_shader_tessellator (GLEW_CONTEXT_ARG_DEF_INIT)
@@ -3511,6 +3875,115 @@ static GLboolean _glewInit_GL_AMD_vertex_shader_tessellator (GLEW_CONTEXT_ARG_DE
#endif /* GL_AMD_vertex_shader_tessellator */
+#ifdef GL_AMD_vertex_shader_viewport_index
+
+#endif /* GL_AMD_vertex_shader_viewport_index */
+
+#ifdef GL_ANGLE_depth_texture
+
+#endif /* GL_ANGLE_depth_texture */
+
+#ifdef GL_ANGLE_framebuffer_blit
+
+static GLboolean _glewInit_GL_ANGLE_framebuffer_blit (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glBlitFramebufferANGLE = (PFNGLBLITFRAMEBUFFERANGLEPROC)glewGetProcAddress((const GLubyte*)"glBlitFramebufferANGLE")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_ANGLE_framebuffer_blit */
+
+#ifdef GL_ANGLE_framebuffer_multisample
+
+static GLboolean _glewInit_GL_ANGLE_framebuffer_multisample (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glRenderbufferStorageMultisampleANGLE = (PFNGLRENDERBUFFERSTORAGEMULTISAMPLEANGLEPROC)glewGetProcAddress((const GLubyte*)"glRenderbufferStorageMultisampleANGLE")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_ANGLE_framebuffer_multisample */
+
+#ifdef GL_ANGLE_instanced_arrays
+
+static GLboolean _glewInit_GL_ANGLE_instanced_arrays (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glDrawArraysInstancedANGLE = (PFNGLDRAWARRAYSINSTANCEDANGLEPROC)glewGetProcAddress((const GLubyte*)"glDrawArraysInstancedANGLE")) == NULL) || r;
+ r = ((glDrawElementsInstancedANGLE = (PFNGLDRAWELEMENTSINSTANCEDANGLEPROC)glewGetProcAddress((const GLubyte*)"glDrawElementsInstancedANGLE")) == NULL) || r;
+ r = ((glVertexAttribDivisorANGLE = (PFNGLVERTEXATTRIBDIVISORANGLEPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribDivisorANGLE")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_ANGLE_instanced_arrays */
+
+#ifdef GL_ANGLE_pack_reverse_row_order
+
+#endif /* GL_ANGLE_pack_reverse_row_order */
+
+#ifdef GL_ANGLE_program_binary
+
+#endif /* GL_ANGLE_program_binary */
+
+#ifdef GL_ANGLE_texture_compression_dxt1
+
+#endif /* GL_ANGLE_texture_compression_dxt1 */
+
+#ifdef GL_ANGLE_texture_compression_dxt3
+
+#endif /* GL_ANGLE_texture_compression_dxt3 */
+
+#ifdef GL_ANGLE_texture_compression_dxt5
+
+#endif /* GL_ANGLE_texture_compression_dxt5 */
+
+#ifdef GL_ANGLE_texture_usage
+
+#endif /* GL_ANGLE_texture_usage */
+
+#ifdef GL_ANGLE_timer_query
+
+static GLboolean _glewInit_GL_ANGLE_timer_query (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glBeginQueryANGLE = (PFNGLBEGINQUERYANGLEPROC)glewGetProcAddress((const GLubyte*)"glBeginQueryANGLE")) == NULL) || r;
+ r = ((glDeleteQueriesANGLE = (PFNGLDELETEQUERIESANGLEPROC)glewGetProcAddress((const GLubyte*)"glDeleteQueriesANGLE")) == NULL) || r;
+ r = ((glEndQueryANGLE = (PFNGLENDQUERYANGLEPROC)glewGetProcAddress((const GLubyte*)"glEndQueryANGLE")) == NULL) || r;
+ r = ((glGenQueriesANGLE = (PFNGLGENQUERIESANGLEPROC)glewGetProcAddress((const GLubyte*)"glGenQueriesANGLE")) == NULL) || r;
+ r = ((glGetQueryObjecti64vANGLE = (PFNGLGETQUERYOBJECTI64VANGLEPROC)glewGetProcAddress((const GLubyte*)"glGetQueryObjecti64vANGLE")) == NULL) || r;
+ r = ((glGetQueryObjectivANGLE = (PFNGLGETQUERYOBJECTIVANGLEPROC)glewGetProcAddress((const GLubyte*)"glGetQueryObjectivANGLE")) == NULL) || r;
+ r = ((glGetQueryObjectui64vANGLE = (PFNGLGETQUERYOBJECTUI64VANGLEPROC)glewGetProcAddress((const GLubyte*)"glGetQueryObjectui64vANGLE")) == NULL) || r;
+ r = ((glGetQueryObjectuivANGLE = (PFNGLGETQUERYOBJECTUIVANGLEPROC)glewGetProcAddress((const GLubyte*)"glGetQueryObjectuivANGLE")) == NULL) || r;
+ r = ((glGetQueryivANGLE = (PFNGLGETQUERYIVANGLEPROC)glewGetProcAddress((const GLubyte*)"glGetQueryivANGLE")) == NULL) || r;
+ r = ((glIsQueryANGLE = (PFNGLISQUERYANGLEPROC)glewGetProcAddress((const GLubyte*)"glIsQueryANGLE")) == NULL) || r;
+ r = ((glQueryCounterANGLE = (PFNGLQUERYCOUNTERANGLEPROC)glewGetProcAddress((const GLubyte*)"glQueryCounterANGLE")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_ANGLE_timer_query */
+
+#ifdef GL_ANGLE_translated_shader_source
+
+static GLboolean _glewInit_GL_ANGLE_translated_shader_source (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glGetTranslatedShaderSourceANGLE = (PFNGLGETTRANSLATEDSHADERSOURCEANGLEPROC)glewGetProcAddress((const GLubyte*)"glGetTranslatedShaderSourceANGLE")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_ANGLE_translated_shader_source */
+
#ifdef GL_APPLE_aux_depth_stencil
#endif /* GL_APPLE_aux_depth_stencil */
@@ -3694,6 +4167,14 @@ static GLboolean _glewInit_GL_ARB_ES2_compatibility (GLEW_CONTEXT_ARG_DEF_INIT)
#endif /* GL_ARB_ES2_compatibility */
+#ifdef GL_ARB_ES3_compatibility
+
+#endif /* GL_ARB_ES3_compatibility */
+
+#ifdef GL_ARB_arrays_of_arrays
+
+#endif /* GL_ARB_arrays_of_arrays */
+
#ifdef GL_ARB_base_instance
static GLboolean _glewInit_GL_ARB_base_instance (GLEW_CONTEXT_ARG_DEF_INIT)
@@ -3709,6 +4190,34 @@ static GLboolean _glewInit_GL_ARB_base_instance (GLEW_CONTEXT_ARG_DEF_INIT)
#endif /* GL_ARB_base_instance */
+#ifdef GL_ARB_bindless_texture
+
+static GLboolean _glewInit_GL_ARB_bindless_texture (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glGetImageHandleARB = (PFNGLGETIMAGEHANDLEARBPROC)glewGetProcAddress((const GLubyte*)"glGetImageHandleARB")) == NULL) || r;
+ r = ((glGetTextureHandleARB = (PFNGLGETTEXTUREHANDLEARBPROC)glewGetProcAddress((const GLubyte*)"glGetTextureHandleARB")) == NULL) || r;
+ r = ((glGetTextureSamplerHandleARB = (PFNGLGETTEXTURESAMPLERHANDLEARBPROC)glewGetProcAddress((const GLubyte*)"glGetTextureSamplerHandleARB")) == NULL) || r;
+ r = ((glGetVertexAttribLui64vARB = (PFNGLGETVERTEXATTRIBLUI64VARBPROC)glewGetProcAddress((const GLubyte*)"glGetVertexAttribLui64vARB")) == NULL) || r;
+ r = ((glIsImageHandleResidentARB = (PFNGLISIMAGEHANDLERESIDENTARBPROC)glewGetProcAddress((const GLubyte*)"glIsImageHandleResidentARB")) == NULL) || r;
+ r = ((glIsTextureHandleResidentARB = (PFNGLISTEXTUREHANDLERESIDENTARBPROC)glewGetProcAddress((const GLubyte*)"glIsTextureHandleResidentARB")) == NULL) || r;
+ r = ((glMakeImageHandleNonResidentARB = (PFNGLMAKEIMAGEHANDLENONRESIDENTARBPROC)glewGetProcAddress((const GLubyte*)"glMakeImageHandleNonResidentARB")) == NULL) || r;
+ r = ((glMakeImageHandleResidentARB = (PFNGLMAKEIMAGEHANDLERESIDENTARBPROC)glewGetProcAddress((const GLubyte*)"glMakeImageHandleResidentARB")) == NULL) || r;
+ r = ((glMakeTextureHandleNonResidentARB = (PFNGLMAKETEXTUREHANDLENONRESIDENTARBPROC)glewGetProcAddress((const GLubyte*)"glMakeTextureHandleNonResidentARB")) == NULL) || r;
+ r = ((glMakeTextureHandleResidentARB = (PFNGLMAKETEXTUREHANDLERESIDENTARBPROC)glewGetProcAddress((const GLubyte*)"glMakeTextureHandleResidentARB")) == NULL) || r;
+ r = ((glProgramUniformHandleui64ARB = (PFNGLPROGRAMUNIFORMHANDLEUI64ARBPROC)glewGetProcAddress((const GLubyte*)"glProgramUniformHandleui64ARB")) == NULL) || r;
+ r = ((glProgramUniformHandleui64vARB = (PFNGLPROGRAMUNIFORMHANDLEUI64VARBPROC)glewGetProcAddress((const GLubyte*)"glProgramUniformHandleui64vARB")) == NULL) || r;
+ r = ((glUniformHandleui64ARB = (PFNGLUNIFORMHANDLEUI64ARBPROC)glewGetProcAddress((const GLubyte*)"glUniformHandleui64ARB")) == NULL) || r;
+ r = ((glUniformHandleui64vARB = (PFNGLUNIFORMHANDLEUI64VARBPROC)glewGetProcAddress((const GLubyte*)"glUniformHandleui64vARB")) == NULL) || r;
+ r = ((glVertexAttribL1ui64ARB = (PFNGLVERTEXATTRIBL1UI64ARBPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribL1ui64ARB")) == NULL) || r;
+ r = ((glVertexAttribL1ui64vARB = (PFNGLVERTEXATTRIBL1UI64VARBPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribL1ui64vARB")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_ARB_bindless_texture */
+
#ifdef GL_ARB_blend_func_extended
static GLboolean _glewInit_GL_ARB_blend_func_extended (GLEW_CONTEXT_ARG_DEF_INIT)
@@ -3723,6 +4232,20 @@ static GLboolean _glewInit_GL_ARB_blend_func_extended (GLEW_CONTEXT_ARG_DEF_INIT
#endif /* GL_ARB_blend_func_extended */
+#ifdef GL_ARB_buffer_storage
+
+static GLboolean _glewInit_GL_ARB_buffer_storage (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glBufferStorage = (PFNGLBUFFERSTORAGEPROC)glewGetProcAddress((const GLubyte*)"glBufferStorage")) == NULL) || r;
+ r = ((glNamedBufferStorageEXT = (PFNGLNAMEDBUFFERSTORAGEEXTPROC)glewGetProcAddress((const GLubyte*)"glNamedBufferStorageEXT")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_ARB_buffer_storage */
+
#ifdef GL_ARB_cl_event
static GLboolean _glewInit_GL_ARB_cl_event (GLEW_CONTEXT_ARG_DEF_INIT)
@@ -3736,6 +4259,36 @@ static GLboolean _glewInit_GL_ARB_cl_event (GLEW_CONTEXT_ARG_DEF_INIT)
#endif /* GL_ARB_cl_event */
+#ifdef GL_ARB_clear_buffer_object
+
+static GLboolean _glewInit_GL_ARB_clear_buffer_object (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glClearBufferData = (PFNGLCLEARBUFFERDATAPROC)glewGetProcAddress((const GLubyte*)"glClearBufferData")) == NULL) || r;
+ r = ((glClearBufferSubData = (PFNGLCLEARBUFFERSUBDATAPROC)glewGetProcAddress((const GLubyte*)"glClearBufferSubData")) == NULL) || r;
+ r = ((glClearNamedBufferDataEXT = (PFNGLCLEARNAMEDBUFFERDATAEXTPROC)glewGetProcAddress((const GLubyte*)"glClearNamedBufferDataEXT")) == NULL) || r;
+ r = ((glClearNamedBufferSubDataEXT = (PFNGLCLEARNAMEDBUFFERSUBDATAEXTPROC)glewGetProcAddress((const GLubyte*)"glClearNamedBufferSubDataEXT")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_ARB_clear_buffer_object */
+
+#ifdef GL_ARB_clear_texture
+
+static GLboolean _glewInit_GL_ARB_clear_texture (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glClearTexImage = (PFNGLCLEARTEXIMAGEPROC)glewGetProcAddress((const GLubyte*)"glClearTexImage")) == NULL) || r;
+ r = ((glClearTexSubImage = (PFNGLCLEARTEXSUBIMAGEPROC)glewGetProcAddress((const GLubyte*)"glClearTexSubImage")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_ARB_clear_texture */
+
#ifdef GL_ARB_color_buffer_float
static GLboolean _glewInit_GL_ARB_color_buffer_float (GLEW_CONTEXT_ARG_DEF_INIT)
@@ -3757,6 +4310,33 @@ static GLboolean _glewInit_GL_ARB_color_buffer_float (GLEW_CONTEXT_ARG_DEF_INIT)
#endif /* GL_ARB_compressed_texture_pixel_storage */
+#ifdef GL_ARB_compute_shader
+
+static GLboolean _glewInit_GL_ARB_compute_shader (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glDispatchCompute = (PFNGLDISPATCHCOMPUTEPROC)glewGetProcAddress((const GLubyte*)"glDispatchCompute")) == NULL) || r;
+ r = ((glDispatchComputeIndirect = (PFNGLDISPATCHCOMPUTEINDIRECTPROC)glewGetProcAddress((const GLubyte*)"glDispatchComputeIndirect")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_ARB_compute_shader */
+
+#ifdef GL_ARB_compute_variable_group_size
+
+static GLboolean _glewInit_GL_ARB_compute_variable_group_size (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glDispatchComputeGroupSizeARB = (PFNGLDISPATCHCOMPUTEGROUPSIZEARBPROC)glewGetProcAddress((const GLubyte*)"glDispatchComputeGroupSizeARB")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_ARB_compute_variable_group_size */
+
#ifdef GL_ARB_conservative_depth
#endif /* GL_ARB_conservative_depth */
@@ -3774,6 +4354,19 @@ static GLboolean _glewInit_GL_ARB_copy_buffer (GLEW_CONTEXT_ARG_DEF_INIT)
#endif /* GL_ARB_copy_buffer */
+#ifdef GL_ARB_copy_image
+
+static GLboolean _glewInit_GL_ARB_copy_image (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glCopyImageSubData = (PFNGLCOPYIMAGESUBDATAPROC)glewGetProcAddress((const GLubyte*)"glCopyImageSubData")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_ARB_copy_image */
+
#ifdef GL_ARB_debug_output
static GLboolean _glewInit_GL_ARB_debug_output (GLEW_CONTEXT_ARG_DEF_INIT)
@@ -3865,14 +4458,26 @@ static GLboolean _glewInit_GL_ARB_draw_indirect (GLEW_CONTEXT_ARG_DEF_INIT)
#endif /* GL_ARB_draw_instanced */
+#ifdef GL_ARB_enhanced_layouts
+
+#endif /* GL_ARB_enhanced_layouts */
+
#ifdef GL_ARB_explicit_attrib_location
#endif /* GL_ARB_explicit_attrib_location */
+#ifdef GL_ARB_explicit_uniform_location
+
+#endif /* GL_ARB_explicit_uniform_location */
+
#ifdef GL_ARB_fragment_coord_conventions
#endif /* GL_ARB_fragment_coord_conventions */
+#ifdef GL_ARB_fragment_layer_viewport
+
+#endif /* GL_ARB_fragment_layer_viewport */
+
#ifdef GL_ARB_fragment_program
#endif /* GL_ARB_fragment_program */
@@ -3885,6 +4490,22 @@ static GLboolean _glewInit_GL_ARB_draw_indirect (GLEW_CONTEXT_ARG_DEF_INIT)
#endif /* GL_ARB_fragment_shader */
+#ifdef GL_ARB_framebuffer_no_attachments
+
+static GLboolean _glewInit_GL_ARB_framebuffer_no_attachments (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glFramebufferParameteri = (PFNGLFRAMEBUFFERPARAMETERIPROC)glewGetProcAddress((const GLubyte*)"glFramebufferParameteri")) == NULL) || r;
+ r = ((glGetFramebufferParameteriv = (PFNGLGETFRAMEBUFFERPARAMETERIVPROC)glewGetProcAddress((const GLubyte*)"glGetFramebufferParameteriv")) == NULL) || r;
+ r = ((glGetNamedFramebufferParameterivEXT = (PFNGLGETNAMEDFRAMEBUFFERPARAMETERIVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetNamedFramebufferParameterivEXT")) == NULL) || r;
+ r = ((glNamedFramebufferParameteriEXT = (PFNGLNAMEDFRAMEBUFFERPARAMETERIEXTPROC)glewGetProcAddress((const GLubyte*)"glNamedFramebufferParameteriEXT")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_ARB_framebuffer_no_attachments */
+
#ifdef GL_ARB_framebuffer_object
static GLboolean _glewInit_GL_ARB_framebuffer_object (GLEW_CONTEXT_ARG_DEF_INIT)
@@ -3963,23 +4584,6 @@ static GLboolean _glewInit_GL_ARB_gpu_shader_fp64 (GLEW_CONTEXT_ARG_DEF_INIT)
GLboolean r = GL_FALSE;
r = ((glGetUniformdv = (PFNGLGETUNIFORMDVPROC)glewGetProcAddress((const GLubyte*)"glGetUniformdv")) == NULL) || r;
- r = ((glProgramUniform1dEXT = (PFNGLPROGRAMUNIFORM1DEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform1dEXT")) == NULL) || r;
- r = ((glProgramUniform1dvEXT = (PFNGLPROGRAMUNIFORM1DVEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform1dvEXT")) == NULL) || r;
- r = ((glProgramUniform2dEXT = (PFNGLPROGRAMUNIFORM2DEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform2dEXT")) == NULL) || r;
- r = ((glProgramUniform2dvEXT = (PFNGLPROGRAMUNIFORM2DVEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform2dvEXT")) == NULL) || r;
- r = ((glProgramUniform3dEXT = (PFNGLPROGRAMUNIFORM3DEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform3dEXT")) == NULL) || r;
- r = ((glProgramUniform3dvEXT = (PFNGLPROGRAMUNIFORM3DVEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform3dvEXT")) == NULL) || r;
- r = ((glProgramUniform4dEXT = (PFNGLPROGRAMUNIFORM4DEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform4dEXT")) == NULL) || r;
- r = ((glProgramUniform4dvEXT = (PFNGLPROGRAMUNIFORM4DVEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform4dvEXT")) == NULL) || r;
- r = ((glProgramUniformMatrix2dvEXT = (PFNGLPROGRAMUNIFORMMATRIX2DVEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramUniformMatrix2dvEXT")) == NULL) || r;
- r = ((glProgramUniformMatrix2x3dvEXT = (PFNGLPROGRAMUNIFORMMATRIX2X3DVEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramUniformMatrix2x3dvEXT")) == NULL) || r;
- r = ((glProgramUniformMatrix2x4dvEXT = (PFNGLPROGRAMUNIFORMMATRIX2X4DVEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramUniformMatrix2x4dvEXT")) == NULL) || r;
- r = ((glProgramUniformMatrix3dvEXT = (PFNGLPROGRAMUNIFORMMATRIX3DVEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramUniformMatrix3dvEXT")) == NULL) || r;
- r = ((glProgramUniformMatrix3x2dvEXT = (PFNGLPROGRAMUNIFORMMATRIX3X2DVEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramUniformMatrix3x2dvEXT")) == NULL) || r;
- r = ((glProgramUniformMatrix3x4dvEXT = (PFNGLPROGRAMUNIFORMMATRIX3X4DVEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramUniformMatrix3x4dvEXT")) == NULL) || r;
- r = ((glProgramUniformMatrix4dvEXT = (PFNGLPROGRAMUNIFORMMATRIX4DVEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramUniformMatrix4dvEXT")) == NULL) || r;
- r = ((glProgramUniformMatrix4x2dvEXT = (PFNGLPROGRAMUNIFORMMATRIX4X2DVEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramUniformMatrix4x2dvEXT")) == NULL) || r;
- r = ((glProgramUniformMatrix4x3dvEXT = (PFNGLPROGRAMUNIFORMMATRIX4X3DVEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramUniformMatrix4x3dvEXT")) == NULL) || r;
r = ((glUniform1d = (PFNGLUNIFORM1DPROC)glewGetProcAddress((const GLubyte*)"glUniform1d")) == NULL) || r;
r = ((glUniform1dv = (PFNGLUNIFORM1DVPROC)glewGetProcAddress((const GLubyte*)"glUniform1dv")) == NULL) || r;
r = ((glUniform2d = (PFNGLUNIFORM2DPROC)glewGetProcAddress((const GLubyte*)"glUniform2d")) == NULL) || r;
@@ -4056,6 +4660,20 @@ static GLboolean _glewInit_GL_ARB_imaging (GLEW_CONTEXT_ARG_DEF_INIT)
#endif /* GL_ARB_imaging */
+#ifdef GL_ARB_indirect_parameters
+
+static GLboolean _glewInit_GL_ARB_indirect_parameters (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glMultiDrawArraysIndirectCountARB = (PFNGLMULTIDRAWARRAYSINDIRECTCOUNTARBPROC)glewGetProcAddress((const GLubyte*)"glMultiDrawArraysIndirectCountARB")) == NULL) || r;
+ r = ((glMultiDrawElementsIndirectCountARB = (PFNGLMULTIDRAWELEMENTSINDIRECTCOUNTARBPROC)glewGetProcAddress((const GLubyte*)"glMultiDrawElementsIndirectCountARB")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_ARB_indirect_parameters */
+
#ifdef GL_ARB_instanced_arrays
static GLboolean _glewInit_GL_ARB_instanced_arrays (GLEW_CONTEXT_ARG_DEF_INIT)
@@ -4084,6 +4702,37 @@ static GLboolean _glewInit_GL_ARB_internalformat_query (GLEW_CONTEXT_ARG_DEF_INI
#endif /* GL_ARB_internalformat_query */
+#ifdef GL_ARB_internalformat_query2
+
+static GLboolean _glewInit_GL_ARB_internalformat_query2 (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glGetInternalformati64v = (PFNGLGETINTERNALFORMATI64VPROC)glewGetProcAddress((const GLubyte*)"glGetInternalformati64v")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_ARB_internalformat_query2 */
+
+#ifdef GL_ARB_invalidate_subdata
+
+static GLboolean _glewInit_GL_ARB_invalidate_subdata (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glInvalidateBufferData = (PFNGLINVALIDATEBUFFERDATAPROC)glewGetProcAddress((const GLubyte*)"glInvalidateBufferData")) == NULL) || r;
+ r = ((glInvalidateBufferSubData = (PFNGLINVALIDATEBUFFERSUBDATAPROC)glewGetProcAddress((const GLubyte*)"glInvalidateBufferSubData")) == NULL) || r;
+ r = ((glInvalidateFramebuffer = (PFNGLINVALIDATEFRAMEBUFFERPROC)glewGetProcAddress((const GLubyte*)"glInvalidateFramebuffer")) == NULL) || r;
+ r = ((glInvalidateSubFramebuffer = (PFNGLINVALIDATESUBFRAMEBUFFERPROC)glewGetProcAddress((const GLubyte*)"glInvalidateSubFramebuffer")) == NULL) || r;
+ r = ((glInvalidateTexImage = (PFNGLINVALIDATETEXIMAGEPROC)glewGetProcAddress((const GLubyte*)"glInvalidateTexImage")) == NULL) || r;
+ r = ((glInvalidateTexSubImage = (PFNGLINVALIDATETEXSUBIMAGEPROC)glewGetProcAddress((const GLubyte*)"glInvalidateTexSubImage")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_ARB_invalidate_subdata */
+
#ifdef GL_ARB_map_buffer_alignment
#endif /* GL_ARB_map_buffer_alignment */
@@ -4119,6 +4768,38 @@ static GLboolean _glewInit_GL_ARB_matrix_palette (GLEW_CONTEXT_ARG_DEF_INIT)
#endif /* GL_ARB_matrix_palette */
+#ifdef GL_ARB_multi_bind
+
+static GLboolean _glewInit_GL_ARB_multi_bind (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glBindBuffersBase = (PFNGLBINDBUFFERSBASEPROC)glewGetProcAddress((const GLubyte*)"glBindBuffersBase")) == NULL) || r;
+ r = ((glBindBuffersRange = (PFNGLBINDBUFFERSRANGEPROC)glewGetProcAddress((const GLubyte*)"glBindBuffersRange")) == NULL) || r;
+ r = ((glBindImageTextures = (PFNGLBINDIMAGETEXTURESPROC)glewGetProcAddress((const GLubyte*)"glBindImageTextures")) == NULL) || r;
+ r = ((glBindSamplers = (PFNGLBINDSAMPLERSPROC)glewGetProcAddress((const GLubyte*)"glBindSamplers")) == NULL) || r;
+ r = ((glBindTextures = (PFNGLBINDTEXTURESPROC)glewGetProcAddress((const GLubyte*)"glBindTextures")) == NULL) || r;
+ r = ((glBindVertexBuffers = (PFNGLBINDVERTEXBUFFERSPROC)glewGetProcAddress((const GLubyte*)"glBindVertexBuffers")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_ARB_multi_bind */
+
+#ifdef GL_ARB_multi_draw_indirect
+
+static GLboolean _glewInit_GL_ARB_multi_draw_indirect (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glMultiDrawArraysIndirect = (PFNGLMULTIDRAWARRAYSINDIRECTPROC)glewGetProcAddress((const GLubyte*)"glMultiDrawArraysIndirect")) == NULL) || r;
+ r = ((glMultiDrawElementsIndirect = (PFNGLMULTIDRAWELEMENTSINDIRECTPROC)glewGetProcAddress((const GLubyte*)"glMultiDrawElementsIndirect")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_ARB_multi_draw_indirect */
+
#ifdef GL_ARB_multisample
static GLboolean _glewInit_GL_ARB_multisample (GLEW_CONTEXT_ARG_DEF_INIT)
@@ -4224,6 +4905,24 @@ static GLboolean _glewInit_GL_ARB_point_parameters (GLEW_CONTEXT_ARG_DEF_INIT)
#endif /* GL_ARB_point_sprite */
+#ifdef GL_ARB_program_interface_query
+
+static GLboolean _glewInit_GL_ARB_program_interface_query (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glGetProgramInterfaceiv = (PFNGLGETPROGRAMINTERFACEIVPROC)glewGetProcAddress((const GLubyte*)"glGetProgramInterfaceiv")) == NULL) || r;
+ r = ((glGetProgramResourceIndex = (PFNGLGETPROGRAMRESOURCEINDEXPROC)glewGetProcAddress((const GLubyte*)"glGetProgramResourceIndex")) == NULL) || r;
+ r = ((glGetProgramResourceLocation = (PFNGLGETPROGRAMRESOURCELOCATIONPROC)glewGetProcAddress((const GLubyte*)"glGetProgramResourceLocation")) == NULL) || r;
+ r = ((glGetProgramResourceLocationIndex = (PFNGLGETPROGRAMRESOURCELOCATIONINDEXPROC)glewGetProcAddress((const GLubyte*)"glGetProgramResourceLocationIndex")) == NULL) || r;
+ r = ((glGetProgramResourceName = (PFNGLGETPROGRAMRESOURCENAMEPROC)glewGetProcAddress((const GLubyte*)"glGetProgramResourceName")) == NULL) || r;
+ r = ((glGetProgramResourceiv = (PFNGLGETPROGRAMRESOURCEIVPROC)glewGetProcAddress((const GLubyte*)"glGetProgramResourceiv")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_ARB_program_interface_query */
+
#ifdef GL_ARB_provoking_vertex
static GLboolean _glewInit_GL_ARB_provoking_vertex (GLEW_CONTEXT_ARG_DEF_INIT)
@@ -4237,6 +4936,14 @@ static GLboolean _glewInit_GL_ARB_provoking_vertex (GLEW_CONTEXT_ARG_DEF_INIT)
#endif /* GL_ARB_provoking_vertex */
+#ifdef GL_ARB_query_buffer_object
+
+#endif /* GL_ARB_query_buffer_object */
+
+#ifdef GL_ARB_robust_buffer_access_behavior
+
+#endif /* GL_ARB_robust_buffer_access_behavior */
+
#ifdef GL_ARB_robustness
static GLboolean _glewInit_GL_ARB_robustness (GLEW_CONTEXT_ARG_DEF_INIT)
@@ -4269,6 +4976,14 @@ static GLboolean _glewInit_GL_ARB_robustness (GLEW_CONTEXT_ARG_DEF_INIT)
#endif /* GL_ARB_robustness */
+#ifdef GL_ARB_robustness_application_isolation
+
+#endif /* GL_ARB_robustness_application_isolation */
+
+#ifdef GL_ARB_robustness_share_group_isolation
+
+#endif /* GL_ARB_robustness_share_group_isolation */
+
#ifdef GL_ARB_sample_shading
static GLboolean _glewInit_GL_ARB_sample_shading (GLEW_CONTEXT_ARG_DEF_INIT)
@@ -4312,6 +5027,10 @@ static GLboolean _glewInit_GL_ARB_sampler_objects (GLEW_CONTEXT_ARG_DEF_INIT)
#endif /* GL_ARB_seamless_cube_map */
+#ifdef GL_ARB_seamless_cubemap_per_texture
+
+#endif /* GL_ARB_seamless_cubemap_per_texture */
+
#ifdef GL_ARB_separate_shader_objects
static GLboolean _glewInit_GL_ARB_separate_shader_objects (GLEW_CONTEXT_ARG_DEF_INIT)
@@ -4401,6 +5120,14 @@ static GLboolean _glewInit_GL_ARB_shader_atomic_counters (GLEW_CONTEXT_ARG_DEF_I
#endif /* GL_ARB_shader_bit_encoding */
+#ifdef GL_ARB_shader_draw_parameters
+
+#endif /* GL_ARB_shader_draw_parameters */
+
+#ifdef GL_ARB_shader_group_vote
+
+#endif /* GL_ARB_shader_group_vote */
+
#ifdef GL_ARB_shader_image_load_store
static GLboolean _glewInit_GL_ARB_shader_image_load_store (GLEW_CONTEXT_ARG_DEF_INIT)
@@ -4415,6 +5142,10 @@ static GLboolean _glewInit_GL_ARB_shader_image_load_store (GLEW_CONTEXT_ARG_DEF_
#endif /* GL_ARB_shader_image_load_store */
+#ifdef GL_ARB_shader_image_size
+
+#endif /* GL_ARB_shader_image_size */
+
#ifdef GL_ARB_shader_objects
static GLboolean _glewInit_GL_ARB_shader_objects (GLEW_CONTEXT_ARG_DEF_INIT)
@@ -4474,6 +5205,19 @@ static GLboolean _glewInit_GL_ARB_shader_objects (GLEW_CONTEXT_ARG_DEF_INIT)
#endif /* GL_ARB_shader_stencil_export */
+#ifdef GL_ARB_shader_storage_buffer_object
+
+static GLboolean _glewInit_GL_ARB_shader_storage_buffer_object (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glShaderStorageBlockBinding = (PFNGLSHADERSTORAGEBLOCKBINDINGPROC)glewGetProcAddress((const GLubyte*)"glShaderStorageBlockBinding")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_ARB_shader_storage_buffer_object */
+
#ifdef GL_ARB_shader_subroutine
static GLboolean _glewInit_GL_ARB_shader_subroutine (GLEW_CONTEXT_ARG_DEF_INIT)
@@ -4536,6 +5280,24 @@ static GLboolean _glewInit_GL_ARB_shading_language_include (GLEW_CONTEXT_ARG_DEF
#endif /* GL_ARB_shadow_ambient */
+#ifdef GL_ARB_sparse_texture
+
+static GLboolean _glewInit_GL_ARB_sparse_texture (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glTexPageCommitmentARB = (PFNGLTEXPAGECOMMITMENTARBPROC)glewGetProcAddress((const GLubyte*)"glTexPageCommitmentARB")) == NULL) || r;
+ r = ((glTexturePageCommitmentEXT = (PFNGLTEXTUREPAGECOMMITMENTEXTPROC)glewGetProcAddress((const GLubyte*)"glTexturePageCommitmentEXT")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_ARB_sparse_texture */
+
+#ifdef GL_ARB_stencil_texturing
+
+#endif /* GL_ARB_stencil_texturing */
+
#ifdef GL_ARB_sync
static GLboolean _glewInit_GL_ARB_sync (GLEW_CONTEXT_ARG_DEF_INIT)
@@ -4590,6 +5352,20 @@ static GLboolean _glewInit_GL_ARB_texture_buffer_object (GLEW_CONTEXT_ARG_DEF_IN
#endif /* GL_ARB_texture_buffer_object_rgb32 */
+#ifdef GL_ARB_texture_buffer_range
+
+static GLboolean _glewInit_GL_ARB_texture_buffer_range (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glTexBufferRange = (PFNGLTEXBUFFERRANGEPROC)glewGetProcAddress((const GLubyte*)"glTexBufferRange")) == NULL) || r;
+ r = ((glTextureBufferRangeEXT = (PFNGLTEXTUREBUFFERRANGEEXTPROC)glewGetProcAddress((const GLubyte*)"glTextureBufferRangeEXT")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_ARB_texture_buffer_range */
+
#ifdef GL_ARB_texture_compression
static GLboolean _glewInit_GL_ARB_texture_compression (GLEW_CONTEXT_ARG_DEF_INIT)
@@ -4649,6 +5425,10 @@ static GLboolean _glewInit_GL_ARB_texture_compression (GLEW_CONTEXT_ARG_DEF_INIT
#endif /* GL_ARB_texture_gather */
+#ifdef GL_ARB_texture_mirror_clamp_to_edge
+
+#endif /* GL_ARB_texture_mirror_clamp_to_edge */
+
#ifdef GL_ARB_texture_mirrored_repeat
#endif /* GL_ARB_texture_mirrored_repeat */
@@ -4673,6 +5453,10 @@ static GLboolean _glewInit_GL_ARB_texture_multisample (GLEW_CONTEXT_ARG_DEF_INIT
#endif /* GL_ARB_texture_non_power_of_two */
+#ifdef GL_ARB_texture_query_levels
+
+#endif /* GL_ARB_texture_query_levels */
+
#ifdef GL_ARB_texture_query_lod
#endif /* GL_ARB_texture_query_lod */
@@ -4689,6 +5473,10 @@ static GLboolean _glewInit_GL_ARB_texture_multisample (GLEW_CONTEXT_ARG_DEF_INIT
#endif /* GL_ARB_texture_rgb10_a2ui */
+#ifdef GL_ARB_texture_stencil8
+
+#endif /* GL_ARB_texture_stencil8 */
+
#ifdef GL_ARB_texture_storage
static GLboolean _glewInit_GL_ARB_texture_storage (GLEW_CONTEXT_ARG_DEF_INIT)
@@ -4707,10 +5495,39 @@ static GLboolean _glewInit_GL_ARB_texture_storage (GLEW_CONTEXT_ARG_DEF_INIT)
#endif /* GL_ARB_texture_storage */
+#ifdef GL_ARB_texture_storage_multisample
+
+static GLboolean _glewInit_GL_ARB_texture_storage_multisample (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glTexStorage2DMultisample = (PFNGLTEXSTORAGE2DMULTISAMPLEPROC)glewGetProcAddress((const GLubyte*)"glTexStorage2DMultisample")) == NULL) || r;
+ r = ((glTexStorage3DMultisample = (PFNGLTEXSTORAGE3DMULTISAMPLEPROC)glewGetProcAddress((const GLubyte*)"glTexStorage3DMultisample")) == NULL) || r;
+ r = ((glTextureStorage2DMultisampleEXT = (PFNGLTEXTURESTORAGE2DMULTISAMPLEEXTPROC)glewGetProcAddress((const GLubyte*)"glTextureStorage2DMultisampleEXT")) == NULL) || r;
+ r = ((glTextureStorage3DMultisampleEXT = (PFNGLTEXTURESTORAGE3DMULTISAMPLEEXTPROC)glewGetProcAddress((const GLubyte*)"glTextureStorage3DMultisampleEXT")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_ARB_texture_storage_multisample */
+
#ifdef GL_ARB_texture_swizzle
#endif /* GL_ARB_texture_swizzle */
+#ifdef GL_ARB_texture_view
+
+static GLboolean _glewInit_GL_ARB_texture_view (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glTextureView = (PFNGLTEXTUREVIEWPROC)glewGetProcAddress((const GLubyte*)"glTextureView")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_ARB_texture_view */
+
#ifdef GL_ARB_timer_query
static GLboolean _glewInit_GL_ARB_timer_query (GLEW_CONTEXT_ARG_DEF_INIT)
@@ -4855,6 +5672,24 @@ static GLboolean _glewInit_GL_ARB_vertex_attrib_64bit (GLEW_CONTEXT_ARG_DEF_INIT
#endif /* GL_ARB_vertex_attrib_64bit */
+#ifdef GL_ARB_vertex_attrib_binding
+
+static GLboolean _glewInit_GL_ARB_vertex_attrib_binding (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glBindVertexBuffer = (PFNGLBINDVERTEXBUFFERPROC)glewGetProcAddress((const GLubyte*)"glBindVertexBuffer")) == NULL) || r;
+ r = ((glVertexAttribBinding = (PFNGLVERTEXATTRIBBINDINGPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribBinding")) == NULL) || r;
+ r = ((glVertexAttribFormat = (PFNGLVERTEXATTRIBFORMATPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribFormat")) == NULL) || r;
+ r = ((glVertexAttribIFormat = (PFNGLVERTEXATTRIBIFORMATPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribIFormat")) == NULL) || r;
+ r = ((glVertexAttribLFormat = (PFNGLVERTEXATTRIBLFORMATPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribLFormat")) == NULL) || r;
+ r = ((glVertexBindingDivisor = (PFNGLVERTEXBINDINGDIVISORPROC)glewGetProcAddress((const GLubyte*)"glVertexBindingDivisor")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_ARB_vertex_attrib_binding */
+
#ifdef GL_ARB_vertex_blend
static GLboolean _glewInit_GL_ARB_vertex_blend (GLEW_CONTEXT_ARG_DEF_INIT)
@@ -4989,6 +5824,10 @@ static GLboolean _glewInit_GL_ARB_vertex_shader (GLEW_CONTEXT_ARG_DEF_INIT)
#endif /* GL_ARB_vertex_shader */
+#ifdef GL_ARB_vertex_type_10f_11f_11f_rev
+
+#endif /* GL_ARB_vertex_type_10f_11f_11f_rev */
+
#ifdef GL_ARB_vertex_type_2_10_10_10_rev
static GLboolean _glewInit_GL_ARB_vertex_type_2_10_10_10_rev (GLEW_CONTEXT_ARG_DEF_INIT)
@@ -5303,6 +6142,14 @@ static GLboolean _glewInit_GL_ATI_vertex_streams (GLEW_CONTEXT_ARG_DEF_INIT)
r = ((glNormalStream3svATI = (PFNGLNORMALSTREAM3SVATIPROC)glewGetProcAddress((const GLubyte*)"glNormalStream3svATI")) == NULL) || r;
r = ((glVertexBlendEnvfATI = (PFNGLVERTEXBLENDENVFATIPROC)glewGetProcAddress((const GLubyte*)"glVertexBlendEnvfATI")) == NULL) || r;
r = ((glVertexBlendEnviATI = (PFNGLVERTEXBLENDENVIATIPROC)glewGetProcAddress((const GLubyte*)"glVertexBlendEnviATI")) == NULL) || r;
+ r = ((glVertexStream1dATI = (PFNGLVERTEXSTREAM1DATIPROC)glewGetProcAddress((const GLubyte*)"glVertexStream1dATI")) == NULL) || r;
+ r = ((glVertexStream1dvATI = (PFNGLVERTEXSTREAM1DVATIPROC)glewGetProcAddress((const GLubyte*)"glVertexStream1dvATI")) == NULL) || r;
+ r = ((glVertexStream1fATI = (PFNGLVERTEXSTREAM1FATIPROC)glewGetProcAddress((const GLubyte*)"glVertexStream1fATI")) == NULL) || r;
+ r = ((glVertexStream1fvATI = (PFNGLVERTEXSTREAM1FVATIPROC)glewGetProcAddress((const GLubyte*)"glVertexStream1fvATI")) == NULL) || r;
+ r = ((glVertexStream1iATI = (PFNGLVERTEXSTREAM1IATIPROC)glewGetProcAddress((const GLubyte*)"glVertexStream1iATI")) == NULL) || r;
+ r = ((glVertexStream1ivATI = (PFNGLVERTEXSTREAM1IVATIPROC)glewGetProcAddress((const GLubyte*)"glVertexStream1ivATI")) == NULL) || r;
+ r = ((glVertexStream1sATI = (PFNGLVERTEXSTREAM1SATIPROC)glewGetProcAddress((const GLubyte*)"glVertexStream1sATI")) == NULL) || r;
+ r = ((glVertexStream1svATI = (PFNGLVERTEXSTREAM1SVATIPROC)glewGetProcAddress((const GLubyte*)"glVertexStream1svATI")) == NULL) || r;
r = ((glVertexStream2dATI = (PFNGLVERTEXSTREAM2DATIPROC)glewGetProcAddress((const GLubyte*)"glVertexStream2dATI")) == NULL) || r;
r = ((glVertexStream2dvATI = (PFNGLVERTEXSTREAM2DVATIPROC)glewGetProcAddress((const GLubyte*)"glVertexStream2dvATI")) == NULL) || r;
r = ((glVertexStream2fATI = (PFNGLVERTEXSTREAM2FATIPROC)glewGetProcAddress((const GLubyte*)"glVertexStream2fATI")) == NULL) || r;
@@ -5530,6 +6377,21 @@ static GLboolean _glewInit_GL_EXT_cull_vertex (GLEW_CONTEXT_ARG_DEF_INIT)
#endif /* GL_EXT_cull_vertex */
+#ifdef GL_EXT_debug_marker
+
+static GLboolean _glewInit_GL_EXT_debug_marker (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glInsertEventMarkerEXT = (PFNGLINSERTEVENTMARKEREXTPROC)glewGetProcAddress((const GLubyte*)"glInsertEventMarkerEXT")) == NULL) || r;
+ r = ((glPopGroupMarkerEXT = (PFNGLPOPGROUPMARKEREXTPROC)glewGetProcAddress((const GLubyte*)"glPopGroupMarkerEXT")) == NULL) || r;
+ r = ((glPushGroupMarkerEXT = (PFNGLPUSHGROUPMARKEREXTPROC)glewGetProcAddress((const GLubyte*)"glPushGroupMarkerEXT")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_EXT_debug_marker */
+
#ifdef GL_EXT_depth_bounds_test
static GLboolean _glewInit_GL_EXT_depth_bounds_test (GLEW_CONTEXT_ARG_DEF_INIT)
@@ -6763,6 +7625,21 @@ static GLboolean _glewInit_GL_IBM_vertex_array_lists (GLEW_CONTEXT_ARG_DEF_INIT)
#endif /* GL_INGR_interlace_read */
+#ifdef GL_INTEL_map_texture
+
+static GLboolean _glewInit_GL_INTEL_map_texture (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glMapTexture2DINTEL = (PFNGLMAPTEXTURE2DINTELPROC)glewGetProcAddress((const GLubyte*)"glMapTexture2DINTEL")) == NULL) || r;
+ r = ((glSyncTextureINTEL = (PFNGLSYNCTEXTUREINTELPROC)glewGetProcAddress((const GLubyte*)"glSyncTextureINTEL")) == NULL) || r;
+ r = ((glUnmapTexture2DINTEL = (PFNGLUNMAPTEXTURE2DINTELPROC)glewGetProcAddress((const GLubyte*)"glUnmapTexture2DINTEL")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_INTEL_map_texture */
+
#ifdef GL_INTEL_parallel_arrays
static GLboolean _glewInit_GL_INTEL_parallel_arrays (GLEW_CONTEXT_ARG_DEF_INIT)
@@ -6793,6 +7670,32 @@ static GLboolean _glewInit_GL_INTEL_texture_scissor (GLEW_CONTEXT_ARG_DEF_INIT)
#endif /* GL_INTEL_texture_scissor */
+#ifdef GL_KHR_debug
+
+static GLboolean _glewInit_GL_KHR_debug (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glDebugMessageCallback = (PFNGLDEBUGMESSAGECALLBACKPROC)glewGetProcAddress((const GLubyte*)"glDebugMessageCallback")) == NULL) || r;
+ r = ((glDebugMessageControl = (PFNGLDEBUGMESSAGECONTROLPROC)glewGetProcAddress((const GLubyte*)"glDebugMessageControl")) == NULL) || r;
+ r = ((glDebugMessageInsert = (PFNGLDEBUGMESSAGEINSERTPROC)glewGetProcAddress((const GLubyte*)"glDebugMessageInsert")) == NULL) || r;
+ r = ((glGetDebugMessageLog = (PFNGLGETDEBUGMESSAGELOGPROC)glewGetProcAddress((const GLubyte*)"glGetDebugMessageLog")) == NULL) || r;
+ r = ((glGetObjectLabel = (PFNGLGETOBJECTLABELPROC)glewGetProcAddress((const GLubyte*)"glGetObjectLabel")) == NULL) || r;
+ r = ((glGetObjectPtrLabel = (PFNGLGETOBJECTPTRLABELPROC)glewGetProcAddress((const GLubyte*)"glGetObjectPtrLabel")) == NULL) || r;
+ r = ((glObjectLabel = (PFNGLOBJECTLABELPROC)glewGetProcAddress((const GLubyte*)"glObjectLabel")) == NULL) || r;
+ r = ((glObjectPtrLabel = (PFNGLOBJECTPTRLABELPROC)glewGetProcAddress((const GLubyte*)"glObjectPtrLabel")) == NULL) || r;
+ r = ((glPopDebugGroup = (PFNGLPOPDEBUGGROUPPROC)glewGetProcAddress((const GLubyte*)"glPopDebugGroup")) == NULL) || r;
+ r = ((glPushDebugGroup = (PFNGLPUSHDEBUGGROUPPROC)glewGetProcAddress((const GLubyte*)"glPushDebugGroup")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_KHR_debug */
+
+#ifdef GL_KHR_texture_compression_astc_ldr
+
+#endif /* GL_KHR_texture_compression_astc_ldr */
+
#ifdef GL_KTX_buffer_region
static GLboolean _glewInit_GL_KTX_buffer_region (GLEW_CONTEXT_ARG_DEF_INIT)
@@ -6871,14 +7774,89 @@ static GLboolean _glewInit_GL_MESA_window_pos (GLEW_CONTEXT_ARG_DEF_INIT)
#endif /* GL_MESA_ycbcr_texture */
+#ifdef GL_NVX_conditional_render
+
+static GLboolean _glewInit_GL_NVX_conditional_render (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glBeginConditionalRenderNVX = (PFNGLBEGINCONDITIONALRENDERNVXPROC)glewGetProcAddress((const GLubyte*)"glBeginConditionalRenderNVX")) == NULL) || r;
+ r = ((glEndConditionalRenderNVX = (PFNGLENDCONDITIONALRENDERNVXPROC)glewGetProcAddress((const GLubyte*)"glEndConditionalRenderNVX")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_NVX_conditional_render */
+
#ifdef GL_NVX_gpu_memory_info
#endif /* GL_NVX_gpu_memory_info */
+#ifdef GL_NV_bindless_multi_draw_indirect
+
+static GLboolean _glewInit_GL_NV_bindless_multi_draw_indirect (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glMultiDrawArraysIndirectBindlessNV = (PFNGLMULTIDRAWARRAYSINDIRECTBINDLESSNVPROC)glewGetProcAddress((const GLubyte*)"glMultiDrawArraysIndirectBindlessNV")) == NULL) || r;
+ r = ((glMultiDrawElementsIndirectBindlessNV = (PFNGLMULTIDRAWELEMENTSINDIRECTBINDLESSNVPROC)glewGetProcAddress((const GLubyte*)"glMultiDrawElementsIndirectBindlessNV")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_NV_bindless_multi_draw_indirect */
+
+#ifdef GL_NV_bindless_texture
+
+static GLboolean _glewInit_GL_NV_bindless_texture (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glGetImageHandleNV = (PFNGLGETIMAGEHANDLENVPROC)glewGetProcAddress((const GLubyte*)"glGetImageHandleNV")) == NULL) || r;
+ r = ((glGetTextureHandleNV = (PFNGLGETTEXTUREHANDLENVPROC)glewGetProcAddress((const GLubyte*)"glGetTextureHandleNV")) == NULL) || r;
+ r = ((glGetTextureSamplerHandleNV = (PFNGLGETTEXTURESAMPLERHANDLENVPROC)glewGetProcAddress((const GLubyte*)"glGetTextureSamplerHandleNV")) == NULL) || r;
+ r = ((glIsImageHandleResidentNV = (PFNGLISIMAGEHANDLERESIDENTNVPROC)glewGetProcAddress((const GLubyte*)"glIsImageHandleResidentNV")) == NULL) || r;
+ r = ((glIsTextureHandleResidentNV = (PFNGLISTEXTUREHANDLERESIDENTNVPROC)glewGetProcAddress((const GLubyte*)"glIsTextureHandleResidentNV")) == NULL) || r;
+ r = ((glMakeImageHandleNonResidentNV = (PFNGLMAKEIMAGEHANDLENONRESIDENTNVPROC)glewGetProcAddress((const GLubyte*)"glMakeImageHandleNonResidentNV")) == NULL) || r;
+ r = ((glMakeImageHandleResidentNV = (PFNGLMAKEIMAGEHANDLERESIDENTNVPROC)glewGetProcAddress((const GLubyte*)"glMakeImageHandleResidentNV")) == NULL) || r;
+ r = ((glMakeTextureHandleNonResidentNV = (PFNGLMAKETEXTUREHANDLENONRESIDENTNVPROC)glewGetProcAddress((const GLubyte*)"glMakeTextureHandleNonResidentNV")) == NULL) || r;
+ r = ((glMakeTextureHandleResidentNV = (PFNGLMAKETEXTUREHANDLERESIDENTNVPROC)glewGetProcAddress((const GLubyte*)"glMakeTextureHandleResidentNV")) == NULL) || r;
+ r = ((glProgramUniformHandleui64NV = (PFNGLPROGRAMUNIFORMHANDLEUI64NVPROC)glewGetProcAddress((const GLubyte*)"glProgramUniformHandleui64NV")) == NULL) || r;
+ r = ((glProgramUniformHandleui64vNV = (PFNGLPROGRAMUNIFORMHANDLEUI64VNVPROC)glewGetProcAddress((const GLubyte*)"glProgramUniformHandleui64vNV")) == NULL) || r;
+ r = ((glUniformHandleui64NV = (PFNGLUNIFORMHANDLEUI64NVPROC)glewGetProcAddress((const GLubyte*)"glUniformHandleui64NV")) == NULL) || r;
+ r = ((glUniformHandleui64vNV = (PFNGLUNIFORMHANDLEUI64VNVPROC)glewGetProcAddress((const GLubyte*)"glUniformHandleui64vNV")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_NV_bindless_texture */
+
+#ifdef GL_NV_blend_equation_advanced
+
+static GLboolean _glewInit_GL_NV_blend_equation_advanced (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glBlendBarrierNV = (PFNGLBLENDBARRIERNVPROC)glewGetProcAddress((const GLubyte*)"glBlendBarrierNV")) == NULL) || r;
+ r = ((glBlendParameteriNV = (PFNGLBLENDPARAMETERINVPROC)glewGetProcAddress((const GLubyte*)"glBlendParameteriNV")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_NV_blend_equation_advanced */
+
+#ifdef GL_NV_blend_equation_advanced_coherent
+
+#endif /* GL_NV_blend_equation_advanced_coherent */
+
#ifdef GL_NV_blend_square
#endif /* GL_NV_blend_square */
+#ifdef GL_NV_compute_program5
+
+#endif /* GL_NV_compute_program5 */
+
#ifdef GL_NV_conditional_render
static GLboolean _glewInit_GL_NV_conditional_render (GLEW_CONTEXT_ARG_DEF_INIT)
@@ -6910,6 +7888,10 @@ static GLboolean _glewInit_GL_NV_copy_image (GLEW_CONTEXT_ARG_DEF_INIT)
#endif /* GL_NV_copy_image */
+#ifdef GL_NV_deep_texture3D
+
+#endif /* GL_NV_deep_texture3D */
+
#ifdef GL_NV_depth_buffer_float
static GLboolean _glewInit_GL_NV_depth_buffer_float (GLEW_CONTEXT_ARG_DEF_INIT)
@@ -6933,6 +7915,19 @@ static GLboolean _glewInit_GL_NV_depth_buffer_float (GLEW_CONTEXT_ARG_DEF_INIT)
#endif /* GL_NV_depth_range_unclamped */
+#ifdef GL_NV_draw_texture
+
+static GLboolean _glewInit_GL_NV_draw_texture (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glDrawTextureNV = (PFNGLDRAWTEXTURENVPROC)glewGetProcAddress((const GLubyte*)"glDrawTextureNV")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_NV_draw_texture */
+
#ifdef GL_NV_evaluators
static GLboolean _glewInit_GL_NV_evaluators (GLEW_CONTEXT_ARG_DEF_INIT)
@@ -7084,6 +8079,10 @@ static GLboolean _glewInit_GL_NV_gpu_program4 (GLEW_CONTEXT_ARG_DEF_INIT)
#endif /* GL_NV_gpu_program5 */
+#ifdef GL_NV_gpu_program5_mem_extended
+
+#endif /* GL_NV_gpu_program5_mem_extended */
+
#ifdef GL_NV_gpu_program_fp64
#endif /* GL_NV_gpu_program_fp64 */
@@ -7406,6 +8405,14 @@ static GLboolean _glewInit_GL_NV_register_combiners2 (GLEW_CONTEXT_ARG_DEF_INIT)
#endif /* GL_NV_register_combiners2 */
+#ifdef GL_NV_shader_atomic_counters
+
+#endif /* GL_NV_shader_atomic_counters */
+
+#ifdef GL_NV_shader_atomic_float
+
+#endif /* GL_NV_shader_atomic_float */
+
#ifdef GL_NV_shader_buffer_load
static GLboolean _glewInit_GL_NV_shader_buffer_load (GLEW_CONTEXT_ARG_DEF_INIT)
@@ -7431,6 +8438,10 @@ static GLboolean _glewInit_GL_NV_shader_buffer_load (GLEW_CONTEXT_ARG_DEF_INIT)
#endif /* GL_NV_shader_buffer_load */
+#ifdef GL_NV_shader_storage_buffer_object
+
+#endif /* GL_NV_shader_storage_buffer_object */
+
#ifdef GL_NV_tessellation_program5
#endif /* GL_NV_tessellation_program5 */
@@ -7809,6 +8820,118 @@ static GLboolean _glewInit_GL_OES_single_precision (GLEW_CONTEXT_ARG_DEF_INIT)
#endif /* GL_PGI_vertex_hints */
+#ifdef GL_REGAL_ES1_0_compatibility
+
+static GLboolean _glewInit_GL_REGAL_ES1_0_compatibility (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glAlphaFuncx = (PFNGLALPHAFUNCXPROC)glewGetProcAddress((const GLubyte*)"glAlphaFuncx")) == NULL) || r;
+ r = ((glClearColorx = (PFNGLCLEARCOLORXPROC)glewGetProcAddress((const GLubyte*)"glClearColorx")) == NULL) || r;
+ r = ((glClearDepthx = (PFNGLCLEARDEPTHXPROC)glewGetProcAddress((const GLubyte*)"glClearDepthx")) == NULL) || r;
+ r = ((glColor4x = (PFNGLCOLOR4XPROC)glewGetProcAddress((const GLubyte*)"glColor4x")) == NULL) || r;
+ r = ((glDepthRangex = (PFNGLDEPTHRANGEXPROC)glewGetProcAddress((const GLubyte*)"glDepthRangex")) == NULL) || r;
+ r = ((glFogx = (PFNGLFOGXPROC)glewGetProcAddress((const GLubyte*)"glFogx")) == NULL) || r;
+ r = ((glFogxv = (PFNGLFOGXVPROC)glewGetProcAddress((const GLubyte*)"glFogxv")) == NULL) || r;
+ r = ((glFrustumf = (PFNGLFRUSTUMFPROC)glewGetProcAddress((const GLubyte*)"glFrustumf")) == NULL) || r;
+ r = ((glFrustumx = (PFNGLFRUSTUMXPROC)glewGetProcAddress((const GLubyte*)"glFrustumx")) == NULL) || r;
+ r = ((glLightModelx = (PFNGLLIGHTMODELXPROC)glewGetProcAddress((const GLubyte*)"glLightModelx")) == NULL) || r;
+ r = ((glLightModelxv = (PFNGLLIGHTMODELXVPROC)glewGetProcAddress((const GLubyte*)"glLightModelxv")) == NULL) || r;
+ r = ((glLightx = (PFNGLLIGHTXPROC)glewGetProcAddress((const GLubyte*)"glLightx")) == NULL) || r;
+ r = ((glLightxv = (PFNGLLIGHTXVPROC)glewGetProcAddress((const GLubyte*)"glLightxv")) == NULL) || r;
+ r = ((glLineWidthx = (PFNGLLINEWIDTHXPROC)glewGetProcAddress((const GLubyte*)"glLineWidthx")) == NULL) || r;
+ r = ((glLoadMatrixx = (PFNGLLOADMATRIXXPROC)glewGetProcAddress((const GLubyte*)"glLoadMatrixx")) == NULL) || r;
+ r = ((glMaterialx = (PFNGLMATERIALXPROC)glewGetProcAddress((const GLubyte*)"glMaterialx")) == NULL) || r;
+ r = ((glMaterialxv = (PFNGLMATERIALXVPROC)glewGetProcAddress((const GLubyte*)"glMaterialxv")) == NULL) || r;
+ r = ((glMultMatrixx = (PFNGLMULTMATRIXXPROC)glewGetProcAddress((const GLubyte*)"glMultMatrixx")) == NULL) || r;
+ r = ((glMultiTexCoord4x = (PFNGLMULTITEXCOORD4XPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord4x")) == NULL) || r;
+ r = ((glNormal3x = (PFNGLNORMAL3XPROC)glewGetProcAddress((const GLubyte*)"glNormal3x")) == NULL) || r;
+ r = ((glOrthof = (PFNGLORTHOFPROC)glewGetProcAddress((const GLubyte*)"glOrthof")) == NULL) || r;
+ r = ((glOrthox = (PFNGLORTHOXPROC)glewGetProcAddress((const GLubyte*)"glOrthox")) == NULL) || r;
+ r = ((glPointSizex = (PFNGLPOINTSIZEXPROC)glewGetProcAddress((const GLubyte*)"glPointSizex")) == NULL) || r;
+ r = ((glPolygonOffsetx = (PFNGLPOLYGONOFFSETXPROC)glewGetProcAddress((const GLubyte*)"glPolygonOffsetx")) == NULL) || r;
+ r = ((glRotatex = (PFNGLROTATEXPROC)glewGetProcAddress((const GLubyte*)"glRotatex")) == NULL) || r;
+ r = ((glSampleCoveragex = (PFNGLSAMPLECOVERAGEXPROC)glewGetProcAddress((const GLubyte*)"glSampleCoveragex")) == NULL) || r;
+ r = ((glScalex = (PFNGLSCALEXPROC)glewGetProcAddress((const GLubyte*)"glScalex")) == NULL) || r;
+ r = ((glTexEnvx = (PFNGLTEXENVXPROC)glewGetProcAddress((const GLubyte*)"glTexEnvx")) == NULL) || r;
+ r = ((glTexEnvxv = (PFNGLTEXENVXVPROC)glewGetProcAddress((const GLubyte*)"glTexEnvxv")) == NULL) || r;
+ r = ((glTexParameterx = (PFNGLTEXPARAMETERXPROC)glewGetProcAddress((const GLubyte*)"glTexParameterx")) == NULL) || r;
+ r = ((glTranslatex = (PFNGLTRANSLATEXPROC)glewGetProcAddress((const GLubyte*)"glTranslatex")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_REGAL_ES1_0_compatibility */
+
+#ifdef GL_REGAL_ES1_1_compatibility
+
+static GLboolean _glewInit_GL_REGAL_ES1_1_compatibility (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glClipPlanef = (PFNGLCLIPPLANEFPROC)glewGetProcAddress((const GLubyte*)"glClipPlanef")) == NULL) || r;
+ r = ((glClipPlanex = (PFNGLCLIPPLANEXPROC)glewGetProcAddress((const GLubyte*)"glClipPlanex")) == NULL) || r;
+ r = ((glGetClipPlanef = (PFNGLGETCLIPPLANEFPROC)glewGetProcAddress((const GLubyte*)"glGetClipPlanef")) == NULL) || r;
+ r = ((glGetClipPlanex = (PFNGLGETCLIPPLANEXPROC)glewGetProcAddress((const GLubyte*)"glGetClipPlanex")) == NULL) || r;
+ r = ((glGetFixedv = (PFNGLGETFIXEDVPROC)glewGetProcAddress((const GLubyte*)"glGetFixedv")) == NULL) || r;
+ r = ((glGetLightxv = (PFNGLGETLIGHTXVPROC)glewGetProcAddress((const GLubyte*)"glGetLightxv")) == NULL) || r;
+ r = ((glGetMaterialxv = (PFNGLGETMATERIALXVPROC)glewGetProcAddress((const GLubyte*)"glGetMaterialxv")) == NULL) || r;
+ r = ((glGetTexEnvxv = (PFNGLGETTEXENVXVPROC)glewGetProcAddress((const GLubyte*)"glGetTexEnvxv")) == NULL) || r;
+ r = ((glGetTexParameterxv = (PFNGLGETTEXPARAMETERXVPROC)glewGetProcAddress((const GLubyte*)"glGetTexParameterxv")) == NULL) || r;
+ r = ((glPointParameterx = (PFNGLPOINTPARAMETERXPROC)glewGetProcAddress((const GLubyte*)"glPointParameterx")) == NULL) || r;
+ r = ((glPointParameterxv = (PFNGLPOINTPARAMETERXVPROC)glewGetProcAddress((const GLubyte*)"glPointParameterxv")) == NULL) || r;
+ r = ((glPointSizePointerOES = (PFNGLPOINTSIZEPOINTEROESPROC)glewGetProcAddress((const GLubyte*)"glPointSizePointerOES")) == NULL) || r;
+ r = ((glTexParameterxv = (PFNGLTEXPARAMETERXVPROC)glewGetProcAddress((const GLubyte*)"glTexParameterxv")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_REGAL_ES1_1_compatibility */
+
+#ifdef GL_REGAL_enable
+
+#endif /* GL_REGAL_enable */
+
+#ifdef GL_REGAL_error_string
+
+static GLboolean _glewInit_GL_REGAL_error_string (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glErrorStringREGAL = (PFNGLERRORSTRINGREGALPROC)glewGetProcAddress((const GLubyte*)"glErrorStringREGAL")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_REGAL_error_string */
+
+#ifdef GL_REGAL_extension_query
+
+static GLboolean _glewInit_GL_REGAL_extension_query (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glGetExtensionREGAL = (PFNGLGETEXTENSIONREGALPROC)glewGetProcAddress((const GLubyte*)"glGetExtensionREGAL")) == NULL) || r;
+ r = ((glIsSupportedREGAL = (PFNGLISSUPPORTEDREGALPROC)glewGetProcAddress((const GLubyte*)"glIsSupportedREGAL")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_REGAL_extension_query */
+
+#ifdef GL_REGAL_log
+
+static GLboolean _glewInit_GL_REGAL_log (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glLogMessageCallbackREGAL = (PFNGLLOGMESSAGECALLBACKREGALPROC)glewGetProcAddress((const GLubyte*)"glLogMessageCallbackREGAL")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_REGAL_log */
+
#ifdef GL_REND_screen_coordinates
#endif /* GL_REND_screen_coordinates */
@@ -8345,7 +9468,7 @@ static GLboolean _glewInit_GL_WIN_swap_hint (GLEW_CONTEXT_ARG_DEF_INIT)
/* ------------------------------------------------------------------------- */
-GLboolean glewGetExtension (const char* name)
+GLboolean GLEWAPIENTRY glewGetExtension (const char* name)
{
const GLubyte* start;
const GLubyte* end;
@@ -8361,7 +9484,7 @@ GLboolean glewGetExtension (const char* name)
#ifndef GLEW_MX
static
#endif
-GLenum glewContextInit (GLEW_CONTEXT_ARG_DEF_LIST)
+GLenum GLEWAPIENTRY glewContextInit (GLEW_CONTEXT_ARG_DEF_LIST)
{
const GLubyte* s;
GLuint dot;
@@ -8389,7 +9512,9 @@ GLenum glewContextInit (GLEW_CONTEXT_ARG_DEF_LIST)
}
else
{
- CONST_CAST(GLEW_VERSION_4_2) = ( major > 4 ) || ( major == 4 && minor >= 2 ) ? GL_TRUE : GL_FALSE;
+ CONST_CAST(GLEW_VERSION_4_4) = ( major > 4 ) || ( major == 4 && minor >= 4 ) ? GL_TRUE : GL_FALSE;
+ CONST_CAST(GLEW_VERSION_4_3) = GLEW_VERSION_4_4 == GL_TRUE || ( major == 4 && minor >= 3 ) ? GL_TRUE : GL_FALSE;
+ CONST_CAST(GLEW_VERSION_4_2) = GLEW_VERSION_4_3 == GL_TRUE || ( major == 4 && minor >= 2 ) ? GL_TRUE : GL_FALSE;
CONST_CAST(GLEW_VERSION_4_1) = GLEW_VERSION_4_2 == GL_TRUE || ( major == 4 && minor >= 1 ) ? GL_TRUE : GL_FALSE;
CONST_CAST(GLEW_VERSION_4_0) = GLEW_VERSION_4_1 == GL_TRUE || ( major == 4 ) ? GL_TRUE : GL_FALSE;
CONST_CAST(GLEW_VERSION_3_3) = GLEW_VERSION_4_0 == GL_TRUE || ( major == 3 && minor >= 3 ) ? GL_TRUE : GL_FALSE;
@@ -8452,6 +9577,10 @@ GLenum glewContextInit (GLEW_CONTEXT_ARG_DEF_LIST)
#endif /* GL_VERSION_4_1 */
#ifdef GL_VERSION_4_2
#endif /* GL_VERSION_4_2 */
+#ifdef GL_VERSION_4_3
+#endif /* GL_VERSION_4_3 */
+#ifdef GL_VERSION_4_4
+#endif /* GL_VERSION_4_4 */
#ifdef GL_3DFX_multisample
CONST_CAST(GLEW_3DFX_multisample) = _glewSearchExtension("GL_3DFX_multisample", extStart, extEnd);
#endif /* GL_3DFX_multisample */
@@ -8479,6 +9608,10 @@ GLenum glewContextInit (GLEW_CONTEXT_ARG_DEF_LIST)
CONST_CAST(GLEW_AMD_draw_buffers_blend) = _glewSearchExtension("GL_AMD_draw_buffers_blend", extStart, extEnd);
if (glewExperimental || GLEW_AMD_draw_buffers_blend) CONST_CAST(GLEW_AMD_draw_buffers_blend) = !_glewInit_GL_AMD_draw_buffers_blend(GLEW_CONTEXT_ARG_VAR_INIT);
#endif /* GL_AMD_draw_buffers_blend */
+#ifdef GL_AMD_interleaved_elements
+ CONST_CAST(GLEW_AMD_interleaved_elements) = _glewSearchExtension("GL_AMD_interleaved_elements", extStart, extEnd);
+ if (glewExperimental || GLEW_AMD_interleaved_elements) CONST_CAST(GLEW_AMD_interleaved_elements) = !_glewInit_GL_AMD_interleaved_elements(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_AMD_interleaved_elements */
#ifdef GL_AMD_multi_draw_indirect
CONST_CAST(GLEW_AMD_multi_draw_indirect) = _glewSearchExtension("GL_AMD_multi_draw_indirect", extStart, extEnd);
if (glewExperimental || GLEW_AMD_multi_draw_indirect) CONST_CAST(GLEW_AMD_multi_draw_indirect) = !_glewInit_GL_AMD_multi_draw_indirect(GLEW_CONTEXT_ARG_VAR_INIT);
@@ -8491,6 +9624,12 @@ GLenum glewContextInit (GLEW_CONTEXT_ARG_DEF_LIST)
CONST_CAST(GLEW_AMD_performance_monitor) = _glewSearchExtension("GL_AMD_performance_monitor", extStart, extEnd);
if (glewExperimental || GLEW_AMD_performance_monitor) CONST_CAST(GLEW_AMD_performance_monitor) = !_glewInit_GL_AMD_performance_monitor(GLEW_CONTEXT_ARG_VAR_INIT);
#endif /* GL_AMD_performance_monitor */
+#ifdef GL_AMD_pinned_memory
+ CONST_CAST(GLEW_AMD_pinned_memory) = _glewSearchExtension("GL_AMD_pinned_memory", extStart, extEnd);
+#endif /* GL_AMD_pinned_memory */
+#ifdef GL_AMD_query_buffer_object
+ CONST_CAST(GLEW_AMD_query_buffer_object) = _glewSearchExtension("GL_AMD_query_buffer_object", extStart, extEnd);
+#endif /* GL_AMD_query_buffer_object */
#ifdef GL_AMD_sample_positions
CONST_CAST(GLEW_AMD_sample_positions) = _glewSearchExtension("GL_AMD_sample_positions", extStart, extEnd);
if (glewExperimental || GLEW_AMD_sample_positions) CONST_CAST(GLEW_AMD_sample_positions) = !_glewInit_GL_AMD_sample_positions(GLEW_CONTEXT_ARG_VAR_INIT);
@@ -8501,16 +9640,74 @@ GLenum glewContextInit (GLEW_CONTEXT_ARG_DEF_LIST)
#ifdef GL_AMD_shader_stencil_export
CONST_CAST(GLEW_AMD_shader_stencil_export) = _glewSearchExtension("GL_AMD_shader_stencil_export", extStart, extEnd);
#endif /* GL_AMD_shader_stencil_export */
+#ifdef GL_AMD_shader_trinary_minmax
+ CONST_CAST(GLEW_AMD_shader_trinary_minmax) = _glewSearchExtension("GL_AMD_shader_trinary_minmax", extStart, extEnd);
+#endif /* GL_AMD_shader_trinary_minmax */
+#ifdef GL_AMD_sparse_texture
+ CONST_CAST(GLEW_AMD_sparse_texture) = _glewSearchExtension("GL_AMD_sparse_texture", extStart, extEnd);
+ if (glewExperimental || GLEW_AMD_sparse_texture) CONST_CAST(GLEW_AMD_sparse_texture) = !_glewInit_GL_AMD_sparse_texture(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_AMD_sparse_texture */
+#ifdef GL_AMD_stencil_operation_extended
+ CONST_CAST(GLEW_AMD_stencil_operation_extended) = _glewSearchExtension("GL_AMD_stencil_operation_extended", extStart, extEnd);
+ if (glewExperimental || GLEW_AMD_stencil_operation_extended) CONST_CAST(GLEW_AMD_stencil_operation_extended) = !_glewInit_GL_AMD_stencil_operation_extended(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_AMD_stencil_operation_extended */
#ifdef GL_AMD_texture_texture4
CONST_CAST(GLEW_AMD_texture_texture4) = _glewSearchExtension("GL_AMD_texture_texture4", extStart, extEnd);
#endif /* GL_AMD_texture_texture4 */
#ifdef GL_AMD_transform_feedback3_lines_triangles
CONST_CAST(GLEW_AMD_transform_feedback3_lines_triangles) = _glewSearchExtension("GL_AMD_transform_feedback3_lines_triangles", extStart, extEnd);
#endif /* GL_AMD_transform_feedback3_lines_triangles */
+#ifdef GL_AMD_vertex_shader_layer
+ CONST_CAST(GLEW_AMD_vertex_shader_layer) = _glewSearchExtension("GL_AMD_vertex_shader_layer", extStart, extEnd);
+#endif /* GL_AMD_vertex_shader_layer */
#ifdef GL_AMD_vertex_shader_tessellator
CONST_CAST(GLEW_AMD_vertex_shader_tessellator) = _glewSearchExtension("GL_AMD_vertex_shader_tessellator", extStart, extEnd);
if (glewExperimental || GLEW_AMD_vertex_shader_tessellator) CONST_CAST(GLEW_AMD_vertex_shader_tessellator) = !_glewInit_GL_AMD_vertex_shader_tessellator(GLEW_CONTEXT_ARG_VAR_INIT);
#endif /* GL_AMD_vertex_shader_tessellator */
+#ifdef GL_AMD_vertex_shader_viewport_index
+ CONST_CAST(GLEW_AMD_vertex_shader_viewport_index) = _glewSearchExtension("GL_AMD_vertex_shader_viewport_index", extStart, extEnd);
+#endif /* GL_AMD_vertex_shader_viewport_index */
+#ifdef GL_ANGLE_depth_texture
+ CONST_CAST(GLEW_ANGLE_depth_texture) = _glewSearchExtension("GL_ANGLE_depth_texture", extStart, extEnd);
+#endif /* GL_ANGLE_depth_texture */
+#ifdef GL_ANGLE_framebuffer_blit
+ CONST_CAST(GLEW_ANGLE_framebuffer_blit) = _glewSearchExtension("GL_ANGLE_framebuffer_blit", extStart, extEnd);
+ if (glewExperimental || GLEW_ANGLE_framebuffer_blit) CONST_CAST(GLEW_ANGLE_framebuffer_blit) = !_glewInit_GL_ANGLE_framebuffer_blit(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_ANGLE_framebuffer_blit */
+#ifdef GL_ANGLE_framebuffer_multisample
+ CONST_CAST(GLEW_ANGLE_framebuffer_multisample) = _glewSearchExtension("GL_ANGLE_framebuffer_multisample", extStart, extEnd);
+ if (glewExperimental || GLEW_ANGLE_framebuffer_multisample) CONST_CAST(GLEW_ANGLE_framebuffer_multisample) = !_glewInit_GL_ANGLE_framebuffer_multisample(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_ANGLE_framebuffer_multisample */
+#ifdef GL_ANGLE_instanced_arrays
+ CONST_CAST(GLEW_ANGLE_instanced_arrays) = _glewSearchExtension("GL_ANGLE_instanced_arrays", extStart, extEnd);
+ if (glewExperimental || GLEW_ANGLE_instanced_arrays) CONST_CAST(GLEW_ANGLE_instanced_arrays) = !_glewInit_GL_ANGLE_instanced_arrays(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_ANGLE_instanced_arrays */
+#ifdef GL_ANGLE_pack_reverse_row_order
+ CONST_CAST(GLEW_ANGLE_pack_reverse_row_order) = _glewSearchExtension("GL_ANGLE_pack_reverse_row_order", extStart, extEnd);
+#endif /* GL_ANGLE_pack_reverse_row_order */
+#ifdef GL_ANGLE_program_binary
+ CONST_CAST(GLEW_ANGLE_program_binary) = _glewSearchExtension("GL_ANGLE_program_binary", extStart, extEnd);
+#endif /* GL_ANGLE_program_binary */
+#ifdef GL_ANGLE_texture_compression_dxt1
+ CONST_CAST(GLEW_ANGLE_texture_compression_dxt1) = _glewSearchExtension("GL_ANGLE_texture_compression_dxt1", extStart, extEnd);
+#endif /* GL_ANGLE_texture_compression_dxt1 */
+#ifdef GL_ANGLE_texture_compression_dxt3
+ CONST_CAST(GLEW_ANGLE_texture_compression_dxt3) = _glewSearchExtension("GL_ANGLE_texture_compression_dxt3", extStart, extEnd);
+#endif /* GL_ANGLE_texture_compression_dxt3 */
+#ifdef GL_ANGLE_texture_compression_dxt5
+ CONST_CAST(GLEW_ANGLE_texture_compression_dxt5) = _glewSearchExtension("GL_ANGLE_texture_compression_dxt5", extStart, extEnd);
+#endif /* GL_ANGLE_texture_compression_dxt5 */
+#ifdef GL_ANGLE_texture_usage
+ CONST_CAST(GLEW_ANGLE_texture_usage) = _glewSearchExtension("GL_ANGLE_texture_usage", extStart, extEnd);
+#endif /* GL_ANGLE_texture_usage */
+#ifdef GL_ANGLE_timer_query
+ CONST_CAST(GLEW_ANGLE_timer_query) = _glewSearchExtension("GL_ANGLE_timer_query", extStart, extEnd);
+ if (glewExperimental || GLEW_ANGLE_timer_query) CONST_CAST(GLEW_ANGLE_timer_query) = !_glewInit_GL_ANGLE_timer_query(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_ANGLE_timer_query */
+#ifdef GL_ANGLE_translated_shader_source
+ CONST_CAST(GLEW_ANGLE_translated_shader_source) = _glewSearchExtension("GL_ANGLE_translated_shader_source", extStart, extEnd);
+ if (glewExperimental || GLEW_ANGLE_translated_shader_source) CONST_CAST(GLEW_ANGLE_translated_shader_source) = !_glewInit_GL_ANGLE_translated_shader_source(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_ANGLE_translated_shader_source */
#ifdef GL_APPLE_aux_depth_stencil
CONST_CAST(GLEW_APPLE_aux_depth_stencil) = _glewSearchExtension("GL_APPLE_aux_depth_stencil", extStart, extEnd);
#endif /* GL_APPLE_aux_depth_stencil */
@@ -8574,18 +9771,40 @@ GLenum glewContextInit (GLEW_CONTEXT_ARG_DEF_LIST)
CONST_CAST(GLEW_ARB_ES2_compatibility) = _glewSearchExtension("GL_ARB_ES2_compatibility", extStart, extEnd);
if (glewExperimental || GLEW_ARB_ES2_compatibility) CONST_CAST(GLEW_ARB_ES2_compatibility) = !_glewInit_GL_ARB_ES2_compatibility(GLEW_CONTEXT_ARG_VAR_INIT);
#endif /* GL_ARB_ES2_compatibility */
+#ifdef GL_ARB_ES3_compatibility
+ CONST_CAST(GLEW_ARB_ES3_compatibility) = _glewSearchExtension("GL_ARB_ES3_compatibility", extStart, extEnd);
+#endif /* GL_ARB_ES3_compatibility */
+#ifdef GL_ARB_arrays_of_arrays
+ CONST_CAST(GLEW_ARB_arrays_of_arrays) = _glewSearchExtension("GL_ARB_arrays_of_arrays", extStart, extEnd);
+#endif /* GL_ARB_arrays_of_arrays */
#ifdef GL_ARB_base_instance
CONST_CAST(GLEW_ARB_base_instance) = _glewSearchExtension("GL_ARB_base_instance", extStart, extEnd);
if (glewExperimental || GLEW_ARB_base_instance) CONST_CAST(GLEW_ARB_base_instance) = !_glewInit_GL_ARB_base_instance(GLEW_CONTEXT_ARG_VAR_INIT);
#endif /* GL_ARB_base_instance */
+#ifdef GL_ARB_bindless_texture
+ CONST_CAST(GLEW_ARB_bindless_texture) = _glewSearchExtension("GL_ARB_bindless_texture", extStart, extEnd);
+ if (glewExperimental || GLEW_ARB_bindless_texture) CONST_CAST(GLEW_ARB_bindless_texture) = !_glewInit_GL_ARB_bindless_texture(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_ARB_bindless_texture */
#ifdef GL_ARB_blend_func_extended
CONST_CAST(GLEW_ARB_blend_func_extended) = _glewSearchExtension("GL_ARB_blend_func_extended", extStart, extEnd);
if (glewExperimental || GLEW_ARB_blend_func_extended) CONST_CAST(GLEW_ARB_blend_func_extended) = !_glewInit_GL_ARB_blend_func_extended(GLEW_CONTEXT_ARG_VAR_INIT);
#endif /* GL_ARB_blend_func_extended */
+#ifdef GL_ARB_buffer_storage
+ CONST_CAST(GLEW_ARB_buffer_storage) = _glewSearchExtension("GL_ARB_buffer_storage", extStart, extEnd);
+ if (glewExperimental || GLEW_ARB_buffer_storage) CONST_CAST(GLEW_ARB_buffer_storage) = !_glewInit_GL_ARB_buffer_storage(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_ARB_buffer_storage */
#ifdef GL_ARB_cl_event
CONST_CAST(GLEW_ARB_cl_event) = _glewSearchExtension("GL_ARB_cl_event", extStart, extEnd);
if (glewExperimental || GLEW_ARB_cl_event) CONST_CAST(GLEW_ARB_cl_event) = !_glewInit_GL_ARB_cl_event(GLEW_CONTEXT_ARG_VAR_INIT);
#endif /* GL_ARB_cl_event */
+#ifdef GL_ARB_clear_buffer_object
+ CONST_CAST(GLEW_ARB_clear_buffer_object) = _glewSearchExtension("GL_ARB_clear_buffer_object", extStart, extEnd);
+ if (glewExperimental || GLEW_ARB_clear_buffer_object) CONST_CAST(GLEW_ARB_clear_buffer_object) = !_glewInit_GL_ARB_clear_buffer_object(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_ARB_clear_buffer_object */
+#ifdef GL_ARB_clear_texture
+ CONST_CAST(GLEW_ARB_clear_texture) = _glewSearchExtension("GL_ARB_clear_texture", extStart, extEnd);
+ if (glewExperimental || GLEW_ARB_clear_texture) CONST_CAST(GLEW_ARB_clear_texture) = !_glewInit_GL_ARB_clear_texture(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_ARB_clear_texture */
#ifdef GL_ARB_color_buffer_float
CONST_CAST(GLEW_ARB_color_buffer_float) = _glewSearchExtension("GL_ARB_color_buffer_float", extStart, extEnd);
if (glewExperimental || GLEW_ARB_color_buffer_float) CONST_CAST(GLEW_ARB_color_buffer_float) = !_glewInit_GL_ARB_color_buffer_float(GLEW_CONTEXT_ARG_VAR_INIT);
@@ -8596,6 +9815,14 @@ GLenum glewContextInit (GLEW_CONTEXT_ARG_DEF_LIST)
#ifdef GL_ARB_compressed_texture_pixel_storage
CONST_CAST(GLEW_ARB_compressed_texture_pixel_storage) = _glewSearchExtension("GL_ARB_compressed_texture_pixel_storage", extStart, extEnd);
#endif /* GL_ARB_compressed_texture_pixel_storage */
+#ifdef GL_ARB_compute_shader
+ CONST_CAST(GLEW_ARB_compute_shader) = _glewSearchExtension("GL_ARB_compute_shader", extStart, extEnd);
+ if (glewExperimental || GLEW_ARB_compute_shader) CONST_CAST(GLEW_ARB_compute_shader) = !_glewInit_GL_ARB_compute_shader(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_ARB_compute_shader */
+#ifdef GL_ARB_compute_variable_group_size
+ CONST_CAST(GLEW_ARB_compute_variable_group_size) = _glewSearchExtension("GL_ARB_compute_variable_group_size", extStart, extEnd);
+ if (glewExperimental || GLEW_ARB_compute_variable_group_size) CONST_CAST(GLEW_ARB_compute_variable_group_size) = !_glewInit_GL_ARB_compute_variable_group_size(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_ARB_compute_variable_group_size */
#ifdef GL_ARB_conservative_depth
CONST_CAST(GLEW_ARB_conservative_depth) = _glewSearchExtension("GL_ARB_conservative_depth", extStart, extEnd);
#endif /* GL_ARB_conservative_depth */
@@ -8603,6 +9830,10 @@ GLenum glewContextInit (GLEW_CONTEXT_ARG_DEF_LIST)
CONST_CAST(GLEW_ARB_copy_buffer) = _glewSearchExtension("GL_ARB_copy_buffer", extStart, extEnd);
if (glewExperimental || GLEW_ARB_copy_buffer) CONST_CAST(GLEW_ARB_copy_buffer) = !_glewInit_GL_ARB_copy_buffer(GLEW_CONTEXT_ARG_VAR_INIT);
#endif /* GL_ARB_copy_buffer */
+#ifdef GL_ARB_copy_image
+ CONST_CAST(GLEW_ARB_copy_image) = _glewSearchExtension("GL_ARB_copy_image", extStart, extEnd);
+ if (glewExperimental || GLEW_ARB_copy_image) CONST_CAST(GLEW_ARB_copy_image) = !_glewInit_GL_ARB_copy_image(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_ARB_copy_image */
#ifdef GL_ARB_debug_output
CONST_CAST(GLEW_ARB_debug_output) = _glewSearchExtension("GL_ARB_debug_output", extStart, extEnd);
if (glewExperimental || GLEW_ARB_debug_output) CONST_CAST(GLEW_ARB_debug_output) = !_glewInit_GL_ARB_debug_output(GLEW_CONTEXT_ARG_VAR_INIT);
@@ -8635,12 +9866,21 @@ GLenum glewContextInit (GLEW_CONTEXT_ARG_DEF_LIST)
#ifdef GL_ARB_draw_instanced
CONST_CAST(GLEW_ARB_draw_instanced) = _glewSearchExtension("GL_ARB_draw_instanced", extStart, extEnd);
#endif /* GL_ARB_draw_instanced */
+#ifdef GL_ARB_enhanced_layouts
+ CONST_CAST(GLEW_ARB_enhanced_layouts) = _glewSearchExtension("GL_ARB_enhanced_layouts", extStart, extEnd);
+#endif /* GL_ARB_enhanced_layouts */
#ifdef GL_ARB_explicit_attrib_location
CONST_CAST(GLEW_ARB_explicit_attrib_location) = _glewSearchExtension("GL_ARB_explicit_attrib_location", extStart, extEnd);
#endif /* GL_ARB_explicit_attrib_location */
+#ifdef GL_ARB_explicit_uniform_location
+ CONST_CAST(GLEW_ARB_explicit_uniform_location) = _glewSearchExtension("GL_ARB_explicit_uniform_location", extStart, extEnd);
+#endif /* GL_ARB_explicit_uniform_location */
#ifdef GL_ARB_fragment_coord_conventions
CONST_CAST(GLEW_ARB_fragment_coord_conventions) = _glewSearchExtension("GL_ARB_fragment_coord_conventions", extStart, extEnd);
#endif /* GL_ARB_fragment_coord_conventions */
+#ifdef GL_ARB_fragment_layer_viewport
+ CONST_CAST(GLEW_ARB_fragment_layer_viewport) = _glewSearchExtension("GL_ARB_fragment_layer_viewport", extStart, extEnd);
+#endif /* GL_ARB_fragment_layer_viewport */
#ifdef GL_ARB_fragment_program
CONST_CAST(GLEW_ARB_fragment_program) = _glewSearchExtension("GL_ARB_fragment_program", extStart, extEnd);
#endif /* GL_ARB_fragment_program */
@@ -8650,6 +9890,10 @@ GLenum glewContextInit (GLEW_CONTEXT_ARG_DEF_LIST)
#ifdef GL_ARB_fragment_shader
CONST_CAST(GLEW_ARB_fragment_shader) = _glewSearchExtension("GL_ARB_fragment_shader", extStart, extEnd);
#endif /* GL_ARB_fragment_shader */
+#ifdef GL_ARB_framebuffer_no_attachments
+ CONST_CAST(GLEW_ARB_framebuffer_no_attachments) = _glewSearchExtension("GL_ARB_framebuffer_no_attachments", extStart, extEnd);
+ if (glewExperimental || GLEW_ARB_framebuffer_no_attachments) CONST_CAST(GLEW_ARB_framebuffer_no_attachments) = !_glewInit_GL_ARB_framebuffer_no_attachments(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_ARB_framebuffer_no_attachments */
#ifdef GL_ARB_framebuffer_object
CONST_CAST(GLEW_ARB_framebuffer_object) = _glewSearchExtension("GL_ARB_framebuffer_object", extStart, extEnd);
if (glewExperimental || GLEW_ARB_framebuffer_object) CONST_CAST(GLEW_ARB_framebuffer_object) = !_glewInit_GL_ARB_framebuffer_object(GLEW_CONTEXT_ARG_VAR_INIT);
@@ -8682,6 +9926,10 @@ GLenum glewContextInit (GLEW_CONTEXT_ARG_DEF_LIST)
CONST_CAST(GLEW_ARB_imaging) = _glewSearchExtension("GL_ARB_imaging", extStart, extEnd);
if (glewExperimental || GLEW_ARB_imaging) CONST_CAST(GLEW_ARB_imaging) = !_glewInit_GL_ARB_imaging(GLEW_CONTEXT_ARG_VAR_INIT);
#endif /* GL_ARB_imaging */
+#ifdef GL_ARB_indirect_parameters
+ CONST_CAST(GLEW_ARB_indirect_parameters) = _glewSearchExtension("GL_ARB_indirect_parameters", extStart, extEnd);
+ if (glewExperimental || GLEW_ARB_indirect_parameters) CONST_CAST(GLEW_ARB_indirect_parameters) = !_glewInit_GL_ARB_indirect_parameters(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_ARB_indirect_parameters */
#ifdef GL_ARB_instanced_arrays
CONST_CAST(GLEW_ARB_instanced_arrays) = _glewSearchExtension("GL_ARB_instanced_arrays", extStart, extEnd);
if (glewExperimental || GLEW_ARB_instanced_arrays) CONST_CAST(GLEW_ARB_instanced_arrays) = !_glewInit_GL_ARB_instanced_arrays(GLEW_CONTEXT_ARG_VAR_INIT);
@@ -8690,6 +9938,14 @@ GLenum glewContextInit (GLEW_CONTEXT_ARG_DEF_LIST)
CONST_CAST(GLEW_ARB_internalformat_query) = _glewSearchExtension("GL_ARB_internalformat_query", extStart, extEnd);
if (glewExperimental || GLEW_ARB_internalformat_query) CONST_CAST(GLEW_ARB_internalformat_query) = !_glewInit_GL_ARB_internalformat_query(GLEW_CONTEXT_ARG_VAR_INIT);
#endif /* GL_ARB_internalformat_query */
+#ifdef GL_ARB_internalformat_query2
+ CONST_CAST(GLEW_ARB_internalformat_query2) = _glewSearchExtension("GL_ARB_internalformat_query2", extStart, extEnd);
+ if (glewExperimental || GLEW_ARB_internalformat_query2) CONST_CAST(GLEW_ARB_internalformat_query2) = !_glewInit_GL_ARB_internalformat_query2(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_ARB_internalformat_query2 */
+#ifdef GL_ARB_invalidate_subdata
+ CONST_CAST(GLEW_ARB_invalidate_subdata) = _glewSearchExtension("GL_ARB_invalidate_subdata", extStart, extEnd);
+ if (glewExperimental || GLEW_ARB_invalidate_subdata) CONST_CAST(GLEW_ARB_invalidate_subdata) = !_glewInit_GL_ARB_invalidate_subdata(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_ARB_invalidate_subdata */
#ifdef GL_ARB_map_buffer_alignment
CONST_CAST(GLEW_ARB_map_buffer_alignment) = _glewSearchExtension("GL_ARB_map_buffer_alignment", extStart, extEnd);
#endif /* GL_ARB_map_buffer_alignment */
@@ -8701,6 +9957,14 @@ GLenum glewContextInit (GLEW_CONTEXT_ARG_DEF_LIST)
CONST_CAST(GLEW_ARB_matrix_palette) = _glewSearchExtension("GL_ARB_matrix_palette", extStart, extEnd);
if (glewExperimental || GLEW_ARB_matrix_palette) CONST_CAST(GLEW_ARB_matrix_palette) = !_glewInit_GL_ARB_matrix_palette(GLEW_CONTEXT_ARG_VAR_INIT);
#endif /* GL_ARB_matrix_palette */
+#ifdef GL_ARB_multi_bind
+ CONST_CAST(GLEW_ARB_multi_bind) = _glewSearchExtension("GL_ARB_multi_bind", extStart, extEnd);
+ if (glewExperimental || GLEW_ARB_multi_bind) CONST_CAST(GLEW_ARB_multi_bind) = !_glewInit_GL_ARB_multi_bind(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_ARB_multi_bind */
+#ifdef GL_ARB_multi_draw_indirect
+ CONST_CAST(GLEW_ARB_multi_draw_indirect) = _glewSearchExtension("GL_ARB_multi_draw_indirect", extStart, extEnd);
+ if (glewExperimental || GLEW_ARB_multi_draw_indirect) CONST_CAST(GLEW_ARB_multi_draw_indirect) = !_glewInit_GL_ARB_multi_draw_indirect(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_ARB_multi_draw_indirect */
#ifdef GL_ARB_multisample
CONST_CAST(GLEW_ARB_multisample) = _glewSearchExtension("GL_ARB_multisample", extStart, extEnd);
if (glewExperimental || GLEW_ARB_multisample) CONST_CAST(GLEW_ARB_multisample) = !_glewInit_GL_ARB_multisample(GLEW_CONTEXT_ARG_VAR_INIT);
@@ -8726,14 +9990,30 @@ GLenum glewContextInit (GLEW_CONTEXT_ARG_DEF_LIST)
#ifdef GL_ARB_point_sprite
CONST_CAST(GLEW_ARB_point_sprite) = _glewSearchExtension("GL_ARB_point_sprite", extStart, extEnd);
#endif /* GL_ARB_point_sprite */
+#ifdef GL_ARB_program_interface_query
+ CONST_CAST(GLEW_ARB_program_interface_query) = _glewSearchExtension("GL_ARB_program_interface_query", extStart, extEnd);
+ if (glewExperimental || GLEW_ARB_program_interface_query) CONST_CAST(GLEW_ARB_program_interface_query) = !_glewInit_GL_ARB_program_interface_query(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_ARB_program_interface_query */
#ifdef GL_ARB_provoking_vertex
CONST_CAST(GLEW_ARB_provoking_vertex) = _glewSearchExtension("GL_ARB_provoking_vertex", extStart, extEnd);
if (glewExperimental || GLEW_ARB_provoking_vertex) CONST_CAST(GLEW_ARB_provoking_vertex) = !_glewInit_GL_ARB_provoking_vertex(GLEW_CONTEXT_ARG_VAR_INIT);
#endif /* GL_ARB_provoking_vertex */
+#ifdef GL_ARB_query_buffer_object
+ CONST_CAST(GLEW_ARB_query_buffer_object) = _glewSearchExtension("GL_ARB_query_buffer_object", extStart, extEnd);
+#endif /* GL_ARB_query_buffer_object */
+#ifdef GL_ARB_robust_buffer_access_behavior
+ CONST_CAST(GLEW_ARB_robust_buffer_access_behavior) = _glewSearchExtension("GL_ARB_robust_buffer_access_behavior", extStart, extEnd);
+#endif /* GL_ARB_robust_buffer_access_behavior */
#ifdef GL_ARB_robustness
CONST_CAST(GLEW_ARB_robustness) = _glewSearchExtension("GL_ARB_robustness", extStart, extEnd);
if (glewExperimental || GLEW_ARB_robustness) CONST_CAST(GLEW_ARB_robustness) = !_glewInit_GL_ARB_robustness(GLEW_CONTEXT_ARG_VAR_INIT);
#endif /* GL_ARB_robustness */
+#ifdef GL_ARB_robustness_application_isolation
+ CONST_CAST(GLEW_ARB_robustness_application_isolation) = _glewSearchExtension("GL_ARB_robustness_application_isolation", extStart, extEnd);
+#endif /* GL_ARB_robustness_application_isolation */
+#ifdef GL_ARB_robustness_share_group_isolation
+ CONST_CAST(GLEW_ARB_robustness_share_group_isolation) = _glewSearchExtension("GL_ARB_robustness_share_group_isolation", extStart, extEnd);
+#endif /* GL_ARB_robustness_share_group_isolation */
#ifdef GL_ARB_sample_shading
CONST_CAST(GLEW_ARB_sample_shading) = _glewSearchExtension("GL_ARB_sample_shading", extStart, extEnd);
if (glewExperimental || GLEW_ARB_sample_shading) CONST_CAST(GLEW_ARB_sample_shading) = !_glewInit_GL_ARB_sample_shading(GLEW_CONTEXT_ARG_VAR_INIT);
@@ -8745,6 +10025,9 @@ GLenum glewContextInit (GLEW_CONTEXT_ARG_DEF_LIST)
#ifdef GL_ARB_seamless_cube_map
CONST_CAST(GLEW_ARB_seamless_cube_map) = _glewSearchExtension("GL_ARB_seamless_cube_map", extStart, extEnd);
#endif /* GL_ARB_seamless_cube_map */
+#ifdef GL_ARB_seamless_cubemap_per_texture
+ CONST_CAST(GLEW_ARB_seamless_cubemap_per_texture) = _glewSearchExtension("GL_ARB_seamless_cubemap_per_texture", extStart, extEnd);
+#endif /* GL_ARB_seamless_cubemap_per_texture */
#ifdef GL_ARB_separate_shader_objects
CONST_CAST(GLEW_ARB_separate_shader_objects) = _glewSearchExtension("GL_ARB_separate_shader_objects", extStart, extEnd);
if (glewExperimental || GLEW_ARB_separate_shader_objects) CONST_CAST(GLEW_ARB_separate_shader_objects) = !_glewInit_GL_ARB_separate_shader_objects(GLEW_CONTEXT_ARG_VAR_INIT);
@@ -8756,10 +10039,19 @@ GLenum glewContextInit (GLEW_CONTEXT_ARG_DEF_LIST)
#ifdef GL_ARB_shader_bit_encoding
CONST_CAST(GLEW_ARB_shader_bit_encoding) = _glewSearchExtension("GL_ARB_shader_bit_encoding", extStart, extEnd);
#endif /* GL_ARB_shader_bit_encoding */
+#ifdef GL_ARB_shader_draw_parameters
+ CONST_CAST(GLEW_ARB_shader_draw_parameters) = _glewSearchExtension("GL_ARB_shader_draw_parameters", extStart, extEnd);
+#endif /* GL_ARB_shader_draw_parameters */
+#ifdef GL_ARB_shader_group_vote
+ CONST_CAST(GLEW_ARB_shader_group_vote) = _glewSearchExtension("GL_ARB_shader_group_vote", extStart, extEnd);
+#endif /* GL_ARB_shader_group_vote */
#ifdef GL_ARB_shader_image_load_store
CONST_CAST(GLEW_ARB_shader_image_load_store) = _glewSearchExtension("GL_ARB_shader_image_load_store", extStart, extEnd);
if (glewExperimental || GLEW_ARB_shader_image_load_store) CONST_CAST(GLEW_ARB_shader_image_load_store) = !_glewInit_GL_ARB_shader_image_load_store(GLEW_CONTEXT_ARG_VAR_INIT);
#endif /* GL_ARB_shader_image_load_store */
+#ifdef GL_ARB_shader_image_size
+ CONST_CAST(GLEW_ARB_shader_image_size) = _glewSearchExtension("GL_ARB_shader_image_size", extStart, extEnd);
+#endif /* GL_ARB_shader_image_size */
#ifdef GL_ARB_shader_objects
CONST_CAST(GLEW_ARB_shader_objects) = _glewSearchExtension("GL_ARB_shader_objects", extStart, extEnd);
if (glewExperimental || GLEW_ARB_shader_objects) CONST_CAST(GLEW_ARB_shader_objects) = !_glewInit_GL_ARB_shader_objects(GLEW_CONTEXT_ARG_VAR_INIT);
@@ -8770,6 +10062,10 @@ GLenum glewContextInit (GLEW_CONTEXT_ARG_DEF_LIST)
#ifdef GL_ARB_shader_stencil_export
CONST_CAST(GLEW_ARB_shader_stencil_export) = _glewSearchExtension("GL_ARB_shader_stencil_export", extStart, extEnd);
#endif /* GL_ARB_shader_stencil_export */
+#ifdef GL_ARB_shader_storage_buffer_object
+ CONST_CAST(GLEW_ARB_shader_storage_buffer_object) = _glewSearchExtension("GL_ARB_shader_storage_buffer_object", extStart, extEnd);
+ if (glewExperimental || GLEW_ARB_shader_storage_buffer_object) CONST_CAST(GLEW_ARB_shader_storage_buffer_object) = !_glewInit_GL_ARB_shader_storage_buffer_object(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_ARB_shader_storage_buffer_object */
#ifdef GL_ARB_shader_subroutine
CONST_CAST(GLEW_ARB_shader_subroutine) = _glewSearchExtension("GL_ARB_shader_subroutine", extStart, extEnd);
if (glewExperimental || GLEW_ARB_shader_subroutine) CONST_CAST(GLEW_ARB_shader_subroutine) = !_glewInit_GL_ARB_shader_subroutine(GLEW_CONTEXT_ARG_VAR_INIT);
@@ -8796,6 +10092,13 @@ GLenum glewContextInit (GLEW_CONTEXT_ARG_DEF_LIST)
#ifdef GL_ARB_shadow_ambient
CONST_CAST(GLEW_ARB_shadow_ambient) = _glewSearchExtension("GL_ARB_shadow_ambient", extStart, extEnd);
#endif /* GL_ARB_shadow_ambient */
+#ifdef GL_ARB_sparse_texture
+ CONST_CAST(GLEW_ARB_sparse_texture) = _glewSearchExtension("GL_ARB_sparse_texture", extStart, extEnd);
+ if (glewExperimental || GLEW_ARB_sparse_texture) CONST_CAST(GLEW_ARB_sparse_texture) = !_glewInit_GL_ARB_sparse_texture(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_ARB_sparse_texture */
+#ifdef GL_ARB_stencil_texturing
+ CONST_CAST(GLEW_ARB_stencil_texturing) = _glewSearchExtension("GL_ARB_stencil_texturing", extStart, extEnd);
+#endif /* GL_ARB_stencil_texturing */
#ifdef GL_ARB_sync
CONST_CAST(GLEW_ARB_sync) = _glewSearchExtension("GL_ARB_sync", extStart, extEnd);
if (glewExperimental || GLEW_ARB_sync) CONST_CAST(GLEW_ARB_sync) = !_glewInit_GL_ARB_sync(GLEW_CONTEXT_ARG_VAR_INIT);
@@ -8814,6 +10117,10 @@ GLenum glewContextInit (GLEW_CONTEXT_ARG_DEF_LIST)
#ifdef GL_ARB_texture_buffer_object_rgb32
CONST_CAST(GLEW_ARB_texture_buffer_object_rgb32) = _glewSearchExtension("GL_ARB_texture_buffer_object_rgb32", extStart, extEnd);
#endif /* GL_ARB_texture_buffer_object_rgb32 */
+#ifdef GL_ARB_texture_buffer_range
+ CONST_CAST(GLEW_ARB_texture_buffer_range) = _glewSearchExtension("GL_ARB_texture_buffer_range", extStart, extEnd);
+ if (glewExperimental || GLEW_ARB_texture_buffer_range) CONST_CAST(GLEW_ARB_texture_buffer_range) = !_glewInit_GL_ARB_texture_buffer_range(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_ARB_texture_buffer_range */
#ifdef GL_ARB_texture_compression
CONST_CAST(GLEW_ARB_texture_compression) = _glewSearchExtension("GL_ARB_texture_compression", extStart, extEnd);
if (glewExperimental || GLEW_ARB_texture_compression) CONST_CAST(GLEW_ARB_texture_compression) = !_glewInit_GL_ARB_texture_compression(GLEW_CONTEXT_ARG_VAR_INIT);
@@ -8848,6 +10155,9 @@ GLenum glewContextInit (GLEW_CONTEXT_ARG_DEF_LIST)
#ifdef GL_ARB_texture_gather
CONST_CAST(GLEW_ARB_texture_gather) = _glewSearchExtension("GL_ARB_texture_gather", extStart, extEnd);
#endif /* GL_ARB_texture_gather */
+#ifdef GL_ARB_texture_mirror_clamp_to_edge
+ CONST_CAST(GLEW_ARB_texture_mirror_clamp_to_edge) = _glewSearchExtension("GL_ARB_texture_mirror_clamp_to_edge", extStart, extEnd);
+#endif /* GL_ARB_texture_mirror_clamp_to_edge */
#ifdef GL_ARB_texture_mirrored_repeat
CONST_CAST(GLEW_ARB_texture_mirrored_repeat) = _glewSearchExtension("GL_ARB_texture_mirrored_repeat", extStart, extEnd);
#endif /* GL_ARB_texture_mirrored_repeat */
@@ -8858,6 +10168,9 @@ GLenum glewContextInit (GLEW_CONTEXT_ARG_DEF_LIST)
#ifdef GL_ARB_texture_non_power_of_two
CONST_CAST(GLEW_ARB_texture_non_power_of_two) = _glewSearchExtension("GL_ARB_texture_non_power_of_two", extStart, extEnd);
#endif /* GL_ARB_texture_non_power_of_two */
+#ifdef GL_ARB_texture_query_levels
+ CONST_CAST(GLEW_ARB_texture_query_levels) = _glewSearchExtension("GL_ARB_texture_query_levels", extStart, extEnd);
+#endif /* GL_ARB_texture_query_levels */
#ifdef GL_ARB_texture_query_lod
CONST_CAST(GLEW_ARB_texture_query_lod) = _glewSearchExtension("GL_ARB_texture_query_lod", extStart, extEnd);
#endif /* GL_ARB_texture_query_lod */
@@ -8870,13 +10183,24 @@ GLenum glewContextInit (GLEW_CONTEXT_ARG_DEF_LIST)
#ifdef GL_ARB_texture_rgb10_a2ui
CONST_CAST(GLEW_ARB_texture_rgb10_a2ui) = _glewSearchExtension("GL_ARB_texture_rgb10_a2ui", extStart, extEnd);
#endif /* GL_ARB_texture_rgb10_a2ui */
+#ifdef GL_ARB_texture_stencil8
+ CONST_CAST(GLEW_ARB_texture_stencil8) = _glewSearchExtension("GL_ARB_texture_stencil8", extStart, extEnd);
+#endif /* GL_ARB_texture_stencil8 */
#ifdef GL_ARB_texture_storage
CONST_CAST(GLEW_ARB_texture_storage) = _glewSearchExtension("GL_ARB_texture_storage", extStart, extEnd);
if (glewExperimental || GLEW_ARB_texture_storage) CONST_CAST(GLEW_ARB_texture_storage) = !_glewInit_GL_ARB_texture_storage(GLEW_CONTEXT_ARG_VAR_INIT);
#endif /* GL_ARB_texture_storage */
+#ifdef GL_ARB_texture_storage_multisample
+ CONST_CAST(GLEW_ARB_texture_storage_multisample) = _glewSearchExtension("GL_ARB_texture_storage_multisample", extStart, extEnd);
+ if (glewExperimental || GLEW_ARB_texture_storage_multisample) CONST_CAST(GLEW_ARB_texture_storage_multisample) = !_glewInit_GL_ARB_texture_storage_multisample(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_ARB_texture_storage_multisample */
#ifdef GL_ARB_texture_swizzle
CONST_CAST(GLEW_ARB_texture_swizzle) = _glewSearchExtension("GL_ARB_texture_swizzle", extStart, extEnd);
#endif /* GL_ARB_texture_swizzle */
+#ifdef GL_ARB_texture_view
+ CONST_CAST(GLEW_ARB_texture_view) = _glewSearchExtension("GL_ARB_texture_view", extStart, extEnd);
+ if (glewExperimental || GLEW_ARB_texture_view) CONST_CAST(GLEW_ARB_texture_view) = !_glewInit_GL_ARB_texture_view(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_ARB_texture_view */
#ifdef GL_ARB_timer_query
CONST_CAST(GLEW_ARB_timer_query) = _glewSearchExtension("GL_ARB_timer_query", extStart, extEnd);
if (glewExperimental || GLEW_ARB_timer_query) CONST_CAST(GLEW_ARB_timer_query) = !_glewInit_GL_ARB_timer_query(GLEW_CONTEXT_ARG_VAR_INIT);
@@ -8912,6 +10236,10 @@ GLenum glewContextInit (GLEW_CONTEXT_ARG_DEF_LIST)
CONST_CAST(GLEW_ARB_vertex_attrib_64bit) = _glewSearchExtension("GL_ARB_vertex_attrib_64bit", extStart, extEnd);
if (glewExperimental || GLEW_ARB_vertex_attrib_64bit) CONST_CAST(GLEW_ARB_vertex_attrib_64bit) = !_glewInit_GL_ARB_vertex_attrib_64bit(GLEW_CONTEXT_ARG_VAR_INIT);
#endif /* GL_ARB_vertex_attrib_64bit */
+#ifdef GL_ARB_vertex_attrib_binding
+ CONST_CAST(GLEW_ARB_vertex_attrib_binding) = _glewSearchExtension("GL_ARB_vertex_attrib_binding", extStart, extEnd);
+ if (glewExperimental || GLEW_ARB_vertex_attrib_binding) CONST_CAST(GLEW_ARB_vertex_attrib_binding) = !_glewInit_GL_ARB_vertex_attrib_binding(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_ARB_vertex_attrib_binding */
#ifdef GL_ARB_vertex_blend
CONST_CAST(GLEW_ARB_vertex_blend) = _glewSearchExtension("GL_ARB_vertex_blend", extStart, extEnd);
if (glewExperimental || GLEW_ARB_vertex_blend) CONST_CAST(GLEW_ARB_vertex_blend) = !_glewInit_GL_ARB_vertex_blend(GLEW_CONTEXT_ARG_VAR_INIT);
@@ -8928,6 +10256,9 @@ GLenum glewContextInit (GLEW_CONTEXT_ARG_DEF_LIST)
CONST_CAST(GLEW_ARB_vertex_shader) = _glewSearchExtension("GL_ARB_vertex_shader", extStart, extEnd);
if (glewExperimental || GLEW_ARB_vertex_shader) CONST_CAST(GLEW_ARB_vertex_shader) = !_glewInit_GL_ARB_vertex_shader(GLEW_CONTEXT_ARG_VAR_INIT);
#endif /* GL_ARB_vertex_shader */
+#ifdef GL_ARB_vertex_type_10f_11f_11f_rev
+ CONST_CAST(GLEW_ARB_vertex_type_10f_11f_11f_rev) = _glewSearchExtension("GL_ARB_vertex_type_10f_11f_11f_rev", extStart, extEnd);
+#endif /* GL_ARB_vertex_type_10f_11f_11f_rev */
#ifdef GL_ARB_vertex_type_2_10_10_10_rev
CONST_CAST(GLEW_ARB_vertex_type_2_10_10_10_rev) = _glewSearchExtension("GL_ARB_vertex_type_2_10_10_10_rev", extStart, extEnd);
if (glewExperimental || GLEW_ARB_vertex_type_2_10_10_10_rev) CONST_CAST(GLEW_ARB_vertex_type_2_10_10_10_rev) = !_glewInit_GL_ARB_vertex_type_2_10_10_10_rev(GLEW_CONTEXT_ARG_VAR_INIT);
@@ -9081,6 +10412,10 @@ GLenum glewContextInit (GLEW_CONTEXT_ARG_DEF_LIST)
CONST_CAST(GLEW_EXT_cull_vertex) = _glewSearchExtension("GL_EXT_cull_vertex", extStart, extEnd);
if (glewExperimental || GLEW_EXT_cull_vertex) CONST_CAST(GLEW_EXT_cull_vertex) = !_glewInit_GL_EXT_cull_vertex(GLEW_CONTEXT_ARG_VAR_INIT);
#endif /* GL_EXT_cull_vertex */
+#ifdef GL_EXT_debug_marker
+ CONST_CAST(GLEW_EXT_debug_marker) = _glewSearchExtension("GL_EXT_debug_marker", extStart, extEnd);
+ if (glewExperimental || GLEW_EXT_debug_marker) CONST_CAST(GLEW_EXT_debug_marker) = !_glewInit_GL_EXT_debug_marker(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_EXT_debug_marker */
#ifdef GL_EXT_depth_bounds_test
CONST_CAST(GLEW_EXT_depth_bounds_test) = _glewSearchExtension("GL_EXT_depth_bounds_test", extStart, extEnd);
if (glewExperimental || GLEW_EXT_depth_bounds_test) CONST_CAST(GLEW_EXT_depth_bounds_test) = !_glewInit_GL_EXT_depth_bounds_test(GLEW_CONTEXT_ARG_VAR_INIT);
@@ -9411,6 +10746,10 @@ GLenum glewContextInit (GLEW_CONTEXT_ARG_DEF_LIST)
#ifdef GL_INGR_interlace_read
CONST_CAST(GLEW_INGR_interlace_read) = _glewSearchExtension("GL_INGR_interlace_read", extStart, extEnd);
#endif /* GL_INGR_interlace_read */
+#ifdef GL_INTEL_map_texture
+ CONST_CAST(GLEW_INTEL_map_texture) = _glewSearchExtension("GL_INTEL_map_texture", extStart, extEnd);
+ if (glewExperimental || GLEW_INTEL_map_texture) CONST_CAST(GLEW_INTEL_map_texture) = !_glewInit_GL_INTEL_map_texture(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_INTEL_map_texture */
#ifdef GL_INTEL_parallel_arrays
CONST_CAST(GLEW_INTEL_parallel_arrays) = _glewSearchExtension("GL_INTEL_parallel_arrays", extStart, extEnd);
if (glewExperimental || GLEW_INTEL_parallel_arrays) CONST_CAST(GLEW_INTEL_parallel_arrays) = !_glewInit_GL_INTEL_parallel_arrays(GLEW_CONTEXT_ARG_VAR_INIT);
@@ -9419,6 +10758,13 @@ GLenum glewContextInit (GLEW_CONTEXT_ARG_DEF_LIST)
CONST_CAST(GLEW_INTEL_texture_scissor) = _glewSearchExtension("GL_INTEL_texture_scissor", extStart, extEnd);
if (glewExperimental || GLEW_INTEL_texture_scissor) CONST_CAST(GLEW_INTEL_texture_scissor) = !_glewInit_GL_INTEL_texture_scissor(GLEW_CONTEXT_ARG_VAR_INIT);
#endif /* GL_INTEL_texture_scissor */
+#ifdef GL_KHR_debug
+ CONST_CAST(GLEW_KHR_debug) = _glewSearchExtension("GL_KHR_debug", extStart, extEnd);
+ if (glewExperimental || GLEW_KHR_debug) CONST_CAST(GLEW_KHR_debug) = !_glewInit_GL_KHR_debug(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_KHR_debug */
+#ifdef GL_KHR_texture_compression_astc_ldr
+ CONST_CAST(GLEW_KHR_texture_compression_astc_ldr) = _glewSearchExtension("GL_KHR_texture_compression_astc_ldr", extStart, extEnd);
+#endif /* GL_KHR_texture_compression_astc_ldr */
#ifdef GL_KTX_buffer_region
CONST_CAST(GLEW_KTX_buffer_region) = _glewSearchExtension("GL_KTX_buffer_region", extStart, extEnd);
if (glewExperimental || GLEW_KTX_buffer_region) CONST_CAST(GLEW_KTX_buffer_region) = !_glewInit_GL_KTX_buffer_region(GLEW_CONTEXT_ARG_VAR_INIT);
@@ -9440,12 +10786,34 @@ GLenum glewContextInit (GLEW_CONTEXT_ARG_DEF_LIST)
#ifdef GL_MESA_ycbcr_texture
CONST_CAST(GLEW_MESA_ycbcr_texture) = _glewSearchExtension("GL_MESA_ycbcr_texture", extStart, extEnd);
#endif /* GL_MESA_ycbcr_texture */
+#ifdef GL_NVX_conditional_render
+ CONST_CAST(GLEW_NVX_conditional_render) = _glewSearchExtension("GL_NVX_conditional_render", extStart, extEnd);
+ if (glewExperimental || GLEW_NVX_conditional_render) CONST_CAST(GLEW_NVX_conditional_render) = !_glewInit_GL_NVX_conditional_render(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_NVX_conditional_render */
#ifdef GL_NVX_gpu_memory_info
CONST_CAST(GLEW_NVX_gpu_memory_info) = _glewSearchExtension("GL_NVX_gpu_memory_info", extStart, extEnd);
#endif /* GL_NVX_gpu_memory_info */
+#ifdef GL_NV_bindless_multi_draw_indirect
+ CONST_CAST(GLEW_NV_bindless_multi_draw_indirect) = _glewSearchExtension("GL_NV_bindless_multi_draw_indirect", extStart, extEnd);
+ if (glewExperimental || GLEW_NV_bindless_multi_draw_indirect) CONST_CAST(GLEW_NV_bindless_multi_draw_indirect) = !_glewInit_GL_NV_bindless_multi_draw_indirect(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_NV_bindless_multi_draw_indirect */
+#ifdef GL_NV_bindless_texture
+ CONST_CAST(GLEW_NV_bindless_texture) = _glewSearchExtension("GL_NV_bindless_texture", extStart, extEnd);
+ if (glewExperimental || GLEW_NV_bindless_texture) CONST_CAST(GLEW_NV_bindless_texture) = !_glewInit_GL_NV_bindless_texture(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_NV_bindless_texture */
+#ifdef GL_NV_blend_equation_advanced
+ CONST_CAST(GLEW_NV_blend_equation_advanced) = _glewSearchExtension("GL_NV_blend_equation_advanced", extStart, extEnd);
+ if (glewExperimental || GLEW_NV_blend_equation_advanced) CONST_CAST(GLEW_NV_blend_equation_advanced) = !_glewInit_GL_NV_blend_equation_advanced(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_NV_blend_equation_advanced */
+#ifdef GL_NV_blend_equation_advanced_coherent
+ CONST_CAST(GLEW_NV_blend_equation_advanced_coherent) = _glewSearchExtension("GL_NV_blend_equation_advanced_coherent", extStart, extEnd);
+#endif /* GL_NV_blend_equation_advanced_coherent */
#ifdef GL_NV_blend_square
CONST_CAST(GLEW_NV_blend_square) = _glewSearchExtension("GL_NV_blend_square", extStart, extEnd);
#endif /* GL_NV_blend_square */
+#ifdef GL_NV_compute_program5
+ CONST_CAST(GLEW_NV_compute_program5) = _glewSearchExtension("GL_NV_compute_program5", extStart, extEnd);
+#endif /* GL_NV_compute_program5 */
#ifdef GL_NV_conditional_render
CONST_CAST(GLEW_NV_conditional_render) = _glewSearchExtension("GL_NV_conditional_render", extStart, extEnd);
if (glewExperimental || GLEW_NV_conditional_render) CONST_CAST(GLEW_NV_conditional_render) = !_glewInit_GL_NV_conditional_render(GLEW_CONTEXT_ARG_VAR_INIT);
@@ -9457,6 +10825,9 @@ GLenum glewContextInit (GLEW_CONTEXT_ARG_DEF_LIST)
CONST_CAST(GLEW_NV_copy_image) = _glewSearchExtension("GL_NV_copy_image", extStart, extEnd);
if (glewExperimental || GLEW_NV_copy_image) CONST_CAST(GLEW_NV_copy_image) = !_glewInit_GL_NV_copy_image(GLEW_CONTEXT_ARG_VAR_INIT);
#endif /* GL_NV_copy_image */
+#ifdef GL_NV_deep_texture3D
+ CONST_CAST(GLEW_NV_deep_texture3D) = _glewSearchExtension("GL_NV_deep_texture3D", extStart, extEnd);
+#endif /* GL_NV_deep_texture3D */
#ifdef GL_NV_depth_buffer_float
CONST_CAST(GLEW_NV_depth_buffer_float) = _glewSearchExtension("GL_NV_depth_buffer_float", extStart, extEnd);
if (glewExperimental || GLEW_NV_depth_buffer_float) CONST_CAST(GLEW_NV_depth_buffer_float) = !_glewInit_GL_NV_depth_buffer_float(GLEW_CONTEXT_ARG_VAR_INIT);
@@ -9467,6 +10838,10 @@ GLenum glewContextInit (GLEW_CONTEXT_ARG_DEF_LIST)
#ifdef GL_NV_depth_range_unclamped
CONST_CAST(GLEW_NV_depth_range_unclamped) = _glewSearchExtension("GL_NV_depth_range_unclamped", extStart, extEnd);
#endif /* GL_NV_depth_range_unclamped */
+#ifdef GL_NV_draw_texture
+ CONST_CAST(GLEW_NV_draw_texture) = _glewSearchExtension("GL_NV_draw_texture", extStart, extEnd);
+ if (glewExperimental || GLEW_NV_draw_texture) CONST_CAST(GLEW_NV_draw_texture) = !_glewInit_GL_NV_draw_texture(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_NV_draw_texture */
#ifdef GL_NV_evaluators
CONST_CAST(GLEW_NV_evaluators) = _glewSearchExtension("GL_NV_evaluators", extStart, extEnd);
if (glewExperimental || GLEW_NV_evaluators) CONST_CAST(GLEW_NV_evaluators) = !_glewInit_GL_NV_evaluators(GLEW_CONTEXT_ARG_VAR_INIT);
@@ -9516,6 +10891,9 @@ GLenum glewContextInit (GLEW_CONTEXT_ARG_DEF_LIST)
#ifdef GL_NV_gpu_program5
CONST_CAST(GLEW_NV_gpu_program5) = _glewSearchExtension("GL_NV_gpu_program5", extStart, extEnd);
#endif /* GL_NV_gpu_program5 */
+#ifdef GL_NV_gpu_program5_mem_extended
+ CONST_CAST(GLEW_NV_gpu_program5_mem_extended) = _glewSearchExtension("GL_NV_gpu_program5_mem_extended", extStart, extEnd);
+#endif /* GL_NV_gpu_program5_mem_extended */
#ifdef GL_NV_gpu_program_fp64
CONST_CAST(GLEW_NV_gpu_program_fp64) = _glewSearchExtension("GL_NV_gpu_program_fp64", extStart, extEnd);
#endif /* GL_NV_gpu_program_fp64 */
@@ -9578,10 +10956,19 @@ GLenum glewContextInit (GLEW_CONTEXT_ARG_DEF_LIST)
CONST_CAST(GLEW_NV_register_combiners2) = _glewSearchExtension("GL_NV_register_combiners2", extStart, extEnd);
if (glewExperimental || GLEW_NV_register_combiners2) CONST_CAST(GLEW_NV_register_combiners2) = !_glewInit_GL_NV_register_combiners2(GLEW_CONTEXT_ARG_VAR_INIT);
#endif /* GL_NV_register_combiners2 */
+#ifdef GL_NV_shader_atomic_counters
+ CONST_CAST(GLEW_NV_shader_atomic_counters) = _glewSearchExtension("GL_NV_shader_atomic_counters", extStart, extEnd);
+#endif /* GL_NV_shader_atomic_counters */
+#ifdef GL_NV_shader_atomic_float
+ CONST_CAST(GLEW_NV_shader_atomic_float) = _glewSearchExtension("GL_NV_shader_atomic_float", extStart, extEnd);
+#endif /* GL_NV_shader_atomic_float */
#ifdef GL_NV_shader_buffer_load
CONST_CAST(GLEW_NV_shader_buffer_load) = _glewSearchExtension("GL_NV_shader_buffer_load", extStart, extEnd);
if (glewExperimental || GLEW_NV_shader_buffer_load) CONST_CAST(GLEW_NV_shader_buffer_load) = !_glewInit_GL_NV_shader_buffer_load(GLEW_CONTEXT_ARG_VAR_INIT);
#endif /* GL_NV_shader_buffer_load */
+#ifdef GL_NV_shader_storage_buffer_object
+ CONST_CAST(GLEW_NV_shader_storage_buffer_object) = _glewSearchExtension("GL_NV_shader_storage_buffer_object", extStart, extEnd);
+#endif /* GL_NV_shader_storage_buffer_object */
#ifdef GL_NV_tessellation_program5
CONST_CAST(GLEW_NV_tessellation_program5) = _glewSearchExtension("GL_NV_gpu_program5", extStart, extEnd);
#endif /* GL_NV_tessellation_program5 */
@@ -9698,6 +11085,29 @@ GLenum glewContextInit (GLEW_CONTEXT_ARG_DEF_LIST)
#ifdef GL_PGI_vertex_hints
CONST_CAST(GLEW_PGI_vertex_hints) = _glewSearchExtension("GL_PGI_vertex_hints", extStart, extEnd);
#endif /* GL_PGI_vertex_hints */
+#ifdef GL_REGAL_ES1_0_compatibility
+ CONST_CAST(GLEW_REGAL_ES1_0_compatibility) = _glewSearchExtension("GL_REGAL_ES1_0_compatibility", extStart, extEnd);
+ if (glewExperimental || GLEW_REGAL_ES1_0_compatibility) CONST_CAST(GLEW_REGAL_ES1_0_compatibility) = !_glewInit_GL_REGAL_ES1_0_compatibility(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_REGAL_ES1_0_compatibility */
+#ifdef GL_REGAL_ES1_1_compatibility
+ CONST_CAST(GLEW_REGAL_ES1_1_compatibility) = _glewSearchExtension("GL_REGAL_ES1_1_compatibility", extStart, extEnd);
+ if (glewExperimental || GLEW_REGAL_ES1_1_compatibility) CONST_CAST(GLEW_REGAL_ES1_1_compatibility) = !_glewInit_GL_REGAL_ES1_1_compatibility(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_REGAL_ES1_1_compatibility */
+#ifdef GL_REGAL_enable
+ CONST_CAST(GLEW_REGAL_enable) = _glewSearchExtension("GL_REGAL_enable", extStart, extEnd);
+#endif /* GL_REGAL_enable */
+#ifdef GL_REGAL_error_string
+ CONST_CAST(GLEW_REGAL_error_string) = _glewSearchExtension("GL_REGAL_error_string", extStart, extEnd);
+ if (glewExperimental || GLEW_REGAL_error_string) CONST_CAST(GLEW_REGAL_error_string) = !_glewInit_GL_REGAL_error_string(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_REGAL_error_string */
+#ifdef GL_REGAL_extension_query
+ CONST_CAST(GLEW_REGAL_extension_query) = _glewSearchExtension("GL_REGAL_extension_query", extStart, extEnd);
+ if (glewExperimental || GLEW_REGAL_extension_query) CONST_CAST(GLEW_REGAL_extension_query) = !_glewInit_GL_REGAL_extension_query(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_REGAL_extension_query */
+#ifdef GL_REGAL_log
+ CONST_CAST(GLEW_REGAL_log) = _glewSearchExtension("GL_REGAL_log", extStart, extEnd);
+ if (glewExperimental || GLEW_REGAL_log) CONST_CAST(GLEW_REGAL_log) = !_glewInit_GL_REGAL_log(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_REGAL_log */
#ifdef GL_REND_screen_coordinates
CONST_CAST(GLEW_REND_screen_coordinates) = _glewSearchExtension("GL_REND_screen_coordinates", extStart, extEnd);
#endif /* GL_REND_screen_coordinates */
@@ -10077,9 +11487,12 @@ GLboolean __WGLEW_ARB_pbuffer = GL_FALSE;
GLboolean __WGLEW_ARB_pixel_format = GL_FALSE;
GLboolean __WGLEW_ARB_pixel_format_float = GL_FALSE;
GLboolean __WGLEW_ARB_render_texture = GL_FALSE;
+GLboolean __WGLEW_ARB_robustness_application_isolation = GL_FALSE;
+GLboolean __WGLEW_ARB_robustness_share_group_isolation = GL_FALSE;
GLboolean __WGLEW_ATI_pixel_format_float = GL_FALSE;
GLboolean __WGLEW_ATI_render_texture_rectangle = GL_FALSE;
GLboolean __WGLEW_EXT_create_context_es2_profile = GL_FALSE;
+GLboolean __WGLEW_EXT_create_context_es_profile = GL_FALSE;
GLboolean __WGLEW_EXT_depth_float = GL_FALSE;
GLboolean __WGLEW_EXT_display_color_table = GL_FALSE;
GLboolean __WGLEW_EXT_extensions_string = GL_FALSE;
@@ -10090,6 +11503,7 @@ GLboolean __WGLEW_EXT_pbuffer = GL_FALSE;
GLboolean __WGLEW_EXT_pixel_format = GL_FALSE;
GLboolean __WGLEW_EXT_pixel_format_packed_float = GL_FALSE;
GLboolean __WGLEW_EXT_swap_control = GL_FALSE;
+GLboolean __WGLEW_EXT_swap_control_tear = GL_FALSE;
GLboolean __WGLEW_I3D_digital_video_control = GL_FALSE;
GLboolean __WGLEW_I3D_gamma = GL_FALSE;
GLboolean __WGLEW_I3D_genlock = GL_FALSE;
@@ -10097,6 +11511,7 @@ GLboolean __WGLEW_I3D_image_buffer = GL_FALSE;
GLboolean __WGLEW_I3D_swap_frame_lock = GL_FALSE;
GLboolean __WGLEW_I3D_swap_frame_usage = GL_FALSE;
GLboolean __WGLEW_NV_DX_interop = GL_FALSE;
+GLboolean __WGLEW_NV_DX_interop2 = GL_FALSE;
GLboolean __WGLEW_NV_copy_image = GL_FALSE;
GLboolean __WGLEW_NV_float_buffer = GL_FALSE;
GLboolean __WGLEW_NV_gpu_affinity = GL_FALSE;
@@ -10273,6 +11688,14 @@ static GLboolean _glewInit_WGL_ARB_render_texture (WGLEW_CONTEXT_ARG_DEF_INIT)
#endif /* WGL_ARB_render_texture */
+#ifdef WGL_ARB_robustness_application_isolation
+
+#endif /* WGL_ARB_robustness_application_isolation */
+
+#ifdef WGL_ARB_robustness_share_group_isolation
+
+#endif /* WGL_ARB_robustness_share_group_isolation */
+
#ifdef WGL_ATI_pixel_format_float
#endif /* WGL_ATI_pixel_format_float */
@@ -10285,6 +11708,10 @@ static GLboolean _glewInit_WGL_ARB_render_texture (WGLEW_CONTEXT_ARG_DEF_INIT)
#endif /* WGL_EXT_create_context_es2_profile */
+#ifdef WGL_EXT_create_context_es_profile
+
+#endif /* WGL_EXT_create_context_es_profile */
+
#ifdef WGL_EXT_depth_float
#endif /* WGL_EXT_depth_float */
@@ -10390,6 +11817,10 @@ static GLboolean _glewInit_WGL_EXT_swap_control (WGLEW_CONTEXT_ARG_DEF_INIT)
#endif /* WGL_EXT_swap_control */
+#ifdef WGL_EXT_swap_control_tear
+
+#endif /* WGL_EXT_swap_control_tear */
+
#ifdef WGL_I3D_digital_video_control
static GLboolean _glewInit_WGL_I3D_digital_video_control (WGLEW_CONTEXT_ARG_DEF_INIT)
@@ -10512,6 +11943,10 @@ static GLboolean _glewInit_WGL_NV_DX_interop (WGLEW_CONTEXT_ARG_DEF_INIT)
#endif /* WGL_NV_DX_interop */
+#ifdef WGL_NV_DX_interop2
+
+#endif /* WGL_NV_DX_interop2 */
+
#ifdef WGL_NV_copy_image
static GLboolean _glewInit_WGL_NV_copy_image (WGLEW_CONTEXT_ARG_DEF_INIT)
@@ -10663,7 +12098,7 @@ static GLboolean _glewInit_WGL_OML_sync_control (WGLEW_CONTEXT_ARG_DEF_INIT)
static PFNWGLGETEXTENSIONSSTRINGARBPROC _wglewGetExtensionsStringARB = NULL;
static PFNWGLGETEXTENSIONSSTRINGEXTPROC _wglewGetExtensionsStringEXT = NULL;
-GLboolean wglewGetExtension (const char* name)
+GLboolean GLEWAPIENTRY wglewGetExtension (const char* name)
{
const GLubyte* start;
const GLubyte* end;
@@ -10680,7 +12115,7 @@ GLboolean wglewGetExtension (const char* name)
return _glewSearchExtension(name, start, end);
}
-GLenum wglewContextInit (WGLEW_CONTEXT_ARG_DEF_LIST)
+GLenum GLEWAPIENTRY wglewContextInit (WGLEW_CONTEXT_ARG_DEF_LIST)
{
GLboolean crippled;
const GLubyte* extStart;
@@ -10753,6 +12188,12 @@ GLenum wglewContextInit (WGLEW_CONTEXT_ARG_DEF_LIST)
CONST_CAST(WGLEW_ARB_render_texture) = _glewSearchExtension("WGL_ARB_render_texture", extStart, extEnd);
if (glewExperimental || WGLEW_ARB_render_texture|| crippled) CONST_CAST(WGLEW_ARB_render_texture)= !_glewInit_WGL_ARB_render_texture(GLEW_CONTEXT_ARG_VAR_INIT);
#endif /* WGL_ARB_render_texture */
+#ifdef WGL_ARB_robustness_application_isolation
+ CONST_CAST(WGLEW_ARB_robustness_application_isolation) = _glewSearchExtension("WGL_ARB_robustness_application_isolation", extStart, extEnd);
+#endif /* WGL_ARB_robustness_application_isolation */
+#ifdef WGL_ARB_robustness_share_group_isolation
+ CONST_CAST(WGLEW_ARB_robustness_share_group_isolation) = _glewSearchExtension("WGL_ARB_robustness_share_group_isolation", extStart, extEnd);
+#endif /* WGL_ARB_robustness_share_group_isolation */
#ifdef WGL_ATI_pixel_format_float
CONST_CAST(WGLEW_ATI_pixel_format_float) = _glewSearchExtension("WGL_ATI_pixel_format_float", extStart, extEnd);
#endif /* WGL_ATI_pixel_format_float */
@@ -10762,6 +12203,9 @@ GLenum wglewContextInit (WGLEW_CONTEXT_ARG_DEF_LIST)
#ifdef WGL_EXT_create_context_es2_profile
CONST_CAST(WGLEW_EXT_create_context_es2_profile) = _glewSearchExtension("WGL_EXT_create_context_es2_profile", extStart, extEnd);
#endif /* WGL_EXT_create_context_es2_profile */
+#ifdef WGL_EXT_create_context_es_profile
+ CONST_CAST(WGLEW_EXT_create_context_es_profile) = _glewSearchExtension("WGL_EXT_create_context_es_profile", extStart, extEnd);
+#endif /* WGL_EXT_create_context_es_profile */
#ifdef WGL_EXT_depth_float
CONST_CAST(WGLEW_EXT_depth_float) = _glewSearchExtension("WGL_EXT_depth_float", extStart, extEnd);
#endif /* WGL_EXT_depth_float */
@@ -10798,6 +12242,9 @@ GLenum wglewContextInit (WGLEW_CONTEXT_ARG_DEF_LIST)
CONST_CAST(WGLEW_EXT_swap_control) = _glewSearchExtension("WGL_EXT_swap_control", extStart, extEnd);
if (glewExperimental || WGLEW_EXT_swap_control|| crippled) CONST_CAST(WGLEW_EXT_swap_control)= !_glewInit_WGL_EXT_swap_control(GLEW_CONTEXT_ARG_VAR_INIT);
#endif /* WGL_EXT_swap_control */
+#ifdef WGL_EXT_swap_control_tear
+ CONST_CAST(WGLEW_EXT_swap_control_tear) = _glewSearchExtension("WGL_EXT_swap_control_tear", extStart, extEnd);
+#endif /* WGL_EXT_swap_control_tear */
#ifdef WGL_I3D_digital_video_control
CONST_CAST(WGLEW_I3D_digital_video_control) = _glewSearchExtension("WGL_I3D_digital_video_control", extStart, extEnd);
if (glewExperimental || WGLEW_I3D_digital_video_control|| crippled) CONST_CAST(WGLEW_I3D_digital_video_control)= !_glewInit_WGL_I3D_digital_video_control(GLEW_CONTEXT_ARG_VAR_INIT);
@@ -10826,6 +12273,9 @@ GLenum wglewContextInit (WGLEW_CONTEXT_ARG_DEF_LIST)
CONST_CAST(WGLEW_NV_DX_interop) = _glewSearchExtension("WGL_NV_DX_interop", extStart, extEnd);
if (glewExperimental || WGLEW_NV_DX_interop|| crippled) CONST_CAST(WGLEW_NV_DX_interop)= !_glewInit_WGL_NV_DX_interop(GLEW_CONTEXT_ARG_VAR_INIT);
#endif /* WGL_NV_DX_interop */
+#ifdef WGL_NV_DX_interop2
+ CONST_CAST(WGLEW_NV_DX_interop2) = _glewSearchExtension("WGL_NV_DX_interop2", extStart, extEnd);
+#endif /* WGL_NV_DX_interop2 */
#ifdef WGL_NV_copy_image
CONST_CAST(WGLEW_NV_copy_image) = _glewSearchExtension("WGL_NV_copy_image", extStart, extEnd);
if (glewExperimental || WGLEW_NV_copy_image|| crippled) CONST_CAST(WGLEW_NV_copy_image)= !_glewInit_WGL_NV_copy_image(GLEW_CONTEXT_ARG_VAR_INIT);
@@ -10874,7 +12324,7 @@ GLenum wglewContextInit (WGLEW_CONTEXT_ARG_DEF_LIST)
return GLEW_OK;
}
-#elif !defined(__APPLE__) || defined(GLEW_APPLE_GLX)
+#elif !defined(__ANDROID__) && !defined(__native_client__) && (!defined(__APPLE__) || defined(GLEW_APPLE_GLX))
PFNGLXGETCURRENTDISPLAYPROC __glewXGetCurrentDisplay = NULL;
@@ -10896,6 +12346,16 @@ PFNGLXQUERYCONTEXTPROC __glewXQueryContext = NULL;
PFNGLXQUERYDRAWABLEPROC __glewXQueryDrawable = NULL;
PFNGLXSELECTEVENTPROC __glewXSelectEvent = NULL;
+PFNGLXBLITCONTEXTFRAMEBUFFERAMDPROC __glewXBlitContextFramebufferAMD = NULL;
+PFNGLXCREATEASSOCIATEDCONTEXTAMDPROC __glewXCreateAssociatedContextAMD = NULL;
+PFNGLXCREATEASSOCIATEDCONTEXTATTRIBSAMDPROC __glewXCreateAssociatedContextAttribsAMD = NULL;
+PFNGLXDELETEASSOCIATEDCONTEXTAMDPROC __glewXDeleteAssociatedContextAMD = NULL;
+PFNGLXGETCONTEXTGPUIDAMDPROC __glewXGetContextGPUIDAMD = NULL;
+PFNGLXGETCURRENTASSOCIATEDCONTEXTAMDPROC __glewXGetCurrentAssociatedContextAMD = NULL;
+PFNGLXGETGPUIDSAMDPROC __glewXGetGPUIDsAMD = NULL;
+PFNGLXGETGPUINFOAMDPROC __glewXGetGPUInfoAMD = NULL;
+PFNGLXMAKEASSOCIATEDCONTEXTCURRENTAMDPROC __glewXMakeAssociatedContextCurrentAMD = NULL;
+
PFNGLXCREATECONTEXTATTRIBSARBPROC __glewXCreateContextAttribsARB = NULL;
PFNGLXBINDTEXIMAGEATIPROC __glewXBindTexImageATI = NULL;
@@ -11023,15 +12483,20 @@ GLboolean __GLXEW_ARB_fbconfig_float = GL_FALSE;
GLboolean __GLXEW_ARB_framebuffer_sRGB = GL_FALSE;
GLboolean __GLXEW_ARB_get_proc_address = GL_FALSE;
GLboolean __GLXEW_ARB_multisample = GL_FALSE;
+GLboolean __GLXEW_ARB_robustness_application_isolation = GL_FALSE;
+GLboolean __GLXEW_ARB_robustness_share_group_isolation = GL_FALSE;
GLboolean __GLXEW_ARB_vertex_buffer_object = GL_FALSE;
GLboolean __GLXEW_ATI_pixel_format_float = GL_FALSE;
GLboolean __GLXEW_ATI_render_texture = GL_FALSE;
+GLboolean __GLXEW_EXT_buffer_age = GL_FALSE;
GLboolean __GLXEW_EXT_create_context_es2_profile = GL_FALSE;
+GLboolean __GLXEW_EXT_create_context_es_profile = GL_FALSE;
GLboolean __GLXEW_EXT_fbconfig_packed_float = GL_FALSE;
GLboolean __GLXEW_EXT_framebuffer_sRGB = GL_FALSE;
GLboolean __GLXEW_EXT_import_context = GL_FALSE;
GLboolean __GLXEW_EXT_scene_marker = GL_FALSE;
GLboolean __GLXEW_EXT_swap_control = GL_FALSE;
+GLboolean __GLXEW_EXT_swap_control_tear = GL_FALSE;
GLboolean __GLXEW_EXT_texture_from_pixmap = GL_FALSE;
GLboolean __GLXEW_EXT_visual_info = GL_FALSE;
GLboolean __GLXEW_EXT_visual_rating = GL_FALSE;
@@ -11124,6 +12589,23 @@ static GLboolean _glewInit_GLX_VERSION_1_3 (GLXEW_CONTEXT_ARG_DEF_INIT)
#ifdef GLX_AMD_gpu_association
+static GLboolean _glewInit_GLX_AMD_gpu_association (GLXEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glXBlitContextFramebufferAMD = (PFNGLXBLITCONTEXTFRAMEBUFFERAMDPROC)glewGetProcAddress((const GLubyte*)"glXBlitContextFramebufferAMD")) == NULL) || r;
+ r = ((glXCreateAssociatedContextAMD = (PFNGLXCREATEASSOCIATEDCONTEXTAMDPROC)glewGetProcAddress((const GLubyte*)"glXCreateAssociatedContextAMD")) == NULL) || r;
+ r = ((glXCreateAssociatedContextAttribsAMD = (PFNGLXCREATEASSOCIATEDCONTEXTATTRIBSAMDPROC)glewGetProcAddress((const GLubyte*)"glXCreateAssociatedContextAttribsAMD")) == NULL) || r;
+ r = ((glXDeleteAssociatedContextAMD = (PFNGLXDELETEASSOCIATEDCONTEXTAMDPROC)glewGetProcAddress((const GLubyte*)"glXDeleteAssociatedContextAMD")) == NULL) || r;
+ r = ((glXGetContextGPUIDAMD = (PFNGLXGETCONTEXTGPUIDAMDPROC)glewGetProcAddress((const GLubyte*)"glXGetContextGPUIDAMD")) == NULL) || r;
+ r = ((glXGetCurrentAssociatedContextAMD = (PFNGLXGETCURRENTASSOCIATEDCONTEXTAMDPROC)glewGetProcAddress((const GLubyte*)"glXGetCurrentAssociatedContextAMD")) == NULL) || r;
+ r = ((glXGetGPUIDsAMD = (PFNGLXGETGPUIDSAMDPROC)glewGetProcAddress((const GLubyte*)"glXGetGPUIDsAMD")) == NULL) || r;
+ r = ((glXGetGPUInfoAMD = (PFNGLXGETGPUINFOAMDPROC)glewGetProcAddress((const GLubyte*)"glXGetGPUInfoAMD")) == NULL) || r;
+ r = ((glXMakeAssociatedContextCurrentAMD = (PFNGLXMAKEASSOCIATEDCONTEXTCURRENTAMDPROC)glewGetProcAddress((const GLubyte*)"glXMakeAssociatedContextCurrentAMD")) == NULL) || r;
+
+ return r;
+}
+
#endif /* GLX_AMD_gpu_association */
#ifdef GLX_ARB_create_context
@@ -11163,6 +12645,14 @@ static GLboolean _glewInit_GLX_ARB_create_context (GLXEW_CONTEXT_ARG_DEF_INIT)
#endif /* GLX_ARB_multisample */
+#ifdef GLX_ARB_robustness_application_isolation
+
+#endif /* GLX_ARB_robustness_application_isolation */
+
+#ifdef GLX_ARB_robustness_share_group_isolation
+
+#endif /* GLX_ARB_robustness_share_group_isolation */
+
#ifdef GLX_ARB_vertex_buffer_object
#endif /* GLX_ARB_vertex_buffer_object */
@@ -11186,10 +12676,18 @@ static GLboolean _glewInit_GLX_ATI_render_texture (GLXEW_CONTEXT_ARG_DEF_INIT)
#endif /* GLX_ATI_render_texture */
+#ifdef GLX_EXT_buffer_age
+
+#endif /* GLX_EXT_buffer_age */
+
#ifdef GLX_EXT_create_context_es2_profile
#endif /* GLX_EXT_create_context_es2_profile */
+#ifdef GLX_EXT_create_context_es_profile
+
+#endif /* GLX_EXT_create_context_es_profile */
+
#ifdef GLX_EXT_fbconfig_packed_float
#endif /* GLX_EXT_fbconfig_packed_float */
@@ -11231,6 +12729,10 @@ static GLboolean _glewInit_GLX_EXT_swap_control (GLXEW_CONTEXT_ARG_DEF_INIT)
#endif /* GLX_EXT_swap_control */
+#ifdef GLX_EXT_swap_control_tear
+
+#endif /* GLX_EXT_swap_control_tear */
+
#ifdef GLX_EXT_texture_from_pixmap
static GLboolean _glewInit_GLX_EXT_texture_from_pixmap (GLXEW_CONTEXT_ARG_DEF_INIT)
@@ -11720,6 +13222,7 @@ GLenum glxewContextInit (GLXEW_CONTEXT_ARG_DEF_LIST)
#endif /* GLX_3DFX_multisample */
#ifdef GLX_AMD_gpu_association
CONST_CAST(GLXEW_AMD_gpu_association) = _glewSearchExtension("GLX_AMD_gpu_association", extStart, extEnd);
+ if (glewExperimental || GLXEW_AMD_gpu_association) CONST_CAST(GLXEW_AMD_gpu_association) = !_glewInit_GLX_AMD_gpu_association(GLEW_CONTEXT_ARG_VAR_INIT);
#endif /* GLX_AMD_gpu_association */
#ifdef GLX_ARB_create_context
CONST_CAST(GLXEW_ARB_create_context) = _glewSearchExtension("GLX_ARB_create_context", extStart, extEnd);
@@ -11743,6 +13246,12 @@ GLenum glxewContextInit (GLXEW_CONTEXT_ARG_DEF_LIST)
#ifdef GLX_ARB_multisample
CONST_CAST(GLXEW_ARB_multisample) = _glewSearchExtension("GLX_ARB_multisample", extStart, extEnd);
#endif /* GLX_ARB_multisample */
+#ifdef GLX_ARB_robustness_application_isolation
+ CONST_CAST(GLXEW_ARB_robustness_application_isolation) = _glewSearchExtension("GLX_ARB_robustness_application_isolation", extStart, extEnd);
+#endif /* GLX_ARB_robustness_application_isolation */
+#ifdef GLX_ARB_robustness_share_group_isolation
+ CONST_CAST(GLXEW_ARB_robustness_share_group_isolation) = _glewSearchExtension("GLX_ARB_robustness_share_group_isolation", extStart, extEnd);
+#endif /* GLX_ARB_robustness_share_group_isolation */
#ifdef GLX_ARB_vertex_buffer_object
CONST_CAST(GLXEW_ARB_vertex_buffer_object) = _glewSearchExtension("GLX_ARB_vertex_buffer_object", extStart, extEnd);
#endif /* GLX_ARB_vertex_buffer_object */
@@ -11753,9 +13262,15 @@ GLenum glxewContextInit (GLXEW_CONTEXT_ARG_DEF_LIST)
CONST_CAST(GLXEW_ATI_render_texture) = _glewSearchExtension("GLX_ATI_render_texture", extStart, extEnd);
if (glewExperimental || GLXEW_ATI_render_texture) CONST_CAST(GLXEW_ATI_render_texture) = !_glewInit_GLX_ATI_render_texture(GLEW_CONTEXT_ARG_VAR_INIT);
#endif /* GLX_ATI_render_texture */
+#ifdef GLX_EXT_buffer_age
+ CONST_CAST(GLXEW_EXT_buffer_age) = _glewSearchExtension("GLX_EXT_buffer_age", extStart, extEnd);
+#endif /* GLX_EXT_buffer_age */
#ifdef GLX_EXT_create_context_es2_profile
CONST_CAST(GLXEW_EXT_create_context_es2_profile) = _glewSearchExtension("GLX_EXT_create_context_es2_profile", extStart, extEnd);
#endif /* GLX_EXT_create_context_es2_profile */
+#ifdef GLX_EXT_create_context_es_profile
+ CONST_CAST(GLXEW_EXT_create_context_es_profile) = _glewSearchExtension("GLX_EXT_create_context_es_profile", extStart, extEnd);
+#endif /* GLX_EXT_create_context_es_profile */
#ifdef GLX_EXT_fbconfig_packed_float
CONST_CAST(GLXEW_EXT_fbconfig_packed_float) = _glewSearchExtension("GLX_EXT_fbconfig_packed_float", extStart, extEnd);
#endif /* GLX_EXT_fbconfig_packed_float */
@@ -11773,6 +13288,9 @@ GLenum glxewContextInit (GLXEW_CONTEXT_ARG_DEF_LIST)
CONST_CAST(GLXEW_EXT_swap_control) = _glewSearchExtension("GLX_EXT_swap_control", extStart, extEnd);
if (glewExperimental || GLXEW_EXT_swap_control) CONST_CAST(GLXEW_EXT_swap_control) = !_glewInit_GLX_EXT_swap_control(GLEW_CONTEXT_ARG_VAR_INIT);
#endif /* GLX_EXT_swap_control */
+#ifdef GLX_EXT_swap_control_tear
+ CONST_CAST(GLXEW_EXT_swap_control_tear) = _glewSearchExtension("GLX_EXT_swap_control_tear", extStart, extEnd);
+#endif /* GLX_EXT_swap_control_tear */
#ifdef GLX_EXT_texture_from_pixmap
CONST_CAST(GLXEW_EXT_texture_from_pixmap) = _glewSearchExtension("GLX_EXT_texture_from_pixmap", extStart, extEnd);
if (glewExperimental || GLXEW_EXT_texture_from_pixmap) CONST_CAST(GLXEW_EXT_texture_from_pixmap) = !_glewInit_GLX_EXT_texture_from_pixmap(GLEW_CONTEXT_ARG_VAR_INIT);
@@ -11914,11 +13432,11 @@ GLenum glxewContextInit (GLXEW_CONTEXT_ARG_DEF_LIST)
return GLEW_OK;
}
-#endif /* !__APPLE__ || GLEW_APPLE_GLX */
+#endif /* !defined(__ANDROID__) && !defined(__native_client__) && (!defined(__APPLE__) || defined(GLEW_APPLE_GLX)) */
/* ------------------------------------------------------------------------ */
-const GLubyte* glewGetErrorString (GLenum error)
+const GLubyte * GLEWAPIENTRY glewGetErrorString (GLenum error)
{
static const GLubyte* _glewErrorString[] =
{
@@ -11932,14 +13450,14 @@ const GLubyte* glewGetErrorString (GLenum error)
return _glewErrorString[(int)error > max_error ? max_error : (int)error];
}
-const GLubyte* glewGetString (GLenum name)
+const GLubyte * GLEWAPIENTRY glewGetString (GLenum name)
{
static const GLubyte* _glewString[] =
{
(const GLubyte*)NULL,
- (const GLubyte*)"1.7.0",
+ (const GLubyte*)"1.10.0",
(const GLubyte*)"1",
- (const GLubyte*)"7",
+ (const GLubyte*)"10",
(const GLubyte*)"0"
};
const int max_string = sizeof(_glewString)/sizeof(*_glewString) - 1;
@@ -11953,18 +13471,19 @@ GLboolean glewExperimental = GL_FALSE;
#if !defined(GLEW_MX)
#if defined(_WIN32)
-extern GLenum wglewContextInit (void);
-#elif !defined(__APPLE__) || defined(GLEW_APPLE_GLX) /* _UNIX */
-extern GLenum glxewContextInit (void);
+extern GLenum GLEWAPIENTRY wglewContextInit (void);
+#elif !defined(__ANDROID__) && !defined(__native_client__) && (!defined(__APPLE__) || defined(GLEW_APPLE_GLX))
+extern GLenum GLEWAPIENTRY glxewContextInit (void);
#endif /* _WIN32 */
-GLenum glewInit ()
+GLenum GLEWAPIENTRY glewInit (void)
{
GLenum r;
- if ( (r = glewContextInit()) ) return r;
+ r = glewContextInit();
+ if ( r != 0 ) return r;
#if defined(_WIN32)
return wglewContextInit();
-#elif !defined(__APPLE__) || defined(GLEW_APPLE_GLX) /* _UNIX */
+#elif !defined(__ANDROID__) && !defined(__native_client__) && (!defined(__APPLE__) || defined(GLEW_APPLE_GLX)) /* _UNIX */
return glxewContextInit();
#else
return r;
@@ -11973,9 +13492,9 @@ GLenum glewInit ()
#endif /* !GLEW_MX */
#ifdef GLEW_MX
-GLboolean glewContextIsSupported (const GLEWContext* ctx, const char* name)
+GLboolean GLEWAPIENTRY glewContextIsSupported (const GLEWContext* ctx, const char* name)
#else
-GLboolean glewIsSupported (const char* name)
+GLboolean GLEWAPIENTRY glewIsSupported (const char* name)
#endif
{
GLubyte* pos = (GLubyte*)name;
@@ -12085,6 +13604,20 @@ GLboolean glewIsSupported (const char* name)
continue;
}
#endif
+#ifdef GL_VERSION_4_3
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"4_3", 3))
+ {
+ ret = GLEW_VERSION_4_3;
+ continue;
+ }
+#endif
+#ifdef GL_VERSION_4_4
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"4_4", 3))
+ {
+ ret = GLEW_VERSION_4_4;
+ continue;
+ }
+#endif
}
if (_glewStrSame2(&pos, &len, (const GLubyte*)"3DFX_", 5))
{
@@ -12147,6 +13680,13 @@ GLboolean glewIsSupported (const char* name)
continue;
}
#endif
+#ifdef GL_AMD_interleaved_elements
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"interleaved_elements", 20))
+ {
+ ret = GLEW_AMD_interleaved_elements;
+ continue;
+ }
+#endif
#ifdef GL_AMD_multi_draw_indirect
if (_glewStrSame3(&pos, &len, (const GLubyte*)"multi_draw_indirect", 19))
{
@@ -12168,6 +13708,20 @@ GLboolean glewIsSupported (const char* name)
continue;
}
#endif
+#ifdef GL_AMD_pinned_memory
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"pinned_memory", 13))
+ {
+ ret = GLEW_AMD_pinned_memory;
+ continue;
+ }
+#endif
+#ifdef GL_AMD_query_buffer_object
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"query_buffer_object", 19))
+ {
+ ret = GLEW_AMD_query_buffer_object;
+ continue;
+ }
+#endif
#ifdef GL_AMD_sample_positions
if (_glewStrSame3(&pos, &len, (const GLubyte*)"sample_positions", 16))
{
@@ -12189,6 +13743,27 @@ GLboolean glewIsSupported (const char* name)
continue;
}
#endif
+#ifdef GL_AMD_shader_trinary_minmax
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"shader_trinary_minmax", 21))
+ {
+ ret = GLEW_AMD_shader_trinary_minmax;
+ continue;
+ }
+#endif
+#ifdef GL_AMD_sparse_texture
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"sparse_texture", 14))
+ {
+ ret = GLEW_AMD_sparse_texture;
+ continue;
+ }
+#endif
+#ifdef GL_AMD_stencil_operation_extended
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"stencil_operation_extended", 26))
+ {
+ ret = GLEW_AMD_stencil_operation_extended;
+ continue;
+ }
+#endif
#ifdef GL_AMD_texture_texture4
if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_texture4", 16))
{
@@ -12203,6 +13778,13 @@ GLboolean glewIsSupported (const char* name)
continue;
}
#endif
+#ifdef GL_AMD_vertex_shader_layer
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"vertex_shader_layer", 19))
+ {
+ ret = GLEW_AMD_vertex_shader_layer;
+ continue;
+ }
+#endif
#ifdef GL_AMD_vertex_shader_tessellator
if (_glewStrSame3(&pos, &len, (const GLubyte*)"vertex_shader_tessellator", 25))
{
@@ -12210,6 +13792,100 @@ GLboolean glewIsSupported (const char* name)
continue;
}
#endif
+#ifdef GL_AMD_vertex_shader_viewport_index
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"vertex_shader_viewport_index", 28))
+ {
+ ret = GLEW_AMD_vertex_shader_viewport_index;
+ continue;
+ }
+#endif
+ }
+ if (_glewStrSame2(&pos, &len, (const GLubyte*)"ANGLE_", 6))
+ {
+#ifdef GL_ANGLE_depth_texture
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"depth_texture", 13))
+ {
+ ret = GLEW_ANGLE_depth_texture;
+ continue;
+ }
+#endif
+#ifdef GL_ANGLE_framebuffer_blit
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"framebuffer_blit", 16))
+ {
+ ret = GLEW_ANGLE_framebuffer_blit;
+ continue;
+ }
+#endif
+#ifdef GL_ANGLE_framebuffer_multisample
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"framebuffer_multisample", 23))
+ {
+ ret = GLEW_ANGLE_framebuffer_multisample;
+ continue;
+ }
+#endif
+#ifdef GL_ANGLE_instanced_arrays
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"instanced_arrays", 16))
+ {
+ ret = GLEW_ANGLE_instanced_arrays;
+ continue;
+ }
+#endif
+#ifdef GL_ANGLE_pack_reverse_row_order
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"pack_reverse_row_order", 22))
+ {
+ ret = GLEW_ANGLE_pack_reverse_row_order;
+ continue;
+ }
+#endif
+#ifdef GL_ANGLE_program_binary
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"program_binary", 14))
+ {
+ ret = GLEW_ANGLE_program_binary;
+ continue;
+ }
+#endif
+#ifdef GL_ANGLE_texture_compression_dxt1
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_compression_dxt1", 24))
+ {
+ ret = GLEW_ANGLE_texture_compression_dxt1;
+ continue;
+ }
+#endif
+#ifdef GL_ANGLE_texture_compression_dxt3
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_compression_dxt3", 24))
+ {
+ ret = GLEW_ANGLE_texture_compression_dxt3;
+ continue;
+ }
+#endif
+#ifdef GL_ANGLE_texture_compression_dxt5
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_compression_dxt5", 24))
+ {
+ ret = GLEW_ANGLE_texture_compression_dxt5;
+ continue;
+ }
+#endif
+#ifdef GL_ANGLE_texture_usage
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_usage", 13))
+ {
+ ret = GLEW_ANGLE_texture_usage;
+ continue;
+ }
+#endif
+#ifdef GL_ANGLE_timer_query
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"timer_query", 11))
+ {
+ ret = GLEW_ANGLE_timer_query;
+ continue;
+ }
+#endif
+#ifdef GL_ANGLE_translated_shader_source
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"translated_shader_source", 24))
+ {
+ ret = GLEW_ANGLE_translated_shader_source;
+ continue;
+ }
+#endif
}
if (_glewStrSame2(&pos, &len, (const GLubyte*)"APPLE_", 6))
{
@@ -12342,6 +14018,20 @@ GLboolean glewIsSupported (const char* name)
continue;
}
#endif
+#ifdef GL_ARB_ES3_compatibility
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"ES3_compatibility", 17))
+ {
+ ret = GLEW_ARB_ES3_compatibility;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_arrays_of_arrays
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"arrays_of_arrays", 16))
+ {
+ ret = GLEW_ARB_arrays_of_arrays;
+ continue;
+ }
+#endif
#ifdef GL_ARB_base_instance
if (_glewStrSame3(&pos, &len, (const GLubyte*)"base_instance", 13))
{
@@ -12349,6 +14039,13 @@ GLboolean glewIsSupported (const char* name)
continue;
}
#endif
+#ifdef GL_ARB_bindless_texture
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"bindless_texture", 16))
+ {
+ ret = GLEW_ARB_bindless_texture;
+ continue;
+ }
+#endif
#ifdef GL_ARB_blend_func_extended
if (_glewStrSame3(&pos, &len, (const GLubyte*)"blend_func_extended", 19))
{
@@ -12356,6 +14053,13 @@ GLboolean glewIsSupported (const char* name)
continue;
}
#endif
+#ifdef GL_ARB_buffer_storage
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"buffer_storage", 14))
+ {
+ ret = GLEW_ARB_buffer_storage;
+ continue;
+ }
+#endif
#ifdef GL_ARB_cl_event
if (_glewStrSame3(&pos, &len, (const GLubyte*)"cl_event", 8))
{
@@ -12363,6 +14067,20 @@ GLboolean glewIsSupported (const char* name)
continue;
}
#endif
+#ifdef GL_ARB_clear_buffer_object
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"clear_buffer_object", 19))
+ {
+ ret = GLEW_ARB_clear_buffer_object;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_clear_texture
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"clear_texture", 13))
+ {
+ ret = GLEW_ARB_clear_texture;
+ continue;
+ }
+#endif
#ifdef GL_ARB_color_buffer_float
if (_glewStrSame3(&pos, &len, (const GLubyte*)"color_buffer_float", 18))
{
@@ -12384,6 +14102,20 @@ GLboolean glewIsSupported (const char* name)
continue;
}
#endif
+#ifdef GL_ARB_compute_shader
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"compute_shader", 14))
+ {
+ ret = GLEW_ARB_compute_shader;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_compute_variable_group_size
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"compute_variable_group_size", 27))
+ {
+ ret = GLEW_ARB_compute_variable_group_size;
+ continue;
+ }
+#endif
#ifdef GL_ARB_conservative_depth
if (_glewStrSame3(&pos, &len, (const GLubyte*)"conservative_depth", 18))
{
@@ -12398,6 +14130,13 @@ GLboolean glewIsSupported (const char* name)
continue;
}
#endif
+#ifdef GL_ARB_copy_image
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"copy_image", 10))
+ {
+ ret = GLEW_ARB_copy_image;
+ continue;
+ }
+#endif
#ifdef GL_ARB_debug_output
if (_glewStrSame3(&pos, &len, (const GLubyte*)"debug_output", 12))
{
@@ -12461,6 +14200,13 @@ GLboolean glewIsSupported (const char* name)
continue;
}
#endif
+#ifdef GL_ARB_enhanced_layouts
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"enhanced_layouts", 16))
+ {
+ ret = GLEW_ARB_enhanced_layouts;
+ continue;
+ }
+#endif
#ifdef GL_ARB_explicit_attrib_location
if (_glewStrSame3(&pos, &len, (const GLubyte*)"explicit_attrib_location", 24))
{
@@ -12468,6 +14214,13 @@ GLboolean glewIsSupported (const char* name)
continue;
}
#endif
+#ifdef GL_ARB_explicit_uniform_location
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"explicit_uniform_location", 25))
+ {
+ ret = GLEW_ARB_explicit_uniform_location;
+ continue;
+ }
+#endif
#ifdef GL_ARB_fragment_coord_conventions
if (_glewStrSame3(&pos, &len, (const GLubyte*)"fragment_coord_conventions", 26))
{
@@ -12475,6 +14228,13 @@ GLboolean glewIsSupported (const char* name)
continue;
}
#endif
+#ifdef GL_ARB_fragment_layer_viewport
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"fragment_layer_viewport", 23))
+ {
+ ret = GLEW_ARB_fragment_layer_viewport;
+ continue;
+ }
+#endif
#ifdef GL_ARB_fragment_program
if (_glewStrSame3(&pos, &len, (const GLubyte*)"fragment_program", 16))
{
@@ -12496,6 +14256,13 @@ GLboolean glewIsSupported (const char* name)
continue;
}
#endif
+#ifdef GL_ARB_framebuffer_no_attachments
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"framebuffer_no_attachments", 26))
+ {
+ ret = GLEW_ARB_framebuffer_no_attachments;
+ continue;
+ }
+#endif
#ifdef GL_ARB_framebuffer_object
if (_glewStrSame3(&pos, &len, (const GLubyte*)"framebuffer_object", 18))
{
@@ -12559,6 +14326,13 @@ GLboolean glewIsSupported (const char* name)
continue;
}
#endif
+#ifdef GL_ARB_indirect_parameters
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"indirect_parameters", 19))
+ {
+ ret = GLEW_ARB_indirect_parameters;
+ continue;
+ }
+#endif
#ifdef GL_ARB_instanced_arrays
if (_glewStrSame3(&pos, &len, (const GLubyte*)"instanced_arrays", 16))
{
@@ -12573,6 +14347,20 @@ GLboolean glewIsSupported (const char* name)
continue;
}
#endif
+#ifdef GL_ARB_internalformat_query2
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"internalformat_query2", 21))
+ {
+ ret = GLEW_ARB_internalformat_query2;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_invalidate_subdata
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"invalidate_subdata", 18))
+ {
+ ret = GLEW_ARB_invalidate_subdata;
+ continue;
+ }
+#endif
#ifdef GL_ARB_map_buffer_alignment
if (_glewStrSame3(&pos, &len, (const GLubyte*)"map_buffer_alignment", 20))
{
@@ -12594,6 +14382,20 @@ GLboolean glewIsSupported (const char* name)
continue;
}
#endif
+#ifdef GL_ARB_multi_bind
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"multi_bind", 10))
+ {
+ ret = GLEW_ARB_multi_bind;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_multi_draw_indirect
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"multi_draw_indirect", 19))
+ {
+ ret = GLEW_ARB_multi_draw_indirect;
+ continue;
+ }
+#endif
#ifdef GL_ARB_multisample
if (_glewStrSame3(&pos, &len, (const GLubyte*)"multisample", 11))
{
@@ -12643,6 +14445,13 @@ GLboolean glewIsSupported (const char* name)
continue;
}
#endif
+#ifdef GL_ARB_program_interface_query
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"program_interface_query", 23))
+ {
+ ret = GLEW_ARB_program_interface_query;
+ continue;
+ }
+#endif
#ifdef GL_ARB_provoking_vertex
if (_glewStrSame3(&pos, &len, (const GLubyte*)"provoking_vertex", 16))
{
@@ -12650,6 +14459,20 @@ GLboolean glewIsSupported (const char* name)
continue;
}
#endif
+#ifdef GL_ARB_query_buffer_object
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"query_buffer_object", 19))
+ {
+ ret = GLEW_ARB_query_buffer_object;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_robust_buffer_access_behavior
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"robust_buffer_access_behavior", 29))
+ {
+ ret = GLEW_ARB_robust_buffer_access_behavior;
+ continue;
+ }
+#endif
#ifdef GL_ARB_robustness
if (_glewStrSame3(&pos, &len, (const GLubyte*)"robustness", 10))
{
@@ -12657,6 +14480,20 @@ GLboolean glewIsSupported (const char* name)
continue;
}
#endif
+#ifdef GL_ARB_robustness_application_isolation
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"robustness_application_isolation", 32))
+ {
+ ret = GLEW_ARB_robustness_application_isolation;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_robustness_share_group_isolation
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"robustness_share_group_isolation", 32))
+ {
+ ret = GLEW_ARB_robustness_share_group_isolation;
+ continue;
+ }
+#endif
#ifdef GL_ARB_sample_shading
if (_glewStrSame3(&pos, &len, (const GLubyte*)"sample_shading", 14))
{
@@ -12678,6 +14515,13 @@ GLboolean glewIsSupported (const char* name)
continue;
}
#endif
+#ifdef GL_ARB_seamless_cubemap_per_texture
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"seamless_cubemap_per_texture", 28))
+ {
+ ret = GLEW_ARB_seamless_cubemap_per_texture;
+ continue;
+ }
+#endif
#ifdef GL_ARB_separate_shader_objects
if (_glewStrSame3(&pos, &len, (const GLubyte*)"separate_shader_objects", 23))
{
@@ -12699,6 +14543,20 @@ GLboolean glewIsSupported (const char* name)
continue;
}
#endif
+#ifdef GL_ARB_shader_draw_parameters
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"shader_draw_parameters", 22))
+ {
+ ret = GLEW_ARB_shader_draw_parameters;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_shader_group_vote
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"shader_group_vote", 17))
+ {
+ ret = GLEW_ARB_shader_group_vote;
+ continue;
+ }
+#endif
#ifdef GL_ARB_shader_image_load_store
if (_glewStrSame3(&pos, &len, (const GLubyte*)"shader_image_load_store", 23))
{
@@ -12706,6 +14564,13 @@ GLboolean glewIsSupported (const char* name)
continue;
}
#endif
+#ifdef GL_ARB_shader_image_size
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"shader_image_size", 17))
+ {
+ ret = GLEW_ARB_shader_image_size;
+ continue;
+ }
+#endif
#ifdef GL_ARB_shader_objects
if (_glewStrSame3(&pos, &len, (const GLubyte*)"shader_objects", 14))
{
@@ -12727,6 +14592,13 @@ GLboolean glewIsSupported (const char* name)
continue;
}
#endif
+#ifdef GL_ARB_shader_storage_buffer_object
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"shader_storage_buffer_object", 28))
+ {
+ ret = GLEW_ARB_shader_storage_buffer_object;
+ continue;
+ }
+#endif
#ifdef GL_ARB_shader_subroutine
if (_glewStrSame3(&pos, &len, (const GLubyte*)"shader_subroutine", 17))
{
@@ -12783,6 +14655,20 @@ GLboolean glewIsSupported (const char* name)
continue;
}
#endif
+#ifdef GL_ARB_sparse_texture
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"sparse_texture", 14))
+ {
+ ret = GLEW_ARB_sparse_texture;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_stencil_texturing
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"stencil_texturing", 17))
+ {
+ ret = GLEW_ARB_stencil_texturing;
+ continue;
+ }
+#endif
#ifdef GL_ARB_sync
if (_glewStrSame3(&pos, &len, (const GLubyte*)"sync", 4))
{
@@ -12818,6 +14704,13 @@ GLboolean glewIsSupported (const char* name)
continue;
}
#endif
+#ifdef GL_ARB_texture_buffer_range
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_buffer_range", 20))
+ {
+ ret = GLEW_ARB_texture_buffer_range;
+ continue;
+ }
+#endif
#ifdef GL_ARB_texture_compression
if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_compression", 19))
{
@@ -12895,6 +14788,13 @@ GLboolean glewIsSupported (const char* name)
continue;
}
#endif
+#ifdef GL_ARB_texture_mirror_clamp_to_edge
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_mirror_clamp_to_edge", 28))
+ {
+ ret = GLEW_ARB_texture_mirror_clamp_to_edge;
+ continue;
+ }
+#endif
#ifdef GL_ARB_texture_mirrored_repeat
if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_mirrored_repeat", 23))
{
@@ -12916,6 +14816,13 @@ GLboolean glewIsSupported (const char* name)
continue;
}
#endif
+#ifdef GL_ARB_texture_query_levels
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_query_levels", 20))
+ {
+ ret = GLEW_ARB_texture_query_levels;
+ continue;
+ }
+#endif
#ifdef GL_ARB_texture_query_lod
if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_query_lod", 17))
{
@@ -12944,6 +14851,13 @@ GLboolean glewIsSupported (const char* name)
continue;
}
#endif
+#ifdef GL_ARB_texture_stencil8
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_stencil8", 16))
+ {
+ ret = GLEW_ARB_texture_stencil8;
+ continue;
+ }
+#endif
#ifdef GL_ARB_texture_storage
if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_storage", 15))
{
@@ -12951,6 +14865,13 @@ GLboolean glewIsSupported (const char* name)
continue;
}
#endif
+#ifdef GL_ARB_texture_storage_multisample
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_storage_multisample", 27))
+ {
+ ret = GLEW_ARB_texture_storage_multisample;
+ continue;
+ }
+#endif
#ifdef GL_ARB_texture_swizzle
if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_swizzle", 15))
{
@@ -12958,6 +14879,13 @@ GLboolean glewIsSupported (const char* name)
continue;
}
#endif
+#ifdef GL_ARB_texture_view
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_view", 12))
+ {
+ ret = GLEW_ARB_texture_view;
+ continue;
+ }
+#endif
#ifdef GL_ARB_timer_query
if (_glewStrSame3(&pos, &len, (const GLubyte*)"timer_query", 11))
{
@@ -13021,6 +14949,13 @@ GLboolean glewIsSupported (const char* name)
continue;
}
#endif
+#ifdef GL_ARB_vertex_attrib_binding
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"vertex_attrib_binding", 21))
+ {
+ ret = GLEW_ARB_vertex_attrib_binding;
+ continue;
+ }
+#endif
#ifdef GL_ARB_vertex_blend
if (_glewStrSame3(&pos, &len, (const GLubyte*)"vertex_blend", 12))
{
@@ -13049,6 +14984,13 @@ GLboolean glewIsSupported (const char* name)
continue;
}
#endif
+#ifdef GL_ARB_vertex_type_10f_11f_11f_rev
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"vertex_type_10f_11f_11f_rev", 27))
+ {
+ ret = GLEW_ARB_vertex_type_10f_11f_11f_rev;
+ continue;
+ }
+#endif
#ifdef GL_ARB_vertex_type_2_10_10_10_rev
if (_glewStrSame3(&pos, &len, (const GLubyte*)"vertex_type_2_10_10_10_rev", 26))
{
@@ -13359,6 +15301,13 @@ GLboolean glewIsSupported (const char* name)
continue;
}
#endif
+#ifdef GL_EXT_debug_marker
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"debug_marker", 12))
+ {
+ ret = GLEW_EXT_debug_marker;
+ continue;
+ }
+#endif
#ifdef GL_EXT_depth_bounds_test
if (_glewStrSame3(&pos, &len, (const GLubyte*)"depth_bounds_test", 17))
{
@@ -14032,6 +15981,13 @@ GLboolean glewIsSupported (const char* name)
}
if (_glewStrSame2(&pos, &len, (const GLubyte*)"INTEL_", 6))
{
+#ifdef GL_INTEL_map_texture
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"map_texture", 11))
+ {
+ ret = GLEW_INTEL_map_texture;
+ continue;
+ }
+#endif
#ifdef GL_INTEL_parallel_arrays
if (_glewStrSame3(&pos, &len, (const GLubyte*)"parallel_arrays", 15))
{
@@ -14047,6 +16003,23 @@ GLboolean glewIsSupported (const char* name)
}
#endif
}
+ if (_glewStrSame2(&pos, &len, (const GLubyte*)"KHR_", 4))
+ {
+#ifdef GL_KHR_debug
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"debug", 5))
+ {
+ ret = GLEW_KHR_debug;
+ continue;
+ }
+#endif
+#ifdef GL_KHR_texture_compression_astc_ldr
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_compression_astc_ldr", 28))
+ {
+ ret = GLEW_KHR_texture_compression_astc_ldr;
+ continue;
+ }
+#endif
+ }
if (_glewStrSame2(&pos, &len, (const GLubyte*)"KTX_", 4))
{
#ifdef GL_KTX_buffer_region
@@ -14100,6 +16073,13 @@ GLboolean glewIsSupported (const char* name)
}
if (_glewStrSame2(&pos, &len, (const GLubyte*)"NVX_", 4))
{
+#ifdef GL_NVX_conditional_render
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"conditional_render", 18))
+ {
+ ret = GLEW_NVX_conditional_render;
+ continue;
+ }
+#endif
#ifdef GL_NVX_gpu_memory_info
if (_glewStrSame3(&pos, &len, (const GLubyte*)"gpu_memory_info", 15))
{
@@ -14110,6 +16090,34 @@ GLboolean glewIsSupported (const char* name)
}
if (_glewStrSame2(&pos, &len, (const GLubyte*)"NV_", 3))
{
+#ifdef GL_NV_bindless_multi_draw_indirect
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"bindless_multi_draw_indirect", 28))
+ {
+ ret = GLEW_NV_bindless_multi_draw_indirect;
+ continue;
+ }
+#endif
+#ifdef GL_NV_bindless_texture
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"bindless_texture", 16))
+ {
+ ret = GLEW_NV_bindless_texture;
+ continue;
+ }
+#endif
+#ifdef GL_NV_blend_equation_advanced
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"blend_equation_advanced", 23))
+ {
+ ret = GLEW_NV_blend_equation_advanced;
+ continue;
+ }
+#endif
+#ifdef GL_NV_blend_equation_advanced_coherent
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"blend_equation_advanced_coherent", 32))
+ {
+ ret = GLEW_NV_blend_equation_advanced_coherent;
+ continue;
+ }
+#endif
#ifdef GL_NV_blend_square
if (_glewStrSame3(&pos, &len, (const GLubyte*)"blend_square", 12))
{
@@ -14117,6 +16125,13 @@ GLboolean glewIsSupported (const char* name)
continue;
}
#endif
+#ifdef GL_NV_compute_program5
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"compute_program5", 16))
+ {
+ ret = GLEW_NV_compute_program5;
+ continue;
+ }
+#endif
#ifdef GL_NV_conditional_render
if (_glewStrSame3(&pos, &len, (const GLubyte*)"conditional_render", 18))
{
@@ -14138,6 +16153,13 @@ GLboolean glewIsSupported (const char* name)
continue;
}
#endif
+#ifdef GL_NV_deep_texture3D
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"deep_texture3D", 14))
+ {
+ ret = GLEW_NV_deep_texture3D;
+ continue;
+ }
+#endif
#ifdef GL_NV_depth_buffer_float
if (_glewStrSame3(&pos, &len, (const GLubyte*)"depth_buffer_float", 18))
{
@@ -14159,6 +16181,13 @@ GLboolean glewIsSupported (const char* name)
continue;
}
#endif
+#ifdef GL_NV_draw_texture
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"draw_texture", 12))
+ {
+ ret = GLEW_NV_draw_texture;
+ continue;
+ }
+#endif
#ifdef GL_NV_evaluators
if (_glewStrSame3(&pos, &len, (const GLubyte*)"evaluators", 10))
{
@@ -14257,6 +16286,13 @@ GLboolean glewIsSupported (const char* name)
continue;
}
#endif
+#ifdef GL_NV_gpu_program5_mem_extended
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"gpu_program5_mem_extended", 25))
+ {
+ ret = GLEW_NV_gpu_program5_mem_extended;
+ continue;
+ }
+#endif
#ifdef GL_NV_gpu_program_fp64
if (_glewStrSame3(&pos, &len, (const GLubyte*)"gpu_program_fp64", 16))
{
@@ -14376,6 +16412,20 @@ GLboolean glewIsSupported (const char* name)
continue;
}
#endif
+#ifdef GL_NV_shader_atomic_counters
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"shader_atomic_counters", 22))
+ {
+ ret = GLEW_NV_shader_atomic_counters;
+ continue;
+ }
+#endif
+#ifdef GL_NV_shader_atomic_float
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"shader_atomic_float", 19))
+ {
+ ret = GLEW_NV_shader_atomic_float;
+ continue;
+ }
+#endif
#ifdef GL_NV_shader_buffer_load
if (_glewStrSame3(&pos, &len, (const GLubyte*)"shader_buffer_load", 18))
{
@@ -14383,6 +16433,13 @@ GLboolean glewIsSupported (const char* name)
continue;
}
#endif
+#ifdef GL_NV_shader_storage_buffer_object
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"shader_storage_buffer_object", 28))
+ {
+ ret = GLEW_NV_shader_storage_buffer_object;
+ continue;
+ }
+#endif
#ifdef GL_NV_tessellation_program5
if (_glewStrSame3(&pos, &len, (const GLubyte*)"tessellation_program5", 21))
{
@@ -14638,6 +16695,51 @@ GLboolean glewIsSupported (const char* name)
}
#endif
}
+ if (_glewStrSame2(&pos, &len, (const GLubyte*)"REGAL_", 6))
+ {
+#ifdef GL_REGAL_ES1_0_compatibility
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"ES1_0_compatibility", 19))
+ {
+ ret = GLEW_REGAL_ES1_0_compatibility;
+ continue;
+ }
+#endif
+#ifdef GL_REGAL_ES1_1_compatibility
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"ES1_1_compatibility", 19))
+ {
+ ret = GLEW_REGAL_ES1_1_compatibility;
+ continue;
+ }
+#endif
+#ifdef GL_REGAL_enable
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"enable", 6))
+ {
+ ret = GLEW_REGAL_enable;
+ continue;
+ }
+#endif
+#ifdef GL_REGAL_error_string
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"error_string", 12))
+ {
+ ret = GLEW_REGAL_error_string;
+ continue;
+ }
+#endif
+#ifdef GL_REGAL_extension_query
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"extension_query", 15))
+ {
+ ret = GLEW_REGAL_extension_query;
+ continue;
+ }
+#endif
+#ifdef GL_REGAL_log
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"log", 3))
+ {
+ ret = GLEW_REGAL_log;
+ continue;
+ }
+#endif
+ }
if (_glewStrSame2(&pos, &len, (const GLubyte*)"REND_", 5))
{
#ifdef GL_REND_screen_coordinates
@@ -15105,9 +17207,9 @@ GLboolean glewIsSupported (const char* name)
#if defined(_WIN32)
#if defined(GLEW_MX)
-GLboolean wglewContextIsSupported (const WGLEWContext* ctx, const char* name)
+GLboolean GLEWAPIENTRY wglewContextIsSupported (const WGLEWContext* ctx, const char* name)
#else
-GLboolean wglewIsSupported (const char* name)
+GLboolean GLEWAPIENTRY wglewIsSupported (const char* name)
#endif
{
GLubyte* pos = (GLubyte*)name;
@@ -15233,6 +17335,20 @@ GLboolean wglewIsSupported (const char* name)
continue;
}
#endif
+#ifdef WGL_ARB_robustness_application_isolation
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"robustness_application_isolation", 32))
+ {
+ ret = WGLEW_ARB_robustness_application_isolation;
+ continue;
+ }
+#endif
+#ifdef WGL_ARB_robustness_share_group_isolation
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"robustness_share_group_isolation", 32))
+ {
+ ret = WGLEW_ARB_robustness_share_group_isolation;
+ continue;
+ }
+#endif
}
if (_glewStrSame2(&pos, &len, (const GLubyte*)"ATI_", 4))
{
@@ -15260,6 +17376,13 @@ GLboolean wglewIsSupported (const char* name)
continue;
}
#endif
+#ifdef WGL_EXT_create_context_es_profile
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"create_context_es_profile", 25))
+ {
+ ret = WGLEW_EXT_create_context_es_profile;
+ continue;
+ }
+#endif
#ifdef WGL_EXT_depth_float
if (_glewStrSame3(&pos, &len, (const GLubyte*)"depth_float", 11))
{
@@ -15330,6 +17453,13 @@ GLboolean wglewIsSupported (const char* name)
continue;
}
#endif
+#ifdef WGL_EXT_swap_control_tear
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"swap_control_tear", 17))
+ {
+ ret = WGLEW_EXT_swap_control_tear;
+ continue;
+ }
+#endif
}
if (_glewStrSame2(&pos, &len, (const GLubyte*)"I3D_", 4))
{
@@ -15385,6 +17515,13 @@ GLboolean wglewIsSupported (const char* name)
continue;
}
#endif
+#ifdef WGL_NV_DX_interop2
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"DX_interop2", 11))
+ {
+ ret = WGLEW_NV_DX_interop2;
+ continue;
+ }
+#endif
#ifdef WGL_NV_copy_image
if (_glewStrSame3(&pos, &len, (const GLubyte*)"copy_image", 10))
{
@@ -15479,7 +17616,7 @@ GLboolean wglewIsSupported (const char* name)
return ret;
}
-#elif !defined(__APPLE__) || defined(GLEW_APPLE_GLX)
+#elif !defined(__ANDROID__) && !defined(__native_client__) && !defined(__APPLE__) || defined(GLEW_APPLE_GLX)
#if defined(GLEW_MX)
GLboolean glxewContextIsSupported (const GLXEWContext* ctx, const char* name)
@@ -15589,6 +17726,20 @@ GLboolean glxewIsSupported (const char* name)
continue;
}
#endif
+#ifdef GLX_ARB_robustness_application_isolation
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"robustness_application_isolation", 32))
+ {
+ ret = GLXEW_ARB_robustness_application_isolation;
+ continue;
+ }
+#endif
+#ifdef GLX_ARB_robustness_share_group_isolation
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"robustness_share_group_isolation", 32))
+ {
+ ret = GLXEW_ARB_robustness_share_group_isolation;
+ continue;
+ }
+#endif
#ifdef GLX_ARB_vertex_buffer_object
if (_glewStrSame3(&pos, &len, (const GLubyte*)"vertex_buffer_object", 20))
{
@@ -15616,6 +17767,13 @@ GLboolean glxewIsSupported (const char* name)
}
if (_glewStrSame2(&pos, &len, (const GLubyte*)"EXT_", 4))
{
+#ifdef GLX_EXT_buffer_age
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"buffer_age", 10))
+ {
+ ret = GLXEW_EXT_buffer_age;
+ continue;
+ }
+#endif
#ifdef GLX_EXT_create_context_es2_profile
if (_glewStrSame3(&pos, &len, (const GLubyte*)"create_context_es2_profile", 26))
{
@@ -15623,6 +17781,13 @@ GLboolean glxewIsSupported (const char* name)
continue;
}
#endif
+#ifdef GLX_EXT_create_context_es_profile
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"create_context_es_profile", 25))
+ {
+ ret = GLXEW_EXT_create_context_es_profile;
+ continue;
+ }
+#endif
#ifdef GLX_EXT_fbconfig_packed_float
if (_glewStrSame3(&pos, &len, (const GLubyte*)"fbconfig_packed_float", 21))
{
@@ -15658,6 +17823,13 @@ GLboolean glxewIsSupported (const char* name)
continue;
}
#endif
+#ifdef GLX_EXT_swap_control_tear
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"swap_control_tear", 17))
+ {
+ ret = GLXEW_EXT_swap_control_tear;
+ continue;
+ }
+#endif
#ifdef GLX_EXT_texture_from_pixmap
if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_from_pixmap", 19))
{
diff --git a/extern/gtest/CMakeLists.txt b/extern/gtest/CMakeLists.txt
index 86f2aaa314a..21b296f93df 100644
--- a/extern/gtest/CMakeLists.txt
+++ b/extern/gtest/CMakeLists.txt
@@ -21,6 +21,13 @@
#
# ***** END GPL LICENSE BLOCK *****
+# avoid noisy warnings
+if(CMAKE_COMPILER_IS_GNUCC)
+ remove_cc_flag(
+ "-Wmissing-declarations"
+ )
+endif()
+
set(INC
.
include
diff --git a/extern/libmv/CMakeLists.txt b/extern/libmv/CMakeLists.txt
index 6a4a61ea779..089743567f0 100644
--- a/extern/libmv/CMakeLists.txt
+++ b/extern/libmv/CMakeLists.txt
@@ -37,13 +37,42 @@ set(SRC
libmv-capi.h
)
-if(WITH_LIBMV)
+if(WITH_LIBMV OR WITH_GTESTS OR (WITH_CYCLES AND WITH_CYCLES_LOGGING))
+ list(APPEND INC
+ third_party/gflags
+ third_party/gflags/gflags
+ third_party/glog/src
+ third_party/ceres/include
+ third_party/ceres/config
+ ../../intern/guardedalloc
+ )
+
+ list(APPEND INC_SYS
+ ${EIGEN3_INCLUDE_DIRS}
+ ${PNG_INCLUDE_DIRS}
+ ${ZLIB_INCLUDE_DIRS}
+ )
+
+ if(WIN32)
+ list(APPEND INC
+ third_party/glog/src/windows
+ )
+
+ if(NOT MINGW)
+ list(APPEND INC
+ third_party/msinttypes
+ )
+ endif()
+ endif()
+
add_definitions(
-DWITH_LIBMV_GUARDED_ALLOC
-DGOOGLE_GLOG_DLL_DECL=
-DLIBMV_NO_FAST_DETECTOR=
)
+endif()
+if(WITH_LIBMV)
TEST_SHARED_PTR_SUPPORT()
if(SHARED_PTR_FOUND)
if(SHARED_PTR_TR1_MEMORY_HEADER)
@@ -56,29 +85,21 @@ if(WITH_LIBMV)
message(FATAL_ERROR "Unable to find shared_ptr.")
endif()
- list(APPEND INC
- third_party/gflags
- third_party/glog/src
- third_party/ceres/include
- third_party/ceres/config
- ../../intern/guardedalloc
- )
-
- set(INC_SYS
- ../Eigen3
- ${PNG_INCLUDE_DIRS}
- ${ZLIB_INCLUDE_DIRS}
- )
-
list(APPEND SRC
+ intern/autotrack.cc
intern/camera_intrinsics.cc
intern/detector.cc
+ intern/frame_accessor.cc
intern/homography.cc
intern/image.cc
intern/logging.cc
intern/reconstruction.cc
intern/track_region.cc
intern/tracks.cc
+ intern/tracksN.cc
+ libmv/autotrack/autotrack.cc
+ libmv/autotrack/predict_tracks.cc
+ libmv/autotrack/tracks.cc
libmv/base/aligned_malloc.cc
libmv/image/array_nd.cc
libmv/image/convolve.cc
@@ -114,14 +135,27 @@ if(WITH_LIBMV)
libmv/tracking/trklt_region_tracker.cc
+ intern/autotrack.h
intern/camera_intrinsics.h
intern/detector.h
+ intern/frame_accessor.h
intern/homography.h
intern/image.h
intern/logging.h
intern/reconstruction.h
intern/track_region.h
intern/tracks.h
+ intern/tracksN.h
+ libmv/autotrack/autotrack.h
+ libmv/autotrack/callbacks.h
+ libmv/autotrack/frame_accessor.h
+ libmv/autotrack/marker.h
+ libmv/autotrack/model.h
+ libmv/autotrack/predict_tracks.h
+ libmv/autotrack/quad.h
+ libmv/autotrack/reconstruction.h
+ libmv/autotrack/region.h
+ libmv/autotrack/tracks.h
libmv/base/aligned_malloc.h
libmv/base/id_generator.h
libmv/base/scoped_ptr.h
@@ -171,6 +205,7 @@ if(WITH_LIBMV)
libmv/simple_pipeline/tracks.h
libmv/tracking/brute_region_tracker.h
libmv/tracking/hybrid_region_tracker.h
+ libmv/tracking/kalman_filter.h
libmv/tracking/klt_region_tracker.h
libmv/tracking/pyramid_region_tracker.h
libmv/tracking/region_tracker.h
@@ -182,21 +217,12 @@ if(WITH_LIBMV)
third_party/msinttypes/stdint.h
)
- if(WIN32)
- list(APPEND INC
- third_party/glog/src/windows
- )
-
- if(NOT MINGW)
- list(APPEND INC
- third_party/msinttypes
- )
- endif()
- endif()
if(WITH_GTESTS)
blender_add_lib(libmv_test_dataset "./libmv/multiview/test_data_sets.cc" "" "")
+ BLENDER_SRC_GTEST("libmv_predict_tracks" "./libmv/autotrack/predict_tracks_test.cc" "libmv_test_dataset;extern_libmv;extern_ceres")
+ BLENDER_SRC_GTEST("libmv_tracks" "./libmv/autotrack/tracks_test.cc" "libmv_test_dataset;extern_libmv;extern_ceres")
BLENDER_SRC_GTEST("libmv_scoped_ptr" "./libmv/base/scoped_ptr_test.cc" "libmv_test_dataset;extern_libmv;extern_ceres")
BLENDER_SRC_GTEST("libmv_vector" "./libmv/base/vector_test.cc" "libmv_test_dataset;extern_libmv;extern_ceres")
BLENDER_SRC_GTEST("libmv_array_nd" "./libmv/image/array_nd_test.cc" "libmv_test_dataset;extern_libmv;extern_ceres")
@@ -240,7 +266,7 @@ if(WITH_LIBMV)
endif()
# make GLog a separate target, so it can be used for gtest as well.
-if(WITH_LIBMV OR WITH_GTESTS OR WITH_CYCLES_LOGGING)
+if(WITH_LIBMV OR WITH_GTESTS OR (WITH_CYCLES AND WITH_CYCLES_LOGGING))
# We compile GLog together with GFlag so we don't worry about
# adding extra lib to linker.
set(GLOG_SRC
@@ -281,6 +307,9 @@ if(WITH_LIBMV OR WITH_GTESTS OR WITH_CYCLES_LOGGING)
third_party/glog/src/windows/glog/log_severity.h
third_party/glog/src/windows/port.h
third_party/glog/src/windows/config.h
+
+ third_party/gflags/windows_port.cc
+ third_party/gflags/windows_port.h
)
else()
list(APPEND GLOG_SRC
@@ -316,13 +345,5 @@ if(WITH_LIBMV OR WITH_GTESTS OR WITH_CYCLES_LOGGING)
)
endif()
- set(GLOG_INC
- third_party/gflags
- third_party/glog/src
- )
-
- set(GLOG_INC_SYS
- )
-
- blender_add_lib(extern_glog "${GLOG_SRC}" "${GLOG_INC}" "${GLOG_INC_SYS}")
+ blender_add_lib(extern_glog "${GLOG_SRC}" "${INC}" "${INC_SYS}")
endif()
diff --git a/extern/libmv/ChangeLog b/extern/libmv/ChangeLog
index 276fbb2ff0d..0bb340b2491 100644
--- a/extern/libmv/ChangeLog
+++ b/extern/libmv/ChangeLog
@@ -1,3 +1,404 @@
+commit 7d6020d2ec42c6cb2749bc891186b4880d26d40b
+Author: Sergey Sharybin <sergey.vfx@gmail.com>
+Date: Wed Dec 31 15:32:07 2014 +0500
+
+ Update GLog to latest upstream revision 143
+
+ Mainly to solve compilation error with demangle.cc.
+
+commit 5dc746700eaf85cb674f0fb73ff3c1b49a7f6315
+Author: Sergey Sharybin <sergey.vfx@gmail.com>
+Date: Fri Dec 12 14:59:55 2014 +0500
+
+ Update GFlags to latest release 2.1.1
+
+ Main purpose of this (andsome of upcoming) update is to check if the
+ upstream sources are useable without any modifications for us. And if
+ not, then we'll need to consider moving some changes into upstream.
+
+ This commit contains an one-to-one copy of the upstream GFlags library
+ and also changes namespace usage since it's changed in the upstream.
+
+commit 6fe6d75f7e90e161b44643b953f058a3829a5247
+Author: Sergey Sharybin <sergey.vfx@gmail.com>
+Date: Sat Nov 1 02:53:36 2014 +0500
+
+ Libmv: Code cleanup, mixed class/struct in declaration/definition
+
+commit d2a5f7953812d2d09765431b59c6c4ac72faf35b
+Author: Sergey Sharybin <sergey.vfx@gmail.com>
+Date: Thu Oct 30 23:13:53 2014 +0500
+
+ Libmv: Support disabled color channels in tracking settings
+
+ This was never ported to a new tracking pipeline and now it's done using
+ FrameAccessor::Transform routines. Quite striaghtforward, but i've changed
+ order of grayscale conversion in blender side with call of transform callback.
+
+ This way it's much easier to perform rescaling in libmv side.
+
+commit d976e034cdf74b34860e0632d7b29713f47c5756
+Author: Keir Mierle <mierle@gmail.com>
+Date: Sat Aug 23 00:38:01 2014 -0700
+
+ Minor keyframe selection cleanups
+
+ Reviewers: sergey
+
+ Reviewed By: sergey
+
+ Differential Revision: https://developer.blender.org/D757
+
+commit bc99ca55dadfca89fde0f93764397c2fe028943d
+Author: Sergey Sharybin <sergey.vfx@gmail.com>
+Date: Sat Aug 23 01:55:32 2014 +0600
+
+ implement backward prediction
+
+ The title actually says it all, just extend current implementation
+ of PredictMarkerPosition() to cases when tracking happens in the reverse
+ order (from the end frame to start).
+
+ it's still doesn't solve all the ambiguity happening in the function
+ in cases when one tracks the feature and then re-tracks it in order
+ to refine the sliding. This is considered a separate TODO for now and
+ will likely be solved by passing tracking direction to the prediction
+ function.
+
+ Reviewers: keir
+
+ Reviewed By: keir
+
+ Differential Revision: https://developer.blender.org/D663
+
+commit 5b87682d98df65ade02638bc6482d824cf0dd0b3
+Author: Keir Mierle <mierle@gmail.com>
+Date: Thu Aug 21 22:45:22 2014 -0700
+
+ Make libmv compile on Ubuntu 14.04
+
+ Reviewers: fsiddi
+
+ Reviewed By: fsiddi
+
+ Subscribers: sergey
+
+ Differential Revision: https://developer.blender.org/D755
+
+commit 0a81db623c458e0384b4f7060d1bcff8993fb469
+Author: Sergey Sharybin <sergey.vfx@gmail.com>
+Date: Wed Jul 23 00:42:00 2014 +0600
+
+ Fix wrong residual blocks counter
+
+ This happened in cases when having zero-weighted tracks
+ and could lead to some assert failures on marking parameter
+ block constant.
+
+commit 2824dbac54cacf74828678be7a5c9fd960ce83e2
+Author: Sergey Sharybin <sergey.vfx@gmail.com>
+Date: Fri Jul 18 12:52:03 2014 +0600
+
+ Fix search area sliding issue
+
+ The only way to do this is to store search region in floats
+ and round when we need to sample it. Otherwise you'll always
+ have sliding effect caused by rounding the issues, especially
+ when doing incremental offset (thing which happens in the
+ prediction code).
+
+ Pretty much straightforward change apart from stuff to be kept
+ in mind: offset calculation int should happen relative to the
+ rounded search region. This is because tracker works in the space
+ of the search window image which get's rounded on the frame access,
+
+ This makes API a bit creepy because frame accessor uses the same
+ Region struct as the search window in Marker and ideally we would
+ need to have either IntRegion or Region<int> in order to make
+ Libmv fully track on what's getting rounded and when.
+
+ Reviewers: keir
+
+ Reviewed By: keir
+
+ Differential Revision: https://developer.blender.org/D616
+
+commit 04862c479332308be47a0f27361402444ace8880
+Author: Keir Mierle <mierle@gmail.com>
+Date: Fri May 9 23:00:03 2014 +0200
+
+ Start the automatic 2D tracking code
+
+ This starts the 2D automatic tracking code. It is totally unfinished.
+
+ Reviewers: sergey
+
+ Reviewed By: sergey
+
+ Differential Revision: https://developer.blender.org/D523
+
+commit be679f67d807a2139c1f7d7e2ca45141940b30d5
+Author: Keir Mierle <mierle@gmail.com>
+Date: Fri May 9 14:36:04 2014 +0200
+
+ Also shift the search window
+
+ Reviewers: sergey
+
+ Reviewed By: sergey
+
+ Differential Revision: https://developer.blender.org/D520
+
+commit 66b8f5eef2633ebcde32a388fc14c60171011821
+Author: Keir Mierle <mierle@gmail.com>
+Date: Fri May 9 13:06:28 2014 +0200
+
+ Change the search region to absolute frame coordinates
+
+ Smarter Eigen usage
+
+ Better error logging
+
+ Reviewers: sergey
+
+ Reviewed By: sergey
+
+ Differential Revision: https://developer.blender.org/D519
+
+commit a08193319ae409fad8f08887eae1f79f02e91eaa
+Author: Keir Mierle <mierle@gmail.com>
+Date: Fri May 9 12:02:47 2014 +0200
+
+ First cut at predictive tracing
+
+ This adds a Kalman filter-based approach to predict where a marker
+ will go in the next frame to track. Hopefully this will make the
+ tracker work faster by avoiding lengthy searches. This code
+ compiles, but is otherwise untested, and likely does not work.
+
+ Fix else branch
+
+ Add some tests
+
+ Update patch coordinates as well (and test)
+
+ Reviewers: sergey
+
+ Reviewed By: sergey
+
+ Differential Revision: https://developer.blender.org/D518
+
+commit 607ffb2f62b56e34a841abbb952d83e19cd1e23c
+Author: Keir Mierle <mierle@gmail.com>
+Date: Thu May 8 16:05:28 2014 +0200
+
+ Add constructor to AutoTrack
+
+commit c39e20a0c27da3733804c3848454b5d4c4f0e66b
+Author: Keir Mierle <mierle@gmail.com>
+Date: Thu May 8 16:04:20 2014 +0200
+
+ Fix GetMarker compilation issue
+
+commit 8dd93e431b6e44439c803bfd26ec2669b656177e
+Author: Keir Mierle <mierle@gmail.com>
+Date: Thu May 8 15:50:26 2014 +0200
+
+ Expose GetMarker() in AutoTrack
+
+ Reviewers: sergey
+
+ Reviewed By: sergey
+
+ Differential Revision: https://developer.blender.org/D516
+
+commit 4405dff60ea08d454b64da1a7c0595d9328cf8a3
+Author: Keir Mierle <mierle@gmail.com>
+Date: Thu May 8 15:38:14 2014 +0200
+
+ Add public SetMarkers to AutoTrack
+
+ Reviewers: sergey
+
+ Reviewed By: sergey
+
+ Differential Revision: https://developer.blender.org/D515
+
+commit c90837f6db276a3b1f610eaad509155f6a43b24f
+Author: Keir Mierle <mierle@gmail.com>
+Date: Thu May 8 15:17:48 2014 +0200
+
+ Make autotrack skeleton compile
+
+ Reviewers: sergey
+
+ Reviewed By: sergey
+
+ Differential Revision: https://developer.blender.org/D514
+
+commit be01baa2e82e36f63e548f073157e68d2ff870c0
+Author: Keir Mierle <mierle@gmail.com>
+Date: Wed May 7 18:48:55 2014 +0200
+
+ Add preliminary TrackMarkerToFrame in autotrack
+
+ Reviewers: sergey
+
+ Reviewed By: sergey
+
+ Differential Revision: https://developer.blender.org/D509
+
+commit 0cab028d591b3d08672ca86eb6c6e4ac1aacf1d0
+Author: Sergey Sharybin <sergey.vfx@gmail.com>
+Date: Wed May 7 17:59:11 2014 +0200
+
+ Remove assert from ArrayND Resize
+
+ That assert broke initialization of arrays which doesn't
+ own the data since constructor uses Resize to set shape
+ and strides.
+
+ Strides are still to be fixed, but that's for later.
+
+commit 64f9c118029a9351e9023e96527c120e1d724d5b
+Author: Sergey Sharybin <sergey.vfx@gmail.com>
+Date: Wed May 7 17:42:21 2014 +0200
+
+ Fix ArrayND freeing the data it doesn't own
+
+ Can't really guarantee it works fully correct now,
+ but at least this check is needed anyway and compilation
+ works just fine.
+
+ Reviewers: keir
+
+ Reviewed By: keir
+
+ Differential Revision: https://developer.blender.org/D508
+
+commit 0618f1c8e88dfc738cdde55784da80b889905e7c
+Author: Keir Mierle <mierle@gmail.com>
+Date: Wed May 7 12:03:32 2014 +0200
+
+ Minor changes
+
+ Reviewers: sergey
+
+ Reviewed By: sergey
+
+ Differential Revision: https://developer.blender.org/D505
+
+commit 5c34335e1bb90c4ed701ee830c718ed4e20dbffa
+Author: Sergey Sharybin <sergey.vfx@gmail.com>
+Date: Wed May 7 11:12:23 2014 +0200
+
+ Fix compilation error in frame accessor
+
+ - int64 is not a standard type, we've got int64_t defined in
+ std int. We also have an msvc port of this header, so should
+ not be an issue.
+
+ - Fixed inconsistency in usage of CacheKey and Key, used Key.
+
+ - Some functions weren't marked as virtual.
+
+ Additional change: added self to authors.
+
+ Reviewers: keir
+
+ Reviewed By: keir
+
+ Differential Revision: https://developer.blender.org/D504
+
+commit 06bc207614e262cd688e2c3ed820ade7c77bdb66
+Author: Keir Mierle <mierle@gmail.com>
+Date: Tue May 6 22:30:59 2014 +0200
+
+ Start new Tracks implementation
+
+ This adds the new Tracks implementation, as well as a
+ trivial test to show it compiles.
+
+ Reviewers: sergey
+
+ Reviewed By: sergey
+
+ Differential Revision: https://developer.blender.org/D502
+
+commit 25ce061e6da69881460ba7718bb0d660a2380a02
+Author: Keir Mierle <mierle@gmail.com>
+Date: Tue May 6 19:10:51 2014 +0200
+
+ Add Reconstruction class for new API
+
+ This starts the new Reconstruction class (with support for e.g. planes). This
+ also starts the new namespace "mv" which will eventually have all the symbols
+ we wish to export.
+
+ Reviewers: sergey
+
+ Reviewed By: sergey
+
+ Differential Revision: https://developer.blender.org/D501
+
+commit 0a6af3e29016048978aea607673340500e050339
+Author: Keir Mierle <mierle@gmail.com>
+Date: Tue May 6 17:52:53 2014 +0200
+
+ Add a new Tracks implementation
+
+ Reviewers: sergey
+
+ Reviewed By: sergey
+
+ Differential Revision: https://developer.blender.org/D500
+
+commit 887b68d29c2b198f4939f9ab5153881aa2c1806e
+Author: Keir Mierle <mierle@gmail.com>
+Date: Tue May 6 17:01:39 2014 +0200
+
+ Initial commit of unfinished AutoTrack API
+
+ This starts the creating the new AutoTrack API. The new API will
+ make it possible for libmv to do full autotracking, including
+ predictive tracking and also support multiple motion models (3D
+ planes etc).
+
+ The first goal (not in this patch) is to convert Blender to use
+ the new API without adding any new functionality.
+
+ Note: This does not add any of the API to the build system!
+ It likely does not compile.
+
+ Reviewers: sergey
+
+ Reviewed By: sergey
+
+ Differential Revision: https://developer.blender.org/D499
+
+commit 08cc227d431d257d27f300fbb8e6991e663302da
+Author: Sergey Sharybin <sergey.vfx@gmail.com>
+Date: Tue May 6 13:09:22 2014 +0200
+
+ Fix homography test failure
+
+ It was caused by assuming that reconstructed homography matrix
+ should look exactly the same as the matrix used to generate a
+ test case.
+
+ It's not actually valid assumption because different-looking
+ matrices could correspond to the same exact transform.
+
+ In this change we make it so actual "re-projected" vectors
+ are being checked, not the values in matrix. This makes it
+ more predictable verification.
+
+ Reviewers: keir
+
+ Reviewed By: keir
+
+ Differential Revision: https://developer.blender.org/D488
+
commit 0b7d83dc9627447dc7df64d7e3a468aefe9ddc13
Author: Sergey Sharybin <sergey.vfx@gmail.com>
Date: Wed Apr 23 19:14:55 2014 +0600
@@ -304,376 +705,3 @@ Author: Sergey Sharybin <sergey.vfx@gmail.com>
Date: Tue Feb 18 19:38:22 2014 +0600
Remove .orig file which was added by accident
-
-commit 62597e3cf0f266a2fefec415c89759e502793e06
-Author: Sergey Sharybin <sergey.vfx@gmail.com>
-Date: Thu Jan 2 16:02:08 2014 +0600
-
- Upgrade glog to latest svn r139
-
- The intention of this upgrade is to get rid of custom patches
- we've been having to support compilation on different platforms
- and compilers.
-
-commit 2452d5d42b390c7ab853e6fe60e58bdd7a01a004
-Author: Sergey Sharybin <sergey.vfx@gmail.com>
-Date: Tue Feb 18 18:46:08 2014 +0600
-
- Tweak Ceres CMake to detect uninstall target properly on Windows
-
-commit 98a281d58ce2301f3dd239a97a448e53f48d0258
-Author: Sergey Sharybin <sergey.vfx@gmail.com>
-Date: Fri Feb 14 00:36:44 2014 +0600
-
- Fix order of third party libs compilation and options used by them
-
- WITH_FAST_DETECTOR was defined too late and third_party folder
- didn't see this option.
-
-commit 4962bccd643ec0f2aed3035170d5f20e8f6efc85
-Author: Sergey Sharybin <sergey.vfx@gmail.com>
-Date: Thu Feb 13 23:55:03 2014 +0600
-
- Disable Ceres unit tests and examples by default
-
- Actually we're to switch to external Ceres rather than
- bundled one, would make life much easier actually.
-
-commit b1381540305d69c702eb2f051bd543fb5c1c3e2c
-Author: Sergey Sharybin <sergey.vfx@gmail.com>
-Date: Thu Feb 6 18:01:58 2014 +0600
-
- Made FAST detector optional
-
- This way it's possible to bundle Libmv sources subset
- to applications which doesn't need FAST detector.
-
- Mainly this is done for Blender integration.
-
-commit da4607f010bca0b3532cd4444afbb10bc774fc32
-Author: Sergey Sharybin <sergey.vfx@gmail.com>
-Date: Tue Jan 28 18:32:39 2014 +0600
-
- Implemented scoped_array and use it in detector
-
- scoped_array is pretty much the same as scoped_ptr
- with the only difference that it'll free memory using
- delete[] operator.
-
- It also gives some additional API functions to access
- array elements.
-
- Currently it only used to manage images denoted as byte
- arrays in detector.
-
- Reviewers: keir
-
- Reviewed By: keir
-
- Differential Revision: https://developer.blender.org/D266
-
-commit cd7eb3eff2e69ce5e08570ead83ae6d35ee48857
-Author: Sergey Sharybin <sergey.vfx@gmail.com>
-Date: Tue Jan 28 17:23:47 2014 +0600
-
- Improvements to weighted tracks behavior
-
- First thing changed by this commit is making it so
- Euclidean intersection takes track weight into account
- when solving minimization problem. This behaves the
- same exact way as it is for BA step.
-
- Second thing is related on how average reprojection error
- is being calculated. It didn't take track weight into
- account which could confuse users. Now average reprojection
- error will give the same result as intersection/BA uses
- during minimization which gives much more predictable
- behavior.
-
- Reviewers: keir
-
- Reviewed By: keir
-
- CC: sebastian_k
-
- Differential Revision: https://developer.blender.org/D265
-
-commit 6559b36dc14369175bfa0830323146acd3426483
-Author: Sergey Sharybin <sergey.vfx@gmail.com>
-Date: Tue Jan 28 16:39:14 2014 +0600
-
- Fixes for keyframe selection
-
- Using tracks with constant zero weight used to crash
- keyframe selection since it was trying to use missing
- parameter blocks for Jacobian evaluation,
-
- Also fixed possible issues with wrong camera block being
- marked as variable. This could technically happen when
- having zero weighted tracks. Made it so all camera blocks
- are marked as variable for now.
-
-commit 557d531b061aa69d114e89cbb325c5175389afec
-Author: Sergey Sharybin <sergey.vfx@gmail.com>
-Date: Tue Jan 28 16:10:33 2014 +0600
-
- Style cleanup: wrong indentation of wrapped line
-
-commit ca15262cf07a873268173965ee1fb84f9729b744
-Author: Sergey Sharybin <sergey.vfx@gmail.com>
-Date: Tue Jan 28 15:21:36 2014 +0600
-
- Rework detector API and implement Harris detector
-
- Switch the detector API to a single function which accepts
- a float image and detector options. This makes usage of
- feature detection more unified across different algorithms.
-
- Options structure is pretty much straightforward and contains
- detector to be used and all the detector-specific settings.
-
- Also implemented Harris feature detection algorithm which
- is not as fast as FAST one but is expected to detect more
- robust feature points.
-
- Reviewers: keir
-
- Reviewed By: keir
-
- Differential Revision: https://developer.blender.org/D258
-
-commit 6458915f64fceba108c5279b7320ca8c76e8a742
-Author: Sergey Sharybin <sergey.vfx@gmail.com>
-Date: Fri Jan 24 19:14:18 2014 +0600
-
- Add arcanist configuration file
-
-commit 0a69fadadc5aacbd339f839ac5bd12c3571278b1
-Author: Sergey Sharybin <sergey.vfx@gmail.com>
-Date: Thu Jan 9 15:50:11 2014 +0600
-
- Fix compilation error on NetBSD
-
- - NetBSD doesn't provide sincos(3) in libm, so don't try to use it
- - Use posix_memalign on NetBSD
-
- Original patch is by Jeorg Sonnenberger to Blender patch tracker, thanks!
-
-commit b0df3e291e6c85f791658be04334efafc41989f5
-Author: Sergey Sharybin <sergey.vfx@gmail.com>
-Date: Thu Jan 2 15:12:18 2014 +0600
-
- Fix build configuration warnings
-
- Those warnings were mainly caused by installation
- configuration of Ceres. Made some tweaks to make
- CMake happy for now.
-
- But for sure bigger cleanup here is needed.
-
-commit b68de6acd20f3ffab92e0cd450198a700cd109ab
-Author: Sergey Sharybin <sergey.vfx@gmail.com>
-Date: Thu Jan 2 15:04:05 2014 +0600
-
- Code and style cleanup
-
- Mainly fixed some style warnings reported by cpplint.
-
- Also changed how camera (un)distortion happens internally
- by replacing number of channels as a template argument
- with number as channels passing as function argument.
- Makes code easier to follow by eliminating loads checks
- how much channels are used and which argument to pass to
- the template.
-
-commit b9e467e7c077b58199c4110f6967b7c18d1e7bf7
-Author: Sergey Sharybin <sergey.vfx@gmail.com>
-Date: Tue Dec 31 20:34:39 2013 +0600
-
- Update Ceres to the latest upstream
-
- This brings up much easier termination type usage,
- which for us means we might use:
-
- ceres::Summary::IsSolutionUsable()
-
- instead of doing manual funky enum values check.
-
-commit 3aeb2367e50b52ca2b9d59d4f0f0b4bbfd6a05e8
-Author: Sergey Sharybin <sergey.vfx@gmail.com>
-Date: Tue Dec 31 20:43:24 2013 +0600
-
- Update gtest to latest version 1.7.0
-
- Also reshuffled CMakeLists in order to avoid
- conflicts happening between gflags bundled to
- Ceres and third_party.
-
-commit 30aaa9cd0b4a4eb0948a17824e7e7622d8ebcb41
-Author: Sergey Sharybin <sergey.vfx@gmail.com>
-Date: Tue Dec 31 20:10:06 2013 +0600
-
- Changes for VC2013
-
- Solves compilation error when using msvc2013
-
- Original patch is by Alexandr Kuznetsov to blender.git
-
-commit b204c0d25065a2b149de256929ff37d8f00f45bb
-Author: Keir Mierle <mierle@gmail.com>
-Date: Tue Dec 31 20:05:58 2013 +0600
-
- Eagerly attempt to refine a track before doing a brute search
-
- Before the refinement phase of tracking, a brute force SAD search
- is run across the search area. This works well but is slow;
- especially if the guess for the track's location is accurate.
-
- This patch runs a refinement phase before running a brute force
- search, hoping that the guessed position (in x2, y2) is close to
- the best answer. If it is, then no brute search is done. If it is
- not, then a normal brute force search followed by refinement is
- done.
-
- In some cases this may produce worse tracks than before; the
- regressions will need investigation. The predictive motion model
- (to be implemented) will reduce the probability of that happening.
-
-commit 5361513f0328ff94b53125d29129561bb03132e8
-Author: Keir Mierle <mierle@gmail.com>
-Date: Tue Dec 31 20:04:46 2013 +0600
-
- Fix bug where libmv tracking incorrectly succeeds on failure
-
- Before this patch, if Ceres returned USER_SUCCESS indicating that
- Ceres was only changing the tracked quad slightly between
- iterations (indicating convergence), no final correlation check
- was done. This leads to incorrectly returning that the tracking
- was successful, when it actually failed.
-
-commit ba9e63eed09e33a48bbcb081058f45ac16f8738e
-Author: Sergey Sharybin <sergey.vfx@gmail.com>
-Date: Tue Dec 31 20:00:46 2013 +0600
-
- Implementation of weighted tracks
-
- Added a weight field to Track structure which means
- how much affect this track will have on the final
- reconstruction.
-
- Currently it affects on BA step only which in most
- cases will work just fine. However, it worth looking
- into weight support for intersection/resection.
-
-commit 4600df8b685ca8c4daa22d6c3b0125fd42c3bc67
-Author: Sergey Sharybin <sergey.vfx@gmail.com>
-Date: Tue Dec 31 19:30:14 2013 +0600
-
- Code cleanup: move function prototype to header file
-
-commit 0ce5b6efde774b3f042acf9e42c95674548f1c01
-Author: Sergey Sharybin <sergey.vfx@gmail.com>
-Date: Tue Dec 31 19:26:48 2013 +0600
-
- Get rid of Allow Fallback option for euclidean resection
-
- It was rather confusing from the user usage point of view
- and didn't get so much improvement after new bundle adjuster
- was added.
-
- In the future we might want to switch resection to PPnP algorithm,
- which could also might be a nice alternative to fallback option.
-
-commit 5d063426f4809000c27f38ed798e4224bbd09a6d
-Author: Sergey Sharybin <sergey.vfx@gmail.com>
-Date: Tue Dec 31 19:24:05 2013 +0600
-
- Use explicit declaration of int types sign
-
- Mainly needs to make blender happy with this custom
- header which used to run into conflict with other int
- types headers.
-
- Wouldn't harm being more explicit here anyway.
-
-commit c5be59dee94f94de369006c544080282cfb245cc
-Author: Sergey Sharybin <sergey.vfx@gmail.com>
-Date: Tue Dec 31 14:50:00 2013 +0600
-
- Implement refinement of estimated homography/fundamental matrices
-
- It was only possible to perform algebraic estimation, which didn't
- give so much accurate results.
-
- Implemented a way to perform algebraic estimation followed with
- refinement step using Ceres minimizer.
-
- The code was actually mostly already there since keyframe selection
- patch. Made such estimation a generic function in multiview/ and
- hanged API for estimation in order to pass all additional options via
- an options structure (the same way as it's done fr Ceres).
-
- Most of the options are straight-forward to understand,but some
- deserves more description here:
-
- * expected_average_symmetric_distance is used as an early output check
- and as soon as average symmetric error goes below this threshold
- refining finishes.
-
- This distance is measured in the same units as input points are.
-
- It is arguable whether we need callback for this or not, but seems
- Ceres doesn't have some kind of absolute threshold for function value
- and function_tolerance behaves different from logic behind expected
- symmetric error.
-
- * There' an option to normalize correspondences before estimating the
- homography in order to increase estimation stability. See
-
- R. Hartley and A. Zisserman. Multiple View Geometry in Computer
- Vision. Cambridge University Press, second edition, 2003.
-
- https://www.cs.ubc.ca/grads/resources/thesis/May09/Dubrofsky_Elan.pdf
-
-commit 1cdad972c4a9005e78891524cbd6d65600ca7e99
-Author: Sergey Sharybin <sergey.vfx@gmail.com>
-Date: Wed Sep 25 16:12:29 2013 +0600
-
- Code cleanup: Minor function capitalization fix
-
- Original patch by Joseph Mansfield to the Blender repository.
-
-commit 434316d084e8a41fd452f03610d7244d664948dc
-Author: Sergey Sharybin <sergey.vfx@gmail.com>
-Date: Wed Sep 25 16:07:43 2013 +0600
-
- Code cleanup: spelling correction
-
- Original patch by Joseph Mansfield to the Blender repository.
-
-commit 5cfe8465ac70407c0959c53bcd5206657a1322a2
-Author: Sergey Sharybin <sergey.vfx@gmail.com>
-Date: Wed Sep 25 16:02:48 2013 +0600
-
- Fix for uninitialized covariance matrix
-
- Lead to unpredictable tracking termination criteria.
-
-commit fd86b77d413489649a989f075b061714ed9a72fc
-Author: Sergey Sharybin <sergey.vfx@gmail.com>
-Date: Wed Sep 25 16:01:19 2013 +0600
-
- Add Procrustes PNP ("PPnP") resection algorithm to libmv
-
- This adds a new Euclidean resection method, used to create the
- initial reconstruction in the motion tracker, to libmv. The method
- is based on the Procrustes PNP algorithm (aka "PPnP"). Currently
- the algorithm is not connected with the motion tracker, but it
- will be eventually since it supports initialization.
-
- Having an initial guess when doing resection is important for
- ambiguous cases where potentially the user could offer extra
- guidance to the solver, in the form of "this point is in front of
- that point".
-
- Original patch by Keir Mierle made to Blender repository.
diff --git a/extern/libmv/SConscript b/extern/libmv/SConscript
index 162fb88df53..251e5835d64 100644
--- a/extern/libmv/SConscript
+++ b/extern/libmv/SConscript
@@ -6,13 +6,28 @@
import sys
import os
-from FindSharedPtr import FindSharedPtr
Import('env')
defs = []
incs = '.'
+if env['WITH_BF_LIBMV'] or (env['WITH_BF_CYCLES'] and env['WITH_BF_CYCLES_LOGGING']):
+ defs.append('GOOGLE_GLOG_DLL_DECL=')
+ defs.append('WITH_LIBMV_GUARDED_ALLOC')
+ defs.append('LIBMV_NO_FAST_DETECTOR')
+
+ incs += ' ../Eigen3 third_party/gflags third_party/gflags/gflags third_party/glog/src third_party/ceres/include third_party/ceres/config ../../intern/guardedalloc'
+ incs += ' ' + env['BF_PNG_INC']
+ incs += ' ' + env['BF_ZLIB_INC']
+
+ if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'linuxcross', 'win64-vc', 'win64-mingw'):
+ incs += ' ./third_party/glog/src/windows ./third_party/glog/src/windows/glog'
+ if env['OURPLATFORM'] in ('win32-vc', 'win64-vc'):
+ incs += ' ./third_party/msinttypes'
+ else:
+ incs += ' ./third_party/glog/src'
+
if env['WITH_BF_LIBMV']:
if not env['WITH_SHARED_PTR_SUPPORT']:
print("-- Unable to find shared_ptr which is required for compilation.")
@@ -23,40 +38,33 @@ if env['WITH_BF_LIBMV']:
if env['SHARED_PTR_NAMESPACE'] == 'std::tr1':
defs.append('CERES_TR1_SHARED_PTR')
- defs.append('GOOGLE_GLOG_DLL_DECL=')
- defs.append('WITH_LIBMV_GUARDED_ALLOC')
- defs.append('LIBMV_NO_FAST_DETECTOR')
-
src = env.Glob('intern/*.cc')
src.remove('intern' + os.sep + 'stub.cc')
+ src += env.Glob('libmv/autotrack/*.cc')
src += env.Glob('libmv/base/*.cc')
src += env.Glob('libmv/image/*.cc')
src += env.Glob('libmv/multiview/*.cc')
src += env.Glob('libmv/numeric/*.cc')
src += env.Glob('libmv/simple_pipeline/*.cc')
src += env.Glob('libmv/tracking/*.cc')
- src += env.Glob('third_party/gflags/*.cc')
-
- incs += ' ../Eigen3 third_party/gflags third_party/glog/src third_party/ceres/include third_party/ceres/config ../../intern/guardedalloc'
- incs += ' ' + env['BF_PNG_INC']
- incs += ' ' + env['BF_ZLIB_INC']
-
- if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'linuxcross', 'win64-vc', 'win64-mingw'):
- incs += ' ./third_party/glog/src/windows ./third_party/glog/src/windows/glog'
- if env['OURPLATFORM'] in ('win32-vc', 'win64-vc'):
- incs += ' ./third_party/msinttypes'
-
- src += ['./third_party/glog/src/logging.cc', './third_party/glog/src/raw_logging.cc', './third_party/glog/src/utilities.cc', './third_party/glog/src/vlog_is_on.cc']
- src += ['./third_party/glog/src/windows/port.cc']
- else:
- src += env.Glob("third_party/glog/src/*.cc")
- incs += ' ./third_party/glog/src'
else:
src = env.Glob("intern/stub.cc")
src = [src for src in src if src.find('_test.cc') == -1]
-env.BlenderLib ( libname = 'extern_libmv', sources=src, includes=Split(incs), defines=defs, libtype=['extern', 'player'], priority=[20,137] )
+env.BlenderLib(libname = 'extern_libmv', sources=src, includes=Split(incs), defines=defs, libtype=['extern', 'player'], priority=[20,137])
+
+if env['WITH_BF_LIBMV'] or (env['WITH_BF_CYCLES'] and env['WITH_BF_CYCLES_LOGGING']):
+ glog_src = []
+ glog_src += env.Glob("third_party/gflags/*.cc")
+ if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'linuxcross', 'win64-vc', 'win64-mingw'):
+ glog_src += ['./third_party/glog/src/logging.cc', './third_party/glog/src/raw_logging.cc', './third_party/glog/src/utilities.cc', './third_party/glog/src/vlog_is_on.cc']
+ glog_src += ['./third_party/glog/src/windows/port.cc']
+ else:
+ glog_src.remove('third_party/gflags/windows_port.cc')
+ glog_src += env.Glob("third_party/glog/src/*.cc")
+
+ env.BlenderLib(libname = 'extern_glog', sources=glog_src, includes=Split(incs), defines=defs, libtype=['extern', 'player'], priority=[20,137])
if env['WITH_BF_LIBMV']:
SConscript(['third_party/SConscript'])
diff --git a/extern/libmv/bundle.sh b/extern/libmv/bundle.sh
index f37ab1fcff9..ac4190041bd 100755
--- a/extern/libmv/bundle.sh
+++ b/extern/libmv/bundle.sh
@@ -75,7 +75,7 @@ for x in $src_dir $src_third_dir; do
fi
fi
- if test `echo $x | grep -c windows ` -eq 0; then
+ if test `echo $x | grep -c "windows\|gflags" ` -eq 0; then
if [ -z "$src" ]; then
src=$t
else
@@ -130,13 +130,42 @@ set(SRC
libmv-capi.h
)
-if(WITH_LIBMV)
+if(WITH_LIBMV OR WITH_GTESTS OR (WITH_CYCLES AND WITH_CYCLES_LOGGING))
+ list(APPEND INC
+ third_party/gflags
+ third_party/gflags/gflags
+ third_party/glog/src
+ third_party/ceres/include
+ third_party/ceres/config
+ ../../intern/guardedalloc
+ )
+
+ list(APPEND INC_SYS
+ \${EIGEN3_INCLUDE_DIRS}
+ \${PNG_INCLUDE_DIRS}
+ \${ZLIB_INCLUDE_DIRS}
+ )
+
+ if(WIN32)
+ list(APPEND INC
+ third_party/glog/src/windows
+ )
+
+ if(NOT MINGW)
+ list(APPEND INC
+ third_party/msinttypes
+ )
+ endif()
+ endif()
+
add_definitions(
-DWITH_LIBMV_GUARDED_ALLOC
-DGOOGLE_GLOG_DLL_DECL=
-DLIBMV_NO_FAST_DETECTOR=
)
+endif()
+if(WITH_LIBMV)
TEST_SHARED_PTR_SUPPORT()
if(SHARED_PTR_FOUND)
if(SHARED_PTR_TR1_MEMORY_HEADER)
@@ -149,21 +178,8 @@ if(WITH_LIBMV)
message(FATAL_ERROR "Unable to find shared_ptr.")
endif()
- list(APPEND INC
- third_party/gflags
- third_party/glog/src
- third_party/ceres/include
- third_party/ceres/config
- ../../intern/guardedalloc
- )
-
- set(INC_SYS
- ../Eigen3
- \${PNG_INCLUDE_DIR}
- \${ZLIB_INCLUDE_DIRS}
- )
-
list(APPEND SRC
+ intern/autotrack.cc
intern/camera_intrinsics.cc
intern/detector.cc
intern/frame_accessor.cc
@@ -177,6 +193,7 @@ if(WITH_LIBMV)
${sources}
${third_sources}
+ intern/autotrack.h
intern/camera_intrinsics.h
intern/detector.h
intern/frame_accessor.h
@@ -192,17 +209,6 @@ ${headers}
${third_headers}
)
- if(WIN32)
- list(APPEND INC
- third_party/glog/src/windows
- )
-
- if(NOT MINGW)
- list(APPEND INC
- third_party/msinttypes
- )
- endif()
- endif()
if(WITH_GTESTS)
blender_add_lib(libmv_test_dataset "./libmv/multiview/test_data_sets.cc" "${INC}" "${INC_SYS}")
@@ -211,7 +217,7 @@ ${tests}
endif()
else()
list(APPEND SRC
- libmv-capi_stub.cc
+ intern/stub.cc
)
endif()
@@ -222,7 +228,7 @@ if(WITH_LIBMV)
endif()
# make GLog a separate target, so it can be used for gtest as well.
-if(WITH_LIBMV OR WITH_GTESTS)
+if(WITH_LIBMV OR WITH_GTESTS OR (WITH_CYCLES AND WITH_CYCLES_LOGGING))
# We compile GLog together with GFlag so we don't worry about
# adding extra lib to linker.
set(GLOG_SRC
@@ -256,6 +262,9 @@ ${third_gflags_headers}
third_party/glog/src/windows/glog/log_severity.h
third_party/glog/src/windows/port.h
third_party/glog/src/windows/config.h
+
+ third_party/gflags/windows_port.cc
+ third_party/gflags/windows_port.h
)
else()
list(APPEND GLOG_SRC
@@ -265,21 +274,11 @@ ${third_glog_headers}
)
endif()
- set(GLOG_INC
- third_party/gflags
- third_party/glog/src
- )
-
- set(GLOG_INC_SYS
- )
-
- blender_add_lib(extern_glog "\${GLOG_SRC}" "\${GLOG_INC}" "\${GLOG_INC_SYS}")
+ blender_add_lib(extern_glog "\${GLOG_SRC}" "\${INC}" "\${INC_SYS}")
endif()
EOF
cat > SConscript << EOF
-#!/usr/bin/python
-
# NOTE: This file is automatically generated by bundle.sh script
# If you're doing changes in this file, please update template
# in that script too
@@ -292,25 +291,12 @@ Import('env')
defs = []
incs = '.'
-if env['WITH_BF_LIBMV']:
- if not env['WITH_SHARED_PTR_SUPPORT']:
- print("-- Unable to find shared_ptr which is required for compilation.")
- exit(1)
-
- if env['SHARED_PTR_HEADER'] == 'tr1/memory':
- defs.append('CERES_TR1_MEMORY_HEADER')
- if env['SHARED_PTR_NAMESPACE'] == 'std::tr1':
- defs.append('CERES_TR1_SHARED_PTR')
-
+if env['WITH_BF_LIBMV'] or (env['WITH_BF_CYCLES'] and env['WITH_BF_CYCLES_LOGGING']):
defs.append('GOOGLE_GLOG_DLL_DECL=')
defs.append('WITH_LIBMV_GUARDED_ALLOC')
defs.append('LIBMV_NO_FAST_DETECTOR')
- src = env.Glob('intern/*.cc')
- src.remove('intern' + os.sep + 'stub.cc')
-$src
-
- incs += ' ../Eigen3 third_party/gflags third_party/glog/src third_party/ceres/include third_party/ceres/config ../../intern/guardedalloc'
+ incs += ' ../Eigen3 third_party/gflags third_party/gflags/gflags third_party/glog/src third_party/ceres/include third_party/ceres/config ../../intern/guardedalloc'
incs += ' ' + env['BF_PNG_INC']
incs += ' ' + env['BF_ZLIB_INC']
@@ -318,18 +304,40 @@ $src
incs += ' ./third_party/glog/src/windows ./third_party/glog/src/windows/glog'
if env['OURPLATFORM'] in ('win32-vc', 'win64-vc'):
incs += ' ./third_party/msinttypes'
-${win_src}
- src += ['./third_party/glog/src/logging.cc', './third_party/glog/src/raw_logging.cc', './third_party/glog/src/utilities.cc', './third_party/glog/src/vlog_is_on.cc']
- src += ['./third_party/glog/src/windows/port.cc']
else:
- src += env.Glob("third_party/glog/src/*.cc")
incs += ' ./third_party/glog/src'
+
+if env['WITH_BF_LIBMV']:
+ if not env['WITH_SHARED_PTR_SUPPORT']:
+ print("-- Unable to find shared_ptr which is required for compilation.")
+ exit(1)
+
+ if env['SHARED_PTR_HEADER'] == 'tr1/memory':
+ defs.append('CERES_TR1_MEMORY_HEADER')
+ if env['SHARED_PTR_NAMESPACE'] == 'std::tr1':
+ defs.append('CERES_TR1_SHARED_PTR')
+
+ src = env.Glob('intern/*.cc')
+ src.remove('intern' + os.sep + 'stub.cc')
+$src
else:
src = env.Glob("intern/stub.cc")
src = [src for src in src if src.find('_test.cc') == -1]
-env.BlenderLib ( libname = 'extern_libmv', sources=src, includes=Split(incs), defines=defs, libtype=['extern', 'player'], priority=[20,137] )
+env.BlenderLib(libname = 'extern_libmv', sources=src, includes=Split(incs), defines=defs, libtype=['extern', 'player'], priority=[20,137])
+
+if env['WITH_BF_LIBMV'] or (env['WITH_BF_CYCLES'] and env['WITH_BF_CYCLES_LOGGING']):
+ glog_src = []
+ glog_src += env.Glob("third_party/gflags/*.cc")
+ if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'linuxcross', 'win64-vc', 'win64-mingw'):
+ glog_src += ['./third_party/glog/src/logging.cc', './third_party/glog/src/raw_logging.cc', './third_party/glog/src/utilities.cc', './third_party/glog/src/vlog_is_on.cc']
+ glog_src += ['./third_party/glog/src/windows/port.cc']
+ else:
+ glog_src.remove('third_party/gflags/windows_port.cc')
+ glog_src += env.Glob("third_party/glog/src/*.cc")
+
+ env.BlenderLib(libname = 'extern_glog', sources=glog_src, includes=Split(incs), defines=defs, libtype=['extern', 'player'], priority=[20,137])
if env['WITH_BF_LIBMV']:
SConscript(['third_party/SConscript'])
diff --git a/extern/libmv/files.txt b/extern/libmv/files.txt
index f1eb9580ff5..11f8ef24781 100644
--- a/extern/libmv/files.txt
+++ b/extern/libmv/files.txt
@@ -1,3 +1,18 @@
+libmv/autotrack/autotrack.cc
+libmv/autotrack/autotrack.h
+libmv/autotrack/callbacks.h
+libmv/autotrack/frame_accessor.h
+libmv/autotrack/marker.h
+libmv/autotrack/model.h
+libmv/autotrack/predict_tracks.cc
+libmv/autotrack/predict_tracks.h
+libmv/autotrack/predict_tracks_test.cc
+libmv/autotrack/quad.h
+libmv/autotrack/reconstruction.h
+libmv/autotrack/region.h
+libmv/autotrack/tracks.cc
+libmv/autotrack/tracks.h
+libmv/autotrack/tracks_test.cc
libmv/base/aligned_malloc.cc
libmv/base/aligned_malloc.h
libmv/base/id_generator.h
@@ -104,6 +119,7 @@ libmv/tracking/brute_region_tracker.h
libmv/tracking/brute_region_tracker_test.cc
libmv/tracking/hybrid_region_tracker.cc
libmv/tracking/hybrid_region_tracker.h
+libmv/tracking/kalman_filter.h
libmv/tracking/klt_region_tracker.cc
libmv/tracking/klt_region_tracker.h
libmv/tracking/klt_region_tracker_test.cc
@@ -117,10 +133,10 @@ libmv/tracking/track_region.cc
libmv/tracking/track_region.h
libmv/tracking/trklt_region_tracker.cc
libmv/tracking/trklt_region_tracker.h
-third_party/gflags/AUTHORS
-third_party/gflags/ChangeLog
+third_party/gflags/AUTHORS.txt
+third_party/gflags/ChangeLog.txt
third_party/gflags/config.h
-third_party/gflags/COPYING
+third_party/gflags/COPYING.txt
third_party/gflags/gflags.cc
third_party/gflags/gflags_completions.cc
third_party/gflags/gflags/gflags_completions.h
@@ -128,9 +144,11 @@ third_party/gflags/gflags/gflags_declare.h
third_party/gflags/gflags/gflags.h
third_party/gflags/gflags_reporting.cc
third_party/gflags/mutex.h
-third_party/gflags/NEWS
+third_party/gflags/NEWS.txt
third_party/gflags/README.libmv
third_party/gflags/util.h
+third_party/gflags/windows_port.cc
+third_party/gflags/windows_port.h
third_party/glog/AUTHORS
third_party/glog/ChangeLog
third_party/glog/COPYING
diff --git a/extern/libmv/intern/autotrack.cc b/extern/libmv/intern/autotrack.cc
new file mode 100644
index 00000000000..f0cbc68f11e
--- /dev/null
+++ b/extern/libmv/intern/autotrack.cc
@@ -0,0 +1,99 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2014 Blender Foundation.
+ * All rights reserved.
+ *
+ * Contributor(s): Blender Foundation,
+ * Sergey Sharybin
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include "intern/autotrack.h"
+#include "intern/tracksN.h"
+#include "intern/utildefines.h"
+#include "libmv/autotrack/autotrack.h"
+
+using mv::AutoTrack;
+using mv::FrameAccessor;
+using mv::Marker;
+using libmv::TrackRegionOptions;
+using libmv::TrackRegionResult;
+
+libmv_AutoTrack* libmv_autoTrackNew(libmv_FrameAccessor *frame_accessor) {
+ return (libmv_AutoTrack*) LIBMV_OBJECT_NEW(AutoTrack,
+ (FrameAccessor*) frame_accessor);
+}
+
+void libmv_autoTrackDestroy(libmv_AutoTrack* libmv_autotrack) {
+ LIBMV_OBJECT_DELETE(libmv_autotrack, AutoTrack);
+}
+
+void libmv_autoTrackSetOptions(libmv_AutoTrack* libmv_autotrack,
+ const libmv_AutoTrackOptions* options) {
+ AutoTrack *autotrack = ((AutoTrack*) libmv_autotrack);
+ libmv_configureTrackRegionOptions(options->track_region,
+ &autotrack->options.track_region);
+
+ autotrack->options.search_region.min(0) = options->search_region.min[0];
+ autotrack->options.search_region.min(1) = options->search_region.min[1];
+ autotrack->options.search_region.max(0) = options->search_region.max[0];
+ autotrack->options.search_region.max(1) = options->search_region.max[1];
+}
+
+int libmv_autoTrackMarker(libmv_AutoTrack* libmv_autotrack,
+ const libmv_TrackRegionOptions* libmv_options,
+ libmv_Marker *libmv_tracked_marker,
+ libmv_TrackRegionResult* libmv_result) {
+
+ Marker tracked_marker;
+ TrackRegionOptions options;
+ TrackRegionResult result;
+ libmv_apiMarkerToMarker(*libmv_tracked_marker, &tracked_marker);
+ libmv_configureTrackRegionOptions(*libmv_options,
+ &options);
+ (((AutoTrack*) libmv_autotrack)->TrackMarker(&tracked_marker,
+ &result,
+ &options));
+ libmv_markerToApiMarker(tracked_marker, libmv_tracked_marker);
+ libmv_regionTrackergetResult(result, libmv_result);
+ return result.is_usable();
+}
+
+void libmv_autoTrackAddMarker(libmv_AutoTrack* libmv_autotrack,
+ const libmv_Marker* libmv_marker) {
+ Marker marker;
+ libmv_apiMarkerToMarker(*libmv_marker, &marker);
+ ((AutoTrack*) libmv_autotrack)->AddMarker(marker);
+}
+
+int libmv_autoTrackGetMarker(libmv_AutoTrack* libmv_autotrack,
+ int clip,
+ int frame,
+ int track,
+ libmv_Marker *libmv_marker) {
+ Marker marker;
+ int ok = ((AutoTrack*) libmv_autotrack)->GetMarker(clip,
+ frame,
+ track,
+ &marker);
+ if (ok) {
+ libmv_markerToApiMarker(marker, libmv_marker);
+ }
+ return ok;
+}
diff --git a/extern/libmv/intern/autotrack.h b/extern/libmv/intern/autotrack.h
new file mode 100644
index 00000000000..2a4a8f3c97f
--- /dev/null
+++ b/extern/libmv/intern/autotrack.h
@@ -0,0 +1,71 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2014 Blender Foundation.
+ * All rights reserved.
+ *
+ * Contributor(s): Blender Foundation,
+ * Sergey Sharybin
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef LIBMV_C_API_AUTOTRACK_H_
+#define LIBMV_C_API_AUTOTRACK_H_
+
+#include "intern/frame_accessor.h"
+#include "intern/tracksN.h"
+#include "intern/track_region.h"
+#include "intern/region.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct libmv_AutoTrack libmv_AutoTrack;
+
+typedef struct libmv_AutoTrackOptions {
+ libmv_TrackRegionOptions track_region;
+ libmv_Region search_region;
+} libmv_AutoTrackOptions;
+
+libmv_AutoTrack* libmv_autoTrackNew(libmv_FrameAccessor *frame_accessor);
+
+void libmv_autoTrackDestroy(libmv_AutoTrack* libmv_autotrack);
+
+void libmv_autoTrackSetOptions(libmv_AutoTrack* libmv_autotrack,
+ const libmv_AutoTrackOptions* options);
+
+int libmv_autoTrackMarker(libmv_AutoTrack* libmv_autotrack,
+ const libmv_TrackRegionOptions* libmv_options,
+ libmv_Marker *libmv_tracker_marker,
+ libmv_TrackRegionResult* libmv_result);
+
+void libmv_autoTrackAddMarker(libmv_AutoTrack* libmv_autotrack,
+ const libmv_Marker* libmv_marker);
+
+int libmv_autoTrackGetMarker(libmv_AutoTrack* libmv_autotrack,
+ int clip,
+ int frame,
+ int track,
+ libmv_Marker *libmv_marker);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // LIBMV_C_API_TRACKS_H_
diff --git a/extern/libmv/intern/camera_intrinsics.cc b/extern/libmv/intern/camera_intrinsics.cc
index e8b99970ff7..0ce757cc93b 100644
--- a/extern/libmv/intern/camera_intrinsics.cc
+++ b/extern/libmv/intern/camera_intrinsics.cc
@@ -349,6 +349,7 @@ CameraIntrinsics* libmv_cameraIntrinsicsCreateFromOptions(
default:
assert(!"Unknown distortion model");
}
- libmv_cameraIntrinsicsFillFromOptions(camera_intrinsics_options, camera_intrinsics);
+ libmv_cameraIntrinsicsFillFromOptions(camera_intrinsics_options,
+ camera_intrinsics);
return camera_intrinsics;
}
diff --git a/extern/libmv/intern/frame_accessor.cc b/extern/libmv/intern/frame_accessor.cc
new file mode 100644
index 00000000000..8bf2cab914b
--- /dev/null
+++ b/extern/libmv/intern/frame_accessor.cc
@@ -0,0 +1,164 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2014 Blender Foundation.
+ * All rights reserved.
+ *
+ * Contributor(s): Blender Foundation,
+ * Sergey Sharybin
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include "intern/frame_accessor.h"
+#include "intern/image.h"
+#include "intern/utildefines.h"
+#include "libmv/autotrack/frame_accessor.h"
+#include "libmv/autotrack/region.h"
+#include "libmv/image/image.h"
+
+namespace {
+
+using libmv::FloatImage;
+using mv::FrameAccessor;
+using mv::Region;
+
+struct LibmvFrameAccessor : public FrameAccessor {
+ LibmvFrameAccessor(libmv_FrameAccessorUserData* user_data,
+ libmv_GetImageCallback get_image_callback,
+ libmv_ReleaseImageCallback release_image_callback)
+ : user_data_(user_data),
+ get_image_callback_(get_image_callback),
+ release_image_callback_(release_image_callback) { }
+
+ libmv_InputMode get_libmv_input_mode(InputMode input_mode) {
+ switch (input_mode) {
+#define CHECK_INPUT_MODE(mode) \
+ case mode: \
+ return LIBMV_IMAGE_MODE_ ## mode;
+ CHECK_INPUT_MODE(MONO)
+ CHECK_INPUT_MODE(RGBA)
+#undef CHECK_INPUT_MODE
+ }
+ assert(!"unknown input mode passed from Libmv.");
+ // TODO(sergey): Proper error handling here in the future.
+ return LIBMV_IMAGE_MODE_MONO;
+ }
+
+ void get_libmv_region(const Region& region,
+ libmv_Region* libmv_region) {
+ libmv_region->min[0] = region.min(0);
+ libmv_region->min[1] = region.min(1);
+ libmv_region->max[0] = region.max(0);
+ libmv_region->max[1] = region.max(1);
+ }
+
+ Key GetImage(int clip,
+ int frame,
+ InputMode input_mode,
+ int downscale,
+ const Region* region,
+ const Transform* transform,
+ FloatImage* destination) {
+ float *float_buffer;
+ int width, height, channels;
+ libmv_Region libmv_region;
+ if (region) {
+ get_libmv_region(*region, &libmv_region);
+ }
+ Key cache_key = get_image_callback_(user_data_,
+ clip,
+ frame,
+ get_libmv_input_mode(input_mode),
+ downscale,
+ region != NULL ? &libmv_region : NULL,
+ (libmv_FrameTransform*) transform,
+ &float_buffer,
+ &width,
+ &height,
+ &channels);
+
+ // TODO(sergey): Dumb code for until we can set data directly.
+ FloatImage temp_image(float_buffer,
+ height,
+ width,
+ channels);
+ destination->CopyFrom(temp_image);
+
+ return cache_key;
+ }
+
+ void ReleaseImage(Key cache_key) {
+ release_image_callback_(cache_key);
+ }
+
+ bool GetClipDimensions(int clip, int *width, int *height) {
+ return false;
+ }
+
+ int NumClips() {
+ return 1;
+ }
+
+ int NumFrames(int clip) {
+ return 0;
+ }
+
+ libmv_FrameAccessorUserData* user_data_;
+ libmv_GetImageCallback get_image_callback_;
+ libmv_ReleaseImageCallback release_image_callback_;
+};
+
+} // namespace
+
+libmv_FrameAccessor* libmv_FrameAccessorNew(
+ libmv_FrameAccessorUserData* user_data,
+ libmv_GetImageCallback get_image_callback,
+ libmv_ReleaseImageCallback release_image_callback) {
+ return (libmv_FrameAccessor*) LIBMV_OBJECT_NEW(LibmvFrameAccessor,
+ user_data,
+ get_image_callback,
+ release_image_callback);
+}
+
+void libmv_FrameAccessorDestroy(libmv_FrameAccessor* frame_accessor) {
+ LIBMV_OBJECT_DELETE(frame_accessor, LibmvFrameAccessor);
+}
+
+int64_t libmv_frameAccessorgetTransformKey(const libmv_FrameTransform *transform) {
+ return ((FrameAccessor::Transform*) transform)->key();
+}
+
+void libmv_frameAccessorgetTransformRun(const libmv_FrameTransform *transform,
+ const libmv_FloatImage *input_image,
+ libmv_FloatImage *output_image) {
+ const FloatImage input(input_image->buffer,
+ input_image->height,
+ input_image->width,
+ input_image->channels);
+
+ FloatImage output;
+ ((FrameAccessor::Transform*) transform)->run(input,
+ &output);
+
+ int num_pixels = output.Width() *output.Height() * output.Depth();
+ output_image->buffer = new float[num_pixels];
+ memcpy(output_image->buffer, output.Data(), num_pixels * sizeof(float));
+ output_image->width = output.Width();
+ output_image->height = output.Height();
+ output_image->channels = output.Depth();
+}
diff --git a/extern/libmv/intern/frame_accessor.h b/extern/libmv/intern/frame_accessor.h
new file mode 100644
index 00000000000..3e813fe7581
--- /dev/null
+++ b/extern/libmv/intern/frame_accessor.h
@@ -0,0 +1,79 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2014 Blender Foundation.
+ * All rights reserved.
+ *
+ * Contributor(s): Blender Foundation,
+ * Sergey Sharybin
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef LIBMV_C_API_FRAME_ACCESSOR_H_
+#define LIBMV_C_API_FRAME_ACCESSOR_H_
+
+#include <stdint.h>
+
+#include "intern/image.h"
+#include "intern/region.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct libmv_FrameAccessor libmv_FrameAccessor;
+typedef struct libmv_FrameTransform libmv_FrameTransform;
+typedef struct libmv_FrameAccessorUserData libmv_FrameAccessorUserData;
+typedef void *libmv_CacheKey;
+
+typedef enum {
+ LIBMV_IMAGE_MODE_MONO,
+ LIBMV_IMAGE_MODE_RGBA,
+} libmv_InputMode;
+
+typedef libmv_CacheKey (*libmv_GetImageCallback) (
+ libmv_FrameAccessorUserData* user_data,
+ int clip,
+ int frame,
+ libmv_InputMode input_mode,
+ int downscale,
+ const libmv_Region* region,
+ const libmv_FrameTransform* transform,
+ float** destination,
+ int* width,
+ int* height,
+ int* channels);
+
+typedef void (*libmv_ReleaseImageCallback) (libmv_CacheKey cache_key);
+
+libmv_FrameAccessor* libmv_FrameAccessorNew(
+ libmv_FrameAccessorUserData* user_data,
+ libmv_GetImageCallback get_image_callback,
+ libmv_ReleaseImageCallback release_image_callback);
+void libmv_FrameAccessorDestroy(libmv_FrameAccessor* frame_accessor);
+
+int64_t libmv_frameAccessorgetTransformKey(const libmv_FrameTransform *transform);
+
+void libmv_frameAccessorgetTransformRun(const libmv_FrameTransform *transform,
+ const libmv_FloatImage *input_image,
+ libmv_FloatImage *output_image);
+#ifdef __cplusplus
+}
+#endif
+
+#endif // LIBMV_C_API_FRAME_ACCESSOR_H_
diff --git a/extern/libmv/intern/image.cc b/extern/libmv/intern/image.cc
index 7e623bdbec7..5018caef5b1 100644
--- a/extern/libmv/intern/image.cc
+++ b/extern/libmv/intern/image.cc
@@ -34,7 +34,7 @@
using libmv::FloatImage;
using libmv::SamplePlanarPatch;
-void libmv_floatImaheDestroy(libmv_FloatImage *image) {
+void libmv_floatImageDestroy(libmv_FloatImage *image) {
delete [] image->buffer;
}
@@ -238,7 +238,7 @@ void libmv_samplePlanarPatchFloat(const float* image,
libmv_floatImageToFloatBuffer(libmv_patch, patch);
}
- void libmv_samplePlanarPatchByte(const unsigned char* image,
+void libmv_samplePlanarPatchByte(const unsigned char* image,
int width,
int height,
int channels,
@@ -268,5 +268,5 @@ void libmv_samplePlanarPatchFloat(const float* image,
warped_position_x,
warped_position_y);
- libmv_floatImageToByteBuffer(libmv_patch, patch);
+ libmv_floatImageToByteBuffer(libmv_patch, patch);
}
diff --git a/extern/libmv/intern/image.h b/extern/libmv/intern/image.h
index 9936e748b9d..1213943aac4 100644
--- a/extern/libmv/intern/image.h
+++ b/extern/libmv/intern/image.h
@@ -64,7 +64,7 @@ typedef struct libmv_FloatImage {
int channels;
} libmv_FloatImage;
-void libmv_floatImaheDestroy(libmv_FloatImage *image);
+void libmv_floatImageDestroy(libmv_FloatImage *image);
void libmv_samplePlanarPatchFloat(const float* image,
int width,
diff --git a/extern/libmv/intern/logging.cc b/extern/libmv/intern/logging.cc
index 4ab2d91c8b4..77b56ef4df3 100644
--- a/extern/libmv/intern/logging.cc
+++ b/extern/libmv/intern/logging.cc
@@ -35,21 +35,21 @@ void libmv_initLogging(const char* argv0) {
google::GLOG_FATAL);
google::InitGoogleLogging(argv0);
- google::SetCommandLineOption("logtostderr", "1");
- google::SetCommandLineOption("v", "0");
- google::SetCommandLineOption("stderrthreshold", severity_fatal);
- google::SetCommandLineOption("minloglevel", severity_fatal);
+ gflags::SetCommandLineOption("logtostderr", "1");
+ gflags::SetCommandLineOption("v", "0");
+ gflags::SetCommandLineOption("stderrthreshold", severity_fatal);
+ gflags::SetCommandLineOption("minloglevel", severity_fatal);
}
void libmv_startDebugLogging(void) {
- google::SetCommandLineOption("logtostderr", "1");
- google::SetCommandLineOption("v", "2");
- google::SetCommandLineOption("stderrthreshold", "1");
- google::SetCommandLineOption("minloglevel", "0");
+ gflags::SetCommandLineOption("logtostderr", "1");
+ gflags::SetCommandLineOption("v", "2");
+ gflags::SetCommandLineOption("stderrthreshold", "1");
+ gflags::SetCommandLineOption("minloglevel", "0");
}
void libmv_setLoggingVerbosity(int verbosity) {
char val[10];
snprintf(val, sizeof(val), "%d", verbosity);
- google::SetCommandLineOption("v", val);
+ gflags::SetCommandLineOption("v", val);
}
diff --git a/extern/libmv/intern/reconstruction.cc b/extern/libmv/intern/reconstruction.cc
index eb3677fd206..046671e467f 100644
--- a/extern/libmv/intern/reconstruction.cc
+++ b/extern/libmv/intern/reconstruction.cc
@@ -61,6 +61,7 @@ struct libmv_Reconstruction {
CameraIntrinsics *intrinsics;
double error;
+ bool is_valid;
};
namespace {
@@ -220,8 +221,7 @@ Marker libmv_projectMarker(const EuclideanPoint& point,
void libmv_getNormalizedTracks(const Tracks &tracks,
const CameraIntrinsics &camera_intrinsics,
- Tracks *normalized_tracks)
-{
+ Tracks *normalized_tracks) {
libmv::vector<Marker> markers = tracks.AllMarkers();
for (int i = 0; i < markers.size(); ++i) {
Marker &marker = markers[i];
@@ -290,6 +290,12 @@ libmv_Reconstruction *libmv_solveReconstruction(
LG << "number of markers for init: " << keyframe_markers.size();
+ if (keyframe_markers.size() < 8) {
+ LG << "No enough markers to initialize from";
+ libmv_reconstruction->is_valid = false;
+ return libmv_reconstruction;
+ }
+
update_callback.invoke(0, "Initial reconstruction");
EuclideanReconstructTwoFrames(keyframe_markers, &reconstruction);
@@ -320,6 +326,7 @@ libmv_Reconstruction *libmv_solveReconstruction(
progress_update_callback,
callback_customdata);
+ libmv_reconstruction->is_valid = true;
return (libmv_Reconstruction *) libmv_reconstruction;
}
@@ -378,9 +385,14 @@ libmv_Reconstruction *libmv_solveModal(
progress_update_callback,
callback_customdata);
+ libmv_reconstruction->is_valid = true;
return (libmv_Reconstruction *) libmv_reconstruction;
}
+int libmv_reconstructionIsValid(libmv_Reconstruction *libmv_reconstruction) {
+ return libmv_reconstruction->is_valid;
+}
+
void libmv_reconstructionDestroy(libmv_Reconstruction *libmv_reconstruction) {
LIBMV_OBJECT_DELETE(libmv_reconstruction->intrinsics, CameraIntrinsics);
LIBMV_OBJECT_DELETE(libmv_reconstruction, libmv_Reconstruction);
diff --git a/extern/libmv/intern/reconstruction.h b/extern/libmv/intern/reconstruction.h
index 744f4bafb0b..8b6b34a6142 100644
--- a/extern/libmv/intern/reconstruction.h
+++ b/extern/libmv/intern/reconstruction.h
@@ -31,10 +31,11 @@
extern "C" {
#endif
-typedef struct libmv_CameraIntrinsics libmv_CameraIntrinsics;
-typedef struct libmv_CameraIntrinsicsOptions libmv_CameraIntrinsicsOptions;
+struct libmv_Tracks;
+struct libmv_CameraIntrinsics;
+struct libmv_CameraIntrinsicsOptions;
+
typedef struct libmv_Reconstruction libmv_Reconstruction;
-typedef struct libmv_Tracks libmv_Tracks;
enum {
LIBMV_REFINE_FOCAL_LENGTH = (1 << 0),
@@ -54,19 +55,21 @@ typedef void (*reconstruct_progress_update_cb) (void* customdata,
const char* message);
libmv_Reconstruction* libmv_solveReconstruction(
- const libmv_Tracks* libmv_tracks,
- const libmv_CameraIntrinsicsOptions* libmv_camera_intrinsics_options,
+ const struct libmv_Tracks* libmv_tracks,
+ const struct libmv_CameraIntrinsicsOptions* libmv_camera_intrinsics_options,
libmv_ReconstructionOptions* libmv_reconstruction_options,
reconstruct_progress_update_cb progress_update_callback,
void* callback_customdata);
libmv_Reconstruction* libmv_solveModal(
- const libmv_Tracks* libmv_tracks,
- const libmv_CameraIntrinsicsOptions* libmv_camera_intrinsics_options,
+ const struct libmv_Tracks* libmv_tracks,
+ const struct libmv_CameraIntrinsicsOptions* libmv_camera_intrinsics_options,
const libmv_ReconstructionOptions* libmv_reconstruction_options,
reconstruct_progress_update_cb progress_update_callback,
void* callback_customdata);
+int libmv_reconstructionIsValid(libmv_Reconstruction *libmv_reconstruction);
+
void libmv_reconstructionDestroy(libmv_Reconstruction* libmv_reconstruction);
int libmv_reprojectionPointForTrack(
@@ -89,7 +92,7 @@ int libmv_reprojectionCameraForImage(
double libmv_reprojectionError(const libmv_Reconstruction* libmv_reconstruction);
-libmv_CameraIntrinsics* libmv_reconstructionExtractIntrinsics(
+struct libmv_CameraIntrinsics* libmv_reconstructionExtractIntrinsics(
libmv_Reconstruction *libmv_Reconstruction);
#ifdef __cplusplus
diff --git a/extern/libmv/intern/stub.cc b/extern/libmv/intern/stub.cc
index cd8bb8ab841..5d667baa880 100644
--- a/extern/libmv/intern/stub.cc
+++ b/extern/libmv/intern/stub.cc
@@ -97,6 +97,10 @@ void libmv_samplePlanarPatchByte(const unsigned char * /*image*/,
/* TODO(sergey): implement */
}
+void libmv_floatImageDestroy(libmv_FloatImage* /*image*/)
+{
+}
+
/* ************ Tracks ************ */
libmv_Tracks *libmv_tracksNew(void) {
@@ -134,6 +138,10 @@ libmv_Reconstruction *libmv_solveModal(
return NULL;
}
+int libmv_reconstructionIsValid(libmv_Reconstruction * /*libmv_reconstruction*/) {
+ return 0;
+}
+
int libmv_reprojectionPointForTrack(
const libmv_Reconstruction * /*libmv_reconstruction*/,
int /*track*/,
@@ -171,20 +179,20 @@ void libmv_reconstructionDestroy(
/* ************ Feature detector ************ */
-libmv_Features *libmv_detectFeaturesByte(const unsigned char */*image_buffer*/,
+libmv_Features *libmv_detectFeaturesByte(const unsigned char * /*image_buffer*/,
int /*width*/,
int /*height*/,
int /*channels*/,
- libmv_DetectOptions */*options*/) {
+ libmv_DetectOptions * /*options*/) {
return NULL;
}
struct libmv_Features *libmv_detectFeaturesFloat(
- const float */*image_buffer*/,
+ const float * /*image_buffer*/,
int /*width*/,
int /*height*/,
int /*channels*/,
- libmv_DetectOptions */*options*/) {
+ libmv_DetectOptions * /*options*/) {
return NULL;
}
@@ -239,7 +247,7 @@ void libmv_cameraIntrinsicsSetThreads(
}
void libmv_cameraIntrinsicsExtractOptions(
- const libmv_CameraIntrinsics */*libmv_intrinsics*/,
+ const libmv_CameraIntrinsics * /*libmv_intrinsics*/,
libmv_CameraIntrinsicsOptions *camera_intrinsics_options) {
memset(camera_intrinsics_options, 0, sizeof(libmv_CameraIntrinsicsOptions));
camera_intrinsics_options->focal_length = 1.0;
@@ -328,3 +336,68 @@ void libmv_homography2DFromCorrespondencesEuc(/* const */ double (*x1)[2],
H[1][1] = 1.0f;
H[2][2] = 1.0f;
}
+
+/* ************ autotrack ************ */
+
+libmv_AutoTrack* libmv_autoTrackNew(libmv_FrameAccessor* /*frame_accessor*/)
+{
+ return NULL;
+}
+
+void libmv_autoTrackDestroy(libmv_AutoTrack* /*libmv_autotrack*/)
+{
+}
+
+void libmv_autoTrackSetOptions(libmv_AutoTrack* /*libmv_autotrack*/,
+ const libmv_AutoTrackOptions* /*options*/)
+{
+}
+
+int libmv_autoTrackMarker(libmv_AutoTrack* /*libmv_autotrack*/,
+ const libmv_TrackRegionOptions* /*libmv_options*/,
+ libmv_Marker * /*libmv_tracker_marker*/,
+ libmv_TrackRegionResult* /*libmv_result*/)
+{
+ return 0;
+}
+
+void libmv_autoTrackAddMarker(libmv_AutoTrack* /*libmv_autotrack*/,
+ const libmv_Marker* /*libmv_marker*/)
+{
+}
+
+int libmv_autoTrackGetMarker(libmv_AutoTrack* /*libmv_autotrack*/,
+ int /*clip*/,
+ int /*frame*/,
+ int /*track*/,
+ libmv_Marker* /*libmv_marker*/)
+{
+ return 0;
+}
+
+/* ************ frame accessor ************ */
+
+libmv_FrameAccessor* libmv_FrameAccessorNew(
+ libmv_FrameAccessorUserData* /*user_data**/,
+ libmv_GetImageCallback /*get_image_callback*/,
+ libmv_ReleaseImageCallback /*release_image_callback*/)
+{
+ return NULL;
+}
+
+void libmv_FrameAccessorDestroy(libmv_FrameAccessor* /*frame_accessor*/)
+{
+}
+
+int64_t libmv_frameAccessorgetTransformKey(
+ const libmv_FrameTransform * /*transform*/)
+{
+ return 0;
+}
+
+void libmv_frameAccessorgetTransformRun(const libmv_FrameTransform* /*transform*/,
+ const libmv_FloatImage* /*input_image*/,
+ libmv_FloatImage* /*output_image*/)
+{
+}
+
diff --git a/extern/libmv/intern/track_region.h b/extern/libmv/intern/track_region.h
index 95ec124c3e1..7ed3e443e40 100644
--- a/extern/libmv/intern/track_region.h
+++ b/extern/libmv/intern/track_region.h
@@ -49,8 +49,8 @@ typedef struct libmv_TrackRegionResult {
#ifdef __cplusplus
namespace libmv {
- class TrackRegionOptions;
- class TrackRegionResult;
+ struct TrackRegionOptions;
+ struct TrackRegionResult;
}
void libmv_configureTrackRegionOptions(
const libmv_TrackRegionOptions& options,
diff --git a/extern/libmv/intern/tracksN.cc b/extern/libmv/intern/tracksN.cc
new file mode 100644
index 00000000000..9e1da88ef10
--- /dev/null
+++ b/extern/libmv/intern/tracksN.cc
@@ -0,0 +1,138 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2011 Blender Foundation.
+ * All rights reserved.
+ *
+ * Contributor(s): Blender Foundation,
+ * Sergey Sharybin
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include "intern/tracksN.h"
+#include "intern/utildefines.h"
+#include "libmv/autotrack/marker.h"
+#include "libmv/autotrack/tracks.h"
+
+using mv::Marker;
+using mv::Tracks;
+
+void libmv_apiMarkerToMarker(const libmv_Marker& libmv_marker,
+ Marker *marker) {
+ marker->clip = libmv_marker.clip;
+ marker->frame = libmv_marker.frame;
+ marker->track = libmv_marker.track;
+ marker->center(0) = libmv_marker.center[0];
+ marker->center(1) = libmv_marker.center[1];
+ for (int i = 0; i < 4; i++) {
+ marker->patch.coordinates(i, 0) = libmv_marker.patch[i][0];
+ marker->patch.coordinates(i, 1) = libmv_marker.patch[i][1];
+ }
+ marker->search_region.min(0) = libmv_marker.search_region_min[0];
+ marker->search_region.min(1) = libmv_marker.search_region_min[1];
+ marker->search_region.max(0) = libmv_marker.search_region_max[0];
+ marker->search_region.max(1) = libmv_marker.search_region_max[1];
+ marker->weight = libmv_marker.weight;
+ marker->source = (Marker::Source) libmv_marker.source;
+ marker->status = (Marker::Status) libmv_marker.status;
+ marker->reference_clip = libmv_marker.reference_clip;
+ marker->reference_frame = libmv_marker.reference_frame;
+ marker->model_type = (Marker::ModelType) libmv_marker.model_type;
+ marker->model_id = libmv_marker.model_id;
+ marker->disabled_channels = libmv_marker.disabled_channels;
+}
+
+void libmv_markerToApiMarker(const Marker& marker,
+ libmv_Marker *libmv_marker) {
+ libmv_marker->clip = marker.clip;
+ libmv_marker->frame = marker.frame;
+ libmv_marker->track = marker.track;
+ libmv_marker->center[0] = marker.center(0);
+ libmv_marker->center[1] = marker.center(1);
+ for (int i = 0; i < 4; i++) {
+ libmv_marker->patch[i][0] = marker.patch.coordinates(i, 0);
+ libmv_marker->patch[i][1] = marker.patch.coordinates(i, 1);
+ }
+ libmv_marker->search_region_min[0] = marker.search_region.min(0);
+ libmv_marker->search_region_min[1] = marker.search_region.min(1);
+ libmv_marker->search_region_max[0] = marker.search_region.max(0);
+ libmv_marker->search_region_max[1] = marker.search_region.max(1);
+ libmv_marker->weight = marker.weight;
+ libmv_marker->source = (libmv_MarkerSource) marker.source;
+ libmv_marker->status = (libmv_MarkerStatus) marker.status;
+ libmv_marker->reference_clip = marker.reference_clip;
+ libmv_marker->reference_frame = marker.reference_frame;
+ libmv_marker->model_type = (libmv_MarkerModelType) marker.model_type;
+ libmv_marker->model_id = marker.model_id;
+ libmv_marker->disabled_channels = marker.disabled_channels;
+}
+
+libmv_TracksN* libmv_tracksNewN(void) {
+ Tracks* tracks = LIBMV_OBJECT_NEW(Tracks);
+
+ return (libmv_TracksN*) tracks;
+}
+
+void libmv_tracksDestroyN(libmv_TracksN* libmv_tracks) {
+ LIBMV_OBJECT_DELETE(libmv_tracks, Tracks);
+}
+
+void libmv_tracksAddMarkerN(libmv_TracksN* libmv_tracks,
+ const libmv_Marker* libmv_marker) {
+ Marker marker;
+ libmv_apiMarkerToMarker(*libmv_marker, &marker);
+ ((Tracks*) libmv_tracks)->AddMarker(marker);
+}
+
+void libmv_tracksGetMarkerN(libmv_TracksN* libmv_tracks,
+ int clip,
+ int frame,
+ int track,
+ libmv_Marker* libmv_marker) {
+ Marker marker;
+ ((Tracks*) libmv_tracks)->GetMarker(clip, frame, track, &marker);
+ libmv_markerToApiMarker(marker, libmv_marker);
+}
+
+void libmv_tracksRemoveMarkerN(libmv_TracksN* libmv_tracks,
+ int clip,
+ int frame,
+ int track) {
+ ((Tracks *) libmv_tracks)->RemoveMarker(clip, frame, track);
+}
+
+void libmv_tracksRemoveMarkersForTrack(libmv_TracksN* libmv_tracks,
+ int track) {
+ ((Tracks *) libmv_tracks)->RemoveMarkersForTrack(track);
+}
+
+int libmv_tracksMaxClipN(libmv_TracksN* libmv_tracks) {
+ return ((Tracks*) libmv_tracks)->MaxClip();
+}
+
+int libmv_tracksMaxFrameN(libmv_TracksN* libmv_tracks, int clip) {
+ return ((Tracks*) libmv_tracks)->MaxFrame(clip);
+}
+
+int libmv_tracksMaxTrackN(libmv_TracksN* libmv_tracks) {
+ return ((Tracks*) libmv_tracks)->MaxTrack();
+}
+
+int libmv_tracksNumMarkersN(libmv_TracksN* libmv_tracks) {
+ return ((Tracks*) libmv_tracks)->NumMarkers();
+}
diff --git a/extern/libmv/intern/tracksN.h b/extern/libmv/intern/tracksN.h
new file mode 100644
index 00000000000..d0cb54e40bc
--- /dev/null
+++ b/extern/libmv/intern/tracksN.h
@@ -0,0 +1,129 @@
+/*
+ * ***** 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) 2011 Blender Foundation.
+ * All rights reserved.
+ *
+ * Contributor(s): Blender Foundation,
+ * Sergey Sharybin
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+// TODO(serrgey): For the time being we're converting simple pipeline
+// to an autotrack pipeline we call it tracks.
+// Once we've done with porting we remove N.
+
+#ifndef LIBMV_C_API_TRACKSN_H_
+#define LIBMV_C_API_TRACKSN_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct libmv_TracksN libmv_TracksN;
+
+// Keep order in this enums exactly the same as in mv::Marker.
+// Otherwise API wouldn't convert the values properly.
+typedef enum libmv_MarkerSource {
+ LIBMV_MARKER_SOURCE_MANUAL,
+ LIBMV_MARKER_SOURCE_DETECTED,
+ LIBMV_MARKER_SOURCE_TRACKED,
+ LIBMV_MARKER_SOURCE_MATCHED,
+ LIBMV_MARKER_SOURCE_PREDICTED,
+} libmv_MarkerSource;
+
+typedef enum libmv_MarkerStatus {
+ LIBMV_MARKER_STATUS_UNKNOWN,
+ LIBMV_MARKER_STATUS_INLIER,
+ LIBMV_MARKER_STATUS_OUTLIER,
+} libmv_MarkerStatus;
+
+typedef enum libmv_MarkerModelType {
+ LIBMV_MARKER_MODEL_TYPE_POINT,
+ LIBMV_MARKER_MODEL_TYPE_PLANE,
+ LIBMV_MARKER_MODEL_TYPE_LINE,
+ LIBMV_MARKER_MODEL_TYPE_CUBE,
+} libmv_MarkerModelType;
+
+enum libmv_MarkerChannel {
+ LIBMV_MARKER_CHANNEL_R = (1 << 0),
+ LIBMV_MARKER_CHANNEL_G = (1 << 1),
+ LIBMV_MARKER_CHANNEL_B = (1 << 2),
+};
+
+typedef struct libmv_Marker {
+ int clip;
+ int frame;
+ int track;
+ float center[2];
+ float patch[4][2];
+ float search_region_min[2];
+ float search_region_max[2];
+ float weight;
+ libmv_MarkerSource source;
+ libmv_MarkerStatus status;
+ int reference_clip;
+ int reference_frame;
+ libmv_MarkerModelType model_type;
+ int model_id;
+ int disabled_channels;
+} libmv_Marker;
+
+#ifdef __cplusplus
+namespace mv {
+ struct Marker;
+}
+void libmv_apiMarkerToMarker(const libmv_Marker& libmv_marker,
+ mv::Marker *marker);
+
+void libmv_markerToApiMarker(const mv::Marker& marker,
+ libmv_Marker *libmv_marker);
+#endif
+
+libmv_TracksN* libmv_tracksNewN(void);
+
+void libmv_tracksDestroyN(libmv_TracksN* libmv_tracks);
+
+
+void libmv_tracksAddMarkerN(libmv_TracksN* libmv_tracks,
+ const libmv_Marker* libmv_marker);
+
+void libmv_tracksGetMarkerN(libmv_TracksN* libmv_tracks,
+ int clip,
+ int frame,
+ int track,
+ libmv_Marker* libmv_marker);
+
+void libmv_tracksRemoveMarkerN(libmv_TracksN* libmv_tracks,
+ int clip,
+ int frame,
+ int track);
+
+void libmv_tracksRemoveMarkersForTrack(libmv_TracksN* libmv_tracks,
+ int track);
+
+int libmv_tracksMaxClipN(libmv_TracksN* libmv_tracks);
+int libmv_tracksMaxFrameN(libmv_TracksN* libmv_tracks, int clip);
+int libmv_tracksMaxTrackN(libmv_TracksN* libmv_tracks);
+int libmv_tracksNumMarkersN(libmv_TracksN* libmv_tracks);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // LIBMV_C_API_TRACKS_H_
diff --git a/extern/libmv/libmv-capi.h b/extern/libmv/libmv-capi.h
index 524f1822bc7..92e206a19b2 100644
--- a/extern/libmv/libmv-capi.h
+++ b/extern/libmv/libmv-capi.h
@@ -27,13 +27,16 @@
#ifndef LIBMV_C_API_H
#define LIBMV_C_API_H
+#include "intern/autotrack.h"
#include "intern/camera_intrinsics.h"
#include "intern/detector.h"
+#include "intern/frame_accessor.h"
#include "intern/homography.h"
#include "intern/image.h"
#include "intern/logging.h"
#include "intern/reconstruction.h"
#include "intern/track_region.h"
#include "intern/tracks.h"
+#include "intern/tracksN.h"
#endif // LIBMV_C_API_H
diff --git a/extern/libmv/libmv/autotrack/autotrack.cc b/extern/libmv/libmv/autotrack/autotrack.cc
new file mode 100644
index 00000000000..4c7bdf1fde8
--- /dev/null
+++ b/extern/libmv/libmv/autotrack/autotrack.cc
@@ -0,0 +1,291 @@
+// Copyright (c) 2014 libmv authors.
+//
+// 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.
+//
+// Author: mierle@gmail.com (Keir Mierle)
+
+#include "libmv/autotrack/autotrack.h"
+#include "libmv/autotrack/quad.h"
+#include "libmv/autotrack/frame_accessor.h"
+#include "libmv/autotrack/predict_tracks.h"
+#include "libmv/base/scoped_ptr.h"
+#include "libmv/logging/logging.h"
+#include "libmv/numeric/numeric.h"
+
+namespace mv {
+
+namespace {
+
+class DisableChannelsTransform : public FrameAccessor::Transform {
+ public:
+ DisableChannelsTransform(int disabled_channels)
+ : disabled_channels_(disabled_channels) { }
+
+ int64_t key() const {
+ return disabled_channels_;
+ }
+
+ void run(const FloatImage& input, FloatImage* output) const {
+ bool disable_red = (disabled_channels_ & Marker::CHANNEL_R) != 0,
+ disable_green = (disabled_channels_ & Marker::CHANNEL_G) != 0,
+ disable_blue = (disabled_channels_ & Marker::CHANNEL_B) != 0;
+
+ LG << "Disabling channels: "
+ << (disable_red ? "R " : "")
+ << (disable_green ? "G " : "")
+ << (disable_blue ? "B" : "");
+
+ // It's important to rescale the resultappropriately so that e.g. if only
+ // blue is selected, it's not zeroed out.
+ float scale = (disable_red ? 0.0f : 0.2126f) +
+ (disable_green ? 0.0f : 0.7152f) +
+ (disable_blue ? 0.0f : 0.0722f);
+
+ output->Resize(input.Height(), input.Width(), 1);
+ for (int y = 0; y < input.Height(); y++) {
+ for (int x = 0; x < input.Width(); x++) {
+ float r = disable_red ? 0.0f : input(y, x, 0);
+ float g = disable_green ? 0.0f : input(y, x, 1);
+ float b = disable_blue ? 0.0f : input(y, x, 2);
+ (*output)(y, x, 0) = (0.2126f * r + 0.7152f * g + 0.0722f * b) / scale;
+ }
+ }
+ }
+
+ private:
+ // Bitfield representing visible channels, bits are from Marker::Channel.
+ int disabled_channels_;
+};
+
+template<typename QuadT, typename ArrayT>
+void QuadToArrays(const QuadT& quad, ArrayT* x, ArrayT* y) {
+ for (int i = 0; i < 4; ++i) {
+ x[i] = quad.coordinates(i, 0);
+ y[i] = quad.coordinates(i, 1);
+ }
+}
+
+void MarkerToArrays(const Marker& marker, double* x, double* y) {
+ Quad2Df offset_quad = marker.patch;
+ Vec2f origin = marker.search_region.Rounded().min;
+ offset_quad.coordinates.rowwise() -= origin.transpose();
+ QuadToArrays(offset_quad, x, y);
+ x[4] = marker.center.x() - origin(0);
+ y[4] = marker.center.y() - origin(1);
+}
+
+FrameAccessor::Key GetImageForMarker(const Marker& marker,
+ FrameAccessor* frame_accessor,
+ FloatImage* image) {
+ // TODO(sergey): Currently we pass float region to the accessor,
+ // but we don't want the accessor to decide the rounding, so we
+ // do rounding here.
+ // Ideally we would need to pass IntRegion to the frame accessor.
+ Region region = marker.search_region.Rounded();
+ libmv::scoped_ptr<FrameAccessor::Transform> transform = NULL;
+ if (marker.disabled_channels != 0) {
+ transform.reset(new DisableChannelsTransform(marker.disabled_channels));
+ }
+ return frame_accessor->GetImage(marker.clip,
+ marker.frame,
+ FrameAccessor::MONO,
+ 0, // No downscale for now.
+ &region,
+ transform.get(),
+ image);
+}
+
+} // namespace
+
+bool AutoTrack::TrackMarker(Marker* tracked_marker,
+ TrackRegionResult* result,
+ const TrackRegionOptions* track_options) {
+ // Try to predict the location of the second marker.
+ bool predicted_position = false;
+ if (PredictMarkerPosition(tracks_, tracked_marker)) {
+ LG << "Succesfully predicted!";
+ predicted_position = true;
+ } else {
+ LG << "Prediction failed; trying to track anyway.";
+ }
+
+ Marker reference_marker;
+ tracks_.GetMarker(tracked_marker->reference_clip,
+ tracked_marker->reference_frame,
+ tracked_marker->track,
+ &reference_marker);
+
+ // Convert markers into the format expected by TrackRegion.
+ double x1[5], y1[5];
+ MarkerToArrays(reference_marker, x1, y1);
+
+ double x2[5], y2[5];
+ MarkerToArrays(*tracked_marker, x2, y2);
+
+ // TODO(keir): Technically this could take a smaller slice from the source
+ // image instead of taking one the size of the search window.
+ FloatImage reference_image;
+ FrameAccessor::Key reference_key = GetImageForMarker(reference_marker,
+ frame_accessor_,
+ &reference_image);
+ if (!reference_key) {
+ LG << "Couldn't get frame for reference marker: " << reference_marker;
+ return false;
+ }
+
+ FloatImage tracked_image;
+ FrameAccessor::Key tracked_key = GetImageForMarker(*tracked_marker,
+ frame_accessor_,
+ &tracked_image);
+ if (!tracked_key) {
+ frame_accessor_->ReleaseImage(reference_key);
+ LG << "Couldn't get frame for tracked marker: " << tracked_marker;
+ return false;
+ }
+
+ // Store original position befoer tracking, so we can claculate offset later.
+ Vec2f original_center = tracked_marker->center;
+
+ // Do the tracking!
+ TrackRegionOptions local_track_region_options;
+ if (track_options) {
+ local_track_region_options = *track_options;
+ }
+ local_track_region_options.num_extra_points = 1; // For center point.
+ local_track_region_options.attempt_refine_before_brute = predicted_position;
+ TrackRegion(reference_image,
+ tracked_image,
+ x1, y1,
+ local_track_region_options,
+ x2, y2,
+ result);
+
+ // Copy results over the tracked marker.
+ Vec2f tracked_origin = tracked_marker->search_region.Rounded().min;
+ for (int i = 0; i < 4; ++i) {
+ tracked_marker->patch.coordinates(i, 0) = x2[i] + tracked_origin[0];
+ tracked_marker->patch.coordinates(i, 1) = y2[i] + tracked_origin[1];
+ }
+ tracked_marker->center(0) = x2[4] + tracked_origin[0];
+ tracked_marker->center(1) = y2[4] + tracked_origin[1];
+ Vec2f delta = tracked_marker->center - original_center;
+ tracked_marker->search_region.Offset(delta);
+ tracked_marker->source = Marker::TRACKED;
+ tracked_marker->status = Marker::UNKNOWN;
+ tracked_marker->reference_clip = reference_marker.clip;
+ tracked_marker->reference_frame = reference_marker.frame;
+
+ // Release the images from the accessor cache.
+ frame_accessor_->ReleaseImage(reference_key);
+ frame_accessor_->ReleaseImage(tracked_key);
+
+ // TODO(keir): Possibly the return here should get removed since the results
+ // are part of TrackResult. However, eventually the autotrack stuff will have
+ // extra status (e.g. prediction fail, etc) that should get included.
+ return true;
+}
+
+void AutoTrack::AddMarker(const Marker& marker) {
+ tracks_.AddMarker(marker);
+}
+
+void AutoTrack::SetMarkers(vector<Marker>* markers) {
+ tracks_.SetMarkers(markers);
+}
+
+bool AutoTrack::GetMarker(int clip, int frame, int track,
+ Marker* markers) const {
+ return tracks_.GetMarker(clip, frame, track, markers);
+}
+
+void AutoTrack::DetectAndTrack(const DetectAndTrackOptions& options) {
+ int num_clips = frame_accessor_->NumClips();
+ for (int clip = 0; clip < num_clips; ++clip) {
+ int num_frames = frame_accessor_->NumFrames(clip);
+ vector<Marker> previous_frame_markers;
+ // Q: How to decide track #s when detecting?
+ // Q: How to match markers from previous frame? set of prev frame tracks?
+ // Q: How to decide what markers should get tracked and which ones should not?
+ for (int frame = 0; frame < num_frames; ++frame) {
+ if (Cancelled()) {
+ LG << "Got cancel message while detecting and tracking...";
+ return;
+ }
+ // First, get or detect markers for this frame.
+ vector<Marker> this_frame_markers;
+ tracks_.GetMarkersInFrame(clip, frame, &this_frame_markers);
+ LG << "Clip " << clip << ", frame " << frame << " have "
+ << this_frame_markers.size();
+ if (this_frame_markers.size() < options.min_num_features) {
+ DetectFeaturesInFrame(clip, frame);
+ this_frame_markers.clear();
+ tracks_.GetMarkersInFrame(clip, frame, &this_frame_markers);
+ LG << "... detected " << this_frame_markers.size() << " features.";
+ }
+ if (previous_frame_markers.empty()) {
+ LG << "First frame; skipping tracking stage.";
+ previous_frame_markers.swap(this_frame_markers);
+ continue;
+ }
+ // Second, find tracks that should get tracked forward into this frame.
+ // To avoid tracking markers that are already tracked to this frame, make
+ // a sorted set of the tracks that exist in the last frame.
+ vector<int> tracks_in_this_frame;
+ for (int i = 0; i < this_frame_markers.size(); ++i) {
+ tracks_in_this_frame.push_back(this_frame_markers[i].track);
+ }
+ std::sort(tracks_in_this_frame.begin(),
+ tracks_in_this_frame.end());
+
+ // Find tracks in the previous frame that are not in this one.
+ vector<Marker*> previous_frame_markers_to_track;
+ int num_skipped = 0;
+ for (int i = 0; i < previous_frame_markers.size(); ++i) {
+ if (std::binary_search(tracks_in_this_frame.begin(),
+ tracks_in_this_frame.end(),
+ previous_frame_markers[i].track)) {
+ num_skipped++;
+ } else {
+ previous_frame_markers_to_track.push_back(&previous_frame_markers[i]);
+ }
+ }
+
+ // Finally track the markers from the last frame into this one.
+ // TODO(keir): Use OMP.
+ for (int i = 0; i < previous_frame_markers_to_track.size(); ++i) {
+ Marker this_frame_marker = *previous_frame_markers_to_track[i];
+ this_frame_marker.frame = frame;
+ LG << "Tracking: " << this_frame_marker;
+ TrackRegionResult result;
+ TrackMarker(&this_frame_marker, &result);
+ if (result.is_usable()) {
+ LG << "Success: " << this_frame_marker;
+ AddMarker(this_frame_marker);
+ this_frame_markers.push_back(this_frame_marker);
+ } else {
+ LG << "Failed to track: " << this_frame_marker;
+ }
+ }
+ // Put the markers from this frame
+ previous_frame_markers.swap(this_frame_markers);
+ }
+ }
+}
+
+} // namespace mv
diff --git a/extern/libmv/libmv/autotrack/autotrack.h b/extern/libmv/libmv/autotrack/autotrack.h
new file mode 100644
index 00000000000..1d7422f54e7
--- /dev/null
+++ b/extern/libmv/libmv/autotrack/autotrack.h
@@ -0,0 +1,226 @@
+// Copyright (c) 2014 libmv authors.
+//
+// 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.
+//
+// Author: mierle@gmail.com (Keir Mierle)
+
+#ifndef LIBMV_AUTOTRACK_AUTOTRACK_H_
+#define LIBMV_AUTOTRACK_AUTOTRACK_H_
+
+#include "libmv/autotrack/tracks.h"
+#include "libmv/autotrack/region.h"
+#include "libmv/tracking/track_region.h"
+
+namespace libmv {
+class CameraIntrinsics;
+};
+
+namespace mv {
+
+using libmv::CameraIntrinsics;
+using libmv::TrackRegionOptions;
+using libmv::TrackRegionResult;
+
+struct FrameAccessor;
+class OperationListener;
+
+// The coordinator of all tracking operations; keeps track of all state
+// relating to tracking and reconstruction; for example, 2D tracks and motion
+// models, reconstructed cameras, points, and planes; tracking settings; etc.
+//
+// Typical usage for full autotrack:
+//
+// AutoTrack auto_track(image_accessor);
+// auto_track.SetNumFramesInClip(0, 10);
+// auto_track.SetNumFramesInClip(1, 54);
+// auto_track.AutoTrack()
+//
+// It is also possible to specify options to control the reconstruction.
+// Furthermore, the individual methods of reconstruction are exposed to make it
+// possible to interact with the pipeline as it runs. For example, to track one
+// marker across frames,
+//
+// AutoTrack auto_track(image_accessor);
+// auto_track.SetNumFramesInClip(0, 10);
+// auto_track.SetNumFramesInClip(1, 54);
+// auto_track.AddMarker(...);
+// auto_track.TrackMarkerToFrame(int clip1, int frame1,
+// int clip2, int frame2,
+// options?)
+//
+class AutoTrack {
+ public:
+ struct Options {
+ // Default configuration for 2D tracking when calling TrackMarkerToFrame().
+ TrackRegionOptions track_region;
+
+ // Default search window for region tracking, in absolute frame pixels.
+ Region search_region;
+ };
+
+ AutoTrack(FrameAccessor* frame_accessor)
+ : frame_accessor_(frame_accessor) {}
+
+ // Marker manipulation.
+ // Clip manipulation.
+
+ // Set the number of clips. These clips will get accessed from the frame
+ // accessor, matches between frames found, and a reconstruction created.
+ //void SetNumFrames(int clip, int num_frames);
+
+ // Tracking & Matching
+
+ // Find the marker for the track in the frame indicated by the marker.
+ // Caller maintains ownership of *result and *tracked_marker.
+ bool TrackMarker(Marker* tracked_marker,
+ TrackRegionResult* result,
+ const TrackRegionOptions* track_options=NULL);
+
+ // Wrapper around Tracks API; however these may add additional processing.
+ void AddMarker(const Marker& tracked_marker);
+ void SetMarkers(vector<Marker>* markers);
+ bool GetMarker(int clip, int frame, int track, Marker* marker) const;
+
+ // TODO(keir): Implement frame matching! This could be very cool for loop
+ // closing and connecting across clips.
+ //void MatchFrames(int clip1, int frame1, int clip2, int frame2) {}
+
+ // Wrapper around the Reconstruction API.
+ // Returns the new ID.
+ int AddCameraIntrinsics(CameraIntrinsics* intrinsics) {
+ (void) intrinsics;
+ return 0;
+ } // XXX
+ int SetClipIntrinsics(int clip, int intrinsics) {
+ (void) clip;
+ (void) intrinsics;
+ return 0;
+ } // XXX
+
+ enum Motion {
+ GENERAL_CAMERA_MOTION,
+ TRIPOD_CAMERA_MOTION,
+ };
+ int SetClipMotion(int clip, Motion motion) {
+ (void) clip;
+ (void) motion;
+ return 0;
+ } // XXX
+
+ // Decide what to refine for the given intrinsics. bundle_options is from
+ // bundle.h (e.g. BUNDLE_FOCAL_LENGTH | BUNDLE_RADIAL_K1).
+ void SetIntrinsicsRefine(int intrinsics, int bundle_options) {
+ (void) intrinsics;
+ (void) bundle_options;
+ } // XXX
+
+ // Keyframe read/write.
+ struct ClipFrame {
+ int clip;
+ int frame;
+ };
+ const vector<ClipFrame>& keyframes() { return keyframes_; }
+ void ClearKeyframes() { keyframes_.clear(); }
+ void SetKeyframes(const vector<ClipFrame>& keyframes) {
+ keyframes_ = keyframes;
+ }
+
+ // What about reporting what happened? -- callbacks; maybe result struct.
+ void Reconstruct();
+
+ // Detect and track in 2D.
+ struct DetectAndTrackOptions {
+ int min_num_features;
+ };
+ void DetectAndTrack(const DetectAndTrackOptions& options);
+
+ struct DetectFeaturesInFrameOptions {
+ };
+ void DetectFeaturesInFrame(int clip, int frame,
+ const DetectFeaturesInFrameOptions* options=NULL) {
+ (void) clip;
+ (void) frame;
+ (void) options;
+ } // XXX
+
+ // Does not take ownership of the given listener, but keeps a reference to it.
+ void AddListener(OperationListener* listener) {(void) listener;} // XXX
+
+ // Create the initial reconstruction,
+ //void FindInitialReconstruction();
+
+ // State machine
+ //
+ // Question: Have explicit state? Or determine state from existing data?
+ // Conclusion: Determine state from existing data.
+ //
+ // Preliminary state thoughts
+ //
+ // No tracks or markers
+ // - Tracks empty.
+ //
+ // Initial tracks found
+ // - All images have at least 5 tracks
+ //
+ // Ran RANSAC on tracks to mark inliers / outliers.
+ // - All images have at least 8 "inlier" tracks
+ //
+ // Detector matching run to close loops and match across clips
+ // - At least 5 matching tracks between clips
+ //
+ // Initial reconstruction found (2 frames)?
+ // - There exists two cameras with intrinsics / extrinsics
+ //
+ // Preliminary reconstruction finished
+ // - Poses for all frames in all clips estimated.
+ //
+ // Final reconstruction finished
+ // - Final reconstruction bundle adjusted.
+
+ // For now, expose options directly. In the future this may change.
+ Options options;
+
+ private:
+ bool Log();
+ bool Progress();
+ bool Cancelled() { return false; }
+
+ Tracks tracks_; // May be normalized camera coordinates or raw pixels.
+ //Reconstruction reconstruction_;
+
+ // TODO(keir): Add the motion models here.
+ //vector<MotionModel> motion_models_;
+
+ // TODO(keir): Should num_clips and num_frames get moved to FrameAccessor?
+ // TODO(keir): What about masking for clips and frames to prevent various
+ // things like reconstruction or tracking from happening on certain frames?
+ FrameAccessor* frame_accessor_;
+ //int num_clips_;
+ //vector<int> num_frames_; // Indexed by clip.
+
+ // The intrinsics for each clip, assuming each clip has fixed intrinsics.
+ // TODO(keir): Decide what the semantics should be for varying focal length.
+ vector<int> clip_intrinsics_;
+
+ vector<ClipFrame> keyframes_;
+};
+
+} // namespace mv
+
+#endif // LIBMV_AUTOTRACK_AUTOTRACK_H_
diff --git a/extern/libmv/libmv/autotrack/callbacks.h b/extern/libmv/libmv/autotrack/callbacks.h
new file mode 100644
index 00000000000..e65841de3ce
--- /dev/null
+++ b/extern/libmv/libmv/autotrack/callbacks.h
@@ -0,0 +1,38 @@
+// Copyright (c) 2014 libmv authors.
+//
+// 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.
+//
+// Author: mierle@gmail.com (Keir Mierle)
+
+#ifndef LIBMV_AUTOTRACK_LISTENER_H_
+#define LIBMV_AUTOTRACK_LISTENER_H_
+
+namespace mv {
+
+struct OperationListener {
+ // All hooks return true to continue or false to indicate the operation
+ // should abort. Hooks should be thread safe (reentrant).
+ virtual bool Log(const string& message) = 0;
+ virtual bool Progress(double fraction) = 0;
+ virtual bool Cancelled() = 0;
+};
+
+} // namespace mv
+
+#endif // LIBMV_AUTOTRACK_LISTENER_H_
diff --git a/extern/libmv/libmv/autotrack/frame_accessor.h b/extern/libmv/libmv/autotrack/frame_accessor.h
new file mode 100644
index 00000000000..8de5d865cd7
--- /dev/null
+++ b/extern/libmv/libmv/autotrack/frame_accessor.h
@@ -0,0 +1,86 @@
+// Copyright (c) 2014 libmv authors.
+//
+// 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.
+//
+// Author: mierle@gmail.com (Keir Mierle)
+
+#ifndef LIBMV_AUTOTRACK_FRAME_ACCESSOR_H_
+#define LIBMV_AUTOTRACK_FRAME_ACCESSOR_H_
+
+#include <stdint.h>
+
+#include "libmv/image/image.h"
+
+namespace mv {
+
+struct Region;
+
+using libmv::FloatImage;
+
+// This is the abstraction to different sources of images that will be part of
+// a reconstruction. These may come from disk or they may come from Blender. In
+// most cases it's expected that the implementation provides some caching
+// otherwise performance will be terrible. Sometimes the images need to get
+// filtered, and this interface provides for that as well (and permits
+// implementations to cache filtered image pieces).
+struct FrameAccessor {
+ struct Transform {
+ virtual ~Transform() { }
+ // The key should depend on the transform arguments. Must be non-zero.
+ virtual int64_t key() const = 0;
+
+ // Apply the expected transform. Output is sized correctly already.
+ // TODO(keir): What about blurs that need to access pixels outside the ROI?
+ virtual void run(const FloatImage& input, FloatImage* output) const = 0;
+ };
+
+ enum InputMode {
+ MONO,
+ RGBA
+ };
+
+ typedef void* Key;
+
+ // Get a possibly-filtered version of a frame of a video. Downscale will
+ // cause the input image to get downscaled by 2^downscale for pyramid access.
+ // Region is always in original-image coordinates, and describes the
+ // requested area. The transform describes an (optional) transform to apply
+ // to the image before it is returned.
+ //
+ // When done with an image, you must call ReleaseImage with the returned key.
+ virtual Key GetImage(int clip,
+ int frame,
+ InputMode input_mode,
+ int downscale, // Downscale by 2^downscale.
+ const Region* region, // Get full image if NULL.
+ const Transform* transform, // May be NULL.
+ FloatImage* destination) = 0;
+
+ // Releases an image from the frame accessor. Non-caching implementations may
+ // free the image immediately; others may hold onto the image.
+ virtual void ReleaseImage(Key) = 0;
+
+ virtual bool GetClipDimensions(int clip, int* width, int* height) = 0;
+ virtual int NumClips() = 0;
+ virtual int NumFrames(int clip) = 0;
+};
+
+} // namespace libmv
+
+#endif // LIBMV_AUTOTRACK_FRAME_ACCESSOR_H_
diff --git a/extern/libmv/libmv/autotrack/marker.h b/extern/libmv/libmv/autotrack/marker.h
new file mode 100644
index 00000000000..bb803313af8
--- /dev/null
+++ b/extern/libmv/libmv/autotrack/marker.h
@@ -0,0 +1,144 @@
+// Copyright (c) 2014 libmv authors.
+//
+// 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.
+//
+// Author: mierle@gmail.com (Keir Mierle)
+
+#ifndef LIBMV_AUTOTRACK_MARKER_H_
+#define LIBMV_AUTOTRACK_MARKER_H_
+
+#include <ostream>
+
+#include "libmv/autotrack/quad.h"
+#include "libmv/autotrack/region.h"
+#include "libmv/numeric/numeric.h"
+
+namespace mv {
+
+using libmv::Vec2f;
+
+// A marker is the 2D location of a tracked region (quad) in an image.
+// Note that some of this information could be normalized by having a
+// collection of inter-connected structs. Instead the "fat Marker" design below
+// trades memory for data structure simplicity.
+struct Marker {
+ int clip; // The clip this marker is from.
+ int frame; // The frame within the clip this marker is from.
+ int track; // The track this marker is from.
+
+ // The center of the marker in frame coordinates. This is typically, but not
+ // always, the same as the center of the patch.
+ Vec2f center;
+
+ // A frame-realtive quad defining the part of the image the marker covers.
+ // For reference markers, the pixels in the patch are the tracking pattern.
+ Quad2Df patch;
+
+ // Some markers are less certain than others; the weight determines the
+ // amount this marker contributes to the error. 1.0 indicates normal
+ // contribution; 0.0 indicates a zero-weight track (and will be omitted from
+ // bundle adjustment).
+ float weight;
+
+ enum Source {
+ MANUAL, // The user placed this marker manually.
+ DETECTED, // A keypoint detector found this point.
+ TRACKED, // The tracking algorithm placed this marker.
+ MATCHED, // A matching algorithm (e.g. SIFT or SURF or ORB) found this.
+ PREDICTED, // A motion model predicted this marker. This is needed for
+ // handling occlusions in some cases where an imaginary marker
+ // is placed to keep camera motion smooth.
+ };
+ Source source;
+
+ // Markers may be inliers or outliers if the tracking fails; this allows
+ // visualizing the markers in the image.
+ enum Status {
+ UNKNOWN,
+ INLIER,
+ OUTLIER
+ };
+ Status status;
+
+ // When doing correlation tracking, where to search in the current frame for
+ // the pattern from the reference frame, in absolute frame coordinates.
+ Region search_region;
+
+ // For tracked and matched markers, indicates what the reference was.
+ int reference_clip;
+ int reference_frame;
+
+ // Model related information for non-point tracks.
+ //
+ // Some tracks are on a larger object, such as a plane or a line or perhaps
+ // another primitive (a rectangular prisim). This captures the information
+ // needed to say that for example a collection of markers belongs to model #2
+ // (and model #2 is a plane).
+ enum ModelType {
+ POINT,
+ PLANE,
+ LINE,
+ CUBE
+ };
+ ModelType model_type;
+
+ // The model ID this track (e.g. the second model, which is a plane).
+ int model_id;
+
+ // TODO(keir): Add a "int model_argument" to capture that e.g. a marker is on
+ // the 3rd face of a cube.
+
+ enum Channel {
+ CHANNEL_R = (1 << 0),
+ CHANNEL_G = (1 << 1),
+ CHANNEL_B = (1 << 2),
+ };
+
+ // Channels from the original frame which this marker is unable to see.
+ int disabled_channels;
+
+ // Offset everything (center, patch, search) by the given delta.
+ template<typename T>
+ void Offset(const T& offset) {
+ center += offset.template cast<float>();
+ patch.coordinates.rowwise() += offset.template cast<int>();
+ search_region.Offset(offset);
+ }
+
+ // Shift the center to the given new position (and patch, search).
+ template<typename T>
+ void SetPosition(const T& new_center) {
+ Offset(new_center - center);
+ }
+};
+
+inline std::ostream& operator<<(std::ostream& out, const Marker& marker) {
+ out << "{"
+ << marker.clip << ", "
+ << marker.frame << ", "
+ << marker.track << ", ("
+ << marker.center.x() << ", "
+ << marker.center.y() << ")"
+ << "}";
+ return out;
+}
+
+} // namespace mv
+
+#endif // LIBMV_AUTOTRACK_MARKER_H_
diff --git a/extern/libmv/libmv/autotrack/model.h b/extern/libmv/libmv/autotrack/model.h
new file mode 100644
index 00000000000..1165281cdac
--- /dev/null
+++ b/extern/libmv/libmv/autotrack/model.h
@@ -0,0 +1,44 @@
+// Copyright (c) 2014 libmv authors.
+//
+// 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.
+//
+// Author: mierle@gmail.com (Keir Mierle)
+
+#ifndef LIBMV_AUTOTRACK_MODEL_H_
+#define LIBMV_AUTOTRACK_MODEL_H_
+
+#include "libmv/numeric/numeric.h"
+#include "libmv/autotrack/quad.h"
+
+namespace mv {
+
+struct Model {
+ enum ModelType {
+ POINT,
+ PLANE,
+ LINE,
+ CUBE
+ };
+
+ // ???
+};
+
+} // namespace mv
+
+#endif // LIBMV_AUTOTRACK_MODEL_H_
diff --git a/extern/libmv/libmv/autotrack/predict_tracks.cc b/extern/libmv/libmv/autotrack/predict_tracks.cc
new file mode 100644
index 00000000000..adc986a0033
--- /dev/null
+++ b/extern/libmv/libmv/autotrack/predict_tracks.cc
@@ -0,0 +1,316 @@
+// Copyright (c) 2014 libmv authors.
+//
+// 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.
+//
+// Author: mierle@gmail.com (Keir Mierle)
+
+#include "libmv/autotrack/marker.h"
+#include "libmv/autotrack/predict_tracks.h"
+#include "libmv/autotrack/tracks.h"
+#include "libmv/base/vector.h"
+#include "libmv/logging/logging.h"
+#include "libmv/tracking/kalman_filter.h"
+
+namespace mv {
+
+namespace {
+
+using libmv::vector;
+using libmv::Vec2;
+
+// Implied time delta between steps. Set empirically by tweaking and seeing
+// what numbers did best at prediction.
+const double dt = 3.8;
+
+// State transition matrix.
+
+// The states for predicting a track are as follows:
+//
+// 0 - X position
+// 1 - X velocity
+// 2 - X acceleration
+// 3 - Y position
+// 4 - Y velocity
+// 5 - Y acceleration
+//
+// Note that in the velocity-only state transition matrix, the acceleration
+// component is ignored; so technically the system could be modelled with only
+// 4 states instead of 6. For ease of implementation, this keeps order 6.
+
+// Choose one or the other model from below (velocity or acceleration).
+
+// For a typical system having constant velocity. This gives smooth-appearing
+// predictions, but they are not always as accurate.
+const double velocity_state_transition_data[] = {
+ 1, dt, 0, 0, 0, 0,
+ 0, 1, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 1, dt, 0,
+ 0, 0, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0, 1
+};
+
+// This 3rd-order system also models acceleration. This makes for "jerky"
+// predictions, but that tend to be more accurate.
+const double acceleration_state_transition_data[] = {
+ 1, dt, dt*dt/2, 0, 0, 0,
+ 0, 1, dt, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 1, dt, dt*dt/2,
+ 0, 0, 0, 0, 1, dt,
+ 0, 0, 0, 0, 0, 1
+};
+
+// This system (attempts) to add an angular velocity component. However, it's
+// total junk.
+const double angular_state_transition_data[] = {
+ 1, dt, -dt, 0, 0, 0, // Position x
+ 0, 1, 0, 0, 0, 0, // Velocity x
+ 0, 0, 1, 0, 0, 0, // Angular momentum
+ 0, 0, dt, 1, dt, 0, // Position y
+ 0, 0, 0, 0, 1, 0, // Velocity y
+ 0, 0, 0, 0, 0, 1 // Ignored
+};
+
+const double* state_transition_data = velocity_state_transition_data;
+
+// Observation matrix.
+const double observation_data[] = {
+ 1., 0., 0., 0., 0., 0.,
+ 0., 0., 0., 1., 0., 0.
+};
+
+// Process covariance.
+const double process_covariance_data[] = {
+ 35, 0, 0, 0, 0, 0,
+ 0, 5, 0, 0, 0, 0,
+ 0, 0, 5, 0, 0, 0,
+ 0, 0, 0, 35, 0, 0,
+ 0, 0, 0, 0, 5, 0,
+ 0, 0, 0, 0, 0, 5
+};
+
+// Process covariance.
+const double measurement_covariance_data[] = {
+ 0.01, 0.00,
+ 0.00, 0.01,
+};
+
+// Initial covariance.
+const double initial_covariance_data[] = {
+ 10, 0, 0, 0, 0, 0,
+ 0, 1, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 10, 0, 0,
+ 0, 0, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0, 1
+};
+
+typedef mv::KalmanFilter<double, 6, 2> TrackerKalman;
+
+TrackerKalman filter(state_transition_data,
+ observation_data,
+ process_covariance_data,
+ measurement_covariance_data);
+
+bool OrderByFrameLessThan(const Marker* a, const Marker* b) {
+ if (a->frame == b->frame) {
+ if (a->clip == b->clip) {
+ return a->track < b->track;
+ }
+ return a->clip < b->clip;
+ }
+ return a->frame < b-> frame;
+}
+
+// Predicted must be after the previous markers (in the frame numbering sense).
+void RunPrediction(const vector<Marker*> previous_markers,
+ Marker* predicted_marker) {
+ TrackerKalman::State state;
+ state.mean << previous_markers[0]->center.x(), 0, 0,
+ previous_markers[0]->center.y(), 0, 0;
+ state.covariance = Eigen::Matrix<double, 6, 6, Eigen::RowMajor>(
+ initial_covariance_data);
+
+ int current_frame = previous_markers[0]->frame;
+ int target_frame = predicted_marker->frame;
+
+ bool predict_forward = current_frame < target_frame;
+ int frame_delta = predict_forward ? 1 : -1;
+
+ for (int i = 1; i < previous_markers.size(); ++i) {
+ // Step forward predicting the state until it is on the current marker.
+ int predictions = 0;
+ for (;
+ current_frame != previous_markers[i]->frame;
+ current_frame += frame_delta) {
+ filter.Step(&state);
+ predictions++;
+ LG << "Predicted point (frame " << current_frame << "): "
+ << state.mean(0) << ", " << state.mean(3);
+ }
+ // Log the error -- not actually used, but interesting.
+ Vec2 error = previous_markers[i]->center.cast<double>() -
+ Vec2(state.mean(0), state.mean(3));
+ LG << "Prediction error for " << predictions << " steps: ("
+ << error.x() << ", " << error.y() << "); norm: " << error.norm();
+ // Now that the state is predicted in the current frame, update the state
+ // based on the measurement from the current frame.
+ filter.Update(previous_markers[i]->center.cast<double>(),
+ Eigen::Matrix<double, 2, 2, Eigen::RowMajor>(
+ measurement_covariance_data),
+ &state);
+ LG << "Updated point: " << state.mean(0) << ", " << state.mean(3);
+ }
+ // At this point as all the prediction that's possible is done. Finally
+ // predict until the target frame.
+ for (; current_frame != target_frame; current_frame += frame_delta) {
+ filter.Step(&state);
+ LG << "Final predicted point (frame " << current_frame << "): "
+ << state.mean(0) << ", " << state.mean(3);
+ }
+
+ // The x and y positions are at 0 and 3; ignore acceleration and velocity.
+ predicted_marker->center.x() = state.mean(0);
+ predicted_marker->center.y() = state.mean(3);
+
+ // Take the patch from the last marker then shift it to match the prediction.
+ const Marker& last_marker = *previous_markers[previous_markers.size() - 1];
+ predicted_marker->patch = last_marker.patch;
+ Vec2f delta = predicted_marker->center - last_marker.center;
+ for (int i = 0; i < 4; ++i) {
+ predicted_marker->patch.coordinates.row(i) += delta;
+ }
+
+ // Alter the search area as well so it always corresponds to the center.
+ predicted_marker->search_region = last_marker.search_region;
+ predicted_marker->search_region.Offset(delta);
+}
+
+} // namespace
+
+bool PredictMarkerPosition(const Tracks& tracks, Marker* marker) {
+ // Get all markers for this clip and track.
+ vector<Marker> markers;
+ tracks.GetMarkersForTrackInClip(marker->clip, marker->track, &markers);
+
+ if (markers.empty()) {
+ LG << "No markers to predict from for " << *marker;
+ return false;
+ }
+
+ // Order the markers by frame within the clip.
+ vector<Marker*> boxed_markers(markers.size());
+ for (int i = 0; i < markers.size(); ++i) {
+ boxed_markers[i] = &markers[i];
+ }
+ std::sort(boxed_markers.begin(), boxed_markers.end(), OrderByFrameLessThan);
+
+ // Find the insertion point for this marker among the returned ones.
+ int insert_at = -1; // If we find the exact frame
+ int insert_before = -1; // Otherwise...
+ for (int i = 0; i < boxed_markers.size(); ++i) {
+ if (boxed_markers[i]->frame == marker->frame) {
+ insert_at = i;
+ break;
+ }
+ if (boxed_markers[i]->frame > marker->frame) {
+ insert_before = i;
+ break;
+ }
+ }
+
+ // Forward starts at the marker or insertion point, and goes forward.
+ int forward_scan_begin, forward_scan_end;
+
+ // Backward scan starts at the marker or insertion point, and goes backward.
+ int backward_scan_begin, backward_scan_end;
+
+ // Determine the scanning ranges.
+ if (insert_at == -1 && insert_before == -1) {
+ // Didn't find an insertion point except the end.
+ forward_scan_begin = forward_scan_end = 0;
+ backward_scan_begin = markers.size() - 1;
+ backward_scan_end = 0;
+ } else if (insert_at != -1) {
+ // Found existing marker; scan before and after it.
+ forward_scan_begin = insert_at + 1;
+ forward_scan_end = markers.size() - 1;;
+ backward_scan_begin = insert_at - 1;
+ backward_scan_end = 0;
+ } else {
+ // Didn't find existing marker but found an insertion point.
+ forward_scan_begin = insert_before;
+ forward_scan_end = markers.size() - 1;;
+ backward_scan_begin = insert_before - 1;
+ backward_scan_end = 0;
+ }
+
+ const int num_consecutive_needed = 2;
+
+ if (forward_scan_begin <= forward_scan_end &&
+ forward_scan_end - forward_scan_begin > num_consecutive_needed) {
+ // TODO(keir): Finish this.
+ }
+
+ bool predict_forward = false;
+ if (backward_scan_end <= backward_scan_begin) {
+ // TODO(keir): Add smarter handling and detecting of consecutive frames!
+ predict_forward = true;
+ }
+
+ const int max_frames_to_predict_from = 20;
+ if (predict_forward) {
+ if (backward_scan_begin - backward_scan_end < num_consecutive_needed) {
+ // Not enough information to do a prediction.
+ LG << "Predicting forward impossible, not enough information";
+ return false;
+ }
+ LG << "Predicting forward";
+ int predict_begin =
+ std::max(backward_scan_begin - max_frames_to_predict_from, 0);
+ int predict_end = backward_scan_begin;
+ vector<Marker*> previous_markers;
+ for (int i = predict_begin; i <= predict_end; ++i) {
+ previous_markers.push_back(boxed_markers[i]);
+ }
+ RunPrediction(previous_markers, marker);
+ return true;
+ } else {
+ if (forward_scan_end - forward_scan_begin < num_consecutive_needed) {
+ // Not enough information to do a prediction.
+ LG << "Predicting backward impossible, not enough information";
+ return false;
+ }
+ LG << "Predicting backward";
+ int predict_begin =
+ std::min(forward_scan_begin + max_frames_to_predict_from,
+ forward_scan_end);
+ int predict_end = forward_scan_begin;
+ vector<Marker*> previous_markers;
+ for (int i = predict_begin; i >= predict_end; --i) {
+ previous_markers.push_back(boxed_markers[i]);
+ }
+ RunPrediction(previous_markers, marker);
+ return false;
+ }
+
+}
+
+} // namespace mv
diff --git a/extern/libmv/libmv/autotrack/predict_tracks.h b/extern/libmv/libmv/autotrack/predict_tracks.h
new file mode 100644
index 00000000000..0a176d08378
--- /dev/null
+++ b/extern/libmv/libmv/autotrack/predict_tracks.h
@@ -0,0 +1,37 @@
+// Copyright (c) 2014 libmv authors.
+//
+// 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.
+//
+// Author: mierle@gmail.com (Keir Mierle)
+
+#ifndef LIBMV_AUTOTRACK_PREDICT_TRACKS_H_
+#define LIBMV_AUTOTRACK_PREDICT_TRACKS_H_
+
+namespace mv {
+
+class Tracks;
+struct Marker;
+
+// Predict the position of the given marker, and update it accordingly. The
+// existing position will be overwritten.
+bool PredictMarkerPosition(const Tracks& tracks, Marker* marker);
+
+} // namespace mv
+
+#endif // LIBMV_AUTOTRACK_PREDICT_TRACKS_H_
diff --git a/extern/libmv/libmv/autotrack/predict_tracks_test.cc b/extern/libmv/libmv/autotrack/predict_tracks_test.cc
new file mode 100644
index 00000000000..fc90e260d94
--- /dev/null
+++ b/extern/libmv/libmv/autotrack/predict_tracks_test.cc
@@ -0,0 +1,201 @@
+// Copyright (c) 2014 libmv authors.
+//
+// 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.
+//
+// Author: mierle@gmail.com (Keir Mierle)
+
+#include "libmv/autotrack/predict_tracks.h"
+
+#include "libmv/autotrack/marker.h"
+#include "libmv/autotrack/tracks.h"
+#include "libmv/logging/logging.h"
+#include "testing/testing.h"
+
+namespace mv {
+
+void AddMarker(int frame, float x, float y, Tracks* tracks) {
+ Marker marker;
+ marker.clip = marker.track = 0;
+ marker.frame = frame;
+ marker.center.x() = x;
+ marker.center.y() = y;
+ marker.patch.coordinates << x - 1, y - 1,
+ x + 1, y - 1,
+ x + 1, y + 1,
+ x - 1, y + 1;
+ tracks->AddMarker(marker);
+}
+
+TEST(PredictMarkerPosition, EasyLinearMotion) {
+ Tracks tracks;
+ AddMarker(0, 1.0, 0.0, &tracks);
+ AddMarker(1, 2.0, 5.0, &tracks);
+ AddMarker(2, 3.0, 10.0, &tracks);
+ AddMarker(3, 4.0, 15.0, &tracks);
+ AddMarker(4, 5.0, 20.0, &tracks);
+ AddMarker(5, 6.0, 25.0, &tracks);
+ AddMarker(6, 7.0, 30.0, &tracks);
+ AddMarker(7, 8.0, 35.0, &tracks);
+
+ Marker predicted;
+ predicted.clip = 0;
+ predicted.track = 0;
+ predicted.frame = 8;
+
+ PredictMarkerPosition(tracks, &predicted);
+ double error = (libmv::Vec2f(9.0, 40.0) - predicted.center).norm();
+ LG << "Got error: " << error;
+ EXPECT_LT(error, 0.1);
+
+ // Check the patch coordinates as well.
+ double x = 9, y = 40.0;
+ Quad2Df expected_patch;
+ expected_patch.coordinates << x - 1, y - 1,
+ x + 1, y - 1,
+ x + 1, y + 1,
+ x - 1, y + 1;
+
+ error = (expected_patch.coordinates - predicted.patch.coordinates).norm();
+ LG << "Patch error: " << error;
+ EXPECT_LT(error, 0.1);
+}
+
+TEST(PredictMarkerPosition, EasyBackwardLinearMotion) {
+ Tracks tracks;
+ AddMarker(8, 1.0, 0.0, &tracks);
+ AddMarker(7, 2.0, 5.0, &tracks);
+ AddMarker(6, 3.0, 10.0, &tracks);
+ AddMarker(5, 4.0, 15.0, &tracks);
+ AddMarker(4, 5.0, 20.0, &tracks);
+ AddMarker(3, 6.0, 25.0, &tracks);
+ AddMarker(2, 7.0, 30.0, &tracks);
+ AddMarker(1, 8.0, 35.0, &tracks);
+
+ Marker predicted;
+ predicted.clip = 0;
+ predicted.track = 0;
+ predicted.frame = 0;
+
+ PredictMarkerPosition(tracks, &predicted);
+ LG << predicted;
+ double error = (libmv::Vec2f(9.0, 40.0) - predicted.center).norm();
+ LG << "Got error: " << error;
+ EXPECT_LT(error, 0.1);
+
+ // Check the patch coordinates as well.
+ double x = 9.0, y = 40.0;
+ Quad2Df expected_patch;
+ expected_patch.coordinates << x - 1, y - 1,
+ x + 1, y - 1,
+ x + 1, y + 1,
+ x - 1, y + 1;
+
+ error = (expected_patch.coordinates - predicted.patch.coordinates).norm();
+ LG << "Patch error: " << error;
+ EXPECT_LT(error, 0.1);
+}
+
+TEST(PredictMarkerPosition, TwoFrameGap) {
+ Tracks tracks;
+ AddMarker(0, 1.0, 0.0, &tracks);
+ AddMarker(1, 2.0, 5.0, &tracks);
+ AddMarker(2, 3.0, 10.0, &tracks);
+ AddMarker(3, 4.0, 15.0, &tracks);
+ AddMarker(4, 5.0, 20.0, &tracks);
+ AddMarker(5, 6.0, 25.0, &tracks);
+ AddMarker(6, 7.0, 30.0, &tracks);
+ // Missing frame 7!
+
+ Marker predicted;
+ predicted.clip = 0;
+ predicted.track = 0;
+ predicted.frame = 8;
+
+ PredictMarkerPosition(tracks, &predicted);
+ double error = (libmv::Vec2f(9.0, 40.0) - predicted.center).norm();
+ LG << "Got error: " << error;
+ EXPECT_LT(error, 0.1);
+}
+
+TEST(PredictMarkerPosition, FourFrameGap) {
+ Tracks tracks;
+ AddMarker(0, 1.0, 0.0, &tracks);
+ AddMarker(1, 2.0, 5.0, &tracks);
+ AddMarker(2, 3.0, 10.0, &tracks);
+ AddMarker(3, 4.0, 15.0, &tracks);
+ // Missing frames 4, 5, 6, 7.
+
+ Marker predicted;
+ predicted.clip = 0;
+ predicted.track = 0;
+ predicted.frame = 8;
+
+ PredictMarkerPosition(tracks, &predicted);
+ double error = (libmv::Vec2f(9.0, 40.0) - predicted.center).norm();
+ LG << "Got error: " << error;
+ EXPECT_LT(error, 2.0); // Generous error due to larger prediction window.
+}
+
+TEST(PredictMarkerPosition, MultipleGaps) {
+ Tracks tracks;
+ AddMarker(0, 1.0, 0.0, &tracks);
+ AddMarker(1, 2.0, 5.0, &tracks);
+ AddMarker(2, 3.0, 10.0, &tracks);
+ // AddMarker(3, 4.0, 15.0, &tracks); // Note the 3-frame gap.
+ // AddMarker(4, 5.0, 20.0, &tracks);
+ // AddMarker(5, 6.0, 25.0, &tracks);
+ AddMarker(6, 7.0, 30.0, &tracks); // Intermediate measurement.
+ // AddMarker(7, 8.0, 35.0, &tracks);
+
+ Marker predicted;
+ predicted.clip = 0;
+ predicted.track = 0;
+ predicted.frame = 8;
+
+ PredictMarkerPosition(tracks, &predicted);
+ double error = (libmv::Vec2f(9.0, 40.0) - predicted.center).norm();
+ LG << "Got error: " << error;
+ EXPECT_LT(error, 1.0); // Generous error due to larger prediction window.
+}
+
+TEST(PredictMarkerPosition, MarkersInRandomOrder) {
+ Tracks tracks;
+
+ // This is the same as the easy, except that the tracks are randomly ordered.
+ AddMarker(0, 1.0, 0.0, &tracks);
+ AddMarker(2, 3.0, 10.0, &tracks);
+ AddMarker(7, 8.0, 35.0, &tracks);
+ AddMarker(5, 6.0, 25.0, &tracks);
+ AddMarker(4, 5.0, 20.0, &tracks);
+ AddMarker(3, 4.0, 15.0, &tracks);
+ AddMarker(6, 7.0, 30.0, &tracks);
+ AddMarker(1, 2.0, 5.0, &tracks);
+
+ Marker predicted;
+ predicted.clip = 0;
+ predicted.track = 0;
+ predicted.frame = 8;
+
+ PredictMarkerPosition(tracks, &predicted);
+ double error = (libmv::Vec2f(9.0, 40.0) - predicted.center).norm();
+ LG << "Got error: " << error;
+ EXPECT_LT(error, 0.1);
+}
+
+} // namespace mv
diff --git a/extern/libmv/libmv/autotrack/quad.h b/extern/libmv/libmv/autotrack/quad.h
new file mode 100644
index 00000000000..0c70f9882da
--- /dev/null
+++ b/extern/libmv/libmv/autotrack/quad.h
@@ -0,0 +1,57 @@
+// Copyright (c) 2014 libmv authors.
+//
+// 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.
+//
+// Author: mierle@gmail.com (Keir Mierle)
+
+#ifndef LIBMV_AUTOTRACK_QUAD_H_
+#define LIBMV_AUTOTRACK_QUAD_H_
+
+#include <Eigen/Core>
+
+namespace mv {
+
+template<typename T, int D>
+struct Quad {
+ // A quad is 4 points; generally in 2D or 3D.
+ //
+ // +----------> x
+ // |\.
+ // | \.
+ // | z (z goes into screen)
+ // |
+ // | r0----->r1
+ // | ^ |
+ // | | . |
+ // | | V
+ // | r3<-----r2
+ // | \.
+ // | \.
+ // v normal goes away (right handed).
+ // y
+ //
+ // Each row is one of the corners coordinates; either (x, y) or (x, y, z).
+ Eigen::Matrix<T, 4, D> coordinates;
+};
+
+typedef Quad<float, 2> Quad2Df;
+
+} // namespace mv
+
+#endif // LIBMV_AUTOTRACK_QUAD_H_
diff --git a/extern/libmv/libmv/autotrack/reconstruction.h b/extern/libmv/libmv/autotrack/reconstruction.h
new file mode 100644
index 00000000000..e1d4e882cbd
--- /dev/null
+++ b/extern/libmv/libmv/autotrack/reconstruction.h
@@ -0,0 +1,89 @@
+// Copyright (c) 2014 libmv authors.
+//
+// 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.
+//
+// Author: mierle@gmail.com (Keir Mierle)
+
+#ifndef LIBMV_AUTOTRACK_RECONSTRUCTION_H_
+#define LIBMV_AUTOTRACK_RECONSTRUCTION_H_
+
+#include "libmv/base/vector.h"
+#include "libmv/numeric/numeric.h"
+#include "libmv/simple_pipeline/camera_intrinsics.h"
+
+namespace mv {
+
+using libmv::CameraIntrinsics;
+using libmv::vector;
+
+class Model;
+
+class CameraPose {
+ int clip;
+ int frame;
+ int intrinsics;
+ Mat3 R;
+ Vec3 t;
+};
+
+class Point {
+ int track;
+
+ // The coordinates of the point. Note that not all coordinates are always
+ // used; for example points on a plane only use the first two coordinates.
+ Vec3 X;
+};
+
+// A reconstruction for a set of tracks. The indexing for clip, frame, and
+// track should match that of a Tracs object, stored elsewhere.
+class Reconstruction {
+ public:
+ // All methods copy their input reference or take ownership of the pointer.
+ void AddCameraPose(const CameraPose& pose);
+ int AddCameraIntrinsics(CameraIntrinsics* intrinsics);
+ int AddPoint(const Point& point);
+ int AddModel(Model* model);
+
+ // Returns the corresponding pose or point or NULL if missing.
+ CameraPose* CameraPoseForFrame(int clip, int frame);
+ const CameraPose* CameraPoseForFrame(int clip, int frame) const;
+ Point* PointForTrack(int track);
+ const Point* PointForTrack(int track) const;
+
+ const vector<vector<CameraPose> >& camera_poses() const {
+ return camera_poses_;
+ }
+
+ private:
+ // Indexed by CameraPose::intrinsics. Owns the intrinsics objects.
+ vector<CameraIntrinsics*> camera_intrinsics_;
+
+ // Indexed by Marker::clip then by Marker::frame.
+ vector<vector<CameraPose> > camera_poses_;
+
+ // Indexed by Marker::track.
+ vector<Point> points_;
+
+ // Indexed by Marker::model_id. Owns model objects.
+ vector<Model*> models_;
+};
+
+} // namespace mv
+
+#endif // LIBMV_AUTOTRACK_RECONSTRUCTION_H_
diff --git a/extern/libmv/libmv/autotrack/region.h b/extern/libmv/libmv/autotrack/region.h
new file mode 100644
index 00000000000..b35d99eb60d
--- /dev/null
+++ b/extern/libmv/libmv/autotrack/region.h
@@ -0,0 +1,67 @@
+// Copyright (c) 2014 libmv authors.
+//
+// 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.
+//
+// Author: mierle@gmail.com (Keir Mierle)
+
+#ifndef LIBMV_AUTOTRACK_REGION_H_
+#define LIBMV_AUTOTRACK_REGION_H_
+
+#include "libmv/numeric/numeric.h"
+
+namespace mv {
+
+using libmv::Vec2f;
+
+// A region is a bounding box within an image.
+//
+// +----------> x
+// |
+// | (min.x, min.y) (max.x, min.y)
+// | +-------------------------+
+// | | |
+// | | |
+// | | |
+// | +-------------------------+
+// v (min.x, max.y) (max.x, max.y)
+// y
+//
+struct Region {
+ Vec2f min;
+ Vec2f max;
+
+ template<typename T>
+ void Offset(const T& offset) {
+ min += offset.template cast<float>();
+ max += offset.template cast<float>();
+ }
+
+ Region Rounded() const {
+ Region result;
+ result.min(0) = ceil(this->min(0));
+ result.min(1) = ceil(this->min(1));
+ result.max(0) = ceil(this->max(0));
+ result.max(1) = ceil(this->max(1));
+ return result;
+ }
+};
+
+} // namespace mv
+
+#endif // LIBMV_AUTOTRACK_REGION_H_
diff --git a/extern/libmv/libmv/autotrack/tracks.cc b/extern/libmv/libmv/autotrack/tracks.cc
new file mode 100644
index 00000000000..174f264f3f2
--- /dev/null
+++ b/extern/libmv/libmv/autotrack/tracks.cc
@@ -0,0 +1,193 @@
+// Copyright (c) 2014 libmv authors.
+//
+// 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.
+//
+// Author: mierle@gmail.com (Keir Mierle)
+
+#include "libmv/autotrack/tracks.h"
+
+#include <algorithm>
+#include <vector>
+#include <iterator>
+
+#include "libmv/numeric/numeric.h"
+
+namespace mv {
+
+Tracks::Tracks(const Tracks& other) {
+ markers_ = other.markers_;
+}
+
+Tracks::Tracks(const vector<Marker>& markers) : markers_(markers) {}
+
+bool Tracks::GetMarker(int clip, int frame, int track, Marker* marker) const {
+ for (int i = 0; i < markers_.size(); ++i) {
+ if (markers_[i].clip == clip &&
+ markers_[i].frame == frame &&
+ markers_[i].track == track) {
+ *marker = markers_[i];
+ return true;
+ }
+ }
+ return false;
+}
+
+void Tracks::GetMarkersForTrack(int track, vector<Marker>* markers) const {
+ for (int i = 0; i < markers_.size(); ++i) {
+ if (track == markers_[i].track) {
+ markers->push_back(markers_[i]);
+ }
+ }
+}
+
+void Tracks::GetMarkersForTrackInClip(int clip,
+ int track,
+ vector<Marker>* markers) const {
+ for (int i = 0; i < markers_.size(); ++i) {
+ if (clip == markers_[i].clip &&
+ track == markers_[i].track) {
+ markers->push_back(markers_[i]);
+ }
+ }
+}
+
+void Tracks::GetMarkersInFrame(int clip,
+ int frame,
+ vector<Marker>* markers) const {
+ for (int i = 0; i < markers_.size(); ++i) {
+ if (markers_[i].clip == clip &&
+ markers_[i].frame == frame) {
+ markers->push_back(markers_[i]);
+ }
+ }
+}
+
+void Tracks::GetMarkersForTracksInBothImages(int clip1, int frame1,
+ int clip2, int frame2,
+ vector<Marker>* markers) const {
+ std::vector<int> image1_tracks;
+ std::vector<int> image2_tracks;
+
+ // Collect the tracks in each of the two images.
+ for (int i = 0; i < markers_.size(); ++i) {
+ int clip = markers_[i].clip;
+ int frame = markers_[i].frame;
+ if (clip == clip1 && frame == frame1) {
+ image1_tracks.push_back(markers_[i].track);
+ } else if (clip == clip2 && frame == frame2) {
+ image2_tracks.push_back(markers_[i].track);
+ }
+ }
+
+ // Intersect the two sets to find the tracks of interest.
+ std::sort(image1_tracks.begin(), image1_tracks.end());
+ std::sort(image2_tracks.begin(), image2_tracks.end());
+ std::vector<int> intersection;
+ std::set_intersection(image1_tracks.begin(), image1_tracks.end(),
+ image2_tracks.begin(), image2_tracks.end(),
+ std::back_inserter(intersection));
+
+ // Scan through and get the relevant tracks from the two images.
+ for (int i = 0; i < markers_.size(); ++i) {
+ // Save markers that are in either frame and are in our candidate set.
+ if (((markers_[i].clip == clip1 &&
+ markers_[i].frame == frame1) ||
+ (markers_[i].clip == clip2 &&
+ markers_[i].frame == frame2)) &&
+ std::binary_search(intersection.begin(),
+ intersection.end(),
+ markers_[i].track)) {
+ markers->push_back(markers_[i]);
+ }
+ }
+}
+
+void Tracks::AddMarker(const Marker& marker) {
+ // TODO(keir): This is quadratic for repeated insertions. Fix this by adding
+ // a smarter data structure like a set<>.
+ for (int i = 0; i < markers_.size(); ++i) {
+ if (markers_[i].clip == marker.clip &&
+ markers_[i].frame == marker.frame &&
+ markers_[i].track == marker.track) {
+ markers_[i] = marker;
+ return;
+ }
+ }
+ markers_.push_back(marker);
+}
+
+void Tracks::SetMarkers(vector<Marker>* markers) {
+ std::swap(markers_, *markers);
+}
+
+bool Tracks::RemoveMarker(int clip, int frame, int track) {
+ int size = markers_.size();
+ for (int i = 0; i < markers_.size(); ++i) {
+ if (markers_[i].clip == clip &&
+ markers_[i].frame == frame &&
+ markers_[i].track == track) {
+ markers_[i] = markers_[size - 1];
+ markers_.resize(size - 1);
+ return true;
+ }
+ }
+ return false;
+}
+
+void Tracks::RemoveMarkersForTrack(int track) {
+ int size = 0;
+ for (int i = 0; i < markers_.size(); ++i) {
+ if (markers_[i].track != track) {
+ markers_[size++] = markers_[i];
+ }
+ }
+ markers_.resize(size);
+}
+
+int Tracks::MaxClip() const {
+ int max_clip = 0;
+ for (int i = 0; i < markers_.size(); ++i) {
+ max_clip = std::max(markers_[i].clip, max_clip);
+ }
+ return max_clip;
+}
+
+int Tracks::MaxFrame(int clip) const {
+ int max_frame = 0;
+ for (int i = 0; i < markers_.size(); ++i) {
+ if (markers_[i].clip == clip) {
+ max_frame = std::max(markers_[i].frame, max_frame);
+ }
+ }
+ return max_frame;
+}
+
+int Tracks::MaxTrack() const {
+ int max_track = 0;
+ for (int i = 0; i < markers_.size(); ++i) {
+ max_track = std::max(markers_[i].track, max_track);
+ }
+ return max_track;
+}
+
+int Tracks::NumMarkers() const {
+ return markers_.size();
+}
+
+} // namespace mv
diff --git a/extern/libmv/libmv/autotrack/tracks.h b/extern/libmv/libmv/autotrack/tracks.h
new file mode 100644
index 00000000000..0b7de91d211
--- /dev/null
+++ b/extern/libmv/libmv/autotrack/tracks.h
@@ -0,0 +1,82 @@
+// Copyright (c) 2014 libmv authors.
+//
+// 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.
+//
+// Author: mierle@gmail.com (Keir Mierle)
+
+#ifndef LIBMV_AUTOTRACK_TRACKS_H_
+#define LIBMV_AUTOTRACK_TRACKS_H_
+
+#include "libmv/base/vector.h"
+#include "libmv/autotrack/marker.h"
+
+namespace mv {
+
+using libmv::vector;
+
+// The Tracks container stores correspondences between frames.
+class Tracks {
+ public:
+ Tracks() { }
+ Tracks(const Tracks &other);
+
+ // Create a tracks object with markers already initialized. Copies markers.
+ explicit Tracks(const vector<Marker>& markers);
+
+ // All getters append to the output argument vector.
+ bool GetMarker(int clip, int frame, int track, Marker* marker) const;
+ void GetMarkersForTrack(int track, vector<Marker>* markers) const;
+ void GetMarkersForTrackInClip(int clip,
+ int track,
+ vector<Marker>* markers) const;
+ void GetMarkersInFrame(int clip, int frame, vector<Marker>* markers) const;
+
+ // Get the markers in frame1 and frame2 which have a common track.
+ //
+ // This is not the same as the union of the markers in frame1 and
+ // frame2; each marker is for a track that appears in both images.
+ void GetMarkersForTracksInBothImages(int clip1, int frame1,
+ int clip2, int frame2,
+ vector<Marker>* markers) const;
+
+ void AddMarker(const Marker& marker);
+
+ // Moves the contents of *markers over top of the existing markers. This
+ // destroys *markers in the process (but avoids copies).
+ void SetMarkers(vector<Marker>* markers);
+ bool RemoveMarker(int clip, int frame, int track);
+ void RemoveMarkersForTrack(int track);
+
+ int MaxClip() const;
+ int MaxFrame(int clip) const;
+ int MaxTrack() const;
+ int NumMarkers() const;
+
+ const vector<Marker>& markers() const { return markers_; }
+
+ private:
+ vector<Marker> markers_;
+
+ // TODO(keir): Consider adding access-map data structures to avoid all the
+ // linear lookup penalties for the accessors.
+};
+
+} // namespace mv
+
+#endif // LIBMV_AUTOTRACK_TRACKS_H_
diff --git a/extern/libmv/libmv/autotrack/tracks_test.cc b/extern/libmv/libmv/autotrack/tracks_test.cc
new file mode 100644
index 00000000000..028b4a10913
--- /dev/null
+++ b/extern/libmv/libmv/autotrack/tracks_test.cc
@@ -0,0 +1,52 @@
+// Copyright (c) 2014 libmv authors.
+//
+// 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.
+//
+// Author: mierle@gmail.com (Keir Mierle)
+
+#include "libmv/autotrack/tracks.h"
+
+#include "testing/testing.h"
+#include "libmv/logging/logging.h"
+
+namespace mv {
+
+TEST(Tracks, MaxFrame) {
+ Marker marker;
+ Tracks tracks;
+
+ // Add some markers to clip 0.
+ marker.clip = 0;
+ marker.frame = 1;
+ tracks.AddMarker(marker);
+
+ // Add some markers to clip 1.
+ marker.clip = 1;
+ marker.frame = 1;
+ tracks.AddMarker(marker);
+
+ marker.clip = 1;
+ marker.frame = 12;
+ tracks.AddMarker(marker);
+
+ EXPECT_EQ(1, tracks.MaxFrame(0));
+ EXPECT_EQ(12, tracks.MaxFrame(1));
+}
+
+} // namespace mv
diff --git a/extern/libmv/libmv/base/vector.h b/extern/libmv/libmv/base/vector.h
index 067db4ba7f7..1931fb0b1f9 100644
--- a/extern/libmv/libmv/base/vector.h
+++ b/extern/libmv/libmv/base/vector.h
@@ -101,8 +101,6 @@ class vector {
size_ = size;
}
-
-
void push_back(const T &value) {
if (size_ == capacity_) {
reserve(size_ ? 2 * size_ : 1);
@@ -130,6 +128,10 @@ class vector {
}
}
+ bool empty() {
+ return size_ == 0;
+ }
+
private:
void construct(int start, int end) {
for (int i = start; i < end; ++i) {
diff --git a/extern/libmv/libmv/image/array_nd.h b/extern/libmv/libmv/image/array_nd.h
index c5099f24d7b..b56a765223b 100644
--- a/extern/libmv/libmv/image/array_nd.h
+++ b/extern/libmv/libmv/image/array_nd.h
@@ -41,33 +41,35 @@ class ArrayND : public BaseArray {
typedef Tuple<int, N> Index;
/// Create an empty array.
- ArrayND() : data_(NULL), own_data(true) { Resize(Index(0)); }
+ ArrayND() : data_(NULL), own_data_(true) { Resize(Index(0)); }
/// Create an array with the specified shape.
- ArrayND(const Index &shape) : data_(NULL), own_data(true) { Resize(shape); }
+ ArrayND(const Index &shape) : data_(NULL), own_data_(true) { Resize(shape); }
/// Create an array with the specified shape.
- ArrayND(int *shape) : data_(NULL), own_data(true) { Resize(shape); }
+ ArrayND(int *shape) : data_(NULL), own_data_(true) { Resize(shape); }
/// Copy constructor.
- ArrayND(const ArrayND<T, N> &b) : data_(NULL), own_data(true) {
+ ArrayND(const ArrayND<T, N> &b) : data_(NULL), own_data_(true) {
ResizeLike(b);
std::memcpy(Data(), b.Data(), sizeof(T) * Size());
}
- ArrayND(int s0) : data_(NULL), own_data(true) { Resize(s0); }
- ArrayND(int s0, int s1) : data_(NULL), own_data(true) { Resize(s0, s1); }
- ArrayND(int s0, int s1, int s2) : data_(NULL), own_data(true) {
+ ArrayND(int s0) : data_(NULL), own_data_(true) { Resize(s0); }
+ ArrayND(int s0, int s1) : data_(NULL), own_data_(true) { Resize(s0, s1); }
+ ArrayND(int s0, int s1, int s2) : data_(NULL), own_data_(true) {
Resize(s0, s1, s2);
}
- ArrayND(T* data, int s0, int s1, int s2) : data_(data), own_data(false) {
+ ArrayND(T* data, int s0, int s1, int s2) : data_(data), own_data_(false) {
Resize(s0, s1, s2);
}
/// Destructor deletes pixel data.
~ArrayND() {
- delete [] data_;
+ if (own_data_) {
+ delete [] data_;
+ }
}
/// Assignation copies pixel data.
@@ -97,7 +99,7 @@ class ArrayND : public BaseArray {
for (int i = N - 1; i > 0; --i) {
strides_(i - 1) = strides_(i) * shape_(i);
}
- if (own_data) {
+ if (own_data_) {
delete [] data_;
data_ = NULL;
if (Size() > 0) {
@@ -336,7 +338,7 @@ class ArrayND : public BaseArray {
T *data_;
/// Flag if this Array either own or reference the data
- bool own_data;
+ bool own_data_;
};
/// 3D array (row, column, channel).
diff --git a/extern/libmv/libmv/multiview/homography.cc b/extern/libmv/libmv/multiview/homography.cc
index ce533a3ead2..346acb3afd9 100644
--- a/extern/libmv/libmv/multiview/homography.cc
+++ b/extern/libmv/libmv/multiview/homography.cc
@@ -179,8 +179,12 @@ void GetNormalizedPoints(const Mat &original_points,
class HomographySymmetricGeometricCostFunctor {
public:
HomographySymmetricGeometricCostFunctor(const Vec2 &x,
- const Vec2 &y)
- : x_(x), y_(y) { }
+ const Vec2 &y) {
+ xx_ = x(0);
+ xy_ = x(1);
+ yx_ = y(0);
+ yy_ = y(1);
+ }
template<typename T>
bool operator()(const T *homography_parameters, T *residuals) const {
@@ -189,8 +193,8 @@ class HomographySymmetricGeometricCostFunctor {
Mat3 H(homography_parameters);
- Vec3 x(T(x_(0)), T(x_(1)), T(1.0));
- Vec3 y(T(y_(0)), T(y_(1)), T(1.0));
+ Vec3 x(T(xx_), T(xy_), T(1.0));
+ Vec3 y(T(yx_), T(yy_), T(1.0));
Vec3 H_x = H * x;
Vec3 Hinv_y = H.inverse() * y;
@@ -199,18 +203,19 @@ class HomographySymmetricGeometricCostFunctor {
Hinv_y /= Hinv_y(2);
// This is a forward error.
- residuals[0] = H_x(0) - T(y_(0));
- residuals[1] = H_x(1) - T(y_(1));
+ residuals[0] = H_x(0) - T(yx_);
+ residuals[1] = H_x(1) - T(yy_);
// This is a backward error.
- residuals[2] = Hinv_y(0) - T(x_(0));
- residuals[3] = Hinv_y(1) - T(x_(1));
+ residuals[2] = Hinv_y(0) - T(xx_);
+ residuals[3] = Hinv_y(1) - T(xy_);
return true;
}
- const Vec2 x_;
- const Vec2 y_;
+ // TODO(sergey): Think of better naming.
+ double xx_, xy_;
+ double yx_, yy_;
};
// Termination checking callback used for homography estimation.
diff --git a/extern/libmv/libmv/simple_pipeline/bundle.cc b/extern/libmv/libmv/simple_pipeline/bundle.cc
index 09b55f34eef..e61650fb371 100644
--- a/extern/libmv/libmv/simple_pipeline/bundle.cc
+++ b/extern/libmv/libmv/simple_pipeline/bundle.cc
@@ -424,6 +424,7 @@ void EuclideanBundlePointsOnly(const DistortionModelType distortion_model,
options.use_nonmonotonic_steps = true;
options.preconditioner_type = ceres::SCHUR_JACOBI;
options.linear_solver_type = ceres::ITERATIVE_SCHUR;
+ options.use_explicit_schur_complement = true;
options.use_inner_iterations = true;
options.max_num_iterations = 100;
@@ -593,6 +594,7 @@ void EuclideanBundleCommonIntrinsics(
options.use_nonmonotonic_steps = true;
options.preconditioner_type = ceres::SCHUR_JACOBI;
options.linear_solver_type = ceres::ITERATIVE_SCHUR;
+ options.use_explicit_schur_complement = true;
options.use_inner_iterations = true;
options.max_num_iterations = 100;
diff --git a/extern/libmv/libmv/simple_pipeline/keyframe_selection.cc b/extern/libmv/libmv/simple_pipeline/keyframe_selection.cc
index 7b90c28bbca..241b5600505 100644
--- a/extern/libmv/libmv/simple_pipeline/keyframe_selection.cc
+++ b/extern/libmv/libmv/simple_pipeline/keyframe_selection.cc
@@ -69,54 +69,50 @@ double GRIC(const Vec &e, int d, int k, int r) {
// http://www.robots.ox.ac.uk/~vgg/publications/papers/torr99.ps.gz
double lambda3 = 2.0;
- // measurement error of tracker
+ // Variance of tracker position. Physically, this is typically about 0.1px,
+ // and when squared becomes 0.01 px^2.
double sigma2 = 0.01;
- // Actual GRIC computation
- double gric_result = 0.0;
-
+ // Finally, calculate the GRIC score.
+ double gric = 0.0;
for (int i = 0; i < n; i++) {
- double rho = std::min(e(i) * e(i) / sigma2, lambda3 * (r - d));
- gric_result += rho;
+ gric += std::min(e(i) * e(i) / sigma2, lambda3 * (r - d));
}
-
- gric_result += lambda1 * d * n;
- gric_result += lambda2 * k;
-
- return gric_result;
+ gric += lambda1 * d * n;
+ gric += lambda2 * k;
+ return gric;
}
-// Compute a generalized inverse using eigen value decomposition.
-// It'll actually also zero 7 last eigen values to deal with
-// gauges, since this function is used to compute variance of
+// Compute a generalized inverse using eigen value decomposition, clamping the
+// smallest eigenvalues if requested. This is needed to compute the variance of
// reconstructed 3D points.
//
-// TODO(sergey): Could be generalized by making it so number
-// of values to be zeroed is passed by an argument
-// and moved to numeric module.
-Mat pseudoInverse(const Mat &matrix) {
- Eigen::EigenSolver<Mat> eigenSolver(matrix);
- Mat D = eigenSolver.pseudoEigenvalueMatrix();
- Mat V = eigenSolver.pseudoEigenvectors();
-
+// TODO(keir): Consider moving this into the numeric code, since this is not
+// related to keyframe selection.
+Mat PseudoInverseWithClampedEigenvalues(const Mat &matrix,
+ int num_eigenvalues_to_clamp) {
+ Eigen::EigenSolver<Mat> eigen_solver(matrix);
+ Mat D = eigen_solver.pseudoEigenvalueMatrix();
+ Mat V = eigen_solver.pseudoEigenvectors();
+
+ // Clamp too-small singular values to zero to prevent numeric blowup.
double epsilon = std::numeric_limits<double>::epsilon();
-
for (int i = 0; i < D.cols(); ++i) {
- if (D(i, i) > epsilon)
+ if (D(i, i) > epsilon) {
D(i, i) = 1.0 / D(i, i);
- else
+ } else {
D(i, i) = 0.0;
+ }
}
- // Zero last 7 (which corresponds to smallest eigen values).
- // 7 equals to the number of gauge freedoms.
- for (int i = D.cols() - 7; i < D.cols(); ++i)
+ // Apply the clamp.
+ for (int i = D.cols() - num_eigenvalues_to_clamp; i < D.cols(); ++i) {
D(i, i) = 0.0;
-
+ }
return V * D * V.inverse();
}
-void filterZeroWeightMarkersFromTracks(const Tracks &tracks,
+void FilterZeroWeightMarkersFromTracks(const Tracks &tracks,
Tracks *filtered_tracks) {
vector<Marker> all_markers = tracks.AllMarkers();
@@ -143,7 +139,7 @@ void SelectKeyframesBasedOnGRICAndVariance(const Tracks &_tracks,
// http://www.cs.ait.ac.th/~mdailey/papers/Tahir-KeyFrame.pdf
Tracks filtered_tracks;
- filterZeroWeightMarkersFromTracks(_tracks, &filtered_tracks);
+ FilterZeroWeightMarkersFromTracks(_tracks, &filtered_tracks);
int max_image = filtered_tracks.MaxImage();
int next_keyframe = 1;
@@ -224,9 +220,9 @@ void SelectKeyframesBasedOnGRICAndVariance(const Tracks &_tracks,
EstimateFundamentalOptions estimate_fundamental_options;
EstimateFundamentalFromCorrespondences(x1,
- x2,
- estimate_fundamental_options,
- &F);
+ x2,
+ estimate_fundamental_options,
+ &F);
// Convert fundamental to original pixel space.
F = N_inverse * F * N;
@@ -379,7 +375,8 @@ void SelectKeyframesBasedOnGRICAndVariance(const Tracks &_tracks,
Mat &jacobian = evaluation.jacobian;
Mat JT_J = jacobian.transpose() * jacobian;
- Mat JT_J_inv = pseudoInverse(JT_J);
+ // There are 7 degrees of freedom, so clamp them out.
+ Mat JT_J_inv = PseudoInverseWithClampedEigenvalues(JT_J, 7);
Mat temp_derived = JT_J * JT_J_inv * JT_J;
bool is_inversed = (temp_derived - JT_J).cwiseAbs2().sum() <
diff --git a/extern/libmv/libmv/tracking/kalman_filter.h b/extern/libmv/libmv/tracking/kalman_filter.h
new file mode 100644
index 00000000000..9841f0e912c
--- /dev/null
+++ b/extern/libmv/libmv/tracking/kalman_filter.h
@@ -0,0 +1,112 @@
+// Copyright (c) 2014 libmv authors.
+//
+// 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 LIBMV_TRACKING_KALMAN_FILTER_H_
+
+#include "libmv/numeric/numeric.h"
+
+namespace mv {
+
+// A Kalman filter with order N and observation size K.
+template<typename T, int N, int K>
+class KalmanFilter {
+ public:
+ struct State {
+ Eigen::Matrix<T, N, 1> mean;
+ Eigen::Matrix<T, N, N> covariance;
+ };
+
+ // Initialize from row-major data; convenient for constant initializers.
+ KalmanFilter(const T* state_transition_data,
+ const T* observation_data,
+ const T* process_covariance_data,
+ const T* default_measurement_covariance_data)
+ : state_transition_matrix_(
+ Eigen::Matrix<T, N, N, Eigen::RowMajor>(state_transition_data)),
+ observation_matrix_(
+ Eigen::Matrix<T, K, N, Eigen::RowMajor>(observation_data)),
+ process_covariance_(
+ Eigen::Matrix<T, N, N, Eigen::RowMajor>(process_covariance_data)),
+ default_measurement_covariance_(
+ Eigen::Matrix<T, K, K, Eigen::RowMajor>(
+ default_measurement_covariance_data)) {
+ }
+
+ KalmanFilter(
+ const Eigen::Matrix<T, N, N> &state_transition_matrix,
+ const Eigen::Matrix<T, K, N> &observation_matrix,
+ const Eigen::Matrix<T, N, N> &process_covariance,
+ const Eigen::Matrix<T, K, K> &default_measurement_covariance)
+ : state_transition_matrix_(state_transition_matrix),
+ observation_matrix_(observation_matrix),
+ process_covariance_(process_covariance),
+ default_measurement_covariance_(default_measurement_covariance) {
+ }
+
+ // Advances the system according to the current state estimate.
+ void Step(State *state) const {
+ state->mean = state_transition_matrix_ * state->mean;
+ state->covariance = state_transition_matrix_ *
+ state->covariance *
+ state_transition_matrix_.transpose() +
+ process_covariance_;
+ }
+
+ // Updates a state with a new measurement.
+ void Update(const Eigen::Matrix<T, K, 1> &measurement_mean,
+ const Eigen::Matrix<T, K, K> &measurement_covariance,
+ State *state) const {
+ // Calculate the innovation, which is a distribution over prediction error.
+ Eigen::Matrix<T, K, 1> innovation_mean = measurement_mean -
+ observation_matrix_ *
+ state->mean;
+ Eigen::Matrix<T, K, K> innovation_covariance =
+ observation_matrix_ *
+ state->covariance *
+ observation_matrix_.transpose() +
+ measurement_covariance;
+
+ // Calculate the Kalman gain.
+ Eigen::Matrix<T, 6, 2> kalman_gain = state->covariance *
+ observation_matrix_.transpose() *
+ innovation_covariance.inverse();
+
+ // Update the state mean and covariance.
+ state->mean += kalman_gain * innovation_mean;
+ state->covariance = (Eigen::Matrix<T, N, N>::Identity() -
+ kalman_gain * observation_matrix_) *
+ state->covariance;
+ }
+
+ void Update(State *state,
+ const Eigen::Matrix<T, K, 1> &measurement_mean) const {
+ Update(state, measurement_mean, default_measurement_covariance_);
+ }
+
+ private:
+ const Eigen::Matrix<T, N, N> state_transition_matrix_;
+ const Eigen::Matrix<T, K, N> observation_matrix_;
+ const Eigen::Matrix<T, N, N> process_covariance_;
+ const Eigen::Matrix<T, K, K> default_measurement_covariance_;
+};
+
+} // namespace mv
+
+#endif // LIBMV_TRACKING_KALMAN_FILTER_H_
diff --git a/extern/libmv/libmv/tracking/track_region.h b/extern/libmv/libmv/tracking/track_region.h
index 2ced9dd6550..be1d8ef3e03 100644
--- a/extern/libmv/libmv/tracking/track_region.h
+++ b/extern/libmv/libmv/tracking/track_region.h
@@ -42,7 +42,13 @@ struct TrackRegionOptions {
};
Mode mode;
+ // Minimum normalized cross-correlation necessary between the final tracked
+ // positoin of the patch on the destination image and the reference patch
+ // needed to declare tracking success. If the minimum correlation is not met,
+ // then TrackResult::termination is INSUFFICIENT_CORRELATION.
double minimum_correlation;
+
+ // Maximum number of Ceres iterations to run for the inner minimization.
int max_iterations;
// Use the "Efficient Second-order Minimization" scheme. This increases
@@ -124,6 +130,11 @@ struct TrackRegionResult {
};
Termination termination;
+ bool is_usable() {
+ return termination == CONVERGENCE ||
+ termination == NO_CONVERGENCE;
+ }
+
int num_iterations;
double correlation;
diff --git a/extern/libmv/third_party/ceres/CMakeLists.txt b/extern/libmv/third_party/ceres/CMakeLists.txt
index a349d3fca26..694982ec606 100644
--- a/extern/libmv/third_party/ceres/CMakeLists.txt
+++ b/extern/libmv/third_party/ceres/CMakeLists.txt
@@ -36,7 +36,7 @@ set(INC
)
set(INC_SYS
- ../../../Eigen3
+ ${EIGEN3_INCLUDE_DIRS}
)
set(SRC
@@ -262,7 +262,7 @@ set(SRC
internal/ceres/wall_time.h
)
-if(TRUE)
+if(WITH_LIBMV_SCHUR_SPECIALIZATIONS)
list(APPEND SRC
internal/ceres/generated/partitioned_matrix_view_2_2_2.cc
internal/ceres/generated/partitioned_matrix_view_2_2_3.cc
@@ -301,6 +301,8 @@ if(TRUE)
internal/ceres/generated/schur_eliminator_4_4_4.cc
internal/ceres/generated/schur_eliminator_4_4_d.cc
)
+else()
+ add_definitions(-DCERES_RESTRICT_SCHUR_SPECIALIZATION)
endif()
if(WIN32)
diff --git a/extern/libmv/third_party/ceres/ChangeLog b/extern/libmv/third_party/ceres/ChangeLog
index cd168a44b35..b4f78ee0731 100644
--- a/extern/libmv/third_party/ceres/ChangeLog
+++ b/extern/libmv/third_party/ceres/ChangeLog
@@ -1,3 +1,203 @@
+commit 0435246de5f45e69b2c97d244ed61bedd340215a
+Author: Sameer Agarwal <sameeragarwal@google.com>
+Date: Wed Oct 8 18:12:53 2014 -0700
+
+ Add seene to users.rst
+
+ Change-Id: If40726775a3d4b234b6e10517fe9943d122a3384
+
+commit fdf32b315f39553639f0becf078ad4eec763a10e
+Author: Sameer Agarwal <sameeragarwal@google.com>
+Date: Wed Oct 8 16:04:32 2014 -0700
+
+ Fix some errant tabs.
+
+ Change-Id: Iaf1906eaade49467ba282656cf0a10879d258b1f
+
+commit 6768b3586a027bb850c0a50e2a27380f5d80142a
+Author: Sameer Agarwal <sameeragarwal@google.com>
+Date: Wed Oct 8 12:48:16 2014 -0700
+
+ Minor cleanups in preparation for a release.
+
+ 1. Fix the release script to ignore the version.h checking.
+ 2. Fix some ceres documentation formatting errors.
+
+ Change-Id: I3fd6b85e771b242f463d6a36c3efd8d691f9242f
+
+commit 7b6bd1cd31aa0b8cb7fb97600c1b9999846e3152
+Author: Sameer Agarwal <sameeragarwal@google.com>
+Date: Thu Oct 2 16:16:26 2014 -0700
+
+ Documentation update.
+
+ 1. Complete restructuring of the documentation to account for
+ GradientProblemSolver.
+ 2. Update the version history to account for changes since 1.9.0.
+ 3. Add links and document the various examples that ship with ceres.
+ 4. Documentation for GradientProblem GradientProblemSolver.
+
+ Change-Id: If3a18f2850cbc98be1bc34435e9ea468785b8b27
+
+commit b7d321f505e936b6c09aeb43ae3f7b1252388a95
+Author: Sameer Agarwal <sameeragarwal@google.com>
+Date: Fri Oct 3 15:47:59 2014 -0700
+
+ Relax the warning/error handing in GCC.
+
+ Thanks to Matthew Woehlke for suggesting this.
+
+ Change-Id: Iae754465c086b0841a7816df1a36781371d0dc9a
+
+commit 94c6e7d27b5d48d81ab54ed9cdcbc55c3c099311
+Author: Sameer Agarwal <sameeragarwal@google.com>
+Date: Wed Oct 1 15:55:13 2014 -0700
+
+ Improve multithreading when using inner iterations.
+
+ Inner iterations by default would use problems where the evaluator
+ was configured to use exactly one thread for doing the evaluation.
+ This is fine when there are multiple inner iteration problems
+ being executed concurrently, but every now and then there are
+ problem decompositions where there is just one parameter block
+ in the current independent set and it touches every single
+ residual block. In such cases it is essential that the evaluator
+ be configured to use multiple threads.
+
+ We now pay attention to the size of the independent set and
+ dynamically configure the number of threads being used by the
+ outer loop and the evaluator loop.
+
+ Thanks to William Rucklidge for reporting this issue and providing
+ a test problem to debug.
+
+ Change-Id: Iaff9a4ab6d2658cf7b61ea213575d23aab604e3b
+
+commit 9e11cd16d09403b9270e621e839d5948b6a74b8d
+Author: Sameer Agarwal <sameeragarwal@google.com>
+Date: Mon Sep 29 14:27:58 2014 -0700
+
+ Faster BlockRandomAccessSparseMatrix::SymmetricRightMultiply.
+
+ Trade a small amount of memory to improve the cache coherency of
+ the SymmetricRightMultiply operation.
+
+ The resulting code leads to a 10-20% speedup in the linear solver
+ end to end.
+
+ Change-Id: I8ab2fe152099e849b211b5b19e4ef9f03d8e7f1c
+
+commit 46b8461fd010c1e7ffce6bb2bdf8a84b659d5e09
+Author: Sameer Agarwal <sameeragarwal@google.com>
+Date: Mon Sep 29 15:10:58 2014 -0700
+
+ Various minor fixes from William Rucklidge.
+
+ Change-Id: Ibe731d5db374ad8ee148d62a9fdd8d726b607a3f
+
+commit b44cfdef25f6bf0917a23b3fd65cce38aa6a3362
+Author: Sameer Agarwal <sameeragarwal@google.com>
+Date: Mon Sep 29 07:53:54 2014 -0700
+
+ Let ITERATIVE_SCHUR use an explicit Schur Complement matrix.
+
+ Up till now ITERATIVE_SCHUR evaluates matrix-vector products
+ between the Schur complement and a vector implicitly by exploiting
+ the algebraic expression for the Schur complement.
+
+ This cost of this evaluation scales with the number of non-zeros
+ in the Jacobian.
+
+ For small to medium sized problems there is a sweet spot where
+ computing the Schur complement is cheap enough that it is much
+ more efficient to explicitly compute it and use it for evaluating
+ the matrix-vector products.
+
+ This changes implements support for an explicit Schur complement
+ in ITERATIVE_SCHUR in combination with the SCHUR_JACOBI preconditioner.
+
+ API wise a new bool Solver::Options::use_explicit_schur_complement
+ has been added.
+
+ The implementation extends the SparseSchurComplementSolver to use
+ Conjugate Gradients.
+
+ Example speedup:
+
+ use_explicit_schur_complement = false
+
+ Time (in seconds):
+ Preprocessor 0.585
+
+ Residual evaluation 0.319
+ Jacobian evaluation 1.590
+ Linear solver 25.685
+ Minimizer 27.990
+
+ Postprocessor 0.010
+ Total 28.585
+
+ use_explicit_schur_complement = true
+
+ Time (in seconds):
+ Preprocessor 0.638
+
+ Residual evaluation 0.318
+ Jacobian evaluation 1.507
+ Linear solver 5.930
+ Minimizer 8.144
+
+ Postprocessor 0.010
+ Total 8.791
+
+ Which indicates an end-to-end speedup of more than 3x, with the linear
+ solver being sped up by > 4x.
+
+ The idea to explore this optimization was inspired by the recent paper:
+
+ Mining structure fragments for smart bundle adjustment
+ L. Carlone, P. Alcantarilla, H. Chiu, K. Zsolt, F. Dellaert
+ British Machine Vision Conference, 2014
+
+ which uses a more complicated algorithm to compute parts of the
+ Schur complement to speed up the matrix-vector product.
+
+ Change-Id: I95324af0ab351faa1600f5204039a1d2a64ae61d
+
+commit 4ad91490827f2ebebcc70d17e63ef653bf06fd0d
+Author: Sameer Agarwal <sameeragarwal@google.com>
+Date: Wed Sep 24 23:54:18 2014 -0700
+
+ Simplify the Block Jacobi and Schur Jacobi preconditioners.
+
+ 1. Extend the implementation of BlockRandomAccessDiagonalMatrix
+ by adding Invert and RightMultiply methods.
+
+ 2. Simplify the implementation of the Schur Jacobi preconditioner
+ using these new methods.
+
+ 3. Replace the custom storage used inside Block Jacobi preconditioner
+ with BlockRandomAccessDiagonalMatrix and simplify its implementation
+ too.
+
+ Change-Id: I9d4888b35f0f228c08244abbdda5298b3ce9c466
+
+commit 8f7be1036b853addc33224d97b92412b5a1281b6
+Author: Sameer Agarwal <sameeragarwal@google.com>
+Date: Mon Sep 29 08:13:35 2014 -0700
+
+ Fix a formatting error TrustRegionMinimizer logging.
+
+ Change-Id: Iad1873c51eece46c3fdee1356d154367cfd7925e
+
+commit c99872d48e322662ea19efb9010a62b7432687ae
+Author: Sameer Agarwal <sameeragarwal@google.com>
+Date: Wed Sep 24 21:30:02 2014 -0700
+
+ Add BlockRandomAccessSparseMatrix::SymmetricRightMultiply.
+
+ Change-Id: Ib06a22a209b4c985ba218162dfb6bf46bd93169e
+
commit d3ecd18625ba260e0d00912a305a448b566acc59
Author: Sameer Agarwal <sameeragarwal@google.com>
Date: Tue Sep 23 10:12:42 2014 -0700
@@ -471,182 +671,3 @@ Date: Thu Jun 5 21:30:13 2014 -0700
solve.
Change-Id: I80f35cfc9f2cbf78f1df4aceace27075779d8a3a
-
-commit bd90384226a7f8629467f72fc410a9e8086a2dff
-Author: Sameer Agarwal <sameeragarwal@google.com>
-Date: Mon Aug 18 11:27:06 2014 -0700
-
- Lint comments from William Rucklidge.
-
- Also some minor refactoring of the trust_region_preprocessor_test.cc
-
- Change-Id: Ica28002254c95722faf93a7ef35bf3deab557f0b
-
-commit 3150321db4a0cb1bb4894961a030d95dacae3591
-Author: Sameer Agarwal <sameeragarwal@google.com>
-Date: Tue Aug 12 22:46:51 2014 -0700
-
- Preprocessor for the LineSearchMinimizer.
-
- Change-Id: Ieb5dfe1c0b96ef323c1130edd0c3a8a8b2c644cc
-
-commit f7da411ef0d0067e269629887d64cdb769368800
-Author: Sameer Agarwal <sameeragarwal@google.com>
-Date: Thu Aug 7 14:30:33 2014 -0700
-
- Preprocessor for the TrustRegionMinimizer.
-
- 1. Base class for preprocessors.
- 2. A preprocessor for problems that will be solved using
- the trust region minimizer.
- 3. Added sanity tests to the program reordering options
- for Schur type linear solvers.
- 4. Tests for the TrustRegionPreprocessor.
-
- Change-Id: I88cd926f0053bbbf2bd6b11e03ec55b8bf473cf1
-
-commit 54893ba523106e38ab06eb72fb5d8748685c7797
-Author: Alex Stewart <alexs.mac@gmail.com>
-Date: Mon Aug 11 19:04:18 2014 +0100
-
- Add missing #include of <limits> for loss functions.
-
- Change-Id: Id632451429e03031a1533a9be795270debc70706
-
-commit 4a2a888905fd1ce7203e45df15762d52740bb240
-Author: Sameer Agarwal <sameeragarwal@google.com>
-Date: Thu Aug 7 11:48:03 2014 -0700
-
- Change ownership of pointers in Minimizer::Options.
-
- This is a intermediate change to clean things up
- in preparation for a broader refactoring of the SolverImpl.
-
- Essentially we are replacing raw pointers in Minimizer::Options
- with shared_ptr objects. For now this only makes things a bit
- more complicated looking inside solver_impl.cc, but going
- forward this will lead to considerable simplifications in
- tracking ownership of various pointers.
-
- Change-Id: I21db8fc6763c29b0d15e834d7c968a0f514042a0
-
-commit 0d4e3bd664d442b700fee2895c7a8ac37717dc08
-Author: Sameer Agarwal <sameeragarwal@google.com>
-Date: Thu Aug 7 12:19:10 2014 -0700
-
- GradientCheckingProblem's parameter blocks are initialized correctly.
-
- Ensure that when a new problem object is constructed for validing
- gradients, the parameter blocks have their data pointers point to
- the user's parameter blocks.
-
- We used to do this inside solver_impl.cc, but doing this at
- construction is the right thing to do.
-
- Change-Id: I3bfdc89bb0027c8d67cde937e8f2fa385d89c30c
-
-commit cfb36463f9c1f806121779d651c7105ad899bb20
-Author: Sameer Agarwal <sameeragarwal@google.com>
-Date: Tue Aug 5 14:42:33 2014 -0700
-
- Small fixes from William Rucklidge.
-
- Change-Id: I0be52f0f1e53cedccffe4807dc664a2f3fb4a8e4
-
-commit 9a41132a0523af407b53644c07900f86aa6fceac
-Author: Sameer Agarwal <sameeragarwal@google.com>
-Date: Mon Aug 4 22:45:53 2014 -0700
-
- Small changes from Jim Roseborough.
-
- Change-Id: Ic8b19ea5c5f4f8fd782eb4420b30514153087d18
-
-commit a521fc3afc11425b46992388a83ef07017d02ac9
-Author: Sameer Agarwal <sameeragarwal@google.com>
-Date: Fri Aug 1 08:27:35 2014 -0700
-
- Simplify, cleanup and instrument SchurComplementSolver.
-
- The instrumentation revealed that EIGEN_SPARSE can be upto
- an order of magnitude slower than CX_SPARSE on some bundle
- adjustment problems.
-
- The problem comes down to the quality of AMD ordering that
- CXSparse/Eigen implements. It does particularly badly
- on the Schur complement. In the CXSparse implementation
- we got around this by considering the block sparsity structure
- and computing the AMD ordering on it and lifting it to the
- full matrix.
-
- This is currently not possible with the release version of
- Eigen, as the support for using preordered/natural orderings
- is in the master branch but has not been released yet.
-
- Change-Id: I25588d3e723e50606f327db5759f174f58439e29
-
-commit b43e73a03485f0fd0fe514e356ad8925731d3a81
-Author: Sameer Agarwal <sameeragarwal@google.com>
-Date: Fri Aug 1 12:09:09 2014 -0700
-
- Simplify the Eigen code in SparseNormalCholeskySolver.
-
- Simplifying some of the template handling, and remove the use
- of SelfAdjointView as it is not needed. The solver itself takes
- an argument for where the data is actually stored.
-
- The performance of SparseNormalCholesky with EIGEN_SPARSE
- seems to be on par with CX_SPARSE.
-
- Change-Id: I69e22a144b447c052b6cbe59ef1aa33eae2dd9e3
-
-commit 031598295c6b2f061c171b9b2338919f41b7eb0b
-Author: Sameer Agarwal <sameeragarwal@google.com>
-Date: Thu Jul 17 14:35:18 2014 -0700
-
- Enable Eigen as sparse linear algebra library.
-
- SPARSE_NORMAL_CHOLESKY and SPARSE_SCHUR can now be used
- with EIGEN_SPARSE as the backend.
-
- The performance is not as good as CXSparse. This needs to be
- investigated. Is it because the quality of AMD ordering that
- we are computing is not as good as the one for CXSparse? This
- could be because we are working with the scalar matrix instead
- of the block matrix.
-
- Also, the upper/lower triangular story is not completely clear.
- Both of these issues will be benchmarked and tackled in the
- near future.
-
- Also included in this change is a bunch of cleanup to the
- SparseNormalCholeskySolver and SparseSchurComplementSolver
- classes around the use of the of defines used to conditionally
- compile out parts of the code.
-
- The system_test has been updated to test EIGEN_SPARSE also.
-
- Change-Id: I46a57e9c4c97782696879e0b15cfc7a93fe5496a
-
-commit 1b17145adf6aa0072db2989ad799e90313970ab3
-Author: Sameer Agarwal <sameeragarwal@google.com>
-Date: Wed Jul 30 10:14:15 2014 -0700
-
- Make canned loss functions more robust.
-
- The loss functions that ship with ceres can sometimes
- generate a zero first derivative if the residual is too
- large.
-
- In such cases Corrector fails with an ugly undebuggable
- crash. This CL is the first in a series of fixes to
- take care of this.
-
- We clamp the values of rho' from below by
- numeric_limits<double>::min().
-
- Also included here is some minor cleanup where the constants
- are treated as doubles rather than integers.
-
- Thanks to Pierre Moulon for reporting this problem.
-
- Change-Id: I3aaf375303ecc2659bbf6fb56a812e7dc3a41106
diff --git a/extern/libmv/third_party/ceres/SConscript b/extern/libmv/third_party/ceres/SConscript
index a8a50dbbf7d..f53d54ba94b 100644
--- a/extern/libmv/third_party/ceres/SConscript
+++ b/extern/libmv/third_party/ceres/SConscript
@@ -13,9 +13,12 @@ src = []
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')
+if env['WITH_BF_LIBMV_SCHUR_SPECIALIZATIONS']:
+ src += env.Glob('internal/ceres/generated/*.cc')
+else:
+ 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')
+ defs.append('CERES_RESTRICT_SCHUR_SPECIALIZATION')
defs.append('CERES_HAVE_PTHREAD')
defs.append('CERES_NO_SUITESPARSE')
@@ -49,11 +52,6 @@ if env['SHARED_PTR_NAMESPACE'] == 'std::tr1':
incs = '. ../../ ../../../Eigen3 ./include ./internal ../gflags ./config'
-# work around broken hashtable in 10.5 SDK
-if env['OURPLATFORM'] == 'darwin' and env['WITH_BF_BOOST']:
- incs += ' ' + env['BF_BOOST_INC']
- defs.append('CERES_HASH_BOOST')
-
if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'linuxcross', 'win64-vc', 'win64-mingw'):
if env['OURPLATFORM'] in ('win32-vc', 'win64-vc'):
incs += ' ../msinttypes'
diff --git a/extern/libmv/third_party/ceres/bundle.sh b/extern/libmv/third_party/ceres/bundle.sh
index 89b32416e22..0becc87dd4f 100755
--- a/extern/libmv/third_party/ceres/bundle.sh
+++ b/extern/libmv/third_party/ceres/bundle.sh
@@ -129,7 +129,7 @@ set(INC
)
set(INC_SYS
- ../../../Eigen3
+ ${EIGEN3_INCLUDE_DIRS}
)
set(SRC
@@ -138,10 +138,12 @@ ${sources}
${headers}
)
-if(TRUE)
+if(WITH_LIBMV_SCHUR_SPECIALIZATIONS)
list(APPEND SRC
${generated_sources}
)
+else()
+ add_definitions(-DCERES_RESTRICT_SCHUR_SPECIALIZATION)
endif()
if(WIN32)
@@ -199,7 +201,7 @@ blender_add_lib(extern_ceres "\${SRC}" "\${INC}" "\${INC_SYS}")
EOF
cat > SConscript << EOF
-#!/usr/bin/python
+#!/usr/bin/env python
# NOTE: This file is automatically generated by bundle.sh script
# If you're doing changes in this file, please update template
@@ -214,9 +216,12 @@ src = []
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')
+if env['WITH_BF_LIBMV_SCHUR_SPECIALIZATIONS']:
+ src += env.Glob('internal/ceres/generated/*.cc')
+else:
+ 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')
+ defs.append('CERES_RESTRICT_SCHUR_SPECIALIZATION')
defs.append('CERES_HAVE_PTHREAD')
defs.append('CERES_NO_SUITESPARSE')
@@ -250,11 +255,6 @@ if env['SHARED_PTR_NAMESPACE'] == 'std::tr1':
incs = '. ../../ ../../../Eigen3 ./include ./internal ../gflags ./config'
-# work around broken hashtable in 10.5 SDK
-if env['OURPLATFORM'] == 'darwin' and env['WITH_BF_BOOST']:
- incs += ' ' + env['BF_BOOST_INC']
- defs.append('CERES_HASH_BOOST')
-
if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'linuxcross', 'win64-vc', 'win64-mingw'):
if env['OURPLATFORM'] in ('win32-vc', 'win64-vc'):
incs += ' ../msinttypes'
diff --git a/extern/libmv/third_party/ceres/include/ceres/gradient_problem_solver.h b/extern/libmv/third_party/ceres/include/ceres/gradient_problem_solver.h
index 484d88ece82..db706f7dbaf 100644
--- a/extern/libmv/third_party/ceres/include/ceres/gradient_problem_solver.h
+++ b/extern/libmv/third_party/ceres/include/ceres/gradient_problem_solver.h
@@ -72,7 +72,6 @@ class CERES_EXPORT GradientProblemSolver {
max_line_search_step_expansion = 10.0;
max_num_iterations = 50;
max_solver_time_in_seconds = 1e9;
- num_threads = 1;
function_tolerance = 1e-6;
gradient_tolerance = 1e-10;
logging_type = PER_MINIMIZER_ITERATION;
@@ -224,10 +223,6 @@ class CERES_EXPORT GradientProblemSolver {
// Maximum time for which the minimizer should run for.
double max_solver_time_in_seconds;
- // Number of threads used by Ceres for evaluating the cost and
- // jacobians.
- int num_threads;
-
// Minimizer terminates when
//
// (new_cost - old_cost) < function_tolerance * old_cost;
@@ -251,13 +246,6 @@ class CERES_EXPORT GradientProblemSolver {
// is sent to STDOUT.
bool minimizer_progress_to_stdout;
- // If true, the user's parameter blocks are updated at the end of
- // every Minimizer iteration, otherwise they are updated when the
- // Minimizer terminates. This is useful if, for example, the user
- // wishes to visualize the state of the optimization every
- // iteration.
- bool update_state_every_iteration;
-
// Callbacks that are executed at the end of each iteration of the
// Minimizer. An iteration may terminate midway, either due to
// numerical failures or because one of the convergence tests has
@@ -309,10 +297,10 @@ class CERES_EXPORT GradientProblemSolver {
// Sum total of all time spent inside Ceres when Solve is called.
double total_time_in_seconds;
- // Time (in seconds) spent evaluating the residual vector.
+ // Time (in seconds) spent evaluating the cost.
double cost_evaluation_time_in_seconds;
- // Time (in seconds) spent evaluating the jacobian matrix.
+ // Time (in seconds) spent evaluating the gradient.
double gradient_evaluation_time_in_seconds;
// Number of parameters in the probem.
diff --git a/extern/libmv/third_party/ceres/include/ceres/solver.h b/extern/libmv/third_party/ceres/include/ceres/solver.h
index 0af34cacef2..a5efa2a3915 100644
--- a/extern/libmv/third_party/ceres/include/ceres/solver.h
+++ b/extern/libmv/third_party/ceres/include/ceres/solver.h
@@ -118,6 +118,7 @@ class CERES_EXPORT Solver {
#endif
num_linear_solver_threads = 1;
+ use_explicit_schur_complement = false;
use_postordering = false;
dynamic_sparsity = false;
min_linear_solver_iterations = 0;
@@ -496,6 +497,29 @@ class CERES_EXPORT Solver {
// smaller than the group containing cameras.
shared_ptr<ParameterBlockOrdering> linear_solver_ordering;
+ // Use an explicitly computed Schur complement matrix with
+ // ITERATIVE_SCHUR.
+ //
+ // By default this option is disabled and ITERATIVE_SCHUR
+ // evaluates evaluates matrix-vector products between the Schur
+ // complement and a vector implicitly by exploiting the algebraic
+ // expression for the Schur complement.
+ //
+ // The cost of this evaluation scales with the number of non-zeros
+ // in the Jacobian.
+ //
+ // For small to medium sized problems there is a sweet spot where
+ // computing the Schur complement is cheap enough that it is much
+ // more efficient to explicitly compute it and use it for evaluating
+ // the matrix-vector products.
+ //
+ // Enabling this option tells ITERATIVE_SCHUR to use an explicitly
+ // computed Schur complement.
+ //
+ // NOTE: This option can only be used with the SCHUR_JACOBI
+ // preconditioner.
+ bool use_explicit_schur_complement;
+
// Sparse Cholesky factorization algorithms use a fill-reducing
// ordering to permute the columns of the Jacobian matrix. There
// are two ways of doing this.
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 19b749bfc39..7f79a4f993d 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
@@ -30,9 +30,9 @@
#include "ceres/block_jacobi_preconditioner.h"
-#include "Eigen/Cholesky"
#include "ceres/block_sparse_matrix.h"
#include "ceres/block_structure.h"
+#include "ceres/block_random_access_diagonal_matrix.h"
#include "ceres/casts.h"
#include "ceres/integral_types.h"
#include "ceres/internal/eigen.h"
@@ -41,27 +41,14 @@ namespace ceres {
namespace internal {
BlockJacobiPreconditioner::BlockJacobiPreconditioner(
- const BlockSparseMatrix& A)
- : num_rows_(A.num_rows()),
- block_structure_(*A.block_structure()) {
- // Calculate the amount of storage needed.
- int storage_needed = 0;
- for (int c = 0; c < block_structure_.cols.size(); ++c) {
- int size = block_structure_.cols[c].size;
- storage_needed += size * size;
+ const BlockSparseMatrix& A) {
+ const CompressedRowBlockStructure* bs = A.block_structure();
+ vector<int> blocks(bs->cols.size());
+ for (int i = 0; i < blocks.size(); ++i) {
+ blocks[i] = bs->cols[i].size;
}
- // Size the offsets and storage.
- blocks_.resize(block_structure_.cols.size());
- block_storage_.resize(storage_needed);
-
- // Put pointers to the storage in the offsets.
- double* block_cursor = &block_storage_[0];
- for (int c = 0; c < block_structure_.cols.size(); ++c) {
- int size = block_structure_.cols[c].size;
- blocks_[c] = block_cursor;
- block_cursor += size * size;
- }
+ m_.reset(new BlockRandomAccessDiagonalMatrix(blocks));
}
BlockJacobiPreconditioner::~BlockJacobiPreconditioner() {}
@@ -69,70 +56,50 @@ BlockJacobiPreconditioner::~BlockJacobiPreconditioner() {}
bool BlockJacobiPreconditioner::UpdateImpl(const BlockSparseMatrix& A,
const double* D) {
const CompressedRowBlockStructure* bs = A.block_structure();
-
- // Compute the diagonal blocks by block inner products.
- std::fill(block_storage_.begin(), block_storage_.end(), 0.0);
const double* values = A.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 = 0; c < cells.size(); ++c) {
- const int col_block_size = bs->cols[cells[c].block_id].size;
- ConstMatrixRef m(values + cells[c].position,
+ m_->SetZero();
+ for (int i = 0; i < bs->rows.size(); ++i) {
+ const int row_block_size = bs->rows[i].block.size;
+ const vector<Cell>& cells = bs->rows[i].cells;
+ for (int j = 0; j < cells.size(); ++j) {
+ const int block_id = cells[j].block_id;
+ const int col_block_size = bs->cols[block_id].size;
+
+ int r, c, row_stride, col_stride;
+ CellInfo* cell_info = m_->GetCell(block_id, block_id,
+ &r, &c,
+ &row_stride, &col_stride);
+ MatrixRef m(cell_info->values, row_stride, col_stride);
+ ConstMatrixRef b(values + cells[j].position,
row_block_size,
col_block_size);
-
- MatrixRef(blocks_[cells[c].block_id],
- col_block_size,
- col_block_size).noalias() += m.transpose() * m;
-
- // TODO(keir): Figure out when the below expression is actually faster
- // than doing the full rank update. The issue is that for smaller sizes,
- // the rankUpdate() function is slower than the full product done above.
- //
- // On the typical bundling problems, the above product is ~5% faster.
- //
- // MatrixRef(blocks_[cells[c].block_id],
- // col_block_size,
- // col_block_size)
- // .selfadjointView<Eigen::Upper>()
- // .rankUpdate(m);
- //
+ m.block(r, c, col_block_size, col_block_size) += b.transpose() * b;
}
}
- // Add the diagonal and invert each block.
- for (int c = 0; c < bs->cols.size(); ++c) {
- const int size = block_structure_.cols[c].size;
- const int position = block_structure_.cols[c].position;
- MatrixRef block(blocks_[c], size, size);
-
- if (D != NULL) {
- block.diagonal() +=
- ConstVectorRef(D + position, size).array().square().matrix();
+ if (D != NULL) {
+ // Add the diagonal.
+ int position = 0;
+ for (int i = 0; i < bs->cols.size(); ++i) {
+ const int block_size = bs->cols[i].size;
+ int r, c, row_stride, col_stride;
+ CellInfo* cell_info = m_->GetCell(i, i,
+ &r, &c,
+ &row_stride, &col_stride);
+ MatrixRef m(cell_info->values, row_stride, col_stride);
+ m.block(r, c, block_size, block_size).diagonal() +=
+ ConstVectorRef(D + position, block_size).array().square().matrix();
+ position += block_size;
}
-
- block = block.selfadjointView<Eigen::Upper>()
- .llt()
- .solve(Matrix::Identity(size, size));
}
+
+ m_->Invert();
return true;
}
void BlockJacobiPreconditioner::RightMultiply(const double* x,
double* y) const {
- for (int c = 0; c < block_structure_.cols.size(); ++c) {
- const int size = block_structure_.cols[c].size;
- const int position = block_structure_.cols[c].position;
- ConstMatrixRef D(blocks_[c], size, size);
- ConstVectorRef x_block(x + position, size);
- VectorRef y_block(y + position, size);
- y_block += D * x_block;
- }
-}
-
-void BlockJacobiPreconditioner::LeftMultiply(const double* x, double* y) const {
- RightMultiply(x, y);
+ m_->RightMultiply(x, y);
}
} // namespace internal
diff --git a/extern/libmv/third_party/ceres/internal/ceres/block_jacobi_preconditioner.h b/extern/libmv/third_party/ceres/internal/ceres/block_jacobi_preconditioner.h
index 3505a01248b..e23e0e2d24c 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/block_jacobi_preconditioner.h
+++ b/extern/libmv/third_party/ceres/internal/ceres/block_jacobi_preconditioner.h
@@ -1,5 +1,5 @@
// Ceres Solver - A fast non-linear least squares minimizer
-// Copyright 2012 Google Inc. All rights reserved.
+// Copyright 2014 Google Inc. All rights reserved.
// http://code.google.com/p/ceres-solver/
//
// Redistribution and use in source and binary forms, with or without
@@ -32,6 +32,8 @@
#define CERES_INTERNAL_BLOCK_JACOBI_PRECONDITIONER_H_
#include <vector>
+#include "ceres/block_random_access_diagonal_matrix.h"
+#include "ceres/internal/scoped_ptr.h"
#include "ceres/preconditioner.h"
namespace ceres {
@@ -39,7 +41,6 @@ namespace internal {
class BlockSparseMatrix;
struct CompressedRowBlockStructure;
-class LinearOperator;
// A block Jacobi preconditioner. This is intended for use with
// conjugate gradients, or other iterative symmetric solvers. To use
@@ -59,19 +60,14 @@ class BlockJacobiPreconditioner : public BlockSparseMatrixPreconditioner {
// Preconditioner interface
virtual void RightMultiply(const double* x, double* y) const;
- virtual void LeftMultiply(const double* x, double* y) const;
- virtual int num_rows() const { return num_rows_; }
- virtual int num_cols() const { return num_rows_; }
+ virtual int num_rows() const { return m_->num_rows(); }
+ virtual int num_cols() const { return m_->num_rows(); }
+ const BlockRandomAccessDiagonalMatrix& matrix() const { return *m_; }
private:
virtual bool UpdateImpl(const BlockSparseMatrix& A, const double* D);
- std::vector<double*> blocks_;
- std::vector<double> block_storage_;
- int num_rows_;
-
- // The block structure of the matrix this preconditioner is for (e.g. J).
- const CompressedRowBlockStructure& block_structure_;
+ scoped_ptr<BlockRandomAccessDiagonalMatrix> m_;
};
} // namespace internal
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
index d8bf4ef0cb5..b7ff33184cb 100644
--- 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
@@ -34,16 +34,19 @@
#include <set>
#include <utility>
#include <vector>
+#include "Eigen/Dense"
#include "ceres/internal/port.h"
#include "ceres/internal/scoped_ptr.h"
+#include "ceres/stl_util.h"
#include "ceres/triplet_sparse_matrix.h"
#include "ceres/types.h"
-#include "ceres/stl_util.h"
#include "glog/logging.h"
namespace ceres {
namespace internal {
+// TODO(sameeragarwal): Drop the dependence on TripletSparseMatrix.
+
BlockRandomAccessDiagonalMatrix::BlockRandomAccessDiagonalMatrix(
const vector<int>& blocks)
: blocks_(blocks) {
@@ -51,9 +54,9 @@ BlockRandomAccessDiagonalMatrix::BlockRandomAccessDiagonalMatrix(
// rows/columns.
int num_cols = 0;
int num_nonzeros = 0;
- vector<int> col_layout;
+ vector<int> block_positions;
for (int i = 0; i < blocks_.size(); ++i) {
- col_layout.push_back(num_cols);
+ block_positions.push_back(num_cols);
num_cols += blocks_[i];
num_nonzeros += blocks_[i] * blocks_[i];
}
@@ -72,7 +75,7 @@ BlockRandomAccessDiagonalMatrix::BlockRandomAccessDiagonalMatrix(
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];
+ const int block_begin = block_positions[i];
for (int r = 0; r < block_size; ++r) {
for (int c = 0; c < block_size; ++c, ++pos) {
rows[pos] = block_begin + r;
@@ -116,5 +119,34 @@ void BlockRandomAccessDiagonalMatrix::SetZero() {
}
}
+void BlockRandomAccessDiagonalMatrix::Invert() {
+ double* values = tsm_->mutable_values();
+ for (int i = 0; i < blocks_.size(); ++i) {
+ const int block_size = blocks_[i];
+ MatrixRef block(values, block_size, block_size);
+ block =
+ block
+ .selfadjointView<Eigen::Upper>()
+ .llt()
+ .solve(Matrix::Identity(block_size, block_size));
+ values += block_size * block_size;
+ }
+}
+
+void BlockRandomAccessDiagonalMatrix::RightMultiply(const double* x,
+ double* y) const {
+ CHECK_NOTNULL(x);
+ CHECK_NOTNULL(y);
+ const double* values = tsm_->values();
+ for (int i = 0; i < blocks_.size(); ++i) {
+ const int block_size = blocks_[i];
+ ConstMatrixRef block(values, block_size, block_size);
+ VectorRef(y, block_size).noalias() += block * ConstVectorRef(x, block_size);
+ x += block_size;
+ y += block_size;
+ values += block_size * block_size;
+ }
+}
+
} // 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
index 6b3cff2338f..ea9967817db 100644
--- 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
@@ -52,7 +52,7 @@ namespace internal {
class BlockRandomAccessDiagonalMatrix : public BlockRandomAccessMatrix {
public:
// blocks is an array of block sizes.
- BlockRandomAccessDiagonalMatrix(const vector<int>& blocks);
+ explicit 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.
@@ -70,11 +70,16 @@ class BlockRandomAccessDiagonalMatrix : public BlockRandomAccessMatrix {
// locked.
virtual void SetZero();
+ // Invert the matrix assuming that each block is positive definite.
+ void Invert();
+
+ // y += S * x
+ void RightMultiply(const double* x, double* y) const;
+
// 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(); }
diff --git a/extern/libmv/third_party/ceres/internal/ceres/block_random_access_sparse_matrix.cc b/extern/libmv/third_party/ceres/internal/ceres/block_random_access_sparse_matrix.cc
index f789436364a..c43a9b78feb 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/block_random_access_sparse_matrix.cc
+++ b/extern/libmv/third_party/ceres/internal/ceres/block_random_access_sparse_matrix.cc
@@ -54,9 +54,9 @@ BlockRandomAccessSparseMatrix::BlockRandomAccessSparseMatrix(
// Build the row/column layout vector and count the number of scalar
// rows/columns.
int num_cols = 0;
- vector<int> col_layout;
+ block_positions_.reserve(blocks_.size());
for (int i = 0; i < blocks_.size(); ++i) {
- col_layout.push_back(num_cols);
+ block_positions_.push_back(num_cols);
num_cols += blocks_[i];
}
@@ -88,6 +88,8 @@ BlockRandomAccessSparseMatrix::BlockRandomAccessSparseMatrix(
++it) {
const int row_block_size = blocks_[it->first];
const int col_block_size = blocks_[it->second];
+ cell_values_.push_back(make_pair(make_pair(it->first, it->second),
+ values + pos));
layout_[IntPairToLong(it->first, it->second)] =
new CellInfo(values + pos);
pos += row_block_size * col_block_size;
@@ -105,8 +107,8 @@ BlockRandomAccessSparseMatrix::BlockRandomAccessSparseMatrix(
layout_[IntPairToLong(row_block_id, col_block_id)]->values - values;
for (int r = 0; r < row_block_size; ++r) {
for (int c = 0; c < col_block_size; ++c, ++pos) {
- rows[pos] = col_layout[row_block_id] + r;
- cols[pos] = col_layout[col_block_id] + c;
+ rows[pos] = block_positions_[row_block_id] + r;
+ cols[pos] = block_positions_[col_block_id] + c;
values[pos] = 1.0;
DCHECK_LT(rows[pos], tsm_->num_rows());
DCHECK_LT(cols[pos], tsm_->num_rows());
@@ -154,5 +156,36 @@ void BlockRandomAccessSparseMatrix::SetZero() {
}
}
+void BlockRandomAccessSparseMatrix::SymmetricRightMultiply(const double* x,
+ double* y) const {
+ vector< pair<pair<int, int>, double*> >::const_iterator it =
+ cell_values_.begin();
+ for (; it != cell_values_.end(); ++it) {
+ const int row = it->first.first;
+ const int row_block_size = blocks_[row];
+ const int row_block_pos = block_positions_[row];
+
+ const int col = it->first.second;
+ const int col_block_size = blocks_[col];
+ const int col_block_pos = block_positions_[col];
+
+ MatrixVectorMultiply<Eigen::Dynamic, Eigen::Dynamic, 1>(
+ it->second, row_block_size, col_block_size,
+ x + col_block_pos,
+ y + row_block_pos);
+
+ // Since the matrix is symmetric, but only the upper triangular
+ // part is stored, if the block being accessed is not a diagonal
+ // block, then use the same block to do the corresponding lower
+ // triangular multiply also.
+ if (row != col) {
+ MatrixTransposeVectorMultiply<Eigen::Dynamic, Eigen::Dynamic, 1>(
+ it->second, row_block_size, col_block_size,
+ x + row_block_pos,
+ y + col_block_pos);
+ }
+ }
+}
+
} // namespace internal
} // namespace ceres
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 27b10296d6c..51b5d20cfe0 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
@@ -43,6 +43,7 @@
#include "ceres/internal/port.h"
#include "ceres/internal/scoped_ptr.h"
#include "ceres/types.h"
+#include "ceres/small_blas.h"
namespace ceres {
namespace internal {
@@ -75,6 +76,12 @@ class BlockRandomAccessSparseMatrix : public BlockRandomAccessMatrix {
// locked.
virtual void SetZero();
+ // Assume that the matrix is symmetric and only one half of the
+ // matrix is stored.
+ //
+ // y += S * x
+ void SymmetricRightMultiply(const double* x, double* y) const;
+
// 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(); }
@@ -84,19 +91,30 @@ class BlockRandomAccessSparseMatrix : public BlockRandomAccessMatrix {
TripletSparseMatrix* mutable_matrix() { return tsm_.get(); }
private:
- int64 IntPairToLong(int a, int b) {
- return a * kMaxRowBlocks + b;
+ int64 IntPairToLong(int row, int col) const {
+ return row * kMaxRowBlocks + col;
+ }
+
+ void LongToIntPair(int64 index, int* row, int* col) const {
+ *row = index / kMaxRowBlocks;
+ *col = index % kMaxRowBlocks;
}
const int64 kMaxRowBlocks;
+
// row/column block sizes.
const vector<int> blocks_;
+ vector<int> block_positions_;
// A mapping from <row_block_id, col_block_id> to the position in
// the values array of tsm_ where the block is stored.
typedef HashMap<long int, CellInfo* > LayoutType;
LayoutType layout_;
+ // In order traversal of contents of the matrix. This allows us to
+ // implement a matrix-vector which is 20% faster than using the
+ // iterator in the Layout object instead.
+ vector<pair<pair<int, int>, double*> > cell_values_;
// The underlying matrix object which actually stores the cells.
scoped_ptr<TripletSparseMatrix> tsm_;
diff --git a/extern/libmv/third_party/ceres/internal/ceres/callbacks.cc b/extern/libmv/third_party/ceres/internal/ceres/callbacks.cc
index d2236335c53..7d5ce2548e4 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/callbacks.cc
+++ b/extern/libmv/third_party/ceres/internal/ceres/callbacks.cc
@@ -81,7 +81,7 @@ CallbackReturnType LoggingCallback::operator()(
output = "iter cost cost_change |gradient| |step| tr_ratio tr_radius ls_iter iter_time total_time\n";
}
const char* kReportRowFormat =
- "% 4d % 8e % 3.2e % 3.2e % 3.2e % 3.2e % 3.2e % 3d % 3.2e % 3.2e";
+ "% 4d % 8e % 3.2e % 3.2e % 3.2e % 3.2e % 3.2e % 4d % 3.2e % 3.2e";
output += StringPrintf(kReportRowFormat,
summary.iteration,
summary.cost,
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 1d55458bb69..0d8adee7cd8 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
@@ -1,5 +1,5 @@
// Ceres Solver - A fast non-linear least squares minimizer
-// Copyright 2012 Google Inc. All rights reserved.
+// Copyright 2014 Google Inc. All rights reserved.
// http://code.google.com/p/ceres-solver/
//
// Redistribution and use in source and binary forms, with or without
@@ -140,15 +140,24 @@ void CoordinateDescentMinimizer::Minimize(
}
for (int i = 0; i < independent_set_offsets_.size() - 1; ++i) {
- // No point paying the price for an OpemMP call if the set if of
+ const int num_problems =
+ independent_set_offsets_[i + 1] - independent_set_offsets_[i];
+ // No point paying the price for an OpemMP call if the set is of
// size zero.
- if (independent_set_offsets_[i] == independent_set_offsets_[i + 1]) {
+ if (num_problems == 0) {
continue;
}
+#ifdef CERES_USE_OPENMP
+ const int num_inner_iteration_threads =
+ min(options.num_threads, num_problems);
+ evaluator_options_.num_threads =
+ max(1, options.num_threads / num_inner_iteration_threads);
+
// The parameter blocks in each independent set can be optimized
// in parallel, since they do not co-occur in any residual block.
-#pragma omp parallel for num_threads(options.num_threads)
+#pragma omp parallel for num_threads(num_inner_iteration_threads)
+#endif
for (int j = independent_set_offsets_[i];
j < independent_set_offsets_[i + 1];
++j) {
diff --git a/extern/libmv/third_party/ceres/internal/ceres/linear_solver.cc b/extern/libmv/third_party/ceres/internal/ceres/linear_solver.cc
index d905ec2e1fd..e479b751363 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/linear_solver.cc
+++ b/extern/libmv/third_party/ceres/internal/ceres/linear_solver.cc
@@ -96,7 +96,11 @@ LinearSolver* LinearSolver::Create(const LinearSolver::Options& options) {
return new DenseSchurComplementSolver(options);
case ITERATIVE_SCHUR:
- return new IterativeSchurComplementSolver(options);
+ if (options.use_explicit_schur_complement) {
+ return new SparseSchurComplementSolver(options);
+ } else {
+ return new IterativeSchurComplementSolver(options);
+ }
case DENSE_QR:
return new DenseQRSolver(options);
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 58b9044b8f9..5f59765f074 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/linear_solver.h
+++ b/extern/libmv/third_party/ceres/internal/ceres/linear_solver.h
@@ -99,6 +99,7 @@ class LinearSolver {
sparse_linear_algebra_library_type(SUITE_SPARSE),
use_postordering(false),
dynamic_sparsity(false),
+ use_explicit_schur_complement(false),
min_num_iterations(1),
max_num_iterations(1),
num_threads(1),
@@ -114,9 +115,10 @@ class LinearSolver {
DenseLinearAlgebraLibraryType dense_linear_algebra_library_type;
SparseLinearAlgebraLibraryType sparse_linear_algebra_library_type;
- // See solver.h for information about this flag.
+ // See solver.h for information about these flags.
bool use_postordering;
bool dynamic_sparsity;
+ bool use_explicit_schur_complement;
// Number of internal iterations that the solver uses. This
// parameter only makes sense for iterative solvers like CG.
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 d2aa168c807..33f812b8c96 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
@@ -40,6 +40,7 @@
#include "ceres/block_random_access_sparse_matrix.h"
#include "ceres/block_sparse_matrix.h"
#include "ceres/block_structure.h"
+#include "ceres/conjugate_gradients_solver.h"
#include "ceres/cxsparse.h"
#include "ceres/detect_structure.h"
#include "ceres/internal/eigen.h"
@@ -56,6 +57,61 @@
namespace ceres {
namespace internal {
+namespace {
+
+class BlockRandomAccessSparseMatrixAdapter : public LinearOperator {
+ public:
+ explicit BlockRandomAccessSparseMatrixAdapter(
+ const BlockRandomAccessSparseMatrix& m)
+ : m_(m) {
+ }
+
+ virtual ~BlockRandomAccessSparseMatrixAdapter() {}
+
+ // y = y + Ax;
+ virtual void RightMultiply(const double* x, double* y) const {
+ m_.SymmetricRightMultiply(x, y);
+ }
+
+ // y = y + A'x;
+ virtual void LeftMultiply(const double* x, double* y) const {
+ m_.SymmetricRightMultiply(x, y);
+ }
+
+ virtual int num_rows() const { return m_.num_rows(); }
+ virtual int num_cols() const { return m_.num_rows(); }
+
+ private:
+ const BlockRandomAccessSparseMatrix& m_;
+};
+
+class BlockRandomAccessDiagonalMatrixAdapter : public LinearOperator {
+ public:
+ explicit BlockRandomAccessDiagonalMatrixAdapter(
+ const BlockRandomAccessDiagonalMatrix& m)
+ : m_(m) {
+ }
+
+ virtual ~BlockRandomAccessDiagonalMatrixAdapter() {}
+
+ // y = y + Ax;
+ virtual void RightMultiply(const double* x, double* y) const {
+ m_.RightMultiply(x, y);
+ }
+
+ // y = y + A'x;
+ virtual void LeftMultiply(const double* x, double* y) const {
+ m_.RightMultiply(x, y);
+ }
+
+ virtual int num_rows() const { return m_.num_rows(); }
+ virtual int num_cols() const { return m_.num_rows(); }
+
+ private:
+ const BlockRandomAccessDiagonalMatrix& m_;
+};
+
+} // namespace
LinearSolver::Summary SchurComplementSolver::SolveImpl(
BlockSparseMatrix* A,
@@ -82,7 +138,7 @@ LinearSolver::Summary SchurComplementSolver::SolveImpl(
double* reduced_solution = x + A->num_cols() - lhs_->num_cols();
const LinearSolver::Summary summary =
- SolveReducedLinearSystem(reduced_solution);
+ SolveReducedLinearSystem(per_solve_options, reduced_solution);
event_logger.AddEvent("ReducedSolve");
if (summary.termination_type == LINEAR_SOLVER_SUCCESS) {
@@ -115,7 +171,9 @@ void DenseSchurComplementSolver::InitStorage(
// BlockRandomAccessDenseMatrix. The linear system is solved using
// Eigen's Cholesky factorization.
LinearSolver::Summary
-DenseSchurComplementSolver::SolveReducedLinearSystem(double* solution) {
+DenseSchurComplementSolver::SolveReducedLinearSystem(
+ const LinearSolver::PerSolveOptions& per_solve_options,
+ double* solution) {
LinearSolver::Summary summary;
summary.num_iterations = 0;
summary.termination_type = LINEAR_SOLVER_SUCCESS;
@@ -249,14 +307,25 @@ void SparseSchurComplementSolver::InitStorage(
}
LinearSolver::Summary
-SparseSchurComplementSolver::SolveReducedLinearSystem(double* solution) {
+SparseSchurComplementSolver::SolveReducedLinearSystem(
+ const LinearSolver::PerSolveOptions& per_solve_options,
+ double* solution) {
+ if (options().type == ITERATIVE_SCHUR) {
+ CHECK(options().use_explicit_schur_complement);
+ return SolveReducedLinearSystemUsingConjugateGradients(per_solve_options,
+ solution);
+ }
+
switch (options().sparse_linear_algebra_library_type) {
case SUITE_SPARSE:
- return SolveReducedLinearSystemUsingSuiteSparse(solution);
+ return SolveReducedLinearSystemUsingSuiteSparse(per_solve_options,
+ solution);
case CX_SPARSE:
- return SolveReducedLinearSystemUsingCXSparse(solution);
+ return SolveReducedLinearSystemUsingCXSparse(per_solve_options,
+ solution);
case EIGEN_SPARSE:
- return SolveReducedLinearSystemUsingEigen(solution);
+ return SolveReducedLinearSystemUsingEigen(per_solve_options,
+ solution);
default:
LOG(FATAL) << "Unknown sparse linear algebra library : "
<< options().sparse_linear_algebra_library_type;
@@ -270,6 +339,7 @@ SparseSchurComplementSolver::SolveReducedLinearSystem(double* solution) {
// CHOLMOD's sparse cholesky factorization routines.
LinearSolver::Summary
SparseSchurComplementSolver::SolveReducedLinearSystemUsingSuiteSparse(
+ const LinearSolver::PerSolveOptions& per_solve_options,
double* solution) {
#ifdef CERES_NO_SUITESPARSE
@@ -377,6 +447,7 @@ SparseSchurComplementSolver::SolveReducedLinearSystemUsingSuiteSparse(
// CXSparse's sparse cholesky factorization routines.
LinearSolver::Summary
SparseSchurComplementSolver::SolveReducedLinearSystemUsingCXSparse(
+ const LinearSolver::PerSolveOptions& per_solve_options,
double* solution) {
#ifdef CERES_NO_CXSPARSE
@@ -433,6 +504,7 @@ SparseSchurComplementSolver::SolveReducedLinearSystemUsingCXSparse(
// Eigen's sparse cholesky factorization routines.
LinearSolver::Summary
SparseSchurComplementSolver::SolveReducedLinearSystemUsingEigen(
+ const LinearSolver::PerSolveOptions& per_solve_options,
double* solution) {
#ifndef CERES_USE_EIGEN_SPARSE
@@ -514,5 +586,79 @@ SparseSchurComplementSolver::SolveReducedLinearSystemUsingEigen(
#endif // CERES_USE_EIGEN_SPARSE
}
+LinearSolver::Summary
+SparseSchurComplementSolver::SolveReducedLinearSystemUsingConjugateGradients(
+ const LinearSolver::PerSolveOptions& per_solve_options,
+ double* solution) {
+ const int num_rows = lhs()->num_rows();
+ // The case where there are no f blocks, and the system is block
+ // diagonal.
+ if (num_rows == 0) {
+ LinearSolver::Summary summary;
+ summary.num_iterations = 0;
+ summary.termination_type = LINEAR_SOLVER_SUCCESS;
+ summary.message = "Success.";
+ return summary;
+ }
+
+ // Only SCHUR_JACOBI is supported over here right now.
+ CHECK_EQ(options().preconditioner_type, SCHUR_JACOBI);
+
+ if (preconditioner_.get() == NULL) {
+ preconditioner_.reset(new BlockRandomAccessDiagonalMatrix(blocks_));
+ }
+
+ BlockRandomAccessSparseMatrix* sc =
+ down_cast<BlockRandomAccessSparseMatrix*>(
+ const_cast<BlockRandomAccessMatrix*>(lhs()));
+
+ // Extract block diagonal from the Schur complement to construct the
+ // schur_jacobi preconditioner.
+ for (int i = 0; i < blocks_.size(); ++i) {
+ const int block_size = blocks_[i];
+
+ int sc_r, sc_c, sc_row_stride, sc_col_stride;
+ CellInfo* sc_cell_info =
+ CHECK_NOTNULL(sc->GetCell(i, i,
+ &sc_r, &sc_c,
+ &sc_row_stride, &sc_col_stride));
+ MatrixRef sc_m(sc_cell_info->values, sc_row_stride, sc_col_stride);
+
+ int pre_r, pre_c, pre_row_stride, pre_col_stride;
+ CellInfo* pre_cell_info = CHECK_NOTNULL(
+ preconditioner_->GetCell(i, i,
+ &pre_r, &pre_c,
+ &pre_row_stride, &pre_col_stride));
+ MatrixRef pre_m(pre_cell_info->values, pre_row_stride, pre_col_stride);
+
+ pre_m.block(pre_r, pre_c, block_size, block_size) =
+ sc_m.block(sc_r, sc_c, block_size, block_size);
+ }
+ preconditioner_->Invert();
+
+ VectorRef(solution, num_rows).setZero();
+
+ scoped_ptr<LinearOperator> lhs_adapter(
+ new BlockRandomAccessSparseMatrixAdapter(*sc));
+ scoped_ptr<LinearOperator> preconditioner_adapter(
+ new BlockRandomAccessDiagonalMatrixAdapter(*preconditioner_));
+
+
+ LinearSolver::Options cg_options;
+ cg_options.min_num_iterations = options().min_num_iterations;
+ cg_options.max_num_iterations = options().max_num_iterations;
+ ConjugateGradientsSolver cg_solver(cg_options);
+
+ LinearSolver::PerSolveOptions cg_per_solve_options;
+ cg_per_solve_options.r_tolerance = per_solve_options.r_tolerance;
+ cg_per_solve_options.q_tolerance = per_solve_options.q_tolerance;
+ cg_per_solve_options.preconditioner = preconditioner_adapter.get();
+
+ return cg_solver.Solve(lhs_adapter.get(),
+ rhs(),
+ cg_per_solve_options,
+ solution);
+}
+
} // namespace internal
} // namespace ceres
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 1b431dc5340..93d23e3d012 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
@@ -46,6 +46,7 @@
#include "ceres/suitesparse.h"
#include "ceres/internal/scoped_ptr.h"
#include "ceres/types.h"
+#include "ceres/block_random_access_diagonal_matrix.h"
#ifdef CERES_USE_EIGEN_SPARSE
#include "Eigen/SparseCholesky"
@@ -134,6 +135,7 @@ class SchurComplementSolver : public BlockSparseMatrixSolver {
private:
virtual void InitStorage(const CompressedRowBlockStructure* bs) = 0;
virtual LinearSolver::Summary SolveReducedLinearSystem(
+ const LinearSolver::PerSolveOptions& per_solve_options,
double* solution) = 0;
LinearSolver::Options options_;
@@ -155,6 +157,7 @@ class DenseSchurComplementSolver : public SchurComplementSolver {
private:
virtual void InitStorage(const CompressedRowBlockStructure* bs);
virtual LinearSolver::Summary SolveReducedLinearSystem(
+ const LinearSolver::PerSolveOptions& per_solve_options,
double* solution);
CERES_DISALLOW_COPY_AND_ASSIGN(DenseSchurComplementSolver);
@@ -169,12 +172,19 @@ class SparseSchurComplementSolver : public SchurComplementSolver {
private:
virtual void InitStorage(const CompressedRowBlockStructure* bs);
virtual LinearSolver::Summary SolveReducedLinearSystem(
+ const LinearSolver::PerSolveOptions& per_solve_options,
double* solution);
LinearSolver::Summary SolveReducedLinearSystemUsingSuiteSparse(
+ const LinearSolver::PerSolveOptions& per_solve_options,
double* solution);
LinearSolver::Summary SolveReducedLinearSystemUsingCXSparse(
+ const LinearSolver::PerSolveOptions& per_solve_options,
double* solution);
LinearSolver::Summary SolveReducedLinearSystemUsingEigen(
+ const LinearSolver::PerSolveOptions& per_solve_options,
+ double* solution);
+ LinearSolver::Summary SolveReducedLinearSystemUsingConjugateGradients(
+ const LinearSolver::PerSolveOptions& per_solve_options,
double* solution);
// Size of the blocks in the Schur complement.
@@ -206,6 +216,7 @@ class SparseSchurComplementSolver : public SchurComplementSolver {
scoped_ptr<SimplicialLDLT> simplicial_ldlt_;
#endif
+ scoped_ptr<BlockRandomAccessDiagonalMatrix> preconditioner_;
CERES_DISALLOW_COPY_AND_ASSIGN(SparseSchurComplementSolver);
};
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 6dc9e89d3cc..cbdb7086102 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
@@ -32,7 +32,6 @@
#include <utility>
#include <vector>
-#include "Eigen/Dense"
#include "ceres/block_random_access_diagonal_matrix.h"
#include "ceres/block_sparse_matrix.h"
#include "ceres/collections_port.h"
@@ -55,12 +54,12 @@ SchurJacobiPreconditioner::SchurJacobiPreconditioner(
<< "Jacobian should have atleast 1 f_block for "
<< "SCHUR_JACOBI preconditioner.";
- block_size_.resize(num_blocks);
+ vector<int> blocks(num_blocks);
for (int i = 0; i < num_blocks; ++i) {
- block_size_[i] = bs.cols[i + options_.elimination_groups[0]].size;
+ blocks[i] = bs.cols[i + options_.elimination_groups[0]].size;
}
- m_.reset(new BlockRandomAccessDiagonalMatrix(block_size_));
+ m_.reset(new BlockRandomAccessDiagonalMatrix(blocks));
InitEliminator(bs);
}
@@ -99,32 +98,13 @@ bool SchurJacobiPreconditioner::UpdateImpl(const BlockSparseMatrix& A,
// Compute a subset of the entries of the Schur complement.
eliminator_->Eliminate(&A, b.data(), D, m_.get(), rhs.data());
+ m_->Invert();
return true;
}
void SchurJacobiPreconditioner::RightMultiply(const double* x,
double* y) const {
- CHECK_NOTNULL(x);
- CHECK_NOTNULL(y);
-
- const double* lhs_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) {
- const int block_size = block_size_[i];
- ConstMatrixRef block(lhs_values, block_size, block_size);
-
- VectorRef(y, block_size) =
- block
- .selfadjointView<Eigen::Upper>()
- .llt()
- .solve(ConstVectorRef(x, block_size));
-
- x += block_size;
- y += block_size;
- lhs_values += block_size * block_size;
- }
+ m_->RightMultiply(x, y);
}
int SchurJacobiPreconditioner::num_rows() const {
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 aecb0151083..8b528e25075 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
@@ -94,11 +94,7 @@ class SchurJacobiPreconditioner : public BlockSparseMatrixPreconditioner {
virtual bool UpdateImpl(const BlockSparseMatrix& A, const double* D);
Preconditioner::Options options_;
-
- // Sizes of the blocks in the schur complement.
- vector<int> block_size_;
scoped_ptr<SchurEliminatorBase> eliminator_;
-
// Preconditioner matrix.
scoped_ptr<BlockRandomAccessDiagonalMatrix> m_;
CERES_DISALLOW_COPY_AND_ASSIGN(SchurJacobiPreconditioner);
diff --git a/extern/libmv/third_party/ceres/internal/ceres/solver.cc b/extern/libmv/third_party/ceres/internal/ceres/solver.cc
index f90045baac9..3512e156f9e 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/solver.cc
+++ b/extern/libmv/third_party/ceres/internal/ceres/solver.cc
@@ -120,6 +120,14 @@ bool TrustRegionOptionsAreValid(const Solver::Options& options, string* error) {
OPTION_GT(max_consecutive_nonmonotonic_steps, 0);
}
+ if (options.linear_solver_type == ITERATIVE_SCHUR &&
+ options.use_explicit_schur_complement &&
+ options.preconditioner_type != SCHUR_JACOBI) {
+ *error = "use_explicit_schur_complement only supports "
+ "SCHUR_JACOBI as the preconditioner.";
+ return false;
+ }
+
if (options.preconditioner_type == CLUSTER_JACOBI &&
options.sparse_linear_algebra_library_type != SUITE_SPARSE) {
*error = "CLUSTER_JACOBI requires "
diff --git a/extern/libmv/third_party/ceres/internal/ceres/trust_region_preprocessor.cc b/extern/libmv/third_party/ceres/internal/ceres/trust_region_preprocessor.cc
index ba3baa12c1f..22ea1ec8c80 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/trust_region_preprocessor.cc
+++ b/extern/libmv/third_party/ceres/internal/ceres/trust_region_preprocessor.cc
@@ -184,6 +184,8 @@ bool SetupLinearSolver(PreprocessedProblem* pp) {
options.sparse_linear_algebra_library_type;
pp->linear_solver_options.dense_linear_algebra_library_type =
options.dense_linear_algebra_library_type;
+ pp->linear_solver_options.use_explicit_schur_complement =
+ options.use_explicit_schur_complement;
pp->linear_solver_options.dynamic_sparsity = options.dynamic_sparsity;
pp->linear_solver_options.num_threads = options.num_linear_solver_threads;
diff --git a/extern/libmv/third_party/gflags/AUTHORS b/extern/libmv/third_party/gflags/AUTHORS.txt
index 887918bd00e..887918bd00e 100644
--- a/extern/libmv/third_party/gflags/AUTHORS
+++ b/extern/libmv/third_party/gflags/AUTHORS.txt
diff --git a/extern/libmv/third_party/gflags/COPYING b/extern/libmv/third_party/gflags/COPYING.txt
index d15b0c24134..d15b0c24134 100644
--- a/extern/libmv/third_party/gflags/COPYING
+++ b/extern/libmv/third_party/gflags/COPYING.txt
diff --git a/extern/libmv/third_party/gflags/ChangeLog b/extern/libmv/third_party/gflags/ChangeLog
deleted file mode 100644
index f9ef9350984..00000000000
--- a/extern/libmv/third_party/gflags/ChangeLog
+++ /dev/null
@@ -1,195 +0,0 @@
-Wed Jan 25 15:09:14 2012 Google Inc. <google-gflags@googlegroups.com>
-
- * gflags: version 2.0
- * Changed the 'official' gflags email in setup.py/etc
- * Renamed google-gflags.sln to gflags.sln
- * Changed copyright text to reflect Google's relinquished ownership
-
-Tue Dec 20 19:48:57 2011 Google Inc. <opensource@google.com>
-
- * google-gflags: version 1.7
- * Add CommandLineFlagInfo::flag_ptr pointing to current storage (musji)
- * PORTING: flush after writing to stderr, needed on cygwin
- * PORTING: Clean up the GFLAGS_DLL_DECL stuff better
- * Fix a bug in StringPrintf() that affected large strings (csilvers)
- * Die at configure-time when g++ isn't installed
-
-Fri Jul 29 19:05:21 2011 Google Inc. <opensource@google.com>
-
- * google-gflags: version 1.6
- * BUGFIX: Fix a bug where we were leaving out a required $(top_srcdir)
- * Fix definition of clstring (jyrki)
- * Split up flag declares into its own file (jyrki)
- * Add --version support (csilvers)
- * Update the README for gflags with static libs
- * Update acx_pthread.m4 for nostdlib
- * Change ReparseCommandLineFlags to return void (csilvers)
- * Some doc typofixes and example augmentation (various)
-
-Mon Jan 24 16:11:35 2011 Google Inc. <opensource@google.com>
-
- * google-gflags: version 1.5
- * Better reporting of current vs default value (handler)
- * Add API for cleaning up of memory at program-exit (jmarantz)
- * Fix macros to work inside namespaces (csilvers)
- * Use our own string typedef in case string is redefined (csilvers)
- * Updated to autoconf 2.65
-
-Wed Oct 13 17:40:12 2010 Google Inc. <opensource@google.com>
-
- * google-gflags: version 1.4
- * Add a check to prevent passing 0 to DEFINE_string (jorg)
- * Reduce compile (.o) size (jyrki)
- * Some small changes to quiet debug compiles (alexk)
- * PORTING: better support static linking on windows (csilvers)
- * DOCUMENTATION: change default values, use validators, etc.
- * Update the NEWS file to be non-empty
- * Add pkg-config (.pc) files for libgflags and libgflags_nothreads
-
-Mon Jan 4 18:09:30 2010 Google Inc. <opensource@google.com>
-
- * google-gflags: version 1.3
- * PORTABILITY: can now build and run tests under MSVC (csilvers)
- * Remove the python gflags code, which is now its own package (tansell)
- * Clarify that "last flag wins" in the docs (csilvers)
- * Comment danger of using GetAllFlags in validators (wojtekm)
- * PORTABILITY: Some fixes necessary for c++0x (mboerger)
- * Makefile fix: $(srcdir) -> $(top_srcdir) in one place (csilvres)
- * INSTALL: autotools to autoconf v2.64 + automake v1.11 (csilvers)
-
-Thu Sep 10 12:53:04 2009 Google Inc. <opensource@google.com>
-
- * google-gflags: version 1.2
- * PORTABILITY: can now build and run tests under mingw (csilvers)
- * Using a string arg for a bool flag is a compile-time error (rbayardo)
- * Add --helpxml to gflags.py (salcianu)
- * Protect against a hypothetical global d'tor mutex problem (csilvers)
- * BUGFIX: can now define a flag after 'using namespace google' (hamaji)
-
-Tue Apr 14 12:35:25 2009 Google Inc. <opensource@google.com>
-
- * google-gflags: version 1.1
- * Add both foo and nofoo for boolean flags, with --undefok (andychu)
- * Better document how validators work (wojtekm)
- * Improve binary-detection for bash-completion (mtamsky)
- * Python: Add a concept of "key flags", used with --help (salcianu)
- * Python: Robustify flag_values (salcianu)
- * Python: Add a new DEFINE_bool alias (keir, andrewliu)
- * Python: Do module introspection based on module name (dsturtevant)
- * Fix autoconf a bit better, especially on windows and solaris (ajenjo)
- * BUG FIX: gflags_nothreads was linking against the wrong lib (ajenjo)
- * BUG FIX: threads-detection failed on FreeBSD; replace it (ajenjo)
- * PORTABILITY: Quiet an internal compiler error with SUSE 10 (csilvers)
- * PORTABILITY: Update deb.sh for more recenty debuilds (csilvers)
- * PORTABILITY: #include more headers to satify new gcc's (csilvers)
- * INSTALL: Updated to autoconf 2.61 and libtool 1.5.26 (csilvers)
-
-Fri Oct 3 15:16:46 2008 Google Inc. <opensource@google.com>
-
- * google-gflags: version 1.0
- * Add a missing newline to an error string (bcmills)
- * (otherwise exactly the same as gflags 1.0rc2)
-
-Thu Sep 18 12:58:05 2008 Google Inc. <opensource@google.com>
-
- * google-gflags: version 1.0rc2
- * Report current flag values in --helpxml (hdn)
- * Fix compilation troubles with gcc 4.3.3 (simonb)
- * BUG FIX: I was missing a std:: in DECLARE_string (csilvers)
- * BUG FIX: Clarify in docs how to specify --bool flags (csilvers)
- * BUG FIX: Fix --helpshort for source files not in a subdir (csilvers)
- * BUG FIX: Fix python unittest for 64-bit builds (bcmills)
-
-Tue Aug 19 16:15:48 2008
-
- * google-gflags: version 1.0rc1
- * Move #include files from google/ to gflags/ (csilvers)
- * Small optimizations to reduce binary (library) size (jyrki)
- * BUGFIX: forgot a std:: in one of the .h files (csilvers)
- * Speed up locking by making sure calls are inlined (ajenjo)
- * 64-BIT COMPATIBILITY: Use %PRId64 instead of %lld (csilvers)
- * PORTABILITY: fix Makefile to work with Cygwin (ajenjo)
- * PORTABILITY: fix code to compile under Visual Studio (ajenjo)
- * PORTABILITY: fix code to compile under Solaris 10 with CC (csilvers)
-
-Mon Jul 21 23:01:38 2008 Google Inc. <opensource@google.com>
-
- * google-gflags: version 0.9
- * Add the ability to validate a command-line flag (csilvers)
- * Add completion support for commandline flags in bash (daven)
- * Add -W compile flags to Makefile, when using gcc (csilvers)
- * Allow helpstring to be NULL (cristianoc)
- * Improved documentation of classes in the .cc file (csilvers)
- * Fix python bug with AppendFlagValues + shortnames (jjtswan)
- * Use bool instead of int for boolean flags in gflags.py (bcmills)
- * Simplify the way we declare flags, now more foolproof (csilvers)
- * Better error messages when bool flags collide (colohan)
- * Only evaluate DEFINE_foo macro args once (csilvers)
-
-Wed Mar 26 15:20:18 2008 Google Inc. <opensource@google.com>
-
- * google-gflags: version 0.8
- * Export DescribeOneFlag() in the API
- * Add support for automatic line wrapping at 80 cols for gflags.py
- * Bugfix: do not treat an isolated "-" the same as an isolated "--"
- * Update rpm spec to point to Google Code rather than sourceforge (!)
- * Improve documentation (including documenting thread-safety)
- * Improve #include hygiene
- * Improve testing
-
-Thu Oct 18 11:33:20 2007 Google Inc. <opensource@google.com>
-
- * google-gflags: version 0.7
- * Deal even more correctly with libpthread not linked in (csilvers)
- * Add STRIP_LOG, an improved DO_NOT_SHOW_COMMANDLINE_HELP (sioffe)
- * Be more accurate printing default flag values in --help (dsturtevant)
- * Reduce .o file size a bit by using shorter namespace names (jeff)
- * Use relative install path, so 'setup.py --home' works (csilvers)
- * Notice when a boolean flag has a non-boolean default (bnmouli)
- * Broaden --helpshort to match foo-main.cc and foo_main.cc (hendrie)
- * Fix "no modules match" message for --helpshort, etc (hendrie)
-
-Wed Aug 15 07:35:51 2007 Google Inc. <opensource@google.com>
-
- * google-gflags: version 0.6
- * Deal correctly with case that libpthread is not linked in (csilvers)
- * Update Makefile/tests so we pass "make distcheck" (csilvers)
- * Document and test that last assignment to a flag wins (wan)
-
-Tue Jun 12 15:23:42 2007 Google Inc. <opensource@google.com>
-
- * google-gflags: version 0.5
- * Include all m4 macros in the distribution (csilvers)
- * Python: Fix broken data_files field in setup.py (sidlon)
- * Python: better string serliaizing and unparsing (abo, csimmons)
- * Fix checks for NaN and inf to work with Mac OS X (csilvers)
-
-Thu Apr 19 15:15:07 2007 Google Inc. <opensource@google.com>
-
- * google-gflags: version 0.4
- * Remove is_default from GetCommandLineFlagInfo (csilvers)
- * Portability fixes: includes, strtoll, gcc4.3 errors (csilvers)
- * A few doc typo cleanups (csilvers)
-
-Wed Mar 28 12:15:56 2007 Google Inc. <opensource@google.com>
-
- * google-gflags: version 0.3
- * python portability fix: use popen instead of subprocess (csilvers)
- * Add is_default to CommandLineFlagInfo (pchien)
- * Make docs a bit prettier (csilvers)
- * Actually include the python files in the distribution! :-/ (csilvers)
-
-Mon Jan 22 15:33:06 2007 Google Inc. <opensource@google.com>
-
- * google-gflags: version 0.2
- * added support for python commandlineflags, as well as c++
- * gflags2man, a script to turn flags into a man page (dchristian)
-
-Wed Dec 13 12:37:19 2006 Google Inc. <opensource@google.com>
-
- * google-gflags: initial release:
- The gflags package contains a library that implements commandline
- flags processing. As such it's a replacement for getopt(). It
- has increased flexibility, including built-in support for C++
- types like string, and the ability to define flags in the source
- file in which they're used.
diff --git a/extern/libmv/third_party/gflags/ChangeLog.txt b/extern/libmv/third_party/gflags/ChangeLog.txt
new file mode 100644
index 00000000000..e14d88e35f2
--- /dev/null
+++ b/extern/libmv/third_party/gflags/ChangeLog.txt
@@ -0,0 +1,208 @@
+* Sun Mar 20 2014 - Andreas Schuh <google-gflags@googlegroups.com>
+
+- gflags: version 2.1.1
+- Fixed issue 77: GFLAGS_IS_A_DLL expands to empty string in gflags_declare.h
+- Fixed issue 79: GFLAGS_NAMESPACE not expanded to actual namespace in gflags_declare.h
+- Fixed issue 80: Allow include path to differ from GFLAGS_NAMESPACE
+
+* Thu Mar 20 2014 - Andreas Schuh <google-gflags@googlegroups.com>
+
+- gflags: version 2.1.0
+- Build system configuration using CMake instead of autotools
+- CPack packaging support for Debian/Ubuntu, Red Hat, and Mac OS X
+- Fixed issue 54: Fix "invalid suffix on literal" (C++11)
+- Fixed issue 57: Use _strdup instead of strdup on Windows
+- Fixed issue 62: Change all preprocessor include guards to start with GFLAGS_
+- Fixed issue 64: Add DEFINE_validator macro
+- Fixed issue 73: Warnings in Visual Studio 2010 and unable to compile unit test
+
+* Wed Jan 25 2012 - Google Inc. <google-gflags@googlegroups.com>
+
+- gflags: version 2.0
+- Changed the 'official' gflags email in setup.py/etc
+- Renamed google-gflags.sln to gflags.sln
+- Changed copyright text to reflect Google's relinquished ownership
+
+* Tue Dec 20 2011 - Google Inc. <opensource@google.com>
+
+- google-gflags: version 1.7
+- Add CommandLineFlagInfo::flag_ptr pointing to current storage (musji)
+- PORTING: flush after writing to stderr, needed on cygwin
+- PORTING: Clean up the GFLAGS_DLL_DECL stuff better
+- Fix a bug in StringPrintf() that affected large strings (csilvers)
+- Die at configure-time when g++ isn't installed
+
+* Fri Jul 29 2011 - Google Inc. <opensource@google.com>
+
+- google-gflags: version 1.6
+- BUGFIX: Fix a bug where we were leaving out a required $(top_srcdir)
+- Fix definition of clstring (jyrki)
+- Split up flag declares into its own file (jyrki)
+- Add --version support (csilvers)
+- Update the README for gflags with static libs
+- Update acx_pthread.m4 for nostdlib
+- Change ReparseCommandLineFlags to return void (csilvers)
+- Some doc typofixes and example augmentation (various)
+
+* Mon Jan 24 2011 - Google Inc. <opensource@google.com>
+
+- google-gflags: version 1.5
+- Better reporting of current vs default value (handler)
+- Add API for cleaning up of memory at program-exit (jmarantz)
+- Fix macros to work inside namespaces (csilvers)
+- Use our own string typedef in case string is redefined (csilvers)
+- Updated to autoconf 2.65
+
+* Wed Oct 13 2010 - Google Inc. <opensource@google.com>
+
+- google-gflags: version 1.4
+- Add a check to prevent passing 0 to DEFINE_string (jorg)
+- Reduce compile (.o) size (jyrki)
+- Some small changes to quiet debug compiles (alexk)
+- PORTING: better support static linking on windows (csilvers)
+- DOCUMENTATION: change default values, use validators, etc.
+- Update the NEWS file to be non-empty
+- Add pkg-config (.pc) files for libgflags and libgflags_nothreads
+
+* Mon Jan 4 2010 - Google Inc. <opensource@google.com>
+
+- google-gflags: version 1.3
+- PORTABILITY: can now build and run tests under MSVC (csilvers)
+- Remove the python gflags code, which is now its own package (tansell)
+- Clarify that "last flag wins" in the docs (csilvers)
+- Comment danger of using GetAllFlags in validators (wojtekm)
+- PORTABILITY: Some fixes necessary for c++0x (mboerger)
+- Makefile fix: $(srcdir) -> $(top_srcdir) in one place (csilvres)
+- INSTALL: autotools to autoconf v2.64 + automake v1.11 (csilvers)
+
+* Thu Sep 10 2009 - Google Inc. <opensource@google.com>
+
+- google-gflags: version 1.2
+- PORTABILITY: can now build and run tests under mingw (csilvers)
+- Using a string arg for a bool flag is a compile-time error (rbayardo)
+- Add --helpxml to gflags.py (salcianu)
+- Protect against a hypothetical global d'tor mutex problem (csilvers)
+- BUGFIX: can now define a flag after 'using namespace google' (hamaji)
+
+* Tue Apr 14 2009 - Google Inc. <opensource@google.com>
+
+- google-gflags: version 1.1
+- Add both foo and nofoo for boolean flags, with --undefok (andychu)
+- Better document how validators work (wojtekm)
+- Improve binary-detection for bash-completion (mtamsky)
+- Python: Add a concept of "key flags", used with --help (salcianu)
+- Python: Robustify flag_values (salcianu)
+- Python: Add a new DEFINE_bool alias (keir, andrewliu)
+- Python: Do module introspection based on module name (dsturtevant)
+- Fix autoconf a bit better, especially on windows and solaris (ajenjo)
+- BUG FIX: gflags_nothreads was linking against the wrong lib (ajenjo)
+- BUG FIX: threads-detection failed on FreeBSD; replace it (ajenjo)
+- PORTABILITY: Quiet an internal compiler error with SUSE 10 (csilvers)
+- PORTABILITY: Update deb.sh for more recenty debuilds (csilvers)
+- PORTABILITY: #include more headers to satify new gcc's (csilvers)
+- INSTALL: Updated to autoconf 2.61 and libtool 1.5.26 (csilvers)
+
+* Fri Oct 3 2008 - Google Inc. <opensource@google.com>
+
+- google-gflags: version 1.0
+- Add a missing newline to an error string (bcmills)
+- (otherwise exactly the same as gflags 1.0rc2)
+
+* Thu Sep 18 2008 - Google Inc. <opensource@google.com>
+
+- google-gflags: version 1.0rc2
+- Report current flag values in --helpxml (hdn)
+- Fix compilation troubles with gcc 4.3.3 (simonb)
+- BUG FIX: I was missing a std:: in DECLARE_string (csilvers)
+- BUG FIX: Clarify in docs how to specify --bool flags (csilvers)
+- BUG FIX: Fix --helpshort for source files not in a subdir (csilvers)
+- BUG FIX: Fix python unittest for 64-bit builds (bcmills)
+
+* Tue Aug 19 2008 - Google Inc. <opensource@google.com>
+
+- google-gflags: version 1.0rc1
+- Move #include files from google/ to gflags/ (csilvers)
+- Small optimizations to reduce binary (library) size (jyrki)
+- BUGFIX: forgot a std:: in one of the .h files (csilvers)
+- Speed up locking by making sure calls are inlined (ajenjo)
+- 64-BIT COMPATIBILITY: Use %PRId64 instead of %lld (csilvers)
+- PORTABILITY: fix Makefile to work with Cygwin (ajenjo)
+- PORTABILITY: fix code to compile under Visual Studio (ajenjo)
+- PORTABILITY: fix code to compile under Solaris 10 with CC (csilvers)
+
+* Mon Jul 21 2008 - Google Inc. <opensource@google.com>
+
+- google-gflags: version 0.9
+- Add the ability to validate a command-line flag (csilvers)
+- Add completion support for commandline flags in bash (daven)
+- Add -W compile flags to Makefile, when using gcc (csilvers)
+- Allow helpstring to be NULL (cristianoc)
+- Improved documentation of classes in the .cc file (csilvers)
+- Fix python bug with AppendFlagValues + shortnames (jjtswan)
+- Use bool instead of int for boolean flags in gflags.py (bcmills)
+- Simplify the way we declare flags, now more foolproof (csilvers)
+- Better error messages when bool flags collide (colohan)
+- Only evaluate DEFINE_foo macro args once (csilvers)
+
+* Wed Mar 26 2008 - Google Inc. <opensource@google.com>
+
+- google-gflags: version 0.8
+- Export DescribeOneFlag() in the API
+- Add support for automatic line wrapping at 80 cols for gflags.py
+- Bugfix: do not treat an isolated "-" the same as an isolated "--"
+- Update rpm spec to point to Google Code rather than sourceforge (!)
+- Improve documentation (including documenting thread-safety)
+- Improve #include hygiene
+- Improve testing
+
+* Thu Oct 18 2007 - Google Inc. <opensource@google.com>
+
+- google-gflags: version 0.7
+- Deal even more correctly with libpthread not linked in (csilvers)
+- Add STRIP_LOG, an improved DO_NOT_SHOW_COMMANDLINE_HELP (sioffe)
+- Be more accurate printing default flag values in --help (dsturtevant)
+- Reduce .o file size a bit by using shorter namespace names (jeff)
+- Use relative install path, so 'setup.py --home' works (csilvers)
+- Notice when a boolean flag has a non-boolean default (bnmouli)
+- Broaden --helpshort to match foo-main.cc and foo_main.cc (hendrie)
+- Fix "no modules match" message for --helpshort, etc (hendrie)
+
+* Wed Aug 15 2007 - Google Inc. <opensource@google.com>
+
+- google-gflags: version 0.6
+- Deal correctly with case that libpthread is not linked in (csilvers)
+- Update Makefile/tests so we pass "make distcheck" (csilvers)
+- Document and test that last assignment to a flag wins (wan)
+
+* Tue Jun 12 2007 - Google Inc. <opensource@google.com>
+
+- google-gflags: version 0.5
+- Include all m4 macros in the distribution (csilvers)
+- Python: Fix broken data_files field in setup.py (sidlon)
+- Python: better string serliaizing and unparsing (abo, csimmons)
+- Fix checks for NaN and inf to work with Mac OS X (csilvers)
+
+* Thu Apr 19 2007 - Google Inc. <opensource@google.com>
+
+- google-gflags: version 0.4
+- Remove is_default from GetCommandLineFlagInfo (csilvers)
+- Portability fixes: includes, strtoll, gcc4.3 errors (csilvers)
+- A few doc typo cleanups (csilvers)
+
+* Wed Mar 28 2007 - Google Inc. <opensource@google.com>
+
+- google-gflags: version 0.3
+- python portability fix: use popen instead of subprocess (csilvers)
+- Add is_default to CommandLineFlagInfo (pchien)
+- Make docs a bit prettier (csilvers)
+- Actually include the python files in the distribution! :-/ (csilvers)
+
+* Mon Jan 22 2007 - Google Inc. <opensource@google.com>
+
+- google-gflags: version 0.2
+- added support for python commandlineflags, as well as c++
+- gflags2man, a script to turn flags into a man page (dchristian)
+
+* Wed Dec 13 2006 - Google Inc. <opensource@google.com>
+
+- google-gflags: version 0.1
diff --git a/extern/libmv/third_party/gflags/NEWS b/extern/libmv/third_party/gflags/NEWS.txt
index ffc0127d91e..74186071129 100644
--- a/extern/libmv/third_party/gflags/NEWS
+++ b/extern/libmv/third_party/gflags/NEWS.txt
@@ -1,4 +1,86 @@
-== 25 January 2012 ==
+=== 30 March 2014 ===
+
+I've just released gflags 2.1.1.
+
+This release fixes a few bugs in the configuration of gflags_declare.h
+and adds a separate GFLAGS_INCLUDE_DIR CMake variable to the build configuration.
+Setting GFLAGS_NAMESPACE to "google" no longer changes also the include
+path of the public header files. This allows the use of the library with
+other Google projects such as glog which still use the deprecated "google"
+namespace for the gflags library, but include it as "gflags/gflags.h".
+
+=== 20 March 2014 ===
+
+I've just released gflags 2.1.
+
+The major changes are the use of CMake for the build configuration instead
+of the autotools and packaging support through CPack. The default namespace
+of all C++ symbols is now "gflags" instead of "google". This can be
+configured via the GFLAGS_NAMESPACE variable.
+
+This release compiles with all major compilers without warnings and passed
+the unit tests on Ubuntu 12.04, Windows 7 (Visual Studio 2008 and 2010,
+Cygwin, MinGW), and Mac OS X (Xcode 5.1).
+
+The SVN repository on Google Code is now frozen and replaced by a Git
+repository such that it can be used as Git submodule by projects. The main
+hosting of this project remains at Google Code. Thanks to the distributed
+character of Git, I can push (and pull) changes from both GitHub and Google Code
+in order to keep the two public repositories in sync.
+When fixing an issue for a pull request through either of these hosting
+platforms, please reference the issue number as
+[https://code.google.com/p/support/wiki/IssueTracker#Integration_with_version_control described here].
+For the further development, I am following the
+[http://nvie.com/posts/a-successful-git-branching-model/ Git branching model]
+with feature branch names prefixed by "feature/" and bugfix branch names
+prefixed by "bugfix/", respectively.
+
+Binary and source [https://github.com/schuhschuh/gflags/releases packages] are available on GitHub.
+
+
+=== 14 January 2013 ===
+
+The migration of the build system to CMake is almost complete.
+What remains to be done is rewriting the tests in Python such they can be
+executed on non-Unix platforms and splitting them up into separate CTest tests.
+Though merging these changes into the master branch yet remains to be done,
+it is recommended to already start using the
+[https://github.com/schuhschuh/gflags/tree/cmake-migration cmake-migration] branch.
+
+
+=== 20 April 2013 ===
+
+More than a year has past since I (Andreas) took over the maintenance for
+`gflags`. Only few minor changes have been made since then, much to my regret.
+To get more involved and stimulate participation in the further
+development of the library, I moved the project source code today to
+[https://github.com/schuhschuh/gflags GitHub].
+I believe that the strengths of [http://git-scm.com/ Git] will allow for better community collaboration
+as well as ease the integration of changes made by others. I encourage everyone
+who would like to contribute to send me pull requests.
+Git's lightweight feature branches will also provide the right tool for more
+radical changes which should only be merged back into the master branch
+after these are complete and implement the desired behavior.
+
+The SVN repository remains accessible at Google Code and I will keep the
+master branch of the Git repository hosted at GitHub and the trunk of the
+Subversion repository synchronized. Initially, I was going to simply switch the
+Google Code project to Git, but in this case the SVN repository would be
+frozen and force everyone who would like the latest development changes to
+use Git as well. Therefore I decided to host the public Git repository at GitHub
+instead.
+
+Please continue to report any issues with gflags on Google Code. The GitHub project will
+only be used to host the Git repository.
+
+One major change of the project structure I have in mind for the next weeks
+is the migration from autotools to [http://www.cmake.org/ CMake].
+Check out the (unstable!)
+[https://github.com/schuhschuh/gflags/tree/cmake-migration cmake-migration]
+branch on GitHub for details.
+
+
+=== 25 January 2012 ===
I've just released gflags 2.0.
@@ -128,7 +210,7 @@ If you've tried to install a .rpm or .deb and it doesn't work for you,
let me know. I'm excited to finally have 64-bit package files, but
there may still be some wrinkles in the new system to iron out.
-===1 October 2008===
+=== 1 October 2008 ===
gflags 1.0rc2 was out for a few weeks without any issues, so gflags
1.0 is now released. This is much like gflags 0.9. The major change
diff --git a/extern/libmv/third_party/gflags/README.libmv b/extern/libmv/third_party/gflags/README.libmv
index b310c57ac34..f4310b39bbb 100644
--- a/extern/libmv/third_party/gflags/README.libmv
+++ b/extern/libmv/third_party/gflags/README.libmv
@@ -1,16 +1,18 @@
Project: Google Flags
URL: http://code.google.com/p/google-gflags/
License: New BSD
-Upstream version: 2.0
+Upstream version: 2.1.1
Local modifications:
-- Flattened the tree and only included files needed for libmv. This involved
- changing some of the includes to point to the current directory instead of a
- nested gflags directory.
+- Flattened the tree and only included files needed for libmv.
-- Added a poor-man's version of upstream's port.cc/h to make gflags compile on
- windows. This isn't sufficient but is a stopgap for now.
+- config.h was originally generated on linux machine with some
+ further tweaks:
-- Added -fPIC flag, so shared libraries from Ceres could be linked against static glog
+ * OS_WINDOWS need to be conditinally defined from inside #ifdef WIN32
+ * Same applies yo HAVE_SHLWAPI_H
+ * Disabeld HAVE_FNMATCH_H
+
+- Removed attribute(unused) from FlagSaver.
TODO(keir): Import and use gflags for Windows from upstream.
diff --git a/extern/libmv/third_party/gflags/config.h b/extern/libmv/third_party/gflags/config.h
index 03ed03ca99b..858510835c1 100644
--- a/extern/libmv/third_party/gflags/config.h
+++ b/extern/libmv/third_party/gflags/config.h
@@ -1,101 +1,117 @@
-/* src/config.h. Generated from config.h.in by configure. */
-/* src/config.h.in. Generated from configure.ac by autoheader. */
+/* Generated from config.h.in during build configuration using CMake. */
-/* Always the empty-string on non-windows systems. On windows, should be
- "__declspec(dllexport)". This way, when we compile the dll, we export our
- functions/classes. It's safe to define this here because config.h is only
- used internally, to compile the DLL, and every DLL source file #includes
- "config.h" before anything else. */
-#define GFLAGS_DLL_DECL /**/
+// Note: This header file is only used internally. It is not part of public interface!
-/* Namespace for Google classes */
-#define GOOGLE_NAMESPACE ::google
+// ---------------------------------------------------------------------------
+// System checks
-/* Define to 1 if you have the <dlfcn.h> header file. */
-#define HAVE_DLFCN_H 1
+// Define if you build this library for a MS Windows OS.
+#ifdef WIN32
+# define OS_WINDOWS
+#endif
-/* Define to 1 if you have the <fnmatch.h> header file. */
-/* #ubdef HAVE_FNMATCH_H 1 */
+// Define if you have the <stdint.h> header file.
+#define HAVE_STDINT_H
-/* Define to 1 if you have the <inttypes.h> header file. */
-#define HAVE_INTTYPES_H 1
+// Define if you have the <sys/types.h> header file.
+#define HAVE_SYS_TYPES_H
-/* Define to 1 if you have the <memory.h> header file. */
-#define HAVE_MEMORY_H 1
+// Define if you have the <inttypes.h> header file.
+#define HAVE_INTTYPES_H
-/* define if the compiler implements namespaces */
-#define HAVE_NAMESPACES 1
+// Define if you have the <sys/stat.h> header file.
+#define HAVE_SYS_STAT_H
-/* Define if you have POSIX threads libraries and header files. */
-#define HAVE_PTHREAD 1
+// Define if you have the <unistd.h> header file.
+#define HAVE_UNISTD_H
-/* Define to 1 if you have the <stdint.h> header file. */
-#define HAVE_STDINT_H 1
+// Define if you have the <fnmatch.h> header file.
+/* #undef HAVE_FNMATCH_H */
-/* Define to 1 if you have the <stdlib.h> header file. */
-#define HAVE_STDLIB_H 1
+// Define if you have the <shlwapi.h> header file (Windows 2000/XP).
+#undef HAVE_SHLWAPI_H
-/* Define to 1 if you have the <strings.h> header file. */
-#define HAVE_STRINGS_H 1
+// Define if you have the strtoll function.
+#define HAVE_STRTOLL
-/* Define to 1 if you have the <string.h> header file. */
-#define HAVE_STRING_H 1
+// Define if you have the strtoq function.
+/* #undef HAVE_STRTOQ */
-/* Define to 1 if you have the `strtoll' function. */
-#define HAVE_STRTOLL 1
+// Define if you have the <pthread.h> header file.
+#define HAVE_PTHREAD
-/* Define to 1 if you have the `strtoq' function. */
-#define HAVE_STRTOQ 1
+// Define if your pthread library defines the type pthread_rwlock_t
+#define HAVE_RWLOCK
-/* Define to 1 if you have the <sys/stat.h> header file. */
-#define HAVE_SYS_STAT_H 1
+// gcc requires this to get PRId64, etc.
+#if defined(HAVE_INTTYPES_H) && !defined(__STDC_FORMAT_MACROS)
+# define __STDC_FORMAT_MACROS 1
+#endif
-/* Define to 1 if you have the <sys/types.h> header file. */
-#define HAVE_SYS_TYPES_H 1
+// ---------------------------------------------------------------------------
+// Package information
-/* Define to 1 if you have the <unistd.h> header file. */
-#define HAVE_UNISTD_H 1
+// Name of package.
+#define PACKAGE gflags
-/* define if your compiler has __attribute__ */
-#define HAVE___ATTRIBUTE__ 1
+// Define to the full name of this package.
+#define PACKAGE_NAME gflags
-/* Define to the sub-directory in which libtool stores uninstalled libraries.
- */
-#define LT_OBJDIR ".libs/"
+// Define to the full name and version of this package.
+#define PACKAGE_STRING gflags 2.1.1
-/* Name of package */
-#define PACKAGE "gflags"
+// Define to the one symbol short name of this package.
+#define PACKAGE_TARNAME gflags-2.1.1
-/* Define to the address where bug reports for this package should be sent. */
-#define PACKAGE_BUGREPORT "google-gflags@googlegroups.com"
+// Define to the version of this package.
+#define PACKAGE_VERSION 2.1.1
-/* Define to the full name of this package. */
-#define PACKAGE_NAME "gflags"
+// Version number of package.
+#define VERSION PACKAGE_VERSION
-/* Define to the full name and version of this package. */
-#define PACKAGE_STRING "gflags 2.0"
+// Define to the address where bug reports for this package should be sent.
+#define PACKAGE_BUGREPORT https://code.google.com/p/gflags/issues/
-/* Define to the one symbol short name of this package. */
-#define PACKAGE_TARNAME "gflags"
+// Namespace of gflags library symbols.
+#define GFLAGS_NAMESPACE gflags
-/* Define to the version of this package. */
-#define PACKAGE_VERSION "2.0"
+// ---------------------------------------------------------------------------
+// Path separator
+#ifndef PATH_SEPARATOR
+# ifdef OS_WINDOWS
+# define PATH_SEPARATOR '\\'
+# else
+# define PATH_SEPARATOR '/'
+# endif
+#endif
-/* Define to necessary symbol if this constant uses a non-standard name on
- your system. */
-/* #undef PTHREAD_CREATE_JOINABLE */
+// ---------------------------------------------------------------------------
+// Windows
-/* Define to 1 if you have the ANSI C header files. */
-#define STDC_HEADERS 1
+// Whether gflags library is a DLL.
+#ifndef GFLAGS_IS_A_DLL
+# define GFLAGS_IS_A_DLL 0
+#endif
-/* the namespace where STL code like vector<> is defined */
-#define STL_NAMESPACE std
-
-/* Version number of package */
-#define VERSION "2.0"
-
-/* Stops putting the code inside the Google namespace */
-#define _END_GOOGLE_NAMESPACE_ }
-
-/* Puts following code inside the Google namespace */
-#define _START_GOOGLE_NAMESPACE_ namespace google {
+// Always export symbols when compiling a shared library as this file is only
+// included by internal modules when building the gflags library itself.
+// The gflags_declare.h header file will set it to import these symbols otherwise.
+#ifndef GFLAGS_DLL_DECL
+# if GFLAGS_IS_A_DLL && defined(_MSC_VER)
+# define GFLAGS_DLL_DECL __declspec(dllexport)
+# else
+# define GFLAGS_DLL_DECL
+# endif
+#endif
+// Flags defined by the gflags library itself must be exported
+#ifndef GFLAGS_DLL_DEFINE_FLAG
+# define GFLAGS_DLL_DEFINE_FLAG GFLAGS_DLL_DECL
+#endif
+
+#ifdef OS_WINDOWS
+// The unittests import the symbols of the shared gflags library
+# if GFLAGS_IS_A_DLL && defined(_MSC_VER)
+# define GFLAGS_DLL_DECL_FOR_UNITTESTS __declspec(dllimport)
+# endif
+# include "windows_port.h"
+#endif
diff --git a/extern/libmv/third_party/gflags/gflags.cc b/extern/libmv/third_party/gflags/gflags.cc
index 4ba2b6f393c..285050fe9ec 100644
--- a/extern/libmv/third_party/gflags/gflags.cc
+++ b/extern/libmv/third_party/gflags/gflags.cc
@@ -87,18 +87,16 @@
// other hand, hooks into CommandLineFlagParser. Other API functions
// are, similarly, mostly hooks into the functionality described above.
-// This comes first to ensure we define __STDC_FORMAT_MACROS in time.
#include "config.h"
-#if defined(HAVE_INTTYPES_H) && !defined(__STDC_FORMAT_MACROS)
-# define __STDC_FORMAT_MACROS 1 // gcc requires this to get PRId64, etc.
-#endif
+#include "gflags.h"
-#include "gflags/gflags.h"
#include <assert.h>
#include <ctype.h>
#include <errno.h>
-#ifdef HAVE_FNMATCH_H
-# include <fnmatch.h>
+#if defined(HAVE_FNMATCH_H)
+# include <fnmatch.h>
+#elif defined(HAVE_SHLWAPI_H)
+# include <shlwapi.h>
#endif
#include <stdarg.h> // For va_list and related operations
#include <stdio.h>
@@ -109,31 +107,23 @@
#include <string>
#include <utility> // for pair<>
#include <vector>
+
#include "mutex.h"
#include "util.h"
-#ifndef PATH_SEPARATOR
-#define PATH_SEPARATOR '/'
-#endif
-
-
// Special flags, type 1: the 'recursive' flags. They set another flag's val.
-DEFINE_string(flagfile, "",
- "load flags from file");
-DEFINE_string(fromenv, "",
- "set flags from the environment"
- " [use 'export FLAGS_flag1=value']");
-DEFINE_string(tryfromenv, "",
- "set flags from the environment if present");
+DEFINE_string(flagfile, "", "load flags from file");
+DEFINE_string(fromenv, "", "set flags from the environment"
+ " [use 'export FLAGS_flag1=value']");
+DEFINE_string(tryfromenv, "", "set flags from the environment if present");
// Special flags, type 2: the 'parsing' flags. They modify how we parse.
-DEFINE_string(undefok, "",
- "comma-separated list of flag names that it is okay to specify "
- "on the command line even if the program does not define a flag "
- "with that name. IMPORTANT: flags in this list that have "
- "arguments MUST use the flag=value format");
+DEFINE_string(undefok, "", "comma-separated list of flag names that it is okay to specify "
+ "on the command line even if the program does not define a flag "
+ "with that name. IMPORTANT: flags in this list that have "
+ "arguments MUST use the flag=value format");
-_START_GOOGLE_NAMESPACE_
+namespace GFLAGS_NAMESPACE {
using std::map;
using std::pair;
@@ -206,7 +196,7 @@ class FlagValue {
private:
friend class CommandLineFlag; // for many things, including Validate()
- friend class GOOGLE_NAMESPACE::FlagSaverImpl; // calls New()
+ friend class GFLAGS_NAMESPACE::FlagSaverImpl; // calls New()
friend class FlagRegistry; // checks value_buffer_ for flags_by_ptr_ map
template <typename T> friend T GetFromEnv(const char*, const char*, T);
friend bool TryParseLocked(const CommandLineFlag*, FlagValue*,
@@ -348,13 +338,13 @@ string FlagValue::ToString() const {
case FV_BOOL:
return VALUE_AS(bool) ? "true" : "false";
case FV_INT32:
- snprintf(intbuf, sizeof(intbuf), "%"PRId32, VALUE_AS(int32));
+ snprintf(intbuf, sizeof(intbuf), "%" PRId32, VALUE_AS(int32));
return intbuf;
case FV_INT64:
- snprintf(intbuf, sizeof(intbuf), "%"PRId64, VALUE_AS(int64));
+ snprintf(intbuf, sizeof(intbuf), "%" PRId64, VALUE_AS(int64));
return intbuf;
case FV_UINT64:
- snprintf(intbuf, sizeof(intbuf), "%"PRIu64, VALUE_AS(uint64));
+ snprintf(intbuf, sizeof(intbuf), "%" PRIu64, VALUE_AS(uint64));
return intbuf;
case FV_DOUBLE:
snprintf(intbuf, sizeof(intbuf), "%.17g", VALUE_AS(double));
@@ -406,8 +396,7 @@ const char* FlagValue::TypeName() const {
assert(false);
return "";
}
- // Directly indexing the strigns in the 'types' string, each of them
- // is 7 bytes long.
+ // Directly indexing the strings in the 'types' string, each of them is 7 bytes long.
return &types[type_ * 7];
}
@@ -504,7 +493,7 @@ class CommandLineFlag {
private:
// for SetFlagLocked() and setting flags_by_ptr_
friend class FlagRegistry;
- friend class GOOGLE_NAMESPACE::FlagSaverImpl; // for cloning the values
+ friend class GFLAGS_NAMESPACE::FlagSaverImpl; // for cloning the values
// set validate_fn
friend bool AddFlagValidator(const void*, ValidateFnProto);
@@ -671,9 +660,9 @@ class FlagRegistry {
static FlagRegistry* GlobalRegistry(); // returns a singleton registry
private:
- friend class GOOGLE_NAMESPACE::FlagSaverImpl; // reads all the flags in order to copy them
+ friend class GFLAGS_NAMESPACE::FlagSaverImpl; // reads all the flags in order to copy them
friend class CommandLineFlagParser; // for ValidateAllFlags
- friend void GOOGLE_NAMESPACE::GetAllFlags(vector<CommandLineFlagInfo>*);
+ friend void GFLAGS_NAMESPACE::GetAllFlags(vector<CommandLineFlagInfo>*);
// The map from name to flag, for FindFlagLocked().
typedef map<const char*, CommandLineFlag*, StringCmp> FlagMap;
@@ -1003,8 +992,8 @@ static string ReadFileIntoString(const char* filename) {
const int kBufSize = 8092;
char buffer[kBufSize];
string s;
- FILE* fp = fopen(filename, "r");
- if (!fp) PFATAL(filename);
+ FILE* fp;
+ if ((errno = SafeFOpen(&fp, filename, "r")) != 0) PFATAL(filename);
size_t n;
while ( (n=fread(buffer, 1, kBufSize, fp)) > 0 ) {
if (ferror(fp)) PFATAL(filename);
@@ -1148,8 +1137,8 @@ string CommandLineFlagParser::ProcessFromenvLocked(const string& flagval,
}
const string envname = string("FLAGS_") + string(flagname);
- const char* envval = getenv(envname.c_str());
- if (!envval) {
+ string envval;
+ if (!SafeGetEnv(envname.c_str(), envval)) {
if (errors_are_fatal) {
error_flags_[flagname] = (string(kError) + envname +
" not found in environment\n");
@@ -1158,15 +1147,14 @@ string CommandLineFlagParser::ProcessFromenvLocked(const string& flagval,
}
// Avoid infinite recursion.
- if ((strcmp(envval, "fromenv") == 0) ||
- (strcmp(envval, "tryfromenv") == 0)) {
+ if (envval == "fromenv" || envval == "tryfromenv") {
error_flags_[flagname] =
StringPrintf("%sinfinite recursion on environment flag '%s'\n",
- kError, envval);
+ kError, envval.c_str());
continue;
}
- msg += ProcessSingleOptionLocked(flag, envval, set_mode);
+ msg += ProcessSingleOptionLocked(flag, envval.c_str(), set_mode);
}
return msg;
}
@@ -1318,13 +1306,12 @@ string CommandLineFlagParser::ProcessOptionsFromStringLocked(
// We try matching both against the full argv0 and basename(argv0)
if (glob == ProgramInvocationName() // small optimization
|| glob == ProgramInvocationShortName()
-#ifdef HAVE_FNMATCH_H
- || fnmatch(glob.c_str(),
- ProgramInvocationName(),
- FNM_PATHNAME) == 0
- || fnmatch(glob.c_str(),
- ProgramInvocationShortName(),
- FNM_PATHNAME) == 0
+#if defined(HAVE_FNMATCH_H)
+ || fnmatch(glob.c_str(), ProgramInvocationName(), FNM_PATHNAME) == 0
+ || fnmatch(glob.c_str(), ProgramInvocationShortName(), FNM_PATHNAME) == 0
+#elif defined(HAVE_SHLWAPI_H)
+ || PathMatchSpec(glob.c_str(), ProgramInvocationName())
+ || PathMatchSpec(glob.c_str(), ProgramInvocationShortName())
#endif
) {
flags_are_relevant = true;
@@ -1346,14 +1333,15 @@ string CommandLineFlagParser::ProcessOptionsFromStringLocked(
template<typename T>
T GetFromEnv(const char *varname, const char* type, T dflt) {
- const char* const valstr = getenv(varname);
- if (!valstr)
- return dflt;
- FlagValue ifv(new T, type, true);
- if (!ifv.ParseFrom(valstr))
- ReportError(DIE, "ERROR: error parsing env variable '%s' with value '%s'\n",
- varname, valstr);
- return OTHER_VALUE_AS(ifv, T);
+ std::string valstr;
+ if (SafeGetEnv(varname, valstr)) {
+ FlagValue ifv(new T, type, true);
+ if (!ifv.ParseFrom(valstr.c_str())) {
+ ReportError(DIE, "ERROR: error parsing env variable '%s' with value '%s'\n",
+ varname, valstr.c_str());
+ }
+ return OTHER_VALUE_AS(ifv, T);
+ } else return dflt;
}
bool AddFlagValidator(const void* flag_ptr, ValidateFnProto validate_fn_proto) {
@@ -1765,8 +1753,8 @@ bool ReadFlagsFromString(const string& flagfilecontents,
// TODO(csilvers): nix prog_name in favor of ProgramInvocationShortName()
bool AppendFlagsIntoFile(const string& filename, const char *prog_name) {
- FILE *fp = fopen(filename.c_str(), "a");
- if (!fp) {
+ FILE *fp;
+ if (SafeFOpen(&fp, filename.c_str(), "a") != 0) {
return false;
}
@@ -1824,10 +1812,18 @@ uint64 Uint64FromEnv(const char *v, uint64 dflt) {
double DoubleFromEnv(const char *v, double dflt) {
return GetFromEnv(v, "double", dflt);
}
+
+#ifdef _MSC_VER
+# pragma warning(push)
+# pragma warning(disable: 4996) // ignore getenv security warning
+#endif
const char *StringFromEnv(const char *varname, const char *dflt) {
const char* const val = getenv(varname);
return val ? val : dflt;
}
+#ifdef _MSC_VER
+# pragma warning(pop)
+#endif
// --------------------------------------------------------------------
@@ -1957,4 +1953,5 @@ void ShutDownCommandLineFlags() {
FlagRegistry::DeleteGlobalRegistry();
}
-_END_GOOGLE_NAMESPACE_
+
+} // namespace GFLAGS_NAMESPACE
diff --git a/extern/libmv/third_party/gflags/gflags/gflags.h b/extern/libmv/third_party/gflags/gflags/gflags.h
index e69812c8c38..797a54cac52 100644
--- a/extern/libmv/third_party/gflags/gflags/gflags.h
+++ b/extern/libmv/third_party/gflags/gflags/gflags.h
@@ -75,21 +75,26 @@
// other thread is writing to the variable or calling non-const
// methods of this class.
-#ifndef BASE_COMMANDLINEFLAGS_H_
-#define BASE_COMMANDLINEFLAGS_H_
+#ifndef GFLAGS_GFLAGS_H_
+#define GFLAGS_GFLAGS_H_
#include <string>
#include <vector>
-#include "gflags_declare.h" // IWYU pragma: export
-namespace google {
-//
-// NOTE: all functions below MUST have an explicit 'extern' before
-// them. Our automated opensourcing tools use this as a signal to do
-// appropriate munging for windows, which needs to add GFLAGS_DLL_DECL.
-//
-#define GFLAGS_DLL_DECL /* rewritten to be non-empty in windows dir */
-#define GFLAGS_DLL_DEFINE_FLAG /* rewritten to be non-empty in windows dir */
+#include "gflags_declare.h" // IWYU pragma: export
+
+
+// We always want to export variables defined in user code
+#ifndef GFLAGS_DLL_DEFINE_FLAG
+# if 0 && defined(_MSC_VER)
+# define GFLAGS_DLL_DEFINE_FLAG __declspec(dllexport)
+# else
+# define GFLAGS_DLL_DEFINE_FLAG
+# endif
+#endif
+
+
+namespace gflags {
// --------------------------------------------------------------------
@@ -121,19 +126,17 @@ namespace google {
// Returns true if successfully registered, false if not (because the
// first argument doesn't point to a command-line flag, or because a
// validator is already registered for this flag).
-extern bool RegisterFlagValidator(const bool* flag,
- bool (*validate_fn)(const char*, bool));
-extern bool RegisterFlagValidator(const int32* flag,
- bool (*validate_fn)(const char*, int32));
-extern bool RegisterFlagValidator(const int64* flag,
- bool (*validate_fn)(const char*, int64));
-extern bool RegisterFlagValidator(const uint64* flag,
- bool (*validate_fn)(const char*, uint64));
-extern bool RegisterFlagValidator(const double* flag,
- bool (*validate_fn)(const char*, double));
-extern bool RegisterFlagValidator(const std::string* flag,
- bool (*validate_fn)(const char*,
- const std::string&));
+extern GFLAGS_DLL_DECL bool RegisterFlagValidator(const bool* flag, bool (*validate_fn)(const char*, bool));
+extern GFLAGS_DLL_DECL bool RegisterFlagValidator(const int32* flag, bool (*validate_fn)(const char*, int32));
+extern GFLAGS_DLL_DECL bool RegisterFlagValidator(const int64* flag, bool (*validate_fn)(const char*, int64));
+extern GFLAGS_DLL_DECL bool RegisterFlagValidator(const uint64* flag, bool (*validate_fn)(const char*, uint64));
+extern GFLAGS_DLL_DECL bool RegisterFlagValidator(const double* flag, bool (*validate_fn)(const char*, double));
+extern GFLAGS_DLL_DECL bool RegisterFlagValidator(const std::string* flag, bool (*validate_fn)(const char*, const std::string&));
+
+// Convenience macro for the registration of a flag validator
+#define DEFINE_validator(name, validator) \
+ static const bool name##_validator_registered = \
+ gflags::RegisterFlagValidator(&FLAGS_##name, validator)
// --------------------------------------------------------------------
@@ -146,19 +149,20 @@ extern bool RegisterFlagValidator(const std::string* flag,
// In addition to accessing flags, you can also access argv[0] (the program
// name) and argv (the entire commandline), which we sock away a copy of.
// These variables are static, so you should only set them once.
-
-struct GFLAGS_DLL_DECL CommandLineFlagInfo {
+//
+// No need to export this data only structure from DLL, avoiding VS warning 4251.
+struct CommandLineFlagInfo {
std::string name; // the name of the flag
std::string type; // the type of the flag: int32, etc
std::string description; // the "help text" associated with the flag
std::string current_value; // the current value, as a string
std::string default_value; // the default value, as a string
std::string filename; // 'cleaned' version of filename holding the flag
- bool has_validator_fn; // true if RegisterFlagValidator called on this flag
- bool is_default; // true if the flag has the default value and
- // has not been set explicitly from the cmdline
- // or via SetCommandLineOption
- const void* flag_ptr; // pointer to the flag's current value (i.e. FLAGS_foo)
+ bool has_validator_fn; // true if RegisterFlagValidator called on this flag
+ bool is_default; // true if the flag has the default value and
+ // has not been set explicitly from the cmdline
+ // or via SetCommandLineOption
+ const void* flag_ptr; // pointer to the flag's current value (i.e. FLAGS_foo)
};
// Using this inside of a validator is a recipe for a deadlock.
@@ -166,34 +170,34 @@ struct GFLAGS_DLL_DECL CommandLineFlagInfo {
// call validators during ParseAllFlags.
// Also make sure then to uncomment the corresponding unit test in
// gflags_unittest.sh
-extern void GetAllFlags(std::vector<CommandLineFlagInfo>* OUTPUT);
+extern GFLAGS_DLL_DECL void GetAllFlags(std::vector<CommandLineFlagInfo>* OUTPUT);
// These two are actually defined in gflags_reporting.cc.
-extern void ShowUsageWithFlags(const char *argv0); // what --help does
-extern void ShowUsageWithFlagsRestrict(const char *argv0, const char *restrict);
+extern GFLAGS_DLL_DECL void ShowUsageWithFlags(const char *argv0); // what --help does
+extern GFLAGS_DLL_DECL void ShowUsageWithFlagsRestrict(const char *argv0, const char *restrict);
// Create a descriptive string for a flag.
// Goes to some trouble to make pretty line breaks.
-extern std::string DescribeOneFlag(const CommandLineFlagInfo& flag);
+extern GFLAGS_DLL_DECL std::string DescribeOneFlag(const CommandLineFlagInfo& flag);
// Thread-hostile; meant to be called before any threads are spawned.
-extern void SetArgv(int argc, const char** argv);
+extern GFLAGS_DLL_DECL void SetArgv(int argc, const char** argv);
// The following functions are thread-safe as long as SetArgv() is
// only called before any threads start.
-extern const std::vector<std::string>& GetArgvs();
-extern const char* GetArgv(); // all of argv as a string
-extern const char* GetArgv0(); // only argv0
-extern uint32 GetArgvSum(); // simple checksum of argv
-extern const char* ProgramInvocationName(); // argv0, or "UNKNOWN" if not set
-extern const char* ProgramInvocationShortName(); // basename(argv0)
+extern GFLAGS_DLL_DECL const std::vector<std::string>& GetArgvs();
+extern GFLAGS_DLL_DECL const char* GetArgv(); // all of argv as a string
+extern GFLAGS_DLL_DECL const char* GetArgv0(); // only argv0
+extern GFLAGS_DLL_DECL uint32 GetArgvSum(); // simple checksum of argv
+extern GFLAGS_DLL_DECL const char* ProgramInvocationName(); // argv0, or "UNKNOWN" if not set
+extern GFLAGS_DLL_DECL const char* ProgramInvocationShortName(); // basename(argv0)
// ProgramUsage() is thread-safe as long as SetUsageMessage() is only
// called before any threads start.
-extern const char* ProgramUsage(); // string set by SetUsageMessage()
+extern GFLAGS_DLL_DECL const char* ProgramUsage(); // string set by SetUsageMessage()
// VersionString() is thread-safe as long as SetVersionString() is only
// called before any threads start.
-extern const char* VersionString(); // string set by SetVersionString()
+extern GFLAGS_DLL_DECL const char* VersionString(); // string set by SetVersionString()
@@ -207,17 +211,16 @@ extern const char* VersionString(); // string set by SetVersionString()
// Return true iff the flagname was found.
// OUTPUT is set to the flag's value, or unchanged if we return false.
-extern bool GetCommandLineOption(const char* name, std::string* OUTPUT);
+extern GFLAGS_DLL_DECL bool GetCommandLineOption(const char* name, std::string* OUTPUT);
// Return true iff the flagname was found. OUTPUT is set to the flag's
// CommandLineFlagInfo or unchanged if we return false.
-extern bool GetCommandLineFlagInfo(const char* name,
- CommandLineFlagInfo* OUTPUT);
+extern GFLAGS_DLL_DECL bool GetCommandLineFlagInfo(const char* name, CommandLineFlagInfo* OUTPUT);
// Return the CommandLineFlagInfo of the flagname. exit() if name not found.
// Example usage, to check if a flag's value is currently the default value:
// if (GetCommandLineFlagInfoOrDie("foo").is_default) ...
-extern CommandLineFlagInfo GetCommandLineFlagInfoOrDie(const char* name);
+extern GFLAGS_DLL_DECL CommandLineFlagInfo GetCommandLineFlagInfoOrDie(const char* name);
enum GFLAGS_DLL_DECL FlagSettingMode {
// update the flag's value (can call this multiple times).
@@ -239,9 +242,8 @@ enum GFLAGS_DLL_DECL FlagSettingMode {
// non-empty else.
// SetCommandLineOption uses set_mode == SET_FLAGS_VALUE (the common case)
-extern std::string SetCommandLineOption(const char* name, const char* value);
-extern std::string SetCommandLineOptionWithMode(const char* name, const char* value,
- FlagSettingMode set_mode);
+extern GFLAGS_DLL_DECL std::string SetCommandLineOption (const char* name, const char* value);
+extern GFLAGS_DLL_DECL std::string SetCommandLineOptionWithMode(const char* name, const char* value, FlagSettingMode set_mode);
// --------------------------------------------------------------------
@@ -262,8 +264,8 @@ extern std::string SetCommandLineOptionWithMode(const char* name, const char* va
// // without worrying about restoring the FLAG values.
// }
//
-// Note: This class is marked with ATTRIBUTE_UNUSED because all the
-// work is done in the constructor and destructor, so in the standard
+// Note: This class is marked with GFLAGS_ATTRIBUTE_UNUSED because all
+// the work is done in the constructor and destructor, so in the standard
// usage example above, the compiler would complain that it's an
// unused variable.
//
@@ -282,27 +284,23 @@ class GFLAGS_DLL_DECL FlagSaver {
FlagSaver(const FlagSaver&); // no copying!
void operator=(const FlagSaver&);
-}
-#ifndef _MSC_VER
-__attribute__ ((unused))
-#endif
-;
+};
// --------------------------------------------------------------------
// Some deprecated or hopefully-soon-to-be-deprecated functions.
// This is often used for logging. TODO(csilvers): figure out a better way
-extern std::string CommandlineFlagsIntoString();
+extern GFLAGS_DLL_DECL std::string CommandlineFlagsIntoString();
// Usually where this is used, a FlagSaver should be used instead.
-extern bool ReadFlagsFromString(const std::string& flagfilecontents,
- const char* prog_name,
- bool errors_are_fatal); // uses SET_FLAGS_VALUE
+extern GFLAGS_DLL_DECL
+bool ReadFlagsFromString(const std::string& flagfilecontents,
+ const char* prog_name,
+ bool errors_are_fatal); // uses SET_FLAGS_VALUE
// These let you manually implement --flagfile functionality.
// DEPRECATED.
-extern bool AppendFlagsIntoFile(const std::string& filename, const char* prog_name);
-extern bool ReadFromFlagsFile(const std::string& filename, const char* prog_name,
- bool errors_are_fatal); // uses SET_FLAGS_VALUE
+extern GFLAGS_DLL_DECL bool AppendFlagsIntoFile(const std::string& filename, const char* prog_name);
+extern GFLAGS_DLL_DECL bool ReadFromFlagsFile(const std::string& filename, const char* prog_name, bool errors_are_fatal); // uses SET_FLAGS_VALUE
// --------------------------------------------------------------------
@@ -313,12 +311,12 @@ extern bool ReadFromFlagsFile(const std::string& filename, const char* prog_name
// Otherwise, return the value. NOTE: for booleans, for true use
// 't' or 'T' or 'true' or '1', for false 'f' or 'F' or 'false' or '0'.
-extern bool BoolFromEnv(const char *varname, bool defval);
-extern int32 Int32FromEnv(const char *varname, int32 defval);
-extern int64 Int64FromEnv(const char *varname, int64 defval);
-extern uint64 Uint64FromEnv(const char *varname, uint64 defval);
-extern double DoubleFromEnv(const char *varname, double defval);
-extern const char *StringFromEnv(const char *varname, const char *defval);
+extern GFLAGS_DLL_DECL bool BoolFromEnv(const char *varname, bool defval);
+extern GFLAGS_DLL_DECL int32 Int32FromEnv(const char *varname, int32 defval);
+extern GFLAGS_DLL_DECL int64 Int64FromEnv(const char *varname, int64 defval);
+extern GFLAGS_DLL_DECL uint64 Uint64FromEnv(const char *varname, uint64 defval);
+extern GFLAGS_DLL_DECL double DoubleFromEnv(const char *varname, double defval);
+extern GFLAGS_DLL_DECL const char *StringFromEnv(const char *varname, const char *defval);
// --------------------------------------------------------------------
@@ -330,12 +328,12 @@ extern const char *StringFromEnv(const char *varname, const char *defval);
// SetUsageMessage(usage);
// Do not include commandline flags in the usage: we do that for you!
// Thread-hostile; meant to be called before any threads are spawned.
-extern void SetUsageMessage(const std::string& usage);
+extern GFLAGS_DLL_DECL void SetUsageMessage(const std::string& usage);
// Sets the version string, which is emitted with --version.
// For instance: SetVersionString("1.3");
// Thread-hostile; meant to be called before any threads are spawned.
-extern void SetVersionString(const std::string& version);
+extern GFLAGS_DLL_DECL void SetVersionString(const std::string& version);
// Looks for flags in argv and parses them. Rearranges argv to put
@@ -345,7 +343,7 @@ extern void SetVersionString(const std::string& version);
// of the first non-flag argument.
// See top-of-file for more details on this function.
#ifndef SWIG // In swig, use ParseCommandLineFlagsScript() instead.
-extern uint32 ParseCommandLineFlags(int *argc, char*** argv, bool remove_flags);
+extern GFLAGS_DLL_DECL uint32 ParseCommandLineFlags(int *argc, char*** argv, bool remove_flags);
#endif
@@ -359,18 +357,18 @@ extern uint32 ParseCommandLineFlags(int *argc, char*** argv, bool remove_flags);
// defined more than once in the command line or flag file, the last
// definition is used. Returns the index (into argv) of the first
// non-flag argument. (If remove_flags is true, will always return 1.)
-extern uint32 ParseCommandLineNonHelpFlags(int *argc, char*** argv,
- bool remove_flags);
+extern GFLAGS_DLL_DECL uint32 ParseCommandLineNonHelpFlags(int *argc, char*** argv, bool remove_flags);
+
// This is actually defined in gflags_reporting.cc.
// This function is misnamed (it also handles --version, etc.), but
// it's too late to change that now. :-(
-extern void HandleCommandLineHelpFlags(); // in gflags_reporting.cc
+extern GFLAGS_DLL_DECL void HandleCommandLineHelpFlags(); // in gflags_reporting.cc
// Allow command line reparsing. Disables the error normally
// generated when an unknown flag is found, since it may be found in a
// later parse. Thread-hostile; meant to be called before any threads
// are spawned.
-extern void AllowCommandLineReparsing();
+extern GFLAGS_DLL_DECL void AllowCommandLineReparsing();
// Reparse the flags that have not yet been recognized. Only flags
// registered since the last parse will be recognized. Any flag value
@@ -378,7 +376,7 @@ extern void AllowCommandLineReparsing();
// separate command line argument that follows the flag argument.
// Intended for handling flags from dynamically loaded libraries,
// since their flags are not registered until they are loaded.
-extern void ReparseCommandLineNonHelpFlags();
+extern GFLAGS_DLL_DECL void ReparseCommandLineNonHelpFlags();
// Clean up memory allocated by flags. This is only needed to reduce
// the quantity of "potentially leaked" reports emitted by memory
@@ -389,7 +387,7 @@ extern void ReparseCommandLineNonHelpFlags();
// called will have unexpected consequences. This is not safe to run
// when multiple threads might be running: the function is
// thread-hostile.
-extern void ShutDownCommandLineFlags();
+extern GFLAGS_DLL_DECL void ShutDownCommandLineFlags();
// --------------------------------------------------------------------
@@ -420,7 +418,7 @@ extern void ShutDownCommandLineFlags();
// directly. The idea is that DEFINE puts the flag in the weird
// namespace, and DECLARE imports the flag from there into the current
// namespace. The net result is to force people to use DECLARE to get
-// access to a flag, rather than saying "extern bool FLAGS_whatever;"
+// access to a flag, rather than saying "extern GFLAGS_DLL_DECL bool FLAGS_whatever;"
// or some such instead. We want this so we can put extra
// functionality (like sanity-checking) in DECLARE if we want, and
// make sure it is picked up everywhere.
@@ -441,16 +439,18 @@ class GFLAGS_DLL_DECL FlagRegisterer {
// binary file. This can reduce the size of the resulting binary
// somewhat, and may also be useful for security reasons.
-extern const char kStrippedFlagHelp[];
+extern GFLAGS_DLL_DECL const char kStrippedFlagHelp[];
+
+
+} // namespace gflags
-}
#ifndef SWIG // In swig, ignore the main flag declarations
#if defined(STRIP_FLAG_HELP) && STRIP_FLAG_HELP > 0
// Need this construct to avoid the 'defined but not used' warning.
#define MAYBE_STRIPPED_HELP(txt) \
- (false ? (txt) : ::google::kStrippedFlagHelp)
+ (false ? (txt) : gflags::kStrippedFlagHelp)
#else
#define MAYBE_STRIPPED_HELP(txt) txt
#endif
@@ -472,7 +472,7 @@ extern const char kStrippedFlagHelp[];
/* We always want to export defined variables, dll or no */ \
GFLAGS_DLL_DEFINE_FLAG type FLAGS_##name = FLAGS_nono##name; \
type FLAGS_no##name = FLAGS_nono##name; \
- static ::google::FlagRegisterer o_##name( \
+ static gflags::FlagRegisterer o_##name( \
#name, #type, MAYBE_STRIPPED_HELP(help), __FILE__, \
&FLAGS_##name, &FLAGS_no##name); \
} \
@@ -505,15 +505,15 @@ GFLAGS_DLL_DECL bool IsBoolFlag(bool from);
DEFINE_VARIABLE(bool, B, name, val, txt)
#define DEFINE_int32(name, val, txt) \
- DEFINE_VARIABLE(::google::int32, I, \
+ DEFINE_VARIABLE(gflags::int32, I, \
name, val, txt)
#define DEFINE_int64(name, val, txt) \
- DEFINE_VARIABLE(::google::int64, I64, \
+ DEFINE_VARIABLE(gflags::int64, I64, \
name, val, txt)
#define DEFINE_uint64(name,val, txt) \
- DEFINE_VARIABLE(::google::uint64, U64, \
+ DEFINE_VARIABLE(gflags::uint64, U64, \
name, val, txt)
#define DEFINE_double(name, val, txt) \
@@ -554,7 +554,7 @@ inline clstring* dont_pass0toDEFINE_string(char *stringspot,
clstring* const FLAGS_no##name = ::fLS:: \
dont_pass0toDEFINE_string(s_##name[0].s, \
val); \
- static ::google::FlagRegisterer o_##name( \
+ static gflags::FlagRegisterer o_##name( \
#name, "string", MAYBE_STRIPPED_HELP(txt), __FILE__, \
s_##name[0].s, new (s_##name[1].s) clstring(*FLAGS_no##name)); \
extern GFLAGS_DLL_DEFINE_FLAG clstring& FLAGS_##name; \
@@ -565,4 +565,4 @@ inline clstring* dont_pass0toDEFINE_string(char *stringspot,
#endif // SWIG
-#endif // BASE_COMMANDLINEFLAGS_H_
+#endif // GFLAGS_GFLAGS_H_
diff --git a/extern/libmv/third_party/gflags/gflags/gflags_completions.h b/extern/libmv/third_party/gflags/gflags/gflags_completions.h
index 37f5b0ec2cf..2fa0db6d48a 100644
--- a/extern/libmv/third_party/gflags/gflags/gflags_completions.h
+++ b/extern/libmv/third_party/gflags/gflags/gflags_completions.h
@@ -109,22 +109,13 @@ $ complete -o bashdefault -o default -o nospace -C \
// produce the expected completion output.
-#ifndef BASE_COMMANDLINEFLAGS_COMPLETIONS_H_
-#define BASE_COMMANDLINEFLAGS_COMPLETIONS_H_
+#ifndef GFLAGS_COMPLETIONS_H_
+#define GFLAGS_COMPLETIONS_H_
-// Annoying stuff for windows -- makes sure clients can import these functions
-//
-// NOTE: all functions below MUST have an explicit 'extern' before
-// them. Our automated opensourcing tools use this as a signal to do
-// appropriate munging for windows, which needs to add GFLAGS_DLL_DECL.
-//
-#define GFLAGS_DLL_DECL /* rewritten to be non-empty in windows dir */
-
-
-namespace google {
+namespace gflags {
extern void HandleCommandLineCompletions(void);
}
-#endif // BASE_COMMANDLINEFLAGS_COMPLETIONS_H_
+#endif // GFLAGS_COMPLETIONS_H_
diff --git a/extern/libmv/third_party/gflags/gflags/gflags_declare.h b/extern/libmv/third_party/gflags/gflags/gflags_declare.h
index 503b686657f..335c389b610 100644
--- a/extern/libmv/third_party/gflags/gflags/gflags_declare.h
+++ b/extern/libmv/third_party/gflags/gflags/gflags_declare.h
@@ -34,43 +34,64 @@
// This is the file that should be included by any file which declares
// command line flag.
-#ifndef BASE_COMMANDLINEFLAGS_DECLARE_H_
-#define BASE_COMMANDLINEFLAGS_DECLARE_H_
-
-#include <string>
-#if 1
-#include <stdint.h> // the normal place uint16_t is defined
+#ifndef GFLAGS_DECLARE_H_
+#define GFLAGS_DECLARE_H_
+
+// ---------------------------------------------------------------------------
+// Windows DLL import/export.
+
+// We always want to import the symbols of the gflags library
+#ifndef GFLAGS_DLL_DECL
+# if 0 && defined(_MSC_VER)
+# define GFLAGS_DLL_DECL __declspec(dllimport)
+# else
+# define GFLAGS_DLL_DECL
+# endif
#endif
-#if 1
-#include <sys/types.h> // the normal place u_int16_t is defined
+
+// We always want to import variables declared in user code
+#ifndef GFLAGS_DLL_DECLARE_FLAG
+# if 0 && defined(_MSC_VER)
+# define GFLAGS_DLL_DECLARE_FLAG __declspec(dllimport)
+# else
+# define GFLAGS_DLL_DECLARE_FLAG
+# endif
#endif
+
+// ---------------------------------------------------------------------------
+// Flag types
+#include <string>
#if 1
-#include <inttypes.h> // a third place for uint16_t or u_int16_t
+# include <stdint.h> // the normal place uint32_t is defined
+#elif 1
+# include <sys/types.h> // the normal place u_int32_t is defined
+#elif 1
+# include <inttypes.h> // a third place for uint32_t or u_int32_t
#endif
-namespace google {
-#if defined(__GNUC__) || defined(__MINGW32__) // the C99 format
-typedef int32_t int32;
-typedef uint32_t uint32;
-typedef int64_t int64;
-typedef uint64_t uint64;
-#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) // the BSD format
-typedef int32_t int32;
-typedef u_int32_t uint32;
-typedef int64_t int64;
-typedef u_int64_t uint64;
-#elif defined(_MSC_VER) // the windows (vc7) format
-typedef __int32 int32;
+namespace gflags {
+
+#if 1 // C99
+typedef int32_t int32;
+typedef uint32_t uint32;
+typedef int64_t int64;
+typedef uint64_t uint64;
+#elif 0 // BSD
+typedef int32_t int32;
+typedef u_int32_t uint32;
+typedef int64_t int64;
+typedef u_int64_t uint64;
+#elif 0 // Windows
+typedef __int32 int32;
typedef unsigned __int32 uint32;
-typedef __int64 int64;
+typedef __int64 int64;
typedef unsigned __int64 uint64;
#else
-#error Do not know how to define a 32-bit integer quantity on your system
+# error Do not know how to define a 32-bit integer quantity on your system
#endif
-}
+} // namespace gflags
-#define GFLAGS_DLL_DECLARE_FLAG /* rewritten to be non-empty in windows dir */
namespace fLS {
@@ -80,7 +101,8 @@ namespace fLS {
// included). Save the current meaning now and use it in the macros.
typedef std::string clstring;
-}
+} // namespace fLS
+
#define DECLARE_VARIABLE(type, shorttype, name) \
/* We always want to import declared variables, dll or no */ \
@@ -91,22 +113,24 @@ typedef std::string clstring;
DECLARE_VARIABLE(bool, B, name)
#define DECLARE_int32(name) \
- DECLARE_VARIABLE(::google::int32, I, name)
+ DECLARE_VARIABLE(::gflags::int32, I, name)
#define DECLARE_int64(name) \
- DECLARE_VARIABLE(::google::int64, I64, name)
+ DECLARE_VARIABLE(::gflags::int64, I64, name)
#define DECLARE_uint64(name) \
- DECLARE_VARIABLE(::google::uint64, U64, name)
+ DECLARE_VARIABLE(::gflags::uint64, U64, name)
#define DECLARE_double(name) \
DECLARE_VARIABLE(double, D, name)
#define DECLARE_string(name) \
- namespace fLS { \
- using ::fLS::clstring; \
+ /* We always want to import declared variables, dll or no */ \
+ namespace fLS { \
+ using ::fLS::clstring; \
extern GFLAGS_DLL_DECLARE_FLAG ::fLS::clstring& FLAGS_##name; \
- } \
+ } \
using fLS::FLAGS_##name
-#endif // BASE_COMMANDLINEFLAGS_DECLARE_H_
+
+#endif // GFLAGS_DECLARE_H_
diff --git a/extern/libmv/third_party/gflags/gflags_completions.cc b/extern/libmv/third_party/gflags/gflags_completions.cc
index f46a2e0814e..3a476230ff9 100644
--- a/extern/libmv/third_party/gflags/gflags_completions.cc
+++ b/extern/libmv/third_party/gflags/gflags_completions.cc
@@ -48,6 +48,7 @@
#include "config.h"
+
#include <stdio.h>
#include <stdlib.h>
#include <string.h> // for strlen
@@ -57,17 +58,13 @@
#include <utility>
#include <vector>
-#include "gflags/gflags_completions.h"
-#include "gflags/gflags.h"
+#include "gflags.h"
#include "util.h"
using std::set;
using std::string;
using std::vector;
-#ifndef PATH_SEPARATOR
-#define PATH_SEPARATOR '/'
-#endif
DEFINE_string(tab_completion_word, "",
"If non-empty, HandleCommandLineCompletions() will hijack the "
@@ -76,7 +73,9 @@ DEFINE_string(tab_completion_word, "",
DEFINE_int32(tab_completion_columns, 80,
"Number of columns to use in output for tab completion");
-_START_GOOGLE_NAMESPACE_
+
+namespace GFLAGS_NAMESPACE {
+
namespace {
// Function prototypes and Type forward declarations. Code may be
@@ -766,4 +765,5 @@ void HandleCommandLineCompletions(void) {
gflags_exitfunc(0);
}
-_END_GOOGLE_NAMESPACE_
+
+} // namespace GFLAGS_NAMESPACE
diff --git a/extern/libmv/third_party/gflags/gflags_reporting.cc b/extern/libmv/third_party/gflags/gflags_reporting.cc
index c74bcc8d762..9cc41a7488c 100644
--- a/extern/libmv/third_party/gflags/gflags_reporting.cc
+++ b/extern/libmv/third_party/gflags/gflags_reporting.cc
@@ -48,40 +48,32 @@
// called after all flag-values have been assigned, that is, after
// parsing the command-line.
-#include "config.h"
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <assert.h>
#include <string>
#include <vector>
-#include "gflags/gflags.h"
-#include "gflags/gflags_completions.h"
+
+#include "config.h"
+#include "gflags.h"
+#include "gflags_completions.h"
#include "util.h"
-#ifndef PATH_SEPARATOR
-#define PATH_SEPARATOR '/'
-#endif
// The 'reporting' flags. They all call gflags_exitfunc().
-DEFINE_bool(help, false,
- "show help on all flags [tip: all flags can have two dashes]");
-DEFINE_bool(helpfull, false,
- "show help on all flags -- same as -help");
-DEFINE_bool(helpshort, false,
- "show help on only the main module for this program");
-DEFINE_string(helpon, "",
- "show help on the modules named by this flag value");
-DEFINE_string(helpmatch, "",
- "show help on modules whose name contains the specified substr");
-DEFINE_bool(helppackage, false,
- "show help on all modules in the main package");
-DEFINE_bool(helpxml, false,
- "produce an xml version of help");
-DEFINE_bool(version, false,
- "show version and build info and exit");
-
-_START_GOOGLE_NAMESPACE_
+DEFINE_bool (help, false, "show help on all flags [tip: all flags can have two dashes]");
+DEFINE_bool (helpfull, false, "show help on all flags -- same as -help");
+DEFINE_bool (helpshort, false, "show help on only the main module for this program");
+DEFINE_string(helpon, "", "show help on the modules named by this flag value");
+DEFINE_string(helpmatch, "", "show help on modules whose name contains the specified substr");
+DEFINE_bool (helppackage, false, "show help on all modules in the main package");
+DEFINE_bool (helpxml, false, "produce an xml version of help");
+DEFINE_bool (version, false, "show version and build info and exit");
+
+
+namespace GFLAGS_NAMESPACE {
+
using std::string;
using std::vector;
@@ -254,7 +246,7 @@ static bool FileMatchesSubstring(const string& filename,
// the string to be at the beginning of a directory component.
// That should match the first directory component as well, so
// we allow '/foo' to match a filename of 'foo'.
- if (!target->empty() && (*target)[0] == '/' &&
+ if (!target->empty() && (*target)[0] == PATH_SEPARATOR &&
strncmp(filename.c_str(), target->c_str() + 1,
strlen(target->c_str() + 1)) == 0)
return true;
@@ -360,7 +352,8 @@ static void ShowVersion() {
static void AppendPrognameStrings(vector<string>* substrings,
const char* progname) {
- string r("/");
+ string r("");
+ r += PATH_SEPARATOR;
r += progname;
substrings->push_back(r + ".");
substrings->push_back(r + "-main.");
@@ -395,7 +388,7 @@ void HandleCommandLineHelpFlags() {
gflags_exitfunc(1);
} else if (!FLAGS_helpon.empty()) {
- string restrict = "/" + FLAGS_helpon + ".";
+ string restrict = PATH_SEPARATOR + FLAGS_helpon + ".";
ShowUsageWithFlagsRestrict(progname, restrict.c_str());
gflags_exitfunc(1);
@@ -417,7 +410,7 @@ void HandleCommandLineHelpFlags() {
++flag) {
if (!FileMatchesSubstring(flag->filename, substrings))
continue;
- const string package = Dirname(flag->filename) + "/";
+ const string package = Dirname(flag->filename) + PATH_SEPARATOR;
if (package != last_package) {
ShowUsageWithFlagsRestrict(progname, package.c_str());
VLOG(7) << "Found package: " << package;
@@ -444,4 +437,5 @@ void HandleCommandLineHelpFlags() {
}
}
-_END_GOOGLE_NAMESPACE_
+
+} // namespace GFLAGS_NAMESPACE
diff --git a/extern/libmv/third_party/gflags/mutex.h b/extern/libmv/third_party/gflags/mutex.h
index 7c3c060a043..0bdd9d5f2a5 100644
--- a/extern/libmv/third_party/gflags/mutex.h
+++ b/extern/libmv/third_party/gflags/mutex.h
@@ -32,11 +32,6 @@
// A simple mutex wrapper, supporting locks and read-write locks.
// You should assume the locks are *not* re-entrant.
//
-// To use: you should define the following macros in your configure.ac:
-// ACX_PTHREAD
-// AC_RWLOCK
-// The latter is defined in ../autoconf.
-//
// This class is meant to be internal-only and should be wrapped by an
// internal namespace. Before you use this module, please give the
// name of your internal namespace for this module. Or, if you want
@@ -108,14 +103,14 @@
// weird to a Mutex's memory after it is destroyed, but for a
// static global variable, that's pretty safe.
-#ifndef GOOGLE_MUTEX_H_
-#define GOOGLE_MUTEX_H_
+#ifndef GFLAGS_MUTEX_H_
+#define GFLAGS_MUTEX_H_
-#include "config.h" // to figure out pthreads support
+#include "gflags_declare.h" // to figure out pthreads support
#if defined(NO_THREADS)
- typedef int MutexType; // to keep a lock-count
-#elif defined(_WIN32) || defined(__CYGWIN32__) || defined(__CYGWIN64__)
+ typedef int MutexType; // to keep a lock-count
+#elif defined(OS_WINDOWS)
# ifndef WIN32_LEAN_AND_MEAN
# define WIN32_LEAN_AND_MEAN // We only need minimal includes
# endif
@@ -232,7 +227,7 @@ bool Mutex::TryLock() { if (mutex_) return false; Lock(); return true; }
void Mutex::ReaderLock() { assert(++mutex_ > 0); }
void Mutex::ReaderUnlock() { assert(mutex_-- > 0); }
-#elif defined(_WIN32) || defined(__CYGWIN32__) || defined(__CYGWIN64__)
+#elif defined(OS_WINDOWS)
Mutex::Mutex() : destroy_(true) {
InitializeCriticalSection(&mutex_);
@@ -353,4 +348,4 @@ using namespace MUTEX_NAMESPACE;
#undef MUTEX_NAMESPACE
-#endif /* #define GOOGLE_MUTEX_H__ */
+#endif /* #define GFLAGS_MUTEX_H__ */
diff --git a/extern/libmv/third_party/gflags/util.h b/extern/libmv/third_party/gflags/util.h
index 8e2b1b89525..366e1be22e2 100644
--- a/extern/libmv/third_party/gflags/util.h
+++ b/extern/libmv/third_party/gflags/util.h
@@ -34,48 +34,53 @@
#ifndef GFLAGS_UTIL_H_
#define GFLAGS_UTIL_H_
-#include <assert.h>
#include "config.h"
+
+#include <assert.h>
+#include <config.h>
#ifdef HAVE_INTTYPES_H
-# include <inttypes.h>
+# include <inttypes.h>
#endif
#include <stdarg.h> // for va_*
#include <stdlib.h>
#include <stdio.h>
#include <iostream>
#include <string>
+#include <errno.h>
#ifdef HAVE_SYS_STAT_H
-# include <sys/stat.h>
-#endif // for mkdir()
+# include <sys/stat.h> // for mkdir
+#endif
+
+
+namespace GFLAGS_NAMESPACE {
-_START_GOOGLE_NAMESPACE_
// This is used for unittests for death-testing. It is defined in gflags.cc.
extern GFLAGS_DLL_DECL void (*gflags_exitfunc)(int);
-// Work properly if either strtoll or strtoq is on this system
-#ifdef HAVE_STRTOLL
-# define strto64 strtoll
-# define strtou64 strtoull
-#elif HAVE_STRTOQ
-# define strto64 strtoq
-# define strtou64 strtouq
-#else
+// Work properly if either strtoll or strtoq is on this system.
+#if defined(strtoll) || defined(HAVE_STRTOLL)
+# define strto64 strtoll
+# define strtou64 strtoull
+#elif defined(HAVE_STRTOQ)
+# define strto64 strtoq
+# define strtou64 strtouq
// Neither strtoll nor strtoq are defined. I hope strtol works!
-# define strto64 strtol
-# define strtou64 strtoul
+#else
+# define strto64 strtol
+# define strtou64 strtoul
#endif
-// If we have inttypes.h, it will have defined PRId32/etc for us. If
-// not, take our best guess.
+// If we have inttypes.h, it will have defined PRId32/etc for us.
+// If not, take our best guess.
#ifndef PRId32
-# define PRId32 "d"
+# define PRId32 "d"
#endif
#ifndef PRId64
-# define PRId64 "lld"
+# define PRId64 "lld"
#endif
#ifndef PRIu64
-# define PRIu64 "llu"
+# define PRIu64 "llu"
#endif
typedef signed char int8;
@@ -230,37 +235,36 @@ class Test {};
#if defined(__MINGW32__)
#include <io.h>
inline void MakeTmpdir(std::string* path) {
+ if (!path->empty()) {
+ path->append("/gflags_unittest_testdir");
+ int err = mkdir(path->c_str());
+ if (err == 0 || errno == EEXIST) return;
+ }
// I had trouble creating a directory in /tmp from mingw
- *path = "./gflags_unittest_testdir";
- mkdir(path->c_str()); // mingw has a weird one-arg mkdir
+ *path = "./gflags_unittest";
+ mkdir(path->c_str());
}
#elif defined(_MSC_VER)
#include <direct.h>
-#include <windows.h>
inline void MakeTmpdir(std::string* path) {
+ if (!path->empty()) {
+ int err = _mkdir(path->c_str());
+ if (err == 0 || errno == EEXIST) return;
+ }
char tmppath_buffer[1024];
int tmppath_len = GetTempPathA(sizeof(tmppath_buffer), tmppath_buffer);
assert(tmppath_len > 0 && tmppath_len < sizeof(tmppath_buffer));
assert(tmppath_buffer[tmppath_len - 1] == '\\'); // API guarantees it
- *path = std::string(tmppath_buffer) + "gflags_unittest_testdir";
+ *path = std::string(tmppath_buffer) + "gflags_unittest";
_mkdir(path->c_str());
}
-// Windows is missing random bits like strcasecmp, strtoll, strtoull, and
-// snprintf in the usual locations. Put them somewhere sensible.
-//
-// TODO(keir): Get the upstream Windows port and use that instead.
-#define snprintf _snprintf
-#undef strtoint64
-#define strtoint64 _strtoi64
-#undef strtouint64
-#define strtouint64 _strtoui64
-#define strcasecmp _stricmp
-#define va_copy(dst, src) ((dst) = (src))
-#define strto64 _strtoi64
-#define strtou64 _strtoui64
#else
inline void MakeTmpdir(std::string* path) {
- mkdir(path->c_str(), 0755);
+ if (!path->empty()) {
+ int err = mkdir(path->c_str(), 0755);
+ if (err == 0 || errno == EEXIST) return;
+ }
+ mkdir("/tmp/gflags_unittest", 0755);
}
#endif
@@ -278,7 +282,7 @@ inline void InternalStringPrintf(std::string* output, const char* format,
int bytes_written = vsnprintf(space, sizeof(space), format, backup_ap);
va_end(backup_ap);
- if ((bytes_written >= 0) && (bytes_written < sizeof(space))) {
+ if ((bytes_written >= 0) && (static_cast<size_t>(bytes_written) < sizeof(space))) {
output->append(space, bytes_written);
return;
}
@@ -334,6 +338,36 @@ inline std::string StringPrintf(const char* format, ...) {
return output;
}
-_END_GOOGLE_NAMESPACE_
+inline bool SafeGetEnv(const char *varname, std::string &valstr)
+{
+#if defined(_MSC_VER) && _MSC_VER >= 1400
+ char *val;
+ size_t sz;
+ if (_dupenv_s(&val, &sz, varname) != 0 || !val) return false;
+ valstr = val;
+ free(val);
+#else
+ const char * const val = getenv(varname);
+ if (!val) return false;
+ valstr = val;
+#endif
+ return true;
+}
+
+inline int SafeFOpen(FILE **fp, const char* fname, const char *mode)
+{
+#if defined(_MSC_VER) && _MSC_VER >= 1400
+ return fopen_s(fp, fname, mode);
+#else
+ assert(fp != NULL);
+ *fp = fopen(fname, mode);
+ // errno only guaranteed to be set on failure
+ return ((*fp == NULL) ? errno : 0);
+#endif
+}
+
+
+} // namespace GFLAGS_NAMESPACE
+
#endif // GFLAGS_UTIL_H_
diff --git a/extern/libmv/third_party/gflags/windows_port.cc b/extern/libmv/third_party/gflags/windows_port.cc
new file mode 100644
index 00000000000..1f40458e888
--- /dev/null
+++ b/extern/libmv/third_party/gflags/windows_port.cc
@@ -0,0 +1,71 @@
+/* Copyright (c) 2009, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * ---
+ * Author: Craig Silverstein
+ */
+
+#ifndef _WIN32
+# error You should only be including windows/port.cc in a windows environment!
+#endif
+
+#include <string.h> // for strlen(), memset(), memcmp()
+#include <assert.h>
+#include <stdarg.h> // for va_list, va_start, va_end
+#include <windows.h>
+
+#include "windows_port.h"
+
+// These call the windows _vsnprintf, but always NUL-terminate.
+#if !defined(__MINGW32__) && !defined(__MINGW64__) /* mingw already defines */
+
+#ifdef _MSC_VER
+# pragma warning(push)
+# pragma warning(disable: 4996) // ignore _vsnprintf security warning
+#endif
+int safe_vsnprintf(char *str, size_t size, const char *format, va_list ap) {
+ if (size == 0) // not even room for a \0?
+ return -1; // not what C99 says to do, but what windows does
+ str[size-1] = '\0';
+ return _vsnprintf(str, size-1, format, ap);
+}
+#ifdef _MSC_VER
+# pragma warning(pop)
+#endif
+
+int snprintf(char *str, size_t size, const char *format, ...) {
+ int r;
+ va_list ap;
+ va_start(ap, format);
+ r = vsnprintf(str, size, format, ap);
+ va_end(ap);
+ return r;
+}
+
+#endif /* #if !defined(__MINGW32__) && !defined(__MINGW64__) */
diff --git a/extern/libmv/third_party/gflags/windows_port.h b/extern/libmv/third_party/gflags/windows_port.h
new file mode 100644
index 00000000000..c8ff24f8f00
--- /dev/null
+++ b/extern/libmv/third_party/gflags/windows_port.h
@@ -0,0 +1,127 @@
+/* Copyright (c) 2009, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * ---
+ * Author: Craig Silverstein
+ *
+ * These are some portability typedefs and defines to make it a bit
+ * easier to compile this code under VC++.
+ *
+ * Several of these are taken from glib:
+ * http://developer.gnome.org/doc/API/glib/glib-windows-compatability-functions.html
+ */
+
+#ifndef GFLAGS_WINDOWS_PORT_H_
+#define GFLAGS_WINDOWS_PORT_H_
+
+#include "config.h"
+
+// This must be defined before the windows.h is included.
+// It's needed for mutex.h, to give access to the TryLock method.
+# if !defined(_WIN32_WINNT) && !(defined( __MINGW32__) || defined(__MINGW64__))
+# define _WIN32_WINNT 0x0400
+# endif
+// We always want minimal includes
+#ifndef WIN32_LEAN_AND_MEAN
+# define WIN32_LEAN_AND_MEAN
+#endif
+#include <windows.h>
+#include <direct.h> /* for mkdir */
+#include <stdlib.h> /* for _putenv, getenv */
+#include <stdio.h> /* need this to override stdio's snprintf, also defines _unlink used by unit tests */
+#include <stdarg.h> /* util.h uses va_copy */
+#include <string.h> /* for _stricmp and _strdup */
+
+/* We can't just use _vsnprintf and _snprintf as drop-in-replacements,
+ * because they don't always NUL-terminate. :-( We also can't use the
+ * name vsnprintf, since windows defines that (but not snprintf (!)).
+ */
+#if !defined(__MINGW32__) && !defined(__MINGW64__) /* mingw already defines */
+extern GFLAGS_DLL_DECL int snprintf(char *str, size_t size,
+ const char *format, ...);
+extern int GFLAGS_DLL_DECL safe_vsnprintf(char *str, size_t size,
+ const char *format, va_list ap);
+#define vsnprintf(str, size, format, ap) safe_vsnprintf(str, size, format, ap)
+#define va_copy(dst, src) (dst) = (src)
+#endif /* #if !defined(__MINGW32__) && !defined(__MINGW64__) */
+
+#ifdef _MSC_VER
+# pragma warning(push)
+# pragma warning(disable: 4996) // ignore getenv security warning
+#endif
+inline void setenv(const char* name, const char* value, int) {
+ // In windows, it's impossible to set a variable to the empty string.
+ // We handle this by setting it to "0" and the NUL-ing out the \0.
+ // That is, we putenv("FOO=0") and then find out where in memory the
+ // putenv wrote "FOO=0", and change it in-place to "FOO=\0".
+ // c.f. http://svn.apache.org/viewvc/stdcxx/trunk/tests/src/environ.cpp?r1=611451&r2=637508&pathrev=637508
+ static const char* const kFakeZero = "0";
+ if (*value == '\0')
+ value = kFakeZero;
+ // Apparently the semantics of putenv() is that the input
+ // must live forever, so we leak memory here. :-(
+ const size_t nameval_len = strlen(name) + 1 + strlen(value) + 1;
+ char* nameval = reinterpret_cast<char*>(malloc(nameval_len));
+ snprintf(nameval, nameval_len, "%s=%s", name, value);
+ _putenv(nameval);
+ if (value == kFakeZero) {
+ nameval[nameval_len - 2] = '\0'; // works when putenv() makes no copy
+ if (*getenv(name) != '\0')
+ *getenv(name) = '\0'; // works when putenv() copies nameval
+ }
+}
+#ifdef _MSC_VER
+# pragma warning(pop)
+#endif
+
+#define strcasecmp _stricmp
+
+#if defined(_MSC_VER) && _MSC_VER >= 1400
+#define strdup _strdup
+#define unlink _unlink
+#endif
+
+#define PRId32 "d"
+#define PRIu32 "u"
+#define PRId64 "I64d"
+#define PRIu64 "I64u"
+
+#if !defined(__MINGW32__) && !defined(__MINGW64__)
+#define strtoq _strtoi64
+#define strtouq _strtoui64
+#define strtoll _strtoi64
+#define strtoull _strtoui64
+#define atoll _atoi64
+#endif
+
+#ifndef PATH_MAX
+#define PATH_MAX 1024
+#endif
+
+#endif /* GFLAGS_WINDOWS_PORT_H_ */
diff --git a/extern/libmv/third_party/glog/README.libmv b/extern/libmv/third_party/glog/README.libmv
index eb4b2ea3379..10e51fa6df4 100644
--- a/extern/libmv/third_party/glog/README.libmv
+++ b/extern/libmv/third_party/glog/README.libmv
@@ -1,7 +1,7 @@
Project: Google Logging
URL: http://code.google.com/p/google-glog/
License: New BSD
-Upstream version: 0.3.3, r139
+Upstream version: 0.3.3, r143
Local modifications:
* Added per-platform config.h files so no configuration-time
checks for functions and so are needed.
diff --git a/extern/libmv/third_party/glog/src/demangle.cc b/extern/libmv/third_party/glog/src/demangle.cc
index 0daf30893b3..e858181a68f 100644
--- a/extern/libmv/third_party/glog/src/demangle.cc
+++ b/extern/libmv/third_party/glog/src/demangle.cc
@@ -167,7 +167,7 @@ static size_t StrLen(const char *str) {
// Returns true if "str" has at least "n" characters remaining.
static bool AtLeastNumCharsRemaining(const char *str, int n) {
for (int i = 0; i < n; ++i) {
- if (str == '\0') {
+ if (str[i] == '\0') {
return false;
}
}
@@ -223,9 +223,6 @@ static bool ParseTwoCharToken(State *state, const char *two_char_token) {
// Returns true and advances "mangled_cur" if we find any character in
// "char_class" at "mangled_cur" position.
static bool ParseCharClass(State *state, const char *char_class) {
- if (state->mangled_cur == '\0') {
- return false;
- }
const char *p = char_class;
for (; *p != '\0'; ++p) {
if (state->mangled_cur[0] == *p) {
diff --git a/extern/libmv/third_party/glog/src/logging.cc b/extern/libmv/third_party/glog/src/logging.cc
index 5e2ce61c9c9..75047353535 100644
--- a/extern/libmv/third_party/glog/src/logging.cc
+++ b/extern/libmv/third_party/glog/src/logging.cc
@@ -31,6 +31,7 @@
#include "utilities.h"
+#include <algorithm>
#include <assert.h>
#include <iomanip>
#include <string>
@@ -181,6 +182,10 @@ GLOG_DEFINE_string(log_backtrace_at, "",
#define PATH_SEPARATOR '/'
#ifndef HAVE_PREAD
+#if defined(OS_WINDOWS)
+#include <BaseTsd.h>
+#define ssize_t SSIZE_T
+#endif
static ssize_t pread(int fd, void* buf, size_t count, off_t offset) {
off_t orig_offset = lseek(fd, 0, SEEK_CUR);
if (orig_offset == (off_t)-1)
diff --git a/extern/libmv/third_party/glog/src/symbolize.cc b/extern/libmv/third_party/glog/src/symbolize.cc
index 18bbccf3072..b25f7479d0d 100644
--- a/extern/libmv/third_party/glog/src/symbolize.cc
+++ b/extern/libmv/third_party/glog/src/symbolize.cc
@@ -45,6 +45,12 @@
// some functions which are not guaranteed to be so, such as memchr()
// and memmove(). We assume they are async-signal-safe.
//
+// Additional header can be specified by the GLOG_BUILD_CONFIG_INCLUDE
+// macro to add platform specific defines (e.g. OS_OPENBSD).
+
+#ifdef GLOG_BUILD_CONFIG_INCLUDE
+#include GLOG_BUILD_CONFIG_INCLUDE
+#endif // GLOG_BUILD_CONFIG_INCLUDE
#include "utilities.h"
@@ -74,6 +80,13 @@ void InstallSymbolizeCallback(SymbolizeCallback callback) {
g_symbolize_callback = callback;
}
+static SymbolizeOpenObjectFileCallback g_symbolize_open_object_file_callback =
+ NULL;
+void InstallSymbolizeOpenObjectFileCallback(
+ SymbolizeOpenObjectFileCallback callback) {
+ g_symbolize_open_object_file_callback = callback;
+}
+
// This function wraps the Demangle function to provide an interface
// where the input symbol is demangled in-place.
// To keep stack consumption low, we would like this function to not
@@ -95,11 +108,14 @@ _END_GOOGLE_NAMESPACE_
#if defined(__ELF__)
#include <dlfcn.h>
+#if defined(OS_OPENBSD)
+#include <sys/exec_elf.h>
+#else
#include <elf.h>
+#endif
#include <errno.h>
#include <fcntl.h>
#include <limits.h>
-#include <link.h> // For ElfW() macro.
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
@@ -123,7 +139,7 @@ _START_GOOGLE_NAMESPACE_
// success, return the number of bytes read. Otherwise, return -1.
static ssize_t ReadPersistent(const int fd, void *buf, const size_t count) {
SAFE_ASSERT(fd >= 0);
- SAFE_ASSERT(count >= 0 && count <= std::numeric_limits<ssize_t>::max());
+ SAFE_ASSERT(count <= std::numeric_limits<ssize_t>::max());
char *buf0 = reinterpret_cast<char *>(buf);
ssize_t num_bytes = 0;
while (num_bytes < count) {
@@ -326,31 +342,29 @@ static bool GetSymbolFromObjectFile(const int fd, uint64_t pc,
ElfW(Shdr) symtab, strtab;
// Consult a regular symbol table first.
- if (!GetSectionHeaderByType(fd, elf_header.e_shnum, elf_header.e_shoff,
- SHT_SYMTAB, &symtab)) {
- return false;
- }
- if (!ReadFromOffsetExact(fd, &strtab, sizeof(strtab), elf_header.e_shoff +
- symtab.sh_link * sizeof(symtab))) {
- return false;
- }
- if (FindSymbol(pc, fd, out, out_size, symbol_offset,
- &strtab, &symtab)) {
- return true; // Found the symbol in a regular symbol table.
+ if (GetSectionHeaderByType(fd, elf_header.e_shnum, elf_header.e_shoff,
+ SHT_SYMTAB, &symtab)) {
+ if (!ReadFromOffsetExact(fd, &strtab, sizeof(strtab), elf_header.e_shoff +
+ symtab.sh_link * sizeof(symtab))) {
+ return false;
+ }
+ if (FindSymbol(pc, fd, out, out_size, symbol_offset,
+ &strtab, &symtab)) {
+ return true; // Found the symbol in a regular symbol table.
+ }
}
// If the symbol is not found, then consult a dynamic symbol table.
- if (!GetSectionHeaderByType(fd, elf_header.e_shnum, elf_header.e_shoff,
- SHT_DYNSYM, &symtab)) {
- return false;
- }
- if (!ReadFromOffsetExact(fd, &strtab, sizeof(strtab), elf_header.e_shoff +
- symtab.sh_link * sizeof(symtab))) {
- return false;
- }
- if (FindSymbol(pc, fd, out, out_size, symbol_offset,
- &strtab, &symtab)) {
- return true; // Found the symbol in a dynamic symbol table.
+ if (GetSectionHeaderByType(fd, elf_header.e_shnum, elf_header.e_shoff,
+ SHT_DYNSYM, &symtab)) {
+ if (!ReadFromOffsetExact(fd, &strtab, sizeof(strtab), elf_header.e_shoff +
+ symtab.sh_link * sizeof(symtab))) {
+ return false;
+ }
+ if (FindSymbol(pc, fd, out, out_size, symbol_offset,
+ &strtab, &symtab)) {
+ return true; // Found the symbol in a dynamic symbol table.
+ }
}
return false;
@@ -481,13 +495,20 @@ static char *GetHex(const char *start, const char *end, uint64_t *hex) {
return const_cast<char *>(p);
}
-// Search for the object file (from /proc/self/maps) that contains
-// the specified pc. If found, open this file and return the file handle,
-// and also set start_address to the start address of where this object
-// file is mapped to in memory. Otherwise, return -1.
+// Searches for the object file (from /proc/self/maps) that contains
+// the specified pc. If found, sets |start_address| to the start address
+// of where this object file is mapped in memory, sets the module base
+// address into |base_address|, copies the object file name into
+// |out_file_name|, and attempts to open the object file. If the object
+// file is opened successfully, returns the file descriptor. Otherwise,
+// returns -1. |out_file_name_size| is the size of the file name buffer
+// (including the null-terminator).
static ATTRIBUTE_NOINLINE int
OpenObjectFileContainingPcAndGetStartAddress(uint64_t pc,
- uint64_t &start_address) {
+ uint64_t &start_address,
+ uint64_t &base_address,
+ char *out_file_name,
+ int out_file_name_size) {
int object_fd;
// Open /proc/self/maps.
@@ -501,8 +522,10 @@ OpenObjectFileContainingPcAndGetStartAddress(uint64_t pc,
// Iterate over maps and look for the map containing the pc. Then
// look into the symbol tables inside.
char buf[1024]; // Big enough for line of sane /proc/self/maps
+ int num_maps = 0;
LineReader reader(wrapped_maps_fd.get(), buf, sizeof(buf));
while (true) {
+ num_maps++;
const char *cursor;
const char *eol;
if (!reader.ReadLine(&cursor, &eol)) { // EOF or malformed line.
@@ -552,14 +575,35 @@ OpenObjectFileContainingPcAndGetStartAddress(uint64_t pc,
}
++cursor; // Skip ' '.
- // Skip to file name. "cursor" now points to file offset. We need to
- // skip at least three spaces for file offset, dev, and inode.
+ // Read file offset.
+ uint64_t file_offset;
+ cursor = GetHex(cursor, eol, &file_offset);
+ if (cursor == eol || *cursor != ' ') {
+ return -1; // Malformed line.
+ }
+ ++cursor; // Skip ' '.
+
+ // Don't subtract 'start_address' from the first entry:
+ // * If a binary is compiled w/o -pie, then the first entry in
+ // process maps is likely the binary itself (all dynamic libs
+ // are mapped higher in address space). For such a binary,
+ // instruction offset in binary coincides with the actual
+ // instruction address in virtual memory (as code section
+ // is mapped to a fixed memory range).
+ // * If a binary is compiled with -pie, all the modules are
+ // mapped high at address space (in particular, higher than
+ // shadow memory of the tool), so the module can't be the
+ // first entry.
+ base_address = ((num_maps == 1) ? 0U : start_address) - file_offset;
+
+ // Skip to file name. "cursor" now points to dev. We need to
+ // skip at least two spaces for dev and inode.
int num_spaces = 0;
while (cursor < eol) {
if (*cursor == ' ') {
++num_spaces;
- } else if (num_spaces >= 3) {
- // The first non-space character after skipping three spaces
+ } else if (num_spaces >= 2) {
+ // The first non-space character after skipping two spaces
// is the beginning of the file name.
break;
}
@@ -572,12 +616,105 @@ OpenObjectFileContainingPcAndGetStartAddress(uint64_t pc,
// Finally, "cursor" now points to file name of our interest.
NO_INTR(object_fd = open(cursor, O_RDONLY));
if (object_fd < 0) {
+ // Failed to open object file. Copy the object file name to
+ // |out_file_name|.
+ strncpy(out_file_name, cursor, out_file_name_size);
+ // Making sure |out_file_name| is always null-terminated.
+ out_file_name[out_file_name_size - 1] = '\0';
return -1;
}
return object_fd;
}
}
+// POSIX doesn't define any async-signal safe function for converting
+// an integer to ASCII. We'll have to define our own version.
+// itoa_r() converts a (signed) integer to ASCII. It returns "buf", if the
+// conversion was successful or NULL otherwise. It never writes more than "sz"
+// bytes. Output will be truncated as needed, and a NUL character is always
+// appended.
+// NOTE: code from sandbox/linux/seccomp-bpf/demo.cc.
+char *itoa_r(intptr_t i, char *buf, size_t sz, int base, size_t padding) {
+ // Make sure we can write at least one NUL byte.
+ size_t n = 1;
+ if (n > sz)
+ return NULL;
+
+ if (base < 2 || base > 16) {
+ buf[0] = '\000';
+ return NULL;
+ }
+
+ char *start = buf;
+
+ uintptr_t j = i;
+
+ // Handle negative numbers (only for base 10).
+ if (i < 0 && base == 10) {
+ j = -i;
+
+ // Make sure we can write the '-' character.
+ if (++n > sz) {
+ buf[0] = '\000';
+ return NULL;
+ }
+ *start++ = '-';
+ }
+
+ // Loop until we have converted the entire number. Output at least one
+ // character (i.e. '0').
+ char *ptr = start;
+ do {
+ // Make sure there is still enough space left in our output buffer.
+ if (++n > sz) {
+ buf[0] = '\000';
+ return NULL;
+ }
+
+ // Output the next digit.
+ *ptr++ = "0123456789abcdef"[j % base];
+ j /= base;
+
+ if (padding > 0)
+ padding--;
+ } while (j > 0 || padding > 0);
+
+ // Terminate the output with a NUL character.
+ *ptr = '\000';
+
+ // Conversion to ASCII actually resulted in the digits being in reverse
+ // order. We can't easily generate them in forward order, as we can't tell
+ // the number of characters needed until we are done converting.
+ // So, now, we reverse the string (except for the possible "-" sign).
+ while (--ptr > start) {
+ char ch = *ptr;
+ *ptr = *start;
+ *start++ = ch;
+ }
+ return buf;
+}
+
+// Safely appends string |source| to string |dest|. Never writes past the
+// buffer size |dest_size| and guarantees that |dest| is null-terminated.
+void SafeAppendString(const char* source, char* dest, int dest_size) {
+ int dest_string_length = strlen(dest);
+ SAFE_ASSERT(dest_string_length < dest_size);
+ dest += dest_string_length;
+ dest_size -= dest_string_length;
+ strncpy(dest, source, dest_size);
+ // Making sure |dest| is always null-terminated.
+ dest[dest_size - 1] = '\0';
+}
+
+// Converts a 64-bit value into a hex string, and safely appends it to |dest|.
+// Never writes past the buffer size |dest_size| and guarantees that |dest| is
+// null-terminated.
+void SafeAppendHexNumber(uint64_t value, char* dest, int dest_size) {
+ // 64-bit numbers in hex can have up to 16 digits.
+ char buf[17] = {'\0'};
+ SafeAppendString(itoa_r(value, buf, sizeof(buf), 16, 0), dest, dest_size);
+}
+
// The implementation of our symbolization routine. If it
// successfully finds the symbol containing "pc" and obtains the
// symbol name, returns true and write the symbol name to "out".
@@ -590,10 +727,40 @@ static ATTRIBUTE_NOINLINE bool SymbolizeAndDemangle(void *pc, char *out,
int out_size) {
uint64_t pc0 = reinterpret_cast<uintptr_t>(pc);
uint64_t start_address = 0;
+ uint64_t base_address = 0;
+ int object_fd = -1;
- int object_fd = OpenObjectFileContainingPcAndGetStartAddress(pc0,
- start_address);
- if (object_fd == -1) {
+ if (out_size < 1) {
+ return false;
+ }
+ out[0] = '\0';
+ SafeAppendString("(", out, out_size);
+
+ if (g_symbolize_open_object_file_callback) {
+ object_fd = g_symbolize_open_object_file_callback(pc0, start_address,
+ base_address, out + 1,
+ out_size - 1);
+ } else {
+ object_fd = OpenObjectFileContainingPcAndGetStartAddress(pc0, start_address,
+ base_address,
+ out + 1,
+ out_size - 1);
+ }
+
+ // Check whether a file name was returned.
+ if (object_fd < 0) {
+ if (out[1]) {
+ // The object file containing PC was determined successfully however the
+ // object file was not opened successfully. This is still considered
+ // success because the object file name and offset are known and tools
+ // like asan_symbolize.py can be used for the symbolization.
+ out[out_size - 1] = '\0'; // Making sure |out| is always null-terminated.
+ SafeAppendString("+0x", out, out_size);
+ SafeAppendHexNumber(pc0 - base_address, out, out_size);
+ SafeAppendString(")", out, out_size);
+ return true;
+ }
+ // Failed to determine the object file containing PC. Bail out.
return false;
}
FileDescriptor wrapped_object_fd(object_fd);
diff --git a/extern/libmv/third_party/glog/src/symbolize.h b/extern/libmv/third_party/glog/src/symbolize.h
index 1ebe4dd94a2..f617184249c 100644
--- a/extern/libmv/third_party/glog/src/symbolize.h
+++ b/extern/libmv/third_party/glog/src/symbolize.h
@@ -60,9 +60,26 @@
#ifdef HAVE_SYMBOLIZE
-#if defined(__ELF__) // defined by gcc on Linux
+#if defined(__ELF__) // defined by gcc
+#if defined(__OpenBSD__)
+#include <sys/exec_elf.h>
+#else
#include <elf.h>
+#endif
+
+#if !defined(ANDROID)
#include <link.h> // For ElfW() macro.
+#endif
+
+// For systems where SIZEOF_VOID_P is not defined, determine it
+// based on __LP64__ (defined by gcc on 64-bit systems)
+#if !defined(SIZEOF_VOID_P)
+# if defined(__LP64__)
+# define SIZEOF_VOID_P 8
+# else
+# define SIZEOF_VOID_P 4
+# endif
+#endif
// If there is no ElfW macro, let's define it by ourself.
#ifndef ElfW
@@ -88,6 +105,10 @@ _END_GOOGLE_NAMESPACE_
_START_GOOGLE_NAMESPACE_
+// Restrictions on the callbacks that follow:
+// - The callbacks must not use heaps but only use stacks.
+// - The callbacks must be async-signal-safe.
+
// Installs a callback function, which will be called right before a symbol name
// is printed. The callback is intended to be used for showing a file name and a
// line number preceding a symbol name.
@@ -99,6 +120,24 @@ typedef int (*SymbolizeCallback)(int fd, void *pc, char *out, size_t out_size,
uint64 relocation);
void InstallSymbolizeCallback(SymbolizeCallback callback);
+// Installs a callback function, which will be called instead of
+// OpenObjectFileContainingPcAndGetStartAddress. The callback is expected
+// to searches for the object file (from /proc/self/maps) that contains
+// the specified pc. If found, sets |start_address| to the start address
+// of where this object file is mapped in memory, sets the module base
+// address into |base_address|, copies the object file name into
+// |out_file_name|, and attempts to open the object file. If the object
+// file is opened successfully, returns the file descriptor. Otherwise,
+// returns -1. |out_file_name_size| is the size of the file name buffer
+// (including the null-terminator).
+typedef int (*SymbolizeOpenObjectFileCallback)(uint64_t pc,
+ uint64_t &start_address,
+ uint64_t &base_address,
+ char *out_file_name,
+ int out_file_name_size);
+void InstallSymbolizeOpenObjectFileCallback(
+ SymbolizeOpenObjectFileCallback callback);
+
_END_GOOGLE_NAMESPACE_
#endif
diff --git a/extern/libopenjpeg/CMakeLists.txt b/extern/libopenjpeg/CMakeLists.txt
index c602ddcabb9..ad49eee25b6 100644
--- a/extern/libopenjpeg/CMakeLists.txt
+++ b/extern/libopenjpeg/CMakeLists.txt
@@ -31,9 +31,7 @@ set(INC_SYS
)
-if(WIN32)
- add_definitions(-DOPJ_STATIC)
-endif()
+add_definitions(${OPENJPEG_DEFINES})
set(SRC
bio.c
diff --git a/extern/libredcode/CMakeLists.txt b/extern/libredcode/CMakeLists.txt
index c9d2bfc8fd6..c75523741ea 100644
--- a/extern/libredcode/CMakeLists.txt
+++ b/extern/libredcode/CMakeLists.txt
@@ -41,4 +41,6 @@ set(SRC
format.h
)
+add_definitions(${OPENJPEG_DEFINES})
+
blender_add_lib(extern_redcode "${SRC}" "${INC}" "${INC_SYS}")
diff --git a/extern/libredcode/format.c b/extern/libredcode/format.c
index 8c6cae5234e..9a3023fa2c0 100644
--- a/extern/libredcode/format.c
+++ b/extern/libredcode/format.c
@@ -78,7 +78,7 @@ static unsigned char* read_packet(FILE * fp, char * expect)
len = read_be32(len);
if (strcmp(expect, head) != 0) {
- fprintf(stderr, "Read: %s, expect: %s\n", head, expect);
+ /* fprintf(stderr, "Read: %s, expect: %s\n", head, expect); */
return NULL;
}
diff --git a/extern/lzo/CMakeLists.txt b/extern/lzo/CMakeLists.txt
index 5172a96e599..23bbf268cc6 100644
--- a/extern/lzo/CMakeLists.txt
+++ b/extern/lzo/CMakeLists.txt
@@ -23,6 +23,8 @@
#
# ***** END GPL LICENSE BLOCK *****
+remove_strict_flags()
+
set(INC
)
diff --git a/extern/lzo/minilzo/README.LZO b/extern/lzo/minilzo/README.LZO
index 058eace70a0..83e10e352ff 100644
--- a/extern/lzo/minilzo/README.LZO
+++ b/extern/lzo/minilzo/README.LZO
@@ -6,8 +6,8 @@
Author : Markus Franz Xaver Johannes Oberhumer
<markus@oberhumer.com>
http://www.oberhumer.com/opensource/lzo/
- Version : 2.06
- Date : 12 Aug 2011
+ Version : 2.08
+ Date : 29 Jun 2014
I've created miniLZO for projects where it is inconvenient to
include (or require) the full LZO source code just because you
@@ -110,9 +110,8 @@
Appendix D: Copyright
---------------------
- LZO and miniLZO are Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001,
- 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
- Markus Franz Xaver Oberhumer <markus@oberhumer.com>.
+ LZO and miniLZO are Copyright (C) 1996-2014 Markus Franz Xaver Oberhumer
+ All Rights Reserved.
LZO and miniLZO are distributed under the terms of the GNU General
Public License (GPL). See the file COPYING.
diff --git a/extern/lzo/minilzo/lzoconf.h b/extern/lzo/minilzo/lzoconf.h
index 23c6ca93fcc..61be29c5dc2 100644
--- a/extern/lzo/minilzo/lzoconf.h
+++ b/extern/lzo/minilzo/lzoconf.h
@@ -2,22 +2,7 @@
This file is part of the LZO real-time data compression library.
- Copyright (C) 2011 Markus Franz Xaver Johannes Oberhumer
- Copyright (C) 2010 Markus Franz Xaver Johannes Oberhumer
- Copyright (C) 2009 Markus Franz Xaver Johannes Oberhumer
- Copyright (C) 2008 Markus Franz Xaver Johannes Oberhumer
- Copyright (C) 2007 Markus Franz Xaver Johannes Oberhumer
- Copyright (C) 2006 Markus Franz Xaver Johannes Oberhumer
- Copyright (C) 2005 Markus Franz Xaver Johannes Oberhumer
- Copyright (C) 2004 Markus Franz Xaver Johannes Oberhumer
- Copyright (C) 2003 Markus Franz Xaver Johannes Oberhumer
- Copyright (C) 2002 Markus Franz Xaver Johannes Oberhumer
- Copyright (C) 2001 Markus Franz Xaver Johannes Oberhumer
- Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer
- Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer
- Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer
- Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer
- Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1996-2014 Markus Franz Xaver Johannes Oberhumer
All Rights Reserved.
The LZO library is free software; you can redistribute it and/or
@@ -44,9 +29,9 @@
#ifndef __LZOCONF_H_INCLUDED
#define __LZOCONF_H_INCLUDED 1
-#define LZO_VERSION 0x2060
-#define LZO_VERSION_STRING "2.06"
-#define LZO_VERSION_DATE "Aug 12 2011"
+#define LZO_VERSION 0x2080
+#define LZO_VERSION_STRING "2.08"
+#define LZO_VERSION_DATE "Jun 29 2014"
/* internal Autoconf configuration file - only used when building LZO */
#if defined(LZO_HAVE_CONFIG_H)
@@ -63,7 +48,7 @@
#if !defined(CHAR_BIT) || (CHAR_BIT != 8)
# error "invalid CHAR_BIT"
#endif
-#if !defined(UCHAR_MAX) || !defined(UINT_MAX) || !defined(ULONG_MAX)
+#if !defined(UCHAR_MAX) || !defined(USHRT_MAX) || !defined(UINT_MAX) || !defined(ULONG_MAX)
# error "check your compiler installation"
#endif
#if (USHRT_MAX < 1) || (UINT_MAX < 1) || (ULONG_MAX < 1)
@@ -85,14 +70,6 @@ extern "C" {
// some core defines
************************************************************************/
-#if !defined(LZO_UINT32_C)
-# if (UINT_MAX < LZO_0xffffffffL)
-# define LZO_UINT32_C(c) c ## UL
-# else
-# define LZO_UINT32_C(c) ((c) + 0U)
-# endif
-#endif
-
/* memory checkers */
#if !defined(__LZO_CHECKER)
# if defined(__BOUNDS_CHECKING_ON)
@@ -111,28 +88,31 @@ extern "C" {
// integral and pointer types
************************************************************************/
-/* lzo_uint should match size_t */
+/* lzo_uint must match size_t */
#if !defined(LZO_UINT_MAX)
-# if defined(LZO_ABI_LLP64) /* WIN64 */
-# if defined(LZO_OS_WIN64)
+# if (LZO_ABI_LLP64)
+# if (LZO_OS_WIN64)
typedef unsigned __int64 lzo_uint;
typedef __int64 lzo_int;
# else
- typedef unsigned long long lzo_uint;
- typedef long long lzo_int;
+ typedef lzo_ullong_t lzo_uint;
+ typedef lzo_llong_t lzo_int;
# endif
+# define LZO_SIZEOF_LZO_UINT 8
# define LZO_UINT_MAX 0xffffffffffffffffull
# define LZO_INT_MAX 9223372036854775807LL
# define LZO_INT_MIN (-1LL - LZO_INT_MAX)
-# elif defined(LZO_ABI_IP32L64) /* MIPS R5900 */
+# elif (LZO_ABI_IP32L64) /* MIPS R5900 */
typedef unsigned int lzo_uint;
typedef int lzo_int;
+# define LZO_SIZEOF_LZO_UINT LZO_SIZEOF_INT
# define LZO_UINT_MAX UINT_MAX
# define LZO_INT_MAX INT_MAX
# define LZO_INT_MIN INT_MIN
# elif (ULONG_MAX >= LZO_0xffffffffL)
typedef unsigned long lzo_uint;
typedef long lzo_int;
+# define LZO_SIZEOF_LZO_UINT LZO_SIZEOF_LONG
# define LZO_UINT_MAX ULONG_MAX
# define LZO_INT_MAX LONG_MAX
# define LZO_INT_MIN LONG_MIN
@@ -141,63 +121,22 @@ extern "C" {
# endif
#endif
-/* Integral types with 32 bits or more. */
-#if !defined(LZO_UINT32_MAX)
-# if (UINT_MAX >= LZO_0xffffffffL)
- typedef unsigned int lzo_uint32;
- typedef int lzo_int32;
-# define LZO_UINT32_MAX UINT_MAX
-# define LZO_INT32_MAX INT_MAX
-# define LZO_INT32_MIN INT_MIN
-# elif (ULONG_MAX >= LZO_0xffffffffL)
- typedef unsigned long lzo_uint32;
- typedef long lzo_int32;
-# define LZO_UINT32_MAX ULONG_MAX
-# define LZO_INT32_MAX LONG_MAX
-# define LZO_INT32_MIN LONG_MIN
-# else
-# error "lzo_uint32"
-# endif
-#endif
-
-/* Integral types with exactly 64 bits. */
-#if !defined(LZO_UINT64_MAX)
-# if (LZO_UINT_MAX >= LZO_0xffffffffL)
-# if ((((LZO_UINT_MAX) >> 31) >> 31) == 3)
-# define lzo_uint64 lzo_uint
-# define lzo_int64 lzo_int
-# define LZO_UINT64_MAX LZO_UINT_MAX
-# define LZO_INT64_MAX LZO_INT_MAX
-# define LZO_INT64_MIN LZO_INT_MIN
-# endif
-# elif (ULONG_MAX >= LZO_0xffffffffL)
-# if ((((ULONG_MAX) >> 31) >> 31) == 3)
- typedef unsigned long lzo_uint64;
- typedef long lzo_int64;
-# define LZO_UINT64_MAX ULONG_MAX
-# define LZO_INT64_MAX LONG_MAX
-# define LZO_INT64_MIN LONG_MIN
-# endif
-# endif
-#endif
-
-/* The larger type of lzo_uint and lzo_uint32. */
-#if (LZO_UINT_MAX >= LZO_UINT32_MAX)
+/* The larger type of lzo_uint and lzo_uint32_t. */
+#if (LZO_SIZEOF_LZO_UINT >= 4)
# define lzo_xint lzo_uint
#else
-# define lzo_xint lzo_uint32
+# define lzo_xint lzo_uint32_t
#endif
-/* Memory model that allows to access memory at offsets of lzo_uint. */
-#if !defined(__LZO_MMODEL)
-# if (LZO_UINT_MAX <= UINT_MAX)
-# define __LZO_MMODEL /*empty*/
-# elif defined(LZO_HAVE_MM_HUGE_PTR)
-# define __LZO_MMODEL_HUGE 1
-# define __LZO_MMODEL __huge
-# else
-# define __LZO_MMODEL /*empty*/
-# endif
+typedef int lzo_bool;
+
+/* sanity checks */
+LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_uint) == LZO_SIZEOF_LZO_UINT)
+LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_xint) >= sizeof(lzo_uint))
+LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_xint) >= sizeof(lzo_uint32_t))
+
+#ifndef __LZO_MMODEL
+#define __LZO_MMODEL /*empty*/
#endif
/* no typedef here because of const-pointer issues */
@@ -206,21 +145,52 @@ extern "C" {
#define lzo_voidp void __LZO_MMODEL *
#define lzo_shortp short __LZO_MMODEL *
#define lzo_ushortp unsigned short __LZO_MMODEL *
-#define lzo_uint32p lzo_uint32 __LZO_MMODEL *
-#define lzo_int32p lzo_int32 __LZO_MMODEL *
-#if defined(LZO_UINT64_MAX)
-#define lzo_uint64p lzo_uint64 __LZO_MMODEL *
-#define lzo_int64p lzo_int64 __LZO_MMODEL *
-#endif
-#define lzo_uintp lzo_uint __LZO_MMODEL *
#define lzo_intp lzo_int __LZO_MMODEL *
+#define lzo_uintp lzo_uint __LZO_MMODEL *
#define lzo_xintp lzo_xint __LZO_MMODEL *
#define lzo_voidpp lzo_voidp __LZO_MMODEL *
#define lzo_bytepp lzo_bytep __LZO_MMODEL *
-/* deprecated - use 'lzo_bytep' instead of 'lzo_byte *' */
-#define lzo_byte unsigned char __LZO_MMODEL
-typedef int lzo_bool;
+#define lzo_int8_tp lzo_int8_t __LZO_MMODEL *
+#define lzo_uint8_tp lzo_uint8_t __LZO_MMODEL *
+#define lzo_int16_tp lzo_int16_t __LZO_MMODEL *
+#define lzo_uint16_tp lzo_uint16_t __LZO_MMODEL *
+#define lzo_int32_tp lzo_int32_t __LZO_MMODEL *
+#define lzo_uint32_tp lzo_uint32_t __LZO_MMODEL *
+#if defined(lzo_int64_t)
+#define lzo_int64_tp lzo_int64_t __LZO_MMODEL *
+#define lzo_uint64_tp lzo_uint64_t __LZO_MMODEL *
+#endif
+
+/* Older LZO versions used to support ancient systems and memory models
+ * like 16-bit MSDOS with __huge pointers and Cray PVP, but these
+ * obsolete configurations are not supported any longer.
+ */
+#if defined(__LZO_MMODEL_HUGE)
+#error "__LZO_MMODEL_HUGE is unsupported"
+#endif
+#if (LZO_MM_PVP)
+#error "LZO_MM_PVP is unsupported"
+#endif
+#if (LZO_SIZEOF_INT < 4)
+#error "LZO_SIZEOF_INT < 4 is unsupported"
+#endif
+#if (__LZO_UINTPTR_T_IS_POINTER)
+#error "__LZO_UINTPTR_T_IS_POINTER is unsupported"
+#endif
+LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(int) >= 4)
+LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_uint) >= 4)
+/* Strange configurations where sizeof(lzo_uint) != sizeof(size_t) should
+ * work but have not received much testing lately, so be strict here.
+ */
+LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_uint) == sizeof(size_t))
+LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_uint) == sizeof(ptrdiff_t))
+LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_uint) == sizeof(lzo_uintptr_t))
+LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(void *) == sizeof(lzo_uintptr_t))
+LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(char *) == sizeof(lzo_uintptr_t))
+LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(long *) == sizeof(lzo_uintptr_t))
+LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(void *) == sizeof(lzo_voidp))
+LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(char *) == sizeof(lzo_bytep))
/***********************************************************************
@@ -315,7 +285,7 @@ struct lzo_callback_t
/* a progress indicator callback function (set to 0 to disable) */
lzo_progress_func_t nprogress;
- /* NOTE: the first parameter "self" of the nalloc/nfree/nprogress
+ /* INFO: the first parameter "self" of the nalloc/nfree/nprogress
* callbacks points back to this struct, so you are free to store
* some extra info in the following variables. */
lzo_voidp user1;
@@ -343,6 +313,9 @@ struct lzo_callback_t
#define LZO_E_INPUT_NOT_CONSUMED (-8)
#define LZO_E_NOT_YET_IMPLEMENTED (-9) /* [not used right now] */
#define LZO_E_INVALID_ARGUMENT (-10)
+#define LZO_E_INVALID_ALIGNMENT (-11) /* pointer argument is not properly aligned */
+#define LZO_E_OUTPUT_NOT_CONSUMED (-12)
+#define LZO_E_INTERNAL_ERROR (-99)
#ifndef lzo_sizeof_dict_t
@@ -356,7 +329,7 @@ struct lzo_callback_t
* compiler's view of various types are consistent.
*/
#define lzo_init() __lzo_init_v2(LZO_VERSION,(int)sizeof(short),(int)sizeof(int),\
- (int)sizeof(long),(int)sizeof(lzo_uint32),(int)sizeof(lzo_uint),\
+ (int)sizeof(long),(int)sizeof(lzo_uint32_t),(int)sizeof(lzo_uint),\
(int)lzo_sizeof_dict_t,(int)sizeof(char *),(int)sizeof(lzo_voidp),\
(int)sizeof(lzo_callback_t))
LZO_EXTERN(int) __lzo_init_v2(unsigned,int,int,int,int,int,int,int,int,int);
@@ -379,18 +352,22 @@ LZO_EXTERN(lzo_voidp)
lzo_memset(lzo_voidp buf, int c, lzo_uint len);
/* checksum functions */
-LZO_EXTERN(lzo_uint32)
- lzo_adler32(lzo_uint32 c, const lzo_bytep buf, lzo_uint len);
-LZO_EXTERN(lzo_uint32)
- lzo_crc32(lzo_uint32 c, const lzo_bytep buf, lzo_uint len);
-LZO_EXTERN(const lzo_uint32p)
+LZO_EXTERN(lzo_uint32_t)
+ lzo_adler32(lzo_uint32_t c, const lzo_bytep buf, lzo_uint len);
+LZO_EXTERN(lzo_uint32_t)
+ lzo_crc32(lzo_uint32_t c, const lzo_bytep buf, lzo_uint len);
+LZO_EXTERN(const lzo_uint32_tp)
lzo_get_crc32_table(void);
/* misc. */
LZO_EXTERN(int) _lzo_config_check(void);
-typedef union { lzo_bytep p; lzo_uint u; } __lzo_pu_u;
-typedef union { lzo_bytep p; lzo_uint32 u32; } __lzo_pu32_u;
-typedef union { void *vp; lzo_bytep bp; lzo_uint u; lzo_uint32 u32; unsigned long l; } lzo_align_t;
+typedef union {
+ lzo_voidp a00; lzo_bytep a01; lzo_uint a02; lzo_xint a03; lzo_uintptr_t a04;
+ void *a05; unsigned char *a06; unsigned long a07; size_t a08; ptrdiff_t a09;
+#if defined(lzo_int64_t)
+ lzo_uint64_t a10;
+#endif
+} lzo_align_t;
/* align a char pointer on a boundary that is a multiple of 'size' */
LZO_EXTERN(unsigned) __lzo_align_gap(const lzo_voidp p, lzo_uint size);
@@ -399,9 +376,30 @@ LZO_EXTERN(unsigned) __lzo_align_gap(const lzo_voidp p, lzo_uint size);
/***********************************************************************
-// deprecated macros - only for backward compatibility with LZO v1.xx
+// deprecated macros - only for backward compatibility
************************************************************************/
+/* deprecated - use 'lzo_bytep' instead of 'lzo_byte *' */
+#define lzo_byte unsigned char
+/* deprecated type names */
+#define lzo_int32 lzo_int32_t
+#define lzo_uint32 lzo_uint32_t
+#define lzo_int32p lzo_int32_t __LZO_MMODEL *
+#define lzo_uint32p lzo_uint32_t __LZO_MMODEL *
+#define LZO_INT32_MAX LZO_INT32_C(2147483647)
+#define LZO_UINT32_MAX LZO_UINT32_C(4294967295)
+#if defined(lzo_int64_t)
+#define lzo_int64 lzo_int64_t
+#define lzo_uint64 lzo_uint64_t
+#define lzo_int64p lzo_int64_t __LZO_MMODEL *
+#define lzo_uint64p lzo_uint64_t __LZO_MMODEL *
+#define LZO_INT64_MAX LZO_INT64_C(9223372036854775807)
+#define LZO_UINT64_MAX LZO_UINT64_C(18446744073709551615)
+#endif
+/* deprecated types */
+typedef union { lzo_bytep a; lzo_uint b; } __lzo_pu_u;
+typedef union { lzo_bytep a; lzo_uint32_t b; } __lzo_pu32_u;
+
#if defined(LZO_CFG_COMPAT)
#define __LZOCONF_H 1
@@ -443,4 +441,4 @@ LZO_EXTERN(unsigned) __lzo_align_gap(const lzo_voidp p, lzo_uint size);
#endif /* already included */
-/* vim:set ts=4 et: */
+/* vim:set ts=4 sw=4 et: */
diff --git a/extern/lzo/minilzo/lzodefs.h b/extern/lzo/minilzo/lzodefs.h
index 0e40e332a8d..f4ae9487ebe 100644
--- a/extern/lzo/minilzo/lzodefs.h
+++ b/extern/lzo/minilzo/lzodefs.h
@@ -2,22 +2,7 @@
This file is part of the LZO real-time data compression library.
- Copyright (C) 2011 Markus Franz Xaver Johannes Oberhumer
- Copyright (C) 2010 Markus Franz Xaver Johannes Oberhumer
- Copyright (C) 2009 Markus Franz Xaver Johannes Oberhumer
- Copyright (C) 2008 Markus Franz Xaver Johannes Oberhumer
- Copyright (C) 2007 Markus Franz Xaver Johannes Oberhumer
- Copyright (C) 2006 Markus Franz Xaver Johannes Oberhumer
- Copyright (C) 2005 Markus Franz Xaver Johannes Oberhumer
- Copyright (C) 2004 Markus Franz Xaver Johannes Oberhumer
- Copyright (C) 2003 Markus Franz Xaver Johannes Oberhumer
- Copyright (C) 2002 Markus Franz Xaver Johannes Oberhumer
- Copyright (C) 2001 Markus Franz Xaver Johannes Oberhumer
- Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer
- Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer
- Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer
- Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer
- Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1996-2014 Markus Franz Xaver Johannes Oberhumer
All Rights Reserved.
The LZO library is free software; you can redistribute it and/or
@@ -47,12 +32,6 @@
#if defined(__CYGWIN32__) && !defined(__CYGWIN__)
# define __CYGWIN__ __CYGWIN32__
#endif
-#if defined(__IBMCPP__) && !defined(__IBMC__)
-# define __IBMC__ __IBMCPP__
-#endif
-#if defined(__ICL) && defined(_WIN32) && !defined(__INTEL_COMPILER)
-# define __INTEL_COMPILER __ICL
-#endif
#if 1 && defined(__INTERIX) && defined(__GNUC__) && !defined(_ALL_SOURCE)
# define _ALL_SOURCE 1
#endif
@@ -61,19 +40,30 @@
# define __LONG_MAX__ 9223372036854775807L
# endif
#endif
-#if defined(__INTEL_COMPILER) && defined(__linux__)
+#if !defined(LZO_CFG_NO_DISABLE_WUNDEF)
+#if defined(__ARMCC_VERSION)
+# pragma diag_suppress 193
+#elif defined(__clang__) && defined(__clang_minor__)
+# pragma clang diagnostic ignored "-Wundef"
+#elif defined(__INTEL_COMPILER)
# pragma warning(disable: 193)
-#endif
-#if defined(__KEIL__) && defined(__C166__)
-# pragma warning disable = 322
-#elif 0 && defined(__C251__)
+#elif defined(__KEIL__) && defined(__C166__)
# pragma warning disable = 322
-#endif
-#if defined(_MSC_VER) && !defined(__INTEL_COMPILER) && !defined(__MWERKS__)
-# if (_MSC_VER >= 1300)
+#elif defined(__GNUC__) && defined(__GNUC_MINOR__) && !defined(__PATHSCALE__)
+# if ((__GNUC__-0) >= 5 || ((__GNUC__-0) == 4 && (__GNUC_MINOR__-0) >= 2))
+# pragma GCC diagnostic ignored "-Wundef"
+# endif
+#elif defined(_MSC_VER) && !defined(__clang__) && !defined(__INTEL_COMPILER) && !defined(__MWERKS__)
+# if ((_MSC_VER-0) >= 1300)
# pragma warning(disable: 4668)
# endif
#endif
+#endif
+#if 0 && defined(__POCC__) && defined(_WIN32)
+# if (__POCC__ >= 400)
+# pragma warn(disable: 2216)
+# endif
+#endif
#if 0 && defined(__WATCOMC__)
# if (__WATCOMC__ >= 1050) && (__WATCOMC__ < 1060)
# pragma warning 203 9
@@ -82,13 +72,29 @@
#if defined(__BORLANDC__) && defined(__MSDOS__) && !defined(__FLAT__)
# pragma option -h
#endif
+#if !(LZO_CFG_NO_DISABLE_WCRTNONSTDC)
+#ifndef _CRT_NONSTDC_NO_DEPRECATE
+#define _CRT_NONSTDC_NO_DEPRECATE 1
+#endif
+#ifndef _CRT_NONSTDC_NO_WARNINGS
+#define _CRT_NONSTDC_NO_WARNINGS 1
+#endif
+#ifndef _CRT_SECURE_NO_DEPRECATE
+#define _CRT_SECURE_NO_DEPRECATE 1
+#endif
+#ifndef _CRT_SECURE_NO_WARNINGS
+#define _CRT_SECURE_NO_WARNINGS 1
+#endif
+#endif
#if 0
-#define LZO_0xffffL 0xfffful
-#define LZO_0xffffffffL 0xfffffffful
+#define LZO_0xffffUL 0xfffful
+#define LZO_0xffffffffUL 0xfffffffful
#else
-#define LZO_0xffffL 65535ul
-#define LZO_0xffffffffL 4294967295ul
+#define LZO_0xffffUL 65535ul
+#define LZO_0xffffffffUL 4294967295ul
#endif
+#define LZO_0xffffL LZO_0xffffUL
+#define LZO_0xffffffffL LZO_0xffffffffUL
#if (LZO_0xffffL == LZO_0xffffffffL)
# error "your preprocessor is broken 1"
#endif
@@ -103,6 +109,13 @@
# error "your preprocessor is broken 4"
#endif
#endif
+#if defined(__COUNTER__)
+# ifndef LZO_CFG_USE_COUNTER
+# define LZO_CFG_USE_COUNTER 1
+# endif
+#else
+# undef LZO_CFG_USE_COUNTER
+#endif
#if (UINT_MAX == LZO_0xffffL)
#if defined(__ZTC__) && defined(__I86__) && !defined(__OS2__)
# if !defined(MSDOS)
@@ -233,14 +246,31 @@
#endif
#define LZO_PP_STRINGIZE(x) #x
#define LZO_PP_MACRO_EXPAND(x) LZO_PP_STRINGIZE(x)
+#define LZO_PP_CONCAT0() /*empty*/
+#define LZO_PP_CONCAT1(a) a
#define LZO_PP_CONCAT2(a,b) a ## b
#define LZO_PP_CONCAT3(a,b,c) a ## b ## c
#define LZO_PP_CONCAT4(a,b,c,d) a ## b ## c ## d
#define LZO_PP_CONCAT5(a,b,c,d,e) a ## b ## c ## d ## e
+#define LZO_PP_CONCAT6(a,b,c,d,e,f) a ## b ## c ## d ## e ## f
+#define LZO_PP_CONCAT7(a,b,c,d,e,f,g) a ## b ## c ## d ## e ## f ## g
+#define LZO_PP_ECONCAT0() LZO_PP_CONCAT0()
+#define LZO_PP_ECONCAT1(a) LZO_PP_CONCAT1(a)
#define LZO_PP_ECONCAT2(a,b) LZO_PP_CONCAT2(a,b)
#define LZO_PP_ECONCAT3(a,b,c) LZO_PP_CONCAT3(a,b,c)
#define LZO_PP_ECONCAT4(a,b,c,d) LZO_PP_CONCAT4(a,b,c,d)
#define LZO_PP_ECONCAT5(a,b,c,d,e) LZO_PP_CONCAT5(a,b,c,d,e)
+#define LZO_PP_ECONCAT6(a,b,c,d,e,f) LZO_PP_CONCAT6(a,b,c,d,e,f)
+#define LZO_PP_ECONCAT7(a,b,c,d,e,f,g) LZO_PP_CONCAT7(a,b,c,d,e,f,g)
+#define LZO_PP_EMPTY /*empty*/
+#define LZO_PP_EMPTY0() /*empty*/
+#define LZO_PP_EMPTY1(a) /*empty*/
+#define LZO_PP_EMPTY2(a,b) /*empty*/
+#define LZO_PP_EMPTY3(a,b,c) /*empty*/
+#define LZO_PP_EMPTY4(a,b,c,d) /*empty*/
+#define LZO_PP_EMPTY5(a,b,c,d,e) /*empty*/
+#define LZO_PP_EMPTY6(a,b,c,d,e,f) /*empty*/
+#define LZO_PP_EMPTY7(a,b,c,d,e,f,g) /*empty*/
#if 1
#define LZO_CPP_STRINGIZE(x) #x
#define LZO_CPP_MACRO_EXPAND(x) LZO_CPP_STRINGIZE(x)
@@ -248,12 +278,16 @@
#define LZO_CPP_CONCAT3(a,b,c) a ## b ## c
#define LZO_CPP_CONCAT4(a,b,c,d) a ## b ## c ## d
#define LZO_CPP_CONCAT5(a,b,c,d,e) a ## b ## c ## d ## e
+#define LZO_CPP_CONCAT6(a,b,c,d,e,f) a ## b ## c ## d ## e ## f
+#define LZO_CPP_CONCAT7(a,b,c,d,e,f,g) a ## b ## c ## d ## e ## f ## g
#define LZO_CPP_ECONCAT2(a,b) LZO_CPP_CONCAT2(a,b)
#define LZO_CPP_ECONCAT3(a,b,c) LZO_CPP_CONCAT3(a,b,c)
#define LZO_CPP_ECONCAT4(a,b,c,d) LZO_CPP_CONCAT4(a,b,c,d)
#define LZO_CPP_ECONCAT5(a,b,c,d,e) LZO_CPP_CONCAT5(a,b,c,d,e)
+#define LZO_CPP_ECONCAT6(a,b,c,d,e,f) LZO_CPP_CONCAT6(a,b,c,d,e,f)
+#define LZO_CPP_ECONCAT7(a,b,c,d,e,f,g) LZO_CPP_CONCAT7(a,b,c,d,e,f,g)
#endif
-#define __LZO_MASK_GEN(o,b) (((((o) << ((b)-1)) - (o)) << 1) + (o))
+#define __LZO_MASK_GEN(o,b) (((((o) << ((b)-!!(b))) - (o)) << 1) + (o)*!!(b))
#if 1 && defined(__cplusplus)
# if !defined(__STDC_CONSTANT_MACROS)
# define __STDC_CONSTANT_MACROS 1
@@ -263,9 +297,13 @@
# endif
#endif
#if defined(__cplusplus)
-# define LZO_EXTERN_C extern "C"
+# define LZO_EXTERN_C extern "C"
+# define LZO_EXTERN_C_BEGIN extern "C" {
+# define LZO_EXTERN_C_END }
#else
-# define LZO_EXTERN_C extern
+# define LZO_EXTERN_C extern
+# define LZO_EXTERN_C_BEGIN /*empty*/
+# define LZO_EXTERN_C_END /*empty*/
#endif
#if !defined(__LZO_OS_OVERRIDE)
#if (LZO_OS_FREESTANDING)
@@ -366,12 +404,12 @@
#elif defined(__VMS)
# define LZO_OS_VMS 1
# define LZO_INFO_OS "vms"
-#elif ((defined(__mips__) && defined(__R5900__)) || defined(__MIPS_PSX2__))
+#elif (defined(__mips__) && defined(__R5900__)) || defined(__MIPS_PSX2__)
# define LZO_OS_CONSOLE 1
# define LZO_OS_CONSOLE_PS2 1
# define LZO_INFO_OS "console"
# define LZO_INFO_OS_CONSOLE "ps2"
-#elif (defined(__mips__) && defined(__psp__))
+#elif defined(__mips__) && defined(__psp__)
# define LZO_OS_CONSOLE 1
# define LZO_OS_CONSOLE_PSP 1
# define LZO_INFO_OS "console"
@@ -399,9 +437,18 @@
# elif defined(__linux__) || defined(__linux) || defined(__LINUX__)
# define LZO_OS_POSIX_LINUX 1
# define LZO_INFO_OS_POSIX "linux"
-# elif defined(__APPLE__) || defined(__MACOS__)
-# define LZO_OS_POSIX_MACOSX 1
-# define LZO_INFO_OS_POSIX "macosx"
+# elif defined(__APPLE__) && defined(__MACH__)
+# if ((__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__-0) >= 20000)
+# define LZO_OS_POSIX_DARWIN 1040
+# define LZO_INFO_OS_POSIX "darwin_iphone"
+# elif ((__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__-0) >= 1040)
+# define LZO_OS_POSIX_DARWIN __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__
+# define LZO_INFO_OS_POSIX "darwin"
+# else
+# define LZO_OS_POSIX_DARWIN 1
+# define LZO_INFO_OS_POSIX "darwin"
+# endif
+# define LZO_OS_POSIX_MACOSX LZO_OS_POSIX_DARWIN
# elif defined(__minix__) || defined(__minix)
# define LZO_OS_POSIX_MINIX 1
# define LZO_INFO_OS_POSIX "minix"
@@ -436,18 +483,18 @@
#endif
#if (LZO_OS_DOS16 || LZO_OS_OS216 || LZO_OS_WIN16)
# if (UINT_MAX != LZO_0xffffL)
-# error "this should not happen"
+# error "unexpected configuration - check your compiler defines"
# endif
# if (ULONG_MAX != LZO_0xffffffffL)
-# error "this should not happen"
+# error "unexpected configuration - check your compiler defines"
# endif
#endif
#if (LZO_OS_DOS32 || LZO_OS_OS2 || LZO_OS_WIN32 || LZO_OS_WIN64)
# if (UINT_MAX != LZO_0xffffffffL)
-# error "this should not happen"
+# error "unexpected configuration - check your compiler defines"
# endif
# if (ULONG_MAX != LZO_0xffffffffL)
-# error "this should not happen"
+# error "unexpected configuration - check your compiler defines"
# endif
#endif
#if defined(CIL) && defined(_GNUCC) && defined(__GNUC__)
@@ -463,59 +510,65 @@
# define LZO_INFO_CC "sdcc"
# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(SDCC)
#elif defined(__PATHSCALE__) && defined(__PATHCC_PATCHLEVEL__)
-# define LZO_CC_PATHSCALE (__PATHCC__ * 0x10000L + __PATHCC_MINOR__ * 0x100 + __PATHCC_PATCHLEVEL__)
+# define LZO_CC_PATHSCALE (__PATHCC__ * 0x10000L + (__PATHCC_MINOR__-0) * 0x100 + (__PATHCC_PATCHLEVEL__-0))
# define LZO_INFO_CC "Pathscale C"
# define LZO_INFO_CCVER __PATHSCALE__
-#elif defined(__INTEL_COMPILER)
-# define LZO_CC_INTELC 1
+# if defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__VERSION__)
+# define LZO_CC_PATHSCALE_GNUC (__GNUC__ * 0x10000L + (__GNUC_MINOR__-0) * 0x100 + (__GNUC_PATCHLEVEL__-0))
+# endif
+#elif defined(__INTEL_COMPILER) && ((__INTEL_COMPILER-0) > 0)
+# define LZO_CC_INTELC __INTEL_COMPILER
# define LZO_INFO_CC "Intel C"
# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__INTEL_COMPILER)
-# if defined(_WIN32) || defined(_WIN64)
-# define LZO_CC_SYNTAX_MSC 1
-# else
-# define LZO_CC_SYNTAX_GNUC 1
+# if defined(_MSC_VER) && ((_MSC_VER-0) > 0)
+# define LZO_CC_INTELC_MSC _MSC_VER
+# elif defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__VERSION__)
+# define LZO_CC_INTELC_GNUC (__GNUC__ * 0x10000L + (__GNUC_MINOR__-0) * 0x100 + (__GNUC_PATCHLEVEL__-0))
# endif
#elif defined(__POCC__) && defined(_WIN32)
# define LZO_CC_PELLESC 1
# define LZO_INFO_CC "Pelles C"
# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__POCC__)
-#elif defined(__clang__) && defined(__llvm__) && defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__VERSION__)
+#elif defined(__ARMCC_VERSION) && defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__VERSION__)
# if defined(__GNUC_PATCHLEVEL__)
-# define LZO_CC_CLANG_GNUC (__GNUC__ * 0x10000L + __GNUC_MINOR__ * 0x100 + __GNUC_PATCHLEVEL__)
+# define LZO_CC_ARMCC_GNUC (__GNUC__ * 0x10000L + (__GNUC_MINOR__-0) * 0x100 + (__GNUC_PATCHLEVEL__-0))
# else
-# define LZO_CC_CLANG_GNUC (__GNUC__ * 0x10000L + __GNUC_MINOR__ * 0x100)
+# define LZO_CC_ARMCC_GNUC (__GNUC__ * 0x10000L + (__GNUC_MINOR__-0) * 0x100)
# endif
+# define LZO_CC_ARMCC __ARMCC_VERSION
+# define LZO_INFO_CC "ARM C Compiler"
+# define LZO_INFO_CCVER __VERSION__
+#elif defined(__clang__) && defined(__llvm__) && defined(__VERSION__)
# if defined(__clang_major__) && defined(__clang_minor__) && defined(__clang_patchlevel__)
-# define LZO_CC_CLANG_CLANG (__clang_major__ * 0x10000L + __clang_minor__ * 0x100 + __clang_patchlevel__)
+# define LZO_CC_CLANG (__clang_major__ * 0x10000L + (__clang_minor__-0) * 0x100 + (__clang_patchlevel__-0))
# else
-# define LZO_CC_CLANG_CLANG 0x010000L
+# define LZO_CC_CLANG 0x010000L
+# endif
+# if defined(_MSC_VER) && ((_MSC_VER-0) > 0)
+# define LZO_CC_CLANG_MSC _MSC_VER
+# elif defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__VERSION__)
+# define LZO_CC_CLANG_GNUC (__GNUC__ * 0x10000L + (__GNUC_MINOR__-0) * 0x100 + (__GNUC_PATCHLEVEL__-0))
# endif
-# define LZO_CC_CLANG LZO_CC_CLANG_GNUC
# define LZO_INFO_CC "clang"
# define LZO_INFO_CCVER __VERSION__
#elif defined(__llvm__) && defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__VERSION__)
# if defined(__GNUC_PATCHLEVEL__)
-# define LZO_CC_LLVM_GNUC (__GNUC__ * 0x10000L + __GNUC_MINOR__ * 0x100 + __GNUC_PATCHLEVEL__)
+# define LZO_CC_LLVM_GNUC (__GNUC__ * 0x10000L + (__GNUC_MINOR__-0) * 0x100 + (__GNUC_PATCHLEVEL__-0))
# else
-# define LZO_CC_LLVM_GNUC (__GNUC__ * 0x10000L + __GNUC_MINOR__ * 0x100)
+# define LZO_CC_LLVM_GNUC (__GNUC__ * 0x10000L + (__GNUC_MINOR__-0) * 0x100)
# endif
# define LZO_CC_LLVM LZO_CC_LLVM_GNUC
# define LZO_INFO_CC "llvm-gcc"
# define LZO_INFO_CCVER __VERSION__
-#elif defined(__GNUC__) && defined(__VERSION__)
-# if defined(__GNUC_MINOR__) && defined(__GNUC_PATCHLEVEL__)
-# define LZO_CC_GNUC (__GNUC__ * 0x10000L + __GNUC_MINOR__ * 0x100 + __GNUC_PATCHLEVEL__)
-# elif defined(__GNUC_MINOR__)
-# define LZO_CC_GNUC (__GNUC__ * 0x10000L + __GNUC_MINOR__ * 0x100)
-# else
-# define LZO_CC_GNUC (__GNUC__ * 0x10000L)
-# endif
-# define LZO_INFO_CC "gcc"
-# define LZO_INFO_CCVER __VERSION__
#elif defined(__ACK__) && defined(_ACK)
# define LZO_CC_ACK 1
# define LZO_INFO_CC "Amsterdam Compiler Kit C"
# define LZO_INFO_CCVER "unknown"
+#elif defined(__ARMCC_VERSION) && !defined(__GNUC__)
+# define LZO_CC_ARMCC __ARMCC_VERSION
+# define LZO_CC_ARMCC_ARMCC __ARMCC_VERSION
+# define LZO_INFO_CC "ARM C Compiler"
+# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__ARMCC_VERSION)
#elif defined(__AZTEC_C__)
# define LZO_CC_AZTECC 1
# define LZO_INFO_CC "Aztec C"
@@ -540,10 +593,23 @@
# define LZO_CC_DECC 1
# define LZO_INFO_CC "DEC C"
# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__DECC)
+#elif (defined(__ghs) || defined(__ghs__)) && defined(__GHS_VERSION_NUMBER) && ((__GHS_VERSION_NUMBER-0) > 0)
+# define LZO_CC_GHS 1
+# define LZO_INFO_CC "Green Hills C"
+# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__GHS_VERSION_NUMBER)
+# if defined(_MSC_VER) && ((_MSC_VER-0) > 0)
+# define LZO_CC_GHS_MSC _MSC_VER
+# elif defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__VERSION__)
+# define LZO_CC_GHS_GNUC (__GNUC__ * 0x10000L + (__GNUC_MINOR__-0) * 0x100 + (__GNUC_PATCHLEVEL__-0))
+# endif
#elif defined(__HIGHC__)
# define LZO_CC_HIGHC 1
# define LZO_INFO_CC "MetaWare High C"
# define LZO_INFO_CCVER "unknown"
+#elif defined(__HP_aCC) && ((__HP_aCC-0) > 0)
+# define LZO_CC_HPACC __HP_aCC
+# define LZO_INFO_CC "HP aCC"
+# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__HP_aCC)
#elif defined(__IAR_SYSTEMS_ICC__)
# define LZO_CC_IARC 1
# define LZO_INFO_CC "IAR C"
@@ -552,10 +618,14 @@
# else
# define LZO_INFO_CCVER "unknown"
# endif
-#elif defined(__IBMC__)
-# define LZO_CC_IBMC 1
+#elif defined(__IBMC__) && ((__IBMC__-0) > 0)
+# define LZO_CC_IBMC __IBMC__
# define LZO_INFO_CC "IBM C"
# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__IBMC__)
+#elif defined(__IBMCPP__) && ((__IBMCPP__-0) > 0)
+# define LZO_CC_IBMC __IBMCPP__
+# define LZO_INFO_CC "IBM C"
+# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__IBMCPP__)
#elif defined(__KEIL__) && defined(__C166__)
# define LZO_CC_KEILC 1
# define LZO_INFO_CC "Keil C"
@@ -572,16 +642,8 @@
# else
# define LZO_INFO_CCVER "unknown"
# endif
-#elif defined(_MSC_VER)
-# define LZO_CC_MSC 1
-# define LZO_INFO_CC "Microsoft C"
-# if defined(_MSC_FULL_VER)
-# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(_MSC_VER) "." LZO_PP_MACRO_EXPAND(_MSC_FULL_VER)
-# else
-# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(_MSC_VER)
-# endif
-#elif defined(__MWERKS__)
-# define LZO_CC_MWERKS 1
+#elif defined(__MWERKS__) && ((__MWERKS__-0) > 0)
+# define LZO_CC_MWERKS __MWERKS__
# define LZO_INFO_CC "Metrowerks C"
# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__MWERKS__)
#elif (defined(__NDPC__) || defined(__NDPX__)) && defined(__i386)
@@ -592,6 +654,15 @@
# define LZO_CC_PACIFICC 1
# define LZO_INFO_CC "Pacific C"
# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__PACIFIC__)
+#elif defined(__PGI) && defined(__PGIC__) && defined(__PGIC_MINOR__)
+# if defined(__PGIC_PATCHLEVEL__)
+# define LZO_CC_PGI (__PGIC__ * 0x10000L + (__PGIC_MINOR__-0) * 0x100 + (__PGIC_PATCHLEVEL__-0))
+# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__PGIC__) "." LZO_PP_MACRO_EXPAND(__PGIC_MINOR__) "." LZO_PP_MACRO_EXPAND(__PGIC_PATCHLEVEL__)
+# else
+# define LZO_CC_PGI (__PGIC__ * 0x10000L + (__PGIC_MINOR__-0) * 0x100)
+# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__PGIC__) "." LZO_PP_MACRO_EXPAND(__PGIC_MINOR__) ".0"
+# endif
+# define LZO_INFO_CC "Portland Group PGI C"
#elif defined(__PGI) && (defined(__linux__) || defined(__WIN32__))
# define LZO_CC_PGI 1
# define LZO_INFO_CC "Portland Group PGI C"
@@ -606,7 +677,7 @@
# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__SC__)
#elif defined(__SUNPRO_C)
# define LZO_INFO_CC "SunPro C"
-# if ((__SUNPRO_C)+0 > 0)
+# if ((__SUNPRO_C-0) > 0)
# define LZO_CC_SUNPROC __SUNPRO_C
# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__SUNPRO_C)
# else
@@ -615,7 +686,7 @@
# endif
#elif defined(__SUNPRO_CC)
# define LZO_INFO_CC "SunPro C"
-# if ((__SUNPRO_CC)+0 > 0)
+# if ((__SUNPRO_CC-0) > 0)
# define LZO_CC_SUNPROC __SUNPRO_CC
# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__SUNPRO_CC)
# else
@@ -641,16 +712,46 @@
#elif defined(__ZTC__)
# define LZO_CC_ZORTECHC 1
# define LZO_INFO_CC "Zortech C"
-# if (__ZTC__ == 0x310)
+# if ((__ZTC__-0) == 0x310)
# define LZO_INFO_CCVER "0x310"
# else
# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__ZTC__)
# endif
+#elif defined(__GNUC__) && defined(__VERSION__)
+# if defined(__GNUC_MINOR__) && defined(__GNUC_PATCHLEVEL__)
+# define LZO_CC_GNUC (__GNUC__ * 0x10000L + (__GNUC_MINOR__-0) * 0x100 + (__GNUC_PATCHLEVEL__-0))
+# elif defined(__GNUC_MINOR__)
+# define LZO_CC_GNUC (__GNUC__ * 0x10000L + (__GNUC_MINOR__-0) * 0x100)
+# else
+# define LZO_CC_GNUC (__GNUC__ * 0x10000L)
+# endif
+# define LZO_INFO_CC "gcc"
+# define LZO_INFO_CCVER __VERSION__
+#elif defined(_MSC_VER) && ((_MSC_VER-0) > 0)
+# define LZO_CC_MSC _MSC_VER
+# define LZO_INFO_CC "Microsoft C"
+# if defined(_MSC_FULL_VER)
+# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(_MSC_VER) "." LZO_PP_MACRO_EXPAND(_MSC_FULL_VER)
+# else
+# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(_MSC_VER)
+# endif
#else
# define LZO_CC_UNKNOWN 1
# define LZO_INFO_CC "unknown"
# define LZO_INFO_CCVER "unknown"
#endif
+#if (LZO_CC_GNUC) && defined(__OPEN64__)
+# if defined(__OPENCC__) && defined(__OPENCC_MINOR__) && defined(__OPENCC_PATCHLEVEL__)
+# define LZO_CC_OPEN64 (__OPENCC__ * 0x10000L + (__OPENCC_MINOR__-0) * 0x100 + (__OPENCC_PATCHLEVEL__-0))
+# define LZO_CC_OPEN64_GNUC LZO_CC_GNUC
+# endif
+#endif
+#if (LZO_CC_GNUC) && defined(__PCC__)
+# if defined(__PCC__) && defined(__PCC_MINOR__) && defined(__PCC_MINORMINOR__)
+# define LZO_CC_PCC (__PCC__ * 0x10000L + (__PCC_MINOR__-0) * 0x100 + (__PCC_MINORMINOR__-0))
+# define LZO_CC_PCC_GNUC LZO_CC_GNUC
+# endif
+#endif
#if 0 && (LZO_CC_MSC && (_MSC_VER >= 1200)) && !defined(_MSC_FULL_VER)
# error "LZO_CC_MSC: _MSC_FULL_VER is not defined"
#endif
@@ -668,8 +769,10 @@
# define LZO_INFO_ARCH "generic"
#elif (LZO_OS_DOS16 || LZO_OS_OS216 || LZO_OS_WIN16)
# define LZO_ARCH_I086 1
-# define LZO_ARCH_IA16 1
# define LZO_INFO_ARCH "i086"
+#elif defined(__aarch64__)
+# define LZO_ARCH_ARM64 1
+# define LZO_INFO_ARCH "arm64"
#elif defined(__alpha__) || defined(__alpha) || defined(_M_ALPHA)
# define LZO_ARCH_ALPHA 1
# define LZO_INFO_ARCH "alpha"
@@ -685,10 +788,10 @@
# define LZO_INFO_ARCH "arm_thumb"
#elif defined(__IAR_SYSTEMS_ICC__) && defined(__ICCARM__)
# define LZO_ARCH_ARM 1
-# if defined(__CPU_MODE__) && ((__CPU_MODE__)+0 == 1)
+# if defined(__CPU_MODE__) && ((__CPU_MODE__-0) == 1)
# define LZO_ARCH_ARM_THUMB 1
# define LZO_INFO_ARCH "arm_thumb"
-# elif defined(__CPU_MODE__) && ((__CPU_MODE__)+0 == 2)
+# elif defined(__CPU_MODE__) && ((__CPU_MODE__-0) == 2)
# define LZO_INFO_ARCH "arm"
# else
# define LZO_INFO_ARCH "arm"
@@ -806,53 +909,147 @@
# error "FIXME - missing define for CPU architecture"
#endif
#if 1 && (LZO_ARCH_UNKNOWN) && (LZO_OS_WIN32)
-# error "FIXME - missing WIN32 define for CPU architecture"
+# error "FIXME - missing LZO_OS_WIN32 define for CPU architecture"
#endif
#if 1 && (LZO_ARCH_UNKNOWN) && (LZO_OS_WIN64)
-# error "FIXME - missing WIN64 define for CPU architecture"
+# error "FIXME - missing LZO_OS_WIN64 define for CPU architecture"
#endif
#if (LZO_OS_OS216 || LZO_OS_WIN16)
# define LZO_ARCH_I086PM 1
-# define LZO_ARCH_IA16PM 1
#elif 1 && (LZO_OS_DOS16 && defined(BLX286))
# define LZO_ARCH_I086PM 1
-# define LZO_ARCH_IA16PM 1
#elif 1 && (LZO_OS_DOS16 && defined(DOSX286))
# define LZO_ARCH_I086PM 1
-# define LZO_ARCH_IA16PM 1
#elif 1 && (LZO_OS_DOS16 && LZO_CC_BORLANDC && defined(__DPMI16__))
# define LZO_ARCH_I086PM 1
-# define LZO_ARCH_IA16PM 1
#endif
-#if (LZO_ARCH_ARM_THUMB) && !(LZO_ARCH_ARM)
-# error "this should not happen"
+#if (LZO_ARCH_AMD64 && !LZO_ARCH_X64)
+# define LZO_ARCH_X64 1
+#elif (!LZO_ARCH_AMD64 && LZO_ARCH_X64) && defined(__LZO_ARCH_OVERRIDE)
+# define LZO_ARCH_AMD64 1
#endif
-#if (LZO_ARCH_I086PM) && !(LZO_ARCH_I086)
-# error "this should not happen"
+#if (LZO_ARCH_ARM64 && !LZO_ARCH_AARCH64)
+# define LZO_ARCH_AARCH64 1
+#elif (!LZO_ARCH_ARM64 && LZO_ARCH_AARCH64) && defined(__LZO_ARCH_OVERRIDE)
+# define LZO_ARCH_ARM64 1
+#endif
+#if (LZO_ARCH_I386 && !LZO_ARCH_X86)
+# define LZO_ARCH_X86 1
+#elif (!LZO_ARCH_I386 && LZO_ARCH_X86) && defined(__LZO_ARCH_OVERRIDE)
+# define LZO_ARCH_I386 1
+#endif
+#if (LZO_ARCH_AMD64 && !LZO_ARCH_X64) || (!LZO_ARCH_AMD64 && LZO_ARCH_X64)
+# error "unexpected configuration - check your compiler defines"
+#endif
+#if (LZO_ARCH_ARM64 && !LZO_ARCH_AARCH64) || (!LZO_ARCH_ARM64 && LZO_ARCH_AARCH64)
+# error "unexpected configuration - check your compiler defines"
+#endif
+#if (LZO_ARCH_I386 && !LZO_ARCH_X86) || (!LZO_ARCH_I386 && LZO_ARCH_X86)
+# error "unexpected configuration - check your compiler defines"
+#endif
+#if (LZO_ARCH_ARM_THUMB && !LZO_ARCH_ARM)
+# error "unexpected configuration - check your compiler defines"
+#endif
+#if (LZO_ARCH_ARM_THUMB1 && !LZO_ARCH_ARM_THUMB)
+# error "unexpected configuration - check your compiler defines"
+#endif
+#if (LZO_ARCH_ARM_THUMB2 && !LZO_ARCH_ARM_THUMB)
+# error "unexpected configuration - check your compiler defines"
+#endif
+#if (LZO_ARCH_ARM_THUMB1 && LZO_ARCH_ARM_THUMB2)
+# error "unexpected configuration - check your compiler defines"
+#endif
+#if (LZO_ARCH_I086PM && !LZO_ARCH_I086)
+# error "unexpected configuration - check your compiler defines"
#endif
#if (LZO_ARCH_I086)
# if (UINT_MAX != LZO_0xffffL)
-# error "this should not happen"
+# error "unexpected configuration - check your compiler defines"
# endif
# if (ULONG_MAX != LZO_0xffffffffL)
-# error "this should not happen"
+# error "unexpected configuration - check your compiler defines"
# endif
#endif
#if (LZO_ARCH_I386)
# if (UINT_MAX != LZO_0xffffL) && defined(__i386_int16__)
-# error "this should not happen"
+# error "unexpected configuration - check your compiler defines"
# endif
# if (UINT_MAX != LZO_0xffffffffL) && !defined(__i386_int16__)
-# error "this should not happen"
+# error "unexpected configuration - check your compiler defines"
# endif
# if (ULONG_MAX != LZO_0xffffffffL)
-# error "this should not happen"
+# error "unexpected configuration - check your compiler defines"
+# endif
+#endif
+#if (LZO_ARCH_AMD64 || LZO_ARCH_I386)
+# if !defined(LZO_TARGET_FEATURE_SSE2)
+# if defined(__SSE2__)
+# define LZO_TARGET_FEATURE_SSE2 1
+# elif defined(_MSC_VER) && ((defined(_M_IX86_FP) && ((_M_IX86_FP)+0 >= 2)) || defined(_M_AMD64))
+# define LZO_TARGET_FEATURE_SSE2 1
+# endif
+# endif
+# if !defined(LZO_TARGET_FEATURE_SSSE3)
+# if (LZO_TARGET_FEATURE_SSE2)
+# if defined(__SSSE3__)
+# define LZO_TARGET_FEATURE_SSSE3 1
+# elif defined(_MSC_VER) && defined(__AVX__)
+# define LZO_TARGET_FEATURE_SSSE3 1
+# endif
+# endif
+# endif
+# if !defined(LZO_TARGET_FEATURE_SSE4_2)
+# if (LZO_TARGET_FEATURE_SSSE3)
+# if defined(__SSE4_2__)
+# define LZO_TARGET_FEATURE_SSE4_2 1
+# endif
+# endif
+# endif
+# if !defined(LZO_TARGET_FEATURE_AVX)
+# if (LZO_TARGET_FEATURE_SSSE3)
+# if defined(__AVX__)
+# define LZO_TARGET_FEATURE_AVX 1
+# endif
+# endif
+# endif
+# if !defined(LZO_TARGET_FEATURE_AVX2)
+# if (LZO_TARGET_FEATURE_AVX)
+# if defined(__AVX2__)
+# define LZO_TARGET_FEATURE_AVX2 1
+# endif
+# endif
# endif
#endif
-#if !defined(__LZO_MM_OVERRIDE)
+#if (LZO_TARGET_FEATURE_SSSE3 && !(LZO_TARGET_FEATURE_SSE2))
+# error "unexpected configuration - check your compiler defines"
+#endif
+#if (LZO_TARGET_FEATURE_SSE4_2 && !(LZO_TARGET_FEATURE_SSSE3))
+# error "unexpected configuration - check your compiler defines"
+#endif
+#if (LZO_TARGET_FEATURE_AVX && !(LZO_TARGET_FEATURE_SSSE3))
+# error "unexpected configuration - check your compiler defines"
+#endif
+#if (LZO_TARGET_FEATURE_AVX2 && !(LZO_TARGET_FEATURE_AVX))
+# error "unexpected configuration - check your compiler defines"
+#endif
+#if (LZO_ARCH_ARM)
+# if !defined(LZO_TARGET_FEATURE_NEON)
+# if defined(__ARM_NEON__)
+# define LZO_TARGET_FEATURE_NEON 1
+# endif
+# endif
+#elif (LZO_ARCH_ARM64)
+# if !defined(LZO_TARGET_FEATURE_NEON)
+# if 1
+# define LZO_TARGET_FEATURE_NEON 1
+# endif
+# endif
+#endif
+#if 0
+#elif !defined(__LZO_MM_OVERRIDE)
#if (LZO_ARCH_I086)
#if (UINT_MAX != LZO_0xffffL)
-# error "this should not happen"
+# error "unexpected configuration - check your compiler defines"
#endif
#if defined(__TINY__) || defined(M_I86TM) || defined(_M_I86TM)
# define LZO_MM_TINY 1
@@ -879,7 +1076,7 @@
#elif (LZO_CC_ZORTECHC && defined(__VCM__))
# define LZO_MM_LARGE 1
#else
-# error "unknown memory model"
+# error "unknown LZO_ARCH_I086 memory model"
#endif
#if (LZO_OS_DOS16 || LZO_OS_OS216 || LZO_OS_WIN16)
#define LZO_HAVE_MM_HUGE_PTR 1
@@ -902,10 +1099,10 @@
#endif
#if (LZO_ARCH_I086PM) && !(LZO_HAVE_MM_HUGE_PTR)
# if (LZO_OS_DOS16)
-# error "this should not happen"
+# error "unexpected configuration - check your compiler defines"
# elif (LZO_CC_ZORTECHC)
# else
-# error "this should not happen"
+# error "unexpected configuration - check your compiler defines"
# endif
#endif
#ifdef __cplusplus
@@ -937,7 +1134,7 @@ extern "C" {
#endif
#elif (LZO_ARCH_C166)
#if !defined(__MODEL__)
-# error "FIXME - C166 __MODEL__"
+# error "FIXME - LZO_ARCH_C166 __MODEL__"
#elif ((__MODEL__) == 0)
# define LZO_MM_SMALL 1
#elif ((__MODEL__) == 1)
@@ -951,11 +1148,11 @@ extern "C" {
#elif ((__MODEL__) == 5)
# define LZO_MM_XSMALL 1
#else
-# error "FIXME - C166 __MODEL__"
+# error "FIXME - LZO_ARCH_C166 __MODEL__"
#endif
#elif (LZO_ARCH_MCS251)
#if !defined(__MODEL__)
-# error "FIXME - MCS251 __MODEL__"
+# error "FIXME - LZO_ARCH_MCS251 __MODEL__"
#elif ((__MODEL__) == 0)
# define LZO_MM_SMALL 1
#elif ((__MODEL__) == 2)
@@ -967,11 +1164,11 @@ extern "C" {
#elif ((__MODEL__) == 5)
# define LZO_MM_XSMALL 1
#else
-# error "FIXME - MCS251 __MODEL__"
+# error "FIXME - LZO_ARCH_MCS251 __MODEL__"
#endif
#elif (LZO_ARCH_MCS51)
#if !defined(__MODEL__)
-# error "FIXME - MCS51 __MODEL__"
+# error "FIXME - LZO_ARCH_MCS51 __MODEL__"
#elif ((__MODEL__) == 1)
# define LZO_MM_SMALL 1
#elif ((__MODEL__) == 2)
@@ -983,7 +1180,7 @@ extern "C" {
#elif ((__MODEL__) == 5)
# define LZO_MM_XSMALL 1
#else
-# error "FIXME - MCS51 __MODEL__"
+# error "FIXME - LZO_ARCH_MCS51 __MODEL__"
#endif
#elif (LZO_ARCH_CRAY_PVP)
# define LZO_MM_PVP 1
@@ -1010,35 +1207,818 @@ extern "C" {
# error "unknown memory model"
#endif
#endif
+#if !defined(__lzo_gnuc_extension__)
+#if (LZO_CC_GNUC >= 0x020800ul)
+# define __lzo_gnuc_extension__ __extension__
+#elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE)
+# define __lzo_gnuc_extension__ __extension__
+#elif (LZO_CC_IBMC >= 600)
+# define __lzo_gnuc_extension__ __extension__
+#else
+#endif
+#endif
+#if !defined(__lzo_gnuc_extension__)
+# define __lzo_gnuc_extension__ /*empty*/
+#endif
+#if !defined(LZO_CFG_USE_NEW_STYLE_CASTS) && defined(__cplusplus) && 0
+# if (LZO_CC_GNUC && (LZO_CC_GNUC < 0x020800ul))
+# define LZO_CFG_USE_NEW_STYLE_CASTS 0
+# elif (LZO_CC_INTELC && (__INTEL_COMPILER < 1200))
+# define LZO_CFG_USE_NEW_STYLE_CASTS 0
+# else
+# define LZO_CFG_USE_NEW_STYLE_CASTS 1
+# endif
+#endif
+#if !defined(LZO_CFG_USE_NEW_STYLE_CASTS)
+# define LZO_CFG_USE_NEW_STYLE_CASTS 0
+#endif
+#if !defined(__cplusplus)
+# if defined(LZO_CFG_USE_NEW_STYLE_CASTS)
+# undef LZO_CFG_USE_NEW_STYLE_CASTS
+# endif
+# define LZO_CFG_USE_NEW_STYLE_CASTS 0
+#endif
+#if !defined(LZO_REINTERPRET_CAST)
+# if (LZO_CFG_USE_NEW_STYLE_CASTS)
+# define LZO_REINTERPRET_CAST(t,e) (reinterpret_cast<t> (e))
+# endif
+#endif
+#if !defined(LZO_REINTERPRET_CAST)
+# define LZO_REINTERPRET_CAST(t,e) ((t) (e))
+#endif
+#if !defined(LZO_STATIC_CAST)
+# if (LZO_CFG_USE_NEW_STYLE_CASTS)
+# define LZO_STATIC_CAST(t,e) (static_cast<t> (e))
+# endif
+#endif
+#if !defined(LZO_STATIC_CAST)
+# define LZO_STATIC_CAST(t,e) ((t) (e))
+#endif
+#if !defined(LZO_STATIC_CAST2)
+# define LZO_STATIC_CAST2(t1,t2,e) LZO_STATIC_CAST(t1, LZO_STATIC_CAST(t2, e))
+#endif
+#if !defined(LZO_UNCONST_CAST)
+# if (LZO_CFG_USE_NEW_STYLE_CASTS)
+# define LZO_UNCONST_CAST(t,e) (const_cast<t> (e))
+# elif (LZO_HAVE_MM_HUGE_PTR)
+# define LZO_UNCONST_CAST(t,e) ((t) (e))
+# elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE)
+# define LZO_UNCONST_CAST(t,e) ((t) ((void *) ((lzo_uintptr_t) ((const void *) (e)))))
+# endif
+#endif
+#if !defined(LZO_UNCONST_CAST)
+# define LZO_UNCONST_CAST(t,e) ((t) ((void *) ((const void *) (e))))
+#endif
+#if !defined(LZO_UNCONST_VOLATILE_CAST)
+# if (LZO_CFG_USE_NEW_STYLE_CASTS)
+# define LZO_UNCONST_VOLATILE_CAST(t,e) (const_cast<t> (e))
+# elif (LZO_HAVE_MM_HUGE_PTR)
+# define LZO_UNCONST_VOLATILE_CAST(t,e) ((t) (e))
+# elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE)
+# define LZO_UNCONST_VOLATILE_CAST(t,e) ((t) ((volatile void *) ((lzo_uintptr_t) ((volatile const void *) (e)))))
+# endif
+#endif
+#if !defined(LZO_UNCONST_VOLATILE_CAST)
+# define LZO_UNCONST_VOLATILE_CAST(t,e) ((t) ((volatile void *) ((volatile const void *) (e))))
+#endif
+#if !defined(LZO_UNVOLATILE_CAST)
+# if (LZO_CFG_USE_NEW_STYLE_CASTS)
+# define LZO_UNVOLATILE_CAST(t,e) (const_cast<t> (e))
+# elif (LZO_HAVE_MM_HUGE_PTR)
+# define LZO_UNVOLATILE_CAST(t,e) ((t) (e))
+# elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE)
+# define LZO_UNVOLATILE_CAST(t,e) ((t) ((void *) ((lzo_uintptr_t) ((volatile void *) (e)))))
+# endif
+#endif
+#if !defined(LZO_UNVOLATILE_CAST)
+# define LZO_UNVOLATILE_CAST(t,e) ((t) ((void *) ((volatile void *) (e))))
+#endif
+#if !defined(LZO_UNVOLATILE_CONST_CAST)
+# if (LZO_CFG_USE_NEW_STYLE_CASTS)
+# define LZO_UNVOLATILE_CONST_CAST(t,e) (const_cast<t> (e))
+# elif (LZO_HAVE_MM_HUGE_PTR)
+# define LZO_UNVOLATILE_CONST_CAST(t,e) ((t) (e))
+# elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE)
+# define LZO_UNVOLATILE_CONST_CAST(t,e) ((t) ((const void *) ((lzo_uintptr_t) ((volatile const void *) (e)))))
+# endif
+#endif
+#if !defined(LZO_UNVOLATILE_CONST_CAST)
+# define LZO_UNVOLATILE_CONST_CAST(t,e) ((t) ((const void *) ((volatile const void *) (e))))
+#endif
+#if !defined(LZO_PCAST)
+# if (LZO_HAVE_MM_HUGE_PTR)
+# define LZO_PCAST(t,e) ((t) (e))
+# endif
+#endif
+#if !defined(LZO_PCAST)
+# define LZO_PCAST(t,e) LZO_STATIC_CAST(t, LZO_STATIC_CAST(void *, e))
+#endif
+#if !defined(LZO_CCAST)
+# if (LZO_HAVE_MM_HUGE_PTR)
+# define LZO_CCAST(t,e) ((t) (e))
+# endif
+#endif
+#if !defined(LZO_CCAST)
+# define LZO_CCAST(t,e) LZO_STATIC_CAST(t, LZO_STATIC_CAST(const void *, e))
+#endif
+#if !defined(LZO_ICONV)
+# define LZO_ICONV(t,e) LZO_STATIC_CAST(t, e)
+#endif
+#if !defined(LZO_ICAST)
+# define LZO_ICAST(t,e) LZO_STATIC_CAST(t, e)
+#endif
+#if !defined(LZO_ITRUNC)
+# define LZO_ITRUNC(t,e) LZO_STATIC_CAST(t, e)
+#endif
+#if !defined(__lzo_cte)
+# if (LZO_CC_MSC || LZO_CC_WATCOMC)
+# define __lzo_cte(e) ((void)0,(e))
+# elif 1
+# define __lzo_cte(e) ((void)0,(e))
+# endif
+#endif
+#if !defined(__lzo_cte)
+# define __lzo_cte(e) (e)
+#endif
+#if !defined(LZO_BLOCK_BEGIN)
+# define LZO_BLOCK_BEGIN do {
+# define LZO_BLOCK_END } while __lzo_cte(0)
+#endif
+#if !defined(LZO_UNUSED)
+# if (LZO_CC_BORLANDC && (__BORLANDC__ >= 0x0600))
+# define LZO_UNUSED(var) ((void) &var)
+# elif (LZO_CC_BORLANDC || LZO_CC_HIGHC || LZO_CC_NDPC || LZO_CC_PELLESC || LZO_CC_TURBOC)
+# define LZO_UNUSED(var) if (&var) ; else
+# elif (LZO_CC_CLANG && (LZO_CC_CLANG >= 0x030200ul))
+# define LZO_UNUSED(var) ((void) &var)
+# elif (LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE)
+# define LZO_UNUSED(var) ((void) var)
+# elif (LZO_CC_MSC && (_MSC_VER < 900))
+# define LZO_UNUSED(var) if (&var) ; else
+# elif (LZO_CC_KEILC)
+# define LZO_UNUSED(var) {LZO_EXTERN_C int lzo_unused__[1-2*!(sizeof(var)>0)];}
+# elif (LZO_CC_PACIFICC)
+# define LZO_UNUSED(var) ((void) sizeof(var))
+# elif (LZO_CC_WATCOMC) && defined(__cplusplus)
+# define LZO_UNUSED(var) ((void) var)
+# else
+# define LZO_UNUSED(var) ((void) &var)
+# endif
+#endif
+#if !defined(LZO_UNUSED_FUNC)
+# if (LZO_CC_BORLANDC && (__BORLANDC__ >= 0x0600))
+# define LZO_UNUSED_FUNC(func) ((void) func)
+# elif (LZO_CC_BORLANDC || LZO_CC_NDPC || LZO_CC_TURBOC)
+# define LZO_UNUSED_FUNC(func) if (func) ; else
+# elif (LZO_CC_CLANG || LZO_CC_LLVM)
+# define LZO_UNUSED_FUNC(func) ((void) &func)
+# elif (LZO_CC_MSC && (_MSC_VER < 900))
+# define LZO_UNUSED_FUNC(func) if (func) ; else
+# elif (LZO_CC_MSC)
+# define LZO_UNUSED_FUNC(func) ((void) &func)
+# elif (LZO_CC_KEILC || LZO_CC_PELLESC)
+# define LZO_UNUSED_FUNC(func) {LZO_EXTERN_C int lzo_unused_func__[1-2*!(sizeof((int)func)>0)];}
+# else
+# define LZO_UNUSED_FUNC(func) ((void) func)
+# endif
+#endif
+#if !defined(LZO_UNUSED_LABEL)
+# if (LZO_CC_CLANG >= 0x020800ul)
+# define LZO_UNUSED_LABEL(l) (__lzo_gnuc_extension__ ((void) ((const void *) &&l)))
+# elif (LZO_CC_ARMCC || LZO_CC_CLANG || LZO_CC_INTELC || LZO_CC_WATCOMC)
+# define LZO_UNUSED_LABEL(l) if __lzo_cte(0) goto l
+# else
+# define LZO_UNUSED_LABEL(l) switch (0) case 1:goto l
+# endif
+#endif
+#if !defined(LZO_DEFINE_UNINITIALIZED_VAR)
+# if 0
+# define LZO_DEFINE_UNINITIALIZED_VAR(type,var,init) type var
+# elif 0 && (LZO_CC_GNUC)
+# define LZO_DEFINE_UNINITIALIZED_VAR(type,var,init) type var = var
+# else
+# define LZO_DEFINE_UNINITIALIZED_VAR(type,var,init) type var = init
+# endif
+#endif
+#if !defined(__lzo_inline)
+#if (LZO_CC_TURBOC && (__TURBOC__ <= 0x0295))
+#elif defined(__cplusplus)
+# define __lzo_inline inline
+#elif defined(__STDC_VERSION__) && (__STDC_VERSION__-0 >= 199901L)
+# define __lzo_inline inline
+#elif (LZO_CC_BORLANDC && (__BORLANDC__ >= 0x0550))
+# define __lzo_inline __inline
+#elif (LZO_CC_ARMCC_GNUC || LZO_CC_CILLY || LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE || LZO_CC_PGI)
+# define __lzo_inline __inline__
+#elif (LZO_CC_DMC)
+# define __lzo_inline __inline
+#elif (LZO_CC_GHS)
+# define __lzo_inline __inline__
+#elif (LZO_CC_IBMC >= 600)
+# define __lzo_inline __inline__
+#elif (LZO_CC_INTELC)
+# define __lzo_inline __inline
+#elif (LZO_CC_MWERKS && (__MWERKS__ >= 0x2405))
+# define __lzo_inline __inline
+#elif (LZO_CC_MSC && (_MSC_VER >= 900))
+# define __lzo_inline __inline
+#elif (LZO_CC_SUNPROC >= 0x5100)
+# define __lzo_inline __inline__
+#endif
+#endif
+#if defined(__lzo_inline)
+# ifndef __lzo_HAVE_inline
+# define __lzo_HAVE_inline 1
+# endif
+#else
+# define __lzo_inline /*empty*/
+#endif
+#if !defined(__lzo_forceinline)
+#if (LZO_CC_GNUC >= 0x030200ul)
+# define __lzo_forceinline __inline__ __attribute__((__always_inline__))
+#elif (LZO_CC_IBMC >= 700)
+# define __lzo_forceinline __inline__ __attribute__((__always_inline__))
+#elif (LZO_CC_INTELC_MSC && (__INTEL_COMPILER >= 450))
+# define __lzo_forceinline __forceinline
+#elif (LZO_CC_INTELC_GNUC && (__INTEL_COMPILER >= 800))
+# define __lzo_forceinline __inline__ __attribute__((__always_inline__))
+#elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE)
+# define __lzo_forceinline __inline__ __attribute__((__always_inline__))
+#elif (LZO_CC_MSC && (_MSC_VER >= 1200))
+# define __lzo_forceinline __forceinline
+#elif (LZO_CC_PGI >= 0x0d0a00ul)
+# define __lzo_forceinline __inline__ __attribute__((__always_inline__))
+#elif (LZO_CC_SUNPROC >= 0x5100)
+# define __lzo_forceinline __inline__ __attribute__((__always_inline__))
+#endif
+#endif
+#if defined(__lzo_forceinline)
+# ifndef __lzo_HAVE_forceinline
+# define __lzo_HAVE_forceinline 1
+# endif
+#else
+# define __lzo_forceinline __lzo_inline
+#endif
+#if !defined(__lzo_noinline)
+#if 1 && (LZO_ARCH_I386) && (LZO_CC_GNUC >= 0x040000ul) && (LZO_CC_GNUC < 0x040003ul)
+# define __lzo_noinline __attribute__((__noinline__,__used__))
+#elif (LZO_CC_GNUC >= 0x030200ul)
+# define __lzo_noinline __attribute__((__noinline__))
+#elif (LZO_CC_IBMC >= 700)
+# define __lzo_noinline __attribute__((__noinline__))
+#elif (LZO_CC_INTELC_MSC && (__INTEL_COMPILER >= 600))
+# define __lzo_noinline __declspec(noinline)
+#elif (LZO_CC_INTELC_GNUC && (__INTEL_COMPILER >= 800))
+# define __lzo_noinline __attribute__((__noinline__))
+#elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE)
+# define __lzo_noinline __attribute__((__noinline__))
+#elif (LZO_CC_MSC && (_MSC_VER >= 1300))
+# define __lzo_noinline __declspec(noinline)
+#elif (LZO_CC_MWERKS && (__MWERKS__ >= 0x3200) && (LZO_OS_WIN32 || LZO_OS_WIN64))
+# if defined(__cplusplus)
+# else
+# define __lzo_noinline __declspec(noinline)
+# endif
+#elif (LZO_CC_PGI >= 0x0d0a00ul)
+# define __lzo_noinline __attribute__((__noinline__))
+#elif (LZO_CC_SUNPROC >= 0x5100)
+# define __lzo_noinline __attribute__((__noinline__))
+#endif
+#endif
+#if defined(__lzo_noinline)
+# ifndef __lzo_HAVE_noinline
+# define __lzo_HAVE_noinline 1
+# endif
+#else
+# define __lzo_noinline /*empty*/
+#endif
+#if (__lzo_HAVE_forceinline || __lzo_HAVE_noinline) && !(__lzo_HAVE_inline)
+# error "unexpected configuration - check your compiler defines"
+#endif
+#if !defined(__lzo_static_inline)
+#if (LZO_CC_IBMC)
+# define __lzo_static_inline __lzo_gnuc_extension__ static __lzo_inline
+#endif
+#endif
+#if !defined(__lzo_static_inline)
+# define __lzo_static_inline static __lzo_inline
+#endif
+#if !defined(__lzo_static_forceinline)
+#if (LZO_CC_IBMC)
+# define __lzo_static_forceinline __lzo_gnuc_extension__ static __lzo_forceinline
+#endif
+#endif
+#if !defined(__lzo_static_forceinline)
+# define __lzo_static_forceinline static __lzo_forceinline
+#endif
+#if !defined(__lzo_static_noinline)
+#if (LZO_CC_IBMC)
+# define __lzo_static_noinline __lzo_gnuc_extension__ static __lzo_noinline
+#endif
+#endif
+#if !defined(__lzo_static_noinline)
+# define __lzo_static_noinline static __lzo_noinline
+#endif
+#if !defined(__lzo_c99_extern_inline)
+#if defined(__GNUC_GNU_INLINE__)
+# define __lzo_c99_extern_inline __lzo_inline
+#elif defined(__GNUC_STDC_INLINE__)
+# define __lzo_c99_extern_inline extern __lzo_inline
+#elif defined(__STDC_VERSION__) && (__STDC_VERSION__-0 >= 199901L)
+# define __lzo_c99_extern_inline extern __lzo_inline
+#endif
+#if !defined(__lzo_c99_extern_inline) && (__lzo_HAVE_inline)
+# define __lzo_c99_extern_inline __lzo_inline
+#endif
+#endif
+#if defined(__lzo_c99_extern_inline)
+# ifndef __lzo_HAVE_c99_extern_inline
+# define __lzo_HAVE_c99_extern_inline 1
+# endif
+#else
+# define __lzo_c99_extern_inline /*empty*/
+#endif
+#if !defined(__lzo_may_alias)
+#if (LZO_CC_GNUC >= 0x030400ul)
+# define __lzo_may_alias __attribute__((__may_alias__))
+#elif (LZO_CC_CLANG >= 0x020900ul)
+# define __lzo_may_alias __attribute__((__may_alias__))
+#elif (LZO_CC_INTELC_GNUC && (__INTEL_COMPILER >= 1210)) && 0
+# define __lzo_may_alias __attribute__((__may_alias__))
+#elif (LZO_CC_PGI >= 0x0d0a00ul) && 0
+# define __lzo_may_alias __attribute__((__may_alias__))
+#endif
+#endif
+#if defined(__lzo_may_alias)
+# ifndef __lzo_HAVE_may_alias
+# define __lzo_HAVE_may_alias 1
+# endif
+#else
+# define __lzo_may_alias /*empty*/
+#endif
+#if !defined(__lzo_noreturn)
+#if (LZO_CC_GNUC >= 0x020700ul)
+# define __lzo_noreturn __attribute__((__noreturn__))
+#elif (LZO_CC_IBMC >= 700)
+# define __lzo_noreturn __attribute__((__noreturn__))
+#elif (LZO_CC_INTELC_MSC && (__INTEL_COMPILER >= 450))
+# define __lzo_noreturn __declspec(noreturn)
+#elif (LZO_CC_INTELC_GNUC && (__INTEL_COMPILER >= 600))
+# define __lzo_noreturn __attribute__((__noreturn__))
+#elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE)
+# define __lzo_noreturn __attribute__((__noreturn__))
+#elif (LZO_CC_MSC && (_MSC_VER >= 1200))
+# define __lzo_noreturn __declspec(noreturn)
+#elif (LZO_CC_PGI >= 0x0d0a00ul)
+# define __lzo_noreturn __attribute__((__noreturn__))
+#endif
+#endif
+#if defined(__lzo_noreturn)
+# ifndef __lzo_HAVE_noreturn
+# define __lzo_HAVE_noreturn 1
+# endif
+#else
+# define __lzo_noreturn /*empty*/
+#endif
+#if !defined(__lzo_nothrow)
+#if (LZO_CC_GNUC >= 0x030300ul)
+# define __lzo_nothrow __attribute__((__nothrow__))
+#elif (LZO_CC_INTELC_MSC && (__INTEL_COMPILER >= 450)) && defined(__cplusplus)
+# define __lzo_nothrow __declspec(nothrow)
+#elif (LZO_CC_INTELC_GNUC && (__INTEL_COMPILER >= 900))
+# define __lzo_nothrow __attribute__((__nothrow__))
+#elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE)
+# define __lzo_nothrow __attribute__((__nothrow__))
+#elif (LZO_CC_MSC && (_MSC_VER >= 1200)) && defined(__cplusplus)
+# define __lzo_nothrow __declspec(nothrow)
+#endif
+#endif
+#if defined(__lzo_nothrow)
+# ifndef __lzo_HAVE_nothrow
+# define __lzo_HAVE_nothrow 1
+# endif
+#else
+# define __lzo_nothrow /*empty*/
+#endif
+#if !defined(__lzo_restrict)
+#if (LZO_CC_GNUC >= 0x030400ul)
+# define __lzo_restrict __restrict__
+#elif (LZO_CC_IBMC >= 800) && !defined(__cplusplus)
+# define __lzo_restrict __restrict__
+#elif (LZO_CC_IBMC >= 1210)
+# define __lzo_restrict __restrict__
+#elif (LZO_CC_INTELC_MSC && (__INTEL_COMPILER >= 600))
+#elif (LZO_CC_INTELC_GNUC && (__INTEL_COMPILER >= 600))
+# define __lzo_restrict __restrict__
+#elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_LLVM)
+# define __lzo_restrict __restrict__
+#elif (LZO_CC_MSC && (_MSC_VER >= 1400))
+# define __lzo_restrict __restrict
+#elif (LZO_CC_PGI >= 0x0d0a00ul)
+# define __lzo_restrict __restrict__
+#endif
+#endif
+#if defined(__lzo_restrict)
+# ifndef __lzo_HAVE_restrict
+# define __lzo_HAVE_restrict 1
+# endif
+#else
+# define __lzo_restrict /*empty*/
+#endif
+#if !defined(__lzo_alignof)
+#if (LZO_CC_ARMCC || LZO_CC_CILLY || LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE || LZO_CC_PGI)
+# define __lzo_alignof(e) __alignof__(e)
+#elif (LZO_CC_GHS) && !defined(__cplusplus)
+# define __lzo_alignof(e) __alignof__(e)
+#elif (LZO_CC_IBMC >= 600)
+# define __lzo_alignof(e) (__lzo_gnuc_extension__ __alignof__(e))
+#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 700))
+# define __lzo_alignof(e) __alignof__(e)
+#elif (LZO_CC_MSC && (_MSC_VER >= 1300))
+# define __lzo_alignof(e) __alignof(e)
+#elif (LZO_CC_SUNPROC >= 0x5100)
+# define __lzo_alignof(e) __alignof__(e)
+#endif
+#endif
+#if defined(__lzo_alignof)
+# ifndef __lzo_HAVE_alignof
+# define __lzo_HAVE_alignof 1
+# endif
+#endif
+#if !defined(__lzo_struct_packed)
+#if (LZO_CC_CLANG && (LZO_CC_CLANG < 0x020800ul)) && defined(__cplusplus)
+#elif (LZO_CC_GNUC && (LZO_CC_GNUC < 0x020700ul))
+#elif (LZO_CC_GNUC && (LZO_CC_GNUC < 0x020800ul)) && defined(__cplusplus)
+#elif (LZO_CC_PCC && (LZO_CC_PCC < 0x010100ul))
+#elif (LZO_CC_SUNPROC && (LZO_CC_SUNPROC < 0x5110)) && !defined(__cplusplus)
+#elif (LZO_CC_GNUC >= 0x030400ul) && !(LZO_CC_PCC_GNUC) && (LZO_ARCH_AMD64 || LZO_ARCH_I386)
+# define __lzo_struct_packed(s) struct s {
+# define __lzo_struct_packed_end() } __attribute__((__gcc_struct__,__packed__));
+# define __lzo_struct_packed_ma_end() } __lzo_may_alias __attribute__((__gcc_struct__,__packed__));
+#elif (LZO_CC_ARMCC || LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_INTELC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE || (LZO_CC_PGI >= 0x0d0a00ul) || (LZO_CC_SUNPROC >= 0x5100))
+# define __lzo_struct_packed(s) struct s {
+# define __lzo_struct_packed_end() } __attribute__((__packed__));
+# define __lzo_struct_packed_ma_end() } __lzo_may_alias __attribute__((__packed__));
+#elif (LZO_CC_IBMC >= 700)
+# define __lzo_struct_packed(s) __lzo_gnuc_extension__ struct s {
+# define __lzo_struct_packed_end() } __attribute__((__packed__));
+# define __lzo_struct_packed_ma_end() } __lzo_may_alias __attribute__((__packed__));
+#elif (LZO_CC_INTELC_MSC) || (LZO_CC_MSC && (_MSC_VER >= 1300))
+# define __lzo_struct_packed(s) __pragma(pack(push,1)) struct s {
+# define __lzo_struct_packed_end() } __pragma(pack(pop));
+#elif (LZO_CC_WATCOMC && (__WATCOMC__ >= 900))
+# define __lzo_struct_packed(s) _Packed struct s {
+# define __lzo_struct_packed_end() };
+#endif
+#endif
+#if defined(__lzo_struct_packed) && !defined(__lzo_struct_packed_ma)
+# define __lzo_struct_packed_ma(s) __lzo_struct_packed(s)
+#endif
+#if defined(__lzo_struct_packed_end) && !defined(__lzo_struct_packed_ma_end)
+# define __lzo_struct_packed_ma_end() __lzo_struct_packed_end()
+#endif
+#if !defined(__lzo_byte_struct)
+#if defined(__lzo_struct_packed)
+# define __lzo_byte_struct(s,n) __lzo_struct_packed(s) unsigned char a[n]; __lzo_struct_packed_end()
+# define __lzo_byte_struct_ma(s,n) __lzo_struct_packed_ma(s) unsigned char a[n]; __lzo_struct_packed_ma_end()
+#elif (LZO_CC_CILLY || LZO_CC_CLANG || LZO_CC_PGI || (LZO_CC_SUNPROC >= 0x5100))
+# define __lzo_byte_struct(s,n) struct s { unsigned char a[n]; } __attribute__((__packed__));
+# define __lzo_byte_struct_ma(s,n) struct s { unsigned char a[n]; } __lzo_may_alias __attribute__((__packed__));
+#endif
+#endif
+#if defined(__lzo_byte_struct) && !defined(__lzo_byte_struct_ma)
+# define __lzo_byte_struct_ma(s,n) __lzo_byte_struct(s,n)
+#endif
+#if !defined(__lzo_struct_align16) && (__lzo_HAVE_alignof)
+#if (LZO_CC_GNUC && (LZO_CC_GNUC < 0x030000ul))
+#elif (LZO_CC_CLANG && (LZO_CC_CLANG < 0x020800ul)) && defined(__cplusplus)
+#elif (LZO_CC_CILLY || LZO_CC_PCC)
+#elif (LZO_CC_INTELC_MSC) || (LZO_CC_MSC && (_MSC_VER >= 1300))
+# define __lzo_struct_align16(s) struct __declspec(align(16)) s {
+# define __lzo_struct_align16_end() };
+# define __lzo_struct_align32(s) struct __declspec(align(32)) s {
+# define __lzo_struct_align32_end() };
+# define __lzo_struct_align64(s) struct __declspec(align(64)) s {
+# define __lzo_struct_align64_end() };
+#elif (LZO_CC_ARMCC || LZO_CC_CLANG || LZO_CC_GNUC || (LZO_CC_IBMC >= 700) || LZO_CC_INTELC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE)
+# define __lzo_struct_align16(s) struct s {
+# define __lzo_struct_align16_end() } __attribute__((__aligned__(16)));
+# define __lzo_struct_align32(s) struct s {
+# define __lzo_struct_align32_end() } __attribute__((__aligned__(32)));
+# define __lzo_struct_align64(s) struct s {
+# define __lzo_struct_align64_end() } __attribute__((__aligned__(64)));
+#endif
+#endif
+#if !defined(__lzo_union_um)
+#if (LZO_CC_CLANG && (LZO_CC_CLANG < 0x020800ul)) && defined(__cplusplus)
+#elif (LZO_CC_GNUC && (LZO_CC_GNUC < 0x020700ul))
+#elif (LZO_CC_GNUC && (LZO_CC_GNUC < 0x020800ul)) && defined(__cplusplus)
+#elif (LZO_CC_INTELC_GNUC && (__INTEL_COMPILER < 810))
+#elif (LZO_CC_PCC && (LZO_CC_PCC < 0x010100ul))
+#elif (LZO_CC_SUNPROC && (LZO_CC_SUNPROC < 0x5110)) && !defined(__cplusplus)
+#elif (LZO_CC_ARMCC || LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_INTELC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE || (LZO_CC_PGI >= 0x0d0a00ul) || (LZO_CC_SUNPROC >= 0x5100))
+# define __lzo_union_am(s) union s {
+# define __lzo_union_am_end() } __lzo_may_alias;
+# define __lzo_union_um(s) union s {
+# define __lzo_union_um_end() } __lzo_may_alias __attribute__((__packed__));
+#elif (LZO_CC_IBMC >= 700)
+# define __lzo_union_am(s) __lzo_gnuc_extension__ union s {
+# define __lzo_union_am_end() } __lzo_may_alias;
+# define __lzo_union_um(s) __lzo_gnuc_extension__ union s {
+# define __lzo_union_um_end() } __lzo_may_alias __attribute__((__packed__));
+#elif (LZO_CC_INTELC_MSC) || (LZO_CC_MSC && (_MSC_VER >= 1300))
+# define __lzo_union_um(s) __pragma(pack(push,1)) union s {
+# define __lzo_union_um_end() } __pragma(pack(pop));
+#elif (LZO_CC_WATCOMC && (__WATCOMC__ >= 900))
+# define __lzo_union_um(s) _Packed union s {
+# define __lzo_union_um_end() };
+#endif
+#endif
+#if !defined(__lzo_union_am)
+# define __lzo_union_am(s) union s {
+# define __lzo_union_am_end() };
+#endif
+#if !defined(__lzo_constructor)
+#if (LZO_CC_GNUC >= 0x030400ul)
+# define __lzo_constructor __attribute__((__constructor__,__used__))
+#elif (LZO_CC_GNUC >= 0x020700ul)
+# define __lzo_constructor __attribute__((__constructor__))
+#elif (LZO_CC_INTELC_GNUC && (__INTEL_COMPILER >= 800))
+# define __lzo_constructor __attribute__((__constructor__,__used__))
+#elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE)
+# define __lzo_constructor __attribute__((__constructor__))
+#endif
+#endif
+#if defined(__lzo_constructor)
+# ifndef __lzo_HAVE_constructor
+# define __lzo_HAVE_constructor 1
+# endif
+#endif
+#if !defined(__lzo_destructor)
+#if (LZO_CC_GNUC >= 0x030400ul)
+# define __lzo_destructor __attribute__((__destructor__,__used__))
+#elif (LZO_CC_GNUC >= 0x020700ul)
+# define __lzo_destructor __attribute__((__destructor__))
+#elif (LZO_CC_INTELC_GNUC && (__INTEL_COMPILER >= 800))
+# define __lzo_destructor __attribute__((__destructor__,__used__))
+#elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE)
+# define __lzo_destructor __attribute__((__destructor__))
+#endif
+#endif
+#if defined(__lzo_destructor)
+# ifndef __lzo_HAVE_destructor
+# define __lzo_HAVE_destructor 1
+# endif
+#endif
+#if (__lzo_HAVE_destructor) && !(__lzo_HAVE_constructor)
+# error "unexpected configuration - check your compiler defines"
+#endif
+#if !defined(__lzo_likely) && !defined(__lzo_unlikely)
+#if (LZO_CC_GNUC >= 0x030200ul)
+# define __lzo_likely(e) (__builtin_expect(!!(e),1))
+# define __lzo_unlikely(e) (__builtin_expect(!!(e),0))
+#elif (LZO_CC_IBMC >= 1010)
+# define __lzo_likely(e) (__builtin_expect(!!(e),1))
+# define __lzo_unlikely(e) (__builtin_expect(!!(e),0))
+#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 800))
+# define __lzo_likely(e) (__builtin_expect(!!(e),1))
+# define __lzo_unlikely(e) (__builtin_expect(!!(e),0))
+#elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE)
+# define __lzo_likely(e) (__builtin_expect(!!(e),1))
+# define __lzo_unlikely(e) (__builtin_expect(!!(e),0))
+#endif
+#endif
+#if defined(__lzo_likely)
+# ifndef __lzo_HAVE_likely
+# define __lzo_HAVE_likely 1
+# endif
+#else
+# define __lzo_likely(e) (e)
+#endif
+#if defined(__lzo_unlikely)
+# ifndef __lzo_HAVE_unlikely
+# define __lzo_HAVE_unlikely 1
+# endif
+#else
+# define __lzo_unlikely(e) (e)
+#endif
+#if !defined(__lzo_static_unused_void_func)
+# if 1 && (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || (LZO_CC_GNUC >= 0x020700ul) || LZO_CC_INTELC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE || LZO_CC_PGI)
+# define __lzo_static_unused_void_func(f) static void __attribute__((__unused__)) f(void)
+# else
+# define __lzo_static_unused_void_func(f) static __lzo_inline void f(void)
+# endif
+#endif
+#if !defined(__lzo_loop_forever)
+# if (LZO_CC_IBMC)
+# define __lzo_loop_forever() LZO_BLOCK_BEGIN for (;;) { ; } LZO_BLOCK_END
+# else
+# define __lzo_loop_forever() do { ; } while __lzo_cte(1)
+# endif
+#endif
+#if !defined(__lzo_unreachable)
+#if (LZO_CC_CLANG && (LZO_CC_CLANG >= 0x020800ul))
+# define __lzo_unreachable() __builtin_unreachable();
+#elif (LZO_CC_GNUC >= 0x040500ul)
+# define __lzo_unreachable() __builtin_unreachable();
+#elif (LZO_CC_INTELC_GNUC && (__INTEL_COMPILER >= 1300)) && 1
+# define __lzo_unreachable() __builtin_unreachable();
+#endif
+#endif
+#if defined(__lzo_unreachable)
+# ifndef __lzo_HAVE_unreachable
+# define __lzo_HAVE_unreachable 1
+# endif
+#else
+# if 0
+# define __lzo_unreachable() ((void)0);
+# else
+# define __lzo_unreachable() __lzo_loop_forever();
+# endif
+#endif
+#ifndef __LZO_CTA_NAME
+#if (LZO_CFG_USE_COUNTER)
+# define __LZO_CTA_NAME(a) LZO_PP_ECONCAT2(a,__COUNTER__)
+#else
+# define __LZO_CTA_NAME(a) LZO_PP_ECONCAT2(a,__LINE__)
+#endif
+#endif
+#if !defined(LZO_COMPILE_TIME_ASSERT_HEADER)
+# if (LZO_CC_AZTECC || LZO_CC_ZORTECHC)
+# define LZO_COMPILE_TIME_ASSERT_HEADER(e) LZO_EXTERN_C_BEGIN extern int __LZO_CTA_NAME(lzo_cta__)[1-!(e)]; LZO_EXTERN_C_END
+# elif (LZO_CC_DMC || LZO_CC_SYMANTECC)
+# define LZO_COMPILE_TIME_ASSERT_HEADER(e) LZO_EXTERN_C_BEGIN extern int __LZO_CTA_NAME(lzo_cta__)[1u-2*!(e)]; LZO_EXTERN_C_END
+# elif (LZO_CC_TURBOC && (__TURBOC__ == 0x0295))
+# define LZO_COMPILE_TIME_ASSERT_HEADER(e) LZO_EXTERN_C_BEGIN extern int __LZO_CTA_NAME(lzo_cta__)[1-!(e)]; LZO_EXTERN_C_END
+# elif (LZO_CC_CLANG && (LZO_CC_CLANG < 0x020900ul)) && defined(__cplusplus)
+# define LZO_COMPILE_TIME_ASSERT_HEADER(e) LZO_EXTERN_C_BEGIN int __LZO_CTA_NAME(lzo_cta_f__)(int [1-2*!(e)]); LZO_EXTERN_C_END
+# elif (LZO_CC_GNUC) && defined(__CHECKER__) && defined(__SPARSE_CHECKER__)
+# define LZO_COMPILE_TIME_ASSERT_HEADER(e) LZO_EXTERN_C_BEGIN enum {__LZO_CTA_NAME(lzo_cta_e__)=1/!!(e)} __attribute__((__unused__)); LZO_EXTERN_C_END
+# else
+# define LZO_COMPILE_TIME_ASSERT_HEADER(e) LZO_EXTERN_C_BEGIN extern int __LZO_CTA_NAME(lzo_cta__)[1-2*!(e)]; LZO_EXTERN_C_END
+# endif
+#endif
+#if !defined(LZO_COMPILE_TIME_ASSERT)
+# if (LZO_CC_AZTECC)
+# define LZO_COMPILE_TIME_ASSERT(e) {typedef int __LZO_CTA_NAME(lzo_cta_t__)[1-!(e)];}
+# elif (LZO_CC_DMC || LZO_CC_PACIFICC || LZO_CC_SYMANTECC || LZO_CC_ZORTECHC)
+# define LZO_COMPILE_TIME_ASSERT(e) switch(0) case 1:case !(e):break;
+# elif (LZO_CC_GNUC) && defined(__CHECKER__) && defined(__SPARSE_CHECKER__)
+# define LZO_COMPILE_TIME_ASSERT(e) {(void) (0/!!(e));}
+# elif (LZO_CC_GNUC >= 0x040700ul) && (LZO_CFG_USE_COUNTER) && defined(__cplusplus)
+# define LZO_COMPILE_TIME_ASSERT(e) {enum {__LZO_CTA_NAME(lzo_cta_e__)=1/!!(e)} __attribute__((__unused__));}
+# elif (LZO_CC_GNUC >= 0x040700ul)
+# define LZO_COMPILE_TIME_ASSERT(e) {typedef int __LZO_CTA_NAME(lzo_cta_t__)[1-2*!(e)] __attribute__((__unused__));}
+# elif (LZO_CC_MSC && (_MSC_VER < 900))
+# define LZO_COMPILE_TIME_ASSERT(e) switch(0) case 1:case !(e):break;
+# elif (LZO_CC_TURBOC && (__TURBOC__ == 0x0295))
+# define LZO_COMPILE_TIME_ASSERT(e) switch(0) case 1:case !(e):break;
+# else
+# define LZO_COMPILE_TIME_ASSERT(e) {typedef int __LZO_CTA_NAME(lzo_cta_t__)[1-2*!(e)];}
+# endif
+#endif
+LZO_COMPILE_TIME_ASSERT_HEADER(1 == 1)
+#if defined(__cplusplus)
+extern "C" { LZO_COMPILE_TIME_ASSERT_HEADER(2 == 2) }
+#endif
+LZO_COMPILE_TIME_ASSERT_HEADER(3 == 3)
+#if (LZO_ARCH_I086 || LZO_ARCH_I386) && (LZO_OS_DOS16 || LZO_OS_DOS32 || LZO_OS_OS2 || LZO_OS_OS216 || LZO_OS_WIN16 || LZO_OS_WIN32 || LZO_OS_WIN64)
+# if (LZO_CC_GNUC || LZO_CC_HIGHC || LZO_CC_NDPC || LZO_CC_PACIFICC)
+# elif (LZO_CC_DMC || LZO_CC_SYMANTECC || LZO_CC_ZORTECHC)
+# define __lzo_cdecl __cdecl
+# define __lzo_cdecl_atexit /*empty*/
+# define __lzo_cdecl_main __cdecl
+# if (LZO_OS_OS2 && (LZO_CC_DMC || LZO_CC_SYMANTECC))
+# define __lzo_cdecl_qsort __pascal
+# elif (LZO_OS_OS2 && (LZO_CC_ZORTECHC))
+# define __lzo_cdecl_qsort _stdcall
+# else
+# define __lzo_cdecl_qsort __cdecl
+# endif
+# elif (LZO_CC_WATCOMC)
+# define __lzo_cdecl __cdecl
+# else
+# define __lzo_cdecl __cdecl
+# define __lzo_cdecl_atexit __cdecl
+# define __lzo_cdecl_main __cdecl
+# define __lzo_cdecl_qsort __cdecl
+# endif
+# if (LZO_CC_GNUC || LZO_CC_HIGHC || LZO_CC_NDPC || LZO_CC_PACIFICC || LZO_CC_WATCOMC)
+# elif (LZO_OS_OS2 && (LZO_CC_DMC || LZO_CC_SYMANTECC))
+# define __lzo_cdecl_sighandler __pascal
+# elif (LZO_OS_OS2 && (LZO_CC_ZORTECHC))
+# define __lzo_cdecl_sighandler _stdcall
+# elif (LZO_CC_MSC && (_MSC_VER >= 1400)) && defined(_M_CEE_PURE)
+# define __lzo_cdecl_sighandler __clrcall
+# elif (LZO_CC_MSC && (_MSC_VER >= 600 && _MSC_VER < 700))
+# if defined(_DLL)
+# define __lzo_cdecl_sighandler _far _cdecl _loadds
+# elif defined(_MT)
+# define __lzo_cdecl_sighandler _far _cdecl
+# else
+# define __lzo_cdecl_sighandler _cdecl
+# endif
+# else
+# define __lzo_cdecl_sighandler __cdecl
+# endif
+#elif (LZO_ARCH_I386) && (LZO_CC_WATCOMC)
+# define __lzo_cdecl __cdecl
+#elif (LZO_ARCH_M68K && LZO_OS_TOS && (LZO_CC_PUREC || LZO_CC_TURBOC))
+# define __lzo_cdecl cdecl
+#endif
+#if !defined(__lzo_cdecl)
+# define __lzo_cdecl /*empty*/
+#endif
+#if !defined(__lzo_cdecl_atexit)
+# define __lzo_cdecl_atexit /*empty*/
+#endif
+#if !defined(__lzo_cdecl_main)
+# define __lzo_cdecl_main /*empty*/
+#endif
+#if !defined(__lzo_cdecl_qsort)
+# define __lzo_cdecl_qsort /*empty*/
+#endif
+#if !defined(__lzo_cdecl_sighandler)
+# define __lzo_cdecl_sighandler /*empty*/
+#endif
+#if !defined(__lzo_cdecl_va)
+# define __lzo_cdecl_va __lzo_cdecl
+#endif
+#if !(LZO_CFG_NO_WINDOWS_H)
+#if !defined(LZO_HAVE_WINDOWS_H)
+#if (LZO_OS_CYGWIN || (LZO_OS_EMX && defined(__RSXNT__)) || LZO_OS_WIN32 || LZO_OS_WIN64)
+# if (LZO_CC_WATCOMC && (__WATCOMC__ < 1000))
+# elif (LZO_OS_WIN32 && LZO_CC_GNUC) && defined(__PW32__)
+# elif ((LZO_OS_CYGWIN || defined(__MINGW32__)) && (LZO_CC_GNUC && (LZO_CC_GNUC < 0x025f00ul)))
+# else
+# define LZO_HAVE_WINDOWS_H 1
+# endif
+#endif
+#endif
+#endif
+#ifndef LZO_SIZEOF_SHORT
#if defined(SIZEOF_SHORT)
# define LZO_SIZEOF_SHORT (SIZEOF_SHORT)
+#elif defined(__SIZEOF_SHORT__)
+# define LZO_SIZEOF_SHORT (__SIZEOF_SHORT__)
+#endif
#endif
+#ifndef LZO_SIZEOF_INT
#if defined(SIZEOF_INT)
# define LZO_SIZEOF_INT (SIZEOF_INT)
+#elif defined(__SIZEOF_INT__)
+# define LZO_SIZEOF_INT (__SIZEOF_INT__)
#endif
+#endif
+#ifndef LZO_SIZEOF_LONG
#if defined(SIZEOF_LONG)
# define LZO_SIZEOF_LONG (SIZEOF_LONG)
+#elif defined(__SIZEOF_LONG__)
+# define LZO_SIZEOF_LONG (__SIZEOF_LONG__)
+#endif
#endif
+#ifndef LZO_SIZEOF_LONG_LONG
#if defined(SIZEOF_LONG_LONG)
# define LZO_SIZEOF_LONG_LONG (SIZEOF_LONG_LONG)
+#elif defined(__SIZEOF_LONG_LONG__)
+# define LZO_SIZEOF_LONG_LONG (__SIZEOF_LONG_LONG__)
#endif
+#endif
+#ifndef LZO_SIZEOF___INT16
#if defined(SIZEOF___INT16)
# define LZO_SIZEOF___INT16 (SIZEOF___INT16)
#endif
+#endif
+#ifndef LZO_SIZEOF___INT32
#if defined(SIZEOF___INT32)
# define LZO_SIZEOF___INT32 (SIZEOF___INT32)
#endif
+#endif
+#ifndef LZO_SIZEOF___INT64
#if defined(SIZEOF___INT64)
# define LZO_SIZEOF___INT64 (SIZEOF___INT64)
#endif
+#endif
+#ifndef LZO_SIZEOF_VOID_P
#if defined(SIZEOF_VOID_P)
# define LZO_SIZEOF_VOID_P (SIZEOF_VOID_P)
+#elif defined(__SIZEOF_POINTER__)
+# define LZO_SIZEOF_VOID_P (__SIZEOF_POINTER__)
#endif
+#endif
+#ifndef LZO_SIZEOF_SIZE_T
#if defined(SIZEOF_SIZE_T)
# define LZO_SIZEOF_SIZE_T (SIZEOF_SIZE_T)
+#elif defined(__SIZEOF_SIZE_T__)
+# define LZO_SIZEOF_SIZE_T (__SIZEOF_SIZE_T__)
+#endif
#endif
+#ifndef LZO_SIZEOF_PTRDIFF_T
#if defined(SIZEOF_PTRDIFF_T)
# define LZO_SIZEOF_PTRDIFF_T (SIZEOF_PTRDIFF_T)
+#elif defined(__SIZEOF_PTRDIFF_T__)
+# define LZO_SIZEOF_PTRDIFF_T (__SIZEOF_PTRDIFF_T__)
+#endif
#endif
#define __LZO_LSR(x,b) (((x)+0ul) >> (b))
#if !defined(LZO_SIZEOF_SHORT)
@@ -1060,6 +2040,7 @@ extern "C" {
# error "LZO_SIZEOF_SHORT"
# endif
#endif
+LZO_COMPILE_TIME_ASSERT_HEADER(LZO_SIZEOF_SHORT == sizeof(short))
#if !defined(LZO_SIZEOF_INT)
# if (LZO_ARCH_CRAY_PVP)
# define LZO_SIZEOF_INT 8
@@ -1081,6 +2062,7 @@ extern "C" {
# error "LZO_SIZEOF_INT"
# endif
#endif
+LZO_COMPILE_TIME_ASSERT_HEADER(LZO_SIZEOF_INT == sizeof(int))
#if !defined(LZO_SIZEOF_LONG)
# if (ULONG_MAX == LZO_0xffffffffL)
# define LZO_SIZEOF_LONG 4
@@ -1090,6 +2072,8 @@ extern "C" {
# define LZO_SIZEOF_LONG 2
# elif (__LZO_LSR(ULONG_MAX,31) == 1)
# define LZO_SIZEOF_LONG 4
+# elif (__LZO_LSR(ULONG_MAX,39) == 1)
+# define LZO_SIZEOF_LONG 5
# elif (__LZO_LSR(ULONG_MAX,63) == 1)
# define LZO_SIZEOF_LONG 8
# elif (__LZO_LSR(ULONG_MAX,127) == 1)
@@ -1098,11 +2082,12 @@ extern "C" {
# error "LZO_SIZEOF_LONG"
# endif
#endif
+LZO_COMPILE_TIME_ASSERT_HEADER(LZO_SIZEOF_LONG == sizeof(long))
#if !defined(LZO_SIZEOF_LONG_LONG) && !defined(LZO_SIZEOF___INT64)
#if (LZO_SIZEOF_LONG > 0 && LZO_SIZEOF_LONG < 8)
# if defined(__LONG_MAX__) && defined(__LONG_LONG_MAX__)
# if (LZO_CC_GNUC >= 0x030300ul)
-# if ((__LONG_MAX__)+0 == (__LONG_LONG_MAX__)+0)
+# if ((__LONG_MAX__-0) == (__LONG_LONG_MAX__-0))
# define LZO_SIZEOF_LONG_LONG LZO_SIZEOF_LONG
# elif (__LZO_LSR(__LONG_LONG_MAX__,30) == 1)
# define LZO_SIZEOF_LONG_LONG 4
@@ -1116,7 +2101,7 @@ extern "C" {
#if (LZO_ARCH_I086 && LZO_CC_DMC)
#elif (LZO_CC_CILLY) && defined(__GNUC__)
# define LZO_SIZEOF_LONG_LONG 8
-#elif (LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE)
+#elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE)
# define LZO_SIZEOF_LONG_LONG 8
#elif ((LZO_OS_WIN32 || LZO_OS_WIN64 || defined(_WIN32)) && LZO_CC_MSC && (_MSC_VER >= 1400))
# define LZO_SIZEOF_LONG_LONG 8
@@ -1138,11 +2123,13 @@ extern "C" {
# define LZO_SIZEOF___INT64 8
#elif (LZO_ARCH_I386 && (LZO_CC_WATCOMC && (__WATCOMC__ >= 1100)))
# define LZO_SIZEOF___INT64 8
-#elif (LZO_CC_WATCOMC && defined(_INTEGRAL_MAX_BITS) && (_INTEGRAL_MAX_BITS == 64))
+#elif (LZO_CC_GHS && defined(__LLONG_BIT) && ((__LLONG_BIT-0) == 64))
+# define LZO_SIZEOF_LONG_LONG 8
+#elif (LZO_CC_WATCOMC && defined(_INTEGRAL_MAX_BITS) && ((_INTEGRAL_MAX_BITS-0) == 64))
# define LZO_SIZEOF___INT64 8
#elif (LZO_OS_OS400 || defined(__OS400__)) && defined(__LLP64_IFC__)
# define LZO_SIZEOF_LONG_LONG 8
-#elif (defined(__vms) || defined(__VMS)) && (__INITIAL_POINTER_SIZE+0 == 64)
+#elif (defined(__vms) || defined(__VMS)) && ((__INITIAL_POINTER_SIZE-0) == 64)
# define LZO_SIZEOF_LONG_LONG 8
#elif (LZO_CC_SDCC) && (LZO_SIZEOF_INT == 2)
#elif 1 && defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
@@ -1155,87 +2142,127 @@ extern "C" {
# undef LZO_SIZEOF_LONG_LONG
# endif
#endif
-#if (LZO_CFG_NO_LONG_LONG) || defined(__NO_LONG_LONG)
+#if (LZO_CFG_NO_LONG_LONG)
+# undef LZO_SIZEOF_LONG_LONG
+#elif defined(__NO_LONG_LONG)
+# undef LZO_SIZEOF_LONG_LONG
+#elif defined(_NO_LONGLONG)
# undef LZO_SIZEOF_LONG_LONG
#endif
-#if !defined(LZO_SIZEOF_VOID_P)
-#if (LZO_ARCH_I086)
-# define __LZO_WORDSIZE 2
-# if (LZO_MM_TINY || LZO_MM_SMALL || LZO_MM_MEDIUM)
-# define LZO_SIZEOF_VOID_P 2
-# elif (LZO_MM_COMPACT || LZO_MM_LARGE || LZO_MM_HUGE)
-# define LZO_SIZEOF_VOID_P 4
+#if !defined(LZO_WORDSIZE)
+#if (LZO_ARCH_ALPHA)
+# define LZO_WORDSIZE 8
+#elif (LZO_ARCH_AMD64)
+# define LZO_WORDSIZE 8
+#elif (LZO_ARCH_AVR)
+# define LZO_WORDSIZE 1
+#elif (LZO_ARCH_H8300)
+# if defined(__NORMAL_MODE__)
+# define LZO_WORDSIZE 4
+# elif defined(__H8300H__) || defined(__H8300S__) || defined(__H8300SX__)
+# define LZO_WORDSIZE 4
# else
-# error "LZO_MM"
+# define LZO_WORDSIZE 2
# endif
-#elif (LZO_ARCH_AVR || LZO_ARCH_Z80)
-# define __LZO_WORDSIZE 1
+#elif (LZO_ARCH_I086)
+# define LZO_WORDSIZE 2
+#elif (LZO_ARCH_IA64)
+# define LZO_WORDSIZE 8
+#elif (LZO_ARCH_M16C)
+# define LZO_WORDSIZE 2
+#elif (LZO_ARCH_SPU)
+# define LZO_WORDSIZE 4
+#elif (LZO_ARCH_Z80)
+# define LZO_WORDSIZE 1
+#elif (LZO_SIZEOF_LONG == 8) && ((defined(__mips__) && defined(__R5900__)) || defined(__MIPS_PSX2__))
+# define LZO_WORDSIZE 8
+#elif (LZO_OS_OS400 || defined(__OS400__))
+# define LZO_WORDSIZE 8
+#elif (defined(__vms) || defined(__VMS)) && (__INITIAL_POINTER_SIZE+0 == 64)
+# define LZO_WORDSIZE 8
+#endif
+#endif
+#if !defined(LZO_SIZEOF_VOID_P)
+#if defined(__ILP32__) || defined(__ILP32) || defined(_ILP32)
+LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(int) == 4)
+LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(long) == 4)
+# define LZO_SIZEOF_VOID_P 4
+#elif defined(__ILP64__) || defined(__ILP64) || defined(_ILP64)
+LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(int) == 8)
+LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(long) == 8)
+# define LZO_SIZEOF_VOID_P 8
+#elif defined(__LLP64__) || defined(__LLP64) || defined(_LLP64) || defined(_WIN64)
+LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(long) == 4)
+# define LZO_SIZEOF_VOID_P 8
+#elif defined(__LP64__) || defined(__LP64) || defined(_LP64)
+LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(long) == 8)
+# define LZO_SIZEOF_VOID_P 8
+#elif (LZO_ARCH_AVR)
# define LZO_SIZEOF_VOID_P 2
#elif (LZO_ARCH_C166 || LZO_ARCH_MCS51 || LZO_ARCH_MCS251 || LZO_ARCH_MSP430)
# define LZO_SIZEOF_VOID_P 2
#elif (LZO_ARCH_H8300)
# if defined(__NORMAL_MODE__)
-# define __LZO_WORDSIZE 4
# define LZO_SIZEOF_VOID_P 2
# elif defined(__H8300H__) || defined(__H8300S__) || defined(__H8300SX__)
-# define __LZO_WORDSIZE 4
# define LZO_SIZEOF_VOID_P 4
# else
-# define __LZO_WORDSIZE 2
# define LZO_SIZEOF_VOID_P 2
# endif
# if (LZO_CC_GNUC && (LZO_CC_GNUC < 0x040000ul)) && (LZO_SIZEOF_INT == 4)
# define LZO_SIZEOF_SIZE_T LZO_SIZEOF_INT
# define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_INT
# endif
+#elif (LZO_ARCH_I086)
+# if (LZO_MM_TINY || LZO_MM_SMALL || LZO_MM_MEDIUM)
+# define LZO_SIZEOF_VOID_P 2
+# elif (LZO_MM_COMPACT || LZO_MM_LARGE || LZO_MM_HUGE)
+# define LZO_SIZEOF_VOID_P 4
+# else
+# error "invalid LZO_ARCH_I086 memory model"
+# endif
#elif (LZO_ARCH_M16C)
-# define __LZO_WORDSIZE 2
# if defined(__m32c_cpu__) || defined(__m32cm_cpu__)
# define LZO_SIZEOF_VOID_P 4
# else
# define LZO_SIZEOF_VOID_P 2
# endif
+#elif (LZO_ARCH_SPU)
+# define LZO_SIZEOF_VOID_P 4
+#elif (LZO_ARCH_Z80)
+# define LZO_SIZEOF_VOID_P 2
#elif (LZO_SIZEOF_LONG == 8) && ((defined(__mips__) && defined(__R5900__)) || defined(__MIPS_PSX2__))
-# define __LZO_WORDSIZE 8
# define LZO_SIZEOF_VOID_P 4
-#elif defined(__LLP64__) || defined(__LLP64) || defined(_LLP64) || defined(_WIN64)
-# define __LZO_WORDSIZE 8
-# define LZO_SIZEOF_VOID_P 8
-#elif (LZO_OS_OS400 || defined(__OS400__)) && defined(__LLP64_IFC__)
-# define LZO_SIZEOF_VOID_P LZO_SIZEOF_LONG
-# define LZO_SIZEOF_SIZE_T LZO_SIZEOF_LONG
-# define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_LONG
#elif (LZO_OS_OS400 || defined(__OS400__))
-# define __LZO_WORDSIZE LZO_SIZEOF_LONG
-# define LZO_SIZEOF_VOID_P 16
-# define LZO_SIZEOF_SIZE_T LZO_SIZEOF_LONG
-# define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_LONG
+# if defined(__LLP64_IFC__)
+# define LZO_SIZEOF_VOID_P 8
+# define LZO_SIZEOF_SIZE_T LZO_SIZEOF_LONG
+# define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_LONG
+# else
+# define LZO_SIZEOF_VOID_P 16
+# define LZO_SIZEOF_SIZE_T LZO_SIZEOF_LONG
+# define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_LONG
+# endif
#elif (defined(__vms) || defined(__VMS)) && (__INITIAL_POINTER_SIZE+0 == 64)
# define LZO_SIZEOF_VOID_P 8
# define LZO_SIZEOF_SIZE_T LZO_SIZEOF_LONG
# define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_LONG
-#elif (LZO_ARCH_SPU)
-# if 0
-# define __LZO_WORDSIZE 16
-# endif
-# define LZO_SIZEOF_VOID_P 4
-#else
-# define LZO_SIZEOF_VOID_P LZO_SIZEOF_LONG
#endif
#endif
-#if !defined(LZO_WORDSIZE)
-# if defined(__LZO_WORDSIZE)
-# define LZO_WORDSIZE __LZO_WORDSIZE
-# else
-# define LZO_WORDSIZE LZO_SIZEOF_VOID_P
-# endif
+#if !defined(LZO_SIZEOF_VOID_P)
+# define LZO_SIZEOF_VOID_P LZO_SIZEOF_LONG
#endif
+LZO_COMPILE_TIME_ASSERT_HEADER(LZO_SIZEOF_VOID_P == sizeof(void *))
#if !defined(LZO_SIZEOF_SIZE_T)
#if (LZO_ARCH_I086 || LZO_ARCH_M16C)
# define LZO_SIZEOF_SIZE_T 2
-#else
+#endif
+#endif
+#if !defined(LZO_SIZEOF_SIZE_T)
# define LZO_SIZEOF_SIZE_T LZO_SIZEOF_VOID_P
#endif
+#if defined(offsetof)
+LZO_COMPILE_TIME_ASSERT_HEADER(LZO_SIZEOF_SIZE_T == sizeof(size_t))
#endif
#if !defined(LZO_SIZEOF_PTRDIFF_T)
#if (LZO_ARCH_I086)
@@ -1248,11 +2275,18 @@ extern "C" {
# define LZO_SIZEOF_PTRDIFF_T 2
# endif
# else
-# error "LZO_MM"
+# error "invalid LZO_ARCH_I086 memory model"
# endif
-#else
+#endif
+#endif
+#if !defined(LZO_SIZEOF_PTRDIFF_T)
# define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_SIZE_T
#endif
+#if defined(offsetof)
+LZO_COMPILE_TIME_ASSERT_HEADER(LZO_SIZEOF_PTRDIFF_T == sizeof(ptrdiff_t))
+#endif
+#if !defined(LZO_WORDSIZE)
+# define LZO_WORDSIZE LZO_SIZEOF_VOID_P
#endif
#if (LZO_ABI_NEUTRAL_ENDIAN)
# undef LZO_ABI_BIG_ENDIAN
@@ -1264,7 +2298,7 @@ extern "C" {
# define LZO_ABI_LITTLE_ENDIAN 1
#elif (LZO_ARCH_ALPHA || LZO_ARCH_AMD64 || LZO_ARCH_BLACKFIN || LZO_ARCH_CRIS || LZO_ARCH_I086 || LZO_ARCH_I386 || LZO_ARCH_MSP430)
# define LZO_ABI_LITTLE_ENDIAN 1
-#elif (LZO_ARCH_AVR32 || LZO_ARCH_M68K || LZO_ARCH_S390)
+#elif (LZO_ARCH_AVR32 || LZO_ARCH_M68K || LZO_ARCH_S390 || LZO_ARCH_SPU)
# define LZO_ABI_BIG_ENDIAN 1
#elif 1 && defined(__IAR_SYSTEMS_ICC__) && defined(__LITTLE_ENDIAN__)
# if (__LITTLE_ENDIAN__ == 1)
@@ -1280,6 +2314,19 @@ extern "C" {
# define LZO_ABI_BIG_ENDIAN 1
#elif 1 && (LZO_ARCH_ARM) && defined(__ARMEL__) && !defined(__ARMEB__)
# define LZO_ABI_LITTLE_ENDIAN 1
+#elif 1 && (LZO_ARCH_ARM && LZO_CC_ARMCC_ARMCC)
+# if defined(__BIG_ENDIAN) && defined(__LITTLE_ENDIAN)
+# error "unexpected configuration - check your compiler defines"
+# elif defined(__BIG_ENDIAN)
+# define LZO_ABI_BIG_ENDIAN 1
+# else
+# define LZO_ABI_LITTLE_ENDIAN 1
+# endif
+# define LZO_ABI_LITTLE_ENDIAN 1
+#elif 1 && (LZO_ARCH_ARM64) && defined(__AARCH64EB__) && !defined(__AARCH64EL__)
+# define LZO_ABI_BIG_ENDIAN 1
+#elif 1 && (LZO_ARCH_ARM64) && defined(__AARCH64EL__) && !defined(__AARCH64EB__)
+# define LZO_ABI_LITTLE_ENDIAN 1
#elif 1 && (LZO_ARCH_MIPS) && defined(__MIPSEB__) && !defined(__MIPSEL__)
# define LZO_ABI_BIG_ENDIAN 1
#elif 1 && (LZO_ARCH_MIPS) && defined(__MIPSEL__) && !defined(__MIPSEB__)
@@ -1287,7 +2334,7 @@ extern "C" {
#endif
#endif
#if (LZO_ABI_BIG_ENDIAN) && (LZO_ABI_LITTLE_ENDIAN)
-# error "this should not happen"
+# error "unexpected configuration - check your compiler defines"
#endif
#if (LZO_ABI_BIG_ENDIAN)
# define LZO_INFO_ABI_ENDIAN "be"
@@ -1302,6 +2349,9 @@ extern "C" {
#elif (LZO_SIZEOF_INT == 2 && LZO_SIZEOF_LONG == 2 && LZO_SIZEOF_VOID_P == 2)
# define LZO_ABI_ILP16 1
# define LZO_INFO_ABI_PM "ilp16"
+#elif (LZO_SIZEOF_INT == 2 && LZO_SIZEOF_LONG == 4 && LZO_SIZEOF_VOID_P == 4)
+# define LZO_ABI_LP32 1
+# define LZO_INFO_ABI_PM "lp32"
#elif (LZO_SIZEOF_INT == 4 && LZO_SIZEOF_LONG == 4 && LZO_SIZEOF_VOID_P == 4)
# define LZO_ABI_ILP32 1
# define LZO_INFO_ABI_PM "ilp32"
@@ -1318,7 +2368,8 @@ extern "C" {
# define LZO_ABI_IP32L64 1
# define LZO_INFO_ABI_PM "ip32l64"
#endif
-#if !defined(__LZO_LIBC_OVERRIDE)
+#if 0
+#elif !defined(__LZO_LIBC_OVERRIDE)
#if (LZO_LIBC_NAKED)
# define LZO_INFO_LIBC "naked"
#elif (LZO_LIBC_FREESTANDING)
@@ -1329,6 +2380,9 @@ extern "C" {
# define LZO_INFO_LIBC "isoc90"
#elif (LZO_LIBC_ISOC99)
# define LZO_INFO_LIBC "isoc99"
+#elif (LZO_CC_ARMCC_ARMCC) && defined(__ARMCLIB_VERSION)
+# define LZO_LIBC_ISOC90 1
+# define LZO_INFO_LIBC "isoc90"
#elif defined(__dietlibc__)
# define LZO_LIBC_DIETLIBC 1
# define LZO_INFO_LIBC "dietlibc"
@@ -1337,13 +2391,13 @@ extern "C" {
# define LZO_INFO_LIBC "newlib"
#elif defined(__UCLIBC__) && defined(__UCLIBC_MAJOR__) && defined(__UCLIBC_MINOR__)
# if defined(__UCLIBC_SUBLEVEL__)
-# define LZO_LIBC_UCLIBC (__UCLIBC_MAJOR__ * 0x10000L + __UCLIBC_MINOR__ * 0x100 + __UCLIBC_SUBLEVEL__)
+# define LZO_LIBC_UCLIBC (__UCLIBC_MAJOR__ * 0x10000L + (__UCLIBC_MINOR__-0) * 0x100 + (__UCLIBC_SUBLEVEL__-0))
# else
# define LZO_LIBC_UCLIBC 0x00090bL
# endif
-# define LZO_INFO_LIBC "uclibc"
+# define LZO_INFO_LIBC "uc" "libc"
#elif defined(__GLIBC__) && defined(__GLIBC_MINOR__)
-# define LZO_LIBC_GLIBC (__GLIBC__ * 0x10000L + __GLIBC_MINOR__ * 0x100)
+# define LZO_LIBC_GLIBC (__GLIBC__ * 0x10000L + (__GLIBC_MINOR__-0) * 0x100)
# define LZO_INFO_LIBC "glibc"
#elif (LZO_CC_MWERKS) && defined(__MSL__)
# define LZO_LIBC_MSL __MSL__
@@ -1356,424 +2410,160 @@ extern "C" {
# define LZO_INFO_LIBC "default"
#endif
#endif
-#if !defined(__lzo_gnuc_extension__)
-#if (LZO_CC_GNUC >= 0x020800ul)
-# define __lzo_gnuc_extension__ __extension__
-#elif (LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE)
-# define __lzo_gnuc_extension__ __extension__
-#else
-# define __lzo_gnuc_extension__ /*empty*/
-#endif
-#endif
-#if !defined(__lzo_ua_volatile)
-# define __lzo_ua_volatile volatile
-#endif
-#if !defined(__lzo_alignof)
-#if (LZO_CC_CILLY || LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE || LZO_CC_PGI)
-# define __lzo_alignof(e) __alignof__(e)
-#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 700))
-# define __lzo_alignof(e) __alignof__(e)
-#elif (LZO_CC_MSC && (_MSC_VER >= 1300))
-# define __lzo_alignof(e) __alignof(e)
-#elif (LZO_CC_SUNPROC && (LZO_CC_SUNPROC >= 0x5100))
-# define __lzo_alignof(e) __alignof__(e)
-#endif
-#endif
-#if defined(__lzo_alignof)
-# define __lzo_HAVE_alignof 1
-#endif
-#if !defined(__lzo_constructor)
-#if (LZO_CC_GNUC >= 0x030400ul)
-# define __lzo_constructor __attribute__((__constructor__,__used__))
-#elif (LZO_CC_GNUC >= 0x020700ul)
-# define __lzo_constructor __attribute__((__constructor__))
-#elif (LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE)
-# define __lzo_constructor __attribute__((__constructor__))
-#endif
-#endif
-#if defined(__lzo_constructor)
-# define __lzo_HAVE_constructor 1
-#endif
-#if !defined(__lzo_destructor)
-#if (LZO_CC_GNUC >= 0x030400ul)
-# define __lzo_destructor __attribute__((__destructor__,__used__))
-#elif (LZO_CC_GNUC >= 0x020700ul)
-# define __lzo_destructor __attribute__((__destructor__))
-#elif (LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE)
-# define __lzo_destructor __attribute__((__destructor__))
-#endif
-#endif
-#if defined(__lzo_destructor)
-# define __lzo_HAVE_destructor 1
-#endif
-#if (__lzo_HAVE_destructor) && !(__lzo_HAVE_constructor)
-# error "this should not happen"
-#endif
-#if !defined(__lzo_inline)
-#if (LZO_CC_TURBOC && (__TURBOC__ <= 0x0295))
-#elif defined(__cplusplus)
-# define __lzo_inline inline
-#elif (LZO_CC_BORLANDC && (__BORLANDC__ >= 0x0550))
-# define __lzo_inline __inline
-#elif (LZO_CC_CILLY || LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE || LZO_CC_PGI)
-# define __lzo_inline __inline__
-#elif (LZO_CC_DMC)
-# define __lzo_inline __inline
-#elif (LZO_CC_INTELC)
-# define __lzo_inline __inline
-#elif (LZO_CC_MWERKS && (__MWERKS__ >= 0x2405))
-# define __lzo_inline __inline
-#elif (LZO_CC_MSC && (_MSC_VER >= 900))
-# define __lzo_inline __inline
-#elif (LZO_CC_SUNPROC && (LZO_CC_SUNPROC >= 0x5100))
-# define __lzo_inline __inline__
-#elif defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
-# define __lzo_inline inline
-#endif
+#if (LZO_ARCH_I386 && (LZO_OS_DOS32 || LZO_OS_WIN32) && (LZO_CC_DMC || LZO_CC_INTELC || LZO_CC_MSC || LZO_CC_PELLESC))
+# define LZO_ASM_SYNTAX_MSC 1
+#elif (LZO_OS_WIN64 && (LZO_CC_DMC || LZO_CC_INTELC || LZO_CC_MSC || LZO_CC_PELLESC))
+#elif (LZO_ARCH_I386 && LZO_CC_GNUC && (LZO_CC_GNUC == 0x011f00ul))
+#elif (LZO_ARCH_I386 && (LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_INTELC || LZO_CC_PATHSCALE))
+# define LZO_ASM_SYNTAX_GNUC 1
+#elif (LZO_ARCH_AMD64 && (LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_INTELC || LZO_CC_PATHSCALE))
+# define LZO_ASM_SYNTAX_GNUC 1
+#elif (LZO_CC_GNUC)
+# define LZO_ASM_SYNTAX_GNUC 1
#endif
-#if defined(__lzo_inline)
-# define __lzo_HAVE_inline 1
+#if (LZO_ASM_SYNTAX_GNUC)
+#if (LZO_ARCH_I386 && LZO_CC_GNUC && (LZO_CC_GNUC < 0x020000ul))
+# define __LZO_ASM_CLOBBER "ax"
+# define __LZO_ASM_CLOBBER_LIST_CC /*empty*/
+# define __LZO_ASM_CLOBBER_LIST_CC_MEMORY /*empty*/
+# define __LZO_ASM_CLOBBER_LIST_EMPTY /*empty*/
+#elif (LZO_CC_INTELC && (__INTEL_COMPILER < 1000))
+# define __LZO_ASM_CLOBBER "memory"
+# define __LZO_ASM_CLOBBER_LIST_CC /*empty*/
+# define __LZO_ASM_CLOBBER_LIST_CC_MEMORY : "memory"
+# define __LZO_ASM_CLOBBER_LIST_EMPTY /*empty*/
#else
-# define __lzo_inline /*empty*/
-#endif
-#if !defined(__lzo_forceinline)
-#if (LZO_CC_GNUC >= 0x030200ul)
-# define __lzo_forceinline __inline__ __attribute__((__always_inline__))
-#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 450) && LZO_CC_SYNTAX_MSC)
-# define __lzo_forceinline __forceinline
-#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 800) && LZO_CC_SYNTAX_GNUC)
-# define __lzo_forceinline __inline__ __attribute__((__always_inline__))
-#elif (LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE)
-# define __lzo_forceinline __inline__ __attribute__((__always_inline__))
-#elif (LZO_CC_MSC && (_MSC_VER >= 1200))
-# define __lzo_forceinline __forceinline
-#elif (LZO_CC_SUNPROC && (LZO_CC_SUNPROC >= 0x5100))
-# define __lzo_forceinline __inline__ __attribute__((__always_inline__))
+# define __LZO_ASM_CLOBBER "cc", "memory"
+# define __LZO_ASM_CLOBBER_LIST_CC : "cc"
+# define __LZO_ASM_CLOBBER_LIST_CC_MEMORY : "cc", "memory"
+# define __LZO_ASM_CLOBBER_LIST_EMPTY /*empty*/
#endif
#endif
-#if defined(__lzo_forceinline)
-# define __lzo_HAVE_forceinline 1
-#else
-# define __lzo_forceinline /*empty*/
-#endif
-#if !defined(__lzo_noinline)
-#if 1 && (LZO_ARCH_I386) && (LZO_CC_GNUC >= 0x040000ul) && (LZO_CC_GNUC < 0x040003ul)
-# define __lzo_noinline __attribute__((__noinline__,__used__))
-#elif (LZO_CC_GNUC >= 0x030200ul)
-# define __lzo_noinline __attribute__((__noinline__))
-#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 600) && LZO_CC_SYNTAX_MSC)
-# define __lzo_noinline __declspec(noinline)
-#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 800) && LZO_CC_SYNTAX_GNUC)
-# define __lzo_noinline __attribute__((__noinline__))
-#elif (LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE)
-# define __lzo_noinline __attribute__((__noinline__))
-#elif (LZO_CC_MSC && (_MSC_VER >= 1300))
-# define __lzo_noinline __declspec(noinline)
-#elif (LZO_CC_MWERKS && (__MWERKS__ >= 0x3200) && (LZO_OS_WIN32 || LZO_OS_WIN64))
-# if defined(__cplusplus)
-# else
-# define __lzo_noinline __declspec(noinline)
+#if (LZO_ARCH_ALPHA)
+# define LZO_OPT_AVOID_UINT_INDEX 1
+#elif (LZO_ARCH_AMD64)
+# define LZO_OPT_AVOID_INT_INDEX 1
+# define LZO_OPT_AVOID_UINT_INDEX 1
+# ifndef LZO_OPT_UNALIGNED16
+# define LZO_OPT_UNALIGNED16 1
# endif
-#elif (LZO_CC_SUNPROC && (LZO_CC_SUNPROC >= 0x5100))
-# define __lzo_noinline __attribute__((__noinline__))
-#endif
-#endif
-#if defined(__lzo_noinline)
-# define __lzo_HAVE_noinline 1
-#else
-# define __lzo_noinline /*empty*/
-#endif
-#if (__lzo_HAVE_forceinline || __lzo_HAVE_noinline) && !(__lzo_HAVE_inline)
-# error "this should not happen"
-#endif
-#if !defined(__lzo_noreturn)
-#if (LZO_CC_GNUC >= 0x020700ul)
-# define __lzo_noreturn __attribute__((__noreturn__))
-#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 450) && LZO_CC_SYNTAX_MSC)
-# define __lzo_noreturn __declspec(noreturn)
-#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 600) && LZO_CC_SYNTAX_GNUC)
-# define __lzo_noreturn __attribute__((__noreturn__))
-#elif (LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE)
-# define __lzo_noreturn __attribute__((__noreturn__))
-#elif (LZO_CC_MSC && (_MSC_VER >= 1200))
-# define __lzo_noreturn __declspec(noreturn)
-#endif
-#endif
-#if defined(__lzo_noreturn)
-# define __lzo_HAVE_noreturn 1
-#else
-# define __lzo_noreturn /*empty*/
-#endif
-#if !defined(__lzo_nothrow)
-#if (LZO_CC_GNUC >= 0x030300ul)
-# define __lzo_nothrow __attribute__((__nothrow__))
-#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 450) && LZO_CC_SYNTAX_MSC) && defined(__cplusplus)
-# define __lzo_nothrow __declspec(nothrow)
-#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 900) && LZO_CC_SYNTAX_GNUC)
-# define __lzo_nothrow __attribute__((__nothrow__))
-#elif (LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE)
-# define __lzo_nothrow __attribute__((__nothrow__))
-#elif (LZO_CC_MSC && (_MSC_VER >= 1200)) && defined(__cplusplus)
-# define __lzo_nothrow __declspec(nothrow)
-#endif
-#endif
-#if defined(__lzo_nothrow)
-# define __lzo_HAVE_nothrow 1
-#else
-# define __lzo_nothrow /*empty*/
-#endif
-#if !defined(__lzo_restrict)
-#if (LZO_CC_GNUC >= 0x030400ul)
-# define __lzo_restrict __restrict__
-#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 600) && LZO_CC_SYNTAX_GNUC)
-# define __lzo_restrict __restrict__
-#elif (LZO_CC_CLANG || LZO_CC_LLVM)
-# define __lzo_restrict __restrict__
-#elif (LZO_CC_MSC && (_MSC_VER >= 1400))
-# define __lzo_restrict __restrict
-#endif
-#endif
-#if defined(__lzo_restrict)
-# define __lzo_HAVE_restrict 1
-#else
-# define __lzo_restrict /*empty*/
-#endif
-#if !defined(__lzo_likely) && !defined(__lzo_unlikely)
-#if (LZO_CC_GNUC >= 0x030200ul)
-# define __lzo_likely(e) (__builtin_expect(!!(e),1))
-# define __lzo_unlikely(e) (__builtin_expect(!!(e),0))
-#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 800))
-# define __lzo_likely(e) (__builtin_expect(!!(e),1))
-# define __lzo_unlikely(e) (__builtin_expect(!!(e),0))
-#elif (LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE)
-# define __lzo_likely(e) (__builtin_expect(!!(e),1))
-# define __lzo_unlikely(e) (__builtin_expect(!!(e),0))
-#endif
-#endif
-#if defined(__lzo_likely)
-# define __lzo_HAVE_likely 1
-#else
-# define __lzo_likely(e) (e)
-#endif
-#if defined(__lzo_unlikely)
-# define __lzo_HAVE_unlikely 1
-#else
-# define __lzo_unlikely(e) (e)
-#endif
-#if !defined(LZO_UNUSED)
-# if (LZO_CC_BORLANDC && (__BORLANDC__ >= 0x0600))
-# define LZO_UNUSED(var) ((void) &var)
-# elif (LZO_CC_BORLANDC || LZO_CC_HIGHC || LZO_CC_NDPC || LZO_CC_PELLESC || LZO_CC_TURBOC)
-# define LZO_UNUSED(var) if (&var) ; else
-# elif (LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE)
-# define LZO_UNUSED(var) ((void) var)
-# elif (LZO_CC_MSC && (_MSC_VER < 900))
-# define LZO_UNUSED(var) if (&var) ; else
-# elif (LZO_CC_KEILC)
-# define LZO_UNUSED(var) {extern int __lzo_unused[1-2*!(sizeof(var)>0)];}
-# elif (LZO_CC_PACIFICC)
-# define LZO_UNUSED(var) ((void) sizeof(var))
-# elif (LZO_CC_WATCOMC) && defined(__cplusplus)
-# define LZO_UNUSED(var) ((void) var)
-# else
-# define LZO_UNUSED(var) ((void) &var)
+# ifndef LZO_OPT_UNALIGNED32
+# define LZO_OPT_UNALIGNED32 1
# endif
-#endif
-#if !defined(LZO_UNUSED_FUNC)
-# if (LZO_CC_BORLANDC && (__BORLANDC__ >= 0x0600))
-# define LZO_UNUSED_FUNC(func) ((void) func)
-# elif (LZO_CC_BORLANDC || LZO_CC_NDPC || LZO_CC_TURBOC)
-# define LZO_UNUSED_FUNC(func) if (func) ; else
-# elif (LZO_CC_CLANG || LZO_CC_LLVM)
-# define LZO_UNUSED_FUNC(func) ((void) &func)
-# elif (LZO_CC_MSC && (_MSC_VER < 900))
-# define LZO_UNUSED_FUNC(func) if (func) ; else
-# elif (LZO_CC_MSC)
-# define LZO_UNUSED_FUNC(func) ((void) &func)
-# elif (LZO_CC_KEILC || LZO_CC_PELLESC)
-# define LZO_UNUSED_FUNC(func) {extern int __lzo_unused[1-2*!(sizeof((int)func)>0)];}
-# else
-# define LZO_UNUSED_FUNC(func) ((void) func)
+# ifndef LZO_OPT_UNALIGNED64
+# define LZO_OPT_UNALIGNED64 1
# endif
-#endif
-#if !defined(LZO_UNUSED_LABEL)
-# if (LZO_CC_WATCOMC) && defined(__cplusplus)
-# define LZO_UNUSED_LABEL(l) switch(0) case 1:goto l
-# elif (LZO_CC_CLANG || LZO_CC_INTELC || LZO_CC_WATCOMC)
-# define LZO_UNUSED_LABEL(l) if (0) goto l
-# else
-# define LZO_UNUSED_LABEL(l) switch(0) case 1:goto l
+#elif (LZO_ARCH_ARM)
+# if defined(__ARM_FEATURE_UNALIGNED)
+# ifndef LZO_OPT_UNALIGNED16
+# define LZO_OPT_UNALIGNED16 1
+# endif
+# ifndef LZO_OPT_UNALIGNED32
+# define LZO_OPT_UNALIGNED32 1
+# endif
+# elif defined(__TARGET_ARCH_ARM) && ((__TARGET_ARCH_ARM+0) >= 7)
+# ifndef LZO_OPT_UNALIGNED16
+# define LZO_OPT_UNALIGNED16 1
+# endif
+# ifndef LZO_OPT_UNALIGNED32
+# define LZO_OPT_UNALIGNED32 1
+# endif
+# elif defined(__TARGET_ARCH_ARM) && ((__TARGET_ARCH_ARM+0) >= 6) && !defined(__TARGET_PROFILE_M)
+# ifndef LZO_OPT_UNALIGNED16
+# define LZO_OPT_UNALIGNED16 1
+# endif
+# ifndef LZO_OPT_UNALIGNED32
+# define LZO_OPT_UNALIGNED32 1
+# endif
# endif
-#endif
-#if !defined(LZO_DEFINE_UNINITIALIZED_VAR)
-# if 0
-# define LZO_DEFINE_UNINITIALIZED_VAR(type,var,init) type var
-# elif 0 && (LZO_CC_GNUC)
-# define LZO_DEFINE_UNINITIALIZED_VAR(type,var,init) type var = var
-# else
-# define LZO_DEFINE_UNINITIALIZED_VAR(type,var,init) type var = init
+#elif (LZO_ARCH_ARM64)
+# ifndef LZO_OPT_UNALIGNED16
+# define LZO_OPT_UNALIGNED16 1
# endif
-#endif
-#if !defined(LZO_UNCONST_CAST)
-# if 0 && defined(__cplusplus)
-# define LZO_UNCONST_CAST(t,e) (const_cast<t> (e))
-# elif (LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE)
-# define LZO_UNCONST_CAST(t,e) ((t) ((void *) ((char *) ((lzo_uintptr_t) ((const void *) (e))))))
-# else
-# define LZO_UNCONST_CAST(t,e) ((t) ((void *) ((char *) ((const void *) (e)))))
+# ifndef LZO_OPT_UNALIGNED32
+# define LZO_OPT_UNALIGNED32 1
# endif
-#endif
-#if !defined(LZO_COMPILE_TIME_ASSERT_HEADER)
-# if (LZO_CC_AZTECC || LZO_CC_ZORTECHC)
-# define LZO_COMPILE_TIME_ASSERT_HEADER(e) extern int __lzo_cta[1-!(e)];
-# elif (LZO_CC_DMC || LZO_CC_SYMANTECC)
-# define LZO_COMPILE_TIME_ASSERT_HEADER(e) extern int __lzo_cta[1u-2*!(e)];
-# elif (LZO_CC_TURBOC && (__TURBOC__ == 0x0295))
-# define LZO_COMPILE_TIME_ASSERT_HEADER(e) extern int __lzo_cta[1-!(e)];
-# else
-# define LZO_COMPILE_TIME_ASSERT_HEADER(e) extern int __lzo_cta[1-2*!(e)];
+# ifndef LZO_OPT_UNALIGNED64
+# define LZO_OPT_UNALIGNED64 1
# endif
-#endif
-#if !defined(LZO_COMPILE_TIME_ASSERT)
-# if (LZO_CC_AZTECC)
-# define LZO_COMPILE_TIME_ASSERT(e) {typedef int __lzo_cta_t[1-!(e)];}
-# elif (LZO_CC_DMC || LZO_CC_PACIFICC || LZO_CC_SYMANTECC || LZO_CC_ZORTECHC)
-# define LZO_COMPILE_TIME_ASSERT(e) switch(0) case 1:case !(e):break;
-# elif (LZO_CC_MSC && (_MSC_VER < 900))
-# define LZO_COMPILE_TIME_ASSERT(e) switch(0) case 1:case !(e):break;
-# elif (LZO_CC_TURBOC && (__TURBOC__ == 0x0295))
-# define LZO_COMPILE_TIME_ASSERT(e) switch(0) case 1:case !(e):break;
-# else
-# define LZO_COMPILE_TIME_ASSERT(e) {typedef int __lzo_cta_t[1-2*!(e)];}
+#elif (LZO_ARCH_CRIS)
+# ifndef LZO_OPT_UNALIGNED16
+# define LZO_OPT_UNALIGNED16 1
# endif
-#endif
-#if (LZO_ARCH_I086 || LZO_ARCH_I386) && (LZO_OS_DOS16 || LZO_OS_DOS32 || LZO_OS_OS2 || LZO_OS_OS216 || LZO_OS_WIN16 || LZO_OS_WIN32 || LZO_OS_WIN64)
-# if (LZO_CC_GNUC || LZO_CC_HIGHC || LZO_CC_NDPC || LZO_CC_PACIFICC)
-# elif (LZO_CC_DMC || LZO_CC_SYMANTECC || LZO_CC_ZORTECHC)
-# define __lzo_cdecl __cdecl
-# define __lzo_cdecl_atexit /*empty*/
-# define __lzo_cdecl_main __cdecl
-# if (LZO_OS_OS2 && (LZO_CC_DMC || LZO_CC_SYMANTECC))
-# define __lzo_cdecl_qsort __pascal
-# elif (LZO_OS_OS2 && (LZO_CC_ZORTECHC))
-# define __lzo_cdecl_qsort _stdcall
-# else
-# define __lzo_cdecl_qsort __cdecl
-# endif
-# elif (LZO_CC_WATCOMC)
-# define __lzo_cdecl __cdecl
-# else
-# define __lzo_cdecl __cdecl
-# define __lzo_cdecl_atexit __cdecl
-# define __lzo_cdecl_main __cdecl
-# define __lzo_cdecl_qsort __cdecl
+# ifndef LZO_OPT_UNALIGNED32
+# define LZO_OPT_UNALIGNED32 1
# endif
-# if (LZO_CC_GNUC || LZO_CC_HIGHC || LZO_CC_NDPC || LZO_CC_PACIFICC || LZO_CC_WATCOMC)
-# elif (LZO_OS_OS2 && (LZO_CC_DMC || LZO_CC_SYMANTECC))
-# define __lzo_cdecl_sighandler __pascal
-# elif (LZO_OS_OS2 && (LZO_CC_ZORTECHC))
-# define __lzo_cdecl_sighandler _stdcall
-# elif (LZO_CC_MSC && (_MSC_VER >= 1400)) && defined(_M_CEE_PURE)
-# define __lzo_cdecl_sighandler __clrcall
-# elif (LZO_CC_MSC && (_MSC_VER >= 600 && _MSC_VER < 700))
-# if defined(_DLL)
-# define __lzo_cdecl_sighandler _far _cdecl _loadds
-# elif defined(_MT)
-# define __lzo_cdecl_sighandler _far _cdecl
-# else
-# define __lzo_cdecl_sighandler _cdecl
-# endif
-# else
-# define __lzo_cdecl_sighandler __cdecl
+#elif (LZO_ARCH_I386)
+# ifndef LZO_OPT_UNALIGNED16
+# define LZO_OPT_UNALIGNED16 1
# endif
-#elif (LZO_ARCH_I386) && (LZO_CC_WATCOMC)
-# define __lzo_cdecl __cdecl
-#elif (LZO_ARCH_M68K && LZO_OS_TOS && (LZO_CC_PUREC || LZO_CC_TURBOC))
-# define __lzo_cdecl cdecl
-#endif
-#if !defined(__lzo_cdecl)
-# define __lzo_cdecl /*empty*/
-#endif
-#if !defined(__lzo_cdecl_atexit)
-# define __lzo_cdecl_atexit /*empty*/
-#endif
-#if !defined(__lzo_cdecl_main)
-# define __lzo_cdecl_main /*empty*/
-#endif
-#if !defined(__lzo_cdecl_qsort)
-# define __lzo_cdecl_qsort /*empty*/
-#endif
-#if !defined(__lzo_cdecl_sighandler)
-# define __lzo_cdecl_sighandler /*empty*/
-#endif
-#if !defined(__lzo_cdecl_va)
-# define __lzo_cdecl_va __lzo_cdecl
-#endif
-#if !(LZO_CFG_NO_WINDOWS_H)
-#if (LZO_OS_CYGWIN || (LZO_OS_EMX && defined(__RSXNT__)) || LZO_OS_WIN32 || LZO_OS_WIN64)
-# if (LZO_CC_WATCOMC && (__WATCOMC__ < 1000))
-# elif (LZO_OS_WIN32 && LZO_CC_GNUC) && defined(__PW32__)
-# elif ((LZO_OS_CYGWIN || defined(__MINGW32__)) && (LZO_CC_GNUC && (LZO_CC_GNUC < 0x025f00ul)))
-# else
-# define LZO_HAVE_WINDOWS_H 1
+# ifndef LZO_OPT_UNALIGNED32
+# define LZO_OPT_UNALIGNED32 1
# endif
-#endif
-#endif
-#if (LZO_ARCH_ALPHA)
-# define LZO_OPT_AVOID_UINT_INDEX 1
-# define LZO_OPT_AVOID_SHORT 1
-# define LZO_OPT_AVOID_USHORT 1
-#elif (LZO_ARCH_AMD64)
-# define LZO_OPT_AVOID_INT_INDEX 1
-# define LZO_OPT_AVOID_UINT_INDEX 1
-# define LZO_OPT_UNALIGNED16 1
-# define LZO_OPT_UNALIGNED32 1
-# define LZO_OPT_UNALIGNED64 1
-#elif (LZO_ARCH_ARM && LZO_ARCH_ARM_THUMB)
-#elif (LZO_ARCH_ARM)
-# define LZO_OPT_AVOID_SHORT 1
-# define LZO_OPT_AVOID_USHORT 1
-#elif (LZO_ARCH_CRIS)
-# define LZO_OPT_UNALIGNED16 1
-# define LZO_OPT_UNALIGNED32 1
-#elif (LZO_ARCH_I386)
-# define LZO_OPT_UNALIGNED16 1
-# define LZO_OPT_UNALIGNED32 1
#elif (LZO_ARCH_IA64)
-# define LZO_OPT_AVOID_INT_INDEX 1
-# define LZO_OPT_AVOID_UINT_INDEX 1
-# define LZO_OPT_PREFER_POSTINC 1
+# define LZO_OPT_AVOID_INT_INDEX 1
+# define LZO_OPT_AVOID_UINT_INDEX 1
+# define LZO_OPT_PREFER_POSTINC 1
#elif (LZO_ARCH_M68K)
-# define LZO_OPT_PREFER_POSTINC 1
-# define LZO_OPT_PREFER_PREDEC 1
+# define LZO_OPT_PREFER_POSTINC 1
+# define LZO_OPT_PREFER_PREDEC 1
# if defined(__mc68020__) && !defined(__mcoldfire__)
-# define LZO_OPT_UNALIGNED16 1
-# define LZO_OPT_UNALIGNED32 1
+# ifndef LZO_OPT_UNALIGNED16
+# define LZO_OPT_UNALIGNED16 1
+# endif
+# ifndef LZO_OPT_UNALIGNED32
+# define LZO_OPT_UNALIGNED32 1
+# endif
# endif
#elif (LZO_ARCH_MIPS)
-# define LZO_OPT_AVOID_UINT_INDEX 1
+# define LZO_OPT_AVOID_UINT_INDEX 1
#elif (LZO_ARCH_POWERPC)
-# define LZO_OPT_PREFER_PREINC 1
-# define LZO_OPT_PREFER_PREDEC 1
+# define LZO_OPT_PREFER_PREINC 1
+# define LZO_OPT_PREFER_PREDEC 1
# if (LZO_ABI_BIG_ENDIAN)
-# define LZO_OPT_UNALIGNED16 1
-# define LZO_OPT_UNALIGNED32 1
+# ifndef LZO_OPT_UNALIGNED16
+# define LZO_OPT_UNALIGNED16 1
+# endif
+# ifndef LZO_OPT_UNALIGNED32
+# define LZO_OPT_UNALIGNED32 1
+# endif
+# if (LZO_WORDSIZE == 8)
+# ifndef LZO_OPT_UNALIGNED64
+# define LZO_OPT_UNALIGNED64 1
+# endif
+# endif
# endif
#elif (LZO_ARCH_S390)
-# define LZO_OPT_UNALIGNED16 1
-# define LZO_OPT_UNALIGNED32 1
-# if (LZO_SIZEOF_SIZE_T == 8)
-# define LZO_OPT_UNALIGNED64 1
+# ifndef LZO_OPT_UNALIGNED16
+# define LZO_OPT_UNALIGNED16 1
+# endif
+# ifndef LZO_OPT_UNALIGNED32
+# define LZO_OPT_UNALIGNED32 1
+# endif
+# if (LZO_WORDSIZE == 8)
+# ifndef LZO_OPT_UNALIGNED64
+# define LZO_OPT_UNALIGNED64 1
+# endif
# endif
#elif (LZO_ARCH_SH)
-# define LZO_OPT_PREFER_POSTINC 1
-# define LZO_OPT_PREFER_PREDEC 1
+# define LZO_OPT_PREFER_POSTINC 1
+# define LZO_OPT_PREFER_PREDEC 1
#endif
#ifndef LZO_CFG_NO_INLINE_ASM
-#if (LZO_CC_LLVM)
+#if (LZO_ABI_NEUTRAL_ENDIAN) || (LZO_ARCH_GENERIC)
+# define LZO_CFG_NO_INLINE_ASM 1
+#elif (LZO_CC_LLVM)
# define LZO_CFG_NO_INLINE_ASM 1
#endif
#endif
+#if (LZO_CFG_NO_INLINE_ASM)
+# undef LZO_ASM_SYNTAX_MSC
+# undef LZO_ASM_SYNTAX_GNUC
+# undef __LZO_ASM_CLOBBER
+# undef __LZO_ASM_CLOBBER_LIST_CC
+# undef __LZO_ASM_CLOBBER_LIST_CC_MEMORY
+# undef __LZO_ASM_CLOBBER_LIST_EMPTY
+#endif
#ifndef LZO_CFG_NO_UNALIGNED
#if (LZO_ABI_NEUTRAL_ENDIAN) || (LZO_ARCH_GENERIC)
# define LZO_CFG_NO_UNALIGNED 1
@@ -1784,25 +2574,6 @@ extern "C" {
# undef LZO_OPT_UNALIGNED32
# undef LZO_OPT_UNALIGNED64
#endif
-#if (LZO_CFG_NO_INLINE_ASM)
-#elif (LZO_ARCH_I386 && (LZO_OS_DOS32 || LZO_OS_WIN32) && (LZO_CC_DMC || LZO_CC_INTELC || LZO_CC_MSC || LZO_CC_PELLESC))
-# define LZO_ASM_SYNTAX_MSC 1
-#elif (LZO_OS_WIN64 && (LZO_CC_DMC || LZO_CC_INTELC || LZO_CC_MSC || LZO_CC_PELLESC))
-#elif (LZO_ARCH_I386 && LZO_CC_GNUC && (LZO_CC_GNUC == 0x011f00ul))
-#elif (LZO_ARCH_I386 && (LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_INTELC || LZO_CC_PATHSCALE))
-# define LZO_ASM_SYNTAX_GNUC 1
-#elif (LZO_ARCH_AMD64 && (LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_INTELC || LZO_CC_PATHSCALE))
-# define LZO_ASM_SYNTAX_GNUC 1
-#endif
-#if (LZO_ASM_SYNTAX_GNUC)
-#if (LZO_ARCH_I386 && LZO_CC_GNUC && (LZO_CC_GNUC < 0x020000ul))
-# define __LZO_ASM_CLOBBER "ax"
-#elif (LZO_CC_INTELC)
-# define __LZO_ASM_CLOBBER "memory"
-#else
-# define __LZO_ASM_CLOBBER "cc", "memory"
-#endif
-#endif
#if defined(__LZO_INFOSTR_MM)
#elif (LZO_MM_FLAT) && (defined(__LZO_INFOSTR_PM) || defined(LZO_INFO_ABI_PM))
# define __LZO_INFOSTR_MM ""
@@ -1846,7 +2617,382 @@ extern "C" {
#define LZO_INFO_STRING \
LZO_INFO_ARCH __LZO_INFOSTR_MM __LZO_INFOSTR_PM __LZO_INFOSTR_ENDIAN \
" " __LZO_INFOSTR_OSNAME __LZO_INFOSTR_LIBC " " LZO_INFO_CC __LZO_INFOSTR_CCVER
+#if !(LZO_CFG_SKIP_LZO_TYPES)
+#if (!(LZO_SIZEOF_SHORT+0 > 0 && LZO_SIZEOF_INT+0 > 0 && LZO_SIZEOF_LONG+0 > 0))
+# error "missing defines for sizes"
+#endif
+#if (!(LZO_SIZEOF_PTRDIFF_T+0 > 0 && LZO_SIZEOF_SIZE_T+0 > 0 && LZO_SIZEOF_VOID_P+0 > 0))
+# error "missing defines for sizes"
+#endif
+#if !defined(lzo_llong_t)
+#if (LZO_SIZEOF_LONG_LONG+0 > 0)
+__lzo_gnuc_extension__ typedef long long lzo_llong_t__;
+__lzo_gnuc_extension__ typedef unsigned long long lzo_ullong_t__;
+# define lzo_llong_t lzo_llong_t__
+# define lzo_ullong_t lzo_ullong_t__
+#endif
+#endif
+#if !defined(lzo_int16e_t)
+#if (LZO_SIZEOF_LONG == 2)
+# define lzo_int16e_t long
+# define lzo_uint16e_t unsigned long
+#elif (LZO_SIZEOF_INT == 2)
+# define lzo_int16e_t int
+# define lzo_uint16e_t unsigned int
+#elif (LZO_SIZEOF_SHORT == 2)
+# define lzo_int16e_t short int
+# define lzo_uint16e_t unsigned short int
+#elif 1 && !(LZO_CFG_TYPE_NO_MODE_HI) && (LZO_CC_CLANG || (LZO_CC_GNUC >= 0x025f00ul) || LZO_CC_LLVM)
+ typedef int lzo_int16e_hi_t__ __attribute__((__mode__(__HI__)));
+ typedef unsigned int lzo_uint16e_hi_t__ __attribute__((__mode__(__HI__)));
+# define lzo_int16e_t lzo_int16e_hi_t__
+# define lzo_uint16e_t lzo_uint16e_hi_t__
+#elif (LZO_SIZEOF___INT16 == 2)
+# define lzo_int16e_t __int16
+# define lzo_uint16e_t unsigned __int16
+#else
+#endif
+#endif
+#if defined(lzo_int16e_t)
+# define LZO_SIZEOF_LZO_INT16E_T 2
+ LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int16e_t) == 2)
+ LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int16e_t) == LZO_SIZEOF_LZO_INT16E_T)
+#endif
+#if !defined(lzo_int32e_t)
+#if (LZO_SIZEOF_LONG == 4)
+# define lzo_int32e_t long int
+# define lzo_uint32e_t unsigned long int
+#elif (LZO_SIZEOF_INT == 4)
+# define lzo_int32e_t int
+# define lzo_uint32e_t unsigned int
+#elif (LZO_SIZEOF_SHORT == 4)
+# define lzo_int32e_t short int
+# define lzo_uint32e_t unsigned short int
+#elif (LZO_SIZEOF_LONG_LONG == 4)
+# define lzo_int32e_t lzo_llong_t
+# define lzo_uint32e_t lzo_ullong_t
+#elif 1 && !(LZO_CFG_TYPE_NO_MODE_SI) && (LZO_CC_CLANG || (LZO_CC_GNUC >= 0x025f00ul) || LZO_CC_LLVM) && (__INT_MAX__+0 > 2147483647L)
+ typedef int lzo_int32e_si_t__ __attribute__((__mode__(__SI__)));
+ typedef unsigned int lzo_uint32e_si_t__ __attribute__((__mode__(__SI__)));
+# define lzo_int32e_t lzo_int32e_si_t__
+# define lzo_uint32e_t lzo_uint32e_si_t__
+#elif 1 && !(LZO_CFG_TYPE_NO_MODE_SI) && (LZO_CC_GNUC >= 0x025f00ul) && defined(__AVR__) && (__LONG_MAX__+0 == 32767L)
+ typedef int lzo_int32e_si_t__ __attribute__((__mode__(__SI__)));
+ typedef unsigned int lzo_uint32e_si_t__ __attribute__((__mode__(__SI__)));
+# define lzo_int32e_t lzo_int32e_si_t__
+# define lzo_uint32e_t lzo_uint32e_si_t__
+# define LZO_INT32_C(c) (c##LL)
+# define LZO_UINT32_C(c) (c##ULL)
+#elif (LZO_SIZEOF___INT32 == 4)
+# define lzo_int32e_t __int32
+# define lzo_uint32e_t unsigned __int32
+#else
+#endif
+#endif
+#if defined(lzo_int32e_t)
+# define LZO_SIZEOF_LZO_INT32E_T 4
+ LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int32e_t) == 4)
+ LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int32e_t) == LZO_SIZEOF_LZO_INT32E_T)
+#endif
+#if !defined(lzo_int64e_t)
+#if (LZO_SIZEOF___INT64 == 8)
+# if (LZO_CC_BORLANDC) && !(LZO_CFG_TYPE_PREFER___INT64)
+# define LZO_CFG_TYPE_PREFER___INT64 1
+# endif
+#endif
+#if (LZO_SIZEOF_INT == 8) && (LZO_SIZEOF_INT < LZO_SIZEOF_LONG)
+# define lzo_int64e_t int
+# define lzo_uint64e_t unsigned int
+# define LZO_SIZEOF_LZO_INT64E_T LZO_SIZEOF_INT
+#elif (LZO_SIZEOF_LONG == 8)
+# define lzo_int64e_t long int
+# define lzo_uint64e_t unsigned long int
+# define LZO_SIZEOF_LZO_INT64E_T LZO_SIZEOF_LONG
+#elif (LZO_SIZEOF_LONG_LONG == 8) && !(LZO_CFG_TYPE_PREFER___INT64)
+# define lzo_int64e_t lzo_llong_t
+# define lzo_uint64e_t lzo_ullong_t
+# if (LZO_CC_BORLANDC)
+# define LZO_INT64_C(c) ((c) + 0ll)
+# define LZO_UINT64_C(c) ((c) + 0ull)
+# elif 0
+# define LZO_INT64_C(c) (__lzo_gnuc_extension__ (c##LL))
+# define LZO_UINT64_C(c) (__lzo_gnuc_extension__ (c##ULL))
+# else
+# define LZO_INT64_C(c) (c##LL)
+# define LZO_UINT64_C(c) (c##ULL)
+# endif
+# define LZO_SIZEOF_LZO_INT64E_T LZO_SIZEOF_LONG_LONG
+#elif (LZO_SIZEOF___INT64 == 8)
+# define lzo_int64e_t __int64
+# define lzo_uint64e_t unsigned __int64
+# if (LZO_CC_BORLANDC)
+# define LZO_INT64_C(c) ((c) + 0i64)
+# define LZO_UINT64_C(c) ((c) + 0ui64)
+# else
+# define LZO_INT64_C(c) (c##i64)
+# define LZO_UINT64_C(c) (c##ui64)
+# endif
+# define LZO_SIZEOF_LZO_INT64E_T LZO_SIZEOF___INT64
+#else
+#endif
+#endif
+#if defined(lzo_int64e_t)
+ LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int64e_t) == 8)
+ LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int64e_t) == LZO_SIZEOF_LZO_INT64E_T)
+#endif
+#if !defined(lzo_int32l_t)
+#if defined(lzo_int32e_t)
+# define lzo_int32l_t lzo_int32e_t
+# define lzo_uint32l_t lzo_uint32e_t
+# define LZO_SIZEOF_LZO_INT32L_T LZO_SIZEOF_LZO_INT32E_T
+#elif (LZO_SIZEOF_INT >= 4) && (LZO_SIZEOF_INT < LZO_SIZEOF_LONG)
+# define lzo_int32l_t int
+# define lzo_uint32l_t unsigned int
+# define LZO_SIZEOF_LZO_INT32L_T LZO_SIZEOF_INT
+#elif (LZO_SIZEOF_LONG >= 4)
+# define lzo_int32l_t long int
+# define lzo_uint32l_t unsigned long int
+# define LZO_SIZEOF_LZO_INT32L_T LZO_SIZEOF_LONG
+#else
+# error "lzo_int32l_t"
+#endif
+#endif
+#if 1
+ LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int32l_t) >= 4)
+ LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int32l_t) == LZO_SIZEOF_LZO_INT32L_T)
+#endif
+#if !defined(lzo_int64l_t)
+#if defined(lzo_int64e_t)
+# define lzo_int64l_t lzo_int64e_t
+# define lzo_uint64l_t lzo_uint64e_t
+# define LZO_SIZEOF_LZO_INT64L_T LZO_SIZEOF_LZO_INT64E_T
+#else
+#endif
+#endif
+#if defined(lzo_int64l_t)
+ LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int64l_t) >= 8)
+ LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int64l_t) == LZO_SIZEOF_LZO_INT64L_T)
+#endif
+#if !defined(lzo_int32f_t)
+#if (LZO_SIZEOF_SIZE_T >= 8)
+# define lzo_int32f_t lzo_int64l_t
+# define lzo_uint32f_t lzo_uint64l_t
+# define LZO_SIZEOF_LZO_INT32F_T LZO_SIZEOF_LZO_INT64L_T
+#else
+# define lzo_int32f_t lzo_int32l_t
+# define lzo_uint32f_t lzo_uint32l_t
+# define LZO_SIZEOF_LZO_INT32F_T LZO_SIZEOF_LZO_INT32L_T
+#endif
+#endif
+#if 1
+ LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int32f_t) >= 4)
+ LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int32f_t) == LZO_SIZEOF_LZO_INT32F_T)
+#endif
+#if !defined(lzo_int64f_t)
+#if defined(lzo_int64l_t)
+# define lzo_int64f_t lzo_int64l_t
+# define lzo_uint64f_t lzo_uint64l_t
+# define LZO_SIZEOF_LZO_INT64F_T LZO_SIZEOF_LZO_INT64L_T
+#else
+#endif
+#endif
+#if defined(lzo_int64f_t)
+ LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int64f_t) >= 8)
+ LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int64f_t) == LZO_SIZEOF_LZO_INT64F_T)
+#endif
+#if !defined(lzo_intptr_t)
+#if 1 && (LZO_OS_OS400 && (LZO_SIZEOF_VOID_P == 16))
+# define __LZO_INTPTR_T_IS_POINTER 1
+ typedef char* lzo_intptr_t;
+ typedef char* lzo_uintptr_t;
+# define lzo_intptr_t lzo_intptr_t
+# define lzo_uintptr_t lzo_uintptr_t
+# define LZO_SIZEOF_LZO_INTPTR_T LZO_SIZEOF_VOID_P
+#elif (LZO_CC_MSC && (_MSC_VER >= 1300) && (LZO_SIZEOF_VOID_P == 4) && (LZO_SIZEOF_INT == 4))
+ typedef __w64 int lzo_intptr_t;
+ typedef __w64 unsigned int lzo_uintptr_t;
+# define lzo_intptr_t lzo_intptr_t
+# define lzo_uintptr_t lzo_uintptr_t
+# define LZO_SIZEOF_LZO_INTPTR_T LZO_SIZEOF_INT
+#elif (LZO_SIZEOF_SHORT == LZO_SIZEOF_VOID_P) && (LZO_SIZEOF_INT > LZO_SIZEOF_VOID_P)
+# define lzo_intptr_t short
+# define lzo_uintptr_t unsigned short
+# define LZO_SIZEOF_LZO_INTPTR_T LZO_SIZEOF_SHORT
+#elif (LZO_SIZEOF_INT >= LZO_SIZEOF_VOID_P) && (LZO_SIZEOF_INT < LZO_SIZEOF_LONG)
+# define lzo_intptr_t int
+# define lzo_uintptr_t unsigned int
+# define LZO_SIZEOF_LZO_INTPTR_T LZO_SIZEOF_INT
+#elif (LZO_SIZEOF_LONG >= LZO_SIZEOF_VOID_P)
+# define lzo_intptr_t long
+# define lzo_uintptr_t unsigned long
+# define LZO_SIZEOF_LZO_INTPTR_T LZO_SIZEOF_LONG
+#elif (LZO_SIZEOF_LZO_INT64L_T >= LZO_SIZEOF_VOID_P)
+# define lzo_intptr_t lzo_int64l_t
+# define lzo_uintptr_t lzo_uint64l_t
+# define LZO_SIZEOF_LZO_INTPTR_T LZO_SIZEOF_LZO_INT64L_T
+#else
+# error "lzo_intptr_t"
+#endif
+#endif
+#if 1
+ LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_intptr_t) >= sizeof(void *))
+ LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_intptr_t) == sizeof(lzo_uintptr_t))
+#endif
+#if !defined(lzo_word_t)
+#if defined(LZO_WORDSIZE) && (LZO_WORDSIZE+0 > 0)
+#if (LZO_WORDSIZE == LZO_SIZEOF_LZO_INTPTR_T) && !(__LZO_INTPTR_T_IS_POINTER)
+# define lzo_word_t lzo_uintptr_t
+# define lzo_sword_t lzo_intptr_t
+# define LZO_SIZEOF_LZO_WORD_T LZO_SIZEOF_LZO_INTPTR_T
+#elif (LZO_WORDSIZE == LZO_SIZEOF_LONG)
+# define lzo_word_t unsigned long
+# define lzo_sword_t long
+# define LZO_SIZEOF_LZO_WORD_T LZO_SIZEOF_LONG
+#elif (LZO_WORDSIZE == LZO_SIZEOF_INT)
+# define lzo_word_t unsigned int
+# define lzo_sword_t int
+# define LZO_SIZEOF_LZO_WORD_T LZO_SIZEOF_INT
+#elif (LZO_WORDSIZE == LZO_SIZEOF_SHORT)
+# define lzo_word_t unsigned short
+# define lzo_sword_t short
+# define LZO_SIZEOF_LZO_WORD_T LZO_SIZEOF_SHORT
+#elif (LZO_WORDSIZE == 1)
+# define lzo_word_t unsigned char
+# define lzo_sword_t signed char
+# define LZO_SIZEOF_LZO_WORD_T 1
+#elif (LZO_WORDSIZE == LZO_SIZEOF_LZO_INT64L_T)
+# define lzo_word_t lzo_uint64l_t
+# define lzo_sword_t lzo_int64l_t
+# define LZO_SIZEOF_LZO_WORD_T LZO_SIZEOF_LZO_INT64L_T
+#elif (LZO_ARCH_SPU) && (LZO_CC_GNUC)
+#if 0
+ typedef unsigned lzo_word_t __attribute__((__mode__(__V16QI__)));
+ typedef int lzo_sword_t __attribute__((__mode__(__V16QI__)));
+# define lzo_word_t lzo_word_t
+# define lzo_sword_t lzo_sword_t
+# define LZO_SIZEOF_LZO_WORD_T 16
+#endif
+#else
+# error "lzo_word_t"
+#endif
+#endif
+#endif
+#if 1 && defined(lzo_word_t)
+ LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_word_t) == LZO_WORDSIZE)
+ LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_sword_t) == LZO_WORDSIZE)
+#endif
+#if 1
+#define lzo_int8_t signed char
+#define lzo_uint8_t unsigned char
+#define LZO_SIZEOF_LZO_INT8_T 1
+LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int8_t) == 1)
+LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int8_t) == sizeof(lzo_uint8_t))
+#endif
+#if defined(lzo_int16e_t)
+#define lzo_int16_t lzo_int16e_t
+#define lzo_uint16_t lzo_uint16e_t
+#define LZO_SIZEOF_LZO_INT16_T LZO_SIZEOF_LZO_INT16E_T
+LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int16_t) == 2)
+LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int16_t) == sizeof(lzo_uint16_t))
+#endif
+#if defined(lzo_int32e_t)
+#define lzo_int32_t lzo_int32e_t
+#define lzo_uint32_t lzo_uint32e_t
+#define LZO_SIZEOF_LZO_INT32_T LZO_SIZEOF_LZO_INT32E_T
+LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int32_t) == 4)
+LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int32_t) == sizeof(lzo_uint32_t))
+#endif
+#if defined(lzo_int64e_t)
+#define lzo_int64_t lzo_int64e_t
+#define lzo_uint64_t lzo_uint64e_t
+#define LZO_SIZEOF_LZO_INT64_T LZO_SIZEOF_LZO_INT64E_T
+LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int64_t) == 8)
+LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int64_t) == sizeof(lzo_uint64_t))
+#endif
+#if 1
+#define lzo_int_least32_t lzo_int32l_t
+#define lzo_uint_least32_t lzo_uint32l_t
+#define LZO_SIZEOF_LZO_INT_LEAST32_T LZO_SIZEOF_LZO_INT32L_T
+LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int_least32_t) >= 4)
+LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int_least32_t) == sizeof(lzo_uint_least32_t))
+#endif
+#if defined(lzo_int64l_t)
+#define lzo_int_least64_t lzo_int64l_t
+#define lzo_uint_least64_t lzo_uint64l_t
+#define LZO_SIZEOF_LZO_INT_LEAST64_T LZO_SIZEOF_LZO_INT64L_T
+LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int_least64_t) >= 8)
+LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int_least64_t) == sizeof(lzo_uint_least64_t))
+#endif
+#if 1
+#define lzo_int_fast32_t lzo_int32f_t
+#define lzo_uint_fast32_t lzo_uint32f_t
+#define LZO_SIZEOF_LZO_INT_FAST32_T LZO_SIZEOF_LZO_INT32F_T
+LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int_fast32_t) >= 4)
+LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int_fast32_t) == sizeof(lzo_uint_fast32_t))
+#endif
+#if defined(lzo_int64f_t)
+#define lzo_int_fast64_t lzo_int64f_t
+#define lzo_uint_fast64_t lzo_uint64f_t
+#define LZO_SIZEOF_LZO_INT_FAST64_T LZO_SIZEOF_LZO_INT64F_T
+LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int_fast64_t) >= 8)
+LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int_fast64_t) == sizeof(lzo_uint_fast64_t))
+#endif
+#if !defined(LZO_INT16_C)
+# if (LZO_BROKEN_INTEGRAL_CONSTANTS) && (LZO_SIZEOF_INT >= 2)
+# define LZO_INT16_C(c) ((c) + 0)
+# define LZO_UINT16_C(c) ((c) + 0U)
+# elif (LZO_BROKEN_INTEGRAL_CONSTANTS) && (LZO_SIZEOF_LONG >= 2)
+# define LZO_INT16_C(c) ((c) + 0L)
+# define LZO_UINT16_C(c) ((c) + 0UL)
+# elif (LZO_SIZEOF_INT >= 2)
+# define LZO_INT16_C(c) (c)
+# define LZO_UINT16_C(c) (c##U)
+# elif (LZO_SIZEOF_LONG >= 2)
+# define LZO_INT16_C(c) (c##L)
+# define LZO_UINT16_C(c) (c##UL)
+# else
+# error "LZO_INT16_C"
+# endif
+#endif
+#if !defined(LZO_INT32_C)
+# if (LZO_BROKEN_INTEGRAL_CONSTANTS) && (LZO_SIZEOF_INT >= 4)
+# define LZO_INT32_C(c) ((c) + 0)
+# define LZO_UINT32_C(c) ((c) + 0U)
+# elif (LZO_BROKEN_INTEGRAL_CONSTANTS) && (LZO_SIZEOF_LONG >= 4)
+# define LZO_INT32_C(c) ((c) + 0L)
+# define LZO_UINT32_C(c) ((c) + 0UL)
+# elif (LZO_SIZEOF_INT >= 4)
+# define LZO_INT32_C(c) (c)
+# define LZO_UINT32_C(c) (c##U)
+# elif (LZO_SIZEOF_LONG >= 4)
+# define LZO_INT32_C(c) (c##L)
+# define LZO_UINT32_C(c) (c##UL)
+# elif (LZO_SIZEOF_LONG_LONG >= 4)
+# define LZO_INT32_C(c) (c##LL)
+# define LZO_UINT32_C(c) (c##ULL)
+# else
+# error "LZO_INT32_C"
+# endif
+#endif
+#if !defined(LZO_INT64_C) && defined(lzo_int64l_t)
+# if (LZO_BROKEN_INTEGRAL_CONSTANTS) && (LZO_SIZEOF_INT >= 8)
+# define LZO_INT64_C(c) ((c) + 0)
+# define LZO_UINT64_C(c) ((c) + 0U)
+# elif (LZO_BROKEN_INTEGRAL_CONSTANTS) && (LZO_SIZEOF_LONG >= 8)
+# define LZO_INT64_C(c) ((c) + 0L)
+# define LZO_UINT64_C(c) ((c) + 0UL)
+# elif (LZO_SIZEOF_INT >= 8)
+# define LZO_INT64_C(c) (c)
+# define LZO_UINT64_C(c) (c##U)
+# elif (LZO_SIZEOF_LONG >= 8)
+# define LZO_INT64_C(c) (c##L)
+# define LZO_UINT64_C(c) (c##UL)
+# else
+# error "LZO_INT64_C"
+# endif
+#endif
+#endif
#endif /* already included */
-/* vim:set ts=4 et: */
+/* vim:set ts=4 sw=4 et: */
diff --git a/extern/lzo/minilzo/minilzo.c b/extern/lzo/minilzo/minilzo.c
index 34ce0f090bd..ab2be5f4fd0 100644
--- a/extern/lzo/minilzo/minilzo.c
+++ b/extern/lzo/minilzo/minilzo.c
@@ -2,22 +2,7 @@
This file is part of the LZO real-time data compression library.
- Copyright (C) 2011 Markus Franz Xaver Johannes Oberhumer
- Copyright (C) 2010 Markus Franz Xaver Johannes Oberhumer
- Copyright (C) 2009 Markus Franz Xaver Johannes Oberhumer
- Copyright (C) 2008 Markus Franz Xaver Johannes Oberhumer
- Copyright (C) 2007 Markus Franz Xaver Johannes Oberhumer
- Copyright (C) 2006 Markus Franz Xaver Johannes Oberhumer
- Copyright (C) 2005 Markus Franz Xaver Johannes Oberhumer
- Copyright (C) 2004 Markus Franz Xaver Johannes Oberhumer
- Copyright (C) 2003 Markus Franz Xaver Johannes Oberhumer
- Copyright (C) 2002 Markus Franz Xaver Johannes Oberhumer
- Copyright (C) 2001 Markus Franz Xaver Johannes Oberhumer
- Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer
- Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer
- Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer
- Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer
- Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1996-2014 Markus Franz Xaver Johannes Oberhumer
All Rights Reserved.
The LZO library is free software; you can redistribute it and/or
@@ -67,12 +52,6 @@
#if defined(__CYGWIN32__) && !defined(__CYGWIN__)
# define __CYGWIN__ __CYGWIN32__
#endif
-#if defined(__IBMCPP__) && !defined(__IBMC__)
-# define __IBMC__ __IBMCPP__
-#endif
-#if defined(__ICL) && defined(_WIN32) && !defined(__INTEL_COMPILER)
-# define __INTEL_COMPILER __ICL
-#endif
#if 1 && defined(__INTERIX) && defined(__GNUC__) && !defined(_ALL_SOURCE)
# define _ALL_SOURCE 1
#endif
@@ -81,19 +60,30 @@
# define __LONG_MAX__ 9223372036854775807L
# endif
#endif
-#if defined(__INTEL_COMPILER) && defined(__linux__)
+#if !defined(LZO_CFG_NO_DISABLE_WUNDEF)
+#if defined(__ARMCC_VERSION)
+# pragma diag_suppress 193
+#elif defined(__clang__) && defined(__clang_minor__)
+# pragma clang diagnostic ignored "-Wundef"
+#elif defined(__INTEL_COMPILER)
# pragma warning(disable: 193)
-#endif
-#if defined(__KEIL__) && defined(__C166__)
-# pragma warning disable = 322
-#elif 0 && defined(__C251__)
+#elif defined(__KEIL__) && defined(__C166__)
# pragma warning disable = 322
-#endif
-#if defined(_MSC_VER) && !defined(__INTEL_COMPILER) && !defined(__MWERKS__)
-# if (_MSC_VER >= 1300)
+#elif defined(__GNUC__) && defined(__GNUC_MINOR__) && !defined(__PATHSCALE__)
+# if ((__GNUC__-0) >= 5 || ((__GNUC__-0) == 4 && (__GNUC_MINOR__-0) >= 2))
+# pragma GCC diagnostic ignored "-Wundef"
+# endif
+#elif defined(_MSC_VER) && !defined(__clang__) && !defined(__INTEL_COMPILER) && !defined(__MWERKS__)
+# if ((_MSC_VER-0) >= 1300)
# pragma warning(disable: 4668)
# endif
#endif
+#endif
+#if 0 && defined(__POCC__) && defined(_WIN32)
+# if (__POCC__ >= 400)
+# pragma warn(disable: 2216)
+# endif
+#endif
#if 0 && defined(__WATCOMC__)
# if (__WATCOMC__ >= 1050) && (__WATCOMC__ < 1060)
# pragma warning 203 9
@@ -102,13 +92,29 @@
#if defined(__BORLANDC__) && defined(__MSDOS__) && !defined(__FLAT__)
# pragma option -h
#endif
+#if !(LZO_CFG_NO_DISABLE_WCRTNONSTDC)
+#ifndef _CRT_NONSTDC_NO_DEPRECATE
+#define _CRT_NONSTDC_NO_DEPRECATE 1
+#endif
+#ifndef _CRT_NONSTDC_NO_WARNINGS
+#define _CRT_NONSTDC_NO_WARNINGS 1
+#endif
+#ifndef _CRT_SECURE_NO_DEPRECATE
+#define _CRT_SECURE_NO_DEPRECATE 1
+#endif
+#ifndef _CRT_SECURE_NO_WARNINGS
+#define _CRT_SECURE_NO_WARNINGS 1
+#endif
+#endif
#if 0
-#define LZO_0xffffL 0xfffful
-#define LZO_0xffffffffL 0xfffffffful
+#define LZO_0xffffUL 0xfffful
+#define LZO_0xffffffffUL 0xfffffffful
#else
-#define LZO_0xffffL 65535ul
-#define LZO_0xffffffffL 4294967295ul
+#define LZO_0xffffUL 65535ul
+#define LZO_0xffffffffUL 4294967295ul
#endif
+#define LZO_0xffffL LZO_0xffffUL
+#define LZO_0xffffffffL LZO_0xffffffffUL
#if (LZO_0xffffL == LZO_0xffffffffL)
# error "your preprocessor is broken 1"
#endif
@@ -123,6 +129,13 @@
# error "your preprocessor is broken 4"
#endif
#endif
+#if defined(__COUNTER__)
+# ifndef LZO_CFG_USE_COUNTER
+# define LZO_CFG_USE_COUNTER 1
+# endif
+#else
+# undef LZO_CFG_USE_COUNTER
+#endif
#if (UINT_MAX == LZO_0xffffL)
#if defined(__ZTC__) && defined(__I86__) && !defined(__OS2__)
# if !defined(MSDOS)
@@ -253,14 +266,31 @@
#endif
#define LZO_PP_STRINGIZE(x) #x
#define LZO_PP_MACRO_EXPAND(x) LZO_PP_STRINGIZE(x)
+#define LZO_PP_CONCAT0() /*empty*/
+#define LZO_PP_CONCAT1(a) a
#define LZO_PP_CONCAT2(a,b) a ## b
#define LZO_PP_CONCAT3(a,b,c) a ## b ## c
#define LZO_PP_CONCAT4(a,b,c,d) a ## b ## c ## d
#define LZO_PP_CONCAT5(a,b,c,d,e) a ## b ## c ## d ## e
+#define LZO_PP_CONCAT6(a,b,c,d,e,f) a ## b ## c ## d ## e ## f
+#define LZO_PP_CONCAT7(a,b,c,d,e,f,g) a ## b ## c ## d ## e ## f ## g
+#define LZO_PP_ECONCAT0() LZO_PP_CONCAT0()
+#define LZO_PP_ECONCAT1(a) LZO_PP_CONCAT1(a)
#define LZO_PP_ECONCAT2(a,b) LZO_PP_CONCAT2(a,b)
#define LZO_PP_ECONCAT3(a,b,c) LZO_PP_CONCAT3(a,b,c)
#define LZO_PP_ECONCAT4(a,b,c,d) LZO_PP_CONCAT4(a,b,c,d)
#define LZO_PP_ECONCAT5(a,b,c,d,e) LZO_PP_CONCAT5(a,b,c,d,e)
+#define LZO_PP_ECONCAT6(a,b,c,d,e,f) LZO_PP_CONCAT6(a,b,c,d,e,f)
+#define LZO_PP_ECONCAT7(a,b,c,d,e,f,g) LZO_PP_CONCAT7(a,b,c,d,e,f,g)
+#define LZO_PP_EMPTY /*empty*/
+#define LZO_PP_EMPTY0() /*empty*/
+#define LZO_PP_EMPTY1(a) /*empty*/
+#define LZO_PP_EMPTY2(a,b) /*empty*/
+#define LZO_PP_EMPTY3(a,b,c) /*empty*/
+#define LZO_PP_EMPTY4(a,b,c,d) /*empty*/
+#define LZO_PP_EMPTY5(a,b,c,d,e) /*empty*/
+#define LZO_PP_EMPTY6(a,b,c,d,e,f) /*empty*/
+#define LZO_PP_EMPTY7(a,b,c,d,e,f,g) /*empty*/
#if 1
#define LZO_CPP_STRINGIZE(x) #x
#define LZO_CPP_MACRO_EXPAND(x) LZO_CPP_STRINGIZE(x)
@@ -268,12 +298,16 @@
#define LZO_CPP_CONCAT3(a,b,c) a ## b ## c
#define LZO_CPP_CONCAT4(a,b,c,d) a ## b ## c ## d
#define LZO_CPP_CONCAT5(a,b,c,d,e) a ## b ## c ## d ## e
+#define LZO_CPP_CONCAT6(a,b,c,d,e,f) a ## b ## c ## d ## e ## f
+#define LZO_CPP_CONCAT7(a,b,c,d,e,f,g) a ## b ## c ## d ## e ## f ## g
#define LZO_CPP_ECONCAT2(a,b) LZO_CPP_CONCAT2(a,b)
#define LZO_CPP_ECONCAT3(a,b,c) LZO_CPP_CONCAT3(a,b,c)
#define LZO_CPP_ECONCAT4(a,b,c,d) LZO_CPP_CONCAT4(a,b,c,d)
#define LZO_CPP_ECONCAT5(a,b,c,d,e) LZO_CPP_CONCAT5(a,b,c,d,e)
+#define LZO_CPP_ECONCAT6(a,b,c,d,e,f) LZO_CPP_CONCAT6(a,b,c,d,e,f)
+#define LZO_CPP_ECONCAT7(a,b,c,d,e,f,g) LZO_CPP_CONCAT7(a,b,c,d,e,f,g)
#endif
-#define __LZO_MASK_GEN(o,b) (((((o) << ((b)-1)) - (o)) << 1) + (o))
+#define __LZO_MASK_GEN(o,b) (((((o) << ((b)-!!(b))) - (o)) << 1) + (o)*!!(b))
#if 1 && defined(__cplusplus)
# if !defined(__STDC_CONSTANT_MACROS)
# define __STDC_CONSTANT_MACROS 1
@@ -283,9 +317,13 @@
# endif
#endif
#if defined(__cplusplus)
-# define LZO_EXTERN_C extern "C"
+# define LZO_EXTERN_C extern "C"
+# define LZO_EXTERN_C_BEGIN extern "C" {
+# define LZO_EXTERN_C_END }
#else
-# define LZO_EXTERN_C extern
+# define LZO_EXTERN_C extern
+# define LZO_EXTERN_C_BEGIN /*empty*/
+# define LZO_EXTERN_C_END /*empty*/
#endif
#if !defined(__LZO_OS_OVERRIDE)
#if (LZO_OS_FREESTANDING)
@@ -386,12 +424,12 @@
#elif defined(__VMS)
# define LZO_OS_VMS 1
# define LZO_INFO_OS "vms"
-#elif ((defined(__mips__) && defined(__R5900__)) || defined(__MIPS_PSX2__))
+#elif (defined(__mips__) && defined(__R5900__)) || defined(__MIPS_PSX2__)
# define LZO_OS_CONSOLE 1
# define LZO_OS_CONSOLE_PS2 1
# define LZO_INFO_OS "console"
# define LZO_INFO_OS_CONSOLE "ps2"
-#elif (defined(__mips__) && defined(__psp__))
+#elif defined(__mips__) && defined(__psp__)
# define LZO_OS_CONSOLE 1
# define LZO_OS_CONSOLE_PSP 1
# define LZO_INFO_OS "console"
@@ -419,9 +457,18 @@
# elif defined(__linux__) || defined(__linux) || defined(__LINUX__)
# define LZO_OS_POSIX_LINUX 1
# define LZO_INFO_OS_POSIX "linux"
-# elif defined(__APPLE__) || defined(__MACOS__)
-# define LZO_OS_POSIX_MACOSX 1
-# define LZO_INFO_OS_POSIX "macosx"
+# elif defined(__APPLE__) && defined(__MACH__)
+# if ((__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__-0) >= 20000)
+# define LZO_OS_POSIX_DARWIN 1040
+# define LZO_INFO_OS_POSIX "darwin_iphone"
+# elif ((__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__-0) >= 1040)
+# define LZO_OS_POSIX_DARWIN __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__
+# define LZO_INFO_OS_POSIX "darwin"
+# else
+# define LZO_OS_POSIX_DARWIN 1
+# define LZO_INFO_OS_POSIX "darwin"
+# endif
+# define LZO_OS_POSIX_MACOSX LZO_OS_POSIX_DARWIN
# elif defined(__minix__) || defined(__minix)
# define LZO_OS_POSIX_MINIX 1
# define LZO_INFO_OS_POSIX "minix"
@@ -456,18 +503,18 @@
#endif
#if (LZO_OS_DOS16 || LZO_OS_OS216 || LZO_OS_WIN16)
# if (UINT_MAX != LZO_0xffffL)
-# error "this should not happen"
+# error "unexpected configuration - check your compiler defines"
# endif
# if (ULONG_MAX != LZO_0xffffffffL)
-# error "this should not happen"
+# error "unexpected configuration - check your compiler defines"
# endif
#endif
#if (LZO_OS_DOS32 || LZO_OS_OS2 || LZO_OS_WIN32 || LZO_OS_WIN64)
# if (UINT_MAX != LZO_0xffffffffL)
-# error "this should not happen"
+# error "unexpected configuration - check your compiler defines"
# endif
# if (ULONG_MAX != LZO_0xffffffffL)
-# error "this should not happen"
+# error "unexpected configuration - check your compiler defines"
# endif
#endif
#if defined(CIL) && defined(_GNUCC) && defined(__GNUC__)
@@ -483,59 +530,65 @@
# define LZO_INFO_CC "sdcc"
# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(SDCC)
#elif defined(__PATHSCALE__) && defined(__PATHCC_PATCHLEVEL__)
-# define LZO_CC_PATHSCALE (__PATHCC__ * 0x10000L + __PATHCC_MINOR__ * 0x100 + __PATHCC_PATCHLEVEL__)
+# define LZO_CC_PATHSCALE (__PATHCC__ * 0x10000L + (__PATHCC_MINOR__-0) * 0x100 + (__PATHCC_PATCHLEVEL__-0))
# define LZO_INFO_CC "Pathscale C"
# define LZO_INFO_CCVER __PATHSCALE__
-#elif defined(__INTEL_COMPILER)
-# define LZO_CC_INTELC 1
+# if defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__VERSION__)
+# define LZO_CC_PATHSCALE_GNUC (__GNUC__ * 0x10000L + (__GNUC_MINOR__-0) * 0x100 + (__GNUC_PATCHLEVEL__-0))
+# endif
+#elif defined(__INTEL_COMPILER) && ((__INTEL_COMPILER-0) > 0)
+# define LZO_CC_INTELC __INTEL_COMPILER
# define LZO_INFO_CC "Intel C"
# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__INTEL_COMPILER)
-# if defined(_WIN32) || defined(_WIN64)
-# define LZO_CC_SYNTAX_MSC 1
-# else
-# define LZO_CC_SYNTAX_GNUC 1
+# if defined(_MSC_VER) && ((_MSC_VER-0) > 0)
+# define LZO_CC_INTELC_MSC _MSC_VER
+# elif defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__VERSION__)
+# define LZO_CC_INTELC_GNUC (__GNUC__ * 0x10000L + (__GNUC_MINOR__-0) * 0x100 + (__GNUC_PATCHLEVEL__-0))
# endif
#elif defined(__POCC__) && defined(_WIN32)
# define LZO_CC_PELLESC 1
# define LZO_INFO_CC "Pelles C"
# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__POCC__)
-#elif defined(__clang__) && defined(__llvm__) && defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__VERSION__)
+#elif defined(__ARMCC_VERSION) && defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__VERSION__)
# if defined(__GNUC_PATCHLEVEL__)
-# define LZO_CC_CLANG_GNUC (__GNUC__ * 0x10000L + __GNUC_MINOR__ * 0x100 + __GNUC_PATCHLEVEL__)
+# define LZO_CC_ARMCC_GNUC (__GNUC__ * 0x10000L + (__GNUC_MINOR__-0) * 0x100 + (__GNUC_PATCHLEVEL__-0))
# else
-# define LZO_CC_CLANG_GNUC (__GNUC__ * 0x10000L + __GNUC_MINOR__ * 0x100)
+# define LZO_CC_ARMCC_GNUC (__GNUC__ * 0x10000L + (__GNUC_MINOR__-0) * 0x100)
# endif
+# define LZO_CC_ARMCC __ARMCC_VERSION
+# define LZO_INFO_CC "ARM C Compiler"
+# define LZO_INFO_CCVER __VERSION__
+#elif defined(__clang__) && defined(__llvm__) && defined(__VERSION__)
# if defined(__clang_major__) && defined(__clang_minor__) && defined(__clang_patchlevel__)
-# define LZO_CC_CLANG_CLANG (__clang_major__ * 0x10000L + __clang_minor__ * 0x100 + __clang_patchlevel__)
+# define LZO_CC_CLANG (__clang_major__ * 0x10000L + (__clang_minor__-0) * 0x100 + (__clang_patchlevel__-0))
# else
-# define LZO_CC_CLANG_CLANG 0x010000L
+# define LZO_CC_CLANG 0x010000L
+# endif
+# if defined(_MSC_VER) && ((_MSC_VER-0) > 0)
+# define LZO_CC_CLANG_MSC _MSC_VER
+# elif defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__VERSION__)
+# define LZO_CC_CLANG_GNUC (__GNUC__ * 0x10000L + (__GNUC_MINOR__-0) * 0x100 + (__GNUC_PATCHLEVEL__-0))
# endif
-# define LZO_CC_CLANG LZO_CC_CLANG_GNUC
# define LZO_INFO_CC "clang"
# define LZO_INFO_CCVER __VERSION__
#elif defined(__llvm__) && defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__VERSION__)
# if defined(__GNUC_PATCHLEVEL__)
-# define LZO_CC_LLVM_GNUC (__GNUC__ * 0x10000L + __GNUC_MINOR__ * 0x100 + __GNUC_PATCHLEVEL__)
+# define LZO_CC_LLVM_GNUC (__GNUC__ * 0x10000L + (__GNUC_MINOR__-0) * 0x100 + (__GNUC_PATCHLEVEL__-0))
# else
-# define LZO_CC_LLVM_GNUC (__GNUC__ * 0x10000L + __GNUC_MINOR__ * 0x100)
+# define LZO_CC_LLVM_GNUC (__GNUC__ * 0x10000L + (__GNUC_MINOR__-0) * 0x100)
# endif
# define LZO_CC_LLVM LZO_CC_LLVM_GNUC
# define LZO_INFO_CC "llvm-gcc"
# define LZO_INFO_CCVER __VERSION__
-#elif defined(__GNUC__) && defined(__VERSION__)
-# if defined(__GNUC_MINOR__) && defined(__GNUC_PATCHLEVEL__)
-# define LZO_CC_GNUC (__GNUC__ * 0x10000L + __GNUC_MINOR__ * 0x100 + __GNUC_PATCHLEVEL__)
-# elif defined(__GNUC_MINOR__)
-# define LZO_CC_GNUC (__GNUC__ * 0x10000L + __GNUC_MINOR__ * 0x100)
-# else
-# define LZO_CC_GNUC (__GNUC__ * 0x10000L)
-# endif
-# define LZO_INFO_CC "gcc"
-# define LZO_INFO_CCVER __VERSION__
#elif defined(__ACK__) && defined(_ACK)
# define LZO_CC_ACK 1
# define LZO_INFO_CC "Amsterdam Compiler Kit C"
# define LZO_INFO_CCVER "unknown"
+#elif defined(__ARMCC_VERSION) && !defined(__GNUC__)
+# define LZO_CC_ARMCC __ARMCC_VERSION
+# define LZO_CC_ARMCC_ARMCC __ARMCC_VERSION
+# define LZO_INFO_CC "ARM C Compiler"
+# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__ARMCC_VERSION)
#elif defined(__AZTEC_C__)
# define LZO_CC_AZTECC 1
# define LZO_INFO_CC "Aztec C"
@@ -560,10 +613,23 @@
# define LZO_CC_DECC 1
# define LZO_INFO_CC "DEC C"
# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__DECC)
+#elif (defined(__ghs) || defined(__ghs__)) && defined(__GHS_VERSION_NUMBER) && ((__GHS_VERSION_NUMBER-0) > 0)
+# define LZO_CC_GHS 1
+# define LZO_INFO_CC "Green Hills C"
+# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__GHS_VERSION_NUMBER)
+# if defined(_MSC_VER) && ((_MSC_VER-0) > 0)
+# define LZO_CC_GHS_MSC _MSC_VER
+# elif defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__VERSION__)
+# define LZO_CC_GHS_GNUC (__GNUC__ * 0x10000L + (__GNUC_MINOR__-0) * 0x100 + (__GNUC_PATCHLEVEL__-0))
+# endif
#elif defined(__HIGHC__)
# define LZO_CC_HIGHC 1
# define LZO_INFO_CC "MetaWare High C"
# define LZO_INFO_CCVER "unknown"
+#elif defined(__HP_aCC) && ((__HP_aCC-0) > 0)
+# define LZO_CC_HPACC __HP_aCC
+# define LZO_INFO_CC "HP aCC"
+# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__HP_aCC)
#elif defined(__IAR_SYSTEMS_ICC__)
# define LZO_CC_IARC 1
# define LZO_INFO_CC "IAR C"
@@ -572,10 +638,14 @@
# else
# define LZO_INFO_CCVER "unknown"
# endif
-#elif defined(__IBMC__)
-# define LZO_CC_IBMC 1
+#elif defined(__IBMC__) && ((__IBMC__-0) > 0)
+# define LZO_CC_IBMC __IBMC__
# define LZO_INFO_CC "IBM C"
# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__IBMC__)
+#elif defined(__IBMCPP__) && ((__IBMCPP__-0) > 0)
+# define LZO_CC_IBMC __IBMCPP__
+# define LZO_INFO_CC "IBM C"
+# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__IBMCPP__)
#elif defined(__KEIL__) && defined(__C166__)
# define LZO_CC_KEILC 1
# define LZO_INFO_CC "Keil C"
@@ -592,16 +662,8 @@
# else
# define LZO_INFO_CCVER "unknown"
# endif
-#elif defined(_MSC_VER)
-# define LZO_CC_MSC 1
-# define LZO_INFO_CC "Microsoft C"
-# if defined(_MSC_FULL_VER)
-# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(_MSC_VER) "." LZO_PP_MACRO_EXPAND(_MSC_FULL_VER)
-# else
-# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(_MSC_VER)
-# endif
-#elif defined(__MWERKS__)
-# define LZO_CC_MWERKS 1
+#elif defined(__MWERKS__) && ((__MWERKS__-0) > 0)
+# define LZO_CC_MWERKS __MWERKS__
# define LZO_INFO_CC "Metrowerks C"
# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__MWERKS__)
#elif (defined(__NDPC__) || defined(__NDPX__)) && defined(__i386)
@@ -612,6 +674,15 @@
# define LZO_CC_PACIFICC 1
# define LZO_INFO_CC "Pacific C"
# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__PACIFIC__)
+#elif defined(__PGI) && defined(__PGIC__) && defined(__PGIC_MINOR__)
+# if defined(__PGIC_PATCHLEVEL__)
+# define LZO_CC_PGI (__PGIC__ * 0x10000L + (__PGIC_MINOR__-0) * 0x100 + (__PGIC_PATCHLEVEL__-0))
+# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__PGIC__) "." LZO_PP_MACRO_EXPAND(__PGIC_MINOR__) "." LZO_PP_MACRO_EXPAND(__PGIC_PATCHLEVEL__)
+# else
+# define LZO_CC_PGI (__PGIC__ * 0x10000L + (__PGIC_MINOR__-0) * 0x100)
+# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__PGIC__) "." LZO_PP_MACRO_EXPAND(__PGIC_MINOR__) ".0"
+# endif
+# define LZO_INFO_CC "Portland Group PGI C"
#elif defined(__PGI) && (defined(__linux__) || defined(__WIN32__))
# define LZO_CC_PGI 1
# define LZO_INFO_CC "Portland Group PGI C"
@@ -626,7 +697,7 @@
# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__SC__)
#elif defined(__SUNPRO_C)
# define LZO_INFO_CC "SunPro C"
-# if ((__SUNPRO_C)+0 > 0)
+# if ((__SUNPRO_C-0) > 0)
# define LZO_CC_SUNPROC __SUNPRO_C
# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__SUNPRO_C)
# else
@@ -635,7 +706,7 @@
# endif
#elif defined(__SUNPRO_CC)
# define LZO_INFO_CC "SunPro C"
-# if ((__SUNPRO_CC)+0 > 0)
+# if ((__SUNPRO_CC-0) > 0)
# define LZO_CC_SUNPROC __SUNPRO_CC
# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__SUNPRO_CC)
# else
@@ -661,16 +732,46 @@
#elif defined(__ZTC__)
# define LZO_CC_ZORTECHC 1
# define LZO_INFO_CC "Zortech C"
-# if (__ZTC__ == 0x310)
+# if ((__ZTC__-0) == 0x310)
# define LZO_INFO_CCVER "0x310"
# else
# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__ZTC__)
# endif
+#elif defined(__GNUC__) && defined(__VERSION__)
+# if defined(__GNUC_MINOR__) && defined(__GNUC_PATCHLEVEL__)
+# define LZO_CC_GNUC (__GNUC__ * 0x10000L + (__GNUC_MINOR__-0) * 0x100 + (__GNUC_PATCHLEVEL__-0))
+# elif defined(__GNUC_MINOR__)
+# define LZO_CC_GNUC (__GNUC__ * 0x10000L + (__GNUC_MINOR__-0) * 0x100)
+# else
+# define LZO_CC_GNUC (__GNUC__ * 0x10000L)
+# endif
+# define LZO_INFO_CC "gcc"
+# define LZO_INFO_CCVER __VERSION__
+#elif defined(_MSC_VER) && ((_MSC_VER-0) > 0)
+# define LZO_CC_MSC _MSC_VER
+# define LZO_INFO_CC "Microsoft C"
+# if defined(_MSC_FULL_VER)
+# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(_MSC_VER) "." LZO_PP_MACRO_EXPAND(_MSC_FULL_VER)
+# else
+# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(_MSC_VER)
+# endif
#else
# define LZO_CC_UNKNOWN 1
# define LZO_INFO_CC "unknown"
# define LZO_INFO_CCVER "unknown"
#endif
+#if (LZO_CC_GNUC) && defined(__OPEN64__)
+# if defined(__OPENCC__) && defined(__OPENCC_MINOR__) && defined(__OPENCC_PATCHLEVEL__)
+# define LZO_CC_OPEN64 (__OPENCC__ * 0x10000L + (__OPENCC_MINOR__-0) * 0x100 + (__OPENCC_PATCHLEVEL__-0))
+# define LZO_CC_OPEN64_GNUC LZO_CC_GNUC
+# endif
+#endif
+#if (LZO_CC_GNUC) && defined(__PCC__)
+# if defined(__PCC__) && defined(__PCC_MINOR__) && defined(__PCC_MINORMINOR__)
+# define LZO_CC_PCC (__PCC__ * 0x10000L + (__PCC_MINOR__-0) * 0x100 + (__PCC_MINORMINOR__-0))
+# define LZO_CC_PCC_GNUC LZO_CC_GNUC
+# endif
+#endif
#if 0 && (LZO_CC_MSC && (_MSC_VER >= 1200)) && !defined(_MSC_FULL_VER)
# error "LZO_CC_MSC: _MSC_FULL_VER is not defined"
#endif
@@ -688,8 +789,10 @@
# define LZO_INFO_ARCH "generic"
#elif (LZO_OS_DOS16 || LZO_OS_OS216 || LZO_OS_WIN16)
# define LZO_ARCH_I086 1
-# define LZO_ARCH_IA16 1
# define LZO_INFO_ARCH "i086"
+#elif defined(__aarch64__)
+# define LZO_ARCH_ARM64 1
+# define LZO_INFO_ARCH "arm64"
#elif defined(__alpha__) || defined(__alpha) || defined(_M_ALPHA)
# define LZO_ARCH_ALPHA 1
# define LZO_INFO_ARCH "alpha"
@@ -705,10 +808,10 @@
# define LZO_INFO_ARCH "arm_thumb"
#elif defined(__IAR_SYSTEMS_ICC__) && defined(__ICCARM__)
# define LZO_ARCH_ARM 1
-# if defined(__CPU_MODE__) && ((__CPU_MODE__)+0 == 1)
+# if defined(__CPU_MODE__) && ((__CPU_MODE__-0) == 1)
# define LZO_ARCH_ARM_THUMB 1
# define LZO_INFO_ARCH "arm_thumb"
-# elif defined(__CPU_MODE__) && ((__CPU_MODE__)+0 == 2)
+# elif defined(__CPU_MODE__) && ((__CPU_MODE__-0) == 2)
# define LZO_INFO_ARCH "arm"
# else
# define LZO_INFO_ARCH "arm"
@@ -826,53 +929,147 @@
# error "FIXME - missing define for CPU architecture"
#endif
#if 1 && (LZO_ARCH_UNKNOWN) && (LZO_OS_WIN32)
-# error "FIXME - missing WIN32 define for CPU architecture"
+# error "FIXME - missing LZO_OS_WIN32 define for CPU architecture"
#endif
#if 1 && (LZO_ARCH_UNKNOWN) && (LZO_OS_WIN64)
-# error "FIXME - missing WIN64 define for CPU architecture"
+# error "FIXME - missing LZO_OS_WIN64 define for CPU architecture"
#endif
#if (LZO_OS_OS216 || LZO_OS_WIN16)
# define LZO_ARCH_I086PM 1
-# define LZO_ARCH_IA16PM 1
#elif 1 && (LZO_OS_DOS16 && defined(BLX286))
# define LZO_ARCH_I086PM 1
-# define LZO_ARCH_IA16PM 1
#elif 1 && (LZO_OS_DOS16 && defined(DOSX286))
# define LZO_ARCH_I086PM 1
-# define LZO_ARCH_IA16PM 1
#elif 1 && (LZO_OS_DOS16 && LZO_CC_BORLANDC && defined(__DPMI16__))
# define LZO_ARCH_I086PM 1
-# define LZO_ARCH_IA16PM 1
#endif
-#if (LZO_ARCH_ARM_THUMB) && !(LZO_ARCH_ARM)
-# error "this should not happen"
+#if (LZO_ARCH_AMD64 && !LZO_ARCH_X64)
+# define LZO_ARCH_X64 1
+#elif (!LZO_ARCH_AMD64 && LZO_ARCH_X64) && defined(__LZO_ARCH_OVERRIDE)
+# define LZO_ARCH_AMD64 1
+#endif
+#if (LZO_ARCH_ARM64 && !LZO_ARCH_AARCH64)
+# define LZO_ARCH_AARCH64 1
+#elif (!LZO_ARCH_ARM64 && LZO_ARCH_AARCH64) && defined(__LZO_ARCH_OVERRIDE)
+# define LZO_ARCH_ARM64 1
+#endif
+#if (LZO_ARCH_I386 && !LZO_ARCH_X86)
+# define LZO_ARCH_X86 1
+#elif (!LZO_ARCH_I386 && LZO_ARCH_X86) && defined(__LZO_ARCH_OVERRIDE)
+# define LZO_ARCH_I386 1
+#endif
+#if (LZO_ARCH_AMD64 && !LZO_ARCH_X64) || (!LZO_ARCH_AMD64 && LZO_ARCH_X64)
+# error "unexpected configuration - check your compiler defines"
+#endif
+#if (LZO_ARCH_ARM64 && !LZO_ARCH_AARCH64) || (!LZO_ARCH_ARM64 && LZO_ARCH_AARCH64)
+# error "unexpected configuration - check your compiler defines"
+#endif
+#if (LZO_ARCH_I386 && !LZO_ARCH_X86) || (!LZO_ARCH_I386 && LZO_ARCH_X86)
+# error "unexpected configuration - check your compiler defines"
+#endif
+#if (LZO_ARCH_ARM_THUMB && !LZO_ARCH_ARM)
+# error "unexpected configuration - check your compiler defines"
#endif
-#if (LZO_ARCH_I086PM) && !(LZO_ARCH_I086)
-# error "this should not happen"
+#if (LZO_ARCH_ARM_THUMB1 && !LZO_ARCH_ARM_THUMB)
+# error "unexpected configuration - check your compiler defines"
+#endif
+#if (LZO_ARCH_ARM_THUMB2 && !LZO_ARCH_ARM_THUMB)
+# error "unexpected configuration - check your compiler defines"
+#endif
+#if (LZO_ARCH_ARM_THUMB1 && LZO_ARCH_ARM_THUMB2)
+# error "unexpected configuration - check your compiler defines"
+#endif
+#if (LZO_ARCH_I086PM && !LZO_ARCH_I086)
+# error "unexpected configuration - check your compiler defines"
#endif
#if (LZO_ARCH_I086)
# if (UINT_MAX != LZO_0xffffL)
-# error "this should not happen"
+# error "unexpected configuration - check your compiler defines"
# endif
# if (ULONG_MAX != LZO_0xffffffffL)
-# error "this should not happen"
+# error "unexpected configuration - check your compiler defines"
# endif
#endif
#if (LZO_ARCH_I386)
# if (UINT_MAX != LZO_0xffffL) && defined(__i386_int16__)
-# error "this should not happen"
+# error "unexpected configuration - check your compiler defines"
# endif
# if (UINT_MAX != LZO_0xffffffffL) && !defined(__i386_int16__)
-# error "this should not happen"
+# error "unexpected configuration - check your compiler defines"
# endif
# if (ULONG_MAX != LZO_0xffffffffL)
-# error "this should not happen"
+# error "unexpected configuration - check your compiler defines"
+# endif
+#endif
+#if (LZO_ARCH_AMD64 || LZO_ARCH_I386)
+# if !defined(LZO_TARGET_FEATURE_SSE2)
+# if defined(__SSE2__)
+# define LZO_TARGET_FEATURE_SSE2 1
+# elif defined(_MSC_VER) && ((defined(_M_IX86_FP) && ((_M_IX86_FP)+0 >= 2)) || defined(_M_AMD64))
+# define LZO_TARGET_FEATURE_SSE2 1
+# endif
+# endif
+# if !defined(LZO_TARGET_FEATURE_SSSE3)
+# if (LZO_TARGET_FEATURE_SSE2)
+# if defined(__SSSE3__)
+# define LZO_TARGET_FEATURE_SSSE3 1
+# elif defined(_MSC_VER) && defined(__AVX__)
+# define LZO_TARGET_FEATURE_SSSE3 1
+# endif
+# endif
+# endif
+# if !defined(LZO_TARGET_FEATURE_SSE4_2)
+# if (LZO_TARGET_FEATURE_SSSE3)
+# if defined(__SSE4_2__)
+# define LZO_TARGET_FEATURE_SSE4_2 1
+# endif
+# endif
+# endif
+# if !defined(LZO_TARGET_FEATURE_AVX)
+# if (LZO_TARGET_FEATURE_SSSE3)
+# if defined(__AVX__)
+# define LZO_TARGET_FEATURE_AVX 1
+# endif
+# endif
+# endif
+# if !defined(LZO_TARGET_FEATURE_AVX2)
+# if (LZO_TARGET_FEATURE_AVX)
+# if defined(__AVX2__)
+# define LZO_TARGET_FEATURE_AVX2 1
+# endif
+# endif
+# endif
+#endif
+#if (LZO_TARGET_FEATURE_SSSE3 && !(LZO_TARGET_FEATURE_SSE2))
+# error "unexpected configuration - check your compiler defines"
+#endif
+#if (LZO_TARGET_FEATURE_SSE4_2 && !(LZO_TARGET_FEATURE_SSSE3))
+# error "unexpected configuration - check your compiler defines"
+#endif
+#if (LZO_TARGET_FEATURE_AVX && !(LZO_TARGET_FEATURE_SSSE3))
+# error "unexpected configuration - check your compiler defines"
+#endif
+#if (LZO_TARGET_FEATURE_AVX2 && !(LZO_TARGET_FEATURE_AVX))
+# error "unexpected configuration - check your compiler defines"
+#endif
+#if (LZO_ARCH_ARM)
+# if !defined(LZO_TARGET_FEATURE_NEON)
+# if defined(__ARM_NEON__)
+# define LZO_TARGET_FEATURE_NEON 1
+# endif
+# endif
+#elif (LZO_ARCH_ARM64)
+# if !defined(LZO_TARGET_FEATURE_NEON)
+# if 1
+# define LZO_TARGET_FEATURE_NEON 1
+# endif
# endif
#endif
-#if !defined(__LZO_MM_OVERRIDE)
+#if 0
+#elif !defined(__LZO_MM_OVERRIDE)
#if (LZO_ARCH_I086)
#if (UINT_MAX != LZO_0xffffL)
-# error "this should not happen"
+# error "unexpected configuration - check your compiler defines"
#endif
#if defined(__TINY__) || defined(M_I86TM) || defined(_M_I86TM)
# define LZO_MM_TINY 1
@@ -899,7 +1096,7 @@
#elif (LZO_CC_ZORTECHC && defined(__VCM__))
# define LZO_MM_LARGE 1
#else
-# error "unknown memory model"
+# error "unknown LZO_ARCH_I086 memory model"
#endif
#if (LZO_OS_DOS16 || LZO_OS_OS216 || LZO_OS_WIN16)
#define LZO_HAVE_MM_HUGE_PTR 1
@@ -922,10 +1119,10 @@
#endif
#if (LZO_ARCH_I086PM) && !(LZO_HAVE_MM_HUGE_PTR)
# if (LZO_OS_DOS16)
-# error "this should not happen"
+# error "unexpected configuration - check your compiler defines"
# elif (LZO_CC_ZORTECHC)
# else
-# error "this should not happen"
+# error "unexpected configuration - check your compiler defines"
# endif
#endif
#ifdef __cplusplus
@@ -957,7 +1154,7 @@ extern "C" {
#endif
#elif (LZO_ARCH_C166)
#if !defined(__MODEL__)
-# error "FIXME - C166 __MODEL__"
+# error "FIXME - LZO_ARCH_C166 __MODEL__"
#elif ((__MODEL__) == 0)
# define LZO_MM_SMALL 1
#elif ((__MODEL__) == 1)
@@ -971,11 +1168,11 @@ extern "C" {
#elif ((__MODEL__) == 5)
# define LZO_MM_XSMALL 1
#else
-# error "FIXME - C166 __MODEL__"
+# error "FIXME - LZO_ARCH_C166 __MODEL__"
#endif
#elif (LZO_ARCH_MCS251)
#if !defined(__MODEL__)
-# error "FIXME - MCS251 __MODEL__"
+# error "FIXME - LZO_ARCH_MCS251 __MODEL__"
#elif ((__MODEL__) == 0)
# define LZO_MM_SMALL 1
#elif ((__MODEL__) == 2)
@@ -987,11 +1184,11 @@ extern "C" {
#elif ((__MODEL__) == 5)
# define LZO_MM_XSMALL 1
#else
-# error "FIXME - MCS251 __MODEL__"
+# error "FIXME - LZO_ARCH_MCS251 __MODEL__"
#endif
#elif (LZO_ARCH_MCS51)
#if !defined(__MODEL__)
-# error "FIXME - MCS51 __MODEL__"
+# error "FIXME - LZO_ARCH_MCS51 __MODEL__"
#elif ((__MODEL__) == 1)
# define LZO_MM_SMALL 1
#elif ((__MODEL__) == 2)
@@ -1003,7 +1200,7 @@ extern "C" {
#elif ((__MODEL__) == 5)
# define LZO_MM_XSMALL 1
#else
-# error "FIXME - MCS51 __MODEL__"
+# error "FIXME - LZO_ARCH_MCS51 __MODEL__"
#endif
#elif (LZO_ARCH_CRAY_PVP)
# define LZO_MM_PVP 1
@@ -1030,35 +1227,818 @@ extern "C" {
# error "unknown memory model"
#endif
#endif
+#if !defined(__lzo_gnuc_extension__)
+#if (LZO_CC_GNUC >= 0x020800ul)
+# define __lzo_gnuc_extension__ __extension__
+#elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE)
+# define __lzo_gnuc_extension__ __extension__
+#elif (LZO_CC_IBMC >= 600)
+# define __lzo_gnuc_extension__ __extension__
+#else
+#endif
+#endif
+#if !defined(__lzo_gnuc_extension__)
+# define __lzo_gnuc_extension__ /*empty*/
+#endif
+#if !defined(LZO_CFG_USE_NEW_STYLE_CASTS) && defined(__cplusplus) && 0
+# if (LZO_CC_GNUC && (LZO_CC_GNUC < 0x020800ul))
+# define LZO_CFG_USE_NEW_STYLE_CASTS 0
+# elif (LZO_CC_INTELC && (__INTEL_COMPILER < 1200))
+# define LZO_CFG_USE_NEW_STYLE_CASTS 0
+# else
+# define LZO_CFG_USE_NEW_STYLE_CASTS 1
+# endif
+#endif
+#if !defined(LZO_CFG_USE_NEW_STYLE_CASTS)
+# define LZO_CFG_USE_NEW_STYLE_CASTS 0
+#endif
+#if !defined(__cplusplus)
+# if defined(LZO_CFG_USE_NEW_STYLE_CASTS)
+# undef LZO_CFG_USE_NEW_STYLE_CASTS
+# endif
+# define LZO_CFG_USE_NEW_STYLE_CASTS 0
+#endif
+#if !defined(LZO_REINTERPRET_CAST)
+# if (LZO_CFG_USE_NEW_STYLE_CASTS)
+# define LZO_REINTERPRET_CAST(t,e) (reinterpret_cast<t> (e))
+# endif
+#endif
+#if !defined(LZO_REINTERPRET_CAST)
+# define LZO_REINTERPRET_CAST(t,e) ((t) (e))
+#endif
+#if !defined(LZO_STATIC_CAST)
+# if (LZO_CFG_USE_NEW_STYLE_CASTS)
+# define LZO_STATIC_CAST(t,e) (static_cast<t> (e))
+# endif
+#endif
+#if !defined(LZO_STATIC_CAST)
+# define LZO_STATIC_CAST(t,e) ((t) (e))
+#endif
+#if !defined(LZO_STATIC_CAST2)
+# define LZO_STATIC_CAST2(t1,t2,e) LZO_STATIC_CAST(t1, LZO_STATIC_CAST(t2, e))
+#endif
+#if !defined(LZO_UNCONST_CAST)
+# if (LZO_CFG_USE_NEW_STYLE_CASTS)
+# define LZO_UNCONST_CAST(t,e) (const_cast<t> (e))
+# elif (LZO_HAVE_MM_HUGE_PTR)
+# define LZO_UNCONST_CAST(t,e) ((t) (e))
+# elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE)
+# define LZO_UNCONST_CAST(t,e) ((t) ((void *) ((lzo_uintptr_t) ((const void *) (e)))))
+# endif
+#endif
+#if !defined(LZO_UNCONST_CAST)
+# define LZO_UNCONST_CAST(t,e) ((t) ((void *) ((const void *) (e))))
+#endif
+#if !defined(LZO_UNCONST_VOLATILE_CAST)
+# if (LZO_CFG_USE_NEW_STYLE_CASTS)
+# define LZO_UNCONST_VOLATILE_CAST(t,e) (const_cast<t> (e))
+# elif (LZO_HAVE_MM_HUGE_PTR)
+# define LZO_UNCONST_VOLATILE_CAST(t,e) ((t) (e))
+# elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE)
+# define LZO_UNCONST_VOLATILE_CAST(t,e) ((t) ((volatile void *) ((lzo_uintptr_t) ((volatile const void *) (e)))))
+# endif
+#endif
+#if !defined(LZO_UNCONST_VOLATILE_CAST)
+# define LZO_UNCONST_VOLATILE_CAST(t,e) ((t) ((volatile void *) ((volatile const void *) (e))))
+#endif
+#if !defined(LZO_UNVOLATILE_CAST)
+# if (LZO_CFG_USE_NEW_STYLE_CASTS)
+# define LZO_UNVOLATILE_CAST(t,e) (const_cast<t> (e))
+# elif (LZO_HAVE_MM_HUGE_PTR)
+# define LZO_UNVOLATILE_CAST(t,e) ((t) (e))
+# elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE)
+# define LZO_UNVOLATILE_CAST(t,e) ((t) ((void *) ((lzo_uintptr_t) ((volatile void *) (e)))))
+# endif
+#endif
+#if !defined(LZO_UNVOLATILE_CAST)
+# define LZO_UNVOLATILE_CAST(t,e) ((t) ((void *) ((volatile void *) (e))))
+#endif
+#if !defined(LZO_UNVOLATILE_CONST_CAST)
+# if (LZO_CFG_USE_NEW_STYLE_CASTS)
+# define LZO_UNVOLATILE_CONST_CAST(t,e) (const_cast<t> (e))
+# elif (LZO_HAVE_MM_HUGE_PTR)
+# define LZO_UNVOLATILE_CONST_CAST(t,e) ((t) (e))
+# elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE)
+# define LZO_UNVOLATILE_CONST_CAST(t,e) ((t) ((const void *) ((lzo_uintptr_t) ((volatile const void *) (e)))))
+# endif
+#endif
+#if !defined(LZO_UNVOLATILE_CONST_CAST)
+# define LZO_UNVOLATILE_CONST_CAST(t,e) ((t) ((const void *) ((volatile const void *) (e))))
+#endif
+#if !defined(LZO_PCAST)
+# if (LZO_HAVE_MM_HUGE_PTR)
+# define LZO_PCAST(t,e) ((t) (e))
+# endif
+#endif
+#if !defined(LZO_PCAST)
+# define LZO_PCAST(t,e) LZO_STATIC_CAST(t, LZO_STATIC_CAST(void *, e))
+#endif
+#if !defined(LZO_CCAST)
+# if (LZO_HAVE_MM_HUGE_PTR)
+# define LZO_CCAST(t,e) ((t) (e))
+# endif
+#endif
+#if !defined(LZO_CCAST)
+# define LZO_CCAST(t,e) LZO_STATIC_CAST(t, LZO_STATIC_CAST(const void *, e))
+#endif
+#if !defined(LZO_ICONV)
+# define LZO_ICONV(t,e) LZO_STATIC_CAST(t, e)
+#endif
+#if !defined(LZO_ICAST)
+# define LZO_ICAST(t,e) LZO_STATIC_CAST(t, e)
+#endif
+#if !defined(LZO_ITRUNC)
+# define LZO_ITRUNC(t,e) LZO_STATIC_CAST(t, e)
+#endif
+#if !defined(__lzo_cte)
+# if (LZO_CC_MSC || LZO_CC_WATCOMC)
+# define __lzo_cte(e) ((void)0,(e))
+# elif 1
+# define __lzo_cte(e) ((void)0,(e))
+# endif
+#endif
+#if !defined(__lzo_cte)
+# define __lzo_cte(e) (e)
+#endif
+#if !defined(LZO_BLOCK_BEGIN)
+# define LZO_BLOCK_BEGIN do {
+# define LZO_BLOCK_END } while __lzo_cte(0)
+#endif
+#if !defined(LZO_UNUSED)
+# if (LZO_CC_BORLANDC && (__BORLANDC__ >= 0x0600))
+# define LZO_UNUSED(var) ((void) &var)
+# elif (LZO_CC_BORLANDC || LZO_CC_HIGHC || LZO_CC_NDPC || LZO_CC_PELLESC || LZO_CC_TURBOC)
+# define LZO_UNUSED(var) if (&var) ; else
+# elif (LZO_CC_CLANG && (LZO_CC_CLANG >= 0x030200ul))
+# define LZO_UNUSED(var) ((void) &var)
+# elif (LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE)
+# define LZO_UNUSED(var) ((void) var)
+# elif (LZO_CC_MSC && (_MSC_VER < 900))
+# define LZO_UNUSED(var) if (&var) ; else
+# elif (LZO_CC_KEILC)
+# define LZO_UNUSED(var) {LZO_EXTERN_C int lzo_unused__[1-2*!(sizeof(var)>0)];}
+# elif (LZO_CC_PACIFICC)
+# define LZO_UNUSED(var) ((void) sizeof(var))
+# elif (LZO_CC_WATCOMC) && defined(__cplusplus)
+# define LZO_UNUSED(var) ((void) var)
+# else
+# define LZO_UNUSED(var) ((void) &var)
+# endif
+#endif
+#if !defined(LZO_UNUSED_FUNC)
+# if (LZO_CC_BORLANDC && (__BORLANDC__ >= 0x0600))
+# define LZO_UNUSED_FUNC(func) ((void) func)
+# elif (LZO_CC_BORLANDC || LZO_CC_NDPC || LZO_CC_TURBOC)
+# define LZO_UNUSED_FUNC(func) if (func) ; else
+# elif (LZO_CC_CLANG || LZO_CC_LLVM)
+# define LZO_UNUSED_FUNC(func) ((void) &func)
+# elif (LZO_CC_MSC && (_MSC_VER < 900))
+# define LZO_UNUSED_FUNC(func) if (func) ; else
+# elif (LZO_CC_MSC)
+# define LZO_UNUSED_FUNC(func) ((void) &func)
+# elif (LZO_CC_KEILC || LZO_CC_PELLESC)
+# define LZO_UNUSED_FUNC(func) {LZO_EXTERN_C int lzo_unused_func__[1-2*!(sizeof((int)func)>0)];}
+# else
+# define LZO_UNUSED_FUNC(func) ((void) func)
+# endif
+#endif
+#if !defined(LZO_UNUSED_LABEL)
+# if (LZO_CC_CLANG >= 0x020800ul)
+# define LZO_UNUSED_LABEL(l) (__lzo_gnuc_extension__ ((void) ((const void *) &&l)))
+# elif (LZO_CC_ARMCC || LZO_CC_CLANG || LZO_CC_INTELC || LZO_CC_WATCOMC)
+# define LZO_UNUSED_LABEL(l) if __lzo_cte(0) goto l
+# else
+# define LZO_UNUSED_LABEL(l) switch (0) case 1:goto l
+# endif
+#endif
+#if !defined(LZO_DEFINE_UNINITIALIZED_VAR)
+# if 0
+# define LZO_DEFINE_UNINITIALIZED_VAR(type,var,init) type var
+# elif 0 && (LZO_CC_GNUC)
+# define LZO_DEFINE_UNINITIALIZED_VAR(type,var,init) type var = var
+# else
+# define LZO_DEFINE_UNINITIALIZED_VAR(type,var,init) type var = init
+# endif
+#endif
+#if !defined(__lzo_inline)
+#if (LZO_CC_TURBOC && (__TURBOC__ <= 0x0295))
+#elif defined(__cplusplus)
+# define __lzo_inline inline
+#elif defined(__STDC_VERSION__) && (__STDC_VERSION__-0 >= 199901L)
+# define __lzo_inline inline
+#elif (LZO_CC_BORLANDC && (__BORLANDC__ >= 0x0550))
+# define __lzo_inline __inline
+#elif (LZO_CC_ARMCC_GNUC || LZO_CC_CILLY || LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE || LZO_CC_PGI)
+# define __lzo_inline __inline__
+#elif (LZO_CC_DMC)
+# define __lzo_inline __inline
+#elif (LZO_CC_GHS)
+# define __lzo_inline __inline__
+#elif (LZO_CC_IBMC >= 600)
+# define __lzo_inline __inline__
+#elif (LZO_CC_INTELC)
+# define __lzo_inline __inline
+#elif (LZO_CC_MWERKS && (__MWERKS__ >= 0x2405))
+# define __lzo_inline __inline
+#elif (LZO_CC_MSC && (_MSC_VER >= 900))
+# define __lzo_inline __inline
+#elif (LZO_CC_SUNPROC >= 0x5100)
+# define __lzo_inline __inline__
+#endif
+#endif
+#if defined(__lzo_inline)
+# ifndef __lzo_HAVE_inline
+# define __lzo_HAVE_inline 1
+# endif
+#else
+# define __lzo_inline /*empty*/
+#endif
+#if !defined(__lzo_forceinline)
+#if (LZO_CC_GNUC >= 0x030200ul)
+# define __lzo_forceinline __inline__ __attribute__((__always_inline__))
+#elif (LZO_CC_IBMC >= 700)
+# define __lzo_forceinline __inline__ __attribute__((__always_inline__))
+#elif (LZO_CC_INTELC_MSC && (__INTEL_COMPILER >= 450))
+# define __lzo_forceinline __forceinline
+#elif (LZO_CC_INTELC_GNUC && (__INTEL_COMPILER >= 800))
+# define __lzo_forceinline __inline__ __attribute__((__always_inline__))
+#elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE)
+# define __lzo_forceinline __inline__ __attribute__((__always_inline__))
+#elif (LZO_CC_MSC && (_MSC_VER >= 1200))
+# define __lzo_forceinline __forceinline
+#elif (LZO_CC_PGI >= 0x0d0a00ul)
+# define __lzo_forceinline __inline__ __attribute__((__always_inline__))
+#elif (LZO_CC_SUNPROC >= 0x5100)
+# define __lzo_forceinline __inline__ __attribute__((__always_inline__))
+#endif
+#endif
+#if defined(__lzo_forceinline)
+# ifndef __lzo_HAVE_forceinline
+# define __lzo_HAVE_forceinline 1
+# endif
+#else
+# define __lzo_forceinline __lzo_inline
+#endif
+#if !defined(__lzo_noinline)
+#if 1 && (LZO_ARCH_I386) && (LZO_CC_GNUC >= 0x040000ul) && (LZO_CC_GNUC < 0x040003ul)
+# define __lzo_noinline __attribute__((__noinline__,__used__))
+#elif (LZO_CC_GNUC >= 0x030200ul)
+# define __lzo_noinline __attribute__((__noinline__))
+#elif (LZO_CC_IBMC >= 700)
+# define __lzo_noinline __attribute__((__noinline__))
+#elif (LZO_CC_INTELC_MSC && (__INTEL_COMPILER >= 600))
+# define __lzo_noinline __declspec(noinline)
+#elif (LZO_CC_INTELC_GNUC && (__INTEL_COMPILER >= 800))
+# define __lzo_noinline __attribute__((__noinline__))
+#elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE)
+# define __lzo_noinline __attribute__((__noinline__))
+#elif (LZO_CC_MSC && (_MSC_VER >= 1300))
+# define __lzo_noinline __declspec(noinline)
+#elif (LZO_CC_MWERKS && (__MWERKS__ >= 0x3200) && (LZO_OS_WIN32 || LZO_OS_WIN64))
+# if defined(__cplusplus)
+# else
+# define __lzo_noinline __declspec(noinline)
+# endif
+#elif (LZO_CC_PGI >= 0x0d0a00ul)
+# define __lzo_noinline __attribute__((__noinline__))
+#elif (LZO_CC_SUNPROC >= 0x5100)
+# define __lzo_noinline __attribute__((__noinline__))
+#endif
+#endif
+#if defined(__lzo_noinline)
+# ifndef __lzo_HAVE_noinline
+# define __lzo_HAVE_noinline 1
+# endif
+#else
+# define __lzo_noinline /*empty*/
+#endif
+#if (__lzo_HAVE_forceinline || __lzo_HAVE_noinline) && !(__lzo_HAVE_inline)
+# error "unexpected configuration - check your compiler defines"
+#endif
+#if !defined(__lzo_static_inline)
+#if (LZO_CC_IBMC)
+# define __lzo_static_inline __lzo_gnuc_extension__ static __lzo_inline
+#endif
+#endif
+#if !defined(__lzo_static_inline)
+# define __lzo_static_inline static __lzo_inline
+#endif
+#if !defined(__lzo_static_forceinline)
+#if (LZO_CC_IBMC)
+# define __lzo_static_forceinline __lzo_gnuc_extension__ static __lzo_forceinline
+#endif
+#endif
+#if !defined(__lzo_static_forceinline)
+# define __lzo_static_forceinline static __lzo_forceinline
+#endif
+#if !defined(__lzo_static_noinline)
+#if (LZO_CC_IBMC)
+# define __lzo_static_noinline __lzo_gnuc_extension__ static __lzo_noinline
+#endif
+#endif
+#if !defined(__lzo_static_noinline)
+# define __lzo_static_noinline static __lzo_noinline
+#endif
+#if !defined(__lzo_c99_extern_inline)
+#if defined(__GNUC_GNU_INLINE__)
+# define __lzo_c99_extern_inline __lzo_inline
+#elif defined(__GNUC_STDC_INLINE__)
+# define __lzo_c99_extern_inline extern __lzo_inline
+#elif defined(__STDC_VERSION__) && (__STDC_VERSION__-0 >= 199901L)
+# define __lzo_c99_extern_inline extern __lzo_inline
+#endif
+#if !defined(__lzo_c99_extern_inline) && (__lzo_HAVE_inline)
+# define __lzo_c99_extern_inline __lzo_inline
+#endif
+#endif
+#if defined(__lzo_c99_extern_inline)
+# ifndef __lzo_HAVE_c99_extern_inline
+# define __lzo_HAVE_c99_extern_inline 1
+# endif
+#else
+# define __lzo_c99_extern_inline /*empty*/
+#endif
+#if !defined(__lzo_may_alias)
+#if (LZO_CC_GNUC >= 0x030400ul)
+# define __lzo_may_alias __attribute__((__may_alias__))
+#elif (LZO_CC_CLANG >= 0x020900ul)
+# define __lzo_may_alias __attribute__((__may_alias__))
+#elif (LZO_CC_INTELC_GNUC && (__INTEL_COMPILER >= 1210)) && 0
+# define __lzo_may_alias __attribute__((__may_alias__))
+#elif (LZO_CC_PGI >= 0x0d0a00ul) && 0
+# define __lzo_may_alias __attribute__((__may_alias__))
+#endif
+#endif
+#if defined(__lzo_may_alias)
+# ifndef __lzo_HAVE_may_alias
+# define __lzo_HAVE_may_alias 1
+# endif
+#else
+# define __lzo_may_alias /*empty*/
+#endif
+#if !defined(__lzo_noreturn)
+#if (LZO_CC_GNUC >= 0x020700ul)
+# define __lzo_noreturn __attribute__((__noreturn__))
+#elif (LZO_CC_IBMC >= 700)
+# define __lzo_noreturn __attribute__((__noreturn__))
+#elif (LZO_CC_INTELC_MSC && (__INTEL_COMPILER >= 450))
+# define __lzo_noreturn __declspec(noreturn)
+#elif (LZO_CC_INTELC_GNUC && (__INTEL_COMPILER >= 600))
+# define __lzo_noreturn __attribute__((__noreturn__))
+#elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE)
+# define __lzo_noreturn __attribute__((__noreturn__))
+#elif (LZO_CC_MSC && (_MSC_VER >= 1200))
+# define __lzo_noreturn __declspec(noreturn)
+#elif (LZO_CC_PGI >= 0x0d0a00ul)
+# define __lzo_noreturn __attribute__((__noreturn__))
+#endif
+#endif
+#if defined(__lzo_noreturn)
+# ifndef __lzo_HAVE_noreturn
+# define __lzo_HAVE_noreturn 1
+# endif
+#else
+# define __lzo_noreturn /*empty*/
+#endif
+#if !defined(__lzo_nothrow)
+#if (LZO_CC_GNUC >= 0x030300ul)
+# define __lzo_nothrow __attribute__((__nothrow__))
+#elif (LZO_CC_INTELC_MSC && (__INTEL_COMPILER >= 450)) && defined(__cplusplus)
+# define __lzo_nothrow __declspec(nothrow)
+#elif (LZO_CC_INTELC_GNUC && (__INTEL_COMPILER >= 900))
+# define __lzo_nothrow __attribute__((__nothrow__))
+#elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE)
+# define __lzo_nothrow __attribute__((__nothrow__))
+#elif (LZO_CC_MSC && (_MSC_VER >= 1200)) && defined(__cplusplus)
+# define __lzo_nothrow __declspec(nothrow)
+#endif
+#endif
+#if defined(__lzo_nothrow)
+# ifndef __lzo_HAVE_nothrow
+# define __lzo_HAVE_nothrow 1
+# endif
+#else
+# define __lzo_nothrow /*empty*/
+#endif
+#if !defined(__lzo_restrict)
+#if (LZO_CC_GNUC >= 0x030400ul)
+# define __lzo_restrict __restrict__
+#elif (LZO_CC_IBMC >= 800) && !defined(__cplusplus)
+# define __lzo_restrict __restrict__
+#elif (LZO_CC_IBMC >= 1210)
+# define __lzo_restrict __restrict__
+#elif (LZO_CC_INTELC_MSC && (__INTEL_COMPILER >= 600))
+#elif (LZO_CC_INTELC_GNUC && (__INTEL_COMPILER >= 600))
+# define __lzo_restrict __restrict__
+#elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_LLVM)
+# define __lzo_restrict __restrict__
+#elif (LZO_CC_MSC && (_MSC_VER >= 1400))
+# define __lzo_restrict __restrict
+#elif (LZO_CC_PGI >= 0x0d0a00ul)
+# define __lzo_restrict __restrict__
+#endif
+#endif
+#if defined(__lzo_restrict)
+# ifndef __lzo_HAVE_restrict
+# define __lzo_HAVE_restrict 1
+# endif
+#else
+# define __lzo_restrict /*empty*/
+#endif
+#if !defined(__lzo_alignof)
+#if (LZO_CC_ARMCC || LZO_CC_CILLY || LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE || LZO_CC_PGI)
+# define __lzo_alignof(e) __alignof__(e)
+#elif (LZO_CC_GHS) && !defined(__cplusplus)
+# define __lzo_alignof(e) __alignof__(e)
+#elif (LZO_CC_IBMC >= 600)
+# define __lzo_alignof(e) (__lzo_gnuc_extension__ __alignof__(e))
+#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 700))
+# define __lzo_alignof(e) __alignof__(e)
+#elif (LZO_CC_MSC && (_MSC_VER >= 1300))
+# define __lzo_alignof(e) __alignof(e)
+#elif (LZO_CC_SUNPROC >= 0x5100)
+# define __lzo_alignof(e) __alignof__(e)
+#endif
+#endif
+#if defined(__lzo_alignof)
+# ifndef __lzo_HAVE_alignof
+# define __lzo_HAVE_alignof 1
+# endif
+#endif
+#if !defined(__lzo_struct_packed)
+#if (LZO_CC_CLANG && (LZO_CC_CLANG < 0x020800ul)) && defined(__cplusplus)
+#elif (LZO_CC_GNUC && (LZO_CC_GNUC < 0x020700ul))
+#elif (LZO_CC_GNUC && (LZO_CC_GNUC < 0x020800ul)) && defined(__cplusplus)
+#elif (LZO_CC_PCC && (LZO_CC_PCC < 0x010100ul))
+#elif (LZO_CC_SUNPROC && (LZO_CC_SUNPROC < 0x5110)) && !defined(__cplusplus)
+#elif (LZO_CC_GNUC >= 0x030400ul) && !(LZO_CC_PCC_GNUC) && (LZO_ARCH_AMD64 || LZO_ARCH_I386)
+# define __lzo_struct_packed(s) struct s {
+# define __lzo_struct_packed_end() } __attribute__((__gcc_struct__,__packed__));
+# define __lzo_struct_packed_ma_end() } __lzo_may_alias __attribute__((__gcc_struct__,__packed__));
+#elif (LZO_CC_ARMCC || LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_INTELC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE || (LZO_CC_PGI >= 0x0d0a00ul) || (LZO_CC_SUNPROC >= 0x5100))
+# define __lzo_struct_packed(s) struct s {
+# define __lzo_struct_packed_end() } __attribute__((__packed__));
+# define __lzo_struct_packed_ma_end() } __lzo_may_alias __attribute__((__packed__));
+#elif (LZO_CC_IBMC >= 700)
+# define __lzo_struct_packed(s) __lzo_gnuc_extension__ struct s {
+# define __lzo_struct_packed_end() } __attribute__((__packed__));
+# define __lzo_struct_packed_ma_end() } __lzo_may_alias __attribute__((__packed__));
+#elif (LZO_CC_INTELC_MSC) || (LZO_CC_MSC && (_MSC_VER >= 1300))
+# define __lzo_struct_packed(s) __pragma(pack(push,1)) struct s {
+# define __lzo_struct_packed_end() } __pragma(pack(pop));
+#elif (LZO_CC_WATCOMC && (__WATCOMC__ >= 900))
+# define __lzo_struct_packed(s) _Packed struct s {
+# define __lzo_struct_packed_end() };
+#endif
+#endif
+#if defined(__lzo_struct_packed) && !defined(__lzo_struct_packed_ma)
+# define __lzo_struct_packed_ma(s) __lzo_struct_packed(s)
+#endif
+#if defined(__lzo_struct_packed_end) && !defined(__lzo_struct_packed_ma_end)
+# define __lzo_struct_packed_ma_end() __lzo_struct_packed_end()
+#endif
+#if !defined(__lzo_byte_struct)
+#if defined(__lzo_struct_packed)
+# define __lzo_byte_struct(s,n) __lzo_struct_packed(s) unsigned char a[n]; __lzo_struct_packed_end()
+# define __lzo_byte_struct_ma(s,n) __lzo_struct_packed_ma(s) unsigned char a[n]; __lzo_struct_packed_ma_end()
+#elif (LZO_CC_CILLY || LZO_CC_CLANG || LZO_CC_PGI || (LZO_CC_SUNPROC >= 0x5100))
+# define __lzo_byte_struct(s,n) struct s { unsigned char a[n]; } __attribute__((__packed__));
+# define __lzo_byte_struct_ma(s,n) struct s { unsigned char a[n]; } __lzo_may_alias __attribute__((__packed__));
+#endif
+#endif
+#if defined(__lzo_byte_struct) && !defined(__lzo_byte_struct_ma)
+# define __lzo_byte_struct_ma(s,n) __lzo_byte_struct(s,n)
+#endif
+#if !defined(__lzo_struct_align16) && (__lzo_HAVE_alignof)
+#if (LZO_CC_GNUC && (LZO_CC_GNUC < 0x030000ul))
+#elif (LZO_CC_CLANG && (LZO_CC_CLANG < 0x020800ul)) && defined(__cplusplus)
+#elif (LZO_CC_CILLY || LZO_CC_PCC)
+#elif (LZO_CC_INTELC_MSC) || (LZO_CC_MSC && (_MSC_VER >= 1300))
+# define __lzo_struct_align16(s) struct __declspec(align(16)) s {
+# define __lzo_struct_align16_end() };
+# define __lzo_struct_align32(s) struct __declspec(align(32)) s {
+# define __lzo_struct_align32_end() };
+# define __lzo_struct_align64(s) struct __declspec(align(64)) s {
+# define __lzo_struct_align64_end() };
+#elif (LZO_CC_ARMCC || LZO_CC_CLANG || LZO_CC_GNUC || (LZO_CC_IBMC >= 700) || LZO_CC_INTELC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE)
+# define __lzo_struct_align16(s) struct s {
+# define __lzo_struct_align16_end() } __attribute__((__aligned__(16)));
+# define __lzo_struct_align32(s) struct s {
+# define __lzo_struct_align32_end() } __attribute__((__aligned__(32)));
+# define __lzo_struct_align64(s) struct s {
+# define __lzo_struct_align64_end() } __attribute__((__aligned__(64)));
+#endif
+#endif
+#if !defined(__lzo_union_um)
+#if (LZO_CC_CLANG && (LZO_CC_CLANG < 0x020800ul)) && defined(__cplusplus)
+#elif (LZO_CC_GNUC && (LZO_CC_GNUC < 0x020700ul))
+#elif (LZO_CC_GNUC && (LZO_CC_GNUC < 0x020800ul)) && defined(__cplusplus)
+#elif (LZO_CC_INTELC_GNUC && (__INTEL_COMPILER < 810))
+#elif (LZO_CC_PCC && (LZO_CC_PCC < 0x010100ul))
+#elif (LZO_CC_SUNPROC && (LZO_CC_SUNPROC < 0x5110)) && !defined(__cplusplus)
+#elif (LZO_CC_ARMCC || LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_INTELC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE || (LZO_CC_PGI >= 0x0d0a00ul) || (LZO_CC_SUNPROC >= 0x5100))
+# define __lzo_union_am(s) union s {
+# define __lzo_union_am_end() } __lzo_may_alias;
+# define __lzo_union_um(s) union s {
+# define __lzo_union_um_end() } __lzo_may_alias __attribute__((__packed__));
+#elif (LZO_CC_IBMC >= 700)
+# define __lzo_union_am(s) __lzo_gnuc_extension__ union s {
+# define __lzo_union_am_end() } __lzo_may_alias;
+# define __lzo_union_um(s) __lzo_gnuc_extension__ union s {
+# define __lzo_union_um_end() } __lzo_may_alias __attribute__((__packed__));
+#elif (LZO_CC_INTELC_MSC) || (LZO_CC_MSC && (_MSC_VER >= 1300))
+# define __lzo_union_um(s) __pragma(pack(push,1)) union s {
+# define __lzo_union_um_end() } __pragma(pack(pop));
+#elif (LZO_CC_WATCOMC && (__WATCOMC__ >= 900))
+# define __lzo_union_um(s) _Packed union s {
+# define __lzo_union_um_end() };
+#endif
+#endif
+#if !defined(__lzo_union_am)
+# define __lzo_union_am(s) union s {
+# define __lzo_union_am_end() };
+#endif
+#if !defined(__lzo_constructor)
+#if (LZO_CC_GNUC >= 0x030400ul)
+# define __lzo_constructor __attribute__((__constructor__,__used__))
+#elif (LZO_CC_GNUC >= 0x020700ul)
+# define __lzo_constructor __attribute__((__constructor__))
+#elif (LZO_CC_INTELC_GNUC && (__INTEL_COMPILER >= 800))
+# define __lzo_constructor __attribute__((__constructor__,__used__))
+#elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE)
+# define __lzo_constructor __attribute__((__constructor__))
+#endif
+#endif
+#if defined(__lzo_constructor)
+# ifndef __lzo_HAVE_constructor
+# define __lzo_HAVE_constructor 1
+# endif
+#endif
+#if !defined(__lzo_destructor)
+#if (LZO_CC_GNUC >= 0x030400ul)
+# define __lzo_destructor __attribute__((__destructor__,__used__))
+#elif (LZO_CC_GNUC >= 0x020700ul)
+# define __lzo_destructor __attribute__((__destructor__))
+#elif (LZO_CC_INTELC_GNUC && (__INTEL_COMPILER >= 800))
+# define __lzo_destructor __attribute__((__destructor__,__used__))
+#elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE)
+# define __lzo_destructor __attribute__((__destructor__))
+#endif
+#endif
+#if defined(__lzo_destructor)
+# ifndef __lzo_HAVE_destructor
+# define __lzo_HAVE_destructor 1
+# endif
+#endif
+#if (__lzo_HAVE_destructor) && !(__lzo_HAVE_constructor)
+# error "unexpected configuration - check your compiler defines"
+#endif
+#if !defined(__lzo_likely) && !defined(__lzo_unlikely)
+#if (LZO_CC_GNUC >= 0x030200ul)
+# define __lzo_likely(e) (__builtin_expect(!!(e),1))
+# define __lzo_unlikely(e) (__builtin_expect(!!(e),0))
+#elif (LZO_CC_IBMC >= 1010)
+# define __lzo_likely(e) (__builtin_expect(!!(e),1))
+# define __lzo_unlikely(e) (__builtin_expect(!!(e),0))
+#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 800))
+# define __lzo_likely(e) (__builtin_expect(!!(e),1))
+# define __lzo_unlikely(e) (__builtin_expect(!!(e),0))
+#elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE)
+# define __lzo_likely(e) (__builtin_expect(!!(e),1))
+# define __lzo_unlikely(e) (__builtin_expect(!!(e),0))
+#endif
+#endif
+#if defined(__lzo_likely)
+# ifndef __lzo_HAVE_likely
+# define __lzo_HAVE_likely 1
+# endif
+#else
+# define __lzo_likely(e) (e)
+#endif
+#if defined(__lzo_unlikely)
+# ifndef __lzo_HAVE_unlikely
+# define __lzo_HAVE_unlikely 1
+# endif
+#else
+# define __lzo_unlikely(e) (e)
+#endif
+#if !defined(__lzo_static_unused_void_func)
+# if 1 && (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || (LZO_CC_GNUC >= 0x020700ul) || LZO_CC_INTELC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE || LZO_CC_PGI)
+# define __lzo_static_unused_void_func(f) static void __attribute__((__unused__)) f(void)
+# else
+# define __lzo_static_unused_void_func(f) static __lzo_inline void f(void)
+# endif
+#endif
+#if !defined(__lzo_loop_forever)
+# if (LZO_CC_IBMC)
+# define __lzo_loop_forever() LZO_BLOCK_BEGIN for (;;) { ; } LZO_BLOCK_END
+# else
+# define __lzo_loop_forever() do { ; } while __lzo_cte(1)
+# endif
+#endif
+#if !defined(__lzo_unreachable)
+#if (LZO_CC_CLANG && (LZO_CC_CLANG >= 0x020800ul))
+# define __lzo_unreachable() __builtin_unreachable();
+#elif (LZO_CC_GNUC >= 0x040500ul)
+# define __lzo_unreachable() __builtin_unreachable();
+#elif (LZO_CC_INTELC_GNUC && (__INTEL_COMPILER >= 1300)) && 1
+# define __lzo_unreachable() __builtin_unreachable();
+#endif
+#endif
+#if defined(__lzo_unreachable)
+# ifndef __lzo_HAVE_unreachable
+# define __lzo_HAVE_unreachable 1
+# endif
+#else
+# if 0
+# define __lzo_unreachable() ((void)0);
+# else
+# define __lzo_unreachable() __lzo_loop_forever();
+# endif
+#endif
+#ifndef __LZO_CTA_NAME
+#if (LZO_CFG_USE_COUNTER)
+# define __LZO_CTA_NAME(a) LZO_PP_ECONCAT2(a,__COUNTER__)
+#else
+# define __LZO_CTA_NAME(a) LZO_PP_ECONCAT2(a,__LINE__)
+#endif
+#endif
+#if !defined(LZO_COMPILE_TIME_ASSERT_HEADER)
+# if (LZO_CC_AZTECC || LZO_CC_ZORTECHC)
+# define LZO_COMPILE_TIME_ASSERT_HEADER(e) LZO_EXTERN_C_BEGIN extern int __LZO_CTA_NAME(lzo_cta__)[1-!(e)]; LZO_EXTERN_C_END
+# elif (LZO_CC_DMC || LZO_CC_SYMANTECC)
+# define LZO_COMPILE_TIME_ASSERT_HEADER(e) LZO_EXTERN_C_BEGIN extern int __LZO_CTA_NAME(lzo_cta__)[1u-2*!(e)]; LZO_EXTERN_C_END
+# elif (LZO_CC_TURBOC && (__TURBOC__ == 0x0295))
+# define LZO_COMPILE_TIME_ASSERT_HEADER(e) LZO_EXTERN_C_BEGIN extern int __LZO_CTA_NAME(lzo_cta__)[1-!(e)]; LZO_EXTERN_C_END
+# elif (LZO_CC_CLANG && (LZO_CC_CLANG < 0x020900ul)) && defined(__cplusplus)
+# define LZO_COMPILE_TIME_ASSERT_HEADER(e) LZO_EXTERN_C_BEGIN int __LZO_CTA_NAME(lzo_cta_f__)(int [1-2*!(e)]); LZO_EXTERN_C_END
+# elif (LZO_CC_GNUC) && defined(__CHECKER__) && defined(__SPARSE_CHECKER__)
+# define LZO_COMPILE_TIME_ASSERT_HEADER(e) LZO_EXTERN_C_BEGIN enum {__LZO_CTA_NAME(lzo_cta_e__)=1/!!(e)} __attribute__((__unused__)); LZO_EXTERN_C_END
+# else
+# define LZO_COMPILE_TIME_ASSERT_HEADER(e) LZO_EXTERN_C_BEGIN extern int __LZO_CTA_NAME(lzo_cta__)[1-2*!(e)]; LZO_EXTERN_C_END
+# endif
+#endif
+#if !defined(LZO_COMPILE_TIME_ASSERT)
+# if (LZO_CC_AZTECC)
+# define LZO_COMPILE_TIME_ASSERT(e) {typedef int __LZO_CTA_NAME(lzo_cta_t__)[1-!(e)];}
+# elif (LZO_CC_DMC || LZO_CC_PACIFICC || LZO_CC_SYMANTECC || LZO_CC_ZORTECHC)
+# define LZO_COMPILE_TIME_ASSERT(e) switch(0) case 1:case !(e):break;
+# elif (LZO_CC_GNUC) && defined(__CHECKER__) && defined(__SPARSE_CHECKER__)
+# define LZO_COMPILE_TIME_ASSERT(e) {(void) (0/!!(e));}
+# elif (LZO_CC_GNUC >= 0x040700ul) && (LZO_CFG_USE_COUNTER) && defined(__cplusplus)
+# define LZO_COMPILE_TIME_ASSERT(e) {enum {__LZO_CTA_NAME(lzo_cta_e__)=1/!!(e)} __attribute__((__unused__));}
+# elif (LZO_CC_GNUC >= 0x040700ul)
+# define LZO_COMPILE_TIME_ASSERT(e) {typedef int __LZO_CTA_NAME(lzo_cta_t__)[1-2*!(e)] __attribute__((__unused__));}
+# elif (LZO_CC_MSC && (_MSC_VER < 900))
+# define LZO_COMPILE_TIME_ASSERT(e) switch(0) case 1:case !(e):break;
+# elif (LZO_CC_TURBOC && (__TURBOC__ == 0x0295))
+# define LZO_COMPILE_TIME_ASSERT(e) switch(0) case 1:case !(e):break;
+# else
+# define LZO_COMPILE_TIME_ASSERT(e) {typedef int __LZO_CTA_NAME(lzo_cta_t__)[1-2*!(e)];}
+# endif
+#endif
+LZO_COMPILE_TIME_ASSERT_HEADER(1 == 1)
+#if defined(__cplusplus)
+extern "C" { LZO_COMPILE_TIME_ASSERT_HEADER(2 == 2) }
+#endif
+LZO_COMPILE_TIME_ASSERT_HEADER(3 == 3)
+#if (LZO_ARCH_I086 || LZO_ARCH_I386) && (LZO_OS_DOS16 || LZO_OS_DOS32 || LZO_OS_OS2 || LZO_OS_OS216 || LZO_OS_WIN16 || LZO_OS_WIN32 || LZO_OS_WIN64)
+# if (LZO_CC_GNUC || LZO_CC_HIGHC || LZO_CC_NDPC || LZO_CC_PACIFICC)
+# elif (LZO_CC_DMC || LZO_CC_SYMANTECC || LZO_CC_ZORTECHC)
+# define __lzo_cdecl __cdecl
+# define __lzo_cdecl_atexit /*empty*/
+# define __lzo_cdecl_main __cdecl
+# if (LZO_OS_OS2 && (LZO_CC_DMC || LZO_CC_SYMANTECC))
+# define __lzo_cdecl_qsort __pascal
+# elif (LZO_OS_OS2 && (LZO_CC_ZORTECHC))
+# define __lzo_cdecl_qsort _stdcall
+# else
+# define __lzo_cdecl_qsort __cdecl
+# endif
+# elif (LZO_CC_WATCOMC)
+# define __lzo_cdecl __cdecl
+# else
+# define __lzo_cdecl __cdecl
+# define __lzo_cdecl_atexit __cdecl
+# define __lzo_cdecl_main __cdecl
+# define __lzo_cdecl_qsort __cdecl
+# endif
+# if (LZO_CC_GNUC || LZO_CC_HIGHC || LZO_CC_NDPC || LZO_CC_PACIFICC || LZO_CC_WATCOMC)
+# elif (LZO_OS_OS2 && (LZO_CC_DMC || LZO_CC_SYMANTECC))
+# define __lzo_cdecl_sighandler __pascal
+# elif (LZO_OS_OS2 && (LZO_CC_ZORTECHC))
+# define __lzo_cdecl_sighandler _stdcall
+# elif (LZO_CC_MSC && (_MSC_VER >= 1400)) && defined(_M_CEE_PURE)
+# define __lzo_cdecl_sighandler __clrcall
+# elif (LZO_CC_MSC && (_MSC_VER >= 600 && _MSC_VER < 700))
+# if defined(_DLL)
+# define __lzo_cdecl_sighandler _far _cdecl _loadds
+# elif defined(_MT)
+# define __lzo_cdecl_sighandler _far _cdecl
+# else
+# define __lzo_cdecl_sighandler _cdecl
+# endif
+# else
+# define __lzo_cdecl_sighandler __cdecl
+# endif
+#elif (LZO_ARCH_I386) && (LZO_CC_WATCOMC)
+# define __lzo_cdecl __cdecl
+#elif (LZO_ARCH_M68K && LZO_OS_TOS && (LZO_CC_PUREC || LZO_CC_TURBOC))
+# define __lzo_cdecl cdecl
+#endif
+#if !defined(__lzo_cdecl)
+# define __lzo_cdecl /*empty*/
+#endif
+#if !defined(__lzo_cdecl_atexit)
+# define __lzo_cdecl_atexit /*empty*/
+#endif
+#if !defined(__lzo_cdecl_main)
+# define __lzo_cdecl_main /*empty*/
+#endif
+#if !defined(__lzo_cdecl_qsort)
+# define __lzo_cdecl_qsort /*empty*/
+#endif
+#if !defined(__lzo_cdecl_sighandler)
+# define __lzo_cdecl_sighandler /*empty*/
+#endif
+#if !defined(__lzo_cdecl_va)
+# define __lzo_cdecl_va __lzo_cdecl
+#endif
+#if !(LZO_CFG_NO_WINDOWS_H)
+#if !defined(LZO_HAVE_WINDOWS_H)
+#if (LZO_OS_CYGWIN || (LZO_OS_EMX && defined(__RSXNT__)) || LZO_OS_WIN32 || LZO_OS_WIN64)
+# if (LZO_CC_WATCOMC && (__WATCOMC__ < 1000))
+# elif (LZO_OS_WIN32 && LZO_CC_GNUC) && defined(__PW32__)
+# elif ((LZO_OS_CYGWIN || defined(__MINGW32__)) && (LZO_CC_GNUC && (LZO_CC_GNUC < 0x025f00ul)))
+# else
+# define LZO_HAVE_WINDOWS_H 1
+# endif
+#endif
+#endif
+#endif
+#ifndef LZO_SIZEOF_SHORT
#if defined(SIZEOF_SHORT)
# define LZO_SIZEOF_SHORT (SIZEOF_SHORT)
+#elif defined(__SIZEOF_SHORT__)
+# define LZO_SIZEOF_SHORT (__SIZEOF_SHORT__)
+#endif
#endif
+#ifndef LZO_SIZEOF_INT
#if defined(SIZEOF_INT)
# define LZO_SIZEOF_INT (SIZEOF_INT)
+#elif defined(__SIZEOF_INT__)
+# define LZO_SIZEOF_INT (__SIZEOF_INT__)
#endif
+#endif
+#ifndef LZO_SIZEOF_LONG
#if defined(SIZEOF_LONG)
# define LZO_SIZEOF_LONG (SIZEOF_LONG)
+#elif defined(__SIZEOF_LONG__)
+# define LZO_SIZEOF_LONG (__SIZEOF_LONG__)
+#endif
#endif
+#ifndef LZO_SIZEOF_LONG_LONG
#if defined(SIZEOF_LONG_LONG)
# define LZO_SIZEOF_LONG_LONG (SIZEOF_LONG_LONG)
+#elif defined(__SIZEOF_LONG_LONG__)
+# define LZO_SIZEOF_LONG_LONG (__SIZEOF_LONG_LONG__)
+#endif
#endif
+#ifndef LZO_SIZEOF___INT16
#if defined(SIZEOF___INT16)
# define LZO_SIZEOF___INT16 (SIZEOF___INT16)
#endif
+#endif
+#ifndef LZO_SIZEOF___INT32
#if defined(SIZEOF___INT32)
# define LZO_SIZEOF___INT32 (SIZEOF___INT32)
#endif
+#endif
+#ifndef LZO_SIZEOF___INT64
#if defined(SIZEOF___INT64)
# define LZO_SIZEOF___INT64 (SIZEOF___INT64)
#endif
+#endif
+#ifndef LZO_SIZEOF_VOID_P
#if defined(SIZEOF_VOID_P)
# define LZO_SIZEOF_VOID_P (SIZEOF_VOID_P)
+#elif defined(__SIZEOF_POINTER__)
+# define LZO_SIZEOF_VOID_P (__SIZEOF_POINTER__)
#endif
+#endif
+#ifndef LZO_SIZEOF_SIZE_T
#if defined(SIZEOF_SIZE_T)
# define LZO_SIZEOF_SIZE_T (SIZEOF_SIZE_T)
+#elif defined(__SIZEOF_SIZE_T__)
+# define LZO_SIZEOF_SIZE_T (__SIZEOF_SIZE_T__)
+#endif
#endif
+#ifndef LZO_SIZEOF_PTRDIFF_T
#if defined(SIZEOF_PTRDIFF_T)
# define LZO_SIZEOF_PTRDIFF_T (SIZEOF_PTRDIFF_T)
+#elif defined(__SIZEOF_PTRDIFF_T__)
+# define LZO_SIZEOF_PTRDIFF_T (__SIZEOF_PTRDIFF_T__)
+#endif
#endif
#define __LZO_LSR(x,b) (((x)+0ul) >> (b))
#if !defined(LZO_SIZEOF_SHORT)
@@ -1080,6 +2060,7 @@ extern "C" {
# error "LZO_SIZEOF_SHORT"
# endif
#endif
+LZO_COMPILE_TIME_ASSERT_HEADER(LZO_SIZEOF_SHORT == sizeof(short))
#if !defined(LZO_SIZEOF_INT)
# if (LZO_ARCH_CRAY_PVP)
# define LZO_SIZEOF_INT 8
@@ -1101,6 +2082,7 @@ extern "C" {
# error "LZO_SIZEOF_INT"
# endif
#endif
+LZO_COMPILE_TIME_ASSERT_HEADER(LZO_SIZEOF_INT == sizeof(int))
#if !defined(LZO_SIZEOF_LONG)
# if (ULONG_MAX == LZO_0xffffffffL)
# define LZO_SIZEOF_LONG 4
@@ -1110,6 +2092,8 @@ extern "C" {
# define LZO_SIZEOF_LONG 2
# elif (__LZO_LSR(ULONG_MAX,31) == 1)
# define LZO_SIZEOF_LONG 4
+# elif (__LZO_LSR(ULONG_MAX,39) == 1)
+# define LZO_SIZEOF_LONG 5
# elif (__LZO_LSR(ULONG_MAX,63) == 1)
# define LZO_SIZEOF_LONG 8
# elif (__LZO_LSR(ULONG_MAX,127) == 1)
@@ -1118,11 +2102,12 @@ extern "C" {
# error "LZO_SIZEOF_LONG"
# endif
#endif
+LZO_COMPILE_TIME_ASSERT_HEADER(LZO_SIZEOF_LONG == sizeof(long))
#if !defined(LZO_SIZEOF_LONG_LONG) && !defined(LZO_SIZEOF___INT64)
#if (LZO_SIZEOF_LONG > 0 && LZO_SIZEOF_LONG < 8)
# if defined(__LONG_MAX__) && defined(__LONG_LONG_MAX__)
# if (LZO_CC_GNUC >= 0x030300ul)
-# if ((__LONG_MAX__)+0 == (__LONG_LONG_MAX__)+0)
+# if ((__LONG_MAX__-0) == (__LONG_LONG_MAX__-0))
# define LZO_SIZEOF_LONG_LONG LZO_SIZEOF_LONG
# elif (__LZO_LSR(__LONG_LONG_MAX__,30) == 1)
# define LZO_SIZEOF_LONG_LONG 4
@@ -1136,7 +2121,7 @@ extern "C" {
#if (LZO_ARCH_I086 && LZO_CC_DMC)
#elif (LZO_CC_CILLY) && defined(__GNUC__)
# define LZO_SIZEOF_LONG_LONG 8
-#elif (LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE)
+#elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE)
# define LZO_SIZEOF_LONG_LONG 8
#elif ((LZO_OS_WIN32 || LZO_OS_WIN64 || defined(_WIN32)) && LZO_CC_MSC && (_MSC_VER >= 1400))
# define LZO_SIZEOF_LONG_LONG 8
@@ -1158,11 +2143,13 @@ extern "C" {
# define LZO_SIZEOF___INT64 8
#elif (LZO_ARCH_I386 && (LZO_CC_WATCOMC && (__WATCOMC__ >= 1100)))
# define LZO_SIZEOF___INT64 8
-#elif (LZO_CC_WATCOMC && defined(_INTEGRAL_MAX_BITS) && (_INTEGRAL_MAX_BITS == 64))
+#elif (LZO_CC_GHS && defined(__LLONG_BIT) && ((__LLONG_BIT-0) == 64))
+# define LZO_SIZEOF_LONG_LONG 8
+#elif (LZO_CC_WATCOMC && defined(_INTEGRAL_MAX_BITS) && ((_INTEGRAL_MAX_BITS-0) == 64))
# define LZO_SIZEOF___INT64 8
#elif (LZO_OS_OS400 || defined(__OS400__)) && defined(__LLP64_IFC__)
# define LZO_SIZEOF_LONG_LONG 8
-#elif (defined(__vms) || defined(__VMS)) && (__INITIAL_POINTER_SIZE+0 == 64)
+#elif (defined(__vms) || defined(__VMS)) && ((__INITIAL_POINTER_SIZE-0) == 64)
# define LZO_SIZEOF_LONG_LONG 8
#elif (LZO_CC_SDCC) && (LZO_SIZEOF_INT == 2)
#elif 1 && defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
@@ -1175,87 +2162,127 @@ extern "C" {
# undef LZO_SIZEOF_LONG_LONG
# endif
#endif
-#if (LZO_CFG_NO_LONG_LONG) || defined(__NO_LONG_LONG)
+#if (LZO_CFG_NO_LONG_LONG)
+# undef LZO_SIZEOF_LONG_LONG
+#elif defined(__NO_LONG_LONG)
+# undef LZO_SIZEOF_LONG_LONG
+#elif defined(_NO_LONGLONG)
# undef LZO_SIZEOF_LONG_LONG
#endif
-#if !defined(LZO_SIZEOF_VOID_P)
-#if (LZO_ARCH_I086)
-# define __LZO_WORDSIZE 2
-# if (LZO_MM_TINY || LZO_MM_SMALL || LZO_MM_MEDIUM)
-# define LZO_SIZEOF_VOID_P 2
-# elif (LZO_MM_COMPACT || LZO_MM_LARGE || LZO_MM_HUGE)
-# define LZO_SIZEOF_VOID_P 4
+#if !defined(LZO_WORDSIZE)
+#if (LZO_ARCH_ALPHA)
+# define LZO_WORDSIZE 8
+#elif (LZO_ARCH_AMD64)
+# define LZO_WORDSIZE 8
+#elif (LZO_ARCH_AVR)
+# define LZO_WORDSIZE 1
+#elif (LZO_ARCH_H8300)
+# if defined(__NORMAL_MODE__)
+# define LZO_WORDSIZE 4
+# elif defined(__H8300H__) || defined(__H8300S__) || defined(__H8300SX__)
+# define LZO_WORDSIZE 4
# else
-# error "LZO_MM"
+# define LZO_WORDSIZE 2
# endif
-#elif (LZO_ARCH_AVR || LZO_ARCH_Z80)
-# define __LZO_WORDSIZE 1
+#elif (LZO_ARCH_I086)
+# define LZO_WORDSIZE 2
+#elif (LZO_ARCH_IA64)
+# define LZO_WORDSIZE 8
+#elif (LZO_ARCH_M16C)
+# define LZO_WORDSIZE 2
+#elif (LZO_ARCH_SPU)
+# define LZO_WORDSIZE 4
+#elif (LZO_ARCH_Z80)
+# define LZO_WORDSIZE 1
+#elif (LZO_SIZEOF_LONG == 8) && ((defined(__mips__) && defined(__R5900__)) || defined(__MIPS_PSX2__))
+# define LZO_WORDSIZE 8
+#elif (LZO_OS_OS400 || defined(__OS400__))
+# define LZO_WORDSIZE 8
+#elif (defined(__vms) || defined(__VMS)) && (__INITIAL_POINTER_SIZE+0 == 64)
+# define LZO_WORDSIZE 8
+#endif
+#endif
+#if !defined(LZO_SIZEOF_VOID_P)
+#if defined(__ILP32__) || defined(__ILP32) || defined(_ILP32)
+LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(int) == 4)
+LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(long) == 4)
+# define LZO_SIZEOF_VOID_P 4
+#elif defined(__ILP64__) || defined(__ILP64) || defined(_ILP64)
+LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(int) == 8)
+LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(long) == 8)
+# define LZO_SIZEOF_VOID_P 8
+#elif defined(__LLP64__) || defined(__LLP64) || defined(_LLP64) || defined(_WIN64)
+LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(long) == 4)
+# define LZO_SIZEOF_VOID_P 8
+#elif defined(__LP64__) || defined(__LP64) || defined(_LP64)
+LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(long) == 8)
+# define LZO_SIZEOF_VOID_P 8
+#elif (LZO_ARCH_AVR)
# define LZO_SIZEOF_VOID_P 2
#elif (LZO_ARCH_C166 || LZO_ARCH_MCS51 || LZO_ARCH_MCS251 || LZO_ARCH_MSP430)
# define LZO_SIZEOF_VOID_P 2
#elif (LZO_ARCH_H8300)
# if defined(__NORMAL_MODE__)
-# define __LZO_WORDSIZE 4
# define LZO_SIZEOF_VOID_P 2
# elif defined(__H8300H__) || defined(__H8300S__) || defined(__H8300SX__)
-# define __LZO_WORDSIZE 4
# define LZO_SIZEOF_VOID_P 4
# else
-# define __LZO_WORDSIZE 2
# define LZO_SIZEOF_VOID_P 2
# endif
# if (LZO_CC_GNUC && (LZO_CC_GNUC < 0x040000ul)) && (LZO_SIZEOF_INT == 4)
# define LZO_SIZEOF_SIZE_T LZO_SIZEOF_INT
# define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_INT
# endif
+#elif (LZO_ARCH_I086)
+# if (LZO_MM_TINY || LZO_MM_SMALL || LZO_MM_MEDIUM)
+# define LZO_SIZEOF_VOID_P 2
+# elif (LZO_MM_COMPACT || LZO_MM_LARGE || LZO_MM_HUGE)
+# define LZO_SIZEOF_VOID_P 4
+# else
+# error "invalid LZO_ARCH_I086 memory model"
+# endif
#elif (LZO_ARCH_M16C)
-# define __LZO_WORDSIZE 2
# if defined(__m32c_cpu__) || defined(__m32cm_cpu__)
# define LZO_SIZEOF_VOID_P 4
# else
# define LZO_SIZEOF_VOID_P 2
# endif
+#elif (LZO_ARCH_SPU)
+# define LZO_SIZEOF_VOID_P 4
+#elif (LZO_ARCH_Z80)
+# define LZO_SIZEOF_VOID_P 2
#elif (LZO_SIZEOF_LONG == 8) && ((defined(__mips__) && defined(__R5900__)) || defined(__MIPS_PSX2__))
-# define __LZO_WORDSIZE 8
# define LZO_SIZEOF_VOID_P 4
-#elif defined(__LLP64__) || defined(__LLP64) || defined(_LLP64) || defined(_WIN64)
-# define __LZO_WORDSIZE 8
-# define LZO_SIZEOF_VOID_P 8
-#elif (LZO_OS_OS400 || defined(__OS400__)) && defined(__LLP64_IFC__)
-# define LZO_SIZEOF_VOID_P LZO_SIZEOF_LONG
-# define LZO_SIZEOF_SIZE_T LZO_SIZEOF_LONG
-# define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_LONG
#elif (LZO_OS_OS400 || defined(__OS400__))
-# define __LZO_WORDSIZE LZO_SIZEOF_LONG
-# define LZO_SIZEOF_VOID_P 16
-# define LZO_SIZEOF_SIZE_T LZO_SIZEOF_LONG
-# define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_LONG
+# if defined(__LLP64_IFC__)
+# define LZO_SIZEOF_VOID_P 8
+# define LZO_SIZEOF_SIZE_T LZO_SIZEOF_LONG
+# define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_LONG
+# else
+# define LZO_SIZEOF_VOID_P 16
+# define LZO_SIZEOF_SIZE_T LZO_SIZEOF_LONG
+# define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_LONG
+# endif
#elif (defined(__vms) || defined(__VMS)) && (__INITIAL_POINTER_SIZE+0 == 64)
# define LZO_SIZEOF_VOID_P 8
# define LZO_SIZEOF_SIZE_T LZO_SIZEOF_LONG
# define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_LONG
-#elif (LZO_ARCH_SPU)
-# if 0
-# define __LZO_WORDSIZE 16
-# endif
-# define LZO_SIZEOF_VOID_P 4
-#else
-# define LZO_SIZEOF_VOID_P LZO_SIZEOF_LONG
#endif
#endif
-#if !defined(LZO_WORDSIZE)
-# if defined(__LZO_WORDSIZE)
-# define LZO_WORDSIZE __LZO_WORDSIZE
-# else
-# define LZO_WORDSIZE LZO_SIZEOF_VOID_P
-# endif
+#if !defined(LZO_SIZEOF_VOID_P)
+# define LZO_SIZEOF_VOID_P LZO_SIZEOF_LONG
#endif
+LZO_COMPILE_TIME_ASSERT_HEADER(LZO_SIZEOF_VOID_P == sizeof(void *))
#if !defined(LZO_SIZEOF_SIZE_T)
#if (LZO_ARCH_I086 || LZO_ARCH_M16C)
# define LZO_SIZEOF_SIZE_T 2
-#else
+#endif
+#endif
+#if !defined(LZO_SIZEOF_SIZE_T)
# define LZO_SIZEOF_SIZE_T LZO_SIZEOF_VOID_P
#endif
+#if defined(offsetof)
+LZO_COMPILE_TIME_ASSERT_HEADER(LZO_SIZEOF_SIZE_T == sizeof(size_t))
#endif
#if !defined(LZO_SIZEOF_PTRDIFF_T)
#if (LZO_ARCH_I086)
@@ -1268,11 +2295,18 @@ extern "C" {
# define LZO_SIZEOF_PTRDIFF_T 2
# endif
# else
-# error "LZO_MM"
+# error "invalid LZO_ARCH_I086 memory model"
# endif
-#else
+#endif
+#endif
+#if !defined(LZO_SIZEOF_PTRDIFF_T)
# define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_SIZE_T
#endif
+#if defined(offsetof)
+LZO_COMPILE_TIME_ASSERT_HEADER(LZO_SIZEOF_PTRDIFF_T == sizeof(ptrdiff_t))
+#endif
+#if !defined(LZO_WORDSIZE)
+# define LZO_WORDSIZE LZO_SIZEOF_VOID_P
#endif
#if (LZO_ABI_NEUTRAL_ENDIAN)
# undef LZO_ABI_BIG_ENDIAN
@@ -1284,7 +2318,7 @@ extern "C" {
# define LZO_ABI_LITTLE_ENDIAN 1
#elif (LZO_ARCH_ALPHA || LZO_ARCH_AMD64 || LZO_ARCH_BLACKFIN || LZO_ARCH_CRIS || LZO_ARCH_I086 || LZO_ARCH_I386 || LZO_ARCH_MSP430)
# define LZO_ABI_LITTLE_ENDIAN 1
-#elif (LZO_ARCH_AVR32 || LZO_ARCH_M68K || LZO_ARCH_S390)
+#elif (LZO_ARCH_AVR32 || LZO_ARCH_M68K || LZO_ARCH_S390 || LZO_ARCH_SPU)
# define LZO_ABI_BIG_ENDIAN 1
#elif 1 && defined(__IAR_SYSTEMS_ICC__) && defined(__LITTLE_ENDIAN__)
# if (__LITTLE_ENDIAN__ == 1)
@@ -1300,6 +2334,19 @@ extern "C" {
# define LZO_ABI_BIG_ENDIAN 1
#elif 1 && (LZO_ARCH_ARM) && defined(__ARMEL__) && !defined(__ARMEB__)
# define LZO_ABI_LITTLE_ENDIAN 1
+#elif 1 && (LZO_ARCH_ARM && LZO_CC_ARMCC_ARMCC)
+# if defined(__BIG_ENDIAN) && defined(__LITTLE_ENDIAN)
+# error "unexpected configuration - check your compiler defines"
+# elif defined(__BIG_ENDIAN)
+# define LZO_ABI_BIG_ENDIAN 1
+# else
+# define LZO_ABI_LITTLE_ENDIAN 1
+# endif
+# define LZO_ABI_LITTLE_ENDIAN 1
+#elif 1 && (LZO_ARCH_ARM64) && defined(__AARCH64EB__) && !defined(__AARCH64EL__)
+# define LZO_ABI_BIG_ENDIAN 1
+#elif 1 && (LZO_ARCH_ARM64) && defined(__AARCH64EL__) && !defined(__AARCH64EB__)
+# define LZO_ABI_LITTLE_ENDIAN 1
#elif 1 && (LZO_ARCH_MIPS) && defined(__MIPSEB__) && !defined(__MIPSEL__)
# define LZO_ABI_BIG_ENDIAN 1
#elif 1 && (LZO_ARCH_MIPS) && defined(__MIPSEL__) && !defined(__MIPSEB__)
@@ -1307,7 +2354,7 @@ extern "C" {
#endif
#endif
#if (LZO_ABI_BIG_ENDIAN) && (LZO_ABI_LITTLE_ENDIAN)
-# error "this should not happen"
+# error "unexpected configuration - check your compiler defines"
#endif
#if (LZO_ABI_BIG_ENDIAN)
# define LZO_INFO_ABI_ENDIAN "be"
@@ -1322,6 +2369,9 @@ extern "C" {
#elif (LZO_SIZEOF_INT == 2 && LZO_SIZEOF_LONG == 2 && LZO_SIZEOF_VOID_P == 2)
# define LZO_ABI_ILP16 1
# define LZO_INFO_ABI_PM "ilp16"
+#elif (LZO_SIZEOF_INT == 2 && LZO_SIZEOF_LONG == 4 && LZO_SIZEOF_VOID_P == 4)
+# define LZO_ABI_LP32 1
+# define LZO_INFO_ABI_PM "lp32"
#elif (LZO_SIZEOF_INT == 4 && LZO_SIZEOF_LONG == 4 && LZO_SIZEOF_VOID_P == 4)
# define LZO_ABI_ILP32 1
# define LZO_INFO_ABI_PM "ilp32"
@@ -1338,7 +2388,8 @@ extern "C" {
# define LZO_ABI_IP32L64 1
# define LZO_INFO_ABI_PM "ip32l64"
#endif
-#if !defined(__LZO_LIBC_OVERRIDE)
+#if 0
+#elif !defined(__LZO_LIBC_OVERRIDE)
#if (LZO_LIBC_NAKED)
# define LZO_INFO_LIBC "naked"
#elif (LZO_LIBC_FREESTANDING)
@@ -1349,6 +2400,9 @@ extern "C" {
# define LZO_INFO_LIBC "isoc90"
#elif (LZO_LIBC_ISOC99)
# define LZO_INFO_LIBC "isoc99"
+#elif (LZO_CC_ARMCC_ARMCC) && defined(__ARMCLIB_VERSION)
+# define LZO_LIBC_ISOC90 1
+# define LZO_INFO_LIBC "isoc90"
#elif defined(__dietlibc__)
# define LZO_LIBC_DIETLIBC 1
# define LZO_INFO_LIBC "dietlibc"
@@ -1357,13 +2411,13 @@ extern "C" {
# define LZO_INFO_LIBC "newlib"
#elif defined(__UCLIBC__) && defined(__UCLIBC_MAJOR__) && defined(__UCLIBC_MINOR__)
# if defined(__UCLIBC_SUBLEVEL__)
-# define LZO_LIBC_UCLIBC (__UCLIBC_MAJOR__ * 0x10000L + __UCLIBC_MINOR__ * 0x100 + __UCLIBC_SUBLEVEL__)
+# define LZO_LIBC_UCLIBC (__UCLIBC_MAJOR__ * 0x10000L + (__UCLIBC_MINOR__-0) * 0x100 + (__UCLIBC_SUBLEVEL__-0))
# else
# define LZO_LIBC_UCLIBC 0x00090bL
# endif
-# define LZO_INFO_LIBC "uclibc"
+# define LZO_INFO_LIBC "uc" "libc"
#elif defined(__GLIBC__) && defined(__GLIBC_MINOR__)
-# define LZO_LIBC_GLIBC (__GLIBC__ * 0x10000L + __GLIBC_MINOR__ * 0x100)
+# define LZO_LIBC_GLIBC (__GLIBC__ * 0x10000L + (__GLIBC_MINOR__-0) * 0x100)
# define LZO_INFO_LIBC "glibc"
#elif (LZO_CC_MWERKS) && defined(__MSL__)
# define LZO_LIBC_MSL __MSL__
@@ -1376,424 +2430,160 @@ extern "C" {
# define LZO_INFO_LIBC "default"
#endif
#endif
-#if !defined(__lzo_gnuc_extension__)
-#if (LZO_CC_GNUC >= 0x020800ul)
-# define __lzo_gnuc_extension__ __extension__
-#elif (LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE)
-# define __lzo_gnuc_extension__ __extension__
-#else
-# define __lzo_gnuc_extension__ /*empty*/
-#endif
-#endif
-#if !defined(__lzo_ua_volatile)
-# define __lzo_ua_volatile volatile
-#endif
-#if !defined(__lzo_alignof)
-#if (LZO_CC_CILLY || LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE || LZO_CC_PGI)
-# define __lzo_alignof(e) __alignof__(e)
-#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 700))
-# define __lzo_alignof(e) __alignof__(e)
-#elif (LZO_CC_MSC && (_MSC_VER >= 1300))
-# define __lzo_alignof(e) __alignof(e)
-#elif (LZO_CC_SUNPROC && (LZO_CC_SUNPROC >= 0x5100))
-# define __lzo_alignof(e) __alignof__(e)
-#endif
-#endif
-#if defined(__lzo_alignof)
-# define __lzo_HAVE_alignof 1
-#endif
-#if !defined(__lzo_constructor)
-#if (LZO_CC_GNUC >= 0x030400ul)
-# define __lzo_constructor __attribute__((__constructor__,__used__))
-#elif (LZO_CC_GNUC >= 0x020700ul)
-# define __lzo_constructor __attribute__((__constructor__))
-#elif (LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE)
-# define __lzo_constructor __attribute__((__constructor__))
-#endif
-#endif
-#if defined(__lzo_constructor)
-# define __lzo_HAVE_constructor 1
-#endif
-#if !defined(__lzo_destructor)
-#if (LZO_CC_GNUC >= 0x030400ul)
-# define __lzo_destructor __attribute__((__destructor__,__used__))
-#elif (LZO_CC_GNUC >= 0x020700ul)
-# define __lzo_destructor __attribute__((__destructor__))
-#elif (LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE)
-# define __lzo_destructor __attribute__((__destructor__))
-#endif
-#endif
-#if defined(__lzo_destructor)
-# define __lzo_HAVE_destructor 1
-#endif
-#if (__lzo_HAVE_destructor) && !(__lzo_HAVE_constructor)
-# error "this should not happen"
-#endif
-#if !defined(__lzo_inline)
-#if (LZO_CC_TURBOC && (__TURBOC__ <= 0x0295))
-#elif defined(__cplusplus)
-# define __lzo_inline inline
-#elif (LZO_CC_BORLANDC && (__BORLANDC__ >= 0x0550))
-# define __lzo_inline __inline
-#elif (LZO_CC_CILLY || LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE || LZO_CC_PGI)
-# define __lzo_inline __inline__
-#elif (LZO_CC_DMC)
-# define __lzo_inline __inline
-#elif (LZO_CC_INTELC)
-# define __lzo_inline __inline
-#elif (LZO_CC_MWERKS && (__MWERKS__ >= 0x2405))
-# define __lzo_inline __inline
-#elif (LZO_CC_MSC && (_MSC_VER >= 900))
-# define __lzo_inline __inline
-#elif (LZO_CC_SUNPROC && (LZO_CC_SUNPROC >= 0x5100))
-# define __lzo_inline __inline__
-#elif defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
-# define __lzo_inline inline
-#endif
+#if (LZO_ARCH_I386 && (LZO_OS_DOS32 || LZO_OS_WIN32) && (LZO_CC_DMC || LZO_CC_INTELC || LZO_CC_MSC || LZO_CC_PELLESC))
+# define LZO_ASM_SYNTAX_MSC 1
+#elif (LZO_OS_WIN64 && (LZO_CC_DMC || LZO_CC_INTELC || LZO_CC_MSC || LZO_CC_PELLESC))
+#elif (LZO_ARCH_I386 && LZO_CC_GNUC && (LZO_CC_GNUC == 0x011f00ul))
+#elif (LZO_ARCH_I386 && (LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_INTELC || LZO_CC_PATHSCALE))
+# define LZO_ASM_SYNTAX_GNUC 1
+#elif (LZO_ARCH_AMD64 && (LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_INTELC || LZO_CC_PATHSCALE))
+# define LZO_ASM_SYNTAX_GNUC 1
+#elif (LZO_CC_GNUC)
+# define LZO_ASM_SYNTAX_GNUC 1
#endif
-#if defined(__lzo_inline)
-# define __lzo_HAVE_inline 1
+#if (LZO_ASM_SYNTAX_GNUC)
+#if (LZO_ARCH_I386 && LZO_CC_GNUC && (LZO_CC_GNUC < 0x020000ul))
+# define __LZO_ASM_CLOBBER "ax"
+# define __LZO_ASM_CLOBBER_LIST_CC /*empty*/
+# define __LZO_ASM_CLOBBER_LIST_CC_MEMORY /*empty*/
+# define __LZO_ASM_CLOBBER_LIST_EMPTY /*empty*/
+#elif (LZO_CC_INTELC && (__INTEL_COMPILER < 1000))
+# define __LZO_ASM_CLOBBER "memory"
+# define __LZO_ASM_CLOBBER_LIST_CC /*empty*/
+# define __LZO_ASM_CLOBBER_LIST_CC_MEMORY : "memory"
+# define __LZO_ASM_CLOBBER_LIST_EMPTY /*empty*/
#else
-# define __lzo_inline /*empty*/
-#endif
-#if !defined(__lzo_forceinline)
-#if (LZO_CC_GNUC >= 0x030200ul)
-# define __lzo_forceinline __inline__ __attribute__((__always_inline__))
-#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 450) && LZO_CC_SYNTAX_MSC)
-# define __lzo_forceinline __forceinline
-#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 800) && LZO_CC_SYNTAX_GNUC)
-# define __lzo_forceinline __inline__ __attribute__((__always_inline__))
-#elif (LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE)
-# define __lzo_forceinline __inline__ __attribute__((__always_inline__))
-#elif (LZO_CC_MSC && (_MSC_VER >= 1200))
-# define __lzo_forceinline __forceinline
-#elif (LZO_CC_SUNPROC && (LZO_CC_SUNPROC >= 0x5100))
-# define __lzo_forceinline __inline__ __attribute__((__always_inline__))
+# define __LZO_ASM_CLOBBER "cc", "memory"
+# define __LZO_ASM_CLOBBER_LIST_CC : "cc"
+# define __LZO_ASM_CLOBBER_LIST_CC_MEMORY : "cc", "memory"
+# define __LZO_ASM_CLOBBER_LIST_EMPTY /*empty*/
#endif
#endif
-#if defined(__lzo_forceinline)
-# define __lzo_HAVE_forceinline 1
-#else
-# define __lzo_forceinline /*empty*/
-#endif
-#if !defined(__lzo_noinline)
-#if 1 && (LZO_ARCH_I386) && (LZO_CC_GNUC >= 0x040000ul) && (LZO_CC_GNUC < 0x040003ul)
-# define __lzo_noinline __attribute__((__noinline__,__used__))
-#elif (LZO_CC_GNUC >= 0x030200ul)
-# define __lzo_noinline __attribute__((__noinline__))
-#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 600) && LZO_CC_SYNTAX_MSC)
-# define __lzo_noinline __declspec(noinline)
-#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 800) && LZO_CC_SYNTAX_GNUC)
-# define __lzo_noinline __attribute__((__noinline__))
-#elif (LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE)
-# define __lzo_noinline __attribute__((__noinline__))
-#elif (LZO_CC_MSC && (_MSC_VER >= 1300))
-# define __lzo_noinline __declspec(noinline)
-#elif (LZO_CC_MWERKS && (__MWERKS__ >= 0x3200) && (LZO_OS_WIN32 || LZO_OS_WIN64))
-# if defined(__cplusplus)
-# else
-# define __lzo_noinline __declspec(noinline)
+#if (LZO_ARCH_ALPHA)
+# define LZO_OPT_AVOID_UINT_INDEX 1
+#elif (LZO_ARCH_AMD64)
+# define LZO_OPT_AVOID_INT_INDEX 1
+# define LZO_OPT_AVOID_UINT_INDEX 1
+# ifndef LZO_OPT_UNALIGNED16
+# define LZO_OPT_UNALIGNED16 1
# endif
-#elif (LZO_CC_SUNPROC && (LZO_CC_SUNPROC >= 0x5100))
-# define __lzo_noinline __attribute__((__noinline__))
-#endif
-#endif
-#if defined(__lzo_noinline)
-# define __lzo_HAVE_noinline 1
-#else
-# define __lzo_noinline /*empty*/
-#endif
-#if (__lzo_HAVE_forceinline || __lzo_HAVE_noinline) && !(__lzo_HAVE_inline)
-# error "this should not happen"
-#endif
-#if !defined(__lzo_noreturn)
-#if (LZO_CC_GNUC >= 0x020700ul)
-# define __lzo_noreturn __attribute__((__noreturn__))
-#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 450) && LZO_CC_SYNTAX_MSC)
-# define __lzo_noreturn __declspec(noreturn)
-#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 600) && LZO_CC_SYNTAX_GNUC)
-# define __lzo_noreturn __attribute__((__noreturn__))
-#elif (LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE)
-# define __lzo_noreturn __attribute__((__noreturn__))
-#elif (LZO_CC_MSC && (_MSC_VER >= 1200))
-# define __lzo_noreturn __declspec(noreturn)
-#endif
-#endif
-#if defined(__lzo_noreturn)
-# define __lzo_HAVE_noreturn 1
-#else
-# define __lzo_noreturn /*empty*/
-#endif
-#if !defined(__lzo_nothrow)
-#if (LZO_CC_GNUC >= 0x030300ul)
-# define __lzo_nothrow __attribute__((__nothrow__))
-#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 450) && LZO_CC_SYNTAX_MSC) && defined(__cplusplus)
-# define __lzo_nothrow __declspec(nothrow)
-#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 900) && LZO_CC_SYNTAX_GNUC)
-# define __lzo_nothrow __attribute__((__nothrow__))
-#elif (LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE)
-# define __lzo_nothrow __attribute__((__nothrow__))
-#elif (LZO_CC_MSC && (_MSC_VER >= 1200)) && defined(__cplusplus)
-# define __lzo_nothrow __declspec(nothrow)
-#endif
-#endif
-#if defined(__lzo_nothrow)
-# define __lzo_HAVE_nothrow 1
-#else
-# define __lzo_nothrow /*empty*/
-#endif
-#if !defined(__lzo_restrict)
-#if (LZO_CC_GNUC >= 0x030400ul)
-# define __lzo_restrict __restrict__
-#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 600) && LZO_CC_SYNTAX_GNUC)
-# define __lzo_restrict __restrict__
-#elif (LZO_CC_CLANG || LZO_CC_LLVM)
-# define __lzo_restrict __restrict__
-#elif (LZO_CC_MSC && (_MSC_VER >= 1400))
-# define __lzo_restrict __restrict
-#endif
-#endif
-#if defined(__lzo_restrict)
-# define __lzo_HAVE_restrict 1
-#else
-# define __lzo_restrict /*empty*/
-#endif
-#if !defined(__lzo_likely) && !defined(__lzo_unlikely)
-#if (LZO_CC_GNUC >= 0x030200ul)
-# define __lzo_likely(e) (__builtin_expect(!!(e),1))
-# define __lzo_unlikely(e) (__builtin_expect(!!(e),0))
-#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 800))
-# define __lzo_likely(e) (__builtin_expect(!!(e),1))
-# define __lzo_unlikely(e) (__builtin_expect(!!(e),0))
-#elif (LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE)
-# define __lzo_likely(e) (__builtin_expect(!!(e),1))
-# define __lzo_unlikely(e) (__builtin_expect(!!(e),0))
-#endif
-#endif
-#if defined(__lzo_likely)
-# define __lzo_HAVE_likely 1
-#else
-# define __lzo_likely(e) (e)
-#endif
-#if defined(__lzo_unlikely)
-# define __lzo_HAVE_unlikely 1
-#else
-# define __lzo_unlikely(e) (e)
-#endif
-#if !defined(LZO_UNUSED)
-# if (LZO_CC_BORLANDC && (__BORLANDC__ >= 0x0600))
-# define LZO_UNUSED(var) ((void) &var)
-# elif (LZO_CC_BORLANDC || LZO_CC_HIGHC || LZO_CC_NDPC || LZO_CC_PELLESC || LZO_CC_TURBOC)
-# define LZO_UNUSED(var) if (&var) ; else
-# elif (LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE)
-# define LZO_UNUSED(var) ((void) var)
-# elif (LZO_CC_MSC && (_MSC_VER < 900))
-# define LZO_UNUSED(var) if (&var) ; else
-# elif (LZO_CC_KEILC)
-# define LZO_UNUSED(var) {extern int __lzo_unused[1-2*!(sizeof(var)>0)];}
-# elif (LZO_CC_PACIFICC)
-# define LZO_UNUSED(var) ((void) sizeof(var))
-# elif (LZO_CC_WATCOMC) && defined(__cplusplus)
-# define LZO_UNUSED(var) ((void) var)
-# else
-# define LZO_UNUSED(var) ((void) &var)
+# ifndef LZO_OPT_UNALIGNED32
+# define LZO_OPT_UNALIGNED32 1
# endif
-#endif
-#if !defined(LZO_UNUSED_FUNC)
-# if (LZO_CC_BORLANDC && (__BORLANDC__ >= 0x0600))
-# define LZO_UNUSED_FUNC(func) ((void) func)
-# elif (LZO_CC_BORLANDC || LZO_CC_NDPC || LZO_CC_TURBOC)
-# define LZO_UNUSED_FUNC(func) if (func) ; else
-# elif (LZO_CC_CLANG || LZO_CC_LLVM)
-# define LZO_UNUSED_FUNC(func) ((void) &func)
-# elif (LZO_CC_MSC && (_MSC_VER < 900))
-# define LZO_UNUSED_FUNC(func) if (func) ; else
-# elif (LZO_CC_MSC)
-# define LZO_UNUSED_FUNC(func) ((void) &func)
-# elif (LZO_CC_KEILC || LZO_CC_PELLESC)
-# define LZO_UNUSED_FUNC(func) {extern int __lzo_unused[1-2*!(sizeof((int)func)>0)];}
-# else
-# define LZO_UNUSED_FUNC(func) ((void) func)
+# ifndef LZO_OPT_UNALIGNED64
+# define LZO_OPT_UNALIGNED64 1
# endif
-#endif
-#if !defined(LZO_UNUSED_LABEL)
-# if (LZO_CC_WATCOMC) && defined(__cplusplus)
-# define LZO_UNUSED_LABEL(l) switch(0) case 1:goto l
-# elif (LZO_CC_CLANG || LZO_CC_INTELC || LZO_CC_WATCOMC)
-# define LZO_UNUSED_LABEL(l) if (0) goto l
-# else
-# define LZO_UNUSED_LABEL(l) switch(0) case 1:goto l
+#elif (LZO_ARCH_ARM)
+# if defined(__ARM_FEATURE_UNALIGNED)
+# ifndef LZO_OPT_UNALIGNED16
+# define LZO_OPT_UNALIGNED16 1
+# endif
+# ifndef LZO_OPT_UNALIGNED32
+# define LZO_OPT_UNALIGNED32 1
+# endif
+# elif defined(__TARGET_ARCH_ARM) && ((__TARGET_ARCH_ARM+0) >= 7)
+# ifndef LZO_OPT_UNALIGNED16
+# define LZO_OPT_UNALIGNED16 1
+# endif
+# ifndef LZO_OPT_UNALIGNED32
+# define LZO_OPT_UNALIGNED32 1
+# endif
+# elif defined(__TARGET_ARCH_ARM) && ((__TARGET_ARCH_ARM+0) >= 6) && !defined(__TARGET_PROFILE_M)
+# ifndef LZO_OPT_UNALIGNED16
+# define LZO_OPT_UNALIGNED16 1
+# endif
+# ifndef LZO_OPT_UNALIGNED32
+# define LZO_OPT_UNALIGNED32 1
+# endif
# endif
-#endif
-#if !defined(LZO_DEFINE_UNINITIALIZED_VAR)
-# if 0
-# define LZO_DEFINE_UNINITIALIZED_VAR(type,var,init) type var
-# elif 0 && (LZO_CC_GNUC)
-# define LZO_DEFINE_UNINITIALIZED_VAR(type,var,init) type var = var
-# else
-# define LZO_DEFINE_UNINITIALIZED_VAR(type,var,init) type var = init
+#elif (LZO_ARCH_ARM64)
+# ifndef LZO_OPT_UNALIGNED16
+# define LZO_OPT_UNALIGNED16 1
# endif
-#endif
-#if !defined(LZO_UNCONST_CAST)
-# if 0 && defined(__cplusplus)
-# define LZO_UNCONST_CAST(t,e) (const_cast<t> (e))
-# elif (LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE)
-# define LZO_UNCONST_CAST(t,e) ((t) ((void *) ((char *) ((lzo_uintptr_t) ((const void *) (e))))))
-# else
-# define LZO_UNCONST_CAST(t,e) ((t) ((void *) ((char *) ((const void *) (e)))))
+# ifndef LZO_OPT_UNALIGNED32
+# define LZO_OPT_UNALIGNED32 1
# endif
-#endif
-#if !defined(LZO_COMPILE_TIME_ASSERT_HEADER)
-# if (LZO_CC_AZTECC || LZO_CC_ZORTECHC)
-# define LZO_COMPILE_TIME_ASSERT_HEADER(e) extern int __lzo_cta[1-!(e)];
-# elif (LZO_CC_DMC || LZO_CC_SYMANTECC)
-# define LZO_COMPILE_TIME_ASSERT_HEADER(e) extern int __lzo_cta[1u-2*!(e)];
-# elif (LZO_CC_TURBOC && (__TURBOC__ == 0x0295))
-# define LZO_COMPILE_TIME_ASSERT_HEADER(e) extern int __lzo_cta[1-!(e)];
-# else
-# define LZO_COMPILE_TIME_ASSERT_HEADER(e) extern int __lzo_cta[1-2*!(e)];
+# ifndef LZO_OPT_UNALIGNED64
+# define LZO_OPT_UNALIGNED64 1
# endif
-#endif
-#if !defined(LZO_COMPILE_TIME_ASSERT)
-# if (LZO_CC_AZTECC)
-# define LZO_COMPILE_TIME_ASSERT(e) {typedef int __lzo_cta_t[1-!(e)];}
-# elif (LZO_CC_DMC || LZO_CC_PACIFICC || LZO_CC_SYMANTECC || LZO_CC_ZORTECHC)
-# define LZO_COMPILE_TIME_ASSERT(e) switch(0) case 1:case !(e):break;
-# elif (LZO_CC_MSC && (_MSC_VER < 900))
-# define LZO_COMPILE_TIME_ASSERT(e) switch(0) case 1:case !(e):break;
-# elif (LZO_CC_TURBOC && (__TURBOC__ == 0x0295))
-# define LZO_COMPILE_TIME_ASSERT(e) switch(0) case 1:case !(e):break;
-# else
-# define LZO_COMPILE_TIME_ASSERT(e) {typedef int __lzo_cta_t[1-2*!(e)];}
+#elif (LZO_ARCH_CRIS)
+# ifndef LZO_OPT_UNALIGNED16
+# define LZO_OPT_UNALIGNED16 1
# endif
-#endif
-#if (LZO_ARCH_I086 || LZO_ARCH_I386) && (LZO_OS_DOS16 || LZO_OS_DOS32 || LZO_OS_OS2 || LZO_OS_OS216 || LZO_OS_WIN16 || LZO_OS_WIN32 || LZO_OS_WIN64)
-# if (LZO_CC_GNUC || LZO_CC_HIGHC || LZO_CC_NDPC || LZO_CC_PACIFICC)
-# elif (LZO_CC_DMC || LZO_CC_SYMANTECC || LZO_CC_ZORTECHC)
-# define __lzo_cdecl __cdecl
-# define __lzo_cdecl_atexit /*empty*/
-# define __lzo_cdecl_main __cdecl
-# if (LZO_OS_OS2 && (LZO_CC_DMC || LZO_CC_SYMANTECC))
-# define __lzo_cdecl_qsort __pascal
-# elif (LZO_OS_OS2 && (LZO_CC_ZORTECHC))
-# define __lzo_cdecl_qsort _stdcall
-# else
-# define __lzo_cdecl_qsort __cdecl
-# endif
-# elif (LZO_CC_WATCOMC)
-# define __lzo_cdecl __cdecl
-# else
-# define __lzo_cdecl __cdecl
-# define __lzo_cdecl_atexit __cdecl
-# define __lzo_cdecl_main __cdecl
-# define __lzo_cdecl_qsort __cdecl
+# ifndef LZO_OPT_UNALIGNED32
+# define LZO_OPT_UNALIGNED32 1
# endif
-# if (LZO_CC_GNUC || LZO_CC_HIGHC || LZO_CC_NDPC || LZO_CC_PACIFICC || LZO_CC_WATCOMC)
-# elif (LZO_OS_OS2 && (LZO_CC_DMC || LZO_CC_SYMANTECC))
-# define __lzo_cdecl_sighandler __pascal
-# elif (LZO_OS_OS2 && (LZO_CC_ZORTECHC))
-# define __lzo_cdecl_sighandler _stdcall
-# elif (LZO_CC_MSC && (_MSC_VER >= 1400)) && defined(_M_CEE_PURE)
-# define __lzo_cdecl_sighandler __clrcall
-# elif (LZO_CC_MSC && (_MSC_VER >= 600 && _MSC_VER < 700))
-# if defined(_DLL)
-# define __lzo_cdecl_sighandler _far _cdecl _loadds
-# elif defined(_MT)
-# define __lzo_cdecl_sighandler _far _cdecl
-# else
-# define __lzo_cdecl_sighandler _cdecl
-# endif
-# else
-# define __lzo_cdecl_sighandler __cdecl
+#elif (LZO_ARCH_I386)
+# ifndef LZO_OPT_UNALIGNED16
+# define LZO_OPT_UNALIGNED16 1
# endif
-#elif (LZO_ARCH_I386) && (LZO_CC_WATCOMC)
-# define __lzo_cdecl __cdecl
-#elif (LZO_ARCH_M68K && LZO_OS_TOS && (LZO_CC_PUREC || LZO_CC_TURBOC))
-# define __lzo_cdecl cdecl
-#endif
-#if !defined(__lzo_cdecl)
-# define __lzo_cdecl /*empty*/
-#endif
-#if !defined(__lzo_cdecl_atexit)
-# define __lzo_cdecl_atexit /*empty*/
-#endif
-#if !defined(__lzo_cdecl_main)
-# define __lzo_cdecl_main /*empty*/
-#endif
-#if !defined(__lzo_cdecl_qsort)
-# define __lzo_cdecl_qsort /*empty*/
-#endif
-#if !defined(__lzo_cdecl_sighandler)
-# define __lzo_cdecl_sighandler /*empty*/
-#endif
-#if !defined(__lzo_cdecl_va)
-# define __lzo_cdecl_va __lzo_cdecl
-#endif
-#if !(LZO_CFG_NO_WINDOWS_H)
-#if (LZO_OS_CYGWIN || (LZO_OS_EMX && defined(__RSXNT__)) || LZO_OS_WIN32 || LZO_OS_WIN64)
-# if (LZO_CC_WATCOMC && (__WATCOMC__ < 1000))
-# elif (LZO_OS_WIN32 && LZO_CC_GNUC) && defined(__PW32__)
-# elif ((LZO_OS_CYGWIN || defined(__MINGW32__)) && (LZO_CC_GNUC && (LZO_CC_GNUC < 0x025f00ul)))
-# else
-# define LZO_HAVE_WINDOWS_H 1
+# ifndef LZO_OPT_UNALIGNED32
+# define LZO_OPT_UNALIGNED32 1
# endif
-#endif
-#endif
-#if (LZO_ARCH_ALPHA)
-# define LZO_OPT_AVOID_UINT_INDEX 1
-# define LZO_OPT_AVOID_SHORT 1
-# define LZO_OPT_AVOID_USHORT 1
-#elif (LZO_ARCH_AMD64)
-# define LZO_OPT_AVOID_INT_INDEX 1
-# define LZO_OPT_AVOID_UINT_INDEX 1
-# define LZO_OPT_UNALIGNED16 1
-# define LZO_OPT_UNALIGNED32 1
-# define LZO_OPT_UNALIGNED64 1
-#elif (LZO_ARCH_ARM && LZO_ARCH_ARM_THUMB)
-#elif (LZO_ARCH_ARM)
-# define LZO_OPT_AVOID_SHORT 1
-# define LZO_OPT_AVOID_USHORT 1
-#elif (LZO_ARCH_CRIS)
-# define LZO_OPT_UNALIGNED16 1
-# define LZO_OPT_UNALIGNED32 1
-#elif (LZO_ARCH_I386)
-# define LZO_OPT_UNALIGNED16 1
-# define LZO_OPT_UNALIGNED32 1
#elif (LZO_ARCH_IA64)
-# define LZO_OPT_AVOID_INT_INDEX 1
-# define LZO_OPT_AVOID_UINT_INDEX 1
-# define LZO_OPT_PREFER_POSTINC 1
+# define LZO_OPT_AVOID_INT_INDEX 1
+# define LZO_OPT_AVOID_UINT_INDEX 1
+# define LZO_OPT_PREFER_POSTINC 1
#elif (LZO_ARCH_M68K)
-# define LZO_OPT_PREFER_POSTINC 1
-# define LZO_OPT_PREFER_PREDEC 1
+# define LZO_OPT_PREFER_POSTINC 1
+# define LZO_OPT_PREFER_PREDEC 1
# if defined(__mc68020__) && !defined(__mcoldfire__)
-# define LZO_OPT_UNALIGNED16 1
-# define LZO_OPT_UNALIGNED32 1
+# ifndef LZO_OPT_UNALIGNED16
+# define LZO_OPT_UNALIGNED16 1
+# endif
+# ifndef LZO_OPT_UNALIGNED32
+# define LZO_OPT_UNALIGNED32 1
+# endif
# endif
#elif (LZO_ARCH_MIPS)
-# define LZO_OPT_AVOID_UINT_INDEX 1
+# define LZO_OPT_AVOID_UINT_INDEX 1
#elif (LZO_ARCH_POWERPC)
-# define LZO_OPT_PREFER_PREINC 1
-# define LZO_OPT_PREFER_PREDEC 1
+# define LZO_OPT_PREFER_PREINC 1
+# define LZO_OPT_PREFER_PREDEC 1
# if (LZO_ABI_BIG_ENDIAN)
-# define LZO_OPT_UNALIGNED16 1
-# define LZO_OPT_UNALIGNED32 1
+# ifndef LZO_OPT_UNALIGNED16
+# define LZO_OPT_UNALIGNED16 1
+# endif
+# ifndef LZO_OPT_UNALIGNED32
+# define LZO_OPT_UNALIGNED32 1
+# endif
+# if (LZO_WORDSIZE == 8)
+# ifndef LZO_OPT_UNALIGNED64
+# define LZO_OPT_UNALIGNED64 1
+# endif
+# endif
# endif
#elif (LZO_ARCH_S390)
-# define LZO_OPT_UNALIGNED16 1
-# define LZO_OPT_UNALIGNED32 1
-# if (LZO_SIZEOF_SIZE_T == 8)
-# define LZO_OPT_UNALIGNED64 1
+# ifndef LZO_OPT_UNALIGNED16
+# define LZO_OPT_UNALIGNED16 1
+# endif
+# ifndef LZO_OPT_UNALIGNED32
+# define LZO_OPT_UNALIGNED32 1
+# endif
+# if (LZO_WORDSIZE == 8)
+# ifndef LZO_OPT_UNALIGNED64
+# define LZO_OPT_UNALIGNED64 1
+# endif
# endif
#elif (LZO_ARCH_SH)
-# define LZO_OPT_PREFER_POSTINC 1
-# define LZO_OPT_PREFER_PREDEC 1
+# define LZO_OPT_PREFER_POSTINC 1
+# define LZO_OPT_PREFER_PREDEC 1
#endif
#ifndef LZO_CFG_NO_INLINE_ASM
-#if (LZO_CC_LLVM)
+#if (LZO_ABI_NEUTRAL_ENDIAN) || (LZO_ARCH_GENERIC)
+# define LZO_CFG_NO_INLINE_ASM 1
+#elif (LZO_CC_LLVM)
# define LZO_CFG_NO_INLINE_ASM 1
#endif
#endif
+#if (LZO_CFG_NO_INLINE_ASM)
+# undef LZO_ASM_SYNTAX_MSC
+# undef LZO_ASM_SYNTAX_GNUC
+# undef __LZO_ASM_CLOBBER
+# undef __LZO_ASM_CLOBBER_LIST_CC
+# undef __LZO_ASM_CLOBBER_LIST_CC_MEMORY
+# undef __LZO_ASM_CLOBBER_LIST_EMPTY
+#endif
#ifndef LZO_CFG_NO_UNALIGNED
#if (LZO_ABI_NEUTRAL_ENDIAN) || (LZO_ARCH_GENERIC)
# define LZO_CFG_NO_UNALIGNED 1
@@ -1804,25 +2594,6 @@ extern "C" {
# undef LZO_OPT_UNALIGNED32
# undef LZO_OPT_UNALIGNED64
#endif
-#if (LZO_CFG_NO_INLINE_ASM)
-#elif (LZO_ARCH_I386 && (LZO_OS_DOS32 || LZO_OS_WIN32) && (LZO_CC_DMC || LZO_CC_INTELC || LZO_CC_MSC || LZO_CC_PELLESC))
-# define LZO_ASM_SYNTAX_MSC 1
-#elif (LZO_OS_WIN64 && (LZO_CC_DMC || LZO_CC_INTELC || LZO_CC_MSC || LZO_CC_PELLESC))
-#elif (LZO_ARCH_I386 && LZO_CC_GNUC && (LZO_CC_GNUC == 0x011f00ul))
-#elif (LZO_ARCH_I386 && (LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_INTELC || LZO_CC_PATHSCALE))
-# define LZO_ASM_SYNTAX_GNUC 1
-#elif (LZO_ARCH_AMD64 && (LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_INTELC || LZO_CC_PATHSCALE))
-# define LZO_ASM_SYNTAX_GNUC 1
-#endif
-#if (LZO_ASM_SYNTAX_GNUC)
-#if (LZO_ARCH_I386 && LZO_CC_GNUC && (LZO_CC_GNUC < 0x020000ul))
-# define __LZO_ASM_CLOBBER "ax"
-#elif (LZO_CC_INTELC)
-# define __LZO_ASM_CLOBBER "memory"
-#else
-# define __LZO_ASM_CLOBBER "cc", "memory"
-#endif
-#endif
#if defined(__LZO_INFOSTR_MM)
#elif (LZO_MM_FLAT) && (defined(__LZO_INFOSTR_PM) || defined(LZO_INFO_ABI_PM))
# define __LZO_INFOSTR_MM ""
@@ -1866,6 +2637,381 @@ extern "C" {
#define LZO_INFO_STRING \
LZO_INFO_ARCH __LZO_INFOSTR_MM __LZO_INFOSTR_PM __LZO_INFOSTR_ENDIAN \
" " __LZO_INFOSTR_OSNAME __LZO_INFOSTR_LIBC " " LZO_INFO_CC __LZO_INFOSTR_CCVER
+#if !(LZO_CFG_SKIP_LZO_TYPES)
+#if (!(LZO_SIZEOF_SHORT+0 > 0 && LZO_SIZEOF_INT+0 > 0 && LZO_SIZEOF_LONG+0 > 0))
+# error "missing defines for sizes"
+#endif
+#if (!(LZO_SIZEOF_PTRDIFF_T+0 > 0 && LZO_SIZEOF_SIZE_T+0 > 0 && LZO_SIZEOF_VOID_P+0 > 0))
+# error "missing defines for sizes"
+#endif
+#if !defined(lzo_llong_t)
+#if (LZO_SIZEOF_LONG_LONG+0 > 0)
+__lzo_gnuc_extension__ typedef long long lzo_llong_t__;
+__lzo_gnuc_extension__ typedef unsigned long long lzo_ullong_t__;
+# define lzo_llong_t lzo_llong_t__
+# define lzo_ullong_t lzo_ullong_t__
+#endif
+#endif
+#if !defined(lzo_int16e_t)
+#if (LZO_SIZEOF_LONG == 2)
+# define lzo_int16e_t long
+# define lzo_uint16e_t unsigned long
+#elif (LZO_SIZEOF_INT == 2)
+# define lzo_int16e_t int
+# define lzo_uint16e_t unsigned int
+#elif (LZO_SIZEOF_SHORT == 2)
+# define lzo_int16e_t short int
+# define lzo_uint16e_t unsigned short int
+#elif 1 && !(LZO_CFG_TYPE_NO_MODE_HI) && (LZO_CC_CLANG || (LZO_CC_GNUC >= 0x025f00ul) || LZO_CC_LLVM)
+ typedef int lzo_int16e_hi_t__ __attribute__((__mode__(__HI__)));
+ typedef unsigned int lzo_uint16e_hi_t__ __attribute__((__mode__(__HI__)));
+# define lzo_int16e_t lzo_int16e_hi_t__
+# define lzo_uint16e_t lzo_uint16e_hi_t__
+#elif (LZO_SIZEOF___INT16 == 2)
+# define lzo_int16e_t __int16
+# define lzo_uint16e_t unsigned __int16
+#else
+#endif
+#endif
+#if defined(lzo_int16e_t)
+# define LZO_SIZEOF_LZO_INT16E_T 2
+ LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int16e_t) == 2)
+ LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int16e_t) == LZO_SIZEOF_LZO_INT16E_T)
+#endif
+#if !defined(lzo_int32e_t)
+#if (LZO_SIZEOF_LONG == 4)
+# define lzo_int32e_t long int
+# define lzo_uint32e_t unsigned long int
+#elif (LZO_SIZEOF_INT == 4)
+# define lzo_int32e_t int
+# define lzo_uint32e_t unsigned int
+#elif (LZO_SIZEOF_SHORT == 4)
+# define lzo_int32e_t short int
+# define lzo_uint32e_t unsigned short int
+#elif (LZO_SIZEOF_LONG_LONG == 4)
+# define lzo_int32e_t lzo_llong_t
+# define lzo_uint32e_t lzo_ullong_t
+#elif 1 && !(LZO_CFG_TYPE_NO_MODE_SI) && (LZO_CC_CLANG || (LZO_CC_GNUC >= 0x025f00ul) || LZO_CC_LLVM) && (__INT_MAX__+0 > 2147483647L)
+ typedef int lzo_int32e_si_t__ __attribute__((__mode__(__SI__)));
+ typedef unsigned int lzo_uint32e_si_t__ __attribute__((__mode__(__SI__)));
+# define lzo_int32e_t lzo_int32e_si_t__
+# define lzo_uint32e_t lzo_uint32e_si_t__
+#elif 1 && !(LZO_CFG_TYPE_NO_MODE_SI) && (LZO_CC_GNUC >= 0x025f00ul) && defined(__AVR__) && (__LONG_MAX__+0 == 32767L)
+ typedef int lzo_int32e_si_t__ __attribute__((__mode__(__SI__)));
+ typedef unsigned int lzo_uint32e_si_t__ __attribute__((__mode__(__SI__)));
+# define lzo_int32e_t lzo_int32e_si_t__
+# define lzo_uint32e_t lzo_uint32e_si_t__
+# define LZO_INT32_C(c) (c##LL)
+# define LZO_UINT32_C(c) (c##ULL)
+#elif (LZO_SIZEOF___INT32 == 4)
+# define lzo_int32e_t __int32
+# define lzo_uint32e_t unsigned __int32
+#else
+#endif
+#endif
+#if defined(lzo_int32e_t)
+# define LZO_SIZEOF_LZO_INT32E_T 4
+ LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int32e_t) == 4)
+ LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int32e_t) == LZO_SIZEOF_LZO_INT32E_T)
+#endif
+#if !defined(lzo_int64e_t)
+#if (LZO_SIZEOF___INT64 == 8)
+# if (LZO_CC_BORLANDC) && !(LZO_CFG_TYPE_PREFER___INT64)
+# define LZO_CFG_TYPE_PREFER___INT64 1
+# endif
+#endif
+#if (LZO_SIZEOF_INT == 8) && (LZO_SIZEOF_INT < LZO_SIZEOF_LONG)
+# define lzo_int64e_t int
+# define lzo_uint64e_t unsigned int
+# define LZO_SIZEOF_LZO_INT64E_T LZO_SIZEOF_INT
+#elif (LZO_SIZEOF_LONG == 8)
+# define lzo_int64e_t long int
+# define lzo_uint64e_t unsigned long int
+# define LZO_SIZEOF_LZO_INT64E_T LZO_SIZEOF_LONG
+#elif (LZO_SIZEOF_LONG_LONG == 8) && !(LZO_CFG_TYPE_PREFER___INT64)
+# define lzo_int64e_t lzo_llong_t
+# define lzo_uint64e_t lzo_ullong_t
+# if (LZO_CC_BORLANDC)
+# define LZO_INT64_C(c) ((c) + 0ll)
+# define LZO_UINT64_C(c) ((c) + 0ull)
+# elif 0
+# define LZO_INT64_C(c) (__lzo_gnuc_extension__ (c##LL))
+# define LZO_UINT64_C(c) (__lzo_gnuc_extension__ (c##ULL))
+# else
+# define LZO_INT64_C(c) (c##LL)
+# define LZO_UINT64_C(c) (c##ULL)
+# endif
+# define LZO_SIZEOF_LZO_INT64E_T LZO_SIZEOF_LONG_LONG
+#elif (LZO_SIZEOF___INT64 == 8)
+# define lzo_int64e_t __int64
+# define lzo_uint64e_t unsigned __int64
+# if (LZO_CC_BORLANDC)
+# define LZO_INT64_C(c) ((c) + 0i64)
+# define LZO_UINT64_C(c) ((c) + 0ui64)
+# else
+# define LZO_INT64_C(c) (c##i64)
+# define LZO_UINT64_C(c) (c##ui64)
+# endif
+# define LZO_SIZEOF_LZO_INT64E_T LZO_SIZEOF___INT64
+#else
+#endif
+#endif
+#if defined(lzo_int64e_t)
+ LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int64e_t) == 8)
+ LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int64e_t) == LZO_SIZEOF_LZO_INT64E_T)
+#endif
+#if !defined(lzo_int32l_t)
+#if defined(lzo_int32e_t)
+# define lzo_int32l_t lzo_int32e_t
+# define lzo_uint32l_t lzo_uint32e_t
+# define LZO_SIZEOF_LZO_INT32L_T LZO_SIZEOF_LZO_INT32E_T
+#elif (LZO_SIZEOF_INT >= 4) && (LZO_SIZEOF_INT < LZO_SIZEOF_LONG)
+# define lzo_int32l_t int
+# define lzo_uint32l_t unsigned int
+# define LZO_SIZEOF_LZO_INT32L_T LZO_SIZEOF_INT
+#elif (LZO_SIZEOF_LONG >= 4)
+# define lzo_int32l_t long int
+# define lzo_uint32l_t unsigned long int
+# define LZO_SIZEOF_LZO_INT32L_T LZO_SIZEOF_LONG
+#else
+# error "lzo_int32l_t"
+#endif
+#endif
+#if 1
+ LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int32l_t) >= 4)
+ LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int32l_t) == LZO_SIZEOF_LZO_INT32L_T)
+#endif
+#if !defined(lzo_int64l_t)
+#if defined(lzo_int64e_t)
+# define lzo_int64l_t lzo_int64e_t
+# define lzo_uint64l_t lzo_uint64e_t
+# define LZO_SIZEOF_LZO_INT64L_T LZO_SIZEOF_LZO_INT64E_T
+#else
+#endif
+#endif
+#if defined(lzo_int64l_t)
+ LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int64l_t) >= 8)
+ LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int64l_t) == LZO_SIZEOF_LZO_INT64L_T)
+#endif
+#if !defined(lzo_int32f_t)
+#if (LZO_SIZEOF_SIZE_T >= 8)
+# define lzo_int32f_t lzo_int64l_t
+# define lzo_uint32f_t lzo_uint64l_t
+# define LZO_SIZEOF_LZO_INT32F_T LZO_SIZEOF_LZO_INT64L_T
+#else
+# define lzo_int32f_t lzo_int32l_t
+# define lzo_uint32f_t lzo_uint32l_t
+# define LZO_SIZEOF_LZO_INT32F_T LZO_SIZEOF_LZO_INT32L_T
+#endif
+#endif
+#if 1
+ LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int32f_t) >= 4)
+ LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int32f_t) == LZO_SIZEOF_LZO_INT32F_T)
+#endif
+#if !defined(lzo_int64f_t)
+#if defined(lzo_int64l_t)
+# define lzo_int64f_t lzo_int64l_t
+# define lzo_uint64f_t lzo_uint64l_t
+# define LZO_SIZEOF_LZO_INT64F_T LZO_SIZEOF_LZO_INT64L_T
+#else
+#endif
+#endif
+#if defined(lzo_int64f_t)
+ LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int64f_t) >= 8)
+ LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int64f_t) == LZO_SIZEOF_LZO_INT64F_T)
+#endif
+#if !defined(lzo_intptr_t)
+#if 1 && (LZO_OS_OS400 && (LZO_SIZEOF_VOID_P == 16))
+# define __LZO_INTPTR_T_IS_POINTER 1
+ typedef char* lzo_intptr_t;
+ typedef char* lzo_uintptr_t;
+# define lzo_intptr_t lzo_intptr_t
+# define lzo_uintptr_t lzo_uintptr_t
+# define LZO_SIZEOF_LZO_INTPTR_T LZO_SIZEOF_VOID_P
+#elif (LZO_CC_MSC && (_MSC_VER >= 1300) && (LZO_SIZEOF_VOID_P == 4) && (LZO_SIZEOF_INT == 4))
+ typedef __w64 int lzo_intptr_t;
+ typedef __w64 unsigned int lzo_uintptr_t;
+# define lzo_intptr_t lzo_intptr_t
+# define lzo_uintptr_t lzo_uintptr_t
+# define LZO_SIZEOF_LZO_INTPTR_T LZO_SIZEOF_INT
+#elif (LZO_SIZEOF_SHORT == LZO_SIZEOF_VOID_P) && (LZO_SIZEOF_INT > LZO_SIZEOF_VOID_P)
+# define lzo_intptr_t short
+# define lzo_uintptr_t unsigned short
+# define LZO_SIZEOF_LZO_INTPTR_T LZO_SIZEOF_SHORT
+#elif (LZO_SIZEOF_INT >= LZO_SIZEOF_VOID_P) && (LZO_SIZEOF_INT < LZO_SIZEOF_LONG)
+# define lzo_intptr_t int
+# define lzo_uintptr_t unsigned int
+# define LZO_SIZEOF_LZO_INTPTR_T LZO_SIZEOF_INT
+#elif (LZO_SIZEOF_LONG >= LZO_SIZEOF_VOID_P)
+# define lzo_intptr_t long
+# define lzo_uintptr_t unsigned long
+# define LZO_SIZEOF_LZO_INTPTR_T LZO_SIZEOF_LONG
+#elif (LZO_SIZEOF_LZO_INT64L_T >= LZO_SIZEOF_VOID_P)
+# define lzo_intptr_t lzo_int64l_t
+# define lzo_uintptr_t lzo_uint64l_t
+# define LZO_SIZEOF_LZO_INTPTR_T LZO_SIZEOF_LZO_INT64L_T
+#else
+# error "lzo_intptr_t"
+#endif
+#endif
+#if 1
+ LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_intptr_t) >= sizeof(void *))
+ LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_intptr_t) == sizeof(lzo_uintptr_t))
+#endif
+#if !defined(lzo_word_t)
+#if defined(LZO_WORDSIZE) && (LZO_WORDSIZE+0 > 0)
+#if (LZO_WORDSIZE == LZO_SIZEOF_LZO_INTPTR_T) && !(__LZO_INTPTR_T_IS_POINTER)
+# define lzo_word_t lzo_uintptr_t
+# define lzo_sword_t lzo_intptr_t
+# define LZO_SIZEOF_LZO_WORD_T LZO_SIZEOF_LZO_INTPTR_T
+#elif (LZO_WORDSIZE == LZO_SIZEOF_LONG)
+# define lzo_word_t unsigned long
+# define lzo_sword_t long
+# define LZO_SIZEOF_LZO_WORD_T LZO_SIZEOF_LONG
+#elif (LZO_WORDSIZE == LZO_SIZEOF_INT)
+# define lzo_word_t unsigned int
+# define lzo_sword_t int
+# define LZO_SIZEOF_LZO_WORD_T LZO_SIZEOF_INT
+#elif (LZO_WORDSIZE == LZO_SIZEOF_SHORT)
+# define lzo_word_t unsigned short
+# define lzo_sword_t short
+# define LZO_SIZEOF_LZO_WORD_T LZO_SIZEOF_SHORT
+#elif (LZO_WORDSIZE == 1)
+# define lzo_word_t unsigned char
+# define lzo_sword_t signed char
+# define LZO_SIZEOF_LZO_WORD_T 1
+#elif (LZO_WORDSIZE == LZO_SIZEOF_LZO_INT64L_T)
+# define lzo_word_t lzo_uint64l_t
+# define lzo_sword_t lzo_int64l_t
+# define LZO_SIZEOF_LZO_WORD_T LZO_SIZEOF_LZO_INT64L_T
+#elif (LZO_ARCH_SPU) && (LZO_CC_GNUC)
+#if 0
+ typedef unsigned lzo_word_t __attribute__((__mode__(__V16QI__)));
+ typedef int lzo_sword_t __attribute__((__mode__(__V16QI__)));
+# define lzo_word_t lzo_word_t
+# define lzo_sword_t lzo_sword_t
+# define LZO_SIZEOF_LZO_WORD_T 16
+#endif
+#else
+# error "lzo_word_t"
+#endif
+#endif
+#endif
+#if 1 && defined(lzo_word_t)
+ LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_word_t) == LZO_WORDSIZE)
+ LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_sword_t) == LZO_WORDSIZE)
+#endif
+#if 1
+#define lzo_int8_t signed char
+#define lzo_uint8_t unsigned char
+#define LZO_SIZEOF_LZO_INT8_T 1
+LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int8_t) == 1)
+LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int8_t) == sizeof(lzo_uint8_t))
+#endif
+#if defined(lzo_int16e_t)
+#define lzo_int16_t lzo_int16e_t
+#define lzo_uint16_t lzo_uint16e_t
+#define LZO_SIZEOF_LZO_INT16_T LZO_SIZEOF_LZO_INT16E_T
+LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int16_t) == 2)
+LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int16_t) == sizeof(lzo_uint16_t))
+#endif
+#if defined(lzo_int32e_t)
+#define lzo_int32_t lzo_int32e_t
+#define lzo_uint32_t lzo_uint32e_t
+#define LZO_SIZEOF_LZO_INT32_T LZO_SIZEOF_LZO_INT32E_T
+LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int32_t) == 4)
+LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int32_t) == sizeof(lzo_uint32_t))
+#endif
+#if defined(lzo_int64e_t)
+#define lzo_int64_t lzo_int64e_t
+#define lzo_uint64_t lzo_uint64e_t
+#define LZO_SIZEOF_LZO_INT64_T LZO_SIZEOF_LZO_INT64E_T
+LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int64_t) == 8)
+LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int64_t) == sizeof(lzo_uint64_t))
+#endif
+#if 1
+#define lzo_int_least32_t lzo_int32l_t
+#define lzo_uint_least32_t lzo_uint32l_t
+#define LZO_SIZEOF_LZO_INT_LEAST32_T LZO_SIZEOF_LZO_INT32L_T
+LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int_least32_t) >= 4)
+LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int_least32_t) == sizeof(lzo_uint_least32_t))
+#endif
+#if defined(lzo_int64l_t)
+#define lzo_int_least64_t lzo_int64l_t
+#define lzo_uint_least64_t lzo_uint64l_t
+#define LZO_SIZEOF_LZO_INT_LEAST64_T LZO_SIZEOF_LZO_INT64L_T
+LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int_least64_t) >= 8)
+LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int_least64_t) == sizeof(lzo_uint_least64_t))
+#endif
+#if 1
+#define lzo_int_fast32_t lzo_int32f_t
+#define lzo_uint_fast32_t lzo_uint32f_t
+#define LZO_SIZEOF_LZO_INT_FAST32_T LZO_SIZEOF_LZO_INT32F_T
+LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int_fast32_t) >= 4)
+LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int_fast32_t) == sizeof(lzo_uint_fast32_t))
+#endif
+#if defined(lzo_int64f_t)
+#define lzo_int_fast64_t lzo_int64f_t
+#define lzo_uint_fast64_t lzo_uint64f_t
+#define LZO_SIZEOF_LZO_INT_FAST64_T LZO_SIZEOF_LZO_INT64F_T
+LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int_fast64_t) >= 8)
+LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int_fast64_t) == sizeof(lzo_uint_fast64_t))
+#endif
+#if !defined(LZO_INT16_C)
+# if (LZO_BROKEN_INTEGRAL_CONSTANTS) && (LZO_SIZEOF_INT >= 2)
+# define LZO_INT16_C(c) ((c) + 0)
+# define LZO_UINT16_C(c) ((c) + 0U)
+# elif (LZO_BROKEN_INTEGRAL_CONSTANTS) && (LZO_SIZEOF_LONG >= 2)
+# define LZO_INT16_C(c) ((c) + 0L)
+# define LZO_UINT16_C(c) ((c) + 0UL)
+# elif (LZO_SIZEOF_INT >= 2)
+# define LZO_INT16_C(c) (c)
+# define LZO_UINT16_C(c) (c##U)
+# elif (LZO_SIZEOF_LONG >= 2)
+# define LZO_INT16_C(c) (c##L)
+# define LZO_UINT16_C(c) (c##UL)
+# else
+# error "LZO_INT16_C"
+# endif
+#endif
+#if !defined(LZO_INT32_C)
+# if (LZO_BROKEN_INTEGRAL_CONSTANTS) && (LZO_SIZEOF_INT >= 4)
+# define LZO_INT32_C(c) ((c) + 0)
+# define LZO_UINT32_C(c) ((c) + 0U)
+# elif (LZO_BROKEN_INTEGRAL_CONSTANTS) && (LZO_SIZEOF_LONG >= 4)
+# define LZO_INT32_C(c) ((c) + 0L)
+# define LZO_UINT32_C(c) ((c) + 0UL)
+# elif (LZO_SIZEOF_INT >= 4)
+# define LZO_INT32_C(c) (c)
+# define LZO_UINT32_C(c) (c##U)
+# elif (LZO_SIZEOF_LONG >= 4)
+# define LZO_INT32_C(c) (c##L)
+# define LZO_UINT32_C(c) (c##UL)
+# elif (LZO_SIZEOF_LONG_LONG >= 4)
+# define LZO_INT32_C(c) (c##LL)
+# define LZO_UINT32_C(c) (c##ULL)
+# else
+# error "LZO_INT32_C"
+# endif
+#endif
+#if !defined(LZO_INT64_C) && defined(lzo_int64l_t)
+# if (LZO_BROKEN_INTEGRAL_CONSTANTS) && (LZO_SIZEOF_INT >= 8)
+# define LZO_INT64_C(c) ((c) + 0)
+# define LZO_UINT64_C(c) ((c) + 0U)
+# elif (LZO_BROKEN_INTEGRAL_CONSTANTS) && (LZO_SIZEOF_LONG >= 8)
+# define LZO_INT64_C(c) ((c) + 0L)
+# define LZO_UINT64_C(c) ((c) + 0UL)
+# elif (LZO_SIZEOF_INT >= 8)
+# define LZO_INT64_C(c) (c)
+# define LZO_UINT64_C(c) (c##U)
+# elif (LZO_SIZEOF_LONG >= 8)
+# define LZO_INT64_C(c) (c##L)
+# define LZO_UINT64_C(c) (c##UL)
+# else
+# error "LZO_INT64_C"
+# endif
+#endif
+#endif
#endif
@@ -1874,7 +3020,7 @@ extern "C" {
#undef LZO_HAVE_CONFIG_H
#include "minilzo.h"
-#if !defined(MINILZO_VERSION) || (MINILZO_VERSION != 0x2060)
+#if !defined(MINILZO_VERSION) || (MINILZO_VERSION != 0x2080)
# error "version mismatch in miniLZO source files"
#endif
@@ -1886,23 +3032,9 @@ extern "C" {
#define __LZO_CONF_H 1
#if !defined(__LZO_IN_MINILZO)
-#if (LZO_CFG_FREESTANDING)
+#if defined(LZO_CFG_FREESTANDING) && (LZO_CFG_FREESTANDING)
# define LZO_LIBC_FREESTANDING 1
# define LZO_OS_FREESTANDING 1
-# define ACC_LIBC_FREESTANDING 1
-# define ACC_OS_FREESTANDING 1
-#endif
-#if (LZO_CFG_NO_UNALIGNED)
-# define ACC_CFG_NO_UNALIGNED 1
-#endif
-#if (LZO_ARCH_GENERIC)
-# define ACC_ARCH_GENERIC 1
-#endif
-#if (LZO_ABI_NEUTRAL_ENDIAN)
-# define ACC_ABI_NEUTRAL_ENDIAN 1
-#endif
-#if (LZO_HAVE_CONFIG_H)
-# define ACC_CONFIG_NO_HEADER 1
#endif
#if defined(LZO_CFG_EXTRA_CONFIG_HEADER)
# include LZO_CFG_EXTRA_CONFIG_HEADER
@@ -1911,22 +3043,27 @@ extern "C" {
# error "include this file first"
#endif
#include "lzo/lzoconf.h"
+#if defined(LZO_CFG_EXTRA_CONFIG_HEADER2)
+# include LZO_CFG_EXTRA_CONFIG_HEADER2
+#endif
#endif
-#if (LZO_VERSION < 0x02000) || !defined(__LZOCONF_H_INCLUDED)
+#if (LZO_VERSION < 0x2080) || !defined(__LZOCONF_H_INCLUDED)
# error "version mismatch"
#endif
-#if (LZO_CC_BORLANDC && LZO_ARCH_I086)
-# pragma option -h
+#if (LZO_CC_MSC && (_MSC_VER >= 1000 && _MSC_VER < 1100))
+# pragma warning(disable: 4702)
#endif
-
#if (LZO_CC_MSC && (_MSC_VER >= 1000))
# pragma warning(disable: 4127 4701)
+# pragma warning(disable: 4514 4710 4711)
#endif
#if (LZO_CC_MSC && (_MSC_VER >= 1300))
# pragma warning(disable: 4820)
-# pragma warning(disable: 4514 4710 4711)
+#endif
+#if (LZO_CC_MSC && (_MSC_VER >= 1800))
+# pragma warning(disable: 4746)
#endif
#if (LZO_CC_SUNPROC)
@@ -1937,48 +3074,15 @@ extern "C" {
#endif
#endif
-#if (__LZO_MMODEL_HUGE) && !(LZO_HAVE_MM_HUGE_PTR)
-# error "this should not happen - check defines for __huge"
-#endif
-
-#if defined(__LZO_IN_MINILZO) || defined(LZO_CFG_FREESTANDING)
-#elif (LZO_OS_DOS16 || LZO_OS_OS216 || LZO_OS_WIN16)
-# define ACC_WANT_ACC_INCD_H 1
-# define ACC_WANT_ACC_INCE_H 1
-# define ACC_WANT_ACC_INCI_H 1
+#if defined(__LZO_IN_MINILZO) || (LZO_CFG_FREESTANDING)
#elif 1
# include <string.h>
#else
-# define ACC_WANT_ACC_INCD_H 1
+# define LZO_WANT_ACC_INCD_H 1
#endif
-
-#if (LZO_ARCH_I086)
-# define ACC_MM_AHSHIFT LZO_MM_AHSHIFT
-# define ACC_PTR_FP_OFF(x) (((const unsigned __far*)&(x))[0])
-# define ACC_PTR_FP_SEG(x) (((const unsigned __far*)&(x))[1])
-# define ACC_PTR_MK_FP(s,o) ((void __far*)(((unsigned long)(s)<<16)+(unsigned)(o)))
-#endif
-
-#if !defined(lzo_uintptr_t)
-# if defined(__LZO_MMODEL_HUGE)
-# define lzo_uintptr_t unsigned long
-# elif 1 && defined(LZO_OS_OS400) && (LZO_SIZEOF_VOID_P == 16)
-# define __LZO_UINTPTR_T_IS_POINTER 1
- typedef char* lzo_uintptr_t;
-# define lzo_uintptr_t lzo_uintptr_t
-# elif (LZO_SIZEOF_SIZE_T == LZO_SIZEOF_VOID_P)
-# define lzo_uintptr_t size_t
-# elif (LZO_SIZEOF_LONG == LZO_SIZEOF_VOID_P)
-# define lzo_uintptr_t unsigned long
-# elif (LZO_SIZEOF_INT == LZO_SIZEOF_VOID_P)
-# define lzo_uintptr_t unsigned int
-# elif (LZO_SIZEOF_LONG_LONG == LZO_SIZEOF_VOID_P)
-# define lzo_uintptr_t unsigned long long
-# else
-# define lzo_uintptr_t size_t
-# endif
+#if defined(LZO_HAVE_CONFIG_H)
+# define LZO_CFG_NO_CONFIG_HEADER 1
#endif
-LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_uintptr_t) >= sizeof(lzo_voidp))
#if 1 && !defined(LZO_CFG_FREESTANDING)
#if 1 && !defined(HAVE_STRING_H)
@@ -2002,6 +3106,23 @@ LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_uintptr_t) >= sizeof(lzo_voidp))
#include <string.h>
#endif
+#if 1 || defined(lzo_int8_t) || defined(lzo_uint8_t)
+LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int8_t) == 1)
+LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_uint8_t) == 1)
+#endif
+#if 1 || defined(lzo_int16_t) || defined(lzo_uint16_t)
+LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int16_t) == 2)
+LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_uint16_t) == 2)
+#endif
+#if 1 || defined(lzo_int32_t) || defined(lzo_uint32_t)
+LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int32_t) == 4)
+LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_uint32_t) == 4)
+#endif
+#if defined(lzo_int64_t) || defined(lzo_uint64_t)
+LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int64_t) == 8)
+LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_uint64_t) == 8)
+#endif
+
#if (LZO_CFG_FREESTANDING)
# undef HAVE_MEMCMP
# undef HAVE_MEMCPY
@@ -2012,28 +3133,28 @@ LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_uintptr_t) >= sizeof(lzo_voidp))
#if !(HAVE_MEMCMP)
# undef memcmp
# define memcmp(a,b,c) lzo_memcmp(a,b,c)
-#elif !(__LZO_MMODEL_HUGE)
+#else
# undef lzo_memcmp
# define lzo_memcmp(a,b,c) memcmp(a,b,c)
#endif
#if !(HAVE_MEMCPY)
# undef memcpy
# define memcpy(a,b,c) lzo_memcpy(a,b,c)
-#elif !(__LZO_MMODEL_HUGE)
+#else
# undef lzo_memcpy
# define lzo_memcpy(a,b,c) memcpy(a,b,c)
#endif
#if !(HAVE_MEMMOVE)
# undef memmove
# define memmove(a,b,c) lzo_memmove(a,b,c)
-#elif !(__LZO_MMODEL_HUGE)
+#else
# undef lzo_memmove
# define lzo_memmove(a,b,c) memmove(a,b,c)
#endif
#if !(HAVE_MEMSET)
# undef memset
# define memset(a,b,c) lzo_memset(a,b,c)
-#elif !(__LZO_MMODEL_HUGE)
+#else
# undef lzo_memset
# define lzo_memset(a,b,c) memset(a,b,c)
#endif
@@ -2058,27 +3179,29 @@ LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_uintptr_t) >= sizeof(lzo_voidp))
# define BOUNDS_CHECKING_OFF_IN_EXPR(expr) (expr)
#endif
-#if !defined(__lzo_inline)
-# define __lzo_inline /*empty*/
-#endif
-#if !defined(__lzo_forceinline)
-# define __lzo_forceinline /*empty*/
-#endif
-#if !defined(__lzo_noinline)
-# define __lzo_noinline /*empty*/
-#endif
-
#if (LZO_CFG_PGO)
-# undef __acc_likely
-# undef __acc_unlikely
# undef __lzo_likely
# undef __lzo_unlikely
-# define __acc_likely(e) (e)
-# define __acc_unlikely(e) (e)
# define __lzo_likely(e) (e)
# define __lzo_unlikely(e) (e)
#endif
+#undef _
+#undef __
+#undef ___
+#undef ____
+#undef _p0
+#undef _p1
+#undef _p2
+#undef _p3
+#undef _p4
+#undef _s0
+#undef _s1
+#undef _s2
+#undef _s3
+#undef _s4
+#undef _ww
+
#if 1
# define LZO_BYTE(x) ((unsigned char) (x))
#else
@@ -2097,84 +3220,548 @@ LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_uintptr_t) >= sizeof(lzo_voidp))
#define LZO_SIZE(bits) (1u << (bits))
#define LZO_MASK(bits) (LZO_SIZE(bits) - 1)
-#define LZO_LSIZE(bits) (1ul << (bits))
-#define LZO_LMASK(bits) (LZO_LSIZE(bits) - 1)
-
#define LZO_USIZE(bits) ((lzo_uint) 1 << (bits))
#define LZO_UMASK(bits) (LZO_USIZE(bits) - 1)
#if !defined(DMUL)
#if 0
-# define DMUL(a,b) ((lzo_xint) ((lzo_uint32)(a) * (lzo_uint32)(b)))
+# define DMUL(a,b) ((lzo_xint) ((lzo_uint32_t)(a) * (lzo_uint32_t)(b)))
#else
# define DMUL(a,b) ((lzo_xint) ((a) * (b)))
#endif
#endif
-#if 1 && (LZO_ARCH_AMD64 || LZO_ARCH_I386 || LZO_ARCH_POWERPC)
-# if (LZO_SIZEOF_SHORT == 2)
-# define LZO_UNALIGNED_OK_2 1
-# endif
-# if (LZO_SIZEOF_INT == 4)
-# define LZO_UNALIGNED_OK_4 1
-# endif
+#ifndef __LZO_FUNC_H
+#define __LZO_FUNC_H 1
+
+#if !defined(LZO_BITOPS_USE_ASM_BITSCAN) && !defined(LZO_BITOPS_USE_GNUC_BITSCAN) && !defined(LZO_BITOPS_USE_MSC_BITSCAN)
+#if 1 && (LZO_ARCH_AMD64) && (LZO_CC_GNUC && (LZO_CC_GNUC < 0x040000ul)) && (LZO_ASM_SYNTAX_GNUC)
+#define LZO_BITOPS_USE_ASM_BITSCAN 1
+#elif (LZO_CC_CLANG || (LZO_CC_GNUC >= 0x030400ul) || (LZO_CC_INTELC_GNUC && (__INTEL_COMPILER >= 1000)) || (LZO_CC_LLVM && (!defined(__llvm_tools_version__) || (__llvm_tools_version__+0 >= 0x010500ul))))
+#define LZO_BITOPS_USE_GNUC_BITSCAN 1
+#elif (LZO_OS_WIN32 || LZO_OS_WIN64) && ((LZO_CC_INTELC_MSC && (__INTEL_COMPILER >= 1010)) || (LZO_CC_MSC && (_MSC_VER >= 1400)))
+#define LZO_BITOPS_USE_MSC_BITSCAN 1
+#if (LZO_CC_MSC) && (LZO_ARCH_AMD64 || LZO_ARCH_I386)
+#include <intrin.h>
#endif
-#if 1 && (LZO_ARCH_AMD64)
-# if defined(LZO_UINT64_MAX)
-# define LZO_UNALIGNED_OK_8 1
-# endif
+#if (LZO_CC_MSC) && (LZO_ARCH_AMD64 || LZO_ARCH_I386)
+#pragma intrinsic(_BitScanReverse)
+#pragma intrinsic(_BitScanForward)
#endif
-#if (LZO_CFG_NO_UNALIGNED)
-# undef LZO_UNALIGNED_OK_2
-# undef LZO_UNALIGNED_OK_4
-# undef LZO_UNALIGNED_OK_8
-#endif
-
-#undef UA_GET16
-#undef UA_SET16
-#undef UA_COPY16
-#undef UA_GET32
-#undef UA_SET32
-#undef UA_COPY32
-#undef UA_GET64
-#undef UA_SET64
-#undef UA_COPY64
-#if defined(LZO_UNALIGNED_OK_2)
- LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(unsigned short) == 2)
-# if 1 && defined(ACC_UA_COPY16)
-# define UA_GET16 ACC_UA_GET16
-# define UA_SET16 ACC_UA_SET16
-# define UA_COPY16 ACC_UA_COPY16
-# else
-# define UA_GET16(p) (* (__lzo_ua_volatile const lzo_ushortp) (__lzo_ua_volatile const lzo_voidp) (p))
-# define UA_SET16(p,v) ((* (__lzo_ua_volatile lzo_ushortp) (__lzo_ua_volatile lzo_voidp) (p)) = (unsigned short) (v))
-# define UA_COPY16(d,s) UA_SET16(d, UA_GET16(s))
-# endif
+#if (LZO_CC_MSC) && (LZO_ARCH_AMD64)
+#pragma intrinsic(_BitScanReverse64)
+#pragma intrinsic(_BitScanForward64)
#endif
-#if defined(LZO_UNALIGNED_OK_4) || defined(LZO_ALIGNED_OK_4)
- LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_uint32) == 4)
-# if 1 && defined(ACC_UA_COPY32)
-# define UA_GET32 ACC_UA_GET32
-# define UA_SET32 ACC_UA_SET32
-# define UA_COPY32 ACC_UA_COPY32
-# else
-# define UA_GET32(p) (* (__lzo_ua_volatile const lzo_uint32p) (__lzo_ua_volatile const lzo_voidp) (p))
-# define UA_SET32(p,v) ((* (__lzo_ua_volatile lzo_uint32p) (__lzo_ua_volatile lzo_voidp) (p)) = (lzo_uint32) (v))
-# define UA_COPY32(d,s) UA_SET32(d, UA_GET32(s))
-# endif
#endif
-#if defined(LZO_UNALIGNED_OK_8)
- LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_uint64) == 8)
-# if 1 && defined(ACC_UA_COPY64)
-# define UA_GET64 ACC_UA_GET64
-# define UA_SET64 ACC_UA_SET64
-# define UA_COPY64 ACC_UA_COPY64
-# else
-# define UA_GET64(p) (* (__lzo_ua_volatile const lzo_uint64p) (__lzo_ua_volatile const lzo_voidp) (p))
-# define UA_SET64(p,v) ((* (__lzo_ua_volatile lzo_uint64p) (__lzo_ua_volatile lzo_voidp) (p)) = (lzo_uint64) (v))
-# define UA_COPY64(d,s) UA_SET64(d, UA_GET64(s))
-# endif
+#endif
+
+__lzo_static_forceinline unsigned lzo_bitops_ctlz32_func(lzo_uint32_t v)
+{
+#if (LZO_BITOPS_USE_MSC_BITSCAN) && (LZO_ARCH_AMD64 || LZO_ARCH_I386)
+ unsigned long r; (void) _BitScanReverse(&r, v); return (unsigned) r ^ 31;
+#define lzo_bitops_ctlz32(v) lzo_bitops_ctlz32_func(v)
+#elif (LZO_BITOPS_USE_ASM_BITSCAN) && (LZO_ARCH_AMD64 || LZO_ARCH_I386) && (LZO_ASM_SYNTAX_GNUC)
+ lzo_uint32_t r;
+ __asm__("bsr %1,%0" : "=r" (r) : "rm" (v) __LZO_ASM_CLOBBER_LIST_CC);
+ return (unsigned) r ^ 31;
+#define lzo_bitops_ctlz32(v) lzo_bitops_ctlz32_func(v)
+#elif (LZO_BITOPS_USE_GNUC_BITSCAN) && (LZO_SIZEOF_INT == 4)
+ unsigned r; r = (unsigned) __builtin_clz(v); return r;
+#define lzo_bitops_ctlz32(v) ((unsigned) __builtin_clz(v))
+#else
+ LZO_UNUSED(v); return 0;
+#endif
+}
+
+#if defined(lzo_uint64_t)
+__lzo_static_forceinline unsigned lzo_bitops_ctlz64_func(lzo_uint64_t v)
+{
+#if (LZO_BITOPS_USE_MSC_BITSCAN) && (LZO_ARCH_AMD64)
+ unsigned long r; (void) _BitScanReverse64(&r, v); return (unsigned) r ^ 63;
+#define lzo_bitops_ctlz64(v) lzo_bitops_ctlz64_func(v)
+#elif (LZO_BITOPS_USE_ASM_BITSCAN) && (LZO_ARCH_AMD64) && (LZO_ASM_SYNTAX_GNUC)
+ lzo_uint64_t r;
+ __asm__("bsr %1,%0" : "=r" (r) : "rm" (v) __LZO_ASM_CLOBBER_LIST_CC);
+ return (unsigned) r ^ 63;
+#define lzo_bitops_ctlz64(v) lzo_bitops_ctlz64_func(v)
+#elif (LZO_BITOPS_USE_GNUC_BITSCAN) && (LZO_SIZEOF_LONG == 8) && (LZO_WORDSIZE >= 8)
+ unsigned r; r = (unsigned) __builtin_clzl(v); return r;
+#define lzo_bitops_ctlz64(v) ((unsigned) __builtin_clzl(v))
+#elif (LZO_BITOPS_USE_GNUC_BITSCAN) && (LZO_SIZEOF_LONG_LONG == 8) && (LZO_WORDSIZE >= 8)
+ unsigned r; r = (unsigned) __builtin_clzll(v); return r;
+#define lzo_bitops_ctlz64(v) ((unsigned) __builtin_clzll(v))
+#else
+ LZO_UNUSED(v); return 0;
+#endif
+}
+#endif
+
+__lzo_static_forceinline unsigned lzo_bitops_cttz32_func(lzo_uint32_t v)
+{
+#if (LZO_BITOPS_USE_MSC_BITSCAN) && (LZO_ARCH_AMD64 || LZO_ARCH_I386)
+ unsigned long r; (void) _BitScanForward(&r, v); return (unsigned) r;
+#define lzo_bitops_cttz32(v) lzo_bitops_cttz32_func(v)
+#elif (LZO_BITOPS_USE_ASM_BITSCAN) && (LZO_ARCH_AMD64 || LZO_ARCH_I386) && (LZO_ASM_SYNTAX_GNUC)
+ lzo_uint32_t r;
+ __asm__("bsf %1,%0" : "=r" (r) : "rm" (v) __LZO_ASM_CLOBBER_LIST_CC);
+ return (unsigned) r;
+#define lzo_bitops_cttz32(v) lzo_bitops_cttz32_func(v)
+#elif (LZO_BITOPS_USE_GNUC_BITSCAN) && (LZO_SIZEOF_INT >= 4)
+ unsigned r; r = (unsigned) __builtin_ctz(v); return r;
+#define lzo_bitops_cttz32(v) ((unsigned) __builtin_ctz(v))
+#else
+ LZO_UNUSED(v); return 0;
+#endif
+}
+
+#if defined(lzo_uint64_t)
+__lzo_static_forceinline unsigned lzo_bitops_cttz64_func(lzo_uint64_t v)
+{
+#if (LZO_BITOPS_USE_MSC_BITSCAN) && (LZO_ARCH_AMD64)
+ unsigned long r; (void) _BitScanForward64(&r, v); return (unsigned) r;
+#define lzo_bitops_cttz64(v) lzo_bitops_cttz64_func(v)
+#elif (LZO_BITOPS_USE_ASM_BITSCAN) && (LZO_ARCH_AMD64) && (LZO_ASM_SYNTAX_GNUC)
+ lzo_uint64_t r;
+ __asm__("bsf %1,%0" : "=r" (r) : "rm" (v) __LZO_ASM_CLOBBER_LIST_CC);
+ return (unsigned) r;
+#define lzo_bitops_cttz64(v) lzo_bitops_cttz64_func(v)
+#elif (LZO_BITOPS_USE_GNUC_BITSCAN) && (LZO_SIZEOF_LONG >= 8) && (LZO_WORDSIZE >= 8)
+ unsigned r; r = (unsigned) __builtin_ctzl(v); return r;
+#define lzo_bitops_cttz64(v) ((unsigned) __builtin_ctzl(v))
+#elif (LZO_BITOPS_USE_GNUC_BITSCAN) && (LZO_SIZEOF_LONG_LONG >= 8) && (LZO_WORDSIZE >= 8)
+ unsigned r; r = (unsigned) __builtin_ctzll(v); return r;
+#define lzo_bitops_cttz64(v) ((unsigned) __builtin_ctzll(v))
+#else
+ LZO_UNUSED(v); return 0;
+#endif
+}
+#endif
+
+#if 1 && (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || (LZO_CC_GNUC >= 0x020700ul) || LZO_CC_INTELC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE || LZO_CC_PGI)
+static void __attribute__((__unused__))
+#else
+__lzo_static_forceinline void
+#endif
+lzo_bitops_unused_funcs(void)
+{
+ LZO_UNUSED_FUNC(lzo_bitops_ctlz32_func);
+ LZO_UNUSED_FUNC(lzo_bitops_cttz32_func);
+#if defined(lzo_uint64_t)
+ LZO_UNUSED_FUNC(lzo_bitops_ctlz64_func);
+ LZO_UNUSED_FUNC(lzo_bitops_cttz64_func);
+#endif
+ LZO_UNUSED_FUNC(lzo_bitops_unused_funcs);
+}
+
+#if defined(__lzo_alignof) && !(LZO_CFG_NO_UNALIGNED)
+#ifndef __lzo_memops_tcheck
+#define __lzo_memops_tcheck(t,a,b) ((void)0, sizeof(t) == (a) && __lzo_alignof(t) == (b))
+#endif
+#endif
+#ifndef lzo_memops_TU0p
+#define lzo_memops_TU0p void __LZO_MMODEL *
+#endif
+#ifndef lzo_memops_TU1p
+#define lzo_memops_TU1p unsigned char __LZO_MMODEL *
+#endif
+#ifndef lzo_memops_TU2p
+#if (LZO_OPT_UNALIGNED16)
+typedef lzo_uint16_t __lzo_may_alias lzo_memops_TU2;
+#define lzo_memops_TU2p volatile lzo_memops_TU2 *
+#elif defined(__lzo_byte_struct)
+__lzo_byte_struct(lzo_memops_TU2_struct,2)
+typedef struct lzo_memops_TU2_struct lzo_memops_TU2;
+#else
+struct lzo_memops_TU2_struct { unsigned char a[2]; } __lzo_may_alias;
+typedef struct lzo_memops_TU2_struct lzo_memops_TU2;
+#endif
+#ifndef lzo_memops_TU2p
+#define lzo_memops_TU2p lzo_memops_TU2 *
+#endif
+#endif
+#ifndef lzo_memops_TU4p
+#if (LZO_OPT_UNALIGNED32)
+typedef lzo_uint32_t __lzo_may_alias lzo_memops_TU4;
+#define lzo_memops_TU4p volatile lzo_memops_TU4 __LZO_MMODEL *
+#elif defined(__lzo_byte_struct)
+__lzo_byte_struct(lzo_memops_TU4_struct,4)
+typedef struct lzo_memops_TU4_struct lzo_memops_TU4;
+#else
+struct lzo_memops_TU4_struct { unsigned char a[4]; } __lzo_may_alias;
+typedef struct lzo_memops_TU4_struct lzo_memops_TU4;
+#endif
+#ifndef lzo_memops_TU4p
+#define lzo_memops_TU4p lzo_memops_TU4 __LZO_MMODEL *
+#endif
+#endif
+#ifndef lzo_memops_TU8p
+#if (LZO_OPT_UNALIGNED64)
+typedef lzo_uint64_t __lzo_may_alias lzo_memops_TU8;
+#define lzo_memops_TU8p volatile lzo_memops_TU8 __LZO_MMODEL *
+#elif defined(__lzo_byte_struct)
+__lzo_byte_struct(lzo_memops_TU8_struct,8)
+typedef struct lzo_memops_TU8_struct lzo_memops_TU8;
+#else
+struct lzo_memops_TU8_struct { unsigned char a[8]; } __lzo_may_alias;
+typedef struct lzo_memops_TU8_struct lzo_memops_TU8;
+#endif
+#ifndef lzo_memops_TU8p
+#define lzo_memops_TU8p lzo_memops_TU8 __LZO_MMODEL *
+#endif
+#endif
+#ifndef lzo_memops_set_TU1p
+#define lzo_memops_set_TU1p volatile lzo_memops_TU1p
+#endif
+#ifndef lzo_memops_move_TU1p
+#define lzo_memops_move_TU1p lzo_memops_TU1p
+#endif
+#define LZO_MEMOPS_SET1(dd,cc) \
+ LZO_BLOCK_BEGIN \
+ lzo_memops_set_TU1p d__1 = (lzo_memops_set_TU1p) (lzo_memops_TU0p) (dd); \
+ d__1[0] = LZO_BYTE(cc); \
+ LZO_BLOCK_END
+#define LZO_MEMOPS_SET2(dd,cc) \
+ LZO_BLOCK_BEGIN \
+ lzo_memops_set_TU1p d__2 = (lzo_memops_set_TU1p) (lzo_memops_TU0p) (dd); \
+ d__2[0] = LZO_BYTE(cc); d__2[1] = LZO_BYTE(cc); \
+ LZO_BLOCK_END
+#define LZO_MEMOPS_SET3(dd,cc) \
+ LZO_BLOCK_BEGIN \
+ lzo_memops_set_TU1p d__3 = (lzo_memops_set_TU1p) (lzo_memops_TU0p) (dd); \
+ d__3[0] = LZO_BYTE(cc); d__3[1] = LZO_BYTE(cc); d__3[2] = LZO_BYTE(cc); \
+ LZO_BLOCK_END
+#define LZO_MEMOPS_SET4(dd,cc) \
+ LZO_BLOCK_BEGIN \
+ lzo_memops_set_TU1p d__4 = (lzo_memops_set_TU1p) (lzo_memops_TU0p) (dd); \
+ d__4[0] = LZO_BYTE(cc); d__4[1] = LZO_BYTE(cc); d__4[2] = LZO_BYTE(cc); d__4[3] = LZO_BYTE(cc); \
+ LZO_BLOCK_END
+#define LZO_MEMOPS_MOVE1(dd,ss) \
+ LZO_BLOCK_BEGIN \
+ lzo_memops_move_TU1p d__1 = (lzo_memops_move_TU1p) (lzo_memops_TU0p) (dd); \
+ const lzo_memops_move_TU1p s__1 = (const lzo_memops_move_TU1p) (const lzo_memops_TU0p) (ss); \
+ d__1[0] = s__1[0]; \
+ LZO_BLOCK_END
+#define LZO_MEMOPS_MOVE2(dd,ss) \
+ LZO_BLOCK_BEGIN \
+ lzo_memops_move_TU1p d__2 = (lzo_memops_move_TU1p) (lzo_memops_TU0p) (dd); \
+ const lzo_memops_move_TU1p s__2 = (const lzo_memops_move_TU1p) (const lzo_memops_TU0p) (ss); \
+ d__2[0] = s__2[0]; d__2[1] = s__2[1]; \
+ LZO_BLOCK_END
+#define LZO_MEMOPS_MOVE3(dd,ss) \
+ LZO_BLOCK_BEGIN \
+ lzo_memops_move_TU1p d__3 = (lzo_memops_move_TU1p) (lzo_memops_TU0p) (dd); \
+ const lzo_memops_move_TU1p s__3 = (const lzo_memops_move_TU1p) (const lzo_memops_TU0p) (ss); \
+ d__3[0] = s__3[0]; d__3[1] = s__3[1]; d__3[2] = s__3[2]; \
+ LZO_BLOCK_END
+#define LZO_MEMOPS_MOVE4(dd,ss) \
+ LZO_BLOCK_BEGIN \
+ lzo_memops_move_TU1p d__4 = (lzo_memops_move_TU1p) (lzo_memops_TU0p) (dd); \
+ const lzo_memops_move_TU1p s__4 = (const lzo_memops_move_TU1p) (const lzo_memops_TU0p) (ss); \
+ d__4[0] = s__4[0]; d__4[1] = s__4[1]; d__4[2] = s__4[2]; d__4[3] = s__4[3]; \
+ LZO_BLOCK_END
+#define LZO_MEMOPS_MOVE8(dd,ss) \
+ LZO_BLOCK_BEGIN \
+ lzo_memops_move_TU1p d__8 = (lzo_memops_move_TU1p) (lzo_memops_TU0p) (dd); \
+ const lzo_memops_move_TU1p s__8 = (const lzo_memops_move_TU1p) (const lzo_memops_TU0p) (ss); \
+ d__8[0] = s__8[0]; d__8[1] = s__8[1]; d__8[2] = s__8[2]; d__8[3] = s__8[3]; \
+ d__8[4] = s__8[4]; d__8[5] = s__8[5]; d__8[6] = s__8[6]; d__8[7] = s__8[7]; \
+ LZO_BLOCK_END
+LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(*(lzo_memops_TU1p)0)==1)
+#define LZO_MEMOPS_COPY1(dd,ss) LZO_MEMOPS_MOVE1(dd,ss)
+#if (LZO_OPT_UNALIGNED16)
+LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(*(lzo_memops_TU2p)0)==2)
+#define LZO_MEMOPS_COPY2(dd,ss) \
+ * (lzo_memops_TU2p) (lzo_memops_TU0p) (dd) = * (const lzo_memops_TU2p) (const lzo_memops_TU0p) (ss)
+#elif defined(__lzo_memops_tcheck)
+#define LZO_MEMOPS_COPY2(dd,ss) \
+ LZO_BLOCK_BEGIN if (__lzo_memops_tcheck(lzo_memops_TU2,2,1)) { \
+ * (lzo_memops_TU2p) (lzo_memops_TU0p) (dd) = * (const lzo_memops_TU2p) (const lzo_memops_TU0p) (ss); \
+ } else { LZO_MEMOPS_MOVE2(dd,ss); } LZO_BLOCK_END
+#else
+#define LZO_MEMOPS_COPY2(dd,ss) LZO_MEMOPS_MOVE2(dd,ss)
+#endif
+#if (LZO_OPT_UNALIGNED32)
+LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(*(lzo_memops_TU4p)0)==4)
+#define LZO_MEMOPS_COPY4(dd,ss) \
+ * (lzo_memops_TU4p) (lzo_memops_TU0p) (dd) = * (const lzo_memops_TU4p) (const lzo_memops_TU0p) (ss)
+#elif defined(__lzo_memops_tcheck)
+#define LZO_MEMOPS_COPY4(dd,ss) \
+ LZO_BLOCK_BEGIN if (__lzo_memops_tcheck(lzo_memops_TU4,4,1)) { \
+ * (lzo_memops_TU4p) (lzo_memops_TU0p) (dd) = * (const lzo_memops_TU4p) (const lzo_memops_TU0p) (ss); \
+ } else { LZO_MEMOPS_MOVE4(dd,ss); } LZO_BLOCK_END
+#else
+#define LZO_MEMOPS_COPY4(dd,ss) LZO_MEMOPS_MOVE4(dd,ss)
+#endif
+#if (LZO_WORDSIZE != 8)
+#define LZO_MEMOPS_COPY8(dd,ss) \
+ LZO_BLOCK_BEGIN LZO_MEMOPS_COPY4(dd,ss); LZO_MEMOPS_COPY4((lzo_memops_TU1p)(lzo_memops_TU0p)(dd)+4,(const lzo_memops_TU1p)(const lzo_memops_TU0p)(ss)+4); LZO_BLOCK_END
+#else
+#if (LZO_OPT_UNALIGNED64)
+LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(*(lzo_memops_TU8p)0)==8)
+#define LZO_MEMOPS_COPY8(dd,ss) \
+ * (lzo_memops_TU8p) (lzo_memops_TU0p) (dd) = * (const lzo_memops_TU8p) (const lzo_memops_TU0p) (ss)
+#elif (LZO_OPT_UNALIGNED32)
+#define LZO_MEMOPS_COPY8(dd,ss) \
+ LZO_BLOCK_BEGIN LZO_MEMOPS_COPY4(dd,ss); LZO_MEMOPS_COPY4((lzo_memops_TU1p)(lzo_memops_TU0p)(dd)+4,(const lzo_memops_TU1p)(const lzo_memops_TU0p)(ss)+4); LZO_BLOCK_END
+#elif defined(__lzo_memops_tcheck)
+#define LZO_MEMOPS_COPY8(dd,ss) \
+ LZO_BLOCK_BEGIN if (__lzo_memops_tcheck(lzo_memops_TU8,8,1)) { \
+ * (lzo_memops_TU8p) (lzo_memops_TU0p) (dd) = * (const lzo_memops_TU8p) (const lzo_memops_TU0p) (ss); \
+ } else { LZO_MEMOPS_MOVE8(dd,ss); } LZO_BLOCK_END
+#else
+#define LZO_MEMOPS_COPY8(dd,ss) LZO_MEMOPS_MOVE8(dd,ss)
+#endif
+#endif
+#define LZO_MEMOPS_COPYN(dd,ss,nn) \
+ LZO_BLOCK_BEGIN \
+ lzo_memops_TU1p d__n = (lzo_memops_TU1p) (lzo_memops_TU0p) (dd); \
+ const lzo_memops_TU1p s__n = (const lzo_memops_TU1p) (const lzo_memops_TU0p) (ss); \
+ lzo_uint n__n = (nn); \
+ while ((void)0, n__n >= 8) { LZO_MEMOPS_COPY8(d__n, s__n); d__n += 8; s__n += 8; n__n -= 8; } \
+ if ((void)0, n__n >= 4) { LZO_MEMOPS_COPY4(d__n, s__n); d__n += 4; s__n += 4; n__n -= 4; } \
+ if ((void)0, n__n > 0) do { *d__n++ = *s__n++; } while (--n__n > 0); \
+ LZO_BLOCK_END
+
+__lzo_static_forceinline lzo_uint16_t lzo_memops_get_le16(const lzo_voidp ss)
+{
+ lzo_uint16_t v;
+#if (LZO_ABI_LITTLE_ENDIAN)
+ LZO_MEMOPS_COPY2(&v, ss);
+#elif (LZO_OPT_UNALIGNED16 && LZO_ARCH_POWERPC && LZO_ABI_BIG_ENDIAN) && (LZO_ASM_SYNTAX_GNUC)
+ const lzo_memops_TU2p s = (const lzo_memops_TU2p) ss;
+ unsigned long vv;
+ __asm__("lhbrx %0,0,%1" : "=r" (vv) : "r" (s), "m" (*s));
+ v = (lzo_uint16_t) vv;
+#else
+ const lzo_memops_TU1p s = (const lzo_memops_TU1p) ss;
+ v = (lzo_uint16_t) (((lzo_uint16_t)s[0]) | ((lzo_uint16_t)s[1] << 8));
+#endif
+ return v;
+}
+#if (LZO_OPT_UNALIGNED16) && (LZO_ABI_LITTLE_ENDIAN)
+#define LZO_MEMOPS_GET_LE16(ss) * (const lzo_memops_TU2p) (const lzo_memops_TU0p) (ss)
+#else
+#define LZO_MEMOPS_GET_LE16(ss) lzo_memops_get_le16(ss)
+#endif
+
+__lzo_static_forceinline lzo_uint32_t lzo_memops_get_le32(const lzo_voidp ss)
+{
+ lzo_uint32_t v;
+#if (LZO_ABI_LITTLE_ENDIAN)
+ LZO_MEMOPS_COPY4(&v, ss);
+#elif (LZO_OPT_UNALIGNED32 && LZO_ARCH_POWERPC && LZO_ABI_BIG_ENDIAN) && (LZO_ASM_SYNTAX_GNUC)
+ const lzo_memops_TU4p s = (const lzo_memops_TU4p) ss;
+ unsigned long vv;
+ __asm__("lwbrx %0,0,%1" : "=r" (vv) : "r" (s), "m" (*s));
+ v = (lzo_uint32_t) vv;
+#else
+ const lzo_memops_TU1p s = (const lzo_memops_TU1p) ss;
+ v = (lzo_uint32_t) (((lzo_uint32_t)s[0]) | ((lzo_uint32_t)s[1] << 8) | ((lzo_uint32_t)s[2] << 16) | ((lzo_uint32_t)s[3] << 24));
+#endif
+ return v;
+}
+#if (LZO_OPT_UNALIGNED32) && (LZO_ABI_LITTLE_ENDIAN)
+#define LZO_MEMOPS_GET_LE32(ss) * (const lzo_memops_TU4p) (const lzo_memops_TU0p) (ss)
+#else
+#define LZO_MEMOPS_GET_LE32(ss) lzo_memops_get_le32(ss)
+#endif
+
+#if (LZO_OPT_UNALIGNED64) && (LZO_ABI_LITTLE_ENDIAN)
+#define LZO_MEMOPS_GET_LE64(ss) * (const lzo_memops_TU8p) (const lzo_memops_TU0p) (ss)
+#endif
+
+__lzo_static_forceinline lzo_uint16_t lzo_memops_get_ne16(const lzo_voidp ss)
+{
+ lzo_uint16_t v;
+ LZO_MEMOPS_COPY2(&v, ss);
+ return v;
+}
+#if (LZO_OPT_UNALIGNED16)
+#define LZO_MEMOPS_GET_NE16(ss) * (const lzo_memops_TU2p) (const lzo_memops_TU0p) (ss)
+#else
+#define LZO_MEMOPS_GET_NE16(ss) lzo_memops_get_ne16(ss)
+#endif
+
+__lzo_static_forceinline lzo_uint32_t lzo_memops_get_ne32(const lzo_voidp ss)
+{
+ lzo_uint32_t v;
+ LZO_MEMOPS_COPY4(&v, ss);
+ return v;
+}
+#if (LZO_OPT_UNALIGNED32)
+#define LZO_MEMOPS_GET_NE32(ss) * (const lzo_memops_TU4p) (const lzo_memops_TU0p) (ss)
+#else
+#define LZO_MEMOPS_GET_NE32(ss) lzo_memops_get_ne32(ss)
+#endif
+
+#if (LZO_OPT_UNALIGNED64)
+#define LZO_MEMOPS_GET_NE64(ss) * (const lzo_memops_TU8p) (const lzo_memops_TU0p) (ss)
+#endif
+
+__lzo_static_forceinline void lzo_memops_put_le16(lzo_voidp dd, lzo_uint16_t vv)
+{
+#if (LZO_ABI_LITTLE_ENDIAN)
+ LZO_MEMOPS_COPY2(dd, &vv);
+#elif (LZO_OPT_UNALIGNED16 && LZO_ARCH_POWERPC && LZO_ABI_BIG_ENDIAN) && (LZO_ASM_SYNTAX_GNUC)
+ lzo_memops_TU2p d = (lzo_memops_TU2p) dd;
+ unsigned long v = vv;
+ __asm__("sthbrx %2,0,%1" : "=m" (*d) : "r" (d), "r" (v));
+#else
+ lzo_memops_TU1p d = (lzo_memops_TU1p) dd;
+ d[0] = LZO_BYTE((vv ) & 0xff);
+ d[1] = LZO_BYTE((vv >> 8) & 0xff);
+#endif
+}
+#if (LZO_OPT_UNALIGNED16) && (LZO_ABI_LITTLE_ENDIAN)
+#define LZO_MEMOPS_PUT_LE16(dd,vv) (* (lzo_memops_TU2p) (lzo_memops_TU0p) (dd) = (vv))
+#else
+#define LZO_MEMOPS_PUT_LE16(dd,vv) lzo_memops_put_le16(dd,vv)
+#endif
+
+__lzo_static_forceinline void lzo_memops_put_le32(lzo_voidp dd, lzo_uint32_t vv)
+{
+#if (LZO_ABI_LITTLE_ENDIAN)
+ LZO_MEMOPS_COPY4(dd, &vv);
+#elif (LZO_OPT_UNALIGNED32 && LZO_ARCH_POWERPC && LZO_ABI_BIG_ENDIAN) && (LZO_ASM_SYNTAX_GNUC)
+ lzo_memops_TU4p d = (lzo_memops_TU4p) dd;
+ unsigned long v = vv;
+ __asm__("stwbrx %2,0,%1" : "=m" (*d) : "r" (d), "r" (v));
+#else
+ lzo_memops_TU1p d = (lzo_memops_TU1p) dd;
+ d[0] = LZO_BYTE((vv ) & 0xff);
+ d[1] = LZO_BYTE((vv >> 8) & 0xff);
+ d[2] = LZO_BYTE((vv >> 16) & 0xff);
+ d[3] = LZO_BYTE((vv >> 24) & 0xff);
+#endif
+}
+#if (LZO_OPT_UNALIGNED32) && (LZO_ABI_LITTLE_ENDIAN)
+#define LZO_MEMOPS_PUT_LE32(dd,vv) (* (lzo_memops_TU4p) (lzo_memops_TU0p) (dd) = (vv))
+#else
+#define LZO_MEMOPS_PUT_LE32(dd,vv) lzo_memops_put_le32(dd,vv)
+#endif
+
+__lzo_static_forceinline void lzo_memops_put_ne16(lzo_voidp dd, lzo_uint16_t vv)
+{
+ LZO_MEMOPS_COPY2(dd, &vv);
+}
+#if (LZO_OPT_UNALIGNED16)
+#define LZO_MEMOPS_PUT_NE16(dd,vv) (* (lzo_memops_TU2p) (lzo_memops_TU0p) (dd) = (vv))
+#else
+#define LZO_MEMOPS_PUT_NE16(dd,vv) lzo_memops_put_ne16(dd,vv)
+#endif
+
+__lzo_static_forceinline void lzo_memops_put_ne32(lzo_voidp dd, lzo_uint32_t vv)
+{
+ LZO_MEMOPS_COPY4(dd, &vv);
+}
+#if (LZO_OPT_UNALIGNED32)
+#define LZO_MEMOPS_PUT_NE32(dd,vv) (* (lzo_memops_TU4p) (lzo_memops_TU0p) (dd) = (vv))
+#else
+#define LZO_MEMOPS_PUT_NE32(dd,vv) lzo_memops_put_ne32(dd,vv)
+#endif
+
+#if 1 && (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || (LZO_CC_GNUC >= 0x020700ul) || LZO_CC_INTELC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE || LZO_CC_PGI)
+static void __attribute__((__unused__))
+#else
+__lzo_static_forceinline void
+#endif
+lzo_memops_unused_funcs(void)
+{
+ LZO_UNUSED_FUNC(lzo_memops_get_le16);
+ LZO_UNUSED_FUNC(lzo_memops_get_le32);
+ LZO_UNUSED_FUNC(lzo_memops_get_ne16);
+ LZO_UNUSED_FUNC(lzo_memops_get_ne32);
+ LZO_UNUSED_FUNC(lzo_memops_put_le16);
+ LZO_UNUSED_FUNC(lzo_memops_put_le32);
+ LZO_UNUSED_FUNC(lzo_memops_put_ne16);
+ LZO_UNUSED_FUNC(lzo_memops_put_ne32);
+ LZO_UNUSED_FUNC(lzo_memops_unused_funcs);
+}
+
+#endif
+
+#ifndef UA_SET1
+#define UA_SET1 LZO_MEMOPS_SET1
+#endif
+#ifndef UA_SET2
+#define UA_SET2 LZO_MEMOPS_SET2
+#endif
+#ifndef UA_SET3
+#define UA_SET3 LZO_MEMOPS_SET3
+#endif
+#ifndef UA_SET4
+#define UA_SET4 LZO_MEMOPS_SET4
+#endif
+#ifndef UA_MOVE1
+#define UA_MOVE1 LZO_MEMOPS_MOVE1
+#endif
+#ifndef UA_MOVE2
+#define UA_MOVE2 LZO_MEMOPS_MOVE2
+#endif
+#ifndef UA_MOVE3
+#define UA_MOVE3 LZO_MEMOPS_MOVE3
+#endif
+#ifndef UA_MOVE4
+#define UA_MOVE4 LZO_MEMOPS_MOVE4
+#endif
+#ifndef UA_MOVE8
+#define UA_MOVE8 LZO_MEMOPS_MOVE8
+#endif
+#ifndef UA_COPY1
+#define UA_COPY1 LZO_MEMOPS_COPY1
+#endif
+#ifndef UA_COPY2
+#define UA_COPY2 LZO_MEMOPS_COPY2
+#endif
+#ifndef UA_COPY3
+#define UA_COPY3 LZO_MEMOPS_COPY3
+#endif
+#ifndef UA_COPY4
+#define UA_COPY4 LZO_MEMOPS_COPY4
+#endif
+#ifndef UA_COPY8
+#define UA_COPY8 LZO_MEMOPS_COPY8
+#endif
+#ifndef UA_COPYN
+#define UA_COPYN LZO_MEMOPS_COPYN
+#endif
+#ifndef UA_COPYN_X
+#define UA_COPYN_X LZO_MEMOPS_COPYN
+#endif
+#ifndef UA_GET_LE16
+#define UA_GET_LE16 LZO_MEMOPS_GET_LE16
+#endif
+#ifndef UA_GET_LE32
+#define UA_GET_LE32 LZO_MEMOPS_GET_LE32
+#endif
+#ifdef LZO_MEMOPS_GET_LE64
+#ifndef UA_GET_LE64
+#define UA_GET_LE64 LZO_MEMOPS_GET_LE64
+#endif
+#endif
+#ifndef UA_GET_NE16
+#define UA_GET_NE16 LZO_MEMOPS_GET_NE16
+#endif
+#ifndef UA_GET_NE32
+#define UA_GET_NE32 LZO_MEMOPS_GET_NE32
+#endif
+#ifdef LZO_MEMOPS_GET_NE64
+#ifndef UA_GET_NE64
+#define UA_GET_NE64 LZO_MEMOPS_GET_NE64
+#endif
+#endif
+#ifndef UA_PUT_LE16
+#define UA_PUT_LE16 LZO_MEMOPS_PUT_LE16
+#endif
+#ifndef UA_PUT_LE32
+#define UA_PUT_LE32 LZO_MEMOPS_PUT_LE32
+#endif
+#ifndef UA_PUT_NE16
+#define UA_PUT_NE16 LZO_MEMOPS_PUT_NE16
+#endif
+#ifndef UA_PUT_NE32
+#define UA_PUT_NE32 LZO_MEMOPS_PUT_NE32
#endif
#define MEMCPY8_DS(dest,src,len) \
@@ -2195,25 +3782,10 @@ LZO_EXTERN(const lzo_bytep) lzo_copyright(void);
extern "C" {
#endif
-#if !defined(lzo_uintptr_t)
-# if (__LZO_MMODEL_HUGE)
-# define lzo_uintptr_t unsigned long
-# else
-# define lzo_uintptr_t acc_uintptr_t
-# ifdef __ACC_INTPTR_T_IS_POINTER
-# define __LZO_UINTPTR_T_IS_POINTER 1
-# endif
-# endif
-#endif
-
#if (LZO_ARCH_I086)
-#define PTR(a) ((lzo_bytep) (a))
-#define PTR_ALIGNED_4(a) ((ACC_PTR_FP_OFF(a) & 3) == 0)
-#define PTR_ALIGNED2_4(a,b) (((ACC_PTR_FP_OFF(a) | ACC_PTR_FP_OFF(b)) & 3) == 0)
+#error "LZO_ARCH_I086 is unsupported"
#elif (LZO_MM_PVP)
-#define PTR(a) ((lzo_bytep) (a))
-#define PTR_ALIGNED_8(a) ((((lzo_uintptr_t)(a)) >> 61) == 0)
-#define PTR_ALIGNED2_8(a,b) ((((lzo_uintptr_t)(a)|(lzo_uintptr_t)(b)) >> 61) == 0)
+#error "LZO_MM_PVP is unsupported"
#else
#define PTR(a) ((lzo_uintptr_t) (a))
#define PTR_LINEAR(a) PTR(a)
@@ -2243,24 +3815,28 @@ typedef union
unsigned long a_ulong;
lzo_int a_lzo_int;
lzo_uint a_lzo_uint;
- lzo_int32 a_lzo_int32;
- lzo_uint32 a_lzo_uint32;
-#if defined(LZO_UINT64_MAX)
- lzo_int64 a_lzo_int64;
- lzo_uint64 a_lzo_uint64;
-#endif
+ lzo_xint a_lzo_xint;
+ lzo_int16_t a_lzo_int16_t;
+ lzo_uint16_t a_lzo_uint16_t;
+ lzo_int32_t a_lzo_int32_t;
+ lzo_uint32_t a_lzo_uint32_t;
+#if defined(lzo_uint64_t)
+ lzo_int64_t a_lzo_int64_t;
+ lzo_uint64_t a_lzo_uint64_t;
+#endif
+ size_t a_size_t;
ptrdiff_t a_ptrdiff_t;
lzo_uintptr_t a_lzo_uintptr_t;
- lzo_voidp a_lzo_voidp;
void * a_void_p;
- lzo_bytep a_lzo_bytep;
- lzo_bytepp a_lzo_bytepp;
- lzo_uintp a_lzo_uintp;
- lzo_uint * a_lzo_uint_p;
- lzo_uint32p a_lzo_uint32p;
- lzo_uint32 * a_lzo_uint32_p;
- unsigned char * a_uchar_p;
char * a_char_p;
+ unsigned char * a_uchar_p;
+ const void * a_c_void_p;
+ const char * a_c_char_p;
+ const unsigned char * a_c_uchar_p;
+ lzo_voidp a_lzo_voidp;
+ lzo_bytep a_lzo_bytep;
+ const lzo_voidp a_c_lzo_voidp;
+ const lzo_bytep a_c_lzo_bytep;
}
lzo_full_align_t;
@@ -2276,18 +3852,14 @@ lzo_full_align_t;
#ifndef LZO_DICT_USE_PTR
#define LZO_DICT_USE_PTR 1
-#if 0 && (LZO_ARCH_I086)
-# undef LZO_DICT_USE_PTR
-# define LZO_DICT_USE_PTR 0
-#endif
#endif
#if (LZO_DICT_USE_PTR)
# define lzo_dict_t const lzo_bytep
-# define lzo_dict_p lzo_dict_t __LZO_MMODEL *
+# define lzo_dict_p lzo_dict_t *
#else
# define lzo_dict_t lzo_uint
-# define lzo_dict_p lzo_dict_t __LZO_MMODEL *
+# define lzo_dict_p lzo_dict_t *
#endif
#endif
@@ -2300,10 +3872,9 @@ __lzo_ptr_linear(const lzo_voidp ptr)
lzo_uintptr_t p;
#if (LZO_ARCH_I086)
- p = (((lzo_uintptr_t)(ACC_PTR_FP_SEG(ptr))) << (16 - ACC_MM_AHSHIFT)) + (ACC_PTR_FP_OFF(ptr));
+#error "LZO_ARCH_I086 is unsupported"
#elif (LZO_MM_PVP)
- p = (lzo_uintptr_t) (ptr);
- p = (p << 3) | (p >> 61);
+#error "LZO_MM_PVP is unsupported"
#else
p = (lzo_uintptr_t) PTR_LINEAR(ptr);
#endif
@@ -2314,9 +3885,8 @@ __lzo_ptr_linear(const lzo_voidp ptr)
LZO_PUBLIC(unsigned)
__lzo_align_gap(const lzo_voidp ptr, lzo_uint size)
{
-#if defined(__LZO_UINTPTR_T_IS_POINTER)
- size_t n = (size_t) ptr;
- n = (((n + size - 1) / size) * size) - n;
+#if (__LZO_UINTPTR_T_IS_POINTER)
+#error "__LZO_UINTPTR_T_IS_POINTER is unsupported"
#else
lzo_uintptr_t p, n;
p = __lzo_ptr_linear(ptr);
@@ -2342,7 +3912,7 @@ static const char __lzo_copyright[] =
#else
"\r\n\n"
"LZO data compression library.\n"
- "$Copyright: LZO Copyright (C) 1996-2011 Markus Franz Xaver Johannes Oberhumer\n"
+ "$Copyright: LZO Copyright (C) 1996-2014 Markus Franz Xaver Johannes Oberhumer\n"
"<markus@oberhumer.com>\n"
"http://www.oberhumer.com $\n\n"
"$Id: LZO version: v" LZO_VERSION_STRING ", " LZO_VERSION_DATE " $\n"
@@ -2352,11 +3922,7 @@ static const char __lzo_copyright[] =
LZO_PUBLIC(const lzo_bytep)
lzo_copyright(void)
{
-#if (LZO_OS_DOS16 && LZO_CC_TURBOC)
- return (lzo_voidp) __lzo_copyright;
-#else
return (const lzo_bytep) __lzo_copyright;
-#endif
}
LZO_PUBLIC(unsigned)
@@ -2393,16 +3959,16 @@ _lzo_version_date(void)
#define LZO_NMAX 5552
#define LZO_DO1(buf,i) s1 += buf[i]; s2 += s1
-#define LZO_DO2(buf,i) LZO_DO1(buf,i); LZO_DO1(buf,i+1);
-#define LZO_DO4(buf,i) LZO_DO2(buf,i); LZO_DO2(buf,i+2);
-#define LZO_DO8(buf,i) LZO_DO4(buf,i); LZO_DO4(buf,i+4);
-#define LZO_DO16(buf,i) LZO_DO8(buf,i); LZO_DO8(buf,i+8);
+#define LZO_DO2(buf,i) LZO_DO1(buf,i); LZO_DO1(buf,i+1)
+#define LZO_DO4(buf,i) LZO_DO2(buf,i); LZO_DO2(buf,i+2)
+#define LZO_DO8(buf,i) LZO_DO4(buf,i); LZO_DO4(buf,i+4)
+#define LZO_DO16(buf,i) LZO_DO8(buf,i); LZO_DO8(buf,i+8)
-LZO_PUBLIC(lzo_uint32)
-lzo_adler32(lzo_uint32 adler, const lzo_bytep buf, lzo_uint len)
+LZO_PUBLIC(lzo_uint32_t)
+lzo_adler32(lzo_uint32_t adler, const lzo_bytep buf, lzo_uint len)
{
- lzo_uint32 s1 = adler & 0xffff;
- lzo_uint32 s2 = (adler >> 16) & 0xffff;
+ lzo_uint32_t s1 = adler & 0xffff;
+ lzo_uint32_t s2 = (adler >> 16) & 0xffff;
unsigned k;
if (buf == NULL)
@@ -2459,8 +4025,8 @@ lzo_adler32(lzo_uint32 adler, const lzo_bytep buf, lzo_uint len)
LZOLIB_PUBLIC(int, lzo_hmemcmp) (const lzo_hvoid_p s1, const lzo_hvoid_p s2, lzo_hsize_t len)
{
#if (LZO_HAVE_MM_HUGE_PTR) || !(HAVE_MEMCMP)
- const lzo_hbyte_p p1 = (const lzo_hbyte_p) s1;
- const lzo_hbyte_p p2 = (const lzo_hbyte_p) s2;
+ const lzo_hbyte_p p1 = LZO_STATIC_CAST(const lzo_hbyte_p, s1);
+ const lzo_hbyte_p p2 = LZO_STATIC_CAST(const lzo_hbyte_p, s2);
if __lzo_likely(len > 0) do
{
int d = *p1 - *p2;
@@ -2476,8 +4042,8 @@ LZOLIB_PUBLIC(int, lzo_hmemcmp) (const lzo_hvoid_p s1, const lzo_hvoid_p s2, lzo
LZOLIB_PUBLIC(lzo_hvoid_p, lzo_hmemcpy) (lzo_hvoid_p dest, const lzo_hvoid_p src, lzo_hsize_t len)
{
#if (LZO_HAVE_MM_HUGE_PTR) || !(HAVE_MEMCPY)
- lzo_hbyte_p p1 = (lzo_hbyte_p) dest;
- const lzo_hbyte_p p2 = (const lzo_hbyte_p) src;
+ lzo_hbyte_p p1 = LZO_STATIC_CAST(lzo_hbyte_p, dest);
+ const lzo_hbyte_p p2 = LZO_STATIC_CAST(const lzo_hbyte_p, src);
if (!(len > 0) || p1 == p2)
return dest;
do
@@ -2491,8 +4057,8 @@ LZOLIB_PUBLIC(lzo_hvoid_p, lzo_hmemcpy) (lzo_hvoid_p dest, const lzo_hvoid_p src
LZOLIB_PUBLIC(lzo_hvoid_p, lzo_hmemmove) (lzo_hvoid_p dest, const lzo_hvoid_p src, lzo_hsize_t len)
{
#if (LZO_HAVE_MM_HUGE_PTR) || !(HAVE_MEMMOVE)
- lzo_hbyte_p p1 = (lzo_hbyte_p) dest;
- const lzo_hbyte_p p2 = (const lzo_hbyte_p) src;
+ lzo_hbyte_p p1 = LZO_STATIC_CAST(lzo_hbyte_p, dest);
+ const lzo_hbyte_p p2 = LZO_STATIC_CAST(const lzo_hbyte_p, src);
if (!(len > 0) || p1 == p2)
return dest;
if (p1 < p2)
@@ -2514,16 +4080,17 @@ LZOLIB_PUBLIC(lzo_hvoid_p, lzo_hmemmove) (lzo_hvoid_p dest, const lzo_hvoid_p sr
return memmove(dest, src, len);
#endif
}
-LZOLIB_PUBLIC(lzo_hvoid_p, lzo_hmemset) (lzo_hvoid_p s, int c, lzo_hsize_t len)
+LZOLIB_PUBLIC(lzo_hvoid_p, lzo_hmemset) (lzo_hvoid_p s, int cc, lzo_hsize_t len)
{
#if (LZO_HAVE_MM_HUGE_PTR) || !(HAVE_MEMSET)
- lzo_hbyte_p p = (lzo_hbyte_p) s;
+ lzo_hbyte_p p = LZO_STATIC_CAST(lzo_hbyte_p, s);
+ unsigned char c = LZO_ITRUNC(unsigned char, cc);
if __lzo_likely(len > 0) do
- *p++ = (unsigned char) c;
+ *p++ = c;
while __lzo_likely(--len > 0);
return s;
#else
- return memset(s, c, len);
+ return memset(s, cc, len);
#endif
}
#undef LZOLIB_PUBLIC
@@ -2532,103 +4099,28 @@ LZOLIB_PUBLIC(lzo_hvoid_p, lzo_hmemset) (lzo_hvoid_p s, int c, lzo_hsize_t len)
#if !defined(__LZO_IN_MINILZO)
-#define ACC_WANT_ACC_CHK_CH 1
-#undef ACCCHK_ASSERT
-
- ACCCHK_ASSERT_IS_SIGNED_T(lzo_int)
- ACCCHK_ASSERT_IS_UNSIGNED_T(lzo_uint)
-
- ACCCHK_ASSERT_IS_SIGNED_T(lzo_int32)
- ACCCHK_ASSERT_IS_UNSIGNED_T(lzo_uint32)
- ACCCHK_ASSERT((LZO_UINT32_C(1) << (int)(8*sizeof(LZO_UINT32_C(1))-1)) > 0)
- ACCCHK_ASSERT(sizeof(lzo_uint32) >= 4)
-#if defined(LZO_UINT64_MAX)
- ACCCHK_ASSERT(sizeof(lzo_uint64) == 8)
- ACCCHK_ASSERT_IS_SIGNED_T(lzo_int64)
- ACCCHK_ASSERT_IS_UNSIGNED_T(lzo_uint64)
-#endif
-
-#if !defined(__LZO_UINTPTR_T_IS_POINTER)
- ACCCHK_ASSERT_IS_UNSIGNED_T(lzo_uintptr_t)
-#endif
- ACCCHK_ASSERT(sizeof(lzo_uintptr_t) >= sizeof(lzo_voidp))
-
- ACCCHK_ASSERT_IS_UNSIGNED_T(lzo_xint)
- ACCCHK_ASSERT(sizeof(lzo_xint) >= sizeof(lzo_uint32))
- ACCCHK_ASSERT(sizeof(lzo_xint) >= sizeof(lzo_uint))
- ACCCHK_ASSERT(sizeof(lzo_xint) == sizeof(lzo_uint32) || sizeof(lzo_xint) == sizeof(lzo_uint))
+#define LZO_WANT_ACC_CHK_CH 1
+#undef LZOCHK_ASSERT
+ LZOCHK_ASSERT((LZO_UINT32_C(1) << (int)(8*sizeof(LZO_UINT32_C(1))-1)) > 0)
+ LZOCHK_ASSERT_IS_SIGNED_T(lzo_int)
+ LZOCHK_ASSERT_IS_UNSIGNED_T(lzo_uint)
+#if !(__LZO_UINTPTR_T_IS_POINTER)
+ LZOCHK_ASSERT_IS_UNSIGNED_T(lzo_uintptr_t)
#endif
-#undef ACCCHK_ASSERT
+ LZOCHK_ASSERT(sizeof(lzo_uintptr_t) >= sizeof(lzo_voidp))
+ LZOCHK_ASSERT_IS_UNSIGNED_T(lzo_xint)
-#define WANT_lzo_bitops_clz32 1
-#define WANT_lzo_bitops_clz64 1
-#define WANT_lzo_bitops_ctz32 1
-#define WANT_lzo_bitops_ctz64 1
-
-#if (defined(_WIN32) || defined(_WIN64)) && ((LZO_CC_INTELC && (__INTEL_COMPILER >= 1000)) || (LZO_CC_MSC && (_MSC_VER >= 1400)))
-#include <intrin.h>
-#if !defined(lzo_bitops_clz32) && defined(WANT_lzo_bitops_clz32) && 0
-#pragma intrinsic(_BitScanReverse)
-static __lzo_inline unsigned lzo_bitops_clz32(lzo_uint32 v)
-{
- unsigned long r;
- (void) _BitScanReverse(&r, v);
- return (unsigned) r;
-}
-#define lzo_bitops_clz32 lzo_bitops_clz32
-#endif
-#if !defined(lzo_bitops_clz64) && defined(WANT_lzo_bitops_clz64) && defined(LZO_UINT64_MAX) && 0
-#pragma intrinsic(_BitScanReverse64)
-static __lzo_inline unsigned lzo_bitops_clz64(lzo_uint64 v)
-{
- unsigned long r;
- (void) _BitScanReverse64(&r, v);
- return (unsigned) r;
-}
-#define lzo_bitops_clz64 lzo_bitops_clz64
-#endif
-#if !defined(lzo_bitops_ctz32) && defined(WANT_lzo_bitops_ctz32)
-#pragma intrinsic(_BitScanForward)
-static __lzo_inline unsigned lzo_bitops_ctz32(lzo_uint32 v)
-{
- unsigned long r;
- (void) _BitScanForward(&r, v);
- return (unsigned) r;
-}
-#define lzo_bitops_ctz32 lzo_bitops_ctz32
-#endif
-#if !defined(lzo_bitops_ctz64) && defined(WANT_lzo_bitops_ctz64) && defined(LZO_UINT64_MAX)
-#pragma intrinsic(_BitScanForward64)
-static __lzo_inline unsigned lzo_bitops_ctz64(lzo_uint64 v)
-{
- unsigned long r;
- (void) _BitScanForward64(&r, v);
- return (unsigned) r;
-}
-#define lzo_bitops_ctz64 lzo_bitops_ctz64
#endif
+#undef LZOCHK_ASSERT
-#elif (LZO_CC_CLANG || (LZO_CC_GNUC >= 0x030400ul) || (LZO_CC_INTELC && (__INTEL_COMPILER >= 1000)) || (LZO_CC_LLVM && (!defined(__llvm_tools_version__) || (__llvm_tools_version__+0 >= 0x010500ul))))
-#if !defined(lzo_bitops_clz32) && defined(WANT_lzo_bitops_clz32)
-#define lzo_bitops_clz32(v) ((unsigned) __builtin_clz(v))
-#endif
-#if !defined(lzo_bitops_clz64) && defined(WANT_lzo_bitops_clz64) && defined(LZO_UINT64_MAX)
-#define lzo_bitops_clz64(v) ((unsigned) __builtin_clzll(v))
-#endif
-#if !defined(lzo_bitops_ctz32) && defined(WANT_lzo_bitops_ctz32)
-#define lzo_bitops_ctz32(v) ((unsigned) __builtin_ctz(v))
-#endif
-#if !defined(lzo_bitops_ctz64) && defined(WANT_lzo_bitops_ctz64) && defined(LZO_UINT64_MAX)
-#define lzo_bitops_ctz64(v) ((unsigned) __builtin_ctzll(v))
-#endif
-#if !defined(lzo_bitops_popcount32) && defined(WANT_lzo_bitops_popcount32)
-#define lzo_bitops_popcount32(v) ((unsigned) __builtin_popcount(v))
-#endif
-#if !defined(lzo_bitops_popcount32) && defined(WANT_lzo_bitops_popcount64) && defined(LZO_UINT64_MAX)
-#define lzo_bitops_popcount64(v) ((unsigned) __builtin_popcountll(v))
-#endif
+union lzo_config_check_union {
+ lzo_uint a[2];
+ unsigned char b[2*LZO_MAX(8,sizeof(lzo_uint))];
+#if defined(lzo_uint64_t)
+ lzo_uint64_t c[2];
#endif
+};
#if 0
#define u2p(ptr,off) ((lzo_voidp) (((lzo_bytep)(lzo_voidp)(ptr)) + (off)))
@@ -2642,73 +4134,101 @@ static __lzo_noinline lzo_voidp u2p(lzo_voidp ptr, lzo_uint off)
LZO_PUBLIC(int)
_lzo_config_check(void)
{
- lzo_bool r = 1;
- union {
- lzo_xint a[2]; unsigned char b[2*LZO_MAX(8,sizeof(lzo_xint))];
-#if defined(LZO_UNALIGNED_OK_8)
- lzo_uint64 c[2];
-#endif
- unsigned short x[2]; lzo_uint32 y[2]; lzo_uint z[2];
- } u;
+#if (LZO_CC_CLANG && (LZO_CC_CLANG >= 0x030100ul && LZO_CC_CLANG < 0x030300ul))
+# if 0
+ volatile
+# endif
+#endif
+ union lzo_config_check_union u;
lzo_voidp p;
+ unsigned r = 1;
u.a[0] = u.a[1] = 0;
p = u2p(&u, 0);
r &= ((* (lzo_bytep) p) == 0);
-#if !defined(LZO_CFG_NO_CONFIG_CHECK)
-#if defined(LZO_ABI_BIG_ENDIAN)
+#if !(LZO_CFG_NO_CONFIG_CHECK)
+#if (LZO_ABI_BIG_ENDIAN)
u.a[0] = u.a[1] = 0; u.b[sizeof(lzo_uint) - 1] = 128;
p = u2p(&u, 0);
r &= ((* (lzo_uintp) p) == 128);
#endif
-#if defined(LZO_ABI_LITTLE_ENDIAN)
+#if (LZO_ABI_LITTLE_ENDIAN)
u.a[0] = u.a[1] = 0; u.b[0] = 128;
p = u2p(&u, 0);
r &= ((* (lzo_uintp) p) == 128);
#endif
-#if defined(LZO_UNALIGNED_OK_2)
u.a[0] = u.a[1] = 0;
- u.b[0] = 1; u.b[sizeof(unsigned short) + 1] = 2;
+ u.b[0] = 1; u.b[3] = 2;
p = u2p(&u, 1);
- r &= ((* (lzo_ushortp) p) == 0);
+ r &= UA_GET_NE16(p) == 0;
+ r &= UA_GET_LE16(p) == 0;
+ u.b[1] = 128;
+ r &= UA_GET_LE16(p) == 128;
+ u.b[2] = 129;
+ r &= UA_GET_LE16(p) == LZO_UINT16_C(0x8180);
+#if (LZO_ABI_BIG_ENDIAN)
+ r &= UA_GET_NE16(p) == LZO_UINT16_C(0x8081);
+#endif
+#if (LZO_ABI_LITTLE_ENDIAN)
+ r &= UA_GET_NE16(p) == LZO_UINT16_C(0x8180);
#endif
-#if defined(LZO_UNALIGNED_OK_4)
u.a[0] = u.a[1] = 0;
- u.b[0] = 3; u.b[sizeof(lzo_uint32) + 1] = 4;
+ u.b[0] = 3; u.b[5] = 4;
p = u2p(&u, 1);
- r &= ((* (lzo_uint32p) p) == 0);
+ r &= UA_GET_NE32(p) == 0;
+ r &= UA_GET_LE32(p) == 0;
+ u.b[1] = 128;
+ r &= UA_GET_LE32(p) == 128;
+ u.b[2] = 129; u.b[3] = 130; u.b[4] = 131;
+ r &= UA_GET_LE32(p) == LZO_UINT32_C(0x83828180);
+#if (LZO_ABI_BIG_ENDIAN)
+ r &= UA_GET_NE32(p) == LZO_UINT32_C(0x80818283);
#endif
-#if defined(LZO_UNALIGNED_OK_8)
+#if (LZO_ABI_LITTLE_ENDIAN)
+ r &= UA_GET_NE32(p) == LZO_UINT32_C(0x83828180);
+#endif
+#if defined(UA_GET_NE64)
u.c[0] = u.c[1] = 0;
- u.b[0] = 5; u.b[sizeof(lzo_uint64) + 1] = 6;
+ u.b[0] = 5; u.b[9] = 6;
p = u2p(&u, 1);
- r &= ((* (lzo_uint64p) p) == 0);
-#endif
-#if defined(lzo_bitops_clz32)
- { unsigned i; lzo_uint32 v = 1;
- for (i = 0; i < 32; i++, v <<= 1)
- r &= lzo_bitops_clz32(v) == 31 - i;
- }
-#endif
-#if defined(lzo_bitops_clz64)
- { unsigned i; lzo_uint64 v = 1;
- for (i = 0; i < 64; i++, v <<= 1)
- r &= lzo_bitops_clz64(v) == 63 - i;
- }
-#endif
-#if defined(lzo_bitops_ctz32)
- { unsigned i; lzo_uint32 v = 1;
- for (i = 0; i < 32; i++, v <<= 1)
- r &= lzo_bitops_ctz32(v) == i;
- }
-#endif
-#if defined(lzo_bitops_ctz64)
- { unsigned i; lzo_uint64 v = 1;
- for (i = 0; i < 64; i++, v <<= 1)
- r &= lzo_bitops_ctz64(v) == i;
- }
-#endif
-#endif
+ u.c[0] = u.c[1] = 0;
+ r &= UA_GET_NE64(p) == 0;
+#if defined(UA_GET_LE64)
+ r &= UA_GET_LE64(p) == 0;
+ u.b[1] = 128;
+ r &= UA_GET_LE64(p) == 128;
+#endif
+#endif
+#if defined(lzo_bitops_ctlz32)
+ { unsigned i = 0; lzo_uint32_t v;
+ for (v = 1; v != 0 && r == 1; v <<= 1, i++) {
+ r &= lzo_bitops_ctlz32(v) == 31 - i;
+ r &= lzo_bitops_ctlz32_func(v) == 31 - i;
+ }}
+#endif
+#if defined(lzo_bitops_ctlz64)
+ { unsigned i = 0; lzo_uint64_t v;
+ for (v = 1; v != 0 && r == 1; v <<= 1, i++) {
+ r &= lzo_bitops_ctlz64(v) == 63 - i;
+ r &= lzo_bitops_ctlz64_func(v) == 63 - i;
+ }}
+#endif
+#if defined(lzo_bitops_cttz32)
+ { unsigned i = 0; lzo_uint32_t v;
+ for (v = 1; v != 0 && r == 1; v <<= 1, i++) {
+ r &= lzo_bitops_cttz32(v) == i;
+ r &= lzo_bitops_cttz32_func(v) == i;
+ }}
+#endif
+#if defined(lzo_bitops_cttz64)
+ { unsigned i = 0; lzo_uint64_t v;
+ for (v = 1; v != 0 && r == 1; v <<= 1, i++) {
+ r &= lzo_bitops_cttz64(v) == i;
+ r &= lzo_bitops_cttz64_func(v) == i;
+ }}
+#endif
+#endif
+ LZO_UNUSED_FUNC(lzo_bitops_unused_funcs);
return r == 1 ? LZO_E_OK : LZO_E_ERROR;
}
@@ -2722,11 +4242,11 @@ __lzo_init_v2(unsigned v, int s1, int s2, int s3, int s4, int s5,
#if defined(__LZO_IN_MINILZO)
#elif (LZO_CC_MSC && ((_MSC_VER) < 700))
#else
-#define ACC_WANT_ACC_CHK_CH 1
-#undef ACCCHK_ASSERT
-#define ACCCHK_ASSERT(expr) LZO_COMPILE_TIME_ASSERT(expr)
+#define LZO_WANT_ACC_CHK_CH 1
+#undef LZOCHK_ASSERT
+#define LZOCHK_ASSERT(expr) LZO_COMPILE_TIME_ASSERT(expr)
#endif
-#undef ACCCHK_ASSERT
+#undef LZOCHK_ASSERT
if (v == 0)
return LZO_E_ERROR;
@@ -2734,7 +4254,7 @@ __lzo_init_v2(unsigned v, int s1, int s2, int s3, int s4, int s5,
r = (s1 == -1 || s1 == (int) sizeof(short)) &&
(s2 == -1 || s2 == (int) sizeof(int)) &&
(s3 == -1 || s3 == (int) sizeof(long)) &&
- (s4 == -1 || s4 == (int) sizeof(lzo_uint32)) &&
+ (s4 == -1 || s4 == (int) sizeof(lzo_uint32_t)) &&
(s5 == -1 || s5 == (int) sizeof(lzo_uint)) &&
(s6 == -1 || s6 == (int) lzo_sizeof_dict_t) &&
(s7 == -1 || s7 == (int) sizeof(char *)) &&
@@ -2777,11 +4297,11 @@ int __far __pascal LibMain ( int a, short b, short c, long d )
#if !defined(MINILZO_CFG_SKIP_LZO1X_1_COMPRESS)
-#if 1 && defined(UA_GET32)
+#if 1 && defined(UA_GET_LE32)
#undef LZO_DICT_USE_PTR
#define LZO_DICT_USE_PTR 0
#undef lzo_dict_t
-#define lzo_dict_t unsigned short
+#define lzo_dict_t lzo_uint16_t
#endif
#define LZO_NEED_DICT_H 1
@@ -3086,81 +4606,7 @@ DVAL_ASSERT(lzo_xint dv, const lzo_bytep p)
#endif
#if 1 && defined(DO_COMPRESS) && !defined(do_compress)
-# define do_compress LZO_CPP_ECONCAT2(DO_COMPRESS,_core)
-#endif
-
-#if defined(UA_GET64) && (LZO_ABI_BIG_ENDIAN)
-# define WANT_lzo_bitops_clz64 1
-#elif defined(UA_GET64) && (LZO_ABI_LITTLE_ENDIAN)
-# define WANT_lzo_bitops_ctz64 1
-#elif defined(UA_GET32) && (LZO_ABI_BIG_ENDIAN)
-# define WANT_lzo_bitops_clz32 1
-#elif defined(UA_GET32) && (LZO_ABI_LITTLE_ENDIAN)
-# define WANT_lzo_bitops_ctz32 1
-#endif
-
-#if (defined(_WIN32) || defined(_WIN64)) && ((LZO_CC_INTELC && (__INTEL_COMPILER >= 1000)) || (LZO_CC_MSC && (_MSC_VER >= 1400)))
-#include <intrin.h>
-#if !defined(lzo_bitops_clz32) && defined(WANT_lzo_bitops_clz32) && 0
-#pragma intrinsic(_BitScanReverse)
-static __lzo_inline unsigned lzo_bitops_clz32(lzo_uint32 v)
-{
- unsigned long r;
- (void) _BitScanReverse(&r, v);
- return (unsigned) r;
-}
-#define lzo_bitops_clz32 lzo_bitops_clz32
-#endif
-#if !defined(lzo_bitops_clz64) && defined(WANT_lzo_bitops_clz64) && defined(LZO_UINT64_MAX) && 0
-#pragma intrinsic(_BitScanReverse64)
-static __lzo_inline unsigned lzo_bitops_clz64(lzo_uint64 v)
-{
- unsigned long r;
- (void) _BitScanReverse64(&r, v);
- return (unsigned) r;
-}
-#define lzo_bitops_clz64 lzo_bitops_clz64
-#endif
-#if !defined(lzo_bitops_ctz32) && defined(WANT_lzo_bitops_ctz32)
-#pragma intrinsic(_BitScanForward)
-static __lzo_inline unsigned lzo_bitops_ctz32(lzo_uint32 v)
-{
- unsigned long r;
- (void) _BitScanForward(&r, v);
- return (unsigned) r;
-}
-#define lzo_bitops_ctz32 lzo_bitops_ctz32
-#endif
-#if !defined(lzo_bitops_ctz64) && defined(WANT_lzo_bitops_ctz64) && defined(LZO_UINT64_MAX)
-#pragma intrinsic(_BitScanForward64)
-static __lzo_inline unsigned lzo_bitops_ctz64(lzo_uint64 v)
-{
- unsigned long r;
- (void) _BitScanForward64(&r, v);
- return (unsigned) r;
-}
-#define lzo_bitops_ctz64 lzo_bitops_ctz64
-#endif
-
-#elif (LZO_CC_CLANG || (LZO_CC_GNUC >= 0x030400ul) || (LZO_CC_INTELC && (__INTEL_COMPILER >= 1000)) || (LZO_CC_LLVM && (!defined(__llvm_tools_version__) || (__llvm_tools_version__+0 >= 0x010500ul))))
-#if !defined(lzo_bitops_clz32) && defined(WANT_lzo_bitops_clz32)
-#define lzo_bitops_clz32(v) ((unsigned) __builtin_clz(v))
-#endif
-#if !defined(lzo_bitops_clz64) && defined(WANT_lzo_bitops_clz64) && defined(LZO_UINT64_MAX)
-#define lzo_bitops_clz64(v) ((unsigned) __builtin_clzll(v))
-#endif
-#if !defined(lzo_bitops_ctz32) && defined(WANT_lzo_bitops_ctz32)
-#define lzo_bitops_ctz32(v) ((unsigned) __builtin_ctz(v))
-#endif
-#if !defined(lzo_bitops_ctz64) && defined(WANT_lzo_bitops_ctz64) && defined(LZO_UINT64_MAX)
-#define lzo_bitops_ctz64(v) ((unsigned) __builtin_ctzll(v))
-#endif
-#if !defined(lzo_bitops_popcount32) && defined(WANT_lzo_bitops_popcount32)
-#define lzo_bitops_popcount32(v) ((unsigned) __builtin_popcount(v))
-#endif
-#if !defined(lzo_bitops_popcount32) && defined(WANT_lzo_bitops_popcount64) && defined(LZO_UINT64_MAX)
-#define lzo_bitops_popcount64(v) ((unsigned) __builtin_popcountll(v))
-#endif
+# define do_compress LZO_PP_ECONCAT2(DO_COMPRESS,_core)
#endif
static __lzo_noinline lzo_uint
@@ -3168,7 +4614,7 @@ do_compress ( const lzo_bytep in , lzo_uint in_len,
lzo_bytep out, lzo_uintp out_len,
lzo_uint ti, lzo_voidp wrkmem)
{
- register const lzo_bytep ip;
+ const lzo_bytep ip;
lzo_bytep op;
const lzo_bytep const in_end = in + in_len;
const lzo_bytep const ip_end = in + in_len - 20;
@@ -3207,8 +4653,8 @@ next:
goto literal;
try_match:
-#if defined(UA_GET32)
- if (UA_GET32(m_pos) != UA_GET32(ip))
+#if (LZO_OPT_UNALIGNED32)
+ if (UA_GET_NE32(m_pos) != UA_GET_NE32(ip))
#else
if (m_pos[0] != ip[0] || m_pos[1] != ip[1] || m_pos[2] != ip[2] || m_pos[3] != ip[3])
#endif
@@ -3223,50 +4669,43 @@ literal:
lzo_uint m_off;
lzo_uint m_len;
{
- lzo_uint32 dv;
+ lzo_uint32_t dv;
lzo_uint dindex;
literal:
ip += 1 + ((ip - ii) >> 5);
next:
if __lzo_unlikely(ip >= ip_end)
break;
- dv = UA_GET32(ip);
+ dv = UA_GET_LE32(ip);
dindex = DINDEX(dv,ip);
GINDEX(m_off,m_pos,in+dict,dindex,in);
UPDATE_I(dict,0,dindex,ip,in);
- if __lzo_unlikely(dv != UA_GET32(m_pos))
+ if __lzo_unlikely(dv != UA_GET_LE32(m_pos))
goto literal;
}
#endif
ii -= ti; ti = 0;
{
- register lzo_uint t = pd(ip,ii);
+ lzo_uint t = pd(ip,ii);
if (t != 0)
{
if (t <= 3)
{
- op[-2] |= LZO_BYTE(t);
-#if defined(UA_COPY32)
- UA_COPY32(op, ii);
+ op[-2] = LZO_BYTE(op[-2] | t);
+#if (LZO_OPT_UNALIGNED32)
+ UA_COPY4(op, ii);
op += t;
#else
{ do *op++ = *ii++; while (--t > 0); }
#endif
}
-#if defined(UA_COPY32) || defined(UA_COPY64)
+#if (LZO_OPT_UNALIGNED32) || (LZO_OPT_UNALIGNED64)
else if (t <= 16)
{
*op++ = LZO_BYTE(t - 3);
-#if defined(UA_COPY64)
- UA_COPY64(op, ii);
- UA_COPY64(op+8, ii+8);
-#else
- UA_COPY32(op, ii);
- UA_COPY32(op+4, ii+4);
- UA_COPY32(op+8, ii+8);
- UA_COPY32(op+12, ii+12);
-#endif
+ UA_COPY8(op, ii);
+ UA_COPY8(op+8, ii+8);
op += t;
}
#endif
@@ -3276,31 +4715,21 @@ next:
*op++ = LZO_BYTE(t - 3);
else
{
- register lzo_uint tt = t - 18;
+ lzo_uint tt = t - 18;
*op++ = 0;
while __lzo_unlikely(tt > 255)
{
tt -= 255;
-#if 1 && (LZO_CC_MSC && (_MSC_VER >= 1400))
- * (volatile unsigned char *) op++ = 0;
-#else
- *op++ = 0;
-#endif
+ UA_SET1(op, 0);
+ op++;
}
assert(tt > 0);
*op++ = LZO_BYTE(tt);
}
-#if defined(UA_COPY32) || defined(UA_COPY64)
+#if (LZO_OPT_UNALIGNED32) || (LZO_OPT_UNALIGNED64)
do {
-#if defined(UA_COPY64)
- UA_COPY64(op, ii);
- UA_COPY64(op+8, ii+8);
-#else
- UA_COPY32(op, ii);
- UA_COPY32(op+4, ii+4);
- UA_COPY32(op+8, ii+8);
- UA_COPY32(op+12, ii+12);
-#endif
+ UA_COPY8(op, ii);
+ UA_COPY8(op+8, ii+8);
op += 16; ii += 16; t -= 16;
} while (t >= 16); if (t > 0)
#endif
@@ -3310,26 +4739,26 @@ next:
}
m_len = 4;
{
-#if defined(UA_GET64)
- lzo_uint64 v;
- v = UA_GET64(ip + m_len) ^ UA_GET64(m_pos + m_len);
+#if (LZO_OPT_UNALIGNED64)
+ lzo_uint64_t v;
+ v = UA_GET_NE64(ip + m_len) ^ UA_GET_NE64(m_pos + m_len);
if __lzo_unlikely(v == 0) {
do {
m_len += 8;
- v = UA_GET64(ip + m_len) ^ UA_GET64(m_pos + m_len);
+ v = UA_GET_NE64(ip + m_len) ^ UA_GET_NE64(m_pos + m_len);
if __lzo_unlikely(ip + m_len >= ip_end)
goto m_len_done;
} while (v == 0);
}
-#if (LZO_ABI_BIG_ENDIAN) && defined(lzo_bitops_clz64)
- m_len += lzo_bitops_clz64(v) / CHAR_BIT;
+#if (LZO_ABI_BIG_ENDIAN) && defined(lzo_bitops_ctlz64)
+ m_len += lzo_bitops_ctlz64(v) / CHAR_BIT;
#elif (LZO_ABI_BIG_ENDIAN)
if ((v >> (64 - CHAR_BIT)) == 0) do {
v <<= CHAR_BIT;
m_len += 1;
} while ((v >> (64 - CHAR_BIT)) == 0);
-#elif (LZO_ABI_LITTLE_ENDIAN) && defined(lzo_bitops_ctz64)
- m_len += lzo_bitops_ctz64(v) / CHAR_BIT;
+#elif (LZO_ABI_LITTLE_ENDIAN) && defined(lzo_bitops_cttz64)
+ m_len += lzo_bitops_cttz64(v) / CHAR_BIT;
#elif (LZO_ABI_LITTLE_ENDIAN)
if ((v & UCHAR_MAX) == 0) do {
v >>= CHAR_BIT;
@@ -3340,26 +4769,30 @@ next:
m_len += 1;
} while (ip[m_len] == m_pos[m_len]);
#endif
-#elif defined(UA_GET32)
- lzo_uint32 v;
- v = UA_GET32(ip + m_len) ^ UA_GET32(m_pos + m_len);
+#elif (LZO_OPT_UNALIGNED32)
+ lzo_uint32_t v;
+ v = UA_GET_NE32(ip + m_len) ^ UA_GET_NE32(m_pos + m_len);
if __lzo_unlikely(v == 0) {
do {
m_len += 4;
- v = UA_GET32(ip + m_len) ^ UA_GET32(m_pos + m_len);
+ v = UA_GET_NE32(ip + m_len) ^ UA_GET_NE32(m_pos + m_len);
+ if (v != 0)
+ break;
+ m_len += 4;
+ v = UA_GET_NE32(ip + m_len) ^ UA_GET_NE32(m_pos + m_len);
if __lzo_unlikely(ip + m_len >= ip_end)
goto m_len_done;
} while (v == 0);
}
-#if (LZO_ABI_BIG_ENDIAN) && defined(lzo_bitops_clz32)
- m_len += lzo_bitops_clz32(v) / CHAR_BIT;
+#if (LZO_ABI_BIG_ENDIAN) && defined(lzo_bitops_ctlz32)
+ m_len += lzo_bitops_ctlz32(v) / CHAR_BIT;
#elif (LZO_ABI_BIG_ENDIAN)
if ((v >> (32 - CHAR_BIT)) == 0) do {
v <<= CHAR_BIT;
m_len += 1;
} while ((v >> (32 - CHAR_BIT)) == 0);
-#elif (LZO_ABI_LITTLE_ENDIAN) && defined(lzo_bitops_ctz32)
- m_len += lzo_bitops_ctz32(v) / CHAR_BIT;
+#elif (LZO_ABI_LITTLE_ENDIAN) && defined(lzo_bitops_cttz32)
+ m_len += lzo_bitops_cttz32(v) / CHAR_BIT;
#elif (LZO_ABI_LITTLE_ENDIAN)
if ((v & UCHAR_MAX) == 0) do {
v >>= CHAR_BIT;
@@ -3374,6 +4807,27 @@ next:
if __lzo_unlikely(ip[m_len] == m_pos[m_len]) {
do {
m_len += 1;
+ if (ip[m_len] != m_pos[m_len])
+ break;
+ m_len += 1;
+ if (ip[m_len] != m_pos[m_len])
+ break;
+ m_len += 1;
+ if (ip[m_len] != m_pos[m_len])
+ break;
+ m_len += 1;
+ if (ip[m_len] != m_pos[m_len])
+ break;
+ m_len += 1;
+ if (ip[m_len] != m_pos[m_len])
+ break;
+ m_len += 1;
+ if (ip[m_len] != m_pos[m_len])
+ break;
+ m_len += 1;
+ if (ip[m_len] != m_pos[m_len])
+ break;
+ m_len += 1;
if __lzo_unlikely(ip + m_len >= ip_end)
goto m_len_done;
} while (ip[m_len] == m_pos[m_len]);
@@ -3407,11 +4861,8 @@ m_len_done:
while __lzo_unlikely(m_len > 255)
{
m_len -= 255;
-#if 1 && (LZO_CC_MSC && (_MSC_VER >= 1400))
- * (volatile unsigned char *) op++ = 0;
-#else
- *op++ = 0;
-#endif
+ UA_SET1(op, 0);
+ op++;
}
*op++ = LZO_BYTE(m_len);
}
@@ -3430,11 +4881,8 @@ m_len_done:
while __lzo_unlikely(m_len > 255)
{
m_len -= 255;
-#if 1 && (LZO_CC_MSC && (_MSC_VER >= 1400))
- * (volatile unsigned char *) op++ = 0;
-#else
- *op++ = 0;
-#endif
+ UA_SET1(op, 0);
+ op++;
}
*op++ = LZO_BYTE(m_len);
}
@@ -3485,7 +4933,7 @@ DO_COMPRESS ( const lzo_bytep in , lzo_uint in_len,
if (op == out && t <= 238)
*op++ = LZO_BYTE(17 + t);
else if (t <= 3)
- op[-2] |= LZO_BYTE(t);
+ op[-2] = LZO_BYTE(op[-2] | t);
else if (t <= 18)
*op++ = LZO_BYTE(t - 3);
else
@@ -3496,17 +4944,14 @@ DO_COMPRESS ( const lzo_bytep in , lzo_uint in_len,
while (tt > 255)
{
tt -= 255;
-#if 1 && (LZO_CC_MSC && (_MSC_VER >= 1400))
-
- * (volatile unsigned char *) op++ = 0;
-#else
- *op++ = 0;
-#endif
+ UA_SET1(op, 0);
+ op++;
}
assert(tt > 0);
*op++ = LZO_BYTE(tt);
}
- do *op++ = *ii++; while (--t > 0);
+ UA_COPYN(op, ii, t);
+ op += t;
}
*op++ = M4_MARKER | 1;
@@ -3543,10 +4988,13 @@ DO_COMPRESS ( const lzo_bytep in , lzo_uint in_len,
#undef TEST_IP
#undef TEST_OP
+#undef TEST_IP_AND_TEST_OP
#undef TEST_LB
#undef TEST_LBO
#undef NEED_IP
#undef NEED_OP
+#undef TEST_IV
+#undef TEST_OV
#undef HAVE_TEST_IP
#undef HAVE_TEST_OP
#undef HAVE_NEED_IP
@@ -3561,6 +5009,7 @@ DO_COMPRESS ( const lzo_bytep in , lzo_uint in_len,
# if (LZO_TEST_OVERRUN_INPUT >= 2)
# define NEED_IP(x) \
if ((lzo_uint)(ip_end - ip) < (lzo_uint)(x)) goto input_overrun
+# define TEST_IV(x) if ((x) > (lzo_uint)0 - (511)) goto input_overrun
# endif
#endif
@@ -3572,12 +5021,13 @@ DO_COMPRESS ( const lzo_bytep in , lzo_uint in_len,
# undef TEST_OP
# define NEED_OP(x) \
if ((lzo_uint)(op_end - op) < (lzo_uint)(x)) goto output_overrun
+# define TEST_OV(x) if ((x) > (lzo_uint)0 - (511)) goto output_overrun
# endif
#endif
#if defined(LZO_TEST_OVERRUN_LOOKBEHIND)
-# define TEST_LB(m_pos) if (m_pos < out || m_pos >= op) goto lookbehind_overrun
-# define TEST_LBO(m_pos,o) if (m_pos < out || m_pos >= op - (o)) goto lookbehind_overrun
+# define TEST_LB(m_pos) if (PTR_LT(m_pos,out) || PTR_GE(m_pos,op)) goto lookbehind_overrun
+# define TEST_LBO(m_pos,o) if (PTR_LT(m_pos,out) || PTR_GE(m_pos,op-(o))) goto lookbehind_overrun
#else
# define TEST_LB(m_pos) ((void) 0)
# define TEST_LBO(m_pos,o) ((void) 0)
@@ -3598,15 +5048,27 @@ DO_COMPRESS ( const lzo_bytep in , lzo_uint in_len,
# define TEST_OP 1
#endif
+#if defined(HAVE_TEST_IP) && defined(HAVE_TEST_OP)
+# define TEST_IP_AND_TEST_OP (TEST_IP && TEST_OP)
+#elif defined(HAVE_TEST_IP)
+# define TEST_IP_AND_TEST_OP TEST_IP
+#elif defined(HAVE_TEST_OP)
+# define TEST_IP_AND_TEST_OP TEST_OP
+#else
+# define TEST_IP_AND_TEST_OP 1
+#endif
+
#if defined(NEED_IP)
# define HAVE_NEED_IP 1
#else
# define NEED_IP(x) ((void) 0)
+# define TEST_IV(x) ((void) 0)
#endif
#if defined(NEED_OP)
# define HAVE_NEED_OP 1
#else
# define NEED_OP(x) ((void) 0)
+# define TEST_OV(x) ((void) 0)
#endif
#if defined(HAVE_TEST_IP) || defined(HAVE_NEED_IP)
@@ -3623,14 +5085,14 @@ DO_DECOMPRESS ( const lzo_bytep in , lzo_uint in_len,
lzo_voidp wrkmem )
#endif
{
- register lzo_bytep op;
- register const lzo_bytep ip;
- register lzo_uint t;
+ lzo_bytep op;
+ const lzo_bytep ip;
+ lzo_uint t;
#if defined(COPY_DICT)
lzo_uint m_off;
const lzo_bytep dict_end;
#else
- register const lzo_bytep m_pos;
+ const lzo_bytep m_pos;
#endif
const lzo_bytep const ip_end = in + in_len;
@@ -3665,43 +5127,45 @@ DO_DECOMPRESS ( const lzo_bytep in , lzo_uint in_len,
op = out;
ip = in;
+ NEED_IP(1);
if (*ip > 17)
{
t = *ip++ - 17;
if (t < 4)
goto match_next;
- assert(t > 0); NEED_OP(t); NEED_IP(t+1);
+ assert(t > 0); NEED_OP(t); NEED_IP(t+3);
do *op++ = *ip++; while (--t > 0);
goto first_literal_run;
}
- while (TEST_IP && TEST_OP)
+ for (;;)
{
+ NEED_IP(3);
t = *ip++;
if (t >= 16)
goto match;
if (t == 0)
{
- NEED_IP(1);
while (*ip == 0)
{
t += 255;
ip++;
+ TEST_IV(t);
NEED_IP(1);
}
t += 15 + *ip++;
}
- assert(t > 0); NEED_OP(t+3); NEED_IP(t+4);
-#if defined(LZO_UNALIGNED_OK_8) && defined(LZO_UNALIGNED_OK_4)
+ assert(t > 0); NEED_OP(t+3); NEED_IP(t+6);
+#if (LZO_OPT_UNALIGNED64) && (LZO_OPT_UNALIGNED32)
t += 3;
if (t >= 8) do
{
- UA_COPY64(op,ip);
+ UA_COPY8(op,ip);
op += 8; ip += 8; t -= 8;
} while (t >= 8);
if (t >= 4)
{
- UA_COPY32(op,ip);
+ UA_COPY4(op,ip);
op += 4; ip += 4; t -= 4;
}
if (t > 0)
@@ -3709,19 +5173,19 @@ DO_DECOMPRESS ( const lzo_bytep in , lzo_uint in_len,
*op++ = *ip++;
if (t > 1) { *op++ = *ip++; if (t > 2) { *op++ = *ip++; } }
}
-#elif defined(LZO_UNALIGNED_OK_4) || defined(LZO_ALIGNED_OK_4)
-#if !defined(LZO_UNALIGNED_OK_4)
+#elif (LZO_OPT_UNALIGNED32) || (LZO_ALIGNED_OK_4)
+#if !(LZO_OPT_UNALIGNED32)
if (PTR_ALIGNED2_4(op,ip))
{
#endif
- UA_COPY32(op,ip);
+ UA_COPY4(op,ip);
op += 4; ip += 4;
if (--t > 0)
{
if (t >= 4)
{
do {
- UA_COPY32(op,ip);
+ UA_COPY4(op,ip);
op += 4; ip += 4; t -= 4;
} while (t >= 4);
if (t > 0) do *op++ = *ip++; while (--t > 0);
@@ -3729,12 +5193,12 @@ DO_DECOMPRESS ( const lzo_bytep in , lzo_uint in_len,
else
do *op++ = *ip++; while (--t > 0);
}
-#if !defined(LZO_UNALIGNED_OK_4)
+#if !(LZO_OPT_UNALIGNED32)
}
else
#endif
#endif
-#if !defined(LZO_UNALIGNED_OK_4) && !defined(LZO_UNALIGNED_OK_8)
+#if !(LZO_OPT_UNALIGNED32)
{
*op++ = *ip++; *op++ = *ip++; *op++ = *ip++;
do *op++ = *ip++; while (--t > 0);
@@ -3770,7 +5234,7 @@ first_literal_run:
#endif
goto match_done;
- do {
+ for (;;) {
match:
if (t >= 64)
{
@@ -3830,14 +5294,15 @@ match:
t &= 31;
if (t == 0)
{
- NEED_IP(1);
while (*ip == 0)
{
t += 255;
ip++;
+ TEST_OV(t);
NEED_IP(1);
}
t += 31 + *ip++;
+ NEED_IP(2);
}
#if defined(COPY_DICT)
#if defined(LZO1Z)
@@ -3853,9 +5318,9 @@ match:
m_pos = op - off;
last_m_off = off;
}
-#elif defined(LZO_UNALIGNED_OK_2) && defined(LZO_ABI_LITTLE_ENDIAN)
+#elif (LZO_OPT_UNALIGNED16) && (LZO_ABI_LITTLE_ENDIAN)
m_pos = op - 1;
- m_pos -= UA_GET16(ip) >> 2;
+ m_pos -= UA_GET_LE16(ip) >> 2;
#else
m_pos = op - 1;
m_pos -= (ip[0] >> 2) + (ip[1] << 6);
@@ -3874,14 +5339,15 @@ match:
t &= 7;
if (t == 0)
{
- NEED_IP(1);
while (*ip == 0)
{
t += 255;
ip++;
+ TEST_OV(t);
NEED_IP(1);
}
t += 7 + *ip++;
+ NEED_IP(2);
}
#if defined(COPY_DICT)
#if defined(LZO1Z)
@@ -3899,8 +5365,8 @@ match:
#else
#if defined(LZO1Z)
m_pos -= (ip[0] << 6) + (ip[1] >> 2);
-#elif defined(LZO_UNALIGNED_OK_2) && defined(LZO_ABI_LITTLE_ENDIAN)
- m_pos -= UA_GET16(ip) >> 2;
+#elif (LZO_OPT_UNALIGNED16) && (LZO_ABI_LITTLE_ENDIAN)
+ m_pos -= UA_GET_LE16(ip) >> 2;
#else
m_pos -= (ip[0] >> 2) + (ip[1] << 6);
#endif
@@ -3948,18 +5414,18 @@ match:
#else
TEST_LB(m_pos); assert(t > 0); NEED_OP(t+3-1);
-#if defined(LZO_UNALIGNED_OK_8) && defined(LZO_UNALIGNED_OK_4)
+#if (LZO_OPT_UNALIGNED64) && (LZO_OPT_UNALIGNED32)
if (op - m_pos >= 8)
{
t += (3 - 1);
if (t >= 8) do
{
- UA_COPY64(op,m_pos);
+ UA_COPY8(op,m_pos);
op += 8; m_pos += 8; t -= 8;
} while (t >= 8);
if (t >= 4)
{
- UA_COPY32(op,m_pos);
+ UA_COPY4(op,m_pos);
op += 4; m_pos += 4; t -= 4;
}
if (t > 0)
@@ -3969,8 +5435,8 @@ match:
}
}
else
-#elif defined(LZO_UNALIGNED_OK_4) || defined(LZO_ALIGNED_OK_4)
-#if !defined(LZO_UNALIGNED_OK_4)
+#elif (LZO_OPT_UNALIGNED32) || (LZO_ALIGNED_OK_4)
+#if !(LZO_OPT_UNALIGNED32)
if (t >= 2 * 4 - (3 - 1) && PTR_ALIGNED2_4(op,m_pos))
{
assert((op - m_pos) >= 4);
@@ -3978,10 +5444,10 @@ match:
if (t >= 2 * 4 - (3 - 1) && (op - m_pos) >= 4)
{
#endif
- UA_COPY32(op,m_pos);
+ UA_COPY4(op,m_pos);
op += 4; m_pos += 4; t -= 4 - (3 - 1);
do {
- UA_COPY32(op,m_pos);
+ UA_COPY4(op,m_pos);
op += 4; m_pos += 4; t -= 4;
} while (t >= 4);
if (t > 0) do *op++ = *m_pos++; while (--t > 0);
@@ -4006,7 +5472,7 @@ match_done:
break;
match_next:
- assert(t > 0); assert(t < 4); NEED_OP(t); NEED_IP(t+1);
+ assert(t > 0); assert(t < 4); NEED_OP(t); NEED_IP(t+3);
#if 0
do *op++ = *ip++; while (--t > 0);
#else
@@ -4014,16 +5480,10 @@ match_next:
if (t > 1) { *op++ = *ip++; if (t > 2) { *op++ = *ip++; } }
#endif
t = *ip++;
- } while (TEST_IP && TEST_OP);
+ }
}
-#if defined(HAVE_TEST_IP) || defined(HAVE_TEST_OP)
- *out_len = pd(op, out);
- return LZO_E_EOF_NOT_FOUND;
-#endif
-
eof_found:
- assert(t == 1);
*out_len = pd(op, out);
return (ip == ip_end ? LZO_E_OK :
(ip < ip_end ? LZO_E_INPUT_NOT_CONSUMED : LZO_E_INPUT_OVERRUN));
@@ -4069,10 +5529,13 @@ lookbehind_overrun:
#undef TEST_IP
#undef TEST_OP
+#undef TEST_IP_AND_TEST_OP
#undef TEST_LB
#undef TEST_LBO
#undef NEED_IP
#undef NEED_OP
+#undef TEST_IV
+#undef TEST_OV
#undef HAVE_TEST_IP
#undef HAVE_TEST_OP
#undef HAVE_NEED_IP
@@ -4087,6 +5550,7 @@ lookbehind_overrun:
# if (LZO_TEST_OVERRUN_INPUT >= 2)
# define NEED_IP(x) \
if ((lzo_uint)(ip_end - ip) < (lzo_uint)(x)) goto input_overrun
+# define TEST_IV(x) if ((x) > (lzo_uint)0 - (511)) goto input_overrun
# endif
#endif
@@ -4098,12 +5562,13 @@ lookbehind_overrun:
# undef TEST_OP
# define NEED_OP(x) \
if ((lzo_uint)(op_end - op) < (lzo_uint)(x)) goto output_overrun
+# define TEST_OV(x) if ((x) > (lzo_uint)0 - (511)) goto output_overrun
# endif
#endif
#if defined(LZO_TEST_OVERRUN_LOOKBEHIND)
-# define TEST_LB(m_pos) if (m_pos < out || m_pos >= op) goto lookbehind_overrun
-# define TEST_LBO(m_pos,o) if (m_pos < out || m_pos >= op - (o)) goto lookbehind_overrun
+# define TEST_LB(m_pos) if (PTR_LT(m_pos,out) || PTR_GE(m_pos,op)) goto lookbehind_overrun
+# define TEST_LBO(m_pos,o) if (PTR_LT(m_pos,out) || PTR_GE(m_pos,op-(o))) goto lookbehind_overrun
#else
# define TEST_LB(m_pos) ((void) 0)
# define TEST_LBO(m_pos,o) ((void) 0)
@@ -4124,15 +5589,27 @@ lookbehind_overrun:
# define TEST_OP 1
#endif
+#if defined(HAVE_TEST_IP) && defined(HAVE_TEST_OP)
+# define TEST_IP_AND_TEST_OP (TEST_IP && TEST_OP)
+#elif defined(HAVE_TEST_IP)
+# define TEST_IP_AND_TEST_OP TEST_IP
+#elif defined(HAVE_TEST_OP)
+# define TEST_IP_AND_TEST_OP TEST_OP
+#else
+# define TEST_IP_AND_TEST_OP 1
+#endif
+
#if defined(NEED_IP)
# define HAVE_NEED_IP 1
#else
# define NEED_IP(x) ((void) 0)
+# define TEST_IV(x) ((void) 0)
#endif
#if defined(NEED_OP)
# define HAVE_NEED_OP 1
#else
# define NEED_OP(x) ((void) 0)
+# define TEST_OV(x) ((void) 0)
#endif
#if defined(HAVE_TEST_IP) || defined(HAVE_NEED_IP)
@@ -4149,14 +5626,14 @@ DO_DECOMPRESS ( const lzo_bytep in , lzo_uint in_len,
lzo_voidp wrkmem )
#endif
{
- register lzo_bytep op;
- register const lzo_bytep ip;
- register lzo_uint t;
+ lzo_bytep op;
+ const lzo_bytep ip;
+ lzo_uint t;
#if defined(COPY_DICT)
lzo_uint m_off;
const lzo_bytep dict_end;
#else
- register const lzo_bytep m_pos;
+ const lzo_bytep m_pos;
#endif
const lzo_bytep const ip_end = in + in_len;
@@ -4191,43 +5668,45 @@ DO_DECOMPRESS ( const lzo_bytep in , lzo_uint in_len,
op = out;
ip = in;
+ NEED_IP(1);
if (*ip > 17)
{
t = *ip++ - 17;
if (t < 4)
goto match_next;
- assert(t > 0); NEED_OP(t); NEED_IP(t+1);
+ assert(t > 0); NEED_OP(t); NEED_IP(t+3);
do *op++ = *ip++; while (--t > 0);
goto first_literal_run;
}
- while (TEST_IP && TEST_OP)
+ for (;;)
{
+ NEED_IP(3);
t = *ip++;
if (t >= 16)
goto match;
if (t == 0)
{
- NEED_IP(1);
while (*ip == 0)
{
t += 255;
ip++;
+ TEST_IV(t);
NEED_IP(1);
}
t += 15 + *ip++;
}
- assert(t > 0); NEED_OP(t+3); NEED_IP(t+4);
-#if defined(LZO_UNALIGNED_OK_8) && defined(LZO_UNALIGNED_OK_4)
+ assert(t > 0); NEED_OP(t+3); NEED_IP(t+6);
+#if (LZO_OPT_UNALIGNED64) && (LZO_OPT_UNALIGNED32)
t += 3;
if (t >= 8) do
{
- UA_COPY64(op,ip);
+ UA_COPY8(op,ip);
op += 8; ip += 8; t -= 8;
} while (t >= 8);
if (t >= 4)
{
- UA_COPY32(op,ip);
+ UA_COPY4(op,ip);
op += 4; ip += 4; t -= 4;
}
if (t > 0)
@@ -4235,19 +5714,19 @@ DO_DECOMPRESS ( const lzo_bytep in , lzo_uint in_len,
*op++ = *ip++;
if (t > 1) { *op++ = *ip++; if (t > 2) { *op++ = *ip++; } }
}
-#elif defined(LZO_UNALIGNED_OK_4) || defined(LZO_ALIGNED_OK_4)
-#if !defined(LZO_UNALIGNED_OK_4)
+#elif (LZO_OPT_UNALIGNED32) || (LZO_ALIGNED_OK_4)
+#if !(LZO_OPT_UNALIGNED32)
if (PTR_ALIGNED2_4(op,ip))
{
#endif
- UA_COPY32(op,ip);
+ UA_COPY4(op,ip);
op += 4; ip += 4;
if (--t > 0)
{
if (t >= 4)
{
do {
- UA_COPY32(op,ip);
+ UA_COPY4(op,ip);
op += 4; ip += 4; t -= 4;
} while (t >= 4);
if (t > 0) do *op++ = *ip++; while (--t > 0);
@@ -4255,12 +5734,12 @@ DO_DECOMPRESS ( const lzo_bytep in , lzo_uint in_len,
else
do *op++ = *ip++; while (--t > 0);
}
-#if !defined(LZO_UNALIGNED_OK_4)
+#if !(LZO_OPT_UNALIGNED32)
}
else
#endif
#endif
-#if !defined(LZO_UNALIGNED_OK_4) && !defined(LZO_UNALIGNED_OK_8)
+#if !(LZO_OPT_UNALIGNED32)
{
*op++ = *ip++; *op++ = *ip++; *op++ = *ip++;
do *op++ = *ip++; while (--t > 0);
@@ -4296,7 +5775,7 @@ first_literal_run:
#endif
goto match_done;
- do {
+ for (;;) {
match:
if (t >= 64)
{
@@ -4356,14 +5835,15 @@ match:
t &= 31;
if (t == 0)
{
- NEED_IP(1);
while (*ip == 0)
{
t += 255;
ip++;
+ TEST_OV(t);
NEED_IP(1);
}
t += 31 + *ip++;
+ NEED_IP(2);
}
#if defined(COPY_DICT)
#if defined(LZO1Z)
@@ -4379,9 +5859,9 @@ match:
m_pos = op - off;
last_m_off = off;
}
-#elif defined(LZO_UNALIGNED_OK_2) && defined(LZO_ABI_LITTLE_ENDIAN)
+#elif (LZO_OPT_UNALIGNED16) && (LZO_ABI_LITTLE_ENDIAN)
m_pos = op - 1;
- m_pos -= UA_GET16(ip) >> 2;
+ m_pos -= UA_GET_LE16(ip) >> 2;
#else
m_pos = op - 1;
m_pos -= (ip[0] >> 2) + (ip[1] << 6);
@@ -4400,14 +5880,15 @@ match:
t &= 7;
if (t == 0)
{
- NEED_IP(1);
while (*ip == 0)
{
t += 255;
ip++;
+ TEST_OV(t);
NEED_IP(1);
}
t += 7 + *ip++;
+ NEED_IP(2);
}
#if defined(COPY_DICT)
#if defined(LZO1Z)
@@ -4425,8 +5906,8 @@ match:
#else
#if defined(LZO1Z)
m_pos -= (ip[0] << 6) + (ip[1] >> 2);
-#elif defined(LZO_UNALIGNED_OK_2) && defined(LZO_ABI_LITTLE_ENDIAN)
- m_pos -= UA_GET16(ip) >> 2;
+#elif (LZO_OPT_UNALIGNED16) && (LZO_ABI_LITTLE_ENDIAN)
+ m_pos -= UA_GET_LE16(ip) >> 2;
#else
m_pos -= (ip[0] >> 2) + (ip[1] << 6);
#endif
@@ -4474,18 +5955,18 @@ match:
#else
TEST_LB(m_pos); assert(t > 0); NEED_OP(t+3-1);
-#if defined(LZO_UNALIGNED_OK_8) && defined(LZO_UNALIGNED_OK_4)
+#if (LZO_OPT_UNALIGNED64) && (LZO_OPT_UNALIGNED32)
if (op - m_pos >= 8)
{
t += (3 - 1);
if (t >= 8) do
{
- UA_COPY64(op,m_pos);
+ UA_COPY8(op,m_pos);
op += 8; m_pos += 8; t -= 8;
} while (t >= 8);
if (t >= 4)
{
- UA_COPY32(op,m_pos);
+ UA_COPY4(op,m_pos);
op += 4; m_pos += 4; t -= 4;
}
if (t > 0)
@@ -4495,8 +5976,8 @@ match:
}
}
else
-#elif defined(LZO_UNALIGNED_OK_4) || defined(LZO_ALIGNED_OK_4)
-#if !defined(LZO_UNALIGNED_OK_4)
+#elif (LZO_OPT_UNALIGNED32) || (LZO_ALIGNED_OK_4)
+#if !(LZO_OPT_UNALIGNED32)
if (t >= 2 * 4 - (3 - 1) && PTR_ALIGNED2_4(op,m_pos))
{
assert((op - m_pos) >= 4);
@@ -4504,10 +5985,10 @@ match:
if (t >= 2 * 4 - (3 - 1) && (op - m_pos) >= 4)
{
#endif
- UA_COPY32(op,m_pos);
+ UA_COPY4(op,m_pos);
op += 4; m_pos += 4; t -= 4 - (3 - 1);
do {
- UA_COPY32(op,m_pos);
+ UA_COPY4(op,m_pos);
op += 4; m_pos += 4; t -= 4;
} while (t >= 4);
if (t > 0) do *op++ = *m_pos++; while (--t > 0);
@@ -4532,7 +6013,7 @@ match_done:
break;
match_next:
- assert(t > 0); assert(t < 4); NEED_OP(t); NEED_IP(t+1);
+ assert(t > 0); assert(t < 4); NEED_OP(t); NEED_IP(t+3);
#if 0
do *op++ = *ip++; while (--t > 0);
#else
@@ -4540,16 +6021,10 @@ match_next:
if (t > 1) { *op++ = *ip++; if (t > 2) { *op++ = *ip++; } }
#endif
t = *ip++;
- } while (TEST_IP && TEST_OP);
+ }
}
-#if defined(HAVE_TEST_IP) || defined(HAVE_TEST_OP)
- *out_len = pd(op, out);
- return LZO_E_EOF_NOT_FOUND;
-#endif
-
eof_found:
- assert(t == 1);
*out_len = pd(op, out);
return (ip == ip_end ? LZO_E_OK :
(ip < ip_end ? LZO_E_INPUT_NOT_CONSUMED : LZO_E_INPUT_OVERRUN));
@@ -4576,4 +6051,3 @@ lookbehind_overrun:
#endif
/***** End of minilzo.c *****/
-
diff --git a/extern/lzo/minilzo/minilzo.h b/extern/lzo/minilzo/minilzo.h
index f2c104856e3..79374546748 100644
--- a/extern/lzo/minilzo/minilzo.h
+++ b/extern/lzo/minilzo/minilzo.h
@@ -2,22 +2,7 @@
This file is part of the LZO real-time data compression library.
- Copyright (C) 2011 Markus Franz Xaver Johannes Oberhumer
- Copyright (C) 2010 Markus Franz Xaver Johannes Oberhumer
- Copyright (C) 2009 Markus Franz Xaver Johannes Oberhumer
- Copyright (C) 2008 Markus Franz Xaver Johannes Oberhumer
- Copyright (C) 2007 Markus Franz Xaver Johannes Oberhumer
- Copyright (C) 2006 Markus Franz Xaver Johannes Oberhumer
- Copyright (C) 2005 Markus Franz Xaver Johannes Oberhumer
- Copyright (C) 2004 Markus Franz Xaver Johannes Oberhumer
- Copyright (C) 2003 Markus Franz Xaver Johannes Oberhumer
- Copyright (C) 2002 Markus Franz Xaver Johannes Oberhumer
- Copyright (C) 2001 Markus Franz Xaver Johannes Oberhumer
- Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer
- Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer
- Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer
- Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer
- Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1996-2014 Markus Franz Xaver Johannes Oberhumer
All Rights Reserved.
The LZO library is free software; you can redistribute it and/or
@@ -50,7 +35,7 @@
#ifndef __MINILZO_H
#define __MINILZO_H 1
-#define MINILZO_VERSION 0x2060
+#define MINILZO_VERSION 0x2080
#ifdef __LZOCONF_H
# error "you cannot use both LZO and miniLZO"
@@ -78,7 +63,7 @@ extern "C" {
*/
#define LZO1X_MEM_COMPRESS LZO1X_1_MEM_COMPRESS
-#define LZO1X_1_MEM_COMPRESS ((lzo_uint32) (16384L * lzo_sizeof_dict_t))
+#define LZO1X_1_MEM_COMPRESS ((lzo_uint32_t) (16384L * lzo_sizeof_dict_t))
#define LZO1X_MEM_DECOMPRESS (0)
@@ -101,11 +86,6 @@ lzo1x_decompress_safe ( const lzo_bytep src, lzo_uint src_len,
lzo_voidp wrkmem /* NOT USED */ );
-#define LZO_OUT_LEN(size) ((size) + (size) / 16 + 64 + 3)
-
-#define LZO_HEAP_ALLOC(var,size) \
- lzo_align_t __LZO_MMODEL var [ ((size) + (sizeof(lzo_align_t) - 1)) / sizeof(lzo_align_t) ]
-
#ifdef __cplusplus
} /* extern "C" */
#endif
diff --git a/extern/rangetree/range_tree.hh b/extern/rangetree/range_tree.hh
index 919e0b04933..b247a0c6a1e 100644
--- a/extern/rangetree/range_tree.hh
+++ b/extern/rangetree/range_tree.hh
@@ -92,6 +92,28 @@ struct RangeTree {
tree.insert(Range(t + 1, cur.max));
}
+ /* clone of 'take' that checks if the item exists */
+ bool retake(T t) {
+ #if RANGE_TREE_DEBUG_PRINT_FUNCTION
+ std::cout << __func__ << "(" << t << ")\n";
+ #endif
+
+ TreeIter iter = tree.find(Range(t));
+ if (iter == tree.end()) {
+ return false;
+ }
+
+ Range cur = *iter;
+ tree.erase(iter);
+ if (t > cur.min)
+ tree.insert(Range(cur.min, t - 1));
+ if (t + 1 <= cur.max)
+ tree.insert(Range(t + 1, cur.max));
+
+ return true;
+ }
+
+
/* Take the first element out of the first range in the
tree. Precondition: tree must not be empty. */
T take_any() {
diff --git a/extern/rangetree/range_tree_c_api.cc b/extern/rangetree/range_tree_c_api.cc
index 56f2d90d329..f040b5eaeb6 100644
--- a/extern/rangetree/range_tree_c_api.cc
+++ b/extern/rangetree/range_tree_c_api.cc
@@ -43,6 +43,11 @@ void range_tree_uint_take(RangeTreeUInt *rt, unsigned v)
rt->take(v);
}
+bool range_tree_uint_retake(RangeTreeUInt *rt, unsigned v)
+{
+ return rt->retake(v);
+}
+
unsigned range_tree_uint_take_any(RangeTreeUInt *rt)
{
return rt->take_any();
@@ -53,19 +58,20 @@ void range_tree_uint_release(RangeTreeUInt *rt, unsigned v)
rt->release(v);
}
-int range_tree_uint_has(const RangeTreeUInt *rt, unsigned v)
+bool range_tree_uint_has(const RangeTreeUInt *rt, unsigned v)
{
return rt->has(v);
}
-int range_tree_uint_has_range(const RangeTreeUInt *rt,
- unsigned vmin,
- unsigned vmax)
+bool range_tree_uint_has_range(
+ const RangeTreeUInt *rt,
+ unsigned vmin,
+ unsigned vmax)
{
return rt->has_range(vmin, vmax);
}
-int range_tree_uint_empty(const RangeTreeUInt *rt)
+bool range_tree_uint_empty(const RangeTreeUInt *rt)
{
return rt->empty();
}
diff --git a/extern/rangetree/range_tree_c_api.h b/extern/rangetree/range_tree_c_api.h
index af6a7b161a8..6abfb6bd55e 100644
--- a/extern/rangetree/range_tree_c_api.h
+++ b/extern/rangetree/range_tree_c_api.h
@@ -14,8 +14,8 @@
02110-1301, USA.
*/
-#ifndef RANGE_TREE_C_API_H
-#define RANGE_TREE_C_API_H
+#ifndef __RANGE_TREE_C_API_H__
+#define __RANGE_TREE_C_API_H__
#ifdef __cplusplus
extern "C" {
@@ -35,17 +35,19 @@ void range_tree_uint_free(RangeTreeUInt *rt);
void range_tree_uint_take(RangeTreeUInt *rt, unsigned v);
+bool range_tree_uint_retake(RangeTreeUInt *rt, unsigned v);
+
unsigned range_tree_uint_take_any(RangeTreeUInt *rt);
void range_tree_uint_release(RangeTreeUInt *rt, unsigned v);
-int range_tree_uint_has(const RangeTreeUInt *rt, unsigned v);
+bool range_tree_uint_has(const RangeTreeUInt *rt, unsigned v);
-int range_tree_uint_has_range(const RangeTreeUInt *rt,
- unsigned vmin,
- unsigned vmax);
+bool range_tree_uint_has_range(
+ const RangeTreeUInt *rt,
+ unsigned vmin, unsigned vmax);
-int range_tree_uint_empty(const RangeTreeUInt *rt);
+bool range_tree_uint_empty(const RangeTreeUInt *rt);
unsigned range_tree_uint_size(const RangeTreeUInt *rt);
@@ -57,4 +59,4 @@ unsigned int range_tree_uint_allocation_lower_bound(const RangeTreeUInt *rt);
}
#endif
-#endif /* __DUALCON_H__ */
+#endif /* __RANGE_TREE_C_API_H__ */
diff --git a/extern/sdlew/CMakeLists.txt b/extern/sdlew/CMakeLists.txt
new file mode 100644
index 00000000000..8571ad9251d
--- /dev/null
+++ b/extern/sdlew/CMakeLists.txt
@@ -0,0 +1,40 @@
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# The Original Code is Copyright (C) 2006, Blender Foundation
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): Jacques Beaurain.
+#
+# ***** END GPL LICENSE BLOCK *****
+
+set(INC
+ .
+ include
+)
+
+set(INC_SYS
+
+)
+
+set(SRC
+ include/sdlew.h
+ src/sdlew.c
+)
+
+blender_add_lib(extern_sdlew "${SRC}" "${INC}" "${INC_SYS}")
diff --git a/extern/sdlew/SConscript b/extern/sdlew/SConscript
new file mode 100644
index 00000000000..287f9c09ec8
--- /dev/null
+++ b/extern/sdlew/SConscript
@@ -0,0 +1,35 @@
+#!/usr/bin/env python
+#
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# The Original Code is Copyright (C) 2014, Blender Foundation
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): Sergey Sharybin.
+#
+# ***** END GPL LICENSE BLOCK *****
+
+Import ('env')
+
+sources = env.Glob('src/sdlew.c')
+
+incs = 'include'
+defs = []
+
+env.BlenderLib ('extern_sdlew', sources, Split(incs), defines=defs, libtype=['extern'], priority = [999])
diff --git a/extern/sdlew/auto/sdlew_gen.sh b/extern/sdlew/auto/sdlew_gen.sh
new file mode 100755
index 00000000000..36a2d939d20
--- /dev/null
+++ b/extern/sdlew/auto/sdlew_gen.sh
@@ -0,0 +1,250 @@
+#!/bin/bash
+
+SDL="SDL2"
+INCLUDE_DIR="/usr/include/${SDL}"
+SCRIPT=`realpath -s $0`
+DIR=`dirname $SCRIPT`
+DIR=`dirname $DIR`
+
+mkdir -p $DIR/include/${SDL}
+mkdir -p $DIR/src
+
+rm -rf $DIR/include/${SDL}/*.h
+rm -rf $DIR/src/sdlew.c
+
+echo "Generating sdlew headers..."
+
+UNSUPPORTED="SDL_MemoryBarrierRelease SDL_MemoryBarrierAcquire SDL_AtomicCAS SDL_AtomicCASPtr \
+ SDL_iPhoneSetAnimationCallback SDL_iPhoneSetEventPump SDL_AndroidGetJNIEnv SDL_AndroidGetActivity \
+ SDL_AndroidGetActivity SDL_AndroidGetInternalStoragePath SDL_AndroidGetExternalStorageState \
+ SDL_AndroidGetExternalStoragePath SDL_CreateShapedWindow SDL_IsShapedWindow tSDL_SetWindowShape \
+ SDL_GetShapedWindowMode"
+
+for header in $INCLUDE_DIR/*; do
+ filename=`basename $header`
+ cat $header \
+ | sed -r 's/extern DECLSPEC ((const )?[a-z0-9_]+(\s\*)?)\s?SDLCALL /typedef \1 SDLCALL t/i' \
+ > $DIR/include/${SDL}/$filename
+
+ line_num=`cat $DIR/include/${SDL}/$filename | grep -n "Ends C function" | cut -d : -f 1`
+ if [ ! -z "$line_num" ]; then
+ functions=`grep -E 'typedef [A-Za-z0-9_ \*]+ SDLCALL' $DIR/include/${SDL}/$filename \
+ | sed -r 's/typedef [A-Za-z0-9_ \*]+ SDLCALL t([a-z0-9_]+).*/extern t\1 *\1;/i'`
+ functions=`echo "${functions}" | sed -e 's/[\/&]/\\\&/g'`
+ echo "$functions" | while read function; do
+ if [ -z "$function" ]; then
+ continue;
+ fi
+ func_name=`echo $function | cut -d '*' -f 2 | sed -r 's/;//'`
+ if [ ! -z "`echo "$UNSUPPORTED" | grep $func_name`" ]; then
+ continue;
+ fi
+ if [ "$func_name" == "SDL_memcpy" ]; then
+ line_num=`cat $DIR/include/${SDL}/$filename | grep -n "SDL_memcpy4" | cut -d : -f 1`
+ sed -ri "${line_num}s/(.*)/${function}\n\1/" $DIR/include/${SDL}/$filename
+ else
+ sed -ri "${line_num}s/(.*)/${function}\n\1/" $DIR/include/${SDL}/$filename
+ fi
+ line_num=`cat $DIR/include/${SDL}/$filename | grep -n "Ends C function" | cut -d : -f 1`
+ done
+ line_num=`cat $DIR/include/${SDL}/$filename | grep -n "Ends C function" | cut -d : -f 1`
+ sed -ri "${line_num}s/(.*)/\n\1/" $DIR/include/${SDL}/$filename
+ fi
+
+ if [ $filename == "SDL_stdinc.h" ]; then
+ cat $header | grep -E '#if(def)? (defined\()?HAVE_' | sed -r 's/#if(def)? //' | while read check; do
+ func_names=`cat $DIR/include/${SDL}/$filename \
+ | grep -A 8 "$check\$" \
+ | grep -v struct \
+ | grep 'typedef' \
+ | sed -r 's/typedef [a-z0-9_ \*]+ SDLCALL ([a-z0-9_]+).*/\1/i'`
+ full_check=`echo "${check}" | sed -e 's/[\/&]/\\\&/g'`
+ if [ ! -z "`echo $full_check | grep defined`" ]; then
+ full_check="#if !($full_check)"
+ else
+ full_check="#ifndef $full_check"
+ fi
+ for func_name in $func_names; do
+ line_num=`grep -n "extern ${func_name} \*" $DIR/include/${SDL}/$filename | cut -d : -f 1`
+ let prev_num=line_num-1
+ if [ -z "`cat $DIR/include/${SDL}/$filename | head -n $prev_num | tail -n 1 | grep '#if'`" ]; then
+ sed -ri "${line_num}s/(.*)/$full_check \/* GEN_CHECK_MARKER *\/\n\1\n#endif \/* GEN_CHECK_MARKER *\//" $DIR/include/${SDL}/$filename
+ fi
+ done
+ done
+ fi
+done
+
+cat << EOF > $DIR/include/sdlew.h
+/*
+ * Copyright 2014 Blender Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+#ifndef __SDL_EW_H__
+#define __SDL_EW_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+enum {
+ SDLEW_SUCCESS = 0,
+ SDLEW_ERROR_OPEN_FAILED = -1,
+ SDLEW_ERROR_ATEXIT_FAILED = -2,
+ SDLEW_ERROR_VERSION = -3,
+};
+
+int sdlewInit(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __SDL_EW_H__ */
+EOF
+
+echo "Generating sdlew sources..."
+
+cat << EOF > $DIR/src/sdlew.c
+/*
+ * Copyright 2014 Blender Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+#ifdef _MSC_VER
+# define snprintf _snprintf
+# define popen _popen
+# define pclose _pclose
+# define _CRT_SECURE_NO_WARNINGS
+#endif
+
+#include "sdlew.h"
+
+#include "${SDL}/SDL.h"
+#include "${SDL}/SDL_syswm.h"
+
+#include <assert.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/stat.h>
+
+#ifdef _WIN32
+# define WIN32_LEAN_AND_MEAN
+# define VC_EXTRALEAN
+# include <windows.h>
+
+/* Utility macros. */
+
+typedef HMODULE DynamicLibrary;
+
+# define dynamic_library_open(path) LoadLibrary(path)
+# define dynamic_library_close(lib) FreeLibrary(lib)
+# define dynamic_library_find(lib, symbol) GetProcAddress(lib, symbol)
+#else
+# include <dlfcn.h>
+
+typedef void* DynamicLibrary;
+
+# define dynamic_library_open(path) dlopen(path, RTLD_NOW)
+# define dynamic_library_close(lib) dlclose(lib)
+# define dynamic_library_find(lib, symbol) dlsym(lib, symbol)
+#endif
+
+#define SDL_LIBRARY_FIND_CHECKED(name) \
+ name = (t##name *)dynamic_library_find(lib, #name); \
+ assert(name);
+
+#define SDL_LIBRARY_FIND(name) \
+ name = (t##name *)dynamic_library_find(lib, #name);
+
+static DynamicLibrary lib;
+
+EOF
+
+content=`grep --no-filename -ER "extern tSDL|GEN_CHECK_MARKER" $DIR/include/${SDL}/`
+
+echo "$content" | sed -r 's/extern t([a-z0-9_]+).*/t\1 *\1;/gi' >> $DIR/src/sdlew.c
+
+cat << EOF >> $DIR/src/sdlew.c
+
+static void sdlewExit(void) {
+ if(lib != NULL) {
+ /* Ignore errors. */
+ dynamic_library_close(lib);
+ lib = NULL;
+ }
+}
+
+/* Implementation function. */
+int sdlewInit(void) {
+ /* Library paths. */
+#ifdef _WIN32
+ /* Expected in c:/windows/system or similar, no path needed. */
+ const char *path = "SDL2.dll";
+#elif defined(__APPLE__)
+ /* Default installation path. */
+ const char *path = "/usr/local/cuda/lib/libSDL2.dylib";
+#else
+ const char *path = "libSDL2.so";
+#endif
+ static int initialized = 0;
+ static int result = 0;
+ int error;
+
+ if (initialized) {
+ return result;
+ }
+
+ initialized = 1;
+
+ error = atexit(sdlewExit);
+ if (error) {
+ result = SDLEW_ERROR_ATEXIT_FAILED;
+ return result;
+ }
+
+ /* Load library. */
+ lib = dynamic_library_open(path);
+
+ if (lib == NULL) {
+ result = SDLEW_ERROR_OPEN_FAILED;
+ return result;
+ }
+
+EOF
+
+echo "$content" | sed -r 's/extern t([a-z0-9_]+).*/ SDL_LIBRARY_FIND(\1);/gi' >> $DIR/src/sdlew.c
+
+cat << EOF >> $DIR/src/sdlew.c
+
+ result = SDLEW_SUCCESS;
+
+ return result;
+}
+EOF
+
+sed -i 's/\s\/\* GEN_CHECK_MARKER \*\///g' $DIR/src/sdlew.c
+sed -i 's/\s\/\* GEN_CHECK_MARKER \*\///g' $DIR/include/${SDL}/SDL_stdinc.h
diff --git a/extern/sdlew/auto/strip_comments.sh b/extern/sdlew/auto/strip_comments.sh
new file mode 100755
index 00000000000..c89224c3d56
--- /dev/null
+++ b/extern/sdlew/auto/strip_comments.sh
@@ -0,0 +1,15 @@
+#!/bin/bash
+
+SDL="SDL2"
+INCLUDE_DIR="/usr/include/${SDL}"
+SCRIPT=`realpath -s $0`
+DIR=`dirname $SCRIPT`
+DIR=`dirname $DIR`
+
+for f in $DIR/include/${SDL}/*.h; do
+ file_name=`basename $f`
+ echo "Striping $file_name..."
+ sed -r ':a; s%(.*)/\*.*\*/%\1%; ta; /\/\*/ !b; N; ba' -i $f
+ sed 's/[ \t]*$//' -i $f
+ sed '/^$/N;/^\n$/D' -i $f
+done
diff --git a/extern/sdlew/include/SDL2/SDL.h b/extern/sdlew/include/SDL2/SDL.h
new file mode 100644
index 00000000000..1dc71e9e765
--- /dev/null
+++ b/extern/sdlew/include/SDL2/SDL.h
@@ -0,0 +1,73 @@
+
+#ifndef _SDL_H
+#define _SDL_H
+
+#include "SDL_main.h"
+#include "SDL_stdinc.h"
+#include "SDL_assert.h"
+#include "SDL_atomic.h"
+#include "SDL_audio.h"
+#include "SDL_clipboard.h"
+#include "SDL_cpuinfo.h"
+#include "SDL_endian.h"
+#include "SDL_error.h"
+#include "SDL_events.h"
+#include "SDL_joystick.h"
+#include "SDL_gamecontroller.h"
+#include "SDL_haptic.h"
+#include "SDL_hints.h"
+#include "SDL_loadso.h"
+#include "SDL_log.h"
+#include "SDL_messagebox.h"
+#include "SDL_mutex.h"
+#include "SDL_power.h"
+#include "SDL_render.h"
+#include "SDL_rwops.h"
+#include "SDL_system.h"
+#include "SDL_thread.h"
+#include "SDL_timer.h"
+#include "SDL_version.h"
+#include "SDL_video.h"
+
+#include "begin_code.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define SDL_INIT_TIMER 0x00000001
+#define SDL_INIT_AUDIO 0x00000010
+#define SDL_INIT_VIDEO 0x00000020
+#define SDL_INIT_JOYSTICK 0x00000200
+#define SDL_INIT_HAPTIC 0x00001000
+#define SDL_INIT_GAMECONTROLLER 0x00002000
+#define SDL_INIT_EVENTS 0x00004000
+#define SDL_INIT_NOPARACHUTE 0x00100000
+#define SDL_INIT_EVERYTHING ( \
+ SDL_INIT_TIMER | SDL_INIT_AUDIO | SDL_INIT_VIDEO | SDL_INIT_EVENTS | \
+ SDL_INIT_JOYSTICK | SDL_INIT_HAPTIC | SDL_INIT_GAMECONTROLLER \
+ )
+
+typedef int SDLCALL tSDL_Init(Uint32 flags);
+
+typedef int SDLCALL tSDL_InitSubSystem(Uint32 flags);
+
+typedef void SDLCALL tSDL_QuitSubSystem(Uint32 flags);
+
+typedef Uint32 SDLCALL tSDL_WasInit(Uint32 flags);
+
+typedef void SDLCALL tSDL_Quit(void);
+
+extern tSDL_Init *SDL_Init;
+extern tSDL_InitSubSystem *SDL_InitSubSystem;
+extern tSDL_QuitSubSystem *SDL_QuitSubSystem;
+extern tSDL_WasInit *SDL_WasInit;
+extern tSDL_Quit *SDL_Quit;
+
+#ifdef __cplusplus
+}
+#endif
+#include "close_code.h"
+
+#endif
+
diff --git a/extern/sdlew/include/SDL2/SDL_assert.h b/extern/sdlew/include/SDL2/SDL_assert.h
new file mode 100644
index 00000000000..aa7b3ee2c25
--- /dev/null
+++ b/extern/sdlew/include/SDL2/SDL_assert.h
@@ -0,0 +1,140 @@
+
+#ifndef _SDL_assert_h
+#define _SDL_assert_h
+
+#include "SDL_config.h"
+
+#include "begin_code.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef SDL_ASSERT_LEVEL
+#ifdef SDL_DEFAULT_ASSERT_LEVEL
+#define SDL_ASSERT_LEVEL SDL_DEFAULT_ASSERT_LEVEL
+#elif defined(_DEBUG) || defined(DEBUG) || \
+ (defined(__GNUC__) && !defined(__OPTIMIZE__))
+#define SDL_ASSERT_LEVEL 2
+#else
+#define SDL_ASSERT_LEVEL 1
+#endif
+#endif
+
+#if defined(_MSC_VER)
+
+ extern void __cdecl __debugbreak(void);
+ #define SDL_TriggerBreakpoint() __debugbreak()
+#elif (defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)))
+ #define SDL_TriggerBreakpoint() __asm__ __volatile__ ( "int $3\n\t" )
+#elif defined(HAVE_SIGNAL_H)
+ #include <signal.h>
+ #define SDL_TriggerBreakpoint() raise(SIGTRAP)
+#else
+
+ #define SDL_TriggerBreakpoint()
+#endif
+
+#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
+# define SDL_FUNCTION __func__
+#elif ((__GNUC__ >= 2) || defined(_MSC_VER))
+# define SDL_FUNCTION __FUNCTION__
+#else
+# define SDL_FUNCTION "???"
+#endif
+#define SDL_FILE __FILE__
+#define SDL_LINE __LINE__
+
+#define SDL_disabled_assert(condition) \
+ do { (void) sizeof ((condition)); } while (0)
+
+typedef enum
+{
+ SDL_ASSERTION_RETRY,
+ SDL_ASSERTION_BREAK,
+ SDL_ASSERTION_ABORT,
+ SDL_ASSERTION_IGNORE,
+ SDL_ASSERTION_ALWAYS_IGNORE
+} SDL_assert_state;
+
+typedef struct SDL_assert_data
+{
+ int always_ignore;
+ unsigned int trigger_count;
+ const char *condition;
+ const char *filename;
+ int linenum;
+ const char *function;
+ const struct SDL_assert_data *next;
+} SDL_assert_data;
+
+#if (SDL_ASSERT_LEVEL > 0)
+
+typedef SDL_assert_state SDLCALL tSDL_ReportAssertion(SDL_assert_data *,
+ const char *,
+ const char *, int);
+
+#define SDL_enabled_assert(condition) \
+ do { \
+ while ( !(condition) ) { \
+ static struct SDL_assert_data assert_data = { \
+ 0, 0, #condition, 0, 0, 0, 0 \
+ }; \
+ const SDL_assert_state state = SDL_ReportAssertion(&assert_data, \
+ SDL_FUNCTION, \
+ SDL_FILE, \
+ SDL_LINE); \
+ if (state == SDL_ASSERTION_RETRY) { \
+ continue; \
+ } else if (state == SDL_ASSERTION_BREAK) { \
+ SDL_TriggerBreakpoint(); \
+ } \
+ break; \
+ } \
+ } while (0)
+
+#endif
+
+#if SDL_ASSERT_LEVEL == 0
+# define SDL_assert(condition) SDL_disabled_assert(condition)
+# define SDL_assert_release(condition) SDL_disabled_assert(condition)
+# define SDL_assert_paranoid(condition) SDL_disabled_assert(condition)
+#elif SDL_ASSERT_LEVEL == 1
+# define SDL_assert(condition) SDL_disabled_assert(condition)
+# define SDL_assert_release(condition) SDL_enabled_assert(condition)
+# define SDL_assert_paranoid(condition) SDL_disabled_assert(condition)
+#elif SDL_ASSERT_LEVEL == 2
+# define SDL_assert(condition) SDL_enabled_assert(condition)
+# define SDL_assert_release(condition) SDL_enabled_assert(condition)
+# define SDL_assert_paranoid(condition) SDL_disabled_assert(condition)
+#elif SDL_ASSERT_LEVEL == 3
+# define SDL_assert(condition) SDL_enabled_assert(condition)
+# define SDL_assert_release(condition) SDL_enabled_assert(condition)
+# define SDL_assert_paranoid(condition) SDL_enabled_assert(condition)
+#else
+# error Unknown assertion level.
+#endif
+
+typedef SDL_assert_state (SDLCALL *SDL_AssertionHandler)(
+ const SDL_assert_data* data, void* userdata);
+
+typedef void SDLCALL tSDL_SetAssertionHandler(
+ SDL_AssertionHandler handler,
+ void *userdata);
+
+typedef const SDL_assert_data * SDLCALL tSDL_GetAssertionReport(void);
+
+typedef void SDLCALL tSDL_ResetAssertionReport(void);
+
+extern tSDL_ReportAssertion *SDL_ReportAssertion;
+extern tSDL_SetAssertionHandler *SDL_SetAssertionHandler;
+extern tSDL_GetAssertionReport *SDL_GetAssertionReport;
+extern tSDL_ResetAssertionReport *SDL_ResetAssertionReport;
+
+#ifdef __cplusplus
+}
+#endif
+#include "close_code.h"
+
+#endif
+
diff --git a/extern/sdlew/include/SDL2/SDL_atomic.h b/extern/sdlew/include/SDL2/SDL_atomic.h
new file mode 100644
index 00000000000..6531a3e7115
--- /dev/null
+++ b/extern/sdlew/include/SDL2/SDL_atomic.h
@@ -0,0 +1,185 @@
+
+#ifndef _SDL_atomic_h_
+#define _SDL_atomic_h_
+
+#include "SDL_stdinc.h"
+#include "SDL_platform.h"
+
+#include "begin_code.h"
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1500)
+#include <intrin.h>
+#define HAVE_MSC_ATOMICS 1
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef int SDL_SpinLock;
+
+typedef SDL_bool SDLCALL tSDL_AtomicTryLock(SDL_SpinLock *lock);
+
+typedef void SDLCALL tSDL_AtomicLock(SDL_SpinLock *lock);
+
+typedef void SDLCALL tSDL_AtomicUnlock(SDL_SpinLock *lock);
+
+#if defined(_MSC_VER) && (_MSC_VER > 1200)
+void _ReadWriteBarrier(void);
+#pragma intrinsic(_ReadWriteBarrier)
+#define SDL_CompilerBarrier() _ReadWriteBarrier()
+#elif defined(__GNUC__)
+#define SDL_CompilerBarrier() __asm__ __volatile__ ("" : : : "memory")
+#else
+#define SDL_CompilerBarrier() \
+{ SDL_SpinLock _tmp = 0; SDL_AtomicLock(&_tmp); SDL_AtomicUnlock(&_tmp); }
+#endif
+
+#if defined(__GNUC__) && (defined(__powerpc__) || defined(__ppc__))
+#define SDL_MemoryBarrierRelease() __asm__ __volatile__ ("lwsync" : : : "memory")
+#define SDL_MemoryBarrierAcquire() __asm__ __volatile__ ("lwsync" : : : "memory")
+#elif defined(__GNUC__) && defined(__arm__)
+#if defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) || defined(__ARM_ARCH_7EM__) || defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7S__)
+#define SDL_MemoryBarrierRelease() __asm__ __volatile__ ("dmb ish" : : : "memory")
+#define SDL_MemoryBarrierAcquire() __asm__ __volatile__ ("dmb ish" : : : "memory")
+#elif defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) || defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6T2__) || defined(__ARM_ARCH_6Z__) || defined(__ARM_ARCH_6ZK__)
+#ifdef __thumb__
+
+typedef void SDLCALL tSDL_MemoryBarrierRelease();
+typedef void SDLCALL tSDL_MemoryBarrierAcquire();
+#else
+#define SDL_MemoryBarrierRelease() __asm__ __volatile__ ("mcr p15, 0, %0, c7, c10, 5" : : "r"(0) : "memory")
+#define SDL_MemoryBarrierAcquire() __asm__ __volatile__ ("mcr p15, 0, %0, c7, c10, 5" : : "r"(0) : "memory")
+#endif
+#else
+#define SDL_MemoryBarrierRelease() __asm__ __volatile__ ("" : : : "memory")
+#define SDL_MemoryBarrierAcquire() __asm__ __volatile__ ("" : : : "memory")
+#endif
+#else
+
+#define SDL_MemoryBarrierRelease() SDL_CompilerBarrier()
+#define SDL_MemoryBarrierAcquire() SDL_CompilerBarrier()
+#endif
+
+#if defined(SDL_ATOMIC_DISABLED) && SDL_ATOMIC_DISABLED
+#define SDL_DISABLE_ATOMIC_INLINE
+#endif
+#ifndef SDL_DISABLE_ATOMIC_INLINE
+
+#ifdef HAVE_MSC_ATOMICS
+
+#define SDL_AtomicSet(a, v) _InterlockedExchange((long*)&(a)->value, (v))
+#define SDL_AtomicAdd(a, v) _InterlockedExchangeAdd((long*)&(a)->value, (v))
+#define SDL_AtomicCAS(a, oldval, newval) (_InterlockedCompareExchange((long*)&(a)->value, (newval), (oldval)) == (oldval))
+#define SDL_AtomicSetPtr(a, v) _InterlockedExchangePointer((a), (v))
+#if _M_IX86
+#define SDL_AtomicCASPtr(a, oldval, newval) (_InterlockedCompareExchange((long*)(a), (long)(newval), (long)(oldval)) == (long)(oldval))
+#else
+#define SDL_AtomicCASPtr(a, oldval, newval) (_InterlockedCompareExchangePointer((a), (newval), (oldval)) == (oldval))
+#endif
+
+#elif defined(__MACOSX__)
+#include <libkern/OSAtomic.h>
+
+#define SDL_AtomicCAS(a, oldval, newval) OSAtomicCompareAndSwap32Barrier((oldval), (newval), &(a)->value)
+#ifdef __LP64__
+#define SDL_AtomicCASPtr(a, oldval, newval) OSAtomicCompareAndSwap64Barrier((int64_t)(oldval), (int64_t)(newval), (int64_t*)(a))
+#else
+#define SDL_AtomicCASPtr(a, oldval, newval) OSAtomicCompareAndSwap32Barrier((int32_t)(oldval), (int32_t)(newval), (int32_t*)(a))
+#endif
+
+#elif defined(HAVE_GCC_ATOMICS)
+
+#define SDL_AtomicSet(a, v) __sync_lock_test_and_set(&(a)->value, v)
+#define SDL_AtomicAdd(a, v) __sync_fetch_and_add(&(a)->value, v)
+#define SDL_AtomicSetPtr(a, v) __sync_lock_test_and_set(a, v)
+#define SDL_AtomicCAS(a, oldval, newval) __sync_bool_compare_and_swap(&(a)->value, oldval, newval)
+#define SDL_AtomicCASPtr(a, oldval, newval) __sync_bool_compare_and_swap(a, oldval, newval)
+
+#endif
+
+#endif
+
+#ifndef SDL_atomic_t_defined
+typedef struct { int value; } SDL_atomic_t;
+#endif
+
+#ifndef SDL_AtomicCAS
+typedef SDL_bool SDLCALL tSDL_AtomicCAS(SDL_atomic_t *a, int oldval, int newval);
+#endif
+
+#ifndef SDL_AtomicSet
+SDL_FORCE_INLINE int SDL_AtomicSet(SDL_atomic_t *a, int v)
+{
+ int value;
+ do {
+ value = a->value;
+ } while (!SDL_AtomicCAS(a, value, v));
+ return value;
+}
+#endif
+
+#ifndef SDL_AtomicGet
+SDL_FORCE_INLINE int SDL_AtomicGet(SDL_atomic_t *a)
+{
+ int value = a->value;
+ SDL_CompilerBarrier();
+ return value;
+}
+#endif
+
+#ifndef SDL_AtomicAdd
+SDL_FORCE_INLINE int SDL_AtomicAdd(SDL_atomic_t *a, int v)
+{
+ int value;
+ do {
+ value = a->value;
+ } while (!SDL_AtomicCAS(a, value, (value + v)));
+ return value;
+}
+#endif
+
+#ifndef SDL_AtomicIncRef
+#define SDL_AtomicIncRef(a) SDL_AtomicAdd(a, 1)
+#endif
+
+#ifndef SDL_AtomicDecRef
+#define SDL_AtomicDecRef(a) (SDL_AtomicAdd(a, -1) == 1)
+#endif
+
+#ifndef SDL_AtomicCASPtr
+typedef SDL_bool SDLCALL tSDL_AtomicCASPtr(void* *a, void *oldval, void *newval);
+#endif
+
+#ifndef SDL_AtomicSetPtr
+SDL_FORCE_INLINE void* SDL_AtomicSetPtr(void* *a, void* v)
+{
+ void* value;
+ do {
+ value = *a;
+ } while (!SDL_AtomicCASPtr(a, value, v));
+ return value;
+}
+#endif
+
+#ifndef SDL_AtomicGetPtr
+SDL_FORCE_INLINE void* SDL_AtomicGetPtr(void* *a)
+{
+ void* value = *a;
+ SDL_CompilerBarrier();
+ return value;
+}
+#endif
+
+extern tSDL_AtomicTryLock *SDL_AtomicTryLock;
+extern tSDL_AtomicLock *SDL_AtomicLock;
+extern tSDL_AtomicUnlock *SDL_AtomicUnlock;
+
+#ifdef __cplusplus
+}
+#endif
+
+#include "close_code.h"
+
+#endif
+
diff --git a/extern/sdlew/include/SDL2/SDL_audio.h b/extern/sdlew/include/SDL2/SDL_audio.h
new file mode 100644
index 00000000000..707c5d5d4dc
--- /dev/null
+++ b/extern/sdlew/include/SDL2/SDL_audio.h
@@ -0,0 +1,222 @@
+
+#ifndef _SDL_audio_h
+#define _SDL_audio_h
+
+#include "SDL_stdinc.h"
+#include "SDL_error.h"
+#include "SDL_endian.h"
+#include "SDL_mutex.h"
+#include "SDL_thread.h"
+#include "SDL_rwops.h"
+
+#include "begin_code.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef Uint16 SDL_AudioFormat;
+
+#define SDL_AUDIO_MASK_BITSIZE (0xFF)
+#define SDL_AUDIO_MASK_DATATYPE (1<<8)
+#define SDL_AUDIO_MASK_ENDIAN (1<<12)
+#define SDL_AUDIO_MASK_SIGNED (1<<15)
+#define SDL_AUDIO_BITSIZE(x) (x & SDL_AUDIO_MASK_BITSIZE)
+#define SDL_AUDIO_ISFLOAT(x) (x & SDL_AUDIO_MASK_DATATYPE)
+#define SDL_AUDIO_ISBIGENDIAN(x) (x & SDL_AUDIO_MASK_ENDIAN)
+#define SDL_AUDIO_ISSIGNED(x) (x & SDL_AUDIO_MASK_SIGNED)
+#define SDL_AUDIO_ISINT(x) (!SDL_AUDIO_ISFLOAT(x))
+#define SDL_AUDIO_ISLITTLEENDIAN(x) (!SDL_AUDIO_ISBIGENDIAN(x))
+#define SDL_AUDIO_ISUNSIGNED(x) (!SDL_AUDIO_ISSIGNED(x))
+
+#define AUDIO_U8 0x0008
+#define AUDIO_S8 0x8008
+#define AUDIO_U16LSB 0x0010
+#define AUDIO_S16LSB 0x8010
+#define AUDIO_U16MSB 0x1010
+#define AUDIO_S16MSB 0x9010
+#define AUDIO_U16 AUDIO_U16LSB
+#define AUDIO_S16 AUDIO_S16LSB
+
+#define AUDIO_S32LSB 0x8020
+#define AUDIO_S32MSB 0x9020
+#define AUDIO_S32 AUDIO_S32LSB
+
+#define AUDIO_F32LSB 0x8120
+#define AUDIO_F32MSB 0x9120
+#define AUDIO_F32 AUDIO_F32LSB
+
+#if SDL_BYTEORDER == SDL_LIL_ENDIAN
+#define AUDIO_U16SYS AUDIO_U16LSB
+#define AUDIO_S16SYS AUDIO_S16LSB
+#define AUDIO_S32SYS AUDIO_S32LSB
+#define AUDIO_F32SYS AUDIO_F32LSB
+#else
+#define AUDIO_U16SYS AUDIO_U16MSB
+#define AUDIO_S16SYS AUDIO_S16MSB
+#define AUDIO_S32SYS AUDIO_S32MSB
+#define AUDIO_F32SYS AUDIO_F32MSB
+#endif
+
+#define SDL_AUDIO_ALLOW_FREQUENCY_CHANGE 0x00000001
+#define SDL_AUDIO_ALLOW_FORMAT_CHANGE 0x00000002
+#define SDL_AUDIO_ALLOW_CHANNELS_CHANGE 0x00000004
+#define SDL_AUDIO_ALLOW_ANY_CHANGE (SDL_AUDIO_ALLOW_FREQUENCY_CHANGE|SDL_AUDIO_ALLOW_FORMAT_CHANGE|SDL_AUDIO_ALLOW_CHANNELS_CHANGE)
+
+typedef void (SDLCALL * SDL_AudioCallback) (void *userdata, Uint8 * stream,
+ int len);
+
+typedef struct SDL_AudioSpec
+{
+ int freq;
+ SDL_AudioFormat format;
+ Uint8 channels;
+ Uint8 silence;
+ Uint16 samples;
+ Uint16 padding;
+ Uint32 size;
+ SDL_AudioCallback callback;
+ void *userdata;
+} SDL_AudioSpec;
+
+struct SDL_AudioCVT;
+typedef void (SDLCALL * SDL_AudioFilter) (struct SDL_AudioCVT * cvt,
+ SDL_AudioFormat format);
+
+#ifdef __GNUC__
+
+#define SDL_AUDIOCVT_PACKED __attribute__((packed))
+#else
+#define SDL_AUDIOCVT_PACKED
+#endif
+
+typedef struct SDL_AudioCVT
+{
+ int needed;
+ SDL_AudioFormat src_format;
+ SDL_AudioFormat dst_format;
+ double rate_incr;
+ Uint8 *buf;
+ int len;
+ int len_cvt;
+ int len_mult;
+ double len_ratio;
+ SDL_AudioFilter filters[10];
+ int filter_index;
+} SDL_AUDIOCVT_PACKED SDL_AudioCVT;
+
+typedef int SDLCALL tSDL_GetNumAudioDrivers(void);
+typedef const char * SDLCALL tSDL_GetAudioDriver(int index);
+
+typedef int SDLCALL tSDL_AudioInit(const char *driver_name);
+typedef void SDLCALL tSDL_AudioQuit(void);
+
+typedef const char * SDLCALL tSDL_GetCurrentAudioDriver(void);
+
+typedef int SDLCALL tSDL_OpenAudio(SDL_AudioSpec * desired,
+ SDL_AudioSpec * obtained);
+
+typedef Uint32 SDL_AudioDeviceID;
+
+typedef int SDLCALL tSDL_GetNumAudioDevices(int iscapture);
+
+typedef const char * SDLCALL tSDL_GetAudioDeviceName(int index,
+ int iscapture);
+
+typedef SDL_AudioDeviceID SDLCALL tSDL_OpenAudioDevice(const char
+ *device,
+ int iscapture,
+ const
+ SDL_AudioSpec *
+ desired,
+ SDL_AudioSpec *
+ obtained,
+ int
+ allowed_changes);
+
+typedef enum
+{
+ SDL_AUDIO_STOPPED = 0,
+ SDL_AUDIO_PLAYING,
+ SDL_AUDIO_PAUSED
+} SDL_AudioStatus;
+typedef SDL_AudioStatus SDLCALL tSDL_GetAudioStatus(void);
+
+extern DECLSPEC SDL_AudioStatus SDLCALL
+SDL_GetAudioDeviceStatus(SDL_AudioDeviceID dev);
+
+typedef void SDLCALL tSDL_PauseAudio(int pause_on);
+typedef void SDLCALL tSDL_PauseAudioDevice(SDL_AudioDeviceID dev,
+ int pause_on);
+
+typedef SDL_AudioSpec * SDLCALL tSDL_LoadWAV_RW(SDL_RWops * src,
+ int freesrc,
+ SDL_AudioSpec * spec,
+ Uint8 ** audio_buf,
+ Uint32 * audio_len);
+
+#define SDL_LoadWAV(file, spec, audio_buf, audio_len) \
+ SDL_LoadWAV_RW(SDL_RWFromFile(file, "rb"),1, spec,audio_buf,audio_len)
+
+typedef void SDLCALL tSDL_FreeWAV(Uint8 * audio_buf);
+
+typedef int SDLCALL tSDL_BuildAudioCVT(SDL_AudioCVT * cvt,
+ SDL_AudioFormat src_format,
+ Uint8 src_channels,
+ int src_rate,
+ SDL_AudioFormat dst_format,
+ Uint8 dst_channels,
+ int dst_rate);
+
+typedef int SDLCALL tSDL_ConvertAudio(SDL_AudioCVT * cvt);
+
+#define SDL_MIX_MAXVOLUME 128
+
+typedef void SDLCALL tSDL_MixAudio(Uint8 * dst, const Uint8 * src,
+ Uint32 len, int volume);
+
+typedef void SDLCALL tSDL_MixAudioFormat(Uint8 * dst,
+ const Uint8 * src,
+ SDL_AudioFormat format,
+ Uint32 len, int volume);
+
+typedef void SDLCALL tSDL_LockAudio(void);
+typedef void SDLCALL tSDL_LockAudioDevice(SDL_AudioDeviceID dev);
+typedef void SDLCALL tSDL_UnlockAudio(void);
+typedef void SDLCALL tSDL_UnlockAudioDevice(SDL_AudioDeviceID dev);
+
+typedef void SDLCALL tSDL_CloseAudio(void);
+typedef void SDLCALL tSDL_CloseAudioDevice(SDL_AudioDeviceID dev);
+
+extern tSDL_GetNumAudioDrivers *SDL_GetNumAudioDrivers;
+extern tSDL_GetAudioDriver *SDL_GetAudioDriver;
+extern tSDL_AudioInit *SDL_AudioInit;
+extern tSDL_AudioQuit *SDL_AudioQuit;
+extern tSDL_GetCurrentAudioDriver *SDL_GetCurrentAudioDriver;
+extern tSDL_OpenAudio *SDL_OpenAudio;
+extern tSDL_GetNumAudioDevices *SDL_GetNumAudioDevices;
+extern tSDL_GetAudioDeviceName *SDL_GetAudioDeviceName;
+extern tSDL_OpenAudioDevice *SDL_OpenAudioDevice;
+extern tSDL_GetAudioStatus *SDL_GetAudioStatus;
+extern tSDL_PauseAudio *SDL_PauseAudio;
+extern tSDL_PauseAudioDevice *SDL_PauseAudioDevice;
+extern tSDL_LoadWAV_RW *SDL_LoadWAV_RW;
+extern tSDL_FreeWAV *SDL_FreeWAV;
+extern tSDL_BuildAudioCVT *SDL_BuildAudioCVT;
+extern tSDL_ConvertAudio *SDL_ConvertAudio;
+extern tSDL_MixAudio *SDL_MixAudio;
+extern tSDL_MixAudioFormat *SDL_MixAudioFormat;
+extern tSDL_LockAudio *SDL_LockAudio;
+extern tSDL_LockAudioDevice *SDL_LockAudioDevice;
+extern tSDL_UnlockAudio *SDL_UnlockAudio;
+extern tSDL_UnlockAudioDevice *SDL_UnlockAudioDevice;
+extern tSDL_CloseAudio *SDL_CloseAudio;
+extern tSDL_CloseAudioDevice *SDL_CloseAudioDevice;
+
+#ifdef __cplusplus
+}
+#endif
+#include "close_code.h"
+
+#endif
+
diff --git a/extern/sdlew/include/SDL2/SDL_bits.h b/extern/sdlew/include/SDL2/SDL_bits.h
new file mode 100644
index 00000000000..bb98c7d4144
--- /dev/null
+++ b/extern/sdlew/include/SDL2/SDL_bits.h
@@ -0,0 +1,53 @@
+
+#ifndef _SDL_bits_h
+#define _SDL_bits_h
+
+#include "SDL_stdinc.h"
+
+#include "begin_code.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+SDL_FORCE_INLINE int
+SDL_MostSignificantBitIndex32(Uint32 x)
+{
+#if defined(__GNUC__) && __GNUC__ >= 4
+
+ if (x == 0) {
+ return -1;
+ }
+ return 31 - __builtin_clz(x);
+#else
+
+ const Uint32 b[] = {0x2, 0xC, 0xF0, 0xFF00, 0xFFFF0000};
+ const int S[] = {1, 2, 4, 8, 16};
+
+ int msbIndex = 0;
+ int i;
+
+ if (x == 0) {
+ return -1;
+ }
+
+ for (i = 4; i >= 0; i--)
+ {
+ if (x & b[i])
+ {
+ x >>= S[i];
+ msbIndex |= S[i];
+ }
+ }
+
+ return msbIndex;
+#endif
+}
+
+#ifdef __cplusplus
+}
+#endif
+#include "close_code.h"
+
+#endif
+
diff --git a/extern/sdlew/include/SDL2/SDL_blendmode.h b/extern/sdlew/include/SDL2/SDL_blendmode.h
new file mode 100644
index 00000000000..3baa1e376f1
--- /dev/null
+++ b/extern/sdlew/include/SDL2/SDL_blendmode.h
@@ -0,0 +1,25 @@
+
+#ifndef _SDL_blendmode_h
+#define _SDL_blendmode_h
+
+#include "begin_code.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef enum
+{
+ SDL_BLENDMODE_NONE = 0x00000000,
+ SDL_BLENDMODE_BLEND = 0x00000001,
+ SDL_BLENDMODE_ADD = 0x00000002,
+ SDL_BLENDMODE_MOD = 0x00000004
+} SDL_BlendMode;
+
+#ifdef __cplusplus
+}
+#endif
+#include "close_code.h"
+
+#endif
+
diff --git a/extern/sdlew/include/SDL2/SDL_clipboard.h b/extern/sdlew/include/SDL2/SDL_clipboard.h
new file mode 100644
index 00000000000..61db474487e
--- /dev/null
+++ b/extern/sdlew/include/SDL2/SDL_clipboard.h
@@ -0,0 +1,29 @@
+
+#ifndef _SDL_clipboard_h
+#define _SDL_clipboard_h
+
+#include "SDL_stdinc.h"
+
+#include "begin_code.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef int SDLCALL tSDL_SetClipboardText(const char *text);
+
+typedef char * SDLCALL tSDL_GetClipboardText(void);
+
+typedef SDL_bool SDLCALL tSDL_HasClipboardText(void);
+
+extern tSDL_SetClipboardText *SDL_SetClipboardText;
+extern tSDL_GetClipboardText *SDL_GetClipboardText;
+extern tSDL_HasClipboardText *SDL_HasClipboardText;
+
+#ifdef __cplusplus
+}
+#endif
+#include "close_code.h"
+
+#endif
+
diff --git a/extern/sdlew/include/SDL2/SDL_config.h b/extern/sdlew/include/SDL2/SDL_config.h
new file mode 100644
index 00000000000..e7b0feef95c
--- /dev/null
+++ b/extern/sdlew/include/SDL2/SDL_config.h
@@ -0,0 +1,175 @@
+
+#ifndef _SDL_config_h
+#define _SDL_config_h
+
+#include "SDL_platform.h"
+
+#ifdef _MSC_VER
+#error You should run hg revert SDL_config.h
+#endif
+
+#ifdef __LP64__
+#define SIZEOF_VOIDP 8
+#else
+#define SIZEOF_VOIDP 4
+#endif
+#define HAVE_GCC_ATOMICS 1
+
+#define HAVE_PTHREAD_SPINLOCK 1
+
+#define HAVE_LIBC 1
+#if HAVE_LIBC
+
+#define HAVE_ALLOCA_H 1
+#define HAVE_SYS_TYPES_H 1
+#define HAVE_STDIO_H 1
+#define STDC_HEADERS 1
+#define HAVE_STDLIB_H 1
+#define HAVE_STDARG_H 1
+#define HAVE_MALLOC_H 1
+#define HAVE_MEMORY_H 1
+#define HAVE_STRING_H 1
+#define HAVE_STRINGS_H 1
+#define HAVE_INTTYPES_H 1
+#define HAVE_STDINT_H 1
+#define HAVE_CTYPE_H 1
+#define HAVE_MATH_H 1
+#define HAVE_ICONV_H 1
+#define HAVE_SIGNAL_H 1
+
+#define HAVE_LIBUDEV_H 1
+#define HAVE_DBUS_DBUS_H 1
+
+#define HAVE_MALLOC 1
+#define HAVE_CALLOC 1
+#define HAVE_REALLOC 1
+#define HAVE_FREE 1
+#define HAVE_ALLOCA 1
+#ifndef __WIN32__
+#define HAVE_GETENV 1
+#define HAVE_SETENV 1
+#define HAVE_PUTENV 1
+#define HAVE_UNSETENV 1
+#endif
+#define HAVE_QSORT 1
+#define HAVE_ABS 1
+#define HAVE_BCOPY 1
+#define HAVE_MEMSET 1
+#define HAVE_MEMCPY 1
+#define HAVE_MEMMOVE 1
+#define HAVE_MEMCMP 1
+#define HAVE_STRLEN 1
+
+#define HAVE_STRDUP 1
+
+#define HAVE_STRCHR 1
+#define HAVE_STRRCHR 1
+#define HAVE_STRSTR 1
+
+#define HAVE_STRTOL 1
+#define HAVE_STRTOUL 1
+
+#define HAVE_STRTOLL 1
+#define HAVE_STRTOULL 1
+#define HAVE_STRTOD 1
+#define HAVE_ATOI 1
+#define HAVE_ATOF 1
+#define HAVE_STRCMP 1
+#define HAVE_STRNCMP 1
+
+#define HAVE_STRCASECMP 1
+
+#define HAVE_STRNCASECMP 1
+#define HAVE_SSCANF 1
+#define HAVE_SNPRINTF 1
+#define HAVE_VSNPRINTF 1
+#define HAVE_M_PI
+#define HAVE_ATAN 1
+#define HAVE_ATAN2 1
+#define HAVE_CEIL 1
+#define HAVE_COPYSIGN 1
+#define HAVE_COS 1
+#define HAVE_COSF 1
+#define HAVE_FABS 1
+#define HAVE_FLOOR 1
+#define HAVE_LOG 1
+#define HAVE_POW 1
+#define HAVE_SCALBN 1
+#define HAVE_SIN 1
+#define HAVE_SINF 1
+#define HAVE_SQRT 1
+#define HAVE_FSEEKO 1
+#define HAVE_FSEEKO64 1
+#define HAVE_SIGACTION 1
+#define HAVE_SA_SIGACTION 1
+#define HAVE_SETJMP 1
+#define HAVE_NANOSLEEP 1
+#define HAVE_SYSCONF 1
+
+#define HAVE_CLOCK_GETTIME 1
+
+#define HAVE_MPROTECT 1
+#define HAVE_ICONV 1
+#define HAVE_PTHREAD_SETNAME_NP 1
+
+#define HAVE_SEM_TIMEDWAIT 1
+
+#else
+#define HAVE_STDARG_H 1
+#define HAVE_STDDEF_H 1
+#define HAVE_STDINT_H 1
+#endif
+
+#define SDL_LOADSO_DISABLED 1
+
+#define SDL_AUDIO_DRIVER_ALSA 1
+
+#define SDL_AUDIO_DRIVER_PULSEAUDIO 1
+
+#define SDL_AUDIO_DRIVER_DISK 1
+#define SDL_AUDIO_DRIVER_DUMMY 1
+
+#define SDL_AUDIO_DRIVER_OSS 1
+
+#define SDL_INPUT_LINUXEV 1
+#define SDL_INPUT_TSLIB 1
+
+#define SDL_JOYSTICK_LINUX 1
+
+#define SDL_HAPTIC_LINUX 1
+
+#define SDL_LOADSO_DLOPEN 1
+
+#define SDL_THREAD_PTHREAD 1
+#define SDL_THREAD_PTHREAD_RECURSIVE_MUTEX 1
+
+#define SDL_TIMER_UNIX 1
+
+#define SDL_VIDEO_DRIVER_DUMMY 1
+
+#define SDL_VIDEO_DRIVER_X11 1
+
+#define SDL_VIDEO_DRIVER_X11_XCURSOR 1
+#define SDL_VIDEO_DRIVER_X11_XINERAMA 1
+#define SDL_VIDEO_DRIVER_X11_XINPUT2 1
+#define SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_MULTITOUCH 1
+#define SDL_VIDEO_DRIVER_X11_XRANDR 1
+#define SDL_VIDEO_DRIVER_X11_XSCRNSAVER 1
+#define SDL_VIDEO_DRIVER_X11_XSHAPE 1
+#define SDL_VIDEO_DRIVER_X11_XVIDMODE 1
+#define SDL_VIDEO_DRIVER_X11_SUPPORTS_GENERIC_EVENTS 1
+
+#define SDL_VIDEO_DRIVER_X11_CONST_PARAM_XEXTADDDISPLAY 1
+#define SDL_VIDEO_DRIVER_X11_HAS_XKBKEYCODETOKEYSYM 1
+
+#define SDL_VIDEO_RENDER_OGL 1
+
+#define SDL_VIDEO_OPENGL 1
+
+#define SDL_VIDEO_OPENGL_GLX 1
+
+#define SDL_POWER_LINUX 1
+
+#define SDL_ASSEMBLY_ROUTINES 1
+
+#endif
diff --git a/extern/sdlew/include/SDL2/SDL_cpuinfo.h b/extern/sdlew/include/SDL2/SDL_cpuinfo.h
new file mode 100644
index 00000000000..830f8d537dd
--- /dev/null
+++ b/extern/sdlew/include/SDL2/SDL_cpuinfo.h
@@ -0,0 +1,86 @@
+
+#ifndef _SDL_cpuinfo_h
+#define _SDL_cpuinfo_h
+
+#include "SDL_stdinc.h"
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1500)
+#include <intrin.h>
+#ifndef _WIN64
+#define __MMX__
+#define __3dNOW__
+#endif
+#define __SSE__
+#define __SSE2__
+#elif defined(__MINGW64_VERSION_MAJOR)
+#include <intrin.h>
+#else
+#ifdef __ALTIVEC__
+#if HAVE_ALTIVEC_H && !defined(__APPLE_ALTIVEC__)
+#include <altivec.h>
+#undef pixel
+#endif
+#endif
+#ifdef __MMX__
+#include <mmintrin.h>
+#endif
+#ifdef __3dNOW__
+#include <mm3dnow.h>
+#endif
+#ifdef __SSE__
+#include <xmmintrin.h>
+#endif
+#ifdef __SSE2__
+#include <emmintrin.h>
+#endif
+#endif
+
+#include "begin_code.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define SDL_CACHELINE_SIZE 128
+
+typedef int SDLCALL tSDL_GetCPUCount(void);
+
+typedef int SDLCALL tSDL_GetCPUCacheLineSize(void);
+
+typedef SDL_bool SDLCALL tSDL_HasRDTSC(void);
+
+typedef SDL_bool SDLCALL tSDL_HasAltiVec(void);
+
+typedef SDL_bool SDLCALL tSDL_HasMMX(void);
+
+typedef SDL_bool SDLCALL tSDL_Has3DNow(void);
+
+typedef SDL_bool SDLCALL tSDL_HasSSE(void);
+
+typedef SDL_bool SDLCALL tSDL_HasSSE2(void);
+
+typedef SDL_bool SDLCALL tSDL_HasSSE3(void);
+
+typedef SDL_bool SDLCALL tSDL_HasSSE41(void);
+
+typedef SDL_bool SDLCALL tSDL_HasSSE42(void);
+
+extern tSDL_GetCPUCount *SDL_GetCPUCount;
+extern tSDL_GetCPUCacheLineSize *SDL_GetCPUCacheLineSize;
+extern tSDL_HasRDTSC *SDL_HasRDTSC;
+extern tSDL_HasAltiVec *SDL_HasAltiVec;
+extern tSDL_HasMMX *SDL_HasMMX;
+extern tSDL_Has3DNow *SDL_Has3DNow;
+extern tSDL_HasSSE *SDL_HasSSE;
+extern tSDL_HasSSE2 *SDL_HasSSE2;
+extern tSDL_HasSSE3 *SDL_HasSSE3;
+extern tSDL_HasSSE41 *SDL_HasSSE41;
+extern tSDL_HasSSE42 *SDL_HasSSE42;
+
+#ifdef __cplusplus
+}
+#endif
+#include "close_code.h"
+
+#endif
+
diff --git a/extern/sdlew/include/SDL2/SDL_endian.h b/extern/sdlew/include/SDL2/SDL_endian.h
new file mode 100644
index 00000000000..f039f0ebdec
--- /dev/null
+++ b/extern/sdlew/include/SDL2/SDL_endian.h
@@ -0,0 +1,193 @@
+
+#ifndef _SDL_endian_h
+#define _SDL_endian_h
+
+#include "SDL_stdinc.h"
+
+#define SDL_LIL_ENDIAN 1234
+#define SDL_BIG_ENDIAN 4321
+
+#ifndef SDL_BYTEORDER
+#ifdef __linux__
+#include <endian.h>
+#define SDL_BYTEORDER __BYTE_ORDER
+#else
+#if defined(__hppa__) || \
+ defined(__m68k__) || defined(mc68000) || defined(_M_M68K) || \
+ (defined(__MIPS__) && defined(__MISPEB__)) || \
+ defined(__ppc__) || defined(__POWERPC__) || defined(_M_PPC) || \
+ defined(__sparc__)
+#define SDL_BYTEORDER SDL_BIG_ENDIAN
+#else
+#define SDL_BYTEORDER SDL_LIL_ENDIAN
+#endif
+#endif
+#endif
+
+#include "begin_code.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if defined(__GNUC__) && defined(__i386__) && \
+ !(__GNUC__ == 2 && __GNUC_MINOR__ == 95 )
+SDL_FORCE_INLINE Uint16
+SDL_Swap16(Uint16 x)
+{
+ __asm__("xchgb %b0,%h0": "=q"(x):"0"(x));
+ return x;
+}
+#elif defined(__GNUC__) && defined(__x86_64__)
+SDL_FORCE_INLINE Uint16
+SDL_Swap16(Uint16 x)
+{
+ __asm__("xchgb %b0,%h0": "=Q"(x):"0"(x));
+ return x;
+}
+#elif defined(__GNUC__) && (defined(__powerpc__) || defined(__ppc__))
+SDL_FORCE_INLINE Uint16
+SDL_Swap16(Uint16 x)
+{
+ int result;
+
+ __asm__("rlwimi %0,%2,8,16,23": "=&r"(result):"0"(x >> 8), "r"(x));
+ return (Uint16)result;
+}
+#elif defined(__GNUC__) && (defined(__M68000__) || defined(__M68020__)) && !defined(__mcoldfire__)
+SDL_FORCE_INLINE Uint16
+SDL_Swap16(Uint16 x)
+{
+ __asm__("rorw #8,%0": "=d"(x): "0"(x):"cc");
+ return x;
+}
+#else
+SDL_FORCE_INLINE Uint16
+SDL_Swap16(Uint16 x)
+{
+ return SDL_static_cast(Uint16, ((x << 8) | (x >> 8)));
+}
+#endif
+
+#if defined(__GNUC__) && defined(__i386__)
+SDL_FORCE_INLINE Uint32
+SDL_Swap32(Uint32 x)
+{
+ __asm__("bswap %0": "=r"(x):"0"(x));
+ return x;
+}
+#elif defined(__GNUC__) && defined(__x86_64__)
+SDL_FORCE_INLINE Uint32
+SDL_Swap32(Uint32 x)
+{
+ __asm__("bswapl %0": "=r"(x):"0"(x));
+ return x;
+}
+#elif defined(__GNUC__) && (defined(__powerpc__) || defined(__ppc__))
+SDL_FORCE_INLINE Uint32
+SDL_Swap32(Uint32 x)
+{
+ Uint32 result;
+
+ __asm__("rlwimi %0,%2,24,16,23": "=&r"(result):"0"(x >> 24), "r"(x));
+ __asm__("rlwimi %0,%2,8,8,15": "=&r"(result):"0"(result), "r"(x));
+ __asm__("rlwimi %0,%2,24,0,7": "=&r"(result):"0"(result), "r"(x));
+ return result;
+}
+#elif defined(__GNUC__) && (defined(__M68000__) || defined(__M68020__)) && !defined(__mcoldfire__)
+SDL_FORCE_INLINE Uint32
+SDL_Swap32(Uint32 x)
+{
+ __asm__("rorw #8,%0\n\tswap %0\n\trorw #8,%0": "=d"(x): "0"(x):"cc");
+ return x;
+}
+#else
+SDL_FORCE_INLINE Uint32
+SDL_Swap32(Uint32 x)
+{
+ return SDL_static_cast(Uint32, ((x << 24) | ((x << 8) & 0x00FF0000) |
+ ((x >> 8) & 0x0000FF00) | (x >> 24)));
+}
+#endif
+
+#if defined(__GNUC__) && defined(__i386__)
+SDL_FORCE_INLINE Uint64
+SDL_Swap64(Uint64 x)
+{
+ union
+ {
+ struct
+ {
+ Uint32 a, b;
+ } s;
+ Uint64 u;
+ } v;
+ v.u = x;
+ __asm__("bswapl %0 ; bswapl %1 ; xchgl %0,%1": "=r"(v.s.a), "=r"(v.s.b):"0"(v.s.a),
+ "1"(v.s.
+ b));
+ return v.u;
+}
+#elif defined(__GNUC__) && defined(__x86_64__)
+SDL_FORCE_INLINE Uint64
+SDL_Swap64(Uint64 x)
+{
+ __asm__("bswapq %0": "=r"(x):"0"(x));
+ return x;
+}
+#else
+SDL_FORCE_INLINE Uint64
+SDL_Swap64(Uint64 x)
+{
+ Uint32 hi, lo;
+
+ lo = SDL_static_cast(Uint32, x & 0xFFFFFFFF);
+ x >>= 32;
+ hi = SDL_static_cast(Uint32, x & 0xFFFFFFFF);
+ x = SDL_Swap32(lo);
+ x <<= 32;
+ x |= SDL_Swap32(hi);
+ return (x);
+}
+#endif
+
+SDL_FORCE_INLINE float
+SDL_SwapFloat(float x)
+{
+ union
+ {
+ float f;
+ Uint32 ui32;
+ } swapper;
+ swapper.f = x;
+ swapper.ui32 = SDL_Swap32(swapper.ui32);
+ return swapper.f;
+}
+
+#if SDL_BYTEORDER == SDL_LIL_ENDIAN
+#define SDL_SwapLE16(X) (X)
+#define SDL_SwapLE32(X) (X)
+#define SDL_SwapLE64(X) (X)
+#define SDL_SwapFloatLE(X) (X)
+#define SDL_SwapBE16(X) SDL_Swap16(X)
+#define SDL_SwapBE32(X) SDL_Swap32(X)
+#define SDL_SwapBE64(X) SDL_Swap64(X)
+#define SDL_SwapFloatBE(X) SDL_SwapFloat(X)
+#else
+#define SDL_SwapLE16(X) SDL_Swap16(X)
+#define SDL_SwapLE32(X) SDL_Swap32(X)
+#define SDL_SwapLE64(X) SDL_Swap64(X)
+#define SDL_SwapFloatLE(X) SDL_SwapFloat(X)
+#define SDL_SwapBE16(X) (X)
+#define SDL_SwapBE32(X) (X)
+#define SDL_SwapBE64(X) (X)
+#define SDL_SwapFloatBE(X) (X)
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+#include "close_code.h"
+
+#endif
+
diff --git a/extern/sdlew/include/SDL2/SDL_error.h b/extern/sdlew/include/SDL2/SDL_error.h
new file mode 100644
index 00000000000..8bef6c109be
--- /dev/null
+++ b/extern/sdlew/include/SDL2/SDL_error.h
@@ -0,0 +1,43 @@
+
+#ifndef _SDL_error_h
+#define _SDL_error_h
+
+#include "SDL_stdinc.h"
+
+#include "begin_code.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef int SDLCALL tSDL_SetError(const char *fmt, ...);
+typedef const char * SDLCALL tSDL_GetError(void);
+typedef void SDLCALL tSDL_ClearError(void);
+
+#define SDL_OutOfMemory() SDL_Error(SDL_ENOMEM)
+#define SDL_Unsupported() SDL_Error(SDL_UNSUPPORTED)
+#define SDL_InvalidParamError(param) SDL_SetError("Parameter '%s' is invalid", (param))
+typedef enum
+{
+ SDL_ENOMEM,
+ SDL_EFREAD,
+ SDL_EFWRITE,
+ SDL_EFSEEK,
+ SDL_UNSUPPORTED,
+ SDL_LASTERROR
+} SDL_errorcode;
+
+typedef int SDLCALL tSDL_Error(SDL_errorcode code);
+
+extern tSDL_SetError *SDL_SetError;
+extern tSDL_GetError *SDL_GetError;
+extern tSDL_ClearError *SDL_ClearError;
+extern tSDL_Error *SDL_Error;
+
+#ifdef __cplusplus
+}
+#endif
+#include "close_code.h"
+
+#endif
+
diff --git a/extern/sdlew/include/SDL2/SDL_events.h b/extern/sdlew/include/SDL2/SDL_events.h
new file mode 100644
index 00000000000..41a0b479703
--- /dev/null
+++ b/extern/sdlew/include/SDL2/SDL_events.h
@@ -0,0 +1,446 @@
+
+#ifndef _SDL_events_h
+#define _SDL_events_h
+
+#include "SDL_stdinc.h"
+#include "SDL_error.h"
+#include "SDL_video.h"
+#include "SDL_keyboard.h"
+#include "SDL_mouse.h"
+#include "SDL_joystick.h"
+#include "SDL_gamecontroller.h"
+#include "SDL_quit.h"
+#include "SDL_gesture.h"
+#include "SDL_touch.h"
+
+#include "begin_code.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define SDL_RELEASED 0
+#define SDL_PRESSED 1
+
+typedef enum
+{
+ SDL_FIRSTEVENT = 0,
+
+ SDL_QUIT = 0x100,
+
+ SDL_APP_TERMINATING,
+ SDL_APP_LOWMEMORY,
+ SDL_APP_WILLENTERBACKGROUND,
+ SDL_APP_DIDENTERBACKGROUND,
+ SDL_APP_WILLENTERFOREGROUND,
+ SDL_APP_DIDENTERFOREGROUND,
+
+ SDL_WINDOWEVENT = 0x200,
+ SDL_SYSWMEVENT,
+
+ SDL_KEYDOWN = 0x300,
+ SDL_KEYUP,
+ SDL_TEXTEDITING,
+ SDL_TEXTINPUT,
+
+ SDL_MOUSEMOTION = 0x400,
+ SDL_MOUSEBUTTONDOWN,
+ SDL_MOUSEBUTTONUP,
+ SDL_MOUSEWHEEL,
+
+ SDL_JOYAXISMOTION = 0x600,
+ SDL_JOYBALLMOTION,
+ SDL_JOYHATMOTION,
+ SDL_JOYBUTTONDOWN,
+ SDL_JOYBUTTONUP,
+ SDL_JOYDEVICEADDED,
+ SDL_JOYDEVICEREMOVED,
+
+ SDL_CONTROLLERAXISMOTION = 0x650,
+ SDL_CONTROLLERBUTTONDOWN,
+ SDL_CONTROLLERBUTTONUP,
+ SDL_CONTROLLERDEVICEADDED,
+ SDL_CONTROLLERDEVICEREMOVED,
+ SDL_CONTROLLERDEVICEREMAPPED,
+
+ SDL_FINGERDOWN = 0x700,
+ SDL_FINGERUP,
+ SDL_FINGERMOTION,
+
+ SDL_DOLLARGESTURE = 0x800,
+ SDL_DOLLARRECORD,
+ SDL_MULTIGESTURE,
+
+ SDL_CLIPBOARDUPDATE = 0x900,
+
+ SDL_DROPFILE = 0x1000,
+
+ SDL_USEREVENT = 0x8000,
+
+ SDL_LASTEVENT = 0xFFFF
+} SDL_EventType;
+
+typedef struct SDL_CommonEvent
+{
+ Uint32 type;
+ Uint32 timestamp;
+} SDL_CommonEvent;
+
+typedef struct SDL_WindowEvent
+{
+ Uint32 type;
+ Uint32 timestamp;
+ Uint32 windowID;
+ Uint8 event;
+ Uint8 padding1;
+ Uint8 padding2;
+ Uint8 padding3;
+ Sint32 data1;
+ Sint32 data2;
+} SDL_WindowEvent;
+
+typedef struct SDL_KeyboardEvent
+{
+ Uint32 type;
+ Uint32 timestamp;
+ Uint32 windowID;
+ Uint8 state;
+ Uint8 repeat;
+ Uint8 padding2;
+ Uint8 padding3;
+ SDL_Keysym keysym;
+} SDL_KeyboardEvent;
+
+#define SDL_TEXTEDITINGEVENT_TEXT_SIZE (32)
+
+typedef struct SDL_TextEditingEvent
+{
+ Uint32 type;
+ Uint32 timestamp;
+ Uint32 windowID;
+ char text[SDL_TEXTEDITINGEVENT_TEXT_SIZE];
+ Sint32 start;
+ Sint32 length;
+} SDL_TextEditingEvent;
+
+#define SDL_TEXTINPUTEVENT_TEXT_SIZE (32)
+
+typedef struct SDL_TextInputEvent
+{
+ Uint32 type;
+ Uint32 timestamp;
+ Uint32 windowID;
+ char text[SDL_TEXTINPUTEVENT_TEXT_SIZE];
+} SDL_TextInputEvent;
+
+typedef struct SDL_MouseMotionEvent
+{
+ Uint32 type;
+ Uint32 timestamp;
+ Uint32 windowID;
+ Uint32 which;
+ Uint32 state;
+ Sint32 x;
+ Sint32 y;
+ Sint32 xrel;
+ Sint32 yrel;
+} SDL_MouseMotionEvent;
+
+typedef struct SDL_MouseButtonEvent
+{
+ Uint32 type;
+ Uint32 timestamp;
+ Uint32 windowID;
+ Uint32 which;
+ Uint8 button;
+ Uint8 state;
+ Uint8 padding1;
+ Uint8 padding2;
+ Sint32 x;
+ Sint32 y;
+} SDL_MouseButtonEvent;
+
+typedef struct SDL_MouseWheelEvent
+{
+ Uint32 type;
+ Uint32 timestamp;
+ Uint32 windowID;
+ Uint32 which;
+ Sint32 x;
+ Sint32 y;
+} SDL_MouseWheelEvent;
+
+typedef struct SDL_JoyAxisEvent
+{
+ Uint32 type;
+ Uint32 timestamp;
+ SDL_JoystickID which;
+ Uint8 axis;
+ Uint8 padding1;
+ Uint8 padding2;
+ Uint8 padding3;
+ Sint16 value;
+ Uint16 padding4;
+} SDL_JoyAxisEvent;
+
+typedef struct SDL_JoyBallEvent
+{
+ Uint32 type;
+ Uint32 timestamp;
+ SDL_JoystickID which;
+ Uint8 ball;
+ Uint8 padding1;
+ Uint8 padding2;
+ Uint8 padding3;
+ Sint16 xrel;
+ Sint16 yrel;
+} SDL_JoyBallEvent;
+
+typedef struct SDL_JoyHatEvent
+{
+ Uint32 type;
+ Uint32 timestamp;
+ SDL_JoystickID which;
+ Uint8 hat;
+ Uint8 value;
+ Uint8 padding1;
+ Uint8 padding2;
+} SDL_JoyHatEvent;
+
+typedef struct SDL_JoyButtonEvent
+{
+ Uint32 type;
+ Uint32 timestamp;
+ SDL_JoystickID which;
+ Uint8 button;
+ Uint8 state;
+ Uint8 padding1;
+ Uint8 padding2;
+} SDL_JoyButtonEvent;
+
+typedef struct SDL_JoyDeviceEvent
+{
+ Uint32 type;
+ Uint32 timestamp;
+ Sint32 which;
+} SDL_JoyDeviceEvent;
+
+typedef struct SDL_ControllerAxisEvent
+{
+ Uint32 type;
+ Uint32 timestamp;
+ SDL_JoystickID which;
+ Uint8 axis;
+ Uint8 padding1;
+ Uint8 padding2;
+ Uint8 padding3;
+ Sint16 value;
+ Uint16 padding4;
+} SDL_ControllerAxisEvent;
+
+typedef struct SDL_ControllerButtonEvent
+{
+ Uint32 type;
+ Uint32 timestamp;
+ SDL_JoystickID which;
+ Uint8 button;
+ Uint8 state;
+ Uint8 padding1;
+ Uint8 padding2;
+} SDL_ControllerButtonEvent;
+
+typedef struct SDL_ControllerDeviceEvent
+{
+ Uint32 type;
+ Uint32 timestamp;
+ Sint32 which;
+} SDL_ControllerDeviceEvent;
+
+typedef struct SDL_TouchFingerEvent
+{
+ Uint32 type;
+ Uint32 timestamp;
+ SDL_TouchID touchId;
+ SDL_FingerID fingerId;
+ float x;
+ float y;
+ float dx;
+ float dy;
+ float pressure;
+} SDL_TouchFingerEvent;
+
+typedef struct SDL_MultiGestureEvent
+{
+ Uint32 type;
+ Uint32 timestamp;
+ SDL_TouchID touchId;
+ float dTheta;
+ float dDist;
+ float x;
+ float y;
+ Uint16 numFingers;
+ Uint16 padding;
+} SDL_MultiGestureEvent;
+
+typedef struct SDL_DollarGestureEvent
+{
+ Uint32 type;
+ Uint32 timestamp;
+ SDL_TouchID touchId;
+ SDL_GestureID gestureId;
+ Uint32 numFingers;
+ float error;
+ float x;
+ float y;
+} SDL_DollarGestureEvent;
+
+typedef struct SDL_DropEvent
+{
+ Uint32 type;
+ Uint32 timestamp;
+ char *file;
+} SDL_DropEvent;
+
+typedef struct SDL_QuitEvent
+{
+ Uint32 type;
+ Uint32 timestamp;
+} SDL_QuitEvent;
+
+typedef struct SDL_OSEvent
+{
+ Uint32 type;
+ Uint32 timestamp;
+} SDL_OSEvent;
+
+typedef struct SDL_UserEvent
+{
+ Uint32 type;
+ Uint32 timestamp;
+ Uint32 windowID;
+ Sint32 code;
+ void *data1;
+ void *data2;
+} SDL_UserEvent;
+
+struct SDL_SysWMmsg;
+typedef struct SDL_SysWMmsg SDL_SysWMmsg;
+
+typedef struct SDL_SysWMEvent
+{
+ Uint32 type;
+ Uint32 timestamp;
+ SDL_SysWMmsg *msg;
+} SDL_SysWMEvent;
+
+typedef union SDL_Event
+{
+ Uint32 type;
+ SDL_CommonEvent common;
+ SDL_WindowEvent window;
+ SDL_KeyboardEvent key;
+ SDL_TextEditingEvent edit;
+ SDL_TextInputEvent text;
+ SDL_MouseMotionEvent motion;
+ SDL_MouseButtonEvent button;
+ SDL_MouseWheelEvent wheel;
+ SDL_JoyAxisEvent jaxis;
+ SDL_JoyBallEvent jball;
+ SDL_JoyHatEvent jhat;
+ SDL_JoyButtonEvent jbutton;
+ SDL_JoyDeviceEvent jdevice;
+ SDL_ControllerAxisEvent caxis;
+ SDL_ControllerButtonEvent cbutton;
+ SDL_ControllerDeviceEvent cdevice;
+ SDL_QuitEvent quit;
+ SDL_UserEvent user;
+ SDL_SysWMEvent syswm;
+ SDL_TouchFingerEvent tfinger;
+ SDL_MultiGestureEvent mgesture;
+ SDL_DollarGestureEvent dgesture;
+ SDL_DropEvent drop;
+
+ Uint8 padding[56];
+} SDL_Event;
+
+typedef void SDLCALL tSDL_PumpEvents(void);
+
+typedef enum
+{
+ SDL_ADDEVENT,
+ SDL_PEEKEVENT,
+ SDL_GETEVENT
+} SDL_eventaction;
+
+typedef int SDLCALL tSDL_PeepEvents(SDL_Event * events, int numevents,
+ SDL_eventaction action,
+ Uint32 minType, Uint32 maxType);
+
+typedef SDL_bool SDLCALL tSDL_HasEvent(Uint32 type);
+typedef SDL_bool SDLCALL tSDL_HasEvents(Uint32 minType, Uint32 maxType);
+
+typedef void SDLCALL tSDL_FlushEvent(Uint32 type);
+typedef void SDLCALL tSDL_FlushEvents(Uint32 minType, Uint32 maxType);
+
+typedef int SDLCALL tSDL_PollEvent(SDL_Event * event);
+
+typedef int SDLCALL tSDL_WaitEvent(SDL_Event * event);
+
+typedef int SDLCALL tSDL_WaitEventTimeout(SDL_Event * event,
+ int timeout);
+
+typedef int SDLCALL tSDL_PushEvent(SDL_Event * event);
+
+typedef int (SDLCALL * SDL_EventFilter) (void *userdata, SDL_Event * event);
+
+typedef void SDLCALL tSDL_SetEventFilter(SDL_EventFilter filter,
+ void *userdata);
+
+typedef SDL_bool SDLCALL tSDL_GetEventFilter(SDL_EventFilter * filter,
+ void **userdata);
+
+typedef void SDLCALL tSDL_AddEventWatch(SDL_EventFilter filter,
+ void *userdata);
+
+typedef void SDLCALL tSDL_DelEventWatch(SDL_EventFilter filter,
+ void *userdata);
+
+typedef void SDLCALL tSDL_FilterEvents(SDL_EventFilter filter,
+ void *userdata);
+
+#define SDL_QUERY -1
+#define SDL_IGNORE 0
+#define SDL_DISABLE 0
+#define SDL_ENABLE 1
+
+typedef Uint8 SDLCALL tSDL_EventState(Uint32 type, int state);
+
+#define SDL_GetEventState(type) SDL_EventState(type, SDL_QUERY)
+
+typedef Uint32 SDLCALL tSDL_RegisterEvents(int numevents);
+
+extern tSDL_PumpEvents *SDL_PumpEvents;
+extern tSDL_PeepEvents *SDL_PeepEvents;
+extern tSDL_HasEvent *SDL_HasEvent;
+extern tSDL_HasEvents *SDL_HasEvents;
+extern tSDL_FlushEvent *SDL_FlushEvent;
+extern tSDL_FlushEvents *SDL_FlushEvents;
+extern tSDL_PollEvent *SDL_PollEvent;
+extern tSDL_WaitEvent *SDL_WaitEvent;
+extern tSDL_WaitEventTimeout *SDL_WaitEventTimeout;
+extern tSDL_PushEvent *SDL_PushEvent;
+extern tSDL_SetEventFilter *SDL_SetEventFilter;
+extern tSDL_GetEventFilter *SDL_GetEventFilter;
+extern tSDL_AddEventWatch *SDL_AddEventWatch;
+extern tSDL_DelEventWatch *SDL_DelEventWatch;
+extern tSDL_FilterEvents *SDL_FilterEvents;
+extern tSDL_EventState *SDL_EventState;
+extern tSDL_RegisterEvents *SDL_RegisterEvents;
+
+#ifdef __cplusplus
+}
+#endif
+#include "close_code.h"
+
+#endif
+
diff --git a/extern/sdlew/include/SDL2/SDL_gamecontroller.h b/extern/sdlew/include/SDL2/SDL_gamecontroller.h
new file mode 100644
index 00000000000..baed2bd173a
--- /dev/null
+++ b/extern/sdlew/include/SDL2/SDL_gamecontroller.h
@@ -0,0 +1,143 @@
+
+#ifndef _SDL_gamecontroller_h
+#define _SDL_gamecontroller_h
+
+#include "SDL_stdinc.h"
+#include "SDL_error.h"
+#include "SDL_joystick.h"
+
+#include "begin_code.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct _SDL_GameController;
+typedef struct _SDL_GameController SDL_GameController;
+
+typedef enum
+{
+ SDL_CONTROLLER_BINDTYPE_NONE = 0,
+ SDL_CONTROLLER_BINDTYPE_BUTTON,
+ SDL_CONTROLLER_BINDTYPE_AXIS,
+ SDL_CONTROLLER_BINDTYPE_HAT
+} SDL_GameControllerBindType;
+
+typedef struct SDL_GameControllerButtonBind
+{
+ SDL_GameControllerBindType bindType;
+ union
+ {
+ int button;
+ int axis;
+ struct {
+ int hat;
+ int hat_mask;
+ } hat;
+ } value;
+
+} SDL_GameControllerButtonBind;
+
+typedef int SDLCALL tSDL_GameControllerAddMapping( const char* mappingString );
+
+typedef char * SDLCALL tSDL_GameControllerMappingForGUID( SDL_JoystickGUID guid );
+
+typedef char * SDLCALL tSDL_GameControllerMapping( SDL_GameController * gamecontroller );
+
+typedef SDL_bool SDLCALL tSDL_IsGameController(int joystick_index);
+
+typedef const char * SDLCALL tSDL_GameControllerNameForIndex(int joystick_index);
+
+typedef SDL_GameController * SDLCALL tSDL_GameControllerOpen(int joystick_index);
+
+typedef const char * SDLCALL tSDL_GameControllerName(SDL_GameController *gamecontroller);
+
+typedef SDL_bool SDLCALL tSDL_GameControllerGetAttached(SDL_GameController *gamecontroller);
+
+typedef SDL_Joystick * SDLCALL tSDL_GameControllerGetJoystick(SDL_GameController *gamecontroller);
+
+typedef int SDLCALL tSDL_GameControllerEventState(int state);
+
+typedef void SDLCALL tSDL_GameControllerUpdate(void);
+
+typedef enum
+{
+ SDL_CONTROLLER_AXIS_INVALID = -1,
+ SDL_CONTROLLER_AXIS_LEFTX,
+ SDL_CONTROLLER_AXIS_LEFTY,
+ SDL_CONTROLLER_AXIS_RIGHTX,
+ SDL_CONTROLLER_AXIS_RIGHTY,
+ SDL_CONTROLLER_AXIS_TRIGGERLEFT,
+ SDL_CONTROLLER_AXIS_TRIGGERRIGHT,
+ SDL_CONTROLLER_AXIS_MAX
+} SDL_GameControllerAxis;
+
+typedef SDL_GameControllerAxis SDLCALL tSDL_GameControllerGetAxisFromString(const char *pchString);
+
+extern DECLSPEC const char* SDLCALL SDL_GameControllerGetStringForAxis(SDL_GameControllerAxis axis);
+
+extern DECLSPEC SDL_GameControllerButtonBind SDLCALL
+SDL_GameControllerGetBindForAxis(SDL_GameController *gamecontroller,
+ SDL_GameControllerAxis axis);
+
+extern DECLSPEC Sint16 SDLCALL
+SDL_GameControllerGetAxis(SDL_GameController *gamecontroller,
+ SDL_GameControllerAxis axis);
+
+typedef enum
+{
+ SDL_CONTROLLER_BUTTON_INVALID = -1,
+ SDL_CONTROLLER_BUTTON_A,
+ SDL_CONTROLLER_BUTTON_B,
+ SDL_CONTROLLER_BUTTON_X,
+ SDL_CONTROLLER_BUTTON_Y,
+ SDL_CONTROLLER_BUTTON_BACK,
+ SDL_CONTROLLER_BUTTON_GUIDE,
+ SDL_CONTROLLER_BUTTON_START,
+ SDL_CONTROLLER_BUTTON_LEFTSTICK,
+ SDL_CONTROLLER_BUTTON_RIGHTSTICK,
+ SDL_CONTROLLER_BUTTON_LEFTSHOULDER,
+ SDL_CONTROLLER_BUTTON_RIGHTSHOULDER,
+ SDL_CONTROLLER_BUTTON_DPAD_UP,
+ SDL_CONTROLLER_BUTTON_DPAD_DOWN,
+ SDL_CONTROLLER_BUTTON_DPAD_LEFT,
+ SDL_CONTROLLER_BUTTON_DPAD_RIGHT,
+ SDL_CONTROLLER_BUTTON_MAX
+} SDL_GameControllerButton;
+
+typedef SDL_GameControllerButton SDLCALL tSDL_GameControllerGetButtonFromString(const char *pchString);
+
+extern DECLSPEC const char* SDLCALL SDL_GameControllerGetStringForButton(SDL_GameControllerButton button);
+
+extern DECLSPEC SDL_GameControllerButtonBind SDLCALL
+SDL_GameControllerGetBindForButton(SDL_GameController *gamecontroller,
+ SDL_GameControllerButton button);
+
+typedef Uint8 SDLCALL tSDL_GameControllerGetButton(SDL_GameController *gamecontroller,
+ SDL_GameControllerButton button);
+
+typedef void SDLCALL tSDL_GameControllerClose(SDL_GameController *gamecontroller);
+
+extern tSDL_GameControllerAddMapping *SDL_GameControllerAddMapping;
+extern tSDL_GameControllerMappingForGUID *SDL_GameControllerMappingForGUID;
+extern tSDL_GameControllerMapping *SDL_GameControllerMapping;
+extern tSDL_IsGameController *SDL_IsGameController;
+extern tSDL_GameControllerNameForIndex *SDL_GameControllerNameForIndex;
+extern tSDL_GameControllerOpen *SDL_GameControllerOpen;
+extern tSDL_GameControllerName *SDL_GameControllerName;
+extern tSDL_GameControllerGetAttached *SDL_GameControllerGetAttached;
+extern tSDL_GameControllerGetJoystick *SDL_GameControllerGetJoystick;
+extern tSDL_GameControllerEventState *SDL_GameControllerEventState;
+extern tSDL_GameControllerUpdate *SDL_GameControllerUpdate;
+extern tSDL_GameControllerGetAxisFromString *SDL_GameControllerGetAxisFromString;
+extern tSDL_GameControllerGetButtonFromString *SDL_GameControllerGetButtonFromString;
+extern tSDL_GameControllerGetButton *SDL_GameControllerGetButton;
+extern tSDL_GameControllerClose *SDL_GameControllerClose;
+
+#ifdef __cplusplus
+}
+#endif
+#include "close_code.h"
+
+#endif
+
diff --git a/extern/sdlew/include/SDL2/SDL_gesture.h b/extern/sdlew/include/SDL2/SDL_gesture.h
new file mode 100644
index 00000000000..9909d9d13d1
--- /dev/null
+++ b/extern/sdlew/include/SDL2/SDL_gesture.h
@@ -0,0 +1,38 @@
+
+#ifndef _SDL_gesture_h
+#define _SDL_gesture_h
+
+#include "SDL_stdinc.h"
+#include "SDL_error.h"
+#include "SDL_video.h"
+
+#include "SDL_touch.h"
+
+#include "begin_code.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef Sint64 SDL_GestureID;
+
+typedef int SDLCALL tSDL_RecordGesture(SDL_TouchID touchId);
+
+typedef int SDLCALL tSDL_SaveAllDollarTemplates(SDL_RWops *src);
+
+typedef int SDLCALL tSDL_SaveDollarTemplate(SDL_GestureID gestureId,SDL_RWops *src);
+
+typedef int SDLCALL tSDL_LoadDollarTemplates(SDL_TouchID touchId, SDL_RWops *src);
+
+extern tSDL_RecordGesture *SDL_RecordGesture;
+extern tSDL_SaveAllDollarTemplates *SDL_SaveAllDollarTemplates;
+extern tSDL_SaveDollarTemplate *SDL_SaveDollarTemplate;
+extern tSDL_LoadDollarTemplates *SDL_LoadDollarTemplates;
+
+#ifdef __cplusplus
+}
+#endif
+#include "close_code.h"
+
+#endif
+
diff --git a/extern/sdlew/include/SDL2/SDL_haptic.h b/extern/sdlew/include/SDL2/SDL_haptic.h
new file mode 100644
index 00000000000..88fee82e549
--- /dev/null
+++ b/extern/sdlew/include/SDL2/SDL_haptic.h
@@ -0,0 +1,302 @@
+
+#ifndef _SDL_haptic_h
+#define _SDL_haptic_h
+
+#include "SDL_stdinc.h"
+#include "SDL_error.h"
+#include "SDL_joystick.h"
+
+#include "begin_code.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct _SDL_Haptic;
+typedef struct _SDL_Haptic SDL_Haptic;
+
+#define SDL_HAPTIC_CONSTANT (1<<0)
+
+#define SDL_HAPTIC_SINE (1<<1)
+
+#define SDL_HAPTIC_LEFTRIGHT (1<<2)
+
+#define SDL_HAPTIC_TRIANGLE (1<<3)
+
+#define SDL_HAPTIC_SAWTOOTHUP (1<<4)
+
+#define SDL_HAPTIC_SAWTOOTHDOWN (1<<5)
+
+#define SDL_HAPTIC_RAMP (1<<6)
+
+#define SDL_HAPTIC_SPRING (1<<7)
+
+#define SDL_HAPTIC_DAMPER (1<<8)
+
+#define SDL_HAPTIC_INERTIA (1<<9)
+
+#define SDL_HAPTIC_FRICTION (1<<10)
+
+#define SDL_HAPTIC_CUSTOM (1<<11)
+
+#define SDL_HAPTIC_GAIN (1<<12)
+
+#define SDL_HAPTIC_AUTOCENTER (1<<13)
+
+#define SDL_HAPTIC_STATUS (1<<14)
+
+#define SDL_HAPTIC_PAUSE (1<<15)
+
+#define SDL_HAPTIC_POLAR 0
+
+#define SDL_HAPTIC_CARTESIAN 1
+
+#define SDL_HAPTIC_SPHERICAL 2
+
+#define SDL_HAPTIC_INFINITY 4294967295U
+
+typedef struct SDL_HapticDirection
+{
+ Uint8 type;
+ Sint32 dir[3];
+} SDL_HapticDirection;
+
+typedef struct SDL_HapticConstant
+{
+
+ Uint16 type;
+ SDL_HapticDirection direction;
+
+ Uint32 length;
+ Uint16 delay;
+
+ Uint16 button;
+ Uint16 interval;
+
+ Sint16 level;
+
+ Uint16 attack_length;
+ Uint16 attack_level;
+ Uint16 fade_length;
+ Uint16 fade_level;
+} SDL_HapticConstant;
+
+typedef struct SDL_HapticPeriodic
+{
+
+ Uint16 type;
+ SDL_HapticDirection direction;
+
+ Uint32 length;
+ Uint16 delay;
+
+ Uint16 button;
+ Uint16 interval;
+
+ Uint16 period;
+ Sint16 magnitude;
+ Sint16 offset;
+ Uint16 phase;
+
+ Uint16 attack_length;
+ Uint16 attack_level;
+ Uint16 fade_length;
+ Uint16 fade_level;
+} SDL_HapticPeriodic;
+
+typedef struct SDL_HapticCondition
+{
+
+ Uint16 type;
+ SDL_HapticDirection direction;
+
+ Uint32 length;
+ Uint16 delay;
+
+ Uint16 button;
+ Uint16 interval;
+
+ Uint16 right_sat[3];
+ Uint16 left_sat[3];
+ Sint16 right_coeff[3];
+ Sint16 left_coeff[3];
+ Uint16 deadband[3];
+ Sint16 center[3];
+} SDL_HapticCondition;
+
+typedef struct SDL_HapticRamp
+{
+
+ Uint16 type;
+ SDL_HapticDirection direction;
+
+ Uint32 length;
+ Uint16 delay;
+
+ Uint16 button;
+ Uint16 interval;
+
+ Sint16 start;
+ Sint16 end;
+
+ Uint16 attack_length;
+ Uint16 attack_level;
+ Uint16 fade_length;
+ Uint16 fade_level;
+} SDL_HapticRamp;
+
+typedef struct SDL_HapticLeftRight
+{
+
+ Uint16 type;
+
+ Uint32 length;
+
+ Uint16 large_magnitude;
+ Uint16 small_magnitude;
+} SDL_HapticLeftRight;
+
+typedef struct SDL_HapticCustom
+{
+
+ Uint16 type;
+ SDL_HapticDirection direction;
+
+ Uint32 length;
+ Uint16 delay;
+
+ Uint16 button;
+ Uint16 interval;
+
+ Uint8 channels;
+ Uint16 period;
+ Uint16 samples;
+ Uint16 *data;
+
+ Uint16 attack_length;
+ Uint16 attack_level;
+ Uint16 fade_length;
+ Uint16 fade_level;
+} SDL_HapticCustom;
+
+typedef union SDL_HapticEffect
+{
+
+ Uint16 type;
+ SDL_HapticConstant constant;
+ SDL_HapticPeriodic periodic;
+ SDL_HapticCondition condition;
+ SDL_HapticRamp ramp;
+ SDL_HapticLeftRight leftright;
+ SDL_HapticCustom custom;
+} SDL_HapticEffect;
+
+typedef int SDLCALL tSDL_NumHaptics(void);
+
+typedef const char * SDLCALL tSDL_HapticName(int device_index);
+
+typedef SDL_Haptic * SDLCALL tSDL_HapticOpen(int device_index);
+
+typedef int SDLCALL tSDL_HapticOpened(int device_index);
+
+typedef int SDLCALL tSDL_HapticIndex(SDL_Haptic * haptic);
+
+typedef int SDLCALL tSDL_MouseIsHaptic(void);
+
+typedef SDL_Haptic * SDLCALL tSDL_HapticOpenFromMouse(void);
+
+typedef int SDLCALL tSDL_JoystickIsHaptic(SDL_Joystick * joystick);
+
+typedef SDL_Haptic * SDLCALL tSDL_HapticOpenFromJoystick(SDL_Joystick *
+ joystick);
+
+typedef void SDLCALL tSDL_HapticClose(SDL_Haptic * haptic);
+
+typedef int SDLCALL tSDL_HapticNumEffects(SDL_Haptic * haptic);
+
+typedef int SDLCALL tSDL_HapticNumEffectsPlaying(SDL_Haptic * haptic);
+
+extern DECLSPEC unsigned int SDLCALL SDL_HapticQuery(SDL_Haptic * haptic);
+
+typedef int SDLCALL tSDL_HapticNumAxes(SDL_Haptic * haptic);
+
+typedef int SDLCALL tSDL_HapticEffectSupported(SDL_Haptic * haptic,
+ SDL_HapticEffect *
+ effect);
+
+typedef int SDLCALL tSDL_HapticNewEffect(SDL_Haptic * haptic,
+ SDL_HapticEffect * effect);
+
+typedef int SDLCALL tSDL_HapticUpdateEffect(SDL_Haptic * haptic,
+ int effect,
+ SDL_HapticEffect * data);
+
+typedef int SDLCALL tSDL_HapticRunEffect(SDL_Haptic * haptic,
+ int effect,
+ Uint32 iterations);
+
+typedef int SDLCALL tSDL_HapticStopEffect(SDL_Haptic * haptic,
+ int effect);
+
+typedef void SDLCALL tSDL_HapticDestroyEffect(SDL_Haptic * haptic,
+ int effect);
+
+typedef int SDLCALL tSDL_HapticGetEffectStatus(SDL_Haptic * haptic,
+ int effect);
+
+typedef int SDLCALL tSDL_HapticSetGain(SDL_Haptic * haptic, int gain);
+
+typedef int SDLCALL tSDL_HapticSetAutocenter(SDL_Haptic * haptic,
+ int autocenter);
+
+typedef int SDLCALL tSDL_HapticPause(SDL_Haptic * haptic);
+
+typedef int SDLCALL tSDL_HapticUnpause(SDL_Haptic * haptic);
+
+typedef int SDLCALL tSDL_HapticStopAll(SDL_Haptic * haptic);
+
+typedef int SDLCALL tSDL_HapticRumbleSupported(SDL_Haptic * haptic);
+
+typedef int SDLCALL tSDL_HapticRumbleInit(SDL_Haptic * haptic);
+
+typedef int SDLCALL tSDL_HapticRumblePlay(SDL_Haptic * haptic, float strength, Uint32 length );
+
+typedef int SDLCALL tSDL_HapticRumbleStop(SDL_Haptic * haptic);
+
+extern tSDL_NumHaptics *SDL_NumHaptics;
+extern tSDL_HapticName *SDL_HapticName;
+extern tSDL_HapticOpen *SDL_HapticOpen;
+extern tSDL_HapticOpened *SDL_HapticOpened;
+extern tSDL_HapticIndex *SDL_HapticIndex;
+extern tSDL_MouseIsHaptic *SDL_MouseIsHaptic;
+extern tSDL_HapticOpenFromMouse *SDL_HapticOpenFromMouse;
+extern tSDL_JoystickIsHaptic *SDL_JoystickIsHaptic;
+extern tSDL_HapticOpenFromJoystick *SDL_HapticOpenFromJoystick;
+extern tSDL_HapticClose *SDL_HapticClose;
+extern tSDL_HapticNumEffects *SDL_HapticNumEffects;
+extern tSDL_HapticNumEffectsPlaying *SDL_HapticNumEffectsPlaying;
+extern tSDL_HapticNumAxes *SDL_HapticNumAxes;
+extern tSDL_HapticEffectSupported *SDL_HapticEffectSupported;
+extern tSDL_HapticNewEffect *SDL_HapticNewEffect;
+extern tSDL_HapticUpdateEffect *SDL_HapticUpdateEffect;
+extern tSDL_HapticRunEffect *SDL_HapticRunEffect;
+extern tSDL_HapticStopEffect *SDL_HapticStopEffect;
+extern tSDL_HapticDestroyEffect *SDL_HapticDestroyEffect;
+extern tSDL_HapticGetEffectStatus *SDL_HapticGetEffectStatus;
+extern tSDL_HapticSetGain *SDL_HapticSetGain;
+extern tSDL_HapticSetAutocenter *SDL_HapticSetAutocenter;
+extern tSDL_HapticPause *SDL_HapticPause;
+extern tSDL_HapticUnpause *SDL_HapticUnpause;
+extern tSDL_HapticStopAll *SDL_HapticStopAll;
+extern tSDL_HapticRumbleSupported *SDL_HapticRumbleSupported;
+extern tSDL_HapticRumbleInit *SDL_HapticRumbleInit;
+extern tSDL_HapticRumblePlay *SDL_HapticRumblePlay;
+extern tSDL_HapticRumbleStop *SDL_HapticRumbleStop;
+
+#ifdef __cplusplus
+}
+#endif
+#include "close_code.h"
+
+#endif
+
diff --git a/extern/sdlew/include/SDL2/SDL_hints.h b/extern/sdlew/include/SDL2/SDL_hints.h
new file mode 100644
index 00000000000..fbf9307d4d8
--- /dev/null
+++ b/extern/sdlew/include/SDL2/SDL_hints.h
@@ -0,0 +1,87 @@
+
+#ifndef _SDL_hints_h
+#define _SDL_hints_h
+
+#include "SDL_stdinc.h"
+
+#include "begin_code.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define SDL_HINT_FRAMEBUFFER_ACCELERATION "SDL_FRAMEBUFFER_ACCELERATION"
+
+#define SDL_HINT_RENDER_DRIVER "SDL_RENDER_DRIVER"
+
+#define SDL_HINT_RENDER_OPENGL_SHADERS "SDL_RENDER_OPENGL_SHADERS"
+
+#define SDL_HINT_RENDER_SCALE_QUALITY "SDL_RENDER_SCALE_QUALITY"
+
+#define SDL_HINT_RENDER_VSYNC "SDL_RENDER_VSYNC"
+
+#define SDL_HINT_VIDEO_X11_XVIDMODE "SDL_VIDEO_X11_XVIDMODE"
+
+#define SDL_HINT_VIDEO_X11_XINERAMA "SDL_VIDEO_X11_XINERAMA"
+
+#define SDL_HINT_VIDEO_X11_XRANDR "SDL_VIDEO_X11_XRANDR"
+
+#define SDL_HINT_GRAB_KEYBOARD "SDL_GRAB_KEYBOARD"
+
+#define SDL_HINT_VIDEO_MINIMIZE_ON_FOCUS_LOSS "SDL_VIDEO_MINIMIZE_ON_FOCUS_LOSS"
+
+#define SDL_HINT_IDLE_TIMER_DISABLED "SDL_IOS_IDLE_TIMER_DISABLED"
+
+#define SDL_HINT_ORIENTATIONS "SDL_IOS_ORIENTATIONS"
+
+#define SDL_HINT_XINPUT_ENABLED "SDL_XINPUT_ENABLED"
+
+#define SDL_HINT_GAMECONTROLLERCONFIG "SDL_GAMECONTROLLERCONFIG"
+
+#define SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS "SDL_JOYSTICK_ALLOW_BACKGROUND_EVENTS"
+
+#define SDL_HINT_ALLOW_TOPMOST "SDL_ALLOW_TOPMOST"
+
+#define SDL_HINT_TIMER_RESOLUTION "SDL_TIMER_RESOLUTION"
+
+typedef enum
+{
+ SDL_HINT_DEFAULT,
+ SDL_HINT_NORMAL,
+ SDL_HINT_OVERRIDE
+} SDL_HintPriority;
+
+typedef SDL_bool SDLCALL tSDL_SetHintWithPriority(const char *name,
+ const char *value,
+ SDL_HintPriority priority);
+
+typedef SDL_bool SDLCALL tSDL_SetHint(const char *name,
+ const char *value);
+
+typedef const char * SDLCALL tSDL_GetHint(const char *name);
+
+typedef void (*SDL_HintCallback)(void *userdata, const char *name, const char *oldValue, const char *newValue);
+typedef void SDLCALL tSDL_AddHintCallback(const char *name,
+ SDL_HintCallback callback,
+ void *userdata);
+
+typedef void SDLCALL tSDL_DelHintCallback(const char *name,
+ SDL_HintCallback callback,
+ void *userdata);
+
+typedef void SDLCALL tSDL_ClearHints(void);
+
+extern tSDL_SetHintWithPriority *SDL_SetHintWithPriority;
+extern tSDL_SetHint *SDL_SetHint;
+extern tSDL_GetHint *SDL_GetHint;
+extern tSDL_AddHintCallback *SDL_AddHintCallback;
+extern tSDL_DelHintCallback *SDL_DelHintCallback;
+extern tSDL_ClearHints *SDL_ClearHints;
+
+#ifdef __cplusplus
+}
+#endif
+#include "close_code.h"
+
+#endif
+
diff --git a/extern/sdlew/include/SDL2/SDL_joystick.h b/extern/sdlew/include/SDL2/SDL_joystick.h
new file mode 100644
index 00000000000..16e4d5ec312
--- /dev/null
+++ b/extern/sdlew/include/SDL2/SDL_joystick.h
@@ -0,0 +1,106 @@
+
+#ifndef _SDL_joystick_h
+#define _SDL_joystick_h
+
+#include "SDL_stdinc.h"
+#include "SDL_error.h"
+
+#include "begin_code.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct _SDL_Joystick;
+typedef struct _SDL_Joystick SDL_Joystick;
+
+typedef struct {
+ Uint8 data[16];
+} SDL_JoystickGUID;
+
+typedef Sint32 SDL_JoystickID;
+
+typedef int SDLCALL tSDL_NumJoysticks(void);
+
+typedef const char * SDLCALL tSDL_JoystickNameForIndex(int device_index);
+
+typedef SDL_Joystick * SDLCALL tSDL_JoystickOpen(int device_index);
+
+typedef const char * SDLCALL tSDL_JoystickName(SDL_Joystick * joystick);
+
+typedef SDL_JoystickGUID SDLCALL tSDL_JoystickGetDeviceGUID(int device_index);
+
+typedef SDL_JoystickGUID SDLCALL tSDL_JoystickGetGUID(SDL_Joystick * joystick);
+
+extern DECLSPEC void SDL_JoystickGetGUIDString(SDL_JoystickGUID guid, char *pszGUID, int cbGUID);
+
+typedef SDL_JoystickGUID SDLCALL tSDL_JoystickGetGUIDFromString(const char *pchGUID);
+
+typedef SDL_bool SDLCALL tSDL_JoystickGetAttached(SDL_Joystick * joystick);
+
+typedef SDL_JoystickID SDLCALL tSDL_JoystickInstanceID(SDL_Joystick * joystick);
+
+typedef int SDLCALL tSDL_JoystickNumAxes(SDL_Joystick * joystick);
+
+typedef int SDLCALL tSDL_JoystickNumBalls(SDL_Joystick * joystick);
+
+typedef int SDLCALL tSDL_JoystickNumHats(SDL_Joystick * joystick);
+
+typedef int SDLCALL tSDL_JoystickNumButtons(SDL_Joystick * joystick);
+
+typedef void SDLCALL tSDL_JoystickUpdate(void);
+
+typedef int SDLCALL tSDL_JoystickEventState(int state);
+
+typedef Sint16 SDLCALL tSDL_JoystickGetAxis(SDL_Joystick * joystick,
+ int axis);
+
+#define SDL_HAT_CENTERED 0x00
+#define SDL_HAT_UP 0x01
+#define SDL_HAT_RIGHT 0x02
+#define SDL_HAT_DOWN 0x04
+#define SDL_HAT_LEFT 0x08
+#define SDL_HAT_RIGHTUP (SDL_HAT_RIGHT|SDL_HAT_UP)
+#define SDL_HAT_RIGHTDOWN (SDL_HAT_RIGHT|SDL_HAT_DOWN)
+#define SDL_HAT_LEFTUP (SDL_HAT_LEFT|SDL_HAT_UP)
+#define SDL_HAT_LEFTDOWN (SDL_HAT_LEFT|SDL_HAT_DOWN)
+
+typedef Uint8 SDLCALL tSDL_JoystickGetHat(SDL_Joystick * joystick,
+ int hat);
+
+typedef int SDLCALL tSDL_JoystickGetBall(SDL_Joystick * joystick,
+ int ball, int *dx, int *dy);
+
+typedef Uint8 SDLCALL tSDL_JoystickGetButton(SDL_Joystick * joystick,
+ int button);
+
+typedef void SDLCALL tSDL_JoystickClose(SDL_Joystick * joystick);
+
+extern tSDL_NumJoysticks *SDL_NumJoysticks;
+extern tSDL_JoystickNameForIndex *SDL_JoystickNameForIndex;
+extern tSDL_JoystickOpen *SDL_JoystickOpen;
+extern tSDL_JoystickName *SDL_JoystickName;
+extern tSDL_JoystickGetDeviceGUID *SDL_JoystickGetDeviceGUID;
+extern tSDL_JoystickGetGUID *SDL_JoystickGetGUID;
+extern tSDL_JoystickGetGUIDFromString *SDL_JoystickGetGUIDFromString;
+extern tSDL_JoystickGetAttached *SDL_JoystickGetAttached;
+extern tSDL_JoystickInstanceID *SDL_JoystickInstanceID;
+extern tSDL_JoystickNumAxes *SDL_JoystickNumAxes;
+extern tSDL_JoystickNumBalls *SDL_JoystickNumBalls;
+extern tSDL_JoystickNumHats *SDL_JoystickNumHats;
+extern tSDL_JoystickNumButtons *SDL_JoystickNumButtons;
+extern tSDL_JoystickUpdate *SDL_JoystickUpdate;
+extern tSDL_JoystickEventState *SDL_JoystickEventState;
+extern tSDL_JoystickGetAxis *SDL_JoystickGetAxis;
+extern tSDL_JoystickGetHat *SDL_JoystickGetHat;
+extern tSDL_JoystickGetBall *SDL_JoystickGetBall;
+extern tSDL_JoystickGetButton *SDL_JoystickGetButton;
+extern tSDL_JoystickClose *SDL_JoystickClose;
+
+#ifdef __cplusplus
+}
+#endif
+#include "close_code.h"
+
+#endif
+
diff --git a/extern/sdlew/include/SDL2/SDL_keyboard.h b/extern/sdlew/include/SDL2/SDL_keyboard.h
new file mode 100644
index 00000000000..c2517b4f665
--- /dev/null
+++ b/extern/sdlew/include/SDL2/SDL_keyboard.h
@@ -0,0 +1,79 @@
+
+#ifndef _SDL_keyboard_h
+#define _SDL_keyboard_h
+
+#include "SDL_stdinc.h"
+#include "SDL_error.h"
+#include "SDL_keycode.h"
+#include "SDL_video.h"
+
+#include "begin_code.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct SDL_Keysym
+{
+ SDL_Scancode scancode;
+ SDL_Keycode sym;
+ Uint16 mod;
+ Uint32 unused;
+} SDL_Keysym;
+
+typedef SDL_Window * SDLCALL tSDL_GetKeyboardFocus(void);
+
+typedef const Uint8 * SDLCALL tSDL_GetKeyboardState(int *numkeys);
+
+typedef SDL_Keymod SDLCALL tSDL_GetModState(void);
+
+typedef void SDLCALL tSDL_SetModState(SDL_Keymod modstate);
+
+typedef SDL_Keycode SDLCALL tSDL_GetKeyFromScancode(SDL_Scancode scancode);
+
+typedef SDL_Scancode SDLCALL tSDL_GetScancodeFromKey(SDL_Keycode key);
+
+typedef const char * SDLCALL tSDL_GetScancodeName(SDL_Scancode scancode);
+
+typedef SDL_Scancode SDLCALL tSDL_GetScancodeFromName(const char *name);
+
+typedef const char * SDLCALL tSDL_GetKeyName(SDL_Keycode key);
+
+typedef SDL_Keycode SDLCALL tSDL_GetKeyFromName(const char *name);
+
+typedef void SDLCALL tSDL_StartTextInput(void);
+
+typedef SDL_bool SDLCALL tSDL_IsTextInputActive(void);
+
+typedef void SDLCALL tSDL_StopTextInput(void);
+
+typedef void SDLCALL tSDL_SetTextInputRect(SDL_Rect *rect);
+
+typedef SDL_bool SDLCALL tSDL_HasScreenKeyboardSupport(void);
+
+typedef SDL_bool SDLCALL tSDL_IsScreenKeyboardShown(SDL_Window *window);
+
+extern tSDL_GetKeyboardFocus *SDL_GetKeyboardFocus;
+extern tSDL_GetKeyboardState *SDL_GetKeyboardState;
+extern tSDL_GetModState *SDL_GetModState;
+extern tSDL_SetModState *SDL_SetModState;
+extern tSDL_GetKeyFromScancode *SDL_GetKeyFromScancode;
+extern tSDL_GetScancodeFromKey *SDL_GetScancodeFromKey;
+extern tSDL_GetScancodeName *SDL_GetScancodeName;
+extern tSDL_GetScancodeFromName *SDL_GetScancodeFromName;
+extern tSDL_GetKeyName *SDL_GetKeyName;
+extern tSDL_GetKeyFromName *SDL_GetKeyFromName;
+extern tSDL_StartTextInput *SDL_StartTextInput;
+extern tSDL_IsTextInputActive *SDL_IsTextInputActive;
+extern tSDL_StopTextInput *SDL_StopTextInput;
+extern tSDL_SetTextInputRect *SDL_SetTextInputRect;
+extern tSDL_HasScreenKeyboardSupport *SDL_HasScreenKeyboardSupport;
+extern tSDL_IsScreenKeyboardShown *SDL_IsScreenKeyboardShown;
+
+#ifdef __cplusplus
+}
+#endif
+#include "close_code.h"
+
+#endif
+
diff --git a/extern/sdlew/include/SDL2/SDL_keycode.h b/extern/sdlew/include/SDL2/SDL_keycode.h
new file mode 100644
index 00000000000..28bc1bafb41
--- /dev/null
+++ b/extern/sdlew/include/SDL2/SDL_keycode.h
@@ -0,0 +1,301 @@
+
+#ifndef _SDL_keycode_h
+#define _SDL_keycode_h
+
+#include "SDL_stdinc.h"
+#include "SDL_scancode.h"
+
+typedef Sint32 SDL_Keycode;
+
+#define SDLK_SCANCODE_MASK (1<<30)
+#define SDL_SCANCODE_TO_KEYCODE(X) (X | SDLK_SCANCODE_MASK)
+
+enum
+{
+ SDLK_UNKNOWN = 0,
+
+ SDLK_RETURN = '\r',
+ SDLK_ESCAPE = '\033',
+ SDLK_BACKSPACE = '\b',
+ SDLK_TAB = '\t',
+ SDLK_SPACE = ' ',
+ SDLK_EXCLAIM = '!',
+ SDLK_QUOTEDBL = '"',
+ SDLK_HASH = '#',
+ SDLK_PERCENT = '%',
+ SDLK_DOLLAR = '$',
+ SDLK_AMPERSAND = '&',
+ SDLK_QUOTE = '\'',
+ SDLK_LEFTPAREN = '(',
+ SDLK_RIGHTPAREN = ')',
+ SDLK_ASTERISK = '*',
+ SDLK_PLUS = '+',
+ SDLK_COMMA = ',',
+ SDLK_MINUS = '-',
+ SDLK_PERIOD = '.',
+ SDLK_SLASH = '/',
+ SDLK_0 = '0',
+ SDLK_1 = '1',
+ SDLK_2 = '2',
+ SDLK_3 = '3',
+ SDLK_4 = '4',
+ SDLK_5 = '5',
+ SDLK_6 = '6',
+ SDLK_7 = '7',
+ SDLK_8 = '8',
+ SDLK_9 = '9',
+ SDLK_COLON = ':',
+ SDLK_SEMICOLON = ';',
+ SDLK_LESS = '<',
+ SDLK_EQUALS = '=',
+ SDLK_GREATER = '>',
+ SDLK_QUESTION = '?',
+ SDLK_AT = '@',
+
+ SDLK_LEFTBRACKET = '[',
+ SDLK_BACKSLASH = '\\',
+ SDLK_RIGHTBRACKET = ']',
+ SDLK_CARET = '^',
+ SDLK_UNDERSCORE = '_',
+ SDLK_BACKQUOTE = '`',
+ SDLK_a = 'a',
+ SDLK_b = 'b',
+ SDLK_c = 'c',
+ SDLK_d = 'd',
+ SDLK_e = 'e',
+ SDLK_f = 'f',
+ SDLK_g = 'g',
+ SDLK_h = 'h',
+ SDLK_i = 'i',
+ SDLK_j = 'j',
+ SDLK_k = 'k',
+ SDLK_l = 'l',
+ SDLK_m = 'm',
+ SDLK_n = 'n',
+ SDLK_o = 'o',
+ SDLK_p = 'p',
+ SDLK_q = 'q',
+ SDLK_r = 'r',
+ SDLK_s = 's',
+ SDLK_t = 't',
+ SDLK_u = 'u',
+ SDLK_v = 'v',
+ SDLK_w = 'w',
+ SDLK_x = 'x',
+ SDLK_y = 'y',
+ SDLK_z = 'z',
+
+ SDLK_CAPSLOCK = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_CAPSLOCK),
+
+ SDLK_F1 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F1),
+ SDLK_F2 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F2),
+ SDLK_F3 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F3),
+ SDLK_F4 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F4),
+ SDLK_F5 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F5),
+ SDLK_F6 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F6),
+ SDLK_F7 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F7),
+ SDLK_F8 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F8),
+ SDLK_F9 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F9),
+ SDLK_F10 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F10),
+ SDLK_F11 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F11),
+ SDLK_F12 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F12),
+
+ SDLK_PRINTSCREEN = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_PRINTSCREEN),
+ SDLK_SCROLLLOCK = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_SCROLLLOCK),
+ SDLK_PAUSE = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_PAUSE),
+ SDLK_INSERT = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_INSERT),
+ SDLK_HOME = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_HOME),
+ SDLK_PAGEUP = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_PAGEUP),
+ SDLK_DELETE = '\177',
+ SDLK_END = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_END),
+ SDLK_PAGEDOWN = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_PAGEDOWN),
+ SDLK_RIGHT = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_RIGHT),
+ SDLK_LEFT = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_LEFT),
+ SDLK_DOWN = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_DOWN),
+ SDLK_UP = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_UP),
+
+ SDLK_NUMLOCKCLEAR = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_NUMLOCKCLEAR),
+ SDLK_KP_DIVIDE = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_DIVIDE),
+ SDLK_KP_MULTIPLY = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_MULTIPLY),
+ SDLK_KP_MINUS = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_MINUS),
+ SDLK_KP_PLUS = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_PLUS),
+ SDLK_KP_ENTER = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_ENTER),
+ SDLK_KP_1 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_1),
+ SDLK_KP_2 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_2),
+ SDLK_KP_3 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_3),
+ SDLK_KP_4 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_4),
+ SDLK_KP_5 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_5),
+ SDLK_KP_6 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_6),
+ SDLK_KP_7 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_7),
+ SDLK_KP_8 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_8),
+ SDLK_KP_9 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_9),
+ SDLK_KP_0 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_0),
+ SDLK_KP_PERIOD = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_PERIOD),
+
+ SDLK_APPLICATION = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_APPLICATION),
+ SDLK_POWER = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_POWER),
+ SDLK_KP_EQUALS = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_EQUALS),
+ SDLK_F13 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F13),
+ SDLK_F14 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F14),
+ SDLK_F15 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F15),
+ SDLK_F16 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F16),
+ SDLK_F17 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F17),
+ SDLK_F18 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F18),
+ SDLK_F19 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F19),
+ SDLK_F20 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F20),
+ SDLK_F21 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F21),
+ SDLK_F22 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F22),
+ SDLK_F23 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F23),
+ SDLK_F24 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F24),
+ SDLK_EXECUTE = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_EXECUTE),
+ SDLK_HELP = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_HELP),
+ SDLK_MENU = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_MENU),
+ SDLK_SELECT = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_SELECT),
+ SDLK_STOP = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_STOP),
+ SDLK_AGAIN = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_AGAIN),
+ SDLK_UNDO = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_UNDO),
+ SDLK_CUT = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_CUT),
+ SDLK_COPY = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_COPY),
+ SDLK_PASTE = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_PASTE),
+ SDLK_FIND = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_FIND),
+ SDLK_MUTE = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_MUTE),
+ SDLK_VOLUMEUP = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_VOLUMEUP),
+ SDLK_VOLUMEDOWN = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_VOLUMEDOWN),
+ SDLK_KP_COMMA = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_COMMA),
+ SDLK_KP_EQUALSAS400 =
+ SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_EQUALSAS400),
+
+ SDLK_ALTERASE = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_ALTERASE),
+ SDLK_SYSREQ = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_SYSREQ),
+ SDLK_CANCEL = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_CANCEL),
+ SDLK_CLEAR = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_CLEAR),
+ SDLK_PRIOR = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_PRIOR),
+ SDLK_RETURN2 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_RETURN2),
+ SDLK_SEPARATOR = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_SEPARATOR),
+ SDLK_OUT = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_OUT),
+ SDLK_OPER = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_OPER),
+ SDLK_CLEARAGAIN = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_CLEARAGAIN),
+ SDLK_CRSEL = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_CRSEL),
+ SDLK_EXSEL = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_EXSEL),
+
+ SDLK_KP_00 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_00),
+ SDLK_KP_000 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_000),
+ SDLK_THOUSANDSSEPARATOR =
+ SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_THOUSANDSSEPARATOR),
+ SDLK_DECIMALSEPARATOR =
+ SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_DECIMALSEPARATOR),
+ SDLK_CURRENCYUNIT = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_CURRENCYUNIT),
+ SDLK_CURRENCYSUBUNIT =
+ SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_CURRENCYSUBUNIT),
+ SDLK_KP_LEFTPAREN = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_LEFTPAREN),
+ SDLK_KP_RIGHTPAREN = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_RIGHTPAREN),
+ SDLK_KP_LEFTBRACE = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_LEFTBRACE),
+ SDLK_KP_RIGHTBRACE = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_RIGHTBRACE),
+ SDLK_KP_TAB = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_TAB),
+ SDLK_KP_BACKSPACE = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_BACKSPACE),
+ SDLK_KP_A = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_A),
+ SDLK_KP_B = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_B),
+ SDLK_KP_C = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_C),
+ SDLK_KP_D = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_D),
+ SDLK_KP_E = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_E),
+ SDLK_KP_F = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_F),
+ SDLK_KP_XOR = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_XOR),
+ SDLK_KP_POWER = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_POWER),
+ SDLK_KP_PERCENT = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_PERCENT),
+ SDLK_KP_LESS = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_LESS),
+ SDLK_KP_GREATER = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_GREATER),
+ SDLK_KP_AMPERSAND = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_AMPERSAND),
+ SDLK_KP_DBLAMPERSAND =
+ SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_DBLAMPERSAND),
+ SDLK_KP_VERTICALBAR =
+ SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_VERTICALBAR),
+ SDLK_KP_DBLVERTICALBAR =
+ SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_DBLVERTICALBAR),
+ SDLK_KP_COLON = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_COLON),
+ SDLK_KP_HASH = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_HASH),
+ SDLK_KP_SPACE = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_SPACE),
+ SDLK_KP_AT = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_AT),
+ SDLK_KP_EXCLAM = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_EXCLAM),
+ SDLK_KP_MEMSTORE = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_MEMSTORE),
+ SDLK_KP_MEMRECALL = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_MEMRECALL),
+ SDLK_KP_MEMCLEAR = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_MEMCLEAR),
+ SDLK_KP_MEMADD = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_MEMADD),
+ SDLK_KP_MEMSUBTRACT =
+ SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_MEMSUBTRACT),
+ SDLK_KP_MEMMULTIPLY =
+ SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_MEMMULTIPLY),
+ SDLK_KP_MEMDIVIDE = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_MEMDIVIDE),
+ SDLK_KP_PLUSMINUS = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_PLUSMINUS),
+ SDLK_KP_CLEAR = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_CLEAR),
+ SDLK_KP_CLEARENTRY = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_CLEARENTRY),
+ SDLK_KP_BINARY = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_BINARY),
+ SDLK_KP_OCTAL = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_OCTAL),
+ SDLK_KP_DECIMAL = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_DECIMAL),
+ SDLK_KP_HEXADECIMAL =
+ SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_HEXADECIMAL),
+
+ SDLK_LCTRL = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_LCTRL),
+ SDLK_LSHIFT = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_LSHIFT),
+ SDLK_LALT = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_LALT),
+ SDLK_LGUI = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_LGUI),
+ SDLK_RCTRL = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_RCTRL),
+ SDLK_RSHIFT = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_RSHIFT),
+ SDLK_RALT = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_RALT),
+ SDLK_RGUI = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_RGUI),
+
+ SDLK_MODE = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_MODE),
+
+ SDLK_AUDIONEXT = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_AUDIONEXT),
+ SDLK_AUDIOPREV = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_AUDIOPREV),
+ SDLK_AUDIOSTOP = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_AUDIOSTOP),
+ SDLK_AUDIOPLAY = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_AUDIOPLAY),
+ SDLK_AUDIOMUTE = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_AUDIOMUTE),
+ SDLK_MEDIASELECT = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_MEDIASELECT),
+ SDLK_WWW = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_WWW),
+ SDLK_MAIL = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_MAIL),
+ SDLK_CALCULATOR = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_CALCULATOR),
+ SDLK_COMPUTER = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_COMPUTER),
+ SDLK_AC_SEARCH = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_AC_SEARCH),
+ SDLK_AC_HOME = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_AC_HOME),
+ SDLK_AC_BACK = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_AC_BACK),
+ SDLK_AC_FORWARD = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_AC_FORWARD),
+ SDLK_AC_STOP = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_AC_STOP),
+ SDLK_AC_REFRESH = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_AC_REFRESH),
+ SDLK_AC_BOOKMARKS = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_AC_BOOKMARKS),
+
+ SDLK_BRIGHTNESSDOWN =
+ SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_BRIGHTNESSDOWN),
+ SDLK_BRIGHTNESSUP = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_BRIGHTNESSUP),
+ SDLK_DISPLAYSWITCH = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_DISPLAYSWITCH),
+ SDLK_KBDILLUMTOGGLE =
+ SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KBDILLUMTOGGLE),
+ SDLK_KBDILLUMDOWN = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KBDILLUMDOWN),
+ SDLK_KBDILLUMUP = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KBDILLUMUP),
+ SDLK_EJECT = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_EJECT),
+ SDLK_SLEEP = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_SLEEP)
+};
+
+typedef enum
+{
+ KMOD_NONE = 0x0000,
+ KMOD_LSHIFT = 0x0001,
+ KMOD_RSHIFT = 0x0002,
+ KMOD_LCTRL = 0x0040,
+ KMOD_RCTRL = 0x0080,
+ KMOD_LALT = 0x0100,
+ KMOD_RALT = 0x0200,
+ KMOD_LGUI = 0x0400,
+ KMOD_RGUI = 0x0800,
+ KMOD_NUM = 0x1000,
+ KMOD_CAPS = 0x2000,
+ KMOD_MODE = 0x4000,
+ KMOD_RESERVED = 0x8000
+} SDL_Keymod;
+
+#define KMOD_CTRL (KMOD_LCTRL|KMOD_RCTRL)
+#define KMOD_SHIFT (KMOD_LSHIFT|KMOD_RSHIFT)
+#define KMOD_ALT (KMOD_LALT|KMOD_RALT)
+#define KMOD_GUI (KMOD_LGUI|KMOD_RGUI)
+
+#endif
+
diff --git a/extern/sdlew/include/SDL2/SDL_loadso.h b/extern/sdlew/include/SDL2/SDL_loadso.h
new file mode 100644
index 00000000000..942f096a360
--- /dev/null
+++ b/extern/sdlew/include/SDL2/SDL_loadso.h
@@ -0,0 +1,31 @@
+
+#ifndef _SDL_loadso_h
+#define _SDL_loadso_h
+
+#include "SDL_stdinc.h"
+#include "SDL_error.h"
+
+#include "begin_code.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef void * SDLCALL tSDL_LoadObject(const char *sofile);
+
+typedef void * SDLCALL tSDL_LoadFunction(void *handle,
+ const char *name);
+
+typedef void SDLCALL tSDL_UnloadObject(void *handle);
+
+extern tSDL_LoadObject *SDL_LoadObject;
+extern tSDL_LoadFunction *SDL_LoadFunction;
+extern tSDL_UnloadObject *SDL_UnloadObject;
+
+#ifdef __cplusplus
+}
+#endif
+#include "close_code.h"
+
+#endif
+
diff --git a/extern/sdlew/include/SDL2/SDL_log.h b/extern/sdlew/include/SDL2/SDL_log.h
new file mode 100644
index 00000000000..3add97a00f3
--- /dev/null
+++ b/extern/sdlew/include/SDL2/SDL_log.h
@@ -0,0 +1,111 @@
+
+#ifndef _SDL_log_h
+#define _SDL_log_h
+
+#include "SDL_stdinc.h"
+
+#include "begin_code.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define SDL_MAX_LOG_MESSAGE 4096
+
+enum
+{
+ SDL_LOG_CATEGORY_APPLICATION,
+ SDL_LOG_CATEGORY_ERROR,
+ SDL_LOG_CATEGORY_ASSERT,
+ SDL_LOG_CATEGORY_SYSTEM,
+ SDL_LOG_CATEGORY_AUDIO,
+ SDL_LOG_CATEGORY_VIDEO,
+ SDL_LOG_CATEGORY_RENDER,
+ SDL_LOG_CATEGORY_INPUT,
+ SDL_LOG_CATEGORY_TEST,
+
+ SDL_LOG_CATEGORY_RESERVED1,
+ SDL_LOG_CATEGORY_RESERVED2,
+ SDL_LOG_CATEGORY_RESERVED3,
+ SDL_LOG_CATEGORY_RESERVED4,
+ SDL_LOG_CATEGORY_RESERVED5,
+ SDL_LOG_CATEGORY_RESERVED6,
+ SDL_LOG_CATEGORY_RESERVED7,
+ SDL_LOG_CATEGORY_RESERVED8,
+ SDL_LOG_CATEGORY_RESERVED9,
+ SDL_LOG_CATEGORY_RESERVED10,
+
+ SDL_LOG_CATEGORY_CUSTOM
+};
+
+typedef enum
+{
+ SDL_LOG_PRIORITY_VERBOSE = 1,
+ SDL_LOG_PRIORITY_DEBUG,
+ SDL_LOG_PRIORITY_INFO,
+ SDL_LOG_PRIORITY_WARN,
+ SDL_LOG_PRIORITY_ERROR,
+ SDL_LOG_PRIORITY_CRITICAL,
+ SDL_NUM_LOG_PRIORITIES
+} SDL_LogPriority;
+
+typedef void SDLCALL tSDL_LogSetAllPriority(SDL_LogPriority priority);
+
+typedef void SDLCALL tSDL_LogSetPriority(int category,
+ SDL_LogPriority priority);
+
+typedef SDL_LogPriority SDLCALL tSDL_LogGetPriority(int category);
+
+typedef void SDLCALL tSDL_LogResetPriorities(void);
+
+typedef void SDLCALL tSDL_Log(const char *fmt, ...);
+
+typedef void SDLCALL tSDL_LogVerbose(int category, const char *fmt, ...);
+
+typedef void SDLCALL tSDL_LogDebug(int category, const char *fmt, ...);
+
+typedef void SDLCALL tSDL_LogInfo(int category, const char *fmt, ...);
+
+typedef void SDLCALL tSDL_LogWarn(int category, const char *fmt, ...);
+
+typedef void SDLCALL tSDL_LogError(int category, const char *fmt, ...);
+
+typedef void SDLCALL tSDL_LogCritical(int category, const char *fmt, ...);
+
+typedef void SDLCALL tSDL_LogMessage(int category,
+ SDL_LogPriority priority,
+ const char *fmt, ...);
+
+typedef void SDLCALL tSDL_LogMessageV(int category,
+ SDL_LogPriority priority,
+ const char *fmt, va_list ap);
+
+typedef void (*SDL_LogOutputFunction)(void *userdata, int category, SDL_LogPriority priority, const char *message);
+
+typedef void SDLCALL tSDL_LogGetOutputFunction(SDL_LogOutputFunction *callback, void **userdata);
+
+typedef void SDLCALL tSDL_LogSetOutputFunction(SDL_LogOutputFunction callback, void *userdata);
+
+extern tSDL_LogSetAllPriority *SDL_LogSetAllPriority;
+extern tSDL_LogSetPriority *SDL_LogSetPriority;
+extern tSDL_LogGetPriority *SDL_LogGetPriority;
+extern tSDL_LogResetPriorities *SDL_LogResetPriorities;
+extern tSDL_Log *SDL_Log;
+extern tSDL_LogVerbose *SDL_LogVerbose;
+extern tSDL_LogDebug *SDL_LogDebug;
+extern tSDL_LogInfo *SDL_LogInfo;
+extern tSDL_LogWarn *SDL_LogWarn;
+extern tSDL_LogError *SDL_LogError;
+extern tSDL_LogCritical *SDL_LogCritical;
+extern tSDL_LogMessage *SDL_LogMessage;
+extern tSDL_LogMessageV *SDL_LogMessageV;
+extern tSDL_LogGetOutputFunction *SDL_LogGetOutputFunction;
+extern tSDL_LogSetOutputFunction *SDL_LogSetOutputFunction;
+
+#ifdef __cplusplus
+}
+#endif
+#include "close_code.h"
+
+#endif
+
diff --git a/extern/sdlew/include/SDL2/SDL_main.h b/extern/sdlew/include/SDL2/SDL_main.h
new file mode 100644
index 00000000000..9f7386af065
--- /dev/null
+++ b/extern/sdlew/include/SDL2/SDL_main.h
@@ -0,0 +1,56 @@
+
+#ifndef _SDL_main_h
+#define _SDL_main_h
+
+#include "SDL_stdinc.h"
+
+#ifndef SDL_MAIN_HANDLED
+#if defined(__WIN32__)
+
+#define SDL_MAIN_AVAILABLE
+
+#elif defined(__IPHONEOS__)
+
+#define SDL_MAIN_NEEDED
+
+#elif defined(__ANDROID__)
+
+#define SDL_MAIN_NEEDED
+
+#endif
+#endif
+
+#ifdef __cplusplus
+#define C_LINKAGE "C"
+#else
+#define C_LINKAGE
+#endif
+
+#if defined(SDL_MAIN_NEEDED) || defined(SDL_MAIN_AVAILABLE)
+#define main SDL_main
+#endif
+
+extern C_LINKAGE int SDL_main(int argc, char *argv[]);
+
+#include "begin_code.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern DECLSPEC void SDL_SetMainReady(void);
+
+#ifdef __WIN32__
+
+typedef int SDLCALL tSDL_RegisterApp(char *name, Uint32 style,
+ void *hInst);
+typedef void SDLCALL tSDL_UnregisterApp(void);
+
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+#include "close_code.h"
+
+#endif
+
diff --git a/extern/sdlew/include/SDL2/SDL_messagebox.h b/extern/sdlew/include/SDL2/SDL_messagebox.h
new file mode 100644
index 00000000000..378d5d94868
--- /dev/null
+++ b/extern/sdlew/include/SDL2/SDL_messagebox.h
@@ -0,0 +1,80 @@
+
+#ifndef _SDL_messagebox_h
+#define _SDL_messagebox_h
+
+#include "SDL_stdinc.h"
+#include "SDL_video.h"
+
+#include "begin_code.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef enum
+{
+ SDL_MESSAGEBOX_ERROR = 0x00000010,
+ SDL_MESSAGEBOX_WARNING = 0x00000020,
+ SDL_MESSAGEBOX_INFORMATION = 0x00000040
+} SDL_MessageBoxFlags;
+
+typedef enum
+{
+ SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT = 0x00000001,
+ SDL_MESSAGEBOX_BUTTON_ESCAPEKEY_DEFAULT = 0x00000002
+} SDL_MessageBoxButtonFlags;
+
+typedef struct
+{
+ Uint32 flags;
+ int buttonid;
+ const char * text;
+} SDL_MessageBoxButtonData;
+
+typedef struct
+{
+ Uint8 r, g, b;
+} SDL_MessageBoxColor;
+
+typedef enum
+{
+ SDL_MESSAGEBOX_COLOR_BACKGROUND,
+ SDL_MESSAGEBOX_COLOR_TEXT,
+ SDL_MESSAGEBOX_COLOR_BUTTON_BORDER,
+ SDL_MESSAGEBOX_COLOR_BUTTON_BACKGROUND,
+ SDL_MESSAGEBOX_COLOR_BUTTON_SELECTED,
+ SDL_MESSAGEBOX_COLOR_MAX
+} SDL_MessageBoxColorType;
+
+typedef struct
+{
+ SDL_MessageBoxColor colors[SDL_MESSAGEBOX_COLOR_MAX];
+} SDL_MessageBoxColorScheme;
+
+typedef struct
+{
+ Uint32 flags;
+ SDL_Window *window;
+ const char *title;
+ const char *message;
+
+ int numbuttons;
+ const SDL_MessageBoxButtonData *buttons;
+
+ const SDL_MessageBoxColorScheme *colorScheme;
+} SDL_MessageBoxData;
+
+typedef int SDLCALL tSDL_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonid);
+
+typedef int SDLCALL tSDL_ShowSimpleMessageBox(Uint32 flags, const char *title, const char *message, SDL_Window *window);
+
+extern tSDL_ShowMessageBox *SDL_ShowMessageBox;
+extern tSDL_ShowSimpleMessageBox *SDL_ShowSimpleMessageBox;
+
+#ifdef __cplusplus
+}
+#endif
+#include "close_code.h"
+
+#endif
+
diff --git a/extern/sdlew/include/SDL2/SDL_mouse.h b/extern/sdlew/include/SDL2/SDL_mouse.h
new file mode 100644
index 00000000000..e6700a405ee
--- /dev/null
+++ b/extern/sdlew/include/SDL2/SDL_mouse.h
@@ -0,0 +1,101 @@
+
+#ifndef _SDL_mouse_h
+#define _SDL_mouse_h
+
+#include "SDL_stdinc.h"
+#include "SDL_error.h"
+#include "SDL_video.h"
+
+#include "begin_code.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct SDL_Cursor SDL_Cursor;
+
+typedef enum
+{
+ SDL_SYSTEM_CURSOR_ARROW,
+ SDL_SYSTEM_CURSOR_IBEAM,
+ SDL_SYSTEM_CURSOR_WAIT,
+ SDL_SYSTEM_CURSOR_CROSSHAIR,
+ SDL_SYSTEM_CURSOR_WAITARROW,
+ SDL_SYSTEM_CURSOR_SIZENWSE,
+ SDL_SYSTEM_CURSOR_SIZENESW,
+ SDL_SYSTEM_CURSOR_SIZEWE,
+ SDL_SYSTEM_CURSOR_SIZENS,
+ SDL_SYSTEM_CURSOR_SIZEALL,
+ SDL_SYSTEM_CURSOR_NO,
+ SDL_SYSTEM_CURSOR_HAND,
+ SDL_NUM_SYSTEM_CURSORS
+} SDL_SystemCursor;
+
+typedef SDL_Window * SDLCALL tSDL_GetMouseFocus(void);
+
+typedef Uint32 SDLCALL tSDL_GetMouseState(int *x, int *y);
+
+typedef Uint32 SDLCALL tSDL_GetRelativeMouseState(int *x, int *y);
+
+typedef void SDLCALL tSDL_WarpMouseInWindow(SDL_Window * window,
+ int x, int y);
+
+typedef int SDLCALL tSDL_SetRelativeMouseMode(SDL_bool enabled);
+
+typedef SDL_bool SDLCALL tSDL_GetRelativeMouseMode(void);
+
+typedef SDL_Cursor * SDLCALL tSDL_CreateCursor(const Uint8 * data,
+ const Uint8 * mask,
+ int w, int h, int hot_x,
+ int hot_y);
+
+typedef SDL_Cursor * SDLCALL tSDL_CreateColorCursor(SDL_Surface *surface,
+ int hot_x,
+ int hot_y);
+
+typedef SDL_Cursor * SDLCALL tSDL_CreateSystemCursor(SDL_SystemCursor id);
+
+typedef void SDLCALL tSDL_SetCursor(SDL_Cursor * cursor);
+
+typedef SDL_Cursor * SDLCALL tSDL_GetCursor(void);
+
+typedef SDL_Cursor * SDLCALL tSDL_GetDefaultCursor(void);
+
+typedef void SDLCALL tSDL_FreeCursor(SDL_Cursor * cursor);
+
+typedef int SDLCALL tSDL_ShowCursor(int toggle);
+
+#define SDL_BUTTON(X) (1 << ((X)-1))
+#define SDL_BUTTON_LEFT 1
+#define SDL_BUTTON_MIDDLE 2
+#define SDL_BUTTON_RIGHT 3
+#define SDL_BUTTON_X1 4
+#define SDL_BUTTON_X2 5
+#define SDL_BUTTON_LMASK SDL_BUTTON(SDL_BUTTON_LEFT)
+#define SDL_BUTTON_MMASK SDL_BUTTON(SDL_BUTTON_MIDDLE)
+#define SDL_BUTTON_RMASK SDL_BUTTON(SDL_BUTTON_RIGHT)
+#define SDL_BUTTON_X1MASK SDL_BUTTON(SDL_BUTTON_X1)
+#define SDL_BUTTON_X2MASK SDL_BUTTON(SDL_BUTTON_X2)
+
+extern tSDL_GetMouseFocus *SDL_GetMouseFocus;
+extern tSDL_GetMouseState *SDL_GetMouseState;
+extern tSDL_GetRelativeMouseState *SDL_GetRelativeMouseState;
+extern tSDL_WarpMouseInWindow *SDL_WarpMouseInWindow;
+extern tSDL_SetRelativeMouseMode *SDL_SetRelativeMouseMode;
+extern tSDL_GetRelativeMouseMode *SDL_GetRelativeMouseMode;
+extern tSDL_CreateCursor *SDL_CreateCursor;
+extern tSDL_CreateColorCursor *SDL_CreateColorCursor;
+extern tSDL_CreateSystemCursor *SDL_CreateSystemCursor;
+extern tSDL_SetCursor *SDL_SetCursor;
+extern tSDL_GetCursor *SDL_GetCursor;
+extern tSDL_GetDefaultCursor *SDL_GetDefaultCursor;
+extern tSDL_FreeCursor *SDL_FreeCursor;
+extern tSDL_ShowCursor *SDL_ShowCursor;
+
+#ifdef __cplusplus
+}
+#endif
+#include "close_code.h"
+
+#endif
+
diff --git a/extern/sdlew/include/SDL2/SDL_mutex.h b/extern/sdlew/include/SDL2/SDL_mutex.h
new file mode 100644
index 00000000000..ddfc5730349
--- /dev/null
+++ b/extern/sdlew/include/SDL2/SDL_mutex.h
@@ -0,0 +1,91 @@
+
+#ifndef _SDL_mutex_h
+#define _SDL_mutex_h
+
+#include "SDL_stdinc.h"
+#include "SDL_error.h"
+
+#include "begin_code.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define SDL_MUTEX_TIMEDOUT 1
+
+#define SDL_MUTEX_MAXWAIT (~(Uint32)0)
+
+struct SDL_mutex;
+typedef struct SDL_mutex SDL_mutex;
+
+typedef SDL_mutex * SDLCALL tSDL_CreateMutex(void);
+
+#define SDL_mutexP(m) SDL_LockMutex(m)
+typedef int SDLCALL tSDL_LockMutex(SDL_mutex * mutex);
+
+typedef int SDLCALL tSDL_TryLockMutex(SDL_mutex * mutex);
+
+#define SDL_mutexV(m) SDL_UnlockMutex(m)
+typedef int SDLCALL tSDL_UnlockMutex(SDL_mutex * mutex);
+
+typedef void SDLCALL tSDL_DestroyMutex(SDL_mutex * mutex);
+
+struct SDL_semaphore;
+typedef struct SDL_semaphore SDL_sem;
+
+typedef SDL_sem * SDLCALL tSDL_CreateSemaphore(Uint32 initial_value);
+
+typedef void SDLCALL tSDL_DestroySemaphore(SDL_sem * sem);
+
+typedef int SDLCALL tSDL_SemWait(SDL_sem * sem);
+
+typedef int SDLCALL tSDL_SemTryWait(SDL_sem * sem);
+
+typedef int SDLCALL tSDL_SemWaitTimeout(SDL_sem * sem, Uint32 ms);
+
+typedef int SDLCALL tSDL_SemPost(SDL_sem * sem);
+
+typedef Uint32 SDLCALL tSDL_SemValue(SDL_sem * sem);
+
+struct SDL_cond;
+typedef struct SDL_cond SDL_cond;
+
+typedef SDL_cond * SDLCALL tSDL_CreateCond(void);
+
+typedef void SDLCALL tSDL_DestroyCond(SDL_cond * cond);
+
+typedef int SDLCALL tSDL_CondSignal(SDL_cond * cond);
+
+typedef int SDLCALL tSDL_CondBroadcast(SDL_cond * cond);
+
+typedef int SDLCALL tSDL_CondWait(SDL_cond * cond, SDL_mutex * mutex);
+
+typedef int SDLCALL tSDL_CondWaitTimeout(SDL_cond * cond,
+ SDL_mutex * mutex, Uint32 ms);
+
+extern tSDL_CreateMutex *SDL_CreateMutex;
+extern tSDL_LockMutex *SDL_LockMutex;
+extern tSDL_TryLockMutex *SDL_TryLockMutex;
+extern tSDL_UnlockMutex *SDL_UnlockMutex;
+extern tSDL_DestroyMutex *SDL_DestroyMutex;
+extern tSDL_CreateSemaphore *SDL_CreateSemaphore;
+extern tSDL_DestroySemaphore *SDL_DestroySemaphore;
+extern tSDL_SemWait *SDL_SemWait;
+extern tSDL_SemTryWait *SDL_SemTryWait;
+extern tSDL_SemWaitTimeout *SDL_SemWaitTimeout;
+extern tSDL_SemPost *SDL_SemPost;
+extern tSDL_SemValue *SDL_SemValue;
+extern tSDL_CreateCond *SDL_CreateCond;
+extern tSDL_DestroyCond *SDL_DestroyCond;
+extern tSDL_CondSignal *SDL_CondSignal;
+extern tSDL_CondBroadcast *SDL_CondBroadcast;
+extern tSDL_CondWait *SDL_CondWait;
+extern tSDL_CondWaitTimeout *SDL_CondWaitTimeout;
+
+#ifdef __cplusplus
+}
+#endif
+#include "close_code.h"
+
+#endif
+
diff --git a/extern/sdlew/include/SDL2/SDL_name.h b/extern/sdlew/include/SDL2/SDL_name.h
new file mode 100644
index 00000000000..49e800a4ed9
--- /dev/null
+++ b/extern/sdlew/include/SDL2/SDL_name.h
@@ -0,0 +1,11 @@
+
+#ifndef _SDLname_h_
+#define _SDLname_h_
+
+#if defined(__STDC__) || defined(__cplusplus)
+#define NeedFunctionPrototypes 1
+#endif
+
+#define SDL_NAME(X) SDL_##X
+
+#endif
diff --git a/extern/sdlew/include/SDL2/SDL_opengl.h b/extern/sdlew/include/SDL2/SDL_opengl.h
new file mode 100644
index 00000000000..da242f25394
--- /dev/null
+++ b/extern/sdlew/include/SDL2/SDL_opengl.h
@@ -0,0 +1,10607 @@
+
+#ifndef _SDL_opengl_h
+#define _SDL_opengl_h
+
+#include "SDL_config.h"
+
+#ifndef __IPHONEOS__
+
+#ifdef __WIN32__
+#define WIN32_LEAN_AND_MEAN
+#ifndef NOMINMAX
+#define NOMINMAX
+#endif
+#include <windows.h>
+#endif
+
+#ifdef __glext_h_
+
+#define NO_SDL_GLEXT
+#endif
+#ifndef NO_SDL_GLEXT
+#define __glext_h_
+#endif
+#if defined(__MACOSX__)
+#include <OpenGL/gl.h>
+#define __X_GL_H
+#else
+#include <GL/gl.h>
+#endif
+#ifndef NO_SDL_GLEXT
+#undef __glext_h_
+#endif
+
+#if !defined(NO_SDL_GLEXT) && !defined(GL_GLEXT_LEGACY)
+#ifndef __glext_h_
+#define __glext_h_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define GL_GLEXT_VERSION 64
+
+#if defined(_WIN32) && !defined(APIENTRY) && !defined(__CYGWIN__) && !defined(__SCITECH_SNAP__)
+#define WIN32_LEAN_AND_MEAN 1
+#include <windows.h>
+#endif
+
+#ifndef APIENTRY
+#define APIENTRY
+#endif
+#ifndef APIENTRYP
+#define APIENTRYP APIENTRY *
+#endif
+#ifndef GLAPI
+#define GLAPI extern
+#endif
+
+#ifndef GL_VERSION_1_2
+#define GL_UNSIGNED_BYTE_3_3_2 0x8032
+#define GL_UNSIGNED_SHORT_4_4_4_4 0x8033
+#define GL_UNSIGNED_SHORT_5_5_5_1 0x8034
+#define GL_UNSIGNED_INT_8_8_8_8 0x8035
+#define GL_UNSIGNED_INT_10_10_10_2 0x8036
+#define GL_TEXTURE_BINDING_3D 0x806A
+#define GL_PACK_SKIP_IMAGES 0x806B
+#define GL_PACK_IMAGE_HEIGHT 0x806C
+#define GL_UNPACK_SKIP_IMAGES 0x806D
+#define GL_UNPACK_IMAGE_HEIGHT 0x806E
+#define GL_TEXTURE_3D 0x806F
+#define GL_PROXY_TEXTURE_3D 0x8070
+#define GL_TEXTURE_DEPTH 0x8071
+#define GL_TEXTURE_WRAP_R 0x8072
+#define GL_MAX_3D_TEXTURE_SIZE 0x8073
+#define GL_UNSIGNED_BYTE_2_3_3_REV 0x8362
+#define GL_UNSIGNED_SHORT_5_6_5 0x8363
+#define GL_UNSIGNED_SHORT_5_6_5_REV 0x8364
+#define GL_UNSIGNED_SHORT_4_4_4_4_REV 0x8365
+#define GL_UNSIGNED_SHORT_1_5_5_5_REV 0x8366
+#define GL_UNSIGNED_INT_8_8_8_8_REV 0x8367
+#define GL_UNSIGNED_INT_2_10_10_10_REV 0x8368
+#define GL_BGR 0x80E0
+#define GL_BGRA 0x80E1
+#define GL_MAX_ELEMENTS_VERTICES 0x80E8
+#define GL_MAX_ELEMENTS_INDICES 0x80E9
+#define GL_CLAMP_TO_EDGE 0x812F
+#define GL_TEXTURE_MIN_LOD 0x813A
+#define GL_TEXTURE_MAX_LOD 0x813B
+#define GL_TEXTURE_BASE_LEVEL 0x813C
+#define GL_TEXTURE_MAX_LEVEL 0x813D
+#define GL_SMOOTH_POINT_SIZE_RANGE 0x0B12
+#define GL_SMOOTH_POINT_SIZE_GRANULARITY 0x0B13
+#define GL_SMOOTH_LINE_WIDTH_RANGE 0x0B22
+#define GL_SMOOTH_LINE_WIDTH_GRANULARITY 0x0B23
+#define GL_ALIASED_LINE_WIDTH_RANGE 0x846E
+#endif
+
+#ifndef GL_VERSION_1_2_DEPRECATED
+#define GL_RESCALE_NORMAL 0x803A
+#define GL_LIGHT_MODEL_COLOR_CONTROL 0x81F8
+#define GL_SINGLE_COLOR 0x81F9
+#define GL_SEPARATE_SPECULAR_COLOR 0x81FA
+#define GL_ALIASED_POINT_SIZE_RANGE 0x846D
+#endif
+
+#ifndef GL_ARB_imaging
+#define GL_CONSTANT_COLOR 0x8001
+#define GL_ONE_MINUS_CONSTANT_COLOR 0x8002
+#define GL_CONSTANT_ALPHA 0x8003
+#define GL_ONE_MINUS_CONSTANT_ALPHA 0x8004
+#define GL_BLEND_COLOR 0x8005
+#define GL_FUNC_ADD 0x8006
+#define GL_MIN 0x8007
+#define GL_MAX 0x8008
+#define GL_BLEND_EQUATION 0x8009
+#define GL_FUNC_SUBTRACT 0x800A
+#define GL_FUNC_REVERSE_SUBTRACT 0x800B
+#endif
+
+#ifndef GL_ARB_imaging_DEPRECATED
+#define GL_CONVOLUTION_1D 0x8010
+#define GL_CONVOLUTION_2D 0x8011
+#define GL_SEPARABLE_2D 0x8012
+#define GL_CONVOLUTION_BORDER_MODE 0x8013
+#define GL_CONVOLUTION_FILTER_SCALE 0x8014
+#define GL_CONVOLUTION_FILTER_BIAS 0x8015
+#define GL_REDUCE 0x8016
+#define GL_CONVOLUTION_FORMAT 0x8017
+#define GL_CONVOLUTION_WIDTH 0x8018
+#define GL_CONVOLUTION_HEIGHT 0x8019
+#define GL_MAX_CONVOLUTION_WIDTH 0x801A
+#define GL_MAX_CONVOLUTION_HEIGHT 0x801B
+#define GL_POST_CONVOLUTION_RED_SCALE 0x801C
+#define GL_POST_CONVOLUTION_GREEN_SCALE 0x801D
+#define GL_POST_CONVOLUTION_BLUE_SCALE 0x801E
+#define GL_POST_CONVOLUTION_ALPHA_SCALE 0x801F
+#define GL_POST_CONVOLUTION_RED_BIAS 0x8020
+#define GL_POST_CONVOLUTION_GREEN_BIAS 0x8021
+#define GL_POST_CONVOLUTION_BLUE_BIAS 0x8022
+#define GL_POST_CONVOLUTION_ALPHA_BIAS 0x8023
+#define GL_HISTOGRAM 0x8024
+#define GL_PROXY_HISTOGRAM 0x8025
+#define GL_HISTOGRAM_WIDTH 0x8026
+#define GL_HISTOGRAM_FORMAT 0x8027
+#define GL_HISTOGRAM_RED_SIZE 0x8028
+#define GL_HISTOGRAM_GREEN_SIZE 0x8029
+#define GL_HISTOGRAM_BLUE_SIZE 0x802A
+#define GL_HISTOGRAM_ALPHA_SIZE 0x802B
+#define GL_HISTOGRAM_LUMINANCE_SIZE 0x802C
+#define GL_HISTOGRAM_SINK 0x802D
+#define GL_MINMAX 0x802E
+#define GL_MINMAX_FORMAT 0x802F
+#define GL_MINMAX_SINK 0x8030
+#define GL_TABLE_TOO_LARGE 0x8031
+#define GL_COLOR_MATRIX 0x80B1
+#define GL_COLOR_MATRIX_STACK_DEPTH 0x80B2
+#define GL_MAX_COLOR_MATRIX_STACK_DEPTH 0x80B3
+#define GL_POST_COLOR_MATRIX_RED_SCALE 0x80B4
+#define GL_POST_COLOR_MATRIX_GREEN_SCALE 0x80B5
+#define GL_POST_COLOR_MATRIX_BLUE_SCALE 0x80B6
+#define GL_POST_COLOR_MATRIX_ALPHA_SCALE 0x80B7
+#define GL_POST_COLOR_MATRIX_RED_BIAS 0x80B8
+#define GL_POST_COLOR_MATRIX_GREEN_BIAS 0x80B9
+#define GL_POST_COLOR_MATRIX_BLUE_BIAS 0x80BA
+#define GL_POST_COLOR_MATRIX_ALPHA_BIAS 0x80BB
+#define GL_COLOR_TABLE 0x80D0
+#define GL_POST_CONVOLUTION_COLOR_TABLE 0x80D1
+#define GL_POST_COLOR_MATRIX_COLOR_TABLE 0x80D2
+#define GL_PROXY_COLOR_TABLE 0x80D3
+#define GL_PROXY_POST_CONVOLUTION_COLOR_TABLE 0x80D4
+#define GL_PROXY_POST_COLOR_MATRIX_COLOR_TABLE 0x80D5
+#define GL_COLOR_TABLE_SCALE 0x80D6
+#define GL_COLOR_TABLE_BIAS 0x80D7
+#define GL_COLOR_TABLE_FORMAT 0x80D8
+#define GL_COLOR_TABLE_WIDTH 0x80D9
+#define GL_COLOR_TABLE_RED_SIZE 0x80DA
+#define GL_COLOR_TABLE_GREEN_SIZE 0x80DB
+#define GL_COLOR_TABLE_BLUE_SIZE 0x80DC
+#define GL_COLOR_TABLE_ALPHA_SIZE 0x80DD
+#define GL_COLOR_TABLE_LUMINANCE_SIZE 0x80DE
+#define GL_COLOR_TABLE_INTENSITY_SIZE 0x80DF
+#define GL_CONSTANT_BORDER 0x8151
+#define GL_REPLICATE_BORDER 0x8153
+#define GL_CONVOLUTION_BORDER_COLOR 0x8154
+#endif
+
+#ifndef GL_VERSION_1_3
+#define GL_TEXTURE0 0x84C0
+#define GL_TEXTURE1 0x84C1
+#define GL_TEXTURE2 0x84C2
+#define GL_TEXTURE3 0x84C3
+#define GL_TEXTURE4 0x84C4
+#define GL_TEXTURE5 0x84C5
+#define GL_TEXTURE6 0x84C6
+#define GL_TEXTURE7 0x84C7
+#define GL_TEXTURE8 0x84C8
+#define GL_TEXTURE9 0x84C9
+#define GL_TEXTURE10 0x84CA
+#define GL_TEXTURE11 0x84CB
+#define GL_TEXTURE12 0x84CC
+#define GL_TEXTURE13 0x84CD
+#define GL_TEXTURE14 0x84CE
+#define GL_TEXTURE15 0x84CF
+#define GL_TEXTURE16 0x84D0
+#define GL_TEXTURE17 0x84D1
+#define GL_TEXTURE18 0x84D2
+#define GL_TEXTURE19 0x84D3
+#define GL_TEXTURE20 0x84D4
+#define GL_TEXTURE21 0x84D5
+#define GL_TEXTURE22 0x84D6
+#define GL_TEXTURE23 0x84D7
+#define GL_TEXTURE24 0x84D8
+#define GL_TEXTURE25 0x84D9
+#define GL_TEXTURE26 0x84DA
+#define GL_TEXTURE27 0x84DB
+#define GL_TEXTURE28 0x84DC
+#define GL_TEXTURE29 0x84DD
+#define GL_TEXTURE30 0x84DE
+#define GL_TEXTURE31 0x84DF
+#define GL_ACTIVE_TEXTURE 0x84E0
+#define GL_MULTISAMPLE 0x809D
+#define GL_SAMPLE_ALPHA_TO_COVERAGE 0x809E
+#define GL_SAMPLE_ALPHA_TO_ONE 0x809F
+#define GL_SAMPLE_COVERAGE 0x80A0
+#define GL_SAMPLE_BUFFERS 0x80A8
+#define GL_SAMPLES 0x80A9
+#define GL_SAMPLE_COVERAGE_VALUE 0x80AA
+#define GL_SAMPLE_COVERAGE_INVERT 0x80AB
+#define GL_TEXTURE_CUBE_MAP 0x8513
+#define GL_TEXTURE_BINDING_CUBE_MAP 0x8514
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_X 0x8515
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_X 0x8516
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_Y 0x8517
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y 0x8518
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z 0x8519
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z 0x851A
+#define GL_PROXY_TEXTURE_CUBE_MAP 0x851B
+#define GL_MAX_CUBE_MAP_TEXTURE_SIZE 0x851C
+#define GL_COMPRESSED_RGB 0x84ED
+#define GL_COMPRESSED_RGBA 0x84EE
+#define GL_TEXTURE_COMPRESSION_HINT 0x84EF
+#define GL_TEXTURE_COMPRESSED_IMAGE_SIZE 0x86A0
+#define GL_TEXTURE_COMPRESSED 0x86A1
+#define GL_NUM_COMPRESSED_TEXTURE_FORMATS 0x86A2
+#define GL_COMPRESSED_TEXTURE_FORMATS 0x86A3
+#define GL_CLAMP_TO_BORDER 0x812D
+#endif
+
+#ifndef GL_VERSION_1_3_DEPRECATED
+#define GL_CLIENT_ACTIVE_TEXTURE 0x84E1
+#define GL_MAX_TEXTURE_UNITS 0x84E2
+#define GL_TRANSPOSE_MODELVIEW_MATRIX 0x84E3
+#define GL_TRANSPOSE_PROJECTION_MATRIX 0x84E4
+#define GL_TRANSPOSE_TEXTURE_MATRIX 0x84E5
+#define GL_TRANSPOSE_COLOR_MATRIX 0x84E6
+#define GL_MULTISAMPLE_BIT 0x20000000
+#define GL_NORMAL_MAP 0x8511
+#define GL_REFLECTION_MAP 0x8512
+#define GL_COMPRESSED_ALPHA 0x84E9
+#define GL_COMPRESSED_LUMINANCE 0x84EA
+#define GL_COMPRESSED_LUMINANCE_ALPHA 0x84EB
+#define GL_COMPRESSED_INTENSITY 0x84EC
+#define GL_COMBINE 0x8570
+#define GL_COMBINE_RGB 0x8571
+#define GL_COMBINE_ALPHA 0x8572
+#define GL_SOURCE0_RGB 0x8580
+#define GL_SOURCE1_RGB 0x8581
+#define GL_SOURCE2_RGB 0x8582
+#define GL_SOURCE0_ALPHA 0x8588
+#define GL_SOURCE1_ALPHA 0x8589
+#define GL_SOURCE2_ALPHA 0x858A
+#define GL_OPERAND0_RGB 0x8590
+#define GL_OPERAND1_RGB 0x8591
+#define GL_OPERAND2_RGB 0x8592
+#define GL_OPERAND0_ALPHA 0x8598
+#define GL_OPERAND1_ALPHA 0x8599
+#define GL_OPERAND2_ALPHA 0x859A
+#define GL_RGB_SCALE 0x8573
+#define GL_ADD_SIGNED 0x8574
+#define GL_INTERPOLATE 0x8575
+#define GL_SUBTRACT 0x84E7
+#define GL_CONSTANT 0x8576
+#define GL_PRIMARY_COLOR 0x8577
+#define GL_PREVIOUS 0x8578
+#define GL_DOT3_RGB 0x86AE
+#define GL_DOT3_RGBA 0x86AF
+#endif
+
+#ifndef GL_VERSION_1_4
+#define GL_BLEND_DST_RGB 0x80C8
+#define GL_BLEND_SRC_RGB 0x80C9
+#define GL_BLEND_DST_ALPHA 0x80CA
+#define GL_BLEND_SRC_ALPHA 0x80CB
+#define GL_POINT_FADE_THRESHOLD_SIZE 0x8128
+#define GL_DEPTH_COMPONENT16 0x81A5
+#define GL_DEPTH_COMPONENT24 0x81A6
+#define GL_DEPTH_COMPONENT32 0x81A7
+#define GL_MIRRORED_REPEAT 0x8370
+#define GL_MAX_TEXTURE_LOD_BIAS 0x84FD
+#define GL_TEXTURE_LOD_BIAS 0x8501
+#define GL_INCR_WRAP 0x8507
+#define GL_DECR_WRAP 0x8508
+#define GL_TEXTURE_DEPTH_SIZE 0x884A
+#define GL_TEXTURE_COMPARE_MODE 0x884C
+#define GL_TEXTURE_COMPARE_FUNC 0x884D
+#endif
+
+#ifndef GL_VERSION_1_4_DEPRECATED
+#define GL_POINT_SIZE_MIN 0x8126
+#define GL_POINT_SIZE_MAX 0x8127
+#define GL_POINT_DISTANCE_ATTENUATION 0x8129
+#define GL_GENERATE_MIPMAP 0x8191
+#define GL_GENERATE_MIPMAP_HINT 0x8192
+#define GL_FOG_COORDINATE_SOURCE 0x8450
+#define GL_FOG_COORDINATE 0x8451
+#define GL_FRAGMENT_DEPTH 0x8452
+#define GL_CURRENT_FOG_COORDINATE 0x8453
+#define GL_FOG_COORDINATE_ARRAY_TYPE 0x8454
+#define GL_FOG_COORDINATE_ARRAY_STRIDE 0x8455
+#define GL_FOG_COORDINATE_ARRAY_POINTER 0x8456
+#define GL_FOG_COORDINATE_ARRAY 0x8457
+#define GL_COLOR_SUM 0x8458
+#define GL_CURRENT_SECONDARY_COLOR 0x8459
+#define GL_SECONDARY_COLOR_ARRAY_SIZE 0x845A
+#define GL_SECONDARY_COLOR_ARRAY_TYPE 0x845B
+#define GL_SECONDARY_COLOR_ARRAY_STRIDE 0x845C
+#define GL_SECONDARY_COLOR_ARRAY_POINTER 0x845D
+#define GL_SECONDARY_COLOR_ARRAY 0x845E
+#define GL_TEXTURE_FILTER_CONTROL 0x8500
+#define GL_DEPTH_TEXTURE_MODE 0x884B
+#define GL_COMPARE_R_TO_TEXTURE 0x884E
+#endif
+
+#ifndef GL_VERSION_1_5
+#define GL_BUFFER_SIZE 0x8764
+#define GL_BUFFER_USAGE 0x8765
+#define GL_QUERY_COUNTER_BITS 0x8864
+#define GL_CURRENT_QUERY 0x8865
+#define GL_QUERY_RESULT 0x8866
+#define GL_QUERY_RESULT_AVAILABLE 0x8867
+#define GL_ARRAY_BUFFER 0x8892
+#define GL_ELEMENT_ARRAY_BUFFER 0x8893
+#define GL_ARRAY_BUFFER_BINDING 0x8894
+#define GL_ELEMENT_ARRAY_BUFFER_BINDING 0x8895
+#define GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING 0x889F
+#define GL_READ_ONLY 0x88B8
+#define GL_WRITE_ONLY 0x88B9
+#define GL_READ_WRITE 0x88BA
+#define GL_BUFFER_ACCESS 0x88BB
+#define GL_BUFFER_MAPPED 0x88BC
+#define GL_BUFFER_MAP_POINTER 0x88BD
+#define GL_STREAM_DRAW 0x88E0
+#define GL_STREAM_READ 0x88E1
+#define GL_STREAM_COPY 0x88E2
+#define GL_STATIC_DRAW 0x88E4
+#define GL_STATIC_READ 0x88E5
+#define GL_STATIC_COPY 0x88E6
+#define GL_DYNAMIC_DRAW 0x88E8
+#define GL_DYNAMIC_READ 0x88E9
+#define GL_DYNAMIC_COPY 0x88EA
+#define GL_SAMPLES_PASSED 0x8914
+#endif
+
+#ifndef GL_VERSION_1_5_DEPRECATED
+#define GL_VERTEX_ARRAY_BUFFER_BINDING 0x8896
+#define GL_NORMAL_ARRAY_BUFFER_BINDING 0x8897
+#define GL_COLOR_ARRAY_BUFFER_BINDING 0x8898
+#define GL_INDEX_ARRAY_BUFFER_BINDING 0x8899
+#define GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING 0x889A
+#define GL_EDGE_FLAG_ARRAY_BUFFER_BINDING 0x889B
+#define GL_SECONDARY_COLOR_ARRAY_BUFFER_BINDING 0x889C
+#define GL_FOG_COORDINATE_ARRAY_BUFFER_BINDING 0x889D
+#define GL_WEIGHT_ARRAY_BUFFER_BINDING 0x889E
+#define GL_FOG_COORD_SRC 0x8450
+#define GL_FOG_COORD 0x8451
+#define GL_CURRENT_FOG_COORD 0x8453
+#define GL_FOG_COORD_ARRAY_TYPE 0x8454
+#define GL_FOG_COORD_ARRAY_STRIDE 0x8455
+#define GL_FOG_COORD_ARRAY_POINTER 0x8456
+#define GL_FOG_COORD_ARRAY 0x8457
+#define GL_FOG_COORD_ARRAY_BUFFER_BINDING 0x889D
+#define GL_SRC0_RGB 0x8580
+#define GL_SRC1_RGB 0x8581
+#define GL_SRC2_RGB 0x8582
+#define GL_SRC0_ALPHA 0x8588
+#define GL_SRC1_ALPHA 0x8589
+#define GL_SRC2_ALPHA 0x858A
+#endif
+
+#ifndef GL_VERSION_2_0
+#define GL_BLEND_EQUATION_RGB 0x8009
+#define GL_VERTEX_ATTRIB_ARRAY_ENABLED 0x8622
+#define GL_VERTEX_ATTRIB_ARRAY_SIZE 0x8623
+#define GL_VERTEX_ATTRIB_ARRAY_STRIDE 0x8624
+#define GL_VERTEX_ATTRIB_ARRAY_TYPE 0x8625
+#define GL_CURRENT_VERTEX_ATTRIB 0x8626
+#define GL_VERTEX_PROGRAM_POINT_SIZE 0x8642
+#define GL_VERTEX_ATTRIB_ARRAY_POINTER 0x8645
+#define GL_STENCIL_BACK_FUNC 0x8800
+#define GL_STENCIL_BACK_FAIL 0x8801
+#define GL_STENCIL_BACK_PASS_DEPTH_FAIL 0x8802
+#define GL_STENCIL_BACK_PASS_DEPTH_PASS 0x8803
+#define GL_MAX_DRAW_BUFFERS 0x8824
+#define GL_DRAW_BUFFER0 0x8825
+#define GL_DRAW_BUFFER1 0x8826
+#define GL_DRAW_BUFFER2 0x8827
+#define GL_DRAW_BUFFER3 0x8828
+#define GL_DRAW_BUFFER4 0x8829
+#define GL_DRAW_BUFFER5 0x882A
+#define GL_DRAW_BUFFER6 0x882B
+#define GL_DRAW_BUFFER7 0x882C
+#define GL_DRAW_BUFFER8 0x882D
+#define GL_DRAW_BUFFER9 0x882E
+#define GL_DRAW_BUFFER10 0x882F
+#define GL_DRAW_BUFFER11 0x8830
+#define GL_DRAW_BUFFER12 0x8831
+#define GL_DRAW_BUFFER13 0x8832
+#define GL_DRAW_BUFFER14 0x8833
+#define GL_DRAW_BUFFER15 0x8834
+#define GL_BLEND_EQUATION_ALPHA 0x883D
+#define GL_MAX_VERTEX_ATTRIBS 0x8869
+#define GL_VERTEX_ATTRIB_ARRAY_NORMALIZED 0x886A
+#define GL_MAX_TEXTURE_IMAGE_UNITS 0x8872
+#define GL_FRAGMENT_SHADER 0x8B30
+#define GL_VERTEX_SHADER 0x8B31
+#define GL_MAX_FRAGMENT_UNIFORM_COMPONENTS 0x8B49
+#define GL_MAX_VERTEX_UNIFORM_COMPONENTS 0x8B4A
+#define GL_MAX_VARYING_FLOATS 0x8B4B
+#define GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS 0x8B4C
+#define GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS 0x8B4D
+#define GL_SHADER_TYPE 0x8B4F
+#define GL_FLOAT_VEC2 0x8B50
+#define GL_FLOAT_VEC3 0x8B51
+#define GL_FLOAT_VEC4 0x8B52
+#define GL_INT_VEC2 0x8B53
+#define GL_INT_VEC3 0x8B54
+#define GL_INT_VEC4 0x8B55
+#define GL_BOOL 0x8B56
+#define GL_BOOL_VEC2 0x8B57
+#define GL_BOOL_VEC3 0x8B58
+#define GL_BOOL_VEC4 0x8B59
+#define GL_FLOAT_MAT2 0x8B5A
+#define GL_FLOAT_MAT3 0x8B5B
+#define GL_FLOAT_MAT4 0x8B5C
+#define GL_SAMPLER_1D 0x8B5D
+#define GL_SAMPLER_2D 0x8B5E
+#define GL_SAMPLER_3D 0x8B5F
+#define GL_SAMPLER_CUBE 0x8B60
+#define GL_SAMPLER_1D_SHADOW 0x8B61
+#define GL_SAMPLER_2D_SHADOW 0x8B62
+#define GL_DELETE_STATUS 0x8B80
+#define GL_COMPILE_STATUS 0x8B81
+#define GL_LINK_STATUS 0x8B82
+#define GL_VALIDATE_STATUS 0x8B83
+#define GL_INFO_LOG_LENGTH 0x8B84
+#define GL_ATTACHED_SHADERS 0x8B85
+#define GL_ACTIVE_UNIFORMS 0x8B86
+#define GL_ACTIVE_UNIFORM_MAX_LENGTH 0x8B87
+#define GL_SHADER_SOURCE_LENGTH 0x8B88
+#define GL_ACTIVE_ATTRIBUTES 0x8B89
+#define GL_ACTIVE_ATTRIBUTE_MAX_LENGTH 0x8B8A
+#define GL_FRAGMENT_SHADER_DERIVATIVE_HINT 0x8B8B
+#define GL_SHADING_LANGUAGE_VERSION 0x8B8C
+#define GL_CURRENT_PROGRAM 0x8B8D
+#define GL_POINT_SPRITE_COORD_ORIGIN 0x8CA0
+#define GL_LOWER_LEFT 0x8CA1
+#define GL_UPPER_LEFT 0x8CA2
+#define GL_STENCIL_BACK_REF 0x8CA3
+#define GL_STENCIL_BACK_VALUE_MASK 0x8CA4
+#define GL_STENCIL_BACK_WRITEMASK 0x8CA5
+#endif
+
+#ifndef GL_VERSION_2_0_DEPRECATED
+#define GL_VERTEX_PROGRAM_TWO_SIDE 0x8643
+#define GL_POINT_SPRITE 0x8861
+#define GL_COORD_REPLACE 0x8862
+#define GL_MAX_TEXTURE_COORDS 0x8871
+#endif
+
+#ifndef GL_VERSION_2_1
+#define GL_PIXEL_PACK_BUFFER 0x88EB
+#define GL_PIXEL_UNPACK_BUFFER 0x88EC
+#define GL_PIXEL_PACK_BUFFER_BINDING 0x88ED
+#define GL_PIXEL_UNPACK_BUFFER_BINDING 0x88EF
+#define GL_FLOAT_MAT2x3 0x8B65
+#define GL_FLOAT_MAT2x4 0x8B66
+#define GL_FLOAT_MAT3x2 0x8B67
+#define GL_FLOAT_MAT3x4 0x8B68
+#define GL_FLOAT_MAT4x2 0x8B69
+#define GL_FLOAT_MAT4x3 0x8B6A
+#define GL_SRGB 0x8C40
+#define GL_SRGB8 0x8C41
+#define GL_SRGB_ALPHA 0x8C42
+#define GL_SRGB8_ALPHA8 0x8C43
+#define GL_COMPRESSED_SRGB 0x8C48
+#define GL_COMPRESSED_SRGB_ALPHA 0x8C49
+#endif
+
+#ifndef GL_VERSION_2_1_DEPRECATED
+#define GL_CURRENT_RASTER_SECONDARY_COLOR 0x845F
+#define GL_SLUMINANCE_ALPHA 0x8C44
+#define GL_SLUMINANCE8_ALPHA8 0x8C45
+#define GL_SLUMINANCE 0x8C46
+#define GL_SLUMINANCE8 0x8C47
+#define GL_COMPRESSED_SLUMINANCE 0x8C4A
+#define GL_COMPRESSED_SLUMINANCE_ALPHA 0x8C4B
+#endif
+
+#ifndef GL_VERSION_3_0
+#define GL_COMPARE_REF_TO_TEXTURE 0x884E
+#define GL_CLIP_DISTANCE0 0x3000
+#define GL_CLIP_DISTANCE1 0x3001
+#define GL_CLIP_DISTANCE2 0x3002
+#define GL_CLIP_DISTANCE3 0x3003
+#define GL_CLIP_DISTANCE4 0x3004
+#define GL_CLIP_DISTANCE5 0x3005
+#define GL_CLIP_DISTANCE6 0x3006
+#define GL_CLIP_DISTANCE7 0x3007
+#define GL_MAX_CLIP_DISTANCES 0x0D32
+#define GL_MAJOR_VERSION 0x821B
+#define GL_MINOR_VERSION 0x821C
+#define GL_NUM_EXTENSIONS 0x821D
+#define GL_CONTEXT_FLAGS 0x821E
+#define GL_DEPTH_BUFFER 0x8223
+#define GL_STENCIL_BUFFER 0x8224
+#define GL_COMPRESSED_RED 0x8225
+#define GL_COMPRESSED_RG 0x8226
+#define GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT 0x0001
+#define GL_RGBA32F 0x8814
+#define GL_RGB32F 0x8815
+#define GL_RGBA16F 0x881A
+#define GL_RGB16F 0x881B
+#define GL_VERTEX_ATTRIB_ARRAY_INTEGER 0x88FD
+#define GL_MAX_ARRAY_TEXTURE_LAYERS 0x88FF
+#define GL_MIN_PROGRAM_TEXEL_OFFSET 0x8904
+#define GL_MAX_PROGRAM_TEXEL_OFFSET 0x8905
+#define GL_CLAMP_READ_COLOR 0x891C
+#define GL_FIXED_ONLY 0x891D
+#define GL_MAX_VARYING_COMPONENTS 0x8B4B
+#define GL_TEXTURE_1D_ARRAY 0x8C18
+#define GL_PROXY_TEXTURE_1D_ARRAY 0x8C19
+#define GL_TEXTURE_2D_ARRAY 0x8C1A
+#define GL_PROXY_TEXTURE_2D_ARRAY 0x8C1B
+#define GL_TEXTURE_BINDING_1D_ARRAY 0x8C1C
+#define GL_TEXTURE_BINDING_2D_ARRAY 0x8C1D
+#define GL_R11F_G11F_B10F 0x8C3A
+#define GL_UNSIGNED_INT_10F_11F_11F_REV 0x8C3B
+#define GL_RGB9_E5 0x8C3D
+#define GL_UNSIGNED_INT_5_9_9_9_REV 0x8C3E
+#define GL_TEXTURE_SHARED_SIZE 0x8C3F
+#define GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH 0x8C76
+#define GL_TRANSFORM_FEEDBACK_BUFFER_MODE 0x8C7F
+#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS 0x8C80
+#define GL_TRANSFORM_FEEDBACK_VARYINGS 0x8C83
+#define GL_TRANSFORM_FEEDBACK_BUFFER_START 0x8C84
+#define GL_TRANSFORM_FEEDBACK_BUFFER_SIZE 0x8C85
+#define GL_PRIMITIVES_GENERATED 0x8C87
+#define GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN 0x8C88
+#define GL_RASTERIZER_DISCARD 0x8C89
+#define GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS 0x8C8A
+#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS 0x8C8B
+#define GL_INTERLEAVED_ATTRIBS 0x8C8C
+#define GL_SEPARATE_ATTRIBS 0x8C8D
+#define GL_TRANSFORM_FEEDBACK_BUFFER 0x8C8E
+#define GL_TRANSFORM_FEEDBACK_BUFFER_BINDING 0x8C8F
+#define GL_RGBA32UI 0x8D70
+#define GL_RGB32UI 0x8D71
+#define GL_RGBA16UI 0x8D76
+#define GL_RGB16UI 0x8D77
+#define GL_RGBA8UI 0x8D7C
+#define GL_RGB8UI 0x8D7D
+#define GL_RGBA32I 0x8D82
+#define GL_RGB32I 0x8D83
+#define GL_RGBA16I 0x8D88
+#define GL_RGB16I 0x8D89
+#define GL_RGBA8I 0x8D8E
+#define GL_RGB8I 0x8D8F
+#define GL_RED_INTEGER 0x8D94
+#define GL_GREEN_INTEGER 0x8D95
+#define GL_BLUE_INTEGER 0x8D96
+#define GL_RGB_INTEGER 0x8D98
+#define GL_RGBA_INTEGER 0x8D99
+#define GL_BGR_INTEGER 0x8D9A
+#define GL_BGRA_INTEGER 0x8D9B
+#define GL_SAMPLER_1D_ARRAY 0x8DC0
+#define GL_SAMPLER_2D_ARRAY 0x8DC1
+#define GL_SAMPLER_1D_ARRAY_SHADOW 0x8DC3
+#define GL_SAMPLER_2D_ARRAY_SHADOW 0x8DC4
+#define GL_SAMPLER_CUBE_SHADOW 0x8DC5
+#define GL_UNSIGNED_INT_VEC2 0x8DC6
+#define GL_UNSIGNED_INT_VEC3 0x8DC7
+#define GL_UNSIGNED_INT_VEC4 0x8DC8
+#define GL_INT_SAMPLER_1D 0x8DC9
+#define GL_INT_SAMPLER_2D 0x8DCA
+#define GL_INT_SAMPLER_3D 0x8DCB
+#define GL_INT_SAMPLER_CUBE 0x8DCC
+#define GL_INT_SAMPLER_1D_ARRAY 0x8DCE
+#define GL_INT_SAMPLER_2D_ARRAY 0x8DCF
+#define GL_UNSIGNED_INT_SAMPLER_1D 0x8DD1
+#define GL_UNSIGNED_INT_SAMPLER_2D 0x8DD2
+#define GL_UNSIGNED_INT_SAMPLER_3D 0x8DD3
+#define GL_UNSIGNED_INT_SAMPLER_CUBE 0x8DD4
+#define GL_UNSIGNED_INT_SAMPLER_1D_ARRAY 0x8DD6
+#define GL_UNSIGNED_INT_SAMPLER_2D_ARRAY 0x8DD7
+#define GL_QUERY_WAIT 0x8E13
+#define GL_QUERY_NO_WAIT 0x8E14
+#define GL_QUERY_BY_REGION_WAIT 0x8E15
+#define GL_QUERY_BY_REGION_NO_WAIT 0x8E16
+#define GL_BUFFER_ACCESS_FLAGS 0x911F
+#define GL_BUFFER_MAP_LENGTH 0x9120
+#define GL_BUFFER_MAP_OFFSET 0x9121
+
+#endif
+
+#ifndef GL_VERSION_3_0_DEPRECATED
+#define GL_CLAMP_VERTEX_COLOR 0x891A
+#define GL_CLAMP_FRAGMENT_COLOR 0x891B
+#define GL_ALPHA_INTEGER 0x8D97
+
+#endif
+
+#ifndef GL_VERSION_3_1
+#define GL_SAMPLER_2D_RECT 0x8B63
+#define GL_SAMPLER_2D_RECT_SHADOW 0x8B64
+#define GL_SAMPLER_BUFFER 0x8DC2
+#define GL_INT_SAMPLER_2D_RECT 0x8DCD
+#define GL_INT_SAMPLER_BUFFER 0x8DD0
+#define GL_UNSIGNED_INT_SAMPLER_2D_RECT 0x8DD5
+#define GL_UNSIGNED_INT_SAMPLER_BUFFER 0x8DD8
+#define GL_TEXTURE_BUFFER 0x8C2A
+#define GL_MAX_TEXTURE_BUFFER_SIZE 0x8C2B
+#define GL_TEXTURE_BINDING_BUFFER 0x8C2C
+#define GL_TEXTURE_BUFFER_DATA_STORE_BINDING 0x8C2D
+#define GL_TEXTURE_BUFFER_FORMAT 0x8C2E
+#define GL_TEXTURE_RECTANGLE 0x84F5
+#define GL_TEXTURE_BINDING_RECTANGLE 0x84F6
+#define GL_PROXY_TEXTURE_RECTANGLE 0x84F7
+#define GL_MAX_RECTANGLE_TEXTURE_SIZE 0x84F8
+#define GL_RED_SNORM 0x8F90
+#define GL_RG_SNORM 0x8F91
+#define GL_RGB_SNORM 0x8F92
+#define GL_RGBA_SNORM 0x8F93
+#define GL_R8_SNORM 0x8F94
+#define GL_RG8_SNORM 0x8F95
+#define GL_RGB8_SNORM 0x8F96
+#define GL_RGBA8_SNORM 0x8F97
+#define GL_R16_SNORM 0x8F98
+#define GL_RG16_SNORM 0x8F99
+#define GL_RGB16_SNORM 0x8F9A
+#define GL_RGBA16_SNORM 0x8F9B
+#define GL_SIGNED_NORMALIZED 0x8F9C
+#define GL_PRIMITIVE_RESTART 0x8F9D
+#define GL_PRIMITIVE_RESTART_INDEX 0x8F9E
+
+#endif
+
+#ifndef GL_VERSION_3_2
+#define GL_CONTEXT_CORE_PROFILE_BIT 0x00000001
+#define GL_CONTEXT_COMPATIBILITY_PROFILE_BIT 0x00000002
+#define GL_LINES_ADJACENCY 0x000A
+#define GL_LINE_STRIP_ADJACENCY 0x000B
+#define GL_TRIANGLES_ADJACENCY 0x000C
+#define GL_TRIANGLE_STRIP_ADJACENCY 0x000D
+#define GL_PROGRAM_POINT_SIZE 0x8642
+#define GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS 0x8C29
+#define GL_FRAMEBUFFER_ATTACHMENT_LAYERED 0x8DA7
+#define GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS 0x8DA8
+#define GL_GEOMETRY_SHADER 0x8DD9
+#define GL_GEOMETRY_VERTICES_OUT 0x8916
+#define GL_GEOMETRY_INPUT_TYPE 0x8917
+#define GL_GEOMETRY_OUTPUT_TYPE 0x8918
+#define GL_MAX_GEOMETRY_UNIFORM_COMPONENTS 0x8DDF
+#define GL_MAX_GEOMETRY_OUTPUT_VERTICES 0x8DE0
+#define GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS 0x8DE1
+#define GL_MAX_VERTEX_OUTPUT_COMPONENTS 0x9122
+#define GL_MAX_GEOMETRY_INPUT_COMPONENTS 0x9123
+#define GL_MAX_GEOMETRY_OUTPUT_COMPONENTS 0x9124
+#define GL_MAX_FRAGMENT_INPUT_COMPONENTS 0x9125
+#define GL_CONTEXT_PROFILE_MASK 0x9126
+
+#endif
+
+#ifndef GL_VERSION_3_3
+#define GL_VERTEX_ATTRIB_ARRAY_DIVISOR 0x88FE
+
+#endif
+
+#ifndef GL_VERSION_4_0
+#define GL_SAMPLE_SHADING 0x8C36
+#define GL_MIN_SAMPLE_SHADING_VALUE 0x8C37
+#define GL_MIN_PROGRAM_TEXTURE_GATHER_OFFSET 0x8E5E
+#define GL_MAX_PROGRAM_TEXTURE_GATHER_OFFSET 0x8E5F
+#define GL_TEXTURE_CUBE_MAP_ARRAY 0x9009
+#define GL_TEXTURE_BINDING_CUBE_MAP_ARRAY 0x900A
+#define GL_PROXY_TEXTURE_CUBE_MAP_ARRAY 0x900B
+#define GL_SAMPLER_CUBE_MAP_ARRAY 0x900C
+#define GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW 0x900D
+#define GL_INT_SAMPLER_CUBE_MAP_ARRAY 0x900E
+#define GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY 0x900F
+
+#endif
+
+#ifndef GL_VERSION_4_1
+
+#endif
+
+#ifndef GL_ARB_multitexture
+#define GL_TEXTURE0_ARB 0x84C0
+#define GL_TEXTURE1_ARB 0x84C1
+#define GL_TEXTURE2_ARB 0x84C2
+#define GL_TEXTURE3_ARB 0x84C3
+#define GL_TEXTURE4_ARB 0x84C4
+#define GL_TEXTURE5_ARB 0x84C5
+#define GL_TEXTURE6_ARB 0x84C6
+#define GL_TEXTURE7_ARB 0x84C7
+#define GL_TEXTURE8_ARB 0x84C8
+#define GL_TEXTURE9_ARB 0x84C9
+#define GL_TEXTURE10_ARB 0x84CA
+#define GL_TEXTURE11_ARB 0x84CB
+#define GL_TEXTURE12_ARB 0x84CC
+#define GL_TEXTURE13_ARB 0x84CD
+#define GL_TEXTURE14_ARB 0x84CE
+#define GL_TEXTURE15_ARB 0x84CF
+#define GL_TEXTURE16_ARB 0x84D0
+#define GL_TEXTURE17_ARB 0x84D1
+#define GL_TEXTURE18_ARB 0x84D2
+#define GL_TEXTURE19_ARB 0x84D3
+#define GL_TEXTURE20_ARB 0x84D4
+#define GL_TEXTURE21_ARB 0x84D5
+#define GL_TEXTURE22_ARB 0x84D6
+#define GL_TEXTURE23_ARB 0x84D7
+#define GL_TEXTURE24_ARB 0x84D8
+#define GL_TEXTURE25_ARB 0x84D9
+#define GL_TEXTURE26_ARB 0x84DA
+#define GL_TEXTURE27_ARB 0x84DB
+#define GL_TEXTURE28_ARB 0x84DC
+#define GL_TEXTURE29_ARB 0x84DD
+#define GL_TEXTURE30_ARB 0x84DE
+#define GL_TEXTURE31_ARB 0x84DF
+#define GL_ACTIVE_TEXTURE_ARB 0x84E0
+#define GL_CLIENT_ACTIVE_TEXTURE_ARB 0x84E1
+#define GL_MAX_TEXTURE_UNITS_ARB 0x84E2
+#endif
+
+#ifndef GL_ARB_transpose_matrix
+#define GL_TRANSPOSE_MODELVIEW_MATRIX_ARB 0x84E3
+#define GL_TRANSPOSE_PROJECTION_MATRIX_ARB 0x84E4
+#define GL_TRANSPOSE_TEXTURE_MATRIX_ARB 0x84E5
+#define GL_TRANSPOSE_COLOR_MATRIX_ARB 0x84E6
+#endif
+
+#ifndef GL_ARB_multisample
+#define GL_MULTISAMPLE_ARB 0x809D
+#define GL_SAMPLE_ALPHA_TO_COVERAGE_ARB 0x809E
+#define GL_SAMPLE_ALPHA_TO_ONE_ARB 0x809F
+#define GL_SAMPLE_COVERAGE_ARB 0x80A0
+#define GL_SAMPLE_BUFFERS_ARB 0x80A8
+#define GL_SAMPLES_ARB 0x80A9
+#define GL_SAMPLE_COVERAGE_VALUE_ARB 0x80AA
+#define GL_SAMPLE_COVERAGE_INVERT_ARB 0x80AB
+#define GL_MULTISAMPLE_BIT_ARB 0x20000000
+#endif
+
+#ifndef GL_ARB_texture_env_add
+#endif
+
+#ifndef GL_ARB_texture_cube_map
+#define GL_NORMAL_MAP_ARB 0x8511
+#define GL_REFLECTION_MAP_ARB 0x8512
+#define GL_TEXTURE_CUBE_MAP_ARB 0x8513
+#define GL_TEXTURE_BINDING_CUBE_MAP_ARB 0x8514
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB 0x8515
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB 0x8516
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB 0x8517
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB 0x8518
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB 0x8519
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB 0x851A
+#define GL_PROXY_TEXTURE_CUBE_MAP_ARB 0x851B
+#define GL_MAX_CUBE_MAP_TEXTURE_SIZE_ARB 0x851C
+#endif
+
+#ifndef GL_ARB_texture_compression
+#define GL_COMPRESSED_ALPHA_ARB 0x84E9
+#define GL_COMPRESSED_LUMINANCE_ARB 0x84EA
+#define GL_COMPRESSED_LUMINANCE_ALPHA_ARB 0x84EB
+#define GL_COMPRESSED_INTENSITY_ARB 0x84EC
+#define GL_COMPRESSED_RGB_ARB 0x84ED
+#define GL_COMPRESSED_RGBA_ARB 0x84EE
+#define GL_TEXTURE_COMPRESSION_HINT_ARB 0x84EF
+#define GL_TEXTURE_COMPRESSED_IMAGE_SIZE_ARB 0x86A0
+#define GL_TEXTURE_COMPRESSED_ARB 0x86A1
+#define GL_NUM_COMPRESSED_TEXTURE_FORMATS_ARB 0x86A2
+#define GL_COMPRESSED_TEXTURE_FORMATS_ARB 0x86A3
+#endif
+
+#ifndef GL_ARB_texture_border_clamp
+#define GL_CLAMP_TO_BORDER_ARB 0x812D
+#endif
+
+#ifndef GL_ARB_point_parameters
+#define GL_POINT_SIZE_MIN_ARB 0x8126
+#define GL_POINT_SIZE_MAX_ARB 0x8127
+#define GL_POINT_FADE_THRESHOLD_SIZE_ARB 0x8128
+#define GL_POINT_DISTANCE_ATTENUATION_ARB 0x8129
+#endif
+
+#ifndef GL_ARB_vertex_blend
+#define GL_MAX_VERTEX_UNITS_ARB 0x86A4
+#define GL_ACTIVE_VERTEX_UNITS_ARB 0x86A5
+#define GL_WEIGHT_SUM_UNITY_ARB 0x86A6
+#define GL_VERTEX_BLEND_ARB 0x86A7
+#define GL_CURRENT_WEIGHT_ARB 0x86A8
+#define GL_WEIGHT_ARRAY_TYPE_ARB 0x86A9
+#define GL_WEIGHT_ARRAY_STRIDE_ARB 0x86AA
+#define GL_WEIGHT_ARRAY_SIZE_ARB 0x86AB
+#define GL_WEIGHT_ARRAY_POINTER_ARB 0x86AC
+#define GL_WEIGHT_ARRAY_ARB 0x86AD
+#define GL_MODELVIEW0_ARB 0x1700
+#define GL_MODELVIEW1_ARB 0x850A
+#define GL_MODELVIEW2_ARB 0x8722
+#define GL_MODELVIEW3_ARB 0x8723
+#define GL_MODELVIEW4_ARB 0x8724
+#define GL_MODELVIEW5_ARB 0x8725
+#define GL_MODELVIEW6_ARB 0x8726
+#define GL_MODELVIEW7_ARB 0x8727
+#define GL_MODELVIEW8_ARB 0x8728
+#define GL_MODELVIEW9_ARB 0x8729
+#define GL_MODELVIEW10_ARB 0x872A
+#define GL_MODELVIEW11_ARB 0x872B
+#define GL_MODELVIEW12_ARB 0x872C
+#define GL_MODELVIEW13_ARB 0x872D
+#define GL_MODELVIEW14_ARB 0x872E
+#define GL_MODELVIEW15_ARB 0x872F
+#define GL_MODELVIEW16_ARB 0x8730
+#define GL_MODELVIEW17_ARB 0x8731
+#define GL_MODELVIEW18_ARB 0x8732
+#define GL_MODELVIEW19_ARB 0x8733
+#define GL_MODELVIEW20_ARB 0x8734
+#define GL_MODELVIEW21_ARB 0x8735
+#define GL_MODELVIEW22_ARB 0x8736
+#define GL_MODELVIEW23_ARB 0x8737
+#define GL_MODELVIEW24_ARB 0x8738
+#define GL_MODELVIEW25_ARB 0x8739
+#define GL_MODELVIEW26_ARB 0x873A
+#define GL_MODELVIEW27_ARB 0x873B
+#define GL_MODELVIEW28_ARB 0x873C
+#define GL_MODELVIEW29_ARB 0x873D
+#define GL_MODELVIEW30_ARB 0x873E
+#define GL_MODELVIEW31_ARB 0x873F
+#endif
+
+#ifndef GL_ARB_matrix_palette
+#define GL_MATRIX_PALETTE_ARB 0x8840
+#define GL_MAX_MATRIX_PALETTE_STACK_DEPTH_ARB 0x8841
+#define GL_MAX_PALETTE_MATRICES_ARB 0x8842
+#define GL_CURRENT_PALETTE_MATRIX_ARB 0x8843
+#define GL_MATRIX_INDEX_ARRAY_ARB 0x8844
+#define GL_CURRENT_MATRIX_INDEX_ARB 0x8845
+#define GL_MATRIX_INDEX_ARRAY_SIZE_ARB 0x8846
+#define GL_MATRIX_INDEX_ARRAY_TYPE_ARB 0x8847
+#define GL_MATRIX_INDEX_ARRAY_STRIDE_ARB 0x8848
+#define GL_MATRIX_INDEX_ARRAY_POINTER_ARB 0x8849
+#endif
+
+#ifndef GL_ARB_texture_env_combine
+#define GL_COMBINE_ARB 0x8570
+#define GL_COMBINE_RGB_ARB 0x8571
+#define GL_COMBINE_ALPHA_ARB 0x8572
+#define GL_SOURCE0_RGB_ARB 0x8580
+#define GL_SOURCE1_RGB_ARB 0x8581
+#define GL_SOURCE2_RGB_ARB 0x8582
+#define GL_SOURCE0_ALPHA_ARB 0x8588
+#define GL_SOURCE1_ALPHA_ARB 0x8589
+#define GL_SOURCE2_ALPHA_ARB 0x858A
+#define GL_OPERAND0_RGB_ARB 0x8590
+#define GL_OPERAND1_RGB_ARB 0x8591
+#define GL_OPERAND2_RGB_ARB 0x8592
+#define GL_OPERAND0_ALPHA_ARB 0x8598
+#define GL_OPERAND1_ALPHA_ARB 0x8599
+#define GL_OPERAND2_ALPHA_ARB 0x859A
+#define GL_RGB_SCALE_ARB 0x8573
+#define GL_ADD_SIGNED_ARB 0x8574
+#define GL_INTERPOLATE_ARB 0x8575
+#define GL_SUBTRACT_ARB 0x84E7
+#define GL_CONSTANT_ARB 0x8576
+#define GL_PRIMARY_COLOR_ARB 0x8577
+#define GL_PREVIOUS_ARB 0x8578
+#endif
+
+#ifndef GL_ARB_texture_env_crossbar
+#endif
+
+#ifndef GL_ARB_texture_env_dot3
+#define GL_DOT3_RGB_ARB 0x86AE
+#define GL_DOT3_RGBA_ARB 0x86AF
+#endif
+
+#ifndef GL_ARB_texture_mirrored_repeat
+#define GL_MIRRORED_REPEAT_ARB 0x8370
+#endif
+
+#ifndef GL_ARB_depth_texture
+#define GL_DEPTH_COMPONENT16_ARB 0x81A5
+#define GL_DEPTH_COMPONENT24_ARB 0x81A6
+#define GL_DEPTH_COMPONENT32_ARB 0x81A7
+#define GL_TEXTURE_DEPTH_SIZE_ARB 0x884A
+#define GL_DEPTH_TEXTURE_MODE_ARB 0x884B
+#endif
+
+#ifndef GL_ARB_shadow
+#define GL_TEXTURE_COMPARE_MODE_ARB 0x884C
+#define GL_TEXTURE_COMPARE_FUNC_ARB 0x884D
+#define GL_COMPARE_R_TO_TEXTURE_ARB 0x884E
+#endif
+
+#ifndef GL_ARB_shadow_ambient
+#define GL_TEXTURE_COMPARE_FAIL_VALUE_ARB 0x80BF
+#endif
+
+#ifndef GL_ARB_window_pos
+#endif
+
+#ifndef GL_ARB_vertex_program
+#define GL_COLOR_SUM_ARB 0x8458
+#define GL_VERTEX_PROGRAM_ARB 0x8620
+#define GL_VERTEX_ATTRIB_ARRAY_ENABLED_ARB 0x8622
+#define GL_VERTEX_ATTRIB_ARRAY_SIZE_ARB 0x8623
+#define GL_VERTEX_ATTRIB_ARRAY_STRIDE_ARB 0x8624
+#define GL_VERTEX_ATTRIB_ARRAY_TYPE_ARB 0x8625
+#define GL_CURRENT_VERTEX_ATTRIB_ARB 0x8626
+#define GL_PROGRAM_LENGTH_ARB 0x8627
+#define GL_PROGRAM_STRING_ARB 0x8628
+#define GL_MAX_PROGRAM_MATRIX_STACK_DEPTH_ARB 0x862E
+#define GL_MAX_PROGRAM_MATRICES_ARB 0x862F
+#define GL_CURRENT_MATRIX_STACK_DEPTH_ARB 0x8640
+#define GL_CURRENT_MATRIX_ARB 0x8641
+#define GL_VERTEX_PROGRAM_POINT_SIZE_ARB 0x8642
+#define GL_VERTEX_PROGRAM_TWO_SIDE_ARB 0x8643
+#define GL_VERTEX_ATTRIB_ARRAY_POINTER_ARB 0x8645
+#define GL_PROGRAM_ERROR_POSITION_ARB 0x864B
+#define GL_PROGRAM_BINDING_ARB 0x8677
+#define GL_MAX_VERTEX_ATTRIBS_ARB 0x8869
+#define GL_VERTEX_ATTRIB_ARRAY_NORMALIZED_ARB 0x886A
+#define GL_PROGRAM_ERROR_STRING_ARB 0x8874
+#define GL_PROGRAM_FORMAT_ASCII_ARB 0x8875
+#define GL_PROGRAM_FORMAT_ARB 0x8876
+#define GL_PROGRAM_INSTRUCTIONS_ARB 0x88A0
+#define GL_MAX_PROGRAM_INSTRUCTIONS_ARB 0x88A1
+#define GL_PROGRAM_NATIVE_INSTRUCTIONS_ARB 0x88A2
+#define GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB 0x88A3
+#define GL_PROGRAM_TEMPORARIES_ARB 0x88A4
+#define GL_MAX_PROGRAM_TEMPORARIES_ARB 0x88A5
+#define GL_PROGRAM_NATIVE_TEMPORARIES_ARB 0x88A6
+#define GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB 0x88A7
+#define GL_PROGRAM_PARAMETERS_ARB 0x88A8
+#define GL_MAX_PROGRAM_PARAMETERS_ARB 0x88A9
+#define GL_PROGRAM_NATIVE_PARAMETERS_ARB 0x88AA
+#define GL_MAX_PROGRAM_NATIVE_PARAMETERS_ARB 0x88AB
+#define GL_PROGRAM_ATTRIBS_ARB 0x88AC
+#define GL_MAX_PROGRAM_ATTRIBS_ARB 0x88AD
+#define GL_PROGRAM_NATIVE_ATTRIBS_ARB 0x88AE
+#define GL_MAX_PROGRAM_NATIVE_ATTRIBS_ARB 0x88AF
+#define GL_PROGRAM_ADDRESS_REGISTERS_ARB 0x88B0
+#define GL_MAX_PROGRAM_ADDRESS_REGISTERS_ARB 0x88B1
+#define GL_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB 0x88B2
+#define GL_MAX_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB 0x88B3
+#define GL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB 0x88B4
+#define GL_MAX_PROGRAM_ENV_PARAMETERS_ARB 0x88B5
+#define GL_PROGRAM_UNDER_NATIVE_LIMITS_ARB 0x88B6
+#define GL_TRANSPOSE_CURRENT_MATRIX_ARB 0x88B7
+#define GL_MATRIX0_ARB 0x88C0
+#define GL_MATRIX1_ARB 0x88C1
+#define GL_MATRIX2_ARB 0x88C2
+#define GL_MATRIX3_ARB 0x88C3
+#define GL_MATRIX4_ARB 0x88C4
+#define GL_MATRIX5_ARB 0x88C5
+#define GL_MATRIX6_ARB 0x88C6
+#define GL_MATRIX7_ARB 0x88C7
+#define GL_MATRIX8_ARB 0x88C8
+#define GL_MATRIX9_ARB 0x88C9
+#define GL_MATRIX10_ARB 0x88CA
+#define GL_MATRIX11_ARB 0x88CB
+#define GL_MATRIX12_ARB 0x88CC
+#define GL_MATRIX13_ARB 0x88CD
+#define GL_MATRIX14_ARB 0x88CE
+#define GL_MATRIX15_ARB 0x88CF
+#define GL_MATRIX16_ARB 0x88D0
+#define GL_MATRIX17_ARB 0x88D1
+#define GL_MATRIX18_ARB 0x88D2
+#define GL_MATRIX19_ARB 0x88D3
+#define GL_MATRIX20_ARB 0x88D4
+#define GL_MATRIX21_ARB 0x88D5
+#define GL_MATRIX22_ARB 0x88D6
+#define GL_MATRIX23_ARB 0x88D7
+#define GL_MATRIX24_ARB 0x88D8
+#define GL_MATRIX25_ARB 0x88D9
+#define GL_MATRIX26_ARB 0x88DA
+#define GL_MATRIX27_ARB 0x88DB
+#define GL_MATRIX28_ARB 0x88DC
+#define GL_MATRIX29_ARB 0x88DD
+#define GL_MATRIX30_ARB 0x88DE
+#define GL_MATRIX31_ARB 0x88DF
+#endif
+
+#ifndef GL_ARB_fragment_program
+#define GL_FRAGMENT_PROGRAM_ARB 0x8804
+#define GL_PROGRAM_ALU_INSTRUCTIONS_ARB 0x8805
+#define GL_PROGRAM_TEX_INSTRUCTIONS_ARB 0x8806
+#define GL_PROGRAM_TEX_INDIRECTIONS_ARB 0x8807
+#define GL_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB 0x8808
+#define GL_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB 0x8809
+#define GL_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB 0x880A
+#define GL_MAX_PROGRAM_ALU_INSTRUCTIONS_ARB 0x880B
+#define GL_MAX_PROGRAM_TEX_INSTRUCTIONS_ARB 0x880C
+#define GL_MAX_PROGRAM_TEX_INDIRECTIONS_ARB 0x880D
+#define GL_MAX_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB 0x880E
+#define GL_MAX_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB 0x880F
+#define GL_MAX_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB 0x8810
+#define GL_MAX_TEXTURE_COORDS_ARB 0x8871
+#define GL_MAX_TEXTURE_IMAGE_UNITS_ARB 0x8872
+#endif
+
+#ifndef GL_ARB_vertex_buffer_object
+#define GL_BUFFER_SIZE_ARB 0x8764
+#define GL_BUFFER_USAGE_ARB 0x8765
+#define GL_ARRAY_BUFFER_ARB 0x8892
+#define GL_ELEMENT_ARRAY_BUFFER_ARB 0x8893
+#define GL_ARRAY_BUFFER_BINDING_ARB 0x8894
+#define GL_ELEMENT_ARRAY_BUFFER_BINDING_ARB 0x8895
+#define GL_VERTEX_ARRAY_BUFFER_BINDING_ARB 0x8896
+#define GL_NORMAL_ARRAY_BUFFER_BINDING_ARB 0x8897
+#define GL_COLOR_ARRAY_BUFFER_BINDING_ARB 0x8898
+#define GL_INDEX_ARRAY_BUFFER_BINDING_ARB 0x8899
+#define GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING_ARB 0x889A
+#define GL_EDGE_FLAG_ARRAY_BUFFER_BINDING_ARB 0x889B
+#define GL_SECONDARY_COLOR_ARRAY_BUFFER_BINDING_ARB 0x889C
+#define GL_FOG_COORDINATE_ARRAY_BUFFER_BINDING_ARB 0x889D
+#define GL_WEIGHT_ARRAY_BUFFER_BINDING_ARB 0x889E
+#define GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING_ARB 0x889F
+#define GL_READ_ONLY_ARB 0x88B8
+#define GL_WRITE_ONLY_ARB 0x88B9
+#define GL_READ_WRITE_ARB 0x88BA
+#define GL_BUFFER_ACCESS_ARB 0x88BB
+#define GL_BUFFER_MAPPED_ARB 0x88BC
+#define GL_BUFFER_MAP_POINTER_ARB 0x88BD
+#define GL_STREAM_DRAW_ARB 0x88E0
+#define GL_STREAM_READ_ARB 0x88E1
+#define GL_STREAM_COPY_ARB 0x88E2
+#define GL_STATIC_DRAW_ARB 0x88E4
+#define GL_STATIC_READ_ARB 0x88E5
+#define GL_STATIC_COPY_ARB 0x88E6
+#define GL_DYNAMIC_DRAW_ARB 0x88E8
+#define GL_DYNAMIC_READ_ARB 0x88E9
+#define GL_DYNAMIC_COPY_ARB 0x88EA
+#endif
+
+#ifndef GL_ARB_occlusion_query
+#define GL_QUERY_COUNTER_BITS_ARB 0x8864
+#define GL_CURRENT_QUERY_ARB 0x8865
+#define GL_QUERY_RESULT_ARB 0x8866
+#define GL_QUERY_RESULT_AVAILABLE_ARB 0x8867
+#define GL_SAMPLES_PASSED_ARB 0x8914
+#endif
+
+#ifndef GL_ARB_shader_objects
+#define GL_PROGRAM_OBJECT_ARB 0x8B40
+#define GL_SHADER_OBJECT_ARB 0x8B48
+#define GL_OBJECT_TYPE_ARB 0x8B4E
+#define GL_OBJECT_SUBTYPE_ARB 0x8B4F
+#define GL_FLOAT_VEC2_ARB 0x8B50
+#define GL_FLOAT_VEC3_ARB 0x8B51
+#define GL_FLOAT_VEC4_ARB 0x8B52
+#define GL_INT_VEC2_ARB 0x8B53
+#define GL_INT_VEC3_ARB 0x8B54
+#define GL_INT_VEC4_ARB 0x8B55
+#define GL_BOOL_ARB 0x8B56
+#define GL_BOOL_VEC2_ARB 0x8B57
+#define GL_BOOL_VEC3_ARB 0x8B58
+#define GL_BOOL_VEC4_ARB 0x8B59
+#define GL_FLOAT_MAT2_ARB 0x8B5A
+#define GL_FLOAT_MAT3_ARB 0x8B5B
+#define GL_FLOAT_MAT4_ARB 0x8B5C
+#define GL_SAMPLER_1D_ARB 0x8B5D
+#define GL_SAMPLER_2D_ARB 0x8B5E
+#define GL_SAMPLER_3D_ARB 0x8B5F
+#define GL_SAMPLER_CUBE_ARB 0x8B60
+#define GL_SAMPLER_1D_SHADOW_ARB 0x8B61
+#define GL_SAMPLER_2D_SHADOW_ARB 0x8B62
+#define GL_SAMPLER_2D_RECT_ARB 0x8B63
+#define GL_SAMPLER_2D_RECT_SHADOW_ARB 0x8B64
+#define GL_OBJECT_DELETE_STATUS_ARB 0x8B80
+#define GL_OBJECT_COMPILE_STATUS_ARB 0x8B81
+#define GL_OBJECT_LINK_STATUS_ARB 0x8B82
+#define GL_OBJECT_VALIDATE_STATUS_ARB 0x8B83
+#define GL_OBJECT_INFO_LOG_LENGTH_ARB 0x8B84
+#define GL_OBJECT_ATTACHED_OBJECTS_ARB 0x8B85
+#define GL_OBJECT_ACTIVE_UNIFORMS_ARB 0x8B86
+#define GL_OBJECT_ACTIVE_UNIFORM_MAX_LENGTH_ARB 0x8B87
+#define GL_OBJECT_SHADER_SOURCE_LENGTH_ARB 0x8B88
+#endif
+
+#ifndef GL_ARB_vertex_shader
+#define GL_VERTEX_SHADER_ARB 0x8B31
+#define GL_MAX_VERTEX_UNIFORM_COMPONENTS_ARB 0x8B4A
+#define GL_MAX_VARYING_FLOATS_ARB 0x8B4B
+#define GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS_ARB 0x8B4C
+#define GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS_ARB 0x8B4D
+#define GL_OBJECT_ACTIVE_ATTRIBUTES_ARB 0x8B89
+#define GL_OBJECT_ACTIVE_ATTRIBUTE_MAX_LENGTH_ARB 0x8B8A
+#endif
+
+#ifndef GL_ARB_fragment_shader
+#define GL_FRAGMENT_SHADER_ARB 0x8B30
+#define GL_MAX_FRAGMENT_UNIFORM_COMPONENTS_ARB 0x8B49
+#define GL_FRAGMENT_SHADER_DERIVATIVE_HINT_ARB 0x8B8B
+#endif
+
+#ifndef GL_ARB_shading_language_100
+#define GL_SHADING_LANGUAGE_VERSION_ARB 0x8B8C
+#endif
+
+#ifndef GL_ARB_texture_non_power_of_two
+#endif
+
+#ifndef GL_ARB_point_sprite
+#define GL_POINT_SPRITE_ARB 0x8861
+#define GL_COORD_REPLACE_ARB 0x8862
+#endif
+
+#ifndef GL_ARB_fragment_program_shadow
+#endif
+
+#ifndef GL_ARB_draw_buffers
+#define GL_MAX_DRAW_BUFFERS_ARB 0x8824
+#define GL_DRAW_BUFFER0_ARB 0x8825
+#define GL_DRAW_BUFFER1_ARB 0x8826
+#define GL_DRAW_BUFFER2_ARB 0x8827
+#define GL_DRAW_BUFFER3_ARB 0x8828
+#define GL_DRAW_BUFFER4_ARB 0x8829
+#define GL_DRAW_BUFFER5_ARB 0x882A
+#define GL_DRAW_BUFFER6_ARB 0x882B
+#define GL_DRAW_BUFFER7_ARB 0x882C
+#define GL_DRAW_BUFFER8_ARB 0x882D
+#define GL_DRAW_BUFFER9_ARB 0x882E
+#define GL_DRAW_BUFFER10_ARB 0x882F
+#define GL_DRAW_BUFFER11_ARB 0x8830
+#define GL_DRAW_BUFFER12_ARB 0x8831
+#define GL_DRAW_BUFFER13_ARB 0x8832
+#define GL_DRAW_BUFFER14_ARB 0x8833
+#define GL_DRAW_BUFFER15_ARB 0x8834
+#endif
+
+#ifndef GL_ARB_texture_rectangle
+#define GL_TEXTURE_RECTANGLE_ARB 0x84F5
+#define GL_TEXTURE_BINDING_RECTANGLE_ARB 0x84F6
+#define GL_PROXY_TEXTURE_RECTANGLE_ARB 0x84F7
+#define GL_MAX_RECTANGLE_TEXTURE_SIZE_ARB 0x84F8
+#endif
+
+#ifndef GL_ARB_color_buffer_float
+#define GL_RGBA_FLOAT_MODE_ARB 0x8820
+#define GL_CLAMP_VERTEX_COLOR_ARB 0x891A
+#define GL_CLAMP_FRAGMENT_COLOR_ARB 0x891B
+#define GL_CLAMP_READ_COLOR_ARB 0x891C
+#define GL_FIXED_ONLY_ARB 0x891D
+#endif
+
+#ifndef GL_ARB_half_float_pixel
+#define GL_HALF_FLOAT_ARB 0x140B
+#endif
+
+#ifndef GL_ARB_texture_float
+#define GL_TEXTURE_RED_TYPE_ARB 0x8C10
+#define GL_TEXTURE_GREEN_TYPE_ARB 0x8C11
+#define GL_TEXTURE_BLUE_TYPE_ARB 0x8C12
+#define GL_TEXTURE_ALPHA_TYPE_ARB 0x8C13
+#define GL_TEXTURE_LUMINANCE_TYPE_ARB 0x8C14
+#define GL_TEXTURE_INTENSITY_TYPE_ARB 0x8C15
+#define GL_TEXTURE_DEPTH_TYPE_ARB 0x8C16
+#define GL_UNSIGNED_NORMALIZED_ARB 0x8C17
+#define GL_RGBA32F_ARB 0x8814
+#define GL_RGB32F_ARB 0x8815
+#define GL_ALPHA32F_ARB 0x8816
+#define GL_INTENSITY32F_ARB 0x8817
+#define GL_LUMINANCE32F_ARB 0x8818
+#define GL_LUMINANCE_ALPHA32F_ARB 0x8819
+#define GL_RGBA16F_ARB 0x881A
+#define GL_RGB16F_ARB 0x881B
+#define GL_ALPHA16F_ARB 0x881C
+#define GL_INTENSITY16F_ARB 0x881D
+#define GL_LUMINANCE16F_ARB 0x881E
+#define GL_LUMINANCE_ALPHA16F_ARB 0x881F
+#endif
+
+#ifndef GL_ARB_pixel_buffer_object
+#define GL_PIXEL_PACK_BUFFER_ARB 0x88EB
+#define GL_PIXEL_UNPACK_BUFFER_ARB 0x88EC
+#define GL_PIXEL_PACK_BUFFER_BINDING_ARB 0x88ED
+#define GL_PIXEL_UNPACK_BUFFER_BINDING_ARB 0x88EF
+#endif
+
+#ifndef GL_ARB_depth_buffer_float
+#define GL_DEPTH_COMPONENT32F 0x8CAC
+#define GL_DEPTH32F_STENCIL8 0x8CAD
+#define GL_FLOAT_32_UNSIGNED_INT_24_8_REV 0x8DAD
+#endif
+
+#ifndef GL_ARB_draw_instanced
+#endif
+
+#ifndef GL_ARB_framebuffer_object
+#define GL_INVALID_FRAMEBUFFER_OPERATION 0x0506
+#define GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING 0x8210
+#define GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE 0x8211
+#define GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE 0x8212
+#define GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE 0x8213
+#define GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE 0x8214
+#define GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE 0x8215
+#define GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE 0x8216
+#define GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE 0x8217
+#define GL_FRAMEBUFFER_DEFAULT 0x8218
+#define GL_FRAMEBUFFER_UNDEFINED 0x8219
+#define GL_DEPTH_STENCIL_ATTACHMENT 0x821A
+#define GL_MAX_RENDERBUFFER_SIZE 0x84E8
+#define GL_DEPTH_STENCIL 0x84F9
+#define GL_UNSIGNED_INT_24_8 0x84FA
+#define GL_DEPTH24_STENCIL8 0x88F0
+#define GL_TEXTURE_STENCIL_SIZE 0x88F1
+#define GL_TEXTURE_RED_TYPE 0x8C10
+#define GL_TEXTURE_GREEN_TYPE 0x8C11
+#define GL_TEXTURE_BLUE_TYPE 0x8C12
+#define GL_TEXTURE_ALPHA_TYPE 0x8C13
+#define GL_TEXTURE_DEPTH_TYPE 0x8C16
+#define GL_UNSIGNED_NORMALIZED 0x8C17
+#define GL_FRAMEBUFFER_BINDING 0x8CA6
+#define GL_DRAW_FRAMEBUFFER_BINDING GL_FRAMEBUFFER_BINDING
+#define GL_RENDERBUFFER_BINDING 0x8CA7
+#define GL_READ_FRAMEBUFFER 0x8CA8
+#define GL_DRAW_FRAMEBUFFER 0x8CA9
+#define GL_READ_FRAMEBUFFER_BINDING 0x8CAA
+#define GL_RENDERBUFFER_SAMPLES 0x8CAB
+#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE 0x8CD0
+#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME 0x8CD1
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL 0x8CD2
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE 0x8CD3
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER 0x8CD4
+#define GL_FRAMEBUFFER_COMPLETE 0x8CD5
+#define GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT 0x8CD6
+#define GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT 0x8CD7
+#define GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER 0x8CDB
+#define GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER 0x8CDC
+#define GL_FRAMEBUFFER_UNSUPPORTED 0x8CDD
+#define GL_MAX_COLOR_ATTACHMENTS 0x8CDF
+#define GL_COLOR_ATTACHMENT0 0x8CE0
+#define GL_COLOR_ATTACHMENT1 0x8CE1
+#define GL_COLOR_ATTACHMENT2 0x8CE2
+#define GL_COLOR_ATTACHMENT3 0x8CE3
+#define GL_COLOR_ATTACHMENT4 0x8CE4
+#define GL_COLOR_ATTACHMENT5 0x8CE5
+#define GL_COLOR_ATTACHMENT6 0x8CE6
+#define GL_COLOR_ATTACHMENT7 0x8CE7
+#define GL_COLOR_ATTACHMENT8 0x8CE8
+#define GL_COLOR_ATTACHMENT9 0x8CE9
+#define GL_COLOR_ATTACHMENT10 0x8CEA
+#define GL_COLOR_ATTACHMENT11 0x8CEB
+#define GL_COLOR_ATTACHMENT12 0x8CEC
+#define GL_COLOR_ATTACHMENT13 0x8CED
+#define GL_COLOR_ATTACHMENT14 0x8CEE
+#define GL_COLOR_ATTACHMENT15 0x8CEF
+#define GL_DEPTH_ATTACHMENT 0x8D00
+#define GL_STENCIL_ATTACHMENT 0x8D20
+#define GL_FRAMEBUFFER 0x8D40
+#define GL_RENDERBUFFER 0x8D41
+#define GL_RENDERBUFFER_WIDTH 0x8D42
+#define GL_RENDERBUFFER_HEIGHT 0x8D43
+#define GL_RENDERBUFFER_INTERNAL_FORMAT 0x8D44
+#define GL_STENCIL_INDEX1 0x8D46
+#define GL_STENCIL_INDEX4 0x8D47
+#define GL_STENCIL_INDEX8 0x8D48
+#define GL_STENCIL_INDEX16 0x8D49
+#define GL_RENDERBUFFER_RED_SIZE 0x8D50
+#define GL_RENDERBUFFER_GREEN_SIZE 0x8D51
+#define GL_RENDERBUFFER_BLUE_SIZE 0x8D52
+#define GL_RENDERBUFFER_ALPHA_SIZE 0x8D53
+#define GL_RENDERBUFFER_DEPTH_SIZE 0x8D54
+#define GL_RENDERBUFFER_STENCIL_SIZE 0x8D55
+#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE 0x8D56
+#define GL_MAX_SAMPLES 0x8D57
+#endif
+
+#ifndef GL_ARB_framebuffer_object_DEPRECATED
+#define GL_INDEX 0x8222
+#define GL_TEXTURE_LUMINANCE_TYPE 0x8C14
+#define GL_TEXTURE_INTENSITY_TYPE 0x8C15
+#endif
+
+#ifndef GL_ARB_framebuffer_sRGB
+#define GL_FRAMEBUFFER_SRGB 0x8DB9
+#endif
+
+#ifndef GL_ARB_geometry_shader4
+#define GL_LINES_ADJACENCY_ARB 0x000A
+#define GL_LINE_STRIP_ADJACENCY_ARB 0x000B
+#define GL_TRIANGLES_ADJACENCY_ARB 0x000C
+#define GL_TRIANGLE_STRIP_ADJACENCY_ARB 0x000D
+#define GL_PROGRAM_POINT_SIZE_ARB 0x8642
+#define GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS_ARB 0x8C29
+#define GL_FRAMEBUFFER_ATTACHMENT_LAYERED_ARB 0x8DA7
+#define GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_ARB 0x8DA8
+#define GL_FRAMEBUFFER_INCOMPLETE_LAYER_COUNT_ARB 0x8DA9
+#define GL_GEOMETRY_SHADER_ARB 0x8DD9
+#define GL_GEOMETRY_VERTICES_OUT_ARB 0x8DDA
+#define GL_GEOMETRY_INPUT_TYPE_ARB 0x8DDB
+#define GL_GEOMETRY_OUTPUT_TYPE_ARB 0x8DDC
+#define GL_MAX_GEOMETRY_VARYING_COMPONENTS_ARB 0x8DDD
+#define GL_MAX_VERTEX_VARYING_COMPONENTS_ARB 0x8DDE
+#define GL_MAX_GEOMETRY_UNIFORM_COMPONENTS_ARB 0x8DDF
+#define GL_MAX_GEOMETRY_OUTPUT_VERTICES_ARB 0x8DE0
+#define GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS_ARB 0x8DE1
+
+#endif
+
+#ifndef GL_ARB_half_float_vertex
+#define GL_HALF_FLOAT 0x140B
+#endif
+
+#ifndef GL_ARB_instanced_arrays
+#define GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ARB 0x88FE
+#endif
+
+#ifndef GL_ARB_map_buffer_range
+#define GL_MAP_READ_BIT 0x0001
+#define GL_MAP_WRITE_BIT 0x0002
+#define GL_MAP_INVALIDATE_RANGE_BIT 0x0004
+#define GL_MAP_INVALIDATE_BUFFER_BIT 0x0008
+#define GL_MAP_FLUSH_EXPLICIT_BIT 0x0010
+#define GL_MAP_UNSYNCHRONIZED_BIT 0x0020
+#endif
+
+#ifndef GL_ARB_texture_buffer_object
+#define GL_TEXTURE_BUFFER_ARB 0x8C2A
+#define GL_MAX_TEXTURE_BUFFER_SIZE_ARB 0x8C2B
+#define GL_TEXTURE_BINDING_BUFFER_ARB 0x8C2C
+#define GL_TEXTURE_BUFFER_DATA_STORE_BINDING_ARB 0x8C2D
+#define GL_TEXTURE_BUFFER_FORMAT_ARB 0x8C2E
+#endif
+
+#ifndef GL_ARB_texture_compression_rgtc
+#define GL_COMPRESSED_RED_RGTC1 0x8DBB
+#define GL_COMPRESSED_SIGNED_RED_RGTC1 0x8DBC
+#define GL_COMPRESSED_RG_RGTC2 0x8DBD
+#define GL_COMPRESSED_SIGNED_RG_RGTC2 0x8DBE
+#endif
+
+#ifndef GL_ARB_texture_rg
+#define GL_RG 0x8227
+#define GL_RG_INTEGER 0x8228
+#define GL_R8 0x8229
+#define GL_R16 0x822A
+#define GL_RG8 0x822B
+#define GL_RG16 0x822C
+#define GL_R16F 0x822D
+#define GL_R32F 0x822E
+#define GL_RG16F 0x822F
+#define GL_RG32F 0x8230
+#define GL_R8I 0x8231
+#define GL_R8UI 0x8232
+#define GL_R16I 0x8233
+#define GL_R16UI 0x8234
+#define GL_R32I 0x8235
+#define GL_R32UI 0x8236
+#define GL_RG8I 0x8237
+#define GL_RG8UI 0x8238
+#define GL_RG16I 0x8239
+#define GL_RG16UI 0x823A
+#define GL_RG32I 0x823B
+#define GL_RG32UI 0x823C
+#endif
+
+#ifndef GL_ARB_vertex_array_object
+#define GL_VERTEX_ARRAY_BINDING 0x85B5
+#endif
+
+#ifndef GL_ARB_uniform_buffer_object
+#define GL_UNIFORM_BUFFER 0x8A11
+#define GL_UNIFORM_BUFFER_BINDING 0x8A28
+#define GL_UNIFORM_BUFFER_START 0x8A29
+#define GL_UNIFORM_BUFFER_SIZE 0x8A2A
+#define GL_MAX_VERTEX_UNIFORM_BLOCKS 0x8A2B
+#define GL_MAX_GEOMETRY_UNIFORM_BLOCKS 0x8A2C
+#define GL_MAX_FRAGMENT_UNIFORM_BLOCKS 0x8A2D
+#define GL_MAX_COMBINED_UNIFORM_BLOCKS 0x8A2E
+#define GL_MAX_UNIFORM_BUFFER_BINDINGS 0x8A2F
+#define GL_MAX_UNIFORM_BLOCK_SIZE 0x8A30
+#define GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS 0x8A31
+#define GL_MAX_COMBINED_GEOMETRY_UNIFORM_COMPONENTS 0x8A32
+#define GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS 0x8A33
+#define GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT 0x8A34
+#define GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH 0x8A35
+#define GL_ACTIVE_UNIFORM_BLOCKS 0x8A36
+#define GL_UNIFORM_TYPE 0x8A37
+#define GL_UNIFORM_SIZE 0x8A38
+#define GL_UNIFORM_NAME_LENGTH 0x8A39
+#define GL_UNIFORM_BLOCK_INDEX 0x8A3A
+#define GL_UNIFORM_OFFSET 0x8A3B
+#define GL_UNIFORM_ARRAY_STRIDE 0x8A3C
+#define GL_UNIFORM_MATRIX_STRIDE 0x8A3D
+#define GL_UNIFORM_IS_ROW_MAJOR 0x8A3E
+#define GL_UNIFORM_BLOCK_BINDING 0x8A3F
+#define GL_UNIFORM_BLOCK_DATA_SIZE 0x8A40
+#define GL_UNIFORM_BLOCK_NAME_LENGTH 0x8A41
+#define GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS 0x8A42
+#define GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES 0x8A43
+#define GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER 0x8A44
+#define GL_UNIFORM_BLOCK_REFERENCED_BY_GEOMETRY_SHADER 0x8A45
+#define GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER 0x8A46
+#define GL_INVALID_INDEX 0xFFFFFFFFu
+#endif
+
+#ifndef GL_ARB_compatibility
+
+#endif
+
+#ifndef GL_ARB_copy_buffer
+#define GL_COPY_READ_BUFFER 0x8F36
+#define GL_COPY_WRITE_BUFFER 0x8F37
+#endif
+
+#ifndef GL_ARB_shader_texture_lod
+#endif
+
+#ifndef GL_ARB_depth_clamp
+#define GL_DEPTH_CLAMP 0x864F
+#endif
+
+#ifndef GL_ARB_draw_elements_base_vertex
+#endif
+
+#ifndef GL_ARB_fragment_coord_conventions
+#endif
+
+#ifndef GL_ARB_provoking_vertex
+#define GL_QUADS_FOLLOW_PROVOKING_VERTEX_CONVENTION 0x8E4C
+#define GL_FIRST_VERTEX_CONVENTION 0x8E4D
+#define GL_LAST_VERTEX_CONVENTION 0x8E4E
+#define GL_PROVOKING_VERTEX 0x8E4F
+#endif
+
+#ifndef GL_ARB_seamless_cube_map
+#define GL_TEXTURE_CUBE_MAP_SEAMLESS 0x884F
+#endif
+
+#ifndef GL_ARB_sync
+#define GL_MAX_SERVER_WAIT_TIMEOUT 0x9111
+#define GL_OBJECT_TYPE 0x9112
+#define GL_SYNC_CONDITION 0x9113
+#define GL_SYNC_STATUS 0x9114
+#define GL_SYNC_FLAGS 0x9115
+#define GL_SYNC_FENCE 0x9116
+#define GL_SYNC_GPU_COMMANDS_COMPLETE 0x9117
+#define GL_UNSIGNALED 0x9118
+#define GL_SIGNALED 0x9119
+#define GL_ALREADY_SIGNALED 0x911A
+#define GL_TIMEOUT_EXPIRED 0x911B
+#define GL_CONDITION_SATISFIED 0x911C
+#define GL_WAIT_FAILED 0x911D
+#define GL_SYNC_FLUSH_COMMANDS_BIT 0x00000001
+#define GL_TIMEOUT_IGNORED 0xFFFFFFFFFFFFFFFFull
+#endif
+
+#ifndef GL_ARB_texture_multisample
+#define GL_SAMPLE_POSITION 0x8E50
+#define GL_SAMPLE_MASK 0x8E51
+#define GL_SAMPLE_MASK_VALUE 0x8E52
+#define GL_MAX_SAMPLE_MASK_WORDS 0x8E59
+#define GL_TEXTURE_2D_MULTISAMPLE 0x9100
+#define GL_PROXY_TEXTURE_2D_MULTISAMPLE 0x9101
+#define GL_TEXTURE_2D_MULTISAMPLE_ARRAY 0x9102
+#define GL_PROXY_TEXTURE_2D_MULTISAMPLE_ARRAY 0x9103
+#define GL_TEXTURE_BINDING_2D_MULTISAMPLE 0x9104
+#define GL_TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY 0x9105
+#define GL_TEXTURE_SAMPLES 0x9106
+#define GL_TEXTURE_FIXED_SAMPLE_LOCATIONS 0x9107
+#define GL_SAMPLER_2D_MULTISAMPLE 0x9108
+#define GL_INT_SAMPLER_2D_MULTISAMPLE 0x9109
+#define GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE 0x910A
+#define GL_SAMPLER_2D_MULTISAMPLE_ARRAY 0x910B
+#define GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY 0x910C
+#define GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY 0x910D
+#define GL_MAX_COLOR_TEXTURE_SAMPLES 0x910E
+#define GL_MAX_DEPTH_TEXTURE_SAMPLES 0x910F
+#define GL_MAX_INTEGER_SAMPLES 0x9110
+#endif
+
+#ifndef GL_ARB_vertex_array_bgra
+
+#endif
+
+#ifndef GL_ARB_draw_buffers_blend
+#endif
+
+#ifndef GL_ARB_sample_shading
+#define GL_SAMPLE_SHADING_ARB 0x8C36
+#define GL_MIN_SAMPLE_SHADING_VALUE_ARB 0x8C37
+#endif
+
+#ifndef GL_ARB_texture_cube_map_array
+#define GL_TEXTURE_CUBE_MAP_ARRAY_ARB 0x9009
+#define GL_TEXTURE_BINDING_CUBE_MAP_ARRAY_ARB 0x900A
+#define GL_PROXY_TEXTURE_CUBE_MAP_ARRAY_ARB 0x900B
+#define GL_SAMPLER_CUBE_MAP_ARRAY_ARB 0x900C
+#define GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW_ARB 0x900D
+#define GL_INT_SAMPLER_CUBE_MAP_ARRAY_ARB 0x900E
+#define GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY_ARB 0x900F
+#endif
+
+#ifndef GL_ARB_texture_gather
+#define GL_MIN_PROGRAM_TEXTURE_GATHER_OFFSET_ARB 0x8E5E
+#define GL_MAX_PROGRAM_TEXTURE_GATHER_OFFSET_ARB 0x8E5F
+#endif
+
+#ifndef GL_ARB_texture_query_lod
+#endif
+
+#ifndef GL_ARB_shading_language_include
+#define GL_SHADER_INCLUDE_ARB 0x8DAE
+#define GL_NAMED_STRING_LENGTH_ARB 0x8DE9
+#define GL_NAMED_STRING_TYPE_ARB 0x8DEA
+#endif
+
+#ifndef GL_ARB_texture_compression_bptc
+#define GL_COMPRESSED_RGBA_BPTC_UNORM_ARB 0x8E8C
+#define GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_ARB 0x8E8D
+#define GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_ARB 0x8E8E
+#define GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_ARB 0x8E8F
+#endif
+
+#ifndef GL_ARB_blend_func_extended
+#define GL_SRC1_COLOR 0x88F9
+
+#define GL_ONE_MINUS_SRC1_COLOR 0x88FA
+#define GL_ONE_MINUS_SRC1_ALPHA 0x88FB
+#define GL_MAX_DUAL_SOURCE_DRAW_BUFFERS 0x88FC
+#endif
+
+#ifndef GL_ARB_explicit_attrib_location
+#endif
+
+#ifndef GL_ARB_occlusion_query2
+#define GL_ANY_SAMPLES_PASSED 0x8C2F
+#endif
+
+#ifndef GL_ARB_sampler_objects
+#define GL_SAMPLER_BINDING 0x8919
+#endif
+
+#ifndef GL_ARB_shader_bit_encoding
+#endif
+
+#ifndef GL_ARB_texture_rgb10_a2ui
+#define GL_RGB10_A2UI 0x906F
+#endif
+
+#ifndef GL_ARB_texture_swizzle
+#define GL_TEXTURE_SWIZZLE_R 0x8E42
+#define GL_TEXTURE_SWIZZLE_G 0x8E43
+#define GL_TEXTURE_SWIZZLE_B 0x8E44
+#define GL_TEXTURE_SWIZZLE_A 0x8E45
+#define GL_TEXTURE_SWIZZLE_RGBA 0x8E46
+#endif
+
+#ifndef GL_ARB_timer_query
+#define GL_TIME_ELAPSED 0x88BF
+#define GL_TIMESTAMP 0x8E28
+#endif
+
+#ifndef GL_ARB_vertex_type_2_10_10_10_rev
+
+#define GL_INT_2_10_10_10_REV 0x8D9F
+#endif
+
+#ifndef GL_ARB_draw_indirect
+#define GL_DRAW_INDIRECT_BUFFER 0x8F3F
+#define GL_DRAW_INDIRECT_BUFFER_BINDING 0x8F43
+#endif
+
+#ifndef GL_ARB_gpu_shader5
+#define GL_GEOMETRY_SHADER_INVOCATIONS 0x887F
+#define GL_MAX_GEOMETRY_SHADER_INVOCATIONS 0x8E5A
+#define GL_MIN_FRAGMENT_INTERPOLATION_OFFSET 0x8E5B
+#define GL_MAX_FRAGMENT_INTERPOLATION_OFFSET 0x8E5C
+#define GL_FRAGMENT_INTERPOLATION_OFFSET_BITS 0x8E5D
+
+#endif
+
+#ifndef GL_ARB_gpu_shader_fp64
+
+#define GL_DOUBLE_VEC2 0x8FFC
+#define GL_DOUBLE_VEC3 0x8FFD
+#define GL_DOUBLE_VEC4 0x8FFE
+#define GL_DOUBLE_MAT2 0x8F46
+#define GL_DOUBLE_MAT3 0x8F47
+#define GL_DOUBLE_MAT4 0x8F48
+#define GL_DOUBLE_MAT2x3 0x8F49
+#define GL_DOUBLE_MAT2x4 0x8F4A
+#define GL_DOUBLE_MAT3x2 0x8F4B
+#define GL_DOUBLE_MAT3x4 0x8F4C
+#define GL_DOUBLE_MAT4x2 0x8F4D
+#define GL_DOUBLE_MAT4x3 0x8F4E
+#endif
+
+#ifndef GL_ARB_shader_subroutine
+#define GL_ACTIVE_SUBROUTINES 0x8DE5
+#define GL_ACTIVE_SUBROUTINE_UNIFORMS 0x8DE6
+#define GL_ACTIVE_SUBROUTINE_UNIFORM_LOCATIONS 0x8E47
+#define GL_ACTIVE_SUBROUTINE_MAX_LENGTH 0x8E48
+#define GL_ACTIVE_SUBROUTINE_UNIFORM_MAX_LENGTH 0x8E49
+#define GL_MAX_SUBROUTINES 0x8DE7
+#define GL_MAX_SUBROUTINE_UNIFORM_LOCATIONS 0x8DE8
+#define GL_NUM_COMPATIBLE_SUBROUTINES 0x8E4A
+#define GL_COMPATIBLE_SUBROUTINES 0x8E4B
+
+#endif
+
+#ifndef GL_ARB_tessellation_shader
+#define GL_PATCHES 0x000E
+#define GL_PATCH_VERTICES 0x8E72
+#define GL_PATCH_DEFAULT_INNER_LEVEL 0x8E73
+#define GL_PATCH_DEFAULT_OUTER_LEVEL 0x8E74
+#define GL_TESS_CONTROL_OUTPUT_VERTICES 0x8E75
+#define GL_TESS_GEN_MODE 0x8E76
+#define GL_TESS_GEN_SPACING 0x8E77
+#define GL_TESS_GEN_VERTEX_ORDER 0x8E78
+#define GL_TESS_GEN_POINT_MODE 0x8E79
+
+#define GL_ISOLINES 0x8E7A
+
+#define GL_FRACTIONAL_ODD 0x8E7B
+#define GL_FRACTIONAL_EVEN 0x8E7C
+
+#define GL_MAX_PATCH_VERTICES 0x8E7D
+#define GL_MAX_TESS_GEN_LEVEL 0x8E7E
+#define GL_MAX_TESS_CONTROL_UNIFORM_COMPONENTS 0x8E7F
+#define GL_MAX_TESS_EVALUATION_UNIFORM_COMPONENTS 0x8E80
+#define GL_MAX_TESS_CONTROL_TEXTURE_IMAGE_UNITS 0x8E81
+#define GL_MAX_TESS_EVALUATION_TEXTURE_IMAGE_UNITS 0x8E82
+#define GL_MAX_TESS_CONTROL_OUTPUT_COMPONENTS 0x8E83
+#define GL_MAX_TESS_PATCH_COMPONENTS 0x8E84
+#define GL_MAX_TESS_CONTROL_TOTAL_OUTPUT_COMPONENTS 0x8E85
+#define GL_MAX_TESS_EVALUATION_OUTPUT_COMPONENTS 0x8E86
+#define GL_MAX_TESS_CONTROL_UNIFORM_BLOCKS 0x8E89
+#define GL_MAX_TESS_EVALUATION_UNIFORM_BLOCKS 0x8E8A
+#define GL_MAX_TESS_CONTROL_INPUT_COMPONENTS 0x886C
+#define GL_MAX_TESS_EVALUATION_INPUT_COMPONENTS 0x886D
+#define GL_MAX_COMBINED_TESS_CONTROL_UNIFORM_COMPONENTS 0x8E1E
+#define GL_MAX_COMBINED_TESS_EVALUATION_UNIFORM_COMPONENTS 0x8E1F
+#define GL_UNIFORM_BLOCK_REFERENCED_BY_TESS_CONTROL_SHADER 0x84F0
+#define GL_UNIFORM_BLOCK_REFERENCED_BY_TESS_EVALUATION_SHADER 0x84F1
+#define GL_TESS_EVALUATION_SHADER 0x8E87
+#define GL_TESS_CONTROL_SHADER 0x8E88
+#endif
+
+#ifndef GL_ARB_texture_buffer_object_rgb32
+
+#endif
+
+#ifndef GL_ARB_transform_feedback2
+#define GL_TRANSFORM_FEEDBACK 0x8E22
+#define GL_TRANSFORM_FEEDBACK_BUFFER_PAUSED 0x8E23
+#define GL_TRANSFORM_FEEDBACK_BUFFER_ACTIVE 0x8E24
+#define GL_TRANSFORM_FEEDBACK_BINDING 0x8E25
+#endif
+
+#ifndef GL_ARB_transform_feedback3
+#define GL_MAX_TRANSFORM_FEEDBACK_BUFFERS 0x8E70
+#define GL_MAX_VERTEX_STREAMS 0x8E71
+#endif
+
+#ifndef GL_ARB_ES2_compatibility
+#define GL_FIXED 0x140C
+#define GL_IMPLEMENTATION_COLOR_READ_TYPE 0x8B9A
+#define GL_IMPLEMENTATION_COLOR_READ_FORMAT 0x8B9B
+#define GL_LOW_FLOAT 0x8DF0
+#define GL_MEDIUM_FLOAT 0x8DF1
+#define GL_HIGH_FLOAT 0x8DF2
+#define GL_LOW_INT 0x8DF3
+#define GL_MEDIUM_INT 0x8DF4
+#define GL_HIGH_INT 0x8DF5
+#define GL_SHADER_COMPILER 0x8DFA
+#define GL_NUM_SHADER_BINARY_FORMATS 0x8DF9
+#define GL_MAX_VERTEX_UNIFORM_VECTORS 0x8DFB
+#define GL_MAX_VARYING_VECTORS 0x8DFC
+#define GL_MAX_FRAGMENT_UNIFORM_VECTORS 0x8DFD
+#endif
+
+#ifndef GL_ARB_get_program_binary
+#define GL_PROGRAM_BINARY_RETRIEVABLE_HINT 0x8257
+#define GL_PROGRAM_BINARY_LENGTH 0x8741
+#define GL_NUM_PROGRAM_BINARY_FORMATS 0x87FE
+#define GL_PROGRAM_BINARY_FORMATS 0x87FF
+#endif
+
+#ifndef GL_ARB_separate_shader_objects
+#define GL_VERTEX_SHADER_BIT 0x00000001
+#define GL_FRAGMENT_SHADER_BIT 0x00000002
+#define GL_GEOMETRY_SHADER_BIT 0x00000004
+#define GL_TESS_CONTROL_SHADER_BIT 0x00000008
+#define GL_TESS_EVALUATION_SHADER_BIT 0x00000010
+#define GL_ALL_SHADER_BITS 0xFFFFFFFF
+#define GL_PROGRAM_SEPARABLE 0x8258
+#define GL_ACTIVE_PROGRAM 0x8259
+#define GL_PROGRAM_PIPELINE_BINDING 0x825A
+#endif
+
+#ifndef GL_ARB_shader_precision
+#endif
+
+#ifndef GL_ARB_vertex_attrib_64bit
+
+#endif
+
+#ifndef GL_ARB_viewport_array
+
+#define GL_MAX_VIEWPORTS 0x825B
+#define GL_VIEWPORT_SUBPIXEL_BITS 0x825C
+#define GL_VIEWPORT_BOUNDS_RANGE 0x825D
+#define GL_LAYER_PROVOKING_VERTEX 0x825E
+#define GL_VIEWPORT_INDEX_PROVOKING_VERTEX 0x825F
+#define GL_UNDEFINED_VERTEX 0x8260
+
+#endif
+
+#ifndef GL_ARB_cl_event
+#define GL_SYNC_CL_EVENT_ARB 0x8240
+#define GL_SYNC_CL_EVENT_COMPLETE_ARB 0x8241
+#endif
+
+#ifndef GL_ARB_debug_output
+#define GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB 0x8242
+#define GL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH_ARB 0x8243
+#define GL_DEBUG_CALLBACK_FUNCTION_ARB 0x8244
+#define GL_DEBUG_CALLBACK_USER_PARAM_ARB 0x8245
+#define GL_DEBUG_SOURCE_API_ARB 0x8246
+#define GL_DEBUG_SOURCE_WINDOW_SYSTEM_ARB 0x8247
+#define GL_DEBUG_SOURCE_SHADER_COMPILER_ARB 0x8248
+#define GL_DEBUG_SOURCE_THIRD_PARTY_ARB 0x8249
+#define GL_DEBUG_SOURCE_APPLICATION_ARB 0x824A
+#define GL_DEBUG_SOURCE_OTHER_ARB 0x824B
+#define GL_DEBUG_TYPE_ERROR_ARB 0x824C
+#define GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_ARB 0x824D
+#define GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_ARB 0x824E
+#define GL_DEBUG_TYPE_PORTABILITY_ARB 0x824F
+#define GL_DEBUG_TYPE_PERFORMANCE_ARB 0x8250
+#define GL_DEBUG_TYPE_OTHER_ARB 0x8251
+#define GL_MAX_DEBUG_MESSAGE_LENGTH_ARB 0x9143
+#define GL_MAX_DEBUG_LOGGED_MESSAGES_ARB 0x9144
+#define GL_DEBUG_LOGGED_MESSAGES_ARB 0x9145
+#define GL_DEBUG_SEVERITY_HIGH_ARB 0x9146
+#define GL_DEBUG_SEVERITY_MEDIUM_ARB 0x9147
+#define GL_DEBUG_SEVERITY_LOW_ARB 0x9148
+#endif
+
+#ifndef GL_ARB_robustness
+
+#define GL_CONTEXT_FLAG_ROBUST_ACCESS_BIT_ARB 0x00000004
+#define GL_LOSE_CONTEXT_ON_RESET_ARB 0x8252
+#define GL_GUILTY_CONTEXT_RESET_ARB 0x8253
+#define GL_INNOCENT_CONTEXT_RESET_ARB 0x8254
+#define GL_UNKNOWN_CONTEXT_RESET_ARB 0x8255
+#define GL_RESET_NOTIFICATION_STRATEGY_ARB 0x8256
+#define GL_NO_RESET_NOTIFICATION_ARB 0x8261
+#endif
+
+#ifndef GL_ARB_shader_stencil_export
+#endif
+
+#ifndef GL_EXT_abgr
+#define GL_ABGR_EXT 0x8000
+#endif
+
+#ifndef GL_EXT_blend_color
+#define GL_CONSTANT_COLOR_EXT 0x8001
+#define GL_ONE_MINUS_CONSTANT_COLOR_EXT 0x8002
+#define GL_CONSTANT_ALPHA_EXT 0x8003
+#define GL_ONE_MINUS_CONSTANT_ALPHA_EXT 0x8004
+#define GL_BLEND_COLOR_EXT 0x8005
+#endif
+
+#ifndef GL_EXT_polygon_offset
+#define GL_POLYGON_OFFSET_EXT 0x8037
+#define GL_POLYGON_OFFSET_FACTOR_EXT 0x8038
+#define GL_POLYGON_OFFSET_BIAS_EXT 0x8039
+#endif
+
+#ifndef GL_EXT_texture
+#define GL_ALPHA4_EXT 0x803B
+#define GL_ALPHA8_EXT 0x803C
+#define GL_ALPHA12_EXT 0x803D
+#define GL_ALPHA16_EXT 0x803E
+#define GL_LUMINANCE4_EXT 0x803F
+#define GL_LUMINANCE8_EXT 0x8040
+#define GL_LUMINANCE12_EXT 0x8041
+#define GL_LUMINANCE16_EXT 0x8042
+#define GL_LUMINANCE4_ALPHA4_EXT 0x8043
+#define GL_LUMINANCE6_ALPHA2_EXT 0x8044
+#define GL_LUMINANCE8_ALPHA8_EXT 0x8045
+#define GL_LUMINANCE12_ALPHA4_EXT 0x8046
+#define GL_LUMINANCE12_ALPHA12_EXT 0x8047
+#define GL_LUMINANCE16_ALPHA16_EXT 0x8048
+#define GL_INTENSITY_EXT 0x8049
+#define GL_INTENSITY4_EXT 0x804A
+#define GL_INTENSITY8_EXT 0x804B
+#define GL_INTENSITY12_EXT 0x804C
+#define GL_INTENSITY16_EXT 0x804D
+#define GL_RGB2_EXT 0x804E
+#define GL_RGB4_EXT 0x804F
+#define GL_RGB5_EXT 0x8050
+#define GL_RGB8_EXT 0x8051
+#define GL_RGB10_EXT 0x8052
+#define GL_RGB12_EXT 0x8053
+#define GL_RGB16_EXT 0x8054
+#define GL_RGBA2_EXT 0x8055
+#define GL_RGBA4_EXT 0x8056
+#define GL_RGB5_A1_EXT 0x8057
+#define GL_RGBA8_EXT 0x8058
+#define GL_RGB10_A2_EXT 0x8059
+#define GL_RGBA12_EXT 0x805A
+#define GL_RGBA16_EXT 0x805B
+#define GL_TEXTURE_RED_SIZE_EXT 0x805C
+#define GL_TEXTURE_GREEN_SIZE_EXT 0x805D
+#define GL_TEXTURE_BLUE_SIZE_EXT 0x805E
+#define GL_TEXTURE_ALPHA_SIZE_EXT 0x805F
+#define GL_TEXTURE_LUMINANCE_SIZE_EXT 0x8060
+#define GL_TEXTURE_INTENSITY_SIZE_EXT 0x8061
+#define GL_REPLACE_EXT 0x8062
+#define GL_PROXY_TEXTURE_1D_EXT 0x8063
+#define GL_PROXY_TEXTURE_2D_EXT 0x8064
+#define GL_TEXTURE_TOO_LARGE_EXT 0x8065
+#endif
+
+#ifndef GL_EXT_texture3D
+#define GL_PACK_SKIP_IMAGES_EXT 0x806B
+#define GL_PACK_IMAGE_HEIGHT_EXT 0x806C
+#define GL_UNPACK_SKIP_IMAGES_EXT 0x806D
+#define GL_UNPACK_IMAGE_HEIGHT_EXT 0x806E
+#define GL_TEXTURE_3D_EXT 0x806F
+#define GL_PROXY_TEXTURE_3D_EXT 0x8070
+#define GL_TEXTURE_DEPTH_EXT 0x8071
+#define GL_TEXTURE_WRAP_R_EXT 0x8072
+#define GL_MAX_3D_TEXTURE_SIZE_EXT 0x8073
+#endif
+
+#ifndef GL_SGIS_texture_filter4
+#define GL_FILTER4_SGIS 0x8146
+#define GL_TEXTURE_FILTER4_SIZE_SGIS 0x8147
+#endif
+
+#ifndef GL_EXT_subtexture
+#endif
+
+#ifndef GL_EXT_copy_texture
+#endif
+
+#ifndef GL_EXT_histogram
+#define GL_HISTOGRAM_EXT 0x8024
+#define GL_PROXY_HISTOGRAM_EXT 0x8025
+#define GL_HISTOGRAM_WIDTH_EXT 0x8026
+#define GL_HISTOGRAM_FORMAT_EXT 0x8027
+#define GL_HISTOGRAM_RED_SIZE_EXT 0x8028
+#define GL_HISTOGRAM_GREEN_SIZE_EXT 0x8029
+#define GL_HISTOGRAM_BLUE_SIZE_EXT 0x802A
+#define GL_HISTOGRAM_ALPHA_SIZE_EXT 0x802B
+#define GL_HISTOGRAM_LUMINANCE_SIZE_EXT 0x802C
+#define GL_HISTOGRAM_SINK_EXT 0x802D
+#define GL_MINMAX_EXT 0x802E
+#define GL_MINMAX_FORMAT_EXT 0x802F
+#define GL_MINMAX_SINK_EXT 0x8030
+#define GL_TABLE_TOO_LARGE_EXT 0x8031
+#endif
+
+#ifndef GL_EXT_convolution
+#define GL_CONVOLUTION_1D_EXT 0x8010
+#define GL_CONVOLUTION_2D_EXT 0x8011
+#define GL_SEPARABLE_2D_EXT 0x8012
+#define GL_CONVOLUTION_BORDER_MODE_EXT 0x8013
+#define GL_CONVOLUTION_FILTER_SCALE_EXT 0x8014
+#define GL_CONVOLUTION_FILTER_BIAS_EXT 0x8015
+#define GL_REDUCE_EXT 0x8016
+#define GL_CONVOLUTION_FORMAT_EXT 0x8017
+#define GL_CONVOLUTION_WIDTH_EXT 0x8018
+#define GL_CONVOLUTION_HEIGHT_EXT 0x8019
+#define GL_MAX_CONVOLUTION_WIDTH_EXT 0x801A
+#define GL_MAX_CONVOLUTION_HEIGHT_EXT 0x801B
+#define GL_POST_CONVOLUTION_RED_SCALE_EXT 0x801C
+#define GL_POST_CONVOLUTION_GREEN_SCALE_EXT 0x801D
+#define GL_POST_CONVOLUTION_BLUE_SCALE_EXT 0x801E
+#define GL_POST_CONVOLUTION_ALPHA_SCALE_EXT 0x801F
+#define GL_POST_CONVOLUTION_RED_BIAS_EXT 0x8020
+#define GL_POST_CONVOLUTION_GREEN_BIAS_EXT 0x8021
+#define GL_POST_CONVOLUTION_BLUE_BIAS_EXT 0x8022
+#define GL_POST_CONVOLUTION_ALPHA_BIAS_EXT 0x8023
+#endif
+
+#ifndef GL_SGI_color_matrix
+#define GL_COLOR_MATRIX_SGI 0x80B1
+#define GL_COLOR_MATRIX_STACK_DEPTH_SGI 0x80B2
+#define GL_MAX_COLOR_MATRIX_STACK_DEPTH_SGI 0x80B3
+#define GL_POST_COLOR_MATRIX_RED_SCALE_SGI 0x80B4
+#define GL_POST_COLOR_MATRIX_GREEN_SCALE_SGI 0x80B5
+#define GL_POST_COLOR_MATRIX_BLUE_SCALE_SGI 0x80B6
+#define GL_POST_COLOR_MATRIX_ALPHA_SCALE_SGI 0x80B7
+#define GL_POST_COLOR_MATRIX_RED_BIAS_SGI 0x80B8
+#define GL_POST_COLOR_MATRIX_GREEN_BIAS_SGI 0x80B9
+#define GL_POST_COLOR_MATRIX_BLUE_BIAS_SGI 0x80BA
+#define GL_POST_COLOR_MATRIX_ALPHA_BIAS_SGI 0x80BB
+#endif
+
+#ifndef GL_SGI_color_table
+#define GL_COLOR_TABLE_SGI 0x80D0
+#define GL_POST_CONVOLUTION_COLOR_TABLE_SGI 0x80D1
+#define GL_POST_COLOR_MATRIX_COLOR_TABLE_SGI 0x80D2
+#define GL_PROXY_COLOR_TABLE_SGI 0x80D3
+#define GL_PROXY_POST_CONVOLUTION_COLOR_TABLE_SGI 0x80D4
+#define GL_PROXY_POST_COLOR_MATRIX_COLOR_TABLE_SGI 0x80D5
+#define GL_COLOR_TABLE_SCALE_SGI 0x80D6
+#define GL_COLOR_TABLE_BIAS_SGI 0x80D7
+#define GL_COLOR_TABLE_FORMAT_SGI 0x80D8
+#define GL_COLOR_TABLE_WIDTH_SGI 0x80D9
+#define GL_COLOR_TABLE_RED_SIZE_SGI 0x80DA
+#define GL_COLOR_TABLE_GREEN_SIZE_SGI 0x80DB
+#define GL_COLOR_TABLE_BLUE_SIZE_SGI 0x80DC
+#define GL_COLOR_TABLE_ALPHA_SIZE_SGI 0x80DD
+#define GL_COLOR_TABLE_LUMINANCE_SIZE_SGI 0x80DE
+#define GL_COLOR_TABLE_INTENSITY_SIZE_SGI 0x80DF
+#endif
+
+#ifndef GL_SGIS_pixel_texture
+#define GL_PIXEL_TEXTURE_SGIS 0x8353
+#define GL_PIXEL_FRAGMENT_RGB_SOURCE_SGIS 0x8354
+#define GL_PIXEL_FRAGMENT_ALPHA_SOURCE_SGIS 0x8355
+#define GL_PIXEL_GROUP_COLOR_SGIS 0x8356
+#endif
+
+#ifndef GL_SGIX_pixel_texture
+#define GL_PIXEL_TEX_GEN_SGIX 0x8139
+#define GL_PIXEL_TEX_GEN_MODE_SGIX 0x832B
+#endif
+
+#ifndef GL_SGIS_texture4D
+#define GL_PACK_SKIP_VOLUMES_SGIS 0x8130
+#define GL_PACK_IMAGE_DEPTH_SGIS 0x8131
+#define GL_UNPACK_SKIP_VOLUMES_SGIS 0x8132
+#define GL_UNPACK_IMAGE_DEPTH_SGIS 0x8133
+#define GL_TEXTURE_4D_SGIS 0x8134
+#define GL_PROXY_TEXTURE_4D_SGIS 0x8135
+#define GL_TEXTURE_4DSIZE_SGIS 0x8136
+#define GL_TEXTURE_WRAP_Q_SGIS 0x8137
+#define GL_MAX_4D_TEXTURE_SIZE_SGIS 0x8138
+#define GL_TEXTURE_4D_BINDING_SGIS 0x814F
+#endif
+
+#ifndef GL_SGI_texture_color_table
+#define GL_TEXTURE_COLOR_TABLE_SGI 0x80BC
+#define GL_PROXY_TEXTURE_COLOR_TABLE_SGI 0x80BD
+#endif
+
+#ifndef GL_EXT_cmyka
+#define GL_CMYK_EXT 0x800C
+#define GL_CMYKA_EXT 0x800D
+#define GL_PACK_CMYK_HINT_EXT 0x800E
+#define GL_UNPACK_CMYK_HINT_EXT 0x800F
+#endif
+
+#ifndef GL_EXT_texture_object
+#define GL_TEXTURE_PRIORITY_EXT 0x8066
+#define GL_TEXTURE_RESIDENT_EXT 0x8067
+#define GL_TEXTURE_1D_BINDING_EXT 0x8068
+#define GL_TEXTURE_2D_BINDING_EXT 0x8069
+#define GL_TEXTURE_3D_BINDING_EXT 0x806A
+#endif
+
+#ifndef GL_SGIS_detail_texture
+#define GL_DETAIL_TEXTURE_2D_SGIS 0x8095
+#define GL_DETAIL_TEXTURE_2D_BINDING_SGIS 0x8096
+#define GL_LINEAR_DETAIL_SGIS 0x8097
+#define GL_LINEAR_DETAIL_ALPHA_SGIS 0x8098
+#define GL_LINEAR_DETAIL_COLOR_SGIS 0x8099
+#define GL_DETAIL_TEXTURE_LEVEL_SGIS 0x809A
+#define GL_DETAIL_TEXTURE_MODE_SGIS 0x809B
+#define GL_DETAIL_TEXTURE_FUNC_POINTS_SGIS 0x809C
+#endif
+
+#ifndef GL_SGIS_sharpen_texture
+#define GL_LINEAR_SHARPEN_SGIS 0x80AD
+#define GL_LINEAR_SHARPEN_ALPHA_SGIS 0x80AE
+#define GL_LINEAR_SHARPEN_COLOR_SGIS 0x80AF
+#define GL_SHARPEN_TEXTURE_FUNC_POINTS_SGIS 0x80B0
+#endif
+
+#ifndef GL_EXT_packed_pixels
+#define GL_UNSIGNED_BYTE_3_3_2_EXT 0x8032
+#define GL_UNSIGNED_SHORT_4_4_4_4_EXT 0x8033
+#define GL_UNSIGNED_SHORT_5_5_5_1_EXT 0x8034
+#define GL_UNSIGNED_INT_8_8_8_8_EXT 0x8035
+#define GL_UNSIGNED_INT_10_10_10_2_EXT 0x8036
+#endif
+
+#ifndef GL_SGIS_texture_lod
+#define GL_TEXTURE_MIN_LOD_SGIS 0x813A
+#define GL_TEXTURE_MAX_LOD_SGIS 0x813B
+#define GL_TEXTURE_BASE_LEVEL_SGIS 0x813C
+#define GL_TEXTURE_MAX_LEVEL_SGIS 0x813D
+#endif
+
+#ifndef GL_SGIS_multisample
+#define GL_MULTISAMPLE_SGIS 0x809D
+#define GL_SAMPLE_ALPHA_TO_MASK_SGIS 0x809E
+#define GL_SAMPLE_ALPHA_TO_ONE_SGIS 0x809F
+#define GL_SAMPLE_MASK_SGIS 0x80A0
+#define GL_1PASS_SGIS 0x80A1
+#define GL_2PASS_0_SGIS 0x80A2
+#define GL_2PASS_1_SGIS 0x80A3
+#define GL_4PASS_0_SGIS 0x80A4
+#define GL_4PASS_1_SGIS 0x80A5
+#define GL_4PASS_2_SGIS 0x80A6
+#define GL_4PASS_3_SGIS 0x80A7
+#define GL_SAMPLE_BUFFERS_SGIS 0x80A8
+#define GL_SAMPLES_SGIS 0x80A9
+#define GL_SAMPLE_MASK_VALUE_SGIS 0x80AA
+#define GL_SAMPLE_MASK_INVERT_SGIS 0x80AB
+#define GL_SAMPLE_PATTERN_SGIS 0x80AC
+#endif
+
+#ifndef GL_EXT_rescale_normal
+#define GL_RESCALE_NORMAL_EXT 0x803A
+#endif
+
+#ifndef GL_EXT_vertex_array
+#define GL_VERTEX_ARRAY_EXT 0x8074
+#define GL_NORMAL_ARRAY_EXT 0x8075
+#define GL_COLOR_ARRAY_EXT 0x8076
+#define GL_INDEX_ARRAY_EXT 0x8077
+#define GL_TEXTURE_COORD_ARRAY_EXT 0x8078
+#define GL_EDGE_FLAG_ARRAY_EXT 0x8079
+#define GL_VERTEX_ARRAY_SIZE_EXT 0x807A
+#define GL_VERTEX_ARRAY_TYPE_EXT 0x807B
+#define GL_VERTEX_ARRAY_STRIDE_EXT 0x807C
+#define GL_VERTEX_ARRAY_COUNT_EXT 0x807D
+#define GL_NORMAL_ARRAY_TYPE_EXT 0x807E
+#define GL_NORMAL_ARRAY_STRIDE_EXT 0x807F
+#define GL_NORMAL_ARRAY_COUNT_EXT 0x8080
+#define GL_COLOR_ARRAY_SIZE_EXT 0x8081
+#define GL_COLOR_ARRAY_TYPE_EXT 0x8082
+#define GL_COLOR_ARRAY_STRIDE_EXT 0x8083
+#define GL_COLOR_ARRAY_COUNT_EXT 0x8084
+#define GL_INDEX_ARRAY_TYPE_EXT 0x8085
+#define GL_INDEX_ARRAY_STRIDE_EXT 0x8086
+#define GL_INDEX_ARRAY_COUNT_EXT 0x8087
+#define GL_TEXTURE_COORD_ARRAY_SIZE_EXT 0x8088
+#define GL_TEXTURE_COORD_ARRAY_TYPE_EXT 0x8089
+#define GL_TEXTURE_COORD_ARRAY_STRIDE_EXT 0x808A
+#define GL_TEXTURE_COORD_ARRAY_COUNT_EXT 0x808B
+#define GL_EDGE_FLAG_ARRAY_STRIDE_EXT 0x808C
+#define GL_EDGE_FLAG_ARRAY_COUNT_EXT 0x808D
+#define GL_VERTEX_ARRAY_POINTER_EXT 0x808E
+#define GL_NORMAL_ARRAY_POINTER_EXT 0x808F
+#define GL_COLOR_ARRAY_POINTER_EXT 0x8090
+#define GL_INDEX_ARRAY_POINTER_EXT 0x8091
+#define GL_TEXTURE_COORD_ARRAY_POINTER_EXT 0x8092
+#define GL_EDGE_FLAG_ARRAY_POINTER_EXT 0x8093
+#endif
+
+#ifndef GL_EXT_misc_attribute
+#endif
+
+#ifndef GL_SGIS_generate_mipmap
+#define GL_GENERATE_MIPMAP_SGIS 0x8191
+#define GL_GENERATE_MIPMAP_HINT_SGIS 0x8192
+#endif
+
+#ifndef GL_SGIX_clipmap
+#define GL_LINEAR_CLIPMAP_LINEAR_SGIX 0x8170
+#define GL_TEXTURE_CLIPMAP_CENTER_SGIX 0x8171
+#define GL_TEXTURE_CLIPMAP_FRAME_SGIX 0x8172
+#define GL_TEXTURE_CLIPMAP_OFFSET_SGIX 0x8173
+#define GL_TEXTURE_CLIPMAP_VIRTUAL_DEPTH_SGIX 0x8174
+#define GL_TEXTURE_CLIPMAP_LOD_OFFSET_SGIX 0x8175
+#define GL_TEXTURE_CLIPMAP_DEPTH_SGIX 0x8176
+#define GL_MAX_CLIPMAP_DEPTH_SGIX 0x8177
+#define GL_MAX_CLIPMAP_VIRTUAL_DEPTH_SGIX 0x8178
+#define GL_NEAREST_CLIPMAP_NEAREST_SGIX 0x844D
+#define GL_NEAREST_CLIPMAP_LINEAR_SGIX 0x844E
+#define GL_LINEAR_CLIPMAP_NEAREST_SGIX 0x844F
+#endif
+
+#ifndef GL_SGIX_shadow
+#define GL_TEXTURE_COMPARE_SGIX 0x819A
+#define GL_TEXTURE_COMPARE_OPERATOR_SGIX 0x819B
+#define GL_TEXTURE_LEQUAL_R_SGIX 0x819C
+#define GL_TEXTURE_GEQUAL_R_SGIX 0x819D
+#endif
+
+#ifndef GL_SGIS_texture_edge_clamp
+#define GL_CLAMP_TO_EDGE_SGIS 0x812F
+#endif
+
+#ifndef GL_SGIS_texture_border_clamp
+#define GL_CLAMP_TO_BORDER_SGIS 0x812D
+#endif
+
+#ifndef GL_EXT_blend_minmax
+#define GL_FUNC_ADD_EXT 0x8006
+#define GL_MIN_EXT 0x8007
+#define GL_MAX_EXT 0x8008
+#define GL_BLEND_EQUATION_EXT 0x8009
+#endif
+
+#ifndef GL_EXT_blend_subtract
+#define GL_FUNC_SUBTRACT_EXT 0x800A
+#define GL_FUNC_REVERSE_SUBTRACT_EXT 0x800B
+#endif
+
+#ifndef GL_EXT_blend_logic_op
+#endif
+
+#ifndef GL_SGIX_interlace
+#define GL_INTERLACE_SGIX 0x8094
+#endif
+
+#ifndef GL_SGIX_pixel_tiles
+#define GL_PIXEL_TILE_BEST_ALIGNMENT_SGIX 0x813E
+#define GL_PIXEL_TILE_CACHE_INCREMENT_SGIX 0x813F
+#define GL_PIXEL_TILE_WIDTH_SGIX 0x8140
+#define GL_PIXEL_TILE_HEIGHT_SGIX 0x8141
+#define GL_PIXEL_TILE_GRID_WIDTH_SGIX 0x8142
+#define GL_PIXEL_TILE_GRID_HEIGHT_SGIX 0x8143
+#define GL_PIXEL_TILE_GRID_DEPTH_SGIX 0x8144
+#define GL_PIXEL_TILE_CACHE_SIZE_SGIX 0x8145
+#endif
+
+#ifndef GL_SGIS_texture_select
+#define GL_DUAL_ALPHA4_SGIS 0x8110
+#define GL_DUAL_ALPHA8_SGIS 0x8111
+#define GL_DUAL_ALPHA12_SGIS 0x8112
+#define GL_DUAL_ALPHA16_SGIS 0x8113
+#define GL_DUAL_LUMINANCE4_SGIS 0x8114
+#define GL_DUAL_LUMINANCE8_SGIS 0x8115
+#define GL_DUAL_LUMINANCE12_SGIS 0x8116
+#define GL_DUAL_LUMINANCE16_SGIS 0x8117
+#define GL_DUAL_INTENSITY4_SGIS 0x8118
+#define GL_DUAL_INTENSITY8_SGIS 0x8119
+#define GL_DUAL_INTENSITY12_SGIS 0x811A
+#define GL_DUAL_INTENSITY16_SGIS 0x811B
+#define GL_DUAL_LUMINANCE_ALPHA4_SGIS 0x811C
+#define GL_DUAL_LUMINANCE_ALPHA8_SGIS 0x811D
+#define GL_QUAD_ALPHA4_SGIS 0x811E
+#define GL_QUAD_ALPHA8_SGIS 0x811F
+#define GL_QUAD_LUMINANCE4_SGIS 0x8120
+#define GL_QUAD_LUMINANCE8_SGIS 0x8121
+#define GL_QUAD_INTENSITY4_SGIS 0x8122
+#define GL_QUAD_INTENSITY8_SGIS 0x8123
+#define GL_DUAL_TEXTURE_SELECT_SGIS 0x8124
+#define GL_QUAD_TEXTURE_SELECT_SGIS 0x8125
+#endif
+
+#ifndef GL_SGIX_sprite
+#define GL_SPRITE_SGIX 0x8148
+#define GL_SPRITE_MODE_SGIX 0x8149
+#define GL_SPRITE_AXIS_SGIX 0x814A
+#define GL_SPRITE_TRANSLATION_SGIX 0x814B
+#define GL_SPRITE_AXIAL_SGIX 0x814C
+#define GL_SPRITE_OBJECT_ALIGNED_SGIX 0x814D
+#define GL_SPRITE_EYE_ALIGNED_SGIX 0x814E
+#endif
+
+#ifndef GL_SGIX_texture_multi_buffer
+#define GL_TEXTURE_MULTI_BUFFER_HINT_SGIX 0x812E
+#endif
+
+#ifndef GL_EXT_point_parameters
+#define GL_POINT_SIZE_MIN_EXT 0x8126
+#define GL_POINT_SIZE_MAX_EXT 0x8127
+#define GL_POINT_FADE_THRESHOLD_SIZE_EXT 0x8128
+#define GL_DISTANCE_ATTENUATION_EXT 0x8129
+#endif
+
+#ifndef GL_SGIS_point_parameters
+#define GL_POINT_SIZE_MIN_SGIS 0x8126
+#define GL_POINT_SIZE_MAX_SGIS 0x8127
+#define GL_POINT_FADE_THRESHOLD_SIZE_SGIS 0x8128
+#define GL_DISTANCE_ATTENUATION_SGIS 0x8129
+#endif
+
+#ifndef GL_SGIX_instruments
+#define GL_INSTRUMENT_BUFFER_POINTER_SGIX 0x8180
+#define GL_INSTRUMENT_MEASUREMENTS_SGIX 0x8181
+#endif
+
+#ifndef GL_SGIX_texture_scale_bias
+#define GL_POST_TEXTURE_FILTER_BIAS_SGIX 0x8179
+#define GL_POST_TEXTURE_FILTER_SCALE_SGIX 0x817A
+#define GL_POST_TEXTURE_FILTER_BIAS_RANGE_SGIX 0x817B
+#define GL_POST_TEXTURE_FILTER_SCALE_RANGE_SGIX 0x817C
+#endif
+
+#ifndef GL_SGIX_framezoom
+#define GL_FRAMEZOOM_SGIX 0x818B
+#define GL_FRAMEZOOM_FACTOR_SGIX 0x818C
+#define GL_MAX_FRAMEZOOM_FACTOR_SGIX 0x818D
+#endif
+
+#ifndef GL_SGIX_tag_sample_buffer
+#endif
+
+#ifndef GL_FfdMaskSGIX
+#define GL_TEXTURE_DEFORMATION_BIT_SGIX 0x00000001
+#define GL_GEOMETRY_DEFORMATION_BIT_SGIX 0x00000002
+#endif
+
+#ifndef GL_SGIX_polynomial_ffd
+#define GL_GEOMETRY_DEFORMATION_SGIX 0x8194
+#define GL_TEXTURE_DEFORMATION_SGIX 0x8195
+#define GL_DEFORMATIONS_MASK_SGIX 0x8196
+#define GL_MAX_DEFORMATION_ORDER_SGIX 0x8197
+#endif
+
+#ifndef GL_SGIX_reference_plane
+#define GL_REFERENCE_PLANE_SGIX 0x817D
+#define GL_REFERENCE_PLANE_EQUATION_SGIX 0x817E
+#endif
+
+#ifndef GL_SGIX_flush_raster
+#endif
+
+#ifndef GL_SGIX_depth_texture
+#define GL_DEPTH_COMPONENT16_SGIX 0x81A5
+#define GL_DEPTH_COMPONENT24_SGIX 0x81A6
+#define GL_DEPTH_COMPONENT32_SGIX 0x81A7
+#endif
+
+#ifndef GL_SGIS_fog_function
+#define GL_FOG_FUNC_SGIS 0x812A
+#define GL_FOG_FUNC_POINTS_SGIS 0x812B
+#define GL_MAX_FOG_FUNC_POINTS_SGIS 0x812C
+#endif
+
+#ifndef GL_SGIX_fog_offset
+#define GL_FOG_OFFSET_SGIX 0x8198
+#define GL_FOG_OFFSET_VALUE_SGIX 0x8199
+#endif
+
+#ifndef GL_HP_image_transform
+#define GL_IMAGE_SCALE_X_HP 0x8155
+#define GL_IMAGE_SCALE_Y_HP 0x8156
+#define GL_IMAGE_TRANSLATE_X_HP 0x8157
+#define GL_IMAGE_TRANSLATE_Y_HP 0x8158
+#define GL_IMAGE_ROTATE_ANGLE_HP 0x8159
+#define GL_IMAGE_ROTATE_ORIGIN_X_HP 0x815A
+#define GL_IMAGE_ROTATE_ORIGIN_Y_HP 0x815B
+#define GL_IMAGE_MAG_FILTER_HP 0x815C
+#define GL_IMAGE_MIN_FILTER_HP 0x815D
+#define GL_IMAGE_CUBIC_WEIGHT_HP 0x815E
+#define GL_CUBIC_HP 0x815F
+#define GL_AVERAGE_HP 0x8160
+#define GL_IMAGE_TRANSFORM_2D_HP 0x8161
+#define GL_POST_IMAGE_TRANSFORM_COLOR_TABLE_HP 0x8162
+#define GL_PROXY_POST_IMAGE_TRANSFORM_COLOR_TABLE_HP 0x8163
+#endif
+
+#ifndef GL_HP_convolution_border_modes
+#define GL_IGNORE_BORDER_HP 0x8150
+#define GL_CONSTANT_BORDER_HP 0x8151
+#define GL_REPLICATE_BORDER_HP 0x8153
+#define GL_CONVOLUTION_BORDER_COLOR_HP 0x8154
+#endif
+
+#ifndef GL_INGR_palette_buffer
+#endif
+
+#ifndef GL_SGIX_texture_add_env
+#define GL_TEXTURE_ENV_BIAS_SGIX 0x80BE
+#endif
+
+#ifndef GL_EXT_color_subtable
+#endif
+
+#ifndef GL_PGI_vertex_hints
+#define GL_VERTEX_DATA_HINT_PGI 0x1A22A
+#define GL_VERTEX_CONSISTENT_HINT_PGI 0x1A22B
+#define GL_MATERIAL_SIDE_HINT_PGI 0x1A22C
+#define GL_MAX_VERTEX_HINT_PGI 0x1A22D
+#define GL_COLOR3_BIT_PGI 0x00010000
+#define GL_COLOR4_BIT_PGI 0x00020000
+#define GL_EDGEFLAG_BIT_PGI 0x00040000
+#define GL_INDEX_BIT_PGI 0x00080000
+#define GL_MAT_AMBIENT_BIT_PGI 0x00100000
+#define GL_MAT_AMBIENT_AND_DIFFUSE_BIT_PGI 0x00200000
+#define GL_MAT_DIFFUSE_BIT_PGI 0x00400000
+#define GL_MAT_EMISSION_BIT_PGI 0x00800000
+#define GL_MAT_COLOR_INDEXES_BIT_PGI 0x01000000
+#define GL_MAT_SHININESS_BIT_PGI 0x02000000
+#define GL_MAT_SPECULAR_BIT_PGI 0x04000000
+#define GL_NORMAL_BIT_PGI 0x08000000
+#define GL_TEXCOORD1_BIT_PGI 0x10000000
+#define GL_TEXCOORD2_BIT_PGI 0x20000000
+#define GL_TEXCOORD3_BIT_PGI 0x40000000
+#define GL_TEXCOORD4_BIT_PGI 0x80000000
+#define GL_VERTEX23_BIT_PGI 0x00000004
+#define GL_VERTEX4_BIT_PGI 0x00000008
+#endif
+
+#ifndef GL_PGI_misc_hints
+#define GL_PREFER_DOUBLEBUFFER_HINT_PGI 0x1A1F8
+#define GL_CONSERVE_MEMORY_HINT_PGI 0x1A1FD
+#define GL_RECLAIM_MEMORY_HINT_PGI 0x1A1FE
+#define GL_NATIVE_GRAPHICS_HANDLE_PGI 0x1A202
+#define GL_NATIVE_GRAPHICS_BEGIN_HINT_PGI 0x1A203
+#define GL_NATIVE_GRAPHICS_END_HINT_PGI 0x1A204
+#define GL_ALWAYS_FAST_HINT_PGI 0x1A20C
+#define GL_ALWAYS_SOFT_HINT_PGI 0x1A20D
+#define GL_ALLOW_DRAW_OBJ_HINT_PGI 0x1A20E
+#define GL_ALLOW_DRAW_WIN_HINT_PGI 0x1A20F
+#define GL_ALLOW_DRAW_FRG_HINT_PGI 0x1A210
+#define GL_ALLOW_DRAW_MEM_HINT_PGI 0x1A211
+#define GL_STRICT_DEPTHFUNC_HINT_PGI 0x1A216
+#define GL_STRICT_LIGHTING_HINT_PGI 0x1A217
+#define GL_STRICT_SCISSOR_HINT_PGI 0x1A218
+#define GL_FULL_STIPPLE_HINT_PGI 0x1A219
+#define GL_CLIP_NEAR_HINT_PGI 0x1A220
+#define GL_CLIP_FAR_HINT_PGI 0x1A221
+#define GL_WIDE_LINE_HINT_PGI 0x1A222
+#define GL_BACK_NORMALS_HINT_PGI 0x1A223
+#endif
+
+#ifndef GL_EXT_paletted_texture
+#define GL_COLOR_INDEX1_EXT 0x80E2
+#define GL_COLOR_INDEX2_EXT 0x80E3
+#define GL_COLOR_INDEX4_EXT 0x80E4
+#define GL_COLOR_INDEX8_EXT 0x80E5
+#define GL_COLOR_INDEX12_EXT 0x80E6
+#define GL_COLOR_INDEX16_EXT 0x80E7
+#define GL_TEXTURE_INDEX_SIZE_EXT 0x80ED
+#endif
+
+#ifndef GL_EXT_clip_volume_hint
+#define GL_CLIP_VOLUME_CLIPPING_HINT_EXT 0x80F0
+#endif
+
+#ifndef GL_SGIX_list_priority
+#define GL_LIST_PRIORITY_SGIX 0x8182
+#endif
+
+#ifndef GL_SGIX_ir_instrument1
+#define GL_IR_INSTRUMENT1_SGIX 0x817F
+#endif
+
+#ifndef GL_SGIX_calligraphic_fragment
+#define GL_CALLIGRAPHIC_FRAGMENT_SGIX 0x8183
+#endif
+
+#ifndef GL_SGIX_texture_lod_bias
+#define GL_TEXTURE_LOD_BIAS_S_SGIX 0x818E
+#define GL_TEXTURE_LOD_BIAS_T_SGIX 0x818F
+#define GL_TEXTURE_LOD_BIAS_R_SGIX 0x8190
+#endif
+
+#ifndef GL_SGIX_shadow_ambient
+#define GL_SHADOW_AMBIENT_SGIX 0x80BF
+#endif
+
+#ifndef GL_EXT_index_texture
+#endif
+
+#ifndef GL_EXT_index_material
+#define GL_INDEX_MATERIAL_EXT 0x81B8
+#define GL_INDEX_MATERIAL_PARAMETER_EXT 0x81B9
+#define GL_INDEX_MATERIAL_FACE_EXT 0x81BA
+#endif
+
+#ifndef GL_EXT_index_func
+#define GL_INDEX_TEST_EXT 0x81B5
+#define GL_INDEX_TEST_FUNC_EXT 0x81B6
+#define GL_INDEX_TEST_REF_EXT 0x81B7
+#endif
+
+#ifndef GL_EXT_index_array_formats
+#define GL_IUI_V2F_EXT 0x81AD
+#define GL_IUI_V3F_EXT 0x81AE
+#define GL_IUI_N3F_V2F_EXT 0x81AF
+#define GL_IUI_N3F_V3F_EXT 0x81B0
+#define GL_T2F_IUI_V2F_EXT 0x81B1
+#define GL_T2F_IUI_V3F_EXT 0x81B2
+#define GL_T2F_IUI_N3F_V2F_EXT 0x81B3
+#define GL_T2F_IUI_N3F_V3F_EXT 0x81B4
+#endif
+
+#ifndef GL_EXT_compiled_vertex_array
+#define GL_ARRAY_ELEMENT_LOCK_FIRST_EXT 0x81A8
+#define GL_ARRAY_ELEMENT_LOCK_COUNT_EXT 0x81A9
+#endif
+
+#ifndef GL_EXT_cull_vertex
+#define GL_CULL_VERTEX_EXT 0x81AA
+#define GL_CULL_VERTEX_EYE_POSITION_EXT 0x81AB
+#define GL_CULL_VERTEX_OBJECT_POSITION_EXT 0x81AC
+#endif
+
+#ifndef GL_SGIX_ycrcb
+#define GL_YCRCB_422_SGIX 0x81BB
+#define GL_YCRCB_444_SGIX 0x81BC
+#endif
+
+#ifndef GL_SGIX_fragment_lighting
+#define GL_FRAGMENT_LIGHTING_SGIX 0x8400
+#define GL_FRAGMENT_COLOR_MATERIAL_SGIX 0x8401
+#define GL_FRAGMENT_COLOR_MATERIAL_FACE_SGIX 0x8402
+#define GL_FRAGMENT_COLOR_MATERIAL_PARAMETER_SGIX 0x8403
+#define GL_MAX_FRAGMENT_LIGHTS_SGIX 0x8404
+#define GL_MAX_ACTIVE_LIGHTS_SGIX 0x8405
+#define GL_CURRENT_RASTER_NORMAL_SGIX 0x8406
+#define GL_LIGHT_ENV_MODE_SGIX 0x8407
+#define GL_FRAGMENT_LIGHT_MODEL_LOCAL_VIEWER_SGIX 0x8408
+#define GL_FRAGMENT_LIGHT_MODEL_TWO_SIDE_SGIX 0x8409
+#define GL_FRAGMENT_LIGHT_MODEL_AMBIENT_SGIX 0x840A
+#define GL_FRAGMENT_LIGHT_MODEL_NORMAL_INTERPOLATION_SGIX 0x840B
+#define GL_FRAGMENT_LIGHT0_SGIX 0x840C
+#define GL_FRAGMENT_LIGHT1_SGIX 0x840D
+#define GL_FRAGMENT_LIGHT2_SGIX 0x840E
+#define GL_FRAGMENT_LIGHT3_SGIX 0x840F
+#define GL_FRAGMENT_LIGHT4_SGIX 0x8410
+#define GL_FRAGMENT_LIGHT5_SGIX 0x8411
+#define GL_FRAGMENT_LIGHT6_SGIX 0x8412
+#define GL_FRAGMENT_LIGHT7_SGIX 0x8413
+#endif
+
+#ifndef GL_IBM_rasterpos_clip
+#define GL_RASTER_POSITION_UNCLIPPED_IBM 0x19262
+#endif
+
+#ifndef GL_HP_texture_lighting
+#define GL_TEXTURE_LIGHTING_MODE_HP 0x8167
+#define GL_TEXTURE_POST_SPECULAR_HP 0x8168
+#define GL_TEXTURE_PRE_SPECULAR_HP 0x8169
+#endif
+
+#ifndef GL_EXT_draw_range_elements
+#define GL_MAX_ELEMENTS_VERTICES_EXT 0x80E8
+#define GL_MAX_ELEMENTS_INDICES_EXT 0x80E9
+#endif
+
+#ifndef GL_WIN_phong_shading
+#define GL_PHONG_WIN 0x80EA
+#define GL_PHONG_HINT_WIN 0x80EB
+#endif
+
+#ifndef GL_WIN_specular_fog
+#define GL_FOG_SPECULAR_TEXTURE_WIN 0x80EC
+#endif
+
+#ifndef GL_EXT_light_texture
+#define GL_FRAGMENT_MATERIAL_EXT 0x8349
+#define GL_FRAGMENT_NORMAL_EXT 0x834A
+#define GL_FRAGMENT_COLOR_EXT 0x834C
+#define GL_ATTENUATION_EXT 0x834D
+#define GL_SHADOW_ATTENUATION_EXT 0x834E
+#define GL_TEXTURE_APPLICATION_MODE_EXT 0x834F
+#define GL_TEXTURE_LIGHT_EXT 0x8350
+#define GL_TEXTURE_MATERIAL_FACE_EXT 0x8351
+#define GL_TEXTURE_MATERIAL_PARAMETER_EXT 0x8352
+
+#endif
+
+#ifndef GL_SGIX_blend_alpha_minmax
+#define GL_ALPHA_MIN_SGIX 0x8320
+#define GL_ALPHA_MAX_SGIX 0x8321
+#endif
+
+#ifndef GL_SGIX_impact_pixel_texture
+#define GL_PIXEL_TEX_GEN_Q_CEILING_SGIX 0x8184
+#define GL_PIXEL_TEX_GEN_Q_ROUND_SGIX 0x8185
+#define GL_PIXEL_TEX_GEN_Q_FLOOR_SGIX 0x8186
+#define GL_PIXEL_TEX_GEN_ALPHA_REPLACE_SGIX 0x8187
+#define GL_PIXEL_TEX_GEN_ALPHA_NO_REPLACE_SGIX 0x8188
+#define GL_PIXEL_TEX_GEN_ALPHA_LS_SGIX 0x8189
+#define GL_PIXEL_TEX_GEN_ALPHA_MS_SGIX 0x818A
+#endif
+
+#ifndef GL_EXT_bgra
+#define GL_BGR_EXT 0x80E0
+#define GL_BGRA_EXT 0x80E1
+#endif
+
+#ifndef GL_SGIX_async
+#define GL_ASYNC_MARKER_SGIX 0x8329
+#endif
+
+#ifndef GL_SGIX_async_pixel
+#define GL_ASYNC_TEX_IMAGE_SGIX 0x835C
+#define GL_ASYNC_DRAW_PIXELS_SGIX 0x835D
+#define GL_ASYNC_READ_PIXELS_SGIX 0x835E
+#define GL_MAX_ASYNC_TEX_IMAGE_SGIX 0x835F
+#define GL_MAX_ASYNC_DRAW_PIXELS_SGIX 0x8360
+#define GL_MAX_ASYNC_READ_PIXELS_SGIX 0x8361
+#endif
+
+#ifndef GL_SGIX_async_histogram
+#define GL_ASYNC_HISTOGRAM_SGIX 0x832C
+#define GL_MAX_ASYNC_HISTOGRAM_SGIX 0x832D
+#endif
+
+#ifndef GL_INTEL_texture_scissor
+#endif
+
+#ifndef GL_INTEL_parallel_arrays
+#define GL_PARALLEL_ARRAYS_INTEL 0x83F4
+#define GL_VERTEX_ARRAY_PARALLEL_POINTERS_INTEL 0x83F5
+#define GL_NORMAL_ARRAY_PARALLEL_POINTERS_INTEL 0x83F6
+#define GL_COLOR_ARRAY_PARALLEL_POINTERS_INTEL 0x83F7
+#define GL_TEXTURE_COORD_ARRAY_PARALLEL_POINTERS_INTEL 0x83F8
+#endif
+
+#ifndef GL_HP_occlusion_test
+#define GL_OCCLUSION_TEST_HP 0x8165
+#define GL_OCCLUSION_TEST_RESULT_HP 0x8166
+#endif
+
+#ifndef GL_EXT_pixel_transform
+#define GL_PIXEL_TRANSFORM_2D_EXT 0x8330
+#define GL_PIXEL_MAG_FILTER_EXT 0x8331
+#define GL_PIXEL_MIN_FILTER_EXT 0x8332
+#define GL_PIXEL_CUBIC_WEIGHT_EXT 0x8333
+#define GL_CUBIC_EXT 0x8334
+#define GL_AVERAGE_EXT 0x8335
+#define GL_PIXEL_TRANSFORM_2D_STACK_DEPTH_EXT 0x8336
+#define GL_MAX_PIXEL_TRANSFORM_2D_STACK_DEPTH_EXT 0x8337
+#define GL_PIXEL_TRANSFORM_2D_MATRIX_EXT 0x8338
+#endif
+
+#ifndef GL_EXT_pixel_transform_color_table
+#endif
+
+#ifndef GL_EXT_shared_texture_palette
+#define GL_SHARED_TEXTURE_PALETTE_EXT 0x81FB
+#endif
+
+#ifndef GL_EXT_separate_specular_color
+#define GL_LIGHT_MODEL_COLOR_CONTROL_EXT 0x81F8
+#define GL_SINGLE_COLOR_EXT 0x81F9
+#define GL_SEPARATE_SPECULAR_COLOR_EXT 0x81FA
+#endif
+
+#ifndef GL_EXT_secondary_color
+#define GL_COLOR_SUM_EXT 0x8458
+#define GL_CURRENT_SECONDARY_COLOR_EXT 0x8459
+#define GL_SECONDARY_COLOR_ARRAY_SIZE_EXT 0x845A
+#define GL_SECONDARY_COLOR_ARRAY_TYPE_EXT 0x845B
+#define GL_SECONDARY_COLOR_ARRAY_STRIDE_EXT 0x845C
+#define GL_SECONDARY_COLOR_ARRAY_POINTER_EXT 0x845D
+#define GL_SECONDARY_COLOR_ARRAY_EXT 0x845E
+#endif
+
+#ifndef GL_EXT_texture_perturb_normal
+#define GL_PERTURB_EXT 0x85AE
+#define GL_TEXTURE_NORMAL_EXT 0x85AF
+#endif
+
+#ifndef GL_EXT_multi_draw_arrays
+#endif
+
+#ifndef GL_EXT_fog_coord
+#define GL_FOG_COORDINATE_SOURCE_EXT 0x8450
+#define GL_FOG_COORDINATE_EXT 0x8451
+#define GL_FRAGMENT_DEPTH_EXT 0x8452
+#define GL_CURRENT_FOG_COORDINATE_EXT 0x8453
+#define GL_FOG_COORDINATE_ARRAY_TYPE_EXT 0x8454
+#define GL_FOG_COORDINATE_ARRAY_STRIDE_EXT 0x8455
+#define GL_FOG_COORDINATE_ARRAY_POINTER_EXT 0x8456
+#define GL_FOG_COORDINATE_ARRAY_EXT 0x8457
+#endif
+
+#ifndef GL_REND_screen_coordinates
+#define GL_SCREEN_COORDINATES_REND 0x8490
+#define GL_INVERTED_SCREEN_W_REND 0x8491
+#endif
+
+#ifndef GL_EXT_coordinate_frame
+#define GL_TANGENT_ARRAY_EXT 0x8439
+#define GL_BINORMAL_ARRAY_EXT 0x843A
+#define GL_CURRENT_TANGENT_EXT 0x843B
+#define GL_CURRENT_BINORMAL_EXT 0x843C
+#define GL_TANGENT_ARRAY_TYPE_EXT 0x843E
+#define GL_TANGENT_ARRAY_STRIDE_EXT 0x843F
+#define GL_BINORMAL_ARRAY_TYPE_EXT 0x8440
+#define GL_BINORMAL_ARRAY_STRIDE_EXT 0x8441
+#define GL_TANGENT_ARRAY_POINTER_EXT 0x8442
+#define GL_BINORMAL_ARRAY_POINTER_EXT 0x8443
+#define GL_MAP1_TANGENT_EXT 0x8444
+#define GL_MAP2_TANGENT_EXT 0x8445
+#define GL_MAP1_BINORMAL_EXT 0x8446
+#define GL_MAP2_BINORMAL_EXT 0x8447
+#endif
+
+#ifndef GL_EXT_texture_env_combine
+#define GL_COMBINE_EXT 0x8570
+#define GL_COMBINE_RGB_EXT 0x8571
+#define GL_COMBINE_ALPHA_EXT 0x8572
+#define GL_RGB_SCALE_EXT 0x8573
+#define GL_ADD_SIGNED_EXT 0x8574
+#define GL_INTERPOLATE_EXT 0x8575
+#define GL_CONSTANT_EXT 0x8576
+#define GL_PRIMARY_COLOR_EXT 0x8577
+#define GL_PREVIOUS_EXT 0x8578
+#define GL_SOURCE0_RGB_EXT 0x8580
+#define GL_SOURCE1_RGB_EXT 0x8581
+#define GL_SOURCE2_RGB_EXT 0x8582
+#define GL_SOURCE0_ALPHA_EXT 0x8588
+#define GL_SOURCE1_ALPHA_EXT 0x8589
+#define GL_SOURCE2_ALPHA_EXT 0x858A
+#define GL_OPERAND0_RGB_EXT 0x8590
+#define GL_OPERAND1_RGB_EXT 0x8591
+#define GL_OPERAND2_RGB_EXT 0x8592
+#define GL_OPERAND0_ALPHA_EXT 0x8598
+#define GL_OPERAND1_ALPHA_EXT 0x8599
+#define GL_OPERAND2_ALPHA_EXT 0x859A
+#endif
+
+#ifndef GL_APPLE_specular_vector
+#define GL_LIGHT_MODEL_SPECULAR_VECTOR_APPLE 0x85B0
+#endif
+
+#ifndef GL_APPLE_transform_hint
+#define GL_TRANSFORM_HINT_APPLE 0x85B1
+#endif
+
+#ifndef GL_SGIX_fog_scale
+#define GL_FOG_SCALE_SGIX 0x81FC
+#define GL_FOG_SCALE_VALUE_SGIX 0x81FD
+#endif
+
+#ifndef GL_SUNX_constant_data
+#define GL_UNPACK_CONSTANT_DATA_SUNX 0x81D5
+#define GL_TEXTURE_CONSTANT_DATA_SUNX 0x81D6
+#endif
+
+#ifndef GL_SUN_global_alpha
+#define GL_GLOBAL_ALPHA_SUN 0x81D9
+#define GL_GLOBAL_ALPHA_FACTOR_SUN 0x81DA
+#endif
+
+#ifndef GL_SUN_triangle_list
+#define GL_RESTART_SUN 0x0001
+#define GL_REPLACE_MIDDLE_SUN 0x0002
+#define GL_REPLACE_OLDEST_SUN 0x0003
+#define GL_TRIANGLE_LIST_SUN 0x81D7
+#define GL_REPLACEMENT_CODE_SUN 0x81D8
+#define GL_REPLACEMENT_CODE_ARRAY_SUN 0x85C0
+#define GL_REPLACEMENT_CODE_ARRAY_TYPE_SUN 0x85C1
+#define GL_REPLACEMENT_CODE_ARRAY_STRIDE_SUN 0x85C2
+#define GL_REPLACEMENT_CODE_ARRAY_POINTER_SUN 0x85C3
+#define GL_R1UI_V3F_SUN 0x85C4
+#define GL_R1UI_C4UB_V3F_SUN 0x85C5
+#define GL_R1UI_C3F_V3F_SUN 0x85C6
+#define GL_R1UI_N3F_V3F_SUN 0x85C7
+#define GL_R1UI_C4F_N3F_V3F_SUN 0x85C8
+#define GL_R1UI_T2F_V3F_SUN 0x85C9
+#define GL_R1UI_T2F_N3F_V3F_SUN 0x85CA
+#define GL_R1UI_T2F_C4F_N3F_V3F_SUN 0x85CB
+#endif
+
+#ifndef GL_SUN_vertex
+#endif
+
+#ifndef GL_EXT_blend_func_separate
+#define GL_BLEND_DST_RGB_EXT 0x80C8
+#define GL_BLEND_SRC_RGB_EXT 0x80C9
+#define GL_BLEND_DST_ALPHA_EXT 0x80CA
+#define GL_BLEND_SRC_ALPHA_EXT 0x80CB
+#endif
+
+#ifndef GL_INGR_color_clamp
+#define GL_RED_MIN_CLAMP_INGR 0x8560
+#define GL_GREEN_MIN_CLAMP_INGR 0x8561
+#define GL_BLUE_MIN_CLAMP_INGR 0x8562
+#define GL_ALPHA_MIN_CLAMP_INGR 0x8563
+#define GL_RED_MAX_CLAMP_INGR 0x8564
+#define GL_GREEN_MAX_CLAMP_INGR 0x8565
+#define GL_BLUE_MAX_CLAMP_INGR 0x8566
+#define GL_ALPHA_MAX_CLAMP_INGR 0x8567
+#endif
+
+#ifndef GL_INGR_interlace_read
+#define GL_INTERLACE_READ_INGR 0x8568
+#endif
+
+#ifndef GL_EXT_stencil_wrap
+#define GL_INCR_WRAP_EXT 0x8507
+#define GL_DECR_WRAP_EXT 0x8508
+#endif
+
+#ifndef GL_EXT_422_pixels
+#define GL_422_EXT 0x80CC
+#define GL_422_REV_EXT 0x80CD
+#define GL_422_AVERAGE_EXT 0x80CE
+#define GL_422_REV_AVERAGE_EXT 0x80CF
+#endif
+
+#ifndef GL_NV_texgen_reflection
+#define GL_NORMAL_MAP_NV 0x8511
+#define GL_REFLECTION_MAP_NV 0x8512
+#endif
+
+#ifndef GL_EXT_texture_cube_map
+#define GL_NORMAL_MAP_EXT 0x8511
+#define GL_REFLECTION_MAP_EXT 0x8512
+#define GL_TEXTURE_CUBE_MAP_EXT 0x8513
+#define GL_TEXTURE_BINDING_CUBE_MAP_EXT 0x8514
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_X_EXT 0x8515
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_X_EXT 0x8516
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_Y_EXT 0x8517
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_EXT 0x8518
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z_EXT 0x8519
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_EXT 0x851A
+#define GL_PROXY_TEXTURE_CUBE_MAP_EXT 0x851B
+#define GL_MAX_CUBE_MAP_TEXTURE_SIZE_EXT 0x851C
+#endif
+
+#ifndef GL_SUN_convolution_border_modes
+#define GL_WRAP_BORDER_SUN 0x81D4
+#endif
+
+#ifndef GL_EXT_texture_env_add
+#endif
+
+#ifndef GL_EXT_texture_lod_bias
+#define GL_MAX_TEXTURE_LOD_BIAS_EXT 0x84FD
+#define GL_TEXTURE_FILTER_CONTROL_EXT 0x8500
+#define GL_TEXTURE_LOD_BIAS_EXT 0x8501
+#endif
+
+#ifndef GL_EXT_texture_filter_anisotropic
+#define GL_TEXTURE_MAX_ANISOTROPY_EXT 0x84FE
+#define GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT 0x84FF
+#endif
+
+#ifndef GL_EXT_vertex_weighting
+#define GL_MODELVIEW0_STACK_DEPTH_EXT GL_MODELVIEW_STACK_DEPTH
+#define GL_MODELVIEW1_STACK_DEPTH_EXT 0x8502
+#define GL_MODELVIEW0_MATRIX_EXT GL_MODELVIEW_MATRIX
+#define GL_MODELVIEW1_MATRIX_EXT 0x8506
+#define GL_VERTEX_WEIGHTING_EXT 0x8509
+#define GL_MODELVIEW0_EXT GL_MODELVIEW
+#define GL_MODELVIEW1_EXT 0x850A
+#define GL_CURRENT_VERTEX_WEIGHT_EXT 0x850B
+#define GL_VERTEX_WEIGHT_ARRAY_EXT 0x850C
+#define GL_VERTEX_WEIGHT_ARRAY_SIZE_EXT 0x850D
+#define GL_VERTEX_WEIGHT_ARRAY_TYPE_EXT 0x850E
+#define GL_VERTEX_WEIGHT_ARRAY_STRIDE_EXT 0x850F
+#define GL_VERTEX_WEIGHT_ARRAY_POINTER_EXT 0x8510
+#endif
+
+#ifndef GL_NV_light_max_exponent
+#define GL_MAX_SHININESS_NV 0x8504
+#define GL_MAX_SPOT_EXPONENT_NV 0x8505
+#endif
+
+#ifndef GL_NV_vertex_array_range
+#define GL_VERTEX_ARRAY_RANGE_NV 0x851D
+#define GL_VERTEX_ARRAY_RANGE_LENGTH_NV 0x851E
+#define GL_VERTEX_ARRAY_RANGE_VALID_NV 0x851F
+#define GL_MAX_VERTEX_ARRAY_RANGE_ELEMENT_NV 0x8520
+#define GL_VERTEX_ARRAY_RANGE_POINTER_NV 0x8521
+#endif
+
+#ifndef GL_NV_register_combiners
+#define GL_REGISTER_COMBINERS_NV 0x8522
+#define GL_VARIABLE_A_NV 0x8523
+#define GL_VARIABLE_B_NV 0x8524
+#define GL_VARIABLE_C_NV 0x8525
+#define GL_VARIABLE_D_NV 0x8526
+#define GL_VARIABLE_E_NV 0x8527
+#define GL_VARIABLE_F_NV 0x8528
+#define GL_VARIABLE_G_NV 0x8529
+#define GL_CONSTANT_COLOR0_NV 0x852A
+#define GL_CONSTANT_COLOR1_NV 0x852B
+#define GL_PRIMARY_COLOR_NV 0x852C
+#define GL_SECONDARY_COLOR_NV 0x852D
+#define GL_SPARE0_NV 0x852E
+#define GL_SPARE1_NV 0x852F
+#define GL_DISCARD_NV 0x8530
+#define GL_E_TIMES_F_NV 0x8531
+#define GL_SPARE0_PLUS_SECONDARY_COLOR_NV 0x8532
+#define GL_UNSIGNED_IDENTITY_NV 0x8536
+#define GL_UNSIGNED_INVERT_NV 0x8537
+#define GL_EXPAND_NORMAL_NV 0x8538
+#define GL_EXPAND_NEGATE_NV 0x8539
+#define GL_HALF_BIAS_NORMAL_NV 0x853A
+#define GL_HALF_BIAS_NEGATE_NV 0x853B
+#define GL_SIGNED_IDENTITY_NV 0x853C
+#define GL_SIGNED_NEGATE_NV 0x853D
+#define GL_SCALE_BY_TWO_NV 0x853E
+#define GL_SCALE_BY_FOUR_NV 0x853F
+#define GL_SCALE_BY_ONE_HALF_NV 0x8540
+#define GL_BIAS_BY_NEGATIVE_ONE_HALF_NV 0x8541
+#define GL_COMBINER_INPUT_NV 0x8542
+#define GL_COMBINER_MAPPING_NV 0x8543
+#define GL_COMBINER_COMPONENT_USAGE_NV 0x8544
+#define GL_COMBINER_AB_DOT_PRODUCT_NV 0x8545
+#define GL_COMBINER_CD_DOT_PRODUCT_NV 0x8546
+#define GL_COMBINER_MUX_SUM_NV 0x8547
+#define GL_COMBINER_SCALE_NV 0x8548
+#define GL_COMBINER_BIAS_NV 0x8549
+#define GL_COMBINER_AB_OUTPUT_NV 0x854A
+#define GL_COMBINER_CD_OUTPUT_NV 0x854B
+#define GL_COMBINER_SUM_OUTPUT_NV 0x854C
+#define GL_MAX_GENERAL_COMBINERS_NV 0x854D
+#define GL_NUM_GENERAL_COMBINERS_NV 0x854E
+#define GL_COLOR_SUM_CLAMP_NV 0x854F
+#define GL_COMBINER0_NV 0x8550
+#define GL_COMBINER1_NV 0x8551
+#define GL_COMBINER2_NV 0x8552
+#define GL_COMBINER3_NV 0x8553
+#define GL_COMBINER4_NV 0x8554
+#define GL_COMBINER5_NV 0x8555
+#define GL_COMBINER6_NV 0x8556
+#define GL_COMBINER7_NV 0x8557
+
+#endif
+
+#ifndef GL_NV_fog_distance
+#define GL_FOG_DISTANCE_MODE_NV 0x855A
+#define GL_EYE_RADIAL_NV 0x855B
+#define GL_EYE_PLANE_ABSOLUTE_NV 0x855C
+
+#endif
+
+#ifndef GL_NV_texgen_emboss
+#define GL_EMBOSS_LIGHT_NV 0x855D
+#define GL_EMBOSS_CONSTANT_NV 0x855E
+#define GL_EMBOSS_MAP_NV 0x855F
+#endif
+
+#ifndef GL_NV_blend_square
+#endif
+
+#ifndef GL_NV_texture_env_combine4
+#define GL_COMBINE4_NV 0x8503
+#define GL_SOURCE3_RGB_NV 0x8583
+#define GL_SOURCE3_ALPHA_NV 0x858B
+#define GL_OPERAND3_RGB_NV 0x8593
+#define GL_OPERAND3_ALPHA_NV 0x859B
+#endif
+
+#ifndef GL_MESA_resize_buffers
+#endif
+
+#ifndef GL_MESA_window_pos
+#endif
+
+#ifndef GL_EXT_texture_compression_s3tc
+#define GL_COMPRESSED_RGB_S3TC_DXT1_EXT 0x83F0
+#define GL_COMPRESSED_RGBA_S3TC_DXT1_EXT 0x83F1
+#define GL_COMPRESSED_RGBA_S3TC_DXT3_EXT 0x83F2
+#define GL_COMPRESSED_RGBA_S3TC_DXT5_EXT 0x83F3
+#endif
+
+#ifndef GL_IBM_cull_vertex
+#define GL_CULL_VERTEX_IBM 103050
+#endif
+
+#ifndef GL_IBM_multimode_draw_arrays
+#endif
+
+#ifndef GL_IBM_vertex_array_lists
+#define GL_VERTEX_ARRAY_LIST_IBM 103070
+#define GL_NORMAL_ARRAY_LIST_IBM 103071
+#define GL_COLOR_ARRAY_LIST_IBM 103072
+#define GL_INDEX_ARRAY_LIST_IBM 103073
+#define GL_TEXTURE_COORD_ARRAY_LIST_IBM 103074
+#define GL_EDGE_FLAG_ARRAY_LIST_IBM 103075
+#define GL_FOG_COORDINATE_ARRAY_LIST_IBM 103076
+#define GL_SECONDARY_COLOR_ARRAY_LIST_IBM 103077
+#define GL_VERTEX_ARRAY_LIST_STRIDE_IBM 103080
+#define GL_NORMAL_ARRAY_LIST_STRIDE_IBM 103081
+#define GL_COLOR_ARRAY_LIST_STRIDE_IBM 103082
+#define GL_INDEX_ARRAY_LIST_STRIDE_IBM 103083
+#define GL_TEXTURE_COORD_ARRAY_LIST_STRIDE_IBM 103084
+#define GL_EDGE_FLAG_ARRAY_LIST_STRIDE_IBM 103085
+#define GL_FOG_COORDINATE_ARRAY_LIST_STRIDE_IBM 103086
+#define GL_SECONDARY_COLOR_ARRAY_LIST_STRIDE_IBM 103087
+#endif
+
+#ifndef GL_SGIX_subsample
+#define GL_PACK_SUBSAMPLE_RATE_SGIX 0x85A0
+#define GL_UNPACK_SUBSAMPLE_RATE_SGIX 0x85A1
+#define GL_PIXEL_SUBSAMPLE_4444_SGIX 0x85A2
+#define GL_PIXEL_SUBSAMPLE_2424_SGIX 0x85A3
+#define GL_PIXEL_SUBSAMPLE_4242_SGIX 0x85A4
+#endif
+
+#ifndef GL_SGIX_ycrcb_subsample
+#endif
+
+#ifndef GL_SGIX_ycrcba
+#define GL_YCRCB_SGIX 0x8318
+#define GL_YCRCBA_SGIX 0x8319
+#endif
+
+#ifndef GL_SGI_depth_pass_instrument
+#define GL_DEPTH_PASS_INSTRUMENT_SGIX 0x8310
+#define GL_DEPTH_PASS_INSTRUMENT_COUNTERS_SGIX 0x8311
+#define GL_DEPTH_PASS_INSTRUMENT_MAX_SGIX 0x8312
+#endif
+
+#ifndef GL_3DFX_texture_compression_FXT1
+#define GL_COMPRESSED_RGB_FXT1_3DFX 0x86B0
+#define GL_COMPRESSED_RGBA_FXT1_3DFX 0x86B1
+#endif
+
+#ifndef GL_3DFX_multisample
+#define GL_MULTISAMPLE_3DFX 0x86B2
+#define GL_SAMPLE_BUFFERS_3DFX 0x86B3
+#define GL_SAMPLES_3DFX 0x86B4
+#define GL_MULTISAMPLE_BIT_3DFX 0x20000000
+#endif
+
+#ifndef GL_3DFX_tbuffer
+#endif
+
+#ifndef GL_EXT_multisample
+#define GL_MULTISAMPLE_EXT 0x809D
+#define GL_SAMPLE_ALPHA_TO_MASK_EXT 0x809E
+#define GL_SAMPLE_ALPHA_TO_ONE_EXT 0x809F
+#define GL_SAMPLE_MASK_EXT 0x80A0
+#define GL_1PASS_EXT 0x80A1
+#define GL_2PASS_0_EXT 0x80A2
+#define GL_2PASS_1_EXT 0x80A3
+#define GL_4PASS_0_EXT 0x80A4
+#define GL_4PASS_1_EXT 0x80A5
+#define GL_4PASS_2_EXT 0x80A6
+#define GL_4PASS_3_EXT 0x80A7
+#define GL_SAMPLE_BUFFERS_EXT 0x80A8
+#define GL_SAMPLES_EXT 0x80A9
+#define GL_SAMPLE_MASK_VALUE_EXT 0x80AA
+#define GL_SAMPLE_MASK_INVERT_EXT 0x80AB
+#define GL_SAMPLE_PATTERN_EXT 0x80AC
+#define GL_MULTISAMPLE_BIT_EXT 0x20000000
+#endif
+
+#ifndef GL_SGIX_vertex_preclip
+#define GL_VERTEX_PRECLIP_SGIX 0x83EE
+#define GL_VERTEX_PRECLIP_HINT_SGIX 0x83EF
+#endif
+
+#ifndef GL_SGIX_convolution_accuracy
+#define GL_CONVOLUTION_HINT_SGIX 0x8316
+#endif
+
+#ifndef GL_SGIX_resample
+#define GL_PACK_RESAMPLE_SGIX 0x842C
+#define GL_UNPACK_RESAMPLE_SGIX 0x842D
+#define GL_RESAMPLE_REPLICATE_SGIX 0x842E
+#define GL_RESAMPLE_ZERO_FILL_SGIX 0x842F
+#define GL_RESAMPLE_DECIMATE_SGIX 0x8430
+#endif
+
+#ifndef GL_SGIS_point_line_texgen
+#define GL_EYE_DISTANCE_TO_POINT_SGIS 0x81F0
+#define GL_OBJECT_DISTANCE_TO_POINT_SGIS 0x81F1
+#define GL_EYE_DISTANCE_TO_LINE_SGIS 0x81F2
+#define GL_OBJECT_DISTANCE_TO_LINE_SGIS 0x81F3
+#define GL_EYE_POINT_SGIS 0x81F4
+#define GL_OBJECT_POINT_SGIS 0x81F5
+#define GL_EYE_LINE_SGIS 0x81F6
+#define GL_OBJECT_LINE_SGIS 0x81F7
+#endif
+
+#ifndef GL_SGIS_texture_color_mask
+#define GL_TEXTURE_COLOR_WRITEMASK_SGIS 0x81EF
+#endif
+
+#ifndef GL_EXT_texture_env_dot3
+#define GL_DOT3_RGB_EXT 0x8740
+#define GL_DOT3_RGBA_EXT 0x8741
+#endif
+
+#ifndef GL_ATI_texture_mirror_once
+#define GL_MIRROR_CLAMP_ATI 0x8742
+#define GL_MIRROR_CLAMP_TO_EDGE_ATI 0x8743
+#endif
+
+#ifndef GL_NV_fence
+#define GL_ALL_COMPLETED_NV 0x84F2
+#define GL_FENCE_STATUS_NV 0x84F3
+#define GL_FENCE_CONDITION_NV 0x84F4
+#endif
+
+#ifndef GL_IBM_texture_mirrored_repeat
+#define GL_MIRRORED_REPEAT_IBM 0x8370
+#endif
+
+#ifndef GL_NV_evaluators
+#define GL_EVAL_2D_NV 0x86C0
+#define GL_EVAL_TRIANGULAR_2D_NV 0x86C1
+#define GL_MAP_TESSELLATION_NV 0x86C2
+#define GL_MAP_ATTRIB_U_ORDER_NV 0x86C3
+#define GL_MAP_ATTRIB_V_ORDER_NV 0x86C4
+#define GL_EVAL_FRACTIONAL_TESSELLATION_NV 0x86C5
+#define GL_EVAL_VERTEX_ATTRIB0_NV 0x86C6
+#define GL_EVAL_VERTEX_ATTRIB1_NV 0x86C7
+#define GL_EVAL_VERTEX_ATTRIB2_NV 0x86C8
+#define GL_EVAL_VERTEX_ATTRIB3_NV 0x86C9
+#define GL_EVAL_VERTEX_ATTRIB4_NV 0x86CA
+#define GL_EVAL_VERTEX_ATTRIB5_NV 0x86CB
+#define GL_EVAL_VERTEX_ATTRIB6_NV 0x86CC
+#define GL_EVAL_VERTEX_ATTRIB7_NV 0x86CD
+#define GL_EVAL_VERTEX_ATTRIB8_NV 0x86CE
+#define GL_EVAL_VERTEX_ATTRIB9_NV 0x86CF
+#define GL_EVAL_VERTEX_ATTRIB10_NV 0x86D0
+#define GL_EVAL_VERTEX_ATTRIB11_NV 0x86D1
+#define GL_EVAL_VERTEX_ATTRIB12_NV 0x86D2
+#define GL_EVAL_VERTEX_ATTRIB13_NV 0x86D3
+#define GL_EVAL_VERTEX_ATTRIB14_NV 0x86D4
+#define GL_EVAL_VERTEX_ATTRIB15_NV 0x86D5
+#define GL_MAX_MAP_TESSELLATION_NV 0x86D6
+#define GL_MAX_RATIONAL_EVAL_ORDER_NV 0x86D7
+#endif
+
+#ifndef GL_NV_packed_depth_stencil
+#define GL_DEPTH_STENCIL_NV 0x84F9
+#define GL_UNSIGNED_INT_24_8_NV 0x84FA
+#endif
+
+#ifndef GL_NV_register_combiners2
+#define GL_PER_STAGE_CONSTANTS_NV 0x8535
+#endif
+
+#ifndef GL_NV_texture_compression_vtc
+#endif
+
+#ifndef GL_NV_texture_rectangle
+#define GL_TEXTURE_RECTANGLE_NV 0x84F5
+#define GL_TEXTURE_BINDING_RECTANGLE_NV 0x84F6
+#define GL_PROXY_TEXTURE_RECTANGLE_NV 0x84F7
+#define GL_MAX_RECTANGLE_TEXTURE_SIZE_NV 0x84F8
+#endif
+
+#ifndef GL_NV_texture_shader
+#define GL_OFFSET_TEXTURE_RECTANGLE_NV 0x864C
+#define GL_OFFSET_TEXTURE_RECTANGLE_SCALE_NV 0x864D
+#define GL_DOT_PRODUCT_TEXTURE_RECTANGLE_NV 0x864E
+#define GL_RGBA_UNSIGNED_DOT_PRODUCT_MAPPING_NV 0x86D9
+#define GL_UNSIGNED_INT_S8_S8_8_8_NV 0x86DA
+#define GL_UNSIGNED_INT_8_8_S8_S8_REV_NV 0x86DB
+#define GL_DSDT_MAG_INTENSITY_NV 0x86DC
+#define GL_SHADER_CONSISTENT_NV 0x86DD
+#define GL_TEXTURE_SHADER_NV 0x86DE
+#define GL_SHADER_OPERATION_NV 0x86DF
+#define GL_CULL_MODES_NV 0x86E0
+#define GL_OFFSET_TEXTURE_MATRIX_NV 0x86E1
+#define GL_OFFSET_TEXTURE_SCALE_NV 0x86E2
+#define GL_OFFSET_TEXTURE_BIAS_NV 0x86E3
+#define GL_OFFSET_TEXTURE_2D_MATRIX_NV GL_OFFSET_TEXTURE_MATRIX_NV
+#define GL_OFFSET_TEXTURE_2D_SCALE_NV GL_OFFSET_TEXTURE_SCALE_NV
+#define GL_OFFSET_TEXTURE_2D_BIAS_NV GL_OFFSET_TEXTURE_BIAS_NV
+#define GL_PREVIOUS_TEXTURE_INPUT_NV 0x86E4
+#define GL_CONST_EYE_NV 0x86E5
+#define GL_PASS_THROUGH_NV 0x86E6
+#define GL_CULL_FRAGMENT_NV 0x86E7
+#define GL_OFFSET_TEXTURE_2D_NV 0x86E8
+#define GL_DEPENDENT_AR_TEXTURE_2D_NV 0x86E9
+#define GL_DEPENDENT_GB_TEXTURE_2D_NV 0x86EA
+#define GL_DOT_PRODUCT_NV 0x86EC
+#define GL_DOT_PRODUCT_DEPTH_REPLACE_NV 0x86ED
+#define GL_DOT_PRODUCT_TEXTURE_2D_NV 0x86EE
+#define GL_DOT_PRODUCT_TEXTURE_CUBE_MAP_NV 0x86F0
+#define GL_DOT_PRODUCT_DIFFUSE_CUBE_MAP_NV 0x86F1
+#define GL_DOT_PRODUCT_REFLECT_CUBE_MAP_NV 0x86F2
+#define GL_DOT_PRODUCT_CONST_EYE_REFLECT_CUBE_MAP_NV 0x86F3
+#define GL_HILO_NV 0x86F4
+#define GL_DSDT_NV 0x86F5
+#define GL_DSDT_MAG_NV 0x86F6
+#define GL_DSDT_MAG_VIB_NV 0x86F7
+#define GL_HILO16_NV 0x86F8
+#define GL_SIGNED_HILO_NV 0x86F9
+#define GL_SIGNED_HILO16_NV 0x86FA
+#define GL_SIGNED_RGBA_NV 0x86FB
+#define GL_SIGNED_RGBA8_NV 0x86FC
+#define GL_SIGNED_RGB_NV 0x86FE
+#define GL_SIGNED_RGB8_NV 0x86FF
+#define GL_SIGNED_LUMINANCE_NV 0x8701
+#define GL_SIGNED_LUMINANCE8_NV 0x8702
+#define GL_SIGNED_LUMINANCE_ALPHA_NV 0x8703
+#define GL_SIGNED_LUMINANCE8_ALPHA8_NV 0x8704
+#define GL_SIGNED_ALPHA_NV 0x8705
+#define GL_SIGNED_ALPHA8_NV 0x8706
+#define GL_SIGNED_INTENSITY_NV 0x8707
+#define GL_SIGNED_INTENSITY8_NV 0x8708
+#define GL_DSDT8_NV 0x8709
+#define GL_DSDT8_MAG8_NV 0x870A
+#define GL_DSDT8_MAG8_INTENSITY8_NV 0x870B
+#define GL_SIGNED_RGB_UNSIGNED_ALPHA_NV 0x870C
+#define GL_SIGNED_RGB8_UNSIGNED_ALPHA8_NV 0x870D
+#define GL_HI_SCALE_NV 0x870E
+#define GL_LO_SCALE_NV 0x870F
+#define GL_DS_SCALE_NV 0x8710
+#define GL_DT_SCALE_NV 0x8711
+#define GL_MAGNITUDE_SCALE_NV 0x8712
+#define GL_VIBRANCE_SCALE_NV 0x8713
+#define GL_HI_BIAS_NV 0x8714
+#define GL_LO_BIAS_NV 0x8715
+#define GL_DS_BIAS_NV 0x8716
+#define GL_DT_BIAS_NV 0x8717
+#define GL_MAGNITUDE_BIAS_NV 0x8718
+#define GL_VIBRANCE_BIAS_NV 0x8719
+#define GL_TEXTURE_BORDER_VALUES_NV 0x871A
+#define GL_TEXTURE_HI_SIZE_NV 0x871B
+#define GL_TEXTURE_LO_SIZE_NV 0x871C
+#define GL_TEXTURE_DS_SIZE_NV 0x871D
+#define GL_TEXTURE_DT_SIZE_NV 0x871E
+#define GL_TEXTURE_MAG_SIZE_NV 0x871F
+#endif
+
+#ifndef GL_NV_texture_shader2
+#define GL_DOT_PRODUCT_TEXTURE_3D_NV 0x86EF
+#endif
+
+#ifndef GL_NV_vertex_array_range2
+#define GL_VERTEX_ARRAY_RANGE_WITHOUT_FLUSH_NV 0x8533
+#endif
+
+#ifndef GL_NV_vertex_program
+#define GL_VERTEX_PROGRAM_NV 0x8620
+#define GL_VERTEX_STATE_PROGRAM_NV 0x8621
+#define GL_ATTRIB_ARRAY_SIZE_NV 0x8623
+#define GL_ATTRIB_ARRAY_STRIDE_NV 0x8624
+#define GL_ATTRIB_ARRAY_TYPE_NV 0x8625
+#define GL_CURRENT_ATTRIB_NV 0x8626
+#define GL_PROGRAM_LENGTH_NV 0x8627
+#define GL_PROGRAM_STRING_NV 0x8628
+#define GL_MODELVIEW_PROJECTION_NV 0x8629
+#define GL_IDENTITY_NV 0x862A
+#define GL_INVERSE_NV 0x862B
+#define GL_TRANSPOSE_NV 0x862C
+#define GL_INVERSE_TRANSPOSE_NV 0x862D
+#define GL_MAX_TRACK_MATRIX_STACK_DEPTH_NV 0x862E
+#define GL_MAX_TRACK_MATRICES_NV 0x862F
+#define GL_MATRIX0_NV 0x8630
+#define GL_MATRIX1_NV 0x8631
+#define GL_MATRIX2_NV 0x8632
+#define GL_MATRIX3_NV 0x8633
+#define GL_MATRIX4_NV 0x8634
+#define GL_MATRIX5_NV 0x8635
+#define GL_MATRIX6_NV 0x8636
+#define GL_MATRIX7_NV 0x8637
+#define GL_CURRENT_MATRIX_STACK_DEPTH_NV 0x8640
+#define GL_CURRENT_MATRIX_NV 0x8641
+#define GL_VERTEX_PROGRAM_POINT_SIZE_NV 0x8642
+#define GL_VERTEX_PROGRAM_TWO_SIDE_NV 0x8643
+#define GL_PROGRAM_PARAMETER_NV 0x8644
+#define GL_ATTRIB_ARRAY_POINTER_NV 0x8645
+#define GL_PROGRAM_TARGET_NV 0x8646
+#define GL_PROGRAM_RESIDENT_NV 0x8647
+#define GL_TRACK_MATRIX_NV 0x8648
+#define GL_TRACK_MATRIX_TRANSFORM_NV 0x8649
+#define GL_VERTEX_PROGRAM_BINDING_NV 0x864A
+#define GL_PROGRAM_ERROR_POSITION_NV 0x864B
+#define GL_VERTEX_ATTRIB_ARRAY0_NV 0x8650
+#define GL_VERTEX_ATTRIB_ARRAY1_NV 0x8651
+#define GL_VERTEX_ATTRIB_ARRAY2_NV 0x8652
+#define GL_VERTEX_ATTRIB_ARRAY3_NV 0x8653
+#define GL_VERTEX_ATTRIB_ARRAY4_NV 0x8654
+#define GL_VERTEX_ATTRIB_ARRAY5_NV 0x8655
+#define GL_VERTEX_ATTRIB_ARRAY6_NV 0x8656
+#define GL_VERTEX_ATTRIB_ARRAY7_NV 0x8657
+#define GL_VERTEX_ATTRIB_ARRAY8_NV 0x8658
+#define GL_VERTEX_ATTRIB_ARRAY9_NV 0x8659
+#define GL_VERTEX_ATTRIB_ARRAY10_NV 0x865A
+#define GL_VERTEX_ATTRIB_ARRAY11_NV 0x865B
+#define GL_VERTEX_ATTRIB_ARRAY12_NV 0x865C
+#define GL_VERTEX_ATTRIB_ARRAY13_NV 0x865D
+#define GL_VERTEX_ATTRIB_ARRAY14_NV 0x865E
+#define GL_VERTEX_ATTRIB_ARRAY15_NV 0x865F
+#define GL_MAP1_VERTEX_ATTRIB0_4_NV 0x8660
+#define GL_MAP1_VERTEX_ATTRIB1_4_NV 0x8661
+#define GL_MAP1_VERTEX_ATTRIB2_4_NV 0x8662
+#define GL_MAP1_VERTEX_ATTRIB3_4_NV 0x8663
+#define GL_MAP1_VERTEX_ATTRIB4_4_NV 0x8664
+#define GL_MAP1_VERTEX_ATTRIB5_4_NV 0x8665
+#define GL_MAP1_VERTEX_ATTRIB6_4_NV 0x8666
+#define GL_MAP1_VERTEX_ATTRIB7_4_NV 0x8667
+#define GL_MAP1_VERTEX_ATTRIB8_4_NV 0x8668
+#define GL_MAP1_VERTEX_ATTRIB9_4_NV 0x8669
+#define GL_MAP1_VERTEX_ATTRIB10_4_NV 0x866A
+#define GL_MAP1_VERTEX_ATTRIB11_4_NV 0x866B
+#define GL_MAP1_VERTEX_ATTRIB12_4_NV 0x866C
+#define GL_MAP1_VERTEX_ATTRIB13_4_NV 0x866D
+#define GL_MAP1_VERTEX_ATTRIB14_4_NV 0x866E
+#define GL_MAP1_VERTEX_ATTRIB15_4_NV 0x866F
+#define GL_MAP2_VERTEX_ATTRIB0_4_NV 0x8670
+#define GL_MAP2_VERTEX_ATTRIB1_4_NV 0x8671
+#define GL_MAP2_VERTEX_ATTRIB2_4_NV 0x8672
+#define GL_MAP2_VERTEX_ATTRIB3_4_NV 0x8673
+#define GL_MAP2_VERTEX_ATTRIB4_4_NV 0x8674
+#define GL_MAP2_VERTEX_ATTRIB5_4_NV 0x8675
+#define GL_MAP2_VERTEX_ATTRIB6_4_NV 0x8676
+#define GL_MAP2_VERTEX_ATTRIB7_4_NV 0x8677
+#define GL_MAP2_VERTEX_ATTRIB8_4_NV 0x8678
+#define GL_MAP2_VERTEX_ATTRIB9_4_NV 0x8679
+#define GL_MAP2_VERTEX_ATTRIB10_4_NV 0x867A
+#define GL_MAP2_VERTEX_ATTRIB11_4_NV 0x867B
+#define GL_MAP2_VERTEX_ATTRIB12_4_NV 0x867C
+#define GL_MAP2_VERTEX_ATTRIB13_4_NV 0x867D
+#define GL_MAP2_VERTEX_ATTRIB14_4_NV 0x867E
+#define GL_MAP2_VERTEX_ATTRIB15_4_NV 0x867F
+#endif
+
+#ifndef GL_SGIX_texture_coordinate_clamp
+#define GL_TEXTURE_MAX_CLAMP_S_SGIX 0x8369
+#define GL_TEXTURE_MAX_CLAMP_T_SGIX 0x836A
+#define GL_TEXTURE_MAX_CLAMP_R_SGIX 0x836B
+#endif
+
+#ifndef GL_SGIX_scalebias_hint
+#define GL_SCALEBIAS_HINT_SGIX 0x8322
+#endif
+
+#ifndef GL_OML_interlace
+#define GL_INTERLACE_OML 0x8980
+#define GL_INTERLACE_READ_OML 0x8981
+#endif
+
+#ifndef GL_OML_subsample
+#define GL_FORMAT_SUBSAMPLE_24_24_OML 0x8982
+#define GL_FORMAT_SUBSAMPLE_244_244_OML 0x8983
+#endif
+
+#ifndef GL_OML_resample
+#define GL_PACK_RESAMPLE_OML 0x8984
+#define GL_UNPACK_RESAMPLE_OML 0x8985
+#define GL_RESAMPLE_REPLICATE_OML 0x8986
+#define GL_RESAMPLE_ZERO_FILL_OML 0x8987
+#define GL_RESAMPLE_AVERAGE_OML 0x8988
+#define GL_RESAMPLE_DECIMATE_OML 0x8989
+#endif
+
+#ifndef GL_NV_copy_depth_to_color
+#define GL_DEPTH_STENCIL_TO_RGBA_NV 0x886E
+#define GL_DEPTH_STENCIL_TO_BGRA_NV 0x886F
+#endif
+
+#ifndef GL_ATI_envmap_bumpmap
+#define GL_BUMP_ROT_MATRIX_ATI 0x8775
+#define GL_BUMP_ROT_MATRIX_SIZE_ATI 0x8776
+#define GL_BUMP_NUM_TEX_UNITS_ATI 0x8777
+#define GL_BUMP_TEX_UNITS_ATI 0x8778
+#define GL_DUDV_ATI 0x8779
+#define GL_DU8DV8_ATI 0x877A
+#define GL_BUMP_ENVMAP_ATI 0x877B
+#define GL_BUMP_TARGET_ATI 0x877C
+#endif
+
+#ifndef GL_ATI_fragment_shader
+#define GL_FRAGMENT_SHADER_ATI 0x8920
+#define GL_REG_0_ATI 0x8921
+#define GL_REG_1_ATI 0x8922
+#define GL_REG_2_ATI 0x8923
+#define GL_REG_3_ATI 0x8924
+#define GL_REG_4_ATI 0x8925
+#define GL_REG_5_ATI 0x8926
+#define GL_REG_6_ATI 0x8927
+#define GL_REG_7_ATI 0x8928
+#define GL_REG_8_ATI 0x8929
+#define GL_REG_9_ATI 0x892A
+#define GL_REG_10_ATI 0x892B
+#define GL_REG_11_ATI 0x892C
+#define GL_REG_12_ATI 0x892D
+#define GL_REG_13_ATI 0x892E
+#define GL_REG_14_ATI 0x892F
+#define GL_REG_15_ATI 0x8930
+#define GL_REG_16_ATI 0x8931
+#define GL_REG_17_ATI 0x8932
+#define GL_REG_18_ATI 0x8933
+#define GL_REG_19_ATI 0x8934
+#define GL_REG_20_ATI 0x8935
+#define GL_REG_21_ATI 0x8936
+#define GL_REG_22_ATI 0x8937
+#define GL_REG_23_ATI 0x8938
+#define GL_REG_24_ATI 0x8939
+#define GL_REG_25_ATI 0x893A
+#define GL_REG_26_ATI 0x893B
+#define GL_REG_27_ATI 0x893C
+#define GL_REG_28_ATI 0x893D
+#define GL_REG_29_ATI 0x893E
+#define GL_REG_30_ATI 0x893F
+#define GL_REG_31_ATI 0x8940
+#define GL_CON_0_ATI 0x8941
+#define GL_CON_1_ATI 0x8942
+#define GL_CON_2_ATI 0x8943
+#define GL_CON_3_ATI 0x8944
+#define GL_CON_4_ATI 0x8945
+#define GL_CON_5_ATI 0x8946
+#define GL_CON_6_ATI 0x8947
+#define GL_CON_7_ATI 0x8948
+#define GL_CON_8_ATI 0x8949
+#define GL_CON_9_ATI 0x894A
+#define GL_CON_10_ATI 0x894B
+#define GL_CON_11_ATI 0x894C
+#define GL_CON_12_ATI 0x894D
+#define GL_CON_13_ATI 0x894E
+#define GL_CON_14_ATI 0x894F
+#define GL_CON_15_ATI 0x8950
+#define GL_CON_16_ATI 0x8951
+#define GL_CON_17_ATI 0x8952
+#define GL_CON_18_ATI 0x8953
+#define GL_CON_19_ATI 0x8954
+#define GL_CON_20_ATI 0x8955
+#define GL_CON_21_ATI 0x8956
+#define GL_CON_22_ATI 0x8957
+#define GL_CON_23_ATI 0x8958
+#define GL_CON_24_ATI 0x8959
+#define GL_CON_25_ATI 0x895A
+#define GL_CON_26_ATI 0x895B
+#define GL_CON_27_ATI 0x895C
+#define GL_CON_28_ATI 0x895D
+#define GL_CON_29_ATI 0x895E
+#define GL_CON_30_ATI 0x895F
+#define GL_CON_31_ATI 0x8960
+#define GL_MOV_ATI 0x8961
+#define GL_ADD_ATI 0x8963
+#define GL_MUL_ATI 0x8964
+#define GL_SUB_ATI 0x8965
+#define GL_DOT3_ATI 0x8966
+#define GL_DOT4_ATI 0x8967
+#define GL_MAD_ATI 0x8968
+#define GL_LERP_ATI 0x8969
+#define GL_CND_ATI 0x896A
+#define GL_CND0_ATI 0x896B
+#define GL_DOT2_ADD_ATI 0x896C
+#define GL_SECONDARY_INTERPOLATOR_ATI 0x896D
+#define GL_NUM_FRAGMENT_REGISTERS_ATI 0x896E
+#define GL_NUM_FRAGMENT_CONSTANTS_ATI 0x896F
+#define GL_NUM_PASSES_ATI 0x8970
+#define GL_NUM_INSTRUCTIONS_PER_PASS_ATI 0x8971
+#define GL_NUM_INSTRUCTIONS_TOTAL_ATI 0x8972
+#define GL_NUM_INPUT_INTERPOLATOR_COMPONENTS_ATI 0x8973
+#define GL_NUM_LOOPBACK_COMPONENTS_ATI 0x8974
+#define GL_COLOR_ALPHA_PAIRING_ATI 0x8975
+#define GL_SWIZZLE_STR_ATI 0x8976
+#define GL_SWIZZLE_STQ_ATI 0x8977
+#define GL_SWIZZLE_STR_DR_ATI 0x8978
+#define GL_SWIZZLE_STQ_DQ_ATI 0x8979
+#define GL_SWIZZLE_STRQ_ATI 0x897A
+#define GL_SWIZZLE_STRQ_DQ_ATI 0x897B
+#define GL_RED_BIT_ATI 0x00000001
+#define GL_GREEN_BIT_ATI 0x00000002
+#define GL_BLUE_BIT_ATI 0x00000004
+#define GL_2X_BIT_ATI 0x00000001
+#define GL_4X_BIT_ATI 0x00000002
+#define GL_8X_BIT_ATI 0x00000004
+#define GL_HALF_BIT_ATI 0x00000008
+#define GL_QUARTER_BIT_ATI 0x00000010
+#define GL_EIGHTH_BIT_ATI 0x00000020
+#define GL_SATURATE_BIT_ATI 0x00000040
+#define GL_COMP_BIT_ATI 0x00000002
+#define GL_NEGATE_BIT_ATI 0x00000004
+#define GL_BIAS_BIT_ATI 0x00000008
+#endif
+
+#ifndef GL_ATI_pn_triangles
+#define GL_PN_TRIANGLES_ATI 0x87F0
+#define GL_MAX_PN_TRIANGLES_TESSELATION_LEVEL_ATI 0x87F1
+#define GL_PN_TRIANGLES_POINT_MODE_ATI 0x87F2
+#define GL_PN_TRIANGLES_NORMAL_MODE_ATI 0x87F3
+#define GL_PN_TRIANGLES_TESSELATION_LEVEL_ATI 0x87F4
+#define GL_PN_TRIANGLES_POINT_MODE_LINEAR_ATI 0x87F5
+#define GL_PN_TRIANGLES_POINT_MODE_CUBIC_ATI 0x87F6
+#define GL_PN_TRIANGLES_NORMAL_MODE_LINEAR_ATI 0x87F7
+#define GL_PN_TRIANGLES_NORMAL_MODE_QUADRATIC_ATI 0x87F8
+#endif
+
+#ifndef GL_ATI_vertex_array_object
+#define GL_STATIC_ATI 0x8760
+#define GL_DYNAMIC_ATI 0x8761
+#define GL_PRESERVE_ATI 0x8762
+#define GL_DISCARD_ATI 0x8763
+#define GL_OBJECT_BUFFER_SIZE_ATI 0x8764
+#define GL_OBJECT_BUFFER_USAGE_ATI 0x8765
+#define GL_ARRAY_OBJECT_BUFFER_ATI 0x8766
+#define GL_ARRAY_OBJECT_OFFSET_ATI 0x8767
+#endif
+
+#ifndef GL_EXT_vertex_shader
+#define GL_VERTEX_SHADER_EXT 0x8780
+#define GL_VERTEX_SHADER_BINDING_EXT 0x8781
+#define GL_OP_INDEX_EXT 0x8782
+#define GL_OP_NEGATE_EXT 0x8783
+#define GL_OP_DOT3_EXT 0x8784
+#define GL_OP_DOT4_EXT 0x8785
+#define GL_OP_MUL_EXT 0x8786
+#define GL_OP_ADD_EXT 0x8787
+#define GL_OP_MADD_EXT 0x8788
+#define GL_OP_FRAC_EXT 0x8789
+#define GL_OP_MAX_EXT 0x878A
+#define GL_OP_MIN_EXT 0x878B
+#define GL_OP_SET_GE_EXT 0x878C
+#define GL_OP_SET_LT_EXT 0x878D
+#define GL_OP_CLAMP_EXT 0x878E
+#define GL_OP_FLOOR_EXT 0x878F
+#define GL_OP_ROUND_EXT 0x8790
+#define GL_OP_EXP_BASE_2_EXT 0x8791
+#define GL_OP_LOG_BASE_2_EXT 0x8792
+#define GL_OP_POWER_EXT 0x8793
+#define GL_OP_RECIP_EXT 0x8794
+#define GL_OP_RECIP_SQRT_EXT 0x8795
+#define GL_OP_SUB_EXT 0x8796
+#define GL_OP_CROSS_PRODUCT_EXT 0x8797
+#define GL_OP_MULTIPLY_MATRIX_EXT 0x8798
+#define GL_OP_MOV_EXT 0x8799
+#define GL_OUTPUT_VERTEX_EXT 0x879A
+#define GL_OUTPUT_COLOR0_EXT 0x879B
+#define GL_OUTPUT_COLOR1_EXT 0x879C
+#define GL_OUTPUT_TEXTURE_COORD0_EXT 0x879D
+#define GL_OUTPUT_TEXTURE_COORD1_EXT 0x879E
+#define GL_OUTPUT_TEXTURE_COORD2_EXT 0x879F
+#define GL_OUTPUT_TEXTURE_COORD3_EXT 0x87A0
+#define GL_OUTPUT_TEXTURE_COORD4_EXT 0x87A1
+#define GL_OUTPUT_TEXTURE_COORD5_EXT 0x87A2
+#define GL_OUTPUT_TEXTURE_COORD6_EXT 0x87A3
+#define GL_OUTPUT_TEXTURE_COORD7_EXT 0x87A4
+#define GL_OUTPUT_TEXTURE_COORD8_EXT 0x87A5
+#define GL_OUTPUT_TEXTURE_COORD9_EXT 0x87A6
+#define GL_OUTPUT_TEXTURE_COORD10_EXT 0x87A7
+#define GL_OUTPUT_TEXTURE_COORD11_EXT 0x87A8
+#define GL_OUTPUT_TEXTURE_COORD12_EXT 0x87A9
+#define GL_OUTPUT_TEXTURE_COORD13_EXT 0x87AA
+#define GL_OUTPUT_TEXTURE_COORD14_EXT 0x87AB
+#define GL_OUTPUT_TEXTURE_COORD15_EXT 0x87AC
+#define GL_OUTPUT_TEXTURE_COORD16_EXT 0x87AD
+#define GL_OUTPUT_TEXTURE_COORD17_EXT 0x87AE
+#define GL_OUTPUT_TEXTURE_COORD18_EXT 0x87AF
+#define GL_OUTPUT_TEXTURE_COORD19_EXT 0x87B0
+#define GL_OUTPUT_TEXTURE_COORD20_EXT 0x87B1
+#define GL_OUTPUT_TEXTURE_COORD21_EXT 0x87B2
+#define GL_OUTPUT_TEXTURE_COORD22_EXT 0x87B3
+#define GL_OUTPUT_TEXTURE_COORD23_EXT 0x87B4
+#define GL_OUTPUT_TEXTURE_COORD24_EXT 0x87B5
+#define GL_OUTPUT_TEXTURE_COORD25_EXT 0x87B6
+#define GL_OUTPUT_TEXTURE_COORD26_EXT 0x87B7
+#define GL_OUTPUT_TEXTURE_COORD27_EXT 0x87B8
+#define GL_OUTPUT_TEXTURE_COORD28_EXT 0x87B9
+#define GL_OUTPUT_TEXTURE_COORD29_EXT 0x87BA
+#define GL_OUTPUT_TEXTURE_COORD30_EXT 0x87BB
+#define GL_OUTPUT_TEXTURE_COORD31_EXT 0x87BC
+#define GL_OUTPUT_FOG_EXT 0x87BD
+#define GL_SCALAR_EXT 0x87BE
+#define GL_VECTOR_EXT 0x87BF
+#define GL_MATRIX_EXT 0x87C0
+#define GL_VARIANT_EXT 0x87C1
+#define GL_INVARIANT_EXT 0x87C2
+#define GL_LOCAL_CONSTANT_EXT 0x87C3
+#define GL_LOCAL_EXT 0x87C4
+#define GL_MAX_VERTEX_SHADER_INSTRUCTIONS_EXT 0x87C5
+#define GL_MAX_VERTEX_SHADER_VARIANTS_EXT 0x87C6
+#define GL_MAX_VERTEX_SHADER_INVARIANTS_EXT 0x87C7
+#define GL_MAX_VERTEX_SHADER_LOCAL_CONSTANTS_EXT 0x87C8
+#define GL_MAX_VERTEX_SHADER_LOCALS_EXT 0x87C9
+#define GL_MAX_OPTIMIZED_VERTEX_SHADER_INSTRUCTIONS_EXT 0x87CA
+#define GL_MAX_OPTIMIZED_VERTEX_SHADER_VARIANTS_EXT 0x87CB
+#define GL_MAX_OPTIMIZED_VERTEX_SHADER_LOCAL_CONSTANTS_EXT 0x87CC
+#define GL_MAX_OPTIMIZED_VERTEX_SHADER_INVARIANTS_EXT 0x87CD
+#define GL_MAX_OPTIMIZED_VERTEX_SHADER_LOCALS_EXT 0x87CE
+#define GL_VERTEX_SHADER_INSTRUCTIONS_EXT 0x87CF
+#define GL_VERTEX_SHADER_VARIANTS_EXT 0x87D0
+#define GL_VERTEX_SHADER_INVARIANTS_EXT 0x87D1
+#define GL_VERTEX_SHADER_LOCAL_CONSTANTS_EXT 0x87D2
+#define GL_VERTEX_SHADER_LOCALS_EXT 0x87D3
+#define GL_VERTEX_SHADER_OPTIMIZED_EXT 0x87D4
+#define GL_X_EXT 0x87D5
+#define GL_Y_EXT 0x87D6
+#define GL_Z_EXT 0x87D7
+#define GL_W_EXT 0x87D8
+#define GL_NEGATIVE_X_EXT 0x87D9
+#define GL_NEGATIVE_Y_EXT 0x87DA
+#define GL_NEGATIVE_Z_EXT 0x87DB
+#define GL_NEGATIVE_W_EXT 0x87DC
+#define GL_ZERO_EXT 0x87DD
+#define GL_ONE_EXT 0x87DE
+#define GL_NEGATIVE_ONE_EXT 0x87DF
+#define GL_NORMALIZED_RANGE_EXT 0x87E0
+#define GL_FULL_RANGE_EXT 0x87E1
+#define GL_CURRENT_VERTEX_EXT 0x87E2
+#define GL_MVP_MATRIX_EXT 0x87E3
+#define GL_VARIANT_VALUE_EXT 0x87E4
+#define GL_VARIANT_DATATYPE_EXT 0x87E5
+#define GL_VARIANT_ARRAY_STRIDE_EXT 0x87E6
+#define GL_VARIANT_ARRAY_TYPE_EXT 0x87E7
+#define GL_VARIANT_ARRAY_EXT 0x87E8
+#define GL_VARIANT_ARRAY_POINTER_EXT 0x87E9
+#define GL_INVARIANT_VALUE_EXT 0x87EA
+#define GL_INVARIANT_DATATYPE_EXT 0x87EB
+#define GL_LOCAL_CONSTANT_VALUE_EXT 0x87EC
+#define GL_LOCAL_CONSTANT_DATATYPE_EXT 0x87ED
+#endif
+
+#ifndef GL_ATI_vertex_streams
+#define GL_MAX_VERTEX_STREAMS_ATI 0x876B
+#define GL_VERTEX_STREAM0_ATI 0x876C
+#define GL_VERTEX_STREAM1_ATI 0x876D
+#define GL_VERTEX_STREAM2_ATI 0x876E
+#define GL_VERTEX_STREAM3_ATI 0x876F
+#define GL_VERTEX_STREAM4_ATI 0x8770
+#define GL_VERTEX_STREAM5_ATI 0x8771
+#define GL_VERTEX_STREAM6_ATI 0x8772
+#define GL_VERTEX_STREAM7_ATI 0x8773
+#define GL_VERTEX_SOURCE_ATI 0x8774
+#endif
+
+#ifndef GL_ATI_element_array
+#define GL_ELEMENT_ARRAY_ATI 0x8768
+#define GL_ELEMENT_ARRAY_TYPE_ATI 0x8769
+#define GL_ELEMENT_ARRAY_POINTER_ATI 0x876A
+#endif
+
+#ifndef GL_SUN_mesh_array
+#define GL_QUAD_MESH_SUN 0x8614
+#define GL_TRIANGLE_MESH_SUN 0x8615
+#endif
+
+#ifndef GL_SUN_slice_accum
+#define GL_SLICE_ACCUM_SUN 0x85CC
+#endif
+
+#ifndef GL_NV_multisample_filter_hint
+#define GL_MULTISAMPLE_FILTER_HINT_NV 0x8534
+#endif
+
+#ifndef GL_NV_depth_clamp
+#define GL_DEPTH_CLAMP_NV 0x864F
+#endif
+
+#ifndef GL_NV_occlusion_query
+#define GL_PIXEL_COUNTER_BITS_NV 0x8864
+#define GL_CURRENT_OCCLUSION_QUERY_ID_NV 0x8865
+#define GL_PIXEL_COUNT_NV 0x8866
+#define GL_PIXEL_COUNT_AVAILABLE_NV 0x8867
+#endif
+
+#ifndef GL_NV_point_sprite
+#define GL_POINT_SPRITE_NV 0x8861
+#define GL_COORD_REPLACE_NV 0x8862
+#define GL_POINT_SPRITE_R_MODE_NV 0x8863
+#endif
+
+#ifndef GL_NV_texture_shader3
+#define GL_OFFSET_PROJECTIVE_TEXTURE_2D_NV 0x8850
+#define GL_OFFSET_PROJECTIVE_TEXTURE_2D_SCALE_NV 0x8851
+#define GL_OFFSET_PROJECTIVE_TEXTURE_RECTANGLE_NV 0x8852
+#define GL_OFFSET_PROJECTIVE_TEXTURE_RECTANGLE_SCALE_NV 0x8853
+#define GL_OFFSET_HILO_TEXTURE_2D_NV 0x8854
+#define GL_OFFSET_HILO_TEXTURE_RECTANGLE_NV 0x8855
+#define GL_OFFSET_HILO_PROJECTIVE_TEXTURE_2D_NV 0x8856
+#define GL_OFFSET_HILO_PROJECTIVE_TEXTURE_RECTANGLE_NV 0x8857
+#define GL_DEPENDENT_HILO_TEXTURE_2D_NV 0x8858
+#define GL_DEPENDENT_RGB_TEXTURE_3D_NV 0x8859
+#define GL_DEPENDENT_RGB_TEXTURE_CUBE_MAP_NV 0x885A
+#define GL_DOT_PRODUCT_PASS_THROUGH_NV 0x885B
+#define GL_DOT_PRODUCT_TEXTURE_1D_NV 0x885C
+#define GL_DOT_PRODUCT_AFFINE_DEPTH_REPLACE_NV 0x885D
+#define GL_HILO8_NV 0x885E
+#define GL_SIGNED_HILO8_NV 0x885F
+#define GL_FORCE_BLUE_TO_ONE_NV 0x8860
+#endif
+
+#ifndef GL_NV_vertex_program1_1
+#endif
+
+#ifndef GL_EXT_shadow_funcs
+#endif
+
+#ifndef GL_EXT_stencil_two_side
+#define GL_STENCIL_TEST_TWO_SIDE_EXT 0x8910
+#define GL_ACTIVE_STENCIL_FACE_EXT 0x8911
+#endif
+
+#ifndef GL_ATI_text_fragment_shader
+#define GL_TEXT_FRAGMENT_SHADER_ATI 0x8200
+#endif
+
+#ifndef GL_APPLE_client_storage
+#define GL_UNPACK_CLIENT_STORAGE_APPLE 0x85B2
+#endif
+
+#ifndef GL_APPLE_element_array
+#define GL_ELEMENT_ARRAY_APPLE 0x8A0C
+#define GL_ELEMENT_ARRAY_TYPE_APPLE 0x8A0D
+#define GL_ELEMENT_ARRAY_POINTER_APPLE 0x8A0E
+#endif
+
+#ifndef GL_APPLE_fence
+#define GL_DRAW_PIXELS_APPLE 0x8A0A
+#define GL_FENCE_APPLE 0x8A0B
+#endif
+
+#ifndef GL_APPLE_vertex_array_object
+#define GL_VERTEX_ARRAY_BINDING_APPLE 0x85B5
+#endif
+
+#ifndef GL_APPLE_vertex_array_range
+#define GL_VERTEX_ARRAY_RANGE_APPLE 0x851D
+#define GL_VERTEX_ARRAY_RANGE_LENGTH_APPLE 0x851E
+#define GL_VERTEX_ARRAY_STORAGE_HINT_APPLE 0x851F
+#define GL_VERTEX_ARRAY_RANGE_POINTER_APPLE 0x8521
+#define GL_STORAGE_CLIENT_APPLE 0x85B4
+#define GL_STORAGE_CACHED_APPLE 0x85BE
+#define GL_STORAGE_SHARED_APPLE 0x85BF
+#endif
+
+#ifndef GL_APPLE_ycbcr_422
+#define GL_YCBCR_422_APPLE 0x85B9
+#define GL_UNSIGNED_SHORT_8_8_APPLE 0x85BA
+#define GL_UNSIGNED_SHORT_8_8_REV_APPLE 0x85BB
+#endif
+
+#ifndef GL_S3_s3tc
+#define GL_RGB_S3TC 0x83A0
+#define GL_RGB4_S3TC 0x83A1
+#define GL_RGBA_S3TC 0x83A2
+#define GL_RGBA4_S3TC 0x83A3
+#endif
+
+#ifndef GL_ATI_draw_buffers
+#define GL_MAX_DRAW_BUFFERS_ATI 0x8824
+#define GL_DRAW_BUFFER0_ATI 0x8825
+#define GL_DRAW_BUFFER1_ATI 0x8826
+#define GL_DRAW_BUFFER2_ATI 0x8827
+#define GL_DRAW_BUFFER3_ATI 0x8828
+#define GL_DRAW_BUFFER4_ATI 0x8829
+#define GL_DRAW_BUFFER5_ATI 0x882A
+#define GL_DRAW_BUFFER6_ATI 0x882B
+#define GL_DRAW_BUFFER7_ATI 0x882C
+#define GL_DRAW_BUFFER8_ATI 0x882D
+#define GL_DRAW_BUFFER9_ATI 0x882E
+#define GL_DRAW_BUFFER10_ATI 0x882F
+#define GL_DRAW_BUFFER11_ATI 0x8830
+#define GL_DRAW_BUFFER12_ATI 0x8831
+#define GL_DRAW_BUFFER13_ATI 0x8832
+#define GL_DRAW_BUFFER14_ATI 0x8833
+#define GL_DRAW_BUFFER15_ATI 0x8834
+#endif
+
+#ifndef GL_ATI_pixel_format_float
+#define GL_TYPE_RGBA_FLOAT_ATI 0x8820
+#define GL_COLOR_CLEAR_UNCLAMPED_VALUE_ATI 0x8835
+#endif
+
+#ifndef GL_ATI_texture_env_combine3
+#define GL_MODULATE_ADD_ATI 0x8744
+#define GL_MODULATE_SIGNED_ADD_ATI 0x8745
+#define GL_MODULATE_SUBTRACT_ATI 0x8746
+#endif
+
+#ifndef GL_ATI_texture_float
+#define GL_RGBA_FLOAT32_ATI 0x8814
+#define GL_RGB_FLOAT32_ATI 0x8815
+#define GL_ALPHA_FLOAT32_ATI 0x8816
+#define GL_INTENSITY_FLOAT32_ATI 0x8817
+#define GL_LUMINANCE_FLOAT32_ATI 0x8818
+#define GL_LUMINANCE_ALPHA_FLOAT32_ATI 0x8819
+#define GL_RGBA_FLOAT16_ATI 0x881A
+#define GL_RGB_FLOAT16_ATI 0x881B
+#define GL_ALPHA_FLOAT16_ATI 0x881C
+#define GL_INTENSITY_FLOAT16_ATI 0x881D
+#define GL_LUMINANCE_FLOAT16_ATI 0x881E
+#define GL_LUMINANCE_ALPHA_FLOAT16_ATI 0x881F
+#endif
+
+#ifndef GL_NV_float_buffer
+#define GL_FLOAT_R_NV 0x8880
+#define GL_FLOAT_RG_NV 0x8881
+#define GL_FLOAT_RGB_NV 0x8882
+#define GL_FLOAT_RGBA_NV 0x8883
+#define GL_FLOAT_R16_NV 0x8884
+#define GL_FLOAT_R32_NV 0x8885
+#define GL_FLOAT_RG16_NV 0x8886
+#define GL_FLOAT_RG32_NV 0x8887
+#define GL_FLOAT_RGB16_NV 0x8888
+#define GL_FLOAT_RGB32_NV 0x8889
+#define GL_FLOAT_RGBA16_NV 0x888A
+#define GL_FLOAT_RGBA32_NV 0x888B
+#define GL_TEXTURE_FLOAT_COMPONENTS_NV 0x888C
+#define GL_FLOAT_CLEAR_COLOR_VALUE_NV 0x888D
+#define GL_FLOAT_RGBA_MODE_NV 0x888E
+#endif
+
+#ifndef GL_NV_fragment_program
+#define GL_MAX_FRAGMENT_PROGRAM_LOCAL_PARAMETERS_NV 0x8868
+#define GL_FRAGMENT_PROGRAM_NV 0x8870
+#define GL_MAX_TEXTURE_COORDS_NV 0x8871
+#define GL_MAX_TEXTURE_IMAGE_UNITS_NV 0x8872
+#define GL_FRAGMENT_PROGRAM_BINDING_NV 0x8873
+#define GL_PROGRAM_ERROR_STRING_NV 0x8874
+#endif
+
+#ifndef GL_NV_half_float
+#define GL_HALF_FLOAT_NV 0x140B
+#endif
+
+#ifndef GL_NV_pixel_data_range
+#define GL_WRITE_PIXEL_DATA_RANGE_NV 0x8878
+#define GL_READ_PIXEL_DATA_RANGE_NV 0x8879
+#define GL_WRITE_PIXEL_DATA_RANGE_LENGTH_NV 0x887A
+#define GL_READ_PIXEL_DATA_RANGE_LENGTH_NV 0x887B
+#define GL_WRITE_PIXEL_DATA_RANGE_POINTER_NV 0x887C
+#define GL_READ_PIXEL_DATA_RANGE_POINTER_NV 0x887D
+#endif
+
+#ifndef GL_NV_primitive_restart
+#define GL_PRIMITIVE_RESTART_NV 0x8558
+#define GL_PRIMITIVE_RESTART_INDEX_NV 0x8559
+#endif
+
+#ifndef GL_NV_texture_expand_normal
+#define GL_TEXTURE_UNSIGNED_REMAP_MODE_NV 0x888F
+#endif
+
+#ifndef GL_NV_vertex_program2
+#endif
+
+#ifndef GL_ATI_map_object_buffer
+#endif
+
+#ifndef GL_ATI_separate_stencil
+#define GL_STENCIL_BACK_FUNC_ATI 0x8800
+#define GL_STENCIL_BACK_FAIL_ATI 0x8801
+#define GL_STENCIL_BACK_PASS_DEPTH_FAIL_ATI 0x8802
+#define GL_STENCIL_BACK_PASS_DEPTH_PASS_ATI 0x8803
+#endif
+
+#ifndef GL_ATI_vertex_attrib_array_object
+#endif
+
+#ifndef GL_OES_read_format
+#define GL_IMPLEMENTATION_COLOR_READ_TYPE_OES 0x8B9A
+#define GL_IMPLEMENTATION_COLOR_READ_FORMAT_OES 0x8B9B
+#endif
+
+#ifndef GL_EXT_depth_bounds_test
+#define GL_DEPTH_BOUNDS_TEST_EXT 0x8890
+#define GL_DEPTH_BOUNDS_EXT 0x8891
+#endif
+
+#ifndef GL_EXT_texture_mirror_clamp
+#define GL_MIRROR_CLAMP_EXT 0x8742
+#define GL_MIRROR_CLAMP_TO_EDGE_EXT 0x8743
+#define GL_MIRROR_CLAMP_TO_BORDER_EXT 0x8912
+#endif
+
+#ifndef GL_EXT_blend_equation_separate
+#define GL_BLEND_EQUATION_RGB_EXT 0x8009
+#define GL_BLEND_EQUATION_ALPHA_EXT 0x883D
+#endif
+
+#ifndef GL_MESA_pack_invert
+#define GL_PACK_INVERT_MESA 0x8758
+#endif
+
+#ifndef GL_MESA_ycbcr_texture
+#define GL_UNSIGNED_SHORT_8_8_MESA 0x85BA
+#define GL_UNSIGNED_SHORT_8_8_REV_MESA 0x85BB
+#define GL_YCBCR_MESA 0x8757
+#endif
+
+#ifndef GL_EXT_pixel_buffer_object
+#define GL_PIXEL_PACK_BUFFER_EXT 0x88EB
+#define GL_PIXEL_UNPACK_BUFFER_EXT 0x88EC
+#define GL_PIXEL_PACK_BUFFER_BINDING_EXT 0x88ED
+#define GL_PIXEL_UNPACK_BUFFER_BINDING_EXT 0x88EF
+#endif
+
+#ifndef GL_NV_fragment_program_option
+#endif
+
+#ifndef GL_NV_fragment_program2
+#define GL_MAX_PROGRAM_EXEC_INSTRUCTIONS_NV 0x88F4
+#define GL_MAX_PROGRAM_CALL_DEPTH_NV 0x88F5
+#define GL_MAX_PROGRAM_IF_DEPTH_NV 0x88F6
+#define GL_MAX_PROGRAM_LOOP_DEPTH_NV 0x88F7
+#define GL_MAX_PROGRAM_LOOP_COUNT_NV 0x88F8
+#endif
+
+#ifndef GL_NV_vertex_program2_option
+
+#endif
+
+#ifndef GL_NV_vertex_program3
+
+#endif
+
+#ifndef GL_EXT_framebuffer_object
+#define GL_INVALID_FRAMEBUFFER_OPERATION_EXT 0x0506
+#define GL_MAX_RENDERBUFFER_SIZE_EXT 0x84E8
+#define GL_FRAMEBUFFER_BINDING_EXT 0x8CA6
+#define GL_RENDERBUFFER_BINDING_EXT 0x8CA7
+#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_EXT 0x8CD0
+#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_EXT 0x8CD1
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL_EXT 0x8CD2
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE_EXT 0x8CD3
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_3D_ZOFFSET_EXT 0x8CD4
+#define GL_FRAMEBUFFER_COMPLETE_EXT 0x8CD5
+#define GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT 0x8CD6
+#define GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT 0x8CD7
+#define GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT 0x8CD9
+#define GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT 0x8CDA
+#define GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT 0x8CDB
+#define GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT 0x8CDC
+#define GL_FRAMEBUFFER_UNSUPPORTED_EXT 0x8CDD
+#define GL_MAX_COLOR_ATTACHMENTS_EXT 0x8CDF
+#define GL_COLOR_ATTACHMENT0_EXT 0x8CE0
+#define GL_COLOR_ATTACHMENT1_EXT 0x8CE1
+#define GL_COLOR_ATTACHMENT2_EXT 0x8CE2
+#define GL_COLOR_ATTACHMENT3_EXT 0x8CE3
+#define GL_COLOR_ATTACHMENT4_EXT 0x8CE4
+#define GL_COLOR_ATTACHMENT5_EXT 0x8CE5
+#define GL_COLOR_ATTACHMENT6_EXT 0x8CE6
+#define GL_COLOR_ATTACHMENT7_EXT 0x8CE7
+#define GL_COLOR_ATTACHMENT8_EXT 0x8CE8
+#define GL_COLOR_ATTACHMENT9_EXT 0x8CE9
+#define GL_COLOR_ATTACHMENT10_EXT 0x8CEA
+#define GL_COLOR_ATTACHMENT11_EXT 0x8CEB
+#define GL_COLOR_ATTACHMENT12_EXT 0x8CEC
+#define GL_COLOR_ATTACHMENT13_EXT 0x8CED
+#define GL_COLOR_ATTACHMENT14_EXT 0x8CEE
+#define GL_COLOR_ATTACHMENT15_EXT 0x8CEF
+#define GL_DEPTH_ATTACHMENT_EXT 0x8D00
+#define GL_STENCIL_ATTACHMENT_EXT 0x8D20
+#define GL_FRAMEBUFFER_EXT 0x8D40
+#define GL_RENDERBUFFER_EXT 0x8D41
+#define GL_RENDERBUFFER_WIDTH_EXT 0x8D42
+#define GL_RENDERBUFFER_HEIGHT_EXT 0x8D43
+#define GL_RENDERBUFFER_INTERNAL_FORMAT_EXT 0x8D44
+#define GL_STENCIL_INDEX1_EXT 0x8D46
+#define GL_STENCIL_INDEX4_EXT 0x8D47
+#define GL_STENCIL_INDEX8_EXT 0x8D48
+#define GL_STENCIL_INDEX16_EXT 0x8D49
+#define GL_RENDERBUFFER_RED_SIZE_EXT 0x8D50
+#define GL_RENDERBUFFER_GREEN_SIZE_EXT 0x8D51
+#define GL_RENDERBUFFER_BLUE_SIZE_EXT 0x8D52
+#define GL_RENDERBUFFER_ALPHA_SIZE_EXT 0x8D53
+#define GL_RENDERBUFFER_DEPTH_SIZE_EXT 0x8D54
+#define GL_RENDERBUFFER_STENCIL_SIZE_EXT 0x8D55
+#endif
+
+#ifndef GL_GREMEDY_string_marker
+#endif
+
+#ifndef GL_EXT_packed_depth_stencil
+#define GL_DEPTH_STENCIL_EXT 0x84F9
+#define GL_UNSIGNED_INT_24_8_EXT 0x84FA
+#define GL_DEPTH24_STENCIL8_EXT 0x88F0
+#define GL_TEXTURE_STENCIL_SIZE_EXT 0x88F1
+#endif
+
+#ifndef GL_EXT_stencil_clear_tag
+#define GL_STENCIL_TAG_BITS_EXT 0x88F2
+#define GL_STENCIL_CLEAR_TAG_VALUE_EXT 0x88F3
+#endif
+
+#ifndef GL_EXT_texture_sRGB
+#define GL_SRGB_EXT 0x8C40
+#define GL_SRGB8_EXT 0x8C41
+#define GL_SRGB_ALPHA_EXT 0x8C42
+#define GL_SRGB8_ALPHA8_EXT 0x8C43
+#define GL_SLUMINANCE_ALPHA_EXT 0x8C44
+#define GL_SLUMINANCE8_ALPHA8_EXT 0x8C45
+#define GL_SLUMINANCE_EXT 0x8C46
+#define GL_SLUMINANCE8_EXT 0x8C47
+#define GL_COMPRESSED_SRGB_EXT 0x8C48
+#define GL_COMPRESSED_SRGB_ALPHA_EXT 0x8C49
+#define GL_COMPRESSED_SLUMINANCE_EXT 0x8C4A
+#define GL_COMPRESSED_SLUMINANCE_ALPHA_EXT 0x8C4B
+#define GL_COMPRESSED_SRGB_S3TC_DXT1_EXT 0x8C4C
+#define GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT 0x8C4D
+#define GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT 0x8C4E
+#define GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT 0x8C4F
+#endif
+
+#ifndef GL_EXT_framebuffer_blit
+#define GL_READ_FRAMEBUFFER_EXT 0x8CA8
+#define GL_DRAW_FRAMEBUFFER_EXT 0x8CA9
+#define GL_DRAW_FRAMEBUFFER_BINDING_EXT GL_FRAMEBUFFER_BINDING_EXT
+#define GL_READ_FRAMEBUFFER_BINDING_EXT 0x8CAA
+#endif
+
+#ifndef GL_EXT_framebuffer_multisample
+#define GL_RENDERBUFFER_SAMPLES_EXT 0x8CAB
+#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT 0x8D56
+#define GL_MAX_SAMPLES_EXT 0x8D57
+#endif
+
+#ifndef GL_MESAX_texture_stack
+#define GL_TEXTURE_1D_STACK_MESAX 0x8759
+#define GL_TEXTURE_2D_STACK_MESAX 0x875A
+#define GL_PROXY_TEXTURE_1D_STACK_MESAX 0x875B
+#define GL_PROXY_TEXTURE_2D_STACK_MESAX 0x875C
+#define GL_TEXTURE_1D_STACK_BINDING_MESAX 0x875D
+#define GL_TEXTURE_2D_STACK_BINDING_MESAX 0x875E
+#endif
+
+#ifndef GL_EXT_timer_query
+#define GL_TIME_ELAPSED_EXT 0x88BF
+#endif
+
+#ifndef GL_EXT_gpu_program_parameters
+#endif
+
+#ifndef GL_APPLE_flush_buffer_range
+#define GL_BUFFER_SERIALIZED_MODIFY_APPLE 0x8A12
+#define GL_BUFFER_FLUSHING_UNMAP_APPLE 0x8A13
+#endif
+
+#ifndef GL_NV_gpu_program4
+#define GL_MIN_PROGRAM_TEXEL_OFFSET_NV 0x8904
+#define GL_MAX_PROGRAM_TEXEL_OFFSET_NV 0x8905
+#define GL_PROGRAM_ATTRIB_COMPONENTS_NV 0x8906
+#define GL_PROGRAM_RESULT_COMPONENTS_NV 0x8907
+#define GL_MAX_PROGRAM_ATTRIB_COMPONENTS_NV 0x8908
+#define GL_MAX_PROGRAM_RESULT_COMPONENTS_NV 0x8909
+#define GL_MAX_PROGRAM_GENERIC_ATTRIBS_NV 0x8DA5
+#define GL_MAX_PROGRAM_GENERIC_RESULTS_NV 0x8DA6
+#endif
+
+#ifndef GL_NV_geometry_program4
+#define GL_LINES_ADJACENCY_EXT 0x000A
+#define GL_LINE_STRIP_ADJACENCY_EXT 0x000B
+#define GL_TRIANGLES_ADJACENCY_EXT 0x000C
+#define GL_TRIANGLE_STRIP_ADJACENCY_EXT 0x000D
+#define GL_GEOMETRY_PROGRAM_NV 0x8C26
+#define GL_MAX_PROGRAM_OUTPUT_VERTICES_NV 0x8C27
+#define GL_MAX_PROGRAM_TOTAL_OUTPUT_COMPONENTS_NV 0x8C28
+#define GL_GEOMETRY_VERTICES_OUT_EXT 0x8DDA
+#define GL_GEOMETRY_INPUT_TYPE_EXT 0x8DDB
+#define GL_GEOMETRY_OUTPUT_TYPE_EXT 0x8DDC
+#define GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS_EXT 0x8C29
+#define GL_FRAMEBUFFER_ATTACHMENT_LAYERED_EXT 0x8DA7
+#define GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_EXT 0x8DA8
+#define GL_FRAMEBUFFER_INCOMPLETE_LAYER_COUNT_EXT 0x8DA9
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER_EXT 0x8CD4
+#define GL_PROGRAM_POINT_SIZE_EXT 0x8642
+#endif
+
+#ifndef GL_EXT_geometry_shader4
+#define GL_GEOMETRY_SHADER_EXT 0x8DD9
+
+#define GL_MAX_GEOMETRY_VARYING_COMPONENTS_EXT 0x8DDD
+#define GL_MAX_VERTEX_VARYING_COMPONENTS_EXT 0x8DDE
+#define GL_MAX_VARYING_COMPONENTS_EXT 0x8B4B
+#define GL_MAX_GEOMETRY_UNIFORM_COMPONENTS_EXT 0x8DDF
+#define GL_MAX_GEOMETRY_OUTPUT_VERTICES_EXT 0x8DE0
+#define GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS_EXT 0x8DE1
+
+#endif
+
+#ifndef GL_NV_vertex_program4
+#define GL_VERTEX_ATTRIB_ARRAY_INTEGER_NV 0x88FD
+#endif
+
+#ifndef GL_EXT_gpu_shader4
+#define GL_SAMPLER_1D_ARRAY_EXT 0x8DC0
+#define GL_SAMPLER_2D_ARRAY_EXT 0x8DC1
+#define GL_SAMPLER_BUFFER_EXT 0x8DC2
+#define GL_SAMPLER_1D_ARRAY_SHADOW_EXT 0x8DC3
+#define GL_SAMPLER_2D_ARRAY_SHADOW_EXT 0x8DC4
+#define GL_SAMPLER_CUBE_SHADOW_EXT 0x8DC5
+#define GL_UNSIGNED_INT_VEC2_EXT 0x8DC6
+#define GL_UNSIGNED_INT_VEC3_EXT 0x8DC7
+#define GL_UNSIGNED_INT_VEC4_EXT 0x8DC8
+#define GL_INT_SAMPLER_1D_EXT 0x8DC9
+#define GL_INT_SAMPLER_2D_EXT 0x8DCA
+#define GL_INT_SAMPLER_3D_EXT 0x8DCB
+#define GL_INT_SAMPLER_CUBE_EXT 0x8DCC
+#define GL_INT_SAMPLER_2D_RECT_EXT 0x8DCD
+#define GL_INT_SAMPLER_1D_ARRAY_EXT 0x8DCE
+#define GL_INT_SAMPLER_2D_ARRAY_EXT 0x8DCF
+#define GL_INT_SAMPLER_BUFFER_EXT 0x8DD0
+#define GL_UNSIGNED_INT_SAMPLER_1D_EXT 0x8DD1
+#define GL_UNSIGNED_INT_SAMPLER_2D_EXT 0x8DD2
+#define GL_UNSIGNED_INT_SAMPLER_3D_EXT 0x8DD3
+#define GL_UNSIGNED_INT_SAMPLER_CUBE_EXT 0x8DD4
+#define GL_UNSIGNED_INT_SAMPLER_2D_RECT_EXT 0x8DD5
+#define GL_UNSIGNED_INT_SAMPLER_1D_ARRAY_EXT 0x8DD6
+#define GL_UNSIGNED_INT_SAMPLER_2D_ARRAY_EXT 0x8DD7
+#define GL_UNSIGNED_INT_SAMPLER_BUFFER_EXT 0x8DD8
+#endif
+
+#ifndef GL_EXT_draw_instanced
+#endif
+
+#ifndef GL_EXT_packed_float
+#define GL_R11F_G11F_B10F_EXT 0x8C3A
+#define GL_UNSIGNED_INT_10F_11F_11F_REV_EXT 0x8C3B
+#define GL_RGBA_SIGNED_COMPONENTS_EXT 0x8C3C
+#endif
+
+#ifndef GL_EXT_texture_array
+#define GL_TEXTURE_1D_ARRAY_EXT 0x8C18
+#define GL_PROXY_TEXTURE_1D_ARRAY_EXT 0x8C19
+#define GL_TEXTURE_2D_ARRAY_EXT 0x8C1A
+#define GL_PROXY_TEXTURE_2D_ARRAY_EXT 0x8C1B
+#define GL_TEXTURE_BINDING_1D_ARRAY_EXT 0x8C1C
+#define GL_TEXTURE_BINDING_2D_ARRAY_EXT 0x8C1D
+#define GL_MAX_ARRAY_TEXTURE_LAYERS_EXT 0x88FF
+#define GL_COMPARE_REF_DEPTH_TO_TEXTURE_EXT 0x884E
+
+#endif
+
+#ifndef GL_EXT_texture_buffer_object
+#define GL_TEXTURE_BUFFER_EXT 0x8C2A
+#define GL_MAX_TEXTURE_BUFFER_SIZE_EXT 0x8C2B
+#define GL_TEXTURE_BINDING_BUFFER_EXT 0x8C2C
+#define GL_TEXTURE_BUFFER_DATA_STORE_BINDING_EXT 0x8C2D
+#define GL_TEXTURE_BUFFER_FORMAT_EXT 0x8C2E
+#endif
+
+#ifndef GL_EXT_texture_compression_latc
+#define GL_COMPRESSED_LUMINANCE_LATC1_EXT 0x8C70
+#define GL_COMPRESSED_SIGNED_LUMINANCE_LATC1_EXT 0x8C71
+#define GL_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT 0x8C72
+#define GL_COMPRESSED_SIGNED_LUMINANCE_ALPHA_LATC2_EXT 0x8C73
+#endif
+
+#ifndef GL_EXT_texture_compression_rgtc
+#define GL_COMPRESSED_RED_RGTC1_EXT 0x8DBB
+#define GL_COMPRESSED_SIGNED_RED_RGTC1_EXT 0x8DBC
+#define GL_COMPRESSED_RED_GREEN_RGTC2_EXT 0x8DBD
+#define GL_COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT 0x8DBE
+#endif
+
+#ifndef GL_EXT_texture_shared_exponent
+#define GL_RGB9_E5_EXT 0x8C3D
+#define GL_UNSIGNED_INT_5_9_9_9_REV_EXT 0x8C3E
+#define GL_TEXTURE_SHARED_SIZE_EXT 0x8C3F
+#endif
+
+#ifndef GL_NV_depth_buffer_float
+#define GL_DEPTH_COMPONENT32F_NV 0x8DAB
+#define GL_DEPTH32F_STENCIL8_NV 0x8DAC
+#define GL_FLOAT_32_UNSIGNED_INT_24_8_REV_NV 0x8DAD
+#define GL_DEPTH_BUFFER_FLOAT_MODE_NV 0x8DAF
+#endif
+
+#ifndef GL_NV_fragment_program4
+#endif
+
+#ifndef GL_NV_framebuffer_multisample_coverage
+#define GL_RENDERBUFFER_COVERAGE_SAMPLES_NV 0x8CAB
+#define GL_RENDERBUFFER_COLOR_SAMPLES_NV 0x8E10
+#define GL_MAX_MULTISAMPLE_COVERAGE_MODES_NV 0x8E11
+#define GL_MULTISAMPLE_COVERAGE_MODES_NV 0x8E12
+#endif
+
+#ifndef GL_EXT_framebuffer_sRGB
+#define GL_FRAMEBUFFER_SRGB_EXT 0x8DB9
+#define GL_FRAMEBUFFER_SRGB_CAPABLE_EXT 0x8DBA
+#endif
+
+#ifndef GL_NV_geometry_shader4
+#endif
+
+#ifndef GL_NV_parameter_buffer_object
+#define GL_MAX_PROGRAM_PARAMETER_BUFFER_BINDINGS_NV 0x8DA0
+#define GL_MAX_PROGRAM_PARAMETER_BUFFER_SIZE_NV 0x8DA1
+#define GL_VERTEX_PROGRAM_PARAMETER_BUFFER_NV 0x8DA2
+#define GL_GEOMETRY_PROGRAM_PARAMETER_BUFFER_NV 0x8DA3
+#define GL_FRAGMENT_PROGRAM_PARAMETER_BUFFER_NV 0x8DA4
+#endif
+
+#ifndef GL_EXT_draw_buffers2
+#endif
+
+#ifndef GL_NV_transform_feedback
+#define GL_BACK_PRIMARY_COLOR_NV 0x8C77
+#define GL_BACK_SECONDARY_COLOR_NV 0x8C78
+#define GL_TEXTURE_COORD_NV 0x8C79
+#define GL_CLIP_DISTANCE_NV 0x8C7A
+#define GL_VERTEX_ID_NV 0x8C7B
+#define GL_PRIMITIVE_ID_NV 0x8C7C
+#define GL_GENERIC_ATTRIB_NV 0x8C7D
+#define GL_TRANSFORM_FEEDBACK_ATTRIBS_NV 0x8C7E
+#define GL_TRANSFORM_FEEDBACK_BUFFER_MODE_NV 0x8C7F
+#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS_NV 0x8C80
+#define GL_ACTIVE_VARYINGS_NV 0x8C81
+#define GL_ACTIVE_VARYING_MAX_LENGTH_NV 0x8C82
+#define GL_TRANSFORM_FEEDBACK_VARYINGS_NV 0x8C83
+#define GL_TRANSFORM_FEEDBACK_BUFFER_START_NV 0x8C84
+#define GL_TRANSFORM_FEEDBACK_BUFFER_SIZE_NV 0x8C85
+#define GL_TRANSFORM_FEEDBACK_RECORD_NV 0x8C86
+#define GL_PRIMITIVES_GENERATED_NV 0x8C87
+#define GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN_NV 0x8C88
+#define GL_RASTERIZER_DISCARD_NV 0x8C89
+#define GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_ATTRIBS_NV 0x8C8A
+#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS_NV 0x8C8B
+#define GL_INTERLEAVED_ATTRIBS_NV 0x8C8C
+#define GL_SEPARATE_ATTRIBS_NV 0x8C8D
+#define GL_TRANSFORM_FEEDBACK_BUFFER_NV 0x8C8E
+#define GL_TRANSFORM_FEEDBACK_BUFFER_BINDING_NV 0x8C8F
+#define GL_LAYER_NV 0x8DAA
+#define GL_NEXT_BUFFER_NV -2
+#define GL_SKIP_COMPONENTS4_NV -3
+#define GL_SKIP_COMPONENTS3_NV -4
+#define GL_SKIP_COMPONENTS2_NV -5
+#define GL_SKIP_COMPONENTS1_NV -6
+#endif
+
+#ifndef GL_EXT_bindable_uniform
+#define GL_MAX_VERTEX_BINDABLE_UNIFORMS_EXT 0x8DE2
+#define GL_MAX_FRAGMENT_BINDABLE_UNIFORMS_EXT 0x8DE3
+#define GL_MAX_GEOMETRY_BINDABLE_UNIFORMS_EXT 0x8DE4
+#define GL_MAX_BINDABLE_UNIFORM_SIZE_EXT 0x8DED
+#define GL_UNIFORM_BUFFER_EXT 0x8DEE
+#define GL_UNIFORM_BUFFER_BINDING_EXT 0x8DEF
+#endif
+
+#ifndef GL_EXT_texture_integer
+#define GL_RGBA32UI_EXT 0x8D70
+#define GL_RGB32UI_EXT 0x8D71
+#define GL_ALPHA32UI_EXT 0x8D72
+#define GL_INTENSITY32UI_EXT 0x8D73
+#define GL_LUMINANCE32UI_EXT 0x8D74
+#define GL_LUMINANCE_ALPHA32UI_EXT 0x8D75
+#define GL_RGBA16UI_EXT 0x8D76
+#define GL_RGB16UI_EXT 0x8D77
+#define GL_ALPHA16UI_EXT 0x8D78
+#define GL_INTENSITY16UI_EXT 0x8D79
+#define GL_LUMINANCE16UI_EXT 0x8D7A
+#define GL_LUMINANCE_ALPHA16UI_EXT 0x8D7B
+#define GL_RGBA8UI_EXT 0x8D7C
+#define GL_RGB8UI_EXT 0x8D7D
+#define GL_ALPHA8UI_EXT 0x8D7E
+#define GL_INTENSITY8UI_EXT 0x8D7F
+#define GL_LUMINANCE8UI_EXT 0x8D80
+#define GL_LUMINANCE_ALPHA8UI_EXT 0x8D81
+#define GL_RGBA32I_EXT 0x8D82
+#define GL_RGB32I_EXT 0x8D83
+#define GL_ALPHA32I_EXT 0x8D84
+#define GL_INTENSITY32I_EXT 0x8D85
+#define GL_LUMINANCE32I_EXT 0x8D86
+#define GL_LUMINANCE_ALPHA32I_EXT 0x8D87
+#define GL_RGBA16I_EXT 0x8D88
+#define GL_RGB16I_EXT 0x8D89
+#define GL_ALPHA16I_EXT 0x8D8A
+#define GL_INTENSITY16I_EXT 0x8D8B
+#define GL_LUMINANCE16I_EXT 0x8D8C
+#define GL_LUMINANCE_ALPHA16I_EXT 0x8D8D
+#define GL_RGBA8I_EXT 0x8D8E
+#define GL_RGB8I_EXT 0x8D8F
+#define GL_ALPHA8I_EXT 0x8D90
+#define GL_INTENSITY8I_EXT 0x8D91
+#define GL_LUMINANCE8I_EXT 0x8D92
+#define GL_LUMINANCE_ALPHA8I_EXT 0x8D93
+#define GL_RED_INTEGER_EXT 0x8D94
+#define GL_GREEN_INTEGER_EXT 0x8D95
+#define GL_BLUE_INTEGER_EXT 0x8D96
+#define GL_ALPHA_INTEGER_EXT 0x8D97
+#define GL_RGB_INTEGER_EXT 0x8D98
+#define GL_RGBA_INTEGER_EXT 0x8D99
+#define GL_BGR_INTEGER_EXT 0x8D9A
+#define GL_BGRA_INTEGER_EXT 0x8D9B
+#define GL_LUMINANCE_INTEGER_EXT 0x8D9C
+#define GL_LUMINANCE_ALPHA_INTEGER_EXT 0x8D9D
+#define GL_RGBA_INTEGER_MODE_EXT 0x8D9E
+#endif
+
+#ifndef GL_GREMEDY_frame_terminator
+#endif
+
+#ifndef GL_NV_conditional_render
+#define GL_QUERY_WAIT_NV 0x8E13
+#define GL_QUERY_NO_WAIT_NV 0x8E14
+#define GL_QUERY_BY_REGION_WAIT_NV 0x8E15
+#define GL_QUERY_BY_REGION_NO_WAIT_NV 0x8E16
+#endif
+
+#ifndef GL_NV_present_video
+#define GL_FRAME_NV 0x8E26
+#define GL_FIELDS_NV 0x8E27
+#define GL_CURRENT_TIME_NV 0x8E28
+#define GL_NUM_FILL_STREAMS_NV 0x8E29
+#define GL_PRESENT_TIME_NV 0x8E2A
+#define GL_PRESENT_DURATION_NV 0x8E2B
+#endif
+
+#ifndef GL_EXT_transform_feedback
+#define GL_TRANSFORM_FEEDBACK_BUFFER_EXT 0x8C8E
+#define GL_TRANSFORM_FEEDBACK_BUFFER_START_EXT 0x8C84
+#define GL_TRANSFORM_FEEDBACK_BUFFER_SIZE_EXT 0x8C85
+#define GL_TRANSFORM_FEEDBACK_BUFFER_BINDING_EXT 0x8C8F
+#define GL_INTERLEAVED_ATTRIBS_EXT 0x8C8C
+#define GL_SEPARATE_ATTRIBS_EXT 0x8C8D
+#define GL_PRIMITIVES_GENERATED_EXT 0x8C87
+#define GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN_EXT 0x8C88
+#define GL_RASTERIZER_DISCARD_EXT 0x8C89
+#define GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS_EXT 0x8C8A
+#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS_EXT 0x8C8B
+#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS_EXT 0x8C80
+#define GL_TRANSFORM_FEEDBACK_VARYINGS_EXT 0x8C83
+#define GL_TRANSFORM_FEEDBACK_BUFFER_MODE_EXT 0x8C7F
+#define GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH_EXT 0x8C76
+#endif
+
+#ifndef GL_EXT_direct_state_access
+#define GL_PROGRAM_MATRIX_EXT 0x8E2D
+#define GL_TRANSPOSE_PROGRAM_MATRIX_EXT 0x8E2E
+#define GL_PROGRAM_MATRIX_STACK_DEPTH_EXT 0x8E2F
+#endif
+
+#ifndef GL_EXT_vertex_array_bgra
+
+#endif
+
+#ifndef GL_EXT_texture_swizzle
+#define GL_TEXTURE_SWIZZLE_R_EXT 0x8E42
+#define GL_TEXTURE_SWIZZLE_G_EXT 0x8E43
+#define GL_TEXTURE_SWIZZLE_B_EXT 0x8E44
+#define GL_TEXTURE_SWIZZLE_A_EXT 0x8E45
+#define GL_TEXTURE_SWIZZLE_RGBA_EXT 0x8E46
+#endif
+
+#ifndef GL_NV_explicit_multisample
+#define GL_SAMPLE_POSITION_NV 0x8E50
+#define GL_SAMPLE_MASK_NV 0x8E51
+#define GL_SAMPLE_MASK_VALUE_NV 0x8E52
+#define GL_TEXTURE_BINDING_RENDERBUFFER_NV 0x8E53
+#define GL_TEXTURE_RENDERBUFFER_DATA_STORE_BINDING_NV 0x8E54
+#define GL_TEXTURE_RENDERBUFFER_NV 0x8E55
+#define GL_SAMPLER_RENDERBUFFER_NV 0x8E56
+#define GL_INT_SAMPLER_RENDERBUFFER_NV 0x8E57
+#define GL_UNSIGNED_INT_SAMPLER_RENDERBUFFER_NV 0x8E58
+#define GL_MAX_SAMPLE_MASK_WORDS_NV 0x8E59
+#endif
+
+#ifndef GL_NV_transform_feedback2
+#define GL_TRANSFORM_FEEDBACK_NV 0x8E22
+#define GL_TRANSFORM_FEEDBACK_BUFFER_PAUSED_NV 0x8E23
+#define GL_TRANSFORM_FEEDBACK_BUFFER_ACTIVE_NV 0x8E24
+#define GL_TRANSFORM_FEEDBACK_BINDING_NV 0x8E25
+#endif
+
+#ifndef GL_ATI_meminfo
+#define GL_VBO_FREE_MEMORY_ATI 0x87FB
+#define GL_TEXTURE_FREE_MEMORY_ATI 0x87FC
+#define GL_RENDERBUFFER_FREE_MEMORY_ATI 0x87FD
+#endif
+
+#ifndef GL_AMD_performance_monitor
+#define GL_COUNTER_TYPE_AMD 0x8BC0
+#define GL_COUNTER_RANGE_AMD 0x8BC1
+#define GL_UNSIGNED_INT64_AMD 0x8BC2
+#define GL_PERCENTAGE_AMD 0x8BC3
+#define GL_PERFMON_RESULT_AVAILABLE_AMD 0x8BC4
+#define GL_PERFMON_RESULT_SIZE_AMD 0x8BC5
+#define GL_PERFMON_RESULT_AMD 0x8BC6
+#endif
+
+#ifndef GL_AMD_texture_texture4
+#endif
+
+#ifndef GL_AMD_vertex_shader_tesselator
+#define GL_SAMPLER_BUFFER_AMD 0x9001
+#define GL_INT_SAMPLER_BUFFER_AMD 0x9002
+#define GL_UNSIGNED_INT_SAMPLER_BUFFER_AMD 0x9003
+#define GL_TESSELLATION_MODE_AMD 0x9004
+#define GL_TESSELLATION_FACTOR_AMD 0x9005
+#define GL_DISCRETE_AMD 0x9006
+#define GL_CONTINUOUS_AMD 0x9007
+#endif
+
+#ifndef GL_EXT_provoking_vertex
+#define GL_QUADS_FOLLOW_PROVOKING_VERTEX_CONVENTION_EXT 0x8E4C
+#define GL_FIRST_VERTEX_CONVENTION_EXT 0x8E4D
+#define GL_LAST_VERTEX_CONVENTION_EXT 0x8E4E
+#define GL_PROVOKING_VERTEX_EXT 0x8E4F
+#endif
+
+#ifndef GL_EXT_texture_snorm
+#define GL_ALPHA_SNORM 0x9010
+#define GL_LUMINANCE_SNORM 0x9011
+#define GL_LUMINANCE_ALPHA_SNORM 0x9012
+#define GL_INTENSITY_SNORM 0x9013
+#define GL_ALPHA8_SNORM 0x9014
+#define GL_LUMINANCE8_SNORM 0x9015
+#define GL_LUMINANCE8_ALPHA8_SNORM 0x9016
+#define GL_INTENSITY8_SNORM 0x9017
+#define GL_ALPHA16_SNORM 0x9018
+#define GL_LUMINANCE16_SNORM 0x9019
+#define GL_LUMINANCE16_ALPHA16_SNORM 0x901A
+#define GL_INTENSITY16_SNORM 0x901B
+
+#endif
+
+#ifndef GL_AMD_draw_buffers_blend
+#endif
+
+#ifndef GL_APPLE_texture_range
+#define GL_TEXTURE_RANGE_LENGTH_APPLE 0x85B7
+#define GL_TEXTURE_RANGE_POINTER_APPLE 0x85B8
+#define GL_TEXTURE_STORAGE_HINT_APPLE 0x85BC
+#define GL_STORAGE_PRIVATE_APPLE 0x85BD
+
+#endif
+
+#ifndef GL_APPLE_float_pixels
+#define GL_HALF_APPLE 0x140B
+#define GL_RGBA_FLOAT32_APPLE 0x8814
+#define GL_RGB_FLOAT32_APPLE 0x8815
+#define GL_ALPHA_FLOAT32_APPLE 0x8816
+#define GL_INTENSITY_FLOAT32_APPLE 0x8817
+#define GL_LUMINANCE_FLOAT32_APPLE 0x8818
+#define GL_LUMINANCE_ALPHA_FLOAT32_APPLE 0x8819
+#define GL_RGBA_FLOAT16_APPLE 0x881A
+#define GL_RGB_FLOAT16_APPLE 0x881B
+#define GL_ALPHA_FLOAT16_APPLE 0x881C
+#define GL_INTENSITY_FLOAT16_APPLE 0x881D
+#define GL_LUMINANCE_FLOAT16_APPLE 0x881E
+#define GL_LUMINANCE_ALPHA_FLOAT16_APPLE 0x881F
+#define GL_COLOR_FLOAT_APPLE 0x8A0F
+#endif
+
+#ifndef GL_APPLE_vertex_program_evaluators
+#define GL_VERTEX_ATTRIB_MAP1_APPLE 0x8A00
+#define GL_VERTEX_ATTRIB_MAP2_APPLE 0x8A01
+#define GL_VERTEX_ATTRIB_MAP1_SIZE_APPLE 0x8A02
+#define GL_VERTEX_ATTRIB_MAP1_COEFF_APPLE 0x8A03
+#define GL_VERTEX_ATTRIB_MAP1_ORDER_APPLE 0x8A04
+#define GL_VERTEX_ATTRIB_MAP1_DOMAIN_APPLE 0x8A05
+#define GL_VERTEX_ATTRIB_MAP2_SIZE_APPLE 0x8A06
+#define GL_VERTEX_ATTRIB_MAP2_COEFF_APPLE 0x8A07
+#define GL_VERTEX_ATTRIB_MAP2_ORDER_APPLE 0x8A08
+#define GL_VERTEX_ATTRIB_MAP2_DOMAIN_APPLE 0x8A09
+#endif
+
+#ifndef GL_APPLE_aux_depth_stencil
+#define GL_AUX_DEPTH_STENCIL_APPLE 0x8A14
+#endif
+
+#ifndef GL_APPLE_object_purgeable
+#define GL_BUFFER_OBJECT_APPLE 0x85B3
+#define GL_RELEASED_APPLE 0x8A19
+#define GL_VOLATILE_APPLE 0x8A1A
+#define GL_RETAINED_APPLE 0x8A1B
+#define GL_UNDEFINED_APPLE 0x8A1C
+#define GL_PURGEABLE_APPLE 0x8A1D
+#endif
+
+#ifndef GL_APPLE_row_bytes
+#define GL_PACK_ROW_BYTES_APPLE 0x8A15
+#define GL_UNPACK_ROW_BYTES_APPLE 0x8A16
+#endif
+
+#ifndef GL_APPLE_rgb_422
+#define GL_RGB_422_APPLE 0x8A1F
+
+#endif
+
+#ifndef GL_NV_video_capture
+#define GL_VIDEO_BUFFER_NV 0x9020
+#define GL_VIDEO_BUFFER_BINDING_NV 0x9021
+#define GL_FIELD_UPPER_NV 0x9022
+#define GL_FIELD_LOWER_NV 0x9023
+#define GL_NUM_VIDEO_CAPTURE_STREAMS_NV 0x9024
+#define GL_NEXT_VIDEO_CAPTURE_BUFFER_STATUS_NV 0x9025
+#define GL_VIDEO_CAPTURE_TO_422_SUPPORTED_NV 0x9026
+#define GL_LAST_VIDEO_CAPTURE_STATUS_NV 0x9027
+#define GL_VIDEO_BUFFER_PITCH_NV 0x9028
+#define GL_VIDEO_COLOR_CONVERSION_MATRIX_NV 0x9029
+#define GL_VIDEO_COLOR_CONVERSION_MAX_NV 0x902A
+#define GL_VIDEO_COLOR_CONVERSION_MIN_NV 0x902B
+#define GL_VIDEO_COLOR_CONVERSION_OFFSET_NV 0x902C
+#define GL_VIDEO_BUFFER_INTERNAL_FORMAT_NV 0x902D
+#define GL_PARTIAL_SUCCESS_NV 0x902E
+#define GL_SUCCESS_NV 0x902F
+#define GL_FAILURE_NV 0x9030
+#define GL_YCBYCR8_422_NV 0x9031
+#define GL_YCBAYCR8A_4224_NV 0x9032
+#define GL_Z6Y10Z6CB10Z6Y10Z6CR10_422_NV 0x9033
+#define GL_Z6Y10Z6CB10Z6A10Z6Y10Z6CR10Z6A10_4224_NV 0x9034
+#define GL_Z4Y12Z4CB12Z4Y12Z4CR12_422_NV 0x9035
+#define GL_Z4Y12Z4CB12Z4A12Z4Y12Z4CR12Z4A12_4224_NV 0x9036
+#define GL_Z4Y12Z4CB12Z4CR12_444_NV 0x9037
+#define GL_VIDEO_CAPTURE_FRAME_WIDTH_NV 0x9038
+#define GL_VIDEO_CAPTURE_FRAME_HEIGHT_NV 0x9039
+#define GL_VIDEO_CAPTURE_FIELD_UPPER_HEIGHT_NV 0x903A
+#define GL_VIDEO_CAPTURE_FIELD_LOWER_HEIGHT_NV 0x903B
+#define GL_VIDEO_CAPTURE_SURFACE_ORIGIN_NV 0x903C
+#endif
+
+#ifndef GL_NV_copy_image
+#endif
+
+#ifndef GL_EXT_separate_shader_objects
+#define GL_ACTIVE_PROGRAM_EXT 0x8B8D
+#endif
+
+#ifndef GL_NV_parameter_buffer_object2
+#endif
+
+#ifndef GL_NV_shader_buffer_load
+#define GL_BUFFER_GPU_ADDRESS_NV 0x8F1D
+#define GL_GPU_ADDRESS_NV 0x8F34
+#define GL_MAX_SHADER_BUFFER_ADDRESS_NV 0x8F35
+#endif
+
+#ifndef GL_NV_vertex_buffer_unified_memory
+#define GL_VERTEX_ATTRIB_ARRAY_UNIFIED_NV 0x8F1E
+#define GL_ELEMENT_ARRAY_UNIFIED_NV 0x8F1F
+#define GL_VERTEX_ATTRIB_ARRAY_ADDRESS_NV 0x8F20
+#define GL_VERTEX_ARRAY_ADDRESS_NV 0x8F21
+#define GL_NORMAL_ARRAY_ADDRESS_NV 0x8F22
+#define GL_COLOR_ARRAY_ADDRESS_NV 0x8F23
+#define GL_INDEX_ARRAY_ADDRESS_NV 0x8F24
+#define GL_TEXTURE_COORD_ARRAY_ADDRESS_NV 0x8F25
+#define GL_EDGE_FLAG_ARRAY_ADDRESS_NV 0x8F26
+#define GL_SECONDARY_COLOR_ARRAY_ADDRESS_NV 0x8F27
+#define GL_FOG_COORD_ARRAY_ADDRESS_NV 0x8F28
+#define GL_ELEMENT_ARRAY_ADDRESS_NV 0x8F29
+#define GL_VERTEX_ATTRIB_ARRAY_LENGTH_NV 0x8F2A
+#define GL_VERTEX_ARRAY_LENGTH_NV 0x8F2B
+#define GL_NORMAL_ARRAY_LENGTH_NV 0x8F2C
+#define GL_COLOR_ARRAY_LENGTH_NV 0x8F2D
+#define GL_INDEX_ARRAY_LENGTH_NV 0x8F2E
+#define GL_TEXTURE_COORD_ARRAY_LENGTH_NV 0x8F2F
+#define GL_EDGE_FLAG_ARRAY_LENGTH_NV 0x8F30
+#define GL_SECONDARY_COLOR_ARRAY_LENGTH_NV 0x8F31
+#define GL_FOG_COORD_ARRAY_LENGTH_NV 0x8F32
+#define GL_ELEMENT_ARRAY_LENGTH_NV 0x8F33
+#define GL_DRAW_INDIRECT_UNIFIED_NV 0x8F40
+#define GL_DRAW_INDIRECT_ADDRESS_NV 0x8F41
+#define GL_DRAW_INDIRECT_LENGTH_NV 0x8F42
+#endif
+
+#ifndef GL_NV_texture_barrier
+#endif
+
+#ifndef GL_AMD_shader_stencil_export
+#endif
+
+#ifndef GL_AMD_seamless_cubemap_per_texture
+
+#endif
+
+#ifndef GL_AMD_conservative_depth
+#endif
+
+#ifndef GL_EXT_shader_image_load_store
+#define GL_MAX_IMAGE_UNITS_EXT 0x8F38
+#define GL_MAX_COMBINED_IMAGE_UNITS_AND_FRAGMENT_OUTPUTS_EXT 0x8F39
+#define GL_IMAGE_BINDING_NAME_EXT 0x8F3A
+#define GL_IMAGE_BINDING_LEVEL_EXT 0x8F3B
+#define GL_IMAGE_BINDING_LAYERED_EXT 0x8F3C
+#define GL_IMAGE_BINDING_LAYER_EXT 0x8F3D
+#define GL_IMAGE_BINDING_ACCESS_EXT 0x8F3E
+#define GL_IMAGE_1D_EXT 0x904C
+#define GL_IMAGE_2D_EXT 0x904D
+#define GL_IMAGE_3D_EXT 0x904E
+#define GL_IMAGE_2D_RECT_EXT 0x904F
+#define GL_IMAGE_CUBE_EXT 0x9050
+#define GL_IMAGE_BUFFER_EXT 0x9051
+#define GL_IMAGE_1D_ARRAY_EXT 0x9052
+#define GL_IMAGE_2D_ARRAY_EXT 0x9053
+#define GL_IMAGE_CUBE_MAP_ARRAY_EXT 0x9054
+#define GL_IMAGE_2D_MULTISAMPLE_EXT 0x9055
+#define GL_IMAGE_2D_MULTISAMPLE_ARRAY_EXT 0x9056
+#define GL_INT_IMAGE_1D_EXT 0x9057
+#define GL_INT_IMAGE_2D_EXT 0x9058
+#define GL_INT_IMAGE_3D_EXT 0x9059
+#define GL_INT_IMAGE_2D_RECT_EXT 0x905A
+#define GL_INT_IMAGE_CUBE_EXT 0x905B
+#define GL_INT_IMAGE_BUFFER_EXT 0x905C
+#define GL_INT_IMAGE_1D_ARRAY_EXT 0x905D
+#define GL_INT_IMAGE_2D_ARRAY_EXT 0x905E
+#define GL_INT_IMAGE_CUBE_MAP_ARRAY_EXT 0x905F
+#define GL_INT_IMAGE_2D_MULTISAMPLE_EXT 0x9060
+#define GL_INT_IMAGE_2D_MULTISAMPLE_ARRAY_EXT 0x9061
+#define GL_UNSIGNED_INT_IMAGE_1D_EXT 0x9062
+#define GL_UNSIGNED_INT_IMAGE_2D_EXT 0x9063
+#define GL_UNSIGNED_INT_IMAGE_3D_EXT 0x9064
+#define GL_UNSIGNED_INT_IMAGE_2D_RECT_EXT 0x9065
+#define GL_UNSIGNED_INT_IMAGE_CUBE_EXT 0x9066
+#define GL_UNSIGNED_INT_IMAGE_BUFFER_EXT 0x9067
+#define GL_UNSIGNED_INT_IMAGE_1D_ARRAY_EXT 0x9068
+#define GL_UNSIGNED_INT_IMAGE_2D_ARRAY_EXT 0x9069
+#define GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY_EXT 0x906A
+#define GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE_EXT 0x906B
+#define GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE_ARRAY_EXT 0x906C
+#define GL_MAX_IMAGE_SAMPLES_EXT 0x906D
+#define GL_IMAGE_BINDING_FORMAT_EXT 0x906E
+#define GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT_EXT 0x00000001
+#define GL_ELEMENT_ARRAY_BARRIER_BIT_EXT 0x00000002
+#define GL_UNIFORM_BARRIER_BIT_EXT 0x00000004
+#define GL_TEXTURE_FETCH_BARRIER_BIT_EXT 0x00000008
+#define GL_SHADER_IMAGE_ACCESS_BARRIER_BIT_EXT 0x00000020
+#define GL_COMMAND_BARRIER_BIT_EXT 0x00000040
+#define GL_PIXEL_BUFFER_BARRIER_BIT_EXT 0x00000080
+#define GL_TEXTURE_UPDATE_BARRIER_BIT_EXT 0x00000100
+#define GL_BUFFER_UPDATE_BARRIER_BIT_EXT 0x00000200
+#define GL_FRAMEBUFFER_BARRIER_BIT_EXT 0x00000400
+#define GL_TRANSFORM_FEEDBACK_BARRIER_BIT_EXT 0x00000800
+#define GL_ATOMIC_COUNTER_BARRIER_BIT_EXT 0x00001000
+#define GL_ALL_BARRIER_BITS_EXT 0xFFFFFFFF
+#endif
+
+#ifndef GL_EXT_vertex_attrib_64bit
+
+#define GL_DOUBLE_VEC2_EXT 0x8FFC
+#define GL_DOUBLE_VEC3_EXT 0x8FFD
+#define GL_DOUBLE_VEC4_EXT 0x8FFE
+#define GL_DOUBLE_MAT2_EXT 0x8F46
+#define GL_DOUBLE_MAT3_EXT 0x8F47
+#define GL_DOUBLE_MAT4_EXT 0x8F48
+#define GL_DOUBLE_MAT2x3_EXT 0x8F49
+#define GL_DOUBLE_MAT2x4_EXT 0x8F4A
+#define GL_DOUBLE_MAT3x2_EXT 0x8F4B
+#define GL_DOUBLE_MAT3x4_EXT 0x8F4C
+#define GL_DOUBLE_MAT4x2_EXT 0x8F4D
+#define GL_DOUBLE_MAT4x3_EXT 0x8F4E
+#endif
+
+#ifndef GL_NV_gpu_program5
+#define GL_MAX_GEOMETRY_PROGRAM_INVOCATIONS_NV 0x8E5A
+#define GL_MIN_FRAGMENT_INTERPOLATION_OFFSET_NV 0x8E5B
+#define GL_MAX_FRAGMENT_INTERPOLATION_OFFSET_NV 0x8E5C
+#define GL_FRAGMENT_PROGRAM_INTERPOLATION_OFFSET_BITS_NV 0x8E5D
+#define GL_MAX_PROGRAM_SUBROUTINE_PARAMETERS_NV 0x8F44
+#define GL_MAX_PROGRAM_SUBROUTINE_NUM_NV 0x8F45
+#endif
+
+#ifndef GL_NV_gpu_shader5
+#define GL_INT64_NV 0x140E
+#define GL_UNSIGNED_INT64_NV 0x140F
+#define GL_INT8_NV 0x8FE0
+#define GL_INT8_VEC2_NV 0x8FE1
+#define GL_INT8_VEC3_NV 0x8FE2
+#define GL_INT8_VEC4_NV 0x8FE3
+#define GL_INT16_NV 0x8FE4
+#define GL_INT16_VEC2_NV 0x8FE5
+#define GL_INT16_VEC3_NV 0x8FE6
+#define GL_INT16_VEC4_NV 0x8FE7
+#define GL_INT64_VEC2_NV 0x8FE9
+#define GL_INT64_VEC3_NV 0x8FEA
+#define GL_INT64_VEC4_NV 0x8FEB
+#define GL_UNSIGNED_INT8_NV 0x8FEC
+#define GL_UNSIGNED_INT8_VEC2_NV 0x8FED
+#define GL_UNSIGNED_INT8_VEC3_NV 0x8FEE
+#define GL_UNSIGNED_INT8_VEC4_NV 0x8FEF
+#define GL_UNSIGNED_INT16_NV 0x8FF0
+#define GL_UNSIGNED_INT16_VEC2_NV 0x8FF1
+#define GL_UNSIGNED_INT16_VEC3_NV 0x8FF2
+#define GL_UNSIGNED_INT16_VEC4_NV 0x8FF3
+#define GL_UNSIGNED_INT64_VEC2_NV 0x8FF5
+#define GL_UNSIGNED_INT64_VEC3_NV 0x8FF6
+#define GL_UNSIGNED_INT64_VEC4_NV 0x8FF7
+#define GL_FLOAT16_NV 0x8FF8
+#define GL_FLOAT16_VEC2_NV 0x8FF9
+#define GL_FLOAT16_VEC3_NV 0x8FFA
+#define GL_FLOAT16_VEC4_NV 0x8FFB
+
+#endif
+
+#ifndef GL_NV_shader_buffer_store
+#define GL_SHADER_GLOBAL_ACCESS_BARRIER_BIT_NV 0x00000010
+
+#endif
+
+#ifndef GL_NV_tessellation_program5
+#define GL_MAX_PROGRAM_PATCH_ATTRIBS_NV 0x86D8
+#define GL_TESS_CONTROL_PROGRAM_NV 0x891E
+#define GL_TESS_EVALUATION_PROGRAM_NV 0x891F
+#define GL_TESS_CONTROL_PROGRAM_PARAMETER_BUFFER_NV 0x8C74
+#define GL_TESS_EVALUATION_PROGRAM_PARAMETER_BUFFER_NV 0x8C75
+#endif
+
+#ifndef GL_NV_vertex_attrib_integer_64bit
+
+#endif
+
+#ifndef GL_NV_multisample_coverage
+#define GL_COVERAGE_SAMPLES_NV 0x80A9
+#define GL_COLOR_SAMPLES_NV 0x8E20
+#endif
+
+#ifndef GL_AMD_name_gen_delete
+#define GL_DATA_BUFFER_AMD 0x9151
+#define GL_PERFORMANCE_MONITOR_AMD 0x9152
+#define GL_QUERY_OBJECT_AMD 0x9153
+#define GL_VERTEX_ARRAY_OBJECT_AMD 0x9154
+#define GL_SAMPLER_OBJECT_AMD 0x9155
+#endif
+
+#ifndef GL_AMD_debug_output
+#define GL_MAX_DEBUG_LOGGED_MESSAGES_AMD 0x9144
+#define GL_DEBUG_LOGGED_MESSAGES_AMD 0x9145
+#define GL_DEBUG_SEVERITY_HIGH_AMD 0x9146
+#define GL_DEBUG_SEVERITY_MEDIUM_AMD 0x9147
+#define GL_DEBUG_SEVERITY_LOW_AMD 0x9148
+#define GL_DEBUG_CATEGORY_API_ERROR_AMD 0x9149
+#define GL_DEBUG_CATEGORY_WINDOW_SYSTEM_AMD 0x914A
+#define GL_DEBUG_CATEGORY_DEPRECATION_AMD 0x914B
+#define GL_DEBUG_CATEGORY_UNDEFINED_BEHAVIOR_AMD 0x914C
+#define GL_DEBUG_CATEGORY_PERFORMANCE_AMD 0x914D
+#define GL_DEBUG_CATEGORY_SHADER_COMPILER_AMD 0x914E
+#define GL_DEBUG_CATEGORY_APPLICATION_AMD 0x914F
+#define GL_DEBUG_CATEGORY_OTHER_AMD 0x9150
+#endif
+
+#ifndef GL_NV_vdpau_interop
+#define GL_SURFACE_STATE_NV 0x86EB
+#define GL_SURFACE_REGISTERED_NV 0x86FD
+#define GL_SURFACE_MAPPED_NV 0x8700
+#define GL_WRITE_DISCARD_NV 0x88BE
+#endif
+
+#ifndef GL_AMD_transform_feedback3_lines_triangles
+#endif
+
+#include <stddef.h>
+#ifndef GL_VERSION_2_0
+
+typedef char GLchar;
+#endif
+
+#ifndef GL_VERSION_1_5
+
+#if defined(__APPLE__)
+typedef long GLintptr;
+typedef long GLsizeiptr;
+#else
+typedef ptrdiff_t GLintptr;
+typedef ptrdiff_t GLsizeiptr;
+#endif
+#endif
+
+#ifndef GL_ARB_vertex_buffer_object
+
+#if defined(__APPLE__)
+typedef long GLintptrARB;
+typedef long GLsizeiptrARB;
+#else
+typedef ptrdiff_t GLintptrARB;
+typedef ptrdiff_t GLsizeiptrARB;
+#endif
+#endif
+
+#ifndef GL_ARB_shader_objects
+
+typedef char GLcharARB;
+#if defined(__APPLE__)
+typedef void *GLhandleARB;
+#else
+typedef unsigned int GLhandleARB;
+#endif
+#endif
+
+#ifndef GL_ARB_half_float_pixel
+typedef unsigned short GLhalfARB;
+#endif
+
+#ifndef GL_NV_half_float
+typedef unsigned short GLhalfNV;
+#endif
+
+#ifndef GLEXT_64_TYPES_DEFINED
+
+#define GLEXT_64_TYPES_DEFINED
+
+#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
+#include <inttypes.h>
+#elif defined(__sun__) || defined(__digital__)
+#include <inttypes.h>
+#if defined(__STDC__)
+#if defined(__arch64__) || defined(_LP64)
+typedef long int int64_t;
+typedef unsigned long int uint64_t;
+#else
+typedef long long int int64_t;
+typedef unsigned long long int uint64_t;
+#endif
+#endif
+#elif defined( __VMS ) || defined(__sgi)
+#include <inttypes.h>
+#elif defined(__SCO__) || defined(__USLC__)
+#include <stdint.h>
+#elif defined(__UNIXOS2__) || defined(__SOL64__)
+typedef long int int32_t;
+typedef long long int int64_t;
+typedef unsigned long long int uint64_t;
+#elif defined(_WIN32) && defined(__GNUC__)
+#include <stdint.h>
+#elif defined(_WIN32)
+typedef __int32 int32_t;
+typedef __int64 int64_t;
+typedef unsigned __int64 uint64_t;
+#else
+
+#include <inttypes.h>
+#endif
+#endif
+
+#ifndef GL_EXT_timer_query
+typedef int64_t GLint64EXT;
+typedef uint64_t GLuint64EXT;
+#endif
+
+#ifndef GL_ARB_sync
+typedef int64_t GLint64;
+typedef uint64_t GLuint64;
+typedef struct __GLsync *GLsync;
+#endif
+
+#ifndef GL_ARB_cl_event
+
+struct _cl_context;
+struct _cl_event;
+#endif
+
+#ifndef GL_ARB_debug_output
+typedef void (APIENTRY *GLDEBUGPROCARB)(GLenum source,GLenum type,GLuint id,GLenum severity,GLsizei length,const GLchar *message,GLvoid *userParam);
+#endif
+
+#ifndef GL_AMD_debug_output
+typedef void (APIENTRY *GLDEBUGPROCAMD)(GLuint id,GLenum category,GLenum severity,GLsizei length,const GLchar *message,GLvoid *userParam);
+#endif
+
+#ifndef GL_NV_vdpau_interop
+typedef GLintptr GLvdpauSurfaceNV;
+#endif
+
+#ifndef GL_VERSION_1_2
+#define GL_VERSION_1_2 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glBlendColor (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
+GLAPI void APIENTRY glBlendEquation (GLenum mode);
+GLAPI void APIENTRY glDrawRangeElements (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid *indices);
+GLAPI void APIENTRY glTexImage3D (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid *pixels);
+GLAPI void APIENTRY glTexSubImage3D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid *pixels);
+GLAPI void APIENTRY glCopyTexSubImage3D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+#endif
+typedef void (APIENTRYP PFNGLBLENDCOLORPROC) (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
+typedef void (APIENTRYP PFNGLBLENDEQUATIONPROC) (GLenum mode);
+typedef void (APIENTRYP PFNGLDRAWRANGEELEMENTSPROC) (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid *indices);
+typedef void (APIENTRYP PFNGLTEXIMAGE3DPROC) (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid *pixels);
+typedef void (APIENTRYP PFNGLTEXSUBIMAGE3DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid *pixels);
+typedef void (APIENTRYP PFNGLCOPYTEXSUBIMAGE3DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+#endif
+
+#ifndef GL_VERSION_1_2_DEPRECATED
+#define GL_VERSION_1_2_DEPRECATED 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glColorTable (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const GLvoid *table);
+GLAPI void APIENTRY glColorTableParameterfv (GLenum target, GLenum pname, const GLfloat *params);
+GLAPI void APIENTRY glColorTableParameteriv (GLenum target, GLenum pname, const GLint *params);
+GLAPI void APIENTRY glCopyColorTable (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width);
+GLAPI void APIENTRY glGetColorTable (GLenum target, GLenum format, GLenum type, GLvoid *table);
+GLAPI void APIENTRY glGetColorTableParameterfv (GLenum target, GLenum pname, GLfloat *params);
+GLAPI void APIENTRY glGetColorTableParameteriv (GLenum target, GLenum pname, GLint *params);
+GLAPI void APIENTRY glColorSubTable (GLenum target, GLsizei start, GLsizei count, GLenum format, GLenum type, const GLvoid *data);
+GLAPI void APIENTRY glCopyColorSubTable (GLenum target, GLsizei start, GLint x, GLint y, GLsizei width);
+GLAPI void APIENTRY glConvolutionFilter1D (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const GLvoid *image);
+GLAPI void APIENTRY glConvolutionFilter2D (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *image);
+GLAPI void APIENTRY glConvolutionParameterf (GLenum target, GLenum pname, GLfloat params);
+GLAPI void APIENTRY glConvolutionParameterfv (GLenum target, GLenum pname, const GLfloat *params);
+GLAPI void APIENTRY glConvolutionParameteri (GLenum target, GLenum pname, GLint params);
+GLAPI void APIENTRY glConvolutionParameteriv (GLenum target, GLenum pname, const GLint *params);
+GLAPI void APIENTRY glCopyConvolutionFilter1D (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width);
+GLAPI void APIENTRY glCopyConvolutionFilter2D (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height);
+GLAPI void APIENTRY glGetConvolutionFilter (GLenum target, GLenum format, GLenum type, GLvoid *image);
+GLAPI void APIENTRY glGetConvolutionParameterfv (GLenum target, GLenum pname, GLfloat *params);
+GLAPI void APIENTRY glGetConvolutionParameteriv (GLenum target, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetSeparableFilter (GLenum target, GLenum format, GLenum type, GLvoid *row, GLvoid *column, GLvoid *span);
+GLAPI void APIENTRY glSeparableFilter2D (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *row, const GLvoid *column);
+GLAPI void APIENTRY glGetHistogram (GLenum target, GLboolean reset, GLenum format, GLenum type, GLvoid *values);
+GLAPI void APIENTRY glGetHistogramParameterfv (GLenum target, GLenum pname, GLfloat *params);
+GLAPI void APIENTRY glGetHistogramParameteriv (GLenum target, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetMinmax (GLenum target, GLboolean reset, GLenum format, GLenum type, GLvoid *values);
+GLAPI void APIENTRY glGetMinmaxParameterfv (GLenum target, GLenum pname, GLfloat *params);
+GLAPI void APIENTRY glGetMinmaxParameteriv (GLenum target, GLenum pname, GLint *params);
+GLAPI void APIENTRY glHistogram (GLenum target, GLsizei width, GLenum internalformat, GLboolean sink);
+GLAPI void APIENTRY glMinmax (GLenum target, GLenum internalformat, GLboolean sink);
+GLAPI void APIENTRY glResetHistogram (GLenum target);
+GLAPI void APIENTRY glResetMinmax (GLenum target);
+#endif
+typedef void (APIENTRYP PFNGLCOLORTABLEPROC) (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const GLvoid *table);
+typedef void (APIENTRYP PFNGLCOLORTABLEPARAMETERFVPROC) (GLenum target, GLenum pname, const GLfloat *params);
+typedef void (APIENTRYP PFNGLCOLORTABLEPARAMETERIVPROC) (GLenum target, GLenum pname, const GLint *params);
+typedef void (APIENTRYP PFNGLCOPYCOLORTABLEPROC) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width);
+typedef void (APIENTRYP PFNGLGETCOLORTABLEPROC) (GLenum target, GLenum format, GLenum type, GLvoid *table);
+typedef void (APIENTRYP PFNGLGETCOLORTABLEPARAMETERFVPROC) (GLenum target, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETCOLORTABLEPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLCOLORSUBTABLEPROC) (GLenum target, GLsizei start, GLsizei count, GLenum format, GLenum type, const GLvoid *data);
+typedef void (APIENTRYP PFNGLCOPYCOLORSUBTABLEPROC) (GLenum target, GLsizei start, GLint x, GLint y, GLsizei width);
+typedef void (APIENTRYP PFNGLCONVOLUTIONFILTER1DPROC) (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const GLvoid *image);
+typedef void (APIENTRYP PFNGLCONVOLUTIONFILTER2DPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *image);
+typedef void (APIENTRYP PFNGLCONVOLUTIONPARAMETERFPROC) (GLenum target, GLenum pname, GLfloat params);
+typedef void (APIENTRYP PFNGLCONVOLUTIONPARAMETERFVPROC) (GLenum target, GLenum pname, const GLfloat *params);
+typedef void (APIENTRYP PFNGLCONVOLUTIONPARAMETERIPROC) (GLenum target, GLenum pname, GLint params);
+typedef void (APIENTRYP PFNGLCONVOLUTIONPARAMETERIVPROC) (GLenum target, GLenum pname, const GLint *params);
+typedef void (APIENTRYP PFNGLCOPYCONVOLUTIONFILTER1DPROC) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width);
+typedef void (APIENTRYP PFNGLCOPYCONVOLUTIONFILTER2DPROC) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height);
+typedef void (APIENTRYP PFNGLGETCONVOLUTIONFILTERPROC) (GLenum target, GLenum format, GLenum type, GLvoid *image);
+typedef void (APIENTRYP PFNGLGETCONVOLUTIONPARAMETERFVPROC) (GLenum target, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETCONVOLUTIONPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETSEPARABLEFILTERPROC) (GLenum target, GLenum format, GLenum type, GLvoid *row, GLvoid *column, GLvoid *span);
+typedef void (APIENTRYP PFNGLSEPARABLEFILTER2DPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *row, const GLvoid *column);
+typedef void (APIENTRYP PFNGLGETHISTOGRAMPROC) (GLenum target, GLboolean reset, GLenum format, GLenum type, GLvoid *values);
+typedef void (APIENTRYP PFNGLGETHISTOGRAMPARAMETERFVPROC) (GLenum target, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETHISTOGRAMPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETMINMAXPROC) (GLenum target, GLboolean reset, GLenum format, GLenum type, GLvoid *values);
+typedef void (APIENTRYP PFNGLGETMINMAXPARAMETERFVPROC) (GLenum target, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETMINMAXPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLHISTOGRAMPROC) (GLenum target, GLsizei width, GLenum internalformat, GLboolean sink);
+typedef void (APIENTRYP PFNGLMINMAXPROC) (GLenum target, GLenum internalformat, GLboolean sink);
+typedef void (APIENTRYP PFNGLRESETHISTOGRAMPROC) (GLenum target);
+typedef void (APIENTRYP PFNGLRESETMINMAXPROC) (GLenum target);
+#endif
+
+#ifndef GL_VERSION_1_3
+#define GL_VERSION_1_3 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glActiveTexture (GLenum texture);
+GLAPI void APIENTRY glSampleCoverage (GLclampf value, GLboolean invert);
+GLAPI void APIENTRY glCompressedTexImage3D (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid *data);
+GLAPI void APIENTRY glCompressedTexImage2D (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *data);
+GLAPI void APIENTRY glCompressedTexImage1D (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const GLvoid *data);
+GLAPI void APIENTRY glCompressedTexSubImage3D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid *data);
+GLAPI void APIENTRY glCompressedTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid *data);
+GLAPI void APIENTRY glCompressedTexSubImage1D (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const GLvoid *data);
+GLAPI void APIENTRY glGetCompressedTexImage (GLenum target, GLint level, GLvoid *img);
+#endif
+typedef void (APIENTRYP PFNGLACTIVETEXTUREPROC) (GLenum texture);
+typedef void (APIENTRYP PFNGLSAMPLECOVERAGEPROC) (GLclampf value, GLboolean invert);
+typedef void (APIENTRYP PFNGLCOMPRESSEDTEXIMAGE3DPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid *data);
+typedef void (APIENTRYP PFNGLCOMPRESSEDTEXIMAGE2DPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *data);
+typedef void (APIENTRYP PFNGLCOMPRESSEDTEXIMAGE1DPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const GLvoid *data);
+typedef void (APIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid *data);
+typedef void (APIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid *data);
+typedef void (APIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE1DPROC) (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const GLvoid *data);
+typedef void (APIENTRYP PFNGLGETCOMPRESSEDTEXIMAGEPROC) (GLenum target, GLint level, GLvoid *img);
+#endif
+
+#ifndef GL_VERSION_1_3_DEPRECATED
+#define GL_VERSION_1_3_DEPRECATED 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glClientActiveTexture (GLenum texture);
+GLAPI void APIENTRY glMultiTexCoord1d (GLenum target, GLdouble s);
+GLAPI void APIENTRY glMultiTexCoord1dv (GLenum target, const GLdouble *v);
+GLAPI void APIENTRY glMultiTexCoord1f (GLenum target, GLfloat s);
+GLAPI void APIENTRY glMultiTexCoord1fv (GLenum target, const GLfloat *v);
+GLAPI void APIENTRY glMultiTexCoord1i (GLenum target, GLint s);
+GLAPI void APIENTRY glMultiTexCoord1iv (GLenum target, const GLint *v);
+GLAPI void APIENTRY glMultiTexCoord1s (GLenum target, GLshort s);
+GLAPI void APIENTRY glMultiTexCoord1sv (GLenum target, const GLshort *v);
+GLAPI void APIENTRY glMultiTexCoord2d (GLenum target, GLdouble s, GLdouble t);
+GLAPI void APIENTRY glMultiTexCoord2dv (GLenum target, const GLdouble *v);
+GLAPI void APIENTRY glMultiTexCoord2f (GLenum target, GLfloat s, GLfloat t);
+GLAPI void APIENTRY glMultiTexCoord2fv (GLenum target, const GLfloat *v);
+GLAPI void APIENTRY glMultiTexCoord2i (GLenum target, GLint s, GLint t);
+GLAPI void APIENTRY glMultiTexCoord2iv (GLenum target, const GLint *v);
+GLAPI void APIENTRY glMultiTexCoord2s (GLenum target, GLshort s, GLshort t);
+GLAPI void APIENTRY glMultiTexCoord2sv (GLenum target, const GLshort *v);
+GLAPI void APIENTRY glMultiTexCoord3d (GLenum target, GLdouble s, GLdouble t, GLdouble r);
+GLAPI void APIENTRY glMultiTexCoord3dv (GLenum target, const GLdouble *v);
+GLAPI void APIENTRY glMultiTexCoord3f (GLenum target, GLfloat s, GLfloat t, GLfloat r);
+GLAPI void APIENTRY glMultiTexCoord3fv (GLenum target, const GLfloat *v);
+GLAPI void APIENTRY glMultiTexCoord3i (GLenum target, GLint s, GLint t, GLint r);
+GLAPI void APIENTRY glMultiTexCoord3iv (GLenum target, const GLint *v);
+GLAPI void APIENTRY glMultiTexCoord3s (GLenum target, GLshort s, GLshort t, GLshort r);
+GLAPI void APIENTRY glMultiTexCoord3sv (GLenum target, const GLshort *v);
+GLAPI void APIENTRY glMultiTexCoord4d (GLenum target, GLdouble s, GLdouble t, GLdouble r, GLdouble q);
+GLAPI void APIENTRY glMultiTexCoord4dv (GLenum target, const GLdouble *v);
+GLAPI void APIENTRY glMultiTexCoord4f (GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q);
+GLAPI void APIENTRY glMultiTexCoord4fv (GLenum target, const GLfloat *v);
+GLAPI void APIENTRY glMultiTexCoord4i (GLenum target, GLint s, GLint t, GLint r, GLint q);
+GLAPI void APIENTRY glMultiTexCoord4iv (GLenum target, const GLint *v);
+GLAPI void APIENTRY glMultiTexCoord4s (GLenum target, GLshort s, GLshort t, GLshort r, GLshort q);
+GLAPI void APIENTRY glMultiTexCoord4sv (GLenum target, const GLshort *v);
+GLAPI void APIENTRY glLoadTransposeMatrixf (const GLfloat *m);
+GLAPI void APIENTRY glLoadTransposeMatrixd (const GLdouble *m);
+GLAPI void APIENTRY glMultTransposeMatrixf (const GLfloat *m);
+GLAPI void APIENTRY glMultTransposeMatrixd (const GLdouble *m);
+#endif
+typedef void (APIENTRYP PFNGLCLIENTACTIVETEXTUREPROC) (GLenum texture);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD1DPROC) (GLenum target, GLdouble s);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD1DVPROC) (GLenum target, const GLdouble *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD1FPROC) (GLenum target, GLfloat s);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD1FVPROC) (GLenum target, const GLfloat *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD1IPROC) (GLenum target, GLint s);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD1IVPROC) (GLenum target, const GLint *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD1SPROC) (GLenum target, GLshort s);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD1SVPROC) (GLenum target, const GLshort *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD2DPROC) (GLenum target, GLdouble s, GLdouble t);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD2DVPROC) (GLenum target, const GLdouble *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD2FPROC) (GLenum target, GLfloat s, GLfloat t);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD2FVPROC) (GLenum target, const GLfloat *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD2IPROC) (GLenum target, GLint s, GLint t);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD2IVPROC) (GLenum target, const GLint *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD2SPROC) (GLenum target, GLshort s, GLshort t);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD2SVPROC) (GLenum target, const GLshort *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD3DPROC) (GLenum target, GLdouble s, GLdouble t, GLdouble r);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD3DVPROC) (GLenum target, const GLdouble *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD3FPROC) (GLenum target, GLfloat s, GLfloat t, GLfloat r);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD3FVPROC) (GLenum target, const GLfloat *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD3IPROC) (GLenum target, GLint s, GLint t, GLint r);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD3IVPROC) (GLenum target, const GLint *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD3SPROC) (GLenum target, GLshort s, GLshort t, GLshort r);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD3SVPROC) (GLenum target, const GLshort *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD4DPROC) (GLenum target, GLdouble s, GLdouble t, GLdouble r, GLdouble q);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD4DVPROC) (GLenum target, const GLdouble *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD4FPROC) (GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD4FVPROC) (GLenum target, const GLfloat *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD4IPROC) (GLenum target, GLint s, GLint t, GLint r, GLint q);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD4IVPROC) (GLenum target, const GLint *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD4SPROC) (GLenum target, GLshort s, GLshort t, GLshort r, GLshort q);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD4SVPROC) (GLenum target, const GLshort *v);
+typedef void (APIENTRYP PFNGLLOADTRANSPOSEMATRIXFPROC) (const GLfloat *m);
+typedef void (APIENTRYP PFNGLLOADTRANSPOSEMATRIXDPROC) (const GLdouble *m);
+typedef void (APIENTRYP PFNGLMULTTRANSPOSEMATRIXFPROC) (const GLfloat *m);
+typedef void (APIENTRYP PFNGLMULTTRANSPOSEMATRIXDPROC) (const GLdouble *m);
+#endif
+
+#ifndef GL_VERSION_1_4
+#define GL_VERSION_1_4 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glBlendFuncSeparate (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha);
+GLAPI void APIENTRY glMultiDrawArrays (GLenum mode, const GLint *first, const GLsizei *count, GLsizei primcount);
+GLAPI void APIENTRY glMultiDrawElements (GLenum mode, const GLsizei *count, GLenum type, const GLvoid* *indices, GLsizei primcount);
+GLAPI void APIENTRY glPointParameterf (GLenum pname, GLfloat param);
+GLAPI void APIENTRY glPointParameterfv (GLenum pname, const GLfloat *params);
+GLAPI void APIENTRY glPointParameteri (GLenum pname, GLint param);
+GLAPI void APIENTRY glPointParameteriv (GLenum pname, const GLint *params);
+#endif
+typedef void (APIENTRYP PFNGLBLENDFUNCSEPARATEPROC) (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha);
+typedef void (APIENTRYP PFNGLMULTIDRAWARRAYSPROC) (GLenum mode, const GLint *first, const GLsizei *count, GLsizei primcount);
+typedef void (APIENTRYP PFNGLMULTIDRAWELEMENTSPROC) (GLenum mode, const GLsizei *count, GLenum type, const GLvoid* *indices, GLsizei primcount);
+typedef void (APIENTRYP PFNGLPOINTPARAMETERFPROC) (GLenum pname, GLfloat param);
+typedef void (APIENTRYP PFNGLPOINTPARAMETERFVPROC) (GLenum pname, const GLfloat *params);
+typedef void (APIENTRYP PFNGLPOINTPARAMETERIPROC) (GLenum pname, GLint param);
+typedef void (APIENTRYP PFNGLPOINTPARAMETERIVPROC) (GLenum pname, const GLint *params);
+#endif
+
+#ifndef GL_VERSION_1_4_DEPRECATED
+#define GL_VERSION_1_4_DEPRECATED 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glFogCoordf (GLfloat coord);
+GLAPI void APIENTRY glFogCoordfv (const GLfloat *coord);
+GLAPI void APIENTRY glFogCoordd (GLdouble coord);
+GLAPI void APIENTRY glFogCoorddv (const GLdouble *coord);
+GLAPI void APIENTRY glFogCoordPointer (GLenum type, GLsizei stride, const GLvoid *pointer);
+GLAPI void APIENTRY glSecondaryColor3b (GLbyte red, GLbyte green, GLbyte blue);
+GLAPI void APIENTRY glSecondaryColor3bv (const GLbyte *v);
+GLAPI void APIENTRY glSecondaryColor3d (GLdouble red, GLdouble green, GLdouble blue);
+GLAPI void APIENTRY glSecondaryColor3dv (const GLdouble *v);
+GLAPI void APIENTRY glSecondaryColor3f (GLfloat red, GLfloat green, GLfloat blue);
+GLAPI void APIENTRY glSecondaryColor3fv (const GLfloat *v);
+GLAPI void APIENTRY glSecondaryColor3i (GLint red, GLint green, GLint blue);
+GLAPI void APIENTRY glSecondaryColor3iv (const GLint *v);
+GLAPI void APIENTRY glSecondaryColor3s (GLshort red, GLshort green, GLshort blue);
+GLAPI void APIENTRY glSecondaryColor3sv (const GLshort *v);
+GLAPI void APIENTRY glSecondaryColor3ub (GLubyte red, GLubyte green, GLubyte blue);
+GLAPI void APIENTRY glSecondaryColor3ubv (const GLubyte *v);
+GLAPI void APIENTRY glSecondaryColor3ui (GLuint red, GLuint green, GLuint blue);
+GLAPI void APIENTRY glSecondaryColor3uiv (const GLuint *v);
+GLAPI void APIENTRY glSecondaryColor3us (GLushort red, GLushort green, GLushort blue);
+GLAPI void APIENTRY glSecondaryColor3usv (const GLushort *v);
+GLAPI void APIENTRY glSecondaryColorPointer (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);
+GLAPI void APIENTRY glWindowPos2d (GLdouble x, GLdouble y);
+GLAPI void APIENTRY glWindowPos2dv (const GLdouble *v);
+GLAPI void APIENTRY glWindowPos2f (GLfloat x, GLfloat y);
+GLAPI void APIENTRY glWindowPos2fv (const GLfloat *v);
+GLAPI void APIENTRY glWindowPos2i (GLint x, GLint y);
+GLAPI void APIENTRY glWindowPos2iv (const GLint *v);
+GLAPI void APIENTRY glWindowPos2s (GLshort x, GLshort y);
+GLAPI void APIENTRY glWindowPos2sv (const GLshort *v);
+GLAPI void APIENTRY glWindowPos3d (GLdouble x, GLdouble y, GLdouble z);
+GLAPI void APIENTRY glWindowPos3dv (const GLdouble *v);
+GLAPI void APIENTRY glWindowPos3f (GLfloat x, GLfloat y, GLfloat z);
+GLAPI void APIENTRY glWindowPos3fv (const GLfloat *v);
+GLAPI void APIENTRY glWindowPos3i (GLint x, GLint y, GLint z);
+GLAPI void APIENTRY glWindowPos3iv (const GLint *v);
+GLAPI void APIENTRY glWindowPos3s (GLshort x, GLshort y, GLshort z);
+GLAPI void APIENTRY glWindowPos3sv (const GLshort *v);
+#endif
+typedef void (APIENTRYP PFNGLFOGCOORDFPROC) (GLfloat coord);
+typedef void (APIENTRYP PFNGLFOGCOORDFVPROC) (const GLfloat *coord);
+typedef void (APIENTRYP PFNGLFOGCOORDDPROC) (GLdouble coord);
+typedef void (APIENTRYP PFNGLFOGCOORDDVPROC) (const GLdouble *coord);
+typedef void (APIENTRYP PFNGLFOGCOORDPOINTERPROC) (GLenum type, GLsizei stride, const GLvoid *pointer);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3BPROC) (GLbyte red, GLbyte green, GLbyte blue);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3BVPROC) (const GLbyte *v);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3DPROC) (GLdouble red, GLdouble green, GLdouble blue);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3DVPROC) (const GLdouble *v);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3FPROC) (GLfloat red, GLfloat green, GLfloat blue);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3FVPROC) (const GLfloat *v);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3IPROC) (GLint red, GLint green, GLint blue);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3IVPROC) (const GLint *v);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3SPROC) (GLshort red, GLshort green, GLshort blue);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3SVPROC) (const GLshort *v);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3UBPROC) (GLubyte red, GLubyte green, GLubyte blue);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3UBVPROC) (const GLubyte *v);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3UIPROC) (GLuint red, GLuint green, GLuint blue);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3UIVPROC) (const GLuint *v);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3USPROC) (GLushort red, GLushort green, GLushort blue);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3USVPROC) (const GLushort *v);
+typedef void (APIENTRYP PFNGLSECONDARYCOLORPOINTERPROC) (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);
+typedef void (APIENTRYP PFNGLWINDOWPOS2DPROC) (GLdouble x, GLdouble y);
+typedef void (APIENTRYP PFNGLWINDOWPOS2DVPROC) (const GLdouble *v);
+typedef void (APIENTRYP PFNGLWINDOWPOS2FPROC) (GLfloat x, GLfloat y);
+typedef void (APIENTRYP PFNGLWINDOWPOS2FVPROC) (const GLfloat *v);
+typedef void (APIENTRYP PFNGLWINDOWPOS2IPROC) (GLint x, GLint y);
+typedef void (APIENTRYP PFNGLWINDOWPOS2IVPROC) (const GLint *v);
+typedef void (APIENTRYP PFNGLWINDOWPOS2SPROC) (GLshort x, GLshort y);
+typedef void (APIENTRYP PFNGLWINDOWPOS2SVPROC) (const GLshort *v);
+typedef void (APIENTRYP PFNGLWINDOWPOS3DPROC) (GLdouble x, GLdouble y, GLdouble z);
+typedef void (APIENTRYP PFNGLWINDOWPOS3DVPROC) (const GLdouble *v);
+typedef void (APIENTRYP PFNGLWINDOWPOS3FPROC) (GLfloat x, GLfloat y, GLfloat z);
+typedef void (APIENTRYP PFNGLWINDOWPOS3FVPROC) (const GLfloat *v);
+typedef void (APIENTRYP PFNGLWINDOWPOS3IPROC) (GLint x, GLint y, GLint z);
+typedef void (APIENTRYP PFNGLWINDOWPOS3IVPROC) (const GLint *v);
+typedef void (APIENTRYP PFNGLWINDOWPOS3SPROC) (GLshort x, GLshort y, GLshort z);
+typedef void (APIENTRYP PFNGLWINDOWPOS3SVPROC) (const GLshort *v);
+#endif
+
+#ifndef GL_VERSION_1_5
+#define GL_VERSION_1_5 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glGenQueries (GLsizei n, GLuint *ids);
+GLAPI void APIENTRY glDeleteQueries (GLsizei n, const GLuint *ids);
+GLAPI GLboolean APIENTRY glIsQuery (GLuint id);
+GLAPI void APIENTRY glBeginQuery (GLenum target, GLuint id);
+GLAPI void APIENTRY glEndQuery (GLenum target);
+GLAPI void APIENTRY glGetQueryiv (GLenum target, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetQueryObjectiv (GLuint id, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetQueryObjectuiv (GLuint id, GLenum pname, GLuint *params);
+GLAPI void APIENTRY glBindBuffer (GLenum target, GLuint buffer);
+GLAPI void APIENTRY glDeleteBuffers (GLsizei n, const GLuint *buffers);
+GLAPI void APIENTRY glGenBuffers (GLsizei n, GLuint *buffers);
+GLAPI GLboolean APIENTRY glIsBuffer (GLuint buffer);
+GLAPI void APIENTRY glBufferData (GLenum target, GLsizeiptr size, const GLvoid *data, GLenum usage);
+GLAPI void APIENTRY glBufferSubData (GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid *data);
+GLAPI void APIENTRY glGetBufferSubData (GLenum target, GLintptr offset, GLsizeiptr size, GLvoid *data);
+GLAPI GLvoid* APIENTRY glMapBuffer (GLenum target, GLenum access);
+GLAPI GLboolean APIENTRY glUnmapBuffer (GLenum target);
+GLAPI void APIENTRY glGetBufferParameteriv (GLenum target, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetBufferPointerv (GLenum target, GLenum pname, GLvoid* *params);
+#endif
+typedef void (APIENTRYP PFNGLGENQUERIESPROC) (GLsizei n, GLuint *ids);
+typedef void (APIENTRYP PFNGLDELETEQUERIESPROC) (GLsizei n, const GLuint *ids);
+typedef GLboolean (APIENTRYP PFNGLISQUERYPROC) (GLuint id);
+typedef void (APIENTRYP PFNGLBEGINQUERYPROC) (GLenum target, GLuint id);
+typedef void (APIENTRYP PFNGLENDQUERYPROC) (GLenum target);
+typedef void (APIENTRYP PFNGLGETQUERYIVPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETQUERYOBJECTIVPROC) (GLuint id, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETQUERYOBJECTUIVPROC) (GLuint id, GLenum pname, GLuint *params);
+typedef void (APIENTRYP PFNGLBINDBUFFERPROC) (GLenum target, GLuint buffer);
+typedef void (APIENTRYP PFNGLDELETEBUFFERSPROC) (GLsizei n, const GLuint *buffers);
+typedef void (APIENTRYP PFNGLGENBUFFERSPROC) (GLsizei n, GLuint *buffers);
+typedef GLboolean (APIENTRYP PFNGLISBUFFERPROC) (GLuint buffer);
+typedef void (APIENTRYP PFNGLBUFFERDATAPROC) (GLenum target, GLsizeiptr size, const GLvoid *data, GLenum usage);
+typedef void (APIENTRYP PFNGLBUFFERSUBDATAPROC) (GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid *data);
+typedef void (APIENTRYP PFNGLGETBUFFERSUBDATAPROC) (GLenum target, GLintptr offset, GLsizeiptr size, GLvoid *data);
+typedef GLvoid* (APIENTRYP PFNGLMAPBUFFERPROC) (GLenum target, GLenum access);
+typedef GLboolean (APIENTRYP PFNGLUNMAPBUFFERPROC) (GLenum target);
+typedef void (APIENTRYP PFNGLGETBUFFERPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETBUFFERPOINTERVPROC) (GLenum target, GLenum pname, GLvoid* *params);
+#endif
+
+#ifndef GL_VERSION_2_0
+#define GL_VERSION_2_0 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glBlendEquationSeparate (GLenum modeRGB, GLenum modeAlpha);
+GLAPI void APIENTRY glDrawBuffers (GLsizei n, const GLenum *bufs);
+GLAPI void APIENTRY glStencilOpSeparate (GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass);
+GLAPI void APIENTRY glStencilFuncSeparate (GLenum face, GLenum func, GLint ref, GLuint mask);
+GLAPI void APIENTRY glStencilMaskSeparate (GLenum face, GLuint mask);
+GLAPI void APIENTRY glAttachShader (GLuint program, GLuint shader);
+GLAPI void APIENTRY glBindAttribLocation (GLuint program, GLuint index, const GLchar *name);
+GLAPI void APIENTRY glCompileShader (GLuint shader);
+GLAPI GLuint APIENTRY glCreateProgram (void);
+GLAPI GLuint APIENTRY glCreateShader (GLenum type);
+GLAPI void APIENTRY glDeleteProgram (GLuint program);
+GLAPI void APIENTRY glDeleteShader (GLuint shader);
+GLAPI void APIENTRY glDetachShader (GLuint program, GLuint shader);
+GLAPI void APIENTRY glDisableVertexAttribArray (GLuint index);
+GLAPI void APIENTRY glEnableVertexAttribArray (GLuint index);
+GLAPI void APIENTRY glGetActiveAttrib (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name);
+GLAPI void APIENTRY glGetActiveUniform (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name);
+GLAPI void APIENTRY glGetAttachedShaders (GLuint program, GLsizei maxCount, GLsizei *count, GLuint *obj);
+GLAPI GLint APIENTRY glGetAttribLocation (GLuint program, const GLchar *name);
+GLAPI void APIENTRY glGetProgramiv (GLuint program, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetProgramInfoLog (GLuint program, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
+GLAPI void APIENTRY glGetShaderiv (GLuint shader, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetShaderInfoLog (GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
+GLAPI void APIENTRY glGetShaderSource (GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *source);
+GLAPI GLint APIENTRY glGetUniformLocation (GLuint program, const GLchar *name);
+GLAPI void APIENTRY glGetUniformfv (GLuint program, GLint location, GLfloat *params);
+GLAPI void APIENTRY glGetUniformiv (GLuint program, GLint location, GLint *params);
+GLAPI void APIENTRY glGetVertexAttribdv (GLuint index, GLenum pname, GLdouble *params);
+GLAPI void APIENTRY glGetVertexAttribfv (GLuint index, GLenum pname, GLfloat *params);
+GLAPI void APIENTRY glGetVertexAttribiv (GLuint index, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetVertexAttribPointerv (GLuint index, GLenum pname, GLvoid* *pointer);
+GLAPI GLboolean APIENTRY glIsProgram (GLuint program);
+GLAPI GLboolean APIENTRY glIsShader (GLuint shader);
+GLAPI void APIENTRY glLinkProgram (GLuint program);
+GLAPI void APIENTRY glShaderSource (GLuint shader, GLsizei count, const GLchar* *string, const GLint *length);
+GLAPI void APIENTRY glUseProgram (GLuint program);
+GLAPI void APIENTRY glUniform1f (GLint location, GLfloat v0);
+GLAPI void APIENTRY glUniform2f (GLint location, GLfloat v0, GLfloat v1);
+GLAPI void APIENTRY glUniform3f (GLint location, GLfloat v0, GLfloat v1, GLfloat v2);
+GLAPI void APIENTRY glUniform4f (GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
+GLAPI void APIENTRY glUniform1i (GLint location, GLint v0);
+GLAPI void APIENTRY glUniform2i (GLint location, GLint v0, GLint v1);
+GLAPI void APIENTRY glUniform3i (GLint location, GLint v0, GLint v1, GLint v2);
+GLAPI void APIENTRY glUniform4i (GLint location, GLint v0, GLint v1, GLint v2, GLint v3);
+GLAPI void APIENTRY glUniform1fv (GLint location, GLsizei count, const GLfloat *value);
+GLAPI void APIENTRY glUniform2fv (GLint location, GLsizei count, const GLfloat *value);
+GLAPI void APIENTRY glUniform3fv (GLint location, GLsizei count, const GLfloat *value);
+GLAPI void APIENTRY glUniform4fv (GLint location, GLsizei count, const GLfloat *value);
+GLAPI void APIENTRY glUniform1iv (GLint location, GLsizei count, const GLint *value);
+GLAPI void APIENTRY glUniform2iv (GLint location, GLsizei count, const GLint *value);
+GLAPI void APIENTRY glUniform3iv (GLint location, GLsizei count, const GLint *value);
+GLAPI void APIENTRY glUniform4iv (GLint location, GLsizei count, const GLint *value);
+GLAPI void APIENTRY glUniformMatrix2fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GLAPI void APIENTRY glUniformMatrix3fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GLAPI void APIENTRY glUniformMatrix4fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GLAPI void APIENTRY glValidateProgram (GLuint program);
+GLAPI void APIENTRY glVertexAttrib1d (GLuint index, GLdouble x);
+GLAPI void APIENTRY glVertexAttrib1dv (GLuint index, const GLdouble *v);
+GLAPI void APIENTRY glVertexAttrib1f (GLuint index, GLfloat x);
+GLAPI void APIENTRY glVertexAttrib1fv (GLuint index, const GLfloat *v);
+GLAPI void APIENTRY glVertexAttrib1s (GLuint index, GLshort x);
+GLAPI void APIENTRY glVertexAttrib1sv (GLuint index, const GLshort *v);
+GLAPI void APIENTRY glVertexAttrib2d (GLuint index, GLdouble x, GLdouble y);
+GLAPI void APIENTRY glVertexAttrib2dv (GLuint index, const GLdouble *v);
+GLAPI void APIENTRY glVertexAttrib2f (GLuint index, GLfloat x, GLfloat y);
+GLAPI void APIENTRY glVertexAttrib2fv (GLuint index, const GLfloat *v);
+GLAPI void APIENTRY glVertexAttrib2s (GLuint index, GLshort x, GLshort y);
+GLAPI void APIENTRY glVertexAttrib2sv (GLuint index, const GLshort *v);
+GLAPI void APIENTRY glVertexAttrib3d (GLuint index, GLdouble x, GLdouble y, GLdouble z);
+GLAPI void APIENTRY glVertexAttrib3dv (GLuint index, const GLdouble *v);
+GLAPI void APIENTRY glVertexAttrib3f (GLuint index, GLfloat x, GLfloat y, GLfloat z);
+GLAPI void APIENTRY glVertexAttrib3fv (GLuint index, const GLfloat *v);
+GLAPI void APIENTRY glVertexAttrib3s (GLuint index, GLshort x, GLshort y, GLshort z);
+GLAPI void APIENTRY glVertexAttrib3sv (GLuint index, const GLshort *v);
+GLAPI void APIENTRY glVertexAttrib4Nbv (GLuint index, const GLbyte *v);
+GLAPI void APIENTRY glVertexAttrib4Niv (GLuint index, const GLint *v);
+GLAPI void APIENTRY glVertexAttrib4Nsv (GLuint index, const GLshort *v);
+GLAPI void APIENTRY glVertexAttrib4Nub (GLuint index, GLubyte x, GLubyte y, GLubyte z, GLubyte w);
+GLAPI void APIENTRY glVertexAttrib4Nubv (GLuint index, const GLubyte *v);
+GLAPI void APIENTRY glVertexAttrib4Nuiv (GLuint index, const GLuint *v);
+GLAPI void APIENTRY glVertexAttrib4Nusv (GLuint index, const GLushort *v);
+GLAPI void APIENTRY glVertexAttrib4bv (GLuint index, const GLbyte *v);
+GLAPI void APIENTRY glVertexAttrib4d (GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+GLAPI void APIENTRY glVertexAttrib4dv (GLuint index, const GLdouble *v);
+GLAPI void APIENTRY glVertexAttrib4f (GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+GLAPI void APIENTRY glVertexAttrib4fv (GLuint index, const GLfloat *v);
+GLAPI void APIENTRY glVertexAttrib4iv (GLuint index, const GLint *v);
+GLAPI void APIENTRY glVertexAttrib4s (GLuint index, GLshort x, GLshort y, GLshort z, GLshort w);
+GLAPI void APIENTRY glVertexAttrib4sv (GLuint index, const GLshort *v);
+GLAPI void APIENTRY glVertexAttrib4ubv (GLuint index, const GLubyte *v);
+GLAPI void APIENTRY glVertexAttrib4uiv (GLuint index, const GLuint *v);
+GLAPI void APIENTRY glVertexAttrib4usv (GLuint index, const GLushort *v);
+GLAPI void APIENTRY glVertexAttribPointer (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid *pointer);
+#endif
+typedef void (APIENTRYP PFNGLBLENDEQUATIONSEPARATEPROC) (GLenum modeRGB, GLenum modeAlpha);
+typedef void (APIENTRYP PFNGLDRAWBUFFERSPROC) (GLsizei n, const GLenum *bufs);
+typedef void (APIENTRYP PFNGLSTENCILOPSEPARATEPROC) (GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass);
+typedef void (APIENTRYP PFNGLSTENCILFUNCSEPARATEPROC) (GLenum face, GLenum func, GLint ref, GLuint mask);
+typedef void (APIENTRYP PFNGLSTENCILMASKSEPARATEPROC) (GLenum face, GLuint mask);
+typedef void (APIENTRYP PFNGLATTACHSHADERPROC) (GLuint program, GLuint shader);
+typedef void (APIENTRYP PFNGLBINDATTRIBLOCATIONPROC) (GLuint program, GLuint index, const GLchar *name);
+typedef void (APIENTRYP PFNGLCOMPILESHADERPROC) (GLuint shader);
+typedef GLuint (APIENTRYP PFNGLCREATEPROGRAMPROC) (void);
+typedef GLuint (APIENTRYP PFNGLCREATESHADERPROC) (GLenum type);
+typedef void (APIENTRYP PFNGLDELETEPROGRAMPROC) (GLuint program);
+typedef void (APIENTRYP PFNGLDELETESHADERPROC) (GLuint shader);
+typedef void (APIENTRYP PFNGLDETACHSHADERPROC) (GLuint program, GLuint shader);
+typedef void (APIENTRYP PFNGLDISABLEVERTEXATTRIBARRAYPROC) (GLuint index);
+typedef void (APIENTRYP PFNGLENABLEVERTEXATTRIBARRAYPROC) (GLuint index);
+typedef void (APIENTRYP PFNGLGETACTIVEATTRIBPROC) (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name);
+typedef void (APIENTRYP PFNGLGETACTIVEUNIFORMPROC) (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name);
+typedef void (APIENTRYP PFNGLGETATTACHEDSHADERSPROC) (GLuint program, GLsizei maxCount, GLsizei *count, GLuint *obj);
+typedef GLint (APIENTRYP PFNGLGETATTRIBLOCATIONPROC) (GLuint program, const GLchar *name);
+typedef void (APIENTRYP PFNGLGETPROGRAMIVPROC) (GLuint program, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETPROGRAMINFOLOGPROC) (GLuint program, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
+typedef void (APIENTRYP PFNGLGETSHADERIVPROC) (GLuint shader, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETSHADERINFOLOGPROC) (GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
+typedef void (APIENTRYP PFNGLGETSHADERSOURCEPROC) (GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *source);
+typedef GLint (APIENTRYP PFNGLGETUNIFORMLOCATIONPROC) (GLuint program, const GLchar *name);
+typedef void (APIENTRYP PFNGLGETUNIFORMFVPROC) (GLuint program, GLint location, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETUNIFORMIVPROC) (GLuint program, GLint location, GLint *params);
+typedef void (APIENTRYP PFNGLGETVERTEXATTRIBDVPROC) (GLuint index, GLenum pname, GLdouble *params);
+typedef void (APIENTRYP PFNGLGETVERTEXATTRIBFVPROC) (GLuint index, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETVERTEXATTRIBIVPROC) (GLuint index, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETVERTEXATTRIBPOINTERVPROC) (GLuint index, GLenum pname, GLvoid* *pointer);
+typedef GLboolean (APIENTRYP PFNGLISPROGRAMPROC) (GLuint program);
+typedef GLboolean (APIENTRYP PFNGLISSHADERPROC) (GLuint shader);
+typedef void (APIENTRYP PFNGLLINKPROGRAMPROC) (GLuint program);
+typedef void (APIENTRYP PFNGLSHADERSOURCEPROC) (GLuint shader, GLsizei count, const GLchar* *string, const GLint *length);
+typedef void (APIENTRYP PFNGLUSEPROGRAMPROC) (GLuint program);
+typedef void (APIENTRYP PFNGLUNIFORM1FPROC) (GLint location, GLfloat v0);
+typedef void (APIENTRYP PFNGLUNIFORM2FPROC) (GLint location, GLfloat v0, GLfloat v1);
+typedef void (APIENTRYP PFNGLUNIFORM3FPROC) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2);
+typedef void (APIENTRYP PFNGLUNIFORM4FPROC) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
+typedef void (APIENTRYP PFNGLUNIFORM1IPROC) (GLint location, GLint v0);
+typedef void (APIENTRYP PFNGLUNIFORM2IPROC) (GLint location, GLint v0, GLint v1);
+typedef void (APIENTRYP PFNGLUNIFORM3IPROC) (GLint location, GLint v0, GLint v1, GLint v2);
+typedef void (APIENTRYP PFNGLUNIFORM4IPROC) (GLint location, GLint v0, GLint v1, GLint v2, GLint v3);
+typedef void (APIENTRYP PFNGLUNIFORM1FVPROC) (GLint location, GLsizei count, const GLfloat *value);
+typedef void (APIENTRYP PFNGLUNIFORM2FVPROC) (GLint location, GLsizei count, const GLfloat *value);
+typedef void (APIENTRYP PFNGLUNIFORM3FVPROC) (GLint location, GLsizei count, const GLfloat *value);
+typedef void (APIENTRYP PFNGLUNIFORM4FVPROC) (GLint location, GLsizei count, const GLfloat *value);
+typedef void (APIENTRYP PFNGLUNIFORM1IVPROC) (GLint location, GLsizei count, const GLint *value);
+typedef void (APIENTRYP PFNGLUNIFORM2IVPROC) (GLint location, GLsizei count, const GLint *value);
+typedef void (APIENTRYP PFNGLUNIFORM3IVPROC) (GLint location, GLsizei count, const GLint *value);
+typedef void (APIENTRYP PFNGLUNIFORM4IVPROC) (GLint location, GLsizei count, const GLint *value);
+typedef void (APIENTRYP PFNGLUNIFORMMATRIX2FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (APIENTRYP PFNGLUNIFORMMATRIX3FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (APIENTRYP PFNGLUNIFORMMATRIX4FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (APIENTRYP PFNGLVALIDATEPROGRAMPROC) (GLuint program);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB1DPROC) (GLuint index, GLdouble x);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB1DVPROC) (GLuint index, const GLdouble *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB1FPROC) (GLuint index, GLfloat x);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB1FVPROC) (GLuint index, const GLfloat *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB1SPROC) (GLuint index, GLshort x);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB1SVPROC) (GLuint index, const GLshort *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB2DPROC) (GLuint index, GLdouble x, GLdouble y);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB2DVPROC) (GLuint index, const GLdouble *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB2FPROC) (GLuint index, GLfloat x, GLfloat y);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB2FVPROC) (GLuint index, const GLfloat *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB2SPROC) (GLuint index, GLshort x, GLshort y);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB2SVPROC) (GLuint index, const GLshort *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB3DPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB3DVPROC) (GLuint index, const GLdouble *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB3FPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB3FVPROC) (GLuint index, const GLfloat *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB3SPROC) (GLuint index, GLshort x, GLshort y, GLshort z);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB3SVPROC) (GLuint index, const GLshort *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4NBVPROC) (GLuint index, const GLbyte *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4NIVPROC) (GLuint index, const GLint *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4NSVPROC) (GLuint index, const GLshort *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4NUBPROC) (GLuint index, GLubyte x, GLubyte y, GLubyte z, GLubyte w);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4NUBVPROC) (GLuint index, const GLubyte *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4NUIVPROC) (GLuint index, const GLuint *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4NUSVPROC) (GLuint index, const GLushort *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4BVPROC) (GLuint index, const GLbyte *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4DPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4DVPROC) (GLuint index, const GLdouble *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4FPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4FVPROC) (GLuint index, const GLfloat *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4IVPROC) (GLuint index, const GLint *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4SPROC) (GLuint index, GLshort x, GLshort y, GLshort z, GLshort w);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4SVPROC) (GLuint index, const GLshort *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4UBVPROC) (GLuint index, const GLubyte *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4UIVPROC) (GLuint index, const GLuint *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4USVPROC) (GLuint index, const GLushort *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBPOINTERPROC) (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid *pointer);
+#endif
+
+#ifndef GL_VERSION_2_1
+#define GL_VERSION_2_1 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glUniformMatrix2x3fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GLAPI void APIENTRY glUniformMatrix3x2fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GLAPI void APIENTRY glUniformMatrix2x4fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GLAPI void APIENTRY glUniformMatrix4x2fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GLAPI void APIENTRY glUniformMatrix3x4fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GLAPI void APIENTRY glUniformMatrix4x3fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+#endif
+typedef void (APIENTRYP PFNGLUNIFORMMATRIX2X3FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (APIENTRYP PFNGLUNIFORMMATRIX3X2FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (APIENTRYP PFNGLUNIFORMMATRIX2X4FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (APIENTRYP PFNGLUNIFORMMATRIX4X2FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (APIENTRYP PFNGLUNIFORMMATRIX3X4FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (APIENTRYP PFNGLUNIFORMMATRIX4X3FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+#endif
+
+#ifndef GL_VERSION_3_0
+#define GL_VERSION_3_0 1
+
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glColorMaski (GLuint index, GLboolean r, GLboolean g, GLboolean b, GLboolean a);
+GLAPI void APIENTRY glGetBooleani_v (GLenum target, GLuint index, GLboolean *data);
+GLAPI void APIENTRY glGetIntegeri_v (GLenum target, GLuint index, GLint *data);
+GLAPI void APIENTRY glEnablei (GLenum target, GLuint index);
+GLAPI void APIENTRY glDisablei (GLenum target, GLuint index);
+GLAPI GLboolean APIENTRY glIsEnabledi (GLenum target, GLuint index);
+GLAPI void APIENTRY glBeginTransformFeedback (GLenum primitiveMode);
+GLAPI void APIENTRY glEndTransformFeedback (void);
+GLAPI void APIENTRY glBindBufferRange (GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size);
+GLAPI void APIENTRY glBindBufferBase (GLenum target, GLuint index, GLuint buffer);
+GLAPI void APIENTRY glTransformFeedbackVaryings (GLuint program, GLsizei count, const GLchar* *varyings, GLenum bufferMode);
+GLAPI void APIENTRY glGetTransformFeedbackVarying (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLsizei *size, GLenum *type, GLchar *name);
+GLAPI void APIENTRY glClampColor (GLenum target, GLenum clamp);
+GLAPI void APIENTRY glBeginConditionalRender (GLuint id, GLenum mode);
+GLAPI void APIENTRY glEndConditionalRender (void);
+GLAPI void APIENTRY glVertexAttribIPointer (GLuint index, GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);
+GLAPI void APIENTRY glGetVertexAttribIiv (GLuint index, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetVertexAttribIuiv (GLuint index, GLenum pname, GLuint *params);
+GLAPI void APIENTRY glVertexAttribI1i (GLuint index, GLint x);
+GLAPI void APIENTRY glVertexAttribI2i (GLuint index, GLint x, GLint y);
+GLAPI void APIENTRY glVertexAttribI3i (GLuint index, GLint x, GLint y, GLint z);
+GLAPI void APIENTRY glVertexAttribI4i (GLuint index, GLint x, GLint y, GLint z, GLint w);
+GLAPI void APIENTRY glVertexAttribI1ui (GLuint index, GLuint x);
+GLAPI void APIENTRY glVertexAttribI2ui (GLuint index, GLuint x, GLuint y);
+GLAPI void APIENTRY glVertexAttribI3ui (GLuint index, GLuint x, GLuint y, GLuint z);
+GLAPI void APIENTRY glVertexAttribI4ui (GLuint index, GLuint x, GLuint y, GLuint z, GLuint w);
+GLAPI void APIENTRY glVertexAttribI1iv (GLuint index, const GLint *v);
+GLAPI void APIENTRY glVertexAttribI2iv (GLuint index, const GLint *v);
+GLAPI void APIENTRY glVertexAttribI3iv (GLuint index, const GLint *v);
+GLAPI void APIENTRY glVertexAttribI4iv (GLuint index, const GLint *v);
+GLAPI void APIENTRY glVertexAttribI1uiv (GLuint index, const GLuint *v);
+GLAPI void APIENTRY glVertexAttribI2uiv (GLuint index, const GLuint *v);
+GLAPI void APIENTRY glVertexAttribI3uiv (GLuint index, const GLuint *v);
+GLAPI void APIENTRY glVertexAttribI4uiv (GLuint index, const GLuint *v);
+GLAPI void APIENTRY glVertexAttribI4bv (GLuint index, const GLbyte *v);
+GLAPI void APIENTRY glVertexAttribI4sv (GLuint index, const GLshort *v);
+GLAPI void APIENTRY glVertexAttribI4ubv (GLuint index, const GLubyte *v);
+GLAPI void APIENTRY glVertexAttribI4usv (GLuint index, const GLushort *v);
+GLAPI void APIENTRY glGetUniformuiv (GLuint program, GLint location, GLuint *params);
+GLAPI void APIENTRY glBindFragDataLocation (GLuint program, GLuint color, const GLchar *name);
+GLAPI GLint APIENTRY glGetFragDataLocation (GLuint program, const GLchar *name);
+GLAPI void APIENTRY glUniform1ui (GLint location, GLuint v0);
+GLAPI void APIENTRY glUniform2ui (GLint location, GLuint v0, GLuint v1);
+GLAPI void APIENTRY glUniform3ui (GLint location, GLuint v0, GLuint v1, GLuint v2);
+GLAPI void APIENTRY glUniform4ui (GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3);
+GLAPI void APIENTRY glUniform1uiv (GLint location, GLsizei count, const GLuint *value);
+GLAPI void APIENTRY glUniform2uiv (GLint location, GLsizei count, const GLuint *value);
+GLAPI void APIENTRY glUniform3uiv (GLint location, GLsizei count, const GLuint *value);
+GLAPI void APIENTRY glUniform4uiv (GLint location, GLsizei count, const GLuint *value);
+GLAPI void APIENTRY glTexParameterIiv (GLenum target, GLenum pname, const GLint *params);
+GLAPI void APIENTRY glTexParameterIuiv (GLenum target, GLenum pname, const GLuint *params);
+GLAPI void APIENTRY glGetTexParameterIiv (GLenum target, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetTexParameterIuiv (GLenum target, GLenum pname, GLuint *params);
+GLAPI void APIENTRY glClearBufferiv (GLenum buffer, GLint drawbuffer, const GLint *value);
+GLAPI void APIENTRY glClearBufferuiv (GLenum buffer, GLint drawbuffer, const GLuint *value);
+GLAPI void APIENTRY glClearBufferfv (GLenum buffer, GLint drawbuffer, const GLfloat *value);
+GLAPI void APIENTRY glClearBufferfi (GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil);
+GLAPI const GLubyte * APIENTRY glGetStringi (GLenum name, GLuint index);
+#endif
+typedef void (APIENTRYP PFNGLCOLORMASKIPROC) (GLuint index, GLboolean r, GLboolean g, GLboolean b, GLboolean a);
+typedef void (APIENTRYP PFNGLGETBOOLEANI_VPROC) (GLenum target, GLuint index, GLboolean *data);
+typedef void (APIENTRYP PFNGLGETINTEGERI_VPROC) (GLenum target, GLuint index, GLint *data);
+typedef void (APIENTRYP PFNGLENABLEIPROC) (GLenum target, GLuint index);
+typedef void (APIENTRYP PFNGLDISABLEIPROC) (GLenum target, GLuint index);
+typedef GLboolean (APIENTRYP PFNGLISENABLEDIPROC) (GLenum target, GLuint index);
+typedef void (APIENTRYP PFNGLBEGINTRANSFORMFEEDBACKPROC) (GLenum primitiveMode);
+typedef void (APIENTRYP PFNGLENDTRANSFORMFEEDBACKPROC) (void);
+typedef void (APIENTRYP PFNGLBINDBUFFERRANGEPROC) (GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size);
+typedef void (APIENTRYP PFNGLBINDBUFFERBASEPROC) (GLenum target, GLuint index, GLuint buffer);
+typedef void (APIENTRYP PFNGLTRANSFORMFEEDBACKVARYINGSPROC) (GLuint program, GLsizei count, const GLchar* *varyings, GLenum bufferMode);
+typedef void (APIENTRYP PFNGLGETTRANSFORMFEEDBACKVARYINGPROC) (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLsizei *size, GLenum *type, GLchar *name);
+typedef void (APIENTRYP PFNGLCLAMPCOLORPROC) (GLenum target, GLenum clamp);
+typedef void (APIENTRYP PFNGLBEGINCONDITIONALRENDERPROC) (GLuint id, GLenum mode);
+typedef void (APIENTRYP PFNGLENDCONDITIONALRENDERPROC) (void);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBIPOINTERPROC) (GLuint index, GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);
+typedef void (APIENTRYP PFNGLGETVERTEXATTRIBIIVPROC) (GLuint index, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETVERTEXATTRIBIUIVPROC) (GLuint index, GLenum pname, GLuint *params);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI1IPROC) (GLuint index, GLint x);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI2IPROC) (GLuint index, GLint x, GLint y);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI3IPROC) (GLuint index, GLint x, GLint y, GLint z);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI4IPROC) (GLuint index, GLint x, GLint y, GLint z, GLint w);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI1UIPROC) (GLuint index, GLuint x);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI2UIPROC) (GLuint index, GLuint x, GLuint y);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI3UIPROC) (GLuint index, GLuint x, GLuint y, GLuint z);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI4UIPROC) (GLuint index, GLuint x, GLuint y, GLuint z, GLuint w);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI1IVPROC) (GLuint index, const GLint *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI2IVPROC) (GLuint index, const GLint *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI3IVPROC) (GLuint index, const GLint *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI4IVPROC) (GLuint index, const GLint *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI1UIVPROC) (GLuint index, const GLuint *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI2UIVPROC) (GLuint index, const GLuint *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI3UIVPROC) (GLuint index, const GLuint *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI4UIVPROC) (GLuint index, const GLuint *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI4BVPROC) (GLuint index, const GLbyte *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI4SVPROC) (GLuint index, const GLshort *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI4UBVPROC) (GLuint index, const GLubyte *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI4USVPROC) (GLuint index, const GLushort *v);
+typedef void (APIENTRYP PFNGLGETUNIFORMUIVPROC) (GLuint program, GLint location, GLuint *params);
+typedef void (APIENTRYP PFNGLBINDFRAGDATALOCATIONPROC) (GLuint program, GLuint color, const GLchar *name);
+typedef GLint (APIENTRYP PFNGLGETFRAGDATALOCATIONPROC) (GLuint program, const GLchar *name);
+typedef void (APIENTRYP PFNGLUNIFORM1UIPROC) (GLint location, GLuint v0);
+typedef void (APIENTRYP PFNGLUNIFORM2UIPROC) (GLint location, GLuint v0, GLuint v1);
+typedef void (APIENTRYP PFNGLUNIFORM3UIPROC) (GLint location, GLuint v0, GLuint v1, GLuint v2);
+typedef void (APIENTRYP PFNGLUNIFORM4UIPROC) (GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3);
+typedef void (APIENTRYP PFNGLUNIFORM1UIVPROC) (GLint location, GLsizei count, const GLuint *value);
+typedef void (APIENTRYP PFNGLUNIFORM2UIVPROC) (GLint location, GLsizei count, const GLuint *value);
+typedef void (APIENTRYP PFNGLUNIFORM3UIVPROC) (GLint location, GLsizei count, const GLuint *value);
+typedef void (APIENTRYP PFNGLUNIFORM4UIVPROC) (GLint location, GLsizei count, const GLuint *value);
+typedef void (APIENTRYP PFNGLTEXPARAMETERIIVPROC) (GLenum target, GLenum pname, const GLint *params);
+typedef void (APIENTRYP PFNGLTEXPARAMETERIUIVPROC) (GLenum target, GLenum pname, const GLuint *params);
+typedef void (APIENTRYP PFNGLGETTEXPARAMETERIIVPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETTEXPARAMETERIUIVPROC) (GLenum target, GLenum pname, GLuint *params);
+typedef void (APIENTRYP PFNGLCLEARBUFFERIVPROC) (GLenum buffer, GLint drawbuffer, const GLint *value);
+typedef void (APIENTRYP PFNGLCLEARBUFFERUIVPROC) (GLenum buffer, GLint drawbuffer, const GLuint *value);
+typedef void (APIENTRYP PFNGLCLEARBUFFERFVPROC) (GLenum buffer, GLint drawbuffer, const GLfloat *value);
+typedef void (APIENTRYP PFNGLCLEARBUFFERFIPROC) (GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil);
+typedef const GLubyte * (APIENTRYP PFNGLGETSTRINGIPROC) (GLenum name, GLuint index);
+#endif
+
+#ifndef GL_VERSION_3_1
+#define GL_VERSION_3_1 1
+
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glDrawArraysInstanced (GLenum mode, GLint first, GLsizei count, GLsizei primcount);
+GLAPI void APIENTRY glDrawElementsInstanced (GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLsizei primcount);
+GLAPI void APIENTRY glTexBuffer (GLenum target, GLenum internalformat, GLuint buffer);
+GLAPI void APIENTRY glPrimitiveRestartIndex (GLuint index);
+#endif
+typedef void (APIENTRYP PFNGLDRAWARRAYSINSTANCEDPROC) (GLenum mode, GLint first, GLsizei count, GLsizei primcount);
+typedef void (APIENTRYP PFNGLDRAWELEMENTSINSTANCEDPROC) (GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLsizei primcount);
+typedef void (APIENTRYP PFNGLTEXBUFFERPROC) (GLenum target, GLenum internalformat, GLuint buffer);
+typedef void (APIENTRYP PFNGLPRIMITIVERESTARTINDEXPROC) (GLuint index);
+#endif
+
+#ifndef GL_VERSION_3_2
+#define GL_VERSION_3_2 1
+
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glGetInteger64i_v (GLenum target, GLuint index, GLint64 *data);
+GLAPI void APIENTRY glGetBufferParameteri64v (GLenum target, GLenum pname, GLint64 *params);
+GLAPI void APIENTRY glFramebufferTexture (GLenum target, GLenum attachment, GLuint texture, GLint level);
+#endif
+typedef void (APIENTRYP PFNGLGETINTEGER64I_VPROC) (GLenum target, GLuint index, GLint64 *data);
+typedef void (APIENTRYP PFNGLGETBUFFERPARAMETERI64VPROC) (GLenum target, GLenum pname, GLint64 *params);
+typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTUREPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level);
+#endif
+
+#ifndef GL_VERSION_3_3
+#define GL_VERSION_3_3 1
+
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glVertexAttribDivisor (GLuint index, GLuint divisor);
+#endif
+typedef void (APIENTRYP PFNGLVERTEXATTRIBDIVISORPROC) (GLuint index, GLuint divisor);
+#endif
+
+#ifndef GL_VERSION_4_0
+#define GL_VERSION_4_0 1
+
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glMinSampleShading (GLclampf value);
+GLAPI void APIENTRY glBlendEquationi (GLuint buf, GLenum mode);
+GLAPI void APIENTRY glBlendEquationSeparatei (GLuint buf, GLenum modeRGB, GLenum modeAlpha);
+GLAPI void APIENTRY glBlendFunci (GLuint buf, GLenum src, GLenum dst);
+GLAPI void APIENTRY glBlendFuncSeparatei (GLuint buf, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha);
+#endif
+typedef void (APIENTRYP PFNGLMINSAMPLESHADINGPROC) (GLclampf value);
+typedef void (APIENTRYP PFNGLBLENDEQUATIONIPROC) (GLuint buf, GLenum mode);
+typedef void (APIENTRYP PFNGLBLENDEQUATIONSEPARATEIPROC) (GLuint buf, GLenum modeRGB, GLenum modeAlpha);
+typedef void (APIENTRYP PFNGLBLENDFUNCIPROC) (GLuint buf, GLenum src, GLenum dst);
+typedef void (APIENTRYP PFNGLBLENDFUNCSEPARATEIPROC) (GLuint buf, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha);
+#endif
+
+#ifndef GL_VERSION_4_1
+#define GL_VERSION_4_1 1
+
+#endif
+
+#ifndef GL_ARB_multitexture
+#define GL_ARB_multitexture 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glActiveTextureARB (GLenum texture);
+GLAPI void APIENTRY glClientActiveTextureARB (GLenum texture);
+GLAPI void APIENTRY glMultiTexCoord1dARB (GLenum target, GLdouble s);
+GLAPI void APIENTRY glMultiTexCoord1dvARB (GLenum target, const GLdouble *v);
+GLAPI void APIENTRY glMultiTexCoord1fARB (GLenum target, GLfloat s);
+GLAPI void APIENTRY glMultiTexCoord1fvARB (GLenum target, const GLfloat *v);
+GLAPI void APIENTRY glMultiTexCoord1iARB (GLenum target, GLint s);
+GLAPI void APIENTRY glMultiTexCoord1ivARB (GLenum target, const GLint *v);
+GLAPI void APIENTRY glMultiTexCoord1sARB (GLenum target, GLshort s);
+GLAPI void APIENTRY glMultiTexCoord1svARB (GLenum target, const GLshort *v);
+GLAPI void APIENTRY glMultiTexCoord2dARB (GLenum target, GLdouble s, GLdouble t);
+GLAPI void APIENTRY glMultiTexCoord2dvARB (GLenum target, const GLdouble *v);
+GLAPI void APIENTRY glMultiTexCoord2fARB (GLenum target, GLfloat s, GLfloat t);
+GLAPI void APIENTRY glMultiTexCoord2fvARB (GLenum target, const GLfloat *v);
+GLAPI void APIENTRY glMultiTexCoord2iARB (GLenum target, GLint s, GLint t);
+GLAPI void APIENTRY glMultiTexCoord2ivARB (GLenum target, const GLint *v);
+GLAPI void APIENTRY glMultiTexCoord2sARB (GLenum target, GLshort s, GLshort t);
+GLAPI void APIENTRY glMultiTexCoord2svARB (GLenum target, const GLshort *v);
+GLAPI void APIENTRY glMultiTexCoord3dARB (GLenum target, GLdouble s, GLdouble t, GLdouble r);
+GLAPI void APIENTRY glMultiTexCoord3dvARB (GLenum target, const GLdouble *v);
+GLAPI void APIENTRY glMultiTexCoord3fARB (GLenum target, GLfloat s, GLfloat t, GLfloat r);
+GLAPI void APIENTRY glMultiTexCoord3fvARB (GLenum target, const GLfloat *v);
+GLAPI void APIENTRY glMultiTexCoord3iARB (GLenum target, GLint s, GLint t, GLint r);
+GLAPI void APIENTRY glMultiTexCoord3ivARB (GLenum target, const GLint *v);
+GLAPI void APIENTRY glMultiTexCoord3sARB (GLenum target, GLshort s, GLshort t, GLshort r);
+GLAPI void APIENTRY glMultiTexCoord3svARB (GLenum target, const GLshort *v);
+GLAPI void APIENTRY glMultiTexCoord4dARB (GLenum target, GLdouble s, GLdouble t, GLdouble r, GLdouble q);
+GLAPI void APIENTRY glMultiTexCoord4dvARB (GLenum target, const GLdouble *v);
+GLAPI void APIENTRY glMultiTexCoord4fARB (GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q);
+GLAPI void APIENTRY glMultiTexCoord4fvARB (GLenum target, const GLfloat *v);
+GLAPI void APIENTRY glMultiTexCoord4iARB (GLenum target, GLint s, GLint t, GLint r, GLint q);
+GLAPI void APIENTRY glMultiTexCoord4ivARB (GLenum target, const GLint *v);
+GLAPI void APIENTRY glMultiTexCoord4sARB (GLenum target, GLshort s, GLshort t, GLshort r, GLshort q);
+GLAPI void APIENTRY glMultiTexCoord4svARB (GLenum target, const GLshort *v);
+#endif
+typedef void (APIENTRYP PFNGLACTIVETEXTUREARBPROC) (GLenum texture);
+typedef void (APIENTRYP PFNGLCLIENTACTIVETEXTUREARBPROC) (GLenum texture);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD1DARBPROC) (GLenum target, GLdouble s);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD1DVARBPROC) (GLenum target, const GLdouble *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD1FARBPROC) (GLenum target, GLfloat s);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD1FVARBPROC) (GLenum target, const GLfloat *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD1IARBPROC) (GLenum target, GLint s);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD1IVARBPROC) (GLenum target, const GLint *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD1SARBPROC) (GLenum target, GLshort s);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD1SVARBPROC) (GLenum target, const GLshort *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD2DARBPROC) (GLenum target, GLdouble s, GLdouble t);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD2DVARBPROC) (GLenum target, const GLdouble *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD2FARBPROC) (GLenum target, GLfloat s, GLfloat t);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD2FVARBPROC) (GLenum target, const GLfloat *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD2IARBPROC) (GLenum target, GLint s, GLint t);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD2IVARBPROC) (GLenum target, const GLint *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD2SARBPROC) (GLenum target, GLshort s, GLshort t);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD2SVARBPROC) (GLenum target, const GLshort *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD3DARBPROC) (GLenum target, GLdouble s, GLdouble t, GLdouble r);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD3DVARBPROC) (GLenum target, const GLdouble *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD3FARBPROC) (GLenum target, GLfloat s, GLfloat t, GLfloat r);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD3FVARBPROC) (GLenum target, const GLfloat *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD3IARBPROC) (GLenum target, GLint s, GLint t, GLint r);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD3IVARBPROC) (GLenum target, const GLint *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD3SARBPROC) (GLenum target, GLshort s, GLshort t, GLshort r);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD3SVARBPROC) (GLenum target, const GLshort *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD4DARBPROC) (GLenum target, GLdouble s, GLdouble t, GLdouble r, GLdouble q);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD4DVARBPROC) (GLenum target, const GLdouble *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD4FARBPROC) (GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD4FVARBPROC) (GLenum target, const GLfloat *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD4IARBPROC) (GLenum target, GLint s, GLint t, GLint r, GLint q);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD4IVARBPROC) (GLenum target, const GLint *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD4SARBPROC) (GLenum target, GLshort s, GLshort t, GLshort r, GLshort q);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD4SVARBPROC) (GLenum target, const GLshort *v);
+#endif
+
+#ifndef GL_ARB_transpose_matrix
+#define GL_ARB_transpose_matrix 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glLoadTransposeMatrixfARB (const GLfloat *m);
+GLAPI void APIENTRY glLoadTransposeMatrixdARB (const GLdouble *m);
+GLAPI void APIENTRY glMultTransposeMatrixfARB (const GLfloat *m);
+GLAPI void APIENTRY glMultTransposeMatrixdARB (const GLdouble *m);
+#endif
+typedef void (APIENTRYP PFNGLLOADTRANSPOSEMATRIXFARBPROC) (const GLfloat *m);
+typedef void (APIENTRYP PFNGLLOADTRANSPOSEMATRIXDARBPROC) (const GLdouble *m);
+typedef void (APIENTRYP PFNGLMULTTRANSPOSEMATRIXFARBPROC) (const GLfloat *m);
+typedef void (APIENTRYP PFNGLMULTTRANSPOSEMATRIXDARBPROC) (const GLdouble *m);
+#endif
+
+#ifndef GL_ARB_multisample
+#define GL_ARB_multisample 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glSampleCoverageARB (GLclampf value, GLboolean invert);
+#endif
+typedef void (APIENTRYP PFNGLSAMPLECOVERAGEARBPROC) (GLclampf value, GLboolean invert);
+#endif
+
+#ifndef GL_ARB_texture_env_add
+#define GL_ARB_texture_env_add 1
+#endif
+
+#ifndef GL_ARB_texture_cube_map
+#define GL_ARB_texture_cube_map 1
+#endif
+
+#ifndef GL_ARB_texture_compression
+#define GL_ARB_texture_compression 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glCompressedTexImage3DARB (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid *data);
+GLAPI void APIENTRY glCompressedTexImage2DARB (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *data);
+GLAPI void APIENTRY glCompressedTexImage1DARB (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const GLvoid *data);
+GLAPI void APIENTRY glCompressedTexSubImage3DARB (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid *data);
+GLAPI void APIENTRY glCompressedTexSubImage2DARB (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid *data);
+GLAPI void APIENTRY glCompressedTexSubImage1DARB (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const GLvoid *data);
+GLAPI void APIENTRY glGetCompressedTexImageARB (GLenum target, GLint level, GLvoid *img);
+#endif
+typedef void (APIENTRYP PFNGLCOMPRESSEDTEXIMAGE3DARBPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid *data);
+typedef void (APIENTRYP PFNGLCOMPRESSEDTEXIMAGE2DARBPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *data);
+typedef void (APIENTRYP PFNGLCOMPRESSEDTEXIMAGE1DARBPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const GLvoid *data);
+typedef void (APIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE3DARBPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid *data);
+typedef void (APIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE2DARBPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid *data);
+typedef void (APIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE1DARBPROC) (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const GLvoid *data);
+typedef void (APIENTRYP PFNGLGETCOMPRESSEDTEXIMAGEARBPROC) (GLenum target, GLint level, GLvoid *img);
+#endif
+
+#ifndef GL_ARB_texture_border_clamp
+#define GL_ARB_texture_border_clamp 1
+#endif
+
+#ifndef GL_ARB_point_parameters
+#define GL_ARB_point_parameters 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glPointParameterfARB (GLenum pname, GLfloat param);
+GLAPI void APIENTRY glPointParameterfvARB (GLenum pname, const GLfloat *params);
+#endif
+typedef void (APIENTRYP PFNGLPOINTPARAMETERFARBPROC) (GLenum pname, GLfloat param);
+typedef void (APIENTRYP PFNGLPOINTPARAMETERFVARBPROC) (GLenum pname, const GLfloat *params);
+#endif
+
+#ifndef GL_ARB_vertex_blend
+#define GL_ARB_vertex_blend 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glWeightbvARB (GLint size, const GLbyte *weights);
+GLAPI void APIENTRY glWeightsvARB (GLint size, const GLshort *weights);
+GLAPI void APIENTRY glWeightivARB (GLint size, const GLint *weights);
+GLAPI void APIENTRY glWeightfvARB (GLint size, const GLfloat *weights);
+GLAPI void APIENTRY glWeightdvARB (GLint size, const GLdouble *weights);
+GLAPI void APIENTRY glWeightubvARB (GLint size, const GLubyte *weights);
+GLAPI void APIENTRY glWeightusvARB (GLint size, const GLushort *weights);
+GLAPI void APIENTRY glWeightuivARB (GLint size, const GLuint *weights);
+GLAPI void APIENTRY glWeightPointerARB (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);
+GLAPI void APIENTRY glVertexBlendARB (GLint count);
+#endif
+typedef void (APIENTRYP PFNGLWEIGHTBVARBPROC) (GLint size, const GLbyte *weights);
+typedef void (APIENTRYP PFNGLWEIGHTSVARBPROC) (GLint size, const GLshort *weights);
+typedef void (APIENTRYP PFNGLWEIGHTIVARBPROC) (GLint size, const GLint *weights);
+typedef void (APIENTRYP PFNGLWEIGHTFVARBPROC) (GLint size, const GLfloat *weights);
+typedef void (APIENTRYP PFNGLWEIGHTDVARBPROC) (GLint size, const GLdouble *weights);
+typedef void (APIENTRYP PFNGLWEIGHTUBVARBPROC) (GLint size, const GLubyte *weights);
+typedef void (APIENTRYP PFNGLWEIGHTUSVARBPROC) (GLint size, const GLushort *weights);
+typedef void (APIENTRYP PFNGLWEIGHTUIVARBPROC) (GLint size, const GLuint *weights);
+typedef void (APIENTRYP PFNGLWEIGHTPOINTERARBPROC) (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);
+typedef void (APIENTRYP PFNGLVERTEXBLENDARBPROC) (GLint count);
+#endif
+
+#ifndef GL_ARB_matrix_palette
+#define GL_ARB_matrix_palette 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glCurrentPaletteMatrixARB (GLint index);
+GLAPI void APIENTRY glMatrixIndexubvARB (GLint size, const GLubyte *indices);
+GLAPI void APIENTRY glMatrixIndexusvARB (GLint size, const GLushort *indices);
+GLAPI void APIENTRY glMatrixIndexuivARB (GLint size, const GLuint *indices);
+GLAPI void APIENTRY glMatrixIndexPointerARB (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);
+#endif
+typedef void (APIENTRYP PFNGLCURRENTPALETTEMATRIXARBPROC) (GLint index);
+typedef void (APIENTRYP PFNGLMATRIXINDEXUBVARBPROC) (GLint size, const GLubyte *indices);
+typedef void (APIENTRYP PFNGLMATRIXINDEXUSVARBPROC) (GLint size, const GLushort *indices);
+typedef void (APIENTRYP PFNGLMATRIXINDEXUIVARBPROC) (GLint size, const GLuint *indices);
+typedef void (APIENTRYP PFNGLMATRIXINDEXPOINTERARBPROC) (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);
+#endif
+
+#ifndef GL_ARB_texture_env_combine
+#define GL_ARB_texture_env_combine 1
+#endif
+
+#ifndef GL_ARB_texture_env_crossbar
+#define GL_ARB_texture_env_crossbar 1
+#endif
+
+#ifndef GL_ARB_texture_env_dot3
+#define GL_ARB_texture_env_dot3 1
+#endif
+
+#ifndef GL_ARB_texture_mirrored_repeat
+#define GL_ARB_texture_mirrored_repeat 1
+#endif
+
+#ifndef GL_ARB_depth_texture
+#define GL_ARB_depth_texture 1
+#endif
+
+#ifndef GL_ARB_shadow
+#define GL_ARB_shadow 1
+#endif
+
+#ifndef GL_ARB_shadow_ambient
+#define GL_ARB_shadow_ambient 1
+#endif
+
+#ifndef GL_ARB_window_pos
+#define GL_ARB_window_pos 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glWindowPos2dARB (GLdouble x, GLdouble y);
+GLAPI void APIENTRY glWindowPos2dvARB (const GLdouble *v);
+GLAPI void APIENTRY glWindowPos2fARB (GLfloat x, GLfloat y);
+GLAPI void APIENTRY glWindowPos2fvARB (const GLfloat *v);
+GLAPI void APIENTRY glWindowPos2iARB (GLint x, GLint y);
+GLAPI void APIENTRY glWindowPos2ivARB (const GLint *v);
+GLAPI void APIENTRY glWindowPos2sARB (GLshort x, GLshort y);
+GLAPI void APIENTRY glWindowPos2svARB (const GLshort *v);
+GLAPI void APIENTRY glWindowPos3dARB (GLdouble x, GLdouble y, GLdouble z);
+GLAPI void APIENTRY glWindowPos3dvARB (const GLdouble *v);
+GLAPI void APIENTRY glWindowPos3fARB (GLfloat x, GLfloat y, GLfloat z);
+GLAPI void APIENTRY glWindowPos3fvARB (const GLfloat *v);
+GLAPI void APIENTRY glWindowPos3iARB (GLint x, GLint y, GLint z);
+GLAPI void APIENTRY glWindowPos3ivARB (const GLint *v);
+GLAPI void APIENTRY glWindowPos3sARB (GLshort x, GLshort y, GLshort z);
+GLAPI void APIENTRY glWindowPos3svARB (const GLshort *v);
+#endif
+typedef void (APIENTRYP PFNGLWINDOWPOS2DARBPROC) (GLdouble x, GLdouble y);
+typedef void (APIENTRYP PFNGLWINDOWPOS2DVARBPROC) (const GLdouble *v);
+typedef void (APIENTRYP PFNGLWINDOWPOS2FARBPROC) (GLfloat x, GLfloat y);
+typedef void (APIENTRYP PFNGLWINDOWPOS2FVARBPROC) (const GLfloat *v);
+typedef void (APIENTRYP PFNGLWINDOWPOS2IARBPROC) (GLint x, GLint y);
+typedef void (APIENTRYP PFNGLWINDOWPOS2IVARBPROC) (const GLint *v);
+typedef void (APIENTRYP PFNGLWINDOWPOS2SARBPROC) (GLshort x, GLshort y);
+typedef void (APIENTRYP PFNGLWINDOWPOS2SVARBPROC) (const GLshort *v);
+typedef void (APIENTRYP PFNGLWINDOWPOS3DARBPROC) (GLdouble x, GLdouble y, GLdouble z);
+typedef void (APIENTRYP PFNGLWINDOWPOS3DVARBPROC) (const GLdouble *v);
+typedef void (APIENTRYP PFNGLWINDOWPOS3FARBPROC) (GLfloat x, GLfloat y, GLfloat z);
+typedef void (APIENTRYP PFNGLWINDOWPOS3FVARBPROC) (const GLfloat *v);
+typedef void (APIENTRYP PFNGLWINDOWPOS3IARBPROC) (GLint x, GLint y, GLint z);
+typedef void (APIENTRYP PFNGLWINDOWPOS3IVARBPROC) (const GLint *v);
+typedef void (APIENTRYP PFNGLWINDOWPOS3SARBPROC) (GLshort x, GLshort y, GLshort z);
+typedef void (APIENTRYP PFNGLWINDOWPOS3SVARBPROC) (const GLshort *v);
+#endif
+
+#ifndef GL_ARB_vertex_program
+#define GL_ARB_vertex_program 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glVertexAttrib1dARB (GLuint index, GLdouble x);
+GLAPI void APIENTRY glVertexAttrib1dvARB (GLuint index, const GLdouble *v);
+GLAPI void APIENTRY glVertexAttrib1fARB (GLuint index, GLfloat x);
+GLAPI void APIENTRY glVertexAttrib1fvARB (GLuint index, const GLfloat *v);
+GLAPI void APIENTRY glVertexAttrib1sARB (GLuint index, GLshort x);
+GLAPI void APIENTRY glVertexAttrib1svARB (GLuint index, const GLshort *v);
+GLAPI void APIENTRY glVertexAttrib2dARB (GLuint index, GLdouble x, GLdouble y);
+GLAPI void APIENTRY glVertexAttrib2dvARB (GLuint index, const GLdouble *v);
+GLAPI void APIENTRY glVertexAttrib2fARB (GLuint index, GLfloat x, GLfloat y);
+GLAPI void APIENTRY glVertexAttrib2fvARB (GLuint index, const GLfloat *v);
+GLAPI void APIENTRY glVertexAttrib2sARB (GLuint index, GLshort x, GLshort y);
+GLAPI void APIENTRY glVertexAttrib2svARB (GLuint index, const GLshort *v);
+GLAPI void APIENTRY glVertexAttrib3dARB (GLuint index, GLdouble x, GLdouble y, GLdouble z);
+GLAPI void APIENTRY glVertexAttrib3dvARB (GLuint index, const GLdouble *v);
+GLAPI void APIENTRY glVertexAttrib3fARB (GLuint index, GLfloat x, GLfloat y, GLfloat z);
+GLAPI void APIENTRY glVertexAttrib3fvARB (GLuint index, const GLfloat *v);
+GLAPI void APIENTRY glVertexAttrib3sARB (GLuint index, GLshort x, GLshort y, GLshort z);
+GLAPI void APIENTRY glVertexAttrib3svARB (GLuint index, const GLshort *v);
+GLAPI void APIENTRY glVertexAttrib4NbvARB (GLuint index, const GLbyte *v);
+GLAPI void APIENTRY glVertexAttrib4NivARB (GLuint index, const GLint *v);
+GLAPI void APIENTRY glVertexAttrib4NsvARB (GLuint index, const GLshort *v);
+GLAPI void APIENTRY glVertexAttrib4NubARB (GLuint index, GLubyte x, GLubyte y, GLubyte z, GLubyte w);
+GLAPI void APIENTRY glVertexAttrib4NubvARB (GLuint index, const GLubyte *v);
+GLAPI void APIENTRY glVertexAttrib4NuivARB (GLuint index, const GLuint *v);
+GLAPI void APIENTRY glVertexAttrib4NusvARB (GLuint index, const GLushort *v);
+GLAPI void APIENTRY glVertexAttrib4bvARB (GLuint index, const GLbyte *v);
+GLAPI void APIENTRY glVertexAttrib4dARB (GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+GLAPI void APIENTRY glVertexAttrib4dvARB (GLuint index, const GLdouble *v);
+GLAPI void APIENTRY glVertexAttrib4fARB (GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+GLAPI void APIENTRY glVertexAttrib4fvARB (GLuint index, const GLfloat *v);
+GLAPI void APIENTRY glVertexAttrib4ivARB (GLuint index, const GLint *v);
+GLAPI void APIENTRY glVertexAttrib4sARB (GLuint index, GLshort x, GLshort y, GLshort z, GLshort w);
+GLAPI void APIENTRY glVertexAttrib4svARB (GLuint index, const GLshort *v);
+GLAPI void APIENTRY glVertexAttrib4ubvARB (GLuint index, const GLubyte *v);
+GLAPI void APIENTRY glVertexAttrib4uivARB (GLuint index, const GLuint *v);
+GLAPI void APIENTRY glVertexAttrib4usvARB (GLuint index, const GLushort *v);
+GLAPI void APIENTRY glVertexAttribPointerARB (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid *pointer);
+GLAPI void APIENTRY glEnableVertexAttribArrayARB (GLuint index);
+GLAPI void APIENTRY glDisableVertexAttribArrayARB (GLuint index);
+GLAPI void APIENTRY glProgramStringARB (GLenum target, GLenum format, GLsizei len, const GLvoid *string);
+GLAPI void APIENTRY glBindProgramARB (GLenum target, GLuint program);
+GLAPI void APIENTRY glDeleteProgramsARB (GLsizei n, const GLuint *programs);
+GLAPI void APIENTRY glGenProgramsARB (GLsizei n, GLuint *programs);
+GLAPI void APIENTRY glProgramEnvParameter4dARB (GLenum target, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+GLAPI void APIENTRY glProgramEnvParameter4dvARB (GLenum target, GLuint index, const GLdouble *params);
+GLAPI void APIENTRY glProgramEnvParameter4fARB (GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+GLAPI void APIENTRY glProgramEnvParameter4fvARB (GLenum target, GLuint index, const GLfloat *params);
+GLAPI void APIENTRY glProgramLocalParameter4dARB (GLenum target, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+GLAPI void APIENTRY glProgramLocalParameter4dvARB (GLenum target, GLuint index, const GLdouble *params);
+GLAPI void APIENTRY glProgramLocalParameter4fARB (GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+GLAPI void APIENTRY glProgramLocalParameter4fvARB (GLenum target, GLuint index, const GLfloat *params);
+GLAPI void APIENTRY glGetProgramEnvParameterdvARB (GLenum target, GLuint index, GLdouble *params);
+GLAPI void APIENTRY glGetProgramEnvParameterfvARB (GLenum target, GLuint index, GLfloat *params);
+GLAPI void APIENTRY glGetProgramLocalParameterdvARB (GLenum target, GLuint index, GLdouble *params);
+GLAPI void APIENTRY glGetProgramLocalParameterfvARB (GLenum target, GLuint index, GLfloat *params);
+GLAPI void APIENTRY glGetProgramivARB (GLenum target, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetProgramStringARB (GLenum target, GLenum pname, GLvoid *string);
+GLAPI void APIENTRY glGetVertexAttribdvARB (GLuint index, GLenum pname, GLdouble *params);
+GLAPI void APIENTRY glGetVertexAttribfvARB (GLuint index, GLenum pname, GLfloat *params);
+GLAPI void APIENTRY glGetVertexAttribivARB (GLuint index, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetVertexAttribPointervARB (GLuint index, GLenum pname, GLvoid* *pointer);
+GLAPI GLboolean APIENTRY glIsProgramARB (GLuint program);
+#endif
+typedef void (APIENTRYP PFNGLVERTEXATTRIB1DARBPROC) (GLuint index, GLdouble x);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB1DVARBPROC) (GLuint index, const GLdouble *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB1FARBPROC) (GLuint index, GLfloat x);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB1FVARBPROC) (GLuint index, const GLfloat *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB1SARBPROC) (GLuint index, GLshort x);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB1SVARBPROC) (GLuint index, const GLshort *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB2DARBPROC) (GLuint index, GLdouble x, GLdouble y);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB2DVARBPROC) (GLuint index, const GLdouble *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB2FARBPROC) (GLuint index, GLfloat x, GLfloat y);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB2FVARBPROC) (GLuint index, const GLfloat *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB2SARBPROC) (GLuint index, GLshort x, GLshort y);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB2SVARBPROC) (GLuint index, const GLshort *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB3DARBPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB3DVARBPROC) (GLuint index, const GLdouble *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB3FARBPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB3FVARBPROC) (GLuint index, const GLfloat *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB3SARBPROC) (GLuint index, GLshort x, GLshort y, GLshort z);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB3SVARBPROC) (GLuint index, const GLshort *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4NBVARBPROC) (GLuint index, const GLbyte *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4NIVARBPROC) (GLuint index, const GLint *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4NSVARBPROC) (GLuint index, const GLshort *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4NUBARBPROC) (GLuint index, GLubyte x, GLubyte y, GLubyte z, GLubyte w);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4NUBVARBPROC) (GLuint index, const GLubyte *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4NUIVARBPROC) (GLuint index, const GLuint *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4NUSVARBPROC) (GLuint index, const GLushort *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4BVARBPROC) (GLuint index, const GLbyte *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4DARBPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4DVARBPROC) (GLuint index, const GLdouble *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4FARBPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4FVARBPROC) (GLuint index, const GLfloat *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4IVARBPROC) (GLuint index, const GLint *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4SARBPROC) (GLuint index, GLshort x, GLshort y, GLshort z, GLshort w);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4SVARBPROC) (GLuint index, const GLshort *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4UBVARBPROC) (GLuint index, const GLubyte *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4UIVARBPROC) (GLuint index, const GLuint *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4USVARBPROC) (GLuint index, const GLushort *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBPOINTERARBPROC) (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid *pointer);
+typedef void (APIENTRYP PFNGLENABLEVERTEXATTRIBARRAYARBPROC) (GLuint index);
+typedef void (APIENTRYP PFNGLDISABLEVERTEXATTRIBARRAYARBPROC) (GLuint index);
+typedef void (APIENTRYP PFNGLPROGRAMSTRINGARBPROC) (GLenum target, GLenum format, GLsizei len, const GLvoid *string);
+typedef void (APIENTRYP PFNGLBINDPROGRAMARBPROC) (GLenum target, GLuint program);
+typedef void (APIENTRYP PFNGLDELETEPROGRAMSARBPROC) (GLsizei n, const GLuint *programs);
+typedef void (APIENTRYP PFNGLGENPROGRAMSARBPROC) (GLsizei n, GLuint *programs);
+typedef void (APIENTRYP PFNGLPROGRAMENVPARAMETER4DARBPROC) (GLenum target, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+typedef void (APIENTRYP PFNGLPROGRAMENVPARAMETER4DVARBPROC) (GLenum target, GLuint index, const GLdouble *params);
+typedef void (APIENTRYP PFNGLPROGRAMENVPARAMETER4FARBPROC) (GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+typedef void (APIENTRYP PFNGLPROGRAMENVPARAMETER4FVARBPROC) (GLenum target, GLuint index, const GLfloat *params);
+typedef void (APIENTRYP PFNGLPROGRAMLOCALPARAMETER4DARBPROC) (GLenum target, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+typedef void (APIENTRYP PFNGLPROGRAMLOCALPARAMETER4DVARBPROC) (GLenum target, GLuint index, const GLdouble *params);
+typedef void (APIENTRYP PFNGLPROGRAMLOCALPARAMETER4FARBPROC) (GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+typedef void (APIENTRYP PFNGLPROGRAMLOCALPARAMETER4FVARBPROC) (GLenum target, GLuint index, const GLfloat *params);
+typedef void (APIENTRYP PFNGLGETPROGRAMENVPARAMETERDVARBPROC) (GLenum target, GLuint index, GLdouble *params);
+typedef void (APIENTRYP PFNGLGETPROGRAMENVPARAMETERFVARBPROC) (GLenum target, GLuint index, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETPROGRAMLOCALPARAMETERDVARBPROC) (GLenum target, GLuint index, GLdouble *params);
+typedef void (APIENTRYP PFNGLGETPROGRAMLOCALPARAMETERFVARBPROC) (GLenum target, GLuint index, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETPROGRAMIVARBPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETPROGRAMSTRINGARBPROC) (GLenum target, GLenum pname, GLvoid *string);
+typedef void (APIENTRYP PFNGLGETVERTEXATTRIBDVARBPROC) (GLuint index, GLenum pname, GLdouble *params);
+typedef void (APIENTRYP PFNGLGETVERTEXATTRIBFVARBPROC) (GLuint index, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETVERTEXATTRIBIVARBPROC) (GLuint index, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETVERTEXATTRIBPOINTERVARBPROC) (GLuint index, GLenum pname, GLvoid* *pointer);
+typedef GLboolean (APIENTRYP PFNGLISPROGRAMARBPROC) (GLuint program);
+#endif
+
+#ifndef GL_ARB_fragment_program
+#define GL_ARB_fragment_program 1
+
+#endif
+
+#ifndef GL_ARB_vertex_buffer_object
+#define GL_ARB_vertex_buffer_object 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glBindBufferARB (GLenum target, GLuint buffer);
+GLAPI void APIENTRY glDeleteBuffersARB (GLsizei n, const GLuint *buffers);
+GLAPI void APIENTRY glGenBuffersARB (GLsizei n, GLuint *buffers);
+GLAPI GLboolean APIENTRY glIsBufferARB (GLuint buffer);
+GLAPI void APIENTRY glBufferDataARB (GLenum target, GLsizeiptrARB size, const GLvoid *data, GLenum usage);
+GLAPI void APIENTRY glBufferSubDataARB (GLenum target, GLintptrARB offset, GLsizeiptrARB size, const GLvoid *data);
+GLAPI void APIENTRY glGetBufferSubDataARB (GLenum target, GLintptrARB offset, GLsizeiptrARB size, GLvoid *data);
+GLAPI GLvoid* APIENTRY glMapBufferARB (GLenum target, GLenum access);
+GLAPI GLboolean APIENTRY glUnmapBufferARB (GLenum target);
+GLAPI void APIENTRY glGetBufferParameterivARB (GLenum target, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetBufferPointervARB (GLenum target, GLenum pname, GLvoid* *params);
+#endif
+typedef void (APIENTRYP PFNGLBINDBUFFERARBPROC) (GLenum target, GLuint buffer);
+typedef void (APIENTRYP PFNGLDELETEBUFFERSARBPROC) (GLsizei n, const GLuint *buffers);
+typedef void (APIENTRYP PFNGLGENBUFFERSARBPROC) (GLsizei n, GLuint *buffers);
+typedef GLboolean (APIENTRYP PFNGLISBUFFERARBPROC) (GLuint buffer);
+typedef void (APIENTRYP PFNGLBUFFERDATAARBPROC) (GLenum target, GLsizeiptrARB size, const GLvoid *data, GLenum usage);
+typedef void (APIENTRYP PFNGLBUFFERSUBDATAARBPROC) (GLenum target, GLintptrARB offset, GLsizeiptrARB size, const GLvoid *data);
+typedef void (APIENTRYP PFNGLGETBUFFERSUBDATAARBPROC) (GLenum target, GLintptrARB offset, GLsizeiptrARB size, GLvoid *data);
+typedef GLvoid* (APIENTRYP PFNGLMAPBUFFERARBPROC) (GLenum target, GLenum access);
+typedef GLboolean (APIENTRYP PFNGLUNMAPBUFFERARBPROC) (GLenum target);
+typedef void (APIENTRYP PFNGLGETBUFFERPARAMETERIVARBPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETBUFFERPOINTERVARBPROC) (GLenum target, GLenum pname, GLvoid* *params);
+#endif
+
+#ifndef GL_ARB_occlusion_query
+#define GL_ARB_occlusion_query 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glGenQueriesARB (GLsizei n, GLuint *ids);
+GLAPI void APIENTRY glDeleteQueriesARB (GLsizei n, const GLuint *ids);
+GLAPI GLboolean APIENTRY glIsQueryARB (GLuint id);
+GLAPI void APIENTRY glBeginQueryARB (GLenum target, GLuint id);
+GLAPI void APIENTRY glEndQueryARB (GLenum target);
+GLAPI void APIENTRY glGetQueryivARB (GLenum target, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetQueryObjectivARB (GLuint id, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetQueryObjectuivARB (GLuint id, GLenum pname, GLuint *params);
+#endif
+typedef void (APIENTRYP PFNGLGENQUERIESARBPROC) (GLsizei n, GLuint *ids);
+typedef void (APIENTRYP PFNGLDELETEQUERIESARBPROC) (GLsizei n, const GLuint *ids);
+typedef GLboolean (APIENTRYP PFNGLISQUERYARBPROC) (GLuint id);
+typedef void (APIENTRYP PFNGLBEGINQUERYARBPROC) (GLenum target, GLuint id);
+typedef void (APIENTRYP PFNGLENDQUERYARBPROC) (GLenum target);
+typedef void (APIENTRYP PFNGLGETQUERYIVARBPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETQUERYOBJECTIVARBPROC) (GLuint id, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETQUERYOBJECTUIVARBPROC) (GLuint id, GLenum pname, GLuint *params);
+#endif
+
+#ifndef GL_ARB_shader_objects
+#define GL_ARB_shader_objects 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glDeleteObjectARB (GLhandleARB obj);
+GLAPI GLhandleARB APIENTRY glGetHandleARB (GLenum pname);
+GLAPI void APIENTRY glDetachObjectARB (GLhandleARB containerObj, GLhandleARB attachedObj);
+GLAPI GLhandleARB APIENTRY glCreateShaderObjectARB (GLenum shaderType);
+GLAPI void APIENTRY glShaderSourceARB (GLhandleARB shaderObj, GLsizei count, const GLcharARB* *string, const GLint *length);
+GLAPI void APIENTRY glCompileShaderARB (GLhandleARB shaderObj);
+GLAPI GLhandleARB APIENTRY glCreateProgramObjectARB (void);
+GLAPI void APIENTRY glAttachObjectARB (GLhandleARB containerObj, GLhandleARB obj);
+GLAPI void APIENTRY glLinkProgramARB (GLhandleARB programObj);
+GLAPI void APIENTRY glUseProgramObjectARB (GLhandleARB programObj);
+GLAPI void APIENTRY glValidateProgramARB (GLhandleARB programObj);
+GLAPI void APIENTRY glUniform1fARB (GLint location, GLfloat v0);
+GLAPI void APIENTRY glUniform2fARB (GLint location, GLfloat v0, GLfloat v1);
+GLAPI void APIENTRY glUniform3fARB (GLint location, GLfloat v0, GLfloat v1, GLfloat v2);
+GLAPI void APIENTRY glUniform4fARB (GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
+GLAPI void APIENTRY glUniform1iARB (GLint location, GLint v0);
+GLAPI void APIENTRY glUniform2iARB (GLint location, GLint v0, GLint v1);
+GLAPI void APIENTRY glUniform3iARB (GLint location, GLint v0, GLint v1, GLint v2);
+GLAPI void APIENTRY glUniform4iARB (GLint location, GLint v0, GLint v1, GLint v2, GLint v3);
+GLAPI void APIENTRY glUniform1fvARB (GLint location, GLsizei count, const GLfloat *value);
+GLAPI void APIENTRY glUniform2fvARB (GLint location, GLsizei count, const GLfloat *value);
+GLAPI void APIENTRY glUniform3fvARB (GLint location, GLsizei count, const GLfloat *value);
+GLAPI void APIENTRY glUniform4fvARB (GLint location, GLsizei count, const GLfloat *value);
+GLAPI void APIENTRY glUniform1ivARB (GLint location, GLsizei count, const GLint *value);
+GLAPI void APIENTRY glUniform2ivARB (GLint location, GLsizei count, const GLint *value);
+GLAPI void APIENTRY glUniform3ivARB (GLint location, GLsizei count, const GLint *value);
+GLAPI void APIENTRY glUniform4ivARB (GLint location, GLsizei count, const GLint *value);
+GLAPI void APIENTRY glUniformMatrix2fvARB (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GLAPI void APIENTRY glUniformMatrix3fvARB (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GLAPI void APIENTRY glUniformMatrix4fvARB (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GLAPI void APIENTRY glGetObjectParameterfvARB (GLhandleARB obj, GLenum pname, GLfloat *params);
+GLAPI void APIENTRY glGetObjectParameterivARB (GLhandleARB obj, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetInfoLogARB (GLhandleARB obj, GLsizei maxLength, GLsizei *length, GLcharARB *infoLog);
+GLAPI void APIENTRY glGetAttachedObjectsARB (GLhandleARB containerObj, GLsizei maxCount, GLsizei *count, GLhandleARB *obj);
+GLAPI GLint APIENTRY glGetUniformLocationARB (GLhandleARB programObj, const GLcharARB *name);
+GLAPI void APIENTRY glGetActiveUniformARB (GLhandleARB programObj, GLuint index, GLsizei maxLength, GLsizei *length, GLint *size, GLenum *type, GLcharARB *name);
+GLAPI void APIENTRY glGetUniformfvARB (GLhandleARB programObj, GLint location, GLfloat *params);
+GLAPI void APIENTRY glGetUniformivARB (GLhandleARB programObj, GLint location, GLint *params);
+GLAPI void APIENTRY glGetShaderSourceARB (GLhandleARB obj, GLsizei maxLength, GLsizei *length, GLcharARB *source);
+#endif
+typedef void (APIENTRYP PFNGLDELETEOBJECTARBPROC) (GLhandleARB obj);
+typedef GLhandleARB (APIENTRYP PFNGLGETHANDLEARBPROC) (GLenum pname);
+typedef void (APIENTRYP PFNGLDETACHOBJECTARBPROC) (GLhandleARB containerObj, GLhandleARB attachedObj);
+typedef GLhandleARB (APIENTRYP PFNGLCREATESHADEROBJECTARBPROC) (GLenum shaderType);
+typedef void (APIENTRYP PFNGLSHADERSOURCEARBPROC) (GLhandleARB shaderObj, GLsizei count, const GLcharARB* *string, const GLint *length);
+typedef void (APIENTRYP PFNGLCOMPILESHADERARBPROC) (GLhandleARB shaderObj);
+typedef GLhandleARB (APIENTRYP PFNGLCREATEPROGRAMOBJECTARBPROC) (void);
+typedef void (APIENTRYP PFNGLATTACHOBJECTARBPROC) (GLhandleARB containerObj, GLhandleARB obj);
+typedef void (APIENTRYP PFNGLLINKPROGRAMARBPROC) (GLhandleARB programObj);
+typedef void (APIENTRYP PFNGLUSEPROGRAMOBJECTARBPROC) (GLhandleARB programObj);
+typedef void (APIENTRYP PFNGLVALIDATEPROGRAMARBPROC) (GLhandleARB programObj);
+typedef void (APIENTRYP PFNGLUNIFORM1FARBPROC) (GLint location, GLfloat v0);
+typedef void (APIENTRYP PFNGLUNIFORM2FARBPROC) (GLint location, GLfloat v0, GLfloat v1);
+typedef void (APIENTRYP PFNGLUNIFORM3FARBPROC) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2);
+typedef void (APIENTRYP PFNGLUNIFORM4FARBPROC) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
+typedef void (APIENTRYP PFNGLUNIFORM1IARBPROC) (GLint location, GLint v0);
+typedef void (APIENTRYP PFNGLUNIFORM2IARBPROC) (GLint location, GLint v0, GLint v1);
+typedef void (APIENTRYP PFNGLUNIFORM3IARBPROC) (GLint location, GLint v0, GLint v1, GLint v2);
+typedef void (APIENTRYP PFNGLUNIFORM4IARBPROC) (GLint location, GLint v0, GLint v1, GLint v2, GLint v3);
+typedef void (APIENTRYP PFNGLUNIFORM1FVARBPROC) (GLint location, GLsizei count, const GLfloat *value);
+typedef void (APIENTRYP PFNGLUNIFORM2FVARBPROC) (GLint location, GLsizei count, const GLfloat *value);
+typedef void (APIENTRYP PFNGLUNIFORM3FVARBPROC) (GLint location, GLsizei count, const GLfloat *value);
+typedef void (APIENTRYP PFNGLUNIFORM4FVARBPROC) (GLint location, GLsizei count, const GLfloat *value);
+typedef void (APIENTRYP PFNGLUNIFORM1IVARBPROC) (GLint location, GLsizei count, const GLint *value);
+typedef void (APIENTRYP PFNGLUNIFORM2IVARBPROC) (GLint location, GLsizei count, const GLint *value);
+typedef void (APIENTRYP PFNGLUNIFORM3IVARBPROC) (GLint location, GLsizei count, const GLint *value);
+typedef void (APIENTRYP PFNGLUNIFORM4IVARBPROC) (GLint location, GLsizei count, const GLint *value);
+typedef void (APIENTRYP PFNGLUNIFORMMATRIX2FVARBPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (APIENTRYP PFNGLUNIFORMMATRIX3FVARBPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (APIENTRYP PFNGLUNIFORMMATRIX4FVARBPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (APIENTRYP PFNGLGETOBJECTPARAMETERFVARBPROC) (GLhandleARB obj, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETOBJECTPARAMETERIVARBPROC) (GLhandleARB obj, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETINFOLOGARBPROC) (GLhandleARB obj, GLsizei maxLength, GLsizei *length, GLcharARB *infoLog);
+typedef void (APIENTRYP PFNGLGETATTACHEDOBJECTSARBPROC) (GLhandleARB containerObj, GLsizei maxCount, GLsizei *count, GLhandleARB *obj);
+typedef GLint (APIENTRYP PFNGLGETUNIFORMLOCATIONARBPROC) (GLhandleARB programObj, const GLcharARB *name);
+typedef void (APIENTRYP PFNGLGETACTIVEUNIFORMARBPROC) (GLhandleARB programObj, GLuint index, GLsizei maxLength, GLsizei *length, GLint *size, GLenum *type, GLcharARB *name);
+typedef void (APIENTRYP PFNGLGETUNIFORMFVARBPROC) (GLhandleARB programObj, GLint location, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETUNIFORMIVARBPROC) (GLhandleARB programObj, GLint location, GLint *params);
+typedef void (APIENTRYP PFNGLGETSHADERSOURCEARBPROC) (GLhandleARB obj, GLsizei maxLength, GLsizei *length, GLcharARB *source);
+#endif
+
+#ifndef GL_ARB_vertex_shader
+#define GL_ARB_vertex_shader 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glBindAttribLocationARB (GLhandleARB programObj, GLuint index, const GLcharARB *name);
+GLAPI void APIENTRY glGetActiveAttribARB (GLhandleARB programObj, GLuint index, GLsizei maxLength, GLsizei *length, GLint *size, GLenum *type, GLcharARB *name);
+GLAPI GLint APIENTRY glGetAttribLocationARB (GLhandleARB programObj, const GLcharARB *name);
+#endif
+typedef void (APIENTRYP PFNGLBINDATTRIBLOCATIONARBPROC) (GLhandleARB programObj, GLuint index, const GLcharARB *name);
+typedef void (APIENTRYP PFNGLGETACTIVEATTRIBARBPROC) (GLhandleARB programObj, GLuint index, GLsizei maxLength, GLsizei *length, GLint *size, GLenum *type, GLcharARB *name);
+typedef GLint (APIENTRYP PFNGLGETATTRIBLOCATIONARBPROC) (GLhandleARB programObj, const GLcharARB *name);
+#endif
+
+#ifndef GL_ARB_fragment_shader
+#define GL_ARB_fragment_shader 1
+#endif
+
+#ifndef GL_ARB_shading_language_100
+#define GL_ARB_shading_language_100 1
+#endif
+
+#ifndef GL_ARB_texture_non_power_of_two
+#define GL_ARB_texture_non_power_of_two 1
+#endif
+
+#ifndef GL_ARB_point_sprite
+#define GL_ARB_point_sprite 1
+#endif
+
+#ifndef GL_ARB_fragment_program_shadow
+#define GL_ARB_fragment_program_shadow 1
+#endif
+
+#ifndef GL_ARB_draw_buffers
+#define GL_ARB_draw_buffers 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glDrawBuffersARB (GLsizei n, const GLenum *bufs);
+#endif
+typedef void (APIENTRYP PFNGLDRAWBUFFERSARBPROC) (GLsizei n, const GLenum *bufs);
+#endif
+
+#ifndef GL_ARB_texture_rectangle
+#define GL_ARB_texture_rectangle 1
+#endif
+
+#ifndef GL_ARB_color_buffer_float
+#define GL_ARB_color_buffer_float 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glClampColorARB (GLenum target, GLenum clamp);
+#endif
+typedef void (APIENTRYP PFNGLCLAMPCOLORARBPROC) (GLenum target, GLenum clamp);
+#endif
+
+#ifndef GL_ARB_half_float_pixel
+#define GL_ARB_half_float_pixel 1
+#endif
+
+#ifndef GL_ARB_texture_float
+#define GL_ARB_texture_float 1
+#endif
+
+#ifndef GL_ARB_pixel_buffer_object
+#define GL_ARB_pixel_buffer_object 1
+#endif
+
+#ifndef GL_ARB_depth_buffer_float
+#define GL_ARB_depth_buffer_float 1
+#endif
+
+#ifndef GL_ARB_draw_instanced
+#define GL_ARB_draw_instanced 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glDrawArraysInstancedARB (GLenum mode, GLint first, GLsizei count, GLsizei primcount);
+GLAPI void APIENTRY glDrawElementsInstancedARB (GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLsizei primcount);
+#endif
+typedef void (APIENTRYP PFNGLDRAWARRAYSINSTANCEDARBPROC) (GLenum mode, GLint first, GLsizei count, GLsizei primcount);
+typedef void (APIENTRYP PFNGLDRAWELEMENTSINSTANCEDARBPROC) (GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLsizei primcount);
+#endif
+
+#ifndef GL_ARB_framebuffer_object
+#define GL_ARB_framebuffer_object 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI GLboolean APIENTRY glIsRenderbuffer (GLuint renderbuffer);
+GLAPI void APIENTRY glBindRenderbuffer (GLenum target, GLuint renderbuffer);
+GLAPI void APIENTRY glDeleteRenderbuffers (GLsizei n, const GLuint *renderbuffers);
+GLAPI void APIENTRY glGenRenderbuffers (GLsizei n, GLuint *renderbuffers);
+GLAPI void APIENTRY glRenderbufferStorage (GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
+GLAPI void APIENTRY glGetRenderbufferParameteriv (GLenum target, GLenum pname, GLint *params);
+GLAPI GLboolean APIENTRY glIsFramebuffer (GLuint framebuffer);
+GLAPI void APIENTRY glBindFramebuffer (GLenum target, GLuint framebuffer);
+GLAPI void APIENTRY glDeleteFramebuffers (GLsizei n, const GLuint *framebuffers);
+GLAPI void APIENTRY glGenFramebuffers (GLsizei n, GLuint *framebuffers);
+GLAPI GLenum APIENTRY glCheckFramebufferStatus (GLenum target);
+GLAPI void APIENTRY glFramebufferTexture1D (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
+GLAPI void APIENTRY glFramebufferTexture2D (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
+GLAPI void APIENTRY glFramebufferTexture3D (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset);
+GLAPI void APIENTRY glFramebufferRenderbuffer (GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer);
+GLAPI void APIENTRY glGetFramebufferAttachmentParameteriv (GLenum target, GLenum attachment, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGenerateMipmap (GLenum target);
+GLAPI void APIENTRY glBlitFramebuffer (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter);
+GLAPI void APIENTRY glRenderbufferStorageMultisample (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
+GLAPI void APIENTRY glFramebufferTextureLayer (GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer);
+#endif
+typedef GLboolean (APIENTRYP PFNGLISRENDERBUFFERPROC) (GLuint renderbuffer);
+typedef void (APIENTRYP PFNGLBINDRENDERBUFFERPROC) (GLenum target, GLuint renderbuffer);
+typedef void (APIENTRYP PFNGLDELETERENDERBUFFERSPROC) (GLsizei n, const GLuint *renderbuffers);
+typedef void (APIENTRYP PFNGLGENRENDERBUFFERSPROC) (GLsizei n, GLuint *renderbuffers);
+typedef void (APIENTRYP PFNGLRENDERBUFFERSTORAGEPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
+typedef void (APIENTRYP PFNGLGETRENDERBUFFERPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params);
+typedef GLboolean (APIENTRYP PFNGLISFRAMEBUFFERPROC) (GLuint framebuffer);
+typedef void (APIENTRYP PFNGLBINDFRAMEBUFFERPROC) (GLenum target, GLuint framebuffer);
+typedef void (APIENTRYP PFNGLDELETEFRAMEBUFFERSPROC) (GLsizei n, const GLuint *framebuffers);
+typedef void (APIENTRYP PFNGLGENFRAMEBUFFERSPROC) (GLsizei n, GLuint *framebuffers);
+typedef GLenum (APIENTRYP PFNGLCHECKFRAMEBUFFERSTATUSPROC) (GLenum target);
+typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTURE1DPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
+typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTURE2DPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
+typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTURE3DPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset);
+typedef void (APIENTRYP PFNGLFRAMEBUFFERRENDERBUFFERPROC) (GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer);
+typedef void (APIENTRYP PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC) (GLenum target, GLenum attachment, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGENERATEMIPMAPPROC) (GLenum target);
+typedef void (APIENTRYP PFNGLBLITFRAMEBUFFERPROC) (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter);
+typedef void (APIENTRYP PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
+typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTURELAYERPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer);
+#endif
+
+#ifndef GL_ARB_framebuffer_sRGB
+#define GL_ARB_framebuffer_sRGB 1
+#endif
+
+#ifndef GL_ARB_geometry_shader4
+#define GL_ARB_geometry_shader4 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glProgramParameteriARB (GLuint program, GLenum pname, GLint value);
+GLAPI void APIENTRY glFramebufferTextureARB (GLenum target, GLenum attachment, GLuint texture, GLint level);
+GLAPI void APIENTRY glFramebufferTextureLayerARB (GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer);
+GLAPI void APIENTRY glFramebufferTextureFaceARB (GLenum target, GLenum attachment, GLuint texture, GLint level, GLenum face);
+#endif
+typedef void (APIENTRYP PFNGLPROGRAMPARAMETERIARBPROC) (GLuint program, GLenum pname, GLint value);
+typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTUREARBPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level);
+typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTURELAYERARBPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer);
+typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTUREFACEARBPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level, GLenum face);
+#endif
+
+#ifndef GL_ARB_half_float_vertex
+#define GL_ARB_half_float_vertex 1
+#endif
+
+#ifndef GL_ARB_instanced_arrays
+#define GL_ARB_instanced_arrays 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glVertexAttribDivisorARB (GLuint index, GLuint divisor);
+#endif
+typedef void (APIENTRYP PFNGLVERTEXATTRIBDIVISORARBPROC) (GLuint index, GLuint divisor);
+#endif
+
+#ifndef GL_ARB_map_buffer_range
+#define GL_ARB_map_buffer_range 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI GLvoid* APIENTRY glMapBufferRange (GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access);
+GLAPI void APIENTRY glFlushMappedBufferRange (GLenum target, GLintptr offset, GLsizeiptr length);
+#endif
+typedef GLvoid* (APIENTRYP PFNGLMAPBUFFERRANGEPROC) (GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access);
+typedef void (APIENTRYP PFNGLFLUSHMAPPEDBUFFERRANGEPROC) (GLenum target, GLintptr offset, GLsizeiptr length);
+#endif
+
+#ifndef GL_ARB_texture_buffer_object
+#define GL_ARB_texture_buffer_object 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glTexBufferARB (GLenum target, GLenum internalformat, GLuint buffer);
+#endif
+typedef void (APIENTRYP PFNGLTEXBUFFERARBPROC) (GLenum target, GLenum internalformat, GLuint buffer);
+#endif
+
+#ifndef GL_ARB_texture_compression_rgtc
+#define GL_ARB_texture_compression_rgtc 1
+#endif
+
+#ifndef GL_ARB_texture_rg
+#define GL_ARB_texture_rg 1
+#endif
+
+#ifndef GL_ARB_vertex_array_object
+#define GL_ARB_vertex_array_object 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glBindVertexArray (GLuint array);
+GLAPI void APIENTRY glDeleteVertexArrays (GLsizei n, const GLuint *arrays);
+GLAPI void APIENTRY glGenVertexArrays (GLsizei n, GLuint *arrays);
+GLAPI GLboolean APIENTRY glIsVertexArray (GLuint array);
+#endif
+typedef void (APIENTRYP PFNGLBINDVERTEXARRAYPROC) (GLuint array);
+typedef void (APIENTRYP PFNGLDELETEVERTEXARRAYSPROC) (GLsizei n, const GLuint *arrays);
+typedef void (APIENTRYP PFNGLGENVERTEXARRAYSPROC) (GLsizei n, GLuint *arrays);
+typedef GLboolean (APIENTRYP PFNGLISVERTEXARRAYPROC) (GLuint array);
+#endif
+
+#ifndef GL_ARB_uniform_buffer_object
+#define GL_ARB_uniform_buffer_object 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glGetUniformIndices (GLuint program, GLsizei uniformCount, const GLchar* *uniformNames, GLuint *uniformIndices);
+GLAPI void APIENTRY glGetActiveUniformsiv (GLuint program, GLsizei uniformCount, const GLuint *uniformIndices, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetActiveUniformName (GLuint program, GLuint uniformIndex, GLsizei bufSize, GLsizei *length, GLchar *uniformName);
+GLAPI GLuint APIENTRY glGetUniformBlockIndex (GLuint program, const GLchar *uniformBlockName);
+GLAPI void APIENTRY glGetActiveUniformBlockiv (GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetActiveUniformBlockName (GLuint program, GLuint uniformBlockIndex, GLsizei bufSize, GLsizei *length, GLchar *uniformBlockName);
+GLAPI void APIENTRY glUniformBlockBinding (GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding);
+#endif
+typedef void (APIENTRYP PFNGLGETUNIFORMINDICESPROC) (GLuint program, GLsizei uniformCount, const GLchar* *uniformNames, GLuint *uniformIndices);
+typedef void (APIENTRYP PFNGLGETACTIVEUNIFORMSIVPROC) (GLuint program, GLsizei uniformCount, const GLuint *uniformIndices, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETACTIVEUNIFORMNAMEPROC) (GLuint program, GLuint uniformIndex, GLsizei bufSize, GLsizei *length, GLchar *uniformName);
+typedef GLuint (APIENTRYP PFNGLGETUNIFORMBLOCKINDEXPROC) (GLuint program, const GLchar *uniformBlockName);
+typedef void (APIENTRYP PFNGLGETACTIVEUNIFORMBLOCKIVPROC) (GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETACTIVEUNIFORMBLOCKNAMEPROC) (GLuint program, GLuint uniformBlockIndex, GLsizei bufSize, GLsizei *length, GLchar *uniformBlockName);
+typedef void (APIENTRYP PFNGLUNIFORMBLOCKBINDINGPROC) (GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding);
+#endif
+
+#ifndef GL_ARB_compatibility
+#define GL_ARB_compatibility 1
+#endif
+
+#ifndef GL_ARB_copy_buffer
+#define GL_ARB_copy_buffer 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glCopyBufferSubData (GLenum readTarget, GLenum writeTarget, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size);
+#endif
+typedef void (APIENTRYP PFNGLCOPYBUFFERSUBDATAPROC) (GLenum readTarget, GLenum writeTarget, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size);
+#endif
+
+#ifndef GL_ARB_shader_texture_lod
+#define GL_ARB_shader_texture_lod 1
+#endif
+
+#ifndef GL_ARB_depth_clamp
+#define GL_ARB_depth_clamp 1
+#endif
+
+#ifndef GL_ARB_draw_elements_base_vertex
+#define GL_ARB_draw_elements_base_vertex 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glDrawElementsBaseVertex (GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLint basevertex);
+GLAPI void APIENTRY glDrawRangeElementsBaseVertex (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid *indices, GLint basevertex);
+GLAPI void APIENTRY glDrawElementsInstancedBaseVertex (GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLsizei primcount, GLint basevertex);
+GLAPI void APIENTRY glMultiDrawElementsBaseVertex (GLenum mode, const GLsizei *count, GLenum type, const GLvoid* *indices, GLsizei primcount, const GLint *basevertex);
+#endif
+typedef void (APIENTRYP PFNGLDRAWELEMENTSBASEVERTEXPROC) (GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLint basevertex);
+typedef void (APIENTRYP PFNGLDRAWRANGEELEMENTSBASEVERTEXPROC) (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid *indices, GLint basevertex);
+typedef void (APIENTRYP PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXPROC) (GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLsizei primcount, GLint basevertex);
+typedef void (APIENTRYP PFNGLMULTIDRAWELEMENTSBASEVERTEXPROC) (GLenum mode, const GLsizei *count, GLenum type, const GLvoid* *indices, GLsizei primcount, const GLint *basevertex);
+#endif
+
+#ifndef GL_ARB_fragment_coord_conventions
+#define GL_ARB_fragment_coord_conventions 1
+#endif
+
+#ifndef GL_ARB_provoking_vertex
+#define GL_ARB_provoking_vertex 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glProvokingVertex (GLenum mode);
+#endif
+typedef void (APIENTRYP PFNGLPROVOKINGVERTEXPROC) (GLenum mode);
+#endif
+
+#ifndef GL_ARB_seamless_cube_map
+#define GL_ARB_seamless_cube_map 1
+#endif
+
+#ifndef GL_ARB_sync
+#define GL_ARB_sync 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI GLsync APIENTRY glFenceSync (GLenum condition, GLbitfield flags);
+GLAPI GLboolean APIENTRY glIsSync (GLsync sync);
+GLAPI void APIENTRY glDeleteSync (GLsync sync);
+GLAPI GLenum APIENTRY glClientWaitSync (GLsync sync, GLbitfield flags, GLuint64 timeout);
+GLAPI void APIENTRY glWaitSync (GLsync sync, GLbitfield flags, GLuint64 timeout);
+GLAPI void APIENTRY glGetInteger64v (GLenum pname, GLint64 *params);
+GLAPI void APIENTRY glGetSynciv (GLsync sync, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *values);
+#endif
+typedef GLsync (APIENTRYP PFNGLFENCESYNCPROC) (GLenum condition, GLbitfield flags);
+typedef GLboolean (APIENTRYP PFNGLISSYNCPROC) (GLsync sync);
+typedef void (APIENTRYP PFNGLDELETESYNCPROC) (GLsync sync);
+typedef GLenum (APIENTRYP PFNGLCLIENTWAITSYNCPROC) (GLsync sync, GLbitfield flags, GLuint64 timeout);
+typedef void (APIENTRYP PFNGLWAITSYNCPROC) (GLsync sync, GLbitfield flags, GLuint64 timeout);
+typedef void (APIENTRYP PFNGLGETINTEGER64VPROC) (GLenum pname, GLint64 *params);
+typedef void (APIENTRYP PFNGLGETSYNCIVPROC) (GLsync sync, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *values);
+#endif
+
+#ifndef GL_ARB_texture_multisample
+#define GL_ARB_texture_multisample 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glTexImage2DMultisample (GLenum target, GLsizei samples, GLint internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations);
+GLAPI void APIENTRY glTexImage3DMultisample (GLenum target, GLsizei samples, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedsamplelocations);
+GLAPI void APIENTRY glGetMultisamplefv (GLenum pname, GLuint index, GLfloat *val);
+GLAPI void APIENTRY glSampleMaski (GLuint index, GLbitfield mask);
+#endif
+typedef void (APIENTRYP PFNGLTEXIMAGE2DMULTISAMPLEPROC) (GLenum target, GLsizei samples, GLint internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations);
+typedef void (APIENTRYP PFNGLTEXIMAGE3DMULTISAMPLEPROC) (GLenum target, GLsizei samples, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedsamplelocations);
+typedef void (APIENTRYP PFNGLGETMULTISAMPLEFVPROC) (GLenum pname, GLuint index, GLfloat *val);
+typedef void (APIENTRYP PFNGLSAMPLEMASKIPROC) (GLuint index, GLbitfield mask);
+#endif
+
+#ifndef GL_ARB_vertex_array_bgra
+#define GL_ARB_vertex_array_bgra 1
+#endif
+
+#ifndef GL_ARB_draw_buffers_blend
+#define GL_ARB_draw_buffers_blend 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glBlendEquationiARB (GLuint buf, GLenum mode);
+GLAPI void APIENTRY glBlendEquationSeparateiARB (GLuint buf, GLenum modeRGB, GLenum modeAlpha);
+GLAPI void APIENTRY glBlendFunciARB (GLuint buf, GLenum src, GLenum dst);
+GLAPI void APIENTRY glBlendFuncSeparateiARB (GLuint buf, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha);
+#endif
+typedef void (APIENTRYP PFNGLBLENDEQUATIONIARBPROC) (GLuint buf, GLenum mode);
+typedef void (APIENTRYP PFNGLBLENDEQUATIONSEPARATEIARBPROC) (GLuint buf, GLenum modeRGB, GLenum modeAlpha);
+typedef void (APIENTRYP PFNGLBLENDFUNCIARBPROC) (GLuint buf, GLenum src, GLenum dst);
+typedef void (APIENTRYP PFNGLBLENDFUNCSEPARATEIARBPROC) (GLuint buf, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha);
+#endif
+
+#ifndef GL_ARB_sample_shading
+#define GL_ARB_sample_shading 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glMinSampleShadingARB (GLclampf value);
+#endif
+typedef void (APIENTRYP PFNGLMINSAMPLESHADINGARBPROC) (GLclampf value);
+#endif
+
+#ifndef GL_ARB_texture_cube_map_array
+#define GL_ARB_texture_cube_map_array 1
+#endif
+
+#ifndef GL_ARB_texture_gather
+#define GL_ARB_texture_gather 1
+#endif
+
+#ifndef GL_ARB_texture_query_lod
+#define GL_ARB_texture_query_lod 1
+#endif
+
+#ifndef GL_ARB_shading_language_include
+#define GL_ARB_shading_language_include 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glNamedStringARB (GLenum type, GLint namelen, const GLchar *name, GLint stringlen, const GLchar *string);
+GLAPI void APIENTRY glDeleteNamedStringARB (GLint namelen, const GLchar *name);
+GLAPI void APIENTRY glCompileShaderIncludeARB (GLuint shader, GLsizei count, const GLchar* *path, const GLint *length);
+GLAPI GLboolean APIENTRY glIsNamedStringARB (GLint namelen, const GLchar *name);
+GLAPI void APIENTRY glGetNamedStringARB (GLint namelen, const GLchar *name, GLsizei bufSize, GLint *stringlen, GLchar *string);
+GLAPI void APIENTRY glGetNamedStringivARB (GLint namelen, const GLchar *name, GLenum pname, GLint *params);
+#endif
+typedef void (APIENTRYP PFNGLNAMEDSTRINGARBPROC) (GLenum type, GLint namelen, const GLchar *name, GLint stringlen, const GLchar *string);
+typedef void (APIENTRYP PFNGLDELETENAMEDSTRINGARBPROC) (GLint namelen, const GLchar *name);
+typedef void (APIENTRYP PFNGLCOMPILESHADERINCLUDEARBPROC) (GLuint shader, GLsizei count, const GLchar* *path, const GLint *length);
+typedef GLboolean (APIENTRYP PFNGLISNAMEDSTRINGARBPROC) (GLint namelen, const GLchar *name);
+typedef void (APIENTRYP PFNGLGETNAMEDSTRINGARBPROC) (GLint namelen, const GLchar *name, GLsizei bufSize, GLint *stringlen, GLchar *string);
+typedef void (APIENTRYP PFNGLGETNAMEDSTRINGIVARBPROC) (GLint namelen, const GLchar *name, GLenum pname, GLint *params);
+#endif
+
+#ifndef GL_ARB_texture_compression_bptc
+#define GL_ARB_texture_compression_bptc 1
+#endif
+
+#ifndef GL_ARB_blend_func_extended
+#define GL_ARB_blend_func_extended 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glBindFragDataLocationIndexed (GLuint program, GLuint colorNumber, GLuint index, const GLchar *name);
+GLAPI GLint APIENTRY glGetFragDataIndex (GLuint program, const GLchar *name);
+#endif
+typedef void (APIENTRYP PFNGLBINDFRAGDATALOCATIONINDEXEDPROC) (GLuint program, GLuint colorNumber, GLuint index, const GLchar *name);
+typedef GLint (APIENTRYP PFNGLGETFRAGDATAINDEXPROC) (GLuint program, const GLchar *name);
+#endif
+
+#ifndef GL_ARB_explicit_attrib_location
+#define GL_ARB_explicit_attrib_location 1
+#endif
+
+#ifndef GL_ARB_occlusion_query2
+#define GL_ARB_occlusion_query2 1
+#endif
+
+#ifndef GL_ARB_sampler_objects
+#define GL_ARB_sampler_objects 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glGenSamplers (GLsizei count, GLuint *samplers);
+GLAPI void APIENTRY glDeleteSamplers (GLsizei count, const GLuint *samplers);
+GLAPI GLboolean APIENTRY glIsSampler (GLuint sampler);
+GLAPI void APIENTRY glBindSampler (GLuint unit, GLuint sampler);
+GLAPI void APIENTRY glSamplerParameteri (GLuint sampler, GLenum pname, GLint param);
+GLAPI void APIENTRY glSamplerParameteriv (GLuint sampler, GLenum pname, const GLint *param);
+GLAPI void APIENTRY glSamplerParameterf (GLuint sampler, GLenum pname, GLfloat param);
+GLAPI void APIENTRY glSamplerParameterfv (GLuint sampler, GLenum pname, const GLfloat *param);
+GLAPI void APIENTRY glSamplerParameterIiv (GLuint sampler, GLenum pname, const GLint *param);
+GLAPI void APIENTRY glSamplerParameterIuiv (GLuint sampler, GLenum pname, const GLuint *param);
+GLAPI void APIENTRY glGetSamplerParameteriv (GLuint sampler, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetSamplerParameterIiv (GLuint sampler, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetSamplerParameterfv (GLuint sampler, GLenum pname, GLfloat *params);
+GLAPI void APIENTRY glGetSamplerParameterIuiv (GLuint sampler, GLenum pname, GLuint *params);
+#endif
+typedef void (APIENTRYP PFNGLGENSAMPLERSPROC) (GLsizei count, GLuint *samplers);
+typedef void (APIENTRYP PFNGLDELETESAMPLERSPROC) (GLsizei count, const GLuint *samplers);
+typedef GLboolean (APIENTRYP PFNGLISSAMPLERPROC) (GLuint sampler);
+typedef void (APIENTRYP PFNGLBINDSAMPLERPROC) (GLuint unit, GLuint sampler);
+typedef void (APIENTRYP PFNGLSAMPLERPARAMETERIPROC) (GLuint sampler, GLenum pname, GLint param);
+typedef void (APIENTRYP PFNGLSAMPLERPARAMETERIVPROC) (GLuint sampler, GLenum pname, const GLint *param);
+typedef void (APIENTRYP PFNGLSAMPLERPARAMETERFPROC) (GLuint sampler, GLenum pname, GLfloat param);
+typedef void (APIENTRYP PFNGLSAMPLERPARAMETERFVPROC) (GLuint sampler, GLenum pname, const GLfloat *param);
+typedef void (APIENTRYP PFNGLSAMPLERPARAMETERIIVPROC) (GLuint sampler, GLenum pname, const GLint *param);
+typedef void (APIENTRYP PFNGLSAMPLERPARAMETERIUIVPROC) (GLuint sampler, GLenum pname, const GLuint *param);
+typedef void (APIENTRYP PFNGLGETSAMPLERPARAMETERIVPROC) (GLuint sampler, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETSAMPLERPARAMETERIIVPROC) (GLuint sampler, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETSAMPLERPARAMETERFVPROC) (GLuint sampler, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETSAMPLERPARAMETERIUIVPROC) (GLuint sampler, GLenum pname, GLuint *params);
+#endif
+
+#ifndef GL_ARB_texture_rgb10_a2ui
+#define GL_ARB_texture_rgb10_a2ui 1
+#endif
+
+#ifndef GL_ARB_texture_swizzle
+#define GL_ARB_texture_swizzle 1
+#endif
+
+#ifndef GL_ARB_timer_query
+#define GL_ARB_timer_query 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glQueryCounter (GLuint id, GLenum target);
+GLAPI void APIENTRY glGetQueryObjecti64v (GLuint id, GLenum pname, GLint64 *params);
+GLAPI void APIENTRY glGetQueryObjectui64v (GLuint id, GLenum pname, GLuint64 *params);
+#endif
+typedef void (APIENTRYP PFNGLQUERYCOUNTERPROC) (GLuint id, GLenum target);
+typedef void (APIENTRYP PFNGLGETQUERYOBJECTI64VPROC) (GLuint id, GLenum pname, GLint64 *params);
+typedef void (APIENTRYP PFNGLGETQUERYOBJECTUI64VPROC) (GLuint id, GLenum pname, GLuint64 *params);
+#endif
+
+#ifndef GL_ARB_vertex_type_2_10_10_10_rev
+#define GL_ARB_vertex_type_2_10_10_10_rev 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glVertexP2ui (GLenum type, GLuint value);
+GLAPI void APIENTRY glVertexP2uiv (GLenum type, const GLuint *value);
+GLAPI void APIENTRY glVertexP3ui (GLenum type, GLuint value);
+GLAPI void APIENTRY glVertexP3uiv (GLenum type, const GLuint *value);
+GLAPI void APIENTRY glVertexP4ui (GLenum type, GLuint value);
+GLAPI void APIENTRY glVertexP4uiv (GLenum type, const GLuint *value);
+GLAPI void APIENTRY glTexCoordP1ui (GLenum type, GLuint coords);
+GLAPI void APIENTRY glTexCoordP1uiv (GLenum type, const GLuint *coords);
+GLAPI void APIENTRY glTexCoordP2ui (GLenum type, GLuint coords);
+GLAPI void APIENTRY glTexCoordP2uiv (GLenum type, const GLuint *coords);
+GLAPI void APIENTRY glTexCoordP3ui (GLenum type, GLuint coords);
+GLAPI void APIENTRY glTexCoordP3uiv (GLenum type, const GLuint *coords);
+GLAPI void APIENTRY glTexCoordP4ui (GLenum type, GLuint coords);
+GLAPI void APIENTRY glTexCoordP4uiv (GLenum type, const GLuint *coords);
+GLAPI void APIENTRY glMultiTexCoordP1ui (GLenum texture, GLenum type, GLuint coords);
+GLAPI void APIENTRY glMultiTexCoordP1uiv (GLenum texture, GLenum type, const GLuint *coords);
+GLAPI void APIENTRY glMultiTexCoordP2ui (GLenum texture, GLenum type, GLuint coords);
+GLAPI void APIENTRY glMultiTexCoordP2uiv (GLenum texture, GLenum type, const GLuint *coords);
+GLAPI void APIENTRY glMultiTexCoordP3ui (GLenum texture, GLenum type, GLuint coords);
+GLAPI void APIENTRY glMultiTexCoordP3uiv (GLenum texture, GLenum type, const GLuint *coords);
+GLAPI void APIENTRY glMultiTexCoordP4ui (GLenum texture, GLenum type, GLuint coords);
+GLAPI void APIENTRY glMultiTexCoordP4uiv (GLenum texture, GLenum type, const GLuint *coords);
+GLAPI void APIENTRY glNormalP3ui (GLenum type, GLuint coords);
+GLAPI void APIENTRY glNormalP3uiv (GLenum type, const GLuint *coords);
+GLAPI void APIENTRY glColorP3ui (GLenum type, GLuint color);
+GLAPI void APIENTRY glColorP3uiv (GLenum type, const GLuint *color);
+GLAPI void APIENTRY glColorP4ui (GLenum type, GLuint color);
+GLAPI void APIENTRY glColorP4uiv (GLenum type, const GLuint *color);
+GLAPI void APIENTRY glSecondaryColorP3ui (GLenum type, GLuint color);
+GLAPI void APIENTRY glSecondaryColorP3uiv (GLenum type, const GLuint *color);
+GLAPI void APIENTRY glVertexAttribP1ui (GLuint index, GLenum type, GLboolean normalized, GLuint value);
+GLAPI void APIENTRY glVertexAttribP1uiv (GLuint index, GLenum type, GLboolean normalized, const GLuint *value);
+GLAPI void APIENTRY glVertexAttribP2ui (GLuint index, GLenum type, GLboolean normalized, GLuint value);
+GLAPI void APIENTRY glVertexAttribP2uiv (GLuint index, GLenum type, GLboolean normalized, const GLuint *value);
+GLAPI void APIENTRY glVertexAttribP3ui (GLuint index, GLenum type, GLboolean normalized, GLuint value);
+GLAPI void APIENTRY glVertexAttribP3uiv (GLuint index, GLenum type, GLboolean normalized, const GLuint *value);
+GLAPI void APIENTRY glVertexAttribP4ui (GLuint index, GLenum type, GLboolean normalized, GLuint value);
+GLAPI void APIENTRY glVertexAttribP4uiv (GLuint index, GLenum type, GLboolean normalized, const GLuint *value);
+#endif
+typedef void (APIENTRYP PFNGLVERTEXP2UIPROC) (GLenum type, GLuint value);
+typedef void (APIENTRYP PFNGLVERTEXP2UIVPROC) (GLenum type, const GLuint *value);
+typedef void (APIENTRYP PFNGLVERTEXP3UIPROC) (GLenum type, GLuint value);
+typedef void (APIENTRYP PFNGLVERTEXP3UIVPROC) (GLenum type, const GLuint *value);
+typedef void (APIENTRYP PFNGLVERTEXP4UIPROC) (GLenum type, GLuint value);
+typedef void (APIENTRYP PFNGLVERTEXP4UIVPROC) (GLenum type, const GLuint *value);
+typedef void (APIENTRYP PFNGLTEXCOORDP1UIPROC) (GLenum type, GLuint coords);
+typedef void (APIENTRYP PFNGLTEXCOORDP1UIVPROC) (GLenum type, const GLuint *coords);
+typedef void (APIENTRYP PFNGLTEXCOORDP2UIPROC) (GLenum type, GLuint coords);
+typedef void (APIENTRYP PFNGLTEXCOORDP2UIVPROC) (GLenum type, const GLuint *coords);
+typedef void (APIENTRYP PFNGLTEXCOORDP3UIPROC) (GLenum type, GLuint coords);
+typedef void (APIENTRYP PFNGLTEXCOORDP3UIVPROC) (GLenum type, const GLuint *coords);
+typedef void (APIENTRYP PFNGLTEXCOORDP4UIPROC) (GLenum type, GLuint coords);
+typedef void (APIENTRYP PFNGLTEXCOORDP4UIVPROC) (GLenum type, const GLuint *coords);
+typedef void (APIENTRYP PFNGLMULTITEXCOORDP1UIPROC) (GLenum texture, GLenum type, GLuint coords);
+typedef void (APIENTRYP PFNGLMULTITEXCOORDP1UIVPROC) (GLenum texture, GLenum type, const GLuint *coords);
+typedef void (APIENTRYP PFNGLMULTITEXCOORDP2UIPROC) (GLenum texture, GLenum type, GLuint coords);
+typedef void (APIENTRYP PFNGLMULTITEXCOORDP2UIVPROC) (GLenum texture, GLenum type, const GLuint *coords);
+typedef void (APIENTRYP PFNGLMULTITEXCOORDP3UIPROC) (GLenum texture, GLenum type, GLuint coords);
+typedef void (APIENTRYP PFNGLMULTITEXCOORDP3UIVPROC) (GLenum texture, GLenum type, const GLuint *coords);
+typedef void (APIENTRYP PFNGLMULTITEXCOORDP4UIPROC) (GLenum texture, GLenum type, GLuint coords);
+typedef void (APIENTRYP PFNGLMULTITEXCOORDP4UIVPROC) (GLenum texture, GLenum type, const GLuint *coords);
+typedef void (APIENTRYP PFNGLNORMALP3UIPROC) (GLenum type, GLuint coords);
+typedef void (APIENTRYP PFNGLNORMALP3UIVPROC) (GLenum type, const GLuint *coords);
+typedef void (APIENTRYP PFNGLCOLORP3UIPROC) (GLenum type, GLuint color);
+typedef void (APIENTRYP PFNGLCOLORP3UIVPROC) (GLenum type, const GLuint *color);
+typedef void (APIENTRYP PFNGLCOLORP4UIPROC) (GLenum type, GLuint color);
+typedef void (APIENTRYP PFNGLCOLORP4UIVPROC) (GLenum type, const GLuint *color);
+typedef void (APIENTRYP PFNGLSECONDARYCOLORP3UIPROC) (GLenum type, GLuint color);
+typedef void (APIENTRYP PFNGLSECONDARYCOLORP3UIVPROC) (GLenum type, const GLuint *color);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBP1UIPROC) (GLuint index, GLenum type, GLboolean normalized, GLuint value);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBP1UIVPROC) (GLuint index, GLenum type, GLboolean normalized, const GLuint *value);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBP2UIPROC) (GLuint index, GLenum type, GLboolean normalized, GLuint value);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBP2UIVPROC) (GLuint index, GLenum type, GLboolean normalized, const GLuint *value);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBP3UIPROC) (GLuint index, GLenum type, GLboolean normalized, GLuint value);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBP3UIVPROC) (GLuint index, GLenum type, GLboolean normalized, const GLuint *value);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBP4UIPROC) (GLuint index, GLenum type, GLboolean normalized, GLuint value);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBP4UIVPROC) (GLuint index, GLenum type, GLboolean normalized, const GLuint *value);
+#endif
+
+#ifndef GL_ARB_draw_indirect
+#define GL_ARB_draw_indirect 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glDrawArraysIndirect (GLenum mode, const GLvoid *indirect);
+GLAPI void APIENTRY glDrawElementsIndirect (GLenum mode, GLenum type, const GLvoid *indirect);
+#endif
+typedef void (APIENTRYP PFNGLDRAWARRAYSINDIRECTPROC) (GLenum mode, const GLvoid *indirect);
+typedef void (APIENTRYP PFNGLDRAWELEMENTSINDIRECTPROC) (GLenum mode, GLenum type, const GLvoid *indirect);
+#endif
+
+#ifndef GL_ARB_gpu_shader5
+#define GL_ARB_gpu_shader5 1
+#endif
+
+#ifndef GL_ARB_gpu_shader_fp64
+#define GL_ARB_gpu_shader_fp64 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glUniform1d (GLint location, GLdouble x);
+GLAPI void APIENTRY glUniform2d (GLint location, GLdouble x, GLdouble y);
+GLAPI void APIENTRY glUniform3d (GLint location, GLdouble x, GLdouble y, GLdouble z);
+GLAPI void APIENTRY glUniform4d (GLint location, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+GLAPI void APIENTRY glUniform1dv (GLint location, GLsizei count, const GLdouble *value);
+GLAPI void APIENTRY glUniform2dv (GLint location, GLsizei count, const GLdouble *value);
+GLAPI void APIENTRY glUniform3dv (GLint location, GLsizei count, const GLdouble *value);
+GLAPI void APIENTRY glUniform4dv (GLint location, GLsizei count, const GLdouble *value);
+GLAPI void APIENTRY glUniformMatrix2dv (GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+GLAPI void APIENTRY glUniformMatrix3dv (GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+GLAPI void APIENTRY glUniformMatrix4dv (GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+GLAPI void APIENTRY glUniformMatrix2x3dv (GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+GLAPI void APIENTRY glUniformMatrix2x4dv (GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+GLAPI void APIENTRY glUniformMatrix3x2dv (GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+GLAPI void APIENTRY glUniformMatrix3x4dv (GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+GLAPI void APIENTRY glUniformMatrix4x2dv (GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+GLAPI void APIENTRY glUniformMatrix4x3dv (GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+GLAPI void APIENTRY glGetUniformdv (GLuint program, GLint location, GLdouble *params);
+#endif
+typedef void (APIENTRYP PFNGLUNIFORM1DPROC) (GLint location, GLdouble x);
+typedef void (APIENTRYP PFNGLUNIFORM2DPROC) (GLint location, GLdouble x, GLdouble y);
+typedef void (APIENTRYP PFNGLUNIFORM3DPROC) (GLint location, GLdouble x, GLdouble y, GLdouble z);
+typedef void (APIENTRYP PFNGLUNIFORM4DPROC) (GLint location, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+typedef void (APIENTRYP PFNGLUNIFORM1DVPROC) (GLint location, GLsizei count, const GLdouble *value);
+typedef void (APIENTRYP PFNGLUNIFORM2DVPROC) (GLint location, GLsizei count, const GLdouble *value);
+typedef void (APIENTRYP PFNGLUNIFORM3DVPROC) (GLint location, GLsizei count, const GLdouble *value);
+typedef void (APIENTRYP PFNGLUNIFORM4DVPROC) (GLint location, GLsizei count, const GLdouble *value);
+typedef void (APIENTRYP PFNGLUNIFORMMATRIX2DVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+typedef void (APIENTRYP PFNGLUNIFORMMATRIX3DVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+typedef void (APIENTRYP PFNGLUNIFORMMATRIX4DVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+typedef void (APIENTRYP PFNGLUNIFORMMATRIX2X3DVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+typedef void (APIENTRYP PFNGLUNIFORMMATRIX2X4DVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+typedef void (APIENTRYP PFNGLUNIFORMMATRIX3X2DVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+typedef void (APIENTRYP PFNGLUNIFORMMATRIX3X4DVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+typedef void (APIENTRYP PFNGLUNIFORMMATRIX4X2DVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+typedef void (APIENTRYP PFNGLUNIFORMMATRIX4X3DVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+typedef void (APIENTRYP PFNGLGETUNIFORMDVPROC) (GLuint program, GLint location, GLdouble *params);
+#endif
+
+#ifndef GL_ARB_shader_subroutine
+#define GL_ARB_shader_subroutine 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI GLint APIENTRY glGetSubroutineUniformLocation (GLuint program, GLenum shadertype, const GLchar *name);
+GLAPI GLuint APIENTRY glGetSubroutineIndex (GLuint program, GLenum shadertype, const GLchar *name);
+GLAPI void APIENTRY glGetActiveSubroutineUniformiv (GLuint program, GLenum shadertype, GLuint index, GLenum pname, GLint *values);
+GLAPI void APIENTRY glGetActiveSubroutineUniformName (GLuint program, GLenum shadertype, GLuint index, GLsizei bufsize, GLsizei *length, GLchar *name);
+GLAPI void APIENTRY glGetActiveSubroutineName (GLuint program, GLenum shadertype, GLuint index, GLsizei bufsize, GLsizei *length, GLchar *name);
+GLAPI void APIENTRY glUniformSubroutinesuiv (GLenum shadertype, GLsizei count, const GLuint *indices);
+GLAPI void APIENTRY glGetUniformSubroutineuiv (GLenum shadertype, GLint location, GLuint *params);
+GLAPI void APIENTRY glGetProgramStageiv (GLuint program, GLenum shadertype, GLenum pname, GLint *values);
+#endif
+typedef GLint (APIENTRYP PFNGLGETSUBROUTINEUNIFORMLOCATIONPROC) (GLuint program, GLenum shadertype, const GLchar *name);
+typedef GLuint (APIENTRYP PFNGLGETSUBROUTINEINDEXPROC) (GLuint program, GLenum shadertype, const GLchar *name);
+typedef void (APIENTRYP PFNGLGETACTIVESUBROUTINEUNIFORMIVPROC) (GLuint program, GLenum shadertype, GLuint index, GLenum pname, GLint *values);
+typedef void (APIENTRYP PFNGLGETACTIVESUBROUTINEUNIFORMNAMEPROC) (GLuint program, GLenum shadertype, GLuint index, GLsizei bufsize, GLsizei *length, GLchar *name);
+typedef void (APIENTRYP PFNGLGETACTIVESUBROUTINENAMEPROC) (GLuint program, GLenum shadertype, GLuint index, GLsizei bufsize, GLsizei *length, GLchar *name);
+typedef void (APIENTRYP PFNGLUNIFORMSUBROUTINESUIVPROC) (GLenum shadertype, GLsizei count, const GLuint *indices);
+typedef void (APIENTRYP PFNGLGETUNIFORMSUBROUTINEUIVPROC) (GLenum shadertype, GLint location, GLuint *params);
+typedef void (APIENTRYP PFNGLGETPROGRAMSTAGEIVPROC) (GLuint program, GLenum shadertype, GLenum pname, GLint *values);
+#endif
+
+#ifndef GL_ARB_tessellation_shader
+#define GL_ARB_tessellation_shader 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glPatchParameteri (GLenum pname, GLint value);
+GLAPI void APIENTRY glPatchParameterfv (GLenum pname, const GLfloat *values);
+#endif
+typedef void (APIENTRYP PFNGLPATCHPARAMETERIPROC) (GLenum pname, GLint value);
+typedef void (APIENTRYP PFNGLPATCHPARAMETERFVPROC) (GLenum pname, const GLfloat *values);
+#endif
+
+#ifndef GL_ARB_texture_buffer_object_rgb32
+#define GL_ARB_texture_buffer_object_rgb32 1
+#endif
+
+#ifndef GL_ARB_transform_feedback2
+#define GL_ARB_transform_feedback2 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glBindTransformFeedback (GLenum target, GLuint id);
+GLAPI void APIENTRY glDeleteTransformFeedbacks (GLsizei n, const GLuint *ids);
+GLAPI void APIENTRY glGenTransformFeedbacks (GLsizei n, GLuint *ids);
+GLAPI GLboolean APIENTRY glIsTransformFeedback (GLuint id);
+GLAPI void APIENTRY glPauseTransformFeedback (void);
+GLAPI void APIENTRY glResumeTransformFeedback (void);
+GLAPI void APIENTRY glDrawTransformFeedback (GLenum mode, GLuint id);
+#endif
+typedef void (APIENTRYP PFNGLBINDTRANSFORMFEEDBACKPROC) (GLenum target, GLuint id);
+typedef void (APIENTRYP PFNGLDELETETRANSFORMFEEDBACKSPROC) (GLsizei n, const GLuint *ids);
+typedef void (APIENTRYP PFNGLGENTRANSFORMFEEDBACKSPROC) (GLsizei n, GLuint *ids);
+typedef GLboolean (APIENTRYP PFNGLISTRANSFORMFEEDBACKPROC) (GLuint id);
+typedef void (APIENTRYP PFNGLPAUSETRANSFORMFEEDBACKPROC) (void);
+typedef void (APIENTRYP PFNGLRESUMETRANSFORMFEEDBACKPROC) (void);
+typedef void (APIENTRYP PFNGLDRAWTRANSFORMFEEDBACKPROC) (GLenum mode, GLuint id);
+#endif
+
+#ifndef GL_ARB_transform_feedback3
+#define GL_ARB_transform_feedback3 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glDrawTransformFeedbackStream (GLenum mode, GLuint id, GLuint stream);
+GLAPI void APIENTRY glBeginQueryIndexed (GLenum target, GLuint index, GLuint id);
+GLAPI void APIENTRY glEndQueryIndexed (GLenum target, GLuint index);
+GLAPI void APIENTRY glGetQueryIndexediv (GLenum target, GLuint index, GLenum pname, GLint *params);
+#endif
+typedef void (APIENTRYP PFNGLDRAWTRANSFORMFEEDBACKSTREAMPROC) (GLenum mode, GLuint id, GLuint stream);
+typedef void (APIENTRYP PFNGLBEGINQUERYINDEXEDPROC) (GLenum target, GLuint index, GLuint id);
+typedef void (APIENTRYP PFNGLENDQUERYINDEXEDPROC) (GLenum target, GLuint index);
+typedef void (APIENTRYP PFNGLGETQUERYINDEXEDIVPROC) (GLenum target, GLuint index, GLenum pname, GLint *params);
+#endif
+
+#ifndef GL_ARB_ES2_compatibility
+#define GL_ARB_ES2_compatibility 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glReleaseShaderCompiler (void);
+GLAPI void APIENTRY glShaderBinary (GLsizei count, const GLuint *shaders, GLenum binaryformat, const GLvoid *binary, GLsizei length);
+GLAPI void APIENTRY glGetShaderPrecisionFormat (GLenum shadertype, GLenum precisiontype, GLint *range, GLint *precision);
+GLAPI void APIENTRY glDepthRangef (GLclampf n, GLclampf f);
+GLAPI void APIENTRY glClearDepthf (GLclampf d);
+#endif
+typedef void (APIENTRYP PFNGLRELEASESHADERCOMPILERPROC) (void);
+typedef void (APIENTRYP PFNGLSHADERBINARYPROC) (GLsizei count, const GLuint *shaders, GLenum binaryformat, const GLvoid *binary, GLsizei length);
+typedef void (APIENTRYP PFNGLGETSHADERPRECISIONFORMATPROC) (GLenum shadertype, GLenum precisiontype, GLint *range, GLint *precision);
+typedef void (APIENTRYP PFNGLDEPTHRANGEFPROC) (GLclampf n, GLclampf f);
+typedef void (APIENTRYP PFNGLCLEARDEPTHFPROC) (GLclampf d);
+#endif
+
+#ifndef GL_ARB_get_program_binary
+#define GL_ARB_get_program_binary 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glGetProgramBinary (GLuint program, GLsizei bufSize, GLsizei *length, GLenum *binaryFormat, GLvoid *binary);
+GLAPI void APIENTRY glProgramBinary (GLuint program, GLenum binaryFormat, const GLvoid *binary, GLsizei length);
+GLAPI void APIENTRY glProgramParameteri (GLuint program, GLenum pname, GLint value);
+#endif
+typedef void (APIENTRYP PFNGLGETPROGRAMBINARYPROC) (GLuint program, GLsizei bufSize, GLsizei *length, GLenum *binaryFormat, GLvoid *binary);
+typedef void (APIENTRYP PFNGLPROGRAMBINARYPROC) (GLuint program, GLenum binaryFormat, const GLvoid *binary, GLsizei length);
+typedef void (APIENTRYP PFNGLPROGRAMPARAMETERIPROC) (GLuint program, GLenum pname, GLint value);
+#endif
+
+#ifndef GL_ARB_separate_shader_objects
+#define GL_ARB_separate_shader_objects 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glUseProgramStages (GLuint pipeline, GLbitfield stages, GLuint program);
+GLAPI void APIENTRY glActiveShaderProgram (GLuint pipeline, GLuint program);
+GLAPI GLuint APIENTRY glCreateShaderProgramv (GLenum type, GLsizei count, const GLchar* *strings);
+GLAPI void APIENTRY glBindProgramPipeline (GLuint pipeline);
+GLAPI void APIENTRY glDeleteProgramPipelines (GLsizei n, const GLuint *pipelines);
+GLAPI void APIENTRY glGenProgramPipelines (GLsizei n, GLuint *pipelines);
+GLAPI GLboolean APIENTRY glIsProgramPipeline (GLuint pipeline);
+GLAPI void APIENTRY glGetProgramPipelineiv (GLuint pipeline, GLenum pname, GLint *params);
+GLAPI void APIENTRY glProgramUniform1i (GLuint program, GLint location, GLint v0);
+GLAPI void APIENTRY glProgramUniform1iv (GLuint program, GLint location, GLsizei count, const GLint *value);
+GLAPI void APIENTRY glProgramUniform1f (GLuint program, GLint location, GLfloat v0);
+GLAPI void APIENTRY glProgramUniform1fv (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+GLAPI void APIENTRY glProgramUniform1d (GLuint program, GLint location, GLdouble v0);
+GLAPI void APIENTRY glProgramUniform1dv (GLuint program, GLint location, GLsizei count, const GLdouble *value);
+GLAPI void APIENTRY glProgramUniform1ui (GLuint program, GLint location, GLuint v0);
+GLAPI void APIENTRY glProgramUniform1uiv (GLuint program, GLint location, GLsizei count, const GLuint *value);
+GLAPI void APIENTRY glProgramUniform2i (GLuint program, GLint location, GLint v0, GLint v1);
+GLAPI void APIENTRY glProgramUniform2iv (GLuint program, GLint location, GLsizei count, const GLint *value);
+GLAPI void APIENTRY glProgramUniform2f (GLuint program, GLint location, GLfloat v0, GLfloat v1);
+GLAPI void APIENTRY glProgramUniform2fv (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+GLAPI void APIENTRY glProgramUniform2d (GLuint program, GLint location, GLdouble v0, GLdouble v1);
+GLAPI void APIENTRY glProgramUniform2dv (GLuint program, GLint location, GLsizei count, const GLdouble *value);
+GLAPI void APIENTRY glProgramUniform2ui (GLuint program, GLint location, GLuint v0, GLuint v1);
+GLAPI void APIENTRY glProgramUniform2uiv (GLuint program, GLint location, GLsizei count, const GLuint *value);
+GLAPI void APIENTRY glProgramUniform3i (GLuint program, GLint location, GLint v0, GLint v1, GLint v2);
+GLAPI void APIENTRY glProgramUniform3iv (GLuint program, GLint location, GLsizei count, const GLint *value);
+GLAPI void APIENTRY glProgramUniform3f (GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2);
+GLAPI void APIENTRY glProgramUniform3fv (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+GLAPI void APIENTRY glProgramUniform3d (GLuint program, GLint location, GLdouble v0, GLdouble v1, GLdouble v2);
+GLAPI void APIENTRY glProgramUniform3dv (GLuint program, GLint location, GLsizei count, const GLdouble *value);
+GLAPI void APIENTRY glProgramUniform3ui (GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2);
+GLAPI void APIENTRY glProgramUniform3uiv (GLuint program, GLint location, GLsizei count, const GLuint *value);
+GLAPI void APIENTRY glProgramUniform4i (GLuint program, GLint location, GLint v0, GLint v1, GLint v2, GLint v3);
+GLAPI void APIENTRY glProgramUniform4iv (GLuint program, GLint location, GLsizei count, const GLint *value);
+GLAPI void APIENTRY glProgramUniform4f (GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
+GLAPI void APIENTRY glProgramUniform4fv (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+GLAPI void APIENTRY glProgramUniform4d (GLuint program, GLint location, GLdouble v0, GLdouble v1, GLdouble v2, GLdouble v3);
+GLAPI void APIENTRY glProgramUniform4dv (GLuint program, GLint location, GLsizei count, const GLdouble *value);
+GLAPI void APIENTRY glProgramUniform4ui (GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3);
+GLAPI void APIENTRY glProgramUniform4uiv (GLuint program, GLint location, GLsizei count, const GLuint *value);
+GLAPI void APIENTRY glProgramUniformMatrix2fv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GLAPI void APIENTRY glProgramUniformMatrix3fv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GLAPI void APIENTRY glProgramUniformMatrix4fv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GLAPI void APIENTRY glProgramUniformMatrix2dv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+GLAPI void APIENTRY glProgramUniformMatrix3dv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+GLAPI void APIENTRY glProgramUniformMatrix4dv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+GLAPI void APIENTRY glProgramUniformMatrix2x3fv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GLAPI void APIENTRY glProgramUniformMatrix3x2fv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GLAPI void APIENTRY glProgramUniformMatrix2x4fv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GLAPI void APIENTRY glProgramUniformMatrix4x2fv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GLAPI void APIENTRY glProgramUniformMatrix3x4fv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GLAPI void APIENTRY glProgramUniformMatrix4x3fv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GLAPI void APIENTRY glProgramUniformMatrix2x3dv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+GLAPI void APIENTRY glProgramUniformMatrix3x2dv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+GLAPI void APIENTRY glProgramUniformMatrix2x4dv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+GLAPI void APIENTRY glProgramUniformMatrix4x2dv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+GLAPI void APIENTRY glProgramUniformMatrix3x4dv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+GLAPI void APIENTRY glProgramUniformMatrix4x3dv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+GLAPI void APIENTRY glValidateProgramPipeline (GLuint pipeline);
+GLAPI void APIENTRY glGetProgramPipelineInfoLog (GLuint pipeline, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
+#endif
+typedef void (APIENTRYP PFNGLUSEPROGRAMSTAGESPROC) (GLuint pipeline, GLbitfield stages, GLuint program);
+typedef void (APIENTRYP PFNGLACTIVESHADERPROGRAMPROC) (GLuint pipeline, GLuint program);
+typedef GLuint (APIENTRYP PFNGLCREATESHADERPROGRAMVPROC) (GLenum type, GLsizei count, const GLchar* *strings);
+typedef void (APIENTRYP PFNGLBINDPROGRAMPIPELINEPROC) (GLuint pipeline);
+typedef void (APIENTRYP PFNGLDELETEPROGRAMPIPELINESPROC) (GLsizei n, const GLuint *pipelines);
+typedef void (APIENTRYP PFNGLGENPROGRAMPIPELINESPROC) (GLsizei n, GLuint *pipelines);
+typedef GLboolean (APIENTRYP PFNGLISPROGRAMPIPELINEPROC) (GLuint pipeline);
+typedef void (APIENTRYP PFNGLGETPROGRAMPIPELINEIVPROC) (GLuint pipeline, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM1IPROC) (GLuint program, GLint location, GLint v0);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM1IVPROC) (GLuint program, GLint location, GLsizei count, const GLint *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM1FPROC) (GLuint program, GLint location, GLfloat v0);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM1FVPROC) (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM1DPROC) (GLuint program, GLint location, GLdouble v0);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM1DVPROC) (GLuint program, GLint location, GLsizei count, const GLdouble *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM1UIPROC) (GLuint program, GLint location, GLuint v0);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM1UIVPROC) (GLuint program, GLint location, GLsizei count, const GLuint *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM2IPROC) (GLuint program, GLint location, GLint v0, GLint v1);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM2IVPROC) (GLuint program, GLint location, GLsizei count, const GLint *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM2FPROC) (GLuint program, GLint location, GLfloat v0, GLfloat v1);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM2FVPROC) (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM2DPROC) (GLuint program, GLint location, GLdouble v0, GLdouble v1);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM2DVPROC) (GLuint program, GLint location, GLsizei count, const GLdouble *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM2UIPROC) (GLuint program, GLint location, GLuint v0, GLuint v1);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM2UIVPROC) (GLuint program, GLint location, GLsizei count, const GLuint *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM3IPROC) (GLuint program, GLint location, GLint v0, GLint v1, GLint v2);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM3IVPROC) (GLuint program, GLint location, GLsizei count, const GLint *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM3FPROC) (GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM3FVPROC) (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM3DPROC) (GLuint program, GLint location, GLdouble v0, GLdouble v1, GLdouble v2);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM3DVPROC) (GLuint program, GLint location, GLsizei count, const GLdouble *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM3UIPROC) (GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM3UIVPROC) (GLuint program, GLint location, GLsizei count, const GLuint *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM4IPROC) (GLuint program, GLint location, GLint v0, GLint v1, GLint v2, GLint v3);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM4IVPROC) (GLuint program, GLint location, GLsizei count, const GLint *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM4FPROC) (GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM4FVPROC) (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM4DPROC) (GLuint program, GLint location, GLdouble v0, GLdouble v1, GLdouble v2, GLdouble v3);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM4DVPROC) (GLuint program, GLint location, GLsizei count, const GLdouble *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM4UIPROC) (GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM4UIVPROC) (GLuint program, GLint location, GLsizei count, const GLuint *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX2FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX3FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX4FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX2DVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX3DVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX4DVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX2X3FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX3X2FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX2X4FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX4X2FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX3X4FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX4X3FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX2X3DVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX3X2DVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX2X4DVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX4X2DVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX3X4DVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX4X3DVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+typedef void (APIENTRYP PFNGLVALIDATEPROGRAMPIPELINEPROC) (GLuint pipeline);
+typedef void (APIENTRYP PFNGLGETPROGRAMPIPELINEINFOLOGPROC) (GLuint pipeline, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
+#endif
+
+#ifndef GL_ARB_vertex_attrib_64bit
+#define GL_ARB_vertex_attrib_64bit 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glVertexAttribL1d (GLuint index, GLdouble x);
+GLAPI void APIENTRY glVertexAttribL2d (GLuint index, GLdouble x, GLdouble y);
+GLAPI void APIENTRY glVertexAttribL3d (GLuint index, GLdouble x, GLdouble y, GLdouble z);
+GLAPI void APIENTRY glVertexAttribL4d (GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+GLAPI void APIENTRY glVertexAttribL1dv (GLuint index, const GLdouble *v);
+GLAPI void APIENTRY glVertexAttribL2dv (GLuint index, const GLdouble *v);
+GLAPI void APIENTRY glVertexAttribL3dv (GLuint index, const GLdouble *v);
+GLAPI void APIENTRY glVertexAttribL4dv (GLuint index, const GLdouble *v);
+GLAPI void APIENTRY glVertexAttribLPointer (GLuint index, GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);
+GLAPI void APIENTRY glGetVertexAttribLdv (GLuint index, GLenum pname, GLdouble *params);
+#endif
+typedef void (APIENTRYP PFNGLVERTEXATTRIBL1DPROC) (GLuint index, GLdouble x);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBL2DPROC) (GLuint index, GLdouble x, GLdouble y);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBL3DPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBL4DPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBL1DVPROC) (GLuint index, const GLdouble *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBL2DVPROC) (GLuint index, const GLdouble *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBL3DVPROC) (GLuint index, const GLdouble *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBL4DVPROC) (GLuint index, const GLdouble *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBLPOINTERPROC) (GLuint index, GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);
+typedef void (APIENTRYP PFNGLGETVERTEXATTRIBLDVPROC) (GLuint index, GLenum pname, GLdouble *params);
+#endif
+
+#ifndef GL_ARB_viewport_array
+#define GL_ARB_viewport_array 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glViewportArrayv (GLuint first, GLsizei count, const GLfloat *v);
+GLAPI void APIENTRY glViewportIndexedf (GLuint index, GLfloat x, GLfloat y, GLfloat w, GLfloat h);
+GLAPI void APIENTRY glViewportIndexedfv (GLuint index, const GLfloat *v);
+GLAPI void APIENTRY glScissorArrayv (GLuint first, GLsizei count, const GLint *v);
+GLAPI void APIENTRY glScissorIndexed (GLuint index, GLint left, GLint bottom, GLsizei width, GLsizei height);
+GLAPI void APIENTRY glScissorIndexedv (GLuint index, const GLint *v);
+GLAPI void APIENTRY glDepthRangeArrayv (GLuint first, GLsizei count, const GLclampd *v);
+GLAPI void APIENTRY glDepthRangeIndexed (GLuint index, GLclampd n, GLclampd f);
+GLAPI void APIENTRY glGetFloati_v (GLenum target, GLuint index, GLfloat *data);
+GLAPI void APIENTRY glGetDoublei_v (GLenum target, GLuint index, GLdouble *data);
+#endif
+typedef void (APIENTRYP PFNGLVIEWPORTARRAYVPROC) (GLuint first, GLsizei count, const GLfloat *v);
+typedef void (APIENTRYP PFNGLVIEWPORTINDEXEDFPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat w, GLfloat h);
+typedef void (APIENTRYP PFNGLVIEWPORTINDEXEDFVPROC) (GLuint index, const GLfloat *v);
+typedef void (APIENTRYP PFNGLSCISSORARRAYVPROC) (GLuint first, GLsizei count, const GLint *v);
+typedef void (APIENTRYP PFNGLSCISSORINDEXEDPROC) (GLuint index, GLint left, GLint bottom, GLsizei width, GLsizei height);
+typedef void (APIENTRYP PFNGLSCISSORINDEXEDVPROC) (GLuint index, const GLint *v);
+typedef void (APIENTRYP PFNGLDEPTHRANGEARRAYVPROC) (GLuint first, GLsizei count, const GLclampd *v);
+typedef void (APIENTRYP PFNGLDEPTHRANGEINDEXEDPROC) (GLuint index, GLclampd n, GLclampd f);
+typedef void (APIENTRYP PFNGLGETFLOATI_VPROC) (GLenum target, GLuint index, GLfloat *data);
+typedef void (APIENTRYP PFNGLGETDOUBLEI_VPROC) (GLenum target, GLuint index, GLdouble *data);
+#endif
+
+#ifndef GL_ARB_cl_event
+#define GL_ARB_cl_event 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI GLsync APIENTRY glCreateSyncFromCLeventARB (struct _cl_context * context, struct _cl_event * event, GLbitfield flags);
+#endif
+typedef GLsync (APIENTRYP PFNGLCREATESYNCFROMCLEVENTARBPROC) (struct _cl_context * context, struct _cl_event * event, GLbitfield flags);
+#endif
+
+#ifndef GL_ARB_debug_output
+#define GL_ARB_debug_output 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glDebugMessageControlARB (GLenum source, GLenum type, GLenum severity, GLsizei count, const GLuint *ids, GLboolean enabled);
+GLAPI void APIENTRY glDebugMessageInsertARB (GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *buf);
+GLAPI void APIENTRY glDebugMessageCallbackARB (GLDEBUGPROCARB callback, const GLvoid *userParam);
+GLAPI GLuint APIENTRY glGetDebugMessageLogARB (GLuint count, GLsizei bufsize, GLenum *sources, GLenum *types, GLuint *ids, GLenum *severities, GLsizei *lengths, GLchar *messageLog);
+#endif
+typedef void (APIENTRYP PFNGLDEBUGMESSAGECONTROLARBPROC) (GLenum source, GLenum type, GLenum severity, GLsizei count, const GLuint *ids, GLboolean enabled);
+typedef void (APIENTRYP PFNGLDEBUGMESSAGEINSERTARBPROC) (GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *buf);
+typedef void (APIENTRYP PFNGLDEBUGMESSAGECALLBACKARBPROC) (GLDEBUGPROCARB callback, const GLvoid *userParam);
+typedef GLuint (APIENTRYP PFNGLGETDEBUGMESSAGELOGARBPROC) (GLuint count, GLsizei bufsize, GLenum *sources, GLenum *types, GLuint *ids, GLenum *severities, GLsizei *lengths, GLchar *messageLog);
+#endif
+
+#ifndef GL_ARB_robustness
+#define GL_ARB_robustness 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI GLenum APIENTRY glGetGraphicsResetStatusARB (void);
+GLAPI void APIENTRY glGetnMapdvARB (GLenum target, GLenum query, GLsizei bufSize, GLdouble *v);
+GLAPI void APIENTRY glGetnMapfvARB (GLenum target, GLenum query, GLsizei bufSize, GLfloat *v);
+GLAPI void APIENTRY glGetnMapivARB (GLenum target, GLenum query, GLsizei bufSize, GLint *v);
+GLAPI void APIENTRY glGetnPixelMapfvARB (GLenum map, GLsizei bufSize, GLfloat *values);
+GLAPI void APIENTRY glGetnPixelMapuivARB (GLenum map, GLsizei bufSize, GLuint *values);
+GLAPI void APIENTRY glGetnPixelMapusvARB (GLenum map, GLsizei bufSize, GLushort *values);
+GLAPI void APIENTRY glGetnPolygonStippleARB (GLsizei bufSize, GLubyte *pattern);
+GLAPI void APIENTRY glGetnColorTableARB (GLenum target, GLenum format, GLenum type, GLsizei bufSize, GLvoid *table);
+GLAPI void APIENTRY glGetnConvolutionFilterARB (GLenum target, GLenum format, GLenum type, GLsizei bufSize, GLvoid *image);
+GLAPI void APIENTRY glGetnSeparableFilterARB (GLenum target, GLenum format, GLenum type, GLsizei rowBufSize, GLvoid *row, GLsizei columnBufSize, GLvoid *column, GLvoid *span);
+GLAPI void APIENTRY glGetnHistogramARB (GLenum target, GLboolean reset, GLenum format, GLenum type, GLsizei bufSize, GLvoid *values);
+GLAPI void APIENTRY glGetnMinmaxARB (GLenum target, GLboolean reset, GLenum format, GLenum type, GLsizei bufSize, GLvoid *values);
+GLAPI void APIENTRY glGetnTexImageARB (GLenum target, GLint level, GLenum format, GLenum type, GLsizei bufSize, GLvoid *img);
+GLAPI void APIENTRY glReadnPixelsARB (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei bufSize, GLvoid *data);
+GLAPI void APIENTRY glGetnCompressedTexImageARB (GLenum target, GLint lod, GLsizei bufSize, GLvoid *img);
+GLAPI void APIENTRY glGetnUniformfvARB (GLuint program, GLint location, GLsizei bufSize, GLfloat *params);
+GLAPI void APIENTRY glGetnUniformivARB (GLuint program, GLint location, GLsizei bufSize, GLint *params);
+GLAPI void APIENTRY glGetnUniformuivARB (GLuint program, GLint location, GLsizei bufSize, GLuint *params);
+GLAPI void APIENTRY glGetnUniformdvARB (GLuint program, GLint location, GLsizei bufSize, GLdouble *params);
+#endif
+typedef GLenum (APIENTRYP PFNGLGETGRAPHICSRESETSTATUSARBPROC) (void);
+typedef void (APIENTRYP PFNGLGETNMAPDVARBPROC) (GLenum target, GLenum query, GLsizei bufSize, GLdouble *v);
+typedef void (APIENTRYP PFNGLGETNMAPFVARBPROC) (GLenum target, GLenum query, GLsizei bufSize, GLfloat *v);
+typedef void (APIENTRYP PFNGLGETNMAPIVARBPROC) (GLenum target, GLenum query, GLsizei bufSize, GLint *v);
+typedef void (APIENTRYP PFNGLGETNPIXELMAPFVARBPROC) (GLenum map, GLsizei bufSize, GLfloat *values);
+typedef void (APIENTRYP PFNGLGETNPIXELMAPUIVARBPROC) (GLenum map, GLsizei bufSize, GLuint *values);
+typedef void (APIENTRYP PFNGLGETNPIXELMAPUSVARBPROC) (GLenum map, GLsizei bufSize, GLushort *values);
+typedef void (APIENTRYP PFNGLGETNPOLYGONSTIPPLEARBPROC) (GLsizei bufSize, GLubyte *pattern);
+typedef void (APIENTRYP PFNGLGETNCOLORTABLEARBPROC) (GLenum target, GLenum format, GLenum type, GLsizei bufSize, GLvoid *table);
+typedef void (APIENTRYP PFNGLGETNCONVOLUTIONFILTERARBPROC) (GLenum target, GLenum format, GLenum type, GLsizei bufSize, GLvoid *image);
+typedef void (APIENTRYP PFNGLGETNSEPARABLEFILTERARBPROC) (GLenum target, GLenum format, GLenum type, GLsizei rowBufSize, GLvoid *row, GLsizei columnBufSize, GLvoid *column, GLvoid *span);
+typedef void (APIENTRYP PFNGLGETNHISTOGRAMARBPROC) (GLenum target, GLboolean reset, GLenum format, GLenum type, GLsizei bufSize, GLvoid *values);
+typedef void (APIENTRYP PFNGLGETNMINMAXARBPROC) (GLenum target, GLboolean reset, GLenum format, GLenum type, GLsizei bufSize, GLvoid *values);
+typedef void (APIENTRYP PFNGLGETNTEXIMAGEARBPROC) (GLenum target, GLint level, GLenum format, GLenum type, GLsizei bufSize, GLvoid *img);
+typedef void (APIENTRYP PFNGLREADNPIXELSARBPROC) (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei bufSize, GLvoid *data);
+typedef void (APIENTRYP PFNGLGETNCOMPRESSEDTEXIMAGEARBPROC) (GLenum target, GLint lod, GLsizei bufSize, GLvoid *img);
+typedef void (APIENTRYP PFNGLGETNUNIFORMFVARBPROC) (GLuint program, GLint location, GLsizei bufSize, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETNUNIFORMIVARBPROC) (GLuint program, GLint location, GLsizei bufSize, GLint *params);
+typedef void (APIENTRYP PFNGLGETNUNIFORMUIVARBPROC) (GLuint program, GLint location, GLsizei bufSize, GLuint *params);
+typedef void (APIENTRYP PFNGLGETNUNIFORMDVARBPROC) (GLuint program, GLint location, GLsizei bufSize, GLdouble *params);
+#endif
+
+#ifndef GL_ARB_shader_stencil_export
+#define GL_ARB_shader_stencil_export 1
+#endif
+
+#ifndef GL_EXT_abgr
+#define GL_EXT_abgr 1
+#endif
+
+#ifndef GL_EXT_blend_color
+#define GL_EXT_blend_color 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glBlendColorEXT (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
+#endif
+typedef void (APIENTRYP PFNGLBLENDCOLOREXTPROC) (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
+#endif
+
+#ifndef GL_EXT_polygon_offset
+#define GL_EXT_polygon_offset 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glPolygonOffsetEXT (GLfloat factor, GLfloat bias);
+#endif
+typedef void (APIENTRYP PFNGLPOLYGONOFFSETEXTPROC) (GLfloat factor, GLfloat bias);
+#endif
+
+#ifndef GL_EXT_texture
+#define GL_EXT_texture 1
+#endif
+
+#ifndef GL_EXT_texture3D
+#define GL_EXT_texture3D 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glTexImage3DEXT (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid *pixels);
+GLAPI void APIENTRY glTexSubImage3DEXT (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid *pixels);
+#endif
+typedef void (APIENTRYP PFNGLTEXIMAGE3DEXTPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid *pixels);
+typedef void (APIENTRYP PFNGLTEXSUBIMAGE3DEXTPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid *pixels);
+#endif
+
+#ifndef GL_SGIS_texture_filter4
+#define GL_SGIS_texture_filter4 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glGetTexFilterFuncSGIS (GLenum target, GLenum filter, GLfloat *weights);
+GLAPI void APIENTRY glTexFilterFuncSGIS (GLenum target, GLenum filter, GLsizei n, const GLfloat *weights);
+#endif
+typedef void (APIENTRYP PFNGLGETTEXFILTERFUNCSGISPROC) (GLenum target, GLenum filter, GLfloat *weights);
+typedef void (APIENTRYP PFNGLTEXFILTERFUNCSGISPROC) (GLenum target, GLenum filter, GLsizei n, const GLfloat *weights);
+#endif
+
+#ifndef GL_EXT_subtexture
+#define GL_EXT_subtexture 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glTexSubImage1DEXT (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const GLvoid *pixels);
+GLAPI void APIENTRY glTexSubImage2DEXT (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels);
+#endif
+typedef void (APIENTRYP PFNGLTEXSUBIMAGE1DEXTPROC) (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const GLvoid *pixels);
+typedef void (APIENTRYP PFNGLTEXSUBIMAGE2DEXTPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels);
+#endif
+
+#ifndef GL_EXT_copy_texture
+#define GL_EXT_copy_texture 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glCopyTexImage1DEXT (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLint border);
+GLAPI void APIENTRY glCopyTexImage2DEXT (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border);
+GLAPI void APIENTRY glCopyTexSubImage1DEXT (GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width);
+GLAPI void APIENTRY glCopyTexSubImage2DEXT (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+GLAPI void APIENTRY glCopyTexSubImage3DEXT (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+#endif
+typedef void (APIENTRYP PFNGLCOPYTEXIMAGE1DEXTPROC) (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLint border);
+typedef void (APIENTRYP PFNGLCOPYTEXIMAGE2DEXTPROC) (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border);
+typedef void (APIENTRYP PFNGLCOPYTEXSUBIMAGE1DEXTPROC) (GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width);
+typedef void (APIENTRYP PFNGLCOPYTEXSUBIMAGE2DEXTPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+typedef void (APIENTRYP PFNGLCOPYTEXSUBIMAGE3DEXTPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+#endif
+
+#ifndef GL_EXT_histogram
+#define GL_EXT_histogram 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glGetHistogramEXT (GLenum target, GLboolean reset, GLenum format, GLenum type, GLvoid *values);
+GLAPI void APIENTRY glGetHistogramParameterfvEXT (GLenum target, GLenum pname, GLfloat *params);
+GLAPI void APIENTRY glGetHistogramParameterivEXT (GLenum target, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetMinmaxEXT (GLenum target, GLboolean reset, GLenum format, GLenum type, GLvoid *values);
+GLAPI void APIENTRY glGetMinmaxParameterfvEXT (GLenum target, GLenum pname, GLfloat *params);
+GLAPI void APIENTRY glGetMinmaxParameterivEXT (GLenum target, GLenum pname, GLint *params);
+GLAPI void APIENTRY glHistogramEXT (GLenum target, GLsizei width, GLenum internalformat, GLboolean sink);
+GLAPI void APIENTRY glMinmaxEXT (GLenum target, GLenum internalformat, GLboolean sink);
+GLAPI void APIENTRY glResetHistogramEXT (GLenum target);
+GLAPI void APIENTRY glResetMinmaxEXT (GLenum target);
+#endif
+typedef void (APIENTRYP PFNGLGETHISTOGRAMEXTPROC) (GLenum target, GLboolean reset, GLenum format, GLenum type, GLvoid *values);
+typedef void (APIENTRYP PFNGLGETHISTOGRAMPARAMETERFVEXTPROC) (GLenum target, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETHISTOGRAMPARAMETERIVEXTPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETMINMAXEXTPROC) (GLenum target, GLboolean reset, GLenum format, GLenum type, GLvoid *values);
+typedef void (APIENTRYP PFNGLGETMINMAXPARAMETERFVEXTPROC) (GLenum target, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETMINMAXPARAMETERIVEXTPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLHISTOGRAMEXTPROC) (GLenum target, GLsizei width, GLenum internalformat, GLboolean sink);
+typedef void (APIENTRYP PFNGLMINMAXEXTPROC) (GLenum target, GLenum internalformat, GLboolean sink);
+typedef void (APIENTRYP PFNGLRESETHISTOGRAMEXTPROC) (GLenum target);
+typedef void (APIENTRYP PFNGLRESETMINMAXEXTPROC) (GLenum target);
+#endif
+
+#ifndef GL_EXT_convolution
+#define GL_EXT_convolution 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glConvolutionFilter1DEXT (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const GLvoid *image);
+GLAPI void APIENTRY glConvolutionFilter2DEXT (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *image);
+GLAPI void APIENTRY glConvolutionParameterfEXT (GLenum target, GLenum pname, GLfloat params);
+GLAPI void APIENTRY glConvolutionParameterfvEXT (GLenum target, GLenum pname, const GLfloat *params);
+GLAPI void APIENTRY glConvolutionParameteriEXT (GLenum target, GLenum pname, GLint params);
+GLAPI void APIENTRY glConvolutionParameterivEXT (GLenum target, GLenum pname, const GLint *params);
+GLAPI void APIENTRY glCopyConvolutionFilter1DEXT (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width);
+GLAPI void APIENTRY glCopyConvolutionFilter2DEXT (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height);
+GLAPI void APIENTRY glGetConvolutionFilterEXT (GLenum target, GLenum format, GLenum type, GLvoid *image);
+GLAPI void APIENTRY glGetConvolutionParameterfvEXT (GLenum target, GLenum pname, GLfloat *params);
+GLAPI void APIENTRY glGetConvolutionParameterivEXT (GLenum target, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetSeparableFilterEXT (GLenum target, GLenum format, GLenum type, GLvoid *row, GLvoid *column, GLvoid *span);
+GLAPI void APIENTRY glSeparableFilter2DEXT (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *row, const GLvoid *column);
+#endif
+typedef void (APIENTRYP PFNGLCONVOLUTIONFILTER1DEXTPROC) (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const GLvoid *image);
+typedef void (APIENTRYP PFNGLCONVOLUTIONFILTER2DEXTPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *image);
+typedef void (APIENTRYP PFNGLCONVOLUTIONPARAMETERFEXTPROC) (GLenum target, GLenum pname, GLfloat params);
+typedef void (APIENTRYP PFNGLCONVOLUTIONPARAMETERFVEXTPROC) (GLenum target, GLenum pname, const GLfloat *params);
+typedef void (APIENTRYP PFNGLCONVOLUTIONPARAMETERIEXTPROC) (GLenum target, GLenum pname, GLint params);
+typedef void (APIENTRYP PFNGLCONVOLUTIONPARAMETERIVEXTPROC) (GLenum target, GLenum pname, const GLint *params);
+typedef void (APIENTRYP PFNGLCOPYCONVOLUTIONFILTER1DEXTPROC) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width);
+typedef void (APIENTRYP PFNGLCOPYCONVOLUTIONFILTER2DEXTPROC) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height);
+typedef void (APIENTRYP PFNGLGETCONVOLUTIONFILTEREXTPROC) (GLenum target, GLenum format, GLenum type, GLvoid *image);
+typedef void (APIENTRYP PFNGLGETCONVOLUTIONPARAMETERFVEXTPROC) (GLenum target, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETCONVOLUTIONPARAMETERIVEXTPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETSEPARABLEFILTEREXTPROC) (GLenum target, GLenum format, GLenum type, GLvoid *row, GLvoid *column, GLvoid *span);
+typedef void (APIENTRYP PFNGLSEPARABLEFILTER2DEXTPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *row, const GLvoid *column);
+#endif
+
+#ifndef GL_SGI_color_matrix
+#define GL_SGI_color_matrix 1
+#endif
+
+#ifndef GL_SGI_color_table
+#define GL_SGI_color_table 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glColorTableSGI (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const GLvoid *table);
+GLAPI void APIENTRY glColorTableParameterfvSGI (GLenum target, GLenum pname, const GLfloat *params);
+GLAPI void APIENTRY glColorTableParameterivSGI (GLenum target, GLenum pname, const GLint *params);
+GLAPI void APIENTRY glCopyColorTableSGI (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width);
+GLAPI void APIENTRY glGetColorTableSGI (GLenum target, GLenum format, GLenum type, GLvoid *table);
+GLAPI void APIENTRY glGetColorTableParameterfvSGI (GLenum target, GLenum pname, GLfloat *params);
+GLAPI void APIENTRY glGetColorTableParameterivSGI (GLenum target, GLenum pname, GLint *params);
+#endif
+typedef void (APIENTRYP PFNGLCOLORTABLESGIPROC) (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const GLvoid *table);
+typedef void (APIENTRYP PFNGLCOLORTABLEPARAMETERFVSGIPROC) (GLenum target, GLenum pname, const GLfloat *params);
+typedef void (APIENTRYP PFNGLCOLORTABLEPARAMETERIVSGIPROC) (GLenum target, GLenum pname, const GLint *params);
+typedef void (APIENTRYP PFNGLCOPYCOLORTABLESGIPROC) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width);
+typedef void (APIENTRYP PFNGLGETCOLORTABLESGIPROC) (GLenum target, GLenum format, GLenum type, GLvoid *table);
+typedef void (APIENTRYP PFNGLGETCOLORTABLEPARAMETERFVSGIPROC) (GLenum target, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETCOLORTABLEPARAMETERIVSGIPROC) (GLenum target, GLenum pname, GLint *params);
+#endif
+
+#ifndef GL_SGIX_pixel_texture
+#define GL_SGIX_pixel_texture 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glPixelTexGenSGIX (GLenum mode);
+#endif
+typedef void (APIENTRYP PFNGLPIXELTEXGENSGIXPROC) (GLenum mode);
+#endif
+
+#ifndef GL_SGIS_pixel_texture
+#define GL_SGIS_pixel_texture 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glPixelTexGenParameteriSGIS (GLenum pname, GLint param);
+GLAPI void APIENTRY glPixelTexGenParameterivSGIS (GLenum pname, const GLint *params);
+GLAPI void APIENTRY glPixelTexGenParameterfSGIS (GLenum pname, GLfloat param);
+GLAPI void APIENTRY glPixelTexGenParameterfvSGIS (GLenum pname, const GLfloat *params);
+GLAPI void APIENTRY glGetPixelTexGenParameterivSGIS (GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetPixelTexGenParameterfvSGIS (GLenum pname, GLfloat *params);
+#endif
+typedef void (APIENTRYP PFNGLPIXELTEXGENPARAMETERISGISPROC) (GLenum pname, GLint param);
+typedef void (APIENTRYP PFNGLPIXELTEXGENPARAMETERIVSGISPROC) (GLenum pname, const GLint *params);
+typedef void (APIENTRYP PFNGLPIXELTEXGENPARAMETERFSGISPROC) (GLenum pname, GLfloat param);
+typedef void (APIENTRYP PFNGLPIXELTEXGENPARAMETERFVSGISPROC) (GLenum pname, const GLfloat *params);
+typedef void (APIENTRYP PFNGLGETPIXELTEXGENPARAMETERIVSGISPROC) (GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETPIXELTEXGENPARAMETERFVSGISPROC) (GLenum pname, GLfloat *params);
+#endif
+
+#ifndef GL_SGIS_texture4D
+#define GL_SGIS_texture4D 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glTexImage4DSGIS (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLsizei size4d, GLint border, GLenum format, GLenum type, const GLvoid *pixels);
+GLAPI void APIENTRY glTexSubImage4DSGIS (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint woffset, GLsizei width, GLsizei height, GLsizei depth, GLsizei size4d, GLenum format, GLenum type, const GLvoid *pixels);
+#endif
+typedef void (APIENTRYP PFNGLTEXIMAGE4DSGISPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLsizei size4d, GLint border, GLenum format, GLenum type, const GLvoid *pixels);
+typedef void (APIENTRYP PFNGLTEXSUBIMAGE4DSGISPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint woffset, GLsizei width, GLsizei height, GLsizei depth, GLsizei size4d, GLenum format, GLenum type, const GLvoid *pixels);
+#endif
+
+#ifndef GL_SGI_texture_color_table
+#define GL_SGI_texture_color_table 1
+#endif
+
+#ifndef GL_EXT_cmyka
+#define GL_EXT_cmyka 1
+#endif
+
+#ifndef GL_EXT_texture_object
+#define GL_EXT_texture_object 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI GLboolean APIENTRY glAreTexturesResidentEXT (GLsizei n, const GLuint *textures, GLboolean *residences);
+GLAPI void APIENTRY glBindTextureEXT (GLenum target, GLuint texture);
+GLAPI void APIENTRY glDeleteTexturesEXT (GLsizei n, const GLuint *textures);
+GLAPI void APIENTRY glGenTexturesEXT (GLsizei n, GLuint *textures);
+GLAPI GLboolean APIENTRY glIsTextureEXT (GLuint texture);
+GLAPI void APIENTRY glPrioritizeTexturesEXT (GLsizei n, const GLuint *textures, const GLclampf *priorities);
+#endif
+typedef GLboolean (APIENTRYP PFNGLARETEXTURESRESIDENTEXTPROC) (GLsizei n, const GLuint *textures, GLboolean *residences);
+typedef void (APIENTRYP PFNGLBINDTEXTUREEXTPROC) (GLenum target, GLuint texture);
+typedef void (APIENTRYP PFNGLDELETETEXTURESEXTPROC) (GLsizei n, const GLuint *textures);
+typedef void (APIENTRYP PFNGLGENTEXTURESEXTPROC) (GLsizei n, GLuint *textures);
+typedef GLboolean (APIENTRYP PFNGLISTEXTUREEXTPROC) (GLuint texture);
+typedef void (APIENTRYP PFNGLPRIORITIZETEXTURESEXTPROC) (GLsizei n, const GLuint *textures, const GLclampf *priorities);
+#endif
+
+#ifndef GL_SGIS_detail_texture
+#define GL_SGIS_detail_texture 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glDetailTexFuncSGIS (GLenum target, GLsizei n, const GLfloat *points);
+GLAPI void APIENTRY glGetDetailTexFuncSGIS (GLenum target, GLfloat *points);
+#endif
+typedef void (APIENTRYP PFNGLDETAILTEXFUNCSGISPROC) (GLenum target, GLsizei n, const GLfloat *points);
+typedef void (APIENTRYP PFNGLGETDETAILTEXFUNCSGISPROC) (GLenum target, GLfloat *points);
+#endif
+
+#ifndef GL_SGIS_sharpen_texture
+#define GL_SGIS_sharpen_texture 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glSharpenTexFuncSGIS (GLenum target, GLsizei n, const GLfloat *points);
+GLAPI void APIENTRY glGetSharpenTexFuncSGIS (GLenum target, GLfloat *points);
+#endif
+typedef void (APIENTRYP PFNGLSHARPENTEXFUNCSGISPROC) (GLenum target, GLsizei n, const GLfloat *points);
+typedef void (APIENTRYP PFNGLGETSHARPENTEXFUNCSGISPROC) (GLenum target, GLfloat *points);
+#endif
+
+#ifndef GL_EXT_packed_pixels
+#define GL_EXT_packed_pixels 1
+#endif
+
+#ifndef GL_SGIS_texture_lod
+#define GL_SGIS_texture_lod 1
+#endif
+
+#ifndef GL_SGIS_multisample
+#define GL_SGIS_multisample 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glSampleMaskSGIS (GLclampf value, GLboolean invert);
+GLAPI void APIENTRY glSamplePatternSGIS (GLenum pattern);
+#endif
+typedef void (APIENTRYP PFNGLSAMPLEMASKSGISPROC) (GLclampf value, GLboolean invert);
+typedef void (APIENTRYP PFNGLSAMPLEPATTERNSGISPROC) (GLenum pattern);
+#endif
+
+#ifndef GL_EXT_rescale_normal
+#define GL_EXT_rescale_normal 1
+#endif
+
+#ifndef GL_EXT_vertex_array
+#define GL_EXT_vertex_array 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glArrayElementEXT (GLint i);
+GLAPI void APIENTRY glColorPointerEXT (GLint size, GLenum type, GLsizei stride, GLsizei count, const GLvoid *pointer);
+GLAPI void APIENTRY glDrawArraysEXT (GLenum mode, GLint first, GLsizei count);
+GLAPI void APIENTRY glEdgeFlagPointerEXT (GLsizei stride, GLsizei count, const GLboolean *pointer);
+GLAPI void APIENTRY glGetPointervEXT (GLenum pname, GLvoid* *params);
+GLAPI void APIENTRY glIndexPointerEXT (GLenum type, GLsizei stride, GLsizei count, const GLvoid *pointer);
+GLAPI void APIENTRY glNormalPointerEXT (GLenum type, GLsizei stride, GLsizei count, const GLvoid *pointer);
+GLAPI void APIENTRY glTexCoordPointerEXT (GLint size, GLenum type, GLsizei stride, GLsizei count, const GLvoid *pointer);
+GLAPI void APIENTRY glVertexPointerEXT (GLint size, GLenum type, GLsizei stride, GLsizei count, const GLvoid *pointer);
+#endif
+typedef void (APIENTRYP PFNGLARRAYELEMENTEXTPROC) (GLint i);
+typedef void (APIENTRYP PFNGLCOLORPOINTEREXTPROC) (GLint size, GLenum type, GLsizei stride, GLsizei count, const GLvoid *pointer);
+typedef void (APIENTRYP PFNGLDRAWARRAYSEXTPROC) (GLenum mode, GLint first, GLsizei count);
+typedef void (APIENTRYP PFNGLEDGEFLAGPOINTEREXTPROC) (GLsizei stride, GLsizei count, const GLboolean *pointer);
+typedef void (APIENTRYP PFNGLGETPOINTERVEXTPROC) (GLenum pname, GLvoid* *params);
+typedef void (APIENTRYP PFNGLINDEXPOINTEREXTPROC) (GLenum type, GLsizei stride, GLsizei count, const GLvoid *pointer);
+typedef void (APIENTRYP PFNGLNORMALPOINTEREXTPROC) (GLenum type, GLsizei stride, GLsizei count, const GLvoid *pointer);
+typedef void (APIENTRYP PFNGLTEXCOORDPOINTEREXTPROC) (GLint size, GLenum type, GLsizei stride, GLsizei count, const GLvoid *pointer);
+typedef void (APIENTRYP PFNGLVERTEXPOINTEREXTPROC) (GLint size, GLenum type, GLsizei stride, GLsizei count, const GLvoid *pointer);
+#endif
+
+#ifndef GL_EXT_misc_attribute
+#define GL_EXT_misc_attribute 1
+#endif
+
+#ifndef GL_SGIS_generate_mipmap
+#define GL_SGIS_generate_mipmap 1
+#endif
+
+#ifndef GL_SGIX_clipmap
+#define GL_SGIX_clipmap 1
+#endif
+
+#ifndef GL_SGIX_shadow
+#define GL_SGIX_shadow 1
+#endif
+
+#ifndef GL_SGIS_texture_edge_clamp
+#define GL_SGIS_texture_edge_clamp 1
+#endif
+
+#ifndef GL_SGIS_texture_border_clamp
+#define GL_SGIS_texture_border_clamp 1
+#endif
+
+#ifndef GL_EXT_blend_minmax
+#define GL_EXT_blend_minmax 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glBlendEquationEXT (GLenum mode);
+#endif
+typedef void (APIENTRYP PFNGLBLENDEQUATIONEXTPROC) (GLenum mode);
+#endif
+
+#ifndef GL_EXT_blend_subtract
+#define GL_EXT_blend_subtract 1
+#endif
+
+#ifndef GL_EXT_blend_logic_op
+#define GL_EXT_blend_logic_op 1
+#endif
+
+#ifndef GL_SGIX_interlace
+#define GL_SGIX_interlace 1
+#endif
+
+#ifndef GL_SGIX_pixel_tiles
+#define GL_SGIX_pixel_tiles 1
+#endif
+
+#ifndef GL_SGIX_texture_select
+#define GL_SGIX_texture_select 1
+#endif
+
+#ifndef GL_SGIX_sprite
+#define GL_SGIX_sprite 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glSpriteParameterfSGIX (GLenum pname, GLfloat param);
+GLAPI void APIENTRY glSpriteParameterfvSGIX (GLenum pname, const GLfloat *params);
+GLAPI void APIENTRY glSpriteParameteriSGIX (GLenum pname, GLint param);
+GLAPI void APIENTRY glSpriteParameterivSGIX (GLenum pname, const GLint *params);
+#endif
+typedef void (APIENTRYP PFNGLSPRITEPARAMETERFSGIXPROC) (GLenum pname, GLfloat param);
+typedef void (APIENTRYP PFNGLSPRITEPARAMETERFVSGIXPROC) (GLenum pname, const GLfloat *params);
+typedef void (APIENTRYP PFNGLSPRITEPARAMETERISGIXPROC) (GLenum pname, GLint param);
+typedef void (APIENTRYP PFNGLSPRITEPARAMETERIVSGIXPROC) (GLenum pname, const GLint *params);
+#endif
+
+#ifndef GL_SGIX_texture_multi_buffer
+#define GL_SGIX_texture_multi_buffer 1
+#endif
+
+#ifndef GL_EXT_point_parameters
+#define GL_EXT_point_parameters 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glPointParameterfEXT (GLenum pname, GLfloat param);
+GLAPI void APIENTRY glPointParameterfvEXT (GLenum pname, const GLfloat *params);
+#endif
+typedef void (APIENTRYP PFNGLPOINTPARAMETERFEXTPROC) (GLenum pname, GLfloat param);
+typedef void (APIENTRYP PFNGLPOINTPARAMETERFVEXTPROC) (GLenum pname, const GLfloat *params);
+#endif
+
+#ifndef GL_SGIS_point_parameters
+#define GL_SGIS_point_parameters 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glPointParameterfSGIS (GLenum pname, GLfloat param);
+GLAPI void APIENTRY glPointParameterfvSGIS (GLenum pname, const GLfloat *params);
+#endif
+typedef void (APIENTRYP PFNGLPOINTPARAMETERFSGISPROC) (GLenum pname, GLfloat param);
+typedef void (APIENTRYP PFNGLPOINTPARAMETERFVSGISPROC) (GLenum pname, const GLfloat *params);
+#endif
+
+#ifndef GL_SGIX_instruments
+#define GL_SGIX_instruments 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI GLint APIENTRY glGetInstrumentsSGIX (void);
+GLAPI void APIENTRY glInstrumentsBufferSGIX (GLsizei size, GLint *buffer);
+GLAPI GLint APIENTRY glPollInstrumentsSGIX (GLint *marker_p);
+GLAPI void APIENTRY glReadInstrumentsSGIX (GLint marker);
+GLAPI void APIENTRY glStartInstrumentsSGIX (void);
+GLAPI void APIENTRY glStopInstrumentsSGIX (GLint marker);
+#endif
+typedef GLint (APIENTRYP PFNGLGETINSTRUMENTSSGIXPROC) (void);
+typedef void (APIENTRYP PFNGLINSTRUMENTSBUFFERSGIXPROC) (GLsizei size, GLint *buffer);
+typedef GLint (APIENTRYP PFNGLPOLLINSTRUMENTSSGIXPROC) (GLint *marker_p);
+typedef void (APIENTRYP PFNGLREADINSTRUMENTSSGIXPROC) (GLint marker);
+typedef void (APIENTRYP PFNGLSTARTINSTRUMENTSSGIXPROC) (void);
+typedef void (APIENTRYP PFNGLSTOPINSTRUMENTSSGIXPROC) (GLint marker);
+#endif
+
+#ifndef GL_SGIX_texture_scale_bias
+#define GL_SGIX_texture_scale_bias 1
+#endif
+
+#ifndef GL_SGIX_framezoom
+#define GL_SGIX_framezoom 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glFrameZoomSGIX (GLint factor);
+#endif
+typedef void (APIENTRYP PFNGLFRAMEZOOMSGIXPROC) (GLint factor);
+#endif
+
+#ifndef GL_SGIX_tag_sample_buffer
+#define GL_SGIX_tag_sample_buffer 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glTagSampleBufferSGIX (void);
+#endif
+typedef void (APIENTRYP PFNGLTAGSAMPLEBUFFERSGIXPROC) (void);
+#endif
+
+#ifndef GL_SGIX_polynomial_ffd
+#define GL_SGIX_polynomial_ffd 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glDeformationMap3dSGIX (GLenum target, GLdouble u1, GLdouble u2, GLint ustride, GLint uorder, GLdouble v1, GLdouble v2, GLint vstride, GLint vorder, GLdouble w1, GLdouble w2, GLint wstride, GLint worder, const GLdouble *points);
+GLAPI void APIENTRY glDeformationMap3fSGIX (GLenum target, GLfloat u1, GLfloat u2, GLint ustride, GLint uorder, GLfloat v1, GLfloat v2, GLint vstride, GLint vorder, GLfloat w1, GLfloat w2, GLint wstride, GLint worder, const GLfloat *points);
+GLAPI void APIENTRY glDeformSGIX (GLbitfield mask);
+GLAPI void APIENTRY glLoadIdentityDeformationMapSGIX (GLbitfield mask);
+#endif
+typedef void (APIENTRYP PFNGLDEFORMATIONMAP3DSGIXPROC) (GLenum target, GLdouble u1, GLdouble u2, GLint ustride, GLint uorder, GLdouble v1, GLdouble v2, GLint vstride, GLint vorder, GLdouble w1, GLdouble w2, GLint wstride, GLint worder, const GLdouble *points);
+typedef void (APIENTRYP PFNGLDEFORMATIONMAP3FSGIXPROC) (GLenum target, GLfloat u1, GLfloat u2, GLint ustride, GLint uorder, GLfloat v1, GLfloat v2, GLint vstride, GLint vorder, GLfloat w1, GLfloat w2, GLint wstride, GLint worder, const GLfloat *points);
+typedef void (APIENTRYP PFNGLDEFORMSGIXPROC) (GLbitfield mask);
+typedef void (APIENTRYP PFNGLLOADIDENTITYDEFORMATIONMAPSGIXPROC) (GLbitfield mask);
+#endif
+
+#ifndef GL_SGIX_reference_plane
+#define GL_SGIX_reference_plane 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glReferencePlaneSGIX (const GLdouble *equation);
+#endif
+typedef void (APIENTRYP PFNGLREFERENCEPLANESGIXPROC) (const GLdouble *equation);
+#endif
+
+#ifndef GL_SGIX_flush_raster
+#define GL_SGIX_flush_raster 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glFlushRasterSGIX (void);
+#endif
+typedef void (APIENTRYP PFNGLFLUSHRASTERSGIXPROC) (void);
+#endif
+
+#ifndef GL_SGIX_depth_texture
+#define GL_SGIX_depth_texture 1
+#endif
+
+#ifndef GL_SGIS_fog_function
+#define GL_SGIS_fog_function 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glFogFuncSGIS (GLsizei n, const GLfloat *points);
+GLAPI void APIENTRY glGetFogFuncSGIS (GLfloat *points);
+#endif
+typedef void (APIENTRYP PFNGLFOGFUNCSGISPROC) (GLsizei n, const GLfloat *points);
+typedef void (APIENTRYP PFNGLGETFOGFUNCSGISPROC) (GLfloat *points);
+#endif
+
+#ifndef GL_SGIX_fog_offset
+#define GL_SGIX_fog_offset 1
+#endif
+
+#ifndef GL_HP_image_transform
+#define GL_HP_image_transform 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glImageTransformParameteriHP (GLenum target, GLenum pname, GLint param);
+GLAPI void APIENTRY glImageTransformParameterfHP (GLenum target, GLenum pname, GLfloat param);
+GLAPI void APIENTRY glImageTransformParameterivHP (GLenum target, GLenum pname, const GLint *params);
+GLAPI void APIENTRY glImageTransformParameterfvHP (GLenum target, GLenum pname, const GLfloat *params);
+GLAPI void APIENTRY glGetImageTransformParameterivHP (GLenum target, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetImageTransformParameterfvHP (GLenum target, GLenum pname, GLfloat *params);
+#endif
+typedef void (APIENTRYP PFNGLIMAGETRANSFORMPARAMETERIHPPROC) (GLenum target, GLenum pname, GLint param);
+typedef void (APIENTRYP PFNGLIMAGETRANSFORMPARAMETERFHPPROC) (GLenum target, GLenum pname, GLfloat param);
+typedef void (APIENTRYP PFNGLIMAGETRANSFORMPARAMETERIVHPPROC) (GLenum target, GLenum pname, const GLint *params);
+typedef void (APIENTRYP PFNGLIMAGETRANSFORMPARAMETERFVHPPROC) (GLenum target, GLenum pname, const GLfloat *params);
+typedef void (APIENTRYP PFNGLGETIMAGETRANSFORMPARAMETERIVHPPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETIMAGETRANSFORMPARAMETERFVHPPROC) (GLenum target, GLenum pname, GLfloat *params);
+#endif
+
+#ifndef GL_HP_convolution_border_modes
+#define GL_HP_convolution_border_modes 1
+#endif
+
+#ifndef GL_SGIX_texture_add_env
+#define GL_SGIX_texture_add_env 1
+#endif
+
+#ifndef GL_EXT_color_subtable
+#define GL_EXT_color_subtable 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glColorSubTableEXT (GLenum target, GLsizei start, GLsizei count, GLenum format, GLenum type, const GLvoid *data);
+GLAPI void APIENTRY glCopyColorSubTableEXT (GLenum target, GLsizei start, GLint x, GLint y, GLsizei width);
+#endif
+typedef void (APIENTRYP PFNGLCOLORSUBTABLEEXTPROC) (GLenum target, GLsizei start, GLsizei count, GLenum format, GLenum type, const GLvoid *data);
+typedef void (APIENTRYP PFNGLCOPYCOLORSUBTABLEEXTPROC) (GLenum target, GLsizei start, GLint x, GLint y, GLsizei width);
+#endif
+
+#ifndef GL_PGI_vertex_hints
+#define GL_PGI_vertex_hints 1
+#endif
+
+#ifndef GL_PGI_misc_hints
+#define GL_PGI_misc_hints 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glHintPGI (GLenum target, GLint mode);
+#endif
+typedef void (APIENTRYP PFNGLHINTPGIPROC) (GLenum target, GLint mode);
+#endif
+
+#ifndef GL_EXT_paletted_texture
+#define GL_EXT_paletted_texture 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glColorTableEXT (GLenum target, GLenum internalFormat, GLsizei width, GLenum format, GLenum type, const GLvoid *table);
+GLAPI void APIENTRY glGetColorTableEXT (GLenum target, GLenum format, GLenum type, GLvoid *data);
+GLAPI void APIENTRY glGetColorTableParameterivEXT (GLenum target, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetColorTableParameterfvEXT (GLenum target, GLenum pname, GLfloat *params);
+#endif
+typedef void (APIENTRYP PFNGLCOLORTABLEEXTPROC) (GLenum target, GLenum internalFormat, GLsizei width, GLenum format, GLenum type, const GLvoid *table);
+typedef void (APIENTRYP PFNGLGETCOLORTABLEEXTPROC) (GLenum target, GLenum format, GLenum type, GLvoid *data);
+typedef void (APIENTRYP PFNGLGETCOLORTABLEPARAMETERIVEXTPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETCOLORTABLEPARAMETERFVEXTPROC) (GLenum target, GLenum pname, GLfloat *params);
+#endif
+
+#ifndef GL_EXT_clip_volume_hint
+#define GL_EXT_clip_volume_hint 1
+#endif
+
+#ifndef GL_SGIX_list_priority
+#define GL_SGIX_list_priority 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glGetListParameterfvSGIX (GLuint list, GLenum pname, GLfloat *params);
+GLAPI void APIENTRY glGetListParameterivSGIX (GLuint list, GLenum pname, GLint *params);
+GLAPI void APIENTRY glListParameterfSGIX (GLuint list, GLenum pname, GLfloat param);
+GLAPI void APIENTRY glListParameterfvSGIX (GLuint list, GLenum pname, const GLfloat *params);
+GLAPI void APIENTRY glListParameteriSGIX (GLuint list, GLenum pname, GLint param);
+GLAPI void APIENTRY glListParameterivSGIX (GLuint list, GLenum pname, const GLint *params);
+#endif
+typedef void (APIENTRYP PFNGLGETLISTPARAMETERFVSGIXPROC) (GLuint list, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETLISTPARAMETERIVSGIXPROC) (GLuint list, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLLISTPARAMETERFSGIXPROC) (GLuint list, GLenum pname, GLfloat param);
+typedef void (APIENTRYP PFNGLLISTPARAMETERFVSGIXPROC) (GLuint list, GLenum pname, const GLfloat *params);
+typedef void (APIENTRYP PFNGLLISTPARAMETERISGIXPROC) (GLuint list, GLenum pname, GLint param);
+typedef void (APIENTRYP PFNGLLISTPARAMETERIVSGIXPROC) (GLuint list, GLenum pname, const GLint *params);
+#endif
+
+#ifndef GL_SGIX_ir_instrument1
+#define GL_SGIX_ir_instrument1 1
+#endif
+
+#ifndef GL_SGIX_calligraphic_fragment
+#define GL_SGIX_calligraphic_fragment 1
+#endif
+
+#ifndef GL_SGIX_texture_lod_bias
+#define GL_SGIX_texture_lod_bias 1
+#endif
+
+#ifndef GL_SGIX_shadow_ambient
+#define GL_SGIX_shadow_ambient 1
+#endif
+
+#ifndef GL_EXT_index_texture
+#define GL_EXT_index_texture 1
+#endif
+
+#ifndef GL_EXT_index_material
+#define GL_EXT_index_material 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glIndexMaterialEXT (GLenum face, GLenum mode);
+#endif
+typedef void (APIENTRYP PFNGLINDEXMATERIALEXTPROC) (GLenum face, GLenum mode);
+#endif
+
+#ifndef GL_EXT_index_func
+#define GL_EXT_index_func 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glIndexFuncEXT (GLenum func, GLclampf ref);
+#endif
+typedef void (APIENTRYP PFNGLINDEXFUNCEXTPROC) (GLenum func, GLclampf ref);
+#endif
+
+#ifndef GL_EXT_index_array_formats
+#define GL_EXT_index_array_formats 1
+#endif
+
+#ifndef GL_EXT_compiled_vertex_array
+#define GL_EXT_compiled_vertex_array 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glLockArraysEXT (GLint first, GLsizei count);
+GLAPI void APIENTRY glUnlockArraysEXT (void);
+#endif
+typedef void (APIENTRYP PFNGLLOCKARRAYSEXTPROC) (GLint first, GLsizei count);
+typedef void (APIENTRYP PFNGLUNLOCKARRAYSEXTPROC) (void);
+#endif
+
+#ifndef GL_EXT_cull_vertex
+#define GL_EXT_cull_vertex 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glCullParameterdvEXT (GLenum pname, GLdouble *params);
+GLAPI void APIENTRY glCullParameterfvEXT (GLenum pname, GLfloat *params);
+#endif
+typedef void (APIENTRYP PFNGLCULLPARAMETERDVEXTPROC) (GLenum pname, GLdouble *params);
+typedef void (APIENTRYP PFNGLCULLPARAMETERFVEXTPROC) (GLenum pname, GLfloat *params);
+#endif
+
+#ifndef GL_SGIX_ycrcb
+#define GL_SGIX_ycrcb 1
+#endif
+
+#ifndef GL_SGIX_fragment_lighting
+#define GL_SGIX_fragment_lighting 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glFragmentColorMaterialSGIX (GLenum face, GLenum mode);
+GLAPI void APIENTRY glFragmentLightfSGIX (GLenum light, GLenum pname, GLfloat param);
+GLAPI void APIENTRY glFragmentLightfvSGIX (GLenum light, GLenum pname, const GLfloat *params);
+GLAPI void APIENTRY glFragmentLightiSGIX (GLenum light, GLenum pname, GLint param);
+GLAPI void APIENTRY glFragmentLightivSGIX (GLenum light, GLenum pname, const GLint *params);
+GLAPI void APIENTRY glFragmentLightModelfSGIX (GLenum pname, GLfloat param);
+GLAPI void APIENTRY glFragmentLightModelfvSGIX (GLenum pname, const GLfloat *params);
+GLAPI void APIENTRY glFragmentLightModeliSGIX (GLenum pname, GLint param);
+GLAPI void APIENTRY glFragmentLightModelivSGIX (GLenum pname, const GLint *params);
+GLAPI void APIENTRY glFragmentMaterialfSGIX (GLenum face, GLenum pname, GLfloat param);
+GLAPI void APIENTRY glFragmentMaterialfvSGIX (GLenum face, GLenum pname, const GLfloat *params);
+GLAPI void APIENTRY glFragmentMaterialiSGIX (GLenum face, GLenum pname, GLint param);
+GLAPI void APIENTRY glFragmentMaterialivSGIX (GLenum face, GLenum pname, const GLint *params);
+GLAPI void APIENTRY glGetFragmentLightfvSGIX (GLenum light, GLenum pname, GLfloat *params);
+GLAPI void APIENTRY glGetFragmentLightivSGIX (GLenum light, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetFragmentMaterialfvSGIX (GLenum face, GLenum pname, GLfloat *params);
+GLAPI void APIENTRY glGetFragmentMaterialivSGIX (GLenum face, GLenum pname, GLint *params);
+GLAPI void APIENTRY glLightEnviSGIX (GLenum pname, GLint param);
+#endif
+typedef void (APIENTRYP PFNGLFRAGMENTCOLORMATERIALSGIXPROC) (GLenum face, GLenum mode);
+typedef void (APIENTRYP PFNGLFRAGMENTLIGHTFSGIXPROC) (GLenum light, GLenum pname, GLfloat param);
+typedef void (APIENTRYP PFNGLFRAGMENTLIGHTFVSGIXPROC) (GLenum light, GLenum pname, const GLfloat *params);
+typedef void (APIENTRYP PFNGLFRAGMENTLIGHTISGIXPROC) (GLenum light, GLenum pname, GLint param);
+typedef void (APIENTRYP PFNGLFRAGMENTLIGHTIVSGIXPROC) (GLenum light, GLenum pname, const GLint *params);
+typedef void (APIENTRYP PFNGLFRAGMENTLIGHTMODELFSGIXPROC) (GLenum pname, GLfloat param);
+typedef void (APIENTRYP PFNGLFRAGMENTLIGHTMODELFVSGIXPROC) (GLenum pname, const GLfloat *params);
+typedef void (APIENTRYP PFNGLFRAGMENTLIGHTMODELISGIXPROC) (GLenum pname, GLint param);
+typedef void (APIENTRYP PFNGLFRAGMENTLIGHTMODELIVSGIXPROC) (GLenum pname, const GLint *params);
+typedef void (APIENTRYP PFNGLFRAGMENTMATERIALFSGIXPROC) (GLenum face, GLenum pname, GLfloat param);
+typedef void (APIENTRYP PFNGLFRAGMENTMATERIALFVSGIXPROC) (GLenum face, GLenum pname, const GLfloat *params);
+typedef void (APIENTRYP PFNGLFRAGMENTMATERIALISGIXPROC) (GLenum face, GLenum pname, GLint param);
+typedef void (APIENTRYP PFNGLFRAGMENTMATERIALIVSGIXPROC) (GLenum face, GLenum pname, const GLint *params);
+typedef void (APIENTRYP PFNGLGETFRAGMENTLIGHTFVSGIXPROC) (GLenum light, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETFRAGMENTLIGHTIVSGIXPROC) (GLenum light, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETFRAGMENTMATERIALFVSGIXPROC) (GLenum face, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETFRAGMENTMATERIALIVSGIXPROC) (GLenum face, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLLIGHTENVISGIXPROC) (GLenum pname, GLint param);
+#endif
+
+#ifndef GL_IBM_rasterpos_clip
+#define GL_IBM_rasterpos_clip 1
+#endif
+
+#ifndef GL_HP_texture_lighting
+#define GL_HP_texture_lighting 1
+#endif
+
+#ifndef GL_EXT_draw_range_elements
+#define GL_EXT_draw_range_elements 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glDrawRangeElementsEXT (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid *indices);
+#endif
+typedef void (APIENTRYP PFNGLDRAWRANGEELEMENTSEXTPROC) (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid *indices);
+#endif
+
+#ifndef GL_WIN_phong_shading
+#define GL_WIN_phong_shading 1
+#endif
+
+#ifndef GL_WIN_specular_fog
+#define GL_WIN_specular_fog 1
+#endif
+
+#ifndef GL_EXT_light_texture
+#define GL_EXT_light_texture 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glApplyTextureEXT (GLenum mode);
+GLAPI void APIENTRY glTextureLightEXT (GLenum pname);
+GLAPI void APIENTRY glTextureMaterialEXT (GLenum face, GLenum mode);
+#endif
+typedef void (APIENTRYP PFNGLAPPLYTEXTUREEXTPROC) (GLenum mode);
+typedef void (APIENTRYP PFNGLTEXTURELIGHTEXTPROC) (GLenum pname);
+typedef void (APIENTRYP PFNGLTEXTUREMATERIALEXTPROC) (GLenum face, GLenum mode);
+#endif
+
+#ifndef GL_SGIX_blend_alpha_minmax
+#define GL_SGIX_blend_alpha_minmax 1
+#endif
+
+#ifndef GL_EXT_bgra
+#define GL_EXT_bgra 1
+#endif
+
+#ifndef GL_SGIX_async
+#define GL_SGIX_async 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glAsyncMarkerSGIX (GLuint marker);
+GLAPI GLint APIENTRY glFinishAsyncSGIX (GLuint *markerp);
+GLAPI GLint APIENTRY glPollAsyncSGIX (GLuint *markerp);
+GLAPI GLuint APIENTRY glGenAsyncMarkersSGIX (GLsizei range);
+GLAPI void APIENTRY glDeleteAsyncMarkersSGIX (GLuint marker, GLsizei range);
+GLAPI GLboolean APIENTRY glIsAsyncMarkerSGIX (GLuint marker);
+#endif
+typedef void (APIENTRYP PFNGLASYNCMARKERSGIXPROC) (GLuint marker);
+typedef GLint (APIENTRYP PFNGLFINISHASYNCSGIXPROC) (GLuint *markerp);
+typedef GLint (APIENTRYP PFNGLPOLLASYNCSGIXPROC) (GLuint *markerp);
+typedef GLuint (APIENTRYP PFNGLGENASYNCMARKERSSGIXPROC) (GLsizei range);
+typedef void (APIENTRYP PFNGLDELETEASYNCMARKERSSGIXPROC) (GLuint marker, GLsizei range);
+typedef GLboolean (APIENTRYP PFNGLISASYNCMARKERSGIXPROC) (GLuint marker);
+#endif
+
+#ifndef GL_SGIX_async_pixel
+#define GL_SGIX_async_pixel 1
+#endif
+
+#ifndef GL_SGIX_async_histogram
+#define GL_SGIX_async_histogram 1
+#endif
+
+#ifndef GL_INTEL_parallel_arrays
+#define GL_INTEL_parallel_arrays 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glVertexPointervINTEL (GLint size, GLenum type, const GLvoid* *pointer);
+GLAPI void APIENTRY glNormalPointervINTEL (GLenum type, const GLvoid* *pointer);
+GLAPI void APIENTRY glColorPointervINTEL (GLint size, GLenum type, const GLvoid* *pointer);
+GLAPI void APIENTRY glTexCoordPointervINTEL (GLint size, GLenum type, const GLvoid* *pointer);
+#endif
+typedef void (APIENTRYP PFNGLVERTEXPOINTERVINTELPROC) (GLint size, GLenum type, const GLvoid* *pointer);
+typedef void (APIENTRYP PFNGLNORMALPOINTERVINTELPROC) (GLenum type, const GLvoid* *pointer);
+typedef void (APIENTRYP PFNGLCOLORPOINTERVINTELPROC) (GLint size, GLenum type, const GLvoid* *pointer);
+typedef void (APIENTRYP PFNGLTEXCOORDPOINTERVINTELPROC) (GLint size, GLenum type, const GLvoid* *pointer);
+#endif
+
+#ifndef GL_HP_occlusion_test
+#define GL_HP_occlusion_test 1
+#endif
+
+#ifndef GL_EXT_pixel_transform
+#define GL_EXT_pixel_transform 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glPixelTransformParameteriEXT (GLenum target, GLenum pname, GLint param);
+GLAPI void APIENTRY glPixelTransformParameterfEXT (GLenum target, GLenum pname, GLfloat param);
+GLAPI void APIENTRY glPixelTransformParameterivEXT (GLenum target, GLenum pname, const GLint *params);
+GLAPI void APIENTRY glPixelTransformParameterfvEXT (GLenum target, GLenum pname, const GLfloat *params);
+#endif
+typedef void (APIENTRYP PFNGLPIXELTRANSFORMPARAMETERIEXTPROC) (GLenum target, GLenum pname, GLint param);
+typedef void (APIENTRYP PFNGLPIXELTRANSFORMPARAMETERFEXTPROC) (GLenum target, GLenum pname, GLfloat param);
+typedef void (APIENTRYP PFNGLPIXELTRANSFORMPARAMETERIVEXTPROC) (GLenum target, GLenum pname, const GLint *params);
+typedef void (APIENTRYP PFNGLPIXELTRANSFORMPARAMETERFVEXTPROC) (GLenum target, GLenum pname, const GLfloat *params);
+#endif
+
+#ifndef GL_EXT_pixel_transform_color_table
+#define GL_EXT_pixel_transform_color_table 1
+#endif
+
+#ifndef GL_EXT_shared_texture_palette
+#define GL_EXT_shared_texture_palette 1
+#endif
+
+#ifndef GL_EXT_separate_specular_color
+#define GL_EXT_separate_specular_color 1
+#endif
+
+#ifndef GL_EXT_secondary_color
+#define GL_EXT_secondary_color 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glSecondaryColor3bEXT (GLbyte red, GLbyte green, GLbyte blue);
+GLAPI void APIENTRY glSecondaryColor3bvEXT (const GLbyte *v);
+GLAPI void APIENTRY glSecondaryColor3dEXT (GLdouble red, GLdouble green, GLdouble blue);
+GLAPI void APIENTRY glSecondaryColor3dvEXT (const GLdouble *v);
+GLAPI void APIENTRY glSecondaryColor3fEXT (GLfloat red, GLfloat green, GLfloat blue);
+GLAPI void APIENTRY glSecondaryColor3fvEXT (const GLfloat *v);
+GLAPI void APIENTRY glSecondaryColor3iEXT (GLint red, GLint green, GLint blue);
+GLAPI void APIENTRY glSecondaryColor3ivEXT (const GLint *v);
+GLAPI void APIENTRY glSecondaryColor3sEXT (GLshort red, GLshort green, GLshort blue);
+GLAPI void APIENTRY glSecondaryColor3svEXT (const GLshort *v);
+GLAPI void APIENTRY glSecondaryColor3ubEXT (GLubyte red, GLubyte green, GLubyte blue);
+GLAPI void APIENTRY glSecondaryColor3ubvEXT (const GLubyte *v);
+GLAPI void APIENTRY glSecondaryColor3uiEXT (GLuint red, GLuint green, GLuint blue);
+GLAPI void APIENTRY glSecondaryColor3uivEXT (const GLuint *v);
+GLAPI void APIENTRY glSecondaryColor3usEXT (GLushort red, GLushort green, GLushort blue);
+GLAPI void APIENTRY glSecondaryColor3usvEXT (const GLushort *v);
+GLAPI void APIENTRY glSecondaryColorPointerEXT (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);
+#endif
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3BEXTPROC) (GLbyte red, GLbyte green, GLbyte blue);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3BVEXTPROC) (const GLbyte *v);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3DEXTPROC) (GLdouble red, GLdouble green, GLdouble blue);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3DVEXTPROC) (const GLdouble *v);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3FEXTPROC) (GLfloat red, GLfloat green, GLfloat blue);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3FVEXTPROC) (const GLfloat *v);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3IEXTPROC) (GLint red, GLint green, GLint blue);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3IVEXTPROC) (const GLint *v);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3SEXTPROC) (GLshort red, GLshort green, GLshort blue);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3SVEXTPROC) (const GLshort *v);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3UBEXTPROC) (GLubyte red, GLubyte green, GLubyte blue);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3UBVEXTPROC) (const GLubyte *v);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3UIEXTPROC) (GLuint red, GLuint green, GLuint blue);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3UIVEXTPROC) (const GLuint *v);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3USEXTPROC) (GLushort red, GLushort green, GLushort blue);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3USVEXTPROC) (const GLushort *v);
+typedef void (APIENTRYP PFNGLSECONDARYCOLORPOINTEREXTPROC) (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);
+#endif
+
+#ifndef GL_EXT_texture_perturb_normal
+#define GL_EXT_texture_perturb_normal 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glTextureNormalEXT (GLenum mode);
+#endif
+typedef void (APIENTRYP PFNGLTEXTURENORMALEXTPROC) (GLenum mode);
+#endif
+
+#ifndef GL_EXT_multi_draw_arrays
+#define GL_EXT_multi_draw_arrays 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glMultiDrawArraysEXT (GLenum mode, const GLint *first, const GLsizei *count, GLsizei primcount);
+GLAPI void APIENTRY glMultiDrawElementsEXT (GLenum mode, const GLsizei *count, GLenum type, const GLvoid* *indices, GLsizei primcount);
+#endif
+typedef void (APIENTRYP PFNGLMULTIDRAWARRAYSEXTPROC) (GLenum mode, const GLint *first, const GLsizei *count, GLsizei primcount);
+typedef void (APIENTRYP PFNGLMULTIDRAWELEMENTSEXTPROC) (GLenum mode, const GLsizei *count, GLenum type, const GLvoid* *indices, GLsizei primcount);
+#endif
+
+#ifndef GL_EXT_fog_coord
+#define GL_EXT_fog_coord 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glFogCoordfEXT (GLfloat coord);
+GLAPI void APIENTRY glFogCoordfvEXT (const GLfloat *coord);
+GLAPI void APIENTRY glFogCoorddEXT (GLdouble coord);
+GLAPI void APIENTRY glFogCoorddvEXT (const GLdouble *coord);
+GLAPI void APIENTRY glFogCoordPointerEXT (GLenum type, GLsizei stride, const GLvoid *pointer);
+#endif
+typedef void (APIENTRYP PFNGLFOGCOORDFEXTPROC) (GLfloat coord);
+typedef void (APIENTRYP PFNGLFOGCOORDFVEXTPROC) (const GLfloat *coord);
+typedef void (APIENTRYP PFNGLFOGCOORDDEXTPROC) (GLdouble coord);
+typedef void (APIENTRYP PFNGLFOGCOORDDVEXTPROC) (const GLdouble *coord);
+typedef void (APIENTRYP PFNGLFOGCOORDPOINTEREXTPROC) (GLenum type, GLsizei stride, const GLvoid *pointer);
+#endif
+
+#ifndef GL_REND_screen_coordinates
+#define GL_REND_screen_coordinates 1
+#endif
+
+#ifndef GL_EXT_coordinate_frame
+#define GL_EXT_coordinate_frame 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glTangent3bEXT (GLbyte tx, GLbyte ty, GLbyte tz);
+GLAPI void APIENTRY glTangent3bvEXT (const GLbyte *v);
+GLAPI void APIENTRY glTangent3dEXT (GLdouble tx, GLdouble ty, GLdouble tz);
+GLAPI void APIENTRY glTangent3dvEXT (const GLdouble *v);
+GLAPI void APIENTRY glTangent3fEXT (GLfloat tx, GLfloat ty, GLfloat tz);
+GLAPI void APIENTRY glTangent3fvEXT (const GLfloat *v);
+GLAPI void APIENTRY glTangent3iEXT (GLint tx, GLint ty, GLint tz);
+GLAPI void APIENTRY glTangent3ivEXT (const GLint *v);
+GLAPI void APIENTRY glTangent3sEXT (GLshort tx, GLshort ty, GLshort tz);
+GLAPI void APIENTRY glTangent3svEXT (const GLshort *v);
+GLAPI void APIENTRY glBinormal3bEXT (GLbyte bx, GLbyte by, GLbyte bz);
+GLAPI void APIENTRY glBinormal3bvEXT (const GLbyte *v);
+GLAPI void APIENTRY glBinormal3dEXT (GLdouble bx, GLdouble by, GLdouble bz);
+GLAPI void APIENTRY glBinormal3dvEXT (const GLdouble *v);
+GLAPI void APIENTRY glBinormal3fEXT (GLfloat bx, GLfloat by, GLfloat bz);
+GLAPI void APIENTRY glBinormal3fvEXT (const GLfloat *v);
+GLAPI void APIENTRY glBinormal3iEXT (GLint bx, GLint by, GLint bz);
+GLAPI void APIENTRY glBinormal3ivEXT (const GLint *v);
+GLAPI void APIENTRY glBinormal3sEXT (GLshort bx, GLshort by, GLshort bz);
+GLAPI void APIENTRY glBinormal3svEXT (const GLshort *v);
+GLAPI void APIENTRY glTangentPointerEXT (GLenum type, GLsizei stride, const GLvoid *pointer);
+GLAPI void APIENTRY glBinormalPointerEXT (GLenum type, GLsizei stride, const GLvoid *pointer);
+#endif
+typedef void (APIENTRYP PFNGLTANGENT3BEXTPROC) (GLbyte tx, GLbyte ty, GLbyte tz);
+typedef void (APIENTRYP PFNGLTANGENT3BVEXTPROC) (const GLbyte *v);
+typedef void (APIENTRYP PFNGLTANGENT3DEXTPROC) (GLdouble tx, GLdouble ty, GLdouble tz);
+typedef void (APIENTRYP PFNGLTANGENT3DVEXTPROC) (const GLdouble *v);
+typedef void (APIENTRYP PFNGLTANGENT3FEXTPROC) (GLfloat tx, GLfloat ty, GLfloat tz);
+typedef void (APIENTRYP PFNGLTANGENT3FVEXTPROC) (const GLfloat *v);
+typedef void (APIENTRYP PFNGLTANGENT3IEXTPROC) (GLint tx, GLint ty, GLint tz);
+typedef void (APIENTRYP PFNGLTANGENT3IVEXTPROC) (const GLint *v);
+typedef void (APIENTRYP PFNGLTANGENT3SEXTPROC) (GLshort tx, GLshort ty, GLshort tz);
+typedef void (APIENTRYP PFNGLTANGENT3SVEXTPROC) (const GLshort *v);
+typedef void (APIENTRYP PFNGLBINORMAL3BEXTPROC) (GLbyte bx, GLbyte by, GLbyte bz);
+typedef void (APIENTRYP PFNGLBINORMAL3BVEXTPROC) (const GLbyte *v);
+typedef void (APIENTRYP PFNGLBINORMAL3DEXTPROC) (GLdouble bx, GLdouble by, GLdouble bz);
+typedef void (APIENTRYP PFNGLBINORMAL3DVEXTPROC) (const GLdouble *v);
+typedef void (APIENTRYP PFNGLBINORMAL3FEXTPROC) (GLfloat bx, GLfloat by, GLfloat bz);
+typedef void (APIENTRYP PFNGLBINORMAL3FVEXTPROC) (const GLfloat *v);
+typedef void (APIENTRYP PFNGLBINORMAL3IEXTPROC) (GLint bx, GLint by, GLint bz);
+typedef void (APIENTRYP PFNGLBINORMAL3IVEXTPROC) (const GLint *v);
+typedef void (APIENTRYP PFNGLBINORMAL3SEXTPROC) (GLshort bx, GLshort by, GLshort bz);
+typedef void (APIENTRYP PFNGLBINORMAL3SVEXTPROC) (const GLshort *v);
+typedef void (APIENTRYP PFNGLTANGENTPOINTEREXTPROC) (GLenum type, GLsizei stride, const GLvoid *pointer);
+typedef void (APIENTRYP PFNGLBINORMALPOINTEREXTPROC) (GLenum type, GLsizei stride, const GLvoid *pointer);
+#endif
+
+#ifndef GL_EXT_texture_env_combine
+#define GL_EXT_texture_env_combine 1
+#endif
+
+#ifndef GL_APPLE_specular_vector
+#define GL_APPLE_specular_vector 1
+#endif
+
+#ifndef GL_APPLE_transform_hint
+#define GL_APPLE_transform_hint 1
+#endif
+
+#ifndef GL_SGIX_fog_scale
+#define GL_SGIX_fog_scale 1
+#endif
+
+#ifndef GL_SUNX_constant_data
+#define GL_SUNX_constant_data 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glFinishTextureSUNX (void);
+#endif
+typedef void (APIENTRYP PFNGLFINISHTEXTURESUNXPROC) (void);
+#endif
+
+#ifndef GL_SUN_global_alpha
+#define GL_SUN_global_alpha 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glGlobalAlphaFactorbSUN (GLbyte factor);
+GLAPI void APIENTRY glGlobalAlphaFactorsSUN (GLshort factor);
+GLAPI void APIENTRY glGlobalAlphaFactoriSUN (GLint factor);
+GLAPI void APIENTRY glGlobalAlphaFactorfSUN (GLfloat factor);
+GLAPI void APIENTRY glGlobalAlphaFactordSUN (GLdouble factor);
+GLAPI void APIENTRY glGlobalAlphaFactorubSUN (GLubyte factor);
+GLAPI void APIENTRY glGlobalAlphaFactorusSUN (GLushort factor);
+GLAPI void APIENTRY glGlobalAlphaFactoruiSUN (GLuint factor);
+#endif
+typedef void (APIENTRYP PFNGLGLOBALALPHAFACTORBSUNPROC) (GLbyte factor);
+typedef void (APIENTRYP PFNGLGLOBALALPHAFACTORSSUNPROC) (GLshort factor);
+typedef void (APIENTRYP PFNGLGLOBALALPHAFACTORISUNPROC) (GLint factor);
+typedef void (APIENTRYP PFNGLGLOBALALPHAFACTORFSUNPROC) (GLfloat factor);
+typedef void (APIENTRYP PFNGLGLOBALALPHAFACTORDSUNPROC) (GLdouble factor);
+typedef void (APIENTRYP PFNGLGLOBALALPHAFACTORUBSUNPROC) (GLubyte factor);
+typedef void (APIENTRYP PFNGLGLOBALALPHAFACTORUSSUNPROC) (GLushort factor);
+typedef void (APIENTRYP PFNGLGLOBALALPHAFACTORUISUNPROC) (GLuint factor);
+#endif
+
+#ifndef GL_SUN_triangle_list
+#define GL_SUN_triangle_list 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glReplacementCodeuiSUN (GLuint code);
+GLAPI void APIENTRY glReplacementCodeusSUN (GLushort code);
+GLAPI void APIENTRY glReplacementCodeubSUN (GLubyte code);
+GLAPI void APIENTRY glReplacementCodeuivSUN (const GLuint *code);
+GLAPI void APIENTRY glReplacementCodeusvSUN (const GLushort *code);
+GLAPI void APIENTRY glReplacementCodeubvSUN (const GLubyte *code);
+GLAPI void APIENTRY glReplacementCodePointerSUN (GLenum type, GLsizei stride, const GLvoid* *pointer);
+#endif
+typedef void (APIENTRYP PFNGLREPLACEMENTCODEUISUNPROC) (GLuint code);
+typedef void (APIENTRYP PFNGLREPLACEMENTCODEUSSUNPROC) (GLushort code);
+typedef void (APIENTRYP PFNGLREPLACEMENTCODEUBSUNPROC) (GLubyte code);
+typedef void (APIENTRYP PFNGLREPLACEMENTCODEUIVSUNPROC) (const GLuint *code);
+typedef void (APIENTRYP PFNGLREPLACEMENTCODEUSVSUNPROC) (const GLushort *code);
+typedef void (APIENTRYP PFNGLREPLACEMENTCODEUBVSUNPROC) (const GLubyte *code);
+typedef void (APIENTRYP PFNGLREPLACEMENTCODEPOINTERSUNPROC) (GLenum type, GLsizei stride, const GLvoid* *pointer);
+#endif
+
+#ifndef GL_SUN_vertex
+#define GL_SUN_vertex 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glColor4ubVertex2fSUN (GLubyte r, GLubyte g, GLubyte b, GLubyte a, GLfloat x, GLfloat y);
+GLAPI void APIENTRY glColor4ubVertex2fvSUN (const GLubyte *c, const GLfloat *v);
+GLAPI void APIENTRY glColor4ubVertex3fSUN (GLubyte r, GLubyte g, GLubyte b, GLubyte a, GLfloat x, GLfloat y, GLfloat z);
+GLAPI void APIENTRY glColor4ubVertex3fvSUN (const GLubyte *c, const GLfloat *v);
+GLAPI void APIENTRY glColor3fVertex3fSUN (GLfloat r, GLfloat g, GLfloat b, GLfloat x, GLfloat y, GLfloat z);
+GLAPI void APIENTRY glColor3fVertex3fvSUN (const GLfloat *c, const GLfloat *v);
+GLAPI void APIENTRY glNormal3fVertex3fSUN (GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z);
+GLAPI void APIENTRY glNormal3fVertex3fvSUN (const GLfloat *n, const GLfloat *v);
+GLAPI void APIENTRY glColor4fNormal3fVertex3fSUN (GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z);
+GLAPI void APIENTRY glColor4fNormal3fVertex3fvSUN (const GLfloat *c, const GLfloat *n, const GLfloat *v);
+GLAPI void APIENTRY glTexCoord2fVertex3fSUN (GLfloat s, GLfloat t, GLfloat x, GLfloat y, GLfloat z);
+GLAPI void APIENTRY glTexCoord2fVertex3fvSUN (const GLfloat *tc, const GLfloat *v);
+GLAPI void APIENTRY glTexCoord4fVertex4fSUN (GLfloat s, GLfloat t, GLfloat p, GLfloat q, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+GLAPI void APIENTRY glTexCoord4fVertex4fvSUN (const GLfloat *tc, const GLfloat *v);
+GLAPI void APIENTRY glTexCoord2fColor4ubVertex3fSUN (GLfloat s, GLfloat t, GLubyte r, GLubyte g, GLubyte b, GLubyte a, GLfloat x, GLfloat y, GLfloat z);
+GLAPI void APIENTRY glTexCoord2fColor4ubVertex3fvSUN (const GLfloat *tc, const GLubyte *c, const GLfloat *v);
+GLAPI void APIENTRY glTexCoord2fColor3fVertex3fSUN (GLfloat s, GLfloat t, GLfloat r, GLfloat g, GLfloat b, GLfloat x, GLfloat y, GLfloat z);
+GLAPI void APIENTRY glTexCoord2fColor3fVertex3fvSUN (const GLfloat *tc, const GLfloat *c, const GLfloat *v);
+GLAPI void APIENTRY glTexCoord2fNormal3fVertex3fSUN (GLfloat s, GLfloat t, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z);
+GLAPI void APIENTRY glTexCoord2fNormal3fVertex3fvSUN (const GLfloat *tc, const GLfloat *n, const GLfloat *v);
+GLAPI void APIENTRY glTexCoord2fColor4fNormal3fVertex3fSUN (GLfloat s, GLfloat t, GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z);
+GLAPI void APIENTRY glTexCoord2fColor4fNormal3fVertex3fvSUN (const GLfloat *tc, const GLfloat *c, const GLfloat *n, const GLfloat *v);
+GLAPI void APIENTRY glTexCoord4fColor4fNormal3fVertex4fSUN (GLfloat s, GLfloat t, GLfloat p, GLfloat q, GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+GLAPI void APIENTRY glTexCoord4fColor4fNormal3fVertex4fvSUN (const GLfloat *tc, const GLfloat *c, const GLfloat *n, const GLfloat *v);
+GLAPI void APIENTRY glReplacementCodeuiVertex3fSUN (GLuint rc, GLfloat x, GLfloat y, GLfloat z);
+GLAPI void APIENTRY glReplacementCodeuiVertex3fvSUN (const GLuint *rc, const GLfloat *v);
+GLAPI void APIENTRY glReplacementCodeuiColor4ubVertex3fSUN (GLuint rc, GLubyte r, GLubyte g, GLubyte b, GLubyte a, GLfloat x, GLfloat y, GLfloat z);
+GLAPI void APIENTRY glReplacementCodeuiColor4ubVertex3fvSUN (const GLuint *rc, const GLubyte *c, const GLfloat *v);
+GLAPI void APIENTRY glReplacementCodeuiColor3fVertex3fSUN (GLuint rc, GLfloat r, GLfloat g, GLfloat b, GLfloat x, GLfloat y, GLfloat z);
+GLAPI void APIENTRY glReplacementCodeuiColor3fVertex3fvSUN (const GLuint *rc, const GLfloat *c, const GLfloat *v);
+GLAPI void APIENTRY glReplacementCodeuiNormal3fVertex3fSUN (GLuint rc, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z);
+GLAPI void APIENTRY glReplacementCodeuiNormal3fVertex3fvSUN (const GLuint *rc, const GLfloat *n, const GLfloat *v);
+GLAPI void APIENTRY glReplacementCodeuiColor4fNormal3fVertex3fSUN (GLuint rc, GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z);
+GLAPI void APIENTRY glReplacementCodeuiColor4fNormal3fVertex3fvSUN (const GLuint *rc, const GLfloat *c, const GLfloat *n, const GLfloat *v);
+GLAPI void APIENTRY glReplacementCodeuiTexCoord2fVertex3fSUN (GLuint rc, GLfloat s, GLfloat t, GLfloat x, GLfloat y, GLfloat z);
+GLAPI void APIENTRY glReplacementCodeuiTexCoord2fVertex3fvSUN (const GLuint *rc, const GLfloat *tc, const GLfloat *v);
+GLAPI void APIENTRY glReplacementCodeuiTexCoord2fNormal3fVertex3fSUN (GLuint rc, GLfloat s, GLfloat t, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z);
+GLAPI void APIENTRY glReplacementCodeuiTexCoord2fNormal3fVertex3fvSUN (const GLuint *rc, const GLfloat *tc, const GLfloat *n, const GLfloat *v);
+GLAPI void APIENTRY glReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fSUN (GLuint rc, GLfloat s, GLfloat t, GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z);
+GLAPI void APIENTRY glReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fvSUN (const GLuint *rc, const GLfloat *tc, const GLfloat *c, const GLfloat *n, const GLfloat *v);
+#endif
+typedef void (APIENTRYP PFNGLCOLOR4UBVERTEX2FSUNPROC) (GLubyte r, GLubyte g, GLubyte b, GLubyte a, GLfloat x, GLfloat y);
+typedef void (APIENTRYP PFNGLCOLOR4UBVERTEX2FVSUNPROC) (const GLubyte *c, const GLfloat *v);
+typedef void (APIENTRYP PFNGLCOLOR4UBVERTEX3FSUNPROC) (GLubyte r, GLubyte g, GLubyte b, GLubyte a, GLfloat x, GLfloat y, GLfloat z);
+typedef void (APIENTRYP PFNGLCOLOR4UBVERTEX3FVSUNPROC) (const GLubyte *c, const GLfloat *v);
+typedef void (APIENTRYP PFNGLCOLOR3FVERTEX3FSUNPROC) (GLfloat r, GLfloat g, GLfloat b, GLfloat x, GLfloat y, GLfloat z);
+typedef void (APIENTRYP PFNGLCOLOR3FVERTEX3FVSUNPROC) (const GLfloat *c, const GLfloat *v);
+typedef void (APIENTRYP PFNGLNORMAL3FVERTEX3FSUNPROC) (GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z);
+typedef void (APIENTRYP PFNGLNORMAL3FVERTEX3FVSUNPROC) (const GLfloat *n, const GLfloat *v);
+typedef void (APIENTRYP PFNGLCOLOR4FNORMAL3FVERTEX3FSUNPROC) (GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z);
+typedef void (APIENTRYP PFNGLCOLOR4FNORMAL3FVERTEX3FVSUNPROC) (const GLfloat *c, const GLfloat *n, const GLfloat *v);
+typedef void (APIENTRYP PFNGLTEXCOORD2FVERTEX3FSUNPROC) (GLfloat s, GLfloat t, GLfloat x, GLfloat y, GLfloat z);
+typedef void (APIENTRYP PFNGLTEXCOORD2FVERTEX3FVSUNPROC) (const GLfloat *tc, const GLfloat *v);
+typedef void (APIENTRYP PFNGLTEXCOORD4FVERTEX4FSUNPROC) (GLfloat s, GLfloat t, GLfloat p, GLfloat q, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+typedef void (APIENTRYP PFNGLTEXCOORD4FVERTEX4FVSUNPROC) (const GLfloat *tc, const GLfloat *v);
+typedef void (APIENTRYP PFNGLTEXCOORD2FCOLOR4UBVERTEX3FSUNPROC) (GLfloat s, GLfloat t, GLubyte r, GLubyte g, GLubyte b, GLubyte a, GLfloat x, GLfloat y, GLfloat z);
+typedef void (APIENTRYP PFNGLTEXCOORD2FCOLOR4UBVERTEX3FVSUNPROC) (const GLfloat *tc, const GLubyte *c, const GLfloat *v);
+typedef void (APIENTRYP PFNGLTEXCOORD2FCOLOR3FVERTEX3FSUNPROC) (GLfloat s, GLfloat t, GLfloat r, GLfloat g, GLfloat b, GLfloat x, GLfloat y, GLfloat z);
+typedef void (APIENTRYP PFNGLTEXCOORD2FCOLOR3FVERTEX3FVSUNPROC) (const GLfloat *tc, const GLfloat *c, const GLfloat *v);
+typedef void (APIENTRYP PFNGLTEXCOORD2FNORMAL3FVERTEX3FSUNPROC) (GLfloat s, GLfloat t, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z);
+typedef void (APIENTRYP PFNGLTEXCOORD2FNORMAL3FVERTEX3FVSUNPROC) (const GLfloat *tc, const GLfloat *n, const GLfloat *v);
+typedef void (APIENTRYP PFNGLTEXCOORD2FCOLOR4FNORMAL3FVERTEX3FSUNPROC) (GLfloat s, GLfloat t, GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z);
+typedef void (APIENTRYP PFNGLTEXCOORD2FCOLOR4FNORMAL3FVERTEX3FVSUNPROC) (const GLfloat *tc, const GLfloat *c, const GLfloat *n, const GLfloat *v);
+typedef void (APIENTRYP PFNGLTEXCOORD4FCOLOR4FNORMAL3FVERTEX4FSUNPROC) (GLfloat s, GLfloat t, GLfloat p, GLfloat q, GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+typedef void (APIENTRYP PFNGLTEXCOORD4FCOLOR4FNORMAL3FVERTEX4FVSUNPROC) (const GLfloat *tc, const GLfloat *c, const GLfloat *n, const GLfloat *v);
+typedef void (APIENTRYP PFNGLREPLACEMENTCODEUIVERTEX3FSUNPROC) (GLuint rc, GLfloat x, GLfloat y, GLfloat z);
+typedef void (APIENTRYP PFNGLREPLACEMENTCODEUIVERTEX3FVSUNPROC) (const GLuint *rc, const GLfloat *v);
+typedef void (APIENTRYP PFNGLREPLACEMENTCODEUICOLOR4UBVERTEX3FSUNPROC) (GLuint rc, GLubyte r, GLubyte g, GLubyte b, GLubyte a, GLfloat x, GLfloat y, GLfloat z);
+typedef void (APIENTRYP PFNGLREPLACEMENTCODEUICOLOR4UBVERTEX3FVSUNPROC) (const GLuint *rc, const GLubyte *c, const GLfloat *v);
+typedef void (APIENTRYP PFNGLREPLACEMENTCODEUICOLOR3FVERTEX3FSUNPROC) (GLuint rc, GLfloat r, GLfloat g, GLfloat b, GLfloat x, GLfloat y, GLfloat z);
+typedef void (APIENTRYP PFNGLREPLACEMENTCODEUICOLOR3FVERTEX3FVSUNPROC) (const GLuint *rc, const GLfloat *c, const GLfloat *v);
+typedef void (APIENTRYP PFNGLREPLACEMENTCODEUINORMAL3FVERTEX3FSUNPROC) (GLuint rc, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z);
+typedef void (APIENTRYP PFNGLREPLACEMENTCODEUINORMAL3FVERTEX3FVSUNPROC) (const GLuint *rc, const GLfloat *n, const GLfloat *v);
+typedef void (APIENTRYP PFNGLREPLACEMENTCODEUICOLOR4FNORMAL3FVERTEX3FSUNPROC) (GLuint rc, GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z);
+typedef void (APIENTRYP PFNGLREPLACEMENTCODEUICOLOR4FNORMAL3FVERTEX3FVSUNPROC) (const GLuint *rc, const GLfloat *c, const GLfloat *n, const GLfloat *v);
+typedef void (APIENTRYP PFNGLREPLACEMENTCODEUITEXCOORD2FVERTEX3FSUNPROC) (GLuint rc, GLfloat s, GLfloat t, GLfloat x, GLfloat y, GLfloat z);
+typedef void (APIENTRYP PFNGLREPLACEMENTCODEUITEXCOORD2FVERTEX3FVSUNPROC) (const GLuint *rc, const GLfloat *tc, const GLfloat *v);
+typedef void (APIENTRYP PFNGLREPLACEMENTCODEUITEXCOORD2FNORMAL3FVERTEX3FSUNPROC) (GLuint rc, GLfloat s, GLfloat t, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z);
+typedef void (APIENTRYP PFNGLREPLACEMENTCODEUITEXCOORD2FNORMAL3FVERTEX3FVSUNPROC) (const GLuint *rc, const GLfloat *tc, const GLfloat *n, const GLfloat *v);
+typedef void (APIENTRYP PFNGLREPLACEMENTCODEUITEXCOORD2FCOLOR4FNORMAL3FVERTEX3FSUNPROC) (GLuint rc, GLfloat s, GLfloat t, GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z);
+typedef void (APIENTRYP PFNGLREPLACEMENTCODEUITEXCOORD2FCOLOR4FNORMAL3FVERTEX3FVSUNPROC) (const GLuint *rc, const GLfloat *tc, const GLfloat *c, const GLfloat *n, const GLfloat *v);
+#endif
+
+#ifndef GL_EXT_blend_func_separate
+#define GL_EXT_blend_func_separate 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glBlendFuncSeparateEXT (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha);
+#endif
+typedef void (APIENTRYP PFNGLBLENDFUNCSEPARATEEXTPROC) (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha);
+#endif
+
+#ifndef GL_INGR_blend_func_separate
+#define GL_INGR_blend_func_separate 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glBlendFuncSeparateINGR (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha);
+#endif
+typedef void (APIENTRYP PFNGLBLENDFUNCSEPARATEINGRPROC) (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha);
+#endif
+
+#ifndef GL_INGR_color_clamp
+#define GL_INGR_color_clamp 1
+#endif
+
+#ifndef GL_INGR_interlace_read
+#define GL_INGR_interlace_read 1
+#endif
+
+#ifndef GL_EXT_stencil_wrap
+#define GL_EXT_stencil_wrap 1
+#endif
+
+#ifndef GL_EXT_422_pixels
+#define GL_EXT_422_pixels 1
+#endif
+
+#ifndef GL_NV_texgen_reflection
+#define GL_NV_texgen_reflection 1
+#endif
+
+#ifndef GL_SUN_convolution_border_modes
+#define GL_SUN_convolution_border_modes 1
+#endif
+
+#ifndef GL_EXT_texture_env_add
+#define GL_EXT_texture_env_add 1
+#endif
+
+#ifndef GL_EXT_texture_lod_bias
+#define GL_EXT_texture_lod_bias 1
+#endif
+
+#ifndef GL_EXT_texture_filter_anisotropic
+#define GL_EXT_texture_filter_anisotropic 1
+#endif
+
+#ifndef GL_EXT_vertex_weighting
+#define GL_EXT_vertex_weighting 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glVertexWeightfEXT (GLfloat weight);
+GLAPI void APIENTRY glVertexWeightfvEXT (const GLfloat *weight);
+GLAPI void APIENTRY glVertexWeightPointerEXT (GLsizei size, GLenum type, GLsizei stride, const GLvoid *pointer);
+#endif
+typedef void (APIENTRYP PFNGLVERTEXWEIGHTFEXTPROC) (GLfloat weight);
+typedef void (APIENTRYP PFNGLVERTEXWEIGHTFVEXTPROC) (const GLfloat *weight);
+typedef void (APIENTRYP PFNGLVERTEXWEIGHTPOINTEREXTPROC) (GLsizei size, GLenum type, GLsizei stride, const GLvoid *pointer);
+#endif
+
+#ifndef GL_NV_light_max_exponent
+#define GL_NV_light_max_exponent 1
+#endif
+
+#ifndef GL_NV_vertex_array_range
+#define GL_NV_vertex_array_range 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glFlushVertexArrayRangeNV (void);
+GLAPI void APIENTRY glVertexArrayRangeNV (GLsizei length, const GLvoid *pointer);
+#endif
+typedef void (APIENTRYP PFNGLFLUSHVERTEXARRAYRANGENVPROC) (void);
+typedef void (APIENTRYP PFNGLVERTEXARRAYRANGENVPROC) (GLsizei length, const GLvoid *pointer);
+#endif
+
+#ifndef GL_NV_register_combiners
+#define GL_NV_register_combiners 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glCombinerParameterfvNV (GLenum pname, const GLfloat *params);
+GLAPI void APIENTRY glCombinerParameterfNV (GLenum pname, GLfloat param);
+GLAPI void APIENTRY glCombinerParameterivNV (GLenum pname, const GLint *params);
+GLAPI void APIENTRY glCombinerParameteriNV (GLenum pname, GLint param);
+GLAPI void APIENTRY glCombinerInputNV (GLenum stage, GLenum portion, GLenum variable, GLenum input, GLenum mapping, GLenum componentUsage);
+GLAPI void APIENTRY glCombinerOutputNV (GLenum stage, GLenum portion, GLenum abOutput, GLenum cdOutput, GLenum sumOutput, GLenum scale, GLenum bias, GLboolean abDotProduct, GLboolean cdDotProduct, GLboolean muxSum);
+GLAPI void APIENTRY glFinalCombinerInputNV (GLenum variable, GLenum input, GLenum mapping, GLenum componentUsage);
+GLAPI void APIENTRY glGetCombinerInputParameterfvNV (GLenum stage, GLenum portion, GLenum variable, GLenum pname, GLfloat *params);
+GLAPI void APIENTRY glGetCombinerInputParameterivNV (GLenum stage, GLenum portion, GLenum variable, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetCombinerOutputParameterfvNV (GLenum stage, GLenum portion, GLenum pname, GLfloat *params);
+GLAPI void APIENTRY glGetCombinerOutputParameterivNV (GLenum stage, GLenum portion, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetFinalCombinerInputParameterfvNV (GLenum variable, GLenum pname, GLfloat *params);
+GLAPI void APIENTRY glGetFinalCombinerInputParameterivNV (GLenum variable, GLenum pname, GLint *params);
+#endif
+typedef void (APIENTRYP PFNGLCOMBINERPARAMETERFVNVPROC) (GLenum pname, const GLfloat *params);
+typedef void (APIENTRYP PFNGLCOMBINERPARAMETERFNVPROC) (GLenum pname, GLfloat param);
+typedef void (APIENTRYP PFNGLCOMBINERPARAMETERIVNVPROC) (GLenum pname, const GLint *params);
+typedef void (APIENTRYP PFNGLCOMBINERPARAMETERINVPROC) (GLenum pname, GLint param);
+typedef void (APIENTRYP PFNGLCOMBINERINPUTNVPROC) (GLenum stage, GLenum portion, GLenum variable, GLenum input, GLenum mapping, GLenum componentUsage);
+typedef void (APIENTRYP PFNGLCOMBINEROUTPUTNVPROC) (GLenum stage, GLenum portion, GLenum abOutput, GLenum cdOutput, GLenum sumOutput, GLenum scale, GLenum bias, GLboolean abDotProduct, GLboolean cdDotProduct, GLboolean muxSum);
+typedef void (APIENTRYP PFNGLFINALCOMBINERINPUTNVPROC) (GLenum variable, GLenum input, GLenum mapping, GLenum componentUsage);
+typedef void (APIENTRYP PFNGLGETCOMBINERINPUTPARAMETERFVNVPROC) (GLenum stage, GLenum portion, GLenum variable, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETCOMBINERINPUTPARAMETERIVNVPROC) (GLenum stage, GLenum portion, GLenum variable, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETCOMBINEROUTPUTPARAMETERFVNVPROC) (GLenum stage, GLenum portion, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETCOMBINEROUTPUTPARAMETERIVNVPROC) (GLenum stage, GLenum portion, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETFINALCOMBINERINPUTPARAMETERFVNVPROC) (GLenum variable, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETFINALCOMBINERINPUTPARAMETERIVNVPROC) (GLenum variable, GLenum pname, GLint *params);
+#endif
+
+#ifndef GL_NV_fog_distance
+#define GL_NV_fog_distance 1
+#endif
+
+#ifndef GL_NV_texgen_emboss
+#define GL_NV_texgen_emboss 1
+#endif
+
+#ifndef GL_NV_blend_square
+#define GL_NV_blend_square 1
+#endif
+
+#ifndef GL_NV_texture_env_combine4
+#define GL_NV_texture_env_combine4 1
+#endif
+
+#ifndef GL_MESA_resize_buffers
+#define GL_MESA_resize_buffers 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glResizeBuffersMESA (void);
+#endif
+typedef void (APIENTRYP PFNGLRESIZEBUFFERSMESAPROC) (void);
+#endif
+
+#ifndef GL_MESA_window_pos
+#define GL_MESA_window_pos 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glWindowPos2dMESA (GLdouble x, GLdouble y);
+GLAPI void APIENTRY glWindowPos2dvMESA (const GLdouble *v);
+GLAPI void APIENTRY glWindowPos2fMESA (GLfloat x, GLfloat y);
+GLAPI void APIENTRY glWindowPos2fvMESA (const GLfloat *v);
+GLAPI void APIENTRY glWindowPos2iMESA (GLint x, GLint y);
+GLAPI void APIENTRY glWindowPos2ivMESA (const GLint *v);
+GLAPI void APIENTRY glWindowPos2sMESA (GLshort x, GLshort y);
+GLAPI void APIENTRY glWindowPos2svMESA (const GLshort *v);
+GLAPI void APIENTRY glWindowPos3dMESA (GLdouble x, GLdouble y, GLdouble z);
+GLAPI void APIENTRY glWindowPos3dvMESA (const GLdouble *v);
+GLAPI void APIENTRY glWindowPos3fMESA (GLfloat x, GLfloat y, GLfloat z);
+GLAPI void APIENTRY glWindowPos3fvMESA (const GLfloat *v);
+GLAPI void APIENTRY glWindowPos3iMESA (GLint x, GLint y, GLint z);
+GLAPI void APIENTRY glWindowPos3ivMESA (const GLint *v);
+GLAPI void APIENTRY glWindowPos3sMESA (GLshort x, GLshort y, GLshort z);
+GLAPI void APIENTRY glWindowPos3svMESA (const GLshort *v);
+GLAPI void APIENTRY glWindowPos4dMESA (GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+GLAPI void APIENTRY glWindowPos4dvMESA (const GLdouble *v);
+GLAPI void APIENTRY glWindowPos4fMESA (GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+GLAPI void APIENTRY glWindowPos4fvMESA (const GLfloat *v);
+GLAPI void APIENTRY glWindowPos4iMESA (GLint x, GLint y, GLint z, GLint w);
+GLAPI void APIENTRY glWindowPos4ivMESA (const GLint *v);
+GLAPI void APIENTRY glWindowPos4sMESA (GLshort x, GLshort y, GLshort z, GLshort w);
+GLAPI void APIENTRY glWindowPos4svMESA (const GLshort *v);
+#endif
+typedef void (APIENTRYP PFNGLWINDOWPOS2DMESAPROC) (GLdouble x, GLdouble y);
+typedef void (APIENTRYP PFNGLWINDOWPOS2DVMESAPROC) (const GLdouble *v);
+typedef void (APIENTRYP PFNGLWINDOWPOS2FMESAPROC) (GLfloat x, GLfloat y);
+typedef void (APIENTRYP PFNGLWINDOWPOS2FVMESAPROC) (const GLfloat *v);
+typedef void (APIENTRYP PFNGLWINDOWPOS2IMESAPROC) (GLint x, GLint y);
+typedef void (APIENTRYP PFNGLWINDOWPOS2IVMESAPROC) (const GLint *v);
+typedef void (APIENTRYP PFNGLWINDOWPOS2SMESAPROC) (GLshort x, GLshort y);
+typedef void (APIENTRYP PFNGLWINDOWPOS2SVMESAPROC) (const GLshort *v);
+typedef void (APIENTRYP PFNGLWINDOWPOS3DMESAPROC) (GLdouble x, GLdouble y, GLdouble z);
+typedef void (APIENTRYP PFNGLWINDOWPOS3DVMESAPROC) (const GLdouble *v);
+typedef void (APIENTRYP PFNGLWINDOWPOS3FMESAPROC) (GLfloat x, GLfloat y, GLfloat z);
+typedef void (APIENTRYP PFNGLWINDOWPOS3FVMESAPROC) (const GLfloat *v);
+typedef void (APIENTRYP PFNGLWINDOWPOS3IMESAPROC) (GLint x, GLint y, GLint z);
+typedef void (APIENTRYP PFNGLWINDOWPOS3IVMESAPROC) (const GLint *v);
+typedef void (APIENTRYP PFNGLWINDOWPOS3SMESAPROC) (GLshort x, GLshort y, GLshort z);
+typedef void (APIENTRYP PFNGLWINDOWPOS3SVMESAPROC) (const GLshort *v);
+typedef void (APIENTRYP PFNGLWINDOWPOS4DMESAPROC) (GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+typedef void (APIENTRYP PFNGLWINDOWPOS4DVMESAPROC) (const GLdouble *v);
+typedef void (APIENTRYP PFNGLWINDOWPOS4FMESAPROC) (GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+typedef void (APIENTRYP PFNGLWINDOWPOS4FVMESAPROC) (const GLfloat *v);
+typedef void (APIENTRYP PFNGLWINDOWPOS4IMESAPROC) (GLint x, GLint y, GLint z, GLint w);
+typedef void (APIENTRYP PFNGLWINDOWPOS4IVMESAPROC) (const GLint *v);
+typedef void (APIENTRYP PFNGLWINDOWPOS4SMESAPROC) (GLshort x, GLshort y, GLshort z, GLshort w);
+typedef void (APIENTRYP PFNGLWINDOWPOS4SVMESAPROC) (const GLshort *v);
+#endif
+
+#ifndef GL_IBM_cull_vertex
+#define GL_IBM_cull_vertex 1
+#endif
+
+#ifndef GL_IBM_multimode_draw_arrays
+#define GL_IBM_multimode_draw_arrays 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glMultiModeDrawArraysIBM (const GLenum *mode, const GLint *first, const GLsizei *count, GLsizei primcount, GLint modestride);
+GLAPI void APIENTRY glMultiModeDrawElementsIBM (const GLenum *mode, const GLsizei *count, GLenum type, const GLvoid* const *indices, GLsizei primcount, GLint modestride);
+#endif
+typedef void (APIENTRYP PFNGLMULTIMODEDRAWARRAYSIBMPROC) (const GLenum *mode, const GLint *first, const GLsizei *count, GLsizei primcount, GLint modestride);
+typedef void (APIENTRYP PFNGLMULTIMODEDRAWELEMENTSIBMPROC) (const GLenum *mode, const GLsizei *count, GLenum type, const GLvoid* const *indices, GLsizei primcount, GLint modestride);
+#endif
+
+#ifndef GL_IBM_vertex_array_lists
+#define GL_IBM_vertex_array_lists 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glColorPointerListIBM (GLint size, GLenum type, GLint stride, const GLvoid* *pointer, GLint ptrstride);
+GLAPI void APIENTRY glSecondaryColorPointerListIBM (GLint size, GLenum type, GLint stride, const GLvoid* *pointer, GLint ptrstride);
+GLAPI void APIENTRY glEdgeFlagPointerListIBM (GLint stride, const GLboolean* *pointer, GLint ptrstride);
+GLAPI void APIENTRY glFogCoordPointerListIBM (GLenum type, GLint stride, const GLvoid* *pointer, GLint ptrstride);
+GLAPI void APIENTRY glIndexPointerListIBM (GLenum type, GLint stride, const GLvoid* *pointer, GLint ptrstride);
+GLAPI void APIENTRY glNormalPointerListIBM (GLenum type, GLint stride, const GLvoid* *pointer, GLint ptrstride);
+GLAPI void APIENTRY glTexCoordPointerListIBM (GLint size, GLenum type, GLint stride, const GLvoid* *pointer, GLint ptrstride);
+GLAPI void APIENTRY glVertexPointerListIBM (GLint size, GLenum type, GLint stride, const GLvoid* *pointer, GLint ptrstride);
+#endif
+typedef void (APIENTRYP PFNGLCOLORPOINTERLISTIBMPROC) (GLint size, GLenum type, GLint stride, const GLvoid* *pointer, GLint ptrstride);
+typedef void (APIENTRYP PFNGLSECONDARYCOLORPOINTERLISTIBMPROC) (GLint size, GLenum type, GLint stride, const GLvoid* *pointer, GLint ptrstride);
+typedef void (APIENTRYP PFNGLEDGEFLAGPOINTERLISTIBMPROC) (GLint stride, const GLboolean* *pointer, GLint ptrstride);
+typedef void (APIENTRYP PFNGLFOGCOORDPOINTERLISTIBMPROC) (GLenum type, GLint stride, const GLvoid* *pointer, GLint ptrstride);
+typedef void (APIENTRYP PFNGLINDEXPOINTERLISTIBMPROC) (GLenum type, GLint stride, const GLvoid* *pointer, GLint ptrstride);
+typedef void (APIENTRYP PFNGLNORMALPOINTERLISTIBMPROC) (GLenum type, GLint stride, const GLvoid* *pointer, GLint ptrstride);
+typedef void (APIENTRYP PFNGLTEXCOORDPOINTERLISTIBMPROC) (GLint size, GLenum type, GLint stride, const GLvoid* *pointer, GLint ptrstride);
+typedef void (APIENTRYP PFNGLVERTEXPOINTERLISTIBMPROC) (GLint size, GLenum type, GLint stride, const GLvoid* *pointer, GLint ptrstride);
+#endif
+
+#ifndef GL_SGIX_subsample
+#define GL_SGIX_subsample 1
+#endif
+
+#ifndef GL_SGIX_ycrcba
+#define GL_SGIX_ycrcba 1
+#endif
+
+#ifndef GL_SGIX_ycrcb_subsample
+#define GL_SGIX_ycrcb_subsample 1
+#endif
+
+#ifndef GL_SGIX_depth_pass_instrument
+#define GL_SGIX_depth_pass_instrument 1
+#endif
+
+#ifndef GL_3DFX_texture_compression_FXT1
+#define GL_3DFX_texture_compression_FXT1 1
+#endif
+
+#ifndef GL_3DFX_multisample
+#define GL_3DFX_multisample 1
+#endif
+
+#ifndef GL_3DFX_tbuffer
+#define GL_3DFX_tbuffer 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glTbufferMask3DFX (GLuint mask);
+#endif
+typedef void (APIENTRYP PFNGLTBUFFERMASK3DFXPROC) (GLuint mask);
+#endif
+
+#ifndef GL_EXT_multisample
+#define GL_EXT_multisample 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glSampleMaskEXT (GLclampf value, GLboolean invert);
+GLAPI void APIENTRY glSamplePatternEXT (GLenum pattern);
+#endif
+typedef void (APIENTRYP PFNGLSAMPLEMASKEXTPROC) (GLclampf value, GLboolean invert);
+typedef void (APIENTRYP PFNGLSAMPLEPATTERNEXTPROC) (GLenum pattern);
+#endif
+
+#ifndef GL_SGIX_vertex_preclip
+#define GL_SGIX_vertex_preclip 1
+#endif
+
+#ifndef GL_SGIX_convolution_accuracy
+#define GL_SGIX_convolution_accuracy 1
+#endif
+
+#ifndef GL_SGIX_resample
+#define GL_SGIX_resample 1
+#endif
+
+#ifndef GL_SGIS_point_line_texgen
+#define GL_SGIS_point_line_texgen 1
+#endif
+
+#ifndef GL_SGIS_texture_color_mask
+#define GL_SGIS_texture_color_mask 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glTextureColorMaskSGIS (GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha);
+#endif
+typedef void (APIENTRYP PFNGLTEXTURECOLORMASKSGISPROC) (GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha);
+#endif
+
+#ifndef GL_SGIX_igloo_interface
+#define GL_SGIX_igloo_interface 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glIglooInterfaceSGIX (GLenum pname, const GLvoid *params);
+#endif
+typedef void (APIENTRYP PFNGLIGLOOINTERFACESGIXPROC) (GLenum pname, const GLvoid *params);
+#endif
+
+#ifndef GL_EXT_texture_env_dot3
+#define GL_EXT_texture_env_dot3 1
+#endif
+
+#ifndef GL_ATI_texture_mirror_once
+#define GL_ATI_texture_mirror_once 1
+#endif
+
+#ifndef GL_NV_fence
+#define GL_NV_fence 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glDeleteFencesNV (GLsizei n, const GLuint *fences);
+GLAPI void APIENTRY glGenFencesNV (GLsizei n, GLuint *fences);
+GLAPI GLboolean APIENTRY glIsFenceNV (GLuint fence);
+GLAPI GLboolean APIENTRY glTestFenceNV (GLuint fence);
+GLAPI void APIENTRY glGetFenceivNV (GLuint fence, GLenum pname, GLint *params);
+GLAPI void APIENTRY glFinishFenceNV (GLuint fence);
+GLAPI void APIENTRY glSetFenceNV (GLuint fence, GLenum condition);
+#endif
+typedef void (APIENTRYP PFNGLDELETEFENCESNVPROC) (GLsizei n, const GLuint *fences);
+typedef void (APIENTRYP PFNGLGENFENCESNVPROC) (GLsizei n, GLuint *fences);
+typedef GLboolean (APIENTRYP PFNGLISFENCENVPROC) (GLuint fence);
+typedef GLboolean (APIENTRYP PFNGLTESTFENCENVPROC) (GLuint fence);
+typedef void (APIENTRYP PFNGLGETFENCEIVNVPROC) (GLuint fence, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLFINISHFENCENVPROC) (GLuint fence);
+typedef void (APIENTRYP PFNGLSETFENCENVPROC) (GLuint fence, GLenum condition);
+#endif
+
+#ifndef GL_NV_evaluators
+#define GL_NV_evaluators 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glMapControlPointsNV (GLenum target, GLuint index, GLenum type, GLsizei ustride, GLsizei vstride, GLint uorder, GLint vorder, GLboolean packed, const GLvoid *points);
+GLAPI void APIENTRY glMapParameterivNV (GLenum target, GLenum pname, const GLint *params);
+GLAPI void APIENTRY glMapParameterfvNV (GLenum target, GLenum pname, const GLfloat *params);
+GLAPI void APIENTRY glGetMapControlPointsNV (GLenum target, GLuint index, GLenum type, GLsizei ustride, GLsizei vstride, GLboolean packed, GLvoid *points);
+GLAPI void APIENTRY glGetMapParameterivNV (GLenum target, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetMapParameterfvNV (GLenum target, GLenum pname, GLfloat *params);
+GLAPI void APIENTRY glGetMapAttribParameterivNV (GLenum target, GLuint index, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetMapAttribParameterfvNV (GLenum target, GLuint index, GLenum pname, GLfloat *params);
+GLAPI void APIENTRY glEvalMapsNV (GLenum target, GLenum mode);
+#endif
+typedef void (APIENTRYP PFNGLMAPCONTROLPOINTSNVPROC) (GLenum target, GLuint index, GLenum type, GLsizei ustride, GLsizei vstride, GLint uorder, GLint vorder, GLboolean packed, const GLvoid *points);
+typedef void (APIENTRYP PFNGLMAPPARAMETERIVNVPROC) (GLenum target, GLenum pname, const GLint *params);
+typedef void (APIENTRYP PFNGLMAPPARAMETERFVNVPROC) (GLenum target, GLenum pname, const GLfloat *params);
+typedef void (APIENTRYP PFNGLGETMAPCONTROLPOINTSNVPROC) (GLenum target, GLuint index, GLenum type, GLsizei ustride, GLsizei vstride, GLboolean packed, GLvoid *points);
+typedef void (APIENTRYP PFNGLGETMAPPARAMETERIVNVPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETMAPPARAMETERFVNVPROC) (GLenum target, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETMAPATTRIBPARAMETERIVNVPROC) (GLenum target, GLuint index, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETMAPATTRIBPARAMETERFVNVPROC) (GLenum target, GLuint index, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLEVALMAPSNVPROC) (GLenum target, GLenum mode);
+#endif
+
+#ifndef GL_NV_packed_depth_stencil
+#define GL_NV_packed_depth_stencil 1
+#endif
+
+#ifndef GL_NV_register_combiners2
+#define GL_NV_register_combiners2 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glCombinerStageParameterfvNV (GLenum stage, GLenum pname, const GLfloat *params);
+GLAPI void APIENTRY glGetCombinerStageParameterfvNV (GLenum stage, GLenum pname, GLfloat *params);
+#endif
+typedef void (APIENTRYP PFNGLCOMBINERSTAGEPARAMETERFVNVPROC) (GLenum stage, GLenum pname, const GLfloat *params);
+typedef void (APIENTRYP PFNGLGETCOMBINERSTAGEPARAMETERFVNVPROC) (GLenum stage, GLenum pname, GLfloat *params);
+#endif
+
+#ifndef GL_NV_texture_compression_vtc
+#define GL_NV_texture_compression_vtc 1
+#endif
+
+#ifndef GL_NV_texture_rectangle
+#define GL_NV_texture_rectangle 1
+#endif
+
+#ifndef GL_NV_texture_shader
+#define GL_NV_texture_shader 1
+#endif
+
+#ifndef GL_NV_texture_shader2
+#define GL_NV_texture_shader2 1
+#endif
+
+#ifndef GL_NV_vertex_array_range2
+#define GL_NV_vertex_array_range2 1
+#endif
+
+#ifndef GL_NV_vertex_program
+#define GL_NV_vertex_program 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI GLboolean APIENTRY glAreProgramsResidentNV (GLsizei n, const GLuint *programs, GLboolean *residences);
+GLAPI void APIENTRY glBindProgramNV (GLenum target, GLuint id);
+GLAPI void APIENTRY glDeleteProgramsNV (GLsizei n, const GLuint *programs);
+GLAPI void APIENTRY glExecuteProgramNV (GLenum target, GLuint id, const GLfloat *params);
+GLAPI void APIENTRY glGenProgramsNV (GLsizei n, GLuint *programs);
+GLAPI void APIENTRY glGetProgramParameterdvNV (GLenum target, GLuint index, GLenum pname, GLdouble *params);
+GLAPI void APIENTRY glGetProgramParameterfvNV (GLenum target, GLuint index, GLenum pname, GLfloat *params);
+GLAPI void APIENTRY glGetProgramivNV (GLuint id, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetProgramStringNV (GLuint id, GLenum pname, GLubyte *program);
+GLAPI void APIENTRY glGetTrackMatrixivNV (GLenum target, GLuint address, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetVertexAttribdvNV (GLuint index, GLenum pname, GLdouble *params);
+GLAPI void APIENTRY glGetVertexAttribfvNV (GLuint index, GLenum pname, GLfloat *params);
+GLAPI void APIENTRY glGetVertexAttribivNV (GLuint index, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetVertexAttribPointervNV (GLuint index, GLenum pname, GLvoid* *pointer);
+GLAPI GLboolean APIENTRY glIsProgramNV (GLuint id);
+GLAPI void APIENTRY glLoadProgramNV (GLenum target, GLuint id, GLsizei len, const GLubyte *program);
+GLAPI void APIENTRY glProgramParameter4dNV (GLenum target, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+GLAPI void APIENTRY glProgramParameter4dvNV (GLenum target, GLuint index, const GLdouble *v);
+GLAPI void APIENTRY glProgramParameter4fNV (GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+GLAPI void APIENTRY glProgramParameter4fvNV (GLenum target, GLuint index, const GLfloat *v);
+GLAPI void APIENTRY glProgramParameters4dvNV (GLenum target, GLuint index, GLuint count, const GLdouble *v);
+GLAPI void APIENTRY glProgramParameters4fvNV (GLenum target, GLuint index, GLuint count, const GLfloat *v);
+GLAPI void APIENTRY glRequestResidentProgramsNV (GLsizei n, const GLuint *programs);
+GLAPI void APIENTRY glTrackMatrixNV (GLenum target, GLuint address, GLenum matrix, GLenum transform);
+GLAPI void APIENTRY glVertexAttribPointerNV (GLuint index, GLint fsize, GLenum type, GLsizei stride, const GLvoid *pointer);
+GLAPI void APIENTRY glVertexAttrib1dNV (GLuint index, GLdouble x);
+GLAPI void APIENTRY glVertexAttrib1dvNV (GLuint index, const GLdouble *v);
+GLAPI void APIENTRY glVertexAttrib1fNV (GLuint index, GLfloat x);
+GLAPI void APIENTRY glVertexAttrib1fvNV (GLuint index, const GLfloat *v);
+GLAPI void APIENTRY glVertexAttrib1sNV (GLuint index, GLshort x);
+GLAPI void APIENTRY glVertexAttrib1svNV (GLuint index, const GLshort *v);
+GLAPI void APIENTRY glVertexAttrib2dNV (GLuint index, GLdouble x, GLdouble y);
+GLAPI void APIENTRY glVertexAttrib2dvNV (GLuint index, const GLdouble *v);
+GLAPI void APIENTRY glVertexAttrib2fNV (GLuint index, GLfloat x, GLfloat y);
+GLAPI void APIENTRY glVertexAttrib2fvNV (GLuint index, const GLfloat *v);
+GLAPI void APIENTRY glVertexAttrib2sNV (GLuint index, GLshort x, GLshort y);
+GLAPI void APIENTRY glVertexAttrib2svNV (GLuint index, const GLshort *v);
+GLAPI void APIENTRY glVertexAttrib3dNV (GLuint index, GLdouble x, GLdouble y, GLdouble z);
+GLAPI void APIENTRY glVertexAttrib3dvNV (GLuint index, const GLdouble *v);
+GLAPI void APIENTRY glVertexAttrib3fNV (GLuint index, GLfloat x, GLfloat y, GLfloat z);
+GLAPI void APIENTRY glVertexAttrib3fvNV (GLuint index, const GLfloat *v);
+GLAPI void APIENTRY glVertexAttrib3sNV (GLuint index, GLshort x, GLshort y, GLshort z);
+GLAPI void APIENTRY glVertexAttrib3svNV (GLuint index, const GLshort *v);
+GLAPI void APIENTRY glVertexAttrib4dNV (GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+GLAPI void APIENTRY glVertexAttrib4dvNV (GLuint index, const GLdouble *v);
+GLAPI void APIENTRY glVertexAttrib4fNV (GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+GLAPI void APIENTRY glVertexAttrib4fvNV (GLuint index, const GLfloat *v);
+GLAPI void APIENTRY glVertexAttrib4sNV (GLuint index, GLshort x, GLshort y, GLshort z, GLshort w);
+GLAPI void APIENTRY glVertexAttrib4svNV (GLuint index, const GLshort *v);
+GLAPI void APIENTRY glVertexAttrib4ubNV (GLuint index, GLubyte x, GLubyte y, GLubyte z, GLubyte w);
+GLAPI void APIENTRY glVertexAttrib4ubvNV (GLuint index, const GLubyte *v);
+GLAPI void APIENTRY glVertexAttribs1dvNV (GLuint index, GLsizei count, const GLdouble *v);
+GLAPI void APIENTRY glVertexAttribs1fvNV (GLuint index, GLsizei count, const GLfloat *v);
+GLAPI void APIENTRY glVertexAttribs1svNV (GLuint index, GLsizei count, const GLshort *v);
+GLAPI void APIENTRY glVertexAttribs2dvNV (GLuint index, GLsizei count, const GLdouble *v);
+GLAPI void APIENTRY glVertexAttribs2fvNV (GLuint index, GLsizei count, const GLfloat *v);
+GLAPI void APIENTRY glVertexAttribs2svNV (GLuint index, GLsizei count, const GLshort *v);
+GLAPI void APIENTRY glVertexAttribs3dvNV (GLuint index, GLsizei count, const GLdouble *v);
+GLAPI void APIENTRY glVertexAttribs3fvNV (GLuint index, GLsizei count, const GLfloat *v);
+GLAPI void APIENTRY glVertexAttribs3svNV (GLuint index, GLsizei count, const GLshort *v);
+GLAPI void APIENTRY glVertexAttribs4dvNV (GLuint index, GLsizei count, const GLdouble *v);
+GLAPI void APIENTRY glVertexAttribs4fvNV (GLuint index, GLsizei count, const GLfloat *v);
+GLAPI void APIENTRY glVertexAttribs4svNV (GLuint index, GLsizei count, const GLshort *v);
+GLAPI void APIENTRY glVertexAttribs4ubvNV (GLuint index, GLsizei count, const GLubyte *v);
+#endif
+typedef GLboolean (APIENTRYP PFNGLAREPROGRAMSRESIDENTNVPROC) (GLsizei n, const GLuint *programs, GLboolean *residences);
+typedef void (APIENTRYP PFNGLBINDPROGRAMNVPROC) (GLenum target, GLuint id);
+typedef void (APIENTRYP PFNGLDELETEPROGRAMSNVPROC) (GLsizei n, const GLuint *programs);
+typedef void (APIENTRYP PFNGLEXECUTEPROGRAMNVPROC) (GLenum target, GLuint id, const GLfloat *params);
+typedef void (APIENTRYP PFNGLGENPROGRAMSNVPROC) (GLsizei n, GLuint *programs);
+typedef void (APIENTRYP PFNGLGETPROGRAMPARAMETERDVNVPROC) (GLenum target, GLuint index, GLenum pname, GLdouble *params);
+typedef void (APIENTRYP PFNGLGETPROGRAMPARAMETERFVNVPROC) (GLenum target, GLuint index, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETPROGRAMIVNVPROC) (GLuint id, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETPROGRAMSTRINGNVPROC) (GLuint id, GLenum pname, GLubyte *program);
+typedef void (APIENTRYP PFNGLGETTRACKMATRIXIVNVPROC) (GLenum target, GLuint address, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETVERTEXATTRIBDVNVPROC) (GLuint index, GLenum pname, GLdouble *params);
+typedef void (APIENTRYP PFNGLGETVERTEXATTRIBFVNVPROC) (GLuint index, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETVERTEXATTRIBIVNVPROC) (GLuint index, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETVERTEXATTRIBPOINTERVNVPROC) (GLuint index, GLenum pname, GLvoid* *pointer);
+typedef GLboolean (APIENTRYP PFNGLISPROGRAMNVPROC) (GLuint id);
+typedef void (APIENTRYP PFNGLLOADPROGRAMNVPROC) (GLenum target, GLuint id, GLsizei len, const GLubyte *program);
+typedef void (APIENTRYP PFNGLPROGRAMPARAMETER4DNVPROC) (GLenum target, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+typedef void (APIENTRYP PFNGLPROGRAMPARAMETER4DVNVPROC) (GLenum target, GLuint index, const GLdouble *v);
+typedef void (APIENTRYP PFNGLPROGRAMPARAMETER4FNVPROC) (GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+typedef void (APIENTRYP PFNGLPROGRAMPARAMETER4FVNVPROC) (GLenum target, GLuint index, const GLfloat *v);
+typedef void (APIENTRYP PFNGLPROGRAMPARAMETERS4DVNVPROC) (GLenum target, GLuint index, GLuint count, const GLdouble *v);
+typedef void (APIENTRYP PFNGLPROGRAMPARAMETERS4FVNVPROC) (GLenum target, GLuint index, GLuint count, const GLfloat *v);
+typedef void (APIENTRYP PFNGLREQUESTRESIDENTPROGRAMSNVPROC) (GLsizei n, const GLuint *programs);
+typedef void (APIENTRYP PFNGLTRACKMATRIXNVPROC) (GLenum target, GLuint address, GLenum matrix, GLenum transform);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBPOINTERNVPROC) (GLuint index, GLint fsize, GLenum type, GLsizei stride, const GLvoid *pointer);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB1DNVPROC) (GLuint index, GLdouble x);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB1DVNVPROC) (GLuint index, const GLdouble *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB1FNVPROC) (GLuint index, GLfloat x);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB1FVNVPROC) (GLuint index, const GLfloat *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB1SNVPROC) (GLuint index, GLshort x);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB1SVNVPROC) (GLuint index, const GLshort *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB2DNVPROC) (GLuint index, GLdouble x, GLdouble y);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB2DVNVPROC) (GLuint index, const GLdouble *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB2FNVPROC) (GLuint index, GLfloat x, GLfloat y);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB2FVNVPROC) (GLuint index, const GLfloat *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB2SNVPROC) (GLuint index, GLshort x, GLshort y);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB2SVNVPROC) (GLuint index, const GLshort *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB3DNVPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB3DVNVPROC) (GLuint index, const GLdouble *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB3FNVPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB3FVNVPROC) (GLuint index, const GLfloat *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB3SNVPROC) (GLuint index, GLshort x, GLshort y, GLshort z);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB3SVNVPROC) (GLuint index, const GLshort *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4DNVPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4DVNVPROC) (GLuint index, const GLdouble *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4FNVPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4FVNVPROC) (GLuint index, const GLfloat *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4SNVPROC) (GLuint index, GLshort x, GLshort y, GLshort z, GLshort w);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4SVNVPROC) (GLuint index, const GLshort *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4UBNVPROC) (GLuint index, GLubyte x, GLubyte y, GLubyte z, GLubyte w);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4UBVNVPROC) (GLuint index, const GLubyte *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBS1DVNVPROC) (GLuint index, GLsizei count, const GLdouble *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBS1FVNVPROC) (GLuint index, GLsizei count, const GLfloat *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBS1SVNVPROC) (GLuint index, GLsizei count, const GLshort *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBS2DVNVPROC) (GLuint index, GLsizei count, const GLdouble *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBS2FVNVPROC) (GLuint index, GLsizei count, const GLfloat *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBS2SVNVPROC) (GLuint index, GLsizei count, const GLshort *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBS3DVNVPROC) (GLuint index, GLsizei count, const GLdouble *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBS3FVNVPROC) (GLuint index, GLsizei count, const GLfloat *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBS3SVNVPROC) (GLuint index, GLsizei count, const GLshort *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBS4DVNVPROC) (GLuint index, GLsizei count, const GLdouble *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBS4FVNVPROC) (GLuint index, GLsizei count, const GLfloat *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBS4SVNVPROC) (GLuint index, GLsizei count, const GLshort *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBS4UBVNVPROC) (GLuint index, GLsizei count, const GLubyte *v);
+#endif
+
+#ifndef GL_SGIX_texture_coordinate_clamp
+#define GL_SGIX_texture_coordinate_clamp 1
+#endif
+
+#ifndef GL_SGIX_scalebias_hint
+#define GL_SGIX_scalebias_hint 1
+#endif
+
+#ifndef GL_OML_interlace
+#define GL_OML_interlace 1
+#endif
+
+#ifndef GL_OML_subsample
+#define GL_OML_subsample 1
+#endif
+
+#ifndef GL_OML_resample
+#define GL_OML_resample 1
+#endif
+
+#ifndef GL_NV_copy_depth_to_color
+#define GL_NV_copy_depth_to_color 1
+#endif
+
+#ifndef GL_ATI_envmap_bumpmap
+#define GL_ATI_envmap_bumpmap 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glTexBumpParameterivATI (GLenum pname, const GLint *param);
+GLAPI void APIENTRY glTexBumpParameterfvATI (GLenum pname, const GLfloat *param);
+GLAPI void APIENTRY glGetTexBumpParameterivATI (GLenum pname, GLint *param);
+GLAPI void APIENTRY glGetTexBumpParameterfvATI (GLenum pname, GLfloat *param);
+#endif
+typedef void (APIENTRYP PFNGLTEXBUMPPARAMETERIVATIPROC) (GLenum pname, const GLint *param);
+typedef void (APIENTRYP PFNGLTEXBUMPPARAMETERFVATIPROC) (GLenum pname, const GLfloat *param);
+typedef void (APIENTRYP PFNGLGETTEXBUMPPARAMETERIVATIPROC) (GLenum pname, GLint *param);
+typedef void (APIENTRYP PFNGLGETTEXBUMPPARAMETERFVATIPROC) (GLenum pname, GLfloat *param);
+#endif
+
+#ifndef GL_ATI_fragment_shader
+#define GL_ATI_fragment_shader 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI GLuint APIENTRY glGenFragmentShadersATI (GLuint range);
+GLAPI void APIENTRY glBindFragmentShaderATI (GLuint id);
+GLAPI void APIENTRY glDeleteFragmentShaderATI (GLuint id);
+GLAPI void APIENTRY glBeginFragmentShaderATI (void);
+GLAPI void APIENTRY glEndFragmentShaderATI (void);
+GLAPI void APIENTRY glPassTexCoordATI (GLuint dst, GLuint coord, GLenum swizzle);
+GLAPI void APIENTRY glSampleMapATI (GLuint dst, GLuint interp, GLenum swizzle);
+GLAPI void APIENTRY glColorFragmentOp1ATI (GLenum op, GLuint dst, GLuint dstMask, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod);
+GLAPI void APIENTRY glColorFragmentOp2ATI (GLenum op, GLuint dst, GLuint dstMask, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, GLuint arg2Mod);
+GLAPI void APIENTRY glColorFragmentOp3ATI (GLenum op, GLuint dst, GLuint dstMask, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, GLuint arg2Mod, GLuint arg3, GLuint arg3Rep, GLuint arg3Mod);
+GLAPI void APIENTRY glAlphaFragmentOp1ATI (GLenum op, GLuint dst, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod);
+GLAPI void APIENTRY glAlphaFragmentOp2ATI (GLenum op, GLuint dst, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, GLuint arg2Mod);
+GLAPI void APIENTRY glAlphaFragmentOp3ATI (GLenum op, GLuint dst, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, GLuint arg2Mod, GLuint arg3, GLuint arg3Rep, GLuint arg3Mod);
+GLAPI void APIENTRY glSetFragmentShaderConstantATI (GLuint dst, const GLfloat *value);
+#endif
+typedef GLuint (APIENTRYP PFNGLGENFRAGMENTSHADERSATIPROC) (GLuint range);
+typedef void (APIENTRYP PFNGLBINDFRAGMENTSHADERATIPROC) (GLuint id);
+typedef void (APIENTRYP PFNGLDELETEFRAGMENTSHADERATIPROC) (GLuint id);
+typedef void (APIENTRYP PFNGLBEGINFRAGMENTSHADERATIPROC) (void);
+typedef void (APIENTRYP PFNGLENDFRAGMENTSHADERATIPROC) (void);
+typedef void (APIENTRYP PFNGLPASSTEXCOORDATIPROC) (GLuint dst, GLuint coord, GLenum swizzle);
+typedef void (APIENTRYP PFNGLSAMPLEMAPATIPROC) (GLuint dst, GLuint interp, GLenum swizzle);
+typedef void (APIENTRYP PFNGLCOLORFRAGMENTOP1ATIPROC) (GLenum op, GLuint dst, GLuint dstMask, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod);
+typedef void (APIENTRYP PFNGLCOLORFRAGMENTOP2ATIPROC) (GLenum op, GLuint dst, GLuint dstMask, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, GLuint arg2Mod);
+typedef void (APIENTRYP PFNGLCOLORFRAGMENTOP3ATIPROC) (GLenum op, GLuint dst, GLuint dstMask, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, GLuint arg2Mod, GLuint arg3, GLuint arg3Rep, GLuint arg3Mod);
+typedef void (APIENTRYP PFNGLALPHAFRAGMENTOP1ATIPROC) (GLenum op, GLuint dst, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod);
+typedef void (APIENTRYP PFNGLALPHAFRAGMENTOP2ATIPROC) (GLenum op, GLuint dst, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, GLuint arg2Mod);
+typedef void (APIENTRYP PFNGLALPHAFRAGMENTOP3ATIPROC) (GLenum op, GLuint dst, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, GLuint arg2Mod, GLuint arg3, GLuint arg3Rep, GLuint arg3Mod);
+typedef void (APIENTRYP PFNGLSETFRAGMENTSHADERCONSTANTATIPROC) (GLuint dst, const GLfloat *value);
+#endif
+
+#ifndef GL_ATI_pn_triangles
+#define GL_ATI_pn_triangles 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glPNTrianglesiATI (GLenum pname, GLint param);
+GLAPI void APIENTRY glPNTrianglesfATI (GLenum pname, GLfloat param);
+#endif
+typedef void (APIENTRYP PFNGLPNTRIANGLESIATIPROC) (GLenum pname, GLint param);
+typedef void (APIENTRYP PFNGLPNTRIANGLESFATIPROC) (GLenum pname, GLfloat param);
+#endif
+
+#ifndef GL_ATI_vertex_array_object
+#define GL_ATI_vertex_array_object 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI GLuint APIENTRY glNewObjectBufferATI (GLsizei size, const GLvoid *pointer, GLenum usage);
+GLAPI GLboolean APIENTRY glIsObjectBufferATI (GLuint buffer);
+GLAPI void APIENTRY glUpdateObjectBufferATI (GLuint buffer, GLuint offset, GLsizei size, const GLvoid *pointer, GLenum preserve);
+GLAPI void APIENTRY glGetObjectBufferfvATI (GLuint buffer, GLenum pname, GLfloat *params);
+GLAPI void APIENTRY glGetObjectBufferivATI (GLuint buffer, GLenum pname, GLint *params);
+GLAPI void APIENTRY glFreeObjectBufferATI (GLuint buffer);
+GLAPI void APIENTRY glArrayObjectATI (GLenum array, GLint size, GLenum type, GLsizei stride, GLuint buffer, GLuint offset);
+GLAPI void APIENTRY glGetArrayObjectfvATI (GLenum array, GLenum pname, GLfloat *params);
+GLAPI void APIENTRY glGetArrayObjectivATI (GLenum array, GLenum pname, GLint *params);
+GLAPI void APIENTRY glVariantArrayObjectATI (GLuint id, GLenum type, GLsizei stride, GLuint buffer, GLuint offset);
+GLAPI void APIENTRY glGetVariantArrayObjectfvATI (GLuint id, GLenum pname, GLfloat *params);
+GLAPI void APIENTRY glGetVariantArrayObjectivATI (GLuint id, GLenum pname, GLint *params);
+#endif
+typedef GLuint (APIENTRYP PFNGLNEWOBJECTBUFFERATIPROC) (GLsizei size, const GLvoid *pointer, GLenum usage);
+typedef GLboolean (APIENTRYP PFNGLISOBJECTBUFFERATIPROC) (GLuint buffer);
+typedef void (APIENTRYP PFNGLUPDATEOBJECTBUFFERATIPROC) (GLuint buffer, GLuint offset, GLsizei size, const GLvoid *pointer, GLenum preserve);
+typedef void (APIENTRYP PFNGLGETOBJECTBUFFERFVATIPROC) (GLuint buffer, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETOBJECTBUFFERIVATIPROC) (GLuint buffer, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLFREEOBJECTBUFFERATIPROC) (GLuint buffer);
+typedef void (APIENTRYP PFNGLARRAYOBJECTATIPROC) (GLenum array, GLint size, GLenum type, GLsizei stride, GLuint buffer, GLuint offset);
+typedef void (APIENTRYP PFNGLGETARRAYOBJECTFVATIPROC) (GLenum array, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETARRAYOBJECTIVATIPROC) (GLenum array, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLVARIANTARRAYOBJECTATIPROC) (GLuint id, GLenum type, GLsizei stride, GLuint buffer, GLuint offset);
+typedef void (APIENTRYP PFNGLGETVARIANTARRAYOBJECTFVATIPROC) (GLuint id, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETVARIANTARRAYOBJECTIVATIPROC) (GLuint id, GLenum pname, GLint *params);
+#endif
+
+#ifndef GL_EXT_vertex_shader
+#define GL_EXT_vertex_shader 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glBeginVertexShaderEXT (void);
+GLAPI void APIENTRY glEndVertexShaderEXT (void);
+GLAPI void APIENTRY glBindVertexShaderEXT (GLuint id);
+GLAPI GLuint APIENTRY glGenVertexShadersEXT (GLuint range);
+GLAPI void APIENTRY glDeleteVertexShaderEXT (GLuint id);
+GLAPI void APIENTRY glShaderOp1EXT (GLenum op, GLuint res, GLuint arg1);
+GLAPI void APIENTRY glShaderOp2EXT (GLenum op, GLuint res, GLuint arg1, GLuint arg2);
+GLAPI void APIENTRY glShaderOp3EXT (GLenum op, GLuint res, GLuint arg1, GLuint arg2, GLuint arg3);
+GLAPI void APIENTRY glSwizzleEXT (GLuint res, GLuint in, GLenum outX, GLenum outY, GLenum outZ, GLenum outW);
+GLAPI void APIENTRY glWriteMaskEXT (GLuint res, GLuint in, GLenum outX, GLenum outY, GLenum outZ, GLenum outW);
+GLAPI void APIENTRY glInsertComponentEXT (GLuint res, GLuint src, GLuint num);
+GLAPI void APIENTRY glExtractComponentEXT (GLuint res, GLuint src, GLuint num);
+GLAPI GLuint APIENTRY glGenSymbolsEXT (GLenum datatype, GLenum storagetype, GLenum range, GLuint components);
+GLAPI void APIENTRY glSetInvariantEXT (GLuint id, GLenum type, const GLvoid *addr);
+GLAPI void APIENTRY glSetLocalConstantEXT (GLuint id, GLenum type, const GLvoid *addr);
+GLAPI void APIENTRY glVariantbvEXT (GLuint id, const GLbyte *addr);
+GLAPI void APIENTRY glVariantsvEXT (GLuint id, const GLshort *addr);
+GLAPI void APIENTRY glVariantivEXT (GLuint id, const GLint *addr);
+GLAPI void APIENTRY glVariantfvEXT (GLuint id, const GLfloat *addr);
+GLAPI void APIENTRY glVariantdvEXT (GLuint id, const GLdouble *addr);
+GLAPI void APIENTRY glVariantubvEXT (GLuint id, const GLubyte *addr);
+GLAPI void APIENTRY glVariantusvEXT (GLuint id, const GLushort *addr);
+GLAPI void APIENTRY glVariantuivEXT (GLuint id, const GLuint *addr);
+GLAPI void APIENTRY glVariantPointerEXT (GLuint id, GLenum type, GLuint stride, const GLvoid *addr);
+GLAPI void APIENTRY glEnableVariantClientStateEXT (GLuint id);
+GLAPI void APIENTRY glDisableVariantClientStateEXT (GLuint id);
+GLAPI GLuint APIENTRY glBindLightParameterEXT (GLenum light, GLenum value);
+GLAPI GLuint APIENTRY glBindMaterialParameterEXT (GLenum face, GLenum value);
+GLAPI GLuint APIENTRY glBindTexGenParameterEXT (GLenum unit, GLenum coord, GLenum value);
+GLAPI GLuint APIENTRY glBindTextureUnitParameterEXT (GLenum unit, GLenum value);
+GLAPI GLuint APIENTRY glBindParameterEXT (GLenum value);
+GLAPI GLboolean APIENTRY glIsVariantEnabledEXT (GLuint id, GLenum cap);
+GLAPI void APIENTRY glGetVariantBooleanvEXT (GLuint id, GLenum value, GLboolean *data);
+GLAPI void APIENTRY glGetVariantIntegervEXT (GLuint id, GLenum value, GLint *data);
+GLAPI void APIENTRY glGetVariantFloatvEXT (GLuint id, GLenum value, GLfloat *data);
+GLAPI void APIENTRY glGetVariantPointervEXT (GLuint id, GLenum value, GLvoid* *data);
+GLAPI void APIENTRY glGetInvariantBooleanvEXT (GLuint id, GLenum value, GLboolean *data);
+GLAPI void APIENTRY glGetInvariantIntegervEXT (GLuint id, GLenum value, GLint *data);
+GLAPI void APIENTRY glGetInvariantFloatvEXT (GLuint id, GLenum value, GLfloat *data);
+GLAPI void APIENTRY glGetLocalConstantBooleanvEXT (GLuint id, GLenum value, GLboolean *data);
+GLAPI void APIENTRY glGetLocalConstantIntegervEXT (GLuint id, GLenum value, GLint *data);
+GLAPI void APIENTRY glGetLocalConstantFloatvEXT (GLuint id, GLenum value, GLfloat *data);
+#endif
+typedef void (APIENTRYP PFNGLBEGINVERTEXSHADEREXTPROC) (void);
+typedef void (APIENTRYP PFNGLENDVERTEXSHADEREXTPROC) (void);
+typedef void (APIENTRYP PFNGLBINDVERTEXSHADEREXTPROC) (GLuint id);
+typedef GLuint (APIENTRYP PFNGLGENVERTEXSHADERSEXTPROC) (GLuint range);
+typedef void (APIENTRYP PFNGLDELETEVERTEXSHADEREXTPROC) (GLuint id);
+typedef void (APIENTRYP PFNGLSHADEROP1EXTPROC) (GLenum op, GLuint res, GLuint arg1);
+typedef void (APIENTRYP PFNGLSHADEROP2EXTPROC) (GLenum op, GLuint res, GLuint arg1, GLuint arg2);
+typedef void (APIENTRYP PFNGLSHADEROP3EXTPROC) (GLenum op, GLuint res, GLuint arg1, GLuint arg2, GLuint arg3);
+typedef void (APIENTRYP PFNGLSWIZZLEEXTPROC) (GLuint res, GLuint in, GLenum outX, GLenum outY, GLenum outZ, GLenum outW);
+typedef void (APIENTRYP PFNGLWRITEMASKEXTPROC) (GLuint res, GLuint in, GLenum outX, GLenum outY, GLenum outZ, GLenum outW);
+typedef void (APIENTRYP PFNGLINSERTCOMPONENTEXTPROC) (GLuint res, GLuint src, GLuint num);
+typedef void (APIENTRYP PFNGLEXTRACTCOMPONENTEXTPROC) (GLuint res, GLuint src, GLuint num);
+typedef GLuint (APIENTRYP PFNGLGENSYMBOLSEXTPROC) (GLenum datatype, GLenum storagetype, GLenum range, GLuint components);
+typedef void (APIENTRYP PFNGLSETINVARIANTEXTPROC) (GLuint id, GLenum type, const GLvoid *addr);
+typedef void (APIENTRYP PFNGLSETLOCALCONSTANTEXTPROC) (GLuint id, GLenum type, const GLvoid *addr);
+typedef void (APIENTRYP PFNGLVARIANTBVEXTPROC) (GLuint id, const GLbyte *addr);
+typedef void (APIENTRYP PFNGLVARIANTSVEXTPROC) (GLuint id, const GLshort *addr);
+typedef void (APIENTRYP PFNGLVARIANTIVEXTPROC) (GLuint id, const GLint *addr);
+typedef void (APIENTRYP PFNGLVARIANTFVEXTPROC) (GLuint id, const GLfloat *addr);
+typedef void (APIENTRYP PFNGLVARIANTDVEXTPROC) (GLuint id, const GLdouble *addr);
+typedef void (APIENTRYP PFNGLVARIANTUBVEXTPROC) (GLuint id, const GLubyte *addr);
+typedef void (APIENTRYP PFNGLVARIANTUSVEXTPROC) (GLuint id, const GLushort *addr);
+typedef void (APIENTRYP PFNGLVARIANTUIVEXTPROC) (GLuint id, const GLuint *addr);
+typedef void (APIENTRYP PFNGLVARIANTPOINTEREXTPROC) (GLuint id, GLenum type, GLuint stride, const GLvoid *addr);
+typedef void (APIENTRYP PFNGLENABLEVARIANTCLIENTSTATEEXTPROC) (GLuint id);
+typedef void (APIENTRYP PFNGLDISABLEVARIANTCLIENTSTATEEXTPROC) (GLuint id);
+typedef GLuint (APIENTRYP PFNGLBINDLIGHTPARAMETEREXTPROC) (GLenum light, GLenum value);
+typedef GLuint (APIENTRYP PFNGLBINDMATERIALPARAMETEREXTPROC) (GLenum face, GLenum value);
+typedef GLuint (APIENTRYP PFNGLBINDTEXGENPARAMETEREXTPROC) (GLenum unit, GLenum coord, GLenum value);
+typedef GLuint (APIENTRYP PFNGLBINDTEXTUREUNITPARAMETEREXTPROC) (GLenum unit, GLenum value);
+typedef GLuint (APIENTRYP PFNGLBINDPARAMETEREXTPROC) (GLenum value);
+typedef GLboolean (APIENTRYP PFNGLISVARIANTENABLEDEXTPROC) (GLuint id, GLenum cap);
+typedef void (APIENTRYP PFNGLGETVARIANTBOOLEANVEXTPROC) (GLuint id, GLenum value, GLboolean *data);
+typedef void (APIENTRYP PFNGLGETVARIANTINTEGERVEXTPROC) (GLuint id, GLenum value, GLint *data);
+typedef void (APIENTRYP PFNGLGETVARIANTFLOATVEXTPROC) (GLuint id, GLenum value, GLfloat *data);
+typedef void (APIENTRYP PFNGLGETVARIANTPOINTERVEXTPROC) (GLuint id, GLenum value, GLvoid* *data);
+typedef void (APIENTRYP PFNGLGETINVARIANTBOOLEANVEXTPROC) (GLuint id, GLenum value, GLboolean *data);
+typedef void (APIENTRYP PFNGLGETINVARIANTINTEGERVEXTPROC) (GLuint id, GLenum value, GLint *data);
+typedef void (APIENTRYP PFNGLGETINVARIANTFLOATVEXTPROC) (GLuint id, GLenum value, GLfloat *data);
+typedef void (APIENTRYP PFNGLGETLOCALCONSTANTBOOLEANVEXTPROC) (GLuint id, GLenum value, GLboolean *data);
+typedef void (APIENTRYP PFNGLGETLOCALCONSTANTINTEGERVEXTPROC) (GLuint id, GLenum value, GLint *data);
+typedef void (APIENTRYP PFNGLGETLOCALCONSTANTFLOATVEXTPROC) (GLuint id, GLenum value, GLfloat *data);
+#endif
+
+#ifndef GL_ATI_vertex_streams
+#define GL_ATI_vertex_streams 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glVertexStream1sATI (GLenum stream, GLshort x);
+GLAPI void APIENTRY glVertexStream1svATI (GLenum stream, const GLshort *coords);
+GLAPI void APIENTRY glVertexStream1iATI (GLenum stream, GLint x);
+GLAPI void APIENTRY glVertexStream1ivATI (GLenum stream, const GLint *coords);
+GLAPI void APIENTRY glVertexStream1fATI (GLenum stream, GLfloat x);
+GLAPI void APIENTRY glVertexStream1fvATI (GLenum stream, const GLfloat *coords);
+GLAPI void APIENTRY glVertexStream1dATI (GLenum stream, GLdouble x);
+GLAPI void APIENTRY glVertexStream1dvATI (GLenum stream, const GLdouble *coords);
+GLAPI void APIENTRY glVertexStream2sATI (GLenum stream, GLshort x, GLshort y);
+GLAPI void APIENTRY glVertexStream2svATI (GLenum stream, const GLshort *coords);
+GLAPI void APIENTRY glVertexStream2iATI (GLenum stream, GLint x, GLint y);
+GLAPI void APIENTRY glVertexStream2ivATI (GLenum stream, const GLint *coords);
+GLAPI void APIENTRY glVertexStream2fATI (GLenum stream, GLfloat x, GLfloat y);
+GLAPI void APIENTRY glVertexStream2fvATI (GLenum stream, const GLfloat *coords);
+GLAPI void APIENTRY glVertexStream2dATI (GLenum stream, GLdouble x, GLdouble y);
+GLAPI void APIENTRY glVertexStream2dvATI (GLenum stream, const GLdouble *coords);
+GLAPI void APIENTRY glVertexStream3sATI (GLenum stream, GLshort x, GLshort y, GLshort z);
+GLAPI void APIENTRY glVertexStream3svATI (GLenum stream, const GLshort *coords);
+GLAPI void APIENTRY glVertexStream3iATI (GLenum stream, GLint x, GLint y, GLint z);
+GLAPI void APIENTRY glVertexStream3ivATI (GLenum stream, const GLint *coords);
+GLAPI void APIENTRY glVertexStream3fATI (GLenum stream, GLfloat x, GLfloat y, GLfloat z);
+GLAPI void APIENTRY glVertexStream3fvATI (GLenum stream, const GLfloat *coords);
+GLAPI void APIENTRY glVertexStream3dATI (GLenum stream, GLdouble x, GLdouble y, GLdouble z);
+GLAPI void APIENTRY glVertexStream3dvATI (GLenum stream, const GLdouble *coords);
+GLAPI void APIENTRY glVertexStream4sATI (GLenum stream, GLshort x, GLshort y, GLshort z, GLshort w);
+GLAPI void APIENTRY glVertexStream4svATI (GLenum stream, const GLshort *coords);
+GLAPI void APIENTRY glVertexStream4iATI (GLenum stream, GLint x, GLint y, GLint z, GLint w);
+GLAPI void APIENTRY glVertexStream4ivATI (GLenum stream, const GLint *coords);
+GLAPI void APIENTRY glVertexStream4fATI (GLenum stream, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+GLAPI void APIENTRY glVertexStream4fvATI (GLenum stream, const GLfloat *coords);
+GLAPI void APIENTRY glVertexStream4dATI (GLenum stream, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+GLAPI void APIENTRY glVertexStream4dvATI (GLenum stream, const GLdouble *coords);
+GLAPI void APIENTRY glNormalStream3bATI (GLenum stream, GLbyte nx, GLbyte ny, GLbyte nz);
+GLAPI void APIENTRY glNormalStream3bvATI (GLenum stream, const GLbyte *coords);
+GLAPI void APIENTRY glNormalStream3sATI (GLenum stream, GLshort nx, GLshort ny, GLshort nz);
+GLAPI void APIENTRY glNormalStream3svATI (GLenum stream, const GLshort *coords);
+GLAPI void APIENTRY glNormalStream3iATI (GLenum stream, GLint nx, GLint ny, GLint nz);
+GLAPI void APIENTRY glNormalStream3ivATI (GLenum stream, const GLint *coords);
+GLAPI void APIENTRY glNormalStream3fATI (GLenum stream, GLfloat nx, GLfloat ny, GLfloat nz);
+GLAPI void APIENTRY glNormalStream3fvATI (GLenum stream, const GLfloat *coords);
+GLAPI void APIENTRY glNormalStream3dATI (GLenum stream, GLdouble nx, GLdouble ny, GLdouble nz);
+GLAPI void APIENTRY glNormalStream3dvATI (GLenum stream, const GLdouble *coords);
+GLAPI void APIENTRY glClientActiveVertexStreamATI (GLenum stream);
+GLAPI void APIENTRY glVertexBlendEnviATI (GLenum pname, GLint param);
+GLAPI void APIENTRY glVertexBlendEnvfATI (GLenum pname, GLfloat param);
+#endif
+typedef void (APIENTRYP PFNGLVERTEXSTREAM1SATIPROC) (GLenum stream, GLshort x);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM1SVATIPROC) (GLenum stream, const GLshort *coords);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM1IATIPROC) (GLenum stream, GLint x);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM1IVATIPROC) (GLenum stream, const GLint *coords);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM1FATIPROC) (GLenum stream, GLfloat x);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM1FVATIPROC) (GLenum stream, const GLfloat *coords);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM1DATIPROC) (GLenum stream, GLdouble x);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM1DVATIPROC) (GLenum stream, const GLdouble *coords);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM2SATIPROC) (GLenum stream, GLshort x, GLshort y);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM2SVATIPROC) (GLenum stream, const GLshort *coords);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM2IATIPROC) (GLenum stream, GLint x, GLint y);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM2IVATIPROC) (GLenum stream, const GLint *coords);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM2FATIPROC) (GLenum stream, GLfloat x, GLfloat y);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM2FVATIPROC) (GLenum stream, const GLfloat *coords);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM2DATIPROC) (GLenum stream, GLdouble x, GLdouble y);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM2DVATIPROC) (GLenum stream, const GLdouble *coords);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM3SATIPROC) (GLenum stream, GLshort x, GLshort y, GLshort z);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM3SVATIPROC) (GLenum stream, const GLshort *coords);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM3IATIPROC) (GLenum stream, GLint x, GLint y, GLint z);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM3IVATIPROC) (GLenum stream, const GLint *coords);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM3FATIPROC) (GLenum stream, GLfloat x, GLfloat y, GLfloat z);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM3FVATIPROC) (GLenum stream, const GLfloat *coords);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM3DATIPROC) (GLenum stream, GLdouble x, GLdouble y, GLdouble z);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM3DVATIPROC) (GLenum stream, const GLdouble *coords);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM4SATIPROC) (GLenum stream, GLshort x, GLshort y, GLshort z, GLshort w);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM4SVATIPROC) (GLenum stream, const GLshort *coords);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM4IATIPROC) (GLenum stream, GLint x, GLint y, GLint z, GLint w);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM4IVATIPROC) (GLenum stream, const GLint *coords);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM4FATIPROC) (GLenum stream, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM4FVATIPROC) (GLenum stream, const GLfloat *coords);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM4DATIPROC) (GLenum stream, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM4DVATIPROC) (GLenum stream, const GLdouble *coords);
+typedef void (APIENTRYP PFNGLNORMALSTREAM3BATIPROC) (GLenum stream, GLbyte nx, GLbyte ny, GLbyte nz);
+typedef void (APIENTRYP PFNGLNORMALSTREAM3BVATIPROC) (GLenum stream, const GLbyte *coords);
+typedef void (APIENTRYP PFNGLNORMALSTREAM3SATIPROC) (GLenum stream, GLshort nx, GLshort ny, GLshort nz);
+typedef void (APIENTRYP PFNGLNORMALSTREAM3SVATIPROC) (GLenum stream, const GLshort *coords);
+typedef void (APIENTRYP PFNGLNORMALSTREAM3IATIPROC) (GLenum stream, GLint nx, GLint ny, GLint nz);
+typedef void (APIENTRYP PFNGLNORMALSTREAM3IVATIPROC) (GLenum stream, const GLint *coords);
+typedef void (APIENTRYP PFNGLNORMALSTREAM3FATIPROC) (GLenum stream, GLfloat nx, GLfloat ny, GLfloat nz);
+typedef void (APIENTRYP PFNGLNORMALSTREAM3FVATIPROC) (GLenum stream, const GLfloat *coords);
+typedef void (APIENTRYP PFNGLNORMALSTREAM3DATIPROC) (GLenum stream, GLdouble nx, GLdouble ny, GLdouble nz);
+typedef void (APIENTRYP PFNGLNORMALSTREAM3DVATIPROC) (GLenum stream, const GLdouble *coords);
+typedef void (APIENTRYP PFNGLCLIENTACTIVEVERTEXSTREAMATIPROC) (GLenum stream);
+typedef void (APIENTRYP PFNGLVERTEXBLENDENVIATIPROC) (GLenum pname, GLint param);
+typedef void (APIENTRYP PFNGLVERTEXBLENDENVFATIPROC) (GLenum pname, GLfloat param);
+#endif
+
+#ifndef GL_ATI_element_array
+#define GL_ATI_element_array 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glElementPointerATI (GLenum type, const GLvoid *pointer);
+GLAPI void APIENTRY glDrawElementArrayATI (GLenum mode, GLsizei count);
+GLAPI void APIENTRY glDrawRangeElementArrayATI (GLenum mode, GLuint start, GLuint end, GLsizei count);
+#endif
+typedef void (APIENTRYP PFNGLELEMENTPOINTERATIPROC) (GLenum type, const GLvoid *pointer);
+typedef void (APIENTRYP PFNGLDRAWELEMENTARRAYATIPROC) (GLenum mode, GLsizei count);
+typedef void (APIENTRYP PFNGLDRAWRANGEELEMENTARRAYATIPROC) (GLenum mode, GLuint start, GLuint end, GLsizei count);
+#endif
+
+#ifndef GL_SUN_mesh_array
+#define GL_SUN_mesh_array 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glDrawMeshArraysSUN (GLenum mode, GLint first, GLsizei count, GLsizei width);
+#endif
+typedef void (APIENTRYP PFNGLDRAWMESHARRAYSSUNPROC) (GLenum mode, GLint first, GLsizei count, GLsizei width);
+#endif
+
+#ifndef GL_SUN_slice_accum
+#define GL_SUN_slice_accum 1
+#endif
+
+#ifndef GL_NV_multisample_filter_hint
+#define GL_NV_multisample_filter_hint 1
+#endif
+
+#ifndef GL_NV_depth_clamp
+#define GL_NV_depth_clamp 1
+#endif
+
+#ifndef GL_NV_occlusion_query
+#define GL_NV_occlusion_query 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glGenOcclusionQueriesNV (GLsizei n, GLuint *ids);
+GLAPI void APIENTRY glDeleteOcclusionQueriesNV (GLsizei n, const GLuint *ids);
+GLAPI GLboolean APIENTRY glIsOcclusionQueryNV (GLuint id);
+GLAPI void APIENTRY glBeginOcclusionQueryNV (GLuint id);
+GLAPI void APIENTRY glEndOcclusionQueryNV (void);
+GLAPI void APIENTRY glGetOcclusionQueryivNV (GLuint id, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetOcclusionQueryuivNV (GLuint id, GLenum pname, GLuint *params);
+#endif
+typedef void (APIENTRYP PFNGLGENOCCLUSIONQUERIESNVPROC) (GLsizei n, GLuint *ids);
+typedef void (APIENTRYP PFNGLDELETEOCCLUSIONQUERIESNVPROC) (GLsizei n, const GLuint *ids);
+typedef GLboolean (APIENTRYP PFNGLISOCCLUSIONQUERYNVPROC) (GLuint id);
+typedef void (APIENTRYP PFNGLBEGINOCCLUSIONQUERYNVPROC) (GLuint id);
+typedef void (APIENTRYP PFNGLENDOCCLUSIONQUERYNVPROC) (void);
+typedef void (APIENTRYP PFNGLGETOCCLUSIONQUERYIVNVPROC) (GLuint id, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETOCCLUSIONQUERYUIVNVPROC) (GLuint id, GLenum pname, GLuint *params);
+#endif
+
+#ifndef GL_NV_point_sprite
+#define GL_NV_point_sprite 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glPointParameteriNV (GLenum pname, GLint param);
+GLAPI void APIENTRY glPointParameterivNV (GLenum pname, const GLint *params);
+#endif
+typedef void (APIENTRYP PFNGLPOINTPARAMETERINVPROC) (GLenum pname, GLint param);
+typedef void (APIENTRYP PFNGLPOINTPARAMETERIVNVPROC) (GLenum pname, const GLint *params);
+#endif
+
+#ifndef GL_NV_texture_shader3
+#define GL_NV_texture_shader3 1
+#endif
+
+#ifndef GL_NV_vertex_program1_1
+#define GL_NV_vertex_program1_1 1
+#endif
+
+#ifndef GL_EXT_shadow_funcs
+#define GL_EXT_shadow_funcs 1
+#endif
+
+#ifndef GL_EXT_stencil_two_side
+#define GL_EXT_stencil_two_side 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glActiveStencilFaceEXT (GLenum face);
+#endif
+typedef void (APIENTRYP PFNGLACTIVESTENCILFACEEXTPROC) (GLenum face);
+#endif
+
+#ifndef GL_ATI_text_fragment_shader
+#define GL_ATI_text_fragment_shader 1
+#endif
+
+#ifndef GL_APPLE_client_storage
+#define GL_APPLE_client_storage 1
+#endif
+
+#ifndef GL_APPLE_element_array
+#define GL_APPLE_element_array 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glElementPointerAPPLE (GLenum type, const GLvoid *pointer);
+GLAPI void APIENTRY glDrawElementArrayAPPLE (GLenum mode, GLint first, GLsizei count);
+GLAPI void APIENTRY glDrawRangeElementArrayAPPLE (GLenum mode, GLuint start, GLuint end, GLint first, GLsizei count);
+GLAPI void APIENTRY glMultiDrawElementArrayAPPLE (GLenum mode, const GLint *first, const GLsizei *count, GLsizei primcount);
+GLAPI void APIENTRY glMultiDrawRangeElementArrayAPPLE (GLenum mode, GLuint start, GLuint end, const GLint *first, const GLsizei *count, GLsizei primcount);
+#endif
+typedef void (APIENTRYP PFNGLELEMENTPOINTERAPPLEPROC) (GLenum type, const GLvoid *pointer);
+typedef void (APIENTRYP PFNGLDRAWELEMENTARRAYAPPLEPROC) (GLenum mode, GLint first, GLsizei count);
+typedef void (APIENTRYP PFNGLDRAWRANGEELEMENTARRAYAPPLEPROC) (GLenum mode, GLuint start, GLuint end, GLint first, GLsizei count);
+typedef void (APIENTRYP PFNGLMULTIDRAWELEMENTARRAYAPPLEPROC) (GLenum mode, const GLint *first, const GLsizei *count, GLsizei primcount);
+typedef void (APIENTRYP PFNGLMULTIDRAWRANGEELEMENTARRAYAPPLEPROC) (GLenum mode, GLuint start, GLuint end, const GLint *first, const GLsizei *count, GLsizei primcount);
+#endif
+
+#ifndef GL_APPLE_fence
+#define GL_APPLE_fence 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glGenFencesAPPLE (GLsizei n, GLuint *fences);
+GLAPI void APIENTRY glDeleteFencesAPPLE (GLsizei n, const GLuint *fences);
+GLAPI void APIENTRY glSetFenceAPPLE (GLuint fence);
+GLAPI GLboolean APIENTRY glIsFenceAPPLE (GLuint fence);
+GLAPI GLboolean APIENTRY glTestFenceAPPLE (GLuint fence);
+GLAPI void APIENTRY glFinishFenceAPPLE (GLuint fence);
+GLAPI GLboolean APIENTRY glTestObjectAPPLE (GLenum object, GLuint name);
+GLAPI void APIENTRY glFinishObjectAPPLE (GLenum object, GLint name);
+#endif
+typedef void (APIENTRYP PFNGLGENFENCESAPPLEPROC) (GLsizei n, GLuint *fences);
+typedef void (APIENTRYP PFNGLDELETEFENCESAPPLEPROC) (GLsizei n, const GLuint *fences);
+typedef void (APIENTRYP PFNGLSETFENCEAPPLEPROC) (GLuint fence);
+typedef GLboolean (APIENTRYP PFNGLISFENCEAPPLEPROC) (GLuint fence);
+typedef GLboolean (APIENTRYP PFNGLTESTFENCEAPPLEPROC) (GLuint fence);
+typedef void (APIENTRYP PFNGLFINISHFENCEAPPLEPROC) (GLuint fence);
+typedef GLboolean (APIENTRYP PFNGLTESTOBJECTAPPLEPROC) (GLenum object, GLuint name);
+typedef void (APIENTRYP PFNGLFINISHOBJECTAPPLEPROC) (GLenum object, GLint name);
+#endif
+
+#ifndef GL_APPLE_vertex_array_object
+#define GL_APPLE_vertex_array_object 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glBindVertexArrayAPPLE (GLuint array);
+GLAPI void APIENTRY glDeleteVertexArraysAPPLE (GLsizei n, const GLuint *arrays);
+GLAPI void APIENTRY glGenVertexArraysAPPLE (GLsizei n, GLuint *arrays);
+GLAPI GLboolean APIENTRY glIsVertexArrayAPPLE (GLuint array);
+#endif
+typedef void (APIENTRYP PFNGLBINDVERTEXARRAYAPPLEPROC) (GLuint array);
+typedef void (APIENTRYP PFNGLDELETEVERTEXARRAYSAPPLEPROC) (GLsizei n, const GLuint *arrays);
+typedef void (APIENTRYP PFNGLGENVERTEXARRAYSAPPLEPROC) (GLsizei n, GLuint *arrays);
+typedef GLboolean (APIENTRYP PFNGLISVERTEXARRAYAPPLEPROC) (GLuint array);
+#endif
+
+#ifndef GL_APPLE_vertex_array_range
+#define GL_APPLE_vertex_array_range 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glVertexArrayRangeAPPLE (GLsizei length, GLvoid *pointer);
+GLAPI void APIENTRY glFlushVertexArrayRangeAPPLE (GLsizei length, GLvoid *pointer);
+GLAPI void APIENTRY glVertexArrayParameteriAPPLE (GLenum pname, GLint param);
+#endif
+typedef void (APIENTRYP PFNGLVERTEXARRAYRANGEAPPLEPROC) (GLsizei length, GLvoid *pointer);
+typedef void (APIENTRYP PFNGLFLUSHVERTEXARRAYRANGEAPPLEPROC) (GLsizei length, GLvoid *pointer);
+typedef void (APIENTRYP PFNGLVERTEXARRAYPARAMETERIAPPLEPROC) (GLenum pname, GLint param);
+#endif
+
+#ifndef GL_APPLE_ycbcr_422
+#define GL_APPLE_ycbcr_422 1
+#endif
+
+#ifndef GL_S3_s3tc
+#define GL_S3_s3tc 1
+#endif
+
+#ifndef GL_ATI_draw_buffers
+#define GL_ATI_draw_buffers 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glDrawBuffersATI (GLsizei n, const GLenum *bufs);
+#endif
+typedef void (APIENTRYP PFNGLDRAWBUFFERSATIPROC) (GLsizei n, const GLenum *bufs);
+#endif
+
+#ifndef GL_ATI_pixel_format_float
+#define GL_ATI_pixel_format_float 1
+
+#endif
+
+#ifndef GL_ATI_texture_env_combine3
+#define GL_ATI_texture_env_combine3 1
+#endif
+
+#ifndef GL_ATI_texture_float
+#define GL_ATI_texture_float 1
+#endif
+
+#ifndef GL_NV_float_buffer
+#define GL_NV_float_buffer 1
+#endif
+
+#ifndef GL_NV_fragment_program
+#define GL_NV_fragment_program 1
+
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glProgramNamedParameter4fNV (GLuint id, GLsizei len, const GLubyte *name, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+GLAPI void APIENTRY glProgramNamedParameter4dNV (GLuint id, GLsizei len, const GLubyte *name, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+GLAPI void APIENTRY glProgramNamedParameter4fvNV (GLuint id, GLsizei len, const GLubyte *name, const GLfloat *v);
+GLAPI void APIENTRY glProgramNamedParameter4dvNV (GLuint id, GLsizei len, const GLubyte *name, const GLdouble *v);
+GLAPI void APIENTRY glGetProgramNamedParameterfvNV (GLuint id, GLsizei len, const GLubyte *name, GLfloat *params);
+GLAPI void APIENTRY glGetProgramNamedParameterdvNV (GLuint id, GLsizei len, const GLubyte *name, GLdouble *params);
+#endif
+typedef void (APIENTRYP PFNGLPROGRAMNAMEDPARAMETER4FNVPROC) (GLuint id, GLsizei len, const GLubyte *name, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+typedef void (APIENTRYP PFNGLPROGRAMNAMEDPARAMETER4DNVPROC) (GLuint id, GLsizei len, const GLubyte *name, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+typedef void (APIENTRYP PFNGLPROGRAMNAMEDPARAMETER4FVNVPROC) (GLuint id, GLsizei len, const GLubyte *name, const GLfloat *v);
+typedef void (APIENTRYP PFNGLPROGRAMNAMEDPARAMETER4DVNVPROC) (GLuint id, GLsizei len, const GLubyte *name, const GLdouble *v);
+typedef void (APIENTRYP PFNGLGETPROGRAMNAMEDPARAMETERFVNVPROC) (GLuint id, GLsizei len, const GLubyte *name, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETPROGRAMNAMEDPARAMETERDVNVPROC) (GLuint id, GLsizei len, const GLubyte *name, GLdouble *params);
+#endif
+
+#ifndef GL_NV_half_float
+#define GL_NV_half_float 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glVertex2hNV (GLhalfNV x, GLhalfNV y);
+GLAPI void APIENTRY glVertex2hvNV (const GLhalfNV *v);
+GLAPI void APIENTRY glVertex3hNV (GLhalfNV x, GLhalfNV y, GLhalfNV z);
+GLAPI void APIENTRY glVertex3hvNV (const GLhalfNV *v);
+GLAPI void APIENTRY glVertex4hNV (GLhalfNV x, GLhalfNV y, GLhalfNV z, GLhalfNV w);
+GLAPI void APIENTRY glVertex4hvNV (const GLhalfNV *v);
+GLAPI void APIENTRY glNormal3hNV (GLhalfNV nx, GLhalfNV ny, GLhalfNV nz);
+GLAPI void APIENTRY glNormal3hvNV (const GLhalfNV *v);
+GLAPI void APIENTRY glColor3hNV (GLhalfNV red, GLhalfNV green, GLhalfNV blue);
+GLAPI void APIENTRY glColor3hvNV (const GLhalfNV *v);
+GLAPI void APIENTRY glColor4hNV (GLhalfNV red, GLhalfNV green, GLhalfNV blue, GLhalfNV alpha);
+GLAPI void APIENTRY glColor4hvNV (const GLhalfNV *v);
+GLAPI void APIENTRY glTexCoord1hNV (GLhalfNV s);
+GLAPI void APIENTRY glTexCoord1hvNV (const GLhalfNV *v);
+GLAPI void APIENTRY glTexCoord2hNV (GLhalfNV s, GLhalfNV t);
+GLAPI void APIENTRY glTexCoord2hvNV (const GLhalfNV *v);
+GLAPI void APIENTRY glTexCoord3hNV (GLhalfNV s, GLhalfNV t, GLhalfNV r);
+GLAPI void APIENTRY glTexCoord3hvNV (const GLhalfNV *v);
+GLAPI void APIENTRY glTexCoord4hNV (GLhalfNV s, GLhalfNV t, GLhalfNV r, GLhalfNV q);
+GLAPI void APIENTRY glTexCoord4hvNV (const GLhalfNV *v);
+GLAPI void APIENTRY glMultiTexCoord1hNV (GLenum target, GLhalfNV s);
+GLAPI void APIENTRY glMultiTexCoord1hvNV (GLenum target, const GLhalfNV *v);
+GLAPI void APIENTRY glMultiTexCoord2hNV (GLenum target, GLhalfNV s, GLhalfNV t);
+GLAPI void APIENTRY glMultiTexCoord2hvNV (GLenum target, const GLhalfNV *v);
+GLAPI void APIENTRY glMultiTexCoord3hNV (GLenum target, GLhalfNV s, GLhalfNV t, GLhalfNV r);
+GLAPI void APIENTRY glMultiTexCoord3hvNV (GLenum target, const GLhalfNV *v);
+GLAPI void APIENTRY glMultiTexCoord4hNV (GLenum target, GLhalfNV s, GLhalfNV t, GLhalfNV r, GLhalfNV q);
+GLAPI void APIENTRY glMultiTexCoord4hvNV (GLenum target, const GLhalfNV *v);
+GLAPI void APIENTRY glFogCoordhNV (GLhalfNV fog);
+GLAPI void APIENTRY glFogCoordhvNV (const GLhalfNV *fog);
+GLAPI void APIENTRY glSecondaryColor3hNV (GLhalfNV red, GLhalfNV green, GLhalfNV blue);
+GLAPI void APIENTRY glSecondaryColor3hvNV (const GLhalfNV *v);
+GLAPI void APIENTRY glVertexWeighthNV (GLhalfNV weight);
+GLAPI void APIENTRY glVertexWeighthvNV (const GLhalfNV *weight);
+GLAPI void APIENTRY glVertexAttrib1hNV (GLuint index, GLhalfNV x);
+GLAPI void APIENTRY glVertexAttrib1hvNV (GLuint index, const GLhalfNV *v);
+GLAPI void APIENTRY glVertexAttrib2hNV (GLuint index, GLhalfNV x, GLhalfNV y);
+GLAPI void APIENTRY glVertexAttrib2hvNV (GLuint index, const GLhalfNV *v);
+GLAPI void APIENTRY glVertexAttrib3hNV (GLuint index, GLhalfNV x, GLhalfNV y, GLhalfNV z);
+GLAPI void APIENTRY glVertexAttrib3hvNV (GLuint index, const GLhalfNV *v);
+GLAPI void APIENTRY glVertexAttrib4hNV (GLuint index, GLhalfNV x, GLhalfNV y, GLhalfNV z, GLhalfNV w);
+GLAPI void APIENTRY glVertexAttrib4hvNV (GLuint index, const GLhalfNV *v);
+GLAPI void APIENTRY glVertexAttribs1hvNV (GLuint index, GLsizei n, const GLhalfNV *v);
+GLAPI void APIENTRY glVertexAttribs2hvNV (GLuint index, GLsizei n, const GLhalfNV *v);
+GLAPI void APIENTRY glVertexAttribs3hvNV (GLuint index, GLsizei n, const GLhalfNV *v);
+GLAPI void APIENTRY glVertexAttribs4hvNV (GLuint index, GLsizei n, const GLhalfNV *v);
+#endif
+typedef void (APIENTRYP PFNGLVERTEX2HNVPROC) (GLhalfNV x, GLhalfNV y);
+typedef void (APIENTRYP PFNGLVERTEX2HVNVPROC) (const GLhalfNV *v);
+typedef void (APIENTRYP PFNGLVERTEX3HNVPROC) (GLhalfNV x, GLhalfNV y, GLhalfNV z);
+typedef void (APIENTRYP PFNGLVERTEX3HVNVPROC) (const GLhalfNV *v);
+typedef void (APIENTRYP PFNGLVERTEX4HNVPROC) (GLhalfNV x, GLhalfNV y, GLhalfNV z, GLhalfNV w);
+typedef void (APIENTRYP PFNGLVERTEX4HVNVPROC) (const GLhalfNV *v);
+typedef void (APIENTRYP PFNGLNORMAL3HNVPROC) (GLhalfNV nx, GLhalfNV ny, GLhalfNV nz);
+typedef void (APIENTRYP PFNGLNORMAL3HVNVPROC) (const GLhalfNV *v);
+typedef void (APIENTRYP PFNGLCOLOR3HNVPROC) (GLhalfNV red, GLhalfNV green, GLhalfNV blue);
+typedef void (APIENTRYP PFNGLCOLOR3HVNVPROC) (const GLhalfNV *v);
+typedef void (APIENTRYP PFNGLCOLOR4HNVPROC) (GLhalfNV red, GLhalfNV green, GLhalfNV blue, GLhalfNV alpha);
+typedef void (APIENTRYP PFNGLCOLOR4HVNVPROC) (const GLhalfNV *v);
+typedef void (APIENTRYP PFNGLTEXCOORD1HNVPROC) (GLhalfNV s);
+typedef void (APIENTRYP PFNGLTEXCOORD1HVNVPROC) (const GLhalfNV *v);
+typedef void (APIENTRYP PFNGLTEXCOORD2HNVPROC) (GLhalfNV s, GLhalfNV t);
+typedef void (APIENTRYP PFNGLTEXCOORD2HVNVPROC) (const GLhalfNV *v);
+typedef void (APIENTRYP PFNGLTEXCOORD3HNVPROC) (GLhalfNV s, GLhalfNV t, GLhalfNV r);
+typedef void (APIENTRYP PFNGLTEXCOORD3HVNVPROC) (const GLhalfNV *v);
+typedef void (APIENTRYP PFNGLTEXCOORD4HNVPROC) (GLhalfNV s, GLhalfNV t, GLhalfNV r, GLhalfNV q);
+typedef void (APIENTRYP PFNGLTEXCOORD4HVNVPROC) (const GLhalfNV *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD1HNVPROC) (GLenum target, GLhalfNV s);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD1HVNVPROC) (GLenum target, const GLhalfNV *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD2HNVPROC) (GLenum target, GLhalfNV s, GLhalfNV t);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD2HVNVPROC) (GLenum target, const GLhalfNV *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD3HNVPROC) (GLenum target, GLhalfNV s, GLhalfNV t, GLhalfNV r);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD3HVNVPROC) (GLenum target, const GLhalfNV *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD4HNVPROC) (GLenum target, GLhalfNV s, GLhalfNV t, GLhalfNV r, GLhalfNV q);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD4HVNVPROC) (GLenum target, const GLhalfNV *v);
+typedef void (APIENTRYP PFNGLFOGCOORDHNVPROC) (GLhalfNV fog);
+typedef void (APIENTRYP PFNGLFOGCOORDHVNVPROC) (const GLhalfNV *fog);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3HNVPROC) (GLhalfNV red, GLhalfNV green, GLhalfNV blue);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3HVNVPROC) (const GLhalfNV *v);
+typedef void (APIENTRYP PFNGLVERTEXWEIGHTHNVPROC) (GLhalfNV weight);
+typedef void (APIENTRYP PFNGLVERTEXWEIGHTHVNVPROC) (const GLhalfNV *weight);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB1HNVPROC) (GLuint index, GLhalfNV x);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB1HVNVPROC) (GLuint index, const GLhalfNV *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB2HNVPROC) (GLuint index, GLhalfNV x, GLhalfNV y);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB2HVNVPROC) (GLuint index, const GLhalfNV *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB3HNVPROC) (GLuint index, GLhalfNV x, GLhalfNV y, GLhalfNV z);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB3HVNVPROC) (GLuint index, const GLhalfNV *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4HNVPROC) (GLuint index, GLhalfNV x, GLhalfNV y, GLhalfNV z, GLhalfNV w);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4HVNVPROC) (GLuint index, const GLhalfNV *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBS1HVNVPROC) (GLuint index, GLsizei n, const GLhalfNV *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBS2HVNVPROC) (GLuint index, GLsizei n, const GLhalfNV *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBS3HVNVPROC) (GLuint index, GLsizei n, const GLhalfNV *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBS4HVNVPROC) (GLuint index, GLsizei n, const GLhalfNV *v);
+#endif
+
+#ifndef GL_NV_pixel_data_range
+#define GL_NV_pixel_data_range 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glPixelDataRangeNV (GLenum target, GLsizei length, GLvoid *pointer);
+GLAPI void APIENTRY glFlushPixelDataRangeNV (GLenum target);
+#endif
+typedef void (APIENTRYP PFNGLPIXELDATARANGENVPROC) (GLenum target, GLsizei length, GLvoid *pointer);
+typedef void (APIENTRYP PFNGLFLUSHPIXELDATARANGENVPROC) (GLenum target);
+#endif
+
+#ifndef GL_NV_primitive_restart
+#define GL_NV_primitive_restart 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glPrimitiveRestartNV (void);
+GLAPI void APIENTRY glPrimitiveRestartIndexNV (GLuint index);
+#endif
+typedef void (APIENTRYP PFNGLPRIMITIVERESTARTNVPROC) (void);
+typedef void (APIENTRYP PFNGLPRIMITIVERESTARTINDEXNVPROC) (GLuint index);
+#endif
+
+#ifndef GL_NV_texture_expand_normal
+#define GL_NV_texture_expand_normal 1
+#endif
+
+#ifndef GL_NV_vertex_program2
+#define GL_NV_vertex_program2 1
+#endif
+
+#ifndef GL_ATI_map_object_buffer
+#define GL_ATI_map_object_buffer 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI GLvoid* APIENTRY glMapObjectBufferATI (GLuint buffer);
+GLAPI void APIENTRY glUnmapObjectBufferATI (GLuint buffer);
+#endif
+typedef GLvoid* (APIENTRYP PFNGLMAPOBJECTBUFFERATIPROC) (GLuint buffer);
+typedef void (APIENTRYP PFNGLUNMAPOBJECTBUFFERATIPROC) (GLuint buffer);
+#endif
+
+#ifndef GL_ATI_separate_stencil
+#define GL_ATI_separate_stencil 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glStencilOpSeparateATI (GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass);
+GLAPI void APIENTRY glStencilFuncSeparateATI (GLenum frontfunc, GLenum backfunc, GLint ref, GLuint mask);
+#endif
+typedef void (APIENTRYP PFNGLSTENCILOPSEPARATEATIPROC) (GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass);
+typedef void (APIENTRYP PFNGLSTENCILFUNCSEPARATEATIPROC) (GLenum frontfunc, GLenum backfunc, GLint ref, GLuint mask);
+#endif
+
+#ifndef GL_ATI_vertex_attrib_array_object
+#define GL_ATI_vertex_attrib_array_object 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glVertexAttribArrayObjectATI (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, GLuint buffer, GLuint offset);
+GLAPI void APIENTRY glGetVertexAttribArrayObjectfvATI (GLuint index, GLenum pname, GLfloat *params);
+GLAPI void APIENTRY glGetVertexAttribArrayObjectivATI (GLuint index, GLenum pname, GLint *params);
+#endif
+typedef void (APIENTRYP PFNGLVERTEXATTRIBARRAYOBJECTATIPROC) (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, GLuint buffer, GLuint offset);
+typedef void (APIENTRYP PFNGLGETVERTEXATTRIBARRAYOBJECTFVATIPROC) (GLuint index, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETVERTEXATTRIBARRAYOBJECTIVATIPROC) (GLuint index, GLenum pname, GLint *params);
+#endif
+
+#ifndef GL_OES_read_format
+#define GL_OES_read_format 1
+#endif
+
+#ifndef GL_EXT_depth_bounds_test
+#define GL_EXT_depth_bounds_test 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glDepthBoundsEXT (GLclampd zmin, GLclampd zmax);
+#endif
+typedef void (APIENTRYP PFNGLDEPTHBOUNDSEXTPROC) (GLclampd zmin, GLclampd zmax);
+#endif
+
+#ifndef GL_EXT_texture_mirror_clamp
+#define GL_EXT_texture_mirror_clamp 1
+#endif
+
+#ifndef GL_EXT_blend_equation_separate
+#define GL_EXT_blend_equation_separate 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glBlendEquationSeparateEXT (GLenum modeRGB, GLenum modeAlpha);
+#endif
+typedef void (APIENTRYP PFNGLBLENDEQUATIONSEPARATEEXTPROC) (GLenum modeRGB, GLenum modeAlpha);
+#endif
+
+#ifndef GL_MESA_pack_invert
+#define GL_MESA_pack_invert 1
+#endif
+
+#ifndef GL_MESA_ycbcr_texture
+#define GL_MESA_ycbcr_texture 1
+#endif
+
+#ifndef GL_EXT_pixel_buffer_object
+#define GL_EXT_pixel_buffer_object 1
+#endif
+
+#ifndef GL_NV_fragment_program_option
+#define GL_NV_fragment_program_option 1
+#endif
+
+#ifndef GL_NV_fragment_program2
+#define GL_NV_fragment_program2 1
+#endif
+
+#ifndef GL_NV_vertex_program2_option
+#define GL_NV_vertex_program2_option 1
+#endif
+
+#ifndef GL_NV_vertex_program3
+#define GL_NV_vertex_program3 1
+#endif
+
+#ifndef GL_EXT_framebuffer_object
+#define GL_EXT_framebuffer_object 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI GLboolean APIENTRY glIsRenderbufferEXT (GLuint renderbuffer);
+GLAPI void APIENTRY glBindRenderbufferEXT (GLenum target, GLuint renderbuffer);
+GLAPI void APIENTRY glDeleteRenderbuffersEXT (GLsizei n, const GLuint *renderbuffers);
+GLAPI void APIENTRY glGenRenderbuffersEXT (GLsizei n, GLuint *renderbuffers);
+GLAPI void APIENTRY glRenderbufferStorageEXT (GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
+GLAPI void APIENTRY glGetRenderbufferParameterivEXT (GLenum target, GLenum pname, GLint *params);
+GLAPI GLboolean APIENTRY glIsFramebufferEXT (GLuint framebuffer);
+GLAPI void APIENTRY glBindFramebufferEXT (GLenum target, GLuint framebuffer);
+GLAPI void APIENTRY glDeleteFramebuffersEXT (GLsizei n, const GLuint *framebuffers);
+GLAPI void APIENTRY glGenFramebuffersEXT (GLsizei n, GLuint *framebuffers);
+GLAPI GLenum APIENTRY glCheckFramebufferStatusEXT (GLenum target);
+GLAPI void APIENTRY glFramebufferTexture1DEXT (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
+GLAPI void APIENTRY glFramebufferTexture2DEXT (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
+GLAPI void APIENTRY glFramebufferTexture3DEXT (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset);
+GLAPI void APIENTRY glFramebufferRenderbufferEXT (GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer);
+GLAPI void APIENTRY glGetFramebufferAttachmentParameterivEXT (GLenum target, GLenum attachment, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGenerateMipmapEXT (GLenum target);
+#endif
+typedef GLboolean (APIENTRYP PFNGLISRENDERBUFFEREXTPROC) (GLuint renderbuffer);
+typedef void (APIENTRYP PFNGLBINDRENDERBUFFEREXTPROC) (GLenum target, GLuint renderbuffer);
+typedef void (APIENTRYP PFNGLDELETERENDERBUFFERSEXTPROC) (GLsizei n, const GLuint *renderbuffers);
+typedef void (APIENTRYP PFNGLGENRENDERBUFFERSEXTPROC) (GLsizei n, GLuint *renderbuffers);
+typedef void (APIENTRYP PFNGLRENDERBUFFERSTORAGEEXTPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
+typedef void (APIENTRYP PFNGLGETRENDERBUFFERPARAMETERIVEXTPROC) (GLenum target, GLenum pname, GLint *params);
+typedef GLboolean (APIENTRYP PFNGLISFRAMEBUFFEREXTPROC) (GLuint framebuffer);
+typedef void (APIENTRYP PFNGLBINDFRAMEBUFFEREXTPROC) (GLenum target, GLuint framebuffer);
+typedef void (APIENTRYP PFNGLDELETEFRAMEBUFFERSEXTPROC) (GLsizei n, const GLuint *framebuffers);
+typedef void (APIENTRYP PFNGLGENFRAMEBUFFERSEXTPROC) (GLsizei n, GLuint *framebuffers);
+typedef GLenum (APIENTRYP PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC) (GLenum target);
+typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTURE1DEXTPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
+typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTURE2DEXTPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
+typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTURE3DEXTPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset);
+typedef void (APIENTRYP PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC) (GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer);
+typedef void (APIENTRYP PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC) (GLenum target, GLenum attachment, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGENERATEMIPMAPEXTPROC) (GLenum target);
+#endif
+
+#ifndef GL_GREMEDY_string_marker
+#define GL_GREMEDY_string_marker 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glStringMarkerGREMEDY (GLsizei len, const GLvoid *string);
+#endif
+typedef void (APIENTRYP PFNGLSTRINGMARKERGREMEDYPROC) (GLsizei len, const GLvoid *string);
+#endif
+
+#ifndef GL_EXT_packed_depth_stencil
+#define GL_EXT_packed_depth_stencil 1
+#endif
+
+#ifndef GL_EXT_stencil_clear_tag
+#define GL_EXT_stencil_clear_tag 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glStencilClearTagEXT (GLsizei stencilTagBits, GLuint stencilClearTag);
+#endif
+typedef void (APIENTRYP PFNGLSTENCILCLEARTAGEXTPROC) (GLsizei stencilTagBits, GLuint stencilClearTag);
+#endif
+
+#ifndef GL_EXT_texture_sRGB
+#define GL_EXT_texture_sRGB 1
+#endif
+
+#ifndef GL_EXT_framebuffer_blit
+#define GL_EXT_framebuffer_blit 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glBlitFramebufferEXT (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter);
+#endif
+typedef void (APIENTRYP PFNGLBLITFRAMEBUFFEREXTPROC) (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter);
+#endif
+
+#ifndef GL_EXT_framebuffer_multisample
+#define GL_EXT_framebuffer_multisample 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glRenderbufferStorageMultisampleEXT (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
+#endif
+typedef void (APIENTRYP PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
+#endif
+
+#ifndef GL_MESAX_texture_stack
+#define GL_MESAX_texture_stack 1
+#endif
+
+#ifndef GL_EXT_timer_query
+#define GL_EXT_timer_query 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glGetQueryObjecti64vEXT (GLuint id, GLenum pname, GLint64EXT *params);
+GLAPI void APIENTRY glGetQueryObjectui64vEXT (GLuint id, GLenum pname, GLuint64EXT *params);
+#endif
+typedef void (APIENTRYP PFNGLGETQUERYOBJECTI64VEXTPROC) (GLuint id, GLenum pname, GLint64EXT *params);
+typedef void (APIENTRYP PFNGLGETQUERYOBJECTUI64VEXTPROC) (GLuint id, GLenum pname, GLuint64EXT *params);
+#endif
+
+#ifndef GL_EXT_gpu_program_parameters
+#define GL_EXT_gpu_program_parameters 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glProgramEnvParameters4fvEXT (GLenum target, GLuint index, GLsizei count, const GLfloat *params);
+GLAPI void APIENTRY glProgramLocalParameters4fvEXT (GLenum target, GLuint index, GLsizei count, const GLfloat *params);
+#endif
+typedef void (APIENTRYP PFNGLPROGRAMENVPARAMETERS4FVEXTPROC) (GLenum target, GLuint index, GLsizei count, const GLfloat *params);
+typedef void (APIENTRYP PFNGLPROGRAMLOCALPARAMETERS4FVEXTPROC) (GLenum target, GLuint index, GLsizei count, const GLfloat *params);
+#endif
+
+#ifndef GL_APPLE_flush_buffer_range
+#define GL_APPLE_flush_buffer_range 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glBufferParameteriAPPLE (GLenum target, GLenum pname, GLint param);
+GLAPI void APIENTRY glFlushMappedBufferRangeAPPLE (GLenum target, GLintptr offset, GLsizeiptr size);
+#endif
+typedef void (APIENTRYP PFNGLBUFFERPARAMETERIAPPLEPROC) (GLenum target, GLenum pname, GLint param);
+typedef void (APIENTRYP PFNGLFLUSHMAPPEDBUFFERRANGEAPPLEPROC) (GLenum target, GLintptr offset, GLsizeiptr size);
+#endif
+
+#ifndef GL_NV_gpu_program4
+#define GL_NV_gpu_program4 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glProgramLocalParameterI4iNV (GLenum target, GLuint index, GLint x, GLint y, GLint z, GLint w);
+GLAPI void APIENTRY glProgramLocalParameterI4ivNV (GLenum target, GLuint index, const GLint *params);
+GLAPI void APIENTRY glProgramLocalParametersI4ivNV (GLenum target, GLuint index, GLsizei count, const GLint *params);
+GLAPI void APIENTRY glProgramLocalParameterI4uiNV (GLenum target, GLuint index, GLuint x, GLuint y, GLuint z, GLuint w);
+GLAPI void APIENTRY glProgramLocalParameterI4uivNV (GLenum target, GLuint index, const GLuint *params);
+GLAPI void APIENTRY glProgramLocalParametersI4uivNV (GLenum target, GLuint index, GLsizei count, const GLuint *params);
+GLAPI void APIENTRY glProgramEnvParameterI4iNV (GLenum target, GLuint index, GLint x, GLint y, GLint z, GLint w);
+GLAPI void APIENTRY glProgramEnvParameterI4ivNV (GLenum target, GLuint index, const GLint *params);
+GLAPI void APIENTRY glProgramEnvParametersI4ivNV (GLenum target, GLuint index, GLsizei count, const GLint *params);
+GLAPI void APIENTRY glProgramEnvParameterI4uiNV (GLenum target, GLuint index, GLuint x, GLuint y, GLuint z, GLuint w);
+GLAPI void APIENTRY glProgramEnvParameterI4uivNV (GLenum target, GLuint index, const GLuint *params);
+GLAPI void APIENTRY glProgramEnvParametersI4uivNV (GLenum target, GLuint index, GLsizei count, const GLuint *params);
+GLAPI void APIENTRY glGetProgramLocalParameterIivNV (GLenum target, GLuint index, GLint *params);
+GLAPI void APIENTRY glGetProgramLocalParameterIuivNV (GLenum target, GLuint index, GLuint *params);
+GLAPI void APIENTRY glGetProgramEnvParameterIivNV (GLenum target, GLuint index, GLint *params);
+GLAPI void APIENTRY glGetProgramEnvParameterIuivNV (GLenum target, GLuint index, GLuint *params);
+#endif
+typedef void (APIENTRYP PFNGLPROGRAMLOCALPARAMETERI4INVPROC) (GLenum target, GLuint index, GLint x, GLint y, GLint z, GLint w);
+typedef void (APIENTRYP PFNGLPROGRAMLOCALPARAMETERI4IVNVPROC) (GLenum target, GLuint index, const GLint *params);
+typedef void (APIENTRYP PFNGLPROGRAMLOCALPARAMETERSI4IVNVPROC) (GLenum target, GLuint index, GLsizei count, const GLint *params);
+typedef void (APIENTRYP PFNGLPROGRAMLOCALPARAMETERI4UINVPROC) (GLenum target, GLuint index, GLuint x, GLuint y, GLuint z, GLuint w);
+typedef void (APIENTRYP PFNGLPROGRAMLOCALPARAMETERI4UIVNVPROC) (GLenum target, GLuint index, const GLuint *params);
+typedef void (APIENTRYP PFNGLPROGRAMLOCALPARAMETERSI4UIVNVPROC) (GLenum target, GLuint index, GLsizei count, const GLuint *params);
+typedef void (APIENTRYP PFNGLPROGRAMENVPARAMETERI4INVPROC) (GLenum target, GLuint index, GLint x, GLint y, GLint z, GLint w);
+typedef void (APIENTRYP PFNGLPROGRAMENVPARAMETERI4IVNVPROC) (GLenum target, GLuint index, const GLint *params);
+typedef void (APIENTRYP PFNGLPROGRAMENVPARAMETERSI4IVNVPROC) (GLenum target, GLuint index, GLsizei count, const GLint *params);
+typedef void (APIENTRYP PFNGLPROGRAMENVPARAMETERI4UINVPROC) (GLenum target, GLuint index, GLuint x, GLuint y, GLuint z, GLuint w);
+typedef void (APIENTRYP PFNGLPROGRAMENVPARAMETERI4UIVNVPROC) (GLenum target, GLuint index, const GLuint *params);
+typedef void (APIENTRYP PFNGLPROGRAMENVPARAMETERSI4UIVNVPROC) (GLenum target, GLuint index, GLsizei count, const GLuint *params);
+typedef void (APIENTRYP PFNGLGETPROGRAMLOCALPARAMETERIIVNVPROC) (GLenum target, GLuint index, GLint *params);
+typedef void (APIENTRYP PFNGLGETPROGRAMLOCALPARAMETERIUIVNVPROC) (GLenum target, GLuint index, GLuint *params);
+typedef void (APIENTRYP PFNGLGETPROGRAMENVPARAMETERIIVNVPROC) (GLenum target, GLuint index, GLint *params);
+typedef void (APIENTRYP PFNGLGETPROGRAMENVPARAMETERIUIVNVPROC) (GLenum target, GLuint index, GLuint *params);
+#endif
+
+#ifndef GL_NV_geometry_program4
+#define GL_NV_geometry_program4 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glProgramVertexLimitNV (GLenum target, GLint limit);
+GLAPI void APIENTRY glFramebufferTextureEXT (GLenum target, GLenum attachment, GLuint texture, GLint level);
+GLAPI void APIENTRY glFramebufferTextureLayerEXT (GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer);
+GLAPI void APIENTRY glFramebufferTextureFaceEXT (GLenum target, GLenum attachment, GLuint texture, GLint level, GLenum face);
+#endif
+typedef void (APIENTRYP PFNGLPROGRAMVERTEXLIMITNVPROC) (GLenum target, GLint limit);
+typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTUREEXTPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level);
+typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTURELAYEREXTPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer);
+typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTUREFACEEXTPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level, GLenum face);
+#endif
+
+#ifndef GL_EXT_geometry_shader4
+#define GL_EXT_geometry_shader4 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glProgramParameteriEXT (GLuint program, GLenum pname, GLint value);
+#endif
+typedef void (APIENTRYP PFNGLPROGRAMPARAMETERIEXTPROC) (GLuint program, GLenum pname, GLint value);
+#endif
+
+#ifndef GL_NV_vertex_program4
+#define GL_NV_vertex_program4 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glVertexAttribI1iEXT (GLuint index, GLint x);
+GLAPI void APIENTRY glVertexAttribI2iEXT (GLuint index, GLint x, GLint y);
+GLAPI void APIENTRY glVertexAttribI3iEXT (GLuint index, GLint x, GLint y, GLint z);
+GLAPI void APIENTRY glVertexAttribI4iEXT (GLuint index, GLint x, GLint y, GLint z, GLint w);
+GLAPI void APIENTRY glVertexAttribI1uiEXT (GLuint index, GLuint x);
+GLAPI void APIENTRY glVertexAttribI2uiEXT (GLuint index, GLuint x, GLuint y);
+GLAPI void APIENTRY glVertexAttribI3uiEXT (GLuint index, GLuint x, GLuint y, GLuint z);
+GLAPI void APIENTRY glVertexAttribI4uiEXT (GLuint index, GLuint x, GLuint y, GLuint z, GLuint w);
+GLAPI void APIENTRY glVertexAttribI1ivEXT (GLuint index, const GLint *v);
+GLAPI void APIENTRY glVertexAttribI2ivEXT (GLuint index, const GLint *v);
+GLAPI void APIENTRY glVertexAttribI3ivEXT (GLuint index, const GLint *v);
+GLAPI void APIENTRY glVertexAttribI4ivEXT (GLuint index, const GLint *v);
+GLAPI void APIENTRY glVertexAttribI1uivEXT (GLuint index, const GLuint *v);
+GLAPI void APIENTRY glVertexAttribI2uivEXT (GLuint index, const GLuint *v);
+GLAPI void APIENTRY glVertexAttribI3uivEXT (GLuint index, const GLuint *v);
+GLAPI void APIENTRY glVertexAttribI4uivEXT (GLuint index, const GLuint *v);
+GLAPI void APIENTRY glVertexAttribI4bvEXT (GLuint index, const GLbyte *v);
+GLAPI void APIENTRY glVertexAttribI4svEXT (GLuint index, const GLshort *v);
+GLAPI void APIENTRY glVertexAttribI4ubvEXT (GLuint index, const GLubyte *v);
+GLAPI void APIENTRY glVertexAttribI4usvEXT (GLuint index, const GLushort *v);
+GLAPI void APIENTRY glVertexAttribIPointerEXT (GLuint index, GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);
+GLAPI void APIENTRY glGetVertexAttribIivEXT (GLuint index, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetVertexAttribIuivEXT (GLuint index, GLenum pname, GLuint *params);
+#endif
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI1IEXTPROC) (GLuint index, GLint x);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI2IEXTPROC) (GLuint index, GLint x, GLint y);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI3IEXTPROC) (GLuint index, GLint x, GLint y, GLint z);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI4IEXTPROC) (GLuint index, GLint x, GLint y, GLint z, GLint w);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI1UIEXTPROC) (GLuint index, GLuint x);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI2UIEXTPROC) (GLuint index, GLuint x, GLuint y);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI3UIEXTPROC) (GLuint index, GLuint x, GLuint y, GLuint z);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI4UIEXTPROC) (GLuint index, GLuint x, GLuint y, GLuint z, GLuint w);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI1IVEXTPROC) (GLuint index, const GLint *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI2IVEXTPROC) (GLuint index, const GLint *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI3IVEXTPROC) (GLuint index, const GLint *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI4IVEXTPROC) (GLuint index, const GLint *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI1UIVEXTPROC) (GLuint index, const GLuint *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI2UIVEXTPROC) (GLuint index, const GLuint *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI3UIVEXTPROC) (GLuint index, const GLuint *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI4UIVEXTPROC) (GLuint index, const GLuint *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI4BVEXTPROC) (GLuint index, const GLbyte *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI4SVEXTPROC) (GLuint index, const GLshort *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI4UBVEXTPROC) (GLuint index, const GLubyte *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI4USVEXTPROC) (GLuint index, const GLushort *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBIPOINTEREXTPROC) (GLuint index, GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);
+typedef void (APIENTRYP PFNGLGETVERTEXATTRIBIIVEXTPROC) (GLuint index, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETVERTEXATTRIBIUIVEXTPROC) (GLuint index, GLenum pname, GLuint *params);
+#endif
+
+#ifndef GL_EXT_gpu_shader4
+#define GL_EXT_gpu_shader4 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glGetUniformuivEXT (GLuint program, GLint location, GLuint *params);
+GLAPI void APIENTRY glBindFragDataLocationEXT (GLuint program, GLuint color, const GLchar *name);
+GLAPI GLint APIENTRY glGetFragDataLocationEXT (GLuint program, const GLchar *name);
+GLAPI void APIENTRY glUniform1uiEXT (GLint location, GLuint v0);
+GLAPI void APIENTRY glUniform2uiEXT (GLint location, GLuint v0, GLuint v1);
+GLAPI void APIENTRY glUniform3uiEXT (GLint location, GLuint v0, GLuint v1, GLuint v2);
+GLAPI void APIENTRY glUniform4uiEXT (GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3);
+GLAPI void APIENTRY glUniform1uivEXT (GLint location, GLsizei count, const GLuint *value);
+GLAPI void APIENTRY glUniform2uivEXT (GLint location, GLsizei count, const GLuint *value);
+GLAPI void APIENTRY glUniform3uivEXT (GLint location, GLsizei count, const GLuint *value);
+GLAPI void APIENTRY glUniform4uivEXT (GLint location, GLsizei count, const GLuint *value);
+#endif
+typedef void (APIENTRYP PFNGLGETUNIFORMUIVEXTPROC) (GLuint program, GLint location, GLuint *params);
+typedef void (APIENTRYP PFNGLBINDFRAGDATALOCATIONEXTPROC) (GLuint program, GLuint color, const GLchar *name);
+typedef GLint (APIENTRYP PFNGLGETFRAGDATALOCATIONEXTPROC) (GLuint program, const GLchar *name);
+typedef void (APIENTRYP PFNGLUNIFORM1UIEXTPROC) (GLint location, GLuint v0);
+typedef void (APIENTRYP PFNGLUNIFORM2UIEXTPROC) (GLint location, GLuint v0, GLuint v1);
+typedef void (APIENTRYP PFNGLUNIFORM3UIEXTPROC) (GLint location, GLuint v0, GLuint v1, GLuint v2);
+typedef void (APIENTRYP PFNGLUNIFORM4UIEXTPROC) (GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3);
+typedef void (APIENTRYP PFNGLUNIFORM1UIVEXTPROC) (GLint location, GLsizei count, const GLuint *value);
+typedef void (APIENTRYP PFNGLUNIFORM2UIVEXTPROC) (GLint location, GLsizei count, const GLuint *value);
+typedef void (APIENTRYP PFNGLUNIFORM3UIVEXTPROC) (GLint location, GLsizei count, const GLuint *value);
+typedef void (APIENTRYP PFNGLUNIFORM4UIVEXTPROC) (GLint location, GLsizei count, const GLuint *value);
+#endif
+
+#ifndef GL_EXT_draw_instanced
+#define GL_EXT_draw_instanced 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glDrawArraysInstancedEXT (GLenum mode, GLint start, GLsizei count, GLsizei primcount);
+GLAPI void APIENTRY glDrawElementsInstancedEXT (GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLsizei primcount);
+#endif
+typedef void (APIENTRYP PFNGLDRAWARRAYSINSTANCEDEXTPROC) (GLenum mode, GLint start, GLsizei count, GLsizei primcount);
+typedef void (APIENTRYP PFNGLDRAWELEMENTSINSTANCEDEXTPROC) (GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLsizei primcount);
+#endif
+
+#ifndef GL_EXT_packed_float
+#define GL_EXT_packed_float 1
+#endif
+
+#ifndef GL_EXT_texture_array
+#define GL_EXT_texture_array 1
+#endif
+
+#ifndef GL_EXT_texture_buffer_object
+#define GL_EXT_texture_buffer_object 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glTexBufferEXT (GLenum target, GLenum internalformat, GLuint buffer);
+#endif
+typedef void (APIENTRYP PFNGLTEXBUFFEREXTPROC) (GLenum target, GLenum internalformat, GLuint buffer);
+#endif
+
+#ifndef GL_EXT_texture_compression_latc
+#define GL_EXT_texture_compression_latc 1
+#endif
+
+#ifndef GL_EXT_texture_compression_rgtc
+#define GL_EXT_texture_compression_rgtc 1
+#endif
+
+#ifndef GL_EXT_texture_shared_exponent
+#define GL_EXT_texture_shared_exponent 1
+#endif
+
+#ifndef GL_NV_depth_buffer_float
+#define GL_NV_depth_buffer_float 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glDepthRangedNV (GLdouble zNear, GLdouble zFar);
+GLAPI void APIENTRY glClearDepthdNV (GLdouble depth);
+GLAPI void APIENTRY glDepthBoundsdNV (GLdouble zmin, GLdouble zmax);
+#endif
+typedef void (APIENTRYP PFNGLDEPTHRANGEDNVPROC) (GLdouble zNear, GLdouble zFar);
+typedef void (APIENTRYP PFNGLCLEARDEPTHDNVPROC) (GLdouble depth);
+typedef void (APIENTRYP PFNGLDEPTHBOUNDSDNVPROC) (GLdouble zmin, GLdouble zmax);
+#endif
+
+#ifndef GL_NV_fragment_program4
+#define GL_NV_fragment_program4 1
+#endif
+
+#ifndef GL_NV_framebuffer_multisample_coverage
+#define GL_NV_framebuffer_multisample_coverage 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glRenderbufferStorageMultisampleCoverageNV (GLenum target, GLsizei coverageSamples, GLsizei colorSamples, GLenum internalformat, GLsizei width, GLsizei height);
+#endif
+typedef void (APIENTRYP PFNGLRENDERBUFFERSTORAGEMULTISAMPLECOVERAGENVPROC) (GLenum target, GLsizei coverageSamples, GLsizei colorSamples, GLenum internalformat, GLsizei width, GLsizei height);
+#endif
+
+#ifndef GL_EXT_framebuffer_sRGB
+#define GL_EXT_framebuffer_sRGB 1
+#endif
+
+#ifndef GL_NV_geometry_shader4
+#define GL_NV_geometry_shader4 1
+#endif
+
+#ifndef GL_NV_parameter_buffer_object
+#define GL_NV_parameter_buffer_object 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glProgramBufferParametersfvNV (GLenum target, GLuint buffer, GLuint index, GLsizei count, const GLfloat *params);
+GLAPI void APIENTRY glProgramBufferParametersIivNV (GLenum target, GLuint buffer, GLuint index, GLsizei count, const GLint *params);
+GLAPI void APIENTRY glProgramBufferParametersIuivNV (GLenum target, GLuint buffer, GLuint index, GLsizei count, const GLuint *params);
+#endif
+typedef void (APIENTRYP PFNGLPROGRAMBUFFERPARAMETERSFVNVPROC) (GLenum target, GLuint buffer, GLuint index, GLsizei count, const GLfloat *params);
+typedef void (APIENTRYP PFNGLPROGRAMBUFFERPARAMETERSIIVNVPROC) (GLenum target, GLuint buffer, GLuint index, GLsizei count, const GLint *params);
+typedef void (APIENTRYP PFNGLPROGRAMBUFFERPARAMETERSIUIVNVPROC) (GLenum target, GLuint buffer, GLuint index, GLsizei count, const GLuint *params);
+#endif
+
+#ifndef GL_EXT_draw_buffers2
+#define GL_EXT_draw_buffers2 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glColorMaskIndexedEXT (GLuint index, GLboolean r, GLboolean g, GLboolean b, GLboolean a);
+GLAPI void APIENTRY glGetBooleanIndexedvEXT (GLenum target, GLuint index, GLboolean *data);
+GLAPI void APIENTRY glGetIntegerIndexedvEXT (GLenum target, GLuint index, GLint *data);
+GLAPI void APIENTRY glEnableIndexedEXT (GLenum target, GLuint index);
+GLAPI void APIENTRY glDisableIndexedEXT (GLenum target, GLuint index);
+GLAPI GLboolean APIENTRY glIsEnabledIndexedEXT (GLenum target, GLuint index);
+#endif
+typedef void (APIENTRYP PFNGLCOLORMASKINDEXEDEXTPROC) (GLuint index, GLboolean r, GLboolean g, GLboolean b, GLboolean a);
+typedef void (APIENTRYP PFNGLGETBOOLEANINDEXEDVEXTPROC) (GLenum target, GLuint index, GLboolean *data);
+typedef void (APIENTRYP PFNGLGETINTEGERINDEXEDVEXTPROC) (GLenum target, GLuint index, GLint *data);
+typedef void (APIENTRYP PFNGLENABLEINDEXEDEXTPROC) (GLenum target, GLuint index);
+typedef void (APIENTRYP PFNGLDISABLEINDEXEDEXTPROC) (GLenum target, GLuint index);
+typedef GLboolean (APIENTRYP PFNGLISENABLEDINDEXEDEXTPROC) (GLenum target, GLuint index);
+#endif
+
+#ifndef GL_NV_transform_feedback
+#define GL_NV_transform_feedback 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glBeginTransformFeedbackNV (GLenum primitiveMode);
+GLAPI void APIENTRY glEndTransformFeedbackNV (void);
+GLAPI void APIENTRY glTransformFeedbackAttribsNV (GLuint count, const GLint *attribs, GLenum bufferMode);
+GLAPI void APIENTRY glBindBufferRangeNV (GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size);
+GLAPI void APIENTRY glBindBufferOffsetNV (GLenum target, GLuint index, GLuint buffer, GLintptr offset);
+GLAPI void APIENTRY glBindBufferBaseNV (GLenum target, GLuint index, GLuint buffer);
+GLAPI void APIENTRY glTransformFeedbackVaryingsNV (GLuint program, GLsizei count, const GLint *locations, GLenum bufferMode);
+GLAPI void APIENTRY glActiveVaryingNV (GLuint program, const GLchar *name);
+GLAPI GLint APIENTRY glGetVaryingLocationNV (GLuint program, const GLchar *name);
+GLAPI void APIENTRY glGetActiveVaryingNV (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLsizei *size, GLenum *type, GLchar *name);
+GLAPI void APIENTRY glGetTransformFeedbackVaryingNV (GLuint program, GLuint index, GLint *location);
+GLAPI void APIENTRY glTransformFeedbackStreamAttribsNV (GLsizei count, const GLint *attribs, GLsizei nbuffers, const GLint *bufstreams, GLenum bufferMode);
+#endif
+typedef void (APIENTRYP PFNGLBEGINTRANSFORMFEEDBACKNVPROC) (GLenum primitiveMode);
+typedef void (APIENTRYP PFNGLENDTRANSFORMFEEDBACKNVPROC) (void);
+typedef void (APIENTRYP PFNGLTRANSFORMFEEDBACKATTRIBSNVPROC) (GLuint count, const GLint *attribs, GLenum bufferMode);
+typedef void (APIENTRYP PFNGLBINDBUFFERRANGENVPROC) (GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size);
+typedef void (APIENTRYP PFNGLBINDBUFFEROFFSETNVPROC) (GLenum target, GLuint index, GLuint buffer, GLintptr offset);
+typedef void (APIENTRYP PFNGLBINDBUFFERBASENVPROC) (GLenum target, GLuint index, GLuint buffer);
+typedef void (APIENTRYP PFNGLTRANSFORMFEEDBACKVARYINGSNVPROC) (GLuint program, GLsizei count, const GLint *locations, GLenum bufferMode);
+typedef void (APIENTRYP PFNGLACTIVEVARYINGNVPROC) (GLuint program, const GLchar *name);
+typedef GLint (APIENTRYP PFNGLGETVARYINGLOCATIONNVPROC) (GLuint program, const GLchar *name);
+typedef void (APIENTRYP PFNGLGETACTIVEVARYINGNVPROC) (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLsizei *size, GLenum *type, GLchar *name);
+typedef void (APIENTRYP PFNGLGETTRANSFORMFEEDBACKVARYINGNVPROC) (GLuint program, GLuint index, GLint *location);
+typedef void (APIENTRYP PFNGLTRANSFORMFEEDBACKSTREAMATTRIBSNVPROC) (GLsizei count, const GLint *attribs, GLsizei nbuffers, const GLint *bufstreams, GLenum bufferMode);
+#endif
+
+#ifndef GL_EXT_bindable_uniform
+#define GL_EXT_bindable_uniform 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glUniformBufferEXT (GLuint program, GLint location, GLuint buffer);
+GLAPI GLint APIENTRY glGetUniformBufferSizeEXT (GLuint program, GLint location);
+GLAPI GLintptr APIENTRY glGetUniformOffsetEXT (GLuint program, GLint location);
+#endif
+typedef void (APIENTRYP PFNGLUNIFORMBUFFEREXTPROC) (GLuint program, GLint location, GLuint buffer);
+typedef GLint (APIENTRYP PFNGLGETUNIFORMBUFFERSIZEEXTPROC) (GLuint program, GLint location);
+typedef GLintptr (APIENTRYP PFNGLGETUNIFORMOFFSETEXTPROC) (GLuint program, GLint location);
+#endif
+
+#ifndef GL_EXT_texture_integer
+#define GL_EXT_texture_integer 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glTexParameterIivEXT (GLenum target, GLenum pname, const GLint *params);
+GLAPI void APIENTRY glTexParameterIuivEXT (GLenum target, GLenum pname, const GLuint *params);
+GLAPI void APIENTRY glGetTexParameterIivEXT (GLenum target, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetTexParameterIuivEXT (GLenum target, GLenum pname, GLuint *params);
+GLAPI void APIENTRY glClearColorIiEXT (GLint red, GLint green, GLint blue, GLint alpha);
+GLAPI void APIENTRY glClearColorIuiEXT (GLuint red, GLuint green, GLuint blue, GLuint alpha);
+#endif
+typedef void (APIENTRYP PFNGLTEXPARAMETERIIVEXTPROC) (GLenum target, GLenum pname, const GLint *params);
+typedef void (APIENTRYP PFNGLTEXPARAMETERIUIVEXTPROC) (GLenum target, GLenum pname, const GLuint *params);
+typedef void (APIENTRYP PFNGLGETTEXPARAMETERIIVEXTPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETTEXPARAMETERIUIVEXTPROC) (GLenum target, GLenum pname, GLuint *params);
+typedef void (APIENTRYP PFNGLCLEARCOLORIIEXTPROC) (GLint red, GLint green, GLint blue, GLint alpha);
+typedef void (APIENTRYP PFNGLCLEARCOLORIUIEXTPROC) (GLuint red, GLuint green, GLuint blue, GLuint alpha);
+#endif
+
+#ifndef GL_GREMEDY_frame_terminator
+#define GL_GREMEDY_frame_terminator 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glFrameTerminatorGREMEDY (void);
+#endif
+typedef void (APIENTRYP PFNGLFRAMETERMINATORGREMEDYPROC) (void);
+#endif
+
+#ifndef GL_NV_conditional_render
+#define GL_NV_conditional_render 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glBeginConditionalRenderNV (GLuint id, GLenum mode);
+GLAPI void APIENTRY glEndConditionalRenderNV (void);
+#endif
+typedef void (APIENTRYP PFNGLBEGINCONDITIONALRENDERNVPROC) (GLuint id, GLenum mode);
+typedef void (APIENTRYP PFNGLENDCONDITIONALRENDERNVPROC) (void);
+#endif
+
+#ifndef GL_NV_present_video
+#define GL_NV_present_video 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glPresentFrameKeyedNV (GLuint video_slot, GLuint64EXT minPresentTime, GLuint beginPresentTimeId, GLuint presentDurationId, GLenum type, GLenum target0, GLuint fill0, GLuint key0, GLenum target1, GLuint fill1, GLuint key1);
+GLAPI void APIENTRY glPresentFrameDualFillNV (GLuint video_slot, GLuint64EXT minPresentTime, GLuint beginPresentTimeId, GLuint presentDurationId, GLenum type, GLenum target0, GLuint fill0, GLenum target1, GLuint fill1, GLenum target2, GLuint fill2, GLenum target3, GLuint fill3);
+GLAPI void APIENTRY glGetVideoivNV (GLuint video_slot, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetVideouivNV (GLuint video_slot, GLenum pname, GLuint *params);
+GLAPI void APIENTRY glGetVideoi64vNV (GLuint video_slot, GLenum pname, GLint64EXT *params);
+GLAPI void APIENTRY glGetVideoui64vNV (GLuint video_slot, GLenum pname, GLuint64EXT *params);
+#endif
+typedef void (APIENTRYP PFNGLPRESENTFRAMEKEYEDNVPROC) (GLuint video_slot, GLuint64EXT minPresentTime, GLuint beginPresentTimeId, GLuint presentDurationId, GLenum type, GLenum target0, GLuint fill0, GLuint key0, GLenum target1, GLuint fill1, GLuint key1);
+typedef void (APIENTRYP PFNGLPRESENTFRAMEDUALFILLNVPROC) (GLuint video_slot, GLuint64EXT minPresentTime, GLuint beginPresentTimeId, GLuint presentDurationId, GLenum type, GLenum target0, GLuint fill0, GLenum target1, GLuint fill1, GLenum target2, GLuint fill2, GLenum target3, GLuint fill3);
+typedef void (APIENTRYP PFNGLGETVIDEOIVNVPROC) (GLuint video_slot, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETVIDEOUIVNVPROC) (GLuint video_slot, GLenum pname, GLuint *params);
+typedef void (APIENTRYP PFNGLGETVIDEOI64VNVPROC) (GLuint video_slot, GLenum pname, GLint64EXT *params);
+typedef void (APIENTRYP PFNGLGETVIDEOUI64VNVPROC) (GLuint video_slot, GLenum pname, GLuint64EXT *params);
+#endif
+
+#ifndef GL_EXT_transform_feedback
+#define GL_EXT_transform_feedback 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glBeginTransformFeedbackEXT (GLenum primitiveMode);
+GLAPI void APIENTRY glEndTransformFeedbackEXT (void);
+GLAPI void APIENTRY glBindBufferRangeEXT (GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size);
+GLAPI void APIENTRY glBindBufferOffsetEXT (GLenum target, GLuint index, GLuint buffer, GLintptr offset);
+GLAPI void APIENTRY glBindBufferBaseEXT (GLenum target, GLuint index, GLuint buffer);
+GLAPI void APIENTRY glTransformFeedbackVaryingsEXT (GLuint program, GLsizei count, const GLchar* *varyings, GLenum bufferMode);
+GLAPI void APIENTRY glGetTransformFeedbackVaryingEXT (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLsizei *size, GLenum *type, GLchar *name);
+#endif
+typedef void (APIENTRYP PFNGLBEGINTRANSFORMFEEDBACKEXTPROC) (GLenum primitiveMode);
+typedef void (APIENTRYP PFNGLENDTRANSFORMFEEDBACKEXTPROC) (void);
+typedef void (APIENTRYP PFNGLBINDBUFFERRANGEEXTPROC) (GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size);
+typedef void (APIENTRYP PFNGLBINDBUFFEROFFSETEXTPROC) (GLenum target, GLuint index, GLuint buffer, GLintptr offset);
+typedef void (APIENTRYP PFNGLBINDBUFFERBASEEXTPROC) (GLenum target, GLuint index, GLuint buffer);
+typedef void (APIENTRYP PFNGLTRANSFORMFEEDBACKVARYINGSEXTPROC) (GLuint program, GLsizei count, const GLchar* *varyings, GLenum bufferMode);
+typedef void (APIENTRYP PFNGLGETTRANSFORMFEEDBACKVARYINGEXTPROC) (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLsizei *size, GLenum *type, GLchar *name);
+#endif
+
+#ifndef GL_EXT_direct_state_access
+#define GL_EXT_direct_state_access 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glClientAttribDefaultEXT (GLbitfield mask);
+GLAPI void APIENTRY glPushClientAttribDefaultEXT (GLbitfield mask);
+GLAPI void APIENTRY glMatrixLoadfEXT (GLenum mode, const GLfloat *m);
+GLAPI void APIENTRY glMatrixLoaddEXT (GLenum mode, const GLdouble *m);
+GLAPI void APIENTRY glMatrixMultfEXT (GLenum mode, const GLfloat *m);
+GLAPI void APIENTRY glMatrixMultdEXT (GLenum mode, const GLdouble *m);
+GLAPI void APIENTRY glMatrixLoadIdentityEXT (GLenum mode);
+GLAPI void APIENTRY glMatrixRotatefEXT (GLenum mode, GLfloat angle, GLfloat x, GLfloat y, GLfloat z);
+GLAPI void APIENTRY glMatrixRotatedEXT (GLenum mode, GLdouble angle, GLdouble x, GLdouble y, GLdouble z);
+GLAPI void APIENTRY glMatrixScalefEXT (GLenum mode, GLfloat x, GLfloat y, GLfloat z);
+GLAPI void APIENTRY glMatrixScaledEXT (GLenum mode, GLdouble x, GLdouble y, GLdouble z);
+GLAPI void APIENTRY glMatrixTranslatefEXT (GLenum mode, GLfloat x, GLfloat y, GLfloat z);
+GLAPI void APIENTRY glMatrixTranslatedEXT (GLenum mode, GLdouble x, GLdouble y, GLdouble z);
+GLAPI void APIENTRY glMatrixFrustumEXT (GLenum mode, GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar);
+GLAPI void APIENTRY glMatrixOrthoEXT (GLenum mode, GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar);
+GLAPI void APIENTRY glMatrixPopEXT (GLenum mode);
+GLAPI void APIENTRY glMatrixPushEXT (GLenum mode);
+GLAPI void APIENTRY glMatrixLoadTransposefEXT (GLenum mode, const GLfloat *m);
+GLAPI void APIENTRY glMatrixLoadTransposedEXT (GLenum mode, const GLdouble *m);
+GLAPI void APIENTRY glMatrixMultTransposefEXT (GLenum mode, const GLfloat *m);
+GLAPI void APIENTRY glMatrixMultTransposedEXT (GLenum mode, const GLdouble *m);
+GLAPI void APIENTRY glTextureParameterfEXT (GLuint texture, GLenum target, GLenum pname, GLfloat param);
+GLAPI void APIENTRY glTextureParameterfvEXT (GLuint texture, GLenum target, GLenum pname, const GLfloat *params);
+GLAPI void APIENTRY glTextureParameteriEXT (GLuint texture, GLenum target, GLenum pname, GLint param);
+GLAPI void APIENTRY glTextureParameterivEXT (GLuint texture, GLenum target, GLenum pname, const GLint *params);
+GLAPI void APIENTRY glTextureImage1DEXT (GLuint texture, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLenum format, GLenum type, const GLvoid *pixels);
+GLAPI void APIENTRY glTextureImage2DEXT (GLuint texture, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels);
+GLAPI void APIENTRY glTextureSubImage1DEXT (GLuint texture, GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const GLvoid *pixels);
+GLAPI void APIENTRY glTextureSubImage2DEXT (GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels);
+GLAPI void APIENTRY glCopyTextureImage1DEXT (GLuint texture, GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLint border);
+GLAPI void APIENTRY glCopyTextureImage2DEXT (GLuint texture, GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border);
+GLAPI void APIENTRY glCopyTextureSubImage1DEXT (GLuint texture, GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width);
+GLAPI void APIENTRY glCopyTextureSubImage2DEXT (GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+GLAPI void APIENTRY glGetTextureImageEXT (GLuint texture, GLenum target, GLint level, GLenum format, GLenum type, GLvoid *pixels);
+GLAPI void APIENTRY glGetTextureParameterfvEXT (GLuint texture, GLenum target, GLenum pname, GLfloat *params);
+GLAPI void APIENTRY glGetTextureParameterivEXT (GLuint texture, GLenum target, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetTextureLevelParameterfvEXT (GLuint texture, GLenum target, GLint level, GLenum pname, GLfloat *params);
+GLAPI void APIENTRY glGetTextureLevelParameterivEXT (GLuint texture, GLenum target, GLint level, GLenum pname, GLint *params);
+GLAPI void APIENTRY glTextureImage3DEXT (GLuint texture, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid *pixels);
+GLAPI void APIENTRY glTextureSubImage3DEXT (GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid *pixels);
+GLAPI void APIENTRY glCopyTextureSubImage3DEXT (GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+GLAPI void APIENTRY glMultiTexParameterfEXT (GLenum texunit, GLenum target, GLenum pname, GLfloat param);
+GLAPI void APIENTRY glMultiTexParameterfvEXT (GLenum texunit, GLenum target, GLenum pname, const GLfloat *params);
+GLAPI void APIENTRY glMultiTexParameteriEXT (GLenum texunit, GLenum target, GLenum pname, GLint param);
+GLAPI void APIENTRY glMultiTexParameterivEXT (GLenum texunit, GLenum target, GLenum pname, const GLint *params);
+GLAPI void APIENTRY glMultiTexImage1DEXT (GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLenum format, GLenum type, const GLvoid *pixels);
+GLAPI void APIENTRY glMultiTexImage2DEXT (GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels);
+GLAPI void APIENTRY glMultiTexSubImage1DEXT (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const GLvoid *pixels);
+GLAPI void APIENTRY glMultiTexSubImage2DEXT (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels);
+GLAPI void APIENTRY glCopyMultiTexImage1DEXT (GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLint border);
+GLAPI void APIENTRY glCopyMultiTexImage2DEXT (GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border);
+GLAPI void APIENTRY glCopyMultiTexSubImage1DEXT (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width);
+GLAPI void APIENTRY glCopyMultiTexSubImage2DEXT (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+GLAPI void APIENTRY glGetMultiTexImageEXT (GLenum texunit, GLenum target, GLint level, GLenum format, GLenum type, GLvoid *pixels);
+GLAPI void APIENTRY glGetMultiTexParameterfvEXT (GLenum texunit, GLenum target, GLenum pname, GLfloat *params);
+GLAPI void APIENTRY glGetMultiTexParameterivEXT (GLenum texunit, GLenum target, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetMultiTexLevelParameterfvEXT (GLenum texunit, GLenum target, GLint level, GLenum pname, GLfloat *params);
+GLAPI void APIENTRY glGetMultiTexLevelParameterivEXT (GLenum texunit, GLenum target, GLint level, GLenum pname, GLint *params);
+GLAPI void APIENTRY glMultiTexImage3DEXT (GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid *pixels);
+GLAPI void APIENTRY glMultiTexSubImage3DEXT (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid *pixels);
+GLAPI void APIENTRY glCopyMultiTexSubImage3DEXT (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+GLAPI void APIENTRY glBindMultiTextureEXT (GLenum texunit, GLenum target, GLuint texture);
+GLAPI void APIENTRY glEnableClientStateIndexedEXT (GLenum array, GLuint index);
+GLAPI void APIENTRY glDisableClientStateIndexedEXT (GLenum array, GLuint index);
+GLAPI void APIENTRY glMultiTexCoordPointerEXT (GLenum texunit, GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);
+GLAPI void APIENTRY glMultiTexEnvfEXT (GLenum texunit, GLenum target, GLenum pname, GLfloat param);
+GLAPI void APIENTRY glMultiTexEnvfvEXT (GLenum texunit, GLenum target, GLenum pname, const GLfloat *params);
+GLAPI void APIENTRY glMultiTexEnviEXT (GLenum texunit, GLenum target, GLenum pname, GLint param);
+GLAPI void APIENTRY glMultiTexEnvivEXT (GLenum texunit, GLenum target, GLenum pname, const GLint *params);
+GLAPI void APIENTRY glMultiTexGendEXT (GLenum texunit, GLenum coord, GLenum pname, GLdouble param);
+GLAPI void APIENTRY glMultiTexGendvEXT (GLenum texunit, GLenum coord, GLenum pname, const GLdouble *params);
+GLAPI void APIENTRY glMultiTexGenfEXT (GLenum texunit, GLenum coord, GLenum pname, GLfloat param);
+GLAPI void APIENTRY glMultiTexGenfvEXT (GLenum texunit, GLenum coord, GLenum pname, const GLfloat *params);
+GLAPI void APIENTRY glMultiTexGeniEXT (GLenum texunit, GLenum coord, GLenum pname, GLint param);
+GLAPI void APIENTRY glMultiTexGenivEXT (GLenum texunit, GLenum coord, GLenum pname, const GLint *params);
+GLAPI void APIENTRY glGetMultiTexEnvfvEXT (GLenum texunit, GLenum target, GLenum pname, GLfloat *params);
+GLAPI void APIENTRY glGetMultiTexEnvivEXT (GLenum texunit, GLenum target, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetMultiTexGendvEXT (GLenum texunit, GLenum coord, GLenum pname, GLdouble *params);
+GLAPI void APIENTRY glGetMultiTexGenfvEXT (GLenum texunit, GLenum coord, GLenum pname, GLfloat *params);
+GLAPI void APIENTRY glGetMultiTexGenivEXT (GLenum texunit, GLenum coord, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetFloatIndexedvEXT (GLenum target, GLuint index, GLfloat *data);
+GLAPI void APIENTRY glGetDoubleIndexedvEXT (GLenum target, GLuint index, GLdouble *data);
+GLAPI void APIENTRY glGetPointerIndexedvEXT (GLenum target, GLuint index, GLvoid* *data);
+GLAPI void APIENTRY glCompressedTextureImage3DEXT (GLuint texture, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid *bits);
+GLAPI void APIENTRY glCompressedTextureImage2DEXT (GLuint texture, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *bits);
+GLAPI void APIENTRY glCompressedTextureImage1DEXT (GLuint texture, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const GLvoid *bits);
+GLAPI void APIENTRY glCompressedTextureSubImage3DEXT (GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid *bits);
+GLAPI void APIENTRY glCompressedTextureSubImage2DEXT (GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid *bits);
+GLAPI void APIENTRY glCompressedTextureSubImage1DEXT (GLuint texture, GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const GLvoid *bits);
+GLAPI void APIENTRY glGetCompressedTextureImageEXT (GLuint texture, GLenum target, GLint lod, GLvoid *img);
+GLAPI void APIENTRY glCompressedMultiTexImage3DEXT (GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid *bits);
+GLAPI void APIENTRY glCompressedMultiTexImage2DEXT (GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *bits);
+GLAPI void APIENTRY glCompressedMultiTexImage1DEXT (GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const GLvoid *bits);
+GLAPI void APIENTRY glCompressedMultiTexSubImage3DEXT (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid *bits);
+GLAPI void APIENTRY glCompressedMultiTexSubImage2DEXT (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid *bits);
+GLAPI void APIENTRY glCompressedMultiTexSubImage1DEXT (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const GLvoid *bits);
+GLAPI void APIENTRY glGetCompressedMultiTexImageEXT (GLenum texunit, GLenum target, GLint lod, GLvoid *img);
+GLAPI void APIENTRY glNamedProgramStringEXT (GLuint program, GLenum target, GLenum format, GLsizei len, const GLvoid *string);
+GLAPI void APIENTRY glNamedProgramLocalParameter4dEXT (GLuint program, GLenum target, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+GLAPI void APIENTRY glNamedProgramLocalParameter4dvEXT (GLuint program, GLenum target, GLuint index, const GLdouble *params);
+GLAPI void APIENTRY glNamedProgramLocalParameter4fEXT (GLuint program, GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+GLAPI void APIENTRY glNamedProgramLocalParameter4fvEXT (GLuint program, GLenum target, GLuint index, const GLfloat *params);
+GLAPI void APIENTRY glGetNamedProgramLocalParameterdvEXT (GLuint program, GLenum target, GLuint index, GLdouble *params);
+GLAPI void APIENTRY glGetNamedProgramLocalParameterfvEXT (GLuint program, GLenum target, GLuint index, GLfloat *params);
+GLAPI void APIENTRY glGetNamedProgramivEXT (GLuint program, GLenum target, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetNamedProgramStringEXT (GLuint program, GLenum target, GLenum pname, GLvoid *string);
+GLAPI void APIENTRY glNamedProgramLocalParameters4fvEXT (GLuint program, GLenum target, GLuint index, GLsizei count, const GLfloat *params);
+GLAPI void APIENTRY glNamedProgramLocalParameterI4iEXT (GLuint program, GLenum target, GLuint index, GLint x, GLint y, GLint z, GLint w);
+GLAPI void APIENTRY glNamedProgramLocalParameterI4ivEXT (GLuint program, GLenum target, GLuint index, const GLint *params);
+GLAPI void APIENTRY glNamedProgramLocalParametersI4ivEXT (GLuint program, GLenum target, GLuint index, GLsizei count, const GLint *params);
+GLAPI void APIENTRY glNamedProgramLocalParameterI4uiEXT (GLuint program, GLenum target, GLuint index, GLuint x, GLuint y, GLuint z, GLuint w);
+GLAPI void APIENTRY glNamedProgramLocalParameterI4uivEXT (GLuint program, GLenum target, GLuint index, const GLuint *params);
+GLAPI void APIENTRY glNamedProgramLocalParametersI4uivEXT (GLuint program, GLenum target, GLuint index, GLsizei count, const GLuint *params);
+GLAPI void APIENTRY glGetNamedProgramLocalParameterIivEXT (GLuint program, GLenum target, GLuint index, GLint *params);
+GLAPI void APIENTRY glGetNamedProgramLocalParameterIuivEXT (GLuint program, GLenum target, GLuint index, GLuint *params);
+GLAPI void APIENTRY glTextureParameterIivEXT (GLuint texture, GLenum target, GLenum pname, const GLint *params);
+GLAPI void APIENTRY glTextureParameterIuivEXT (GLuint texture, GLenum target, GLenum pname, const GLuint *params);
+GLAPI void APIENTRY glGetTextureParameterIivEXT (GLuint texture, GLenum target, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetTextureParameterIuivEXT (GLuint texture, GLenum target, GLenum pname, GLuint *params);
+GLAPI void APIENTRY glMultiTexParameterIivEXT (GLenum texunit, GLenum target, GLenum pname, const GLint *params);
+GLAPI void APIENTRY glMultiTexParameterIuivEXT (GLenum texunit, GLenum target, GLenum pname, const GLuint *params);
+GLAPI void APIENTRY glGetMultiTexParameterIivEXT (GLenum texunit, GLenum target, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetMultiTexParameterIuivEXT (GLenum texunit, GLenum target, GLenum pname, GLuint *params);
+GLAPI void APIENTRY glProgramUniform1fEXT (GLuint program, GLint location, GLfloat v0);
+GLAPI void APIENTRY glProgramUniform2fEXT (GLuint program, GLint location, GLfloat v0, GLfloat v1);
+GLAPI void APIENTRY glProgramUniform3fEXT (GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2);
+GLAPI void APIENTRY glProgramUniform4fEXT (GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
+GLAPI void APIENTRY glProgramUniform1iEXT (GLuint program, GLint location, GLint v0);
+GLAPI void APIENTRY glProgramUniform2iEXT (GLuint program, GLint location, GLint v0, GLint v1);
+GLAPI void APIENTRY glProgramUniform3iEXT (GLuint program, GLint location, GLint v0, GLint v1, GLint v2);
+GLAPI void APIENTRY glProgramUniform4iEXT (GLuint program, GLint location, GLint v0, GLint v1, GLint v2, GLint v3);
+GLAPI void APIENTRY glProgramUniform1fvEXT (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+GLAPI void APIENTRY glProgramUniform2fvEXT (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+GLAPI void APIENTRY glProgramUniform3fvEXT (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+GLAPI void APIENTRY glProgramUniform4fvEXT (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+GLAPI void APIENTRY glProgramUniform1ivEXT (GLuint program, GLint location, GLsizei count, const GLint *value);
+GLAPI void APIENTRY glProgramUniform2ivEXT (GLuint program, GLint location, GLsizei count, const GLint *value);
+GLAPI void APIENTRY glProgramUniform3ivEXT (GLuint program, GLint location, GLsizei count, const GLint *value);
+GLAPI void APIENTRY glProgramUniform4ivEXT (GLuint program, GLint location, GLsizei count, const GLint *value);
+GLAPI void APIENTRY glProgramUniformMatrix2fvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GLAPI void APIENTRY glProgramUniformMatrix3fvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GLAPI void APIENTRY glProgramUniformMatrix4fvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GLAPI void APIENTRY glProgramUniformMatrix2x3fvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GLAPI void APIENTRY glProgramUniformMatrix3x2fvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GLAPI void APIENTRY glProgramUniformMatrix2x4fvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GLAPI void APIENTRY glProgramUniformMatrix4x2fvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GLAPI void APIENTRY glProgramUniformMatrix3x4fvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GLAPI void APIENTRY glProgramUniformMatrix4x3fvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GLAPI void APIENTRY glProgramUniform1uiEXT (GLuint program, GLint location, GLuint v0);
+GLAPI void APIENTRY glProgramUniform2uiEXT (GLuint program, GLint location, GLuint v0, GLuint v1);
+GLAPI void APIENTRY glProgramUniform3uiEXT (GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2);
+GLAPI void APIENTRY glProgramUniform4uiEXT (GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3);
+GLAPI void APIENTRY glProgramUniform1uivEXT (GLuint program, GLint location, GLsizei count, const GLuint *value);
+GLAPI void APIENTRY glProgramUniform2uivEXT (GLuint program, GLint location, GLsizei count, const GLuint *value);
+GLAPI void APIENTRY glProgramUniform3uivEXT (GLuint program, GLint location, GLsizei count, const GLuint *value);
+GLAPI void APIENTRY glProgramUniform4uivEXT (GLuint program, GLint location, GLsizei count, const GLuint *value);
+GLAPI void APIENTRY glNamedBufferDataEXT (GLuint buffer, GLsizeiptr size, const GLvoid *data, GLenum usage);
+GLAPI void APIENTRY glNamedBufferSubDataEXT (GLuint buffer, GLintptr offset, GLsizeiptr size, const GLvoid *data);
+GLAPI GLvoid* APIENTRY glMapNamedBufferEXT (GLuint buffer, GLenum access);
+GLAPI GLboolean APIENTRY glUnmapNamedBufferEXT (GLuint buffer);
+GLAPI GLvoid* APIENTRY glMapNamedBufferRangeEXT (GLuint buffer, GLintptr offset, GLsizeiptr length, GLbitfield access);
+GLAPI void APIENTRY glFlushMappedNamedBufferRangeEXT (GLuint buffer, GLintptr offset, GLsizeiptr length);
+GLAPI void APIENTRY glNamedCopyBufferSubDataEXT (GLuint readBuffer, GLuint writeBuffer, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size);
+GLAPI void APIENTRY glGetNamedBufferParameterivEXT (GLuint buffer, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetNamedBufferPointervEXT (GLuint buffer, GLenum pname, GLvoid* *params);
+GLAPI void APIENTRY glGetNamedBufferSubDataEXT (GLuint buffer, GLintptr offset, GLsizeiptr size, GLvoid *data);
+GLAPI void APIENTRY glTextureBufferEXT (GLuint texture, GLenum target, GLenum internalformat, GLuint buffer);
+GLAPI void APIENTRY glMultiTexBufferEXT (GLenum texunit, GLenum target, GLenum internalformat, GLuint buffer);
+GLAPI void APIENTRY glNamedRenderbufferStorageEXT (GLuint renderbuffer, GLenum internalformat, GLsizei width, GLsizei height);
+GLAPI void APIENTRY glGetNamedRenderbufferParameterivEXT (GLuint renderbuffer, GLenum pname, GLint *params);
+GLAPI GLenum APIENTRY glCheckNamedFramebufferStatusEXT (GLuint framebuffer, GLenum target);
+GLAPI void APIENTRY glNamedFramebufferTexture1DEXT (GLuint framebuffer, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
+GLAPI void APIENTRY glNamedFramebufferTexture2DEXT (GLuint framebuffer, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
+GLAPI void APIENTRY glNamedFramebufferTexture3DEXT (GLuint framebuffer, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset);
+GLAPI void APIENTRY glNamedFramebufferRenderbufferEXT (GLuint framebuffer, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer);
+GLAPI void APIENTRY glGetNamedFramebufferAttachmentParameterivEXT (GLuint framebuffer, GLenum attachment, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGenerateTextureMipmapEXT (GLuint texture, GLenum target);
+GLAPI void APIENTRY glGenerateMultiTexMipmapEXT (GLenum texunit, GLenum target);
+GLAPI void APIENTRY glFramebufferDrawBufferEXT (GLuint framebuffer, GLenum mode);
+GLAPI void APIENTRY glFramebufferDrawBuffersEXT (GLuint framebuffer, GLsizei n, const GLenum *bufs);
+GLAPI void APIENTRY glFramebufferReadBufferEXT (GLuint framebuffer, GLenum mode);
+GLAPI void APIENTRY glGetFramebufferParameterivEXT (GLuint framebuffer, GLenum pname, GLint *params);
+GLAPI void APIENTRY glNamedRenderbufferStorageMultisampleEXT (GLuint renderbuffer, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
+GLAPI void APIENTRY glNamedRenderbufferStorageMultisampleCoverageEXT (GLuint renderbuffer, GLsizei coverageSamples, GLsizei colorSamples, GLenum internalformat, GLsizei width, GLsizei height);
+GLAPI void APIENTRY glNamedFramebufferTextureEXT (GLuint framebuffer, GLenum attachment, GLuint texture, GLint level);
+GLAPI void APIENTRY glNamedFramebufferTextureLayerEXT (GLuint framebuffer, GLenum attachment, GLuint texture, GLint level, GLint layer);
+GLAPI void APIENTRY glNamedFramebufferTextureFaceEXT (GLuint framebuffer, GLenum attachment, GLuint texture, GLint level, GLenum face);
+GLAPI void APIENTRY glTextureRenderbufferEXT (GLuint texture, GLenum target, GLuint renderbuffer);
+GLAPI void APIENTRY glMultiTexRenderbufferEXT (GLenum texunit, GLenum target, GLuint renderbuffer);
+GLAPI void APIENTRY glProgramUniform1dEXT (GLuint program, GLint location, GLdouble x);
+GLAPI void APIENTRY glProgramUniform2dEXT (GLuint program, GLint location, GLdouble x, GLdouble y);
+GLAPI void APIENTRY glProgramUniform3dEXT (GLuint program, GLint location, GLdouble x, GLdouble y, GLdouble z);
+GLAPI void APIENTRY glProgramUniform4dEXT (GLuint program, GLint location, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+GLAPI void APIENTRY glProgramUniform1dvEXT (GLuint program, GLint location, GLsizei count, const GLdouble *value);
+GLAPI void APIENTRY glProgramUniform2dvEXT (GLuint program, GLint location, GLsizei count, const GLdouble *value);
+GLAPI void APIENTRY glProgramUniform3dvEXT (GLuint program, GLint location, GLsizei count, const GLdouble *value);
+GLAPI void APIENTRY glProgramUniform4dvEXT (GLuint program, GLint location, GLsizei count, const GLdouble *value);
+GLAPI void APIENTRY glProgramUniformMatrix2dvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+GLAPI void APIENTRY glProgramUniformMatrix3dvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+GLAPI void APIENTRY glProgramUniformMatrix4dvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+GLAPI void APIENTRY glProgramUniformMatrix2x3dvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+GLAPI void APIENTRY glProgramUniformMatrix2x4dvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+GLAPI void APIENTRY glProgramUniformMatrix3x2dvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+GLAPI void APIENTRY glProgramUniformMatrix3x4dvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+GLAPI void APIENTRY glProgramUniformMatrix4x2dvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+GLAPI void APIENTRY glProgramUniformMatrix4x3dvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+#endif
+typedef void (APIENTRYP PFNGLCLIENTATTRIBDEFAULTEXTPROC) (GLbitfield mask);
+typedef void (APIENTRYP PFNGLPUSHCLIENTATTRIBDEFAULTEXTPROC) (GLbitfield mask);
+typedef void (APIENTRYP PFNGLMATRIXLOADFEXTPROC) (GLenum mode, const GLfloat *m);
+typedef void (APIENTRYP PFNGLMATRIXLOADDEXTPROC) (GLenum mode, const GLdouble *m);
+typedef void (APIENTRYP PFNGLMATRIXMULTFEXTPROC) (GLenum mode, const GLfloat *m);
+typedef void (APIENTRYP PFNGLMATRIXMULTDEXTPROC) (GLenum mode, const GLdouble *m);
+typedef void (APIENTRYP PFNGLMATRIXLOADIDENTITYEXTPROC) (GLenum mode);
+typedef void (APIENTRYP PFNGLMATRIXROTATEFEXTPROC) (GLenum mode, GLfloat angle, GLfloat x, GLfloat y, GLfloat z);
+typedef void (APIENTRYP PFNGLMATRIXROTATEDEXTPROC) (GLenum mode, GLdouble angle, GLdouble x, GLdouble y, GLdouble z);
+typedef void (APIENTRYP PFNGLMATRIXSCALEFEXTPROC) (GLenum mode, GLfloat x, GLfloat y, GLfloat z);
+typedef void (APIENTRYP PFNGLMATRIXSCALEDEXTPROC) (GLenum mode, GLdouble x, GLdouble y, GLdouble z);
+typedef void (APIENTRYP PFNGLMATRIXTRANSLATEFEXTPROC) (GLenum mode, GLfloat x, GLfloat y, GLfloat z);
+typedef void (APIENTRYP PFNGLMATRIXTRANSLATEDEXTPROC) (GLenum mode, GLdouble x, GLdouble y, GLdouble z);
+typedef void (APIENTRYP PFNGLMATRIXFRUSTUMEXTPROC) (GLenum mode, GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar);
+typedef void (APIENTRYP PFNGLMATRIXORTHOEXTPROC) (GLenum mode, GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar);
+typedef void (APIENTRYP PFNGLMATRIXPOPEXTPROC) (GLenum mode);
+typedef void (APIENTRYP PFNGLMATRIXPUSHEXTPROC) (GLenum mode);
+typedef void (APIENTRYP PFNGLMATRIXLOADTRANSPOSEFEXTPROC) (GLenum mode, const GLfloat *m);
+typedef void (APIENTRYP PFNGLMATRIXLOADTRANSPOSEDEXTPROC) (GLenum mode, const GLdouble *m);
+typedef void (APIENTRYP PFNGLMATRIXMULTTRANSPOSEFEXTPROC) (GLenum mode, const GLfloat *m);
+typedef void (APIENTRYP PFNGLMATRIXMULTTRANSPOSEDEXTPROC) (GLenum mode, const GLdouble *m);
+typedef void (APIENTRYP PFNGLTEXTUREPARAMETERFEXTPROC) (GLuint texture, GLenum target, GLenum pname, GLfloat param);
+typedef void (APIENTRYP PFNGLTEXTUREPARAMETERFVEXTPROC) (GLuint texture, GLenum target, GLenum pname, const GLfloat *params);
+typedef void (APIENTRYP PFNGLTEXTUREPARAMETERIEXTPROC) (GLuint texture, GLenum target, GLenum pname, GLint param);
+typedef void (APIENTRYP PFNGLTEXTUREPARAMETERIVEXTPROC) (GLuint texture, GLenum target, GLenum pname, const GLint *params);
+typedef void (APIENTRYP PFNGLTEXTUREIMAGE1DEXTPROC) (GLuint texture, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLenum format, GLenum type, const GLvoid *pixels);
+typedef void (APIENTRYP PFNGLTEXTUREIMAGE2DEXTPROC) (GLuint texture, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels);
+typedef void (APIENTRYP PFNGLTEXTURESUBIMAGE1DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const GLvoid *pixels);
+typedef void (APIENTRYP PFNGLTEXTURESUBIMAGE2DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels);
+typedef void (APIENTRYP PFNGLCOPYTEXTUREIMAGE1DEXTPROC) (GLuint texture, GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLint border);
+typedef void (APIENTRYP PFNGLCOPYTEXTUREIMAGE2DEXTPROC) (GLuint texture, GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border);
+typedef void (APIENTRYP PFNGLCOPYTEXTURESUBIMAGE1DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width);
+typedef void (APIENTRYP PFNGLCOPYTEXTURESUBIMAGE2DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+typedef void (APIENTRYP PFNGLGETTEXTUREIMAGEEXTPROC) (GLuint texture, GLenum target, GLint level, GLenum format, GLenum type, GLvoid *pixels);
+typedef void (APIENTRYP PFNGLGETTEXTUREPARAMETERFVEXTPROC) (GLuint texture, GLenum target, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETTEXTUREPARAMETERIVEXTPROC) (GLuint texture, GLenum target, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETTEXTURELEVELPARAMETERFVEXTPROC) (GLuint texture, GLenum target, GLint level, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETTEXTURELEVELPARAMETERIVEXTPROC) (GLuint texture, GLenum target, GLint level, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLTEXTUREIMAGE3DEXTPROC) (GLuint texture, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid *pixels);
+typedef void (APIENTRYP PFNGLTEXTURESUBIMAGE3DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid *pixels);
+typedef void (APIENTRYP PFNGLCOPYTEXTURESUBIMAGE3DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+typedef void (APIENTRYP PFNGLMULTITEXPARAMETERFEXTPROC) (GLenum texunit, GLenum target, GLenum pname, GLfloat param);
+typedef void (APIENTRYP PFNGLMULTITEXPARAMETERFVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, const GLfloat *params);
+typedef void (APIENTRYP PFNGLMULTITEXPARAMETERIEXTPROC) (GLenum texunit, GLenum target, GLenum pname, GLint param);
+typedef void (APIENTRYP PFNGLMULTITEXPARAMETERIVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, const GLint *params);
+typedef void (APIENTRYP PFNGLMULTITEXIMAGE1DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLenum format, GLenum type, const GLvoid *pixels);
+typedef void (APIENTRYP PFNGLMULTITEXIMAGE2DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels);
+typedef void (APIENTRYP PFNGLMULTITEXSUBIMAGE1DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const GLvoid *pixels);
+typedef void (APIENTRYP PFNGLMULTITEXSUBIMAGE2DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels);
+typedef void (APIENTRYP PFNGLCOPYMULTITEXIMAGE1DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLint border);
+typedef void (APIENTRYP PFNGLCOPYMULTITEXIMAGE2DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border);
+typedef void (APIENTRYP PFNGLCOPYMULTITEXSUBIMAGE1DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width);
+typedef void (APIENTRYP PFNGLCOPYMULTITEXSUBIMAGE2DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+typedef void (APIENTRYP PFNGLGETMULTITEXIMAGEEXTPROC) (GLenum texunit, GLenum target, GLint level, GLenum format, GLenum type, GLvoid *pixels);
+typedef void (APIENTRYP PFNGLGETMULTITEXPARAMETERFVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETMULTITEXPARAMETERIVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETMULTITEXLEVELPARAMETERFVEXTPROC) (GLenum texunit, GLenum target, GLint level, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETMULTITEXLEVELPARAMETERIVEXTPROC) (GLenum texunit, GLenum target, GLint level, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLMULTITEXIMAGE3DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid *pixels);
+typedef void (APIENTRYP PFNGLMULTITEXSUBIMAGE3DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid *pixels);
+typedef void (APIENTRYP PFNGLCOPYMULTITEXSUBIMAGE3DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+typedef void (APIENTRYP PFNGLBINDMULTITEXTUREEXTPROC) (GLenum texunit, GLenum target, GLuint texture);
+typedef void (APIENTRYP PFNGLENABLECLIENTSTATEINDEXEDEXTPROC) (GLenum array, GLuint index);
+typedef void (APIENTRYP PFNGLDISABLECLIENTSTATEINDEXEDEXTPROC) (GLenum array, GLuint index);
+typedef void (APIENTRYP PFNGLMULTITEXCOORDPOINTEREXTPROC) (GLenum texunit, GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);
+typedef void (APIENTRYP PFNGLMULTITEXENVFEXTPROC) (GLenum texunit, GLenum target, GLenum pname, GLfloat param);
+typedef void (APIENTRYP PFNGLMULTITEXENVFVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, const GLfloat *params);
+typedef void (APIENTRYP PFNGLMULTITEXENVIEXTPROC) (GLenum texunit, GLenum target, GLenum pname, GLint param);
+typedef void (APIENTRYP PFNGLMULTITEXENVIVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, const GLint *params);
+typedef void (APIENTRYP PFNGLMULTITEXGENDEXTPROC) (GLenum texunit, GLenum coord, GLenum pname, GLdouble param);
+typedef void (APIENTRYP PFNGLMULTITEXGENDVEXTPROC) (GLenum texunit, GLenum coord, GLenum pname, const GLdouble *params);
+typedef void (APIENTRYP PFNGLMULTITEXGENFEXTPROC) (GLenum texunit, GLenum coord, GLenum pname, GLfloat param);
+typedef void (APIENTRYP PFNGLMULTITEXGENFVEXTPROC) (GLenum texunit, GLenum coord, GLenum pname, const GLfloat *params);
+typedef void (APIENTRYP PFNGLMULTITEXGENIEXTPROC) (GLenum texunit, GLenum coord, GLenum pname, GLint param);
+typedef void (APIENTRYP PFNGLMULTITEXGENIVEXTPROC) (GLenum texunit, GLenum coord, GLenum pname, const GLint *params);
+typedef void (APIENTRYP PFNGLGETMULTITEXENVFVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETMULTITEXENVIVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETMULTITEXGENDVEXTPROC) (GLenum texunit, GLenum coord, GLenum pname, GLdouble *params);
+typedef void (APIENTRYP PFNGLGETMULTITEXGENFVEXTPROC) (GLenum texunit, GLenum coord, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETMULTITEXGENIVEXTPROC) (GLenum texunit, GLenum coord, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETFLOATINDEXEDVEXTPROC) (GLenum target, GLuint index, GLfloat *data);
+typedef void (APIENTRYP PFNGLGETDOUBLEINDEXEDVEXTPROC) (GLenum target, GLuint index, GLdouble *data);
+typedef void (APIENTRYP PFNGLGETPOINTERINDEXEDVEXTPROC) (GLenum target, GLuint index, GLvoid* *data);
+typedef void (APIENTRYP PFNGLCOMPRESSEDTEXTUREIMAGE3DEXTPROC) (GLuint texture, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid *bits);
+typedef void (APIENTRYP PFNGLCOMPRESSEDTEXTUREIMAGE2DEXTPROC) (GLuint texture, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *bits);
+typedef void (APIENTRYP PFNGLCOMPRESSEDTEXTUREIMAGE1DEXTPROC) (GLuint texture, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const GLvoid *bits);
+typedef void (APIENTRYP PFNGLCOMPRESSEDTEXTURESUBIMAGE3DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid *bits);
+typedef void (APIENTRYP PFNGLCOMPRESSEDTEXTURESUBIMAGE2DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid *bits);
+typedef void (APIENTRYP PFNGLCOMPRESSEDTEXTURESUBIMAGE1DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const GLvoid *bits);
+typedef void (APIENTRYP PFNGLGETCOMPRESSEDTEXTUREIMAGEEXTPROC) (GLuint texture, GLenum target, GLint lod, GLvoid *img);
+typedef void (APIENTRYP PFNGLCOMPRESSEDMULTITEXIMAGE3DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid *bits);
+typedef void (APIENTRYP PFNGLCOMPRESSEDMULTITEXIMAGE2DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *bits);
+typedef void (APIENTRYP PFNGLCOMPRESSEDMULTITEXIMAGE1DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const GLvoid *bits);
+typedef void (APIENTRYP PFNGLCOMPRESSEDMULTITEXSUBIMAGE3DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid *bits);
+typedef void (APIENTRYP PFNGLCOMPRESSEDMULTITEXSUBIMAGE2DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid *bits);
+typedef void (APIENTRYP PFNGLCOMPRESSEDMULTITEXSUBIMAGE1DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const GLvoid *bits);
+typedef void (APIENTRYP PFNGLGETCOMPRESSEDMULTITEXIMAGEEXTPROC) (GLenum texunit, GLenum target, GLint lod, GLvoid *img);
+typedef void (APIENTRYP PFNGLNAMEDPROGRAMSTRINGEXTPROC) (GLuint program, GLenum target, GLenum format, GLsizei len, const GLvoid *string);
+typedef void (APIENTRYP PFNGLNAMEDPROGRAMLOCALPARAMETER4DEXTPROC) (GLuint program, GLenum target, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+typedef void (APIENTRYP PFNGLNAMEDPROGRAMLOCALPARAMETER4DVEXTPROC) (GLuint program, GLenum target, GLuint index, const GLdouble *params);
+typedef void (APIENTRYP PFNGLNAMEDPROGRAMLOCALPARAMETER4FEXTPROC) (GLuint program, GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+typedef void (APIENTRYP PFNGLNAMEDPROGRAMLOCALPARAMETER4FVEXTPROC) (GLuint program, GLenum target, GLuint index, const GLfloat *params);
+typedef void (APIENTRYP PFNGLGETNAMEDPROGRAMLOCALPARAMETERDVEXTPROC) (GLuint program, GLenum target, GLuint index, GLdouble *params);
+typedef void (APIENTRYP PFNGLGETNAMEDPROGRAMLOCALPARAMETERFVEXTPROC) (GLuint program, GLenum target, GLuint index, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETNAMEDPROGRAMIVEXTPROC) (GLuint program, GLenum target, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETNAMEDPROGRAMSTRINGEXTPROC) (GLuint program, GLenum target, GLenum pname, GLvoid *string);
+typedef void (APIENTRYP PFNGLNAMEDPROGRAMLOCALPARAMETERS4FVEXTPROC) (GLuint program, GLenum target, GLuint index, GLsizei count, const GLfloat *params);
+typedef void (APIENTRYP PFNGLNAMEDPROGRAMLOCALPARAMETERI4IEXTPROC) (GLuint program, GLenum target, GLuint index, GLint x, GLint y, GLint z, GLint w);
+typedef void (APIENTRYP PFNGLNAMEDPROGRAMLOCALPARAMETERI4IVEXTPROC) (GLuint program, GLenum target, GLuint index, const GLint *params);
+typedef void (APIENTRYP PFNGLNAMEDPROGRAMLOCALPARAMETERSI4IVEXTPROC) (GLuint program, GLenum target, GLuint index, GLsizei count, const GLint *params);
+typedef void (APIENTRYP PFNGLNAMEDPROGRAMLOCALPARAMETERI4UIEXTPROC) (GLuint program, GLenum target, GLuint index, GLuint x, GLuint y, GLuint z, GLuint w);
+typedef void (APIENTRYP PFNGLNAMEDPROGRAMLOCALPARAMETERI4UIVEXTPROC) (GLuint program, GLenum target, GLuint index, const GLuint *params);
+typedef void (APIENTRYP PFNGLNAMEDPROGRAMLOCALPARAMETERSI4UIVEXTPROC) (GLuint program, GLenum target, GLuint index, GLsizei count, const GLuint *params);
+typedef void (APIENTRYP PFNGLGETNAMEDPROGRAMLOCALPARAMETERIIVEXTPROC) (GLuint program, GLenum target, GLuint index, GLint *params);
+typedef void (APIENTRYP PFNGLGETNAMEDPROGRAMLOCALPARAMETERIUIVEXTPROC) (GLuint program, GLenum target, GLuint index, GLuint *params);
+typedef void (APIENTRYP PFNGLTEXTUREPARAMETERIIVEXTPROC) (GLuint texture, GLenum target, GLenum pname, const GLint *params);
+typedef void (APIENTRYP PFNGLTEXTUREPARAMETERIUIVEXTPROC) (GLuint texture, GLenum target, GLenum pname, const GLuint *params);
+typedef void (APIENTRYP PFNGLGETTEXTUREPARAMETERIIVEXTPROC) (GLuint texture, GLenum target, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETTEXTUREPARAMETERIUIVEXTPROC) (GLuint texture, GLenum target, GLenum pname, GLuint *params);
+typedef void (APIENTRYP PFNGLMULTITEXPARAMETERIIVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, const GLint *params);
+typedef void (APIENTRYP PFNGLMULTITEXPARAMETERIUIVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, const GLuint *params);
+typedef void (APIENTRYP PFNGLGETMULTITEXPARAMETERIIVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETMULTITEXPARAMETERIUIVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, GLuint *params);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM1FEXTPROC) (GLuint program, GLint location, GLfloat v0);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM2FEXTPROC) (GLuint program, GLint location, GLfloat v0, GLfloat v1);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM3FEXTPROC) (GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM4FEXTPROC) (GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM1IEXTPROC) (GLuint program, GLint location, GLint v0);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM2IEXTPROC) (GLuint program, GLint location, GLint v0, GLint v1);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM3IEXTPROC) (GLuint program, GLint location, GLint v0, GLint v1, GLint v2);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM4IEXTPROC) (GLuint program, GLint location, GLint v0, GLint v1, GLint v2, GLint v3);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM1FVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM2FVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM3FVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM4FVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM1IVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLint *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM2IVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLint *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM3IVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLint *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM4IVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLint *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX2FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX3FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX4FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX2X3FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX3X2FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX2X4FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX4X2FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX3X4FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX4X3FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM1UIEXTPROC) (GLuint program, GLint location, GLuint v0);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM2UIEXTPROC) (GLuint program, GLint location, GLuint v0, GLuint v1);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM3UIEXTPROC) (GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM4UIEXTPROC) (GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM1UIVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLuint *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM2UIVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLuint *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM3UIVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLuint *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM4UIVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLuint *value);
+typedef void (APIENTRYP PFNGLNAMEDBUFFERDATAEXTPROC) (GLuint buffer, GLsizeiptr size, const GLvoid *data, GLenum usage);
+typedef void (APIENTRYP PFNGLNAMEDBUFFERSUBDATAEXTPROC) (GLuint buffer, GLintptr offset, GLsizeiptr size, const GLvoid *data);
+typedef GLvoid* (APIENTRYP PFNGLMAPNAMEDBUFFEREXTPROC) (GLuint buffer, GLenum access);
+typedef GLboolean (APIENTRYP PFNGLUNMAPNAMEDBUFFEREXTPROC) (GLuint buffer);
+typedef GLvoid* (APIENTRYP PFNGLMAPNAMEDBUFFERRANGEEXTPROC) (GLuint buffer, GLintptr offset, GLsizeiptr length, GLbitfield access);
+typedef void (APIENTRYP PFNGLFLUSHMAPPEDNAMEDBUFFERRANGEEXTPROC) (GLuint buffer, GLintptr offset, GLsizeiptr length);
+typedef void (APIENTRYP PFNGLNAMEDCOPYBUFFERSUBDATAEXTPROC) (GLuint readBuffer, GLuint writeBuffer, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size);
+typedef void (APIENTRYP PFNGLGETNAMEDBUFFERPARAMETERIVEXTPROC) (GLuint buffer, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETNAMEDBUFFERPOINTERVEXTPROC) (GLuint buffer, GLenum pname, GLvoid* *params);
+typedef void (APIENTRYP PFNGLGETNAMEDBUFFERSUBDATAEXTPROC) (GLuint buffer, GLintptr offset, GLsizeiptr size, GLvoid *data);
+typedef void (APIENTRYP PFNGLTEXTUREBUFFEREXTPROC) (GLuint texture, GLenum target, GLenum internalformat, GLuint buffer);
+typedef void (APIENTRYP PFNGLMULTITEXBUFFEREXTPROC) (GLenum texunit, GLenum target, GLenum internalformat, GLuint buffer);
+typedef void (APIENTRYP PFNGLNAMEDRENDERBUFFERSTORAGEEXTPROC) (GLuint renderbuffer, GLenum internalformat, GLsizei width, GLsizei height);
+typedef void (APIENTRYP PFNGLGETNAMEDRENDERBUFFERPARAMETERIVEXTPROC) (GLuint renderbuffer, GLenum pname, GLint *params);
+typedef GLenum (APIENTRYP PFNGLCHECKNAMEDFRAMEBUFFERSTATUSEXTPROC) (GLuint framebuffer, GLenum target);
+typedef void (APIENTRYP PFNGLNAMEDFRAMEBUFFERTEXTURE1DEXTPROC) (GLuint framebuffer, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
+typedef void (APIENTRYP PFNGLNAMEDFRAMEBUFFERTEXTURE2DEXTPROC) (GLuint framebuffer, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
+typedef void (APIENTRYP PFNGLNAMEDFRAMEBUFFERTEXTURE3DEXTPROC) (GLuint framebuffer, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset);
+typedef void (APIENTRYP PFNGLNAMEDFRAMEBUFFERRENDERBUFFEREXTPROC) (GLuint framebuffer, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer);
+typedef void (APIENTRYP PFNGLGETNAMEDFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC) (GLuint framebuffer, GLenum attachment, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGENERATETEXTUREMIPMAPEXTPROC) (GLuint texture, GLenum target);
+typedef void (APIENTRYP PFNGLGENERATEMULTITEXMIPMAPEXTPROC) (GLenum texunit, GLenum target);
+typedef void (APIENTRYP PFNGLFRAMEBUFFERDRAWBUFFEREXTPROC) (GLuint framebuffer, GLenum mode);
+typedef void (APIENTRYP PFNGLFRAMEBUFFERDRAWBUFFERSEXTPROC) (GLuint framebuffer, GLsizei n, const GLenum *bufs);
+typedef void (APIENTRYP PFNGLFRAMEBUFFERREADBUFFEREXTPROC) (GLuint framebuffer, GLenum mode);
+typedef void (APIENTRYP PFNGLGETFRAMEBUFFERPARAMETERIVEXTPROC) (GLuint framebuffer, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLNAMEDRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC) (GLuint renderbuffer, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
+typedef void (APIENTRYP PFNGLNAMEDRENDERBUFFERSTORAGEMULTISAMPLECOVERAGEEXTPROC) (GLuint renderbuffer, GLsizei coverageSamples, GLsizei colorSamples, GLenum internalformat, GLsizei width, GLsizei height);
+typedef void (APIENTRYP PFNGLNAMEDFRAMEBUFFERTEXTUREEXTPROC) (GLuint framebuffer, GLenum attachment, GLuint texture, GLint level);
+typedef void (APIENTRYP PFNGLNAMEDFRAMEBUFFERTEXTURELAYEREXTPROC) (GLuint framebuffer, GLenum attachment, GLuint texture, GLint level, GLint layer);
+typedef void (APIENTRYP PFNGLNAMEDFRAMEBUFFERTEXTUREFACEEXTPROC) (GLuint framebuffer, GLenum attachment, GLuint texture, GLint level, GLenum face);
+typedef void (APIENTRYP PFNGLTEXTURERENDERBUFFEREXTPROC) (GLuint texture, GLenum target, GLuint renderbuffer);
+typedef void (APIENTRYP PFNGLMULTITEXRENDERBUFFEREXTPROC) (GLenum texunit, GLenum target, GLuint renderbuffer);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM1DEXTPROC) (GLuint program, GLint location, GLdouble x);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM2DEXTPROC) (GLuint program, GLint location, GLdouble x, GLdouble y);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM3DEXTPROC) (GLuint program, GLint location, GLdouble x, GLdouble y, GLdouble z);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM4DEXTPROC) (GLuint program, GLint location, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM1DVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLdouble *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM2DVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLdouble *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM3DVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLdouble *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM4DVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLdouble *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX2DVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX3DVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX4DVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX2X3DVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX2X4DVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX3X2DVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX3X4DVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX4X2DVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX4X3DVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+#endif
+
+#ifndef GL_EXT_vertex_array_bgra
+#define GL_EXT_vertex_array_bgra 1
+#endif
+
+#ifndef GL_EXT_texture_swizzle
+#define GL_EXT_texture_swizzle 1
+#endif
+
+#ifndef GL_NV_explicit_multisample
+#define GL_NV_explicit_multisample 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glGetMultisamplefvNV (GLenum pname, GLuint index, GLfloat *val);
+GLAPI void APIENTRY glSampleMaskIndexedNV (GLuint index, GLbitfield mask);
+GLAPI void APIENTRY glTexRenderbufferNV (GLenum target, GLuint renderbuffer);
+#endif
+typedef void (APIENTRYP PFNGLGETMULTISAMPLEFVNVPROC) (GLenum pname, GLuint index, GLfloat *val);
+typedef void (APIENTRYP PFNGLSAMPLEMASKINDEXEDNVPROC) (GLuint index, GLbitfield mask);
+typedef void (APIENTRYP PFNGLTEXRENDERBUFFERNVPROC) (GLenum target, GLuint renderbuffer);
+#endif
+
+#ifndef GL_NV_transform_feedback2
+#define GL_NV_transform_feedback2 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glBindTransformFeedbackNV (GLenum target, GLuint id);
+GLAPI void APIENTRY glDeleteTransformFeedbacksNV (GLsizei n, const GLuint *ids);
+GLAPI void APIENTRY glGenTransformFeedbacksNV (GLsizei n, GLuint *ids);
+GLAPI GLboolean APIENTRY glIsTransformFeedbackNV (GLuint id);
+GLAPI void APIENTRY glPauseTransformFeedbackNV (void);
+GLAPI void APIENTRY glResumeTransformFeedbackNV (void);
+GLAPI void APIENTRY glDrawTransformFeedbackNV (GLenum mode, GLuint id);
+#endif
+typedef void (APIENTRYP PFNGLBINDTRANSFORMFEEDBACKNVPROC) (GLenum target, GLuint id);
+typedef void (APIENTRYP PFNGLDELETETRANSFORMFEEDBACKSNVPROC) (GLsizei n, const GLuint *ids);
+typedef void (APIENTRYP PFNGLGENTRANSFORMFEEDBACKSNVPROC) (GLsizei n, GLuint *ids);
+typedef GLboolean (APIENTRYP PFNGLISTRANSFORMFEEDBACKNVPROC) (GLuint id);
+typedef void (APIENTRYP PFNGLPAUSETRANSFORMFEEDBACKNVPROC) (void);
+typedef void (APIENTRYP PFNGLRESUMETRANSFORMFEEDBACKNVPROC) (void);
+typedef void (APIENTRYP PFNGLDRAWTRANSFORMFEEDBACKNVPROC) (GLenum mode, GLuint id);
+#endif
+
+#ifndef GL_ATI_meminfo
+#define GL_ATI_meminfo 1
+#endif
+
+#ifndef GL_AMD_performance_monitor
+#define GL_AMD_performance_monitor 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glGetPerfMonitorGroupsAMD (GLint *numGroups, GLsizei groupsSize, GLuint *groups);
+GLAPI void APIENTRY glGetPerfMonitorCountersAMD (GLuint group, GLint *numCounters, GLint *maxActiveCounters, GLsizei counterSize, GLuint *counters);
+GLAPI void APIENTRY glGetPerfMonitorGroupStringAMD (GLuint group, GLsizei bufSize, GLsizei *length, GLchar *groupString);
+GLAPI void APIENTRY glGetPerfMonitorCounterStringAMD (GLuint group, GLuint counter, GLsizei bufSize, GLsizei *length, GLchar *counterString);
+GLAPI void APIENTRY glGetPerfMonitorCounterInfoAMD (GLuint group, GLuint counter, GLenum pname, GLvoid *data);
+GLAPI void APIENTRY glGenPerfMonitorsAMD (GLsizei n, GLuint *monitors);
+GLAPI void APIENTRY glDeletePerfMonitorsAMD (GLsizei n, GLuint *monitors);
+GLAPI void APIENTRY glSelectPerfMonitorCountersAMD (GLuint monitor, GLboolean enable, GLuint group, GLint numCounters, GLuint *counterList);
+GLAPI void APIENTRY glBeginPerfMonitorAMD (GLuint monitor);
+GLAPI void APIENTRY glEndPerfMonitorAMD (GLuint monitor);
+GLAPI void APIENTRY glGetPerfMonitorCounterDataAMD (GLuint monitor, GLenum pname, GLsizei dataSize, GLuint *data, GLint *bytesWritten);
+#endif
+typedef void (APIENTRYP PFNGLGETPERFMONITORGROUPSAMDPROC) (GLint *numGroups, GLsizei groupsSize, GLuint *groups);
+typedef void (APIENTRYP PFNGLGETPERFMONITORCOUNTERSAMDPROC) (GLuint group, GLint *numCounters, GLint *maxActiveCounters, GLsizei counterSize, GLuint *counters);
+typedef void (APIENTRYP PFNGLGETPERFMONITORGROUPSTRINGAMDPROC) (GLuint group, GLsizei bufSize, GLsizei *length, GLchar *groupString);
+typedef void (APIENTRYP PFNGLGETPERFMONITORCOUNTERSTRINGAMDPROC) (GLuint group, GLuint counter, GLsizei bufSize, GLsizei *length, GLchar *counterString);
+typedef void (APIENTRYP PFNGLGETPERFMONITORCOUNTERINFOAMDPROC) (GLuint group, GLuint counter, GLenum pname, GLvoid *data);
+typedef void (APIENTRYP PFNGLGENPERFMONITORSAMDPROC) (GLsizei n, GLuint *monitors);
+typedef void (APIENTRYP PFNGLDELETEPERFMONITORSAMDPROC) (GLsizei n, GLuint *monitors);
+typedef void (APIENTRYP PFNGLSELECTPERFMONITORCOUNTERSAMDPROC) (GLuint monitor, GLboolean enable, GLuint group, GLint numCounters, GLuint *counterList);
+typedef void (APIENTRYP PFNGLBEGINPERFMONITORAMDPROC) (GLuint monitor);
+typedef void (APIENTRYP PFNGLENDPERFMONITORAMDPROC) (GLuint monitor);
+typedef void (APIENTRYP PFNGLGETPERFMONITORCOUNTERDATAAMDPROC) (GLuint monitor, GLenum pname, GLsizei dataSize, GLuint *data, GLint *bytesWritten);
+#endif
+
+#ifndef GL_AMD_texture_texture4
+#define GL_AMD_texture_texture4 1
+#endif
+
+#ifndef GL_AMD_vertex_shader_tesselator
+#define GL_AMD_vertex_shader_tesselator 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glTessellationFactorAMD (GLfloat factor);
+GLAPI void APIENTRY glTessellationModeAMD (GLenum mode);
+#endif
+typedef void (APIENTRYP PFNGLTESSELLATIONFACTORAMDPROC) (GLfloat factor);
+typedef void (APIENTRYP PFNGLTESSELLATIONMODEAMDPROC) (GLenum mode);
+#endif
+
+#ifndef GL_EXT_provoking_vertex
+#define GL_EXT_provoking_vertex 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glProvokingVertexEXT (GLenum mode);
+#endif
+typedef void (APIENTRYP PFNGLPROVOKINGVERTEXEXTPROC) (GLenum mode);
+#endif
+
+#ifndef GL_EXT_texture_snorm
+#define GL_EXT_texture_snorm 1
+#endif
+
+#ifndef GL_AMD_draw_buffers_blend
+#define GL_AMD_draw_buffers_blend 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glBlendFuncIndexedAMD (GLuint buf, GLenum src, GLenum dst);
+GLAPI void APIENTRY glBlendFuncSeparateIndexedAMD (GLuint buf, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha);
+GLAPI void APIENTRY glBlendEquationIndexedAMD (GLuint buf, GLenum mode);
+GLAPI void APIENTRY glBlendEquationSeparateIndexedAMD (GLuint buf, GLenum modeRGB, GLenum modeAlpha);
+#endif
+typedef void (APIENTRYP PFNGLBLENDFUNCINDEXEDAMDPROC) (GLuint buf, GLenum src, GLenum dst);
+typedef void (APIENTRYP PFNGLBLENDFUNCSEPARATEINDEXEDAMDPROC) (GLuint buf, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha);
+typedef void (APIENTRYP PFNGLBLENDEQUATIONINDEXEDAMDPROC) (GLuint buf, GLenum mode);
+typedef void (APIENTRYP PFNGLBLENDEQUATIONSEPARATEINDEXEDAMDPROC) (GLuint buf, GLenum modeRGB, GLenum modeAlpha);
+#endif
+
+#ifndef GL_APPLE_texture_range
+#define GL_APPLE_texture_range 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glTextureRangeAPPLE (GLenum target, GLsizei length, const GLvoid *pointer);
+GLAPI void APIENTRY glGetTexParameterPointervAPPLE (GLenum target, GLenum pname, GLvoid* *params);
+#endif
+typedef void (APIENTRYP PFNGLTEXTURERANGEAPPLEPROC) (GLenum target, GLsizei length, const GLvoid *pointer);
+typedef void (APIENTRYP PFNGLGETTEXPARAMETERPOINTERVAPPLEPROC) (GLenum target, GLenum pname, GLvoid* *params);
+#endif
+
+#ifndef GL_APPLE_float_pixels
+#define GL_APPLE_float_pixels 1
+#endif
+
+#ifndef GL_APPLE_vertex_program_evaluators
+#define GL_APPLE_vertex_program_evaluators 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glEnableVertexAttribAPPLE (GLuint index, GLenum pname);
+GLAPI void APIENTRY glDisableVertexAttribAPPLE (GLuint index, GLenum pname);
+GLAPI GLboolean APIENTRY glIsVertexAttribEnabledAPPLE (GLuint index, GLenum pname);
+GLAPI void APIENTRY glMapVertexAttrib1dAPPLE (GLuint index, GLuint size, GLdouble u1, GLdouble u2, GLint stride, GLint order, const GLdouble *points);
+GLAPI void APIENTRY glMapVertexAttrib1fAPPLE (GLuint index, GLuint size, GLfloat u1, GLfloat u2, GLint stride, GLint order, const GLfloat *points);
+GLAPI void APIENTRY glMapVertexAttrib2dAPPLE (GLuint index, GLuint size, GLdouble u1, GLdouble u2, GLint ustride, GLint uorder, GLdouble v1, GLdouble v2, GLint vstride, GLint vorder, const GLdouble *points);
+GLAPI void APIENTRY glMapVertexAttrib2fAPPLE (GLuint index, GLuint size, GLfloat u1, GLfloat u2, GLint ustride, GLint uorder, GLfloat v1, GLfloat v2, GLint vstride, GLint vorder, const GLfloat *points);
+#endif
+typedef void (APIENTRYP PFNGLENABLEVERTEXATTRIBAPPLEPROC) (GLuint index, GLenum pname);
+typedef void (APIENTRYP PFNGLDISABLEVERTEXATTRIBAPPLEPROC) (GLuint index, GLenum pname);
+typedef GLboolean (APIENTRYP PFNGLISVERTEXATTRIBENABLEDAPPLEPROC) (GLuint index, GLenum pname);
+typedef void (APIENTRYP PFNGLMAPVERTEXATTRIB1DAPPLEPROC) (GLuint index, GLuint size, GLdouble u1, GLdouble u2, GLint stride, GLint order, const GLdouble *points);
+typedef void (APIENTRYP PFNGLMAPVERTEXATTRIB1FAPPLEPROC) (GLuint index, GLuint size, GLfloat u1, GLfloat u2, GLint stride, GLint order, const GLfloat *points);
+typedef void (APIENTRYP PFNGLMAPVERTEXATTRIB2DAPPLEPROC) (GLuint index, GLuint size, GLdouble u1, GLdouble u2, GLint ustride, GLint uorder, GLdouble v1, GLdouble v2, GLint vstride, GLint vorder, const GLdouble *points);
+typedef void (APIENTRYP PFNGLMAPVERTEXATTRIB2FAPPLEPROC) (GLuint index, GLuint size, GLfloat u1, GLfloat u2, GLint ustride, GLint uorder, GLfloat v1, GLfloat v2, GLint vstride, GLint vorder, const GLfloat *points);
+#endif
+
+#ifndef GL_APPLE_aux_depth_stencil
+#define GL_APPLE_aux_depth_stencil 1
+#endif
+
+#ifndef GL_APPLE_object_purgeable
+#define GL_APPLE_object_purgeable 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI GLenum APIENTRY glObjectPurgeableAPPLE (GLenum objectType, GLuint name, GLenum option);
+GLAPI GLenum APIENTRY glObjectUnpurgeableAPPLE (GLenum objectType, GLuint name, GLenum option);
+GLAPI void APIENTRY glGetObjectParameterivAPPLE (GLenum objectType, GLuint name, GLenum pname, GLint *params);
+#endif
+typedef GLenum (APIENTRYP PFNGLOBJECTPURGEABLEAPPLEPROC) (GLenum objectType, GLuint name, GLenum option);
+typedef GLenum (APIENTRYP PFNGLOBJECTUNPURGEABLEAPPLEPROC) (GLenum objectType, GLuint name, GLenum option);
+typedef void (APIENTRYP PFNGLGETOBJECTPARAMETERIVAPPLEPROC) (GLenum objectType, GLuint name, GLenum pname, GLint *params);
+#endif
+
+#ifndef GL_APPLE_row_bytes
+#define GL_APPLE_row_bytes 1
+#endif
+
+#ifndef GL_APPLE_rgb_422
+#define GL_APPLE_rgb_422 1
+#endif
+
+#ifndef GL_NV_video_capture
+#define GL_NV_video_capture 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glBeginVideoCaptureNV (GLuint video_capture_slot);
+GLAPI void APIENTRY glBindVideoCaptureStreamBufferNV (GLuint video_capture_slot, GLuint stream, GLenum frame_region, GLintptrARB offset);
+GLAPI void APIENTRY glBindVideoCaptureStreamTextureNV (GLuint video_capture_slot, GLuint stream, GLenum frame_region, GLenum target, GLuint texture);
+GLAPI void APIENTRY glEndVideoCaptureNV (GLuint video_capture_slot);
+GLAPI void APIENTRY glGetVideoCaptureivNV (GLuint video_capture_slot, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetVideoCaptureStreamivNV (GLuint video_capture_slot, GLuint stream, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetVideoCaptureStreamfvNV (GLuint video_capture_slot, GLuint stream, GLenum pname, GLfloat *params);
+GLAPI void APIENTRY glGetVideoCaptureStreamdvNV (GLuint video_capture_slot, GLuint stream, GLenum pname, GLdouble *params);
+GLAPI GLenum APIENTRY glVideoCaptureNV (GLuint video_capture_slot, GLuint *sequence_num, GLuint64EXT *capture_time);
+GLAPI void APIENTRY glVideoCaptureStreamParameterivNV (GLuint video_capture_slot, GLuint stream, GLenum pname, const GLint *params);
+GLAPI void APIENTRY glVideoCaptureStreamParameterfvNV (GLuint video_capture_slot, GLuint stream, GLenum pname, const GLfloat *params);
+GLAPI void APIENTRY glVideoCaptureStreamParameterdvNV (GLuint video_capture_slot, GLuint stream, GLenum pname, const GLdouble *params);
+#endif
+typedef void (APIENTRYP PFNGLBEGINVIDEOCAPTURENVPROC) (GLuint video_capture_slot);
+typedef void (APIENTRYP PFNGLBINDVIDEOCAPTURESTREAMBUFFERNVPROC) (GLuint video_capture_slot, GLuint stream, GLenum frame_region, GLintptrARB offset);
+typedef void (APIENTRYP PFNGLBINDVIDEOCAPTURESTREAMTEXTURENVPROC) (GLuint video_capture_slot, GLuint stream, GLenum frame_region, GLenum target, GLuint texture);
+typedef void (APIENTRYP PFNGLENDVIDEOCAPTURENVPROC) (GLuint video_capture_slot);
+typedef void (APIENTRYP PFNGLGETVIDEOCAPTUREIVNVPROC) (GLuint video_capture_slot, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETVIDEOCAPTURESTREAMIVNVPROC) (GLuint video_capture_slot, GLuint stream, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETVIDEOCAPTURESTREAMFVNVPROC) (GLuint video_capture_slot, GLuint stream, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETVIDEOCAPTURESTREAMDVNVPROC) (GLuint video_capture_slot, GLuint stream, GLenum pname, GLdouble *params);
+typedef GLenum (APIENTRYP PFNGLVIDEOCAPTURENVPROC) (GLuint video_capture_slot, GLuint *sequence_num, GLuint64EXT *capture_time);
+typedef void (APIENTRYP PFNGLVIDEOCAPTURESTREAMPARAMETERIVNVPROC) (GLuint video_capture_slot, GLuint stream, GLenum pname, const GLint *params);
+typedef void (APIENTRYP PFNGLVIDEOCAPTURESTREAMPARAMETERFVNVPROC) (GLuint video_capture_slot, GLuint stream, GLenum pname, const GLfloat *params);
+typedef void (APIENTRYP PFNGLVIDEOCAPTURESTREAMPARAMETERDVNVPROC) (GLuint video_capture_slot, GLuint stream, GLenum pname, const GLdouble *params);
+#endif
+
+#ifndef GL_NV_copy_image
+#define GL_NV_copy_image 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glCopyImageSubDataNV (GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei width, GLsizei height, GLsizei depth);
+#endif
+typedef void (APIENTRYP PFNGLCOPYIMAGESUBDATANVPROC) (GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei width, GLsizei height, GLsizei depth);
+#endif
+
+#ifndef GL_EXT_separate_shader_objects
+#define GL_EXT_separate_shader_objects 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glUseShaderProgramEXT (GLenum type, GLuint program);
+GLAPI void APIENTRY glActiveProgramEXT (GLuint program);
+GLAPI GLuint APIENTRY glCreateShaderProgramEXT (GLenum type, const GLchar *string);
+#endif
+typedef void (APIENTRYP PFNGLUSESHADERPROGRAMEXTPROC) (GLenum type, GLuint program);
+typedef void (APIENTRYP PFNGLACTIVEPROGRAMEXTPROC) (GLuint program);
+typedef GLuint (APIENTRYP PFNGLCREATESHADERPROGRAMEXTPROC) (GLenum type, const GLchar *string);
+#endif
+
+#ifndef GL_NV_parameter_buffer_object2
+#define GL_NV_parameter_buffer_object2 1
+#endif
+
+#ifndef GL_NV_shader_buffer_load
+#define GL_NV_shader_buffer_load 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glMakeBufferResidentNV (GLenum target, GLenum access);
+GLAPI void APIENTRY glMakeBufferNonResidentNV (GLenum target);
+GLAPI GLboolean APIENTRY glIsBufferResidentNV (GLenum target);
+GLAPI void APIENTRY glMakeNamedBufferResidentNV (GLuint buffer, GLenum access);
+GLAPI void APIENTRY glMakeNamedBufferNonResidentNV (GLuint buffer);
+GLAPI GLboolean APIENTRY glIsNamedBufferResidentNV (GLuint buffer);
+GLAPI void APIENTRY glGetBufferParameterui64vNV (GLenum target, GLenum pname, GLuint64EXT *params);
+GLAPI void APIENTRY glGetNamedBufferParameterui64vNV (GLuint buffer, GLenum pname, GLuint64EXT *params);
+GLAPI void APIENTRY glGetIntegerui64vNV (GLenum value, GLuint64EXT *result);
+GLAPI void APIENTRY glUniformui64NV (GLint location, GLuint64EXT value);
+GLAPI void APIENTRY glUniformui64vNV (GLint location, GLsizei count, const GLuint64EXT *value);
+GLAPI void APIENTRY glGetUniformui64vNV (GLuint program, GLint location, GLuint64EXT *params);
+GLAPI void APIENTRY glProgramUniformui64NV (GLuint program, GLint location, GLuint64EXT value);
+GLAPI void APIENTRY glProgramUniformui64vNV (GLuint program, GLint location, GLsizei count, const GLuint64EXT *value);
+#endif
+typedef void (APIENTRYP PFNGLMAKEBUFFERRESIDENTNVPROC) (GLenum target, GLenum access);
+typedef void (APIENTRYP PFNGLMAKEBUFFERNONRESIDENTNVPROC) (GLenum target);
+typedef GLboolean (APIENTRYP PFNGLISBUFFERRESIDENTNVPROC) (GLenum target);
+typedef void (APIENTRYP PFNGLMAKENAMEDBUFFERRESIDENTNVPROC) (GLuint buffer, GLenum access);
+typedef void (APIENTRYP PFNGLMAKENAMEDBUFFERNONRESIDENTNVPROC) (GLuint buffer);
+typedef GLboolean (APIENTRYP PFNGLISNAMEDBUFFERRESIDENTNVPROC) (GLuint buffer);
+typedef void (APIENTRYP PFNGLGETBUFFERPARAMETERUI64VNVPROC) (GLenum target, GLenum pname, GLuint64EXT *params);
+typedef void (APIENTRYP PFNGLGETNAMEDBUFFERPARAMETERUI64VNVPROC) (GLuint buffer, GLenum pname, GLuint64EXT *params);
+typedef void (APIENTRYP PFNGLGETINTEGERUI64VNVPROC) (GLenum value, GLuint64EXT *result);
+typedef void (APIENTRYP PFNGLUNIFORMUI64NVPROC) (GLint location, GLuint64EXT value);
+typedef void (APIENTRYP PFNGLUNIFORMUI64VNVPROC) (GLint location, GLsizei count, const GLuint64EXT *value);
+typedef void (APIENTRYP PFNGLGETUNIFORMUI64VNVPROC) (GLuint program, GLint location, GLuint64EXT *params);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORMUI64NVPROC) (GLuint program, GLint location, GLuint64EXT value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORMUI64VNVPROC) (GLuint program, GLint location, GLsizei count, const GLuint64EXT *value);
+#endif
+
+#ifndef GL_NV_vertex_buffer_unified_memory
+#define GL_NV_vertex_buffer_unified_memory 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glBufferAddressRangeNV (GLenum pname, GLuint index, GLuint64EXT address, GLsizeiptr length);
+GLAPI void APIENTRY glVertexFormatNV (GLint size, GLenum type, GLsizei stride);
+GLAPI void APIENTRY glNormalFormatNV (GLenum type, GLsizei stride);
+GLAPI void APIENTRY glColorFormatNV (GLint size, GLenum type, GLsizei stride);
+GLAPI void APIENTRY glIndexFormatNV (GLenum type, GLsizei stride);
+GLAPI void APIENTRY glTexCoordFormatNV (GLint size, GLenum type, GLsizei stride);
+GLAPI void APIENTRY glEdgeFlagFormatNV (GLsizei stride);
+GLAPI void APIENTRY glSecondaryColorFormatNV (GLint size, GLenum type, GLsizei stride);
+GLAPI void APIENTRY glFogCoordFormatNV (GLenum type, GLsizei stride);
+GLAPI void APIENTRY glVertexAttribFormatNV (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride);
+GLAPI void APIENTRY glVertexAttribIFormatNV (GLuint index, GLint size, GLenum type, GLsizei stride);
+GLAPI void APIENTRY glGetIntegerui64i_vNV (GLenum value, GLuint index, GLuint64EXT *result);
+#endif
+typedef void (APIENTRYP PFNGLBUFFERADDRESSRANGENVPROC) (GLenum pname, GLuint index, GLuint64EXT address, GLsizeiptr length);
+typedef void (APIENTRYP PFNGLVERTEXFORMATNVPROC) (GLint size, GLenum type, GLsizei stride);
+typedef void (APIENTRYP PFNGLNORMALFORMATNVPROC) (GLenum type, GLsizei stride);
+typedef void (APIENTRYP PFNGLCOLORFORMATNVPROC) (GLint size, GLenum type, GLsizei stride);
+typedef void (APIENTRYP PFNGLINDEXFORMATNVPROC) (GLenum type, GLsizei stride);
+typedef void (APIENTRYP PFNGLTEXCOORDFORMATNVPROC) (GLint size, GLenum type, GLsizei stride);
+typedef void (APIENTRYP PFNGLEDGEFLAGFORMATNVPROC) (GLsizei stride);
+typedef void (APIENTRYP PFNGLSECONDARYCOLORFORMATNVPROC) (GLint size, GLenum type, GLsizei stride);
+typedef void (APIENTRYP PFNGLFOGCOORDFORMATNVPROC) (GLenum type, GLsizei stride);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBFORMATNVPROC) (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBIFORMATNVPROC) (GLuint index, GLint size, GLenum type, GLsizei stride);
+typedef void (APIENTRYP PFNGLGETINTEGERUI64I_VNVPROC) (GLenum value, GLuint index, GLuint64EXT *result);
+#endif
+
+#ifndef GL_NV_texture_barrier
+#define GL_NV_texture_barrier 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glTextureBarrierNV (void);
+#endif
+typedef void (APIENTRYP PFNGLTEXTUREBARRIERNVPROC) (void);
+#endif
+
+#ifndef GL_AMD_shader_stencil_export
+#define GL_AMD_shader_stencil_export 1
+#endif
+
+#ifndef GL_AMD_seamless_cubemap_per_texture
+#define GL_AMD_seamless_cubemap_per_texture 1
+#endif
+
+#ifndef GL_AMD_conservative_depth
+#define GL_AMD_conservative_depth 1
+#endif
+
+#ifndef GL_EXT_shader_image_load_store
+#define GL_EXT_shader_image_load_store 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glBindImageTextureEXT (GLuint index, GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum access, GLint format);
+GLAPI void APIENTRY glMemoryBarrierEXT (GLbitfield barriers);
+#endif
+typedef void (APIENTRYP PFNGLBINDIMAGETEXTUREEXTPROC) (GLuint index, GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum access, GLint format);
+typedef void (APIENTRYP PFNGLMEMORYBARRIEREXTPROC) (GLbitfield barriers);
+#endif
+
+#ifndef GL_EXT_vertex_attrib_64bit
+#define GL_EXT_vertex_attrib_64bit 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glVertexAttribL1dEXT (GLuint index, GLdouble x);
+GLAPI void APIENTRY glVertexAttribL2dEXT (GLuint index, GLdouble x, GLdouble y);
+GLAPI void APIENTRY glVertexAttribL3dEXT (GLuint index, GLdouble x, GLdouble y, GLdouble z);
+GLAPI void APIENTRY glVertexAttribL4dEXT (GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+GLAPI void APIENTRY glVertexAttribL1dvEXT (GLuint index, const GLdouble *v);
+GLAPI void APIENTRY glVertexAttribL2dvEXT (GLuint index, const GLdouble *v);
+GLAPI void APIENTRY glVertexAttribL3dvEXT (GLuint index, const GLdouble *v);
+GLAPI void APIENTRY glVertexAttribL4dvEXT (GLuint index, const GLdouble *v);
+GLAPI void APIENTRY glVertexAttribLPointerEXT (GLuint index, GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);
+GLAPI void APIENTRY glGetVertexAttribLdvEXT (GLuint index, GLenum pname, GLdouble *params);
+GLAPI void APIENTRY glVertexArrayVertexAttribLOffsetEXT (GLuint vaobj, GLuint buffer, GLuint index, GLint size, GLenum type, GLsizei stride, GLintptr offset);
+#endif
+typedef void (APIENTRYP PFNGLVERTEXATTRIBL1DEXTPROC) (GLuint index, GLdouble x);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBL2DEXTPROC) (GLuint index, GLdouble x, GLdouble y);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBL3DEXTPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBL4DEXTPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBL1DVEXTPROC) (GLuint index, const GLdouble *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBL2DVEXTPROC) (GLuint index, const GLdouble *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBL3DVEXTPROC) (GLuint index, const GLdouble *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBL4DVEXTPROC) (GLuint index, const GLdouble *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBLPOINTEREXTPROC) (GLuint index, GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);
+typedef void (APIENTRYP PFNGLGETVERTEXATTRIBLDVEXTPROC) (GLuint index, GLenum pname, GLdouble *params);
+typedef void (APIENTRYP PFNGLVERTEXARRAYVERTEXATTRIBLOFFSETEXTPROC) (GLuint vaobj, GLuint buffer, GLuint index, GLint size, GLenum type, GLsizei stride, GLintptr offset);
+#endif
+
+#ifndef GL_NV_gpu_program5
+#define GL_NV_gpu_program5 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glProgramSubroutineParametersuivNV (GLenum target, GLsizei count, const GLuint *params);
+GLAPI void APIENTRY glGetProgramSubroutineParameteruivNV (GLenum target, GLuint index, GLuint *param);
+#endif
+typedef void (APIENTRYP PFNGLPROGRAMSUBROUTINEPARAMETERSUIVNVPROC) (GLenum target, GLsizei count, const GLuint *params);
+typedef void (APIENTRYP PFNGLGETPROGRAMSUBROUTINEPARAMETERUIVNVPROC) (GLenum target, GLuint index, GLuint *param);
+#endif
+
+#ifndef GL_NV_gpu_shader5
+#define GL_NV_gpu_shader5 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glUniform1i64NV (GLint location, GLint64EXT x);
+GLAPI void APIENTRY glUniform2i64NV (GLint location, GLint64EXT x, GLint64EXT y);
+GLAPI void APIENTRY glUniform3i64NV (GLint location, GLint64EXT x, GLint64EXT y, GLint64EXT z);
+GLAPI void APIENTRY glUniform4i64NV (GLint location, GLint64EXT x, GLint64EXT y, GLint64EXT z, GLint64EXT w);
+GLAPI void APIENTRY glUniform1i64vNV (GLint location, GLsizei count, const GLint64EXT *value);
+GLAPI void APIENTRY glUniform2i64vNV (GLint location, GLsizei count, const GLint64EXT *value);
+GLAPI void APIENTRY glUniform3i64vNV (GLint location, GLsizei count, const GLint64EXT *value);
+GLAPI void APIENTRY glUniform4i64vNV (GLint location, GLsizei count, const GLint64EXT *value);
+GLAPI void APIENTRY glUniform1ui64NV (GLint location, GLuint64EXT x);
+GLAPI void APIENTRY glUniform2ui64NV (GLint location, GLuint64EXT x, GLuint64EXT y);
+GLAPI void APIENTRY glUniform3ui64NV (GLint location, GLuint64EXT x, GLuint64EXT y, GLuint64EXT z);
+GLAPI void APIENTRY glUniform4ui64NV (GLint location, GLuint64EXT x, GLuint64EXT y, GLuint64EXT z, GLuint64EXT w);
+GLAPI void APIENTRY glUniform1ui64vNV (GLint location, GLsizei count, const GLuint64EXT *value);
+GLAPI void APIENTRY glUniform2ui64vNV (GLint location, GLsizei count, const GLuint64EXT *value);
+GLAPI void APIENTRY glUniform3ui64vNV (GLint location, GLsizei count, const GLuint64EXT *value);
+GLAPI void APIENTRY glUniform4ui64vNV (GLint location, GLsizei count, const GLuint64EXT *value);
+GLAPI void APIENTRY glGetUniformi64vNV (GLuint program, GLint location, GLint64EXT *params);
+GLAPI void APIENTRY glProgramUniform1i64NV (GLuint program, GLint location, GLint64EXT x);
+GLAPI void APIENTRY glProgramUniform2i64NV (GLuint program, GLint location, GLint64EXT x, GLint64EXT y);
+GLAPI void APIENTRY glProgramUniform3i64NV (GLuint program, GLint location, GLint64EXT x, GLint64EXT y, GLint64EXT z);
+GLAPI void APIENTRY glProgramUniform4i64NV (GLuint program, GLint location, GLint64EXT x, GLint64EXT y, GLint64EXT z, GLint64EXT w);
+GLAPI void APIENTRY glProgramUniform1i64vNV (GLuint program, GLint location, GLsizei count, const GLint64EXT *value);
+GLAPI void APIENTRY glProgramUniform2i64vNV (GLuint program, GLint location, GLsizei count, const GLint64EXT *value);
+GLAPI void APIENTRY glProgramUniform3i64vNV (GLuint program, GLint location, GLsizei count, const GLint64EXT *value);
+GLAPI void APIENTRY glProgramUniform4i64vNV (GLuint program, GLint location, GLsizei count, const GLint64EXT *value);
+GLAPI void APIENTRY glProgramUniform1ui64NV (GLuint program, GLint location, GLuint64EXT x);
+GLAPI void APIENTRY glProgramUniform2ui64NV (GLuint program, GLint location, GLuint64EXT x, GLuint64EXT y);
+GLAPI void APIENTRY glProgramUniform3ui64NV (GLuint program, GLint location, GLuint64EXT x, GLuint64EXT y, GLuint64EXT z);
+GLAPI void APIENTRY glProgramUniform4ui64NV (GLuint program, GLint location, GLuint64EXT x, GLuint64EXT y, GLuint64EXT z, GLuint64EXT w);
+GLAPI void APIENTRY glProgramUniform1ui64vNV (GLuint program, GLint location, GLsizei count, const GLuint64EXT *value);
+GLAPI void APIENTRY glProgramUniform2ui64vNV (GLuint program, GLint location, GLsizei count, const GLuint64EXT *value);
+GLAPI void APIENTRY glProgramUniform3ui64vNV (GLuint program, GLint location, GLsizei count, const GLuint64EXT *value);
+GLAPI void APIENTRY glProgramUniform4ui64vNV (GLuint program, GLint location, GLsizei count, const GLuint64EXT *value);
+#endif
+typedef void (APIENTRYP PFNGLUNIFORM1I64NVPROC) (GLint location, GLint64EXT x);
+typedef void (APIENTRYP PFNGLUNIFORM2I64NVPROC) (GLint location, GLint64EXT x, GLint64EXT y);
+typedef void (APIENTRYP PFNGLUNIFORM3I64NVPROC) (GLint location, GLint64EXT x, GLint64EXT y, GLint64EXT z);
+typedef void (APIENTRYP PFNGLUNIFORM4I64NVPROC) (GLint location, GLint64EXT x, GLint64EXT y, GLint64EXT z, GLint64EXT w);
+typedef void (APIENTRYP PFNGLUNIFORM1I64VNVPROC) (GLint location, GLsizei count, const GLint64EXT *value);
+typedef void (APIENTRYP PFNGLUNIFORM2I64VNVPROC) (GLint location, GLsizei count, const GLint64EXT *value);
+typedef void (APIENTRYP PFNGLUNIFORM3I64VNVPROC) (GLint location, GLsizei count, const GLint64EXT *value);
+typedef void (APIENTRYP PFNGLUNIFORM4I64VNVPROC) (GLint location, GLsizei count, const GLint64EXT *value);
+typedef void (APIENTRYP PFNGLUNIFORM1UI64NVPROC) (GLint location, GLuint64EXT x);
+typedef void (APIENTRYP PFNGLUNIFORM2UI64NVPROC) (GLint location, GLuint64EXT x, GLuint64EXT y);
+typedef void (APIENTRYP PFNGLUNIFORM3UI64NVPROC) (GLint location, GLuint64EXT x, GLuint64EXT y, GLuint64EXT z);
+typedef void (APIENTRYP PFNGLUNIFORM4UI64NVPROC) (GLint location, GLuint64EXT x, GLuint64EXT y, GLuint64EXT z, GLuint64EXT w);
+typedef void (APIENTRYP PFNGLUNIFORM1UI64VNVPROC) (GLint location, GLsizei count, const GLuint64EXT *value);
+typedef void (APIENTRYP PFNGLUNIFORM2UI64VNVPROC) (GLint location, GLsizei count, const GLuint64EXT *value);
+typedef void (APIENTRYP PFNGLUNIFORM3UI64VNVPROC) (GLint location, GLsizei count, const GLuint64EXT *value);
+typedef void (APIENTRYP PFNGLUNIFORM4UI64VNVPROC) (GLint location, GLsizei count, const GLuint64EXT *value);
+typedef void (APIENTRYP PFNGLGETUNIFORMI64VNVPROC) (GLuint program, GLint location, GLint64EXT *params);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM1I64NVPROC) (GLuint program, GLint location, GLint64EXT x);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM2I64NVPROC) (GLuint program, GLint location, GLint64EXT x, GLint64EXT y);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM3I64NVPROC) (GLuint program, GLint location, GLint64EXT x, GLint64EXT y, GLint64EXT z);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM4I64NVPROC) (GLuint program, GLint location, GLint64EXT x, GLint64EXT y, GLint64EXT z, GLint64EXT w);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM1I64VNVPROC) (GLuint program, GLint location, GLsizei count, const GLint64EXT *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM2I64VNVPROC) (GLuint program, GLint location, GLsizei count, const GLint64EXT *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM3I64VNVPROC) (GLuint program, GLint location, GLsizei count, const GLint64EXT *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM4I64VNVPROC) (GLuint program, GLint location, GLsizei count, const GLint64EXT *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM1UI64NVPROC) (GLuint program, GLint location, GLuint64EXT x);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM2UI64NVPROC) (GLuint program, GLint location, GLuint64EXT x, GLuint64EXT y);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM3UI64NVPROC) (GLuint program, GLint location, GLuint64EXT x, GLuint64EXT y, GLuint64EXT z);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM4UI64NVPROC) (GLuint program, GLint location, GLuint64EXT x, GLuint64EXT y, GLuint64EXT z, GLuint64EXT w);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM1UI64VNVPROC) (GLuint program, GLint location, GLsizei count, const GLuint64EXT *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM2UI64VNVPROC) (GLuint program, GLint location, GLsizei count, const GLuint64EXT *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM3UI64VNVPROC) (GLuint program, GLint location, GLsizei count, const GLuint64EXT *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM4UI64VNVPROC) (GLuint program, GLint location, GLsizei count, const GLuint64EXT *value);
+#endif
+
+#ifndef GL_NV_shader_buffer_store
+#define GL_NV_shader_buffer_store 1
+#endif
+
+#ifndef GL_NV_tessellation_program5
+#define GL_NV_tessellation_program5 1
+#endif
+
+#ifndef GL_NV_vertex_attrib_integer_64bit
+#define GL_NV_vertex_attrib_integer_64bit 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glVertexAttribL1i64NV (GLuint index, GLint64EXT x);
+GLAPI void APIENTRY glVertexAttribL2i64NV (GLuint index, GLint64EXT x, GLint64EXT y);
+GLAPI void APIENTRY glVertexAttribL3i64NV (GLuint index, GLint64EXT x, GLint64EXT y, GLint64EXT z);
+GLAPI void APIENTRY glVertexAttribL4i64NV (GLuint index, GLint64EXT x, GLint64EXT y, GLint64EXT z, GLint64EXT w);
+GLAPI void APIENTRY glVertexAttribL1i64vNV (GLuint index, const GLint64EXT *v);
+GLAPI void APIENTRY glVertexAttribL2i64vNV (GLuint index, const GLint64EXT *v);
+GLAPI void APIENTRY glVertexAttribL3i64vNV (GLuint index, const GLint64EXT *v);
+GLAPI void APIENTRY glVertexAttribL4i64vNV (GLuint index, const GLint64EXT *v);
+GLAPI void APIENTRY glVertexAttribL1ui64NV (GLuint index, GLuint64EXT x);
+GLAPI void APIENTRY glVertexAttribL2ui64NV (GLuint index, GLuint64EXT x, GLuint64EXT y);
+GLAPI void APIENTRY glVertexAttribL3ui64NV (GLuint index, GLuint64EXT x, GLuint64EXT y, GLuint64EXT z);
+GLAPI void APIENTRY glVertexAttribL4ui64NV (GLuint index, GLuint64EXT x, GLuint64EXT y, GLuint64EXT z, GLuint64EXT w);
+GLAPI void APIENTRY glVertexAttribL1ui64vNV (GLuint index, const GLuint64EXT *v);
+GLAPI void APIENTRY glVertexAttribL2ui64vNV (GLuint index, const GLuint64EXT *v);
+GLAPI void APIENTRY glVertexAttribL3ui64vNV (GLuint index, const GLuint64EXT *v);
+GLAPI void APIENTRY glVertexAttribL4ui64vNV (GLuint index, const GLuint64EXT *v);
+GLAPI void APIENTRY glGetVertexAttribLi64vNV (GLuint index, GLenum pname, GLint64EXT *params);
+GLAPI void APIENTRY glGetVertexAttribLui64vNV (GLuint index, GLenum pname, GLuint64EXT *params);
+GLAPI void APIENTRY glVertexAttribLFormatNV (GLuint index, GLint size, GLenum type, GLsizei stride);
+#endif
+typedef void (APIENTRYP PFNGLVERTEXATTRIBL1I64NVPROC) (GLuint index, GLint64EXT x);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBL2I64NVPROC) (GLuint index, GLint64EXT x, GLint64EXT y);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBL3I64NVPROC) (GLuint index, GLint64EXT x, GLint64EXT y, GLint64EXT z);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBL4I64NVPROC) (GLuint index, GLint64EXT x, GLint64EXT y, GLint64EXT z, GLint64EXT w);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBL1I64VNVPROC) (GLuint index, const GLint64EXT *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBL2I64VNVPROC) (GLuint index, const GLint64EXT *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBL3I64VNVPROC) (GLuint index, const GLint64EXT *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBL4I64VNVPROC) (GLuint index, const GLint64EXT *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBL1UI64NVPROC) (GLuint index, GLuint64EXT x);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBL2UI64NVPROC) (GLuint index, GLuint64EXT x, GLuint64EXT y);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBL3UI64NVPROC) (GLuint index, GLuint64EXT x, GLuint64EXT y, GLuint64EXT z);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBL4UI64NVPROC) (GLuint index, GLuint64EXT x, GLuint64EXT y, GLuint64EXT z, GLuint64EXT w);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBL1UI64VNVPROC) (GLuint index, const GLuint64EXT *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBL2UI64VNVPROC) (GLuint index, const GLuint64EXT *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBL3UI64VNVPROC) (GLuint index, const GLuint64EXT *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBL4UI64VNVPROC) (GLuint index, const GLuint64EXT *v);
+typedef void (APIENTRYP PFNGLGETVERTEXATTRIBLI64VNVPROC) (GLuint index, GLenum pname, GLint64EXT *params);
+typedef void (APIENTRYP PFNGLGETVERTEXATTRIBLUI64VNVPROC) (GLuint index, GLenum pname, GLuint64EXT *params);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBLFORMATNVPROC) (GLuint index, GLint size, GLenum type, GLsizei stride);
+#endif
+
+#ifndef GL_NV_multisample_coverage
+#define GL_NV_multisample_coverage 1
+#endif
+
+#ifndef GL_AMD_name_gen_delete
+#define GL_AMD_name_gen_delete 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glGenNamesAMD (GLenum identifier, GLuint num, GLuint *names);
+GLAPI void APIENTRY glDeleteNamesAMD (GLenum identifier, GLuint num, const GLuint *names);
+GLAPI GLboolean APIENTRY glIsNameAMD (GLenum identifier, GLuint name);
+#endif
+typedef void (APIENTRYP PFNGLGENNAMESAMDPROC) (GLenum identifier, GLuint num, GLuint *names);
+typedef void (APIENTRYP PFNGLDELETENAMESAMDPROC) (GLenum identifier, GLuint num, const GLuint *names);
+typedef GLboolean (APIENTRYP PFNGLISNAMEAMDPROC) (GLenum identifier, GLuint name);
+#endif
+
+#ifndef GL_AMD_debug_output
+#define GL_AMD_debug_output 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glDebugMessageEnableAMD (GLenum category, GLenum severity, GLsizei count, const GLuint *ids, GLboolean enabled);
+GLAPI void APIENTRY glDebugMessageInsertAMD (GLenum category, GLenum severity, GLuint id, GLsizei length, const GLchar *buf);
+GLAPI void APIENTRY glDebugMessageCallbackAMD (GLDEBUGPROCAMD callback, GLvoid *userParam);
+GLAPI GLuint APIENTRY glGetDebugMessageLogAMD (GLuint count, GLsizei bufsize, GLenum *categories, GLuint *severities, GLuint *ids, GLsizei *lengths, GLchar *message);
+#endif
+typedef void (APIENTRYP PFNGLDEBUGMESSAGEENABLEAMDPROC) (GLenum category, GLenum severity, GLsizei count, const GLuint *ids, GLboolean enabled);
+typedef void (APIENTRYP PFNGLDEBUGMESSAGEINSERTAMDPROC) (GLenum category, GLenum severity, GLuint id, GLsizei length, const GLchar *buf);
+typedef void (APIENTRYP PFNGLDEBUGMESSAGECALLBACKAMDPROC) (GLDEBUGPROCAMD callback, GLvoid *userParam);
+typedef GLuint (APIENTRYP PFNGLGETDEBUGMESSAGELOGAMDPROC) (GLuint count, GLsizei bufsize, GLenum *categories, GLuint *severities, GLuint *ids, GLsizei *lengths, GLchar *message);
+#endif
+
+#ifndef GL_NV_vdpau_interop
+#define GL_NV_vdpau_interop 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glVDPAUInitNV (const GLvoid *vdpDevice, const GLvoid *getProcAddress);
+GLAPI void APIENTRY glVDPAUFiniNV (void);
+GLAPI GLvdpauSurfaceNV APIENTRY glVDPAURegisterVideoSurfaceNV (GLvoid *vdpSurface, GLenum target, GLsizei numTextureNames, const GLuint *textureNames);
+GLAPI GLvdpauSurfaceNV APIENTRY glVDPAURegisterOutputSurfaceNV (GLvoid *vdpSurface, GLenum target, GLsizei numTextureNames, const GLuint *textureNames);
+GLAPI void APIENTRY glVDPAUIsSurfaceNV (GLvdpauSurfaceNV surface);
+GLAPI void APIENTRY glVDPAUUnregisterSurfaceNV (GLvdpauSurfaceNV surface);
+GLAPI void APIENTRY glVDPAUGetSurfaceivNV (GLvdpauSurfaceNV surface, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *values);
+GLAPI void APIENTRY glVDPAUSurfaceAccessNV (GLvdpauSurfaceNV surface, GLenum access);
+GLAPI void APIENTRY glVDPAUMapSurfacesNV (GLsizei numSurfaces, const GLvdpauSurfaceNV *surfaces);
+GLAPI void APIENTRY glVDPAUUnmapSurfacesNV (GLsizei numSurface, const GLvdpauSurfaceNV *surfaces);
+#endif
+typedef void (APIENTRYP PFNGLVDPAUINITNVPROC) (const GLvoid *vdpDevice, const GLvoid *getProcAddress);
+typedef void (APIENTRYP PFNGLVDPAUFININVPROC) (void);
+typedef GLvdpauSurfaceNV (APIENTRYP PFNGLVDPAUREGISTERVIDEOSURFACENVPROC) (GLvoid *vdpSurface, GLenum target, GLsizei numTextureNames, const GLuint *textureNames);
+typedef GLvdpauSurfaceNV (APIENTRYP PFNGLVDPAUREGISTEROUTPUTSURFACENVPROC) (GLvoid *vdpSurface, GLenum target, GLsizei numTextureNames, const GLuint *textureNames);
+typedef void (APIENTRYP PFNGLVDPAUISSURFACENVPROC) (GLvdpauSurfaceNV surface);
+typedef void (APIENTRYP PFNGLVDPAUUNREGISTERSURFACENVPROC) (GLvdpauSurfaceNV surface);
+typedef void (APIENTRYP PFNGLVDPAUGETSURFACEIVNVPROC) (GLvdpauSurfaceNV surface, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *values);
+typedef void (APIENTRYP PFNGLVDPAUSURFACEACCESSNVPROC) (GLvdpauSurfaceNV surface, GLenum access);
+typedef void (APIENTRYP PFNGLVDPAUMAPSURFACESNVPROC) (GLsizei numSurfaces, const GLvdpauSurfaceNV *surfaces);
+typedef void (APIENTRYP PFNGLVDPAUUNMAPSURFACESNVPROC) (GLsizei numSurface, const GLvdpauSurfaceNV *surfaces);
+#endif
+
+#ifndef GL_AMD_transform_feedback3_lines_triangles
+#define GL_AMD_transform_feedback3_lines_triangles 1
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+#endif
+
+#endif
+
+#endif
+
diff --git a/extern/sdlew/include/SDL2/SDL_opengles.h b/extern/sdlew/include/SDL2/SDL_opengles.h
new file mode 100644
index 00000000000..f55a8630835
--- /dev/null
+++ b/extern/sdlew/include/SDL2/SDL_opengles.h
@@ -0,0 +1,12 @@
+
+#ifdef __IPHONEOS__
+#include <OpenGLES/ES1/gl.h>
+#include <OpenGLES/ES1/glext.h>
+#else
+#include <GLES/gl.h>
+#include <GLES/glext.h>
+#endif
+
+#ifndef APIENTRY
+#define APIENTRY
+#endif
diff --git a/extern/sdlew/include/SDL2/SDL_opengles2.h b/extern/sdlew/include/SDL2/SDL_opengles2.h
new file mode 100644
index 00000000000..87a92612369
--- /dev/null
+++ b/extern/sdlew/include/SDL2/SDL_opengles2.h
@@ -0,0 +1,12 @@
+
+#ifdef __IPHONEOS__
+#include <OpenGLES/ES2/gl.h>
+#include <OpenGLES/ES2/glext.h>
+#else
+#include <GLES2/gl2.h>
+#include <GLES2/gl2ext.h>
+#endif
+
+#ifndef APIENTRY
+#define APIENTRY
+#endif
diff --git a/extern/sdlew/include/SDL2/SDL_pixels.h b/extern/sdlew/include/SDL2/SDL_pixels.h
new file mode 100644
index 00000000000..bc919d38155
--- /dev/null
+++ b/extern/sdlew/include/SDL2/SDL_pixels.h
@@ -0,0 +1,320 @@
+
+#ifndef _SDL_pixels_h
+#define _SDL_pixels_h
+
+#include "begin_code.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define SDL_ALPHA_OPAQUE 255
+#define SDL_ALPHA_TRANSPARENT 0
+
+enum
+{
+ SDL_PIXELTYPE_UNKNOWN,
+ SDL_PIXELTYPE_INDEX1,
+ SDL_PIXELTYPE_INDEX4,
+ SDL_PIXELTYPE_INDEX8,
+ SDL_PIXELTYPE_PACKED8,
+ SDL_PIXELTYPE_PACKED16,
+ SDL_PIXELTYPE_PACKED32,
+ SDL_PIXELTYPE_ARRAYU8,
+ SDL_PIXELTYPE_ARRAYU16,
+ SDL_PIXELTYPE_ARRAYU32,
+ SDL_PIXELTYPE_ARRAYF16,
+ SDL_PIXELTYPE_ARRAYF32
+};
+
+enum
+{
+ SDL_BITMAPORDER_NONE,
+ SDL_BITMAPORDER_4321,
+ SDL_BITMAPORDER_1234
+};
+
+enum
+{
+ SDL_PACKEDORDER_NONE,
+ SDL_PACKEDORDER_XRGB,
+ SDL_PACKEDORDER_RGBX,
+ SDL_PACKEDORDER_ARGB,
+ SDL_PACKEDORDER_RGBA,
+ SDL_PACKEDORDER_XBGR,
+ SDL_PACKEDORDER_BGRX,
+ SDL_PACKEDORDER_ABGR,
+ SDL_PACKEDORDER_BGRA
+};
+
+enum
+{
+ SDL_ARRAYORDER_NONE,
+ SDL_ARRAYORDER_RGB,
+ SDL_ARRAYORDER_RGBA,
+ SDL_ARRAYORDER_ARGB,
+ SDL_ARRAYORDER_BGR,
+ SDL_ARRAYORDER_BGRA,
+ SDL_ARRAYORDER_ABGR
+};
+
+enum
+{
+ SDL_PACKEDLAYOUT_NONE,
+ SDL_PACKEDLAYOUT_332,
+ SDL_PACKEDLAYOUT_4444,
+ SDL_PACKEDLAYOUT_1555,
+ SDL_PACKEDLAYOUT_5551,
+ SDL_PACKEDLAYOUT_565,
+ SDL_PACKEDLAYOUT_8888,
+ SDL_PACKEDLAYOUT_2101010,
+ SDL_PACKEDLAYOUT_1010102
+};
+
+#define SDL_DEFINE_PIXELFOURCC(A, B, C, D) SDL_FOURCC(A, B, C, D)
+
+#define SDL_DEFINE_PIXELFORMAT(type, order, layout, bits, bytes) \
+ ((1 << 28) | ((type) << 24) | ((order) << 20) | ((layout) << 16) | \
+ ((bits) << 8) | ((bytes) << 0))
+
+#define SDL_PIXELFLAG(X) (((X) >> 28) & 0x0F)
+#define SDL_PIXELTYPE(X) (((X) >> 24) & 0x0F)
+#define SDL_PIXELORDER(X) (((X) >> 20) & 0x0F)
+#define SDL_PIXELLAYOUT(X) (((X) >> 16) & 0x0F)
+#define SDL_BITSPERPIXEL(X) (((X) >> 8) & 0xFF)
+#define SDL_BYTESPERPIXEL(X) \
+ (SDL_ISPIXELFORMAT_FOURCC(X) ? \
+ ((((X) == SDL_PIXELFORMAT_YUY2) || \
+ ((X) == SDL_PIXELFORMAT_UYVY) || \
+ ((X) == SDL_PIXELFORMAT_YVYU)) ? 2 : 1) : (((X) >> 0) & 0xFF))
+
+#define SDL_ISPIXELFORMAT_INDEXED(format) \
+ (!SDL_ISPIXELFORMAT_FOURCC(format) && \
+ ((SDL_PIXELTYPE(format) == SDL_PIXELTYPE_INDEX1) || \
+ (SDL_PIXELTYPE(format) == SDL_PIXELTYPE_INDEX4) || \
+ (SDL_PIXELTYPE(format) == SDL_PIXELTYPE_INDEX8)))
+
+#define SDL_ISPIXELFORMAT_ALPHA(format) \
+ (!SDL_ISPIXELFORMAT_FOURCC(format) && \
+ ((SDL_PIXELORDER(format) == SDL_PACKEDORDER_ARGB) || \
+ (SDL_PIXELORDER(format) == SDL_PACKEDORDER_RGBA) || \
+ (SDL_PIXELORDER(format) == SDL_PACKEDORDER_ABGR) || \
+ (SDL_PIXELORDER(format) == SDL_PACKEDORDER_BGRA)))
+
+#define SDL_ISPIXELFORMAT_FOURCC(format) \
+ ((format) && (SDL_PIXELFLAG(format) != 1))
+
+enum
+{
+ SDL_PIXELFORMAT_UNKNOWN,
+ SDL_PIXELFORMAT_INDEX1LSB =
+ SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_INDEX1, SDL_BITMAPORDER_4321, 0,
+ 1, 0),
+ SDL_PIXELFORMAT_INDEX1MSB =
+ SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_INDEX1, SDL_BITMAPORDER_1234, 0,
+ 1, 0),
+ SDL_PIXELFORMAT_INDEX4LSB =
+ SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_INDEX4, SDL_BITMAPORDER_4321, 0,
+ 4, 0),
+ SDL_PIXELFORMAT_INDEX4MSB =
+ SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_INDEX4, SDL_BITMAPORDER_1234, 0,
+ 4, 0),
+ SDL_PIXELFORMAT_INDEX8 =
+ SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_INDEX8, 0, 0, 8, 1),
+ SDL_PIXELFORMAT_RGB332 =
+ SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED8, SDL_PACKEDORDER_XRGB,
+ SDL_PACKEDLAYOUT_332, 8, 1),
+ SDL_PIXELFORMAT_RGB444 =
+ SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED16, SDL_PACKEDORDER_XRGB,
+ SDL_PACKEDLAYOUT_4444, 12, 2),
+ SDL_PIXELFORMAT_RGB555 =
+ SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED16, SDL_PACKEDORDER_XRGB,
+ SDL_PACKEDLAYOUT_1555, 15, 2),
+ SDL_PIXELFORMAT_BGR555 =
+ SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED16, SDL_PACKEDORDER_XBGR,
+ SDL_PACKEDLAYOUT_1555, 15, 2),
+ SDL_PIXELFORMAT_ARGB4444 =
+ SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED16, SDL_PACKEDORDER_ARGB,
+ SDL_PACKEDLAYOUT_4444, 16, 2),
+ SDL_PIXELFORMAT_RGBA4444 =
+ SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED16, SDL_PACKEDORDER_RGBA,
+ SDL_PACKEDLAYOUT_4444, 16, 2),
+ SDL_PIXELFORMAT_ABGR4444 =
+ SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED16, SDL_PACKEDORDER_ABGR,
+ SDL_PACKEDLAYOUT_4444, 16, 2),
+ SDL_PIXELFORMAT_BGRA4444 =
+ SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED16, SDL_PACKEDORDER_BGRA,
+ SDL_PACKEDLAYOUT_4444, 16, 2),
+ SDL_PIXELFORMAT_ARGB1555 =
+ SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED16, SDL_PACKEDORDER_ARGB,
+ SDL_PACKEDLAYOUT_1555, 16, 2),
+ SDL_PIXELFORMAT_RGBA5551 =
+ SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED16, SDL_PACKEDORDER_RGBA,
+ SDL_PACKEDLAYOUT_5551, 16, 2),
+ SDL_PIXELFORMAT_ABGR1555 =
+ SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED16, SDL_PACKEDORDER_ABGR,
+ SDL_PACKEDLAYOUT_1555, 16, 2),
+ SDL_PIXELFORMAT_BGRA5551 =
+ SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED16, SDL_PACKEDORDER_BGRA,
+ SDL_PACKEDLAYOUT_5551, 16, 2),
+ SDL_PIXELFORMAT_RGB565 =
+ SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED16, SDL_PACKEDORDER_XRGB,
+ SDL_PACKEDLAYOUT_565, 16, 2),
+ SDL_PIXELFORMAT_BGR565 =
+ SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED16, SDL_PACKEDORDER_XBGR,
+ SDL_PACKEDLAYOUT_565, 16, 2),
+ SDL_PIXELFORMAT_RGB24 =
+ SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_ARRAYU8, SDL_ARRAYORDER_RGB, 0,
+ 24, 3),
+ SDL_PIXELFORMAT_BGR24 =
+ SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_ARRAYU8, SDL_ARRAYORDER_BGR, 0,
+ 24, 3),
+ SDL_PIXELFORMAT_RGB888 =
+ SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED32, SDL_PACKEDORDER_XRGB,
+ SDL_PACKEDLAYOUT_8888, 24, 4),
+ SDL_PIXELFORMAT_RGBX8888 =
+ SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED32, SDL_PACKEDORDER_RGBX,
+ SDL_PACKEDLAYOUT_8888, 24, 4),
+ SDL_PIXELFORMAT_BGR888 =
+ SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED32, SDL_PACKEDORDER_XBGR,
+ SDL_PACKEDLAYOUT_8888, 24, 4),
+ SDL_PIXELFORMAT_BGRX8888 =
+ SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED32, SDL_PACKEDORDER_BGRX,
+ SDL_PACKEDLAYOUT_8888, 24, 4),
+ SDL_PIXELFORMAT_ARGB8888 =
+ SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED32, SDL_PACKEDORDER_ARGB,
+ SDL_PACKEDLAYOUT_8888, 32, 4),
+ SDL_PIXELFORMAT_RGBA8888 =
+ SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED32, SDL_PACKEDORDER_RGBA,
+ SDL_PACKEDLAYOUT_8888, 32, 4),
+ SDL_PIXELFORMAT_ABGR8888 =
+ SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED32, SDL_PACKEDORDER_ABGR,
+ SDL_PACKEDLAYOUT_8888, 32, 4),
+ SDL_PIXELFORMAT_BGRA8888 =
+ SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED32, SDL_PACKEDORDER_BGRA,
+ SDL_PACKEDLAYOUT_8888, 32, 4),
+ SDL_PIXELFORMAT_ARGB2101010 =
+ SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED32, SDL_PACKEDORDER_ARGB,
+ SDL_PACKEDLAYOUT_2101010, 32, 4),
+
+ SDL_PIXELFORMAT_YV12 =
+ SDL_DEFINE_PIXELFOURCC('Y', 'V', '1', '2'),
+ SDL_PIXELFORMAT_IYUV =
+ SDL_DEFINE_PIXELFOURCC('I', 'Y', 'U', 'V'),
+ SDL_PIXELFORMAT_YUY2 =
+ SDL_DEFINE_PIXELFOURCC('Y', 'U', 'Y', '2'),
+ SDL_PIXELFORMAT_UYVY =
+ SDL_DEFINE_PIXELFOURCC('U', 'Y', 'V', 'Y'),
+ SDL_PIXELFORMAT_YVYU =
+ SDL_DEFINE_PIXELFOURCC('Y', 'V', 'Y', 'U')
+};
+
+typedef struct SDL_Color
+{
+ Uint8 r;
+ Uint8 g;
+ Uint8 b;
+ Uint8 a;
+} SDL_Color;
+#define SDL_Colour SDL_Color
+
+typedef struct SDL_Palette
+{
+ int ncolors;
+ SDL_Color *colors;
+ Uint32 version;
+ int refcount;
+} SDL_Palette;
+
+typedef struct SDL_PixelFormat
+{
+ Uint32 format;
+ SDL_Palette *palette;
+ Uint8 BitsPerPixel;
+ Uint8 BytesPerPixel;
+ Uint8 padding[2];
+ Uint32 Rmask;
+ Uint32 Gmask;
+ Uint32 Bmask;
+ Uint32 Amask;
+ Uint8 Rloss;
+ Uint8 Gloss;
+ Uint8 Bloss;
+ Uint8 Aloss;
+ Uint8 Rshift;
+ Uint8 Gshift;
+ Uint8 Bshift;
+ Uint8 Ashift;
+ int refcount;
+ struct SDL_PixelFormat *next;
+} SDL_PixelFormat;
+
+extern DECLSPEC const char* SDLCALL SDL_GetPixelFormatName(Uint32 format);
+
+typedef SDL_bool SDLCALL tSDL_PixelFormatEnumToMasks(Uint32 format,
+ int *bpp,
+ Uint32 * Rmask,
+ Uint32 * Gmask,
+ Uint32 * Bmask,
+ Uint32 * Amask);
+
+typedef Uint32 SDLCALL tSDL_MasksToPixelFormatEnum(int bpp,
+ Uint32 Rmask,
+ Uint32 Gmask,
+ Uint32 Bmask,
+ Uint32 Amask);
+
+typedef SDL_PixelFormat * SDLCALL tSDL_AllocFormat(Uint32 pixel_format);
+
+typedef void SDLCALL tSDL_FreeFormat(SDL_PixelFormat *format);
+
+typedef SDL_Palette * SDLCALL tSDL_AllocPalette(int ncolors);
+
+typedef int SDLCALL tSDL_SetPixelFormatPalette(SDL_PixelFormat * format,
+ SDL_Palette *palette);
+
+typedef int SDLCALL tSDL_SetPaletteColors(SDL_Palette * palette,
+ const SDL_Color * colors,
+ int firstcolor, int ncolors);
+
+typedef void SDLCALL tSDL_FreePalette(SDL_Palette * palette);
+
+typedef Uint32 SDLCALL tSDL_MapRGB(const SDL_PixelFormat * format,
+ Uint8 r, Uint8 g, Uint8 b);
+
+typedef Uint32 SDLCALL tSDL_MapRGBA(const SDL_PixelFormat * format,
+ Uint8 r, Uint8 g, Uint8 b,
+ Uint8 a);
+
+typedef void SDLCALL tSDL_GetRGB(Uint32 pixel,
+ const SDL_PixelFormat * format,
+ Uint8 * r, Uint8 * g, Uint8 * b);
+
+typedef void SDLCALL tSDL_GetRGBA(Uint32 pixel,
+ const SDL_PixelFormat * format,
+ Uint8 * r, Uint8 * g, Uint8 * b,
+ Uint8 * a);
+
+typedef void SDLCALL tSDL_CalculateGammaRamp(float gamma, Uint16 * ramp);
+
+extern tSDL_PixelFormatEnumToMasks *SDL_PixelFormatEnumToMasks;
+extern tSDL_MasksToPixelFormatEnum *SDL_MasksToPixelFormatEnum;
+extern tSDL_AllocFormat *SDL_AllocFormat;
+extern tSDL_FreeFormat *SDL_FreeFormat;
+extern tSDL_AllocPalette *SDL_AllocPalette;
+extern tSDL_SetPixelFormatPalette *SDL_SetPixelFormatPalette;
+extern tSDL_SetPaletteColors *SDL_SetPaletteColors;
+extern tSDL_FreePalette *SDL_FreePalette;
+extern tSDL_MapRGB *SDL_MapRGB;
+extern tSDL_MapRGBA *SDL_MapRGBA;
+extern tSDL_GetRGB *SDL_GetRGB;
+extern tSDL_GetRGBA *SDL_GetRGBA;
+extern tSDL_CalculateGammaRamp *SDL_CalculateGammaRamp;
+
+#ifdef __cplusplus
+}
+#endif
+#include "close_code.h"
+
+#endif
+
diff --git a/extern/sdlew/include/SDL2/SDL_platform.h b/extern/sdlew/include/SDL2/SDL_platform.h
new file mode 100644
index 00000000000..6f18a970e4f
--- /dev/null
+++ b/extern/sdlew/include/SDL2/SDL_platform.h
@@ -0,0 +1,122 @@
+
+#ifndef _SDL_platform_h
+#define _SDL_platform_h
+
+#if defined(_AIX)
+#undef __AIX__
+#define __AIX__ 1
+#endif
+#if defined(__BEOS__)
+#undef __BEOS__
+#define __BEOS__ 1
+#endif
+#if defined(__HAIKU__)
+#undef __HAIKU__
+#define __HAIKU__ 1
+#endif
+#if defined(bsdi) || defined(__bsdi) || defined(__bsdi__)
+#undef __BSDI__
+#define __BSDI__ 1
+#endif
+#if defined(_arch_dreamcast)
+#undef __DREAMCAST__
+#define __DREAMCAST__ 1
+#endif
+#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
+#undef __FREEBSD__
+#define __FREEBSD__ 1
+#endif
+#if defined(hpux) || defined(__hpux) || defined(__hpux__)
+#undef __HPUX__
+#define __HPUX__ 1
+#endif
+#if defined(sgi) || defined(__sgi) || defined(__sgi__) || defined(_SGI_SOURCE)
+#undef __IRIX__
+#define __IRIX__ 1
+#endif
+#if defined(linux) || defined(__linux) || defined(__linux__)
+#undef __LINUX__
+#define __LINUX__ 1
+#endif
+#if defined(ANDROID)
+#undef __ANDROID__
+#undef __LINUX__
+#define __ANDROID__ 1
+#endif
+
+#if defined(__APPLE__)
+
+#include "AvailabilityMacros.h"
+#include "TargetConditionals.h"
+#if TARGET_OS_IPHONE
+
+#undef __IPHONEOS__
+#define __IPHONEOS__ 1
+#undef __MACOSX__
+#else
+
+#undef __MACOSX__
+#define __MACOSX__ 1
+#if MAC_OS_X_VERSION_MIN_REQUIRED < 1050
+# error SDL for Mac OS X only supports deploying on 10.5 and above.
+#endif
+#if MAC_OS_X_VERSION_MAX_ALLOWED < 1060
+# error SDL for Mac OS X must be built with a 10.6 SDK or above.
+#endif
+#endif
+#endif
+
+#if defined(__NetBSD__)
+#undef __NETBSD__
+#define __NETBSD__ 1
+#endif
+#if defined(__OpenBSD__)
+#undef __OPENBSD__
+#define __OPENBSD__ 1
+#endif
+#if defined(__OS2__)
+#undef __OS2__
+#define __OS2__ 1
+#endif
+#if defined(osf) || defined(__osf) || defined(__osf__) || defined(_OSF_SOURCE)
+#undef __OSF__
+#define __OSF__ 1
+#endif
+#if defined(__QNXNTO__)
+#undef __QNXNTO__
+#define __QNXNTO__ 1
+#endif
+#if defined(riscos) || defined(__riscos) || defined(__riscos__)
+#undef __RISCOS__
+#define __RISCOS__ 1
+#endif
+#if defined(__SVR4)
+#undef __SOLARIS__
+#define __SOLARIS__ 1
+#endif
+#if defined(WIN32) || defined(_WIN32) || defined(__CYGWIN__)
+#undef __WIN32__
+#define __WIN32__ 1
+#endif
+#if defined(__PSP__)
+#undef __PSP__
+#define __PSP__ 1
+#endif
+
+#include "begin_code.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef const char * SDLCALL tSDL_GetPlatform (void);
+
+extern tSDL_GetPlatform *SDL_GetPlatform;
+
+#ifdef __cplusplus
+}
+#endif
+#include "close_code.h"
+
+#endif
+
diff --git a/extern/sdlew/include/SDL2/SDL_power.h b/extern/sdlew/include/SDL2/SDL_power.h
new file mode 100644
index 00000000000..00d63072e7c
--- /dev/null
+++ b/extern/sdlew/include/SDL2/SDL_power.h
@@ -0,0 +1,32 @@
+
+#ifndef _SDL_power_h
+#define _SDL_power_h
+
+#include "SDL_stdinc.h"
+
+#include "begin_code.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef enum
+{
+ SDL_POWERSTATE_UNKNOWN,
+ SDL_POWERSTATE_ON_BATTERY,
+ SDL_POWERSTATE_NO_BATTERY,
+ SDL_POWERSTATE_CHARGING,
+ SDL_POWERSTATE_CHARGED
+} SDL_PowerState;
+
+typedef SDL_PowerState SDLCALL tSDL_GetPowerInfo(int *secs, int *pct);
+
+extern tSDL_GetPowerInfo *SDL_GetPowerInfo;
+
+#ifdef __cplusplus
+}
+#endif
+#include "close_code.h"
+
+#endif
+
diff --git a/extern/sdlew/include/SDL2/SDL_quit.h b/extern/sdlew/include/SDL2/SDL_quit.h
new file mode 100644
index 00000000000..a91450ec793
--- /dev/null
+++ b/extern/sdlew/include/SDL2/SDL_quit.h
@@ -0,0 +1,11 @@
+
+#ifndef _SDL_quit_h
+#define _SDL_quit_h
+
+#include "SDL_stdinc.h"
+#include "SDL_error.h"
+
+#define SDL_QuitRequested() \
+ (SDL_PumpEvents(), (SDL_PeepEvents(NULL,0,SDL_PEEKEVENT,SDL_QUIT,SDL_QUIT) > 0))
+
+#endif
diff --git a/extern/sdlew/include/SDL2/SDL_rect.h b/extern/sdlew/include/SDL2/SDL_rect.h
new file mode 100644
index 00000000000..36e0eb3eca1
--- /dev/null
+++ b/extern/sdlew/include/SDL2/SDL_rect.h
@@ -0,0 +1,72 @@
+
+#ifndef _SDL_rect_h
+#define _SDL_rect_h
+
+#include "SDL_stdinc.h"
+#include "SDL_error.h"
+#include "SDL_pixels.h"
+#include "SDL_rwops.h"
+
+#include "begin_code.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct
+{
+ int x;
+ int y;
+} SDL_Point;
+
+typedef struct SDL_Rect
+{
+ int x, y;
+ int w, h;
+} SDL_Rect;
+
+SDL_FORCE_INLINE SDL_bool SDL_RectEmpty(const SDL_Rect *r)
+{
+ return ((!r) || (r->w <= 0) || (r->h <= 0)) ? SDL_TRUE : SDL_FALSE;
+}
+
+SDL_FORCE_INLINE SDL_bool SDL_RectEquals(const SDL_Rect *a, const SDL_Rect *b)
+{
+ return (a && b && (a->x == b->x) && (a->y == b->y) &&
+ (a->w == b->w) && (a->h == b->h)) ? SDL_TRUE : SDL_FALSE;
+}
+
+typedef SDL_bool SDLCALL tSDL_HasIntersection(const SDL_Rect * A,
+ const SDL_Rect * B);
+
+typedef SDL_bool SDLCALL tSDL_IntersectRect(const SDL_Rect * A,
+ const SDL_Rect * B,
+ SDL_Rect * result);
+
+typedef void SDLCALL tSDL_UnionRect(const SDL_Rect * A,
+ const SDL_Rect * B,
+ SDL_Rect * result);
+
+typedef SDL_bool SDLCALL tSDL_EnclosePoints(const SDL_Point * points,
+ int count,
+ const SDL_Rect * clip,
+ SDL_Rect * result);
+
+typedef SDL_bool SDLCALL tSDL_IntersectRectAndLine(const SDL_Rect *
+ rect, int *X1,
+ int *Y1, int *X2,
+ int *Y2);
+
+extern tSDL_HasIntersection *SDL_HasIntersection;
+extern tSDL_IntersectRect *SDL_IntersectRect;
+extern tSDL_UnionRect *SDL_UnionRect;
+extern tSDL_EnclosePoints *SDL_EnclosePoints;
+extern tSDL_IntersectRectAndLine *SDL_IntersectRectAndLine;
+
+#ifdef __cplusplus
+}
+#endif
+#include "close_code.h"
+
+#endif
+
diff --git a/extern/sdlew/include/SDL2/SDL_render.h b/extern/sdlew/include/SDL2/SDL_render.h
new file mode 100644
index 00000000000..a68f47cec0d
--- /dev/null
+++ b/extern/sdlew/include/SDL2/SDL_render.h
@@ -0,0 +1,280 @@
+
+#ifndef _SDL_render_h
+#define _SDL_render_h
+
+#include "SDL_stdinc.h"
+#include "SDL_rect.h"
+#include "SDL_video.h"
+
+#include "begin_code.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef enum
+{
+ SDL_RENDERER_SOFTWARE = 0x00000001,
+ SDL_RENDERER_ACCELERATED = 0x00000002,
+ SDL_RENDERER_PRESENTVSYNC = 0x00000004,
+ SDL_RENDERER_TARGETTEXTURE = 0x00000008
+} SDL_RendererFlags;
+
+typedef struct SDL_RendererInfo
+{
+ const char *name;
+ Uint32 flags;
+ Uint32 num_texture_formats;
+ Uint32 texture_formats[16];
+ int max_texture_width;
+ int max_texture_height;
+} SDL_RendererInfo;
+
+typedef enum
+{
+ SDL_TEXTUREACCESS_STATIC,
+ SDL_TEXTUREACCESS_STREAMING,
+ SDL_TEXTUREACCESS_TARGET
+} SDL_TextureAccess;
+
+typedef enum
+{
+ SDL_TEXTUREMODULATE_NONE = 0x00000000,
+ SDL_TEXTUREMODULATE_COLOR = 0x00000001,
+ SDL_TEXTUREMODULATE_ALPHA = 0x00000002
+} SDL_TextureModulate;
+
+typedef enum
+{
+ SDL_FLIP_NONE = 0x00000000,
+ SDL_FLIP_HORIZONTAL = 0x00000001,
+ SDL_FLIP_VERTICAL = 0x00000002
+} SDL_RendererFlip;
+
+struct SDL_Renderer;
+typedef struct SDL_Renderer SDL_Renderer;
+
+struct SDL_Texture;
+typedef struct SDL_Texture SDL_Texture;
+
+typedef int SDLCALL tSDL_GetNumRenderDrivers(void);
+
+typedef int SDLCALL tSDL_GetRenderDriverInfo(int index,
+ SDL_RendererInfo * info);
+
+typedef int SDLCALL tSDL_CreateWindowAndRenderer(
+ int width, int height, Uint32 window_flags,
+ SDL_Window **window, SDL_Renderer **renderer);
+
+typedef SDL_Renderer * SDLCALL tSDL_CreateRenderer(SDL_Window * window,
+ int index, Uint32 flags);
+
+typedef SDL_Renderer * SDLCALL tSDL_CreateSoftwareRenderer(SDL_Surface * surface);
+
+typedef SDL_Renderer * SDLCALL tSDL_GetRenderer(SDL_Window * window);
+
+typedef int SDLCALL tSDL_GetRendererInfo(SDL_Renderer * renderer,
+ SDL_RendererInfo * info);
+
+typedef int SDLCALL tSDL_GetRendererOutputSize(SDL_Renderer * renderer,
+ int *w, int *h);
+
+typedef SDL_Texture * SDLCALL tSDL_CreateTexture(SDL_Renderer * renderer,
+ Uint32 format,
+ int access, int w,
+ int h);
+
+typedef SDL_Texture * SDLCALL tSDL_CreateTextureFromSurface(SDL_Renderer * renderer, SDL_Surface * surface);
+
+typedef int SDLCALL tSDL_QueryTexture(SDL_Texture * texture,
+ Uint32 * format, int *access,
+ int *w, int *h);
+
+typedef int SDLCALL tSDL_SetTextureColorMod(SDL_Texture * texture,
+ Uint8 r, Uint8 g, Uint8 b);
+
+typedef int SDLCALL tSDL_GetTextureColorMod(SDL_Texture * texture,
+ Uint8 * r, Uint8 * g,
+ Uint8 * b);
+
+typedef int SDLCALL tSDL_SetTextureAlphaMod(SDL_Texture * texture,
+ Uint8 alpha);
+
+typedef int SDLCALL tSDL_GetTextureAlphaMod(SDL_Texture * texture,
+ Uint8 * alpha);
+
+typedef int SDLCALL tSDL_SetTextureBlendMode(SDL_Texture * texture,
+ SDL_BlendMode blendMode);
+
+typedef int SDLCALL tSDL_GetTextureBlendMode(SDL_Texture * texture,
+ SDL_BlendMode *blendMode);
+
+typedef int SDLCALL tSDL_UpdateTexture(SDL_Texture * texture,
+ const SDL_Rect * rect,
+ const void *pixels, int pitch);
+
+typedef int SDLCALL tSDL_LockTexture(SDL_Texture * texture,
+ const SDL_Rect * rect,
+ void **pixels, int *pitch);
+
+typedef void SDLCALL tSDL_UnlockTexture(SDL_Texture * texture);
+
+typedef SDL_bool SDLCALL tSDL_RenderTargetSupported(SDL_Renderer *renderer);
+
+typedef int SDLCALL tSDL_SetRenderTarget(SDL_Renderer *renderer,
+ SDL_Texture *texture);
+
+typedef SDL_Texture * SDLCALL tSDL_GetRenderTarget(SDL_Renderer *renderer);
+
+typedef int SDLCALL tSDL_RenderSetLogicalSize(SDL_Renderer * renderer, int w, int h);
+
+typedef void SDLCALL tSDL_RenderGetLogicalSize(SDL_Renderer * renderer, int *w, int *h);
+
+typedef int SDLCALL tSDL_RenderSetViewport(SDL_Renderer * renderer,
+ const SDL_Rect * rect);
+
+typedef void SDLCALL tSDL_RenderGetViewport(SDL_Renderer * renderer,
+ SDL_Rect * rect);
+
+typedef int SDLCALL tSDL_RenderSetClipRect(SDL_Renderer * renderer,
+ const SDL_Rect * rect);
+
+typedef void SDLCALL tSDL_RenderGetClipRect(SDL_Renderer * renderer,
+ SDL_Rect * rect);
+
+typedef int SDLCALL tSDL_RenderSetScale(SDL_Renderer * renderer,
+ float scaleX, float scaleY);
+
+typedef void SDLCALL tSDL_RenderGetScale(SDL_Renderer * renderer,
+ float *scaleX, float *scaleY);
+
+extern DECLSPEC int SDL_SetRenderDrawColor(SDL_Renderer * renderer,
+ Uint8 r, Uint8 g, Uint8 b,
+ Uint8 a);
+
+extern DECLSPEC int SDL_GetRenderDrawColor(SDL_Renderer * renderer,
+ Uint8 * r, Uint8 * g, Uint8 * b,
+ Uint8 * a);
+
+typedef int SDLCALL tSDL_SetRenderDrawBlendMode(SDL_Renderer * renderer,
+ SDL_BlendMode blendMode);
+
+typedef int SDLCALL tSDL_GetRenderDrawBlendMode(SDL_Renderer * renderer,
+ SDL_BlendMode *blendMode);
+
+typedef int SDLCALL tSDL_RenderClear(SDL_Renderer * renderer);
+
+typedef int SDLCALL tSDL_RenderDrawPoint(SDL_Renderer * renderer,
+ int x, int y);
+
+typedef int SDLCALL tSDL_RenderDrawPoints(SDL_Renderer * renderer,
+ const SDL_Point * points,
+ int count);
+
+typedef int SDLCALL tSDL_RenderDrawLine(SDL_Renderer * renderer,
+ int x1, int y1, int x2, int y2);
+
+typedef int SDLCALL tSDL_RenderDrawLines(SDL_Renderer * renderer,
+ const SDL_Point * points,
+ int count);
+
+typedef int SDLCALL tSDL_RenderDrawRect(SDL_Renderer * renderer,
+ const SDL_Rect * rect);
+
+typedef int SDLCALL tSDL_RenderDrawRects(SDL_Renderer * renderer,
+ const SDL_Rect * rects,
+ int count);
+
+typedef int SDLCALL tSDL_RenderFillRect(SDL_Renderer * renderer,
+ const SDL_Rect * rect);
+
+typedef int SDLCALL tSDL_RenderFillRects(SDL_Renderer * renderer,
+ const SDL_Rect * rects,
+ int count);
+
+typedef int SDLCALL tSDL_RenderCopy(SDL_Renderer * renderer,
+ SDL_Texture * texture,
+ const SDL_Rect * srcrect,
+ const SDL_Rect * dstrect);
+
+typedef int SDLCALL tSDL_RenderCopyEx(SDL_Renderer * renderer,
+ SDL_Texture * texture,
+ const SDL_Rect * srcrect,
+ const SDL_Rect * dstrect,
+ const double angle,
+ const SDL_Point *center,
+ const SDL_RendererFlip flip);
+
+typedef int SDLCALL tSDL_RenderReadPixels(SDL_Renderer * renderer,
+ const SDL_Rect * rect,
+ Uint32 format,
+ void *pixels, int pitch);
+
+typedef void SDLCALL tSDL_RenderPresent(SDL_Renderer * renderer);
+
+typedef void SDLCALL tSDL_DestroyTexture(SDL_Texture * texture);
+
+typedef void SDLCALL tSDL_DestroyRenderer(SDL_Renderer * renderer);
+
+typedef int SDLCALL tSDL_GL_BindTexture(SDL_Texture *texture, float *texw, float *texh);
+
+typedef int SDLCALL tSDL_GL_UnbindTexture(SDL_Texture *texture);
+
+extern tSDL_GetNumRenderDrivers *SDL_GetNumRenderDrivers;
+extern tSDL_GetRenderDriverInfo *SDL_GetRenderDriverInfo;
+extern tSDL_CreateWindowAndRenderer *SDL_CreateWindowAndRenderer;
+extern tSDL_CreateRenderer *SDL_CreateRenderer;
+extern tSDL_CreateSoftwareRenderer *SDL_CreateSoftwareRenderer;
+extern tSDL_GetRenderer *SDL_GetRenderer;
+extern tSDL_GetRendererInfo *SDL_GetRendererInfo;
+extern tSDL_GetRendererOutputSize *SDL_GetRendererOutputSize;
+extern tSDL_CreateTexture *SDL_CreateTexture;
+extern tSDL_CreateTextureFromSurface *SDL_CreateTextureFromSurface;
+extern tSDL_QueryTexture *SDL_QueryTexture;
+extern tSDL_SetTextureColorMod *SDL_SetTextureColorMod;
+extern tSDL_GetTextureColorMod *SDL_GetTextureColorMod;
+extern tSDL_SetTextureAlphaMod *SDL_SetTextureAlphaMod;
+extern tSDL_GetTextureAlphaMod *SDL_GetTextureAlphaMod;
+extern tSDL_SetTextureBlendMode *SDL_SetTextureBlendMode;
+extern tSDL_GetTextureBlendMode *SDL_GetTextureBlendMode;
+extern tSDL_UpdateTexture *SDL_UpdateTexture;
+extern tSDL_LockTexture *SDL_LockTexture;
+extern tSDL_UnlockTexture *SDL_UnlockTexture;
+extern tSDL_RenderTargetSupported *SDL_RenderTargetSupported;
+extern tSDL_SetRenderTarget *SDL_SetRenderTarget;
+extern tSDL_GetRenderTarget *SDL_GetRenderTarget;
+extern tSDL_RenderSetLogicalSize *SDL_RenderSetLogicalSize;
+extern tSDL_RenderGetLogicalSize *SDL_RenderGetLogicalSize;
+extern tSDL_RenderSetViewport *SDL_RenderSetViewport;
+extern tSDL_RenderGetViewport *SDL_RenderGetViewport;
+extern tSDL_RenderSetClipRect *SDL_RenderSetClipRect;
+extern tSDL_RenderGetClipRect *SDL_RenderGetClipRect;
+extern tSDL_RenderSetScale *SDL_RenderSetScale;
+extern tSDL_RenderGetScale *SDL_RenderGetScale;
+extern tSDL_SetRenderDrawBlendMode *SDL_SetRenderDrawBlendMode;
+extern tSDL_GetRenderDrawBlendMode *SDL_GetRenderDrawBlendMode;
+extern tSDL_RenderClear *SDL_RenderClear;
+extern tSDL_RenderDrawPoint *SDL_RenderDrawPoint;
+extern tSDL_RenderDrawPoints *SDL_RenderDrawPoints;
+extern tSDL_RenderDrawLine *SDL_RenderDrawLine;
+extern tSDL_RenderDrawLines *SDL_RenderDrawLines;
+extern tSDL_RenderDrawRect *SDL_RenderDrawRect;
+extern tSDL_RenderDrawRects *SDL_RenderDrawRects;
+extern tSDL_RenderFillRect *SDL_RenderFillRect;
+extern tSDL_RenderFillRects *SDL_RenderFillRects;
+extern tSDL_RenderCopy *SDL_RenderCopy;
+extern tSDL_RenderCopyEx *SDL_RenderCopyEx;
+extern tSDL_RenderReadPixels *SDL_RenderReadPixels;
+extern tSDL_RenderPresent *SDL_RenderPresent;
+extern tSDL_DestroyTexture *SDL_DestroyTexture;
+extern tSDL_DestroyRenderer *SDL_DestroyRenderer;
+extern tSDL_GL_BindTexture *SDL_GL_BindTexture;
+extern tSDL_GL_UnbindTexture *SDL_GL_UnbindTexture;
+
+#ifdef __cplusplus
+}
+#endif
+#include "close_code.h"
+
+#endif
+
diff --git a/extern/sdlew/include/SDL2/SDL_revision.h b/extern/sdlew/include/SDL2/SDL_revision.h
new file mode 100644
index 00000000000..2d57530ee69
--- /dev/null
+++ b/extern/sdlew/include/SDL2/SDL_revision.h
@@ -0,0 +1,2 @@
+#define SDL_REVISION "hg-7633:d6a8fa507a45"
+#define SDL_REVISION_NUMBER 7633
diff --git a/extern/sdlew/include/SDL2/SDL_rwops.h b/extern/sdlew/include/SDL2/SDL_rwops.h
new file mode 100644
index 00000000000..6129ffb4825
--- /dev/null
+++ b/extern/sdlew/include/SDL2/SDL_rwops.h
@@ -0,0 +1,162 @@
+
+#ifndef _SDL_rwops_h
+#define _SDL_rwops_h
+
+#include "SDL_stdinc.h"
+#include "SDL_error.h"
+
+#include "begin_code.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define SDL_RWOPS_UNKNOWN 0
+#define SDL_RWOPS_WINFILE 1
+#define SDL_RWOPS_STDFILE 2
+#define SDL_RWOPS_JNIFILE 3
+#define SDL_RWOPS_MEMORY 4
+#define SDL_RWOPS_MEMORY_RO 5
+
+typedef struct SDL_RWops
+{
+
+ Sint64 (SDLCALL * size) (struct SDL_RWops * context);
+
+ Sint64 (SDLCALL * seek) (struct SDL_RWops * context, Sint64 offset,
+ int whence);
+
+ size_t (SDLCALL * read) (struct SDL_RWops * context, void *ptr,
+ size_t size, size_t maxnum);
+
+ size_t (SDLCALL * write) (struct SDL_RWops * context, const void *ptr,
+ size_t size, size_t num);
+
+ int (SDLCALL * close) (struct SDL_RWops * context);
+
+ Uint32 type;
+ union
+ {
+#if defined(ANDROID)
+ struct
+ {
+ void *fileNameRef;
+ void *inputStreamRef;
+ void *readableByteChannelRef;
+ void *readMethod;
+ void *assetFileDescriptorRef;
+ long position;
+ long size;
+ long offset;
+ int fd;
+ } androidio;
+#elif defined(__WIN32__)
+ struct
+ {
+ SDL_bool append;
+ void *h;
+ struct
+ {
+ void *data;
+ size_t size;
+ size_t left;
+ } buffer;
+ } windowsio;
+#endif
+
+#ifdef HAVE_STDIO_H
+ struct
+ {
+ SDL_bool autoclose;
+ FILE *fp;
+ } stdio;
+#endif
+ struct
+ {
+ Uint8 *base;
+ Uint8 *here;
+ Uint8 *stop;
+ } mem;
+ struct
+ {
+ void *data1;
+ void *data2;
+ } unknown;
+ } hidden;
+
+} SDL_RWops;
+
+typedef SDL_RWops * SDLCALL tSDL_RWFromFile(const char *file,
+ const char *mode);
+
+#ifdef HAVE_STDIO_H
+typedef SDL_RWops * SDLCALL tSDL_RWFromFP(FILE * fp,
+ SDL_bool autoclose);
+#else
+typedef SDL_RWops * SDLCALL tSDL_RWFromFP(void * fp,
+ SDL_bool autoclose);
+#endif
+
+typedef SDL_RWops * SDLCALL tSDL_RWFromMem(void *mem, int size);
+typedef SDL_RWops * SDLCALL tSDL_RWFromConstMem(const void *mem,
+ int size);
+
+typedef SDL_RWops * SDLCALL tSDL_AllocRW(void);
+typedef void SDLCALL tSDL_FreeRW(SDL_RWops * area);
+
+#define RW_SEEK_SET 0
+#define RW_SEEK_CUR 1
+#define RW_SEEK_END 2
+
+#define SDL_RWsize(ctx) (ctx)->size(ctx)
+#define SDL_RWseek(ctx, offset, whence) (ctx)->seek(ctx, offset, whence)
+#define SDL_RWtell(ctx) (ctx)->seek(ctx, 0, RW_SEEK_CUR)
+#define SDL_RWread(ctx, ptr, size, n) (ctx)->read(ctx, ptr, size, n)
+#define SDL_RWwrite(ctx, ptr, size, n) (ctx)->write(ctx, ptr, size, n)
+#define SDL_RWclose(ctx) (ctx)->close(ctx)
+
+typedef Uint8 SDLCALL tSDL_ReadU8(SDL_RWops * src);
+typedef Uint16 SDLCALL tSDL_ReadLE16(SDL_RWops * src);
+typedef Uint16 SDLCALL tSDL_ReadBE16(SDL_RWops * src);
+typedef Uint32 SDLCALL tSDL_ReadLE32(SDL_RWops * src);
+typedef Uint32 SDLCALL tSDL_ReadBE32(SDL_RWops * src);
+typedef Uint64 SDLCALL tSDL_ReadLE64(SDL_RWops * src);
+typedef Uint64 SDLCALL tSDL_ReadBE64(SDL_RWops * src);
+
+typedef size_t SDLCALL tSDL_WriteU8(SDL_RWops * dst, Uint8 value);
+typedef size_t SDLCALL tSDL_WriteLE16(SDL_RWops * dst, Uint16 value);
+typedef size_t SDLCALL tSDL_WriteBE16(SDL_RWops * dst, Uint16 value);
+typedef size_t SDLCALL tSDL_WriteLE32(SDL_RWops * dst, Uint32 value);
+typedef size_t SDLCALL tSDL_WriteBE32(SDL_RWops * dst, Uint32 value);
+typedef size_t SDLCALL tSDL_WriteLE64(SDL_RWops * dst, Uint64 value);
+typedef size_t SDLCALL tSDL_WriteBE64(SDL_RWops * dst, Uint64 value);
+
+extern tSDL_RWFromFile *SDL_RWFromFile;
+extern tSDL_RWFromFP *SDL_RWFromFP;
+extern tSDL_RWFromFP *SDL_RWFromFP;
+extern tSDL_RWFromMem *SDL_RWFromMem;
+extern tSDL_RWFromConstMem *SDL_RWFromConstMem;
+extern tSDL_AllocRW *SDL_AllocRW;
+extern tSDL_FreeRW *SDL_FreeRW;
+extern tSDL_ReadU8 *SDL_ReadU8;
+extern tSDL_ReadLE16 *SDL_ReadLE16;
+extern tSDL_ReadBE16 *SDL_ReadBE16;
+extern tSDL_ReadLE32 *SDL_ReadLE32;
+extern tSDL_ReadBE32 *SDL_ReadBE32;
+extern tSDL_ReadLE64 *SDL_ReadLE64;
+extern tSDL_ReadBE64 *SDL_ReadBE64;
+extern tSDL_WriteU8 *SDL_WriteU8;
+extern tSDL_WriteLE16 *SDL_WriteLE16;
+extern tSDL_WriteBE16 *SDL_WriteBE16;
+extern tSDL_WriteLE32 *SDL_WriteLE32;
+extern tSDL_WriteBE32 *SDL_WriteBE32;
+extern tSDL_WriteLE64 *SDL_WriteLE64;
+extern tSDL_WriteBE64 *SDL_WriteBE64;
+
+#ifdef __cplusplus
+}
+#endif
+#include "close_code.h"
+
+#endif
+
diff --git a/extern/sdlew/include/SDL2/SDL_scancode.h b/extern/sdlew/include/SDL2/SDL_scancode.h
new file mode 100644
index 00000000000..558f29c6bd9
--- /dev/null
+++ b/extern/sdlew/include/SDL2/SDL_scancode.h
@@ -0,0 +1,273 @@
+
+#ifndef _SDL_scancode_h
+#define _SDL_scancode_h
+
+#include "SDL_stdinc.h"
+
+typedef enum
+{
+ SDL_SCANCODE_UNKNOWN = 0,
+
+ SDL_SCANCODE_A = 4,
+ SDL_SCANCODE_B = 5,
+ SDL_SCANCODE_C = 6,
+ SDL_SCANCODE_D = 7,
+ SDL_SCANCODE_E = 8,
+ SDL_SCANCODE_F = 9,
+ SDL_SCANCODE_G = 10,
+ SDL_SCANCODE_H = 11,
+ SDL_SCANCODE_I = 12,
+ SDL_SCANCODE_J = 13,
+ SDL_SCANCODE_K = 14,
+ SDL_SCANCODE_L = 15,
+ SDL_SCANCODE_M = 16,
+ SDL_SCANCODE_N = 17,
+ SDL_SCANCODE_O = 18,
+ SDL_SCANCODE_P = 19,
+ SDL_SCANCODE_Q = 20,
+ SDL_SCANCODE_R = 21,
+ SDL_SCANCODE_S = 22,
+ SDL_SCANCODE_T = 23,
+ SDL_SCANCODE_U = 24,
+ SDL_SCANCODE_V = 25,
+ SDL_SCANCODE_W = 26,
+ SDL_SCANCODE_X = 27,
+ SDL_SCANCODE_Y = 28,
+ SDL_SCANCODE_Z = 29,
+
+ SDL_SCANCODE_1 = 30,
+ SDL_SCANCODE_2 = 31,
+ SDL_SCANCODE_3 = 32,
+ SDL_SCANCODE_4 = 33,
+ SDL_SCANCODE_5 = 34,
+ SDL_SCANCODE_6 = 35,
+ SDL_SCANCODE_7 = 36,
+ SDL_SCANCODE_8 = 37,
+ SDL_SCANCODE_9 = 38,
+ SDL_SCANCODE_0 = 39,
+
+ SDL_SCANCODE_RETURN = 40,
+ SDL_SCANCODE_ESCAPE = 41,
+ SDL_SCANCODE_BACKSPACE = 42,
+ SDL_SCANCODE_TAB = 43,
+ SDL_SCANCODE_SPACE = 44,
+
+ SDL_SCANCODE_MINUS = 45,
+ SDL_SCANCODE_EQUALS = 46,
+ SDL_SCANCODE_LEFTBRACKET = 47,
+ SDL_SCANCODE_RIGHTBRACKET = 48,
+ SDL_SCANCODE_BACKSLASH = 49,
+ SDL_SCANCODE_NONUSHASH = 50,
+ SDL_SCANCODE_SEMICOLON = 51,
+ SDL_SCANCODE_APOSTROPHE = 52,
+ SDL_SCANCODE_GRAVE = 53,
+ SDL_SCANCODE_COMMA = 54,
+ SDL_SCANCODE_PERIOD = 55,
+ SDL_SCANCODE_SLASH = 56,
+
+ SDL_SCANCODE_CAPSLOCK = 57,
+
+ SDL_SCANCODE_F1 = 58,
+ SDL_SCANCODE_F2 = 59,
+ SDL_SCANCODE_F3 = 60,
+ SDL_SCANCODE_F4 = 61,
+ SDL_SCANCODE_F5 = 62,
+ SDL_SCANCODE_F6 = 63,
+ SDL_SCANCODE_F7 = 64,
+ SDL_SCANCODE_F8 = 65,
+ SDL_SCANCODE_F9 = 66,
+ SDL_SCANCODE_F10 = 67,
+ SDL_SCANCODE_F11 = 68,
+ SDL_SCANCODE_F12 = 69,
+
+ SDL_SCANCODE_PRINTSCREEN = 70,
+ SDL_SCANCODE_SCROLLLOCK = 71,
+ SDL_SCANCODE_PAUSE = 72,
+ SDL_SCANCODE_INSERT = 73,
+ SDL_SCANCODE_HOME = 74,
+ SDL_SCANCODE_PAGEUP = 75,
+ SDL_SCANCODE_DELETE = 76,
+ SDL_SCANCODE_END = 77,
+ SDL_SCANCODE_PAGEDOWN = 78,
+ SDL_SCANCODE_RIGHT = 79,
+ SDL_SCANCODE_LEFT = 80,
+ SDL_SCANCODE_DOWN = 81,
+ SDL_SCANCODE_UP = 82,
+
+ SDL_SCANCODE_NUMLOCKCLEAR = 83,
+ SDL_SCANCODE_KP_DIVIDE = 84,
+ SDL_SCANCODE_KP_MULTIPLY = 85,
+ SDL_SCANCODE_KP_MINUS = 86,
+ SDL_SCANCODE_KP_PLUS = 87,
+ SDL_SCANCODE_KP_ENTER = 88,
+ SDL_SCANCODE_KP_1 = 89,
+ SDL_SCANCODE_KP_2 = 90,
+ SDL_SCANCODE_KP_3 = 91,
+ SDL_SCANCODE_KP_4 = 92,
+ SDL_SCANCODE_KP_5 = 93,
+ SDL_SCANCODE_KP_6 = 94,
+ SDL_SCANCODE_KP_7 = 95,
+ SDL_SCANCODE_KP_8 = 96,
+ SDL_SCANCODE_KP_9 = 97,
+ SDL_SCANCODE_KP_0 = 98,
+ SDL_SCANCODE_KP_PERIOD = 99,
+
+ SDL_SCANCODE_NONUSBACKSLASH = 100,
+ SDL_SCANCODE_APPLICATION = 101,
+ SDL_SCANCODE_POWER = 102,
+ SDL_SCANCODE_KP_EQUALS = 103,
+ SDL_SCANCODE_F13 = 104,
+ SDL_SCANCODE_F14 = 105,
+ SDL_SCANCODE_F15 = 106,
+ SDL_SCANCODE_F16 = 107,
+ SDL_SCANCODE_F17 = 108,
+ SDL_SCANCODE_F18 = 109,
+ SDL_SCANCODE_F19 = 110,
+ SDL_SCANCODE_F20 = 111,
+ SDL_SCANCODE_F21 = 112,
+ SDL_SCANCODE_F22 = 113,
+ SDL_SCANCODE_F23 = 114,
+ SDL_SCANCODE_F24 = 115,
+ SDL_SCANCODE_EXECUTE = 116,
+ SDL_SCANCODE_HELP = 117,
+ SDL_SCANCODE_MENU = 118,
+ SDL_SCANCODE_SELECT = 119,
+ SDL_SCANCODE_STOP = 120,
+ SDL_SCANCODE_AGAIN = 121,
+ SDL_SCANCODE_UNDO = 122,
+ SDL_SCANCODE_CUT = 123,
+ SDL_SCANCODE_COPY = 124,
+ SDL_SCANCODE_PASTE = 125,
+ SDL_SCANCODE_FIND = 126,
+ SDL_SCANCODE_MUTE = 127,
+ SDL_SCANCODE_VOLUMEUP = 128,
+ SDL_SCANCODE_VOLUMEDOWN = 129,
+
+ SDL_SCANCODE_KP_COMMA = 133,
+ SDL_SCANCODE_KP_EQUALSAS400 = 134,
+
+ SDL_SCANCODE_INTERNATIONAL1 = 135,
+ SDL_SCANCODE_INTERNATIONAL2 = 136,
+ SDL_SCANCODE_INTERNATIONAL3 = 137,
+ SDL_SCANCODE_INTERNATIONAL4 = 138,
+ SDL_SCANCODE_INTERNATIONAL5 = 139,
+ SDL_SCANCODE_INTERNATIONAL6 = 140,
+ SDL_SCANCODE_INTERNATIONAL7 = 141,
+ SDL_SCANCODE_INTERNATIONAL8 = 142,
+ SDL_SCANCODE_INTERNATIONAL9 = 143,
+ SDL_SCANCODE_LANG1 = 144,
+ SDL_SCANCODE_LANG2 = 145,
+ SDL_SCANCODE_LANG3 = 146,
+ SDL_SCANCODE_LANG4 = 147,
+ SDL_SCANCODE_LANG5 = 148,
+ SDL_SCANCODE_LANG6 = 149,
+ SDL_SCANCODE_LANG7 = 150,
+ SDL_SCANCODE_LANG8 = 151,
+ SDL_SCANCODE_LANG9 = 152,
+
+ SDL_SCANCODE_ALTERASE = 153,
+ SDL_SCANCODE_SYSREQ = 154,
+ SDL_SCANCODE_CANCEL = 155,
+ SDL_SCANCODE_CLEAR = 156,
+ SDL_SCANCODE_PRIOR = 157,
+ SDL_SCANCODE_RETURN2 = 158,
+ SDL_SCANCODE_SEPARATOR = 159,
+ SDL_SCANCODE_OUT = 160,
+ SDL_SCANCODE_OPER = 161,
+ SDL_SCANCODE_CLEARAGAIN = 162,
+ SDL_SCANCODE_CRSEL = 163,
+ SDL_SCANCODE_EXSEL = 164,
+
+ SDL_SCANCODE_KP_00 = 176,
+ SDL_SCANCODE_KP_000 = 177,
+ SDL_SCANCODE_THOUSANDSSEPARATOR = 178,
+ SDL_SCANCODE_DECIMALSEPARATOR = 179,
+ SDL_SCANCODE_CURRENCYUNIT = 180,
+ SDL_SCANCODE_CURRENCYSUBUNIT = 181,
+ SDL_SCANCODE_KP_LEFTPAREN = 182,
+ SDL_SCANCODE_KP_RIGHTPAREN = 183,
+ SDL_SCANCODE_KP_LEFTBRACE = 184,
+ SDL_SCANCODE_KP_RIGHTBRACE = 185,
+ SDL_SCANCODE_KP_TAB = 186,
+ SDL_SCANCODE_KP_BACKSPACE = 187,
+ SDL_SCANCODE_KP_A = 188,
+ SDL_SCANCODE_KP_B = 189,
+ SDL_SCANCODE_KP_C = 190,
+ SDL_SCANCODE_KP_D = 191,
+ SDL_SCANCODE_KP_E = 192,
+ SDL_SCANCODE_KP_F = 193,
+ SDL_SCANCODE_KP_XOR = 194,
+ SDL_SCANCODE_KP_POWER = 195,
+ SDL_SCANCODE_KP_PERCENT = 196,
+ SDL_SCANCODE_KP_LESS = 197,
+ SDL_SCANCODE_KP_GREATER = 198,
+ SDL_SCANCODE_KP_AMPERSAND = 199,
+ SDL_SCANCODE_KP_DBLAMPERSAND = 200,
+ SDL_SCANCODE_KP_VERTICALBAR = 201,
+ SDL_SCANCODE_KP_DBLVERTICALBAR = 202,
+ SDL_SCANCODE_KP_COLON = 203,
+ SDL_SCANCODE_KP_HASH = 204,
+ SDL_SCANCODE_KP_SPACE = 205,
+ SDL_SCANCODE_KP_AT = 206,
+ SDL_SCANCODE_KP_EXCLAM = 207,
+ SDL_SCANCODE_KP_MEMSTORE = 208,
+ SDL_SCANCODE_KP_MEMRECALL = 209,
+ SDL_SCANCODE_KP_MEMCLEAR = 210,
+ SDL_SCANCODE_KP_MEMADD = 211,
+ SDL_SCANCODE_KP_MEMSUBTRACT = 212,
+ SDL_SCANCODE_KP_MEMMULTIPLY = 213,
+ SDL_SCANCODE_KP_MEMDIVIDE = 214,
+ SDL_SCANCODE_KP_PLUSMINUS = 215,
+ SDL_SCANCODE_KP_CLEAR = 216,
+ SDL_SCANCODE_KP_CLEARENTRY = 217,
+ SDL_SCANCODE_KP_BINARY = 218,
+ SDL_SCANCODE_KP_OCTAL = 219,
+ SDL_SCANCODE_KP_DECIMAL = 220,
+ SDL_SCANCODE_KP_HEXADECIMAL = 221,
+
+ SDL_SCANCODE_LCTRL = 224,
+ SDL_SCANCODE_LSHIFT = 225,
+ SDL_SCANCODE_LALT = 226,
+ SDL_SCANCODE_LGUI = 227,
+ SDL_SCANCODE_RCTRL = 228,
+ SDL_SCANCODE_RSHIFT = 229,
+ SDL_SCANCODE_RALT = 230,
+ SDL_SCANCODE_RGUI = 231,
+
+ SDL_SCANCODE_MODE = 257,
+
+ SDL_SCANCODE_AUDIONEXT = 258,
+ SDL_SCANCODE_AUDIOPREV = 259,
+ SDL_SCANCODE_AUDIOSTOP = 260,
+ SDL_SCANCODE_AUDIOPLAY = 261,
+ SDL_SCANCODE_AUDIOMUTE = 262,
+ SDL_SCANCODE_MEDIASELECT = 263,
+ SDL_SCANCODE_WWW = 264,
+ SDL_SCANCODE_MAIL = 265,
+ SDL_SCANCODE_CALCULATOR = 266,
+ SDL_SCANCODE_COMPUTER = 267,
+ SDL_SCANCODE_AC_SEARCH = 268,
+ SDL_SCANCODE_AC_HOME = 269,
+ SDL_SCANCODE_AC_BACK = 270,
+ SDL_SCANCODE_AC_FORWARD = 271,
+ SDL_SCANCODE_AC_STOP = 272,
+ SDL_SCANCODE_AC_REFRESH = 273,
+ SDL_SCANCODE_AC_BOOKMARKS = 274,
+
+ SDL_SCANCODE_BRIGHTNESSDOWN = 275,
+ SDL_SCANCODE_BRIGHTNESSUP = 276,
+ SDL_SCANCODE_DISPLAYSWITCH = 277,
+ SDL_SCANCODE_KBDILLUMTOGGLE = 278,
+ SDL_SCANCODE_KBDILLUMDOWN = 279,
+ SDL_SCANCODE_KBDILLUMUP = 280,
+ SDL_SCANCODE_EJECT = 281,
+ SDL_SCANCODE_SLEEP = 282,
+
+ SDL_SCANCODE_APP1 = 283,
+ SDL_SCANCODE_APP2 = 284,
+
+ SDL_NUM_SCANCODES = 512
+} SDL_Scancode;
+
+#endif
+
diff --git a/extern/sdlew/include/SDL2/SDL_shape.h b/extern/sdlew/include/SDL2/SDL_shape.h
new file mode 100644
index 00000000000..781e3d8eb3d
--- /dev/null
+++ b/extern/sdlew/include/SDL2/SDL_shape.h
@@ -0,0 +1,60 @@
+
+#ifndef _SDL_shape_h
+#define _SDL_shape_h
+
+#include "SDL_stdinc.h"
+#include "SDL_pixels.h"
+#include "SDL_rect.h"
+#include "SDL_surface.h"
+#include "SDL_video.h"
+
+#include "begin_code.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define SDL_NONSHAPEABLE_WINDOW -1
+#define SDL_INVALID_SHAPE_ARGUMENT -2
+#define SDL_WINDOW_LACKS_SHAPE -3
+
+typedef SDL_Window * SDLCALL tSDL_CreateShapedWindow(const char *title,unsigned int x,unsigned int y,unsigned int w,unsigned int h,Uint32 flags);
+
+typedef SDL_bool SDLCALL tSDL_IsShapedWindow(const SDL_Window *window);
+
+typedef enum {
+
+ ShapeModeDefault,
+
+ ShapeModeBinarizeAlpha,
+
+ ShapeModeReverseBinarizeAlpha,
+
+ ShapeModeColorKey
+} WindowShapeMode;
+
+#define SDL_SHAPEMODEALPHA(mode) (mode == ShapeModeDefault || mode == ShapeModeBinarizeAlpha || mode == ShapeModeReverseBinarizeAlpha)
+
+typedef union {
+
+ Uint8 binarizationCutoff;
+ SDL_Color colorKey;
+} SDL_WindowShapeParams;
+
+typedef struct SDL_WindowShapeMode {
+
+ WindowShapeMode mode;
+
+ SDL_WindowShapeParams parameters;
+} SDL_WindowShapeMode;
+
+typedef int SDLCALL tSDL_SetWindowShape(SDL_Window *window,SDL_Surface *shape,SDL_WindowShapeMode *shape_mode);
+
+typedef int SDLCALL tSDL_GetShapedWindowMode(SDL_Window *window,SDL_WindowShapeMode *shape_mode);
+
+#ifdef __cplusplus
+}
+#endif
+#include "close_code.h"
+
+#endif
diff --git a/extern/sdlew/include/SDL2/SDL_stdinc.h b/extern/sdlew/include/SDL2/SDL_stdinc.h
new file mode 100644
index 00000000000..a67bcaccb9f
--- /dev/null
+++ b/extern/sdlew/include/SDL2/SDL_stdinc.h
@@ -0,0 +1,378 @@
+
+#ifndef _SDL_stdinc_h
+#define _SDL_stdinc_h
+
+#include "SDL_config.h"
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_STDIO_H
+#include <stdio.h>
+#endif
+#if defined(STDC_HEADERS)
+# include <stdlib.h>
+# include <stddef.h>
+# include <stdarg.h>
+#else
+# if defined(HAVE_STDLIB_H)
+# include <stdlib.h>
+# elif defined(HAVE_MALLOC_H)
+# include <malloc.h>
+# endif
+# if defined(HAVE_STDDEF_H)
+# include <stddef.h>
+# endif
+# if defined(HAVE_STDARG_H)
+# include <stdarg.h>
+# endif
+#endif
+#ifdef HAVE_STRING_H
+# if !defined(STDC_HEADERS) && defined(HAVE_MEMORY_H)
+# include <memory.h>
+# endif
+# include <string.h>
+#endif
+#ifdef HAVE_STRINGS_H
+# include <strings.h>
+#endif
+#if defined(HAVE_INTTYPES_H)
+# include <inttypes.h>
+#elif defined(HAVE_STDINT_H)
+# include <stdint.h>
+#endif
+#ifdef HAVE_CTYPE_H
+# include <ctype.h>
+#endif
+#ifdef HAVE_MATH_H
+# include <math.h>
+#endif
+#if defined(HAVE_ICONV) && defined(HAVE_ICONV_H)
+# include <iconv.h>
+#endif
+
+#define SDL_arraysize(array) (sizeof(array)/sizeof(array[0]))
+#define SDL_TABLESIZE(table) SDL_arraysize(table)
+
+#ifdef __cplusplus
+#define SDL_reinterpret_cast(type, expression) reinterpret_cast<type>(expression)
+#define SDL_static_cast(type, expression) static_cast<type>(expression)
+#define SDL_const_cast(type, expression) const_cast<type>(expression)
+#else
+#define SDL_reinterpret_cast(type, expression) ((type)(expression))
+#define SDL_static_cast(type, expression) ((type)(expression))
+#define SDL_const_cast(type, expression) ((type)(expression))
+#endif
+
+#define SDL_FOURCC(A, B, C, D) \
+ ((SDL_static_cast(Uint32, SDL_static_cast(Uint8, (A))) << 0) | \
+ (SDL_static_cast(Uint32, SDL_static_cast(Uint8, (B))) << 8) | \
+ (SDL_static_cast(Uint32, SDL_static_cast(Uint8, (C))) << 16) | \
+ (SDL_static_cast(Uint32, SDL_static_cast(Uint8, (D))) << 24))
+
+typedef enum
+{
+ SDL_FALSE = 0,
+ SDL_TRUE = 1
+} SDL_bool;
+
+typedef int8_t Sint8;
+
+typedef uint8_t Uint8;
+
+typedef int16_t Sint16;
+
+typedef uint16_t Uint16;
+
+typedef int32_t Sint32;
+
+typedef uint32_t Uint32;
+
+typedef int64_t Sint64;
+
+typedef uint64_t Uint64;
+
+#define SDL_COMPILE_TIME_ASSERT(name, x) \
+ typedef int SDL_dummy_ ## name[(x) * 2 - 1]
+
+#ifndef DOXYGEN_SHOULD_IGNORE_THIS
+SDL_COMPILE_TIME_ASSERT(uint8, sizeof(Uint8) == 1);
+SDL_COMPILE_TIME_ASSERT(sint8, sizeof(Sint8) == 1);
+SDL_COMPILE_TIME_ASSERT(uint16, sizeof(Uint16) == 2);
+SDL_COMPILE_TIME_ASSERT(sint16, sizeof(Sint16) == 2);
+SDL_COMPILE_TIME_ASSERT(uint32, sizeof(Uint32) == 4);
+SDL_COMPILE_TIME_ASSERT(sint32, sizeof(Sint32) == 4);
+SDL_COMPILE_TIME_ASSERT(uint64, sizeof(Uint64) == 8);
+SDL_COMPILE_TIME_ASSERT(sint64, sizeof(Sint64) == 8);
+#endif
+
+#ifndef DOXYGEN_SHOULD_IGNORE_THIS
+#if !defined(__ANDROID__)
+
+typedef enum
+{
+ DUMMY_ENUM_VALUE
+} SDL_DUMMY_ENUM;
+
+SDL_COMPILE_TIME_ASSERT(enum, sizeof(SDL_DUMMY_ENUM) == sizeof(int));
+#endif
+#endif
+
+#include "begin_code.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if defined(HAVE_ALLOCA) && !defined(alloca)
+# if defined(HAVE_ALLOCA_H)
+# include <alloca.h>
+# elif defined(__GNUC__)
+# define alloca __builtin_alloca
+# elif defined(_MSC_VER)
+# include <malloc.h>
+# define alloca _alloca
+# elif defined(__WATCOMC__)
+# include <malloc.h>
+# elif defined(__BORLANDC__)
+# include <malloc.h>
+# elif defined(__DMC__)
+# include <stdlib.h>
+# elif defined(__AIX__)
+#pragma alloca
+# elif defined(__MRC__)
+void *alloca(unsigned);
+# else
+char *alloca();
+# endif
+#endif
+#ifdef HAVE_ALLOCA
+#define SDL_stack_alloc(type, count) (type*)alloca(sizeof(type)*(count))
+#define SDL_stack_free(data)
+#else
+#define SDL_stack_alloc(type, count) (type*)SDL_malloc(sizeof(type)*(count))
+#define SDL_stack_free(data) SDL_free(data)
+#endif
+
+typedef void * SDLCALL tSDL_malloc(size_t size);
+typedef void * SDLCALL tSDL_calloc(size_t nmemb, size_t size);
+typedef void * SDLCALL tSDL_realloc(void *mem, size_t size);
+typedef void SDLCALL tSDL_free(void *mem);
+
+typedef char * SDLCALL tSDL_getenv(const char *name);
+typedef int SDLCALL tSDL_setenv(const char *name, const char *value, int overwrite);
+
+typedef void SDLCALL tSDL_qsort(void *base, size_t nmemb, size_t size, int (*compare) (const void *, const void *));
+
+typedef int SDLCALL tSDL_abs(int x);
+
+#define SDL_min(x, y) (((x) < (y)) ? (x) : (y))
+#define SDL_max(x, y) (((x) > (y)) ? (x) : (y))
+
+typedef int SDLCALL tSDL_isdigit(int x);
+typedef int SDLCALL tSDL_isspace(int x);
+typedef int SDLCALL tSDL_toupper(int x);
+typedef int SDLCALL tSDL_tolower(int x);
+
+typedef void * SDLCALL tSDL_memset(void *dst, int c, size_t len);
+
+#define SDL_zero(x) SDL_memset(&(x), 0, sizeof((x)))
+#define SDL_zerop(x) SDL_memset((x), 0, sizeof(*(x)))
+
+SDL_FORCE_INLINE void SDL_memset4(void *dst, int val, size_t dwords)
+{
+#if defined(__GNUC__) && defined(i386)
+ int u0, u1, u2;
+ __asm__ __volatile__ (
+ "cld \n\t"
+ "rep ; stosl \n\t"
+ : "=&D" (u0), "=&a" (u1), "=&c" (u2)
+ : "0" (dst), "1" (val), "2" (SDL_static_cast(Uint32, dwords))
+ : "memory"
+ );
+#else
+ size_t _n = (dwords + 3) / 4;
+ Uint32 *_p = SDL_static_cast(Uint32 *, dst);
+ Uint32 _val = (val);
+ if (dwords == 0)
+ return;
+ switch (dwords % 4)
+ {
+ case 0: do { *_p++ = _val;
+ case 3: *_p++ = _val;
+ case 2: *_p++ = _val;
+ case 1: *_p++ = _val;
+ } while ( --_n );
+ }
+#endif
+}
+
+typedef void * SDLCALL tSDL_memcpy(void *dst, const void *src, size_t len);
+
+extern tSDL_memcpy *SDL_memcpy;
+SDL_FORCE_INLINE void *SDL_memcpy4(void *dst, const void *src, size_t dwords)
+{
+ return SDL_memcpy(dst, src, dwords * 4);
+}
+
+typedef void * SDLCALL tSDL_memmove(void *dst, const void *src, size_t len);
+typedef int SDLCALL tSDL_memcmp(const void *s1, const void *s2, size_t len);
+
+typedef size_t SDLCALL tSDL_wcslen(const wchar_t *wstr);
+typedef size_t SDLCALL tSDL_wcslcpy(wchar_t *dst, const wchar_t *src, size_t maxlen);
+typedef size_t SDLCALL tSDL_wcslcat(wchar_t *dst, const wchar_t *src, size_t maxlen);
+
+typedef size_t SDLCALL tSDL_strlen(const char *str);
+typedef size_t SDLCALL tSDL_strlcpy(char *dst, const char *src, size_t maxlen);
+typedef size_t SDLCALL tSDL_utf8strlcpy(char *dst, const char *src, size_t dst_bytes);
+typedef size_t SDLCALL tSDL_strlcat(char *dst, const char *src, size_t maxlen);
+typedef char * SDLCALL tSDL_strdup(const char *str);
+typedef char * SDLCALL tSDL_strrev(char *str);
+typedef char * SDLCALL tSDL_strupr(char *str);
+typedef char * SDLCALL tSDL_strlwr(char *str);
+typedef char * SDLCALL tSDL_strchr(const char *str, int c);
+typedef char * SDLCALL tSDL_strrchr(const char *str, int c);
+typedef char * SDLCALL tSDL_strstr(const char *haystack, const char *needle);
+
+typedef char * SDLCALL tSDL_itoa(int value, char *str, int radix);
+typedef char * SDLCALL tSDL_uitoa(unsigned int value, char *str, int radix);
+typedef char * SDLCALL tSDL_ltoa(long value, char *str, int radix);
+typedef char * SDLCALL tSDL_ultoa(unsigned long value, char *str, int radix);
+typedef char * SDLCALL tSDL_lltoa(Sint64 value, char *str, int radix);
+typedef char * SDLCALL tSDL_ulltoa(Uint64 value, char *str, int radix);
+
+typedef int SDLCALL tSDL_atoi(const char *str);
+typedef double SDLCALL tSDL_atof(const char *str);
+typedef long SDLCALL tSDL_strtol(const char *str, char **endp, int base);
+extern DECLSPEC unsigned long SDLCALL SDL_strtoul(const char *str, char **endp, int base);
+typedef Sint64 SDLCALL tSDL_strtoll(const char *str, char **endp, int base);
+typedef Uint64 SDLCALL tSDL_strtoull(const char *str, char **endp, int base);
+typedef double SDLCALL tSDL_strtod(const char *str, char **endp);
+
+typedef int SDLCALL tSDL_strcmp(const char *str1, const char *str2);
+typedef int SDLCALL tSDL_strncmp(const char *str1, const char *str2, size_t maxlen);
+typedef int SDLCALL tSDL_strcasecmp(const char *str1, const char *str2);
+typedef int SDLCALL tSDL_strncasecmp(const char *str1, const char *str2, size_t len);
+
+typedef int SDLCALL tSDL_sscanf(const char *text, const char *fmt, ...);
+typedef int SDLCALL tSDL_snprintf(char *text, size_t maxlen, const char *fmt, ...);
+typedef int SDLCALL tSDL_vsnprintf(char *text, size_t maxlen, const char *fmt, va_list ap);
+
+#ifndef HAVE_M_PI
+#ifndef M_PI
+#define M_PI 3.14159265358979323846264338327950288
+#endif
+#endif
+
+typedef double SDLCALL tSDL_atan(double x);
+typedef double SDLCALL tSDL_atan2(double x, double y);
+typedef double SDLCALL tSDL_ceil(double x);
+typedef double SDLCALL tSDL_copysign(double x, double y);
+typedef double SDLCALL tSDL_cos(double x);
+typedef float SDLCALL tSDL_cosf(float x);
+typedef double SDLCALL tSDL_fabs(double x);
+typedef double SDLCALL tSDL_floor(double x);
+typedef double SDLCALL tSDL_log(double x);
+typedef double SDLCALL tSDL_pow(double x, double y);
+typedef double SDLCALL tSDL_scalbn(double x, int n);
+typedef double SDLCALL tSDL_sin(double x);
+typedef float SDLCALL tSDL_sinf(float x);
+typedef double SDLCALL tSDL_sqrt(double x);
+
+#define SDL_ICONV_ERROR (size_t)-1
+#define SDL_ICONV_E2BIG (size_t)-2
+#define SDL_ICONV_EILSEQ (size_t)-3
+#define SDL_ICONV_EINVAL (size_t)-4
+
+typedef struct _SDL_iconv_t *SDL_iconv_t;
+typedef SDL_iconv_t SDLCALL tSDL_iconv_open(const char *tocode,
+ const char *fromcode);
+typedef int SDLCALL tSDL_iconv_close(SDL_iconv_t cd);
+typedef size_t SDLCALL tSDL_iconv(SDL_iconv_t cd, const char **inbuf,
+ size_t * inbytesleft, char **outbuf,
+ size_t * outbytesleft);
+
+typedef char * SDLCALL tSDL_iconv_string(const char *tocode,
+ const char *fromcode,
+ const char *inbuf,
+ size_t inbytesleft);
+#define SDL_iconv_utf8_locale(S) SDL_iconv_string("", "UTF-8", S, SDL_strlen(S)+1)
+#define SDL_iconv_utf8_ucs2(S) (Uint16 *)SDL_iconv_string("UCS-2-INTERNAL", "UTF-8", S, SDL_strlen(S)+1)
+#define SDL_iconv_utf8_ucs4(S) (Uint32 *)SDL_iconv_string("UCS-4-INTERNAL", "UTF-8", S, SDL_strlen(S)+1)
+
+#ifndef HAVE_ALLOCA
+extern tSDL_malloc *SDL_malloc;
+#endif
+extern tSDL_calloc *SDL_calloc;
+extern tSDL_realloc *SDL_realloc;
+extern tSDL_free *SDL_free;
+extern tSDL_getenv *SDL_getenv;
+extern tSDL_setenv *SDL_setenv;
+extern tSDL_qsort *SDL_qsort;
+extern tSDL_abs *SDL_abs;
+extern tSDL_isdigit *SDL_isdigit;
+extern tSDL_isspace *SDL_isspace;
+extern tSDL_toupper *SDL_toupper;
+extern tSDL_tolower *SDL_tolower;
+extern tSDL_memset *SDL_memset;
+extern tSDL_memmove *SDL_memmove;
+extern tSDL_memcmp *SDL_memcmp;
+extern tSDL_wcslen *SDL_wcslen;
+extern tSDL_wcslcpy *SDL_wcslcpy;
+extern tSDL_wcslcat *SDL_wcslcat;
+extern tSDL_strlen *SDL_strlen;
+extern tSDL_strlcpy *SDL_strlcpy;
+extern tSDL_utf8strlcpy *SDL_utf8strlcpy;
+extern tSDL_strlcat *SDL_strlcat;
+extern tSDL_strdup *SDL_strdup;
+extern tSDL_strrev *SDL_strrev;
+extern tSDL_strupr *SDL_strupr;
+extern tSDL_strlwr *SDL_strlwr;
+extern tSDL_strchr *SDL_strchr;
+extern tSDL_strrchr *SDL_strrchr;
+extern tSDL_strstr *SDL_strstr;
+extern tSDL_itoa *SDL_itoa;
+extern tSDL_uitoa *SDL_uitoa;
+extern tSDL_ltoa *SDL_ltoa;
+extern tSDL_ultoa *SDL_ultoa;
+extern tSDL_lltoa *SDL_lltoa;
+extern tSDL_ulltoa *SDL_ulltoa;
+extern tSDL_atoi *SDL_atoi;
+extern tSDL_atof *SDL_atof;
+extern tSDL_strtol *SDL_strtol;
+extern tSDL_strtoll *SDL_strtoll;
+extern tSDL_strtoull *SDL_strtoull;
+extern tSDL_strtod *SDL_strtod;
+extern tSDL_strcmp *SDL_strcmp;
+extern tSDL_strncmp *SDL_strncmp;
+extern tSDL_strcasecmp *SDL_strcasecmp;
+extern tSDL_strncasecmp *SDL_strncasecmp;
+extern tSDL_sscanf *SDL_sscanf;
+extern tSDL_snprintf *SDL_snprintf;
+extern tSDL_vsnprintf *SDL_vsnprintf;
+extern tSDL_atan *SDL_atan;
+extern tSDL_atan2 *SDL_atan2;
+extern tSDL_ceil *SDL_ceil;
+extern tSDL_copysign *SDL_copysign;
+extern tSDL_cos *SDL_cos;
+extern tSDL_cosf *SDL_cosf;
+extern tSDL_fabs *SDL_fabs;
+extern tSDL_floor *SDL_floor;
+extern tSDL_log *SDL_log;
+extern tSDL_pow *SDL_pow;
+extern tSDL_scalbn *SDL_scalbn;
+extern tSDL_sin *SDL_sin;
+extern tSDL_sinf *SDL_sinf;
+extern tSDL_sqrt *SDL_sqrt;
+extern tSDL_iconv_open *SDL_iconv_open;
+extern tSDL_iconv_close *SDL_iconv_close;
+extern tSDL_iconv *SDL_iconv;
+extern tSDL_iconv_string *SDL_iconv_string;
+
+#ifdef __cplusplus
+}
+#endif
+#include "close_code.h"
+
+#endif
+
diff --git a/extern/sdlew/include/SDL2/SDL_surface.h b/extern/sdlew/include/SDL2/SDL_surface.h
new file mode 100644
index 00000000000..5125eee4402
--- /dev/null
+++ b/extern/sdlew/include/SDL2/SDL_surface.h
@@ -0,0 +1,190 @@
+
+#ifndef _SDL_surface_h
+#define _SDL_surface_h
+
+#include "SDL_stdinc.h"
+#include "SDL_pixels.h"
+#include "SDL_rect.h"
+#include "SDL_blendmode.h"
+#include "SDL_rwops.h"
+
+#include "begin_code.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define SDL_SWSURFACE 0
+#define SDL_PREALLOC 0x00000001
+#define SDL_RLEACCEL 0x00000002
+#define SDL_DONTFREE 0x00000004
+
+#define SDL_MUSTLOCK(S) (((S)->flags & SDL_RLEACCEL) != 0)
+
+typedef struct SDL_Surface
+{
+ Uint32 flags;
+ SDL_PixelFormat *format;
+ int w, h;
+ int pitch;
+ void *pixels;
+
+ void *userdata;
+
+ int locked;
+ void *lock_data;
+
+ SDL_Rect clip_rect;
+
+ struct SDL_BlitMap *map;
+
+ int refcount;
+} SDL_Surface;
+
+typedef int (*SDL_blit) (struct SDL_Surface * src, SDL_Rect * srcrect,
+ struct SDL_Surface * dst, SDL_Rect * dstrect);
+
+typedef SDL_Surface * SDLCALL tSDL_CreateRGBSurface
+ (Uint32 flags, int width, int height, int depth,
+ Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask);
+typedef SDL_Surface * SDLCALL tSDL_CreateRGBSurfaceFrom(void *pixels,
+ int width,
+ int height,
+ int depth,
+ int pitch,
+ Uint32 Rmask,
+ Uint32 Gmask,
+ Uint32 Bmask,
+ Uint32 Amask);
+typedef void SDLCALL tSDL_FreeSurface(SDL_Surface * surface);
+
+typedef int SDLCALL tSDL_SetSurfacePalette(SDL_Surface * surface,
+ SDL_Palette * palette);
+
+typedef int SDLCALL tSDL_LockSurface(SDL_Surface * surface);
+
+typedef void SDLCALL tSDL_UnlockSurface(SDL_Surface * surface);
+
+typedef SDL_Surface * SDLCALL tSDL_LoadBMP_RW(SDL_RWops * src,
+ int freesrc);
+
+#define SDL_LoadBMP(file) SDL_LoadBMP_RW(SDL_RWFromFile(file, "rb"), 1)
+
+typedef int SDLCALL tSDL_SaveBMP_RW
+ (SDL_Surface * surface, SDL_RWops * dst, int freedst);
+
+#define SDL_SaveBMP(surface, file) \
+ SDL_SaveBMP_RW(surface, SDL_RWFromFile(file, "wb"), 1)
+
+typedef int SDLCALL tSDL_SetSurfaceRLE(SDL_Surface * surface,
+ int flag);
+
+typedef int SDLCALL tSDL_SetColorKey(SDL_Surface * surface,
+ int flag, Uint32 key);
+
+typedef int SDLCALL tSDL_GetColorKey(SDL_Surface * surface,
+ Uint32 * key);
+
+typedef int SDLCALL tSDL_SetSurfaceColorMod(SDL_Surface * surface,
+ Uint8 r, Uint8 g, Uint8 b);
+
+typedef int SDLCALL tSDL_GetSurfaceColorMod(SDL_Surface * surface,
+ Uint8 * r, Uint8 * g,
+ Uint8 * b);
+
+typedef int SDLCALL tSDL_SetSurfaceAlphaMod(SDL_Surface * surface,
+ Uint8 alpha);
+
+typedef int SDLCALL tSDL_GetSurfaceAlphaMod(SDL_Surface * surface,
+ Uint8 * alpha);
+
+typedef int SDLCALL tSDL_SetSurfaceBlendMode(SDL_Surface * surface,
+ SDL_BlendMode blendMode);
+
+typedef int SDLCALL tSDL_GetSurfaceBlendMode(SDL_Surface * surface,
+ SDL_BlendMode *blendMode);
+
+typedef SDL_bool SDLCALL tSDL_SetClipRect(SDL_Surface * surface,
+ const SDL_Rect * rect);
+
+typedef void SDLCALL tSDL_GetClipRect(SDL_Surface * surface,
+ SDL_Rect * rect);
+
+typedef SDL_Surface * SDLCALL tSDL_ConvertSurface
+ (SDL_Surface * src, SDL_PixelFormat * fmt, Uint32 flags);
+typedef SDL_Surface * SDLCALL tSDL_ConvertSurfaceFormat
+ (SDL_Surface * src, Uint32 pixel_format, Uint32 flags);
+
+typedef int SDLCALL tSDL_ConvertPixels(int width, int height,
+ Uint32 src_format,
+ const void * src, int src_pitch,
+ Uint32 dst_format,
+ void * dst, int dst_pitch);
+
+typedef int SDLCALL tSDL_FillRect
+ (SDL_Surface * dst, const SDL_Rect * rect, Uint32 color);
+typedef int SDLCALL tSDL_FillRects
+ (SDL_Surface * dst, const SDL_Rect * rects, int count, Uint32 color);
+
+#define SDL_BlitSurface SDL_UpperBlit
+
+typedef int SDLCALL tSDL_UpperBlit
+ (SDL_Surface * src, const SDL_Rect * srcrect,
+ SDL_Surface * dst, SDL_Rect * dstrect);
+
+typedef int SDLCALL tSDL_LowerBlit
+ (SDL_Surface * src, SDL_Rect * srcrect,
+ SDL_Surface * dst, SDL_Rect * dstrect);
+
+typedef int SDLCALL tSDL_SoftStretch(SDL_Surface * src,
+ const SDL_Rect * srcrect,
+ SDL_Surface * dst,
+ const SDL_Rect * dstrect);
+
+#define SDL_BlitScaled SDL_UpperBlitScaled
+
+typedef int SDLCALL tSDL_UpperBlitScaled
+ (SDL_Surface * src, const SDL_Rect * srcrect,
+ SDL_Surface * dst, SDL_Rect * dstrect);
+
+typedef int SDLCALL tSDL_LowerBlitScaled
+ (SDL_Surface * src, SDL_Rect * srcrect,
+ SDL_Surface * dst, SDL_Rect * dstrect);
+
+extern tSDL_CreateRGBSurface *SDL_CreateRGBSurface;
+extern tSDL_CreateRGBSurfaceFrom *SDL_CreateRGBSurfaceFrom;
+extern tSDL_FreeSurface *SDL_FreeSurface;
+extern tSDL_SetSurfacePalette *SDL_SetSurfacePalette;
+extern tSDL_LockSurface *SDL_LockSurface;
+extern tSDL_UnlockSurface *SDL_UnlockSurface;
+extern tSDL_LoadBMP_RW *SDL_LoadBMP_RW;
+extern tSDL_SaveBMP_RW *SDL_SaveBMP_RW;
+extern tSDL_SetSurfaceRLE *SDL_SetSurfaceRLE;
+extern tSDL_SetColorKey *SDL_SetColorKey;
+extern tSDL_GetColorKey *SDL_GetColorKey;
+extern tSDL_SetSurfaceColorMod *SDL_SetSurfaceColorMod;
+extern tSDL_GetSurfaceColorMod *SDL_GetSurfaceColorMod;
+extern tSDL_SetSurfaceAlphaMod *SDL_SetSurfaceAlphaMod;
+extern tSDL_GetSurfaceAlphaMod *SDL_GetSurfaceAlphaMod;
+extern tSDL_SetSurfaceBlendMode *SDL_SetSurfaceBlendMode;
+extern tSDL_GetSurfaceBlendMode *SDL_GetSurfaceBlendMode;
+extern tSDL_SetClipRect *SDL_SetClipRect;
+extern tSDL_GetClipRect *SDL_GetClipRect;
+extern tSDL_ConvertSurface *SDL_ConvertSurface;
+extern tSDL_ConvertSurfaceFormat *SDL_ConvertSurfaceFormat;
+extern tSDL_ConvertPixels *SDL_ConvertPixels;
+extern tSDL_FillRect *SDL_FillRect;
+extern tSDL_FillRects *SDL_FillRects;
+extern tSDL_UpperBlit *SDL_UpperBlit;
+extern tSDL_LowerBlit *SDL_LowerBlit;
+extern tSDL_SoftStretch *SDL_SoftStretch;
+extern tSDL_UpperBlitScaled *SDL_UpperBlitScaled;
+extern tSDL_LowerBlitScaled *SDL_LowerBlitScaled;
+
+#ifdef __cplusplus
+}
+#endif
+#include "close_code.h"
+
+#endif
+
diff --git a/extern/sdlew/include/SDL2/SDL_system.h b/extern/sdlew/include/SDL2/SDL_system.h
new file mode 100644
index 00000000000..57fbb4d08e2
--- /dev/null
+++ b/extern/sdlew/include/SDL2/SDL_system.h
@@ -0,0 +1,48 @@
+
+#ifndef _SDL_system_h
+#define _SDL_system_h
+
+#include "SDL_stdinc.h"
+
+#if defined(__IPHONEOS__) && __IPHONEOS__
+#include "SDL_video.h"
+#include "SDL_keyboard.h"
+#endif
+
+#include "begin_code.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if defined(__IPHONEOS__) && __IPHONEOS__
+
+typedef int SDLCALL tSDL_iPhoneSetAnimationCallback(SDL_Window * window, int interval, void (*callback)(void*), void *callbackParam);
+typedef void SDLCALL tSDL_iPhoneSetEventPump(SDL_bool enabled);
+
+#endif
+
+#if defined(__ANDROID__) && __ANDROID__
+
+typedef void * SDLCALL tSDL_AndroidGetJNIEnv();
+
+typedef void * SDLCALL tSDL_AndroidGetActivity();
+
+#define SDL_ANDROID_EXTERNAL_STORAGE_READ 0x01
+#define SDL_ANDROID_EXTERNAL_STORAGE_WRITE 0x02
+
+typedef const char * SDLCALL tSDL_AndroidGetInternalStoragePath();
+
+typedef int SDLCALL tSDL_AndroidGetExternalStorageState();
+
+typedef const char * SDLCALL tSDL_AndroidGetExternalStoragePath();
+
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+#include "close_code.h"
+
+#endif
+
diff --git a/extern/sdlew/include/SDL2/SDL_syswm.h b/extern/sdlew/include/SDL2/SDL_syswm.h
new file mode 100644
index 00000000000..7c4bc3188bc
--- /dev/null
+++ b/extern/sdlew/include/SDL2/SDL_syswm.h
@@ -0,0 +1,171 @@
+
+#ifndef _SDL_syswm_h
+#define _SDL_syswm_h
+
+#include "SDL_stdinc.h"
+#include "SDL_error.h"
+#include "SDL_video.h"
+#include "SDL_version.h"
+
+#include "begin_code.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef SDL_PROTOTYPES_ONLY
+struct SDL_SysWMinfo;
+#else
+
+#if defined(SDL_VIDEO_DRIVER_WINDOWS)
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#endif
+
+#if defined(SDL_VIDEO_DRIVER_X11)
+#if defined(__APPLE__) && defined(__MACH__)
+
+#define Cursor X11Cursor
+#endif
+
+#include <X11/Xlib.h>
+#include <X11/Xatom.h>
+
+#if defined(__APPLE__) && defined(__MACH__)
+
+#undef Cursor
+#endif
+
+#endif
+
+#if defined(SDL_VIDEO_DRIVER_DIRECTFB)
+#include <directfb.h>
+#endif
+
+#if defined(SDL_VIDEO_DRIVER_COCOA)
+#ifdef __OBJC__
+#include <Cocoa/Cocoa.h>
+#else
+typedef struct _NSWindow NSWindow;
+#endif
+#endif
+
+#if defined(SDL_VIDEO_DRIVER_UIKIT)
+#ifdef __OBJC__
+#include <UIKit/UIKit.h>
+#else
+typedef struct _UIWindow UIWindow;
+#endif
+#endif
+
+typedef enum
+{
+ SDL_SYSWM_UNKNOWN,
+ SDL_SYSWM_WINDOWS,
+ SDL_SYSWM_X11,
+ SDL_SYSWM_DIRECTFB,
+ SDL_SYSWM_COCOA,
+ SDL_SYSWM_UIKIT,
+} SDL_SYSWM_TYPE;
+
+struct SDL_SysWMmsg
+{
+ SDL_version version;
+ SDL_SYSWM_TYPE subsystem;
+ union
+ {
+#if defined(SDL_VIDEO_DRIVER_WINDOWS)
+ struct {
+ HWND hwnd;
+ UINT msg;
+ WPARAM wParam;
+ LPARAM lParam;
+ } win;
+#endif
+#if defined(SDL_VIDEO_DRIVER_X11)
+ struct {
+ XEvent event;
+ } x11;
+#endif
+#if defined(SDL_VIDEO_DRIVER_DIRECTFB)
+ struct {
+ DFBEvent event;
+ } dfb;
+#endif
+#if defined(SDL_VIDEO_DRIVER_COCOA)
+ struct
+ {
+
+ } cocoa;
+#endif
+#if defined(SDL_VIDEO_DRIVER_UIKIT)
+ struct
+ {
+
+ } uikit;
+#endif
+
+ int dummy;
+ } msg;
+};
+
+struct SDL_SysWMinfo
+{
+ SDL_version version;
+ SDL_SYSWM_TYPE subsystem;
+ union
+ {
+#if defined(SDL_VIDEO_DRIVER_WINDOWS)
+ struct
+ {
+ HWND window;
+ } win;
+#endif
+#if defined(SDL_VIDEO_DRIVER_X11)
+ struct
+ {
+ Display *display;
+ Window window;
+ } x11;
+#endif
+#if defined(SDL_VIDEO_DRIVER_DIRECTFB)
+ struct
+ {
+ IDirectFB *dfb;
+ IDirectFBWindow *window;
+ IDirectFBSurface *surface;
+ } dfb;
+#endif
+#if defined(SDL_VIDEO_DRIVER_COCOA)
+ struct
+ {
+ NSWindow *window;
+ } cocoa;
+#endif
+#if defined(SDL_VIDEO_DRIVER_UIKIT)
+ struct
+ {
+ UIWindow *window;
+ } uikit;
+#endif
+
+ int dummy;
+ } info;
+};
+
+#endif
+
+typedef struct SDL_SysWMinfo SDL_SysWMinfo;
+
+typedef SDL_bool SDLCALL tSDL_GetWindowWMInfo(SDL_Window * window,
+ SDL_SysWMinfo * info);
+
+extern tSDL_GetWindowWMInfo *SDL_GetWindowWMInfo;
+
+#ifdef __cplusplus
+}
+#endif
+#include "close_code.h"
+
+#endif
+
diff --git a/extern/sdlew/include/SDL2/SDL_test.h b/extern/sdlew/include/SDL2/SDL_test.h
new file mode 100644
index 00000000000..b2032dae5e4
--- /dev/null
+++ b/extern/sdlew/include/SDL2/SDL_test.h
@@ -0,0 +1,32 @@
+
+#ifndef _SDL_test_h
+#define _SDL_test_h
+
+#include "SDL.h"
+#include "SDL_test_common.h"
+#include "SDL_test_font.h"
+#include "SDL_test_random.h"
+#include "SDL_test_fuzzer.h"
+#include "SDL_test_crc32.h"
+#include "SDL_test_md5.h"
+#include "SDL_test_log.h"
+#include "SDL_test_assert.h"
+#include "SDL_test_harness.h"
+#include "SDL_test_images.h"
+#include "SDL_test_compare.h"
+
+#include "begin_code.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define SDLTEST_MAX_LOGMESSAGE_LENGTH 3584
+
+#ifdef __cplusplus
+}
+#endif
+#include "close_code.h"
+
+#endif
+
diff --git a/extern/sdlew/include/SDL2/SDL_test_assert.h b/extern/sdlew/include/SDL2/SDL_test_assert.h
new file mode 100644
index 00000000000..2c91c422ed1
--- /dev/null
+++ b/extern/sdlew/include/SDL2/SDL_test_assert.h
@@ -0,0 +1,33 @@
+
+#ifndef _SDL_test_assert_h
+#define _SDL_test_assert_h
+
+#include "begin_code.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define ASSERT_FAIL 0
+
+#define ASSERT_PASS 1
+
+void SDLTest_Assert(int assertCondition, const char *assertDescription, ...);
+
+int SDLTest_AssertCheck(int assertCondition, const char *assertDescription, ...);
+
+void SDLTest_AssertPass(const char *assertDescription, ...);
+
+void SDLTest_ResetAssertSummary();
+
+void SDLTest_LogAssertSummary();
+
+int SDLTest_AssertSummaryToTestResult();
+
+#ifdef __cplusplus
+}
+#endif
+#include "close_code.h"
+
+#endif
+
diff --git a/extern/sdlew/include/SDL2/SDL_test_common.h b/extern/sdlew/include/SDL2/SDL_test_common.h
new file mode 100644
index 00000000000..53b455eec90
--- /dev/null
+++ b/extern/sdlew/include/SDL2/SDL_test_common.h
@@ -0,0 +1,103 @@
+
+#ifndef _SDL_test_common_h
+#define _SDL_test_common_h
+
+#include "SDL.h"
+
+#if defined(__PSP__)
+#define DEFAULT_WINDOW_WIDTH 480
+#define DEFAULT_WINDOW_HEIGHT 272
+#else
+#define DEFAULT_WINDOW_WIDTH 640
+#define DEFAULT_WINDOW_HEIGHT 480
+#endif
+
+#define VERBOSE_VIDEO 0x00000001
+#define VERBOSE_MODES 0x00000002
+#define VERBOSE_RENDER 0x00000004
+#define VERBOSE_EVENT 0x00000008
+#define VERBOSE_AUDIO 0x00000010
+
+typedef struct
+{
+
+ char **argv;
+ Uint32 flags;
+ Uint32 verbose;
+
+ const char *videodriver;
+ int display;
+ const char *window_title;
+ const char *window_icon;
+ Uint32 window_flags;
+ int window_x;
+ int window_y;
+ int window_w;
+ int window_h;
+ int window_minW;
+ int window_minH;
+ int window_maxW;
+ int window_maxH;
+ int logical_w;
+ int logical_h;
+ float scale;
+ int depth;
+ int refresh_rate;
+ int num_windows;
+ SDL_Window **windows;
+
+ const char *renderdriver;
+ Uint32 render_flags;
+ SDL_bool skip_renderer;
+ SDL_Renderer **renderers;
+
+ const char *audiodriver;
+ SDL_AudioSpec audiospec;
+
+ int gl_red_size;
+ int gl_green_size;
+ int gl_blue_size;
+ int gl_alpha_size;
+ int gl_buffer_size;
+ int gl_depth_size;
+ int gl_stencil_size;
+ int gl_double_buffer;
+ int gl_accum_red_size;
+ int gl_accum_green_size;
+ int gl_accum_blue_size;
+ int gl_accum_alpha_size;
+ int gl_stereo;
+ int gl_multisamplebuffers;
+ int gl_multisamplesamples;
+ int gl_retained_backing;
+ int gl_accelerated;
+ int gl_major_version;
+ int gl_minor_version;
+ int gl_debug;
+} SDLTest_CommonState;
+
+#include "begin_code.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+SDLTest_CommonState *SDLTest_CommonCreateState(char **argv, Uint32 flags);
+
+int SDLTest_CommonArg(SDLTest_CommonState * state, int index);
+
+const char *SDLTest_CommonUsage(SDLTest_CommonState * state);
+
+SDL_bool SDLTest_CommonInit(SDLTest_CommonState * state);
+
+void SDLTest_CommonEvent(SDLTest_CommonState * state, SDL_Event * event, int *done);
+
+void SDLTest_CommonQuit(SDLTest_CommonState * state);
+
+#ifdef __cplusplus
+}
+#endif
+#include "close_code.h"
+
+#endif
+
diff --git a/extern/sdlew/include/SDL2/SDL_test_compare.h b/extern/sdlew/include/SDL2/SDL_test_compare.h
new file mode 100644
index 00000000000..fc3536f5a10
--- /dev/null
+++ b/extern/sdlew/include/SDL2/SDL_test_compare.h
@@ -0,0 +1,23 @@
+
+#ifndef _SDL_test_compare_h
+#define _SDL_test_compare_h
+
+#include "SDL.h"
+
+#include "SDL_test_images.h"
+
+#include "begin_code.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int SDLTest_CompareSurfaces(SDL_Surface *surface, SDL_Surface *referenceSurface, int allowable_error);
+
+#ifdef __cplusplus
+}
+#endif
+#include "close_code.h"
+
+#endif
+
diff --git a/extern/sdlew/include/SDL2/SDL_test_crc32.h b/extern/sdlew/include/SDL2/SDL_test_crc32.h
new file mode 100644
index 00000000000..31d76b51616
--- /dev/null
+++ b/extern/sdlew/include/SDL2/SDL_test_crc32.h
@@ -0,0 +1,44 @@
+
+#ifndef _SDL_test_crc32_h
+#define _SDL_test_crc32_h
+
+#include "begin_code.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef CrcUint32
+ #define CrcUint32 unsigned int
+#endif
+#ifndef CrcUint8
+ #define CrcUint8 unsigned char
+#endif
+
+#ifdef ORIGINAL_METHOD
+ #define CRC32_POLY 0x04c11db7
+#else
+ #define CRC32_POLY 0xEDB88320
+#endif
+
+ typedef struct {
+ CrcUint32 crc32_table[256];
+ } SDLTest_Crc32Context;
+
+ int SDLTest_Crc32Init(SDLTest_Crc32Context * crcContext);
+
+int SDLTest_crc32Calc(SDLTest_Crc32Context * crcContext, CrcUint8 *inBuf, CrcUint32 inLen, CrcUint32 *crc32);
+
+int SDLTest_Crc32CalcStart(SDLTest_Crc32Context * crcContext, CrcUint32 *crc32);
+int SDLTest_Crc32CalcEnd(SDLTest_Crc32Context * crcContext, CrcUint32 *crc32);
+int SDLTest_Crc32CalcBuffer(SDLTest_Crc32Context * crcContext, CrcUint8 *inBuf, CrcUint32 inLen, CrcUint32 *crc32);
+
+int SDLTest_Crc32Done(SDLTest_Crc32Context * crcContext);
+
+#ifdef __cplusplus
+}
+#endif
+#include "close_code.h"
+
+#endif
+
diff --git a/extern/sdlew/include/SDL2/SDL_test_font.h b/extern/sdlew/include/SDL2/SDL_test_font.h
new file mode 100644
index 00000000000..b016486b649
--- /dev/null
+++ b/extern/sdlew/include/SDL2/SDL_test_font.h
@@ -0,0 +1,19 @@
+
+#ifndef _SDL_test_font_h
+#define _SDL_test_font_h
+
+#include "begin_code.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int SDLTest_DrawString(SDL_Renderer * renderer, int x, int y, const char *s);
+
+#ifdef __cplusplus
+}
+#endif
+#include "close_code.h"
+
+#endif
+
diff --git a/extern/sdlew/include/SDL2/SDL_test_fuzzer.h b/extern/sdlew/include/SDL2/SDL_test_fuzzer.h
new file mode 100644
index 00000000000..6935affc963
--- /dev/null
+++ b/extern/sdlew/include/SDL2/SDL_test_fuzzer.h
@@ -0,0 +1,69 @@
+
+#ifndef _SDL_test_fuzzer_h
+#define _SDL_test_fuzzer_h
+
+#include "begin_code.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void SDLTest_FuzzerInit(Uint64 execKey);
+
+Uint8 SDLTest_RandomUint8();
+
+Sint8 SDLTest_RandomSint8();
+
+Uint16 SDLTest_RandomUint16();
+
+Sint16 SDLTest_RandomSint16();
+
+Sint32 SDLTest_RandomSint32();
+
+Uint32 SDLTest_RandomUint32();
+
+Uint64 SDLTest_RandomUint64();
+
+Sint64 SDLTest_RandomSint64();
+
+float SDLTest_RandomUnitFloat();
+
+double SDLTest_RandomUnitDouble();
+
+float SDLTest_RandomFloat();
+
+double SDLTest_RandomDouble();
+
+Uint8 SDLTest_RandomUint8BoundaryValue(Uint8 boundary1, Uint8 boundary2, SDL_bool validDomain);
+
+Uint16 SDLTest_RandomUint16BoundaryValue(Uint16 boundary1, Uint16 boundary2, SDL_bool validDomain);
+
+Uint32 SDLTest_RandomUint32BoundaryValue(Uint32 boundary1, Uint32 boundary2, SDL_bool validDomain);
+
+Uint64 SDLTest_RandomUint64BoundaryValue(Uint64 boundary1, Uint64 boundary2, SDL_bool validDomain);
+
+Sint8 SDLTest_RandomSint8BoundaryValue(Sint8 boundary1, Sint8 boundary2, SDL_bool validDomain);
+
+Sint16 SDLTest_RandomSint16BoundaryValue(Sint16 boundary1, Sint16 boundary2, SDL_bool validDomain);
+
+Sint32 SDLTest_RandomSint32BoundaryValue(Sint32 boundary1, Sint32 boundary2, SDL_bool validDomain);
+
+Sint64 SDLTest_RandomSint64BoundaryValue(Sint64 boundary1, Sint64 boundary2, SDL_bool validDomain);
+
+Sint32 SDLTest_RandomIntegerInRange(Sint32 min, Sint32 max);
+
+char * SDLTest_RandomAsciiString();
+
+char * SDLTest_RandomAsciiStringWithMaximumLength(int maxLength);
+
+char * SDLTest_RandomAsciiStringOfSize(int size);
+
+int SDLTest_GetFuzzerInvocationCount();
+
+#ifdef __cplusplus
+}
+#endif
+#include "close_code.h"
+
+#endif
+
diff --git a/extern/sdlew/include/SDL2/SDL_test_harness.h b/extern/sdlew/include/SDL2/SDL_test_harness.h
new file mode 100644
index 00000000000..4ec6dc45a81
--- /dev/null
+++ b/extern/sdlew/include/SDL2/SDL_test_harness.h
@@ -0,0 +1,67 @@
+
+#ifndef _SDL_test_harness_h
+#define _SDL_test_harness_h
+
+#include "begin_code.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+//! Definitions for test case structures
+#define TEST_ENABLED 1
+#define TEST_DISABLED 0
+
+//! Definition of all the possible test return values of the test case method
+#define TEST_ABORTED -1
+#define TEST_STARTED 0
+#define TEST_COMPLETED 1
+#define TEST_SKIPPED 2
+
+//! Definition of all the possible test results for the harness
+#define TEST_RESULT_PASSED 0
+#define TEST_RESULT_FAILED 1
+#define TEST_RESULT_NO_ASSERT 2
+#define TEST_RESULT_SKIPPED 3
+#define TEST_RESULT_SETUP_FAILURE 4
+
+//!< Function pointer to a test case setup function (run before every test)
+typedef void (*SDLTest_TestCaseSetUpFp)(void *arg);
+
+//!< Function pointer to a test case function
+typedef int (*SDLTest_TestCaseFp)(void *arg);
+
+//!< Function pointer to a test case teardown function (run after every test)
+typedef void (*SDLTest_TestCaseTearDownFp)(void *arg);
+
+typedef struct SDLTest_TestCaseReference {
+
+ SDLTest_TestCaseFp testCase;
+
+ char *name;
+
+ char *description;
+
+ int enabled;
+} SDLTest_TestCaseReference;
+
+typedef struct SDLTest_TestSuiteReference {
+
+ char *name;
+
+ SDLTest_TestCaseSetUpFp testSetUp;
+
+ const SDLTest_TestCaseReference **testCases;
+
+ SDLTest_TestCaseTearDownFp testTearDown;
+} SDLTest_TestSuiteReference;
+
+int SDLTest_RunSuites(SDLTest_TestSuiteReference *testSuites[], const char *userRunSeed, Uint64 userExecKey, const char *filter, int testIterations);
+
+#ifdef __cplusplus
+}
+#endif
+#include "close_code.h"
+
+#endif
+
diff --git a/extern/sdlew/include/SDL2/SDL_test_images.h b/extern/sdlew/include/SDL2/SDL_test_images.h
new file mode 100644
index 00000000000..545dd186078
--- /dev/null
+++ b/extern/sdlew/include/SDL2/SDL_test_images.h
@@ -0,0 +1,38 @@
+
+#ifndef _SDL_test_images_h
+#define _SDL_test_images_h
+
+#include "SDL.h"
+
+#include "begin_code.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct SDLTest_SurfaceImage_s {
+ int width;
+ int height;
+ unsigned int bytes_per_pixel;
+ const char *pixel_data;
+} SDLTest_SurfaceImage_t;
+
+SDL_Surface *SDLTest_ImageBlit();
+SDL_Surface *SDLTest_ImageBlitColor();
+SDL_Surface *SDLTest_ImageBlitAlpha();
+SDL_Surface *SDLTest_ImageBlitBlendAdd();
+SDL_Surface *SDLTest_ImageBlitBlend();
+SDL_Surface *SDLTest_ImageBlitBlendMod();
+SDL_Surface *SDLTest_ImageBlitBlendNone();
+SDL_Surface *SDLTest_ImageBlitBlendAll();
+SDL_Surface *SDLTest_ImageFace();
+SDL_Surface *SDLTest_ImagePrimitives();
+SDL_Surface *SDLTest_ImagePrimitivesBlend();
+
+#ifdef __cplusplus
+}
+#endif
+#include "close_code.h"
+
+#endif
+
diff --git a/extern/sdlew/include/SDL2/SDL_test_log.h b/extern/sdlew/include/SDL2/SDL_test_log.h
new file mode 100644
index 00000000000..084942a5774
--- /dev/null
+++ b/extern/sdlew/include/SDL2/SDL_test_log.h
@@ -0,0 +1,21 @@
+
+#ifndef _SDL_test_log_h
+#define _SDL_test_log_h
+
+#include "begin_code.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void SDLTest_Log(const char *fmt, ...);
+
+void SDLTest_LogError(const char *fmt, ...);
+
+#ifdef __cplusplus
+}
+#endif
+#include "close_code.h"
+
+#endif
+
diff --git a/extern/sdlew/include/SDL2/SDL_test_md5.h b/extern/sdlew/include/SDL2/SDL_test_md5.h
new file mode 100644
index 00000000000..9e149cc1f65
--- /dev/null
+++ b/extern/sdlew/include/SDL2/SDL_test_md5.h
@@ -0,0 +1,33 @@
+
+#ifndef _SDL_test_md5_h
+#define _SDL_test_md5_h
+
+#include "begin_code.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+ typedef unsigned long int MD5UINT4;
+
+ typedef struct {
+ MD5UINT4 i[2];
+ MD5UINT4 buf[4];
+ unsigned char in[64];
+ unsigned char digest[16];
+ } SDLTest_Md5Context;
+
+ void SDLTest_Md5Init(SDLTest_Md5Context * mdContext);
+
+ void SDLTest_Md5Update(SDLTest_Md5Context * mdContext, unsigned char *inBuf,
+ unsigned int inLen);
+
+ void SDLTest_Md5Final(SDLTest_Md5Context * mdContext);
+
+#ifdef __cplusplus
+}
+#endif
+#include "close_code.h"
+
+#endif
+
diff --git a/extern/sdlew/include/SDL2/SDL_test_random.h b/extern/sdlew/include/SDL2/SDL_test_random.h
new file mode 100644
index 00000000000..61a0c1b7a09
--- /dev/null
+++ b/extern/sdlew/include/SDL2/SDL_test_random.h
@@ -0,0 +1,34 @@
+
+#ifndef _SDL_test_random_h
+#define _SDL_test_random_h
+
+#include "begin_code.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define SDLTest_RandomInt(c) ((int)SDLTest_Random(c))
+
+ typedef struct {
+ unsigned int a;
+ unsigned int x;
+ unsigned int c;
+ unsigned int ah;
+ unsigned int al;
+ } SDLTest_RandomContext;
+
+ void SDLTest_RandomInit(SDLTest_RandomContext * rndContext, unsigned int xi,
+ unsigned int ci);
+
+ void SDLTest_RandomInitTime(SDLTest_RandomContext *rndContext);
+
+ unsigned int SDLTest_Random(SDLTest_RandomContext *rndContext);
+
+#ifdef __cplusplus
+}
+#endif
+#include "close_code.h"
+
+#endif
+
diff --git a/extern/sdlew/include/SDL2/SDL_thread.h b/extern/sdlew/include/SDL2/SDL_thread.h
new file mode 100644
index 00000000000..d7662713e51
--- /dev/null
+++ b/extern/sdlew/include/SDL2/SDL_thread.h
@@ -0,0 +1,90 @@
+
+#ifndef _SDL_thread_h
+#define _SDL_thread_h
+
+#include "SDL_stdinc.h"
+#include "SDL_error.h"
+
+#include "SDL_atomic.h"
+#include "SDL_mutex.h"
+
+#include "begin_code.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct SDL_Thread;
+typedef struct SDL_Thread SDL_Thread;
+
+typedef unsigned long SDL_threadID;
+
+typedef unsigned int SDL_TLSID;
+
+typedef enum {
+ SDL_THREAD_PRIORITY_LOW,
+ SDL_THREAD_PRIORITY_NORMAL,
+ SDL_THREAD_PRIORITY_HIGH
+} SDL_ThreadPriority;
+
+typedef int (SDLCALL * SDL_ThreadFunction) (void *data);
+
+#if defined(__WIN32__) && !defined(HAVE_LIBC)
+
+#define SDL_PASSED_BEGINTHREAD_ENDTHREAD
+#include <process.h>
+
+typedef uintptr_t(__cdecl * pfnSDL_CurrentBeginThread) (void *, unsigned,
+ unsigned (__stdcall *
+ func) (void
+ *),
+ void *arg, unsigned,
+ unsigned *threadID);
+typedef void (__cdecl * pfnSDL_CurrentEndThread) (unsigned code);
+
+extern DECLSPEC SDL_Thread *SDLCALL
+SDL_CreateThread(SDL_ThreadFunction fn, const char *name, void *data,
+ pfnSDL_CurrentBeginThread pfnBeginThread,
+ pfnSDL_CurrentEndThread pfnEndThread);
+
+#define SDL_CreateThread(fn, name, data) SDL_CreateThread(fn, name, data, (pfnSDL_CurrentBeginThread)_beginthreadex, (pfnSDL_CurrentEndThread)_endthreadex)
+
+#else
+
+extern DECLSPEC SDL_Thread *SDLCALL
+SDL_CreateThread(SDL_ThreadFunction fn, const char *name, void *data);
+
+#endif
+
+typedef const char * SDLCALL tSDL_GetThreadName(SDL_Thread *thread);
+
+typedef SDL_threadID SDLCALL tSDL_ThreadID(void);
+
+typedef SDL_threadID SDLCALL tSDL_GetThreadID(SDL_Thread * thread);
+
+typedef int SDLCALL tSDL_SetThreadPriority(SDL_ThreadPriority priority);
+
+typedef void SDLCALL tSDL_WaitThread(SDL_Thread * thread, int *status);
+
+typedef SDL_TLSID SDLCALL tSDL_TLSCreate(void);
+
+typedef void * SDLCALL tSDL_TLSGet(SDL_TLSID id);
+
+typedef int SDLCALL tSDL_TLSSet(SDL_TLSID id, const void *value, void (*destructor)(void*));
+
+extern tSDL_GetThreadName *SDL_GetThreadName;
+extern tSDL_ThreadID *SDL_ThreadID;
+extern tSDL_GetThreadID *SDL_GetThreadID;
+extern tSDL_SetThreadPriority *SDL_SetThreadPriority;
+extern tSDL_WaitThread *SDL_WaitThread;
+extern tSDL_TLSCreate *SDL_TLSCreate;
+extern tSDL_TLSGet *SDL_TLSGet;
+extern tSDL_TLSSet *SDL_TLSSet;
+
+#ifdef __cplusplus
+}
+#endif
+#include "close_code.h"
+
+#endif
+
diff --git a/extern/sdlew/include/SDL2/SDL_timer.h b/extern/sdlew/include/SDL2/SDL_timer.h
new file mode 100644
index 00000000000..bfaee50f6e1
--- /dev/null
+++ b/extern/sdlew/include/SDL2/SDL_timer.h
@@ -0,0 +1,45 @@
+
+#ifndef _SDL_timer_h
+#define _SDL_timer_h
+
+#include "SDL_stdinc.h"
+#include "SDL_error.h"
+
+#include "begin_code.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef Uint32 SDLCALL tSDL_GetTicks(void);
+
+typedef Uint64 SDLCALL tSDL_GetPerformanceCounter(void);
+
+typedef Uint64 SDLCALL tSDL_GetPerformanceFrequency(void);
+
+typedef void SDLCALL tSDL_Delay(Uint32 ms);
+
+typedef Uint32 (SDLCALL * SDL_TimerCallback) (Uint32 interval, void *param);
+
+typedef int SDL_TimerID;
+
+typedef SDL_TimerID SDLCALL tSDL_AddTimer(Uint32 interval,
+ SDL_TimerCallback callback,
+ void *param);
+
+typedef SDL_bool SDLCALL tSDL_RemoveTimer(SDL_TimerID id);
+
+extern tSDL_GetTicks *SDL_GetTicks;
+extern tSDL_GetPerformanceCounter *SDL_GetPerformanceCounter;
+extern tSDL_GetPerformanceFrequency *SDL_GetPerformanceFrequency;
+extern tSDL_Delay *SDL_Delay;
+extern tSDL_AddTimer *SDL_AddTimer;
+extern tSDL_RemoveTimer *SDL_RemoveTimer;
+
+#ifdef __cplusplus
+}
+#endif
+#include "close_code.h"
+
+#endif
+
diff --git a/extern/sdlew/include/SDL2/SDL_touch.h b/extern/sdlew/include/SDL2/SDL_touch.h
new file mode 100644
index 00000000000..bd8ded65748
--- /dev/null
+++ b/extern/sdlew/include/SDL2/SDL_touch.h
@@ -0,0 +1,47 @@
+
+#ifndef _SDL_touch_h
+#define _SDL_touch_h
+
+#include "SDL_stdinc.h"
+#include "SDL_error.h"
+#include "SDL_video.h"
+
+#include "begin_code.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef Sint64 SDL_TouchID;
+typedef Sint64 SDL_FingerID;
+
+typedef struct SDL_Finger
+{
+ SDL_FingerID id;
+ float x;
+ float y;
+ float pressure;
+} SDL_Finger;
+
+#define SDL_TOUCH_MOUSEID ((Uint32)-1)
+
+typedef int SDLCALL tSDL_GetNumTouchDevices(void);
+
+typedef SDL_TouchID SDLCALL tSDL_GetTouchDevice(int index);
+
+typedef int SDLCALL tSDL_GetNumTouchFingers(SDL_TouchID touchID);
+
+typedef SDL_Finger * SDLCALL tSDL_GetTouchFinger(SDL_TouchID touchID, int index);
+
+extern tSDL_GetNumTouchDevices *SDL_GetNumTouchDevices;
+extern tSDL_GetTouchDevice *SDL_GetTouchDevice;
+extern tSDL_GetNumTouchFingers *SDL_GetNumTouchFingers;
+extern tSDL_GetTouchFinger *SDL_GetTouchFinger;
+
+#ifdef __cplusplus
+}
+#endif
+#include "close_code.h"
+
+#endif
+
diff --git a/extern/sdlew/include/SDL2/SDL_types.h b/extern/sdlew/include/SDL2/SDL_types.h
new file mode 100644
index 00000000000..8ac56b71f2c
--- /dev/null
+++ b/extern/sdlew/include/SDL2/SDL_types.h
@@ -0,0 +1,2 @@
+
+#include "SDL_stdinc.h"
diff --git a/extern/sdlew/include/SDL2/SDL_version.h b/extern/sdlew/include/SDL2/SDL_version.h
new file mode 100644
index 00000000000..0156f77daea
--- /dev/null
+++ b/extern/sdlew/include/SDL2/SDL_version.h
@@ -0,0 +1,56 @@
+
+#ifndef _SDL_version_h
+#define _SDL_version_h
+
+#include "SDL_stdinc.h"
+
+#include "begin_code.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct SDL_version
+{
+ Uint8 major;
+ Uint8 minor;
+ Uint8 patch;
+} SDL_version;
+
+#define SDL_MAJOR_VERSION 2
+#define SDL_MINOR_VERSION 0
+#define SDL_PATCHLEVEL 0
+
+#define SDL_VERSION(x) \
+{ \
+ (x)->major = SDL_MAJOR_VERSION; \
+ (x)->minor = SDL_MINOR_VERSION; \
+ (x)->patch = SDL_PATCHLEVEL; \
+}
+
+#define SDL_VERSIONNUM(X, Y, Z) \
+ ((X)*1000 + (Y)*100 + (Z))
+
+#define SDL_COMPILEDVERSION \
+ SDL_VERSIONNUM(SDL_MAJOR_VERSION, SDL_MINOR_VERSION, SDL_PATCHLEVEL)
+
+#define SDL_VERSION_ATLEAST(X, Y, Z) \
+ (SDL_COMPILEDVERSION >= SDL_VERSIONNUM(X, Y, Z))
+
+typedef void SDLCALL tSDL_GetVersion(SDL_version * ver);
+
+typedef const char * SDLCALL tSDL_GetRevision(void);
+
+typedef int SDLCALL tSDL_GetRevisionNumber(void);
+
+extern tSDL_GetVersion *SDL_GetVersion;
+extern tSDL_GetRevision *SDL_GetRevision;
+extern tSDL_GetRevisionNumber *SDL_GetRevisionNumber;
+
+#ifdef __cplusplus
+}
+#endif
+#include "close_code.h"
+
+#endif
+
diff --git a/extern/sdlew/include/SDL2/SDL_video.h b/extern/sdlew/include/SDL2/SDL_video.h
new file mode 100644
index 00000000000..0a97ea45915
--- /dev/null
+++ b/extern/sdlew/include/SDL2/SDL_video.h
@@ -0,0 +1,367 @@
+
+#ifndef _SDL_video_h
+#define _SDL_video_h
+
+#include "SDL_stdinc.h"
+#include "SDL_pixels.h"
+#include "SDL_rect.h"
+#include "SDL_surface.h"
+
+#include "begin_code.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct
+{
+ Uint32 format;
+ int w;
+ int h;
+ int refresh_rate;
+ void *driverdata;
+} SDL_DisplayMode;
+
+typedef struct SDL_Window SDL_Window;
+
+typedef enum
+{
+ SDL_WINDOW_FULLSCREEN = 0x00000001,
+ SDL_WINDOW_OPENGL = 0x00000002,
+ SDL_WINDOW_SHOWN = 0x00000004,
+ SDL_WINDOW_HIDDEN = 0x00000008,
+ SDL_WINDOW_BORDERLESS = 0x00000010,
+ SDL_WINDOW_RESIZABLE = 0x00000020,
+ SDL_WINDOW_MINIMIZED = 0x00000040,
+ SDL_WINDOW_MAXIMIZED = 0x00000080,
+ SDL_WINDOW_INPUT_GRABBED = 0x00000100,
+ SDL_WINDOW_INPUT_FOCUS = 0x00000200,
+ SDL_WINDOW_MOUSE_FOCUS = 0x00000400,
+ SDL_WINDOW_FULLSCREEN_DESKTOP = ( SDL_WINDOW_FULLSCREEN | 0x00001000 ),
+ SDL_WINDOW_FOREIGN = 0x00000800
+} SDL_WindowFlags;
+
+#define SDL_WINDOWPOS_UNDEFINED_MASK 0x1FFF0000
+#define SDL_WINDOWPOS_UNDEFINED_DISPLAY(X) (SDL_WINDOWPOS_UNDEFINED_MASK|(X))
+#define SDL_WINDOWPOS_UNDEFINED SDL_WINDOWPOS_UNDEFINED_DISPLAY(0)
+#define SDL_WINDOWPOS_ISUNDEFINED(X) \
+ (((X)&0xFFFF0000) == SDL_WINDOWPOS_UNDEFINED_MASK)
+
+#define SDL_WINDOWPOS_CENTERED_MASK 0x2FFF0000
+#define SDL_WINDOWPOS_CENTERED_DISPLAY(X) (SDL_WINDOWPOS_CENTERED_MASK|(X))
+#define SDL_WINDOWPOS_CENTERED SDL_WINDOWPOS_CENTERED_DISPLAY(0)
+#define SDL_WINDOWPOS_ISCENTERED(X) \
+ (((X)&0xFFFF0000) == SDL_WINDOWPOS_CENTERED_MASK)
+
+typedef enum
+{
+ SDL_WINDOWEVENT_NONE,
+ SDL_WINDOWEVENT_SHOWN,
+ SDL_WINDOWEVENT_HIDDEN,
+ SDL_WINDOWEVENT_EXPOSED,
+ SDL_WINDOWEVENT_MOVED,
+ SDL_WINDOWEVENT_RESIZED,
+ SDL_WINDOWEVENT_SIZE_CHANGED,
+ SDL_WINDOWEVENT_MINIMIZED,
+ SDL_WINDOWEVENT_MAXIMIZED,
+ SDL_WINDOWEVENT_RESTORED,
+ SDL_WINDOWEVENT_ENTER,
+ SDL_WINDOWEVENT_LEAVE,
+ SDL_WINDOWEVENT_FOCUS_GAINED,
+ SDL_WINDOWEVENT_FOCUS_LOST,
+ SDL_WINDOWEVENT_CLOSE
+} SDL_WindowEventID;
+
+typedef void *SDL_GLContext;
+
+typedef enum
+{
+ SDL_GL_RED_SIZE,
+ SDL_GL_GREEN_SIZE,
+ SDL_GL_BLUE_SIZE,
+ SDL_GL_ALPHA_SIZE,
+ SDL_GL_BUFFER_SIZE,
+ SDL_GL_DOUBLEBUFFER,
+ SDL_GL_DEPTH_SIZE,
+ SDL_GL_STENCIL_SIZE,
+ SDL_GL_ACCUM_RED_SIZE,
+ SDL_GL_ACCUM_GREEN_SIZE,
+ SDL_GL_ACCUM_BLUE_SIZE,
+ SDL_GL_ACCUM_ALPHA_SIZE,
+ SDL_GL_STEREO,
+ SDL_GL_MULTISAMPLEBUFFERS,
+ SDL_GL_MULTISAMPLESAMPLES,
+ SDL_GL_ACCELERATED_VISUAL,
+ SDL_GL_RETAINED_BACKING,
+ SDL_GL_CONTEXT_MAJOR_VERSION,
+ SDL_GL_CONTEXT_MINOR_VERSION,
+ SDL_GL_CONTEXT_EGL,
+ SDL_GL_CONTEXT_FLAGS,
+ SDL_GL_CONTEXT_PROFILE_MASK,
+ SDL_GL_SHARE_WITH_CURRENT_CONTEXT
+} SDL_GLattr;
+
+typedef enum
+{
+ SDL_GL_CONTEXT_PROFILE_CORE = 0x0001,
+ SDL_GL_CONTEXT_PROFILE_COMPATIBILITY = 0x0002,
+ SDL_GL_CONTEXT_PROFILE_ES = 0x0004
+} SDL_GLprofile;
+
+typedef enum
+{
+ SDL_GL_CONTEXT_DEBUG_FLAG = 0x0001,
+ SDL_GL_CONTEXT_FORWARD_COMPATIBLE_FLAG = 0x0002,
+ SDL_GL_CONTEXT_ROBUST_ACCESS_FLAG = 0x0004,
+ SDL_GL_CONTEXT_RESET_ISOLATION_FLAG = 0x0008
+} SDL_GLcontextFlag;
+
+typedef int SDLCALL tSDL_GetNumVideoDrivers(void);
+
+typedef const char * SDLCALL tSDL_GetVideoDriver(int index);
+
+typedef int SDLCALL tSDL_VideoInit(const char *driver_name);
+
+typedef void SDLCALL tSDL_VideoQuit(void);
+
+typedef const char * SDLCALL tSDL_GetCurrentVideoDriver(void);
+
+typedef int SDLCALL tSDL_GetNumVideoDisplays(void);
+
+typedef const char * SDLCALL tSDL_GetDisplayName(int displayIndex);
+
+typedef int SDLCALL tSDL_GetDisplayBounds(int displayIndex, SDL_Rect * rect);
+
+typedef int SDLCALL tSDL_GetNumDisplayModes(int displayIndex);
+
+typedef int SDLCALL tSDL_GetDisplayMode(int displayIndex, int modeIndex,
+ SDL_DisplayMode * mode);
+
+typedef int SDLCALL tSDL_GetDesktopDisplayMode(int displayIndex, SDL_DisplayMode * mode);
+
+typedef int SDLCALL tSDL_GetCurrentDisplayMode(int displayIndex, SDL_DisplayMode * mode);
+
+typedef SDL_DisplayMode * SDLCALL tSDL_GetClosestDisplayMode(int displayIndex, const SDL_DisplayMode * mode, SDL_DisplayMode * closest);
+
+typedef int SDLCALL tSDL_GetWindowDisplayIndex(SDL_Window * window);
+
+typedef int SDLCALL tSDL_SetWindowDisplayMode(SDL_Window * window,
+ const SDL_DisplayMode
+ * mode);
+
+typedef int SDLCALL tSDL_GetWindowDisplayMode(SDL_Window * window,
+ SDL_DisplayMode * mode);
+
+typedef Uint32 SDLCALL tSDL_GetWindowPixelFormat(SDL_Window * window);
+
+typedef SDL_Window * SDLCALL tSDL_CreateWindow(const char *title,
+ int x, int y, int w,
+ int h, Uint32 flags);
+
+typedef SDL_Window * SDLCALL tSDL_CreateWindowFrom(const void *data);
+
+typedef Uint32 SDLCALL tSDL_GetWindowID(SDL_Window * window);
+
+typedef SDL_Window * SDLCALL tSDL_GetWindowFromID(Uint32 id);
+
+typedef Uint32 SDLCALL tSDL_GetWindowFlags(SDL_Window * window);
+
+typedef void SDLCALL tSDL_SetWindowTitle(SDL_Window * window,
+ const char *title);
+
+typedef const char * SDLCALL tSDL_GetWindowTitle(SDL_Window * window);
+
+typedef void SDLCALL tSDL_SetWindowIcon(SDL_Window * window,
+ SDL_Surface * icon);
+
+extern DECLSPEC void* SDLCALL SDL_SetWindowData(SDL_Window * window,
+ const char *name,
+ void *userdata);
+
+typedef void * SDLCALL tSDL_GetWindowData(SDL_Window * window,
+ const char *name);
+
+typedef void SDLCALL tSDL_SetWindowPosition(SDL_Window * window,
+ int x, int y);
+
+typedef void SDLCALL tSDL_GetWindowPosition(SDL_Window * window,
+ int *x, int *y);
+
+typedef void SDLCALL tSDL_SetWindowSize(SDL_Window * window, int w,
+ int h);
+
+typedef void SDLCALL tSDL_GetWindowSize(SDL_Window * window, int *w,
+ int *h);
+
+typedef void SDLCALL tSDL_SetWindowMinimumSize(SDL_Window * window,
+ int min_w, int min_h);
+
+typedef void SDLCALL tSDL_GetWindowMinimumSize(SDL_Window * window,
+ int *w, int *h);
+
+typedef void SDLCALL tSDL_SetWindowMaximumSize(SDL_Window * window,
+ int max_w, int max_h);
+
+typedef void SDLCALL tSDL_GetWindowMaximumSize(SDL_Window * window,
+ int *w, int *h);
+
+typedef void SDLCALL tSDL_SetWindowBordered(SDL_Window * window,
+ SDL_bool bordered);
+
+typedef void SDLCALL tSDL_ShowWindow(SDL_Window * window);
+
+typedef void SDLCALL tSDL_HideWindow(SDL_Window * window);
+
+typedef void SDLCALL tSDL_RaiseWindow(SDL_Window * window);
+
+typedef void SDLCALL tSDL_MaximizeWindow(SDL_Window * window);
+
+typedef void SDLCALL tSDL_MinimizeWindow(SDL_Window * window);
+
+typedef void SDLCALL tSDL_RestoreWindow(SDL_Window * window);
+
+typedef int SDLCALL tSDL_SetWindowFullscreen(SDL_Window * window,
+ Uint32 flags);
+
+typedef SDL_Surface * SDLCALL tSDL_GetWindowSurface(SDL_Window * window);
+
+typedef int SDLCALL tSDL_UpdateWindowSurface(SDL_Window * window);
+
+typedef int SDLCALL tSDL_UpdateWindowSurfaceRects(SDL_Window * window,
+ const SDL_Rect * rects,
+ int numrects);
+
+typedef void SDLCALL tSDL_SetWindowGrab(SDL_Window * window,
+ SDL_bool grabbed);
+
+typedef SDL_bool SDLCALL tSDL_GetWindowGrab(SDL_Window * window);
+
+typedef int SDLCALL tSDL_SetWindowBrightness(SDL_Window * window, float brightness);
+
+typedef float SDLCALL tSDL_GetWindowBrightness(SDL_Window * window);
+
+typedef int SDLCALL tSDL_SetWindowGammaRamp(SDL_Window * window,
+ const Uint16 * red,
+ const Uint16 * green,
+ const Uint16 * blue);
+
+typedef int SDLCALL tSDL_GetWindowGammaRamp(SDL_Window * window,
+ Uint16 * red,
+ Uint16 * green,
+ Uint16 * blue);
+
+typedef void SDLCALL tSDL_DestroyWindow(SDL_Window * window);
+
+typedef SDL_bool SDLCALL tSDL_IsScreenSaverEnabled(void);
+
+typedef void SDLCALL tSDL_EnableScreenSaver(void);
+
+typedef void SDLCALL tSDL_DisableScreenSaver(void);
+
+typedef int SDLCALL tSDL_GL_LoadLibrary(const char *path);
+
+typedef void * SDLCALL tSDL_GL_GetProcAddress(const char *proc);
+
+typedef void SDLCALL tSDL_GL_UnloadLibrary(void);
+
+typedef SDL_bool SDLCALL tSDL_GL_ExtensionSupported(const char
+ *extension);
+
+typedef int SDLCALL tSDL_GL_SetAttribute(SDL_GLattr attr, int value);
+
+typedef int SDLCALL tSDL_GL_GetAttribute(SDL_GLattr attr, int *value);
+
+typedef SDL_GLContext SDLCALL tSDL_GL_CreateContext(SDL_Window *
+ window);
+
+typedef int SDLCALL tSDL_GL_MakeCurrent(SDL_Window * window,
+ SDL_GLContext context);
+
+extern DECLSPEC SDL_Window* SDLCALL SDL_GL_GetCurrentWindow(void);
+
+typedef SDL_GLContext SDLCALL tSDL_GL_GetCurrentContext(void);
+
+typedef int SDLCALL tSDL_GL_SetSwapInterval(int interval);
+
+typedef int SDLCALL tSDL_GL_GetSwapInterval(void);
+
+typedef void SDLCALL tSDL_GL_SwapWindow(SDL_Window * window);
+
+typedef void SDLCALL tSDL_GL_DeleteContext(SDL_GLContext context);
+
+extern tSDL_GetNumVideoDrivers *SDL_GetNumVideoDrivers;
+extern tSDL_GetVideoDriver *SDL_GetVideoDriver;
+extern tSDL_VideoInit *SDL_VideoInit;
+extern tSDL_VideoQuit *SDL_VideoQuit;
+extern tSDL_GetCurrentVideoDriver *SDL_GetCurrentVideoDriver;
+extern tSDL_GetNumVideoDisplays *SDL_GetNumVideoDisplays;
+extern tSDL_GetDisplayName *SDL_GetDisplayName;
+extern tSDL_GetDisplayBounds *SDL_GetDisplayBounds;
+extern tSDL_GetNumDisplayModes *SDL_GetNumDisplayModes;
+extern tSDL_GetDisplayMode *SDL_GetDisplayMode;
+extern tSDL_GetDesktopDisplayMode *SDL_GetDesktopDisplayMode;
+extern tSDL_GetCurrentDisplayMode *SDL_GetCurrentDisplayMode;
+extern tSDL_GetClosestDisplayMode *SDL_GetClosestDisplayMode;
+extern tSDL_GetWindowDisplayIndex *SDL_GetWindowDisplayIndex;
+extern tSDL_SetWindowDisplayMode *SDL_SetWindowDisplayMode;
+extern tSDL_GetWindowDisplayMode *SDL_GetWindowDisplayMode;
+extern tSDL_GetWindowPixelFormat *SDL_GetWindowPixelFormat;
+extern tSDL_CreateWindow *SDL_CreateWindow;
+extern tSDL_CreateWindowFrom *SDL_CreateWindowFrom;
+extern tSDL_GetWindowID *SDL_GetWindowID;
+extern tSDL_GetWindowFromID *SDL_GetWindowFromID;
+extern tSDL_GetWindowFlags *SDL_GetWindowFlags;
+extern tSDL_SetWindowTitle *SDL_SetWindowTitle;
+extern tSDL_GetWindowTitle *SDL_GetWindowTitle;
+extern tSDL_SetWindowIcon *SDL_SetWindowIcon;
+extern tSDL_GetWindowData *SDL_GetWindowData;
+extern tSDL_SetWindowPosition *SDL_SetWindowPosition;
+extern tSDL_GetWindowPosition *SDL_GetWindowPosition;
+extern tSDL_SetWindowSize *SDL_SetWindowSize;
+extern tSDL_GetWindowSize *SDL_GetWindowSize;
+extern tSDL_SetWindowMinimumSize *SDL_SetWindowMinimumSize;
+extern tSDL_GetWindowMinimumSize *SDL_GetWindowMinimumSize;
+extern tSDL_SetWindowMaximumSize *SDL_SetWindowMaximumSize;
+extern tSDL_GetWindowMaximumSize *SDL_GetWindowMaximumSize;
+extern tSDL_SetWindowBordered *SDL_SetWindowBordered;
+extern tSDL_ShowWindow *SDL_ShowWindow;
+extern tSDL_HideWindow *SDL_HideWindow;
+extern tSDL_RaiseWindow *SDL_RaiseWindow;
+extern tSDL_MaximizeWindow *SDL_MaximizeWindow;
+extern tSDL_MinimizeWindow *SDL_MinimizeWindow;
+extern tSDL_RestoreWindow *SDL_RestoreWindow;
+extern tSDL_SetWindowFullscreen *SDL_SetWindowFullscreen;
+extern tSDL_GetWindowSurface *SDL_GetWindowSurface;
+extern tSDL_UpdateWindowSurface *SDL_UpdateWindowSurface;
+extern tSDL_UpdateWindowSurfaceRects *SDL_UpdateWindowSurfaceRects;
+extern tSDL_SetWindowGrab *SDL_SetWindowGrab;
+extern tSDL_GetWindowGrab *SDL_GetWindowGrab;
+extern tSDL_SetWindowBrightness *SDL_SetWindowBrightness;
+extern tSDL_GetWindowBrightness *SDL_GetWindowBrightness;
+extern tSDL_SetWindowGammaRamp *SDL_SetWindowGammaRamp;
+extern tSDL_GetWindowGammaRamp *SDL_GetWindowGammaRamp;
+extern tSDL_DestroyWindow *SDL_DestroyWindow;
+extern tSDL_IsScreenSaverEnabled *SDL_IsScreenSaverEnabled;
+extern tSDL_EnableScreenSaver *SDL_EnableScreenSaver;
+extern tSDL_DisableScreenSaver *SDL_DisableScreenSaver;
+extern tSDL_GL_LoadLibrary *SDL_GL_LoadLibrary;
+extern tSDL_GL_GetProcAddress *SDL_GL_GetProcAddress;
+extern tSDL_GL_UnloadLibrary *SDL_GL_UnloadLibrary;
+extern tSDL_GL_ExtensionSupported *SDL_GL_ExtensionSupported;
+extern tSDL_GL_SetAttribute *SDL_GL_SetAttribute;
+extern tSDL_GL_GetAttribute *SDL_GL_GetAttribute;
+extern tSDL_GL_CreateContext *SDL_GL_CreateContext;
+extern tSDL_GL_MakeCurrent *SDL_GL_MakeCurrent;
+extern tSDL_GL_GetCurrentContext *SDL_GL_GetCurrentContext;
+extern tSDL_GL_SetSwapInterval *SDL_GL_SetSwapInterval;
+extern tSDL_GL_GetSwapInterval *SDL_GL_GetSwapInterval;
+extern tSDL_GL_SwapWindow *SDL_GL_SwapWindow;
+extern tSDL_GL_DeleteContext *SDL_GL_DeleteContext;
+
+#ifdef __cplusplus
+}
+#endif
+#include "close_code.h"
+
+#endif
+
diff --git a/extern/sdlew/include/SDL2/begin_code.h b/extern/sdlew/include/SDL2/begin_code.h
new file mode 100644
index 00000000000..8922c000c5f
--- /dev/null
+++ b/extern/sdlew/include/SDL2/begin_code.h
@@ -0,0 +1,107 @@
+
+#ifdef _begin_code_h
+#error Nested inclusion of begin_code.h
+#endif
+#define _begin_code_h
+
+#ifndef DECLSPEC
+# if defined(__BEOS__) || defined(__HAIKU__)
+# if defined(__GNUC__)
+# define DECLSPEC __declspec(dllexport)
+# else
+# define DECLSPEC __declspec(export)
+# endif
+# elif defined(__WIN32__)
+# ifdef __BORLANDC__
+# ifdef BUILD_SDL
+# define DECLSPEC
+# else
+# define DECLSPEC __declspec(dllimport)
+# endif
+# else
+# define DECLSPEC __declspec(dllexport)
+# endif
+# else
+# if defined(__GNUC__) && __GNUC__ >= 4
+# define DECLSPEC __attribute__ ((visibility("default")))
+# else
+# define DECLSPEC
+# endif
+# endif
+#endif
+
+#ifndef SDLCALL
+#if defined(__WIN32__) && !defined(__GNUC__)
+#define SDLCALL __cdecl
+#else
+#define SDLCALL
+#endif
+#endif
+
+#ifdef __SYMBIAN32__
+#undef DECLSPEC
+#define DECLSPEC
+#endif
+
+#if defined(_MSC_VER) || defined(__MWERKS__) || defined(__BORLANDC__)
+#ifdef _MSC_VER
+#pragma warning(disable: 4103)
+#endif
+#ifdef __BORLANDC__
+#pragma nopackwarning
+#endif
+#ifdef _M_X64
+
+#pragma pack(push,8)
+#else
+#pragma pack(push,4)
+#endif
+#endif
+
+#ifndef SDL_INLINE_OKAY
+#ifdef __GNUC__
+#define SDL_INLINE_OKAY
+#else
+
+#if defined(_MSC_VER) || defined(__BORLANDC__) || \
+ defined(__DMC__) || defined(__SC__) || \
+ defined(__WATCOMC__) || defined(__LCC__) || \
+ defined(__DECC)
+#ifndef __inline__
+#define __inline__ __inline
+#endif
+#define SDL_INLINE_OKAY
+#else
+#if !defined(__MRC__) && !defined(_SGI_SOURCE)
+#ifndef __inline__
+#define __inline__ inline
+#endif
+#define SDL_INLINE_OKAY
+#endif
+#endif
+#endif
+#endif
+
+#ifndef SDL_INLINE_OKAY
+#define __inline__
+#endif
+
+#ifndef SDL_FORCE_INLINE
+#if defined(_MSC_VER)
+#define SDL_FORCE_INLINE __forceinline
+#elif ( (defined(__GNUC__) && (__GNUC__ >= 4)) || defined(__clang__) )
+#define SDL_FORCE_INLINE __attribute__((always_inline)) static inline
+#else
+#define SDL_FORCE_INLINE static __inline__
+#endif
+#endif
+
+#if !defined(__MACH__)
+#ifndef NULL
+#ifdef __cplusplus
+#define NULL 0
+#else
+#define NULL ((void *)0)
+#endif
+#endif
+#endif
diff --git a/extern/sdlew/include/SDL2/close_code.h b/extern/sdlew/include/SDL2/close_code.h
new file mode 100644
index 00000000000..7a1e48c0539
--- /dev/null
+++ b/extern/sdlew/include/SDL2/close_code.h
@@ -0,0 +1,9 @@
+
+#undef _begin_code_h
+
+#if defined(_MSC_VER) || defined(__MWERKS__) || defined(__WATCOMC__) || defined(__BORLANDC__)
+#ifdef __BORLANDC__
+#pragma nopackwarning
+#endif
+#pragma pack(pop)
+#endif
diff --git a/intern/cycles/render/blackbody.h b/extern/sdlew/include/sdlew.h
index c3be0ebdf30..dde3d70ab31 100644
--- a/intern/cycles/render/blackbody.h
+++ b/extern/sdlew/include/sdlew.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2011-2013 Blender Foundation
+ * Copyright 2014 Blender Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,15 +14,24 @@
* limitations under the License
*/
-#ifndef __BLACKBODY_H__
-#define __BLACKBODY_H__
+#ifndef __SDL_EW_H__
+#define __SDL_EW_H__
-#include "util_vector.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
-CCL_NAMESPACE_BEGIN
+enum {
+ SDLEW_SUCCESS = 0,
+ SDLEW_ERROR_OPEN_FAILED = -1,
+ SDLEW_ERROR_ATEXIT_FAILED = -2,
+ SDLEW_ERROR_VERSION = -3,
+};
-vector<float> blackbody_table();
+int sdlewInit(void);
-CCL_NAMESPACE_END
+#ifdef __cplusplus
+}
+#endif
-#endif /* __BLACKBODY_H__ */
+#endif /* __SDL_EW_H__ */
diff --git a/extern/sdlew/src/sdlew.c b/extern/sdlew/src/sdlew.c
new file mode 100644
index 00000000000..3b19f0cef47
--- /dev/null
+++ b/extern/sdlew/src/sdlew.c
@@ -0,0 +1,1112 @@
+/*
+ * Copyright 2014 Blender Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+#ifdef _MSC_VER
+# define snprintf _snprintf
+# define popen _popen
+# define pclose _pclose
+# define _CRT_SECURE_NO_WARNINGS
+#endif
+
+#include "sdlew.h"
+
+#include "SDL2/SDL.h"
+#include "SDL2/SDL_syswm.h"
+
+#include <assert.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/stat.h>
+
+#ifdef _WIN32
+# define WIN32_LEAN_AND_MEAN
+# define VC_EXTRALEAN
+# include <windows.h>
+
+/* Utility macros. */
+
+typedef HMODULE DynamicLibrary;
+
+# define dynamic_library_open(path) LoadLibrary(path)
+# define dynamic_library_close(lib) FreeLibrary(lib)
+# define dynamic_library_find(lib, symbol) GetProcAddress(lib, symbol)
+#else
+# include <dlfcn.h>
+
+typedef void* DynamicLibrary;
+
+# define dynamic_library_open(path) dlopen(path, RTLD_NOW)
+# define dynamic_library_close(lib) dlclose(lib)
+# define dynamic_library_find(lib, symbol) dlsym(lib, symbol)
+#endif
+
+#define SDL_LIBRARY_FIND_CHECKED(name) name = (t##name *)dynamic_library_find(lib, #name); assert(name);
+
+#define SDL_LIBRARY_FIND(name) name = (t##name *)dynamic_library_find(lib, #name);
+
+static DynamicLibrary lib;
+
+tSDL_GetPlatform *SDL_GetPlatform;
+tSDL_memcpy *SDL_memcpy;
+#ifndef HAVE_ALLOCA
+tSDL_malloc *SDL_malloc;
+#endif
+tSDL_calloc *SDL_calloc;
+tSDL_realloc *SDL_realloc;
+tSDL_free *SDL_free;
+tSDL_getenv *SDL_getenv;
+tSDL_setenv *SDL_setenv;
+tSDL_qsort *SDL_qsort;
+tSDL_abs *SDL_abs;
+tSDL_isdigit *SDL_isdigit;
+tSDL_isspace *SDL_isspace;
+tSDL_toupper *SDL_toupper;
+tSDL_tolower *SDL_tolower;
+tSDL_memset *SDL_memset;
+tSDL_memmove *SDL_memmove;
+tSDL_memcmp *SDL_memcmp;
+tSDL_wcslen *SDL_wcslen;
+tSDL_wcslcpy *SDL_wcslcpy;
+tSDL_wcslcat *SDL_wcslcat;
+tSDL_strlen *SDL_strlen;
+tSDL_strlcpy *SDL_strlcpy;
+tSDL_utf8strlcpy *SDL_utf8strlcpy;
+tSDL_strlcat *SDL_strlcat;
+tSDL_strdup *SDL_strdup;
+tSDL_strrev *SDL_strrev;
+tSDL_strupr *SDL_strupr;
+tSDL_strlwr *SDL_strlwr;
+tSDL_strchr *SDL_strchr;
+tSDL_strrchr *SDL_strrchr;
+tSDL_strstr *SDL_strstr;
+tSDL_itoa *SDL_itoa;
+tSDL_uitoa *SDL_uitoa;
+tSDL_ltoa *SDL_ltoa;
+tSDL_ultoa *SDL_ultoa;
+tSDL_lltoa *SDL_lltoa;
+tSDL_ulltoa *SDL_ulltoa;
+tSDL_atoi *SDL_atoi;
+tSDL_atof *SDL_atof;
+tSDL_strtol *SDL_strtol;
+tSDL_strtoll *SDL_strtoll;
+tSDL_strtoull *SDL_strtoull;
+tSDL_strtod *SDL_strtod;
+tSDL_strcmp *SDL_strcmp;
+tSDL_strncmp *SDL_strncmp;
+tSDL_strcasecmp *SDL_strcasecmp;
+tSDL_strncasecmp *SDL_strncasecmp;
+tSDL_sscanf *SDL_sscanf;
+tSDL_snprintf *SDL_snprintf;
+tSDL_vsnprintf *SDL_vsnprintf;
+tSDL_atan *SDL_atan;
+tSDL_atan2 *SDL_atan2;
+tSDL_ceil *SDL_ceil;
+tSDL_copysign *SDL_copysign;
+tSDL_cos *SDL_cos;
+tSDL_cosf *SDL_cosf;
+tSDL_fabs *SDL_fabs;
+tSDL_floor *SDL_floor;
+tSDL_log *SDL_log;
+tSDL_pow *SDL_pow;
+tSDL_scalbn *SDL_scalbn;
+tSDL_sin *SDL_sin;
+tSDL_sinf *SDL_sinf;
+tSDL_sqrt *SDL_sqrt;
+tSDL_iconv_open *SDL_iconv_open;
+tSDL_iconv_close *SDL_iconv_close;
+tSDL_iconv *SDL_iconv;
+tSDL_iconv_string *SDL_iconv_string;
+tSDL_GetNumRenderDrivers *SDL_GetNumRenderDrivers;
+tSDL_GetRenderDriverInfo *SDL_GetRenderDriverInfo;
+tSDL_CreateWindowAndRenderer *SDL_CreateWindowAndRenderer;
+tSDL_CreateRenderer *SDL_CreateRenderer;
+tSDL_CreateSoftwareRenderer *SDL_CreateSoftwareRenderer;
+tSDL_GetRenderer *SDL_GetRenderer;
+tSDL_GetRendererInfo *SDL_GetRendererInfo;
+tSDL_GetRendererOutputSize *SDL_GetRendererOutputSize;
+tSDL_CreateTexture *SDL_CreateTexture;
+tSDL_CreateTextureFromSurface *SDL_CreateTextureFromSurface;
+tSDL_QueryTexture *SDL_QueryTexture;
+tSDL_SetTextureColorMod *SDL_SetTextureColorMod;
+tSDL_GetTextureColorMod *SDL_GetTextureColorMod;
+tSDL_SetTextureAlphaMod *SDL_SetTextureAlphaMod;
+tSDL_GetTextureAlphaMod *SDL_GetTextureAlphaMod;
+tSDL_SetTextureBlendMode *SDL_SetTextureBlendMode;
+tSDL_GetTextureBlendMode *SDL_GetTextureBlendMode;
+tSDL_UpdateTexture *SDL_UpdateTexture;
+tSDL_LockTexture *SDL_LockTexture;
+tSDL_UnlockTexture *SDL_UnlockTexture;
+tSDL_RenderTargetSupported *SDL_RenderTargetSupported;
+tSDL_SetRenderTarget *SDL_SetRenderTarget;
+tSDL_GetRenderTarget *SDL_GetRenderTarget;
+tSDL_RenderSetLogicalSize *SDL_RenderSetLogicalSize;
+tSDL_RenderGetLogicalSize *SDL_RenderGetLogicalSize;
+tSDL_RenderSetViewport *SDL_RenderSetViewport;
+tSDL_RenderGetViewport *SDL_RenderGetViewport;
+tSDL_RenderSetClipRect *SDL_RenderSetClipRect;
+tSDL_RenderGetClipRect *SDL_RenderGetClipRect;
+tSDL_RenderSetScale *SDL_RenderSetScale;
+tSDL_RenderGetScale *SDL_RenderGetScale;
+tSDL_SetRenderDrawBlendMode *SDL_SetRenderDrawBlendMode;
+tSDL_GetRenderDrawBlendMode *SDL_GetRenderDrawBlendMode;
+tSDL_RenderClear *SDL_RenderClear;
+tSDL_RenderDrawPoint *SDL_RenderDrawPoint;
+tSDL_RenderDrawPoints *SDL_RenderDrawPoints;
+tSDL_RenderDrawLine *SDL_RenderDrawLine;
+tSDL_RenderDrawLines *SDL_RenderDrawLines;
+tSDL_RenderDrawRect *SDL_RenderDrawRect;
+tSDL_RenderDrawRects *SDL_RenderDrawRects;
+tSDL_RenderFillRect *SDL_RenderFillRect;
+tSDL_RenderFillRects *SDL_RenderFillRects;
+tSDL_RenderCopy *SDL_RenderCopy;
+tSDL_RenderCopyEx *SDL_RenderCopyEx;
+tSDL_RenderReadPixels *SDL_RenderReadPixels;
+tSDL_RenderPresent *SDL_RenderPresent;
+tSDL_DestroyTexture *SDL_DestroyTexture;
+tSDL_DestroyRenderer *SDL_DestroyRenderer;
+tSDL_GL_BindTexture *SDL_GL_BindTexture;
+tSDL_GL_UnbindTexture *SDL_GL_UnbindTexture;
+tSDL_LoadObject *SDL_LoadObject;
+tSDL_LoadFunction *SDL_LoadFunction;
+tSDL_UnloadObject *SDL_UnloadObject;
+tSDL_ReportAssertion *SDL_ReportAssertion;
+tSDL_SetAssertionHandler *SDL_SetAssertionHandler;
+tSDL_GetAssertionReport *SDL_GetAssertionReport;
+tSDL_ResetAssertionReport *SDL_ResetAssertionReport;
+tSDL_AtomicTryLock *SDL_AtomicTryLock;
+tSDL_AtomicLock *SDL_AtomicLock;
+tSDL_AtomicUnlock *SDL_AtomicUnlock;
+tSDL_HasIntersection *SDL_HasIntersection;
+tSDL_IntersectRect *SDL_IntersectRect;
+tSDL_UnionRect *SDL_UnionRect;
+tSDL_EnclosePoints *SDL_EnclosePoints;
+tSDL_IntersectRectAndLine *SDL_IntersectRectAndLine;
+tSDL_LogSetAllPriority *SDL_LogSetAllPriority;
+tSDL_LogSetPriority *SDL_LogSetPriority;
+tSDL_LogGetPriority *SDL_LogGetPriority;
+tSDL_LogResetPriorities *SDL_LogResetPriorities;
+tSDL_Log *SDL_Log;
+tSDL_LogVerbose *SDL_LogVerbose;
+tSDL_LogDebug *SDL_LogDebug;
+tSDL_LogInfo *SDL_LogInfo;
+tSDL_LogWarn *SDL_LogWarn;
+tSDL_LogError *SDL_LogError;
+tSDL_LogCritical *SDL_LogCritical;
+tSDL_LogMessage *SDL_LogMessage;
+tSDL_LogMessageV *SDL_LogMessageV;
+tSDL_LogGetOutputFunction *SDL_LogGetOutputFunction;
+tSDL_LogSetOutputFunction *SDL_LogSetOutputFunction;
+tSDL_CreateMutex *SDL_CreateMutex;
+tSDL_LockMutex *SDL_LockMutex;
+tSDL_TryLockMutex *SDL_TryLockMutex;
+tSDL_UnlockMutex *SDL_UnlockMutex;
+tSDL_DestroyMutex *SDL_DestroyMutex;
+tSDL_CreateSemaphore *SDL_CreateSemaphore;
+tSDL_DestroySemaphore *SDL_DestroySemaphore;
+tSDL_SemWait *SDL_SemWait;
+tSDL_SemTryWait *SDL_SemTryWait;
+tSDL_SemWaitTimeout *SDL_SemWaitTimeout;
+tSDL_SemPost *SDL_SemPost;
+tSDL_SemValue *SDL_SemValue;
+tSDL_CreateCond *SDL_CreateCond;
+tSDL_DestroyCond *SDL_DestroyCond;
+tSDL_CondSignal *SDL_CondSignal;
+tSDL_CondBroadcast *SDL_CondBroadcast;
+tSDL_CondWait *SDL_CondWait;
+tSDL_CondWaitTimeout *SDL_CondWaitTimeout;
+tSDL_CreateRGBSurface *SDL_CreateRGBSurface;
+tSDL_CreateRGBSurfaceFrom *SDL_CreateRGBSurfaceFrom;
+tSDL_FreeSurface *SDL_FreeSurface;
+tSDL_SetSurfacePalette *SDL_SetSurfacePalette;
+tSDL_LockSurface *SDL_LockSurface;
+tSDL_UnlockSurface *SDL_UnlockSurface;
+tSDL_LoadBMP_RW *SDL_LoadBMP_RW;
+tSDL_SaveBMP_RW *SDL_SaveBMP_RW;
+tSDL_SetSurfaceRLE *SDL_SetSurfaceRLE;
+tSDL_SetColorKey *SDL_SetColorKey;
+tSDL_GetColorKey *SDL_GetColorKey;
+tSDL_SetSurfaceColorMod *SDL_SetSurfaceColorMod;
+tSDL_GetSurfaceColorMod *SDL_GetSurfaceColorMod;
+tSDL_SetSurfaceAlphaMod *SDL_SetSurfaceAlphaMod;
+tSDL_GetSurfaceAlphaMod *SDL_GetSurfaceAlphaMod;
+tSDL_SetSurfaceBlendMode *SDL_SetSurfaceBlendMode;
+tSDL_GetSurfaceBlendMode *SDL_GetSurfaceBlendMode;
+tSDL_SetClipRect *SDL_SetClipRect;
+tSDL_GetClipRect *SDL_GetClipRect;
+tSDL_ConvertSurface *SDL_ConvertSurface;
+tSDL_ConvertSurfaceFormat *SDL_ConvertSurfaceFormat;
+tSDL_ConvertPixels *SDL_ConvertPixels;
+tSDL_FillRect *SDL_FillRect;
+tSDL_FillRects *SDL_FillRects;
+tSDL_UpperBlit *SDL_UpperBlit;
+tSDL_LowerBlit *SDL_LowerBlit;
+tSDL_SoftStretch *SDL_SoftStretch;
+tSDL_UpperBlitScaled *SDL_UpperBlitScaled;
+tSDL_LowerBlitScaled *SDL_LowerBlitScaled;
+tSDL_PumpEvents *SDL_PumpEvents;
+tSDL_PeepEvents *SDL_PeepEvents;
+tSDL_HasEvent *SDL_HasEvent;
+tSDL_HasEvents *SDL_HasEvents;
+tSDL_FlushEvent *SDL_FlushEvent;
+tSDL_FlushEvents *SDL_FlushEvents;
+tSDL_PollEvent *SDL_PollEvent;
+tSDL_WaitEvent *SDL_WaitEvent;
+tSDL_WaitEventTimeout *SDL_WaitEventTimeout;
+tSDL_PushEvent *SDL_PushEvent;
+tSDL_SetEventFilter *SDL_SetEventFilter;
+tSDL_GetEventFilter *SDL_GetEventFilter;
+tSDL_AddEventWatch *SDL_AddEventWatch;
+tSDL_DelEventWatch *SDL_DelEventWatch;
+tSDL_FilterEvents *SDL_FilterEvents;
+tSDL_EventState *SDL_EventState;
+tSDL_RegisterEvents *SDL_RegisterEvents;
+tSDL_GetMouseFocus *SDL_GetMouseFocus;
+tSDL_GetMouseState *SDL_GetMouseState;
+tSDL_GetRelativeMouseState *SDL_GetRelativeMouseState;
+tSDL_WarpMouseInWindow *SDL_WarpMouseInWindow;
+tSDL_SetRelativeMouseMode *SDL_SetRelativeMouseMode;
+tSDL_GetRelativeMouseMode *SDL_GetRelativeMouseMode;
+tSDL_CreateCursor *SDL_CreateCursor;
+tSDL_CreateColorCursor *SDL_CreateColorCursor;
+tSDL_CreateSystemCursor *SDL_CreateSystemCursor;
+tSDL_SetCursor *SDL_SetCursor;
+tSDL_GetCursor *SDL_GetCursor;
+tSDL_GetDefaultCursor *SDL_GetDefaultCursor;
+tSDL_FreeCursor *SDL_FreeCursor;
+tSDL_ShowCursor *SDL_ShowCursor;
+tSDL_GetThreadName *SDL_GetThreadName;
+tSDL_ThreadID *SDL_ThreadID;
+tSDL_GetThreadID *SDL_GetThreadID;
+tSDL_SetThreadPriority *SDL_SetThreadPriority;
+tSDL_WaitThread *SDL_WaitThread;
+tSDL_TLSCreate *SDL_TLSCreate;
+tSDL_TLSGet *SDL_TLSGet;
+tSDL_TLSSet *SDL_TLSSet;
+tSDL_GetKeyboardFocus *SDL_GetKeyboardFocus;
+tSDL_GetKeyboardState *SDL_GetKeyboardState;
+tSDL_GetModState *SDL_GetModState;
+tSDL_SetModState *SDL_SetModState;
+tSDL_GetKeyFromScancode *SDL_GetKeyFromScancode;
+tSDL_GetScancodeFromKey *SDL_GetScancodeFromKey;
+tSDL_GetScancodeName *SDL_GetScancodeName;
+tSDL_GetScancodeFromName *SDL_GetScancodeFromName;
+tSDL_GetKeyName *SDL_GetKeyName;
+tSDL_GetKeyFromName *SDL_GetKeyFromName;
+tSDL_StartTextInput *SDL_StartTextInput;
+tSDL_IsTextInputActive *SDL_IsTextInputActive;
+tSDL_StopTextInput *SDL_StopTextInput;
+tSDL_SetTextInputRect *SDL_SetTextInputRect;
+tSDL_HasScreenKeyboardSupport *SDL_HasScreenKeyboardSupport;
+tSDL_IsScreenKeyboardShown *SDL_IsScreenKeyboardShown;
+tSDL_GameControllerAddMapping *SDL_GameControllerAddMapping;
+tSDL_GameControllerMappingForGUID *SDL_GameControllerMappingForGUID;
+tSDL_GameControllerMapping *SDL_GameControllerMapping;
+tSDL_IsGameController *SDL_IsGameController;
+tSDL_GameControllerNameForIndex *SDL_GameControllerNameForIndex;
+tSDL_GameControllerOpen *SDL_GameControllerOpen;
+tSDL_GameControllerName *SDL_GameControllerName;
+tSDL_GameControllerGetAttached *SDL_GameControllerGetAttached;
+tSDL_GameControllerGetJoystick *SDL_GameControllerGetJoystick;
+tSDL_GameControllerEventState *SDL_GameControllerEventState;
+tSDL_GameControllerUpdate *SDL_GameControllerUpdate;
+tSDL_GameControllerGetAxisFromString *SDL_GameControllerGetAxisFromString;
+tSDL_GameControllerGetButtonFromString *SDL_GameControllerGetButtonFromString;
+tSDL_GameControllerGetButton *SDL_GameControllerGetButton;
+tSDL_GameControllerClose *SDL_GameControllerClose;
+tSDL_GetNumAudioDrivers *SDL_GetNumAudioDrivers;
+tSDL_GetAudioDriver *SDL_GetAudioDriver;
+tSDL_AudioInit *SDL_AudioInit;
+tSDL_AudioQuit *SDL_AudioQuit;
+tSDL_GetCurrentAudioDriver *SDL_GetCurrentAudioDriver;
+tSDL_OpenAudio *SDL_OpenAudio;
+tSDL_GetNumAudioDevices *SDL_GetNumAudioDevices;
+tSDL_GetAudioDeviceName *SDL_GetAudioDeviceName;
+tSDL_OpenAudioDevice *SDL_OpenAudioDevice;
+tSDL_GetAudioStatus *SDL_GetAudioStatus;
+tSDL_PauseAudio *SDL_PauseAudio;
+tSDL_PauseAudioDevice *SDL_PauseAudioDevice;
+tSDL_LoadWAV_RW *SDL_LoadWAV_RW;
+tSDL_FreeWAV *SDL_FreeWAV;
+tSDL_BuildAudioCVT *SDL_BuildAudioCVT;
+tSDL_ConvertAudio *SDL_ConvertAudio;
+tSDL_MixAudio *SDL_MixAudio;
+tSDL_MixAudioFormat *SDL_MixAudioFormat;
+tSDL_LockAudio *SDL_LockAudio;
+tSDL_LockAudioDevice *SDL_LockAudioDevice;
+tSDL_UnlockAudio *SDL_UnlockAudio;
+tSDL_UnlockAudioDevice *SDL_UnlockAudioDevice;
+tSDL_CloseAudio *SDL_CloseAudio;
+tSDL_CloseAudioDevice *SDL_CloseAudioDevice;
+tSDL_GetNumVideoDrivers *SDL_GetNumVideoDrivers;
+tSDL_GetVideoDriver *SDL_GetVideoDriver;
+tSDL_VideoInit *SDL_VideoInit;
+tSDL_VideoQuit *SDL_VideoQuit;
+tSDL_GetCurrentVideoDriver *SDL_GetCurrentVideoDriver;
+tSDL_GetNumVideoDisplays *SDL_GetNumVideoDisplays;
+tSDL_GetDisplayName *SDL_GetDisplayName;
+tSDL_GetDisplayBounds *SDL_GetDisplayBounds;
+tSDL_GetNumDisplayModes *SDL_GetNumDisplayModes;
+tSDL_GetDisplayMode *SDL_GetDisplayMode;
+tSDL_GetDesktopDisplayMode *SDL_GetDesktopDisplayMode;
+tSDL_GetCurrentDisplayMode *SDL_GetCurrentDisplayMode;
+tSDL_GetClosestDisplayMode *SDL_GetClosestDisplayMode;
+tSDL_GetWindowDisplayIndex *SDL_GetWindowDisplayIndex;
+tSDL_SetWindowDisplayMode *SDL_SetWindowDisplayMode;
+tSDL_GetWindowDisplayMode *SDL_GetWindowDisplayMode;
+tSDL_GetWindowPixelFormat *SDL_GetWindowPixelFormat;
+tSDL_CreateWindow *SDL_CreateWindow;
+tSDL_CreateWindowFrom *SDL_CreateWindowFrom;
+tSDL_GetWindowID *SDL_GetWindowID;
+tSDL_GetWindowFromID *SDL_GetWindowFromID;
+tSDL_GetWindowFlags *SDL_GetWindowFlags;
+tSDL_SetWindowTitle *SDL_SetWindowTitle;
+tSDL_GetWindowTitle *SDL_GetWindowTitle;
+tSDL_SetWindowIcon *SDL_SetWindowIcon;
+tSDL_GetWindowData *SDL_GetWindowData;
+tSDL_SetWindowPosition *SDL_SetWindowPosition;
+tSDL_GetWindowPosition *SDL_GetWindowPosition;
+tSDL_SetWindowSize *SDL_SetWindowSize;
+tSDL_GetWindowSize *SDL_GetWindowSize;
+tSDL_SetWindowMinimumSize *SDL_SetWindowMinimumSize;
+tSDL_GetWindowMinimumSize *SDL_GetWindowMinimumSize;
+tSDL_SetWindowMaximumSize *SDL_SetWindowMaximumSize;
+tSDL_GetWindowMaximumSize *SDL_GetWindowMaximumSize;
+tSDL_SetWindowBordered *SDL_SetWindowBordered;
+tSDL_ShowWindow *SDL_ShowWindow;
+tSDL_HideWindow *SDL_HideWindow;
+tSDL_RaiseWindow *SDL_RaiseWindow;
+tSDL_MaximizeWindow *SDL_MaximizeWindow;
+tSDL_MinimizeWindow *SDL_MinimizeWindow;
+tSDL_RestoreWindow *SDL_RestoreWindow;
+tSDL_SetWindowFullscreen *SDL_SetWindowFullscreen;
+tSDL_GetWindowSurface *SDL_GetWindowSurface;
+tSDL_UpdateWindowSurface *SDL_UpdateWindowSurface;
+tSDL_UpdateWindowSurfaceRects *SDL_UpdateWindowSurfaceRects;
+tSDL_SetWindowGrab *SDL_SetWindowGrab;
+tSDL_GetWindowGrab *SDL_GetWindowGrab;
+tSDL_SetWindowBrightness *SDL_SetWindowBrightness;
+tSDL_GetWindowBrightness *SDL_GetWindowBrightness;
+tSDL_SetWindowGammaRamp *SDL_SetWindowGammaRamp;
+tSDL_GetWindowGammaRamp *SDL_GetWindowGammaRamp;
+tSDL_DestroyWindow *SDL_DestroyWindow;
+tSDL_IsScreenSaverEnabled *SDL_IsScreenSaverEnabled;
+tSDL_EnableScreenSaver *SDL_EnableScreenSaver;
+tSDL_DisableScreenSaver *SDL_DisableScreenSaver;
+tSDL_GL_LoadLibrary *SDL_GL_LoadLibrary;
+tSDL_GL_GetProcAddress *SDL_GL_GetProcAddress;
+tSDL_GL_UnloadLibrary *SDL_GL_UnloadLibrary;
+tSDL_GL_ExtensionSupported *SDL_GL_ExtensionSupported;
+tSDL_GL_SetAttribute *SDL_GL_SetAttribute;
+tSDL_GL_GetAttribute *SDL_GL_GetAttribute;
+tSDL_GL_CreateContext *SDL_GL_CreateContext;
+tSDL_GL_MakeCurrent *SDL_GL_MakeCurrent;
+tSDL_GL_GetCurrentContext *SDL_GL_GetCurrentContext;
+tSDL_GL_SetSwapInterval *SDL_GL_SetSwapInterval;
+tSDL_GL_GetSwapInterval *SDL_GL_GetSwapInterval;
+tSDL_GL_SwapWindow *SDL_GL_SwapWindow;
+tSDL_GL_DeleteContext *SDL_GL_DeleteContext;
+tSDL_RWFromFile *SDL_RWFromFile;
+tSDL_RWFromFP *SDL_RWFromFP;
+tSDL_RWFromFP *SDL_RWFromFP;
+tSDL_RWFromMem *SDL_RWFromMem;
+tSDL_RWFromConstMem *SDL_RWFromConstMem;
+tSDL_AllocRW *SDL_AllocRW;
+tSDL_FreeRW *SDL_FreeRW;
+tSDL_ReadU8 *SDL_ReadU8;
+tSDL_ReadLE16 *SDL_ReadLE16;
+tSDL_ReadBE16 *SDL_ReadBE16;
+tSDL_ReadLE32 *SDL_ReadLE32;
+tSDL_ReadBE32 *SDL_ReadBE32;
+tSDL_ReadLE64 *SDL_ReadLE64;
+tSDL_ReadBE64 *SDL_ReadBE64;
+tSDL_WriteU8 *SDL_WriteU8;
+tSDL_WriteLE16 *SDL_WriteLE16;
+tSDL_WriteBE16 *SDL_WriteBE16;
+tSDL_WriteLE32 *SDL_WriteLE32;
+tSDL_WriteBE32 *SDL_WriteBE32;
+tSDL_WriteLE64 *SDL_WriteLE64;
+tSDL_WriteBE64 *SDL_WriteBE64;
+tSDL_Init *SDL_Init;
+tSDL_InitSubSystem *SDL_InitSubSystem;
+tSDL_QuitSubSystem *SDL_QuitSubSystem;
+tSDL_WasInit *SDL_WasInit;
+tSDL_Quit *SDL_Quit;
+tSDL_GetVersion *SDL_GetVersion;
+tSDL_GetRevision *SDL_GetRevision;
+tSDL_GetRevisionNumber *SDL_GetRevisionNumber;
+tSDL_GetTicks *SDL_GetTicks;
+tSDL_GetPerformanceCounter *SDL_GetPerformanceCounter;
+tSDL_GetPerformanceFrequency *SDL_GetPerformanceFrequency;
+tSDL_Delay *SDL_Delay;
+tSDL_AddTimer *SDL_AddTimer;
+tSDL_RemoveTimer *SDL_RemoveTimer;
+tSDL_SetHintWithPriority *SDL_SetHintWithPriority;
+tSDL_SetHint *SDL_SetHint;
+tSDL_GetHint *SDL_GetHint;
+tSDL_AddHintCallback *SDL_AddHintCallback;
+tSDL_DelHintCallback *SDL_DelHintCallback;
+tSDL_ClearHints *SDL_ClearHints;
+tSDL_NumJoysticks *SDL_NumJoysticks;
+tSDL_JoystickNameForIndex *SDL_JoystickNameForIndex;
+tSDL_JoystickOpen *SDL_JoystickOpen;
+tSDL_JoystickName *SDL_JoystickName;
+tSDL_JoystickGetDeviceGUID *SDL_JoystickGetDeviceGUID;
+tSDL_JoystickGetGUID *SDL_JoystickGetGUID;
+tSDL_JoystickGetGUIDFromString *SDL_JoystickGetGUIDFromString;
+tSDL_JoystickGetAttached *SDL_JoystickGetAttached;
+tSDL_JoystickInstanceID *SDL_JoystickInstanceID;
+tSDL_JoystickNumAxes *SDL_JoystickNumAxes;
+tSDL_JoystickNumBalls *SDL_JoystickNumBalls;
+tSDL_JoystickNumHats *SDL_JoystickNumHats;
+tSDL_JoystickNumButtons *SDL_JoystickNumButtons;
+tSDL_JoystickUpdate *SDL_JoystickUpdate;
+tSDL_JoystickEventState *SDL_JoystickEventState;
+tSDL_JoystickGetAxis *SDL_JoystickGetAxis;
+tSDL_JoystickGetHat *SDL_JoystickGetHat;
+tSDL_JoystickGetBall *SDL_JoystickGetBall;
+tSDL_JoystickGetButton *SDL_JoystickGetButton;
+tSDL_JoystickClose *SDL_JoystickClose;
+tSDL_RecordGesture *SDL_RecordGesture;
+tSDL_SaveAllDollarTemplates *SDL_SaveAllDollarTemplates;
+tSDL_SaveDollarTemplate *SDL_SaveDollarTemplate;
+tSDL_LoadDollarTemplates *SDL_LoadDollarTemplates;
+tSDL_NumHaptics *SDL_NumHaptics;
+tSDL_HapticName *SDL_HapticName;
+tSDL_HapticOpen *SDL_HapticOpen;
+tSDL_HapticOpened *SDL_HapticOpened;
+tSDL_HapticIndex *SDL_HapticIndex;
+tSDL_MouseIsHaptic *SDL_MouseIsHaptic;
+tSDL_HapticOpenFromMouse *SDL_HapticOpenFromMouse;
+tSDL_JoystickIsHaptic *SDL_JoystickIsHaptic;
+tSDL_HapticOpenFromJoystick *SDL_HapticOpenFromJoystick;
+tSDL_HapticClose *SDL_HapticClose;
+tSDL_HapticNumEffects *SDL_HapticNumEffects;
+tSDL_HapticNumEffectsPlaying *SDL_HapticNumEffectsPlaying;
+tSDL_HapticNumAxes *SDL_HapticNumAxes;
+tSDL_HapticEffectSupported *SDL_HapticEffectSupported;
+tSDL_HapticNewEffect *SDL_HapticNewEffect;
+tSDL_HapticUpdateEffect *SDL_HapticUpdateEffect;
+tSDL_HapticRunEffect *SDL_HapticRunEffect;
+tSDL_HapticStopEffect *SDL_HapticStopEffect;
+tSDL_HapticDestroyEffect *SDL_HapticDestroyEffect;
+tSDL_HapticGetEffectStatus *SDL_HapticGetEffectStatus;
+tSDL_HapticSetGain *SDL_HapticSetGain;
+tSDL_HapticSetAutocenter *SDL_HapticSetAutocenter;
+tSDL_HapticPause *SDL_HapticPause;
+tSDL_HapticUnpause *SDL_HapticUnpause;
+tSDL_HapticStopAll *SDL_HapticStopAll;
+tSDL_HapticRumbleSupported *SDL_HapticRumbleSupported;
+tSDL_HapticRumbleInit *SDL_HapticRumbleInit;
+tSDL_HapticRumblePlay *SDL_HapticRumblePlay;
+tSDL_HapticRumbleStop *SDL_HapticRumbleStop;
+tSDL_ShowMessageBox *SDL_ShowMessageBox;
+tSDL_ShowSimpleMessageBox *SDL_ShowSimpleMessageBox;
+tSDL_PixelFormatEnumToMasks *SDL_PixelFormatEnumToMasks;
+tSDL_MasksToPixelFormatEnum *SDL_MasksToPixelFormatEnum;
+tSDL_AllocFormat *SDL_AllocFormat;
+tSDL_FreeFormat *SDL_FreeFormat;
+tSDL_AllocPalette *SDL_AllocPalette;
+tSDL_SetPixelFormatPalette *SDL_SetPixelFormatPalette;
+tSDL_SetPaletteColors *SDL_SetPaletteColors;
+tSDL_FreePalette *SDL_FreePalette;
+tSDL_MapRGB *SDL_MapRGB;
+tSDL_MapRGBA *SDL_MapRGBA;
+tSDL_GetRGB *SDL_GetRGB;
+tSDL_GetRGBA *SDL_GetRGBA;
+tSDL_CalculateGammaRamp *SDL_CalculateGammaRamp;
+tSDL_GetPowerInfo *SDL_GetPowerInfo;
+tSDL_GetCPUCount *SDL_GetCPUCount;
+tSDL_GetCPUCacheLineSize *SDL_GetCPUCacheLineSize;
+tSDL_HasRDTSC *SDL_HasRDTSC;
+tSDL_HasAltiVec *SDL_HasAltiVec;
+tSDL_HasMMX *SDL_HasMMX;
+tSDL_Has3DNow *SDL_Has3DNow;
+tSDL_HasSSE *SDL_HasSSE;
+tSDL_HasSSE2 *SDL_HasSSE2;
+tSDL_HasSSE3 *SDL_HasSSE3;
+tSDL_HasSSE41 *SDL_HasSSE41;
+tSDL_HasSSE42 *SDL_HasSSE42;
+tSDL_GetNumTouchDevices *SDL_GetNumTouchDevices;
+tSDL_GetTouchDevice *SDL_GetTouchDevice;
+tSDL_GetNumTouchFingers *SDL_GetNumTouchFingers;
+tSDL_GetTouchFinger *SDL_GetTouchFinger;
+tSDL_SetError *SDL_SetError;
+tSDL_GetError *SDL_GetError;
+tSDL_ClearError *SDL_ClearError;
+tSDL_Error *SDL_Error;
+tSDL_SetClipboardText *SDL_SetClipboardText;
+tSDL_GetClipboardText *SDL_GetClipboardText;
+tSDL_HasClipboardText *SDL_HasClipboardText;
+tSDL_GetWindowWMInfo *SDL_GetWindowWMInfo;
+
+static void sdlewExit(void) {
+ if(lib != NULL) {
+ /* Ignore errors. */
+ dynamic_library_close(lib);
+ lib = NULL;
+ }
+}
+
+/* Implementation function. */
+int sdlewInit(void) {
+ /* Library paths. */
+#ifdef _WIN32
+ /* Expected in c:/windows/system or similar, no path needed. */
+ const char *paths[] = {"SDL2.dll", NULL};
+#elif defined(__APPLE__)
+ /* Default installation path. */
+ const char *paths[] = {"/usr/local/cuda/lib/libSDL2.dylib", NULL};
+#else
+ const char *paths[] = {"libSDL2.so",
+ "libSDL2-2.0.so.0",
+ "libSDL.so",
+ NULL};
+#endif
+ static int initialized = 0;
+ static int result = 0;
+ int a, error;
+ SDL_version version;
+
+ if (initialized) {
+ return result;
+ }
+
+ initialized = 1;
+
+ error = atexit(sdlewExit);
+ if (error) {
+ result = SDLEW_ERROR_ATEXIT_FAILED;
+ return result;
+ }
+
+ /* Load library. */
+ for (a = 0; paths[a] != NULL && lib == NULL; ++a) {
+ lib = dynamic_library_open(paths[a]);
+ }
+
+ if (lib == NULL) {
+ result = SDLEW_ERROR_OPEN_FAILED;
+ return result;
+ }
+
+ SDL_LIBRARY_FIND(SDL_GetPlatform);
+ SDL_LIBRARY_FIND(SDL_memcpy);
+#ifndef HAVE_ALLOCA
+ SDL_LIBRARY_FIND(SDL_malloc);
+#endif
+ SDL_LIBRARY_FIND(SDL_calloc);
+ SDL_LIBRARY_FIND(SDL_realloc);
+ SDL_LIBRARY_FIND(SDL_free);
+ SDL_LIBRARY_FIND(SDL_getenv);
+ SDL_LIBRARY_FIND(SDL_setenv);
+ SDL_LIBRARY_FIND(SDL_qsort);
+ SDL_LIBRARY_FIND(SDL_abs);
+ SDL_LIBRARY_FIND(SDL_isdigit);
+ SDL_LIBRARY_FIND(SDL_isspace);
+ SDL_LIBRARY_FIND(SDL_toupper);
+ SDL_LIBRARY_FIND(SDL_tolower);
+ SDL_LIBRARY_FIND(SDL_memset);
+ SDL_LIBRARY_FIND(SDL_memmove);
+ SDL_LIBRARY_FIND(SDL_memcmp);
+ SDL_LIBRARY_FIND(SDL_wcslen);
+ SDL_LIBRARY_FIND(SDL_wcslcpy);
+ SDL_LIBRARY_FIND(SDL_wcslcat);
+ SDL_LIBRARY_FIND(SDL_strlen);
+ SDL_LIBRARY_FIND(SDL_strlcpy);
+ SDL_LIBRARY_FIND(SDL_utf8strlcpy);
+ SDL_LIBRARY_FIND(SDL_strlcat);
+ SDL_LIBRARY_FIND(SDL_strdup);
+ SDL_LIBRARY_FIND(SDL_strrev);
+ SDL_LIBRARY_FIND(SDL_strupr);
+ SDL_LIBRARY_FIND(SDL_strlwr);
+ SDL_LIBRARY_FIND(SDL_strchr);
+ SDL_LIBRARY_FIND(SDL_strrchr);
+ SDL_LIBRARY_FIND(SDL_strstr);
+ SDL_LIBRARY_FIND(SDL_itoa);
+ SDL_LIBRARY_FIND(SDL_uitoa);
+ SDL_LIBRARY_FIND(SDL_ltoa);
+ SDL_LIBRARY_FIND(SDL_ultoa);
+ SDL_LIBRARY_FIND(SDL_lltoa);
+ SDL_LIBRARY_FIND(SDL_ulltoa);
+ SDL_LIBRARY_FIND(SDL_atoi);
+ SDL_LIBRARY_FIND(SDL_atof);
+ SDL_LIBRARY_FIND(SDL_strtol);
+ SDL_LIBRARY_FIND(SDL_strtoll);
+ SDL_LIBRARY_FIND(SDL_strtoull);
+ SDL_LIBRARY_FIND(SDL_strtod);
+ SDL_LIBRARY_FIND(SDL_strcmp);
+ SDL_LIBRARY_FIND(SDL_strncmp);
+ SDL_LIBRARY_FIND(SDL_strcasecmp);
+ SDL_LIBRARY_FIND(SDL_strncasecmp);
+ SDL_LIBRARY_FIND(SDL_sscanf);
+ SDL_LIBRARY_FIND(SDL_snprintf);
+ SDL_LIBRARY_FIND(SDL_vsnprintf);
+ SDL_LIBRARY_FIND(SDL_atan);
+ SDL_LIBRARY_FIND(SDL_atan2);
+ SDL_LIBRARY_FIND(SDL_ceil);
+ SDL_LIBRARY_FIND(SDL_copysign);
+ SDL_LIBRARY_FIND(SDL_cos);
+ SDL_LIBRARY_FIND(SDL_cosf);
+ SDL_LIBRARY_FIND(SDL_fabs);
+ SDL_LIBRARY_FIND(SDL_floor);
+ SDL_LIBRARY_FIND(SDL_log);
+ SDL_LIBRARY_FIND(SDL_pow);
+ SDL_LIBRARY_FIND(SDL_scalbn);
+ SDL_LIBRARY_FIND(SDL_sin);
+ SDL_LIBRARY_FIND(SDL_sinf);
+ SDL_LIBRARY_FIND(SDL_sqrt);
+ SDL_LIBRARY_FIND(SDL_iconv_open);
+ SDL_LIBRARY_FIND(SDL_iconv_close);
+ SDL_LIBRARY_FIND(SDL_iconv);
+ SDL_LIBRARY_FIND(SDL_iconv_string);
+ SDL_LIBRARY_FIND(SDL_GetNumRenderDrivers);
+ SDL_LIBRARY_FIND(SDL_GetRenderDriverInfo);
+ SDL_LIBRARY_FIND(SDL_CreateWindowAndRenderer);
+ SDL_LIBRARY_FIND(SDL_CreateRenderer);
+ SDL_LIBRARY_FIND(SDL_CreateSoftwareRenderer);
+ SDL_LIBRARY_FIND(SDL_GetRenderer);
+ SDL_LIBRARY_FIND(SDL_GetRendererInfo);
+ SDL_LIBRARY_FIND(SDL_GetRendererOutputSize);
+ SDL_LIBRARY_FIND(SDL_CreateTexture);
+ SDL_LIBRARY_FIND(SDL_CreateTextureFromSurface);
+ SDL_LIBRARY_FIND(SDL_QueryTexture);
+ SDL_LIBRARY_FIND(SDL_SetTextureColorMod);
+ SDL_LIBRARY_FIND(SDL_GetTextureColorMod);
+ SDL_LIBRARY_FIND(SDL_SetTextureAlphaMod);
+ SDL_LIBRARY_FIND(SDL_GetTextureAlphaMod);
+ SDL_LIBRARY_FIND(SDL_SetTextureBlendMode);
+ SDL_LIBRARY_FIND(SDL_GetTextureBlendMode);
+ SDL_LIBRARY_FIND(SDL_UpdateTexture);
+ SDL_LIBRARY_FIND(SDL_LockTexture);
+ SDL_LIBRARY_FIND(SDL_UnlockTexture);
+ SDL_LIBRARY_FIND(SDL_RenderTargetSupported);
+ SDL_LIBRARY_FIND(SDL_SetRenderTarget);
+ SDL_LIBRARY_FIND(SDL_GetRenderTarget);
+ SDL_LIBRARY_FIND(SDL_RenderSetLogicalSize);
+ SDL_LIBRARY_FIND(SDL_RenderGetLogicalSize);
+ SDL_LIBRARY_FIND(SDL_RenderSetViewport);
+ SDL_LIBRARY_FIND(SDL_RenderGetViewport);
+ SDL_LIBRARY_FIND(SDL_RenderSetClipRect);
+ SDL_LIBRARY_FIND(SDL_RenderGetClipRect);
+ SDL_LIBRARY_FIND(SDL_RenderSetScale);
+ SDL_LIBRARY_FIND(SDL_RenderGetScale);
+ SDL_LIBRARY_FIND(SDL_SetRenderDrawBlendMode);
+ SDL_LIBRARY_FIND(SDL_GetRenderDrawBlendMode);
+ SDL_LIBRARY_FIND(SDL_RenderClear);
+ SDL_LIBRARY_FIND(SDL_RenderDrawPoint);
+ SDL_LIBRARY_FIND(SDL_RenderDrawPoints);
+ SDL_LIBRARY_FIND(SDL_RenderDrawLine);
+ SDL_LIBRARY_FIND(SDL_RenderDrawLines);
+ SDL_LIBRARY_FIND(SDL_RenderDrawRect);
+ SDL_LIBRARY_FIND(SDL_RenderDrawRects);
+ SDL_LIBRARY_FIND(SDL_RenderFillRect);
+ SDL_LIBRARY_FIND(SDL_RenderFillRects);
+ SDL_LIBRARY_FIND(SDL_RenderCopy);
+ SDL_LIBRARY_FIND(SDL_RenderCopyEx);
+ SDL_LIBRARY_FIND(SDL_RenderReadPixels);
+ SDL_LIBRARY_FIND(SDL_RenderPresent);
+ SDL_LIBRARY_FIND(SDL_DestroyTexture);
+ SDL_LIBRARY_FIND(SDL_DestroyRenderer);
+ SDL_LIBRARY_FIND(SDL_GL_BindTexture);
+ SDL_LIBRARY_FIND(SDL_GL_UnbindTexture);
+ SDL_LIBRARY_FIND(SDL_LoadObject);
+ SDL_LIBRARY_FIND(SDL_LoadFunction);
+ SDL_LIBRARY_FIND(SDL_UnloadObject);
+ SDL_LIBRARY_FIND(SDL_ReportAssertion);
+ SDL_LIBRARY_FIND(SDL_SetAssertionHandler);
+ SDL_LIBRARY_FIND(SDL_GetAssertionReport);
+ SDL_LIBRARY_FIND(SDL_ResetAssertionReport);
+ SDL_LIBRARY_FIND(SDL_AtomicTryLock);
+ SDL_LIBRARY_FIND(SDL_AtomicLock);
+ SDL_LIBRARY_FIND(SDL_AtomicUnlock);
+ SDL_LIBRARY_FIND(SDL_HasIntersection);
+ SDL_LIBRARY_FIND(SDL_IntersectRect);
+ SDL_LIBRARY_FIND(SDL_UnionRect);
+ SDL_LIBRARY_FIND(SDL_EnclosePoints);
+ SDL_LIBRARY_FIND(SDL_IntersectRectAndLine);
+ SDL_LIBRARY_FIND(SDL_LogSetAllPriority);
+ SDL_LIBRARY_FIND(SDL_LogSetPriority);
+ SDL_LIBRARY_FIND(SDL_LogGetPriority);
+ SDL_LIBRARY_FIND(SDL_LogResetPriorities);
+ SDL_LIBRARY_FIND(SDL_Log);
+ SDL_LIBRARY_FIND(SDL_LogVerbose);
+ SDL_LIBRARY_FIND(SDL_LogDebug);
+ SDL_LIBRARY_FIND(SDL_LogInfo);
+ SDL_LIBRARY_FIND(SDL_LogWarn);
+ SDL_LIBRARY_FIND(SDL_LogError);
+ SDL_LIBRARY_FIND(SDL_LogCritical);
+ SDL_LIBRARY_FIND(SDL_LogMessage);
+ SDL_LIBRARY_FIND(SDL_LogMessageV);
+ SDL_LIBRARY_FIND(SDL_LogGetOutputFunction);
+ SDL_LIBRARY_FIND(SDL_LogSetOutputFunction);
+ SDL_LIBRARY_FIND(SDL_CreateMutex);
+ SDL_LIBRARY_FIND(SDL_LockMutex);
+ SDL_LIBRARY_FIND(SDL_TryLockMutex);
+ SDL_LIBRARY_FIND(SDL_UnlockMutex);
+ SDL_LIBRARY_FIND(SDL_DestroyMutex);
+ SDL_LIBRARY_FIND(SDL_CreateSemaphore);
+ SDL_LIBRARY_FIND(SDL_DestroySemaphore);
+ SDL_LIBRARY_FIND(SDL_SemWait);
+ SDL_LIBRARY_FIND(SDL_SemTryWait);
+ SDL_LIBRARY_FIND(SDL_SemWaitTimeout);
+ SDL_LIBRARY_FIND(SDL_SemPost);
+ SDL_LIBRARY_FIND(SDL_SemValue);
+ SDL_LIBRARY_FIND(SDL_CreateCond);
+ SDL_LIBRARY_FIND(SDL_DestroyCond);
+ SDL_LIBRARY_FIND(SDL_CondSignal);
+ SDL_LIBRARY_FIND(SDL_CondBroadcast);
+ SDL_LIBRARY_FIND(SDL_CondWait);
+ SDL_LIBRARY_FIND(SDL_CondWaitTimeout);
+ SDL_LIBRARY_FIND(SDL_CreateRGBSurface);
+ SDL_LIBRARY_FIND(SDL_CreateRGBSurfaceFrom);
+ SDL_LIBRARY_FIND(SDL_FreeSurface);
+ SDL_LIBRARY_FIND(SDL_SetSurfacePalette);
+ SDL_LIBRARY_FIND(SDL_LockSurface);
+ SDL_LIBRARY_FIND(SDL_UnlockSurface);
+ SDL_LIBRARY_FIND(SDL_LoadBMP_RW);
+ SDL_LIBRARY_FIND(SDL_SaveBMP_RW);
+ SDL_LIBRARY_FIND(SDL_SetSurfaceRLE);
+ SDL_LIBRARY_FIND(SDL_SetColorKey);
+ SDL_LIBRARY_FIND(SDL_GetColorKey);
+ SDL_LIBRARY_FIND(SDL_SetSurfaceColorMod);
+ SDL_LIBRARY_FIND(SDL_GetSurfaceColorMod);
+ SDL_LIBRARY_FIND(SDL_SetSurfaceAlphaMod);
+ SDL_LIBRARY_FIND(SDL_GetSurfaceAlphaMod);
+ SDL_LIBRARY_FIND(SDL_SetSurfaceBlendMode);
+ SDL_LIBRARY_FIND(SDL_GetSurfaceBlendMode);
+ SDL_LIBRARY_FIND(SDL_SetClipRect);
+ SDL_LIBRARY_FIND(SDL_GetClipRect);
+ SDL_LIBRARY_FIND(SDL_ConvertSurface);
+ SDL_LIBRARY_FIND(SDL_ConvertSurfaceFormat);
+ SDL_LIBRARY_FIND(SDL_ConvertPixels);
+ SDL_LIBRARY_FIND(SDL_FillRect);
+ SDL_LIBRARY_FIND(SDL_FillRects);
+ SDL_LIBRARY_FIND(SDL_UpperBlit);
+ SDL_LIBRARY_FIND(SDL_LowerBlit);
+ SDL_LIBRARY_FIND(SDL_SoftStretch);
+ SDL_LIBRARY_FIND(SDL_UpperBlitScaled);
+ SDL_LIBRARY_FIND(SDL_LowerBlitScaled);
+ SDL_LIBRARY_FIND(SDL_PumpEvents);
+ SDL_LIBRARY_FIND(SDL_PeepEvents);
+ SDL_LIBRARY_FIND(SDL_HasEvent);
+ SDL_LIBRARY_FIND(SDL_HasEvents);
+ SDL_LIBRARY_FIND(SDL_FlushEvent);
+ SDL_LIBRARY_FIND(SDL_FlushEvents);
+ SDL_LIBRARY_FIND(SDL_PollEvent);
+ SDL_LIBRARY_FIND(SDL_WaitEvent);
+ SDL_LIBRARY_FIND(SDL_WaitEventTimeout);
+ SDL_LIBRARY_FIND(SDL_PushEvent);
+ SDL_LIBRARY_FIND(SDL_SetEventFilter);
+ SDL_LIBRARY_FIND(SDL_GetEventFilter);
+ SDL_LIBRARY_FIND(SDL_AddEventWatch);
+ SDL_LIBRARY_FIND(SDL_DelEventWatch);
+ SDL_LIBRARY_FIND(SDL_FilterEvents);
+ SDL_LIBRARY_FIND(SDL_EventState);
+ SDL_LIBRARY_FIND(SDL_RegisterEvents);
+ SDL_LIBRARY_FIND(SDL_GetMouseFocus);
+ SDL_LIBRARY_FIND(SDL_GetMouseState);
+ SDL_LIBRARY_FIND(SDL_GetRelativeMouseState);
+ SDL_LIBRARY_FIND(SDL_WarpMouseInWindow);
+ SDL_LIBRARY_FIND(SDL_SetRelativeMouseMode);
+ SDL_LIBRARY_FIND(SDL_GetRelativeMouseMode);
+ SDL_LIBRARY_FIND(SDL_CreateCursor);
+ SDL_LIBRARY_FIND(SDL_CreateColorCursor);
+ SDL_LIBRARY_FIND(SDL_CreateSystemCursor);
+ SDL_LIBRARY_FIND(SDL_SetCursor);
+ SDL_LIBRARY_FIND(SDL_GetCursor);
+ SDL_LIBRARY_FIND(SDL_GetDefaultCursor);
+ SDL_LIBRARY_FIND(SDL_FreeCursor);
+ SDL_LIBRARY_FIND(SDL_ShowCursor);
+ SDL_LIBRARY_FIND(SDL_GetThreadName);
+ SDL_LIBRARY_FIND(SDL_ThreadID);
+ SDL_LIBRARY_FIND(SDL_GetThreadID);
+ SDL_LIBRARY_FIND(SDL_SetThreadPriority);
+ SDL_LIBRARY_FIND(SDL_WaitThread);
+ SDL_LIBRARY_FIND(SDL_TLSCreate);
+ SDL_LIBRARY_FIND(SDL_TLSGet);
+ SDL_LIBRARY_FIND(SDL_TLSSet);
+ SDL_LIBRARY_FIND(SDL_GetKeyboardFocus);
+ SDL_LIBRARY_FIND(SDL_GetKeyboardState);
+ SDL_LIBRARY_FIND(SDL_GetModState);
+ SDL_LIBRARY_FIND(SDL_SetModState);
+ SDL_LIBRARY_FIND(SDL_GetKeyFromScancode);
+ SDL_LIBRARY_FIND(SDL_GetScancodeFromKey);
+ SDL_LIBRARY_FIND(SDL_GetScancodeName);
+ SDL_LIBRARY_FIND(SDL_GetScancodeFromName);
+ SDL_LIBRARY_FIND(SDL_GetKeyName);
+ SDL_LIBRARY_FIND(SDL_GetKeyFromName);
+ SDL_LIBRARY_FIND(SDL_StartTextInput);
+ SDL_LIBRARY_FIND(SDL_IsTextInputActive);
+ SDL_LIBRARY_FIND(SDL_StopTextInput);
+ SDL_LIBRARY_FIND(SDL_SetTextInputRect);
+ SDL_LIBRARY_FIND(SDL_HasScreenKeyboardSupport);
+ SDL_LIBRARY_FIND(SDL_IsScreenKeyboardShown);
+ SDL_LIBRARY_FIND(SDL_GameControllerAddMapping);
+ SDL_LIBRARY_FIND(SDL_GameControllerMappingForGUID);
+ SDL_LIBRARY_FIND(SDL_GameControllerMapping);
+ SDL_LIBRARY_FIND(SDL_IsGameController);
+ SDL_LIBRARY_FIND(SDL_GameControllerNameForIndex);
+ SDL_LIBRARY_FIND(SDL_GameControllerOpen);
+ SDL_LIBRARY_FIND(SDL_GameControllerName);
+ SDL_LIBRARY_FIND(SDL_GameControllerGetAttached);
+ SDL_LIBRARY_FIND(SDL_GameControllerGetJoystick);
+ SDL_LIBRARY_FIND(SDL_GameControllerEventState);
+ SDL_LIBRARY_FIND(SDL_GameControllerUpdate);
+ SDL_LIBRARY_FIND(SDL_GameControllerGetAxisFromString);
+ SDL_LIBRARY_FIND(SDL_GameControllerGetButtonFromString);
+ SDL_LIBRARY_FIND(SDL_GameControllerGetButton);
+ SDL_LIBRARY_FIND(SDL_GameControllerClose);
+ SDL_LIBRARY_FIND(SDL_GetNumAudioDrivers);
+ SDL_LIBRARY_FIND(SDL_GetAudioDriver);
+ SDL_LIBRARY_FIND(SDL_AudioInit);
+ SDL_LIBRARY_FIND(SDL_AudioQuit);
+ SDL_LIBRARY_FIND(SDL_GetCurrentAudioDriver);
+ SDL_LIBRARY_FIND(SDL_OpenAudio);
+ SDL_LIBRARY_FIND(SDL_GetNumAudioDevices);
+ SDL_LIBRARY_FIND(SDL_GetAudioDeviceName);
+ SDL_LIBRARY_FIND(SDL_OpenAudioDevice);
+ SDL_LIBRARY_FIND(SDL_GetAudioStatus);
+ SDL_LIBRARY_FIND(SDL_PauseAudio);
+ SDL_LIBRARY_FIND(SDL_PauseAudioDevice);
+ SDL_LIBRARY_FIND(SDL_LoadWAV_RW);
+ SDL_LIBRARY_FIND(SDL_FreeWAV);
+ SDL_LIBRARY_FIND(SDL_BuildAudioCVT);
+ SDL_LIBRARY_FIND(SDL_ConvertAudio);
+ SDL_LIBRARY_FIND(SDL_MixAudio);
+ SDL_LIBRARY_FIND(SDL_MixAudioFormat);
+ SDL_LIBRARY_FIND(SDL_LockAudio);
+ SDL_LIBRARY_FIND(SDL_LockAudioDevice);
+ SDL_LIBRARY_FIND(SDL_UnlockAudio);
+ SDL_LIBRARY_FIND(SDL_UnlockAudioDevice);
+ SDL_LIBRARY_FIND(SDL_CloseAudio);
+ SDL_LIBRARY_FIND(SDL_CloseAudioDevice);
+ SDL_LIBRARY_FIND(SDL_GetNumVideoDrivers);
+ SDL_LIBRARY_FIND(SDL_GetVideoDriver);
+ SDL_LIBRARY_FIND(SDL_VideoInit);
+ SDL_LIBRARY_FIND(SDL_VideoQuit);
+ SDL_LIBRARY_FIND(SDL_GetCurrentVideoDriver);
+ SDL_LIBRARY_FIND(SDL_GetNumVideoDisplays);
+ SDL_LIBRARY_FIND(SDL_GetDisplayName);
+ SDL_LIBRARY_FIND(SDL_GetDisplayBounds);
+ SDL_LIBRARY_FIND(SDL_GetNumDisplayModes);
+ SDL_LIBRARY_FIND(SDL_GetDisplayMode);
+ SDL_LIBRARY_FIND(SDL_GetDesktopDisplayMode);
+ SDL_LIBRARY_FIND(SDL_GetCurrentDisplayMode);
+ SDL_LIBRARY_FIND(SDL_GetClosestDisplayMode);
+ SDL_LIBRARY_FIND(SDL_GetWindowDisplayIndex);
+ SDL_LIBRARY_FIND(SDL_SetWindowDisplayMode);
+ SDL_LIBRARY_FIND(SDL_GetWindowDisplayMode);
+ SDL_LIBRARY_FIND(SDL_GetWindowPixelFormat);
+ SDL_LIBRARY_FIND(SDL_CreateWindow);
+ SDL_LIBRARY_FIND(SDL_CreateWindowFrom);
+ SDL_LIBRARY_FIND(SDL_GetWindowID);
+ SDL_LIBRARY_FIND(SDL_GetWindowFromID);
+ SDL_LIBRARY_FIND(SDL_GetWindowFlags);
+ SDL_LIBRARY_FIND(SDL_SetWindowTitle);
+ SDL_LIBRARY_FIND(SDL_GetWindowTitle);
+ SDL_LIBRARY_FIND(SDL_SetWindowIcon);
+ SDL_LIBRARY_FIND(SDL_GetWindowData);
+ SDL_LIBRARY_FIND(SDL_SetWindowPosition);
+ SDL_LIBRARY_FIND(SDL_GetWindowPosition);
+ SDL_LIBRARY_FIND(SDL_SetWindowSize);
+ SDL_LIBRARY_FIND(SDL_GetWindowSize);
+ SDL_LIBRARY_FIND(SDL_SetWindowMinimumSize);
+ SDL_LIBRARY_FIND(SDL_GetWindowMinimumSize);
+ SDL_LIBRARY_FIND(SDL_SetWindowMaximumSize);
+ SDL_LIBRARY_FIND(SDL_GetWindowMaximumSize);
+ SDL_LIBRARY_FIND(SDL_SetWindowBordered);
+ SDL_LIBRARY_FIND(SDL_ShowWindow);
+ SDL_LIBRARY_FIND(SDL_HideWindow);
+ SDL_LIBRARY_FIND(SDL_RaiseWindow);
+ SDL_LIBRARY_FIND(SDL_MaximizeWindow);
+ SDL_LIBRARY_FIND(SDL_MinimizeWindow);
+ SDL_LIBRARY_FIND(SDL_RestoreWindow);
+ SDL_LIBRARY_FIND(SDL_SetWindowFullscreen);
+ SDL_LIBRARY_FIND(SDL_GetWindowSurface);
+ SDL_LIBRARY_FIND(SDL_UpdateWindowSurface);
+ SDL_LIBRARY_FIND(SDL_UpdateWindowSurfaceRects);
+ SDL_LIBRARY_FIND(SDL_SetWindowGrab);
+ SDL_LIBRARY_FIND(SDL_GetWindowGrab);
+ SDL_LIBRARY_FIND(SDL_SetWindowBrightness);
+ SDL_LIBRARY_FIND(SDL_GetWindowBrightness);
+ SDL_LIBRARY_FIND(SDL_SetWindowGammaRamp);
+ SDL_LIBRARY_FIND(SDL_GetWindowGammaRamp);
+ SDL_LIBRARY_FIND(SDL_DestroyWindow);
+ SDL_LIBRARY_FIND(SDL_IsScreenSaverEnabled);
+ SDL_LIBRARY_FIND(SDL_EnableScreenSaver);
+ SDL_LIBRARY_FIND(SDL_DisableScreenSaver);
+ SDL_LIBRARY_FIND(SDL_GL_LoadLibrary);
+ SDL_LIBRARY_FIND(SDL_GL_GetProcAddress);
+ SDL_LIBRARY_FIND(SDL_GL_UnloadLibrary);
+ SDL_LIBRARY_FIND(SDL_GL_ExtensionSupported);
+ SDL_LIBRARY_FIND(SDL_GL_SetAttribute);
+ SDL_LIBRARY_FIND(SDL_GL_GetAttribute);
+ SDL_LIBRARY_FIND(SDL_GL_CreateContext);
+ SDL_LIBRARY_FIND(SDL_GL_MakeCurrent);
+ SDL_LIBRARY_FIND(SDL_GL_GetCurrentContext);
+ SDL_LIBRARY_FIND(SDL_GL_SetSwapInterval);
+ SDL_LIBRARY_FIND(SDL_GL_GetSwapInterval);
+ SDL_LIBRARY_FIND(SDL_GL_SwapWindow);
+ SDL_LIBRARY_FIND(SDL_GL_DeleteContext);
+ SDL_LIBRARY_FIND(SDL_RWFromFile);
+ SDL_LIBRARY_FIND(SDL_RWFromFP);
+ SDL_LIBRARY_FIND(SDL_RWFromFP);
+ SDL_LIBRARY_FIND(SDL_RWFromMem);
+ SDL_LIBRARY_FIND(SDL_RWFromConstMem);
+ SDL_LIBRARY_FIND(SDL_AllocRW);
+ SDL_LIBRARY_FIND(SDL_FreeRW);
+ SDL_LIBRARY_FIND(SDL_ReadU8);
+ SDL_LIBRARY_FIND(SDL_ReadLE16);
+ SDL_LIBRARY_FIND(SDL_ReadBE16);
+ SDL_LIBRARY_FIND(SDL_ReadLE32);
+ SDL_LIBRARY_FIND(SDL_ReadBE32);
+ SDL_LIBRARY_FIND(SDL_ReadLE64);
+ SDL_LIBRARY_FIND(SDL_ReadBE64);
+ SDL_LIBRARY_FIND(SDL_WriteU8);
+ SDL_LIBRARY_FIND(SDL_WriteLE16);
+ SDL_LIBRARY_FIND(SDL_WriteBE16);
+ SDL_LIBRARY_FIND(SDL_WriteLE32);
+ SDL_LIBRARY_FIND(SDL_WriteBE32);
+ SDL_LIBRARY_FIND(SDL_WriteLE64);
+ SDL_LIBRARY_FIND(SDL_WriteBE64);
+ SDL_LIBRARY_FIND(SDL_Init);
+ SDL_LIBRARY_FIND(SDL_InitSubSystem);
+ SDL_LIBRARY_FIND(SDL_QuitSubSystem);
+ SDL_LIBRARY_FIND(SDL_WasInit);
+ SDL_LIBRARY_FIND(SDL_Quit);
+ SDL_LIBRARY_FIND(SDL_GetVersion);
+ SDL_LIBRARY_FIND(SDL_GetRevision);
+ SDL_LIBRARY_FIND(SDL_GetRevisionNumber);
+ SDL_LIBRARY_FIND(SDL_GetTicks);
+ SDL_LIBRARY_FIND(SDL_GetPerformanceCounter);
+ SDL_LIBRARY_FIND(SDL_GetPerformanceFrequency);
+ SDL_LIBRARY_FIND(SDL_Delay);
+ SDL_LIBRARY_FIND(SDL_AddTimer);
+ SDL_LIBRARY_FIND(SDL_RemoveTimer);
+ SDL_LIBRARY_FIND(SDL_SetHintWithPriority);
+ SDL_LIBRARY_FIND(SDL_SetHint);
+ SDL_LIBRARY_FIND(SDL_GetHint);
+ SDL_LIBRARY_FIND(SDL_AddHintCallback);
+ SDL_LIBRARY_FIND(SDL_DelHintCallback);
+ SDL_LIBRARY_FIND(SDL_ClearHints);
+ SDL_LIBRARY_FIND(SDL_NumJoysticks);
+ SDL_LIBRARY_FIND(SDL_JoystickNameForIndex);
+ SDL_LIBRARY_FIND(SDL_JoystickOpen);
+ SDL_LIBRARY_FIND(SDL_JoystickName);
+ SDL_LIBRARY_FIND(SDL_JoystickGetDeviceGUID);
+ SDL_LIBRARY_FIND(SDL_JoystickGetGUID);
+ SDL_LIBRARY_FIND(SDL_JoystickGetGUIDFromString);
+ SDL_LIBRARY_FIND(SDL_JoystickGetAttached);
+ SDL_LIBRARY_FIND(SDL_JoystickInstanceID);
+ SDL_LIBRARY_FIND(SDL_JoystickNumAxes);
+ SDL_LIBRARY_FIND(SDL_JoystickNumBalls);
+ SDL_LIBRARY_FIND(SDL_JoystickNumHats);
+ SDL_LIBRARY_FIND(SDL_JoystickNumButtons);
+ SDL_LIBRARY_FIND(SDL_JoystickUpdate);
+ SDL_LIBRARY_FIND(SDL_JoystickEventState);
+ SDL_LIBRARY_FIND(SDL_JoystickGetAxis);
+ SDL_LIBRARY_FIND(SDL_JoystickGetHat);
+ SDL_LIBRARY_FIND(SDL_JoystickGetBall);
+ SDL_LIBRARY_FIND(SDL_JoystickGetButton);
+ SDL_LIBRARY_FIND(SDL_JoystickClose);
+ SDL_LIBRARY_FIND(SDL_RecordGesture);
+ SDL_LIBRARY_FIND(SDL_SaveAllDollarTemplates);
+ SDL_LIBRARY_FIND(SDL_SaveDollarTemplate);
+ SDL_LIBRARY_FIND(SDL_LoadDollarTemplates);
+ SDL_LIBRARY_FIND(SDL_NumHaptics);
+ SDL_LIBRARY_FIND(SDL_HapticName);
+ SDL_LIBRARY_FIND(SDL_HapticOpen);
+ SDL_LIBRARY_FIND(SDL_HapticOpened);
+ SDL_LIBRARY_FIND(SDL_HapticIndex);
+ SDL_LIBRARY_FIND(SDL_MouseIsHaptic);
+ SDL_LIBRARY_FIND(SDL_HapticOpenFromMouse);
+ SDL_LIBRARY_FIND(SDL_JoystickIsHaptic);
+ SDL_LIBRARY_FIND(SDL_HapticOpenFromJoystick);
+ SDL_LIBRARY_FIND(SDL_HapticClose);
+ SDL_LIBRARY_FIND(SDL_HapticNumEffects);
+ SDL_LIBRARY_FIND(SDL_HapticNumEffectsPlaying);
+ SDL_LIBRARY_FIND(SDL_HapticNumAxes);
+ SDL_LIBRARY_FIND(SDL_HapticEffectSupported);
+ SDL_LIBRARY_FIND(SDL_HapticNewEffect);
+ SDL_LIBRARY_FIND(SDL_HapticUpdateEffect);
+ SDL_LIBRARY_FIND(SDL_HapticRunEffect);
+ SDL_LIBRARY_FIND(SDL_HapticStopEffect);
+ SDL_LIBRARY_FIND(SDL_HapticDestroyEffect);
+ SDL_LIBRARY_FIND(SDL_HapticGetEffectStatus);
+ SDL_LIBRARY_FIND(SDL_HapticSetGain);
+ SDL_LIBRARY_FIND(SDL_HapticSetAutocenter);
+ SDL_LIBRARY_FIND(SDL_HapticPause);
+ SDL_LIBRARY_FIND(SDL_HapticUnpause);
+ SDL_LIBRARY_FIND(SDL_HapticStopAll);
+ SDL_LIBRARY_FIND(SDL_HapticRumbleSupported);
+ SDL_LIBRARY_FIND(SDL_HapticRumbleInit);
+ SDL_LIBRARY_FIND(SDL_HapticRumblePlay);
+ SDL_LIBRARY_FIND(SDL_HapticRumbleStop);
+ SDL_LIBRARY_FIND(SDL_ShowMessageBox);
+ SDL_LIBRARY_FIND(SDL_ShowSimpleMessageBox);
+ SDL_LIBRARY_FIND(SDL_PixelFormatEnumToMasks);
+ SDL_LIBRARY_FIND(SDL_MasksToPixelFormatEnum);
+ SDL_LIBRARY_FIND(SDL_AllocFormat);
+ SDL_LIBRARY_FIND(SDL_FreeFormat);
+ SDL_LIBRARY_FIND(SDL_AllocPalette);
+ SDL_LIBRARY_FIND(SDL_SetPixelFormatPalette);
+ SDL_LIBRARY_FIND(SDL_SetPaletteColors);
+ SDL_LIBRARY_FIND(SDL_FreePalette);
+ SDL_LIBRARY_FIND(SDL_MapRGB);
+ SDL_LIBRARY_FIND(SDL_MapRGBA);
+ SDL_LIBRARY_FIND(SDL_GetRGB);
+ SDL_LIBRARY_FIND(SDL_GetRGBA);
+ SDL_LIBRARY_FIND(SDL_CalculateGammaRamp);
+ SDL_LIBRARY_FIND(SDL_GetPowerInfo);
+ SDL_LIBRARY_FIND(SDL_GetCPUCount);
+ SDL_LIBRARY_FIND(SDL_GetCPUCacheLineSize);
+ SDL_LIBRARY_FIND(SDL_HasRDTSC);
+ SDL_LIBRARY_FIND(SDL_HasAltiVec);
+ SDL_LIBRARY_FIND(SDL_HasMMX);
+ SDL_LIBRARY_FIND(SDL_Has3DNow);
+ SDL_LIBRARY_FIND(SDL_HasSSE);
+ SDL_LIBRARY_FIND(SDL_HasSSE2);
+ SDL_LIBRARY_FIND(SDL_HasSSE3);
+ SDL_LIBRARY_FIND(SDL_HasSSE41);
+ SDL_LIBRARY_FIND(SDL_HasSSE42);
+ SDL_LIBRARY_FIND(SDL_GetNumTouchDevices);
+ SDL_LIBRARY_FIND(SDL_GetTouchDevice);
+ SDL_LIBRARY_FIND(SDL_GetNumTouchFingers);
+ SDL_LIBRARY_FIND(SDL_GetTouchFinger);
+ SDL_LIBRARY_FIND(SDL_SetError);
+ SDL_LIBRARY_FIND(SDL_GetError);
+ SDL_LIBRARY_FIND(SDL_ClearError);
+ SDL_LIBRARY_FIND(SDL_Error);
+ SDL_LIBRARY_FIND(SDL_SetClipboardText);
+ SDL_LIBRARY_FIND(SDL_GetClipboardText);
+ SDL_LIBRARY_FIND(SDL_HasClipboardText);
+ SDL_LIBRARY_FIND(SDL_GetWindowWMInfo);
+
+ if (SDL_GetVersion == NULL) {
+ result = SDLEW_ERROR_VERSION;
+ }
+ else {
+ SDL_GetVersion(&version);
+ if(version.major < 2) {
+ result = SDLEW_ERROR_VERSION;
+ }
+ else {
+ result = SDLEW_SUCCESS;
+ }
+ }
+
+ return result;
+}
diff --git a/extern/sdlew/src/sdlew.map b/extern/sdlew/src/sdlew.map
new file mode 100644
index 00000000000..3fb0a6f0fc9
--- /dev/null
+++ b/extern/sdlew/src/sdlew.map
@@ -0,0 +1,7 @@
+{
+global:
+ *;
+local:
+ *SDL*;
+};
+
diff --git a/intern/CMakeLists.txt b/intern/CMakeLists.txt
index 0796a43245d..4ee3dff7695 100644
--- a/intern/CMakeLists.txt
+++ b/intern/CMakeLists.txt
@@ -31,6 +31,7 @@ add_subdirectory(memutil)
add_subdirectory(opencolorio)
add_subdirectory(mikktspace)
add_subdirectory(raskter)
+add_subdirectory(glew-mx)
if(WITH_AUDASPACE)
add_subdirectory(audaspace)
@@ -76,8 +77,11 @@ if(WITH_OPENNL)
add_subdirectory(opennl)
endif()
+if(WITH_OPENSUBDIV)
+ add_subdirectory(opensubdiv)
+endif()
+
# only windows needs utf16 converter
if(WIN32)
add_subdirectory(utfconv)
endif()
-
diff --git a/intern/SConscript b/intern/SConscript
index 0b39fcb5d26..124afd4bbb9 100644
--- a/intern/SConscript
+++ b/intern/SConscript
@@ -27,9 +27,9 @@
Import ('env')
-SConscript(['audaspace/SConscript',
- 'string/SConscript',
+SConscript(['string/SConscript',
'ghost/SConscript',
+ 'glew-mx/SConscript',
'guardedalloc/SConscript',
'moto/SConscript',
'memutil/SConscript/',
@@ -44,6 +44,9 @@ SConscript(['audaspace/SConscript',
# currently only contains headers
# SConscript('container/SConscript')
+if env['WITH_BF_AUDASPACE']:
+ SConscript(['audaspace/SConscript'])
+
if env ['WITH_BF_REMESH']:
SConscript(['dualcon/SConscript'])
@@ -62,3 +65,5 @@ if env['WITH_BF_BULLET']:
if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'win64-mingw', 'linuxcross', 'win64-vc'):
SConscript(['utfconv/SConscript'])
+if env['WITH_BF_OPENSUBDIV']:
+ SConscript (['opensubdiv/SConscript'])
diff --git a/intern/atomic/atomic_ops.h b/intern/atomic/atomic_ops.h
index f63ff630c40..d8161d10401 100644
--- a/intern/atomic/atomic_ops.h
+++ b/intern/atomic/atomic_ops.h
@@ -34,6 +34,11 @@
#if defined (__APPLE__)
# include <libkern/OSAtomic.h>
#elif defined(_MSC_VER)
+# define NOGDI
+# ifndef NOMINMAX
+# define NOMINMAX
+# endif
+# define WIN32_LEAN_AND_MEAN
# include <windows.h>
#elif defined(__arm__)
/* Attempt to fix compilation error on Debian armel kernel.
@@ -72,6 +77,27 @@
# define LG_SIZEOF_INT 2
#endif
+/************************/
+/* Function prototypes. */
+
+#if (LG_SIZEOF_PTR == 3 || LG_SIZEOF_INT == 3)
+ATOMIC_INLINE uint64_t atomic_add_uint64(uint64_t *p, uint64_t x);
+ATOMIC_INLINE uint64_t atomic_sub_uint64(uint64_t *p, uint64_t x);
+ATOMIC_INLINE uint64_t atomic_cas_uint64(uint64_t *v, uint64_t old, uint64_t _new);
+#endif
+
+ATOMIC_INLINE uint32_t atomic_add_uint32(uint32_t *p, uint32_t x);
+ATOMIC_INLINE uint32_t atomic_sub_uint32(uint32_t *p, uint32_t x);
+ATOMIC_INLINE uint32_t atomic_cas_uint32(uint32_t *v, uint32_t old, uint32_t _new);
+
+ATOMIC_INLINE size_t atomic_add_z(size_t *p, size_t x);
+ATOMIC_INLINE size_t atomic_sub_z(size_t *p, size_t x);
+ATOMIC_INLINE size_t atomic_cas_z(size_t *v, size_t old, size_t _new);
+
+ATOMIC_INLINE unsigned atomic_add_u(unsigned *p, unsigned x);
+ATOMIC_INLINE unsigned atomic_sub_u(unsigned *p, unsigned x);
+ATOMIC_INLINE unsigned atomic_cas_u(unsigned *v, unsigned old, unsigned _new);
+
/******************************************************************************/
/* 64-bit operations. */
#if (LG_SIZEOF_PTR == 3 || LG_SIZEOF_INT == 3)
@@ -97,13 +123,13 @@ atomic_cas_uint64(uint64_t *v, uint64_t old, uint64_t _new)
ATOMIC_INLINE uint64_t
atomic_add_uint64(uint64_t *p, uint64_t x)
{
- return InterlockedExchangeAdd64(p, x);
+ return InterlockedExchangeAdd64((int64_t *)p, (int64_t)x) + x;
}
ATOMIC_INLINE uint64_t
atomic_sub_uint64(uint64_t *p, uint64_t x)
{
- return InterlockedExchangeAdd64(p, -((int64_t)x));
+ return InterlockedExchangeAdd64((int64_t *)p, -((int64_t)x)) - x;
}
ATOMIC_INLINE uint64_t
@@ -189,7 +215,7 @@ atomic_sub_uint64(uint64_t *p, uint64_t x)
}
ATOMIC_INLINE uint64_t
-atomic_cas_uint32(uint64_t *v, uint64_t old, uint64_t _new)
+atomic_cas_uint64(uint64_t *v, uint64_t old, uint64_t _new)
{
assert(sizeof(uint64_t) == sizeof(unsigned long));
@@ -209,7 +235,7 @@ atomic_sub_uint64(uint64_t *p, uint64_t x)
}
ATOMIC_INLINE uint64_t
-atomic_cas_uint32(uint64_t *v, uint64_t old, uint64_t _new)
+atomic_cas_uint64(uint64_t *v, uint64_t old, uint64_t _new)
{
return __sync_val_compare_and_swap(v, old, _new);
}
@@ -242,13 +268,13 @@ atomic_cas_uint32(uint32_t *v, uint32_t old, uint32_t _new)
ATOMIC_INLINE uint32_t
atomic_add_uint32(uint32_t *p, uint32_t x)
{
- return InterlockedExchangeAdd(p, x);
+ return InterlockedExchangeAdd(p, x) + x;
}
ATOMIC_INLINE uint32_t
atomic_sub_uint32(uint32_t *p, uint32_t x)
{
- return InterlockedExchangeAdd(p, -((int32_t)x));
+ return InterlockedExchangeAdd(p, -((int32_t)x)) - x;
}
ATOMIC_INLINE uint32_t
diff --git a/intern/audaspace/CMakeLists.txt b/intern/audaspace/CMakeLists.txt
index 21a42553935..b3682a77875 100644
--- a/intern/audaspace/CMakeLists.txt
+++ b/intern/audaspace/CMakeLists.txt
@@ -19,6 +19,37 @@
#
# ***** END LGPL LICENSE BLOCK *****
+remove_extra_strict_flags()
+
+if(WITH_SYSTEM_AUDASPACE)
+
+ set(INC
+ .
+ )
+
+ set(INC_SYS
+ ${AUDASPACE_C_INCLUDE_DIRS}
+ ${AUDASPACE_PY_INCLUDE_DIRS}
+ )
+
+ set(SRC
+ intern/AUD_Set.cpp
+ intern/AUD_Set.h
+ )
+
+if(WITH_PYTHON)
+ list(APPEND INC_SYS
+ ${PYTHON_INCLUDE_DIRS}
+ )
+ list(APPEND SRC
+ intern/AUD_PyInit.cpp
+ intern/AUD_PyInit.h
+ )
+ add_definitions(-DWITH_PYTHON)
+endif()
+
+else()
+
set(INC
.
FX
@@ -133,6 +164,8 @@ set(SRC
intern/AUD_SequencerHandle.h
intern/AUD_SequencerReader.cpp
intern/AUD_SequencerReader.h
+ intern/AUD_Set.cpp
+ intern/AUD_Set.h
intern/AUD_SilenceFactory.cpp
intern/AUD_SilenceFactory.h
intern/AUD_SilenceReader.cpp
@@ -314,5 +347,6 @@ if(WITH_PYTHON)
)
add_definitions(-DWITH_PYTHON)
endif()
+endif()
blender_add_lib(bf_intern_audaspace "${SRC}" "${INC}" "${INC_SYS}")
diff --git a/intern/audaspace/OpenAL/AUD_OpenALDevice.cpp b/intern/audaspace/OpenAL/AUD_OpenALDevice.cpp
index d055c131183..c0c77b6f917 100644
--- a/intern/audaspace/OpenAL/AUD_OpenALDevice.cpp
+++ b/intern/audaspace/OpenAL/AUD_OpenALDevice.cpp
@@ -276,49 +276,48 @@ bool AUD_OpenALDevice::AUD_OpenALHandle::seek(float position)
alGetSourcei(m_source, AL_SOURCE_STATE, &info);
- if(info != AL_PLAYING)
- {
- if(info == AL_PAUSED)
- alSourceStop(m_source);
+ // we need to stop playing sounds as well to clear the buffers
+ // this might cause clicks, but fixes a bug regarding position determination
+ if(info == AL_PAUSED || info == AL_PLAYING)
+ alSourceStop(m_source);
+
+ alSourcei(m_source, AL_BUFFER, 0);
+ m_current = 0;
- alSourcei(m_source, AL_BUFFER, 0);
- m_current = 0;
+ ALenum err;
+ if((err = alGetError()) == AL_NO_ERROR)
+ {
+ int length;
+ AUD_DeviceSpecs specs = m_device->m_specs;
+ specs.specs = m_reader->getSpecs();
+ m_device->m_buffer.assureSize(m_device->m_buffersize * AUD_DEVICE_SAMPLE_SIZE(specs));
- ALenum err;
- if((err = alGetError()) == AL_NO_ERROR)
+ for(int i = 0; i < CYCLE_BUFFERS; i++)
{
- int length;
- AUD_DeviceSpecs specs = m_device->m_specs;
- specs.specs = m_reader->getSpecs();
- m_device->m_buffer.assureSize(m_device->m_buffersize * AUD_DEVICE_SAMPLE_SIZE(specs));
+ length = m_device->m_buffersize;
+ m_reader->read(length, m_eos, m_device->m_buffer.getBuffer());
- for(int i = 0; i < CYCLE_BUFFERS; i++)
+ if(length == 0)
{
- length = m_device->m_buffersize;
- m_reader->read(length, m_eos, m_device->m_buffer.getBuffer());
-
- if(length == 0)
- {
- // AUD_XXX: TODO: don't fill all buffers and enqueue them later
- length = 1;
- memset(m_device->m_buffer.getBuffer(), 0, length * AUD_DEVICE_SAMPLE_SIZE(specs));
- }
-
- alBufferData(m_buffers[i], m_format, m_device->m_buffer.getBuffer(),
- length * AUD_DEVICE_SAMPLE_SIZE(specs), specs.rate);
-
- if(alGetError() != AL_NO_ERROR)
- break;
+ // AUD_XXX: TODO: don't fill all buffers and enqueue them later
+ length = 1;
+ memset(m_device->m_buffer.getBuffer(), 0, length * AUD_DEVICE_SAMPLE_SIZE(specs));
}
- if(m_loopcount != 0)
- m_eos = false;
+ alBufferData(m_buffers[i], m_format, m_device->m_buffer.getBuffer(),
+ length * AUD_DEVICE_SAMPLE_SIZE(specs), specs.rate);
- alSourceQueueBuffers(m_source, CYCLE_BUFFERS, m_buffers);
+ if(alGetError() != AL_NO_ERROR)
+ break;
}
- alSourceRewind(m_source);
+ if(m_loopcount != 0)
+ m_eos = false;
+
+ alSourceQueueBuffers(m_source, CYCLE_BUFFERS, m_buffers);
}
+
+ alSourceRewind(m_source);
}
if(m_status == AUD_STATUS_STOPPED)
@@ -343,9 +342,14 @@ float AUD_OpenALDevice::AUD_OpenALHandle::getPosition()
if(!m_isBuffered)
{
+ int queued;
+
+ // this usually always returns CYCLE_BUFFERS
+ alGetSourcei(m_source, AL_BUFFERS_QUEUED, &queued);
+
AUD_Specs specs = m_reader->getSpecs();
position += (m_reader->getPosition() - m_device->m_buffersize *
- CYCLE_BUFFERS) / (float)specs.rate;
+ queued) / (float)specs.rate;
}
return position;
diff --git a/intern/audaspace/Python/AUD_PyAPI.cpp b/intern/audaspace/Python/AUD_PyAPI.cpp
index b00289b3fae..dc019c1f245 100644
--- a/intern/audaspace/Python/AUD_PyAPI.cpp
+++ b/intern/audaspace/Python/AUD_PyAPI.cpp
@@ -2588,7 +2588,7 @@ Device_set_listener_orientation(Device *self, PyObject *args, void* nothing)
PyDoc_STRVAR(M_aud_Device_speed_of_sound_doc,
"The speed of sound of the device.\n"
- "The speed of sound in air is typically 343 m/s.");
+ "The speed of sound in air is typically 343.3 m/s.");
static PyObject *
Device_get_speed_of_sound(Device *self, void* nothing)
diff --git a/intern/audaspace/SConscript b/intern/audaspace/SConscript
index cc338629c85..8dfaa861ce2 100644
--- a/intern/audaspace/SConscript
+++ b/intern/audaspace/SConscript
@@ -21,9 +21,15 @@
#
# ***** END LGPL LICENSE BLOCK *****
+from os import path
Import ('env')
sources = env.Glob('intern/*.cpp') + env.Glob('FX/*.cpp')
+
+# AUD_PyInit is for external audaspace only
+sources.remove(path.join('intern', 'AUD_PyInit.cpp'))
+
+
incs = '. intern FX ' + env['BF_PTHREADS_INC'] + ' ' + env['BF_BOOST_INC']
defs = []
diff --git a/intern/audaspace/ffmpeg/AUD_FFMPEGWriter.cpp b/intern/audaspace/ffmpeg/AUD_FFMPEGWriter.cpp
index d30835da4e5..4ee99c723aa 100644
--- a/intern/audaspace/ffmpeg/AUD_FFMPEGWriter.cpp
+++ b/intern/audaspace/ffmpeg/AUD_FFMPEGWriter.cpp
@@ -170,7 +170,7 @@ AUD_FFMPEGWriter::AUD_FFMPEGWriter(std::string filename, AUD_DeviceSpecs specs,
AUD_THROW(AUD_ERROR_FFMPEG, codec_error);
if(codec->sample_fmts) {
- // Check if the prefered sample format for this codec is supported.
+ // Check if the preferred sample format for this codec is supported.
const enum AVSampleFormat *p = codec->sample_fmts;
for(; *p != -1; p++) {
if(*p == m_stream->codec->sample_fmt)
diff --git a/intern/audaspace/intern/AUD_AnimateableProperty.cpp b/intern/audaspace/intern/AUD_AnimateableProperty.cpp
index 9f399a0b99f..e0bc18ea520 100644
--- a/intern/audaspace/intern/AUD_AnimateableProperty.cpp
+++ b/intern/audaspace/intern/AUD_AnimateableProperty.cpp
@@ -119,13 +119,11 @@ void AUD_AnimateableProperty::write(const float* data, int position, int count)
{
m_unknown.push_back(Unknown(pos, position - 1));
+ // if the buffer was not animated before, we copy the previous static value
if(pos == 0)
- {
- for(int i = 0; i < position; i++)
- memcpy(buf + i * m_count, data, m_count * sizeof(float));
- }
- else
- updateUnknownCache(pos, position - 1);
+ pos = 1;
+
+ updateUnknownCache(pos, position - 1);
}
// otherwise it's not at the end, let's check if some unknown part got filled
else
diff --git a/intern/audaspace/intern/AUD_C-API.cpp b/intern/audaspace/intern/AUD_C-API.cpp
index aa82e1da678..341f1cd3f6b 100644
--- a/intern/audaspace/intern/AUD_C-API.cpp
+++ b/intern/audaspace/intern/AUD_C-API.cpp
@@ -41,11 +41,11 @@
# include "AUD_PyAPI.h"
#endif
-#include <set>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <sstream>
+#include <iostream>
#include "AUD_NULLDevice.h"
#include "AUD_I3DDevice.h"
@@ -75,6 +75,7 @@
#include "AUD_MutexLock.h"
#ifdef WITH_SDL
+#include <SDL.h>
#include "AUD_SDLDevice.h"
#endif
@@ -97,7 +98,7 @@ extern "C" {
#include <cassert>
typedef boost::shared_ptr<AUD_IFactory> AUD_Sound;
-typedef boost::shared_ptr<AUD_ReadDevice> AUD_Device;
+typedef boost::shared_ptr<AUD_IDevice> AUD_Device;
typedef boost::shared_ptr<AUD_IHandle> AUD_Handle;
typedef boost::shared_ptr<AUD_SequencerEntry> AUD_SEntry;
@@ -128,64 +129,69 @@ void AUD_exitOnce()
#endif
}
-int AUD_init(AUD_DeviceType device, AUD_DeviceSpecs specs, int buffersize)
+AUD_Device* AUD_init(const char* device, AUD_DeviceSpecs specs, int buffersize, const char* name)
{
boost::shared_ptr<AUD_IDevice> dev;
if (AUD_device.get()) {
- AUD_exit();
+ AUD_exit(NULL);
}
+ std::string dname = device;
+
try {
- switch(device) {
- case AUD_NULL_DEVICE:
+ if(dname == "Null") {
dev = boost::shared_ptr<AUD_IDevice>(new AUD_NULLDevice());
- break;
+ }
#ifdef WITH_SDL
- case AUD_SDL_DEVICE:
+ else if(dname == "SDL")
+ {
dev = boost::shared_ptr<AUD_IDevice>(new AUD_SDLDevice(specs, buffersize));
- break;
+ }
#endif
#ifdef WITH_OPENAL
- case AUD_OPENAL_DEVICE:
+ else if(dname == "OpenAL")
+ {
dev = boost::shared_ptr<AUD_IDevice>(new AUD_OpenALDevice(specs, buffersize));
- break;
+ }
#endif
#ifdef WITH_JACK
- case AUD_JACK_DEVICE:
+ else if(dname == "Jack")
+ {
#ifdef __APPLE__
struct stat st;
if (stat("/Library/Frameworks/Jackmp.framework", &st) != 0) {
printf("Warning: Jack Framework not installed\n");
- // No break, fall through to default, to return false
+ return NULL;
}
else
#endif
if (!AUD_jack_supported()) {
printf("Warning: Jack cllient not installed\n");
- // No break, fall through to default, to return false
+ return NULL;
}
else {
- dev = boost::shared_ptr<AUD_IDevice>(new AUD_JackDevice("Blender", specs, buffersize));
- break;
+ dev = boost::shared_ptr<AUD_IDevice>(new AUD_JackDevice(name, specs, buffersize));
}
+ }
#endif
- default:
- return false;
+ else
+ {
+ return NULL;
}
AUD_device = dev;
AUD_3ddevice = dynamic_cast<AUD_I3DDevice *>(AUD_device.get());
- return true;
+ return (AUD_Device*)1;
}
catch(AUD_Exception&)
{
- return false;
+ return NULL;
}
}
-void AUD_exit()
+void AUD_exit(AUD_Device* device)
{
AUD_device = boost::shared_ptr<AUD_IDevice>();
AUD_3ddevice = NULL;
@@ -214,7 +220,7 @@ static PyMethodDef meth_getcdevice[] = {
};
extern "C" {
-extern void *sound_get_factory(void *sound);
+extern void *BKE_sound_get_factory(void *sound);
}
static PyObject *AUD_getSoundFromPointer(PyObject *self, PyObject *args)
@@ -223,7 +229,7 @@ static PyObject *AUD_getSoundFromPointer(PyObject *self, PyObject *args)
if (PyArg_Parse(args, "l:_sound_from_pointer", &lptr)) {
if (lptr) {
- boost::shared_ptr<AUD_IFactory>* factory = (boost::shared_ptr<AUD_IFactory>*) sound_get_factory((void *) lptr);
+ boost::shared_ptr<AUD_IFactory>* factory = (boost::shared_ptr<AUD_IFactory>*) BKE_sound_get_factory((void *) lptr);
if (factory) {
Factory *obj = (Factory *)Factory_empty();
@@ -258,7 +264,7 @@ PyObject *AUD_initPython()
return module;
}
-void *AUD_getPythonFactory(AUD_Sound *sound)
+void *AUD_getPythonSound(AUD_Sound *sound)
{
if (sound) {
Factory *obj = (Factory *) Factory_empty();
@@ -271,7 +277,7 @@ void *AUD_getPythonFactory(AUD_Sound *sound)
return NULL;
}
-AUD_Sound *AUD_getPythonSound(void *sound)
+AUD_Sound *AUD_getSoundFromPython(void *sound)
{
Factory *factory = checkFactory((PyObject *)sound);
@@ -283,16 +289,26 @@ AUD_Sound *AUD_getPythonSound(void *sound)
#endif
-void AUD_lock()
+void AUD_Device_lock(AUD_Device* device)
{
AUD_device->lock();
}
-void AUD_unlock()
+void AUD_Device_unlock(AUD_Device* device)
{
AUD_device->unlock();
}
+AUD_Channels AUD_Device_getChannels(AUD_Device* device)
+{
+ return AUD_device->getSpecs().channels;
+}
+
+AUD_SampleRate AUD_Device_getRate(AUD_Device* device)
+{
+ return AUD_device->getSpecs().rate;
+}
+
AUD_SoundInfo AUD_getInfo(AUD_Sound *sound)
{
assert(sound);
@@ -310,26 +326,27 @@ AUD_SoundInfo AUD_getInfo(AUD_Sound *sound)
info.length = reader->getLength() / (float) info.specs.rate;
}
}
- catch(AUD_Exception&)
+ catch(AUD_Exception &ae)
{
+ std::cout << ae.str << std::endl;
}
return info;
}
-AUD_Sound *AUD_load(const char *filename)
+AUD_Sound *AUD_Sound_file(const char *filename)
{
assert(filename);
return new AUD_Sound(new AUD_FileFactory(filename));
}
-AUD_Sound *AUD_loadBuffer(unsigned char *buffer, int size)
+AUD_Sound *AUD_Sound_bufferFile(unsigned char *buffer, int size)
{
assert(buffer);
return new AUD_Sound(new AUD_FileFactory(buffer, size));
}
-AUD_Sound *AUD_bufferSound(AUD_Sound *sound)
+AUD_Sound *AUD_Sound_cache(AUD_Sound *sound)
{
assert(sound);
@@ -342,13 +359,13 @@ AUD_Sound *AUD_bufferSound(AUD_Sound *sound)
}
}
-AUD_Sound *AUD_monoSound(AUD_Sound *sound)
+AUD_Sound *AUD_Sound_rechannel(AUD_Sound *sound, AUD_Channels channels)
{
assert(sound);
try {
AUD_DeviceSpecs specs;
- specs.channels = AUD_CHANNELS_MONO;
+ specs.channels = channels;
specs.rate = AUD_RATE_INVALID;
specs.format = AUD_FORMAT_INVALID;
return new AUD_Sound(new AUD_ChannelMapperFactory(*sound, specs));
@@ -359,7 +376,7 @@ AUD_Sound *AUD_monoSound(AUD_Sound *sound)
}
}
-AUD_Sound *AUD_delaySound(AUD_Sound *sound, float delay)
+AUD_Sound *AUD_Sound_delay(AUD_Sound *sound, float delay)
{
assert(sound);
@@ -372,7 +389,7 @@ AUD_Sound *AUD_delaySound(AUD_Sound *sound, float delay)
}
}
-AUD_Sound *AUD_limitSound(AUD_Sound *sound, float start, float end)
+AUD_Sound *AUD_Sound_limit(AUD_Sound *sound, float start, float end)
{
assert(sound);
@@ -385,7 +402,7 @@ AUD_Sound *AUD_limitSound(AUD_Sound *sound, float start, float end)
}
}
-AUD_Sound *AUD_pingpongSound(AUD_Sound *sound)
+AUD_Sound *AUD_Sound_pingpong(AUD_Sound *sound)
{
assert(sound);
@@ -398,7 +415,7 @@ AUD_Sound *AUD_pingpongSound(AUD_Sound *sound)
}
}
-AUD_Sound *AUD_loopSound(AUD_Sound *sound)
+AUD_Sound *AUD_Sound_loop(AUD_Sound *sound)
{
assert(sound);
@@ -411,7 +428,7 @@ AUD_Sound *AUD_loopSound(AUD_Sound *sound)
}
}
-int AUD_setLoop(AUD_Handle *handle, int loops)
+int AUD_Handle_setLoopCount(AUD_Handle *handle, int loops)
{
assert(handle);
@@ -438,13 +455,13 @@ AUD_Sound *AUD_rectifySound(AUD_Sound *sound)
}
}
-void AUD_unload(AUD_Sound *sound)
+void AUD_Sound_free(AUD_Sound *sound)
{
assert(sound);
delete sound;
}
-AUD_Handle *AUD_play(AUD_Sound *sound, int keep)
+AUD_Handle *AUD_Device_play(AUD_Device* device, AUD_Sound *sound, int keep)
{
assert(sound);
try {
@@ -459,19 +476,19 @@ AUD_Handle *AUD_play(AUD_Sound *sound, int keep)
return NULL;
}
-int AUD_pause(AUD_Handle *handle)
+int AUD_Handle_pause(AUD_Handle *handle)
{
assert(handle);
return (*handle)->pause();
}
-int AUD_resume(AUD_Handle *handle)
+int AUD_Handle_resume(AUD_Handle *handle)
{
assert(handle);
return (*handle)->resume();
}
-int AUD_stop(AUD_Handle *handle)
+int AUD_Handle_stop(AUD_Handle *handle)
{
assert(handle);
int result = (*handle)->stop();
@@ -479,31 +496,36 @@ int AUD_stop(AUD_Handle *handle)
return result;
}
-int AUD_setKeep(AUD_Handle *handle, int keep)
+void AUD_Device_stopAll(void* device)
+{
+ AUD_device->stopAll();
+}
+
+int AUD_Handle_setKeep(AUD_Handle *handle, int keep)
{
assert(handle);
return (*handle)->setKeep(keep);
}
-int AUD_seek(AUD_Handle *handle, float seekTo)
+int AUD_Handle_setPosition(AUD_Handle *handle, float seekTo)
{
assert(handle);
return (*handle)->seek(seekTo);
}
-float AUD_getPosition(AUD_Handle *handle)
+float AUD_Handle_getPosition(AUD_Handle *handle)
{
assert(handle);
return (*handle)->getPosition();
}
-AUD_Status AUD_getStatus(AUD_Handle *handle)
+AUD_Status AUD_Handle_getStatus(AUD_Handle *handle)
{
assert(handle);
return (*handle)->getStatus();
}
-int AUD_setListenerLocation(const float location[3])
+int AUD_Device_setListenerLocation(const float location[3])
{
if (AUD_3ddevice) {
AUD_Vector3 v(location[0], location[1], location[2]);
@@ -514,7 +536,7 @@ int AUD_setListenerLocation(const float location[3])
return false;
}
-int AUD_setListenerVelocity(const float velocity[3])
+int AUD_Device_setListenerVelocity(const float velocity[3])
{
if (AUD_3ddevice) {
AUD_Vector3 v(velocity[0], velocity[1], velocity[2]);
@@ -525,7 +547,7 @@ int AUD_setListenerVelocity(const float velocity[3])
return false;
}
-int AUD_setListenerOrientation(const float orientation[4])
+int AUD_Device_setListenerOrientation(const float orientation[4])
{
if (AUD_3ddevice) {
AUD_Quaternion q(orientation[3], orientation[0], orientation[1], orientation[2]);
@@ -536,7 +558,7 @@ int AUD_setListenerOrientation(const float orientation[4])
return false;
}
-int AUD_setSpeedOfSound(float speed)
+int AUD_Device_setSpeedOfSound(void* device, float speed)
{
if (AUD_3ddevice) {
AUD_3ddevice->setSpeedOfSound(speed);
@@ -546,7 +568,7 @@ int AUD_setSpeedOfSound(float speed)
return false;
}
-int AUD_setDopplerFactor(float factor)
+int AUD_Device_setDopplerFactor(void* device, float factor)
{
if (AUD_3ddevice) {
AUD_3ddevice->setDopplerFactor(factor);
@@ -556,7 +578,7 @@ int AUD_setDopplerFactor(float factor)
return false;
}
-int AUD_setDistanceModel(AUD_DistanceModel model)
+int AUD_Device_setDistanceModel(void* device, AUD_DistanceModel model)
{
if (AUD_3ddevice) {
AUD_3ddevice->setDistanceModel(model);
@@ -566,7 +588,7 @@ int AUD_setDistanceModel(AUD_DistanceModel model)
return false;
}
-int AUD_setSourceLocation(AUD_Handle *handle, const float location[3])
+int AUD_Handle_setLocation(AUD_Handle *handle, const float location[3])
{
assert(handle);
boost::shared_ptr<AUD_I3DHandle> h = boost::dynamic_pointer_cast<AUD_I3DHandle>(*handle);
@@ -579,7 +601,7 @@ int AUD_setSourceLocation(AUD_Handle *handle, const float location[3])
return false;
}
-int AUD_setSourceVelocity(AUD_Handle *handle, const float velocity[3])
+int AUD_Handle_setVelocity(AUD_Handle *handle, const float velocity[3])
{
assert(handle);
boost::shared_ptr<AUD_I3DHandle> h = boost::dynamic_pointer_cast<AUD_I3DHandle>(*handle);
@@ -592,7 +614,7 @@ int AUD_setSourceVelocity(AUD_Handle *handle, const float velocity[3])
return false;
}
-int AUD_setSourceOrientation(AUD_Handle *handle, const float orientation[4])
+int AUD_Handle_setOrientation(AUD_Handle *handle, const float orientation[4])
{
assert(handle);
boost::shared_ptr<AUD_I3DHandle> h = boost::dynamic_pointer_cast<AUD_I3DHandle>(*handle);
@@ -605,7 +627,7 @@ int AUD_setSourceOrientation(AUD_Handle *handle, const float orientation[4])
return false;
}
-int AUD_setRelative(AUD_Handle *handle, int relative)
+int AUD_Handle_setRelative(AUD_Handle *handle, int relative)
{
assert(handle);
boost::shared_ptr<AUD_I3DHandle> h = boost::dynamic_pointer_cast<AUD_I3DHandle>(*handle);
@@ -617,7 +639,7 @@ int AUD_setRelative(AUD_Handle *handle, int relative)
return false;
}
-int AUD_setVolumeMaximum(AUD_Handle *handle, float volume)
+int AUD_Handle_setVolumeMaximum(AUD_Handle *handle, float volume)
{
assert(handle);
boost::shared_ptr<AUD_I3DHandle> h = boost::dynamic_pointer_cast<AUD_I3DHandle>(*handle);
@@ -629,7 +651,7 @@ int AUD_setVolumeMaximum(AUD_Handle *handle, float volume)
return false;
}
-int AUD_setVolumeMinimum(AUD_Handle *handle, float volume)
+int AUD_Handle_setVolumeMinimum(AUD_Handle *handle, float volume)
{
assert(handle);
boost::shared_ptr<AUD_I3DHandle> h = boost::dynamic_pointer_cast<AUD_I3DHandle>(*handle);
@@ -641,7 +663,7 @@ int AUD_setVolumeMinimum(AUD_Handle *handle, float volume)
return false;
}
-int AUD_setDistanceMaximum(AUD_Handle *handle, float distance)
+int AUD_Handle_setDistanceMaximum(AUD_Handle *handle, float distance)
{
assert(handle);
boost::shared_ptr<AUD_I3DHandle> h = boost::dynamic_pointer_cast<AUD_I3DHandle>(*handle);
@@ -653,7 +675,7 @@ int AUD_setDistanceMaximum(AUD_Handle *handle, float distance)
return false;
}
-int AUD_setDistanceReference(AUD_Handle *handle, float distance)
+int AUD_Handle_setDistanceReference(AUD_Handle *handle, float distance)
{
assert(handle);
boost::shared_ptr<AUD_I3DHandle> h = boost::dynamic_pointer_cast<AUD_I3DHandle>(*handle);
@@ -665,7 +687,7 @@ int AUD_setDistanceReference(AUD_Handle *handle, float distance)
return false;
}
-int AUD_setAttenuation(AUD_Handle *handle, float factor)
+int AUD_Handle_setAttenuation(AUD_Handle *handle, float factor)
{
assert(handle);
boost::shared_ptr<AUD_I3DHandle> h = boost::dynamic_pointer_cast<AUD_I3DHandle>(*handle);
@@ -677,7 +699,7 @@ int AUD_setAttenuation(AUD_Handle *handle, float factor)
return false;
}
-int AUD_setConeAngleOuter(AUD_Handle *handle, float angle)
+int AUD_Handle_setConeAngleOuter(AUD_Handle *handle, float angle)
{
assert(handle);
boost::shared_ptr<AUD_I3DHandle> h = boost::dynamic_pointer_cast<AUD_I3DHandle>(*handle);
@@ -689,7 +711,7 @@ int AUD_setConeAngleOuter(AUD_Handle *handle, float angle)
return false;
}
-int AUD_setConeAngleInner(AUD_Handle *handle, float angle)
+int AUD_Handle_setConeAngleInner(AUD_Handle *handle, float angle)
{
assert(handle);
boost::shared_ptr<AUD_I3DHandle> h = boost::dynamic_pointer_cast<AUD_I3DHandle>(*handle);
@@ -701,7 +723,7 @@ int AUD_setConeAngleInner(AUD_Handle *handle, float angle)
return false;
}
-int AUD_setConeVolumeOuter(AUD_Handle *handle, float volume)
+int AUD_Handle_setConeVolumeOuter(AUD_Handle *handle, float volume)
{
assert(handle);
boost::shared_ptr<AUD_I3DHandle> h = boost::dynamic_pointer_cast<AUD_I3DHandle>(*handle);
@@ -713,7 +735,7 @@ int AUD_setConeVolumeOuter(AUD_Handle *handle, float volume)
return false;
}
-int AUD_setSoundVolume(AUD_Handle *handle, float volume)
+int AUD_Handle_setVolume(AUD_Handle *handle, float volume)
{
assert(handle);
try {
@@ -723,7 +745,7 @@ int AUD_setSoundVolume(AUD_Handle *handle, float volume)
return false;
}
-int AUD_setSoundPitch(AUD_Handle *handle, float pitch)
+int AUD_Handle_setPitch(AUD_Handle *handle, float pitch)
{
assert(handle);
try {
@@ -775,13 +797,13 @@ int AUD_setDeviceVolume(AUD_Device *device, float volume)
return false;
}
-int AUD_readDevice(AUD_Device *device, data_t *buffer, int length)
+int AUD_Device_read(AUD_Device *device, data_t *buffer, int length)
{
assert(device);
assert(buffer);
try {
- return (*device)->read(buffer, length);
+ return boost::dynamic_pointer_cast<AUD_ReadDevice>(*device)->read(buffer, length);
}
catch(AUD_Exception&)
{
@@ -789,12 +811,11 @@ int AUD_readDevice(AUD_Device *device, data_t *buffer, int length)
}
}
-void AUD_closeReadDevice(AUD_Device *device)
+void AUD_Device_free(AUD_Device *device)
{
- assert(device);
-
try {
- delete device;
+ if(device != &AUD_device)
+ delete device;
}
catch(AUD_Exception&)
{
@@ -892,7 +913,7 @@ AUD_Handle *AUD_pauseAfter(AUD_Handle *handle, float seconds)
return NULL;
}
-AUD_Sound *AUD_createSequencer(float fps, int muted)
+AUD_Sound *AUD_Sequence_create(float fps, int muted)
{
// specs are changed at a later point!
AUD_Specs specs;
@@ -902,22 +923,22 @@ AUD_Sound *AUD_createSequencer(float fps, int muted)
return sequencer;
}
-void AUD_destroySequencer(AUD_Sound *sequencer)
+void AUD_Sequence_free(AUD_Sound *sequencer)
{
delete sequencer;
}
-void AUD_setSequencerMuted(AUD_Sound *sequencer, int muted)
+void AUD_Sequence_setMuted(AUD_Sound *sequencer, int muted)
{
dynamic_cast<AUD_SequencerFactory *>(sequencer->get())->mute(muted);
}
-void AUD_setSequencerFPS(AUD_Sound *sequencer, float fps)
+void AUD_Sequence_setFPS(AUD_Sound *sequencer, float fps)
{
dynamic_cast<AUD_SequencerFactory *>(sequencer->get())->setFPS(fps);
}
-AUD_SEntry *AUD_addSequence(AUD_Sound *sequencer, AUD_Sound *sound,
+AUD_SEntry *AUD_Sequence_add(AUD_Sound *sequencer, AUD_Sound *sound,
float begin, float end, float skip)
{
if (!sound)
@@ -925,28 +946,23 @@ AUD_SEntry *AUD_addSequence(AUD_Sound *sequencer, AUD_Sound *sound,
return new AUD_SEntry(((AUD_SequencerFactory *)sequencer->get())->add(*sound, begin, end, skip));
}
-void AUD_removeSequence(AUD_Sound *sequencer, AUD_SEntry *entry)
+void AUD_Sequence_remove(AUD_Sound *sequencer, AUD_SEntry *entry)
{
dynamic_cast<AUD_SequencerFactory *>(sequencer->get())->remove(*entry);
delete entry;
}
-void AUD_moveSequence(AUD_SEntry *entry, float begin, float end, float skip)
+void AUD_SequenceEntry_move(AUD_SEntry *entry, float begin, float end, float skip)
{
(*entry)->move(begin, end, skip);
}
-void AUD_muteSequence(AUD_SEntry *entry, char mute)
+void AUD_SequenceEntry_setMuted(AUD_SEntry *entry, char mute)
{
(*entry)->mute(mute);
}
-void AUD_setRelativeSequence(AUD_SEntry *entry, char relative)
-{
- (*entry)->setRelative(relative);
-}
-
-void AUD_updateSequenceSound(AUD_SEntry *entry, AUD_Sound *sound)
+void AUD_SequenceEntry_setSound(AUD_SEntry *entry, AUD_Sound *sound)
{
if (sound)
(*entry)->setSound(*sound);
@@ -954,7 +970,7 @@ void AUD_updateSequenceSound(AUD_SEntry *entry, AUD_Sound *sound)
(*entry)->setSound(AUD_Sound());
}
-void AUD_setSequenceAnimData(AUD_SEntry *entry, AUD_AnimateablePropertyType type, int frame, float *data, char animated)
+void AUD_SequenceEntry_setAnimationData(AUD_SEntry *entry, AUD_AnimateablePropertyType type, int frame, float *data, char animated)
{
AUD_AnimateableProperty *prop = (*entry)->getAnimProperty(type);
if (animated) {
@@ -966,7 +982,7 @@ void AUD_setSequenceAnimData(AUD_SEntry *entry, AUD_AnimateablePropertyType type
}
}
-void AUD_setSequencerAnimData(AUD_Sound *sequencer, AUD_AnimateablePropertyType type, int frame, float *data, char animated)
+void AUD_Sequence_setAnimationData(AUD_Sound *sequencer, AUD_AnimateablePropertyType type, int frame, float *data, char animated)
{
AUD_AnimateableProperty *prop = dynamic_cast<AUD_SequencerFactory *>(sequencer->get())->getAnimProperty(type);
if (animated) {
@@ -979,21 +995,76 @@ void AUD_setSequencerAnimData(AUD_Sound *sequencer, AUD_AnimateablePropertyType
}
}
-void AUD_updateSequenceData(AUD_SEntry *entry, float volume_max, float volume_min,
- float distance_max, float distance_reference, float attenuation,
- float cone_angle_outer, float cone_angle_inner, float cone_volume_outer)
+void AUD_Sequence_setDistanceModel(AUD_Sound* sequence, AUD_DistanceModel value)
+{
+ assert(sequence);
+ dynamic_cast<AUD_SequencerFactory *>(sequence->get())->setDistanceModel(static_cast<AUD_DistanceModel>(value));
+}
+
+void AUD_Sequence_setDopplerFactor(AUD_Sound* sequence, float value)
+{
+ assert(sequence);
+ dynamic_cast<AUD_SequencerFactory *>(sequence->get())->setDopplerFactor(value);
+}
+
+void AUD_Sequence_setSpeedOfSound(AUD_Sound* sequence, float value)
+{
+ assert(sequence);
+ dynamic_cast<AUD_SequencerFactory *>(sequence->get())->setSpeedOfSound(value);
+}
+
+void AUD_SequenceEntry_setAttenuation(AUD_SEntry* sequence_entry, float value)
+{
+ assert(sequence_entry);
+ (*sequence_entry)->setAttenuation(value);
+}
+
+void AUD_SequenceEntry_setConeAngleInner(AUD_SEntry* sequence_entry, float value)
+{
+ assert(sequence_entry);
+ (*sequence_entry)->setConeAngleInner(value);
+}
+
+void AUD_SequenceEntry_setConeAngleOuter(AUD_SEntry* sequence_entry, float value)
+{
+ assert(sequence_entry);
+ (*sequence_entry)->setConeAngleOuter(value);
+}
+
+void AUD_SequenceEntry_setConeVolumeOuter(AUD_SEntry* sequence_entry, float value)
+{
+ assert(sequence_entry);
+ (*sequence_entry)->setConeVolumeOuter(value);
+}
+
+void AUD_SequenceEntry_setDistanceMaximum(AUD_SEntry* sequence_entry, float value)
+{
+ assert(sequence_entry);
+ (*sequence_entry)->setDistanceMaximum(value);
+}
+
+void AUD_SequenceEntry_setDistanceReference(AUD_SEntry* sequence_entry, float value)
+{
+ assert(sequence_entry);
+ (*sequence_entry)->setDistanceReference(value);
+}
+
+void AUD_SequenceEntry_setRelative(AUD_SEntry* sequence_entry, int value)
{
- (*entry)->updateAll(volume_max, volume_min, distance_max, distance_reference, attenuation,
- cone_angle_outer, cone_angle_inner, cone_volume_outer);
+ assert(sequence_entry);
+ (*sequence_entry)->setRelative(value);
}
-void AUD_updateSequencerData(AUD_Sound *sequencer, float speed_of_sound,
- float factor, AUD_DistanceModel model)
+void AUD_SequenceEntry_setVolumeMaximum(AUD_SEntry* sequence_entry, float value)
{
- AUD_SequencerFactory *f = dynamic_cast<AUD_SequencerFactory *>(sequencer->get());
- f->setSpeedOfSound(speed_of_sound);
- f->setDopplerFactor(factor);
- f->setDistanceModel(model);
+ assert(sequence_entry);
+ (*sequence_entry)->setVolumeMaximum(value);
+}
+
+void AUD_SequenceEntry_setVolumeMinimum(AUD_SEntry* sequence_entry, float value)
+{
+ assert(sequence_entry);
+ (*sequence_entry)->setVolumeMinimum(value);
}
void AUD_setSequencerDeviceSpecs(AUD_Sound *sequencer)
@@ -1001,12 +1072,12 @@ void AUD_setSequencerDeviceSpecs(AUD_Sound *sequencer)
dynamic_cast<AUD_SequencerFactory *>(sequencer->get())->setSpecs(AUD_device->getSpecs().specs);
}
-void AUD_setSequencerSpecs(AUD_Sound *sequencer, AUD_Specs specs)
+void AUD_Sequence_setSpecs(AUD_Sound *sequencer, AUD_Specs specs)
{
dynamic_cast<AUD_SequencerFactory *>(sequencer->get())->setSpecs(specs);
}
-void AUD_seekSequencer(AUD_Handle *handle, float time)
+void AUD_seekSynchronizer(AUD_Handle *handle, float time)
{
#ifdef WITH_JACK
AUD_JackDevice *device = dynamic_cast<AUD_JackDevice *>(AUD_device.get());
@@ -1021,7 +1092,7 @@ void AUD_seekSequencer(AUD_Handle *handle, float time)
}
}
-float AUD_getSequencerPosition(AUD_Handle *handle)
+float AUD_getSynchronizerPosition(AUD_Handle *handle)
{
#ifdef WITH_JACK
AUD_JackDevice *device = dynamic_cast<AUD_JackDevice *>(AUD_device.get());
@@ -1036,7 +1107,7 @@ float AUD_getSequencerPosition(AUD_Handle *handle)
}
}
-void AUD_startPlayback()
+void AUD_playSynchronizer()
{
#ifdef WITH_JACK
AUD_JackDevice *device = dynamic_cast<AUD_JackDevice *>(AUD_device.get());
@@ -1046,7 +1117,7 @@ void AUD_startPlayback()
#endif
}
-void AUD_stopPlayback()
+void AUD_stopSynchronizer()
{
#ifdef WITH_JACK
AUD_JackDevice *device = dynamic_cast<AUD_JackDevice *>(AUD_device.get());
@@ -1057,7 +1128,7 @@ void AUD_stopPlayback()
}
#ifdef WITH_JACK
-void AUD_setSyncCallback(AUD_syncFunction function, void *data)
+void AUD_setSynchronizerCallback(AUD_syncFunction function, void *data)
{
AUD_JackDevice *device = dynamic_cast<AUD_JackDevice *>(AUD_device.get());
if (device) {
@@ -1066,7 +1137,7 @@ void AUD_setSyncCallback(AUD_syncFunction function, void *data)
}
#endif
-int AUD_doesPlayback()
+int AUD_isSynchronizerPlaying()
{
#ifdef WITH_JACK
AUD_JackDevice *device = dynamic_cast<AUD_JackDevice *>(AUD_device.get());
@@ -1077,7 +1148,7 @@ int AUD_doesPlayback()
return -1;
}
-int AUD_readSound(AUD_Sound *sound, sample_t *buffer, int length, int samples_per_second)
+int AUD_readSound(AUD_Sound *sound, sample_t *buffer, int length, int samples_per_second, short *interrupt)
{
AUD_DeviceSpecs specs;
sample_t *buf;
@@ -1100,6 +1171,9 @@ int AUD_readSound(AUD_Sound *sound, sample_t *buffer, int length, int samples_pe
for (int i = 0; i < length; i++) {
len = floor(samplejump * (i+1)) - floor(samplejump * i);
+ if (*interrupt) {
+ return 0;
+ }
aBuffer.assureSize(len * AUD_SAMPLE_SIZE(specs));
buf = aBuffer.getBuffer();
@@ -1139,54 +1213,16 @@ int AUD_readSound(AUD_Sound *sound, sample_t *buffer, int length, int samples_pe
return length;
}
-AUD_Sound *AUD_copy(AUD_Sound *sound)
+AUD_Sound *AUD_Sound_copy(AUD_Sound *sound)
{
return new boost::shared_ptr<AUD_IFactory>(*sound);
}
-void AUD_freeHandle(AUD_Handle *handle)
+void AUD_Handle_free(AUD_Handle *handle)
{
delete handle;
}
-void *AUD_createSet()
-{
- return new std::set<void *>();
-}
-
-void AUD_destroySet(void *set)
-{
- delete reinterpret_cast<std::set<void *>*>(set);
-}
-
-char AUD_removeSet(void *set, void *entry)
-{
- if (set)
- return reinterpret_cast<std::set<void *>*>(set)->erase(entry);
- return 0;
-}
-
-void AUD_addSet(void *set, void *entry)
-{
- if (entry)
- reinterpret_cast<std::set<void *>*>(set)->insert(entry);
-}
-
-void *AUD_getSet(void *set)
-{
- if (set) {
- std::set<void *>* rset = reinterpret_cast<std::set<void *>*>(set);
- if (!rset->empty()) {
- std::set<void *>::iterator it = rset->begin();
- void *result = *it;
- rset->erase(it);
- return result;
- }
- }
-
- return NULL;
-}
-
const char *AUD_mixdown(AUD_Sound *sound, unsigned int start, unsigned int length, unsigned int buffersize, const char *filename, AUD_DeviceSpecs specs, AUD_Container format, AUD_Codec codec, unsigned int bitrate)
{
try {
@@ -1271,14 +1307,9 @@ AUD_Device *AUD_openMixdownDevice(AUD_DeviceSpecs specs, AUD_Sound *sequencer, f
}
}
-boost::shared_ptr<AUD_IDevice> AUD_getDevice()
-{
- return AUD_device;
-}
-
-AUD_I3DDevice *AUD_get3DDevice()
+AUD_Device *AUD_Device_getCurrent(void)
{
- return AUD_3ddevice;
+ return &AUD_device;
}
int AUD_isJackSupported(void)
diff --git a/intern/audaspace/intern/AUD_C-API.h b/intern/audaspace/intern/AUD_C-API.h
index 64a3d06bd5f..bdbe751b140 100644
--- a/intern/audaspace/intern/AUD_C-API.h
+++ b/intern/audaspace/intern/AUD_C-API.h
@@ -77,22 +77,26 @@ extern void AUD_exitOnce(void);
* \param buffersize The buffersize for the device.
* \return Whether the device has been initialized.
*/
-extern int AUD_init(AUD_DeviceType device, AUD_DeviceSpecs specs, int buffersize);
+extern AUD_Device* AUD_init(const char* device, AUD_DeviceSpecs specs, int buffersize, const char* name);
/**
* Unitinitializes an audio device.
*/
-extern void AUD_exit(void);
+extern void AUD_exit(AUD_Device* device);
/**
* Locks the playback device.
*/
-extern void AUD_lock(void);
+extern void AUD_Device_lock(AUD_Device* device);
/**
* Unlocks the device.
*/
-extern void AUD_unlock(void);
+extern void AUD_Device_unlock(AUD_Device* device);
+
+extern AUD_Channels AUD_Device_getChannels(AUD_Device* device);
+
+extern AUD_SampleRate AUD_Device_getRate(AUD_Device* device);
/**
* Returns information about a sound.
@@ -106,7 +110,7 @@ extern AUD_SoundInfo AUD_getInfo(AUD_Sound *sound);
* \param filename The filename of the sound file.
* \return A handle of the sound file.
*/
-extern AUD_Sound *AUD_load(const char *filename);
+extern AUD_Sound *AUD_Sound_file(const char *filename);
/**
* Loads a sound file.
@@ -114,21 +118,21 @@ extern AUD_Sound *AUD_load(const char *filename);
* \param size The size of the buffer.
* \return A handle of the sound file.
*/
-extern AUD_Sound *AUD_loadBuffer(unsigned char *buffer, int size);
+extern AUD_Sound *AUD_Sound_bufferFile(unsigned char *buffer, int size);
/**
* Buffers a sound.
* \param sound The sound to buffer.
* \return A handle of the sound buffer.
*/
-extern AUD_Sound *AUD_bufferSound(AUD_Sound *sound);
+extern AUD_Sound *AUD_Sound_cache(AUD_Sound *sound);
/**
* Rechannels the sound to be mono.
* \param sound The sound to rechannel.
* \return The mono sound.
*/
-extern AUD_Sound *AUD_monoSound(AUD_Sound *sound);
+extern AUD_Sound *AUD_Sound_rechannel(AUD_Sound *sound, AUD_Channels channels);
/**
* Delays a sound.
@@ -136,7 +140,7 @@ extern AUD_Sound *AUD_monoSound(AUD_Sound *sound);
* \param delay The delay in seconds.
* \return A handle of the delayed sound.
*/
-extern AUD_Sound *AUD_delaySound(AUD_Sound *sound, float delay);
+extern AUD_Sound *AUD_Sound_delay(AUD_Sound *sound, float delay);
/**
* Limits a sound.
@@ -145,21 +149,21 @@ extern AUD_Sound *AUD_delaySound(AUD_Sound *sound, float delay);
* \param end The stop time in seconds.
* \return A handle of the limited sound.
*/
-extern AUD_Sound *AUD_limitSound(AUD_Sound *sound, float start, float end);
+extern AUD_Sound *AUD_Sound_limit(AUD_Sound *sound, float start, float end);
/**
* Ping pongs a sound.
* \param sound The sound to ping pong.
* \return A handle of the ping pong sound.
*/
-extern AUD_Sound *AUD_pingpongSound(AUD_Sound *sound);
+extern AUD_Sound *AUD_Sound_pingpong(AUD_Sound *sound);
/**
* Loops a sound.
* \param sound The sound to loop.
* \return A handle of the looped sound.
*/
-extern AUD_Sound *AUD_loopSound(AUD_Sound *sound);
+extern AUD_Sound *AUD_Sound_loop(AUD_Sound *sound);
/**
* Sets a remaining loop count of a looping sound that currently plays.
@@ -167,7 +171,7 @@ extern AUD_Sound *AUD_loopSound(AUD_Sound *sound);
* \param loops The count of remaining loops, -1 for infinity.
* \return Whether the handle is valid.
*/
-extern int AUD_setLoop(AUD_Handle *handle, int loops);
+extern int AUD_Handle_setLoopCount(AUD_Handle *handle, int loops);
/**
* Rectifies a sound.
@@ -180,7 +184,7 @@ extern AUD_Sound *AUD_rectifySound(AUD_Sound *sound);
* Unloads a sound of any type.
* \param sound The handle of the sound.
*/
-extern void AUD_unload(AUD_Sound *sound);
+extern void AUD_Sound_free(AUD_Sound *sound);
/**
* Plays back a sound file.
@@ -189,28 +193,30 @@ extern void AUD_unload(AUD_Sound *sound);
* paused when its end has been reached.
* \return A handle to the played back sound.
*/
-extern AUD_Handle *AUD_play(AUD_Sound *sound, int keep);
+extern AUD_Handle *AUD_Device_play(AUD_Device* device, AUD_Sound *sound, int keep);
/**
* Pauses a played back sound.
* \param handle The handle to the sound.
* \return Whether the handle has been playing or not.
*/
-extern int AUD_pause(AUD_Handle *handle);
+extern int AUD_Handle_pause(AUD_Handle *handle);
/**
* Resumes a paused sound.
* \param handle The handle to the sound.
* \return Whether the handle has been paused or not.
*/
-extern int AUD_resume(AUD_Handle *handle);
+extern int AUD_Handle_resume(AUD_Handle *handle);
/**
* Stops a playing or paused sound.
* \param handle The handle to the sound.
* \return Whether the handle has been valid or not.
*/
-extern int AUD_stop(AUD_Handle *handle);
+extern int AUD_Handle_stop(AUD_Handle *handle);
+
+extern void AUD_Device_stopAll(void* device);
/**
* Sets the end behaviour of a playing or paused sound.
@@ -219,7 +225,7 @@ extern int AUD_stop(AUD_Handle *handle);
* paused when its end has been reached.
* \return Whether the handle has been valid or not.
*/
-extern int AUD_setKeep(AUD_Handle *handle, int keep);
+extern int AUD_Handle_setKeep(AUD_Handle *handle, int keep);
/**
* Seeks a playing or paused sound.
@@ -227,7 +233,7 @@ extern int AUD_setKeep(AUD_Handle *handle, int keep);
* \param seekTo From where the sound file should be played back in seconds.
* \return Whether the handle has been valid or not.
*/
-extern int AUD_seek(AUD_Handle *handle, float seekTo);
+extern int AUD_Handle_setPosition(AUD_Handle *handle, float seekTo);
/**
* Retrieves the playback position of a handle.
@@ -235,39 +241,39 @@ extern int AUD_seek(AUD_Handle *handle, float seekTo);
* \return The current playback position in seconds or 0.0 if the handle is
* invalid.
*/
-extern float AUD_getPosition(AUD_Handle *handle);
+extern float AUD_Handle_getPosition(AUD_Handle *handle);
/**
* Returns the status of a playing, paused or stopped sound.
* \param handle The handle to the sound.
* \return The status of the sound behind the handle.
*/
-extern AUD_Status AUD_getStatus(AUD_Handle *handle);
+extern AUD_Status AUD_Handle_getStatus(AUD_Handle *handle);
/**
* Sets the listener location.
* \param location The new location.
*/
-extern int AUD_setListenerLocation(const float location[3]);
+extern int AUD_Device_setListenerLocation(const float location[3]);
/**
* Sets the listener velocity.
* \param velocity The new velocity.
*/
-extern int AUD_setListenerVelocity(const float velocity[3]);
+extern int AUD_Device_setListenerVelocity(const float velocity[3]);
/**
* Sets the listener orientation.
* \param orientation The new orientation as quaternion.
*/
-extern int AUD_setListenerOrientation(const float orientation[4]);
+extern int AUD_Device_setListenerOrientation(const float orientation[4]);
/**
* Sets the speed of sound.
* This value is needed for doppler effect calculation.
* \param speed The new speed of sound.
*/
-extern int AUD_setSpeedOfSound(float speed);
+extern int AUD_Device_setSpeedOfSound(void* device, float speed);
/**
* Sets the doppler factor.
@@ -275,13 +281,13 @@ extern int AUD_setSpeedOfSound(float speed);
* listener which is used while calculating the doppler effect.
* \param factor The new doppler factor.
*/
-extern int AUD_setDopplerFactor(float factor);
+extern int AUD_Device_setDopplerFactor(void* device, float factor);
/**
* Sets the distance model.
* \param model distance model.
*/
-extern int AUD_setDistanceModel(AUD_DistanceModel model);
+extern int AUD_Device_setDistanceModel(void* device, AUD_DistanceModel model);
/**
* Sets the location of a source.
@@ -289,7 +295,7 @@ extern int AUD_setDistanceModel(AUD_DistanceModel model);
* \param location The new location.
* \return Whether the action succeeded.
*/
-extern int AUD_setSourceLocation(AUD_Handle *handle, const float location[3]);
+extern int AUD_Handle_setLocation(AUD_Handle *handle, const float location[3]);
/**
* Sets the velocity of a source.
@@ -297,7 +303,7 @@ extern int AUD_setSourceLocation(AUD_Handle *handle, const float location[3]);
* \param velocity The new velocity.
* \return Whether the action succeeded.
*/
-extern int AUD_setSourceVelocity(AUD_Handle *handle, const float velocity[3]);
+extern int AUD_Handle_setVelocity(AUD_Handle *handle, const float velocity[3]);
/**
* Sets the orientation of a source.
@@ -305,7 +311,7 @@ extern int AUD_setSourceVelocity(AUD_Handle *handle, const float velocity[3]);
* \param orientation The new orientation as quaternion.
* \return Whether the action succeeded.
*/
-extern int AUD_setSourceOrientation(AUD_Handle *handle, const float orientation[4]);
+extern int AUD_Handle_setOrientation(AUD_Handle *handle, const float orientation[4]);
/**
* Sets whether the source location, velocity and orientation are relative
@@ -314,7 +320,7 @@ extern int AUD_setSourceOrientation(AUD_Handle *handle, const float orientation[
* \param relative Whether the source is relative.
* \return Whether the action succeeded.
*/
-extern int AUD_setRelative(AUD_Handle *handle, int relative);
+extern int AUD_Handle_setRelative(AUD_Handle *handle, int relative);
/**
* Sets the maximum volume of a source.
@@ -322,7 +328,7 @@ extern int AUD_setRelative(AUD_Handle *handle, int relative);
* \param volume The new maximum volume.
* \return Whether the action succeeded.
*/
-extern int AUD_setVolumeMaximum(AUD_Handle *handle, float volume);
+extern int AUD_Handle_setVolumeMaximum(AUD_Handle *handle, float volume);
/**
* Sets the minimum volume of a source.
@@ -330,7 +336,7 @@ extern int AUD_setVolumeMaximum(AUD_Handle *handle, float volume);
* \param volume The new minimum volume.
* \return Whether the action succeeded.
*/
-extern int AUD_setVolumeMinimum(AUD_Handle *handle, float volume);
+extern int AUD_Handle_setVolumeMinimum(AUD_Handle *handle, float volume);
/**
* Sets the maximum distance of a source.
@@ -340,7 +346,7 @@ extern int AUD_setVolumeMinimum(AUD_Handle *handle, float volume);
* \param distance The new maximum distance.
* \return Whether the action succeeded.
*/
-extern int AUD_setDistanceMaximum(AUD_Handle *handle, float distance);
+extern int AUD_Handle_setDistanceMaximum(AUD_Handle *handle, float distance);
/**
* Sets the reference distance of a source.
@@ -348,7 +354,7 @@ extern int AUD_setDistanceMaximum(AUD_Handle *handle, float distance);
* \param distance The new reference distance.
* \return Whether the action succeeded.
*/
-extern int AUD_setDistanceReference(AUD_Handle *handle, float distance);
+extern int AUD_Handle_setDistanceReference(AUD_Handle *handle, float distance);
/**
* Sets the attenuation of a source.
@@ -357,7 +363,7 @@ extern int AUD_setDistanceReference(AUD_Handle *handle, float distance);
* \param factor The new attenuation.
* \return Whether the action succeeded.
*/
-extern int AUD_setAttenuation(AUD_Handle *handle, float factor);
+extern int AUD_Handle_setAttenuation(AUD_Handle *handle, float factor);
/**
* Sets the outer angle of the cone of a source.
@@ -365,7 +371,7 @@ extern int AUD_setAttenuation(AUD_Handle *handle, float factor);
* \param angle The new outer angle of the cone.
* \return Whether the action succeeded.
*/
-extern int AUD_setConeAngleOuter(AUD_Handle *handle, float angle);
+extern int AUD_Handle_setConeAngleOuter(AUD_Handle *handle, float angle);
/**
* Sets the inner angle of the cone of a source.
@@ -373,7 +379,7 @@ extern int AUD_setConeAngleOuter(AUD_Handle *handle, float angle);
* \param angle The new inner angle of the cone.
* \return Whether the action succeeded.
*/
-extern int AUD_setConeAngleInner(AUD_Handle *handle, float angle);
+extern int AUD_Handle_setConeAngleInner(AUD_Handle *handle, float angle);
/**
* Sets the outer volume of the cone of a source.
@@ -383,7 +389,7 @@ extern int AUD_setConeAngleInner(AUD_Handle *handle, float angle);
* \param volume The new outer volume of the cone.
* \return Whether the action succeeded.
*/
-extern int AUD_setConeVolumeOuter(AUD_Handle *handle, float volume);
+extern int AUD_Handle_setConeVolumeOuter(AUD_Handle *handle, float volume);
/**
* Sets the volume of a played back sound.
@@ -391,7 +397,7 @@ extern int AUD_setConeVolumeOuter(AUD_Handle *handle, float volume);
* \param volume The new volume, must be between 0.0 and 1.0.
* \return Whether the action succeeded.
*/
-extern int AUD_setSoundVolume(AUD_Handle *handle, float volume);
+extern int AUD_Handle_setVolume(AUD_Handle *handle, float volume);
/**
* Sets the pitch of a played back sound.
@@ -399,7 +405,7 @@ extern int AUD_setSoundVolume(AUD_Handle *handle, float volume);
* \param pitch The new pitch.
* \return Whether the action succeeded.
*/
-extern int AUD_setSoundPitch(AUD_Handle *handle, float pitch);
+extern int AUD_Handle_setPitch(AUD_Handle *handle, float pitch);
/**
* Opens a read device, with which audio data can be read.
@@ -434,13 +440,13 @@ extern AUD_Handle *AUD_playDevice(AUD_Device *device, AUD_Sound *sound, float se
* played back currently, in that case the buffer is filled with
* silence.
*/
-extern int AUD_readDevice(AUD_Device *device, data_t *buffer, int length);
+extern int AUD_Device_read(AUD_Device *device, data_t *buffer, int length);
/**
* Closes a read device.
* \param device The read device.
*/
-extern void AUD_closeReadDevice(AUD_Device *device);
+extern void AUD_Device_free(AUD_Device *device);
/**
* Reads a sound file into a newly created float buffer.
@@ -466,27 +472,27 @@ extern AUD_Handle *AUD_pauseAfter(AUD_Handle *handle, float seconds);
* \param muted Whether the scene is muted.
* \return The new sound scene.
*/
-extern AUD_Sound *AUD_createSequencer(float fps, int muted);
+extern AUD_Sound *AUD_Sequence_create(float fps, int muted);
/**
* Deletes a sound scene.
* \param sequencer The sound scene.
*/
-extern void AUD_destroySequencer(AUD_Sound *sequencer);
+extern void AUD_Sequence_free(AUD_Sound *sequencer);
/**
* Sets the muting state of the scene.
* \param sequencer The sound scene.
* \param muted Whether the scene is muted.
*/
-extern void AUD_setSequencerMuted(AUD_Sound *sequencer, int muted);
+extern void AUD_Sequence_setMuted(AUD_Sound *sequencer, int muted);
/**
* Sets the scene's FPS.
* \param sequencer The sound scene.
* \param fps The new FPS.
*/
-extern void AUD_setSequencerFPS(AUD_Sound *sequencer, float fps);
+extern void AUD_Sequence_setFPS(AUD_Sound *sequencer, float fps);
/**
* Adds a new entry to the scene.
@@ -497,7 +503,7 @@ extern void AUD_setSequencerFPS(AUD_Sound *sequencer, float fps);
* \param skip How much seconds should be skipped at the beginning.
* \return The entry added.
*/
-extern AUD_SEntry *AUD_addSequence(AUD_Sound *sequencer, AUD_Sound *sound,
+extern AUD_SEntry *AUD_Sequence_add(AUD_Sound *sequencer, AUD_Sound *sound,
float begin, float end, float skip);
/**
@@ -505,7 +511,7 @@ extern AUD_SEntry *AUD_addSequence(AUD_Sound *sequencer, AUD_Sound *sound,
* \param sequencer The sound scene.
* \param entry The entry to remove.
*/
-extern void AUD_removeSequence(AUD_Sound *sequencer, AUD_SEntry *entry);
+extern void AUD_Sequence_remove(AUD_Sound *sequencer, AUD_SEntry *entry);
/**
* Moves the entry.
@@ -514,30 +520,21 @@ extern void AUD_removeSequence(AUD_Sound *sequencer, AUD_SEntry *entry);
* \param end The new end time or a negative value if unknown.
* \param skip How many seconds to skip at the beginning.
*/
-extern void AUD_moveSequence(AUD_SEntry *entry, float begin, float end, float skip);
+extern void AUD_SequenceEntry_move(AUD_SEntry *entry, float begin, float end, float skip);
/**
* Sets the muting state of the entry.
* \param entry The sequenced entry.
* \param mute Whether the entry should be muted or not.
*/
-extern void AUD_muteSequence(AUD_SEntry *entry, char mute);
-
-/**
- * Sets whether the entrie's location, velocity and orientation are relative
- * to the listener.
- * \param entry The sequenced entry.
- * \param relative Whether the source is relative.
- * \return Whether the action succeeded.
- */
-extern void AUD_setRelativeSequence(AUD_SEntry *entry, char relative);
+extern void AUD_SequenceEntry_setMuted(AUD_SEntry *entry, char mute);
/**
* Sets the sound of the entry.
* \param entry The sequenced entry.
* \param sound The new sound.
*/
-extern void AUD_updateSequenceSound(AUD_SEntry *entry, AUD_Sound *sound);
+extern void AUD_SequenceEntry_setSound(AUD_SEntry *entry, AUD_Sound *sound);
/**
* Writes animation data to a sequenced entry.
@@ -547,7 +544,7 @@ extern void AUD_updateSequenceSound(AUD_SEntry *entry, AUD_Sound *sound);
* \param data The data to write.
* \param animated Whether the attribute is animated.
*/
-extern void AUD_setSequenceAnimData(AUD_SEntry *entry, AUD_AnimateablePropertyType type, int frame, float *data, char animated);
+extern void AUD_SequenceEntry_setAnimationData(AUD_SEntry *entry, AUD_AnimateablePropertyType type, int frame, float *data, char animated);
/**
* Writes animation data to a sequenced entry.
@@ -557,33 +554,90 @@ extern void AUD_setSequenceAnimData(AUD_SEntry *entry, AUD_AnimateablePropertyTy
* \param data The data to write.
* \param animated Whether the attribute is animated.
*/
-extern void AUD_setSequencerAnimData(AUD_Sound *sequencer, AUD_AnimateablePropertyType type, int frame, float *data, char animated);
+extern void AUD_Sequence_setAnimationData(AUD_Sound *sequencer, AUD_AnimateablePropertyType type, int frame, float *data, char animated);
/**
- * Updates all non-animated parameters of the entry.
- * \param entry The sequenced entry.
- * \param volume_max The maximum volume.
- * \param volume_min The minimum volume.
- * \param distance_max The maximum distance.
- * \param distance_reference The reference distance.
- * \param attenuation The attenuation.
- * \param cone_angle_outer The outer cone opening angle.
- * \param cone_angle_inner The inner cone opening angle.
- * \param cone_volume_outer The volume outside the outer cone.
+ * Sets the distance model of a sequence.
+ * param sequence The sequence to set the distance model from.
+ * param value The new distance model to set.
*/
-extern void AUD_updateSequenceData(AUD_SEntry *entry, float volume_max, float volume_min,
- float distance_max, float distance_reference, float attenuation,
- float cone_angle_outer, float cone_angle_inner, float cone_volume_outer);
+extern void AUD_Sequence_setDistanceModel(AUD_Sound* sequence, AUD_DistanceModel value);
/**
- * Updates all non-animated parameters of the entry.
- * \param sequencer The sound scene.
- * \param speed_of_sound The speed of sound for doppler calculation.
- * \param factor The doppler factor to control the effect's strength.
- * \param model The distance model for distance calculation.
+ * Sets the doppler factor of a sequence.
+ * param sequence The sequence to set the doppler factor from.
+ * param value The new doppler factor to set.
*/
-extern void AUD_updateSequencerData(AUD_Sound *sequencer, float speed_of_sound,
- float factor, AUD_DistanceModel model);
+extern void AUD_Sequence_setDopplerFactor(AUD_Sound* sequence, float value);
+
+/**
+ * Sets the speed of sound of a sequence.
+ * param sequence The sequence to set the speed of sound from.
+ * param value The new speed of sound to set.
+ */
+extern void AUD_Sequence_setSpeedOfSound(AUD_Sound* sequence, float value);
+/**
+ * Sets the attenuation of a sequence_entry.
+ * param sequence_entry The sequence_entry to set the attenuation from.
+ * param value The new attenuation to set.
+ */
+extern void AUD_SequenceEntry_setAttenuation(AUD_SEntry* sequence_entry, float value);
+
+/**
+ * Sets the cone angle inner of a sequence_entry.
+ * param sequence_entry The sequence_entry to set the cone angle inner from.
+ * param value The new cone angle inner to set.
+ */
+extern void AUD_SequenceEntry_setConeAngleInner(AUD_SEntry* sequence_entry, float value);
+
+/**
+ * Sets the cone angle outer of a sequence_entry.
+ * param sequence_entry The sequence_entry to set the cone angle outer from.
+ * param value The new cone angle outer to set.
+ */
+extern void AUD_SequenceEntry_setConeAngleOuter(AUD_SEntry* sequence_entry, float value);
+
+/**
+ * Sets the cone volume outer of a sequence_entry.
+ * param sequence_entry The sequence_entry to set the cone volume outer from.
+ * param value The new cone volume outer to set.
+ */
+extern void AUD_SequenceEntry_setConeVolumeOuter(AUD_SEntry* sequence_entry, float value);
+
+/**
+ * Sets the distance maximum of a sequence_entry.
+ * param sequence_entry The sequence_entry to set the distance maximum from.
+ * param value The new distance maximum to set.
+ */
+extern void AUD_SequenceEntry_setDistanceMaximum(AUD_SEntry* sequence_entry, float value);
+
+/**
+ * Sets the distance reference of a sequence_entry.
+ * param sequence_entry The sequence_entry to set the distance reference from.
+ * param value The new distance reference to set.
+ */
+extern void AUD_SequenceEntry_setDistanceReference(AUD_SEntry* sequence_entry, float value);
+
+/**
+ * Sets the relative of a sequence_entry.
+ * param sequence_entry The sequence_entry to set the relative from.
+ * param value The new relative to set.
+ */
+extern void AUD_SequenceEntry_setRelative(AUD_SEntry* sequence_entry, int value);
+
+/**
+ * Sets the volume maximum of a sequence_entry.
+ * param sequence_entry The sequence_entry to set the volume maximum from.
+ * param value The new volume maximum to set.
+ */
+extern void AUD_SequenceEntry_setVolumeMaximum(AUD_SEntry* sequence_entry, float value);
+
+/**
+ * Sets the volume minimum of a sequence_entry.
+ * param sequence_entry The sequence_entry to set the volume minimum from.
+ * param value The new volume minimum to set.
+ */
+extern void AUD_SequenceEntry_setVolumeMinimum(AUD_SEntry* sequence_entry, float value);
/**
* Sets the audio output specification of the sound scene to the specs of the
@@ -597,31 +651,31 @@ extern void AUD_setSequencerDeviceSpecs(AUD_Sound *sequencer);
* \param sequencer The sound scene.
* \param specs The new specification.
*/
-extern void AUD_setSequencerSpecs(AUD_Sound *sequencer, AUD_Specs specs);
+extern void AUD_Sequence_setSpecs(AUD_Sound *sequencer, AUD_Specs specs);
/**
* Seeks sequenced sound scene playback.
* \param handle Playback handle.
* \param time Time in seconds to seek to.
*/
-extern void AUD_seekSequencer(AUD_Handle *handle, float time);
+extern void AUD_seekSynchronizer(AUD_Handle *handle, float time);
/**
* Returns the current sound scene playback time.
* \param handle Playback handle.
* \return The playback time in seconds.
*/
-extern float AUD_getSequencerPosition(AUD_Handle *handle);
+extern float AUD_getSynchronizerPosition(AUD_Handle *handle);
/**
* Starts the playback of jack transport if possible.
*/
-extern void AUD_startPlayback(void);
+extern void AUD_playSynchronizer(void);
/**
* Stops the playback of jack transport if possible.
*/
-extern void AUD_stopPlayback(void);
+extern void AUD_stopSynchronizer(void);
#ifdef WITH_JACK
/**
@@ -629,14 +683,14 @@ extern void AUD_stopPlayback(void);
* \param function The callback function.
* \param data The data parameter for the callback.
*/
-extern void AUD_setSyncCallback(AUD_syncFunction function, void *data);
+extern void AUD_setSynchronizerCallback(AUD_syncFunction function, void *data);
#endif
/**
* Returns whether jack transport is currently playing.
* \return Whether jack transport is currently playing.
*/
-extern int AUD_doesPlayback(void);
+extern int AUD_isSynchronizerPlaying(void);
/**
* Reads a sound into a buffer for drawing at a specific sampling rate.
@@ -646,20 +700,20 @@ extern int AUD_doesPlayback(void);
* \param samples_per_second How many samples to read per second of the sound.
* \return How many samples really have been read. Always <= length.
*/
-extern int AUD_readSound(AUD_Sound *sound, sample_t *buffer, int length, int samples_per_second);
+extern int AUD_readSound(AUD_Sound *sound, sample_t *buffer, int length, int samples_per_second, short *interrupt);
/**
* Copies a sound.
* \param sound Sound to copy.
* \return Copied sound.
*/
-extern AUD_Sound *AUD_copy(AUD_Sound *sound);
+extern AUD_Sound *AUD_Sound_copy(AUD_Sound *sound);
/**
* Frees a handle.
* \param channel Handle to free.
*/
-extern void AUD_freeHandle(AUD_Handle *channel);
+extern void AUD_Handle_free(AUD_Handle *channel);
/**
* Creates a new set.
@@ -747,36 +801,22 @@ extern AUD_Device *AUD_openMixdownDevice(AUD_DeviceSpecs specs, AUD_Sound *seque
* \param sound The sound factory.
* \return The python factory.
*/
-extern void *AUD_getPythonFactory(AUD_Sound *sound);
+extern void *AUD_getPythonSound(AUD_Sound *sound);
/**
* Retrieves the sound factory of a python factory.
* \param sound The python factory.
* \return The sound factory.
*/
-extern AUD_Sound *AUD_getPythonSound(void *sound);
+extern AUD_Sound *AUD_getSoundFromPython(void *sound);
#endif
+extern AUD_Device *AUD_Device_getCurrent(void);
+
extern int AUD_isJackSupported(void);
#ifdef __cplusplus
}
-
-#include <boost/shared_ptr.hpp>
-class AUD_IDevice;
-class AUD_I3DDevice;
-
-/**
- * Returns the current playback device.
- * \return The playback device.
- */
-boost::shared_ptr<AUD_IDevice> AUD_getDevice();
-
-/**
- * Returns the current playback 3D device.
- * \return The playback 3D device.
- */
-AUD_I3DDevice *AUD_get3DDevice();
#endif
#endif //__AUD_C_API_H__
diff --git a/intern/audaspace/intern/AUD_ConverterFunctions.h b/intern/audaspace/intern/AUD_ConverterFunctions.h
index 7817ee88c07..eca2b327b8c 100644
--- a/intern/audaspace/intern/AUD_ConverterFunctions.h
+++ b/intern/audaspace/intern/AUD_ConverterFunctions.h
@@ -33,16 +33,7 @@
#include "AUD_Space.h"
#include <cstring>
-#ifdef _MSC_VER
-#if (_MSC_VER <= 1500)
- typedef short int16_t;
- typedef int int32_t;
-#else
-# include <stdint.h>
-#endif
-#else
#include <stdint.h>
-#endif
typedef void (*AUD_convert_f)(data_t* target, data_t* source, int length);
diff --git a/intern/audaspace/intern/AUD_PyInit.cpp b/intern/audaspace/intern/AUD_PyInit.cpp
new file mode 100644
index 00000000000..4e27c31b838
--- /dev/null
+++ b/intern/audaspace/intern/AUD_PyInit.cpp
@@ -0,0 +1,78 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * Copyright 2009-2011 Jörg Hermann Müller
+ *
+ * This file is part of AudaSpace.
+ *
+ * Audaspace 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.
+ *
+ * AudaSpace 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 Audaspace; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file audaspace/intern/AUD_PyInit.cpp
+ * \ingroup audaspaceintern
+ */
+
+#include "AUD_PyInit.h"
+
+#include <AUD_Sound.h>
+#include <python/PySound.h>
+#include <python/PyAPI.h>
+
+extern "C" {
+extern void *BKE_sound_get_factory(void *sound);
+}
+
+static PyObject *AUD_getSoundFromPointer(PyObject *self, PyObject *args)
+{
+ long int lptr;
+
+ if (PyArg_Parse(args, "l:_sound_from_pointer", &lptr)) {
+ if (lptr) {
+ AUD_Sound* sound = BKE_sound_get_factory((void *) lptr);
+
+ if (sound) {
+ Sound *obj = (Sound *)Sound_empty();
+ if (obj) {
+ obj->sound = AUD_Sound_copy(sound);
+ return (PyObject *) obj;
+ }
+ }
+ }
+ }
+
+ Py_RETURN_NONE;
+}
+
+static PyMethodDef meth_sound_from_pointer[] = {
+ {"_sound_from_pointer", (PyCFunction)AUD_getSoundFromPointer, METH_O,
+ "_sound_from_pointer(pointer)\n\n"
+ "Returns the corresponding :class:`Factory` object.\n\n"
+ ":arg pointer: The pointer to the bSound object as long.\n"
+ ":type pointer: long\n"
+ ":return: The corresponding :class:`Factory` object.\n"
+ ":rtype: :class:`Factory`"}
+};
+
+PyObject *AUD_initPython(void)
+{
+ PyObject *module = PyInit_aud();
+ PyModule_AddObject(module, "_sound_from_pointer", (PyObject *)PyCFunction_New(meth_sound_from_pointer, NULL));
+ PyDict_SetItemString(PyImport_GetModuleDict(), "aud", module);
+
+ return module;
+}
+
diff --git a/intern/audaspace/intern/AUD_Sequencer.cpp b/intern/audaspace/intern/AUD_Sequencer.cpp
index 6c5e48c73f0..ddcf97e2ea1 100644
--- a/intern/audaspace/intern/AUD_Sequencer.cpp
+++ b/intern/audaspace/intern/AUD_Sequencer.cpp
@@ -39,7 +39,7 @@ AUD_Sequencer::AUD_Sequencer(AUD_Specs specs, float fps, bool muted) :
m_id(0),
m_muted(muted),
m_fps(fps),
- m_speed_of_sound(434),
+ m_speed_of_sound(343.3f),
m_doppler_factor(1),
m_distance_model(AUD_DISTANCE_MODEL_INVERSE_CLAMPED),
m_volume(1, 1.0f),
diff --git a/intern/audaspace/intern/AUD_SequencerHandle.cpp b/intern/audaspace/intern/AUD_SequencerHandle.cpp
index 135c960471c..aa742f7b8db 100644
--- a/intern/audaspace/intern/AUD_SequencerHandle.cpp
+++ b/intern/audaspace/intern/AUD_SequencerHandle.cpp
@@ -31,18 +31,99 @@
#include "AUD_ReadDevice.h"
#include "AUD_MutexLock.h"
+#define KEEP_TIME 10
+
+void AUD_SequencerHandle::start()
+{
+ // we already tried to start, aborting
+ if(!m_valid)
+ return;
+
+ // in case the sound is playing, we need to stop first
+ stop();
+
+ AUD_MutexLock lock(*m_entry);
+
+ // let's try playing
+ if(m_entry->m_sound.get())
+ {
+ try
+ {
+ m_handle = m_device.play(m_entry->m_sound, true);
+ m_3dhandle = boost::dynamic_pointer_cast<AUD_I3DHandle>(m_handle);
+ }
+ catch(AUD_Exception&)
+ {
+ // handle stays invalid in case we get an exception
+ }
+
+ // after starting we have to set the properties, so let's ensure that
+ m_status--;
+ }
+
+ // if the sound could not be played, we invalidate
+ m_valid = m_handle.get();
+}
+
+bool AUD_SequencerHandle::updatePosition(float position)
+{
+ AUD_MutexLock lock(*m_entry);
+
+ if(m_handle.get())
+ {
+ // we currently have a handle, let's check where we are
+ if(position >= m_entry->m_end)
+ {
+ if(position >= m_entry->m_end + KEEP_TIME)
+ // far end, stopping
+ stop();
+ else
+ {
+ // close end, just pausing
+ m_handle->pause();
+ return true;
+ }
+ }
+ else if(position >= m_entry->m_begin)
+ {
+ // inside, resuming
+ m_handle->resume();
+ return true;
+ }
+ else
+ {
+ if(position < m_entry->m_begin - KEEP_TIME)
+ // far beginning, stopping
+ stop();
+ else
+ {
+ // close beginning, just pausing
+ m_handle->pause();
+ return true;
+ }
+ }
+ }
+ else
+ {
+ // we don't have a handle, let's start if we should be playing
+ if(position >= m_entry->m_begin && position <= m_entry->m_end)
+ {
+ start();
+ return m_valid;
+ }
+ }
+
+ return false;
+}
+
AUD_SequencerHandle::AUD_SequencerHandle(boost::shared_ptr<AUD_SequencerEntry> entry, AUD_ReadDevice& device) :
m_entry(entry),
+ m_valid(true),
m_status(0),
m_pos_status(0),
m_sound_status(0),
m_device(device)
{
- if(entry->m_sound.get())
- {
- m_handle = device.play(entry->m_sound, true);
- m_3dhandle = boost::dynamic_pointer_cast<AUD_I3DHandle>(m_handle);
- }
}
AUD_SequencerHandle::~AUD_SequencerHandle()
@@ -63,101 +144,116 @@ void AUD_SequencerHandle::stop()
{
if(m_handle.get())
m_handle->stop();
+ m_handle = boost::shared_ptr<AUD_IHandle>();
+ m_3dhandle = boost::shared_ptr<AUD_I3DHandle>();
}
void AUD_SequencerHandle::update(float position, float frame, float fps)
{
- if(m_handle.get())
+ if(m_sound_status != m_entry->m_sound_status)
{
- AUD_MutexLock lock(*m_entry);
- if(position >= m_entry->m_end)
- m_handle->pause();
- else if(position >= m_entry->m_begin)
- m_handle->resume();
+ // if a new sound has been set, it's possible to get valid again!
+ m_sound_status = m_entry->m_sound_status;
+ m_valid = true;
- if(m_sound_status != m_entry->m_sound_status)
- {
- if(m_handle.get())
- m_handle->stop();
-
- if(m_entry->m_sound.get())
- {
- m_handle = m_device.play(m_entry->m_sound, true);
- m_3dhandle = boost::dynamic_pointer_cast<AUD_I3DHandle>(m_handle);
- }
+ // stop whatever sound has been playing
+ stop();
- m_sound_status = m_entry->m_sound_status;
- m_pos_status--;
- m_status--;
- }
+ // seek starts and seeks to the correct position
+ if(!seek(position))
+ // no handle, aborting
+ return;
+ }
+ else
+ {
+ if(!m_valid)
+ // invalid, aborting
+ return;
- if(m_pos_status != m_entry->m_pos_status)
+ if(m_handle.get())
{
- seek(position);
-
- m_pos_status = m_entry->m_pos_status;
+ // we have a handle, let's update the position
+ if(!updatePosition(position))
+ // lost handle, aborting
+ return;
}
-
- if(m_status != m_entry->m_status)
+ else
{
- m_3dhandle->setRelative(m_entry->m_relative);
- m_3dhandle->setVolumeMaximum(m_entry->m_volume_max);
- m_3dhandle->setVolumeMinimum(m_entry->m_volume_min);
- m_3dhandle->setDistanceMaximum(m_entry->m_distance_max);
- m_3dhandle->setDistanceReference(m_entry->m_distance_reference);
- m_3dhandle->setAttenuation(m_entry->m_attenuation);
- m_3dhandle->setConeAngleOuter(m_entry->m_cone_angle_outer);
- m_3dhandle->setConeAngleInner(m_entry->m_cone_angle_inner);
- m_3dhandle->setConeVolumeOuter(m_entry->m_cone_volume_outer);
-
- m_status = m_entry->m_status;
+ // we don't have a handle, let's see if we can start
+ if(!seek(position))
+ return;
}
+ }
- float value;
+ AUD_MutexLock lock(*m_entry);
+ if(m_pos_status != m_entry->m_pos_status)
+ {
+ m_pos_status = m_entry->m_pos_status;
- m_entry->m_volume.read(frame, &value);
- m_handle->setVolume(value);
- m_entry->m_pitch.read(frame, &value);
- m_handle->setPitch(value);
- m_entry->m_panning.read(frame, &value);
- AUD_SoftwareDevice::setPanning(m_handle.get(), value);
+ // position changed, need to seek
+ if(!seek(position))
+ // lost handle, aborting
+ return;
+ }
- AUD_Vector3 v, v2;
- AUD_Quaternion q;
+ // so far everything alright and handle is there, let's keep going
- m_entry->m_orientation.read(frame, q.get());
- m_3dhandle->setSourceOrientation(q);
- m_entry->m_location.read(frame, v.get());
- m_3dhandle->setSourceLocation(v);
- m_entry->m_location.read(frame + 1, v2.get());
- v2 -= v;
- m_3dhandle->setSourceVelocity(v2 * fps);
+ if(m_status != m_entry->m_status)
+ {
+ m_status = m_entry->m_status;
- if(m_entry->m_muted)
- m_handle->setVolume(0);
+ m_3dhandle->setRelative(m_entry->m_relative);
+ m_3dhandle->setVolumeMaximum(m_entry->m_volume_max);
+ m_3dhandle->setVolumeMinimum(m_entry->m_volume_min);
+ m_3dhandle->setDistanceMaximum(m_entry->m_distance_max);
+ m_3dhandle->setDistanceReference(m_entry->m_distance_reference);
+ m_3dhandle->setAttenuation(m_entry->m_attenuation);
+ m_3dhandle->setConeAngleOuter(m_entry->m_cone_angle_outer);
+ m_3dhandle->setConeAngleInner(m_entry->m_cone_angle_inner);
+ m_3dhandle->setConeVolumeOuter(m_entry->m_cone_volume_outer);
}
+
+ float value;
+
+ m_entry->m_volume.read(frame, &value);
+ m_handle->setVolume(value);
+ m_entry->m_pitch.read(frame, &value);
+ m_handle->setPitch(value);
+ m_entry->m_panning.read(frame, &value);
+ AUD_SoftwareDevice::setPanning(m_handle.get(), value);
+
+ AUD_Vector3 v, v2;
+ AUD_Quaternion q;
+
+ m_entry->m_orientation.read(frame, q.get());
+ m_3dhandle->setSourceOrientation(q);
+ m_entry->m_location.read(frame, v.get());
+ m_3dhandle->setSourceLocation(v);
+ m_entry->m_location.read(frame + 1, v2.get());
+ v2 -= v;
+ m_3dhandle->setSourceVelocity(v2 * fps);
+
+ if(m_entry->m_muted)
+ m_handle->setVolume(0);
}
-void AUD_SequencerHandle::seek(float position)
+bool AUD_SequencerHandle::seek(float position)
{
- if(m_handle.get())
- {
- AUD_MutexLock lock(*m_entry);
- if(position >= m_entry->m_end)
- {
- m_handle->pause();
- return;
- }
+ if(!m_valid)
+ // sound not valid, aborting
+ return false;
- float seekpos = position - m_entry->m_begin;
- if(seekpos < 0)
- seekpos = 0;
- seekpos += m_entry->m_skip;
- m_handle->setPitch(1.0f);
- m_handle->seek(seekpos);
- if(position < m_entry->m_begin)
- m_handle->pause();
- else
- m_handle->resume();
- }
+ if(!updatePosition(position))
+ // no handle, aborting
+ return false;
+
+ AUD_MutexLock lock(*m_entry);
+ float seekpos = position - m_entry->m_begin;
+ if(seekpos < 0)
+ seekpos = 0;
+ seekpos += m_entry->m_skip;
+ m_handle->setPitch(1.0f);
+ m_handle->seek(seekpos);
+
+ return true;
}
diff --git a/intern/audaspace/intern/AUD_SequencerHandle.h b/intern/audaspace/intern/AUD_SequencerHandle.h
index 881bbdd43dc..306df4a84b9 100644
--- a/intern/audaspace/intern/AUD_SequencerHandle.h
+++ b/intern/audaspace/intern/AUD_SequencerHandle.h
@@ -51,6 +51,9 @@ private:
/// The 3D handle in the read device.
boost::shared_ptr<AUD_I3DHandle> m_3dhandle;
+ /// Whether the sound is playable.
+ bool m_valid;
+
/// The last read status from the entry.
int m_status;
@@ -63,6 +66,18 @@ private:
/// The read device this handle is played on.
AUD_ReadDevice& m_device;
+ /**
+ * Starts playing back the handle.
+ */
+ void start();
+
+ /**
+ * Updates the handle state depending on position.
+ * \param position Current playback position in seconds.
+ * \return Whether the handle is valid.
+ */
+ bool updatePosition(float position);
+
public:
/**
* Creates a new sequenced handle.
@@ -99,8 +114,9 @@ public:
/**
* Seeks the handle to a specific time position.
* \param position The time to seek to.
+ * \return Whether the handle is valid.
*/
- void seek(float position);
+ bool seek(float position);
};
#endif //__AUD_SEQUENCERHANDLE_H__
diff --git a/intern/audaspace/intern/AUD_Set.cpp b/intern/audaspace/intern/AUD_Set.cpp
new file mode 100644
index 00000000000..eb04e37f666
--- /dev/null
+++ b/intern/audaspace/intern/AUD_Set.cpp
@@ -0,0 +1,69 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * Copyright 2009-2011 Jörg Hermann Müller
+ *
+ * This file is part of AudaSpace.
+ *
+ * Audaspace 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.
+ *
+ * AudaSpace 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 Audaspace; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file audaspace/intern/AUD_Set.cpp
+ * \ingroup audaspaceintern
+ */
+
+#include <set>
+
+#include "AUD_Set.h"
+
+void *AUD_createSet()
+{
+ return new std::set<void *>();
+}
+
+void AUD_destroySet(void *set)
+{
+ delete reinterpret_cast<std::set<void *>*>(set);
+}
+
+char AUD_removeSet(void *set, void *entry)
+{
+ if (set)
+ return reinterpret_cast<std::set<void *>*>(set)->erase(entry);
+ return 0;
+}
+
+void AUD_addSet(void *set, void *entry)
+{
+ if (entry)
+ reinterpret_cast<std::set<void *>*>(set)->insert(entry);
+}
+
+void *AUD_getSet(void *set)
+{
+ if (set) {
+ std::set<void *>* rset = reinterpret_cast<std::set<void *>*>(set);
+ if (!rset->empty()) {
+ std::set<void *>::iterator it = rset->begin();
+ void *result = *it;
+ rset->erase(it);
+ return result;
+ }
+ }
+
+ return (void*) 0;
+}
diff --git a/intern/audaspace/intern/AUD_Set.h b/intern/audaspace/intern/AUD_Set.h
new file mode 100644
index 00000000000..ca1419293b0
--- /dev/null
+++ b/intern/audaspace/intern/AUD_Set.h
@@ -0,0 +1,74 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * Copyright 2009-2011 Jörg Hermann Müller
+ *
+ * This file is part of AudaSpace.
+ *
+ * Audaspace 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.
+ *
+ * AudaSpace 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 Audaspace; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file AUD_Set.h
+ * \ingroup audaspace
+ */
+
+#ifndef __AUD_SET_H__
+#define __AUD_SET_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Creates a new set.
+ * \return The new set.
+ */
+extern void *AUD_createSet(void);
+
+/**
+ * Deletes a set.
+ * \param set The set to delete.
+ */
+extern void AUD_destroySet(void *set);
+
+/**
+ * Removes an entry from a set.
+ * \param set The set work on.
+ * \param entry The entry to remove.
+ * \return Whether the entry was in the set or not.
+ */
+extern char AUD_removeSet(void *set, void *entry);
+
+/**
+ * Adds a new entry to a set.
+ * \param set The set work on.
+ * \param entry The entry to add.
+ */
+extern void AUD_addSet(void *set, void *entry);
+
+/**
+ * Removes one entry from a set and returns it.
+ * \param set The set work on.
+ * \return The entry or NULL if the set is empty.
+ */
+extern void *AUD_getSet(void *set);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif //__AUD_SET_H__
diff --git a/intern/audaspace/intern/AUD_SoftwareDevice.cpp b/intern/audaspace/intern/AUD_SoftwareDevice.cpp
index 6ffa5e1fcae..c4277a6d02e 100644
--- a/intern/audaspace/intern/AUD_SoftwareDevice.cpp
+++ b/intern/audaspace/intern/AUD_SoftwareDevice.cpp
@@ -705,7 +705,7 @@ void AUD_SoftwareDevice::create()
m_playback = false;
m_volume = 1.0f;
m_mixer = boost::shared_ptr<AUD_Mixer>(new AUD_Mixer(m_specs));
- m_speed_of_sound = 343.0f;
+ m_speed_of_sound = 343.3f;
m_doppler_factor = 1.0f;
m_distance_model = AUD_DISTANCE_MODEL_INVERSE_CLAMPED;
m_flags = 0;
diff --git a/intern/cycles/CMakeLists.txt b/intern/cycles/CMakeLists.txt
index ae38fbb2934..5b68da79623 100644
--- a/intern/cycles/CMakeLists.txt
+++ b/intern/cycles/CMakeLists.txt
@@ -14,8 +14,19 @@ include(cmake/external_libs.cmake)
# todo: refactor this code to match scons
# note: CXX_HAS_SSE is needed in case passing SSE flags fails altogether (gcc-arm)
-if(WIN32 AND MSVC)
+if(WITH_CYCLES_WERROR)
+ ADD_CHECK_C_COMPILER_FLAG(CMAKE_C_FLAGS C_WERROR -Werror)
+ ADD_CHECK_CXX_COMPILER_FLAG(CMAKE_CXX_FLAGS C_WERROR -Werror)
+endif()
+
+if(NOT WITH_CPU_SSE)
+ set(CXX_HAS_SSE FALSE)
+ set(CXX_HAS_AVX FALSE)
+ set(CXX_HAS_AVX2 FALSE)
+elseif(WIN32 AND MSVC)
set(CXX_HAS_SSE TRUE)
+ set(CXX_HAS_AVX TRUE)
+ set(CXX_HAS_AVX2 TRUE)
# /arch:AVX for VC2012 and above
if(NOT MSVC_VERSION LESS 1700)
@@ -47,22 +58,34 @@ if(WIN32 AND MSVC)
set(CMAKE_CXX_FLAGS_MINSIZEREL "${CMAKE_CXX_FLAGS_MINSIZEREL} /Ox")
elseif(CMAKE_COMPILER_IS_GNUCC)
check_cxx_compiler_flag(-msse CXX_HAS_SSE)
+ check_cxx_compiler_flag(-mavx CXX_HAS_AVX)
+ check_cxx_compiler_flag(-mavx2 CXX_HAS_AVX2)
if(CXX_HAS_SSE)
set(CYCLES_SSE2_KERNEL_FLAGS "-ffast-math -msse -msse2 -mfpmath=sse")
set(CYCLES_SSE3_KERNEL_FLAGS "-ffast-math -msse -msse2 -msse3 -mssse3 -mfpmath=sse")
set(CYCLES_SSE41_KERNEL_FLAGS "-ffast-math -msse -msse2 -msse3 -mssse3 -msse4.1 -mfpmath=sse")
+ endif()
+ if(CXX_HAS_AVX)
set(CYCLES_AVX_KERNEL_FLAGS "-ffast-math -msse -msse2 -msse3 -mssse3 -msse4.1 -mavx -mfpmath=sse")
- set(CYCLES_AVX2_KERNEL_FLAGS "-ffast-math -msse -msse2 -msse3 -mssse3 -msse4.1 -mavx -mavx2 -mfma -mlzcnt -mbmi -mbmi2 -mfpmath=sse")
+ endif()
+ if(CXX_HAS_AVX2)
+ set(CYCLES_AVX2_KERNEL_FLAGS "-ffast-math -msse -msse2 -msse3 -mssse3 -msse4.1 -mavx -mavx2 -mfma -mlzcnt -mbmi -mbmi2 -mf16c -mfpmath=sse")
endif()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -ffast-math")
elseif(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
check_cxx_compiler_flag(-msse CXX_HAS_SSE)
+ check_cxx_compiler_flag(-mavx CXX_HAS_AVX)
+ check_cxx_compiler_flag(-mavx2 CXX_HAS_AVX2)
if(CXX_HAS_SSE)
set(CYCLES_SSE2_KERNEL_FLAGS "-ffast-math -msse -msse2")
set(CYCLES_SSE3_KERNEL_FLAGS "-ffast-math -msse -msse2 -msse3 -mssse3")
set(CYCLES_SSE41_KERNEL_FLAGS "-ffast-math -msse -msse2 -msse3 -mssse3 -msse4.1")
+ endif()
+ if(CXX_HAS_AVX)
set(CYCLES_AVX_KERNEL_FLAGS "-ffast-math -msse -msse2 -msse3 -mssse3 -msse4.1 -mavx")
- set(CYCLES_AVX2_KERNEL_FLAGS "-ffast-math -msse -msse2 -msse3 -mssse3 -msse4.1 -mavx -mavx2 -mfma -mlzcnt -mbmi -mbmi2")
+ endif()
+ if(CXX_HAS_AVX2)
+ set(CYCLES_AVX2_KERNEL_FLAGS "-ffast-math -msse -msse2 -msse3 -mssse3 -msse4.1 -mavx -mavx2 -mfma -mlzcnt -mbmi -mbmi2 -mf16c")
endif()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -ffast-math")
endif()
@@ -72,11 +95,17 @@ if(CXX_HAS_SSE)
-DWITH_KERNEL_SSE2
-DWITH_KERNEL_SSE3
-DWITH_KERNEL_SSE41
- -DWITH_KERNEL_AVX
- -DWITH_KERNEL_AVX2
)
endif()
+if(CXX_HAS_AVX)
+ add_definitions(-DWITH_KERNEL_AVX)
+endif()
+
+if(CXX_HAS_AVX2)
+ add_definitions(-DWITH_KERNEL_AVX2)
+endif()
+
if(WITH_CYCLES_OSL)
if(WIN32 AND MSVC)
set(RTTI_DISABLE_FLAGS "/GR- -DBOOST_NO_RTTI -DBOOST_NO_TYPEID")
@@ -118,7 +147,7 @@ if(WITH_CYCLES_OSL)
add_definitions(-DOSL_STATIC_LIBRARY)
include_directories(
SYSTEM
- ${OSL_INCLUDES}
+ ${OSL_INCLUDE_DIR}
)
endif()
@@ -128,22 +157,42 @@ add_definitions(
-DWITH_MULTI
)
+TEST_UNORDERED_MAP_SUPPORT()
+if(HAVE_STD_UNORDERED_MAP_HEADER)
+ if(HAVE_UNORDERED_MAP_IN_STD_NAMESPACE)
+ add_definitions(-DCYCLES_STD_UNORDERED_MAP)
+ else()
+ if(HAVE_UNORDERED_MAP_IN_TR1_NAMESPACE)
+ add_definitions(-DCYCLES_STD_UNORDERED_MAP_IN_TR1_NAMESPACE)
+ else()
+ add_definitions(-DCYCLES_NO_UNORDERED_MAP)
+ message(STATUS "Replacing unordered_map/set with map/set (warning: slower!)")
+ endif()
+ endif()
+else()
+ if(HAVE_UNORDERED_MAP_IN_TR1_NAMESPACE)
+ add_definitions(-DCYCLES_TR1_UNORDERED_MAP)
+ else()
+ add_definitions(-DCYCLES_NO_UNORDERED_MAP)
+ message(STATUS "Replacing unordered_map/set with map/set (warning: slower!)")
+ endif()
+endif()
+
+# Logging capabilities using GLog library.
if(WITH_CYCLES_LOGGING)
add_definitions(-DWITH_CYCLES_LOGGING)
add_definitions(-DGOOGLE_GLOG_DLL_DECL=)
- if(WIN32)
- include_directories(
- SYSTEM
- ../../extern/libmv/third_party/glog/src/windows
- ../../extern/libmv/third_party/gflags
- )
- else()
- include_directories(
- SYSTEM
- ../../extern/libmv/third_party/glog/src
- ../../extern/libmv/third_party/gflags
- )
- endif()
+ add_definitions(-DCYCLES_GFLAGS_NAMESPACE=${GFLAGS_NAMESPACE})
+ include_directories(
+ SYSTEM
+ ${GLOG_INCLUDE_DIRS}
+ ${GFLAGS_INCLUDE_DIRS}
+ )
+endif()
+
+# Debugging capabilities (debug passes etc).
+if(WITH_CYCLES_DEBUG)
+ add_definitions(-DWITH_CYCLES_DEBUG)
endif()
if(WITH_LIBMV)
@@ -160,13 +209,21 @@ include_directories(
${OPENIMAGEIO_INCLUDE_DIRS}/OpenImageIO
${OPENEXR_INCLUDE_DIR}
${OPENEXR_INCLUDE_DIRS}
+ ${PUGIXML_INCLUDE_DIR}
)
+if(CYCLES_STANDALONE_REPOSITORY)
+ include_directories(../third_party/atomic)
+else()
+ include_directories(../atomic)
+endif()
# Warnings
if(CMAKE_COMPILER_IS_GNUCXX)
ADD_CHECK_CXX_COMPILER_FLAG(CMAKE_CXX_FLAGS _has_cxxflag_float_conversion "-Werror=float-conversion")
+ ADD_CHECK_CXX_COMPILER_FLAG(CMAKE_CXX_FLAGS _has_cxxflag_double_promotion "-Werror=double-promotion")
unset(_has_cxxflag_float_conversion)
+ unset(_has_cxxflag_double_promotion)
endif()
diff --git a/intern/cycles/SConscript b/intern/cycles/SConscript
index 58685f599a5..11af440dfe8 100644
--- a/intern/cycles/SConscript
+++ b/intern/cycles/SConscript
@@ -34,18 +34,26 @@ cycles.Depends('../../source/blender/makesrna/intern/RNA_blender_cpp.h', 'makesr
sources = cycles.Glob('bvh/*.cpp') + cycles.Glob('device/*.cpp') + cycles.Glob('kernel/*.cpp') + cycles.Glob('render/*.cpp') + cycles.Glob('subd/*.cpp') + cycles.Glob('util/*.cpp') + cycles.Glob('blender/*.cpp')
+sources.append(path.join('kernel', 'kernels', 'cpu', 'kernel.cpp'))
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'))
-sources.remove(path.join('kernel', 'kernel_avx.cpp'))
-sources.remove(path.join('kernel', 'kernel_avx2.cpp'))
incs = []
defs = []
cxxflags = Split(env['CXXFLAGS'])
-defs.append('GLEW_STATIC')
+defs += env['BF_GL_DEFINITIONS']
+
+if env['WITH_UNORDERED_MAP_SUPPORT']:
+ if env['UNORDERED_MAP_HEADER'] == 'unordered_map':
+ if env['UNORDERED_MAP_NAMESPACE'] == 'std':
+ defs.append('CYCLES_STD_UNORDERED_MAP')
+ elif env['UNORDERED_MAP_NAMESPACE'] == 'std::tr1':
+ defs.append('CYCLES_STD_UNORDERED_MAP_IN_TR1_NAMESPACE')
+ elif env['UNORDERED_MAP_NAMESPACE'] == 'std::tr1':
+ defs.append('CYCLES_TR1_UNORDERED_MAP')
+else:
+ print("-- Replacing unordered_map/set with map/set (warning: slower!)")
+ defs.append('CYCLES_NO_UNORDERED_MAP')
defs.append('CCL_NAMESPACE_BEGIN=namespace ccl {')
defs.append('CCL_NAMESPACE_END=}')
@@ -63,10 +71,30 @@ if env['WITH_BF_LIBMV']:
defs.append('WITH_CYCLES_DISTORTION')
incs.append('#extern/libmv')
+if env['WITH_BF_CYCLES_DEBUG']:
+ defs.append('WITH_CYCLES_DEBUG')
+
+if env['WITH_BF_CYCLES_LOGGING']:
+ defs.append('WITH_CYCLES_LOGGING')
+ defs.append('GOOGLE_GLOG_DLL_DECL=')
+ defs.append('CYCLES_GFLAGS_NAMESPACE=gflags')
+ if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'linuxcross', 'win64-vc', 'win64-mingw'):
+ incs.append('#extern/libmv/third_party/glog/src/windows')
+ incs.append('#extern/libmv/third_party/gflags')
+ else:
+ incs.append('#extern/libmv/third_party/glog/src')
+ incs.append('#extern/libmv/third_party/gflags')
+
incs.extend('. bvh render device kernel kernel/osl kernel/svm util subd'.split())
incs.extend('#intern/guardedalloc #source/blender/makesrna #source/blender/makesdna #source/blender/blenlib'.split())
incs.extend('#source/blender/blenloader ../../source/blender/makesrna/intern'.split())
+
+incs.append(env['BF_GLEW_INC'])
+incs.append('#/intern/glew-mx')
+incs.append('#/intern/atomic')
+incs.append('#intern/mikktspace')
incs.extend('#extern/glew/include #extern/clew/include #extern/cuew/include #intern/mikktspace'.split())
+
incs.append(cycles['BF_OIIO_INC'])
incs.append(cycles['BF_BOOST_INC'])
incs.append(cycles['BF_OPENEXR_INC'].split())
@@ -112,13 +140,13 @@ else:
if (env['C_COMPILER_ID'] == 'gcc' and env['CCVERSION'] >= '4.6') or (env['C_COMPILER_ID'] == 'clang' and env['CCVERSION'] >= '3.1'):
kernel_flags['avx'] = kernel_flags['sse41'] + ' -mavx'
- kernel_flags['avx2'] = kernel_flags['avx'] + ' -mavx2 -mfma -mlzcnt -mbmi -mbmi2'
+ kernel_flags['avx2'] = kernel_flags['avx'] + ' -mavx2 -mfma -mlzcnt -mbmi -mbmi2 -mf16c'
for kernel_type in kernel_flags.keys():
defs.append('WITH_KERNEL_' + kernel_type.upper())
for kernel_type in kernel_flags.keys():
- kernel_source = path.join('kernel', 'kernel_' + kernel_type + '.cpp')
+ kernel_source = path.join('kernel', 'kernels', 'cpu', 'kernel_' + kernel_type + '.cpp')
kernel_cxxflags = Split(env['CXXFLAGS'])
kernel_cxxflags.append(kernel_flags[kernel_type].split())
kernel_defs = defs[:]
diff --git a/intern/cycles/app/CMakeLists.txt b/intern/cycles/app/CMakeLists.txt
index 5876ac3779c..b000266cac2 100644
--- a/intern/cycles/app/CMakeLists.txt
+++ b/intern/cycles/app/CMakeLists.txt
@@ -12,6 +12,8 @@ set(INC
set(INC_SYS
)
+# NOTE: LIBRARIES contains all the libraries which are common
+# across release and debug build types, stored in a linking order.
set(LIBRARIES
cycles_device
cycles_kernel
@@ -19,36 +21,85 @@ set(LIBRARIES
cycles_bvh
cycles_subd
cycles_util
- ${BOOST_LIBRARIES}
- ${OPENEXR_LIBRARIES}
- ${OPENGL_LIBRARIES}
- ${CYCLES_GLEW_LIBRARY}
- ${OPENIMAGEIO_LIBRARIES}
+ ${BLENDER_GL_LIBRARIES}
+ ${CYCLES_APP_GLEW_LIBRARY}
${PNG_LIBRARIES}
${JPEG_LIBRARIES}
${ZLIB_LIBRARIES}
${TIFF_LIBRARY}
+ ${PTHREADS_LIBRARIES}
extern_clew
extern_cuew
)
-if(WIN32)
- list(APPEND LIBRARIES ${PTHREADS_LIBRARIES})
+if(WITH_CYCLES_OSL)
+ list(APPEND LIBRARIES cycles_kernel_osl)
endif()
-link_directories(${OPENIMAGEIO_LIBPATH} ${BOOST_LIBPATH} ${PNG_LIBPATH} ${JPEG_LIBPATH} ${ZLIB_LIBPATH} ${TIFF_LIBPATH})
+if(CYCLES_STANDALONE_REPOSITORY)
+ if(WITH_CYCLES_LOGGING)
+ list(APPEND LIBRARIES
+ ${GLOG_LIBRARIES}
+ ${GFLAGS_LIBRARIES}
+ )
+ endif()
+else()
+ list(APPEND LIBRARIES bf_intern_glew_mx)
+ if(WITH_CYCLES_LOGGING)
+ list(APPEND LIBRARIES extern_glog)
+ endif()
+endif()
if(WITH_CYCLES_STANDALONE AND WITH_CYCLES_STANDALONE_GUI)
list(APPEND LIBRARIES ${GLUT_LIBRARIES})
endif()
-if(WITH_CYCLES_OSL)
- list(APPEND LIBRARIES cycles_kernel_osl ${OSL_LIBRARIES} ${LLVM_LIBRARY})
-endif()
+# Common configuration.
+
+link_directories(${OPENIMAGEIO_LIBPATH}
+ ${BOOST_LIBPATH}
+ ${PNG_LIBPATH}
+ ${JPEG_LIBPATH}
+ ${ZLIB_LIBPATH}
+ ${TIFF_LIBPATH}
+ ${OPENEXR_LIBPATH})
+
+add_definitions(${GL_DEFINITIONS})
include_directories(${INC})
include_directories(SYSTEM ${INC_SYS})
+# Make sure given target is linked against proper libraries
+# which varies across debug and release build types.
+#
+# This will also make sure dependencies of that libraries
+# are sent to the linker after them.
+#
+# TODO(sergey): Think of a better place for this?
+macro(cycles_target_link_libraries target)
+ target_link_libraries(${target} ${LIBRARIES})
+ if(WITH_CYCLES_OSL)
+ target_link_libraries_decoupled(${target} OSL_LIBRARIES)
+ if(MSVC)
+ target_link_libraries_debug(${target} "${LLVM_LIBRARIES_DEBUG}")
+ target_link_libraries_optimized(${target} "${LLVM_LIBRARIES}")
+ else()
+ target_link_libraries(${target} ${LLVM_LIBRARIES})
+ endif()
+ endif()
+ target_link_libraries_decoupled(${target} OPENIMAGEIO_LIBRARIES)
+ target_link_libraries_decoupled(${target} OPENEXR_LIBRARIES)
+ target_link_libraries(
+ ${target}
+ ${PUGIXML_LIBRARIES}
+ ${BOOST_LIBRARIES}
+ ${CMAKE_DL_LIBS}
+ ${PLATFORM_LINKLIBS}
+ )
+endmacro()
+
+# Application build targets
+
if(WITH_CYCLES_STANDALONE)
set(SRC
cycles_standalone.cpp
@@ -56,8 +107,7 @@ if(WITH_CYCLES_STANDALONE)
cycles_xml.h
)
add_executable(cycles ${SRC})
- list(APPEND LIBRARIES ${PLATFORM_LINKLIBS})
- target_link_libraries(cycles ${LIBRARIES} ${CMAKE_DL_LIBS})
+ cycles_target_link_libraries(cycles)
if(UNIX AND NOT APPLE)
set_target_properties(cycles PROPERTIES INSTALL_RPATH $ORIGIN/lib)
@@ -70,11 +120,10 @@ if(WITH_CYCLES_NETWORK)
cycles_server.cpp
)
add_executable(cycles_server ${SRC})
- target_link_libraries(cycles_server ${LIBRARIES} ${CMAKE_DL_LIBS})
+ cycles_target_link_libraries(cycles_server)
if(UNIX AND NOT APPLE)
set_target_properties(cycles_server PROPERTIES INSTALL_RPATH $ORIGIN/lib)
endif()
unset(SRC)
endif()
-
diff --git a/intern/cycles/app/cycles_server.cpp b/intern/cycles/app/cycles_server.cpp
index f4cacb2d001..4ef9cd070bb 100644
--- a/intern/cycles/app/cycles_server.cpp
+++ b/intern/cycles/app/cycles_server.cpp
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#include <stdio.h>
@@ -24,18 +24,20 @@
#include "util_stats.h"
#include "util_string.h"
#include "util_task.h"
+#include "util_logging.h"
using namespace ccl;
int main(int argc, const char **argv)
{
+ util_logging_init(argv[0]);
path_init();
/* device types */
string devicelist = "";
string devicename = "cpu";
- bool list = false;
- int threads = 0;
+ bool list = false, debug = false;
+ int threads = 0, verbosity = 1;
vector<DeviceType>& types = Device::available_types();
@@ -53,6 +55,10 @@ int main(int argc, const char **argv)
"--device %s", &devicename, ("Devices to use: " + devicelist).c_str(),
"--list-devices", &list, "List information about all available devices",
"--threads %d", &threads, "Number of threads to use for CPU device",
+#ifdef WITH_CYCLES_LOGGING
+ "--debug", &debug, "Enable debug logging",
+ "--verbose %d", &verbosity, "Set verbosity of the logger",
+#endif
NULL);
if(ap.parse(argc, argv) < 0) {
@@ -60,7 +66,13 @@ int main(int argc, const char **argv)
ap.usage();
exit(EXIT_FAILURE);
}
- else if(list) {
+
+ if(debug) {
+ util_logging_start();
+ util_logging_verbosity_set(verbosity);
+ }
+
+ if(list) {
vector<DeviceInfo>& devices = Device::available_devices();
printf("Devices:\n");
diff --git a/intern/cycles/app/cycles_standalone.cpp b/intern/cycles/app/cycles_standalone.cpp
index 90333eb3fc5..b0d49d6ee72 100644
--- a/intern/cycles/app/cycles_standalone.cpp
+++ b/intern/cycles/app/cycles_standalone.cpp
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#include <stdio.h>
@@ -21,10 +21,12 @@
#include "device.h"
#include "scene.h"
#include "session.h"
+#include "integrator.h"
#include "util_args.h"
#include "util_foreach.h"
#include "util_function.h"
+#include "util_logging.h"
#include "util_path.h"
#include "util_progress.h"
#include "util_string.h"
@@ -70,12 +72,12 @@ static void session_print(const string& str)
static void session_print_status()
{
int sample, tile;
- double total_time, sample_time;
+ double total_time, sample_time, render_time;
string status, substatus;
/* get status */
sample = options.session->progress.get_sample();
- options.session->progress.get_tile(tile, total_time, sample_time);
+ options.session->progress.get_tile(tile, total_time, sample_time, render_time);
options.session->progress.get_status(status, substatus);
if(substatus != "")
@@ -123,7 +125,7 @@ static void scene_init()
xml_read_file(options.scene, options.filepath.c_str());
/* Camera width/height override? */
- if (!(options.width == 0 || options.height == 0)) {
+ if(!(options.width == 0 || options.height == 0)) {
options.scene->camera->width = options.width;
options.scene->camera->height = options.height;
}
@@ -165,11 +167,11 @@ static void display_info(Progress& progress)
last = elapsed;
int sample, tile;
- double total_time, sample_time;
+ double total_time, sample_time, render_time;
string status, substatus;
sample = progress.get_sample();
- progress.get_tile(tile, total_time, sample_time);
+ progress.get_tile(tile, total_time, sample_time, render_time);
progress.get_status(status, substatus);
if(substatus != "")
@@ -271,6 +273,7 @@ static void keyboard(unsigned char key)
else if(key == 'i')
options.interactive = !(options.interactive);
+ /* Navigation */
else if(options.interactive && (key == 'w' || key == 'a' || key == 's' || key == 'd')) {
Transform matrix = options.session->scene->camera->matrix;
float3 translate;
@@ -293,6 +296,25 @@ static void keyboard(unsigned char key)
options.session->reset(session_buffer_params(), options.session_params.samples);
}
+
+ /* Set Max Bounces */
+ else if(options.interactive && (key == '0' || key == '1' || key == '2' || key == '3')) {
+ int bounce;
+ switch(key) {
+ case '0': bounce = 0; break;
+ case '1': bounce = 1; break;
+ case '2': bounce = 2; break;
+ case '3': bounce = 3; break;
+ default: bounce = 0; break;
+ }
+
+ options.session->scene->integrator->max_bounce = bounce;
+
+ /* Update and Reset */
+ options.session->scene->integrator->need_update = true;
+
+ options.session->reset(session_buffer_params(), options.session_params.samples);
+ }
}
#endif
@@ -319,6 +341,11 @@ static void options_parse(int argc, const char **argv)
vector<DeviceType>& types = Device::available_types();
+ /* TODO(sergey): Here's a feedback loop happens: on the one hand we want
+ * the device list to be printed in help message, on the other hand logging
+ * is not initialized yet so we wouldn't have debug log happening in the
+ * device initialization.
+ */
foreach(DeviceType type, types) {
if(device_names != "")
device_names += ", ";
@@ -331,7 +358,8 @@ static void options_parse(int argc, const char **argv)
/* parse options */
ArgParse ap;
- bool help = false;
+ bool help = false, debug = false;
+ int verbosity = 1;
ap.options ("Usage: cycles [options] file.xml",
"%*", files_parse, "",
@@ -347,6 +375,10 @@ static void options_parse(int argc, const char **argv)
"--width %d", &options.width, "Window width in pixel",
"--height %d", &options.height, "Window height in pixel",
"--list-devices", &list, "List information about all available devices",
+#ifdef WITH_CYCLES_LOGGING
+ "--debug", &debug, "Enable debug logging",
+ "--verbose %d", &verbosity, "Set verbosity of the logger",
+#endif
"--help", &help, "Print help message",
NULL);
@@ -355,12 +387,19 @@ static void options_parse(int argc, const char **argv)
ap.usage();
exit(EXIT_FAILURE);
}
- else if(list) {
+
+ if(debug) {
+ util_logging_start();
+ util_logging_verbosity_set(verbosity);
+ }
+
+ if(list) {
vector<DeviceInfo>& devices = Device::available_devices();
printf("Devices:\n");
foreach(DeviceInfo& info, devices) {
- printf(" %s%s\n",
+ printf(" %-10s%s%s\n",
+ Device::string_from_type(info.type).c_str(),
info.description.c_str(),
(info.display_device)? " (display)": "");
}
@@ -435,6 +474,7 @@ using namespace ccl;
int main(int argc, const char **argv)
{
+ util_logging_init(argv[0]);
path_init();
options_parse(argc, argv);
diff --git a/intern/cycles/app/cycles_xml.cpp b/intern/cycles/app/cycles_xml.cpp
index 431796e106b..edea8cd0ec4 100644
--- a/intern/cycles/app/cycles_xml.cpp
+++ b/intern/cycles/app/cycles_xml.cpp
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#include <stdio.h>
@@ -20,6 +20,7 @@
#include <algorithm>
#include <iterator>
+#include "background.h"
#include "camera.h"
#include "film.h"
#include "graph.h"
@@ -55,6 +56,16 @@ struct XMLReadState {
string base; /* base path to current file*/
float dicing_rate; /* current dicing rate */
Mesh::DisplacementMethod displacement_method;
+
+ XMLReadState()
+ : scene(NULL),
+ smooth(false),
+ shader(0),
+ dicing_rate(0.0f),
+ displacement_method(Mesh::DISPLACE_BUMP)
+ {
+ tfm = transform_identity();
+ }
};
/* Attribute Reading */
@@ -225,21 +236,21 @@ static ShaderSocketType xml_read_socket_type(pugi::xml_node node, const char *na
if(attr) {
string value = attr.value();
- if (string_iequals(value, "float"))
+ if(string_iequals(value, "float"))
return SHADER_SOCKET_FLOAT;
- else if (string_iequals(value, "int"))
+ else if(string_iequals(value, "int"))
return SHADER_SOCKET_INT;
- else if (string_iequals(value, "color"))
+ else if(string_iequals(value, "color"))
return SHADER_SOCKET_COLOR;
- else if (string_iequals(value, "vector"))
+ else if(string_iequals(value, "vector"))
return SHADER_SOCKET_VECTOR;
- else if (string_iequals(value, "point"))
+ else if(string_iequals(value, "point"))
return SHADER_SOCKET_POINT;
- else if (string_iequals(value, "normal"))
+ else if(string_iequals(value, "normal"))
return SHADER_SOCKET_NORMAL;
- else if (string_iequals(value, "closure color"))
+ else if(string_iequals(value, "closure color"))
return SHADER_SOCKET_CLOSURE;
- else if (string_iequals(value, "string"))
+ else if(string_iequals(value, "string"))
return SHADER_SOCKET_STRING;
else
fprintf(stderr, "Unknown shader socket type \"%s\" for attribute \"%s\".\n", value.c_str(), name);
@@ -299,7 +310,6 @@ static void xml_read_integrator(const XMLReadState& state, pugi::xml_node node)
xml_read_bool(&integrator->transparent_shadows, node, "transparent_shadows");
/* Volume */
- xml_read_int(&integrator->volume_homogeneous_sampling, node, "volume_homogeneous_sampling");
xml_read_float(&integrator->volume_step_size, node, "volume_step_size");
xml_read_int(&integrator->volume_max_steps, node, "volume_max_steps");
@@ -382,6 +392,10 @@ static void xml_read_shader_graph(const XMLReadState& state, Shader *shader, pug
for(pugi::xml_node node = graph_node.first_child(); node; node = node.next_sibling()) {
ShaderNode *snode = NULL;
+ /* ToDo: Add missing nodes
+ * RGBCurvesNode, VectorCurvesNode, RGBRampNode and ConvertNode (RGB -> BW).
+ */
+
if(string_iequals(node.name(), "image_texture")) {
ImageTextureNode *img = new ImageTextureNode();
@@ -392,6 +406,8 @@ static void xml_read_shader_graph(const XMLReadState& state, Shader *shader, pug
xml_read_enum(&img->projection, ImageTextureNode::projection_enum, node, "projection");
xml_read_float(&img->projection_blend, node, "projection_blend");
+ /* ToDo: Interpolation */
+
snode = img;
}
else if(string_iequals(node.name(), "environment_texture")) {
@@ -420,25 +436,25 @@ static void xml_read_shader_graph(const XMLReadState& state, Shader *shader, pug
* Socket names must be stored in the extra lists instead. */
/* read input values */
for(pugi::xml_node param = node.first_child(); param; param = param.next_sibling()) {
- if (string_iequals(param.name(), "input")) {
+ if(string_iequals(param.name(), "input")) {
string name;
- if (!xml_read_string(&name, param, "name"))
+ if(!xml_read_string(&name, param, "name"))
continue;
ShaderSocketType type = xml_read_socket_type(param, "type");
- if (type == SHADER_SOCKET_UNDEFINED)
+ if(type == SHADER_SOCKET_UNDEFINED)
continue;
osl->input_names.push_back(ustring(name));
osl->add_input(osl->input_names.back().c_str(), type);
}
- else if (string_iequals(param.name(), "output")) {
+ else if(string_iequals(param.name(), "output")) {
string name;
- if (!xml_read_string(&name, param, "name"))
+ if(!xml_read_string(&name, param, "name"))
continue;
ShaderSocketType type = xml_read_socket_type(param, "type");
- if (type == SHADER_SOCKET_UNDEFINED)
+ if(type == SHADER_SOCKET_UNDEFINED)
continue;
osl->output_names.push_back(ustring(name));
@@ -494,10 +510,6 @@ static void xml_read_shader_graph(const XMLReadState& state, Shader *shader, pug
xml_read_int(&magic->depth, node, "depth");
snode = magic;
}
- else if(string_iequals(node.name(), "noise_texture")) {
- NoiseTextureNode *dist = new NoiseTextureNode();
- snode = dist;
- }
else if(string_iequals(node.name(), "wave_texture")) {
WaveTextureNode *wave = new WaveTextureNode();
xml_read_enum(&wave->type, WaveTextureNode::type_enum, node, "type");
@@ -508,6 +520,11 @@ static void xml_read_shader_graph(const XMLReadState& state, Shader *shader, pug
xml_read_float3(&normal->direction, node, "direction");
snode = normal;
}
+ else if(string_iequals(node.name(), "bump")) {
+ BumpNode *bump = new BumpNode();
+ xml_read_bool(&bump->invert, node, "invert");
+ snode = bump;
+ }
else if(string_iequals(node.name(), "mapping")) {
snode = new MappingNode();
}
@@ -562,6 +579,9 @@ static void xml_read_shader_graph(const XMLReadState& state, Shader *shader, pug
else if(string_iequals(node.name(), "background")) {
snode = new BackgroundNode();
}
+ else if(string_iequals(node.name(), "holdout")) {
+ snode = new HoldoutNode();
+ }
else if(string_iequals(node.name(), "absorption_volume")) {
snode = new AbsorptionVolumeNode();
}
@@ -570,7 +590,14 @@ static void xml_read_shader_graph(const XMLReadState& state, Shader *shader, pug
}
else if(string_iequals(node.name(), "subsurface_scattering")) {
SubsurfaceScatteringNode *sss = new SubsurfaceScatteringNode();
- //xml_read_enum(&sss->falloff, SubsurfaceScatteringNode::falloff_enum, node, "falloff");
+
+ string falloff;
+ xml_read_string(&falloff, node, "falloff");
+ if(falloff == "cubic")
+ sss->closure = CLOSURE_BSSRDF_CUBIC_ID;
+ else
+ sss->closure = CLOSURE_BSSRDF_GAUSSIAN_ID;
+
snode = sss;
}
else if(string_iequals(node.name(), "geometry")) {
@@ -614,6 +641,7 @@ static void xml_read_shader_graph(const XMLReadState& state, Shader *shader, pug
snode = new InvertNode();
}
else if(string_iequals(node.name(), "mix")) {
+ /* ToDo: Tag Mix case for optimization */
MixNode *mix = new MixNode();
xml_read_enum(&mix->type, MixNode::type_enum, node, "type");
xml_read_bool(&mix->use_clamp, node, "use_clamp");
@@ -638,10 +666,10 @@ static void xml_read_shader_graph(const XMLReadState& state, Shader *shader, pug
snode = new SeparateHSVNode();
}
else if(string_iequals(node.name(), "combine_xyz")) {
- snode = new CombineHSVNode();
+ snode = new CombineXYZNode();
}
else if(string_iequals(node.name(), "separate_xyz")) {
- snode = new SeparateHSVNode();
+ snode = new SeparateXYZNode();
}
else if(string_iequals(node.name(), "hsv")) {
snode = new HSVNode();
@@ -803,7 +831,17 @@ static void xml_read_shader(const XMLReadState& state, pugi::xml_node node)
xml_read_string(&shader->name, node, "name");
xml_read_bool(&shader->use_mis, node, "use_mis");
xml_read_bool(&shader->use_transparent_shadow, node, "use_transparent_shadow");
+
+ /* Volume */
xml_read_bool(&shader->heterogeneous_volume, node, "heterogeneous_volume");
+ xml_read_int(&shader->volume_interpolation_method, node, "volume_interpolation_method");
+
+ if(xml_equal_string(node, "volume_sampling_method", "distance"))
+ shader->volume_sampling_method = VOLUME_SAMPLING_DISTANCE;
+ else if(xml_equal_string(node, "volume_sampling_method", "equiangular"))
+ shader->volume_sampling_method = VOLUME_SAMPLING_EQUIANGULAR;
+ else if(xml_equal_string(node, "volume_sampling_method", "multiple_importance"))
+ shader->volume_sampling_method = VOLUME_SAMPLING_MULTIPLE_IMPORTANCE;
xml_read_shader_graph(state, shader, node);
state.scene->shaders.push_back(shader);
@@ -813,9 +851,26 @@ static void xml_read_shader(const XMLReadState& state, pugi::xml_node node)
static void xml_read_background(const XMLReadState& state, pugi::xml_node node)
{
+ /* Background Settings */
+ Background *bg = state.scene->background;
+
+ xml_read_float(&bg->ao_distance, node, "ao_distance");
+ xml_read_float(&bg->ao_factor, node, "ao_factor");
+
+ xml_read_bool(&bg->transparent, node, "transparent");
+
+ /* Background Shader */
Shader *shader = state.scene->shaders[state.scene->default_background];
xml_read_bool(&shader->heterogeneous_volume, node, "heterogeneous_volume");
+ xml_read_int(&shader->volume_interpolation_method, node, "volume_interpolation_method");
+
+ if(xml_equal_string(node, "volume_sampling_method", "distance"))
+ shader->volume_sampling_method = VOLUME_SAMPLING_DISTANCE;
+ else if(xml_equal_string(node, "volume_sampling_method", "equiangular"))
+ shader->volume_sampling_method = VOLUME_SAMPLING_EQUIANGULAR;
+ else if(xml_equal_string(node, "volume_sampling_method", "multiple_importance"))
+ shader->volume_sampling_method = VOLUME_SAMPLING_MULTIPLE_IMPORTANCE;
xml_read_shader_graph(state, shader, node);
}
@@ -851,6 +906,7 @@ static void xml_read_mesh(const XMLReadState& state, pugi::xml_node node)
/* read vertices and polygons, RIB style */
vector<float3> P;
+ vector<float> UV;
vector<int> verts, nverts;
xml_read_float3_array(P, node, "P");
@@ -922,6 +978,31 @@ static void xml_read_mesh(const XMLReadState& state, pugi::xml_node node)
index_offset += nverts[i];
}
+
+ if(xml_read_float_array(UV, node, "UV")) {
+ ustring name = ustring("UVMap");
+ Attribute *attr = mesh->attributes.add(ATTR_STD_UV, name);
+ float3 *fdata = attr->data_float3();
+
+ /* loop over the triangles */
+ index_offset = 0;
+ for(size_t i = 0; i < nverts.size(); i++) {
+ for(int j = 0; j < nverts[i]-2; j++) {
+ int v0 = verts[index_offset];
+ int v1 = verts[index_offset + j + 1];
+ int v2 = verts[index_offset + j + 2];
+
+ assert(v0*2+1 < (int)UV.size());
+ assert(v1*2+1 < (int)UV.size());
+ assert(v2*2+1 < (int)UV.size());
+
+ fdata[0] = make_float3(UV[v0*2], UV[v0*2+1], 0.0);
+ fdata[1] = make_float3(UV[v1*2], UV[v1*2+1], 0.0);
+ fdata[2] = make_float3(UV[v2*2], UV[v2*2+1], 0.0);
+ fdata += 3;
+ }
+ }
+ }
}
/* temporary for test compatibility */
@@ -1011,13 +1092,28 @@ static void xml_read_light(const XMLReadState& state, pugi::xml_node node)
xml_read_float(&light->sizev, node, "sizev");
xml_read_float3(&light->axisu, node, "axisu");
xml_read_float3(&light->axisv, node, "axisv");
-
+
+ /* Portal? (Area light only) */
+ xml_read_bool(&light->is_portal, node, "is_portal");
+
/* Generic */
xml_read_float(&light->size, node, "size");
xml_read_float3(&light->dir, node, "dir");
xml_read_float3(&light->co, node, "P");
light->co = transform_point(&state.tfm, light->co);
+ /* Settings */
+ xml_read_bool(&light->cast_shadow, node, "cast_shadow");
+ xml_read_bool(&light->use_mis, node, "use_mis");
+ xml_read_int(&light->samples, node, "samples");
+ xml_read_int(&light->max_bounces, node, "max_bounces");
+
+ /* Ray Visibility */
+ xml_read_bool(&light->use_diffuse, node, "use_diffuse");
+ xml_read_bool(&light->use_glossy, node, "use_glossy");
+ xml_read_bool(&light->use_transmission, node, "use_transmission");
+ xml_read_bool(&light->use_scatter, node, "use_scatter");
+
state.scene->lights.push_back(light);
}
@@ -1161,7 +1257,8 @@ static void xml_read_include(const XMLReadState& state, const string& src)
XMLReadState substate = state;
substate.base = path_dirname(path);
- xml_read_scene(substate, doc);
+ pugi::xml_node cycles = doc.child("cycles");
+ xml_read_scene(substate, cycles);
}
else {
fprintf(stderr, "%s read error: %s\n", src.c_str(), parse_result.description());
diff --git a/intern/cycles/app/cycles_xml.h b/intern/cycles/app/cycles_xml.h
index 96bc79c35d8..6a48980d8ea 100644
--- a/intern/cycles/app/cycles_xml.h
+++ b/intern/cycles/app/cycles_xml.h
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#ifndef __CYCLES_XML_H__
diff --git a/intern/cycles/app/io_export_cycles_xml.py b/intern/cycles/app/io_export_cycles_xml.py
index ad8fb9d3dd3..7d6d85f88af 100644
--- a/intern/cycles/app/io_export_cycles_xml.py
+++ b/intern/cycles/app/io_export_cycles_xml.py
@@ -11,7 +11,7 @@
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
-# limitations under the License
+# limitations under the License.
#
# XML exporter for generating test files, not intended for end users
diff --git a/intern/cycles/blender/CCL_api.h b/intern/cycles/blender/CCL_api.h
index cfd0c3ef264..d3a68c4db4f 100644
--- a/intern/cycles/blender/CCL_api.h
+++ b/intern/cycles/blender/CCL_api.h
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#ifndef __CCL_API_H__
diff --git a/intern/cycles/blender/CMakeLists.txt b/intern/cycles/blender/CMakeLists.txt
index 6529d8186cc..7ca1277904e 100644
--- a/intern/cycles/blender/CMakeLists.txt
+++ b/intern/cycles/blender/CMakeLists.txt
@@ -6,6 +6,7 @@ set(INC
../kernel/svm
../util
../subd
+ ../../glew-mx
../../guardedalloc
../../mikktspace
../../../source/blender/makesdna
@@ -16,7 +17,7 @@ set(INC
set(INC_SYS
${PYTHON_INCLUDE_DIRS}
- ${GLEW_INCLUDE_PATH}
+ ${GLEW_INCLUDE_DIR}
)
set(SRC
@@ -31,10 +32,12 @@ set(SRC
blender_session.cpp
blender_shader.cpp
blender_sync.cpp
+ blender_texture.cpp
CCL_api.h
blender_sync.h
blender_session.h
+ blender_texture.h
blender_util.h
)
@@ -49,7 +52,7 @@ set(ADDON_FILES
addon/version_update.py
)
-add_definitions(-DGLEW_STATIC)
+add_definitions(${GL_DEFINITIONS})
blender_add_lib(bf_intern_cycles "${SRC}" "${INC}" "${INC_SYS}")
diff --git a/intern/cycles/blender/addon/__init__.py b/intern/cycles/blender/addon/__init__.py
index 415f6e81be8..7a9caa7b06b 100644
--- a/intern/cycles/blender/addon/__init__.py
+++ b/intern/cycles/blender/addon/__init__.py
@@ -11,7 +11,7 @@
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
-# limitations under the License
+# limitations under the License.
#
# <pep8 compliant>
@@ -49,26 +49,23 @@ class CyclesRender(bpy.types.RenderEngine):
# final render
def update(self, data, scene):
- if self.is_preview:
- if not self.session:
+ if not self.session:
+ if self.is_preview:
cscene = bpy.context.scene.cycles
use_osl = cscene.shading_system and cscene.device == 'CPU'
engine.create(self, data, scene,
None, None, None, use_osl)
- else:
- if not self.session:
- engine.create(self, data, scene)
else:
- engine.reset(self, data, scene)
-
- engine.update(self, data, scene)
+ engine.create(self, data, scene)
+ else:
+ engine.reset(self, data, scene)
def render(self, scene):
engine.render(self)
- def bake(self, scene, obj, pass_type, pixel_array, num_pixels, depth, result):
- engine.bake(self, obj, pass_type, pixel_array, num_pixels, depth, result)
+ def bake(self, scene, obj, pass_type, object_id, pixel_array, num_pixels, depth, result):
+ engine.bake(self, obj, pass_type, object_id, pixel_array, num_pixels, depth, result)
# viewport render
def view_update(self, context):
diff --git a/intern/cycles/blender/addon/engine.py b/intern/cycles/blender/addon/engine.py
index 18235eca790..030f0dbbf14 100644
--- a/intern/cycles/blender/addon/engine.py
+++ b/intern/cycles/blender/addon/engine.py
@@ -11,21 +11,67 @@
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
-# limitations under the License
+# limitations under the License.
#
# <pep8 compliant>
+def _is_using_buggy_driver():
+ import bgl
+ # We need to be conservative here because in multi-GPU systems display card
+ # might be quite old, but others one might be just good.
+ #
+ # So We shouldn't disable possible good dedicated cards just because display
+ # card seems weak. And instead we only blacklist configurations which are
+ # proven to cause problems.
+ if bgl.glGetString(bgl.GL_VENDOR) == "ATI Technologies Inc.":
+ import re
+ version = bgl.glGetString(bgl.GL_VERSION)
+ if version.endswith("Compatibility Profile Context"):
+ # Old HD 4xxx and 5xxx series drivers did not have driver version
+ # in the version string, but those cards do not quite work and
+ # causing crashes.
+ return True
+ regex = re.compile(".*Compatibility Profile Context ([0-9]+(\.[0-9]+)+)$")
+ if not regex.match(version):
+ # Skip cards like FireGL
+ return False
+ version = regex.sub("\\1", version).split('.')
+ return int(version[0]) == 8
+ return False
+
+
+def _workaround_buggy_drivers():
+ if _is_using_buggy_driver():
+ import _cycles
+ if hasattr(_cycles, "opencl_disable"):
+ print("Cycles: OpenGL driver known to be buggy, disabling OpenCL platform.")
+ _cycles.opencl_disable()
+
+
def init():
import bpy
import _cycles
import os.path
+ # Workaround possibly buggy legacy drivers which crashes on the OpenCL
+ # device enumeration.
+ #
+ # This checks are not really correct because they might still fail
+ # in the case of multiple GPUs. However, currently buggy drivers
+ # are really old and likely to be used in single GPU systems only
+ # anyway.
+ #
+ # Can't do it in the background mode, so we hope OpenCL is no enabled
+ # in the user preferences.
+ if not bpy.app.background:
+ _workaround_buggy_drivers()
+
path = os.path.dirname(__file__)
user_path = os.path.dirname(os.path.abspath(bpy.utils.user_resource('CONFIG', '')))
- _cycles.init(path, user_path)
+ _cycles.init(path, user_path, bpy.app.background)
def create(engine, data, scene, region=None, v3d=None, rv3d=None, preview_osl=False):
@@ -59,11 +105,11 @@ def render(engine):
_cycles.render(engine.session)
-def bake(engine, obj, pass_type, pixel_array, num_pixels, depth, result):
+def bake(engine, obj, pass_type, object_id, pixel_array, num_pixels, depth, result):
import _cycles
session = getattr(engine, "session", None)
if session is not None:
- _cycles.bake(engine.session, obj.as_pointer(), pass_type, pixel_array.as_pointer(), num_pixels, depth, result.as_pointer())
+ _cycles.bake(engine.session, obj.as_pointer(), pass_type, object_id, pixel_array.as_pointer(), num_pixels, depth, result.as_pointer())
def reset(engine, data, scene):
@@ -100,3 +146,8 @@ def with_osl():
def with_network():
import _cycles
return _cycles.with_network
+
+
+def system_info():
+ import _cycles
+ return _cycles.system_info()
diff --git a/intern/cycles/blender/addon/osl.py b/intern/cycles/blender/addon/osl.py
index c5f9d93013e..f4aaaab5eab 100644
--- a/intern/cycles/blender/addon/osl.py
+++ b/intern/cycles/blender/addon/osl.py
@@ -11,7 +11,7 @@
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
-# limitations under the License
+# limitations under the License.
#
# <pep8 compliant>
diff --git a/intern/cycles/blender/addon/presets.py b/intern/cycles/blender/addon/presets.py
index 2ec65d7183a..f97b51b629d 100644
--- a/intern/cycles/blender/addon/presets.py
+++ b/intern/cycles/blender/addon/presets.py
@@ -11,7 +11,7 @@
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
-# limitations under the License
+# limitations under the License.
#
# <pep8 compliant>
diff --git a/intern/cycles/blender/addon/properties.py b/intern/cycles/blender/addon/properties.py
index 12c1cd820be..c130594dbf7 100644
--- a/intern/cycles/blender/addon/properties.py
+++ b/intern/cycles/blender/addon/properties.py
@@ -11,7 +11,7 @@
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
-# limitations under the License
+# limitations under the License.
#
# <pep8 compliant>
@@ -59,7 +59,7 @@ enum_filter_types = (
enum_aperture_types = (
('RADIUS', "Radius", "Directly change the size of the aperture"),
- ('FSTOP', "F/stop", "Change the size of the aperture by f/stops"),
+ ('FSTOP', "F-stop", "Change the size of the aperture by f-stop"),
)
enum_panorama_types = (
@@ -67,6 +67,7 @@ enum_panorama_types = (
('FISHEYE_EQUIDISTANT', "Fisheye Equidistant", "Ideal for fulldomes, ignore the sensor dimensions"),
('FISHEYE_EQUISOLID', "Fisheye Equisolid",
"Similar to most fisheye modern lens, takes sensor dimensions into consideration"),
+ ('MIRRORBALL', "Mirror Ball", "Uses the mirror ball mapping"),
)
enum_curve_primitives = (
@@ -115,6 +116,11 @@ enum_volume_sampling = (
('MULTIPLE_IMPORTANCE', "Multiple Importance", "Combine distance and equi-angular sampling for volumes where neither method is ideal"),
)
+enum_volume_interpolation = (
+ ('LINEAR', "Linear", "Good smoothness and speed"),
+ ('CUBIC', "Cubic", "Smoothed high quality interpolation, but slower")
+ )
+
class CyclesRenderSettings(bpy.types.PropertyGroup):
@classmethod
@@ -346,7 +352,7 @@ class CyclesRenderSettings(bpy.types.PropertyGroup):
description="Distance between volume shader samples when rendering the volume "
"(lower values give more accurate and detailed results, but also increased render time)",
default=0.1,
- min=0.0000001, max=100000.0
+ min=0.0000001, max=100000.0, soft_min=0.01, soft_max=1.0
)
cls.volume_max_steps = IntProperty(
@@ -389,6 +395,12 @@ class CyclesRenderSettings(bpy.types.PropertyGroup):
default=0,
)
+ cls.use_animated_seed = BoolProperty(
+ name="Use Animated Seed",
+ description="Use different seed values (and hence noise patterns) at different frames",
+ default=False,
+ )
+
cls.sample_clamp_direct = FloatProperty(
name="Clamp Direct",
description="If non-zero, the maximum value for a direct sample, "
@@ -452,11 +464,6 @@ class CyclesRenderSettings(bpy.types.PropertyGroup):
description="Use BVH spatial splits: longer builder time, faster render",
default=False,
)
- cls.use_cache = BoolProperty(
- name="Cache BVH",
- description="Cache last built BVH to disk for faster re-render if no geometry changed",
- default=False,
- )
cls.tile_order = EnumProperty(
name="Tile Order",
description="Tile order for rendering",
@@ -477,7 +484,7 @@ class CyclesRenderSettings(bpy.types.PropertyGroup):
name="Bake Type",
default='COMBINED',
description="Type of pass to bake",
- items = (
+ items=(
('COMBINED', "Combined", ""),
('AO', "Ambient Occlusion", ""),
('SHADOW', "Shadow", ""),
@@ -500,6 +507,19 @@ class CyclesRenderSettings(bpy.types.PropertyGroup):
),
)
+ cls.use_camera_cull = BoolProperty(
+ name="Use Camera Cull",
+ description="Allow objects to be culled based on the camera frustum",
+ default=False,
+ )
+
+ cls.camera_cull_margin = FloatProperty(
+ name="Camera Cull Margin",
+ description="Margin for the camera space culling",
+ default=0.1,
+ min=0.0, max=5.0
+ )
+
@classmethod
def unregister(cls):
del bpy.types.Scene.cycles
@@ -518,13 +538,13 @@ class CyclesCameraSettings(bpy.types.PropertyGroup):
cls.aperture_type = EnumProperty(
name="Aperture Type",
- description="Use F/stop number or aperture radius",
+ description="Use f-stop number or aperture radius",
items=enum_aperture_types,
default='RADIUS',
)
cls.aperture_fstop = FloatProperty(
- name="Aperture F/stop",
- description="F/stop ratio (lower numbers give more defocus, higher numbers give a sharper image)",
+ name="Aperture f-stop",
+ description="F-stop ratio (lower numbers give more defocus, higher numbers give a sharper image)",
min=0.0, soft_min=0.1, soft_max=64.0,
default=5.6,
step=10,
@@ -578,6 +598,34 @@ class CyclesCameraSettings(bpy.types.PropertyGroup):
min=0.01, soft_max=15.0, max=100.0,
default=10.5,
)
+ cls.latitude_min = FloatProperty(
+ name="Min Latitude",
+ description="Minimum latitude (vertical angle) for the equirectangular lens",
+ min=-0.5 * math.pi, max=0.5 * math.pi,
+ subtype='ANGLE',
+ default=-0.5 * math.pi,
+ )
+ cls.latitude_max = FloatProperty(
+ name="Max Latitude",
+ description="Maximum latitude (vertical angle) for the equirectangular lens",
+ min=-0.5 * math.pi, max=0.5 * math.pi,
+ subtype='ANGLE',
+ default=0.5 * math.pi,
+ )
+ cls.longitude_min = FloatProperty(
+ name="Min Longitude",
+ description="Minimum longitude (horizontal angle) for the equirectangular lens",
+ min=-math.pi, max=math.pi,
+ subtype='ANGLE',
+ default=-math.pi,
+ )
+ cls.longitude_max = FloatProperty(
+ name="Max Longitude",
+ description="Maximum longitude (horizontal angle) for the equirectangular lens",
+ min=-math.pi, max=math.pi,
+ subtype='ANGLE',
+ default=math.pi,
+ )
cls.nodes = StringProperty(
name="nodes",
description="Camera ray nodes")
@@ -621,6 +669,13 @@ class CyclesMaterialSettings(bpy.types.PropertyGroup):
default='DISTANCE',
)
+ cls.volume_interpolation = EnumProperty(
+ name="Volume Interpolation",
+ description="Interpolation method to use for smoke/fire volumes",
+ items=enum_volume_interpolation,
+ default='LINEAR',
+ )
+
@classmethod
def unregister(cls):
del bpy.types.Material.cycles
@@ -645,12 +700,24 @@ class CyclesLampSettings(bpy.types.PropertyGroup):
min=1, max=10000,
default=1,
)
+ cls.max_bounces = IntProperty(
+ name="Max Bounces",
+ description="Maximum number of bounces the light will contribute to the render",
+ min=0, max=1024,
+ default=1024,
+ )
cls.use_multiple_importance_sampling = BoolProperty(
name="Multiple Importance Sample",
description="Use multiple importance sampling for the lamp, "
"reduces noise for area lamps and sharp glossy materials",
default=False,
)
+ cls.is_portal = BoolProperty(
+ name="Is Portal",
+ description="Use this area lamp to guide sampling of the background, "
+ "note that this will make the lamp invisible",
+ default=False,
+ )
@classmethod
def unregister(cls):
@@ -675,7 +742,7 @@ class CyclesWorldSettings(bpy.types.PropertyGroup):
name="Map Resolution",
description="Importance map size is resolution x resolution; "
"higher values potentially produce less noise, at the cost of memory and speed",
- min=4, max=8096,
+ min=4, max=8192,
default=256,
)
cls.samples = IntProperty(
@@ -684,6 +751,12 @@ class CyclesWorldSettings(bpy.types.PropertyGroup):
min=1, max=10000,
default=4,
)
+ cls.max_bounces = IntProperty(
+ name="Max Bounces",
+ description="Maximum number of bounces the background light will contribute to the render",
+ min=0, max=1024,
+ default=1024,
+ )
cls.homogeneous_volume = BoolProperty(
name="Homogeneous Volume",
description="When using volume rendering, assume volume has the same density everywhere"
@@ -697,6 +770,13 @@ class CyclesWorldSettings(bpy.types.PropertyGroup):
default='EQUIANGULAR',
)
+ cls.volume_interpolation = EnumProperty(
+ name="Volume Interpolation",
+ description="Interpolation method to use for volumes",
+ items=enum_volume_interpolation,
+ default='LINEAR',
+ )
+
@classmethod
def unregister(cls):
del bpy.types.World.cycles
@@ -828,6 +908,12 @@ class CyclesObjectBlurSettings(bpy.types.PropertyGroup):
default=1,
)
+ cls.use_camera_cull = BoolProperty(
+ name="Use Camera Cull",
+ description="Allow this object and its duplicators to be culled by camera space culling",
+ default=False,
+ )
+
@classmethod
def unregister(cls):
del bpy.types.Object.cycles
diff --git a/intern/cycles/blender/addon/ui.py b/intern/cycles/blender/addon/ui.py
index b544c476c11..a44a0b46960 100644
--- a/intern/cycles/blender/addon/ui.py
+++ b/intern/cycles/blender/addon/ui.py
@@ -11,14 +11,18 @@
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
-# limitations under the License
+# limitations under the License.
#
# <pep8 compliant>
import bpy
-from bpy.types import Panel, Menu, Operator
+from bpy.types import (
+ Panel,
+ Menu,
+ Operator,
+ )
class CYCLES_MT_sampling_presets(Menu):
@@ -37,7 +41,7 @@ class CYCLES_MT_integrator_presets(Menu):
draw = Menu.draw_preset
-class CyclesButtonsPanel():
+class CyclesButtonsPanel:
bl_space_type = "PROPERTIES"
bl_region_type = "WINDOW"
bl_context = "render"
@@ -56,7 +60,15 @@ def use_cpu(context):
return (device_type == 'NONE' or cscene.device == 'CPU')
-def draw_samples_info(layout, cscene):
+def use_branched_path(context):
+ cscene = context.scene.cycles
+ device_type = context.user_preferences.system.compute_device_type
+
+ return (cscene.progressive == 'BRANCHED_PATH' and device_type != 'OPENCL')
+
+
+def draw_samples_info(layout, context):
+ cscene = context.scene.cycles
integrator = cscene.progressive
# Calculate sample values
@@ -86,7 +98,7 @@ def draw_samples_info(layout, cscene):
# Draw interface
# Do not draw for progressive, when Square Samples are disabled
- if (integrator == 'BRANCHED_PATH') or (cscene.use_square_samples and integrator == 'PATH'):
+ if use_branched_path(context) or (cscene.use_square_samples and integrator == 'PATH'):
col = layout.column(align=True)
col.scale_y = 0.6
col.label("Total Samples:")
@@ -110,6 +122,7 @@ class CyclesRender_PT_sampling(CyclesButtonsPanel, Panel):
scene = context.scene
cscene = scene.cycles
+ device_type = context.user_preferences.system.compute_device_type
row = layout.row(align=True)
row.menu("CYCLES_MT_sampling_presets", text=bpy.types.CYCLES_MT_sampling_presets.bl_label)
@@ -117,7 +130,9 @@ class CyclesRender_PT_sampling(CyclesButtonsPanel, Panel):
row.operator("render.cycles_sampling_preset_add", text="", icon="ZOOMOUT").remove_active = True
row = layout.row()
- row.prop(cscene, "progressive", text="")
+ sub = row.row()
+ sub.active = device_type != 'OPENCL'
+ sub.prop(cscene, "progressive", text="")
row.prop(cscene, "use_square_samples")
split = layout.split()
@@ -125,11 +140,15 @@ class CyclesRender_PT_sampling(CyclesButtonsPanel, Panel):
col = split.column()
sub = col.column(align=True)
sub.label("Settings:")
- sub.prop(cscene, "seed")
+
+ seed_sub = sub.row(align=True)
+ seed_sub.prop(cscene, "seed")
+ seed_sub.prop(cscene, "use_animated_seed", text="", icon="TIME")
+
sub.prop(cscene, "sample_clamp_direct")
sub.prop(cscene, "sample_clamp_indirect")
- if cscene.progressive == 'PATH':
+ if cscene.progressive == 'PATH' or use_branched_path(context) == False:
col = split.column()
sub = col.column(align=True)
sub.label(text="Samples:")
@@ -163,7 +182,7 @@ class CyclesRender_PT_sampling(CyclesButtonsPanel, Panel):
layout.row().prop(cscene, "use_layer_samples")
break
- draw_samples_info(layout, cscene)
+ draw_samples_info(layout, context)
class CyclesRender_PT_volume_sampling(CyclesButtonsPanel, Panel):
@@ -313,7 +332,6 @@ class CyclesRender_PT_performance(CyclesButtonsPanel, Panel):
col.separator()
col.label(text="Final Render:")
- col.prop(cscene, "use_cache")
col.prop(rd, "use_persistent_data", text="Persistent Images")
col.separator()
@@ -412,6 +430,52 @@ class CyclesRender_PT_layer_passes(CyclesButtonsPanel, Panel):
col.prop(rl, "use_pass_emit", text="Emission")
col.prop(rl, "use_pass_environment")
+ if hasattr(rd, "debug_pass_type"):
+ layout.prop(rd, "debug_pass_type")
+
+
+class CyclesRender_PT_views(CyclesButtonsPanel, Panel):
+ bl_label = "Views"
+ bl_context = "render_layer"
+ bl_options = {'DEFAULT_CLOSED'}
+
+ def draw_header(self, context):
+ rd = context.scene.render
+ self.layout.prop(rd, "use_multiview", text="")
+
+ def draw(self, context):
+ layout = self.layout
+
+ scene = context.scene
+ rd = scene.render
+ rv = rd.views.active
+
+ layout.active = rd.use_multiview
+ basic_stereo = (rd.views_format == 'STEREO_3D')
+
+ row = layout.row()
+ row.prop(rd, "views_format", expand=True)
+
+ if basic_stereo:
+ row = layout.row()
+ row.template_list("RENDERLAYER_UL_renderviews", "name", rd, "stereo_views", rd.views, "active_index", rows=2)
+
+ row = layout.row()
+ row.label(text="File Suffix:")
+ row.prop(rv, "file_suffix", text="")
+
+ else:
+ row = layout.row()
+ row.template_list("RENDERLAYER_UL_renderviews", "name", rd, "views", rd.views, "active_index", rows=2)
+
+ col = row.column(align=True)
+ col.operator("scene.render_view_add", icon='ZOOMIN', text="")
+ col.operator("scene.render_view_remove", icon='ZOOMOUT', text="")
+
+ row = layout.row()
+ row.label(text="Camera Suffix:")
+ row.prop(rv, "camera_suffix", text="")
+
class Cycles_PT_post_processing(CyclesButtonsPanel, Panel):
bl_label = "Post Processing"
@@ -445,6 +509,7 @@ class CyclesCamera_PT_dof(CyclesButtonsPanel, Panel):
cam = context.camera
ccam = cam.cycles
+ dof_options = cam.gpu_dof
split = layout.split()
@@ -456,6 +521,16 @@ class CyclesCamera_PT_dof(CyclesButtonsPanel, Panel):
sub.active = cam.dof_object is None
sub.prop(cam, "dof_distance", text="Distance")
+ hq_support = dof_options.is_hq_supported
+ sub = col.column(align=True)
+ sub.label("Viewport:")
+ subhq = sub.column()
+ subhq.active = hq_support
+ subhq.prop(dof_options, "use_high_quality")
+ sub.prop(dof_options, "fstop")
+ if dof_options.use_high_quality and hq_support:
+ sub.prop(dof_options, "blades")
+
col = split.column()
col.label("Aperture:")
@@ -506,11 +581,16 @@ class Cycles_PT_context_material(CyclesButtonsPanel, Panel):
ob = context.object
slot = context.material_slot
space = context.space_data
+ is_sortable = len(ob.material_slots) > 1
if ob:
+ rows = 1
+ if (is_sortable):
+ rows = 4
+
row = layout.row()
- row.template_list("MATERIAL_UL_matslots", "", ob, "material_slots", ob, "active_material_index", rows=1)
+ row.template_list("MATERIAL_UL_matslots", "", ob, "material_slots", ob, "active_material_index", rows=rows)
col = row.column(align=True)
col.operator("object.material_slot_add", icon='ZOOMIN', text="")
@@ -518,6 +598,12 @@ class Cycles_PT_context_material(CyclesButtonsPanel, Panel):
col.menu("MATERIAL_MT_specials", icon='DOWNARROW_HLT', text="")
+ if is_sortable:
+ col.separator()
+
+ col.operator("object.material_slot_move", icon='TRIA_UP', text="").direction = 'UP'
+ col.operator("object.material_slot_move", icon='TRIA_DOWN', text="").direction = 'DOWN'
+
if ob.mode == 'EDIT':
row = layout.row(align=True)
row.operator("object.material_slot_assign", text="Assign")
@@ -579,7 +665,13 @@ class CyclesObject_PT_motion_blur(CyclesButtonsPanel, Panel):
@classmethod
def poll(cls, context):
ob = context.object
- return CyclesButtonsPanel.poll(context) and ob and ob.type in {'MESH', 'CURVE', 'CURVE', 'SURFACE', 'FONT', 'META'}
+ if CyclesButtonsPanel.poll(context) and ob:
+ if ob.type in {'MESH', 'CURVE', 'CURVE', 'SURFACE', 'FONT', 'META'}:
+ return True
+ if ob.dupli_type == 'GROUP' and ob.dupli_group:
+ return True
+ # TODO(sergey): More duplicator types here?
+ return False
def draw_header(self, context):
layout = self.layout
@@ -613,8 +705,8 @@ class CyclesObject_PT_motion_blur(CyclesButtonsPanel, Panel):
sub.prop(cob, "motion_steps", text="Steps")
-class CyclesObject_PT_ray_visibility(CyclesButtonsPanel, Panel):
- bl_label = "Ray Visibility"
+class CyclesObject_PT_cycles_settings(CyclesButtonsPanel, Panel):
+ bl_label = "Cycles Settings"
bl_context = "object"
bl_options = {'DEFAULT_CLOSED'}
@@ -622,15 +714,19 @@ class CyclesObject_PT_ray_visibility(CyclesButtonsPanel, Panel):
def poll(cls, context):
ob = context.object
return (CyclesButtonsPanel.poll(context) and
- ob and ob.type in {'MESH', 'CURVE', 'SURFACE', 'FONT', 'META', 'LAMP'} or
- ob and ob.dupli_type == 'GROUP' and ob.dupli_group)
+ ob and ((ob.type in {'MESH', 'CURVE', 'SURFACE', 'FONT', 'META', 'LAMP'}) or
+ (ob.dupli_type == 'GROUP' and ob.dupli_group)))
def draw(self, context):
layout = self.layout
+ scene = context.scene
+ cscene = scene.cycles
ob = context.object
+ cob = ob.cycles
visibility = ob.cycles_visibility
+ layout.label(text="Ray Visibility:")
flow = layout.column_flow()
flow.prop(visibility, "camera")
@@ -642,6 +738,12 @@ class CyclesObject_PT_ray_visibility(CyclesButtonsPanel, Panel):
if ob.type != 'LAMP':
flow.prop(visibility, "shadow")
+ col = layout.column()
+ col.label(text="Performance:")
+ row = col.row()
+ row.active = scene.render.use_simplify and cscene.use_camera_cull
+ row.prop(cob, "use_camera_cull")
+
class CYCLES_OT_use_shading_nodes(Operator):
"""Enable nodes on a material, world or lamp"""
@@ -668,9 +770,14 @@ def find_node(material, nodetype):
if material and material.node_tree:
ntree = material.node_tree
+ active_output_node = None
for node in ntree.nodes:
if getattr(node, "type", None) == nodetype:
- return node
+ if getattr(node, "is_active_output", True):
+ return node
+ if not active_output_node:
+ active_output_node = node
+ return active_output_node
return None
@@ -707,7 +814,10 @@ class CyclesLamp_PT_preview(CyclesButtonsPanel, Panel):
@classmethod
def poll(cls, context):
- return context.lamp and CyclesButtonsPanel.poll(context)
+ return context.lamp and \
+ not (context.lamp.type == 'AREA' and
+ context.lamp.cycles.is_portal) \
+ and CyclesButtonsPanel.poll(context)
def draw(self, context):
self.layout.template_preview(context.lamp)
@@ -745,13 +855,21 @@ class CyclesLamp_PT_lamp(CyclesButtonsPanel, Panel):
sub.prop(lamp, "size", text="Size X")
sub.prop(lamp, "size_y", text="Size Y")
- if cscene.progressive == 'BRANCHED_PATH':
- col.prop(clamp, "samples")
+ if not (lamp.type == 'AREA' and clamp.is_portal):
+ sub = col.column(align=True)
+ if use_branched_path(context):
+ sub.prop(clamp, "samples")
+ sub.prop(clamp, "max_bounces")
col = split.column()
- col.prop(clamp, "cast_shadow")
- layout.prop(clamp, "use_multiple_importance_sampling")
+ sub = col.column(align=True)
+ sub.active = not (lamp.type == 'AREA' and clamp.is_portal)
+ sub.prop(clamp, "cast_shadow")
+ sub.prop(clamp, "use_multiple_importance_sampling", text="Multiple Importance")
+
+ if lamp.type == 'AREA':
+ col.prop(clamp, "is_portal", text="Portal")
if lamp.type == 'HEMI':
layout.label(text="Not supported, interpreted as sun lamp")
@@ -763,7 +881,9 @@ class CyclesLamp_PT_nodes(CyclesButtonsPanel, Panel):
@classmethod
def poll(cls, context):
- return context.lamp and CyclesButtonsPanel.poll(context)
+ return context.lamp and not (context.lamp.type == 'AREA' and
+ context.lamp.cycles.is_portal) and \
+ CyclesButtonsPanel.poll(context)
def draw(self, context):
layout = self.layout
@@ -946,14 +1066,16 @@ class CyclesWorld_PT_settings(CyclesButtonsPanel, Panel):
sub = col.column(align=True)
sub.active = cworld.sample_as_light
sub.prop(cworld, "sample_map_resolution")
- if cscene.progressive == 'BRANCHED_PATH':
+ if use_branched_path(context):
sub.prop(cworld, "samples")
+ sub.prop(cworld, "max_bounces")
col = split.column()
col.label(text="Volume:")
sub = col.column()
sub.active = use_cpu(context)
sub.prop(cworld, "volume_sampling", text="")
+ sub.prop(cworld, "volume_interpolation", text="")
col.prop(cworld, "homogeneous_volume", text="Homogeneous")
@@ -1037,17 +1159,6 @@ class CyclesMaterial_PT_settings(CyclesButtonsPanel, Panel):
cmat = mat.cycles
split = layout.split()
-
- col = split.column(align=True)
- col.prop(mat, "diffuse_color", text="Viewport Color")
- col.prop(mat, "alpha")
-
- col = split.column(align=True)
- col.label()
- col.prop(mat, "pass_index")
-
- split = layout.split()
-
col = split.column()
col.label(text="Surface:")
col.prop(cmat, "sample_as_light", text="Multiple Importance")
@@ -1058,8 +1169,29 @@ class CyclesMaterial_PT_settings(CyclesButtonsPanel, Panel):
sub = col.column()
sub.active = use_cpu(context)
sub.prop(cmat, "volume_sampling", text="")
+ sub.prop(cmat, "volume_interpolation", text="")
col.prop(cmat, "homogeneous_volume", text="Homogeneous")
+ layout.separator()
+ split = layout.split()
+
+ col = split.column(align=True)
+ col.label("Viewport Color:")
+ col.prop(mat, "diffuse_color", text="")
+ col.prop(mat, "alpha")
+
+ col.separator()
+ col.label("Viewport Alpha:")
+ col.prop(mat.game_settings, "alpha_blend", text="")
+
+ col = split.column(align=True)
+ col.label("Viewport Specular:")
+ col.prop(mat, "specular_color", text="")
+ col.prop(mat, "specular_hardness", text="Hardness")
+
+ col.separator()
+ col.prop(mat, "pass_index")
+
class CyclesTexture_PT_context(CyclesButtonsPanel, Panel):
bl_label = ""
@@ -1126,7 +1258,8 @@ class CyclesTexture_PT_mapping(CyclesButtonsPanel, Panel):
@classmethod
def poll(cls, context):
node = context.texture_node
- return node and CyclesButtonsPanel.poll(context)
+ # TODO(sergey): perform a faster/nicer check?
+ return node and hasattr(node, 'texture_mapping') and CyclesButtonsPanel.poll(context)
def draw(self, context):
layout = self.layout
@@ -1350,13 +1483,28 @@ class CyclesScene_PT_simplify(CyclesButtonsPanel, Panel):
def draw(self, context):
layout = self.layout
- rd = context.scene.render
+ scene = context.scene
+ rd = scene.render
+ cscene = scene.cycles
layout.active = rd.use_simplify
+ split = layout.split()
- row = layout.row()
- row.prop(rd, "simplify_subdivision", text="Subdivision")
- row.prop(rd, "simplify_child_particles", text="Child Particles")
+ col = split.column()
+ col.label(text="Viewport:")
+ col.prop(rd, "simplify_subdivision", text="Subdivision")
+ col.prop(rd, "simplify_child_particles", text="Child Particles")
+
+ col = split.column()
+ col.label(text="Render:")
+ col.prop(rd, "simplify_subdivision_render", text="Subdivision")
+ col.prop(rd, "simplify_child_particles_render", text="Child Particles")
+
+ col = layout.column()
+ col.prop(cscene, "use_camera_cull")
+ subsub = col.column()
+ subsub.active = cscene.use_camera_cull
+ subsub.prop(cscene, "camera_cull_margin")
def draw_device(self, context):
@@ -1399,7 +1547,11 @@ def get_panels():
"RENDER_PT_encoding",
"RENDER_PT_dimensions",
"RENDER_PT_stamp",
+ "RENDER_PT_freestyle",
"RENDERLAYER_PT_layers",
+ "RENDERLAYER_PT_freestyle",
+ "RENDERLAYER_PT_freestyle_lineset",
+ "RENDERLAYER_PT_freestyle_linestyle",
"SCENE_PT_scene",
"SCENE_PT_color_management",
"SCENE_PT_custom_props",
@@ -1424,6 +1576,8 @@ def get_panels():
"DATA_PT_vertex_colors",
"DATA_PT_camera",
"DATA_PT_camera_display",
+ "DATA_PT_camera_stereoscopy",
+ "DATA_PT_camera_safe_areas",
"DATA_PT_lens",
"DATA_PT_speaker",
"DATA_PT_distance",
@@ -1437,6 +1591,7 @@ def get_panels():
"DATA_PT_custom_props_curve",
"DATA_PT_custom_props_lattice",
"DATA_PT_custom_props_metaball",
+ "TEXTURE_PT_preview",
"TEXTURE_PT_custom_props",
"TEXTURE_PT_clouds",
"TEXTURE_PT_wood",
@@ -1454,6 +1609,7 @@ def get_panels():
"TEXTURE_PT_pointdensity",
"TEXTURE_PT_pointdensity_turbulence",
"TEXTURE_PT_mapping",
+ "TEXTURE_PT_ocean",
"TEXTURE_PT_influence",
"TEXTURE_PT_colors",
"PARTICLE_PT_context_particles",
@@ -1475,6 +1631,7 @@ def get_panels():
"PARTICLE_PT_force_fields",
"PARTICLE_PT_vertexgroups",
"MATERIAL_PT_custom_props",
+ "MATERIAL_PT_freestyle_line",
"BONE_PT_custom_props",
"OBJECT_PT_custom_props",
]
diff --git a/intern/cycles/blender/addon/version_update.py b/intern/cycles/blender/addon/version_update.py
index eaeec703ff5..2fbb01ba5b8 100644
--- a/intern/cycles/blender/addon/version_update.py
+++ b/intern/cycles/blender/addon/version_update.py
@@ -11,7 +11,7 @@
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
-# limitations under the License
+# limitations under the License.
#
# <pep8 compliant>
@@ -21,6 +21,85 @@ import bpy
from bpy.app.handlers import persistent
+def check_is_new_shading_ntree(node_tree):
+ for node in node_tree.nodes:
+ # If material has any node with ONLY new shading system
+ # compatibility then it's considered a Cycles material
+ # and versioning code would need to perform on it.
+ #
+ # We can not check for whether NEW_SHADING in compatibility
+ # because some nodes could have compatibility with both old
+ # and new shading system and they can't be used for any
+ # decision here.
+ if node.shading_compatibility == {'NEW_SHADING'}:
+ return True
+
+ # If node is only compatible with old shading system
+ # then material can not be Cycles material and we
+ # can stopiterating nodes now.
+ if node.shading_compatibility == {'OLD_SHADING'}:
+ return False
+ return False
+
+
+def check_is_new_shading_material(material):
+ if not material.node_tree:
+ return False
+ return check_is_new_shading_ntree(material.node_tree)
+
+
+def check_is_new_shading_world(world):
+ if not world.node_tree:
+ return False
+ return check_is_new_shading_ntree(world.node_tree)
+
+
+def check_is_new_shading_lamp(lamp):
+ if not lamp.node_tree:
+ return False
+ return check_is_new_shading_ntree(lamp.node_tree)
+
+
+def foreach_notree_node(nodetree, callback, traversed):
+ if nodetree in traversed:
+ return
+ traversed.add(nodetree)
+ for node in nodetree.nodes:
+ callback(node)
+ if node.bl_idname == 'ShaderNodeGroup':
+ foreach_notree_node(node.node_tree, callback, traversed)
+
+
+def foreach_cycles_node(callback):
+ traversed = set()
+ for material in bpy.data.materials:
+ if check_is_new_shading_material(material):
+ foreach_notree_node(material.node_tree,
+ callback,
+ traversed)
+ for world in bpy.data.worlds:
+ if check_is_new_shading_world(world):
+ foreach_notree_node(world.node_tree,
+ callback,
+ traversed)
+ for lamp in bpy.data.lamps:
+ if check_is_new_shading_world(lamp):
+ foreach_notree_node(lamp.node_tree,
+ callback,
+ traversed)
+
+
+def mapping_node_order_flip(node):
+ """
+ Flip euler order of mapping shader node
+ """
+ if node.bl_idname == 'ShaderNodeMapping':
+ rot = node.rotation.copy()
+ rot.order = 'ZYX'
+ quat = rot.to_quaternion()
+ node.rotation = quat.to_euler('XYZ')
+
+
@persistent
def do_versions(self):
# We don't modify startup file because it assumes to
@@ -57,3 +136,7 @@ def do_versions(self):
cscene.caustics_reflective = False
cscene.caustics_refractive = False
+
+ # Euler order was ZYX in previous versions.
+ if bpy.data.version <= (2, 73, 4):
+ foreach_cycles_node(mapping_node_order_flip)
diff --git a/intern/cycles/blender/blender_camera.cpp b/intern/cycles/blender/blender_camera.cpp
index d26317b6e32..d45dc62a1e0 100644
--- a/intern/cycles/blender/blender_camera.cpp
+++ b/intern/cycles/blender/blender_camera.cpp
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#include "camera.h"
@@ -20,6 +20,8 @@
#include "blender_sync.h"
#include "blender_util.h"
+#include "util_logging.h"
+
CCL_NAMESPACE_BEGIN
/* Blender Camera Intermediate: we first convert both the offline and 3d view
@@ -51,6 +53,10 @@ struct BlenderCamera {
PanoramaType panorama_type;
float fisheye_fov;
float fisheye_lens;
+ float latitude_min;
+ float latitude_max;
+ float longitude_min;
+ float longitude_max;
enum { AUTO, HORIZONTAL, VERTICAL } sensor_fit;
float sensor_width;
@@ -61,11 +67,12 @@ struct BlenderCamera {
BoundBox2D border;
BoundBox2D pano_viewplane;
+ BoundBox2D viewport_camera_border;
Transform matrix;
};
-static void blender_camera_init(BlenderCamera *bcam, BL::RenderSettings b_render, BL::Scene b_scene)
+static void blender_camera_init(BlenderCamera *bcam, BL::RenderSettings b_render)
{
memset(bcam, 0, sizeof(BlenderCamera));
@@ -80,13 +87,15 @@ static void blender_camera_init(BlenderCamera *bcam, BL::RenderSettings b_render
bcam->border.top = 1.0f;
bcam->pano_viewplane.right = 1.0f;
bcam->pano_viewplane.top = 1.0f;
+ bcam->viewport_camera_border.right = 1.0f;
+ bcam->viewport_camera_border.top = 1.0f;
/* render resolution */
bcam->full_width = render_resolution_x(b_render);
bcam->full_height = render_resolution_y(b_render);
}
-static float blender_camera_focal_distance(BL::Object b_ob, BL::Camera b_camera)
+static float blender_camera_focal_distance(BL::RenderEngine b_engine, BL::Object b_ob, BL::Camera b_camera)
{
BL::Object b_dof_object = b_camera.dof_object();
@@ -94,14 +103,16 @@ static float blender_camera_focal_distance(BL::Object b_ob, BL::Camera b_camera)
return b_camera.dof_distance();
/* for dof object, return distance along camera Z direction */
- Transform obmat = transform_clear_scale(get_transform(b_ob.matrix_world()));
+ BL::Array<float, 16> b_ob_matrix;
+ b_engine.camera_model_matrix(b_ob, b_ob_matrix);
+ Transform obmat = get_transform(b_ob_matrix);
Transform dofmat = get_transform(b_dof_object.matrix_world());
- Transform mat = transform_inverse(obmat) * dofmat;
-
- return fabsf(transform_get_column(&mat, 3).z);
+ float3 view_dir = normalize(transform_get_column(&obmat, 2));
+ float3 dof_dir = transform_get_column(&obmat, 3) - transform_get_column(&dofmat, 3);
+ return fabsf(dot(view_dir, dof_dir));
}
-static void blender_camera_from_object(BlenderCamera *bcam, BL::Object b_ob, bool skip_panorama = false)
+static void blender_camera_from_object(BlenderCamera *bcam, BL::RenderEngine b_engine, BL::Object b_ob, bool skip_panorama = false)
{
BL::ID b_ob_data = b_ob.data();
@@ -137,6 +148,9 @@ static void blender_camera_from_object(BlenderCamera *bcam, BL::Object b_ob, boo
case 2:
bcam->panorama_type = PANORAMA_FISHEYE_EQUISOLID;
break;
+ case 3:
+ bcam->panorama_type = PANORAMA_MIRRORBALL;
+ break;
case 0:
default:
bcam->panorama_type = PANORAMA_EQUIRECTANGULAR;
@@ -145,6 +159,10 @@ static void blender_camera_from_object(BlenderCamera *bcam, BL::Object b_ob, boo
bcam->fisheye_fov = RNA_float_get(&ccamera, "fisheye_fov");
bcam->fisheye_lens = RNA_float_get(&ccamera, "fisheye_lens");
+ bcam->latitude_min = RNA_float_get(&ccamera, "latitude_min");
+ bcam->latitude_max = RNA_float_get(&ccamera, "latitude_max");
+ bcam->longitude_min = RNA_float_get(&ccamera, "longitude_min");
+ bcam->longitude_max = RNA_float_get(&ccamera, "longitude_max");
bcam->ortho_scale = b_camera.ortho_scale();
@@ -168,10 +186,10 @@ static void blender_camera_from_object(BlenderCamera *bcam, BL::Object b_ob, boo
bcam->apertureblades = RNA_int_get(&ccamera, "aperture_blades");
bcam->aperturerotation = RNA_float_get(&ccamera, "aperture_rotation");
- bcam->focaldistance = blender_camera_focal_distance(b_ob, b_camera);
+ bcam->focaldistance = blender_camera_focal_distance(b_engine, b_ob, b_camera);
bcam->aperture_ratio = RNA_float_get(&ccamera, "aperture_ratio");
- bcam->shift.x = b_camera.shift_x();
+ bcam->shift.x = b_engine.camera_shift_x(b_ob);
bcam->shift.y = b_camera.shift_y();
bcam->sensor_width = b_camera.sensor_width();
@@ -189,19 +207,34 @@ static void blender_camera_from_object(BlenderCamera *bcam, BL::Object b_ob, boo
}
}
-static Transform blender_camera_matrix(const Transform& tfm, CameraType type)
+static Transform blender_camera_matrix(const Transform& tfm,
+ const CameraType type,
+ const PanoramaType panorama_type)
{
Transform result;
if(type == CAMERA_PANORAMA) {
- /* make it so environment camera needs to be pointed in the direction
- * of the positive x-axis to match an environment texture, this way
- * it is looking at the center of the texture */
- result = tfm *
- make_transform( 0.0f, -1.0f, 0.0f, 0.0f,
- 0.0f, 0.0f, 1.0f, 0.0f,
- -1.0f, 0.0f, 0.0f, 0.0f,
- 0.0f, 0.0f, 0.0f, 1.0f);
+ if(panorama_type == PANORAMA_MIRRORBALL) {
+ /* Mirror ball camera is looking into the negative Y direction
+ * which matches texture mirror ball mapping.
+ */
+ result = tfm *
+ make_transform(1.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 1.0f, 0.0f,
+ 0.0f, 1.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 1.0f);
+ }
+ else {
+ /* Make it so environment camera needs to be pointed in the direction
+ * of the positive x-axis to match an environment texture, this way
+ * it is looking at the center of the texture
+ */
+ result = tfm *
+ make_transform( 0.0f, -1.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 1.0f, 0.0f,
+ -1.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 1.0f);
+ }
}
else {
/* note the blender camera points along the negative z-axis */
@@ -211,8 +244,11 @@ static Transform blender_camera_matrix(const Transform& tfm, CameraType type)
return transform_clear_scale(result);
}
-static void blender_camera_viewplane(BlenderCamera *bcam, int width, int height,
- BoundBox2D *viewplane, float *aspectratio, float *sensor_size)
+static void blender_camera_viewplane(BlenderCamera *bcam,
+ int width, int height,
+ BoundBox2D *viewplane,
+ float *aspectratio,
+ float *sensor_size)
{
/* dimensions */
float xratio = (float)width*bcam->pixelaspect.x;
@@ -225,24 +261,34 @@ static void blender_camera_viewplane(BlenderCamera *bcam, int width, int height,
/* sensor fitting */
if(bcam->sensor_fit == BlenderCamera::AUTO) {
horizontal_fit = (xratio > yratio);
- *sensor_size = bcam->sensor_width;
+ if(sensor_size != NULL) {
+ *sensor_size = bcam->sensor_width;
+ }
}
else if(bcam->sensor_fit == BlenderCamera::HORIZONTAL) {
horizontal_fit = true;
- *sensor_size = bcam->sensor_width;
+ if(sensor_size != NULL) {
+ *sensor_size = bcam->sensor_width;
+ }
}
else {
horizontal_fit = false;
- *sensor_size = bcam->sensor_height;
+ if(sensor_size != NULL) {
+ *sensor_size = bcam->sensor_height;
+ }
}
if(horizontal_fit) {
- *aspectratio = xratio/yratio;
+ if(aspectratio != NULL) {
+ *aspectratio = xratio/yratio;
+ }
xaspect = *aspectratio;
yaspect = 1.0f;
}
else {
- *aspectratio = yratio/xratio;
+ if(aspectratio != NULL) {
+ *aspectratio = yratio/xratio;
+ }
xaspect = 1.0f;
yaspect = *aspectratio;
}
@@ -251,31 +297,37 @@ static void blender_camera_viewplane(BlenderCamera *bcam, int width, int height,
if(bcam->type == CAMERA_ORTHOGRAPHIC) {
xaspect = xaspect*bcam->ortho_scale/(*aspectratio*2.0f);
yaspect = yaspect*bcam->ortho_scale/(*aspectratio*2.0f);
- *aspectratio = bcam->ortho_scale/2.0f;
+ if(aspectratio != NULL) {
+ *aspectratio = bcam->ortho_scale/2.0f;
+ }
}
if(bcam->type == CAMERA_PANORAMA) {
/* set viewplane */
- *viewplane = bcam->pano_viewplane;
+ if(viewplane != NULL) {
+ *viewplane = bcam->pano_viewplane;
+ }
}
else {
/* set viewplane */
- viewplane->left = -xaspect;
- viewplane->right = xaspect;
- viewplane->bottom = -yaspect;
- viewplane->top = yaspect;
-
- /* zoom for 3d camera view */
- *viewplane = (*viewplane) * bcam->zoom;
-
- /* modify viewplane with camera shift and 3d camera view offset */
- float dx = 2.0f*(*aspectratio*bcam->shift.x + bcam->offset.x*xaspect*2.0f);
- float dy = 2.0f*(*aspectratio*bcam->shift.y + bcam->offset.y*yaspect*2.0f);
-
- viewplane->left += dx;
- viewplane->right += dx;
- viewplane->bottom += dy;
- viewplane->top += dy;
+ if(viewplane != NULL) {
+ viewplane->left = -xaspect;
+ viewplane->right = xaspect;
+ viewplane->bottom = -yaspect;
+ viewplane->top = yaspect;
+
+ /* zoom for 3d camera view */
+ *viewplane = (*viewplane) * bcam->zoom;
+
+ /* modify viewplane with camera shift and 3d camera view offset */
+ float dx = 2.0f*(*aspectratio*bcam->shift.x + bcam->offset.x*xaspect*2.0f);
+ float dy = 2.0f*(*aspectratio*bcam->shift.y + bcam->offset.y*yaspect*2.0f);
+
+ viewplane->left += dx;
+ viewplane->right += dx;
+ viewplane->bottom += dy;
+ viewplane->top += dy;
+ }
}
}
@@ -292,7 +344,7 @@ static void blender_camera_sync(Camera *cam, BlenderCamera *bcam, int width, int
&cam->viewplane, &aspectratio, &sensor_size);
/* panorama sensor */
- if (bcam->type == CAMERA_PANORAMA && bcam->panorama_type == PANORAMA_FISHEYE_EQUISOLID) {
+ if(bcam->type == CAMERA_PANORAMA && bcam->panorama_type == PANORAMA_FISHEYE_EQUISOLID) {
float fit_xratio = (float)bcam->full_width*bcam->pixelaspect.x;
float fit_yratio = (float)bcam->full_height*bcam->pixelaspect.y;
bool horizontal_fit;
@@ -336,6 +388,11 @@ static void blender_camera_sync(Camera *cam, BlenderCamera *bcam, int width, int
cam->panorama_type = bcam->panorama_type;
cam->fisheye_fov = bcam->fisheye_fov;
cam->fisheye_lens = bcam->fisheye_lens;
+ cam->latitude_min = bcam->latitude_min;
+ cam->latitude_max = bcam->latitude_max;
+
+ cam->longitude_min = bcam->longitude_min;
+ cam->longitude_max = bcam->longitude_max;
/* anamorphic lens bokeh */
cam->aperture_ratio = bcam->aperture_ratio;
@@ -348,14 +405,20 @@ static void blender_camera_sync(Camera *cam, BlenderCamera *bcam, int width, int
cam->bladesrotation = bcam->aperturerotation;
/* transform */
- cam->matrix = blender_camera_matrix(bcam->matrix, bcam->type);
+ cam->matrix = blender_camera_matrix(bcam->matrix,
+ bcam->type,
+ bcam->panorama_type);
cam->motion.pre = cam->matrix;
cam->motion.post = cam->matrix;
cam->use_motion = false;
+ cam->use_perspective_motion = false;
cam->shuttertime = bcam->shuttertime;
+ cam->fov_pre = cam->fov;
+ cam->fov_post = cam->fov;
/* border */
cam->border = bcam->border;
+ cam->viewport_camera_border = bcam->viewport_camera_border;
/* set update flag */
if(cam->modified(prevcam))
@@ -367,7 +430,7 @@ static void blender_camera_sync(Camera *cam, BlenderCamera *bcam, int width, int
void BlenderSync::sync_camera(BL::RenderSettings b_render, BL::Object b_override, int width, int height)
{
BlenderCamera bcam;
- blender_camera_init(&bcam, b_render, b_scene);
+ blender_camera_init(&bcam, b_render);
/* pixel aspect */
bcam.pixelaspect.x = b_render.pixel_aspect_x();
@@ -389,25 +452,34 @@ void BlenderSync::sync_camera(BL::RenderSettings b_render, BL::Object b_override
b_ob = b_override;
if(b_ob) {
- blender_camera_from_object(&bcam, b_ob);
- bcam.matrix = get_transform(b_ob.matrix_world());
+ BL::Array<float, 16> b_ob_matrix;
+ blender_camera_from_object(&bcam, b_engine, b_ob);
+ b_engine.camera_model_matrix(b_ob, b_ob_matrix);
+ bcam.matrix = get_transform(b_ob_matrix);
}
/* sync */
Camera *cam = scene->camera;
blender_camera_sync(cam, &bcam, width, height);
sync_camera_nodes(b_ob);
- scene->camera->use_camera_in_volume = experimental;
}
-void BlenderSync::sync_camera_motion(BL::Object b_ob, float motion_time)
+void BlenderSync::sync_camera_motion(BL::RenderSettings b_render,
+ BL::Object b_ob,
+ int width, int height,
+ float motion_time)
{
- Camera *cam = scene->camera;
+ if(!b_ob)
+ return;
- Transform tfm = get_transform(b_ob.matrix_world());
- tfm = blender_camera_matrix(tfm, cam->type);
+ Camera *cam = scene->camera;
+ BL::Array<float, 16> b_ob_matrix;
+ b_engine.camera_model_matrix(b_ob, b_ob_matrix);
+ Transform tfm = get_transform(b_ob_matrix);
+ tfm = blender_camera_matrix(tfm, cam->type, cam->panorama_type);
if(tfm != cam->matrix) {
+ VLOG(1) << "Camera " << b_ob.name() << " motion detected.";
if(motion_time == -1.0f) {
cam->motion.pre = tfm;
cam->use_motion = true;
@@ -417,14 +489,39 @@ void BlenderSync::sync_camera_motion(BL::Object b_ob, float motion_time)
cam->use_motion = true;
}
}
+
+ if(cam->type == CAMERA_PERSPECTIVE) {
+ BlenderCamera bcam;
+ float aspectratio, sensor_size;
+ blender_camera_init(&bcam, b_render);
+ blender_camera_from_object(&bcam, b_engine, b_ob);
+ blender_camera_viewplane(&bcam,
+ width, height,
+ NULL,
+ &aspectratio,
+ &sensor_size);
+ /* TODO(sergey): De-duplicate calculation with camera sync. */
+ float fov = 2.0f * atanf((0.5f * sensor_size) / bcam.lens / aspectratio);
+ if(fov != cam->fov) {
+ VLOG(1) << "Camera " << b_ob.name() << " FOV change detected.";
+ if(motion_time == -1.0f) {
+ cam->fov_pre = fov;
+ cam->use_perspective_motion = true;
+ }
+ else if(motion_time == 1.0f) {
+ cam->fov_post = fov;
+ cam->use_perspective_motion = true;
+ }
+ }
+ }
}
/* Sync 3D View Camera */
-static void blender_camera_view_subset(BL::RenderSettings b_render, BL::Scene b_scene, BL::Object b_ob, BL::SpaceView3D b_v3d,
+static void blender_camera_view_subset(BL::RenderEngine b_engine, BL::RenderSettings b_render, BL::Scene b_scene, BL::Object b_ob, BL::SpaceView3D b_v3d,
BL::RegionView3D b_rv3d, int width, int height, BoundBox2D *view_box, BoundBox2D *cam_box);
-static void blender_camera_from_view(BlenderCamera *bcam, BL::Scene b_scene, BL::SpaceView3D b_v3d, BL::RegionView3D b_rv3d, int width, int height, bool skip_panorama = false)
+static void blender_camera_from_view(BlenderCamera *bcam, BL::RenderEngine b_engine, BL::Scene b_scene, BL::SpaceView3D b_v3d, BL::RegionView3D b_rv3d, int width, int height, bool skip_panorama = false)
{
/* 3d view parameters */
bcam->nearclip = b_v3d.clip_start();
@@ -437,13 +534,13 @@ static void blender_camera_from_view(BlenderCamera *bcam, BL::Scene b_scene, BL:
BL::Object b_ob = (b_v3d.lock_camera_and_layers())? b_scene.camera(): b_v3d.camera();
if(b_ob) {
- blender_camera_from_object(bcam, b_ob, skip_panorama);
+ blender_camera_from_object(bcam, b_engine, b_ob, skip_panorama);
if(!skip_panorama && bcam->type == CAMERA_PANORAMA) {
/* in panorama camera view, we map viewplane to camera border */
BoundBox2D view_box, cam_box;
- blender_camera_view_subset(b_scene.render(), b_scene, b_ob, b_v3d, b_rv3d, width, height,
+ blender_camera_view_subset(b_engine, b_scene.render(), b_scene, b_ob, b_v3d, b_rv3d, width, height,
&view_box, &cam_box);
bcam->pano_viewplane = view_box.make_relative_to(cam_box);
@@ -481,7 +578,7 @@ static void blender_camera_from_view(BlenderCamera *bcam, BL::Scene b_scene, BL:
bcam->matrix = transform_inverse(get_transform(b_rv3d.view_matrix()));
}
-static void blender_camera_view_subset(BL::RenderSettings b_render, BL::Scene b_scene, BL::Object b_ob, BL::SpaceView3D b_v3d,
+static void blender_camera_view_subset(BL::RenderEngine b_engine, BL::RenderSettings b_render, BL::Scene b_scene, BL::Object b_ob, BL::SpaceView3D b_v3d,
BL::RegionView3D b_rv3d, int width, int height, BoundBox2D *view_box, BoundBox2D *cam_box)
{
BoundBox2D cam, view;
@@ -489,16 +586,16 @@ static void blender_camera_view_subset(BL::RenderSettings b_render, BL::Scene b_
/* get viewport viewplane */
BlenderCamera view_bcam;
- blender_camera_init(&view_bcam, b_render, b_scene);
- blender_camera_from_view(&view_bcam, b_scene, b_v3d, b_rv3d, width, height, true);
+ blender_camera_init(&view_bcam, b_render);
+ blender_camera_from_view(&view_bcam, b_engine, b_scene, b_v3d, b_rv3d, width, height, true);
blender_camera_viewplane(&view_bcam, width, height,
&view, &view_aspect, &sensor_size);
/* get camera viewplane */
BlenderCamera cam_bcam;
- blender_camera_init(&cam_bcam, b_render, b_scene);
- blender_camera_from_object(&cam_bcam, b_ob, true);
+ blender_camera_init(&cam_bcam, b_render);
+ blender_camera_from_object(&cam_bcam, b_engine, b_ob, true);
blender_camera_viewplane(&cam_bcam, cam_bcam.full_width, cam_bcam.full_height,
&cam, &cam_aspect, &sensor_size);
@@ -508,7 +605,27 @@ static void blender_camera_view_subset(BL::RenderSettings b_render, BL::Scene b_
*cam_box = cam * (1.0f/cam_aspect);
}
-static void blender_camera_border(BlenderCamera *bcam, BL::RenderSettings b_render, BL::Scene b_scene, BL::SpaceView3D b_v3d,
+static void blender_camera_border_subset(BL::RenderEngine b_engine,
+ BL::RenderSettings b_render,
+ BL::Scene b_scene,
+ BL::SpaceView3D b_v3d,
+ BL::RegionView3D b_rv3d,
+ BL::Object b_ob,
+ int width, int height,
+ const BoundBox2D &border,
+ BoundBox2D *result)
+{
+ /* Determine camera viewport subset. */
+ BoundBox2D view_box, cam_box;
+ blender_camera_view_subset(b_engine, b_render, b_scene, b_ob, b_v3d, b_rv3d, width, height,
+ &view_box, &cam_box);
+
+ /* Determine viewport subset matching given border. */
+ cam_box = cam_box.make_relative_to(view_box);
+ *result = cam_box.subset(border);
+}
+
+static void blender_camera_border(BlenderCamera *bcam, BL::RenderEngine b_engine, BL::RenderSettings b_render, BL::Scene b_scene, BL::SpaceView3D b_v3d,
BL::RegionView3D b_rv3d, int width, int height)
{
bool is_camera_view;
@@ -526,47 +643,61 @@ static void blender_camera_border(BlenderCamera *bcam, BL::RenderSettings b_rend
bcam->border.right = b_v3d.render_border_max_x();
bcam->border.bottom = b_v3d.render_border_min_y();
bcam->border.top = b_v3d.render_border_max_y();
-
- return;
}
- }
- else if(!b_render.use_border())
return;
+ }
BL::Object b_ob = (b_v3d.lock_camera_and_layers())? b_scene.camera(): b_v3d.camera();
if(!b_ob)
return;
+ /* Determine camera border inside the viewport. */
+ BoundBox2D full_border;
+ blender_camera_border_subset(b_engine,
+ b_render,
+ b_scene,
+ b_v3d,
+ b_rv3d,
+ b_ob,
+ width, height,
+ full_border,
+ &bcam->viewport_camera_border);
+
+ if(!b_render.use_border()) {
+ return;
+ }
+
bcam->border.left = b_render.border_min_x();
bcam->border.right = b_render.border_max_x();
bcam->border.bottom = b_render.border_min_y();
bcam->border.top = b_render.border_max_y();
- /* determine camera viewport subset */
- BoundBox2D view_box, cam_box;
-
- blender_camera_view_subset(b_render, b_scene, b_ob, b_v3d, b_rv3d, width, height,
- &view_box, &cam_box);
-
- /* determine viewport subset matching camera border */
- cam_box = cam_box.make_relative_to(view_box);
- bcam->border = cam_box.subset(bcam->border).clamp();
+ /* Determine viewport subset matching camera border. */
+ blender_camera_border_subset(b_engine,
+ b_render,
+ b_scene,
+ b_v3d,
+ b_rv3d,
+ b_ob,
+ width, height,
+ bcam->border,
+ &bcam->border);
+ bcam->border.clamp();
}
void BlenderSync::sync_view(BL::SpaceView3D b_v3d, BL::RegionView3D b_rv3d, int width, int height)
{
BlenderCamera bcam;
- blender_camera_init(&bcam, b_scene.render(), b_scene);
- blender_camera_from_view(&bcam, b_scene, b_v3d, b_rv3d, width, height);
- blender_camera_border(&bcam, b_scene.render(), b_scene, b_v3d, b_rv3d, width, height);
+ blender_camera_init(&bcam, b_scene.render());
+ blender_camera_from_view(&bcam, b_engine, b_scene, b_v3d, b_rv3d, width, height);
+ blender_camera_border(&bcam, b_engine, b_scene.render(), b_scene, b_v3d, b_rv3d, width, height);
blender_camera_sync(scene->camera, &bcam, width, height);
sync_view_nodes(b_rv3d);
- scene->camera->use_camera_in_volume = experimental;
}
-BufferParams BlenderSync::get_buffer_params(BL::RenderSettings b_render, BL::Scene b_scene, BL::SpaceView3D b_v3d, BL::RegionView3D b_rv3d, Camera *cam, int width, int height)
+BufferParams BlenderSync::get_buffer_params(BL::RenderSettings b_render, BL::SpaceView3D b_v3d, BL::RegionView3D b_rv3d, Camera *cam, int width, int height)
{
BufferParams params;
bool use_border = false;
@@ -581,10 +712,12 @@ BufferParams BlenderSync::get_buffer_params(BL::RenderSettings b_render, BL::Sce
if(use_border) {
/* border render */
- params.full_x = (int)(cam->border.left * (float)width);
- params.full_y = (int)(cam->border.bottom * (float)height);
- params.width = (int)(cam->border.right * (float)width) - params.full_x;
- params.height = (int)(cam->border.top * (float)height) - params.full_y;
+ /* the viewport may offset the border outside the view */
+ BoundBox2D border = cam->border.clamp();
+ params.full_x = (int)(border.left * (float)width);
+ params.full_y = (int)(border.bottom * (float)height);
+ params.width = (int)(border.right * (float)width) - params.full_x;
+ params.height = (int)(border.top * (float)height) - params.full_y;
/* survive in case border goes out of view or becomes too small */
params.width = max(params.width, 1);
diff --git a/intern/cycles/blender/blender_curves.cpp b/intern/cycles/blender/blender_curves.cpp
index 8cfaea59a06..6a119081bfd 100644
--- a/intern/cycles/blender/blender_curves.cpp
+++ b/intern/cycles/blender/blender_curves.cpp
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#include "attribute.h"
@@ -25,6 +25,7 @@
#include "blender_util.h"
#include "util_foreach.h"
+#include "util_logging.h"
CCL_NAMESPACE_BEGIN
@@ -43,8 +44,8 @@ void ExportCurveSegments(Scene *scene, Mesh *mesh, ParticleCurveData *CData);
void ExportCurveTrianglePlanes(Mesh *mesh, ParticleCurveData *CData,
float3 RotCam, bool is_ortho);
void ExportCurveTriangleGeometry(Mesh *mesh, ParticleCurveData *CData, int resolution);
-void ExportCurveTriangleUV(Mesh *mesh, ParticleCurveData *CData, int vert_offset, int resol, float3 *uvdata);
-void ExportCurveTriangleVcol(Mesh *mesh, ParticleCurveData *CData, int vert_offset, int resol, uchar4 *cdata);
+void ExportCurveTriangleUV(ParticleCurveData *CData, int vert_offset, int resol, float3 *uvdata);
+void ExportCurveTriangleVcol(ParticleCurveData *CData, int vert_offset, int resol, uchar4 *cdata);
ParticleCurveData::ParticleCurveData()
{
@@ -140,17 +141,20 @@ bool ObtainCacheParticleData(Mesh *mesh, BL::Mesh *b_mesh, BL::Object *b_ob, Par
int mi = clamp(b_part.material()-1, 0, mesh->used_shaders.size()-1);
int shader = mesh->used_shaders[mi];
int draw_step = background ? b_part.render_step() : b_part.draw_step();
- int ren_step = (int)powf(2.0f, (float)draw_step);
int totparts = b_psys.particles.length();
int totchild = background ? b_psys.child_particles.length() : (int)((float)b_psys.child_particles.length() * (float)b_part.draw_percentage() / 100.0f);
int totcurves = totchild;
- if(b_part.child_type() == 0)
+ if(b_part.child_type() == 0 || totchild == 0)
totcurves += totparts;
if(totcurves == 0)
continue;
+ int ren_step = (1 << draw_step) + 1;
+ if(b_part.kink() == BL::ParticleSettings::kink_SPIRAL)
+ ren_step += b_part.kink_extra_steps();
+
PointerRNA cpsys = RNA_pointer_get(&b_part.ptr, "cycles");
CData->psys_firstcurve.push_back(curvenum);
@@ -165,15 +169,15 @@ bool ObtainCacheParticleData(Mesh *mesh, BL::Mesh *b_mesh, BL::Object *b_ob, Par
CData->psys_closetip.push_back(get_boolean(cpsys, "use_closetip"));
int pa_no = 0;
- if(!(b_part.child_type() == 0))
+ if(!(b_part.child_type() == 0) && totchild != 0)
pa_no = totparts;
int num_add = (totparts+totchild - pa_no);
CData->curve_firstkey.reserve(CData->curve_firstkey.size() + num_add);
CData->curve_keynum.reserve(CData->curve_keynum.size() + num_add);
CData->curve_length.reserve(CData->curve_length.size() + num_add);
- CData->curvekey_co.reserve(CData->curvekey_co.size() + num_add*(ren_step+1));
- CData->curvekey_time.reserve(CData->curvekey_time.size() + num_add*(ren_step+1));
+ CData->curvekey_co.reserve(CData->curvekey_co.size() + num_add*ren_step);
+ CData->curvekey_time.reserve(CData->curvekey_time.size() + num_add*ren_step);
for(; pa_no < totparts+totchild; pa_no++) {
int keynum = 0;
@@ -181,7 +185,7 @@ bool ObtainCacheParticleData(Mesh *mesh, BL::Mesh *b_mesh, BL::Object *b_ob, Par
float curve_length = 0.0f;
float3 pcKey;
- for(int step_no = 0; step_no <= ren_step; step_no++) {
+ for(int step_no = 0; step_no < ren_step; step_no++) {
float nco[3];
b_psys.co_hair(*b_ob, pa_no, step_no, nco);
float3 cKey = make_float3(nco[0], nco[1], nco[2]);
@@ -195,9 +199,9 @@ bool ObtainCacheParticleData(Mesh *mesh, BL::Mesh *b_mesh, BL::Object *b_ob, Par
CData->curvekey_co.push_back(cKey);
CData->curvekey_time.push_back(curve_length);
pcKey = cKey;
- keyno++;
keynum++;
}
+ keyno += keynum;
CData->curve_keynum.push_back(keynum);
CData->curve_length.push_back(curve_length);
@@ -229,14 +233,14 @@ bool ObtainCacheParticleUV(Mesh *mesh, BL::Mesh *b_mesh, BL::Object *b_ob, Parti
int totchild = background ? b_psys.child_particles.length() : (int)((float)b_psys.child_particles.length() * (float)b_part.draw_percentage() / 100.0f);
int totcurves = totchild;
- if (b_part.child_type() == 0)
+ if(b_part.child_type() == 0 || totchild == 0)
totcurves += totparts;
- if (totcurves == 0)
+ if(totcurves == 0)
continue;
int pa_no = 0;
- if(!(b_part.child_type() == 0))
+ if(!(b_part.child_type() == 0) && totchild != 0)
pa_no = totparts;
int num_add = (totparts+totchild - pa_no);
@@ -283,14 +287,14 @@ bool ObtainCacheParticleVcol(Mesh *mesh, BL::Mesh *b_mesh, BL::Object *b_ob, Par
int totchild = background ? b_psys.child_particles.length() : (int)((float)b_psys.child_particles.length() * (float)b_part.draw_percentage() / 100.0f);
int totcurves = totchild;
- if (b_part.child_type() == 0)
+ if(b_part.child_type() == 0 || totchild == 0)
totcurves += totparts;
- if (totcurves == 0)
+ if(totcurves == 0)
continue;
int pa_no = 0;
- if(!(b_part.child_type() == 0))
+ if(!(b_part.child_type() == 0) && totchild != 0)
pa_no = totparts;
int num_add = (totparts+totchild - pa_no);
@@ -318,11 +322,11 @@ bool ObtainCacheParticleVcol(Mesh *mesh, BL::Mesh *b_mesh, BL::Object *b_ob, Par
return true;
}
-static void set_resolution(Mesh *mesh, BL::Mesh *b_mesh, BL::Object *b_ob, BL::Scene *scene, bool render)
+static void set_resolution(BL::Object *b_ob, BL::Scene *scene, bool render)
{
BL::Object::modifiers_iterator b_mod;
for(b_ob->modifiers.begin(b_mod); b_mod != b_ob->modifiers.end(); ++b_mod) {
- if ((b_mod->type() == b_mod->type_PARTICLE_SYSTEM) && ((b_mod->show_viewport()) || (b_mod->show_render()))) {
+ if((b_mod->type() == b_mod->type_PARTICLE_SYSTEM) && ((b_mod->show_viewport()) || (b_mod->show_render()))) {
BL::ParticleSystemModifier psmd((const PointerRNA)b_mod->ptr);
BL::ParticleSystem b_psys((const PointerRNA)psmd.particle_system().ptr);
b_psys.set_resolution(*scene, *b_ob, (render)? 2: 1);
@@ -509,7 +513,7 @@ void ExportCurveTriangleGeometry(Mesh *mesh, ParticleCurveData *CData, int resol
ybasis = normalize(cross(xbasis, v2));
- for (; subv <= 1; subv++) {
+ for(; subv <= 1; subv++) {
float3 ickey_loc = make_float3(0.0f,0.0f,0.0f);
float time = 0.0f;
@@ -577,6 +581,10 @@ void ExportCurveSegments(Scene *scene, Mesh *mesh, ParticleCurveData *CData)
}
}
+ if(num_curves > 0) {
+ VLOG(1) << "Exporting curve segments for mesh " << mesh->name;
+ }
+
mesh->curve_keys.reserve(mesh->curve_keys.size() + num_keys);
mesh->curves.reserve(mesh->curves.size() + num_curves);
@@ -612,23 +620,27 @@ void ExportCurveSegments(Scene *scene, Mesh *mesh, ParticleCurveData *CData)
}
}
- /* check allocation*/
- if((mesh->curve_keys.size() != num_keys) || (mesh->curves.size() != num_curves)) {
- /* allocation failed -> clear data */
+ /* check allocation */
+ if((mesh->curve_keys.size() != num_keys) || (mesh->curves.size() != num_curves)) {
+ VLOG(1) << "Allocation failed, clearing data";
mesh->curve_keys.clear();
mesh->curves.clear();
mesh->curve_attributes.clear();
}
}
-static void ExportCurveSegmentsMotion(Scene *scene, Mesh *mesh, ParticleCurveData *CData, int time_index)
+static void ExportCurveSegmentsMotion(Mesh *mesh, ParticleCurveData *CData, int time_index)
{
+ VLOG(1) << "Exporting curve motion segments for mesh " << mesh->name
+ << ", time index " << time_index;
+
/* find attribute */
Attribute *attr_mP = mesh->curve_attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
bool new_attribute = false;
/* add new attribute if it doesn't exist already */
if(!attr_mP) {
+ VLOG(1) << "Creating new motion vertex position attribute";
attr_mP = mesh->curve_attributes.add(ATTR_STD_MOTION_VERTEX_POSITION);
new_attribute = true;
}
@@ -675,9 +687,12 @@ static void ExportCurveSegmentsMotion(Scene *scene, Mesh *mesh, ParticleCurveDat
if(new_attribute) {
if(i != numkeys || !have_motion) {
/* no motion, remove attributes again */
+ VLOG(1) << "No motion, removing attribute";
mesh->curve_attributes.remove(ATTR_STD_MOTION_VERTEX_POSITION);
}
else if(time_index > 0) {
+ VLOG(1) << "Filling in new motion vertex position for time_index "
+ << time_index;
/* motion, fill up previous steps that we might have skipped because
* they had no motion, but we need them anyway now */
for(int step = 0; step < time_index; step++) {
@@ -690,7 +705,7 @@ static void ExportCurveSegmentsMotion(Scene *scene, Mesh *mesh, ParticleCurveDat
}
}
-void ExportCurveTriangleUV(Mesh *mesh, ParticleCurveData *CData, int vert_offset, int resol, float3 *uvdata)
+void ExportCurveTriangleUV(ParticleCurveData *CData, int vert_offset, int resol, float3 *uvdata)
{
if(uvdata == NULL)
return;
@@ -735,7 +750,7 @@ void ExportCurveTriangleUV(Mesh *mesh, ParticleCurveData *CData, int vert_offset
}
}
-void ExportCurveTriangleVcol(Mesh *mesh, ParticleCurveData *CData, int vert_offset, int resol, uchar4 *cdata)
+void ExportCurveTriangleVcol(ParticleCurveData *CData, int vert_offset, int resol, uchar4 *cdata)
{
if(cdata == NULL)
return;
@@ -786,30 +801,38 @@ void BlenderSync::sync_curve_settings()
curve_system_manager->subdivisions = get_int(csscene, "subdivisions");
curve_system_manager->use_backfacing = !get_boolean(csscene, "cull_backfacing");
- if(curve_system_manager->primitive == CURVE_TRIANGLES && curve_system_manager->curve_shape == CURVE_RIBBON) {
- /* camera facing planes */
- curve_system_manager->triangle_method = CURVE_CAMERA_TRIANGLES;
- curve_system_manager->resolution = 1;
- }
- else if(curve_system_manager->primitive == CURVE_TRIANGLES && curve_system_manager->curve_shape == CURVE_THICK) {
+ /* Triangles */
+ if(curve_system_manager->primitive == CURVE_TRIANGLES) {
/* camera facing planes */
- curve_system_manager->triangle_method = CURVE_TESSELATED_TRIANGLES;
- }
- else if(curve_system_manager->primitive == CURVE_LINE_SEGMENTS && curve_system_manager->curve_shape == CURVE_RIBBON) {
- /* tangent shading */
- curve_system_manager->line_method = CURVE_UNCORRECTED;
- curve_system_manager->use_encasing = true;
- curve_system_manager->use_backfacing = false;
- curve_system_manager->use_tangent_normal_geometry = true;
+ if(curve_system_manager->curve_shape == CURVE_RIBBON) {
+ curve_system_manager->triangle_method = CURVE_CAMERA_TRIANGLES;
+ curve_system_manager->resolution = 1;
+ }
+ else if(curve_system_manager->curve_shape == CURVE_THICK) {
+ curve_system_manager->triangle_method = CURVE_TESSELATED_TRIANGLES;
+ }
}
- else if(curve_system_manager->primitive == CURVE_LINE_SEGMENTS && curve_system_manager->curve_shape == CURVE_THICK) {
- curve_system_manager->line_method = CURVE_ACCURATE;
- curve_system_manager->use_encasing = false;
- curve_system_manager->use_tangent_normal_geometry = false;
+ /* Line Segments */
+ else if(curve_system_manager->primitive == CURVE_LINE_SEGMENTS) {
+ if(curve_system_manager->curve_shape == CURVE_RIBBON) {
+ /* tangent shading */
+ curve_system_manager->line_method = CURVE_UNCORRECTED;
+ curve_system_manager->use_encasing = true;
+ curve_system_manager->use_backfacing = false;
+ curve_system_manager->use_tangent_normal_geometry = true;
+ }
+ else if(curve_system_manager->curve_shape == CURVE_THICK) {
+ curve_system_manager->line_method = CURVE_ACCURATE;
+ curve_system_manager->use_encasing = false;
+ curve_system_manager->use_tangent_normal_geometry = false;
+ }
}
- else if(curve_system_manager->primitive == CURVE_SEGMENTS && curve_system_manager->curve_shape == CURVE_RIBBON) {
- curve_system_manager->primitive = CURVE_RIBBONS;
- curve_system_manager->use_backfacing = false;
+ /* Curve Segments */
+ else if(curve_system_manager->primitive == CURVE_SEGMENTS) {
+ if(curve_system_manager->curve_shape == CURVE_RIBBON) {
+ curve_system_manager->primitive = CURVE_RIBBONS;
+ curve_system_manager->use_backfacing = false;
+ }
}
if(curve_system_manager->modified_mesh(prev_curve_system_manager)) {
@@ -863,7 +886,7 @@ void BlenderSync::sync_curves(Mesh *mesh, BL::Mesh b_mesh, BL::Object b_ob, bool
ParticleCurveData CData;
if(!preview)
- set_resolution(mesh, &b_mesh, &b_ob, &b_scene, true);
+ set_resolution(&b_ob, &b_scene, true);
ObtainCacheParticleData(mesh, &b_mesh, &b_ob, &CData, !preview);
@@ -894,7 +917,7 @@ void BlenderSync::sync_curves(Mesh *mesh, BL::Mesh b_mesh, BL::Object b_ob, bool
}
else {
if(motion)
- ExportCurveSegmentsMotion(scene, mesh, &CData, time_index);
+ ExportCurveSegmentsMotion(mesh, &CData, time_index);
else
ExportCurveSegments(scene, mesh, &CData);
}
@@ -943,7 +966,7 @@ void BlenderSync::sync_curves(Mesh *mesh, BL::Mesh b_mesh, BL::Object b_ob, bool
uchar4 *cdata = attr_vcol->data_uchar4();
- ExportCurveTriangleVcol(mesh, &CData, tri_num * 3, used_res, cdata);
+ ExportCurveTriangleVcol(&CData, tri_num * 3, used_res, cdata);
}
else {
Attribute *attr_vcol = mesh->curve_attributes.add(
@@ -986,7 +1009,7 @@ void BlenderSync::sync_curves(Mesh *mesh, BL::Mesh b_mesh, BL::Object b_ob, bool
float3 *uv = attr_uv->data_float3();
- ExportCurveTriangleUV(mesh, &CData, tri_num * 3, used_res, uv);
+ ExportCurveTriangleUV(&CData, tri_num * 3, used_res, uv);
}
else {
if(active_render)
@@ -1009,7 +1032,7 @@ void BlenderSync::sync_curves(Mesh *mesh, BL::Mesh b_mesh, BL::Object b_ob, bool
}
if(!preview)
- set_resolution(mesh, &b_mesh, &b_ob, &b_scene, false);
+ set_resolution(&b_ob, &b_scene, false);
mesh->compute_bounds();
}
diff --git a/intern/cycles/blender/blender_logging.cpp b/intern/cycles/blender/blender_logging.cpp
index d3f1accf099..f4f86929168 100644
--- a/intern/cycles/blender/blender_logging.cpp
+++ b/intern/cycles/blender/blender_logging.cpp
@@ -11,55 +11,23 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#include "CCL_api.h"
-
-#include <stdio.h>
-
#include "util_logging.h"
-#ifdef _MSC_VER
-# define snprintf _snprintf
-#endif
-
void CCL_init_logging(const char *argv0)
{
-#ifdef WITH_CYCLES_LOGGING
- /* Make it so FATAL messages are always print into console. */
- char severity_fatal[32];
- snprintf(severity_fatal, sizeof(severity_fatal), "%d",
- google::GLOG_FATAL);
-
- google::InitGoogleLogging(argv0);
- google::SetCommandLineOption("logtostderr", "1");
- google::SetCommandLineOption("v", "0");
- google::SetCommandLineOption("stderrthreshold", severity_fatal);
- google::SetCommandLineOption("minloglevel", severity_fatal);
-#else
- (void) argv0;
-#endif
+ ccl::util_logging_init(argv0);
}
void CCL_start_debug_logging(void)
{
-#ifdef WITH_CYCLES_LOGGING
- google::SetCommandLineOption("logtostderr", "1");
- google::SetCommandLineOption("v", "2");
- google::SetCommandLineOption("stderrthreshold", "1");
- google::SetCommandLineOption("minloglevel", "0");
-#endif
+ ccl::util_logging_start();
}
void CCL_logging_verbosity_set(int verbosity)
{
-#ifdef WITH_CYCLES_LOGGING
- char val[10];
- snprintf(val, sizeof(val), "%d", verbosity);
-
- google::SetCommandLineOption("v", val);
-#else
- (void) verbosity;
-#endif
+ ccl::util_logging_verbosity_set(verbosity);
}
diff --git a/intern/cycles/blender/blender_mesh.cpp b/intern/cycles/blender/blender_mesh.cpp
index a5e4b7bd2ae..7135e938afb 100644
--- a/intern/cycles/blender/blender_mesh.cpp
+++ b/intern/cycles/blender/blender_mesh.cpp
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
@@ -20,6 +20,7 @@
#include "scene.h"
#include "blender_sync.h"
+#include "blender_session.h"
#include "blender_util.h"
#include "subd_mesh.h"
@@ -27,6 +28,8 @@
#include "subd_split.h"
#include "util_foreach.h"
+#include "util_logging.h"
+#include "util_math.h"
#include "mikktspace.h"
@@ -104,7 +107,9 @@ static void mikk_get_texture_coordinate(const SMikkTSpaceContext *context, float
int vert_idx = userdata->mesh.tessfaces[face_num].vertices()[vert_num];
float3 orco =
get_float3(userdata->mesh.vertices[vert_idx].undeformed_co());
- map_to_sphere(&uv[0], &uv[1], orco[0], orco[1], orco[2]);
+ float2 tmp = map_to_sphere(make_float3(orco[0], orco[1], orco[2]));
+ uv[0] = tmp.x;
+ uv[1] = tmp.y;
}
}
@@ -135,7 +140,7 @@ static void mikk_set_tangent_space(const SMikkTSpaceContext *context, const floa
userdata->tangent[face*4 + vert] = make_float4(T[0], T[1], T[2], sign);
}
-static void mikk_compute_tangents(BL::Mesh b_mesh, BL::MeshTextureFaceLayer *b_layer, Mesh *mesh, vector<int>& nverts, bool need_sign, bool active_render)
+static void mikk_compute_tangents(BL::Mesh b_mesh, BL::MeshTextureFaceLayer *b_layer, Mesh *mesh, const vector<int>& nverts, bool need_sign, bool active_render)
{
/* setup userdata */
MikkUserData userdata(b_mesh, b_layer, nverts.size());
@@ -237,8 +242,16 @@ static void create_mesh_volume_attribute(BL::Object b_ob, Mesh *mesh, ImageManag
bool animated = false;
volume_data->manager = image_manager;
- volume_data->slot = image_manager->add_image(Attribute::standard_name(std),
- b_ob.ptr.data, animated, frame, is_float, is_linear, INTERPOLATION_LINEAR, true);
+ volume_data->slot = image_manager->add_image(
+ Attribute::standard_name(std),
+ b_ob.ptr.data,
+ animated,
+ frame,
+ is_float,
+ is_linear,
+ INTERPOLATION_LINEAR,
+ EXTENSION_REPEAT,
+ true);
}
static void create_mesh_volume_attributes(Scene *scene, BL::Object b_ob, Mesh *mesh, float frame)
@@ -256,6 +269,167 @@ static void create_mesh_volume_attributes(Scene *scene, BL::Object b_ob, Mesh *m
create_mesh_volume_attribute(b_ob, mesh, scene->image_manager, ATTR_STD_VOLUME_VELOCITY, frame);
}
+/* Create vertex color attributes. */
+static void attr_create_vertex_color(Scene *scene,
+ Mesh *mesh,
+ BL::Mesh b_mesh,
+ const vector<int>& nverts)
+{
+ BL::Mesh::tessface_vertex_colors_iterator l;
+ for(b_mesh.tessface_vertex_colors.begin(l); l != b_mesh.tessface_vertex_colors.end(); ++l) {
+ if(!mesh->need_attribute(scene, ustring(l->name().c_str())))
+ continue;
+
+ Attribute *attr = mesh->attributes.add(
+ ustring(l->name().c_str()), TypeDesc::TypeColor, ATTR_ELEMENT_CORNER_BYTE);
+
+ BL::MeshColorLayer::data_iterator c;
+ uchar4 *cdata = attr->data_uchar4();
+ size_t i = 0;
+
+ for(l->data.begin(c); c != l->data.end(); ++c, ++i) {
+ cdata[0] = color_float_to_byte(color_srgb_to_scene_linear(get_float3(c->color1())));
+ cdata[1] = color_float_to_byte(color_srgb_to_scene_linear(get_float3(c->color2())));
+ cdata[2] = color_float_to_byte(color_srgb_to_scene_linear(get_float3(c->color3())));
+
+ if(nverts[i] == 4) {
+ cdata[3] = cdata[0];
+ cdata[4] = cdata[2];
+ cdata[5] = color_float_to_byte(color_srgb_to_scene_linear(get_float3(c->color4())));
+ cdata += 6;
+ }
+ else
+ cdata += 3;
+ }
+ }
+}
+
+/* Create uv map attributes. */
+static void attr_create_uv_map(Scene *scene,
+ Mesh *mesh,
+ BL::Mesh b_mesh,
+ const vector<int>& nverts)
+{
+ if(b_mesh.tessface_uv_textures.length() != 0) {
+ BL::Mesh::tessface_uv_textures_iterator l;
+
+ for(b_mesh.tessface_uv_textures.begin(l); l != b_mesh.tessface_uv_textures.end(); ++l) {
+ bool active_render = l->active_render();
+ AttributeStandard std = (active_render)? ATTR_STD_UV: ATTR_STD_NONE;
+ ustring name = ustring(l->name().c_str());
+
+ /* UV map */
+ if(mesh->need_attribute(scene, name) || mesh->need_attribute(scene, std)) {
+ Attribute *attr;
+
+ if(active_render)
+ attr = mesh->attributes.add(std, name);
+ else
+ attr = mesh->attributes.add(name, TypeDesc::TypePoint, ATTR_ELEMENT_CORNER);
+
+ BL::MeshTextureFaceLayer::data_iterator t;
+ float3 *fdata = attr->data_float3();
+ size_t i = 0;
+
+ for(l->data.begin(t); t != l->data.end(); ++t, ++i) {
+ fdata[0] = get_float3(t->uv1());
+ fdata[1] = get_float3(t->uv2());
+ fdata[2] = get_float3(t->uv3());
+ fdata += 3;
+
+ if(nverts[i] == 4) {
+ fdata[0] = get_float3(t->uv1());
+ fdata[1] = get_float3(t->uv3());
+ fdata[2] = get_float3(t->uv4());
+ fdata += 3;
+ }
+ }
+ }
+
+ /* UV tangent */
+ std = (active_render)? ATTR_STD_UV_TANGENT: ATTR_STD_NONE;
+ name = ustring((string(l->name().c_str()) + ".tangent").c_str());
+
+ if(mesh->need_attribute(scene, name) || (active_render && mesh->need_attribute(scene, std))) {
+ std = (active_render)? ATTR_STD_UV_TANGENT_SIGN: ATTR_STD_NONE;
+ name = ustring((string(l->name().c_str()) + ".tangent_sign").c_str());
+ bool need_sign = (mesh->need_attribute(scene, name) || mesh->need_attribute(scene, std));
+
+ mikk_compute_tangents(b_mesh, &(*l), mesh, nverts, need_sign, active_render);
+ }
+ }
+ }
+ else if(mesh->need_attribute(scene, ATTR_STD_UV_TANGENT)) {
+ bool need_sign = mesh->need_attribute(scene, ATTR_STD_UV_TANGENT_SIGN);
+ mikk_compute_tangents(b_mesh, NULL, mesh, nverts, need_sign, true);
+ }
+}
+
+/* Create vertex pointiness attributes. */
+static void attr_create_pointiness(Scene *scene,
+ Mesh *mesh,
+ BL::Mesh b_mesh)
+{
+ if(mesh->need_attribute(scene, ATTR_STD_POINTINESS)) {
+ const int numverts = b_mesh.vertices.length();
+ Attribute *attr = mesh->attributes.add(ATTR_STD_POINTINESS);
+ float *data = attr->data_float();
+ int *counter = new int[numverts];
+ float *raw_data = new float[numverts];
+ float3 *edge_accum = new float3[numverts];
+
+ /* Calculate pointiness using single ring neighborhood. */
+ memset(counter, 0, sizeof(int) * numverts);
+ memset(raw_data, 0, sizeof(float) * numverts);
+ memset(edge_accum, 0, sizeof(float3) * numverts);
+ BL::Mesh::edges_iterator e;
+ int i = 0;
+ for(b_mesh.edges.begin(e); e != b_mesh.edges.end(); ++e, ++i) {
+ int v0 = b_mesh.edges[i].vertices()[0],
+ v1 = b_mesh.edges[i].vertices()[1];
+ float3 co0 = get_float3(b_mesh.vertices[v0].co()),
+ co1 = get_float3(b_mesh.vertices[v1].co());
+ float3 edge = normalize(co1 - co0);
+ edge_accum[v0] += edge;
+ edge_accum[v1] += -edge;
+ ++counter[v0];
+ ++counter[v1];
+ }
+ i = 0;
+ BL::Mesh::vertices_iterator v;
+ for(b_mesh.vertices.begin(v); v != b_mesh.vertices.end(); ++v, ++i) {
+ if(counter[i] > 0) {
+ float3 normal = get_float3(b_mesh.vertices[i].normal());
+ float angle = safe_acosf(dot(normal, edge_accum[i] / counter[i]));
+ raw_data[i] = angle * M_1_PI_F;
+ }
+ else {
+ raw_data[i] = 0.0f;
+ }
+ }
+
+ /* Blur vertices to approximate 2 ring neighborhood. */
+ memset(counter, 0, sizeof(int) * numverts);
+ memcpy(data, raw_data, sizeof(float) * numverts);
+ i = 0;
+ for(b_mesh.edges.begin(e); e != b_mesh.edges.end(); ++e, ++i) {
+ int v0 = b_mesh.edges[i].vertices()[0],
+ v1 = b_mesh.edges[i].vertices()[1];
+ data[v0] += raw_data[v1];
+ data[v1] += raw_data[v0];
+ ++counter[v0];
+ ++counter[v1];
+ }
+ for(i = 0; i < numverts; ++i) {
+ data[i] /= counter[i] + 1;
+ }
+
+ delete [] counter;
+ delete [] raw_data;
+ delete [] edge_accum;
+ }
+}
+
/* Create Mesh */
static void create_mesh(Scene *scene, Mesh *mesh, BL::Mesh b_mesh, const vector<uint>& used_shaders)
@@ -303,6 +477,9 @@ static void create_mesh(Scene *scene, Mesh *mesh, BL::Mesh b_mesh, const vector<
generated[i++] = get_float3(v->undeformed_co())*size - loc;
}
+ /* Create needed vertex attributes. */
+ attr_create_pointiness(scene, mesh, b_mesh);
+
/* create faces */
vector<int> nverts(numfaces);
int fi = 0, ti = 0;
@@ -312,7 +489,7 @@ static void create_mesh(Scene *scene, Mesh *mesh, BL::Mesh b_mesh, const vector<
int n = (vi[3] == 0)? 3: 4;
int mi = clamp(f->material_index(), 0, used_shaders.size()-1);
int shader = used_shaders[mi];
- bool smooth = f->use_smooth();
+ bool smooth = f->use_smooth() || use_loop_normals;
/* split vertices if normal is different
*
@@ -354,92 +531,11 @@ static void create_mesh(Scene *scene, Mesh *mesh, BL::Mesh b_mesh, const vector<
nverts[fi] = n;
}
- /* create vertex color attributes */
- {
- BL::Mesh::tessface_vertex_colors_iterator l;
-
- for(b_mesh.tessface_vertex_colors.begin(l); l != b_mesh.tessface_vertex_colors.end(); ++l) {
- if(!mesh->need_attribute(scene, ustring(l->name().c_str())))
- continue;
-
- Attribute *attr = mesh->attributes.add(
- ustring(l->name().c_str()), TypeDesc::TypeColor, ATTR_ELEMENT_CORNER_BYTE);
-
- BL::MeshColorLayer::data_iterator c;
- uchar4 *cdata = attr->data_uchar4();
- size_t i = 0;
-
- for(l->data.begin(c); c != l->data.end(); ++c, ++i) {
- cdata[0] = color_float_to_byte(color_srgb_to_scene_linear(get_float3(c->color1())));
- cdata[1] = color_float_to_byte(color_srgb_to_scene_linear(get_float3(c->color2())));
- cdata[2] = color_float_to_byte(color_srgb_to_scene_linear(get_float3(c->color3())));
-
- if(nverts[i] == 4) {
- cdata[3] = cdata[0];
- cdata[4] = cdata[2];
- cdata[5] = color_float_to_byte(color_srgb_to_scene_linear(get_float3(c->color4())));
- cdata += 6;
- }
- else
- cdata += 3;
- }
- }
- }
-
- /* create uv map attributes */
- if (b_mesh.tessface_uv_textures.length() != 0) {
- BL::Mesh::tessface_uv_textures_iterator l;
-
- for(b_mesh.tessface_uv_textures.begin(l); l != b_mesh.tessface_uv_textures.end(); ++l) {
- bool active_render = l->active_render();
- AttributeStandard std = (active_render)? ATTR_STD_UV: ATTR_STD_NONE;
- ustring name = ustring(l->name().c_str());
-
- /* UV map */
- if(mesh->need_attribute(scene, name) || mesh->need_attribute(scene, std)) {
- Attribute *attr;
-
- if(active_render)
- attr = mesh->attributes.add(std, name);
- else
- attr = mesh->attributes.add(name, TypeDesc::TypePoint, ATTR_ELEMENT_CORNER);
-
- BL::MeshTextureFaceLayer::data_iterator t;
- float3 *fdata = attr->data_float3();
- size_t i = 0;
-
- for(l->data.begin(t); t != l->data.end(); ++t, ++i) {
- fdata[0] = get_float3(t->uv1());
- fdata[1] = get_float3(t->uv2());
- fdata[2] = get_float3(t->uv3());
- fdata += 3;
-
- if(nverts[i] == 4) {
- fdata[0] = get_float3(t->uv1());
- fdata[1] = get_float3(t->uv3());
- fdata[2] = get_float3(t->uv4());
- fdata += 3;
- }
- }
- }
-
- /* UV tangent */
- std = (active_render)? ATTR_STD_UV_TANGENT: ATTR_STD_NONE;
- name = ustring((string(l->name().c_str()) + ".tangent").c_str());
-
- if(mesh->need_attribute(scene, name) || (active_render && mesh->need_attribute(scene, std))) {
- std = (active_render)? ATTR_STD_UV_TANGENT_SIGN: ATTR_STD_NONE;
- name = ustring((string(l->name().c_str()) + ".tangent_sign").c_str());
- bool need_sign = (mesh->need_attribute(scene, name) || mesh->need_attribute(scene, std));
-
- mikk_compute_tangents(b_mesh, &(*l), mesh, nverts, need_sign, active_render);
- }
- }
- }
- else if(mesh->need_attribute(scene, ATTR_STD_UV_TANGENT)) {
- bool need_sign = mesh->need_attribute(scene, ATTR_STD_UV_TANGENT_SIGN);
- mikk_compute_tangents(b_mesh, NULL, mesh, nverts, need_sign, true);
- }
+ /* Create all needed attributes.
+ * The calculate functions will check whether they're needed or not.
+ */
+ attr_create_vertex_color(scene, mesh, b_mesh, nverts);
+ attr_create_uv_map(scene, mesh, b_mesh, nverts);
/* for volume objects, create a matrix to transform from object space to
* mesh texture space. this does not work with deformations but that can
@@ -501,6 +597,14 @@ static void create_subd_mesh(Scene *scene, Mesh *mesh, BL::Mesh b_mesh, PointerR
Mesh *BlenderSync::sync_mesh(BL::Object b_ob, bool object_updated, bool hide_tris)
{
+ /* When viewport display is not needed during render we can force some
+ * caches to be releases from blender side in order to reduce peak memory
+ * footprint during synchronization process.
+ */
+ const bool is_interface_locked = b_engine.render() &&
+ b_engine.render().use_lock_interface();
+ const bool can_free_caches = BlenderSession::headless || is_interface_locked;
+
/* test if we can instance or if the object is modified */
BL::ID b_ob_data = b_ob.data();
BL::ID key = (BKE_object_is_modified(b_ob))? b_ob: b_ob_data;
@@ -525,7 +629,13 @@ Mesh *BlenderSync::sync_mesh(BL::Object b_ob, bool object_updated, bool hide_tri
}
/* test if we need to sync */
- bool use_mesh_geometry = render_layer.use_surfaces || render_layer.use_hair;
+ int requested_geometry_flags = Mesh::GEOMETRY_NONE;
+ if(render_layer.use_surfaces) {
+ requested_geometry_flags |= Mesh::GEOMETRY_TRIANGLES;
+ }
+ if(render_layer.use_hair) {
+ requested_geometry_flags |= Mesh::GEOMETRY_CURVES;
+ }
Mesh *mesh;
if(!mesh_map.sync(&mesh, key)) {
@@ -534,7 +644,7 @@ Mesh *BlenderSync::sync_mesh(BL::Object b_ob, bool object_updated, bool hide_tri
/* test if shaders changed, these can be object level so mesh
* does not get tagged for recalc */
else if(mesh->used_shaders != used_shaders);
- else if(use_mesh_geometry != mesh->geometry_synced);
+ else if(requested_geometry_flags != mesh->geometry_flags);
else {
/* even if not tagged for recalc, we may need to sync anyway
* because the shader needs different mesh attributes */
@@ -568,7 +678,7 @@ Mesh *BlenderSync::sync_mesh(BL::Object b_ob, bool object_updated, bool hide_tri
mesh->used_shaders = used_shaders;
mesh->name = ustring(b_ob_data.name().c_str());
- if(use_mesh_geometry) {
+ if(requested_geometry_flags != Mesh::GEOMETRY_NONE) {
/* mesh objects does have special handle in the dependency graph,
* they're ensured to have properly updated.
*
@@ -594,11 +704,15 @@ Mesh *BlenderSync::sync_mesh(BL::Object b_ob, bool object_updated, bool hide_tri
if(render_layer.use_hair)
sync_curves(mesh, b_mesh, b_ob, false);
+ if(can_free_caches) {
+ b_ob.cache_release();
+ }
+
/* free derived mesh */
b_data.meshes.remove(b_mesh);
}
- mesh->geometry_synced = true;
}
+ mesh->geometry_flags = requested_geometry_flags;
/* displacement method */
if(cmesh.data) {
@@ -728,6 +842,7 @@ void BlenderSync::sync_mesh_motion(BL::Object b_ob, Object *object, float motion
return;
}
+ /* TODO(sergey): Perform preliminary check for number of verticies. */
if(numverts) {
/* find attributes */
Attribute *attr_mP = mesh->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
@@ -759,13 +874,17 @@ void BlenderSync::sync_mesh_motion(BL::Object b_ob, Object *object, float motion
/* in case of new attribute, we verify if there really was any motion */
if(new_attribute) {
- if(i != numverts || memcmp(mP, &mesh->verts[0], sizeof(float3)*numverts) == 0) {
+ if(b_mesh.vertices.length() != numverts ||
+ memcmp(mP, &mesh->verts[0], sizeof(float3)*numverts) == 0)
+ {
/* no motion, remove attributes again */
+ VLOG(1) << "No actual deformation motion for object " << b_ob.name();
mesh->attributes.remove(ATTR_STD_MOTION_VERTEX_POSITION);
if(attr_mN)
mesh->attributes.remove(ATTR_STD_MOTION_VERTEX_NORMAL);
}
else if(time_index > 0) {
+ VLOG(1) << "Filling deformation motion for object " << b_ob.name();
/* motion, fill up previous steps that we might have skipped because
* they had no motion, but we need them anyway now */
float3 *P = &mesh->verts[0];
diff --git a/intern/cycles/blender/blender_object.cpp b/intern/cycles/blender/blender_object.cpp
index 1e07c5f9c96..432c4aaa078 100644
--- a/intern/cycles/blender/blender_object.cpp
+++ b/intern/cycles/blender/blender_object.cpp
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#include "camera.h"
@@ -30,6 +30,7 @@
#include "util_foreach.h"
#include "util_hash.h"
+#include "util_logging.h"
CCL_NAMESPACE_BEGIN
@@ -89,14 +90,17 @@ static uint object_ray_visibility(BL::Object b_ob)
/* Light */
-void BlenderSync::sync_light(BL::Object b_parent, int persistent_id[OBJECT_PERSISTENT_ID_SIZE], BL::Object b_ob, Transform& tfm)
+void BlenderSync::sync_light(BL::Object b_parent, int persistent_id[OBJECT_PERSISTENT_ID_SIZE], BL::Object b_ob, Transform& tfm, bool *use_portal)
{
/* test if we need to sync */
Light *light;
ObjectKey key(b_parent, persistent_id, b_ob);
- if(!light_map.sync(&light, b_ob, b_parent, key))
+ if(!light_map.sync(&light, b_ob, b_parent, key)) {
+ if(light->is_portal)
+ *use_portal = true;
return;
+ }
BL::Lamp b_lamp(b_ob.data());
@@ -168,6 +172,16 @@ void BlenderSync::sync_light(BL::Object b_parent, int persistent_id[OBJECT_PERSI
else
light->samples = samples;
+ light->max_bounces = get_int(clamp, "max_bounces");
+
+ if(light->type == LIGHT_AREA)
+ light->is_portal = get_boolean(clamp, "is_portal");
+ else
+ light->is_portal = false;
+
+ if(light->is_portal)
+ *use_portal = true;
+
/* visibility */
uint visibility = object_ray_visibility(b_ob);
light->use_diffuse = (visibility & PATH_RAY_DIFFUSE) != 0;
@@ -179,7 +193,7 @@ void BlenderSync::sync_light(BL::Object b_parent, int persistent_id[OBJECT_PERSI
light->tag_update(scene);
}
-void BlenderSync::sync_background_light()
+void BlenderSync::sync_background_light(bool use_portal)
{
BL::World b_world = b_scene.world();
@@ -188,19 +202,21 @@ void BlenderSync::sync_background_light()
PointerRNA cworld = RNA_pointer_get(&b_world.ptr, "cycles");
bool sample_as_light = get_boolean(cworld, "sample_as_light");
- if(sample_as_light) {
+ if(sample_as_light || use_portal) {
/* test if we need to sync */
Light *light;
ObjectKey key(b_world, 0, b_world);
if(light_map.sync(&light, b_world, b_world, key) ||
- world_recalc ||
- b_world.ptr.data != world_map)
+ world_recalc ||
+ b_world.ptr.data != world_map)
{
light->type = LIGHT_BACKGROUND;
light->map_resolution = get_int(cworld, "sample_map_resolution");
light->shader = scene->default_background;
-
+ light->use_mis = sample_as_light;
+ light->max_bounces = get_int(cworld, "max_bounces");
+
int samples = get_int(cworld, "samples");
if(get_boolean(cscene, "use_square_samples"))
light->samples = samples * samples;
@@ -219,8 +235,56 @@ void BlenderSync::sync_background_light()
/* Object */
-Object *BlenderSync::sync_object(BL::Object b_parent, int persistent_id[OBJECT_PERSISTENT_ID_SIZE], BL::DupliObject b_dupli_ob,
- Transform& tfm, uint layer_flag, float motion_time, bool hide_tris)
+/* TODO(sergey): Not really optimal, consider approaches based on k-DOP in order
+ * to reduce number of objects which are wrongly considered visible.
+ */
+static bool object_boundbox_clip(Scene *scene,
+ BL::Object b_ob,
+ Transform& tfm,
+ float margin)
+{
+ Camera *cam = scene->camera;
+ Transform& worldtondc = cam->worldtondc;
+ BL::Array<float, 24> boundbox = b_ob.bound_box();
+ float3 bb_min = make_float3(FLT_MAX, FLT_MAX, FLT_MAX),
+ bb_max = make_float3(-FLT_MAX, -FLT_MAX, -FLT_MAX);
+ bool all_behind = true;
+ for(int i = 0; i < 8; ++i) {
+ float3 p = make_float3(boundbox[3 * i + 0],
+ boundbox[3 * i + 1],
+ boundbox[3 * i + 2]);
+ p = transform_point(&tfm, p);
+ p = transform_point(&worldtondc, p);
+ if(p.z >= -margin) {
+ all_behind = false;
+ }
+ p /= p.z;
+ bb_min = min(bb_min, p);
+ bb_max = max(bb_max, p);
+ }
+ if(!all_behind) {
+ if(bb_min.x >= 1.0f + margin ||
+ bb_min.y >= 1.0f + margin ||
+ bb_max.x <= -margin ||
+ bb_max.y <= -margin)
+ {
+ return true;
+ }
+ return false;
+ }
+ return true;
+}
+
+Object *BlenderSync::sync_object(BL::Object b_parent,
+ int persistent_id[OBJECT_PERSISTENT_ID_SIZE],
+ BL::DupliObject b_dupli_ob,
+ Transform& tfm,
+ uint layer_flag,
+ float motion_time,
+ bool hide_tris,
+ bool use_camera_cull,
+ float camera_cull_margin,
+ bool *use_portal)
{
BL::Object b_ob = (b_dupli_ob ? b_dupli_ob.object() : b_parent);
bool motion = motion_time != 0.0f;
@@ -229,7 +293,7 @@ Object *BlenderSync::sync_object(BL::Object b_parent, int persistent_id[OBJECT_P
if(object_is_light(b_ob)) {
/* don't use lamps for excluded layers used as mask layer */
if(!motion && !((layer_flag & render_layer.holdout_layer) && (layer_flag & render_layer.exclude_layer)))
- sync_light(b_parent, persistent_id, b_ob, tfm);
+ sync_light(b_parent, persistent_id, b_ob, tfm, use_portal);
return NULL;
}
@@ -238,6 +302,11 @@ Object *BlenderSync::sync_object(BL::Object b_parent, int persistent_id[OBJECT_P
if(!object_is_mesh(b_ob))
return NULL;
+ /* Perform camera space culling. */
+ if(use_camera_cull && object_boundbox_clip(scene, b_ob, tfm, camera_cull_margin)) {
+ return NULL;
+ }
+
/* key to lookup object */
ObjectKey key(b_parent, persistent_id, b_ob);
Object *object;
@@ -246,9 +315,12 @@ Object *BlenderSync::sync_object(BL::Object b_parent, int persistent_id[OBJECT_P
if(motion) {
object = object_map.find(key);
- if(object && (scene->need_motion() == Scene::MOTION_PASS || object_use_motion(b_ob))) {
+ if(object && (scene->need_motion() == Scene::MOTION_PASS ||
+ object_use_motion(b_parent, b_ob)))
+ {
/* object transformation */
if(tfm != object->tfm) {
+ VLOG(1) << "Object " << b_ob.name() << " motion detected.";
if(motion_time == -1.0f) {
object->motion.pre = tfm;
object->use_motion = true;
@@ -326,8 +398,8 @@ Object *BlenderSync::sync_object(BL::Object b_parent, int persistent_id[OBJECT_P
mesh->use_motion_blur = false;
- if(object_use_motion(b_ob)) {
- if(object_use_deform_motion(b_ob)) {
+ if(object_use_motion(b_parent, b_ob)) {
+ if(object_use_deform_motion(b_parent, b_ob)) {
mesh->motion_steps = object_motion_steps(b_ob);
mesh->use_motion_blur = true;
}
@@ -352,7 +424,7 @@ Object *BlenderSync::sync_object(BL::Object b_parent, int persistent_id[OBJECT_P
object->random_id ^= hash_int(hash_string(b_parent.name().c_str()));
/* dupli texture coordinates */
- if (b_dupli_ob) {
+ 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());
}
@@ -410,9 +482,17 @@ static bool object_render_hide(BL::Object b_ob, bool top_level, bool parent_hide
/* hide original object for duplis */
BL::Object parent = b_ob.parent();
- if(parent && object_render_hide_original(b_ob.type(), parent.dupli_type()))
- if(parent_hide)
- hide_as_dupli_child_original = true;
+ while(parent) {
+ if(object_render_hide_original(b_ob.type(),
+ parent.dupli_type()))
+ {
+ if(parent_hide) {
+ hide_as_dupli_child_original = true;
+ break;
+ }
+ }
+ parent = parent.parent();
+ }
hide_triangles = hide_emitter;
@@ -454,16 +534,29 @@ void BlenderSync::sync_objects(BL::SpaceView3D b_v3d, float motion_time)
mesh_motion_synced.clear();
}
+ bool allow_camera_cull = false;
+ float camera_cull_margin = 0.0f;
+ if(b_scene.render().use_simplify()) {
+ PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles");
+ allow_camera_cull = scene->camera->type != CAMERA_PANORAMA &&
+ !b_scene.render().use_multiview() &&
+ get_boolean(cscene, "use_camera_cull");
+ if(allow_camera_cull) {
+ camera_cull_margin = get_float(cscene, "camera_cull_margin");
+ }
+ }
+
/* object loop */
BL::Scene::object_bases_iterator b_base;
BL::Scene b_sce = b_scene;
/* modifier result type (not exposed as enum in C++ API)
- * 1 : DAG_EVAL_PREVIEW
- * 2 : DAG_EVAL_RENDER
- */
- int dupli_settings = preview ? 1 : 2;
+ * 1 : DAG_EVAL_PREVIEW
+ * 2 : DAG_EVAL_RENDER
+ */
+ int dupli_settings = preview ? 1 : 2;
bool cancel = false;
+ bool use_portal = false;
for(; b_sce && !cancel; b_sce = b_sce.background_set()) {
for(b_sce.object_bases.begin(b_base); b_base != b_sce.object_bases.end() && !cancel; ++b_base) {
@@ -475,6 +568,12 @@ void BlenderSync::sync_objects(BL::SpaceView3D b_v3d, float motion_time)
if(!hide) {
progress.set_sync_status("Synchronizing object", b_ob.name());
+ PointerRNA cobject = RNA_pointer_get(&b_ob.ptr, "cycles");
+ bool use_camera_cull = allow_camera_cull && get_boolean(cobject, "use_camera_cull");
+ if(use_camera_cull) {
+ /* Need to have proper projection matrix. */
+ scene->camera->update();
+ }
if(b_ob.is_duplicator() && !object_render_hide_duplis(b_ob)) {
/* dupli objects */
b_ob.dupli_list_create(b_scene, dupli_settings);
@@ -494,7 +593,16 @@ void BlenderSync::sync_objects(BL::SpaceView3D b_v3d, float motion_time)
BL::Array<int, OBJECT_PERSISTENT_ID_SIZE> persistent_id = b_dup->persistent_id();
/* sync object and mesh or light data */
- Object *object = sync_object(b_ob, persistent_id.data, *b_dup, tfm, ob_layer, motion_time, hide_tris);
+ Object *object = sync_object(b_ob,
+ persistent_id.data,
+ *b_dup,
+ tfm,
+ ob_layer,
+ motion_time,
+ hide_tris,
+ use_camera_cull,
+ camera_cull_margin,
+ &use_portal);
/* sync possible particle data, note particle_id
* starts counting at 1, first is dummy particle */
@@ -514,7 +622,16 @@ void BlenderSync::sync_objects(BL::SpaceView3D b_v3d, float motion_time)
if(!object_render_hide(b_ob, true, true, hide_tris)) {
/* object itself */
Transform tfm = get_transform(b_ob.matrix_world());
- sync_object(b_ob, NULL, PointerRNA_NULL, tfm, ob_layer, motion_time, hide_tris);
+ sync_object(b_ob,
+ NULL,
+ PointerRNA_NULL,
+ tfm,
+ ob_layer,
+ motion_time,
+ hide_tris,
+ use_camera_cull,
+ camera_cull_margin,
+ &use_portal);
}
}
@@ -525,7 +642,7 @@ void BlenderSync::sync_objects(BL::SpaceView3D b_v3d, float motion_time)
progress.set_sync_status("");
if(!cancel && !motion) {
- sync_background_light();
+ sync_background_light(use_portal);
/* handle removed data and modified pointers */
if(light_map.post_sync())
@@ -542,7 +659,11 @@ void BlenderSync::sync_objects(BL::SpaceView3D b_v3d, float motion_time)
mesh_motion_synced.clear();
}
-void BlenderSync::sync_motion(BL::SpaceView3D b_v3d, BL::Object b_override, void **python_thread_state)
+void BlenderSync::sync_motion(BL::RenderSettings b_render,
+ BL::SpaceView3D b_v3d,
+ BL::Object b_override,
+ int width, int height,
+ void **python_thread_state)
{
if(scene->need_motion() == Scene::MOTION_NONE)
return;
@@ -562,6 +683,9 @@ void BlenderSync::sync_motion(BL::SpaceView3D b_v3d, BL::Object b_override, void
/* note iteration over motion_times set happens in sorted order */
foreach(float relative_time, motion_times) {
+ VLOG(1) << "Synchronizing motion for the relative time "
+ << relative_time << ".";
+
/* fixed shutter time to get previous and next frame for motion pass */
float shuttertime;
@@ -581,8 +705,12 @@ void BlenderSync::sync_motion(BL::SpaceView3D b_v3d, BL::Object b_override, void
python_thread_state_save(python_thread_state);
/* sync camera, only supports two times at the moment */
- if(relative_time == -1.0f || relative_time == 1.0f)
- sync_camera_motion(b_cam, relative_time);
+ if(relative_time == -1.0f || relative_time == 1.0f) {
+ sync_camera_motion(b_render,
+ b_cam,
+ width, height,
+ relative_time);
+ }
/* sync object */
sync_objects(b_v3d, relative_time);
diff --git a/intern/cycles/blender/blender_particles.cpp b/intern/cycles/blender/blender_particles.cpp
index 5b2782ec2ac..6d799e6e10e 100644
--- a/intern/cycles/blender/blender_particles.cpp
+++ b/intern/cycles/blender/blender_particles.cpp
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#include "mesh.h"
@@ -76,7 +76,7 @@ bool BlenderSync::sync_dupli_particle(BL::Object b_ob, BL::DupliObject b_dup, Ob
psys->particles.push_back(pa);
- if (object->particle_index != psys->particles.size() - 1)
+ if(object->particle_index != psys->particles.size() - 1)
scene->object_manager->tag_update(scene);
object->particle_system = psys;
object->particle_index = psys->particles.size() - 1;
diff --git a/intern/cycles/blender/blender_python.cpp b/intern/cycles/blender/blender_python.cpp
index b756d6acdb2..6581d0b997e 100644
--- a/intern/cycles/blender/blender_python.cpp
+++ b/intern/cycles/blender/blender_python.cpp
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#include <Python.h>
@@ -22,9 +22,11 @@
#include "blender_session.h"
#include "util_foreach.h"
+#include "util_logging.h"
#include "util_md5.h"
#include "util_opengl.h"
#include "util_path.h"
+#include "util_types.h"
#ifdef WITH_OSL
#include "osl.h"
@@ -53,25 +55,53 @@ void python_thread_state_restore(void **python_thread_state)
*python_thread_state = NULL;
}
-static PyObject *init_func(PyObject *self, PyObject *args)
+static const char *PyC_UnicodeAsByte(PyObject *py_str, PyObject **coerce)
{
- const char *path, *user_path;
+#ifdef WIN32
+ /* bug [#31856] oddly enough, Python3.2 --> 3.3 on Windows will throw an
+ * exception here this needs to be fixed in python:
+ * see: bugs.python.org/issue15859 */
+ if(!PyUnicode_Check(py_str)) {
+ PyErr_BadArgument();
+ return "";
+ }
+#endif
+ if((*coerce = PyUnicode_EncodeFSDefault(py_str))) {
+ return PyBytes_AS_STRING(*coerce);
+ }
+ return "";
+}
- if(!PyArg_ParseTuple(args, "ss", &path, &user_path))
+static PyObject *init_func(PyObject * /*self*/, PyObject *args)
+{
+ PyObject *path, *user_path;
+ int headless;
+
+ if(!PyArg_ParseTuple(args, "OOi", &path, &user_path, &headless)) {
return NULL;
-
- path_init(path, user_path);
+ }
+
+ PyObject *path_coerce = NULL, *user_path_coerce = NULL;
+ path_init(PyC_UnicodeAsByte(path, &path_coerce),
+ PyC_UnicodeAsByte(user_path, &user_path_coerce));
+ Py_XDECREF(path_coerce);
+ Py_XDECREF(user_path_coerce);
+
+ BlenderSession::headless = headless;
Py_RETURN_NONE;
}
-static PyObject *create_func(PyObject *self, PyObject *args)
+static PyObject *create_func(PyObject * /*self*/, PyObject *args)
{
PyObject *pyengine, *pyuserpref, *pydata, *pyscene, *pyregion, *pyv3d, *pyrv3d;
int preview_osl;
- if(!PyArg_ParseTuple(args, "OOOOOOOi", &pyengine, &pyuserpref, &pydata, &pyscene, &pyregion, &pyv3d, &pyrv3d, &preview_osl))
+ if(!PyArg_ParseTuple(args, "OOOOOOOi", &pyengine, &pyuserpref, &pydata, &pyscene,
+ &pyregion, &pyv3d, &pyrv3d, &preview_osl))
+ {
return NULL;
+ }
/* RNA */
PointerRNA engineptr;
@@ -83,7 +113,7 @@ static PyObject *create_func(PyObject *self, PyObject *args)
BL::UserPreferences userpref(userprefptr);
PointerRNA dataptr;
- RNA_id_pointer_create((ID*)PyLong_AsVoidPtr(pydata), &dataptr);
+ RNA_main_pointer_create((Main*)PyLong_AsVoidPtr(pydata), &dataptr);
BL::BlendData data(dataptr);
PointerRNA sceneptr;
@@ -91,15 +121,15 @@ static PyObject *create_func(PyObject *self, PyObject *args)
BL::Scene scene(sceneptr);
PointerRNA regionptr;
- RNA_id_pointer_create((ID*)pylong_as_voidptr_typesafe(pyregion), &regionptr);
+ RNA_pointer_create(NULL, &RNA_Region, pylong_as_voidptr_typesafe(pyregion), &regionptr);
BL::Region region(regionptr);
PointerRNA v3dptr;
- RNA_id_pointer_create((ID*)pylong_as_voidptr_typesafe(pyv3d), &v3dptr);
+ RNA_pointer_create(NULL, &RNA_SpaceView3D, pylong_as_voidptr_typesafe(pyv3d), &v3dptr);
BL::SpaceView3D v3d(v3dptr);
PointerRNA rv3dptr;
- RNA_id_pointer_create((ID*)pylong_as_voidptr_typesafe(pyrv3d), &rv3dptr);
+ RNA_pointer_create(NULL, &RNA_RegionView3D, pylong_as_voidptr_typesafe(pyrv3d), &rv3dptr);
BL::RegionView3D rv3d(rv3dptr);
/* create session */
@@ -134,14 +164,14 @@ static PyObject *create_func(PyObject *self, PyObject *args)
return PyLong_FromVoidPtr(session);
}
-static PyObject *free_func(PyObject *self, PyObject *value)
+static PyObject *free_func(PyObject * /*self*/, PyObject *value)
{
delete (BlenderSession*)PyLong_AsVoidPtr(value);
Py_RETURN_NONE;
}
-static PyObject *render_func(PyObject *self, PyObject *value)
+static PyObject *render_func(PyObject * /*self*/, PyObject *value)
{
BlenderSession *session = (BlenderSession*)PyLong_AsVoidPtr(value);
@@ -155,14 +185,14 @@ static PyObject *render_func(PyObject *self, PyObject *value)
}
/* pixel_array and result passed as pointers */
-static PyObject *bake_func(PyObject *self, PyObject *args)
+static PyObject *bake_func(PyObject * /*self*/, PyObject *args)
{
PyObject *pysession, *pyobject;
PyObject *pypixel_array, *pyresult;
const char *pass_type;
- int num_pixels, depth;
+ int num_pixels, depth, object_id;
- if(!PyArg_ParseTuple(args, "OOsOiiO", &pysession, &pyobject, &pass_type, &pypixel_array, &num_pixels, &depth, &pyresult))
+ if(!PyArg_ParseTuple(args, "OOsiOiiO", &pysession, &pyobject, &pass_type, &object_id, &pypixel_array, &num_pixels, &depth, &pyresult))
return NULL;
BlenderSession *session = (BlenderSession*)PyLong_AsVoidPtr(pysession);
@@ -174,19 +204,19 @@ static PyObject *bake_func(PyObject *self, PyObject *args)
void *b_result = PyLong_AsVoidPtr(pyresult);
PointerRNA bakepixelptr;
- RNA_id_pointer_create((ID*)PyLong_AsVoidPtr(pypixel_array), &bakepixelptr);
+ RNA_pointer_create(NULL, &RNA_BakePixel, PyLong_AsVoidPtr(pypixel_array), &bakepixelptr);
BL::BakePixel b_bake_pixel(bakepixelptr);
python_thread_state_save(&session->python_thread_state);
- session->bake(b_object, pass_type, b_bake_pixel, (size_t)num_pixels, depth, (float *)b_result);
+ session->bake(b_object, pass_type, object_id, b_bake_pixel, (size_t)num_pixels, depth, (float *)b_result);
python_thread_state_restore(&session->python_thread_state);
Py_RETURN_NONE;
}
-static PyObject *draw_func(PyObject *self, PyObject *args)
+static PyObject *draw_func(PyObject * /*self*/, PyObject *args)
{
PyObject *pysession, *pyv3d, *pyrv3d;
@@ -206,7 +236,7 @@ static PyObject *draw_func(PyObject *self, PyObject *args)
Py_RETURN_NONE;
}
-static PyObject *reset_func(PyObject *self, PyObject *args)
+static PyObject *reset_func(PyObject * /*self*/, PyObject *args)
{
PyObject *pysession, *pydata, *pyscene;
@@ -216,7 +246,7 @@ static PyObject *reset_func(PyObject *self, PyObject *args)
BlenderSession *session = (BlenderSession*)PyLong_AsVoidPtr(pysession);
PointerRNA dataptr;
- RNA_id_pointer_create((ID*)PyLong_AsVoidPtr(pydata), &dataptr);
+ RNA_main_pointer_create((Main*)PyLong_AsVoidPtr(pydata), &dataptr);
BL::BlendData b_data(dataptr);
PointerRNA sceneptr;
@@ -232,7 +262,7 @@ static PyObject *reset_func(PyObject *self, PyObject *args)
Py_RETURN_NONE;
}
-static PyObject *sync_func(PyObject *self, PyObject *value)
+static PyObject *sync_func(PyObject * /*self*/, PyObject *value)
{
BlenderSession *session = (BlenderSession*)PyLong_AsVoidPtr(value);
@@ -245,7 +275,7 @@ static PyObject *sync_func(PyObject *self, PyObject *value)
Py_RETURN_NONE;
}
-static PyObject *available_devices_func(PyObject *self, PyObject *args)
+static PyObject *available_devices_func(PyObject * /*self*/, PyObject * /*args*/)
{
vector<DeviceInfo>& devices = Device::available_devices();
PyObject *ret = PyTuple_New(devices.size());
@@ -260,7 +290,7 @@ static PyObject *available_devices_func(PyObject *self, PyObject *args)
#ifdef WITH_OSL
-static PyObject *osl_update_node_func(PyObject *self, PyObject *args)
+static PyObject *osl_update_node_func(PyObject * /*self*/, PyObject *args)
{
PyObject *pynodegroup, *pynode;
const char *filepath = NULL;
@@ -362,14 +392,8 @@ static PyObject *osl_update_node_func(PyObject *self, PyObject *args)
/* find socket socket */
BL::NodeSocket b_sock(PointerRNA_NULL);
- if (param->isoutput) {
-#if OSL_LIBRARY_VERSION_CODE < 10500
- b_sock = b_node.outputs[param->name];
-#else
+ if(param->isoutput) {
b_sock = b_node.outputs[param->name.string()];
-#endif
-
-
/* remove if type no longer matches */
if(b_sock && b_sock.bl_idname() != socket_type) {
b_node.outputs.remove(b_sock);
@@ -377,12 +401,7 @@ static PyObject *osl_update_node_func(PyObject *self, PyObject *args)
}
}
else {
-#if OSL_LIBRARY_VERSION_CODE < 10500
- b_sock = b_node.inputs[param->name];
-#else
b_sock = b_node.inputs[param->name.string()];
-#endif
-
/* remove if type no longer matches */
if(b_sock && b_sock.bl_idname() != socket_type) {
b_node.inputs.remove(b_sock);
@@ -427,7 +446,7 @@ static PyObject *osl_update_node_func(PyObject *self, PyObject *args)
removed = false;
- for (b_node.inputs.begin(b_input); b_input != b_node.inputs.end(); ++b_input) {
+ for(b_node.inputs.begin(b_input); b_input != b_node.inputs.end(); ++b_input) {
if(used_sockets.find(b_input->ptr.data) == used_sockets.end()) {
b_node.inputs.remove(*b_input);
removed = true;
@@ -435,7 +454,7 @@ static PyObject *osl_update_node_func(PyObject *self, PyObject *args)
}
}
- for (b_node.outputs.begin(b_output); b_output != b_node.outputs.end(); ++b_output) {
+ for(b_node.outputs.begin(b_output); b_output != b_node.outputs.end(); ++b_output) {
if(used_sockets.find(b_output->ptr.data) == used_sockets.end()) {
b_node.outputs.remove(*b_output);
removed = true;
@@ -447,7 +466,7 @@ static PyObject *osl_update_node_func(PyObject *self, PyObject *args)
Py_RETURN_TRUE;
}
-static PyObject *osl_compile_func(PyObject *self, PyObject *args)
+static PyObject *osl_compile_func(PyObject * /*self*/, PyObject *args)
{
const char *inputfile = NULL, *outputfile = NULL;
@@ -462,6 +481,25 @@ static PyObject *osl_compile_func(PyObject *self, PyObject *args)
}
#endif
+static PyObject *system_info_func(PyObject * /*self*/, PyObject * /*value*/)
+{
+ string system_info = Device::device_capabilities();
+ return PyUnicode_FromString(system_info.c_str());
+}
+
+#ifdef WITH_OPENCL
+static PyObject *opencl_disable_func(PyObject * /*self*/, PyObject * /*value*/)
+{
+ VLOG(2) << "Disabling OpenCL platform.";
+#ifdef WIN32
+ putenv("CYCLES_OPENCL_TEST=NONE");
+#else
+ setenv("CYCLES_OPENCL_TEST", "NONE", 1);
+#endif
+ Py_RETURN_NONE;
+}
+#endif
+
static PyMethodDef methods[] = {
{"init", init_func, METH_VARARGS, ""},
{"create", create_func, METH_VARARGS, ""},
@@ -476,6 +514,10 @@ static PyMethodDef methods[] = {
{"osl_compile", osl_compile_func, METH_VARARGS, ""},
#endif
{"available_devices", available_devices_func, METH_NOARGS, ""},
+ {"system_info", system_info_func, METH_NOARGS, ""},
+#ifdef WITH_OPENCL
+ {"opencl_disable", opencl_disable_func, METH_NOARGS, ""},
+#endif
{NULL, NULL, 0, NULL},
};
diff --git a/intern/cycles/blender/blender_session.cpp b/intern/cycles/blender/blender_session.cpp
index 4ff3d89f9f1..04d05ee7b3c 100644
--- a/intern/cycles/blender/blender_session.cpp
+++ b/intern/cycles/blender/blender_session.cpp
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#include <stdlib.h>
@@ -32,6 +32,7 @@
#include "util_color.h"
#include "util_foreach.h"
#include "util_function.h"
+#include "util_logging.h"
#include "util_progress.h"
#include "util_time.h"
@@ -41,6 +42,8 @@
CCL_NAMESPACE_BEGIN
+bool BlenderSession::headless = false;
+
BlenderSession::BlenderSession(BL::RenderEngine b_engine_, BL::UserPreferences b_userpref_,
BL::BlendData b_data_, BL::Scene b_scene_)
: b_engine(b_engine_), b_userpref(b_userpref_), b_data(b_data_), b_render(b_engine_.render()), b_scene(b_scene_),
@@ -86,12 +89,14 @@ void BlenderSession::create()
void BlenderSession::create_session()
{
- SceneParams scene_params = BlenderSync::get_scene_params(b_scene, background);
SessionParams session_params = BlenderSync::get_session_params(b_engine, b_userpref, b_scene, background);
+ bool is_cpu = session_params.device.type == DEVICE_CPU;
+ SceneParams scene_params = BlenderSync::get_scene_params(b_scene, background, is_cpu);
bool session_pause = BlenderSync::get_session_pause(b_scene, background);
/* reset status/progress */
last_status = "";
+ last_error = "";
last_progress = -1.0f;
start_resize_time = 0.0;
@@ -111,13 +116,18 @@ void BlenderSession::create_session()
session->set_pause(session_pause);
/* create sync */
- sync = new BlenderSync(b_engine, b_data, b_scene, scene, !background, session->progress, session_params.device.type == DEVICE_CPU);
+ sync = new BlenderSync(b_engine, b_data, b_scene, scene, !background, session->progress, is_cpu);
if(b_v3d) {
if(session_pause == false) {
/* full data sync */
sync->sync_view(b_v3d, b_rv3d, width, height);
- sync->sync_data(b_v3d, b_engine.camera_override(), &python_thread_state);
+ sync->sync_data(b_render,
+ b_v3d,
+ b_engine.camera_override(),
+ width, height,
+ &python_thread_state,
+ b_rlay_name.c_str());
}
}
else {
@@ -129,7 +139,7 @@ void BlenderSession::create_session()
}
/* set buffer parameters */
- BufferParams buffer_params = BlenderSync::get_buffer_params(b_render, b_scene, b_v3d, b_rv3d, scene->camera, width, height);
+ BufferParams buffer_params = BlenderSync::get_buffer_params(b_render, b_v3d, b_rv3d, scene->camera, width, height);
session->reset(buffer_params, session_params.samples);
b_engine.use_highlight_tiles(session_params.progressive_refine == false);
@@ -141,8 +151,9 @@ void BlenderSession::reset_session(BL::BlendData b_data_, BL::Scene b_scene_)
b_render = b_engine.render();
b_scene = b_scene_;
- SceneParams scene_params = BlenderSync::get_scene_params(b_scene, background);
SessionParams session_params = BlenderSync::get_session_params(b_engine, b_userpref, b_scene, background);
+ const bool is_cpu = session_params.device.type == DEVICE_CPU;
+ SceneParams scene_params = BlenderSync::get_scene_params(b_scene, background, is_cpu);
width = render_resolution_x(b_render);
height = render_resolution_y(b_render);
@@ -173,7 +184,7 @@ void BlenderSession::reset_session(BL::BlendData b_data_, BL::Scene b_scene_)
session->stats.mem_peak = session->stats.mem_used;
/* sync object should be re-created */
- sync = new BlenderSync(b_engine, b_data, b_scene, scene, !background, session->progress, session_params.device.type == DEVICE_CPU);
+ sync = new BlenderSync(b_engine, b_data, b_scene, scene, !background, session->progress, is_cpu);
/* for final render we will do full data sync per render layer, only
* do some basic syncing here, no objects or materials for speed */
@@ -181,7 +192,7 @@ void BlenderSession::reset_session(BL::BlendData b_data_, BL::Scene b_scene_)
sync->sync_integrator();
sync->sync_camera(b_render, b_engine.camera_override(), width, height);
- BufferParams buffer_params = BlenderSync::get_buffer_params(b_render, b_scene, PointerRNA_NULL, PointerRNA_NULL, scene->camera, width, height);
+ BufferParams buffer_params = BlenderSync::get_buffer_params(b_render, PointerRNA_NULL, PointerRNA_NULL, scene->camera, width, height);
session->reset(buffer_params, session_params.samples);
b_engine.use_highlight_tiles(session_params.progressive_refine == false);
@@ -261,6 +272,18 @@ static PassType get_pass_type(BL::RenderPass b_pass)
case BL::RenderPass::type_SPECULAR:
case BL::RenderPass::type_REFLECTION:
return PASS_NONE;
+#ifdef WITH_CYCLES_DEBUG
+ case BL::RenderPass::type_DEBUG:
+ {
+ if(b_pass.debug_type() == BL::RenderPass::debug_type_BVH_TRAVERSAL_STEPS)
+ return PASS_BVH_TRAVERSAL_STEPS;
+ if(b_pass.debug_type() == BL::RenderPass::debug_type_BVH_TRAVERSED_INSTANCES)
+ return PASS_BVH_TRAVERSED_INSTANCES;
+ if(b_pass.debug_type() == BL::RenderPass::debug_type_RAY_BOUNCES)
+ return PASS_RAY_BOUNCES;
+ break;
+ }
+#endif
}
return PASS_NONE;
@@ -318,9 +341,9 @@ static ShaderEvalType get_shader_type(const string& pass_type)
return SHADER_EVAL_BAKE;
}
-static BL::RenderResult begin_render_result(BL::RenderEngine b_engine, int x, int y, int w, int h, const char *layername)
+static BL::RenderResult begin_render_result(BL::RenderEngine b_engine, int x, int y, int w, int h, const char *layername, const char *viewname)
{
- return b_engine.begin_result(x, y, w, h, layername);
+ return b_engine.begin_result(x, y, w, h, layername, viewname);
}
static void end_render_result(BL::RenderEngine b_engine, BL::RenderResult b_rr, bool cancel, bool do_merge_results)
@@ -337,10 +360,10 @@ void BlenderSession::do_write_update_render_tile(RenderTile& rtile, bool do_upda
int h = params.height;
/* get render result */
- BL::RenderResult b_rr = begin_render_result(b_engine, x, y, w, h, b_rlay_name.c_str());
+ BL::RenderResult b_rr = begin_render_result(b_engine, x, y, w, h, b_rlay_name.c_str(), b_rview_name.c_str());
/* can happen if the intersected rectangle gives 0 width or height */
- if (b_rr.ptr.data == NULL) {
+ if(b_rr.ptr.data == NULL) {
return;
}
@@ -353,10 +376,10 @@ void BlenderSession::do_write_update_render_tile(RenderTile& rtile, bool do_upda
BL::RenderLayer b_rlay = *b_single_rlay;
- if (do_update_only) {
+ if(do_update_only) {
/* update only needed */
- if (rtile.sample != 0) {
+ if(rtile.sample != 0) {
/* sample would be zero at initial tile update, which is only needed
* to tag tile form blender side as IN PROGRESS for proper highlight
* no buffers should be sent to blender yet
@@ -384,7 +407,7 @@ void BlenderSession::update_render_tile(RenderTile& rtile)
* be updated in blender side
* would need to be investigated a bit further, but for now shall be fine
*/
- if (!b_engine.is_preview())
+ if(!b_engine.is_preview())
do_write_update_render_tile(rtile, true);
else
do_write_update_render_tile(rtile, false);
@@ -398,17 +421,18 @@ void BlenderSession::render()
/* get buffer parameters */
SessionParams session_params = BlenderSync::get_session_params(b_engine, b_userpref, b_scene, background);
- BufferParams buffer_params = BlenderSync::get_buffer_params(b_render, b_scene, b_v3d, b_rv3d, scene->camera, width, height);
+ BufferParams buffer_params = BlenderSync::get_buffer_params(b_render, b_v3d, b_rv3d, scene->camera, width, height);
/* render each layer */
BL::RenderSettings r = b_scene.render();
- BL::RenderSettings::layers_iterator b_iter;
+ BL::RenderSettings::layers_iterator b_layer_iter;
+ BL::RenderResult::views_iterator b_view_iter;
- for(r.layers.begin(b_iter); b_iter != r.layers.end(); ++b_iter) {
- b_rlay_name = b_iter->name();
+ for(r.layers.begin(b_layer_iter); b_layer_iter != r.layers.end(); ++b_layer_iter) {
+ b_rlay_name = b_layer_iter->name();
- /* temporary render result to find needed passes */
- BL::RenderResult b_rr = begin_render_result(b_engine, 0, 0, 1, 1, b_rlay_name.c_str());
+ /* temporary render result to find needed passes and views */
+ BL::RenderResult b_rr = begin_render_result(b_engine, 0, 0, 1, 1, b_rlay_name.c_str(), NULL);
BL::RenderResult::layers_iterator b_single_rlay;
b_rr.layers.begin(b_single_rlay);
@@ -440,39 +464,59 @@ void BlenderSession::render()
}
}
- /* free result without merging */
- end_render_result(b_engine, b_rr, true, false);
-
buffer_params.passes = passes;
- scene->film->pass_alpha_threshold = b_iter->pass_alpha_threshold();
+ scene->film->pass_alpha_threshold = b_layer_iter->pass_alpha_threshold();
scene->film->tag_passes_update(scene, passes);
scene->film->tag_update(scene);
scene->integrator->tag_update(scene);
- /* update scene */
- sync->sync_camera(b_render, b_engine.camera_override(), width, height);
- sync->sync_data(b_v3d, b_engine.camera_override(), &python_thread_state, b_rlay_name.c_str());
+ for(b_rr.views.begin(b_view_iter); b_view_iter != b_rr.views.end(); ++b_view_iter) {
+ b_rview_name = b_view_iter->name();
- /* update number of samples per layer */
- int samples = sync->get_layer_samples();
- bool bound_samples = sync->get_layer_bound_samples();
+ /* set the current view */
+ b_engine.active_view_set(b_rview_name.c_str());
- if(samples != 0 && (!bound_samples || (samples < session_params.samples)))
- session->reset(buffer_params, samples);
- else
- session->reset(buffer_params, session_params.samples);
+ /* update scene */
+ sync->sync_camera(b_render, b_engine.camera_override(), width, height);
+ sync->sync_data(b_render,
+ b_v3d,
+ b_engine.camera_override(),
+ width, height,
+ &python_thread_state,
+ b_rlay_name.c_str());
- /* render */
- session->start();
- session->wait();
+ /* update number of samples per layer */
+ int samples = sync->get_layer_samples();
+ bool bound_samples = sync->get_layer_bound_samples();
+
+ if(samples != 0 && (!bound_samples || (samples < session_params.samples)))
+ session->reset(buffer_params, samples);
+ else
+ session->reset(buffer_params, session_params.samples);
+
+ /* render */
+ session->start();
+ session->wait();
+
+ if(session->progress.get_cancel())
+ break;
+ }
+
+ /* free result without merging */
+ end_render_result(b_engine, b_rr, true, false);
if(session->progress.get_cancel())
break;
}
+ double total_time, render_time;
+ session->progress.get_time(total_time, render_time);
+ VLOG(1) << "Total render time: " << total_time;
+ VLOG(1) << "Render time (without synchronization): " << render_time;
+
/* clear callback */
- session->write_render_tile_cb = NULL;
- session->update_render_tile_cb = NULL;
+ session->write_render_tile_cb = function_null;
+ session->update_render_tile_cb = function_null;
/* free all memory used (host and device), so we wouldn't leave render
* engine with extra memory allocated
@@ -484,23 +528,32 @@ void BlenderSession::render()
sync = NULL;
}
-static void populate_bake_data(BakeData *data, BL::BakePixel pixel_array, const int num_pixels)
+static void populate_bake_data(BakeData *data, const int object_id, BL::BakePixel pixel_array, const int num_pixels)
{
BL::BakePixel bp = pixel_array;
int i;
for(i=0; i < num_pixels; i++) {
- data->set(i, bp.primitive_id(), bp.uv(), bp.du_dx(), bp.du_dy(), bp.dv_dx(), bp.dv_dy());
+ if(bp.object_id() == object_id) {
+ data->set(i, bp.primitive_id(), bp.uv(), bp.du_dx(), bp.du_dy(), bp.dv_dx(), bp.dv_dy());
+ } else {
+ data->set_null(i);
+ }
bp = bp.next();
}
}
-void BlenderSession::bake(BL::Object b_object, const string& pass_type, BL::BakePixel pixel_array, const size_t num_pixels, const int depth, float result[])
+void BlenderSession::bake(BL::Object b_object, const string& pass_type, const int object_id, BL::BakePixel pixel_array, const size_t num_pixels, const int /*depth*/, float result[])
{
ShaderEvalType shader_type = get_shader_type(pass_type);
size_t object_index = OBJECT_NONE;
int tri_offset = 0;
+ /* Set baking flag in advance, so kernel loading can check if we need
+ * any baking capabilities.
+ */
+ scene->bake_manager->set_baking(true);
+
/* ensure kernels are loaded before we do any scene updates */
session->load_kernels();
@@ -523,14 +576,18 @@ void BlenderSession::bake(BL::Object b_object, const string& pass_type, BL::Bake
/* update scene */
sync->sync_camera(b_render, b_engine.camera_override(), width, height);
- sync->sync_data(b_v3d, b_engine.camera_override(), &python_thread_state);
+ sync->sync_data(b_render,
+ b_v3d,
+ b_engine.camera_override(),
+ width, height,
+ &python_thread_state,
+ b_rlay_name.c_str());
/* get buffer parameters */
SessionParams session_params = BlenderSync::get_session_params(b_engine, b_userpref, b_scene, background);
- BufferParams buffer_params = BlenderSync::get_buffer_params(b_render, b_scene, b_v3d, b_rv3d, scene->camera, width, height);
+ BufferParams buffer_params = BlenderSync::get_buffer_params(b_render, b_v3d, b_rv3d, scene->camera, width, height);
scene->bake_manager->set_shader_limit((size_t)b_engine.tile_x(), (size_t)b_engine.tile_y());
- scene->bake_manager->set_baking(true);
/* set number of samples */
session->tile_manager.set_samples(session_params.samples);
@@ -551,7 +608,7 @@ void BlenderSession::bake(BL::Object b_object, const string& pass_type, BL::Bake
BakeData *bake_data = scene->bake_manager->init(object, tri_offset, num_pixels);
- populate_bake_data(bake_data, pixel_array, num_pixels);
+ populate_bake_data(bake_data, object_id, pixel_array, num_pixels);
/* set number of samples */
session->tile_manager.set_samples(session_params.samples);
@@ -585,7 +642,7 @@ void BlenderSession::do_write_update_render_result(BL::RenderResult b_rr, BL::Re
vector<float> pixels(params.width*params.height*4);
- if (!do_update_only) {
+ if(!do_update_only) {
/* copy each pass */
BL::RenderLayer::passes_iterator b_iter;
@@ -603,10 +660,12 @@ void BlenderSession::do_write_update_render_result(BL::RenderResult b_rr, BL::Re
b_pass.rect(&pixels[0]);
}
}
-
- /* copy combined pass */
- if(buffers->get_pass_rect(PASS_COMBINED, exposure, rtile.sample, 4, &pixels[0]))
- b_rlay.rect(&pixels[0]);
+ else {
+ /* copy combined pass */
+ BL::RenderPass b_combined_pass(b_rlay.passes.find_by_type(BL::RenderPass::type_COMBINED, b_rview_name.c_str()));
+ if(buffers->get_pass_rect(PASS_COMBINED, exposure, rtile.sample, 4, &pixels[0]))
+ b_combined_pass.rect(&pixels[0]);
+ }
/* tag result as updated */
b_engine.update_result(b_rr);
@@ -629,8 +688,9 @@ void BlenderSession::synchronize()
return;
/* on session/scene parameter changes, we recreate session entirely */
- SceneParams scene_params = BlenderSync::get_scene_params(b_scene, background);
SessionParams session_params = BlenderSync::get_session_params(b_engine, b_userpref, b_scene, background);
+ const bool is_cpu = session_params.device.type == DEVICE_CPU;
+ SceneParams scene_params = BlenderSync::get_scene_params(b_scene, background, is_cpu);
bool session_pause = BlenderSync::get_session_pause(b_scene, background);
if(session->params.modified(session_params) ||
@@ -663,7 +723,12 @@ void BlenderSession::synchronize()
}
/* data and camera synchronize */
- sync->sync_data(b_v3d, b_engine.camera_override(), &python_thread_state);
+ sync->sync_data(b_render,
+ b_v3d,
+ b_engine.camera_override(),
+ width, height,
+ &python_thread_state,
+ b_rlay_name.c_str());
if(b_rv3d)
sync->sync_view(b_v3d, b_rv3d, width, height);
@@ -675,7 +740,7 @@ void BlenderSession::synchronize()
/* reset if needed */
if(scene->need_reset()) {
- BufferParams buffer_params = BlenderSync::get_buffer_params(b_render, b_scene, b_v3d, b_rv3d, scene->camera, width, height);
+ BufferParams buffer_params = BlenderSync::get_buffer_params(b_render, b_v3d, b_rv3d, scene->camera, width, height);
session->reset(buffer_params, session_params.samples);
/* reset time */
@@ -730,7 +795,7 @@ bool BlenderSession::draw(int w, int h)
/* reset if requested */
if(reset) {
SessionParams session_params = BlenderSync::get_session_params(b_engine, b_userpref, b_scene, background);
- BufferParams buffer_params = BlenderSync::get_buffer_params(b_render, b_scene, b_v3d, b_rv3d, scene->camera, width, height);
+ BufferParams buffer_params = BlenderSync::get_buffer_params(b_render, b_v3d, b_rv3d, scene->camera, width, height);
bool session_pause = BlenderSync::get_session_pause(b_scene, background);
if(session_pause == false) {
@@ -747,7 +812,7 @@ bool BlenderSession::draw(int w, int h)
update_status_progress();
/* draw */
- BufferParams buffer_params = BlenderSync::get_buffer_params(b_render, b_scene, b_v3d, b_rv3d, scene->camera, width, height);
+ BufferParams buffer_params = BlenderSync::get_buffer_params(b_render, b_v3d, b_rv3d, scene->camera, width, height);
DeviceDrawParams draw_params;
if(session->params.display_buffer_linear) {
@@ -763,19 +828,23 @@ void BlenderSession::get_status(string& status, string& substatus)
session->progress.get_status(status, substatus);
}
-void BlenderSession::get_progress(float& progress, double& total_time)
+void BlenderSession::get_progress(float& progress, double& total_time, double& render_time)
{
double tile_time;
int tile, sample, samples_per_tile;
int tile_total = session->tile_manager.state.num_tiles;
+ int samples = session->tile_manager.state.sample + 1;
+ int total_samples = session->tile_manager.num_samples;
- session->progress.get_tile(tile, total_time, tile_time);
+ session->progress.get_tile(tile, total_time, render_time, tile_time);
sample = session->progress.get_sample();
samples_per_tile = session->tile_manager.num_samples;
- if(samples_per_tile && tile_total)
+ if(background && samples_per_tile && tile_total)
progress = ((float)sample / (float)(tile_total * samples_per_tile));
+ else if(!background && samples > 0 && total_samples != USHRT_MAX)
+ progress = ((float)samples) / total_samples;
else
progress = 0.0;
}
@@ -805,40 +874,36 @@ void BlenderSession::update_status_progress()
string timestatus, status, substatus;
string scene = "";
float progress;
- double total_time, remaining_time = 0;
+ double total_time, remaining_time = 0, render_time;
char time_str[128];
float mem_used = (float)session->stats.mem_used / 1024.0f / 1024.0f;
float mem_peak = (float)session->stats.mem_peak / 1024.0f / 1024.0f;
- int samples = session->tile_manager.state.sample + 1;
- int total_samples = session->tile_manager.num_samples;
get_status(status, substatus);
- get_progress(progress, total_time);
+ get_progress(progress, total_time, render_time);
-
+ if(progress > 0)
+ remaining_time = (1.0 - (double)progress) * (render_time / (double)progress);
if(background) {
- if(progress>0)
- remaining_time = (1-progress) * (total_time / progress);
-
scene += " | " + b_scene.name();
if(b_rlay_name != "")
scene += ", " + b_rlay_name;
+
+ if(b_rview_name != "")
+ scene += ", " + b_rview_name;
}
else {
- BLI_timestr(total_time, time_str, sizeof(time_str));
+ BLI_timecode_string_from_time_simple(time_str, sizeof(time_str), total_time);
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));
+
+ if(remaining_time > 0) {
+ BLI_timecode_string_from_time_simple(time_str, sizeof(time_str), remaining_time);
timestatus += "Remaining:" + string(time_str) + " | ";
}
-
- timestatus += string_printf("Mem:%.2fM, Peak:%.2fM", mem_used, mem_peak);
+
+ timestatus += string_printf("Mem:%.2fM, Peak:%.2fM", (double)mem_used, (double)mem_peak);
if(status.size() > 0)
status = " | " + status;
@@ -854,6 +919,21 @@ void BlenderSession::update_status_progress()
b_engine.update_progress(progress);
last_progress = progress;
}
+
+ if(session->progress.get_error()) {
+ string error = session->progress.get_error_message();
+ if(error != last_error) {
+ /* TODO(sergey): Currently C++ RNA API doesn't let us to
+ * use mnemonic name for the variable. Would be nice to
+ * have this figured out.
+ *
+ * For until then, 1 << 5 means RPT_ERROR.
+ */
+ b_engine.report(1 << 5, error.c_str());
+ b_engine.error_set(error.c_str());
+ last_error = error;
+ }
+ }
}
void BlenderSession::tag_update()
@@ -952,6 +1032,18 @@ void BlenderSession::builtin_image_info(const string &builtin_name, void *builti
is_float = true;
}
+ else {
+ /* TODO(sergey): Check we're indeed in shader node tree. */
+ PointerRNA ptr;
+ RNA_pointer_create(NULL, &RNA_Node, builtin_data, &ptr);
+ BL::Node b_node(ptr);
+ if(b_node.is_a(&RNA_ShaderNodeTexPointDensity)) {
+ BL::ShaderNodeTexPointDensity b_point_density_node(b_node);
+ channels = 4;
+ width = height = depth = b_point_density_node.resolution();
+ is_float = true;
+ }
+ }
}
bool BlenderSession::builtin_image_pixels(const string &builtin_name, void *builtin_data, unsigned char *pixels)
@@ -971,18 +1063,19 @@ bool BlenderSession::builtin_image_pixels(const string &builtin_name, void *buil
unsigned char *image_pixels;
image_pixels = image_get_pixels_for_frame(b_image, frame);
+ size_t num_pixels = ((size_t)width) * height;
if(image_pixels) {
- memcpy(pixels, image_pixels, width * height * channels * sizeof(unsigned char));
+ memcpy(pixels, image_pixels, num_pixels * channels * sizeof(unsigned char));
MEM_freeN(image_pixels);
}
else {
if(channels == 1) {
- memset(pixels, 0, width * height * sizeof(unsigned char));
+ memset(pixels, 0, num_pixels * sizeof(unsigned char));
}
else {
unsigned char *cp = pixels;
- for(int i = 0; i < width * height; i++, cp += channels) {
+ for(size_t i = 0; i < num_pixels; i++, cp += channels) {
cp[0] = 255;
cp[1] = 0;
cp[2] = 255;
@@ -994,7 +1087,7 @@ bool BlenderSession::builtin_image_pixels(const string &builtin_name, void *buil
/* premultiply, byte images are always straight for blender */
unsigned char *cp = pixels;
- for(int i = 0; i < width * height; i++, cp += channels) {
+ for(size_t i = 0; i < num_pixels; i++, cp += channels) {
cp[0] = (cp[0] * cp[3]) >> 8;
cp[1] = (cp[1] * cp[3]) >> 8;
cp[2] = (cp[2] * cp[3]) >> 8;
@@ -1023,18 +1116,19 @@ bool BlenderSession::builtin_image_float_pixels(const string &builtin_name, void
float *image_pixels;
image_pixels = image_get_float_pixels_for_frame(b_image, frame);
+ size_t num_pixels = ((size_t)width) * height;
if(image_pixels) {
- memcpy(pixels, image_pixels, width * height * channels * sizeof(float));
+ memcpy(pixels, image_pixels, num_pixels * channels * sizeof(float));
MEM_freeN(image_pixels);
}
else {
if(channels == 1) {
- memset(pixels, 0, width * height * sizeof(float));
+ memset(pixels, 0, num_pixels * sizeof(float));
}
else {
float *fp = pixels;
- for(int i = 0; i < width * height; i++, fp += channels) {
+ for(int i = 0; i < num_pixels; i++, fp += channels) {
fp[0] = 1.0f;
fp[1] = 0.0f;
fp[2] = 1.0f;
@@ -1060,11 +1154,12 @@ bool BlenderSession::builtin_image_float_pixels(const string &builtin_name, void
int width = resolution.x * amplify;
int height = resolution.y * amplify;
int depth = resolution.z * amplify;
+ size_t num_pixels = ((size_t)width) * height * depth;
if(builtin_name == Attribute::standard_name(ATTR_STD_VOLUME_DENSITY)) {
SmokeDomainSettings_density_grid_get_length(&b_domain.ptr, &length);
- if(length == width*height*depth) {
+ if(length == num_pixels) {
SmokeDomainSettings_density_grid_get(&b_domain.ptr, pixels);
return true;
}
@@ -1074,7 +1169,7 @@ bool BlenderSession::builtin_image_float_pixels(const string &builtin_name, void
* as 1500..3000 K with the first part faded to zero density */
SmokeDomainSettings_flame_grid_get_length(&b_domain.ptr, &length);
- if(length == width*height*depth) {
+ if(length == num_pixels) {
SmokeDomainSettings_flame_grid_get(&b_domain.ptr, pixels);
return true;
}
@@ -1083,7 +1178,7 @@ bool BlenderSession::builtin_image_float_pixels(const string &builtin_name, void
/* the RGB is "premultiplied" by density for better interpolation results */
SmokeDomainSettings_color_grid_get_length(&b_domain.ptr, &length);
- if(length == width*height*depth*4) {
+ if(length == num_pixels*4) {
SmokeDomainSettings_color_grid_get(&b_domain.ptr, pixels);
return true;
}
@@ -1091,6 +1186,17 @@ bool BlenderSession::builtin_image_float_pixels(const string &builtin_name, void
fprintf(stderr, "Cycles error: unexpected smoke volume resolution, skipping\n");
}
+ else {
+ /* TODO(sergey): Check we're indeed in shader node tree. */
+ PointerRNA ptr;
+ RNA_pointer_create(NULL, &RNA_Node, builtin_data, &ptr);
+ BL::Node b_node(ptr);
+ if(b_node.is_a(&RNA_ShaderNodeTexPointDensity)) {
+ BL::ShaderNodeTexPointDensity b_point_density_node(b_node);
+ int length;
+ b_point_density_node.calc_point_density(b_scene, &length, &pixels);
+ }
+ }
return false;
}
diff --git a/intern/cycles/blender/blender_session.h b/intern/cycles/blender/blender_session.h
index ac685118b3d..708776dc8ca 100644
--- a/intern/cycles/blender/blender_session.h
+++ b/intern/cycles/blender/blender_session.h
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#ifndef __BLENDER_SESSION_H__
@@ -52,7 +52,7 @@ public:
/* offline render */
void render();
- void bake(BL::Object b_object, const string& pass_type, BL::BakePixel pixel_array, const size_t num_pixels, const int depth, float pixels[]);
+ void bake(BL::Object b_object, const string& pass_type, const int object_id, BL::BakePixel pixel_array, const size_t num_pixels, const int depth, float pixels[]);
void write_render_result(BL::RenderResult b_rr, BL::RenderLayer b_rlay, RenderTile& rtile);
void write_render_tile(RenderTile& rtile);
@@ -70,12 +70,13 @@ public:
void tag_redraw();
void tag_update();
void get_status(string& status, string& substatus);
- void get_progress(float& progress, double& total_time);
+ void get_progress(float& progress, double& total_time, double& render_time);
void test_cancel();
void update_status_progress();
void update_bake_progress();
bool background;
+ static bool headless;
Session *session;
Scene *scene;
BlenderSync *sync;
@@ -89,8 +90,10 @@ public:
BL::SpaceView3D b_v3d;
BL::RegionView3D b_rv3d;
string b_rlay_name;
+ string b_rview_name;
string last_status;
+ string last_error;
float last_progress;
int width, height;
diff --git a/intern/cycles/blender/blender_shader.cpp b/intern/cycles/blender/blender_shader.cpp
index 33c7bf5f859..42aab52e294 100644
--- a/intern/cycles/blender/blender_shader.cpp
+++ b/intern/cycles/blender/blender_shader.cpp
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#include "background.h"
@@ -22,6 +22,7 @@
#include "scene.h"
#include "shader.h"
+#include "blender_texture.h"
#include "blender_sync.h"
#include "blender_util.h"
@@ -106,7 +107,7 @@ static ShaderSocketType convert_socket_type(BL::NodeSocket b_socket)
}
}
-static void set_default_value(ShaderInput *input, BL::Node b_node, BL::NodeSocket b_sock, BL::BlendData b_data, BL::ID b_id)
+static void set_default_value(ShaderInput *input, BL::NodeSocket b_sock, BL::BlendData b_data, BL::ID b_id)
{
/* copy values for non linked inputs */
switch(input->type) {
@@ -179,53 +180,59 @@ static bool is_output_node(BL::Node b_node)
|| b_node.is_a(&RNA_ShaderNodeOutputLamp));
}
-static ShaderNode *add_node(Scene *scene, BL::BlendData b_data, BL::Scene b_scene, ShaderGraph *graph, BL::ShaderNodeTree b_ntree, BL::ShaderNode b_node)
+static ShaderNode *add_node(Scene *scene,
+ BL::RenderEngine b_engine,
+ BL::BlendData b_data,
+ BL::Scene b_scene,
+ ShaderGraph *graph,
+ BL::ShaderNodeTree b_ntree,
+ BL::ShaderNode b_node)
{
ShaderNode *node = NULL;
/* existing blender nodes */
- if (b_node.is_a(&RNA_ShaderNodeRGBCurve)) {
+ if(b_node.is_a(&RNA_ShaderNodeRGBCurve)) {
BL::ShaderNodeRGBCurve b_curve_node(b_node);
RGBCurvesNode *curves = new RGBCurvesNode();
curvemapping_color_to_array(b_curve_node.mapping(), curves->curves, RAMP_TABLE_SIZE, true);
node = curves;
}
- if (b_node.is_a(&RNA_ShaderNodeVectorCurve)) {
+ if(b_node.is_a(&RNA_ShaderNodeVectorCurve)) {
BL::ShaderNodeVectorCurve b_curve_node(b_node);
VectorCurvesNode *curves = new VectorCurvesNode();
curvemapping_color_to_array(b_curve_node.mapping(), curves->curves, RAMP_TABLE_SIZE, false);
node = curves;
}
- else if (b_node.is_a(&RNA_ShaderNodeValToRGB)) {
+ else if(b_node.is_a(&RNA_ShaderNodeValToRGB)) {
RGBRampNode *ramp = new RGBRampNode();
BL::ShaderNodeValToRGB b_ramp_node(b_node);
colorramp_to_array(b_ramp_node.color_ramp(), ramp->ramp, RAMP_TABLE_SIZE);
ramp->interpolate = b_ramp_node.color_ramp().interpolation() != BL::ColorRamp::interpolation_CONSTANT;
node = ramp;
}
- else if (b_node.is_a(&RNA_ShaderNodeRGB)) {
+ else if(b_node.is_a(&RNA_ShaderNodeRGB)) {
ColorNode *color = new ColorNode();
color->value = get_node_output_rgba(b_node, "Color");
node = color;
}
- else if (b_node.is_a(&RNA_ShaderNodeValue)) {
+ else if(b_node.is_a(&RNA_ShaderNodeValue)) {
ValueNode *value = new ValueNode();
value->value = get_node_output_value(b_node, "Value");
node = value;
}
- else if (b_node.is_a(&RNA_ShaderNodeCameraData)) {
+ else if(b_node.is_a(&RNA_ShaderNodeCameraData)) {
node = new CameraNode();
}
- else if (b_node.is_a(&RNA_ShaderNodeInvert)) {
+ else if(b_node.is_a(&RNA_ShaderNodeInvert)) {
node = new InvertNode();
}
- else if (b_node.is_a(&RNA_ShaderNodeGamma)) {
+ else if(b_node.is_a(&RNA_ShaderNodeGamma)) {
node = new GammaNode();
}
- else if (b_node.is_a(&RNA_ShaderNodeBrightContrast)) {
+ else if(b_node.is_a(&RNA_ShaderNodeBrightContrast)) {
node = new BrightContrastNode();
}
- else if (b_node.is_a(&RNA_ShaderNodeMixRGB)) {
+ else if(b_node.is_a(&RNA_ShaderNodeMixRGB)) {
BL::ShaderNodeMixRGB b_mix_node(b_node);
MixNode *mix = new MixNode();
mix->type = MixNode::type_enum[b_mix_node.blend_type()];
@@ -236,44 +243,44 @@ static ShaderNode *add_node(Scene *scene, BL::BlendData b_data, BL::Scene b_scen
mix->use_clamp = b_mix_node.use_clamp();
node = mix;
}
- else if (b_node.is_a(&RNA_ShaderNodeSeparateRGB)) {
+ else if(b_node.is_a(&RNA_ShaderNodeSeparateRGB)) {
node = new SeparateRGBNode();
}
- else if (b_node.is_a(&RNA_ShaderNodeCombineRGB)) {
+ else if(b_node.is_a(&RNA_ShaderNodeCombineRGB)) {
node = new CombineRGBNode();
}
- else if (b_node.is_a(&RNA_ShaderNodeSeparateHSV)) {
+ else if(b_node.is_a(&RNA_ShaderNodeSeparateHSV)) {
node = new SeparateHSVNode();
}
- else if (b_node.is_a(&RNA_ShaderNodeCombineHSV)) {
+ else if(b_node.is_a(&RNA_ShaderNodeCombineHSV)) {
node = new CombineHSVNode();
}
- else if (b_node.is_a(&RNA_ShaderNodeSeparateXYZ)) {
+ else if(b_node.is_a(&RNA_ShaderNodeSeparateXYZ)) {
node = new SeparateXYZNode();
}
- else if (b_node.is_a(&RNA_ShaderNodeCombineXYZ)) {
+ else if(b_node.is_a(&RNA_ShaderNodeCombineXYZ)) {
node = new CombineXYZNode();
}
- else if (b_node.is_a(&RNA_ShaderNodeHueSaturation)) {
+ else if(b_node.is_a(&RNA_ShaderNodeHueSaturation)) {
node = new HSVNode();
}
- else if (b_node.is_a(&RNA_ShaderNodeRGBToBW)) {
+ else if(b_node.is_a(&RNA_ShaderNodeRGBToBW)) {
node = new ConvertNode(SHADER_SOCKET_COLOR, SHADER_SOCKET_FLOAT);
}
- else if (b_node.is_a(&RNA_ShaderNodeMath)) {
+ else if(b_node.is_a(&RNA_ShaderNodeMath)) {
BL::ShaderNodeMath b_math_node(b_node);
MathNode *math = new MathNode();
math->type = MathNode::type_enum[b_math_node.operation()];
math->use_clamp = b_math_node.use_clamp();
node = math;
}
- else if (b_node.is_a(&RNA_ShaderNodeVectorMath)) {
+ else if(b_node.is_a(&RNA_ShaderNodeVectorMath)) {
BL::ShaderNodeVectorMath b_vector_math_node(b_node);
VectorMathNode *vmath = new VectorMathNode();
vmath->type = VectorMathNode::type_enum[b_vector_math_node.operation()];
node = vmath;
}
- else if (b_node.is_a(&RNA_ShaderNodeVectorTransform)) {
+ else if(b_node.is_a(&RNA_ShaderNodeVectorTransform)) {
BL::ShaderNodeVectorTransform b_vector_transform_node(b_node);
VectorTransformNode *vtransform = new VectorTransformNode();
vtransform->type = VectorTransformNode::type_enum[b_vector_transform_node.type()];
@@ -281,7 +288,7 @@ static ShaderNode *add_node(Scene *scene, BL::BlendData b_data, BL::Scene b_scen
vtransform->convert_to = VectorTransformNode::convert_space_enum[b_vector_transform_node.convert_to()];
node = vtransform;
}
- else if (b_node.is_a(&RNA_ShaderNodeNormal)) {
+ else if(b_node.is_a(&RNA_ShaderNodeNormal)) {
BL::Node::outputs_iterator out_it;
b_node.outputs.begin(out_it);
@@ -289,7 +296,7 @@ static ShaderNode *add_node(Scene *scene, BL::BlendData b_data, BL::Scene b_scen
norm->direction = get_node_output_vector(b_node, "Normal");
node = norm;
}
- else if (b_node.is_a(&RNA_ShaderNodeMapping)) {
+ else if(b_node.is_a(&RNA_ShaderNodeMapping)) {
BL::ShaderNodeMapping b_mapping_node(b_node);
MappingNode *mapping = new MappingNode();
@@ -297,31 +304,31 @@ static ShaderNode *add_node(Scene *scene, BL::BlendData b_data, BL::Scene b_scen
node = mapping;
}
- else if (b_node.is_a(&RNA_ShaderNodeFresnel)) {
+ else if(b_node.is_a(&RNA_ShaderNodeFresnel)) {
node = new FresnelNode();
}
- else if (b_node.is_a(&RNA_ShaderNodeLayerWeight)) {
+ else if(b_node.is_a(&RNA_ShaderNodeLayerWeight)) {
node = new LayerWeightNode();
}
- else if (b_node.is_a(&RNA_ShaderNodeAddShader)) {
+ else if(b_node.is_a(&RNA_ShaderNodeAddShader)) {
node = new AddClosureNode();
}
- else if (b_node.is_a(&RNA_ShaderNodeMixShader)) {
+ else if(b_node.is_a(&RNA_ShaderNodeMixShader)) {
node = new MixClosureNode();
}
- else if (b_node.is_a(&RNA_ShaderNodeAttribute)) {
+ else if(b_node.is_a(&RNA_ShaderNodeAttribute)) {
BL::ShaderNodeAttribute b_attr_node(b_node);
AttributeNode *attr = new AttributeNode();
attr->attribute = b_attr_node.attribute_name();
node = attr;
}
- else if (b_node.is_a(&RNA_ShaderNodeBackground)) {
+ else if(b_node.is_a(&RNA_ShaderNodeBackground)) {
node = new BackgroundNode();
}
- else if (b_node.is_a(&RNA_ShaderNodeHoldout)) {
+ else if(b_node.is_a(&RNA_ShaderNodeHoldout)) {
node = new HoldoutNode();
}
- else if (b_node.is_a(&RNA_ShaderNodeBsdfAnisotropic)) {
+ else if(b_node.is_a(&RNA_ShaderNodeBsdfAnisotropic)) {
BL::ShaderNodeBsdfAnisotropic b_aniso_node(b_node);
AnisotropicBsdfNode *aniso = new AnisotropicBsdfNode();
@@ -340,10 +347,10 @@ static ShaderNode *add_node(Scene *scene, BL::BlendData b_data, BL::Scene b_scen
node = aniso;
}
- else if (b_node.is_a(&RNA_ShaderNodeBsdfDiffuse)) {
+ else if(b_node.is_a(&RNA_ShaderNodeBsdfDiffuse)) {
node = new DiffuseBsdfNode();
}
- else if (b_node.is_a(&RNA_ShaderNodeSubsurfaceScattering)) {
+ else if(b_node.is_a(&RNA_ShaderNodeSubsurfaceScattering)) {
BL::ShaderNodeSubsurfaceScattering b_subsurface_node(b_node);
SubsurfaceScatteringNode *subsurface = new SubsurfaceScatteringNode();
@@ -359,7 +366,7 @@ static ShaderNode *add_node(Scene *scene, BL::BlendData b_data, BL::Scene b_scen
node = subsurface;
}
- else if (b_node.is_a(&RNA_ShaderNodeBsdfGlossy)) {
+ else if(b_node.is_a(&RNA_ShaderNodeBsdfGlossy)) {
BL::ShaderNodeBsdfGlossy b_glossy_node(b_node);
GlossyBsdfNode *glossy = new GlossyBsdfNode();
@@ -379,7 +386,7 @@ static ShaderNode *add_node(Scene *scene, BL::BlendData b_data, BL::Scene b_scen
}
node = glossy;
}
- else if (b_node.is_a(&RNA_ShaderNodeBsdfGlass)) {
+ else if(b_node.is_a(&RNA_ShaderNodeBsdfGlass)) {
BL::ShaderNodeBsdfGlass b_glass_node(b_node);
GlassBsdfNode *glass = new GlassBsdfNode();
switch(b_glass_node.distribution()) {
@@ -395,7 +402,7 @@ static ShaderNode *add_node(Scene *scene, BL::BlendData b_data, BL::Scene b_scen
}
node = glass;
}
- else if (b_node.is_a(&RNA_ShaderNodeBsdfRefraction)) {
+ else if(b_node.is_a(&RNA_ShaderNodeBsdfRefraction)) {
BL::ShaderNodeBsdfRefraction b_refraction_node(b_node);
RefractionBsdfNode *refraction = new RefractionBsdfNode();
switch(b_refraction_node.distribution()) {
@@ -411,7 +418,7 @@ static ShaderNode *add_node(Scene *scene, BL::BlendData b_data, BL::Scene b_scen
}
node = refraction;
}
- else if (b_node.is_a(&RNA_ShaderNodeBsdfToon)) {
+ else if(b_node.is_a(&RNA_ShaderNodeBsdfToon)) {
BL::ShaderNodeBsdfToon b_toon_node(b_node);
ToonBsdfNode *toon = new ToonBsdfNode();
switch(b_toon_node.component()) {
@@ -424,7 +431,7 @@ static ShaderNode *add_node(Scene *scene, BL::BlendData b_data, BL::Scene b_scen
}
node = toon;
}
- else if (b_node.is_a(&RNA_ShaderNodeBsdfHair)) {
+ else if(b_node.is_a(&RNA_ShaderNodeBsdfHair)) {
BL::ShaderNodeBsdfHair b_hair_node(b_node);
HairBsdfNode *hair = new HairBsdfNode();
switch(b_hair_node.component()) {
@@ -437,64 +444,64 @@ static ShaderNode *add_node(Scene *scene, BL::BlendData b_data, BL::Scene b_scen
}
node = hair;
}
- else if (b_node.is_a(&RNA_ShaderNodeBsdfTranslucent)) {
+ else if(b_node.is_a(&RNA_ShaderNodeBsdfTranslucent)) {
node = new TranslucentBsdfNode();
}
- else if (b_node.is_a(&RNA_ShaderNodeBsdfTransparent)) {
+ else if(b_node.is_a(&RNA_ShaderNodeBsdfTransparent)) {
node = new TransparentBsdfNode();
}
- else if (b_node.is_a(&RNA_ShaderNodeBsdfVelvet)) {
+ else if(b_node.is_a(&RNA_ShaderNodeBsdfVelvet)) {
node = new VelvetBsdfNode();
}
- else if (b_node.is_a(&RNA_ShaderNodeEmission)) {
+ else if(b_node.is_a(&RNA_ShaderNodeEmission)) {
node = new EmissionNode();
}
- else if (b_node.is_a(&RNA_ShaderNodeAmbientOcclusion)) {
+ else if(b_node.is_a(&RNA_ShaderNodeAmbientOcclusion)) {
node = new AmbientOcclusionNode();
}
- else if (b_node.is_a(&RNA_ShaderNodeVolumeScatter)) {
+ else if(b_node.is_a(&RNA_ShaderNodeVolumeScatter)) {
node = new ScatterVolumeNode();
}
- else if (b_node.is_a(&RNA_ShaderNodeVolumeAbsorption)) {
+ else if(b_node.is_a(&RNA_ShaderNodeVolumeAbsorption)) {
node = new AbsorptionVolumeNode();
}
- else if (b_node.is_a(&RNA_ShaderNodeNewGeometry)) {
+ else if(b_node.is_a(&RNA_ShaderNodeNewGeometry)) {
node = new GeometryNode();
}
- else if (b_node.is_a(&RNA_ShaderNodeWireframe)) {
+ else if(b_node.is_a(&RNA_ShaderNodeWireframe)) {
BL::ShaderNodeWireframe b_wireframe_node(b_node);
WireframeNode *wire = new WireframeNode();
wire->use_pixel_size = b_wireframe_node.use_pixel_size();
node = wire;
}
- else if (b_node.is_a(&RNA_ShaderNodeWavelength)) {
+ else if(b_node.is_a(&RNA_ShaderNodeWavelength)) {
node = new WavelengthNode();
}
- else if (b_node.is_a(&RNA_ShaderNodeBlackbody)) {
+ else if(b_node.is_a(&RNA_ShaderNodeBlackbody)) {
node = new BlackbodyNode();
}
- else if (b_node.is_a(&RNA_ShaderNodeLightPath)) {
+ else if(b_node.is_a(&RNA_ShaderNodeLightPath)) {
node = new LightPathNode();
}
- else if (b_node.is_a(&RNA_ShaderNodeLightFalloff)) {
+ else if(b_node.is_a(&RNA_ShaderNodeLightFalloff)) {
node = new LightFalloffNode();
}
- else if (b_node.is_a(&RNA_ShaderNodeObjectInfo)) {
+ else if(b_node.is_a(&RNA_ShaderNodeObjectInfo)) {
node = new ObjectInfoNode();
}
- else if (b_node.is_a(&RNA_ShaderNodeParticleInfo)) {
+ else if(b_node.is_a(&RNA_ShaderNodeParticleInfo)) {
node = new ParticleInfoNode();
}
- else if (b_node.is_a(&RNA_ShaderNodeHairInfo)) {
+ else if(b_node.is_a(&RNA_ShaderNodeHairInfo)) {
node = new HairInfoNode();
}
- else if (b_node.is_a(&RNA_ShaderNodeBump)) {
+ else if(b_node.is_a(&RNA_ShaderNodeBump)) {
BL::ShaderNodeBump b_bump_node(b_node);
BumpNode *bump = new BumpNode();
bump->invert = b_bump_node.invert();
node = bump;
}
- else if (b_node.is_a(&RNA_ShaderNodeScript)) {
+ else if(b_node.is_a(&RNA_ShaderNodeScript)) {
#ifdef WITH_OSL
if(scene->shader_manager->use_osl()) {
/* create script node */
@@ -510,16 +517,16 @@ static ShaderNode *add_node(Scene *scene, BL::BlendData b_data, BL::Scene b_scen
* Socket names must be stored in the extra lists instead. */
BL::Node::inputs_iterator b_input;
- for (b_script_node.inputs.begin(b_input); b_input != b_script_node.inputs.end(); ++b_input) {
+ for(b_script_node.inputs.begin(b_input); b_input != b_script_node.inputs.end(); ++b_input) {
script_node->input_names.push_back(ustring(b_input->name()));
ShaderInput *input = script_node->add_input(script_node->input_names.back().c_str(),
convert_socket_type(*b_input));
- set_default_value(input, b_node, *b_input, b_data, b_ntree);
+ set_default_value(input, *b_input, b_data, b_ntree);
}
BL::Node::outputs_iterator b_output;
- for (b_script_node.outputs.begin(b_output); b_output != b_script_node.outputs.end(); ++b_output) {
+ for(b_script_node.outputs.begin(b_output); b_output != b_script_node.outputs.end(); ++b_output) {
script_node->output_names.push_back(ustring(b_output->name()));
script_node->add_output(script_node->output_names.back().c_str(),
convert_socket_type(*b_output));
@@ -543,9 +550,12 @@ static ShaderNode *add_node(Scene *scene, BL::BlendData b_data, BL::Scene b_scen
node = script_node;
}
+#else
+ (void)b_data;
+ (void)b_ntree;
#endif
}
- else if (b_node.is_a(&RNA_ShaderNodeTexImage)) {
+ else if(b_node.is_a(&RNA_ShaderNodeTexImage)) {
BL::ShaderNodeTexImage b_image_node(b_node);
BL::Image b_image(b_image_node.image());
ImageTextureNode *image = new ImageTextureNode();
@@ -555,7 +565,8 @@ static ShaderNode *add_node(Scene *scene, BL::BlendData b_data, BL::Scene b_scen
*/
bool is_builtin = b_image.packed_file() ||
b_image.source() == BL::Image::source_GENERATED ||
- b_image.source() == BL::Image::source_MOVIE;
+ b_image.source() == BL::Image::source_MOVIE ||
+ b_engine.is_preview();
if(is_builtin) {
/* for builtin images we're using image datablock name to find an image to
@@ -578,27 +589,31 @@ static ShaderNode *add_node(Scene *scene, BL::BlendData b_data, BL::Scene b_scen
image->use_alpha = b_image.use_alpha();
/* TODO(sergey): Does not work properly when we change builtin type. */
- if (b_image.is_updated()) {
- scene->image_manager->tag_reload_image(image->filename,
- image->builtin_data,
- (InterpolationType)b_image_node.interpolation());
+ if(b_image.is_updated()) {
+ scene->image_manager->tag_reload_image(
+ image->filename,
+ image->builtin_data,
+ (InterpolationType)b_image_node.interpolation(),
+ (ExtensionType)b_image_node.extension());
}
}
image->color_space = ImageTextureNode::color_space_enum[(int)b_image_node.color_space()];
image->projection = ImageTextureNode::projection_enum[(int)b_image_node.projection()];
image->interpolation = (InterpolationType)b_image_node.interpolation();
+ image->extension = (ExtensionType)b_image_node.extension();
image->projection_blend = b_image_node.projection_blend();
get_tex_mapping(&image->tex_mapping, b_image_node.texture_mapping());
node = image;
}
- else if (b_node.is_a(&RNA_ShaderNodeTexEnvironment)) {
+ else if(b_node.is_a(&RNA_ShaderNodeTexEnvironment)) {
BL::ShaderNodeTexEnvironment b_env_node(b_node);
BL::Image b_image(b_env_node.image());
EnvironmentTextureNode *env = new EnvironmentTextureNode();
if(b_image) {
bool is_builtin = b_image.packed_file() ||
b_image.source() == BL::Image::source_GENERATED ||
- b_image.source() == BL::Image::source_MOVIE;
+ b_image.source() == BL::Image::source_MOVIE ||
+ b_engine.is_preview();
if(is_builtin) {
int scene_frame = b_scene.frame_current();
@@ -615,10 +630,11 @@ static ShaderNode *add_node(Scene *scene, BL::BlendData b_data, BL::Scene b_scen
env->use_alpha = b_image.use_alpha();
/* TODO(sergey): Does not work properly when we change builtin type. */
- if (b_image.is_updated()) {
+ if(b_image.is_updated()) {
scene->image_manager->tag_reload_image(env->filename,
env->builtin_data,
- INTERPOLATION_LINEAR);
+ INTERPOLATION_LINEAR,
+ EXTENSION_REPEAT);
}
}
env->color_space = EnvironmentTextureNode::color_space_enum[(int)b_env_node.color_space()];
@@ -626,41 +642,41 @@ static ShaderNode *add_node(Scene *scene, BL::BlendData b_data, BL::Scene b_scen
get_tex_mapping(&env->tex_mapping, b_env_node.texture_mapping());
node = env;
}
- else if (b_node.is_a(&RNA_ShaderNodeTexGradient)) {
+ else if(b_node.is_a(&RNA_ShaderNodeTexGradient)) {
BL::ShaderNodeTexGradient b_gradient_node(b_node);
GradientTextureNode *gradient = new GradientTextureNode();
gradient->type = GradientTextureNode::type_enum[(int)b_gradient_node.gradient_type()];
get_tex_mapping(&gradient->tex_mapping, b_gradient_node.texture_mapping());
node = gradient;
}
- else if (b_node.is_a(&RNA_ShaderNodeTexVoronoi)) {
+ else if(b_node.is_a(&RNA_ShaderNodeTexVoronoi)) {
BL::ShaderNodeTexVoronoi b_voronoi_node(b_node);
VoronoiTextureNode *voronoi = new VoronoiTextureNode();
voronoi->coloring = VoronoiTextureNode::coloring_enum[(int)b_voronoi_node.coloring()];
get_tex_mapping(&voronoi->tex_mapping, b_voronoi_node.texture_mapping());
node = voronoi;
}
- else if (b_node.is_a(&RNA_ShaderNodeTexMagic)) {
+ else if(b_node.is_a(&RNA_ShaderNodeTexMagic)) {
BL::ShaderNodeTexMagic b_magic_node(b_node);
MagicTextureNode *magic = new MagicTextureNode();
magic->depth = b_magic_node.turbulence_depth();
get_tex_mapping(&magic->tex_mapping, b_magic_node.texture_mapping());
node = magic;
}
- else if (b_node.is_a(&RNA_ShaderNodeTexWave)) {
+ else if(b_node.is_a(&RNA_ShaderNodeTexWave)) {
BL::ShaderNodeTexWave b_wave_node(b_node);
WaveTextureNode *wave = new WaveTextureNode();
wave->type = WaveTextureNode::type_enum[(int)b_wave_node.wave_type()];
get_tex_mapping(&wave->tex_mapping, b_wave_node.texture_mapping());
node = wave;
}
- else if (b_node.is_a(&RNA_ShaderNodeTexChecker)) {
+ else if(b_node.is_a(&RNA_ShaderNodeTexChecker)) {
BL::ShaderNodeTexChecker b_checker_node(b_node);
CheckerTextureNode *checker = new CheckerTextureNode();
get_tex_mapping(&checker->tex_mapping, b_checker_node.texture_mapping());
node = checker;
}
- else if (b_node.is_a(&RNA_ShaderNodeTexBrick)) {
+ else if(b_node.is_a(&RNA_ShaderNodeTexBrick)) {
BL::ShaderNodeTexBrick b_brick_node(b_node);
BrickTextureNode *brick = new BrickTextureNode();
brick->offset = b_brick_node.offset();
@@ -670,26 +686,30 @@ static ShaderNode *add_node(Scene *scene, BL::BlendData b_data, BL::Scene b_scen
get_tex_mapping(&brick->tex_mapping, b_brick_node.texture_mapping());
node = brick;
}
- else if (b_node.is_a(&RNA_ShaderNodeTexNoise)) {
+ else if(b_node.is_a(&RNA_ShaderNodeTexNoise)) {
BL::ShaderNodeTexNoise b_noise_node(b_node);
NoiseTextureNode *noise = new NoiseTextureNode();
get_tex_mapping(&noise->tex_mapping, b_noise_node.texture_mapping());
node = noise;
}
- else if (b_node.is_a(&RNA_ShaderNodeTexMusgrave)) {
+ else if(b_node.is_a(&RNA_ShaderNodeTexMusgrave)) {
BL::ShaderNodeTexMusgrave b_musgrave_node(b_node);
MusgraveTextureNode *musgrave = new MusgraveTextureNode();
musgrave->type = MusgraveTextureNode::type_enum[(int)b_musgrave_node.musgrave_type()];
get_tex_mapping(&musgrave->tex_mapping, b_musgrave_node.texture_mapping());
node = musgrave;
}
- else if (b_node.is_a(&RNA_ShaderNodeTexCoord)) {
+ else if(b_node.is_a(&RNA_ShaderNodeTexCoord)) {
BL::ShaderNodeTexCoord b_tex_coord_node(b_node);
TextureCoordinateNode *tex_coord = new TextureCoordinateNode();
tex_coord->from_dupli = b_tex_coord_node.from_dupli();
+ if(b_tex_coord_node.object()) {
+ tex_coord->use_transform = true;
+ tex_coord->ob_tfm = get_transform(b_tex_coord_node.object().matrix_world());
+ }
node = tex_coord;
}
- else if (b_node.is_a(&RNA_ShaderNodeTexSky)) {
+ else if(b_node.is_a(&RNA_ShaderNodeTexSky)) {
BL::ShaderNodeTexSky b_sky_node(b_node);
SkyTextureNode *sky = new SkyTextureNode();
sky->type = SkyTextureNode::type_enum[(int)b_sky_node.sky_type()];
@@ -699,14 +719,14 @@ static ShaderNode *add_node(Scene *scene, BL::BlendData b_data, BL::Scene b_scen
get_tex_mapping(&sky->tex_mapping, b_sky_node.texture_mapping());
node = sky;
}
- else if (b_node.is_a(&RNA_ShaderNodeNormalMap)) {
+ else if(b_node.is_a(&RNA_ShaderNodeNormalMap)) {
BL::ShaderNodeNormalMap b_normal_map_node(b_node);
NormalMapNode *nmap = new NormalMapNode();
nmap->space = NormalMapNode::space_enum[(int)b_normal_map_node.space()];
nmap->attribute = b_normal_map_node.uv_map();
node = nmap;
}
- else if (b_node.is_a(&RNA_ShaderNodeTangent)) {
+ else if(b_node.is_a(&RNA_ShaderNodeTangent)) {
BL::ShaderNodeTangent b_tangent_node(b_node);
TangentNode *tangent = new TangentNode();
tangent->direction_type = TangentNode::direction_type_enum[(int)b_tangent_node.direction_type()];
@@ -714,13 +734,43 @@ static ShaderNode *add_node(Scene *scene, BL::BlendData b_data, BL::Scene b_scen
tangent->attribute = b_tangent_node.uv_map();
node = tangent;
}
- else if (b_node.is_a(&RNA_ShaderNodeUVMap)) {
+ else if(b_node.is_a(&RNA_ShaderNodeUVMap)) {
BL::ShaderNodeUVMap b_uvmap_node(b_node);
UVMapNode *uvm = new UVMapNode();
uvm->attribute = b_uvmap_node.uv_map();
uvm->from_dupli = b_uvmap_node.from_dupli();
node = uvm;
}
+ else if(b_node.is_a(&RNA_ShaderNodeTexPointDensity)) {
+ BL::ShaderNodeTexPointDensity b_point_density_node(b_node);
+ PointDensityTextureNode *point_density = new PointDensityTextureNode();
+ point_density->filename = b_point_density_node.name();
+ point_density->space =
+ PointDensityTextureNode::space_enum[(int)b_point_density_node.space()];
+ point_density->interpolation =
+ (InterpolationType)b_point_density_node.interpolation();
+ point_density->builtin_data = b_point_density_node.ptr.data;
+
+ /* Transformation form world space to texture space. */
+ BL::Object b_ob(b_point_density_node.object());
+ if(b_ob) {
+ float3 loc, size;
+ point_density_texture_space(b_point_density_node, loc, size);
+ point_density->tfm =
+ transform_translate(-loc) * transform_scale(size) *
+ transform_inverse(get_transform(b_ob.matrix_world()));
+ }
+
+ /* TODO(sergey): Use more proper update flag. */
+ if(true) {
+ scene->image_manager->tag_reload_image(
+ point_density->filename,
+ point_density->builtin_data,
+ point_density->interpolation,
+ EXTENSION_REPEAT);
+ }
+ node = point_density;
+ }
if(node)
graph->add(node);
@@ -730,7 +780,7 @@ static ShaderNode *add_node(Scene *scene, BL::BlendData b_data, BL::Scene b_scen
static bool node_use_modified_socket_name(ShaderNode *node)
{
- if (node->special_type == SHADER_SPECIAL_TYPE_SCRIPT)
+ if(node->special_type == SHADER_SPECIAL_TYPE_SCRIPT)
return false;
return true;
@@ -740,14 +790,14 @@ static ShaderInput *node_find_input_by_name(ShaderNode *node, BL::Node b_node, B
{
string name = b_socket.name();
- if (node_use_modified_socket_name(node)) {
+ if(node_use_modified_socket_name(node)) {
BL::Node::inputs_iterator b_input;
bool found = false;
int counter = 0, total = 0;
- for (b_node.inputs.begin(b_input); b_input != b_node.inputs.end(); ++b_input) {
- if (b_input->name() == name) {
- if (!found)
+ for(b_node.inputs.begin(b_input); b_input != b_node.inputs.end(); ++b_input) {
+ if(b_input->name() == name) {
+ if(!found)
counter++;
total++;
}
@@ -757,10 +807,10 @@ static ShaderInput *node_find_input_by_name(ShaderNode *node, BL::Node b_node, B
}
/* rename if needed */
- if (name == "Shader")
+ if(name == "Shader")
name = "Closure";
- if (total > 1)
+ if(total > 1)
name = string_printf("%s%d", name.c_str(), counter);
}
@@ -771,14 +821,14 @@ static ShaderOutput *node_find_output_by_name(ShaderNode *node, BL::Node b_node,
{
string name = b_socket.name();
- if (node_use_modified_socket_name(node)) {
+ if(node_use_modified_socket_name(node)) {
BL::Node::outputs_iterator b_output;
bool found = false;
int counter = 0, total = 0;
- for (b_node.outputs.begin(b_output); b_output != b_node.outputs.end(); ++b_output) {
- if (b_output->name() == name) {
- if (!found)
+ for(b_node.outputs.begin(b_output); b_output != b_node.outputs.end(); ++b_output) {
+ if(b_output->name() == name) {
+ if(!found)
counter++;
total++;
}
@@ -788,18 +838,24 @@ static ShaderOutput *node_find_output_by_name(ShaderNode *node, BL::Node b_node,
}
/* rename if needed */
- if (name == "Shader")
+ if(name == "Shader")
name = "Closure";
- if (total > 1)
+ if(total > 1)
name = string_printf("%s%d", name.c_str(), counter);
}
return node->output(name.c_str());
}
-static void add_nodes(Scene *scene, BL::BlendData b_data, BL::Scene b_scene, ShaderGraph *graph, BL::ShaderNodeTree b_ntree,
- const ProxyMap &proxy_input_map, const ProxyMap &proxy_output_map)
+static void add_nodes(Scene *scene,
+ BL::RenderEngine b_engine,
+ BL::BlendData b_data,
+ BL::Scene b_scene,
+ ShaderGraph *graph,
+ BL::ShaderNodeTree b_ntree,
+ const ProxyMap &proxy_input_map,
+ const ProxyMap &proxy_output_map)
{
/* add nodes */
BL::ShaderNodeTree::nodes_iterator b_node;
@@ -814,7 +870,7 @@ static void add_nodes(Scene *scene, BL::BlendData b_data, BL::Scene b_scene, Sha
BL::ShaderNode output_node(PointerRNA_NULL);
for(b_ntree.nodes.begin(b_node); b_node != b_ntree.nodes.end(); ++b_node) {
- if (is_output_node(*b_node)) {
+ if(is_output_node(*b_node)) {
BL::ShaderNodeOutputMaterial b_output_node(*b_node);
if(b_output_node.is_active_output()) {
@@ -830,10 +886,10 @@ static void add_nodes(Scene *scene, BL::BlendData b_data, BL::Scene b_scene, Sha
/* add nodes */
for(b_ntree.nodes.begin(b_node); b_node != b_ntree.nodes.end(); ++b_node) {
- if (b_node->mute() || b_node->is_a(&RNA_NodeReroute)) {
+ if(b_node->mute() || b_node->is_a(&RNA_NodeReroute)) {
/* replace muted node with internal links */
BL::Node::internal_links_iterator b_link;
- for (b_node->internal_links.begin(b_link); b_link != b_node->internal_links.end(); ++b_link) {
+ for(b_node->internal_links.begin(b_link); b_link != b_node->internal_links.end(); ++b_link) {
ProxyNode *proxy = new ProxyNode(convert_socket_type(b_link->to_socket()));
input_map[b_link->from_socket().ptr.data] = proxy->inputs[0];
@@ -842,10 +898,10 @@ static void add_nodes(Scene *scene, BL::BlendData b_data, BL::Scene b_scene, Sha
graph->add(proxy);
}
}
- else if (b_node->is_a(&RNA_ShaderNodeGroup) || b_node->is_a(&RNA_NodeCustomGroup)) {
+ else if(b_node->is_a(&RNA_ShaderNodeGroup) || b_node->is_a(&RNA_NodeCustomGroup)) {
BL::ShaderNodeTree b_group_ntree(PointerRNA_NULL);
- if (b_node->is_a(&RNA_ShaderNodeGroup))
+ if(b_node->is_a(&RNA_ShaderNodeGroup))
b_group_ntree = BL::ShaderNodeTree(((BL::NodeGroup)(*b_node)).node_tree());
else
b_group_ntree = BL::ShaderNodeTree(((BL::NodeCustomGroup)(*b_node)).node_tree());
@@ -864,7 +920,7 @@ static void add_nodes(Scene *scene, BL::BlendData b_data, BL::Scene b_scene, Sha
input_map[b_input->ptr.data] = proxy->inputs[0];
- set_default_value(proxy->inputs[0], *b_node, *b_input, b_data, b_ntree);
+ set_default_value(proxy->inputs[0], *b_input, b_data, b_ntree);
}
for(b_node->outputs.begin(b_output); b_output != b_node->outputs.end(); ++b_output) {
ProxyNode *proxy = new ProxyNode(convert_socket_type(*b_output));
@@ -876,33 +932,41 @@ static void add_nodes(Scene *scene, BL::BlendData b_data, BL::Scene b_scene, Sha
output_map[b_output->ptr.data] = proxy->outputs[0];
}
- if (b_group_ntree)
- add_nodes(scene, b_data, b_scene, graph, b_group_ntree, group_proxy_input_map, group_proxy_output_map);
+ if(b_group_ntree) {
+ add_nodes(scene,
+ b_engine,
+ b_data,
+ b_scene,
+ graph,
+ b_group_ntree,
+ group_proxy_input_map,
+ group_proxy_output_map);
+ }
}
- else if (b_node->is_a(&RNA_NodeGroupInput)) {
+ else if(b_node->is_a(&RNA_NodeGroupInput)) {
/* map each socket to a proxy node */
for(b_node->outputs.begin(b_output); b_output != b_node->outputs.end(); ++b_output) {
ProxyMap::const_iterator proxy_it = proxy_input_map.find(b_output->identifier());
- if (proxy_it != proxy_input_map.end()) {
+ if(proxy_it != proxy_input_map.end()) {
ProxyNode *proxy = proxy_it->second;
output_map[b_output->ptr.data] = proxy->outputs[0];
}
}
}
- else if (b_node->is_a(&RNA_NodeGroupOutput)) {
+ else if(b_node->is_a(&RNA_NodeGroupOutput)) {
BL::NodeGroupOutput b_output_node(*b_node);
/* only the active group output is used */
- if (b_output_node.is_active_output()) {
+ if(b_output_node.is_active_output()) {
/* map each socket to a proxy node */
for(b_node->inputs.begin(b_input); b_input != b_node->inputs.end(); ++b_input) {
ProxyMap::const_iterator proxy_it = proxy_output_map.find(b_input->identifier());
- if (proxy_it != proxy_output_map.end()) {
+ if(proxy_it != proxy_output_map.end()) {
ProxyNode *proxy = proxy_it->second;
input_map[b_input->ptr.data] = proxy->inputs[0];
- set_default_value(proxy->inputs[0], *b_node, *b_input, b_data, b_ntree);
+ set_default_value(proxy->inputs[0], *b_input, b_data, b_ntree);
}
}
}
@@ -910,30 +974,36 @@ static void add_nodes(Scene *scene, BL::BlendData b_data, BL::Scene b_scene, Sha
else {
ShaderNode *node = NULL;
- if (is_output_node(*b_node)) {
- if (b_node->ptr.data == output_node.ptr.data) {
+ if(is_output_node(*b_node)) {
+ if(b_node->ptr.data == output_node.ptr.data) {
node = graph->output();
}
}
else {
- node = add_node(scene, b_data, b_scene, graph, b_ntree, BL::ShaderNode(*b_node));
+ node = add_node(scene,
+ b_engine,
+ b_data,
+ b_scene,
+ graph,
+ b_ntree,
+ BL::ShaderNode(*b_node));
}
if(node) {
/* map node sockets for linking */
for(b_node->inputs.begin(b_input); b_input != b_node->inputs.end(); ++b_input) {
ShaderInput *input = node_find_input_by_name(node, *b_node, *b_input);
- if (!input) {
+ if(!input) {
/* XXX should not happen, report error? */
continue;
}
input_map[b_input->ptr.data] = input;
- set_default_value(input, *b_node, *b_input, b_data, b_ntree);
+ set_default_value(input, *b_input, b_data, b_ntree);
}
for(b_node->outputs.begin(b_output); b_output != b_node->outputs.end(); ++b_output) {
ShaderOutput *output = node_find_output_by_name(node, *b_node, *b_output);
- if (!output) {
+ if(!output) {
/* XXX should not happen, report error? */
continue;
}
@@ -947,6 +1017,10 @@ static void add_nodes(Scene *scene, BL::BlendData b_data, BL::Scene b_scene, Sha
BL::NodeTree::links_iterator b_link;
for(b_ntree.links.begin(b_link); b_link != b_ntree.links.end(); ++b_link) {
+ /* Ignore invalid links to avoid unwanted cycles created in graph. */
+ if(!b_link->is_valid()) {
+ continue;
+ }
/* get blender link data */
BL::NodeSocket b_from_sock = b_link->from_socket();
BL::NodeSocket b_to_sock = b_link->to_socket();
@@ -955,10 +1029,10 @@ static void add_nodes(Scene *scene, BL::BlendData b_data, BL::Scene b_scene, Sha
ShaderInput *input = 0;
PtrOutputMap::iterator output_it = output_map.find(b_from_sock.ptr.data);
- if (output_it != output_map.end())
+ if(output_it != output_map.end())
output = output_it->second;
PtrInputMap::iterator input_it = input_map.find(b_to_sock.ptr.data);
- if (input_it != input_map.end())
+ if(input_it != input_map.end())
input = input_it->second;
/* either node may be NULL when the node was not exported, typically
@@ -968,10 +1042,22 @@ static void add_nodes(Scene *scene, BL::BlendData b_data, BL::Scene b_scene, Sha
}
}
-static void add_nodes(Scene *scene, BL::BlendData b_data, BL::Scene b_scene, ShaderGraph *graph, BL::ShaderNodeTree b_ntree)
+static void add_nodes(Scene *scene,
+ BL::RenderEngine b_engine,
+ BL::BlendData b_data,
+ BL::Scene b_scene,
+ ShaderGraph *graph,
+ BL::ShaderNodeTree b_ntree)
{
static const ProxyMap empty_proxy_map;
- add_nodes(scene, b_data, b_scene, graph, b_ntree, empty_proxy_map, empty_proxy_map);
+ add_nodes(scene,
+ b_engine,
+ b_data,
+ b_scene,
+ graph,
+ b_ntree,
+ empty_proxy_map,
+ empty_proxy_map);
}
/* Sync Materials */
@@ -997,7 +1083,7 @@ void BlenderSync::sync_materials(bool update_all)
if(b_mat->use_nodes() && b_mat->node_tree()) {
BL::ShaderNodeTree b_ntree(b_mat->node_tree());
- add_nodes(scene, b_data, b_scene, graph, b_ntree);
+ add_nodes(scene, b_engine, b_data, b_scene, graph, b_ntree);
}
else {
ShaderNode *closure, *out;
@@ -1014,7 +1100,8 @@ void BlenderSync::sync_materials(bool update_all)
shader->use_mis = get_boolean(cmat, "sample_as_light");
shader->use_transparent_shadow = get_boolean(cmat, "use_transparent_shadow");
shader->heterogeneous_volume = !get_boolean(cmat, "homogeneous_volume");
- shader->volume_sampling_method = RNA_enum_get(&cmat, "volume_sampling");
+ shader->volume_sampling_method = (VolumeSampling)RNA_enum_get(&cmat, "volume_sampling");
+ shader->volume_interpolation_method = (VolumeInterpolation)RNA_enum_get(&cmat, "volume_interpolation");
shader->set_graph(graph);
shader->tag_update(scene);
@@ -1039,12 +1126,13 @@ void BlenderSync::sync_world(bool update_all)
if(b_world && b_world.use_nodes() && b_world.node_tree()) {
BL::ShaderNodeTree b_ntree(b_world.node_tree());
- add_nodes(scene, b_data, b_scene, graph, b_ntree);
+ add_nodes(scene, b_engine, b_data, b_scene, graph, b_ntree);
/* volume */
PointerRNA cworld = RNA_pointer_get(&b_world.ptr, "cycles");
shader->heterogeneous_volume = !get_boolean(cworld, "homogeneous_volume");
- shader->volume_sampling_method = RNA_enum_get(&cworld, "volume_sampling");
+ shader->volume_sampling_method = (VolumeSampling)RNA_enum_get(&cworld, "volume_sampling");
+ shader->volume_interpolation_method = (VolumeInterpolation)RNA_enum_get(&cworld, "volume_interpolation");
}
else if(b_world) {
ShaderNode *closure, *out;
@@ -1088,7 +1176,7 @@ void BlenderSync::sync_world(bool update_all)
PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles");
/* when doing preview render check for BI's transparency settings,
- * this is so because bledner's preview render routines are not able
+ * this is so because Blender's preview render routines are not able
* to tweak all cycles's settings depending on different circumstances
*/
if(b_engine.is_preview() == false)
@@ -1124,7 +1212,7 @@ void BlenderSync::sync_lamps(bool update_all)
BL::ShaderNodeTree b_ntree(b_lamp->node_tree());
- add_nodes(scene, b_data, b_scene, graph, b_ntree);
+ add_nodes(scene, b_engine, b_data, b_scene, graph, b_ntree);
}
else {
ShaderNode *closure, *out;
diff --git a/intern/cycles/blender/blender_sync.cpp b/intern/cycles/blender/blender_sync.cpp
index 2ac90b34fd7..aed1b6de138 100644
--- a/intern/cycles/blender/blender_sync.cpp
+++ b/intern/cycles/blender/blender_sync.cpp
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#include "background.h"
@@ -30,11 +30,13 @@
#include "device.h"
#include "blender_sync.h"
+#include "blender_session.h"
#include "blender_util.h"
#include "util_debug.h"
#include "util_foreach.h"
#include "util_opengl.h"
+#include "util_hash.h"
CCL_NAMESPACE_BEGIN
@@ -70,10 +72,18 @@ bool BlenderSync::sync_recalc()
* so we can do it later on if doing it immediate is not suitable */
BL::BlendData::materials_iterator b_mat;
-
- for(b_data.materials.begin(b_mat); b_mat != b_data.materials.end(); ++b_mat)
- if(b_mat->is_updated() || (b_mat->node_tree() && b_mat->node_tree().is_updated()))
+ bool has_updated_objects = b_data.objects.is_updated();
+ for(b_data.materials.begin(b_mat); b_mat != b_data.materials.end(); ++b_mat) {
+ if(b_mat->is_updated() || (b_mat->node_tree() && b_mat->node_tree().is_updated())) {
shader_map.set_recalc(*b_mat);
+ }
+ else {
+ Shader *shader = shader_map.find(*b_mat);
+ if(has_updated_objects && shader != NULL && shader->has_object_dependency) {
+ shader_map.set_recalc(*b_mat);
+ }
+ }
+ }
BL::BlendData::lamps_iterator b_lamp;
@@ -102,7 +112,7 @@ bool BlenderSync::sync_recalc()
if(b_ob->is_updated_data()) {
BL::Object::particle_systems_iterator b_psys;
- for (b_ob->particle_systems.begin(b_psys); b_psys != b_ob->particle_systems.end(); ++b_psys)
+ for(b_ob->particle_systems.begin(b_psys); b_psys != b_ob->particle_systems.end(); ++b_psys)
particle_system_map.set_recalc(*b_ob);
}
}
@@ -135,18 +145,28 @@ bool BlenderSync::sync_recalc()
return recalc;
}
-void BlenderSync::sync_data(BL::SpaceView3D b_v3d, BL::Object b_override, void **python_thread_state, const char *layer)
+void BlenderSync::sync_data(BL::RenderSettings b_render,
+ BL::SpaceView3D b_v3d,
+ BL::Object b_override,
+ int width, int height,
+ void **python_thread_state,
+ const char *layer)
{
sync_render_layers(b_v3d, layer);
sync_integrator();
sync_film();
sync_shaders();
+ sync_images();
sync_curve_settings();
mesh_synced.clear(); /* use for objects and motion sync */
sync_objects(b_v3d);
- sync_motion(b_v3d, b_override, python_thread_state);
+ sync_motion(b_render,
+ b_v3d,
+ b_override,
+ width, height,
+ python_thread_state);
mesh_synced.clear();
}
@@ -185,6 +205,9 @@ void BlenderSync::sync_integrator()
integrator->filter_glossy = get_float(cscene, "blur_glossy");
integrator->seed = get_int(cscene, "seed");
+ if(get_boolean(cscene, "use_animated_seed"))
+ integrator->seed = hash_int_2d(b_scene.frame_current(), get_int(cscene, "seed"));
+
integrator->sampling_pattern = (SamplingPattern)RNA_enum_get(&cscene, "sampling_pattern");
integrator->layer_flag = render_layer.layer;
@@ -351,9 +374,42 @@ void BlenderSync::sync_render_layers(BL::SpaceView3D b_v3d, const char *layer)
}
}
+/* Images */
+void BlenderSync::sync_images()
+{
+ /* Sync is a convention for this API, but currently it frees unused buffers. */
+
+ const bool is_interface_locked = b_engine.render() &&
+ b_engine.render().use_lock_interface();
+ if(is_interface_locked == false && BlenderSession::headless == false) {
+ /* If interface is not locked, it's possible image is needed for
+ * the display.
+ */
+ return;
+ }
+ /* Free buffers used by images which are not needed for render. */
+ BL::BlendData::images_iterator b_image;
+ for(b_data.images.begin(b_image);
+ b_image != b_data.images.end();
+ ++b_image)
+ {
+ /* TODO(sergey): Consider making it an utility function to check
+ * whether image is considered builtin.
+ */
+ const bool is_builtin = b_image->packed_file() ||
+ b_image->source() == BL::Image::source_GENERATED ||
+ b_image->source() == BL::Image::source_MOVIE ||
+ b_engine.is_preview();
+ if(is_builtin == false) {
+ b_image->buffers_free();
+ }
+ /* TODO(sergey): Free builtin images not used by any shader. */
+ }
+}
+
/* Scene Parameters */
-SceneParams BlenderSync::get_scene_params(BL::Scene b_scene, bool background)
+SceneParams BlenderSync::get_scene_params(BL::Scene b_scene, bool background, bool is_cpu)
{
BL::RenderSettings r = b_scene.render();
SceneParams params;
@@ -371,13 +427,22 @@ SceneParams BlenderSync::get_scene_params(BL::Scene b_scene, bool background)
params.bvh_type = (SceneParams::BVHType)RNA_enum_get(&cscene, "debug_bvh_type");
params.use_bvh_spatial_split = RNA_boolean_get(&cscene, "debug_use_spatial_splits");
- params.use_bvh_cache = (background)? RNA_boolean_get(&cscene, "use_cache"): false;
if(background && params.shadingsystem != SHADINGSYSTEM_OSL)
params.persistent_data = r.use_persistent_data();
else
params.persistent_data = false;
+#if !(defined(__GNUC__) && (defined(i386) || defined(_M_IX86)))
+ if(is_cpu) {
+ params.use_qbvh = system_cpu_support_sse2();
+ }
+ else
+#endif
+ {
+ params.use_qbvh = false;
+ }
+
return params;
}
@@ -389,7 +454,10 @@ bool BlenderSync::get_session_pause(BL::Scene b_scene, bool background)
return (background)? false: get_boolean(cscene, "preview_pause");
}
-SessionParams BlenderSync::get_session_params(BL::RenderEngine b_engine, BL::UserPreferences b_userpref, BL::Scene b_scene, bool background)
+SessionParams BlenderSync::get_session_params(BL::RenderEngine b_engine,
+ BL::UserPreferences b_userpref,
+ BL::Scene b_scene,
+ bool background)
{
SessionParams params;
PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles");
@@ -478,8 +546,13 @@ SessionParams BlenderSync::get_session_params(BL::RenderEngine b_engine, BL::Use
params.tile_size = make_int2(tile_x, tile_y);
}
-
- params.tile_order = (TileOrder)RNA_enum_get(&cscene, "tile_order");
+
+ if(BlenderSession::headless == false) {
+ params.tile_order = (TileOrder)RNA_enum_get(&cscene, "tile_order");
+ }
+ else {
+ params.tile_order = TILE_BOTTOM_TO_TOP;
+ }
params.start_resolution = get_int(cscene, "preview_start_resolution");
@@ -515,7 +588,24 @@ SessionParams BlenderSync::get_session_params(BL::RenderEngine b_engine, BL::Use
params.shadingsystem = SHADINGSYSTEM_OSL;
/* color managagement */
- params.display_buffer_linear = GLEW_ARB_half_float_pixel && b_engine.support_display_space_shader(b_scene);
+#ifdef GLEW_MX
+ /* When using GLEW MX we need to check whether we've got an OpenGL
+ * context for current window. This is because command line rendering
+ * doesn't have OpenGL context actually.
+ */
+ if(glewGetContext() != NULL)
+#endif
+ {
+ params.display_buffer_linear = GLEW_ARB_half_float_pixel &&
+ b_engine.support_display_space_shader(b_scene);
+ }
+
+ if(b_engine.is_preview()) {
+ /* For preview rendering we're using same timeout as
+ * blender's job update.
+ */
+ params.progressive_update_timeout = 0.1;
+ }
return params;
}
diff --git a/intern/cycles/blender/blender_sync.h b/intern/cycles/blender/blender_sync.h
index bb8e9c31b1d..e99a64bd23e 100644
--- a/intern/cycles/blender/blender_sync.h
+++ b/intern/cycles/blender/blender_sync.h
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#ifndef __BLENDER_SYNC_H__
@@ -53,7 +53,12 @@ public:
/* sync */
bool sync_recalc();
- void sync_data(BL::SpaceView3D b_v3d, BL::Object b_override, void **python_thread_state, const char *layer = 0);
+ void sync_data(BL::RenderSettings b_render,
+ BL::SpaceView3D b_v3d,
+ BL::Object b_override,
+ int width, int height,
+ void **python_thread_state,
+ const char *layer = 0);
void sync_render_layers(BL::SpaceView3D b_v3d, const char *layer);
void sync_integrator();
void sync_camera(BL::RenderSettings b_render, BL::Object b_override, int width, int height);
@@ -64,17 +69,24 @@ public:
int get_layer_bound_samples() { return render_layer.bound_samples; }
/* get parameters */
- static SceneParams get_scene_params(BL::Scene b_scene, bool background);
- static SessionParams get_session_params(BL::RenderEngine b_engine, BL::UserPreferences b_userpref, BL::Scene b_scene, bool background);
+ static SceneParams get_scene_params(BL::Scene b_scene, bool background, bool is_cpu);
+ static SessionParams get_session_params(BL::RenderEngine b_engine,
+ BL::UserPreferences b_userpref,
+ BL::Scene b_scene,
+ bool background);
static bool get_session_pause(BL::Scene b_scene, bool background);
- static BufferParams get_buffer_params(BL::RenderSettings b_render, BL::Scene b_scene, BL::SpaceView3D b_v3d, BL::RegionView3D b_rv3d, Camera *cam, int width, int height);
+ static BufferParams get_buffer_params(BL::RenderSettings b_render, BL::SpaceView3D b_v3d, BL::RegionView3D b_rv3d, Camera *cam, int width, int height);
private:
/* sync */
void sync_lamps(bool update_all);
void sync_materials(bool update_all);
void sync_objects(BL::SpaceView3D b_v3d, float motion_time = 0.0f);
- void sync_motion(BL::SpaceView3D b_v3d, BL::Object b_override, void **python_thread_state);
+ void sync_motion(BL::RenderSettings b_render,
+ BL::SpaceView3D b_v3d,
+ BL::Object b_override,
+ int width, int height,
+ void **python_thread_state);
void sync_film();
void sync_view();
void sync_world(bool update_all);
@@ -84,16 +96,30 @@ private:
void sync_nodes(Shader *shader, BL::ShaderNodeTree b_ntree);
Mesh *sync_mesh(BL::Object b_ob, bool object_updated, bool hide_tris);
void sync_curves(Mesh *mesh, BL::Mesh b_mesh, BL::Object b_ob, bool motion, int time_index = 0);
- Object *sync_object(BL::Object b_parent, int persistent_id[OBJECT_PERSISTENT_ID_SIZE], BL::DupliObject b_dupli_ob,
- Transform& tfm, uint layer_flag, float motion_time, bool hide_tris);
- void sync_light(BL::Object b_parent, int persistent_id[OBJECT_PERSISTENT_ID_SIZE], BL::Object b_ob, Transform& tfm);
- void sync_background_light();
+ Object *sync_object(BL::Object b_parent,
+ int persistent_id[OBJECT_PERSISTENT_ID_SIZE],
+ BL::DupliObject b_dupli_ob,
+ Transform& tfm,
+ uint layer_flag,
+ float motion_time,
+ bool hide_tris,
+ bool use_camera_cull,
+ float camera_cull_margin,
+ bool *use_portal);
+ void sync_light(BL::Object b_parent, int persistent_id[OBJECT_PERSISTENT_ID_SIZE], BL::Object b_ob, Transform& tfm, bool *use_portal);
+ void sync_background_light(bool use_portal);
void sync_mesh_motion(BL::Object b_ob, Object *object, float motion_time);
- void sync_camera_motion(BL::Object b_ob, float motion_time);
+ void sync_camera_motion(BL::RenderSettings b_render,
+ BL::Object b_ob,
+ int width, int height,
+ float motion_time);
/* particles */
bool sync_dupli_particle(BL::Object b_ob, BL::DupliObject b_dup, Object *object);
+ /* Images. */
+ void sync_images();
+
/* util */
void find_shader(BL::ID id, vector<uint>& used_shaders, int default_shader);
bool BKE_object_is_modified(BL::Object b_ob);
diff --git a/intern/cycles/blender/blender_texture.cpp b/intern/cycles/blender/blender_texture.cpp
new file mode 100644
index 00000000000..cb4dd1792d0
--- /dev/null
+++ b/intern/cycles/blender/blender_texture.cpp
@@ -0,0 +1,116 @@
+/*
+ * Copyright 2011-2015 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 "blender_texture.h"
+
+CCL_NAMESPACE_BEGIN
+
+namespace {
+
+/* Point density helpers. */
+
+static void density_texture_space_invert(float3& loc,
+ float3& size)
+{
+ if(size.x != 0.0f) size.x = 0.5f/size.x;
+ if(size.y != 0.0f) size.y = 0.5f/size.y;
+ if(size.z != 0.0f) size.z = 0.5f/size.z;
+
+ loc = loc*size - make_float3(0.5f, 0.5f, 0.5f);
+}
+
+static void density_object_texture_space(BL::Object b_ob,
+ float radius,
+ float3& loc,
+ float3& size)
+{
+ if(b_ob.type() == BL::Object::type_MESH) {
+ BL::Mesh b_mesh(b_ob.data());
+ loc = get_float3(b_mesh.texspace_location());
+ size = get_float3(b_mesh.texspace_size());
+ }
+ else {
+ /* TODO(sergey): Not supported currently. */
+ }
+ /* Adjust texture space to include density points on the boundaries. */
+ size = size + make_float3(radius, radius, radius);
+ density_texture_space_invert(loc, size);
+}
+
+static void density_particle_system_texture_space(
+ BL::Object b_ob,
+ BL::ParticleSystem b_particle_system,
+ float radius,
+ float3& loc,
+ float3& size)
+{
+ if(b_particle_system.settings().type() == BL::ParticleSettings::type_HAIR) {
+ /* TODO(sergey): Not supported currently. */
+ return;
+ }
+ Transform tfm = get_transform(b_ob.matrix_world());
+ Transform itfm = transform_inverse(tfm);
+ float3 min = make_float3(FLT_MAX, FLT_MAX, FLT_MAX),
+ max = make_float3(-FLT_MAX, -FLT_MAX, -FLT_MAX);
+ float3 particle_size = make_float3(radius, radius, radius);
+ for(int i = 0; i < b_particle_system.particles.length(); ++i) {
+ BL::Particle particle = b_particle_system.particles[i];
+ float3 location = get_float3(particle.location());
+ location = transform_point(&itfm, location);
+ min = ccl::min(min, location - particle_size);
+ max = ccl::max(max, location + particle_size);
+ }
+ /* Calculate texture space from the particle bounds. */
+ loc = (min + max) * 0.5f;
+ size = (max - min) * 0.5f;
+ density_texture_space_invert(loc, size);
+}
+
+} /* namespace */
+
+void point_density_texture_space(BL::ShaderNodeTexPointDensity b_point_density_node,
+ float3& loc,
+ float3& size)
+{
+ /* Fallback values. */
+ loc = make_float3(0.0f, 0.0f, 0.0f);
+ size = make_float3(0.0f, 0.0f, 0.0f);
+ BL::Object b_ob(b_point_density_node.object());
+ if(!b_ob) {
+ return;
+ }
+ if(b_point_density_node.point_source() ==
+ BL::ShaderNodeTexPointDensity::point_source_PARTICLE_SYSTEM)
+ {
+ BL::ParticleSystem b_particle_system(
+ b_point_density_node.particle_system());
+ if(b_particle_system) {
+ density_particle_system_texture_space(b_ob,
+ b_particle_system,
+ b_point_density_node.radius(),
+ loc,
+ size);
+ }
+ }
+ else {
+ density_object_texture_space(b_ob,
+ b_point_density_node.radius(),
+ loc,
+ size);
+ }
+}
+
+CCL_NAMESPACE_END
diff --git a/intern/cycles/util/util_dynlib.h b/intern/cycles/blender/blender_texture.h
index b30cf98c1b9..74fbca02a9e 100644
--- a/intern/cycles/util/util_dynlib.h
+++ b/intern/cycles/blender/blender_texture.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2011-2013 Blender Foundation
+ * Copyright 2011-2015 Blender Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -11,21 +11,21 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
-#ifndef __UTIL_DYNLIB_H__
-#define __UTIL_DYNLIB_H__
+#ifndef __BLENDER_TEXTURE_H__
+#define __BLENDER_TEXTURE_H__
-CCL_NAMESPACE_BEGIN
+#include <stdlib.h>
+#include "blender_sync.h"
-struct DynamicLibrary;
+CCL_NAMESPACE_BEGIN
-DynamicLibrary *dynamic_library_open(const char *name);
-void *dynamic_library_find(DynamicLibrary *lib, const char *name);
-void dynamic_library_close(DynamicLibrary *lib);
+void point_density_texture_space(BL::ShaderNodeTexPointDensity b_point_density_node,
+ float3& loc,
+ float3& size);
CCL_NAMESPACE_END
-#endif /* __UTIL_DYNLIB_H__ */
-
+#endif /* __BLENDER_TEXTURE_H__ */
diff --git a/intern/cycles/blender/blender_util.h b/intern/cycles/blender/blender_util.h
index 35e417d8069..165242d0dff 100644
--- a/intern/cycles/blender/blender_util.h
+++ b/intern/cycles/blender/blender_util.h
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#ifndef __BLENDER_UTIL_H__
@@ -28,7 +28,7 @@
* todo: clean this up ... */
extern "C" {
-void BLI_timestr(double _time, char *str, size_t maxlen);
+size_t BLI_timecode_string_from_time_simple(char *str, size_t maxlen, double time_seconds);
void BKE_image_user_frame_calc(void *iuser, int cfra, int fieldnr);
void BKE_image_user_file_path(void *iuser, void *ima, char *path);
unsigned char *BKE_image_get_pixels_for_frame(void *image, int frame);
@@ -43,11 +43,11 @@ void python_thread_state_restore(void **python_thread_state);
static inline BL::Mesh object_to_mesh(BL::BlendData data, BL::Object object, BL::Scene scene, bool apply_modifiers, bool render, bool calc_undeformed)
{
BL::Mesh me = data.meshes.new_from_object(scene, object, apply_modifiers, (render)? 2: 1, false, calc_undeformed);
- if ((bool)me) {
- if (me.use_auto_smooth()) {
- me.calc_normals_split(me.auto_smooth_angle());
+ if((bool)me) {
+ if(me.use_auto_smooth()) {
+ me.calc_normals_split();
}
- me.calc_tessface();
+ me.calc_tessface(true);
}
return me;
}
@@ -310,7 +310,7 @@ static inline string get_string(PointerRNA& ptr, const char *name)
char cstrbuf[1024];
char *cstr = RNA_string_get_alloc(&ptr, name, cstrbuf, sizeof(cstrbuf));
string str(cstr);
- if (cstr != cstrbuf)
+ if(cstr != cstrbuf)
MEM_freeN(cstr);
return str;
@@ -354,11 +354,20 @@ static inline void mesh_texture_space(BL::Mesh b_mesh, float3& loc, float3& size
}
/* object used for motion blur */
-static inline bool object_use_motion(BL::Object b_ob)
+static inline bool object_use_motion(BL::Object b_parent, BL::Object b_ob)
{
PointerRNA cobject = RNA_pointer_get(&b_ob.ptr, "cycles");
bool use_motion = get_boolean(cobject, "use_motion_blur");
-
+ /* If motion blur is enabled for the object we also check
+ * whether it's enabled for the parent object as well.
+ *
+ * This way we can control motion blur from the dupligroup
+ * duplicator much easier.
+ */
+ if(use_motion && b_parent.ptr.data != b_ob.ptr.data) {
+ PointerRNA parent_cobject = RNA_pointer_get(&b_parent.ptr, "cycles");
+ use_motion &= get_boolean(parent_cobject, "use_motion_blur");
+ }
return use_motion;
}
@@ -375,11 +384,20 @@ static inline uint object_motion_steps(BL::Object b_ob)
}
/* object uses deformation motion blur */
-static inline bool object_use_deform_motion(BL::Object b_ob)
+static inline bool object_use_deform_motion(BL::Object b_parent, BL::Object b_ob)
{
PointerRNA cobject = RNA_pointer_get(&b_ob.ptr, "cycles");
bool use_deform_motion = get_boolean(cobject, "use_deform_motion");
-
+ /* If motion blur is enabled for the object we also check
+ * whether it's enabled for the parent object as well.
+ *
+ * This way we can control motion blur from the dupligroup
+ * duplicator much easier.
+ */
+ if(use_deform_motion && b_parent.ptr.data != b_ob.ptr.data) {
+ PointerRNA parent_cobject = RNA_pointer_get(&b_parent.ptr, "cycles");
+ use_deform_motion &= get_boolean(parent_cobject, "use_deform_motion");
+ }
return use_deform_motion;
}
@@ -388,7 +406,7 @@ static inline BL::SmokeDomainSettings object_smoke_domain_find(BL::Object b_ob)
BL::Object::modifiers_iterator b_mod;
for(b_ob.modifiers.begin(b_mod); b_mod != b_ob.modifiers.end(); ++b_mod) {
- if (b_mod->is_a(&RNA_SmokeModifier)) {
+ if(b_mod->is_a(&RNA_SmokeModifier)) {
BL::SmokeModifier b_smd(*b_mod);
if(b_smd.smoke_type() == BL::SmokeModifier::smoke_type_DOMAIN)
diff --git a/intern/cycles/bvh/bvh.cpp b/intern/cycles/bvh/bvh.cpp
index 15bd814b8d5..4a5f8b1bda6 100644
--- a/intern/cycles/bvh/bvh.cpp
+++ b/intern/cycles/bvh/bvh.cpp
@@ -25,9 +25,9 @@
#include "bvh_node.h"
#include "bvh_params.h"
-#include "util_cache.h"
#include "util_debug.h"
#include "util_foreach.h"
+#include "util_logging.h"
#include "util_map.h"
#include "util_progress.h"
#include "util_system.h"
@@ -69,131 +69,19 @@ BVH *BVH::create(const BVHParams& params, const vector<Object*>& objects)
return new RegularBVH(params, objects);
}
-/* Cache */
-
-bool BVH::cache_read(CacheData& key)
-{
- key.add(system_cpu_bits());
- key.add(&params, sizeof(params));
-
- foreach(Object *ob, objects) {
- Mesh *mesh = ob->mesh;
-
- key.add(mesh->verts);
- key.add(mesh->triangles);
- key.add(mesh->curve_keys);
- key.add(mesh->curves);
- key.add(&ob->bounds, sizeof(ob->bounds));
- key.add(&ob->visibility, sizeof(ob->visibility));
- key.add(&mesh->transform_applied, sizeof(bool));
-
- if(mesh->use_motion_blur) {
- Attribute *attr = mesh->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
- if(attr)
- key.add(attr->buffer);
-
- attr = mesh->curve_attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
- if(attr)
- key.add(attr->buffer);
- }
- }
-
- CacheData value;
-
- if(Cache::global.lookup(key, value)) {
- cache_filename = key.get_filename();
-
- if(!(value.read(pack.root_index) &&
- value.read(pack.SAH) &&
- value.read(pack.nodes) &&
- value.read(pack.object_node) &&
- value.read(pack.tri_woop) &&
- value.read(pack.prim_type) &&
- value.read(pack.prim_visibility) &&
- value.read(pack.prim_index) &&
- value.read(pack.prim_object) &&
- value.read(pack.is_leaf)))
- {
- /* Clear the pack if load failed. */
- pack.root_index = 0;
- pack.SAH = 0.0f;
- pack.nodes.clear();
- pack.object_node.clear();
- pack.tri_woop.clear();
- pack.prim_type.clear();
- pack.prim_visibility.clear();
- pack.prim_index.clear();
- pack.prim_object.clear();
- pack.is_leaf.clear();
- return false;
- }
- return true;
- }
-
- return false;
-}
-
-void BVH::cache_write(CacheData& key)
-{
- CacheData value;
-
- value.add(pack.root_index);
- value.add(pack.SAH);
-
- value.add(pack.nodes);
- value.add(pack.object_node);
- value.add(pack.tri_woop);
- value.add(pack.prim_type);
- value.add(pack.prim_visibility);
- value.add(pack.prim_index);
- value.add(pack.prim_object);
- value.add(pack.is_leaf);
-
- Cache::global.insert(key, value);
-
- cache_filename = key.get_filename();
-}
-
-void BVH::clear_cache_except()
-{
- set<string> except;
-
- if(!cache_filename.empty())
- except.insert(cache_filename);
-
- foreach(Object *ob, objects) {
- Mesh *mesh = ob->mesh;
- BVH *bvh = mesh->bvh;
-
- if(bvh && !bvh->cache_filename.empty())
- except.insert(bvh->cache_filename);
- }
-
- Cache::global.clear_except("bvh", except);
-}
-
/* Building */
void BVH::build(Progress& progress)
{
progress.set_substatus("Building BVH");
- /* cache read */
- CacheData key("bvh");
-
- if(params.use_cache) {
- progress.set_substatus("Looking in BVH cache");
-
- if(cache_read(key))
- return;
- }
-
/* build nodes */
- vector<int> prim_type;
- vector<int> prim_index;
- vector<int> prim_object;
-
- BVHBuild bvh_build(objects, prim_type, prim_index, prim_object, params, progress);
+ BVHBuild bvh_build(objects,
+ pack.prim_type,
+ pack.prim_index,
+ pack.prim_object,
+ params,
+ progress);
BVHNode *root = bvh_build.run();
if(progress.get_cancel()) {
@@ -201,11 +89,6 @@ void BVH::build(Progress& progress)
return;
}
- /* todo: get rid of this copy */
- pack.prim_type = prim_type;
- pack.prim_index = prim_index;
- pack.prim_object = prim_object;
-
/* compute SAH */
if(!params.top_level)
pack.SAH = root->computeSubtreeSAHCost(params);
@@ -226,23 +109,10 @@ void BVH::build(Progress& progress)
/* pack nodes */
progress.set_substatus("Packing BVH nodes");
- array<int> tmp_prim_object = pack.prim_object;
- pack_nodes(tmp_prim_object, root);
-
+ pack_nodes(root);
+
/* free build nodes */
root->deleteSubtree();
-
- if(progress.get_cancel()) return;
-
- /* cache write */
- if(params.use_cache) {
- progress.set_substatus("Writing BVH cache");
- cache_write(key);
-
- /* clear other bvh files from cache */
- if(params.top_level)
- clear_cache_except();
- }
}
/* Refitting */
@@ -263,11 +133,9 @@ void BVH::refit(Progress& progress)
void BVH::pack_triangle(int idx, float4 woop[3])
{
int tob = pack.prim_object[idx];
+ assert(tob >= 0 && tob < objects.size());
const Mesh *mesh = objects[tob]->mesh;
- if(mesh->has_motion_blur())
- return;
-
int tidx = pack.prim_index[idx];
const int *vidx = mesh->triangles[tidx].v;
const float3* vpos = &mesh->verts[0];
@@ -275,68 +143,13 @@ void BVH::pack_triangle(int idx, float4 woop[3])
float3 v1 = vpos[vidx[1]];
float3 v2 = vpos[vidx[2]];
- float3 r0 = v0 - v2;
- float3 r1 = v1 - v2;
- float3 r2 = cross(r0, r1);
-
- if(is_zero(r0) || is_zero(r1) || is_zero(r2)) {
- /* degenerate */
- woop[0] = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
- woop[1] = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
- woop[2] = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
- }
- else {
- Transform t = make_transform(
- r0.x, r1.x, r2.x, v2.x,
- r0.y, r1.y, r2.y, v2.y,
- r0.z, r1.z, r2.z, v2.z,
- 0.0f, 0.0f, 0.0f, 1.0f);
-
- t = transform_inverse(t);
-
- woop[0] = make_float4(t.z.x, t.z.y, t.z.z, -t.z.w);
- woop[1] = make_float4(t.x.x, t.x.y, t.x.z, t.x.w);
- woop[2] = make_float4(t.y.x, t.y.y, t.y.z, t.y.w);
- }
+ woop[0] = float3_to_float4(v0);
+ woop[1] = float3_to_float4(v1);
+ woop[2] = float3_to_float4(v2);
}
/* Curves*/
-void BVH::pack_curve_segment(int idx, float4 woop[3])
-{
- int tob = pack.prim_object[idx];
- const Mesh *mesh = objects[tob]->mesh;
- int tidx = pack.prim_index[idx];
- int segment = PRIMITIVE_UNPACK_SEGMENT(pack.prim_type[idx]);
- int k0 = mesh->curves[tidx].first_key + segment;
- int k1 = mesh->curves[tidx].first_key + segment + 1;
- float3 v0 = float4_to_float3(mesh->curve_keys[k0]);
- float3 v1 = float4_to_float3(mesh->curve_keys[k1]);
-
- float3 d0 = v1 - v0;
- float l = len(d0);
-
- /*Plan
- *Transform tfm = make_transform(
- * location <3> , l,
- * extra curve data <3> , StrID,
- * nextkey, flags/tip?, 0, 0);
- */
- float3 tg0 = make_float3(1.0f, 0.0f, 0.0f);
- float3 tg1 = make_float3(1.0f, 0.0f, 0.0f);
-
- Transform tfm = make_transform(
- tg0.x, tg0.y, tg0.z, l,
- tg1.x, tg1.y, tg1.z, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 1);
-
- woop[0] = tfm.x;
- woop[1] = tfm.y;
- woop[2] = tfm.z;
-
-}
-
void BVH::pack_primitives()
{
int nsize = TRI_NODE_SIZE;
@@ -351,11 +164,14 @@ void BVH::pack_primitives()
if(pack.prim_index[i] != -1) {
float4 woop[3];
- if(pack.prim_type[i] & PRIMITIVE_ALL_CURVE)
- pack_curve_segment(i, woop);
- else
+ if(pack.prim_type[i] & PRIMITIVE_TRIANGLE) {
pack_triangle(i, woop);
-
+ }
+ else {
+ /* Avoid use of uninitialized memory. */
+ memset(&woop, 0, sizeof(woop));
+ }
+
memcpy(&pack.tri_woop[i * nsize], woop, sizeof(float4)*3);
int tob = pack.prim_object[i];
@@ -374,13 +190,14 @@ void BVH::pack_primitives()
/* Pack Instances */
-void BVH::pack_instances(size_t nodes_size)
+void BVH::pack_instances(size_t nodes_size, size_t leaf_nodes_size)
{
/* The BVH's for instances are built separately, but for traversal all
* BVH's are stored in global arrays. This function merges them into the
* top level BVH, adjusting indexes and offsets where appropriate. */
bool use_qbvh = params.use_qbvh;
size_t nsize = (use_qbvh)? BVH_QNODE_SIZE: BVH_NODE_SIZE;
+ size_t nsize_leaf = (use_qbvh)? BVH_QNODE_LEAF_SIZE: BVH_NODE_LEAF_SIZE;
/* adjust primitive index to point to the triangle in the global array, for
* meshes with transform applied and already in the top level BVH */
@@ -395,6 +212,7 @@ void BVH::pack_instances(size_t nodes_size)
/* track offsets of instanced BVH data in global array */
size_t prim_offset = pack.prim_index.size();
size_t nodes_offset = nodes_size;
+ size_t nodes_leaf_offset = leaf_nodes_size;
/* clear array that gives the node indexes for instanced objects */
pack.object_node.clear();
@@ -406,6 +224,7 @@ void BVH::pack_instances(size_t nodes_size)
size_t pack_prim_index_offset = prim_index_size;
size_t pack_tri_woop_offset = tri_woop_size;
size_t pack_nodes_offset = nodes_size;
+ size_t pack_leaf_nodes_offset = leaf_nodes_size;
size_t object_offset = 0;
map<Mesh*, int> mesh_map;
@@ -418,7 +237,8 @@ void BVH::pack_instances(size_t nodes_size)
if(mesh_map.find(mesh) == mesh_map.end()) {
prim_index_size += bvh->pack.prim_index.size();
tri_woop_size += bvh->pack.tri_woop.size();
- nodes_size += bvh->pack.nodes.size()*nsize;
+ nodes_size += bvh->pack.nodes.size();
+ leaf_nodes_size += bvh->pack.leaf_nodes.size();
mesh_map[mesh] = 1;
}
@@ -433,6 +253,7 @@ void BVH::pack_instances(size_t nodes_size)
pack.prim_visibility.resize(prim_index_size);
pack.tri_woop.resize(tri_woop_size);
pack.nodes.resize(nodes_size);
+ pack.leaf_nodes.resize(leaf_nodes_size);
pack.object_node.resize(objects.size());
int *pack_prim_index = (pack.prim_index.size())? &pack.prim_index[0]: NULL;
@@ -441,6 +262,7 @@ void BVH::pack_instances(size_t nodes_size)
uint *pack_prim_visibility = (pack.prim_visibility.size())? &pack.prim_visibility[0]: NULL;
float4 *pack_tri_woop = (pack.tri_woop.size())? &pack.tri_woop[0]: NULL;
int4 *pack_nodes = (pack.nodes.size())? &pack.nodes[0]: NULL;
+ int4 *pack_leaf_nodes = (pack.leaf_nodes.size())? &pack.leaf_nodes[0]: NULL;
/* merge */
foreach(Object *ob, objects) {
@@ -466,12 +288,13 @@ void BVH::pack_instances(size_t nodes_size)
BVH *bvh = mesh->bvh;
int noffset = nodes_offset/nsize;
+ int noffset_leaf = nodes_leaf_offset/nsize_leaf;
int mesh_tri_offset = mesh->tri_offset;
int mesh_curve_offset = mesh->curve_offset;
/* fill in node indexes for instances */
- if((bvh->pack.is_leaf.size() != 0) && bvh->pack.is_leaf[0])
- pack.object_node[object_offset++] = -noffset-1;
+ if(bvh->pack.root_index == -1)
+ pack.object_node[object_offset++] = -noffset_leaf-1;
else
pack.object_node[object_offset++] = noffset;
@@ -505,11 +328,25 @@ void BVH::pack_instances(size_t nodes_size)
}
/* merge nodes */
+ if(bvh->pack.leaf_nodes.size()) {
+ int4 *leaf_nodes_offset = &bvh->pack.leaf_nodes[0];
+ size_t leaf_nodes_offset_size = bvh->pack.leaf_nodes.size();
+ for(size_t i = 0, j = 0; i < leaf_nodes_offset_size; i+=nsize_leaf, j++) {
+ int4 data = leaf_nodes_offset[i];
+ data.x += prim_offset;
+ data.y += prim_offset;
+ pack_leaf_nodes[pack_leaf_nodes_offset] = data;
+ pack_leaf_nodes_offset += nsize_leaf;
+ }
+ }
+
if(bvh->pack.nodes.size()) {
- size_t nsize_bbox = (use_qbvh)? nsize-2: nsize-1;
+ /* For QBVH we're packing a child bbox into 6 float4,
+ * and for regular BVH they're packed into 3 float4.
+ */
+ size_t nsize_bbox = (use_qbvh)? 6: 3;
int4 *bvh_nodes = &bvh->pack.nodes[0];
size_t bvh_nodes_size = bvh->pack.nodes.size();
- int *bvh_is_leaf = (bvh->pack.is_leaf.size() != 0) ? &bvh->pack.is_leaf[0] : NULL;
for(size_t i = 0, j = 0; i < bvh_nodes_size; i+=nsize, j++) {
memcpy(pack_nodes + pack_nodes_offset, bvh_nodes + i, nsize_bbox*sizeof(int4));
@@ -517,30 +354,29 @@ void BVH::pack_instances(size_t nodes_size)
/* modify offsets into arrays */
int4 data = bvh_nodes[i + nsize_bbox];
- if(bvh_is_leaf && bvh_is_leaf[j]) {
- data.x += prim_offset;
- data.y += prim_offset;
- }
- else {
- data.x += (data.x < 0)? -noffset: noffset;
- data.y += (data.y < 0)? -noffset: noffset;
+ data.x += (data.x < 0)? -noffset_leaf: noffset;
+ data.y += (data.y < 0)? -noffset_leaf: noffset;
- if(use_qbvh) {
- data.z += (data.z < 0)? -noffset: noffset;
- data.w += (data.w < 0)? -noffset: noffset;
- }
+ if(use_qbvh) {
+ data.z += (data.z < 0)? -noffset_leaf: noffset;
+ data.w += (data.w < 0)? -noffset_leaf: noffset;
}
pack_nodes[pack_nodes_offset + nsize_bbox] = data;
- if(use_qbvh)
- pack_nodes[pack_nodes_offset + nsize_bbox+1] = bvh_nodes[i + nsize_bbox+1];
+ /* Usually this copies nothing, but we better
+ * be prepared for possible node size extension.
+ */
+ memcpy(&pack_nodes[pack_nodes_offset + nsize_bbox+1],
+ &bvh_nodes[i + nsize_bbox+1],
+ sizeof(int4) * (nsize - (nsize_bbox+1)));
pack_nodes_offset += nsize;
}
}
nodes_offset += bvh->pack.nodes.size();
+ nodes_leaf_offset += bvh->pack.leaf_nodes.size();
prim_offset += bvh->pack.prim_index.size();
}
}
@@ -554,12 +390,24 @@ RegularBVH::RegularBVH(const BVHParams& params_, const vector<Object*>& objects_
void RegularBVH::pack_leaf(const BVHStackEntry& e, const LeafNode *leaf)
{
- if(leaf->num_triangles() == 1 && pack.prim_index[leaf->m_lo] == -1)
+ float4 data[BVH_NODE_LEAF_SIZE];
+ memset(data, 0, sizeof(data));
+ if(leaf->num_triangles() == 1 && pack.prim_index[leaf->m_lo] == -1) {
/* object */
- pack_node(e.idx, leaf->m_bounds, leaf->m_bounds, ~(leaf->m_lo), 0, leaf->m_visibility, leaf->m_visibility);
- else
+ data[0].x = __int_as_float(~(leaf->m_lo));
+ data[0].y = __int_as_float(0);
+ }
+ else {
/* triangle */
- pack_node(e.idx, leaf->m_bounds, leaf->m_bounds, leaf->m_lo, leaf->m_hi, leaf->m_visibility, leaf->m_visibility);
+ data[0].x = __int_as_float(leaf->m_lo);
+ data[0].y = __int_as_float(leaf->m_hi);
+ }
+ data[0].z = __uint_as_float(leaf->m_visibility);
+ if(leaf->num_triangles() != 0) {
+ data[0].w = __uint_as_float(pack.prim_type[leaf->m_lo]);
+ }
+
+ memcpy(&pack.leaf_nodes[e.idx * BVH_NODE_LEAF_SIZE], data, sizeof(float4)*BVH_NODE_LEAF_SIZE);
}
void RegularBVH::pack_inner(const BVHStackEntry& e, const BVHStackEntry& e0, const BVHStackEntry& e1)
@@ -580,33 +428,38 @@ void RegularBVH::pack_node(int idx, const BoundBox& b0, const BoundBox& b1, int
memcpy(&pack.nodes[idx * BVH_NODE_SIZE], data, sizeof(int4)*BVH_NODE_SIZE);
}
-void RegularBVH::pack_nodes(const array<int>& prims, const BVHNode *root)
+void RegularBVH::pack_nodes(const BVHNode *root)
{
- size_t node_size = root->getSubtreeSize(BVH_STAT_NODE_COUNT);
+ size_t tot_node_size = root->getSubtreeSize(BVH_STAT_NODE_COUNT);
+ size_t leaf_node_size = root->getSubtreeSize(BVH_STAT_LEAF_COUNT);
+ size_t node_size = tot_node_size - leaf_node_size;
/* resize arrays */
pack.nodes.clear();
- pack.is_leaf.clear();
- pack.is_leaf.resize(node_size);
/* for top level BVH, first merge existing BVH's so we know the offsets */
- if(params.top_level)
- pack_instances(node_size*BVH_NODE_SIZE);
- else
+ if(params.top_level) {
+ pack_instances(node_size*BVH_NODE_SIZE,
+ leaf_node_size*BVH_NODE_LEAF_SIZE);
+ }
+ else {
pack.nodes.resize(node_size*BVH_NODE_SIZE);
+ pack.leaf_nodes.resize(leaf_node_size*BVH_NODE_LEAF_SIZE);
+ }
- int nextNodeIdx = 0;
+ int nextNodeIdx = 0, nextLeafNodeIdx = 0;
vector<BVHStackEntry> stack;
stack.reserve(BVHParams::MAX_DEPTH*2);
- stack.push_back(BVHStackEntry(root, nextNodeIdx++));
+ if(root->is_leaf())
+ stack.push_back(BVHStackEntry(root, nextLeafNodeIdx++));
+ else
+ stack.push_back(BVHStackEntry(root, nextNodeIdx++));
while(stack.size()) {
BVHStackEntry e = stack.back();
stack.pop_back();
- pack.is_leaf[e.idx] = e.node->is_leaf();
-
if(e.node->is_leaf()) {
/* leaf node */
const LeafNode* leaf = reinterpret_cast<const LeafNode*>(e.node);
@@ -614,15 +467,17 @@ void RegularBVH::pack_nodes(const array<int>& prims, const BVHNode *root)
}
else {
/* innner node */
- stack.push_back(BVHStackEntry(e.node->get_child(0), nextNodeIdx++));
- stack.push_back(BVHStackEntry(e.node->get_child(1), nextNodeIdx++));
+ int idx0 = (e.node->get_child(0)->is_leaf())? (nextLeafNodeIdx++) : (nextNodeIdx++);
+ int idx1 = (e.node->get_child(1)->is_leaf())? (nextLeafNodeIdx++) : (nextNodeIdx++);
+ stack.push_back(BVHStackEntry(e.node->get_child(0), idx0));
+ stack.push_back(BVHStackEntry(e.node->get_child(1), idx1));
pack_inner(e, stack[stack.size()-2], stack[stack.size()-1]);
}
}
/* root index to start traversal at, to handle case of single leaf node */
- pack.root_index = (pack.is_leaf[0])? -1: 0;
+ pack.root_index = (root->is_leaf())? -1: 0;
}
void RegularBVH::refit_nodes()
@@ -631,17 +486,15 @@ void RegularBVH::refit_nodes()
BoundBox bbox = BoundBox::empty;
uint visibility = 0;
- refit_node(0, (pack.is_leaf[0])? true: false, bbox, visibility);
+ refit_node(0, (pack.root_index == -1)? true: false, bbox, visibility);
}
void RegularBVH::refit_node(int idx, bool leaf, BoundBox& bbox, uint& visibility)
{
- int4 *data = &pack.nodes[idx*4];
-
- int c0 = data[3].x;
- int c1 = data[3].y;
-
if(leaf) {
+ int4 *data = &pack.leaf_nodes[idx*BVH_NODE_LEAF_SIZE];
+ int c0 = data[0].x;
+ int c1 = data[0].y;
/* refit leaf node */
for(int prim = c0; prim < c1; prim++) {
int pidx = pack.prim_index[prim];
@@ -675,7 +528,7 @@ void RegularBVH::refit_node(int idx, bool leaf, BoundBox& bbox, uint& visibility
size_t steps = mesh->motion_steps - 1;
float4 *key_steps = attr->data_float4();
- for (size_t i = 0; i < steps; i++)
+ for(size_t i = 0; i < steps; i++)
curve.bounds_grow(k, key_steps + i*mesh_size, bbox);
}
}
@@ -697,7 +550,7 @@ void RegularBVH::refit_node(int idx, bool leaf, BoundBox& bbox, uint& visibility
size_t steps = mesh->motion_steps - 1;
float3 *vert_steps = attr->data_float3();
- for (size_t i = 0; i < steps; i++)
+ for(size_t i = 0; i < steps; i++)
triangle.bounds_grow(vert_steps + i*mesh_size, bbox);
}
}
@@ -707,9 +560,20 @@ void RegularBVH::refit_node(int idx, bool leaf, BoundBox& bbox, uint& visibility
visibility |= ob->visibility;
}
- pack_node(idx, bbox, bbox, c0, c1, visibility, visibility);
+ /* TODO(sergey): De-duplicate with pack_leaf(). */
+ float4 leaf_data[BVH_NODE_LEAF_SIZE];
+ leaf_data[0].x = __int_as_float(c0);
+ leaf_data[0].y = __int_as_float(c1);
+ leaf_data[0].z = __uint_as_float(visibility);
+ leaf_data[0].w = __uint_as_float(data[0].w);
+ memcpy(&pack.leaf_nodes[idx * BVH_NODE_LEAF_SIZE],
+ leaf_data,
+ sizeof(float4)*BVH_NODE_LEAF_SIZE);
}
else {
+ int4 *data = &pack.nodes[idx*BVH_NODE_SIZE];
+ int c0 = data[3].x;
+ int c1 = data[3].y;
/* refit inner node, set bbox from children */
BoundBox bbox0 = BoundBox::empty, bbox1 = BoundBox::empty;
uint visibility0 = 0, visibility1 = 0;
@@ -731,28 +595,28 @@ QBVH::QBVH(const BVHParams& params_, const vector<Object*>& objects_)
: BVH(params_, objects_)
{
params.use_qbvh = true;
-
- /* todo: use visibility */
}
void QBVH::pack_leaf(const BVHStackEntry& e, const LeafNode *leaf)
{
- float4 data[BVH_QNODE_SIZE];
-
+ float4 data[BVH_QNODE_LEAF_SIZE];
memset(data, 0, sizeof(data));
-
if(leaf->num_triangles() == 1 && pack.prim_index[leaf->m_lo] == -1) {
/* object */
- data[6].x = __int_as_float(~(leaf->m_lo));
- data[6].y = __int_as_float(0);
+ data[0].x = __int_as_float(~(leaf->m_lo));
+ data[0].y = __int_as_float(0);
}
else {
/* triangle */
- data[6].x = __int_as_float(leaf->m_lo);
- data[6].y = __int_as_float(leaf->m_hi);
+ data[0].x = __int_as_float(leaf->m_lo);
+ data[0].y = __int_as_float(leaf->m_hi);
+ }
+ data[0].z = __uint_as_float(leaf->m_visibility);
+ if(leaf->num_triangles() != 0) {
+ data[0].w = __uint_as_float(pack.prim_type[leaf->m_lo]);
}
- memcpy(&pack.nodes[e.idx * BVH_QNODE_SIZE], data, sizeof(float4)*BVH_QNODE_SIZE);
+ memcpy(&pack.leaf_nodes[e.idx * BVH_QNODE_LEAF_SIZE], data, sizeof(float4)*BVH_QNODE_LEAF_SIZE);
}
void QBVH::pack_inner(const BVHStackEntry& e, const BVHStackEntry *en, int num)
@@ -771,20 +635,22 @@ void QBVH::pack_inner(const BVHStackEntry& e, const BVHStackEntry *en, int num)
data[5][i] = bb_max.z;
data[6][i] = __int_as_float(en[i].encodeIdx());
- data[7][i] = 0.0f;
}
for(int i = num; i < 4; i++) {
- data[0][i] = 0.0f;
- data[1][i] = 0.0f;
- data[2][i] = 0.0f;
+ /* We store BB which would never be recorded as intersection
+ * so kernel might safely assume there are always 4 child nodes.
+ */
+ data[0][i] = FLT_MAX;
+ data[1][i] = -FLT_MAX;
+
+ data[2][i] = FLT_MAX;
+ data[3][i] = -FLT_MAX;
- data[3][i] = 0.0f;
- data[4][i] = 0.0f;
- data[5][i] = 0.0f;
+ data[4][i] = FLT_MAX;
+ data[5][i] = -FLT_MAX;
data[6][i] = __int_as_float(0);
- data[7][i] = 0.0f;
}
memcpy(&pack.nodes[e.idx * BVH_QNODE_SIZE], data, sizeof(float4)*BVH_QNODE_SIZE);
@@ -792,33 +658,41 @@ void QBVH::pack_inner(const BVHStackEntry& e, const BVHStackEntry *en, int num)
/* Quad SIMD Nodes */
-void QBVH::pack_nodes(const array<int>& prims, const BVHNode *root)
+void QBVH::pack_nodes(const BVHNode *root)
{
- size_t node_size = root->getSubtreeSize(BVH_STAT_NODE_COUNT);
+ size_t tot_node_size = root->getSubtreeSize(BVH_STAT_QNODE_COUNT);
+ size_t leaf_node_size = root->getSubtreeSize(BVH_STAT_LEAF_COUNT);
+ size_t node_size = tot_node_size - leaf_node_size;
/* resize arrays */
pack.nodes.clear();
- pack.is_leaf.clear();
- pack.is_leaf.resize(node_size);
+ pack.leaf_nodes.clear();
/* for top level BVH, first merge existing BVH's so we know the offsets */
- if(params.top_level)
- pack_instances(node_size*BVH_QNODE_SIZE);
- else
+ if(params.top_level) {
+ pack_instances(node_size*BVH_QNODE_SIZE,
+ leaf_node_size*BVH_QNODE_LEAF_SIZE);
+ }
+ else {
pack.nodes.resize(node_size*BVH_QNODE_SIZE);
+ pack.leaf_nodes.resize(leaf_node_size*BVH_QNODE_LEAF_SIZE);
+ }
- int nextNodeIdx = 0;
+ int nextNodeIdx = 0, nextLeafNodeIdx = 0;
vector<BVHStackEntry> stack;
stack.reserve(BVHParams::MAX_DEPTH*2);
- stack.push_back(BVHStackEntry(root, nextNodeIdx++));
+ if(root->is_leaf()) {
+ stack.push_back(BVHStackEntry(root, nextLeafNodeIdx++));
+ }
+ else {
+ stack.push_back(BVHStackEntry(root, nextNodeIdx++));
+ }
while(stack.size()) {
BVHStackEntry e = stack.back();
stack.pop_back();
- pack.is_leaf[e.idx] = e.node->is_leaf();
-
if(e.node->is_leaf()) {
/* leaf node */
const LeafNode* leaf = reinterpret_cast<const LeafNode*>(e.node);
@@ -851,8 +725,16 @@ void QBVH::pack_nodes(const array<int>& prims, const BVHNode *root)
}
/* push entries on the stack */
- for(int i = 0; i < numnodes; i++)
- stack.push_back(BVHStackEntry(nodes[i], nextNodeIdx++));
+ for(int i = 0; i < numnodes; i++) {
+ int idx;
+ if(nodes[i]->is_leaf()) {
+ idx = nextLeafNodeIdx++;
+ }
+ else {
+ idx = nextNodeIdx++;
+ }
+ stack.push_back(BVHStackEntry(nodes[i], idx));
+ }
/* set node */
pack_inner(e, &stack[stack.size()-numnodes], numnodes);
@@ -860,13 +742,144 @@ void QBVH::pack_nodes(const array<int>& prims, const BVHNode *root)
}
/* root index to start traversal at, to handle case of single leaf node */
- pack.root_index = (pack.is_leaf[0])? -1: 0;
+ pack.root_index = (root->is_leaf())? -1: 0;
}
void QBVH::refit_nodes()
{
- assert(0); /* todo */
+ assert(!params.top_level);
+
+ BoundBox bbox = BoundBox::empty;
+ uint visibility = 0;
+ refit_node(0, (pack.root_index == -1)? true: false, bbox, visibility);
}
-CCL_NAMESPACE_END
+void QBVH::refit_node(int idx, bool leaf, BoundBox& bbox, uint& visibility)
+{
+ if(leaf) {
+ int4 *data = &pack.leaf_nodes[idx*BVH_QNODE_LEAF_SIZE];
+ int4 c = data[0];
+ /* Refit leaf node. */
+ for(int prim = c.x; prim < c.y; prim++) {
+ int pidx = pack.prim_index[prim];
+ int tob = pack.prim_object[prim];
+ Object *ob = objects[tob];
+
+ if(pidx == -1) {
+ /* Object instance. */
+ bbox.grow(ob->bounds);
+ }
+ else {
+ /* Primitives. */
+ const Mesh *mesh = ob->mesh;
+
+ if(pack.prim_type[prim] & PRIMITIVE_ALL_CURVE) {
+ /* Curves. */
+ int str_offset = (params.top_level)? mesh->curve_offset: 0;
+ const Mesh::Curve& curve = mesh->curves[pidx - str_offset];
+ int k = PRIMITIVE_UNPACK_SEGMENT(pack.prim_type[prim]);
+
+ curve.bounds_grow(k, &mesh->curve_keys[0], bbox);
+
+ visibility |= PATH_RAY_CURVE;
+
+ /* Motion curves. */
+ if(mesh->use_motion_blur) {
+ Attribute *attr = mesh->curve_attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
+
+ if(attr) {
+ size_t mesh_size = mesh->curve_keys.size();
+ size_t steps = mesh->motion_steps - 1;
+ float4 *key_steps = attr->data_float4();
+
+ for(size_t i = 0; i < steps; i++)
+ curve.bounds_grow(k, key_steps + i*mesh_size, bbox);
+ }
+ }
+ }
+ else {
+ /* Triangles. */
+ int tri_offset = (params.top_level)? mesh->tri_offset: 0;
+ const Mesh::Triangle& triangle = mesh->triangles[pidx - tri_offset];
+ const float3 *vpos = &mesh->verts[0];
+
+ triangle.bounds_grow(vpos, bbox);
+
+ /* Motion triangles. */
+ if(mesh->use_motion_blur) {
+ Attribute *attr = mesh->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
+
+ if(attr) {
+ size_t mesh_size = mesh->verts.size();
+ size_t steps = mesh->motion_steps - 1;
+ float3 *vert_steps = attr->data_float3();
+
+ for(size_t i = 0; i < steps; i++)
+ triangle.bounds_grow(vert_steps + i*mesh_size, bbox);
+ }
+ }
+ }
+ }
+
+ visibility |= ob->visibility;
+ }
+
+ /* TODO(sergey): This is actually a copy of pack_leaf(),
+ * but this chunk of code only knows actual data and has
+ * no idea about BVHNode.
+ *
+ * Would be nice to de-duplicate code, but trying to make
+ * making code more general ends up in much nastier code
+ * in my opinion so far.
+ *
+ * Same applies to the inner nodes case below.
+ */
+ float4 leaf_data[BVH_QNODE_LEAF_SIZE];
+ leaf_data[0].x = __int_as_float(c.x);
+ leaf_data[0].y = __int_as_float(c.y);
+ leaf_data[0].z = __uint_as_float(visibility);
+ leaf_data[0].w = __uint_as_float(c.w);
+ memcpy(&pack.leaf_nodes[idx * BVH_QNODE_LEAF_SIZE],
+ leaf_data,
+ sizeof(float4)*BVH_QNODE_LEAF_SIZE);
+ }
+ else {
+ int4 *data = &pack.nodes[idx*BVH_QNODE_SIZE];
+ int4 c = data[6];
+ /* Refit inner node, set bbox from children. */
+ BoundBox child_bbox[4] = {BoundBox::empty,
+ BoundBox::empty,
+ BoundBox::empty,
+ BoundBox::empty};
+ uint child_visibility[4] = {0};
+ int num_nodes = 0;
+
+ for(int i = 0; i < 4; ++i) {
+ if(c[i] != 0) {
+ refit_node((c[i] < 0)? -c[i]-1: c[i], (c[i] < 0),
+ child_bbox[i], child_visibility[i]);
+ ++num_nodes;
+ bbox.grow(child_bbox[i]);
+ visibility |= child_visibility[i];
+ }
+ }
+ float4 inner_data[BVH_QNODE_SIZE];
+ for(int i = 0; i < 4; ++i) {
+ float3 bb_min = child_bbox[i].min;
+ float3 bb_max = child_bbox[i].max;
+ inner_data[0][i] = bb_min.x;
+ inner_data[1][i] = bb_max.x;
+ inner_data[2][i] = bb_min.y;
+ inner_data[3][i] = bb_max.y;
+ inner_data[4][i] = bb_min.z;
+ inner_data[5][i] = bb_max.z;
+ inner_data[6][i] = __int_as_float(c[i]);
+ }
+ memcpy(&pack.nodes[idx * BVH_QNODE_SIZE],
+ inner_data,
+ sizeof(float4)*BVH_QNODE_SIZE);
+ }
+}
+
+CCL_NAMESPACE_END
diff --git a/intern/cycles/bvh/bvh.h b/intern/cycles/bvh/bvh.h
index 5fcaaaa988c..272a3fa1514 100644
--- a/intern/cycles/bvh/bvh.h
+++ b/intern/cycles/bvh/bvh.h
@@ -20,7 +20,6 @@
#include "bvh_params.h"
-#include "util_string.h"
#include "util_types.h"
#include "util_vector.h"
@@ -30,13 +29,14 @@ class BVHNode;
struct BVHStackEntry;
class BVHParams;
class BoundBox;
-class CacheData;
class LeafNode;
class Object;
class Progress;
#define BVH_NODE_SIZE 4
-#define BVH_QNODE_SIZE 8
+#define BVH_NODE_LEAF_SIZE 1
+#define BVH_QNODE_SIZE 7
+#define BVH_QNODE_LEAF_SIZE 1
#define BVH_ALIGN 4096
#define TRI_NODE_SIZE 3
@@ -47,7 +47,9 @@ class Progress;
struct PackedBVH {
/* BVH nodes storage, one node is 4x int4, and contains two bounding boxes,
* and child, triangle or object indexes depending on the node type */
- array<int4> nodes;
+ array<int4> nodes;
+ /* BVH leaf nodes storage. */
+ array<int4> leaf_nodes;
/* object index to BVH node index mapping for instances */
array<int> object_node;
/* precomputed triangle intersection data, one triangle is 4x float4 */
@@ -61,9 +63,6 @@ struct PackedBVH {
array<int> prim_index;
/* mapping from BVH primitive index, to the object id of that primitive. */
array<int> prim_object;
- /* quick array to lookup if a node is a leaf, not used for traversal, only
- * for instance BVH merging */
- array<int> is_leaf;
/* index of the root node. */
int root_index;
@@ -86,7 +85,6 @@ public:
PackedBVH pack;
BVHParams params;
vector<Object*> objects;
- string cache_filename;
static BVH *create(const BVHParams& params, const vector<Object*>& objects);
virtual ~BVH() {}
@@ -94,25 +92,18 @@ public:
void build(Progress& progress);
void refit(Progress& progress);
- void clear_cache_except();
-
protected:
BVH(const BVHParams& params, const vector<Object*>& objects);
- /* cache */
- bool cache_read(CacheData& key);
- void cache_write(CacheData& key);
-
/* triangles and strands*/
void pack_primitives();
void pack_triangle(int idx, float4 woop[3]);
- void pack_curve_segment(int idx, float4 woop[3]);
/* merge instance BVH's */
- void pack_instances(size_t nodes_size);
+ void pack_instances(size_t nodes_size, size_t leaf_nodes_size);
/* for subclasses to implement */
- virtual void pack_nodes(const array<int>& prims, const BVHNode *root) = 0;
+ virtual void pack_nodes(const BVHNode *root) = 0;
virtual void refit_nodes() = 0;
};
@@ -127,7 +118,7 @@ protected:
RegularBVH(const BVHParams& params, const vector<Object*>& objects);
/* pack */
- void pack_nodes(const array<int>& prims, const BVHNode *root);
+ void pack_nodes(const BVHNode *root);
void pack_leaf(const BVHStackEntry& e, const LeafNode *leaf);
void pack_inner(const BVHStackEntry& e, const BVHStackEntry& e0, const BVHStackEntry& e1);
void pack_node(int idx, const BoundBox& b0, const BoundBox& b1, int c0, int c1, uint visibility0, uint visibility1);
@@ -148,12 +139,13 @@ protected:
QBVH(const BVHParams& params, const vector<Object*>& objects);
/* pack */
- void pack_nodes(const array<int>& prims, const BVHNode *root);
+ void pack_nodes(const BVHNode *root);
void pack_leaf(const BVHStackEntry& e, const LeafNode *leaf);
void pack_inner(const BVHStackEntry& e, const BVHStackEntry *en, int num);
/* refit */
void refit_nodes();
+ void refit_node(int idx, bool leaf, BoundBox& bbox, uint& visibility);
};
CCL_NAMESPACE_END
diff --git a/intern/cycles/bvh/bvh_binning.cpp b/intern/cycles/bvh/bvh_binning.cpp
index bd37ffbcf38..8745e39c21e 100644
--- a/intern/cycles/bvh/bvh_binning.cpp
+++ b/intern/cycles/bvh/bvh_binning.cpp
@@ -29,10 +29,10 @@ CCL_NAMESPACE_BEGIN
/* SSE replacements */
-__forceinline void prefetch_L1 (const void* ptr) { }
-__forceinline void prefetch_L2 (const void* ptr) { }
-__forceinline void prefetch_L3 (const void* ptr) { }
-__forceinline void prefetch_NTA(const void* ptr) { }
+__forceinline void prefetch_L1 (const void* /*ptr*/) { }
+__forceinline void prefetch_L2 (const void* /*ptr*/) { }
+__forceinline void prefetch_L3 (const void* /*ptr*/) { }
+__forceinline void prefetch_NTA(const void* /*ptr*/) { }
template<size_t src> __forceinline float extract(const int4& b)
{ return b[src]; }
@@ -76,8 +76,8 @@ BVHObjectBinning::BVHObjectBinning(const BVHRange& job, BVHReference *prims)
prefetch_L2(&prims[start() + i + 8]);
/* map even and odd primitive to bin */
- BVHReference prim0 = prims[start() + i + 0];
- BVHReference prim1 = prims[start() + i + 1];
+ const BVHReference& prim0 = prims[start() + i + 0];
+ const BVHReference& prim1 = prims[start() + i + 1];
int4 bin0 = get_bin(prim0.bounds());
int4 bin1 = get_bin(prim1.bounds());
@@ -96,7 +96,7 @@ BVHObjectBinning::BVHObjectBinning(const BVHRange& job, BVHReference *prims)
/* for uneven number of primitives */
if(i < ssize_t(size())) {
/* map primitive to bin */
- BVHReference prim0 = prims[start() + i];
+ const BVHReference& prim0 = prims[start() + i];
int4 bin0 = get_bin(prim0.bounds());
/* increase bounds of bins */
diff --git a/intern/cycles/bvh/bvh_build.cpp b/intern/cycles/bvh/bvh_build.cpp
index eb4cca92b6b..45b0aaa2d63 100644
--- a/intern/cycles/bvh/bvh_build.cpp
+++ b/intern/cycles/bvh/bvh_build.cpp
@@ -28,11 +28,27 @@
#include "util_debug.h"
#include "util_foreach.h"
+#include "util_logging.h"
#include "util_progress.h"
#include "util_time.h"
CCL_NAMESPACE_BEGIN
+#if !defined(__KERNEL_SSE2__)
+/* TODO(sergey): Move to some generic header so all code
+ * can use bitscan on non-SSE processors.
+ */
+ccl_device_inline int bitscan(int value)
+{
+ assert(value != 0);
+ int bit = 0;
+ while(value >>= 1) {
+ ++bit;
+ }
+ return bit;
+}
+#endif
+
/* BVH Build Task */
class BVHBuildTask : public Task {
@@ -49,15 +65,18 @@ public:
/* Constructor / Destructor */
BVHBuild::BVHBuild(const vector<Object*>& objects_,
- vector<int>& prim_type_, vector<int>& prim_index_, vector<int>& prim_object_,
- const BVHParams& params_, Progress& progress_)
-: objects(objects_),
- prim_type(prim_type_),
- prim_index(prim_index_),
- prim_object(prim_object_),
- params(params_),
- progress(progress_),
- progress_start_time(0.0)
+ array<int>& prim_type_,
+ array<int>& prim_index_,
+ array<int>& prim_object_,
+ const BVHParams& params_,
+ Progress& progress_)
+ : objects(objects_),
+ prim_type(prim_type_),
+ prim_index(prim_index_),
+ prim_object(prim_object_),
+ params(params_),
+ progress(progress_),
+ progress_start_time(0.0)
{
spatial_min_overlap = 0.0f;
}
@@ -120,7 +139,7 @@ void BVHBuild::add_reference_mesh(BoundBox& root, BoundBox& center, Mesh *mesh,
size_t steps = mesh->motion_steps - 1;
float4 *key_steps = curve_attr_mP->data_float4();
- for (size_t i = 0; i < steps; i++)
+ for(size_t i = 0; i < steps; i++)
curve.bounds_grow(k, key_steps + i*mesh_size, bounds);
type = PRIMITIVE_MOTION_CURVE;
@@ -215,15 +234,22 @@ BVHNode* BVHBuild::run()
return NULL;
/* init spatial splits */
- if(params.top_level) /* todo: get rid of this */
+ if(params.top_level) {
+ /* NOTE: Technically it is supported by the builder but it's not really
+ * optimized for speed yet and not really clear yet if it has measurable
+ * improvement on render time. Needs some extra investigation before
+ * enabling spatial split for top level BVH.
+ */
params.use_spatial_split = false;
+ }
spatial_min_overlap = root.bounds().safe_area() * params.spatial_split_alpha;
spatial_right_bounds.clear();
spatial_right_bounds.resize(max(root.size(), (int)BVHParams::NUM_SPATIAL_BINS) - 1);
/* init progress updates */
- progress_start_time = time_dt();
+ double build_start_time;
+ build_start_time = progress_start_time = time_dt();
progress_count = 0;
progress_total = references.size();
progress_original_total = progress_total;
@@ -251,13 +277,25 @@ BVHNode* BVHBuild::run()
if(progress.get_cancel()) {
rootnode->deleteSubtree();
rootnode = NULL;
+ VLOG(1) << "BVH build cancelled.";
}
else if(!params.use_spatial_split) {
/*rotate(rootnode, 4, 5);*/
rootnode->update_visibility();
}
+ if(rootnode != NULL) {
+ VLOG(1) << "BVH build statistics:\n"
+ << " Build time: " << time_dt() - build_start_time << "\n"
+ << " Total number of nodes: "
+ << rootnode->getSubtreeSize(BVH_STAT_NODE_COUNT) << "\n"
+ << " Number of inner nodes: "
+ << rootnode->getSubtreeSize(BVH_STAT_INNER_COUNT) << "\n"
+ << " Number of leaf nodes: "
+ << rootnode->getSubtreeSize(BVH_STAT_LEAF_COUNT) << "\n";
+ }
}
+
return rootnode;
}
@@ -308,17 +346,22 @@ bool BVHBuild::range_within_max_leaf_size(const BVHRange& range)
size_t num_triangles = 0;
size_t num_curves = 0;
+ size_t num_motion_curves = 0;
for(int i = 0; i < size; i++) {
BVHReference& ref = references[range.start() + i];
- if(ref.prim_type() & PRIMITIVE_ALL_CURVE)
+ if(ref.prim_type() & PRIMITIVE_CURVE)
num_curves++;
+ if(ref.prim_type() & PRIMITIVE_MOTION_CURVE)
+ num_motion_curves++;
else if(ref.prim_type() & PRIMITIVE_ALL_TRIANGLE)
num_triangles++;
}
- return (num_triangles < params.max_triangle_leaf_size) && (num_curves < params.max_curve_leaf_size);
+ return (num_triangles < params.max_triangle_leaf_size) &&
+ (num_curves < params.max_curve_leaf_size) &&
+ (num_motion_curves < params.max_curve_leaf_size);
}
/* multithreaded binning builder */
@@ -394,7 +437,7 @@ BVHNode* BVHBuild::build_node(const BVHRange& range, int level)
progress_total += left.size() + right.size() - range.size();
size_t total = progress_total;
- /* leaft node */
+ /* left node */
BVHNode *leftnode = build_node(left, level + 1);
/* right node (modify start for splits) */
@@ -414,18 +457,10 @@ BVHNode *BVHBuild::create_object_leaf_nodes(const BVHReference *ref, int start,
return new LeafNode(bounds, 0, 0, 0);
}
else if(num == 1) {
- if(start == prim_index.size()) {
- assert(params.use_spatial_split);
-
- prim_type.push_back(ref->prim_type());
- prim_index.push_back(ref->prim_index());
- prim_object.push_back(ref->prim_object());
- }
- else {
- prim_type[start] = ref->prim_type();
- prim_index[start] = ref->prim_index();
- prim_object[start] = ref->prim_object();
- }
+ assert(start < prim_type.size());
+ prim_type[start] = ref->prim_type();
+ prim_index[start] = ref->prim_index();
+ prim_object[start] = ref->prim_object();
uint visibility = objects[ref->prim_object()]->visibility;
return new LeafNode(ref->bounds(), visibility, start, start+1);
@@ -443,61 +478,128 @@ BVHNode *BVHBuild::create_object_leaf_nodes(const BVHReference *ref, int start,
}
}
-BVHNode* BVHBuild::create_leaf_node(const BVHRange& range)
+BVHNode *BVHBuild::create_primitive_leaf_node(const int *p_type,
+ const int *p_index,
+ const int *p_object,
+ const BoundBox& bounds,
+ uint visibility,
+ int start,
+ int num)
{
- vector<int>& p_type = prim_type;
- vector<int>& p_index = prim_index;
- vector<int>& p_object = prim_object;
- BoundBox bounds = BoundBox::empty;
- int num = 0, ob_num = 0;
- uint visibility = 0;
+ for(int i = 0; i < num; ++i) {
+ prim_type[start + i] = p_type[i];
+ prim_index[start + i] = p_index[i];
+ prim_object[start + i] = p_object[i];
+ }
+ return new LeafNode(bounds, visibility, start, start + num);
+}
+BVHNode* BVHBuild::create_leaf_node(const BVHRange& range)
+{
+ /* TODO(sergey): Consider writing own allocator which would
+ * not do heap allocation if number of elements is relatively small.
+ */
+ vector<int> p_type[PRIMITIVE_NUM_TOTAL];
+ vector<int> p_index[PRIMITIVE_NUM_TOTAL];
+ vector<int> p_object[PRIMITIVE_NUM_TOTAL];
+ uint visibility[PRIMITIVE_NUM_TOTAL] = {0};
+ /* NOTE: Keep initializtion in sync with actual number of primitives. */
+ BoundBox bounds[PRIMITIVE_NUM_TOTAL] = {BoundBox::empty,
+ BoundBox::empty,
+ BoundBox::empty,
+ BoundBox::empty};
+ int ob_num = 0;
+
+ /* Fill in per-type type/index array. */
for(int i = 0; i < range.size(); i++) {
BVHReference& ref = references[range.start() + i];
-
if(ref.prim_index() != -1) {
- if(range.start() + num == prim_index.size()) {
- assert(params.use_spatial_split);
-
- p_type.push_back(ref.prim_type());
- p_index.push_back(ref.prim_index());
- p_object.push_back(ref.prim_object());
- }
- else {
- p_type[range.start() + num] = ref.prim_type();
- p_index[range.start() + num] = ref.prim_index();
- p_object[range.start() + num] = ref.prim_object();
- }
+ int type_index = bitscan(ref.prim_type() & PRIMITIVE_ALL);
+ p_type[type_index].push_back(ref.prim_type());
+ p_index[type_index].push_back(ref.prim_index());
+ p_object[type_index].push_back(ref.prim_object());
- bounds.grow(ref.bounds());
- visibility |= objects[ref.prim_object()]->visibility;
- num++;
+ bounds[type_index].grow(ref.bounds());
+ visibility[type_index] |= objects[ref.prim_object()]->visibility;
}
else {
- if(ob_num < i)
+ if(ob_num < i) {
references[range.start() + ob_num] = ref;
+ }
ob_num++;
}
}
- BVHNode *leaf = NULL;
-
- if(num > 0) {
- leaf = new LeafNode(bounds, visibility, range.start(), range.start() + num);
+ /* Extend an array when needed. */
+ if(prim_type.size() < range.end()) {
+ assert(params.use_spatial_split);
+ prim_type.reserve(references.size());
+ prim_index.reserve(references.size());
+ prim_object.reserve(references.size());
+ prim_type.resize(range.end());
+ prim_index.resize(range.end());
+ prim_object.resize(range.end());
+ }
- if(num == range.size())
- return leaf;
+ /* Create leaf nodes for every existing primitive. */
+ BVHNode *leaves[PRIMITIVE_NUM_TOTAL + 1] = {NULL};
+ int num_leaves = 0;
+ int start = range.start();
+ for(int i = 0; i < PRIMITIVE_NUM_TOTAL; ++i) {
+ int num = (int)p_type[i].size();
+ if(num != 0) {
+ assert(p_type[i].size() == p_index[i].size());
+ assert(p_type[i].size() == p_object[i].size());
+ leaves[num_leaves] = create_primitive_leaf_node(&p_type[i][0],
+ &p_index[i][0],
+ &p_object[i][0],
+ bounds[i],
+ visibility[i],
+ start,
+ num);
+ ++num_leaves;
+ start += num;
+ }
}
- /* while there may be multiple triangles in a leaf, for object primitives
- * we want there to be the only one, so we keep splitting */
- const BVHReference *ref = (ob_num)? &references[range.start()]: NULL;
- BVHNode *oleaf = create_object_leaf_nodes(ref, range.start() + num, ob_num);
-
- if(leaf)
- return new InnerNode(range.bounds(), leaf, oleaf);
- else
- return oleaf;
+ /* Create leaf node for object. */
+ if(num_leaves == 0 || ob_num) {
+ /* Only create object leaf nodes if there are objects or no other
+ * nodes created.
+ */
+ const BVHReference *ref = (ob_num)? &references[range.start()]: NULL;
+ leaves[num_leaves] = create_object_leaf_nodes(ref, start, ob_num);
+ ++num_leaves;
+ }
+
+ if(num_leaves == 1) {
+ /* Simplest case: single leaf, just return it.
+ * In all the rest cases we'll be creating intermediate inner node with
+ * an appropriate bounding box.
+ */
+ return leaves[0];
+ }
+ else if(num_leaves == 2) {
+ return new InnerNode(range.bounds(), leaves[0], leaves[1]);
+ }
+ else if(num_leaves == 3) {
+ BoundBox inner_bounds = merge(leaves[1]->m_bounds, leaves[2]->m_bounds);
+ BVHNode *inner = new InnerNode(inner_bounds, leaves[1], leaves[2]);
+ return new InnerNode(range.bounds(), leaves[0], inner);
+ } else {
+ /* Shpuld be doing more branches if more primitive types added. */
+ assert(num_leaves <= 5);
+ BoundBox inner_bounds_a = merge(leaves[0]->m_bounds, leaves[1]->m_bounds);
+ BoundBox inner_bounds_b = merge(leaves[2]->m_bounds, leaves[3]->m_bounds);
+ BVHNode *inner_a = new InnerNode(inner_bounds_a, leaves[0], leaves[1]);
+ BVHNode *inner_b = new InnerNode(inner_bounds_b, leaves[2], leaves[3]);
+ BoundBox inner_bounds_c = merge(inner_a->m_bounds, inner_b->m_bounds);
+ BVHNode *inner_c = new InnerNode(inner_bounds_c, inner_a, inner_b);
+ if(num_leaves == 5) {
+ return new InnerNode(range.bounds(), inner_c, leaves[4]);
+ }
+ return inner_c;
+ }
}
/* Tree Rotations */
@@ -582,4 +684,3 @@ void BVHBuild::rotate(BVHNode *node, int max_depth)
}
CCL_NAMESPACE_END
-
diff --git a/intern/cycles/bvh/bvh_build.h b/intern/cycles/bvh/bvh_build.h
index a6b9916de9b..eefb7b60f7c 100644
--- a/intern/cycles/bvh/bvh_build.h
+++ b/intern/cycles/bvh/bvh_build.h
@@ -42,13 +42,12 @@ class BVHBuild
{
public:
/* Constructor/Destructor */
- BVHBuild(
- const vector<Object*>& objects,
- vector<int>& prim_type,
- vector<int>& prim_index,
- vector<int>& prim_object,
- const BVHParams& params,
- Progress& progress);
+ BVHBuild(const vector<Object*>& objects,
+ array<int>& prim_type,
+ array<int>& prim_index,
+ array<int>& prim_object,
+ const BVHParams& params,
+ Progress& progress);
~BVHBuild();
BVHNode *run();
@@ -70,6 +69,15 @@ protected:
BVHNode *create_leaf_node(const BVHRange& range);
BVHNode *create_object_leaf_nodes(const BVHReference *ref, int start, int num);
+ /* Leaf node type splitting. */
+ BVHNode *create_primitive_leaf_node(const int *p_type,
+ const int *p_index,
+ const int *p_object,
+ const BoundBox& bounds,
+ uint visibility,
+ int start,
+ int nun);
+
bool range_within_max_leaf_size(const BVHRange& range);
/* threads */
@@ -90,9 +98,9 @@ protected:
int num_original_references;
/* output primitive indexes and objects */
- vector<int>& prim_type;
- vector<int>& prim_index;
- vector<int>& prim_object;
+ array<int>& prim_type;
+ array<int>& prim_index;
+ array<int>& prim_object;
/* build parameters */
BVHParams params;
@@ -116,4 +124,3 @@ protected:
CCL_NAMESPACE_END
#endif /* __BVH_BUILD_H__ */
-
diff --git a/intern/cycles/bvh/bvh_node.cpp b/intern/cycles/bvh/bvh_node.cpp
index 7cc9bd333b0..8294690da7d 100644
--- a/intern/cycles/bvh/bvh_node.cpp
+++ b/intern/cycles/bvh/bvh_node.cpp
@@ -47,6 +47,20 @@ int BVHNode::getSubtreeSize(BVH_STAT stat) const
case BVH_STAT_CHILDNODE_COUNT:
cnt = num_children();
break;
+ case BVH_STAT_QNODE_COUNT:
+ cnt = 1;
+ for(int i = 0; i < num_children(); i++) {
+ BVHNode *node = get_child(i);
+ if(node->is_leaf()) {
+ cnt += 1;
+ }
+ else {
+ for(int j = 0; j < node->num_children(); j++) {
+ cnt += node->get_child(j)->getSubtreeSize(stat);
+ }
+ }
+ }
+ return cnt;
default:
assert(0); /* unknown mode */
}
diff --git a/intern/cycles/bvh/bvh_node.h b/intern/cycles/bvh/bvh_node.h
index a0d10a46bfc..44f5518229b 100644
--- a/intern/cycles/bvh/bvh_node.h
+++ b/intern/cycles/bvh/bvh_node.h
@@ -24,13 +24,13 @@
CCL_NAMESPACE_BEGIN
-enum BVH_STAT
-{
+enum BVH_STAT {
BVH_STAT_NODE_COUNT,
BVH_STAT_INNER_COUNT,
BVH_STAT_LEAF_COUNT,
BVH_STAT_TRIANGLE_COUNT,
- BVH_STAT_CHILDNODE_COUNT
+ BVH_STAT_CHILDNODE_COUNT,
+ BVH_STAT_QNODE_COUNT,
};
class BVHParams;
diff --git a/intern/cycles/bvh/bvh_params.h b/intern/cycles/bvh/bvh_params.h
index e073b69472e..faa995c3f29 100644
--- a/intern/cycles/bvh/bvh_params.h
+++ b/intern/cycles/bvh/bvh_params.h
@@ -28,7 +28,7 @@ class BVHParams
{
public:
/* spatial split area threshold */
- int use_spatial_split;
+ bool use_spatial_split;
float spatial_split_alpha;
/* SAH costs */
@@ -41,15 +41,10 @@ public:
int max_curve_leaf_size;
/* object or mesh level bvh */
- int top_level;
-
- /* disk cache */
- int use_cache;
+ bool top_level;
/* QBVH */
- int use_qbvh;
-
- int pad;
+ bool use_qbvh;
/* fixed parameters */
enum {
@@ -73,9 +68,7 @@ public:
max_curve_leaf_size = 2;
top_level = false;
- use_cache = false;
use_qbvh = false;
- pad = false;
}
/* SAH costs */
@@ -115,6 +108,13 @@ public:
__forceinline int prim_object() const { return __float_as_int(rbounds.max.w); }
__forceinline int prim_type() const { return type; }
+ BVHReference& operator=(const BVHReference &arg) {
+ if(&arg != this) {
+ memcpy(this, &arg, sizeof(BVHReference));
+ }
+ return *this;
+ }
+
protected:
BoundBox rbounds;
uint type;
diff --git a/intern/cycles/bvh/bvh_split.cpp b/intern/cycles/bvh/bvh_split.cpp
index 07c35c08c18..534c1aa73b5 100644
--- a/intern/cycles/bvh/bvh_split.cpp
+++ b/intern/cycles/bvh/bvh_split.cpp
@@ -191,11 +191,16 @@ void BVHSpatialSplit::split(BVHBuild *builder, BVHRange& left, BVHRange& right,
}
}
- /* duplicate or unsplit references intersecting both sides. */
+ /* Duplicate or unsplit references intersecting both sides.
+ *
+ * Duplication happens into a temporary pre-allocated vector in order to
+ * reduce number of memmove() calls happening in vector.insert().
+ */
+ vector<BVHReference> new_refs;
+ new_refs.reserve(right_start - left_end);
while(left_end < right_start) {
/* split reference. */
BVHReference lref, rref;
-
split_reference(builder, lref, rref, refs[left_end], this->dim, this->pos);
/* compute SAH for duplicate/unsplit candidates. */
@@ -234,61 +239,36 @@ void BVHSpatialSplit::split(BVHBuild *builder, BVHRange& left, BVHRange& right,
left_bounds = ldb;
right_bounds = rdb;
refs[left_end++] = lref;
- refs.insert(refs.begin() + right_end, rref);
+ new_refs.push_back(rref);
right_end++;
}
}
-
+ /* Insert duplicated references into actual array in one go. */
+ if(new_refs.size() != 0) {
+ refs.insert(refs.begin() + right_end - new_refs.size(),
+ new_refs.begin(),
+ new_refs.end());
+ }
left = BVHRange(left_bounds, left_start, left_end - left_start);
right = BVHRange(right_bounds, right_start, right_end - right_start);
}
-void BVHSpatialSplit::split_reference(BVHBuild *builder, BVHReference& left, BVHReference& right, const BVHReference& ref, int dim, float pos)
+void BVHSpatialSplit::split_triangle_primitive(const Mesh *mesh,
+ const Transform *tfm,
+ int prim_index,
+ int dim,
+ float pos,
+ BoundBox& left_bounds,
+ BoundBox& right_bounds)
{
- /* initialize boundboxes */
- BoundBox left_bounds = BoundBox::empty;
- BoundBox right_bounds = BoundBox::empty;
-
- /* loop over vertices/edges. */
- Object *ob = builder->objects[ref.prim_object()];
- const Mesh *mesh = ob->mesh;
-
- if (ref.prim_type() & PRIMITIVE_ALL_TRIANGLE) {
- const int *inds = mesh->triangles[ref.prim_index()].v;
- const float3 *verts = &mesh->verts[0];
- const float3* v1 = &verts[inds[2]];
-
- for(int i = 0; i < 3; i++) {
- const float3* v0 = v1;
- int vindex = inds[i];
- v1 = &verts[vindex];
- float v0p = (*v0)[dim];
- float v1p = (*v1)[dim];
-
- /* insert vertex to the boxes it belongs to. */
- if(v0p <= pos)
- left_bounds.grow(*v0);
-
- if(v0p >= pos)
- right_bounds.grow(*v0);
-
- /* edge intersects the plane => insert intersection to both boxes. */
- if((v0p < pos && v1p > pos) || (v0p > pos && v1p < pos)) {
- float3 t = lerp(*v0, *v1, clamp((pos - v0p) / (v1p - v0p), 0.0f, 1.0f));
- left_bounds.grow(t);
- right_bounds.grow(t);
- }
- }
- }
- else {
- /* curve split: NOTE - Currently ignores curve width and needs to be fixed.*/
- const int k0 = mesh->curves[ref.prim_index()].first_key + PRIMITIVE_UNPACK_SEGMENT(ref.prim_type());
- const int k1 = k0 + 1;
- const float4 key0 = mesh->curve_keys[k0];
- const float4 key1 = mesh->curve_keys[k1];
- const float3 v0 = float4_to_float3(key0);
- const float3 v1 = float4_to_float3(key1);
-
+ const int *inds = mesh->triangles[prim_index].v;
+ const float3 *verts = &mesh->verts[0];
+ float3 v1 = tfm ? transform_point(tfm, verts[inds[2]]) : verts[inds[2]];
+
+ for(int i = 0; i < 3; i++) {
+ float3 v0 = v1;
+ int vindex = inds[i];
+ v1 = tfm ? transform_point(tfm, verts[vindex]) : verts[vindex];
float v0p = v0[dim];
float v1p = v1[dim];
@@ -299,12 +279,6 @@ void BVHSpatialSplit::split_reference(BVHBuild *builder, BVHReference& left, BVH
if(v0p >= pos)
right_bounds.grow(v0);
- if(v1p <= pos)
- left_bounds.grow(v1);
-
- if(v1p >= pos)
- right_bounds.grow(v1);
-
/* edge intersects the plane => insert intersection to both boxes. */
if((v0p < pos && v1p > pos) || (v0p > pos && v1p < pos)) {
float3 t = lerp(v0, v1, clamp((pos - v0p) / (v1p - v0p), 0.0f, 1.0f));
@@ -312,6 +286,159 @@ void BVHSpatialSplit::split_reference(BVHBuild *builder, BVHReference& left, BVH
right_bounds.grow(t);
}
}
+}
+
+void BVHSpatialSplit::split_curve_primitive(const Mesh *mesh,
+ const Transform *tfm,
+ int prim_index,
+ int segment_index,
+ int dim,
+ float pos,
+ BoundBox& left_bounds,
+ BoundBox& right_bounds)
+{
+ /* curve split: NOTE - Currently ignores curve width and needs to be fixed.*/
+ const int k0 = mesh->curves[prim_index].first_key + segment_index;
+ const int k1 = k0 + 1;
+ const float4& key0 = mesh->curve_keys[k0];
+ const float4& key1 = mesh->curve_keys[k1];
+ float3 v0 = float4_to_float3(key0);
+ float3 v1 = float4_to_float3(key1);
+
+ if(tfm != NULL) {
+ v0 = transform_point(tfm, v0);
+ v1 = transform_point(tfm, v1);
+ }
+
+ float v0p = v0[dim];
+ float v1p = v1[dim];
+
+ /* insert vertex to the boxes it belongs to. */
+ if(v0p <= pos)
+ left_bounds.grow(v0);
+
+ if(v0p >= pos)
+ right_bounds.grow(v0);
+
+ if(v1p <= pos)
+ left_bounds.grow(v1);
+
+ if(v1p >= pos)
+ right_bounds.grow(v1);
+
+ /* edge intersects the plane => insert intersection to both boxes. */
+ if((v0p < pos && v1p > pos) || (v0p > pos && v1p < pos)) {
+ float3 t = lerp(v0, v1, clamp((pos - v0p) / (v1p - v0p), 0.0f, 1.0f));
+ left_bounds.grow(t);
+ right_bounds.grow(t);
+ }
+}
+
+void BVHSpatialSplit::split_triangle_reference(const BVHReference& ref,
+ const Mesh *mesh,
+ int dim,
+ float pos,
+ BoundBox& left_bounds,
+ BoundBox& right_bounds)
+{
+ split_triangle_primitive(mesh,
+ NULL,
+ ref.prim_index(),
+ dim,
+ pos,
+ left_bounds,
+ right_bounds);
+}
+
+void BVHSpatialSplit::split_curve_reference(const BVHReference& ref,
+ const Mesh *mesh,
+ int dim,
+ float pos,
+ BoundBox& left_bounds,
+ BoundBox& right_bounds)
+{
+ split_curve_primitive(mesh,
+ NULL,
+ ref.prim_index(),
+ PRIMITIVE_UNPACK_SEGMENT(ref.prim_type()),
+ dim,
+ pos,
+ left_bounds,
+ right_bounds);
+}
+
+void BVHSpatialSplit::split_object_reference(const Object *object,
+ int dim,
+ float pos,
+ BoundBox& left_bounds,
+ BoundBox& right_bounds)
+{
+ Mesh *mesh = object->mesh;
+ for(int tri_idx = 0; tri_idx < mesh->triangles.size(); ++tri_idx) {
+ split_triangle_primitive(mesh,
+ &object->tfm,
+ tri_idx,
+ dim,
+ pos,
+ left_bounds,
+ right_bounds);
+ }
+ for(int curve_idx = 0; curve_idx < mesh->curves.size(); ++curve_idx) {
+ Mesh::Curve &curve = mesh->curves[curve_idx];
+ for(int segment_idx = 0;
+ segment_idx < curve.num_keys - 1;
+ ++segment_idx)
+ {
+ split_curve_primitive(mesh,
+ &object->tfm,
+ curve_idx,
+ segment_idx,
+ dim,
+ pos,
+ left_bounds,
+ right_bounds);
+ }
+ }
+}
+
+void BVHSpatialSplit::split_reference(BVHBuild *builder,
+ BVHReference& left,
+ BVHReference& right,
+ const BVHReference& ref,
+ int dim,
+ float pos)
+{
+ /* initialize boundboxes */
+ BoundBox left_bounds = BoundBox::empty;
+ BoundBox right_bounds = BoundBox::empty;
+
+ /* loop over vertices/edges. */
+ Object *ob = builder->objects[ref.prim_object()];
+ const Mesh *mesh = ob->mesh;
+
+ if(ref.prim_type() & PRIMITIVE_ALL_TRIANGLE) {
+ split_triangle_reference(ref,
+ mesh,
+ dim,
+ pos,
+ left_bounds,
+ right_bounds);
+ }
+ else if(ref.prim_type() & PRIMITIVE_ALL_CURVE) {
+ split_curve_reference(ref,
+ mesh,
+ dim,
+ pos,
+ left_bounds,
+ right_bounds);
+ }
+ else {
+ split_object_reference(ob,
+ dim,
+ pos,
+ left_bounds,
+ right_bounds);
+ }
/* intersect with original bounds. */
left_bounds.max[dim] = pos;
diff --git a/intern/cycles/bvh/bvh_split.h b/intern/cycles/bvh/bvh_split.h
index 5b739311e5f..1e46bb66203 100644
--- a/intern/cycles/bvh/bvh_split.h
+++ b/intern/cycles/bvh/bvh_split.h
@@ -55,7 +55,58 @@ public:
BVHSpatialSplit(BVHBuild *builder, const BVHRange& range, float nodeSAH);
void split(BVHBuild *builder, BVHRange& left, BVHRange& right, const BVHRange& range);
- void split_reference(BVHBuild *builder, BVHReference& left, BVHReference& right, const BVHReference& ref, int dim, float pos);
+ void split_reference(BVHBuild *builder,
+ BVHReference& left,
+ BVHReference& right,
+ const BVHReference& ref,
+ int dim,
+ float pos);
+
+protected:
+ /* Lower-level functions which calculates boundaries of left and right nodes
+ * needed for spatial split.
+ *
+ * Operates directly with primitive specified by it's index, reused by higher
+ * level splitting functions.
+ */
+ void split_triangle_primitive(const Mesh *mesh,
+ const Transform *tfm,
+ int prim_index,
+ int dim,
+ float pos,
+ BoundBox& left_bounds,
+ BoundBox& right_bounds);
+ void split_curve_primitive(const Mesh *mesh,
+ const Transform *tfm,
+ int prim_index,
+ int segment_index,
+ int dim,
+ float pos,
+ BoundBox& left_bounds,
+ BoundBox& right_bounds);
+
+ /* Lower-level functions which calculates boundaries of left and right nodes
+ * needed for spatial split.
+ *
+ * Operates with BVHReference, internally uses lower level API functions.
+ */
+ void split_triangle_reference(const BVHReference& ref,
+ const Mesh *mesh,
+ int dim,
+ float pos,
+ BoundBox& left_bounds,
+ BoundBox& right_bounds);
+ void split_curve_reference(const BVHReference& ref,
+ const Mesh *mesh,
+ int dim,
+ float pos,
+ BoundBox& left_bounds,
+ BoundBox& right_bounds);
+ void split_object_reference(const Object *object,
+ int dim,
+ float pos,
+ BoundBox& left_bounds,
+ BoundBox& right_bounds);
};
/* Mixed Object-Spatial Split */
diff --git a/intern/cycles/cmake/external_libs.cmake b/intern/cycles/cmake/external_libs.cmake
index bb174d6df26..10a166b6e44 100644
--- a/intern/cycles/cmake/external_libs.cmake
+++ b/intern/cycles/cmake/external_libs.cmake
@@ -1,3 +1,11 @@
+###########################################################################
+# Precompiled libraries tips and hints, for find_package().
+
+if(CYCLES_STANDALONE_REPOSITORY)
+ if(APPLE OR WIN32)
+ include(precompiled_libs)
+ endif()
+endif()
###########################################################################
# GLUT
@@ -14,10 +22,16 @@ if(WITH_CYCLES_STANDALONE AND WITH_CYCLES_STANDALONE_GUI)
)
endif()
-if(WITH_SYSTEM_GLEW)
- set(CYCLES_GLEW_LIBRARY ${GLEW_LIBRARY})
-else()
- set(CYCLES_GLEW_LIBRARY extern_glew)
+###########################################################################
+# GLEW
+
+# Workaround for unconventional variable name use in Blender.
+if(NOT CYCLES_STANDALONE_REPOSITORY)
+ set(GLEW_INCLUDE_DIR "${GLEW_INCLUDE_PATH}")
+endif()
+
+if(WITH_CYCLES_STANDALONE AND WITH_CYCLES_STANDALONE_GUI)
+ set(CYCLES_APP_GLEW_LIBRARY ${BLENDER_GLEW_LIBRARIES})
endif()
###########################################################################
@@ -33,3 +47,97 @@ if(WITH_CYCLES_CUDA_BINARIES)
endif()
endif()
+# Packages which are being found by Blender when building from inside Blender
+# source code. but which we need to take care of when building Cycles from a
+# standalone repository
+if(CYCLES_STANDALONE_REPOSITORY)
+ # PThreads
+ # TODO(sergey): Bloody exception, handled in precompiled_libs.cmake.
+ if(NOT WIN32)
+ set(CMAKE_THREAD_PREFER_PTHREAD TRUE)
+ find_package(Threads REQUIRED)
+ set(PTHREADS_LIBRARIES ${CMAKE_THREAD_LIBS_INIT})
+ endif()
+
+ ####
+ # OpenGL
+
+ # TODO(sergey): We currently re-use the same variable name as we use
+ # in Blender. Ideally we need to make it CYCLES_GL_LIBRARIES.
+ find_package(OpenGL REQUIRED)
+ find_package(GLEW REQUIRED)
+ list(APPEND BLENDER_GL_LIBRARIES
+ "${OPENGL_gl_LIBRARY}"
+ "${OPENGL_glu_LIBRARY}"
+ "${GLEW_LIBRARY}"
+ )
+
+ ####
+ # OpenImageIO
+ find_package(OpenImageIO REQUIRED)
+ if(OPENIMAGEIO_PUGIXML_FOUND)
+ set(PUGIXML_INCLUDE_DIR "${OPENIMAGEIO_INCLUDE_DIR/OpenImageIO}")
+ set(PUGIXML_LIBRARIES "")
+ else()
+ find_package(PugiXML REQUIRED)
+ endif()
+
+ # OIIO usually depends on OpenEXR, so find this library
+ # but don't make it required.
+ find_package(OpenEXR)
+
+ ####
+ # OpenShadingLanguage
+ if(WITH_CYCLES_OSL)
+ find_package(OpenShadingLanguage REQUIRED)
+ find_package(LLVM REQUIRED)
+ endif()
+
+ ####
+ # Boost
+ set(__boost_packages filesystem regex system thread date_time)
+ if(WITH_CYCLES_NETWORK)
+ list(APPEND __boost_packages serialization)
+ endif()
+ if(WITH_CYCLES_OSL)
+ # TODO(sergey): This is because of the way how our precompiled
+ # libraries works, could be different for someone's else libs..
+ if(APPLE OR MSVC)
+ list(APPEND __boost_packages wave)
+ elseif(NOT (${OSL_LIBRARY_VERSION_MAJOR} EQUAL "1" AND ${OSL_LIBRARY_VERSION_MINOR} LESS "6"))
+ list(APPEND __boost_packages wave)
+ endif()
+ endif()
+ find_package(Boost 1.48 COMPONENTS ${__boost_packages} REQUIRED)
+ if(NOT Boost_FOUND)
+ # Try to find non-multithreaded if -mt not found, this flag
+ # doesn't matter for us, it has nothing to do with thread
+ # safety, but keep it to not disturb build setups.
+ set(Boost_USE_MULTITHREADED OFF)
+ find_package(Boost 1.48 COMPONENTS ${__boost_packages})
+ endif()
+ unset(__boost_packages)
+ set(BOOST_INCLUDE_DIR ${Boost_INCLUDE_DIRS})
+ set(BOOST_LIBRARIES ${Boost_LIBRARIES})
+ set(BOOST_LIBPATH ${Boost_LIBRARY_DIRS})
+ set(BOOST_DEFINITIONS "-DBOOST_ALL_NO_LIB")
+
+ ####
+ # Logging
+ if(WITH_CYCLES_LOGGING)
+ find_package(Glog REQUIRED)
+ find_package(Gflags REQUIRED)
+ endif()
+
+ unset(_lib_DIR)
+else()
+ if(WIN32)
+ set(GLOG_INCLUDE_DIRS ${CMAKE_SOURCE_DIR}/extern/libmv/third_party/glog/src/windows)
+ set(GFLAGS_INCLUDE_DIRS ${CMAKE_SOURCE_DIR}/extern/libmv/third_party/gflags)
+ else()
+ set(GLOG_INCLUDE_DIRS ${CMAKE_SOURCE_DIR}/extern/libmv/third_party/glog/src)
+ set(GFLAGS_INCLUDE_DIRS ${CMAKE_SOURCE_DIR}/extern/libmv/third_party/gflags)
+ endif()
+ set(GFLAGS_NAMESPACE "gflags")
+ set(LLVM_LIBRARIES ${LLVM_LIBRARY})
+endif()
diff --git a/intern/cycles/device/CMakeLists.txt b/intern/cycles/device/CMakeLists.txt
index a62ce29f722..b0fa283c1d8 100644
--- a/intern/cycles/device/CMakeLists.txt
+++ b/intern/cycles/device/CMakeLists.txt
@@ -6,11 +6,11 @@ set(INC
../kernel/osl
../util
../render
+ ../../glew-mx
)
set(INC_SYS
- ${OPENGL_INCLUDE_DIR}
- ${GLEW_INCLUDE_PATH}
+ ${GLEW_INCLUDE_DIR}
../../../extern/cuew/include
../../../extern/clew/include
)
@@ -38,7 +38,7 @@ set(SRC_HEADERS
device_task.h
)
-add_definitions(-DGLEW_STATIC)
+add_definitions(${GL_DEFINITIONS})
include_directories(${INC})
include_directories(SYSTEM ${INC_SYS})
diff --git a/intern/cycles/device/device.cpp b/intern/cycles/device/device.cpp
index efdfa98cfb5..fc9959e0b48 100644
--- a/intern/cycles/device/device.cpp
+++ b/intern/cycles/device/device.cpp
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#include <stdlib.h>
@@ -20,9 +20,6 @@
#include "device.h"
#include "device_intern.h"
-#include "cuew.h"
-#include "clew.h"
-
#include "util_debug.h"
#include "util_foreach.h"
#include "util_half.h"
@@ -34,8 +31,38 @@
CCL_NAMESPACE_BEGIN
+/* Device Requested Features */
+
+std::ostream& operator <<(std::ostream &os,
+ const DeviceRequestedFeatures& requested_features)
+{
+ os << "Experimental features: "
+ << (requested_features.experimental ? "On" : "Off") << std::endl;
+ os << "Max closure count: " << requested_features.max_closure << std::endl;
+ os << "Max nodes group: " << requested_features.max_nodes_group << std::endl;
+ /* TODO(sergey): Decode bitflag into list of names. */
+ os << "Nodes features: " << requested_features.nodes_features << std::endl;
+ /* TODO(sergey): Make it utility function to convert bool to string. */
+ os << "Use hair: "
+ << (requested_features.use_hair ? "True" : "False") << std::endl;
+ os << "Use object motion: "
+ << (requested_features.use_object_motion ? "True" : "False") << std::endl;
+ os << "Use camera motion: "
+ << (requested_features.use_camera_motion ? "True" : "False") << std::endl;
+ os << "Use Baking: "
+ << (requested_features.use_baking ? "True" : "False") << std::endl;
+ return os;
+}
+
/* Device */
+Device::~Device()
+{
+ if(!background && vertex_buffer != 0) {
+ glDeleteBuffers(1, &vertex_buffer);
+ }
+}
+
void Device::pixels_alloc(device_memory& mem)
{
mem_alloc(mem, MEM_READ_WRITE);
@@ -54,7 +81,7 @@ void Device::pixels_free(device_memory& mem)
mem_free(mem);
}
-void Device::draw_pixels(device_memory& rgba, int y, int w, int h, int dy, int width, int height, bool transparent,
+void Device::draw_pixels(device_memory& rgba, int y, int w, int h, int dx, int dy, int width, int height, bool transparent,
const DeviceDrawParams &draw_params)
{
pixels_copy_from(rgba, y, w, h);
@@ -70,6 +97,9 @@ void Device::draw_pixels(device_memory& rgba, int y, int w, int h, int dy, int w
/* for multi devices, this assumes the inefficient method that we allocate
* all pixels on the device even though we only render to a subset */
GLhalf *data_pointer = (GLhalf*)rgba.data_pointer;
+ float vbuffer[16], *basep;
+ float *vp = NULL;
+
data_pointer += 4*y*w;
/* draw half float texture, GLSL shader for display transform assumed to be bound */
@@ -86,23 +116,63 @@ void Device::draw_pixels(device_memory& rgba, int y, int w, int h, int dy, int w
draw_params.bind_display_space_shader_cb();
}
- glPushMatrix();
- glTranslatef(0.0f, (float)dy, 0.0f);
+ if(GLEW_VERSION_1_5) {
+ if(!vertex_buffer)
+ glGenBuffers(1, &vertex_buffer);
+
+ glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer);
+ /* invalidate old contents - avoids stalling if buffer is still waiting in queue to be rendered */
+ glBufferData(GL_ARRAY_BUFFER, 16 * sizeof(float), NULL, GL_STREAM_DRAW);
+
+ vp = (float *)glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY);
+
+ basep = NULL;
+ }
+ else {
+ basep = vbuffer;
+ vp = vbuffer;
+ }
+
+ if(vp) {
+ /* texture coordinate - vertex pair */
+ vp[0] = 0.0f;
+ vp[1] = 0.0f;
+ vp[2] = dx;
+ vp[3] = dy;
+
+ vp[4] = 1.0f;
+ vp[5] = 0.0f;
+ vp[6] = (float)width + dx;
+ vp[7] = dy;
+
+ vp[8] = 1.0f;
+ vp[9] = 1.0f;
+ vp[10] = (float)width + dx;
+ vp[11] = (float)height + dy;
+
+ vp[12] = 0.0f;
+ vp[13] = 1.0f;
+ vp[14] = dx;
+ vp[15] = (float)height + dy;
+
+ if(vertex_buffer)
+ glUnmapBuffer(GL_ARRAY_BUFFER);
+ }
+
+ glTexCoordPointer(2, GL_FLOAT, 4 * sizeof(float), basep);
+ glVertexPointer(2, GL_FLOAT, 4 * sizeof(float), ((char *)basep) + 2 * sizeof(float));
- glBegin(GL_QUADS);
-
- glTexCoord2f(0.0f, 0.0f);
- glVertex2f(0.0f, 0.0f);
- glTexCoord2f(1.0f, 0.0f);
- glVertex2f((float)width, 0.0f);
- glTexCoord2f(1.0f, 1.0f);
- glVertex2f((float)width, (float)height);
- glTexCoord2f(0.0f, 1.0f);
- glVertex2f(0.0f, (float)height);
+ glEnableClientState(GL_VERTEX_ARRAY);
+ glEnableClientState(GL_TEXTURE_COORD_ARRAY);
- glEnd();
+ glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
- glPopMatrix();
+ glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+ glDisableClientState(GL_VERTEX_ARRAY);
+
+ if(vertex_buffer) {
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
+ }
if(draw_params.unbind_display_space_shader_cb) {
draw_params.unbind_display_space_shader_cb();
@@ -116,7 +186,7 @@ void Device::draw_pixels(device_memory& rgba, int y, int w, int h, int dy, int w
/* fallback for old graphics cards that don't support GLSL, half float,
* and non-power-of-two textures */
glPixelZoom((float)width/(float)w, (float)height/(float)h);
- glRasterPos2f(0, dy);
+ glRasterPos2f(dx, dy);
uint8_t *pixels = (uint8_t*)rgba.data_pointer;
@@ -268,5 +338,25 @@ vector<DeviceInfo>& Device::available_devices()
return devices;
}
-CCL_NAMESPACE_END
+string Device::device_capabilities()
+{
+ string capabilities = "CPU device capabilities: ";
+ capabilities += device_cpu_capabilities() + "\n";
+#ifdef WITH_CUDA
+ if(device_cuda_init()) {
+ capabilities += "\nCUDA device capabilities:\n";
+ capabilities += device_cuda_capabilities();
+ }
+#endif
+
+#ifdef WITH_OPENCL
+ if(device_opencl_init()) {
+ capabilities += "\nOpenCL device capabilities:\n";
+ capabilities += device_opencl_capabilities();
+ }
+#endif
+
+ return capabilities;
+}
+CCL_NAMESPACE_END
diff --git a/intern/cycles/device/device.h b/intern/cycles/device/device.h
index 20ebfd391d6..3c0fb880948 100644
--- a/intern/cycles/device/device.h
+++ b/intern/cycles/device/device.h
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#ifndef __DEVICE_H__
@@ -55,6 +55,7 @@ public:
bool advanced_shading;
bool pack_images;
bool extended_images; /* flag for GPU and Multi device */
+ bool use_split_kernel; /* Denotes if the device is going to run cycles using split-kernel */
vector<DeviceInfo> multi_devices;
DeviceInfo()
@@ -66,25 +67,88 @@ public:
advanced_shading = true;
pack_images = false;
extended_images = false;
+ use_split_kernel = false;
}
};
+class DeviceRequestedFeatures {
+public:
+ /* Use experimental feature set. */
+ bool experimental;
+
+ /* Maximum number of closures in shader trees. */
+ int max_closure;
+
+ /* Selective nodes compilation. */
+
+ /* Identifier of a node group up to which all the nodes needs to be
+ * compiled in. Nodes from higher group indices will be ignores.
+ */
+ int max_nodes_group;
+
+ /* Features bitfield indicating which features from the requested group
+ * will be compiled in. Nodes which corresponds to features which are not
+ * in this bitfield will be ignored even if they're in the requested group.
+ */
+ int nodes_features;
+
+ /* BVH/sampling kernel features. */
+ bool use_hair;
+ bool use_object_motion;
+ bool use_camera_motion;
+
+ /* Denotes whether baking functionality is needed. */
+ bool use_baking;
+
+ DeviceRequestedFeatures()
+ {
+ /* TODO(sergey): Find more meaningful defaults. */
+ experimental = false;
+ max_closure = 0;
+ max_nodes_group = 0;
+ nodes_features = 0;
+ use_hair = false;
+ use_object_motion = false;
+ use_camera_motion = false;
+ use_baking = false;
+ }
+
+ bool modified(const DeviceRequestedFeatures& requested_features)
+ {
+ return !(experimental == requested_features.experimental &&
+ max_closure == requested_features.max_closure &&
+ max_nodes_group == requested_features.max_nodes_group &&
+ nodes_features == requested_features.nodes_features &&
+ use_hair == requested_features.use_hair &&
+ use_object_motion == requested_features.use_object_motion &&
+ use_camera_motion == requested_features.use_camera_motion &&
+ use_baking == requested_features.use_baking);
+ }
+
+};
+
+std::ostream& operator <<(std::ostream &os,
+ const DeviceRequestedFeatures& requested_features);
+
/* Device */
struct DeviceDrawParams {
- boost::function<void(void)> bind_display_space_shader_cb;
- boost::function<void(void)> unbind_display_space_shader_cb;
+ function<void(void)> bind_display_space_shader_cb;
+ function<void(void)> unbind_display_space_shader_cb;
};
class Device {
protected:
- Device(DeviceInfo& info_, Stats &stats_, bool background) : background(background), info(info_), stats(stats_) {}
+ Device(DeviceInfo& info_, Stats &stats_, bool background) : background(background), vertex_buffer(0), info(info_), stats(stats_) {}
bool background;
string error_msg;
+ /* used for real time display */
+ unsigned int vertex_buffer;
+
public:
- virtual ~Device() {}
+ virtual ~Device();
/* info */
DeviceInfo info;
@@ -106,9 +170,15 @@ public:
virtual void const_copy_to(const char *name, void *host, size_t size) = 0;
/* texture memory */
- virtual void tex_alloc(const char *name, device_memory& mem,
- InterpolationType interpolation = INTERPOLATION_NONE, bool periodic = false) {};
- virtual void tex_free(device_memory& mem) {};
+ virtual void tex_alloc(const char * /*name*/,
+ device_memory& /*mem*/,
+ InterpolationType interpolation = INTERPOLATION_NONE,
+ ExtensionType extension = EXTENSION_REPEAT)
+ {
+ (void)interpolation; /* Ignored. */
+ (void)extension; /* Ignored. */
+ };
+ virtual void tex_free(device_memory& /*mem*/) {};
/* pixel memory */
virtual void pixels_alloc(device_memory& mem);
@@ -119,7 +189,9 @@ public:
virtual void *osl_memory() { return NULL; }
/* load/compile kernels, must be called before adding tasks */
- virtual bool load_kernels(bool experimental) { return true; }
+ virtual bool load_kernels(
+ const DeviceRequestedFeatures& /*requested_features*/)
+ { return true; }
/* tasks */
virtual int get_split_task_count(DeviceTask& task) = 0;
@@ -129,7 +201,7 @@ public:
/* opengl drawing */
virtual void draw_pixels(device_memory& mem, int y, int w, int h,
- int dy, int width, int height, bool transparent,
+ int dx, int dy, int width, int height, bool transparent,
const DeviceDrawParams &draw_params);
#ifdef WITH_NETWORK
@@ -138,8 +210,8 @@ public:
#endif
/* multi device */
- virtual void map_tile(Device *sub_device, RenderTile& tile) {}
- virtual int device_number(Device *sub_device) { return 0; }
+ virtual void map_tile(Device * /*sub_device*/, RenderTile& /*tile*/) {}
+ virtual int device_number(Device * /*sub_device*/) { return 0; }
/* static */
static Device *create(DeviceInfo& info, Stats &stats, bool background = true);
@@ -148,6 +220,7 @@ public:
static string string_from_type(DeviceType type);
static vector<DeviceType>& available_types();
static vector<DeviceInfo>& available_devices();
+ static string device_capabilities();
};
CCL_NAMESPACE_END
diff --git a/intern/cycles/device/device_cpu.cpp b/intern/cycles/device/device_cpu.cpp
index 4623764d210..f06963c146e 100644
--- a/intern/cycles/device/device_cpu.cpp
+++ b/intern/cycles/device/device_cpu.cpp
@@ -11,12 +11,26 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#include <stdlib.h>
#include <string.h>
+/* So ImathMath is included before our kernel_cpu_compat. */
+#ifdef WITH_OSL
+# if defined(_MSC_VER)
+/* Prevent OSL from polluting the context with weird macros from windows.h.
+ * TODO(sergey): Ideally it's only enough to have class/struct declarations in
+ * the header and skip header include here.
+ */
+# define NOGDI
+# define NOMINMAX
+# define WIN32_LEAN_AND_MEAN
+# endif
+# include <OSL/oslexec.h>
+#endif
+
#include "device.h"
#include "device_intern.h"
@@ -33,6 +47,7 @@
#include "util_debug.h"
#include "util_foreach.h"
#include "util_function.h"
+#include "util_logging.h"
#include "util_opengl.h"
#include "util_progress.h"
#include "util_system.h"
@@ -70,19 +85,21 @@ public:
task_pool.stop();
}
- void mem_alloc(device_memory& mem, MemoryType type)
+ void mem_alloc(device_memory& mem, MemoryType /*type*/)
{
mem.device_pointer = mem.data_pointer;
mem.device_size = mem.memory_size();
stats.mem_alloc(mem.device_size);
}
- void mem_copy_to(device_memory& mem)
+ void mem_copy_to(device_memory& /*mem*/)
{
/* no-op */
}
- void mem_copy_from(device_memory& mem, int y, int w, int h, int elem)
+ void mem_copy_from(device_memory& /*mem*/,
+ int /*y*/, int /*w*/, int /*h*/,
+ int /*elem*/)
{
/* no-op */
}
@@ -106,9 +123,20 @@ public:
kernel_const_copy(&kernel_globals, name, host, size);
}
- void tex_alloc(const char *name, device_memory& mem, InterpolationType interpolation, bool periodic)
+ void tex_alloc(const char *name,
+ device_memory& mem,
+ InterpolationType interpolation,
+ ExtensionType extension)
{
- kernel_tex_copy(&kernel_globals, name, mem.data_pointer, mem.data_width, mem.data_height, mem.data_depth, interpolation);
+ VLOG(1) << "Texture allocate: " << name << ", " << mem.memory_size() << " bytes.";
+ kernel_tex_copy(&kernel_globals,
+ name,
+ mem.data_pointer,
+ mem.data_width,
+ mem.data_height,
+ mem.data_depth,
+ interpolation,
+ extension);
mem.device_pointer = mem.data_pointer;
mem.device_size = mem.memory_size();
stats.mem_alloc(mem.device_size);
@@ -165,141 +193,58 @@ public:
#endif
RenderTile tile;
-
- while(task.acquire_tile(this, tile)) {
- float *render_buffer = (float*)tile.buffer;
- uint *rng_state = (uint*)tile.rng_state;
- int start_sample = tile.start_sample;
- int end_sample = tile.start_sample + tile.num_samples;
-
-#ifdef WITH_CYCLES_OPTIMIZED_KERNEL_AVX2
- if(system_cpu_support_avx2()) {
- 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_avx2_path_trace(&kg, render_buffer, rng_state,
- sample, x, y, tile.offset, tile.stride);
- }
- }
- tile.sample = sample + 1;
+ void(*path_trace_kernel)(KernelGlobals*, float*, unsigned int*, int, int, int, int, int);
- task.update_progress(&tile);
- }
- }
- else
+#ifdef WITH_CYCLES_OPTIMIZED_KERNEL_AVX2
+ if(system_cpu_support_avx2())
+ path_trace_kernel = kernel_cpu_avx2_path_trace;
+ else
#endif
#ifdef WITH_CYCLES_OPTIMIZED_KERNEL_AVX
- if(system_cpu_support_avx()) {
- 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_avx_path_trace(&kg, render_buffer, rng_state,
- sample, x, y, tile.offset, tile.stride);
- }
- }
-
- tile.sample = sample + 1;
-
- task.update_progress(&tile);
- }
- }
- else
+ if(system_cpu_support_avx())
+ path_trace_kernel = kernel_cpu_avx_path_trace;
+ else
#endif
-#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
+#ifdef WITH_CYCLES_OPTIMIZED_KERNEL_SSE41
+ if(system_cpu_support_sse41())
+ path_trace_kernel = kernel_cpu_sse41_path_trace;
+ else
#endif
#ifdef WITH_CYCLES_OPTIMIZED_KERNEL_SSE3
- if(system_cpu_support_sse3()) {
- 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_sse3_path_trace(&kg, render_buffer, rng_state,
- sample, x, y, tile.offset, tile.stride);
- }
- }
-
- tile.sample = sample + 1;
-
- task.update_progress(&tile);
- }
- }
- else
+ if(system_cpu_support_sse3())
+ path_trace_kernel = kernel_cpu_sse3_path_trace;
+ else
#endif
#ifdef WITH_CYCLES_OPTIMIZED_KERNEL_SSE2
- if(system_cpu_support_sse2()) {
- 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_sse2_path_trace(&kg, render_buffer, rng_state,
- sample, x, y, tile.offset, tile.stride);
- }
- }
-
- tile.sample = sample + 1;
+ if(system_cpu_support_sse2())
+ path_trace_kernel = kernel_cpu_sse2_path_trace;
+ else
+#endif
+ path_trace_kernel = kernel_cpu_path_trace;
+
+ while(task.acquire_tile(this, tile)) {
+ float *render_buffer = (float*)tile.buffer;
+ uint *rng_state = (uint*)tile.rng_state;
+ int start_sample = tile.start_sample;
+ int end_sample = tile.start_sample + tile.num_samples;
- task.update_progress(&tile);
+ for(int sample = start_sample; sample < end_sample; sample++) {
+ if(task.get_cancel() || task_pool.canceled()) {
+ if(task.need_finish_queue == false)
+ break;
}
- }
- else
-#endif
- {
- 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_path_trace(&kg, render_buffer, rng_state,
- sample, x, y, tile.offset, tile.stride);
- }
+ for(int y = tile.y; y < tile.y + tile.h; y++) {
+ for(int x = tile.x; x < tile.x + tile.w; x++) {
+ path_trace_kernel(&kg, render_buffer, rng_state,
+ sample, x, y, tile.offset, tile.stride);
}
+ }
- tile.sample = sample + 1;
+ tile.sample = sample + 1;
- task.update_progress(&tile);
- }
+ task.update_progress(&tile);
}
task.release_tile(tile);
@@ -320,110 +265,74 @@ public:
float sample_scale = 1.0f/(task.sample + 1);
if(task.rgba_half) {
+ void(*convert_to_half_float_kernel)(KernelGlobals *, uchar4 *, float *, float, int, int, int, int);
#ifdef WITH_CYCLES_OPTIMIZED_KERNEL_AVX2
- if(system_cpu_support_avx2()) {
- for(int y = task.y; y < task.y + task.h; y++)
- for(int x = task.x; x < task.x + task.w; x++)
- kernel_cpu_avx2_convert_to_half_float(&kernel_globals, (uchar4*)task.rgba_half, (float*)task.buffer,
- sample_scale, x, y, task.offset, task.stride);
- }
+ if(system_cpu_support_avx2())
+ convert_to_half_float_kernel = kernel_cpu_avx2_convert_to_half_float;
else
#endif
#ifdef WITH_CYCLES_OPTIMIZED_KERNEL_AVX
- if(system_cpu_support_avx()) {
+ if(system_cpu_support_avx())
for(int y = task.y; y < task.y + task.h; y++)
- for(int x = task.x; x < task.x + task.w; x++)
- kernel_cpu_avx_convert_to_half_float(&kernel_globals, (uchar4*)task.rgba_half, (float*)task.buffer,
- sample_scale, x, y, task.offset, task.stride);
- }
+ convert_to_half_float_kernel = kernel_cpu_avx_convert_to_half_float;
else
#endif
#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);
- }
+ if(system_cpu_support_sse41())
+ convert_to_half_float_kernel = kernel_cpu_sse41_convert_to_half_float;
else
#endif
#ifdef WITH_CYCLES_OPTIMIZED_KERNEL_SSE3
- 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++)
- kernel_cpu_sse3_convert_to_half_float(&kernel_globals, (uchar4*)task.rgba_half, (float*)task.buffer,
- sample_scale, x, y, task.offset, task.stride);
- }
+ if(system_cpu_support_sse3())
+ convert_to_half_float_kernel = kernel_cpu_sse3_convert_to_half_float;
else
#endif
#ifdef WITH_CYCLES_OPTIMIZED_KERNEL_SSE2
- if(system_cpu_support_sse2()) {
- for(int y = task.y; y < task.y + task.h; y++)
- for(int x = task.x; x < task.x + task.w; x++)
- kernel_cpu_sse2_convert_to_half_float(&kernel_globals, (uchar4*)task.rgba_half, (float*)task.buffer,
- sample_scale, x, y, task.offset, task.stride);
- }
+ if(system_cpu_support_sse2())
+ convert_to_half_float_kernel = kernel_cpu_sse2_convert_to_half_float;
else
#endif
- {
- for(int y = task.y; y < task.y + task.h; y++)
- for(int x = task.x; x < task.x + task.w; x++)
- kernel_cpu_convert_to_half_float(&kernel_globals, (uchar4*)task.rgba_half, (float*)task.buffer,
- sample_scale, x, y, task.offset, task.stride);
- }
+ convert_to_half_float_kernel = kernel_cpu_convert_to_half_float;
+
+ for(int y = task.y; y < task.y + task.h; y++)
+ for(int x = task.x; x < task.x + task.w; x++)
+ convert_to_half_float_kernel(&kernel_globals, (uchar4*)task.rgba_half, (float*)task.buffer,
+ sample_scale, x, y, task.offset, task.stride);
}
else {
+ void(*convert_to_byte_kernel)(KernelGlobals *, uchar4 *, float *, float, int, int, int, int);
#ifdef WITH_CYCLES_OPTIMIZED_KERNEL_AVX2
- if(system_cpu_support_avx2()) {
- for(int y = task.y; y < task.y + task.h; y++)
- for(int x = task.x; x < task.x + task.w; x++)
- kernel_cpu_avx2_convert_to_byte(&kernel_globals, (uchar4*)task.rgba_byte, (float*)task.buffer,
- sample_scale, x, y, task.offset, task.stride);
- }
+ if(system_cpu_support_avx2())
+ convert_to_byte_kernel = kernel_cpu_avx2_convert_to_byte;
else
#endif
#ifdef WITH_CYCLES_OPTIMIZED_KERNEL_AVX
- if(system_cpu_support_avx()) {
- for(int y = task.y; y < task.y + task.h; y++)
- for(int x = task.x; x < task.x + task.w; x++)
- kernel_cpu_avx_convert_to_byte(&kernel_globals, (uchar4*)task.rgba_byte, (float*)task.buffer,
- sample_scale, x, y, task.offset, task.stride);
- }
+ if(system_cpu_support_avx())
+ convert_to_byte_kernel = kernel_cpu_avx_convert_to_byte;
else
#endif
#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);
- }
+ if(system_cpu_support_sse41())
+ convert_to_byte_kernel = kernel_cpu_sse41_convert_to_byte;
else
#endif
#ifdef WITH_CYCLES_OPTIMIZED_KERNEL_SSE3
- 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++)
- kernel_cpu_sse3_convert_to_byte(&kernel_globals, (uchar4*)task.rgba_byte, (float*)task.buffer,
- sample_scale, x, y, task.offset, task.stride);
- }
+ if(system_cpu_support_sse3())
+ convert_to_byte_kernel = kernel_cpu_sse3_convert_to_byte;
else
#endif
#ifdef WITH_CYCLES_OPTIMIZED_KERNEL_SSE2
- if(system_cpu_support_sse2()) {
- for(int y = task.y; y < task.y + task.h; y++)
- for(int x = task.x; x < task.x + task.w; x++)
- kernel_cpu_sse2_convert_to_byte(&kernel_globals, (uchar4*)task.rgba_byte, (float*)task.buffer,
- sample_scale, x, y, task.offset, task.stride);
- }
+ if(system_cpu_support_sse2())
+ convert_to_byte_kernel = kernel_cpu_sse2_convert_to_byte;
else
#endif
- {
- for(int y = task.y; y < task.y + task.h; y++)
- for(int x = task.x; x < task.x + task.w; x++)
- kernel_cpu_convert_to_byte(&kernel_globals, (uchar4*)task.rgba_byte, (float*)task.buffer,
- sample_scale, x, y, task.offset, task.stride);
- }
+ convert_to_byte_kernel = kernel_cpu_convert_to_byte;
+
+ for(int y = task.y; y < task.y + task.h; y++)
+ for(int x = task.x; x < task.x + task.w; x++)
+ convert_to_byte_kernel(&kernel_globals, (uchar4*)task.rgba_byte, (float*)task.buffer,
+ sample_scale, x, y, task.offset, task.stride);
+
}
}
@@ -434,93 +343,45 @@ public:
#ifdef WITH_OSL
OSLShader::thread_init(&kg, &kernel_globals, &osl_globals);
#endif
+ void(*shader_kernel)(KernelGlobals*, uint4*, float4*, int, int, int, int);
#ifdef WITH_CYCLES_OPTIMIZED_KERNEL_AVX2
- if(system_cpu_support_avx2()) {
- for(int sample = 0; sample < task.num_samples; sample++) {
- for(int x = task.shader_x; x < task.shader_x + task.shader_w; x++)
- kernel_cpu_avx2_shader(&kg, (uint4*)task.shader_input, (float4*)task.shader_output,
- task.shader_eval_type, x, task.offset, sample);
-
- if(task.get_cancel() || task_pool.canceled())
- break;
-
- task.update_progress(NULL);
- }
- }
+ if(system_cpu_support_avx2())
+ shader_kernel = kernel_cpu_avx2_shader;
else
#endif
#ifdef WITH_CYCLES_OPTIMIZED_KERNEL_AVX
- if(system_cpu_support_avx()) {
- for(int sample = 0; sample < task.num_samples; sample++) {
- for(int x = task.shader_x; x < task.shader_x + task.shader_w; x++)
- kernel_cpu_avx_shader(&kg, (uint4*)task.shader_input, (float4*)task.shader_output,
- task.shader_eval_type, x, task.offset, sample);
-
- if(task.get_cancel() || task_pool.canceled())
- break;
-
- task.update_progress(NULL);
- }
- }
+ if(system_cpu_support_avx())
+ shader_kernel = kernel_cpu_avx_shader;
else
#endif
#ifdef WITH_CYCLES_OPTIMIZED_KERNEL_SSE41
- if(system_cpu_support_sse41()) {
- for(int sample = 0; sample < task.num_samples; sample++) {
- for(int x = task.shader_x; x < task.shader_x + task.shader_w; x++)
- kernel_cpu_sse41_shader(&kg, (uint4*)task.shader_input, (float4*)task.shader_output,
- task.shader_eval_type, x, task.offset, sample);
-
- if(task.get_cancel() || task_pool.canceled())
- break;
-
- task.update_progress(NULL);
- }
- }
+ if(system_cpu_support_sse41())
+ shader_kernel = kernel_cpu_sse41_shader;
else
#endif
#ifdef WITH_CYCLES_OPTIMIZED_KERNEL_SSE3
- if(system_cpu_support_sse3()) {
- for(int sample = 0; sample < task.num_samples; sample++) {
- for(int x = task.shader_x; x < task.shader_x + task.shader_w; x++)
- kernel_cpu_sse3_shader(&kg, (uint4*)task.shader_input, (float4*)task.shader_output,
- task.shader_eval_type, x, task.offset, sample);
-
- if(task.get_cancel() || task_pool.canceled())
- break;
-
- task.update_progress(NULL);
- }
- }
+ if(system_cpu_support_sse3())
+ shader_kernel = kernel_cpu_sse3_shader;
else
#endif
#ifdef WITH_CYCLES_OPTIMIZED_KERNEL_SSE2
- if(system_cpu_support_sse2()) {
- for(int sample = 0; sample < task.num_samples; sample++) {
- for(int x = task.shader_x; x < task.shader_x + task.shader_w; x++)
- kernel_cpu_sse2_shader(&kg, (uint4*)task.shader_input, (float4*)task.shader_output,
- task.shader_eval_type, x, task.offset, sample);
-
- if(task.get_cancel() || task_pool.canceled())
- break;
-
- task.update_progress(NULL);
- }
- }
+ if(system_cpu_support_sse2())
+ shader_kernel = kernel_cpu_sse2_shader;
else
#endif
- {
- for(int sample = 0; sample < task.num_samples; sample++) {
- for(int x = task.shader_x; x < task.shader_x + task.shader_w; x++)
- kernel_cpu_shader(&kg, (uint4*)task.shader_input, (float4*)task.shader_output,
- task.shader_eval_type, x, task.offset, sample);
+ shader_kernel = kernel_cpu_shader;
- if(task.get_cancel() || task_pool.canceled())
- break;
+ for(int sample = 0; sample < task.num_samples; sample++) {
+ for(int x = task.shader_x; x < task.shader_x + task.shader_w; x++)
+ shader_kernel(&kg, (uint4*)task.shader_input, (float4*)task.shader_output,
+ task.shader_eval_type, x, task.offset, sample);
+
+ if(task.get_cancel() || task_pool.canceled())
+ break;
+
+ task.update_progress(NULL);
- task.update_progress(NULL);
- }
}
#ifdef WITH_OSL
@@ -530,7 +391,7 @@ public:
int get_split_task_count(DeviceTask& task)
{
- if (task.type == DeviceTask::SHADER)
+ if(task.type == DeviceTask::SHADER)
return task.get_subtask_count(TaskScheduler::num_threads(), 256);
else
return task.get_subtask_count(TaskScheduler::num_threads());
@@ -580,5 +441,17 @@ void device_cpu_info(vector<DeviceInfo>& devices)
devices.insert(devices.begin(), info);
}
-CCL_NAMESPACE_END
+string device_cpu_capabilities(void)
+{
+ string capabilities = "";
+ capabilities += system_cpu_support_sse2() ? "SSE2 " : "";
+ capabilities += system_cpu_support_sse3() ? "SSE3 " : "";
+ capabilities += system_cpu_support_sse41() ? "SSE41 " : "";
+ capabilities += system_cpu_support_avx() ? "AVX " : "";
+ capabilities += system_cpu_support_avx2() ? "AVX2" : "";
+ if(capabilities[capabilities.size() - 1] == ' ')
+ capabilities.resize(capabilities.size() - 1);
+ return capabilities;
+}
+CCL_NAMESPACE_END
diff --git a/intern/cycles/device/device_cuda.cpp b/intern/cycles/device/device_cuda.cpp
index 5de2efab8be..a47d4edeb56 100644
--- a/intern/cycles/device/device_cuda.cpp
+++ b/intern/cycles/device/device_cuda.cpp
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#include <stdio.h>
@@ -25,9 +25,11 @@
#include "cuew.h"
#include "util_debug.h"
+#include "util_logging.h"
#include "util_map.h"
#include "util_opengl.h"
#include "util_path.h"
+#include "util_string.h"
#include "util_system.h"
#include "util_types.h"
#include "util_time.h"
@@ -76,7 +78,7 @@ public:
{
if(first_error) {
fprintf(stderr, "\nRefer to the Cycles GPU rendering documentation for possible solutions:\n");
- fprintf(stderr, "http://wiki.blender.org/index.php/Doc:2.6/Manual/Render/Cycles/GPU_Rendering\n\n");
+ fprintf(stderr, "http://www.blender.org/manual/render/cycles/gpu_rendering.html\n\n");
first_error = false;
}
}
@@ -183,7 +185,7 @@ public:
cuda_assert(cuCtxDestroy(cuContext));
}
- bool support_device(bool experimental)
+ bool support_device(bool /*experimental*/)
{
int major, minor;
cuDeviceComputeCapability(&major, &minor, cuDevId);
@@ -202,15 +204,18 @@ public:
/* compute cubin name */
int major, minor;
cuDeviceComputeCapability(&major, &minor, cuDevId);
+ string cubin;
/* attempt to use kernel provided with blender */
- string cubin;
if(experimental)
cubin = path_get(string_printf("lib/kernel_experimental_sm_%d%d.cubin", major, minor));
else
cubin = path_get(string_printf("lib/kernel_sm_%d%d.cubin", major, minor));
- if(path_exists(cubin))
+ VLOG(1) << "Testing for pre-compiled kernel " << cubin;
+ if(path_exists(cubin)) {
+ VLOG(1) << "Using precompiled kernel";
return cubin;
+ }
/* not found, try to use locally compiled kernel */
string kernel_path = path_get("kernel");
@@ -221,10 +226,12 @@ public:
else
cubin = string_printf("cycles_kernel_sm%d%d_%s.cubin", major, minor, md5.c_str());
cubin = path_user_get(path_join("cache", cubin));
-
+ VLOG(1) << "Testing for locally compiled kernel " << cubin;
/* if exists already, use it */
- if(path_exists(cubin))
+ if(path_exists(cubin)) {
+ VLOG(1) << "Using locally compiled kernel";
return cubin;
+ }
#ifdef _WIN32
if(have_precompiled_kernels()) {
@@ -245,6 +252,7 @@ public:
}
int cuda_version = cuewCompilerVersion();
+ VLOG(1) << "Found nvcc " << nvcc << ", CUDA version " << cuda_version;
if(cuda_version == 0) {
cuda_error_message("CUDA nvcc compiler version could not be parsed.");
@@ -258,7 +266,7 @@ public:
printf("CUDA version %d.%d detected, build may succeed but only CUDA 6.5 is officially supported.\n", cuda_version/10, cuda_version%10);
/* compile */
- string kernel = path_join(kernel_path, "kernel.cu");
+ string kernel = path_join(kernel_path, path_join("kernels", path_join("cuda", "kernel.cu")));
string include = kernel_path;
const int machine = system_cpu_bits();
@@ -268,11 +276,20 @@ public:
path_create_directories(cubin);
string command = string_printf("\"%s\" -arch=sm_%d%d -m%d --cubin \"%s\" "
- "-o \"%s\" --ptxas-options=\"-v\" -I\"%s\" -DNVCC -D__KERNEL_CUDA_VERSION__=%d",
+ "-o \"%s\" --ptxas-options=\"-v\" --use_fast_math -I\"%s\" "
+ "-DNVCC -D__KERNEL_CUDA_VERSION__=%d",
nvcc, major, minor, machine, kernel.c_str(), cubin.c_str(), include.c_str(), cuda_version);
if(experimental)
- command += " -D__KERNEL_CUDA_EXPERIMENTAL__";
+ command += " -D__KERNEL_EXPERIMENTAL__";
+
+ if(getenv("CYCLES_CUDA_EXTRA_CFLAGS")) {
+ command += string(" ") + getenv("CYCLES_CUDA_EXTRA_CFLAGS");
+ }
+
+#ifdef WITH_CYCLES_DEBUG
+ command += " -D__KERNEL_DEBUG__";
+#endif
printf("%s\n", command.c_str());
@@ -292,18 +309,18 @@ public:
return cubin;
}
- bool load_kernels(bool experimental)
+ bool load_kernels(const DeviceRequestedFeatures& requested_features)
{
/* check if cuda init succeeded */
if(cuContext == 0)
return false;
/* check if GPU is supported */
- if(!support_device(experimental))
+ if(!support_device(requested_features.experimental))
return false;
/* get kernel */
- string cubin = compile_kernel(experimental);
+ string cubin = compile_kernel(requested_features.experimental);
if(cubin == "")
return false;
@@ -314,7 +331,7 @@ public:
string cubin_data;
CUresult result;
- if (path_read_text(cubin, cubin_data))
+ if(path_read_text(cubin, cubin_data))
result = cuModuleLoadData(&cuModule, cubin_data.c_str());
else
result = CUDA_ERROR_FILE_NOT_FOUND;
@@ -327,7 +344,7 @@ public:
return (result == CUDA_SUCCESS);
}
- void mem_alloc(device_memory& mem, MemoryType type)
+ void mem_alloc(device_memory& mem, MemoryType /*type*/)
{
cuda_push_context();
CUdeviceptr device_pointer;
@@ -355,7 +372,7 @@ public:
cuda_push_context();
if(mem.device_pointer) {
cuda_assert(cuMemcpyDtoH((uchar*)mem.data_pointer + offset,
- (CUdeviceptr)((uchar*)mem.device_pointer + offset), size));
+ (CUdeviceptr)(mem.device_pointer + offset), size));
}
else {
memset((char*)mem.data_pointer + offset, 0, size);
@@ -399,9 +416,13 @@ public:
cuda_pop_context();
}
- void tex_alloc(const char *name, device_memory& mem, InterpolationType interpolation, bool periodic)
+ void tex_alloc(const char *name,
+ device_memory& mem,
+ InterpolationType interpolation,
+ ExtensionType extension)
{
/* todo: support 3D textures, only CPU for now */
+ VLOG(1) << "Texture allocate: " << name << ", " << mem.memory_size() << " bytes.";
/* determine format */
CUarray_format_enum format;
@@ -466,7 +487,7 @@ public:
if(interpolation == INTERPOLATION_CLOSEST) {
cuda_assert(cuTexRefSetFilterMode(texref, CU_TR_FILTER_MODE_POINT));
}
- else if (interpolation == INTERPOLATION_LINEAR) {
+ else if(interpolation == INTERPOLATION_LINEAR) {
cuda_assert(cuTexRefSetFilterMode(texref, CU_TR_FILTER_MODE_LINEAR));
}
else {/* CUBIC and SMART are unsupported for CUDA */
@@ -492,13 +513,19 @@ public:
cuda_assert(cuTexRefSetFlags(texref, CU_TRSF_READ_AS_INTEGER));
}
- if(periodic) {
- cuda_assert(cuTexRefSetAddressMode(texref, 0, CU_TR_ADDRESS_MODE_WRAP));
- cuda_assert(cuTexRefSetAddressMode(texref, 1, CU_TR_ADDRESS_MODE_WRAP));
- }
- else {
- cuda_assert(cuTexRefSetAddressMode(texref, 0, CU_TR_ADDRESS_MODE_CLAMP));
- cuda_assert(cuTexRefSetAddressMode(texref, 1, CU_TR_ADDRESS_MODE_CLAMP));
+ switch(extension) {
+ case EXTENSION_REPEAT:
+ cuda_assert(cuTexRefSetAddressMode(texref, 0, CU_TR_ADDRESS_MODE_WRAP));
+ cuda_assert(cuTexRefSetAddressMode(texref, 1, CU_TR_ADDRESS_MODE_WRAP));
+ break;
+ case EXTENSION_EXTEND:
+ cuda_assert(cuTexRefSetAddressMode(texref, 0, CU_TR_ADDRESS_MODE_CLAMP));
+ cuda_assert(cuTexRefSetAddressMode(texref, 1, CU_TR_ADDRESS_MODE_CLAMP));
+ break;
+ case EXTENSION_CLIP:
+ cuda_assert(cuTexRefSetAddressMode(texref, 0, CU_TR_ADDRESS_MODE_BORDER));
+ cuda_assert(cuTexRefSetAddressMode(texref, 1, CU_TR_ADDRESS_MODE_BORDER));
+ break;
}
cuda_assert(cuTexRefSetFormat(texref, format, mem.data_elements));
@@ -862,11 +889,12 @@ public:
}
}
- void draw_pixels(device_memory& mem, int y, int w, int h, int dy, int width, int height, bool transparent,
+ void draw_pixels(device_memory& mem, int y, int w, int h, int dx, int dy, int width, int height, bool transparent,
const DeviceDrawParams &draw_params)
{
if(!background) {
PixelMem pmem = pixel_mem_map[mem.device_pointer];
+ float *vpointer;
cuda_push_context();
@@ -900,23 +928,52 @@ public:
draw_params.bind_display_space_shader_cb();
}
- glPushMatrix();
- glTranslatef(0.0f, (float)dy, 0.0f);
-
- glBegin(GL_QUADS);
-
- glTexCoord2f(0.0f, 0.0f);
- glVertex2f(0.0f, 0.0f);
- glTexCoord2f((float)w/(float)pmem.w, 0.0f);
- glVertex2f((float)width, 0.0f);
- glTexCoord2f((float)w/(float)pmem.w, (float)h/(float)pmem.h);
- glVertex2f((float)width, (float)height);
- glTexCoord2f(0.0f, (float)h/(float)pmem.h);
- glVertex2f(0.0f, (float)height);
+ if(!vertex_buffer)
+ glGenBuffers(1, &vertex_buffer);
+
+ glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer);
+ /* invalidate old contents - avoids stalling if buffer is still waiting in queue to be rendered */
+ glBufferData(GL_ARRAY_BUFFER, 16 * sizeof(float), NULL, GL_STREAM_DRAW);
- glEnd();
+ vpointer = (float *)glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY);
- glPopMatrix();
+ if(vpointer) {
+ /* texture coordinate - vertex pair */
+ vpointer[0] = 0.0f;
+ vpointer[1] = 0.0f;
+ vpointer[2] = dx;
+ vpointer[3] = dy;
+
+ vpointer[4] = (float)w/(float)pmem.w;
+ vpointer[5] = 0.0f;
+ vpointer[6] = (float)width + dx;
+ vpointer[7] = dy;
+
+ vpointer[8] = (float)w/(float)pmem.w;
+ vpointer[9] = (float)h/(float)pmem.h;
+ vpointer[10] = (float)width + dx;
+ vpointer[11] = (float)height + dy;
+
+ vpointer[12] = 0.0f;
+ vpointer[13] = (float)h/(float)pmem.h;
+ vpointer[14] = dx;
+ vpointer[15] = (float)height + dy;
+
+ glUnmapBuffer(GL_ARRAY_BUFFER);
+ }
+
+ glTexCoordPointer(2, GL_FLOAT, 4 * sizeof(float), 0);
+ glVertexPointer(2, GL_FLOAT, 4 * sizeof(float), (char *)NULL + 2 * sizeof(float));
+
+ glEnableClientState(GL_VERTEX_ARRAY);
+ glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+
+ glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
+
+ glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+ glDisableClientState(GL_VERTEX_ARRAY);
+
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
if(draw_params.unbind_display_space_shader_cb) {
draw_params.unbind_display_space_shader_cb();
@@ -933,7 +990,7 @@ public:
return;
}
- Device::draw_pixels(mem, y, w, h, dy, width, height, transparent, draw_params);
+ Device::draw_pixels(mem, y, w, h, dx, dy, width, height, transparent, draw_params);
}
void thread_run(DeviceTask *task)
@@ -949,7 +1006,7 @@ public:
int end_sample = tile.start_sample + tile.num_samples;
for(int sample = start_sample; sample < end_sample; sample++) {
- if (task->get_cancel()) {
+ if(task->get_cancel()) {
if(task->need_finish_queue == false)
break;
}
@@ -982,7 +1039,7 @@ public:
}
};
- int get_split_task_count(DeviceTask& task)
+ int get_split_task_count(DeviceTask& /*task*/)
{
return 1;
}
@@ -1018,19 +1075,34 @@ bool device_cuda_init(void)
static bool initialized = false;
static bool result = false;
- if (initialized)
+ if(initialized)
return result;
initialized = true;
-
- if (cuewInit() == CUEW_SUCCESS) {
- if(CUDADevice::have_precompiled_kernels())
+ int cuew_result = cuewInit();
+ if(cuew_result == CUEW_SUCCESS) {
+ VLOG(1) << "CUEW initialization succeeded";
+ if(CUDADevice::have_precompiled_kernels()) {
+ VLOG(1) << "Found precompiled kernels";
result = true;
+ }
#ifndef _WIN32
- else if(cuewCompilerPath() != NULL)
+ else if(cuewCompilerPath() != NULL) {
+ VLOG(1) << "Found CUDA compiled " << cuewCompilerPath();
result = true;
+ }
+ else {
+ VLOG(1) << "Neither precompiled kernels nor CUDA compiler wad found,"
+ << " unable to use CUDA";
+ }
#endif
}
+ else {
+ VLOG(1) << "CUEW initialization failed: "
+ << ((cuew_result == CUEW_ERROR_ATEXIT_FAILED)
+ ? "Error setting up atexit() handler"
+ : "Error opening the library");
+ }
return result;
}
@@ -1059,14 +1131,20 @@ void device_cuda_info(vector<DeviceInfo>& devices)
}
vector<DeviceInfo> display_devices;
-
+
for(int num = 0; num < count; num++) {
char name[256];
int attr;
-
+
if(cuDeviceGetName(name, 256, num) != CUDA_SUCCESS)
continue;
+ int major, minor;
+ cuDeviceComputeCapability(&major, &minor, num);
+ if(major < 2) {
+ continue;
+ }
+
DeviceInfo info;
info.type = DEVICE_CUDA;
@@ -1074,8 +1152,6 @@ void device_cuda_info(vector<DeviceInfo>& devices)
info.id = string_printf("CUDA_%d", num);
info.num = num;
- int major, minor;
- cuDeviceComputeCapability(&major, &minor, num);
info.advanced_shading = (major >= 2);
info.extended_images = (major >= 3);
info.pack_images = false;
@@ -1093,5 +1169,135 @@ void device_cuda_info(vector<DeviceInfo>& devices)
devices.insert(devices.end(), display_devices.begin(), display_devices.end());
}
-CCL_NAMESPACE_END
+string device_cuda_capabilities(void)
+{
+ CUresult result = cuInit(0);
+ if(result != CUDA_SUCCESS) {
+ if(result != CUDA_ERROR_NO_DEVICE) {
+ return string("Error initializing CUDA: ") + cuewErrorString(result);
+ }
+ return "No CUDA device found\n";
+ }
+
+ int count;
+ result = cuDeviceGetCount(&count);
+ if(result != CUDA_SUCCESS) {
+ return string("Error getting devices: ") + cuewErrorString(result);
+ }
+ string capabilities = "";
+ for(int num = 0; num < count; num++) {
+ char name[256];
+ if(cuDeviceGetName(name, 256, num) != CUDA_SUCCESS) {
+ continue;
+ }
+ capabilities += string("\t") + name + "\n";
+ int value;
+#define GET_ATTR(attr) \
+ { \
+ if(cuDeviceGetAttribute(&value, \
+ CU_DEVICE_ATTRIBUTE_##attr, \
+ num) == CUDA_SUCCESS) \
+ { \
+ capabilities += string_printf("\t\tCU_DEVICE_ATTRIBUTE_" #attr "\t\t\t%d\n", \
+ value); \
+ } \
+ } (void)0
+ /* TODO(sergey): Strip all attributes which are not useful for us
+ * or does not depend on the driver.
+ */
+ GET_ATTR(MAX_THREADS_PER_BLOCK);
+ GET_ATTR(MAX_BLOCK_DIM_X);
+ GET_ATTR(MAX_BLOCK_DIM_Y);
+ GET_ATTR(MAX_BLOCK_DIM_Z);
+ GET_ATTR(MAX_GRID_DIM_X);
+ GET_ATTR(MAX_GRID_DIM_Y);
+ GET_ATTR(MAX_GRID_DIM_Z);
+ GET_ATTR(MAX_SHARED_MEMORY_PER_BLOCK);
+ GET_ATTR(SHARED_MEMORY_PER_BLOCK);
+ GET_ATTR(TOTAL_CONSTANT_MEMORY);
+ GET_ATTR(WARP_SIZE);
+ GET_ATTR(MAX_PITCH);
+ GET_ATTR(MAX_REGISTERS_PER_BLOCK);
+ GET_ATTR(REGISTERS_PER_BLOCK);
+ GET_ATTR(CLOCK_RATE);
+ GET_ATTR(TEXTURE_ALIGNMENT);
+ GET_ATTR(GPU_OVERLAP);
+ GET_ATTR(MULTIPROCESSOR_COUNT);
+ GET_ATTR(KERNEL_EXEC_TIMEOUT);
+ GET_ATTR(INTEGRATED);
+ GET_ATTR(CAN_MAP_HOST_MEMORY);
+ GET_ATTR(COMPUTE_MODE);
+ GET_ATTR(MAXIMUM_TEXTURE1D_WIDTH);
+ GET_ATTR(MAXIMUM_TEXTURE2D_WIDTH);
+ GET_ATTR(MAXIMUM_TEXTURE2D_HEIGHT);
+ GET_ATTR(MAXIMUM_TEXTURE3D_WIDTH);
+ GET_ATTR(MAXIMUM_TEXTURE3D_HEIGHT);
+ GET_ATTR(MAXIMUM_TEXTURE3D_DEPTH);
+ GET_ATTR(MAXIMUM_TEXTURE2D_LAYERED_WIDTH);
+ GET_ATTR(MAXIMUM_TEXTURE2D_LAYERED_HEIGHT);
+ GET_ATTR(MAXIMUM_TEXTURE2D_LAYERED_LAYERS);
+ GET_ATTR(MAXIMUM_TEXTURE2D_ARRAY_WIDTH);
+ GET_ATTR(MAXIMUM_TEXTURE2D_ARRAY_HEIGHT);
+ GET_ATTR(MAXIMUM_TEXTURE2D_ARRAY_NUMSLICES);
+ GET_ATTR(SURFACE_ALIGNMENT);
+ GET_ATTR(CONCURRENT_KERNELS);
+ GET_ATTR(ECC_ENABLED);
+ GET_ATTR(TCC_DRIVER);
+ GET_ATTR(MEMORY_CLOCK_RATE);
+ GET_ATTR(GLOBAL_MEMORY_BUS_WIDTH);
+ GET_ATTR(L2_CACHE_SIZE);
+ GET_ATTR(MAX_THREADS_PER_MULTIPROCESSOR);
+ GET_ATTR(ASYNC_ENGINE_COUNT);
+ GET_ATTR(UNIFIED_ADDRESSING);
+ GET_ATTR(MAXIMUM_TEXTURE1D_LAYERED_WIDTH);
+ GET_ATTR(MAXIMUM_TEXTURE1D_LAYERED_LAYERS);
+ GET_ATTR(CAN_TEX2D_GATHER);
+ GET_ATTR(MAXIMUM_TEXTURE2D_GATHER_WIDTH);
+ GET_ATTR(MAXIMUM_TEXTURE2D_GATHER_HEIGHT);
+ GET_ATTR(MAXIMUM_TEXTURE3D_WIDTH_ALTERNATE);
+ GET_ATTR(MAXIMUM_TEXTURE3D_HEIGHT_ALTERNATE);
+ GET_ATTR(MAXIMUM_TEXTURE3D_DEPTH_ALTERNATE);
+ GET_ATTR(TEXTURE_PITCH_ALIGNMENT);
+ GET_ATTR(MAXIMUM_TEXTURECUBEMAP_WIDTH);
+ GET_ATTR(MAXIMUM_TEXTURECUBEMAP_LAYERED_WIDTH);
+ GET_ATTR(MAXIMUM_TEXTURECUBEMAP_LAYERED_LAYERS);
+ GET_ATTR(MAXIMUM_SURFACE1D_WIDTH);
+ GET_ATTR(MAXIMUM_SURFACE2D_WIDTH);
+ GET_ATTR(MAXIMUM_SURFACE2D_HEIGHT);
+ GET_ATTR(MAXIMUM_SURFACE3D_WIDTH);
+ GET_ATTR(MAXIMUM_SURFACE3D_HEIGHT);
+ GET_ATTR(MAXIMUM_SURFACE3D_DEPTH);
+ GET_ATTR(MAXIMUM_SURFACE1D_LAYERED_WIDTH);
+ GET_ATTR(MAXIMUM_SURFACE1D_LAYERED_LAYERS);
+ GET_ATTR(MAXIMUM_SURFACE2D_LAYERED_WIDTH);
+ GET_ATTR(MAXIMUM_SURFACE2D_LAYERED_HEIGHT);
+ GET_ATTR(MAXIMUM_SURFACE2D_LAYERED_LAYERS);
+ GET_ATTR(MAXIMUM_SURFACECUBEMAP_WIDTH);
+ GET_ATTR(MAXIMUM_SURFACECUBEMAP_LAYERED_WIDTH);
+ GET_ATTR(MAXIMUM_SURFACECUBEMAP_LAYERED_LAYERS);
+ GET_ATTR(MAXIMUM_TEXTURE1D_LINEAR_WIDTH);
+ GET_ATTR(MAXIMUM_TEXTURE2D_LINEAR_WIDTH);
+ GET_ATTR(MAXIMUM_TEXTURE2D_LINEAR_HEIGHT);
+ GET_ATTR(MAXIMUM_TEXTURE2D_LINEAR_PITCH);
+ GET_ATTR(MAXIMUM_TEXTURE2D_MIPMAPPED_WIDTH);
+ GET_ATTR(MAXIMUM_TEXTURE2D_MIPMAPPED_HEIGHT);
+ GET_ATTR(COMPUTE_CAPABILITY_MAJOR);
+ GET_ATTR(COMPUTE_CAPABILITY_MINOR);
+ GET_ATTR(MAXIMUM_TEXTURE1D_MIPMAPPED_WIDTH);
+ GET_ATTR(STREAM_PRIORITIES_SUPPORTED);
+ GET_ATTR(GLOBAL_L1_CACHE_SUPPORTED);
+ GET_ATTR(LOCAL_L1_CACHE_SUPPORTED);
+ GET_ATTR(MAX_SHARED_MEMORY_PER_MULTIPROCESSOR);
+ GET_ATTR(MAX_REGISTERS_PER_MULTIPROCESSOR);
+ GET_ATTR(MANAGED_MEMORY);
+ GET_ATTR(MULTI_GPU_BOARD);
+ GET_ATTR(MULTI_GPU_BOARD_GROUP_ID);
+#undef GET_ATTR
+ capabilities += "\n";
+ }
+
+ return capabilities;
+}
+
+CCL_NAMESPACE_END
diff --git a/intern/cycles/device/device_intern.h b/intern/cycles/device/device_intern.h
index 80f1e2441a5..47584ae6d22 100644
--- a/intern/cycles/device/device_intern.h
+++ b/intern/cycles/device/device_intern.h
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#ifndef __DEVICE_INTERN_H__
@@ -35,6 +35,10 @@ void device_cuda_info(vector<DeviceInfo>& devices);
void device_network_info(vector<DeviceInfo>& devices);
void device_multi_info(vector<DeviceInfo>& devices);
+string device_cpu_capabilities(void);
+string device_opencl_capabilities(void);
+string device_cuda_capabilities(void);
+
CCL_NAMESPACE_END
#endif /* __DEVICE_INTERN_H__ */
diff --git a/intern/cycles/device/device_memory.h b/intern/cycles/device/device_memory.h
index 8eee6a2c79e..ba79f8c88ae 100644
--- a/intern/cycles/device/device_memory.h
+++ b/intern/cycles/device/device_memory.h
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#ifndef __DEVICE_MEMORY_H__
@@ -212,11 +212,14 @@ public:
{
data_size = width * ((height == 0)? 1: height) * ((depth == 0)? 1: depth);
data.resize(data_size);
- data_pointer = (device_ptr)&data[0];
data_width = width;
data_height = height;
data_depth = depth;
-
+ if(data_size == 0) {
+ data_pointer = 0;
+ return NULL;
+ }
+ data_pointer = (device_ptr)&data[0];
return &data[0];
}
@@ -260,6 +263,11 @@ public:
return data.size();
}
+ T* get_data()
+ {
+ return &data[0];
+ }
+
private:
array<T> data;
};
diff --git a/intern/cycles/device/device_multi.cpp b/intern/cycles/device/device_multi.cpp
index 7f055c79491..8fb841b2b0d 100644
--- a/intern/cycles/device/device_multi.cpp
+++ b/intern/cycles/device/device_multi.cpp
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#include <stdlib.h>
@@ -25,6 +25,7 @@
#include "util_foreach.h"
#include "util_list.h"
+#include "util_logging.h"
#include "util_map.h"
#include "util_time.h"
@@ -88,10 +89,10 @@ public:
return error_msg;
}
- bool load_kernels(bool experimental)
+ bool load_kernels(const DeviceRequestedFeatures& requested_features)
{
foreach(SubDevice& sub, devices)
- if(!sub.device->load_kernels(experimental))
+ if(!sub.device->load_kernels(requested_features))
return false;
return true;
@@ -168,11 +169,17 @@ public:
sub.device->const_copy_to(name, host, size);
}
- void tex_alloc(const char *name, device_memory& mem, InterpolationType interpolation, bool periodic)
+ void tex_alloc(const char *name,
+ device_memory& mem,
+ InterpolationType
+ interpolation,
+ ExtensionType extension)
{
+ VLOG(1) << "Texture allocate: " << name << ", " << mem.memory_size() << " bytes.";
+
foreach(SubDevice& sub, devices) {
mem.device_pointer = 0;
- sub.device->tex_alloc(name, mem, interpolation, periodic);
+ sub.device->tex_alloc(name, mem, interpolation, extension);
sub.ptr_map[unique_ptr] = mem.device_pointer;
}
@@ -233,7 +240,7 @@ public:
mem.device_pointer = tmp;
}
- void draw_pixels(device_memory& rgba, int y, int w, int h, int dy, int width, int height, bool transparent,
+ void draw_pixels(device_memory& rgba, int y, int w, int h, int dx, int dy, int width, int height, bool transparent,
const DeviceDrawParams &draw_params)
{
device_ptr tmp = rgba.device_pointer;
@@ -248,7 +255,7 @@ public:
/* adjust math for w/width */
rgba.device_pointer = sub.ptr_map[tmp];
- sub.device->draw_pixels(rgba, sy, w, sh, sdy, width, sheight, transparent, draw_params);
+ sub.device->draw_pixels(rgba, sy, w, sh, dx, sdy, width, sheight, transparent, draw_params);
i++;
}
diff --git a/intern/cycles/device/device_network.cpp b/intern/cycles/device/device_network.cpp
index dca9bf29e70..afa35224aba 100644
--- a/intern/cycles/device/device_network.cpp
+++ b/intern/cycles/device/device_network.cpp
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#include "device.h"
@@ -19,6 +19,7 @@
#include "device_network.h"
#include "util_foreach.h"
+#include "util_logging.h"
#if defined(WITH_NETWORK)
@@ -162,8 +163,13 @@ public:
snd.write_buffer(host, size);
}
- void tex_alloc(const char *name, device_memory& mem, InterpolationType interpolation, bool periodic)
+ void tex_alloc(const char *name,
+ device_memory& mem,
+ InterpolationType interpolation,
+ ExtensionType extension)
{
+ VLOG(1) << "Texture allocate: " << name << ", " << mem.memory_size() << " bytes.";
+
thread_scoped_lock lock(rpc_lock);
mem.device_pointer = ++mem_counter;
@@ -175,7 +181,7 @@ public:
snd.add(name_string);
snd.add(mem);
snd.add(interpolation);
- snd.add(periodic);
+ snd.add(extension);
snd.write();
snd.write_buffer((void*)mem.data_pointer, mem.memory_size());
}
@@ -194,7 +200,7 @@ public:
}
}
- bool load_kernels(bool experimental)
+ bool load_kernels(const DeviceRequestedFeatures& requested_features)
{
if(error_func.have_error())
return false;
@@ -202,7 +208,10 @@ public:
thread_scoped_lock lock(rpc_lock);
RPCSend snd(socket, &error_func, "load_kernels");
- snd.add(experimental);
+ snd.add(requested_features.experimental);
+ snd.add(requested_features.max_closure);
+ snd.add(requested_features.max_nodes_group);
+ snd.add(requested_features.nodes_features);
snd.write();
bool result;
@@ -269,7 +278,7 @@ public:
lock.unlock();
TileList::iterator it = tile_list_find(the_tiles, tile);
- if (it != the_tiles.end()) {
+ if(it != the_tiles.end()) {
tile.buffers = it->buffers;
the_tiles.erase(it);
}
@@ -565,13 +574,13 @@ protected:
network_device_memory mem;
string name;
InterpolationType interpolation;
- bool periodic;
+ ExtensionType extension_type;
device_ptr client_pointer;
rcv.read(name);
rcv.read(mem);
rcv.read(interpolation);
- rcv.read(periodic);
+ rcv.read(extension_type);
lock.unlock();
client_pointer = mem.device_pointer;
@@ -587,7 +596,7 @@ protected:
rcv.read_buffer((uint8_t*)mem.data_pointer, data_size);
- device->tex_alloc(name.c_str(), mem, interpolation, periodic);
+ device->tex_alloc(name.c_str(), mem, interpolation, extension_type);
pointer_mapping_insert(client_pointer, mem.device_pointer);
}
@@ -605,11 +614,14 @@ protected:
device->tex_free(mem);
}
else if(rcv.name == "load_kernels") {
- bool experimental;
- rcv.read(experimental);
+ DeviceRequestedFeatures requested_features;
+ rcv.read(requested_features.experimental);
+ rcv.read(requested_features.max_closure);
+ rcv.read(requested_features.max_nodes_group);
+ rcv.read(requested_features.nodes_features);
bool result;
- result = device->load_kernels(experimental);
+ result = device->load_kernels(requested_features);
RPCSend snd(socket, &error_func, "load_kernels");
snd.add(result);
snd.write();
diff --git a/intern/cycles/device/device_network.h b/intern/cycles/device/device_network.h
index 893841d1da7..2e751f6697f 100644
--- a/intern/cycles/device/device_network.h
+++ b/intern/cycles/device/device_network.h
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#ifndef __DEVICE_NETWORK_H__
diff --git a/intern/cycles/device/device_opencl.cpp b/intern/cycles/device/device_opencl.cpp
index d950d084cd4..a7157e2b041 100644
--- a/intern/cycles/device/device_opencl.cpp
+++ b/intern/cycles/device/device_opencl.cpp
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#ifdef WITH_OPENCL
@@ -20,14 +20,15 @@
#include <stdlib.h>
#include <string.h>
+#include "clew.h"
+
#include "device.h"
#include "device_intern.h"
#include "buffers.h"
-#include "clew.h"
-
#include "util_foreach.h"
+#include "util_logging.h"
#include "util_map.h"
#include "util_math.h"
#include "util_md5.h"
@@ -39,11 +40,55 @@ CCL_NAMESPACE_BEGIN
#define CL_MEM_PTR(p) ((cl_mem)(uintptr_t)(p))
-static cl_device_type opencl_device_type()
+/* Macro declarations used with split kernel */
+
+/* Macro to enable/disable work-stealing */
+#define __WORK_STEALING__
+
+#define SPLIT_KERNEL_LOCAL_SIZE_X 64
+#define SPLIT_KERNEL_LOCAL_SIZE_Y 1
+
+/* This value may be tuned according to the scene we are rendering.
+ *
+ * Modifying PATH_ITER_INC_FACTOR value proportional to number of expected
+ * ray-bounces will improve performance.
+ */
+#define PATH_ITER_INC_FACTOR 8
+
+/* When allocate global memory in chunks. We may not be able to
+ * allocate exactly "CL_DEVICE_MAX_MEM_ALLOC_SIZE" bytes in chunks;
+ * Since some bytes may be needed for aligning chunks of memory;
+ * This is the amount of memory that we dedicate for that purpose.
+ */
+#define DATA_ALLOCATION_MEM_FACTOR 5000000 //5MB
+
+struct OpenCLPlatformDevice {
+ OpenCLPlatformDevice(cl_platform_id platform_id,
+ const string& platform_name,
+ cl_device_id device_id,
+ cl_device_type device_type,
+ const string& device_name)
+ : platform_id(platform_id),
+ platform_name(platform_name),
+ device_id(device_id),
+ device_type(device_type),
+ device_name(device_name) {}
+ cl_platform_id platform_id;
+ string platform_name;
+ cl_device_id device_id;
+ cl_device_type device_type;
+ string device_name;
+};
+
+namespace {
+
+cl_device_type opencl_device_type()
{
char *device = getenv("CYCLES_OPENCL_TEST");
if(device) {
+ if(strcmp(device, "NONE") == 0)
+ return 0;
if(strcmp(device, "ALL") == 0)
return CL_DEVICE_TYPE_ALL;
else if(strcmp(device, "DEFAULT") == 0)
@@ -59,68 +104,277 @@ static cl_device_type opencl_device_type()
return CL_DEVICE_TYPE_ALL;
}
-static bool opencl_kernel_use_debug()
+bool opencl_kernel_use_debug()
{
return (getenv("CYCLES_OPENCL_DEBUG") != NULL);
}
-static bool opencl_kernel_use_advanced_shading(const string& platform)
+bool opencl_kernel_use_advanced_shading(const string& platform)
{
/* keep this in sync with kernel_types.h! */
if(platform == "NVIDIA CUDA")
return true;
else if(platform == "Apple")
- return false;
+ return true;
else if(platform == "AMD Accelerated Parallel Processing")
- return false;
+ return true;
else if(platform == "Intel(R) OpenCL")
return true;
+ /* Make sure officially unsupported OpenCL platforms
+ * does not set up to use advanced shading.
+ */
+ return false;
+}
+bool opencl_kernel_use_split(const string& platform_name,
+ const cl_device_type device_type)
+{
+ if(getenv("CYCLES_OPENCL_SPLIT_KERNEL_TEST") != NULL) {
+ return true;
+ }
+ /* TODO(sergey): Replace string lookups with more enum-like API,
+ * similar to device/vendor checks blender's gpu.
+ */
+ if(platform_name == "AMD Accelerated Parallel Processing" &&
+ device_type == CL_DEVICE_TYPE_GPU)
+ {
+ return true;
+ }
return false;
}
-static string opencl_kernel_build_options(const string& platform, const string *debug_src = NULL)
+bool opencl_device_supported(const string& platform_name,
+ const cl_device_id device_id)
{
- string build_options = " -cl-fast-relaxed-math ";
+ cl_device_type device_type;
+ clGetDeviceInfo(device_id,
+ CL_DEVICE_TYPE,
+ sizeof(cl_device_type),
+ &device_type,
+ NULL);
+ if(platform_name == "AMD Accelerated Parallel Processing" &&
+ device_type == CL_DEVICE_TYPE_GPU)
+ {
+ return true;
+ }
+ if(platform_name == "Apple" && device_type == CL_DEVICE_TYPE_GPU) {
+ return true;
+ }
+ return false;
+}
- if(platform == "NVIDIA CUDA")
- build_options += "-D__KERNEL_OPENCL_NVIDIA__ -cl-nv-maxrregcount=32 -cl-nv-verbose ";
+bool opencl_platform_version_check(cl_platform_id platform,
+ string *error = NULL)
+{
+ const int req_major = 1, req_minor = 1;
+ int major, minor;
+ char version[256];
+ clGetPlatformInfo(platform,
+ CL_PLATFORM_VERSION,
+ sizeof(version),
+ &version,
+ NULL);
+ if(sscanf(version, "OpenCL %d.%d", &major, &minor) < 2) {
+ if(error != NULL) {
+ *error = string_printf("OpenCL: failed to parse platform version string (%s).", version);
+ }
+ return false;
+ }
+ if(!((major == req_major && minor >= req_minor) || (major > req_major))) {
+ if(error != NULL) {
+ *error = string_printf("OpenCL: platform version 1.1 or later required, found %d.%d", major, minor);
+ }
+ return false;
+ }
+ if(error != NULL) {
+ *error = "";
+ }
+ return true;
+}
- else if(platform == "Apple")
- build_options += "-D__KERNEL_OPENCL_APPLE__ ";
+bool opencl_device_version_check(cl_device_id device,
+ string *error = NULL)
+{
+ const int req_major = 1, req_minor = 1;
+ int major, minor;
+ char version[256];
+ clGetDeviceInfo(device,
+ CL_DEVICE_OPENCL_C_VERSION,
+ sizeof(version),
+ &version,
+ NULL);
+ if(sscanf(version, "OpenCL C %d.%d", &major, &minor) < 2) {
+ if(error != NULL) {
+ *error = string_printf("OpenCL: failed to parse OpenCL C version string (%s).", version);
+ }
+ return false;
+ }
+ if(!((major == req_major && minor >= req_minor) || (major > req_major))) {
+ if(error != NULL) {
+ *error = string_printf("OpenCL: C version 1.1 or later required, found %d.%d", major, minor);
+ }
+ return false;
+ }
+ if(error != NULL) {
+ *error = "";
+ }
+ return true;
+}
- else if(platform == "AMD Accelerated Parallel Processing")
- build_options += "-D__KERNEL_OPENCL_AMD__ ";
+void opencl_get_usable_devices(vector<OpenCLPlatformDevice> *usable_devices)
+{
+ const bool force_all_platforms =
+ (getenv("CYCLES_OPENCL_TEST") != NULL) ||
+ (getenv("CYCLES_OPENCL_SPLIT_KERNEL_TEST")) != NULL;
+ const cl_device_type device_type = opencl_device_type();
+ static bool first_time = true;
+#define FIRST_VLOG(severity) if(first_time) VLOG(severity)
+
+ usable_devices->clear();
+
+ if(device_type == 0) {
+ FIRST_VLOG(2) << "OpenCL devices are forced to be disabled.";
+ first_time = false;
+ return;
+ }
- else if(platform == "Intel(R) OpenCL") {
- build_options += "-D__KERNEL_OPENCL_INTEL_CPU__";
+ vector<cl_device_id> device_ids;
+ cl_uint num_devices = 0;
+ vector<cl_platform_id> platform_ids;
+ cl_uint num_platforms = 0;
- /* options for gdb source level kernel debugging. this segfaults on linux currently */
- if(opencl_kernel_use_debug() && debug_src)
- build_options += "-g -s \"" + *debug_src + "\"";
+ /* Get devices. */
+ if(clGetPlatformIDs(0, NULL, &num_platforms) != CL_SUCCESS ||
+ num_platforms == 0)
+ {
+ FIRST_VLOG(2) << "No OpenCL platforms were found.";
+ first_time = false;
+ return;
}
-
- if(opencl_kernel_use_debug())
- build_options += "-D__KERNEL_OPENCL_DEBUG__ ";
-
- return build_options;
+ platform_ids.resize(num_platforms);
+ if(clGetPlatformIDs(num_platforms, &platform_ids[0], NULL) != CL_SUCCESS) {
+ FIRST_VLOG(2) << "Failed to fetch platform IDs from the driver..";
+ first_time = false;
+ return;
+ }
+ /* Devices are numbered consecutively across platforms. */
+ for(int platform = 0; platform < num_platforms; platform++) {
+ cl_platform_id platform_id = platform_ids[platform];
+ char pname[256];
+ if(clGetPlatformInfo(platform_id,
+ CL_PLATFORM_NAME,
+ sizeof(pname),
+ &pname,
+ NULL) != CL_SUCCESS)
+ {
+ FIRST_VLOG(2) << "Failed to get platform name, ignoring.";
+ continue;
+ }
+ string platform_name = pname;
+ FIRST_VLOG(2) << "Enumerating devices for platform "
+ << platform_name << ".";
+ if(!opencl_platform_version_check(platform_id)) {
+ FIRST_VLOG(2) << "Ignoring platform " << platform_name
+ << " due to too old compiler version.";
+ continue;
+ }
+ num_devices = 0;
+ if(clGetDeviceIDs(platform_id,
+ device_type,
+ 0,
+ NULL,
+ &num_devices) != CL_SUCCESS || num_devices == 0)
+ {
+ FIRST_VLOG(2) << "Ignoring platform " << platform_name
+ << ", failed to fetch number of devices.";
+ continue;
+ }
+ device_ids.resize(num_devices);
+ if(clGetDeviceIDs(platform_id,
+ device_type,
+ num_devices,
+ &device_ids[0],
+ NULL) != CL_SUCCESS)
+ {
+ FIRST_VLOG(2) << "Ignoring platform " << platform_name
+ << ", failed to fetch devices list.";
+ continue;
+ }
+ for(int num = 0; num < num_devices; num++) {
+ cl_device_id device_id = device_ids[num];
+ char device_name[1024] = "\0";
+ if(clGetDeviceInfo(device_id,
+ CL_DEVICE_NAME,
+ sizeof(device_name),
+ &device_name,
+ NULL) != CL_SUCCESS)
+ {
+ FIRST_VLOG(2) << "Failed to fetch device name, ignoring.";
+ continue;
+ }
+ if(!opencl_device_version_check(device_id)) {
+ FIRST_VLOG(2) << "Ignoring device " << device_name
+ << " due to old compiler version.";
+ continue;
+ }
+ if(force_all_platforms ||
+ opencl_device_supported(platform_name, device_id))
+ {
+ cl_device_type device_type;
+ if(clGetDeviceInfo(device_id,
+ CL_DEVICE_TYPE,
+ sizeof(cl_device_type),
+ &device_type,
+ NULL) != CL_SUCCESS)
+ {
+ FIRST_VLOG(2) << "Ignoring device " << device_name
+ << ", failed to fetch device type.";
+ continue;
+ }
+ FIRST_VLOG(2) << "Adding new device " << device_name << ".";
+ usable_devices->push_back(OpenCLPlatformDevice(platform_id,
+ platform_name,
+ device_id,
+ device_type,
+ device_name));
+ }
+ else {
+ FIRST_VLOG(2) << "Ignoring device " << device_name
+ << ", not officially supported yet.";
+ }
+ }
+ }
+ first_time = false;
}
-/* thread safe cache for contexts and programs */
+} /* namespace */
+
+/* Thread safe cache for contexts and programs.
+ *
+ * TODO(sergey): Make it more generous, so it can contain any type of program
+ * without hardcoding possible program types in the slot.
+ */
class OpenCLCache
{
struct Slot
{
thread_mutex *mutex;
cl_context context;
- cl_program program;
-
- Slot() : mutex(NULL), context(NULL), program(NULL) {}
-
- Slot(const Slot &rhs)
- : mutex(rhs.mutex)
- , context(rhs.context)
- , program(rhs.program)
+ /* cl_program for shader, bake, film_convert kernels (used in OpenCLDeviceBase) */
+ cl_program ocl_dev_base_program;
+ /* cl_program for megakernel (used in OpenCLDeviceMegaKernel) */
+ cl_program ocl_dev_megakernel_program;
+
+ Slot() : mutex(NULL),
+ context(NULL),
+ ocl_dev_base_program(NULL),
+ ocl_dev_megakernel_program(NULL) {}
+
+ Slot(const Slot& rhs)
+ : mutex(rhs.mutex),
+ context(rhs.context),
+ ocl_dev_base_program(rhs.ocl_dev_base_program),
+ ocl_dev_megakernel_program(rhs.ocl_dev_megakernel_program)
{
/* copy can only happen in map insert, assert that */
assert(mutex == NULL);
@@ -167,12 +421,14 @@ class OpenCLCache
* will be holding a lock for the cache. slot_locker should refer to a
* default constructed thread_scoped_lock */
template<typename T>
- static T get_something(cl_platform_id platform, cl_device_id device,
- T Slot::*member, thread_scoped_lock &slot_locker)
+ static T get_something(cl_platform_id platform,
+ cl_device_id device,
+ T Slot::*member,
+ thread_scoped_lock& slot_locker)
{
assert(platform != NULL);
- OpenCLCache &self = global_instance();
+ OpenCLCache& self = global_instance();
thread_scoped_lock cache_lock(self.cache_lock);
@@ -205,8 +461,11 @@ class OpenCLCache
/* store something in the cache. you MUST have tried to get the item before storing to it */
template<typename T>
- static void store_something(cl_platform_id platform, cl_device_id device, T thing,
- T Slot::*member, thread_scoped_lock &slot_locker)
+ static void store_something(cl_platform_id platform,
+ cl_device_id device,
+ T thing,
+ T Slot::*member,
+ thread_scoped_lock& slot_locker)
{
assert(platform != NULL);
assert(device != NULL);
@@ -231,11 +490,21 @@ class OpenCLCache
}
public:
+
+ enum ProgramName {
+ OCL_DEV_BASE_PROGRAM,
+ OCL_DEV_MEGAKERNEL_PROGRAM,
+ };
+
/* see get_something comment */
- static cl_context get_context(cl_platform_id platform, cl_device_id device,
- thread_scoped_lock &slot_locker)
+ static cl_context get_context(cl_platform_id platform,
+ cl_device_id device,
+ thread_scoped_lock& slot_locker)
{
- cl_context context = get_something<cl_context>(platform, device, &Slot::context, slot_locker);
+ cl_context context = get_something<cl_context>(platform,
+ device,
+ &Slot::context,
+ slot_locker);
if(!context)
return NULL;
@@ -249,10 +518,31 @@ public:
}
/* see get_something comment */
- static cl_program get_program(cl_platform_id platform, cl_device_id device,
- thread_scoped_lock &slot_locker)
+ static cl_program get_program(cl_platform_id platform,
+ cl_device_id device,
+ ProgramName program_name,
+ thread_scoped_lock& slot_locker)
{
- cl_program program = get_something<cl_program>(platform, device, &Slot::program, slot_locker);
+ cl_program program = NULL;
+
+ switch(program_name) {
+ case OCL_DEV_BASE_PROGRAM:
+ /* Get program related to OpenCLDeviceBase */
+ program = get_something<cl_program>(platform,
+ device,
+ &Slot::ocl_dev_base_program,
+ slot_locker);
+ break;
+ case OCL_DEV_MEGAKERNEL_PROGRAM:
+ /* Get program related to megakernel */
+ program = get_something<cl_program>(platform,
+ device,
+ &Slot::ocl_dev_megakernel_program,
+ slot_locker);
+ break;
+ default:
+ assert(!"Invalid program name");
+ }
if(!program)
return NULL;
@@ -266,10 +556,16 @@ public:
}
/* see store_something comment */
- static void store_context(cl_platform_id platform, cl_device_id device, cl_context context,
- thread_scoped_lock &slot_locker)
+ static void store_context(cl_platform_id platform,
+ cl_device_id device,
+ cl_context context,
+ thread_scoped_lock& slot_locker)
{
- store_something<cl_context>(platform, device, context, &Slot::context, slot_locker);
+ store_something<cl_context>(platform,
+ device,
+ context,
+ &Slot::context,
+ slot_locker);
/* increment reference count in OpenCL.
* The caller is going to release the object when done with it. */
@@ -279,28 +575,51 @@ public:
}
/* see store_something comment */
- static void store_program(cl_platform_id platform, cl_device_id device, cl_program program,
- thread_scoped_lock &slot_locker)
+ static void store_program(cl_platform_id platform,
+ cl_device_id device,
+ cl_program program,
+ ProgramName program_name,
+ thread_scoped_lock& slot_locker)
{
- store_something<cl_program>(platform, device, program, &Slot::program, slot_locker);
+ switch (program_name) {
+ case OCL_DEV_BASE_PROGRAM:
+ store_something<cl_program>(platform,
+ device,
+ program,
+ &Slot::ocl_dev_base_program,
+ slot_locker);
+ break;
+ case OCL_DEV_MEGAKERNEL_PROGRAM:
+ store_something<cl_program>(platform,
+ device,
+ program,
+ &Slot::ocl_dev_megakernel_program,
+ slot_locker);
+ break;
+ default:
+ assert(!"Invalid program name\n");
+ return;
+ }
- /* increment reference count in OpenCL.
- * The caller is going to release the object when done with it. */
+ /* Increment reference count in OpenCL.
+ * The caller is going to release the object when done with it.
+ */
cl_int ciErr = clRetainProgram(program);
assert(ciErr == CL_SUCCESS);
(void)ciErr;
}
- /* discard all cached contexts and programs
- * the parameter is a temporary workaround. See OpenCLCache::~OpenCLCache */
+ /* Discard all cached contexts and programs. */
static void flush()
{
OpenCLCache &self = global_instance();
thread_scoped_lock cache_lock(self.cache_lock);
foreach(CacheMap::value_type &item, self.cache) {
- if(item.second.program != NULL)
- clReleaseProgram(item.second.program);
+ if(item.second.ocl_dev_base_program != NULL)
+ clReleaseProgram(item.second.ocl_dev_base_program);
+ if(item.second.ocl_dev_megakernel_program != NULL)
+ clReleaseProgram(item.second.ocl_dev_megakernel_program);
if(item.second.context != NULL)
clReleaseContext(item.second.context);
}
@@ -309,7 +628,7 @@ public:
}
};
-class OpenCLDevice : public Device
+class OpenCLDeviceBase : public Device
{
public:
DedicatedTaskPool task_pool;
@@ -318,7 +637,6 @@ public:
cl_platform_id cpPlatform;
cl_device_id cdDevice;
cl_program cpProgram;
- cl_kernel ckPathTraceKernel;
cl_kernel ckFilmConvertByteKernel;
cl_kernel ckFilmConvertHalfFloatKernel;
cl_kernel ckShaderKernel;
@@ -380,7 +698,7 @@ public:
}
}
- OpenCLDevice(DeviceInfo& info, Stats &stats, bool background_)
+ OpenCLDeviceBase(DeviceInfo& info, Stats &stats, bool background_)
: Device(info, stats, background_)
{
cpPlatform = NULL;
@@ -388,7 +706,6 @@ public:
cxContext = NULL;
cqCommandQueue = NULL;
cpProgram = NULL;
- ckPathTraceKernel = NULL;
ckFilmConvertByteKernel = NULL;
ckFilmConvertHalfFloatKernel = NULL;
ckShaderKernel = NULL;
@@ -396,71 +713,20 @@ public:
null_mem = 0;
device_initialized = false;
- /* setup platform */
- cl_uint num_platforms;
-
- ciErr = clGetPlatformIDs(0, NULL, &num_platforms);
- if(opencl_error(ciErr))
- return;
-
- if(num_platforms == 0) {
- opencl_error("OpenCL: no platforms found.");
- return;
- }
-
- vector<cl_platform_id> platforms(num_platforms, NULL);
-
- ciErr = clGetPlatformIDs(num_platforms, &platforms[0], NULL);
- if(opencl_error(ciErr)) {
- fprintf(stderr, "clGetPlatformIDs failed \n");
- return;
- }
-
- int num_base = 0;
- int total_devices = 0;
-
- for (int platform = 0; platform < num_platforms; platform++) {
- cl_uint num_devices;
-
- if(opencl_error(clGetDeviceIDs(platforms[platform], opencl_device_type(), 0, NULL, &num_devices)))
- return;
-
- total_devices += num_devices;
-
- if(info.num - num_base >= num_devices) {
- /* num doesn't refer to a device in this platform */
- num_base += num_devices;
- continue;
- }
-
- /* device is in this platform */
- cpPlatform = platforms[platform];
-
- /* get devices */
- vector<cl_device_id> device_ids(num_devices, NULL);
-
- if(opencl_error(clGetDeviceIDs(cpPlatform, opencl_device_type(), num_devices, &device_ids[0], NULL))) {
- fprintf(stderr, "clGetDeviceIDs failed \n");
- return;
- }
-
- cdDevice = device_ids[info.num - num_base];
-
- char name[256];
- clGetPlatformInfo(cpPlatform, CL_PLATFORM_NAME, sizeof(name), &name, NULL);
- platform_name = name;
-
- break;
- }
-
- if(total_devices == 0) {
+ vector<OpenCLPlatformDevice> usable_devices;
+ opencl_get_usable_devices(&usable_devices);
+ if(usable_devices.size() == 0) {
opencl_error("OpenCL: no devices found.");
return;
}
- else if(!cdDevice) {
- opencl_error("OpenCL: specified device not found.");
- return;
- }
+ assert(info.num < usable_devices.size());
+ OpenCLPlatformDevice& platform_device = usable_devices[info.num];
+ cpPlatform = platform_device.platform_id;
+ cdDevice = platform_device.device_id;
+ platform_name = platform_device.platform_name;
+ VLOG(2) << "Creating new Cycles device for OpenCL platform "
+ << platform_name << ", device "
+ << platform_device.device_name << ".";
{
/* try to use cached context */
@@ -496,12 +762,12 @@ public:
if(opencl_error(ciErr))
return;
- fprintf(stderr,"Device init succes\n");
+ fprintf(stderr, "Device init success\n");
device_initialized = true;
}
static void CL_CALLBACK context_notify_callback(const char *err_info,
- const void *private_info, size_t cb, void *user_data)
+ const void * /*private_info*/, size_t /*cb*/, void *user_data)
{
char name[256];
clGetDeviceInfo((cl_device_id)user_data, CL_DEVICE_NAME, sizeof(name), &name, NULL);
@@ -511,38 +777,23 @@ public:
bool opencl_version_check()
{
- char version[256];
-
- int major, minor, req_major = 1, req_minor = 1;
-
- clGetPlatformInfo(cpPlatform, CL_PLATFORM_VERSION, sizeof(version), &version, NULL);
-
- if(sscanf(version, "OpenCL %d.%d", &major, &minor) < 2) {
- opencl_error(string_printf("OpenCL: failed to parse platform version string (%s).", version));
+ string error;
+ if(!opencl_platform_version_check(cpPlatform, &error)) {
+ opencl_error(error);
return false;
}
-
- if(!((major == req_major && minor >= req_minor) || (major > req_major))) {
- opencl_error(string_printf("OpenCL: platform version 1.1 or later required, found %d.%d", major, minor));
- return false;
- }
-
- clGetDeviceInfo(cdDevice, CL_DEVICE_OPENCL_C_VERSION, sizeof(version), &version, NULL);
-
- if(sscanf(version, "OpenCL C %d.%d", &major, &minor) < 2) {
- opencl_error(string_printf("OpenCL: failed to parse OpenCL C version string (%s).", version));
+ if(!opencl_device_version_check(cdDevice, &error)) {
+ opencl_error(error);
return false;
}
-
- if(!((major == req_major && minor >= req_minor) || (major > req_major))) {
- opencl_error(string_printf("OpenCL: C version 1.1 or later required, found %d.%d", major, minor));
- return false;
- }
-
return true;
}
- bool load_binary(const string& kernel_path, const string& clbin, const string *debug_src = NULL)
+ bool load_binary(const string& /*kernel_path*/,
+ const string& clbin,
+ string custom_kernel_build_options,
+ cl_program *program,
+ const string *debug_src = NULL)
{
/* read binary into memory */
vector<uint8_t> binary;
@@ -557,7 +808,7 @@ public:
size_t size = binary.size();
const uint8_t *bytes = &binary[0];
- cpProgram = clCreateProgramWithBinary(cxContext, 1, &cdDevice,
+ *program = clCreateProgramWithBinary(cxContext, 1, &cdDevice,
&size, &bytes, &status, &ciErr);
if(opencl_error(status) || opencl_error(ciErr)) {
@@ -565,16 +816,16 @@ public:
return false;
}
- if(!build_kernel(kernel_path, debug_src))
+ if(!build_kernel(program, custom_kernel_build_options, debug_src))
return false;
return true;
}
- bool save_binary(const string& clbin)
+ bool save_binary(cl_program *program, const string& clbin)
{
size_t size = 0;
- clGetProgramInfo(cpProgram, CL_PROGRAM_BINARY_SIZES, sizeof(size_t), &size, NULL);
+ clGetProgramInfo(*program, CL_PROGRAM_BINARY_SIZES, sizeof(size_t), &size, NULL);
if(!size)
return false;
@@ -582,7 +833,7 @@ public:
vector<uint8_t> binary(size);
uint8_t *bytes = &binary[0];
- clGetProgramInfo(cpProgram, CL_PROGRAM_BINARIES, sizeof(uint8_t*), &bytes, NULL);
+ clGetProgramInfo(*program, CL_PROGRAM_BINARIES, sizeof(uint8_t*), &bytes, NULL);
if(!path_write_binary(clbin, binary)) {
opencl_error(string_printf("OpenCL failed to write cached binary %s.", clbin.c_str()));
@@ -592,24 +843,30 @@ public:
return true;
}
- bool build_kernel(const string& kernel_path, const string *debug_src = NULL)
+ bool build_kernel(cl_program *kernel_program,
+ string custom_kernel_build_options,
+ const string *debug_src = NULL)
{
- string build_options = opencl_kernel_build_options(platform_name, debug_src);
-
- ciErr = clBuildProgram(cpProgram, 0, NULL, build_options.c_str(), NULL, NULL);
+ string build_options;
+ build_options = kernel_build_options(debug_src) + custom_kernel_build_options;
+
+ ciErr = clBuildProgram(*kernel_program, 0, NULL, build_options.c_str(), NULL, NULL);
/* show warnings even if build is successful */
size_t ret_val_size = 0;
- clGetProgramBuildInfo(cpProgram, cdDevice, CL_PROGRAM_BUILD_LOG, 0, NULL, &ret_val_size);
+ clGetProgramBuildInfo(*kernel_program, cdDevice, CL_PROGRAM_BUILD_LOG, 0, NULL, &ret_val_size);
if(ret_val_size > 1) {
- vector<char> build_log(ret_val_size+1);
- clGetProgramBuildInfo(cpProgram, cdDevice, CL_PROGRAM_BUILD_LOG, ret_val_size, &build_log[0], NULL);
+ vector<char> build_log(ret_val_size + 1);
+ clGetProgramBuildInfo(*kernel_program, cdDevice, CL_PROGRAM_BUILD_LOG, ret_val_size, &build_log[0], NULL);
build_log[ret_val_size] = '\0';
- fprintf(stderr, "OpenCL kernel build output:\n");
- fprintf(stderr, "%s\n", &build_log[0]);
+ /* Skip meaningless empty output from the NVidia compiler. */
+ if(!(ret_val_size == 2 && build_log[0] == '\n')) {
+ fprintf(stderr, "OpenCL kernel build output:\n");
+ fprintf(stderr, "%s\n", &build_log[0]);
+ }
}
if(ciErr != CL_SUCCESS) {
@@ -620,12 +877,15 @@ public:
return true;
}
- bool compile_kernel(const string& kernel_path, const string& kernel_md5, const string *debug_src = NULL)
+ bool compile_kernel(const string& kernel_path,
+ string source,
+ string custom_kernel_build_options,
+ cl_program *kernel_program,
+ const string *debug_src = NULL)
{
/* we compile kernels consisting of many files. unfortunately opencl
* kernel caches do not seem to recognize changes in included files.
* so we force recompile on changes by adding the md5 hash of all files */
- string source = "#include \"kernel.cl\" // " + kernel_md5 + "\n";
source = path_source_replace_includes(source, kernel_path);
if(debug_src)
@@ -634,15 +894,19 @@ public:
size_t source_len = source.size();
const char *source_str = source.c_str();
- cpProgram = clCreateProgramWithSource(cxContext, 1, &source_str, &source_len, &ciErr);
+ *kernel_program = clCreateProgramWithSource(cxContext, 1, &source_str, &source_len, &ciErr);
if(opencl_error(ciErr))
return false;
double starttime = time_dt();
printf("Compiling OpenCL kernel ...\n");
+ /* TODO(sergey): Report which kernel is being compiled
+ * as well (megakernel or which of split kernels etc..).
+ */
+ printf("Build flags: %s\n", custom_kernel_build_options.c_str());
- if(!build_kernel(kernel_path, debug_src))
+ if(!build_kernel(kernel_program, custom_kernel_build_options, debug_src))
return false;
printf("Kernel compilation finished in %.2lfs.\n", time_dt() - starttime);
@@ -650,7 +914,7 @@ public:
return true;
}
- string device_md5_hash()
+ string device_md5_hash(string kernel_custom_build_options = "")
{
MD5Hash md5;
char version[256], driver[256], name[256], vendor[256];
@@ -665,90 +929,120 @@ public:
md5.append((uint8_t*)name, strlen(name));
md5.append((uint8_t*)driver, strlen(driver));
- string options = opencl_kernel_build_options(platform_name);
+ string options = kernel_build_options();
+ options += kernel_custom_build_options;
md5.append((uint8_t*)options.c_str(), options.size());
return md5.get_hex();
}
- bool load_kernels(bool experimental)
+ bool load_kernels(const DeviceRequestedFeatures& requested_features)
{
- /* verify if device was initialized */
+ /* Verify if device was initialized. */
if(!device_initialized) {
fprintf(stderr, "OpenCL: failed to initialize device.\n");
return false;
}
- /* try to use cached kernel */
+ /* Try to use cached kernel. */
thread_scoped_lock cache_locker;
- cpProgram = OpenCLCache::get_program(cpPlatform, cdDevice, cache_locker);
+ cpProgram = load_cached_kernel(requested_features,
+ OpenCLCache::OCL_DEV_BASE_PROGRAM,
+ cache_locker);
if(!cpProgram) {
- /* verify we have right opencl version */
+ VLOG(2) << "No cached OpenCL kernel.";
+
+ /* Verify we have right opencl version. */
if(!opencl_version_check())
return false;
- /* md5 hash to detect changes */
+ string build_flags = build_options_for_base_program(requested_features);
+
+ /* Calculate md5 hashes to detect changes. */
string kernel_path = path_get("kernel");
string kernel_md5 = path_files_md5_hash(kernel_path);
- string device_md5 = device_md5_hash();
-
- /* path to cached binary */
- string clbin = string_printf("cycles_kernel_%s_%s.clbin", device_md5.c_str(), kernel_md5.c_str());
+ string device_md5 = device_md5_hash(build_flags);
+
+ /* Path to cached binary.
+ *
+ * TODO(sergey): Seems we could de-duplicate all this string_printf()
+ * calls with some utility function which will give file name for a
+ * given hashes..
+ */
+ string clbin = string_printf("cycles_kernel_%s_%s.clbin",
+ device_md5.c_str(),
+ kernel_md5.c_str());
clbin = path_user_get(path_join("cache", clbin));
/* path to preprocessed source for debugging */
string clsrc, *debug_src = NULL;
if(opencl_kernel_use_debug()) {
- clsrc = string_printf("cycles_kernel_%s_%s.cl", device_md5.c_str(), kernel_md5.c_str());
+ clsrc = string_printf("cycles_kernel_%s_%s.cl",
+ device_md5.c_str(),
+ kernel_md5.c_str());
clsrc = path_user_get(path_join("cache", clsrc));
debug_src = &clsrc;
}
- /* if exists already, try use it */
- if(path_exists(clbin) && load_binary(kernel_path, clbin, debug_src)) {
- /* kernel loaded from binary */
+ /* If binary kernel exists already, try use it. */
+ if(path_exists(clbin) && load_binary(kernel_path,
+ clbin,
+ build_flags,
+ &cpProgram)) {
+ /* Kernel loaded from binary, nothing to do. */
+ VLOG(2) << "Loaded kernel from " << clbin << ".";
}
else {
- /* if does not exist or loading binary failed, compile kernel */
- if(!compile_kernel(kernel_path, kernel_md5, debug_src))
+ VLOG(2) << "Kernel file " << clbin << " either doesn't exist or failed to be loaded by driver.";
+ string init_kernel_source = "#include \"kernels/opencl/kernel.cl\" // " + kernel_md5 + "\n";
+
+ /* If does not exist or loading binary failed, compile kernel. */
+ if(!compile_kernel(kernel_path,
+ init_kernel_source,
+ build_flags,
+ &cpProgram,
+ debug_src))
+ {
return false;
+ }
- /* save binary for reuse */
- if(!save_binary(clbin))
+ /* Save binary for reuse. */
+ if(!save_binary(&cpProgram, clbin)) {
return false;
+ }
}
- /* cache the program */
- OpenCLCache::store_program(cpPlatform, cdDevice, cpProgram, cache_locker);
+ /* Cache the program. */
+ store_cached_kernel(cpPlatform,
+ cdDevice,
+ cpProgram,
+ OpenCLCache::OCL_DEV_BASE_PROGRAM,
+ cache_locker);
+ }
+ else {
+ VLOG(2) << "Found cached OpenCL kernel.";
}
- /* find kernels */
- ckPathTraceKernel = clCreateKernel(cpProgram, "kernel_ocl_path_trace", &ciErr);
- if(opencl_error(ciErr))
- return false;
-
- ckFilmConvertByteKernel = clCreateKernel(cpProgram, "kernel_ocl_convert_to_byte", &ciErr);
- if(opencl_error(ciErr))
- return false;
-
- ckFilmConvertHalfFloatKernel = clCreateKernel(cpProgram, "kernel_ocl_convert_to_half_float", &ciErr);
- if(opencl_error(ciErr))
- return false;
-
- ckShaderKernel = clCreateKernel(cpProgram, "kernel_ocl_shader", &ciErr);
- if(opencl_error(ciErr))
- return false;
+ /* Find kernels. */
+#define FIND_KERNEL(kernel_var, kernel_name) \
+ do { \
+ kernel_var = clCreateKernel(cpProgram, "kernel_ocl_" kernel_name, &ciErr); \
+ if(opencl_error(ciErr)) \
+ return false; \
+ } while(0)
- ckBakeKernel = clCreateKernel(cpProgram, "kernel_ocl_bake", &ciErr);
- if(opencl_error(ciErr))
- return false;
+ FIND_KERNEL(ckFilmConvertByteKernel, "convert_to_byte");
+ FIND_KERNEL(ckFilmConvertHalfFloatKernel, "convert_to_half_float");
+ FIND_KERNEL(ckShaderKernel, "shader");
+ FIND_KERNEL(ckBakeKernel, "bake");
+#undef FIND_KERNEL
return true;
}
- ~OpenCLDevice()
+ ~OpenCLDeviceBase()
{
task_pool.stop();
@@ -761,12 +1055,14 @@ public:
delete mt->second;
}
- if(ckPathTraceKernel)
- clReleaseKernel(ckPathTraceKernel);
if(ckFilmConvertByteKernel)
- clReleaseKernel(ckFilmConvertByteKernel);
+ clReleaseKernel(ckFilmConvertByteKernel);
if(ckFilmConvertHalfFloatKernel)
- clReleaseKernel(ckFilmConvertHalfFloatKernel);
+ clReleaseKernel(ckFilmConvertHalfFloatKernel);
+ if(ckShaderKernel)
+ clReleaseKernel(ckShaderKernel);
+ if(ckBakeKernel)
+ clReleaseKernel(ckBakeKernel);
if(cpProgram)
clReleaseProgram(cpProgram);
if(cqCommandQueue)
@@ -789,9 +1085,22 @@ public:
else
mem_flag = CL_MEM_READ_WRITE;
- mem.device_pointer = (device_ptr)clCreateBuffer(cxContext, mem_flag, size, mem_ptr, &ciErr);
-
- opencl_assert_err(ciErr, "clCreateBuffer");
+ /* Zero-size allocation might be invoked by render, but not really
+ * supported by OpenCL. Using NULL as device pointer also doesn't really
+ * work for some reason, so for the time being we'll use special case
+ * will null_mem buffer.
+ */
+ if(size != 0) {
+ mem.device_pointer = (device_ptr)clCreateBuffer(cxContext,
+ mem_flag,
+ size,
+ mem_ptr,
+ &ciErr);
+ opencl_assert_err(ciErr, "clCreateBuffer");
+ }
+ else {
+ mem.device_pointer = null_mem;
+ }
stats.mem_alloc(size);
mem.device_size = size;
@@ -801,15 +1110,31 @@ public:
{
/* this is blocking */
size_t size = mem.memory_size();
- opencl_assert(clEnqueueWriteBuffer(cqCommandQueue, CL_MEM_PTR(mem.device_pointer), CL_TRUE, 0, size, (void*)mem.data_pointer, 0, NULL, NULL));
+ if(size != 0){
+ opencl_assert(clEnqueueWriteBuffer(cqCommandQueue,
+ CL_MEM_PTR(mem.device_pointer),
+ CL_TRUE,
+ 0,
+ size,
+ (void*)mem.data_pointer,
+ 0,
+ NULL, NULL));
+ }
}
void mem_copy_from(device_memory& mem, int y, int w, int h, int elem)
{
size_t offset = elem*y*w;
size_t size = elem*w*h;
-
- opencl_assert(clEnqueueReadBuffer(cqCommandQueue, CL_MEM_PTR(mem.device_pointer), CL_TRUE, offset, size, (uchar*)mem.data_pointer + offset, 0, NULL, NULL));
+ assert(size != 0);
+ opencl_assert(clEnqueueReadBuffer(cqCommandQueue,
+ CL_MEM_PTR(mem.device_pointer),
+ CL_TRUE,
+ offset,
+ size,
+ (uchar*)mem.data_pointer + offset,
+ 0,
+ NULL, NULL));
}
void mem_zero(device_memory& mem)
@@ -823,7 +1148,9 @@ public:
void mem_free(device_memory& mem)
{
if(mem.device_pointer) {
- opencl_assert(clReleaseMemObject(CL_MEM_PTR(mem.device_pointer)));
+ if(mem.device_pointer != null_mem) {
+ opencl_assert(clReleaseMemObject(CL_MEM_PTR(mem.device_pointer)));
+ }
mem.device_pointer = 0;
stats.mem_free(mem.device_size);
@@ -850,8 +1177,12 @@ public:
mem_copy_to(*i->second);
}
- void tex_alloc(const char *name, device_memory& mem, InterpolationType interpolation, bool periodic)
+ void tex_alloc(const char *name,
+ device_memory& mem,
+ InterpolationType /*interpolation*/,
+ ExtensionType /*extension*/)
{
+ VLOG(1) << "Texture allocate: " << name << ", " << mem.memory_size() << " bytes.";
mem_alloc(mem, MEM_READ_ONLY);
mem_copy_to(mem);
assert(mem_map.find(name) == mem_map.end());
@@ -904,42 +1235,6 @@ public:
opencl_assert(clFlush(cqCommandQueue));
}
- void path_trace(RenderTile& rtile, int sample)
- {
- /* cast arguments to cl types */
- cl_mem d_data = CL_MEM_PTR(const_mem_map["__data"]->device_pointer);
- cl_mem d_buffer = CL_MEM_PTR(rtile.buffer);
- cl_mem d_rng_state = CL_MEM_PTR(rtile.rng_state);
- cl_int d_x = rtile.x;
- cl_int d_y = rtile.y;
- cl_int d_w = rtile.w;
- cl_int d_h = rtile.h;
- cl_int d_sample = sample;
- cl_int d_offset = rtile.offset;
- cl_int d_stride = rtile.stride;
-
- /* sample arguments */
- cl_uint narg = 0;
-
- opencl_assert(clSetKernelArg(ckPathTraceKernel, narg++, sizeof(d_data), (void*)&d_data));
- opencl_assert(clSetKernelArg(ckPathTraceKernel, narg++, sizeof(d_buffer), (void*)&d_buffer));
- opencl_assert(clSetKernelArg(ckPathTraceKernel, narg++, sizeof(d_rng_state), (void*)&d_rng_state));
-
-#define KERNEL_TEX(type, ttype, name) \
- set_kernel_arg_mem(ckPathTraceKernel, &narg, #name);
-#include "kernel_textures.h"
-
- opencl_assert(clSetKernelArg(ckPathTraceKernel, narg++, sizeof(d_sample), (void*)&d_sample));
- opencl_assert(clSetKernelArg(ckPathTraceKernel, narg++, sizeof(d_x), (void*)&d_x));
- opencl_assert(clSetKernelArg(ckPathTraceKernel, narg++, sizeof(d_y), (void*)&d_y));
- opencl_assert(clSetKernelArg(ckPathTraceKernel, narg++, sizeof(d_w), (void*)&d_w));
- opencl_assert(clSetKernelArg(ckPathTraceKernel, narg++, sizeof(d_h), (void*)&d_h));
- opencl_assert(clSetKernelArg(ckPathTraceKernel, narg++, sizeof(d_offset), (void*)&d_offset));
- opencl_assert(clSetKernelArg(ckPathTraceKernel, narg++, sizeof(d_stride), (void*)&d_stride));
-
- enqueue_kernel(ckPathTraceKernel, d_w, d_h);
- }
-
void set_kernel_arg_mem(cl_kernel kernel, cl_uint *narg, const char *name)
{
cl_mem ptr;
@@ -970,29 +1265,30 @@ public:
cl_int d_offset = task.offset;
cl_int d_stride = task.stride;
- /* sample arguments */
- cl_uint narg = 0;
-
cl_kernel ckFilmConvertKernel = (rgba_byte)? ckFilmConvertByteKernel: ckFilmConvertHalfFloatKernel;
- opencl_assert(clSetKernelArg(ckFilmConvertKernel, narg++, sizeof(d_data), (void*)&d_data));
- opencl_assert(clSetKernelArg(ckFilmConvertKernel, narg++, sizeof(d_rgba), (void*)&d_rgba));
- opencl_assert(clSetKernelArg(ckFilmConvertKernel, narg++, sizeof(d_buffer), (void*)&d_buffer));
+ cl_uint start_arg_index =
+ kernel_set_args(ckFilmConvertKernel,
+ 0,
+ d_data,
+ d_rgba,
+ d_buffer);
#define KERNEL_TEX(type, ttype, name) \
- set_kernel_arg_mem(ckFilmConvertKernel, &narg, #name);
+ set_kernel_arg_mem(ckFilmConvertKernel, &start_arg_index, #name);
#include "kernel_textures.h"
-
- opencl_assert(clSetKernelArg(ckFilmConvertKernel, narg++, sizeof(d_sample_scale), (void*)&d_sample_scale));
- opencl_assert(clSetKernelArg(ckFilmConvertKernel, narg++, sizeof(d_x), (void*)&d_x));
- opencl_assert(clSetKernelArg(ckFilmConvertKernel, narg++, sizeof(d_y), (void*)&d_y));
- opencl_assert(clSetKernelArg(ckFilmConvertKernel, narg++, sizeof(d_w), (void*)&d_w));
- opencl_assert(clSetKernelArg(ckFilmConvertKernel, narg++, sizeof(d_h), (void*)&d_h));
- opencl_assert(clSetKernelArg(ckFilmConvertKernel, narg++, sizeof(d_offset), (void*)&d_offset));
- opencl_assert(clSetKernelArg(ckFilmConvertKernel, narg++, sizeof(d_stride), (void*)&d_stride));
-
-
+#undef KERNEL_TEX
+
+ start_arg_index += kernel_set_args(ckFilmConvertKernel,
+ start_arg_index,
+ d_sample_scale,
+ d_x,
+ d_y,
+ d_w,
+ d_h,
+ d_offset,
+ d_stride);
enqueue_kernel(ckFilmConvertKernel, d_w, d_h);
}
@@ -1008,9 +1304,6 @@ public:
cl_int d_shader_w = task.shader_w;
cl_int d_offset = task.offset;
- /* sample arguments */
- cl_uint narg = 0;
-
cl_kernel kernel;
if(task.shader_eval_type >= SHADER_EVAL_BAKE)
@@ -1025,19 +1318,25 @@ public:
cl_int d_sample = sample;
- opencl_assert(clSetKernelArg(kernel, narg++, sizeof(d_data), (void*)&d_data));
- opencl_assert(clSetKernelArg(kernel, narg++, sizeof(d_input), (void*)&d_input));
- opencl_assert(clSetKernelArg(kernel, narg++, sizeof(d_output), (void*)&d_output));
+ cl_uint start_arg_index =
+ kernel_set_args(kernel,
+ 0,
+ d_data,
+ d_input,
+ d_output);
#define KERNEL_TEX(type, ttype, name) \
- set_kernel_arg_mem(kernel, &narg, #name);
+ set_kernel_arg_mem(kernel, &start_arg_index, #name);
#include "kernel_textures.h"
+#undef KERNEL_TEX
- opencl_assert(clSetKernelArg(kernel, narg++, sizeof(d_shader_eval_type), (void*)&d_shader_eval_type));
- opencl_assert(clSetKernelArg(kernel, narg++, sizeof(d_shader_x), (void*)&d_shader_x));
- opencl_assert(clSetKernelArg(kernel, narg++, sizeof(d_shader_w), (void*)&d_shader_w));
- opencl_assert(clSetKernelArg(kernel, narg++, sizeof(d_offset), (void*)&d_offset));
- opencl_assert(clSetKernelArg(kernel, narg++, sizeof(d_sample), (void*)&d_sample));
+ start_arg_index += kernel_set_args(kernel,
+ start_arg_index,
+ d_shader_eval_type,
+ d_shader_x,
+ d_shader_w,
+ d_offset,
+ d_sample);
enqueue_kernel(kernel, task.shader_w, 1);
@@ -1045,6 +1344,420 @@ public:
}
}
+ class OpenCLDeviceTask : public DeviceTask {
+ public:
+ OpenCLDeviceTask(OpenCLDeviceBase *device, DeviceTask& task)
+ : DeviceTask(task)
+ {
+ run = function_bind(&OpenCLDeviceBase::thread_run,
+ device,
+ this);
+ }
+ };
+
+ int get_split_task_count(DeviceTask& /*task*/)
+ {
+ return 1;
+ }
+
+ void task_add(DeviceTask& task)
+ {
+ task_pool.push(new OpenCLDeviceTask(this, task));
+ }
+
+ void task_wait()
+ {
+ task_pool.wait();
+ }
+
+ void task_cancel()
+ {
+ task_pool.cancel();
+ }
+
+ virtual void thread_run(DeviceTask * /*task*/) = 0;
+
+protected:
+ string kernel_build_options(const string *debug_src = NULL)
+ {
+ string build_options = " -cl-fast-relaxed-math ";
+
+ if(platform_name == "NVIDIA CUDA") {
+ build_options += "-D__KERNEL_OPENCL_NVIDIA__ "
+ "-cl-nv-maxrregcount=32 "
+ "-cl-nv-verbose ";
+
+ uint compute_capability_major, compute_capability_minor;
+ clGetDeviceInfo(cdDevice, CL_DEVICE_COMPUTE_CAPABILITY_MAJOR_NV,
+ sizeof(cl_uint), &compute_capability_major, NULL);
+ clGetDeviceInfo(cdDevice, CL_DEVICE_COMPUTE_CAPABILITY_MINOR_NV,
+ sizeof(cl_uint), &compute_capability_minor, NULL);
+
+ build_options += string_printf("-D__COMPUTE_CAPABILITY__=%u ",
+ compute_capability_major * 100 +
+ compute_capability_minor * 10);
+ }
+
+ else if(platform_name == "Apple")
+ build_options += "-D__KERNEL_OPENCL_APPLE__ ";
+
+ else if(platform_name == "AMD Accelerated Parallel Processing")
+ build_options += "-D__KERNEL_OPENCL_AMD__ ";
+
+ else if(platform_name == "Intel(R) OpenCL") {
+ build_options += "-D__KERNEL_OPENCL_INTEL_CPU__ ";
+
+ /* Options for gdb source level kernel debugging.
+ * this segfaults on linux currently.
+ */
+ if(opencl_kernel_use_debug() && debug_src)
+ build_options += "-g -s \"" + *debug_src + "\" ";
+ }
+
+ if(opencl_kernel_use_debug())
+ build_options += "-D__KERNEL_OPENCL_DEBUG__ ";
+
+#ifdef WITH_CYCLES_DEBUG
+ build_options += "-D__KERNEL_DEBUG__ ";
+#endif
+
+ return build_options;
+ }
+
+ class ArgumentWrapper {
+ public:
+ ArgumentWrapper() : size(0), pointer(NULL) {}
+ template <typename T>
+ ArgumentWrapper(T& argument) : size(sizeof(argument)),
+ pointer(&argument) { }
+ size_t size;
+ void *pointer;
+ };
+
+ /* TODO(sergey): In the future we can use variadic templates, once
+ * C++0x is allowed. Should allow to clean this up a bit.
+ */
+ int kernel_set_args(cl_kernel kernel,
+ int start_argument_index,
+ const ArgumentWrapper& arg1 = ArgumentWrapper(),
+ const ArgumentWrapper& arg2 = ArgumentWrapper(),
+ const ArgumentWrapper& arg3 = ArgumentWrapper(),
+ const ArgumentWrapper& arg4 = ArgumentWrapper(),
+ const ArgumentWrapper& arg5 = ArgumentWrapper(),
+ const ArgumentWrapper& arg6 = ArgumentWrapper(),
+ const ArgumentWrapper& arg7 = ArgumentWrapper(),
+ const ArgumentWrapper& arg8 = ArgumentWrapper(),
+ const ArgumentWrapper& arg9 = ArgumentWrapper(),
+ const ArgumentWrapper& arg10 = ArgumentWrapper(),
+ const ArgumentWrapper& arg11 = ArgumentWrapper(),
+ const ArgumentWrapper& arg12 = ArgumentWrapper(),
+ const ArgumentWrapper& arg13 = ArgumentWrapper(),
+ const ArgumentWrapper& arg14 = ArgumentWrapper(),
+ const ArgumentWrapper& arg15 = ArgumentWrapper(),
+ const ArgumentWrapper& arg16 = ArgumentWrapper(),
+ const ArgumentWrapper& arg17 = ArgumentWrapper(),
+ const ArgumentWrapper& arg18 = ArgumentWrapper(),
+ const ArgumentWrapper& arg19 = ArgumentWrapper(),
+ const ArgumentWrapper& arg20 = ArgumentWrapper(),
+ const ArgumentWrapper& arg21 = ArgumentWrapper(),
+ const ArgumentWrapper& arg22 = ArgumentWrapper(),
+ const ArgumentWrapper& arg23 = ArgumentWrapper(),
+ const ArgumentWrapper& arg24 = ArgumentWrapper(),
+ const ArgumentWrapper& arg25 = ArgumentWrapper(),
+ const ArgumentWrapper& arg26 = ArgumentWrapper(),
+ const ArgumentWrapper& arg27 = ArgumentWrapper(),
+ const ArgumentWrapper& arg28 = ArgumentWrapper(),
+ const ArgumentWrapper& arg29 = ArgumentWrapper(),
+ const ArgumentWrapper& arg30 = ArgumentWrapper(),
+ const ArgumentWrapper& arg31 = ArgumentWrapper(),
+ const ArgumentWrapper& arg32 = ArgumentWrapper(),
+ const ArgumentWrapper& arg33 = ArgumentWrapper())
+ {
+ int current_arg_index = 0;
+#define FAKE_VARARG_HANDLE_ARG(arg) \
+ do { \
+ if(arg.pointer != NULL) { \
+ opencl_assert(clSetKernelArg( \
+ kernel, \
+ start_argument_index + current_arg_index, \
+ arg.size, arg.pointer)); \
+ ++current_arg_index; \
+ } \
+ else { \
+ return current_arg_index; \
+ } \
+ } while(false)
+ FAKE_VARARG_HANDLE_ARG(arg1);
+ FAKE_VARARG_HANDLE_ARG(arg2);
+ FAKE_VARARG_HANDLE_ARG(arg3);
+ FAKE_VARARG_HANDLE_ARG(arg4);
+ FAKE_VARARG_HANDLE_ARG(arg5);
+ FAKE_VARARG_HANDLE_ARG(arg6);
+ FAKE_VARARG_HANDLE_ARG(arg7);
+ FAKE_VARARG_HANDLE_ARG(arg8);
+ FAKE_VARARG_HANDLE_ARG(arg9);
+ FAKE_VARARG_HANDLE_ARG(arg10);
+ FAKE_VARARG_HANDLE_ARG(arg11);
+ FAKE_VARARG_HANDLE_ARG(arg12);
+ FAKE_VARARG_HANDLE_ARG(arg13);
+ FAKE_VARARG_HANDLE_ARG(arg14);
+ FAKE_VARARG_HANDLE_ARG(arg15);
+ FAKE_VARARG_HANDLE_ARG(arg16);
+ FAKE_VARARG_HANDLE_ARG(arg17);
+ FAKE_VARARG_HANDLE_ARG(arg18);
+ FAKE_VARARG_HANDLE_ARG(arg19);
+ FAKE_VARARG_HANDLE_ARG(arg20);
+ FAKE_VARARG_HANDLE_ARG(arg21);
+ FAKE_VARARG_HANDLE_ARG(arg22);
+ FAKE_VARARG_HANDLE_ARG(arg23);
+ FAKE_VARARG_HANDLE_ARG(arg24);
+ FAKE_VARARG_HANDLE_ARG(arg25);
+ FAKE_VARARG_HANDLE_ARG(arg26);
+ FAKE_VARARG_HANDLE_ARG(arg27);
+ FAKE_VARARG_HANDLE_ARG(arg28);
+ FAKE_VARARG_HANDLE_ARG(arg29);
+ FAKE_VARARG_HANDLE_ARG(arg30);
+ FAKE_VARARG_HANDLE_ARG(arg31);
+ FAKE_VARARG_HANDLE_ARG(arg32);
+ FAKE_VARARG_HANDLE_ARG(arg33);
+#undef FAKE_VARARG_HANDLE_ARG
+ return current_arg_index;
+ }
+
+ inline void release_kernel_safe(cl_kernel kernel)
+ {
+ if(kernel) {
+ clReleaseKernel(kernel);
+ }
+ }
+
+ inline void release_mem_object_safe(cl_mem mem)
+ {
+ if(mem != NULL) {
+ clReleaseMemObject(mem);
+ }
+ }
+
+ inline void release_program_safe(cl_program program)
+ {
+ if(program) {
+ clReleaseProgram(program);
+ }
+ }
+
+ string build_options_from_requested_features(
+ const DeviceRequestedFeatures& requested_features)
+ {
+ string build_options = "";
+ if(requested_features.experimental) {
+ build_options += " -D__KERNEL_EXPERIMENTAL__";
+ }
+ build_options += " -D__NODES_MAX_GROUP__=" +
+ string_printf("%d", requested_features.max_nodes_group);
+ build_options += " -D__NODES_FEATURES__=" +
+ string_printf("%d", requested_features.nodes_features);
+ build_options += string_printf(" -D__MAX_CLOSURE__=%d",
+ requested_features.max_closure);
+ if(!requested_features.use_hair) {
+ build_options += " -D__NO_HAIR__";
+ }
+ if(!requested_features.use_object_motion) {
+ build_options += " -D__NO_OBJECT_MOTION__";
+ }
+ if(!requested_features.use_camera_motion) {
+ build_options += " -D__NO_CAMERA_MOTION__";
+ }
+ if(!requested_features.use_baking) {
+ build_options += " -D__NO_BAKING__";
+ }
+ return build_options;
+ }
+
+ /* ** Those guys are for workign around some compiler-specific bugs ** */
+
+ virtual cl_program load_cached_kernel(
+ const DeviceRequestedFeatures& /*requested_features*/,
+ OpenCLCache::ProgramName program_name,
+ thread_scoped_lock& cache_locker)
+ {
+ return OpenCLCache::get_program(cpPlatform,
+ cdDevice,
+ program_name,
+ cache_locker);
+ }
+
+ virtual void store_cached_kernel(cl_platform_id platform,
+ cl_device_id device,
+ cl_program program,
+ OpenCLCache::ProgramName program_name,
+ thread_scoped_lock& cache_locker)
+ {
+ OpenCLCache::store_program(platform,
+ device,
+ program,
+ program_name,
+ cache_locker);
+ }
+
+ virtual string build_options_for_base_program(
+ const DeviceRequestedFeatures& /*requested_features*/)
+ {
+ /* TODO(sergey): By default we compile all features, meaning
+ * mega kernel is not getting feature-based optimizations.
+ *
+ * Ideally we need always compile kernel with as less features
+ * enabled as possible to keep performance at it's max.
+ */
+ return "";
+ }
+};
+
+class OpenCLDeviceMegaKernel : public OpenCLDeviceBase
+{
+public:
+ cl_kernel ckPathTraceKernel;
+ cl_program path_trace_program;
+
+ OpenCLDeviceMegaKernel(DeviceInfo& info, Stats &stats, bool background_)
+ : OpenCLDeviceBase(info, stats, background_)
+ {
+ ckPathTraceKernel = NULL;
+ path_trace_program = NULL;
+ }
+
+ bool load_kernels(const DeviceRequestedFeatures& requested_features)
+ {
+ /* Get Shader, bake and film convert kernels.
+ * It'll also do verification of OpenCL actually initialized.
+ */
+ if(!OpenCLDeviceBase::load_kernels(requested_features)) {
+ return false;
+ }
+
+ /* Try to use cached kernel. */
+ thread_scoped_lock cache_locker;
+ path_trace_program = OpenCLCache::get_program(cpPlatform,
+ cdDevice,
+ OpenCLCache::OCL_DEV_MEGAKERNEL_PROGRAM,
+ cache_locker);
+
+ if(!path_trace_program) {
+ /* Verify we have right opencl version. */
+ if(!opencl_version_check())
+ return false;
+
+ /* Calculate md5 hash to detect changes. */
+ string kernel_path = path_get("kernel");
+ string kernel_md5 = path_files_md5_hash(kernel_path);
+ string custom_kernel_build_options = "-D__COMPILE_ONLY_MEGAKERNEL__ ";
+ string device_md5 = device_md5_hash(custom_kernel_build_options);
+
+ /* Path to cached binary. */
+ string clbin = string_printf("cycles_kernel_%s_%s.clbin",
+ device_md5.c_str(),
+ kernel_md5.c_str());
+ clbin = path_user_get(path_join("cache", clbin));
+
+ /* Path to preprocessed source for debugging. */
+ string clsrc, *debug_src = NULL;
+ if(opencl_kernel_use_debug()) {
+ clsrc = string_printf("cycles_kernel_%s_%s.cl",
+ device_md5.c_str(),
+ kernel_md5.c_str());
+ clsrc = path_user_get(path_join("cache", clsrc));
+ debug_src = &clsrc;
+ }
+
+ /* If exists already, try use it. */
+ if(path_exists(clbin) && load_binary(kernel_path,
+ clbin,
+ custom_kernel_build_options,
+ &path_trace_program,
+ debug_src)) {
+ /* Kernel loaded from binary, nothing to do. */
+ }
+ else {
+ string init_kernel_source = "#include \"kernels/opencl/kernel.cl\" // " +
+ kernel_md5 + "\n";
+ /* If does not exist or loading binary failed, compile kernel. */
+ if(!compile_kernel(kernel_path,
+ init_kernel_source,
+ custom_kernel_build_options,
+ &path_trace_program,
+ debug_src))
+ {
+ return false;
+ }
+ /* Save binary for reuse. */
+ if(!save_binary(&path_trace_program, clbin)) {
+ return false;
+ }
+ }
+ /* Cache the program. */
+ OpenCLCache::store_program(cpPlatform,
+ cdDevice,
+ path_trace_program,
+ OpenCLCache::OCL_DEV_MEGAKERNEL_PROGRAM,
+ cache_locker);
+ }
+
+ /* Find kernels. */
+ ckPathTraceKernel = clCreateKernel(path_trace_program,
+ "kernel_ocl_path_trace",
+ &ciErr);
+ if(opencl_error(ciErr))
+ return false;
+ return true;
+ }
+
+ ~OpenCLDeviceMegaKernel()
+ {
+ task_pool.stop();
+ release_kernel_safe(ckPathTraceKernel);
+ release_program_safe(path_trace_program);
+ }
+
+ void path_trace(RenderTile& rtile, int sample)
+ {
+ /* Cast arguments to cl types. */
+ cl_mem d_data = CL_MEM_PTR(const_mem_map["__data"]->device_pointer);
+ cl_mem d_buffer = CL_MEM_PTR(rtile.buffer);
+ cl_mem d_rng_state = CL_MEM_PTR(rtile.rng_state);
+ cl_int d_x = rtile.x;
+ cl_int d_y = rtile.y;
+ cl_int d_w = rtile.w;
+ cl_int d_h = rtile.h;
+ cl_int d_offset = rtile.offset;
+ cl_int d_stride = rtile.stride;
+
+ /* Sample arguments. */
+ cl_int d_sample = sample;
+
+ cl_uint start_arg_index =
+ kernel_set_args(ckPathTraceKernel,
+ 0,
+ d_data,
+ d_buffer,
+ d_rng_state);
+
+#define KERNEL_TEX(type, ttype, name) \
+ set_kernel_arg_mem(ckPathTraceKernel, &start_arg_index, #name);
+#include "kernel_textures.h"
+#undef KERNEL_TEX
+
+ start_arg_index += kernel_set_args(ckPathTraceKernel,
+ start_arg_index,
+ d_sample,
+ d_x,
+ d_y,
+ d_w,
+ d_h,
+ d_offset,
+ d_stride);
+
+ enqueue_kernel(ckPathTraceKernel, d_w, d_h);
+ }
+
void thread_run(DeviceTask *task)
{
if(task->type == DeviceTask::FILM_CONVERT) {
@@ -1055,8 +1768,7 @@ public:
}
else if(task->type == DeviceTask::PATH_TRACE) {
RenderTile tile;
-
- /* keep rendering tiles until done */
+ /* Keep rendering tiles until done. */
while(task->acquire_tile(this, tile)) {
int start_sample = tile.start_sample;
int end_sample = tile.start_sample + tile.num_samples;
@@ -1074,61 +1786,1847 @@ public:
task->update_progress(&tile);
}
+ /* Complete kernel execution before release tile */
+ /* This helps in multi-device render;
+ * The device that reaches the critical-section function
+ * release_tile waits (stalling other devices from entering
+ * release_tile) for all kernels to complete. If device1 (a
+ * slow-render device) reaches release_tile first then it would
+ * stall device2 (a fast-render device) from proceeding to render
+ * next tile.
+ */
+ clFinish(cqCommandQueue);
+
task->release_tile(tile);
}
}
}
+};
- class OpenCLDeviceTask : public DeviceTask {
- public:
- OpenCLDeviceTask(OpenCLDevice *device, DeviceTask& task)
- : DeviceTask(task)
+/* TODO(sergey): This is to keep tile split on OpenCL level working
+ * for now, since without this view-port render does not work as it
+ * should.
+ *
+ * Ideally it'll be done on the higher level, but we need to get ready
+ * for merge rather soon, so let's keep split logic private here in
+ * the file.
+ */
+class SplitRenderTile : public RenderTile {
+public:
+ SplitRenderTile()
+ : RenderTile(),
+ buffer_offset_x(0),
+ buffer_offset_y(0),
+ rng_state_offset_x(0),
+ rng_state_offset_y(0),
+ buffer_rng_state_stride(0) {}
+
+ explicit SplitRenderTile(RenderTile& tile)
+ : RenderTile(),
+ buffer_offset_x(0),
+ buffer_offset_y(0),
+ rng_state_offset_x(0),
+ rng_state_offset_y(0),
+ buffer_rng_state_stride(0)
+ {
+ x = tile.x;
+ y = tile.y;
+ w = tile.w;
+ h = tile.h;
+ start_sample = tile.start_sample;
+ num_samples = tile.num_samples;
+ sample = tile.sample;
+ resolution = tile.resolution;
+ offset = tile.offset;
+ stride = tile.stride;
+ buffer = tile.buffer;
+ rng_state = tile.rng_state;
+ buffers = tile.buffers;
+ }
+
+ /* Split kernel is device global memory constrained;
+ * hence split kernel cant render big tile size's in
+ * one go. If the user sets a big tile size (big tile size
+ * is a term relative to the available device global memory),
+ * we split the tile further and then call path_trace on
+ * each of those split tiles. The following variables declared,
+ * assist in achieving that purpose
+ */
+ int buffer_offset_x;
+ int buffer_offset_y;
+ int rng_state_offset_x;
+ int rng_state_offset_y;
+ int buffer_rng_state_stride;
+};
+
+/* OpenCLDeviceSplitKernel's declaration/definition. */
+class OpenCLDeviceSplitKernel : public OpenCLDeviceBase
+{
+public:
+ /* Kernel declaration. */
+ cl_kernel ckPathTraceKernel_data_init;
+ cl_kernel ckPathTraceKernel_scene_intersect;
+ cl_kernel ckPathTraceKernel_lamp_emission;
+ cl_kernel ckPathTraceKernel_queue_enqueue;
+ cl_kernel ckPathTraceKernel_background_buffer_update;
+ cl_kernel ckPathTraceKernel_shader_eval;
+ cl_kernel ckPathTraceKernel_holdout_emission_blurring_pathtermination_ao;
+ cl_kernel ckPathTraceKernel_direct_lighting;
+ cl_kernel ckPathTraceKernel_shadow_blocked;
+ cl_kernel ckPathTraceKernel_next_iteration_setup;
+ cl_kernel ckPathTraceKernel_sum_all_radiance;
+
+ /* cl_program declaration. */
+ cl_program data_init_program;
+ cl_program scene_intersect_program;
+ cl_program lamp_emission_program;
+ cl_program queue_enqueue_program;
+ cl_program background_buffer_update_program;
+ cl_program shader_eval_program;
+ cl_program holdout_emission_blurring_pathtermination_ao_program;
+ cl_program direct_lighting_program;
+ cl_program shadow_blocked_program;
+ cl_program next_iteration_setup_program;
+ cl_program sum_all_radiance_program;
+
+ /* Global memory variables [porting]; These memory is used for
+ * co-operation between different kernels; Data written by one
+ * kernel will be available to another kernel via this global
+ * memory.
+ */
+ cl_mem rng_coop;
+ cl_mem throughput_coop;
+ cl_mem L_transparent_coop;
+ cl_mem PathRadiance_coop;
+ cl_mem Ray_coop;
+ cl_mem PathState_coop;
+ cl_mem Intersection_coop;
+ cl_mem kgbuffer; /* KernelGlobals buffer. */
+
+ /* Global buffers for ShaderData. */
+ cl_mem sd; /* ShaderData used in the main path-iteration loop. */
+ cl_mem sd_DL_shadow; /* ShaderData used in Direct Lighting and
+ * shadow_blocked kernel.
+ */
+
+ /* Global buffers of each member of ShaderData. */
+ cl_mem P_sd;
+ cl_mem P_sd_DL_shadow;
+ cl_mem N_sd;
+ cl_mem N_sd_DL_shadow;
+ cl_mem Ng_sd;
+ cl_mem Ng_sd_DL_shadow;
+ cl_mem I_sd;
+ cl_mem I_sd_DL_shadow;
+ cl_mem shader_sd;
+ cl_mem shader_sd_DL_shadow;
+ cl_mem flag_sd;
+ cl_mem flag_sd_DL_shadow;
+ cl_mem prim_sd;
+ cl_mem prim_sd_DL_shadow;
+ cl_mem type_sd;
+ cl_mem type_sd_DL_shadow;
+ cl_mem u_sd;
+ cl_mem u_sd_DL_shadow;
+ cl_mem v_sd;
+ cl_mem v_sd_DL_shadow;
+ cl_mem object_sd;
+ cl_mem object_sd_DL_shadow;
+ cl_mem time_sd;
+ cl_mem time_sd_DL_shadow;
+ cl_mem ray_length_sd;
+ cl_mem ray_length_sd_DL_shadow;
+ cl_mem ray_depth_sd;
+ cl_mem ray_depth_sd_DL_shadow;
+ cl_mem transparent_depth_sd;
+ cl_mem transparent_depth_sd_DL_shadow;
+
+ /* Ray differentials. */
+ cl_mem dP_sd, dI_sd;
+ cl_mem dP_sd_DL_shadow, dI_sd_DL_shadow;
+ cl_mem du_sd, dv_sd;
+ cl_mem du_sd_DL_shadow, dv_sd_DL_shadow;
+
+ /* Dp/Du */
+ cl_mem dPdu_sd, dPdv_sd;
+ cl_mem dPdu_sd_DL_shadow, dPdv_sd_DL_shadow;
+
+ /* Object motion. */
+ cl_mem ob_tfm_sd, ob_itfm_sd;
+ cl_mem ob_tfm_sd_DL_shadow, ob_itfm_sd_DL_shadow;
+
+ cl_mem closure_sd;
+ cl_mem closure_sd_DL_shadow;
+ cl_mem num_closure_sd;
+ cl_mem num_closure_sd_DL_shadow;
+ cl_mem randb_closure_sd;
+ cl_mem randb_closure_sd_DL_shadow;
+ cl_mem ray_P_sd;
+ cl_mem ray_P_sd_DL_shadow;
+ cl_mem ray_dP_sd;
+ cl_mem ray_dP_sd_DL_shadow;
+
+ /* Global memory required for shadow blocked and accum_radiance. */
+ cl_mem BSDFEval_coop;
+ cl_mem ISLamp_coop;
+ cl_mem LightRay_coop;
+ cl_mem AOAlpha_coop;
+ cl_mem AOBSDF_coop;
+ cl_mem AOLightRay_coop;
+ cl_mem Intersection_coop_AO;
+ cl_mem Intersection_coop_DL;
+
+#ifdef WITH_CYCLES_DEBUG
+ /* DebugData memory */
+ cl_mem debugdata_coop;
+#endif
+
+ /* Global state array that tracks ray state. */
+ cl_mem ray_state;
+
+ /* Per sample buffers. */
+ cl_mem per_sample_output_buffers;
+
+ /* Denotes which sample each ray is being processed for. */
+ cl_mem work_array;
+
+ /* Queue */
+ cl_mem Queue_data; /* Array of size queuesize * num_queues * sizeof(int). */
+ cl_mem Queue_index; /* Array of size num_queues * sizeof(int);
+ * Tracks the size of each queue.
+ */
+
+ /* Flag to make sceneintersect and lampemission kernel use queues. */
+ cl_mem use_queues_flag;
+
+ /* Amount of memory in output buffer associated with one pixel/thread. */
+ size_t per_thread_output_buffer_size;
+
+ /* Total allocatable available device memory. */
+ size_t total_allocatable_memory;
+
+ /* host version of ray_state; Used in checking host path-iteration
+ * termination.
+ */
+ char *hostRayStateArray;
+
+ /* Number of path-iterations to be done in one shot. */
+ unsigned int PathIteration_times;
+
+#ifdef __WORK_STEALING__
+ /* Work pool with respect to each work group. */
+ cl_mem work_pool_wgs;
+
+ /* Denotes the maximum work groups possible w.r.t. current tile size. */
+ unsigned int max_work_groups;
+#endif
+
+ /* clos_max value for which the kernels have been loaded currently. */
+ int current_max_closure;
+
+ /* Marked True in constructor and marked false at the end of path_trace(). */
+ bool first_tile;
+
+ OpenCLDeviceSplitKernel(DeviceInfo& info, Stats &stats, bool background_)
+ : OpenCLDeviceBase(info, stats, background_)
+ {
+ background = background_;
+
+ /* Initialize kernels. */
+ ckPathTraceKernel_data_init = NULL;
+ ckPathTraceKernel_scene_intersect = NULL;
+ ckPathTraceKernel_lamp_emission = NULL;
+ ckPathTraceKernel_background_buffer_update = NULL;
+ ckPathTraceKernel_shader_eval = NULL;
+ ckPathTraceKernel_holdout_emission_blurring_pathtermination_ao = NULL;
+ ckPathTraceKernel_direct_lighting = NULL;
+ ckPathTraceKernel_shadow_blocked = NULL;
+ ckPathTraceKernel_next_iteration_setup = NULL;
+ ckPathTraceKernel_sum_all_radiance = NULL;
+ ckPathTraceKernel_queue_enqueue = NULL;
+
+ /* Initialize program. */
+ data_init_program = NULL;
+ scene_intersect_program = NULL;
+ lamp_emission_program = NULL;
+ queue_enqueue_program = NULL;
+ background_buffer_update_program = NULL;
+ shader_eval_program = NULL;
+ holdout_emission_blurring_pathtermination_ao_program = NULL;
+ direct_lighting_program = NULL;
+ shadow_blocked_program = NULL;
+ next_iteration_setup_program = NULL;
+ sum_all_radiance_program = NULL;
+
+ /* Initialize cl_mem variables. */
+ kgbuffer = NULL;
+ sd = NULL;
+ sd_DL_shadow = NULL;
+
+ P_sd = NULL;
+ P_sd_DL_shadow = NULL;
+ N_sd = NULL;
+ N_sd_DL_shadow = NULL;
+ Ng_sd = NULL;
+ Ng_sd_DL_shadow = NULL;
+ I_sd = NULL;
+ I_sd_DL_shadow = NULL;
+ shader_sd = NULL;
+ shader_sd_DL_shadow = NULL;
+ flag_sd = NULL;
+ flag_sd_DL_shadow = NULL;
+ prim_sd = NULL;
+ prim_sd_DL_shadow = NULL;
+ type_sd = NULL;
+ type_sd_DL_shadow = NULL;
+ u_sd = NULL;
+ u_sd_DL_shadow = NULL;
+ v_sd = NULL;
+ v_sd_DL_shadow = NULL;
+ object_sd = NULL;
+ object_sd_DL_shadow = NULL;
+ time_sd = NULL;
+ time_sd_DL_shadow = NULL;
+ ray_length_sd = NULL;
+ ray_length_sd_DL_shadow = NULL;
+ ray_depth_sd = NULL;
+ ray_depth_sd_DL_shadow = NULL;
+ transparent_depth_sd = NULL;
+ transparent_depth_sd_DL_shadow = NULL;
+
+ /* Ray differentials. */
+ dP_sd = NULL;
+ dI_sd = NULL;
+ dP_sd_DL_shadow = NULL;
+ dI_sd_DL_shadow = NULL;
+ du_sd = NULL;
+ dv_sd = NULL;
+ du_sd_DL_shadow = NULL;
+ dv_sd_DL_shadow = NULL;
+
+ /* Dp/Du */
+ dPdu_sd = NULL;
+ dPdv_sd = NULL;
+ dPdu_sd_DL_shadow = NULL;
+ dPdv_sd_DL_shadow = NULL;
+
+ /* Object motion. */
+ ob_tfm_sd = NULL;
+ ob_itfm_sd = NULL;
+ ob_tfm_sd_DL_shadow = NULL;
+ ob_itfm_sd_DL_shadow = NULL;
+
+ closure_sd = NULL;
+ closure_sd_DL_shadow = NULL;
+ num_closure_sd = NULL;
+ num_closure_sd_DL_shadow = NULL;
+ randb_closure_sd = NULL;
+ randb_closure_sd_DL_shadow = NULL;
+ ray_P_sd = NULL;
+ ray_P_sd_DL_shadow = NULL;
+ ray_dP_sd = NULL;
+ ray_dP_sd_DL_shadow = NULL;
+
+ rng_coop = NULL;
+ throughput_coop = NULL;
+ L_transparent_coop = NULL;
+ PathRadiance_coop = NULL;
+ Ray_coop = NULL;
+ PathState_coop = NULL;
+ Intersection_coop = NULL;
+ ray_state = NULL;
+
+ AOAlpha_coop = NULL;
+ AOBSDF_coop = NULL;
+ AOLightRay_coop = NULL;
+ BSDFEval_coop = NULL;
+ ISLamp_coop = NULL;
+ LightRay_coop = NULL;
+ Intersection_coop_AO = NULL;
+ Intersection_coop_DL = NULL;
+
+#ifdef WITH_CYCLES_DEBUG
+ debugdata_coop = NULL;
+#endif
+
+ work_array = NULL;
+
+ /* Queue. */
+ Queue_data = NULL;
+ Queue_index = NULL;
+ use_queues_flag = NULL;
+
+ per_sample_output_buffers = NULL;
+
+ per_thread_output_buffer_size = 0;
+ hostRayStateArray = NULL;
+ PathIteration_times = PATH_ITER_INC_FACTOR;
+#ifdef __WORK_STEALING__
+ work_pool_wgs = NULL;
+ max_work_groups = 0;
+#endif
+ current_max_closure = -1;
+ first_tile = true;
+
+ /* Get device's maximum memory that can be allocated. */
+ ciErr = clGetDeviceInfo(cdDevice,
+ CL_DEVICE_MAX_MEM_ALLOC_SIZE,
+ sizeof(size_t),
+ &total_allocatable_memory,
+ NULL);
+ assert(ciErr == CL_SUCCESS);
+ if(platform_name == "AMD Accelerated Parallel Processing") {
+ /* This value is tweak-able; AMD platform does not seem to
+ * give maximum performance when all of CL_DEVICE_MAX_MEM_ALLOC_SIZE
+ * is considered for further computation.
+ */
+ total_allocatable_memory /= 2;
+ }
+ }
+
+ /* TODO(sergey): Seems really close to load_kernel(),
+ * could it be de-duplicated?
+ */
+ bool load_split_kernel(string kernel_path,
+ string kernel_init_source,
+ string clbin,
+ string custom_kernel_build_options,
+ cl_program *program,
+ const string *debug_src = NULL)
+ {
+ if(!opencl_version_check())
+ return false;
+
+ clbin = path_user_get(path_join("cache", clbin));
+
+ /* If exists already, try use it. */
+ if(path_exists(clbin) && load_binary(kernel_path,
+ clbin,
+ custom_kernel_build_options,
+ program,
+ debug_src)) {
+ /* Kernel loaded from binary. */
+ }
+ else {
+ /* If does not exist or loading binary failed, compile kernel. */
+ if(!compile_kernel(kernel_path,
+ kernel_init_source,
+ custom_kernel_build_options,
+ program,
+ debug_src))
+ {
+ return false;
+ }
+ /* Save binary for reuse. */
+ if(!save_binary(program, clbin)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /* Split kernel utility functions. */
+ size_t get_tex_size(const char *tex_name)
+ {
+ cl_mem ptr;
+ size_t ret_size = 0;
+ MemMap::iterator i = mem_map.find(tex_name);
+ if(i != mem_map.end()) {
+ ptr = CL_MEM_PTR(i->second);
+ ciErr = clGetMemObjectInfo(ptr,
+ CL_MEM_SIZE,
+ sizeof(ret_size),
+ &ret_size,
+ NULL);
+ assert(ciErr == CL_SUCCESS);
+ }
+ return ret_size;
+ }
+
+ size_t get_shader_closure_size(int max_closure)
+ {
+ return (sizeof(ShaderClosure) * max_closure);
+ }
+
+ size_t get_shader_data_size(size_t shader_closure_size)
+ {
+ /* ShaderData size without accounting for ShaderClosure array. */
+ size_t shader_data_size =
+ sizeof(ShaderData) - (sizeof(ShaderClosure) * MAX_CLOSURE);
+ return (shader_data_size + shader_closure_size);
+ }
+
+ /* Returns size of KernelGlobals structure associated with OpenCL. */
+ size_t get_KernelGlobals_size()
+ {
+ /* Copy dummy KernelGlobals related to OpenCL from kernel_globals.h to
+ * fetch its size.
+ */
+ typedef struct KernelGlobals {
+ ccl_constant KernelData *data;
+#define KERNEL_TEX(type, ttype, name) \
+ ccl_global type *name;
+#include "kernel_textures.h"
+#undef KERNEL_TEX
+ } KernelGlobals;
+
+ return sizeof(KernelGlobals);
+ }
+
+ /* Returns size of Structure of arrays implementation of. */
+ size_t get_shaderdata_soa_size()
+ {
+ size_t shader_soa_size = 0;
+
+#define SD_VAR(type, what) shader_soa_size += sizeof(void *);
+#define SD_CLOSURE_VAR(type, what, max_closure) shader_soa_size += sizeof(void *);
+ #include "kernel_shaderdata_vars.h"
+#undef SD_VAR
+#undef SD_CLOSURE_VAR
+
+ return shader_soa_size;
+ }
+
+ bool load_kernels(const DeviceRequestedFeatures& requested_features)
+ {
+ /* Get Shader, bake and film_convert kernels.
+ * It'll also do verification of OpenCL actually initialized.
+ */
+ if(!OpenCLDeviceBase::load_kernels(requested_features)) {
+ return false;
+ }
+
+ string kernel_path = path_get("kernel");
+ string kernel_md5 = path_files_md5_hash(kernel_path);
+ string device_md5;
+ string kernel_init_source;
+ string clbin;
+ string clsrc, *debug_src = NULL;
+
+ string build_options = "-D__SPLIT_KERNEL__";
+#ifdef __WORK_STEALING__
+ build_options += " -D__WORK_STEALING__";
+#endif
+ build_options += build_options_from_requested_features(requested_features);
+
+ /* Set compute device build option. */
+ cl_device_type device_type;
+ ciErr = clGetDeviceInfo(cdDevice,
+ CL_DEVICE_TYPE,
+ sizeof(cl_device_type),
+ &device_type,
+ NULL);
+ assert(ciErr == CL_SUCCESS);
+ if(device_type == CL_DEVICE_TYPE_GPU) {
+ build_options += " -D__COMPUTE_DEVICE_GPU__";
+ }
+
+#define GLUE(a, b) a ## b
+#define LOAD_KERNEL(name) \
+ do { \
+ kernel_init_source = "#include \"kernels/opencl/kernel_" #name ".cl\" // " + \
+ kernel_md5 + "\n"; \
+ device_md5 = device_md5_hash(build_options); \
+ clbin = string_printf("cycles_kernel_%s_%s_" #name ".clbin", \
+ device_md5.c_str(), kernel_md5.c_str()); \
+ if(opencl_kernel_use_debug()) { \
+ clsrc = string_printf("cycles_kernel_%s_%s_" #name ".cl", \
+ device_md5.c_str(), kernel_md5.c_str()); \
+ clsrc = path_user_get(path_join("cache", clsrc)); \
+ debug_src = &clsrc; \
+ } \
+ if(!load_split_kernel(kernel_path, kernel_init_source, clbin, \
+ build_options, \
+ &GLUE(name, _program), \
+ debug_src)) \
+ { \
+ fprintf(stderr, "Faled to compile %s\n", #name); \
+ return false; \
+ } \
+ } while(false)
+
+ LOAD_KERNEL(data_init);
+ LOAD_KERNEL(scene_intersect);
+ LOAD_KERNEL(lamp_emission);
+ LOAD_KERNEL(queue_enqueue);
+ LOAD_KERNEL(background_buffer_update);
+ LOAD_KERNEL(shader_eval);
+ LOAD_KERNEL(holdout_emission_blurring_pathtermination_ao);
+ LOAD_KERNEL(direct_lighting);
+ LOAD_KERNEL(shadow_blocked);
+ LOAD_KERNEL(next_iteration_setup);
+ LOAD_KERNEL(sum_all_radiance);
+
+#undef LOAD_KERNEL
+
+#define FIND_KERNEL(name) \
+ do { \
+ GLUE(ckPathTraceKernel_, name) = \
+ clCreateKernel(GLUE(name, _program), \
+ "kernel_ocl_path_trace_" #name, &ciErr); \
+ if(opencl_error(ciErr)) { \
+ fprintf(stderr,"Missing kernel kernel_ocl_path_trace_%s\n", #name); \
+ return false; \
+ } \
+ } while(false)
+
+ FIND_KERNEL(data_init);
+ FIND_KERNEL(scene_intersect);
+ FIND_KERNEL(lamp_emission);
+ FIND_KERNEL(queue_enqueue);
+ FIND_KERNEL(background_buffer_update);
+ FIND_KERNEL(shader_eval);
+ FIND_KERNEL(holdout_emission_blurring_pathtermination_ao);
+ FIND_KERNEL(direct_lighting);
+ FIND_KERNEL(shadow_blocked);
+ FIND_KERNEL(next_iteration_setup);
+ FIND_KERNEL(sum_all_radiance);
+#undef FIND_KERNEL
+#undef GLUE
+
+ current_max_closure = requested_features.max_closure;
+
+ return true;
+ }
+
+ ~OpenCLDeviceSplitKernel()
+ {
+ task_pool.stop();
+
+ /* Release kernels */
+ release_kernel_safe(ckPathTraceKernel_data_init);
+ release_kernel_safe(ckPathTraceKernel_scene_intersect);
+ release_kernel_safe(ckPathTraceKernel_lamp_emission);
+ release_kernel_safe(ckPathTraceKernel_queue_enqueue);
+ release_kernel_safe(ckPathTraceKernel_background_buffer_update);
+ release_kernel_safe(ckPathTraceKernel_shader_eval);
+ release_kernel_safe(ckPathTraceKernel_holdout_emission_blurring_pathtermination_ao);
+ release_kernel_safe(ckPathTraceKernel_direct_lighting);
+ release_kernel_safe(ckPathTraceKernel_shadow_blocked);
+ release_kernel_safe(ckPathTraceKernel_next_iteration_setup);
+ release_kernel_safe(ckPathTraceKernel_sum_all_radiance);
+
+ /* Release global memory */
+ release_mem_object_safe(P_sd);
+ release_mem_object_safe(P_sd_DL_shadow);
+ release_mem_object_safe(N_sd);
+ release_mem_object_safe(N_sd_DL_shadow);
+ release_mem_object_safe(Ng_sd);
+ release_mem_object_safe(Ng_sd_DL_shadow);
+ release_mem_object_safe(I_sd);
+ release_mem_object_safe(I_sd_DL_shadow);
+ release_mem_object_safe(shader_sd);
+ release_mem_object_safe(shader_sd_DL_shadow);
+ release_mem_object_safe(flag_sd);
+ release_mem_object_safe(flag_sd_DL_shadow);
+ release_mem_object_safe(prim_sd);
+ release_mem_object_safe(prim_sd_DL_shadow);
+ release_mem_object_safe(type_sd);
+ release_mem_object_safe(type_sd_DL_shadow);
+ release_mem_object_safe(u_sd);
+ release_mem_object_safe(u_sd_DL_shadow);
+ release_mem_object_safe(v_sd);
+ release_mem_object_safe(v_sd_DL_shadow);
+ release_mem_object_safe(object_sd);
+ release_mem_object_safe(object_sd_DL_shadow);
+ release_mem_object_safe(time_sd);
+ release_mem_object_safe(time_sd_DL_shadow);
+ release_mem_object_safe(ray_length_sd);
+ release_mem_object_safe(ray_length_sd_DL_shadow);
+ release_mem_object_safe(ray_depth_sd);
+ release_mem_object_safe(ray_depth_sd_DL_shadow);
+ release_mem_object_safe(transparent_depth_sd);
+ release_mem_object_safe(transparent_depth_sd_DL_shadow);
+
+ /* Ray differentials. */
+ release_mem_object_safe(dP_sd);
+ release_mem_object_safe(dP_sd_DL_shadow);
+ release_mem_object_safe(dI_sd);
+ release_mem_object_safe(dI_sd_DL_shadow);
+ release_mem_object_safe(du_sd);
+ release_mem_object_safe(du_sd_DL_shadow);
+ release_mem_object_safe(dv_sd);
+ release_mem_object_safe(dv_sd_DL_shadow);
+
+ /* Dp/Du */
+ release_mem_object_safe(dPdu_sd);
+ release_mem_object_safe(dPdu_sd_DL_shadow);
+ release_mem_object_safe(dPdv_sd);
+ release_mem_object_safe(dPdv_sd_DL_shadow);
+
+ /* Object motion. */
+ release_mem_object_safe(ob_tfm_sd);
+ release_mem_object_safe(ob_itfm_sd);
+
+ release_mem_object_safe(ob_tfm_sd_DL_shadow);
+ release_mem_object_safe(ob_itfm_sd_DL_shadow);
+
+ release_mem_object_safe(closure_sd);
+ release_mem_object_safe(closure_sd_DL_shadow);
+ release_mem_object_safe(num_closure_sd);
+ release_mem_object_safe(num_closure_sd_DL_shadow);
+ release_mem_object_safe(randb_closure_sd);
+ release_mem_object_safe(randb_closure_sd_DL_shadow);
+ release_mem_object_safe(ray_P_sd);
+ release_mem_object_safe(ray_P_sd_DL_shadow);
+ release_mem_object_safe(ray_dP_sd);
+ release_mem_object_safe(ray_dP_sd_DL_shadow);
+ release_mem_object_safe(rng_coop);
+ release_mem_object_safe(throughput_coop);
+ release_mem_object_safe(L_transparent_coop);
+ release_mem_object_safe(PathRadiance_coop);
+ release_mem_object_safe(Ray_coop);
+ release_mem_object_safe(PathState_coop);
+ release_mem_object_safe(Intersection_coop);
+ release_mem_object_safe(kgbuffer);
+ release_mem_object_safe(sd);
+ release_mem_object_safe(sd_DL_shadow);
+ release_mem_object_safe(ray_state);
+ release_mem_object_safe(AOAlpha_coop);
+ release_mem_object_safe(AOBSDF_coop);
+ release_mem_object_safe(AOLightRay_coop);
+ release_mem_object_safe(BSDFEval_coop);
+ release_mem_object_safe(ISLamp_coop);
+ release_mem_object_safe(LightRay_coop);
+ release_mem_object_safe(Intersection_coop_AO);
+ release_mem_object_safe(Intersection_coop_DL);
+#ifdef WITH_CYCLES_DEBUG
+ release_mem_object_safe(debugdata_coop);
+#endif
+ release_mem_object_safe(use_queues_flag);
+ release_mem_object_safe(Queue_data);
+ release_mem_object_safe(Queue_index);
+ release_mem_object_safe(work_array);
+#ifdef __WORK_STEALING__
+ release_mem_object_safe(work_pool_wgs);
+#endif
+ release_mem_object_safe(per_sample_output_buffers);
+
+ /* Release programs */
+ release_program_safe(data_init_program);
+ release_program_safe(scene_intersect_program);
+ release_program_safe(lamp_emission_program);
+ release_program_safe(queue_enqueue_program);
+ release_program_safe(background_buffer_update_program);
+ release_program_safe(shader_eval_program);
+ release_program_safe(holdout_emission_blurring_pathtermination_ao_program);
+ release_program_safe(direct_lighting_program);
+ release_program_safe(shadow_blocked_program);
+ release_program_safe(next_iteration_setup_program);
+ release_program_safe(sum_all_radiance_program);
+
+ if(hostRayStateArray != NULL) {
+ free(hostRayStateArray);
+ }
+ }
+
+ void path_trace(SplitRenderTile& rtile, int2 max_render_feasible_tile_size)
+ {
+ /* cast arguments to cl types */
+ cl_mem d_data = CL_MEM_PTR(const_mem_map["__data"]->device_pointer);
+ cl_mem d_buffer = CL_MEM_PTR(rtile.buffer);
+ cl_mem d_rng_state = CL_MEM_PTR(rtile.rng_state);
+ cl_int d_x = rtile.x;
+ cl_int d_y = rtile.y;
+ cl_int d_w = rtile.w;
+ cl_int d_h = rtile.h;
+ cl_int d_offset = rtile.offset;
+ cl_int d_stride = rtile.stride;
+
+ /* Make sure that set render feasible tile size is a multiple of local
+ * work size dimensions.
+ */
+ assert(max_render_feasible_tile_size.x % SPLIT_KERNEL_LOCAL_SIZE_X == 0);
+ assert(max_render_feasible_tile_size.y % SPLIT_KERNEL_LOCAL_SIZE_Y == 0);
+
+ size_t global_size[2];
+ size_t local_size[2] = {SPLIT_KERNEL_LOCAL_SIZE_X,
+ SPLIT_KERNEL_LOCAL_SIZE_Y};
+
+ /* Set the range of samples to be processed for every ray in
+ * path-regeneration logic.
+ */
+ cl_int start_sample = rtile.start_sample;
+ cl_int end_sample = rtile.start_sample + rtile.num_samples;
+ cl_int num_samples = rtile.num_samples;
+
+#ifdef __WORK_STEALING__
+ global_size[0] = (((d_w - 1) / local_size[0]) + 1) * local_size[0];
+ global_size[1] = (((d_h - 1) / local_size[1]) + 1) * local_size[1];
+ unsigned int num_parallel_samples = 1;
+#else
+ global_size[1] = (((d_h - 1) / local_size[1]) + 1) * local_size[1];
+ unsigned int num_threads = max_render_feasible_tile_size.x *
+ max_render_feasible_tile_size.y;
+ unsigned int num_tile_columns_possible = num_threads / global_size[1];
+ /* Estimate number of parallel samples that can be
+ * processed in parallel.
+ */
+ unsigned int num_parallel_samples = min(num_tile_columns_possible / d_w,
+ rtile.num_samples);
+ /* Wavefront size in AMD is 64.
+ * TODO(sergey): What about other platforms?
+ */
+ if(num_parallel_samples >= 64) {
+ /* TODO(sergey): Could use generic round-up here. */
+ num_parallel_samples = (num_parallel_samples / 64) * 64;
+ }
+ assert(num_parallel_samples != 0);
+
+ global_size[0] = d_w * num_parallel_samples;
+#endif /* __WORK_STEALING__ */
+
+ assert(global_size[0] * global_size[1] <=
+ max_render_feasible_tile_size.x * max_render_feasible_tile_size.y);
+
+ /* Allocate all required global memory once. */
+ if(first_tile) {
+ size_t num_global_elements = max_render_feasible_tile_size.x *
+ max_render_feasible_tile_size.y;
+ /* TODO(sergey): This will actually over-allocate if
+ * particular kernel does not support multiclosure.
+ */
+ size_t ShaderClosure_size = get_shader_closure_size(current_max_closure);
+
+#ifdef __WORK_STEALING__
+ /* Calculate max groups */
+ size_t max_global_size[2];
+ size_t tile_x = max_render_feasible_tile_size.x;
+ size_t tile_y = max_render_feasible_tile_size.y;
+ max_global_size[0] = (((tile_x - 1) / local_size[0]) + 1) * local_size[0];
+ max_global_size[1] = (((tile_y - 1) / local_size[1]) + 1) * local_size[1];
+ max_work_groups = (max_global_size[0] * max_global_size[1]) /
+ (local_size[0] * local_size[1]);
+ /* Allocate work_pool_wgs memory. */
+ work_pool_wgs = mem_alloc(max_work_groups * sizeof(unsigned int));
+#endif /* __WORK_STEALING__ */
+
+ /* Allocate queue_index memory only once. */
+ Queue_index = mem_alloc(NUM_QUEUES * sizeof(int));
+ use_queues_flag = mem_alloc(sizeof(char));
+ kgbuffer = mem_alloc(get_KernelGlobals_size());
+
+ /* Create global buffers for ShaderData. */
+ sd = mem_alloc(get_shaderdata_soa_size());
+ sd_DL_shadow = mem_alloc(get_shaderdata_soa_size());
+ P_sd = mem_alloc(num_global_elements * sizeof(float3));
+ P_sd_DL_shadow = mem_alloc(num_global_elements * 2 * sizeof(float3));
+ N_sd = mem_alloc(num_global_elements * sizeof(float3));
+ N_sd_DL_shadow = mem_alloc(num_global_elements * 2 * sizeof(float3));
+ Ng_sd = mem_alloc(num_global_elements * sizeof(float3));
+ Ng_sd_DL_shadow = mem_alloc(num_global_elements * 2 * sizeof(float3));
+ I_sd = mem_alloc(num_global_elements * sizeof(float3));
+ I_sd_DL_shadow = mem_alloc(num_global_elements * 2 * sizeof(float3));
+ shader_sd = mem_alloc(num_global_elements * sizeof(int));
+ shader_sd_DL_shadow = mem_alloc(num_global_elements * 2 * sizeof(int));
+ flag_sd = mem_alloc(num_global_elements * sizeof(int));
+ flag_sd_DL_shadow = mem_alloc(num_global_elements * 2 * sizeof(int));
+ prim_sd = mem_alloc(num_global_elements * sizeof(int));
+ prim_sd_DL_shadow = mem_alloc(num_global_elements * 2 * sizeof(int));
+ type_sd = mem_alloc(num_global_elements * sizeof(int));
+ type_sd_DL_shadow = mem_alloc(num_global_elements * 2 * sizeof(int));
+ u_sd = mem_alloc(num_global_elements * sizeof(float));
+ u_sd_DL_shadow = mem_alloc(num_global_elements * 2 * sizeof(float));
+ v_sd = mem_alloc(num_global_elements * sizeof(float));
+ v_sd_DL_shadow = mem_alloc(num_global_elements * 2 * sizeof(float));
+ object_sd = mem_alloc(num_global_elements * sizeof(int));
+ object_sd_DL_shadow = mem_alloc(num_global_elements * 2 * sizeof(int));
+ time_sd = mem_alloc(num_global_elements * sizeof(float));
+ time_sd_DL_shadow = mem_alloc(num_global_elements * 2 * sizeof(float));
+ ray_length_sd = mem_alloc(num_global_elements * sizeof(float));
+ ray_length_sd_DL_shadow = mem_alloc(num_global_elements * 2 * sizeof(float));
+ ray_depth_sd = mem_alloc(num_global_elements * sizeof(int));
+ ray_depth_sd_DL_shadow = mem_alloc(num_global_elements * 2 * sizeof(int));
+ transparent_depth_sd = mem_alloc(num_global_elements * sizeof(int));
+ transparent_depth_sd_DL_shadow = mem_alloc(num_global_elements * 2 * sizeof(int));
+
+ /* Ray differentials. */
+ dP_sd = mem_alloc(num_global_elements * sizeof(differential3));
+ dP_sd_DL_shadow = mem_alloc(num_global_elements * 2 * sizeof(differential3));
+ dI_sd = mem_alloc(num_global_elements * sizeof(differential3));
+ dI_sd_DL_shadow = mem_alloc(num_global_elements * 2 * sizeof(differential3));
+ du_sd = mem_alloc(num_global_elements * sizeof(differential));
+ du_sd_DL_shadow = mem_alloc(num_global_elements * 2 * sizeof(differential));
+ dv_sd = mem_alloc(num_global_elements * sizeof(differential));
+ dv_sd_DL_shadow = mem_alloc(num_global_elements * 2 * sizeof(differential));
+
+ /* Dp/Du */
+ dPdu_sd = mem_alloc(num_global_elements * sizeof(float3));
+ dPdu_sd_DL_shadow = mem_alloc(num_global_elements * 2 * sizeof(float3));
+ dPdv_sd = mem_alloc(num_global_elements * sizeof(float3));
+ dPdv_sd_DL_shadow = mem_alloc(num_global_elements * 2 * sizeof(float3));
+
+ /* Object motion. */
+ ob_tfm_sd = mem_alloc(num_global_elements * sizeof(Transform));
+ ob_tfm_sd_DL_shadow = mem_alloc(num_global_elements * 2 * sizeof(Transform));
+ ob_itfm_sd = mem_alloc(num_global_elements * sizeof(Transform));
+ ob_itfm_sd_DL_shadow = mem_alloc(num_global_elements * 2 * sizeof(Transform));
+
+ closure_sd = mem_alloc(num_global_elements * ShaderClosure_size);
+ closure_sd_DL_shadow = mem_alloc(num_global_elements * 2 * ShaderClosure_size);
+ num_closure_sd = mem_alloc(num_global_elements * sizeof(int));
+ num_closure_sd_DL_shadow = mem_alloc(num_global_elements * 2 * sizeof(int));
+ randb_closure_sd = mem_alloc(num_global_elements * sizeof(float));
+ randb_closure_sd_DL_shadow = mem_alloc(num_global_elements * 2 * sizeof(float));
+ ray_P_sd = mem_alloc(num_global_elements * sizeof(float3));
+ ray_P_sd_DL_shadow = mem_alloc(num_global_elements * 2 * sizeof(float3));
+ ray_dP_sd = mem_alloc(num_global_elements * sizeof(differential3));
+ ray_dP_sd_DL_shadow = mem_alloc(num_global_elements * 2 * sizeof(differential3));
+
+ /* Creation of global memory buffers which are shared among
+ * the kernels.
+ */
+ rng_coop = mem_alloc(num_global_elements * sizeof(RNG));
+ throughput_coop = mem_alloc(num_global_elements * sizeof(float3));
+ L_transparent_coop = mem_alloc(num_global_elements * sizeof(float));
+ PathRadiance_coop = mem_alloc(num_global_elements * sizeof(PathRadiance));
+ Ray_coop = mem_alloc(num_global_elements * sizeof(Ray));
+ PathState_coop = mem_alloc(num_global_elements * sizeof(PathState));
+ Intersection_coop = mem_alloc(num_global_elements * sizeof(Intersection));
+ AOAlpha_coop = mem_alloc(num_global_elements * sizeof(float3));
+ AOBSDF_coop = mem_alloc(num_global_elements * sizeof(float3));
+ AOLightRay_coop = mem_alloc(num_global_elements * sizeof(Ray));
+ BSDFEval_coop = mem_alloc(num_global_elements * sizeof(BsdfEval));
+ ISLamp_coop = mem_alloc(num_global_elements * sizeof(int));
+ LightRay_coop = mem_alloc(num_global_elements * sizeof(Ray));
+ Intersection_coop_AO = mem_alloc(num_global_elements * sizeof(Intersection));
+ Intersection_coop_DL = mem_alloc(num_global_elements * sizeof(Intersection));
+
+#ifdef WITH_CYCLES_DEBUG
+ debugdata_coop = mem_alloc(num_global_elements * sizeof(DebugData));
+#endif
+
+ ray_state = mem_alloc(num_global_elements * sizeof(char));
+
+ hostRayStateArray = (char *)calloc(num_global_elements, sizeof(char));
+ assert(hostRayStateArray != NULL && "Can't create hostRayStateArray memory");
+
+ Queue_data = mem_alloc(num_global_elements * (NUM_QUEUES * sizeof(int)+sizeof(int)));
+ work_array = mem_alloc(num_global_elements * sizeof(unsigned int));
+ per_sample_output_buffers = mem_alloc(num_global_elements *
+ per_thread_output_buffer_size);
+ }
+
+ cl_int dQueue_size = global_size[0] * global_size[1];
+ cl_int total_num_rays = global_size[0] * global_size[1];
+
+ cl_uint start_arg_index =
+ kernel_set_args(ckPathTraceKernel_data_init,
+ 0,
+ kgbuffer,
+ sd,
+ sd_DL_shadow,
+ P_sd,
+ P_sd_DL_shadow,
+ N_sd,
+ N_sd_DL_shadow,
+ Ng_sd,
+ Ng_sd_DL_shadow,
+ I_sd,
+ I_sd_DL_shadow,
+ shader_sd,
+ shader_sd_DL_shadow,
+ flag_sd,
+ flag_sd_DL_shadow,
+ prim_sd,
+ prim_sd_DL_shadow,
+ type_sd,
+ type_sd_DL_shadow,
+ u_sd,
+ u_sd_DL_shadow,
+ v_sd,
+ v_sd_DL_shadow,
+ object_sd,
+ object_sd_DL_shadow,
+ time_sd,
+ time_sd_DL_shadow,
+ ray_length_sd,
+ ray_length_sd_DL_shadow,
+ ray_depth_sd,
+ ray_depth_sd_DL_shadow,
+ transparent_depth_sd,
+ transparent_depth_sd_DL_shadow);
+
+ /* Ray differentials. */
+ start_arg_index +=
+ kernel_set_args(ckPathTraceKernel_data_init,
+ start_arg_index,
+ dP_sd,
+ dP_sd_DL_shadow,
+ dI_sd,
+ dI_sd_DL_shadow,
+ du_sd,
+ du_sd_DL_shadow,
+ dv_sd,
+ dv_sd_DL_shadow);
+
+ /* Dp/Du */
+ start_arg_index +=
+ kernel_set_args(ckPathTraceKernel_data_init,
+ start_arg_index,
+ dPdu_sd,
+ dPdu_sd_DL_shadow,
+ dPdv_sd,
+ dPdv_sd_DL_shadow);
+
+ /* Object motion. */
+ start_arg_index +=
+ kernel_set_args(ckPathTraceKernel_data_init,
+ start_arg_index,
+ ob_tfm_sd,
+ ob_tfm_sd_DL_shadow,
+ ob_itfm_sd,
+ ob_itfm_sd_DL_shadow);
+
+ start_arg_index +=
+ kernel_set_args(ckPathTraceKernel_data_init,
+ start_arg_index,
+ closure_sd,
+ closure_sd_DL_shadow,
+ num_closure_sd,
+ num_closure_sd_DL_shadow,
+ randb_closure_sd,
+ randb_closure_sd_DL_shadow,
+ ray_P_sd,
+ ray_P_sd_DL_shadow,
+ ray_dP_sd,
+ ray_dP_sd_DL_shadow,
+ d_data,
+ per_sample_output_buffers,
+ d_rng_state,
+ rng_coop,
+ throughput_coop,
+ L_transparent_coop,
+ PathRadiance_coop,
+ Ray_coop,
+ PathState_coop,
+ ray_state);
+
+/* TODO(segrey): Avoid map lookup here. */
+#define KERNEL_TEX(type, ttype, name) \
+ set_kernel_arg_mem(ckPathTraceKernel_data_init, &start_arg_index, #name);
+#include "kernel_textures.h"
+#undef KERNEL_TEX
+
+ start_arg_index +=
+ kernel_set_args(ckPathTraceKernel_data_init,
+ start_arg_index,
+ start_sample,
+ d_x,
+ d_y,
+ d_w,
+ d_h,
+ d_offset,
+ d_stride,
+ rtile.rng_state_offset_x,
+ rtile.rng_state_offset_y,
+ rtile.buffer_rng_state_stride,
+ Queue_data,
+ Queue_index,
+ dQueue_size,
+ use_queues_flag,
+ work_array,
+#ifdef __WORK_STEALING__
+ work_pool_wgs,
+ num_samples,
+#endif
+#ifdef WITH_CYCLES_DEBUG
+ debugdata_coop,
+#endif
+ num_parallel_samples);
+
+ kernel_set_args(ckPathTraceKernel_scene_intersect,
+ 0,
+ kgbuffer,
+ d_data,
+ rng_coop,
+ Ray_coop,
+ PathState_coop,
+ Intersection_coop,
+ ray_state,
+ d_w,
+ d_h,
+ Queue_data,
+ Queue_index,
+ dQueue_size,
+ use_queues_flag,
+#ifdef WITH_CYCLES_DEBUG
+ debugdata_coop,
+#endif
+ num_parallel_samples);
+
+ kernel_set_args(ckPathTraceKernel_lamp_emission,
+ 0,
+ kgbuffer,
+ d_data,
+ sd,
+ throughput_coop,
+ PathRadiance_coop,
+ Ray_coop,
+ PathState_coop,
+ Intersection_coop,
+ ray_state,
+ d_w,
+ d_h,
+ Queue_data,
+ Queue_index,
+ dQueue_size,
+ use_queues_flag,
+ num_parallel_samples);
+
+ kernel_set_args(ckPathTraceKernel_queue_enqueue,
+ 0,
+ Queue_data,
+ Queue_index,
+ ray_state,
+ dQueue_size);
+
+ kernel_set_args(ckPathTraceKernel_background_buffer_update,
+ 0,
+ kgbuffer,
+ d_data,
+ sd,
+ per_sample_output_buffers,
+ d_rng_state,
+ rng_coop,
+ throughput_coop,
+ PathRadiance_coop,
+ Ray_coop,
+ PathState_coop,
+ L_transparent_coop,
+ ray_state,
+ d_w,
+ d_h,
+ d_x,
+ d_y,
+ d_stride,
+ rtile.rng_state_offset_x,
+ rtile.rng_state_offset_y,
+ rtile.buffer_rng_state_stride,
+ work_array,
+ Queue_data,
+ Queue_index,
+ dQueue_size,
+ end_sample,
+ start_sample,
+#ifdef __WORK_STEALING__
+ work_pool_wgs,
+ num_samples,
+#endif
+#ifdef WITH_CYCLES_DEBUG
+ debugdata_coop,
+#endif
+ num_parallel_samples);
+
+ kernel_set_args(ckPathTraceKernel_shader_eval,
+ 0,
+ kgbuffer,
+ d_data,
+ sd,
+ rng_coop,
+ Ray_coop,
+ PathState_coop,
+ Intersection_coop,
+ ray_state,
+ Queue_data,
+ Queue_index,
+ dQueue_size);
+
+ kernel_set_args(ckPathTraceKernel_holdout_emission_blurring_pathtermination_ao,
+ 0,
+ kgbuffer,
+ d_data,
+ sd,
+ per_sample_output_buffers,
+ rng_coop,
+ throughput_coop,
+ L_transparent_coop,
+ PathRadiance_coop,
+ PathState_coop,
+ Intersection_coop,
+ AOAlpha_coop,
+ AOBSDF_coop,
+ AOLightRay_coop,
+ d_w,
+ d_h,
+ d_x,
+ d_y,
+ d_stride,
+ ray_state,
+ work_array,
+ Queue_data,
+ Queue_index,
+ dQueue_size,
+#ifdef __WORK_STEALING__
+ start_sample,
+#endif
+ num_parallel_samples);
+
+ kernel_set_args(ckPathTraceKernel_direct_lighting,
+ 0,
+ kgbuffer,
+ d_data,
+ sd,
+ sd_DL_shadow,
+ rng_coop,
+ PathState_coop,
+ ISLamp_coop,
+ LightRay_coop,
+ BSDFEval_coop,
+ ray_state,
+ Queue_data,
+ Queue_index,
+ dQueue_size);
+
+ kernel_set_args(ckPathTraceKernel_shadow_blocked,
+ 0,
+ kgbuffer,
+ d_data,
+ sd_DL_shadow,
+ PathState_coop,
+ LightRay_coop,
+ AOLightRay_coop,
+ Intersection_coop_AO,
+ Intersection_coop_DL,
+ ray_state,
+ Queue_data,
+ Queue_index,
+ dQueue_size,
+ total_num_rays);
+
+ kernel_set_args(ckPathTraceKernel_next_iteration_setup,
+ 0,
+ kgbuffer,
+ d_data,
+ sd,
+ rng_coop,
+ throughput_coop,
+ PathRadiance_coop,
+ Ray_coop,
+ PathState_coop,
+ LightRay_coop,
+ ISLamp_coop,
+ BSDFEval_coop,
+ AOLightRay_coop,
+ AOBSDF_coop,
+ AOAlpha_coop,
+ ray_state,
+ Queue_data,
+ Queue_index,
+ dQueue_size,
+ use_queues_flag);
+
+ kernel_set_args(ckPathTraceKernel_sum_all_radiance,
+ 0,
+ d_data,
+ d_buffer,
+ per_sample_output_buffers,
+ num_parallel_samples,
+ d_w,
+ d_h,
+ d_stride,
+ rtile.buffer_offset_x,
+ rtile.buffer_offset_y,
+ rtile.buffer_rng_state_stride,
+ start_sample);
+
+ /* Macro for Enqueuing split kernels. */
+#define GLUE(a, b) a ## b
+#define ENQUEUE_SPLIT_KERNEL(kernelName, globalSize, localSize) \
+ { \
+ ciErr = clEnqueueNDRangeKernel(cqCommandQueue, \
+ GLUE(ckPathTraceKernel_, \
+ kernelName), \
+ 2, \
+ NULL, \
+ globalSize, \
+ localSize, \
+ 0, \
+ NULL, \
+ NULL); \
+ opencl_assert_err(ciErr, "clEnqueueNDRangeKernel"); \
+ if(ciErr != CL_SUCCESS) { \
+ string message = string_printf("OpenCL error: %s in clEnqueueNDRangeKernel()", \
+ clewErrorString(ciErr)); \
+ opencl_error(message); \
+ return; \
+ } \
+ } (void) 0
+
+ /* Enqueue ckPathTraceKernel_data_init kernel. */
+ ENQUEUE_SPLIT_KERNEL(data_init, global_size, local_size);
+ bool activeRaysAvailable = true;
+
+ /* Record number of time host intervention has been made */
+ unsigned int numHostIntervention = 0;
+ unsigned int numNextPathIterTimes = PathIteration_times;
+ while(activeRaysAvailable) {
+ /* Twice the global work size of other kernels for
+ * ckPathTraceKernel_shadow_blocked_direct_lighting. */
+ size_t global_size_shadow_blocked[2];
+ global_size_shadow_blocked[0] = global_size[0] * 2;
+ global_size_shadow_blocked[1] = global_size[1];
+
+ /* Do path-iteration in host [Enqueue Path-iteration kernels. */
+ for(int PathIter = 0; PathIter < PathIteration_times; PathIter++) {
+ ENQUEUE_SPLIT_KERNEL(scene_intersect, global_size, local_size);
+ ENQUEUE_SPLIT_KERNEL(lamp_emission, global_size, local_size);
+ ENQUEUE_SPLIT_KERNEL(queue_enqueue, global_size, local_size);
+ ENQUEUE_SPLIT_KERNEL(background_buffer_update, global_size, local_size);
+ ENQUEUE_SPLIT_KERNEL(shader_eval, global_size, local_size);
+ ENQUEUE_SPLIT_KERNEL(holdout_emission_blurring_pathtermination_ao, global_size, local_size);
+ ENQUEUE_SPLIT_KERNEL(direct_lighting, global_size, local_size);
+ ENQUEUE_SPLIT_KERNEL(shadow_blocked, global_size_shadow_blocked, local_size);
+ ENQUEUE_SPLIT_KERNEL(next_iteration_setup, global_size, local_size);
+ }
+
+ /* Read ray-state into Host memory to decide if we should exit
+ * path-iteration in host.
+ */
+ ciErr = clEnqueueReadBuffer(cqCommandQueue,
+ ray_state,
+ CL_TRUE,
+ 0,
+ global_size[0] * global_size[1] * sizeof(char),
+ hostRayStateArray,
+ 0,
+ NULL,
+ NULL);
+ assert(ciErr == CL_SUCCESS);
+
+ activeRaysAvailable = false;
+
+ for(int rayStateIter = 0;
+ rayStateIter < global_size[0] * global_size[1];
+ ++rayStateIter)
+ {
+ if(int8_t(hostRayStateArray[rayStateIter]) != RAY_INACTIVE) {
+ /* Not all rays are RAY_INACTIVE. */
+ activeRaysAvailable = true;
+ break;
+ }
+ }
+
+ if(activeRaysAvailable) {
+ numHostIntervention++;
+ PathIteration_times = PATH_ITER_INC_FACTOR;
+ /* Host intervention done before all rays become RAY_INACTIVE;
+ * Set do more initial iterations for the next tile.
+ */
+ numNextPathIterTimes += PATH_ITER_INC_FACTOR;
+ }
+ }
+
+ /* Execute SumALLRadiance kernel to accumulate radiance calculated in
+ * per_sample_output_buffers into RenderTile's output buffer.
+ */
+ size_t sum_all_radiance_local_size[2] = {16, 16};
+ size_t sum_all_radiance_global_size[2];
+ sum_all_radiance_global_size[0] =
+ (((d_w - 1) / sum_all_radiance_local_size[0]) + 1) *
+ sum_all_radiance_local_size[0];
+ sum_all_radiance_global_size[1] =
+ (((d_h - 1) / sum_all_radiance_local_size[1]) + 1) *
+ sum_all_radiance_local_size[1];
+ ENQUEUE_SPLIT_KERNEL(sum_all_radiance,
+ sum_all_radiance_global_size,
+ sum_all_radiance_local_size);
+
+#undef ENQUEUE_SPLIT_KERNEL
+#undef GLUE
+
+ if(numHostIntervention == 0) {
+ /* This means that we are executing kernel more than required
+ * Must avoid this for the next sample/tile.
+ */
+ PathIteration_times = ((numNextPathIterTimes - PATH_ITER_INC_FACTOR) <= 0) ?
+ PATH_ITER_INC_FACTOR : numNextPathIterTimes - PATH_ITER_INC_FACTOR;
+ }
+ else {
+ /* Number of path-iterations done for this tile is set as
+ * Initial path-iteration times for the next tile
+ */
+ PathIteration_times = numNextPathIterTimes;
+ }
+
+ first_tile = false;
+ }
+
+ /* Calculates the amount of memory that has to be always
+ * allocated in order for the split kernel to function.
+ * This memory is tile/scene-property invariant (meaning,
+ * the value returned by this function does not depend
+ * on the user set tile size or scene properties.
+ */
+ size_t get_invariable_mem_allocated()
+ {
+ size_t total_invariable_mem_allocated = 0;
+ size_t KernelGlobals_size = 0;
+ size_t ShaderData_SOA_size = 0;
+
+ KernelGlobals_size = get_KernelGlobals_size();
+ ShaderData_SOA_size = get_shaderdata_soa_size();
+
+ total_invariable_mem_allocated += KernelGlobals_size; /* KernelGlobals size */
+ total_invariable_mem_allocated += NUM_QUEUES * sizeof(unsigned int); /* Queue index size */
+ total_invariable_mem_allocated += sizeof(char); /* use_queues_flag size */
+ total_invariable_mem_allocated += ShaderData_SOA_size; /* sd size */
+ total_invariable_mem_allocated += ShaderData_SOA_size; /* sd_DL_shadow size */
+
+ return total_invariable_mem_allocated;
+ }
+
+ /* Calculate the memory that has-to-be/has-been allocated for
+ * the split kernel to function.
+ */
+ size_t get_tile_specific_mem_allocated(const int2 tile_size)
+ {
+ size_t tile_specific_mem_allocated = 0;
+
+ /* Get required tile info */
+ unsigned int user_set_tile_w = tile_size.x;
+ unsigned int user_set_tile_h = tile_size.y;
+
+#ifdef __WORK_STEALING__
+ /* Calculate memory to be allocated for work_pools in
+ * case of work_stealing.
+ */
+ size_t max_global_size[2];
+ size_t max_num_work_pools = 0;
+ max_global_size[0] =
+ (((user_set_tile_w - 1) / SPLIT_KERNEL_LOCAL_SIZE_X) + 1) *
+ SPLIT_KERNEL_LOCAL_SIZE_X;
+ max_global_size[1] =
+ (((user_set_tile_h - 1) / SPLIT_KERNEL_LOCAL_SIZE_Y) + 1) *
+ SPLIT_KERNEL_LOCAL_SIZE_Y;
+ max_num_work_pools =
+ (max_global_size[0] * max_global_size[1]) /
+ (SPLIT_KERNEL_LOCAL_SIZE_X * SPLIT_KERNEL_LOCAL_SIZE_Y);
+ tile_specific_mem_allocated += max_num_work_pools * sizeof(unsigned int);
+#endif
+
+ tile_specific_mem_allocated +=
+ user_set_tile_w * user_set_tile_h * per_thread_output_buffer_size;
+ tile_specific_mem_allocated +=
+ user_set_tile_w * user_set_tile_h * sizeof(RNG);
+
+ return tile_specific_mem_allocated;
+ }
+
+ /* Calculates the texture memories and KernelData (d_data) memory
+ * that has been allocated.
+ */
+ size_t get_scene_specific_mem_allocated(cl_mem d_data)
+ {
+ size_t scene_specific_mem_allocated = 0;
+ /* Calculate texture memories. */
+#define KERNEL_TEX(type, ttype, name) \
+ scene_specific_mem_allocated += get_tex_size(#name);
+#include "kernel_textures.h"
+#undef KERNEL_TEX
+ size_t d_data_size;
+ ciErr = clGetMemObjectInfo(d_data,
+ CL_MEM_SIZE,
+ sizeof(d_data_size),
+ &d_data_size,
+ NULL);
+ assert(ciErr == CL_SUCCESS && "Can't get d_data mem object info");
+ scene_specific_mem_allocated += d_data_size;
+ return scene_specific_mem_allocated;
+ }
+
+ /* Calculate the memory required for one thread in split kernel. */
+ size_t get_per_thread_memory()
+ {
+ size_t shader_closure_size = 0;
+ size_t shaderdata_volume = 0;
+ shader_closure_size = get_shader_closure_size(current_max_closure);
+ /* TODO(sergey): This will actually over-allocate if
+ * particular kernel does not support multiclosure.
+ */
+ shaderdata_volume = get_shader_data_size(shader_closure_size);
+ size_t retval = sizeof(RNG)
+ + sizeof(float3) /* Throughput size */
+ + sizeof(float) /* L transparent size */
+ + sizeof(char) /* Ray state size */
+ + sizeof(unsigned int) /* Work element size */
+ + sizeof(int) /* ISLamp_size */
+ + sizeof(PathRadiance) + sizeof(Ray) + sizeof(PathState)
+ + sizeof(Intersection) /* Overall isect */
+ + sizeof(Intersection) /* Instersection_coop_AO */
+ + sizeof(Intersection) /* Intersection coop DL */
+ + shaderdata_volume /* Overall ShaderData */
+ + (shaderdata_volume * 2) /* ShaderData : DL and shadow */
+ + sizeof(Ray) + sizeof(BsdfEval)
+ + sizeof(float3) /* AOAlpha size */
+ + sizeof(float3) /* AOBSDF size */
+ + sizeof(Ray)
+ + (sizeof(int) * NUM_QUEUES)
+ + per_thread_output_buffer_size;
+ return retval;
+ }
+
+ /* Considers the total memory available in the device and
+ * and returns the maximum global work size possible.
+ */
+ size_t get_feasible_global_work_size(int2 tile_size, cl_mem d_data)
+ {
+ /* Calculate invariably allocated memory. */
+ size_t invariable_mem_allocated = get_invariable_mem_allocated();
+ /* Calculate tile specific allocated memory. */
+ size_t tile_specific_mem_allocated =
+ get_tile_specific_mem_allocated(tile_size);
+ /* Calculate scene specific allocated memory. */
+ size_t scene_specific_mem_allocated =
+ get_scene_specific_mem_allocated(d_data);
+ /* Calculate total memory available for the threads in global work size. */
+ size_t available_memory = total_allocatable_memory
+ - invariable_mem_allocated
+ - tile_specific_mem_allocated
+ - scene_specific_mem_allocated
+ - DATA_ALLOCATION_MEM_FACTOR;
+ size_t per_thread_memory_required = get_per_thread_memory();
+ return (available_memory / per_thread_memory_required);
+ }
+
+ /* Checks if the device has enough memory to render the whole tile;
+ * If not, we should split single tile into multiple tiles of small size
+ * and process them all.
+ */
+ bool need_to_split_tile(unsigned int d_w,
+ unsigned int d_h,
+ int2 max_render_feasible_tile_size)
+ {
+ size_t global_size_estimate[2];
+ /* TODO(sergey): Such round-ups are in quite few places, need to replace
+ * them with an utility macro.
+ */
+ global_size_estimate[0] =
+ (((d_w - 1) / SPLIT_KERNEL_LOCAL_SIZE_X) + 1) *
+ SPLIT_KERNEL_LOCAL_SIZE_X;
+ global_size_estimate[1] =
+ (((d_h - 1) / SPLIT_KERNEL_LOCAL_SIZE_Y) + 1) *
+ SPLIT_KERNEL_LOCAL_SIZE_Y;
+ if((global_size_estimate[0] * global_size_estimate[1]) >
+ (max_render_feasible_tile_size.x * max_render_feasible_tile_size.y))
{
- run = function_bind(&OpenCLDevice::thread_run, device, this);
+ return true;
}
- };
+ else {
+ return false;
+ }
+ }
- int get_split_task_count(DeviceTask& task)
+ /* Considers the scene properties, global memory available in the device
+ * and returns a rectanglular tile dimension (approx the maximum)
+ * that should render on split kernel.
+ */
+ int2 get_max_render_feasible_tile_size(size_t feasible_global_work_size)
{
- return 1;
+ int2 max_render_feasible_tile_size;
+ int square_root_val = (int)sqrt(feasible_global_work_size);
+ max_render_feasible_tile_size.x = square_root_val;
+ max_render_feasible_tile_size.y = square_root_val;
+ /* Ciel round-off max_render_feasible_tile_size. */
+ int2 ceil_render_feasible_tile_size;
+ ceil_render_feasible_tile_size.x =
+ (((max_render_feasible_tile_size.x - 1) / SPLIT_KERNEL_LOCAL_SIZE_X) + 1) *
+ SPLIT_KERNEL_LOCAL_SIZE_X;
+ ceil_render_feasible_tile_size.y =
+ (((max_render_feasible_tile_size.y - 1) / SPLIT_KERNEL_LOCAL_SIZE_Y) + 1) *
+ SPLIT_KERNEL_LOCAL_SIZE_Y;
+ if(ceil_render_feasible_tile_size.x * ceil_render_feasible_tile_size.y <=
+ feasible_global_work_size)
+ {
+ return ceil_render_feasible_tile_size;
+ }
+ /* Floor round-off max_render_feasible_tile_size. */
+ int2 floor_render_feasible_tile_size;
+ floor_render_feasible_tile_size.x =
+ (max_render_feasible_tile_size.x / SPLIT_KERNEL_LOCAL_SIZE_X) *
+ SPLIT_KERNEL_LOCAL_SIZE_X;
+ floor_render_feasible_tile_size.y =
+ (max_render_feasible_tile_size.y / SPLIT_KERNEL_LOCAL_SIZE_Y) *
+ SPLIT_KERNEL_LOCAL_SIZE_Y;
+ return floor_render_feasible_tile_size;
}
- void task_add(DeviceTask& task)
+ /* Try splitting the current tile into multiple smaller
+ * almost-square-tiles.
+ */
+ int2 get_split_tile_size(RenderTile rtile,
+ int2 max_render_feasible_tile_size)
{
- task_pool.push(new OpenCLDeviceTask(this, task));
+ int2 split_tile_size;
+ int num_global_threads = max_render_feasible_tile_size.x *
+ max_render_feasible_tile_size.y;
+ int d_w = rtile.w;
+ int d_h = rtile.h;
+ /* Ceil round off d_w and d_h */
+ d_w = (((d_w - 1) / SPLIT_KERNEL_LOCAL_SIZE_X) + 1) *
+ SPLIT_KERNEL_LOCAL_SIZE_X;
+ d_h = (((d_h - 1) / SPLIT_KERNEL_LOCAL_SIZE_Y) + 1) *
+ SPLIT_KERNEL_LOCAL_SIZE_Y;
+ while(d_w * d_h > num_global_threads) {
+ /* Halve the longer dimension. */
+ if(d_w >= d_h) {
+ d_w = d_w / 2;
+ d_w = (((d_w - 1) / SPLIT_KERNEL_LOCAL_SIZE_X) + 1) *
+ SPLIT_KERNEL_LOCAL_SIZE_X;
+ }
+ else {
+ d_h = d_h / 2;
+ d_h = (((d_h - 1) / SPLIT_KERNEL_LOCAL_SIZE_Y) + 1) *
+ SPLIT_KERNEL_LOCAL_SIZE_Y;
+ }
+ }
+ split_tile_size.x = d_w;
+ split_tile_size.y = d_h;
+ return split_tile_size;
}
- void task_wait()
+ /* Splits existing tile into multiple tiles of tile size split_tile_size. */
+ vector<SplitRenderTile> split_tiles(RenderTile rtile, int2 split_tile_size)
{
- task_pool.wait();
+ vector<SplitRenderTile> to_path_trace_rtile;
+ int d_w = rtile.w;
+ int d_h = rtile.h;
+ int num_tiles_x = (((d_w - 1) / split_tile_size.x) + 1);
+ int num_tiles_y = (((d_h - 1) / split_tile_size.y) + 1);
+ /* Buffer and rng_state offset calc. */
+ size_t offset_index = rtile.offset + (rtile.x + rtile.y * rtile.stride);
+ size_t offset_x = offset_index % rtile.stride;
+ size_t offset_y = offset_index / rtile.stride;
+ /* Resize to_path_trace_rtile. */
+ to_path_trace_rtile.resize(num_tiles_x * num_tiles_y);
+ for(int tile_iter_y = 0; tile_iter_y < num_tiles_y; tile_iter_y++) {
+ for(int tile_iter_x = 0; tile_iter_x < num_tiles_x; tile_iter_x++) {
+ int rtile_index = tile_iter_y * num_tiles_x + tile_iter_x;
+ to_path_trace_rtile[rtile_index].rng_state_offset_x = offset_x + tile_iter_x * split_tile_size.x;
+ to_path_trace_rtile[rtile_index].rng_state_offset_y = offset_y + tile_iter_y * split_tile_size.y;
+ to_path_trace_rtile[rtile_index].buffer_offset_x = offset_x + tile_iter_x * split_tile_size.x;
+ to_path_trace_rtile[rtile_index].buffer_offset_y = offset_y + tile_iter_y * split_tile_size.y;
+ to_path_trace_rtile[rtile_index].start_sample = rtile.start_sample;
+ to_path_trace_rtile[rtile_index].num_samples = rtile.num_samples;
+ to_path_trace_rtile[rtile_index].sample = rtile.sample;
+ to_path_trace_rtile[rtile_index].resolution = rtile.resolution;
+ to_path_trace_rtile[rtile_index].offset = rtile.offset;
+ to_path_trace_rtile[rtile_index].buffers = rtile.buffers;
+ to_path_trace_rtile[rtile_index].buffer = rtile.buffer;
+ to_path_trace_rtile[rtile_index].rng_state = rtile.rng_state;
+ to_path_trace_rtile[rtile_index].x = rtile.x + (tile_iter_x * split_tile_size.x);
+ to_path_trace_rtile[rtile_index].y = rtile.y + (tile_iter_y * split_tile_size.y);
+ to_path_trace_rtile[rtile_index].buffer_rng_state_stride = rtile.stride;
+ /* Fill width and height of the new render tile. */
+ to_path_trace_rtile[rtile_index].w = (tile_iter_x == (num_tiles_x - 1)) ?
+ (d_w - (tile_iter_x * split_tile_size.x)) /* Border tile */
+ : split_tile_size.x;
+ to_path_trace_rtile[rtile_index].h = (tile_iter_y == (num_tiles_y - 1)) ?
+ (d_h - (tile_iter_y * split_tile_size.y)) /* Border tile */
+ : split_tile_size.y;
+ to_path_trace_rtile[rtile_index].stride = to_path_trace_rtile[rtile_index].w;
+ }
+ }
+ return to_path_trace_rtile;
}
- void task_cancel()
+ void thread_run(DeviceTask *task)
{
- task_pool.cancel();
+ if(task->type == DeviceTask::FILM_CONVERT) {
+ film_convert(*task, task->buffer, task->rgba_byte, task->rgba_half);
+ }
+ else if(task->type == DeviceTask::SHADER) {
+ shader(*task);
+ }
+ else if(task->type == DeviceTask::PATH_TRACE) {
+ RenderTile tile;
+ bool initialize_data_and_check_render_feasibility = false;
+ bool need_to_split_tiles_further = false;
+ int2 max_render_feasible_tile_size;
+ size_t feasible_global_work_size;
+ const int2 tile_size = task->requested_tile_size;
+ /* Keep rendering tiles until done. */
+ while(task->acquire_tile(this, tile)) {
+ if(!initialize_data_and_check_render_feasibility) {
+ /* Initialize data. */
+ /* Calculate per_thread_output_buffer_size. */
+ size_t output_buffer_size = 0;
+ ciErr = clGetMemObjectInfo((cl_mem)tile.buffer,
+ CL_MEM_SIZE,
+ sizeof(output_buffer_size),
+ &output_buffer_size,
+ NULL);
+ assert(ciErr == CL_SUCCESS && "Can't get tile.buffer mem object info");
+ /* This value is different when running on AMD and NV. */
+ if(background) {
+ /* In offline render the number of buffer elements
+ * associated with tile.buffer is the current tile size.
+ */
+ per_thread_output_buffer_size =
+ output_buffer_size / (tile.w * tile.h);
+ }
+ else {
+ /* interactive rendering, unlike offline render, the number of buffer elements
+ * associated with tile.buffer is the entire viewport size.
+ */
+ per_thread_output_buffer_size =
+ output_buffer_size / (tile.buffers->params.width *
+ tile.buffers->params.height);
+ }
+ /* Check render feasibility. */
+ feasible_global_work_size = get_feasible_global_work_size(
+ tile_size,
+ CL_MEM_PTR(const_mem_map["__data"]->device_pointer));
+ max_render_feasible_tile_size =
+ get_max_render_feasible_tile_size(
+ feasible_global_work_size);
+ need_to_split_tiles_further =
+ need_to_split_tile(tile_size.x,
+ tile_size.y,
+ max_render_feasible_tile_size);
+ initialize_data_and_check_render_feasibility = true;
+ }
+ if(need_to_split_tiles_further) {
+ int2 split_tile_size =
+ get_split_tile_size(tile,
+ max_render_feasible_tile_size);
+ vector<SplitRenderTile> to_path_trace_render_tiles =
+ split_tiles(tile, split_tile_size);
+ /* Print message to console */
+ if(background && (to_path_trace_render_tiles.size() > 1)) {
+ fprintf(stderr, "Message : Tiles need to be split "
+ "further inside path trace (due to insufficient "
+ "device-global-memory for split kernel to "
+ "function) \n"
+ "The current tile of dimensions %dx%d is split "
+ "into tiles of dimension %dx%d for render \n",
+ tile.w, tile.h,
+ split_tile_size.x,
+ split_tile_size.y);
+ }
+ /* Process all split tiles. */
+ for(int tile_iter = 0;
+ tile_iter < to_path_trace_render_tiles.size();
+ ++tile_iter)
+ {
+ path_trace(to_path_trace_render_tiles[tile_iter],
+ max_render_feasible_tile_size);
+ }
+ }
+ else {
+ /* No splitting required; process the entire tile at once. */
+ /* Render feasible tile size is user-set-tile-size itself. */
+ max_render_feasible_tile_size.x =
+ (((tile_size.x - 1) / SPLIT_KERNEL_LOCAL_SIZE_X) + 1) *
+ SPLIT_KERNEL_LOCAL_SIZE_X;
+ max_render_feasible_tile_size.y =
+ (((tile_size.y - 1) / SPLIT_KERNEL_LOCAL_SIZE_Y) + 1) *
+ SPLIT_KERNEL_LOCAL_SIZE_Y;
+ /* buffer_rng_state_stride is stride itself. */
+ SplitRenderTile split_tile(tile);
+ split_tile.buffer_rng_state_stride = tile.stride;
+ path_trace(split_tile, max_render_feasible_tile_size);
+ }
+ tile.sample = tile.start_sample + tile.num_samples;
+
+ /* Complete kernel execution before release tile. */
+ /* This helps in multi-device render;
+ * The device that reaches the critical-section function
+ * release_tile waits (stalling other devices from entering
+ * release_tile) for all kernels to complete. If device1 (a
+ * slow-render device) reaches release_tile first then it would
+ * stall device2 (a fast-render device) from proceeding to render
+ * next tile.
+ */
+ clFinish(cqCommandQueue);
+
+ task->release_tile(tile);
+ }
+ }
+ }
+
+protected:
+ cl_mem mem_alloc(size_t bufsize, cl_mem_flags mem_flag = CL_MEM_READ_WRITE)
+ {
+ cl_mem ptr;
+ assert(bufsize != 0);
+ ptr = clCreateBuffer(cxContext, mem_flag, bufsize, NULL, &ciErr);
+ opencl_assert_err(ciErr, "clCreateBuffer");
+ return ptr;
+ }
+
+ /* ** Those guys are for workign around some compiler-specific bugs ** */
+
+ cl_program load_cached_kernel(
+ const DeviceRequestedFeatures& /*requested_features*/,
+ OpenCLCache::ProgramName /*program_name*/,
+ thread_scoped_lock /*cache_locker*/)
+ {
+ VLOG(2) << "Skip loading kernel from cache, "
+ << "not supported by split kernel.";
+ return NULL;
+ }
+
+ void store_cached_kernel(cl_platform_id /*platform*/,
+ cl_device_id /*device*/,
+ cl_program /*program*/,
+ OpenCLCache::ProgramName /*program_name*/,
+ thread_scoped_lock& /*slot_locker*/)
+ {
+ VLOG(2) << "Skip storing kernel in cache, "
+ << "not supported by split kernel.";
+ }
+
+ string build_options_for_base_program(
+ const DeviceRequestedFeatures& requested_features)
+ {
+ return build_options_from_requested_features(requested_features);
}
};
Device *device_opencl_create(DeviceInfo& info, Stats &stats, bool background)
{
- return new OpenCLDevice(info, stats, background);
+ vector<OpenCLPlatformDevice> usable_devices;
+ opencl_get_usable_devices(&usable_devices);
+ assert(info.num < usable_devices.size());
+ const OpenCLPlatformDevice& platform_device = usable_devices[info.num];
+ const string& platform_name = platform_device.platform_name;
+ const cl_device_type device_type = platform_device.device_type;
+ if(opencl_kernel_use_split(platform_name, device_type)) {
+ VLOG(1) << "Using split kernel.";
+ return new OpenCLDeviceSplitKernel(info, stats, background);
+ } else {
+ VLOG(1) << "Using mega kernel.";
+ return new OpenCLDeviceMegaKernel(info, stats, background);
+ }
}
-bool device_opencl_init(void) {
+bool device_opencl_init(void)
+{
static bool initialized = false;
static bool result = false;
- if (initialized)
+ if(initialized)
return result;
initialized = true;
- // OpenCL disabled for now, only works with this environment variable set
- if(!getenv("CYCLES_OPENCL_TEST")) {
- result = false;
+ if(opencl_device_type() != 0) {
+ int clew_result = clewInit();
+ if(clew_result == CLEW_SUCCESS) {
+ VLOG(1) << "CLEW initialization succeeded.";
+ result = true;
+ }
+ else {
+ VLOG(1) << "CLEW initialization failed: "
+ << ((clew_result == CLEW_ERROR_ATEXIT_FAILED)
+ ? "Error setting up atexit() handler"
+ : "Error opening the library");
+ }
}
else {
- result = clewInit() == CLEW_SUCCESS;
+ VLOG(1) << "Skip initializing CLEW, platform is force disabled.";
+ result = false;
}
return result;
@@ -1136,62 +3634,108 @@ bool device_opencl_init(void) {
void device_opencl_info(vector<DeviceInfo>& devices)
{
- vector<cl_device_id> device_ids;
- cl_uint num_devices = 0;
- vector<cl_platform_id> platform_ids;
+ vector<OpenCLPlatformDevice> usable_devices;
+ opencl_get_usable_devices(&usable_devices);
+ /* Devices are numbered consecutively across platforms. */
+ int num_devices = 0;
+ foreach(OpenCLPlatformDevice& platform_device, usable_devices) {
+ const string& platform_name = platform_device.platform_name;
+ const cl_device_type device_type = platform_device.device_type;
+ const string& device_name = platform_device.device_name;
+ DeviceInfo info;
+ info.type = DEVICE_OPENCL;
+ info.description = string_remove_trademark(string(device_name));
+ info.num = num_devices;
+ info.id = string_printf("OPENCL_%d", info.num);
+ /* We don't know if it's used for display, but assume it is. */
+ info.display_device = true;
+ info.advanced_shading = opencl_kernel_use_advanced_shading(platform_name);
+ info.pack_images = true;
+ info.use_split_kernel = opencl_kernel_use_split(platform_name,
+ device_type);
+ devices.push_back(info);
+ num_devices++;
+ }
+}
+
+string device_opencl_capabilities(void)
+{
+ if(opencl_device_type() == 0) {
+ return "All OpenCL devices are forced to be OFF";
+ }
+ string result = "";
+ string error_msg = ""; /* Only used by opencl_assert(), but in the future
+ * it could also be nicely reported to the console.
+ */
cl_uint num_platforms = 0;
+ opencl_assert(clGetPlatformIDs(0, NULL, &num_platforms));
+ if(num_platforms == 0) {
+ return "No OpenCL platforms found\n";
+ }
+ result += string_printf("Number of platforms: %u\n", num_platforms);
- /* get devices */
- if(clGetPlatformIDs(0, NULL, &num_platforms) != CL_SUCCESS || num_platforms == 0)
- return;
-
+ vector<cl_platform_id> platform_ids;
platform_ids.resize(num_platforms);
+ opencl_assert(clGetPlatformIDs(num_platforms, &platform_ids[0], NULL));
+
+#define APPEND_STRING_INFO(func, id, name, what) \
+ do { \
+ char data[1024] = "\0"; \
+ opencl_assert(func(id, what, sizeof(data), &data, NULL)); \
+ result += string_printf("%s: %s\n", name, data); \
+ } while(false)
+#define APPEND_PLATFORM_STRING_INFO(id, name, what) \
+ APPEND_STRING_INFO(clGetPlatformInfo, id, "\tPlatform " name, what)
+#define APPEND_DEVICE_STRING_INFO(id, name, what) \
+ APPEND_STRING_INFO(clGetDeviceInfo, id, "\t\t\tDevice " name, what)
- if(clGetPlatformIDs(num_platforms, &platform_ids[0], NULL) != CL_SUCCESS)
- return;
-
- /* devices are numbered consecutively across platforms */
- int num_base = 0;
-
- for (int platform = 0; platform < num_platforms; platform++, num_base += num_devices) {
- num_devices = 0;
- if(clGetDeviceIDs(platform_ids[platform], opencl_device_type(), 0, NULL, &num_devices) != CL_SUCCESS || num_devices == 0)
- continue;
-
- device_ids.resize(num_devices);
-
- if(clGetDeviceIDs(platform_ids[platform], opencl_device_type(), num_devices, &device_ids[0], NULL) != CL_SUCCESS)
- continue;
-
- char pname[256];
- clGetPlatformInfo(platform_ids[platform], CL_PLATFORM_NAME, sizeof(pname), &pname, NULL);
- string platform_name = pname;
-
- /* add devices */
- for(int num = 0; num < num_devices; num++) {
- cl_device_id device_id = device_ids[num];
- char name[1024] = "\0";
+ vector<cl_device_id> device_ids;
+ for (cl_uint platform = 0; platform < num_platforms; ++platform) {
+ cl_platform_id platform_id = platform_ids[platform];
- if(clGetDeviceInfo(device_id, CL_DEVICE_NAME, sizeof(name), &name, NULL) != CL_SUCCESS)
- continue;
+ result += string_printf("Platform #%u\n", platform);
- DeviceInfo info;
+ APPEND_PLATFORM_STRING_INFO(platform_id, "Name", CL_PLATFORM_NAME);
+ APPEND_PLATFORM_STRING_INFO(platform_id, "Vendor", CL_PLATFORM_VENDOR);
+ APPEND_PLATFORM_STRING_INFO(platform_id, "Version", CL_PLATFORM_VERSION);
+ APPEND_PLATFORM_STRING_INFO(platform_id, "Profile", CL_PLATFORM_PROFILE);
+ APPEND_PLATFORM_STRING_INFO(platform_id, "Extensions", CL_PLATFORM_EXTENSIONS);
- info.type = DEVICE_OPENCL;
- info.description = string(name);
- info.num = num_base + num;
- info.id = string_printf("OPENCL_%d", info.num);
- /* we don't know if it's used for display, but assume it is */
- info.display_device = true;
- info.advanced_shading = opencl_kernel_use_advanced_shading(platform_name);
- info.pack_images = true;
+ cl_uint num_devices = 0;
+ opencl_assert(clGetDeviceIDs(platform_ids[platform],
+ CL_DEVICE_TYPE_ALL,
+ 0,
+ NULL,
+ &num_devices));
+ result += string_printf("\tNumber of devices: %u\n", num_devices);
- devices.push_back(info);
+ device_ids.resize(num_devices);
+ opencl_assert(clGetDeviceIDs(platform_ids[platform],
+ CL_DEVICE_TYPE_ALL,
+ num_devices,
+ &device_ids[0],
+ NULL));
+ for (cl_uint device = 0; device < num_devices; ++device) {
+ cl_device_id device_id = device_ids[device];
+
+ result += string_printf("\t\tDevice: #%u\n", device);
+
+ APPEND_DEVICE_STRING_INFO(device_id, "Name", CL_DEVICE_NAME);
+ APPEND_DEVICE_STRING_INFO(device_id, "Vendor", CL_DEVICE_VENDOR);
+ APPEND_DEVICE_STRING_INFO(device_id, "OpenCL C Version", CL_DEVICE_OPENCL_C_VERSION);
+ APPEND_DEVICE_STRING_INFO(device_id, "Profile", CL_DEVICE_PROFILE);
+ APPEND_DEVICE_STRING_INFO(device_id, "Version", CL_DEVICE_VERSION);
+ APPEND_DEVICE_STRING_INFO(device_id, "Extensions", CL_DEVICE_EXTENSIONS);
}
}
+
+#undef APPEND_STRING_INFO
+#undef APPEND_PLATFORM_STRING_INFO
+#undef APPEND_DEVICE_STRING_INFO
+
+ return result;
}
CCL_NAMESPACE_END
#endif /* WITH_OPENCL */
-
diff --git a/intern/cycles/device/device_task.cpp b/intern/cycles/device/device_task.cpp
index dc124f8cf37..d527540f300 100644
--- a/intern/cycles/device/device_task.cpp
+++ b/intern/cycles/device/device_task.cpp
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#include <stdlib.h>
@@ -111,7 +111,7 @@ void DeviceTask::update_progress(RenderTile *rtile)
if(update_tile_sample) {
double current_time = time_dt();
- if (current_time - last_update_time >= 1.0) {
+ if(current_time - last_update_time >= 1.0) {
update_tile_sample(*rtile);
last_update_time = current_time;
diff --git a/intern/cycles/device/device_task.h b/intern/cycles/device/device_task.h
index 50216adefe2..834ea60988a 100644
--- a/intern/cycles/device/device_task.h
+++ b/intern/cycles/device/device_task.h
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#ifndef __DEVICE_TASK_H__
@@ -57,14 +57,15 @@ public:
void update_progress(RenderTile *rtile);
- boost::function<bool(Device *device, RenderTile&)> acquire_tile;
- boost::function<void(void)> update_progress_sample;
- boost::function<void(RenderTile&)> update_tile_sample;
- boost::function<void(RenderTile&)> release_tile;
- boost::function<bool(void)> get_cancel;
+ function<bool(Device *device, RenderTile&)> acquire_tile;
+ function<void(void)> update_progress_sample;
+ function<void(RenderTile&)> update_tile_sample;
+ function<void(RenderTile&)> release_tile;
+ function<bool(void)> get_cancel;
bool need_finish_queue;
bool integrator_branched;
+ int2 requested_tile_size;
protected:
double last_update_time;
};
diff --git a/intern/cycles/kernel/CMakeLists.txt b/intern/cycles/kernel/CMakeLists.txt
index 8857f86890c..b44e91751ad 100644
--- a/intern/cycles/kernel/CMakeLists.txt
+++ b/intern/cycles/kernel/CMakeLists.txt
@@ -1,3 +1,4 @@
+remove_extra_strict_flags()
set(INC
.
@@ -11,9 +12,20 @@ set(INC_SYS
)
set(SRC
- kernel.cpp
- kernel.cl
- kernel.cu
+ kernels/cpu/kernel.cpp
+ kernels/opencl/kernel.cl
+ kernels/opencl/kernel_data_init.cl
+ kernels/opencl/kernel_queue_enqueue.cl
+ kernels/opencl/kernel_scene_intersect.cl
+ kernels/opencl/kernel_lamp_emission.cl
+ kernels/opencl/kernel_background_buffer_update.cl
+ kernels/opencl/kernel_shader_eval.cl
+ kernels/opencl/kernel_holdout_emission_blurring_pathtermination_ao.cl
+ kernels/opencl/kernel_direct_lighting.cl
+ kernels/opencl/kernel_shadow_blocked.cl
+ kernels/opencl/kernel_next_iteration_setup.cl
+ kernels/opencl/kernel_sum_all_radiance.cl
+ kernels/cuda/kernel.cu
)
set(SRC_HEADERS
@@ -24,6 +36,7 @@ set(SRC_HEADERS
kernel_compat_cpu.h
kernel_compat_cuda.h
kernel_compat_opencl.h
+ kernel_debug.h
kernel_differential.h
kernel_emission.h
kernel_film.h
@@ -34,17 +47,22 @@ set(SRC_HEADERS
kernel_montecarlo.h
kernel_passes.h
kernel_path.h
+ kernel_path_branched.h
+ kernel_path_common.h
kernel_path_state.h
kernel_path_surface.h
kernel_path_volume.h
kernel_projection.h
+ kernel_queues.h
kernel_random.h
kernel_shader.h
+ kernel_shaderdata_vars.h
kernel_shadow.h
kernel_subsurface.h
kernel_textures.h
kernel_types.h
kernel_volume.h
+ kernel_work_stealing.h
)
set(SRC_CLOSURE_HEADERS
@@ -61,12 +79,12 @@ set(SRC_CLOSURE_HEADERS
closure/bsdf_transparent.h
closure/bsdf_util.h
closure/bsdf_ashikhmin_shirley.h
- closure/bsdf_westin.h
closure/bsdf_hair.h
closure/bssrdf.h
closure/emissive.h
closure/volume.h
)
+
set(SRC_SVM_HEADERS
svm/svm.h
svm/svm_attribute.h
@@ -91,6 +109,7 @@ set(SRC_SVM_HEADERS
svm/svm_magic.h
svm/svm_mapping.h
svm/svm_math.h
+ svm/svm_math_util.h
svm/svm_mix.h
svm/svm_musgrave.h
svm/svm_noise.h
@@ -106,6 +125,7 @@ set(SRC_SVM_HEADERS
svm/svm_value.h
svm/svm_vector_transform.h
svm/svm_voronoi.h
+ svm/svm_voxel.h
svm/svm_wave.h
)
@@ -116,22 +136,48 @@ set(SRC_GEOM_HEADERS
geom/geom_bvh_shadow.h
geom/geom_bvh_subsurface.h
geom/geom_bvh_traversal.h
+ geom/geom_bvh_volume.h
+ geom/geom_bvh_volume_all.h
geom/geom_curve.h
geom/geom_motion_curve.h
geom/geom_motion_triangle.h
geom/geom_object.h
geom/geom_primitive.h
+ geom/geom_qbvh.h
+ geom/geom_qbvh_shadow.h
+ geom/geom_qbvh_subsurface.h
+ geom/geom_qbvh_traversal.h
+ geom/geom_qbvh_volume.h
+ geom/geom_qbvh_volume_all.h
geom/geom_triangle.h
+ geom/geom_triangle_intersect.h
geom/geom_volume.h
)
set(SRC_UTIL_HEADERS
+ ../util/util_atomic.h
../util/util_color.h
../util/util_half.h
../util/util_math.h
+ ../util/util_math_fast.h
../util/util_transform.h
../util/util_types.h
)
+
+set(SRC_SPLIT_HEADERS
+ split/kernel_background_buffer_update.h
+ split/kernel_data_init.h
+ split/kernel_direct_lighting.h
+ split/kernel_holdout_emission_blurring_pathtermination_ao.h
+ split/kernel_lamp_emission.h
+ split/kernel_next_iteration_setup.h
+ split/kernel_scene_intersect.h
+ split/kernel_shader_eval.h
+ split/kernel_shadow_blocked.h
+ split/kernel_split_common.h
+ split/kernel_sum_all_radiance.h
+)
+
# CUDA module
if(WITH_CYCLES_CUDA_BINARIES)
@@ -143,7 +189,7 @@ if(WITH_CYCLES_CUDA_BINARIES)
endif()
# CUDA version
- execute_process (COMMAND ${CUDA_NVCC_EXECUTABLE} "--version" OUTPUT_VARIABLE NVCC_OUT)
+ execute_process(COMMAND ${CUDA_NVCC_EXECUTABLE} "--version" OUTPUT_VARIABLE NVCC_OUT)
string(REGEX REPLACE ".*release ([0-9]+)\\.([0-9]+).*" "\\1" CUDA_VERSION_MAJOR ${NVCC_OUT})
string(REGEX REPLACE ".*release ([0-9]+)\\.([0-9]+).*" "\\2" CUDA_VERSION_MINOR ${NVCC_OUT})
set(CUDA_VERSION "${CUDA_VERSION_MAJOR}${CUDA_VERSION_MINOR}")
@@ -157,18 +203,24 @@ if(WITH_CYCLES_CUDA_BINARIES)
endif()
# build for each arch
- set(cuda_sources kernel.cu ${SRC_HEADERS} ${SRC_SVM_HEADERS} ${SRC_GEOM_HEADERS} ${SRC_CLOSURE_HEADERS} ${SRC_UTIL_HEADERS})
+ set(cuda_sources kernels/cuda/kernel.cu ${SRC_HEADERS} ${SRC_SVM_HEADERS} ${SRC_GEOM_HEADERS} ${SRC_CLOSURE_HEADERS} ${SRC_UTIL_HEADERS})
set(cuda_cubins)
macro(CYCLES_CUDA_KERNEL_ADD arch experimental)
if(${experimental})
- set(cuda_extra_flags "-D__KERNEL_CUDA_EXPERIMENTAL__")
+ set(cuda_extra_flags "-D__KERNEL_EXPERIMENTAL__")
set(cuda_cubin kernel_experimental_${arch}.cubin)
else()
set(cuda_extra_flags "")
set(cuda_cubin kernel_${arch}.cubin)
endif()
+ if(WITH_CYCLES_DEBUG)
+ set(cuda_debug_flags "-D__KERNEL_DEBUG__")
+ else()
+ set(cuda_debug_flags "")
+ endif()
+
set(cuda_version_flags "-D__KERNEL_CUDA_VERSION__=${CUDA_VERSION}")
set(cuda_math_flags "--use_fast_math")
@@ -177,13 +229,14 @@ if(WITH_CYCLES_CUDA_BINARIES)
COMMAND ${CUDA_NVCC_EXECUTABLE}
-arch=${arch}
-m${CUDA_BITS}
- --cubin ${CMAKE_CURRENT_SOURCE_DIR}/kernel.cu
+ --cubin ${CMAKE_CURRENT_SOURCE_DIR}/kernels/cuda/kernel.cu
-o ${CMAKE_CURRENT_BINARY_DIR}/${cuda_cubin}
--ptxas-options="-v"
${cuda_arch_flags}
${cuda_version_flags}
${cuda_math_flags}
${cuda_extra_flags}
+ ${cuda_debug_flags}
-I${CMAKE_CURRENT_SOURCE_DIR}/../util
-I${CMAKE_CURRENT_SOURCE_DIR}/svm
-DCCL_NAMESPACE_BEGIN=
@@ -196,6 +249,7 @@ if(WITH_CYCLES_CUDA_BINARIES)
list(APPEND cuda_cubins ${cuda_cubin})
unset(cuda_extra_flags)
+ unset(cuda_debug_flags)
endmacro()
foreach(arch ${CYCLES_CUDA_BINARIES_ARCH})
@@ -223,20 +277,29 @@ include_directories(SYSTEM ${INC_SYS})
if(CXX_HAS_SSE)
list(APPEND SRC
- kernel_sse2.cpp
- kernel_sse3.cpp
- kernel_sse41.cpp
- kernel_avx.cpp
- kernel_avx2.cpp
+ kernels/cpu/kernel_sse2.cpp
+ kernels/cpu/kernel_sse3.cpp
+ kernels/cpu/kernel_sse41.cpp
)
- set_source_files_properties(kernel_sse2.cpp PROPERTIES COMPILE_FLAGS "${CYCLES_SSE2_KERNEL_FLAGS}")
- set_source_files_properties(kernel_sse3.cpp PROPERTIES COMPILE_FLAGS "${CYCLES_SSE3_KERNEL_FLAGS}")
- set_source_files_properties(kernel_sse41.cpp PROPERTIES COMPILE_FLAGS "${CYCLES_SSE41_KERNEL_FLAGS}")
- set_source_files_properties(kernel_avx.cpp PROPERTIES COMPILE_FLAGS "${CYCLES_AVX_KERNEL_FLAGS}")
- set_source_files_properties(kernel_avx2.cpp PROPERTIES COMPILE_FLAGS "${CYCLES_AVX2_KERNEL_FLAGS}")
+ set_source_files_properties(kernels/cpu/kernel_sse2.cpp PROPERTIES COMPILE_FLAGS "${CYCLES_SSE2_KERNEL_FLAGS}")
+ set_source_files_properties(kernels/cpu/kernel_sse3.cpp PROPERTIES COMPILE_FLAGS "${CYCLES_SSE3_KERNEL_FLAGS}")
+ set_source_files_properties(kernels/cpu/kernel_sse41.cpp PROPERTIES COMPILE_FLAGS "${CYCLES_SSE41_KERNEL_FLAGS}")
endif()
+if(CXX_HAS_AVX)
+ list(APPEND SRC
+ kernels/cpu/kernel_avx.cpp
+ )
+ set_source_files_properties(kernels/cpu/kernel_avx.cpp PROPERTIES COMPILE_FLAGS "${CYCLES_AVX_KERNEL_FLAGS}")
+endif()
+
+if(CXX_HAS_AVX2)
+ list(APPEND SRC
+ kernels/cpu/kernel_avx2.cpp
+ )
+ set_source_files_properties(kernels/cpu/kernel_avx2.cpp PROPERTIES COMPILE_FLAGS "${CYCLES_AVX2_KERNEL_FLAGS}")
+endif()
add_library(cycles_kernel ${SRC} ${SRC_HEADERS} ${SRC_CLOSURE_HEADERS} ${SRC_SVM_HEADERS} ${SRC_GEOM_HEADERS})
@@ -254,11 +317,23 @@ endif()
#add_custom_target(cycles_kernel_preprocess ALL DEPENDS ${KERNEL_PREPROCESSED})
#delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "${KERNEL_PREPROCESSED}" ${CYCLES_INSTALL_PATH}/kernel)
-delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "kernel.cl" ${CYCLES_INSTALL_PATH}/kernel)
-delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "kernel.cu" ${CYCLES_INSTALL_PATH}/kernel)
+delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "kernels/opencl/kernel.cl" ${CYCLES_INSTALL_PATH}/kernel/kernels/opencl)
+delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "kernels/opencl/kernel_data_init.cl" ${CYCLES_INSTALL_PATH}/kernel/kernels/opencl)
+delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "kernels/opencl/kernel_queue_enqueue.cl" ${CYCLES_INSTALL_PATH}/kernel/kernels/opencl)
+delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "kernels/opencl/kernel_scene_intersect.cl" ${CYCLES_INSTALL_PATH}/kernel/kernels/opencl)
+delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "kernels/opencl/kernel_lamp_emission.cl" ${CYCLES_INSTALL_PATH}/kernel/kernels/opencl)
+delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "kernels/opencl/kernel_background_buffer_update.cl" ${CYCLES_INSTALL_PATH}/kernel/kernels/opencl)
+delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "kernels/opencl/kernel_shader_eval.cl" ${CYCLES_INSTALL_PATH}/kernel/kernels/opencl)
+delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "kernels/opencl/kernel_holdout_emission_blurring_pathtermination_ao.cl" ${CYCLES_INSTALL_PATH}/kernel/kernels/opencl)
+delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "kernels/opencl/kernel_direct_lighting.cl" ${CYCLES_INSTALL_PATH}/kernel/kernels/opencl)
+delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "kernels/opencl/kernel_shadow_blocked.cl" ${CYCLES_INSTALL_PATH}/kernel/kernels/opencl)
+delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "kernels/opencl/kernel_next_iteration_setup.cl" ${CYCLES_INSTALL_PATH}/kernel/kernels/opencl)
+delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "kernels/opencl/kernel_sum_all_radiance.cl" ${CYCLES_INSTALL_PATH}/kernel/kernels/opencl)
+delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "kernels/cuda/kernel.cu" ${CYCLES_INSTALL_PATH}/kernel/kernels/cuda)
delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "${SRC_HEADERS}" ${CYCLES_INSTALL_PATH}/kernel)
delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "${SRC_CLOSURE_HEADERS}" ${CYCLES_INSTALL_PATH}/kernel/closure)
delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "${SRC_SVM_HEADERS}" ${CYCLES_INSTALL_PATH}/kernel/svm)
delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "${SRC_GEOM_HEADERS}" ${CYCLES_INSTALL_PATH}/kernel/geom)
delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "${SRC_UTIL_HEADERS}" ${CYCLES_INSTALL_PATH}/kernel)
+delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "${SRC_SPLIT_HEADERS}" ${CYCLES_INSTALL_PATH}/kernel/split)
diff --git a/intern/cycles/kernel/SConscript b/intern/cycles/kernel/SConscript
index 5a9e57c5342..e8d51013924 100644
--- a/intern/cycles/kernel/SConscript
+++ b/intern/cycles/kernel/SConscript
@@ -57,8 +57,9 @@ if env['WITH_BF_CYCLES_CUDA_BINARIES']:
build_dir = os.path.join(root_build_dir, 'intern/cycles/kernel')
# source directories and files
+ kernel_file_rel = os.path.join("kernels", "cuda", "kernel.cu")
source_dir = Dir('.').srcnode().path
- kernel_file = os.path.join(source_dir, "kernel.cu")
+ kernel_file = os.path.join(source_dir, kernel_file_rel)
util_dir = os.path.join(source_dir, "../util")
svm_dir = os.path.join(source_dir, "../svm")
geom_dir = os.path.join(source_dir, "../geom")
@@ -79,12 +80,15 @@ if env['WITH_BF_CYCLES_CUDA_BINARIES']:
nvcc_flags += " -DCCL_NAMESPACE_BEGIN= -DCCL_NAMESPACE_END= -DNVCC"
nvcc_flags += " -I \"%s\" -I \"%s\" -I \"%s\" -I \"%s\"" % (util_dir, svm_dir, geom_dir, closure_dir)
+ if env['WITH_BF_CYCLES_DEBUG']:
+ nvcc_flags += " -D__KERNEL_DEBUG__"
+
# dependencies
- dependencies = ['kernel.cu'] + kernel.Glob('*.h') + kernel.Glob('../util/*.h') + kernel.Glob('svm/*.h') + kernel.Glob('geom/*.h') + kernel.Glob('closure/*.h')
+ dependencies = [kernel_file_rel] + kernel.Glob('*.h') + kernel.Glob('../util/*.h') + kernel.Glob('svm/*.h') + kernel.Glob('geom/*.h') + kernel.Glob('closure/*.h')
last_cubin_file = None
configs = (("kernel_%s.cubin", ''),
- ("kernel_experimental_%s.cubin", ' -D__KERNEL_CUDA_EXPERIMENTAL__'))
+ ("kernel_experimental_%s.cubin", ' -D__KERNEL_EXPERIMENTAL__'))
# add command for each cuda architecture
for arch in cuda_archs:
@@ -102,7 +106,7 @@ if env['WITH_BF_CYCLES_CUDA_BINARIES']:
else:
command = "\"%s\" -arch=%s %s \"%s\" -o \"%s\"" % (nvcc, arch, current_flags, kernel_file, cubin_file)
- kernel.Command(cubin_file, 'kernel.cu', command)
+ kernel.Command(cubin_file, kernel_file_rel, command)
kernel.Depends(cubin_file, dependencies)
kernel_binaries.append(cubin_file)
diff --git a/intern/cycles/kernel/closure/bsdf.h b/intern/cycles/kernel/closure/bsdf.h
index 9961071c2ac..558aa0dc6a9 100644
--- a/intern/cycles/kernel/closure/bsdf.h
+++ b/intern/cycles/kernel/closure/bsdf.h
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#include "../closure/bsdf_ashikhmin_velvet.h"
@@ -24,7 +24,6 @@
#include "../closure/bsdf_refraction.h"
#include "../closure/bsdf_transparent.h"
#include "../closure/bsdf_ashikhmin_shirley.h"
-#include "../closure/bsdf_westin.h"
#include "../closure/bsdf_toon.h"
#include "../closure/bsdf_hair.h"
#ifdef __SUBSURFACE__
@@ -48,87 +47,79 @@ ccl_device int bsdf_sample(KernelGlobals *kg, const ShaderData *sd, const Shader
switch(sc->type) {
case CLOSURE_BSDF_DIFFUSE_ID:
case CLOSURE_BSDF_BSSRDF_ID:
- label = bsdf_diffuse_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv,
+ label = bsdf_diffuse_sample(sc, ccl_fetch(sd, Ng), ccl_fetch(sd, I), ccl_fetch(sd, dI).dx, ccl_fetch(sd, dI).dy, randu, randv,
eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
break;
#ifdef __SVM__
case CLOSURE_BSDF_OREN_NAYAR_ID:
- label = bsdf_oren_nayar_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv,
+ label = bsdf_oren_nayar_sample(sc, ccl_fetch(sd, Ng), ccl_fetch(sd, I), ccl_fetch(sd, dI).dx, ccl_fetch(sd, dI).dy, randu, randv,
eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
break;
/*case CLOSURE_BSDF_PHONG_RAMP_ID:
- label = bsdf_phong_ramp_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv,
+ label = bsdf_phong_ramp_sample(sc, ccl_fetch(sd, Ng), ccl_fetch(sd, I), ccl_fetch(sd, dI).dx, ccl_fetch(sd, dI).dy, randu, randv,
eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
break;
case CLOSURE_BSDF_DIFFUSE_RAMP_ID:
- label = bsdf_diffuse_ramp_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv,
+ label = bsdf_diffuse_ramp_sample(sc, ccl_fetch(sd, Ng), ccl_fetch(sd, I), ccl_fetch(sd, dI).dx, ccl_fetch(sd, dI).dy, randu, randv,
eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
break;*/
case CLOSURE_BSDF_TRANSLUCENT_ID:
- label = bsdf_translucent_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv,
+ label = bsdf_translucent_sample(sc, ccl_fetch(sd, Ng), ccl_fetch(sd, I), ccl_fetch(sd, dI).dx, ccl_fetch(sd, dI).dy, randu, randv,
eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
break;
case CLOSURE_BSDF_REFLECTION_ID:
- label = bsdf_reflection_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv,
+ label = bsdf_reflection_sample(sc, ccl_fetch(sd, Ng), ccl_fetch(sd, I), ccl_fetch(sd, dI).dx, ccl_fetch(sd, dI).dy, randu, randv,
eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
break;
case CLOSURE_BSDF_REFRACTION_ID:
- label = bsdf_refraction_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv,
+ label = bsdf_refraction_sample(sc, ccl_fetch(sd, Ng), ccl_fetch(sd, I), ccl_fetch(sd, dI).dx, ccl_fetch(sd, dI).dy, randu, randv,
eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
break;
case CLOSURE_BSDF_TRANSPARENT_ID:
- label = bsdf_transparent_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv,
+ label = bsdf_transparent_sample(sc, ccl_fetch(sd, Ng), ccl_fetch(sd, I), ccl_fetch(sd, dI).dx, ccl_fetch(sd, dI).dy, randu, randv,
eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
break;
case CLOSURE_BSDF_MICROFACET_GGX_ID:
case CLOSURE_BSDF_MICROFACET_GGX_ANISO_ID:
case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID:
- label = bsdf_microfacet_ggx_sample(kg, sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv,
+ label = bsdf_microfacet_ggx_sample(kg, sc, ccl_fetch(sd, Ng), ccl_fetch(sd, I), ccl_fetch(sd, dI).dx, ccl_fetch(sd, dI).dy, randu, randv,
eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
break;
case CLOSURE_BSDF_MICROFACET_BECKMANN_ID:
case CLOSURE_BSDF_MICROFACET_BECKMANN_ANISO_ID:
case CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID:
- label = bsdf_microfacet_beckmann_sample(kg, sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv,
+ label = bsdf_microfacet_beckmann_sample(kg, sc, ccl_fetch(sd, Ng), ccl_fetch(sd, I), ccl_fetch(sd, dI).dx, ccl_fetch(sd, dI).dy, randu, randv,
eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
break;
case CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID:
case CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ANISO_ID:
- label = bsdf_ashikhmin_shirley_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv,
+ label = bsdf_ashikhmin_shirley_sample(sc, ccl_fetch(sd, Ng), ccl_fetch(sd, I), ccl_fetch(sd, dI).dx, ccl_fetch(sd, dI).dy, randu, randv,
eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
break;
case CLOSURE_BSDF_ASHIKHMIN_VELVET_ID:
- label = bsdf_ashikhmin_velvet_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv,
+ label = bsdf_ashikhmin_velvet_sample(sc, ccl_fetch(sd, Ng), ccl_fetch(sd, I), ccl_fetch(sd, dI).dx, ccl_fetch(sd, dI).dy, randu, randv,
eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
break;
case CLOSURE_BSDF_DIFFUSE_TOON_ID:
- label = bsdf_diffuse_toon_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv,
+ label = bsdf_diffuse_toon_sample(sc, ccl_fetch(sd, Ng), ccl_fetch(sd, I), ccl_fetch(sd, dI).dx, ccl_fetch(sd, dI).dy, randu, randv,
eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
break;
case CLOSURE_BSDF_GLOSSY_TOON_ID:
- label = bsdf_glossy_toon_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv,
- eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
- break;
- case CLOSURE_BSDF_WESTIN_BACKSCATTER_ID:
- label = bsdf_westin_backscatter_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv,
- eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
- break;
- case CLOSURE_BSDF_WESTIN_SHEEN_ID:
- label = bsdf_westin_sheen_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv,
+ label = bsdf_glossy_toon_sample(sc, ccl_fetch(sd, Ng), ccl_fetch(sd, I), ccl_fetch(sd, dI).dx, ccl_fetch(sd, dI).dy, randu, randv,
eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
break;
case CLOSURE_BSDF_HAIR_REFLECTION_ID:
- label = bsdf_hair_reflection_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv,
+ label = bsdf_hair_reflection_sample(sc, ccl_fetch(sd, Ng), ccl_fetch(sd, I), ccl_fetch(sd, dI).dx, ccl_fetch(sd, dI).dy, randu, randv,
eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
break;
case CLOSURE_BSDF_HAIR_TRANSMISSION_ID:
- label = bsdf_hair_transmission_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv,
+ label = bsdf_hair_transmission_sample(sc, ccl_fetch(sd, Ng), ccl_fetch(sd, I), ccl_fetch(sd, dI).dx, ccl_fetch(sd, dI).dy, randu, randv,
eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
break;
#endif
#ifdef __VOLUME__
case CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID:
- label = volume_henyey_greenstein_sample(sc, sd->I, sd->dI.dx, sd->dI.dy, randu, randv, eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
+ label = volume_henyey_greenstein_sample(sc, ccl_fetch(sd, I), ccl_fetch(sd, dI).dx, ccl_fetch(sd, dI).dy, randu, randv, eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
break;
#endif
default:
@@ -148,73 +139,67 @@ ccl_device float3 bsdf_eval(KernelGlobals *kg, const ShaderData *sd, const Shade
return OSLShader::bsdf_eval(sd, sc, omega_in, *pdf);
#endif
- if(dot(sd->Ng, omega_in) >= 0.0f) {
+ if(dot(ccl_fetch(sd, Ng), omega_in) >= 0.0f) {
switch(sc->type) {
case CLOSURE_BSDF_DIFFUSE_ID:
case CLOSURE_BSDF_BSSRDF_ID:
- eval = bsdf_diffuse_eval_reflect(sc, sd->I, omega_in, pdf);
+ eval = bsdf_diffuse_eval_reflect(sc, ccl_fetch(sd, I), omega_in, pdf);
break;
#ifdef __SVM__
case CLOSURE_BSDF_OREN_NAYAR_ID:
- eval = bsdf_oren_nayar_eval_reflect(sc, sd->I, omega_in, pdf);
+ eval = bsdf_oren_nayar_eval_reflect(sc, ccl_fetch(sd, I), omega_in, pdf);
break;
/*case CLOSURE_BSDF_PHONG_RAMP_ID:
- eval = bsdf_phong_ramp_eval_reflect(sc, sd->I, omega_in, pdf);
+ eval = bsdf_phong_ramp_eval_reflect(sc, ccl_fetch(sd, I), omega_in, pdf);
break;
case CLOSURE_BSDF_DIFFUSE_RAMP_ID:
- eval = bsdf_diffuse_ramp_eval_reflect(sc, sd->I, omega_in, pdf);
+ eval = bsdf_diffuse_ramp_eval_reflect(sc, ccl_fetch(sd, I), omega_in, pdf);
break;*/
case CLOSURE_BSDF_TRANSLUCENT_ID:
- eval = bsdf_translucent_eval_reflect(sc, sd->I, omega_in, pdf);
+ eval = bsdf_translucent_eval_reflect(sc, ccl_fetch(sd, I), omega_in, pdf);
break;
case CLOSURE_BSDF_REFLECTION_ID:
- eval = bsdf_reflection_eval_reflect(sc, sd->I, omega_in, pdf);
+ eval = bsdf_reflection_eval_reflect(sc, ccl_fetch(sd, I), omega_in, pdf);
break;
case CLOSURE_BSDF_REFRACTION_ID:
- eval = bsdf_refraction_eval_reflect(sc, sd->I, omega_in, pdf);
+ eval = bsdf_refraction_eval_reflect(sc, ccl_fetch(sd, I), omega_in, pdf);
break;
case CLOSURE_BSDF_TRANSPARENT_ID:
- eval = bsdf_transparent_eval_reflect(sc, sd->I, omega_in, pdf);
+ eval = bsdf_transparent_eval_reflect(sc, ccl_fetch(sd, I), omega_in, pdf);
break;
case CLOSURE_BSDF_MICROFACET_GGX_ID:
case CLOSURE_BSDF_MICROFACET_GGX_ANISO_ID:
case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID:
- eval = bsdf_microfacet_ggx_eval_reflect(sc, sd->I, omega_in, pdf);
+ eval = bsdf_microfacet_ggx_eval_reflect(sc, ccl_fetch(sd, I), omega_in, pdf);
break;
case CLOSURE_BSDF_MICROFACET_BECKMANN_ID:
case CLOSURE_BSDF_MICROFACET_BECKMANN_ANISO_ID:
case CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID:
- eval = bsdf_microfacet_beckmann_eval_reflect(sc, sd->I, omega_in, pdf);
+ eval = bsdf_microfacet_beckmann_eval_reflect(sc, ccl_fetch(sd, I), omega_in, pdf);
break;
case CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID:
case CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ANISO_ID:
- eval = bsdf_ashikhmin_shirley_eval_reflect(sc, sd->I, omega_in, pdf);
+ eval = bsdf_ashikhmin_shirley_eval_reflect(sc, ccl_fetch(sd, I), omega_in, pdf);
break;
case CLOSURE_BSDF_ASHIKHMIN_VELVET_ID:
- eval = bsdf_ashikhmin_velvet_eval_reflect(sc, sd->I, omega_in, pdf);
+ eval = bsdf_ashikhmin_velvet_eval_reflect(sc, ccl_fetch(sd, I), omega_in, pdf);
break;
case CLOSURE_BSDF_DIFFUSE_TOON_ID:
- eval = bsdf_diffuse_toon_eval_reflect(sc, sd->I, omega_in, pdf);
+ eval = bsdf_diffuse_toon_eval_reflect(sc, ccl_fetch(sd, I), omega_in, pdf);
break;
case CLOSURE_BSDF_GLOSSY_TOON_ID:
- eval = bsdf_glossy_toon_eval_reflect(sc, sd->I, omega_in, pdf);
- break;
- case CLOSURE_BSDF_WESTIN_BACKSCATTER_ID:
- eval = bsdf_westin_backscatter_eval_reflect(sc, sd->I, omega_in, pdf);
- break;
- case CLOSURE_BSDF_WESTIN_SHEEN_ID:
- eval = bsdf_westin_sheen_eval_reflect(sc, sd->I, omega_in, pdf);
+ eval = bsdf_glossy_toon_eval_reflect(sc, ccl_fetch(sd, I), omega_in, pdf);
break;
case CLOSURE_BSDF_HAIR_REFLECTION_ID:
- eval = bsdf_hair_reflection_eval_reflect(sc, sd->I, omega_in, pdf);
+ eval = bsdf_hair_reflection_eval_reflect(sc, ccl_fetch(sd, I), omega_in, pdf);
break;
case CLOSURE_BSDF_HAIR_TRANSMISSION_ID:
- eval = bsdf_hair_transmission_eval_reflect(sc, sd->I, omega_in, pdf);
+ eval = bsdf_hair_transmission_eval_reflect(sc, ccl_fetch(sd, I), omega_in, pdf);
break;
#endif
#ifdef __VOLUME__
case CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID:
- eval = volume_henyey_greenstein_eval_phase(sc, sd->I, omega_in, pdf);
+ eval = volume_henyey_greenstein_eval_phase(sc, ccl_fetch(sd, I), omega_in, pdf);
break;
#endif
default:
@@ -226,63 +211,57 @@ ccl_device float3 bsdf_eval(KernelGlobals *kg, const ShaderData *sd, const Shade
switch(sc->type) {
case CLOSURE_BSDF_DIFFUSE_ID:
case CLOSURE_BSDF_BSSRDF_ID:
- eval = bsdf_diffuse_eval_transmit(sc, sd->I, omega_in, pdf);
+ eval = bsdf_diffuse_eval_transmit(sc, ccl_fetch(sd, I), omega_in, pdf);
break;
#ifdef __SVM__
case CLOSURE_BSDF_OREN_NAYAR_ID:
- eval = bsdf_oren_nayar_eval_transmit(sc, sd->I, omega_in, pdf);
+ eval = bsdf_oren_nayar_eval_transmit(sc, ccl_fetch(sd, I), omega_in, pdf);
break;
case CLOSURE_BSDF_TRANSLUCENT_ID:
- eval = bsdf_translucent_eval_transmit(sc, sd->I, omega_in, pdf);
+ eval = bsdf_translucent_eval_transmit(sc, ccl_fetch(sd, I), omega_in, pdf);
break;
case CLOSURE_BSDF_REFLECTION_ID:
- eval = bsdf_reflection_eval_transmit(sc, sd->I, omega_in, pdf);
+ eval = bsdf_reflection_eval_transmit(sc, ccl_fetch(sd, I), omega_in, pdf);
break;
case CLOSURE_BSDF_REFRACTION_ID:
- eval = bsdf_refraction_eval_transmit(sc, sd->I, omega_in, pdf);
+ eval = bsdf_refraction_eval_transmit(sc, ccl_fetch(sd, I), omega_in, pdf);
break;
case CLOSURE_BSDF_TRANSPARENT_ID:
- eval = bsdf_transparent_eval_transmit(sc, sd->I, omega_in, pdf);
+ eval = bsdf_transparent_eval_transmit(sc, ccl_fetch(sd, I), omega_in, pdf);
break;
case CLOSURE_BSDF_MICROFACET_GGX_ID:
case CLOSURE_BSDF_MICROFACET_GGX_ANISO_ID:
case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID:
- eval = bsdf_microfacet_ggx_eval_transmit(sc, sd->I, omega_in, pdf);
+ eval = bsdf_microfacet_ggx_eval_transmit(sc, ccl_fetch(sd, I), omega_in, pdf);
break;
case CLOSURE_BSDF_MICROFACET_BECKMANN_ID:
case CLOSURE_BSDF_MICROFACET_BECKMANN_ANISO_ID:
case CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID:
- eval = bsdf_microfacet_beckmann_eval_transmit(sc, sd->I, omega_in, pdf);
+ eval = bsdf_microfacet_beckmann_eval_transmit(sc, ccl_fetch(sd, I), omega_in, pdf);
break;
case CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID:
case CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ANISO_ID:
- eval = bsdf_ashikhmin_shirley_eval_transmit(sc, sd->I, omega_in, pdf);
+ eval = bsdf_ashikhmin_shirley_eval_transmit(sc, ccl_fetch(sd, I), omega_in, pdf);
break;
case CLOSURE_BSDF_ASHIKHMIN_VELVET_ID:
- eval = bsdf_ashikhmin_velvet_eval_transmit(sc, sd->I, omega_in, pdf);
+ eval = bsdf_ashikhmin_velvet_eval_transmit(sc, ccl_fetch(sd, I), omega_in, pdf);
break;
case CLOSURE_BSDF_DIFFUSE_TOON_ID:
- eval = bsdf_diffuse_toon_eval_transmit(sc, sd->I, omega_in, pdf);
+ eval = bsdf_diffuse_toon_eval_transmit(sc, ccl_fetch(sd, I), omega_in, pdf);
break;
case CLOSURE_BSDF_GLOSSY_TOON_ID:
- eval = bsdf_glossy_toon_eval_transmit(sc, sd->I, omega_in, pdf);
- break;
- case CLOSURE_BSDF_WESTIN_BACKSCATTER_ID:
- eval = bsdf_westin_backscatter_eval_transmit(sc, sd->I, omega_in, pdf);
- break;
- case CLOSURE_BSDF_WESTIN_SHEEN_ID:
- eval = bsdf_westin_sheen_eval_transmit(sc, sd->I, omega_in, pdf);
+ eval = bsdf_glossy_toon_eval_transmit(sc, ccl_fetch(sd, I), omega_in, pdf);
break;
case CLOSURE_BSDF_HAIR_REFLECTION_ID:
- eval = bsdf_hair_reflection_eval_transmit(sc, sd->I, omega_in, pdf);
+ eval = bsdf_hair_reflection_eval_transmit(sc, ccl_fetch(sd, I), omega_in, pdf);
break;
case CLOSURE_BSDF_HAIR_TRANSMISSION_ID:
- eval = bsdf_hair_transmission_eval_transmit(sc, sd->I, omega_in, pdf);
+ eval = bsdf_hair_transmission_eval_transmit(sc, ccl_fetch(sd, I), omega_in, pdf);
break;
#endif
#ifdef __VOLUME__
case CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID:
- eval = volume_henyey_greenstein_eval_phase(sc, sd->I, omega_in, pdf);
+ eval = volume_henyey_greenstein_eval_phase(sc, ccl_fetch(sd, I), omega_in, pdf);
break;
#endif
default:
@@ -296,6 +275,8 @@ ccl_device float3 bsdf_eval(KernelGlobals *kg, const ShaderData *sd, const Shade
ccl_device void bsdf_blur(KernelGlobals *kg, ShaderClosure *sc, float roughness)
{
+/* ToDo: do we want to blur volume closures? */
+
#ifdef __OSL__
if(kg->osl && sc->prim) {
OSLShader::bsdf_blur(sc, roughness);
@@ -303,33 +284,8 @@ ccl_device void bsdf_blur(KernelGlobals *kg, ShaderClosure *sc, float roughness)
}
#endif
- switch(sc->type) {
- case CLOSURE_BSDF_DIFFUSE_ID:
- case CLOSURE_BSDF_BSSRDF_ID:
- bsdf_diffuse_blur(sc, roughness);
- break;
#ifdef __SVM__
- case CLOSURE_BSDF_OREN_NAYAR_ID:
- bsdf_oren_nayar_blur(sc, roughness);
- break;
- /*case CLOSURE_BSDF_PHONG_RAMP_ID:
- bsdf_phong_ramp_blur(sc, roughness);
- break;
- case CLOSURE_BSDF_DIFFUSE_RAMP_ID:
- bsdf_diffuse_ramp_blur(sc, roughness);
- break;*/
- case CLOSURE_BSDF_TRANSLUCENT_ID:
- bsdf_translucent_blur(sc, roughness);
- break;
- case CLOSURE_BSDF_REFLECTION_ID:
- bsdf_reflection_blur(sc, roughness);
- break;
- case CLOSURE_BSDF_REFRACTION_ID:
- bsdf_refraction_blur(sc, roughness);
- break;
- case CLOSURE_BSDF_TRANSPARENT_ID:
- bsdf_transparent_blur(sc, roughness);
- break;
+ switch(sc->type) {
case CLOSURE_BSDF_MICROFACET_GGX_ID:
case CLOSURE_BSDF_MICROFACET_GGX_ANISO_ID:
case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID:
@@ -344,30 +300,10 @@ ccl_device void bsdf_blur(KernelGlobals *kg, ShaderClosure *sc, float roughness)
case CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ANISO_ID:
bsdf_ashikhmin_shirley_blur(sc, roughness);
break;
- case CLOSURE_BSDF_ASHIKHMIN_VELVET_ID:
- bsdf_ashikhmin_velvet_blur(sc, roughness);
- break;
- case CLOSURE_BSDF_DIFFUSE_TOON_ID:
- bsdf_diffuse_toon_blur(sc, roughness);
- break;
- case CLOSURE_BSDF_GLOSSY_TOON_ID:
- bsdf_glossy_toon_blur(sc, roughness);
- break;
- case CLOSURE_BSDF_WESTIN_BACKSCATTER_ID:
- bsdf_westin_backscatter_blur(sc, roughness);
- break;
- case CLOSURE_BSDF_WESTIN_SHEEN_ID:
- bsdf_westin_sheen_blur(sc, roughness);
- break;
- case CLOSURE_BSDF_HAIR_REFLECTION_ID:
- case CLOSURE_BSDF_HAIR_TRANSMISSION_ID:
- bsdf_hair_reflection_blur(sc, roughness);
- break;
-#endif
- /* todo: do we want to blur volume closures? */
default:
break;
}
+#endif
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/closure/bsdf_ashikhmin_shirley.h b/intern/cycles/kernel/closure/bsdf_ashikhmin_shirley.h
index ad7864cb8ea..8d7d533d6f8 100644
--- a/intern/cycles/kernel/closure/bsdf_ashikhmin_shirley.h
+++ b/intern/cycles/kernel/closure/bsdf_ashikhmin_shirley.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2011-2013 Blender Foundation
+ * Copyright 2011-2014 Blender Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#ifndef __BSDF_ASHIKHMIN_SHIRLEY_H__
@@ -33,24 +33,20 @@ CCL_NAMESPACE_BEGIN
ccl_device int bsdf_ashikhmin_shirley_setup(ShaderClosure *sc)
{
- /* store roughness. could already convert to exponent to save some cycles
- * in eval, but this is more consistent with other bsdfs and shader_blur. */
sc->data0 = clamp(sc->data0, 1e-4f, 1.0f);
sc->data1 = sc->data0;
sc->type = CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID;
- return SD_BSDF | SD_BSDF_HAS_EVAL | SD_BSDF_GLOSSY;
+ return SD_BSDF|SD_BSDF_HAS_EVAL;
}
ccl_device int bsdf_ashikhmin_shirley_aniso_setup(ShaderClosure *sc)
{
- /* store roughness. could already convert to exponent to save some cycles
- * in eval, but this is more consistent with other bsdfs and shader_blur. */
sc->data0 = clamp(sc->data0, 1e-4f, 1.0f);
sc->data1 = clamp(sc->data1, 1e-4f, 1.0f);
sc->type = CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ANISO_ID;
- return SD_BSDF | SD_BSDF_HAS_EVAL | SD_BSDF_GLOSSY;
+ return SD_BSDF|SD_BSDF_HAS_EVAL;
}
ccl_device void bsdf_ashikhmin_shirley_blur(ShaderClosure *sc, float roughness)
@@ -73,7 +69,10 @@ ccl_device float3 bsdf_ashikhmin_shirley_eval_reflect(const ShaderClosure *sc, c
float out = 0.0f;
- if (NdotI > 0.0f && NdotO > 0.0f) {
+ if(fmaxf(sc->data0, sc->data1) <= 1e-4f)
+ return make_float3(0.0f, 0.0f, 0.0f);
+
+ if(NdotI > 0.0f && NdotO > 0.0f) {
NdotI = fmaxf(NdotI, 1e-6f);
NdotO = fmaxf(NdotO, 1e-6f);
float3 H = normalize(omega_in + I);
@@ -86,7 +85,8 @@ ccl_device float3 bsdf_ashikhmin_shirley_eval_reflect(const ShaderClosure *sc, c
float n_x = bsdf_ashikhmin_shirley_roughness_to_exponent(sc->data0);
float n_y = bsdf_ashikhmin_shirley_roughness_to_exponent(sc->data1);
- if (n_x == n_y) { /* => isotropic case */
+ if(n_x == n_y) {
+ /* isotropic */
float e = n_x;
float lobe = powf(HdotN, e);
float norm = (n_x + 1.0f) / (8.0f * M_PI_F);
@@ -94,7 +94,8 @@ ccl_device float3 bsdf_ashikhmin_shirley_eval_reflect(const ShaderClosure *sc, c
out = NdotO * norm * lobe * pump;
*pdf = norm * lobe / HdotI; /* this is p_h / 4(H.I) (conversion from 'wh measure' to 'wi measure', eq. 8 in paper) */
}
- else { /* => ANisotropic case */
+ else {
+ /* anisotropic */
float3 X, Y;
make_orthonormals_tangent(N, sc->T, &X, &Y);
@@ -130,7 +131,7 @@ ccl_device int bsdf_ashikhmin_shirley_sample(const ShaderClosure *sc, float3 Ng,
float3 N = sc->N;
float NdotI = dot(N, I);
- if (NdotI > 0.0f) {
+ if(NdotI > 0.0f) {
float n_x = bsdf_ashikhmin_shirley_roughness_to_exponent(sc->data0);
float n_y = bsdf_ashikhmin_shirley_roughness_to_exponent(sc->data1);
@@ -146,21 +147,23 @@ ccl_device int bsdf_ashikhmin_shirley_sample(const ShaderClosure *sc, float3 Ng,
/* sample spherical coords for h in tangent space */
float phi;
float cos_theta;
- if (n_x == n_y) { /* => simple isotropic sampling */
+ if(n_x == n_y) {
+ /* isotropic sampling */
phi = M_2PI_F * randu;
cos_theta = powf(randv, 1.0f / (n_x + 1.0f));
}
- else { /* => more complex anisotropic sampling */
- if (randu < 0.25f) { /* first quadrant */
+ else {
+ /* anisotropic sampling */
+ if(randu < 0.25f) { /* first quadrant */
float remapped_randu = 4.0f * randu;
bsdf_ashikhmin_shirley_sample_first_quadrant(n_x, n_y, remapped_randu, randv, &phi, &cos_theta);
}
- else if (randu < 0.5f) { /* second quadrant */
+ else if(randu < 0.5f) { /* second quadrant */
float remapped_randu = 4.0f * (.5f - randu);
bsdf_ashikhmin_shirley_sample_first_quadrant(n_x, n_y, remapped_randu, randv, &phi, &cos_theta);
phi = M_PI_F - phi;
}
- else if (randu < 0.75f) { /* third quadrant */
+ else if(randu < 0.75f) { /* third quadrant */
float remapped_randu = 4.0f * (randu - 0.5f);
bsdf_ashikhmin_shirley_sample_first_quadrant(n_x, n_y, remapped_randu, randv, &phi, &cos_theta);
phi = M_PI_F + phi;
@@ -185,14 +188,20 @@ ccl_device int bsdf_ashikhmin_shirley_sample(const ShaderClosure *sc, float3 Ng,
/* half vector to world space */
float3 H = h.x*X + h.y*Y + h.z*N;
float HdotI = dot(H, I);
- if (HdotI < 0.0f) H = -H;
+ if(HdotI < 0.0f) H = -H;
/* reflect I on H to get omega_in */
*omega_in = -I + (2.0f * HdotI) * H;
- /* leave the rest to eval_reflect */
- /* (could maybe optimize a few things by manual inlining, but I doubt it would make much difference) */
- *eval = bsdf_ashikhmin_shirley_eval_reflect(sc, I, *omega_in, pdf);
+ if(fmaxf(sc->data0, sc->data1) <= 1e-4f) {
+ /* Some high number for MIS. */
+ *pdf = 1e6f;
+ *eval = make_float3(1e6f, 1e6f, 1e6f);
+ }
+ else {
+ /* leave the rest to eval_reflect */
+ *eval = bsdf_ashikhmin_shirley_eval_reflect(sc, I, *omega_in, pdf);
+ }
#ifdef __RAY_DIFFERENTIALS__
/* just do the reflection thing for now */
@@ -201,7 +210,7 @@ ccl_device int bsdf_ashikhmin_shirley_sample(const ShaderClosure *sc, float3 Ng,
#endif
}
- return LABEL_REFLECT | LABEL_GLOSSY;
+ return LABEL_REFLECT|LABEL_GLOSSY;
}
diff --git a/intern/cycles/kernel/closure/bsdf_ashikhmin_velvet.h b/intern/cycles/kernel/closure/bsdf_ashikhmin_velvet.h
index 3631f90bf8c..f1a26650078 100644
--- a/intern/cycles/kernel/closure/bsdf_ashikhmin_velvet.h
+++ b/intern/cycles/kernel/closure/bsdf_ashikhmin_velvet.h
@@ -45,10 +45,6 @@ ccl_device int bsdf_ashikhmin_velvet_setup(ShaderClosure *sc)
return SD_BSDF|SD_BSDF_HAS_EVAL;
}
-ccl_device void bsdf_ashikhmin_velvet_blur(ShaderClosure *sc, float roughness)
-{
-}
-
ccl_device float3 bsdf_ashikhmin_velvet_eval_reflect(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
{
float m_invsigma2 = sc->data0;
@@ -63,7 +59,7 @@ ccl_device float3 bsdf_ashikhmin_velvet_eval_reflect(const ShaderClosure *sc, co
float cosHO = fabsf(dot(I, H));
if(!(fabsf(cosNH) < 1.0f-1e-5f && cosHO > 1e-5f))
- return make_float3(0, 0, 0);
+ return make_float3(0.0f, 0.0f, 0.0f);
float cosNHdivHO = cosNH / cosHO;
cosNHdivHO = fmaxf(cosNHdivHO, 1e-5f);
@@ -84,7 +80,7 @@ ccl_device float3 bsdf_ashikhmin_velvet_eval_reflect(const ShaderClosure *sc, co
return make_float3(out, out, out);
}
- return make_float3(0, 0, 0);
+ return make_float3(0.0f, 0.0f, 0.0f);
}
ccl_device float3 bsdf_ashikhmin_velvet_eval_transmit(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
@@ -118,7 +114,7 @@ ccl_device int bsdf_ashikhmin_velvet_sample(const ShaderClosure *sc, float3 Ng,
float sinNH2 = 1 - cosNH * cosNH;
float sinNH4 = sinNH2 * sinNH2;
- float cotangent2 = (cosNH * cosNH) / sinNH2;
+ float cotangent2 = (cosNH * cosNH) / sinNH2;
float D = expf(-cotangent2 * m_invsigma2) * m_invsigma2 * M_1_PI_F / sinNH4;
float G = min(1.0f, min(fac1, fac2)); // TODO: derive G from D analytically
diff --git a/intern/cycles/kernel/closure/bsdf_diffuse.h b/intern/cycles/kernel/closure/bsdf_diffuse.h
index 949fe869549..4b29bb096d1 100644
--- a/intern/cycles/kernel/closure/bsdf_diffuse.h
+++ b/intern/cycles/kernel/closure/bsdf_diffuse.h
@@ -43,10 +43,6 @@ ccl_device int bsdf_diffuse_setup(ShaderClosure *sc)
return SD_BSDF|SD_BSDF_HAS_EVAL;
}
-ccl_device void bsdf_diffuse_blur(ShaderClosure *sc, float roughness)
-{
-}
-
ccl_device float3 bsdf_diffuse_eval_reflect(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
{
float3 N = sc->N;
@@ -90,10 +86,6 @@ ccl_device int bsdf_translucent_setup(ShaderClosure *sc)
return SD_BSDF|SD_BSDF_HAS_EVAL;
}
-ccl_device void bsdf_translucent_blur(ShaderClosure *sc, float roughness)
-{
-}
-
ccl_device float3 bsdf_translucent_eval_reflect(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
{
return make_float3(0.0f, 0.0f, 0.0f);
@@ -108,11 +100,6 @@ ccl_device float3 bsdf_translucent_eval_transmit(const ShaderClosure *sc, const
return make_float3 (cos_pi, cos_pi, cos_pi);
}
-ccl_device float bsdf_translucent_albedo(const ShaderClosure *sc, const float3 I)
-{
- return 1.0f;
-}
-
ccl_device int bsdf_translucent_sample(const ShaderClosure *sc, float3 Ng, float3 I, float3 dIdx, float3 dIdy, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf)
{
float3 N = sc->N;
diff --git a/intern/cycles/kernel/closure/bsdf_diffuse_ramp.h b/intern/cycles/kernel/closure/bsdf_diffuse_ramp.h
index b856774375f..e0287e7655a 100644
--- a/intern/cycles/kernel/closure/bsdf_diffuse_ramp.h
+++ b/intern/cycles/kernel/closure/bsdf_diffuse_ramp.h
@@ -41,9 +41,9 @@ ccl_device float3 bsdf_diffuse_ramp_get_color(const ShaderClosure *sc, const flo
float npos = pos * (float)(MAXCOLORS - 1);
int ipos = float_to_int(npos);
- if (ipos < 0)
+ if(ipos < 0)
return colors[0];
- if (ipos >= (MAXCOLORS - 1))
+ if(ipos >= (MAXCOLORS - 1))
return colors[MAXCOLORS - 1];
float offset = npos - (float)ipos;
return colors[ipos] * (1.0f - offset) + colors[ipos+1] * offset;
@@ -52,7 +52,9 @@ ccl_device float3 bsdf_diffuse_ramp_get_color(const ShaderClosure *sc, const flo
ccl_device int bsdf_diffuse_ramp_setup(ShaderClosure *sc)
{
sc->type = CLOSURE_BSDF_DIFFUSE_RAMP_ID;
- return SD_BSDF | SD_BSDF_HAS_EVAL;
+ sc->data0 = 0.0f;
+ sc->data1 = 0.0f;
+ return SD_BSDF|SD_BSDF_HAS_EVAL;
}
ccl_device void bsdf_diffuse_ramp_blur(ShaderClosure *sc, float roughness)
diff --git a/intern/cycles/kernel/closure/bsdf_hair.h b/intern/cycles/kernel/closure/bsdf_hair.h
index e0b5454592b..1e81617a7d3 100644
--- a/intern/cycles/kernel/closure/bsdf_hair.h
+++ b/intern/cycles/kernel/closure/bsdf_hair.h
@@ -36,20 +36,12 @@
CCL_NAMESPACE_BEGIN
-ccl_device void bsdf_hair_reflection_blur(ShaderClosure *sc, float roughness)
-{
-}
-
-ccl_device void bsdf_hair_transmission_blur(ShaderClosure *sc, float roughness)
-{
-}
-
ccl_device int bsdf_hair_reflection_setup(ShaderClosure *sc)
{
sc->type = CLOSURE_BSDF_HAIR_REFLECTION_ID;
sc->data0 = clamp(sc->data0, 0.001f, 1.0f);
sc->data1 = clamp(sc->data1, 0.001f, 1.0f);
- return SD_BSDF|SD_BSDF_HAS_EVAL|SD_BSDF_GLOSSY;
+ return SD_BSDF|SD_BSDF_HAS_EVAL;
}
ccl_device int bsdf_hair_transmission_setup(ShaderClosure *sc)
@@ -57,31 +49,25 @@ ccl_device int bsdf_hair_transmission_setup(ShaderClosure *sc)
sc->type = CLOSURE_BSDF_HAIR_TRANSMISSION_ID;
sc->data0 = clamp(sc->data0, 0.001f, 1.0f);
sc->data1 = clamp(sc->data1, 0.001f, 1.0f);
- return SD_BSDF|SD_BSDF_HAS_EVAL|SD_BSDF_GLOSSY;
+ return SD_BSDF|SD_BSDF_HAS_EVAL;
}
ccl_device float3 bsdf_hair_reflection_eval_reflect(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
{
-#ifdef __HAIR__
float offset = sc->data2;
float3 Tg = sc->T;
-#else
- float offset = 0.0f;
- float3 Tg = make_float3(1.0f, 0.0f, 0.0f);
-#endif
float roughness1 = sc->data0;
float roughness2 = sc->data1;
float Iz = dot(Tg, I);
float3 locy = normalize(I - Tg * Iz);
- //float3 locx = cross(locy, Tg);
- float theta_r = M_PI_2_F - safe_acosf(Iz);
+ float theta_r = M_PI_2_F - fast_acosf(Iz);
float omega_in_z = dot(Tg, omega_in);
float3 omega_in_y = normalize(omega_in - Tg * omega_in_z);
- float theta_i = M_PI_2_F - safe_acosf(omega_in_z);
+ float theta_i = M_PI_2_F - fast_acosf(omega_in_z);
float cosphi_i = dot(omega_in_y, locy);
if(M_PI_2_F - fabsf(theta_i) < 0.001f || cosphi_i < 0.0f) {
@@ -89,17 +75,19 @@ ccl_device float3 bsdf_hair_reflection_eval_reflect(const ShaderClosure *sc, con
return make_float3(*pdf, *pdf, *pdf);
}
- float phi_i = safe_acosf(cosphi_i) / roughness2;
+ float roughness1_inv = 1.0f / roughness1;
+ float roughness2_inv = 1.0f / roughness2;
+ float phi_i = fast_acosf(cosphi_i) * roughness2_inv;
phi_i = fabsf(phi_i) < M_PI_F ? phi_i : M_PI_F;
- float costheta_i = cosf(theta_i);
+ float costheta_i = fast_cosf(theta_i);
- float a_R = atan2f(((M_PI_2_F + theta_r) * 0.5f - offset) / roughness1, 1.0f);
- float b_R = atan2f(((-M_PI_2_F + theta_r) * 0.5f - offset) / roughness1, 1.0f);
+ float a_R = fast_atan2f(((M_PI_2_F + theta_r) * 0.5f - offset) * roughness1_inv, 1.0f);
+ float b_R = fast_atan2f(((-M_PI_2_F + theta_r) * 0.5f - offset) * roughness1_inv, 1.0f);
float theta_h = (theta_i + theta_r) * 0.5f;
float t = theta_h - offset;
- float phi_pdf = cosf(phi_i * 0.5f) * 0.25f / roughness2;
+ float phi_pdf = fast_cosf(phi_i * 0.5f) * 0.25f * roughness2_inv;
float theta_pdf = roughness1 / (2 * (t*t + roughness1*roughness1) * (a_R - b_R)* costheta_i);
*pdf = phi_pdf * theta_pdf;
@@ -119,37 +107,32 @@ ccl_device float3 bsdf_hair_reflection_eval_transmit(const ShaderClosure *sc, co
ccl_device float3 bsdf_hair_transmission_eval_transmit(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
{
-#ifdef __HAIR__
float offset = sc->data2;
float3 Tg = sc->T;
-#else
- float offset = 0.0f;
- float3 Tg = make_float3(1.0f, 0.0f, 0.0f);
-#endif
float roughness1 = sc->data0;
float roughness2 = sc->data1;
float Iz = dot(Tg, I);
float3 locy = normalize(I - Tg * Iz);
- //float3 locx = cross(locy, Tg);
- float theta_r = M_PI_2_F - safe_acosf(Iz);
+ float theta_r = M_PI_2_F - fast_acosf(Iz);
float omega_in_z = dot(Tg, omega_in);
float3 omega_in_y = normalize(omega_in - Tg * omega_in_z);
- float theta_i = M_PI_2_F - safe_acosf(omega_in_z);
- float phi_i = safe_acosf(dot(omega_in_y, locy));
+ float theta_i = M_PI_2_F - fast_acosf(omega_in_z);
+ float phi_i = fast_acosf(dot(omega_in_y, locy));
if(M_PI_2_F - fabsf(theta_i) < 0.001f) {
*pdf = 0.0f;
return make_float3(*pdf, *pdf, *pdf);
}
- float costheta_i = cosf(theta_i);
+ float costheta_i = fast_cosf(theta_i);
- float a_TT = atan2f(((M_PI_2_F + theta_r)/2 - offset) / roughness1, 1.0f);
- float b_TT = atan2f(((-M_PI_2_F + theta_r)/2 - offset) / roughness1, 1.0f);
- float c_TT = 2 * atan2f(M_PI_2_F / roughness2, 1.0f);
+ float roughness1_inv = 1.0f / roughness1;
+ float a_TT = fast_atan2f(((M_PI_2_F + theta_r)/2 - offset) * roughness1_inv, 1.0f);
+ float b_TT = fast_atan2f(((-M_PI_2_F + theta_r)/2 - offset) * roughness1_inv, 1.0f);
+ float c_TT = 2 * fast_atan2f(M_PI_2_F / roughness2, 1.0f);
float theta_h = (theta_i + theta_r) / 2;
float t = theta_h - offset;
@@ -165,39 +148,38 @@ ccl_device float3 bsdf_hair_transmission_eval_transmit(const ShaderClosure *sc,
ccl_device int bsdf_hair_reflection_sample(const ShaderClosure *sc, float3 Ng, float3 I, float3 dIdx, float3 dIdy, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf)
{
-#ifdef __HAIR__
float offset = sc->data2;
float3 Tg = sc->T;
-#else
- float offset = 0.0f;
- float3 Tg = make_float3(1.0f, 0.0f, 0.0f);
-#endif
float roughness1 = sc->data0;
float roughness2 = sc->data1;
float Iz = dot(Tg, I);
float3 locy = normalize(I - Tg * Iz);
float3 locx = cross(locy, Tg);
- float theta_r = M_PI_2_F - safe_acosf(Iz);
+ float theta_r = M_PI_2_F - fast_acosf(Iz);
- float a_R = atan2f(((M_PI_2_F + theta_r) * 0.5f - offset) / roughness1, 1.0f);
- float b_R = atan2f(((-M_PI_2_F + theta_r) * 0.5f - offset) / roughness1, 1.0f);
+ float roughness1_inv = 1.0f / roughness1;
+ float a_R = fast_atan2f(((M_PI_2_F + theta_r) * 0.5f - offset) * roughness1_inv, 1.0f);
+ float b_R = fast_atan2f(((-M_PI_2_F + theta_r) * 0.5f - offset) * roughness1_inv, 1.0f);
float t = roughness1 * tanf(randu * (a_R - b_R) + b_R);
float theta_h = t + offset;
float theta_i = 2 * theta_h - theta_r;
- float costheta_i = cosf(theta_i);
- float sintheta_i = sinf(theta_i);
+
+ float costheta_i, sintheta_i;
+ fast_sincosf(theta_i, &sintheta_i, &costheta_i);
float phi = 2 * safe_asinf(1 - 2 * randv) * roughness2;
- float phi_pdf = cosf(phi * 0.5f) * 0.25f / roughness2;
+ float phi_pdf = fast_cosf(phi * 0.5f) * 0.25f / roughness2;
float theta_pdf = roughness1 / (2 * (t*t + roughness1*roughness1) * (a_R - b_R)*costheta_i);
- *omega_in =(cosf(phi) * costheta_i) * locy -
- (sinf(phi) * costheta_i) * locx +
- ( sintheta_i) * Tg;
+ float sinphi, cosphi;
+ fast_sincosf(phi, &sinphi, &cosphi);
+ *omega_in =(cosphi * costheta_i) * locy -
+ (sinphi * costheta_i) * locx +
+ ( sintheta_i) * Tg;
//differentials - TODO: find a better approximation for the reflective bounce
#ifdef __RAY_DIFFERENTIALS__
@@ -211,48 +193,43 @@ ccl_device int bsdf_hair_reflection_sample(const ShaderClosure *sc, float3 Ng, f
*eval = make_float3(*pdf, *pdf, *pdf);
- if(dot(locy, *omega_in) < 0.0f) {
- return LABEL_REFLECT|LABEL_TRANSMIT|LABEL_GLOSSY;
- }
-
return LABEL_REFLECT|LABEL_GLOSSY;
}
ccl_device int bsdf_hair_transmission_sample(const ShaderClosure *sc, float3 Ng, float3 I, float3 dIdx, float3 dIdy, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf)
{
-#ifdef __HAIR__
float offset = sc->data2;
float3 Tg = sc->T;
-#else
- float offset = 0.0f;
- float3 Tg = make_float3(1.0f, 0.0f, 0.0f);
-#endif
float roughness1 = sc->data0;
float roughness2 = sc->data1;
float Iz = dot(Tg, I);
float3 locy = normalize(I - Tg * Iz);
float3 locx = cross(locy, Tg);
- float theta_r = M_PI_2_F - safe_acosf(Iz);
+ float theta_r = M_PI_2_F - fast_acosf(Iz);
- float a_TT = atan2f(((M_PI_2_F + theta_r)/2 - offset) / roughness1, 1.0f);
- float b_TT = atan2f(((-M_PI_2_F + theta_r)/2 - offset) / roughness1, 1.0f);
- float c_TT = 2 * atan2f(M_PI_2_F / roughness2, 1.0f);
+ float roughness1_inv = 1.0f / roughness1;
+ float a_TT = fast_atan2f(((M_PI_2_F + theta_r)/2 - offset) * roughness1_inv, 1.0f);
+ float b_TT = fast_atan2f(((-M_PI_2_F + theta_r)/2 - offset) * roughness1_inv, 1.0f);
+ float c_TT = 2 * fast_atan2f(M_PI_2_F / roughness2, 1.0f);
float t = roughness1 * tanf(randu * (a_TT - b_TT) + b_TT);
float theta_h = t + offset;
float theta_i = 2 * theta_h - theta_r;
- float costheta_i = cosf(theta_i);
- float sintheta_i = sinf(theta_i);
+
+ float costheta_i, sintheta_i;
+ fast_sincosf(theta_i, &sintheta_i, &costheta_i);
float p = roughness2 * tanf(c_TT * (randv - 0.5f));
float phi = p + M_PI_F;
float theta_pdf = roughness1 / (2 * (t*t + roughness1*roughness1) * (a_TT - b_TT) * costheta_i);
float phi_pdf = roughness2 / (c_TT * (p * p + roughness2 * roughness2));
- *omega_in =(cosf(phi) * costheta_i) * locy -
- (sinf(phi) * costheta_i) * locx +
- ( sintheta_i) * Tg;
+ float sinphi, cosphi;
+ fast_sincosf(phi, &sinphi, &cosphi);
+ *omega_in =(cosphi * costheta_i) * locy -
+ (sinphi * costheta_i) * locx +
+ ( sintheta_i) * Tg;
//differentials - TODO: find a better approximation for the transmission bounce
#ifdef __RAY_DIFFERENTIALS__
@@ -267,10 +244,9 @@ ccl_device int bsdf_hair_transmission_sample(const ShaderClosure *sc, float3 Ng,
*eval = make_float3(*pdf, *pdf, *pdf);
- if(dot(locy, *omega_in) < 0.0f)
- return LABEL_TRANSMIT|LABEL_GLOSSY;
-
- return LABEL_GLOSSY;
+ kernel_assert(dot(locy, *omega_in) < 0.0f);
+
+ return LABEL_TRANSMIT|LABEL_GLOSSY;
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/closure/bsdf_microfacet.h b/intern/cycles/kernel/closure/bsdf_microfacet.h
index a0c59e6cbc0..2a0e8f62e7c 100644
--- a/intern/cycles/kernel/closure/bsdf_microfacet.h
+++ b/intern/cycles/kernel/closure/bsdf_microfacet.h
@@ -35,145 +35,7 @@
CCL_NAMESPACE_BEGIN
-/* Approximate erf and erfinv implementations
- *
- * Adapted from code (C) Copyright John Maddock 2006.
- * Use, modification and distribution are subject to the
- * Boost Software License, Version 1.0. (See accompanying file
- * LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) */
-
-ccl_device float approx_erff_impl(float z)
-{
- float result;
-
- if(z < 0.5f) {
- if(z < 1e-10f) {
- if(z == 0) {
- result = 0;
- }
- else {
- float c = 0.0033791670f;
- result = z * 1.125f + z * c;
- }
- }
- else {
- float Y = 1.044948577f;
-
- float zz = z * z;
- float num = (((-0.007727583f * zz) + -0.050999073f)*zz + -0.338165134f)*zz + 0.083430589f;
- float denom = (((0.000370900f * zz) + 0.008585719f)*zz + 0.087522260f)*zz + 0.455004033f;
- result = z * (Y + num / denom);
- }
- }
- else if(z < 2.5f) {
- if(z < 1.5f) {
- float Y = 0.4059357643f;
- float fz = z - 0.5f;
-
- float num = (((0.088890036f * fz) + 0.191003695f)*fz + 0.178114665f)*fz + -0.098090592f;
- float denom = (((0.123850974f * fz) + 0.578052804f)*fz + 1.426280048f)*fz + 1.847590709f;
-
- result = Y + num / denom;
- result *= expf(-z * z) / z;
- }
- else {
- float Y = 0.506728172f;
- float fz = z - 1.5f;
- float num = (((0.017567943f * fz) + 0.043948189f)*fz + 0.038654037f)*fz + -0.024350047f;
- float denom = (((0.325732924f * fz) + 0.982403709f)*fz + 1.539914949f)*fz + 1;
-
- result = Y + num / denom;
- result *= expf(-z * z) / z;
- }
-
- result = 1 - result;
- }
- else {
- result = 1;
- }
-
- return result;
-}
-
-ccl_device float approx_erff(float z)
-{
- float s = 1.0f;
-
- if(z < 0.0f) {
- s = -1.0f;
- z = -z;
- }
-
- return s * approx_erff_impl(z);
-}
-
-ccl_device float approx_erfinvf_impl(float p, float q)
-{
- float result = 0;
-
- if(p <= 0.5f) {
- float Y = 0.089131474f;
- float g = p * (p + 10);
- float num = (((-0.012692614f * p) + 0.033480662f)*p + -0.008368748f)*p + -0.000508781f;
- float denom = (((1.562215583f * p) + -1.565745582f)*p + -0.970005043f)*p + 1.0f;
- float r = num / denom;
- result = g * Y + g * r;
- }
- else if(q >= 0.25f) {
- float Y = 2.249481201f;
- float g = sqrtf(-2 * logf(q));
- float xs = q - 0.25f;
- float num = (((17.644729840f * xs) + 8.370503283f)*xs + 0.105264680f)*xs + -0.202433508f;
- float denom = (((-28.660818049f * xs) + 3.971343795f)*xs + 6.242641248f)*xs + 1.0f;
- float r = num / denom;
- result = g / (Y + r);
- }
- else {
- float x = sqrtf(-logf(q));
-
- if(x < 3) {
- float Y = 0.807220458f;
- float xs = x - 1.125f;
- float num = (((0.387079738f * xs) + 0.117030156f)*xs + -0.163794047f)*xs + -0.131102781f;
- float denom = (((4.778465929f * xs) + 5.381683457f)*xs + 3.466254072f)*xs + 1.0f;
- float R = num / denom;
- result = Y * x + R * x;
- }
- else {
- float Y = 0.939955711f;
- float xs = x - 3;
- float num = (((0.009508047f * xs) + 0.018557330f)*xs + -0.002224265f)*xs + -0.035035378f;
- float denom = (((0.220091105f * xs) + 0.762059164f)*xs + 1.365334981f)*xs + 1.0f;
- float R = num / denom;
- result = Y * x + R * x;
- }
- }
-
- return result;
-}
-
-ccl_device float approx_erfinvf(float z)
-{
- float p, q, s;
-
- if(z < 0) {
- p = -z;
- q = 1 - p;
- s = -1;
- }
- else {
- p = z;
- q = 1 - z;
- s = 1;
- }
-
- return s * approx_erfinvf_impl(p, q);
-}
-
-/* Beckmann and GGX microfacet importance sampling from:
- *
- * Importance Sampling Microfacet-Based BSDFs using the Distribution of Visible Normals.
- * E. Heitz and E. d'Eon, EGSR 2014 */
+/* Beckmann and GGX microfacet importance sampling. */
ccl_device_inline void microfacet_beckmann_sample_slopes(
KernelGlobals *kg,
@@ -194,64 +56,71 @@ ccl_device_inline void microfacet_beckmann_sample_slopes(
/* precomputations */
const float tan_theta_i = sin_theta_i/cos_theta_i;
const float inv_a = tan_theta_i;
- const float a = 1.0f/inv_a;
- const float erf_a = approx_erff(a);
- const float exp_a2 = expf(-a*a);
+ const float cot_theta_i = 1.0f/tan_theta_i;
+ const float erf_a = fast_erff(cot_theta_i);
+ const float exp_a2 = expf(-cot_theta_i*cot_theta_i);
const float SQRT_PI_INV = 0.56418958354f;
const float Lambda = 0.5f*(erf_a - 1.0f) + (0.5f*SQRT_PI_INV)*(exp_a2*inv_a);
const float G1 = 1.0f/(1.0f + Lambda); /* masking */
*G1i = G1;
-#if 0
- const float C = 1.0f - G1 * erf_a;
-
- /* sample slope X */
- if(randu < C) {
- /* rescale randu */
- randu = randu / C;
- const float w_1 = 0.5f * SQRT_PI_INV * sin_theta_i * exp_a2;
- const float w_2 = cos_theta_i * (0.5f - 0.5f*erf_a);
- const float p = w_1 / (w_1 + w_2);
-
- if(randu < p) {
- randu = randu / p;
- *slope_x = -sqrtf(-logf(randu*exp_a2));
- }
- else {
- randu = (randu - p) / (1.0f - p);
- *slope_x = approx_erfinvf(randu - 1.0f - randu*erf_a);
- }
+#if defined(__KERNEL_GPU__)
+ /* Based on paper from Wenzel Jakob
+ * An Improved Visible Normal Sampling Routine for the Beckmann Distribution
+ *
+ * http://www.mitsuba-renderer.org/~wenzel/files/visnormal.pdf
+ *
+ * Reformulation from OpenShadingLanguage which avoids using inverse
+ * trigonometric functions.
+ */
+
+ /* Sample slope X.
+ *
+ * Compute a coarse approximation using the approximation:
+ * exp(-ierf(x)^2) ~= 1 - x * x
+ * solve y = 1 + b + K * (1 - b * b)
+ */
+ float K = tan_theta_i * SQRT_PI_INV;
+ float y_approx = randu * (1.0f + erf_a + K * (1 - erf_a * erf_a));
+ float y_exact = randu * (1.0f + erf_a + K * exp_a2);
+ float b = K > 0 ? (0.5f - sqrtf(K * (K - y_approx + 1.0f) + 0.25f)) / K : y_approx - 1.0f;
+
+ /* Perform newton step to refine toward the true root. */
+ float inv_erf = fast_ierff(b);
+ float value = 1.0f + b + K * expf(-inv_erf * inv_erf) - y_exact;
+ /* Check if we are close enough already,
+ * this also avoids NaNs as we get close to the root.
+ */
+ if(fabsf(value) > 1e-6f) {
+ b -= value / (1.0f - inv_erf * tan_theta_i); /* newton step 1. */
+ inv_erf = fast_ierff(b);
+ value = 1.0f + b + K * expf(-inv_erf * inv_erf) - y_exact;
+ b -= value / (1.0f - inv_erf * tan_theta_i); /* newton step 2. */
+ /* Compute the slope from the refined value. */
+ *slope_x = fast_ierff(b);
}
else {
- /* rescale randu */
- randu = (randu - C) / (1.0f - C);
- *slope_x = approx_erfinvf((-1.0f + 2.0f*randu)*erf_a);
-
- const float p = (-(*slope_x)*sin_theta_i + cos_theta_i) / (2.0f*cos_theta_i);
-
- if(randv > p) {
- *slope_x = -(*slope_x);
- randv = (randv - p) / (1.0f - p);
- }
- else
- randv = randv / p;
+ /* We are close enough already. */
+ *slope_x = inv_erf;
}
-
- /* sample slope Y */
- *slope_y = approx_erfinvf(2.0f*randv - 1.0f);
+ *slope_y = fast_ierff(2.0f*randv - 1.0f);
#else
- /* use precomputed table, because it better preserves stratification
- * of the random number pattern */
+ /* Use precomputed table on CPU, it gives better perfomance. */
int beckmann_table_offset = kernel_data.tables.beckmann_offset;
*slope_x = lookup_table_read_2D(kg, randu, cos_theta_i,
beckmann_table_offset, BECKMANN_TABLE_SIZE, BECKMANN_TABLE_SIZE);
- *slope_y = approx_erfinvf(2.0f*randv - 1.0f);
+ *slope_y = fast_ierff(2.0f*randv - 1.0f);
#endif
-
}
+/* GGX microfacet importance sampling from:
+ *
+ * Importance Sampling Microfacet-Based BSDFs using the Distribution of Visible Normals.
+ * E. Heitz and E. d'Eon, EGSR 2014
+ */
+
ccl_device_inline void microfacet_ggx_sample_slopes(
const float cos_theta_i, const float sin_theta_i,
float randu, float randv, float *slope_x, float *slope_y,
@@ -366,32 +235,32 @@ ccl_device_inline float3 microfacet_sample_stretched(
ccl_device int bsdf_microfacet_ggx_setup(ShaderClosure *sc)
{
- sc->data0 = clamp(sc->data0, 0.0f, 1.0f); /* alpha_x */
+ sc->data0 = saturate(sc->data0); /* alpha_x */
sc->data1 = sc->data0; /* alpha_y */
sc->type = CLOSURE_BSDF_MICROFACET_GGX_ID;
- return SD_BSDF|SD_BSDF_HAS_EVAL|SD_BSDF_GLOSSY;
+ return SD_BSDF|SD_BSDF_HAS_EVAL;
}
ccl_device int bsdf_microfacet_ggx_aniso_setup(ShaderClosure *sc)
{
- sc->data0 = clamp(sc->data0, 0.0f, 1.0f); /* alpha_x */
- sc->data1 = clamp(sc->data1, 0.0f, 1.0f); /* alpha_y */
+ sc->data0 = saturate(sc->data0); /* alpha_x */
+ sc->data1 = saturate(sc->data1); /* alpha_y */
sc->type = CLOSURE_BSDF_MICROFACET_GGX_ANISO_ID;
- return SD_BSDF|SD_BSDF_HAS_EVAL|SD_BSDF_GLOSSY;
+ return SD_BSDF|SD_BSDF_HAS_EVAL;
}
ccl_device int bsdf_microfacet_ggx_refraction_setup(ShaderClosure *sc)
{
- sc->data0 = clamp(sc->data0, 0.0f, 1.0f); /* alpha_x */
+ sc->data0 = saturate(sc->data0); /* alpha_x */
sc->data1 = sc->data0; /* alpha_y */
sc->type = CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID;
- return SD_BSDF|SD_BSDF_HAS_EVAL|SD_BSDF_GLOSSY;
+ return SD_BSDF|SD_BSDF_HAS_EVAL;
}
ccl_device void bsdf_microfacet_ggx_blur(ShaderClosure *sc, float roughness)
@@ -404,11 +273,11 @@ ccl_device float3 bsdf_microfacet_ggx_eval_reflect(const ShaderClosure *sc, cons
{
float alpha_x = sc->data0;
float alpha_y = sc->data1;
- int m_refractive = sc->type == CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID;
+ bool m_refractive = sc->type == CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID;
float3 N = sc->N;
if(m_refractive || fmaxf(alpha_x, alpha_y) <= 1e-4f)
- return make_float3(0, 0, 0);
+ return make_float3(0.0f, 0.0f, 0.0f);
float cosNO = dot(N, I);
float cosNI = dot(N, omega_in);
@@ -487,7 +356,7 @@ ccl_device float3 bsdf_microfacet_ggx_eval_reflect(const ShaderClosure *sc, cons
return make_float3(out, out, out);
}
- return make_float3(0, 0, 0);
+ return make_float3(0.0f, 0.0f, 0.0f);
}
ccl_device float3 bsdf_microfacet_ggx_eval_transmit(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
@@ -495,17 +364,17 @@ ccl_device float3 bsdf_microfacet_ggx_eval_transmit(const ShaderClosure *sc, con
float alpha_x = sc->data0;
float alpha_y = sc->data1;
float m_eta = sc->data2;
- int m_refractive = sc->type == CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID;
+ bool m_refractive = sc->type == CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID;
float3 N = sc->N;
if(!m_refractive || fmaxf(alpha_x, alpha_y) <= 1e-4f)
- return make_float3(0, 0, 0);
+ return make_float3(0.0f, 0.0f, 0.0f);
float cosNO = dot(N, I);
float cosNI = dot(N, omega_in);
if(cosNO <= 0 || cosNI >= 0)
- return make_float3(0, 0, 0); /* vectors on same side -- not possible */
+ return make_float3(0.0f, 0.0f, 0.0f); /* vectors on same side -- not possible */
/* compute half-vector of the refraction (eq. 16) */
float3 ht = -(m_eta * omega_in + I);
@@ -513,10 +382,6 @@ ccl_device float3 bsdf_microfacet_ggx_eval_transmit(const ShaderClosure *sc, con
float cosHO = dot(Ht, I);
float cosHI = dot(Ht, omega_in);
- /* those situations makes chi+ terms in eq. 33, 34 be zero */
- if(dot(Ht, N) <= 0.0f || cosHO * cosNO <= 0.0f || cosHI * cosNI <= 0.0f)
- return make_float3(0.0f, 0.0f, 0.0f);
-
float D, G1o, G1i;
/* eq. 33: first we calculate D(m) with m=Ht: */
@@ -543,7 +408,7 @@ ccl_device float3 bsdf_microfacet_ggx_eval_transmit(const ShaderClosure *sc, con
* pdf = pm * (m_eta * m_eta) * fabsf(cosHI) / Ht2 */
float common = D * (m_eta * m_eta) / (cosNO * Ht2);
float out = G * fabsf(cosHI * cosHO) * common;
- *pdf = G1o * cosHO * fabsf(cosHI) * common;
+ *pdf = G1o * fabsf(cosHO * cosHI) * common;
return make_float3(out, out, out);
}
@@ -552,7 +417,7 @@ ccl_device int bsdf_microfacet_ggx_sample(KernelGlobals *kg, const ShaderClosure
{
float alpha_x = sc->data0;
float alpha_y = sc->data1;
- int m_refractive = sc->type == CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID;
+ bool m_refractive = sc->type == CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID;
float3 N = sc->N;
float cosNO = dot(N, I);
@@ -657,16 +522,16 @@ ccl_device int bsdf_microfacet_ggx_sample(KernelGlobals *kg, const ShaderClosure
#ifdef __RAY_DIFFERENTIALS__
float3 dRdx, dRdy, dTdx, dTdy;
#endif
- float m_eta = sc->data2;
+ float m_eta = sc->data2, fresnel;
bool inside;
- fresnel_dielectric(m_eta, m, I, &R, &T,
+ fresnel = fresnel_dielectric(m_eta, m, I, &R, &T,
#ifdef __RAY_DIFFERENTIALS__
dIdx, dIdy, &dRdx, &dRdy, &dTdx, &dTdy,
#endif
&inside);
- if(!inside) {
+ if(!inside && fresnel != 1.0f) {
*omega_in = T;
#ifdef __RAY_DIFFERENTIALS__
@@ -719,29 +584,29 @@ ccl_device int bsdf_microfacet_ggx_sample(KernelGlobals *kg, const ShaderClosure
ccl_device int bsdf_microfacet_beckmann_setup(ShaderClosure *sc)
{
- sc->data0 = clamp(sc->data0, 0.0f, 1.0f); /* alpha_x */
+ sc->data0 = saturate(sc->data0); /* alpha_x */
sc->data1 = sc->data0; /* alpha_y */
sc->type = CLOSURE_BSDF_MICROFACET_BECKMANN_ID;
- return SD_BSDF|SD_BSDF_HAS_EVAL|SD_BSDF_GLOSSY;
+ return SD_BSDF|SD_BSDF_HAS_EVAL;
}
ccl_device int bsdf_microfacet_beckmann_aniso_setup(ShaderClosure *sc)
{
- sc->data0 = clamp(sc->data0, 0.0f, 1.0f); /* alpha_x */
- sc->data1 = clamp(sc->data1, 0.0f, 1.0f); /* alpha_y */
+ sc->data0 = saturate(sc->data0); /* alpha_x */
+ sc->data1 = saturate(sc->data1); /* alpha_y */
sc->type = CLOSURE_BSDF_MICROFACET_BECKMANN_ANISO_ID;
- return SD_BSDF|SD_BSDF_HAS_EVAL|SD_BSDF_GLOSSY;
+ return SD_BSDF|SD_BSDF_HAS_EVAL;
}
ccl_device int bsdf_microfacet_beckmann_refraction_setup(ShaderClosure *sc)
{
- sc->data0 = clamp(sc->data0, 0.0f, 1.0f); /* alpha_x */
+ sc->data0 = saturate(sc->data0); /* alpha_x */
sc->data1 = sc->data0; /* alpha_y */
sc->type = CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID;
- return SD_BSDF|SD_BSDF_HAS_EVAL|SD_BSDF_GLOSSY;
+ return SD_BSDF|SD_BSDF_HAS_EVAL;
}
ccl_device void bsdf_microfacet_beckmann_blur(ShaderClosure *sc, float roughness)
@@ -754,11 +619,11 @@ ccl_device float3 bsdf_microfacet_beckmann_eval_reflect(const ShaderClosure *sc,
{
float alpha_x = sc->data0;
float alpha_y = sc->data1;
- int m_refractive = sc->type == CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID;
+ bool m_refractive = sc->type == CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID;
float3 N = sc->N;
if(m_refractive || fmaxf(alpha_x, alpha_y) <= 1e-4f)
- return make_float3(0, 0, 0);
+ return make_float3(0.0f, 0.0f, 0.0f);
float cosNO = dot(N, I);
float cosNI = dot(N, omega_in);
@@ -840,7 +705,7 @@ ccl_device float3 bsdf_microfacet_beckmann_eval_reflect(const ShaderClosure *sc,
return make_float3(out, out, out);
}
- return make_float3(0, 0, 0);
+ return make_float3(0.0f, 0.0f, 0.0f);
}
ccl_device float3 bsdf_microfacet_beckmann_eval_transmit(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
@@ -848,17 +713,17 @@ ccl_device float3 bsdf_microfacet_beckmann_eval_transmit(const ShaderClosure *sc
float alpha_x = sc->data0;
float alpha_y = sc->data1;
float m_eta = sc->data2;
- int m_refractive = sc->type == CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID;
+ bool m_refractive = sc->type == CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID;
float3 N = sc->N;
if(!m_refractive || fmaxf(alpha_x, alpha_y) <= 1e-4f)
- return make_float3(0, 0, 0);
+ return make_float3(0.0f, 0.0f, 0.0f);
float cosNO = dot(N, I);
float cosNI = dot(N, omega_in);
if(cosNO <= 0 || cosNI >= 0)
- return make_float3(0, 0, 0);
+ return make_float3(0.0f, 0.0f, 0.0f);
/* compute half-vector of the refraction (eq. 16) */
float3 ht = -(m_eta * omega_in + I);
@@ -866,10 +731,6 @@ ccl_device float3 bsdf_microfacet_beckmann_eval_transmit(const ShaderClosure *sc
float cosHO = dot(Ht, I);
float cosHI = dot(Ht, omega_in);
- /* those situations makes chi+ terms in eq. 25, 27 be zero */
- if(dot(Ht, N) <= 0.0f || cosHO * cosNO <= 0.0f || cosHI * cosNI <= 0.0f)
- return make_float3(0.0f, 0.0f, 0.0f);
-
/* eq. 25: first we calculate D(m) with m=Ht: */
float alpha2 = alpha_x * alpha_y;
float cosThetaM = min(dot(N, Ht), 1.0f);
@@ -895,7 +756,7 @@ ccl_device float3 bsdf_microfacet_beckmann_eval_transmit(const ShaderClosure *sc
* pdf = pm * (m_eta * m_eta) * fabsf(cosHI) / Ht2 */
float common = D * (m_eta * m_eta) / (cosNO * Ht2);
float out = G * fabsf(cosHI * cosHO) * common;
- *pdf = G1o * cosHO * fabsf(cosHI) * common;
+ *pdf = G1o * fabsf(cosHO * cosHI) * common;
return make_float3(out, out, out);
}
@@ -904,7 +765,7 @@ ccl_device int bsdf_microfacet_beckmann_sample(KernelGlobals *kg, const ShaderCl
{
float alpha_x = sc->data0;
float alpha_y = sc->data1;
- int m_refractive = sc->type == CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID;
+ bool m_refractive = sc->type == CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID;
float3 N = sc->N;
float cosNO = dot(N, I);
@@ -1011,16 +872,16 @@ ccl_device int bsdf_microfacet_beckmann_sample(KernelGlobals *kg, const ShaderCl
#ifdef __RAY_DIFFERENTIALS__
float3 dRdx, dRdy, dTdx, dTdy;
#endif
- float m_eta = sc->data2;
+ float m_eta = sc->data2, fresnel;
bool inside;
- fresnel_dielectric(m_eta, m, I, &R, &T,
+ fresnel = fresnel_dielectric(m_eta, m, I, &R, &T,
#ifdef __RAY_DIFFERENTIALS__
dIdx, dIdy, &dRdx, &dRdy, &dTdx, &dTdy,
#endif
&inside);
- if(!inside) {
+ if(!inside && fresnel != 1.0f) {
*omega_in = T;
#ifdef __RAY_DIFFERENTIALS__
diff --git a/intern/cycles/kernel/closure/bsdf_oren_nayar.h b/intern/cycles/kernel/closure/bsdf_oren_nayar.h
index 6f685d5eeea..61b7cb11b02 100644
--- a/intern/cycles/kernel/closure/bsdf_oren_nayar.h
+++ b/intern/cycles/kernel/closure/bsdf_oren_nayar.h
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#ifndef __BSDF_OREN_NAYAR_H__
@@ -25,7 +25,7 @@ ccl_device float3 bsdf_oren_nayar_get_intensity(const ShaderClosure *sc, float3
float nv = max(dot(n, v), 0.0f);
float t = dot(l, v) - nl * nv;
- if (t > 0.0f)
+ if(t > 0.0f)
t /= max(nl, nv) + FLT_MIN;
float is = nl * (sc->data0 + sc->data1 * t);
return make_float3(is, is, is);
@@ -37,23 +37,19 @@ ccl_device int bsdf_oren_nayar_setup(ShaderClosure *sc)
sc->type = CLOSURE_BSDF_OREN_NAYAR_ID;
- sigma = clamp(sigma, 0.0f, 1.0f);
+ sigma = saturate(sigma);
float div = 1.0f / (M_PI_F + ((3.0f * M_PI_F - 4.0f) / 6.0f) * sigma);
sc->data0 = 1.0f * div;
sc->data1 = sigma * div;
- return SD_BSDF | SD_BSDF_HAS_EVAL;
-}
-
-ccl_device void bsdf_oren_nayar_blur(ShaderClosure *sc, float roughness)
-{
+ return SD_BSDF|SD_BSDF_HAS_EVAL;
}
ccl_device float3 bsdf_oren_nayar_eval_reflect(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
{
- if (dot(sc->N, omega_in) > 0.0f) {
+ if(dot(sc->N, omega_in) > 0.0f) {
*pdf = 0.5f * M_1_PI_F;
return bsdf_oren_nayar_get_intensity(sc, sc->N, I, omega_in);
}
@@ -72,7 +68,7 @@ ccl_device int bsdf_oren_nayar_sample(const ShaderClosure *sc, float3 Ng, float3
{
sample_uniform_hemisphere(sc->N, randu, randv, omega_in, pdf);
- if (dot(Ng, *omega_in) > 0.0f) {
+ if(dot(Ng, *omega_in) > 0.0f) {
*eval = bsdf_oren_nayar_get_intensity(sc, sc->N, I, *omega_in);
#ifdef __RAY_DIFFERENTIALS__
@@ -86,7 +82,7 @@ ccl_device int bsdf_oren_nayar_sample(const ShaderClosure *sc, float3 Ng, float3
*eval = make_float3(0.0f, 0.0f, 0.0f);
}
- return LABEL_REFLECT | LABEL_DIFFUSE;
+ return LABEL_REFLECT|LABEL_DIFFUSE;
}
diff --git a/intern/cycles/kernel/closure/bsdf_phong_ramp.h b/intern/cycles/kernel/closure/bsdf_phong_ramp.h
index 2b4e1c68640..1ab15eee954 100644
--- a/intern/cycles/kernel/closure/bsdf_phong_ramp.h
+++ b/intern/cycles/kernel/closure/bsdf_phong_ramp.h
@@ -41,9 +41,9 @@ ccl_device float3 bsdf_phong_ramp_get_color(const ShaderClosure *sc, const float
float npos = pos * (float)(MAXCOLORS - 1);
int ipos = float_to_int(npos);
- if (ipos < 0)
+ if(ipos < 0)
return colors[0];
- if (ipos >= (MAXCOLORS - 1))
+ if(ipos >= (MAXCOLORS - 1))
return colors[MAXCOLORS - 1];
float offset = npos - (float)ipos;
return colors[ipos] * (1.0f - offset) + colors[ipos+1] * offset;
@@ -51,10 +51,10 @@ ccl_device float3 bsdf_phong_ramp_get_color(const ShaderClosure *sc, const float
ccl_device int bsdf_phong_ramp_setup(ShaderClosure *sc)
{
- sc->data0 = max(sc->data0, 0.0f);
-
sc->type = CLOSURE_BSDF_PHONG_RAMP_ID;
- return SD_BSDF | SD_BSDF_HAS_EVAL | SD_BSDF_GLOSSY;
+ sc->data0 = max(sc->data0, 0.0f);
+ sc->data1 = 0.0f;
+ return SD_BSDF|SD_BSDF_HAS_EVAL;
}
ccl_device void bsdf_phong_ramp_blur(ShaderClosure *sc, float roughness)
@@ -67,11 +67,11 @@ ccl_device float3 bsdf_phong_ramp_eval_reflect(const ShaderClosure *sc, const fl
float cosNI = dot(sc->N, omega_in);
float cosNO = dot(sc->N, I);
- if (cosNI > 0 && cosNO > 0) {
+ if(cosNI > 0 && cosNO > 0) {
// reflect the view vector
float3 R = (2 * cosNO) * sc->N - I;
float cosRI = dot(R, omega_in);
- if (cosRI > 0) {
+ if(cosRI > 0) {
float cosp = powf(cosRI, m_exponent);
float common = 0.5f * M_1_PI_F * cosp;
float out = cosNI * (m_exponent + 2) * common;
@@ -93,7 +93,7 @@ ccl_device int bsdf_phong_ramp_sample(const ShaderClosure *sc, const float3 colo
float cosNO = dot(sc->N, I);
float m_exponent = sc->data0;
- if (cosNO > 0) {
+ if(cosNO > 0) {
// reflect the view vector
float3 R = (2 * cosNO) * sc->N - I;
@@ -111,12 +111,12 @@ ccl_device int bsdf_phong_ramp_sample(const ShaderClosure *sc, const float3 colo
*omega_in = (cosf(phi) * sinTheta) * T +
(sinf(phi) * sinTheta) * B +
( cosTheta) * R;
- if (dot(Ng, *omega_in) > 0.0f)
+ if(dot(Ng, *omega_in) > 0.0f)
{
// common terms for pdf and eval
float cosNI = dot(sc->N, *omega_in);
// make sure the direction we chose is still in the right hemisphere
- if (cosNI > 0)
+ if(cosNI > 0)
{
float cosp = powf(cosTheta, m_exponent);
float common = 0.5f * M_1_PI_F * cosp;
diff --git a/intern/cycles/kernel/closure/bsdf_reflection.h b/intern/cycles/kernel/closure/bsdf_reflection.h
index 0baccdf155c..303f4c9ce34 100644
--- a/intern/cycles/kernel/closure/bsdf_reflection.h
+++ b/intern/cycles/kernel/closure/bsdf_reflection.h
@@ -43,10 +43,6 @@ ccl_device int bsdf_reflection_setup(ShaderClosure *sc)
return SD_BSDF;
}
-ccl_device void bsdf_reflection_blur(ShaderClosure *sc, float roughness)
-{
-}
-
ccl_device float3 bsdf_reflection_eval_reflect(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
{
return make_float3(0.0f, 0.0f, 0.0f);
@@ -70,8 +66,9 @@ ccl_device int bsdf_reflection_sample(const ShaderClosure *sc, float3 Ng, float3
*domega_in_dx = 2 * dot(N, dIdx) * N - dIdx;
*domega_in_dy = 2 * dot(N, dIdy) * N - dIdy;
#endif
- *pdf = 1;
- *eval = make_float3(1, 1, 1);
+ /* Some high number for MIS. */
+ *pdf = 1e6f;
+ *eval = make_float3(1e6f, 1e6f, 1e6f);
}
}
return LABEL_REFLECT|LABEL_SINGULAR;
diff --git a/intern/cycles/kernel/closure/bsdf_refraction.h b/intern/cycles/kernel/closure/bsdf_refraction.h
index c4698b42060..c78a4b67134 100644
--- a/intern/cycles/kernel/closure/bsdf_refraction.h
+++ b/intern/cycles/kernel/closure/bsdf_refraction.h
@@ -43,10 +43,6 @@ ccl_device int bsdf_refraction_setup(ShaderClosure *sc)
return SD_BSDF;
}
-ccl_device void bsdf_refraction_blur(ShaderClosure *sc, float roughness)
-{
-}
-
ccl_device float3 bsdf_refraction_eval_reflect(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
{
return make_float3(0.0f, 0.0f, 0.0f);
@@ -67,15 +63,17 @@ ccl_device int bsdf_refraction_sample(const ShaderClosure *sc, float3 Ng, float3
float3 dRdx, dRdy, dTdx, dTdy;
#endif
bool inside;
- fresnel_dielectric(m_eta, N, I, &R, &T,
+ float fresnel;
+ fresnel = fresnel_dielectric(m_eta, N, I, &R, &T,
#ifdef __RAY_DIFFERENTIALS__
dIdx, dIdy, &dRdx, &dRdy, &dTdx, &dTdy,
#endif
&inside);
-
- if(!inside) {
- *pdf = 1.0f;
- *eval = make_float3(1.0f, 1.0f, 1.0f);
+
+ if(!inside && fresnel != 1.0f) {
+ /* Some high number for MIS. */
+ *pdf = 1e6f;
+ *eval = make_float3(1e6f, 1e6f, 1e6f);
*omega_in = T;
#ifdef __RAY_DIFFERENTIALS__
*domega_in_dx = dTdx;
diff --git a/intern/cycles/kernel/closure/bsdf_toon.h b/intern/cycles/kernel/closure/bsdf_toon.h
index 797fa4227ae..e5b6ab93a64 100644
--- a/intern/cycles/kernel/closure/bsdf_toon.h
+++ b/intern/cycles/kernel/closure/bsdf_toon.h
@@ -40,16 +40,12 @@ CCL_NAMESPACE_BEGIN
ccl_device int bsdf_diffuse_toon_setup(ShaderClosure *sc)
{
sc->type = CLOSURE_BSDF_DIFFUSE_TOON_ID;
- sc->data0 = clamp(sc->data0, 0.0f, 1.0f);
- sc->data1 = clamp(sc->data1, 0.0f, 1.0f);
+ sc->data0 = saturate(sc->data0);
+ sc->data1 = saturate(sc->data1);
return SD_BSDF|SD_BSDF_HAS_EVAL;
}
-ccl_device void bsdf_diffuse_toon_blur(ShaderClosure *sc, float roughness)
-{
-}
-
ccl_device float3 bsdf_toon_get_intensity(float max_angle, float smooth, float angle)
{
float is;
@@ -124,16 +120,12 @@ ccl_device int bsdf_diffuse_toon_sample(const ShaderClosure *sc, float3 Ng, floa
ccl_device int bsdf_glossy_toon_setup(ShaderClosure *sc)
{
sc->type = CLOSURE_BSDF_GLOSSY_TOON_ID;
- sc->data0 = clamp(sc->data0, 0.0f, 1.0f);
- sc->data1 = clamp(sc->data1, 0.0f, 1.0f);
+ sc->data0 = saturate(sc->data0);
+ sc->data1 = saturate(sc->data1);
return SD_BSDF|SD_BSDF_HAS_EVAL;
}
-ccl_device void bsdf_glossy_toon_blur(ShaderClosure *sc, float roughness)
-{
-}
-
ccl_device float3 bsdf_glossy_toon_eval_reflect(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
{
float max_angle = sc->data0*M_PI_2_F;
diff --git a/intern/cycles/kernel/closure/bsdf_transparent.h b/intern/cycles/kernel/closure/bsdf_transparent.h
index 73601d20c3a..3c2fd8004df 100644
--- a/intern/cycles/kernel/closure/bsdf_transparent.h
+++ b/intern/cycles/kernel/closure/bsdf_transparent.h
@@ -41,10 +41,6 @@ ccl_device int bsdf_transparent_setup(ShaderClosure *sc)
return SD_BSDF|SD_TRANSPARENT;
}
-ccl_device void bsdf_transparent_blur(ShaderClosure *sc, float roughness)
-{
-}
-
ccl_device float3 bsdf_transparent_eval_reflect(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
{
return make_float3(0.0f, 0.0f, 0.0f);
diff --git a/intern/cycles/kernel/closure/bsdf_westin.h b/intern/cycles/kernel/closure/bsdf_westin.h
deleted file mode 100644
index 9dc1c00bb3d..00000000000
--- a/intern/cycles/kernel/closure/bsdf_westin.h
+++ /dev/null
@@ -1,180 +0,0 @@
-/*
- * Adapted from Open Shading Language with this license:
- *
- * Copyright (c) 2009-2010 Sony Pictures Imageworks Inc., et al.
- * All Rights Reserved.
- *
- * Modifications Copyright 2011, Blender Foundation.
- *
- * 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 Sony Pictures Imageworks 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.
- */
-
-#ifndef __BSDF_WESTIN_H__
-#define __BSDF_WESTIN_H__
-
-CCL_NAMESPACE_BEGIN
-
-/* WESTIN BACKSCATTER */
-
-ccl_device int bsdf_westin_backscatter_setup(ShaderClosure *sc)
-{
- float roughness = sc->data0;
- roughness = clamp(roughness, 1e-5f, 1.0f);
- float m_invroughness = 1.0f/roughness;
-
- sc->type = CLOSURE_BSDF_WESTIN_BACKSCATTER_ID;
- sc->data0 = m_invroughness;
-
- return SD_BSDF|SD_BSDF_HAS_EVAL|SD_BSDF_GLOSSY;
-}
-
-ccl_device void bsdf_westin_backscatter_blur(ShaderClosure *sc, float roughness)
-{
- float m_invroughness = sc->data0;
- m_invroughness = min(1.0f/roughness, m_invroughness);
- sc->data0 = m_invroughness;
-}
-
-ccl_device float3 bsdf_westin_backscatter_eval_reflect(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
-{
- float m_invroughness = sc->data0;
- float3 N = sc->N;
-
- // pdf is implicitly 0 (no indirect sampling)
- float cosNO = dot(N, I);
- float cosNI = dot(N, omega_in);
- if(cosNO > 0 && cosNI > 0) {
- float cosine = dot(I, omega_in);
- *pdf = cosine > 0 ? (m_invroughness + 1) * powf(cosine, m_invroughness) : 0;
- *pdf *= 0.5f * M_1_PI_F;
- return make_float3 (*pdf, *pdf, *pdf);
- }
- return make_float3 (0, 0, 0);
-}
-
-ccl_device float3 bsdf_westin_backscatter_eval_transmit(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
-{
- return make_float3(0.0f, 0.0f, 0.0f);
-}
-
-ccl_device int bsdf_westin_backscatter_sample(const ShaderClosure *sc, float3 Ng, float3 I, float3 dIdx, float3 dIdy, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf)
-{
- float m_invroughness = sc->data0;
- float3 N = sc->N;
-
- float cosNO = dot(N, I);
- if(cosNO > 0) {
-#ifdef __RAY_DIFFERENTIALS__
- *domega_in_dx = dIdx;
- *domega_in_dy = dIdy;
-#endif
- float3 T, B;
- make_orthonormals (I, &T, &B);
- float phi = M_2PI_F * randu;
- float cosTheta = powf(randv, 1 / (m_invroughness + 1));
- float sinTheta2 = 1 - cosTheta * cosTheta;
- float sinTheta = sinTheta2 > 0 ? sqrtf(sinTheta2) : 0;
- *omega_in = (cosf(phi) * sinTheta) * T +
- (sinf(phi) * sinTheta) * B +
- (cosTheta) * I;
- if(dot(Ng, *omega_in) > 0) {
- // common terms for pdf and eval
- float cosNI = dot(N, *omega_in);
- // make sure the direction we chose is still in the right hemisphere
- if(cosNI > 0)
- {
- *pdf = 0.5f * M_1_PI_F * powf(cosTheta, m_invroughness);
- *pdf = (m_invroughness + 1) * (*pdf);
- *eval = make_float3(*pdf, *pdf, *pdf);
- }
- }
- }
- return LABEL_REFLECT|LABEL_GLOSSY;
-}
-
-/* WESTIN SHEEN */
-
-ccl_device int bsdf_westin_sheen_setup(ShaderClosure *sc)
-{
- /* float edginess = sc->data0; */
- sc->type = CLOSURE_BSDF_WESTIN_SHEEN_ID;
- return SD_BSDF|SD_BSDF_HAS_EVAL|SD_BSDF_GLOSSY;
-}
-
-ccl_device void bsdf_westin_sheen_blur(ShaderClosure *sc, float roughness)
-{
-}
-
-ccl_device float3 bsdf_westin_sheen_eval_reflect(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
-{
- float m_edginess = sc->data0;
- float3 N = sc->N;
-
- // pdf is implicitly 0 (no indirect sampling)
- float cosNO = dot(N, I);
- float cosNI = dot(N, omega_in);
- if(cosNO > 0 && cosNI > 0) {
- float sinNO2 = 1 - cosNO * cosNO;
- *pdf = cosNI * M_1_PI_F;
- float westin = sinNO2 > 0 ? powf(sinNO2, 0.5f * m_edginess) * (*pdf) : 0;
- return make_float3 (westin, westin, westin);
- }
- return make_float3 (0, 0, 0);
-}
-
-ccl_device float3 bsdf_westin_sheen_eval_transmit(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
-{
- return make_float3(0.0f, 0.0f, 0.0f);
-}
-
-ccl_device int bsdf_westin_sheen_sample(const ShaderClosure *sc, float3 Ng, float3 I, float3 dIdx, float3 dIdy, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf)
-{
- float m_edginess = sc->data0;
- float3 N = sc->N;
-
- // we are viewing the surface from the right side - send a ray out with cosine
- // distribution over the hemisphere
- sample_cos_hemisphere(N, randu, randv, omega_in, pdf);
- if(dot(Ng, *omega_in) > 0) {
- // TODO: account for sheen when sampling
- float cosNO = dot(N, I);
- float sinNO2 = 1 - cosNO * cosNO;
- float westin = sinNO2 > 0 ? powf(sinNO2, 0.5f * m_edginess) * (*pdf) : 0;
- *eval = make_float3(westin, westin, westin);
-#ifdef __RAY_DIFFERENTIALS__
- // TODO: find a better approximation for the diffuse bounce
- *domega_in_dx = (2 * dot(N, dIdx)) * N - dIdx;
- *domega_in_dy = (2 * dot(N, dIdy)) * N - dIdy;
-#endif
- }
- else {
- pdf = 0;
- }
- return LABEL_REFLECT|LABEL_DIFFUSE;
-}
-
-CCL_NAMESPACE_END
-
-#endif /* __BSDF_WESTIN_H__ */
-
diff --git a/intern/cycles/kernel/closure/bssrdf.h b/intern/cycles/kernel/closure/bssrdf.h
index 3849dedc3b6..f817dcd5f2d 100644
--- a/intern/cycles/kernel/closure/bssrdf.h
+++ b/intern/cycles/kernel/closure/bssrdf.h
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#ifndef __KERNEL_BSSRDF_H__
@@ -30,8 +30,8 @@ ccl_device int bssrdf_setup(ShaderClosure *sc, ClosureType type)
return flag;
}
else {
- sc->data1 = clamp(sc->data1, 0.0f, 1.0f); /* texture blur */
- sc->T.x = clamp(sc->T.x, 0.0f, 1.0f); /* sharpness */
+ sc->data1 = saturate(sc->data1); /* texture blur */
+ sc->T.x = saturate(sc->T.x); /* sharpness */
sc->type = type;
return SD_BSDF|SD_BSDF_HAS_EVAL|SD_BSSRDF;
@@ -157,7 +157,7 @@ ccl_device float bssrdf_cubic_quintic_root_find(float xi)
float x = 0.25f;
int i;
- for (i = 0; i < max_iteration_count; i++) {
+ for(i = 0; i < max_iteration_count; i++) {
float x2 = x*x;
float x3 = x2*x;
float nx = (1.0f - x);
@@ -168,7 +168,7 @@ ccl_device float bssrdf_cubic_quintic_root_find(float xi)
if(fabsf(f) < tolerance || f_ == 0.0f)
break;
- x = clamp(x - f/f_, 0.0f, 1.0f);
+ x = saturate(x - f/f_);
}
return x;
diff --git a/intern/cycles/kernel/closure/volume.h b/intern/cycles/kernel/closure/volume.h
index 058c4b8408f..4d71ba50ec3 100644
--- a/intern/cycles/kernel/closure/volume.h
+++ b/intern/cycles/kernel/closure/volume.h
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#ifndef __VOLUME_H__
@@ -26,9 +26,6 @@ CCL_NAMESPACE_BEGIN
* uniform sphere. g=0 uniform diffuse-like, g=1 close to sharp single ray. */
ccl_device float single_peaked_henyey_greenstein(float cos_theta, float g)
{
- if(fabsf(g) < 1e-3f)
- return M_1_PI_F * 0.25f;
-
return ((1.0f - g * g) / safe_powf(1.0f + g * g - 2.0f * g * cos_theta, 1.5f)) * (M_1_PI_F * 0.25f);
};
@@ -39,7 +36,7 @@ ccl_device int volume_henyey_greenstein_setup(ShaderClosure *sc)
/* clamp anisotropy to avoid delta function */
sc->data0 = signf(sc->data0) * min(fabsf(sc->data0), 1.0f - 1e-3f);
- return SD_SCATTER|SD_PHASE_HAS_EVAL;
+ return SD_SCATTER;
}
ccl_device float3 volume_henyey_greenstein_eval_phase(const ShaderClosure *sc, const float3 I, float3 omega_in, float *pdf)
@@ -47,9 +44,13 @@ ccl_device float3 volume_henyey_greenstein_eval_phase(const ShaderClosure *sc, c
float g = sc->data0;
/* note that I points towards the viewer */
- float cos_theta = dot(-I, omega_in);
-
- *pdf = single_peaked_henyey_greenstein(cos_theta, g);
+ if(fabsf(g) < 1e-3f) {
+ *pdf = M_1_PI_F * 0.25f;
+ }
+ else {
+ float cos_theta = dot(-I, omega_in);
+ *pdf = single_peaked_henyey_greenstein(cos_theta, g);
+ }
return make_float3(*pdf, *pdf, *pdf);
}
@@ -63,10 +64,12 @@ ccl_device int volume_henyey_greenstein_sample(const ShaderClosure *sc, float3 I
/* match pdf for small g */
if(fabsf(g) < 1e-3f) {
cos_theta = (1.0f - 2.0f * randu);
+ *pdf = M_1_PI_F * 0.25f;
}
else {
float k = (1.0f - g * g) / (1.0f - g + 2.0f * g * randu);
cos_theta = (1.0f + g * g - k * k) / (2.0f * g);
+ *pdf = single_peaked_henyey_greenstein(cos_theta, g);
}
float sin_theta = safe_sqrtf(1.0f - cos_theta * cos_theta);
@@ -80,7 +83,6 @@ ccl_device int volume_henyey_greenstein_sample(const ShaderClosure *sc, float3 I
make_orthonormals(-I, &T, &B);
*omega_in = sin_theta * cos_phi * T + sin_theta * sin_phi * B + cos_theta * (-I);
- *pdf = single_peaked_henyey_greenstein(cos_theta, g);
*eval = make_float3(*pdf, *pdf, *pdf); /* perfect importance sampling */
#ifdef __RAY_DIFFERENTIALS__
@@ -105,18 +107,9 @@ ccl_device int volume_absorption_setup(ShaderClosure *sc)
ccl_device float3 volume_phase_eval(const ShaderData *sd, const ShaderClosure *sc, float3 omega_in, float *pdf)
{
- float3 eval;
-
- switch(sc->type) {
- case CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID:
- eval = volume_henyey_greenstein_eval_phase(sc, sd->I, omega_in, pdf);
- break;
- default:
- eval = make_float3(0.0f, 0.0f, 0.0f);
- break;
- }
+ kernel_assert(sc->type == CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID);
- return eval;
+ return volume_henyey_greenstein_eval_phase(sc, sd->I, omega_in, pdf);
}
ccl_device int volume_phase_sample(const ShaderData *sd, const ShaderClosure *sc, float randu,
diff --git a/intern/cycles/kernel/geom/geom.h b/intern/cycles/kernel/geom/geom.h
index 9495a2541f9..5ab900d47aa 100644
--- a/intern/cycles/kernel/geom/geom.h
+++ b/intern/cycles/kernel/geom/geom.h
@@ -20,7 +20,11 @@
/* 64 object BVH + 64 mesh BVH + 64 object node splitting */
#define BVH_STACK_SIZE 192
+#define BVH_QSTACK_SIZE 384
#define BVH_NODE_SIZE 4
+#define BVH_NODE_LEAF_SIZE 1
+#define BVH_QNODE_SIZE 7
+#define BVH_QNODE_LEAF_SIZE 1
#define TRI_NODE_SIZE 3
/* silly workaround for float extended precision that happens when compiling
@@ -35,6 +39,7 @@
#include "geom_attribute.h"
#include "geom_object.h"
#include "geom_triangle.h"
+#include "geom_triangle_intersect.h"
#include "geom_motion_triangle.h"
#include "geom_motion_curve.h"
#include "geom_curve.h"
diff --git a/intern/cycles/kernel/geom/geom_attribute.h b/intern/cycles/kernel/geom/geom_attribute.h
index 63ce31c492f..c7364e9edac 100644
--- a/intern/cycles/kernel/geom/geom_attribute.h
+++ b/intern/cycles/kernel/geom/geom_attribute.h
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
CCL_NAMESPACE_BEGIN
@@ -29,24 +29,27 @@ CCL_NAMESPACE_BEGIN
ccl_device_inline int find_attribute(KernelGlobals *kg, const ShaderData *sd, uint id, AttributeElement *elem)
{
- if(sd->object == PRIM_NONE)
+ if(ccl_fetch(sd, object) == PRIM_NONE)
return (int)ATTR_STD_NOT_FOUND;
/* for SVM, find attribute by unique id */
- uint attr_offset = sd->object*kernel_data.bvh.attributes_map_stride;
+ uint attr_offset = ccl_fetch(sd, object)*kernel_data.bvh.attributes_map_stride;
#ifdef __HAIR__
- attr_offset = (sd->type & PRIMITIVE_ALL_CURVE)? attr_offset + ATTR_PRIM_CURVE: attr_offset;
+ attr_offset = (ccl_fetch(sd, type) & PRIMITIVE_ALL_CURVE)? attr_offset + ATTR_PRIM_CURVE: attr_offset;
#endif
uint4 attr_map = kernel_tex_fetch(__attributes_map, attr_offset);
while(attr_map.x != id) {
+ if(UNLIKELY(attr_map.x == ATTR_STD_NONE)) {
+ return ATTR_STD_NOT_FOUND;
+ }
attr_offset += ATTR_PRIM_TYPES;
attr_map = kernel_tex_fetch(__attributes_map, attr_offset);
}
*elem = (AttributeElement)attr_map.y;
- if(sd->prim == PRIM_NONE && (AttributeElement)attr_map.y != ATTR_ELEMENT_MESH)
+ if(ccl_fetch(sd, prim) == PRIM_NONE && (AttributeElement)attr_map.y != ATTR_ELEMENT_MESH)
return ATTR_STD_NOT_FOUND;
/* return result */
diff --git a/intern/cycles/kernel/geom/geom_bvh.h b/intern/cycles/kernel/geom/geom_bvh.h
index dd6abe32fec..3d0d406dd0b 100644
--- a/intern/cycles/kernel/geom/geom_bvh.h
+++ b/intern/cycles/kernel/geom/geom_bvh.h
@@ -28,6 +28,13 @@
CCL_NAMESPACE_BEGIN
+/* Don't inline intersect functions on GPU, this is faster */
+#ifdef __KERNEL_GPU__
+#define ccl_device_intersect ccl_device_noinline
+#else
+#define ccl_device_intersect ccl_device_inline
+#endif
+
/* BVH intersection function variations */
#define BVH_INSTANCING 1
@@ -35,6 +42,19 @@ CCL_NAMESPACE_BEGIN
#define BVH_HAIR 4
#define BVH_HAIR_MINIMUM_WIDTH 8
+#define BVH_NAME_JOIN(x,y) x ## _ ## y
+#define BVH_NAME_EVAL(x,y) BVH_NAME_JOIN(x,y)
+#define BVH_FUNCTION_FULL_NAME(prefix) BVH_NAME_EVAL(prefix, BVH_FUNCTION_NAME)
+
+#define BVH_FEATURE(f) (((BVH_FUNCTION_FEATURES) & (f)) != 0)
+
+/* Common QBVH functions. */
+#ifdef __QBVH__
+#include "geom_qbvh.h"
+#endif
+
+/* Regular BVH traversal */
+
#define BVH_FUNCTION_NAME bvh_intersect
#define BVH_FUNCTION_FEATURES 0
#include "geom_bvh_traversal.h"
@@ -63,6 +83,8 @@ CCL_NAMESPACE_BEGIN
#include "geom_bvh_traversal.h"
#endif
+/* Subsurface scattering BVH traversal */
+
#if defined(__SUBSURFACE__)
#define BVH_FUNCTION_NAME bvh_intersect_subsurface
#define BVH_FUNCTION_FEATURES 0
@@ -93,43 +115,108 @@ CCL_NAMESPACE_BEGIN
#include "geom_bvh_subsurface.h"
#endif
+/* Volume BVH traversal */
+
+#if defined(__VOLUME__)
+#define BVH_FUNCTION_NAME bvh_intersect_volume
+#define BVH_FUNCTION_FEATURES 0
+#include "geom_bvh_volume.h"
+#endif
+
+#if defined(__VOLUME__) && defined(__INSTANCING__)
+#define BVH_FUNCTION_NAME bvh_intersect_volume_instancing
+#define BVH_FUNCTION_FEATURES BVH_INSTANCING
+#include "geom_bvh_volume.h"
+#endif
+
+#if defined(__VOLUME__) && defined(__HAIR__)
+#define BVH_FUNCTION_NAME bvh_intersect_volume_hair
+#define BVH_FUNCTION_FEATURES BVH_INSTANCING|BVH_HAIR|BVH_HAIR_MINIMUM_WIDTH
+#include "geom_bvh_volume.h"
+#endif
+
+#if defined(__VOLUME__) && defined(__OBJECT_MOTION__)
+#define BVH_FUNCTION_NAME bvh_intersect_volume_motion
+#define BVH_FUNCTION_FEATURES BVH_INSTANCING|BVH_MOTION
+#include "geom_bvh_volume.h"
+#endif
+
+#if defined(__VOLUME__) && defined(__HAIR__) && defined(__OBJECT_MOTION__)
+#define BVH_FUNCTION_NAME bvh_intersect_volume_hair_motion
+#define BVH_FUNCTION_FEATURES BVH_INSTANCING|BVH_HAIR|BVH_HAIR_MINIMUM_WIDTH|BVH_MOTION
+#include "geom_bvh_volume.h"
+#endif
+
+/* Record all intersections - Shadow BVH traversal */
+
#if defined(__SHADOW_RECORD_ALL__)
#define BVH_FUNCTION_NAME bvh_intersect_shadow_all
#define BVH_FUNCTION_FEATURES 0
#include "geom_bvh_shadow.h"
#endif
-#if defined(__SUBSURFACE__) && defined(__INSTANCING__)
+#if defined(__SHADOW_RECORD_ALL__) && defined(__INSTANCING__)
#define BVH_FUNCTION_NAME bvh_intersect_shadow_all_instancing
#define BVH_FUNCTION_FEATURES BVH_INSTANCING
#include "geom_bvh_shadow.h"
#endif
-#if defined(__SUBSURFACE__) && defined(__HAIR__)
+#if defined(__SHADOW_RECORD_ALL__) && defined(__HAIR__)
#define BVH_FUNCTION_NAME bvh_intersect_shadow_all_hair
#define BVH_FUNCTION_FEATURES BVH_INSTANCING|BVH_HAIR
#include "geom_bvh_shadow.h"
#endif
-#if defined(__SUBSURFACE__) && defined(__OBJECT_MOTION__)
+#if defined(__SHADOW_RECORD_ALL__) && defined(__OBJECT_MOTION__)
#define BVH_FUNCTION_NAME bvh_intersect_shadow_all_motion
#define BVH_FUNCTION_FEATURES BVH_INSTANCING|BVH_MOTION
#include "geom_bvh_shadow.h"
#endif
-#if defined(__SUBSURFACE__) && defined(__HAIR__) && defined(__OBJECT_MOTION__)
+#if defined(__SHADOW_RECORD_ALL__) && defined(__HAIR__) && defined(__OBJECT_MOTION__)
#define BVH_FUNCTION_NAME bvh_intersect_shadow_all_hair_motion
#define BVH_FUNCTION_FEATURES BVH_INSTANCING|BVH_HAIR|BVH_MOTION
#include "geom_bvh_shadow.h"
#endif
-/* to work around titan bug when using arrays instead of textures */
-#if !defined(__KERNEL_CUDA__) || defined(__KERNEL_CUDA_TEX_STORAGE__)
-ccl_device_inline
-#else
-ccl_device_noinline
+/* Record all intersections - Volume BVH traversal */
+
+#if defined(__VOLUME_RECORD_ALL__)
+#define BVH_FUNCTION_NAME bvh_intersect_volume_all
+#define BVH_FUNCTION_FEATURES 0
+#include "geom_bvh_volume_all.h"
+#endif
+
+#if defined(__VOLUME_RECORD_ALL__) && defined(__INSTANCING__)
+#define BVH_FUNCTION_NAME bvh_intersect_volume_all_instancing
+#define BVH_FUNCTION_FEATURES BVH_INSTANCING
+#include "geom_bvh_volume_all.h"
+#endif
+
+#if defined(__VOLUME_RECORD_ALL__) && defined(__HAIR__)
+#define BVH_FUNCTION_NAME bvh_intersect_volume_all_hair
+#define BVH_FUNCTION_FEATURES BVH_INSTANCING|BVH_HAIR|BVH_HAIR_MINIMUM_WIDTH
+#include "geom_bvh_volume_all.h"
#endif
-bool scene_intersect(KernelGlobals *kg, const Ray *ray, const uint visibility, Intersection *isect,
+
+#if defined(__VOLUME_RECORD_ALL__) && defined(__OBJECT_MOTION__)
+#define BVH_FUNCTION_NAME bvh_intersect_volume_all_motion
+#define BVH_FUNCTION_FEATURES BVH_INSTANCING|BVH_MOTION
+#include "geom_bvh_volume_all.h"
+#endif
+
+#if defined(__VOLUME_RECORD_ALL__) && defined(__HAIR__) && defined(__OBJECT_MOTION__)
+#define BVH_FUNCTION_NAME bvh_intersect_volume_all_hair_motion
+#define BVH_FUNCTION_FEATURES BVH_INSTANCING|BVH_HAIR|BVH_HAIR_MINIMUM_WIDTH|BVH_MOTION
+#include "geom_bvh_volume_all.h"
+#endif
+
+#undef BVH_FEATURE
+#undef BVH_NAME_JOIN
+#undef BVH_NAME_EVAL
+#undef BVH_FUNCTION_FULL_NAME
+
+ccl_device_intersect bool scene_intersect(KernelGlobals *kg, const Ray *ray, const uint visibility, Intersection *isect,
uint *lcg_state, float difl, float extmax)
{
#ifdef __OBJECT_MOTION__
@@ -167,14 +254,8 @@ bool scene_intersect(KernelGlobals *kg, const Ray *ray, const uint visibility, I
#endif /* __KERNEL_CPU__ */
}
-/* to work around titan bug when using arrays instead of textures */
#ifdef __SUBSURFACE__
-#if !defined(__KERNEL_CUDA__) || defined(__KERNEL_CUDA_TEX_STORAGE__)
-ccl_device_inline
-#else
-ccl_device_noinline
-#endif
-uint scene_intersect_subsurface(KernelGlobals *kg, const Ray *ray, Intersection *isect, int subsurface_object, uint *lcg_state, int max_hits)
+ccl_device_intersect uint scene_intersect_subsurface(KernelGlobals *kg, const Ray *ray, Intersection *isect, int subsurface_object, uint *lcg_state, int max_hits)
{
#ifdef __OBJECT_MOTION__
if(kernel_data.bvh.have_motion) {
@@ -212,14 +293,8 @@ uint scene_intersect_subsurface(KernelGlobals *kg, const Ray *ray, Intersection
}
#endif
-/* to work around titan bug when using arrays instead of textures */
#ifdef __SHADOW_RECORD_ALL__
-#if !defined(__KERNEL_CUDA__) || defined(__KERNEL_CUDA_TEX_STORAGE__)
-ccl_device_inline
-#else
-ccl_device_noinline
-#endif
-uint scene_intersect_shadow_all(KernelGlobals *kg, const Ray *ray, Intersection *isect, uint max_hits, uint *num_hits)
+ccl_device_intersect bool scene_intersect_shadow_all(KernelGlobals *kg, const Ray *ray, Intersection *isect, uint max_hits, uint *num_hits)
{
#ifdef __OBJECT_MOTION__
if(kernel_data.bvh.have_motion) {
@@ -237,26 +312,87 @@ uint scene_intersect_shadow_all(KernelGlobals *kg, const Ray *ray, Intersection
return bvh_intersect_shadow_all_hair(kg, ray, isect, max_hits, num_hits);
#endif /* __HAIR__ */
-#ifdef __KERNEL_CPU__
-
#ifdef __INSTANCING__
if(kernel_data.bvh.have_instancing)
return bvh_intersect_shadow_all_instancing(kg, ray, isect, max_hits, num_hits);
#endif /* __INSTANCING__ */
return bvh_intersect_shadow_all(kg, ray, isect, max_hits, num_hits);
+}
+#endif
+
+#ifdef __VOLUME__
+ccl_device_intersect bool scene_intersect_volume(KernelGlobals *kg,
+ const Ray *ray,
+ Intersection *isect)
+{
+#ifdef __OBJECT_MOTION__
+ if(kernel_data.bvh.have_motion) {
+#ifdef __HAIR__
+ if(kernel_data.bvh.have_curves)
+ return bvh_intersect_volume_hair_motion(kg, ray, isect);
+#endif /* __HAIR__ */
+
+ return bvh_intersect_volume_motion(kg, ray, isect);
+ }
+#endif /* __OBJECT_MOTION__ */
+
+#ifdef __HAIR__
+ if(kernel_data.bvh.have_curves)
+ return bvh_intersect_volume_hair(kg, ray, isect);
+#endif /* __HAIR__ */
+
+#ifdef __KERNEL_CPU__
+
+#ifdef __INSTANCING__
+ if(kernel_data.bvh.have_instancing)
+ return bvh_intersect_volume_instancing(kg, ray, isect);
+#endif /* __INSTANCING__ */
+
+ return bvh_intersect_volume(kg, ray, isect);
#else /* __KERNEL_CPU__ */
#ifdef __INSTANCING__
- return bvh_intersect_shadow_all_instancing(kg, ray, isect, max_hits, num_hits);
+ return bvh_intersect_volume_instancing(kg, ray, isect);
#else
- return bvh_intersect_shadow_all(kg, ray, isect, max_hits, num_hits);
+ return bvh_intersect_volume(kg, ray, isect);
#endif /* __INSTANCING__ */
#endif /* __KERNEL_CPU__ */
}
#endif
+#ifdef __VOLUME_RECORD_ALL__
+ccl_device_intersect uint scene_intersect_volume_all(KernelGlobals *kg,
+ const Ray *ray,
+ Intersection *isect,
+ const uint max_hits)
+{
+#ifdef __OBJECT_MOTION__
+ if(kernel_data.bvh.have_motion) {
+#ifdef __HAIR__
+ if(kernel_data.bvh.have_curves)
+ return bvh_intersect_volume_all_hair_motion(kg, ray, isect, max_hits);
+#endif /* __HAIR__ */
+
+ return bvh_intersect_volume_all_motion(kg, ray, isect, max_hits);
+ }
+#endif /* __OBJECT_MOTION__ */
+
+#ifdef __HAIR__
+ if(kernel_data.bvh.have_curves)
+ return bvh_intersect_volume_all_hair(kg, ray, isect, max_hits);
+#endif /* __HAIR__ */
+
+#ifdef __INSTANCING__
+ if(kernel_data.bvh.have_instancing)
+ return bvh_intersect_volume_all_instancing(kg, ray, isect, max_hits);
+#endif /* __INSTANCING__ */
+
+ return bvh_intersect_volume_all(kg, ray, isect, max_hits);
+}
+#endif
+
/* Ray offset to avoid self intersection.
*
@@ -311,5 +447,21 @@ ccl_device_inline float3 ray_offset(float3 P, float3 Ng)
#endif
}
+#if defined(__SHADOW_RECORD_ALL__) || defined (__VOLUME_RECORD_ALL__)
+/* ToDo: Move to another file? */
+ccl_device int intersections_compare(const void *a, const void *b)
+{
+ const Intersection *isect_a = (const Intersection*)a;
+ const Intersection *isect_b = (const Intersection*)b;
+
+ if(isect_a->t < isect_b->t)
+ return -1;
+ else if(isect_a->t > isect_b->t)
+ return 1;
+ else
+ return 0;
+}
+#endif
+
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/geom/geom_bvh_shadow.h b/intern/cycles/kernel/geom/geom_bvh_shadow.h
index aee4097d77e..e4cba99dc96 100644
--- a/intern/cycles/kernel/geom/geom_bvh_shadow.h
+++ b/intern/cycles/kernel/geom/geom_bvh_shadow.h
@@ -17,6 +17,10 @@
* limitations under the License.
*/
+#ifdef __QBVH__
+#include "geom_qbvh_shadow.h"
+#endif
+
/* This is a template BVH traversal function, where various features can be
* enabled/disabled. This way we can compile optimized versions for each case
* without new features slowing things down.
@@ -27,10 +31,11 @@
*
*/
-#define FEATURE(f) (((BVH_FUNCTION_FEATURES) & (f)) != 0)
-
-ccl_device bool BVH_FUNCTION_NAME
-(KernelGlobals *kg, const Ray *ray, Intersection *isect_array, const uint max_hits, uint *num_hits)
+ccl_device bool BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg,
+ const Ray *ray,
+ Intersection *isect_array,
+ const uint max_hits,
+ uint *num_hits)
{
/* todo:
* - likely and unlikely for if() statements
@@ -53,11 +58,11 @@ ccl_device bool BVH_FUNCTION_NAME
int object = OBJECT_NONE;
float isect_t = tmax;
-#if FEATURE(BVH_MOTION)
+#if BVH_FEATURE(BVH_MOTION)
Transform ob_tfm;
#endif
-#if FEATURE(BVH_INSTANCING)
+#if BVH_FEATURE(BVH_INSTANCING)
int num_hits_in_instance = 0;
#endif
@@ -81,6 +86,9 @@ ccl_device bool BVH_FUNCTION_NAME
gen_idirsplat_swap(pn, shuf_identity, shuf_swap, idir, idirsplat, shufflexyz);
#endif
+ IsectPrecalc isect_precalc;
+ triangle_intersect_precalc(dir, &isect_precalc);
+
/* traversal loop */
do {
do {
@@ -174,6 +182,7 @@ ccl_device bool BVH_FUNCTION_NAME
}
++stackPtr;
+ kernel_assert(stackPtr < BVH_STACK_SIZE);
traversalStack[stackPtr] = nodeAddrChild1;
}
else {
@@ -191,13 +200,15 @@ ccl_device bool BVH_FUNCTION_NAME
/* if node is leaf, fetch triangle list */
if(nodeAddr < 0) {
- float4 leaf = kernel_tex_fetch(__bvh_nodes, (-nodeAddr-1)*BVH_NODE_SIZE+(BVH_NODE_SIZE-1));
+ float4 leaf = kernel_tex_fetch(__bvh_leaf_nodes, (-nodeAddr-1)*BVH_NODE_LEAF_SIZE);
int primAddr = __float_as_int(leaf.x);
-#if FEATURE(BVH_INSTANCING)
+#if BVH_FEATURE(BVH_INSTANCING)
if(primAddr >= 0) {
#endif
- int primAddr2 = __float_as_int(leaf.y);
+ const int primAddr2 = __float_as_int(leaf.y);
+ const uint type = __float_as_int(leaf.w);
+ const uint p_type = type & PRIMITIVE_ALL;
/* pop */
nodeAddr = traversalStack[stackPtr];
@@ -205,25 +216,26 @@ ccl_device bool BVH_FUNCTION_NAME
/* primitive intersection */
while(primAddr < primAddr2) {
+ kernel_assert(kernel_tex_fetch(__prim_type, primAddr) == type);
+
bool hit;
- uint type = kernel_tex_fetch(__prim_type, primAddr);
/* todo: specialized intersect functions which don't fill in
* isect unless needed and check SD_HAS_TRANSPARENT_SHADOW?
* might give a few % performance improvement */
- switch(type & PRIMITIVE_ALL) {
+ switch(p_type) {
case PRIMITIVE_TRIANGLE: {
- hit = triangle_intersect(kg, isect_array, P, dir, PATH_RAY_SHADOW, object, primAddr);
+ hit = triangle_intersect(kg, &isect_precalc, isect_array, P, PATH_RAY_SHADOW, object, primAddr);
break;
}
-#if FEATURE(BVH_MOTION)
+#if BVH_FEATURE(BVH_MOTION)
case PRIMITIVE_MOTION_TRIANGLE: {
hit = motion_triangle_intersect(kg, isect_array, P, dir, ray->time, PATH_RAY_SHADOW, object, primAddr);
break;
}
#endif
-#if FEATURE(BVH_HAIR)
+#if BVH_FEATURE(BVH_HAIR)
case PRIMITIVE_CURVE:
case PRIMITIVE_MOTION_CURVE: {
if(kernel_data.curve.curveflags & CURVE_KN_INTERPOLATE)
@@ -252,7 +264,7 @@ ccl_device bool BVH_FUNCTION_NAME
if(kernel_tex_fetch(__prim_type, isect_array->prim) & PRIMITIVE_ALL_TRIANGLE)
#endif
{
- shader = kernel_tex_fetch(__tri_shader, prim);
+ shader = kernel_tex_fetch(__tri_shader, prim);
}
#ifdef __HAIR__
else {
@@ -274,7 +286,7 @@ ccl_device bool BVH_FUNCTION_NAME
/* move on to next entry in intersections array */
isect_array++;
(*num_hits)++;
-#if FEATURE(BVH_INSTANCING)
+#if BVH_FEATURE(BVH_INSTANCING)
num_hits_in_instance++;
#endif
@@ -284,52 +296,55 @@ ccl_device bool BVH_FUNCTION_NAME
primAddr++;
}
}
-#if FEATURE(BVH_INSTANCING)
+#if BVH_FEATURE(BVH_INSTANCING)
else {
/* instance push */
object = kernel_tex_fetch(__prim_object, -primAddr-1);
-#if FEATURE(BVH_MOTION)
+#if BVH_FEATURE(BVH_MOTION)
bvh_instance_motion_push(kg, object, ray, &P, &dir, &idir, &isect_t, &ob_tfm);
#else
bvh_instance_push(kg, object, ray, &P, &dir, &idir, &isect_t);
#endif
+ triangle_intersect_precalc(dir, &isect_precalc);
num_hits_in_instance = 0;
+ isect_array->t = isect_t;
#if defined(__KERNEL_SSE2__)
Psplat[0] = ssef(P.x);
Psplat[1] = ssef(P.y);
Psplat[2] = ssef(P.z);
- isect_array->t = isect_t;
tsplat = ssef(0.0f, 0.0f, -isect_t, -isect_t);
-
gen_idirsplat_swap(pn, shuf_identity, shuf_swap, idir, idirsplat, shufflexyz);
#endif
++stackPtr;
+ kernel_assert(stackPtr < BVH_STACK_SIZE);
traversalStack[stackPtr] = ENTRYPOINT_SENTINEL;
nodeAddr = kernel_tex_fetch(__object_node, object);
}
}
-#endif
+#endif /* FEATURE(BVH_INSTANCING) */
} while(nodeAddr != ENTRYPOINT_SENTINEL);
-#if FEATURE(BVH_INSTANCING)
+#if BVH_FEATURE(BVH_INSTANCING)
if(stackPtr >= 0) {
kernel_assert(object != OBJECT_NONE);
if(num_hits_in_instance) {
float t_fac;
-#if FEATURE(BVH_MOTION)
+#if BVH_FEATURE(BVH_MOTION)
bvh_instance_motion_pop_factor(kg, object, ray, &P, &dir, &idir, &t_fac, &ob_tfm);
#else
bvh_instance_pop_factor(kg, object, ray, &P, &dir, &idir, &t_fac);
#endif
+ triangle_intersect_precalc(dir, &isect_precalc);
+
/* scale isect->t to adjust for instancing */
for(int i = 0; i < num_hits_in_instance; i++)
(isect_array-i-1)->t *= t_fac;
@@ -337,22 +352,23 @@ ccl_device bool BVH_FUNCTION_NAME
else {
float ignore_t = FLT_MAX;
-#if FEATURE(BVH_MOTION)
+#if BVH_FEATURE(BVH_MOTION)
bvh_instance_motion_pop(kg, object, ray, &P, &dir, &idir, &ignore_t, &ob_tfm);
#else
bvh_instance_pop(kg, object, ray, &P, &dir, &idir, &ignore_t);
#endif
+ triangle_intersect_precalc(dir, &isect_precalc);
}
+ isect_t = tmax;
+ isect_array->t = isect_t;
+
#if defined(__KERNEL_SSE2__)
Psplat[0] = ssef(P.x);
Psplat[1] = ssef(P.y);
Psplat[2] = ssef(P.z);
- isect_t = tmax;
- isect_array->t = isect_t;
tsplat = ssef(0.0f, 0.0f, -isect_t, -isect_t);
-
gen_idirsplat_swap(pn, shuf_identity, shuf_swap, idir, idirsplat, shufflexyz);
#endif
@@ -360,13 +376,37 @@ ccl_device bool BVH_FUNCTION_NAME
nodeAddr = traversalStack[stackPtr];
--stackPtr;
}
-#endif
+#endif /* FEATURE(BVH_INSTANCING) */
} while(nodeAddr != ENTRYPOINT_SENTINEL);
return false;
}
-#undef FEATURE
+ccl_device_inline bool BVH_FUNCTION_NAME(KernelGlobals *kg,
+ const Ray *ray,
+ Intersection *isect_array,
+ const uint max_hits,
+ uint *num_hits)
+{
+#ifdef __QBVH__
+ if(kernel_data.bvh.use_qbvh) {
+ return BVH_FUNCTION_FULL_NAME(QBVH)(kg,
+ ray,
+ isect_array,
+ max_hits,
+ num_hits);
+ }
+ else
+#endif
+ {
+ kernel_assert(kernel_data.bvh.use_qbvh == false);
+ return BVH_FUNCTION_FULL_NAME(BVH)(kg,
+ ray,
+ isect_array,
+ max_hits,
+ num_hits);
+ }
+}
+
#undef BVH_FUNCTION_NAME
#undef BVH_FUNCTION_FEATURES
-
diff --git a/intern/cycles/kernel/geom/geom_bvh_subsurface.h b/intern/cycles/kernel/geom/geom_bvh_subsurface.h
index a8f57cffa78..a73139f9c88 100644
--- a/intern/cycles/kernel/geom/geom_bvh_subsurface.h
+++ b/intern/cycles/kernel/geom/geom_bvh_subsurface.h
@@ -17,6 +17,10 @@
* limitations under the License.
*/
+#ifdef __QBVH__
+#include "geom_qbvh_subsurface.h"
+#endif
+
/* This is a template BVH traversal function for subsurface scattering, where
* various features can be enabled/disabled. This way we can compile optimized
* versions for each case without new features slowing things down.
@@ -26,10 +30,12 @@
*
*/
-#define FEATURE(f) (((BVH_FUNCTION_FEATURES) & (f)) != 0)
-
-ccl_device uint BVH_FUNCTION_NAME(KernelGlobals *kg, const Ray *ray, Intersection *isect_array,
- int subsurface_object, uint *lcg_state, int max_hits)
+ccl_device uint BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg,
+ const Ray *ray,
+ Intersection *isect_array,
+ int subsurface_object,
+ uint *lcg_state,
+ int max_hits)
{
/* todo:
* - test if pushing distance on the stack helps (for non shadow rays)
@@ -54,10 +60,9 @@ ccl_device uint BVH_FUNCTION_NAME(KernelGlobals *kg, const Ray *ray, Intersectio
int object = OBJECT_NONE;
float isect_t = ray->t;
- const uint visibility = PATH_RAY_ALL_VISIBILITY;
uint num_hits = 0;
-#if FEATURE(BVH_MOTION)
+#if BVH_FEATURE(BVH_MOTION)
Transform ob_tfm;
#endif
@@ -78,6 +83,9 @@ ccl_device uint BVH_FUNCTION_NAME(KernelGlobals *kg, const Ray *ray, Intersectio
gen_idirsplat_swap(pn, shuf_identity, shuf_swap, idir, idirsplat, shufflexyz);
#endif
+ IsectPrecalc isect_precalc;
+ triangle_intersect_precalc(dir, &isect_precalc);
+
/* traversal loop */
do {
do
@@ -118,14 +126,8 @@ ccl_device uint BVH_FUNCTION_NAME(KernelGlobals *kg, const Ray *ray, Intersectio
NO_EXTENDED_PRECISION float c1max = min4(max(c1lox, c1hix), max(c1loy, c1hiy), max(c1loz, c1hiz), t);
/* decide which nodes to traverse next */
-#ifdef __VISIBILITY_FLAG__
- /* this visibility test gives a 5% performance hit, how to solve? */
- traverseChild0 = (c0max >= c0min) && (__float_as_uint(cnodes.z) & visibility);
- traverseChild1 = (c1max >= c1min) && (__float_as_uint(cnodes.w) & visibility);
-#else
traverseChild0 = (c0max >= c0min);
traverseChild1 = (c1max >= c1min);
-#endif
#else // __KERNEL_SSE2__
/* Intersect two child bounding boxes, SSE3 version adapted from Embree */
@@ -145,14 +147,8 @@ ccl_device uint BVH_FUNCTION_NAME(KernelGlobals *kg, const Ray *ray, Intersectio
const sseb lrhit = tminmax <= shuffle<2, 3, 0, 1>(tminmax);
/* decide which nodes to traverse next */
-#ifdef __VISIBILITY_FLAG__
- /* this visibility test gives a 5% performance hit, how to solve? */
- traverseChild0 = (movemask(lrhit) & 1) && (__float_as_uint(cnodes.z) & visibility);
- traverseChild1 = (movemask(lrhit) & 2) && (__float_as_uint(cnodes.w) & visibility);
-#else
traverseChild0 = (movemask(lrhit) & 1);
traverseChild1 = (movemask(lrhit) & 2);
-#endif
#endif // __KERNEL_SSE2__
nodeAddr = __float_as_int(cnodes.x);
@@ -173,6 +169,7 @@ ccl_device uint BVH_FUNCTION_NAME(KernelGlobals *kg, const Ray *ray, Intersectio
}
++stackPtr;
+ kernel_assert(stackPtr < BVH_STACK_SIZE);
traversalStack[stackPtr] = nodeAddrChild1;
}
else {
@@ -190,57 +187,64 @@ ccl_device uint BVH_FUNCTION_NAME(KernelGlobals *kg, const Ray *ray, Intersectio
/* if node is leaf, fetch triangle list */
if(nodeAddr < 0) {
- float4 leaf = kernel_tex_fetch(__bvh_nodes, (-nodeAddr-1)*BVH_NODE_SIZE+(BVH_NODE_SIZE-1));
+ float4 leaf = kernel_tex_fetch(__bvh_leaf_nodes, (-nodeAddr-1)*BVH_NODE_LEAF_SIZE);
int primAddr = __float_as_int(leaf.x);
-#if FEATURE(BVH_INSTANCING)
+#if BVH_FEATURE(BVH_INSTANCING)
if(primAddr >= 0) {
#endif
- int primAddr2 = __float_as_int(leaf.y);
+ const int primAddr2 = __float_as_int(leaf.y);
+ const uint type = __float_as_int(leaf.w);
/* pop */
nodeAddr = traversalStack[stackPtr];
--stackPtr;
/* primitive intersection */
- for(; primAddr < primAddr2; primAddr++) {
- /* only primitives from the same object */
- uint tri_object = (object == OBJECT_NONE)? kernel_tex_fetch(__prim_object, primAddr): object;
-
- if(tri_object != subsurface_object)
- continue;
-
- /* intersect ray against primitive */
- uint type = kernel_tex_fetch(__prim_type, primAddr);
-
- switch(type & PRIMITIVE_ALL) {
- case PRIMITIVE_TRIANGLE: {
- triangle_intersect_subsurface(kg, isect_array, P, dir, object, primAddr, isect_t, &num_hits, lcg_state, max_hits);
- break;
+ switch(type & PRIMITIVE_ALL) {
+ case PRIMITIVE_TRIANGLE: {
+ /* intersect ray against primitive */
+ for(; primAddr < primAddr2; primAddr++) {
+ kernel_assert(kernel_tex_fetch(__prim_type, primAddr) == type);
+ /* only primitives from the same object */
+ uint tri_object = (object == OBJECT_NONE)? kernel_tex_fetch(__prim_object, primAddr): object;
+ if(tri_object != subsurface_object)
+ continue;
+ triangle_intersect_subsurface(kg, &isect_precalc, isect_array, P, object, primAddr, isect_t, &num_hits, lcg_state, max_hits);
}
-#if FEATURE(BVH_MOTION)
- case PRIMITIVE_MOTION_TRIANGLE: {
+ break;
+ }
+#if BVH_FEATURE(BVH_MOTION)
+ case PRIMITIVE_MOTION_TRIANGLE: {
+ /* intersect ray against primitive */
+ for(; primAddr < primAddr2; primAddr++) {
+ kernel_assert(kernel_tex_fetch(__prim_type, primAddr) == type);
+ /* only primitives from the same object */
+ uint tri_object = (object == OBJECT_NONE)? kernel_tex_fetch(__prim_object, primAddr): object;
+ if(tri_object != subsurface_object)
+ continue;
motion_triangle_intersect_subsurface(kg, isect_array, P, dir, ray->time, object, primAddr, isect_t, &num_hits, lcg_state, max_hits);
- break;
}
+ break;
+ }
#endif
- default: {
- break;
- }
+ default: {
+ break;
}
}
}
-#if FEATURE(BVH_INSTANCING)
+#if BVH_FEATURE(BVH_INSTANCING)
else {
/* instance push */
if(subsurface_object == kernel_tex_fetch(__prim_object, -primAddr-1)) {
object = subsurface_object;
-#if FEATURE(BVH_MOTION)
+#if BVH_FEATURE(BVH_MOTION)
bvh_instance_motion_push(kg, object, ray, &P, &dir, &idir, &isect_t, &ob_tfm);
#else
bvh_instance_push(kg, object, ray, &P, &dir, &idir, &isect_t);
#endif
+ triangle_intersect_precalc(dir, &isect_precalc);
#if defined(__KERNEL_SSE2__)
Psplat[0] = ssef(P.x);
@@ -253,6 +257,7 @@ ccl_device uint BVH_FUNCTION_NAME(KernelGlobals *kg, const Ray *ray, Intersectio
#endif
++stackPtr;
+ kernel_assert(stackPtr < BVH_STACK_SIZE);
traversalStack[stackPtr] = ENTRYPOINT_SENTINEL;
nodeAddr = kernel_tex_fetch(__object_node, object);
@@ -264,20 +269,22 @@ ccl_device uint BVH_FUNCTION_NAME(KernelGlobals *kg, const Ray *ray, Intersectio
}
}
}
-#endif
+#endif /* FEATURE(BVH_INSTANCING) */
} while(nodeAddr != ENTRYPOINT_SENTINEL);
-#if FEATURE(BVH_INSTANCING)
+#if BVH_FEATURE(BVH_INSTANCING)
if(stackPtr >= 0) {
kernel_assert(object != OBJECT_NONE);
/* instance pop */
-#if FEATURE(BVH_MOTION)
+#if BVH_FEATURE(BVH_MOTION)
bvh_instance_motion_pop(kg, object, ray, &P, &dir, &idir, &isect_t, &ob_tfm);
#else
bvh_instance_pop(kg, object, ray, &P, &dir, &idir, &isect_t);
#endif
+ triangle_intersect_precalc(dir, &isect_precalc);
+
#if defined(__KERNEL_SSE2__)
Psplat[0] = ssef(P.x);
Psplat[1] = ssef(P.y);
@@ -292,13 +299,40 @@ ccl_device uint BVH_FUNCTION_NAME(KernelGlobals *kg, const Ray *ray, Intersectio
nodeAddr = traversalStack[stackPtr];
--stackPtr;
}
-#endif
+#endif /* FEATURE(BVH_INSTANCING) */
} while(nodeAddr != ENTRYPOINT_SENTINEL);
return num_hits;
}
-#undef FEATURE
+ccl_device_inline uint BVH_FUNCTION_NAME(KernelGlobals *kg,
+ const Ray *ray,
+ Intersection *isect_array,
+ int subsurface_object,
+ uint *lcg_state,
+ int max_hits)
+{
+#ifdef __QBVH__
+ if(kernel_data.bvh.use_qbvh) {
+ return BVH_FUNCTION_FULL_NAME(QBVH)(kg,
+ ray,
+ isect_array,
+ subsurface_object,
+ lcg_state,
+ max_hits);
+ }
+ else
+#endif
+ {
+ kernel_assert(kernel_data.bvh.use_qbvh == false);
+ return BVH_FUNCTION_FULL_NAME(BVH)(kg,
+ ray,
+ isect_array,
+ subsurface_object,
+ lcg_state,
+ max_hits);
+ }
+}
+
#undef BVH_FUNCTION_NAME
#undef BVH_FUNCTION_FEATURES
-
diff --git a/intern/cycles/kernel/geom/geom_bvh_traversal.h b/intern/cycles/kernel/geom/geom_bvh_traversal.h
index e39228c33de..73d79fd78ee 100644
--- a/intern/cycles/kernel/geom/geom_bvh_traversal.h
+++ b/intern/cycles/kernel/geom/geom_bvh_traversal.h
@@ -17,6 +17,10 @@
* limitations under the License.
*/
+#ifdef __QBVH__
+#include "geom_qbvh_traversal.h"
+#endif
+
/* This is a template BVH traversal function, where various features can be
* enabled/disabled. This way we can compile optimized versions for each case
* without new features slowing things down.
@@ -28,14 +32,16 @@
*
*/
-#define FEATURE(f) (((BVH_FUNCTION_FEATURES) & (f)) != 0)
-
-ccl_device bool BVH_FUNCTION_NAME
-(KernelGlobals *kg, const Ray *ray, Intersection *isect, const uint visibility
-#if FEATURE(BVH_HAIR_MINIMUM_WIDTH)
-, uint *lcg_state, float difl, float extmax
+ccl_device bool BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg,
+ const Ray *ray,
+ Intersection *isect,
+ const uint visibility
+#if BVH_FEATURE(BVH_HAIR_MINIMUM_WIDTH)
+ , uint *lcg_state,
+ float difl,
+ float extmax
#endif
-)
+ )
{
/* todo:
* - test if pushing distance on the stack helps (for non shadow rays)
@@ -58,15 +64,20 @@ ccl_device bool BVH_FUNCTION_NAME
float3 idir = bvh_inverse_direction(dir);
int object = OBJECT_NONE;
-#if FEATURE(BVH_MOTION)
+#if BVH_FEATURE(BVH_MOTION)
Transform ob_tfm;
#endif
isect->t = ray->t;
- isect->object = OBJECT_NONE;
- isect->prim = PRIM_NONE;
isect->u = 0.0f;
isect->v = 0.0f;
+ isect->prim = PRIM_NONE;
+ isect->object = OBJECT_NONE;
+
+#if defined(__KERNEL_DEBUG__)
+ isect->num_traversal_steps = 0;
+ isect->num_traversed_instances = 0;
+#endif
#if defined(__KERNEL_SSE2__)
const shuffle_swap_t shuf_identity = shuffle_swap_identity();
@@ -85,6 +96,9 @@ ccl_device bool BVH_FUNCTION_NAME
gen_idirsplat_swap(pn, shuf_identity, shuf_swap, idir, idirsplat, shufflexyz);
#endif
+ IsectPrecalc isect_precalc;
+ triangle_intersect_precalc(dir, &isect_precalc);
+
/* traversal loop */
do {
do {
@@ -122,7 +136,7 @@ ccl_device bool BVH_FUNCTION_NAME
NO_EXTENDED_PRECISION float c1min = max4(min(c1lox, c1hix), min(c1loy, c1hiy), min(c1loz, c1hiz), 0.0f);
NO_EXTENDED_PRECISION float c1max = min4(max(c1lox, c1hix), max(c1loy, c1hiy), max(c1loz, c1hiz), t);
-#if FEATURE(BVH_HAIR_MINIMUM_WIDTH)
+#if BVH_FEATURE(BVH_HAIR_MINIMUM_WIDTH)
if(difl != 0.0f) {
float hdiff = 1.0f + difl;
float ldiff = 1.0f - difl;
@@ -163,7 +177,7 @@ ccl_device bool BVH_FUNCTION_NAME
ssef minmax = max(max(tminmaxx, tminmaxy), max(tminmaxz, tsplat));
const ssef tminmax = minmax ^ pn;
-#if FEATURE(BVH_HAIR_MINIMUM_WIDTH)
+#if BVH_FEATURE(BVH_HAIR_MINIMUM_WIDTH)
if(difl != 0.0f) {
float4 *tminmaxview = (float4*)&tminmax;
float &c0min = tminmaxview->x, &c1min = tminmaxview->y;
@@ -213,6 +227,7 @@ ccl_device bool BVH_FUNCTION_NAME
}
++stackPtr;
+ kernel_assert(stackPtr < BVH_STACK_SIZE);
traversalStack[stackPtr] = nodeAddrChild1;
}
else {
@@ -226,80 +241,112 @@ ccl_device bool BVH_FUNCTION_NAME
--stackPtr;
}
}
+
+#if defined(__KERNEL_DEBUG__)
+ isect->num_traversal_steps++;
+#endif
}
/* if node is leaf, fetch triangle list */
if(nodeAddr < 0) {
- float4 leaf = kernel_tex_fetch(__bvh_nodes, (-nodeAddr-1)*BVH_NODE_SIZE+(BVH_NODE_SIZE-1));
+ float4 leaf = kernel_tex_fetch(__bvh_leaf_nodes, (-nodeAddr-1)*BVH_NODE_LEAF_SIZE);
int primAddr = __float_as_int(leaf.x);
-#if FEATURE(BVH_INSTANCING)
+#if BVH_FEATURE(BVH_INSTANCING)
if(primAddr >= 0) {
#endif
- int primAddr2 = __float_as_int(leaf.y);
+ const int primAddr2 = __float_as_int(leaf.y);
+ const uint type = __float_as_int(leaf.w);
/* pop */
nodeAddr = traversalStack[stackPtr];
--stackPtr;
/* primitive intersection */
- while(primAddr < primAddr2) {
- bool hit;
- uint type = kernel_tex_fetch(__prim_type, primAddr);
-
- switch(type & PRIMITIVE_ALL) {
- case PRIMITIVE_TRIANGLE: {
- hit = triangle_intersect(kg, isect, P, dir, visibility, object, primAddr);
- break;
+ switch(type & PRIMITIVE_ALL) {
+ case PRIMITIVE_TRIANGLE: {
+ for(; primAddr < primAddr2; primAddr++) {
+#if defined(__KERNEL_DEBUG__)
+ isect->num_traversal_steps++;
+#endif
+ kernel_assert(kernel_tex_fetch(__prim_type, primAddr) == type);
+ if(triangle_intersect(kg, &isect_precalc, isect, P, visibility, object, primAddr)) {
+ /* shadow ray early termination */
+#if defined(__KERNEL_SSE2__)
+ if(visibility == PATH_RAY_SHADOW_OPAQUE)
+ return true;
+ tsplat = ssef(0.0f, 0.0f, -isect->t, -isect->t);
+#else
+ if(visibility == PATH_RAY_SHADOW_OPAQUE)
+ return true;
+#endif
+ }
}
-#if FEATURE(BVH_MOTION)
- case PRIMITIVE_MOTION_TRIANGLE: {
- hit = motion_triangle_intersect(kg, isect, P, dir, ray->time, visibility, object, primAddr);
- break;
+ break;
+ }
+#if BVH_FEATURE(BVH_MOTION)
+ case PRIMITIVE_MOTION_TRIANGLE: {
+ for(; primAddr < primAddr2; primAddr++) {
+#if defined(__KERNEL_DEBUG__)
+ isect->num_traversal_steps++;
+#endif
+ kernel_assert(kernel_tex_fetch(__prim_type, primAddr) == type);
+ if(motion_triangle_intersect(kg, isect, P, dir, ray->time, visibility, object, primAddr)) {
+ /* shadow ray early termination */
+#if defined(__KERNEL_SSE2__)
+ if(visibility == PATH_RAY_SHADOW_OPAQUE)
+ return true;
+ tsplat = ssef(0.0f, 0.0f, -isect->t, -isect->t);
+#else
+ if(visibility == PATH_RAY_SHADOW_OPAQUE)
+ return true;
+#endif
+ }
}
+ break;
+ }
+#endif /* BVH_FEATURE(BVH_MOTION) */
+#if BVH_FEATURE(BVH_HAIR)
+ case PRIMITIVE_CURVE:
+ case PRIMITIVE_MOTION_CURVE: {
+ for(; primAddr < primAddr2; primAddr++) {
+#if defined(__KERNEL_DEBUG__)
+ isect->num_traversal_steps++;
#endif
-#if FEATURE(BVH_HAIR)
- case PRIMITIVE_CURVE:
- case PRIMITIVE_MOTION_CURVE: {
- if(kernel_data.curve.curveflags & CURVE_KN_INTERPOLATE)
+ kernel_assert(kernel_tex_fetch(__prim_type, primAddr) == type);
+ bool hit;
+ if(kernel_data.curve.curveflags & CURVE_KN_INTERPOLATE)
hit = bvh_cardinal_curve_intersect(kg, isect, P, dir, visibility, object, primAddr, ray->time, type, lcg_state, difl, extmax);
else
hit = bvh_curve_intersect(kg, isect, P, dir, visibility, object, primAddr, ray->time, type, lcg_state, difl, extmax);
- break;
- }
-#endif
- default: {
- hit = false;
- break;
- }
- }
-
- /* shadow ray early termination */
+ if(hit) {
+ /* shadow ray early termination */
#if defined(__KERNEL_SSE2__)
- if(hit) {
- if(visibility == PATH_RAY_SHADOW_OPAQUE)
- return true;
-
- tsplat = ssef(0.0f, 0.0f, -isect->t, -isect->t);
- }
+ if(visibility == PATH_RAY_SHADOW_OPAQUE)
+ return true;
+ tsplat = ssef(0.0f, 0.0f, -isect->t, -isect->t);
#else
- if(hit && visibility == PATH_RAY_SHADOW_OPAQUE)
- return true;
+ if(visibility == PATH_RAY_SHADOW_OPAQUE)
+ return true;
#endif
-
- primAddr++;
+ }
+ }
+ break;
+ }
+#endif /* BVH_FEATURE(BVH_HAIR) */
}
}
-#if FEATURE(BVH_INSTANCING)
+#if BVH_FEATURE(BVH_INSTANCING)
else {
/* instance push */
object = kernel_tex_fetch(__prim_object, -primAddr-1);
-#if FEATURE(BVH_MOTION)
+#if BVH_FEATURE(BVH_MOTION)
bvh_instance_motion_push(kg, object, ray, &P, &dir, &idir, &isect->t, &ob_tfm);
#else
bvh_instance_push(kg, object, ray, &P, &dir, &idir, &isect->t);
#endif
+ triangle_intersect_precalc(dir, &isect_precalc);
#if defined(__KERNEL_SSE2__)
Psplat[0] = ssef(P.x);
@@ -312,24 +359,30 @@ ccl_device bool BVH_FUNCTION_NAME
#endif
++stackPtr;
+ kernel_assert(stackPtr < BVH_STACK_SIZE);
traversalStack[stackPtr] = ENTRYPOINT_SENTINEL;
nodeAddr = kernel_tex_fetch(__object_node, object);
+
+#if defined(__KERNEL_DEBUG__)
+ isect->num_traversed_instances++;
+#endif
}
}
-#endif
+#endif /* FEATURE(BVH_INSTANCING) */
} while(nodeAddr != ENTRYPOINT_SENTINEL);
-#if FEATURE(BVH_INSTANCING)
+#if BVH_FEATURE(BVH_INSTANCING)
if(stackPtr >= 0) {
kernel_assert(object != OBJECT_NONE);
/* instance pop */
-#if FEATURE(BVH_MOTION)
+#if BVH_FEATURE(BVH_MOTION)
bvh_instance_motion_pop(kg, object, ray, &P, &dir, &idir, &isect->t, &ob_tfm);
#else
bvh_instance_pop(kg, object, ray, &P, &dir, &idir, &isect->t);
#endif
+ triangle_intersect_precalc(dir, &isect_precalc);
#if defined(__KERNEL_SSE2__)
Psplat[0] = ssef(P.x);
@@ -345,13 +398,52 @@ ccl_device bool BVH_FUNCTION_NAME
nodeAddr = traversalStack[stackPtr];
--stackPtr;
}
-#endif
+#endif /* FEATURE(BVH_INSTANCING) */
} while(nodeAddr != ENTRYPOINT_SENTINEL);
return (isect->prim != PRIM_NONE);
}
-#undef FEATURE
+ccl_device_inline bool BVH_FUNCTION_NAME(KernelGlobals *kg,
+ const Ray *ray,
+ Intersection *isect,
+ const uint visibility
+#if BVH_FEATURE(BVH_HAIR_MINIMUM_WIDTH)
+ , uint *lcg_state,
+ float difl,
+ float extmax
+#endif
+ )
+{
+#ifdef __QBVH__
+ if(kernel_data.bvh.use_qbvh) {
+ return BVH_FUNCTION_FULL_NAME(QBVH)(kg,
+ ray,
+ isect,
+ visibility
+#if BVH_FEATURE(BVH_HAIR_MINIMUM_WIDTH)
+ , lcg_state,
+ difl,
+ extmax
+#endif
+ );
+ }
+ else
+#endif
+ {
+ kernel_assert(kernel_data.bvh.use_qbvh == false);
+ return BVH_FUNCTION_FULL_NAME(BVH)(kg,
+ ray,
+ isect,
+ visibility
+#if BVH_FEATURE(BVH_HAIR_MINIMUM_WIDTH)
+ , lcg_state,
+ difl,
+ extmax
+#endif
+ );
+ }
+}
+
#undef BVH_FUNCTION_NAME
#undef BVH_FUNCTION_FEATURES
-
diff --git a/intern/cycles/kernel/geom/geom_bvh_volume.h b/intern/cycles/kernel/geom/geom_bvh_volume.h
new file mode 100644
index 00000000000..41c784869f2
--- /dev/null
+++ b/intern/cycles/kernel/geom/geom_bvh_volume.h
@@ -0,0 +1,358 @@
+/*
+ * Adapted from code Copyright 2009-2010 NVIDIA Corporation,
+ * and code copyright 2009-2012 Intel Corporation
+ *
+ * Modifications Copyright 2011-2014, Blender Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifdef __QBVH__
+#include "geom_qbvh_volume.h"
+#endif
+
+/* This is a template BVH traversal function for volumes, where
+ * various features can be enabled/disabled. This way we can compile optimized
+ * versions for each case without new features slowing things down.
+ *
+ * BVH_INSTANCING: object instancing
+ * BVH_HAIR: hair curve rendering
+ * BVH_MOTION: motion blur rendering
+ *
+ */
+
+ccl_device bool BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg,
+ const Ray *ray,
+ Intersection *isect)
+{
+ /* todo:
+ * - test if pushing distance on the stack helps (for non shadow rays)
+ * - separate version for shadow rays
+ * - likely and unlikely for if() statements
+ * - test restrict attribute for pointers
+ */
+
+ /* traversal stack in CUDA thread-local memory */
+ int traversalStack[BVH_STACK_SIZE];
+ traversalStack[0] = ENTRYPOINT_SENTINEL;
+
+ /* traversal variables in registers */
+ int stackPtr = 0;
+ int nodeAddr = kernel_data.bvh.root;
+
+ /* ray parameters in registers */
+ float3 P = ray->P;
+ float3 dir = bvh_clamp_direction(ray->D);
+ float3 idir = bvh_inverse_direction(dir);
+ int object = OBJECT_NONE;
+
+ const uint visibility = PATH_RAY_ALL_VISIBILITY;
+
+#if BVH_FEATURE(BVH_MOTION)
+ Transform ob_tfm;
+#endif
+
+ isect->t = ray->t;
+ isect->u = 0.0f;
+ isect->v = 0.0f;
+ isect->prim = PRIM_NONE;
+ isect->object = OBJECT_NONE;
+
+#if defined(__KERNEL_SSE2__)
+ const shuffle_swap_t shuf_identity = shuffle_swap_identity();
+ const shuffle_swap_t shuf_swap = shuffle_swap_swap();
+
+ const ssef pn = cast(ssei(0, 0, 0x80000000, 0x80000000));
+ ssef Psplat[3], idirsplat[3];
+ shuffle_swap_t shufflexyz[3];
+
+ Psplat[0] = ssef(P.x);
+ Psplat[1] = ssef(P.y);
+ Psplat[2] = ssef(P.z);
+
+ ssef tsplat(0.0f, 0.0f, -isect->t, -isect->t);
+
+ gen_idirsplat_swap(pn, shuf_identity, shuf_swap, idir, idirsplat, shufflexyz);
+#endif
+
+ IsectPrecalc isect_precalc;
+ triangle_intersect_precalc(dir, &isect_precalc);
+
+ /* traversal loop */
+ do {
+ do {
+ /* traverse internal nodes */
+ while(nodeAddr >= 0 && nodeAddr != ENTRYPOINT_SENTINEL) {
+ bool traverseChild0, traverseChild1;
+ int nodeAddrChild1;
+
+#if !defined(__KERNEL_SSE2__)
+ /* Intersect two child bounding boxes, non-SSE version */
+ float t = isect->t;
+
+ /* fetch node data */
+ float4 node0 = kernel_tex_fetch(__bvh_nodes, nodeAddr*BVH_NODE_SIZE+0);
+ float4 node1 = kernel_tex_fetch(__bvh_nodes, nodeAddr*BVH_NODE_SIZE+1);
+ float4 node2 = kernel_tex_fetch(__bvh_nodes, nodeAddr*BVH_NODE_SIZE+2);
+ float4 cnodes = kernel_tex_fetch(__bvh_nodes, nodeAddr*BVH_NODE_SIZE+3);
+
+ /* intersect ray against child nodes */
+ NO_EXTENDED_PRECISION float c0lox = (node0.x - P.x) * idir.x;
+ NO_EXTENDED_PRECISION float c0hix = (node0.z - P.x) * idir.x;
+ NO_EXTENDED_PRECISION float c0loy = (node1.x - P.y) * idir.y;
+ NO_EXTENDED_PRECISION float c0hiy = (node1.z - P.y) * idir.y;
+ NO_EXTENDED_PRECISION float c0loz = (node2.x - P.z) * idir.z;
+ NO_EXTENDED_PRECISION float c0hiz = (node2.z - P.z) * idir.z;
+ NO_EXTENDED_PRECISION float c0min = max4(min(c0lox, c0hix), min(c0loy, c0hiy), min(c0loz, c0hiz), 0.0f);
+ NO_EXTENDED_PRECISION float c0max = min4(max(c0lox, c0hix), max(c0loy, c0hiy), max(c0loz, c0hiz), t);
+
+ NO_EXTENDED_PRECISION float c1lox = (node0.y - P.x) * idir.x;
+ NO_EXTENDED_PRECISION float c1hix = (node0.w - P.x) * idir.x;
+ NO_EXTENDED_PRECISION float c1loy = (node1.y - P.y) * idir.y;
+ NO_EXTENDED_PRECISION float c1hiy = (node1.w - P.y) * idir.y;
+ NO_EXTENDED_PRECISION float c1loz = (node2.y - P.z) * idir.z;
+ NO_EXTENDED_PRECISION float c1hiz = (node2.w - P.z) * idir.z;
+ NO_EXTENDED_PRECISION float c1min = max4(min(c1lox, c1hix), min(c1loy, c1hiy), min(c1loz, c1hiz), 0.0f);
+ NO_EXTENDED_PRECISION float c1max = min4(max(c1lox, c1hix), max(c1loy, c1hiy), max(c1loz, c1hiz), t);
+
+ /* decide which nodes to traverse next */
+ traverseChild0 = (c0max >= c0min);
+ traverseChild1 = (c1max >= c1min);
+
+#else // __KERNEL_SSE2__
+ /* Intersect two child bounding boxes, SSE3 version adapted from Embree */
+
+ /* fetch node data */
+ const ssef *bvh_nodes = (ssef*)kg->__bvh_nodes.data + nodeAddr*BVH_NODE_SIZE;
+ const float4 cnodes = ((float4*)bvh_nodes)[3];
+
+ /* intersect ray against child nodes */
+ const ssef tminmaxx = (shuffle_swap(bvh_nodes[0], shufflexyz[0]) - Psplat[0]) * idirsplat[0];
+ const ssef tminmaxy = (shuffle_swap(bvh_nodes[1], shufflexyz[1]) - Psplat[1]) * idirsplat[1];
+ const ssef tminmaxz = (shuffle_swap(bvh_nodes[2], shufflexyz[2]) - Psplat[2]) * idirsplat[2];
+
+ /* calculate { c0min, c1min, -c0max, -c1max} */
+ ssef minmax = max(max(tminmaxx, tminmaxy), max(tminmaxz, tsplat));
+ const ssef tminmax = minmax ^ pn;
+
+ const sseb lrhit = tminmax <= shuffle<2, 3, 0, 1>(tminmax);
+
+ /* decide which nodes to traverse next */
+ traverseChild0 = (movemask(lrhit) & 1);
+ traverseChild1 = (movemask(lrhit) & 2);
+#endif // __KERNEL_SSE2__
+
+ nodeAddr = __float_as_int(cnodes.x);
+ nodeAddrChild1 = __float_as_int(cnodes.y);
+
+ if(traverseChild0 && traverseChild1) {
+ /* both children were intersected, push the farther one */
+#if !defined(__KERNEL_SSE2__)
+ bool closestChild1 = (c1min < c0min);
+#else
+ bool closestChild1 = tminmax[1] < tminmax[0];
+#endif
+
+ if(closestChild1) {
+ int tmp = nodeAddr;
+ nodeAddr = nodeAddrChild1;
+ nodeAddrChild1 = tmp;
+ }
+
+ ++stackPtr;
+ kernel_assert(stackPtr < BVH_STACK_SIZE);
+ traversalStack[stackPtr] = nodeAddrChild1;
+ }
+ else {
+ /* one child was intersected */
+ if(traverseChild1) {
+ nodeAddr = nodeAddrChild1;
+ }
+ else if(!traverseChild0) {
+ /* neither child was intersected */
+ nodeAddr = traversalStack[stackPtr];
+ --stackPtr;
+ }
+ }
+ }
+
+ /* if node is leaf, fetch triangle list */
+ if(nodeAddr < 0) {
+ float4 leaf = kernel_tex_fetch(__bvh_leaf_nodes, (-nodeAddr-1)*BVH_NODE_LEAF_SIZE);
+ int primAddr = __float_as_int(leaf.x);
+
+#if BVH_FEATURE(BVH_INSTANCING)
+ if(primAddr >= 0) {
+#endif
+ const int primAddr2 = __float_as_int(leaf.y);
+ const uint type = __float_as_int(leaf.w);
+
+ /* pop */
+ nodeAddr = traversalStack[stackPtr];
+ --stackPtr;
+
+ /* primitive intersection */
+ switch(type & PRIMITIVE_ALL) {
+ case PRIMITIVE_TRIANGLE: {
+ /* intersect ray against primitive */
+ for(; primAddr < primAddr2; primAddr++) {
+ kernel_assert(kernel_tex_fetch(__prim_type, primAddr) == type);
+ /* only primitives from volume object */
+ uint tri_object = (object == OBJECT_NONE)? kernel_tex_fetch(__prim_object, primAddr): object;
+ int object_flag = kernel_tex_fetch(__object_flag, tri_object);
+ if((object_flag & SD_OBJECT_HAS_VOLUME) == 0) {
+ continue;
+ }
+ triangle_intersect(kg, &isect_precalc, isect, P, visibility, object, primAddr);
+ }
+ break;
+ }
+#if BVH_FEATURE(BVH_MOTION)
+ case PRIMITIVE_MOTION_TRIANGLE: {
+ /* intersect ray against primitive */
+ for(; primAddr < primAddr2; primAddr++) {
+ kernel_assert(kernel_tex_fetch(__prim_type, primAddr) == type);
+ /* only primitives from volume object */
+ uint tri_object = (object == OBJECT_NONE)? kernel_tex_fetch(__prim_object, primAddr): object;
+ int object_flag = kernel_tex_fetch(__object_flag, tri_object);
+ if((object_flag & SD_OBJECT_HAS_VOLUME) == 0) {
+ continue;
+ }
+ motion_triangle_intersect(kg, isect, P, dir, ray->time, visibility, object, primAddr);
+ }
+ break;
+ }
+#endif
+#if BVH_FEATURE(BVH_HAIR)
+ case PRIMITIVE_CURVE:
+ case PRIMITIVE_MOTION_CURVE: {
+ /* intersect ray against primitive */
+ for(; primAddr < primAddr2; primAddr++) {
+ kernel_assert(kernel_tex_fetch(__prim_type, primAddr) == type);
+ /* only primitives from volume object */
+ uint tri_object = (object == OBJECT_NONE)? kernel_tex_fetch(__prim_object, primAddr): object;
+ int object_flag = kernel_tex_fetch(__object_flag, tri_object);
+ if((object_flag & SD_OBJECT_HAS_VOLUME) == 0) {
+ continue;
+ }
+ if(kernel_data.curve.curveflags & CURVE_KN_INTERPOLATE)
+ bvh_cardinal_curve_intersect(kg, isect, P, dir, visibility, object, primAddr, ray->time, type, NULL, 0, 0);
+ else
+ bvh_curve_intersect(kg, isect, P, dir, visibility, object, primAddr, ray->time, type, NULL, 0, 0);
+ }
+ break;
+ }
+#endif
+ default: {
+ break;
+ }
+ }
+ }
+#if BVH_FEATURE(BVH_INSTANCING)
+ else {
+ /* instance push */
+ object = kernel_tex_fetch(__prim_object, -primAddr-1);
+ int object_flag = kernel_tex_fetch(__object_flag, object);
+
+ if(object_flag & SD_OBJECT_HAS_VOLUME) {
+
+#if BVH_FEATURE(BVH_MOTION)
+ bvh_instance_motion_push(kg, object, ray, &P, &dir, &idir, &isect->t, &ob_tfm);
+#else
+ bvh_instance_push(kg, object, ray, &P, &dir, &idir, &isect->t);
+#endif
+
+ triangle_intersect_precalc(dir, &isect_precalc);
+
+#if defined(__KERNEL_SSE2__)
+ Psplat[0] = ssef(P.x);
+ Psplat[1] = ssef(P.y);
+ Psplat[2] = ssef(P.z);
+
+ tsplat = ssef(0.0f, 0.0f, -isect->t, -isect->t);
+
+ gen_idirsplat_swap(pn, shuf_identity, shuf_swap, idir, idirsplat, shufflexyz);
+#endif
+
+ ++stackPtr;
+ kernel_assert(stackPtr < BVH_STACK_SIZE);
+ traversalStack[stackPtr] = ENTRYPOINT_SENTINEL;
+
+ nodeAddr = kernel_tex_fetch(__object_node, object);
+ }
+ else {
+ /* pop */
+ object = OBJECT_NONE;
+ nodeAddr = traversalStack[stackPtr];
+ --stackPtr;
+ }
+ }
+ }
+#endif /* FEATURE(BVH_INSTANCING) */
+ } while(nodeAddr != ENTRYPOINT_SENTINEL);
+
+#if BVH_FEATURE(BVH_INSTANCING)
+ if(stackPtr >= 0) {
+ kernel_assert(object != OBJECT_NONE);
+
+ /* instance pop */
+#if BVH_FEATURE(BVH_MOTION)
+ bvh_instance_motion_pop(kg, object, ray, &P, &dir, &idir, &isect->t, &ob_tfm);
+#else
+ bvh_instance_pop(kg, object, ray, &P, &dir, &idir, &isect->t);
+#endif
+
+ triangle_intersect_precalc(dir, &isect_precalc);
+
+#if defined(__KERNEL_SSE2__)
+ Psplat[0] = ssef(P.x);
+ Psplat[1] = ssef(P.y);
+ Psplat[2] = ssef(P.z);
+
+ tsplat = ssef(0.0f, 0.0f, -isect->t, -isect->t);
+
+ gen_idirsplat_swap(pn, shuf_identity, shuf_swap, idir, idirsplat, shufflexyz);
+#endif
+
+ object = OBJECT_NONE;
+ nodeAddr = traversalStack[stackPtr];
+ --stackPtr;
+ }
+#endif /* FEATURE(BVH_MOTION) */
+ } while(nodeAddr != ENTRYPOINT_SENTINEL);
+
+ return (isect->prim != PRIM_NONE);
+}
+
+ccl_device_inline bool BVH_FUNCTION_NAME(KernelGlobals *kg,
+ const Ray *ray,
+ Intersection *isect)
+{
+#ifdef __QBVH__
+ if(kernel_data.bvh.use_qbvh) {
+ return BVH_FUNCTION_FULL_NAME(QBVH)(kg,
+ ray,
+ isect);
+ }
+ else
+#endif
+ {
+ kernel_assert(kernel_data.bvh.use_qbvh == false);
+ return BVH_FUNCTION_FULL_NAME(BVH)(kg,
+ ray,
+ isect);
+ }
+}
+
+#undef BVH_FUNCTION_NAME
+#undef BVH_FUNCTION_FEATURES
diff --git a/intern/cycles/kernel/geom/geom_bvh_volume_all.h b/intern/cycles/kernel/geom/geom_bvh_volume_all.h
new file mode 100644
index 00000000000..b6db36f4b17
--- /dev/null
+++ b/intern/cycles/kernel/geom/geom_bvh_volume_all.h
@@ -0,0 +1,454 @@
+/*
+ * Adapted from code Copyright 2009-2010 NVIDIA Corporation,
+ * and code copyright 2009-2012 Intel Corporation
+ *
+ * Modifications Copyright 2011-2014, Blender Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifdef __QBVH__
+#include "geom_qbvh_volume_all.h"
+#endif
+
+/* This is a template BVH traversal function for volumes, where
+ * various features can be enabled/disabled. This way we can compile optimized
+ * versions for each case without new features slowing things down.
+ *
+ * BVH_INSTANCING: object instancing
+ * BVH_HAIR: hair curve rendering
+ * BVH_MOTION: motion blur rendering
+ *
+ */
+
+ccl_device uint BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg,
+ const Ray *ray,
+ Intersection *isect_array,
+ const uint max_hits)
+{
+ /* todo:
+ * - test if pushing distance on the stack helps (for non shadow rays)
+ * - separate version for shadow rays
+ * - likely and unlikely for if() statements
+ * - test restrict attribute for pointers
+ */
+
+ /* traversal stack in CUDA thread-local memory */
+ int traversalStack[BVH_STACK_SIZE];
+ traversalStack[0] = ENTRYPOINT_SENTINEL;
+
+ /* traversal variables in registers */
+ int stackPtr = 0;
+ int nodeAddr = kernel_data.bvh.root;
+
+ /* ray parameters in registers */
+ const float tmax = ray->t;
+ float3 P = ray->P;
+ float3 dir = bvh_clamp_direction(ray->D);
+ float3 idir = bvh_inverse_direction(dir);
+ int object = OBJECT_NONE;
+ float isect_t = tmax;
+
+ const uint visibility = PATH_RAY_ALL_VISIBILITY;
+
+#if BVH_FEATURE(BVH_MOTION)
+ Transform ob_tfm;
+#endif
+
+#if BVH_FEATURE(BVH_INSTANCING)
+ int num_hits_in_instance = 0;
+#endif
+
+ uint num_hits = 0;
+ isect_array->t = tmax;
+
+#if defined(__KERNEL_SSE2__)
+ const shuffle_swap_t shuf_identity = shuffle_swap_identity();
+ const shuffle_swap_t shuf_swap = shuffle_swap_swap();
+
+ const ssef pn = cast(ssei(0, 0, 0x80000000, 0x80000000));
+ ssef Psplat[3], idirsplat[3];
+ shuffle_swap_t shufflexyz[3];
+
+ Psplat[0] = ssef(P.x);
+ Psplat[1] = ssef(P.y);
+ Psplat[2] = ssef(P.z);
+
+ ssef tsplat(0.0f, 0.0f, -isect_t, -isect_t);
+
+ gen_idirsplat_swap(pn, shuf_identity, shuf_swap, idir, idirsplat, shufflexyz);
+#endif
+
+ IsectPrecalc isect_precalc;
+ triangle_intersect_precalc(dir, &isect_precalc);
+
+ /* traversal loop */
+ do {
+ do {
+ /* traverse internal nodes */
+ while(nodeAddr >= 0 && nodeAddr != ENTRYPOINT_SENTINEL) {
+ bool traverseChild0, traverseChild1;
+ int nodeAddrChild1;
+
+#if !defined(__KERNEL_SSE2__)
+ /* Intersect two child bounding boxes, non-SSE version */
+ float t = isect_array->t;
+
+ /* fetch node data */
+ float4 node0 = kernel_tex_fetch(__bvh_nodes, nodeAddr*BVH_NODE_SIZE+0);
+ float4 node1 = kernel_tex_fetch(__bvh_nodes, nodeAddr*BVH_NODE_SIZE+1);
+ float4 node2 = kernel_tex_fetch(__bvh_nodes, nodeAddr*BVH_NODE_SIZE+2);
+ float4 cnodes = kernel_tex_fetch(__bvh_nodes, nodeAddr*BVH_NODE_SIZE+3);
+
+ /* intersect ray against child nodes */
+ NO_EXTENDED_PRECISION float c0lox = (node0.x - P.x) * idir.x;
+ NO_EXTENDED_PRECISION float c0hix = (node0.z - P.x) * idir.x;
+ NO_EXTENDED_PRECISION float c0loy = (node1.x - P.y) * idir.y;
+ NO_EXTENDED_PRECISION float c0hiy = (node1.z - P.y) * idir.y;
+ NO_EXTENDED_PRECISION float c0loz = (node2.x - P.z) * idir.z;
+ NO_EXTENDED_PRECISION float c0hiz = (node2.z - P.z) * idir.z;
+ NO_EXTENDED_PRECISION float c0min = max4(min(c0lox, c0hix), min(c0loy, c0hiy), min(c0loz, c0hiz), 0.0f);
+ NO_EXTENDED_PRECISION float c0max = min4(max(c0lox, c0hix), max(c0loy, c0hiy), max(c0loz, c0hiz), t);
+
+ NO_EXTENDED_PRECISION float c1lox = (node0.y - P.x) * idir.x;
+ NO_EXTENDED_PRECISION float c1hix = (node0.w - P.x) * idir.x;
+ NO_EXTENDED_PRECISION float c1loy = (node1.y - P.y) * idir.y;
+ NO_EXTENDED_PRECISION float c1hiy = (node1.w - P.y) * idir.y;
+ NO_EXTENDED_PRECISION float c1loz = (node2.y - P.z) * idir.z;
+ NO_EXTENDED_PRECISION float c1hiz = (node2.w - P.z) * idir.z;
+ NO_EXTENDED_PRECISION float c1min = max4(min(c1lox, c1hix), min(c1loy, c1hiy), min(c1loz, c1hiz), 0.0f);
+ NO_EXTENDED_PRECISION float c1max = min4(max(c1lox, c1hix), max(c1loy, c1hiy), max(c1loz, c1hiz), t);
+
+ /* decide which nodes to traverse next */
+ traverseChild0 = (c0max >= c0min);
+ traverseChild1 = (c1max >= c1min);
+
+#else // __KERNEL_SSE2__
+ /* Intersect two child bounding boxes, SSE3 version adapted from Embree */
+
+ /* fetch node data */
+ const ssef *bvh_nodes = (ssef*)kg->__bvh_nodes.data + nodeAddr*BVH_NODE_SIZE;
+ const float4 cnodes = ((float4*)bvh_nodes)[3];
+
+ /* intersect ray against child nodes */
+ const ssef tminmaxx = (shuffle_swap(bvh_nodes[0], shufflexyz[0]) - Psplat[0]) * idirsplat[0];
+ const ssef tminmaxy = (shuffle_swap(bvh_nodes[1], shufflexyz[1]) - Psplat[1]) * idirsplat[1];
+ const ssef tminmaxz = (shuffle_swap(bvh_nodes[2], shufflexyz[2]) - Psplat[2]) * idirsplat[2];
+
+ /* calculate { c0min, c1min, -c0max, -c1max} */
+ ssef minmax = max(max(tminmaxx, tminmaxy), max(tminmaxz, tsplat));
+ const ssef tminmax = minmax ^ pn;
+
+ const sseb lrhit = tminmax <= shuffle<2, 3, 0, 1>(tminmax);
+
+ /* decide which nodes to traverse next */
+ traverseChild0 = (movemask(lrhit) & 1);
+ traverseChild1 = (movemask(lrhit) & 2);
+#endif // __KERNEL_SSE2__
+
+ nodeAddr = __float_as_int(cnodes.x);
+ nodeAddrChild1 = __float_as_int(cnodes.y);
+
+ if(traverseChild0 && traverseChild1) {
+ /* both children were intersected, push the farther one */
+#if !defined(__KERNEL_SSE2__)
+ bool closestChild1 = (c1min < c0min);
+#else
+ bool closestChild1 = tminmax[1] < tminmax[0];
+#endif
+
+ if(closestChild1) {
+ int tmp = nodeAddr;
+ nodeAddr = nodeAddrChild1;
+ nodeAddrChild1 = tmp;
+ }
+
+ ++stackPtr;
+ kernel_assert(stackPtr < BVH_STACK_SIZE);
+ traversalStack[stackPtr] = nodeAddrChild1;
+ }
+ else {
+ /* one child was intersected */
+ if(traverseChild1) {
+ nodeAddr = nodeAddrChild1;
+ }
+ else if(!traverseChild0) {
+ /* neither child was intersected */
+ nodeAddr = traversalStack[stackPtr];
+ --stackPtr;
+ }
+ }
+ }
+
+ /* if node is leaf, fetch triangle list */
+ if(nodeAddr < 0) {
+ float4 leaf = kernel_tex_fetch(__bvh_leaf_nodes, (-nodeAddr-1)*BVH_NODE_LEAF_SIZE);
+ int primAddr = __float_as_int(leaf.x);
+
+#if BVH_FEATURE(BVH_INSTANCING)
+ if(primAddr >= 0) {
+#endif
+ const int primAddr2 = __float_as_int(leaf.y);
+ const uint type = __float_as_int(leaf.w);
+ bool hit;
+
+ /* pop */
+ nodeAddr = traversalStack[stackPtr];
+ --stackPtr;
+
+ /* primitive intersection */
+ switch(type & PRIMITIVE_ALL) {
+ case PRIMITIVE_TRIANGLE: {
+ /* intersect ray against primitive */
+ for(; primAddr < primAddr2; primAddr++) {
+ kernel_assert(kernel_tex_fetch(__prim_type, primAddr) == type);
+ /* only primitives from volume object */
+ uint tri_object = (object == OBJECT_NONE)? kernel_tex_fetch(__prim_object, primAddr): object;
+ int object_flag = kernel_tex_fetch(__object_flag, tri_object);
+ if((object_flag & SD_OBJECT_HAS_VOLUME) == 0) {
+ continue;
+ }
+ hit = triangle_intersect(kg, &isect_precalc, isect_array, P, visibility, object, primAddr);
+ if(hit) {
+ /* Move on to next entry in intersections array. */
+ isect_array++;
+ num_hits++;
+#if BVH_FEATURE(BVH_INSTANCING)
+ num_hits_in_instance++;
+#endif
+ isect_array->t = isect_t;
+ if(num_hits == max_hits) {
+#if BVH_FEATURE(BVH_INSTANCING)
+#if BVH_FEATURE(BVH_MOTION)
+ float t_fac = len(transform_direction(&ob_tfm, 1.0f/idir));
+#else
+ Transform tfm = object_fetch_transform(kg, object, OBJECT_TRANSFORM);
+ float t_fac = len(transform_direction(&tfm, 1.0f/idir));
+#endif
+ for(int i = 0; i < num_hits_in_instance; i++) {
+ (isect_array-i-1)->t *= t_fac;
+ }
+#endif /* BVH_FEATURE(BVH_INSTANCING) */
+ return num_hits;
+ }
+ }
+ }
+ break;
+ }
+#if BVH_FEATURE(BVH_MOTION)
+ case PRIMITIVE_MOTION_TRIANGLE: {
+ /* intersect ray against primitive */
+ for(; primAddr < primAddr2; primAddr++) {
+ kernel_assert(kernel_tex_fetch(__prim_type, primAddr) == type);
+ /* only primitives from volume object */
+ uint tri_object = (object == OBJECT_NONE)? kernel_tex_fetch(__prim_object, primAddr): object;
+ int object_flag = kernel_tex_fetch(__object_flag, tri_object);
+ if((object_flag & SD_OBJECT_HAS_VOLUME) == 0) {
+ continue;
+ }
+ hit = motion_triangle_intersect(kg, isect_array, P, dir, ray->time, visibility, object, primAddr);
+ if(hit) {
+ /* Move on to next entry in intersections array. */
+ isect_array++;
+ num_hits++;
+#if BVH_FEATURE(BVH_INSTANCING)
+ num_hits_in_instance++;
+#endif
+ isect_array->t = isect_t;
+ if(num_hits == max_hits) {
+#if BVH_FEATURE(BVH_INSTANCING)
+# if BVH_FEATURE(BVH_MOTION)
+ float t_fac = len(transform_direction(&ob_tfm, 1.0f/idir));
+# else
+ Transform tfm = object_fetch_transform(kg, object, OBJECT_TRANSFORM);
+ float t_fac = len(transform_direction(&tfm, 1.0f/idir));
+#endif
+ for(int i = 0; i < num_hits_in_instance; i++) {
+ (isect_array-i-1)->t *= t_fac;
+ }
+#endif /* BVH_FEATURE(BVH_INSTANCING) */
+ return num_hits;
+ }
+ }
+ }
+ break;
+ }
+#endif
+#if BVH_FEATURE(BVH_HAIR)
+ case PRIMITIVE_CURVE:
+ case PRIMITIVE_MOTION_CURVE: {
+ /* intersect ray against primitive */
+ for(; primAddr < primAddr2; primAddr++) {
+ kernel_assert(kernel_tex_fetch(__prim_type, primAddr) == type);
+ /* only primitives from volume object */
+ uint tri_object = (object == OBJECT_NONE)? kernel_tex_fetch(__prim_object, primAddr): object;
+ int object_flag = kernel_tex_fetch(__object_flag, tri_object);
+ if((object_flag & SD_OBJECT_HAS_VOLUME) == 0) {
+ continue;
+ }
+ if(kernel_data.curve.curveflags & CURVE_KN_INTERPOLATE)
+ hit = bvh_cardinal_curve_intersect(kg, isect_array, P, dir, visibility, object, primAddr, ray->time, type, NULL, 0, 0);
+ else
+ hit = bvh_curve_intersect(kg, isect_array, P, dir, visibility, object, primAddr, ray->time, type, NULL, 0, 0);
+ if(hit) {
+ /* Move on to next entry in intersections array. */
+ isect_array++;
+ num_hits++;
+#if BVH_FEATURE(BVH_INSTANCING)
+ num_hits_in_instance++;
+#endif
+ isect_array->t = isect_t;
+ if(num_hits == max_hits) {
+#if BVH_FEATURE(BVH_INSTANCING)
+# if BVH_FEATURE(BVH_MOTION)
+ float t_fac = len(transform_direction(&ob_tfm, 1.0f/idir));
+# else
+ Transform tfm = object_fetch_transform(kg, object, OBJECT_TRANSFORM);
+ float t_fac = len(transform_direction(&tfm, 1.0f/idir));
+#endif
+ for(int i = 0; i < num_hits_in_instance; i++) {
+ (isect_array-i-1)->t *= t_fac;
+ }
+#endif /* BVH_FEATURE(BVH_INSTANCING) */
+ return num_hits;
+ }
+ }
+ }
+ break;
+ }
+#endif
+ default: {
+ break;
+ }
+ }
+ }
+#if BVH_FEATURE(BVH_INSTANCING)
+ else {
+ /* instance push */
+ object = kernel_tex_fetch(__prim_object, -primAddr-1);
+ int object_flag = kernel_tex_fetch(__object_flag, object);
+
+ if(object_flag & SD_OBJECT_HAS_VOLUME) {
+
+#if BVH_FEATURE(BVH_MOTION)
+ bvh_instance_motion_push(kg, object, ray, &P, &dir, &idir, &isect_t, &ob_tfm);
+#else
+ bvh_instance_push(kg, object, ray, &P, &dir, &idir, &isect_t);
+#endif
+
+ triangle_intersect_precalc(dir, &isect_precalc);
+ num_hits_in_instance = 0;
+ isect_array->t = isect_t;
+
+#if defined(__KERNEL_SSE2__)
+ Psplat[0] = ssef(P.x);
+ Psplat[1] = ssef(P.y);
+ Psplat[2] = ssef(P.z);
+
+ tsplat = ssef(0.0f, 0.0f, -isect_t, -isect_t);
+
+ gen_idirsplat_swap(pn, shuf_identity, shuf_swap, idir, idirsplat, shufflexyz);
+#endif
+
+ ++stackPtr;
+ kernel_assert(stackPtr < BVH_STACK_SIZE);
+ traversalStack[stackPtr] = ENTRYPOINT_SENTINEL;
+
+ nodeAddr = kernel_tex_fetch(__object_node, object);
+ }
+ else {
+ /* pop */
+ object = OBJECT_NONE;
+ nodeAddr = traversalStack[stackPtr];
+ --stackPtr;
+ }
+ }
+ }
+#endif /* FEATURE(BVH_INSTANCING) */
+ } while(nodeAddr != ENTRYPOINT_SENTINEL);
+
+#if BVH_FEATURE(BVH_INSTANCING)
+ if(stackPtr >= 0) {
+ kernel_assert(object != OBJECT_NONE);
+
+ if(num_hits_in_instance) {
+ float t_fac;
+#if BVH_FEATURE(BVH_MOTION)
+ bvh_instance_motion_pop_factor(kg, object, ray, &P, &dir, &idir, &t_fac, &ob_tfm);
+#else
+ bvh_instance_pop_factor(kg, object, ray, &P, &dir, &idir, &t_fac);
+#endif
+ triangle_intersect_precalc(dir, &isect_precalc);
+ /* Scale isect->t to adjust for instancing. */
+ for(int i = 0; i < num_hits_in_instance; i++) {
+ (isect_array-i-1)->t *= t_fac;
+ }
+ }
+ else {
+ float ignore_t = FLT_MAX;
+#if BVH_FEATURE(BVH_MOTION)
+ bvh_instance_motion_pop(kg, object, ray, &P, &dir, &idir, &ignore_t, &ob_tfm);
+#else
+ bvh_instance_pop(kg, object, ray, &P, &dir, &idir, &ignore_t);
+#endif
+ triangle_intersect_precalc(dir, &isect_precalc);
+ }
+
+ isect_t = tmax;
+ isect_array->t = isect_t;
+
+#if defined(__KERNEL_SSE2__)
+ Psplat[0] = ssef(P.x);
+ Psplat[1] = ssef(P.y);
+ Psplat[2] = ssef(P.z);
+
+ tsplat = ssef(0.0f, 0.0f, -isect_t, -isect_t);
+
+ gen_idirsplat_swap(pn, shuf_identity, shuf_swap, idir, idirsplat, shufflexyz);
+#endif
+
+ object = OBJECT_NONE;
+ nodeAddr = traversalStack[stackPtr];
+ --stackPtr;
+ }
+#endif /* FEATURE(BVH_MOTION) */
+ } while(nodeAddr != ENTRYPOINT_SENTINEL);
+
+ return num_hits;
+}
+
+ccl_device_inline uint BVH_FUNCTION_NAME(KernelGlobals *kg,
+ const Ray *ray,
+ Intersection *isect_array,
+ const uint max_hits)
+{
+#ifdef __QBVH__
+ if(kernel_data.bvh.use_qbvh) {
+ return BVH_FUNCTION_FULL_NAME(QBVH)(kg,
+ ray,
+ isect_array,
+ max_hits);
+ }
+ else
+#endif
+ {
+ kernel_assert(kernel_data.bvh.use_qbvh == false);
+ return BVH_FUNCTION_FULL_NAME(BVH)(kg,
+ ray,
+ isect_array,
+ max_hits);
+ }
+}
+
+#undef BVH_FUNCTION_NAME
+#undef BVH_FUNCTION_FEATURES
diff --git a/intern/cycles/kernel/geom/geom_curve.h b/intern/cycles/kernel/geom/geom_curve.h
index c4e9e2ababe..9653ad8f1bb 100644
--- a/intern/cycles/kernel/geom/geom_curve.h
+++ b/intern/cycles/kernel/geom/geom_curve.h
@@ -32,22 +32,22 @@ ccl_device float curve_attribute_float(KernelGlobals *kg, const ShaderData *sd,
if(dy) *dy = 0.0f;
#endif
- return kernel_tex_fetch(__attributes_float, offset + sd->prim);
+ return kernel_tex_fetch(__attributes_float, offset + ccl_fetch(sd, prim));
}
else if(elem == ATTR_ELEMENT_CURVE_KEY || elem == ATTR_ELEMENT_CURVE_KEY_MOTION) {
- float4 curvedata = kernel_tex_fetch(__curves, sd->prim);
- int k0 = __float_as_int(curvedata.x) + PRIMITIVE_UNPACK_SEGMENT(sd->type);
+ float4 curvedata = kernel_tex_fetch(__curves, ccl_fetch(sd, prim));
+ int k0 = __float_as_int(curvedata.x) + PRIMITIVE_UNPACK_SEGMENT(ccl_fetch(sd, type));
int k1 = k0 + 1;
float f0 = kernel_tex_fetch(__attributes_float, offset + k0);
float f1 = kernel_tex_fetch(__attributes_float, offset + k1);
#ifdef __RAY_DIFFERENTIALS__
- if(dx) *dx = sd->du.dx*(f1 - f0);
+ if(dx) *dx = ccl_fetch(sd, du).dx*(f1 - f0);
if(dy) *dy = 0.0f;
#endif
- return (1.0f - sd->u)*f0 + sd->u*f1;
+ return (1.0f - ccl_fetch(sd, u))*f0 + ccl_fetch(sd, u)*f1;
}
else {
#ifdef __RAY_DIFFERENTIALS__
@@ -71,22 +71,22 @@ ccl_device float3 curve_attribute_float3(KernelGlobals *kg, const ShaderData *sd
if(dy) *dy = make_float3(0.0f, 0.0f, 0.0f);
#endif
- return float4_to_float3(kernel_tex_fetch(__attributes_float3, offset + sd->prim));
+ return float4_to_float3(kernel_tex_fetch(__attributes_float3, offset + ccl_fetch(sd, prim)));
}
else if(elem == ATTR_ELEMENT_CURVE_KEY || elem == ATTR_ELEMENT_CURVE_KEY_MOTION) {
- float4 curvedata = kernel_tex_fetch(__curves, sd->prim);
- int k0 = __float_as_int(curvedata.x) + PRIMITIVE_UNPACK_SEGMENT(sd->type);
+ float4 curvedata = kernel_tex_fetch(__curves, ccl_fetch(sd, prim));
+ int k0 = __float_as_int(curvedata.x) + PRIMITIVE_UNPACK_SEGMENT(ccl_fetch(sd, type));
int k1 = k0 + 1;
float3 f0 = float4_to_float3(kernel_tex_fetch(__attributes_float3, offset + k0));
float3 f1 = float4_to_float3(kernel_tex_fetch(__attributes_float3, offset + k1));
#ifdef __RAY_DIFFERENTIALS__
- if(dx) *dx = sd->du.dx*(f1 - f0);
+ if(dx) *dx = ccl_fetch(sd, du).dx*(f1 - f0);
if(dy) *dy = make_float3(0.0f, 0.0f, 0.0f);
#endif
- return (1.0f - sd->u)*f0 + sd->u*f1;
+ return (1.0f - ccl_fetch(sd, u))*f0 + ccl_fetch(sd, u)*f1;
}
else {
#ifdef __RAY_DIFFERENTIALS__
@@ -104,22 +104,22 @@ ccl_device float curve_thickness(KernelGlobals *kg, ShaderData *sd)
{
float r = 0.0f;
- if(sd->type & PRIMITIVE_ALL_CURVE) {
- float4 curvedata = kernel_tex_fetch(__curves, sd->prim);
- int k0 = __float_as_int(curvedata.x) + PRIMITIVE_UNPACK_SEGMENT(sd->type);
+ if(ccl_fetch(sd, type) & PRIMITIVE_ALL_CURVE) {
+ float4 curvedata = kernel_tex_fetch(__curves, ccl_fetch(sd, prim));
+ int k0 = __float_as_int(curvedata.x) + PRIMITIVE_UNPACK_SEGMENT(ccl_fetch(sd, type));
int k1 = k0 + 1;
float4 P_curve[2];
- if(sd->type & PRIMITIVE_CURVE) {
+ if(ccl_fetch(sd, type) & PRIMITIVE_CURVE) {
P_curve[0]= kernel_tex_fetch(__curve_keys, k0);
P_curve[1]= kernel_tex_fetch(__curve_keys, k1);
}
else {
- motion_curve_keys(kg, sd->object, sd->prim, sd->time, k0, k1, P_curve);
+ motion_curve_keys(kg, ccl_fetch(sd, object), ccl_fetch(sd, prim), ccl_fetch(sd, time), k0, k1, P_curve);
}
- r = (P_curve[1].w - P_curve[0].w) * sd->u + P_curve[0].w;
+ r = (P_curve[1].w - P_curve[0].w) * ccl_fetch(sd, u) + P_curve[0].w;
}
return r*2.0f;
@@ -130,8 +130,8 @@ ccl_device float curve_thickness(KernelGlobals *kg, ShaderData *sd)
ccl_device float3 curve_motion_center_location(KernelGlobals *kg, ShaderData *sd)
{
- float4 curvedata = kernel_tex_fetch(__curves, sd->prim);
- int k0 = __float_as_int(curvedata.x) + PRIMITIVE_UNPACK_SEGMENT(sd->type);
+ float4 curvedata = kernel_tex_fetch(__curves, ccl_fetch(sd, prim));
+ int k0 = __float_as_int(curvedata.x) + PRIMITIVE_UNPACK_SEGMENT(ccl_fetch(sd, type));
int k1 = k0 + 1;
float4 P_curve[2];
@@ -139,7 +139,7 @@ ccl_device float3 curve_motion_center_location(KernelGlobals *kg, ShaderData *sd
P_curve[0]= kernel_tex_fetch(__curve_keys, k0);
P_curve[1]= kernel_tex_fetch(__curve_keys, k1);
- return float4_to_float3(P_curve[1]) * sd->u + float4_to_float3(P_curve[0]) * (1.0f - sd->u);
+ return float4_to_float3(P_curve[1]) * ccl_fetch(sd, u) + float4_to_float3(P_curve[0]) * (1.0f - ccl_fetch(sd, u));
}
/* Curve tangent normal */
@@ -148,14 +148,14 @@ ccl_device float3 curve_tangent_normal(KernelGlobals *kg, ShaderData *sd)
{
float3 tgN = make_float3(0.0f,0.0f,0.0f);
- if(sd->type & PRIMITIVE_ALL_CURVE) {
+ if(ccl_fetch(sd, type) & PRIMITIVE_ALL_CURVE) {
- tgN = -(-sd->I - sd->dPdu * (dot(sd->dPdu,-sd->I) / len_squared(sd->dPdu)));
+ tgN = -(-ccl_fetch(sd, I) - ccl_fetch(sd, dPdu) * (dot(ccl_fetch(sd, dPdu),-ccl_fetch(sd, I)) / len_squared(ccl_fetch(sd, dPdu))));
tgN = normalize(tgN);
/* need to find suitable scaled gd for corrected normal */
#if 0
- tgN = normalize(tgN - gd * sd->dPdu);
+ tgN = normalize(tgN - gd * ccl_fetch(sd, dPdu));
#endif
}
@@ -442,12 +442,12 @@ ccl_device_inline bool bvh_cardinal_curve_intersect(KernelGlobals *kg, Intersect
float r_ext = mw_extension + r_curr;
float coverage = 1.0f;
- if (bminz - r_curr > isect->t || bmaxz + r_curr < epsilon || bminx > r_ext|| bmaxx < -r_ext|| bminy > r_ext|| bmaxy < -r_ext) {
+ if(bminz - r_curr > isect->t || bmaxz + r_curr < epsilon || bminx > r_ext|| bmaxx < -r_ext|| bminy > r_ext|| bmaxy < -r_ext) {
/* the bounding box does not overlap the square centered at O */
tree += level;
level = tree & -tree;
}
- else if (level == 1) {
+ else if(level == 1) {
/* the maximum recursion depth is reached.
* check if dP0.(Q-P0)>=0 and dPn.(Pn-Q)>=0.
@@ -459,13 +459,13 @@ ccl_device_inline bool bvh_cardinal_curve_intersect(KernelGlobals *kg, Intersect
if(flags & CURVE_KN_RIBBONS) {
float3 tg = (p_en - p_st);
float w = tg.x * tg.x + tg.y * tg.y;
- if (w == 0) {
+ if(w == 0) {
tree++;
level = tree & -tree;
continue;
}
w = -(p_st.x * tg.x + p_st.y * tg.y) / w;
- w = clamp((float)w, 0.0f, 1.0f);
+ w = saturate(w);
/* compute u on the curve segment */
u = i_st * (1 - w) + i_en * w;
@@ -474,17 +474,17 @@ ccl_device_inline bool bvh_cardinal_curve_intersect(KernelGlobals *kg, Intersect
float3 p_curr = ((curve_coef[3] * u + curve_coef[2]) * u + curve_coef[1]) * u + curve_coef[0];
float3 dp_st = (3 * curve_coef[3] * i_st + 2 * curve_coef[2]) * i_st + curve_coef[1];
- if (dot(tg, dp_st)< 0)
+ if(dot(tg, dp_st)< 0)
dp_st *= -1;
- if (dot(dp_st, -p_st) + p_curr.z * dp_st.z < 0) {
+ if(dot(dp_st, -p_st) + p_curr.z * dp_st.z < 0) {
tree++;
level = tree & -tree;
continue;
}
float3 dp_en = (3 * curve_coef[3] * i_en + 2 * curve_coef[2]) * i_en + curve_coef[1];
- if (dot(tg, dp_en) < 0)
+ if(dot(tg, dp_en) < 0)
dp_en *= -1;
- if (dot(dp_en, p_en) - p_curr.z * dp_en.z < 0) {
+ if(dot(dp_en, p_en) - p_curr.z * dp_en.z < 0) {
tree++;
level = tree & -tree;
continue;
@@ -500,13 +500,13 @@ ccl_device_inline bool bvh_cardinal_curve_intersect(KernelGlobals *kg, Intersect
float d0 = d - r_curr;
float d1 = d + r_curr;
float inv_mw_extension = 1.0f/mw_extension;
- if (d0 >= 0)
+ if(d0 >= 0)
coverage = (min(d1 * inv_mw_extension, 1.0f) - min(d0 * inv_mw_extension, 1.0f)) * 0.5f;
else // inside
coverage = (min(d1 * inv_mw_extension, 1.0f) + min(-d0 * inv_mw_extension, 1.0f)) * 0.5f;
}
- if (p_curr.x * p_curr.x + p_curr.y * p_curr.y >= r_ext * r_ext || p_curr.z <= epsilon || isect->t < p_curr.z) {
+ if(p_curr.x * p_curr.x + p_curr.y * p_curr.y >= r_ext * r_ext || p_curr.z <= epsilon || isect->t < p_curr.z) {
tree++;
level = tree & -tree;
continue;
@@ -548,7 +548,7 @@ ccl_device_inline bool bvh_cardinal_curve_intersect(KernelGlobals *kg, Intersect
float tb = 2*(tdif.z - tg.z*(tdifz + gd*(tdifz*gd + or1)));
float tc = dot(tdif,tdif) - tdifz * tdifz * (1 + gd*gd) - or1*or1 - 2*or1*tdifz*gd;
float td = tb*tb - 4*cyla*tc;
- if (td < 0.0f) {
+ if(td < 0.0f) {
tree++;
level = tree & -tree;
continue;
@@ -559,10 +559,10 @@ ccl_device_inline bool bvh_cardinal_curve_intersect(KernelGlobals *kg, Intersect
t = tcentre + correction;
float3 dp_st = (3 * curve_coef[3] * i_st + 2 * curve_coef[2]) * i_st + curve_coef[1];
- if (dot(tg, dp_st)< 0)
+ if(dot(tg, dp_st)< 0)
dp_st *= -1;
float3 dp_en = (3 * curve_coef[3] * i_en + 2 * curve_coef[2]) * i_en + curve_coef[1];
- if (dot(tg, dp_en) < 0)
+ if(dot(tg, dp_en) < 0)
dp_en *= -1;
if(flags & CURVE_KN_BACKFACING && (dot(dp_st, -p_st) + t * dp_st.z < 0 || dot(dp_en, p_en) - t * dp_en.z < 0 || isect->t < t || t <= 0.0f)) {
@@ -570,14 +570,14 @@ ccl_device_inline bool bvh_cardinal_curve_intersect(KernelGlobals *kg, Intersect
t = tcentre + correction;
}
- if (dot(dp_st, -p_st) + t * dp_st.z < 0 || dot(dp_en, p_en) - t * dp_en.z < 0 || isect->t < t || t <= 0.0f) {
+ if(dot(dp_st, -p_st) + t * dp_st.z < 0 || dot(dp_en, p_en) - t * dp_en.z < 0 || isect->t < t || t <= 0.0f) {
tree++;
level = tree & -tree;
continue;
}
float w = (zcentre + (tg.z * correction)) * invl;
- w = clamp((float)w, 0.0f, 1.0f);
+ w = saturate(w);
/* compute u on the curve segment */
u = i_st * (1 - w) + i_en * w;
@@ -600,12 +600,12 @@ ccl_device_inline bool bvh_cardinal_curve_intersect(KernelGlobals *kg, Intersect
#endif
{
/* record intersection */
+ isect->t = t;
+ isect->u = u;
+ isect->v = gd;
isect->prim = curveAddr;
isect->object = object;
isect->type = type;
- isect->u = u;
- isect->v = gd;
- isect->t = t;
hit = true;
}
@@ -646,8 +646,8 @@ ccl_device_inline bool bvh_curve_intersect(KernelGlobals *kg, Intersection *isec
float4 P_curve[2];
if(type & PRIMITIVE_CURVE) {
- P_curve[0]= kernel_tex_fetch(__curve_keys, k0);
- P_curve[1]= kernel_tex_fetch(__curve_keys, k1);
+ P_curve[0] = kernel_tex_fetch(__curve_keys, k0);
+ P_curve[1] = kernel_tex_fetch(__curve_keys, k1);
}
else {
int fobject = (object == OBJECT_NONE)? kernel_tex_fetch(__prim_object, curveAddr): object;
@@ -709,7 +709,7 @@ ccl_device_inline bool bvh_curve_intersect(KernelGlobals *kg, Intersection *isec
const ssef sphere_dif1 = (dif + dif_second) * 0.5f;
const ssef dir = load4f(direction);
const ssef sphere_b_tmp = dot3_splat(dir, sphere_dif1);
- const ssef sphere_dif2 = nmsub(sphere_b_tmp, dir, sphere_dif1);
+ const ssef sphere_dif2 = nmadd(sphere_b_tmp, dir, sphere_dif1);
#endif
float mr = max(r1, r2);
@@ -777,7 +777,7 @@ ccl_device_inline bool bvh_curve_intersect(KernelGlobals *kg, Intersection *isec
float tc = dot3(tdif, tdif) - tdifz*tdifz - tdifma*tdifma;
float td = tb*tb - 4*a*tc;
- if (td < 0.0f)
+ if(td < 0.0f)
return false;
float rootd = 0.0f;
@@ -818,7 +818,7 @@ ccl_device_inline bool bvh_curve_intersect(KernelGlobals *kg, Intersection *isec
if(t > 0.0f && t < isect->t && z >= 0 && z <= l) {
- if (flags & CURVE_KN_ENCLOSEFILTER) {
+ if(flags & CURVE_KN_ENCLOSEFILTER) {
float enc_ratio = 1.01f;
if((difz > -r1 * enc_ratio) && (dot3(dif_second, tg) < r2 * enc_ratio)) {
float a2 = 1.0f - (dirz*dirz*(1 + gd*gd*enc_ratio*enc_ratio));
@@ -835,12 +835,12 @@ ccl_device_inline bool bvh_curve_intersect(KernelGlobals *kg, Intersection *isec
#endif
{
/* record intersection */
+ isect->t = t;
+ isect->u = z*invl;
+ isect->v = gd;
isect->prim = curveAddr;
isect->object = object;
isect->type = type;
- isect->u = z*invl;
- isect->v = gd;
- isect->t = t;
return true;
}
@@ -890,7 +890,7 @@ ccl_device_inline float3 bvh_curve_refine(KernelGlobals *kg, ShaderData *sd, con
if(isect->object != OBJECT_NONE) {
#ifdef __OBJECT_MOTION__
- Transform tfm = sd->ob_itfm;
+ Transform tfm = ccl_fetch(sd, ob_itfm);
#else
Transform tfm = object_fetch_transform(kg, isect->object, OBJECT_INVERSE_TRANSFORM);
#endif
@@ -903,7 +903,7 @@ ccl_device_inline float3 bvh_curve_refine(KernelGlobals *kg, ShaderData *sd, con
int prim = kernel_tex_fetch(__prim_index, isect->prim);
float4 v00 = kernel_tex_fetch(__curves, prim);
- int k0 = __float_as_int(v00.x) + PRIMITIVE_UNPACK_SEGMENT(sd->type);
+ int k0 = __float_as_int(v00.x) + PRIMITIVE_UNPACK_SEGMENT(ccl_fetch(sd, type));
int k1 = k0 + 1;
float3 tg;
@@ -914,14 +914,14 @@ ccl_device_inline float3 bvh_curve_refine(KernelGlobals *kg, ShaderData *sd, con
float4 P_curve[4];
- if(sd->type & PRIMITIVE_CURVE) {
+ if(ccl_fetch(sd, type) & PRIMITIVE_CURVE) {
P_curve[0] = kernel_tex_fetch(__curve_keys, ka);
P_curve[1] = kernel_tex_fetch(__curve_keys, k0);
P_curve[2] = kernel_tex_fetch(__curve_keys, k1);
P_curve[3] = kernel_tex_fetch(__curve_keys, kb);
}
else {
- motion_cardinal_curve_keys(kg, sd->object, sd->prim, sd->time, ka, k0, k1, kb, P_curve);
+ motion_cardinal_curve_keys(kg, ccl_fetch(sd, object), ccl_fetch(sd, prim), ccl_fetch(sd, time), ka, k0, k1, kb, P_curve);
}
float3 p[4];
@@ -933,43 +933,43 @@ ccl_device_inline float3 bvh_curve_refine(KernelGlobals *kg, ShaderData *sd, con
P = P + D*t;
#ifdef __UV__
- sd->u = isect->u;
- sd->v = 0.0f;
+ ccl_fetch(sd, u) = isect->u;
+ ccl_fetch(sd, v) = 0.0f;
#endif
tg = normalize(curvetangent(isect->u, p[0], p[1], p[2], p[3]));
if(kernel_data.curve.curveflags & CURVE_KN_RIBBONS) {
- sd->Ng = normalize(-(D - tg * (dot(tg, D))));
+ ccl_fetch(sd, Ng) = normalize(-(D - tg * (dot(tg, D))));
}
else {
/* direction from inside to surface of curve */
float3 p_curr = curvepoint(isect->u, p[0], p[1], p[2], p[3]);
- sd->Ng = normalize(P - p_curr);
+ ccl_fetch(sd, Ng) = normalize(P - p_curr);
/* adjustment for changing radius */
float gd = isect->v;
if(gd != 0.0f) {
- sd->Ng = sd->Ng - gd * tg;
- sd->Ng = normalize(sd->Ng);
+ ccl_fetch(sd, Ng) = ccl_fetch(sd, Ng) - gd * tg;
+ ccl_fetch(sd, Ng) = normalize(ccl_fetch(sd, Ng));
}
}
/* todo: sometimes the normal is still so that this is detected as
* backfacing even if cull backfaces is enabled */
- sd->N = sd->Ng;
+ ccl_fetch(sd, N) = ccl_fetch(sd, Ng);
}
else {
float4 P_curve[2];
- if(sd->type & PRIMITIVE_CURVE) {
+ if(ccl_fetch(sd, type) & PRIMITIVE_CURVE) {
P_curve[0]= kernel_tex_fetch(__curve_keys, k0);
P_curve[1]= kernel_tex_fetch(__curve_keys, k1);
}
else {
- motion_curve_keys(kg, sd->object, sd->prim, sd->time, k0, k1, P_curve);
+ motion_curve_keys(kg, ccl_fetch(sd, object), ccl_fetch(sd, prim), ccl_fetch(sd, time), k0, k1, P_curve);
}
float l = 1.0f;
@@ -980,39 +980,39 @@ ccl_device_inline float3 bvh_curve_refine(KernelGlobals *kg, ShaderData *sd, con
float3 dif = P - float4_to_float3(P_curve[0]);
#ifdef __UV__
- sd->u = dot(dif,tg)/l;
- sd->v = 0.0f;
+ ccl_fetch(sd, u) = dot(dif,tg)/l;
+ ccl_fetch(sd, v) = 0.0f;
#endif
- if (flag & CURVE_KN_TRUETANGENTGNORMAL) {
- sd->Ng = -(D - tg * dot(tg, D));
- sd->Ng = normalize(sd->Ng);
+ if(flag & CURVE_KN_TRUETANGENTGNORMAL) {
+ ccl_fetch(sd, Ng) = -(D - tg * dot(tg, D));
+ ccl_fetch(sd, Ng) = normalize(ccl_fetch(sd, Ng));
}
else {
float gd = isect->v;
/* direction from inside to surface of curve */
- sd->Ng = (dif - tg * sd->u * l) / (P_curve[0].w + sd->u * l * gd);
+ ccl_fetch(sd, Ng) = (dif - tg * ccl_fetch(sd, u) * l) / (P_curve[0].w + ccl_fetch(sd, u) * l * gd);
/* adjustment for changing radius */
- if (gd != 0.0f) {
- sd->Ng = sd->Ng - gd * tg;
- sd->Ng = normalize(sd->Ng);
+ if(gd != 0.0f) {
+ ccl_fetch(sd, Ng) = ccl_fetch(sd, Ng) - gd * tg;
+ ccl_fetch(sd, Ng) = normalize(ccl_fetch(sd, Ng));
}
}
- sd->N = sd->Ng;
+ ccl_fetch(sd, N) = ccl_fetch(sd, Ng);
}
#ifdef __DPDU__
/* dPdu/dPdv */
- sd->dPdu = tg;
- sd->dPdv = cross(tg, sd->Ng);
+ ccl_fetch(sd, dPdu) = tg;
+ ccl_fetch(sd, dPdv) = cross(tg, ccl_fetch(sd, Ng));
#endif
if(isect->object != OBJECT_NONE) {
#ifdef __OBJECT_MOTION__
- Transform tfm = sd->ob_tfm;
+ Transform tfm = ccl_fetch(sd, ob_tfm);
#else
Transform tfm = object_fetch_transform(kg, isect->object, OBJECT_TRANSFORM);
#endif
diff --git a/intern/cycles/kernel/geom/geom_motion_curve.h b/intern/cycles/kernel/geom/geom_motion_curve.h
index 1022a957b05..6de5aa7ea99 100644
--- a/intern/cycles/kernel/geom/geom_motion_curve.h
+++ b/intern/cycles/kernel/geom/geom_motion_curve.h
@@ -27,17 +27,22 @@ CCL_NAMESPACE_BEGIN
ccl_device_inline int find_attribute_curve_motion(KernelGlobals *kg, int object, uint id, AttributeElement *elem)
{
- /* todo: find a better (faster) solution for this, maybe store offset per object */
+ /* todo: find a better (faster) solution for this, maybe store offset per object.
+ *
+ * NOTE: currently it's not a bottleneck because in test scenes the loop below runs
+ * zero iterations and rendering is really slow with motion curves. For until other
+ * areas are speed up it's probably not so crucial to optimize this out.
+ */
uint attr_offset = object*kernel_data.bvh.attributes_map_stride + ATTR_PRIM_CURVE;
uint4 attr_map = kernel_tex_fetch(__attributes_map, attr_offset);
-
+
while(attr_map.x != id) {
attr_offset += ATTR_PRIM_TYPES;
attr_map = kernel_tex_fetch(__attributes_map, attr_offset);
}
*elem = (AttributeElement)attr_map.y;
-
+
/* return result */
return (attr_map.y == ATTR_ELEMENT_NONE) ? (int)ATTR_STD_NOT_FOUND : (int)attr_map.z;
}
diff --git a/intern/cycles/kernel/geom/geom_motion_triangle.h b/intern/cycles/kernel/geom/geom_motion_triangle.h
index b275b89a8a4..86f93f242a1 100644
--- a/intern/cycles/kernel/geom/geom_motion_triangle.h
+++ b/intern/cycles/kernel/geom/geom_motion_triangle.h
@@ -130,8 +130,11 @@ ccl_device_inline float3 motion_triangle_refine(KernelGlobals *kg, ShaderData *s
#ifdef __INTERSECTION_REFINE__
if(isect->object != OBJECT_NONE) {
+ if(UNLIKELY(t == 0.0f)) {
+ return P;
+ }
#ifdef __OBJECT_MOTION__
- Transform tfm = sd->ob_itfm;
+ Transform tfm = ccl_fetch(sd, ob_itfm);
#else
Transform tfm = object_fetch_transform(kg, isect->object, OBJECT_INVERSE_TRANSFORM);
#endif
@@ -158,7 +161,7 @@ ccl_device_inline float3 motion_triangle_refine(KernelGlobals *kg, ShaderData *s
if(isect->object != OBJECT_NONE) {
#ifdef __OBJECT_MOTION__
- Transform tfm = sd->ob_tfm;
+ Transform tfm = ccl_fetch(sd, ob_tfm);
#else
Transform tfm = object_fetch_transform(kg, isect->object, OBJECT_TRANSFORM);
#endif
@@ -184,7 +187,7 @@ ccl_device_inline float3 motion_triangle_refine_subsurface(KernelGlobals *kg, Sh
#ifdef __INTERSECTION_REFINE__
if(isect->object != OBJECT_NONE) {
#ifdef __OBJECT_MOTION__
- Transform tfm = sd->ob_itfm;
+ Transform tfm = ccl_fetch(sd, ob_itfm);
#else
Transform tfm = object_fetch_transform(kg, isect->object, OBJECT_INVERSE_TRANSFORM);
#endif
@@ -210,7 +213,7 @@ ccl_device_inline float3 motion_triangle_refine_subsurface(KernelGlobals *kg, Sh
if(isect->object != OBJECT_NONE) {
#ifdef __OBJECT_MOTION__
- Transform tfm = sd->ob_tfm;
+ Transform tfm = ccl_fetch(sd, ob_tfm);
#else
Transform tfm = object_fetch_transform(kg, isect->object, OBJECT_TRANSFORM);
#endif
@@ -233,25 +236,25 @@ ccl_device_inline float3 motion_triangle_refine_subsurface(KernelGlobals *kg, Sh
ccl_device_noinline void motion_triangle_shader_setup(KernelGlobals *kg, ShaderData *sd, const Intersection *isect, const Ray *ray, bool subsurface)
{
/* get shader */
- sd->shader = kernel_tex_fetch(__tri_shader, sd->prim);
+ ccl_fetch(sd, shader) = kernel_tex_fetch(__tri_shader, ccl_fetch(sd, prim));
/* get motion info */
int numsteps, numverts;
- object_motion_info(kg, sd->object, &numsteps, &numverts, NULL);
+ object_motion_info(kg, ccl_fetch(sd, object), &numsteps, &numverts, NULL);
/* figure out which steps we need to fetch and their interpolation factor */
int maxstep = numsteps*2;
- int step = min((int)(sd->time*maxstep), maxstep-1);
- float t = sd->time*maxstep - step;
+ int step = min((int)(ccl_fetch(sd, time)*maxstep), maxstep-1);
+ float t = ccl_fetch(sd, time)*maxstep - step;
/* find attribute */
AttributeElement elem;
- int offset = find_attribute_motion(kg, sd->object, ATTR_STD_MOTION_VERTEX_POSITION, &elem);
+ int offset = find_attribute_motion(kg, ccl_fetch(sd, object), ATTR_STD_MOTION_VERTEX_POSITION, &elem);
kernel_assert(offset != ATTR_STD_NOT_FOUND);
/* fetch vertex coordinates */
float3 verts[3], next_verts[3];
- float3 tri_vindex = float4_to_float3(kernel_tex_fetch(__tri_vindex, sd->prim));
+ float3 tri_vindex = float4_to_float3(kernel_tex_fetch(__tri_vindex, ccl_fetch(sd, prim)));
motion_triangle_verts_for_step(kg, tri_vindex, offset, numverts, numsteps, step, verts);
motion_triangle_verts_for_step(kg, tri_vindex, offset, numverts, numsteps, step+1, next_verts);
@@ -265,33 +268,33 @@ ccl_device_noinline void motion_triangle_shader_setup(KernelGlobals *kg, ShaderD
#ifdef __SUBSURFACE__
if(!subsurface)
#endif
- sd->P = motion_triangle_refine(kg, sd, isect, ray, verts);
+ ccl_fetch(sd, P) = motion_triangle_refine(kg, sd, isect, ray, verts);
#ifdef __SUBSURFACE__
else
- sd->P = motion_triangle_refine_subsurface(kg, sd, isect, ray, verts);
+ ccl_fetch(sd, P) = motion_triangle_refine_subsurface(kg, sd, isect, ray, verts);
#endif
/* compute face normal */
float3 Ng;
- if(sd->flag & SD_NEGATIVE_SCALE_APPLIED)
+ if(ccl_fetch(sd, flag) & SD_NEGATIVE_SCALE_APPLIED)
Ng = normalize(cross(verts[2] - verts[0], verts[1] - verts[0]));
else
Ng = normalize(cross(verts[1] - verts[0], verts[2] - verts[0]));
- sd->Ng = Ng;
- sd->N = Ng;
+ ccl_fetch(sd, Ng) = Ng;
+ ccl_fetch(sd, N) = Ng;
/* compute derivatives of P w.r.t. uv */
#ifdef __DPDU__
- sd->dPdu = (verts[0] - verts[2]);
- sd->dPdv = (verts[1] - verts[2]);
+ ccl_fetch(sd, dPdu) = (verts[0] - verts[2]);
+ ccl_fetch(sd, dPdv) = (verts[1] - verts[2]);
#endif
/* compute smooth normal */
- if(sd->shader & SHADER_SMOOTH_NORMAL) {
+ if(ccl_fetch(sd, shader) & SHADER_SMOOTH_NORMAL) {
/* find attribute */
AttributeElement elem;
- int offset = find_attribute_motion(kg, sd->object, ATTR_STD_MOTION_VERTEX_NORMAL, &elem);
+ int offset = find_attribute_motion(kg, ccl_fetch(sd, object), ATTR_STD_MOTION_VERTEX_NORMAL, &elem);
kernel_assert(offset != ATTR_STD_NOT_FOUND);
/* fetch vertex coordinates */
@@ -305,10 +308,10 @@ ccl_device_noinline void motion_triangle_shader_setup(KernelGlobals *kg, ShaderD
normals[2] = (1.0f - t)*normals[2] + t*next_normals[2];
/* interpolate between vertices */
- float u = sd->u;
- float v = sd->v;
+ float u = ccl_fetch(sd, u);
+ float v = ccl_fetch(sd, v);
float w = 1.0f - u - v;
- sd->N = (u*normals[0] + v*normals[1] + w*normals[2]);
+ ccl_fetch(sd, N) = (u*normals[0] + v*normals[1] + w*normals[2]);
}
}
@@ -336,12 +339,12 @@ ccl_device_inline bool motion_triangle_intersect(KernelGlobals *kg, Intersection
if(kernel_tex_fetch(__prim_visibility, triAddr) & visibility)
#endif
{
+ isect->t = t;
+ isect->u = u;
+ isect->v = v;
isect->prim = triAddr;
isect->object = object;
isect->type = PRIMITIVE_MOTION_TRIANGLE;
- isect->u = u;
- isect->v = v;
- isect->t = t;
return true;
}
@@ -388,12 +391,12 @@ ccl_device_inline void motion_triangle_intersect_subsurface(KernelGlobals *kg, I
/* record intersection */
Intersection *isect = &isect_array[hit];
+ isect->t = t;
+ isect->u = u;
+ isect->v = v;
isect->prim = triAddr;
isect->object = object;
isect->type = PRIMITIVE_MOTION_TRIANGLE;
- isect->u = u;
- isect->v = v;
- isect->t = t;
}
}
#endif
diff --git a/intern/cycles/kernel/geom/geom_object.h b/intern/cycles/kernel/geom/geom_object.h
index 91edd5863ac..9d0a008fff1 100644
--- a/intern/cycles/kernel/geom/geom_object.h
+++ b/intern/cycles/kernel/geom/geom_object.h
@@ -123,9 +123,9 @@ ccl_device_inline Transform object_fetch_transform_motion_test(KernelGlobals *kg
ccl_device_inline void object_position_transform(KernelGlobals *kg, const ShaderData *sd, float3 *P)
{
#ifdef __OBJECT_MOTION__
- *P = transform_point(&sd->ob_tfm, *P);
+ *P = transform_point_auto(&ccl_fetch(sd, ob_tfm), *P);
#else
- Transform tfm = object_fetch_transform(kg, sd->object, OBJECT_TRANSFORM);
+ Transform tfm = object_fetch_transform(kg, ccl_fetch(sd, object), OBJECT_TRANSFORM);
*P = transform_point(&tfm, *P);
#endif
}
@@ -135,9 +135,9 @@ ccl_device_inline void object_position_transform(KernelGlobals *kg, const Shader
ccl_device_inline void object_inverse_position_transform(KernelGlobals *kg, const ShaderData *sd, float3 *P)
{
#ifdef __OBJECT_MOTION__
- *P = transform_point(&sd->ob_itfm, *P);
+ *P = transform_point_auto(&ccl_fetch(sd, ob_itfm), *P);
#else
- Transform tfm = object_fetch_transform(kg, sd->object, OBJECT_INVERSE_TRANSFORM);
+ Transform tfm = object_fetch_transform(kg, ccl_fetch(sd, object), OBJECT_INVERSE_TRANSFORM);
*P = transform_point(&tfm, *P);
#endif
}
@@ -147,9 +147,9 @@ ccl_device_inline void object_inverse_position_transform(KernelGlobals *kg, cons
ccl_device_inline void object_inverse_normal_transform(KernelGlobals *kg, const ShaderData *sd, float3 *N)
{
#ifdef __OBJECT_MOTION__
- *N = normalize(transform_direction_transposed(&sd->ob_tfm, *N));
+ *N = normalize(transform_direction_transposed_auto(&ccl_fetch(sd, ob_tfm), *N));
#else
- Transform tfm = object_fetch_transform(kg, sd->object, OBJECT_TRANSFORM);
+ Transform tfm = object_fetch_transform(kg, ccl_fetch(sd, object), OBJECT_TRANSFORM);
*N = normalize(transform_direction_transposed(&tfm, *N));
#endif
}
@@ -159,9 +159,9 @@ ccl_device_inline void object_inverse_normal_transform(KernelGlobals *kg, const
ccl_device_inline void object_normal_transform(KernelGlobals *kg, const ShaderData *sd, float3 *N)
{
#ifdef __OBJECT_MOTION__
- *N = normalize(transform_direction_transposed(&sd->ob_itfm, *N));
+ *N = normalize(transform_direction_transposed_auto(&ccl_fetch(sd, ob_itfm), *N));
#else
- Transform tfm = object_fetch_transform(kg, sd->object, OBJECT_INVERSE_TRANSFORM);
+ Transform tfm = object_fetch_transform(kg, ccl_fetch(sd, object), OBJECT_INVERSE_TRANSFORM);
*N = normalize(transform_direction_transposed(&tfm, *N));
#endif
}
@@ -171,9 +171,9 @@ ccl_device_inline void object_normal_transform(KernelGlobals *kg, const ShaderDa
ccl_device_inline void object_dir_transform(KernelGlobals *kg, const ShaderData *sd, float3 *D)
{
#ifdef __OBJECT_MOTION__
- *D = transform_direction(&sd->ob_tfm, *D);
+ *D = transform_direction_auto(&ccl_fetch(sd, ob_tfm), *D);
#else
- Transform tfm = object_fetch_transform(kg, sd->object, OBJECT_TRANSFORM);
+ Transform tfm = object_fetch_transform(kg, ccl_fetch(sd, object), OBJECT_TRANSFORM);
*D = transform_direction(&tfm, *D);
#endif
}
@@ -183,9 +183,9 @@ ccl_device_inline void object_dir_transform(KernelGlobals *kg, const ShaderData
ccl_device_inline void object_inverse_dir_transform(KernelGlobals *kg, const ShaderData *sd, float3 *D)
{
#ifdef __OBJECT_MOTION__
- *D = transform_direction(&sd->ob_itfm, *D);
+ *D = transform_direction_auto(&ccl_fetch(sd, ob_itfm), *D);
#else
- Transform tfm = object_fetch_transform(kg, sd->object, OBJECT_INVERSE_TRANSFORM);
+ Transform tfm = object_fetch_transform(kg, ccl_fetch(sd, object), OBJECT_INVERSE_TRANSFORM);
*D = transform_direction(&tfm, *D);
#endif
}
@@ -194,13 +194,13 @@ ccl_device_inline void object_inverse_dir_transform(KernelGlobals *kg, const Sha
ccl_device_inline float3 object_location(KernelGlobals *kg, const ShaderData *sd)
{
- if(sd->object == OBJECT_NONE)
+ if(ccl_fetch(sd, object) == OBJECT_NONE)
return make_float3(0.0f, 0.0f, 0.0f);
#ifdef __OBJECT_MOTION__
- return make_float3(sd->ob_tfm.x.w, sd->ob_tfm.y.w, sd->ob_tfm.z.w);
+ return make_float3(ccl_fetch(sd, ob_tfm).x.w, ccl_fetch(sd, ob_tfm).y.w, ccl_fetch(sd, ob_tfm).z.w);
#else
- Transform tfm = object_fetch_transform(kg, sd->object, OBJECT_TRANSFORM);
+ Transform tfm = object_fetch_transform(kg, ccl_fetch(sd, object), OBJECT_TRANSFORM);
return make_float3(tfm.x.w, tfm.y.w, tfm.z.w);
#endif
}
@@ -243,7 +243,7 @@ ccl_device_inline float object_random_number(KernelGlobals *kg, int object)
ccl_device_inline int object_particle_id(KernelGlobals *kg, int object)
{
if(object == OBJECT_NONE)
- return 0.0f;
+ return 0;
int offset = object*OBJECT_SIZE + OBJECT_PROPERTIES;
float4 f = kernel_tex_fetch(__objects, offset);
@@ -296,7 +296,7 @@ ccl_device_inline void object_motion_info(KernelGlobals *kg, int object, int *nu
ccl_device int shader_pass_id(KernelGlobals *kg, const ShaderData *sd)
{
- return kernel_tex_fetch(__shader_flag, (sd->shader & SHADER_MASK)*2 + 1);
+ return kernel_tex_fetch(__shader_flag, (ccl_fetch(sd, shader) & SHADER_MASK)*2 + 1);
}
/* Particle data from which object was instanced */
@@ -377,7 +377,7 @@ ccl_device_inline float3 bvh_inverse_direction(float3 dir)
/* Transform ray into object space to enter static object in BVH */
-ccl_device_inline void bvh_instance_push(KernelGlobals *kg, int object, const Ray *ray, float3 *P, float3 *dir, float3 *idir, float *t)
+ccl_device_inline void bvh_instance_push(KernelGlobals *kg, int object, const Ray *ray, float3 *P, float3 *dir, float3 *idir, ccl_addr_space float *t)
{
Transform tfm = object_fetch_transform(kg, object, OBJECT_INVERSE_TRANSFORM);
@@ -391,9 +391,41 @@ ccl_device_inline void bvh_instance_push(KernelGlobals *kg, int object, const Ra
*t *= len;
}
+#ifdef __QBVH__
+/* Same as above, but optimized for QBVH scene intersection,
+ * which needs to modify two max distances.
+ *
+ * TODO(sergey): Investigate if passing NULL instead of t1 gets optimized
+ * so we can avoid having this duplication.
+ */
+ccl_device_inline void qbvh_instance_push(KernelGlobals *kg,
+ int object,
+ const Ray *ray,
+ float3 *P,
+ float3 *dir,
+ float3 *idir,
+ float *t,
+ float *t1)
+{
+ Transform tfm = object_fetch_transform(kg, object, OBJECT_INVERSE_TRANSFORM);
+
+ *P = transform_point(&tfm, ray->P);
+
+ float len;
+ *dir = bvh_clamp_direction(normalize_len(transform_direction(&tfm, ray->D), &len));
+ *idir = bvh_inverse_direction(*dir);
+
+ if(*t != FLT_MAX)
+ *t *= len;
+
+ if(*t1 != -FLT_MAX)
+ *t1 *= len;
+}
+#endif
+
/* Transorm ray to exit static object in BVH */
-ccl_device_inline void bvh_instance_pop(KernelGlobals *kg, int object, const Ray *ray, float3 *P, float3 *dir, float3 *idir, float *t)
+ccl_device_inline void bvh_instance_pop(KernelGlobals *kg, int object, const Ray *ray, float3 *P, float3 *dir, float3 *idir, ccl_addr_space float *t)
{
if(*t != FLT_MAX) {
Transform tfm = object_fetch_transform(kg, object, OBJECT_TRANSFORM);
@@ -421,7 +453,7 @@ ccl_device_inline void bvh_instance_pop_factor(KernelGlobals *kg, int object, co
#ifdef __OBJECT_MOTION__
/* Transform ray into object space to enter motion blurred object in BVH */
-ccl_device_inline void bvh_instance_motion_push(KernelGlobals *kg, int object, const Ray *ray, float3 *P, float3 *dir, float3 *idir, float *t, Transform *tfm)
+ccl_device_inline void bvh_instance_motion_push(KernelGlobals *kg, int object, const Ray *ray, float3 *P, float3 *dir, float3 *idir, ccl_addr_space float *t, Transform *tfm)
{
Transform itfm;
*tfm = object_fetch_transform_motion_test(kg, object, ray->time, &itfm);
@@ -436,9 +468,36 @@ ccl_device_inline void bvh_instance_motion_push(KernelGlobals *kg, int object, c
*t *= len;
}
+#ifdef __QBVH__
+/* Same as above, but optimized for QBVH scene intersection,
+ * which needs to modify two max distances.
+ *
+ * TODO(sergey): Investigate if passing NULL instead of t1 gets optimized
+ * so we can avoid having this duplication.
+ */
+ccl_device_inline void qbvh_instance_motion_push(KernelGlobals *kg, int object, const Ray *ray, float3 *P, float3 *dir, float3 *idir, float *t, float *t1, Transform *tfm)
+{
+ Transform itfm;
+ *tfm = object_fetch_transform_motion_test(kg, object, ray->time, &itfm);
+
+ *P = transform_point(&itfm, ray->P);
+
+ float len;
+ *dir = bvh_clamp_direction(normalize_len(transform_direction(&itfm, ray->D), &len));
+ *idir = bvh_inverse_direction(*dir);
+
+
+ if(*t != FLT_MAX)
+ *t *= len;
+
+ if(*t1 != -FLT_MAX)
+ *t1 *= len;
+}
+#endif
+
/* Transorm ray to exit motion blurred object in BVH */
-ccl_device_inline void bvh_instance_motion_pop(KernelGlobals *kg, int object, const Ray *ray, float3 *P, float3 *dir, float3 *idir, float *t, Transform *tfm)
+ccl_device_inline void bvh_instance_motion_pop(KernelGlobals *kg, int object, const Ray *ray, float3 *P, float3 *dir, float3 *idir, ccl_addr_space float *t, Transform *tfm)
{
if(*t != FLT_MAX)
*t *= len(transform_direction(tfm, 1.0f/(*idir)));
@@ -461,5 +520,38 @@ ccl_device_inline void bvh_instance_motion_pop_factor(KernelGlobals *kg, int obj
#endif
+/* TODO(sergey): This is only for until we've got OpenCL 2.0
+ * on all devices we consider supported. It'll be replaced with
+ * generic address space.
+ */
+
+#ifdef __KERNEL_OPENCL__
+ccl_device_inline void object_dir_transform_addrspace(KernelGlobals *kg,
+ const ShaderData *sd,
+ ccl_addr_space float3 *D)
+{
+ float3 private_D = *D;
+ object_dir_transform(kg, sd, &private_D);
+ *D = private_D;
+}
+
+ccl_device_inline void object_normal_transform_addrspace(KernelGlobals *kg,
+ const ShaderData *sd,
+ ccl_addr_space float3 *N)
+{
+ float3 private_N = *N;
+ object_normal_transform(kg, sd, &private_N);
+ *N = private_N;
+}
+#endif
+
+#ifndef __KERNEL_OPENCL__
+# define object_dir_transform_auto object_dir_transform
+# define object_normal_transform_auto object_normal_transform
+#else
+# define object_dir_transform_auto object_dir_transform_addrspace
+# define object_normal_transform_auto object_normal_transform_addrspace
+#endif
+
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/geom/geom_primitive.h b/intern/cycles/kernel/geom/geom_primitive.h
index 5df6c75df86..30f12d32355 100644
--- a/intern/cycles/kernel/geom/geom_primitive.h
+++ b/intern/cycles/kernel/geom/geom_primitive.h
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
/* Primitive Utilities
@@ -25,16 +25,16 @@ CCL_NAMESPACE_BEGIN
ccl_device float primitive_attribute_float(KernelGlobals *kg, const ShaderData *sd, AttributeElement elem, int offset, float *dx, float *dy)
{
- if(sd->type & PRIMITIVE_ALL_TRIANGLE) {
+ if(ccl_fetch(sd, type) & PRIMITIVE_ALL_TRIANGLE) {
return triangle_attribute_float(kg, sd, elem, offset, dx, dy);
}
#ifdef __HAIR__
- else if(sd->type & PRIMITIVE_ALL_CURVE) {
+ else if(ccl_fetch(sd, type) & PRIMITIVE_ALL_CURVE) {
return curve_attribute_float(kg, sd, elem, offset, dx, dy);
}
#endif
#ifdef __VOLUME__
- else if(sd->object != OBJECT_NONE && elem == ATTR_ELEMENT_VOXEL) {
+ else if(ccl_fetch(sd, object) != OBJECT_NONE && elem == ATTR_ELEMENT_VOXEL) {
return volume_attribute_float(kg, sd, elem, offset, dx, dy);
}
#endif
@@ -47,16 +47,16 @@ ccl_device float primitive_attribute_float(KernelGlobals *kg, const ShaderData *
ccl_device float3 primitive_attribute_float3(KernelGlobals *kg, const ShaderData *sd, AttributeElement elem, int offset, float3 *dx, float3 *dy)
{
- if(sd->type & PRIMITIVE_ALL_TRIANGLE) {
+ if(ccl_fetch(sd, type) & PRIMITIVE_ALL_TRIANGLE) {
return triangle_attribute_float3(kg, sd, elem, offset, dx, dy);
}
#ifdef __HAIR__
- else if(sd->type & PRIMITIVE_ALL_CURVE) {
+ else if(ccl_fetch(sd, type) & PRIMITIVE_ALL_CURVE) {
return curve_attribute_float3(kg, sd, elem, offset, dx, dy);
}
#endif
#ifdef __VOLUME__
- else if(sd->object != OBJECT_NONE && elem == ATTR_ELEMENT_VOXEL) {
+ else if(ccl_fetch(sd, object) != OBJECT_NONE && elem == ATTR_ELEMENT_VOXEL) {
return volume_attribute_float3(kg, sd, elem, offset, dx, dy);
}
#endif
@@ -108,9 +108,9 @@ ccl_device bool primitive_ptex(KernelGlobals *kg, ShaderData *sd, float2 *uv, in
ccl_device float3 primitive_tangent(KernelGlobals *kg, ShaderData *sd)
{
#ifdef __HAIR__
- if(sd->type & PRIMITIVE_ALL_CURVE)
+ if(ccl_fetch(sd, type) & PRIMITIVE_ALL_CURVE)
#ifdef __DPDU__
- return normalize(sd->dPdu);
+ return normalize(ccl_fetch(sd, dPdu));
#else
return make_float3(0.0f, 0.0f, 0.0f);
#endif
@@ -124,12 +124,12 @@ ccl_device float3 primitive_tangent(KernelGlobals *kg, ShaderData *sd)
float3 data = primitive_attribute_float3(kg, sd, attr_elem, attr_offset, NULL, NULL);
data = make_float3(-(data.y - 0.5f), (data.x - 0.5f), 0.0f);
object_normal_transform(kg, sd, &data);
- return cross(sd->N, normalize(cross(data, sd->N)));
+ return cross(ccl_fetch(sd, N), normalize(cross(data, ccl_fetch(sd, N))));
}
else {
/* otherwise use surface derivatives */
#ifdef __DPDU__
- return normalize(sd->dPdu);
+ return normalize(ccl_fetch(sd, dPdu));
#else
return make_float3(0.0f, 0.0f, 0.0f);
#endif
@@ -144,15 +144,16 @@ ccl_device float4 primitive_motion_vector(KernelGlobals *kg, ShaderData *sd)
float3 center;
#ifdef __HAIR__
- if(sd->type & PRIMITIVE_ALL_CURVE) {
+ bool is_curve_primitive = ccl_fetch(sd, type) & PRIMITIVE_ALL_CURVE;
+ if(is_curve_primitive) {
center = curve_motion_center_location(kg, sd);
- if(!(sd->flag & SD_TRANSFORM_APPLIED))
+ if(!(ccl_fetch(sd, flag) & SD_TRANSFORM_APPLIED))
object_position_transform(kg, sd, &center);
}
else
#endif
- center = sd->P;
+ center = ccl_fetch(sd, P);
float3 motion_pre = center, motion_post = center;
@@ -163,30 +164,37 @@ ccl_device float4 primitive_motion_vector(KernelGlobals *kg, ShaderData *sd)
if(offset != ATTR_STD_NOT_FOUND) {
/* get motion info */
int numverts, numkeys;
- object_motion_info(kg, sd->object, NULL, &numverts, &numkeys);
+ object_motion_info(kg, ccl_fetch(sd, object), NULL, &numverts, &numkeys);
/* lookup attributes */
- int offset_next = (sd->type & PRIMITIVE_ALL_TRIANGLE)? offset + numverts: offset + numkeys;
+ int offset_next = (ccl_fetch(sd, type) & PRIMITIVE_ALL_TRIANGLE)? offset + numverts: offset + numkeys;
motion_pre = primitive_attribute_float3(kg, sd, elem, offset, NULL, NULL);
motion_post = primitive_attribute_float3(kg, sd, elem, offset_next, NULL, NULL);
+
+#ifdef __HAIR__
+ if(is_curve_primitive && (ccl_fetch(sd, flag) & SD_OBJECT_HAS_VERTEX_MOTION) == 0) {
+ object_position_transform(kg, sd, &motion_pre);
+ object_position_transform(kg, sd, &motion_post);
+ }
+#endif
}
/* object motion. note that depending on the mesh having motion vectors, this
* transformation was set match the world/object space of motion_pre/post */
Transform tfm;
- tfm = object_fetch_vector_transform(kg, sd->object, OBJECT_VECTOR_MOTION_PRE);
+ tfm = object_fetch_vector_transform(kg, ccl_fetch(sd, object), OBJECT_VECTOR_MOTION_PRE);
motion_pre = transform_point(&tfm, motion_pre);
- tfm = object_fetch_vector_transform(kg, sd->object, OBJECT_VECTOR_MOTION_POST);
+ tfm = object_fetch_vector_transform(kg, ccl_fetch(sd, object), OBJECT_VECTOR_MOTION_POST);
motion_post = transform_point(&tfm, motion_post);
float3 motion_center;
/* camera motion, for perspective/orthographic motion.pre/post will be a
* world-to-raster matrix, for panorama it's world-to-camera */
- if (kernel_data.cam.type != CAMERA_PANORAMA) {
+ if(kernel_data.cam.type != CAMERA_PANORAMA) {
tfm = kernel_data.cam.worldtoraster;
motion_center = transform_perspective(&tfm, center);
diff --git a/intern/cycles/kernel/geom/geom_qbvh.h b/intern/cycles/kernel/geom/geom_qbvh.h
new file mode 100644
index 00000000000..37deaac0800
--- /dev/null
+++ b/intern/cycles/kernel/geom/geom_qbvh.h
@@ -0,0 +1,147 @@
+/*
+ * Copyright 2011-2014, Blender Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+struct QBVHStackItem {
+ int addr;
+ float dist;
+};
+
+/* TOOD(sergey): Investigate if using instrinsics helps for both
+ * stack item swap and float comparison.
+ */
+ccl_device_inline void qbvh_item_swap(QBVHStackItem *__restrict a,
+ QBVHStackItem *__restrict b)
+{
+ QBVHStackItem tmp = *a;
+ *a = *b;
+ *b = tmp;
+}
+
+ccl_device_inline void qbvh_stack_sort(QBVHStackItem *__restrict s1,
+ QBVHStackItem *__restrict s2,
+ QBVHStackItem *__restrict s3)
+{
+ if(s2->dist < s1->dist) { qbvh_item_swap(s2, s1); }
+ if(s3->dist < s2->dist) { qbvh_item_swap(s3, s2); }
+ if(s2->dist < s1->dist) { qbvh_item_swap(s2, s1); }
+}
+
+ccl_device_inline void qbvh_stack_sort(QBVHStackItem *__restrict s1,
+ QBVHStackItem *__restrict s2,
+ QBVHStackItem *__restrict s3,
+ QBVHStackItem *__restrict s4)
+{
+ if(s2->dist < s1->dist) { qbvh_item_swap(s2, s1); }
+ if(s4->dist < s3->dist) { qbvh_item_swap(s4, s3); }
+ if(s3->dist < s1->dist) { qbvh_item_swap(s3, s1); }
+ if(s4->dist < s2->dist) { qbvh_item_swap(s4, s2); }
+ if(s3->dist < s2->dist) { qbvh_item_swap(s3, s2); }
+}
+
+ccl_device_inline int qbvh_node_intersect(KernelGlobals *__restrict kg,
+ const ssef& tnear,
+ const ssef& tfar,
+#ifdef __KERNEL_AVX2__
+ const sse3f& org_idir,
+#else
+ const sse3f& org,
+#endif
+ const sse3f& idir,
+ const int near_x,
+ const int near_y,
+ const int near_z,
+ const int far_x,
+ const int far_y,
+ const int far_z,
+ const int nodeAddr,
+ ssef *__restrict dist)
+{
+ const int offset = nodeAddr*BVH_QNODE_SIZE;
+#ifdef __KERNEL_AVX2__
+ const ssef tnear_x = msub(kernel_tex_fetch_ssef(__bvh_nodes, offset+near_x), idir.x, org_idir.x);
+ const ssef tnear_y = msub(kernel_tex_fetch_ssef(__bvh_nodes, offset+near_y), idir.y, org_idir.y);
+ const ssef tnear_z = msub(kernel_tex_fetch_ssef(__bvh_nodes, offset+near_z), idir.z, org_idir.z);
+ const ssef tfar_x = msub(kernel_tex_fetch_ssef(__bvh_nodes, offset+far_x), idir.x, org_idir.x);
+ const ssef tfar_y = msub(kernel_tex_fetch_ssef(__bvh_nodes, offset+far_y), idir.y, org_idir.y);
+ const ssef tfar_z = msub(kernel_tex_fetch_ssef(__bvh_nodes, offset+far_z), idir.z, org_idir.z);
+#else
+ const ssef tnear_x = (kernel_tex_fetch_ssef(__bvh_nodes, offset+near_x) - org.x) * idir.x;
+ const ssef tnear_y = (kernel_tex_fetch_ssef(__bvh_nodes, offset+near_y) - org.y) * idir.y;
+ const ssef tnear_z = (kernel_tex_fetch_ssef(__bvh_nodes, offset+near_z) - org.z) * idir.z;
+ const ssef tfar_x = (kernel_tex_fetch_ssef(__bvh_nodes, offset+far_x) - org.x) * idir.x;
+ const ssef tfar_y = (kernel_tex_fetch_ssef(__bvh_nodes, offset+far_y) - org.y) * idir.y;
+ const ssef tfar_z = (kernel_tex_fetch_ssef(__bvh_nodes, offset+far_z) - org.z) * idir.z;
+#endif
+
+#ifdef __KERNEL_SSE41__
+ const ssef tNear = maxi(maxi(tnear_x, tnear_y), maxi(tnear_z, tnear));
+ const ssef tFar = mini(mini(tfar_x, tfar_y), mini(tfar_z, tfar));
+ const sseb vmask = cast(tNear) > cast(tFar);
+ int mask = (int)movemask(vmask)^0xf;
+#else
+ const ssef tNear = max4(tnear_x, tnear_y, tnear_z, tnear);
+ const ssef tFar = min4(tfar_x, tfar_y, tfar_z, tfar);
+ const sseb vmask = tNear <= tFar;
+ int mask = (int)movemask(vmask);
+#endif
+ *dist = tNear;
+ return mask;
+}
+
+ccl_device_inline int qbvh_node_intersect_robust(KernelGlobals *__restrict kg,
+ const ssef& tnear,
+ const ssef& tfar,
+#ifdef __KERNEL_AVX2__
+ const sse3f& P_idir,
+#else
+ const sse3f& P,
+#endif
+ const sse3f& idir,
+ const int near_x,
+ const int near_y,
+ const int near_z,
+ const int far_x,
+ const int far_y,
+ const int far_z,
+ const int nodeAddr,
+ const float difl,
+ ssef *__restrict dist)
+{
+ const int offset = nodeAddr*BVH_QNODE_SIZE;
+#ifdef __KERNEL_AVX2__
+ const ssef tnear_x = msub(kernel_tex_fetch_ssef(__bvh_nodes, offset+near_x), idir.x, P_idir.x);
+ const ssef tnear_y = msub(kernel_tex_fetch_ssef(__bvh_nodes, offset+near_y), idir.y, P_idir.y);
+ const ssef tnear_z = msub(kernel_tex_fetch_ssef(__bvh_nodes, offset+near_z), idir.z, P_idir.z);
+ const ssef tfar_x = msub(kernel_tex_fetch_ssef(__bvh_nodes, offset+far_x), idir.x, P_idir.x);
+ const ssef tfar_y = msub(kernel_tex_fetch_ssef(__bvh_nodes, offset+far_y), idir.y, P_idir.y);
+ const ssef tfar_z = msub(kernel_tex_fetch_ssef(__bvh_nodes, offset+far_z), idir.z, P_idir.z);
+#else
+ const ssef tnear_x = (kernel_tex_fetch_ssef(__bvh_nodes, offset+near_x) - P.x) * idir.x;
+ const ssef tnear_y = (kernel_tex_fetch_ssef(__bvh_nodes, offset+near_y) - P.y) * idir.y;
+ const ssef tnear_z = (kernel_tex_fetch_ssef(__bvh_nodes, offset+near_z) - P.z) * idir.z;
+ const ssef tfar_x = (kernel_tex_fetch_ssef(__bvh_nodes, offset+far_x) - P.x) * idir.x;
+ const ssef tfar_y = (kernel_tex_fetch_ssef(__bvh_nodes, offset+far_y) - P.y) * idir.y;
+ const ssef tfar_z = (kernel_tex_fetch_ssef(__bvh_nodes, offset+far_z) - P.z) * idir.z;
+#endif
+
+ const float round_down = 1.0f - difl;
+ const float round_up = 1.0f + difl;
+ const ssef tNear = max4(tnear_x, tnear_y, tnear_z, tnear);
+ const ssef tFar = min4(tfar_x, tfar_y, tfar_z, tfar);
+ const sseb vmask = round_down*tNear <= round_up*tFar;
+ *dist = tNear;
+ return (int)movemask(vmask);
+}
diff --git a/intern/cycles/kernel/geom/geom_qbvh_shadow.h b/intern/cycles/kernel/geom/geom_qbvh_shadow.h
new file mode 100644
index 00000000000..dc37e6ecfa4
--- /dev/null
+++ b/intern/cycles/kernel/geom/geom_qbvh_shadow.h
@@ -0,0 +1,403 @@
+/*
+ * Adapted from code Copyright 2009-2010 NVIDIA Corporation,
+ * and code copyright 2009-2012 Intel Corporation
+ *
+ * Modifications Copyright 2011-2014, Blender Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* This is a template BVH traversal function, where various features can be
+ * enabled/disabled. This way we can compile optimized versions for each case
+ * without new features slowing things down.
+ *
+ * BVH_INSTANCING: object instancing
+ * BVH_HAIR: hair curve rendering
+ * BVH_MOTION: motion blur rendering
+ *
+ */
+
+ccl_device bool BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg,
+ const Ray *ray,
+ Intersection *isect_array,
+ const uint max_hits,
+ uint *num_hits)
+{
+ /* TODO(sergey):
+ * - Likely and unlikely for if() statements.
+ * - Test restrict attribute for pointers.
+ */
+
+ /* Traversal stack in CUDA thread-local memory. */
+ QBVHStackItem traversalStack[BVH_QSTACK_SIZE];
+ traversalStack[0].addr = ENTRYPOINT_SENTINEL;
+
+ /* Traversal variables in registers. */
+ int stackPtr = 0;
+ int nodeAddr = kernel_data.bvh.root;
+
+ /* Ray parameters in registers. */
+ const float tmax = ray->t;
+ float3 P = ray->P;
+ float3 dir = bvh_clamp_direction(ray->D);
+ float3 idir = bvh_inverse_direction(dir);
+ int object = OBJECT_NONE;
+ float isect_t = tmax;
+
+#if BVH_FEATURE(BVH_MOTION)
+ Transform ob_tfm;
+#endif
+
+ *num_hits = 0;
+ isect_array->t = tmax;
+
+#ifndef __KERNEL_SSE41__
+ if(!isfinite(P.x)) {
+ return false;
+ }
+#endif
+
+#if BVH_FEATURE(BVH_INSTANCING)
+ int num_hits_in_instance = 0;
+#endif
+
+ ssef tnear(0.0f), tfar(tmax);
+ sse3f idir4(ssef(idir.x), ssef(idir.y), ssef(idir.z));
+
+#ifdef __KERNEL_AVX2__
+ float3 P_idir = P*idir;
+ sse3f P_idir4 = sse3f(P_idir.x, P_idir.y, P_idir.z);
+#else
+ sse3f org = sse3f(ssef(P.x), ssef(P.y), ssef(P.z));
+#endif
+
+ /* Offsets to select the side that becomes the lower or upper bound. */
+ int near_x, near_y, near_z;
+ int far_x, far_y, far_z;
+
+ if(idir.x >= 0.0f) { near_x = 0; far_x = 1; } else { near_x = 1; far_x = 0; }
+ if(idir.y >= 0.0f) { near_y = 2; far_y = 3; } else { near_y = 3; far_y = 2; }
+ if(idir.z >= 0.0f) { near_z = 4; far_z = 5; } else { near_z = 5; far_z = 4; }
+
+ IsectPrecalc isect_precalc;
+ triangle_intersect_precalc(dir, &isect_precalc);
+
+ /* Traversal loop. */
+ do {
+ do {
+ /* Traverse internal nodes. */
+ while(nodeAddr >= 0 && nodeAddr != ENTRYPOINT_SENTINEL) {
+ ssef dist;
+ int traverseChild = qbvh_node_intersect(kg,
+ tnear,
+ tfar,
+#ifdef __KERNEL_AVX2__
+ P_idir4,
+#else
+ org,
+#endif
+ idir4,
+ near_x, near_y, near_z,
+ far_x, far_y, far_z,
+ nodeAddr,
+ &dist);
+
+ if(traverseChild != 0) {
+ float4 cnodes = kernel_tex_fetch(__bvh_nodes, nodeAddr*BVH_QNODE_SIZE+6);
+
+ /* One child is hit, continue with that child. */
+ int r = __bscf(traverseChild);
+ if(traverseChild == 0) {
+ nodeAddr = __float_as_int(cnodes[r]);
+ continue;
+ }
+
+ /* Two children are hit, push far child, and continue with
+ * closer child.
+ */
+ int c0 = __float_as_int(cnodes[r]);
+ float d0 = ((float*)&dist)[r];
+ r = __bscf(traverseChild);
+ int c1 = __float_as_int(cnodes[r]);
+ float d1 = ((float*)&dist)[r];
+ if(traverseChild == 0) {
+ if(d1 < d0) {
+ nodeAddr = c1;
+ ++stackPtr;
+ kernel_assert(stackPtr < BVH_QSTACK_SIZE);
+ traversalStack[stackPtr].addr = c0;
+ traversalStack[stackPtr].dist = d0;
+ continue;
+ }
+ else {
+ nodeAddr = c0;
+ ++stackPtr;
+ kernel_assert(stackPtr < BVH_QSTACK_SIZE);
+ traversalStack[stackPtr].addr = c1;
+ traversalStack[stackPtr].dist = d1;
+ continue;
+ }
+ }
+
+ /* Here starts the slow path for 3 or 4 hit children. We push
+ * all nodes onto the stack to sort them there.
+ */
+ ++stackPtr;
+ kernel_assert(stackPtr < BVH_QSTACK_SIZE);
+ traversalStack[stackPtr].addr = c1;
+ traversalStack[stackPtr].dist = d1;
+ ++stackPtr;
+ kernel_assert(stackPtr < BVH_QSTACK_SIZE);
+ traversalStack[stackPtr].addr = c0;
+ traversalStack[stackPtr].dist = d0;
+
+ /* Three children are hit, push all onto stack and sort 3
+ * stack items, continue with closest child.
+ */
+ r = __bscf(traverseChild);
+ int c2 = __float_as_int(cnodes[r]);
+ float d2 = ((float*)&dist)[r];
+ if(traverseChild == 0) {
+ ++stackPtr;
+ kernel_assert(stackPtr < BVH_QSTACK_SIZE);
+ traversalStack[stackPtr].addr = c2;
+ traversalStack[stackPtr].dist = d2;
+ qbvh_stack_sort(&traversalStack[stackPtr],
+ &traversalStack[stackPtr - 1],
+ &traversalStack[stackPtr - 2]);
+ nodeAddr = traversalStack[stackPtr].addr;
+ --stackPtr;
+ continue;
+ }
+
+ /* Four children are hit, push all onto stack and sort 4
+ * stack items, continue with closest child.
+ */
+ r = __bscf(traverseChild);
+ int c3 = __float_as_int(cnodes[r]);
+ float d3 = ((float*)&dist)[r];
+ ++stackPtr;
+ kernel_assert(stackPtr < BVH_QSTACK_SIZE);
+ traversalStack[stackPtr].addr = c3;
+ traversalStack[stackPtr].dist = d3;
+ ++stackPtr;
+ kernel_assert(stackPtr < BVH_QSTACK_SIZE);
+ traversalStack[stackPtr].addr = c2;
+ traversalStack[stackPtr].dist = d2;
+ qbvh_stack_sort(&traversalStack[stackPtr],
+ &traversalStack[stackPtr - 1],
+ &traversalStack[stackPtr - 2],
+ &traversalStack[stackPtr - 3]);
+ }
+
+ nodeAddr = traversalStack[stackPtr].addr;
+ --stackPtr;
+ }
+
+ /* If node is leaf, fetch triangle list. */
+ if(nodeAddr < 0) {
+ float4 leaf = kernel_tex_fetch(__bvh_leaf_nodes, (-nodeAddr-1)*BVH_QNODE_LEAF_SIZE);
+#ifdef __VISIBILITY_FLAG__
+ if((__float_as_uint(leaf.z) & PATH_RAY_SHADOW) == 0) {
+ /* Pop. */
+ nodeAddr = traversalStack[stackPtr].addr;
+ --stackPtr;
+ continue;
+ }
+#endif
+
+ int primAddr = __float_as_int(leaf.x);
+
+#if BVH_FEATURE(BVH_INSTANCING)
+ if(primAddr >= 0) {
+#endif
+ int primAddr2 = __float_as_int(leaf.y);
+ const uint type = __float_as_int(leaf.w);
+ const uint p_type = type & PRIMITIVE_ALL;
+
+ /* Pop. */
+ nodeAddr = traversalStack[stackPtr].addr;
+ --stackPtr;
+
+ /* Primitive intersection. */
+ while(primAddr < primAddr2) {
+ kernel_assert(kernel_tex_fetch(__prim_type, primAddr) == type);
+
+ bool hit;
+
+ /* todo: specialized intersect functions which don't fill in
+ * isect unless needed and check SD_HAS_TRANSPARENT_SHADOW?
+ * might give a few % performance improvement */
+
+ switch(p_type) {
+ case PRIMITIVE_TRIANGLE: {
+ hit = triangle_intersect(kg, &isect_precalc, isect_array, P, PATH_RAY_SHADOW, object, primAddr);
+ break;
+ }
+#if BVH_FEATURE(BVH_MOTION)
+ case PRIMITIVE_MOTION_TRIANGLE: {
+ hit = motion_triangle_intersect(kg, isect_array, P, dir, ray->time, PATH_RAY_SHADOW, object, primAddr);
+ break;
+ }
+#endif
+#if BVH_FEATURE(BVH_HAIR)
+ case PRIMITIVE_CURVE:
+ case PRIMITIVE_MOTION_CURVE: {
+ if(kernel_data.curve.curveflags & CURVE_KN_INTERPOLATE)
+ hit = bvh_cardinal_curve_intersect(kg, isect_array, P, dir, PATH_RAY_SHADOW, object, primAddr, ray->time, type, NULL, 0, 0);
+ else
+ hit = bvh_curve_intersect(kg, isect_array, P, dir, PATH_RAY_SHADOW, object, primAddr, ray->time, type, NULL, 0, 0);
+ break;
+ }
+#endif
+ default: {
+ hit = false;
+ break;
+ }
+ }
+
+ /* Shadow ray early termination. */
+ if(hit) {
+ /* detect if this surface has a shader with transparent shadows */
+
+ /* todo: optimize so primitive visibility flag indicates if
+ * the primitive has a transparent shadow shader? */
+ int prim = kernel_tex_fetch(__prim_index, isect_array->prim);
+ int shader = 0;
+
+#ifdef __HAIR__
+ if(kernel_tex_fetch(__prim_type, isect_array->prim) & PRIMITIVE_ALL_TRIANGLE)
+#endif
+ {
+ shader = kernel_tex_fetch(__tri_shader, prim);
+ }
+#ifdef __HAIR__
+ else {
+ float4 str = kernel_tex_fetch(__curves, prim);
+ shader = __float_as_int(str.z);
+ }
+#endif
+ int flag = kernel_tex_fetch(__shader_flag, (shader & SHADER_MASK)*2);
+
+ /* if no transparent shadows, all light is blocked */
+ if(!(flag & SD_HAS_TRANSPARENT_SHADOW)) {
+ return true;
+ }
+ /* if maximum number of hits reached, block all light */
+ else if(*num_hits == max_hits) {
+ return true;
+ }
+
+ /* move on to next entry in intersections array */
+ isect_array++;
+ (*num_hits)++;
+#if BVH_FEATURE(BVH_INSTANCING)
+ num_hits_in_instance++;
+#endif
+
+ isect_array->t = isect_t;
+ }
+
+ primAddr++;
+ }
+ }
+#if BVH_FEATURE(BVH_INSTANCING)
+ else {
+ /* Instance push. */
+ object = kernel_tex_fetch(__prim_object, -primAddr-1);
+
+#if BVH_FEATURE(BVH_MOTION)
+ bvh_instance_motion_push(kg, object, ray, &P, &dir, &idir, &isect_t, &ob_tfm);
+#else
+ bvh_instance_push(kg, object, ray, &P, &dir, &idir, &isect_t);
+#endif
+
+ num_hits_in_instance = 0;
+ isect_array->t = isect_t;
+
+ if(idir.x >= 0.0f) { near_x = 0; far_x = 1; } else { near_x = 1; far_x = 0; }
+ if(idir.y >= 0.0f) { near_y = 2; far_y = 3; } else { near_y = 3; far_y = 2; }
+ if(idir.z >= 0.0f) { near_z = 4; far_z = 5; } else { near_z = 5; far_z = 4; }
+ tfar = ssef(isect_t);
+ idir4 = sse3f(ssef(idir.x), ssef(idir.y), ssef(idir.z));
+#ifdef __KERNEL_AVX2__
+ P_idir = P*idir;
+ P_idir4 = sse3f(P_idir.x, P_idir.y, P_idir.z);
+#else
+ org = sse3f(ssef(P.x), ssef(P.y), ssef(P.z));
+#endif
+ triangle_intersect_precalc(dir, &isect_precalc);
+
+ ++stackPtr;
+ kernel_assert(stackPtr < BVH_QSTACK_SIZE);
+ traversalStack[stackPtr].addr = ENTRYPOINT_SENTINEL;
+
+ nodeAddr = kernel_tex_fetch(__object_node, object);
+
+ }
+ }
+#endif /* FEATURE(BVH_INSTANCING) */
+ } while(nodeAddr != ENTRYPOINT_SENTINEL);
+
+#if BVH_FEATURE(BVH_INSTANCING)
+ if(stackPtr >= 0) {
+ kernel_assert(object != OBJECT_NONE);
+
+ if(num_hits_in_instance) {
+ float t_fac;
+
+#if BVH_FEATURE(BVH_MOTION)
+ bvh_instance_motion_pop_factor(kg, object, ray, &P, &dir, &idir, &t_fac, &ob_tfm);
+#else
+ bvh_instance_pop_factor(kg, object, ray, &P, &dir, &idir, &t_fac);
+#endif
+
+ /* scale isect->t to adjust for instancing */
+ for(int i = 0; i < num_hits_in_instance; i++)
+ (isect_array-i-1)->t *= t_fac;
+ }
+ else {
+ float ignore_t = FLT_MAX;
+
+#if BVH_FEATURE(BVH_MOTION)
+ bvh_instance_motion_pop(kg, object, ray, &P, &dir, &idir, &ignore_t, &ob_tfm);
+#else
+ bvh_instance_pop(kg, object, ray, &P, &dir, &idir, &ignore_t);
+#endif
+ }
+
+ isect_t = tmax;
+ isect_array->t = isect_t;
+
+ if(idir.x >= 0.0f) { near_x = 0; far_x = 1; } else { near_x = 1; far_x = 0; }
+ if(idir.y >= 0.0f) { near_y = 2; far_y = 3; } else { near_y = 3; far_y = 2; }
+ if(idir.z >= 0.0f) { near_z = 4; far_z = 5; } else { near_z = 5; far_z = 4; }
+ tfar = ssef(tmax);
+ idir4 = sse3f(ssef(idir.x), ssef(idir.y), ssef(idir.z));
+#ifdef __KERNEL_AVX2__
+ P_idir = P*idir;
+ P_idir4 = sse3f(P_idir.x, P_idir.y, P_idir.z);
+#else
+ org = sse3f(ssef(P.x), ssef(P.y), ssef(P.z));
+#endif
+ triangle_intersect_precalc(dir, &isect_precalc);
+
+ object = OBJECT_NONE;
+ nodeAddr = traversalStack[stackPtr].addr;
+ --stackPtr;
+ }
+#endif /* FEATURE(BVH_INSTANCING) */
+ } while(nodeAddr != ENTRYPOINT_SENTINEL);
+
+ return false;
+}
diff --git a/intern/cycles/kernel/geom/geom_qbvh_subsurface.h b/intern/cycles/kernel/geom/geom_qbvh_subsurface.h
new file mode 100644
index 00000000000..d85e1a4691e
--- /dev/null
+++ b/intern/cycles/kernel/geom/geom_qbvh_subsurface.h
@@ -0,0 +1,326 @@
+/*
+ * Adapted from code Copyright 2009-2010 NVIDIA Corporation,
+ * and code copyright 2009-2012 Intel Corporation
+ *
+ * Modifications Copyright 2011-2014, Blender Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* This is a template BVH traversal function for subsurface scattering, where
+ * various features can be enabled/disabled. This way we can compile optimized
+ * versions for each case without new features slowing things down.
+ *
+ * BVH_INSTANCING: object instancing
+ * BVH_MOTION: motion blur rendering
+ *
+ */
+
+ccl_device uint BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg,
+ const Ray *ray,
+ Intersection *isect_array,
+ int subsurface_object,
+ uint *lcg_state,
+ int max_hits)
+{
+ /* TODO(sergey):
+ * - Test if pushing distance on the stack helps (for non shadow rays).
+ * - Separate version for shadow rays.
+ * - Likely and unlikely for if() statements.
+ * - SSE for hair.
+ * - Test restrict attribute for pointers.
+ */
+
+ /* Traversal stack in CUDA thread-local memory. */
+ QBVHStackItem traversalStack[BVH_QSTACK_SIZE];
+ traversalStack[0].addr = ENTRYPOINT_SENTINEL;
+
+ /* Traversal variables in registers. */
+ int stackPtr = 0;
+ int nodeAddr = kernel_data.bvh.root;
+
+ /* Ray parameters in registers. */
+ float3 P = ray->P;
+ float3 dir = bvh_clamp_direction(ray->D);
+ float3 idir = bvh_inverse_direction(dir);
+ int object = OBJECT_NONE;
+ float isect_t = ray->t;
+ uint num_hits = 0;
+
+#if BVH_FEATURE(BVH_MOTION)
+ Transform ob_tfm;
+#endif
+
+#ifndef __KERNEL_SSE41__
+ if(!isfinite(P.x)) {
+ return 0;
+ }
+#endif
+
+ ssef tnear(0.0f), tfar(isect_t);
+ sse3f idir4(ssef(idir.x), ssef(idir.y), ssef(idir.z));
+
+#ifdef __KERNEL_AVX2__
+ float3 P_idir = P*idir;
+ sse3f P_idir4 = sse3f(P_idir.x, P_idir.y, P_idir.z);
+#else
+ sse3f org = sse3f(ssef(P.x), ssef(P.y), ssef(P.z));
+#endif
+
+ /* Offsets to select the side that becomes the lower or upper bound. */
+ int near_x, near_y, near_z;
+ int far_x, far_y, far_z;
+
+ if(idir.x >= 0.0f) { near_x = 0; far_x = 1; } else { near_x = 1; far_x = 0; }
+ if(idir.y >= 0.0f) { near_y = 2; far_y = 3; } else { near_y = 3; far_y = 2; }
+ if(idir.z >= 0.0f) { near_z = 4; far_z = 5; } else { near_z = 5; far_z = 4; }
+
+ IsectPrecalc isect_precalc;
+ triangle_intersect_precalc(dir, &isect_precalc);
+
+ /* Traversal loop. */
+ do {
+ do {
+ /* Traverse internal nodes. */
+ while(nodeAddr >= 0 && nodeAddr != ENTRYPOINT_SENTINEL) {
+ ssef dist;
+ int traverseChild = qbvh_node_intersect(kg,
+ tnear,
+ tfar,
+#ifdef __KERNEL_AVX2__
+ P_idir4,
+#else
+ org,
+#endif
+ idir4,
+ near_x, near_y, near_z,
+ far_x, far_y, far_z,
+ nodeAddr,
+ &dist);
+
+ if(traverseChild != 0) {
+ float4 cnodes = kernel_tex_fetch(__bvh_nodes, nodeAddr*BVH_QNODE_SIZE+6);
+
+ /* One child is hit, continue with that child. */
+ int r = __bscf(traverseChild);
+ if(traverseChild == 0) {
+ nodeAddr = __float_as_int(cnodes[r]);
+ continue;
+ }
+
+ /* Two children are hit, push far child, and continue with
+ * closer child.
+ */
+ int c0 = __float_as_int(cnodes[r]);
+ float d0 = ((float*)&dist)[r];
+ r = __bscf(traverseChild);
+ int c1 = __float_as_int(cnodes[r]);
+ float d1 = ((float*)&dist)[r];
+ if(traverseChild == 0) {
+ if(d1 < d0) {
+ nodeAddr = c1;
+ ++stackPtr;
+ kernel_assert(stackPtr < BVH_QSTACK_SIZE);
+ traversalStack[stackPtr].addr = c0;
+ traversalStack[stackPtr].dist = d0;
+ continue;
+ }
+ else {
+ nodeAddr = c0;
+ ++stackPtr;
+ kernel_assert(stackPtr < BVH_QSTACK_SIZE);
+ traversalStack[stackPtr].addr = c1;
+ traversalStack[stackPtr].dist = d1;
+ continue;
+ }
+ }
+
+ /* Here starts the slow path for 3 or 4 hit children. We push
+ * all nodes onto the stack to sort them there.
+ */
+ ++stackPtr;
+ kernel_assert(stackPtr < BVH_QSTACK_SIZE);
+ traversalStack[stackPtr].addr = c1;
+ traversalStack[stackPtr].dist = d1;
+ ++stackPtr;
+ kernel_assert(stackPtr < BVH_QSTACK_SIZE);
+ traversalStack[stackPtr].addr = c0;
+ traversalStack[stackPtr].dist = d0;
+
+ /* Three children are hit, push all onto stack and sort 3
+ * stack items, continue with closest child.
+ */
+ r = __bscf(traverseChild);
+ int c2 = __float_as_int(cnodes[r]);
+ float d2 = ((float*)&dist)[r];
+ if(traverseChild == 0) {
+ ++stackPtr;
+ kernel_assert(stackPtr < BVH_QSTACK_SIZE);
+ traversalStack[stackPtr].addr = c2;
+ traversalStack[stackPtr].dist = d2;
+ qbvh_stack_sort(&traversalStack[stackPtr],
+ &traversalStack[stackPtr - 1],
+ &traversalStack[stackPtr - 2]);
+ nodeAddr = traversalStack[stackPtr].addr;
+ --stackPtr;
+ continue;
+ }
+
+ /* Four children are hit, push all onto stack and sort 4
+ * stack items, continue with closest child.
+ */
+ r = __bscf(traverseChild);
+ int c3 = __float_as_int(cnodes[r]);
+ float d3 = ((float*)&dist)[r];
+ ++stackPtr;
+ kernel_assert(stackPtr < BVH_QSTACK_SIZE);
+ traversalStack[stackPtr].addr = c3;
+ traversalStack[stackPtr].dist = d3;
+ ++stackPtr;
+ kernel_assert(stackPtr < BVH_QSTACK_SIZE);
+ traversalStack[stackPtr].addr = c2;
+ traversalStack[stackPtr].dist = d2;
+ qbvh_stack_sort(&traversalStack[stackPtr],
+ &traversalStack[stackPtr - 1],
+ &traversalStack[stackPtr - 2],
+ &traversalStack[stackPtr - 3]);
+ }
+
+ nodeAddr = traversalStack[stackPtr].addr;
+ --stackPtr;
+ }
+
+ /* If node is leaf, fetch triangle list. */
+ if(nodeAddr < 0) {
+ float4 leaf = kernel_tex_fetch(__bvh_leaf_nodes, (-nodeAddr-1)*BVH_QNODE_LEAF_SIZE);
+ int primAddr = __float_as_int(leaf.x);
+
+#if BVH_FEATURE(BVH_INSTANCING)
+ if(primAddr >= 0) {
+#endif
+ int primAddr2 = __float_as_int(leaf.y);
+ const uint type = __float_as_int(leaf.w);
+
+ /* Pop. */
+ nodeAddr = traversalStack[stackPtr].addr;
+ --stackPtr;
+
+ /* Primitive intersection. */
+ switch(type & PRIMITIVE_ALL) {
+ case PRIMITIVE_TRIANGLE: {
+ /* Intersect ray against primitive, */
+ for(; primAddr < primAddr2; primAddr++) {
+ kernel_assert(kernel_tex_fetch(__prim_type, primAddr) == type);
+ /* Only primitives from the same object. */
+ uint tri_object = (object == OBJECT_NONE)? kernel_tex_fetch(__prim_object, primAddr): object;
+ if(tri_object != subsurface_object) {
+ continue;
+ }
+ triangle_intersect_subsurface(kg, &isect_precalc, isect_array, P, object, primAddr, isect_t, &num_hits, lcg_state, max_hits);
+ }
+ break;
+ }
+#if BVH_FEATURE(BVH_MOTION)
+ case PRIMITIVE_MOTION_TRIANGLE: {
+ /* Intersect ray against primitive. */
+ for(; primAddr < primAddr2; primAddr++) {
+ kernel_assert(kernel_tex_fetch(__prim_type, primAddr) == type);
+ /* Only primitives from the same object. */
+ uint tri_object = (object == OBJECT_NONE)? kernel_tex_fetch(__prim_object, primAddr): object;
+ if(tri_object != subsurface_object) {
+ continue;
+ }
+ motion_triangle_intersect_subsurface(kg, isect_array, P, dir, ray->time, object, primAddr, isect_t, &num_hits, lcg_state, max_hits);
+ }
+ break;
+ }
+#endif
+ default:
+ break;
+ }
+ }
+#if BVH_FEATURE(BVH_INSTANCING)
+ else {
+ /* Instance push. */
+ if(subsurface_object == kernel_tex_fetch(__prim_object, -primAddr-1)) {
+ object = subsurface_object;
+
+#if BVH_FEATURE(BVH_MOTION)
+ bvh_instance_motion_push(kg, object, ray, &P, &dir, &idir, &isect_t, &ob_tfm);
+#else
+ bvh_instance_push(kg, object, ray, &P, &dir, &idir, &isect_t);
+#endif
+
+ if(idir.x >= 0.0f) { near_x = 0; far_x = 1; } else { near_x = 1; far_x = 0; }
+ if(idir.y >= 0.0f) { near_y = 2; far_y = 3; } else { near_y = 3; far_y = 2; }
+ if(idir.z >= 0.0f) { near_z = 4; far_z = 5; } else { near_z = 5; far_z = 4; }
+ tfar = ssef(isect_t);
+ idir4 = sse3f(ssef(idir.x), ssef(idir.y), ssef(idir.z));
+#ifdef __KERNEL_AVX2__
+ P_idir = P*idir;
+ P_idir4 = sse3f(P_idir.x, P_idir.y, P_idir.z);
+#else
+ org = sse3f(ssef(P.x), ssef(P.y), ssef(P.z));
+#endif
+ triangle_intersect_precalc(dir, &isect_precalc);
+
+ ++stackPtr;
+ kernel_assert(stackPtr < BVH_QSTACK_SIZE);
+ traversalStack[stackPtr].addr = ENTRYPOINT_SENTINEL;
+
+ nodeAddr = kernel_tex_fetch(__object_node, object);
+ }
+ else {
+ /* Pop. */
+ nodeAddr = traversalStack[stackPtr].addr;
+ --stackPtr;
+ }
+
+ }
+ }
+#endif /* FEATURE(BVH_INSTANCING) */
+ } while(nodeAddr != ENTRYPOINT_SENTINEL);
+
+#if BVH_FEATURE(BVH_INSTANCING)
+ if(stackPtr >= 0) {
+ kernel_assert(object != OBJECT_NONE);
+
+ /* Instance pop. */
+#if BVH_FEATURE(BVH_MOTION)
+ bvh_instance_motion_pop(kg, object, ray, &P, &dir, &idir, &isect_t, &ob_tfm);
+#else
+ bvh_instance_pop(kg, object, ray, &P, &dir, &idir, &isect_t);
+#endif
+
+ if(idir.x >= 0.0f) { near_x = 0; far_x = 1; } else { near_x = 1; far_x = 0; }
+ if(idir.y >= 0.0f) { near_y = 2; far_y = 3; } else { near_y = 3; far_y = 2; }
+ if(idir.z >= 0.0f) { near_z = 4; far_z = 5; } else { near_z = 5; far_z = 4; }
+ tfar = ssef(isect_t);
+ idir4 = sse3f(ssef(idir.x), ssef(idir.y), ssef(idir.z));
+#ifdef __KERNEL_AVX2__
+ P_idir = P*idir;
+ P_idir4 = sse3f(P_idir.x, P_idir.y, P_idir.z);
+#else
+ org = sse3f(ssef(P.x), ssef(P.y), ssef(P.z));
+#endif
+ triangle_intersect_precalc(dir, &isect_precalc);
+
+ object = OBJECT_NONE;
+ nodeAddr = traversalStack[stackPtr].addr;
+ --stackPtr;
+ }
+#endif /* FEATURE(BVH_INSTANCING) */
+ } while(nodeAddr != ENTRYPOINT_SENTINEL);
+
+ return num_hits;
+}
diff --git a/intern/cycles/kernel/geom/geom_qbvh_traversal.h b/intern/cycles/kernel/geom/geom_qbvh_traversal.h
new file mode 100644
index 00000000000..7e356ea062b
--- /dev/null
+++ b/intern/cycles/kernel/geom/geom_qbvh_traversal.h
@@ -0,0 +1,425 @@
+/*
+ * Adapted from code Copyright 2009-2010 NVIDIA Corporation,
+ * and code copyright 2009-2012 Intel Corporation
+ *
+ * Modifications Copyright 2011-2014, Blender Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* This is a template BVH traversal function, where various features can be
+ * enabled/disabled. This way we can compile optimized versions for each case
+ * without new features slowing things down.
+ *
+ * BVH_INSTANCING: object instancing
+ * BVH_HAIR: hair curve rendering
+ * BVH_HAIR_MINIMUM_WIDTH: hair curve rendering with minimum width
+ * BVH_MOTION: motion blur rendering
+ *
+ */
+
+ccl_device bool BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg,
+ const Ray *ray,
+ Intersection *isect,
+ const uint visibility
+#if BVH_FEATURE(BVH_HAIR_MINIMUM_WIDTH)
+ ,uint *lcg_state,
+ float difl,
+ float extmax
+#endif
+ )
+{
+ /* TODO(sergey):
+ * - Test if pushing distance on the stack helps (for non shadow rays).
+ * - Separate version for shadow rays.
+ * - Likely and unlikely for if() statements.
+ * - Test restrict attribute for pointers.
+ */
+
+ /* Traversal stack in CUDA thread-local memory. */
+ QBVHStackItem traversalStack[BVH_QSTACK_SIZE];
+ traversalStack[0].addr = ENTRYPOINT_SENTINEL;
+ traversalStack[0].dist = -FLT_MAX;
+
+ /* Traversal variables in registers. */
+ int stackPtr = 0;
+ int nodeAddr = kernel_data.bvh.root;
+ float nodeDist = -FLT_MAX;
+
+ /* Ray parameters in registers. */
+ float3 P = ray->P;
+ float3 dir = bvh_clamp_direction(ray->D);
+ float3 idir = bvh_inverse_direction(dir);
+ int object = OBJECT_NONE;
+
+#if BVH_FEATURE(BVH_MOTION)
+ Transform ob_tfm;
+#endif
+
+#ifndef __KERNEL_SSE41__
+ if(!isfinite(P.x)) {
+ return false;
+ }
+#endif
+
+ isect->t = ray->t;
+ isect->u = 0.0f;
+ isect->v = 0.0f;
+ isect->prim = PRIM_NONE;
+ isect->object = OBJECT_NONE;
+
+#if defined(__KERNEL_DEBUG__)
+ isect->num_traversal_steps = 0;
+ isect->num_traversed_instances = 0;
+#endif
+
+ ssef tnear(0.0f), tfar(ray->t);
+ sse3f idir4(ssef(idir.x), ssef(idir.y), ssef(idir.z));
+
+#ifdef __KERNEL_AVX2__
+ float3 P_idir = P*idir;
+ sse3f P_idir4 = sse3f(P_idir.x, P_idir.y, P_idir.z);
+#else
+ sse3f org = sse3f(ssef(P.x), ssef(P.y), ssef(P.z));
+#endif
+
+ /* Offsets to select the side that becomes the lower or upper bound. */
+ int near_x, near_y, near_z;
+ int far_x, far_y, far_z;
+
+ if(idir.x >= 0.0f) { near_x = 0; far_x = 1; } else { near_x = 1; far_x = 0; }
+ if(idir.y >= 0.0f) { near_y = 2; far_y = 3; } else { near_y = 3; far_y = 2; }
+ if(idir.z >= 0.0f) { near_z = 4; far_z = 5; } else { near_z = 5; far_z = 4; }
+
+ IsectPrecalc isect_precalc;
+ triangle_intersect_precalc(dir, &isect_precalc);
+
+ /* Traversal loop. */
+ do {
+ do {
+ /* Traverse internal nodes. */
+ while(nodeAddr >= 0 && nodeAddr != ENTRYPOINT_SENTINEL) {
+ if(UNLIKELY(nodeDist > isect->t)) {
+ /* Pop. */
+ nodeAddr = traversalStack[stackPtr].addr;
+ nodeDist = traversalStack[stackPtr].dist;
+ --stackPtr;
+ continue;
+ }
+
+ int traverseChild;
+ ssef dist;
+
+#if defined(__KERNEL_DEBUG__)
+ isect->num_traversal_steps++;
+#endif
+
+#if BVH_FEATURE(BVH_HAIR_MINIMUM_WIDTH)
+ if(difl != 0.0f) {
+ /* NOTE: We extend all the child BB instead of fetching
+ * and checking visibility flags for each of the,
+ *
+ * Need to test if doing opposite would be any faster.
+ */
+ traverseChild = qbvh_node_intersect_robust(kg,
+ tnear,
+ tfar,
+#ifdef __KERNEL_AVX2__
+ P_idir4,
+#else
+ org,
+#endif
+ idir4,
+ near_x, near_y, near_z,
+ far_x, far_y, far_z,
+ nodeAddr,
+ difl,
+ &dist);
+ }
+ else
+#endif
+ {
+ traverseChild = qbvh_node_intersect(kg,
+ tnear,
+ tfar,
+#ifdef __KERNEL_AVX2__
+ P_idir4,
+#else
+ org,
+#endif
+ idir4,
+ near_x, near_y, near_z,
+ far_x, far_y, far_z,
+ nodeAddr,
+ &dist);
+ }
+
+ if(traverseChild != 0) {
+ float4 cnodes = kernel_tex_fetch(__bvh_nodes, nodeAddr*BVH_QNODE_SIZE+6);
+
+ /* One child is hit, continue with that child. */
+ int r = __bscf(traverseChild);
+ float d0 = ((float*)&dist)[r];
+ if(traverseChild == 0) {
+ nodeAddr = __float_as_int(cnodes[r]);
+ nodeDist = d0;
+ continue;
+ }
+
+ /* Two children are hit, push far child, and continue with
+ * closer child.
+ */
+ int c0 = __float_as_int(cnodes[r]);
+ r = __bscf(traverseChild);
+ int c1 = __float_as_int(cnodes[r]);
+ float d1 = ((float*)&dist)[r];
+ if(traverseChild == 0) {
+ if(d1 < d0) {
+ nodeAddr = c1;
+ nodeDist = d1;
+ ++stackPtr;
+ kernel_assert(stackPtr < BVH_QSTACK_SIZE);
+ traversalStack[stackPtr].addr = c0;
+ traversalStack[stackPtr].dist = d0;
+ continue;
+ }
+ else {
+ nodeAddr = c0;
+ nodeDist = d0;
+ ++stackPtr;
+ kernel_assert(stackPtr < BVH_QSTACK_SIZE);
+ traversalStack[stackPtr].addr = c1;
+ traversalStack[stackPtr].dist = d1;
+ continue;
+ }
+ }
+
+ /* Here starts the slow path for 3 or 4 hit children. We push
+ * all nodes onto the stack to sort them there.
+ */
+ ++stackPtr;
+ kernel_assert(stackPtr < BVH_QSTACK_SIZE);
+ traversalStack[stackPtr].addr = c1;
+ traversalStack[stackPtr].dist = d1;
+ ++stackPtr;
+ kernel_assert(stackPtr < BVH_QSTACK_SIZE);
+ traversalStack[stackPtr].addr = c0;
+ traversalStack[stackPtr].dist = d0;
+
+ /* Three children are hit, push all onto stack and sort 3
+ * stack items, continue with closest child.
+ */
+ r = __bscf(traverseChild);
+ int c2 = __float_as_int(cnodes[r]);
+ float d2 = ((float*)&dist)[r];
+ if(traverseChild == 0) {
+ ++stackPtr;
+ kernel_assert(stackPtr < BVH_QSTACK_SIZE);
+ traversalStack[stackPtr].addr = c2;
+ traversalStack[stackPtr].dist = d2;
+ qbvh_stack_sort(&traversalStack[stackPtr],
+ &traversalStack[stackPtr - 1],
+ &traversalStack[stackPtr - 2]);
+ nodeAddr = traversalStack[stackPtr].addr;
+ nodeDist = traversalStack[stackPtr].dist;
+ --stackPtr;
+ continue;
+ }
+
+ /* Four children are hit, push all onto stack and sort 4
+ * stack items, continue with closest child.
+ */
+ r = __bscf(traverseChild);
+ int c3 = __float_as_int(cnodes[r]);
+ float d3 = ((float*)&dist)[r];
+ ++stackPtr;
+ kernel_assert(stackPtr < BVH_QSTACK_SIZE);
+ traversalStack[stackPtr].addr = c3;
+ traversalStack[stackPtr].dist = d3;
+ ++stackPtr;
+ kernel_assert(stackPtr < BVH_QSTACK_SIZE);
+ traversalStack[stackPtr].addr = c2;
+ traversalStack[stackPtr].dist = d2;
+ qbvh_stack_sort(&traversalStack[stackPtr],
+ &traversalStack[stackPtr - 1],
+ &traversalStack[stackPtr - 2],
+ &traversalStack[stackPtr - 3]);
+ }
+
+ nodeAddr = traversalStack[stackPtr].addr;
+ nodeDist = traversalStack[stackPtr].dist;
+ --stackPtr;
+ }
+
+ /* If node is leaf, fetch triangle list. */
+ if(nodeAddr < 0) {
+ float4 leaf = kernel_tex_fetch(__bvh_leaf_nodes, (-nodeAddr-1)*BVH_QNODE_LEAF_SIZE);
+
+#ifdef __VISIBILITY_FLAG__
+ if(UNLIKELY((nodeDist > isect->t) || ((__float_as_uint(leaf.z) & visibility) == 0)))
+#else
+ if(UNLIKELY((nodeDist > isect->t)))
+#endif
+ {
+ /* Pop. */
+ nodeAddr = traversalStack[stackPtr].addr;
+ nodeDist = traversalStack[stackPtr].dist;
+ --stackPtr;
+ continue;
+ }
+
+ int primAddr = __float_as_int(leaf.x);
+
+#if BVH_FEATURE(BVH_INSTANCING)
+ if(primAddr >= 0) {
+#endif
+ int primAddr2 = __float_as_int(leaf.y);
+ const uint type = __float_as_int(leaf.w);
+
+ /* Pop. */
+ nodeAddr = traversalStack[stackPtr].addr;
+ nodeDist = traversalStack[stackPtr].dist;
+ --stackPtr;
+
+ /* Primitive intersection. */
+ switch(type & PRIMITIVE_ALL) {
+ case PRIMITIVE_TRIANGLE: {
+ for(; primAddr < primAddr2; primAddr++) {
+#if defined(__KERNEL_DEBUG__)
+ isect->num_traversal_steps++;
+#endif
+ kernel_assert(kernel_tex_fetch(__prim_type, primAddr) == type);
+ if(triangle_intersect(kg, &isect_precalc, isect, P, visibility, object, primAddr)) {
+ tfar = ssef(isect->t);
+ /* Shadow ray early termination. */
+ if(visibility == PATH_RAY_SHADOW_OPAQUE)
+ return true;
+ }
+ }
+ break;
+ }
+#if BVH_FEATURE(BVH_MOTION)
+ case PRIMITIVE_MOTION_TRIANGLE: {
+ for(; primAddr < primAddr2; primAddr++) {
+#if defined(__KERNEL_DEBUG__)
+ isect->num_traversal_steps++;
+#endif
+ kernel_assert(kernel_tex_fetch(__prim_type, primAddr) == type);
+ if(motion_triangle_intersect(kg, isect, P, dir, ray->time, visibility, object, primAddr)) {
+ tfar = ssef(isect->t);
+ /* Shadow ray early termination. */
+ if(visibility == PATH_RAY_SHADOW_OPAQUE)
+ return true;
+ }
+ }
+ break;
+ }
+#endif /* BVH_FEATURE(BVH_MOTION) */
+#if BVH_FEATURE(BVH_HAIR)
+ case PRIMITIVE_CURVE:
+ case PRIMITIVE_MOTION_CURVE: {
+ for(; primAddr < primAddr2; primAddr++) {
+#if defined(__KERNEL_DEBUG__)
+ isect->num_traversal_steps++;
+#endif
+ kernel_assert(kernel_tex_fetch(__prim_type, primAddr) == type);
+ bool hit;
+ if(kernel_data.curve.curveflags & CURVE_KN_INTERPOLATE)
+ hit = bvh_cardinal_curve_intersect(kg, isect, P, dir, visibility, object, primAddr, ray->time, type, lcg_state, difl, extmax);
+ else
+ hit = bvh_curve_intersect(kg, isect, P, dir, visibility, object, primAddr, ray->time, type, lcg_state, difl, extmax);
+ if(hit) {
+ tfar = ssef(isect->t);
+ /* Shadow ray early termination. */
+ if(visibility == PATH_RAY_SHADOW_OPAQUE)
+ return true;
+ }
+ }
+ break;
+ }
+#endif /* BVH_FEATURE(BVH_HAIR) */
+ }
+ }
+#if BVH_FEATURE(BVH_INSTANCING)
+ else {
+ /* Instance push. */
+ object = kernel_tex_fetch(__prim_object, -primAddr-1);
+
+#if BVH_FEATURE(BVH_MOTION)
+ qbvh_instance_motion_push(kg, object, ray, &P, &dir, &idir, &isect->t, &nodeDist, &ob_tfm);
+#else
+ qbvh_instance_push(kg, object, ray, &P, &dir, &idir, &isect->t, &nodeDist);
+#endif
+
+ if(idir.x >= 0.0f) { near_x = 0; far_x = 1; } else { near_x = 1; far_x = 0; }
+ if(idir.y >= 0.0f) { near_y = 2; far_y = 3; } else { near_y = 3; far_y = 2; }
+ if(idir.z >= 0.0f) { near_z = 4; far_z = 5; } else { near_z = 5; far_z = 4; }
+ tfar = ssef(isect->t);
+ idir4 = sse3f(ssef(idir.x), ssef(idir.y), ssef(idir.z));
+#ifdef __KERNEL_AVX2__
+ P_idir = P*idir;
+ P_idir4 = sse3f(P_idir.x, P_idir.y, P_idir.z);
+#else
+ org = sse3f(ssef(P.x), ssef(P.y), ssef(P.z));
+#endif
+ triangle_intersect_precalc(dir, &isect_precalc);
+
+ ++stackPtr;
+ kernel_assert(stackPtr < BVH_QSTACK_SIZE);
+ traversalStack[stackPtr].addr = ENTRYPOINT_SENTINEL;
+ traversalStack[stackPtr].dist = -FLT_MAX;
+
+ nodeAddr = kernel_tex_fetch(__object_node, object);
+
+#if defined(__KERNEL_DEBUG__)
+ isect->num_traversed_instances++;
+#endif
+ }
+ }
+#endif /* FEATURE(BVH_INSTANCING) */
+ } while(nodeAddr != ENTRYPOINT_SENTINEL);
+
+#if BVH_FEATURE(BVH_INSTANCING)
+ if(stackPtr >= 0) {
+ kernel_assert(object != OBJECT_NONE);
+
+ /* Instance pop. */
+#if BVH_FEATURE(BVH_MOTION)
+ bvh_instance_motion_pop(kg, object, ray, &P, &dir, &idir, &isect->t, &ob_tfm);
+#else
+ bvh_instance_pop(kg, object, ray, &P, &dir, &idir, &isect->t);
+#endif
+
+ if(idir.x >= 0.0f) { near_x = 0; far_x = 1; } else { near_x = 1; far_x = 0; }
+ if(idir.y >= 0.0f) { near_y = 2; far_y = 3; } else { near_y = 3; far_y = 2; }
+ if(idir.z >= 0.0f) { near_z = 4; far_z = 5; } else { near_z = 5; far_z = 4; }
+ tfar = ssef(isect->t);
+ idir4 = sse3f(ssef(idir.x), ssef(idir.y), ssef(idir.z));
+#ifdef __KERNEL_AVX2__
+ P_idir = P*idir;
+ P_idir4 = sse3f(P_idir.x, P_idir.y, P_idir.z);
+#else
+ org = sse3f(ssef(P.x), ssef(P.y), ssef(P.z));
+#endif
+ triangle_intersect_precalc(dir, &isect_precalc);
+
+ object = OBJECT_NONE;
+ nodeAddr = traversalStack[stackPtr].addr;
+ nodeDist = traversalStack[stackPtr].dist;
+ --stackPtr;
+ }
+#endif /* FEATURE(BVH_INSTANCING) */
+ } while(nodeAddr != ENTRYPOINT_SENTINEL);
+
+ return (isect->prim != PRIM_NONE);
+}
diff --git a/intern/cycles/kernel/geom/geom_qbvh_volume.h b/intern/cycles/kernel/geom/geom_qbvh_volume.h
new file mode 100644
index 00000000000..d8cfa3a4061
--- /dev/null
+++ b/intern/cycles/kernel/geom/geom_qbvh_volume.h
@@ -0,0 +1,351 @@
+/*
+ * Adapted from code Copyright 2009-2010 NVIDIA Corporation,
+ * and code copyright 2009-2012 Intel Corporation
+ *
+ * Modifications Copyright 2011-2014, Blender Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* This is a template BVH traversal function for volumes, where
+ * various features can be enabled/disabled. This way we can compile optimized
+ * versions for each case without new features slowing things down.
+ *
+ * BVH_INSTANCING: object instancing
+ * BVH_HAIR: hair curve rendering
+ * BVH_MOTION: motion blur rendering
+ *
+ */
+
+ccl_device bool BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg,
+ const Ray *ray,
+ Intersection *isect)
+{
+ /* TODO(sergey):
+ * - Test if pushing distance on the stack helps.
+ * - Likely and unlikely for if() statements.
+ * - Test restrict attribute for pointers.
+ */
+
+ /* Traversal stack in CUDA thread-local memory. */
+ QBVHStackItem traversalStack[BVH_QSTACK_SIZE];
+ traversalStack[0].addr = ENTRYPOINT_SENTINEL;
+
+ /* Traversal variables in registers. */
+ int stackPtr = 0;
+ int nodeAddr = kernel_data.bvh.root;
+
+ /* Ray parameters in registers. */
+ float3 P = ray->P;
+ float3 dir = bvh_clamp_direction(ray->D);
+ float3 idir = bvh_inverse_direction(dir);
+ int object = OBJECT_NONE;
+
+ const uint visibility = PATH_RAY_ALL_VISIBILITY;
+
+#if BVH_FEATURE(BVH_MOTION)
+ Transform ob_tfm;
+#endif
+
+#ifndef __KERNEL_SSE41__
+ if(!isfinite(P.x)) {
+ return false;
+ }
+#endif
+
+ isect->t = ray->t;
+ isect->u = 0.0f;
+ isect->v = 0.0f;
+ isect->prim = PRIM_NONE;
+ isect->object = OBJECT_NONE;
+
+ ssef tnear(0.0f), tfar(ray->t);
+ sse3f idir4(ssef(idir.x), ssef(idir.y), ssef(idir.z));
+
+#ifdef __KERNEL_AVX2__
+ float3 P_idir = P*idir;
+ sse3f P_idir4 = sse3f(P_idir.x, P_idir.y, P_idir.z);
+#else
+ sse3f org = sse3f(ssef(P.x), ssef(P.y), ssef(P.z));
+#endif
+
+ /* Offsets to select the side that becomes the lower or upper bound. */
+ int near_x, near_y, near_z;
+ int far_x, far_y, far_z;
+
+ if(idir.x >= 0.0f) { near_x = 0; far_x = 1; } else { near_x = 1; far_x = 0; }
+ if(idir.y >= 0.0f) { near_y = 2; far_y = 3; } else { near_y = 3; far_y = 2; }
+ if(idir.z >= 0.0f) { near_z = 4; far_z = 5; } else { near_z = 5; far_z = 4; }
+
+ IsectPrecalc isect_precalc;
+ triangle_intersect_precalc(dir, &isect_precalc);
+
+ /* Traversal loop. */
+ do {
+ do {
+ /* Traverse internal nodes. */
+ while(nodeAddr >= 0 && nodeAddr != ENTRYPOINT_SENTINEL) {
+ ssef dist;
+ int traverseChild = qbvh_node_intersect(kg,
+ tnear,
+ tfar,
+#ifdef __KERNEL_AVX2__
+ P_idir4,
+#else
+ org,
+#endif
+ idir4,
+ near_x, near_y, near_z,
+ far_x, far_y, far_z,
+ nodeAddr,
+ &dist);
+
+ if(traverseChild != 0) {
+ float4 cnodes = kernel_tex_fetch(__bvh_nodes, nodeAddr*BVH_QNODE_SIZE+6);
+
+ /* One child is hit, continue with that child. */
+ int r = __bscf(traverseChild);
+ if(traverseChild == 0) {
+ nodeAddr = __float_as_int(cnodes[r]);
+ continue;
+ }
+
+ /* Two children are hit, push far child, and continue with
+ * closer child.
+ */
+ int c0 = __float_as_int(cnodes[r]);
+ float d0 = ((float*)&dist)[r];
+ r = __bscf(traverseChild);
+ int c1 = __float_as_int(cnodes[r]);
+ float d1 = ((float*)&dist)[r];
+ if(traverseChild == 0) {
+ if(d1 < d0) {
+ nodeAddr = c1;
+ ++stackPtr;
+ kernel_assert(stackPtr < BVH_QSTACK_SIZE);
+ traversalStack[stackPtr].addr = c0;
+ traversalStack[stackPtr].dist = d0;
+ continue;
+ }
+ else {
+ nodeAddr = c0;
+ ++stackPtr;
+ kernel_assert(stackPtr < BVH_QSTACK_SIZE);
+ traversalStack[stackPtr].addr = c1;
+ traversalStack[stackPtr].dist = d1;
+ continue;
+ }
+ }
+
+ /* Here starts the slow path for 3 or 4 hit children. We push
+ * all nodes onto the stack to sort them there.
+ */
+ ++stackPtr;
+ kernel_assert(stackPtr < BVH_QSTACK_SIZE);
+ traversalStack[stackPtr].addr = c1;
+ traversalStack[stackPtr].dist = d1;
+ ++stackPtr;
+ kernel_assert(stackPtr < BVH_QSTACK_SIZE);
+ traversalStack[stackPtr].addr = c0;
+ traversalStack[stackPtr].dist = d0;
+
+ /* Three children are hit, push all onto stack and sort 3
+ * stack items, continue with closest child.
+ */
+ r = __bscf(traverseChild);
+ int c2 = __float_as_int(cnodes[r]);
+ float d2 = ((float*)&dist)[r];
+ if(traverseChild == 0) {
+ ++stackPtr;
+ kernel_assert(stackPtr < BVH_QSTACK_SIZE);
+ traversalStack[stackPtr].addr = c2;
+ traversalStack[stackPtr].dist = d2;
+ qbvh_stack_sort(&traversalStack[stackPtr],
+ &traversalStack[stackPtr - 1],
+ &traversalStack[stackPtr - 2]);
+ nodeAddr = traversalStack[stackPtr].addr;
+ --stackPtr;
+ continue;
+ }
+
+ /* Four children are hit, push all onto stack and sort 4
+ * stack items, continue with closest child.
+ */
+ r = __bscf(traverseChild);
+ int c3 = __float_as_int(cnodes[r]);
+ float d3 = ((float*)&dist)[r];
+ ++stackPtr;
+ kernel_assert(stackPtr < BVH_QSTACK_SIZE);
+ traversalStack[stackPtr].addr = c3;
+ traversalStack[stackPtr].dist = d3;
+ ++stackPtr;
+ kernel_assert(stackPtr < BVH_QSTACK_SIZE);
+ traversalStack[stackPtr].addr = c2;
+ traversalStack[stackPtr].dist = d2;
+ qbvh_stack_sort(&traversalStack[stackPtr],
+ &traversalStack[stackPtr - 1],
+ &traversalStack[stackPtr - 2],
+ &traversalStack[stackPtr - 3]);
+ }
+
+ nodeAddr = traversalStack[stackPtr].addr;
+ --stackPtr;
+ }
+
+ /* If node is leaf, fetch triangle list. */
+ if(nodeAddr < 0) {
+ float4 leaf = kernel_tex_fetch(__bvh_leaf_nodes, (-nodeAddr-1)*BVH_QNODE_LEAF_SIZE);
+ int primAddr = __float_as_int(leaf.x);
+
+#if BVH_FEATURE(BVH_INSTANCING)
+ if(primAddr >= 0) {
+#endif
+ int primAddr2 = __float_as_int(leaf.y);
+ const uint type = __float_as_int(leaf.w);
+ const uint p_type = type & PRIMITIVE_ALL;
+
+ /* Pop. */
+ nodeAddr = traversalStack[stackPtr].addr;
+ --stackPtr;
+
+ /* Primitive intersection. */
+ switch(p_type) {
+ case PRIMITIVE_TRIANGLE: {
+ for(; primAddr < primAddr2; primAddr++) {
+ kernel_assert(kernel_tex_fetch(__prim_type, primAddr) == type);
+ /* Only primitives from volume object. */
+ uint tri_object = (object == OBJECT_NONE)? kernel_tex_fetch(__prim_object, primAddr): object;
+ int object_flag = kernel_tex_fetch(__object_flag, tri_object);
+ if((object_flag & SD_OBJECT_HAS_VOLUME) == 0) {
+ continue;
+ }
+ /* Intersect ray against primitive. */
+ triangle_intersect(kg, &isect_precalc, isect, P, visibility, object, primAddr);
+ }
+ break;
+ }
+#if BVH_FEATURE(BVH_MOTION)
+ case PRIMITIVE_MOTION_TRIANGLE: {
+ for(; primAddr < primAddr2; primAddr++) {
+ kernel_assert(kernel_tex_fetch(__prim_type, primAddr) == type);
+ /* Only primitives from volume object. */
+ uint tri_object = (object == OBJECT_NONE)? kernel_tex_fetch(__prim_object, primAddr): object;
+ int object_flag = kernel_tex_fetch(__object_flag, tri_object);
+ if((object_flag & SD_OBJECT_HAS_VOLUME) == 0) {
+ continue;
+ }
+ /* Intersect ray against primitive. */
+ motion_triangle_intersect(kg, isect, P, dir, ray->time, visibility, object, primAddr);
+ }
+ break;
+ }
+#endif
+#if BVH_FEATURE(BVH_HAIR)
+ case PRIMITIVE_CURVE:
+ case PRIMITIVE_MOTION_CURVE: {
+ for(; primAddr < primAddr2; primAddr++) {
+ kernel_assert(kernel_tex_fetch(__prim_type, primAddr) == type);
+ /* Only primitives from volume object. */
+ uint tri_object = (object == OBJECT_NONE)? kernel_tex_fetch(__prim_object, primAddr): object;
+ int object_flag = kernel_tex_fetch(__object_flag, tri_object);
+ if((object_flag & SD_OBJECT_HAS_VOLUME) == 0) {
+ continue;
+ }
+ /* Intersect ray against primitive. */
+ if(kernel_data.curve.curveflags & CURVE_KN_INTERPOLATE)
+ bvh_cardinal_curve_intersect(kg, isect, P, dir, visibility, object, primAddr, ray->time, type, NULL, 0, 0);
+ else
+ bvh_curve_intersect(kg, isect, P, dir, visibility, object, primAddr, ray->time, type, NULL, 0, 0);
+ }
+ break;
+ }
+#endif
+ }
+ }
+#if BVH_FEATURE(BVH_INSTANCING)
+ else {
+ /* Instance push. */
+ object = kernel_tex_fetch(__prim_object, -primAddr-1);
+ int object_flag = kernel_tex_fetch(__object_flag, object);
+
+ if(object_flag & SD_OBJECT_HAS_VOLUME) {
+
+#if BVH_FEATURE(BVH_MOTION)
+ bvh_instance_motion_push(kg, object, ray, &P, &dir, &idir, &isect->t, &ob_tfm);
+#else
+ bvh_instance_push(kg, object, ray, &P, &dir, &idir, &isect->t);
+#endif
+
+ if(idir.x >= 0.0f) { near_x = 0; far_x = 1; } else { near_x = 1; far_x = 0; }
+ if(idir.y >= 0.0f) { near_y = 2; far_y = 3; } else { near_y = 3; far_y = 2; }
+ if(idir.z >= 0.0f) { near_z = 4; far_z = 5; } else { near_z = 5; far_z = 4; }
+ tfar = ssef(isect->t);
+ idir4 = sse3f(ssef(idir.x), ssef(idir.y), ssef(idir.z));
+#ifdef __KERNEL_AVX2__
+ P_idir = P*idir;
+ P_idir4 = sse3f(P_idir.x, P_idir.y, P_idir.z);
+#else
+ org = sse3f(ssef(P.x), ssef(P.y), ssef(P.z));
+#endif
+ triangle_intersect_precalc(dir, &isect_precalc);
+
+ ++stackPtr;
+ kernel_assert(stackPtr < BVH_QSTACK_SIZE);
+ traversalStack[stackPtr].addr = ENTRYPOINT_SENTINEL;
+
+ nodeAddr = kernel_tex_fetch(__object_node, object);
+ }
+ else {
+ /* Pop. */
+ object = OBJECT_NONE;
+ nodeAddr = traversalStack[stackPtr].addr;
+ --stackPtr;
+ }
+ }
+ }
+#endif /* FEATURE(BVH_INSTANCING) */
+ } while(nodeAddr != ENTRYPOINT_SENTINEL);
+
+#if BVH_FEATURE(BVH_INSTANCING)
+ if(stackPtr >= 0) {
+ kernel_assert(object != OBJECT_NONE);
+
+ /* Instance pop. */
+#if BVH_FEATURE(BVH_MOTION)
+ bvh_instance_motion_pop(kg, object, ray, &P, &dir, &idir, &isect->t, &ob_tfm);
+#else
+ bvh_instance_pop(kg, object, ray, &P, &dir, &idir, &isect->t);
+#endif
+
+ if(idir.x >= 0.0f) { near_x = 0; far_x = 1; } else { near_x = 1; far_x = 0; }
+ if(idir.y >= 0.0f) { near_y = 2; far_y = 3; } else { near_y = 3; far_y = 2; }
+ if(idir.z >= 0.0f) { near_z = 4; far_z = 5; } else { near_z = 5; far_z = 4; }
+ tfar = ssef(isect->t);
+ idir4 = sse3f(ssef(idir.x), ssef(idir.y), ssef(idir.z));
+#ifdef __KERNEL_AVX2__
+ P_idir = P*idir;
+ P_idir4 = sse3f(P_idir.x, P_idir.y, P_idir.z);
+#else
+ org = sse3f(ssef(P.x), ssef(P.y), ssef(P.z));
+#endif
+ triangle_intersect_precalc(dir, &isect_precalc);
+
+ object = OBJECT_NONE;
+ nodeAddr = traversalStack[stackPtr].addr;
+ --stackPtr;
+ }
+#endif /* FEATURE(BVH_INSTANCING) */
+ } while(nodeAddr != ENTRYPOINT_SENTINEL);
+
+ return (isect->prim != PRIM_NONE);
+}
diff --git a/intern/cycles/kernel/geom/geom_qbvh_volume_all.h b/intern/cycles/kernel/geom/geom_qbvh_volume_all.h
new file mode 100644
index 00000000000..056ca9a1ad9
--- /dev/null
+++ b/intern/cycles/kernel/geom/geom_qbvh_volume_all.h
@@ -0,0 +1,446 @@
+/*
+ * Adapted from code Copyright 2009-2010 NVIDIA Corporation,
+ * and code copyright 2009-2012 Intel Corporation
+ *
+ * Modifications Copyright 2011-2014, Blender Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* This is a template BVH traversal function for volumes, where
+ * various features can be enabled/disabled. This way we can compile optimized
+ * versions for each case without new features slowing things down.
+ *
+ * BVH_INSTANCING: object instancing
+ * BVH_HAIR: hair curve rendering
+ * BVH_MOTION: motion blur rendering
+ *
+ */
+
+ccl_device uint BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg,
+ const Ray *ray,
+ Intersection *isect_array,
+ const uint max_hits)
+{
+ /* TODO(sergey):
+ * - Test if pushing distance on the stack helps.
+ * - Likely and unlikely for if() statements.
+ * - Test restrict attribute for pointers.
+ */
+
+ /* Traversal stack in CUDA thread-local memory. */
+ QBVHStackItem traversalStack[BVH_QSTACK_SIZE];
+ traversalStack[0].addr = ENTRYPOINT_SENTINEL;
+
+ /* Traversal variables in registers. */
+ int stackPtr = 0;
+ int nodeAddr = kernel_data.bvh.root;
+
+ /* Ray parameters in registers. */
+ const float tmax = ray->t;
+ float3 P = ray->P;
+ float3 dir = bvh_clamp_direction(ray->D);
+ float3 idir = bvh_inverse_direction(dir);
+ int object = OBJECT_NONE;
+ float isect_t = tmax;
+
+ const uint visibility = PATH_RAY_ALL_VISIBILITY;
+
+#if BVH_FEATURE(BVH_MOTION)
+ Transform ob_tfm;
+#endif
+
+ uint num_hits = 0;
+ isect_array->t = tmax;
+
+#ifndef __KERNEL_SSE41__
+ if(!isfinite(P.x)) {
+ return false;
+ }
+#endif
+
+#if BVH_FEATURE(BVH_INSTANCING)
+ int num_hits_in_instance = 0;
+#endif
+
+ ssef tnear(0.0f), tfar(isect_t);
+ sse3f idir4(ssef(idir.x), ssef(idir.y), ssef(idir.z));
+
+#ifdef __KERNEL_AVX2__
+ float3 P_idir = P*idir;
+ sse3f P_idir4 = sse3f(P_idir.x, P_idir.y, P_idir.z);
+#else
+ sse3f org = sse3f(ssef(P.x), ssef(P.y), ssef(P.z));
+#endif
+
+ /* Offsets to select the side that becomes the lower or upper bound. */
+ int near_x, near_y, near_z;
+ int far_x, far_y, far_z;
+
+ if(idir.x >= 0.0f) { near_x = 0; far_x = 1; } else { near_x = 1; far_x = 0; }
+ if(idir.y >= 0.0f) { near_y = 2; far_y = 3; } else { near_y = 3; far_y = 2; }
+ if(idir.z >= 0.0f) { near_z = 4; far_z = 5; } else { near_z = 5; far_z = 4; }
+
+ IsectPrecalc isect_precalc;
+ triangle_intersect_precalc(dir, &isect_precalc);
+
+ /* Traversal loop. */
+ do {
+ do {
+ /* Traverse internal nodes. */
+ while(nodeAddr >= 0 && nodeAddr != ENTRYPOINT_SENTINEL) {
+ ssef dist;
+ int traverseChild = qbvh_node_intersect(kg,
+ tnear,
+ tfar,
+#ifdef __KERNEL_AVX2__
+ P_idir4,
+#else
+ org,
+#endif
+ idir4,
+ near_x, near_y, near_z,
+ far_x, far_y, far_z,
+ nodeAddr,
+ &dist);
+
+ if(traverseChild != 0) {
+ float4 cnodes = kernel_tex_fetch(__bvh_nodes, nodeAddr*BVH_QNODE_SIZE+6);
+
+ /* One child is hit, continue with that child. */
+ int r = __bscf(traverseChild);
+ if(traverseChild == 0) {
+ nodeAddr = __float_as_int(cnodes[r]);
+ continue;
+ }
+
+ /* Two children are hit, push far child, and continue with
+ * closer child.
+ */
+ int c0 = __float_as_int(cnodes[r]);
+ float d0 = ((float*)&dist)[r];
+ r = __bscf(traverseChild);
+ int c1 = __float_as_int(cnodes[r]);
+ float d1 = ((float*)&dist)[r];
+ if(traverseChild == 0) {
+ if(d1 < d0) {
+ nodeAddr = c1;
+ ++stackPtr;
+ kernel_assert(stackPtr < BVH_QSTACK_SIZE);
+ traversalStack[stackPtr].addr = c0;
+ traversalStack[stackPtr].dist = d0;
+ continue;
+ }
+ else {
+ nodeAddr = c0;
+ ++stackPtr;
+ kernel_assert(stackPtr < BVH_QSTACK_SIZE);
+ traversalStack[stackPtr].addr = c1;
+ traversalStack[stackPtr].dist = d1;
+ continue;
+ }
+ }
+
+ /* Here starts the slow path for 3 or 4 hit children. We push
+ * all nodes onto the stack to sort them there.
+ */
+ ++stackPtr;
+ kernel_assert(stackPtr < BVH_QSTACK_SIZE);
+ traversalStack[stackPtr].addr = c1;
+ traversalStack[stackPtr].dist = d1;
+ ++stackPtr;
+ kernel_assert(stackPtr < BVH_QSTACK_SIZE);
+ traversalStack[stackPtr].addr = c0;
+ traversalStack[stackPtr].dist = d0;
+
+ /* Three children are hit, push all onto stack and sort 3
+ * stack items, continue with closest child.
+ */
+ r = __bscf(traverseChild);
+ int c2 = __float_as_int(cnodes[r]);
+ float d2 = ((float*)&dist)[r];
+ if(traverseChild == 0) {
+ ++stackPtr;
+ kernel_assert(stackPtr < BVH_QSTACK_SIZE);
+ traversalStack[stackPtr].addr = c2;
+ traversalStack[stackPtr].dist = d2;
+ qbvh_stack_sort(&traversalStack[stackPtr],
+ &traversalStack[stackPtr - 1],
+ &traversalStack[stackPtr - 2]);
+ nodeAddr = traversalStack[stackPtr].addr;
+ --stackPtr;
+ continue;
+ }
+
+ /* Four children are hit, push all onto stack and sort 4
+ * stack items, continue with closest child.
+ */
+ r = __bscf(traverseChild);
+ int c3 = __float_as_int(cnodes[r]);
+ float d3 = ((float*)&dist)[r];
+ ++stackPtr;
+ kernel_assert(stackPtr < BVH_QSTACK_SIZE);
+ traversalStack[stackPtr].addr = c3;
+ traversalStack[stackPtr].dist = d3;
+ ++stackPtr;
+ kernel_assert(stackPtr < BVH_QSTACK_SIZE);
+ traversalStack[stackPtr].addr = c2;
+ traversalStack[stackPtr].dist = d2;
+ qbvh_stack_sort(&traversalStack[stackPtr],
+ &traversalStack[stackPtr - 1],
+ &traversalStack[stackPtr - 2],
+ &traversalStack[stackPtr - 3]);
+ }
+
+ nodeAddr = traversalStack[stackPtr].addr;
+ --stackPtr;
+ }
+
+ /* If node is leaf, fetch triangle list. */
+ if(nodeAddr < 0) {
+ float4 leaf = kernel_tex_fetch(__bvh_leaf_nodes, (-nodeAddr-1)*BVH_QNODE_LEAF_SIZE);
+ int primAddr = __float_as_int(leaf.x);
+
+#if BVH_FEATURE(BVH_INSTANCING)
+ if(primAddr >= 0) {
+#endif
+ int primAddr2 = __float_as_int(leaf.y);
+ const uint type = __float_as_int(leaf.w);
+ const uint p_type = type & PRIMITIVE_ALL;
+ bool hit;
+
+ /* Pop. */
+ nodeAddr = traversalStack[stackPtr].addr;
+ --stackPtr;
+
+ /* Primitive intersection. */
+ switch(p_type) {
+ case PRIMITIVE_TRIANGLE: {
+ for(; primAddr < primAddr2; primAddr++) {
+ kernel_assert(kernel_tex_fetch(__prim_type, primAddr) == type);
+ /* Only primitives from volume object. */
+ uint tri_object = (object == OBJECT_NONE)? kernel_tex_fetch(__prim_object, primAddr): object;
+ int object_flag = kernel_tex_fetch(__object_flag, tri_object);
+ if((object_flag & SD_OBJECT_HAS_VOLUME) == 0) {
+ continue;
+ }
+ /* Intersect ray against primitive. */
+ hit = triangle_intersect(kg, &isect_precalc, isect_array, P, visibility, object, primAddr);
+ if(hit) {
+ /* Move on to next entry in intersections array. */
+ isect_array++;
+ num_hits++;
+#if BVH_FEATURE(BVH_INSTANCING)
+ num_hits_in_instance++;
+#endif
+ isect_array->t = isect_t;
+ if(num_hits == max_hits) {
+#if BVH_FEATURE(BVH_INSTANCING)
+#if BVH_FEATURE(BVH_MOTION)
+ float t_fac = len(transform_direction(&ob_tfm, 1.0f/idir));
+#else
+ Transform tfm = object_fetch_transform(kg, object, OBJECT_TRANSFORM);
+ float t_fac = len(transform_direction(&tfm, 1.0f/idir));
+#endif
+ for(int i = 0; i < num_hits_in_instance; i++) {
+ (isect_array-i-1)->t *= t_fac;
+ }
+#endif /* BVH_FEATURE(BVH_INSTANCING) */
+ return num_hits;
+ }
+ }
+ }
+ break;
+ }
+#if BVH_FEATURE(BVH_MOTION)
+ case PRIMITIVE_MOTION_TRIANGLE: {
+ for(; primAddr < primAddr2; primAddr++) {
+ kernel_assert(kernel_tex_fetch(__prim_type, primAddr) == type);
+ /* Only primitives from volume object. */
+ uint tri_object = (object == OBJECT_NONE)? kernel_tex_fetch(__prim_object, primAddr): object;
+ int object_flag = kernel_tex_fetch(__object_flag, tri_object);
+ if((object_flag & SD_OBJECT_HAS_VOLUME) == 0) {
+ continue;
+ }
+ /* Intersect ray against primitive. */
+ hit = motion_triangle_intersect(kg, isect_array, P, dir, ray->time, visibility, object, primAddr);
+ if(hit) {
+ /* Move on to next entry in intersections array. */
+ isect_array++;
+ num_hits++;
+#if BVH_FEATURE(BVH_INSTANCING)
+ num_hits_in_instance++;
+#endif
+ isect_array->t = isect_t;
+ if(num_hits == max_hits) {
+#if BVH_FEATURE(BVH_INSTANCING)
+# if BVH_FEATURE(BVH_MOTION)
+ float t_fac = len(transform_direction(&ob_tfm, 1.0f/idir));
+# else
+ Transform tfm = object_fetch_transform(kg, object, OBJECT_TRANSFORM);
+ float t_fac = len(transform_direction(&tfm, 1.0f/idir));
+#endif
+ for(int i = 0; i < num_hits_in_instance; i++) {
+ (isect_array-i-1)->t *= t_fac;
+ }
+#endif /* BVH_FEATURE(BVH_INSTANCING) */
+ return num_hits;
+ }
+ }
+ }
+ break;
+ }
+#endif
+#if BVH_FEATURE(BVH_HAIR)
+ case PRIMITIVE_CURVE:
+ case PRIMITIVE_MOTION_CURVE: {
+ for(; primAddr < primAddr2; primAddr++) {
+ kernel_assert(kernel_tex_fetch(__prim_type, primAddr) == type);
+ /* Only primitives from volume object. */
+ uint tri_object = (object == OBJECT_NONE)? kernel_tex_fetch(__prim_object, primAddr): object;
+ int object_flag = kernel_tex_fetch(__object_flag, tri_object);
+ if((object_flag & SD_OBJECT_HAS_VOLUME) == 0) {
+ continue;
+ }
+ /* Intersect ray against primitive. */
+ if(kernel_data.curve.curveflags & CURVE_KN_INTERPOLATE)
+ hit = bvh_cardinal_curve_intersect(kg, isect_array, P, dir, visibility, object, primAddr, ray->time, type, NULL, 0, 0);
+ else
+ hit = bvh_curve_intersect(kg, isect_array, P, dir, visibility, object, primAddr, ray->time, type, NULL, 0, 0);
+ if(hit) {
+ /* Move on to next entry in intersections array. */
+ isect_array++;
+ num_hits++;
+#if BVH_FEATURE(BVH_INSTANCING)
+ num_hits_in_instance++;
+#endif
+ isect_array->t = isect_t;
+ if(num_hits == max_hits) {
+#if BVH_FEATURE(BVH_INSTANCING)
+# if BVH_FEATURE(BVH_MOTION)
+ float t_fac = len(transform_direction(&ob_tfm, 1.0f/idir));
+# else
+ Transform tfm = object_fetch_transform(kg, object, OBJECT_TRANSFORM);
+ float t_fac = len(transform_direction(&tfm, 1.0f/idir));
+#endif
+ for(int i = 0; i < num_hits_in_instance; i++) {
+ (isect_array-i-1)->t *= t_fac;
+ }
+#endif /* BVH_FEATURE(BVH_INSTANCING) */
+ return num_hits;
+ }
+ }
+ }
+ break;
+ }
+#endif
+ }
+ }
+#if BVH_FEATURE(BVH_INSTANCING)
+ else {
+ /* Instance push. */
+ object = kernel_tex_fetch(__prim_object, -primAddr-1);
+ int object_flag = kernel_tex_fetch(__object_flag, object);
+
+ if(object_flag & SD_OBJECT_HAS_VOLUME) {
+
+#if BVH_FEATURE(BVH_MOTION)
+ bvh_instance_motion_push(kg, object, ray, &P, &dir, &idir, &isect_t, &ob_tfm);
+#else
+ bvh_instance_push(kg, object, ray, &P, &dir, &idir, &isect_t);
+#endif
+
+ if(idir.x >= 0.0f) { near_x = 0; far_x = 1; } else { near_x = 1; far_x = 0; }
+ if(idir.y >= 0.0f) { near_y = 2; far_y = 3; } else { near_y = 3; far_y = 2; }
+ if(idir.z >= 0.0f) { near_z = 4; far_z = 5; } else { near_z = 5; far_z = 4; }
+ tfar = ssef(isect_t);
+ idir4 = sse3f(ssef(idir.x), ssef(idir.y), ssef(idir.z));
+#ifdef __KERNEL_AVX2__
+ P_idir = P*idir;
+ P_idir4 = sse3f(P_idir.x, P_idir.y, P_idir.z);
+#else
+ org = sse3f(ssef(P.x), ssef(P.y), ssef(P.z));
+#endif
+ triangle_intersect_precalc(dir, &isect_precalc);
+ num_hits_in_instance = 0;
+ isect_array->t = isect_t;
+
+ ++stackPtr;
+ kernel_assert(stackPtr < BVH_QSTACK_SIZE);
+ traversalStack[stackPtr].addr = ENTRYPOINT_SENTINEL;
+
+ nodeAddr = kernel_tex_fetch(__object_node, object);
+ }
+ else {
+ /* Pop. */
+ object = OBJECT_NONE;
+ nodeAddr = traversalStack[stackPtr].addr;
+ --stackPtr;
+ }
+ }
+ }
+#endif /* FEATURE(BVH_INSTANCING) */
+ } while(nodeAddr != ENTRYPOINT_SENTINEL);
+
+#if BVH_FEATURE(BVH_INSTANCING)
+ if(stackPtr >= 0) {
+ kernel_assert(object != OBJECT_NONE);
+
+ /* Instance pop. */
+ if(num_hits_in_instance) {
+ float t_fac;
+#if BVH_FEATURE(BVH_MOTION)
+ bvh_instance_motion_pop_factor(kg, object, ray, &P, &dir, &idir, &t_fac, &ob_tfm);
+#else
+ bvh_instance_pop_factor(kg, object, ray, &P, &dir, &idir, &t_fac);
+#endif
+ triangle_intersect_precalc(dir, &isect_precalc);
+ /* Scale isect->t to adjust for instancing. */
+ for(int i = 0; i < num_hits_in_instance; i++) {
+ (isect_array-i-1)->t *= t_fac;
+ }
+ }
+ else {
+ float ignore_t = FLT_MAX;
+#if BVH_FEATURE(BVH_MOTION)
+ bvh_instance_motion_pop(kg, object, ray, &P, &dir, &idir, &ignore_t, &ob_tfm);
+#else
+ bvh_instance_pop(kg, object, ray, &P, &dir, &idir, &ignore_t);
+#endif
+ triangle_intersect_precalc(dir, &isect_precalc);
+ }
+
+ if(idir.x >= 0.0f) { near_x = 0; far_x = 1; } else { near_x = 1; far_x = 0; }
+ if(idir.y >= 0.0f) { near_y = 2; far_y = 3; } else { near_y = 3; far_y = 2; }
+ if(idir.z >= 0.0f) { near_z = 4; far_z = 5; } else { near_z = 5; far_z = 4; }
+ tfar = ssef(isect_t);
+ idir4 = sse3f(ssef(idir.x), ssef(idir.y), ssef(idir.z));
+#ifdef __KERNEL_AVX2__
+ P_idir = P*idir;
+ P_idir4 = sse3f(P_idir.x, P_idir.y, P_idir.z);
+#else
+ org = sse3f(ssef(P.x), ssef(P.y), ssef(P.z));
+#endif
+ triangle_intersect_precalc(dir, &isect_precalc);
+ isect_t = tmax;
+ isect_array->t = isect_t;
+
+ object = OBJECT_NONE;
+ nodeAddr = traversalStack[stackPtr].addr;
+ --stackPtr;
+ }
+#endif /* FEATURE(BVH_INSTANCING) */
+ } while(nodeAddr != ENTRYPOINT_SENTINEL);
+
+ return num_hits;
+}
diff --git a/intern/cycles/kernel/geom/geom_triangle.h b/intern/cycles/kernel/geom/geom_triangle.h
index 3d3a5e72485..995dfac5b09 100644
--- a/intern/cycles/kernel/geom/geom_triangle.h
+++ b/intern/cycles/kernel/geom/geom_triangle.h
@@ -23,111 +23,18 @@
CCL_NAMESPACE_BEGIN
-/* Refine triangle intersection to more precise hit point. For rays that travel
- * far the precision is often not so good, this reintersects the primitive from
- * a closer distance. */
-
-ccl_device_inline float3 triangle_refine(KernelGlobals *kg, ShaderData *sd, const Intersection *isect, const Ray *ray)
-{
- float3 P = ray->P;
- float3 D = ray->D;
- float t = isect->t;
-
-#ifdef __INTERSECTION_REFINE__
- if(isect->object != OBJECT_NONE) {
-#ifdef __OBJECT_MOTION__
- Transform tfm = sd->ob_itfm;
-#else
- Transform tfm = object_fetch_transform(kg, isect->object, OBJECT_INVERSE_TRANSFORM);
-#endif
-
- P = transform_point(&tfm, P);
- D = transform_direction(&tfm, D*t);
- D = normalize_len(D, &t);
- }
-
- P = P + D*t;
-
- float4 v00 = kernel_tex_fetch(__tri_woop, isect->prim*TRI_NODE_SIZE+0);
- float Oz = v00.w - P.x*v00.x - P.y*v00.y - P.z*v00.z;
- float invDz = 1.0f/(D.x*v00.x + D.y*v00.y + D.z*v00.z);
- float rt = Oz * invDz;
-
- P = P + D*rt;
-
- if(isect->object != OBJECT_NONE) {
-#ifdef __OBJECT_MOTION__
- Transform tfm = sd->ob_tfm;
-#else
- Transform tfm = object_fetch_transform(kg, isect->object, OBJECT_TRANSFORM);
-#endif
-
- P = transform_point(&tfm, P);
- }
-
- return P;
-#else
- return P + D*t;
-#endif
-}
-
-/* same as above, except that isect->t is assumed to be in object space for instancing */
-ccl_device_inline float3 triangle_refine_subsurface(KernelGlobals *kg, ShaderData *sd, const Intersection *isect, const Ray *ray)
-{
- float3 P = ray->P;
- float3 D = ray->D;
- float t = isect->t;
-
-#ifdef __INTERSECTION_REFINE__
- if(isect->object != OBJECT_NONE) {
-#ifdef __OBJECT_MOTION__
- Transform tfm = sd->ob_itfm;
-#else
- Transform tfm = object_fetch_transform(kg, isect->object, OBJECT_INVERSE_TRANSFORM);
-#endif
-
- P = transform_point(&tfm, P);
- D = transform_direction(&tfm, D);
- D = normalize(D);
- }
-
- P = P + D*t;
-
- float4 v00 = kernel_tex_fetch(__tri_woop, isect->prim*TRI_NODE_SIZE+0);
- float Oz = v00.w - P.x*v00.x - P.y*v00.y - P.z*v00.z;
- float invDz = 1.0f/(D.x*v00.x + D.y*v00.y + D.z*v00.z);
- float rt = Oz * invDz;
-
- P = P + D*rt;
-
- if(isect->object != OBJECT_NONE) {
-#ifdef __OBJECT_MOTION__
- Transform tfm = sd->ob_tfm;
-#else
- Transform tfm = object_fetch_transform(kg, isect->object, OBJECT_TRANSFORM);
-#endif
-
- P = transform_point(&tfm, P);
- }
-
- return P;
-#else
- return P + D*t;
-#endif
-}
-
/* normal on triangle */
ccl_device_inline float3 triangle_normal(KernelGlobals *kg, ShaderData *sd)
{
/* load triangle vertices */
- float3 tri_vindex = float4_to_float3(kernel_tex_fetch(__tri_vindex, sd->prim));
+ float4 tri_vindex = kernel_tex_fetch(__tri_vindex, ccl_fetch(sd, prim));
float3 v0 = float4_to_float3(kernel_tex_fetch(__tri_verts, __float_as_int(tri_vindex.x)));
float3 v1 = float4_to_float3(kernel_tex_fetch(__tri_verts, __float_as_int(tri_vindex.y)));
float3 v2 = float4_to_float3(kernel_tex_fetch(__tri_verts, __float_as_int(tri_vindex.z)));
/* return normal */
- if(sd->flag & SD_NEGATIVE_SCALE_APPLIED)
+ if(ccl_fetch(sd, flag) & SD_NEGATIVE_SCALE_APPLIED)
return normalize(cross(v2 - v0, v1 - v0));
else
return normalize(cross(v1 - v0, v2 - v0));
@@ -137,7 +44,7 @@ ccl_device_inline float3 triangle_normal(KernelGlobals *kg, ShaderData *sd)
ccl_device_inline void triangle_point_normal(KernelGlobals *kg, int object, int prim, float u, float v, float3 *P, float3 *Ng, int *shader)
{
/* load triangle vertices */
- float3 tri_vindex = float4_to_float3(kernel_tex_fetch(__tri_vindex, prim));
+ float4 tri_vindex = kernel_tex_fetch(__tri_vindex, prim);
float3 v0 = float4_to_float3(kernel_tex_fetch(__tri_verts, __float_as_int(tri_vindex.x)));
float3 v1 = float4_to_float3(kernel_tex_fetch(__tri_verts, __float_as_int(tri_vindex.y)));
@@ -164,7 +71,7 @@ ccl_device_inline void triangle_point_normal(KernelGlobals *kg, int object, int
ccl_device_inline void triangle_vertices(KernelGlobals *kg, int prim, float3 P[3])
{
- float3 tri_vindex = float4_to_float3(kernel_tex_fetch(__tri_vindex, prim));
+ float4 tri_vindex = kernel_tex_fetch(__tri_vindex, prim);
P[0] = float4_to_float3(kernel_tex_fetch(__tri_verts, __float_as_int(tri_vindex.x)));
P[1] = float4_to_float3(kernel_tex_fetch(__tri_verts, __float_as_int(tri_vindex.y)));
@@ -176,7 +83,7 @@ ccl_device_inline void triangle_vertices(KernelGlobals *kg, int prim, float3 P[3
ccl_device_inline float3 triangle_smooth_normal(KernelGlobals *kg, int prim, float u, float v)
{
/* load triangle vertices */
- float3 tri_vindex = float4_to_float3(kernel_tex_fetch(__tri_vindex, prim));
+ float4 tri_vindex = kernel_tex_fetch(__tri_vindex, prim);
float3 n0 = float4_to_float3(kernel_tex_fetch(__tri_vnormal, __float_as_int(tri_vindex.x)));
float3 n1 = float4_to_float3(kernel_tex_fetch(__tri_vnormal, __float_as_int(tri_vindex.y)));
@@ -187,10 +94,10 @@ ccl_device_inline float3 triangle_smooth_normal(KernelGlobals *kg, int prim, flo
/* Ray differentials on triangle */
-ccl_device_inline void triangle_dPdudv(KernelGlobals *kg, int prim, float3 *dPdu, float3 *dPdv)
+ccl_device_inline void triangle_dPdudv(KernelGlobals *kg, int prim, ccl_addr_space float3 *dPdu, ccl_addr_space float3 *dPdv)
{
/* fetch triangle vertex coordinates */
- float3 tri_vindex = float4_to_float3(kernel_tex_fetch(__tri_vindex, prim));
+ float4 tri_vindex = kernel_tex_fetch(__tri_vindex, prim);
float3 p0 = float4_to_float3(kernel_tex_fetch(__tri_verts, __float_as_int(tri_vindex.x)));
float3 p1 = float4_to_float3(kernel_tex_fetch(__tri_verts, __float_as_int(tri_vindex.y)));
@@ -209,34 +116,34 @@ ccl_device float triangle_attribute_float(KernelGlobals *kg, const ShaderData *s
if(dx) *dx = 0.0f;
if(dy) *dy = 0.0f;
- return kernel_tex_fetch(__attributes_float, offset + sd->prim);
+ return kernel_tex_fetch(__attributes_float, offset + ccl_fetch(sd, prim));
}
else if(elem == ATTR_ELEMENT_VERTEX || elem == ATTR_ELEMENT_VERTEX_MOTION) {
- float3 tri_vindex = float4_to_float3(kernel_tex_fetch(__tri_vindex, sd->prim));
+ float4 tri_vindex = kernel_tex_fetch(__tri_vindex, ccl_fetch(sd, prim));
float f0 = kernel_tex_fetch(__attributes_float, offset + __float_as_int(tri_vindex.x));
float f1 = kernel_tex_fetch(__attributes_float, offset + __float_as_int(tri_vindex.y));
float f2 = kernel_tex_fetch(__attributes_float, offset + __float_as_int(tri_vindex.z));
#ifdef __RAY_DIFFERENTIALS__
- if(dx) *dx = sd->du.dx*f0 + sd->dv.dx*f1 - (sd->du.dx + sd->dv.dx)*f2;
- if(dy) *dy = sd->du.dy*f0 + sd->dv.dy*f1 - (sd->du.dy + sd->dv.dy)*f2;
+ if(dx) *dx = ccl_fetch(sd, du).dx*f0 + ccl_fetch(sd, dv).dx*f1 - (ccl_fetch(sd, du).dx + ccl_fetch(sd, dv).dx)*f2;
+ if(dy) *dy = ccl_fetch(sd, du).dy*f0 + ccl_fetch(sd, dv).dy*f1 - (ccl_fetch(sd, du).dy + ccl_fetch(sd, dv).dy)*f2;
#endif
- return sd->u*f0 + sd->v*f1 + (1.0f - sd->u - sd->v)*f2;
+ return ccl_fetch(sd, u)*f0 + ccl_fetch(sd, v)*f1 + (1.0f - ccl_fetch(sd, u) - ccl_fetch(sd, v))*f2;
}
else if(elem == ATTR_ELEMENT_CORNER) {
- int tri = offset + sd->prim*3;
+ int tri = offset + ccl_fetch(sd, prim)*3;
float f0 = kernel_tex_fetch(__attributes_float, tri + 0);
float f1 = kernel_tex_fetch(__attributes_float, tri + 1);
float f2 = kernel_tex_fetch(__attributes_float, tri + 2);
#ifdef __RAY_DIFFERENTIALS__
- if(dx) *dx = sd->du.dx*f0 + sd->dv.dx*f1 - (sd->du.dx + sd->dv.dx)*f2;
- if(dy) *dy = sd->du.dy*f0 + sd->dv.dy*f1 - (sd->du.dy + sd->dv.dy)*f2;
+ if(dx) *dx = ccl_fetch(sd, du).dx*f0 + ccl_fetch(sd, dv).dx*f1 - (ccl_fetch(sd, du).dx + ccl_fetch(sd, dv).dx)*f2;
+ if(dy) *dy = ccl_fetch(sd, du).dy*f0 + ccl_fetch(sd, dv).dy*f1 - (ccl_fetch(sd, du).dy + ccl_fetch(sd, dv).dy)*f2;
#endif
- return sd->u*f0 + sd->v*f1 + (1.0f - sd->u - sd->v)*f2;
+ return ccl_fetch(sd, u)*f0 + ccl_fetch(sd, v)*f1 + (1.0f - ccl_fetch(sd, u) - ccl_fetch(sd, v))*f2;
}
else {
if(dx) *dx = 0.0f;
@@ -252,24 +159,24 @@ ccl_device float3 triangle_attribute_float3(KernelGlobals *kg, const ShaderData
if(dx) *dx = make_float3(0.0f, 0.0f, 0.0f);
if(dy) *dy = make_float3(0.0f, 0.0f, 0.0f);
- return float4_to_float3(kernel_tex_fetch(__attributes_float3, offset + sd->prim));
+ return float4_to_float3(kernel_tex_fetch(__attributes_float3, offset + ccl_fetch(sd, prim)));
}
else if(elem == ATTR_ELEMENT_VERTEX || elem == ATTR_ELEMENT_VERTEX_MOTION) {
- float3 tri_vindex = float4_to_float3(kernel_tex_fetch(__tri_vindex, sd->prim));
+ float4 tri_vindex = kernel_tex_fetch(__tri_vindex, ccl_fetch(sd, prim));
float3 f0 = float4_to_float3(kernel_tex_fetch(__attributes_float3, offset + __float_as_int(tri_vindex.x)));
float3 f1 = float4_to_float3(kernel_tex_fetch(__attributes_float3, offset + __float_as_int(tri_vindex.y)));
float3 f2 = float4_to_float3(kernel_tex_fetch(__attributes_float3, offset + __float_as_int(tri_vindex.z)));
#ifdef __RAY_DIFFERENTIALS__
- if(dx) *dx = sd->du.dx*f0 + sd->dv.dx*f1 - (sd->du.dx + sd->dv.dx)*f2;
- if(dy) *dy = sd->du.dy*f0 + sd->dv.dy*f1 - (sd->du.dy + sd->dv.dy)*f2;
+ if(dx) *dx = ccl_fetch(sd, du).dx*f0 + ccl_fetch(sd, dv).dx*f1 - (ccl_fetch(sd, du).dx + ccl_fetch(sd, dv).dx)*f2;
+ if(dy) *dy = ccl_fetch(sd, du).dy*f0 + ccl_fetch(sd, dv).dy*f1 - (ccl_fetch(sd, du).dy + ccl_fetch(sd, dv).dy)*f2;
#endif
- return sd->u*f0 + sd->v*f1 + (1.0f - sd->u - sd->v)*f2;
+ return ccl_fetch(sd, u)*f0 + ccl_fetch(sd, v)*f1 + (1.0f - ccl_fetch(sd, u) - ccl_fetch(sd, v))*f2;
}
else if(elem == ATTR_ELEMENT_CORNER || elem == ATTR_ELEMENT_CORNER_BYTE) {
- int tri = offset + sd->prim*3;
+ int tri = offset + ccl_fetch(sd, prim)*3;
float3 f0, f1, f2;
if(elem == ATTR_ELEMENT_CORNER) {
@@ -284,11 +191,11 @@ ccl_device float3 triangle_attribute_float3(KernelGlobals *kg, const ShaderData
}
#ifdef __RAY_DIFFERENTIALS__
- if(dx) *dx = sd->du.dx*f0 + sd->dv.dx*f1 - (sd->du.dx + sd->dv.dx)*f2;
- if(dy) *dy = sd->du.dy*f0 + sd->dv.dy*f1 - (sd->du.dy + sd->dv.dy)*f2;
+ if(dx) *dx = ccl_fetch(sd, du).dx*f0 + ccl_fetch(sd, dv).dx*f1 - (ccl_fetch(sd, du).dx + ccl_fetch(sd, dv).dx)*f2;
+ if(dy) *dy = ccl_fetch(sd, du).dy*f0 + ccl_fetch(sd, dv).dy*f1 - (ccl_fetch(sd, du).dy + ccl_fetch(sd, dv).dy)*f2;
#endif
- return sd->u*f0 + sd->v*f1 + (1.0f - sd->u - sd->v)*f2;
+ return ccl_fetch(sd, u)*f0 + ccl_fetch(sd, v)*f1 + (1.0f - ccl_fetch(sd, u) - ccl_fetch(sd, v))*f2;
}
else {
if(dx) *dx = make_float3(0.0f, 0.0f, 0.0f);
@@ -298,116 +205,4 @@ ccl_device float3 triangle_attribute_float3(KernelGlobals *kg, const ShaderData
}
}
-/* Ray-Triangle intersection for BVH traversal
- *
- * Based on Sven Woop's algorithm with precomputed triangle storage */
-
-ccl_device_inline bool triangle_intersect(KernelGlobals *kg, Intersection *isect,
- float3 P, float3 dir, uint visibility, int object, int triAddr)
-{
- /* compute and check intersection t-value */
- float4 v00 = kernel_tex_fetch(__tri_woop, triAddr*TRI_NODE_SIZE+0);
- float4 v11 = kernel_tex_fetch(__tri_woop, triAddr*TRI_NODE_SIZE+1);
-
- float Oz = v00.w - P.x*v00.x - P.y*v00.y - P.z*v00.z;
- float invDz = 1.0f/(dir.x*v00.x + dir.y*v00.y + dir.z*v00.z);
- float t = Oz * invDz;
-
- if(t > 0.0f && t < isect->t) {
- /* compute and check barycentric u */
- float Ox = v11.w + P.x*v11.x + P.y*v11.y + P.z*v11.z;
- float Dx = dir.x*v11.x + dir.y*v11.y + dir.z*v11.z;
- float u = Ox + t*Dx;
-
- if(u >= 0.0f) {
- /* compute and check barycentric v */
- float4 v22 = kernel_tex_fetch(__tri_woop, triAddr*TRI_NODE_SIZE+2);
- float Oy = v22.w + P.x*v22.x + P.y*v22.y + P.z*v22.z;
- float Dy = dir.x*v22.x + dir.y*v22.y + dir.z*v22.z;
- float v = Oy + t*Dy;
-
- if(v >= 0.0f && u + v <= 1.0f) {
-#ifdef __VISIBILITY_FLAG__
- /* visibility flag test. we do it here under the assumption
- * that most triangles are culled by node flags */
- if(kernel_tex_fetch(__prim_visibility, triAddr) & visibility)
-#endif
- {
- /* record intersection */
- isect->prim = triAddr;
- isect->object = object;
- isect->type = PRIMITIVE_TRIANGLE;
- isect->u = u;
- isect->v = v;
- isect->t = t;
- return true;
- }
- }
- }
- }
-
- return false;
-}
-
-/* Special ray intersection routines for subsurface scattering. In that case we
- * only want to intersect with primitives in the same object, and if case of
- * multiple hits we pick a single random primitive as the intersection point. */
-
-#ifdef __SUBSURFACE__
-ccl_device_inline void triangle_intersect_subsurface(KernelGlobals *kg, Intersection *isect_array,
- float3 P, float3 dir, int object, int triAddr, float tmax, uint *num_hits, uint *lcg_state, int max_hits)
-{
- /* compute and check intersection t-value */
- float4 v00 = kernel_tex_fetch(__tri_woop, triAddr*TRI_NODE_SIZE+0);
- float4 v11 = kernel_tex_fetch(__tri_woop, triAddr*TRI_NODE_SIZE+1);
-
- float Oz = v00.w - P.x*v00.x - P.y*v00.y - P.z*v00.z;
- float invDz = 1.0f/(dir.x*v00.x + dir.y*v00.y + dir.z*v00.z);
- float t = Oz * invDz;
-
- if(t > 0.0f && t < tmax) {
- /* compute and check barycentric u */
- float Ox = v11.w + P.x*v11.x + P.y*v11.y + P.z*v11.z;
- float Dx = dir.x*v11.x + dir.y*v11.y + dir.z*v11.z;
- float u = Ox + t*Dx;
-
- if(u >= 0.0f) {
- /* compute and check barycentric v */
- float4 v22 = kernel_tex_fetch(__tri_woop, triAddr*TRI_NODE_SIZE+2);
- float Oy = v22.w + P.x*v22.x + P.y*v22.y + P.z*v22.z;
- float Dy = dir.x*v22.x + dir.y*v22.y + dir.z*v22.z;
- float v = Oy + t*Dy;
-
- if(v >= 0.0f && u + v <= 1.0f) {
- (*num_hits)++;
-
- int hit;
-
- if(*num_hits <= max_hits) {
- hit = *num_hits - 1;
- }
- else {
- /* reservoir sampling: if we are at the maximum number of
- * hits, randomly replace element or skip it */
- hit = lcg_step_uint(lcg_state) % *num_hits;
-
- if(hit >= max_hits)
- return;
- }
-
- /* record intersection */
- Intersection *isect = &isect_array[hit];
- isect->prim = triAddr;
- isect->object = object;
- isect->type = PRIMITIVE_TRIANGLE;
- isect->u = u;
- isect->v = v;
- isect->t = t;
- }
- }
- }
-}
-#endif
-
CCL_NAMESPACE_END
-
diff --git a/intern/cycles/kernel/geom/geom_triangle_intersect.h b/intern/cycles/kernel/geom/geom_triangle_intersect.h
new file mode 100644
index 00000000000..ba309a1dc53
--- /dev/null
+++ b/intern/cycles/kernel/geom/geom_triangle_intersect.h
@@ -0,0 +1,431 @@
+/*
+ * Copyright 2014, Blender Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* Triangle/Ray intersections.
+ *
+ * For BVH ray intersection we use a precomputed triangle storage to accelerate
+ * intersection at the cost of more memory usage.
+ */
+
+CCL_NAMESPACE_BEGIN
+
+/* Workaround stupidness of CUDA/OpenCL which doesn't allow to access indexed
+ * component of float3 value.
+ */
+#ifndef __KERNEL_CPU__
+# define IDX(vec, idx) \
+ ((idx == 0) ? ((vec).x) : ( (idx == 1) ? ((vec).y) : ((vec).z) ))
+#else
+# define IDX(vec, idx) ((vec)[idx])
+#endif
+
+/* Ray-Triangle intersection for BVH traversal
+ *
+ * Sven Woop
+ * Watertight Ray/Triangle Intersection
+ *
+ * http://jcgt.org/published/0002/01/05/paper.pdf
+ */
+
+/* Precalculated data for the ray->tri intersection. */
+typedef struct IsectPrecalc {
+ /* Maximal dimension kz, and orthogonal dimensions. */
+ int kx, ky, kz;
+
+ /* Shear constants. */
+ float Sx, Sy, Sz;
+} IsectPrecalc;
+
+#if defined(__KERNEL_CUDA__)
+# if (defined(i386) || defined(_M_IX86))
+# if __CUDA_ARCH__ > 500
+ccl_device_noinline
+# else /* __CUDA_ARCH__ > 500 */
+ccl_device_inline
+# endif /* __CUDA_ARCH__ > 500 */
+# else /* (defined(i386) || defined(_M_IX86)) */
+# if defined(__KERNEL_EXPERIMENTAL__) && (__CUDA_ARCH__ >= 500)
+ccl_device_noinline
+# else
+ccl_device_inline
+# endif
+# endif /* (defined(i386) || defined(_M_IX86)) */
+#elif defined(__KERNEL_OPENCL_APPLE__)
+ccl_device_noinline
+#else /* defined(__KERNEL_OPENCL_APPLE__) */
+ccl_device_inline
+#endif /* defined(__KERNEL_OPENCL_APPLE__) */
+void triangle_intersect_precalc(float3 dir,
+ IsectPrecalc *isect_precalc)
+{
+ /* Calculate dimension where the ray direction is maximal. */
+ int kz = util_max_axis(make_float3(fabsf(dir.x),
+ fabsf(dir.y),
+ fabsf(dir.z)));
+ int kx = kz + 1; if(kx == 3) kx = 0;
+ int ky = kx + 1; if(ky == 3) ky = 0;
+
+ /* Swap kx and ky dimensions to preserve winding direction of triangles. */
+ if(IDX(dir, kz) < 0.0f) {
+ int tmp = kx;
+ kx = ky;
+ ky = tmp;
+ }
+
+ /* Calculate the shear constants. */
+ float inv_dir_z = 1.0f / IDX(dir, kz);
+ isect_precalc->Sx = IDX(dir, kx) * inv_dir_z;
+ isect_precalc->Sy = IDX(dir, ky) * inv_dir_z;
+ isect_precalc->Sz = inv_dir_z;
+
+ /* Store the dimensions. */
+ isect_precalc->kx = kx;
+ isect_precalc->ky = ky;
+ isect_precalc->kz = kz;
+}
+
+/* TODO(sergey): Make it general utility function. */
+ccl_device_inline float xor_signmask(float x, int y)
+{
+ return __int_as_float(__float_as_int(x) ^ y);
+}
+
+ccl_device_inline bool triangle_intersect(KernelGlobals *kg,
+ const IsectPrecalc *isect_precalc,
+ Intersection *isect,
+ float3 P,
+ uint visibility,
+ int object,
+ int triAddr)
+{
+ const int kx = isect_precalc->kx;
+ const int ky = isect_precalc->ky;
+ const int kz = isect_precalc->kz;
+ const float Sx = isect_precalc->Sx;
+ const float Sy = isect_precalc->Sy;
+ const float Sz = isect_precalc->Sz;
+
+ /* Calculate vertices relative to ray origin. */
+ const float4 tri_a = kernel_tex_fetch(__tri_woop, triAddr*TRI_NODE_SIZE+0),
+ tri_b = kernel_tex_fetch(__tri_woop, triAddr*TRI_NODE_SIZE+1),
+ tri_c = kernel_tex_fetch(__tri_woop, triAddr*TRI_NODE_SIZE+2);
+ const float3 A = make_float3(tri_a.x - P.x, tri_a.y - P.y, tri_a.z - P.z);
+ const float3 B = make_float3(tri_b.x - P.x, tri_b.y - P.y, tri_b.z - P.z);
+ const float3 C = make_float3(tri_c.x - P.x, tri_c.y - P.y, tri_c.z - P.z);
+
+ const float A_kx = IDX(A, kx), A_ky = IDX(A, ky), A_kz = IDX(A, kz);
+ const float B_kx = IDX(B, kx), B_ky = IDX(B, ky), B_kz = IDX(B, kz);
+ const float C_kx = IDX(C, kx), C_ky = IDX(C, ky), C_kz = IDX(C, kz);
+
+ /* Perform shear and scale of vertices. */
+ const float Ax = A_kx - Sx * A_kz;
+ const float Ay = A_ky - Sy * A_kz;
+ const float Bx = B_kx - Sx * B_kz;
+ const float By = B_ky - Sy * B_kz;
+ const float Cx = C_kx - Sx * C_kz;
+ const float Cy = C_ky - Sy * C_kz;
+
+ /* Calculate scaled barycentric coordinates. */
+ float U = Cx * By - Cy * Bx;
+ float V = Ax * Cy - Ay * Cx;
+ float W = Bx * Ay - By * Ax;
+ const int sign_mask = (__float_as_int(U) & 0x80000000);
+ /* TODO(sergey): Check if multiplication plus sign check is faster
+ * or at least same speed (but robust for endian types).
+ */
+ if(sign_mask != (__float_as_int(V) & 0x80000000) ||
+ sign_mask != (__float_as_int(W) & 0x80000000))
+ {
+ return false;
+ }
+
+ /* Calculate determinant. */
+ float det = U + V + W;
+ if(UNLIKELY(det == 0.0f)) {
+ return false;
+ }
+
+ /* Calculate scaled z-coordinates of vertices and use them to calculate
+ * the hit distance.
+ */
+ const float T = (U * A_kz + V * B_kz + W * C_kz) * Sz;
+ const float sign_T = xor_signmask(T, sign_mask);
+ if((sign_T < 0.0f) ||
+ (sign_T > isect->t * xor_signmask(det, sign_mask)))
+ {
+ return false;
+ }
+
+#ifdef __VISIBILITY_FLAG__
+ /* visibility flag test. we do it here under the assumption
+ * that most triangles are culled by node flags */
+ if(kernel_tex_fetch(__prim_visibility, triAddr) & visibility)
+#endif
+ {
+#ifdef __KERNEL_GPU__
+ float4 a = tri_b - tri_a, b = tri_c - tri_a;
+ if(len_squared(make_float3(a.y*b.z - a.z*b.y,
+ a.z*b.x - a.x*b.z,
+ a.x*b.y - a.y*b.x)) == 0.0f)
+ {
+ return false;
+ }
+#endif
+
+ /* Normalize U, V, W, and T. */
+ const float inv_det = 1.0f / det;
+ isect->prim = triAddr;
+ isect->object = object;
+ isect->type = PRIMITIVE_TRIANGLE;
+ isect->u = U * inv_det;
+ isect->v = V * inv_det;
+ isect->t = T * inv_det;
+ return true;
+ }
+ return false;
+}
+
+/* Special ray intersection routines for subsurface scattering. In that case we
+ * only want to intersect with primitives in the same object, and if case of
+ * multiple hits we pick a single random primitive as the intersection point.
+ */
+
+#ifdef __SUBSURFACE__
+ccl_device_inline void triangle_intersect_subsurface(
+ KernelGlobals *kg,
+ const IsectPrecalc *isect_precalc,
+ Intersection *isect_array,
+ float3 P,
+ int object,
+ int triAddr,
+ float tmax,
+ uint *num_hits,
+ uint *lcg_state,
+ int max_hits)
+{
+ const int kx = isect_precalc->kx;
+ const int ky = isect_precalc->ky;
+ const int kz = isect_precalc->kz;
+ const float Sx = isect_precalc->Sx;
+ const float Sy = isect_precalc->Sy;
+ const float Sz = isect_precalc->Sz;
+
+ /* Calculate vertices relative to ray origin. */
+ const float4 tri_a = kernel_tex_fetch(__tri_woop, triAddr*TRI_NODE_SIZE+0),
+ tri_b = kernel_tex_fetch(__tri_woop, triAddr*TRI_NODE_SIZE+1),
+ tri_c = kernel_tex_fetch(__tri_woop, triAddr*TRI_NODE_SIZE+2);
+ const float3 A = make_float3(tri_a.x - P.x, tri_a.y - P.y, tri_a.z - P.z);
+ const float3 B = make_float3(tri_b.x - P.x, tri_b.y - P.y, tri_b.z - P.z);
+ const float3 C = make_float3(tri_c.x - P.x, tri_c.y - P.y, tri_c.z - P.z);
+
+ const float A_kx = IDX(A, kx), A_ky = IDX(A, ky), A_kz = IDX(A, kz);
+ const float B_kx = IDX(B, kx), B_ky = IDX(B, ky), B_kz = IDX(B, kz);
+ const float C_kx = IDX(C, kx), C_ky = IDX(C, ky), C_kz = IDX(C, kz);
+
+ /* Perform shear and scale of vertices. */
+ const float Ax = A_kx - Sx * A_kz;
+ const float Ay = A_ky - Sy * A_kz;
+ const float Bx = B_kx - Sx * B_kz;
+ const float By = B_ky - Sy * B_kz;
+ const float Cx = C_kx - Sx * C_kz;
+ const float Cy = C_ky - Sy * C_kz;
+
+ /* Calculate scaled barycentric coordinates. */
+ float U = Cx * By - Cy * Bx;
+ int sign_mask = (__float_as_int(U) & 0x80000000);
+ float V = Ax * Cy - Ay * Cx;
+ if(sign_mask != (__float_as_int(V) & 0x80000000)) {
+ return;
+ }
+ float W = Bx * Ay - By * Ax;
+ if(sign_mask != (__float_as_int(W) & 0x80000000)) {
+ return;
+ }
+
+ /* Calculate determinant. */
+ float det = U + V + W;
+ if(UNLIKELY(det == 0.0f)) {
+ return;
+ }
+
+ /* Calculate scaled z−coordinates of vertices and use them to calculate
+ * the hit distance.
+ */
+ const float T = (U * A_kz + V * B_kz + W * C_kz) * Sz;
+ const float sign_T = xor_signmask(T, sign_mask);
+ if((sign_T < 0.0f) ||
+ (sign_T > tmax * xor_signmask(det, sign_mask)))
+ {
+ return;
+ }
+
+ /* Normalize U, V, W, and T. */
+ const float inv_det = 1.0f / det;
+
+ (*num_hits)++;
+ int hit;
+
+ if(*num_hits <= max_hits) {
+ hit = *num_hits - 1;
+ }
+ else {
+ /* reservoir sampling: if we are at the maximum number of
+ * hits, randomly replace element or skip it */
+ hit = lcg_step_uint(lcg_state) % *num_hits;
+
+ if(hit >= max_hits)
+ return;
+ }
+
+ /* record intersection */
+ Intersection *isect = &isect_array[hit];
+ isect->prim = triAddr;
+ isect->object = object;
+ isect->type = PRIMITIVE_TRIANGLE;
+ isect->u = U * inv_det;
+ isect->v = V * inv_det;
+ isect->t = T * inv_det;
+}
+#endif
+
+/* Refine triangle intersection to more precise hit point. For rays that travel
+ * far the precision is often not so good, this reintersects the primitive from
+ * a closer distance. */
+
+/* Reintersections uses the paper:
+ *
+ * Tomas Moeller
+ * Fast, minimum storage ray/triangle intersection
+ * http://www.cs.virginia.edu/~gfx/Courses/2003/ImageSynthesis/papers/Acceleration/Fast%20MinimumStorage%20RayTriangle%20Intersection.pdf
+ */
+
+ccl_device_inline float3 triangle_refine(KernelGlobals *kg,
+ ShaderData *sd,
+ const Intersection *isect,
+ const Ray *ray)
+{
+ float3 P = ray->P;
+ float3 D = ray->D;
+ float t = isect->t;
+
+#ifdef __INTERSECTION_REFINE__
+ if(isect->object != OBJECT_NONE) {
+ if(UNLIKELY(t == 0.0f)) {
+ return P;
+ }
+#ifdef __OBJECT_MOTION__
+ Transform tfm = ccl_fetch(sd, ob_itfm);
+#else
+ Transform tfm = object_fetch_transform(kg, isect->object, OBJECT_INVERSE_TRANSFORM);
+#endif
+
+ P = transform_point(&tfm, P);
+ D = transform_direction(&tfm, D*t);
+ D = normalize_len(D, &t);
+ }
+
+ P = P + D*t;
+
+ const float4 tri_a = kernel_tex_fetch(__tri_woop, isect->prim*TRI_NODE_SIZE+0),
+ tri_b = kernel_tex_fetch(__tri_woop, isect->prim*TRI_NODE_SIZE+1),
+ tri_c = kernel_tex_fetch(__tri_woop, isect->prim*TRI_NODE_SIZE+2);
+ float3 edge1 = make_float3(tri_a.x - tri_c.x, tri_a.y - tri_c.y, tri_a.z - tri_c.z);
+ float3 edge2 = make_float3(tri_b.x - tri_c.x, tri_b.y - tri_c.y, tri_b.z - tri_c.z);
+ float3 tvec = make_float3(P.x - tri_c.x, P.y - tri_c.y, P.z - tri_c.z);
+ float3 qvec = cross(tvec, edge1);
+ float3 pvec = cross(D, edge2);
+ float rt = dot(edge2, qvec) / dot(edge1, pvec);
+
+ P = P + D*rt;
+
+ if(isect->object != OBJECT_NONE) {
+#ifdef __OBJECT_MOTION__
+ Transform tfm = ccl_fetch(sd, ob_tfm);
+#else
+ Transform tfm = object_fetch_transform(kg, isect->object, OBJECT_TRANSFORM);
+#endif
+
+ P = transform_point(&tfm, P);
+ }
+
+ return P;
+#else
+ return P + D*t;
+#endif
+}
+
+/* Same as above, except that isect->t is assumed to be in object space for
+ * instancing.
+ */
+ccl_device_inline float3 triangle_refine_subsurface(KernelGlobals *kg,
+ ShaderData *sd,
+ const Intersection *isect,
+ const Ray *ray)
+{
+ float3 P = ray->P;
+ float3 D = ray->D;
+ float t = isect->t;
+
+#ifdef __INTERSECTION_REFINE__
+ if(isect->object != OBJECT_NONE) {
+#ifdef __OBJECT_MOTION__
+ Transform tfm = ccl_fetch(sd, ob_itfm);
+#else
+ Transform tfm = object_fetch_transform(kg,
+ isect->object,
+ OBJECT_INVERSE_TRANSFORM);
+#endif
+
+ P = transform_point(&tfm, P);
+ D = transform_direction(&tfm, D);
+ D = normalize(D);
+ }
+
+ P = P + D*t;
+
+ const float4 tri_a = kernel_tex_fetch(__tri_woop, isect->prim*TRI_NODE_SIZE+0),
+ tri_b = kernel_tex_fetch(__tri_woop, isect->prim*TRI_NODE_SIZE+1),
+ tri_c = kernel_tex_fetch(__tri_woop, isect->prim*TRI_NODE_SIZE+2);
+ float3 edge1 = make_float3(tri_a.x - tri_c.x, tri_a.y - tri_c.y, tri_a.z - tri_c.z);
+ float3 edge2 = make_float3(tri_b.x - tri_c.x, tri_b.y - tri_c.y, tri_b.z - tri_c.z);
+ float3 tvec = make_float3(P.x - tri_c.x, P.y - tri_c.y, P.z - tri_c.z);
+ float3 qvec = cross(tvec, edge1);
+ float3 pvec = cross(D, edge2);
+ float rt = dot(edge2, qvec) / dot(edge1, pvec);
+
+ P = P + D*rt;
+
+ if(isect->object != OBJECT_NONE) {
+#ifdef __OBJECT_MOTION__
+ Transform tfm = ccl_fetch(sd, ob_tfm);
+#else
+ Transform tfm = object_fetch_transform(kg,
+ isect->object,
+ OBJECT_TRANSFORM);
+#endif
+
+ P = transform_point(&tfm, P);
+ }
+
+ return P;
+#else
+ return P + D*t;
+#endif
+}
+
+#undef IDX
+
+CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/geom/geom_volume.h b/intern/cycles/kernel/geom/geom_volume.h
index 33a20494966..c72afa2a3a4 100644
--- a/intern/cycles/kernel/geom/geom_volume.h
+++ b/intern/cycles/kernel/geom/geom_volume.h
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
/* Volume Primitive
@@ -52,11 +52,15 @@ ccl_device float volume_attribute_float(KernelGlobals *kg, const ShaderData *sd,
#ifdef __KERNEL_GPU__
float4 r = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
#else
- float4 r = kernel_tex_image_interp_3d(id, P.x, P.y, P.z);
+ float4 r;
+ if(sd->flag & SD_VOLUME_CUBIC)
+ r = kernel_tex_image_interp_3d_ex(id, P.x, P.y, P.z, INTERPOLATION_CUBIC);
+ else
+ r = kernel_tex_image_interp_3d(id, P.x, P.y, P.z);
#endif
if(dx) *dx = 0.0f;
- if(dx) *dy = 0.0f;
+ if(dy) *dy = 0.0f;
/* todo: support float textures to lower memory usage for single floats */
return average(float4_to_float3(r));
@@ -68,7 +72,11 @@ ccl_device float3 volume_attribute_float3(KernelGlobals *kg, const ShaderData *s
#ifdef __KERNEL_GPU__
float4 r = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
#else
- float4 r = kernel_tex_image_interp_3d(id, P.x, P.y, P.z);
+ float4 r;
+ if(sd->flag & SD_VOLUME_CUBIC)
+ r = kernel_tex_image_interp_3d_ex(id, P.x, P.y, P.z, INTERPOLATION_CUBIC);
+ else
+ r = kernel_tex_image_interp_3d(id, P.x, P.y, P.z);
#endif
if(dx) *dx = make_float3(0.0f, 0.0f, 0.0f);
diff --git a/intern/cycles/kernel/kernel.h b/intern/cycles/kernel/kernel.h
index 19e06b88797..b2596d10ee7 100644
--- a/intern/cycles/kernel/kernel.h
+++ b/intern/cycles/kernel/kernel.h
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#ifndef __KERNEL_H__
@@ -32,7 +32,14 @@ void *kernel_osl_memory(KernelGlobals *kg);
bool kernel_osl_use(KernelGlobals *kg);
void kernel_const_copy(KernelGlobals *kg, const char *name, void *host, size_t size);
-void kernel_tex_copy(KernelGlobals *kg, const char *name, device_ptr mem, size_t width, size_t height, size_t depth, InterpolationType interpolation=INTERPOLATION_LINEAR);
+void kernel_tex_copy(KernelGlobals *kg,
+ const char *name,
+ device_ptr mem,
+ size_t width,
+ size_t height,
+ size_t depth,
+ InterpolationType interpolation=INTERPOLATION_LINEAR,
+ ExtensionType extension = EXTENSION_REPEAT);
void kernel_cpu_path_trace(KernelGlobals *kg, float *buffer, unsigned int *rng_state,
int sample, int x, int y, int offset, int stride);
diff --git a/intern/cycles/kernel/kernel_accumulate.h b/intern/cycles/kernel/kernel_accumulate.h
index b0efcdc66a7..2dc87fffcbc 100644
--- a/intern/cycles/kernel/kernel_accumulate.h
+++ b/intern/cycles/kernel/kernel_accumulate.h
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
CCL_NAMESPACE_BEGIN
@@ -176,7 +176,7 @@ ccl_device_inline void path_radiance_init(PathRadiance *L, int use_light_pass)
#endif
}
-ccl_device_inline void path_radiance_bsdf_bounce(PathRadiance *L, float3 *throughput,
+ccl_device_inline void path_radiance_bsdf_bounce(PathRadiance *L, ccl_addr_space float3 *throughput,
BsdfEval *bsdf_eval, float bsdf_pdf, int bounce, int bsdf_label)
{
float inverse_pdf = 1.0f/bsdf_pdf;
@@ -341,12 +341,12 @@ ccl_device_inline void path_radiance_reset_indirect(PathRadiance *L)
ccl_device_inline float3 path_radiance_clamp_and_sum(KernelGlobals *kg, PathRadiance *L)
{
- float3 L_sum, L_direct, L_indirect;
- float clamp_direct = kernel_data.integrator.sample_clamp_direct;
- float clamp_indirect = kernel_data.integrator.sample_clamp_indirect;
-
+ float3 L_sum;
/* Light Passes are used */
#ifdef __PASSES__
+ float3 L_direct, L_indirect;
+ float clamp_direct = kernel_data.integrator.sample_clamp_direct;
+ float clamp_indirect = kernel_data.integrator.sample_clamp_indirect;
if(L->use_light_pass) {
path_radiance_sum_indirect(L);
diff --git a/intern/cycles/kernel/kernel_bake.h b/intern/cycles/kernel/kernel_bake.h
index a1ec080e3d3..2b305e5488d 100644
--- a/intern/cycles/kernel/kernel_bake.h
+++ b/intern/cycles/kernel/kernel_bake.h
@@ -11,11 +11,13 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
CCL_NAMESPACE_BEGIN
+#undef USE_BAKE_JITTER
+
ccl_device void compute_light_pass(KernelGlobals *kg, ShaderData *sd, PathRadiance *L, RNG rng,
const bool is_combined, const bool is_ao, const bool is_sss, int sample)
{
@@ -29,6 +31,13 @@ ccl_device void compute_light_pass(KernelGlobals *kg, ShaderData *sd, PathRadian
float3 throughput = make_float3(1.0f, 1.0f, 1.0f);
bool is_sss_sample = is_sss;
+ ray.P = sd->P + sd->Ng;
+ ray.D = -sd->Ng;
+ ray.t = FLT_MAX;
+#ifdef __CAMERA_MOTION__
+ ray.time = TIME_INVALID;
+#endif
+
/* init radiance */
path_radiance_init(&L_sample, kernel_data.film.use_light_pass);
@@ -55,7 +64,7 @@ ccl_device void compute_light_pass(KernelGlobals *kg, ShaderData *sd, PathRadian
/* sample subsurface scattering */
if((is_combined || is_sss_sample) && (sd->flag & SD_BSSRDF)) {
/* when mixing BSSRDF and BSDF closures we should skip BSDF lighting if scattering was successful */
- if (kernel_path_subsurface_scatter(kg, sd, &L_sample, &state, &rng, &ray, &throughput))
+ if(kernel_path_subsurface_scatter(kg, sd, &L_sample, &state, &rng, &ray, &throughput))
is_sss_sample = true;
}
#endif
@@ -159,7 +168,8 @@ ccl_device bool is_light_pass(ShaderEvalType type)
}
}
-#if 0
+/* this helps with AA but it's not the real solution as it does not AA the geometry
+ * but it's better than nothing, thus committed */
ccl_device_inline float bake_clamp_mirror_repeat(float u)
{
/* use mirror repeat (like opengl texture) so that if the barycentric
@@ -170,7 +180,6 @@ ccl_device_inline float bake_clamp_mirror_repeat(float u)
return (((int)fu) & 1)? 1.0f - u: u;
}
-#endif
ccl_device void kernel_bake_evaluate(KernelGlobals *kg, ccl_global uint4 *input, ccl_global float4 *output,
ShaderEvalType type, int i, int offset, int sample)
@@ -198,12 +207,16 @@ ccl_device void kernel_bake_evaluate(KernelGlobals *kg, ccl_global uint4 *input,
int num_samples = kernel_data.integrator.aa_samples;
/* random number generator */
- RNG rng = cmj_hash(offset + i, 0);
+ RNG rng = cmj_hash(offset + i, kernel_data.integrator.seed);
-#if 0
- uint rng_state = cmj_hash(i, 0);
+#ifdef USE_BAKE_JITTER
float filter_x, filter_y;
- path_rng_init(kg, &rng_state, sample, num_samples, &rng, 0, 0, &filter_x, &filter_y);
+ if(sample == 0) {
+ filter_x = filter_y = 0.5f;
+ }
+ else {
+ path_rng_2D(kg, &rng, sample, num_samples, PRNG_FILTER_U, &filter_x, &filter_y);
+ }
/* subpixel u/v offset */
if(sample > 0) {
@@ -253,6 +266,10 @@ ccl_device void kernel_bake_evaluate(KernelGlobals *kg, ccl_global uint4 *input,
/* data passes */
case SHADER_EVAL_NORMAL:
{
+ if((sd.flag & SD_HAS_BUMP)) {
+ shader_eval_surface(kg, &sd, 0.f, 0, SHADER_CONTEXT_MAIN);
+ }
+
/* compression: normal = (2 * color) - 1 */
out = sd.N * 0.5f + make_float3(0.5f, 0.5f, 0.5f);
break;
diff --git a/intern/cycles/kernel/kernel_camera.h b/intern/cycles/kernel/kernel_camera.h
index d1217ae0abc..2d531fdc96e 100644
--- a/intern/cycles/kernel/kernel_camera.h
+++ b/intern/cycles/kernel/kernel_camera.h
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
CCL_NAMESPACE_BEGIN
@@ -41,11 +41,34 @@ ccl_device float2 camera_sample_aperture(KernelGlobals *kg, float u, float v)
return bokeh;
}
-ccl_device void camera_sample_perspective(KernelGlobals *kg, float raster_x, float raster_y, float lens_u, float lens_v, Ray *ray)
+ccl_device void camera_sample_perspective(KernelGlobals *kg, float raster_x, float raster_y, float lens_u, float lens_v, ccl_addr_space Ray *ray)
{
/* create ray form raster position */
Transform rastertocamera = kernel_data.cam.rastertocamera;
- float3 Pcamera = transform_perspective(&rastertocamera, make_float3(raster_x, raster_y, 0.0f));
+ float3 raster = make_float3(raster_x, raster_y, 0.0f);
+ float3 Pcamera = transform_perspective(&rastertocamera, raster);
+
+#ifdef __CAMERA_MOTION__
+ if(kernel_data.cam.have_perspective_motion) {
+ /* TODO(sergey): Currently we interpolate projected coordinate which
+ * gives nice looking result and which is simple, but is in fact a bit
+ * different comparing to constructing projective matrix from an
+ * interpolated field of view.
+ */
+ if(ray->time < 0.5f) {
+ Transform rastertocamera_pre = kernel_data.cam.perspective_motion.pre;
+ float3 Pcamera_pre =
+ transform_perspective(&rastertocamera_pre, raster);
+ Pcamera = interp(Pcamera_pre, Pcamera, ray->time * 2.0f);
+ }
+ else {
+ Transform rastertocamera_post = kernel_data.cam.perspective_motion.post;
+ float3 Pcamera_post =
+ transform_perspective(&rastertocamera_post, raster);
+ Pcamera = interp(Pcamera, Pcamera_post, (ray->time - 0.5f) * 2.0f);
+ }
+ }
+#endif
ray->P = make_float3(0.0f, 0.0f, 0.0f);
ray->D = Pcamera;
@@ -70,8 +93,18 @@ ccl_device void camera_sample_perspective(KernelGlobals *kg, float raster_x, flo
Transform cameratoworld = kernel_data.cam.cameratoworld;
#ifdef __CAMERA_MOTION__
- if(kernel_data.cam.have_motion)
- transform_motion_interpolate(&cameratoworld, (const DecompMotionTransform*)&kernel_data.cam.motion, ray->time);
+ if(kernel_data.cam.have_motion) {
+#ifdef __KERNEL_OPENCL__
+ const MotionTransform tfm = kernel_data.cam.motion;
+ transform_motion_interpolate(&cameratoworld,
+ ((const DecompMotionTransform*)&tfm),
+ ray->time);
+#else
+ transform_motion_interpolate(&cameratoworld,
+ ((const DecompMotionTransform*)&kernel_data.cam.motion),
+ ray->time);
+#endif
+ }
#endif
ray->P = transform_point(&cameratoworld, ray->P);
@@ -90,16 +123,17 @@ ccl_device void camera_sample_perspective(KernelGlobals *kg, float raster_x, flo
#ifdef __CAMERA_CLIPPING__
/* clipping */
- ray->P += kernel_data.cam.nearclip*ray->D;
- ray->t = kernel_data.cam.cliplength;
+ float3 Pclip = normalize(Pcamera);
+ float z_inv = 1.0f / Pclip.z;
+ ray->P += kernel_data.cam.nearclip*ray->D * z_inv;
+ ray->t = kernel_data.cam.cliplength * z_inv;
#else
ray->t = FLT_MAX;
#endif
}
/* Orthographic Camera */
-
-ccl_device void camera_sample_orthographic(KernelGlobals *kg, float raster_x, float raster_y, float lens_u, float lens_v, Ray *ray)
+ccl_device void camera_sample_orthographic(KernelGlobals *kg, float raster_x, float raster_y, float lens_u, float lens_v, ccl_addr_space Ray *ray)
{
/* create ray form raster position */
Transform rastertocamera = kernel_data.cam.rastertocamera;
@@ -129,8 +163,18 @@ ccl_device void camera_sample_orthographic(KernelGlobals *kg, float raster_x, fl
Transform cameratoworld = kernel_data.cam.cameratoworld;
#ifdef __CAMERA_MOTION__
- if(kernel_data.cam.have_motion)
- transform_motion_interpolate(&cameratoworld, (const DecompMotionTransform*)&kernel_data.cam.motion, ray->time);
+ if(kernel_data.cam.have_motion) {
+#ifdef __KERNEL_OPENCL__
+ const MotionTransform tfm = kernel_data.cam.motion;
+ transform_motion_interpolate(&cameratoworld,
+ (const DecompMotionTransform*)&tfm,
+ ray->time);
+#else
+ transform_motion_interpolate(&cameratoworld,
+ (const DecompMotionTransform*)&kernel_data.cam.motion,
+ ray->time);
+#endif
+ }
#endif
ray->P = transform_point(&cameratoworld, ray->P);
@@ -155,7 +199,7 @@ ccl_device void camera_sample_orthographic(KernelGlobals *kg, float raster_x, fl
/* Panorama Camera */
-ccl_device void camera_sample_panorama(KernelGlobals *kg, float raster_x, float raster_y, float lens_u, float lens_v, Ray *ray)
+ccl_device void camera_sample_panorama(KernelGlobals *kg, float raster_x, float raster_y, float lens_u, float lens_v, ccl_addr_space Ray *ray)
{
Transform rastertocamera = kernel_data.cam.rastertocamera;
float3 Pcamera = transform_perspective(&rastertocamera, make_float3(raster_x, raster_y, 0.0f));
@@ -203,8 +247,18 @@ ccl_device void camera_sample_panorama(KernelGlobals *kg, float raster_x, float
Transform cameratoworld = kernel_data.cam.cameratoworld;
#ifdef __CAMERA_MOTION__
- if(kernel_data.cam.have_motion)
- transform_motion_interpolate(&cameratoworld, (const DecompMotionTransform*)&kernel_data.cam.motion, ray->time);
+ if(kernel_data.cam.have_motion) {
+#ifdef __KERNEL_OPENCL__
+ const MotionTransform tfm = kernel_data.cam.motion;
+ transform_motion_interpolate(&cameratoworld,
+ (const DecompMotionTransform*)&tfm,
+ ray->time);
+#else
+ transform_motion_interpolate(&cameratoworld,
+ (const DecompMotionTransform*)&kernel_data.cam.motion,
+ ray->time);
+#endif
+ }
#endif
ray->P = transform_point(&cameratoworld, ray->P);
@@ -215,18 +269,21 @@ ccl_device void camera_sample_panorama(KernelGlobals *kg, float raster_x, float
/* ray differential */
ray->dP = differential3_zero();
+ Pcamera = transform_perspective(&rastertocamera, make_float3(raster_x, raster_y, 0.0f));
+ float3 Ddiff = normalize(transform_direction(&cameratoworld, panorama_to_direction(kg, Pcamera.x, Pcamera.y)));
+
Pcamera = transform_perspective(&rastertocamera, make_float3(raster_x + 1.0f, raster_y, 0.0f));
- ray->dD.dx = normalize(transform_direction(&cameratoworld, panorama_to_direction(kg, Pcamera.x, Pcamera.y))) - ray->D;
+ ray->dD.dx = normalize(transform_direction(&cameratoworld, panorama_to_direction(kg, Pcamera.x, Pcamera.y))) - Ddiff;
Pcamera = transform_perspective(&rastertocamera, make_float3(raster_x, raster_y + 1.0f, 0.0f));
- ray->dD.dy = normalize(transform_direction(&cameratoworld, panorama_to_direction(kg, Pcamera.x, Pcamera.y))) - ray->D;
+ ray->dD.dy = normalize(transform_direction(&cameratoworld, panorama_to_direction(kg, Pcamera.x, Pcamera.y))) - Ddiff;
#endif
}
/* Common */
ccl_device void camera_sample(KernelGlobals *kg, int x, int y, float filter_u, float filter_v,
- float lens_u, float lens_v, float time, Ray *ray)
+ float lens_u, float lens_v, float time, ccl_addr_space Ray *ray)
{
/* pixel filter */
int filter_table_offset = kernel_data.film.filter_table_offset;
@@ -303,7 +360,7 @@ ccl_device_inline float3 camera_world_to_ndc(KernelGlobals *kg, ShaderData *sd,
{
if(kernel_data.cam.type != CAMERA_PANORAMA) {
/* perspective / ortho */
- if(sd->object == PRIM_NONE && kernel_data.cam.type == CAMERA_PERSPECTIVE)
+ if(ccl_fetch(sd, object) == PRIM_NONE && kernel_data.cam.type == CAMERA_PERSPECTIVE)
P += camera_position(kg);
Transform tfm = kernel_data.cam.worldtondc;
@@ -313,7 +370,7 @@ ccl_device_inline float3 camera_world_to_ndc(KernelGlobals *kg, ShaderData *sd,
/* panorama */
Transform tfm = kernel_data.cam.worldtocamera;
- if(sd->object != OBJECT_NONE)
+ if(ccl_fetch(sd, object) != OBJECT_NONE)
P = normalize(transform_point(&tfm, P));
else
P = normalize(transform_direction(&tfm, P));
@@ -325,4 +382,3 @@ ccl_device_inline float3 camera_world_to_ndc(KernelGlobals *kg, ShaderData *sd,
}
CCL_NAMESPACE_END
-
diff --git a/intern/cycles/kernel/kernel_compat_cpu.h b/intern/cycles/kernel/kernel_compat_cpu.h
index c2aab93c87b..ed145b4a967 100644
--- a/intern/cycles/kernel/kernel_compat_cpu.h
+++ b/intern/cycles/kernel/kernel_compat_cpu.h
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#ifndef __KERNEL_COMPAT_CPU_H__
@@ -19,12 +19,39 @@
#define __KERNEL_CPU__
+/* Release kernel has too much false-positive maybe-uninitialized warnings,
+ * which makes it possible to miss actual warnings.
+ */
+#if defined(__GNUC__) && defined(NDEBUG)
+# pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
+# pragma GCC diagnostic ignored "-Wuninitialized"
+#endif
+
+/* Selective nodes compilation. */
+#ifndef __NODES_MAX_GROUP__
+# define __NODES_MAX_GROUP__ NODE_GROUP_LEVEL_MAX
+#endif
+#ifndef __NODES_FEATURES__
+# define __NODES_FEATURES__ NODE_FEATURE_ALL
+#endif
+
#include "util_debug.h"
#include "util_math.h"
#include "util_simd.h"
#include "util_half.h"
#include "util_types.h"
+#define ccl_addr_space
+
+/* On x86_64, versions of glibc < 2.16 have an issue where expf is
+ * much slower than the double version. This was fixed in glibc 2.16.
+ */
+#if !defined(__KERNEL_GPU__) && defined(__x86_64__) && defined(__x86_64__) && \
+ defined(__GNU_LIBRARY__) && defined(__GLIBC__ ) && defined(__GLIBC_MINOR__) && \
+ (__GLIBC__ <= 2 && __GLIBC_MINOR__ < 16)
+# define expf(x) ((float)exp((double)(x)))
+#endif
+
CCL_NAMESPACE_BEGIN
/* Assertions inside the kernel only work for the CPU device, so we wrap it in
@@ -43,7 +70,7 @@ template<typename T> struct texture {
return data[index];
}
-#if 0
+#ifdef __KERNEL_SSE2__
ccl_always_inline ssef fetch_ssef(int index)
{
kernel_assert(index >= 0 && index < width);
@@ -62,6 +89,14 @@ template<typename T> struct texture {
};
template<typename T> struct texture_image {
+#define SET_CUBIC_SPLINE_WEIGHTS(u, t) \
+ { \
+ u[0] = (((-1.0f/6.0f)* t + 0.5f) * t - 0.5f) * t + (1.0f/6.0f); \
+ u[1] = (( 0.5f * t - 1.0f) * t ) * t + (2.0f/3.0f); \
+ u[2] = (( -0.5f * t + 0.5f) * t + 0.5f) * t + (1.0f/6.0f); \
+ u[3] = (1.0f / 6.0f) * t * t * t; \
+ } (void)0
+
ccl_always_inline float4 read(float4 r)
{
return r;
@@ -93,7 +128,7 @@ template<typename T> struct texture_image {
return x - (float)i;
}
- ccl_always_inline float4 interp(float x, float y, bool periodic = true)
+ ccl_always_inline float4 interp(float x, float y)
{
if(UNLIKELY(!data))
return make_float4(0.0f, 0.0f, 0.0f, 0.0f);
@@ -103,34 +138,47 @@ template<typename T> struct texture_image {
if(interpolation == INTERPOLATION_CLOSEST) {
frac(x*(float)width, &ix);
frac(y*(float)height, &iy);
- if(periodic) {
- ix = wrap_periodic(ix, width);
- iy = wrap_periodic(iy, height);
-
- }
- else {
- ix = wrap_clamp(ix, width);
- iy = wrap_clamp(iy, height);
+ switch(extension) {
+ case EXTENSION_REPEAT:
+ ix = wrap_periodic(ix, width);
+ iy = wrap_periodic(iy, height);
+ break;
+ case EXTENSION_CLIP:
+ if (x < 0.0f || y < 0.0f || x > 1.0f || y > 1.0f) {
+ return make_float4(0.0f, 0.0f, 0.0f, 0.0f);
+ }
+ /* Fall through. */
+ case EXTENSION_EXTEND:
+ ix = wrap_clamp(ix, width);
+ iy = wrap_clamp(iy, height);
+ break;
}
return read(data[ix + iy*width]);
}
- else {
+ else if(interpolation == INTERPOLATION_LINEAR) {
float tx = frac(x*(float)width - 0.5f, &ix);
float ty = frac(y*(float)height - 0.5f, &iy);
- if(periodic) {
- ix = wrap_periodic(ix, width);
- iy = wrap_periodic(iy, height);
-
- nix = wrap_periodic(ix+1, width);
- niy = wrap_periodic(iy+1, height);
- }
- else {
- ix = wrap_clamp(ix, width);
- iy = wrap_clamp(iy, height);
-
- nix = wrap_clamp(ix+1, width);
- niy = wrap_clamp(iy+1, height);
+ switch(extension) {
+ case EXTENSION_REPEAT:
+ ix = wrap_periodic(ix, width);
+ iy = wrap_periodic(iy, height);
+
+ nix = wrap_periodic(ix+1, width);
+ niy = wrap_periodic(iy+1, height);
+ break;
+ case EXTENSION_CLIP:
+ if (x < 0.0f || y < 0.0f || x > 1.0f || y > 1.0f) {
+ return make_float4(0.0f, 0.0f, 0.0f, 0.0f);
+ }
+ /* Fall through. */
+ case EXTENSION_EXTEND:
+ nix = wrap_clamp(ix+1, width);
+ niy = wrap_clamp(iy+1, height);
+
+ ix = wrap_clamp(ix, width);
+ iy = wrap_clamp(iy, height);
+ break;
}
float4 r = (1.0f - ty)*(1.0f - tx)*read(data[ix + iy*width]);
@@ -140,9 +188,79 @@ template<typename T> struct texture_image {
return r;
}
+ else {
+ /* Bicubic b-spline interpolation. */
+ float tx = frac(x*(float)width - 0.5f, &ix);
+ float ty = frac(y*(float)height - 0.5f, &iy);
+ int pix, piy, nnix, nniy;
+ switch(extension) {
+ case EXTENSION_REPEAT:
+ ix = wrap_periodic(ix, width);
+ iy = wrap_periodic(iy, height);
+
+ pix = wrap_periodic(ix-1, width);
+ piy = wrap_periodic(iy-1, height);
+
+ nix = wrap_periodic(ix+1, width);
+ niy = wrap_periodic(iy+1, height);
+
+ nnix = wrap_periodic(ix+2, width);
+ nniy = wrap_periodic(iy+2, height);
+ break;
+ case EXTENSION_CLIP:
+ if (x < 0.0f || y < 0.0f || x > 1.0f || y > 1.0f) {
+ return make_float4(0.0f, 0.0f, 0.0f, 0.0f);
+ }
+ /* Fall through. */
+ case EXTENSION_EXTEND:
+ pix = wrap_clamp(ix-1, width);
+ piy = wrap_clamp(iy-1, height);
+
+ nix = wrap_clamp(ix+1, width);
+ niy = wrap_clamp(iy+1, height);
+
+ nnix = wrap_clamp(ix+2, width);
+ nniy = wrap_clamp(iy+2, height);
+
+ ix = wrap_clamp(ix, width);
+ iy = wrap_clamp(iy, height);
+ break;
+ }
+
+ const int xc[4] = {pix, ix, nix, nnix};
+ const int yc[4] = {width * piy,
+ width * iy,
+ width * niy,
+ width * nniy};
+ float u[4], v[4];
+ /* Some helper macro to keep code reasonable size,
+ * let compiler to inline all the matrix multiplications.
+ */
+#define DATA(x, y) (read(data[xc[x] + yc[y]]))
+#define TERM(col) \
+ (v[col] * (u[0] * DATA(0, col) + \
+ u[1] * DATA(1, col) + \
+ u[2] * DATA(2, col) + \
+ u[3] * DATA(3, col)))
+
+ SET_CUBIC_SPLINE_WEIGHTS(u, tx);
+ SET_CUBIC_SPLINE_WEIGHTS(v, ty);
+
+ /* Actual interpolation. */
+ return TERM(0) + TERM(1) + TERM(2) + TERM(3);
+
+#undef TERM
+#undef DATA
+ }
}
- ccl_always_inline float4 interp_3d(float x, float y, float z, bool periodic = false)
+ ccl_always_inline float4 interp_3d(float x, float y, float z)
+ {
+ return interp_3d_ex(x, y, z, interpolation);
+ }
+
+ ccl_always_inline float4 interp_3d_ex(float x, float y, float z,
+ int interpolation = INTERPOLATION_LINEAR)
{
if(UNLIKELY(!data))
return make_float4(0.0f, 0.0f, 0.0f, 0.0f);
@@ -154,41 +272,55 @@ template<typename T> struct texture_image {
frac(y*(float)height, &iy);
frac(z*(float)depth, &iz);
- if(periodic) {
- ix = wrap_periodic(ix, width);
- iy = wrap_periodic(iy, height);
- iz = wrap_periodic(iz, depth);
- }
- else {
- ix = wrap_clamp(ix, width);
- iy = wrap_clamp(iy, height);
- iz = wrap_clamp(iz, depth);
+ switch(extension) {
+ case EXTENSION_REPEAT:
+ ix = wrap_periodic(ix, width);
+ iy = wrap_periodic(iy, height);
+ iz = wrap_periodic(iz, depth);
+ break;
+ case EXTENSION_CLIP:
+ if (x < 0.0f || y < 0.0f || x > 1.0f || y > 1.0f) {
+ return make_float4(0.0f, 0.0f, 0.0f, 0.0f);
+ }
+ /* Fall through. */
+ case EXTENSION_EXTEND:
+ ix = wrap_clamp(ix, width);
+ iy = wrap_clamp(iy, height);
+ iz = wrap_clamp(iz, depth);
+ break;
}
return read(data[ix + iy*width + iz*width*height]);
}
- else {
+ else if(interpolation == INTERPOLATION_LINEAR) {
float tx = frac(x*(float)width - 0.5f, &ix);
float ty = frac(y*(float)height - 0.5f, &iy);
float tz = frac(z*(float)depth - 0.5f, &iz);
- if(periodic) {
- ix = wrap_periodic(ix, width);
- iy = wrap_periodic(iy, height);
- iz = wrap_periodic(iz, depth);
-
- nix = wrap_periodic(ix+1, width);
- niy = wrap_periodic(iy+1, height);
- niz = wrap_periodic(iz+1, depth);
- }
- else {
- ix = wrap_clamp(ix, width);
- iy = wrap_clamp(iy, height);
- iz = wrap_clamp(iz, depth);
-
- nix = wrap_clamp(ix+1, width);
- niy = wrap_clamp(iy+1, height);
- niz = wrap_clamp(iz+1, depth);
+ switch(extension) {
+ case EXTENSION_REPEAT:
+ ix = wrap_periodic(ix, width);
+ iy = wrap_periodic(iy, height);
+ iz = wrap_periodic(iz, depth);
+
+ nix = wrap_periodic(ix+1, width);
+ niy = wrap_periodic(iy+1, height);
+ niz = wrap_periodic(iz+1, depth);
+ break;
+ case EXTENSION_CLIP:
+ if (x < 0.0f || y < 0.0f || x > 1.0f || y > 1.0f) {
+ return make_float4(0.0f, 0.0f, 0.0f, 0.0f);
+ }
+ /* Fall through. */
+ case EXTENSION_EXTEND:
+ nix = wrap_clamp(ix+1, width);
+ niy = wrap_clamp(iy+1, height);
+ niz = wrap_clamp(iz+1, depth);
+
+ ix = wrap_clamp(ix, width);
+ iy = wrap_clamp(iy, height);
+ iz = wrap_clamp(iz, depth);
+ break;
}
float4 r;
@@ -205,6 +337,92 @@ template<typename T> struct texture_image {
return r;
}
+ else {
+ /* Tricubic b-spline interpolation. */
+ const float tx = frac(x*(float)width - 0.5f, &ix);
+ const float ty = frac(y*(float)height - 0.5f, &iy);
+ const float tz = frac(z*(float)depth - 0.5f, &iz);
+ int pix, piy, piz, nnix, nniy, nniz;
+
+ switch(extension) {
+ case EXTENSION_REPEAT:
+ ix = wrap_periodic(ix, width);
+ iy = wrap_periodic(iy, height);
+ iz = wrap_periodic(iz, depth);
+
+ pix = wrap_periodic(ix-1, width);
+ piy = wrap_periodic(iy-1, height);
+ piz = wrap_periodic(iz-1, depth);
+
+ nix = wrap_periodic(ix+1, width);
+ niy = wrap_periodic(iy+1, height);
+ niz = wrap_periodic(iz+1, depth);
+
+ nnix = wrap_periodic(ix+2, width);
+ nniy = wrap_periodic(iy+2, height);
+ nniz = wrap_periodic(iz+2, depth);
+ break;
+ case EXTENSION_CLIP:
+ if (x < 0.0f || y < 0.0f || x > 1.0f || y > 1.0f) {
+ return make_float4(0.0f, 0.0f, 0.0f, 0.0f);
+ }
+ /* Fall through. */
+ case EXTENSION_EXTEND:
+ pix = wrap_clamp(ix-1, width);
+ piy = wrap_clamp(iy-1, height);
+ piz = wrap_clamp(iz-1, depth);
+
+ nix = wrap_clamp(ix+1, width);
+ niy = wrap_clamp(iy+1, height);
+ niz = wrap_clamp(iz+1, depth);
+
+ nnix = wrap_clamp(ix+2, width);
+ nniy = wrap_clamp(iy+2, height);
+ nniz = wrap_clamp(iz+2, depth);
+
+ ix = wrap_clamp(ix, width);
+ iy = wrap_clamp(iy, height);
+ iz = wrap_clamp(iz, depth);
+ break;
+ }
+
+ const int xc[4] = {pix, ix, nix, nnix};
+ const int yc[4] = {width * piy,
+ width * iy,
+ width * niy,
+ width * nniy};
+ const int zc[4] = {width * height * piz,
+ width * height * iz,
+ width * height * niz,
+ width * height * nniz};
+ float u[4], v[4], w[4];
+
+ /* Some helper macro to keep code reasonable size,
+ * let compiler to inline all the matrix multiplications.
+ */
+#define DATA(x, y, z) (read(data[xc[x] + yc[y] + zc[z]]))
+#define COL_TERM(col, row) \
+ (v[col] * (u[0] * DATA(0, col, row) + \
+ u[1] * DATA(1, col, row) + \
+ u[2] * DATA(2, col, row) + \
+ u[3] * DATA(3, col, row)))
+#define ROW_TERM(row) \
+ (w[row] * (COL_TERM(0, row) + \
+ COL_TERM(1, row) + \
+ COL_TERM(2, row) + \
+ COL_TERM(3, row)))
+
+ SET_CUBIC_SPLINE_WEIGHTS(u, tx);
+ SET_CUBIC_SPLINE_WEIGHTS(v, ty);
+ SET_CUBIC_SPLINE_WEIGHTS(w, tz);
+
+ /* Actual interpolation. */
+ return ROW_TERM(0) + ROW_TERM(1) + ROW_TERM(2) + ROW_TERM(3);
+
+#undef COL_TERM
+#undef ROW_TERM
+#undef DATA
+ }
}
ccl_always_inline void dimensions_set(int width_, int height_, int depth_)
@@ -216,7 +434,9 @@ template<typename T> struct texture_image {
T *data;
int interpolation;
+ ExtensionType extension;
int width, height, depth;
+#undef SET_CUBIC_SPLINE_WEIGHTS
};
typedef texture<float4> texture_float4;
@@ -237,9 +457,38 @@ typedef texture_image<uchar4> texture_image_uchar4;
#define kernel_tex_lookup(tex, t, offset, size) (kg->tex.lookup(t, offset, size))
#define kernel_tex_image_interp(tex, x, y) ((tex < MAX_FLOAT_IMAGES) ? kg->texture_float_images[tex].interp(x, y) : kg->texture_byte_images[tex - MAX_FLOAT_IMAGES].interp(x, y))
#define kernel_tex_image_interp_3d(tex, x, y, z) ((tex < MAX_FLOAT_IMAGES) ? kg->texture_float_images[tex].interp_3d(x, y, z) : kg->texture_byte_images[tex - MAX_FLOAT_IMAGES].interp_3d(x, y, z))
+#define kernel_tex_image_interp_3d_ex(tex, x, y, z, interpolation) ((tex < MAX_FLOAT_IMAGES) ? kg->texture_float_images[tex].interp_3d_ex(x, y, z, interpolation) : kg->texture_byte_images[tex - MAX_FLOAT_IMAGES].interp_3d_ex(x, y, z, interpolation))
#define kernel_data (kg->__data)
+#ifdef __KERNEL_SSE2__
+typedef vector3<sseb> sse3b;
+typedef vector3<ssef> sse3f;
+typedef vector3<ssei> sse3i;
+
+ccl_device_inline void print_sse3b(const char *label, sse3b& a)
+{
+ print_sseb(label, a.x);
+ print_sseb(label, a.y);
+ print_sseb(label, a.z);
+}
+
+ccl_device_inline void print_sse3f(const char *label, sse3f& a)
+{
+ print_ssef(label, a.x);
+ print_ssef(label, a.y);
+ print_ssef(label, a.z);
+}
+
+ccl_device_inline void print_sse3i(const char *label, sse3i& a)
+{
+ print_ssei(label, a.x);
+ print_ssei(label, a.y);
+ print_ssei(label, a.z);
+}
+
+#endif
+
CCL_NAMESPACE_END
#endif /* __KERNEL_COMPAT_CPU_H__ */
diff --git a/intern/cycles/kernel/kernel_compat_cuda.h b/intern/cycles/kernel/kernel_compat_cuda.h
index e4c20d26ff1..9fdd3abfec3 100644
--- a/intern/cycles/kernel/kernel_compat_cuda.h
+++ b/intern/cycles/kernel/kernel_compat_cuda.h
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#ifndef __KERNEL_COMPAT_CUDA_H__
@@ -22,6 +22,14 @@
#define CCL_NAMESPACE_BEGIN
#define CCL_NAMESPACE_END
+/* Selective nodes compilation. */
+#ifndef __NODES_MAX_GROUP__
+# define __NODES_MAX_GROUP__ NODE_GROUP_LEVEL_MAX
+#endif
+#ifndef __NODES_FEATURES__
+# define __NODES_FEATURES__ NODE_FEATURE_ALL
+#endif
+
#include <cuda.h>
#include <float.h>
@@ -33,6 +41,7 @@
#define ccl_global
#define ccl_constant
#define ccl_may_alias
+#define ccl_addr_space
/* No assert supported for CUDA */
@@ -75,12 +84,11 @@ typedef texture<uchar4, 2, cudaReadModeNormalizedFloat> texture_image_uchar4;
/* Use fast math functions */
-#define cosf(x) __cosf(((float)x))
-#define sinf(x) __sinf(((float)x))
-#define powf(x, y) __powf(((float)x), ((float)y))
-#define tanf(x) __tanf(((float)x))
-#define logf(x) __logf(((float)x))
-#define expf(x) __expf(((float)x))
+#define cosf(x) __cosf(((float)(x)))
+#define sinf(x) __sinf(((float)(x)))
+#define powf(x, y) __powf(((float)(x)), ((float)(y)))
+#define tanf(x) __tanf(((float)(x)))
+#define logf(x) __logf(((float)(x)))
+#define expf(x) __expf(((float)(x)))
#endif /* __KERNEL_COMPAT_CUDA_H__ */
-
diff --git a/intern/cycles/kernel/kernel_compat_opencl.h b/intern/cycles/kernel/kernel_compat_opencl.h
index 9e58ebff599..e8b36d2605d 100644
--- a/intern/cycles/kernel/kernel_compat_opencl.h
+++ b/intern/cycles/kernel/kernel_compat_opencl.h
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#ifndef __KERNEL_COMPAT_OPENCL_H__
@@ -24,14 +24,6 @@
#define CCL_NAMESPACE_BEGIN
#define CCL_NAMESPACE_END
-#ifdef __KERNEL_OPENCL_AMD__
-#define __CL_NO_FLOAT3__
-#endif
-
-#ifdef __CL_NO_FLOAT3__
-#define float3 float4
-#endif
-
#ifdef __CL_NOINLINE__
#define ccl_noinline __attribute__((noinline))
#else
@@ -45,6 +37,22 @@
#define ccl_may_alias
#define ccl_constant __constant
#define ccl_global __global
+#define ccl_local __local
+#define ccl_private __private
+
+#ifdef __SPLIT_KERNEL__
+#define ccl_addr_space __global
+#else
+#define ccl_addr_space
+#endif
+
+/* Selective nodes compilation. */
+#ifndef __NODES_MAX_GROUP__
+# define __NODES_MAX_GROUP__ NODE_GROUP_LEVEL_MAX
+#endif
+#ifndef __NODES_FEATURES__
+# define __NODES_FEATURES__ NODE_FEATURE_ALL
+#endif
/* no assert in opencl */
#define kernel_assert(cond)
@@ -73,11 +81,7 @@
#endif
#define make_float2(x, y) ((float2)(x, y))
-#ifdef __CL_NO_FLOAT3__
-#define make_float3(x, y, z) ((float4)(x, y, z, 0.0f))
-#else
#define make_float3(x, y, z) ((float3)(x, y, z))
-#endif
#define make_float4(x, y, z, w) ((float4)(x, y, z, w))
#define make_int2(x, y) ((int2)(x, y))
#define make_int3(x, y, z) ((int3)(x, y, z))
@@ -89,34 +93,34 @@
#define __float_as_uint(x) as_uint(x)
#define __int_as_float(x) as_float(x)
#define __float_as_int(x) as_int(x)
-#define powf(x, y) pow(((float)x), ((float)y))
-#define fabsf(x) fabs(((float)x))
-#define copysignf(x, y) copysign(((float)x), ((float)y))
-#define asinf(x) asin(((float)x))
-#define acosf(x) acos(((float)x))
-#define atanf(x) atan(((float)x))
-#define floorf(x) floor(((float)x))
-#define ceilf(x) ceil(((float)x))
-#define hypotf(x, y) hypot(((float)x), ((float)y))
-#define atan2f(x, y) atan2(((float)x), ((float)y))
-#define fmaxf(x, y) fmax(((float)x), ((float)y))
-#define fminf(x, y) fmin(((float)x), ((float)y))
-#define fmodf(x, y) fmod((float)x, (float)y)
+#define powf(x, y) pow(((float)(x)), ((float)(y)))
+#define fabsf(x) fabs(((float)(x)))
+#define copysignf(x, y) copysign(((float)(x)), ((float)(y)))
+#define asinf(x) asin(((float)(x)))
+#define acosf(x) acos(((float)(x)))
+#define atanf(x) atan(((float)(x)))
+#define floorf(x) floor(((float)(x)))
+#define ceilf(x) ceil(((float)(x)))
+#define hypotf(x, y) hypot(((float)(x)), ((float)(y)))
+#define atan2f(x, y) atan2(((float)(x)), ((float)(y)))
+#define fmaxf(x, y) fmax(((float)(x)), ((float)(y)))
+#define fminf(x, y) fmin(((float)(x)), ((float)(y)))
+#define fmodf(x, y) fmod((float)(x), (float)(y))
#ifndef __CL_USE_NATIVE__
-#define sinf(x) native_sin(((float)x))
-#define cosf(x) native_cos(((float)x))
-#define tanf(x) native_tan(((float)x))
-#define expf(x) native_exp(((float)x))
-#define sqrtf(x) native_sqrt(((float)x))
-#define logf(x) native_log(((float)x))
+#define sinf(x) native_sin(((float)(x)))
+#define cosf(x) native_cos(((float)(x)))
+#define tanf(x) native_tan(((float)(x)))
+#define expf(x) native_exp(((float)(x)))
+#define sqrtf(x) native_sqrt(((float)(x)))
+#define logf(x) native_log(((float)(x)))
#else
-#define sinf(x) sin(((float)x))
-#define cosf(x) cos(((float)x))
-#define tanf(x) tan(((float)x))
-#define expf(x) exp(((float)x))
-#define sqrtf(x) sqrt(((float)x))
-#define logf(x) log(((float)x))
+#define sinf(x) sin(((float)(x)))
+#define cosf(x) cos(((float)(x)))
+#define tanf(x) tan(((float)(x)))
+#define expf(x) exp(((float)(x)))
+#define sqrtf(x) sqrt(((float)(x)))
+#define logf(x) log(((float)(x)))
#endif
/* data lookup defines */
diff --git a/intern/cycles/kernel/kernel_debug.h b/intern/cycles/kernel/kernel_debug.h
new file mode 100644
index 00000000000..24d6458567e
--- /dev/null
+++ b/intern/cycles/kernel/kernel_debug.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2011-2014 Blender Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+CCL_NAMESPACE_BEGIN
+
+ccl_device_inline void debug_data_init(DebugData *debug_data)
+{
+ debug_data->num_bvh_traversal_steps = 0;
+ debug_data->num_bvh_traversed_instances = 0;
+ debug_data->num_ray_bounces = 0;
+}
+
+ccl_device_inline void kernel_write_debug_passes(KernelGlobals *kg,
+ ccl_global float *buffer,
+ ccl_addr_space PathState *state,
+ DebugData *debug_data,
+ int sample)
+{
+ int flag = kernel_data.film.pass_flag;
+ if(flag & PASS_BVH_TRAVERSAL_STEPS) {
+ kernel_write_pass_float(buffer + kernel_data.film.pass_bvh_traversal_steps,
+ sample,
+ debug_data->num_bvh_traversal_steps);
+ }
+ if(flag & PASS_BVH_TRAVERSED_INSTANCES) {
+ kernel_write_pass_float(buffer + kernel_data.film.pass_bvh_traversed_instances,
+ sample,
+ debug_data->num_bvh_traversed_instances);
+ }
+ if(flag & PASS_RAY_BOUNCES) {
+ kernel_write_pass_float(buffer + kernel_data.film.pass_ray_bounces,
+ sample,
+ debug_data->num_ray_bounces);
+ }
+}
+
+CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/kernel_differential.h b/intern/cycles/kernel/kernel_differential.h
index daba2d927b7..ae1e70f0167 100644
--- a/intern/cycles/kernel/kernel_differential.h
+++ b/intern/cycles/kernel/kernel_differential.h
@@ -11,14 +11,14 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
CCL_NAMESPACE_BEGIN
/* See "Tracing Ray Differentials", Homan Igehy, 1999. */
-ccl_device void differential_transfer(differential3 *dP_, const differential3 dP, float3 D, const differential3 dD, float3 Ng, float t)
+ccl_device void differential_transfer(ccl_addr_space differential3 *dP_, const differential3 dP, float3 D, const differential3 dD, float3 Ng, float t)
{
/* ray differential transfer through homogeneous medium, to
* compute dPdx/dy at a shading point from the incoming ray */
@@ -31,7 +31,7 @@ ccl_device void differential_transfer(differential3 *dP_, const differential3 dP
dP_->dy = tmpy - dot(tmpy, Ng)*tmp;
}
-ccl_device void differential_incoming(differential3 *dI, const differential3 dD)
+ccl_device void differential_incoming(ccl_addr_space differential3 *dI, const differential3 dD)
{
/* compute dIdx/dy at a shading point, we just need to negate the
* differential of the ray direction */
@@ -40,7 +40,7 @@ ccl_device void differential_incoming(differential3 *dI, const differential3 dD)
dI->dy = -dD.dy;
}
-ccl_device void differential_dudv(differential *du, differential *dv, float3 dPdu, float3 dPdv, differential3 dP, float3 Ng)
+ccl_device void differential_dudv(ccl_addr_space differential *du, ccl_addr_space differential *dv, float3 dPdu, float3 dPdv, differential3 dP, float3 Ng)
{
/* now we have dPdx/dy from the ray differential transfer, and dPdu/dv
* from the primitive, we can compute dudx/dy and dvdx/dy. these are
diff --git a/intern/cycles/kernel/kernel_emission.h b/intern/cycles/kernel/kernel_emission.h
index 4b2bb723ab6..de9e8d77ec8 100644
--- a/intern/cycles/kernel/kernel_emission.h
+++ b/intern/cycles/kernel/kernel_emission.h
@@ -11,18 +11,26 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
CCL_NAMESPACE_BEGIN
/* Direction Emission */
-
ccl_device_noinline float3 direct_emissive_eval(KernelGlobals *kg,
- LightSample *ls, float3 I, differential3 dI, float t, float time, int bounce, int transparent_bounce)
+ LightSample *ls, float3 I, differential3 dI, float t, float time, int bounce, int transparent_bounce
+#ifdef __SPLIT_KERNEL__
+ ,ShaderData *sd_input
+#endif
+)
{
/* setup shading at emitter */
- ShaderData sd;
+#ifdef __SPLIT_KERNEL__
+ ShaderData *sd = sd_input;
+#else
+ ShaderData sd_object;
+ ShaderData *sd = &sd_object;
+#endif
float3 eval;
#ifdef __BACKGROUND_MIS__
@@ -37,23 +45,23 @@ ccl_device_noinline float3 direct_emissive_eval(KernelGlobals *kg,
ray.dP = differential3_zero();
ray.dD = dI;
- shader_setup_from_background(kg, &sd, &ray, bounce+1, transparent_bounce);
- eval = shader_eval_background(kg, &sd, 0, SHADER_CONTEXT_EMISSION);
+ shader_setup_from_background(kg, sd, &ray, bounce+1, transparent_bounce);
+ eval = shader_eval_background(kg, sd, 0, SHADER_CONTEXT_EMISSION);
}
else
#endif
{
- shader_setup_from_sample(kg, &sd, ls->P, ls->Ng, I, ls->shader, ls->object, ls->prim, ls->u, ls->v, t, time, bounce+1, transparent_bounce);
+ shader_setup_from_sample(kg, sd, ls->P, ls->Ng, I, ls->shader, ls->object, ls->prim, ls->u, ls->v, t, time, bounce+1, transparent_bounce);
- ls->Ng = sd.Ng;
+ ls->Ng = ccl_fetch(sd, Ng);
/* no path flag, we're evaluating this for all closures. that's weak but
* we'd have to do multiple evaluations otherwise */
- shader_eval_surface(kg, &sd, 0.0f, 0, SHADER_CONTEXT_EMISSION);
+ shader_eval_surface(kg, sd, 0.0f, 0, SHADER_CONTEXT_EMISSION);
/* evaluate emissive closure */
- if(sd.flag & SD_EMISSION)
- eval = shader_emissive_eval(kg, &sd);
+ if(ccl_fetch(sd, flag) & SD_EMISSION)
+ eval = shader_emissive_eval(kg, sd);
else
eval = make_float3(0.0f, 0.0f, 0.0f);
}
@@ -65,7 +73,11 @@ ccl_device_noinline float3 direct_emissive_eval(KernelGlobals *kg,
ccl_device_noinline bool direct_emission(KernelGlobals *kg, ShaderData *sd,
LightSample *ls, Ray *ray, BsdfEval *eval, bool *is_lamp,
- int bounce, int transparent_bounce)
+ int bounce, int transparent_bounce
+#ifdef __SPLIT_KERNEL__
+ , ShaderData *sd_DL
+#endif
+ )
{
if(ls->pdf == 0.0f)
return false;
@@ -74,7 +86,14 @@ ccl_device_noinline bool direct_emission(KernelGlobals *kg, ShaderData *sd,
differential3 dD = differential3_zero();
/* evaluate closure */
- float3 light_eval = direct_emissive_eval(kg, ls, -ls->D, dD, ls->t, sd->time, bounce, transparent_bounce);
+
+ float3 light_eval = direct_emissive_eval(kg, ls, -ls->D, dD, ls->t, ccl_fetch(sd, time),
+ bounce,
+ transparent_bounce
+#ifdef __SPLIT_KERNEL__
+ ,sd_DL
+#endif
+ );
if(is_zero(light_eval))
return false;
@@ -83,7 +102,7 @@ ccl_device_noinline bool direct_emission(KernelGlobals *kg, ShaderData *sd,
float bsdf_pdf;
#ifdef __VOLUME__
- if(sd->prim != PRIM_NONE)
+ if(ccl_fetch(sd, prim) != PRIM_NONE)
shader_bsdf_eval(kg, sd, ls->D, eval, &bsdf_pdf);
else
shader_volume_phase_eval(kg, sd, ls->D, eval, &bsdf_pdf);
@@ -118,8 +137,8 @@ ccl_device_noinline bool direct_emission(KernelGlobals *kg, ShaderData *sd,
if(ls->shader & SHADER_CAST_SHADOW) {
/* setup ray */
- bool transmit = (dot(sd->Ng, ls->D) < 0.0f);
- ray->P = ray_offset(sd->P, (transmit)? -sd->Ng: sd->Ng);
+ bool transmit = (dot(ccl_fetch(sd, Ng), ls->D) < 0.0f);
+ ray->P = ray_offset(ccl_fetch(sd, P), (transmit)? -ccl_fetch(sd, Ng): ccl_fetch(sd, Ng));
if(ls->t == FLT_MAX) {
/* distant light */
@@ -132,7 +151,7 @@ ccl_device_noinline bool direct_emission(KernelGlobals *kg, ShaderData *sd,
ray->D = normalize_len(ray->D, &ray->t);
}
- ray->dP = sd->dP;
+ ray->dP = ccl_fetch(sd, dP);
ray->dD = differential3_zero();
}
else {
@@ -154,14 +173,14 @@ ccl_device_noinline float3 indirect_primitive_emission(KernelGlobals *kg, Shader
float3 L = shader_emissive_eval(kg, sd);
#ifdef __HAIR__
- if(!(path_flag & PATH_RAY_MIS_SKIP) && (sd->flag & SD_USE_MIS) && (sd->type & PRIMITIVE_ALL_TRIANGLE))
+ if(!(path_flag & PATH_RAY_MIS_SKIP) && (ccl_fetch(sd, flag) & SD_USE_MIS) && (ccl_fetch(sd, type) & PRIMITIVE_ALL_TRIANGLE))
#else
- if(!(path_flag & PATH_RAY_MIS_SKIP) && (sd->flag & SD_USE_MIS))
+ if(!(path_flag & PATH_RAY_MIS_SKIP) && (ccl_fetch(sd, flag) & SD_USE_MIS))
#endif
{
/* multiple importance sampling, get triangle light pdf,
* and compute weight with respect to BSDF pdf */
- float pdf = triangle_light_pdf(kg, sd->Ng, sd->I, t);
+ float pdf = triangle_light_pdf(kg, ccl_fetch(sd, Ng), ccl_fetch(sd, I), t);
float mis_weight = power_heuristic(bsdf_pdf, pdf);
return L*mis_weight;
@@ -172,7 +191,11 @@ ccl_device_noinline float3 indirect_primitive_emission(KernelGlobals *kg, Shader
/* Indirect Lamp Emission */
-ccl_device_noinline bool indirect_lamp_emission(KernelGlobals *kg, PathState *state, Ray *ray, float3 *emission)
+ccl_device_noinline bool indirect_lamp_emission(KernelGlobals *kg, PathState *state, Ray *ray, float3 *emission
+#ifdef __SPLIT_KERNEL__
+ ,ShaderData *sd
+#endif
+ )
{
bool hit_lamp = false;
@@ -188,14 +211,21 @@ ccl_device_noinline bool indirect_lamp_emission(KernelGlobals *kg, PathState *st
/* use visibility flag to skip lights */
if(ls.shader & SHADER_EXCLUDE_ANY) {
if(((ls.shader & SHADER_EXCLUDE_DIFFUSE) && (state->flag & PATH_RAY_DIFFUSE)) ||
- ((ls.shader & SHADER_EXCLUDE_GLOSSY) && (state->flag & PATH_RAY_GLOSSY)) ||
+ ((ls.shader & SHADER_EXCLUDE_GLOSSY) &&
+ ((state->flag & (PATH_RAY_GLOSSY|PATH_RAY_REFLECT)) == (PATH_RAY_GLOSSY|PATH_RAY_REFLECT))) ||
((ls.shader & SHADER_EXCLUDE_TRANSMIT) && (state->flag & PATH_RAY_TRANSMIT)) ||
((ls.shader & SHADER_EXCLUDE_SCATTER) && (state->flag & PATH_RAY_VOLUME_SCATTER)))
continue;
}
#endif
- float3 L = direct_emissive_eval(kg, &ls, -ray->D, ray->dD, ls.t, ray->time, state->bounce, state->transparent_bounce);
+ float3 L = direct_emissive_eval(kg, &ls, -ray->D, ray->dD, ls.t, ray->time,
+ state->bounce,
+ state->transparent_bounce
+#ifdef __SPLIT_KERNEL__
+ ,sd
+#endif
+ );
#ifdef __VOLUME__
if(state->volume_stack[0].shader != SHADER_NONE) {
@@ -224,7 +254,11 @@ ccl_device_noinline bool indirect_lamp_emission(KernelGlobals *kg, PathState *st
/* Indirect Background */
-ccl_device_noinline float3 indirect_background(KernelGlobals *kg, PathState *state, Ray *ray)
+ccl_device_noinline float3 indirect_background(KernelGlobals *kg, ccl_addr_space PathState *state, ccl_addr_space Ray *ray
+#ifdef __SPLIT_KERNEL__
+ ,ShaderData *sd_global
+#endif
+ )
{
#ifdef __BACKGROUND__
int shader = kernel_data.background.surface_shader;
@@ -232,18 +266,25 @@ ccl_device_noinline float3 indirect_background(KernelGlobals *kg, PathState *sta
/* use visibility flag to skip lights */
if(shader & SHADER_EXCLUDE_ANY) {
if(((shader & SHADER_EXCLUDE_DIFFUSE) && (state->flag & PATH_RAY_DIFFUSE)) ||
- ((shader & SHADER_EXCLUDE_GLOSSY) && (state->flag & PATH_RAY_GLOSSY)) ||
+ ((shader & SHADER_EXCLUDE_GLOSSY) &&
+ ((state->flag & (PATH_RAY_GLOSSY|PATH_RAY_REFLECT)) == (PATH_RAY_GLOSSY|PATH_RAY_REFLECT))) ||
((shader & SHADER_EXCLUDE_TRANSMIT) && (state->flag & PATH_RAY_TRANSMIT)) ||
((shader & SHADER_EXCLUDE_CAMERA) && (state->flag & PATH_RAY_CAMERA)) ||
((shader & SHADER_EXCLUDE_SCATTER) && (state->flag & PATH_RAY_VOLUME_SCATTER)))
return make_float3(0.0f, 0.0f, 0.0f);
}
+#ifdef __SPLIT_KERNEL__
/* evaluate background closure */
+ Ray priv_ray = *ray;
+ shader_setup_from_background(kg, sd_global, &priv_ray, state->bounce+1, state->transparent_bounce);
+ float3 L = shader_eval_background(kg, sd_global, state->flag, SHADER_CONTEXT_EMISSION);
+#else
ShaderData sd;
shader_setup_from_background(kg, &sd, ray, state->bounce+1, state->transparent_bounce);
float3 L = shader_eval_background(kg, &sd, state->flag, SHADER_CONTEXT_EMISSION);
+#endif
#ifdef __BACKGROUND_MIS__
/* check if background light exists or if we should skip pdf */
@@ -252,7 +293,7 @@ ccl_device_noinline float3 indirect_background(KernelGlobals *kg, PathState *sta
if(!(state->flag & PATH_RAY_MIS_SKIP) && res) {
/* multiple importance sampling, get background light pdf for ray
* direction, and compute weight with respect to BSDF pdf */
- float pdf = background_light_pdf(kg, ray->D);
+ float pdf = background_light_pdf(kg, ray->P, ray->D);
float mis_weight = power_heuristic(state->ray_pdf, pdf);
return L*mis_weight;
diff --git a/intern/cycles/kernel/kernel_film.h b/intern/cycles/kernel/kernel_film.h
index dc5f6e7ce38..f9e9b413898 100644
--- a/intern/cycles/kernel/kernel_film.h
+++ b/intern/cycles/kernel/kernel_film.h
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
CCL_NAMESPACE_BEGIN
@@ -27,7 +27,7 @@ ccl_device float4 film_map(KernelGlobals *kg, float4 irradiance, float scale)
result.z = color_scene_linear_to_srgb(result.z*exposure);
/* clamp since alpha might be > 1.0 due to russian roulette */
- result.w = clamp(result.w, 0.0f, 1.0f);
+ result.w = saturate(result.w);
return result;
}
@@ -37,10 +37,10 @@ ccl_device uchar4 film_float_to_byte(float4 color)
uchar4 result;
/* simple float to byte conversion */
- result.x = (uchar)clamp(color.x*255.0f, 0.0f, 255.0f);
- result.y = (uchar)clamp(color.y*255.0f, 0.0f, 255.0f);
- result.z = (uchar)clamp(color.z*255.0f, 0.0f, 255.0f);
- result.w = (uchar)clamp(color.w*255.0f, 0.0f, 255.0f);
+ result.x = (uchar)(saturate(color.x)*255.0f);
+ result.y = (uchar)(saturate(color.y)*255.0f);
+ result.z = (uchar)(saturate(color.z)*255.0f);
+ result.w = (uchar)(saturate(color.w)*255.0f);
return result;
}
diff --git a/intern/cycles/kernel/kernel_globals.h b/intern/cycles/kernel/kernel_globals.h
index 6bd2ec0662c..17fa18909c4 100644
--- a/intern/cycles/kernel/kernel_globals.h
+++ b/intern/cycles/kernel/kernel_globals.h
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
/* Constant Globals */
@@ -80,7 +80,7 @@ typedef struct KernelGlobals {} KernelGlobals;
#ifdef __KERNEL_OPENCL__
-typedef struct KernelGlobals {
+typedef ccl_addr_space struct KernelGlobals {
ccl_constant KernelData *data;
#define KERNEL_TEX(type, ttype, name) \
@@ -94,7 +94,7 @@ typedef struct KernelGlobals {
ccl_device float lookup_table_read(KernelGlobals *kg, float x, int offset, int size)
{
- x = clamp(x, 0.0f, 1.0f)*(size-1);
+ x = saturate(x)*(size-1);
int index = min(float_to_int(x), size-1);
int nindex = min(index+1, size-1);
@@ -110,7 +110,7 @@ ccl_device float lookup_table_read(KernelGlobals *kg, float x, int offset, int s
ccl_device float lookup_table_read_2D(KernelGlobals *kg, float x, float y, int offset, int xsize, int ysize)
{
- y = clamp(y, 0.0f, 1.0f)*(ysize-1);
+ y = saturate(y)*(ysize-1);
int index = min(float_to_int(y), ysize-1);
int nindex = min(index+1, ysize-1);
diff --git a/intern/cycles/kernel/kernel_jitter.h b/intern/cycles/kernel/kernel_jitter.h
index 2a5b7689e57..9ba41635b9e 100644
--- a/intern/cycles/kernel/kernel_jitter.h
+++ b/intern/cycles/kernel/kernel_jitter.h
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
/* TODO(sergey): Consider moving portable ctz/clz stuff to util. */
@@ -47,6 +47,8 @@ ccl_device_inline int cmj_fast_div_pow2(int a, int b)
# else
return a >> __builtin_ctz(b);
# endif
+#elif defined(__KERNEL_CUDA__)
+ return a >> (__ffs(b) - 1);
#else
return a/b;
#endif
@@ -63,6 +65,8 @@ ccl_device_inline uint cmj_w_mask(uint w)
# else
return ((1 << (32 - __builtin_clz(w))) - 1);
# endif
+#elif defined(__KERNEL_CUDA__)
+ return ((1 << (32 - __clz(w))) - 1);
#else
w |= w >> 1;
w |= w >> 2;
@@ -124,7 +128,7 @@ ccl_device_inline uint cmj_permute(uint i, uint l, uint p)
i *= 0xc860a3df;
i &= w;
i ^= i >> 5;
- } while (i >= l);
+ } while(i >= l);
return (i + p) % l;
}
@@ -167,7 +171,11 @@ ccl_device void cmj_sample_2D(int s, int N, int p, float *fx, float *fy)
{
kernel_assert(s < N);
+#if defined(__KERNEL_CUDA__)
+ int m = float_to_int(__fsqrt_ru(N));
+#else
int m = float_to_int(sqrtf(N));
+#endif
int n = (N + m - 1)/m;
float invN = 1.0f/N;
float invm = 1.0f/m;
diff --git a/intern/cycles/kernel/kernel_light.h b/intern/cycles/kernel/kernel_light.h
index e7f62f230f8..7590ec2d706 100644
--- a/intern/cycles/kernel/kernel_light.h
+++ b/intern/cycles/kernel/kernel_light.h
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
CCL_NAMESPACE_BEGIN
@@ -33,11 +33,112 @@ typedef struct LightSample {
LightType type; /* type of light */
} LightSample;
+/* Area light sampling */
+
+/* Uses the following paper:
+ *
+ * Carlos Urena et al.
+ * An Area-Preserving Parametrization for Spherical Rectangles.
+ *
+ * https://www.solidangle.com/research/egsr2013_spherical_rectangle.pdf
+ *
+ * Note: light_p is modified when sample_coord is true.
+ */
+ccl_device float area_light_sample(float3 P,
+ float3 *light_p,
+ float3 axisu, float3 axisv,
+ float randu, float randv,
+ bool sample_coord)
+{
+ /* In our name system we're using P for the center,
+ * which is o in the paper.
+ */
+
+ float3 corner = *light_p - axisu * 0.5f - axisv * 0.5f;
+ float axisu_len, axisv_len;
+ /* Compute local reference system R. */
+ float3 x = normalize_len(axisu, &axisu_len);
+ float3 y = normalize_len(axisv, &axisv_len);
+ float3 z = cross(x, y);
+ /* Compute rectangle coords in local reference system. */
+ float3 dir = corner - P;
+ float z0 = dot(dir, z);
+ /* Flip 'z' to make it point against Q. */
+ if(z0 > 0.0f) {
+ z *= -1.0f;
+ z0 *= -1.0f;
+ }
+ float x0 = dot(dir, x);
+ float y0 = dot(dir, y);
+ float x1 = x0 + axisu_len;
+ float y1 = y0 + axisv_len;
+ /* Create vectors to four vertices. */
+ float3 v00 = make_float3(x0, y0, z0);
+ float3 v01 = make_float3(x0, y1, z0);
+ float3 v10 = make_float3(x1, y0, z0);
+ float3 v11 = make_float3(x1, y1, z0);
+ /* Compute normals to edges. */
+ float3 n0 = normalize(cross(v00, v10));
+ float3 n1 = normalize(cross(v10, v11));
+ float3 n2 = normalize(cross(v11, v01));
+ float3 n3 = normalize(cross(v01, v00));
+ /* Compute internal angles (gamma_i). */
+ float g0 = safe_acosf(-dot(n0, n1));
+ float g1 = safe_acosf(-dot(n1, n2));
+ float g2 = safe_acosf(-dot(n2, n3));
+ float g3 = safe_acosf(-dot(n3, n0));
+ /* Compute predefined constants. */
+ float b0 = n0.z;
+ float b1 = n2.z;
+ float b0sq = b0 * b0;
+ float k = M_2PI_F - g2 - g3;
+ /* Compute solid angle from internal angles. */
+ float S = g0 + g1 - k;
+
+ if(sample_coord) {
+ /* Compute cu. */
+ float au = randu * S + k;
+ float fu = (cosf(au) * b0 - b1) / sinf(au);
+ float cu = 1.0f / sqrtf(fu * fu + b0sq) * (fu > 0.0f ? 1.0f : -1.0f);
+ cu = clamp(cu, -1.0f, 1.0f);
+ /* Compute xu. */
+ float xu = -(cu * z0) / sqrtf(1.0f - cu * cu);
+ xu = clamp(xu, x0, x1);
+ /* Compute yv. */
+ float z0sq = z0 * z0;
+ float y0sq = y0 * y0;
+ float y1sq = y1 * y1;
+ float d = sqrtf(xu * xu + z0sq);
+ float h0 = y0 / sqrtf(d * d + y0sq);
+ float h1 = y1 / sqrtf(d * d + y1sq);
+ float hv = h0 + randv * (h1 - h0), hv2 = hv * hv;
+ float yv = (hv2 < 1.0f - 1e-6f) ? (hv * d) / sqrtf(1.0f - hv2) : y1;
+
+ /* Transform (xu, yv, z0) to world coords. */
+ *light_p = P + xu * x + yv * y + z0 * z;
+ }
+
+ /* return pdf */
+ if(S != 0.0f)
+ return 1.0f / S;
+ else
+ return 0.0f;
+}
+
/* Background Light */
#ifdef __BACKGROUND_MIS__
-ccl_device float3 background_light_sample(KernelGlobals *kg, float randu, float randv, float *pdf)
+/* TODO(sergey): In theory it should be all fine to use noinline for all
+ * devices, but we're so close to the release so better not screw things
+ * up for CPU at least.
+ */
+#ifdef __KERNEL_GPU__
+ccl_device_noinline
+#else
+ccl_device
+#endif
+float3 background_map_sample(KernelGlobals *kg, float randu, float randv, float *pdf)
{
/* for the following, the CDF values are actually a pair of floats, with the
* function value as X and the actual CDF as Y. The last entry's function
@@ -107,13 +208,19 @@ ccl_device float3 background_light_sample(KernelGlobals *kg, float randu, float
else
*pdf = (cdf_u.x * cdf_v.x)/(M_2PI_F * M_PI_F * sin_theta * denom);
- *pdf *= kernel_data.integrator.pdf_lights;
-
/* compute direction */
- return -equirectangular_to_direction(u, v);
+ return equirectangular_to_direction(u, v);
}
-ccl_device float background_light_pdf(KernelGlobals *kg, float3 direction)
+/* TODO(sergey): Same as above, after the release we should consider using
+ * 'noinline' for all devices.
+ */
+#ifdef __KERNEL_GPU__
+ccl_device_noinline
+#else
+ccl_device
+#endif
+float background_map_pdf(KernelGlobals *kg, float3 direction)
{
float2 uv = direction_to_equirectangular(direction);
int res = kernel_data.integrator.pdf_background_res;
@@ -139,9 +246,223 @@ ccl_device float background_light_pdf(KernelGlobals *kg, float3 direction)
float2 cdf_u = kernel_tex_fetch(__light_background_conditional_cdf, index_v * (res + 1) + index_u);
float2 cdf_v = kernel_tex_fetch(__light_background_marginal_cdf, index_v);
- float pdf = (cdf_u.x * cdf_v.x)/(M_2PI_F * M_PI_F * sin_theta * denom);
+ return (cdf_u.x * cdf_v.x)/(M_2PI_F * M_PI_F * sin_theta * denom);
+}
+
+ccl_device_inline bool background_portal_data_fetch_and_check_side(KernelGlobals *kg,
+ float3 P,
+ int index,
+ float3 *lightpos,
+ float3 *dir)
+{
+ float4 data0 = kernel_tex_fetch(__light_data, (index + kernel_data.integrator.portal_offset)*LIGHT_SIZE + 0);
+ float4 data3 = kernel_tex_fetch(__light_data, (index + kernel_data.integrator.portal_offset)*LIGHT_SIZE + 3);
+
+ *lightpos = make_float3(data0.y, data0.z, data0.w);
+ *dir = make_float3(data3.y, data3.z, data3.w);
+
+ /* Check whether portal is on the right side. */
+ if(dot(*dir, P - *lightpos) > 1e-5f)
+ return true;
+
+ return false;
+}
+
+ccl_device float background_portal_pdf(KernelGlobals *kg,
+ float3 P,
+ float3 direction,
+ int ignore_portal,
+ bool *is_possible)
+{
+ float portal_pdf = 0.0f;
+
+ for(int p = 0; p < kernel_data.integrator.num_portals; p++) {
+ if(p == ignore_portal)
+ continue;
+
+ float3 lightpos, dir;
+ if(!background_portal_data_fetch_and_check_side(kg, P, p, &lightpos, &dir))
+ continue;
+
+ if(is_possible) {
+ /* There's a portal that could be sampled from this position. */
+ *is_possible = true;
+ }
+
+ float t = -(dot(P, dir) - dot(lightpos, dir)) / dot(direction, dir);
+ if(t <= 1e-5f) {
+ /* Either behind the portal or too close. */
+ continue;
+ }
+
+ float4 data1 = kernel_tex_fetch(__light_data, (p + kernel_data.integrator.portal_offset)*LIGHT_SIZE + 1);
+ float4 data2 = kernel_tex_fetch(__light_data, (p + kernel_data.integrator.portal_offset)*LIGHT_SIZE + 2);
+
+ float3 axisu = make_float3(data1.y, data1.z, data1.w);
+ float3 axisv = make_float3(data2.y, data2.z, data2.w);
+
+ float3 hit = P + t*direction;
+ float3 inplane = hit - lightpos;
+ /* Skip if the the ray doesn't pass through portal. */
+ if(fabsf(dot(inplane, axisu) / dot(axisu, axisu)) > 0.5f)
+ continue;
+ if(fabsf(dot(inplane, axisv) / dot(axisv, axisv)) > 0.5f)
+ continue;
+
+ portal_pdf += area_light_sample(P, &lightpos, axisu, axisv, 0.0f, 0.0f, false);
+ }
- return pdf * kernel_data.integrator.pdf_lights;
+ return kernel_data.integrator.num_portals? portal_pdf / kernel_data.integrator.num_portals: 0.0f;
+}
+
+ccl_device int background_num_possible_portals(KernelGlobals *kg, float3 P)
+{
+ int num_possible_portals = 0;
+ for(int p = 0; p < kernel_data.integrator.num_portals; p++) {
+ float3 lightpos, dir;
+ if(background_portal_data_fetch_and_check_side(kg, P, p, &lightpos, &dir))
+ num_possible_portals++;
+ }
+ return num_possible_portals;
+}
+
+ccl_device float3 background_portal_sample(KernelGlobals *kg,
+ float3 P,
+ float randu,
+ float randv,
+ int num_possible,
+ int *sampled_portal,
+ float *pdf)
+{
+ /* Pick a portal, then re-normalize randv. */
+ randv *= num_possible;
+ int portal = (int)randv;
+ randv -= portal;
+
+ /* TODO(sergey): Some smarter way of finding portal to sample
+ * is welcome.
+ */
+ for(int p = 0; p < kernel_data.integrator.num_portals; p++) {
+ /* Search for the sampled portal. */
+ float3 lightpos, dir;
+ if(!background_portal_data_fetch_and_check_side(kg, P, p, &lightpos, &dir))
+ continue;
+
+ if(portal == 0) {
+ /* p is the portal to be sampled. */
+ float4 data1 = kernel_tex_fetch(__light_data, (p + kernel_data.integrator.portal_offset)*LIGHT_SIZE + 1);
+ float4 data2 = kernel_tex_fetch(__light_data, (p + kernel_data.integrator.portal_offset)*LIGHT_SIZE + 2);
+ float3 axisu = make_float3(data1.y, data1.z, data1.w);
+ float3 axisv = make_float3(data2.y, data2.z, data2.w);
+
+ *pdf = area_light_sample(P, &lightpos,
+ axisu, axisv,
+ randu, randv,
+ true);
+
+ *pdf /= num_possible;
+ *sampled_portal = p;
+ return normalize(lightpos - P);
+ }
+
+ portal--;
+ }
+
+ return make_float3(0.0f, 0.0f, 0.0f);
+}
+
+ccl_device float3 background_light_sample(KernelGlobals *kg, float3 P, float randu, float randv, float *pdf)
+{
+ /* Probability of sampling portals instead of the map. */
+ float portal_sampling_pdf = kernel_data.integrator.portal_pdf;
+
+ /* Check if there are portals in the scene which we can sample. */
+ if(portal_sampling_pdf > 0.0f) {
+ int num_portals = background_num_possible_portals(kg, P);
+ if(num_portals > 0) {
+ if(portal_sampling_pdf == 1.0f || randu < portal_sampling_pdf) {
+ if(portal_sampling_pdf < 1.0f) {
+ randu /= portal_sampling_pdf;
+ }
+ int portal;
+ float3 D = background_portal_sample(kg, P, randu, randv, num_portals, &portal, pdf);
+ if(num_portals > 1) {
+ /* Ignore the chosen portal, its pdf is already included. */
+ *pdf += background_portal_pdf(kg, P, D, portal, NULL);
+ }
+ /* We could also have sampled the map, so combine with MIS. */
+ if(portal_sampling_pdf < 1.0f) {
+ float cdf_pdf = background_map_pdf(kg, D);
+ *pdf = (portal_sampling_pdf * (*pdf)
+ + (1.0f - portal_sampling_pdf) * cdf_pdf);
+ }
+ return D;
+ } else {
+ /* Sample map, but with nonzero portal_sampling_pdf for MIS. */
+ randu = (randu - portal_sampling_pdf) / (1.0f - portal_sampling_pdf);
+ }
+ } else {
+ /* We can't sample a portal.
+ * Check if we can sample the map instead.
+ */
+ if(portal_sampling_pdf == 1.0f) {
+ /* Use uniform as a fallback if we can't sample the map. */
+ *pdf = 1.0f / M_4PI_F;
+ return sample_uniform_sphere(randu, randv);
+ }
+ else {
+ portal_sampling_pdf = 0.0f;
+ }
+ }
+ }
+
+ float3 D = background_map_sample(kg, randu, randv, pdf);
+ /* Use MIS if portals could be sampled as well. */
+ if(portal_sampling_pdf > 0.0f) {
+ float portal_pdf = background_portal_pdf(kg, P, D, -1, NULL);
+ *pdf = (portal_sampling_pdf * portal_pdf
+ + (1.0f - portal_sampling_pdf) * (*pdf));
+ }
+ return D;
+}
+
+ccl_device float background_light_pdf(KernelGlobals *kg, float3 P, float3 direction)
+{
+ /* Probability of sampling portals instead of the map. */
+ float portal_sampling_pdf = kernel_data.integrator.portal_pdf;
+
+ if(portal_sampling_pdf > 0.0f) {
+ bool is_possible = false;
+ float portal_pdf = background_portal_pdf(kg, P, direction, -1, &is_possible);
+ if(portal_pdf == 0.0f) {
+ if(portal_sampling_pdf == 1.0f) {
+ /* If there are no possible portals at this point,
+ * the fallback sampling would have been used.
+ * Otherwise, the direction would not be sampled at all => pdf = 0
+ */
+ return is_possible? 0.0f: kernel_data.integrator.pdf_lights / M_4PI_F;
+ }
+ else {
+ /* We can only sample the map. */
+ return background_map_pdf(kg, direction) * kernel_data.integrator.pdf_lights;
+ }
+ } else {
+ if(portal_sampling_pdf == 1.0f) {
+ /* We can only sample portals. */
+ return portal_pdf * kernel_data.integrator.pdf_lights;
+ }
+ else {
+ /* We can sample both, so combine with MIS. */
+ return (background_map_pdf(kg, direction) * (1.0f - portal_sampling_pdf)
+ + portal_pdf * portal_sampling_pdf) * kernel_data.integrator.pdf_lights;
+ }
+ }
+ }
+
+ /* No portals in the scene, so must sample the map.
+ * At least one of them is always possible if we have a LIGHT_BACKGROUND.
+ */
+ return background_map_pdf(kg, direction) * kernel_data.integrator.pdf_lights;
}
#endif
@@ -167,14 +488,6 @@ ccl_device float3 sphere_light_sample(float3 P, float3 center, float radius, flo
return disk_light_sample(normalize(P - center), randu, randv)*radius;
}
-ccl_device float3 area_light_sample(float3 axisu, float3 axisv, float randu, float randv)
-{
- randu = randu - 0.5f;
- randv = randv - 0.5f;
-
- return axisu*randu + axisv*randv;
-}
-
ccl_device float spot_light_attenuation(float4 data1, float4 data2, LightSample *ls)
{
float3 dir = make_float3(data2.y, data2.z, data2.w);
@@ -245,13 +558,14 @@ ccl_device void lamp_light_sample(KernelGlobals *kg, int lamp,
#ifdef __BACKGROUND_MIS__
else if(type == LIGHT_BACKGROUND) {
/* infinite area light (e.g. light dome or env light) */
- float3 D = background_light_sample(kg, randu, randv, &ls->pdf);
+ float3 D = -background_light_sample(kg, P, randu, randv, &ls->pdf);
ls->P = D;
ls->Ng = D;
ls->D = -D;
ls->t = FLT_MAX;
ls->eval_fac = 1.0f;
+ ls->pdf *= kernel_data.integrator.pdf_lights;
}
#endif
else {
@@ -276,6 +590,7 @@ ccl_device void lamp_light_sample(KernelGlobals *kg, int lamp,
float4 data2 = kernel_tex_fetch(__light_data, lamp*LIGHT_SIZE + 2);
ls->eval_fac *= spot_light_attenuation(data1, data2, ls);
}
+ ls->pdf *= lamp_light_pdf(kg, ls->Ng, -ls->D, ls->t);
}
else {
/* area light */
@@ -286,22 +601,31 @@ ccl_device void lamp_light_sample(KernelGlobals *kg, int lamp,
float3 axisv = make_float3(data2.y, data2.z, data2.w);
float3 D = make_float3(data3.y, data3.z, data3.w);
- ls->P += area_light_sample(axisu, axisv, randu, randv);
+ ls->pdf = area_light_sample(P, &ls->P,
+ axisu, axisv,
+ randu, randv,
+ true);
+
ls->Ng = D;
ls->D = normalize_len(ls->P - P, &ls->t);
float invarea = data2.x;
-
ls->eval_fac = 0.25f*invarea;
- ls->pdf = invarea;
+
+ if(dot(ls->D, D) > 0.0f)
+ ls->pdf = 0.0f;
}
ls->eval_fac *= kernel_data.integrator.inv_pdf_lights;
- ls->pdf *= lamp_light_pdf(kg, ls->Ng, -ls->D, ls->t);
}
}
-ccl_device bool lamp_light_eval(KernelGlobals *kg, int lamp, float3 P, float3 D, float t, LightSample *ls)
+#if defined(__KERNEL_CUDA__) && (__CUDA_ARCH__ >= 500) && (defined(i386) || defined(_M_IX86))
+ccl_device_noinline
+#else
+ccl_device
+#endif
+bool lamp_light_eval(KernelGlobals *kg, int lamp, float3 P, float3 D, float t, LightSample *ls)
{
float4 data0 = kernel_tex_fetch(__light_data, lamp*LIGHT_SIZE + 0);
float4 data1 = kernel_tex_fetch(__light_data, lamp*LIGHT_SIZE + 1);
@@ -355,6 +679,7 @@ ccl_device bool lamp_light_eval(KernelGlobals *kg, int lamp, float3 P, float3 D,
ls->D = D;
ls->t = FLT_MAX;
+ /* compute pdf */
float invarea = data1.w;
ls->pdf = invarea/(costheta*costheta*costheta);
ls->eval_fac = ls->pdf;
@@ -386,6 +711,10 @@ ccl_device bool lamp_light_eval(KernelGlobals *kg, int lamp, float3 P, float3 D,
if(ls->eval_fac == 0.0f)
return false;
}
+
+ /* compute pdf */
+ if(ls->t != FLT_MAX)
+ ls->pdf *= lamp_light_pdf(kg, ls->Ng, -ls->D, ls->t);
}
else if(type == LIGHT_AREA) {
/* area light */
@@ -404,24 +733,20 @@ ccl_device bool lamp_light_eval(KernelGlobals *kg, int lamp, float3 P, float3 D,
if(dot(D, Ng) >= 0.0f)
return false;
- ls->P = make_float3(data0.y, data0.z, data0.w);
+ float3 light_P = make_float3(data0.y, data0.z, data0.w);
if(!ray_quad_intersect(P, D, t,
- ls->P, axisu, axisv, &ls->P, &ls->t))
+ light_P, axisu, axisv, &ls->P, &ls->t))
return false;
ls->D = D;
ls->Ng = Ng;
- ls->pdf = invarea;
- ls->eval_fac = 0.25f*ls->pdf;
+ ls->pdf = area_light_sample(P, &light_P, axisu, axisv, 0, 0, false);
+ ls->eval_fac = 0.25f*invarea;
}
else
return false;
- /* compute pdf */
- if(ls->t != FLT_MAX)
- ls->pdf *= lamp_light_pdf(kg, ls->Ng, -ls->D, ls->t);
-
return true;
}
@@ -514,7 +839,13 @@ ccl_device int light_distribution_sample(KernelGlobals *kg, float randt)
/* Generic Light */
-ccl_device void light_sample(KernelGlobals *kg, float randt, float randu, float randv, float time, float3 P, LightSample *ls)
+ccl_device bool light_select_reached_max_bounces(KernelGlobals *kg, int index, int bounce)
+{
+ float4 data4 = kernel_tex_fetch(__light_data, index*LIGHT_SIZE + 4);
+ return (bounce > __float_as_int(data4.x));
+}
+
+ccl_device void light_sample(KernelGlobals *kg, float randt, float randu, float randv, float time, float3 P, int bounce, LightSample *ls)
{
/* sample index */
int index = light_distribution_sample(kg, randt);
@@ -536,6 +867,12 @@ ccl_device void light_sample(KernelGlobals *kg, float randt, float randu, float
}
else {
int lamp = -prim-1;
+
+ if(UNLIKELY(light_select_reached_max_bounces(kg, lamp, bounce))) {
+ ls->pdf = 0.0f;
+ return;
+ }
+
lamp_light_sample(kg, lamp, randu, randv, P, ls);
}
}
@@ -546,22 +883,5 @@ ccl_device int light_select_num_samples(KernelGlobals *kg, int index)
return __float_as_int(data3.x);
}
-ccl_device int lamp_light_eval_sample(KernelGlobals *kg, float randt)
-{
- /* sample index */
- int index = light_distribution_sample(kg, randt);
-
- /* fetch light data */
- float4 l = kernel_tex_fetch(__light_distribution, index);
- int prim = __float_as_int(l.y);
-
- if(prim < 0) {
- int lamp = -prim-1;
- return lamp;
- }
- else
- return LAMP_NONE;
-}
-
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/kernel_math.h b/intern/cycles/kernel/kernel_math.h
index d95a5c76309..9e14d8cc7cb 100644
--- a/intern/cycles/kernel/kernel_math.h
+++ b/intern/cycles/kernel/kernel_math.h
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#ifndef __KERNEL_MATH_H__
@@ -19,6 +19,7 @@
#include "util_color.h"
#include "util_math.h"
+#include "util_math_fast.h"
#include "util_transform.h"
#include "util_distort.h"
diff --git a/intern/cycles/kernel/kernel_passes.h b/intern/cycles/kernel/kernel_passes.h
index b3b6fc02894..20cf3fa931b 100644
--- a/intern/cycles/kernel/kernel_passes.h
+++ b/intern/cycles/kernel/kernel_passes.h
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
CCL_NAMESPACE_BEGIN
@@ -19,23 +19,49 @@ CCL_NAMESPACE_BEGIN
ccl_device_inline void kernel_write_pass_float(ccl_global float *buffer, int sample, float value)
{
ccl_global float *buf = buffer;
+#if defined(__SPLIT_KERNEL__) && defined(__WORK_STEALING__)
+ atomic_add_float(buf, value);
+#else
*buf = (sample == 0)? value: *buf + value;
+#endif // __SPLIT_KERNEL__ && __WORK_STEALING__
}
ccl_device_inline void kernel_write_pass_float3(ccl_global float *buffer, int sample, float3 value)
{
+#if defined(__SPLIT_KERNEL__) && defined(__WORK_STEALING__)
+ ccl_global float *buf_x = buffer + 0;
+ ccl_global float *buf_y = buffer + 1;
+ ccl_global float *buf_z = buffer + 2;
+
+ atomic_add_float(buf_x, value.x);
+ atomic_add_float(buf_y, value.y);
+ atomic_add_float(buf_z, value.z);
+#else
ccl_global float3 *buf = (ccl_global float3*)buffer;
*buf = (sample == 0)? value: *buf + value;
+#endif // __SPLIT_KERNEL__ && __WORK_STEALING__
}
ccl_device_inline void kernel_write_pass_float4(ccl_global float *buffer, int sample, float4 value)
{
+#if defined(__SPLIT_KERNEL__) && defined(__WORK_STEALING__)
+ ccl_global float *buf_x = buffer + 0;
+ ccl_global float *buf_y = buffer + 1;
+ ccl_global float *buf_z = buffer + 2;
+ ccl_global float *buf_w = buffer + 3;
+
+ atomic_add_float(buf_x, value.x);
+ atomic_add_float(buf_y, value.y);
+ atomic_add_float(buf_z, value.z);
+ atomic_add_float(buf_w, value.w);
+#else
ccl_global float4 *buf = (ccl_global float4*)buffer;
*buf = (sample == 0)? value: *buf + value;
+#endif // __SPLIT_KERNEL__ && __WORK_STEALING__
}
ccl_device_inline void kernel_write_data_passes(KernelGlobals *kg, ccl_global float *buffer, PathRadiance *L,
- ShaderData *sd, int sample, PathState *state, float3 throughput)
+ ShaderData *sd, int sample, ccl_addr_space PathState *state, float3 throughput)
{
#ifdef __PASSES__
int path_flag = state->flag;
@@ -49,18 +75,18 @@ ccl_device_inline void kernel_write_data_passes(KernelGlobals *kg, ccl_global fl
return;
if(!(path_flag & PATH_RAY_SINGLE_PASS_DONE)) {
- if(!(sd->flag & SD_TRANSPARENT) ||
+ if(!(ccl_fetch(sd, flag) & SD_TRANSPARENT) ||
kernel_data.film.pass_alpha_threshold == 0.0f ||
average(shader_bsdf_alpha(kg, sd)) >= kernel_data.film.pass_alpha_threshold)
{
if(sample == 0) {
if(flag & PASS_DEPTH) {
- float depth = camera_distance(kg, sd->P);
+ float depth = camera_distance(kg, ccl_fetch(sd, P));
kernel_write_pass_float(buffer + kernel_data.film.pass_depth, sample, depth);
}
if(flag & PASS_OBJECT_ID) {
- float id = object_pass_id(kg, sd->object);
+ float id = object_pass_id(kg, ccl_fetch(sd, object));
kernel_write_pass_float(buffer + kernel_data.film.pass_object_id, sample, id);
}
if(flag & PASS_MATERIAL_ID) {
@@ -70,7 +96,7 @@ ccl_device_inline void kernel_write_data_passes(KernelGlobals *kg, ccl_global fl
}
if(flag & PASS_NORMAL) {
- float3 normal = sd->N;
+ float3 normal = ccl_fetch(sd, N);
kernel_write_pass_float3(buffer + kernel_data.film.pass_normal, sample, normal);
}
if(flag & PASS_UV) {
@@ -101,8 +127,8 @@ ccl_device_inline void kernel_write_data_passes(KernelGlobals *kg, ccl_global fl
float mist_start = kernel_data.film.mist_start;
float mist_inv_depth = kernel_data.film.mist_inv_depth;
- float depth = camera_distance(kg, sd->P);
- float mist = clamp((depth - mist_start)*mist_inv_depth, 0.0f, 1.0f);
+ float depth = camera_distance(kg, ccl_fetch(sd, P));
+ float mist = saturate((depth - mist_start)*mist_inv_depth);
/* falloff */
float mist_falloff = kernel_data.film.mist_falloff;
diff --git a/intern/cycles/kernel/kernel_path.h b/intern/cycles/kernel/kernel_path.h
index b8994d940fd..9794ad1d180 100644
--- a/intern/cycles/kernel/kernel_path.h
+++ b/intern/cycles/kernel/kernel_path.h
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#ifdef __OSL__
@@ -42,9 +42,14 @@
#include "kernel_path_state.h"
#include "kernel_shadow.h"
#include "kernel_emission.h"
+#include "kernel_path_common.h"
#include "kernel_path_surface.h"
#include "kernel_path_volume.h"
+#ifdef __KERNEL_DEBUG__
+#include "kernel_debug.h"
+#endif
+
CCL_NAMESPACE_BEGIN
ccl_device void kernel_path_indirect(KernelGlobals *kg, RNG *rng, Ray ray,
@@ -113,7 +118,7 @@ ccl_device void kernel_path_indirect(KernelGlobals *kg, RNG *rng, Ray ray,
/* direct light sampling */
kernel_branched_path_volume_connect_light(kg, rng, &volume_sd,
- throughput, &state, L, 1.0f, all, &volume_ray, &volume_segment);
+ throughput, &state, L, all, &volume_ray, &volume_segment);
/* indirect sample. if we use distance sampling and take just
* one sample for direct and indirect light, we could share
@@ -126,9 +131,6 @@ ccl_device void kernel_path_indirect(KernelGlobals *kg, RNG *rng, Ray ray,
rphase, rscatter, &volume_segment, NULL, true);
}
- if(result != VOLUME_PATH_SCATTERED)
- throughput *= volume_segment.accum_transmittance;
-
/* free cached steps */
kernel_volume_decoupled_free(kg, &volume_segment);
@@ -138,6 +140,9 @@ ccl_device void kernel_path_indirect(KernelGlobals *kg, RNG *rng, Ray ray,
else
break;
}
+ else {
+ throughput *= volume_segment.accum_transmittance;
+ }
}
else
#endif
@@ -269,8 +274,6 @@ ccl_device void kernel_path_indirect(KernelGlobals *kg, RNG *rng, Ray ray,
float bssrdf_u, bssrdf_v;
path_state_rng_2D(kg, rng, &state, PRNG_BSDF_U, &bssrdf_u, &bssrdf_v);
subsurface_scatter_step(kg, &sd, state.flag, sc, &lcg_state, bssrdf_u, bssrdf_v, false);
-
- state.flag |= PATH_RAY_BSSRDF_ANCESTOR;
}
}
#endif
@@ -303,17 +306,17 @@ ccl_device void kernel_path_ao(KernelGlobals *kg, ShaderData *sd, PathRadiance *
sample_cos_hemisphere(ao_N, bsdf_u, bsdf_v, &ao_D, &ao_pdf);
- if(dot(sd->Ng, ao_D) > 0.0f && ao_pdf != 0.0f) {
+ if(dot(ccl_fetch(sd, Ng), ao_D) > 0.0f && ao_pdf != 0.0f) {
Ray light_ray;
float3 ao_shadow;
- light_ray.P = ray_offset(sd->P, sd->Ng);
+ light_ray.P = ray_offset(ccl_fetch(sd, P), ccl_fetch(sd, Ng));
light_ray.D = ao_D;
light_ray.t = kernel_data.background.ao_distance;
#ifdef __OBJECT_MOTION__
- light_ray.time = sd->time;
+ light_ray.time = ccl_fetch(sd, time);
#endif
- light_ray.dP = sd->dP;
+ light_ray.dP = ccl_fetch(sd, dP);
light_ray.dD = differential3_zero();
if(!shadow_blocked(kg, state, &light_ray, &ao_shadow))
@@ -321,78 +324,8 @@ ccl_device void kernel_path_ao(KernelGlobals *kg, ShaderData *sd, PathRadiance *
}
}
-ccl_device void kernel_branched_path_ao(KernelGlobals *kg, ShaderData *sd, PathRadiance *L, PathState *state, RNG *rng, float3 throughput)
-{
- int num_samples = kernel_data.integrator.ao_samples;
- float num_samples_inv = 1.0f/num_samples;
- float ao_factor = kernel_data.background.ao_factor;
- float3 ao_N;
- float3 ao_bsdf = shader_bsdf_ao(kg, sd, ao_factor, &ao_N);
- float3 ao_alpha = shader_bsdf_alpha(kg, sd);
-
- for(int j = 0; j < num_samples; j++) {
- float bsdf_u, bsdf_v;
- path_branched_rng_2D(kg, rng, state, j, num_samples, PRNG_BSDF_U, &bsdf_u, &bsdf_v);
-
- float3 ao_D;
- float ao_pdf;
-
- sample_cos_hemisphere(ao_N, bsdf_u, bsdf_v, &ao_D, &ao_pdf);
-
- if(dot(sd->Ng, ao_D) > 0.0f && ao_pdf != 0.0f) {
- Ray light_ray;
- float3 ao_shadow;
-
- light_ray.P = ray_offset(sd->P, sd->Ng);
- light_ray.D = ao_D;
- light_ray.t = kernel_data.background.ao_distance;
-#ifdef __OBJECT_MOTION__
- light_ray.time = sd->time;
-#endif
- light_ray.dP = sd->dP;
- light_ray.dD = differential3_zero();
-
- if(!shadow_blocked(kg, state, &light_ray, &ao_shadow))
- path_radiance_accum_ao(L, throughput*num_samples_inv, ao_alpha, ao_bsdf, ao_shadow, state->bounce);
- }
- }
-}
-
#ifdef __SUBSURFACE__
-#ifdef __VOLUME__
-ccl_device void kernel_path_subsurface_update_volume_stack(KernelGlobals *kg,
- Ray *ray,
- VolumeStack *stack)
-{
- kernel_assert(kernel_data.integrator.use_volumes);
-
- Ray volume_ray = *ray;
- Intersection isect;
- const float3 Pend = volume_ray.P + volume_ray.D*volume_ray.t;
-
- while(
- scene_intersect(kg, &volume_ray, PATH_RAY_ALL_VISIBILITY,
- &isect, NULL, 0.0f, 0.0f)) {
- ShaderData sd;
- shader_setup_from_ray(kg, &sd, &isect, &volume_ray, 0, 0);
- kernel_volume_stack_enter_exit(kg, &sd, stack);
-
- /* Move ray forward. */
- volume_ray.P = ray_offset(sd.P, -sd.Ng);
- volume_ray.D = normalize_len(Pend - volume_ray.P,
- &volume_ray.t);
-
- /* TODO(sergey): Find a faster way detecting that ray_offset moved
- * us pass through the end point.
- */
- if(dot(ray->D, volume_ray.D) < 0.0f) {
- break;
- }
- }
-}
-#endif
-
ccl_device bool kernel_path_subsurface_scatter(KernelGlobals *kg, ShaderData *sd, PathRadiance *L, PathState *state, RNG *rng, Ray *ray, float3 *throughput)
{
float bssrdf_probability;
@@ -411,6 +344,8 @@ ccl_device bool kernel_path_subsurface_scatter(KernelGlobals *kg, ShaderData *sd
int num_hits = subsurface_scatter_multi_step(kg, sd, bssrdf_sd, state->flag, sc, &lcg_state, bssrdf_u, bssrdf_v, false);
#ifdef __VOLUME__
Ray volume_ray = *ray;
+ bool need_update_volume_stack = kernel_data.integrator.use_volumes &&
+ ccl_fetch(sd, flag) & SD_OBJECT_INTERSECTS_VOLUME;
#endif
/* compute lighting with the BSDF closure */
@@ -419,7 +354,6 @@ ccl_device bool kernel_path_subsurface_scatter(KernelGlobals *kg, ShaderData *sd
PathState hit_state = *state;
Ray hit_ray = *ray;
- hit_state.flag |= PATH_RAY_BSSRDF_ANCESTOR;
hit_state.rng_offset += PRNG_BOUNCE_NUM;
kernel_path_surface_connect_light(kg, rng, &bssrdf_sd[hit], tp, state, L);
@@ -430,12 +364,12 @@ ccl_device bool kernel_path_subsurface_scatter(KernelGlobals *kg, ShaderData *sd
#endif
#ifdef __VOLUME__
- if(kernel_data.integrator.use_volumes) {
+ if(need_update_volume_stack) {
/* Setup ray from previous surface point to the new one. */
volume_ray.D = normalize_len(hit_ray.P - volume_ray.P,
&volume_ray.t);
- kernel_path_subsurface_update_volume_stack(
+ kernel_volume_stack_update_for_subsurface(
kg,
&volume_ray,
hit_state.volume_stack);
@@ -471,6 +405,11 @@ ccl_device float4 kernel_path_integrate(KernelGlobals *kg, RNG *rng, int sample,
PathState state;
path_state_init(kg, &state, rng, sample, &ray);
+#ifdef __KERNEL_DEBUG__
+ DebugData debug_data;
+ debug_data_init(&debug_data);
+#endif
+
/* path iteration */
for(;;) {
/* intersect scene */
@@ -497,6 +436,14 @@ ccl_device float4 kernel_path_integrate(KernelGlobals *kg, RNG *rng, int sample,
bool hit = scene_intersect(kg, &ray, visibility, &isect, NULL, 0.0f, 0.0f);
#endif
+#ifdef __KERNEL_DEBUG__
+ if(state.flag & PATH_RAY_CAMERA) {
+ debug_data.num_bvh_traversal_steps += isect.num_traversal_steps;
+ debug_data.num_bvh_traversed_instances += isect.num_traversed_instances;
+ }
+ debug_data.num_ray_bounces++;
+#endif
+
#ifdef __LAMP_MIS__
if(kernel_data.integrator.use_lamp_mis && !(state.flag & PATH_RAY_CAMERA)) {
/* ray starting from previous non-transparent bounce */
@@ -553,7 +500,7 @@ ccl_device float4 kernel_path_integrate(KernelGlobals *kg, RNG *rng, int sample,
/* direct light sampling */
kernel_branched_path_volume_connect_light(kg, rng, &volume_sd,
- throughput, &state, &L, 1.0f, all, &volume_ray, &volume_segment);
+ throughput, &state, &L, all, &volume_ray, &volume_segment);
/* indirect sample. if we use distance sampling and take just
* one sample for direct and indirect light, we could share
@@ -566,9 +513,6 @@ ccl_device float4 kernel_path_integrate(KernelGlobals *kg, RNG *rng, int sample,
rphase, rscatter, &volume_segment, NULL, true);
}
- if(result != VOLUME_PATH_SCATTERED)
- throughput *= volume_segment.accum_transmittance;
-
/* free cached steps */
kernel_volume_decoupled_free(kg, &volume_segment);
@@ -578,6 +522,9 @@ ccl_device float4 kernel_path_integrate(KernelGlobals *kg, RNG *rng, int sample,
else
break;
}
+ else {
+ throughput *= volume_segment.accum_transmittance;
+ }
}
else
#endif
@@ -717,460 +664,13 @@ ccl_device float4 kernel_path_integrate(KernelGlobals *kg, RNG *rng, int sample,
kernel_write_light_passes(kg, buffer, &L, sample);
- return make_float4(L_sum.x, L_sum.y, L_sum.z, 1.0f - L_transparent);
-}
-
-#ifdef __BRANCHED_PATH__
-
-/* branched path tracing: bounce off surface and integrate indirect light */
-ccl_device_noinline void kernel_branched_path_surface_indirect_light(KernelGlobals *kg,
- RNG *rng, ShaderData *sd, float3 throughput, float num_samples_adjust,
- PathState *state, PathRadiance *L)
-{
- for(int i = 0; i< sd->num_closure; i++) {
- const ShaderClosure *sc = &sd->closure[i];
-
- if(!CLOSURE_IS_BSDF(sc->type))
- continue;
- /* transparency is not handled here, but in outer loop */
- if(sc->type == CLOSURE_BSDF_TRANSPARENT_ID)
- continue;
-
- int num_samples;
-
- if(CLOSURE_IS_BSDF_DIFFUSE(sc->type))
- num_samples = kernel_data.integrator.diffuse_samples;
- else if(CLOSURE_IS_BSDF_BSSRDF(sc->type))
- num_samples = 1;
- else if(CLOSURE_IS_BSDF_GLOSSY(sc->type))
- num_samples = kernel_data.integrator.glossy_samples;
- else
- num_samples = kernel_data.integrator.transmission_samples;
-
- num_samples = ceil_to_int(num_samples_adjust*num_samples);
-
- float num_samples_inv = num_samples_adjust/num_samples;
- RNG bsdf_rng = cmj_hash(*rng, i);
-
- for(int j = 0; j < num_samples; j++) {
- PathState ps = *state;
- float3 tp = throughput;
- Ray bsdf_ray;
-
- if(!kernel_branched_path_surface_bounce(kg, &bsdf_rng, sd, sc, j, num_samples, &tp, &ps, L, &bsdf_ray))
- continue;
-
- kernel_path_indirect(kg, rng, bsdf_ray, tp*num_samples_inv, num_samples, ps, L);
-
- /* for render passes, sum and reset indirect light pass variables
- * for the next samples */
- path_radiance_sum_indirect(L);
- path_radiance_reset_indirect(L);
- }
- }
-}
-
-#ifdef __SUBSURFACE__
-ccl_device void kernel_branched_path_subsurface_scatter(KernelGlobals *kg,
- ShaderData *sd,
- PathRadiance *L,
- PathState *state,
- RNG *rng,
- Ray *ray,
- float3 throughput)
-{
- for(int i = 0; i< sd->num_closure; i++) {
- ShaderClosure *sc = &sd->closure[i];
-
- if(!CLOSURE_IS_BSSRDF(sc->type))
- continue;
-
- /* set up random number generator */
- uint lcg_state = lcg_state_init(rng, state, 0x68bc21eb);
- int num_samples = kernel_data.integrator.subsurface_samples;
- float num_samples_inv = 1.0f/num_samples;
- RNG bssrdf_rng = cmj_hash(*rng, i);
-
- state->flag |= PATH_RAY_BSSRDF_ANCESTOR;
-
- /* do subsurface scatter step with copy of shader data, this will
- * replace the BSSRDF with a diffuse BSDF closure */
- for(int j = 0; j < num_samples; j++) {
- ShaderData bssrdf_sd[BSSRDF_MAX_HITS];
- float bssrdf_u, bssrdf_v;
- path_branched_rng_2D(kg, &bssrdf_rng, state, j, num_samples, PRNG_BSDF_U, &bssrdf_u, &bssrdf_v);
- int num_hits = subsurface_scatter_multi_step(kg, sd, bssrdf_sd, state->flag, sc, &lcg_state, bssrdf_u, bssrdf_v, true);
-#ifdef __VOLUME__
- Ray volume_ray = *ray;
-#endif
-
- /* compute lighting with the BSDF closure */
- for(int hit = 0; hit < num_hits; hit++) {
- PathState hit_state = *state;
-
- path_state_branch(&hit_state, j, num_samples);
-
-#ifdef __VOLUME__
- if(kernel_data.integrator.use_volumes) {
- /* Setup ray from previous surface point to the new one. */
- float3 P = ray_offset(bssrdf_sd[hit].P, -bssrdf_sd[hit].Ng);
- volume_ray.D = normalize_len(P - volume_ray.P,
- &volume_ray.t);
-
- kernel_path_subsurface_update_volume_stack(
- kg,
- &volume_ray,
- hit_state.volume_stack);
-
- /* Move volume ray forward. */
- volume_ray.P = P;
- }
-#endif
-
-#if defined(__EMISSION__) && defined(__BRANCHED_PATH__)
- /* direct light */
- if(kernel_data.integrator.use_direct_light) {
- bool all = kernel_data.integrator.sample_all_lights_direct;
- kernel_branched_path_surface_connect_light(kg, rng,
- &bssrdf_sd[hit], &hit_state, throughput, num_samples_inv, L, all);
- }
-#endif
-
- /* indirect light */
- kernel_branched_path_surface_indirect_light(kg, rng,
- &bssrdf_sd[hit], throughput, num_samples_inv,
- &hit_state, L);
- }
- }
-
- state->flag &= ~PATH_RAY_BSSRDF_ANCESTOR;
- }
-}
-#endif
-
-ccl_device float4 kernel_branched_path_integrate(KernelGlobals *kg, RNG *rng, int sample, Ray ray, ccl_global float *buffer)
-{
- /* initialize */
- PathRadiance L;
- float3 throughput = make_float3(1.0f, 1.0f, 1.0f);
- float L_transparent = 0.0f;
-
- path_radiance_init(&L, kernel_data.film.use_light_pass);
-
- PathState state;
- path_state_init(kg, &state, rng, sample, &ray);
-
- for(;;) {
- /* intersect scene */
- Intersection isect;
- uint visibility = path_state_ray_visibility(kg, &state);
-
-#ifdef __HAIR__
- float difl = 0.0f, extmax = 0.0f;
- uint lcg_state = 0;
-
- if(kernel_data.bvh.have_curves) {
- if((kernel_data.cam.resolution == 1) && (state.flag & PATH_RAY_CAMERA)) {
- float3 pixdiff = ray.dD.dx + ray.dD.dy;
- /*pixdiff = pixdiff - dot(pixdiff, ray.D)*ray.D;*/
- difl = kernel_data.curve.minimum_width * len(pixdiff) * 0.5f;
- }
-
- extmax = kernel_data.curve.maximum_width;
- lcg_state = lcg_state_init(rng, &state, 0x51633e2d);
- }
-
- bool hit = scene_intersect(kg, &ray, visibility, &isect, &lcg_state, difl, extmax);
-#else
- bool hit = scene_intersect(kg, &ray, visibility, &isect, NULL, 0.0f, 0.0f);
-#endif
-
-#ifdef __VOLUME__
- /* volume attenuation, emission, scatter */
- if(state.volume_stack[0].shader != SHADER_NONE) {
- Ray volume_ray = ray;
- volume_ray.t = (hit)? isect.t: FLT_MAX;
-
- bool heterogeneous = volume_stack_is_heterogeneous(kg, state.volume_stack);
-
-#ifdef __VOLUME_DECOUPLED__
- /* decoupled ray marching only supported on CPU */
-
- /* cache steps along volume for repeated sampling */
- VolumeSegment volume_segment;
- ShaderData volume_sd;
-
- shader_setup_from_volume(kg, &volume_sd, &volume_ray, state.bounce, state.transparent_bounce);
- kernel_volume_decoupled_record(kg, &state,
- &volume_ray, &volume_sd, &volume_segment, heterogeneous);
-
- /* direct light sampling */
- if(volume_segment.closure_flag & SD_SCATTER) {
- volume_segment.sampling_method = volume_stack_sampling_method(kg, state.volume_stack);
-
- bool all = kernel_data.integrator.sample_all_lights_direct;
-
- kernel_branched_path_volume_connect_light(kg, rng, &volume_sd,
- throughput, &state, &L, 1.0f, all, &volume_ray, &volume_segment);
-
- /* indirect light sampling */
- int num_samples = kernel_data.integrator.volume_samples;
- float num_samples_inv = 1.0f/num_samples;
-
- for(int j = 0; j < num_samples; j++) {
- /* workaround to fix correlation bug in T38710, can find better solution
- * in random number generator later, for now this is done here to not impact
- * performance of rendering without volumes */
- RNG tmp_rng = cmj_hash(*rng, state.rng_offset);
-
- PathState ps = state;
- Ray pray = ray;
- float3 tp = throughput;
-
- /* branch RNG state */
- path_state_branch(&ps, j, num_samples);
-
- /* scatter sample. if we use distance sampling and take just one
- * sample for direct and indirect light, we could share this
- * computation, but makes code a bit complex */
- float rphase = path_state_rng_1D_for_decision(kg, &tmp_rng, &ps, PRNG_PHASE);
- float rscatter = path_state_rng_1D_for_decision(kg, &tmp_rng, &ps, PRNG_SCATTER_DISTANCE);
-
- VolumeIntegrateResult result = kernel_volume_decoupled_scatter(kg,
- &ps, &pray, &volume_sd, &tp, rphase, rscatter, &volume_segment, NULL, false);
-
- (void)result;
- kernel_assert(result == VOLUME_PATH_SCATTERED);
-
- if(kernel_path_volume_bounce(kg, rng, &volume_sd, &tp, &ps, &L, &pray)) {
- kernel_path_indirect(kg, rng, pray, tp*num_samples_inv, num_samples, ps, &L);
-
- /* for render passes, sum and reset indirect light pass variables
- * for the next samples */
- path_radiance_sum_indirect(&L);
- path_radiance_reset_indirect(&L);
- }
- }
- }
-
- /* emission and transmittance */
- if(volume_segment.closure_flag & SD_EMISSION)
- path_radiance_accum_emission(&L, throughput, volume_segment.accum_emission, state.bounce);
- throughput *= volume_segment.accum_transmittance;
-
- /* free cached steps */
- kernel_volume_decoupled_free(kg, &volume_segment);
-#else
- /* GPU: no decoupled ray marching, scatter probalistically */
- int num_samples = kernel_data.integrator.volume_samples;
- float num_samples_inv = 1.0f/num_samples;
-
- /* todo: we should cache the shader evaluations from stepping
- * through the volume, for now we redo them multiple times */
-
- for(int j = 0; j < num_samples; j++) {
- PathState ps = state;
- Ray pray = ray;
- ShaderData volume_sd;
- float3 tp = throughput * num_samples_inv;
-
- /* branch RNG state */
- path_state_branch(&ps, j, num_samples);
-
- VolumeIntegrateResult result = kernel_volume_integrate(
- kg, &ps, &volume_sd, &volume_ray, &L, &tp, rng, heterogeneous);
-
-#ifdef __VOLUME_SCATTER__
- if(result == VOLUME_PATH_SCATTERED) {
- /* todo: support equiangular, MIS and all light sampling.
- * alternatively get decoupled ray marching working on the GPU */
- kernel_path_volume_connect_light(kg, rng, &volume_sd, tp, &state, &L);
-
- if(kernel_path_volume_bounce(kg, rng, &volume_sd, &tp, &ps, &L, &pray)) {
- kernel_path_indirect(kg, rng, pray, tp, num_samples, ps, &L);
-
- /* for render passes, sum and reset indirect light pass variables
- * for the next samples */
- path_radiance_sum_indirect(&L);
- path_radiance_reset_indirect(&L);
- }
- }
-#endif
- }
-
- /* todo: avoid this calculation using decoupled ray marching */
- kernel_volume_shadow(kg, &state, &volume_ray, &throughput);
-#endif
- }
-#endif
-
- if(!hit) {
- /* eval background shader if nothing hit */
- if(kernel_data.background.transparent) {
- L_transparent += average(throughput);
-
-#ifdef __PASSES__
- if(!(kernel_data.film.pass_flag & PASS_BACKGROUND))
-#endif
- break;
- }
-
-#ifdef __BACKGROUND__
- /* sample background shader */
- float3 L_background = indirect_background(kg, &state, &ray);
- path_radiance_accum_background(&L, throughput, L_background, state.bounce);
-#endif
-
- break;
- }
-
- /* setup shading */
- ShaderData sd;
- shader_setup_from_ray(kg, &sd, &isect, &ray, state.bounce, state.transparent_bounce);
- shader_eval_surface(kg, &sd, 0.0f, state.flag, SHADER_CONTEXT_MAIN);
- shader_merge_closures(&sd);
-
- /* holdout */
-#ifdef __HOLDOUT__
- if(sd.flag & (SD_HOLDOUT|SD_HOLDOUT_MASK)) {
- if(kernel_data.background.transparent) {
- float3 holdout_weight;
-
- if(sd.flag & SD_HOLDOUT_MASK)
- holdout_weight = make_float3(1.0f, 1.0f, 1.0f);
- else
- holdout_weight = shader_holdout_eval(kg, &sd);
-
- /* any throughput is ok, should all be identical here */
- L_transparent += average(holdout_weight*throughput);
- }
-
- if(sd.flag & SD_HOLDOUT_MASK)
- break;
- }
-#endif
-
- /* holdout mask objects do not write data passes */
- kernel_write_data_passes(kg, buffer, &L, &sd, sample, &state, throughput);
-
-#ifdef __EMISSION__
- /* emission */
- if(sd.flag & SD_EMISSION) {
- float3 emission = indirect_primitive_emission(kg, &sd, isect.t, state.flag, state.ray_pdf);
- path_radiance_accum_emission(&L, throughput, emission, state.bounce);
- }
-#endif
-
- /* transparency termination */
- if(state.flag & PATH_RAY_TRANSPARENT) {
- /* path termination. this is a strange place to put the termination, it's
- * mainly due to the mixed in MIS that we use. gives too many unneeded
- * shader evaluations, only need emission if we are going to terminate */
- float probability = path_state_terminate_probability(kg, &state, throughput);
-
- if(probability == 0.0f) {
- break;
- }
- else if(probability != 1.0f) {
- float terminate = path_state_rng_1D_for_decision(kg, rng, &state, PRNG_TERMINATE);
-
- if(terminate >= probability)
- break;
-
- throughput /= probability;
- }
- }
-
-#ifdef __AO__
- /* ambient occlusion */
- if(kernel_data.integrator.use_ambient_occlusion || (sd.flag & SD_AO)) {
- kernel_branched_path_ao(kg, &sd, &L, &state, rng, throughput);
- }
-#endif
-
-#ifdef __SUBSURFACE__
- /* bssrdf scatter to a different location on the same object */
- if(sd.flag & SD_BSSRDF) {
- kernel_branched_path_subsurface_scatter(kg, &sd, &L, &state,
- rng, &ray, throughput);
- }
-#endif
-
- if(!(sd.flag & SD_HAS_ONLY_VOLUME)) {
- PathState hit_state = state;
-
-#ifdef __EMISSION__
- /* direct light */
- if(kernel_data.integrator.use_direct_light) {
- bool all = kernel_data.integrator.sample_all_lights_direct;
- kernel_branched_path_surface_connect_light(kg, rng,
- &sd, &hit_state, throughput, 1.0f, &L, all);
- }
-#endif
-
- /* indirect light */
- kernel_branched_path_surface_indirect_light(kg, rng,
- &sd, throughput, 1.0f, &hit_state, &L);
-
- /* continue in case of transparency */
- throughput *= shader_bsdf_transparency(kg, &sd);
-
- if(is_zero(throughput))
- break;
- }
-
- path_state_next(kg, &state, LABEL_TRANSPARENT);
- ray.P = ray_offset(sd.P, -sd.Ng);
- ray.t -= sd.ray_length; /* clipping works through transparent */
-
-
-#ifdef __RAY_DIFFERENTIALS__
- ray.dP = sd.dP;
- ray.dD.dx = -sd.dI.dx;
- ray.dD.dy = -sd.dI.dy;
-#endif
-
-#ifdef __VOLUME__
- /* enter/exit volume */
- kernel_volume_stack_enter_exit(kg, &sd, state.volume_stack);
+#ifdef __KERNEL_DEBUG__
+ kernel_write_debug_passes(kg, buffer, &state, &debug_data, sample);
#endif
- }
-
- float3 L_sum = path_radiance_clamp_and_sum(kg, &L);
-
- kernel_write_light_passes(kg, buffer, &L, sample);
return make_float4(L_sum.x, L_sum.y, L_sum.z, 1.0f - L_transparent);
}
-#endif
-
-ccl_device_inline void kernel_path_trace_setup(KernelGlobals *kg, ccl_global uint *rng_state, int sample, int x, int y, RNG *rng, Ray *ray)
-{
- float filter_u;
- float filter_v;
-
- int num_samples = kernel_data.integrator.aa_samples;
-
- path_rng_init(kg, rng_state, sample, num_samples, rng, x, y, &filter_u, &filter_v);
-
- /* sample camera ray */
-
- float lens_u = 0.0f, lens_v = 0.0f;
-
- if(kernel_data.cam.aperturesize > 0.0f)
- path_rng_2D(kg, rng, sample, num_samples, PRNG_LENS_U, &lens_u, &lens_v);
-
- float time = 0.0f;
-
-#ifdef __CAMERA_MOTION__
- if(kernel_data.cam.shuttertime != -1.0f)
- time = path_rng_1D(kg, rng, sample, num_samples, PRNG_TIME);
-#endif
-
- camera_sample(kg, x, y, filter_u, filter_v, lens_u, lens_v, time, ray);
-}
-
ccl_device void kernel_path_trace(KernelGlobals *kg,
ccl_global float *buffer, ccl_global uint *rng_state,
int sample, int x, int y, int offset, int stride)
@@ -1202,38 +702,5 @@ ccl_device void kernel_path_trace(KernelGlobals *kg,
path_rng_end(kg, rng_state, rng);
}
-#ifdef __BRANCHED_PATH__
-ccl_device void kernel_branched_path_trace(KernelGlobals *kg,
- ccl_global float *buffer, ccl_global uint *rng_state,
- int sample, int x, int y, int offset, int stride)
-{
- /* buffer offset */
- int index = offset + x + y*stride;
- int pass_stride = kernel_data.film.pass_stride;
-
- rng_state += index;
- buffer += index*pass_stride;
-
- /* initialize random numbers and ray */
- RNG rng;
- Ray ray;
-
- kernel_path_trace_setup(kg, rng_state, sample, x, y, &rng, &ray);
-
- /* integrate */
- float4 L;
-
- if(ray.t != 0.0f)
- L = kernel_branched_path_integrate(kg, &rng, sample, ray, buffer);
- else
- L = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
-
- /* accumulate result in output buffer */
- kernel_write_pass_float4(buffer, sample, L);
-
- path_rng_end(kg, rng_state, rng);
-}
-#endif
-
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/kernel_path_branched.h b/intern/cycles/kernel/kernel_path_branched.h
new file mode 100644
index 00000000000..b6d64985f6a
--- /dev/null
+++ b/intern/cycles/kernel/kernel_path_branched.h
@@ -0,0 +1,534 @@
+/*
+ * 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.
+ */
+
+CCL_NAMESPACE_BEGIN
+
+#ifdef __BRANCHED_PATH__
+
+ccl_device void kernel_branched_path_ao(KernelGlobals *kg, ShaderData *sd, PathRadiance *L, PathState *state, RNG *rng, float3 throughput)
+{
+ int num_samples = kernel_data.integrator.ao_samples;
+ float num_samples_inv = 1.0f/num_samples;
+ float ao_factor = kernel_data.background.ao_factor;
+ float3 ao_N;
+ float3 ao_bsdf = shader_bsdf_ao(kg, sd, ao_factor, &ao_N);
+ float3 ao_alpha = shader_bsdf_alpha(kg, sd);
+
+ for(int j = 0; j < num_samples; j++) {
+ float bsdf_u, bsdf_v;
+ path_branched_rng_2D(kg, rng, state, j, num_samples, PRNG_BSDF_U, &bsdf_u, &bsdf_v);
+
+ float3 ao_D;
+ float ao_pdf;
+
+ sample_cos_hemisphere(ao_N, bsdf_u, bsdf_v, &ao_D, &ao_pdf);
+
+ if(dot(ccl_fetch(sd, Ng), ao_D) > 0.0f && ao_pdf != 0.0f) {
+ Ray light_ray;
+ float3 ao_shadow;
+
+ light_ray.P = ray_offset(ccl_fetch(sd, P), ccl_fetch(sd, Ng));
+ light_ray.D = ao_D;
+ light_ray.t = kernel_data.background.ao_distance;
+#ifdef __OBJECT_MOTION__
+ light_ray.time = ccl_fetch(sd, time);
+#endif
+ light_ray.dP = ccl_fetch(sd, dP);
+ light_ray.dD = differential3_zero();
+
+ if(!shadow_blocked(kg, state, &light_ray, &ao_shadow))
+ path_radiance_accum_ao(L, throughput*num_samples_inv, ao_alpha, ao_bsdf, ao_shadow, state->bounce);
+ }
+ }
+}
+
+
+/* bounce off surface and integrate indirect light */
+ccl_device_noinline void kernel_branched_path_surface_indirect_light(KernelGlobals *kg,
+ RNG *rng, ShaderData *sd, float3 throughput, float num_samples_adjust,
+ PathState *state, PathRadiance *L)
+{
+ for(int i = 0; i < ccl_fetch(sd, num_closure); i++) {
+ const ShaderClosure *sc = &ccl_fetch(sd, closure)[i];
+
+ if(!CLOSURE_IS_BSDF(sc->type))
+ continue;
+ /* transparency is not handled here, but in outer loop */
+ if(sc->type == CLOSURE_BSDF_TRANSPARENT_ID)
+ continue;
+
+ int num_samples;
+
+ if(CLOSURE_IS_BSDF_DIFFUSE(sc->type))
+ num_samples = kernel_data.integrator.diffuse_samples;
+ else if(CLOSURE_IS_BSDF_BSSRDF(sc->type))
+ num_samples = 1;
+ else if(CLOSURE_IS_BSDF_GLOSSY(sc->type))
+ num_samples = kernel_data.integrator.glossy_samples;
+ else
+ num_samples = kernel_data.integrator.transmission_samples;
+
+ num_samples = ceil_to_int(num_samples_adjust*num_samples);
+
+ float num_samples_inv = num_samples_adjust/num_samples;
+ RNG bsdf_rng = cmj_hash(*rng, i);
+
+ for(int j = 0; j < num_samples; j++) {
+ PathState ps = *state;
+ float3 tp = throughput;
+ Ray bsdf_ray;
+
+ if(!kernel_branched_path_surface_bounce(kg, &bsdf_rng, sd, sc, j, num_samples, &tp, &ps, L, &bsdf_ray))
+ continue;
+
+ kernel_path_indirect(kg, rng, bsdf_ray, tp*num_samples_inv, num_samples, ps, L);
+
+ /* for render passes, sum and reset indirect light pass variables
+ * for the next samples */
+ path_radiance_sum_indirect(L);
+ path_radiance_reset_indirect(L);
+ }
+ }
+}
+
+#ifdef __SUBSURFACE__
+ccl_device void kernel_branched_path_subsurface_scatter(KernelGlobals *kg,
+ ShaderData *sd,
+ PathRadiance *L,
+ PathState *state,
+ RNG *rng,
+ Ray *ray,
+ float3 throughput)
+{
+ for(int i = 0; i < ccl_fetch(sd, num_closure); i++) {
+ ShaderClosure *sc = &ccl_fetch(sd, closure)[i];
+
+ if(!CLOSURE_IS_BSSRDF(sc->type))
+ continue;
+
+ /* set up random number generator */
+ uint lcg_state = lcg_state_init(rng, state, 0x68bc21eb);
+ int num_samples = kernel_data.integrator.subsurface_samples;
+ float num_samples_inv = 1.0f/num_samples;
+ RNG bssrdf_rng = cmj_hash(*rng, i);
+
+ /* do subsurface scatter step with copy of shader data, this will
+ * replace the BSSRDF with a diffuse BSDF closure */
+ for(int j = 0; j < num_samples; j++) {
+ ShaderData bssrdf_sd[BSSRDF_MAX_HITS];
+ float bssrdf_u, bssrdf_v;
+ path_branched_rng_2D(kg, &bssrdf_rng, state, j, num_samples, PRNG_BSDF_U, &bssrdf_u, &bssrdf_v);
+ int num_hits = subsurface_scatter_multi_step(kg, sd, bssrdf_sd, state->flag, sc, &lcg_state, bssrdf_u, bssrdf_v, true);
+#ifdef __VOLUME__
+ Ray volume_ray = *ray;
+ bool need_update_volume_stack = kernel_data.integrator.use_volumes &&
+ ccl_fetch(sd, flag) & SD_OBJECT_INTERSECTS_VOLUME;
+#endif
+
+ /* compute lighting with the BSDF closure */
+ for(int hit = 0; hit < num_hits; hit++) {
+ PathState hit_state = *state;
+
+ path_state_branch(&hit_state, j, num_samples);
+
+#ifdef __VOLUME__
+ if(need_update_volume_stack) {
+ /* Setup ray from previous surface point to the new one. */
+ float3 P = ray_offset(bssrdf_sd[hit].P, -bssrdf_sd[hit].Ng);
+ volume_ray.D = normalize_len(P - volume_ray.P,
+ &volume_ray.t);
+
+ kernel_volume_stack_update_for_subsurface(
+ kg,
+ &volume_ray,
+ hit_state.volume_stack);
+
+ /* Move volume ray forward. */
+ volume_ray.P = P;
+ }
+#endif
+
+#ifdef __EMISSION__
+ /* direct light */
+ if(kernel_data.integrator.use_direct_light) {
+ bool all = kernel_data.integrator.sample_all_lights_direct;
+ kernel_branched_path_surface_connect_light(kg, rng,
+ &bssrdf_sd[hit], &hit_state, throughput, num_samples_inv, L, all);
+ }
+#endif
+
+ /* indirect light */
+ kernel_branched_path_surface_indirect_light(kg, rng,
+ &bssrdf_sd[hit], throughput, num_samples_inv,
+ &hit_state, L);
+ }
+ }
+ }
+}
+#endif
+
+ccl_device float4 kernel_branched_path_integrate(KernelGlobals *kg, RNG *rng, int sample, Ray ray, ccl_global float *buffer)
+{
+ /* initialize */
+ PathRadiance L;
+ float3 throughput = make_float3(1.0f, 1.0f, 1.0f);
+ float L_transparent = 0.0f;
+
+ path_radiance_init(&L, kernel_data.film.use_light_pass);
+
+ PathState state;
+ path_state_init(kg, &state, rng, sample, &ray);
+
+#ifdef __KERNEL_DEBUG__
+ DebugData debug_data;
+ debug_data_init(&debug_data);
+#endif
+
+ /* Main Loop
+ * Here we only handle transparency intersections from the camera ray.
+ * Indirect bounces are handled in kernel_branched_path_surface_indirect_light().
+ */
+ for(;;) {
+ /* intersect scene */
+ Intersection isect;
+ uint visibility = path_state_ray_visibility(kg, &state);
+
+#ifdef __HAIR__
+ float difl = 0.0f, extmax = 0.0f;
+ uint lcg_state = 0;
+
+ if(kernel_data.bvh.have_curves) {
+ if(kernel_data.cam.resolution == 1) {
+ float3 pixdiff = ray.dD.dx + ray.dD.dy;
+ /*pixdiff = pixdiff - dot(pixdiff, ray.D)*ray.D;*/
+ difl = kernel_data.curve.minimum_width * len(pixdiff) * 0.5f;
+ }
+
+ extmax = kernel_data.curve.maximum_width;
+ lcg_state = lcg_state_init(rng, &state, 0x51633e2d);
+ }
+
+ bool hit = scene_intersect(kg, &ray, visibility, &isect, &lcg_state, difl, extmax);
+#else
+ bool hit = scene_intersect(kg, &ray, visibility, &isect, NULL, 0.0f, 0.0f);
+#endif
+
+#ifdef __KERNEL_DEBUG__
+ debug_data.num_bvh_traversal_steps += isect.num_traversal_steps;
+ debug_data.num_bvh_traversed_instances += isect.num_traversed_instances;
+ debug_data.num_ray_bounces++;
+#endif
+
+#ifdef __VOLUME__
+ /* volume attenuation, emission, scatter */
+ if(state.volume_stack[0].shader != SHADER_NONE) {
+ Ray volume_ray = ray;
+ volume_ray.t = (hit)? isect.t: FLT_MAX;
+
+ bool heterogeneous = volume_stack_is_heterogeneous(kg, state.volume_stack);
+
+#ifdef __VOLUME_DECOUPLED__
+ /* decoupled ray marching only supported on CPU */
+
+ /* cache steps along volume for repeated sampling */
+ VolumeSegment volume_segment;
+ ShaderData volume_sd;
+
+ shader_setup_from_volume(kg, &volume_sd, &volume_ray, state.bounce, state.transparent_bounce);
+ kernel_volume_decoupled_record(kg, &state,
+ &volume_ray, &volume_sd, &volume_segment, heterogeneous);
+
+ /* direct light sampling */
+ if(volume_segment.closure_flag & SD_SCATTER) {
+ volume_segment.sampling_method = volume_stack_sampling_method(kg, state.volume_stack);
+
+ bool all = kernel_data.integrator.sample_all_lights_direct;
+
+ kernel_branched_path_volume_connect_light(kg, rng, &volume_sd,
+ throughput, &state, &L, all, &volume_ray, &volume_segment);
+
+ /* indirect light sampling */
+ int num_samples = kernel_data.integrator.volume_samples;
+ float num_samples_inv = 1.0f/num_samples;
+
+ for(int j = 0; j < num_samples; j++) {
+ /* workaround to fix correlation bug in T38710, can find better solution
+ * in random number generator later, for now this is done here to not impact
+ * performance of rendering without volumes */
+ RNG tmp_rng = cmj_hash(*rng, state.rng_offset);
+
+ PathState ps = state;
+ Ray pray = ray;
+ float3 tp = throughput;
+
+ /* branch RNG state */
+ path_state_branch(&ps, j, num_samples);
+
+ /* scatter sample. if we use distance sampling and take just one
+ * sample for direct and indirect light, we could share this
+ * computation, but makes code a bit complex */
+ float rphase = path_state_rng_1D_for_decision(kg, &tmp_rng, &ps, PRNG_PHASE);
+ float rscatter = path_state_rng_1D_for_decision(kg, &tmp_rng, &ps, PRNG_SCATTER_DISTANCE);
+
+ VolumeIntegrateResult result = kernel_volume_decoupled_scatter(kg,
+ &ps, &pray, &volume_sd, &tp, rphase, rscatter, &volume_segment, NULL, false);
+
+ (void)result;
+ kernel_assert(result == VOLUME_PATH_SCATTERED);
+
+ if(kernel_path_volume_bounce(kg, rng, &volume_sd, &tp, &ps, &L, &pray)) {
+ kernel_path_indirect(kg, rng, pray, tp*num_samples_inv, num_samples, ps, &L);
+
+ /* for render passes, sum and reset indirect light pass variables
+ * for the next samples */
+ path_radiance_sum_indirect(&L);
+ path_radiance_reset_indirect(&L);
+ }
+ }
+ }
+
+ /* emission and transmittance */
+ if(volume_segment.closure_flag & SD_EMISSION)
+ path_radiance_accum_emission(&L, throughput, volume_segment.accum_emission, state.bounce);
+ throughput *= volume_segment.accum_transmittance;
+
+ /* free cached steps */
+ kernel_volume_decoupled_free(kg, &volume_segment);
+#else
+ /* GPU: no decoupled ray marching, scatter probalistically */
+ int num_samples = kernel_data.integrator.volume_samples;
+ float num_samples_inv = 1.0f/num_samples;
+
+ /* todo: we should cache the shader evaluations from stepping
+ * through the volume, for now we redo them multiple times */
+
+ for(int j = 0; j < num_samples; j++) {
+ PathState ps = state;
+ Ray pray = ray;
+ ShaderData volume_sd;
+ float3 tp = throughput * num_samples_inv;
+
+ /* branch RNG state */
+ path_state_branch(&ps, j, num_samples);
+
+ VolumeIntegrateResult result = kernel_volume_integrate(
+ kg, &ps, &volume_sd, &volume_ray, &L, &tp, rng, heterogeneous);
+
+#ifdef __VOLUME_SCATTER__
+ if(result == VOLUME_PATH_SCATTERED) {
+ /* todo: support equiangular, MIS and all light sampling.
+ * alternatively get decoupled ray marching working on the GPU */
+ kernel_path_volume_connect_light(kg, rng, &volume_sd, tp, &state, &L);
+
+ if(kernel_path_volume_bounce(kg, rng, &volume_sd, &tp, &ps, &L, &pray)) {
+ kernel_path_indirect(kg, rng, pray, tp, num_samples, ps, &L);
+
+ /* for render passes, sum and reset indirect light pass variables
+ * for the next samples */
+ path_radiance_sum_indirect(&L);
+ path_radiance_reset_indirect(&L);
+ }
+ }
+#endif
+ }
+
+ /* todo: avoid this calculation using decoupled ray marching */
+ kernel_volume_shadow(kg, &state, &volume_ray, &throughput);
+#endif
+ }
+#endif
+
+ if(!hit) {
+ /* eval background shader if nothing hit */
+ if(kernel_data.background.transparent) {
+ L_transparent += average(throughput);
+
+#ifdef __PASSES__
+ if(!(kernel_data.film.pass_flag & PASS_BACKGROUND))
+#endif
+ break;
+ }
+
+#ifdef __BACKGROUND__
+ /* sample background shader */
+ float3 L_background = indirect_background(kg, &state, &ray);
+ path_radiance_accum_background(&L, throughput, L_background, state.bounce);
+#endif
+
+ break;
+ }
+
+ /* setup shading */
+ ShaderData sd;
+ shader_setup_from_ray(kg, &sd, &isect, &ray, state.bounce, state.transparent_bounce);
+ shader_eval_surface(kg, &sd, 0.0f, state.flag, SHADER_CONTEXT_MAIN);
+ shader_merge_closures(&sd);
+
+ /* holdout */
+#ifdef __HOLDOUT__
+ if(sd.flag & (SD_HOLDOUT|SD_HOLDOUT_MASK)) {
+ if(kernel_data.background.transparent) {
+ float3 holdout_weight;
+
+ if(sd.flag & SD_HOLDOUT_MASK)
+ holdout_weight = make_float3(1.0f, 1.0f, 1.0f);
+ else
+ holdout_weight = shader_holdout_eval(kg, &sd);
+
+ /* any throughput is ok, should all be identical here */
+ L_transparent += average(holdout_weight*throughput);
+ }
+
+ if(sd.flag & SD_HOLDOUT_MASK)
+ break;
+ }
+#endif
+
+ /* holdout mask objects do not write data passes */
+ kernel_write_data_passes(kg, buffer, &L, &sd, sample, &state, throughput);
+
+#ifdef __EMISSION__
+ /* emission */
+ if(sd.flag & SD_EMISSION) {
+ float3 emission = indirect_primitive_emission(kg, &sd, isect.t, state.flag, state.ray_pdf);
+ path_radiance_accum_emission(&L, throughput, emission, state.bounce);
+ }
+#endif
+
+ /* transparency termination */
+ if(state.flag & PATH_RAY_TRANSPARENT) {
+ /* path termination. this is a strange place to put the termination, it's
+ * mainly due to the mixed in MIS that we use. gives too many unneeded
+ * shader evaluations, only need emission if we are going to terminate */
+ float probability = path_state_terminate_probability(kg, &state, throughput);
+
+ if(probability == 0.0f) {
+ break;
+ }
+ else if(probability != 1.0f) {
+ float terminate = path_state_rng_1D_for_decision(kg, rng, &state, PRNG_TERMINATE);
+
+ if(terminate >= probability)
+ break;
+
+ throughput /= probability;
+ }
+ }
+
+#ifdef __AO__
+ /* ambient occlusion */
+ if(kernel_data.integrator.use_ambient_occlusion || (sd.flag & SD_AO)) {
+ kernel_branched_path_ao(kg, &sd, &L, &state, rng, throughput);
+ }
+#endif
+
+#ifdef __SUBSURFACE__
+ /* bssrdf scatter to a different location on the same object */
+ if(sd.flag & SD_BSSRDF) {
+ kernel_branched_path_subsurface_scatter(kg, &sd, &L, &state,
+ rng, &ray, throughput);
+ }
+#endif
+
+ if(!(sd.flag & SD_HAS_ONLY_VOLUME)) {
+ PathState hit_state = state;
+
+#ifdef __EMISSION__
+ /* direct light */
+ if(kernel_data.integrator.use_direct_light) {
+ bool all = kernel_data.integrator.sample_all_lights_direct;
+ kernel_branched_path_surface_connect_light(kg, rng,
+ &sd, &hit_state, throughput, 1.0f, &L, all);
+ }
+#endif
+
+ /* indirect light */
+ kernel_branched_path_surface_indirect_light(kg, rng,
+ &sd, throughput, 1.0f, &hit_state, &L);
+
+ /* continue in case of transparency */
+ throughput *= shader_bsdf_transparency(kg, &sd);
+
+ if(is_zero(throughput))
+ break;
+ }
+
+ /* Update Path State */
+ state.flag |= PATH_RAY_TRANSPARENT;
+ state.transparent_bounce++;
+
+ ray.P = ray_offset(sd.P, -sd.Ng);
+ ray.t -= sd.ray_length; /* clipping works through transparent */
+
+
+#ifdef __RAY_DIFFERENTIALS__
+ ray.dP = sd.dP;
+ ray.dD.dx = -sd.dI.dx;
+ ray.dD.dy = -sd.dI.dy;
+#endif
+
+#ifdef __VOLUME__
+ /* enter/exit volume */
+ kernel_volume_stack_enter_exit(kg, &sd, state.volume_stack);
+#endif
+ }
+
+ float3 L_sum = path_radiance_clamp_and_sum(kg, &L);
+
+ kernel_write_light_passes(kg, buffer, &L, sample);
+
+#ifdef __KERNEL_DEBUG__
+ kernel_write_debug_passes(kg, buffer, &state, &debug_data, sample);
+#endif
+
+ return make_float4(L_sum.x, L_sum.y, L_sum.z, 1.0f - L_transparent);
+}
+
+ccl_device void kernel_branched_path_trace(KernelGlobals *kg,
+ ccl_global float *buffer, ccl_global uint *rng_state,
+ int sample, int x, int y, int offset, int stride)
+{
+ /* buffer offset */
+ int index = offset + x + y*stride;
+ int pass_stride = kernel_data.film.pass_stride;
+
+ rng_state += index;
+ buffer += index*pass_stride;
+
+ /* initialize random numbers and ray */
+ RNG rng;
+ Ray ray;
+
+ kernel_path_trace_setup(kg, rng_state, sample, x, y, &rng, &ray);
+
+ /* integrate */
+ float4 L;
+
+ if(ray.t != 0.0f)
+ L = kernel_branched_path_integrate(kg, &rng, sample, ray, buffer);
+ else
+ L = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
+
+ /* accumulate result in output buffer */
+ kernel_write_pass_float4(buffer, sample, L);
+
+ path_rng_end(kg, rng_state, rng);
+}
+
+#endif /* __BRANCHED_PATH__ */
+
+CCL_NAMESPACE_END
+
diff --git a/intern/cycles/kernel/kernel_path_common.h b/intern/cycles/kernel/kernel_path_common.h
new file mode 100644
index 00000000000..1912dfa16ed
--- /dev/null
+++ b/intern/cycles/kernel/kernel_path_common.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2011-2015 Blender Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+CCL_NAMESPACE_BEGIN
+
+ccl_device_inline void kernel_path_trace_setup(KernelGlobals *kg,
+ ccl_global uint *rng_state,
+ int sample,
+ int x, int y,
+ ccl_addr_space RNG *rng,
+ ccl_addr_space Ray *ray)
+{
+ float filter_u;
+ float filter_v;
+
+ int num_samples = kernel_data.integrator.aa_samples;
+
+ path_rng_init(kg, rng_state, sample, num_samples, rng, x, y, &filter_u, &filter_v);
+
+ /* sample camera ray */
+
+ float lens_u = 0.0f, lens_v = 0.0f;
+
+ if(kernel_data.cam.aperturesize > 0.0f)
+ path_rng_2D(kg, rng, sample, num_samples, PRNG_LENS_U, &lens_u, &lens_v);
+
+ float time = 0.0f;
+
+#ifdef __CAMERA_MOTION__
+ if(kernel_data.cam.shuttertime != -1.0f)
+ time = path_rng_1D(kg, rng, sample, num_samples, PRNG_TIME);
+#endif
+
+ camera_sample(kg, x, y, filter_u, filter_v, lens_u, lens_v, time, ray);
+}
+
+CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/kernel_path_state.h b/intern/cycles/kernel/kernel_path_state.h
index f29168642a4..15efb2371de 100644
--- a/intern/cycles/kernel/kernel_path_state.h
+++ b/intern/cycles/kernel/kernel_path_state.h
@@ -11,12 +11,12 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
CCL_NAMESPACE_BEGIN
-ccl_device_inline void path_state_init(KernelGlobals *kg, PathState *state, RNG *rng, int sample, Ray *ray)
+ccl_device_inline void path_state_init(KernelGlobals *kg, ccl_addr_space PathState *state, ccl_addr_space RNG *rng, int sample, ccl_addr_space Ray *ray)
{
state->flag = PATH_RAY_CAMERA|PATH_RAY_MIS_SKIP;
@@ -51,7 +51,7 @@ ccl_device_inline void path_state_init(KernelGlobals *kg, PathState *state, RNG
#endif
}
-ccl_device_inline void path_state_next(KernelGlobals *kg, PathState *state, int label)
+ccl_device_inline void path_state_next(KernelGlobals *kg, ccl_addr_space PathState *state, int label)
{
/* ray through transparent keeps same flags from previous ray and is
* not counted as a regular bounce, transparent has separate max */
@@ -106,7 +106,7 @@ ccl_device_inline void path_state_next(KernelGlobals *kg, PathState *state, int
state->flag &= ~(PATH_RAY_GLOSSY|PATH_RAY_SINGULAR|PATH_RAY_MIS_SKIP);
}
else if(label & LABEL_GLOSSY) {
- state->flag |= PATH_RAY_GLOSSY|PATH_RAY_GLOSSY_ANCESTOR;
+ state->flag |= PATH_RAY_GLOSSY;
state->flag &= ~(PATH_RAY_DIFFUSE|PATH_RAY_SINGULAR|PATH_RAY_MIS_SKIP);
}
else {
@@ -138,7 +138,7 @@ ccl_device_inline uint path_state_ray_visibility(KernelGlobals *kg, PathState *s
return flag;
}
-ccl_device_inline float path_state_terminate_probability(KernelGlobals *kg, PathState *state, const float3 throughput)
+ccl_device_inline float path_state_terminate_probability(KernelGlobals *kg, ccl_addr_space PathState *state, const float3 throughput)
{
if(state->flag & PATH_RAY_TRANSPARENT) {
/* transparent rays treated separately */
diff --git a/intern/cycles/kernel/kernel_path_surface.h b/intern/cycles/kernel/kernel_path_surface.h
index 9553c2da0df..fe85a6b6e4b 100644
--- a/intern/cycles/kernel/kernel_path_surface.h
+++ b/intern/cycles/kernel/kernel_path_surface.h
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
CCL_NAMESPACE_BEGIN
@@ -24,7 +24,7 @@ ccl_device void kernel_branched_path_surface_connect_light(KernelGlobals *kg, RN
{
#ifdef __EMISSION__
/* sample illumination from lights to find path contribution */
- if(!(sd->flag & SD_BSDF_HAS_EVAL))
+ if(!(ccl_fetch(sd, flag) & SD_BSDF_HAS_EVAL))
return;
Ray light_ray;
@@ -32,12 +32,15 @@ ccl_device void kernel_branched_path_surface_connect_light(KernelGlobals *kg, RN
bool is_lamp;
#ifdef __OBJECT_MOTION__
- light_ray.time = sd->time;
+ light_ray.time = ccl_fetch(sd, time);
#endif
if(sample_all_lights) {
/* lamp sampling */
for(int i = 0; i < kernel_data.integrator.num_all_lights; i++) {
+ if(UNLIKELY(light_select_reached_max_bounces(kg, i, state->bounce)))
+ continue;
+
int num_samples = ceil_to_int(num_samples_adjust*light_select_num_samples(kg, i));
float num_samples_inv = num_samples_adjust/(num_samples*kernel_data.integrator.num_all_lights);
RNG lamp_rng = cmj_hash(*rng, i);
@@ -50,7 +53,7 @@ ccl_device void kernel_branched_path_surface_connect_light(KernelGlobals *kg, RN
path_branched_rng_2D(kg, &lamp_rng, state, j, num_samples, PRNG_LIGHT_U, &light_u, &light_v);
LightSample ls;
- lamp_light_sample(kg, i, light_u, light_v, sd->P, &ls);
+ lamp_light_sample(kg, i, light_u, light_v, ccl_fetch(sd, P), &ls);
if(direct_emission(kg, sd, &ls, &light_ray, &L_light, &is_lamp, state->bounce, state->transparent_bounce)) {
/* trace shadow ray */
@@ -82,7 +85,7 @@ ccl_device void kernel_branched_path_surface_connect_light(KernelGlobals *kg, RN
light_t = 0.5f*light_t;
LightSample ls;
- light_sample(kg, light_t, light_u, light_v, sd->time, sd->P, &ls);
+ light_sample(kg, light_t, light_u, light_v, ccl_fetch(sd, time), ccl_fetch(sd, P), state->bounce, &ls);
if(direct_emission(kg, sd, &ls, &light_ray, &L_light, &is_lamp, state->bounce, state->transparent_bounce)) {
/* trace shadow ray */
@@ -103,7 +106,7 @@ ccl_device void kernel_branched_path_surface_connect_light(KernelGlobals *kg, RN
path_state_rng_2D(kg, rng, state, PRNG_LIGHT_U, &light_u, &light_v);
LightSample ls;
- light_sample(kg, light_t, light_u, light_v, sd->time, sd->P, &ls);
+ light_sample(kg, light_t, light_u, light_v, ccl_fetch(sd, time), ccl_fetch(sd, P), state->bounce, &ls);
/* sample random light */
if(direct_emission(kg, sd, &ls, &light_ray, &L_light, &is_lamp, state->bounce, state->transparent_bounce)) {
@@ -146,15 +149,15 @@ ccl_device bool kernel_branched_path_surface_bounce(KernelGlobals *kg, RNG *rng,
path_state_next(kg, state, label);
/* setup ray */
- ray->P = ray_offset(sd->P, (label & LABEL_TRANSMIT)? -sd->Ng: sd->Ng);
+ ray->P = ray_offset(ccl_fetch(sd, P), (label & LABEL_TRANSMIT)? -ccl_fetch(sd, Ng): ccl_fetch(sd, Ng));
ray->D = bsdf_omega_in;
ray->t = FLT_MAX;
#ifdef __RAY_DIFFERENTIALS__
- ray->dP = sd->dP;
+ ray->dP = ccl_fetch(sd, dP);
ray->dD = bsdf_domega_in;
#endif
#ifdef __OBJECT_MOTION__
- ray->time = sd->time;
+ ray->time = ccl_fetch(sd, time);
#endif
#ifdef __VOLUME__
@@ -178,12 +181,13 @@ ccl_device bool kernel_branched_path_surface_bounce(KernelGlobals *kg, RNG *rng,
#endif
+#ifndef __SPLIT_KERNEL__
/* path tracing: connect path directly to position on a light and add it to L */
-ccl_device_inline void kernel_path_surface_connect_light(KernelGlobals *kg, RNG *rng,
- ShaderData *sd, float3 throughput, PathState *state, PathRadiance *L)
+ccl_device_inline void kernel_path_surface_connect_light(KernelGlobals *kg, ccl_addr_space RNG *rng,
+ ShaderData *sd, float3 throughput, ccl_addr_space PathState *state, PathRadiance *L)
{
#ifdef __EMISSION__
- if(!(kernel_data.integrator.use_direct_light && (sd->flag & SD_BSDF_HAS_EVAL)))
+ if(!(kernel_data.integrator.use_direct_light && (ccl_fetch(sd, flag) & SD_BSDF_HAS_EVAL)))
return;
/* sample illumination from lights to find path contribution */
@@ -196,11 +200,11 @@ ccl_device_inline void kernel_path_surface_connect_light(KernelGlobals *kg, RNG
bool is_lamp;
#ifdef __OBJECT_MOTION__
- light_ray.time = sd->time;
+ light_ray.time = ccl_fetch(sd, time);
#endif
LightSample ls;
- light_sample(kg, light_t, light_u, light_v, sd->time, sd->P, &ls);
+ light_sample(kg, light_t, light_u, light_v, ccl_fetch(sd, time), ccl_fetch(sd, P), state->bounce, &ls);
if(direct_emission(kg, sd, &ls, &light_ray, &L_light, &is_lamp, state->bounce, state->transparent_bounce)) {
/* trace shadow ray */
@@ -213,13 +217,14 @@ ccl_device_inline void kernel_path_surface_connect_light(KernelGlobals *kg, RNG
}
#endif
}
+#endif
/* path tracing: bounce off or through surface to with new direction stored in ray */
-ccl_device_inline bool kernel_path_surface_bounce(KernelGlobals *kg, RNG *rng,
- ShaderData *sd, float3 *throughput, PathState *state, PathRadiance *L, Ray *ray)
+ccl_device_inline bool kernel_path_surface_bounce(KernelGlobals *kg, ccl_addr_space RNG *rng,
+ ShaderData *sd, ccl_addr_space float3 *throughput, ccl_addr_space PathState *state, PathRadiance *L, ccl_addr_space Ray *ray)
{
/* no BSDF? we can stop here */
- if(sd->flag & SD_BSDF) {
+ if(ccl_fetch(sd, flag) & SD_BSDF) {
/* sample BSDF */
float bsdf_pdf;
BsdfEval bsdf_eval;
@@ -251,16 +256,16 @@ ccl_device_inline bool kernel_path_surface_bounce(KernelGlobals *kg, RNG *rng,
path_state_next(kg, state, label);
/* setup ray */
- ray->P = ray_offset(sd->P, (label & LABEL_TRANSMIT)? -sd->Ng: sd->Ng);
+ ray->P = ray_offset(ccl_fetch(sd, P), (label & LABEL_TRANSMIT)? -ccl_fetch(sd, Ng): ccl_fetch(sd, Ng));
ray->D = bsdf_omega_in;
if(state->bounce == 0)
- ray->t -= sd->ray_length; /* clipping works through transparent */
+ ray->t -= ccl_fetch(sd, ray_length); /* clipping works through transparent */
else
ray->t = FLT_MAX;
#ifdef __RAY_DIFFERENTIALS__
- ray->dP = sd->dP;
+ ray->dP = ccl_fetch(sd, dP);
ray->dD = bsdf_domega_in;
#endif
@@ -272,16 +277,21 @@ ccl_device_inline bool kernel_path_surface_bounce(KernelGlobals *kg, RNG *rng,
return true;
}
#ifdef __VOLUME__
- else if(sd->flag & SD_HAS_ONLY_VOLUME) {
+ else if(ccl_fetch(sd, flag) & SD_HAS_ONLY_VOLUME) {
/* no surface shader but have a volume shader? act transparent */
/* update path state, count as transparent */
path_state_next(kg, state, LABEL_TRANSPARENT);
+ if(state->bounce == 0)
+ ray->t -= ccl_fetch(sd, ray_length); /* clipping works through transparent */
+ else
+ ray->t = FLT_MAX;
+
/* setup ray position, direction stays unchanged */
- ray->P = ray_offset(sd->P, -sd->Ng);
+ ray->P = ray_offset(ccl_fetch(sd, P), -ccl_fetch(sd, Ng));
#ifdef __RAY_DIFFERENTIALS__
- ray->dP = sd->dP;
+ ray->dP = ccl_fetch(sd, dP);
#endif
/* enter/exit volume */
diff --git a/intern/cycles/kernel/kernel_path_volume.h b/intern/cycles/kernel/kernel_path_volume.h
index da2d5e6eca8..82dc0f97622 100644
--- a/intern/cycles/kernel/kernel_path_volume.h
+++ b/intern/cycles/kernel/kernel_path_volume.h
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
CCL_NAMESPACE_BEGIN
@@ -40,7 +40,7 @@ ccl_device void kernel_path_volume_connect_light(KernelGlobals *kg, RNG *rng,
light_ray.time = sd->time;
#endif
- light_sample(kg, light_t, light_u, light_v, sd->time, sd->P, &ls);
+ light_sample(kg, light_t, light_u, light_v, sd->time, sd->P, state->bounce, &ls);
if(ls.pdf == 0.0f)
return;
@@ -56,7 +56,12 @@ ccl_device void kernel_path_volume_connect_light(KernelGlobals *kg, RNG *rng,
#endif
}
-ccl_device bool kernel_path_volume_bounce(KernelGlobals *kg, RNG *rng,
+#ifdef __KERNEL_GPU__
+ccl_device_noinline
+#else
+ccl_device
+#endif
+bool kernel_path_volume_bounce(KernelGlobals *kg, RNG *rng,
ShaderData *sd, float3 *throughput, PathState *state, PathRadiance *L, Ray *ray)
{
/* sample phase function */
@@ -102,7 +107,7 @@ ccl_device bool kernel_path_volume_bounce(KernelGlobals *kg, RNG *rng,
ccl_device void kernel_branched_path_volume_connect_light(KernelGlobals *kg, RNG *rng,
ShaderData *sd, float3 throughput, PathState *state, PathRadiance *L,
- float num_samples_adjust, bool sample_all_lights, Ray *ray, const VolumeSegment *segment)
+ bool sample_all_lights, Ray *ray, const VolumeSegment *segment)
{
#ifdef __EMISSION__
if(!kernel_data.integrator.use_direct_light)
@@ -119,8 +124,11 @@ ccl_device void kernel_branched_path_volume_connect_light(KernelGlobals *kg, RNG
if(sample_all_lights) {
/* lamp sampling */
for(int i = 0; i < kernel_data.integrator.num_all_lights; i++) {
- int num_samples = ceil_to_int(num_samples_adjust*light_select_num_samples(kg, i));
- float num_samples_inv = num_samples_adjust/(num_samples*kernel_data.integrator.num_all_lights);
+ if(UNLIKELY(light_select_reached_max_bounces(kg, i, state->bounce)))
+ continue;
+
+ int num_samples = light_select_num_samples(kg, i);
+ float num_samples_inv = 1.0f/(num_samples*kernel_data.integrator.num_all_lights);
RNG lamp_rng = cmj_hash(*rng, i);
if(kernel_data.integrator.pdf_triangles != 0.0f)
@@ -166,8 +174,8 @@ ccl_device void kernel_branched_path_volume_connect_light(KernelGlobals *kg, RNG
/* mesh light sampling */
if(kernel_data.integrator.pdf_triangles != 0.0f) {
- int num_samples = ceil_to_int(num_samples_adjust*kernel_data.integrator.mesh_light_samples);
- float num_samples_inv = num_samples_adjust/num_samples;
+ int num_samples = kernel_data.integrator.mesh_light_samples;
+ float num_samples_inv = 1.0f/num_samples;
if(kernel_data.integrator.num_all_lights)
num_samples_inv *= 0.5f;
@@ -183,7 +191,7 @@ ccl_device void kernel_branched_path_volume_connect_light(KernelGlobals *kg, RNG
light_t = 0.5f*light_t;
LightSample ls;
- light_sample(kg, light_t, light_u, light_v, sd->time, ray->P, &ls);
+ light_sample(kg, light_t, light_u, light_v, sd->time, ray->P, state->bounce, &ls);
float3 tp = throughput;
@@ -198,7 +206,7 @@ ccl_device void kernel_branched_path_volume_connect_light(KernelGlobals *kg, RNG
kernel_assert(result == VOLUME_PATH_SCATTERED);
/* todo: split up light_sample so we don't have to call it again with new position */
- light_sample(kg, light_t, light_u, light_v, sd->time, sd->P, &ls);
+ light_sample(kg, light_t, light_u, light_v, sd->time, sd->P, state->bounce, &ls);
if(ls.pdf == 0.0f)
continue;
@@ -222,7 +230,7 @@ ccl_device void kernel_branched_path_volume_connect_light(KernelGlobals *kg, RNG
path_state_rng_2D(kg, rng, state, PRNG_LIGHT_U, &light_u, &light_v);
LightSample ls;
- light_sample(kg, light_t, light_u, light_v, sd->time, ray->P, &ls);
+ light_sample(kg, light_t, light_u, light_v, sd->time, ray->P, state->bounce, &ls);
float3 tp = throughput;
@@ -237,7 +245,7 @@ ccl_device void kernel_branched_path_volume_connect_light(KernelGlobals *kg, RNG
kernel_assert(result == VOLUME_PATH_SCATTERED);
/* todo: split up light_sample so we don't have to call it again with new position */
- light_sample(kg, light_t, light_u, light_v, sd->time, sd->P, &ls);
+ light_sample(kg, light_t, light_u, light_v, sd->time, sd->P, state->bounce, &ls);
if(ls.pdf == 0.0f)
return;
diff --git a/intern/cycles/kernel/kernel_projection.h b/intern/cycles/kernel/kernel_projection.h
index 6744471d659..62922df3286 100644
--- a/intern/cycles/kernel/kernel_projection.h
+++ b/intern/cycles/kernel/kernel_projection.h
@@ -55,18 +55,18 @@ ccl_device float3 spherical_to_direction(float theta, float phi)
/* Equirectangular coordinates <-> Cartesian direction */
-ccl_device float2 direction_to_equirectangular(float3 dir)
+ccl_device float2 direction_to_equirectangular_range(float3 dir, float4 range)
{
- float u = -atan2f(dir.y, dir.x)/(M_2PI_F) + 0.5f;
- float v = atan2f(dir.z, hypotf(dir.x, dir.y))/M_PI_F + 0.5f;
+ float u = (atan2f(dir.y, dir.x) - range.y) / range.x;
+ float v = (acosf(dir.z / len(dir)) - range.w) / range.z;
return make_float2(u, v);
}
-ccl_device float3 equirectangular_to_direction(float u, float v)
+ccl_device float3 equirectangular_range_to_direction(float u, float v, float4 range)
{
- float phi = M_PI_F*(1.0f - 2.0f*u);
- float theta = M_PI_F*(1.0f - v);
+ float phi = range.x*u + range.y;
+ float theta = range.z*v + range.w;
return make_float3(
sinf(theta)*cosf(phi),
@@ -74,6 +74,16 @@ ccl_device float3 equirectangular_to_direction(float u, float v)
cosf(theta));
}
+ccl_device float2 direction_to_equirectangular(float3 dir)
+{
+ return direction_to_equirectangular_range(dir, make_float4(-M_2PI_F, M_PI_F, -M_PI_F, M_PI_F));
+}
+
+ccl_device float3 equirectangular_to_direction(float u, float v)
+{
+ return equirectangular_range_to_direction(u, v, make_float4(-M_2PI_F, M_PI_F, -M_PI_F, M_PI_F));
+}
+
/* Fisheye <-> Cartesian direction */
ccl_device float2 direction_to_fisheye(float3 dir, float fov)
@@ -153,6 +163,10 @@ ccl_device float3 mirrorball_to_direction(float u, float v)
dir.x = 2.0f*u - 1.0f;
dir.z = 2.0f*v - 1.0f;
+
+ if(dir.x*dir.x + dir.z*dir.z > 1.0f)
+ return make_float3(0.0f, 0.0f, 0.0f);
+
dir.y = -sqrtf(max(1.0f - dir.x*dir.x - dir.z*dir.z, 0.0f));
/* reflection */
@@ -180,7 +194,9 @@ ccl_device float3 panorama_to_direction(KernelGlobals *kg, float u, float v)
{
switch(kernel_data.cam.panorama_type) {
case PANORAMA_EQUIRECTANGULAR:
- return equirectangular_to_direction(u, v);
+ return equirectangular_range_to_direction(u, v, kernel_data.cam.equirectangular_range);
+ case PANORAMA_MIRRORBALL:
+ return mirrorball_to_direction(u, v);
case PANORAMA_FISHEYE_EQUIDISTANT:
return fisheye_to_direction(u, v, kernel_data.cam.fisheye_fov);
case PANORAMA_FISHEYE_EQUISOLID:
@@ -194,7 +210,9 @@ ccl_device float2 direction_to_panorama(KernelGlobals *kg, float3 dir)
{
switch(kernel_data.cam.panorama_type) {
case PANORAMA_EQUIRECTANGULAR:
- return direction_to_equirectangular(dir);
+ return direction_to_equirectangular_range(dir, kernel_data.cam.equirectangular_range);
+ case PANORAMA_MIRRORBALL:
+ return direction_to_mirrorball(dir);
case PANORAMA_FISHEYE_EQUIDISTANT:
return direction_to_fisheye(dir, kernel_data.cam.fisheye_fov);
case PANORAMA_FISHEYE_EQUISOLID:
diff --git a/intern/cycles/kernel/kernel_queues.h b/intern/cycles/kernel/kernel_queues.h
new file mode 100644
index 00000000000..cf5614b8a86
--- /dev/null
+++ b/intern/cycles/kernel/kernel_queues.h
@@ -0,0 +1,125 @@
+/*
+ * Copyright 2011-2015 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 __KERNEL_QUEUE_H__
+#define __KERNEL_QUEUE_H__
+
+/*
+ * Queue utility functions for split kernel
+ */
+
+#pragma OPENCL EXTENSION cl_khr_global_int32_base_atomics : enable
+#pragma OPENCL EXTENSION cl_khr_local_int32_base_atomics : enable
+
+/*
+ * Enqueue ray index into the queue
+ */
+ccl_device void enqueue_ray_index(
+ int ray_index, /* Ray index to be enqueued. */
+ int queue_number, /* Queue in which the ray index should be enqueued. */
+ ccl_global int *queues, /* Buffer of all queues. */
+ int queue_size, /* Size of each queue. */
+ ccl_global int *queue_index) /* Array of size num_queues; Used for atomic increment. */
+{
+ /* This thread's queue index. */
+ int my_queue_index = atomic_inc(&queue_index[queue_number]) + (queue_number * queue_size);
+ queues[my_queue_index] = ray_index;
+}
+
+/*
+ * Get the ray index for this thread
+ * Returns a positive ray_index for threads that have to do some work;
+ * Returns 'QUEUE_EMPTY_SLOT' for threads that don't have any work
+ * i.e All ray's in the queue has been successfully allocated and there
+ * is no more ray to allocate to other threads.
+ */
+ccl_device int get_ray_index(
+ int thread_index, /* Global thread index. */
+ int queue_number, /* Queue to operate on. */
+ ccl_global int *queues, /* Buffer of all queues. */
+ int queuesize, /* Size of a queue. */
+ int empty_queue) /* Empty the queue slot as soon as we fetch the ray index. */
+{
+ int ray_index = queues[queue_number * queuesize + thread_index];
+ if(empty_queue && ray_index != QUEUE_EMPTY_SLOT) {
+ queues[queue_number * queuesize + thread_index] = QUEUE_EMPTY_SLOT;
+ }
+ return ray_index;
+}
+
+/* The following functions are to realize Local memory variant of enqueue ray index function. */
+
+/* All threads should call this function. */
+ccl_device void enqueue_ray_index_local(
+ int ray_index, /* Ray index to enqueue. */
+ int queue_number, /* Queue in which to enqueue ray index. */
+ char enqueue_flag, /* True for threads whose ray index has to be enqueued. */
+ int queuesize, /* queue size. */
+ ccl_local unsigned int *local_queue_atomics, /* To to local queue atomics. */
+ ccl_global int *Queue_data, /* Queues. */
+ ccl_global int *Queue_index) /* To do global queue atomics. */
+{
+ int lidx = get_local_id(1) * get_local_size(0) + get_local_id(0);
+
+ /* Get local queue id .*/
+ unsigned int lqidx;
+ if(enqueue_flag) {
+ lqidx = atomic_inc(local_queue_atomics);
+ }
+ barrier(CLK_LOCAL_MEM_FENCE);
+
+ /* Get global queue offset. */
+ if(lidx == 0) {
+ *local_queue_atomics = atomic_add(&Queue_index[queue_number], *local_queue_atomics);
+ }
+ barrier(CLK_LOCAL_MEM_FENCE);
+
+ /* Get global queue index and enqueue ray. */
+ if(enqueue_flag) {
+ unsigned int my_gqidx = queue_number * queuesize + (*local_queue_atomics) + lqidx;
+ Queue_data[my_gqidx] = ray_index;
+ }
+}
+
+ccl_device unsigned int get_local_queue_index(
+ int queue_number, /* Queue in which to enqueue the ray; -1 if no queue */
+ ccl_local unsigned int *local_queue_atomics)
+{
+ int my_lqidx = atomic_inc(&local_queue_atomics[queue_number]);
+ return my_lqidx;
+}
+
+ccl_device unsigned int get_global_per_queue_offset(
+ int queue_number,
+ ccl_local unsigned int *local_queue_atomics,
+ ccl_global int* global_queue_atomics)
+{
+ unsigned int queue_offset = atomic_add(&global_queue_atomics[queue_number],
+ local_queue_atomics[queue_number]);
+ return queue_offset;
+}
+
+ccl_device unsigned int get_global_queue_index(
+ int queue_number,
+ int queuesize,
+ unsigned int lqidx,
+ ccl_local unsigned int * global_per_queue_offset)
+{
+ int my_gqidx = queuesize * queue_number + lqidx + global_per_queue_offset[queue_number];
+ return my_gqidx;
+}
+
+#endif // __KERNEL_QUEUE_H__
diff --git a/intern/cycles/kernel/kernel_random.h b/intern/cycles/kernel/kernel_random.h
index 236f74c0a82..631a2cb75de 100644
--- a/intern/cycles/kernel/kernel_random.h
+++ b/intern/cycles/kernel/kernel_random.h
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#include "kernel_jitter.h"
@@ -98,7 +98,7 @@ ccl_device uint sobol_lookup(const uint m, const uint frame, const uint ex, cons
return index;
}
-ccl_device_inline float path_rng_1D(KernelGlobals *kg, RNG *rng, int sample, int num_samples, int dimension)
+ccl_device_inline float path_rng_1D(KernelGlobals *kg, ccl_addr_space RNG *rng, int sample, int num_samples, int dimension)
{
#ifdef __CMJ__
if(kernel_data.integrator.sampling_pattern == SAMPLING_PATTERN_CMJ) {
@@ -132,7 +132,7 @@ ccl_device_inline float path_rng_1D(KernelGlobals *kg, RNG *rng, int sample, int
#endif
}
-ccl_device_inline void path_rng_2D(KernelGlobals *kg, RNG *rng, int sample, int num_samples, int dimension, float *fx, float *fy)
+ccl_device_inline void path_rng_2D(KernelGlobals *kg, ccl_addr_space RNG *rng, int sample, int num_samples, int dimension, float *fx, float *fy)
{
#ifdef __CMJ__
if(kernel_data.integrator.sampling_pattern == SAMPLING_PATTERN_CMJ) {
@@ -149,7 +149,7 @@ ccl_device_inline void path_rng_2D(KernelGlobals *kg, RNG *rng, int sample, int
}
}
-ccl_device_inline void path_rng_init(KernelGlobals *kg, ccl_global uint *rng_state, int sample, int num_samples, RNG *rng, int x, int y, float *fx, float *fy)
+ccl_device_inline void path_rng_init(KernelGlobals *kg, ccl_global uint *rng_state, int sample, int num_samples, ccl_addr_space RNG *rng, int x, int y, float *fx, float *fy)
{
#ifdef __SOBOL_FULL_SCREEN__
uint px, py;
@@ -261,12 +261,12 @@ ccl_device uint lcg_init(uint seed)
* For branches in the path we must be careful not to reuse the same number
* in a sequence and offset accordingly. */
-ccl_device_inline float path_state_rng_1D(KernelGlobals *kg, RNG *rng, const PathState *state, int dimension)
+ccl_device_inline float path_state_rng_1D(KernelGlobals *kg, ccl_addr_space RNG *rng, const ccl_addr_space PathState *state, int dimension)
{
return path_rng_1D(kg, rng, state->sample, state->num_samples, state->rng_offset + dimension);
}
-ccl_device_inline float path_state_rng_1D_for_decision(KernelGlobals *kg, RNG *rng, const PathState *state, int dimension)
+ccl_device_inline float path_state_rng_1D_for_decision(KernelGlobals *kg, ccl_addr_space RNG *rng, const ccl_addr_space PathState *state, int dimension)
{
/* the rng_offset is not increased for transparent bounces. if we do then
* fully transparent objects can become subtly visible by the different
@@ -279,23 +279,23 @@ ccl_device_inline float path_state_rng_1D_for_decision(KernelGlobals *kg, RNG *r
return path_rng_1D(kg, rng, state->sample, state->num_samples, rng_offset + dimension);
}
-ccl_device_inline void path_state_rng_2D(KernelGlobals *kg, RNG *rng, const PathState *state, int dimension, float *fx, float *fy)
+ccl_device_inline void path_state_rng_2D(KernelGlobals *kg, ccl_addr_space RNG *rng, const ccl_addr_space PathState *state, int dimension, float *fx, float *fy)
{
path_rng_2D(kg, rng, state->sample, state->num_samples, state->rng_offset + dimension, fx, fy);
}
-ccl_device_inline float path_branched_rng_1D(KernelGlobals *kg, RNG *rng, const PathState *state, int branch, int num_branches, int dimension)
+ccl_device_inline float path_branched_rng_1D(KernelGlobals *kg, ccl_addr_space RNG *rng, const PathState *state, int branch, int num_branches, int dimension)
{
return path_rng_1D(kg, rng, state->sample*num_branches + branch, state->num_samples*num_branches, state->rng_offset + dimension);
}
-ccl_device_inline float path_branched_rng_1D_for_decision(KernelGlobals *kg, RNG *rng, const PathState *state, int branch, int num_branches, int dimension)
+ccl_device_inline float path_branched_rng_1D_for_decision(KernelGlobals *kg, ccl_addr_space RNG *rng, const PathState *state, int branch, int num_branches, int dimension)
{
int rng_offset = state->rng_offset + state->transparent_bounce*PRNG_BOUNCE_NUM;
return path_rng_1D(kg, rng, state->sample*num_branches + branch, state->num_samples*num_branches, rng_offset + dimension);
}
-ccl_device_inline void path_branched_rng_2D(KernelGlobals *kg, RNG *rng, const PathState *state, int branch, int num_branches, int dimension, float *fx, float *fy)
+ccl_device_inline void path_branched_rng_2D(KernelGlobals *kg, ccl_addr_space RNG *rng, const PathState *state, int branch, int num_branches, int dimension, float *fx, float *fy)
{
path_rng_2D(kg, rng, state->sample*num_branches + branch, state->num_samples*num_branches, state->rng_offset + dimension, fx, fy);
}
diff --git a/intern/cycles/kernel/kernel_shader.h b/intern/cycles/kernel/kernel_shader.h
index db08c328d7e..6b560f5fdb2 100644
--- a/intern/cycles/kernel/kernel_shader.h
+++ b/intern/cycles/kernel/kernel_shader.h
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
/*
@@ -37,13 +37,13 @@ CCL_NAMESPACE_BEGIN
#ifdef __OBJECT_MOTION__
ccl_device void shader_setup_object_transforms(KernelGlobals *kg, ShaderData *sd, float time)
{
- if(sd->flag & SD_OBJECT_MOTION) {
- sd->ob_tfm = object_fetch_transform_motion(kg, sd->object, time);
- sd->ob_itfm = transform_quick_inverse(sd->ob_tfm);
+ if(ccl_fetch(sd, flag) & SD_OBJECT_MOTION) {
+ ccl_fetch(sd, ob_tfm) = object_fetch_transform_motion(kg, ccl_fetch(sd, object), time);
+ ccl_fetch(sd, ob_itfm) = transform_quick_inverse(ccl_fetch(sd, ob_tfm));
}
else {
- sd->ob_tfm = object_fetch_transform(kg, sd->object, OBJECT_TRANSFORM);
- sd->ob_itfm = object_fetch_transform(kg, sd->object, OBJECT_INVERSE_TRANSFORM);
+ ccl_fetch(sd, ob_tfm) = object_fetch_transform(kg, ccl_fetch(sd, object), OBJECT_TRANSFORM);
+ ccl_fetch(sd, ob_itfm) = object_fetch_transform(kg, ccl_fetch(sd, object), OBJECT_INVERSE_TRANSFORM);
}
}
#endif
@@ -52,55 +52,55 @@ ccl_device void shader_setup_from_ray(KernelGlobals *kg, ShaderData *sd,
const Intersection *isect, const Ray *ray, int bounce, int transparent_bounce)
{
#ifdef __INSTANCING__
- sd->object = (isect->object == PRIM_NONE)? kernel_tex_fetch(__prim_object, isect->prim): isect->object;
+ ccl_fetch(sd, object) = (isect->object == PRIM_NONE)? kernel_tex_fetch(__prim_object, isect->prim): isect->object;
#endif
- sd->type = isect->type;
- sd->flag = kernel_tex_fetch(__object_flag, sd->object);
+ ccl_fetch(sd, type) = isect->type;
+ ccl_fetch(sd, flag) = kernel_tex_fetch(__object_flag, ccl_fetch(sd, object));
/* matrices and time */
#ifdef __OBJECT_MOTION__
shader_setup_object_transforms(kg, sd, ray->time);
- sd->time = ray->time;
+ ccl_fetch(sd, time) = ray->time;
#endif
- sd->prim = kernel_tex_fetch(__prim_index, isect->prim);
- sd->ray_length = isect->t;
- sd->ray_depth = bounce;
- sd->transparent_depth = transparent_bounce;
+ ccl_fetch(sd, prim) = kernel_tex_fetch(__prim_index, isect->prim);
+ ccl_fetch(sd, ray_length) = isect->t;
+ ccl_fetch(sd, ray_depth) = bounce;
+ ccl_fetch(sd, transparent_depth) = transparent_bounce;
#ifdef __UV__
- sd->u = isect->u;
- sd->v = isect->v;
+ ccl_fetch(sd, u) = isect->u;
+ ccl_fetch(sd, v) = isect->v;
#endif
#ifdef __HAIR__
- if(sd->type & PRIMITIVE_ALL_CURVE) {
+ if(ccl_fetch(sd, type) & PRIMITIVE_ALL_CURVE) {
/* curve */
- float4 curvedata = kernel_tex_fetch(__curves, sd->prim);
+ float4 curvedata = kernel_tex_fetch(__curves, ccl_fetch(sd, prim));
- sd->shader = __float_as_int(curvedata.z);
- sd->P = bvh_curve_refine(kg, sd, isect, ray);
+ ccl_fetch(sd, shader) = __float_as_int(curvedata.z);
+ ccl_fetch(sd, P) = bvh_curve_refine(kg, sd, isect, ray);
}
else
#endif
- if(sd->type & PRIMITIVE_TRIANGLE) {
+ if(ccl_fetch(sd, type) & PRIMITIVE_TRIANGLE) {
/* static triangle */
float3 Ng = triangle_normal(kg, sd);
- sd->shader = kernel_tex_fetch(__tri_shader, sd->prim);
+ ccl_fetch(sd, shader) = kernel_tex_fetch(__tri_shader, ccl_fetch(sd, prim));
/* vectors */
- sd->P = triangle_refine(kg, sd, isect, ray);
- sd->Ng = Ng;
- sd->N = Ng;
+ ccl_fetch(sd, P) = triangle_refine(kg, sd, isect, ray);
+ ccl_fetch(sd, Ng) = Ng;
+ ccl_fetch(sd, N) = Ng;
/* smooth normal */
- if(sd->shader & SHADER_SMOOTH_NORMAL)
- sd->N = triangle_smooth_normal(kg, sd->prim, sd->u, sd->v);
+ if(ccl_fetch(sd, shader) & SHADER_SMOOTH_NORMAL)
+ ccl_fetch(sd, N) = triangle_smooth_normal(kg, ccl_fetch(sd, prim), ccl_fetch(sd, u), ccl_fetch(sd, v));
#ifdef __DPDU__
/* dPdu/dPdv */
- triangle_dPdudv(kg, sd->prim, &sd->dPdu, &sd->dPdv);
+ triangle_dPdudv(kg, ccl_fetch(sd, prim), &ccl_fetch(sd, dPdu), &ccl_fetch(sd, dPdv));
#endif
}
else {
@@ -108,40 +108,40 @@ ccl_device void shader_setup_from_ray(KernelGlobals *kg, ShaderData *sd,
motion_triangle_shader_setup(kg, sd, isect, ray, false);
}
- sd->I = -ray->D;
+ ccl_fetch(sd, I) = -ray->D;
- sd->flag |= kernel_tex_fetch(__shader_flag, (sd->shader & SHADER_MASK)*2);
+ ccl_fetch(sd, flag) |= kernel_tex_fetch(__shader_flag, (ccl_fetch(sd, shader) & SHADER_MASK)*2);
#ifdef __INSTANCING__
if(isect->object != OBJECT_NONE) {
/* instance transform */
- object_normal_transform(kg, sd, &sd->N);
- object_normal_transform(kg, sd, &sd->Ng);
+ object_normal_transform_auto(kg, sd, &ccl_fetch(sd, N));
+ object_normal_transform_auto(kg, sd, &ccl_fetch(sd, Ng));
#ifdef __DPDU__
- object_dir_transform(kg, sd, &sd->dPdu);
- object_dir_transform(kg, sd, &sd->dPdv);
+ object_dir_transform_auto(kg, sd, &ccl_fetch(sd, dPdu));
+ object_dir_transform_auto(kg, sd, &ccl_fetch(sd, dPdv));
#endif
}
#endif
/* backfacing test */
- bool backfacing = (dot(sd->Ng, sd->I) < 0.0f);
+ bool backfacing = (dot(ccl_fetch(sd, Ng), ccl_fetch(sd, I)) < 0.0f);
if(backfacing) {
- sd->flag |= SD_BACKFACING;
- sd->Ng = -sd->Ng;
- sd->N = -sd->N;
+ ccl_fetch(sd, flag) |= SD_BACKFACING;
+ ccl_fetch(sd, Ng) = -ccl_fetch(sd, Ng);
+ ccl_fetch(sd, N) = -ccl_fetch(sd, N);
#ifdef __DPDU__
- sd->dPdu = -sd->dPdu;
- sd->dPdv = -sd->dPdv;
+ ccl_fetch(sd, dPdu) = -ccl_fetch(sd, dPdu);
+ ccl_fetch(sd, dPdv) = -ccl_fetch(sd, dPdv);
#endif
}
#ifdef __RAY_DIFFERENTIALS__
/* differentials */
- differential_transfer(&sd->dP, ray->dP, ray->D, ray->dD, sd->Ng, isect->t);
- differential_incoming(&sd->dI, ray->dD);
- differential_dudv(&sd->du, &sd->dv, sd->dPdu, sd->dPdv, sd->dP, sd->Ng);
+ differential_transfer(&ccl_fetch(sd, dP), ray->dP, ray->D, ray->dD, ccl_fetch(sd, Ng), isect->t);
+ differential_incoming(&ccl_fetch(sd, dI), ray->dD);
+ differential_dudv(&ccl_fetch(sd, du), &ccl_fetch(sd, dv), ccl_fetch(sd, dPdu), ccl_fetch(sd, dPdv), ccl_fetch(sd, dP), ccl_fetch(sd, Ng));
#endif
}
@@ -166,7 +166,7 @@ ccl_device_inline void shader_setup_from_subsurface(KernelGlobals *kg, ShaderDat
/* fetch triangle data */
if(sd->type == PRIMITIVE_TRIANGLE) {
float3 Ng = triangle_normal(kg, sd);
- sd->shader = kernel_tex_fetch(__tri_shader, sd->prim);
+ sd->shader = kernel_tex_fetch(__tri_shader, sd->prim);
/* static triangle */
sd->P = triangle_refine_subsurface(kg, sd, isect, ray);
@@ -230,105 +230,105 @@ ccl_device void shader_setup_from_sample(KernelGlobals *kg, ShaderData *sd,
int shader, int object, int prim, float u, float v, float t, float time, int bounce, int transparent_bounce)
{
/* vectors */
- sd->P = P;
- sd->N = Ng;
- sd->Ng = Ng;
- sd->I = I;
- sd->shader = shader;
- sd->type = (prim == PRIM_NONE)? PRIMITIVE_NONE: PRIMITIVE_TRIANGLE;
+ ccl_fetch(sd, P) = P;
+ ccl_fetch(sd, N) = Ng;
+ ccl_fetch(sd, Ng) = Ng;
+ ccl_fetch(sd, I) = I;
+ ccl_fetch(sd, shader) = shader;
+ ccl_fetch(sd, type) = (prim == PRIM_NONE)? PRIMITIVE_NONE: PRIMITIVE_TRIANGLE;
/* primitive */
#ifdef __INSTANCING__
- sd->object = object;
+ ccl_fetch(sd, object) = object;
#endif
/* currently no access to bvh prim index for strand sd->prim*/
- sd->prim = prim;
+ ccl_fetch(sd, prim) = prim;
#ifdef __UV__
- sd->u = u;
- sd->v = v;
+ ccl_fetch(sd, u) = u;
+ ccl_fetch(sd, v) = v;
#endif
- sd->ray_length = t;
- sd->ray_depth = bounce;
- sd->transparent_depth = transparent_bounce;
+ ccl_fetch(sd, ray_length) = t;
+ ccl_fetch(sd, ray_depth) = bounce;
+ ccl_fetch(sd, transparent_depth) = transparent_bounce;
/* detect instancing, for non-instanced the object index is -object-1 */
#ifdef __INSTANCING__
bool instanced = false;
- if(sd->prim != PRIM_NONE) {
- if(sd->object >= 0)
+ if(ccl_fetch(sd, prim) != PRIM_NONE) {
+ if(ccl_fetch(sd, object) >= 0)
instanced = true;
else
#endif
- sd->object = ~sd->object;
+ ccl_fetch(sd, object) = ~ccl_fetch(sd, object);
#ifdef __INSTANCING__
}
#endif
- sd->flag = kernel_tex_fetch(__shader_flag, (sd->shader & SHADER_MASK)*2);
- if(sd->object != OBJECT_NONE) {
- sd->flag |= kernel_tex_fetch(__object_flag, sd->object);
+ ccl_fetch(sd, flag) = kernel_tex_fetch(__shader_flag, (ccl_fetch(sd, shader) & SHADER_MASK)*2);
+ if(ccl_fetch(sd, object) != OBJECT_NONE) {
+ ccl_fetch(sd, flag) |= kernel_tex_fetch(__object_flag, ccl_fetch(sd, object));
#ifdef __OBJECT_MOTION__
shader_setup_object_transforms(kg, sd, time);
}
- sd->time = time;
+ ccl_fetch(sd, time) = time;
#else
}
#endif
- if(sd->type & PRIMITIVE_TRIANGLE) {
+ if(ccl_fetch(sd, type) & PRIMITIVE_TRIANGLE) {
/* smooth normal */
- if(sd->shader & SHADER_SMOOTH_NORMAL) {
- sd->N = triangle_smooth_normal(kg, sd->prim, sd->u, sd->v);
+ if(ccl_fetch(sd, shader) & SHADER_SMOOTH_NORMAL) {
+ ccl_fetch(sd, N) = triangle_smooth_normal(kg, ccl_fetch(sd, prim), ccl_fetch(sd, u), ccl_fetch(sd, v));
#ifdef __INSTANCING__
if(instanced)
- object_normal_transform(kg, sd, &sd->N);
+ object_normal_transform_auto(kg, sd, &ccl_fetch(sd, N));
#endif
}
/* dPdu/dPdv */
#ifdef __DPDU__
- triangle_dPdudv(kg, sd->prim, &sd->dPdu, &sd->dPdv);
+ triangle_dPdudv(kg, ccl_fetch(sd, prim), &ccl_fetch(sd, dPdu), &ccl_fetch(sd, dPdv));
#ifdef __INSTANCING__
if(instanced) {
- object_dir_transform(kg, sd, &sd->dPdu);
- object_dir_transform(kg, sd, &sd->dPdv);
+ object_dir_transform_auto(kg, sd, &ccl_fetch(sd, dPdu));
+ object_dir_transform_auto(kg, sd, &ccl_fetch(sd, dPdv));
}
#endif
#endif
}
else {
#ifdef __DPDU__
- sd->dPdu = make_float3(0.0f, 0.0f, 0.0f);
- sd->dPdv = make_float3(0.0f, 0.0f, 0.0f);
+ ccl_fetch(sd, dPdu) = make_float3(0.0f, 0.0f, 0.0f);
+ ccl_fetch(sd, dPdv) = make_float3(0.0f, 0.0f, 0.0f);
#endif
}
/* backfacing test */
- if(sd->prim != PRIM_NONE) {
- bool backfacing = (dot(sd->Ng, sd->I) < 0.0f);
+ if(ccl_fetch(sd, prim) != PRIM_NONE) {
+ bool backfacing = (dot(ccl_fetch(sd, Ng), ccl_fetch(sd, I)) < 0.0f);
if(backfacing) {
- sd->flag |= SD_BACKFACING;
- sd->Ng = -sd->Ng;
- sd->N = -sd->N;
+ ccl_fetch(sd, flag) |= SD_BACKFACING;
+ ccl_fetch(sd, Ng) = -ccl_fetch(sd, Ng);
+ ccl_fetch(sd, N) = -ccl_fetch(sd, N);
#ifdef __DPDU__
- sd->dPdu = -sd->dPdu;
- sd->dPdv = -sd->dPdv;
+ ccl_fetch(sd, dPdu) = -ccl_fetch(sd, dPdu);
+ ccl_fetch(sd, dPdv) = -ccl_fetch(sd, dPdv);
#endif
}
}
#ifdef __RAY_DIFFERENTIALS__
/* no ray differentials here yet */
- sd->dP = differential3_zero();
- sd->dI = differential3_zero();
- sd->du = differential_zero();
- sd->dv = differential_zero();
+ ccl_fetch(sd, dP) = differential3_zero();
+ ccl_fetch(sd, dI) = differential3_zero();
+ ccl_fetch(sd, du) = differential_zero();
+ ccl_fetch(sd, dv) = differential_zero();
#endif
}
@@ -355,47 +355,46 @@ ccl_device void shader_setup_from_displace(KernelGlobals *kg, ShaderData *sd,
ccl_device_inline void shader_setup_from_background(KernelGlobals *kg, ShaderData *sd, const Ray *ray, int bounce, int transparent_bounce)
{
/* vectors */
- sd->P = ray->D;
- sd->N = -ray->D;
- sd->Ng = -ray->D;
- sd->I = -ray->D;
- sd->shader = kernel_data.background.surface_shader;
- sd->flag = kernel_tex_fetch(__shader_flag, (sd->shader & SHADER_MASK)*2);
+ ccl_fetch(sd, P) = ray->D;
+ ccl_fetch(sd, N) = -ray->D;
+ ccl_fetch(sd, Ng) = -ray->D;
+ ccl_fetch(sd, I) = -ray->D;
+ ccl_fetch(sd, shader) = kernel_data.background.surface_shader;
+ ccl_fetch(sd, flag) = kernel_tex_fetch(__shader_flag, (ccl_fetch(sd, shader) & SHADER_MASK)*2);
#ifdef __OBJECT_MOTION__
- sd->time = ray->time;
+ ccl_fetch(sd, time) = ray->time;
#endif
- sd->ray_length = 0.0f;
- sd->ray_depth = bounce;
- sd->transparent_depth = transparent_bounce;
+ ccl_fetch(sd, ray_length) = 0.0f;
+ ccl_fetch(sd, ray_depth) = bounce;
+ ccl_fetch(sd, transparent_depth) = transparent_bounce;
#ifdef __INSTANCING__
- sd->object = PRIM_NONE;
+ ccl_fetch(sd, object) = PRIM_NONE;
#endif
- sd->prim = PRIM_NONE;
+ ccl_fetch(sd, prim) = PRIM_NONE;
#ifdef __UV__
- sd->u = 0.0f;
- sd->v = 0.0f;
+ ccl_fetch(sd, u) = 0.0f;
+ ccl_fetch(sd, v) = 0.0f;
#endif
#ifdef __DPDU__
/* dPdu/dPdv */
- sd->dPdu = make_float3(0.0f, 0.0f, 0.0f);
- sd->dPdv = make_float3(0.0f, 0.0f, 0.0f);
+ ccl_fetch(sd, dPdu) = make_float3(0.0f, 0.0f, 0.0f);
+ ccl_fetch(sd, dPdv) = make_float3(0.0f, 0.0f, 0.0f);
#endif
#ifdef __RAY_DIFFERENTIALS__
/* differentials */
- sd->dP = ray->dD;
- differential_incoming(&sd->dI, sd->dP);
- sd->du.dx = 0.0f;
- sd->du.dy = 0.0f;
- sd->dv.dx = 0.0f;
- sd->dv.dy = 0.0f;
+ ccl_fetch(sd, dP) = ray->dD;
+ differential_incoming(&ccl_fetch(sd, dI), ccl_fetch(sd, dP));
+ ccl_fetch(sd, du) = differential_zero();
+ ccl_fetch(sd, dv) = differential_zero();
#endif
}
/* ShaderData setup from point inside volume */
+#ifdef __VOLUME__
ccl_device_inline void shader_setup_from_volume(KernelGlobals *kg, ShaderData *sd, const Ray *ray, int bounce, int transparent_bounce)
{
/* vectors */
@@ -441,6 +440,7 @@ ccl_device_inline void shader_setup_from_volume(KernelGlobals *kg, ShaderData *s
sd->ray_P = ray->P;
sd->ray_dP = ray->dP;
}
+#endif
/* Merging */
@@ -459,7 +459,7 @@ ccl_device void shader_merge_closures(ShaderData *sd)
continue;
#endif
- if(!(sci->type == scj->type && sci->data0 == scj->data0 && sci->data1 == scj->data1))
+ if(!(sci->type == scj->type && sci->data0 == scj->data0 && sci->data1 == scj->data1 && sci->data2 == scj->data2))
continue;
if(CLOSURE_IS_BSDF_OR_BSSRDF(sci->type)) {
@@ -480,6 +480,7 @@ ccl_device void shader_merge_closures(ShaderData *sd)
}
sd->num_closure--;
+ kernel_assert(sd->num_closure >= 0);
j--;
}
}
@@ -493,11 +494,11 @@ ccl_device_inline void _shader_bsdf_multi_eval(KernelGlobals *kg, const ShaderDa
{
/* this is the veach one-sample model with balance heuristic, some pdf
* factors drop out when using balance heuristic weighting */
- for(int i = 0; i< sd->num_closure; i++) {
+ for(int i = 0; i < ccl_fetch(sd, num_closure); i++) {
if(i == skip_bsdf)
continue;
- const ShaderClosure *sc = &sd->closure[i];
+ const ShaderClosure *sc = ccl_fetch_array(sd, closure, i);
if(CLOSURE_IS_BSDF(sc->type)) {
float bsdf_pdf = 0.0f;
@@ -515,7 +516,7 @@ ccl_device_inline void _shader_bsdf_multi_eval(KernelGlobals *kg, const ShaderDa
*pdf = (sum_sample_weight > 0.0f)? sum_pdf/sum_sample_weight: 0.0f;
}
-ccl_device void shader_bsdf_eval(KernelGlobals *kg, const ShaderData *sd,
+ccl_device void shader_bsdf_eval(KernelGlobals *kg, ShaderData *sd,
const float3 omega_in, BsdfEval *eval, float *pdf)
{
bsdf_eval_init(eval, NBUILTIN_CLOSURES, make_float3(0.0f, 0.0f, 0.0f), kernel_data.film.use_light_pass);
@@ -529,22 +530,22 @@ ccl_device int shader_bsdf_sample(KernelGlobals *kg, const ShaderData *sd,
{
int sampled = 0;
- if(sd->num_closure > 1) {
+ if(ccl_fetch(sd, num_closure) > 1) {
/* pick a BSDF closure based on sample weights */
float sum = 0.0f;
- for(sampled = 0; sampled < sd->num_closure; sampled++) {
- const ShaderClosure *sc = &sd->closure[sampled];
+ for(sampled = 0; sampled < ccl_fetch(sd, num_closure); sampled++) {
+ const ShaderClosure *sc = ccl_fetch_array(sd, closure, sampled);
if(CLOSURE_IS_BSDF(sc->type))
sum += sc->sample_weight;
}
- float r = sd->randb_closure*sum;
+ float r = ccl_fetch(sd, randb_closure)*sum;
sum = 0.0f;
- for(sampled = 0; sampled < sd->num_closure; sampled++) {
- const ShaderClosure *sc = &sd->closure[sampled];
+ for(sampled = 0; sampled < ccl_fetch(sd, num_closure); sampled++) {
+ const ShaderClosure *sc = ccl_fetch_array(sd, closure, sampled);
if(CLOSURE_IS_BSDF(sc->type)) {
sum += sc->sample_weight;
@@ -554,13 +555,14 @@ ccl_device int shader_bsdf_sample(KernelGlobals *kg, const ShaderData *sd,
}
}
- if(sampled == sd->num_closure) {
+ if(sampled == ccl_fetch(sd, num_closure)) {
*pdf = 0.0f;
return LABEL_NONE;
}
}
- const ShaderClosure *sc = &sd->closure[sampled];
+ const ShaderClosure *sc = ccl_fetch_array(sd, closure, sampled);
+
int label;
float3 eval;
@@ -570,7 +572,7 @@ ccl_device int shader_bsdf_sample(KernelGlobals *kg, const ShaderData *sd,
if(*pdf != 0.0f) {
bsdf_eval_init(bsdf_eval, sc->type, eval*sc->weight, kernel_data.film.use_light_pass);
- if(sd->num_closure > 1) {
+ if(ccl_fetch(sd, num_closure) > 1) {
float sweight = sc->sample_weight;
_shader_bsdf_multi_eval(kg, sd, *omega_in, pdf, sampled, bsdf_eval, *pdf*sweight, sweight);
}
@@ -597,8 +599,8 @@ ccl_device int shader_bsdf_sample_closure(KernelGlobals *kg, const ShaderData *s
ccl_device void shader_bsdf_blur(KernelGlobals *kg, ShaderData *sd, float roughness)
{
- for(int i = 0; i< sd->num_closure; i++) {
- ShaderClosure *sc = &sd->closure[i];
+ for(int i = 0; i < ccl_fetch(sd, num_closure); i++) {
+ ShaderClosure *sc = ccl_fetch_array(sd, closure, i);
if(CLOSURE_IS_BSDF(sc->type))
bsdf_blur(kg, sc, roughness);
@@ -607,13 +609,13 @@ ccl_device void shader_bsdf_blur(KernelGlobals *kg, ShaderData *sd, float roughn
ccl_device float3 shader_bsdf_transparency(KernelGlobals *kg, ShaderData *sd)
{
- if(sd->flag & SD_HAS_ONLY_VOLUME)
+ if(ccl_fetch(sd, flag) & SD_HAS_ONLY_VOLUME)
return make_float3(1.0f, 1.0f, 1.0f);
float3 eval = make_float3(0.0f, 0.0f, 0.0f);
- for(int i = 0; i< sd->num_closure; i++) {
- ShaderClosure *sc = &sd->closure[i];
+ for(int i = 0; i < ccl_fetch(sd, num_closure); i++) {
+ ShaderClosure *sc = ccl_fetch_array(sd, closure, i);
if(sc->type == CLOSURE_BSDF_TRANSPARENT_ID) // todo: make this work for osl
eval += sc->weight;
@@ -636,8 +638,8 @@ ccl_device float3 shader_bsdf_diffuse(KernelGlobals *kg, ShaderData *sd)
{
float3 eval = make_float3(0.0f, 0.0f, 0.0f);
- for(int i = 0; i< sd->num_closure; i++) {
- ShaderClosure *sc = &sd->closure[i];
+ for(int i = 0; i < ccl_fetch(sd, num_closure); i++) {
+ ShaderClosure *sc = ccl_fetch_array(sd, closure, i);
if(CLOSURE_IS_BSDF_DIFFUSE(sc->type))
eval += sc->weight;
@@ -650,8 +652,8 @@ ccl_device float3 shader_bsdf_glossy(KernelGlobals *kg, ShaderData *sd)
{
float3 eval = make_float3(0.0f, 0.0f, 0.0f);
- for(int i = 0; i< sd->num_closure; i++) {
- ShaderClosure *sc = &sd->closure[i];
+ for(int i = 0; i < ccl_fetch(sd, num_closure); i++) {
+ ShaderClosure *sc = ccl_fetch_array(sd, closure, i);
if(CLOSURE_IS_BSDF_GLOSSY(sc->type))
eval += sc->weight;
@@ -664,8 +666,8 @@ ccl_device float3 shader_bsdf_transmission(KernelGlobals *kg, ShaderData *sd)
{
float3 eval = make_float3(0.0f, 0.0f, 0.0f);
- for(int i = 0; i< sd->num_closure; i++) {
- ShaderClosure *sc = &sd->closure[i];
+ for(int i = 0; i < ccl_fetch(sd, num_closure); i++) {
+ ShaderClosure *sc = ccl_fetch_array(sd, closure, i);
if(CLOSURE_IS_BSDF_TRANSMISSION(sc->type))
eval += sc->weight;
@@ -678,10 +680,10 @@ ccl_device float3 shader_bsdf_subsurface(KernelGlobals *kg, ShaderData *sd)
{
float3 eval = make_float3(0.0f, 0.0f, 0.0f);
- for(int i = 0; i< sd->num_closure; i++) {
- ShaderClosure *sc = &sd->closure[i];
+ for(int i = 0; i < ccl_fetch(sd, num_closure); i++) {
+ ShaderClosure *sc = ccl_fetch_array(sd, closure, i);
- if(CLOSURE_IS_BSSRDF(sc->type))
+ if(CLOSURE_IS_BSSRDF(sc->type) || CLOSURE_IS_BSDF_BSSRDF(sc->type))
eval += sc->weight;
}
@@ -693,8 +695,8 @@ ccl_device float3 shader_bsdf_ao(KernelGlobals *kg, ShaderData *sd, float ao_fac
float3 eval = make_float3(0.0f, 0.0f, 0.0f);
float3 N = make_float3(0.0f, 0.0f, 0.0f);
- for(int i = 0; i< sd->num_closure; i++) {
- ShaderClosure *sc = &sd->closure[i];
+ for(int i = 0; i < ccl_fetch(sd, num_closure); i++) {
+ ShaderClosure *sc = ccl_fetch_array(sd, closure, i);
if(CLOSURE_IS_BSDF_DIFFUSE(sc->type)) {
eval += sc->weight*ao_factor;
@@ -702,12 +704,12 @@ ccl_device float3 shader_bsdf_ao(KernelGlobals *kg, ShaderData *sd, float ao_fac
}
else if(CLOSURE_IS_AMBIENT_OCCLUSION(sc->type)) {
eval += sc->weight;
- N += sd->N*average(sc->weight);
+ N += ccl_fetch(sd, N)*average(sc->weight);
}
}
if(is_zero(N))
- N = sd->N;
+ N = ccl_fetch(sd, N);
else
N = normalize(N);
@@ -721,8 +723,8 @@ ccl_device float3 shader_bssrdf_sum(ShaderData *sd, float3 *N_, float *texture_b
float3 N = make_float3(0.0f, 0.0f, 0.0f);
float texture_blur = 0.0f, weight_sum = 0.0f;
- for(int i = 0; i< sd->num_closure; i++) {
- ShaderClosure *sc = &sd->closure[i];
+ for(int i = 0; i < ccl_fetch(sd, num_closure); i++) {
+ ShaderClosure *sc = ccl_fetch_array(sd, closure, i);
if(CLOSURE_IS_BSSRDF(sc->type)) {
float avg_weight = fabsf(average(sc->weight));
@@ -735,7 +737,7 @@ ccl_device float3 shader_bssrdf_sum(ShaderData *sd, float3 *N_, float *texture_b
}
if(N_)
- *N_ = (is_zero(N))? sd->N: normalize(N);
+ *N_ = (is_zero(N))? ccl_fetch(sd, N): normalize(N);
if(texture_blur_)
*texture_blur_ = texture_blur/weight_sum;
@@ -747,7 +749,7 @@ ccl_device float3 shader_bssrdf_sum(ShaderData *sd, float3 *N_, float *texture_b
ccl_device float3 emissive_eval(KernelGlobals *kg, ShaderData *sd, ShaderClosure *sc)
{
- return emissive_simple_eval(sd->Ng, sd->I);
+ return emissive_simple_eval(ccl_fetch(sd, Ng), ccl_fetch(sd, I));
}
ccl_device float3 shader_emissive_eval(KernelGlobals *kg, ShaderData *sd)
@@ -755,8 +757,8 @@ ccl_device float3 shader_emissive_eval(KernelGlobals *kg, ShaderData *sd)
float3 eval;
eval = make_float3(0.0f, 0.0f, 0.0f);
- for(int i = 0; i < sd->num_closure; i++) {
- ShaderClosure *sc = &sd->closure[i];
+ for(int i = 0; i < ccl_fetch(sd, num_closure); i++) {
+ ShaderClosure *sc = ccl_fetch_array(sd, closure, i);
if(CLOSURE_IS_EMISSION(sc->type))
eval += emissive_eval(kg, sd, sc)*sc->weight;
@@ -771,8 +773,8 @@ ccl_device float3 shader_holdout_eval(KernelGlobals *kg, ShaderData *sd)
{
float3 weight = make_float3(0.0f, 0.0f, 0.0f);
- for(int i = 0; i < sd->num_closure; i++) {
- ShaderClosure *sc = &sd->closure[i];
+ for(int i = 0; i < ccl_fetch(sd, num_closure); i++) {
+ ShaderClosure *sc = ccl_fetch_array(sd, closure, i);
if(CLOSURE_IS_HOLDOUT(sc->type))
weight += sc->weight;
@@ -786,8 +788,8 @@ ccl_device float3 shader_holdout_eval(KernelGlobals *kg, ShaderData *sd)
ccl_device void shader_eval_surface(KernelGlobals *kg, ShaderData *sd,
float randb, int path_flag, ShaderContext ctx)
{
- sd->num_closure = 0;
- sd->randb_closure = randb;
+ ccl_fetch(sd, num_closure) = 0;
+ ccl_fetch(sd, randb_closure) = randb;
#ifdef __OSL__
if(kg->osl)
@@ -798,9 +800,11 @@ ccl_device void shader_eval_surface(KernelGlobals *kg, ShaderData *sd,
#ifdef __SVM__
svm_eval_nodes(kg, sd, SHADER_TYPE_SURFACE, path_flag);
#else
- sd->closure->weight = make_float3(0.8f, 0.8f, 0.8f);
- sd->closure->N = sd->N;
- sd->flag |= bsdf_diffuse_setup(&sd->closure);
+ ccl_fetch_array(sd, closure, 0)->weight = make_float3(0.8f, 0.8f, 0.8f);
+ ccl_fetch_array(sd, closure, 0)->N = ccl_fetch(sd, N);
+ ccl_fetch_array(sd, closure, 0)->data0 = 0.0f;
+ ccl_fetch_array(sd, closure, 0)->data1 = 0.0f;
+ ccl_fetch(sd, flag) |= bsdf_diffuse_setup(ccl_fetch_array(sd, closure, 0));
#endif
}
}
@@ -809,8 +813,8 @@ ccl_device void shader_eval_surface(KernelGlobals *kg, ShaderData *sd,
ccl_device float3 shader_eval_background(KernelGlobals *kg, ShaderData *sd, int path_flag, ShaderContext ctx)
{
- sd->num_closure = 0;
- sd->randb_closure = 0.0f;
+ ccl_fetch(sd, num_closure) = 0;
+ ccl_fetch(sd, randb_closure) = 0.0f;
#ifdef __OSL__
if(kg->osl) {
@@ -825,8 +829,8 @@ ccl_device float3 shader_eval_background(KernelGlobals *kg, ShaderData *sd, int
float3 eval = make_float3(0.0f, 0.0f, 0.0f);
- for(int i = 0; i< sd->num_closure; i++) {
- const ShaderClosure *sc = &sd->closure[i];
+ for(int i = 0; i < ccl_fetch(sd, num_closure); i++) {
+ const ShaderClosure *sc = ccl_fetch_array(sd, closure, i);
if(CLOSURE_IS_BACKGROUND(sc->type))
eval += sc->weight;
@@ -846,7 +850,7 @@ ccl_device float3 shader_eval_background(KernelGlobals *kg, ShaderData *sd, int
ccl_device_inline void _shader_volume_phase_multi_eval(const ShaderData *sd, const float3 omega_in, float *pdf,
int skip_phase, BsdfEval *result_eval, float sum_pdf, float sum_sample_weight)
{
- for(int i = 0; i< sd->num_closure; i++) {
+ for(int i = 0; i < sd->num_closure; i++) {
if(i == skip_phase)
continue;
@@ -999,8 +1003,8 @@ ccl_device void shader_eval_volume(KernelGlobals *kg, ShaderData *sd,
ccl_device void shader_eval_displacement(KernelGlobals *kg, ShaderData *sd, ShaderContext ctx)
{
- sd->num_closure = 0;
- sd->randb_closure = 0.0f;
+ ccl_fetch(sd, num_closure) = 0;
+ ccl_fetch(sd, randb_closure) = 0.0f;
/* this will modify sd->P */
#ifdef __SVM__
diff --git a/intern/cycles/kernel/kernel_shaderdata_vars.h b/intern/cycles/kernel/kernel_shaderdata_vars.h
new file mode 100644
index 00000000000..b157b82e023
--- /dev/null
+++ b/intern/cycles/kernel/kernel_shaderdata_vars.h
@@ -0,0 +1,99 @@
+/*
+* Copyright 2011-2015 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 SD_VAR
+#define SD_VAR(type, what)
+#endif
+#ifndef SD_CLOSURE_VAR
+#define SD_CLOSURE_VAR(type, what, max_closure)
+#endif
+
+/* position */
+SD_VAR(float3, P)
+/* smooth normal for shading */
+SD_VAR(float3, N)
+/* true geometric normal */
+SD_VAR(float3, Ng)
+/* view/incoming direction */
+SD_VAR(float3, I)
+/* shader id */
+SD_VAR(int, shader)
+/* booleans describing shader, see ShaderDataFlag */
+SD_VAR(int, flag)
+
+/* primitive id if there is one, ~0 otherwise */
+SD_VAR(int, prim)
+
+/* combined type and curve segment for hair */
+SD_VAR(int, type)
+
+/* parametric coordinates
+* - barycentric weights for triangles */
+SD_VAR(float, u)
+SD_VAR(float, v)
+/* object id if there is one, ~0 otherwise */
+SD_VAR(int, object)
+
+/* motion blur sample time */
+SD_VAR(float, time)
+
+/* length of the ray being shaded */
+SD_VAR(float, ray_length)
+
+/* ray bounce depth */
+SD_VAR(int, ray_depth)
+
+/* ray transparent depth */
+SD_VAR(int, transparent_depth)
+
+#ifdef __RAY_DIFFERENTIALS__
+/* differential of P. these are orthogonal to Ng, not N */
+SD_VAR(differential3, dP)
+/* differential of I */
+SD_VAR(differential3, dI)
+/* differential of u, v */
+SD_VAR(differential, du)
+SD_VAR(differential, dv)
+#endif
+#ifdef __DPDU__
+/* differential of P w.r.t. parametric coordinates. note that dPdu is
+* not readily suitable as a tangent for shading on triangles. */
+SD_VAR(float3, dPdu)
+SD_VAR(float3, dPdv)
+#endif
+
+#ifdef __OBJECT_MOTION__
+/* object <-> world space transformations, cached to avoid
+* re-interpolating them constantly for shading */
+SD_VAR(Transform, ob_tfm)
+SD_VAR(Transform, ob_itfm)
+#endif
+
+/* Closure data, we store a fixed array of closures */
+SD_CLOSURE_VAR(ShaderClosure, closure, MAX_CLOSURE)
+SD_VAR(int, num_closure)
+SD_VAR(float, randb_closure)
+
+/* ray start position, only set for backgrounds */
+SD_VAR(float3, ray_P)
+SD_VAR(differential3, ray_dP)
+
+#ifdef __OSL__
+SD_VAR(struct KernelGlobals *, osl_globals)
+#endif
+
+#undef SD_VAR
+#undef SD_CLOSURE_VAR
diff --git a/intern/cycles/kernel/kernel_shadow.h b/intern/cycles/kernel/kernel_shadow.h
index 61954282c28..2811a8348ca 100644
--- a/intern/cycles/kernel/kernel_shadow.h
+++ b/intern/cycles/kernel/kernel_shadow.h
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
CCL_NAMESPACE_BEGIN
@@ -39,19 +39,6 @@ CCL_NAMESPACE_BEGIN
* This is CPU only because of qsort, and malloc or high stack space usage to
* record all these intersections. */
-ccl_device_noinline int shadow_intersections_compare(const void *a, const void *b)
-{
- const Intersection *isect_a = (const Intersection*)a;
- const Intersection *isect_b = (const Intersection*)b;
-
- if(isect_a->t < isect_b->t)
- return -1;
- else if(isect_a->t > isect_b->t)
- return 1;
- else
- return 0;
-}
-
#define STACK_MAX_HITS 64
ccl_device_inline bool shadow_blocked(KernelGlobals *kg, PathState *state, Ray *ray, float3 *shadow)
@@ -95,7 +82,7 @@ ccl_device_inline bool shadow_blocked(KernelGlobals *kg, PathState *state, Ray *
PathState ps = *state;
#endif
- qsort(hits, num_hits, sizeof(Intersection), shadow_intersections_compare);
+ qsort(hits, num_hits, sizeof(Intersection), intersections_compare);
for(int hit = 0; hit < num_hits; hit++, isect++) {
/* adjust intersection distance for moving ray forward */
@@ -193,19 +180,36 @@ ccl_device_inline bool shadow_blocked(KernelGlobals *kg, PathState *state, Ray *
* potentially transparent, and only in that case start marching. this gives
* one extra ray cast for the cases were we do want transparency. */
-ccl_device_inline bool shadow_blocked(KernelGlobals *kg, PathState *state, Ray *ray, float3 *shadow)
+ccl_device_inline bool shadow_blocked(KernelGlobals *kg, ccl_addr_space PathState *state, ccl_addr_space Ray *ray_input, float3 *shadow
+#ifdef __SPLIT_KERNEL__
+ , ShaderData *sd_mem, Intersection *isect_mem
+#endif
+ )
{
*shadow = make_float3(1.0f, 1.0f, 1.0f);
- if(ray->t == 0.0f)
+ if(ray_input->t == 0.0f)
return false;
- Intersection isect;
- bool blocked = scene_intersect(kg, ray, PATH_RAY_SHADOW_OPAQUE, &isect, NULL, 0.0f, 0.0f);
+#ifdef __SPLIT_KERNEL__
+ Ray private_ray = *ray_input;
+ Ray *ray = &private_ray;
+#else
+ Ray *ray = ray_input;
+#endif
+
+#ifdef __SPLIT_KERNEL__
+ Intersection *isect = isect_mem;
+#else
+ Intersection isect_object;
+ Intersection *isect = &isect_object;
+#endif
+
+ bool blocked = scene_intersect(kg, ray, PATH_RAY_SHADOW_OPAQUE, isect, NULL, 0.0f, 0.0f);
#ifdef __TRANSPARENT_SHADOWS__
if(blocked && kernel_data.integrator.transparent_shadows) {
- if(shader_transparent_shadow(kg, &isect)) {
+ if(shader_transparent_shadow(kg, isect)) {
float3 throughput = make_float3(1.0f, 1.0f, 1.0f);
float3 Pend = ray->P + ray->D*ray->t;
int bounce = state->transparent_bounce;
@@ -217,9 +221,8 @@ ccl_device_inline bool shadow_blocked(KernelGlobals *kg, PathState *state, Ray *
if(bounce >= kernel_data.integrator.transparent_max_bounce)
return true;
- if(!scene_intersect(kg, ray, PATH_RAY_SHADOW_TRANSPARENT, &isect, NULL, 0.0f, 0.0f))
+ if(!scene_intersect(kg, ray, PATH_RAY_SHADOW_TRANSPARENT, isect, NULL, 0.0f, 0.0f))
{
-
#ifdef __VOLUME__
/* attenuation for last line segment towards light */
if(ps.volume_stack[0].shader != SHADER_NONE)
@@ -231,39 +234,44 @@ ccl_device_inline bool shadow_blocked(KernelGlobals *kg, PathState *state, Ray *
return false;
}
- if(!shader_transparent_shadow(kg, &isect))
+ if(!shader_transparent_shadow(kg, isect))
return true;
#ifdef __VOLUME__
/* attenuation between last surface and next surface */
if(ps.volume_stack[0].shader != SHADER_NONE) {
Ray segment_ray = *ray;
- segment_ray.t = isect.t;
+ segment_ray.t = isect->t;
kernel_volume_shadow(kg, &ps, &segment_ray, &throughput);
}
#endif
/* setup shader data at surface */
- ShaderData sd;
- shader_setup_from_ray(kg, &sd, &isect, ray, state->bounce+1, bounce);
+#ifdef __SPLIT_KERNEL__
+ ShaderData *sd = sd_mem;
+#else
+ ShaderData sd_object;
+ ShaderData *sd = &sd_object;
+#endif
+ shader_setup_from_ray(kg, sd, isect, ray, state->bounce+1, bounce);
/* attenuation from transparent surface */
- if(!(sd.flag & SD_HAS_ONLY_VOLUME)) {
- shader_eval_surface(kg, &sd, 0.0f, PATH_RAY_SHADOW, SHADER_CONTEXT_SHADOW);
- throughput *= shader_bsdf_transparency(kg, &sd);
+ if(!(ccl_fetch(sd, flag) & SD_HAS_ONLY_VOLUME)) {
+ shader_eval_surface(kg, sd, 0.0f, PATH_RAY_SHADOW, SHADER_CONTEXT_SHADOW);
+ throughput *= shader_bsdf_transparency(kg, sd);
}
if(is_zero(throughput))
return true;
/* move ray forward */
- ray->P = ray_offset(sd.P, -sd.Ng);
+ ray->P = ray_offset(ccl_fetch(sd, P), -ccl_fetch(sd, Ng));
if(ray->t != FLT_MAX)
ray->D = normalize_len(Pend - ray->P, &ray->t);
#ifdef __VOLUME__
/* exit/enter volume */
- kernel_volume_stack_enter_exit(kg, &sd, ps.volume_stack);
+ kernel_volume_stack_enter_exit(kg, sd, ps.volume_stack);
#endif
bounce++;
diff --git a/intern/cycles/kernel/kernel_subsurface.h b/intern/cycles/kernel/kernel_subsurface.h
index fb927e81f22..2da060c32a2 100644
--- a/intern/cycles/kernel/kernel_subsurface.h
+++ b/intern/cycles/kernel/kernel_subsurface.h
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
CCL_NAMESPACE_BEGIN
diff --git a/intern/cycles/kernel/kernel_textures.h b/intern/cycles/kernel/kernel_textures.h
index ef46b2f707f..f545a056cc8 100644
--- a/intern/cycles/kernel/kernel_textures.h
+++ b/intern/cycles/kernel/kernel_textures.h
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#ifndef KERNEL_TEX
@@ -24,6 +24,7 @@
/* bvh */
KERNEL_TEX(float4, texture_float4, __bvh_nodes)
+KERNEL_TEX(float4, texture_float4, __bvh_leaf_nodes)
KERNEL_TEX(float4, texture_float4, __tri_woop)
KERNEL_TEX(uint, texture_uint, __prim_type)
KERNEL_TEX(uint, texture_uint, __prim_visibility)
diff --git a/intern/cycles/kernel/kernel_types.h b/intern/cycles/kernel/kernel_types.h
index 0ec34dae87a..60973a71d20 100644
--- a/intern/cycles/kernel/kernel_types.h
+++ b/intern/cycles/kernel/kernel_types.h
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#ifndef __KERNEL_TYPES_H__
@@ -24,12 +24,19 @@
#define __KERNEL_CPU__
#endif
+/* TODO(sergey): This is only to make it possible to include this header
+ * from outside of the kernel. but this could be done somewhat cleaner?
+ */
+#ifndef ccl_addr_space
+#define ccl_addr_space
+#endif
+
CCL_NAMESPACE_BEGIN
/* constants */
#define OBJECT_SIZE 11
#define OBJECT_VECTOR_SIZE 6
-#define LIGHT_SIZE 4
+#define LIGHT_SIZE 5
#define FILTER_TABLE_SIZE 256
#define RAMP_TABLE_SIZE 256
#define PARTICLE_SIZE 5
@@ -38,12 +45,6 @@ CCL_NAMESPACE_BEGIN
#define BSSRDF_MIN_RADIUS 1e-8f
#define BSSRDF_MAX_HITS 4
-#define BB_DRAPPER 800.0f
-#define BB_MAX_TABLE_RANGE 12000.0f
-#define BB_TABLE_XPOWER 1.5f
-#define BB_TABLE_YPOWER 5.0f
-#define BB_TABLE_SPACING 2.0f
-
#define BECKMANN_TABLE_SIZE 256
#define TEX_NUM_FLOAT_IMAGES 5
@@ -57,6 +58,9 @@ CCL_NAMESPACE_BEGIN
/* device capabilities */
#ifdef __KERNEL_CPU__
+#ifdef __KERNEL_SSE2__
+# define __QBVH__
+#endif
#define __KERNEL_SHADING__
#define __KERNEL_ADV_SHADING__
#define __BRANCHED_PATH__
@@ -69,6 +73,7 @@ CCL_NAMESPACE_BEGIN
#define __VOLUME_DECOUPLED__
#define __VOLUME_SCATTER__
#define __SHADOW_RECORD_ALL__
+#define __VOLUME_RECORD_ALL__
#define __CAMERA_RAY_NODES__
#endif
@@ -80,7 +85,7 @@ CCL_NAMESPACE_BEGIN
#define __VOLUME_SCATTER__
/* Experimental on GPU */
-#ifdef __KERNEL_CUDA_EXPERIMENTAL__
+#ifdef __KERNEL_EXPERIMENTAL__
#define __SUBSURFACE__
#define __CMJ__
#endif
@@ -92,38 +97,51 @@ CCL_NAMESPACE_BEGIN
/* keep __KERNEL_ADV_SHADING__ in sync with opencl_kernel_use_advanced_shading! */
#ifdef __KERNEL_OPENCL_NVIDIA__
-#define __KERNEL_SHADING__
-#define __KERNEL_ADV_SHADING__
+# define __KERNEL_SHADING__
+# define __KERNEL_ADV_SHADING__
+# ifdef __KERNEL_EXPERIMENTAL__
+# define __CMJ__
+# endif
#endif
#ifdef __KERNEL_OPENCL_APPLE__
-#define __KERNEL_SHADING__
-//#define __KERNEL_ADV_SHADING__
+# define __KERNEL_SHADING__
+# define __KERNEL_ADV_SHADING__
+/* TODO(sergey): Currently experimental section is ignored here,
+ * this is because megakernel in device_opencl does not support
+ * custom cflags depending on the scene features.
+ */
+# ifdef __KERNEL_EXPERIMENTAL__
+# define __CMJ__
+# endif
#endif
#ifdef __KERNEL_OPENCL_AMD__
-#define __CL_USE_NATIVE__
-#define __KERNEL_SHADING__
-//__KERNEL_ADV_SHADING__
-#define __MULTI_CLOSURE__
-#define __TRANSPARENT_SHADOWS__
-#define __PASSES__
-#define __BACKGROUND_MIS__
-#define __LAMP_MIS__
-#define __AO__
-//#define __CAMERA_MOTION__
-//#define __OBJECT_MOTION__
-//#define __HAIR__
-//end __KERNEL_ADV_SHADING__
+# define __CL_USE_NATIVE__
+# define __KERNEL_SHADING__
+# define __MULTI_CLOSURE__
+# define __PASSES__
+# define __BACKGROUND_MIS__
+# define __LAMP_MIS__
+# define __AO__
+# define __CAMERA_MOTION__
+# define __OBJECT_MOTION__
+# define __HAIR__
+# ifdef __KERNEL_EXPERIMENTAL__
+# define __TRANSPARENT_SHADOWS__
+# endif
#endif
#ifdef __KERNEL_OPENCL_INTEL_CPU__
-#define __CL_USE_NATIVE__
-#define __KERNEL_SHADING__
-#define __KERNEL_ADV_SHADING__
+# define __CL_USE_NATIVE__
+# define __KERNEL_SHADING__
+# define __KERNEL_ADV_SHADING__
+# ifdef __KERNEL_EXPERIMENTAL__
+# define __CMJ__
+# endif
#endif
-#endif
+#endif // __KERNEL_OPENCL__
/* kernel features */
#define __SOBOL__
@@ -158,6 +176,21 @@ CCL_NAMESPACE_BEGIN
#define __HAIR__
#endif
+#ifdef WITH_CYCLES_DEBUG
+# define __KERNEL_DEBUG__
+#endif
+
+/* Scene-based selective featrues compilation/ */
+#ifdef __NO_CAMERA_MOTION__
+# undef __CAMERA_MOTION__
+#endif
+#ifdef __NO_OBJECT_MOTION__
+# undef __OBJECT_MOTION__
+#endif
+#ifdef __NO_HAIR__
+# undef __HAIR__
+#endif
+
/* Random Numbers */
typedef uint RNG;
@@ -263,9 +296,7 @@ enum PathRayFlag {
PATH_RAY_MIS_SKIP = 2048,
PATH_RAY_DIFFUSE_ANCESTOR = 4096,
- PATH_RAY_GLOSSY_ANCESTOR = 8192,
- PATH_RAY_BSSRDF_ANCESTOR = 16384,
- PATH_RAY_SINGLE_PASS_DONE = 32768,
+ PATH_RAY_SINGLE_PASS_DONE = 8192,
/* we need layer member flags to be the 20 upper bits */
PATH_RAY_LAYER_SHIFT = (32-20)
@@ -288,39 +319,44 @@ typedef enum ClosureLabel {
typedef enum PassType {
PASS_NONE = 0,
- PASS_COMBINED = 1,
- PASS_DEPTH = 2,
- PASS_NORMAL = 4,
- PASS_UV = 8,
- PASS_OBJECT_ID = 16,
- PASS_MATERIAL_ID = 32,
- PASS_DIFFUSE_COLOR = 64,
- PASS_GLOSSY_COLOR = 128,
- PASS_TRANSMISSION_COLOR = 256,
- PASS_DIFFUSE_INDIRECT = 512,
- PASS_GLOSSY_INDIRECT = 1024,
- PASS_TRANSMISSION_INDIRECT = 2048,
- PASS_DIFFUSE_DIRECT = 4096,
- PASS_GLOSSY_DIRECT = 8192,
- PASS_TRANSMISSION_DIRECT = 16384,
- PASS_EMISSION = 32768,
- PASS_BACKGROUND = 65536,
- PASS_AO = 131072,
- PASS_SHADOW = 262144,
- PASS_MOTION = 524288,
- PASS_MOTION_WEIGHT = 1048576,
- PASS_MIST = 2097152,
- PASS_SUBSURFACE_DIRECT = 4194304,
- PASS_SUBSURFACE_INDIRECT = 8388608,
- PASS_SUBSURFACE_COLOR = 16777216,
- PASS_LIGHT = 33554432, /* no real pass, used to force use_light_pass */
+ PASS_COMBINED = (1 << 0),
+ PASS_DEPTH = (1 << 1),
+ PASS_NORMAL = (1 << 2),
+ PASS_UV = (1 << 3),
+ PASS_OBJECT_ID = (1 << 4),
+ PASS_MATERIAL_ID = (1 << 5),
+ PASS_DIFFUSE_COLOR = (1 << 6),
+ PASS_GLOSSY_COLOR = (1 << 7),
+ PASS_TRANSMISSION_COLOR = (1 << 8),
+ PASS_DIFFUSE_INDIRECT = (1 << 9),
+ PASS_GLOSSY_INDIRECT = (1 << 10),
+ PASS_TRANSMISSION_INDIRECT = (1 << 11),
+ PASS_DIFFUSE_DIRECT = (1 << 12),
+ PASS_GLOSSY_DIRECT = (1 << 13),
+ PASS_TRANSMISSION_DIRECT = (1 << 14),
+ PASS_EMISSION = (1 << 15),
+ PASS_BACKGROUND = (1 << 16),
+ PASS_AO = (1 << 17),
+ PASS_SHADOW = (1 << 18),
+ PASS_MOTION = (1 << 19),
+ PASS_MOTION_WEIGHT = (1 << 20),
+ PASS_MIST = (1 << 21),
+ PASS_SUBSURFACE_DIRECT = (1 << 22),
+ PASS_SUBSURFACE_INDIRECT = (1 << 23),
+ PASS_SUBSURFACE_COLOR = (1 << 24),
+ PASS_LIGHT = (1 << 25), /* no real pass, used to force use_light_pass */
+#ifdef __KERNEL_DEBUG__
+ PASS_BVH_TRAVERSAL_STEPS = (1 << 26),
+ PASS_BVH_TRAVERSED_INSTANCES = (1 << 27),
+ PASS_RAY_BOUNCES = (1 << 28),
+#endif
} PassType;
#define PASS_ALL (~0)
#ifdef __PASSES__
-typedef struct PathRadiance {
+typedef ccl_addr_space struct PathRadiance {
int use_light_pass;
float3 emission;
@@ -372,7 +408,7 @@ typedef struct BsdfEval {
#else
-typedef float3 PathRadiance;
+typedef ccl_addr_space float3 PathRadiance;
typedef float3 BsdfEval;
#endif
@@ -417,6 +453,7 @@ enum CameraType {
enum PanoramaType {
PANORAMA_EQUIRECTANGULAR,
+ PANORAMA_MIRRORBALL,
PANORAMA_FISHEYE_EQUIDISTANT,
PANORAMA_FISHEYE_EQUISOLID
};
@@ -436,10 +473,26 @@ typedef struct differential {
/* Ray */
typedef struct Ray {
+/* TODO(sergey): This is only needed because current AMD
+ * compiler has hard time building the kernel with this
+ * reshuffle. And at the same time reshuffle will cause
+ * less optimal CPU code in certain places.
+ *
+ * We'll get rid of this nasty exception once AMD compiler
+ * is fixed.
+ */
+#ifndef __KERNEL_OPENCL_AMD__
float3 P; /* origin */
float3 D; /* direction */
+
+ float t; /* length of the ray */
+ float time; /* time (for motion blur) */
+#else
float t; /* length of the ray */
float time; /* time (for motion blur) */
+ float3 P; /* origin */
+ float3 D; /* direction */
+#endif
#ifdef __RAY_DIFFERENTIALS__
differential3 dP;
@@ -449,11 +502,16 @@ typedef struct Ray {
/* Intersection */
-typedef struct Intersection {
+typedef ccl_addr_space struct Intersection {
float t, u, v;
int prim;
int object;
int type;
+
+#ifdef __KERNEL_DEBUG__
+ int num_traversal_steps;
+ int num_traversed_instances;
+#endif
} Intersection;
/* Primitives */
@@ -468,7 +526,12 @@ typedef enum PrimitiveType {
PRIMITIVE_ALL_TRIANGLE = (PRIMITIVE_TRIANGLE|PRIMITIVE_MOTION_TRIANGLE),
PRIMITIVE_ALL_CURVE = (PRIMITIVE_CURVE|PRIMITIVE_MOTION_CURVE),
PRIMITIVE_ALL_MOTION = (PRIMITIVE_MOTION_TRIANGLE|PRIMITIVE_MOTION_CURVE),
- PRIMITIVE_ALL = (PRIMITIVE_ALL_TRIANGLE|PRIMITIVE_ALL_CURVE)
+ PRIMITIVE_ALL = (PRIMITIVE_ALL_TRIANGLE|PRIMITIVE_ALL_CURVE),
+
+ /* Total number of different primitives.
+ * NOTE: This is an actual value, not a bitflag.
+ */
+ PRIMITIVE_NUM_TOTAL = 4,
} PrimitiveType;
#define PRIMITIVE_PACK_SEGMENT(type, segment) ((segment << 16) | type)
@@ -516,6 +579,7 @@ typedef enum AttributeStandard {
ATTR_STD_VOLUME_FLAME,
ATTR_STD_VOLUME_HEAT,
ATTR_STD_VOLUME_VELOCITY,
+ ATTR_STD_POINTINESS,
ATTR_STD_NUM,
ATTR_STD_NOT_FOUND = ~0
@@ -524,39 +588,34 @@ typedef enum AttributeStandard {
/* Closure data */
#ifdef __MULTI_CLOSURE__
-#define MAX_CLOSURE 64
+# ifndef __MAX_CLOSURE__
+# define MAX_CLOSURE 64
+# else
+# define MAX_CLOSURE __MAX_CLOSURE__
+# endif
#else
#define MAX_CLOSURE 1
#endif
-/* TODO(sergey): This is rather nasty bug happening in here, which
- * could be simply a compilers bug for which we can't find a generic
- * platform independent workaround. Also even if it's a compiler
- * issue, it's not so simple to upgrade the compiler in the release
- * environment for linux and doing it so closer to the release is
- * rather a risky business.
- *
- * For this release it's probably safer to stick with such a rather
- * dirty solution, and look for a cleaner fix during the next release
- * cycle.
+/* This struct is to be 16 bytes aligned, we also keep some extra precautions:
+ * - All the float3 members are in the beginning of the struct, so compiler
+ * does not put own padding trying to align this members.
+ * - We make sure OSL pointer is also 16 bytes aligned.
*/
-typedef struct ShaderClosure {
- ClosureType type;
+typedef ccl_addr_space struct ShaderClosure {
float3 weight;
-#ifndef __APPLE__
+ float3 N;
+ float3 T;
+
+ ClosureType type;
float sample_weight;
-#endif
float data0;
float data1;
float data2;
+ int pad1, pad2, pad3;
- float3 N;
- float3 T;
-#ifdef __APPLE__
- float sample_weight;
-#endif
#ifdef __OSL__
- void *prim;
+ void *prim, *pad4;
#endif
} ShaderClosure;
@@ -581,119 +640,70 @@ typedef enum ShaderContext {
enum ShaderDataFlag {
/* runtime flags */
- SD_BACKFACING = 1, /* backside of surface? */
- SD_EMISSION = 2, /* have emissive closure? */
- SD_BSDF = 4, /* have bsdf closure? */
- SD_BSDF_HAS_EVAL = 8, /* have non-singular bsdf closure? */
- SD_PHASE_HAS_EVAL = 8, /* have non-singular phase closure? */
- SD_BSDF_GLOSSY = 16, /* have glossy bsdf */
- SD_BSSRDF = 32, /* have bssrdf */
- SD_HOLDOUT = 64, /* have holdout closure? */
- SD_ABSORPTION = 128, /* have volume absorption closure? */
- SD_SCATTER = 256, /* have volume phase closure? */
- SD_AO = 512, /* have ao closure? */
- SD_TRANSPARENT = 1024, /* have transparent closure? */
-
- SD_CLOSURE_FLAGS = (SD_EMISSION|SD_BSDF|SD_BSDF_HAS_EVAL|SD_BSDF_GLOSSY|
- SD_BSSRDF|SD_HOLDOUT|SD_ABSORPTION|SD_SCATTER|SD_AO),
+ SD_BACKFACING = (1 << 0), /* backside of surface? */
+ SD_EMISSION = (1 << 1), /* have emissive closure? */
+ SD_BSDF = (1 << 2), /* have bsdf closure? */
+ SD_BSDF_HAS_EVAL = (1 << 3), /* have non-singular bsdf closure? */
+ SD_BSSRDF = (1 << 4), /* have bssrdf */
+ SD_HOLDOUT = (1 << 5), /* have holdout closure? */
+ SD_ABSORPTION = (1 << 6), /* have volume absorption closure? */
+ SD_SCATTER = (1 << 7), /* have volume phase closure? */
+ SD_AO = (1 << 8), /* have ao closure? */
+ SD_TRANSPARENT = (1 << 9), /* have transparent closure? */
+
+ SD_CLOSURE_FLAGS = (SD_EMISSION|SD_BSDF|SD_BSDF_HAS_EVAL|SD_BSSRDF|
+ SD_HOLDOUT|SD_ABSORPTION|SD_SCATTER|SD_AO),
/* shader flags */
- SD_USE_MIS = 2048, /* direct light sample */
- SD_HAS_TRANSPARENT_SHADOW = 4096, /* has transparent shadow */
- SD_HAS_VOLUME = 8192, /* has volume shader */
- SD_HAS_ONLY_VOLUME = 16384, /* has only volume shader, no surface */
- SD_HETEROGENEOUS_VOLUME = 32768, /* has heterogeneous volume */
- SD_HAS_BSSRDF_BUMP = 65536, /* bssrdf normal uses bump */
- SD_VOLUME_EQUIANGULAR = 131072, /* use equiangular sampling */
- SD_VOLUME_MIS = 262144, /* use multiple importance sampling */
+ SD_USE_MIS = (1 << 10), /* direct light sample */
+ SD_HAS_TRANSPARENT_SHADOW = (1 << 11), /* has transparent shadow */
+ SD_HAS_VOLUME = (1 << 12), /* has volume shader */
+ SD_HAS_ONLY_VOLUME = (1 << 13), /* has only volume shader, no surface */
+ SD_HETEROGENEOUS_VOLUME = (1 << 14), /* has heterogeneous volume */
+ SD_HAS_BSSRDF_BUMP = (1 << 15), /* bssrdf normal uses bump */
+ SD_VOLUME_EQUIANGULAR = (1 << 16), /* use equiangular sampling */
+ SD_VOLUME_MIS = (1 << 17), /* use multiple importance sampling */
+ SD_VOLUME_CUBIC = (1 << 18), /* use cubic interpolation for voxels */
+ SD_HAS_BUMP = (1 << 19), /* has data connected to the displacement input */
SD_SHADER_FLAGS = (SD_USE_MIS|SD_HAS_TRANSPARENT_SHADOW|SD_HAS_VOLUME|
SD_HAS_ONLY_VOLUME|SD_HETEROGENEOUS_VOLUME|
- SD_HAS_BSSRDF_BUMP|SD_VOLUME_EQUIANGULAR|SD_VOLUME_MIS),
+ SD_HAS_BSSRDF_BUMP|SD_VOLUME_EQUIANGULAR|SD_VOLUME_MIS|
+ SD_VOLUME_CUBIC|SD_HAS_BUMP),
/* object flags */
- SD_HOLDOUT_MASK = 524288, /* holdout for camera rays */
- SD_OBJECT_MOTION = 1048576, /* has object motion blur */
- SD_TRANSFORM_APPLIED = 2097152, /* vertices have transform applied */
- SD_NEGATIVE_SCALE_APPLIED = 4194304, /* vertices have negative scale applied */
-
- SD_OBJECT_FLAGS = (SD_HOLDOUT_MASK|SD_OBJECT_MOTION|SD_TRANSFORM_APPLIED)
+ SD_HOLDOUT_MASK = (1 << 20), /* holdout for camera rays */
+ SD_OBJECT_MOTION = (1 << 21), /* has object motion blur */
+ SD_TRANSFORM_APPLIED = (1 << 22), /* vertices have transform applied */
+ SD_NEGATIVE_SCALE_APPLIED = (1 << 23), /* vertices have negative scale applied */
+ SD_OBJECT_HAS_VOLUME = (1 << 24), /* object has a volume shader */
+ SD_OBJECT_INTERSECTS_VOLUME = (1 << 25), /* object intersects AABB of an object with volume shader */
+ SD_OBJECT_HAS_VERTEX_MOTION = (1 << 26), /* has position for motion vertices */
+
+ SD_OBJECT_FLAGS = (SD_HOLDOUT_MASK|SD_OBJECT_MOTION|SD_TRANSFORM_APPLIED|
+ SD_NEGATIVE_SCALE_APPLIED|SD_OBJECT_HAS_VOLUME|
+ SD_OBJECT_INTERSECTS_VOLUME)
};
struct KernelGlobals;
-typedef struct ShaderData {
- /* position */
- float3 P;
- /* smooth normal for shading */
- float3 N;
- /* true geometric normal */
- float3 Ng;
- /* view/incoming direction */
- float3 I;
- /* shader id */
- int shader;
- /* booleans describing shader, see ShaderDataFlag */
- int flag;
-
- /* primitive id if there is one, ~0 otherwise */
- int prim;
-
- /* combined type and curve segment for hair */
- int type;
-
- /* parametric coordinates
- * - barycentric weights for triangles */
- float u, v;
- /* object id if there is one, ~0 otherwise */
- int object;
-
- /* motion blur sample time */
- float time;
-
- /* length of the ray being shaded */
- float ray_length;
-
- /* ray bounce depth */
- int ray_depth;
-
- /* ray transparent depth */
- int transparent_depth;
-
-#ifdef __RAY_DIFFERENTIALS__
- /* differential of P. these are orthogonal to Ng, not N */
- differential3 dP;
- /* differential of I */
- differential3 dI;
- /* differential of u, v */
- differential du;
- differential dv;
-#endif
-#ifdef __DPDU__
- /* differential of P w.r.t. parametric coordinates. note that dPdu is
- * not readily suitable as a tangent for shading on triangles. */
- float3 dPdu, dPdv;
-#endif
-
-#ifdef __OBJECT_MOTION__
- /* object <-> world space transformations, cached to avoid
- * re-interpolating them constantly for shading */
- Transform ob_tfm;
- Transform ob_itfm;
+#ifdef __SPLIT_KERNEL__
+#define SD_VAR(type, what) ccl_global type *what;
+#define SD_CLOSURE_VAR(type, what, max_closure) type *what;
+#define TIDX (get_global_id(1) * get_global_size(0) + get_global_id(0))
+#define ccl_fetch(s, t) (s->t[TIDX])
+#define ccl_fetch_array(s, t, index) (&s->t[TIDX * MAX_CLOSURE + index])
+#else
+#define SD_VAR(type, what) type what;
+#define SD_CLOSURE_VAR(type, what, max_closure) type what[max_closure];
+#define ccl_fetch(s, t) (s->t)
+#define ccl_fetch_array(s, t, index) (&s->t[index])
#endif
- /* Closure data, we store a fixed array of closures */
- ShaderClosure closure[MAX_CLOSURE];
- int num_closure;
- float randb_closure;
+typedef ccl_addr_space struct ShaderData {
- /* ray start position, only set for backgrounds */
- float3 ray_P;
- differential3 ray_dP;
+#include "kernel_shaderdata_vars.h"
-#ifdef __OSL__
- struct KernelGlobals *osl_globals;
-#endif
} ShaderData;
/* Path State */
@@ -711,7 +721,6 @@ typedef struct PathState {
/* random number generator state */
int rng_offset; /* dimension offset */
- int rng_offset_bsdf; /* dimension offset for picking bsdf */
int sample; /* path sample number */
int num_samples; /* total number of times this path will be sampled */
@@ -751,6 +760,7 @@ typedef struct KernelCamera {
int panorama_type;
float fisheye_fov;
float fisheye_lens;
+ float4 equirectangular_range;
/* matrices */
Transform cameratoworld;
@@ -768,7 +778,7 @@ typedef struct KernelCamera {
/* motion blur */
float shuttertime;
- int have_motion;
+ int have_motion, have_perspective_motion;
/* clipping */
float nearclip;
@@ -789,7 +799,7 @@ typedef struct KernelCamera {
int shader;
float focal_length;
- float pad[3];
+ float pad[2];
/* more matrices */
Transform screentoworld;
@@ -803,6 +813,11 @@ typedef struct KernelCamera {
Transform worldtocamera;
MotionTransform motion;
+
+ /* Denotes changes in the projective matrix, namely in rastertocamera.
+ * Used for camera zoom motion blur,
+ */
+ PerspectiveMotionTransform perspective_motion;
} KernelCamera;
typedef struct KernelFilm {
@@ -850,6 +865,13 @@ typedef struct KernelFilm {
float mist_start;
float mist_inv_depth;
float mist_falloff;
+
+#ifdef __KERNEL_DEBUG__
+ int pass_bvh_traversal_steps;
+ int pass_bvh_traversed_instances;
+ int pass_ray_bounces;
+ int pass_pad3;
+#endif
} KernelFilm;
typedef struct KernelBackground {
@@ -876,6 +898,11 @@ typedef struct KernelIntegrator {
float inv_pdf_lights;
int pdf_background_res;
+ /* light portals */
+ float portal_pdf;
+ int num_portals;
+ int portal_offset;
+
/* bounces */
int min_bounce;
int max_bounce;
@@ -928,6 +955,8 @@ typedef struct KernelIntegrator {
int volume_max_steps;
float volume_step_size;
int volume_samples;
+
+ int pad;
} KernelIntegrator;
typedef struct KernelBVH {
@@ -937,8 +966,8 @@ typedef struct KernelBVH {
int have_motion;
int have_curves;
int have_instancing;
-
- int pad1, pad2, pad3;
+ int use_qbvh;
+ int pad1, pad2;
} KernelBVH;
typedef enum CurveFlag {
@@ -961,9 +990,8 @@ typedef struct KernelCurves {
} KernelCurves;
typedef struct KernelTables {
- int blackbody_offset;
int beckmann_offset;
- int pad1, pad2;
+ int pad1, pad2, pad3;
} KernelTables;
typedef struct KernelData {
@@ -983,6 +1011,68 @@ typedef struct CameraData {
int shader;
} CameraData;
+#ifdef __KERNEL_DEBUG__
+typedef ccl_addr_space struct DebugData {
+ // Total number of BVH node traversal steps and primitives intersections
+ // for the camera rays.
+ int num_bvh_traversal_steps;
+ int num_bvh_traversed_instances;
+ int num_ray_bounces;
+} DebugData;
+#endif
+
+/* Declarations required for split kernel */
+
+/* Macro for queues */
+/* Value marking queue's empty slot */
+#define QUEUE_EMPTY_SLOT -1
+
+/*
+* Queue 1 - Active rays
+* Queue 2 - Background queue
+* Queue 3 - Shadow ray cast kernel - AO
+* Queeu 4 - Shadow ray cast kernel - direct lighting
+*/
+#define NUM_QUEUES 4
+
+/* Queue names */
+enum QueueNumber {
+ QUEUE_ACTIVE_AND_REGENERATED_RAYS = 0, /* All active rays and regenerated rays are enqueued here. */
+ QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS = 1, /* All
+ * 1. Background-hit rays,
+ * 2. Rays that has exited path-iteration but needs to update output buffer
+ * 3. Rays to be regenerated
+ * are enqueued here.
+ */
+ QUEUE_SHADOW_RAY_CAST_AO_RAYS = 2, /* All rays for which a shadow ray should be cast to determine radiance
+ * contribution for AO are enqueued here.
+ */
+ QUEUE_SHADOW_RAY_CAST_DL_RAYS = 3, /* All rays for which a shadow ray should be cast to determine radiance
+ * contributing for direct lighting are enqueued here.
+ */
+};
+
+/* We use RAY_STATE_MASK to get ray_state (enums 0 to 5) */
+#define RAY_STATE_MASK 0x007
+#define RAY_FLAG_MASK 0x0F8
+enum RayState {
+ RAY_ACTIVE = 0, // Denotes ray is actively involved in path-iteration
+ RAY_INACTIVE = 1, // Denotes ray has completed processing all samples and is inactive
+ RAY_UPDATE_BUFFER = 2, // Denoted ray has exited path-iteration and needs to update output buffer
+ RAY_HIT_BACKGROUND = 3, // Donotes ray has hit background
+ RAY_TO_REGENERATE = 4, // Denotes ray has to be regenerated
+ RAY_REGENERATED = 5, // Denotes ray has been regenerated
+ RAY_SKIP_DL = 6, // Denotes ray should skip direct lighting
+ RAY_SHADOW_RAY_CAST_AO = 16, // Flag's ray has to execute shadow blocked function in AO part
+ RAY_SHADOW_RAY_CAST_DL = 32 // Flag's ray has to execute shadow blocked function in direct lighting part
+};
+
+#define ASSIGN_RAY_STATE(ray_state, ray_index, state) (ray_state[ray_index] = ((ray_state[ray_index] & RAY_FLAG_MASK) | state))
+#define IS_STATE(ray_state, ray_index, state) ((ray_state[ray_index] & RAY_STATE_MASK) == state)
+#define ADD_RAY_FLAG(ray_state, ray_index, flag) (ray_state[ray_index] = (ray_state[ray_index] | flag))
+#define REMOVE_RAY_FLAG(ray_state, ray_index, flag) (ray_state[ray_index] = (ray_state[ray_index] & (~flag)))
+#define IS_FLAG(ray_state, ray_index, flag) (ray_state[ray_index] & flag)
+
CCL_NAMESPACE_END
#endif /* __KERNEL_TYPES_H__ */
diff --git a/intern/cycles/kernel/kernel_volume.h b/intern/cycles/kernel/kernel_volume.h
index 1273869ca28..0a74a9deba9 100644
--- a/intern/cycles/kernel/kernel_volume.h
+++ b/intern/cycles/kernel/kernel_volume.h
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
CCL_NAMESPACE_BEGIN
@@ -374,7 +374,7 @@ ccl_device VolumeIntegrateResult kernel_volume_integrate_homogeneous(KernelGloba
/* distance sampling */
sample_t = kernel_volume_distance_sample(ray->t, sigma_t, channel, xi, &transmittance, &pdf);
- /* modifiy pdf for hit/miss decision */
+ /* modify pdf for hit/miss decision */
if(probalistic_scatter)
pdf *= make_float3(1.0f, 1.0f, 1.0f) - volume_color_transmittance(sigma_t, t);
@@ -422,7 +422,7 @@ ccl_device VolumeIntegrateResult kernel_volume_integrate_homogeneous(KernelGloba
/* heterogeneous volume distance sampling: integrate stepping through the
* volume until we reach the end, get absorbed entirely, or run out of
- * iterations. this does probalistically scatter or get transmitted through
+ * iterations. this does probabilistically scatter or get transmitted through
* for path tracing where we don't want to branch. */
ccl_device VolumeIntegrateResult kernel_volume_integrate_heterogeneous_distance(KernelGlobals *kg,
PathState *state, Ray *ray, ShaderData *sd, PathRadiance *L, float3 *throughput, RNG *rng)
@@ -578,10 +578,11 @@ ccl_device_noinline VolumeIntegrateResult kernel_volume_integrate(KernelGlobals
/* Decoupled Volume Sampling
*
* VolumeSegment is list of coefficients and transmittance stored at all steps
- * through a volume. This can then latter be used for decoupled sampling as in:
+ * through a volume. This can then later be used for decoupled sampling as in:
* "Importance Sampling Techniques for Path Tracing in Participating Media"
*
- * On the GPU this is only supported for homogeneous volumes (1 step), due to
+ * On the GPU this is only supported (but currently not enabled)
+ * for homogeneous volumes (1 step), due to
* no support for malloc/free and too much stack usage with a fix size array. */
typedef struct VolumeStep {
@@ -595,6 +596,7 @@ typedef struct VolumeStep {
} VolumeStep;
typedef struct VolumeSegment {
+ VolumeStep stack_step; /* stack storage for homogeneous step, to avoid malloc */
VolumeStep *steps; /* recorded steps */
int numsteps; /* number of steps */
int closure_flag; /* accumulated closure flags from all steps */
@@ -608,7 +610,7 @@ typedef struct VolumeSegment {
/* record volume steps to the end of the volume.
*
* it would be nice if we could only record up to the point that we need to scatter,
- * but the entire segment is needed to do always scattering, rather than probalistically
+ * but the entire segment is needed to do always scattering, rather than probabilistically
* hitting or missing the volume. if we don't know the transmittance at the end of the
* volume we can't generate stratified distance samples up to that transmittance */
ccl_device void kernel_volume_decoupled_record(KernelGlobals *kg, PathState *state,
@@ -621,17 +623,22 @@ ccl_device void kernel_volume_decoupled_record(KernelGlobals *kg, PathState *sta
float step_size, random_jitter_offset;
if(heterogeneous) {
- max_steps = kernel_data.integrator.volume_max_steps;
+ const int global_max_steps = kernel_data.integrator.volume_max_steps;
step_size = kernel_data.integrator.volume_step_size;
- random_jitter_offset = lcg_step_float(&state->rng_congruential) * step_size;
-
/* compute exact steps in advance for malloc */
max_steps = max((int)ceilf(ray->t/step_size), 1);
+ if(max_steps > global_max_steps) {
+ max_steps = global_max_steps;
+ step_size = ray->t / (float)max_steps;
+ }
+ segment->steps = (VolumeStep*)malloc(sizeof(VolumeStep)*max_steps);
+ random_jitter_offset = lcg_step_float(&state->rng_congruential) * step_size;
}
else {
max_steps = 1;
step_size = ray->t;
random_jitter_offset = 0.0f;
+ segment->steps = &segment->stack_step;
}
/* init accumulation variables */
@@ -640,10 +647,9 @@ ccl_device void kernel_volume_decoupled_record(KernelGlobals *kg, PathState *sta
float3 cdf_distance = make_float3(0.0f, 0.0f, 0.0f);
float t = 0.0f;
- segment->closure_flag = 0;
segment->numsteps = 0;
-
- segment->steps = (VolumeStep*)malloc(sizeof(VolumeStep)*max_steps);
+ segment->closure_flag = 0;
+ bool is_last_step_empty = false;
VolumeStep *step = segment->steps;
@@ -685,12 +691,24 @@ ccl_device void kernel_volume_decoupled_record(KernelGlobals *kg, PathState *sta
step->closure_flag = closure_flag;
segment->closure_flag |= closure_flag;
+
+ is_last_step_empty = false;
+ segment->numsteps++;
}
else {
- /* store empty step (todo: skip consecutive empty steps) */
- step->sigma_t = make_float3(0.0f, 0.0f, 0.0f);
- step->sigma_s = make_float3(0.0f, 0.0f, 0.0f);
- step->closure_flag = 0;
+ if(is_last_step_empty) {
+ /* consecutive empty step, merge */
+ step--;
+ }
+ else {
+ /* store empty step */
+ step->sigma_t = make_float3(0.0f, 0.0f, 0.0f);
+ step->sigma_s = make_float3(0.0f, 0.0f, 0.0f);
+ step->closure_flag = 0;
+
+ segment->numsteps++;
+ is_last_step_empty = true;
+ }
}
step->accum_transmittance = accum_transmittance;
@@ -698,8 +716,6 @@ ccl_device void kernel_volume_decoupled_record(KernelGlobals *kg, PathState *sta
step->t = new_t;
step->shade_t = t + random_jitter_offset;
- segment->numsteps++;
-
/* stop if at the end of the volume */
t = new_t;
if(t == ray->t)
@@ -729,16 +745,13 @@ ccl_device void kernel_volume_decoupled_record(KernelGlobals *kg, PathState *sta
ccl_device void kernel_volume_decoupled_free(KernelGlobals *kg, VolumeSegment *segment)
{
- free(segment->steps);
+ if(segment->steps != &segment->stack_step)
+ free(segment->steps);
}
/* scattering for homogeneous and heterogeneous volumes, using decoupled ray
- * marching. unlike the non-decoupled functions, these do not do probalistic
- * scattering, they always scatter if there is any non-zero scattering
- * coefficient.
+ * marching. this function does not do emission or modify throughput.
*
- * these also do not do emission or modify throughput.
- *
* function is expected to return VOLUME_PATH_SCATTERED when probalistic_scatter is false */
ccl_device VolumeIntegrateResult kernel_volume_decoupled_scatter(
KernelGlobals *kg, PathState *state, Ray *ray, ShaderData *sd,
@@ -753,7 +766,7 @@ ccl_device VolumeIntegrateResult kernel_volume_decoupled_scatter(
sd->randb_closure = rphase*3.0f - channel;
float xi = rscatter;
- /* probalistic scattering decision based on transmittance */
+ /* probabilistic scattering decision based on transmittance */
if(probalistic_scatter) {
float sample_transmittance = kernel_volume_channel_get(segment->accum_transmittance, channel);
@@ -833,7 +846,7 @@ ccl_device VolumeIntegrateResult kernel_volume_decoupled_scatter(
float3 distance_pdf;
sample_t = prev_t + kernel_volume_distance_sample(step_t, step->sigma_t, channel, xi, &transmittance, &distance_pdf);
- /* modifiy pdf for hit/miss decision */
+ /* modify pdf for hit/miss decision */
if(probalistic_scatter)
distance_pdf *= make_float3(1.0f, 1.0f, 1.0f) - segment->accum_transmittance;
@@ -929,7 +942,7 @@ ccl_device VolumeIntegrateResult kernel_volume_decoupled_scatter(
/* decide if we need to use decoupled or not */
ccl_device bool kernel_volume_use_decoupled(KernelGlobals *kg, bool heterogeneous, bool direct, int sampling_method)
{
- /* decoupled ray marching for heterogenous volumes not supported on the GPU,
+ /* decoupled ray marching for heterogeneous volumes not supported on the GPU,
* which also means equiangular and multiple importance sampling is not
* support for that case */
#ifdef __KERNEL_GPU__
@@ -958,7 +971,7 @@ ccl_device void kernel_volume_stack_init(KernelGlobals *kg,
Ray *ray,
VolumeStack *stack)
{
- /* NULL ray happens in the baker, does it need proper initializetion of
+ /* NULL ray happens in the baker, does it need proper initialization of
* camera in volume?
*/
if(!kernel_data.cam.is_inside_volume || ray == NULL) {
@@ -976,25 +989,26 @@ ccl_device void kernel_volume_stack_init(KernelGlobals *kg,
return;
}
- const float3 Pend = ray->P + ray->D*ray->t;
Ray volume_ray = *ray;
- int stack_index = 0, enclosed_index = 0;
- int enclosed_volumes[VOLUME_STACK_SIZE];
+ volume_ray.t = FLT_MAX;
- while(stack_index < VOLUME_STACK_SIZE - 1 &&
- enclosed_index < VOLUME_STACK_SIZE - 1)
- {
- Intersection isect;
- bool hit = scene_intersect(kg, &volume_ray, PATH_RAY_ALL_VISIBILITY,
- &isect,
- NULL, 0.0f, 0.0f);
- if(!hit) {
- break;
- }
+ int stack_index = 0, enclosed_index = 0;
- ShaderData sd;
- shader_setup_from_ray(kg, &sd, &isect, &volume_ray, 0, 0);
- if(sd.flag & SD_HAS_VOLUME) {
+#ifdef __VOLUME_RECORD_ALL__
+ Intersection hits[2*VOLUME_STACK_SIZE];
+ uint num_hits = scene_intersect_volume_all(kg,
+ &volume_ray,
+ hits,
+ 2*VOLUME_STACK_SIZE);
+ if(num_hits > 0) {
+ int enclosed_volumes[VOLUME_STACK_SIZE];
+ Intersection *isect = hits;
+
+ qsort(hits, num_hits, sizeof(Intersection), intersections_compare);
+
+ for(uint hit = 0; hit < num_hits; ++hit, ++isect) {
+ ShaderData sd;
+ shader_setup_from_ray(kg, &sd, isect, &volume_ray, 0, 0);
if(sd.flag & SD_BACKFACING) {
/* If ray exited the volume and never entered to that volume
* it means that camera is inside such a volume.
@@ -1014,24 +1028,56 @@ ccl_device void kernel_volume_stack_init(KernelGlobals *kg,
}
else {
/* If ray from camera enters the volume, this volume shouldn't
- * be added to the stak on exit.
+ * be added to the stack on exit.
*/
enclosed_volumes[enclosed_index++] = sd.object;
}
}
+ }
+#else
+ int enclosed_volumes[VOLUME_STACK_SIZE];
+ int step = 0;
- /* Move ray forward. */
- volume_ray.P = ray_offset(sd.P, -sd.Ng);
- if(volume_ray.t != FLT_MAX) {
- volume_ray.D = normalize_len(Pend - volume_ray.P, &volume_ray.t);
- /* TODO(sergey): Find a faster way detecting that ray_offset moved
- * us pass through the end point.
+ while(stack_index < VOLUME_STACK_SIZE - 1 &&
+ enclosed_index < VOLUME_STACK_SIZE - 1 &&
+ step < 2 * VOLUME_STACK_SIZE)
+ {
+ Intersection isect;
+ if(!scene_intersect_volume(kg, &volume_ray, &isect)) {
+ break;
+ }
+
+ ShaderData sd;
+ shader_setup_from_ray(kg, &sd, &isect, &volume_ray, 0, 0);
+ if(sd.flag & SD_BACKFACING) {
+ /* If ray exited the volume and never entered to that volume
+ * it means that camera is inside such a volume.
*/
- if(dot(ray->D, volume_ray.D) < 0.0f) {
- break;
+ bool is_enclosed = false;
+ for(int i = 0; i < enclosed_index; ++i) {
+ if(enclosed_volumes[i] == sd.object) {
+ is_enclosed = true;
+ break;
+ }
}
+ if(is_enclosed == false) {
+ stack[stack_index].object = sd.object;
+ stack[stack_index].shader = sd.shader;
+ ++stack_index;
+ }
+ }
+ else {
+ /* If ray from camera enters the volume, this volume shouldn't
+ * be added to the stack on exit.
+ */
+ enclosed_volumes[enclosed_index++] = sd.object;
}
+
+ /* Move ray forward. */
+ volume_ray.P = ray_offset(sd.P, -sd.Ng);
+ ++step;
}
+#endif
/* stack_index of 0 means quick checks outside of the kernel gave false
* positive, nothing to worry about, just we've wasted quite a few of
* ticks just to come into conclusion that camera is in the air.
@@ -1094,4 +1140,49 @@ ccl_device void kernel_volume_stack_enter_exit(KernelGlobals *kg, ShaderData *sd
}
}
+#ifdef __SUBSURFACE__
+ccl_device void kernel_volume_stack_update_for_subsurface(KernelGlobals *kg,
+ Ray *ray,
+ VolumeStack *stack)
+{
+ kernel_assert(kernel_data.integrator.use_volumes);
+
+ Ray volume_ray = *ray;
+
+#ifdef __VOLUME_RECORD_ALL__
+ Intersection hits[2*VOLUME_STACK_SIZE];
+ uint num_hits = scene_intersect_volume_all(kg,
+ &volume_ray,
+ hits,
+ 2*VOLUME_STACK_SIZE);
+ if(num_hits > 0) {
+ Intersection *isect = hits;
+
+ qsort(hits, num_hits, sizeof(Intersection), intersections_compare);
+
+ for(uint hit = 0; hit < num_hits; ++hit, ++isect) {
+ ShaderData sd;
+ shader_setup_from_ray(kg, &sd, isect, &volume_ray, 0, 0);
+ kernel_volume_stack_enter_exit(kg, &sd, stack);
+ }
+ }
+#else
+ Intersection isect;
+ int step = 0;
+ while(step < 2 * VOLUME_STACK_SIZE &&
+ scene_intersect_volume(kg, &volume_ray, &isect))
+ {
+ ShaderData sd;
+ shader_setup_from_ray(kg, &sd, &isect, &volume_ray, 0, 0);
+ kernel_volume_stack_enter_exit(kg, &sd, stack);
+
+ /* Move ray forward. */
+ volume_ray.P = ray_offset(sd.P, -sd.Ng);
+ volume_ray.t -= sd.ray_length;
+ ++step;
+ }
+#endif
+}
+#endif
+
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/kernel_work_stealing.h b/intern/cycles/kernel/kernel_work_stealing.h
new file mode 100644
index 00000000000..9b83d972e97
--- /dev/null
+++ b/intern/cycles/kernel/kernel_work_stealing.h
@@ -0,0 +1,193 @@
+/*
+ * Copyright 2011-2015 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 __KERNEL_WORK_STEALING_H__
+#define __KERNEL_WORK_STEALING_H__
+
+/*
+ * Utility functions for work stealing
+ */
+
+#ifdef __WORK_STEALING__
+
+#ifdef __KERNEL_OPENCL__
+#pragma OPENCL EXTENSION cl_khr_global_int32_base_atomics : enable
+#endif
+
+uint get_group_id_with_ray_index(uint ray_index,
+ uint tile_dim_x,
+ uint tile_dim_y,
+ uint parallel_samples,
+ int dim)
+{
+ if(dim == 0) {
+ uint x_span = ray_index % (tile_dim_x * parallel_samples);
+ return x_span / get_local_size(0);
+ }
+ else /*if(dim == 1)*/ {
+ kernel_assert(dim == 1);
+ uint y_span = ray_index / (tile_dim_x * parallel_samples);
+ return y_span / get_local_size(1);
+ }
+}
+
+uint get_total_work(uint tile_dim_x,
+ uint tile_dim_y,
+ uint grp_idx,
+ uint grp_idy,
+ uint num_samples)
+{
+ uint threads_within_tile_border_x =
+ (grp_idx == (get_num_groups(0) - 1)) ? tile_dim_x % get_local_size(0)
+ : get_local_size(0);
+ uint threads_within_tile_border_y =
+ (grp_idy == (get_num_groups(1) - 1)) ? tile_dim_y % get_local_size(1)
+ : get_local_size(1);
+
+ threads_within_tile_border_x =
+ (threads_within_tile_border_x == 0) ? get_local_size(0)
+ : threads_within_tile_border_x;
+ threads_within_tile_border_y =
+ (threads_within_tile_border_y == 0) ? get_local_size(1)
+ : threads_within_tile_border_y;
+
+ return threads_within_tile_border_x *
+ threads_within_tile_border_y *
+ num_samples;
+}
+
+/* Returns 0 in case there is no next work available */
+/* Returns 1 in case work assigned is valid */
+int get_next_work(ccl_global uint *work_pool,
+ ccl_private uint *my_work,
+ uint tile_dim_x,
+ uint tile_dim_y,
+ uint num_samples,
+ uint parallel_samples,
+ uint ray_index)
+{
+ uint grp_idx = get_group_id_with_ray_index(ray_index,
+ tile_dim_x,
+ tile_dim_y,
+ parallel_samples,
+ 0);
+ uint grp_idy = get_group_id_with_ray_index(ray_index,
+ tile_dim_x,
+ tile_dim_y,
+ parallel_samples,
+ 1);
+ uint total_work = get_total_work(tile_dim_x,
+ tile_dim_y,
+ grp_idx,
+ grp_idy,
+ num_samples);
+ uint group_index = grp_idy * get_num_groups(0) + grp_idx;
+ *my_work = atomic_inc(&work_pool[group_index]);
+ return (*my_work < total_work) ? 1 : 0;
+}
+
+/* This function assumes that the passed my_work is valid. */
+/* Decode sample number w.r.t. assigned my_work. */
+uint get_my_sample(uint my_work,
+ uint tile_dim_x,
+ uint tile_dim_y,
+ uint parallel_samples,
+ uint ray_index)
+{
+ uint grp_idx = get_group_id_with_ray_index(ray_index,
+ tile_dim_x,
+ tile_dim_y,
+ parallel_samples,
+ 0);
+ uint grp_idy = get_group_id_with_ray_index(ray_index,
+ tile_dim_x,
+ tile_dim_y,
+ parallel_samples,
+ 1);
+ uint threads_within_tile_border_x =
+ (grp_idx == (get_num_groups(0) - 1)) ? tile_dim_x % get_local_size(0)
+ : get_local_size(0);
+ uint threads_within_tile_border_y =
+ (grp_idy == (get_num_groups(1) - 1)) ? tile_dim_y % get_local_size(1)
+ : get_local_size(1);
+
+ threads_within_tile_border_x =
+ (threads_within_tile_border_x == 0) ? get_local_size(0)
+ : threads_within_tile_border_x;
+ threads_within_tile_border_y =
+ (threads_within_tile_border_y == 0) ? get_local_size(1)
+ : threads_within_tile_border_y;
+
+ return my_work /
+ (threads_within_tile_border_x * threads_within_tile_border_y);
+}
+
+/* Decode pixel and tile position w.r.t. assigned my_work. */
+void get_pixel_tile_position(ccl_private uint *pixel_x,
+ ccl_private uint *pixel_y,
+ ccl_private uint *tile_x,
+ ccl_private uint *tile_y,
+ uint my_work,
+ uint tile_dim_x,
+ uint tile_dim_y,
+ uint tile_offset_x,
+ uint tile_offset_y,
+ uint parallel_samples,
+ uint ray_index)
+{
+ uint grp_idx = get_group_id_with_ray_index(ray_index,
+ tile_dim_x,
+ tile_dim_y,
+ parallel_samples,
+ 0);
+ uint grp_idy = get_group_id_with_ray_index(ray_index,
+ tile_dim_x,
+ tile_dim_y,
+ parallel_samples,
+ 1);
+ uint threads_within_tile_border_x =
+ (grp_idx == (get_num_groups(0) - 1)) ? tile_dim_x % get_local_size(0)
+ : get_local_size(0);
+ uint threads_within_tile_border_y =
+ (grp_idy == (get_num_groups(1) - 1)) ? tile_dim_y % get_local_size(1)
+ : get_local_size(1);
+
+ threads_within_tile_border_x =
+ (threads_within_tile_border_x == 0) ? get_local_size(0)
+ : threads_within_tile_border_x;
+ threads_within_tile_border_y =
+ (threads_within_tile_border_y == 0) ? get_local_size(1)
+ : threads_within_tile_border_y;
+
+ uint total_associated_pixels =
+ threads_within_tile_border_x * threads_within_tile_border_y;
+ uint work_group_pixel_index = my_work % total_associated_pixels;
+ uint work_group_pixel_x =
+ work_group_pixel_index % threads_within_tile_border_x;
+ uint work_group_pixel_y =
+ work_group_pixel_index / threads_within_tile_border_x;
+
+ *pixel_x =
+ tile_offset_x + (grp_idx * get_local_size(0)) + work_group_pixel_x;
+ *pixel_y =
+ tile_offset_y + (grp_idy * get_local_size(1)) + work_group_pixel_y;
+ *tile_x = *pixel_x - tile_offset_x;
+ *tile_y = *pixel_y - tile_offset_y;
+}
+
+#endif /* __WORK_STEALING__ */
+
+#endif /* __KERNEL_WORK_STEALING_H__ */
diff --git a/intern/cycles/kernel/kernel.cpp b/intern/cycles/kernel/kernels/cpu/kernel.cpp
index fa2113fbb46..2c8d3503c1a 100644
--- a/intern/cycles/kernel/kernel.cpp
+++ b/intern/cycles/kernel/kernels/cpu/kernel.cpp
@@ -11,18 +11,19 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
/* CPU kernel entry points */
-#include "kernel.h"
#include "kernel_compat_cpu.h"
+#include "kernel.h"
#include "kernel_math.h"
#include "kernel_types.h"
#include "kernel_globals.h"
#include "kernel_film.h"
#include "kernel_path.h"
+#include "kernel_path_branched.h"
#include "kernel_bake.h"
CCL_NAMESPACE_BEGIN
@@ -37,7 +38,14 @@ void kernel_const_copy(KernelGlobals *kg, const char *name, void *host, size_t s
assert(0);
}
-void kernel_tex_copy(KernelGlobals *kg, const char *name, device_ptr mem, size_t width, size_t height, size_t depth, InterpolationType interpolation)
+void kernel_tex_copy(KernelGlobals *kg,
+ const char *name,
+ device_ptr mem,
+ size_t width,
+ size_t height,
+ size_t depth,
+ InterpolationType interpolation,
+ ExtensionType extension)
{
if(0) {
}
@@ -55,7 +63,7 @@ void kernel_tex_copy(KernelGlobals *kg, const char *name, device_ptr mem, size_t
int id = atoi(name + strlen("__tex_image_float_"));
int array_index = id;
- if (array_index >= 0 && array_index < MAX_FLOAT_IMAGES) {
+ if(array_index >= 0 && array_index < MAX_FLOAT_IMAGES) {
tex = &kg->texture_float_images[array_index];
}
@@ -63,6 +71,7 @@ void kernel_tex_copy(KernelGlobals *kg, const char *name, device_ptr mem, size_t
tex->data = (float4*)mem;
tex->dimensions_set(width, height, depth);
tex->interpolation = interpolation;
+ tex->extension = extension;
}
}
else if(strstr(name, "__tex_image")) {
@@ -70,7 +79,7 @@ void kernel_tex_copy(KernelGlobals *kg, const char *name, device_ptr mem, size_t
int id = atoi(name + strlen("__tex_image_"));
int array_index = id - MAX_FLOAT_IMAGES;
- if (array_index >= 0 && array_index < MAX_BYTE_IMAGES) {
+ if(array_index >= 0 && array_index < MAX_BYTE_IMAGES) {
tex = &kg->texture_byte_images[array_index];
}
@@ -78,6 +87,7 @@ void kernel_tex_copy(KernelGlobals *kg, const char *name, device_ptr mem, size_t
tex->data = (uchar4*)mem;
tex->dimensions_set(width, height, depth);
tex->interpolation = interpolation;
+ tex->extension = extension;
}
}
else
diff --git a/intern/cycles/kernel/kernel_avx.cpp b/intern/cycles/kernel/kernels/cpu/kernel_avx.cpp
index e7ff21a6f09..df77bedc729 100644
--- a/intern/cycles/kernel/kernel_avx.cpp
+++ b/intern/cycles/kernel/kernels/cpu/kernel_avx.cpp
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
/* Optimized CPU kernel entry points. This file is compiled with AVX
@@ -31,13 +31,14 @@
#ifdef WITH_CYCLES_OPTIMIZED_KERNEL_AVX
-#include "kernel.h"
#include "kernel_compat_cpu.h"
+#include "kernel.h"
#include "kernel_math.h"
#include "kernel_types.h"
#include "kernel_globals.h"
#include "kernel_film.h"
#include "kernel_path.h"
+#include "kernel_path_branched.h"
#include "kernel_bake.h"
CCL_NAMESPACE_BEGIN
diff --git a/intern/cycles/kernel/kernel_avx2.cpp b/intern/cycles/kernel/kernels/cpu/kernel_avx2.cpp
index cb1662bbfbe..b3192369794 100644
--- a/intern/cycles/kernel/kernel_avx2.cpp
+++ b/intern/cycles/kernel/kernels/cpu/kernel_avx2.cpp
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
/* Optimized CPU kernel entry points. This file is compiled with AVX2
@@ -32,13 +32,14 @@
#ifdef WITH_CYCLES_OPTIMIZED_KERNEL_AVX2
-#include "kernel.h"
#include "kernel_compat_cpu.h"
+#include "kernel.h"
#include "kernel_math.h"
#include "kernel_types.h"
#include "kernel_globals.h"
#include "kernel_film.h"
#include "kernel_path.h"
+#include "kernel_path_branched.h"
#include "kernel_bake.h"
CCL_NAMESPACE_BEGIN
diff --git a/intern/cycles/kernel/kernel_sse2.cpp b/intern/cycles/kernel/kernels/cpu/kernel_sse2.cpp
index 740998e8c92..f9c5134e442 100644
--- a/intern/cycles/kernel/kernel_sse2.cpp
+++ b/intern/cycles/kernel/kernels/cpu/kernel_sse2.cpp
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
/* Optimized CPU kernel entry points. This file is compiled with SSE2
@@ -27,13 +27,14 @@
#ifdef WITH_CYCLES_OPTIMIZED_KERNEL_SSE2
-#include "kernel.h"
#include "kernel_compat_cpu.h"
+#include "kernel.h"
#include "kernel_math.h"
#include "kernel_types.h"
#include "kernel_globals.h"
#include "kernel_film.h"
#include "kernel_path.h"
+#include "kernel_path_branched.h"
#include "kernel_bake.h"
CCL_NAMESPACE_BEGIN
diff --git a/intern/cycles/kernel/kernel_sse3.cpp b/intern/cycles/kernel/kernels/cpu/kernel_sse3.cpp
index da73a3a1c97..2dbe4b81821 100644
--- a/intern/cycles/kernel/kernel_sse3.cpp
+++ b/intern/cycles/kernel/kernels/cpu/kernel_sse3.cpp
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
/* Optimized CPU kernel entry points. This file is compiled with SSE3/SSSE3
@@ -29,13 +29,14 @@
#ifdef WITH_CYCLES_OPTIMIZED_KERNEL_SSE3
-#include "kernel.h"
#include "kernel_compat_cpu.h"
+#include "kernel.h"
#include "kernel_math.h"
#include "kernel_types.h"
#include "kernel_globals.h"
#include "kernel_film.h"
#include "kernel_path.h"
+#include "kernel_path_branched.h"
#include "kernel_bake.h"
CCL_NAMESPACE_BEGIN
diff --git a/intern/cycles/kernel/kernel_sse41.cpp b/intern/cycles/kernel/kernels/cpu/kernel_sse41.cpp
index 5704f60e138..5c57ad01181 100644
--- a/intern/cycles/kernel/kernel_sse41.cpp
+++ b/intern/cycles/kernel/kernels/cpu/kernel_sse41.cpp
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
/* Optimized CPU kernel entry points. This file is compiled with SSE3/SSSE3
@@ -30,13 +30,14 @@
#ifdef WITH_CYCLES_OPTIMIZED_KERNEL_SSE41
-#include "kernel.h"
#include "kernel_compat_cpu.h"
+#include "kernel.h"
#include "kernel_math.h"
#include "kernel_types.h"
#include "kernel_globals.h"
#include "kernel_film.h"
#include "kernel_path.h"
+#include "kernel_path_branched.h"
#include "kernel_bake.h"
CCL_NAMESPACE_BEGIN
diff --git a/intern/cycles/kernel/kernel.cu b/intern/cycles/kernel/kernels/cuda/kernel.cu
index 9ed4592f604..bcd55b8c676 100644
--- a/intern/cycles/kernel/kernel.cu
+++ b/intern/cycles/kernel/kernels/cuda/kernel.cu
@@ -11,18 +11,19 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
/* CUDA kernel entry points */
-#include "kernel_compat_cuda.h"
-#include "kernel_math.h"
-#include "kernel_types.h"
-#include "kernel_globals.h"
-#include "kernel_film.h"
-#include "kernel_path.h"
-#include "kernel_bake.h"
+#include "../../kernel_compat_cuda.h"
+#include "../../kernel_math.h"
+#include "../../kernel_types.h"
+#include "../../kernel_globals.h"
+#include "../../kernel_film.h"
+#include "../../kernel_path.h"
+#include "../../kernel_path_branched.h"
+#include "../../kernel_bake.h"
/* device data taken from CUDA occupancy calculator */
@@ -52,6 +53,18 @@
#define CUDA_KERNEL_MAX_REGISTERS 63
#define CUDA_KERNEL_BRANCHED_MAX_REGISTERS 63
+/* 3.2 */
+#elif __CUDA_ARCH__ == 320
+#define CUDA_MULTIPRESSOR_MAX_REGISTERS 32768
+#define CUDA_MULTIPROCESSOR_MAX_BLOCKS 16
+#define CUDA_BLOCK_MAX_THREADS 1024
+#define CUDA_THREAD_MAX_REGISTERS 63
+
+/* tunable parameters */
+#define CUDA_THREADS_BLOCK_WIDTH 16
+#define CUDA_KERNEL_MAX_REGISTERS 63
+#define CUDA_KERNEL_BRANCHED_MAX_REGISTERS 63
+
/* 5.0 and 5.2 */
#elif __CUDA_ARCH__ == 500 || __CUDA_ARCH__ == 520
#define CUDA_MULTIPRESSOR_MAX_REGISTERS 65536
diff --git a/intern/cycles/kernel/kernel.cl b/intern/cycles/kernel/kernels/opencl/kernel.cl
index 4f20ef9ca15..57db6fd9098 100644
--- a/intern/cycles/kernel/kernel.cl
+++ b/intern/cycles/kernel/kernels/opencl/kernel.cl
@@ -11,19 +11,22 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
/* OpenCL kernel entry points - unfinished */
-#include "kernel_compat_opencl.h"
-#include "kernel_math.h"
-#include "kernel_types.h"
-#include "kernel_globals.h"
+#include "../../kernel_compat_opencl.h"
+#include "../../kernel_math.h"
+#include "../../kernel_types.h"
+#include "../../kernel_globals.h"
-#include "kernel_film.h"
-#include "kernel_path.h"
-#include "kernel_bake.h"
+#include "../../kernel_film.h"
+#include "../../kernel_path.h"
+#include "../../kernel_path_branched.h"
+#include "../../kernel_bake.h"
+
+#ifdef __COMPILE_ONLY_MEGAKERNEL__
__kernel void kernel_ocl_path_trace(
ccl_constant KernelData *data,
@@ -32,7 +35,7 @@ __kernel void kernel_ocl_path_trace(
#define KERNEL_TEX(type, ttype, name) \
ccl_global type *name,
-#include "kernel_textures.h"
+#include "../../kernel_textures.h"
int sample,
int sx, int sy, int sw, int sh, int offset, int stride)
@@ -43,7 +46,7 @@ __kernel void kernel_ocl_path_trace(
#define KERNEL_TEX(type, ttype, name) \
kg->name = name;
-#include "kernel_textures.h"
+#include "../../kernel_textures.h"
int x = sx + get_global_id(0);
int y = sy + get_global_id(1);
@@ -52,17 +55,18 @@ __kernel void kernel_ocl_path_trace(
kernel_path_trace(kg, buffer, rng_state, sample, x, y, offset, stride);
}
-__kernel void kernel_ocl_convert_to_byte(
+#else // __COMPILE_ONLY_MEGAKERNEL__
+
+__kernel void kernel_ocl_shader(
ccl_constant KernelData *data,
- ccl_global uchar4 *rgba,
- ccl_global float *buffer,
+ ccl_global uint4 *input,
+ ccl_global float4 *output,
#define KERNEL_TEX(type, ttype, name) \
ccl_global type *name,
-#include "kernel_textures.h"
+#include "../../kernel_textures.h"
- float sample_scale,
- int sx, int sy, int sw, int sh, int offset, int stride)
+ int type, int sx, int sw, int offset, int sample)
{
KernelGlobals kglobals, *kg = &kglobals;
@@ -70,26 +74,24 @@ __kernel void kernel_ocl_convert_to_byte(
#define KERNEL_TEX(type, ttype, name) \
kg->name = name;
-#include "kernel_textures.h"
+#include "../../kernel_textures.h"
int x = sx + get_global_id(0);
- int y = sy + get_global_id(1);
- if(x < sx + sw && y < sy + sh)
- kernel_film_convert_to_byte(kg, rgba, buffer, sample_scale, x, y, offset, stride);
+ if(x < sx + sw)
+ kernel_shader_evaluate(kg, input, output, (ShaderEvalType)type, x, sample);
}
-__kernel void kernel_ocl_convert_to_half_float(
+__kernel void kernel_ocl_bake(
ccl_constant KernelData *data,
- ccl_global uchar4 *rgba,
- ccl_global float *buffer,
+ ccl_global uint4 *input,
+ ccl_global float4 *output,
#define KERNEL_TEX(type, ttype, name) \
ccl_global type *name,
-#include "kernel_textures.h"
+#include "../../kernel_textures.h"
- float sample_scale,
- int sx, int sy, int sw, int sh, int offset, int stride)
+ int type, int sx, int sw, int offset, int sample)
{
KernelGlobals kglobals, *kg = &kglobals;
@@ -97,25 +99,30 @@ __kernel void kernel_ocl_convert_to_half_float(
#define KERNEL_TEX(type, ttype, name) \
kg->name = name;
-#include "kernel_textures.h"
+#include "../../kernel_textures.h"
int x = sx + get_global_id(0);
- int y = sy + get_global_id(1);
- if(x < sx + sw && y < sy + sh)
- kernel_film_convert_to_half_float(kg, rgba, buffer, sample_scale, x, y, offset, stride);
+ if(x < sx + sw) {
+#ifdef __NO_BAKING__
+ output[x] = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
+#else
+ kernel_bake_evaluate(kg, input, output, (ShaderEvalType)type, x, offset, sample);
+#endif
+ }
}
-__kernel void kernel_ocl_shader(
+__kernel void kernel_ocl_convert_to_byte(
ccl_constant KernelData *data,
- ccl_global uint4 *input,
- ccl_global float4 *output,
+ ccl_global uchar4 *rgba,
+ ccl_global float *buffer,
#define KERNEL_TEX(type, ttype, name) \
ccl_global type *name,
-#include "kernel_textures.h"
+#include "../../kernel_textures.h"
- int type, int sx, int sw, int offset, int sample)
+ float sample_scale,
+ int sx, int sy, int sw, int sh, int offset, int stride)
{
KernelGlobals kglobals, *kg = &kglobals;
@@ -123,24 +130,26 @@ __kernel void kernel_ocl_shader(
#define KERNEL_TEX(type, ttype, name) \
kg->name = name;
-#include "kernel_textures.h"
+#include "../../kernel_textures.h"
int x = sx + get_global_id(0);
+ int y = sy + get_global_id(1);
- if(x < sx + sw)
- kernel_shader_evaluate(kg, input, output, (ShaderEvalType)type, x, sample);
+ if(x < sx + sw && y < sy + sh)
+ kernel_film_convert_to_byte(kg, rgba, buffer, sample_scale, x, y, offset, stride);
}
-__kernel void kernel_ocl_bake(
+__kernel void kernel_ocl_convert_to_half_float(
ccl_constant KernelData *data,
- ccl_global uint4 *input,
- ccl_global float4 *output,
+ ccl_global uchar4 *rgba,
+ ccl_global float *buffer,
#define KERNEL_TEX(type, ttype, name) \
ccl_global type *name,
-#include "kernel_textures.h"
+#include "../../kernel_textures.h"
- int type, int sx, int sw, int offset, int sample)
+ float sample_scale,
+ int sx, int sy, int sw, int sh, int offset, int stride)
{
KernelGlobals kglobals, *kg = &kglobals;
@@ -148,11 +157,13 @@ __kernel void kernel_ocl_bake(
#define KERNEL_TEX(type, ttype, name) \
kg->name = name;
-#include "kernel_textures.h"
+#include "../../kernel_textures.h"
int x = sx + get_global_id(0);
+ int y = sy + get_global_id(1);
- if(x < sx + sw)
- kernel_bake_evaluate(kg, input, output, (ShaderEvalType)type, x, offset, sample);
+ if(x < sx + sw && y < sy + sh)
+ kernel_film_convert_to_half_float(kg, rgba, buffer, sample_scale, x, y, offset, stride);
}
+#endif // __COMPILE_ONLY_MEGAKERNEL__ \ No newline at end of file
diff --git a/intern/cycles/kernel/kernels/opencl/kernel_background_buffer_update.cl b/intern/cycles/kernel/kernels/opencl/kernel_background_buffer_update.cl
new file mode 100644
index 00000000000..eff77b89a0a
--- /dev/null
+++ b/intern/cycles/kernel/kernels/opencl/kernel_background_buffer_update.cl
@@ -0,0 +1,128 @@
+/*
+ * Copyright 2011-2015 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 "split/kernel_background_buffer_update.h"
+
+__kernel void kernel_ocl_path_trace_background_buffer_update(
+ ccl_global char *globals,
+ ccl_constant KernelData *data,
+ ccl_global char *shader_data,
+ ccl_global float *per_sample_output_buffers,
+ ccl_global uint *rng_state,
+ ccl_global uint *rng_coop, /* Required for buffer Update */
+ ccl_global float3 *throughput_coop, /* Required for background hit processing */
+ PathRadiance *PathRadiance_coop, /* Required for background hit processing and buffer Update */
+ ccl_global Ray *Ray_coop, /* Required for background hit processing */
+ ccl_global PathState *PathState_coop, /* Required for background hit processing */
+ ccl_global float *L_transparent_coop, /* Required for background hit processing and buffer Update */
+ ccl_global char *ray_state, /* Stores information on the current state of a ray */
+ int sw, int sh, int sx, int sy, int stride,
+ int rng_state_offset_x,
+ int rng_state_offset_y,
+ int rng_state_stride,
+ ccl_global unsigned int *work_array, /* Denotes work of each ray */
+ ccl_global int *Queue_data, /* Queues memory */
+ ccl_global int *Queue_index, /* Tracks the number of elements in each queue */
+ int queuesize, /* Size (capacity) of each queue */
+ int end_sample,
+ int start_sample,
+#ifdef __WORK_STEALING__
+ ccl_global unsigned int *work_pool_wgs,
+ unsigned int num_samples,
+#endif
+#ifdef __KERNEL_DEBUG__
+ DebugData *debugdata_coop,
+#endif
+ int parallel_samples) /* Number of samples to be processed in parallel */
+{
+ ccl_local unsigned int local_queue_atomics;
+ if(get_local_id(0) == 0 && get_local_id(1) == 0) {
+ local_queue_atomics = 0;
+ }
+ barrier(CLK_LOCAL_MEM_FENCE);
+
+ int ray_index = get_global_id(1) * get_global_size(0) + get_global_id(0);
+ if(ray_index == 0) {
+ /* We will empty this queue in this kernel. */
+ Queue_index[QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS] = 0;
+ }
+ char enqueue_flag = 0;
+ ray_index = get_ray_index(ray_index,
+ QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS,
+ Queue_data,
+ queuesize,
+ 1);
+
+#ifdef __COMPUTE_DEVICE_GPU__
+ /* If we are executing on a GPU device, we exit all threads that are not
+ * required.
+ *
+ * If we are executing on a CPU device, then we need to keep all threads
+ * active since we have barrier() calls later in the kernel. CPU devices,
+ * expect all threads to execute barrier statement.
+ */
+ if(ray_index == QUEUE_EMPTY_SLOT) {
+ return;
+ }
+#endif
+
+#ifndef __COMPUTE_DEVICE_GPU__
+ if(ray_index != QUEUE_EMPTY_SLOT) {
+#endif
+ enqueue_flag =
+ kernel_background_buffer_update(globals,
+ data,
+ shader_data,
+ per_sample_output_buffers,
+ rng_state,
+ rng_coop,
+ throughput_coop,
+ PathRadiance_coop,
+ Ray_coop,
+ PathState_coop,
+ L_transparent_coop,
+ ray_state,
+ sw, sh, sx, sy, stride,
+ rng_state_offset_x,
+ rng_state_offset_y,
+ rng_state_stride,
+ work_array,
+ end_sample,
+ start_sample,
+#ifdef __WORK_STEALING__
+ work_pool_wgs,
+ num_samples,
+#endif
+#ifdef __KERNEL_DEBUG__
+ debugdata_coop,
+#endif
+ parallel_samples,
+ ray_index);
+#ifndef __COMPUTE_DEVICE_GPU__
+ }
+#endif
+
+ /* Enqueue RAY_REGENERATED rays into QUEUE_ACTIVE_AND_REGENERATED_RAYS;
+ * These rays will be made active during next SceneIntersectkernel.
+ */
+ enqueue_ray_index_local(ray_index,
+ QUEUE_ACTIVE_AND_REGENERATED_RAYS,
+ enqueue_flag,
+ queuesize,
+ &local_queue_atomics,
+ Queue_data,
+ Queue_index);
+}
diff --git a/intern/cycles/kernel/kernels/opencl/kernel_data_init.cl b/intern/cycles/kernel/kernels/opencl/kernel_data_init.cl
new file mode 100644
index 00000000000..c3277676029
--- /dev/null
+++ b/intern/cycles/kernel/kernels/opencl/kernel_data_init.cl
@@ -0,0 +1,241 @@
+/*
+ * Copyright 2011-2015 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 "split/kernel_data_init.h"
+
+__kernel void kernel_ocl_path_trace_data_init(
+ ccl_global char *globals,
+ ccl_global char *shader_data_sd, /* Arguments related to ShaderData */
+ ccl_global char *shader_data_sd_DL_shadow, /* Arguments related to ShaderData */
+
+ ccl_global float3 *P_sd,
+ ccl_global float3 *P_sd_DL_shadow,
+
+ ccl_global float3 *N_sd,
+ ccl_global float3 *N_sd_DL_shadow,
+
+ ccl_global float3 *Ng_sd,
+ ccl_global float3 *Ng_sd_DL_shadow,
+
+ ccl_global float3 *I_sd,
+ ccl_global float3 *I_sd_DL_shadow,
+
+ ccl_global int *shader_sd,
+ ccl_global int *shader_sd_DL_shadow,
+
+ ccl_global int *flag_sd,
+ ccl_global int *flag_sd_DL_shadow,
+
+ ccl_global int *prim_sd,
+ ccl_global int *prim_sd_DL_shadow,
+
+ ccl_global int *type_sd,
+ ccl_global int *type_sd_DL_shadow,
+
+ ccl_global float *u_sd,
+ ccl_global float *u_sd_DL_shadow,
+
+ ccl_global float *v_sd,
+ ccl_global float *v_sd_DL_shadow,
+
+ ccl_global int *object_sd,
+ ccl_global int *object_sd_DL_shadow,
+
+ ccl_global float *time_sd,
+ ccl_global float *time_sd_DL_shadow,
+
+ ccl_global float *ray_length_sd,
+ ccl_global float *ray_length_sd_DL_shadow,
+
+ ccl_global int *ray_depth_sd,
+ ccl_global int *ray_depth_sd_DL_shadow,
+
+ ccl_global int *transparent_depth_sd,
+ ccl_global int *transparent_depth_sd_DL_shadow,
+
+ /* Ray differentials. */
+ ccl_global differential3 *dP_sd,
+ ccl_global differential3 *dP_sd_DL_shadow,
+
+ ccl_global differential3 *dI_sd,
+ ccl_global differential3 *dI_sd_DL_shadow,
+
+ ccl_global differential *du_sd,
+ ccl_global differential *du_sd_DL_shadow,
+
+ ccl_global differential *dv_sd,
+ ccl_global differential *dv_sd_DL_shadow,
+
+ /* Dp/Du */
+ ccl_global float3 *dPdu_sd,
+ ccl_global float3 *dPdu_sd_DL_shadow,
+
+ ccl_global float3 *dPdv_sd,
+ ccl_global float3 *dPdv_sd_DL_shadow,
+
+ /* Object motion. */
+ ccl_global Transform *ob_tfm_sd,
+ ccl_global Transform *ob_tfm_sd_DL_shadow,
+
+ ccl_global Transform *ob_itfm_sd,
+ ccl_global Transform *ob_itfm_sd_DL_shadow,
+
+ ShaderClosure *closure_sd,
+ ShaderClosure *closure_sd_DL_shadow,
+
+ ccl_global int *num_closure_sd,
+ ccl_global int *num_closure_sd_DL_shadow,
+
+ ccl_global float *randb_closure_sd,
+ ccl_global float *randb_closure_sd_DL_shadow,
+
+ ccl_global float3 *ray_P_sd,
+ ccl_global float3 *ray_P_sd_DL_shadow,
+
+ ccl_global differential3 *ray_dP_sd,
+ ccl_global differential3 *ray_dP_sd_DL_shadow,
+
+ ccl_constant KernelData *data,
+ ccl_global float *per_sample_output_buffers,
+ ccl_global uint *rng_state,
+ ccl_global uint *rng_coop, /* rng array to store rng values for all rays */
+ ccl_global float3 *throughput_coop, /* throughput array to store throughput values for all rays */
+ ccl_global float *L_transparent_coop, /* L_transparent array to store L_transparent values for all rays */
+ PathRadiance *PathRadiance_coop, /* PathRadiance array to store PathRadiance values for all rays */
+ ccl_global Ray *Ray_coop, /* Ray array to store Ray information for all rays */
+ ccl_global PathState *PathState_coop, /* PathState array to store PathState information for all rays */
+ ccl_global char *ray_state, /* Stores information on current state of a ray */
+
+#define KERNEL_TEX(type, ttype, name) \
+ ccl_global type *name,
+#include "../../kernel_textures.h"
+
+ int start_sample, int sx, int sy, int sw, int sh, int offset, int stride,
+ int rng_state_offset_x,
+ int rng_state_offset_y,
+ int rng_state_stride,
+ ccl_global int *Queue_data, /* Memory for queues */
+ ccl_global int *Queue_index, /* Tracks the number of elements in queues */
+ int queuesize, /* size (capacity) of the queue */
+ ccl_global char *use_queues_flag, /* flag to decide if scene-intersect kernel should use queues to fetch ray index */
+ ccl_global unsigned int *work_array, /* work array to store which work each ray belongs to */
+#ifdef __WORK_STEALING__
+ ccl_global unsigned int *work_pool_wgs, /* Work pool for each work group */
+ unsigned int num_samples, /* Total number of samples per pixel */
+#endif
+#ifdef __KERNEL_DEBUG__
+ DebugData *debugdata_coop,
+#endif
+ int parallel_samples) /* Number of samples to be processed in parallel */
+{
+ kernel_data_init(globals,
+ shader_data_sd,
+ shader_data_sd_DL_shadow,
+ P_sd,
+ P_sd_DL_shadow,
+ N_sd,
+ N_sd_DL_shadow,
+ Ng_sd,
+ Ng_sd_DL_shadow,
+ I_sd,
+ I_sd_DL_shadow,
+ shader_sd,
+ shader_sd_DL_shadow,
+ flag_sd,
+ flag_sd_DL_shadow,
+ prim_sd,
+ prim_sd_DL_shadow,
+ type_sd,
+ type_sd_DL_shadow,
+ u_sd,
+ u_sd_DL_shadow,
+ v_sd,
+ v_sd_DL_shadow,
+ object_sd,
+ object_sd_DL_shadow,
+ time_sd,
+ time_sd_DL_shadow,
+ ray_length_sd,
+ ray_length_sd_DL_shadow,
+ ray_depth_sd,
+ ray_depth_sd_DL_shadow,
+ transparent_depth_sd,
+ transparent_depth_sd_DL_shadow,
+
+ /* Ray differentials. */
+ dP_sd,
+ dP_sd_DL_shadow,
+ dI_sd,
+ dI_sd_DL_shadow,
+ du_sd,
+ du_sd_DL_shadow,
+ dv_sd,
+ dv_sd_DL_shadow,
+
+ /* Dp/Du */
+ dPdu_sd,
+ dPdu_sd_DL_shadow,
+ dPdv_sd,
+ dPdv_sd_DL_shadow,
+
+ /* Object motion. */
+ ob_tfm_sd,
+ ob_tfm_sd_DL_shadow,
+ ob_itfm_sd,
+ ob_itfm_sd_DL_shadow,
+
+ closure_sd,
+ closure_sd_DL_shadow,
+ num_closure_sd,
+ num_closure_sd_DL_shadow,
+ randb_closure_sd,
+ randb_closure_sd_DL_shadow,
+ ray_P_sd,
+ ray_P_sd_DL_shadow,
+ ray_dP_sd,
+ ray_dP_sd_DL_shadow,
+ data,
+ per_sample_output_buffers,
+ rng_state,
+ rng_coop,
+ throughput_coop,
+ L_transparent_coop,
+ PathRadiance_coop,
+ Ray_coop,
+ PathState_coop,
+ ray_state,
+
+#define KERNEL_TEX(type, ttype, name) name,
+#include "../../kernel_textures.h"
+
+ start_sample, sx, sy, sw, sh, offset, stride,
+ rng_state_offset_x,
+ rng_state_offset_y,
+ rng_state_stride,
+ Queue_data,
+ Queue_index,
+ queuesize,
+ use_queues_flag,
+ work_array,
+#ifdef __WORK_STEALING__
+ work_pool_wgs,
+ num_samples,
+#endif
+#ifdef __KERNEL_DEBUG__
+ debugdata_coop,
+#endif
+ parallel_samples);
+}
diff --git a/intern/cycles/kernel/kernels/opencl/kernel_direct_lighting.cl b/intern/cycles/kernel/kernels/opencl/kernel_direct_lighting.cl
new file mode 100644
index 00000000000..6ec75013b3a
--- /dev/null
+++ b/intern/cycles/kernel/kernels/opencl/kernel_direct_lighting.cl
@@ -0,0 +1,90 @@
+/*
+ * Copyright 2011-2015 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 "split/kernel_direct_lighting.h"
+
+__kernel void kernel_ocl_path_trace_direct_lighting(
+ ccl_global char *globals,
+ ccl_constant KernelData *data,
+ ccl_global char *shader_data, /* Required for direct lighting */
+ ccl_global char *shader_DL, /* Required for direct lighting */
+ ccl_global uint *rng_coop, /* Required for direct lighting */
+ ccl_global PathState *PathState_coop, /* Required for direct lighting */
+ ccl_global int *ISLamp_coop, /* Required for direct lighting */
+ ccl_global Ray *LightRay_coop, /* Required for direct lighting */
+ ccl_global BsdfEval *BSDFEval_coop, /* Required for direct lighting */
+ ccl_global char *ray_state, /* Denotes the state of each ray */
+ ccl_global int *Queue_data, /* Queue memory */
+ ccl_global int *Queue_index, /* Tracks the number of elements in each queue */
+ int queuesize) /* Size (capacity) of each queue */
+{
+ ccl_local unsigned int local_queue_atomics;
+ if(get_local_id(0) == 0 && get_local_id(1) == 0) {
+ local_queue_atomics = 0;
+ }
+ barrier(CLK_LOCAL_MEM_FENCE);
+
+ char enqueue_flag = 0;
+ int ray_index = get_global_id(1) * get_global_size(0) + get_global_id(0);
+ ray_index = get_ray_index(ray_index,
+ QUEUE_ACTIVE_AND_REGENERATED_RAYS,
+ Queue_data,
+ queuesize,
+ 0);
+
+#ifdef __COMPUTE_DEVICE_GPU__
+ /* If we are executing on a GPU device, we exit all threads that are not
+ * required.
+ *
+ * If we are executing on a CPU device, then we need to keep all threads
+ * active since we have barrier() calls later in the kernel. CPU devices,
+ * expect all threads to execute barrier statement.
+ */
+ if(ray_index == QUEUE_EMPTY_SLOT) {
+ return;
+ }
+#endif
+
+#ifndef __COMPUTE_DEVICE_GPU__
+ if(ray_index != QUEUE_EMPTY_SLOT) {
+#endif
+ enqueue_flag = kernel_direct_lighting(globals,
+ data,
+ shader_data,
+ shader_DL,
+ rng_coop,
+ PathState_coop,
+ ISLamp_coop,
+ LightRay_coop,
+ BSDFEval_coop,
+ ray_state,
+ ray_index);
+
+#ifndef __COMPUTE_DEVICE_GPU__
+ }
+#endif
+
+#ifdef __EMISSION__
+ /* Enqueue RAY_SHADOW_RAY_CAST_DL rays. */
+ enqueue_ray_index_local(ray_index,
+ QUEUE_SHADOW_RAY_CAST_DL_RAYS,
+ enqueue_flag,
+ queuesize,
+ &local_queue_atomics,
+ Queue_data,
+ Queue_index);
+#endif
+}
diff --git a/intern/cycles/kernel/kernels/opencl/kernel_holdout_emission_blurring_pathtermination_ao.cl b/intern/cycles/kernel/kernels/opencl/kernel_holdout_emission_blurring_pathtermination_ao.cl
new file mode 100644
index 00000000000..ae5f5cd1b3b
--- /dev/null
+++ b/intern/cycles/kernel/kernels/opencl/kernel_holdout_emission_blurring_pathtermination_ao.cl
@@ -0,0 +1,124 @@
+/*
+ * Copyright 2011-2015 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 "split/kernel_holdout_emission_blurring_pathtermination_ao.h"
+
+__kernel void kernel_ocl_path_trace_holdout_emission_blurring_pathtermination_ao(
+ ccl_global char *globals,
+ ccl_constant KernelData *data,
+ ccl_global char *shader_data, /* Required throughout the kernel except probabilistic path termination and AO */
+ ccl_global float *per_sample_output_buffers,
+ ccl_global uint *rng_coop, /* Required for "kernel_write_data_passes" and AO */
+ ccl_global float3 *throughput_coop, /* Required for handling holdout material and AO */
+ ccl_global float *L_transparent_coop, /* Required for handling holdout material */
+ PathRadiance *PathRadiance_coop, /* Required for "kernel_write_data_passes" and indirect primitive emission */
+ ccl_global PathState *PathState_coop, /* Required throughout the kernel and AO */
+ Intersection *Intersection_coop, /* Required for indirect primitive emission */
+ ccl_global float3 *AOAlpha_coop, /* Required for AO */
+ ccl_global float3 *AOBSDF_coop, /* Required for AO */
+ ccl_global Ray *AOLightRay_coop, /* Required for AO */
+ int sw, int sh, int sx, int sy, int stride,
+ ccl_global char *ray_state, /* Denotes the state of each ray */
+ ccl_global unsigned int *work_array, /* Denotes the work that each ray belongs to */
+ ccl_global int *Queue_data, /* Queue memory */
+ ccl_global int *Queue_index, /* Tracks the number of elements in each queue */
+ int queuesize, /* Size (capacity) of each queue */
+#ifdef __WORK_STEALING__
+ unsigned int start_sample,
+#endif
+ int parallel_samples) /* Number of samples to be processed in parallel */
+{
+ ccl_local unsigned int local_queue_atomics_bg;
+ ccl_local unsigned int local_queue_atomics_ao;
+ if(get_local_id(0) == 0 && get_local_id(1) == 0) {
+ local_queue_atomics_bg = 0;
+ local_queue_atomics_ao = 0;
+ }
+ barrier(CLK_LOCAL_MEM_FENCE);
+
+ char enqueue_flag = 0;
+ char enqueue_flag_AO_SHADOW_RAY_CAST = 0;
+ int ray_index = get_global_id(1) * get_global_size(0) + get_global_id(0);
+ ray_index = get_ray_index(ray_index,
+ QUEUE_ACTIVE_AND_REGENERATED_RAYS,
+ Queue_data,
+ queuesize,
+ 0);
+
+#ifdef __COMPUTE_DEVICE_GPU__
+ /* If we are executing on a GPU device, we exit all threads that are not
+ * required.
+ *
+ * If we are executing on a CPU device, then we need to keep all threads
+ * active since we have barrier() calls later in the kernel. CPU devices,
+ * expect all threads to execute barrier statement.
+ */
+ if(ray_index == QUEUE_EMPTY_SLOT) {
+ return;
+ }
+#endif /* __COMPUTE_DEVICE_GPU__ */
+
+#ifndef __COMPUTE_DEVICE_GPU__
+ if(ray_index != QUEUE_EMPTY_SLOT) {
+#endif
+ kernel_holdout_emission_blurring_pathtermination_ao(
+ globals,
+ data,
+ shader_data,
+ per_sample_output_buffers,
+ rng_coop,
+ throughput_coop,
+ L_transparent_coop,
+ PathRadiance_coop,
+ PathState_coop,
+ Intersection_coop,
+ AOAlpha_coop,
+ AOBSDF_coop,
+ AOLightRay_coop,
+ sw, sh, sx, sy, stride,
+ ray_state,
+ work_array,
+#ifdef __WORK_STEALING__
+ start_sample,
+#endif
+ parallel_samples,
+ ray_index,
+ &enqueue_flag,
+ &enqueue_flag_AO_SHADOW_RAY_CAST);
+#ifndef __COMPUTE_DEVICE_GPU__
+ }
+#endif
+
+ /* Enqueue RAY_UPDATE_BUFFER rays. */
+ enqueue_ray_index_local(ray_index,
+ QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS,
+ enqueue_flag,
+ queuesize,
+ &local_queue_atomics_bg,
+ Queue_data,
+ Queue_index);
+
+#ifdef __AO__
+ /* Enqueue to-shadow-ray-cast rays. */
+ enqueue_ray_index_local(ray_index,
+ QUEUE_SHADOW_RAY_CAST_AO_RAYS,
+ enqueue_flag_AO_SHADOW_RAY_CAST,
+ queuesize,
+ &local_queue_atomics_ao,
+ Queue_data,
+ Queue_index);
+#endif
+}
diff --git a/intern/cycles/kernel/kernels/opencl/kernel_lamp_emission.cl b/intern/cycles/kernel/kernels/opencl/kernel_lamp_emission.cl
new file mode 100644
index 00000000000..1bc7808d834
--- /dev/null
+++ b/intern/cycles/kernel/kernels/opencl/kernel_lamp_emission.cl
@@ -0,0 +1,84 @@
+/*
+ * Copyright 2011-2015 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 "split/kernel_lamp_emission.h"
+
+__kernel void kernel_ocl_path_trace_lamp_emission(
+ ccl_global char *globals,
+ ccl_constant KernelData *data,
+ ccl_global char *shader_data, /* Required for lamp emission */
+ ccl_global float3 *throughput_coop, /* Required for lamp emission */
+ PathRadiance *PathRadiance_coop, /* Required for lamp emission */
+ ccl_global Ray *Ray_coop, /* Required for lamp emission */
+ ccl_global PathState *PathState_coop, /* Required for lamp emission */
+ Intersection *Intersection_coop, /* Required for lamp emission */
+ ccl_global char *ray_state, /* Denotes the state of each ray */
+ int sw, int sh,
+ ccl_global int *Queue_data, /* Memory for queues */
+ ccl_global int *Queue_index, /* Tracks the number of elements in queues */
+ int queuesize, /* Size (capacity) of queues */
+ ccl_global char *use_queues_flag, /* Used to decide if this kernel should use
+ * queues to fetch ray index
+ */
+ int parallel_samples) /* Number of samples to be processed in parallel */
+{
+ int x = get_global_id(0);
+ int y = get_global_id(1);
+
+ /* We will empty this queue in this kernel. */
+ if(get_global_id(0) == 0 && get_global_id(1) == 0) {
+ Queue_index[QUEUE_ACTIVE_AND_REGENERATED_RAYS] = 0;
+ }
+ /* Fetch use_queues_flag. */
+ ccl_local char local_use_queues_flag;
+ if(get_local_id(0) == 0 && get_local_id(1) == 0) {
+ local_use_queues_flag = use_queues_flag[0];
+ }
+ barrier(CLK_LOCAL_MEM_FENCE);
+
+ int ray_index;
+ if(local_use_queues_flag) {
+ int thread_index = get_global_id(1) * get_global_size(0) + get_global_id(0);
+ ray_index = get_ray_index(thread_index,
+ QUEUE_ACTIVE_AND_REGENERATED_RAYS,
+ Queue_data,
+ queuesize,
+ 1);
+ if(ray_index == QUEUE_EMPTY_SLOT) {
+ return;
+ }
+ } else {
+ if(x < (sw * parallel_samples) && y < sh){
+ ray_index = x + y * (sw * parallel_samples);
+ } else {
+ return;
+ }
+ }
+
+ kernel_lamp_emission(globals,
+ data,
+ shader_data,
+ throughput_coop,
+ PathRadiance_coop,
+ Ray_coop,
+ PathState_coop,
+ Intersection_coop,
+ ray_state,
+ sw, sh,
+ use_queues_flag,
+ parallel_samples,
+ ray_index);
+}
diff --git a/intern/cycles/kernel/kernels/opencl/kernel_next_iteration_setup.cl b/intern/cycles/kernel/kernels/opencl/kernel_next_iteration_setup.cl
new file mode 100644
index 00000000000..dcf4db40411
--- /dev/null
+++ b/intern/cycles/kernel/kernels/opencl/kernel_next_iteration_setup.cl
@@ -0,0 +1,115 @@
+/*
+ * Copyright 2011-2015 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 "split/kernel_next_iteration_setup.h"
+
+__kernel void kernel_ocl_path_trace_next_iteration_setup(
+ ccl_global char *globals,
+ ccl_constant KernelData *data,
+ ccl_global char *shader_data, /* Required for setting up ray for next iteration */
+ ccl_global uint *rng_coop, /* Required for setting up ray for next iteration */
+ ccl_global float3 *throughput_coop, /* Required for setting up ray for next iteration */
+ PathRadiance *PathRadiance_coop, /* Required for setting up ray for next iteration */
+ ccl_global Ray *Ray_coop, /* Required for setting up ray for next iteration */
+ ccl_global PathState *PathState_coop, /* Required for setting up ray for next iteration */
+ ccl_global Ray *LightRay_dl_coop, /* Required for radiance update - direct lighting */
+ ccl_global int *ISLamp_coop, /* Required for radiance update - direct lighting */
+ ccl_global BsdfEval *BSDFEval_coop, /* Required for radiance update - direct lighting */
+ ccl_global Ray *LightRay_ao_coop, /* Required for radiance update - AO */
+ ccl_global float3 *AOBSDF_coop, /* Required for radiance update - AO */
+ ccl_global float3 *AOAlpha_coop, /* Required for radiance update - AO */
+ ccl_global char *ray_state, /* Denotes the state of each ray */
+ ccl_global int *Queue_data, /* Queue memory */
+ ccl_global int *Queue_index, /* Tracks the number of elements in each queue */
+ int queuesize, /* Size (capacity) of each queue */
+ ccl_global char *use_queues_flag) /* flag to decide if scene_intersect kernel should
+ * use queues to fetch ray index */
+{
+ ccl_local unsigned int local_queue_atomics;
+ if(get_local_id(0) == 0 && get_local_id(1) == 0) {
+ local_queue_atomics = 0;
+ }
+ barrier(CLK_LOCAL_MEM_FENCE);
+
+ if(get_global_id(0) == 0 && get_global_id(1) == 0) {
+ /* If we are here, then it means that scene-intersect kernel
+ * has already been executed atleast once. From the next time,
+ * scene-intersect kernel may operate on queues to fetch ray index
+ */
+ use_queues_flag[0] = 1;
+
+ /* Mark queue indices of QUEUE_SHADOW_RAY_CAST_AO_RAYS and
+ * QUEUE_SHADOW_RAY_CAST_DL_RAYS queues that were made empty during the
+ * previous kernel.
+ */
+ Queue_index[QUEUE_SHADOW_RAY_CAST_AO_RAYS] = 0;
+ Queue_index[QUEUE_SHADOW_RAY_CAST_DL_RAYS] = 0;
+ }
+
+ char enqueue_flag = 0;
+ int ray_index = get_global_id(1) * get_global_size(0) + get_global_id(0);
+ ray_index = get_ray_index(ray_index,
+ QUEUE_ACTIVE_AND_REGENERATED_RAYS,
+ Queue_data,
+ queuesize,
+ 0);
+
+#ifdef __COMPUTE_DEVICE_GPU__
+ /* If we are executing on a GPU device, we exit all threads that are not
+ * required.
+ *
+ * If we are executing on a CPU device, then we need to keep all threads
+ * active since we have barrier() calls later in the kernel. CPU devices,
+ * expect all threads to execute barrier statement.
+ */
+ if(ray_index == QUEUE_EMPTY_SLOT) {
+ return;
+ }
+#endif
+
+#ifndef __COMPUTE_DEVICE_GPU__
+ if(ray_index != QUEUE_EMPTY_SLOT) {
+#endif
+ enqueue_flag = kernel_next_iteration_setup(globals,
+ data,
+ shader_data,
+ rng_coop,
+ throughput_coop,
+ PathRadiance_coop,
+ Ray_coop,
+ PathState_coop,
+ LightRay_dl_coop,
+ ISLamp_coop,
+ BSDFEval_coop,
+ LightRay_ao_coop,
+ AOBSDF_coop,
+ AOAlpha_coop,
+ ray_state,
+ use_queues_flag,
+ ray_index);
+#ifndef __COMPUTE_DEVICE_GPU__
+ }
+#endif
+
+ /* Enqueue RAY_UPDATE_BUFFER rays. */
+ enqueue_ray_index_local(ray_index,
+ QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS,
+ enqueue_flag,
+ queuesize,
+ &local_queue_atomics,
+ Queue_data,
+ Queue_index);
+}
diff --git a/intern/cycles/kernel/kernels/opencl/kernel_queue_enqueue.cl b/intern/cycles/kernel/kernels/opencl/kernel_queue_enqueue.cl
new file mode 100644
index 00000000000..3156dc255fb
--- /dev/null
+++ b/intern/cycles/kernel/kernels/opencl/kernel_queue_enqueue.cl
@@ -0,0 +1,106 @@
+/*
+ * Copyright 2011-2015 Blender Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "../../kernel_compat_opencl.h"
+#include "../../kernel_math.h"
+#include "../../kernel_types.h"
+#include "../../kernel_globals.h"
+#include "../../kernel_queues.h"
+
+/*
+ * The kernel "kernel_queue_enqueue" enqueues rays of
+ * different ray state into their appropriate Queues;
+ * 1. Rays that have been determined to hit the background from the
+ * "kernel_scene_intersect" kernel
+ * are enqueued in QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS;
+ * 2. Rays that have been determined to be actively participating in path-iteration will be enqueued into QUEUE_ACTIVE_AND_REGENERATED_RAYS.
+ *
+ * The input and output of the kernel is as follows,
+ *
+ * ray_state -------------------------------------------|--- kernel_queue_enqueue --|--- Queue_data (QUEUE_ACTIVE_AND_REGENERATED_RAYS & QUEUE_HITBF_BUFF_UPDATE_TOREGEN_RAYS)
+ * Queue_index(QUEUE_ACTIVE_AND_REGENERATED_RAYS) ------| |--- Queue_index (QUEUE_ACTIVE_AND_REGENERATED_RAYS & QUEUE_HITBF_BUFF_UPDATE_TOREGEN_RAYS)
+ * Queue_index(QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS) ---| |
+ * queuesize -------------------------------------------| |
+ *
+ * Note on Queues :
+ * State of queues during the first time this kernel is called :
+ * At entry,
+ * Both QUEUE_ACTIVE_AND_REGENERATED_RAYS and QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS will be empty.
+ * At exit,
+ * QUEUE_ACTIVE_AND_REGENERATED_RAYS will be filled with RAY_ACTIVE rays
+ * QUEUE_HITBF_BUFF_UPDATE_TOREGEN_RAYS will be filled with RAY_HIT_BACKGROUND rays.
+ *
+ * State of queue during other times this kernel is called :
+ * At entry,
+ * QUEUE_ACTIVE_AND_REGENERATED_RAYS will be empty.
+ * QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS will contain RAY_TO_REGENERATE and RAY_UPDATE_BUFFER rays.
+ * At exit,
+ * QUEUE_ACTIVE_AND_REGENERATED_RAYS will be filled with RAY_ACTIVE rays.
+ * QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS will be filled with RAY_TO_REGENERATE, RAY_UPDATE_BUFFER, RAY_HIT_BACKGROUND rays.
+ */
+__kernel void kernel_ocl_path_trace_queue_enqueue(
+ ccl_global int *Queue_data, /* Queue memory */
+ ccl_global int *Queue_index, /* Tracks the number of elements in each queue */
+ ccl_global char *ray_state, /* Denotes the state of each ray */
+ int queuesize) /* Size (capacity) of each queue */
+{
+ /* We have only 2 cases (Hit/Not-Hit) */
+ ccl_local unsigned int local_queue_atomics[2];
+
+ int lidx = get_local_id(1) * get_local_size(0) + get_local_id(0);
+ int ray_index = get_global_id(1) * get_global_size(0) + get_global_id(0);
+
+ if(lidx < 2 ) {
+ local_queue_atomics[lidx] = 0;
+ }
+ barrier(CLK_LOCAL_MEM_FENCE);
+
+ int queue_number = -1;
+
+ if(IS_STATE(ray_state, ray_index, RAY_HIT_BACKGROUND)) {
+ queue_number = QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS;
+ }
+ else if(IS_STATE(ray_state, ray_index, RAY_ACTIVE)) {
+ queue_number = QUEUE_ACTIVE_AND_REGENERATED_RAYS;
+ }
+
+ unsigned int my_lqidx;
+ if(queue_number != -1) {
+ my_lqidx = get_local_queue_index(queue_number, local_queue_atomics);
+ }
+ barrier(CLK_LOCAL_MEM_FENCE);
+
+ if(lidx == 0) {
+ local_queue_atomics[QUEUE_ACTIVE_AND_REGENERATED_RAYS] =
+ get_global_per_queue_offset(QUEUE_ACTIVE_AND_REGENERATED_RAYS,
+ local_queue_atomics,
+ Queue_index);
+ local_queue_atomics[QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS] =
+ get_global_per_queue_offset(QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS,
+ local_queue_atomics,
+ Queue_index);
+ }
+ barrier(CLK_LOCAL_MEM_FENCE);
+
+ unsigned int my_gqidx;
+ if(queue_number != -1) {
+ my_gqidx = get_global_queue_index(queue_number,
+ queuesize,
+ my_lqidx,
+ local_queue_atomics);
+ Queue_data[my_gqidx] = ray_index;
+ }
+}
diff --git a/intern/cycles/kernel/kernels/opencl/kernel_scene_intersect.cl b/intern/cycles/kernel/kernels/opencl/kernel_scene_intersect.cl
new file mode 100644
index 00000000000..e5fad7bce50
--- /dev/null
+++ b/intern/cycles/kernel/kernels/opencl/kernel_scene_intersect.cl
@@ -0,0 +1,82 @@
+/*
+ * Copyright 2011-2015 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 "split/kernel_scene_intersect.h"
+
+__kernel void kernel_ocl_path_trace_scene_intersect(
+ ccl_global char *globals,
+ ccl_constant KernelData *data,
+ ccl_global uint *rng_coop,
+ ccl_global Ray *Ray_coop, /* Required for scene_intersect */
+ ccl_global PathState *PathState_coop, /* Required for scene_intersect */
+ Intersection *Intersection_coop, /* Required for scene_intersect */
+ ccl_global char *ray_state, /* Denotes the state of each ray */
+ int sw, int sh,
+ ccl_global int *Queue_data, /* Memory for queues */
+ ccl_global int *Queue_index, /* Tracks the number of elements in queues */
+ int queuesize, /* Size (capacity) of queues */
+ ccl_global char *use_queues_flag, /* used to decide if this kernel should use
+ * queues to fetch ray index */
+#ifdef __KERNEL_DEBUG__
+ DebugData *debugdata_coop,
+#endif
+ int parallel_samples) /* Number of samples to be processed in parallel */
+{
+ int x = get_global_id(0);
+ int y = get_global_id(1);
+
+ /* Fetch use_queues_flag */
+ ccl_local char local_use_queues_flag;
+ if(get_local_id(0) == 0 && get_local_id(1) == 0) {
+ local_use_queues_flag = use_queues_flag[0];
+ }
+ barrier(CLK_LOCAL_MEM_FENCE);
+
+ int ray_index;
+ if(local_use_queues_flag) {
+ int thread_index = get_global_id(1) * get_global_size(0) + get_global_id(0);
+ ray_index = get_ray_index(thread_index,
+ QUEUE_ACTIVE_AND_REGENERATED_RAYS,
+ Queue_data,
+ queuesize,
+ 0);
+
+ if(ray_index == QUEUE_EMPTY_SLOT) {
+ return;
+ }
+ } else {
+ if(x < (sw * parallel_samples) && y < sh){
+ ray_index = x + y * (sw * parallel_samples);
+ } else {
+ return;
+ }
+ }
+
+ kernel_scene_intersect(globals,
+ data,
+ rng_coop,
+ Ray_coop,
+ PathState_coop,
+ Intersection_coop,
+ ray_state,
+ sw, sh,
+ use_queues_flag,
+#ifdef __KERNEL_DEBUG__
+ debugdata_coop,
+#endif
+ parallel_samples,
+ ray_index);
+}
diff --git a/intern/cycles/kernel/kernels/opencl/kernel_shader_eval.cl b/intern/cycles/kernel/kernels/opencl/kernel_shader_eval.cl
new file mode 100644
index 00000000000..b9f616e6bdf
--- /dev/null
+++ b/intern/cycles/kernel/kernels/opencl/kernel_shader_eval.cl
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2011-2015 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 "split/kernel_shader_eval.h"
+
+__kernel void kernel_ocl_path_trace_shader_eval(
+ ccl_global char *globals,
+ ccl_constant KernelData *data,
+ ccl_global char *shader_data, /* Output ShaderData structure to be filled */
+ ccl_global uint *rng_coop, /* Required for rbsdf calculation */
+ ccl_global Ray *Ray_coop, /* Required for setting up shader from ray */
+ ccl_global PathState *PathState_coop, /* Required for all functions in this kernel */
+ Intersection *Intersection_coop, /* Required for setting up shader from ray */
+ ccl_global char *ray_state, /* Denotes the state of each ray */
+ ccl_global int *Queue_data, /* queue memory */
+ ccl_global int *Queue_index, /* Tracks the number of elements in each queue */
+ int queuesize) /* Size (capacity) of each queue */
+{
+ /* Enqeueue RAY_TO_REGENERATE rays into QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS queue. */
+ ccl_local unsigned int local_queue_atomics;
+ if(get_local_id(0) == 0 && get_local_id(1) == 0) {
+ local_queue_atomics = 0;
+ }
+ barrier(CLK_LOCAL_MEM_FENCE);
+
+ int ray_index = get_global_id(1) * get_global_size(0) + get_global_id(0);
+ ray_index = get_ray_index(ray_index,
+ QUEUE_ACTIVE_AND_REGENERATED_RAYS,
+ Queue_data,
+ queuesize,
+ 0);
+
+ if(ray_index == QUEUE_EMPTY_SLOT) {
+ return;
+ }
+
+ char enqueue_flag = (IS_STATE(ray_state, ray_index, RAY_TO_REGENERATE)) ? 1 : 0;
+ enqueue_ray_index_local(ray_index,
+ QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS,
+ enqueue_flag,
+ queuesize,
+ &local_queue_atomics,
+ Queue_data,
+ Queue_index);
+
+ /* Continue on with shader evaluation. */
+ kernel_shader_eval(globals,
+ data,
+ shader_data,
+ rng_coop,
+ Ray_coop,
+ PathState_coop,
+ Intersection_coop,
+ ray_state,
+ ray_index);
+}
diff --git a/intern/cycles/kernel/kernels/opencl/kernel_shadow_blocked.cl b/intern/cycles/kernel/kernels/opencl/kernel_shadow_blocked.cl
new file mode 100644
index 00000000000..03886c0a030
--- /dev/null
+++ b/intern/cycles/kernel/kernels/opencl/kernel_shadow_blocked.cl
@@ -0,0 +1,83 @@
+/*
+ * Copyright 2011-2015 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 "split/kernel_shadow_blocked.h"
+
+__kernel void kernel_ocl_path_trace_shadow_blocked(
+ ccl_global char *globals,
+ ccl_constant KernelData *data,
+ ccl_global char *shader_shadow, /* Required for shadow blocked */
+ ccl_global PathState *PathState_coop, /* Required for shadow blocked */
+ ccl_global Ray *LightRay_dl_coop, /* Required for direct lighting's shadow blocked */
+ ccl_global Ray *LightRay_ao_coop, /* Required for AO's shadow blocked */
+ Intersection *Intersection_coop_AO,
+ Intersection *Intersection_coop_DL,
+ ccl_global char *ray_state,
+ ccl_global int *Queue_data, /* Queue memory */
+ ccl_global int *Queue_index, /* Tracks the number of elements in each queue */
+ int queuesize, /* Size (capacity) of each queue */
+ int total_num_rays)
+{
+#if 0
+ /* We will make the Queue_index entries '0' in the next kernel. */
+ if(get_global_id(0) == 0 && get_global_id(1) == 0) {
+ /* We empty this queue here */
+ Queue_index[QUEUE_SHADOW_RAY_CAST_AO_RAYS] = 0;
+ Queue_index[QUEUE_SHADOW_RAY_CAST_DL_RAYS] = 0;
+ }
+#endif
+
+ int lidx = get_local_id(1) * get_local_id(0) + get_local_id(0);
+
+ ccl_local unsigned int ao_queue_length;
+ ccl_local unsigned int dl_queue_length;
+ if(lidx == 0) {
+ ao_queue_length = Queue_index[QUEUE_SHADOW_RAY_CAST_AO_RAYS];
+ dl_queue_length = Queue_index[QUEUE_SHADOW_RAY_CAST_DL_RAYS];
+ }
+ barrier(CLK_LOCAL_MEM_FENCE);
+
+ /* flag determining if the current ray is to process shadow ray for AO or DL */
+ char shadow_blocked_type = -1;
+
+ int ray_index = QUEUE_EMPTY_SLOT;
+ int thread_index = get_global_id(1) * get_global_size(0) + get_global_id(0);
+ if(thread_index < ao_queue_length + dl_queue_length) {
+ if(thread_index < ao_queue_length) {
+ ray_index = get_ray_index(thread_index, QUEUE_SHADOW_RAY_CAST_AO_RAYS, Queue_data, queuesize, 1);
+ shadow_blocked_type = RAY_SHADOW_RAY_CAST_AO;
+ } else {
+ ray_index = get_ray_index(thread_index - ao_queue_length, QUEUE_SHADOW_RAY_CAST_DL_RAYS, Queue_data, queuesize, 1);
+ shadow_blocked_type = RAY_SHADOW_RAY_CAST_DL;
+ }
+ }
+
+ if(ray_index == QUEUE_EMPTY_SLOT)
+ return;
+
+ kernel_shadow_blocked(globals,
+ data,
+ shader_shadow,
+ PathState_coop,
+ LightRay_dl_coop,
+ LightRay_ao_coop,
+ Intersection_coop_AO,
+ Intersection_coop_DL,
+ ray_state,
+ total_num_rays,
+ shadow_blocked_type,
+ ray_index);
+}
diff --git a/intern/cycles/kernel/kernels/opencl/kernel_sum_all_radiance.cl b/intern/cycles/kernel/kernels/opencl/kernel_sum_all_radiance.cl
new file mode 100644
index 00000000000..88a1ed830af
--- /dev/null
+++ b/intern/cycles/kernel/kernels/opencl/kernel_sum_all_radiance.cl
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2011-2015 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 "split/kernel_sum_all_radiance.h"
+
+__kernel void kernel_ocl_path_trace_sum_all_radiance(
+ ccl_constant KernelData *data, /* To get pass_stride to offet into buffer */
+ ccl_global float *buffer, /* Output buffer of RenderTile */
+ ccl_global float *per_sample_output_buffer, /* Radiance contributed by all samples */
+ int parallel_samples, int sw, int sh, int stride,
+ int buffer_offset_x,
+ int buffer_offset_y,
+ int buffer_stride,
+ int start_sample)
+{
+ kernel_sum_all_radiance(data,
+ buffer,
+ per_sample_output_buffer,
+ parallel_samples,
+ sw, sh, stride,
+ buffer_offset_x,
+ buffer_offset_y,
+ buffer_stride,
+ start_sample);
+}
diff --git a/intern/cycles/kernel/osl/SConscript b/intern/cycles/kernel/osl/SConscript
index 4685bb7753e..74ba5e1020c 100644
--- a/intern/cycles/kernel/osl/SConscript
+++ b/intern/cycles/kernel/osl/SConscript
@@ -38,11 +38,38 @@ incs.append(env['BF_OIIO_INC'])
incs.append(env['BF_BOOST_INC'])
incs.append(env['BF_OSL_INC'])
incs.append(env['BF_OPENEXR_INC'].split())
+incs.append('#/intern/atomic')
defs.append('CCL_NAMESPACE_BEGIN=namespace ccl {')
defs.append('CCL_NAMESPACE_END=}')
defs.append('WITH_OSL')
+if env['WITH_UNORDERED_MAP_SUPPORT']:
+ if env['UNORDERED_MAP_HEADER'] == 'unordered_map':
+ if env['UNORDERED_MAP_NAMESPACE'] == 'std':
+ defs.append('CYCLES_STD_UNORDERED_MAP')
+ elif env['UNORDERED_MAP_NAMESPACE'] == 'std::tr1':
+ defs.append('CYCLES_STD_UNORDERED_MAP_IN_TR1_NAMESPACE')
+ elif env['UNORDERED_MAP_NAMESPACE'] == 'std::tr1':
+ defs.append('CYCLES_TR1_UNORDERED_MAP')
+else:
+ print("-- Replacing unordered_map/set with map/set (warning: slower!)")
+ defs.append('CYCLES_NO_UNORDERED_MAP')
+
+if env['WITH_BF_CYCLES_DEBUG']:
+ defs.append('WITH_CYCLES_DEBUG')
+
+if env['WITH_BF_CYCLES_LOGGING']:
+ defs.append('WITH_CYCLES_LOGGING')
+ defs.append('GOOGLE_GLOG_DLL_DECL=')
+ defs.append('CYCLES_GFLAGS_NAMESPACE=gflags')
+ if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'linuxcross', 'win64-vc', 'win64-mingw'):
+ incs.append('#extern/libmv/third_party/glog/src/windows')
+ incs.append('#extern/libmv/third_party/gflags')
+ else:
+ incs.append('#extern/libmv/third_party/glog/src')
+ incs.append('#extern/libmv/third_party/gflags')
+
if env['OURPLATFORM'] in ('win32-vc', 'win64-vc'):
cxxflags.append('-DBOOST_NO_RTTI -DBOOST_NO_TYPEID /fp:fast'.split())
incs.append(env['BF_PTHREADS_INC'])
diff --git a/intern/cycles/kernel/osl/background.cpp b/intern/cycles/kernel/osl/background.cpp
index 2facced0914..4d70bc80006 100644
--- a/intern/cycles/kernel/osl/background.cpp
+++ b/intern/cycles/kernel/osl/background.cpp
@@ -77,7 +77,7 @@ public:
ClosureParam *closure_background_params()
{
static ClosureParam params[] = {
- CLOSURE_STRING_KEYPARAM("label"),
+ CLOSURE_STRING_KEYPARAM(GenericBackgroundClosure, label, "label"),
CLOSURE_FINISH_PARAM(GenericBackgroundClosure)
};
return params;
@@ -98,7 +98,7 @@ CCLOSURE_PREPARE(closure_holdout_prepare, HoldoutClosure)
ClosureParam *closure_ambient_occlusion_params()
{
static ClosureParam params[] = {
- CLOSURE_STRING_KEYPARAM("label"),
+ CLOSURE_STRING_KEYPARAM(AmbientOcclusionClosure, label, "label"),
CLOSURE_FINISH_PARAM(AmbientOcclusionClosure)
};
return params;
diff --git a/intern/cycles/kernel/osl/bsdf_diffuse_ramp.cpp b/intern/cycles/kernel/osl/bsdf_diffuse_ramp.cpp
index 8f9c2efd470..b3c71e4a706 100644
--- a/intern/cycles/kernel/osl/bsdf_diffuse_ramp.cpp
+++ b/intern/cycles/kernel/osl/bsdf_diffuse_ramp.cpp
@@ -34,6 +34,7 @@
#include <OSL/genclosure.h>
+#include "kernel_compat_cpu.h"
#include "osl_closures.h"
#include "kernel_types.h"
@@ -92,7 +93,7 @@ ClosureParam *closure_bsdf_diffuse_ramp_params()
static ClosureParam params[] = {
CLOSURE_FLOAT3_PARAM(DiffuseRampClosure, sc.N),
CLOSURE_COLOR_ARRAY_PARAM(DiffuseRampClosure, colors, 8),
- CLOSURE_STRING_KEYPARAM("label"),
+ CLOSURE_STRING_KEYPARAM(DiffuseRampClosure, label, "label"),
CLOSURE_FINISH_PARAM(DiffuseRampClosure)
};
return params;
diff --git a/intern/cycles/kernel/osl/bsdf_phong_ramp.cpp b/intern/cycles/kernel/osl/bsdf_phong_ramp.cpp
index c5851747b54..99f510d31ed 100644
--- a/intern/cycles/kernel/osl/bsdf_phong_ramp.cpp
+++ b/intern/cycles/kernel/osl/bsdf_phong_ramp.cpp
@@ -34,6 +34,7 @@
#include <OSL/genclosure.h>
+#include "kernel_compat_cpu.h"
#include "osl_closures.h"
#include "kernel_types.h"
@@ -92,7 +93,7 @@ ClosureParam *closure_bsdf_phong_ramp_params()
CLOSURE_FLOAT3_PARAM(PhongRampClosure, sc.N),
CLOSURE_FLOAT_PARAM(PhongRampClosure, sc.data0),
CLOSURE_COLOR_ARRAY_PARAM(PhongRampClosure, colors, 8),
- CLOSURE_STRING_KEYPARAM("label"),
+ CLOSURE_STRING_KEYPARAM(PhongRampClosure, label, "label"),
CLOSURE_FINISH_PARAM(PhongRampClosure)
};
return params;
diff --git a/intern/cycles/kernel/osl/emissive.cpp b/intern/cycles/kernel/osl/emissive.cpp
index 02935542c56..9a95fa57a81 100644
--- a/intern/cycles/kernel/osl/emissive.cpp
+++ b/intern/cycles/kernel/osl/emissive.cpp
@@ -77,7 +77,7 @@ public:
ClosureParam *closure_emission_params()
{
static ClosureParam params[] = {
- CLOSURE_STRING_KEYPARAM("label"),
+ CLOSURE_STRING_KEYPARAM(GenericEmissiveClosure, label, "label"),
CLOSURE_FINISH_PARAM(GenericEmissiveClosure)
};
return params;
diff --git a/intern/cycles/kernel/osl/osl_bssrdf.cpp b/intern/cycles/kernel/osl/osl_bssrdf.cpp
index 84ef85e089d..bc395922077 100644
--- a/intern/cycles/kernel/osl/osl_bssrdf.cpp
+++ b/intern/cycles/kernel/osl/osl_bssrdf.cpp
@@ -34,6 +34,7 @@
#include <OSL/genclosure.h>
+#include "kernel_compat_cpu.h"
#include "osl_bssrdf.h"
#include "osl_closures.h"
@@ -68,7 +69,7 @@ ClosureParam *closure_bssrdf_cubic_params()
CLOSURE_FLOAT3_PARAM(CubicBSSRDFClosure, radius),
CLOSURE_FLOAT_PARAM(CubicBSSRDFClosure, sc.data1),
CLOSURE_FLOAT_PARAM(CubicBSSRDFClosure, sc.T.x),
- CLOSURE_STRING_KEYPARAM("label"),
+ CLOSURE_STRING_KEYPARAM(CubicBSSRDFClosure, label, "label"),
CLOSURE_FINISH_PARAM(CubicBSSRDFClosure)
};
return params;
@@ -96,7 +97,7 @@ ClosureParam *closure_bssrdf_gaussian_params()
CLOSURE_FLOAT3_PARAM(GaussianBSSRDFClosure, sc.N),
CLOSURE_FLOAT3_PARAM(GaussianBSSRDFClosure, radius),
CLOSURE_FLOAT_PARAM(GaussianBSSRDFClosure, sc.data1),
- CLOSURE_STRING_KEYPARAM("label"),
+ CLOSURE_STRING_KEYPARAM(GaussianBSSRDFClosure, label, "label"),
CLOSURE_FINISH_PARAM(GaussianBSSRDFClosure)
};
return params;
diff --git a/intern/cycles/kernel/osl/osl_closures.cpp b/intern/cycles/kernel/osl/osl_closures.cpp
index d7789edcfff..461ce8f7598 100644
--- a/intern/cycles/kernel/osl/osl_closures.cpp
+++ b/intern/cycles/kernel/osl/osl_closures.cpp
@@ -54,7 +54,6 @@
#include "closure/bsdf_refraction.h"
#include "closure/bsdf_transparent.h"
#include "closure/bsdf_ashikhmin_shirley.h"
-#include "closure/bsdf_westin.h"
#include "closure/bsdf_toon.h"
#include "closure/bsdf_hair.h"
#include "closure/volume.h"
@@ -87,16 +86,6 @@ BSDF_CLOSURE_CLASS_BEGIN(Refraction, refraction, refraction, LABEL_SINGULAR)
CLOSURE_FLOAT_PARAM(RefractionClosure, sc.data0),
BSDF_CLOSURE_CLASS_END(Refraction, refraction)
-BSDF_CLOSURE_CLASS_BEGIN(WestinBackscatter, westin_backscatter, westin_backscatter, LABEL_GLOSSY)
- CLOSURE_FLOAT3_PARAM(WestinBackscatterClosure, sc.N),
- CLOSURE_FLOAT_PARAM(WestinBackscatterClosure, sc.data0),
-BSDF_CLOSURE_CLASS_END(WestinBackscatter, westin_backscatter)
-
-BSDF_CLOSURE_CLASS_BEGIN(WestinSheen, westin_sheen, westin_sheen, LABEL_DIFFUSE)
- CLOSURE_FLOAT3_PARAM(WestinSheenClosure, sc.N),
- CLOSURE_FLOAT_PARAM(WestinSheenClosure, sc.data0),
-BSDF_CLOSURE_CLASS_END(WestinSheen, westin_sheen)
-
BSDF_CLOSURE_CLASS_BEGIN(Transparent, transparent, transparent, LABEL_SINGULAR)
BSDF_CLOSURE_CLASS_END(Transparent, transparent)
@@ -164,26 +153,16 @@ BSDF_CLOSURE_CLASS_BEGIN(HairReflection, hair_reflection, hair_reflection, LABEL
CLOSURE_FLOAT3_PARAM(HairReflectionClosure, sc.N),
CLOSURE_FLOAT_PARAM(HairReflectionClosure, sc.data0),
CLOSURE_FLOAT_PARAM(HairReflectionClosure, sc.data1),
-#ifdef __HAIR__
CLOSURE_FLOAT3_PARAM(HairReflectionClosure, sc.T),
CLOSURE_FLOAT_PARAM(HairReflectionClosure, sc.data2),
-#else
- CLOSURE_FLOAT3_PARAM(HairReflectionClosure, sc.N),
- CLOSURE_FLOAT_PARAM(HairReflectionClosure, sc.data1),
-#endif
BSDF_CLOSURE_CLASS_END(HairReflection, hair_reflection)
BSDF_CLOSURE_CLASS_BEGIN(HairTransmission, hair_transmission, hair_transmission, LABEL_GLOSSY)
CLOSURE_FLOAT3_PARAM(HairTransmissionClosure, sc.N),
CLOSURE_FLOAT_PARAM(HairTransmissionClosure, sc.data0),
CLOSURE_FLOAT_PARAM(HairTransmissionClosure, sc.data1),
-#ifdef __HAIR__
CLOSURE_FLOAT3_PARAM(HairReflectionClosure, sc.T),
CLOSURE_FLOAT_PARAM(HairReflectionClosure, sc.data2),
-#else
- CLOSURE_FLOAT3_PARAM(HairReflectionClosure, sc.N),
- CLOSURE_FLOAT_PARAM(HairReflectionClosure, sc.data1),
-#endif
BSDF_CLOSURE_CLASS_END(HairTransmission, hair_transmission)
VOLUME_CLOSURE_CLASS_BEGIN(VolumeHenyeyGreenstein, henyey_greenstein, LABEL_VOLUME_SCATTER)
@@ -200,11 +179,7 @@ static void register_closure(OSL::ShadingSystem *ss, const char *name, int id, O
/* optimization: it's possible to not use a prepare function at all and
* only initialize the actual class when accessing the closure component
* data, but then we need to map the id to the class somehow */
-#ifdef CLOSURE_PREPARE
- ss->register_closure(name, id, params, prepare, NULL, NULL);
-#else
- ss->register_closure(name, id, params, prepare, NULL);
-#endif
+ ss->register_closure(name, id, params, prepare, NULL, 16);
}
void OSLShader::register_closures(OSLShadingSystem *ss_)
@@ -244,10 +219,6 @@ void OSLShader::register_closures(OSLShadingSystem *ss_)
bsdf_diffuse_toon_params(), bsdf_diffuse_toon_prepare);
register_closure(ss, "glossy_toon", id++,
bsdf_glossy_toon_params(), bsdf_glossy_toon_prepare);
- register_closure(ss, "westin_backscatter", id++,
- bsdf_westin_backscatter_params(), bsdf_westin_backscatter_prepare);
- register_closure(ss, "westin_sheen", id++,
- bsdf_westin_sheen_params(), bsdf_westin_sheen_prepare);
register_closure(ss, "emission", id++,
closure_emission_params(), closure_emission_prepare);
diff --git a/intern/cycles/kernel/osl/osl_closures.h b/intern/cycles/kernel/osl/osl_closures.h
index 58d215295dc..97bd1b1ac92 100644
--- a/intern/cycles/kernel/osl/osl_closures.h
+++ b/intern/cycles/kernel/osl/osl_closures.h
@@ -48,8 +48,6 @@ OSL::ClosureParam *closure_holdout_params();
OSL::ClosureParam *closure_ambient_occlusion_params();
OSL::ClosureParam *closure_bsdf_diffuse_ramp_params();
OSL::ClosureParam *closure_bsdf_phong_ramp_params();
-OSL::ClosureParam *closure_westin_backscatter_params();
-OSL::ClosureParam *closure_westin_sheen_params();
OSL::ClosureParam *closure_bssrdf_cubic_params();
OSL::ClosureParam *closure_bssrdf_gaussian_params();
OSL::ClosureParam *closure_henyey_greenstein_volume_params();
@@ -60,8 +58,6 @@ void closure_holdout_prepare(OSL::RendererServices *, int id, void *data);
void closure_ambient_occlusion_prepare(OSL::RendererServices *, int id, void *data);
void closure_bsdf_diffuse_ramp_prepare(OSL::RendererServices *, int id, void *data);
void closure_bsdf_phong_ramp_prepare(OSL::RendererServices *, int id, void *data);
-void closure_westin_backscatter_prepare(OSL::RendererServices *, int id, void *data);
-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);
void closure_henyey_greenstein_volume_prepare(OSL::RendererServices *, int id, void *data);
@@ -82,6 +78,11 @@ void name(RendererServices *, int id, void *data) \
#define TO_COLOR3(v) OSL::Color3(v.x, v.y, v.z)
#define TO_FLOAT3(v) make_float3(v[0], v[1], v[2])
+#if OSL_LIBRARY_VERSION_CODE < 10700
+# undef CLOSURE_STRING_KEYPARAM
+# define CLOSURE_STRING_KEYPARAM(st, fld, key) { TypeDesc::TypeString, 0, key, 0 }
+#endif
+
/* Closure */
class CClosurePrimitive {
@@ -101,6 +102,10 @@ public:
virtual void setup() {}
Category category;
+
+#if OSL_LIBRARY_VERSION_CODE >= 10700
+ OSL::ustring label;
+#endif
};
/* BSDF */
@@ -151,14 +156,14 @@ public: \
\
float3 eval_reflect(const float3 &omega_out, const float3 &omega_in, float& pdf) const \
{ \
- pdf = 0; \
- return make_float3(0, 0, 0); \
+ pdf = 0.0f; \
+ return make_float3(0.0f, 0.0f, 0.0f); \
} \
\
float3 eval_transmit(const float3 &omega_out, const float3 &omega_in, float& pdf) const \
{ \
- pdf = 0; \
- return make_float3(0, 0, 0); \
+ pdf = 0.0f; \
+ return make_float3(0.0f, 0.0f, 0.0f); \
} \
\
int sample(const float3 &Ng, \
@@ -179,7 +184,7 @@ static ClosureParam *bsdf_##lower##_params() \
/* parameters */
#define BSDF_CLOSURE_CLASS_END(Upper, lower) \
- CLOSURE_STRING_KEYPARAM("label"), \
+ CLOSURE_STRING_KEYPARAM(Upper##Closure, label, "label"), \
CLOSURE_FINISH_PARAM(Upper##Closure) \
}; \
return params; \
@@ -227,7 +232,7 @@ static ClosureParam *volume_##lower##_params() \
/* parameters */
#define VOLUME_CLOSURE_CLASS_END(Upper, lower) \
- CLOSURE_STRING_KEYPARAM("label"), \
+ CLOSURE_STRING_KEYPARAM(Upper##Closure, label, "label"), \
CLOSURE_FINISH_PARAM(Upper##Closure) \
}; \
return params; \
diff --git a/intern/cycles/kernel/osl/osl_globals.h b/intern/cycles/kernel/osl/osl_globals.h
index 5a658d8244a..e349ac676b0 100644
--- a/intern/cycles/kernel/osl/osl_globals.h
+++ b/intern/cycles/kernel/osl/osl_globals.h
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#ifndef __OSL_GLOBALS_H__
@@ -20,7 +20,6 @@
#ifdef WITH_OSL
#include <OSL/oslexec.h>
-#include <cmath>
#include "util_map.h"
#include "util_param.h"
diff --git a/intern/cycles/kernel/osl/osl_services.cpp b/intern/cycles/kernel/osl/osl_services.cpp
index 1475e5a0a62..3c1955a1e1e 100644
--- a/intern/cycles/kernel/osl/osl_services.cpp
+++ b/intern/cycles/kernel/osl/osl_services.cpp
@@ -11,9 +11,18 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
+/* TODO(sergey): There is a bit of headers dependency hell going on
+ * here, so for now we just put here. In the future it might be better
+ * to have dedicated file for such tweaks.
+ */
+#if defined(__GNUC__) && defined(NDEBUG)
+# pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
+# pragma GCC diagnostic ignored "-Wuninitialized"
+#endif
+
#include <string.h>
#include "mesh.h"
@@ -130,12 +139,12 @@ bool OSLRenderServices::get_matrix(OSL::ShaderGlobals *sg, OSL::Matrix44 &result
{
/* this is only used for shader and object space, we don't really have
* a concept of shader space, so we just use object space for both. */
- if (xform) {
+ if(xform) {
const ShaderData *sd = (const ShaderData *)xform;
KernelGlobals *kg = sd->osl_globals;
int object = sd->object;
- if (object != OBJECT_NONE) {
+ if(object != OBJECT_NONE) {
#ifdef __OBJECT_MOTION__
Transform tfm;
@@ -160,12 +169,12 @@ bool OSLRenderServices::get_inverse_matrix(OSL::ShaderGlobals *sg, OSL::Matrix44
{
/* this is only used for shader and object space, we don't really have
* a concept of shader space, so we just use object space for both. */
- if (xform) {
+ if(xform) {
const ShaderData *sd = (const ShaderData *)xform;
KernelGlobals *kg = sd->osl_globals;
int object = sd->object;
- if (object != OBJECT_NONE) {
+ if(object != OBJECT_NONE) {
#ifdef __OBJECT_MOTION__
Transform itfm;
@@ -190,27 +199,27 @@ bool OSLRenderServices::get_matrix(OSL::ShaderGlobals *sg, OSL::Matrix44 &result
{
KernelGlobals *kg = kernel_globals;
- if (from == u_ndc) {
+ if(from == u_ndc) {
Transform tfm = transform_transpose(transform_quick_inverse(kernel_data.cam.worldtondc));
COPY_MATRIX44(&result, &tfm);
return true;
}
- else if (from == u_raster) {
+ else if(from == u_raster) {
Transform tfm = transform_transpose(kernel_data.cam.rastertoworld);
COPY_MATRIX44(&result, &tfm);
return true;
}
- else if (from == u_screen) {
+ else if(from == u_screen) {
Transform tfm = transform_transpose(kernel_data.cam.screentoworld);
COPY_MATRIX44(&result, &tfm);
return true;
}
- else if (from == u_camera) {
+ else if(from == u_camera) {
Transform tfm = transform_transpose(kernel_data.cam.cameratoworld);
COPY_MATRIX44(&result, &tfm);
return true;
}
- else if (from == u_world) {
+ else if(from == u_world) {
result.makeIdentity();
return true;
}
@@ -222,27 +231,27 @@ bool OSLRenderServices::get_inverse_matrix(OSL::ShaderGlobals *sg, OSL::Matrix44
{
KernelGlobals *kg = kernel_globals;
- if (to == u_ndc) {
+ if(to == u_ndc) {
Transform tfm = transform_transpose(kernel_data.cam.worldtondc);
COPY_MATRIX44(&result, &tfm);
return true;
}
- else if (to == u_raster) {
+ else if(to == u_raster) {
Transform tfm = transform_transpose(kernel_data.cam.worldtoraster);
COPY_MATRIX44(&result, &tfm);
return true;
}
- else if (to == u_screen) {
+ else if(to == u_screen) {
Transform tfm = transform_transpose(kernel_data.cam.worldtoscreen);
COPY_MATRIX44(&result, &tfm);
return true;
}
- else if (to == u_camera) {
+ else if(to == u_camera) {
Transform tfm = transform_transpose(kernel_data.cam.worldtocamera);
COPY_MATRIX44(&result, &tfm);
return true;
}
- else if (to == u_world) {
+ else if(to == u_world) {
result.makeIdentity();
return true;
}
@@ -254,11 +263,11 @@ bool OSLRenderServices::get_matrix(OSL::ShaderGlobals *sg, OSL::Matrix44 &result
{
/* this is only used for shader and object space, we don't really have
* a concept of shader space, so we just use object space for both. */
- if (xform) {
+ if(xform) {
const ShaderData *sd = (const ShaderData *)xform;
int object = sd->object;
- if (object != OBJECT_NONE) {
+ if(object != OBJECT_NONE) {
#ifdef __OBJECT_MOTION__
Transform tfm = sd->ob_tfm;
#else
@@ -279,11 +288,11 @@ bool OSLRenderServices::get_inverse_matrix(OSL::ShaderGlobals *sg, OSL::Matrix44
{
/* this is only used for shader and object space, we don't really have
* a concept of shader space, so we just use object space for both. */
- if (xform) {
+ if(xform) {
const ShaderData *sd = (const ShaderData *)xform;
int object = sd->object;
- if (object != OBJECT_NONE) {
+ if(object != OBJECT_NONE) {
#ifdef __OBJECT_MOTION__
Transform tfm = sd->ob_itfm;
#else
@@ -304,22 +313,22 @@ bool OSLRenderServices::get_matrix(OSL::ShaderGlobals *sg, OSL::Matrix44 &result
{
KernelGlobals *kg = kernel_globals;
- if (from == u_ndc) {
+ if(from == u_ndc) {
Transform tfm = transform_transpose(transform_quick_inverse(kernel_data.cam.worldtondc));
COPY_MATRIX44(&result, &tfm);
return true;
}
- else if (from == u_raster) {
+ else if(from == u_raster) {
Transform tfm = transform_transpose(kernel_data.cam.rastertoworld);
COPY_MATRIX44(&result, &tfm);
return true;
}
- else if (from == u_screen) {
+ else if(from == u_screen) {
Transform tfm = transform_transpose(kernel_data.cam.screentoworld);
COPY_MATRIX44(&result, &tfm);
return true;
}
- else if (from == u_camera) {
+ else if(from == u_camera) {
Transform tfm = transform_transpose(kernel_data.cam.cameratoworld);
COPY_MATRIX44(&result, &tfm);
return true;
@@ -332,22 +341,22 @@ bool OSLRenderServices::get_inverse_matrix(OSL::ShaderGlobals *sg, OSL::Matrix44
{
KernelGlobals *kg = kernel_globals;
- if (to == u_ndc) {
+ if(to == u_ndc) {
Transform tfm = transform_transpose(kernel_data.cam.worldtondc);
COPY_MATRIX44(&result, &tfm);
return true;
}
- else if (to == u_raster) {
+ else if(to == u_raster) {
Transform tfm = transform_transpose(kernel_data.cam.worldtoraster);
COPY_MATRIX44(&result, &tfm);
return true;
}
- else if (to == u_screen) {
+ else if(to == u_screen) {
Transform tfm = transform_transpose(kernel_data.cam.worldtoscreen);
COPY_MATRIX44(&result, &tfm);
return true;
}
- else if (to == u_camera) {
+ else if(to == u_camera) {
Transform tfm = transform_transpose(kernel_data.cam.worldtocamera);
COPY_MATRIX44(&result, &tfm);
return true;
@@ -365,8 +374,8 @@ bool OSLRenderServices::get_array_attribute(OSL::ShaderGlobals *sg, bool derivat
static bool set_attribute_float3(float3 f[3], TypeDesc type, bool derivatives, void *val)
{
- if (type == TypeDesc::TypePoint || type == TypeDesc::TypeVector ||
- type == TypeDesc::TypeNormal || type == TypeDesc::TypeColor)
+ if(type == TypeDesc::TypePoint || type == TypeDesc::TypeVector ||
+ type == TypeDesc::TypeNormal || type == TypeDesc::TypeColor)
{
float *fval = (float *)val;
@@ -374,7 +383,7 @@ static bool set_attribute_float3(float3 f[3], TypeDesc type, bool derivatives, v
fval[1] = f[0].y;
fval[2] = f[0].z;
- if (derivatives) {
+ if(derivatives) {
fval[3] = f[1].x;
fval[4] = f[1].y;
fval[5] = f[1].z;
@@ -390,7 +399,7 @@ static bool set_attribute_float3(float3 f[3], TypeDesc type, bool derivatives, v
float *fval = (float *)val;
fval[0] = average(f[0]);
- if (derivatives) {
+ if(derivatives) {
fval[1] = average(f[1]);
fval[2] = average(f[2]);
}
@@ -414,15 +423,15 @@ static bool set_attribute_float3(float3 f, TypeDesc type, bool derivatives, void
static bool set_attribute_float(float f[3], TypeDesc type, bool derivatives, void *val)
{
- if (type == TypeDesc::TypePoint || type == TypeDesc::TypeVector ||
- type == TypeDesc::TypeNormal || type == TypeDesc::TypeColor)
+ if(type == TypeDesc::TypePoint || type == TypeDesc::TypeVector ||
+ type == TypeDesc::TypeNormal || type == TypeDesc::TypeColor)
{
float *fval = (float *)val;
fval[0] = f[0];
fval[1] = f[1];
fval[2] = f[2];
- if (derivatives) {
+ if(derivatives) {
fval[3] = f[1];
fval[4] = f[1];
fval[5] = f[1];
@@ -438,7 +447,7 @@ static bool set_attribute_float(float f[3], TypeDesc type, bool derivatives, voi
float *fval = (float *)val;
fval[0] = f[0];
- if (derivatives) {
+ if(derivatives) {
fval[1] = f[1];
fval[2] = f[2];
}
@@ -466,7 +475,7 @@ static bool set_attribute_int(int i, TypeDesc type, bool derivatives, void *val)
int *ival = (int *)val;
ival[0] = i;
- if (derivatives) {
+ if(derivatives) {
ival[1] = 0;
ival[2] = 0;
}
@@ -483,7 +492,7 @@ static bool set_attribute_string(ustring str, TypeDesc type, bool derivatives, v
ustring *sval = (ustring *)val;
sval[0] = str;
- if (derivatives) {
+ if(derivatives) {
sval[1] = OSLRenderServices::u_empty;
sval[2] = OSLRenderServices::u_empty;
}
@@ -513,7 +522,7 @@ static bool set_attribute_float3_3(float3 P[3], TypeDesc type, bool derivatives,
if(type.arraylen > 3)
memset(fval + 3*3, 0, sizeof(float)*3*(type.arraylen - 3));
- if (derivatives)
+ if(derivatives)
memset(fval + type.arraylen*3, 0, sizeof(float)*2*3*type.arraylen);
return true;
@@ -536,15 +545,15 @@ static bool set_attribute_matrix(const Transform& tfm, TypeDesc type, void *val)
static bool get_mesh_element_attribute(KernelGlobals *kg, const ShaderData *sd, const OSLGlobals::Attribute& attr,
const TypeDesc& type, bool derivatives, void *val)
{
- if (attr.type == TypeDesc::TypePoint || attr.type == TypeDesc::TypeVector ||
- attr.type == TypeDesc::TypeNormal || attr.type == TypeDesc::TypeColor)
+ if(attr.type == TypeDesc::TypePoint || attr.type == TypeDesc::TypeVector ||
+ attr.type == TypeDesc::TypeNormal || attr.type == TypeDesc::TypeColor)
{
float3 fval[3];
fval[0] = primitive_attribute_float3(kg, sd, attr.elem, attr.offset,
(derivatives) ? &fval[1] : NULL, (derivatives) ? &fval[2] : NULL);
return set_attribute_float3(fval, type, derivatives, val);
}
- else if (attr.type == TypeDesc::TypeFloat) {
+ else if(attr.type == TypeDesc::TypeFloat) {
float fval[3];
fval[0] = primitive_attribute_float(kg, sd, attr.elem, attr.offset,
(derivatives) ? &fval[1] : NULL, (derivatives) ? &fval[2] : NULL);
@@ -558,7 +567,7 @@ static bool get_mesh_element_attribute(KernelGlobals *kg, const ShaderData *sd,
static bool get_mesh_attribute(KernelGlobals *kg, const ShaderData *sd, const OSLGlobals::Attribute& attr,
const TypeDesc& type, bool derivatives, void *val)
{
- if (attr.type == TypeDesc::TypeMatrix) {
+ if(attr.type == TypeDesc::TypeMatrix) {
Transform tfm = primitive_attribute_matrix(kg, sd, attr.offset);
return set_attribute_matrix(tfm, type, val);
}
@@ -572,7 +581,7 @@ static void get_object_attribute(const OSLGlobals::Attribute& attr, bool derivat
size_t datasize = attr.value.datasize();
memcpy(val, attr.value.data(), datasize);
- if (derivatives)
+ if(derivatives)
memset((char *)val + datasize, 0, datasize * 2);
}
@@ -582,80 +591,80 @@ bool OSLRenderServices::get_object_standard_attribute(KernelGlobals *kg, ShaderD
/* todo: turn this into hash table? */
/* Object Attributes */
- if (name == u_object_location) {
+ if(name == u_object_location) {
float3 f = object_location(kg, sd);
return set_attribute_float3(f, type, derivatives, val);
}
- else if (name == u_object_index) {
+ else if(name == u_object_index) {
float f = object_pass_id(kg, sd->object);
return set_attribute_float(f, type, derivatives, val);
}
- else if (name == u_geom_dupli_generated) {
+ else if(name == u_geom_dupli_generated) {
float3 f = object_dupli_generated(kg, sd->object);
return set_attribute_float3(f, type, derivatives, val);
}
- else if (name == u_geom_dupli_uv) {
+ else if(name == u_geom_dupli_uv) {
float3 f = object_dupli_uv(kg, sd->object);
return set_attribute_float3(f, type, derivatives, val);
}
- else if (name == u_material_index) {
+ else if(name == u_material_index) {
float f = shader_pass_id(kg, sd);
return set_attribute_float(f, type, derivatives, val);
}
- else if (name == u_object_random) {
+ else if(name == u_object_random) {
float f = object_random_number(kg, sd->object);
return set_attribute_float(f, type, derivatives, val);
}
/* Particle Attributes */
- else if (name == u_particle_index) {
+ else if(name == u_particle_index) {
int particle_id = object_particle_id(kg, sd->object);
float f = particle_index(kg, particle_id);
return set_attribute_float(f, type, derivatives, val);
}
- else if (name == u_particle_age) {
+ else if(name == u_particle_age) {
int particle_id = object_particle_id(kg, sd->object);
float f = particle_age(kg, particle_id);
return set_attribute_float(f, type, derivatives, val);
}
- else if (name == u_particle_lifetime) {
+ else if(name == u_particle_lifetime) {
int particle_id = object_particle_id(kg, sd->object);
float f = particle_lifetime(kg, particle_id);
return set_attribute_float(f, type, derivatives, val);
}
- else if (name == u_particle_location) {
+ else if(name == u_particle_location) {
int particle_id = object_particle_id(kg, sd->object);
float3 f = particle_location(kg, particle_id);
return set_attribute_float3(f, type, derivatives, val);
}
#if 0 /* unsupported */
- else if (name == u_particle_rotation) {
+ else if(name == u_particle_rotation) {
int particle_id = object_particle_id(kg, sd->object);
float4 f = particle_rotation(kg, particle_id);
return set_attribute_float4(f, type, derivatives, val);
}
#endif
- else if (name == u_particle_size) {
+ else if(name == u_particle_size) {
int particle_id = object_particle_id(kg, sd->object);
float f = particle_size(kg, particle_id);
return set_attribute_float(f, type, derivatives, val);
}
- else if (name == u_particle_velocity) {
+ else if(name == u_particle_velocity) {
int particle_id = object_particle_id(kg, sd->object);
float3 f = particle_velocity(kg, particle_id);
return set_attribute_float3(f, type, derivatives, val);
}
- else if (name == u_particle_angular_velocity) {
+ else if(name == u_particle_angular_velocity) {
int particle_id = object_particle_id(kg, sd->object);
float3 f = particle_angular_velocity(kg, particle_id);
return set_attribute_float3(f, type, derivatives, val);
}
/* Geometry Attributes */
- else if (name == u_geom_numpolyvertices) {
+ else if(name == u_geom_numpolyvertices) {
return set_attribute_int(3, type, derivatives, val);
}
- else if ((name == u_geom_trianglevertices || name == u_geom_polyvertices)
+ else if((name == u_geom_trianglevertices || name == u_geom_polyvertices)
#ifdef __HAIR__
&& sd->type & PRIMITIVE_ALL_TRIANGLE)
#else
@@ -681,21 +690,21 @@ bool OSLRenderServices::get_object_standard_attribute(KernelGlobals *kg, ShaderD
ustring object_name = kg->osl->object_names[sd->object];
return set_attribute_string(object_name, type, derivatives, val);
}
- else if (name == u_is_smooth) {
+ else if(name == u_is_smooth) {
float f = ((sd->shader & SHADER_SMOOTH_NORMAL) != 0);
return set_attribute_float(f, type, derivatives, val);
}
#ifdef __HAIR__
/* Hair Attributes */
- else if (name == u_is_curve) {
+ else if(name == u_is_curve) {
float f = (sd->type & PRIMITIVE_ALL_CURVE) != 0;
return set_attribute_float(f, type, derivatives, val);
}
- else if (name == u_curve_thickness) {
+ else if(name == u_curve_thickness) {
float f = curve_thickness(kg, sd);
return set_attribute_float(f, type, derivatives, val);
}
- else if (name == u_curve_tangent_normal) {
+ else if(name == u_curve_tangent_normal) {
float3 f = curve_tangent_normal(kg, sd);
return set_attribute_float3(f, type, derivatives, val);
}
@@ -707,22 +716,22 @@ bool OSLRenderServices::get_object_standard_attribute(KernelGlobals *kg, ShaderD
bool OSLRenderServices::get_background_attribute(KernelGlobals *kg, ShaderData *sd, ustring name,
TypeDesc type, bool derivatives, void *val)
{
- if (name == u_path_ray_length) {
+ if(name == u_path_ray_length) {
/* Ray Length */
float f = sd->ray_length;
return set_attribute_float(f, type, derivatives, val);
}
- else if (name == u_path_ray_depth) {
+ else if(name == u_path_ray_depth) {
/* Ray Depth */
int f = sd->ray_depth;
return set_attribute_int(f, type, derivatives, val);
}
- else if (name == u_path_transparent_depth) {
+ else if(name == u_path_transparent_depth) {
/* Transparent Ray Depth */
int f = sd->transparent_depth;
return set_attribute_int(f, type, derivatives, val);
}
- else if (name == u_ndc) {
+ else if(name == u_ndc) {
/* NDC coordinates with special exception for otho */
OSLThreadData *tdata = kg->osl_tdata;
OSL::ShaderGlobals *globals = &tdata->globals;
@@ -754,7 +763,7 @@ bool OSLRenderServices::get_background_attribute(KernelGlobals *kg, ShaderData *
bool OSLRenderServices::get_attribute(OSL::ShaderGlobals *sg, bool derivatives, ustring object_name,
TypeDesc type, ustring name, void *val)
{
- if (sg->renderstate == NULL)
+ if(sg->renderstate == NULL)
return false;
ShaderData *sd = (ShaderData *)(sg->renderstate);
@@ -769,10 +778,10 @@ bool OSLRenderServices::get_attribute(ShaderData *sd, bool derivatives, ustring
int object;
/* lookup of attribute on another object */
- if (object_name != u_empty) {
+ if(object_name != u_empty) {
OSLGlobals::ObjectNameMap::iterator it = kg->osl->object_name_map.find(object_name);
- if (it == kg->osl->object_name_map.end())
+ if(it == kg->osl->object_name_map.end())
return false;
object = it->second;
@@ -782,7 +791,7 @@ bool OSLRenderServices::get_attribute(ShaderData *sd, bool derivatives, ustring
object = sd->object;
is_curve = (sd->type & PRIMITIVE_ALL_CURVE) != 0;
- if (object == OBJECT_NONE)
+ if(object == OBJECT_NONE)
return get_background_attribute(kg, sd, name, type, derivatives, val);
}
@@ -791,10 +800,10 @@ bool OSLRenderServices::get_attribute(ShaderData *sd, bool derivatives, ustring
OSLGlobals::AttributeMap& attribute_map = kg->osl->attribute_map[object];
OSLGlobals::AttributeMap::iterator it = attribute_map.find(name);
- if (it != attribute_map.end()) {
+ if(it != attribute_map.end()) {
const OSLGlobals::Attribute& attr = it->second;
- if (attr.elem != ATTR_ELEMENT_OBJECT) {
+ if(attr.elem != ATTR_ELEMENT_OBJECT) {
/* triangle and vertex attributes */
if(get_mesh_element_attribute(kg, sd, attr, type, derivatives, val))
return true;
@@ -811,7 +820,7 @@ bool OSLRenderServices::get_attribute(ShaderData *sd, bool derivatives, ustring
/* not found in attribute, check standard object info */
bool is_std_object_attribute = get_object_standard_attribute(kg, sd, name, type, derivatives, val);
- if (is_std_object_attribute)
+ if(is_std_object_attribute)
return true;
return get_background_attribute(kg, sd, name, type, derivatives, val);
@@ -834,7 +843,7 @@ bool OSLRenderServices::has_userdata(ustring name, TypeDesc type, OSL::ShaderGlo
bool OSLRenderServices::texture(ustring filename, TextureOpt &options,
OSL::ShaderGlobals *sg,
float s, float t, float dsdx, float dtdx,
- float dsdy, float dtdy, float *result)
+ float dsdy, float dtdy, int nchannels, float *result)
{
OSL::TextureSystem *ts = osl_ts;
ShaderData *sd = (ShaderData *)(sg->renderstate);
@@ -869,9 +878,9 @@ bool OSLRenderServices::texture(ustring filename, TextureOpt &options,
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);
+ f->eval(result, options.firstchannel, nchannels, faceid, u, v, dudx, dvdx, dudy, dvdy);
- for(int c = r->numChannels(); c < options.nchannels; c++)
+ for(int c = r->numChannels(); c < nchannels; c++)
result[c] = result[0];
return true;
@@ -879,16 +888,16 @@ bool OSLRenderServices::texture(ustring filename, TextureOpt &options,
#endif
bool status;
- if(filename[0] == '@' && filename.find('.') == -1) {
- int slot = atoi(filename.c_str() + 1);
+ if(filename[0] == '@') {
+ int slot = atoi(filename.c_str() + 1);
float4 rgba = kernel_tex_image_interp(slot, s, 1.0f - t);
result[0] = rgba[0];
- if(options.nchannels > 1)
+ if(nchannels > 1)
result[1] = rgba[1];
- if(options.nchannels > 2)
+ if(nchannels > 2)
result[2] = rgba[2];
- if(options.nchannels > 3)
+ if(nchannels > 3)
result[3] = rgba[3];
status = true;
}
@@ -898,17 +907,24 @@ bool OSLRenderServices::texture(ustring filename, TextureOpt &options,
OIIO::TextureSystem::TextureHandle *th = ts->get_texture_handle(filename, thread_info);
+#if OIIO_VERSION < 10500
status = ts->texture(th, thread_info,
- options, s, t, dsdx, dtdx, dsdy, dtdy, result);
+ options, s, t, dsdx, dtdx, dsdy, dtdy,
+ result);
+#else
+ status = ts->texture(th, thread_info,
+ options, s, t, dsdx, dtdx, dsdy, dtdy,
+ nchannels, result);
+#endif
}
if(!status) {
- if(options.nchannels == 3 || options.nchannels == 4) {
+ if(nchannels == 3 || nchannels == 4) {
result[0] = 1.0f;
result[1] = 0.0f;
result[2] = 1.0f;
- if(options.nchannels == 4)
+ if(nchannels == 4)
result[3] = 1.0f;
}
}
@@ -919,26 +935,46 @@ bool OSLRenderServices::texture(ustring filename, TextureOpt &options,
bool OSLRenderServices::texture3d(ustring filename, TextureOpt &options,
OSL::ShaderGlobals *sg, const OSL::Vec3 &P,
const OSL::Vec3 &dPdx, const OSL::Vec3 &dPdy,
- const OSL::Vec3 &dPdz, float *result)
+ const OSL::Vec3 &dPdz, int nchannels, float *result)
{
OSL::TextureSystem *ts = osl_ts;
ShaderData *sd = (ShaderData *)(sg->renderstate);
KernelGlobals *kg = sd->osl_globals;
- OSLThreadData *tdata = kg->osl_tdata;
- OIIO::TextureSystem::Perthread *thread_info = tdata->oiio_thread_info;
-
- OIIO::TextureSystem::TextureHandle *th = ts->get_texture_handle(filename, thread_info);
+ bool status;
+ if(filename[0] == '@') {
+ int slot = atoi(filename.c_str() + 1);
+ float4 rgba = kernel_tex_image_interp_3d(slot, P.x, P.y, P.z);
- bool status = ts->texture3d(th, thread_info,
- options, P, dPdx, dPdy, dPdz, result);
+ result[0] = rgba[0];
+ if(nchannels > 1)
+ result[1] = rgba[1];
+ if(nchannels > 2)
+ result[2] = rgba[2];
+ if(nchannels > 3)
+ result[3] = rgba[3];
+ status = true;
+ }
+ else {
+ OSLThreadData *tdata = kg->osl_tdata;
+ OIIO::TextureSystem::Perthread *thread_info = tdata->oiio_thread_info;
+ OIIO::TextureSystem::TextureHandle *th = ts->get_texture_handle(filename, thread_info);
+#if OIIO_VERSION < 10500
+ status = ts->texture3d(th, thread_info,
+ options, P, dPdx, dPdy, dPdz, result);
+#else
+ status = ts->texture3d(th, thread_info,
+ options, P, dPdx, dPdy, dPdz,
+ nchannels, result);
+#endif
+ }
if(!status) {
- if(options.nchannels == 3 || options.nchannels == 4) {
+ if(nchannels == 3 || nchannels == 4) {
result[0] = 1.0f;
result[1] = 0.0f;
result[2] = 1.0f;
- if(options.nchannels == 4)
+ if(nchannels == 4)
result[3] = 1.0f;
}
@@ -949,7 +985,8 @@ bool OSLRenderServices::texture3d(ustring filename, TextureOpt &options,
bool OSLRenderServices::environment(ustring filename, TextureOpt &options,
OSL::ShaderGlobals *sg, const OSL::Vec3 &R,
- const OSL::Vec3 &dRdx, const OSL::Vec3 &dRdy, float *result)
+ const OSL::Vec3 &dRdx, const OSL::Vec3 &dRdy,
+ int nchannels, float *result)
{
OSL::TextureSystem *ts = osl_ts;
ShaderData *sd = (ShaderData *)(sg->renderstate);
@@ -957,17 +994,24 @@ bool OSLRenderServices::environment(ustring filename, TextureOpt &options,
OSLThreadData *tdata = kg->osl_tdata;
OIIO::TextureSystem::Perthread *thread_info = tdata->oiio_thread_info;
- OIIO::TextureSystem::TextureHandle *th = ts->get_texture_handle(filename, thread_info);
+ OIIO::TextureSystem::TextureHandle *th = ts->get_texture_handle(filename, thread_info);
+
+#if OIIO_VERSION < 10500
bool status = ts->environment(th, thread_info,
options, R, dRdx, dRdy, result);
+#else
+ bool status = ts->environment(th, thread_info,
+ options, R, dRdx, dRdy,
+ nchannels, result);
+#endif
if(!status) {
- if(options.nchannels == 3 || options.nchannels == 4) {
+ if(nchannels == 3 || nchannels == 4) {
result[0] = 1.0f;
result[1] = 0.0f;
result[2] = 1.0f;
- if(options.nchannels == 4)
+ if(nchannels == 4)
result[3] = 1.0f;
}
}
@@ -1018,7 +1062,7 @@ bool OSLRenderServices::trace(TraceOpt &options, OSL::ShaderGlobals *sg,
ray.P = TO_FLOAT3(P);
ray.D = TO_FLOAT3(R);
- ray.t = (options.maxdist == 1.0e30)? FLT_MAX: options.maxdist - options.mindist;
+ ray.t = (options.maxdist == 1.0e30f)? FLT_MAX: options.maxdist - options.mindist;
ray.time = sd->time;
if(options.mindist == 0.0f) {
diff --git a/intern/cycles/kernel/osl/osl_services.h b/intern/cycles/kernel/osl/osl_services.h
index 6f928a0d103..cb6f2311ad8 100644
--- a/intern/cycles/kernel/osl/osl_services.h
+++ b/intern/cycles/kernel/osl/osl_services.h
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#ifndef __OSL_SERVICES_H__
@@ -97,16 +97,64 @@ public:
bool texture(ustring filename, TextureOpt &options,
OSL::ShaderGlobals *sg,
float s, float t, float dsdx, float dtdx,
- float dsdy, float dtdy, float *result);
+ float dsdy, float dtdy, int nchannels, float *result);
bool texture3d(ustring filename, TextureOpt &options,
OSL::ShaderGlobals *sg, const OSL::Vec3 &P,
const OSL::Vec3 &dPdx, const OSL::Vec3 &dPdy,
- const OSL::Vec3 &dPdz, float *result);
+ const OSL::Vec3 &dPdz, int nchannels, float *result);
+
+#if OSL_LIBRARY_VERSION_CODE >= 10700
+ bool texture(ustring filename,
+ TextureHandle * /*texture_handle*/,
+ TexturePerthread * /*texture_thread_info*/,
+ TextureOpt &options,
+ OSL::ShaderGlobals *sg,
+ float s, float t,
+ float dsdx, float dtdx, float dsdy, float dtdy,
+ int nchannels,
+ float *result,
+ float * /*dresultds*/,
+ float * /*dresultdt*/)
+ {
+ return texture(filename,
+ options,
+ sg,
+ s, t,
+ dsdx, dtdx, dsdy, dtdy,
+ nchannels,
+ result);
+ }
+
+ bool texture3d(ustring filename,
+ TextureHandle * /*texture_handle*/,
+ TexturePerthread * /*texture_thread_info*/,
+ TextureOpt &options,
+ OSL::ShaderGlobals *sg,
+ const OSL::Vec3 &P,
+ const OSL::Vec3 &dPdx,
+ const OSL::Vec3 &dPdy,
+ const OSL::Vec3 &dPdz,
+ int nchannels,
+ float *result,
+ float * /*dresultds*/,
+ float * /*dresultdt*/,
+ float * /*dresultdr*/)
+ {
+ return texture3d(filename,
+ options,
+ sg,
+ P,
+ dPdx, dPdy, dPdz,
+ nchannels,
+ result);
+ }
+#endif
bool environment(ustring filename, TextureOpt &options,
OSL::ShaderGlobals *sg, const OSL::Vec3 &R,
- const OSL::Vec3 &dRdx, const OSL::Vec3 &dRdy, float *result);
+ const OSL::Vec3 &dRdx, const OSL::Vec3 &dRdy,
+ int nchannels, float *result);
bool get_texture_info(OSL::ShaderGlobals *sg, ustring filename, int subimage,
ustring dataname, TypeDesc datatype, void *data);
@@ -159,70 +207,37 @@ public:
static ustring u_v;
static ustring u_empty;
-#if OSL_LIBRARY_VERSION_CODE < 10500
- bool get_matrix(OSL::Matrix44 &result, OSL::TransformationPtr xform, float time) {
- return get_matrix(NULL, result, xform, time);
- }
-
- bool get_inverse_matrix(OSL::Matrix44 &result, OSL::TransformationPtr xform, float time) {
- return get_inverse_matrix(NULL, result, xform, time);
- }
-
- bool get_matrix(OSL::Matrix44 &result, ustring from, float time) {
- return get_matrix(NULL, result, from, time);
- }
-
- bool get_inverse_matrix(OSL::Matrix44 &result, ustring to, float time) {
- return get_inverse_matrix(NULL, result, to, time);
- }
-
- bool get_matrix(OSL::Matrix44 &result, OSL::TransformationPtr xform) {
- return get_matrix(NULL, result, xform);
- }
-
- bool get_inverse_matrix(OSL::Matrix44 &result, OSL::TransformationPtr xform) {
- return get_inverse_matrix(NULL, result, xform);
- }
-
- bool get_matrix(OSL::Matrix44 &result, ustring from) {
- return get_matrix(NULL, result, from);
- }
-
- bool get_inverse_matrix(OSL::Matrix44 &result, ustring to) {
- return get_inverse_matrix(NULL, result, to);
- }
+ /* Code to make OSL versions transition smooth. */
- bool get_array_attribute(void *renderstate, bool derivatives,
- ustring object, TypeDesc type, ustring name,
- int index, void *val) {
- OSL::ShaderGlobals sg;
- sg.renderstate = renderstate;
- return get_array_attribute(&sg, derivatives,
- object, type, name,
- index, val);
- }
-
- bool get_attribute(void *renderstate, bool derivatives, ustring object_name,
- TypeDesc type, ustring name, void *val) {
- OSL::ShaderGlobals sg;
- sg.renderstate = renderstate;
- return get_attribute(&sg, derivatives, object_name, type, name, val);
+#if OSL_LIBRARY_VERSION_CODE < 10600
+ inline bool texture(ustring filename, TextureOpt &options,
+ OSL::ShaderGlobals *sg,
+ float s, float t, float dsdx, float dtdx,
+ float dsdy, float dtdy, float *result)
+ {
+ return texture(filename, options, sg, s, t, dsdx, dtdx, dsdy, dtdy,
+ options.nchannels, result);
}
- bool has_userdata(ustring name, TypeDesc type, void *renderstate) {
- return has_userdata(name, type, (OSL::ShaderGlobals *) renderstate);
+ inline bool texture3d(ustring filename, TextureOpt &options,
+ OSL::ShaderGlobals *sg, const OSL::Vec3 &P,
+ const OSL::Vec3 &dPdx, const OSL::Vec3 &dPdy,
+ const OSL::Vec3 &dPdz, float *result)
+ {
+ return texture3d(filename, options, sg, P, dPdx, dPdy, dPdz,
+ options.nchannels, result);
}
- bool get_userdata(bool derivatives, ustring name, TypeDesc type,
- void *renderstate, void *val) {
- return get_userdata(derivatives, name, type, (OSL::ShaderGlobals *) renderstate, val);
- }
-
- bool get_texture_info(ustring filename, int subimage,
- ustring dataname, TypeDesc datatype, void *data) {
- return get_texture_info(NULL, filename, subimage, dataname, datatype, data);
+ inline bool environment(ustring filename, TextureOpt &options,
+ OSL::ShaderGlobals *sg, const OSL::Vec3 &R,
+ const OSL::Vec3 &dRdx, const OSL::Vec3 &dRdy,
+ float *result)
+ {
+ return environment(filename, options, sg, R, dRdx, dRdy,
+ options.nchannels, result);
}
#endif
+
private:
KernelGlobals *kernel_globals;
OSL::TextureSystem *osl_ts;
diff --git a/intern/cycles/kernel/osl/osl_shader.cpp b/intern/cycles/kernel/osl/osl_shader.cpp
index 48498116874..2f234aa25ea 100644
--- a/intern/cycles/kernel/osl/osl_shader.cpp
+++ b/intern/cycles/kernel/osl/osl_shader.cpp
@@ -11,9 +11,11 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
+#include <OSL/oslexec.h>
+
#include "kernel_compat_cpu.h"
#include "kernel_montecarlo.h"
#include "kernel_types.h"
@@ -34,7 +36,6 @@
#include "attribute.h"
-#include <OSL/oslexec.h>
CCL_NAMESPACE_BEGIN
@@ -145,162 +146,175 @@ static void flatten_surface_closure_tree(ShaderData *sd, int path_flag,
/* OSL gives us a closure tree, we flatten it into arrays per
* closure type, for evaluation, sampling, etc later on. */
- if (closure->type == OSL::ClosureColor::COMPONENT) {
- OSL::ClosureComponent *comp = (OSL::ClosureComponent *)closure;
- CClosurePrimitive *prim = (CClosurePrimitive *)comp->data();
+#if OSL_LIBRARY_VERSION_CODE < 10700
+ switch(closure->type) {
+#else
+ switch(closure->id) {
+#endif
+ case OSL::ClosureColor::MUL: {
+ OSL::ClosureMul *mul = (OSL::ClosureMul *)closure;
+ flatten_surface_closure_tree(sd, path_flag, mul->closure, TO_FLOAT3(mul->weight) * weight);
+ break;
+ }
+ case OSL::ClosureColor::ADD: {
+ OSL::ClosureAdd *add = (OSL::ClosureAdd *)closure;
+ flatten_surface_closure_tree(sd, path_flag, add->closureA, weight);
+ flatten_surface_closure_tree(sd, path_flag, add->closureB, weight);
+ break;
+ }
+ default: {
+ OSL::ClosureComponent *comp = (OSL::ClosureComponent *)closure;
+ CClosurePrimitive *prim = (CClosurePrimitive *)comp->data();
- if (prim) {
- ShaderClosure sc;
+ if(prim) {
+ ShaderClosure sc;
#ifdef OSL_SUPPORTS_WEIGHTED_CLOSURE_COMPONENTS
- weight = weight*TO_FLOAT3(comp->w);
+ weight = weight*TO_FLOAT3(comp->w);
#endif
- sc.weight = weight;
+ sc.weight = weight;
- prim->setup();
+ prim->setup();
- switch (prim->category) {
- case CClosurePrimitive::BSDF: {
- CBSDFClosure *bsdf = (CBSDFClosure *)prim;
- int scattering = bsdf->scattering();
+ switch(prim->category) {
+ case CClosurePrimitive::BSDF: {
+ CBSDFClosure *bsdf = (CBSDFClosure *)prim;
+ int scattering = bsdf->scattering();
- /* caustic options */
- if((scattering & LABEL_GLOSSY) && (path_flag & PATH_RAY_DIFFUSE)) {
- KernelGlobals *kg = sd->osl_globals;
+ /* caustic options */
+ if((scattering & LABEL_GLOSSY) && (path_flag & PATH_RAY_DIFFUSE)) {
+ KernelGlobals *kg = sd->osl_globals;
- if((!kernel_data.integrator.caustics_reflective && (scattering & LABEL_REFLECT)) ||
- (!kernel_data.integrator.caustics_refractive && (scattering & LABEL_TRANSMIT))) {
- return;
+ if((!kernel_data.integrator.caustics_reflective && (scattering & LABEL_REFLECT)) ||
+ (!kernel_data.integrator.caustics_refractive && (scattering & LABEL_TRANSMIT)))
+ {
+ return;
+ }
}
- }
- /* sample weight */
- float sample_weight = fabsf(average(weight));
+ /* sample weight */
+ float sample_weight = fabsf(average(weight));
- sc.sample_weight = sample_weight;
+ sc.sample_weight = sample_weight;
- sc.type = bsdf->sc.type;
- sc.N = bsdf->sc.N;
- sc.T = bsdf->sc.T;
- sc.data0 = bsdf->sc.data0;
- sc.data1 = bsdf->sc.data1;
- sc.data2 = bsdf->sc.data2;
- sc.prim = bsdf->sc.prim;
+ sc.type = bsdf->sc.type;
+ sc.N = bsdf->sc.N;
+ sc.T = bsdf->sc.T;
+ sc.data0 = bsdf->sc.data0;
+ sc.data1 = bsdf->sc.data1;
+ sc.data2 = bsdf->sc.data2;
+ sc.prim = bsdf->sc.prim;
- /* add */
- if(sc.sample_weight > CLOSURE_WEIGHT_CUTOFF && sd->num_closure < MAX_CLOSURE) {
- sd->closure[sd->num_closure++] = sc;
- sd->flag |= bsdf->shaderdata_flag();
- }
- break;
- }
- case CClosurePrimitive::Emissive: {
- /* sample weight */
- float sample_weight = fabsf(average(weight));
-
- sc.sample_weight = sample_weight;
- sc.type = CLOSURE_EMISSION_ID;
- sc.data0 = 0.0f;
- sc.data1 = 0.0f;
- sc.data2 = 0.0f;
- sc.prim = NULL;
-
- /* flag */
- if(sd->num_closure < MAX_CLOSURE) {
- sd->closure[sd->num_closure++] = sc;
- sd->flag |= SD_EMISSION;
- }
- break;
- }
- case CClosurePrimitive::AmbientOcclusion: {
- /* sample weight */
- float sample_weight = fabsf(average(weight));
-
- sc.sample_weight = sample_weight;
- sc.type = CLOSURE_AMBIENT_OCCLUSION_ID;
- sc.data0 = 0.0f;
- sc.data1 = 0.0f;
- sc.data2 = 0.0f;
- sc.prim = NULL;
-
- if(sd->num_closure < MAX_CLOSURE) {
- sd->closure[sd->num_closure++] = sc;
- sd->flag |= SD_AO;
- }
- break;
- }
- case CClosurePrimitive::Holdout: {
- sc.sample_weight = 0.0f;
- sc.type = CLOSURE_HOLDOUT_ID;
- sc.data0 = 0.0f;
- sc.data1 = 0.0f;
- sc.data2 = 0.0f;
- sc.prim = NULL;
-
- if(sd->num_closure < MAX_CLOSURE) {
- sd->closure[sd->num_closure++] = sc;
- sd->flag |= SD_HOLDOUT;
+ /* add */
+ if(sc.sample_weight > CLOSURE_WEIGHT_CUTOFF && sd->num_closure < MAX_CLOSURE) {
+ sd->closure[sd->num_closure++] = sc;
+ sd->flag |= bsdf->shaderdata_flag();
+ }
+ break;
}
- break;
- }
- case CClosurePrimitive::BSSRDF: {
- CBSSRDFClosure *bssrdf = (CBSSRDFClosure *)prim;
- float sample_weight = fabsf(average(weight));
+ case CClosurePrimitive::Emissive: {
+ /* sample weight */
+ float sample_weight = fabsf(average(weight));
- if(sample_weight > CLOSURE_WEIGHT_CUTOFF && sd->num_closure+2 < MAX_CLOSURE) {
sc.sample_weight = sample_weight;
-
- sc.type = bssrdf->sc.type;
- sc.N = bssrdf->sc.N;
- sc.data1 = bssrdf->sc.data1;
- sc.T.x = bssrdf->sc.T.x;
+ sc.type = CLOSURE_EMISSION_ID;
+ sc.data0 = 0.0f;
+ sc.data1 = 0.0f;
+ sc.data2 = 0.0f;
sc.prim = NULL;
- /* disable in case of diffuse ancestor, can't see it well then and
- * adds considerably noise due to probabilities of continuing path
- * getting lower and lower */
- if(path_flag & PATH_RAY_DIFFUSE_ANCESTOR)
- bssrdf->radius = make_float3(0.0f, 0.0f, 0.0f);
-
- /* create one closure for each color channel */
- if(fabsf(weight.x) > 0.0f) {
- sc.weight = make_float3(weight.x, 0.0f, 0.0f);
- sc.data0 = bssrdf->radius.x;
- sd->flag |= bssrdf_setup(&sc, sc.type);
+ /* flag */
+ if(sd->num_closure < MAX_CLOSURE) {
sd->closure[sd->num_closure++] = sc;
+ sd->flag |= SD_EMISSION;
}
+ break;
+ }
+ case CClosurePrimitive::AmbientOcclusion: {
+ /* sample weight */
+ float sample_weight = fabsf(average(weight));
+
+ sc.sample_weight = sample_weight;
+ sc.type = CLOSURE_AMBIENT_OCCLUSION_ID;
+ sc.data0 = 0.0f;
+ sc.data1 = 0.0f;
+ sc.data2 = 0.0f;
+ sc.prim = NULL;
- if(fabsf(weight.y) > 0.0f) {
- sc.weight = make_float3(0.0f, weight.y, 0.0f);
- sc.data0 = bssrdf->radius.y;
- sd->flag |= bssrdf_setup(&sc, sc.type);
+ if(sd->num_closure < MAX_CLOSURE) {
sd->closure[sd->num_closure++] = sc;
+ sd->flag |= SD_AO;
}
+ break;
+ }
+ case CClosurePrimitive::Holdout: {
+ sc.sample_weight = 0.0f;
+ sc.type = CLOSURE_HOLDOUT_ID;
+ sc.data0 = 0.0f;
+ sc.data1 = 0.0f;
+ sc.data2 = 0.0f;
+ sc.prim = NULL;
- if(fabsf(weight.z) > 0.0f) {
- sc.weight = make_float3(0.0f, 0.0f, weight.z);
- sc.data0 = bssrdf->radius.z;
- sd->flag |= bssrdf_setup(&sc, sc.type);
+ if(sd->num_closure < MAX_CLOSURE) {
sd->closure[sd->num_closure++] = sc;
+ sd->flag |= SD_HOLDOUT;
+ }
+ break;
+ }
+ case CClosurePrimitive::BSSRDF: {
+ CBSSRDFClosure *bssrdf = (CBSSRDFClosure *)prim;
+ float sample_weight = fabsf(average(weight));
+
+ if(sample_weight > CLOSURE_WEIGHT_CUTOFF && sd->num_closure+2 < MAX_CLOSURE) {
+ sc.sample_weight = sample_weight;
+
+ sc.type = bssrdf->sc.type;
+ sc.N = bssrdf->sc.N;
+ sc.data1 = bssrdf->sc.data1;
+ sc.T.x = bssrdf->sc.T.x;
+ sc.prim = NULL;
+
+ /* disable in case of diffuse ancestor, can't see it well then and
+ * adds considerably noise due to probabilities of continuing path
+ * getting lower and lower */
+ if(path_flag & PATH_RAY_DIFFUSE_ANCESTOR)
+ bssrdf->radius = make_float3(0.0f, 0.0f, 0.0f);
+
+ /* create one closure for each color channel */
+ if(fabsf(weight.x) > 0.0f) {
+ sc.weight = make_float3(weight.x, 0.0f, 0.0f);
+ sc.data0 = bssrdf->radius.x;
+ sc.data1 = 0.0f;
+ sd->flag |= bssrdf_setup(&sc, sc.type);
+ sd->closure[sd->num_closure++] = sc;
+ }
+
+ if(fabsf(weight.y) > 0.0f) {
+ sc.weight = make_float3(0.0f, weight.y, 0.0f);
+ sc.data0 = bssrdf->radius.y;
+ sc.data1 = 0.0f;
+ sd->flag |= bssrdf_setup(&sc, sc.type);
+ sd->closure[sd->num_closure++] = sc;
+ }
+
+ if(fabsf(weight.z) > 0.0f) {
+ sc.weight = make_float3(0.0f, 0.0f, weight.z);
+ sc.data0 = bssrdf->radius.z;
+ sc.data1 = 0.0f;
+ sd->flag |= bssrdf_setup(&sc, sc.type);
+ sd->closure[sd->num_closure++] = sc;
+ }
}
+ break;
}
- break;
+ case CClosurePrimitive::Background:
+ case CClosurePrimitive::Volume:
+ break; /* not relevant */
}
- case CClosurePrimitive::Background:
- case CClosurePrimitive::Volume:
- break; /* not relevant */
}
+ break;
}
}
- else if (closure->type == OSL::ClosureColor::MUL) {
- OSL::ClosureMul *mul = (OSL::ClosureMul *)closure;
- flatten_surface_closure_tree(sd, path_flag, mul->closure, TO_FLOAT3(mul->weight) * weight);
- }
- else if (closure->type == OSL::ClosureColor::ADD) {
- OSL::ClosureAdd *add = (OSL::ClosureAdd *)closure;
- flatten_surface_closure_tree(sd, path_flag, add->closureA, weight);
- flatten_surface_closure_tree(sd, path_flag, add->closureB, weight);
- }
}
void OSLShader::eval_surface(KernelGlobals *kg, ShaderData *sd, int path_flag, ShaderContext ctx)
@@ -315,11 +329,11 @@ void OSLShader::eval_surface(KernelGlobals *kg, ShaderData *sd, int path_flag, S
OSL::ShadingContext *octx = tdata->context[(int)ctx];
int shader = sd->shader & SHADER_MASK;
- if (kg->osl->surface_state[shader])
+ if(kg->osl->surface_state[shader])
ss->execute(*octx, *(kg->osl->surface_state[shader]), *globals);
/* flatten closure tree */
- if (globals->Ci)
+ if(globals->Ci)
flatten_surface_closure_tree(sd, path_flag, globals->Ci);
}
@@ -331,27 +345,33 @@ static float3 flatten_background_closure_tree(const OSL::ClosureColor *closure)
* is only one supported closure type at the moment, which has no evaluation
* functions, so we just sum the weights */
- if (closure->type == OSL::ClosureColor::COMPONENT) {
- OSL::ClosureComponent *comp = (OSL::ClosureComponent *)closure;
- CClosurePrimitive *prim = (CClosurePrimitive *)comp->data();
-
- if (prim && prim->category == CClosurePrimitive::Background)
-#ifdef OSL_SUPPORTS_WEIGHTED_CLOSURE_COMPONENTS
- return TO_FLOAT3(comp->w);
+#if OSL_LIBRARY_VERSION_CODE < 10700
+ switch(closure->type) {
#else
- return make_float3(1.0f, 1.0f, 1.0f);
+ switch(closure->id) {
#endif
- }
- else if (closure->type == OSL::ClosureColor::MUL) {
- OSL::ClosureMul *mul = (OSL::ClosureMul *)closure;
+ case OSL::ClosureColor::MUL: {
+ OSL::ClosureMul *mul = (OSL::ClosureMul *)closure;
- return TO_FLOAT3(mul->weight) * flatten_background_closure_tree(mul->closure);
- }
- else if (closure->type == OSL::ClosureColor::ADD) {
- OSL::ClosureAdd *add = (OSL::ClosureAdd *)closure;
+ return TO_FLOAT3(mul->weight) * flatten_background_closure_tree(mul->closure);
+ }
+ case OSL::ClosureColor::ADD: {
+ OSL::ClosureAdd *add = (OSL::ClosureAdd *)closure;
- return flatten_background_closure_tree(add->closureA) +
- flatten_background_closure_tree(add->closureB);
+ return flatten_background_closure_tree(add->closureA) +
+ flatten_background_closure_tree(add->closureB);
+ }
+ default: {
+ OSL::ClosureComponent *comp = (OSL::ClosureComponent *)closure;
+ CClosurePrimitive *prim = (CClosurePrimitive *)comp->data();
+
+ if(prim && prim->category == CClosurePrimitive::Background)
+#ifdef OSL_SUPPORTS_WEIGHTED_CLOSURE_COMPONENTS
+ return TO_FLOAT3(comp->w);
+#else
+ return make_float3(1.0f, 1.0f, 1.0f);
+#endif
+ }
}
return make_float3(0.0f, 0.0f, 0.0f);
@@ -368,11 +388,11 @@ float3 OSLShader::eval_background(KernelGlobals *kg, ShaderData *sd, int path_fl
OSL::ShaderGlobals *globals = &tdata->globals;
OSL::ShadingContext *octx = tdata->context[(int)ctx];
- if (kg->osl->background_state)
+ if(kg->osl->background_state)
ss->execute(*octx, *(kg->osl->background_state), *globals);
/* return background color immediately */
- if (globals->Ci)
+ if(globals->Ci)
return flatten_background_closure_tree(globals->Ci);
return make_float3(0.0f, 0.0f, 0.0f);
@@ -386,76 +406,84 @@ static void flatten_volume_closure_tree(ShaderData *sd,
/* OSL gives us a closure tree, we flatten it into arrays per
* closure type, for evaluation, sampling, etc later on. */
- if (closure->type == OSL::ClosureColor::COMPONENT) {
- OSL::ClosureComponent *comp = (OSL::ClosureComponent *)closure;
- CClosurePrimitive *prim = (CClosurePrimitive *)comp->data();
+#if OSL_LIBRARY_VERSION_CODE < 10700
+ switch(closure->type) {
+#else
+ switch(closure->id) {
+#endif
+ case OSL::ClosureColor::MUL: {
+ OSL::ClosureMul *mul = (OSL::ClosureMul *)closure;
+ flatten_volume_closure_tree(sd, mul->closure, TO_FLOAT3(mul->weight) * weight);
+ break;
+ }
+ case OSL::ClosureColor::ADD: {
+ OSL::ClosureAdd *add = (OSL::ClosureAdd *)closure;
+ flatten_volume_closure_tree(sd, add->closureA, weight);
+ flatten_volume_closure_tree(sd, add->closureB, weight);
+ break;
+ }
+ default: {
+ OSL::ClosureComponent *comp = (OSL::ClosureComponent *)closure;
+ CClosurePrimitive *prim = (CClosurePrimitive *)comp->data();
- if (prim) {
- ShaderClosure sc;
+ if(prim) {
+ ShaderClosure sc;
#ifdef OSL_SUPPORTS_WEIGHTED_CLOSURE_COMPONENTS
- weight = weight*TO_FLOAT3(comp->w);
+ weight = weight*TO_FLOAT3(comp->w);
#endif
- sc.weight = weight;
-
- prim->setup();
-
- switch (prim->category) {
- case CClosurePrimitive::Volume: {
- CVolumeClosure *volume = (CVolumeClosure *)prim;
- /* sample weight */
- float sample_weight = fabsf(average(weight));
-
- sc.sample_weight = sample_weight;
- sc.type = volume->sc.type;
- sc.data0 = volume->sc.data0;
- sc.data1 = volume->sc.data1;
-
- /* add */
- if((sc.sample_weight > CLOSURE_WEIGHT_CUTOFF) &&
- (sd->num_closure < MAX_CLOSURE))
- {
- sd->closure[sd->num_closure++] = sc;
- sd->flag |= volume->shaderdata_flag();
+ sc.weight = weight;
+
+ prim->setup();
+
+ switch(prim->category) {
+ case CClosurePrimitive::Volume: {
+ CVolumeClosure *volume = (CVolumeClosure *)prim;
+ /* sample weight */
+ float sample_weight = fabsf(average(weight));
+
+ sc.sample_weight = sample_weight;
+ sc.type = volume->sc.type;
+ sc.data0 = volume->sc.data0;
+ sc.data1 = volume->sc.data1;
+
+ /* add */
+ if((sc.sample_weight > CLOSURE_WEIGHT_CUTOFF) &&
+ (sd->num_closure < MAX_CLOSURE))
+ {
+ sd->closure[sd->num_closure++] = sc;
+ sd->flag |= volume->shaderdata_flag();
+ }
+ break;
}
- break;
- }
- case CClosurePrimitive::Emissive: {
- /* sample weight */
- float sample_weight = fabsf(average(weight));
-
- sc.sample_weight = sample_weight;
- sc.type = CLOSURE_EMISSION_ID;
- sc.data0 = 0.0f;
- sc.data1 = 0.0f;
- sc.prim = NULL;
-
- /* flag */
- if(sd->num_closure < MAX_CLOSURE) {
- sd->closure[sd->num_closure++] = sc;
- sd->flag |= SD_EMISSION;
+ case CClosurePrimitive::Emissive: {
+ /* sample weight */
+ float sample_weight = fabsf(average(weight));
+
+ sc.sample_weight = sample_weight;
+ sc.type = CLOSURE_EMISSION_ID;
+ sc.data0 = 0.0f;
+ sc.data1 = 0.0f;
+ sc.prim = NULL;
+
+ /* flag */
+ if(sd->num_closure < MAX_CLOSURE) {
+ sd->closure[sd->num_closure++] = sc;
+ sd->flag |= SD_EMISSION;
+ }
+ break;
}
- break;
+ case CClosurePrimitive::Holdout:
+ break; /* not implemented */
+ case CClosurePrimitive::Background:
+ case CClosurePrimitive::BSDF:
+ case CClosurePrimitive::BSSRDF:
+ case CClosurePrimitive::AmbientOcclusion:
+ break; /* not relevant */
}
- case CClosurePrimitive::Holdout:
- break; /* not implemented */
- case CClosurePrimitive::Background:
- case CClosurePrimitive::BSDF:
- case CClosurePrimitive::BSSRDF:
- case CClosurePrimitive::AmbientOcclusion:
- break; /* not relevant */
}
}
}
- else if (closure->type == OSL::ClosureColor::MUL) {
- OSL::ClosureMul *mul = (OSL::ClosureMul *)closure;
- flatten_volume_closure_tree(sd, mul->closure, TO_FLOAT3(mul->weight) * weight);
- }
- else if (closure->type == OSL::ClosureColor::ADD) {
- OSL::ClosureAdd *add = (OSL::ClosureAdd *)closure;
- flatten_volume_closure_tree(sd, add->closureA, weight);
- flatten_volume_closure_tree(sd, add->closureB, weight);
- }
}
void OSLShader::eval_volume(KernelGlobals *kg, ShaderData *sd, int path_flag, ShaderContext ctx)
@@ -470,11 +498,11 @@ void OSLShader::eval_volume(KernelGlobals *kg, ShaderData *sd, int path_flag, Sh
OSL::ShadingContext *octx = tdata->context[(int)ctx];
int shader = sd->shader & SHADER_MASK;
- if (kg->osl->volume_state[shader])
+ if(kg->osl->volume_state[shader])
ss->execute(*octx, *(kg->osl->volume_state[shader]), *globals);
/* flatten closure tree */
- if (globals->Ci)
+ if(globals->Ci)
flatten_volume_closure_tree(sd, globals->Ci);
}
@@ -492,7 +520,7 @@ void OSLShader::eval_displacement(KernelGlobals *kg, ShaderData *sd, ShaderConte
OSL::ShadingContext *octx = tdata->context[(int)ctx];
int shader = sd->shader & SHADER_MASK;
- if (kg->osl->displacement_state[shader])
+ if(kg->osl->displacement_state[shader])
ss->execute(*octx, *(kg->osl->displacement_state[shader]), *globals);
/* get back position */
@@ -519,7 +547,7 @@ float3 OSLShader::bsdf_eval(const ShaderData *sd, const ShaderClosure *sc, const
CBSDFClosure *bsdf = (CBSDFClosure *)sc->prim;
float3 bsdf_eval;
- if (dot(sd->Ng, omega_in) >= 0.0f)
+ if(dot(sd->Ng, omega_in) >= 0.0f)
bsdf_eval = bsdf->eval_reflect(sd->I, omega_in, pdf);
else
bsdf_eval = bsdf->eval_transmit(sd->I, omega_in, pdf);
@@ -547,7 +575,7 @@ int OSLShader::find_attribute(KernelGlobals *kg, const ShaderData *sd, uint id,
ustring stdname(std::string("geom:") + std::string(Attribute::standard_name((AttributeStandard)id)));
OSLGlobals::AttributeMap::const_iterator it = attr_map.find(stdname);
- if (it != attr_map.end()) {
+ if(it != attr_map.end()) {
const OSLGlobals::Attribute &osl_attr = it->second;
*elem = osl_attr.elem;
diff --git a/intern/cycles/kernel/osl/osl_shader.h b/intern/cycles/kernel/osl/osl_shader.h
index 40f50d8b0e9..15dd74f9d38 100644
--- a/intern/cycles/kernel/osl/osl_shader.h
+++ b/intern/cycles/kernel/osl/osl_shader.h
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#ifndef __OSL_SHADER_H__
diff --git a/intern/cycles/kernel/shaders/CMakeLists.txt b/intern/cycles/kernel/shaders/CMakeLists.txt
index 0b735ede701..81931463cad 100644
--- a/intern/cycles/kernel/shaders/CMakeLists.txt
+++ b/intern/cycles/kernel/shaders/CMakeLists.txt
@@ -74,6 +74,7 @@ set(SRC_OSL
node_vector_transform.osl
node_velvet_bsdf.osl
node_voronoi_texture.osl
+ node_voxel_texture.osl
node_wavelength.osl
node_blackbody.osl
node_wave_texture.osl
diff --git a/intern/cycles/kernel/shaders/node_absorption_volume.osl b/intern/cycles/kernel/shaders/node_absorption_volume.osl
index 6bac83ba4f5..18f662ebbbd 100644
--- a/intern/cycles/kernel/shaders/node_absorption_volume.osl
+++ b/intern/cycles/kernel/shaders/node_absorption_volume.osl
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#include "stdosl.h"
diff --git a/intern/cycles/kernel/shaders/node_add_closure.osl b/intern/cycles/kernel/shaders/node_add_closure.osl
index b826fb22784..b6596e0b6bd 100644
--- a/intern/cycles/kernel/shaders/node_add_closure.osl
+++ b/intern/cycles/kernel/shaders/node_add_closure.osl
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#include "stdosl.h"
diff --git a/intern/cycles/kernel/shaders/node_ambient_occlusion.osl b/intern/cycles/kernel/shaders/node_ambient_occlusion.osl
index 961aed1016b..5f056122bbe 100644
--- a/intern/cycles/kernel/shaders/node_ambient_occlusion.osl
+++ b/intern/cycles/kernel/shaders/node_ambient_occlusion.osl
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#include "stdosl.h"
diff --git a/intern/cycles/kernel/shaders/node_anisotropic_bsdf.osl b/intern/cycles/kernel/shaders/node_anisotropic_bsdf.osl
index da1e4f77107..281ed4e8726 100644
--- a/intern/cycles/kernel/shaders/node_anisotropic_bsdf.osl
+++ b/intern/cycles/kernel/shaders/node_anisotropic_bsdf.osl
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#include "stdosl.h"
diff --git a/intern/cycles/kernel/shaders/node_attribute.osl b/intern/cycles/kernel/shaders/node_attribute.osl
index 43f69fab053..67183e9ffe0 100644
--- a/intern/cycles/kernel/shaders/node_attribute.osl
+++ b/intern/cycles/kernel/shaders/node_attribute.osl
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#include "stdosl.h"
diff --git a/intern/cycles/kernel/shaders/node_background.osl b/intern/cycles/kernel/shaders/node_background.osl
index c4379a8f71b..613d4e360fa 100644
--- a/intern/cycles/kernel/shaders/node_background.osl
+++ b/intern/cycles/kernel/shaders/node_background.osl
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#include "stdosl.h"
diff --git a/intern/cycles/kernel/shaders/node_blackbody.osl b/intern/cycles/kernel/shaders/node_blackbody.osl
index d26e56ab06d..1da6894d0f0 100644
--- a/intern/cycles/kernel/shaders/node_blackbody.osl
+++ b/intern/cycles/kernel/shaders/node_blackbody.osl
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#include "stdosl.h"
diff --git a/intern/cycles/kernel/shaders/node_brick_texture.osl b/intern/cycles/kernel/shaders/node_brick_texture.osl
index 70a6a6ea7ce..35e01178ba8 100644
--- a/intern/cycles/kernel/shaders/node_brick_texture.osl
+++ b/intern/cycles/kernel/shaders/node_brick_texture.osl
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#include "stdosl.h"
@@ -22,6 +22,7 @@
float brick_noise(int n) /* fast integer noise */
{
int nn;
+ n = (n + 1013) & 2147483647;
n = (n >> 13) ^ n;
nn = (n * (n * n * 60493 + 19990303) + 1376312589) & 2147483647;
return 0.5 * ((float)nn / 1073741824.0);
@@ -87,12 +88,9 @@ shader node_brick_texture(
if (Fac != 1.0) {
float facm = 1.0 - tint;
-
- Col[0] = facm * (Color1[0]) + tint * Color2[0];
- Col[1] = facm * (Color1[1]) + tint * Color2[1];
- Col[2] = facm * (Color1[2]) + tint * Color2[2];
+ Col = facm * Color1 + tint * Color2;
}
- Color = (Fac == 1.0) ? Mortar: Col;
+ Color = (Fac == 1.0) ? Mortar : Col;
}
diff --git a/intern/cycles/kernel/shaders/node_brightness.osl b/intern/cycles/kernel/shaders/node_brightness.osl
index 468b0f052c3..00cfb167885 100644
--- a/intern/cycles/kernel/shaders/node_brightness.osl
+++ b/intern/cycles/kernel/shaders/node_brightness.osl
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#include "stdosl.h"
diff --git a/intern/cycles/kernel/shaders/node_bump.osl b/intern/cycles/kernel/shaders/node_bump.osl
index bbc08760cd5..9882857f2ec 100644
--- a/intern/cycles/kernel/shaders/node_bump.osl
+++ b/intern/cycles/kernel/shaders/node_bump.osl
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#include "stdosl.h"
diff --git a/intern/cycles/kernel/shaders/node_camera.osl b/intern/cycles/kernel/shaders/node_camera.osl
index 20ebb7dc095..5e90cb8b8ee 100644
--- a/intern/cycles/kernel/shaders/node_camera.osl
+++ b/intern/cycles/kernel/shaders/node_camera.osl
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#include "stdosl.h"
diff --git a/intern/cycles/kernel/shaders/node_checker_texture.osl b/intern/cycles/kernel/shaders/node_checker_texture.osl
index a6d21fd36f3..ae84c71dd42 100644
--- a/intern/cycles/kernel/shaders/node_checker_texture.osl
+++ b/intern/cycles/kernel/shaders/node_checker_texture.osl
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#include "stdosl.h"
diff --git a/intern/cycles/kernel/shaders/node_color.h b/intern/cycles/kernel/shaders/node_color.h
index 095e628f20c..4a17286a07f 100644
--- a/intern/cycles/kernel/shaders/node_color.h
+++ b/intern/cycles/kernel/shaders/node_color.h
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
float color_srgb_to_scene_linear(float c)
diff --git a/intern/cycles/kernel/shaders/node_combine_hsv.osl b/intern/cycles/kernel/shaders/node_combine_hsv.osl
index 010773acc5c..6b922bf4e6b 100644
--- a/intern/cycles/kernel/shaders/node_combine_hsv.osl
+++ b/intern/cycles/kernel/shaders/node_combine_hsv.osl
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#include "stdosl.h"
diff --git a/intern/cycles/kernel/shaders/node_combine_rgb.osl b/intern/cycles/kernel/shaders/node_combine_rgb.osl
index 8466a89b536..f343fdefd84 100644
--- a/intern/cycles/kernel/shaders/node_combine_rgb.osl
+++ b/intern/cycles/kernel/shaders/node_combine_rgb.osl
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#include "stdosl.h"
diff --git a/intern/cycles/kernel/shaders/node_combine_xyz.osl b/intern/cycles/kernel/shaders/node_combine_xyz.osl
index 933dee5bd78..86182056b09 100644
--- a/intern/cycles/kernel/shaders/node_combine_xyz.osl
+++ b/intern/cycles/kernel/shaders/node_combine_xyz.osl
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#include "stdosl.h"
diff --git a/intern/cycles/kernel/shaders/node_convert_from_color.osl b/intern/cycles/kernel/shaders/node_convert_from_color.osl
index 2f4503e66e3..44074317f42 100644
--- a/intern/cycles/kernel/shaders/node_convert_from_color.osl
+++ b/intern/cycles/kernel/shaders/node_convert_from_color.osl
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#include "stdosl.h"
diff --git a/intern/cycles/kernel/shaders/node_convert_from_float.osl b/intern/cycles/kernel/shaders/node_convert_from_float.osl
index f5b91903078..fc5c79c4c64 100644
--- a/intern/cycles/kernel/shaders/node_convert_from_float.osl
+++ b/intern/cycles/kernel/shaders/node_convert_from_float.osl
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#include "stdosl.h"
diff --git a/intern/cycles/kernel/shaders/node_convert_from_int.osl b/intern/cycles/kernel/shaders/node_convert_from_int.osl
index 110922a5df1..3c3785ebc0d 100644
--- a/intern/cycles/kernel/shaders/node_convert_from_int.osl
+++ b/intern/cycles/kernel/shaders/node_convert_from_int.osl
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#include "stdosl.h"
diff --git a/intern/cycles/kernel/shaders/node_convert_from_normal.osl b/intern/cycles/kernel/shaders/node_convert_from_normal.osl
index 995c86d8828..8ecc56ac8ce 100644
--- a/intern/cycles/kernel/shaders/node_convert_from_normal.osl
+++ b/intern/cycles/kernel/shaders/node_convert_from_normal.osl
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#include "stdosl.h"
diff --git a/intern/cycles/kernel/shaders/node_convert_from_point.osl b/intern/cycles/kernel/shaders/node_convert_from_point.osl
index 2ed151273a8..e5913b7a1e4 100644
--- a/intern/cycles/kernel/shaders/node_convert_from_point.osl
+++ b/intern/cycles/kernel/shaders/node_convert_from_point.osl
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#include "stdosl.h"
diff --git a/intern/cycles/kernel/shaders/node_convert_from_string.osl b/intern/cycles/kernel/shaders/node_convert_from_string.osl
index 50cce252be4..0466734277b 100644
--- a/intern/cycles/kernel/shaders/node_convert_from_string.osl
+++ b/intern/cycles/kernel/shaders/node_convert_from_string.osl
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#include "stdosl.h"
diff --git a/intern/cycles/kernel/shaders/node_convert_from_vector.osl b/intern/cycles/kernel/shaders/node_convert_from_vector.osl
index 035c46625a0..79c5cb04550 100644
--- a/intern/cycles/kernel/shaders/node_convert_from_vector.osl
+++ b/intern/cycles/kernel/shaders/node_convert_from_vector.osl
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#include "stdosl.h"
diff --git a/intern/cycles/kernel/shaders/node_diffuse_bsdf.osl b/intern/cycles/kernel/shaders/node_diffuse_bsdf.osl
index e8c94660e4f..2bef2d65baa 100644
--- a/intern/cycles/kernel/shaders/node_diffuse_bsdf.osl
+++ b/intern/cycles/kernel/shaders/node_diffuse_bsdf.osl
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#include "stdosl.h"
diff --git a/intern/cycles/kernel/shaders/node_emission.osl b/intern/cycles/kernel/shaders/node_emission.osl
index b28d731c19f..c36e2a4c0f3 100644
--- a/intern/cycles/kernel/shaders/node_emission.osl
+++ b/intern/cycles/kernel/shaders/node_emission.osl
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#include "stdosl.h"
diff --git a/intern/cycles/kernel/shaders/node_environment_texture.osl b/intern/cycles/kernel/shaders/node_environment_texture.osl
index 136ccdf8b18..14f0226a0e5 100644
--- a/intern/cycles/kernel/shaders/node_environment_texture.osl
+++ b/intern/cycles/kernel/shaders/node_environment_texture.osl
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#include "stdosl.h"
diff --git a/intern/cycles/kernel/shaders/node_fresnel.h b/intern/cycles/kernel/shaders/node_fresnel.h
index 9f10ba8023e..de2d40a849c 100644
--- a/intern/cycles/kernel/shaders/node_fresnel.h
+++ b/intern/cycles/kernel/shaders/node_fresnel.h
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
float fresnel_dielectric_cos(float cosi, float eta)
@@ -36,14 +36,14 @@ float fresnel_dielectric_cos(float cosi, float eta)
color fresnel_conductor(float cosi, color eta, color k)
{
- color cosi2 = color(cosi*cosi);
+ color cosi2 = color(cosi * cosi);
color one = color(1, 1, 1);
color tmp_f = eta * eta + k * k;
color tmp = tmp_f * cosi2;
color Rparl2 = (tmp - (2.0 * eta * cosi) + one) /
- (tmp + (2.0 * eta * cosi) + one);
+ (tmp + (2.0 * eta * cosi) + one);
color Rperp2 = (tmp_f - (2.0 * eta * cosi) + cosi2) /
- (tmp_f + (2.0 * eta * cosi) + cosi2);
+ (tmp_f + (2.0 * eta * cosi) + cosi2);
return (Rparl2 + Rperp2) * 0.5;
}
diff --git a/intern/cycles/kernel/shaders/node_fresnel.osl b/intern/cycles/kernel/shaders/node_fresnel.osl
index 7ef553c0f39..8bec7b432f5 100644
--- a/intern/cycles/kernel/shaders/node_fresnel.osl
+++ b/intern/cycles/kernel/shaders/node_fresnel.osl
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#include "stdosl.h"
diff --git a/intern/cycles/kernel/shaders/node_gamma.osl b/intern/cycles/kernel/shaders/node_gamma.osl
index a2ad3f766fe..bc4c1b34266 100644
--- a/intern/cycles/kernel/shaders/node_gamma.osl
+++ b/intern/cycles/kernel/shaders/node_gamma.osl
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#include "stdosl.h"
diff --git a/intern/cycles/kernel/shaders/node_geometry.osl b/intern/cycles/kernel/shaders/node_geometry.osl
index 7bef2051865..b0bd7692489 100644
--- a/intern/cycles/kernel/shaders/node_geometry.osl
+++ b/intern/cycles/kernel/shaders/node_geometry.osl
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#include "stdosl.h"
@@ -26,7 +26,8 @@ shader node_geometry(
output normal TrueNormal = normal(0.0, 0.0, 0.0),
output vector Incoming = vector(0.0, 0.0, 0.0),
output point Parametric = point(0.0, 0.0, 0.0),
- output float Backfacing = 0.0)
+ output float Backfacing = 0.0,
+ output float Pointiness = 0.0)
{
Position = P;
Normal = NormalIn;
@@ -49,7 +50,7 @@ shader node_geometry(
/* try to create spherical tangent from generated coordinates */
if (getattribute("geom:generated", generated)) {
- normal data = normal(-(generated[1]-0.5), (generated[0]-0.5), 0.0);
+ normal data = normal(-(generated[1] - 0.5), (generated[0] - 0.5), 0.0);
vector T = transform("object", "world", data);
Tangent = cross(Normal, normalize(cross(T, Normal)));
}
@@ -57,5 +58,13 @@ shader node_geometry(
/* otherwise use surface derivatives */
Tangent = normalize(dPdu);
}
+
+ getattribute("geom:pointiness", Pointiness);
+ if (bump_offset == "dx") {
+ Pointiness += Dx(Pointiness);
+ }
+ else if (bump_offset == "dy") {
+ Pointiness += Dy(Pointiness);
+ }
}
diff --git a/intern/cycles/kernel/shaders/node_glass_bsdf.osl b/intern/cycles/kernel/shaders/node_glass_bsdf.osl
index b3d6133553b..68bc107cc5e 100644
--- a/intern/cycles/kernel/shaders/node_glass_bsdf.osl
+++ b/intern/cycles/kernel/shaders/node_glass_bsdf.osl
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#include "stdosl.h"
diff --git a/intern/cycles/kernel/shaders/node_glossy_bsdf.osl b/intern/cycles/kernel/shaders/node_glossy_bsdf.osl
index 5c727ca6917..d3250b32d0b 100644
--- a/intern/cycles/kernel/shaders/node_glossy_bsdf.osl
+++ b/intern/cycles/kernel/shaders/node_glossy_bsdf.osl
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#include "stdosl.h"
diff --git a/intern/cycles/kernel/shaders/node_gradient_texture.osl b/intern/cycles/kernel/shaders/node_gradient_texture.osl
index 5aa05917dc2..52b49688ab3 100644
--- a/intern/cycles/kernel/shaders/node_gradient_texture.osl
+++ b/intern/cycles/kernel/shaders/node_gradient_texture.osl
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#include "stdosl.h"
diff --git a/intern/cycles/kernel/shaders/node_hair_info.osl b/intern/cycles/kernel/shaders/node_hair_info.osl
index 1d1ba1983e1..965d2a3c7f7 100644
--- a/intern/cycles/kernel/shaders/node_hair_info.osl
+++ b/intern/cycles/kernel/shaders/node_hair_info.osl
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#include "stdosl.h"
diff --git a/intern/cycles/kernel/shaders/node_holdout.osl b/intern/cycles/kernel/shaders/node_holdout.osl
index cafad1b5757..78a9f46fd15 100644
--- a/intern/cycles/kernel/shaders/node_holdout.osl
+++ b/intern/cycles/kernel/shaders/node_holdout.osl
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#include "stdosl.h"
diff --git a/intern/cycles/kernel/shaders/node_hsv.osl b/intern/cycles/kernel/shaders/node_hsv.osl
index 4722bde4cd7..8d9e50fed6b 100644
--- a/intern/cycles/kernel/shaders/node_hsv.osl
+++ b/intern/cycles/kernel/shaders/node_hsv.osl
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#include "stdosl.h"
@@ -35,6 +35,11 @@ shader node_hsv(
Color = hsv_to_rgb(Color);
+ // Clamp color to prevent negative values cauzed by oversaturation.
+ Color[0] = max(Color[0], 0.0);
+ Color[1] = max(Color[1], 0.0);
+ Color[2] = max(Color[2], 0.0);
+
ColorOut = mix(ColorIn, Color, Fac);
}
diff --git a/intern/cycles/kernel/shaders/node_image_texture.osl b/intern/cycles/kernel/shaders/node_image_texture.osl
index 7238a1e8862..d3a347b70db 100644
--- a/intern/cycles/kernel/shaders/node_image_texture.osl
+++ b/intern/cycles/kernel/shaders/node_image_texture.osl
@@ -11,15 +11,60 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#include "stdosl.h"
#include "node_color.h"
-color image_texture_lookup(string filename, string color_space, float u, float v, output float Alpha, int use_alpha, int is_float, string interpolation)
+point texco_remap_square(point co)
{
- color rgb = (color)texture(filename, u, 1.0 - v, "wrap", "periodic", "interp", interpolation, "alpha", Alpha);
+ return (co - point(0.5, 0.5, 0.5)) * 2.0;
+}
+
+point map_to_tube(vector dir)
+{
+ float u, v;
+ v = (dir[2] + 1.0) * 0.5;
+ float len = sqrt(dir[0] * dir[0] + dir[1] * dir[1]);
+ if (len > 0.0) {
+ u = (1.0 - (atan2(dir[0] / len, dir[1] / len) / M_PI)) * 0.5;
+ }
+ else {
+ v = u = 0.0; /* To avoid un-initialized variables. */
+ }
+ return point(u, v, 0.0);
+}
+
+point map_to_sphere(vector dir)
+{
+ float len = length(dir);
+ float v, u;
+ if (len > 0.0) {
+ if (dir[0] == 0.0 && dir[1] == 0.0) {
+ u = 0.0; /* Othwise domain error. */
+ }
+ else {
+ u = (1.0 - atan2(dir[0], dir[1]) / M_PI) / 2.0;
+ }
+ v = 1.0 - acos(dir[2] / len) / M_PI;
+ }
+ else {
+ v = u = 0.0; /* To avoid un-initialized variables. */
+ }
+ return point(u, v, 0.0);
+}
+
+color image_texture_lookup(string filename,
+ string color_space,
+ float u, float v,
+ output float Alpha,
+ int use_alpha,
+ int is_float,
+ string interpolation,
+ string wrap)
+{
+ color rgb = (color)texture(filename, u, 1.0 - v, "wrap", wrap, "interp", interpolation, "alpha", Alpha);
if (use_alpha) {
rgb = color_unpremultiply(rgb, Alpha);
@@ -43,6 +88,7 @@ shader node_image_texture(
string color_space = "sRGB",
string projection = "Flat",
string interpolation = "smartcubic",
+ string wrap = "periodic",
float projection_blend = 0.0,
int is_float = 1,
int use_alpha = 1,
@@ -55,7 +101,14 @@ shader node_image_texture(
p = transform(mapping, p);
if (projection == "Flat") {
- Color = image_texture_lookup(filename, color_space, p[0], p[1], Alpha, use_alpha, is_float, interpolation);
+ Color = image_texture_lookup(filename,
+ color_space,
+ p[0], p[1],
+ Alpha,
+ use_alpha,
+ is_float,
+ interpolation,
+ wrap);
}
else if (projection == "Box") {
/* object space normal */
@@ -113,6 +166,10 @@ shader node_image_texture(
weight[2] = ((2.0 - limit) * Nob[2] + (limit - 1.0)) / (2.0 * limit - 1.0);
}
}
+ else {
+ /* Desperate mode, no valid choice anyway, fallback to one side.*/
+ weight[0] = 1.0;
+ }
Color = color(0.0, 0.0, 0.0);
Alpha = 0.0;
@@ -120,17 +177,59 @@ shader node_image_texture(
float tmp_alpha;
if (weight[0] > 0.0) {
- Color += weight[0] * image_texture_lookup(filename, color_space, p[1], p[2], tmp_alpha, use_alpha, is_float, interpolation);
+ Color += weight[0] * image_texture_lookup(filename,
+ color_space,
+ p[1], p[2],
+ tmp_alpha,
+ use_alpha,
+ is_float,
+ interpolation,
+ wrap);
Alpha += weight[0] * tmp_alpha;
}
if (weight[1] > 0.0) {
- Color += weight[1] * image_texture_lookup(filename, color_space, p[0], p[2], tmp_alpha, use_alpha, is_float, interpolation);
+ Color += weight[1] * image_texture_lookup(filename,
+ color_space,
+ p[0], p[2],
+ tmp_alpha,
+ use_alpha,
+ is_float,
+ interpolation,
+ wrap);
Alpha += weight[1] * tmp_alpha;
}
if (weight[2] > 0.0) {
- Color += weight[2] * image_texture_lookup(filename, color_space, p[1], p[0], tmp_alpha, use_alpha, is_float, interpolation);
+ Color += weight[2] * image_texture_lookup(filename,
+ color_space,
+ p[1], p[0],
+ tmp_alpha,
+ use_alpha,
+ is_float,
+ interpolation,
+ wrap);
Alpha += weight[2] * tmp_alpha;
}
}
+ else if (projection == "Sphere") {
+ point projected = map_to_sphere(texco_remap_square(p));
+ Color = image_texture_lookup(filename,
+ color_space,
+ projected[0], projected[1],
+ Alpha,
+ use_alpha,
+ is_float,
+ interpolation,
+ wrap);
+ }
+ else if (projection == "Tube") {
+ point projected = map_to_tube(texco_remap_square(p));
+ Color = image_texture_lookup(filename,
+ color_space,
+ projected[0], projected[1],
+ Alpha,
+ use_alpha,
+ is_float,
+ interpolation,
+ wrap);
+ }
}
-
diff --git a/intern/cycles/kernel/shaders/node_invert.osl b/intern/cycles/kernel/shaders/node_invert.osl
index 81ef2d0dc3d..b33b0a43d63 100644
--- a/intern/cycles/kernel/shaders/node_invert.osl
+++ b/intern/cycles/kernel/shaders/node_invert.osl
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#include "stdosl.h"
diff --git a/intern/cycles/kernel/shaders/node_layer_weight.osl b/intern/cycles/kernel/shaders/node_layer_weight.osl
index d03ebe2239a..f583df25773 100644
--- a/intern/cycles/kernel/shaders/node_layer_weight.osl
+++ b/intern/cycles/kernel/shaders/node_layer_weight.osl
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#include "stdosl.h"
diff --git a/intern/cycles/kernel/shaders/node_light_falloff.osl b/intern/cycles/kernel/shaders/node_light_falloff.osl
index 311b87f3764..a594e33d643 100644
--- a/intern/cycles/kernel/shaders/node_light_falloff.osl
+++ b/intern/cycles/kernel/shaders/node_light_falloff.osl
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#include "stdosl.h"
diff --git a/intern/cycles/kernel/shaders/node_light_path.osl b/intern/cycles/kernel/shaders/node_light_path.osl
index 95fbcabf917..99a92c4f403 100644
--- a/intern/cycles/kernel/shaders/node_light_path.osl
+++ b/intern/cycles/kernel/shaders/node_light_path.osl
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#include "stdosl.h"
diff --git a/intern/cycles/kernel/shaders/node_magic_texture.osl b/intern/cycles/kernel/shaders/node_magic_texture.osl
index b8afc6e29ac..c09523f205b 100644
--- a/intern/cycles/kernel/shaders/node_magic_texture.osl
+++ b/intern/cycles/kernel/shaders/node_magic_texture.osl
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#include "stdosl.h"
diff --git a/intern/cycles/kernel/shaders/node_mapping.osl b/intern/cycles/kernel/shaders/node_mapping.osl
index 46ff9f05e07..69106957ee4 100644
--- a/intern/cycles/kernel/shaders/node_mapping.osl
+++ b/intern/cycles/kernel/shaders/node_mapping.osl
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#include "stdosl.h"
diff --git a/intern/cycles/kernel/shaders/node_math.osl b/intern/cycles/kernel/shaders/node_math.osl
index abb6a359e75..7eef97fd7e8 100644
--- a/intern/cycles/kernel/shaders/node_math.osl
+++ b/intern/cycles/kernel/shaders/node_math.osl
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#include "stdosl.h"
@@ -93,8 +93,8 @@ shader node_math(
Value = Value1 > Value2;
else if (type == "Modulo")
Value = safe_modulo(Value1, Value2);
- else if (type == "Absolute")
- Value = fabs(Value1);
+ else if (type == "Absolute")
+ Value = fabs(Value1);
if (Clamp)
Value = clamp(Value, 0.0, 1.0);
diff --git a/intern/cycles/kernel/shaders/node_mix.osl b/intern/cycles/kernel/shaders/node_mix.osl
index dd54fd814de..9ef58e4cbba 100644
--- a/intern/cycles/kernel/shaders/node_mix.osl
+++ b/intern/cycles/kernel/shaders/node_mix.osl
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#include "stdosl.h"
diff --git a/intern/cycles/kernel/shaders/node_mix_closure.osl b/intern/cycles/kernel/shaders/node_mix_closure.osl
index 79d71c97371..5946dfdaaba 100644
--- a/intern/cycles/kernel/shaders/node_mix_closure.osl
+++ b/intern/cycles/kernel/shaders/node_mix_closure.osl
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#include "stdosl.h"
diff --git a/intern/cycles/kernel/shaders/node_musgrave_texture.osl b/intern/cycles/kernel/shaders/node_musgrave_texture.osl
index 60762539002..4f95dec910a 100644
--- a/intern/cycles/kernel/shaders/node_musgrave_texture.osl
+++ b/intern/cycles/kernel/shaders/node_musgrave_texture.osl
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#include "stdosl.h"
@@ -26,7 +26,7 @@
* from "Texturing and Modelling: A procedural approach"
*/
-float noise_musgrave_fBm(point p, string basis, float H, float lacunarity, float octaves)
+float noise_musgrave_fBm(point p, float H, float lacunarity, float octaves)
{
float rmd;
float value = 0.0;
@@ -35,14 +35,14 @@ float noise_musgrave_fBm(point p, string basis, float H, float lacunarity, float
int i;
for (i = 0; i < (int)octaves; i++) {
- value += safe_noise(p, 0) * pwr;
+ value += safe_noise(p, "signed") * pwr;
pwr *= pwHL;
p *= lacunarity;
}
rmd = octaves - floor(octaves);
if (rmd != 0.0)
- value += rmd * safe_noise(p, 0) * pwr;
+ value += rmd * safe_noise(p, "signed") * pwr;
return value;
}
@@ -54,7 +54,7 @@ float noise_musgrave_fBm(point p, string basis, float H, float lacunarity, float
* octaves: number of frequencies in the fBm
*/
-float noise_musgrave_multi_fractal(point p, string basis, float H, float lacunarity, float octaves)
+float noise_musgrave_multi_fractal(point p, float H, float lacunarity, float octaves)
{
float rmd;
float value = 1.0;
@@ -63,14 +63,14 @@ float noise_musgrave_multi_fractal(point p, string basis, float H, float lacunar
int i;
for (i = 0; i < (int)octaves; i++) {
- value *= (pwr * safe_noise(p, 0) + 1.0);
+ value *= (pwr * safe_noise(p, "signed") + 1.0);
pwr *= pwHL;
p *= lacunarity;
}
rmd = octaves - floor(octaves);
if (rmd != 0.0)
- value *= (rmd * pwr * safe_noise(p, 0) + 1.0); /* correct? */
+ value *= (rmd * pwr * safe_noise(p, "signed") + 1.0); /* correct? */
return value;
}
@@ -83,7 +83,7 @@ float noise_musgrave_multi_fractal(point p, string basis, float H, float lacunar
* offset: raises the terrain from `sea level'
*/
-float noise_musgrave_hetero_terrain(point p, string basis, float H, float lacunarity, float octaves, float offset)
+float noise_musgrave_hetero_terrain(point p, float H, float lacunarity, float octaves, float offset)
{
float value, increment, rmd;
float pwHL = pow(lacunarity, -H);
@@ -91,11 +91,11 @@ float noise_musgrave_hetero_terrain(point p, string basis, float H, float lacuna
int i;
/* first unscaled octave of function; later octaves are scaled */
- value = offset + safe_noise(p, 0);
+ value = offset + safe_noise(p, "signed");
p *= lacunarity;
for (i = 1; i < (int)octaves; i++) {
- increment = (safe_noise(p, 0) + offset) * pwr * value;
+ increment = (safe_noise(p, "signed") + offset) * pwr * value;
value += increment;
pwr *= pwHL;
p *= lacunarity;
@@ -103,7 +103,7 @@ float noise_musgrave_hetero_terrain(point p, string basis, float H, float lacuna
rmd = octaves - floor(octaves);
if (rmd != 0.0) {
- increment = (safe_noise(p, 0) + offset) * pwr * value;
+ increment = (safe_noise(p, "signed") + offset) * pwr * value;
value += rmd * increment;
}
@@ -118,15 +118,15 @@ float noise_musgrave_hetero_terrain(point p, string basis, float H, float lacuna
* offset: raises the terrain from `sea level'
*/
-float noise_musgrave_hybrid_multi_fractal(point p, string basis, float H,
- float lacunarity, float octaves, float offset, float gain)
+float noise_musgrave_hybrid_multi_fractal(point p, float H, float lacunarity,
+ float octaves, float offset, float gain)
{
float result, signal, weight, rmd;
float pwHL = pow(lacunarity, -H);
float pwr = pwHL;
int i;
- result = safe_noise(p, 0) + offset;
+ result = safe_noise(p, "signed") + offset;
weight = gain * result;
p *= lacunarity;
@@ -134,7 +134,7 @@ float noise_musgrave_hybrid_multi_fractal(point p, string basis, float H,
if (weight > 1.0)
weight = 1.0;
- signal = (safe_noise(p, 0) + offset) * pwr;
+ signal = (safe_noise(p, "signed") + offset) * pwr;
pwr *= pwHL;
result += weight * signal;
weight *= gain * signal;
@@ -143,7 +143,7 @@ float noise_musgrave_hybrid_multi_fractal(point p, string basis, float H,
rmd = octaves - floor(octaves);
if (rmd != 0.0)
- result += rmd * ((safe_noise(p, 0) + offset) * pwr);
+ result += rmd * ((safe_noise(p, "signed") + offset) * pwr);
return result;
}
@@ -156,15 +156,15 @@ float noise_musgrave_hybrid_multi_fractal(point p, string basis, float H,
* offset: raises the terrain from `sea level'
*/
-float noise_musgrave_ridged_multi_fractal(point p, string basis, float H,
- float lacunarity, float octaves, float offset, float gain)
+float noise_musgrave_ridged_multi_fractal(point p, float H, float lacunarity,
+ float octaves, float offset, float gain)
{
float result, signal, weight;
float pwHL = pow(lacunarity, -H);
float pwr = pwHL;
int i;
- signal = offset - fabs(safe_noise(p, 0));
+ signal = offset - fabs(safe_noise(p, "signed"));
signal *= signal;
result = signal;
weight = 1.0;
@@ -172,7 +172,7 @@ float noise_musgrave_ridged_multi_fractal(point p, string basis, float H,
for (i = 1; i < (int)octaves; i++) {
p *= lacunarity;
weight = clamp(signal * gain, 0.0, 1.0);
- signal = offset - fabs(safe_noise(p, 0));
+ signal = offset - fabs(safe_noise(p, "signed"));
signal *= signal;
signal *= weight;
result += signal * pwr;
@@ -201,7 +201,6 @@ shader node_musgrave_texture(
float dimension = max(Dimension, 1e-5);
float octaves = clamp(Detail, 0.0, 16.0);
float lacunarity = max(Lacunarity, 1e-5);
- string Basis = "Perlin";
float intensity = 1.0;
point p = Vector;
@@ -212,15 +211,15 @@ shader node_musgrave_texture(
p = p * Scale;
if (Type == "Multifractal")
- Fac = intensity * noise_musgrave_multi_fractal(p, Basis, dimension, lacunarity, octaves);
+ Fac = intensity * noise_musgrave_multi_fractal(p, dimension, lacunarity, octaves);
else if (Type == "fBM")
- Fac = intensity * noise_musgrave_fBm(p, Basis, dimension, lacunarity, octaves);
+ Fac = intensity * noise_musgrave_fBm(p, dimension, lacunarity, octaves);
else if (Type == "Hybrid Multifractal")
- Fac = intensity * noise_musgrave_hybrid_multi_fractal(p, Basis, dimension, lacunarity, octaves, Offset, Gain);
+ Fac = intensity * noise_musgrave_hybrid_multi_fractal(p, dimension, lacunarity, octaves, Offset, Gain);
else if (Type == "Ridged Multifractal")
- Fac = intensity * noise_musgrave_ridged_multi_fractal(p, Basis, dimension, lacunarity, octaves, Offset, Gain);
+ Fac = intensity * noise_musgrave_ridged_multi_fractal(p, dimension, lacunarity, octaves, Offset, Gain);
else if (Type == "Hetero Terrain")
- Fac = intensity * noise_musgrave_hetero_terrain(p, Basis, dimension, lacunarity, octaves, Offset);
+ Fac = intensity * noise_musgrave_hetero_terrain(p, dimension, lacunarity, octaves, Offset);
Color = color(Fac, Fac, Fac);
}
diff --git a/intern/cycles/kernel/shaders/node_noise_texture.osl b/intern/cycles/kernel/shaders/node_noise_texture.osl
index 912795966e0..e83e5b5b211 100644
--- a/intern/cycles/kernel/shaders/node_noise_texture.osl
+++ b/intern/cycles/kernel/shaders/node_noise_texture.osl
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#include "stdosl.h"
@@ -19,23 +19,23 @@
/* Noise */
-float noise(point p, string basis, float distortion, float detail, float fac, color Color)
+float noise(point p, float distortion, float detail, float fac, color Color)
{
point r;
int hard = 0;
if (distortion != 0.0) {
- r[0] = noise_basis(p + point(13.5), basis) * distortion;
- r[1] = noise_basis(p, basis) * distortion;
- r[2] = noise_basis(p - point(13.5), basis) * distortion;
+ r[0] = safe_noise(p + point(13.5), "unsigned") * distortion;
+ r[1] = safe_noise(p, "unsigned") * distortion;
+ r[2] = safe_noise(p - point(13.5), "unsigned") * distortion;
p += r;
}
- fac = noise_turbulence(p, basis, detail, hard);
+ fac = noise_turbulence(p, detail, hard);
- Color = color(fac, noise_turbulence(point(p[1], p[0], p[2]), basis, detail, hard),
- noise_turbulence(point(p[1], p[2], p[0]), basis, detail, hard));
+ Color = color(fac, noise_turbulence(point(p[1], p[0], p[2]), detail, hard),
+ noise_turbulence(point(p[1], p[2], p[0]), detail, hard));
return fac;
}
@@ -55,7 +55,6 @@ shader node_noise_texture(
if (use_mapping)
p = transform(mapping, p);
- string Basis = "Perlin";
- Fac = noise(p * Scale, Basis, Distortion, Detail, Fac, Color);
+ Fac = noise(p * Scale, Distortion, Detail, Fac, Color);
}
diff --git a/intern/cycles/kernel/shaders/node_normal.osl b/intern/cycles/kernel/shaders/node_normal.osl
index 14af044e0c0..2d04978fc72 100644
--- a/intern/cycles/kernel/shaders/node_normal.osl
+++ b/intern/cycles/kernel/shaders/node_normal.osl
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#include "stdosl.h"
@@ -23,6 +23,6 @@ shader node_normal(
output float Dot = 1.0)
{
NormalOut = normalize(Direction);
- Dot = dot(NormalOut, NormalIn);
+ Dot = dot(NormalOut, normalize(NormalIn));
}
diff --git a/intern/cycles/kernel/shaders/node_normal_map.osl b/intern/cycles/kernel/shaders/node_normal_map.osl
index c2080ecb194..01be566fb20 100644
--- a/intern/cycles/kernel/shaders/node_normal_map.osl
+++ b/intern/cycles/kernel/shaders/node_normal_map.osl
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#include "stdosl.h"
diff --git a/intern/cycles/kernel/shaders/node_object_info.osl b/intern/cycles/kernel/shaders/node_object_info.osl
index 1ebe767e82d..dd7c663b8d8 100644
--- a/intern/cycles/kernel/shaders/node_object_info.osl
+++ b/intern/cycles/kernel/shaders/node_object_info.osl
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#include "stdosl.h"
diff --git a/intern/cycles/kernel/shaders/node_output_displacement.osl b/intern/cycles/kernel/shaders/node_output_displacement.osl
index 613d6be5f3b..d0688cfda8d 100644
--- a/intern/cycles/kernel/shaders/node_output_displacement.osl
+++ b/intern/cycles/kernel/shaders/node_output_displacement.osl
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#include "stdosl.h"
diff --git a/intern/cycles/kernel/shaders/node_output_surface.osl b/intern/cycles/kernel/shaders/node_output_surface.osl
index fb16e85ce0d..2cc4575a8c8 100644
--- a/intern/cycles/kernel/shaders/node_output_surface.osl
+++ b/intern/cycles/kernel/shaders/node_output_surface.osl
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#include "stdosl.h"
diff --git a/intern/cycles/kernel/shaders/node_output_volume.osl b/intern/cycles/kernel/shaders/node_output_volume.osl
index 11a884b7d75..f220ba866e3 100644
--- a/intern/cycles/kernel/shaders/node_output_volume.osl
+++ b/intern/cycles/kernel/shaders/node_output_volume.osl
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#include "stdosl.h"
diff --git a/intern/cycles/kernel/shaders/node_particle_info.osl b/intern/cycles/kernel/shaders/node_particle_info.osl
index 077b0c114da..768b7753d02 100644
--- a/intern/cycles/kernel/shaders/node_particle_info.osl
+++ b/intern/cycles/kernel/shaders/node_particle_info.osl
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#include "stdosl.h"
diff --git a/intern/cycles/kernel/shaders/node_refraction_bsdf.osl b/intern/cycles/kernel/shaders/node_refraction_bsdf.osl
index 4a32415b482..d458ca730a4 100644
--- a/intern/cycles/kernel/shaders/node_refraction_bsdf.osl
+++ b/intern/cycles/kernel/shaders/node_refraction_bsdf.osl
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#include "stdosl.h"
diff --git a/intern/cycles/kernel/shaders/node_rgb_curves.osl b/intern/cycles/kernel/shaders/node_rgb_curves.osl
index 4e0f8721144..60cb273ba98 100644
--- a/intern/cycles/kernel/shaders/node_rgb_curves.osl
+++ b/intern/cycles/kernel/shaders/node_rgb_curves.osl
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#include "stdosl.h"
diff --git a/intern/cycles/kernel/shaders/node_rgb_ramp.osl b/intern/cycles/kernel/shaders/node_rgb_ramp.osl
index d3c2e9573d2..0202ba0bf79 100644
--- a/intern/cycles/kernel/shaders/node_rgb_ramp.osl
+++ b/intern/cycles/kernel/shaders/node_rgb_ramp.osl
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#include "stdosl.h"
diff --git a/intern/cycles/kernel/shaders/node_scatter_volume.osl b/intern/cycles/kernel/shaders/node_scatter_volume.osl
index 77c157bd92b..002e2750fca 100644
--- a/intern/cycles/kernel/shaders/node_scatter_volume.osl
+++ b/intern/cycles/kernel/shaders/node_scatter_volume.osl
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#include "stdosl.h"
diff --git a/intern/cycles/kernel/shaders/node_separate_hsv.osl b/intern/cycles/kernel/shaders/node_separate_hsv.osl
index 94fc5de9122..2a804040294 100644
--- a/intern/cycles/kernel/shaders/node_separate_hsv.osl
+++ b/intern/cycles/kernel/shaders/node_separate_hsv.osl
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#include "stdosl.h"
diff --git a/intern/cycles/kernel/shaders/node_separate_rgb.osl b/intern/cycles/kernel/shaders/node_separate_rgb.osl
index aebb63a0ee4..43d9e3aa4b1 100644
--- a/intern/cycles/kernel/shaders/node_separate_rgb.osl
+++ b/intern/cycles/kernel/shaders/node_separate_rgb.osl
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#include "stdosl.h"
diff --git a/intern/cycles/kernel/shaders/node_separate_xyz.osl b/intern/cycles/kernel/shaders/node_separate_xyz.osl
index 63725cb9995..e1963a1902f 100644
--- a/intern/cycles/kernel/shaders/node_separate_xyz.osl
+++ b/intern/cycles/kernel/shaders/node_separate_xyz.osl
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#include "stdosl.h"
diff --git a/intern/cycles/kernel/shaders/node_set_normal.osl b/intern/cycles/kernel/shaders/node_set_normal.osl
index 8eef152308a..7ca7ac9350c 100644
--- a/intern/cycles/kernel/shaders/node_set_normal.osl
+++ b/intern/cycles/kernel/shaders/node_set_normal.osl
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#include "stdosl.h"
diff --git a/intern/cycles/kernel/shaders/node_sky_texture.osl b/intern/cycles/kernel/shaders/node_sky_texture.osl
index 85c2dbdb2c2..05eed23bea8 100644
--- a/intern/cycles/kernel/shaders/node_sky_texture.osl
+++ b/intern/cycles/kernel/shaders/node_sky_texture.osl
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#include "stdosl.h"
diff --git a/intern/cycles/kernel/shaders/node_subsurface_scattering.osl b/intern/cycles/kernel/shaders/node_subsurface_scattering.osl
index 1c0cd74c0be..dbbf657776c 100644
--- a/intern/cycles/kernel/shaders/node_subsurface_scattering.osl
+++ b/intern/cycles/kernel/shaders/node_subsurface_scattering.osl
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#include "stdosl.h"
diff --git a/intern/cycles/kernel/shaders/node_tangent.osl b/intern/cycles/kernel/shaders/node_tangent.osl
index 41a2b2b0216..53a47396f9f 100644
--- a/intern/cycles/kernel/shaders/node_tangent.osl
+++ b/intern/cycles/kernel/shaders/node_tangent.osl
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#include "stdosl.h"
diff --git a/intern/cycles/kernel/shaders/node_texture.h b/intern/cycles/kernel/shaders/node_texture.h
index de51559f297..fc2cfdcd55c 100644
--- a/intern/cycles/kernel/shaders/node_texture.h
+++ b/intern/cycles/kernel/shaders/node_texture.h
@@ -11,35 +11,9 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
-/* Voronoi Distances */
-
-float voronoi_distance(string distance_metric, vector d, float e)
-{
-#if 0
- if (distance_metric == "Distance Squared")
-#endif
- return dot(d, d);
-#if 0
- if (distance_metric == "Actual Distance")
- return length(d);
- if (distance_metric == "Manhattan")
- return fabs(d[0]) + fabs(d[1]) + fabs(d[2]);
- if (distance_metric == "Chebychev")
- return max(fabs(d[0]), max(fabs(d[1]), fabs(d[2])));
- if (distance_metric == "Minkovsky 1/2")
- return sqrt(fabs(d[0])) + sqrt(fabs(d[1])) + sqrt(fabs(d[1]));
- if (distance_metric == "Minkovsky 4")
- return sqrt(sqrt(dot(d * d, d * d)));
- if (distance_metric == "Minkovsky")
- return pow(pow(fabs(d[0]), e) + pow(fabs(d[1]), e) + pow(fabs(d[2]), e), 1.0 / e);
-
- return 0.0;
-#endif
-}
-
/* Voronoi / Worley like */
color cellnoise_color(point p)
@@ -51,7 +25,7 @@ color cellnoise_color(point p)
return color(r, g, b);
}
-void voronoi(point p, string distance_metric, float e, float da[4], point pa[4])
+void voronoi(point p, float e, float da[4], point pa[4])
{
/* returns distances in da and point coords in pa */
int xx, yy, zz, xi, yi, zi;
@@ -71,7 +45,7 @@ void voronoi(point p, string distance_metric, float e, float da[4], point pa[4])
point ip = point(xx, yy, zz);
point vp = (point)cellnoise_color(ip);
point pd = p - (vp + ip);
- float d = voronoi_distance(distance_metric, pd, e);
+ float d = dot(pd, pd);
vp += point(xx, yy, zz);
@@ -111,54 +85,14 @@ void voronoi(point p, string distance_metric, float e, float da[4], point pa[4])
}
}
-float voronoi_Fn(point p, int n)
-{
- float da[4];
- point pa[4];
-
- voronoi(p, "Distance Squared", 0, da, pa);
-
- return da[n];
-}
-
-float voronoi_FnFn(point p, int n1, int n2)
-{
- float da[4];
- point pa[4];
-
- voronoi(p, "Distance Squared", 0, da, pa);
-
- return da[n2] - da[n1];
-}
-
-float voronoi_F1(point p) { return voronoi_Fn(p, 0); }
-float voronoi_F2(point p) { return voronoi_Fn(p, 1); }
-float voronoi_F3(point p) { return voronoi_Fn(p, 2); }
-float voronoi_F4(point p) { return voronoi_Fn(p, 3); }
-float voronoi_F1F2(point p) { return voronoi_FnFn(p, 0, 1); }
-
-float voronoi_Cr(point p)
-{
- /* crackle type pattern, just a scale/clamp of F2-F1 */
- float t = 10.0 * voronoi_F1F2(p);
- return (t > 1.0) ? 1.0 : t;
-}
-
-float voronoi_F1S(point p) { return 2.0 * voronoi_F1(p) - 1.0; }
-float voronoi_F2S(point p) { return 2.0 * voronoi_F2(p) - 1.0; }
-float voronoi_F3S(point p) { return 2.0 * voronoi_F3(p) - 1.0; }
-float voronoi_F4S(point p) { return 2.0 * voronoi_F4(p) - 1.0; }
-float voronoi_F1F2S(point p) { return 2.0 * voronoi_F1F2(p) - 1.0; }
-float voronoi_CrS(point p) { return 2.0 * voronoi_Cr(p) - 1.0; }
-
/* Noise Bases */
-float safe_noise(point p, int type)
+float safe_noise(point p, string type)
{
float f = 0.0;
/* Perlin noise in range -1..1 */
- if (type == 0)
+ if (type == "signed")
f = noise("perlin", p);
/* Perlin noise in range 0..1 */
@@ -172,39 +106,9 @@ float safe_noise(point p, int type)
return f;
}
-float noise_basis(point p, string basis)
-{
- if (basis == "Perlin")
- return safe_noise(p, 1);
- if (basis == "Voronoi F1")
- return voronoi_F1S(p);
- if (basis == "Voronoi F2")
- return voronoi_F2S(p);
- if (basis == "Voronoi F3")
- return voronoi_F3S(p);
- if (basis == "Voronoi F4")
- return voronoi_F4S(p);
- if (basis == "Voronoi F2-F1")
- return voronoi_F1F2S(p);
- if (basis == "Voronoi Crackle")
- return voronoi_CrS(p);
- if (basis == "Cell Noise")
- return cellnoise(p);
-
- return 0.0;
-}
-
-/* Soft/Hard Noise */
-
-float noise_basis_hard(point p, string basis, int hard)
-{
- float t = noise_basis(p, basis);
- return (hard) ? fabs(2.0 * t - 1.0) : t;
-}
-
/* Turbulence */
-float noise_turbulence(point p, string basis, float details, int hard)
+float noise_turbulence(point p, float details, int hard)
{
float fscale = 1.0;
float amp = 1.0;
@@ -215,7 +119,7 @@ float noise_turbulence(point p, string basis, float details, int hard)
n = (int)octaves;
for (i = 0; i <= n; i++) {
- float t = noise_basis(fscale * p, basis);
+ float t = safe_noise(fscale * p, "unsigned");
if (hard)
t = fabs(2.0 * t - 1.0);
@@ -228,7 +132,7 @@ float noise_turbulence(point p, string basis, float details, int hard)
float rmd = octaves - floor(octaves);
if (rmd != 0.0) {
- float t = noise_basis(fscale * p, basis);
+ float t = safe_noise(fscale * p, "unsigned");
if (hard)
t = fabs(2.0 * t - 1.0);
diff --git a/intern/cycles/kernel/shaders/node_texture_coordinate.osl b/intern/cycles/kernel/shaders/node_texture_coordinate.osl
index 8fdf469df21..9e2109fa082 100644
--- a/intern/cycles/kernel/shaders/node_texture_coordinate.osl
+++ b/intern/cycles/kernel/shaders/node_texture_coordinate.osl
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#include "stdosl.h"
@@ -21,7 +21,9 @@ shader node_texture_coordinate(
int is_background = 0,
int is_volume = 0,
int from_dupli = 0,
+ int use_transform = 0,
string bump_offset = "center",
+ matrix object_itfm = matrix(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
output point Generated = point(0.0, 0.0, 0.0),
output point UV = point(0.0, 0.0, 0.0),
@@ -60,7 +62,12 @@ shader node_texture_coordinate(
getattribute("geom:uv", UV);
}
- Object = transform("object", P);
+ if (use_transform) {
+ Object = transform(object_itfm, P);
+ }
+ else {
+ Object = transform("object", P);
+ }
Camera = transform("camera", P);
Window = transform("NDC", P);
Normal = transform("world", "object", NormalIn);
diff --git a/intern/cycles/kernel/shaders/node_toon_bsdf.osl b/intern/cycles/kernel/shaders/node_toon_bsdf.osl
index 1f7e1b8e6e1..75c5d06f847 100644
--- a/intern/cycles/kernel/shaders/node_toon_bsdf.osl
+++ b/intern/cycles/kernel/shaders/node_toon_bsdf.osl
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#include "stdosl.h"
diff --git a/intern/cycles/kernel/shaders/node_translucent_bsdf.osl b/intern/cycles/kernel/shaders/node_translucent_bsdf.osl
index 8059f5788ec..94d23d35326 100644
--- a/intern/cycles/kernel/shaders/node_translucent_bsdf.osl
+++ b/intern/cycles/kernel/shaders/node_translucent_bsdf.osl
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#include "stdosl.h"
diff --git a/intern/cycles/kernel/shaders/node_transparent_bsdf.osl b/intern/cycles/kernel/shaders/node_transparent_bsdf.osl
index 552e4106b0c..5d6798f19a6 100644
--- a/intern/cycles/kernel/shaders/node_transparent_bsdf.osl
+++ b/intern/cycles/kernel/shaders/node_transparent_bsdf.osl
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#include "stdosl.h"
diff --git a/intern/cycles/kernel/shaders/node_uv_map.osl b/intern/cycles/kernel/shaders/node_uv_map.osl
index 01c984aff4c..77e2e8d12d7 100644
--- a/intern/cycles/kernel/shaders/node_uv_map.osl
+++ b/intern/cycles/kernel/shaders/node_uv_map.osl
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#include "stdosl.h"
diff --git a/intern/cycles/kernel/shaders/node_value.osl b/intern/cycles/kernel/shaders/node_value.osl
index aebfab35d2a..f75388d1f76 100644
--- a/intern/cycles/kernel/shaders/node_value.osl
+++ b/intern/cycles/kernel/shaders/node_value.osl
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#include "stdosl.h"
diff --git a/intern/cycles/kernel/shaders/node_vector_curves.osl b/intern/cycles/kernel/shaders/node_vector_curves.osl
index 137ebe112eb..7bbf97d95ea 100644
--- a/intern/cycles/kernel/shaders/node_vector_curves.osl
+++ b/intern/cycles/kernel/shaders/node_vector_curves.osl
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#include "stdosl.h"
diff --git a/intern/cycles/kernel/shaders/node_vector_math.osl b/intern/cycles/kernel/shaders/node_vector_math.osl
index 0c8857deae2..f83412dc0f7 100644
--- a/intern/cycles/kernel/shaders/node_vector_math.osl
+++ b/intern/cycles/kernel/shaders/node_vector_math.osl
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#include "stdosl.h"
diff --git a/intern/cycles/kernel/shaders/node_vector_transform.osl b/intern/cycles/kernel/shaders/node_vector_transform.osl
index 6fb0ab1d8cc..8ebaa31ab25 100644
--- a/intern/cycles/kernel/shaders/node_vector_transform.osl
+++ b/intern/cycles/kernel/shaders/node_vector_transform.osl
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#include "stdosl.h"
diff --git a/intern/cycles/kernel/shaders/node_velvet_bsdf.osl b/intern/cycles/kernel/shaders/node_velvet_bsdf.osl
index 37b26babc64..456c26998c8 100644
--- a/intern/cycles/kernel/shaders/node_velvet_bsdf.osl
+++ b/intern/cycles/kernel/shaders/node_velvet_bsdf.osl
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#include "stdosl.h"
diff --git a/intern/cycles/kernel/shaders/node_voronoi_texture.osl b/intern/cycles/kernel/shaders/node_voronoi_texture.osl
index 7a1e0016690..29e143ae207 100644
--- a/intern/cycles/kernel/shaders/node_voronoi_texture.osl
+++ b/intern/cycles/kernel/shaders/node_voronoi_texture.osl
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#include "stdosl.h"
@@ -37,7 +37,7 @@ shader node_voronoi_texture(
float da[4];
point pa[4];
- voronoi(p * Scale, "Distance Squared", 1.0, da, pa);
+ voronoi(p * Scale, 1.0, da, pa);
/* Colored output */
if (Coloring == "Intensity") {
diff --git a/intern/cycles/kernel/shaders/node_voxel_texture.osl b/intern/cycles/kernel/shaders/node_voxel_texture.osl
new file mode 100644
index 00000000000..e45af62220f
--- /dev/null
+++ b/intern/cycles/kernel/shaders/node_voxel_texture.osl
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2011-2015 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 "stdosl.h"
+
+shader node_voxel_texture(
+ string filename = "",
+ string interpolation = "linear",
+ int use_mapping = 0,
+ matrix mapping = matrix(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
+ point Vector = P,
+ output float Density = 0,
+ output color Color = 0)
+{
+ point p = Vector;
+ if (use_mapping) {
+ p = transform(mapping, p);
+ }
+ else {
+ p = transform("object", Vector);
+ matrix tfm;
+ if (getattribute("geom:generated_transform", tfm))
+ p = transform(tfm, p);
+ }
+ if(p[0] < 0.0 || p[1] < 0.0 || p[2] < 0.0 ||
+ p[0] > 1.0 || p[1] > 1.0 || p[2] > 1.0)
+ {
+ Density = 0;
+ Color = color(0, 0, 0);
+ }
+ else {
+ Color = (color)texture3d(filename, p, "wrap", "periodic", "interp", interpolation, "alpha", Density);
+ }
+}
diff --git a/intern/cycles/kernel/shaders/node_wave_texture.osl b/intern/cycles/kernel/shaders/node_wave_texture.osl
index ba40207b446..569f284cbac 100644
--- a/intern/cycles/kernel/shaders/node_wave_texture.osl
+++ b/intern/cycles/kernel/shaders/node_wave_texture.osl
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#include "stdosl.h"
@@ -31,7 +31,7 @@ float wave(point p, string type, float detail, float distortion, float dscale)
}
if (distortion != 0.0) {
- n = n + (distortion * noise_turbulence(p * dscale, "Perlin", detail, 0));
+ n = n + (distortion * noise_turbulence(p * dscale, detail, 0));
}
return 0.5 + 0.5 * sin(n);
}
diff --git a/intern/cycles/kernel/shaders/node_wavelength.osl b/intern/cycles/kernel/shaders/node_wavelength.osl
index 4333c1fd944..79e7043d4bf 100644
--- a/intern/cycles/kernel/shaders/node_wavelength.osl
+++ b/intern/cycles/kernel/shaders/node_wavelength.osl
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#include "stdosl.h"
diff --git a/intern/cycles/kernel/shaders/node_wireframe.osl b/intern/cycles/kernel/shaders/node_wireframe.osl
index db8925c9efc..5cc214495dd 100644
--- a/intern/cycles/kernel/shaders/node_wireframe.osl
+++ b/intern/cycles/kernel/shaders/node_wireframe.osl
@@ -11,17 +11,31 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#include "stdosl.h"
#include "oslutil.h"
shader node_wireframe(
+ string bump_offset = "center",
int use_pixel_size = 0,
float Size = 0.01,
output float Fac = 0.0)
{
Fac = wireframe("triangles", Size, use_pixel_size);
+ /* TODO(sergey): Since we can't use autodiff here we do algebraic
+ * calculation of derivatives by definition. We could probably
+ * optimize this a bit by doing some extra calculation in wireframe().
+ */
+ if (bump_offset == "dx") {
+ point dx = Dx(P);
+ P -= dx;
+ Fac += (Fac - wireframe("triangles", Size, use_pixel_size)) / length(dx);
+ }
+ else if (bump_offset == "dy") {
+ point dy = Dy(P);
+ P -= dy;
+ Fac += (Fac - wireframe("triangles", Size, use_pixel_size)) / length(dy);
+ }
}
-
diff --git a/intern/cycles/kernel/shaders/stdosl.h b/intern/cycles/kernel/shaders/stdosl.h
index f8e5fd510ee..697a1756119 100644
--- a/intern/cycles/kernel/shaders/stdosl.h
+++ b/intern/cycles/kernel/shaders/stdosl.h
@@ -249,7 +249,21 @@ point rotate (point p, float angle, point a, point b)
{
vector axis = normalize (b - a);
float cosang, sinang;
+ /* Older OSX has major issues with sincos() function,
+ * it's likely a big in OSL or LLVM. For until we've
+ * updated to new versions of this libraries we'll
+ * use a workaround to prevent possible crashes on all
+ * the platforms.
+ *
+ * Shouldn't be that bad because it's mainly used for
+ * anisotropic shader where angle is usually constant.
+ */
+#if 0
sincos (angle, sinang, cosang);
+#else
+ sinang = sin (angle);
+ cosang = cos (angle);
+#endif
float cosang1 = 1.0 - cosang;
float x = axis[0], y = axis[1], z = axis[2];
matrix M = matrix (x * x + (1.0 - x * x) * cosang,
@@ -476,8 +490,6 @@ closure color diffuse_ramp(normal N, color colors[8]) BUILTIN;
closure color phong_ramp(normal N, float exponent, color colors[8]) BUILTIN;
closure color diffuse_toon(normal N, float size, float smooth) BUILTIN;
closure color glossy_toon(normal N, float size, float smooth) BUILTIN;
-closure color westin_backscatter(normal N, float roughness) BUILTIN;
-closure color westin_sheen(normal N, float edginess) BUILTIN;
closure color translucent(normal N) BUILTIN;
closure color reflection(normal N) BUILTIN;
closure color refraction(normal N, float eta) BUILTIN;
@@ -507,6 +519,47 @@ closure color hair_transmission(normal N, float roughnessu, float roughnessv, ve
closure color henyey_greenstein(float g) BUILTIN;
closure color absorption() BUILTIN;
+// OSL 1.5 Microfacet functions
+closure color microfacet(string distribution, normal N, vector U, float xalpha, float yalpha, float eta, int refract) {
+ /* GGX */
+ if (distribution == "ggx" || distribution == "default") {
+ if (!refract) {
+ if (xalpha == yalpha) {
+ /* Isotropic */
+ return microfacet_ggx(N, xalpha);
+ }
+ else {
+ /* Anisotropic */
+ return microfacet_ggx_aniso(N, U, xalpha, yalpha);
+ }
+ }
+ else {
+ return microfacet_ggx_refraction(N, xalpha, eta);
+ }
+ }
+ /* Beckmann */
+ else {
+ if (!refract) {
+ if (xalpha == yalpha) {
+ /* Isotropic */
+ return microfacet_beckmann(N, xalpha);
+ }
+ else {
+ /* Anisotropic */
+ return microfacet_beckmann_aniso(N, U, xalpha, yalpha);
+ }
+ }
+ else {
+ return microfacet_beckmann_refraction(N, xalpha, eta);
+ }
+ }
+}
+
+closure color microfacet (string distribution, normal N, float alpha, float eta, int refract) {
+ return microfacet(distribution, N, vector(0), alpha, alpha, eta, refract);
+}
+
+
// Renderer state
int backfacing () BUILTIN;
int raytype (string typename) BUILTIN;
diff --git a/intern/cycles/kernel/split/kernel_background_buffer_update.h b/intern/cycles/kernel/split/kernel_background_buffer_update.h
new file mode 100644
index 00000000000..0132ef9c2f2
--- /dev/null
+++ b/intern/cycles/kernel/split/kernel_background_buffer_update.h
@@ -0,0 +1,254 @@
+/*
+ * Copyright 2011-2015 Blender Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "kernel_split_common.h"
+
+/* Note on kernel_background_buffer_update kernel.
+ * This is the fourth kernel in the ray tracing logic, and the third
+ * of the path iteration kernels. This kernel takes care of rays that hit
+ * the background (sceneintersect kernel), and for the rays of
+ * state RAY_UPDATE_BUFFER it updates the ray's accumulated radiance in
+ * the output buffer. This kernel also takes care of rays that have been determined
+ * to-be-regenerated.
+ *
+ * We will empty QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS queue in this kernel
+ *
+ * Typically all rays that are in state RAY_HIT_BACKGROUND, RAY_UPDATE_BUFFER
+ * will be eventually set to RAY_TO_REGENERATE state in this kernel. Finally all rays of ray_state
+ * RAY_TO_REGENERATE will be regenerated and put in queue QUEUE_ACTIVE_AND_REGENERATED_RAYS.
+ *
+ * The input and output are as follows,
+ *
+ * rng_coop ---------------------------------------------|--- kernel_background_buffer_update --|--- PathRadiance_coop
+ * throughput_coop --------------------------------------| |--- L_transparent_coop
+ * per_sample_output_buffers ----------------------------| |--- per_sample_output_buffers
+ * Ray_coop ---------------------------------------------| |--- ray_state
+ * PathState_coop ---------------------------------------| |--- Queue_data (QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS)
+ * L_transparent_coop -----------------------------------| |--- Queue_data (QUEUE_ACTIVE_AND_REGENERATED_RAYS)
+ * ray_state --------------------------------------------| |--- Queue_index (QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS)
+ * Queue_data (QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS) ----| |--- Queue_index (QUEUE_ACTIVE_AND_REGENERATED_RAYS)
+ * Queue_index (QUEUE_ACTIVE_AND_REGENERATED_RAYS) ------| |--- work_array
+ * parallel_samples -------------------------------------| |--- PathState_coop
+ * end_sample -------------------------------------------| |--- throughput_coop
+ * kg (globals + data) ----------------------------------| |--- rng_coop
+ * rng_state --------------------------------------------| |--- Ray
+ * PathRadiance_coop ------------------------------------| |
+ * sw ---------------------------------------------------| |
+ * sh ---------------------------------------------------| |
+ * sx ---------------------------------------------------| |
+ * sy ---------------------------------------------------| |
+ * stride -----------------------------------------------| |
+ * work_array -------------------------------------------| |--- work_array
+ * queuesize --------------------------------------------| |
+ * start_sample -----------------------------------------| |--- work_pool_wgs
+ * work_pool_wgs ----------------------------------------| |
+ * num_samples ------------------------------------------| |
+ *
+ * note on shader_data : shader_data argument is neither an input nor an output for this kernel. It is just filled and consumed here itself.
+ * Note on Queues :
+ * This kernel fetches rays from QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS queue.
+ *
+ * State of queues when this kernel is called :
+ * At entry,
+ * QUEUE_ACTIVE_AND_REGENERATED_RAYS will be filled with RAY_ACTIVE rays
+ * QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS will be filled with RAY_UPDATE_BUFFER, RAY_HIT_BACKGROUND, RAY_TO_REGENERATE rays
+ * At exit,
+ * QUEUE_ACTIVE_AND_REGENERATED_RAYS will be filled with RAY_ACTIVE and RAY_REGENERATED rays
+ * QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS will be empty
+ */
+ccl_device char kernel_background_buffer_update(
+ ccl_global char *globals,
+ ccl_constant KernelData *data,
+ ccl_global char *shader_data,
+ ccl_global float *per_sample_output_buffers,
+ ccl_global uint *rng_state,
+ ccl_global uint *rng_coop, /* Required for buffer Update */
+ ccl_global float3 *throughput_coop, /* Required for background hit processing */
+ PathRadiance *PathRadiance_coop, /* Required for background hit processing and buffer Update */
+ ccl_global Ray *Ray_coop, /* Required for background hit processing */
+ ccl_global PathState *PathState_coop, /* Required for background hit processing */
+ ccl_global float *L_transparent_coop, /* Required for background hit processing and buffer Update */
+ ccl_global char *ray_state, /* Stores information on the current state of a ray */
+ int sw, int sh, int sx, int sy, int stride,
+ int rng_state_offset_x,
+ int rng_state_offset_y,
+ int rng_state_stride,
+ ccl_global unsigned int *work_array, /* Denotes work of each ray */
+ int end_sample,
+ int start_sample,
+#ifdef __WORK_STEALING__
+ ccl_global unsigned int *work_pool_wgs,
+ unsigned int num_samples,
+#endif
+#ifdef __KERNEL_DEBUG__
+ DebugData *debugdata_coop,
+#endif
+ int parallel_samples, /* Number of samples to be processed in parallel */
+ int ray_index)
+{
+ char enqueue_flag = 0;
+
+ /* Load kernel globals structure and ShaderData strucuture */
+ KernelGlobals *kg = (KernelGlobals *)globals;
+ ShaderData *sd = (ShaderData *)shader_data;
+
+#ifdef __KERNEL_DEBUG__
+ DebugData *debug_data = &debugdata_coop[ray_index];
+#endif
+ ccl_global PathState *state = &PathState_coop[ray_index];
+ PathRadiance *L = L = &PathRadiance_coop[ray_index];
+ ccl_global Ray *ray = &Ray_coop[ray_index];
+ ccl_global float3 *throughput = &throughput_coop[ray_index];
+ ccl_global float *L_transparent = &L_transparent_coop[ray_index];
+ ccl_global uint *rng = &rng_coop[ray_index];
+
+#ifdef __WORK_STEALING__
+ unsigned int my_work;
+ ccl_global float *initial_per_sample_output_buffers;
+ ccl_global uint *initial_rng;
+#endif
+ unsigned int sample;
+ unsigned int tile_x;
+ unsigned int tile_y;
+ unsigned int pixel_x;
+ unsigned int pixel_y;
+ unsigned int my_sample_tile;
+
+#ifdef __WORK_STEALING__
+ my_work = work_array[ray_index];
+ sample = get_my_sample(my_work, sw, sh, parallel_samples, ray_index) + start_sample;
+ get_pixel_tile_position(&pixel_x, &pixel_y,
+ &tile_x, &tile_y,
+ my_work,
+ sw, sh, sx, sy,
+ parallel_samples,
+ ray_index);
+ my_sample_tile = 0;
+ initial_per_sample_output_buffers = per_sample_output_buffers;
+ initial_rng = rng_state;
+#else /* __WORK_STEALING__ */
+ sample = work_array[ray_index];
+ int tile_index = ray_index / parallel_samples;
+ /* buffer and rng_state's stride is "stride". Find x and y using ray_index */
+ tile_x = tile_index % sw;
+ tile_y = tile_index / sw;
+ my_sample_tile = ray_index - (tile_index * parallel_samples);
+#endif /* __WORK_STEALING__ */
+
+ rng_state += (rng_state_offset_x + tile_x) + (rng_state_offset_y + tile_y) * rng_state_stride;
+ per_sample_output_buffers += (((tile_x + (tile_y * stride)) * parallel_samples) + my_sample_tile) * kernel_data.film.pass_stride;
+
+ if(IS_STATE(ray_state, ray_index, RAY_HIT_BACKGROUND)) {
+ /* eval background shader if nothing hit */
+ if(kernel_data.background.transparent && (state->flag & PATH_RAY_CAMERA)) {
+ *L_transparent = (*L_transparent) + average((*throughput));
+#ifdef __PASSES__
+ if(!(kernel_data.film.pass_flag & PASS_BACKGROUND))
+#endif
+ ASSIGN_RAY_STATE(ray_state, ray_index, RAY_UPDATE_BUFFER);
+ }
+
+ if(IS_STATE(ray_state, ray_index, RAY_HIT_BACKGROUND)) {
+#ifdef __BACKGROUND__
+ /* sample background shader */
+ float3 L_background = indirect_background(kg, state, ray, sd);
+ path_radiance_accum_background(L, (*throughput), L_background, state->bounce);
+#endif
+ ASSIGN_RAY_STATE(ray_state, ray_index, RAY_UPDATE_BUFFER);
+ }
+ }
+
+ if(IS_STATE(ray_state, ray_index, RAY_UPDATE_BUFFER)) {
+ float3 L_sum = path_radiance_clamp_and_sum(kg, L);
+ kernel_write_light_passes(kg, per_sample_output_buffers, L, sample);
+#ifdef __KERNEL_DEBUG__
+ kernel_write_debug_passes(kg, per_sample_output_buffers, state, debug_data, sample);
+#endif
+ float4 L_rad = make_float4(L_sum.x, L_sum.y, L_sum.z, 1.0f - (*L_transparent));
+
+ /* accumulate result in output buffer */
+ kernel_write_pass_float4(per_sample_output_buffers, sample, L_rad);
+ path_rng_end(kg, rng_state, *rng);
+
+ ASSIGN_RAY_STATE(ray_state, ray_index, RAY_TO_REGENERATE);
+ }
+
+ if(IS_STATE(ray_state, ray_index, RAY_TO_REGENERATE)) {
+#ifdef __WORK_STEALING__
+ /* We have completed current work; So get next work */
+ int valid_work = get_next_work(work_pool_wgs, &my_work, sw, sh, num_samples, parallel_samples, ray_index);
+ if(!valid_work) {
+ /* If work is invalid, this means no more work is available and the thread may exit */
+ ASSIGN_RAY_STATE(ray_state, ray_index, RAY_INACTIVE);
+ }
+#else /* __WORK_STEALING__ */
+ if((sample + parallel_samples) >= end_sample) {
+ ASSIGN_RAY_STATE(ray_state, ray_index, RAY_INACTIVE);
+ }
+#endif /* __WORK_STEALING__ */
+
+ if(IS_STATE(ray_state, ray_index, RAY_TO_REGENERATE)) {
+#ifdef __WORK_STEALING__
+ work_array[ray_index] = my_work;
+ /* Get the sample associated with the current work */
+ sample = get_my_sample(my_work, sw, sh, parallel_samples, ray_index) + start_sample;
+ /* Get pixel and tile position associated with current work */
+ get_pixel_tile_position(&pixel_x, &pixel_y, &tile_x, &tile_y, my_work, sw, sh, sx, sy, parallel_samples, ray_index);
+ my_sample_tile = 0;
+
+ /* Remap rng_state according to the current work */
+ rng_state = initial_rng + ((rng_state_offset_x + tile_x) + (rng_state_offset_y + tile_y) * rng_state_stride);
+ /* Remap per_sample_output_buffers according to the current work */
+ per_sample_output_buffers = initial_per_sample_output_buffers
+ + (((tile_x + (tile_y * stride)) * parallel_samples) + my_sample_tile) * kernel_data.film.pass_stride;
+#else /* __WORK_STEALING__ */
+ work_array[ray_index] = sample + parallel_samples;
+ sample = work_array[ray_index];
+
+ /* Get ray position from ray index */
+ pixel_x = sx + ((ray_index / parallel_samples) % sw);
+ pixel_y = sy + ((ray_index / parallel_samples) / sw);
+#endif /* __WORK_STEALING__ */
+
+ /* Initialize random numbers and ray. */
+ kernel_path_trace_setup(kg, rng_state, sample, pixel_x, pixel_y, rng, ray);
+
+ if(ray->t != 0.0f) {
+ /* Initialize throughput, L_transparent, Ray, PathState;
+ * These rays proceed with path-iteration.
+ */
+ *throughput = make_float3(1.0f, 1.0f, 1.0f);
+ *L_transparent = 0.0f;
+ path_radiance_init(L, kernel_data.film.use_light_pass);
+ path_state_init(kg, state, rng, sample, ray);
+#ifdef __KERNEL_DEBUG__
+ debug_data_init(debug_data);
+#endif
+ ASSIGN_RAY_STATE(ray_state, ray_index, RAY_REGENERATED);
+ enqueue_flag = 1;
+ } else {
+ /* These rays do not participate in path-iteration. */
+ float4 L_rad = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
+ /* Accumulate result in output buffer. */
+ kernel_write_pass_float4(per_sample_output_buffers, sample, L_rad);
+ path_rng_end(kg, rng_state, *rng);
+
+ ASSIGN_RAY_STATE(ray_state, ray_index, RAY_TO_REGENERATE);
+ }
+ }
+ }
+ return enqueue_flag;
+}
diff --git a/intern/cycles/kernel/split/kernel_data_init.h b/intern/cycles/kernel/split/kernel_data_init.h
new file mode 100644
index 00000000000..4dab79a5c67
--- /dev/null
+++ b/intern/cycles/kernel/split/kernel_data_init.h
@@ -0,0 +1,415 @@
+/*
+ * Copyright 2011-2015 Blender Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "kernel_split_common.h"
+
+/* Note on kernel_data_initialization kernel
+ * This kernel Initializes structures needed in path-iteration kernels.
+ * This is the first kernel in ray-tracing logic.
+ *
+ * Ray state of rays outside the tile-boundary will be marked RAY_INACTIVE
+ *
+ * Its input and output are as follows,
+ *
+ * Un-initialized rng---------------|--- kernel_data_initialization ---|--- Initialized rng
+ * Un-initialized throughput -------| |--- Initialized throughput
+ * Un-initialized L_transparent ----| |--- Initialized L_transparent
+ * Un-initialized PathRadiance -----| |--- Initialized PathRadiance
+ * Un-initialized Ray --------------| |--- Initialized Ray
+ * Un-initialized PathState --------| |--- Initialized PathState
+ * Un-initialized QueueData --------| |--- Initialized QueueData (to QUEUE_EMPTY_SLOT)
+ * Un-initialized QueueIndex -------| |--- Initialized QueueIndex (to 0)
+ * Un-initialized use_queues_flag---| |--- Initialized use_queues_flag (to false)
+ * Un-initialized ray_state --------| |--- Initialized ray_state
+ * parallel_samples --------------- | |--- Initialized per_sample_output_buffers
+ * rng_state -----------------------| |--- Initialized work_array
+ * data ----------------------------| |--- Initialized work_pool_wgs
+ * start_sample --------------------| |
+ * sx ------------------------------| |
+ * sy ------------------------------| |
+ * sw ------------------------------| |
+ * sh ------------------------------| |
+ * stride --------------------------| |
+ * queuesize -----------------------| |
+ * num_samples ---------------------| |
+ *
+ * Note on Queues :
+ * All slots in queues are initialized to queue empty slot;
+ * The number of elements in the queues is initialized to 0;
+ */
+ccl_device void kernel_data_init(
+ ccl_global char *globals,
+ ccl_global char *shader_data_sd, /* Arguments related to ShaderData */
+ ccl_global char *shader_data_sd_DL_shadow, /* Arguments related to ShaderData */
+
+ ccl_global float3 *P_sd,
+ ccl_global float3 *P_sd_DL_shadow,
+
+ ccl_global float3 *N_sd,
+ ccl_global float3 *N_sd_DL_shadow,
+
+ ccl_global float3 *Ng_sd,
+ ccl_global float3 *Ng_sd_DL_shadow,
+
+ ccl_global float3 *I_sd,
+ ccl_global float3 *I_sd_DL_shadow,
+
+ ccl_global int *shader_sd,
+ ccl_global int *shader_sd_DL_shadow,
+
+ ccl_global int *flag_sd,
+ ccl_global int *flag_sd_DL_shadow,
+
+ ccl_global int *prim_sd,
+ ccl_global int *prim_sd_DL_shadow,
+
+ ccl_global int *type_sd,
+ ccl_global int *type_sd_DL_shadow,
+
+ ccl_global float *u_sd,
+ ccl_global float *u_sd_DL_shadow,
+
+ ccl_global float *v_sd,
+ ccl_global float *v_sd_DL_shadow,
+
+ ccl_global int *object_sd,
+ ccl_global int *object_sd_DL_shadow,
+
+ ccl_global float *time_sd,
+ ccl_global float *time_sd_DL_shadow,
+
+ ccl_global float *ray_length_sd,
+ ccl_global float *ray_length_sd_DL_shadow,
+
+ ccl_global int *ray_depth_sd,
+ ccl_global int *ray_depth_sd_DL_shadow,
+
+ ccl_global int *transparent_depth_sd,
+ ccl_global int *transparent_depth_sd_DL_shadow,
+
+ /* Ray differentials. */
+ ccl_global differential3 *dP_sd,
+ ccl_global differential3 *dP_sd_DL_shadow,
+
+ ccl_global differential3 *dI_sd,
+ ccl_global differential3 *dI_sd_DL_shadow,
+
+ ccl_global differential *du_sd,
+ ccl_global differential *du_sd_DL_shadow,
+
+ ccl_global differential *dv_sd,
+ ccl_global differential *dv_sd_DL_shadow,
+
+ /* Dp/Du */
+ ccl_global float3 *dPdu_sd,
+ ccl_global float3 *dPdu_sd_DL_shadow,
+
+ ccl_global float3 *dPdv_sd,
+ ccl_global float3 *dPdv_sd_DL_shadow,
+
+ /* Object motion. */
+ ccl_global Transform *ob_tfm_sd,
+ ccl_global Transform *ob_tfm_sd_DL_shadow,
+
+ ccl_global Transform *ob_itfm_sd,
+ ccl_global Transform *ob_itfm_sd_DL_shadow,
+
+ ShaderClosure *closure_sd,
+ ShaderClosure *closure_sd_DL_shadow,
+
+ ccl_global int *num_closure_sd,
+ ccl_global int *num_closure_sd_DL_shadow,
+
+ ccl_global float *randb_closure_sd,
+ ccl_global float *randb_closure_sd_DL_shadow,
+
+ ccl_global float3 *ray_P_sd,
+ ccl_global float3 *ray_P_sd_DL_shadow,
+
+ ccl_global differential3 *ray_dP_sd,
+ ccl_global differential3 *ray_dP_sd_DL_shadow,
+
+ ccl_constant KernelData *data,
+ ccl_global float *per_sample_output_buffers,
+ ccl_global uint *rng_state,
+ ccl_global uint *rng_coop, /* rng array to store rng values for all rays */
+ ccl_global float3 *throughput_coop, /* throughput array to store throughput values for all rays */
+ ccl_global float *L_transparent_coop, /* L_transparent array to store L_transparent values for all rays */
+ PathRadiance *PathRadiance_coop, /* PathRadiance array to store PathRadiance values for all rays */
+ ccl_global Ray *Ray_coop, /* Ray array to store Ray information for all rays */
+ ccl_global PathState *PathState_coop, /* PathState array to store PathState information for all rays */
+ ccl_global char *ray_state, /* Stores information on current state of a ray */
+
+#define KERNEL_TEX(type, ttype, name) \
+ ccl_global type *name,
+#include "../kernel_textures.h"
+
+ int start_sample, int sx, int sy, int sw, int sh, int offset, int stride,
+ int rng_state_offset_x,
+ int rng_state_offset_y,
+ int rng_state_stride,
+ ccl_global int *Queue_data, /* Memory for queues */
+ ccl_global int *Queue_index, /* Tracks the number of elements in queues */
+ int queuesize, /* size (capacity) of the queue */
+ ccl_global char *use_queues_flag, /* flag to decide if scene-intersect kernel should use queues to fetch ray index */
+ ccl_global unsigned int *work_array, /* work array to store which work each ray belongs to */
+#ifdef __WORK_STEALING__
+ ccl_global unsigned int *work_pool_wgs, /* Work pool for each work group */
+ unsigned int num_samples, /* Total number of samples per pixel */
+#endif
+#ifdef __KERNEL_DEBUG__
+ DebugData *debugdata_coop,
+#endif
+ int parallel_samples) /* Number of samples to be processed in parallel */
+{
+
+ /* Load kernel globals structure */
+ KernelGlobals *kg = (KernelGlobals *)globals;
+
+ kg->data = data;
+#define KERNEL_TEX(type, ttype, name) \
+ kg->name = name;
+#include "../kernel_textures.h"
+
+ /* Load ShaderData structure */
+ ShaderData *sd = (ShaderData *)shader_data_sd;
+ ShaderData *sd_DL_shadow = (ShaderData *)shader_data_sd_DL_shadow;
+
+ sd->P = P_sd;
+ sd_DL_shadow->P = P_sd_DL_shadow;
+
+ sd->N = N_sd;
+ sd_DL_shadow->N = N_sd_DL_shadow;
+
+ sd->Ng = Ng_sd;
+ sd_DL_shadow->Ng = Ng_sd_DL_shadow;
+
+ sd->I = I_sd;
+ sd_DL_shadow->I = I_sd_DL_shadow;
+
+ sd->shader = shader_sd;
+ sd_DL_shadow->shader = shader_sd_DL_shadow;
+
+ sd->flag = flag_sd;
+ sd_DL_shadow->flag = flag_sd_DL_shadow;
+
+ sd->prim = prim_sd;
+ sd_DL_shadow->prim = prim_sd_DL_shadow;
+
+ sd->type = type_sd;
+ sd_DL_shadow->type = type_sd_DL_shadow;
+
+ sd->u = u_sd;
+ sd_DL_shadow->u = u_sd_DL_shadow;
+
+ sd->v = v_sd;
+ sd_DL_shadow->v = v_sd_DL_shadow;
+
+ sd->object = object_sd;
+ sd_DL_shadow->object = object_sd_DL_shadow;
+
+ sd->time = time_sd;
+ sd_DL_shadow->time = time_sd_DL_shadow;
+
+ sd->ray_length = ray_length_sd;
+ sd_DL_shadow->ray_length = ray_length_sd_DL_shadow;
+
+ sd->ray_depth = ray_depth_sd;
+ sd_DL_shadow->ray_depth = ray_depth_sd_DL_shadow;
+
+ sd->transparent_depth = transparent_depth_sd;
+ sd_DL_shadow->transparent_depth = transparent_depth_sd_DL_shadow;
+
+#ifdef __RAY_DIFFERENTIALS__
+ sd->dP = dP_sd;
+ sd_DL_shadow->dP = dP_sd_DL_shadow;
+
+ sd->dI = dI_sd;
+ sd_DL_shadow->dI = dI_sd_DL_shadow;
+
+ sd->du = du_sd;
+ sd_DL_shadow->du = du_sd_DL_shadow;
+
+ sd->dv = dv_sd;
+ sd_DL_shadow->dv = dv_sd_DL_shadow;
+#ifdef __DPDU__
+ sd->dPdu = dPdu_sd;
+ sd_DL_shadow->dPdu = dPdu_sd_DL_shadow;
+
+ sd->dPdv = dPdv_sd;
+ sd_DL_shadow->dPdv = dPdv_sd_DL_shadow;
+#endif
+#endif
+
+#ifdef __OBJECT_MOTION__
+ sd->ob_tfm = ob_tfm_sd;
+ sd_DL_shadow->ob_tfm = ob_tfm_sd_DL_shadow;
+
+ sd->ob_itfm = ob_itfm_sd;
+ sd_DL_shadow->ob_itfm = ob_itfm_sd_DL_shadow;
+#endif
+
+ sd->closure = closure_sd;
+ sd_DL_shadow->closure = closure_sd_DL_shadow;
+
+ sd->num_closure = num_closure_sd;
+ sd_DL_shadow->num_closure = num_closure_sd_DL_shadow;
+
+ sd->randb_closure = randb_closure_sd;
+ sd_DL_shadow->randb_closure = randb_closure_sd_DL_shadow;
+
+ sd->ray_P = ray_P_sd;
+ sd_DL_shadow->ray_P = ray_P_sd_DL_shadow;
+
+ sd->ray_dP = ray_dP_sd;
+ sd_DL_shadow->ray_dP = ray_dP_sd_DL_shadow;
+
+ int thread_index = get_global_id(1) * get_global_size(0) + get_global_id(0);
+
+#ifdef __WORK_STEALING__
+ int lid = get_local_id(1) * get_local_size(0) + get_local_id(0);
+ /* Initialize work_pool_wgs */
+ if(lid == 0) {
+ int group_index = get_group_id(1) * get_num_groups(0) + get_group_id(0);
+ work_pool_wgs[group_index] = 0;
+ }
+ barrier(CLK_LOCAL_MEM_FENCE);
+#endif /* __WORK_STEALING__ */
+
+ /* Initialize queue data and queue index. */
+ if(thread_index < queuesize) {
+ /* Initialize active ray queue. */
+ Queue_data[QUEUE_ACTIVE_AND_REGENERATED_RAYS * queuesize + thread_index] = QUEUE_EMPTY_SLOT;
+ /* Initialize background and buffer update queue. */
+ Queue_data[QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS * queuesize + thread_index] = QUEUE_EMPTY_SLOT;
+ /* Initialize shadow ray cast of AO queue. */
+ Queue_data[QUEUE_SHADOW_RAY_CAST_AO_RAYS * queuesize + thread_index] = QUEUE_EMPTY_SLOT;
+ /* Initialize shadow ray cast of direct lighting queue. */
+ Queue_data[QUEUE_SHADOW_RAY_CAST_DL_RAYS * queuesize + thread_index] = QUEUE_EMPTY_SLOT;
+ }
+
+ if(thread_index == 0) {
+ Queue_index[QUEUE_ACTIVE_AND_REGENERATED_RAYS] = 0;
+ Queue_index[QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS] = 0;
+ Queue_index[QUEUE_SHADOW_RAY_CAST_AO_RAYS] = 0;
+ Queue_index[QUEUE_SHADOW_RAY_CAST_DL_RAYS] = 0;
+ /* The scene-intersect kernel should not use the queues very first time.
+ * since the queue would be empty.
+ */
+ use_queues_flag[0] = 0;
+ }
+
+ int x = get_global_id(0);
+ int y = get_global_id(1);
+
+ if(x < (sw * parallel_samples) && y < sh) {
+ int ray_index = x + y * (sw * parallel_samples);
+
+ /* This is the first assignment to ray_state;
+ * So we dont use ASSIGN_RAY_STATE macro.
+ */
+ ray_state[ray_index] = RAY_ACTIVE;
+
+ unsigned int my_sample;
+ unsigned int pixel_x;
+ unsigned int pixel_y;
+ unsigned int tile_x;
+ unsigned int tile_y;
+ unsigned int my_sample_tile;
+
+#ifdef __WORK_STEALING__
+ unsigned int my_work = 0;
+ /* Get work. */
+ get_next_work(work_pool_wgs, &my_work, sw, sh, num_samples, parallel_samples, ray_index);
+ /* Get the sample associated with the work. */
+ my_sample = get_my_sample(my_work, sw, sh, parallel_samples, ray_index) + start_sample;
+
+ my_sample_tile = 0;
+
+ /* Get pixel and tile position associated with the work. */
+ get_pixel_tile_position(&pixel_x, &pixel_y,
+ &tile_x, &tile_y,
+ my_work,
+ sw, sh, sx, sy,
+ parallel_samples,
+ ray_index);
+ work_array[ray_index] = my_work;
+#else /* __WORK_STEALING__ */
+ unsigned int tile_index = ray_index / parallel_samples;
+ tile_x = tile_index % sw;
+ tile_y = tile_index / sw;
+ my_sample_tile = ray_index - (tile_index * parallel_samples);
+ my_sample = my_sample_tile + start_sample;
+
+ /* Initialize work array. */
+ work_array[ray_index] = my_sample ;
+
+ /* Calculate pixel position of this ray. */
+ pixel_x = sx + tile_x;
+ pixel_y = sy + tile_y;
+#endif /* __WORK_STEALING__ */
+
+ rng_state += (rng_state_offset_x + tile_x) + (rng_state_offset_y + tile_y) * rng_state_stride;
+
+ /* Initialise per_sample_output_buffers to all zeros. */
+ per_sample_output_buffers += (((tile_x + (tile_y * stride)) * parallel_samples) + (my_sample_tile)) * kernel_data.film.pass_stride;
+ int per_sample_output_buffers_iterator = 0;
+ for(per_sample_output_buffers_iterator = 0;
+ per_sample_output_buffers_iterator < kernel_data.film.pass_stride;
+ per_sample_output_buffers_iterator++)
+ {
+ per_sample_output_buffers[per_sample_output_buffers_iterator] = 0.0f;
+ }
+
+ /* Initialize random numbers and ray. */
+ kernel_path_trace_setup(kg,
+ rng_state,
+ my_sample,
+ pixel_x, pixel_y,
+ &rng_coop[ray_index],
+ &Ray_coop[ray_index]);
+
+ if(Ray_coop[ray_index].t != 0.0f) {
+ /* Initialize throughput, L_transparent, Ray, PathState;
+ * These rays proceed with path-iteration.
+ */
+ throughput_coop[ray_index] = make_float3(1.0f, 1.0f, 1.0f);
+ L_transparent_coop[ray_index] = 0.0f;
+ path_radiance_init(&PathRadiance_coop[ray_index], kernel_data.film.use_light_pass);
+ path_state_init(kg,
+ &PathState_coop[ray_index],
+ &rng_coop[ray_index],
+ my_sample,
+ &Ray_coop[ray_index]);
+#ifdef __KERNEL_DEBUG__
+ debug_data_init(&debugdata_coop[ray_index]);
+#endif
+ } else {
+ /* These rays do not participate in path-iteration. */
+ float4 L_rad = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
+ /* Accumulate result in output buffer. */
+ kernel_write_pass_float4(per_sample_output_buffers, my_sample, L_rad);
+ path_rng_end(kg, rng_state, rng_coop[ray_index]);
+ ASSIGN_RAY_STATE(ray_state, ray_index, RAY_TO_REGENERATE);
+ }
+ }
+
+ /* Mark rest of the ray-state indices as RAY_INACTIVE. */
+ if(thread_index < (get_global_size(0) * get_global_size(1)) - (sh * (sw * parallel_samples))) {
+ /* First assignment, hence we dont use ASSIGN_RAY_STATE macro */
+ ray_state[((sw * parallel_samples) * sh) + thread_index] = RAY_INACTIVE;
+ }
+}
diff --git a/intern/cycles/kernel/split/kernel_direct_lighting.h b/intern/cycles/kernel/split/kernel_direct_lighting.h
new file mode 100644
index 00000000000..50c83d06140
--- /dev/null
+++ b/intern/cycles/kernel/split/kernel_direct_lighting.h
@@ -0,0 +1,116 @@
+/*
+ * Copyright 2011-2015 Blender Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "kernel_split_common.h"
+
+/* Note on kernel_direct_lighting kernel.
+ * This is the eighth kernel in the ray tracing logic. This is the seventh
+ * of the path iteration kernels. This kernel takes care of direct lighting
+ * logic. However, the "shadow ray cast" part of direct lighting is handled
+ * in the next kernel.
+ *
+ * This kernels determines the rays for which a shadow_blocked() function associated with direct lighting should be executed.
+ * Those rays for which a shadow_blocked() function for direct-lighting must be executed, are marked with flag RAY_SHADOW_RAY_CAST_DL and
+ * enqueued into the queue QUEUE_SHADOW_RAY_CAST_DL_RAYS
+ *
+ * The input and output are as follows,
+ *
+ * rng_coop -----------------------------------------|--- kernel_direct_lighting --|--- BSDFEval_coop
+ * PathState_coop -----------------------------------| |--- ISLamp_coop
+ * shader_data --------------------------------------| |--- LightRay_coop
+ * ray_state ----------------------------------------| |--- ray_state
+ * Queue_data (QUEUE_ACTIVE_AND_REGENERATED_RAYS) ---| |
+ * kg (globals + data) ------------------------------| |
+ * queuesize ----------------------------------------| |
+ *
+ * note on shader_DL : shader_DL is neither input nor output to this kernel; shader_DL is filled and consumed in this kernel itself.
+ * Note on Queues :
+ * This kernel only reads from the QUEUE_ACTIVE_AND_REGENERATED_RAYS queue and processes
+ * only the rays of state RAY_ACTIVE; If a ray needs to execute the corresponding shadow_blocked
+ * part, after direct lighting, the ray is marked with RAY_SHADOW_RAY_CAST_DL flag.
+ *
+ * State of queues when this kernel is called :
+ * state of queues QUEUE_ACTIVE_AND_REGENERATED_RAYS and QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS will be same
+ * before and after this kernel call.
+ * QUEUE_SHADOW_RAY_CAST_DL_RAYS queue will be filled with rays for which a shadow_blocked function must be executed, after this
+ * kernel call. Before this kernel call the QUEUE_SHADOW_RAY_CAST_DL_RAYS will be empty.
+ */
+ccl_device char kernel_direct_lighting(
+ ccl_global char *globals,
+ ccl_constant KernelData *data,
+ ccl_global char *shader_data, /* Required for direct lighting */
+ ccl_global char *shader_DL, /* Required for direct lighting */
+ ccl_global uint *rng_coop, /* Required for direct lighting */
+ ccl_global PathState *PathState_coop, /* Required for direct lighting */
+ ccl_global int *ISLamp_coop, /* Required for direct lighting */
+ ccl_global Ray *LightRay_coop, /* Required for direct lighting */
+ ccl_global BsdfEval *BSDFEval_coop, /* Required for direct lighting */
+ ccl_global char *ray_state, /* Denotes the state of each ray */
+ int ray_index)
+{
+ char enqueue_flag = 0;
+ if(IS_STATE(ray_state, ray_index, RAY_ACTIVE)) {
+ /* Load kernel globals structure and ShaderData structure. */
+ KernelGlobals *kg = (KernelGlobals *)globals;
+ ShaderData *sd = (ShaderData *)shader_data;
+ ShaderData *sd_DL = (ShaderData *)shader_DL;
+
+ ccl_global PathState *state = &PathState_coop[ray_index];
+
+ /* direct lighting */
+#ifdef __EMISSION__
+ if((kernel_data.integrator.use_direct_light &&
+ (ccl_fetch(sd, flag) & SD_BSDF_HAS_EVAL)))
+ {
+ /* Sample illumination from lights to find path contribution. */
+ ccl_global RNG* rng = &rng_coop[ray_index];
+ float light_t = path_state_rng_1D(kg, rng, state, PRNG_LIGHT);
+ float light_u, light_v;
+ path_state_rng_2D(kg, rng, state, PRNG_LIGHT_U, &light_u, &light_v);
+
+ LightSample ls;
+ light_sample(kg,
+ light_t, light_u, light_v,
+ ccl_fetch(sd, time),
+ ccl_fetch(sd, P),
+ state->bounce,
+ &ls);
+
+ Ray light_ray;
+#ifdef __OBJECT_MOTION__
+ light_ray.time = ccl_fetch(sd, time);
+#endif
+
+ BsdfEval L_light;
+ bool is_lamp;
+ if(direct_emission(kg, sd, &ls, &light_ray, &L_light, &is_lamp,
+ state->bounce, state->transparent_bounce, sd_DL))
+ {
+ /* Write intermediate data to global memory to access from
+ * the next kernel.
+ */
+ LightRay_coop[ray_index] = light_ray;
+ BSDFEval_coop[ray_index] = L_light;
+ ISLamp_coop[ray_index] = is_lamp;
+ /* Mark ray state for next shadow kernel. */
+ ADD_RAY_FLAG(ray_state, ray_index, RAY_SHADOW_RAY_CAST_DL);
+ enqueue_flag = 1;
+ }
+ }
+#endif /* __EMISSION__ */
+ }
+ return enqueue_flag;
+}
diff --git a/intern/cycles/kernel/split/kernel_holdout_emission_blurring_pathtermination_ao.h b/intern/cycles/kernel/split/kernel_holdout_emission_blurring_pathtermination_ao.h
new file mode 100644
index 00000000000..a75523a3e53
--- /dev/null
+++ b/intern/cycles/kernel/split/kernel_holdout_emission_blurring_pathtermination_ao.h
@@ -0,0 +1,264 @@
+/*
+ * Copyright 2011-2015 Blender Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "kernel_split_common.h"
+
+/* Note on kernel_holdout_emission_blurring_pathtermination_ao kernel.
+ * This is the sixth kernel in the ray tracing logic. This is the fifth
+ * of the path iteration kernels. This kernel takes care of the logic to process
+ * "material of type holdout", indirect primitive emission, bsdf blurring,
+ * probabilistic path termination and AO.
+ *
+ * This kernels determines the rays for which a shadow_blocked() function associated with AO should be executed.
+ * Those rays for which a shadow_blocked() function for AO must be executed are marked with flag RAY_SHADOW_RAY_CAST_ao and
+ * enqueued into the queue QUEUE_SHADOW_RAY_CAST_AO_RAYS
+ *
+ * Ray state of rays that are terminated in this kernel are changed to RAY_UPDATE_BUFFER
+ *
+ * The input and output are as follows,
+ *
+ * rng_coop ---------------------------------------------|--- kernel_holdout_emission_blurring_pathtermination_ao ---|--- Queue_index (QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS)
+ * throughput_coop --------------------------------------| |--- PathState_coop
+ * PathRadiance_coop ------------------------------------| |--- throughput_coop
+ * Intersection_coop ------------------------------------| |--- L_transparent_coop
+ * PathState_coop ---------------------------------------| |--- per_sample_output_buffers
+ * L_transparent_coop -----------------------------------| |--- PathRadiance_coop
+ * shader_data ------------------------------------------| |--- ShaderData
+ * ray_state --------------------------------------------| |--- ray_state
+ * Queue_data (QUEUE_ACTIVE_AND_REGENERATED_RAYS) -------| |--- Queue_data (QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS)
+ * Queue_index (QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS) ---| |--- AOAlpha_coop
+ * kg (globals + data) ----------------------------------| |--- AOBSDF_coop
+ * parallel_samples -------------------------------------| |--- AOLightRay_coop
+ * per_sample_output_buffers ----------------------------| |
+ * sw ---------------------------------------------------| |
+ * sh ---------------------------------------------------| |
+ * sx ---------------------------------------------------| |
+ * sy ---------------------------------------------------| |
+ * stride -----------------------------------------------| |
+ * work_array -------------------------------------------| |
+ * queuesize --------------------------------------------| |
+ * start_sample -----------------------------------------| |
+ *
+ * Note on Queues :
+ * This kernel fetches rays from the queue QUEUE_ACTIVE_AND_REGENERATED_RAYS and processes only
+ * the rays of state RAY_ACTIVE.
+ * There are different points in this kernel where a ray may terminate and reach RAY_UPDATE_BUFFER
+ * state. These rays are enqueued into QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS queue. These rays will
+ * still be present in QUEUE_ACTIVE_AND_REGENERATED_RAYS queue, but since their ray-state has been
+ * changed to RAY_UPDATE_BUFFER, there is no problem.
+ *
+ * State of queues when this kernel is called :
+ * At entry,
+ * QUEUE_ACTIVE_AND_REGENERATED_RAYS will be filled with RAY_ACTIVE and RAY_REGENERATED rays
+ * QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS will be filled with RAY_TO_REGENERATE rays.
+ * QUEUE_SHADOW_RAY_CAST_AO_RAYS will be empty.
+ * At exit,
+ * QUEUE_ACTIVE_AND_REGENERATED_RAYS will be filled with RAY_ACTIVE, RAY_REGENERATED and RAY_UPDATE_BUFFER rays
+ * QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS will be filled with RAY_TO_REGENERATE and RAY_UPDATE_BUFFER rays
+ * QUEUE_SHADOW_RAY_CAST_AO_RAYS will be filled with rays marked with flag RAY_SHADOW_RAY_CAST_AO
+ */
+ccl_device void kernel_holdout_emission_blurring_pathtermination_ao(
+ ccl_global char *globals,
+ ccl_constant KernelData *data,
+ ccl_global char *shader_data, /* Required throughout the kernel except probabilistic path termination and AO */
+ ccl_global float *per_sample_output_buffers,
+ ccl_global uint *rng_coop, /* Required for "kernel_write_data_passes" and AO */
+ ccl_global float3 *throughput_coop, /* Required for handling holdout material and AO */
+ ccl_global float *L_transparent_coop, /* Required for handling holdout material */
+ PathRadiance *PathRadiance_coop, /* Required for "kernel_write_data_passes" and indirect primitive emission */
+ ccl_global PathState *PathState_coop, /* Required throughout the kernel and AO */
+ Intersection *Intersection_coop, /* Required for indirect primitive emission */
+ ccl_global float3 *AOAlpha_coop, /* Required for AO */
+ ccl_global float3 *AOBSDF_coop, /* Required for AO */
+ ccl_global Ray *AOLightRay_coop, /* Required for AO */
+ int sw, int sh, int sx, int sy, int stride,
+ ccl_global char *ray_state, /* Denotes the state of each ray */
+ ccl_global unsigned int *work_array, /* Denotes the work that each ray belongs to */
+#ifdef __WORK_STEALING__
+ unsigned int start_sample,
+#endif
+ int parallel_samples, /* Number of samples to be processed in parallel */
+ int ray_index,
+ char *enqueue_flag,
+ char *enqueue_flag_AO_SHADOW_RAY_CAST)
+{
+ /* Load kernel globals structure and ShaderData structure */
+ KernelGlobals *kg = (KernelGlobals *)globals;
+ ShaderData *sd = (ShaderData *)shader_data;
+
+#ifdef __WORK_STEALING__
+ unsigned int my_work;
+ unsigned int pixel_x;
+ unsigned int pixel_y;
+#endif
+ unsigned int tile_x;
+ unsigned int tile_y;
+ int my_sample_tile;
+ unsigned int sample;
+
+ ccl_global RNG *rng = 0x0;
+ ccl_global PathState *state = 0x0;
+ float3 throughput;
+
+ if(IS_STATE(ray_state, ray_index, RAY_ACTIVE)) {
+
+ throughput = throughput_coop[ray_index];
+ state = &PathState_coop[ray_index];
+ rng = &rng_coop[ray_index];
+#ifdef __WORK_STEALING__
+ my_work = work_array[ray_index];
+ sample = get_my_sample(my_work, sw, sh, parallel_samples, ray_index) + start_sample;
+ get_pixel_tile_position(&pixel_x, &pixel_y,
+ &tile_x, &tile_y,
+ my_work,
+ sw, sh, sx, sy,
+ parallel_samples,
+ ray_index);
+ my_sample_tile = 0;
+#else /* __WORK_STEALING__ */
+ sample = work_array[ray_index];
+ /* Buffer's stride is "stride"; Find x and y using ray_index. */
+ int tile_index = ray_index / parallel_samples;
+ tile_x = tile_index % sw;
+ tile_y = tile_index / sw;
+ my_sample_tile = ray_index - (tile_index * parallel_samples);
+#endif /* __WORK_STEALING__ */
+ per_sample_output_buffers +=
+ (((tile_x + (tile_y * stride)) * parallel_samples) + my_sample_tile) *
+ kernel_data.film.pass_stride;
+
+ /* holdout */
+#ifdef __HOLDOUT__
+ if((ccl_fetch(sd, flag) & (SD_HOLDOUT|SD_HOLDOUT_MASK)) &&
+ (state->flag & PATH_RAY_CAMERA))
+ {
+ if(kernel_data.background.transparent) {
+ float3 holdout_weight;
+
+ if(ccl_fetch(sd, flag) & SD_HOLDOUT_MASK)
+ holdout_weight = make_float3(1.0f, 1.0f, 1.0f);
+ else
+ holdout_weight = shader_holdout_eval(kg, sd);
+
+ /* any throughput is ok, should all be identical here */
+ L_transparent_coop[ray_index] += average(holdout_weight*throughput);
+ }
+
+ if(ccl_fetch(sd, flag) & SD_HOLDOUT_MASK) {
+ ASSIGN_RAY_STATE(ray_state, ray_index, RAY_UPDATE_BUFFER);
+ *enqueue_flag = 1;
+ }
+ }
+#endif /* __HOLDOUT__ */
+ }
+
+ if(IS_STATE(ray_state, ray_index, RAY_ACTIVE)) {
+ PathRadiance *L = &PathRadiance_coop[ray_index];
+ /* Holdout mask objects do not write data passes. */
+ kernel_write_data_passes(kg,
+ per_sample_output_buffers,
+ L,
+ sd,
+ sample,
+ state,
+ throughput);
+ /* Blurring of bsdf after bounces, for rays that have a small likelihood
+ * of following this particular path (diffuse, rough glossy.
+ */
+ if(kernel_data.integrator.filter_glossy != FLT_MAX) {
+ float blur_pdf = kernel_data.integrator.filter_glossy*state->min_ray_pdf;
+ if(blur_pdf < 1.0f) {
+ float blur_roughness = sqrtf(1.0f - blur_pdf)*0.5f;
+ shader_bsdf_blur(kg, sd, blur_roughness);
+ }
+ }
+
+#ifdef __EMISSION__
+ /* emission */
+ if(ccl_fetch(sd, flag) & SD_EMISSION) {
+ /* TODO(sergey): is isect.t wrong here for transparent surfaces? */
+ float3 emission = indirect_primitive_emission(
+ kg,
+ sd,
+ Intersection_coop[ray_index].t,
+ state->flag,
+ state->ray_pdf);
+ path_radiance_accum_emission(L, throughput, emission, state->bounce);
+ }
+#endif /* __EMISSION__ */
+
+ /* Path termination. this is a strange place to put the termination, it's
+ * mainly due to the mixed in MIS that we use. gives too many unneeded
+ * shader evaluations, only need emission if we are going to terminate.
+ */
+ float probability = path_state_terminate_probability(kg, state, throughput);
+
+ if(probability == 0.0f) {
+ ASSIGN_RAY_STATE(ray_state, ray_index, RAY_UPDATE_BUFFER);
+ *enqueue_flag = 1;
+ }
+
+ if(IS_STATE(ray_state, ray_index, RAY_ACTIVE)) {
+ if(probability != 1.0f) {
+ float terminate = path_state_rng_1D_for_decision(kg, rng, state, PRNG_TERMINATE);
+ if(terminate >= probability) {
+ ASSIGN_RAY_STATE(ray_state, ray_index, RAY_UPDATE_BUFFER);
+ *enqueue_flag = 1;
+ } else {
+ throughput_coop[ray_index] = throughput/probability;
+ }
+ }
+ }
+ }
+
+#ifdef __AO__
+ if(IS_STATE(ray_state, ray_index, RAY_ACTIVE)) {
+ /* ambient occlusion */
+ if(kernel_data.integrator.use_ambient_occlusion ||
+ (ccl_fetch(sd, flag) & SD_AO))
+ {
+ /* todo: solve correlation */
+ float bsdf_u, bsdf_v;
+ path_state_rng_2D(kg, rng, state, PRNG_BSDF_U, &bsdf_u, &bsdf_v);
+
+ float ao_factor = kernel_data.background.ao_factor;
+ float3 ao_N;
+ AOBSDF_coop[ray_index] = shader_bsdf_ao(kg, sd, ao_factor, &ao_N);
+ AOAlpha_coop[ray_index] = shader_bsdf_alpha(kg, sd);
+
+ float3 ao_D;
+ float ao_pdf;
+ sample_cos_hemisphere(ao_N, bsdf_u, bsdf_v, &ao_D, &ao_pdf);
+
+ if(dot(ccl_fetch(sd, Ng), ao_D) > 0.0f && ao_pdf != 0.0f) {
+ Ray _ray;
+ _ray.P = ray_offset(ccl_fetch(sd, P), ccl_fetch(sd, Ng));
+ _ray.D = ao_D;
+ _ray.t = kernel_data.background.ao_distance;
+#ifdef __OBJECT_MOTION__
+ _ray.time = ccl_fetch(sd, time);
+#endif
+ _ray.dP = ccl_fetch(sd, dP);
+ _ray.dD = differential3_zero();
+ AOLightRay_coop[ray_index] = _ray;
+
+ ADD_RAY_FLAG(ray_state, ray_index, RAY_SHADOW_RAY_CAST_AO);
+ *enqueue_flag_AO_SHADOW_RAY_CAST = 1;
+ }
+ }
+ }
+#endif /* __AO__ */
+}
diff --git a/intern/cycles/kernel/split/kernel_lamp_emission.h b/intern/cycles/kernel/split/kernel_lamp_emission.h
new file mode 100644
index 00000000000..a8e4b0a06c8
--- /dev/null
+++ b/intern/cycles/kernel/split/kernel_lamp_emission.h
@@ -0,0 +1,179 @@
+/*
+ * Copyright 2011-2015 Blender Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "kernel_split_common.h"
+
+/* Note on kernel_lamp_emission
+ * This is the 3rd kernel in the ray-tracing logic. This is the second of the
+ * path-iteration kernels. This kernel takes care of the indirect lamp emission logic.
+ * This kernel operates on QUEUE_ACTIVE_AND_REGENERATED_RAYS. It processes rays of state RAY_ACTIVE
+ * and RAY_HIT_BACKGROUND.
+ * We will empty QUEUE_ACTIVE_AND_REGENERATED_RAYS queue in this kernel.
+ * The input/output of the kernel is as follows,
+ * Throughput_coop ------------------------------------|--- kernel_lamp_emission --|--- PathRadiance_coop
+ * Ray_coop -------------------------------------------| |--- Queue_data(QUEUE_ACTIVE_AND_REGENERATED_RAYS)
+ * PathState_coop -------------------------------------| |--- Queue_index(QUEUE_ACTIVE_AND_REGENERATED_RAYS)
+ * kg (globals + data) --------------------------------| |
+ * Intersection_coop ----------------------------------| |
+ * ray_state ------------------------------------------| |
+ * Queue_data (QUEUE_ACTIVE_AND_REGENERATED_RAYS) -----| |
+ * Queue_index (QUEUE_ACTIVE_AND_REGENERATED_RAYS) ----| |
+ * queuesize ------------------------------------------| |
+ * use_queues_flag ------------------------------------| |
+ * sw -------------------------------------------------| |
+ * sh -------------------------------------------------| |
+ * parallel_samples -----------------------------------| |
+ *
+ * note : shader_data is neither input nor output. Its just filled and consumed in the same, kernel_lamp_emission, kernel.
+ */
+ccl_device void kernel_lamp_emission(
+ ccl_global char *globals,
+ ccl_constant KernelData *data,
+ ccl_global char *shader_data, /* Required for lamp emission */
+ ccl_global float3 *throughput_coop, /* Required for lamp emission */
+ PathRadiance *PathRadiance_coop, /* Required for lamp emission */
+ ccl_global Ray *Ray_coop, /* Required for lamp emission */
+ ccl_global PathState *PathState_coop, /* Required for lamp emission */
+ Intersection *Intersection_coop, /* Required for lamp emission */
+ ccl_global char *ray_state, /* Denotes the state of each ray */
+ int sw, int sh,
+ ccl_global char *use_queues_flag, /* Used to decide if this kernel should use
+ * queues to fetch ray index
+ */
+ int parallel_samples, /* Number of samples to be processed in parallel */
+ int ray_index)
+{
+ if(IS_STATE(ray_state, ray_index, RAY_ACTIVE) ||
+ IS_STATE(ray_state, ray_index, RAY_HIT_BACKGROUND))
+ {
+ KernelGlobals *kg = (KernelGlobals *)globals;
+ ShaderData *sd = (ShaderData *)shader_data;
+ PathRadiance *L = &PathRadiance_coop[ray_index];
+
+ float3 throughput = throughput_coop[ray_index];
+ Ray ray = Ray_coop[ray_index];
+ PathState state = PathState_coop[ray_index];
+
+#ifdef __LAMP_MIS__
+ if(kernel_data.integrator.use_lamp_mis && !(state.flag & PATH_RAY_CAMERA)) {
+ /* ray starting from previous non-transparent bounce */
+ Ray light_ray;
+
+ light_ray.P = ray.P - state.ray_t*ray.D;
+ state.ray_t += Intersection_coop[ray_index].t;
+ light_ray.D = ray.D;
+ light_ray.t = state.ray_t;
+ light_ray.time = ray.time;
+ light_ray.dD = ray.dD;
+ light_ray.dP = ray.dP;
+ /* intersect with lamp */
+ float3 emission;
+
+ if(indirect_lamp_emission(kg, &state, &light_ray, &emission, sd)) {
+ path_radiance_accum_emission(L, throughput, emission, state.bounce);
+ }
+ }
+#endif /* __LAMP_MIS__ */
+
+ /* __VOLUME__ feature is disabled */
+#if 0
+#ifdef __VOLUME__
+ /* volume attenuation, emission, scatter */
+ if(state.volume_stack[0].shader != SHADER_NONE) {
+ Ray volume_ray = ray;
+ volume_ray.t = (hit)? isect.t: FLT_MAX;
+
+ bool heterogeneous = volume_stack_is_heterogeneous(kg, state.volume_stack);
+
+#ifdef __VOLUME_DECOUPLED__
+ int sampling_method = volume_stack_sampling_method(kg, state.volume_stack);
+ bool decoupled = kernel_volume_use_decoupled(kg, heterogeneous, true, sampling_method);
+
+ if(decoupled) {
+ /* cache steps along volume for repeated sampling */
+ VolumeSegment volume_segment;
+ ShaderData volume_sd;
+
+ shader_setup_from_volume(kg, &volume_sd, &volume_ray, state.bounce, state.transparent_bounce);
+ kernel_volume_decoupled_record(kg, &state,
+ &volume_ray, &volume_sd, &volume_segment, heterogeneous);
+
+ volume_segment.sampling_method = sampling_method;
+
+ /* emission */
+ if(volume_segment.closure_flag & SD_EMISSION)
+ path_radiance_accum_emission(&L, throughput, volume_segment.accum_emission, state.bounce);
+
+ /* scattering */
+ VolumeIntegrateResult result = VOLUME_PATH_ATTENUATED;
+
+ if(volume_segment.closure_flag & SD_SCATTER) {
+ bool all = false;
+
+ /* direct light sampling */
+ kernel_branched_path_volume_connect_light(kg, rng, &volume_sd,
+ throughput, &state, &L, 1.0f, all, &volume_ray, &volume_segment);
+
+ /* indirect sample. if we use distance sampling and take just
+ * one sample for direct and indirect light, we could share
+ * this computation, but makes code a bit complex */
+ float rphase = path_state_rng_1D_for_decision(kg, rng, &state, PRNG_PHASE);
+ float rscatter = path_state_rng_1D_for_decision(kg, rng, &state, PRNG_SCATTER_DISTANCE);
+
+ result = kernel_volume_decoupled_scatter(kg,
+ &state, &volume_ray, &volume_sd, &throughput,
+ rphase, rscatter, &volume_segment, NULL, true);
+ }
+
+ if(result != VOLUME_PATH_SCATTERED)
+ throughput *= volume_segment.accum_transmittance;
+
+ /* free cached steps */
+ kernel_volume_decoupled_free(kg, &volume_segment);
+
+ if(result == VOLUME_PATH_SCATTERED) {
+ if(kernel_path_volume_bounce(kg, rng, &volume_sd, &throughput, &state, &L, &ray))
+ continue;
+ else
+ break;
+ }
+ }
+ else
+#endif /* __VOLUME_DECOUPLED__ */
+ {
+ /* integrate along volume segment with distance sampling */
+ ShaderData volume_sd;
+ VolumeIntegrateResult result = kernel_volume_integrate(
+ kg, &state, &volume_sd, &volume_ray, &L, &throughput, rng, heterogeneous);
+
+#ifdef __VOLUME_SCATTER__
+ if(result == VOLUME_PATH_SCATTERED) {
+ /* direct lighting */
+ kernel_path_volume_connect_light(kg, rng, &volume_sd, throughput, &state, &L);
+
+ /* indirect light bounce */
+ if(kernel_path_volume_bounce(kg, rng, &volume_sd, &throughput, &state, &L, &ray))
+ continue;
+ else
+ break;
+ }
+#endif /* __VOLUME_SCATTER__ */
+ }
+ }
+#endif /* __VOLUME__ */
+#endif
+ }
+}
diff --git a/intern/cycles/kernel/split/kernel_next_iteration_setup.h b/intern/cycles/kernel/split/kernel_next_iteration_setup.h
new file mode 100644
index 00000000000..e1a1577d7ae
--- /dev/null
+++ b/intern/cycles/kernel/split/kernel_next_iteration_setup.h
@@ -0,0 +1,144 @@
+/*
+ * Copyright 2011-2015 Blender Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "kernel_split_common.h"
+
+/* Note on kernel_setup_next_iteration kernel.
+ * This is the tenth kernel in the ray tracing logic. This is the ninth
+ * of the path iteration kernels. This kernel takes care of setting up
+ * Ray for the next iteration of path-iteration and accumulating radiance
+ * corresponding to AO and direct-lighting
+ *
+ * Ray state of rays that are terminated in this kernel are changed to RAY_UPDATE_BUFFER
+ *
+ * The input and output are as follows,
+ *
+ * rng_coop ---------------------------------------------|--- kernel_next_iteration_setup -|--- Queue_index (QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS)
+ * throughput_coop --------------------------------------| |--- Queue_data (QUEUE_HITBF_BUFF_UPDATE_TOREGEN_RAYS)
+ * PathRadiance_coop ------------------------------------| |--- throughput_coop
+ * PathState_coop ---------------------------------------| |--- PathRadiance_coop
+ * shader_data ------------------------------------------| |--- PathState_coop
+ * ray_state --------------------------------------------| |--- ray_state
+ * Queue_data (QUEUE_ACTIVE_AND_REGENERATD_RAYS) --------| |--- Ray_coop
+ * Queue_index (QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS) ---| |--- use_queues_flag
+ * Ray_coop ---------------------------------------------| |
+ * kg (globals + data) ----------------------------------| |
+ * LightRay_dl_coop -------------------------------------|
+ * ISLamp_coop ------------------------------------------|
+ * BSDFEval_coop ----------------------------------------|
+ * LightRay_ao_coop -------------------------------------|
+ * AOBSDF_coop ------------------------------------------|
+ * AOAlpha_coop -----------------------------------------|
+ *
+ * Note on queues,
+ * This kernel fetches rays from the queue QUEUE_ACTIVE_AND_REGENERATED_RAYS and processes only
+ * the rays of state RAY_ACTIVE.
+ * There are different points in this kernel where a ray may terminate and reach RAY_UPDATE_BUFF
+ * state. These rays are enqueued into QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS queue. These rays will
+ * still be present in QUEUE_ACTIVE_AND_REGENERATED_RAYS queue, but since their ray-state has been
+ * changed to RAY_UPDATE_BUFF, there is no problem.
+ *
+ * State of queues when this kernel is called :
+ * At entry,
+ * QUEUE_ACTIVE_AND_REGENERATED_RAYS will be filled with RAY_ACTIVE, RAY_REGENERATED, RAY_UPDATE_BUFFER rays.
+ * QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS will be filled with RAY_TO_REGENERATE and RAY_UPDATE_BUFFER rays
+ * At exit,
+ * QUEUE_ACTIVE_AND_REGENERATED_RAYS will be filled with RAY_ACTIVE, RAY_REGENERATED and more RAY_UPDATE_BUFFER rays.
+ * QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS will be filled with RAY_TO_REGENERATE and more RAY_UPDATE_BUFFER rays
+ */
+ccl_device char kernel_next_iteration_setup(
+ ccl_global char *globals,
+ ccl_constant KernelData *data,
+ ccl_global char *shader_data, /* Required for setting up ray for next iteration */
+ ccl_global uint *rng_coop, /* Required for setting up ray for next iteration */
+ ccl_global float3 *throughput_coop, /* Required for setting up ray for next iteration */
+ PathRadiance *PathRadiance_coop, /* Required for setting up ray for next iteration */
+ ccl_global Ray *Ray_coop, /* Required for setting up ray for next iteration */
+ ccl_global PathState *PathState_coop, /* Required for setting up ray for next iteration */
+ ccl_global Ray *LightRay_dl_coop, /* Required for radiance update - direct lighting */
+ ccl_global int *ISLamp_coop, /* Required for radiance update - direct lighting */
+ ccl_global BsdfEval *BSDFEval_coop, /* Required for radiance update - direct lighting */
+ ccl_global Ray *LightRay_ao_coop, /* Required for radiance update - AO */
+ ccl_global float3 *AOBSDF_coop, /* Required for radiance update - AO */
+ ccl_global float3 *AOAlpha_coop, /* Required for radiance update - AO */
+ ccl_global char *ray_state, /* Denotes the state of each ray */
+ ccl_global char *use_queues_flag, /* flag to decide if scene_intersect kernel should
+ * use queues to fetch ray index */
+ int ray_index)
+{
+ char enqueue_flag = 0;
+
+ /* Load kernel globals structure and ShaderData structure. */
+ KernelGlobals *kg = (KernelGlobals *)globals;
+ ShaderData *sd = (ShaderData *)shader_data;
+ PathRadiance *L = 0x0;
+ ccl_global PathState *state = 0x0;
+
+ /* Path radiance update for AO/Direct_lighting's shadow blocked. */
+ if(IS_FLAG(ray_state, ray_index, RAY_SHADOW_RAY_CAST_DL) ||
+ IS_FLAG(ray_state, ray_index, RAY_SHADOW_RAY_CAST_AO))
+ {
+ state = &PathState_coop[ray_index];
+ L = &PathRadiance_coop[ray_index];
+ float3 _throughput = throughput_coop[ray_index];
+
+ if(IS_FLAG(ray_state, ray_index, RAY_SHADOW_RAY_CAST_AO)) {
+ float3 shadow = LightRay_ao_coop[ray_index].P;
+ char update_path_radiance = LightRay_ao_coop[ray_index].t;
+ if(update_path_radiance) {
+ path_radiance_accum_ao(L,
+ _throughput,
+ AOAlpha_coop[ray_index],
+ AOBSDF_coop[ray_index],
+ shadow,
+ state->bounce);
+ }
+ REMOVE_RAY_FLAG(ray_state, ray_index, RAY_SHADOW_RAY_CAST_AO);
+ }
+
+ if(IS_FLAG(ray_state, ray_index, RAY_SHADOW_RAY_CAST_DL)) {
+ float3 shadow = LightRay_dl_coop[ray_index].P;
+ char update_path_radiance = LightRay_dl_coop[ray_index].t;
+ if(update_path_radiance) {
+ BsdfEval L_light = BSDFEval_coop[ray_index];
+ path_radiance_accum_light(L,
+ _throughput,
+ &L_light,
+ shadow,
+ 1.0f,
+ state->bounce,
+ ISLamp_coop[ray_index]);
+ }
+ REMOVE_RAY_FLAG(ray_state, ray_index, RAY_SHADOW_RAY_CAST_DL);
+ }
+ }
+
+ if(IS_STATE(ray_state, ray_index, RAY_ACTIVE)) {
+ ccl_global float3 *throughput = &throughput_coop[ray_index];
+ ccl_global Ray *ray = &Ray_coop[ray_index];
+ ccl_global RNG* rng = &rng_coop[ray_index];
+ state = &PathState_coop[ray_index];
+ L = &PathRadiance_coop[ray_index];
+
+ /* Compute direct lighting and next bounce. */
+ if(!kernel_path_surface_bounce(kg, rng, sd, throughput, state, L, ray)) {
+ ASSIGN_RAY_STATE(ray_state, ray_index, RAY_UPDATE_BUFFER);
+ enqueue_flag = 1;
+ }
+ }
+
+ return enqueue_flag;
+}
diff --git a/intern/cycles/kernel/split/kernel_scene_intersect.h b/intern/cycles/kernel/split/kernel_scene_intersect.h
new file mode 100644
index 00000000000..7eb201ecf32
--- /dev/null
+++ b/intern/cycles/kernel/split/kernel_scene_intersect.h
@@ -0,0 +1,138 @@
+/*
+ * Copyright 2011-2015 Blender Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "kernel_split_common.h"
+
+/* Note on kernel_scene_intersect kernel.
+ * This is the second kernel in the ray tracing logic. This is the first
+ * of the path iteration kernels. This kernel takes care of scene_intersect function.
+ *
+ * This kernel changes the ray_state of RAY_REGENERATED rays to RAY_ACTIVE.
+ * This kernel processes rays of ray state RAY_ACTIVE
+ * This kernel determines the rays that have hit the background and changes their ray state to RAY_HIT_BACKGROUND.
+ *
+ * The input and output are as follows,
+ *
+ * Ray_coop ---------------------------------------|--------- kernel_scene_intersect----------|--- PathState
+ * PathState_coop ---------------------------------| |--- Intersection
+ * ray_state --------------------------------------| |--- ray_state
+ * use_queues_flag --------------------------------| |
+ * parallel_samples -------------------------------| |
+ * QueueData(QUEUE_ACTIVE_AND_REGENERATED_RAYS) ---| |
+ * kg (data + globals) ----------------------------| |
+ * rng_coop ---------------------------------------| |
+ * sw ---------------------------------------------| |
+ * sh ---------------------------------------------| |
+ * queuesize --------------------------------------| |
+ *
+ * Note on Queues :
+ * Ideally we would want kernel_scene_intersect to work on queues.
+ * But during the very first time, the queues will be empty and hence we perform a direct mapping
+ * between ray-index and thread-index; From the next time onward, the queue will be filled and
+ * we may start operating on queues.
+ *
+ * State of queue during the first time this kernel is called :
+ * QUEUE_ACTIVE_AND_REGENERATED_RAYS and QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS will be empty.before and after this kernel
+ *
+ * State of queues during other times this kernel is called :
+ * At entry,
+ * QUEUE_ACTIVE_AND_REGENERATED_RAYS will have a mix of RAY_ACTIVE, RAY_UPDATE_BUFFER and RAY_REGENERATED rays;
+ * QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS will be filled with RAY_TO_REGENERATE and RAY_UPDATE_BUFFER rays ;
+ * (The rays that are in the state RAY_UPDATE_BUFFER in both the queues are actually the same rays; These
+ * are the rays that were in RAY_ACTIVE state during the initial enqueue but on further processing
+ * , by different kernels, have turned into RAY_UPDATE_BUFFER rays. Since all kernel, even after fetching from
+ * QUEUE_ACTIVE_AND_REGENERATED_RAYS, proceed further based on ray state information, RAY_UPDATE_BUFFER rays
+ * being present in QUEUE_ACTIVE_AND_REGENERATED_RAYS does not cause any logical issues)
+ * At exit,
+ * QUEUE_ACTIVE_AND_REGENERATED_RAYS - All RAY_REGENERATED rays will have been converted to RAY_ACTIVE and
+ * Some rays in QUEUE_ACTIVE_AND_REGENERATED_RAYS queue will move to state RAY_HIT_BACKGROUND
+ * QUEUE_HITBF_BUFF_UPDATE_TOREGEN_RAYS - no change
+ */
+
+ccl_device void kernel_scene_intersect(
+ ccl_global char *globals,
+ ccl_constant KernelData *data,
+ ccl_global uint *rng_coop,
+ ccl_global Ray *Ray_coop, /* Required for scene_intersect */
+ ccl_global PathState *PathState_coop, /* Required for scene_intersect */
+ Intersection *Intersection_coop, /* Required for scene_intersect */
+ ccl_global char *ray_state, /* Denotes the state of each ray */
+ int sw, int sh,
+ ccl_global char *use_queues_flag, /* used to decide if this kernel should use
+ * queues to fetch ray index */
+#ifdef __KERNEL_DEBUG__
+ DebugData *debugdata_coop,
+#endif
+ int parallel_samples, /* Number of samples to be processed in parallel */
+ int ray_index)
+{
+ /* All regenerated rays become active here */
+ if(IS_STATE(ray_state, ray_index, RAY_REGENERATED))
+ ASSIGN_RAY_STATE(ray_state, ray_index, RAY_ACTIVE);
+
+ if(!IS_STATE(ray_state, ray_index, RAY_ACTIVE))
+ return;
+
+ /* Load kernel globals structure */
+ KernelGlobals *kg = (KernelGlobals *)globals;
+
+#ifdef __KERNEL_DEBUG__
+ DebugData *debug_data = &debugdata_coop[ray_index];
+#endif
+ Intersection *isect = &Intersection_coop[ray_index];
+ PathState state = PathState_coop[ray_index];
+ Ray ray = Ray_coop[ray_index];
+
+ /* intersect scene */
+ uint visibility = path_state_ray_visibility(kg, &state);
+
+#ifdef __HAIR__
+ float difl = 0.0f, extmax = 0.0f;
+ uint lcg_state = 0;
+ RNG rng = rng_coop[ray_index];
+
+ if(kernel_data.bvh.have_curves) {
+ if((kernel_data.cam.resolution == 1) && (state.flag & PATH_RAY_CAMERA)) {
+ float3 pixdiff = ray.dD.dx + ray.dD.dy;
+ /*pixdiff = pixdiff - dot(pixdiff, ray.D)*ray.D;*/
+ difl = kernel_data.curve.minimum_width * len(pixdiff) * 0.5f;
+ }
+
+ extmax = kernel_data.curve.maximum_width;
+ lcg_state = lcg_state_init(&rng, &state, 0x51633e2d);
+ }
+
+ bool hit = scene_intersect(kg, &ray, visibility, isect, &lcg_state, difl, extmax);
+#else
+ bool hit = scene_intersect(kg, &ray, visibility, isect, NULL, 0.0f, 0.0f);
+#endif
+
+#ifdef __KERNEL_DEBUG__
+ if(state.flag & PATH_RAY_CAMERA) {
+ debug_data->num_bvh_traversal_steps += isect->num_traversal_steps;
+ debug_data->num_bvh_traversed_instances += isect->num_traversed_instances;
+ }
+ debug_data->num_ray_bounces++;
+#endif
+
+ if(!hit) {
+ /* Change the state of rays that hit the background;
+ * These rays undergo special processing in the
+ * background_bufferUpdate kernel.
+ */
+ ASSIGN_RAY_STATE(ray_state, ray_index, RAY_HIT_BACKGROUND);
+ }
+}
diff --git a/intern/cycles/kernel/split/kernel_shader_eval.h b/intern/cycles/kernel/split/kernel_shader_eval.h
new file mode 100644
index 00000000000..e6fdc592586
--- /dev/null
+++ b/intern/cycles/kernel/split/kernel_shader_eval.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2011-2015 Blender Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "kernel_split_common.h"
+
+/* Note on kernel_shader_eval kernel
+ * This kernel is the 5th kernel in the ray tracing logic. This is
+ * the 4rd kernel in path iteration. This kernel sets up the ShaderData
+ * structure from the values computed by the previous kernels. It also identifies
+ * the rays of state RAY_TO_REGENERATE and enqueues them in QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS queue.
+ *
+ * The input and output of the kernel is as follows,
+ * rng_coop -------------------------------------------|--- kernel_shader_eval --|--- shader_data
+ * Ray_coop -------------------------------------------| |--- Queue_data (QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS)
+ * PathState_coop -------------------------------------| |--- Queue_index (QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS)
+ * Intersection_coop ----------------------------------| |
+ * Queue_data (QUEUE_ACTIVE_AND_REGENERATD_RAYS)-------| |
+ * Queue_index(QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS)---| |
+ * ray_state ------------------------------------------| |
+ * kg (globals + data) --------------------------------| |
+ * queuesize ------------------------------------------| |
+ *
+ * Note on Queues :
+ * This kernel reads from the QUEUE_ACTIVE_AND_REGENERATED_RAYS queue and processes
+ * only the rays of state RAY_ACTIVE;
+ * State of queues when this kernel is called,
+ * at entry,
+ * QUEUE_ACTIVE_AND_REGENERATED_RAYS will be filled with RAY_ACTIVE and RAY_REGENERATED rays
+ * QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS will be empty.
+ * at exit,
+ * QUEUE_ACTIVE_AND_REGENERATED_RAYS will be filled with RAY_ACTIVE and RAY_REGENERATED rays
+ * QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS will be filled with RAY_TO_REGENERATE rays
+ */
+ccl_device void kernel_shader_eval(
+ ccl_global char *globals,
+ ccl_constant KernelData *data,
+ ccl_global char *shader_data, /* Output ShaderData structure to be filled */
+ ccl_global uint *rng_coop, /* Required for rbsdf calculation */
+ ccl_global Ray *Ray_coop, /* Required for setting up shader from ray */
+ ccl_global PathState *PathState_coop, /* Required for all functions in this kernel */
+ Intersection *Intersection_coop, /* Required for setting up shader from ray */
+ ccl_global char *ray_state, /* Denotes the state of each ray */
+ int ray_index)
+{
+ if(IS_STATE(ray_state, ray_index, RAY_ACTIVE)) {
+ KernelGlobals *kg = (KernelGlobals *)globals;
+ ShaderData *sd = (ShaderData *)shader_data;
+ Intersection *isect = &Intersection_coop[ray_index];
+ ccl_global uint *rng = &rng_coop[ray_index];
+ ccl_global PathState *state = &PathState_coop[ray_index];
+ Ray ray = Ray_coop[ray_index];
+
+ shader_setup_from_ray(kg,
+ sd,
+ isect,
+ &ray,
+ state->bounce,
+ state->transparent_bounce);
+ float rbsdf = path_state_rng_1D_for_decision(kg, rng, state, PRNG_BSDF);
+ shader_eval_surface(kg, sd, rbsdf, state->flag, SHADER_CONTEXT_MAIN);
+ }
+}
diff --git a/intern/cycles/kernel/split/kernel_shadow_blocked.h b/intern/cycles/kernel/split/kernel_shadow_blocked.h
new file mode 100644
index 00000000000..28351c2b1ae
--- /dev/null
+++ b/intern/cycles/kernel/split/kernel_shadow_blocked.h
@@ -0,0 +1,99 @@
+/*
+ * Copyright 2011-2015 Blender Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "kernel_split_common.h"
+
+/* Note on kernel_shadow_blocked kernel.
+ * This is the ninth kernel in the ray tracing logic. This is the eighth
+ * of the path iteration kernels. This kernel takes care of "shadow ray cast"
+ * logic of the direct lighting and AO part of ray tracing.
+ *
+ * The input and output are as follows,
+ *
+ * PathState_coop ----------------------------------|--- kernel_shadow_blocked --|
+ * LightRay_dl_coop --------------------------------| |--- LightRay_dl_coop
+ * LightRay_ao_coop --------------------------------| |--- LightRay_ao_coop
+ * ray_state ---------------------------------------| |--- ray_state
+ * Queue_data(QUEUE_SHADOW_RAY_CAST_AO_RAYS & | |--- Queue_data (QUEUE_SHADOW_RAY_CAST_AO_RAYS & QUEUE_SHADOW_RAY_CAST_AO_RAYS)
+ QUEUE_SHADOW_RAY_CAST_DL_RAYS) -------| |
+ * Queue_index(QUEUE_SHADOW_RAY_CAST_AO_RAYS&
+ QUEUE_SHADOW_RAY_CAST_DL_RAYS) -------| |
+ * kg (globals + data) -----------------------------| |
+ * queuesize ---------------------------------------| |
+ *
+ * Note on shader_shadow : shader_shadow is neither input nor output to this kernel. shader_shadow is filled and consumed in this kernel itself.
+ * Note on queues :
+ * The kernel fetches from QUEUE_SHADOW_RAY_CAST_AO_RAYS and QUEUE_SHADOW_RAY_CAST_DL_RAYS queues. We will empty
+ * these queues this kernel.
+ * State of queues when this kernel is called :
+ * state of queues QUEUE_ACTIVE_AND_REGENERATED_RAYS and QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS will be same
+ * before and after this kernel call.
+ * QUEUE_SHADOW_RAY_CAST_AO_RAYS & QUEUE_SHADOW_RAY_CAST_DL_RAYS will be filled with rays marked with flags RAY_SHADOW_RAY_CAST_AO
+ * and RAY_SHADOW_RAY_CAST_DL respectively, during kernel entry.
+ * QUEUE_SHADOW_RAY_CAST_AO_RAYS and QUEUE_SHADOW_RAY_CAST_DL_RAYS will be empty at kernel exit.
+ */
+ccl_device void kernel_shadow_blocked(
+ ccl_global char *globals,
+ ccl_constant KernelData *data,
+ ccl_global char *shader_shadow, /* Required for shadow blocked */
+ ccl_global PathState *PathState_coop, /* Required for shadow blocked */
+ ccl_global Ray *LightRay_dl_coop, /* Required for direct lighting's shadow blocked */
+ ccl_global Ray *LightRay_ao_coop, /* Required for AO's shadow blocked */
+ Intersection *Intersection_coop_AO,
+ Intersection *Intersection_coop_DL,
+ ccl_global char *ray_state,
+ int total_num_rays,
+ char shadow_blocked_type,
+ int ray_index)
+{
+ /* Flag determining if we need to update L. */
+ char update_path_radiance = 0;
+
+ if(IS_FLAG(ray_state, ray_index, RAY_SHADOW_RAY_CAST_DL) ||
+ IS_FLAG(ray_state, ray_index, RAY_SHADOW_RAY_CAST_AO))
+ {
+ /* Load kernel global structure. */
+ KernelGlobals *kg = (KernelGlobals *)globals;
+ ShaderData *sd_shadow = (ShaderData *)shader_shadow;
+
+ ccl_global PathState *state = &PathState_coop[ray_index];
+ ccl_global Ray *light_ray_dl_global = &LightRay_dl_coop[ray_index];
+ ccl_global Ray *light_ray_ao_global = &LightRay_ao_coop[ray_index];
+ Intersection *isect_ao_global = &Intersection_coop_AO[ray_index];
+ Intersection *isect_dl_global = &Intersection_coop_DL[ray_index];
+
+ ccl_global Ray *light_ray_global =
+ shadow_blocked_type == RAY_SHADOW_RAY_CAST_AO
+ ? light_ray_ao_global
+ : light_ray_dl_global;
+ Intersection *isect_global =
+ RAY_SHADOW_RAY_CAST_AO ? isect_ao_global : isect_dl_global;
+
+ float3 shadow;
+ update_path_radiance = !(shadow_blocked(kg,
+ state,
+ light_ray_global,
+ &shadow,
+ sd_shadow,
+ isect_global));
+
+ /* We use light_ray_global's P and t to store shadow and
+ * update_path_radiance.
+ */
+ light_ray_global->P = shadow;
+ light_ray_global->t = update_path_radiance;
+ }
+}
diff --git a/intern/cycles/kernel/split/kernel_split_common.h b/intern/cycles/kernel/split/kernel_split_common.h
new file mode 100644
index 00000000000..e1c7e2cea99
--- /dev/null
+++ b/intern/cycles/kernel/split/kernel_split_common.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2011-2015 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 __KERNEL_SPLIT_H__
+#define __KERNEL_SPLIT_H__
+
+#include "kernel_compat_opencl.h"
+#include "kernel_math.h"
+#include "kernel_types.h"
+#include "kernel_globals.h"
+
+#include "util_atomic.h"
+
+#include "kernel_random.h"
+#include "kernel_projection.h"
+#include "kernel_montecarlo.h"
+#include "kernel_differential.h"
+#include "kernel_camera.h"
+
+#include "geom/geom.h"
+
+#include "kernel_accumulate.h"
+#include "kernel_shader.h"
+#include "kernel_light.h"
+#include "kernel_passes.h"
+
+#ifdef __SUBSURFACE__
+#include "kernel_subsurface.h"
+#endif
+
+#ifdef __VOLUME__
+#include "kernel_volume.h"
+#endif
+
+#include "kernel_path_state.h"
+#include "kernel_shadow.h"
+#include "kernel_emission.h"
+#include "kernel_path_common.h"
+#include "kernel_path_surface.h"
+#include "kernel_path_volume.h"
+
+#ifdef __KERNEL_DEBUG__
+#include "kernel_debug.h"
+#endif
+
+#include "kernel_queues.h"
+#include "kernel_work_stealing.h"
+
+#endif /* __KERNEL_SPLIT_H__ */
diff --git a/intern/cycles/kernel/split/kernel_sum_all_radiance.h b/intern/cycles/kernel/split/kernel_sum_all_radiance.h
new file mode 100644
index 00000000000..a21e9b6a0b1
--- /dev/null
+++ b/intern/cycles/kernel/split/kernel_sum_all_radiance.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2011-2015 Blender Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "../kernel_compat_opencl.h"
+#include "../kernel_math.h"
+#include "../kernel_types.h"
+#include "../kernel_globals.h"
+
+/* Since we process various samples in parallel; The output radiance of different samples
+ * are stored in different locations; This kernel combines the output radiance contributed
+ * by all different samples and stores them in the RenderTile's output buffer.
+ */
+ccl_device void kernel_sum_all_radiance(
+ ccl_constant KernelData *data, /* To get pass_stride to offet into buffer */
+ ccl_global float *buffer, /* Output buffer of RenderTile */
+ ccl_global float *per_sample_output_buffer, /* Radiance contributed by all samples */
+ int parallel_samples, int sw, int sh, int stride,
+ int buffer_offset_x,
+ int buffer_offset_y,
+ int buffer_stride,
+ int start_sample)
+{
+ int x = get_global_id(0);
+ int y = get_global_id(1);
+
+ if(x < sw && y < sh) {
+ buffer += ((buffer_offset_x + x) + (buffer_offset_y + y) * buffer_stride) * (data->film.pass_stride);
+ per_sample_output_buffer += ((x + y * stride) * parallel_samples) * (data->film.pass_stride);
+
+ int sample_stride = (data->film.pass_stride);
+
+ int sample_iterator = 0;
+ int pass_stride_iterator = 0;
+ int num_floats = data->film.pass_stride;
+
+ for(sample_iterator = 0; sample_iterator < parallel_samples; sample_iterator++) {
+ for(pass_stride_iterator = 0; pass_stride_iterator < num_floats; pass_stride_iterator++) {
+ *(buffer + pass_stride_iterator) =
+ (start_sample == 0 && sample_iterator == 0)
+ ? *(per_sample_output_buffer + pass_stride_iterator)
+ : *(buffer + pass_stride_iterator) + *(per_sample_output_buffer + pass_stride_iterator);
+ }
+ per_sample_output_buffer += sample_stride;
+ }
+ }
+}
diff --git a/intern/cycles/kernel/svm/svm.h b/intern/cycles/kernel/svm/svm.h
index efbffacf375..84fc0fcf587 100644
--- a/intern/cycles/kernel/svm/svm.h
+++ b/intern/cycles/kernel/svm/svm.h
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#ifndef __SVM_H__
@@ -102,7 +102,7 @@ ccl_device_inline int stack_load_int(float *stack, uint a)
return __float_as_int(stack[a]);
}
-ccl_device_inline float stack_load_int_default(float *stack, uint a, uint value)
+ccl_device_inline int stack_load_int_default(float *stack, uint a, uint value)
{
return (a == (uint)SVM_STACK_INVALID)? (int)value: stack_load_int(stack, a);
}
@@ -157,6 +157,8 @@ CCL_NAMESPACE_END
#include "svm_noise.h"
#include "svm_texture.h"
+#include "svm_math_util.h"
+
#include "svm_attribute.h"
#include "svm_gradient.h"
#include "svm_blackbody.h"
@@ -192,20 +194,24 @@ CCL_NAMESPACE_END
#include "svm_checker.h"
#include "svm_brick.h"
#include "svm_vector_transform.h"
+#include "svm_voxel.h"
CCL_NAMESPACE_BEGIN
-/* Main Interpreter Loop */
+#define NODES_GROUP(group) ((group) <= __NODES_MAX_GROUP__)
+#define NODES_FEATURE(feature) ((__NODES_FEATURES__ & (feature)) != 0)
+/* Main Interpreter Loop */
ccl_device_noinline void svm_eval_nodes(KernelGlobals *kg, ShaderData *sd, ShaderType type, int path_flag)
{
float stack[SVM_STACK_SIZE];
- int offset = sd->shader & SHADER_MASK;
+ int offset = ccl_fetch(sd, shader) & SHADER_MASK;
while(1) {
uint4 node = read_node(kg, &offset);
switch(node.x) {
+#if NODES_GROUP(NODE_GROUP_LEVEL_0)
case NODE_SHADER_JUMP: {
if(type == SHADER_TYPE_SURFACE) offset = node.y;
else if(type == SHADER_TYPE_VOLUME) offset = node.z;
@@ -222,15 +228,6 @@ ccl_device_noinline void svm_eval_nodes(KernelGlobals *kg, ShaderData *sd, Shade
case NODE_CLOSURE_BACKGROUND:
svm_node_closure_background(sd, stack, node);
break;
- case NODE_CLOSURE_HOLDOUT:
- svm_node_closure_holdout(sd, stack, node);
- break;
- case NODE_CLOSURE_AMBIENT_OCCLUSION:
- svm_node_closure_ambient_occlusion(sd, stack, node);
- break;
- case NODE_CLOSURE_VOLUME:
- svm_node_closure_volume(kg, sd, stack, node, path_flag);
- break;
case NODE_CLOSURE_SET_WEIGHT:
svm_node_closure_set_weight(sd, node.y, node.z, node.w);
break;
@@ -251,13 +248,137 @@ ccl_device_noinline void svm_eval_nodes(KernelGlobals *kg, ShaderData *sd, Shade
if(stack_load_float(stack, node.z) == 1.0f)
offset += node.y;
break;
-#ifdef __TEXTURES__
+ case NODE_GEOMETRY:
+ svm_node_geometry(kg, sd, stack, node.y, node.z);
+ break;
+ case NODE_CONVERT:
+ svm_node_convert(sd, stack, node.y, node.z, node.w);
+ break;
+ case NODE_TEX_COORD:
+ svm_node_tex_coord(kg, sd, path_flag, stack, node, &offset);
+ break;
+ case NODE_VALUE_F:
+ svm_node_value_f(kg, sd, stack, node.y, node.z);
+ break;
+ case NODE_VALUE_V:
+ svm_node_value_v(kg, sd, stack, node.y, &offset);
+ break;
+ case NODE_ATTR:
+ svm_node_attr(kg, sd, stack, node);
+ break;
+# if NODES_FEATURE(NODE_FEATURE_BUMP)
+ case NODE_GEOMETRY_BUMP_DX:
+ svm_node_geometry_bump_dx(kg, sd, stack, node.y, node.z);
+ break;
+ case NODE_GEOMETRY_BUMP_DY:
+ svm_node_geometry_bump_dy(kg, sd, stack, node.y, node.z);
+ break;
+ case NODE_SET_DISPLACEMENT:
+ svm_node_set_displacement(sd, stack, node.y);
+ break;
+# endif /* NODES_FEATURE(NODE_FEATURE_BUMP) */
+# ifdef __TEXTURES__
case NODE_TEX_IMAGE:
svm_node_tex_image(kg, sd, stack, node);
break;
case NODE_TEX_IMAGE_BOX:
svm_node_tex_image_box(kg, sd, stack, node);
break;
+ case NODE_TEX_NOISE:
+ svm_node_tex_noise(kg, sd, stack, node, &offset);
+ break;
+# endif /* __TEXTURES__ */
+# ifdef __EXTRA_NODES__
+# if NODES_FEATURE(NODE_FEATURE_BUMP)
+ case NODE_SET_BUMP:
+ svm_node_set_bump(kg, sd, stack, node);
+ break;
+ case NODE_ATTR_BUMP_DX:
+ svm_node_attr_bump_dx(kg, sd, stack, node);
+ break;
+ case NODE_ATTR_BUMP_DY:
+ svm_node_attr_bump_dy(kg, sd, stack, node);
+ break;
+ case NODE_TEX_COORD_BUMP_DX:
+ svm_node_tex_coord_bump_dx(kg, sd, path_flag, stack, node, &offset);
+ break;
+ case NODE_TEX_COORD_BUMP_DY:
+ svm_node_tex_coord_bump_dy(kg, sd, path_flag, stack, node, &offset);
+ break;
+ case NODE_CLOSURE_SET_NORMAL:
+ svm_node_set_normal(kg, sd, stack, node.y, node.z);
+ break;
+# endif /* NODES_FEATURE(NODE_FEATURE_BUMP) */
+ case NODE_HSV:
+ svm_node_hsv(kg, sd, stack, node.y, node.z, node.w, &offset);
+ break;
+# endif /* __EXTRA_NODES__ */
+#endif /* NODES_GROUP(NODE_GROUP_LEVEL_0) */
+
+#if NODES_GROUP(NODE_GROUP_LEVEL_1)
+ case NODE_CLOSURE_HOLDOUT:
+ svm_node_closure_holdout(sd, stack, node);
+ break;
+ case NODE_CLOSURE_AMBIENT_OCCLUSION:
+ svm_node_closure_ambient_occlusion(sd, stack, node);
+ break;
+ case NODE_FRESNEL:
+ svm_node_fresnel(sd, stack, node.y, node.z, node.w);
+ break;
+ case NODE_LAYER_WEIGHT:
+ svm_node_layer_weight(sd, stack, node);
+ break;
+# if NODES_FEATURE(NODE_FEATURE_VOLUME)
+ case NODE_CLOSURE_VOLUME:
+ svm_node_closure_volume(kg, sd, stack, node, path_flag);
+ break;
+# endif /* NODES_FEATURE(NODE_FEATURE_VOLUME) */
+# ifdef __EXTRA_NODES__
+ case NODE_MATH:
+ svm_node_math(kg, sd, stack, node.y, node.z, node.w, &offset);
+ break;
+ case NODE_VECTOR_MATH:
+ svm_node_vector_math(kg, sd, stack, node.y, node.z, node.w, &offset);
+ break;
+ case NODE_RGB_RAMP:
+ svm_node_rgb_ramp(kg, sd, stack, node, &offset);
+ break;
+ case NODE_GAMMA:
+ svm_node_gamma(sd, stack, node.y, node.z, node.w);
+ break;
+ case NODE_BRIGHTCONTRAST:
+ svm_node_brightness(sd, stack, node.y, node.z, node.w);
+ break;
+ case NODE_LIGHT_PATH:
+ svm_node_light_path(sd, stack, node.y, node.z, path_flag);
+ break;
+ case NODE_OBJECT_INFO:
+ svm_node_object_info(kg, sd, stack, node.y, node.z);
+ break;
+ case NODE_PARTICLE_INFO:
+ svm_node_particle_info(kg, sd, stack, node.y, node.z);
+ break;
+# ifdef __HAIR__
+# if NODES_FEATURE(NODE_FEATURE_HAIR)
+ case NODE_HAIR_INFO:
+ svm_node_hair_info(kg, sd, stack, node.y, node.z);
+ break;
+# endif /* NODES_FEATURE(NODE_FEATURE_HAIR) */
+# endif /* __HAIR__ */
+# endif /* __EXTRA_NODES__ */
+#endif /* NODES_GROUP(NODE_GROUP_LEVEL_1) */
+
+#if NODES_GROUP(NODE_GROUP_LEVEL_2)
+ case NODE_MAPPING:
+ svm_node_mapping(kg, sd, stack, node.y, node.z, &offset);
+ break;
+ case NODE_MIN_MAX:
+ svm_node_min_max(kg, sd, stack, node.y, node.z, &offset);
+ break;
+ case NODE_CAMERA:
+ svm_node_camera(kg, sd, stack, node.y, node.z, node.w);
+ break;
+# ifdef __TEXTURES__
case NODE_TEX_ENVIRONMENT:
svm_node_tex_environment(kg, sd, stack, node);
break;
@@ -267,9 +388,6 @@ ccl_device_noinline void svm_eval_nodes(KernelGlobals *kg, ShaderData *sd, Shade
case NODE_TEX_GRADIENT:
svm_node_tex_gradient(sd, stack, node);
break;
- case NODE_TEX_NOISE:
- svm_node_tex_noise(kg, sd, stack, node, &offset);
- break;
case NODE_TEX_VORONOI:
svm_node_tex_voronoi(kg, sd, stack, node, &offset);
break;
@@ -288,55 +406,34 @@ ccl_device_noinline void svm_eval_nodes(KernelGlobals *kg, ShaderData *sd, Shade
case NODE_TEX_BRICK:
svm_node_tex_brick(kg, sd, stack, node, &offset);
break;
-#endif
- case NODE_CAMERA:
- svm_node_camera(kg, sd, stack, node.y, node.z, node.w);
- break;
- case NODE_GEOMETRY:
- svm_node_geometry(kg, sd, stack, node.y, node.z);
- break;
-#ifdef __EXTRA_NODES__
- case NODE_GEOMETRY_BUMP_DX:
- svm_node_geometry_bump_dx(kg, sd, stack, node.y, node.z);
- break;
- case NODE_GEOMETRY_BUMP_DY:
- svm_node_geometry_bump_dy(kg, sd, stack, node.y, node.z);
- break;
- case NODE_LIGHT_PATH:
- svm_node_light_path(sd, stack, node.y, node.z, path_flag);
- break;
- case NODE_OBJECT_INFO:
- svm_node_object_info(kg, sd, stack, node.y, node.z);
- break;
- case NODE_PARTICLE_INFO:
- svm_node_particle_info(kg, sd, stack, node.y, node.z);
+# endif /* __TEXTURES__ */
+# ifdef __EXTRA_NODES__
+ case NODE_NORMAL:
+ svm_node_normal(kg, sd, stack, node.y, node.z, node.w, &offset);
break;
-#ifdef __HAIR__
- case NODE_HAIR_INFO:
- svm_node_hair_info(kg, sd, stack, node.y, node.z);
+ case NODE_LIGHT_FALLOFF:
+ svm_node_light_falloff(sd, stack, node);
break;
-#endif
+# endif /* __EXTRA_NODES__ */
+#endif /* NODES_GROUP(NODE_GROUP_LEVEL_2) */
-#endif
- case NODE_CONVERT:
- svm_node_convert(sd, stack, node.y, node.z, node.w);
+#if NODES_GROUP(NODE_GROUP_LEVEL_3)
+ case NODE_RGB_CURVES:
+ svm_node_rgb_curves(kg, sd, stack, node, &offset);
break;
- case NODE_VALUE_F:
- svm_node_value_f(kg, sd, stack, node.y, node.z);
+ case NODE_VECTOR_CURVES:
+ svm_node_vector_curves(kg, sd, stack, node, &offset);
break;
- case NODE_VALUE_V:
- svm_node_value_v(kg, sd, stack, node.y, &offset);
+ case NODE_TANGENT:
+ svm_node_tangent(kg, sd, stack, node);
break;
-#ifdef __EXTRA_NODES__
+ case NODE_NORMAL_MAP:
+ svm_node_normal_map(kg, sd, stack, node);
+ break;
+# ifdef __EXTRA_NODES__
case NODE_INVERT:
svm_node_invert(sd, stack, node.y, node.z, node.w);
break;
- case NODE_GAMMA:
- svm_node_gamma(sd, stack, node.y, node.z, node.w);
- break;
- case NODE_BRIGHTCONTRAST:
- svm_node_brightness(sd, stack, node.y, node.z, node.w);
- break;
case NODE_MIX:
svm_node_mix(kg, sd, stack, node.y, node.z, node.w, &offset);
break;
@@ -352,30 +449,11 @@ ccl_device_noinline void svm_eval_nodes(KernelGlobals *kg, ShaderData *sd, Shade
case NODE_COMBINE_HSV:
svm_node_combine_hsv(kg, sd, stack, node.y, node.z, node.w, &offset);
break;
- case NODE_HSV:
- svm_node_hsv(kg, sd, stack, node.y, node.z, node.w, &offset);
- break;
-#endif
- case NODE_ATTR:
- svm_node_attr(kg, sd, stack, node);
- break;
-#ifdef __EXTRA_NODES__
- case NODE_ATTR_BUMP_DX:
- svm_node_attr_bump_dx(kg, sd, stack, node);
- break;
- case NODE_ATTR_BUMP_DY:
- svm_node_attr_bump_dy(kg, sd, stack, node);
- break;
-#endif
- case NODE_FRESNEL:
- svm_node_fresnel(sd, stack, node.y, node.z, node.w);
- break;
- case NODE_LAYER_WEIGHT:
- svm_node_layer_weight(sd, stack, node);
+ case NODE_VECTOR_TRANSFORM:
+ svm_node_vector_transform(kg, sd, stack, node);
break;
-#ifdef __EXTRA_NODES__
case NODE_WIREFRAME:
- svm_node_wireframe(kg, sd, stack, node.y, node.z, node.w);
+ svm_node_wireframe(kg, sd, stack, node);
break;
case NODE_WAVELENGTH:
svm_node_wavelength(sd, stack, node.y, node.z);
@@ -383,70 +461,25 @@ ccl_device_noinline void svm_eval_nodes(KernelGlobals *kg, ShaderData *sd, Shade
case NODE_BLACKBODY:
svm_node_blackbody(kg, sd, stack, node.y, node.z);
break;
- case NODE_SET_DISPLACEMENT:
- svm_node_set_displacement(sd, stack, node.y);
- break;
- case NODE_SET_BUMP:
- svm_node_set_bump(kg, sd, stack, node);
- break;
- case NODE_MATH:
- svm_node_math(kg, sd, stack, node.y, node.z, node.w, &offset);
- break;
- case NODE_VECTOR_MATH:
- svm_node_vector_math(kg, sd, stack, node.y, node.z, node.w, &offset);
- break;
- case NODE_VECTOR_TRANSFORM:
- svm_node_vector_transform(kg, sd, stack, node);
- break;
- case NODE_NORMAL:
- svm_node_normal(kg, sd, stack, node.y, node.z, node.w, &offset);
- break;
-#endif
- case NODE_MAPPING:
- svm_node_mapping(kg, sd, stack, node.y, node.z, &offset);
- break;
- case NODE_MIN_MAX:
- svm_node_min_max(kg, sd, stack, node.y, node.z, &offset);
- break;
- case NODE_TEX_COORD:
- svm_node_tex_coord(kg, sd, path_flag, stack, node.y, node.z);
- break;
-#ifdef __EXTRA_NODES__
- case NODE_TEX_COORD_BUMP_DX:
- svm_node_tex_coord_bump_dx(kg, sd, path_flag, stack, node.y, node.z);
- break;
- case NODE_TEX_COORD_BUMP_DY:
- svm_node_tex_coord_bump_dy(kg, sd, path_flag, stack, node.y, node.z);
- break;
- case NODE_CLOSURE_SET_NORMAL:
- svm_node_set_normal(kg, sd, stack, node.y, node.z );
- break;
- case NODE_RGB_RAMP:
- svm_node_rgb_ramp(kg, sd, stack, node, &offset);
- break;
- case NODE_RGB_CURVES:
- svm_node_rgb_curves(kg, sd, stack, node, &offset);
- break;
- case NODE_VECTOR_CURVES:
- svm_node_vector_curves(kg, sd, stack, node, &offset);
- break;
- case NODE_LIGHT_FALLOFF:
- svm_node_light_falloff(sd, stack, node);
- break;
-#endif
- case NODE_TANGENT:
- svm_node_tangent(kg, sd, stack, node);
- break;
- case NODE_NORMAL_MAP:
- svm_node_normal_map(kg, sd, stack, node);
+# endif /* __EXTRA_NODES__ */
+# if NODES_FEATURE(NODE_FEATURE_VOLUME) && !defined(__KERNEL_GPU__)
+ case NODE_TEX_VOXEL:
+ svm_node_tex_voxel(kg, sd, stack, node, &offset);
break;
+# endif /* NODES_FEATURE(NODE_FEATURE_VOLUME) && !defined(__KERNEL_GPU__) */
+#endif /* NODES_GROUP(NODE_GROUP_LEVEL_3) */
case NODE_END:
+ return;
default:
+ kernel_assert(!"Unknown node type was passed to the SVM machine");
return;
}
}
}
+#undef NODES_GROUP
+#undef NODES_FEATURE
+
CCL_NAMESPACE_END
#ifdef __CAMERA_RAY_NODES__
diff --git a/intern/cycles/kernel/svm/svm_attribute.h b/intern/cycles/kernel/svm/svm_attribute.h
index fd0ea7fef31..025ae96f59d 100644
--- a/intern/cycles/kernel/svm/svm_attribute.h
+++ b/intern/cycles/kernel/svm/svm_attribute.h
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
CCL_NAMESPACE_BEGIN
@@ -22,12 +22,12 @@ ccl_device void svm_node_attr_init(KernelGlobals *kg, ShaderData *sd,
uint4 node, NodeAttributeType *type,
NodeAttributeType *mesh_type, AttributeElement *elem, int *offset, uint *out_offset)
{
- if(sd->object != OBJECT_NONE) {
+ if(ccl_fetch(sd, object) != OBJECT_NONE) {
/* find attribute by unique id */
uint id = node.y;
- uint attr_offset = sd->object*kernel_data.bvh.attributes_map_stride;
+ uint attr_offset = ccl_fetch(sd, object)*kernel_data.bvh.attributes_map_stride;
#ifdef __HAIR__
- attr_offset = (sd->type & PRIMITIVE_ALL_CURVE)? attr_offset + ATTR_PRIM_CURVE: attr_offset;
+ attr_offset = (ccl_fetch(sd, type) & PRIMITIVE_ALL_CURVE)? attr_offset + ATTR_PRIM_CURVE: attr_offset;
#endif
uint4 attr_map = kernel_tex_fetch(__attributes_map, attr_offset);
diff --git a/intern/cycles/kernel/svm/svm_blackbody.h b/intern/cycles/kernel/svm/svm_blackbody.h
index 15257aed92e..b750ad87b7f 100644
--- a/intern/cycles/kernel/svm/svm_blackbody.h
+++ b/intern/cycles/kernel/svm/svm_blackbody.h
@@ -36,48 +36,12 @@ CCL_NAMESPACE_BEGIN
ccl_device void svm_node_blackbody(KernelGlobals *kg, ShaderData *sd, float *stack, uint temperature_offset, uint col_offset)
{
- /* Output */
- float3 color_rgb = make_float3(0.0f, 0.0f, 0.0f);
-
/* Input */
float temperature = stack_load_float(stack, temperature_offset);
- if (temperature < BB_DRAPPER) {
- /* just return very very dim red */
- color_rgb = make_float3(1.0e-6f,0.0f,0.0f);
- }
- else if (temperature <= BB_MAX_TABLE_RANGE) {
- /* This is the overall size of the table */
- const int lookuptablesize = 956;
- const float lookuptablenormalize = 1.0f/956.0f;
-
- /* reconstruct a proper index for the table lookup, compared to OSL we don't look up two colors
- just one (the OSL-lerp is also automatically done for us by "lookup_table_read") */
- float t = powf((temperature - BB_DRAPPER) * (1.0f / BB_TABLE_SPACING), (1.0f / BB_TABLE_XPOWER));
-
- int blackbody_table_offset = kernel_data.tables.blackbody_offset;
-
- /* Retrieve colors from the lookup table */
- float lutval = t*lookuptablenormalize;
- float R = lookup_table_read(kg, lutval, blackbody_table_offset, lookuptablesize);
- lutval = (t + 319.0f*1.0f)*lookuptablenormalize;
- float G = lookup_table_read(kg, lutval, blackbody_table_offset, lookuptablesize);
- lutval = (t + 319.0f*2.0f)*lookuptablenormalize;
- float B = lookup_table_read(kg, lutval, blackbody_table_offset, lookuptablesize);
-
- R = powf(R, BB_TABLE_YPOWER);
- G = powf(G, BB_TABLE_YPOWER);
- B = powf(B, BB_TABLE_YPOWER);
-
- color_rgb = make_float3(R, G, B);
- }
-
- /* Luminance */
- float l = linear_rgb_to_gray(color_rgb);
- if (l != 0.0f)
- color_rgb /= l;
+ float3 color_rgb = svm_math_blackbody_color(temperature);
- if (stack_valid(col_offset))
+ if(stack_valid(col_offset))
stack_store_float3(stack, col_offset, color_rgb);
}
diff --git a/intern/cycles/kernel/svm/svm_brick.h b/intern/cycles/kernel/svm/svm_brick.h
index 97c2b545c5f..9b0cf5ab8c4 100644
--- a/intern/cycles/kernel/svm/svm_brick.h
+++ b/intern/cycles/kernel/svm/svm_brick.h
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
CCL_NAMESPACE_BEGIN
@@ -21,6 +21,7 @@ CCL_NAMESPACE_BEGIN
ccl_device_noinline float brick_noise(int n) /* fast integer noise */
{
int nn;
+ n = (n + 1013) & 0x7fffffff;
n = (n >> 13) ^ n;
nn = (n * (n * n * 60493 + 19990303) + 1376312589) & 0x7fffffff;
return 0.5f * ((float)nn / 1073741824.0f);
@@ -47,7 +48,7 @@ ccl_device_noinline float2 svm_brick(float3 p, float mortar_size, float bias,
y = p.y - row_height*rownum;
return make_float2(
- clamp((brick_noise((rownum << 16) + (bricknum & 0xFFFF)) + bias), 0.0f, 1.0f),
+ saturate((brick_noise((rownum << 16) + (bricknum & 0xFFFF)) + bias)),
(x < mortar_size || y < mortar_size ||
x > (brick_width - mortar_size) ||
@@ -95,10 +96,7 @@ ccl_device void svm_node_tex_brick(KernelGlobals *kg, ShaderData *sd, float *sta
if(f != 1.0f) {
float facm = 1.0f - tint;
-
- color1.x = facm * (color1.x) + tint * color2.x;
- color1.y = facm * (color1.y) + tint * color2.y;
- color1.z = facm * (color1.z) + tint * color2.z;
+ color1 = facm * color1 + tint * color2;
}
if(stack_valid(color_offset))
diff --git a/intern/cycles/kernel/svm/svm_brightness.h b/intern/cycles/kernel/svm/svm_brightness.h
index 9b330b3213f..e4d545a00ae 100644
--- a/intern/cycles/kernel/svm/svm_brightness.h
+++ b/intern/cycles/kernel/svm/svm_brightness.h
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
CCL_NAMESPACE_BEGIN
@@ -32,7 +32,7 @@ ccl_device void svm_node_brightness(ShaderData *sd, float *stack, uint in_color,
color.y = max(a*color.y + b, 0.0f);
color.z = max(a*color.z + b, 0.0f);
- if (stack_valid(out_color))
+ if(stack_valid(out_color))
stack_store_float3(stack, out_color, color);
}
diff --git a/intern/cycles/kernel/svm/svm_camera.h b/intern/cycles/kernel/svm/svm_camera.h
index bfe9289fa02..00678a49d70 100644
--- a/intern/cycles/kernel/svm/svm_camera.h
+++ b/intern/cycles/kernel/svm/svm_camera.h
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
CCL_NAMESPACE_BEGIN
@@ -23,17 +23,17 @@ ccl_device void svm_node_camera(KernelGlobals *kg, ShaderData *sd, float *stack,
float3 vector;
Transform tfm = kernel_data.cam.worldtocamera;
- vector = transform_point(&tfm, sd->P);
+ vector = transform_point(&tfm, ccl_fetch(sd, P));
zdepth = vector.z;
distance = len(vector);
- if (stack_valid(out_vector))
+ if(stack_valid(out_vector))
stack_store_float3(stack, out_vector, normalize(vector));
- if (stack_valid(out_zdepth))
+ if(stack_valid(out_zdepth))
stack_store_float(stack, out_zdepth, zdepth);
- if (stack_valid(out_distance))
+ if(stack_valid(out_distance))
stack_store_float(stack, out_distance, distance);
}
diff --git a/intern/cycles/kernel/svm/svm_checker.h b/intern/cycles/kernel/svm/svm_checker.h
index e0408ad334a..186bf7df55f 100644
--- a/intern/cycles/kernel/svm/svm_checker.h
+++ b/intern/cycles/kernel/svm/svm_checker.h
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
CCL_NAMESPACE_BEGIN
diff --git a/intern/cycles/kernel/svm/svm_closure.h b/intern/cycles/kernel/svm/svm_closure.h
index 30110db3ef9..c495ebb35bd 100644
--- a/intern/cycles/kernel/svm/svm_closure.h
+++ b/intern/cycles/kernel/svm/svm_closure.h
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
CCL_NAMESPACE_BEGIN
@@ -25,10 +25,14 @@ ccl_device void svm_node_glass_setup(ShaderData *sd, ShaderClosure *sc, int type
sc->data0 = eta;
sc->data1 = 0.0f;
sc->data2 = 0.0f;
- sd->flag |= bsdf_refraction_setup(sc);
+ ccl_fetch(sd, flag) |= bsdf_refraction_setup(sc);
+ }
+ else {
+ sc->data0 = 0.0f;
+ sc->data1 = 0.0f;
+ sc->data2 = 0.0f;
+ ccl_fetch(sd, flag) |= bsdf_reflection_setup(sc);
}
- else
- sd->flag |= bsdf_reflection_setup(sc);
}
else if(type == CLOSURE_BSDF_MICROFACET_BECKMANN_GLASS_ID) {
sc->data0 = roughness;
@@ -36,9 +40,9 @@ ccl_device void svm_node_glass_setup(ShaderData *sd, ShaderClosure *sc, int type
sc->data2 = eta;
if(refract)
- sd->flag |= bsdf_microfacet_beckmann_refraction_setup(sc);
+ ccl_fetch(sd, flag) |= bsdf_microfacet_beckmann_refraction_setup(sc);
else
- sd->flag |= bsdf_microfacet_beckmann_setup(sc);
+ ccl_fetch(sd, flag) |= bsdf_microfacet_beckmann_setup(sc);
}
else {
sc->data0 = roughness;
@@ -46,23 +50,26 @@ ccl_device void svm_node_glass_setup(ShaderData *sd, ShaderClosure *sc, int type
sc->data2 = eta;
if(refract)
- sd->flag |= bsdf_microfacet_ggx_refraction_setup(sc);
+ ccl_fetch(sd, flag) |= bsdf_microfacet_ggx_refraction_setup(sc);
else
- sd->flag |= bsdf_microfacet_ggx_setup(sc);
+ ccl_fetch(sd, flag) |= bsdf_microfacet_ggx_setup(sc);
}
}
ccl_device_inline ShaderClosure *svm_node_closure_get_non_bsdf(ShaderData *sd, ClosureType type, float mix_weight)
{
- ShaderClosure *sc = &sd->closure[sd->num_closure];
+ ShaderClosure *sc = ccl_fetch_array(sd, closure, ccl_fetch(sd, num_closure));
- if(sd->num_closure < MAX_CLOSURE) {
+ if(ccl_fetch(sd, num_closure) < MAX_CLOSURE) {
sc->weight *= mix_weight;
sc->type = type;
+ sc->data0 = 0.0f;
+ sc->data1 = 0.0f;
+ sc->data2 = 0.0f;
#ifdef __OSL__
sc->prim = NULL;
#endif
- sd->num_closure++;
+ ccl_fetch(sd, num_closure)++;
return sc;
}
@@ -71,14 +78,15 @@ ccl_device_inline ShaderClosure *svm_node_closure_get_non_bsdf(ShaderData *sd, C
ccl_device_inline ShaderClosure *svm_node_closure_get_bsdf(ShaderData *sd, float mix_weight)
{
- ShaderClosure *sc = &sd->closure[sd->num_closure];
+ ShaderClosure *sc = ccl_fetch_array(sd, closure, ccl_fetch(sd, num_closure));
+
float3 weight = sc->weight * mix_weight;
float sample_weight = fabsf(average(weight));
- if(sample_weight > CLOSURE_WEIGHT_CUTOFF && sd->num_closure < MAX_CLOSURE) {
+ if(sample_weight > CLOSURE_WEIGHT_CUTOFF && ccl_fetch(sd, num_closure) < MAX_CLOSURE) {
sc->weight = weight;
sc->sample_weight = sample_weight;
- sd->num_closure++;
+ ccl_fetch(sd, num_closure)++;
#ifdef __OSL__
sc->prim = NULL;
#endif
@@ -90,14 +98,15 @@ ccl_device_inline ShaderClosure *svm_node_closure_get_bsdf(ShaderData *sd, float
ccl_device_inline ShaderClosure *svm_node_closure_get_absorption(ShaderData *sd, float mix_weight)
{
- ShaderClosure *sc = &sd->closure[sd->num_closure];
+ ShaderClosure *sc = ccl_fetch_array(sd, closure, ccl_fetch(sd, num_closure));
+
float3 weight = (make_float3(1.0f, 1.0f, 1.0f) - sc->weight) * mix_weight;
float sample_weight = fabsf(average(weight));
- if(sample_weight > CLOSURE_WEIGHT_CUTOFF && sd->num_closure < MAX_CLOSURE) {
+ if(sample_weight > CLOSURE_WEIGHT_CUTOFF && ccl_fetch(sd, num_closure) < MAX_CLOSURE) {
sc->weight = weight;
sc->sample_weight = sample_weight;
- sd->num_closure++;
+ ccl_fetch(sd, num_closure)++;
#ifdef __OSL__
sc->prim = NULL;
#endif
@@ -121,7 +130,7 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *
if(mix_weight == 0.0f)
return;
- float3 N = stack_valid(data_node.x)? stack_load_float3(stack, data_node.x): sd->N;
+ float3 N = stack_valid(data_node.x)? stack_load_float3(stack, data_node.x): ccl_fetch(sd, N);
float param1 = (stack_valid(param1_offset))? stack_load_float(stack, param1_offset): __uint_as_float(node.z);
float param2 = (stack_valid(param2_offset))? stack_load_float(stack, param2_offset): __uint_as_float(node.w);
@@ -139,13 +148,13 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *
sc->data0 = 0.0f;
sc->data1 = 0.0f;
sc->data2 = 0.0f;
- sd->flag |= bsdf_diffuse_setup(sc);
+ ccl_fetch(sd, flag) |= bsdf_diffuse_setup(sc);
}
else {
sc->data0 = roughness;
sc->data1 = 0.0f;
sc->data2 = 0.0f;
- sd->flag |= bsdf_oren_nayar_setup(sc);
+ ccl_fetch(sd, flag) |= bsdf_oren_nayar_setup(sc);
}
}
break;
@@ -158,7 +167,7 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *
sc->data1 = 0.0f;
sc->data2 = 0.0f;
sc->N = N;
- sd->flag |= bsdf_translucent_setup(sc);
+ ccl_fetch(sd, flag) |= bsdf_translucent_setup(sc);
}
break;
}
@@ -170,7 +179,7 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *
sc->data1 = 0.0f;
sc->data2 = 0.0f;
sc->N = N;
- sd->flag |= bsdf_transparent_setup(sc);
+ ccl_fetch(sd, flag) |= bsdf_transparent_setup(sc);
}
break;
}
@@ -192,13 +201,13 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *
/* setup bsdf */
if(type == CLOSURE_BSDF_REFLECTION_ID)
- sd->flag |= bsdf_reflection_setup(sc);
+ ccl_fetch(sd, flag) |= bsdf_reflection_setup(sc);
else if(type == CLOSURE_BSDF_MICROFACET_BECKMANN_ID)
- sd->flag |= bsdf_microfacet_beckmann_setup(sc);
+ ccl_fetch(sd, flag) |= bsdf_microfacet_beckmann_setup(sc);
else if(type == CLOSURE_BSDF_MICROFACET_GGX_ID)
- sd->flag |= bsdf_microfacet_ggx_setup(sc);
+ ccl_fetch(sd, flag) |= bsdf_microfacet_ggx_setup(sc);
else
- sd->flag |= bsdf_ashikhmin_shirley_setup(sc);
+ ccl_fetch(sd, flag) |= bsdf_ashikhmin_shirley_setup(sc);
}
break;
@@ -216,7 +225,7 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *
sc->N = N;
float eta = fmaxf(param2, 1e-5f);
- eta = (sd->flag & SD_BACKFACING)? 1.0f/eta: eta;
+ eta = (ccl_fetch(sd, flag) & SD_BACKFACING)? 1.0f/eta: eta;
/* setup bsdf */
if(type == CLOSURE_BSDF_REFRACTION_ID) {
@@ -224,7 +233,7 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *
sc->data1 = 0.0f;
sc->data2 = 0.0f;
- sd->flag |= bsdf_refraction_setup(sc);
+ ccl_fetch(sd, flag) |= bsdf_refraction_setup(sc);
}
else {
sc->data0 = param1;
@@ -232,9 +241,9 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *
sc->data2 = eta;
if(type == CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID)
- sd->flag |= bsdf_microfacet_beckmann_refraction_setup(sc);
+ ccl_fetch(sd, flag) |= bsdf_microfacet_beckmann_refraction_setup(sc);
else
- sd->flag |= bsdf_microfacet_ggx_refraction_setup(sc);
+ ccl_fetch(sd, flag) |= bsdf_microfacet_ggx_refraction_setup(sc);
}
}
@@ -251,15 +260,15 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *
#endif
/* index of refraction */
float eta = fmaxf(param2, 1e-5f);
- eta = (sd->flag & SD_BACKFACING)? 1.0f/eta: eta;
+ eta = (ccl_fetch(sd, flag) & SD_BACKFACING)? 1.0f/eta: eta;
/* fresnel */
- float cosNO = dot(N, sd->I);
+ float cosNO = dot(N, ccl_fetch(sd, I));
float fresnel = fresnel_dielectric_cos(cosNO, eta);
float roughness = param1;
/* reflection */
- ShaderClosure *sc = &sd->closure[sd->num_closure];
+ ShaderClosure *sc = ccl_fetch_array(sd, closure, ccl_fetch(sd, num_closure));
float3 weight = sc->weight;
float sample_weight = sc->sample_weight;
@@ -280,15 +289,17 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *
#endif
/* refraction */
- sc = &sd->closure[sd->num_closure];
- sc->weight = weight;
- sc->sample_weight = sample_weight;
+ if(ccl_fetch(sd, num_closure) < MAX_CLOSURE) {
+ sc = ccl_fetch_array(sd, closure, ccl_fetch(sd, num_closure));
+ sc->weight = weight;
+ sc->sample_weight = sample_weight;
- sc = svm_node_closure_get_bsdf(sd, mix_weight*(1.0f - fresnel));
+ sc = svm_node_closure_get_bsdf(sd, mix_weight*(1.0f - fresnel));
- if(sc) {
- sc->N = N;
- svm_node_glass_setup(sd, sc, type, eta, roughness, true);
+ if(sc) {
+ sc->N = N;
+ svm_node_glass_setup(sd, sc, type, eta, roughness, true);
+ }
}
break;
@@ -328,12 +339,12 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *
sc->data2 = 0.0f;
- if (type == CLOSURE_BSDF_MICROFACET_BECKMANN_ANISO_ID)
- sd->flag |= bsdf_microfacet_beckmann_aniso_setup(sc);
- else if (type == CLOSURE_BSDF_MICROFACET_GGX_ANISO_ID)
- sd->flag |= bsdf_microfacet_ggx_aniso_setup(sc);
+ if(type == CLOSURE_BSDF_MICROFACET_BECKMANN_ANISO_ID)
+ ccl_fetch(sd, flag) |= bsdf_microfacet_beckmann_aniso_setup(sc);
+ else if(type == CLOSURE_BSDF_MICROFACET_GGX_ANISO_ID)
+ ccl_fetch(sd, flag) |= bsdf_microfacet_ggx_aniso_setup(sc);
else
- sd->flag |= bsdf_ashikhmin_shirley_aniso_setup(sc);
+ ccl_fetch(sd, flag) |= bsdf_ashikhmin_shirley_aniso_setup(sc);
}
break;
}
@@ -344,10 +355,10 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *
sc->N = N;
/* sigma */
- sc->data0 = clamp(param1, 0.0f, 1.0f);
+ sc->data0 = saturate(param1);
sc->data1 = 0.0f;
sc->data2 = 0.0f;
- sd->flag |= bsdf_ashikhmin_velvet_setup(sc);
+ ccl_fetch(sd, flag) |= bsdf_ashikhmin_velvet_setup(sc);
}
break;
}
@@ -362,10 +373,10 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *
sc->data1 = param2;
sc->data2 = 0.0f;
- if (type == CLOSURE_BSDF_DIFFUSE_TOON_ID)
- sd->flag |= bsdf_diffuse_toon_setup(sc);
+ if(type == CLOSURE_BSDF_DIFFUSE_TOON_ID)
+ ccl_fetch(sd, flag) |= bsdf_diffuse_toon_setup(sc);
else
- sd->flag |= bsdf_glossy_toon_setup(sc);
+ ccl_fetch(sd, flag) |= bsdf_glossy_toon_setup(sc);
}
break;
}
@@ -373,7 +384,7 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *
case CLOSURE_BSDF_HAIR_REFLECTION_ID:
case CLOSURE_BSDF_HAIR_TRANSMISSION_ID: {
- if(sd->flag & SD_BACKFACING && sd->type & PRIMITIVE_ALL_CURVE) {
+ if(ccl_fetch(sd, flag) & SD_BACKFACING && ccl_fetch(sd, type) & PRIMITIVE_ALL_CURVE) {
ShaderClosure *sc = svm_node_closure_get_bsdf(sd, mix_weight);
if(sc) {
@@ -384,11 +395,14 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *
* spawned by transmission from the front */
sc->weight = make_float3(1.0f, 1.0f, 1.0f);
sc->N = N;
- sd->flag |= bsdf_transparent_setup(sc);
+ sc->data0 = 0.0f;
+ sc->data1 = 0.0f;
+ sc->data2 = 0.0f;
+ ccl_fetch(sd, flag) |= bsdf_transparent_setup(sc);
}
}
else {
- ShaderClosure *sc = &sd->closure[sd->num_closure];
+ ShaderClosure *sc = ccl_fetch_array(sd, closure, ccl_fetch(sd, num_closure));
sc = svm_node_closure_get_bsdf(sd, mix_weight);
if(sc) {
@@ -397,18 +411,18 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *
sc->data1 = param2;
sc->data2 = -stack_load_float(stack, data_node.z);
- if(!(sd->type & PRIMITIVE_ALL_CURVE)) {
- sc->T = normalize(sd->dPdv);
+ if(!(ccl_fetch(sd, type) & PRIMITIVE_ALL_CURVE)) {
+ sc->T = normalize(ccl_fetch(sd, dPdv));
sc->data2 = 0.0f;
}
else
- sc->T = sd->dPdu;
+ sc->T = normalize(ccl_fetch(sd, dPdu));
if(type == CLOSURE_BSDF_HAIR_REFLECTION_ID) {
- sd->flag |= bsdf_hair_reflection_setup(sc);
+ ccl_fetch(sd, flag) |= bsdf_hair_reflection_setup(sc);
}
else {
- sd->flag |= bsdf_hair_transmission_setup(sc);
+ ccl_fetch(sd, flag) |= bsdf_hair_transmission_setup(sc);
}
}
}
@@ -418,9 +432,14 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *
#endif
#ifdef __SUBSURFACE__
+#ifndef __SPLIT_KERNEL__
+# define sc_next(sc) sc++
+# else
+# define sc_next(sc) sc = ccl_fetch_array(sd, closure, ccl_fetch(sd, num_closure))
+# endif
case CLOSURE_BSSRDF_CUBIC_ID:
case CLOSURE_BSSRDF_GAUSSIAN_ID: {
- ShaderClosure *sc = &sd->closure[sd->num_closure];
+ ShaderClosure *sc = ccl_fetch_array(sd, closure, ccl_fetch(sd, num_closure));
float3 weight = sc->weight * mix_weight;
float sample_weight = fabsf(average(weight));
@@ -430,7 +449,7 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *
if(path_flag & PATH_RAY_DIFFUSE_ANCESTOR)
param1 = 0.0f;
- if(sample_weight > CLOSURE_WEIGHT_CUTOFF && sd->num_closure+2 < MAX_CLOSURE) {
+ if(sample_weight > CLOSURE_WEIGHT_CUTOFF && ccl_fetch(sd, num_closure)+2 < MAX_CLOSURE) {
/* radius * scale */
float3 radius = stack_load_float3(stack, data_node.z)*param1;
/* sharpness */
@@ -450,10 +469,10 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *
sc->prim = NULL;
#endif
sc->N = N;
- sd->flag |= bssrdf_setup(sc, (ClosureType)type);
+ ccl_fetch(sd, flag) |= bssrdf_setup(sc, (ClosureType)type);
- sd->num_closure++;
- sc++;
+ ccl_fetch(sd, num_closure)++;
+ sc_next(sc);
}
if(fabsf(weight.y) > 0.0f) {
@@ -467,10 +486,10 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *
sc->prim = NULL;
#endif
sc->N = N;
- sd->flag |= bssrdf_setup(sc, (ClosureType)type);
+ ccl_fetch(sd, flag) |= bssrdf_setup(sc, (ClosureType)type);
- sd->num_closure++;
- sc++;
+ ccl_fetch(sd, num_closure)++;
+ sc_next(sc);
}
if(fabsf(weight.z) > 0.0f) {
@@ -484,15 +503,16 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *
sc->prim = NULL;
#endif
sc->N = N;
- sd->flag |= bssrdf_setup(sc, (ClosureType)type);
+ ccl_fetch(sd, flag) |= bssrdf_setup(sc, (ClosureType)type);
- sd->num_closure++;
- sc++;
+ ccl_fetch(sd, num_closure)++;
+ sc_next(sc);
}
}
break;
}
+# undef sc_next
#endif
default:
break;
@@ -520,7 +540,7 @@ ccl_device void svm_node_closure_volume(KernelGlobals *kg, ShaderData *sd, float
ShaderClosure *sc = svm_node_closure_get_absorption(sd, mix_weight * density);
if(sc) {
- sd->flag |= volume_absorption_setup(sc);
+ ccl_fetch(sd, flag) |= volume_absorption_setup(sc);
}
break;
}
@@ -528,9 +548,10 @@ ccl_device void svm_node_closure_volume(KernelGlobals *kg, ShaderData *sd, float
ShaderClosure *sc = svm_node_closure_get_bsdf(sd, mix_weight * density);
if(sc) {
- float g = param2;
- sc->data0 = g;
- sd->flag |= volume_henyey_greenstein_setup(sc);
+ sc->data0 = param2; /* g */
+ sc->data1 = 0.0f;
+ sc->data2 = 0.0f;
+ ccl_fetch(sd, flag) |= volume_henyey_greenstein_setup(sc);
}
break;
}
@@ -555,7 +576,7 @@ ccl_device void svm_node_closure_emission(ShaderData *sd, float *stack, uint4 no
else
svm_node_closure_get_non_bsdf(sd, CLOSURE_EMISSION_ID, 1.0f);
- sd->flag |= SD_EMISSION;
+ ccl_fetch(sd, flag) |= SD_EMISSION;
}
ccl_device void svm_node_closure_background(ShaderData *sd, float *stack, uint4 node)
@@ -589,7 +610,7 @@ ccl_device void svm_node_closure_holdout(ShaderData *sd, float *stack, uint4 nod
else
svm_node_closure_get_non_bsdf(sd, CLOSURE_HOLDOUT_ID, 1.0f);
- sd->flag |= SD_HOLDOUT;
+ ccl_fetch(sd, flag) |= SD_HOLDOUT;
}
ccl_device void svm_node_closure_ambient_occlusion(ShaderData *sd, float *stack, uint4 node)
@@ -607,15 +628,17 @@ ccl_device void svm_node_closure_ambient_occlusion(ShaderData *sd, float *stack,
else
svm_node_closure_get_non_bsdf(sd, CLOSURE_AMBIENT_OCCLUSION_ID, 1.0f);
- sd->flag |= SD_AO;
+ ccl_fetch(sd, flag) |= SD_AO;
}
/* Closure Nodes */
ccl_device_inline void svm_node_closure_store_weight(ShaderData *sd, float3 weight)
{
- if(sd->num_closure < MAX_CLOSURE)
- sd->closure[sd->num_closure].weight = weight;
+ if(ccl_fetch(sd, num_closure) < MAX_CLOSURE) {
+ ShaderClosure *sc = ccl_fetch_array(sd, closure, ccl_fetch(sd, num_closure));
+ sc->weight = weight;
+ }
}
ccl_device void svm_node_closure_set_weight(ShaderData *sd, uint r, uint g, uint b)
@@ -650,7 +673,7 @@ ccl_device void svm_node_mix_closure(ShaderData *sd, float *stack, uint4 node)
decode_node_uchar4(node.y, &weight_offset, &in_weight_offset, &weight1_offset, &weight2_offset);
float weight = stack_load_float(stack, weight_offset);
- weight = clamp(weight, 0.0f, 1.0f);
+ weight = saturate(weight);
float in_weight = (stack_valid(in_weight_offset))? stack_load_float(stack, in_weight_offset): 1.0f;
@@ -665,7 +688,7 @@ ccl_device void svm_node_mix_closure(ShaderData *sd, float *stack, uint4 node)
ccl_device void svm_node_set_normal(KernelGlobals *kg, ShaderData *sd, float *stack, uint in_direction, uint out_normal)
{
float3 normal = stack_load_float3(stack, in_direction);
- sd->N = normal;
+ ccl_fetch(sd, N) = normal;
stack_store_float3(stack, out_normal, normal);
}
diff --git a/intern/cycles/kernel/svm/svm_convert.h b/intern/cycles/kernel/svm/svm_convert.h
index b221e0728ec..34080377083 100644
--- a/intern/cycles/kernel/svm/svm_convert.h
+++ b/intern/cycles/kernel/svm/svm_convert.h
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
CCL_NAMESPACE_BEGIN
diff --git a/intern/cycles/kernel/svm/svm_displace.h b/intern/cycles/kernel/svm/svm_displace.h
index 6cd5ee4b375..8d4b07c9973 100644
--- a/intern/cycles/kernel/svm/svm_displace.h
+++ b/intern/cycles/kernel/svm/svm_displace.h
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
CCL_NAMESPACE_BEGIN
@@ -25,11 +25,11 @@ ccl_device void svm_node_set_bump(KernelGlobals *kg, ShaderData *sd, float *stac
uint normal_offset, distance_offset, invert;
decode_node_uchar4(node.y, &normal_offset, &distance_offset, &invert, NULL);
- float3 normal_in = stack_valid(normal_offset)? stack_load_float3(stack, normal_offset): sd->N;
+ float3 normal_in = stack_valid(normal_offset)? stack_load_float3(stack, normal_offset): ccl_fetch(sd, N);
/* get surface tangents from normal */
- float3 Rx = cross(sd->dP.dy, normal_in);
- float3 Ry = cross(normal_in, sd->dP.dx);
+ float3 Rx = cross(ccl_fetch(sd, dP).dy, normal_in);
+ float3 Ry = cross(normal_in, ccl_fetch(sd, dP).dx);
/* get bump values */
uint c_offset, x_offset, y_offset, strength_offset;
@@ -40,7 +40,7 @@ ccl_device void svm_node_set_bump(KernelGlobals *kg, ShaderData *sd, float *stac
float h_y = stack_load_float(stack, y_offset);
/* compute surface gradient and determinant */
- float det = dot(sd->dP.dx, Rx);
+ float det = dot(ccl_fetch(sd, dP).dx, Rx);
float3 surfgrad = (h_x - h_c)*Rx + (h_y - h_c)*Ry;
float absdet = fabsf(det);
@@ -65,7 +65,7 @@ ccl_device void svm_node_set_bump(KernelGlobals *kg, ShaderData *sd, float *stac
ccl_device void svm_node_set_displacement(ShaderData *sd, float *stack, uint fac_offset)
{
float d = stack_load_float(stack, fac_offset);
- sd->P += sd->N*d*0.1f; /* todo: get rid of this factor */
+ ccl_fetch(sd, P) += ccl_fetch(sd, N)*d*0.1f; /* todo: get rid of this factor */
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/svm/svm_fresnel.h b/intern/cycles/kernel/svm/svm_fresnel.h
index 5def52205eb..23c97d80cb0 100644
--- a/intern/cycles/kernel/svm/svm_fresnel.h
+++ b/intern/cycles/kernel/svm/svm_fresnel.h
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
CCL_NAMESPACE_BEGIN
@@ -23,12 +23,12 @@ ccl_device void svm_node_fresnel(ShaderData *sd, float *stack, uint ior_offset,
uint normal_offset, out_offset;
decode_node_uchar4(node, &normal_offset, &out_offset, NULL, NULL);
float eta = (stack_valid(ior_offset))? stack_load_float(stack, ior_offset): __uint_as_float(ior_value);
- float3 normal_in = stack_valid(normal_offset)? stack_load_float3(stack, normal_offset): sd->N;
+ float3 normal_in = stack_valid(normal_offset)? stack_load_float3(stack, normal_offset): ccl_fetch(sd, N);
eta = fmaxf(eta, 1e-5f);
- eta = (sd->flag & SD_BACKFACING)? 1.0f/eta: eta;
+ eta = (ccl_fetch(sd, flag) & SD_BACKFACING)? 1.0f/eta: eta;
- float f = fresnel_dielectric_cos(dot(sd->I, normal_in), eta);
+ float f = fresnel_dielectric_cos(dot(ccl_fetch(sd, I), normal_in), eta);
stack_store_float(stack, out_offset, f);
}
@@ -44,18 +44,18 @@ ccl_device void svm_node_layer_weight(ShaderData *sd, float *stack, uint4 node)
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;
+ float3 normal_in = (stack_valid(normal_offset))? stack_load_float3(stack, normal_offset): ccl_fetch(sd, N);
float f;
if(type == NODE_LAYER_WEIGHT_FRESNEL) {
float eta = fmaxf(1.0f - blend, 1e-5f);
- eta = (sd->flag & SD_BACKFACING)? eta: 1.0f/eta;
+ eta = (ccl_fetch(sd, flag) & SD_BACKFACING)? eta: 1.0f/eta;
- f = fresnel_dielectric_cos(dot(sd->I, normal_in), eta);
+ f = fresnel_dielectric_cos(dot(ccl_fetch(sd, I), normal_in), eta);
}
else {
- f = fabsf(dot(sd->I, normal_in));
+ f = fabsf(dot(ccl_fetch(sd, I), normal_in));
if(blend != 0.5f) {
blend = clamp(blend, 0.0f, 1.0f-1e-5f);
diff --git a/intern/cycles/kernel/svm/svm_gamma.h b/intern/cycles/kernel/svm/svm_gamma.h
index c4749e7b936..b645ff3f0f9 100644
--- a/intern/cycles/kernel/svm/svm_gamma.h
+++ b/intern/cycles/kernel/svm/svm_gamma.h
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
CCL_NAMESPACE_BEGIN
@@ -21,14 +21,14 @@ ccl_device void svm_node_gamma(ShaderData *sd, float *stack, uint in_gamma, uint
float3 color = stack_load_float3(stack, in_color);
float gamma = stack_load_float(stack, in_gamma);
- if (color.x > 0.0f)
+ if(color.x > 0.0f)
color.x = powf(color.x, gamma);
- if (color.y > 0.0f)
+ if(color.y > 0.0f)
color.y = powf(color.y, gamma);
- if (color.z > 0.0f)
+ if(color.z > 0.0f)
color.z = powf(color.z, gamma);
- if (stack_valid(out_color))
+ if(stack_valid(out_color))
stack_store_float3(stack, out_color, color);
}
diff --git a/intern/cycles/kernel/svm/svm_geometry.h b/intern/cycles/kernel/svm/svm_geometry.h
index fe681ec92af..bb06254c3a9 100644
--- a/intern/cycles/kernel/svm/svm_geometry.h
+++ b/intern/cycles/kernel/svm/svm_geometry.h
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
CCL_NAMESPACE_BEGIN
@@ -23,15 +23,15 @@ ccl_device void svm_node_geometry(KernelGlobals *kg, ShaderData *sd, float *stac
float3 data;
switch(type) {
- case NODE_GEOM_P: data = sd->P; break;
- case NODE_GEOM_N: data = sd->N; break;
+ case NODE_GEOM_P: data = ccl_fetch(sd, P); break;
+ case NODE_GEOM_N: data = ccl_fetch(sd, N); break;
#ifdef __DPDU__
case NODE_GEOM_T: data = primitive_tangent(kg, sd); break;
#endif
- case NODE_GEOM_I: data = sd->I; break;
- case NODE_GEOM_Ng: data = sd->Ng; break;
+ case NODE_GEOM_I: data = ccl_fetch(sd, I); break;
+ case NODE_GEOM_Ng: data = ccl_fetch(sd, Ng); break;
#ifdef __UV__
- case NODE_GEOM_uv: data = make_float3(sd->u, sd->v, 0.0f); break;
+ case NODE_GEOM_uv: data = make_float3(ccl_fetch(sd, u), ccl_fetch(sd, v), 0.0f); break;
#endif
}
@@ -44,8 +44,8 @@ ccl_device void svm_node_geometry_bump_dx(KernelGlobals *kg, ShaderData *sd, flo
float3 data;
switch(type) {
- case NODE_GEOM_P: data = sd->P + sd->dP.dx; break;
- case NODE_GEOM_uv: data = make_float3(sd->u + sd->du.dx, sd->v + sd->dv.dx, 0.0f); break;
+ case NODE_GEOM_P: data = ccl_fetch(sd, P) + ccl_fetch(sd, dP).dx; break;
+ case NODE_GEOM_uv: data = make_float3(ccl_fetch(sd, u) + ccl_fetch(sd, du).dx, ccl_fetch(sd, v) + ccl_fetch(sd, dv).dx, 0.0f); break;
default: svm_node_geometry(kg, sd, stack, type, out_offset); return;
}
@@ -61,8 +61,8 @@ ccl_device void svm_node_geometry_bump_dy(KernelGlobals *kg, ShaderData *sd, flo
float3 data;
switch(type) {
- case NODE_GEOM_P: data = sd->P + sd->dP.dy; break;
- case NODE_GEOM_uv: data = make_float3(sd->u + sd->du.dy, sd->v + sd->dv.dy, 0.0f); break;
+ case NODE_GEOM_P: data = ccl_fetch(sd, P) + ccl_fetch(sd, dP).dy; break;
+ case NODE_GEOM_uv: data = make_float3(ccl_fetch(sd, u) + ccl_fetch(sd, du).dy, ccl_fetch(sd, v) + ccl_fetch(sd, dv).dy, 0.0f); break;
default: svm_node_geometry(kg, sd, stack, type, out_offset); return;
}
@@ -83,9 +83,9 @@ ccl_device void svm_node_object_info(KernelGlobals *kg, ShaderData *sd, float *s
stack_store_float3(stack, out_offset, object_location(kg, sd));
return;
}
- case NODE_INFO_OB_INDEX: data = object_pass_id(kg, sd->object); break;
+ case NODE_INFO_OB_INDEX: data = object_pass_id(kg, ccl_fetch(sd, object)); break;
case NODE_INFO_MAT_INDEX: data = shader_pass_id(kg, sd); break;
- case NODE_INFO_OB_RANDOM: data = object_random_number(kg, sd->object); break;
+ case NODE_INFO_OB_RANDOM: data = object_random_number(kg, ccl_fetch(sd, object)); break;
default: data = 0.0f; break;
}
@@ -98,44 +98,44 @@ ccl_device void svm_node_particle_info(KernelGlobals *kg, ShaderData *sd, float
{
switch(type) {
case NODE_INFO_PAR_INDEX: {
- int particle_id = object_particle_id(kg, sd->object);
+ int particle_id = object_particle_id(kg, ccl_fetch(sd, object));
stack_store_float(stack, out_offset, particle_index(kg, particle_id));
break;
}
case NODE_INFO_PAR_AGE: {
- int particle_id = object_particle_id(kg, sd->object);
+ int particle_id = object_particle_id(kg, ccl_fetch(sd, object));
stack_store_float(stack, out_offset, particle_age(kg, particle_id));
break;
}
case NODE_INFO_PAR_LIFETIME: {
- int particle_id = object_particle_id(kg, sd->object);
+ int particle_id = object_particle_id(kg, ccl_fetch(sd, object));
stack_store_float(stack, out_offset, particle_lifetime(kg, particle_id));
break;
}
case NODE_INFO_PAR_LOCATION: {
- int particle_id = object_particle_id(kg, sd->object);
+ int particle_id = object_particle_id(kg, ccl_fetch(sd, object));
stack_store_float3(stack, out_offset, particle_location(kg, particle_id));
break;
}
#if 0 /* XXX float4 currently not supported in SVM stack */
case NODE_INFO_PAR_ROTATION: {
- int particle_id = object_particle_id(kg, sd->object);
+ int particle_id = object_particle_id(kg, ccl_fetch(sd, object));
stack_store_float4(stack, out_offset, particle_rotation(kg, particle_id));
break;
}
#endif
case NODE_INFO_PAR_SIZE: {
- int particle_id = object_particle_id(kg, sd->object);
+ int particle_id = object_particle_id(kg, ccl_fetch(sd, object));
stack_store_float(stack, out_offset, particle_size(kg, particle_id));
break;
}
case NODE_INFO_PAR_VELOCITY: {
- int particle_id = object_particle_id(kg, sd->object);
+ int particle_id = object_particle_id(kg, ccl_fetch(sd, object));
stack_store_float3(stack, out_offset, particle_velocity(kg, particle_id));
break;
}
case NODE_INFO_PAR_ANGULAR_VELOCITY: {
- int particle_id = object_particle_id(kg, sd->object);
+ int particle_id = object_particle_id(kg, ccl_fetch(sd, object));
stack_store_float3(stack, out_offset, particle_angular_velocity(kg, particle_id));
break;
}
@@ -153,7 +153,7 @@ ccl_device void svm_node_hair_info(KernelGlobals *kg, ShaderData *sd, float *sta
switch(type) {
case NODE_INFO_CURVE_IS_STRAND: {
- data = (sd->type & PRIMITIVE_ALL_CURVE) != 0;
+ data = (ccl_fetch(sd, type) & PRIMITIVE_ALL_CURVE) != 0;
stack_store_float(stack, out_offset, data);
break;
}
@@ -165,7 +165,7 @@ ccl_device void svm_node_hair_info(KernelGlobals *kg, ShaderData *sd, float *sta
break;
}
/*case NODE_INFO_CURVE_FADE: {
- data = sd->curve_transparency;
+ data = ccl_fetch(sd, curve_transparency);
stack_store_float(stack, out_offset, data);
break;
}*/
diff --git a/intern/cycles/kernel/svm/svm_gradient.h b/intern/cycles/kernel/svm/svm_gradient.h
index a4b3c0583f7..53d7b4f812c 100644
--- a/intern/cycles/kernel/svm/svm_gradient.h
+++ b/intern/cycles/kernel/svm/svm_gradient.h
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
CCL_NAMESPACE_BEGIN
@@ -66,7 +66,7 @@ ccl_device void svm_node_tex_gradient(ShaderData *sd, float *stack, uint4 node)
float3 co = stack_load_float3(stack, co_offset);
float f = svm_gradient(co, (NodeGradientType)type);
- f = clamp(f, 0.0f, 1.0f);
+ f = saturate(f);
if(stack_valid(fac_offset))
stack_store_float(stack, fac_offset, f);
diff --git a/intern/cycles/kernel/svm/svm_hsv.h b/intern/cycles/kernel/svm/svm_hsv.h
index 11dfc4f096b..1f2cad60df7 100644
--- a/intern/cycles/kernel/svm/svm_hsv.h
+++ b/intern/cycles/kernel/svm/svm_hsv.h
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#ifndef __SVM_HSV_H__
@@ -46,7 +46,12 @@ ccl_device void svm_node_hsv(KernelGlobals *kg, ShaderData *sd, float *stack, ui
color.y = fac*color.y + (1.0f - fac)*in_color.y;
color.z = fac*color.z + (1.0f - fac)*in_color.z;
- if (stack_valid(out_color_offset))
+ /* Clamp color to prevent negative values caused by oversaturation. */
+ color.x = max(color.x, 0.0f);
+ color.y = max(color.y, 0.0f);
+ color.z = max(color.z, 0.0f);
+
+ if(stack_valid(out_color_offset))
stack_store_float3(stack, out_color_offset, color);
}
diff --git a/intern/cycles/kernel/svm/svm_image.h b/intern/cycles/kernel/svm/svm_image.h
index a7abeda18e5..caf0b37ba35 100644
--- a/intern/cycles/kernel/svm/svm_image.h
+++ b/intern/cycles/kernel/svm/svm_image.h
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
CCL_NAMESPACE_BEGIN
@@ -65,7 +65,7 @@ ccl_device float4 svm_image_texture(KernelGlobals *kg, int id, float x, float y,
float4 r;
int ix, iy, nix, niy;
- if (interpolation == INTERPOLATION_CLOSEST) {
+ if(interpolation == INTERPOLATION_CLOSEST) {
svm_image_texture_frac(x*width, &ix);
svm_image_texture_frac(y*height, &iy);
@@ -251,9 +251,9 @@ ccl_device float4 svm_image_texture(KernelGlobals *kg, int id, float x, float y,
case 95: r = kernel_tex_image_interp(__tex_image_095, x, y); break;
case 96: r = kernel_tex_image_interp(__tex_image_096, x, y); break;
case 97: r = kernel_tex_image_interp(__tex_image_097, x, y); break;
- case 98: r = kernel_tex_image_interp(__tex_image_098, x, y); break;
#if defined(__CUDA_ARCH__) && (__CUDA_ARCH__ >= 300)
+ case 98: r = kernel_tex_image_interp(__tex_image_098, x, y); break;
case 99: r = kernel_tex_image_interp(__tex_image_099, x, y); break;
case 100: r = kernel_tex_image_interp(__tex_image_100, x, y); break;
case 101: r = kernel_tex_image_interp(__tex_image_101, x, y); break;
@@ -354,6 +354,12 @@ ccl_device float4 svm_image_texture(KernelGlobals *kg, int id, float x, float y,
#endif
+/* Remap coordnate from 0..1 box to -1..-1 */
+ccl_device_inline float3 texco_remap_square(float3 co)
+{
+ return (co - make_float3(0.5f, 0.5f, 0.5f)) * 2.0f;
+}
+
ccl_device void svm_node_tex_image(KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node)
{
uint id = node.y;
@@ -362,8 +368,20 @@ ccl_device void svm_node_tex_image(KernelGlobals *kg, ShaderData *sd, float *sta
decode_node_uchar4(node.z, &co_offset, &out_offset, &alpha_offset, &srgb);
float3 co = stack_load_float3(stack, co_offset);
+ float2 tex_co;
uint use_alpha = stack_valid(alpha_offset);
- float4 f = svm_image_texture(kg, id, co.x, co.y, srgb, use_alpha);
+ if(node.w == NODE_IMAGE_PROJ_SPHERE) {
+ co = texco_remap_square(co);
+ tex_co = map_to_sphere(co);
+ }
+ else if(node.w == NODE_IMAGE_PROJ_TUBE) {
+ co = texco_remap_square(co);
+ tex_co = map_to_tube(co);
+ }
+ else {
+ tex_co = make_float2(co.x, co.y);
+ }
+ float4 f = svm_image_texture(kg, id, tex_co.x, tex_co.y, srgb, use_alpha);
if(stack_valid(out_offset))
stack_store_float3(stack, out_offset, make_float3(f.x, f.y, f.z));
@@ -374,10 +392,10 @@ ccl_device void svm_node_tex_image(KernelGlobals *kg, ShaderData *sd, float *sta
ccl_device void svm_node_tex_image_box(KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node)
{
/* get object space normal */
- float3 N = sd->N;
+ float3 N = ccl_fetch(sd, N);
- N = sd->N;
- if(sd->object != OBJECT_NONE)
+ N = ccl_fetch(sd, N);
+ if(ccl_fetch(sd, object) != OBJECT_NONE)
object_inverse_normal_transform(kg, sd, &N);
/* project from direction vector to barycentric coordinates in triangles */
@@ -415,17 +433,17 @@ ccl_device void svm_node_tex_image_box(KernelGlobals *kg, ShaderData *sd, float
/* in case of blending, test for mixes between two textures */
if(N.z < (1.0f - limit)*(N.y + N.x)) {
weight.x = N.x/(N.x + N.y);
- weight.x = clamp((weight.x - 0.5f*(1.0f - blend))/blend, 0.0f, 1.0f);
+ weight.x = saturate((weight.x - 0.5f*(1.0f - blend))/blend);
weight.y = 1.0f - weight.x;
}
else if(N.x < (1.0f - limit)*(N.y + N.z)) {
weight.y = N.y/(N.y + N.z);
- weight.y = clamp((weight.y - 0.5f*(1.0f - blend))/blend, 0.0f, 1.0f);
+ weight.y = saturate((weight.y - 0.5f*(1.0f - blend))/blend);
weight.z = 1.0f - weight.y;
}
else if(N.y < (1.0f - limit)*(N.x + N.z)) {
weight.x = N.x/(N.x + N.z);
- weight.x = clamp((weight.x - 0.5f*(1.0f - blend))/blend, 0.0f, 1.0f);
+ weight.x = saturate((weight.x - 0.5f*(1.0f - blend))/blend);
weight.z = 1.0f - weight.x;
}
else {
@@ -435,6 +453,10 @@ ccl_device void svm_node_tex_image_box(KernelGlobals *kg, ShaderData *sd, float
weight.z = ((2.0f - limit)*N.z + (limit - 1.0f))/(2.0f*limit - 1.0f);
}
}
+ else {
+ /* Desperate mode, no valid choice anyway, fallback to one side.*/
+ weight.x = 1.0f;
+ }
/* now fetch textures */
uint co_offset, out_offset, alpha_offset, srgb;
@@ -459,7 +481,6 @@ ccl_device void svm_node_tex_image_box(KernelGlobals *kg, ShaderData *sd, float
stack_store_float(stack, alpha_offset, f.w);
}
-
ccl_device void svm_node_tex_environment(KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node)
{
uint id = node.y;
diff --git a/intern/cycles/kernel/svm/svm_invert.h b/intern/cycles/kernel/svm/svm_invert.h
index eb47e9ad4ab..5ce858e2e5d 100644
--- a/intern/cycles/kernel/svm/svm_invert.h
+++ b/intern/cycles/kernel/svm/svm_invert.h
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
CCL_NAMESPACE_BEGIN
@@ -30,7 +30,7 @@ ccl_device void svm_node_invert(ShaderData *sd, float *stack, uint in_fac, uint
color.y = invert(color.y, factor);
color.z = invert(color.z, factor);
- if (stack_valid(out_color))
+ if(stack_valid(out_color))
stack_store_float3(stack, out_color, color);
}
diff --git a/intern/cycles/kernel/svm/svm_light_path.h b/intern/cycles/kernel/svm/svm_light_path.h
index da544c63ae0..a235dd35224 100644
--- a/intern/cycles/kernel/svm/svm_light_path.h
+++ b/intern/cycles/kernel/svm/svm_light_path.h
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
CCL_NAMESPACE_BEGIN
@@ -31,10 +31,10 @@ ccl_device void svm_node_light_path(ShaderData *sd, float *stack, uint type, uin
case NODE_LP_reflection: info = (path_flag & PATH_RAY_REFLECT)? 1.0f: 0.0f; break;
case NODE_LP_transmission: info = (path_flag & PATH_RAY_TRANSMIT)? 1.0f: 0.0f; break;
case NODE_LP_volume_scatter: info = (path_flag & PATH_RAY_VOLUME_SCATTER)? 1.0f: 0.0f; break;
- case NODE_LP_backfacing: info = (sd->flag & SD_BACKFACING)? 1.0f: 0.0f; break;
- case NODE_LP_ray_length: info = sd->ray_length; break;
- case NODE_LP_ray_depth: info = (float)sd->ray_depth; break;
- case NODE_LP_ray_transparent: info = sd->transparent_depth; break;
+ case NODE_LP_backfacing: info = (ccl_fetch(sd, flag) & SD_BACKFACING)? 1.0f: 0.0f; break;
+ case NODE_LP_ray_length: info = ccl_fetch(sd, ray_length); break;
+ case NODE_LP_ray_depth: info = (float)ccl_fetch(sd, ray_depth); break;
+ case NODE_LP_ray_transparent: info = (float)ccl_fetch(sd, transparent_depth); break;
}
stack_store_float(stack, out_offset, info);
@@ -53,14 +53,14 @@ ccl_device void svm_node_light_falloff(ShaderData *sd, float *stack, uint4 node)
switch(type) {
case NODE_LIGHT_FALLOFF_QUADRATIC: break;
- case NODE_LIGHT_FALLOFF_LINEAR: strength *= sd->ray_length; break;
- case NODE_LIGHT_FALLOFF_CONSTANT: strength *= sd->ray_length*sd->ray_length; break;
+ case NODE_LIGHT_FALLOFF_LINEAR: strength *= ccl_fetch(sd, ray_length); break;
+ case NODE_LIGHT_FALLOFF_CONSTANT: strength *= ccl_fetch(sd, ray_length)*ccl_fetch(sd, ray_length); break;
}
float smooth = stack_load_float(stack, smooth_offset);
if(smooth > 0.0f) {
- float squared = sd->ray_length*sd->ray_length;
+ float squared = ccl_fetch(sd, ray_length)*ccl_fetch(sd, ray_length);
strength *= squared/(smooth + squared);
}
diff --git a/intern/cycles/kernel/svm/svm_magic.h b/intern/cycles/kernel/svm/svm_magic.h
index b661f5cacf8..ac87c77d719 100644
--- a/intern/cycles/kernel/svm/svm_magic.h
+++ b/intern/cycles/kernel/svm/svm_magic.h
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
CCL_NAMESPACE_BEGIN
diff --git a/intern/cycles/kernel/svm/svm_mapping.h b/intern/cycles/kernel/svm/svm_mapping.h
index c9fa8502dd1..0a890545af4 100644
--- a/intern/cycles/kernel/svm/svm_mapping.h
+++ b/intern/cycles/kernel/svm/svm_mapping.h
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
CCL_NAMESPACE_BEGIN
diff --git a/intern/cycles/kernel/svm/svm_math.h b/intern/cycles/kernel/svm/svm_math.h
index 1ce9386e40e..d633e54ed8d 100644
--- a/intern/cycles/kernel/svm/svm_math.h
+++ b/intern/cycles/kernel/svm/svm_math.h
@@ -11,99 +11,11 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
CCL_NAMESPACE_BEGIN
-ccl_device float svm_math(NodeMath type, float Fac1, float Fac2)
-{
- float Fac;
-
- if(type == NODE_MATH_ADD)
- Fac = Fac1 + Fac2;
- else if(type == NODE_MATH_SUBTRACT)
- Fac = Fac1 - Fac2;
- else if(type == NODE_MATH_MULTIPLY)
- Fac = Fac1*Fac2;
- else if(type == NODE_MATH_DIVIDE)
- Fac = safe_divide(Fac1, Fac2);
- else if(type == NODE_MATH_SINE)
- Fac = sinf(Fac1);
- else if(type == NODE_MATH_COSINE)
- Fac = cosf(Fac1);
- else if(type == NODE_MATH_TANGENT)
- Fac = tanf(Fac1);
- else if(type == NODE_MATH_ARCSINE)
- Fac = safe_asinf(Fac1);
- else if(type == NODE_MATH_ARCCOSINE)
- Fac = safe_acosf(Fac1);
- else if(type == NODE_MATH_ARCTANGENT)
- Fac = atanf(Fac1);
- else if(type == NODE_MATH_POWER)
- Fac = safe_powf(Fac1, Fac2);
- else if(type == NODE_MATH_LOGARITHM)
- Fac = safe_logf(Fac1, Fac2);
- else if(type == NODE_MATH_MINIMUM)
- Fac = fminf(Fac1, Fac2);
- else if(type == NODE_MATH_MAXIMUM)
- Fac = fmaxf(Fac1, Fac2);
- else if(type == NODE_MATH_ROUND)
- Fac = floorf(Fac1 + 0.5f);
- else if(type == NODE_MATH_LESS_THAN)
- Fac = Fac1 < Fac2;
- else if(type == NODE_MATH_GREATER_THAN)
- Fac = Fac1 > Fac2;
- else if(type == NODE_MATH_MODULO)
- Fac = safe_modulo(Fac1, Fac2);
- else if(type == NODE_MATH_ABSOLUTE)
- Fac = fabsf(Fac1);
- else if(type == NODE_MATH_CLAMP)
- Fac = clamp(Fac1, 0.0f, 1.0f);
- else
- Fac = 0.0f;
-
- return Fac;
-}
-
-ccl_device float average_fac(float3 v)
-{
- return (fabsf(v.x) + fabsf(v.y) + fabsf(v.z))/3.0f;
-}
-
-ccl_device void svm_vector_math(float *Fac, float3 *Vector, NodeVectorMath type, float3 Vector1, float3 Vector2)
-{
- if(type == NODE_VECTOR_MATH_ADD) {
- *Vector = Vector1 + Vector2;
- *Fac = average_fac(*Vector);
- }
- else if(type == NODE_VECTOR_MATH_SUBTRACT) {
- *Vector = Vector1 - Vector2;
- *Fac = average_fac(*Vector);
- }
- else if(type == NODE_VECTOR_MATH_AVERAGE) {
- *Fac = len(Vector1 + Vector2);
- *Vector = normalize(Vector1 + Vector2);
- }
- else if(type == NODE_VECTOR_MATH_DOT_PRODUCT) {
- *Fac = dot(Vector1, Vector2);
- *Vector = make_float3(0.0f, 0.0f, 0.0f);
- }
- else if(type == NODE_VECTOR_MATH_CROSS_PRODUCT) {
- float3 c = cross(Vector1, Vector2);
- *Fac = len(c);
- *Vector = normalize(c);
- }
- else if(type == NODE_VECTOR_MATH_NORMALIZE) {
- *Fac = len(Vector1);
- *Vector = normalize(Vector1);
- }
- else {
- *Fac = 0.0f;
- *Vector = make_float3(0.0f, 0.0f, 0.0f);
- }
-}
-
/* Nodes */
ccl_device void svm_node_math(KernelGlobals *kg, ShaderData *sd, float *stack, uint itype, uint f1_offset, uint f2_offset, int *offset)
diff --git a/intern/cycles/kernel/svm/svm_math_util.h b/intern/cycles/kernel/svm/svm_math_util.h
new file mode 100644
index 00000000000..645cbd3fc73
--- /dev/null
+++ b/intern/cycles/kernel/svm/svm_math_util.h
@@ -0,0 +1,170 @@
+/*
+ * Copyright 2011-2014 Blender Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+CCL_NAMESPACE_BEGIN
+
+ccl_device float average_fac(float3 v)
+{
+ return (fabsf(v.x) + fabsf(v.y) + fabsf(v.z))/3.0f;
+}
+
+ccl_device void svm_vector_math(float *Fac, float3 *Vector, NodeVectorMath type, float3 Vector1, float3 Vector2)
+{
+ if(type == NODE_VECTOR_MATH_ADD) {
+ *Vector = Vector1 + Vector2;
+ *Fac = average_fac(*Vector);
+ }
+ else if(type == NODE_VECTOR_MATH_SUBTRACT) {
+ *Vector = Vector1 - Vector2;
+ *Fac = average_fac(*Vector);
+ }
+ else if(type == NODE_VECTOR_MATH_AVERAGE) {
+ *Fac = len(Vector1 + Vector2);
+ *Vector = normalize(Vector1 + Vector2);
+ }
+ else if(type == NODE_VECTOR_MATH_DOT_PRODUCT) {
+ *Fac = dot(Vector1, Vector2);
+ *Vector = make_float3(0.0f, 0.0f, 0.0f);
+ }
+ else if(type == NODE_VECTOR_MATH_CROSS_PRODUCT) {
+ float3 c = cross(Vector1, Vector2);
+ *Fac = len(c);
+ *Vector = normalize(c);
+ }
+ else if(type == NODE_VECTOR_MATH_NORMALIZE) {
+ *Fac = len(Vector1);
+ *Vector = normalize(Vector1);
+ }
+ else {
+ *Fac = 0.0f;
+ *Vector = make_float3(0.0f, 0.0f, 0.0f);
+ }
+}
+
+ccl_device float svm_math(NodeMath type, float Fac1, float Fac2)
+{
+ float Fac;
+
+ if(type == NODE_MATH_ADD)
+ Fac = Fac1 + Fac2;
+ else if(type == NODE_MATH_SUBTRACT)
+ Fac = Fac1 - Fac2;
+ else if(type == NODE_MATH_MULTIPLY)
+ Fac = Fac1*Fac2;
+ else if(type == NODE_MATH_DIVIDE)
+ Fac = safe_divide(Fac1, Fac2);
+ else if(type == NODE_MATH_SINE)
+ Fac = sinf(Fac1);
+ else if(type == NODE_MATH_COSINE)
+ Fac = cosf(Fac1);
+ else if(type == NODE_MATH_TANGENT)
+ Fac = tanf(Fac1);
+ else if(type == NODE_MATH_ARCSINE)
+ Fac = safe_asinf(Fac1);
+ else if(type == NODE_MATH_ARCCOSINE)
+ Fac = safe_acosf(Fac1);
+ else if(type == NODE_MATH_ARCTANGENT)
+ Fac = atanf(Fac1);
+ else if(type == NODE_MATH_POWER)
+ Fac = safe_powf(Fac1, Fac2);
+ else if(type == NODE_MATH_LOGARITHM)
+ Fac = safe_logf(Fac1, Fac2);
+ else if(type == NODE_MATH_MINIMUM)
+ Fac = fminf(Fac1, Fac2);
+ else if(type == NODE_MATH_MAXIMUM)
+ Fac = fmaxf(Fac1, Fac2);
+ else if(type == NODE_MATH_ROUND)
+ Fac = floorf(Fac1 + 0.5f);
+ else if(type == NODE_MATH_LESS_THAN)
+ Fac = Fac1 < Fac2;
+ else if(type == NODE_MATH_GREATER_THAN)
+ Fac = Fac1 > Fac2;
+ else if(type == NODE_MATH_MODULO)
+ Fac = safe_modulo(Fac1, Fac2);
+ else if(type == NODE_MATH_ABSOLUTE)
+ Fac = fabsf(Fac1);
+ else if(type == NODE_MATH_CLAMP)
+ Fac = saturate(Fac1);
+ else
+ Fac = 0.0f;
+
+ return Fac;
+}
+
+ccl_device float3 svm_math_blackbody_color(float t) {
+ /* Calculate color in range 800..12000 using an approximation
+ * a/x+bx+c for R and G and ((at + b)t + c)t + d) for B
+ * Max absolute error for RGB is (0.00095, 0.00077, 0.00057),
+ * which is enough to get the same 8 bit/channel color.
+ */
+
+ const float rc[6][3] = {
+ { 2.52432244e+03f, -1.06185848e-03f, 3.11067539e+00f },
+ { 3.37763626e+03f, -4.34581697e-04f, 1.64843306e+00f },
+ { 4.10671449e+03f, -8.61949938e-05f, 6.41423749e-01f },
+ { 4.66849800e+03f, 2.85655028e-05f, 1.29075375e-01f },
+ { 4.60124770e+03f, 2.89727618e-05f, 1.48001316e-01f },
+ { 3.78765709e+03f, 9.36026367e-06f, 3.98995841e-01f },
+ };
+
+ const float gc[6][3] = {
+ { -7.50343014e+02f, 3.15679613e-04f, 4.73464526e-01f },
+ { -1.00402363e+03f, 1.29189794e-04f, 9.08181524e-01f },
+ { -1.22075471e+03f, 2.56245413e-05f, 1.20753416e+00f },
+ { -1.42546105e+03f, -4.01730887e-05f, 1.44002695e+00f },
+ { -1.18134453e+03f, -2.18913373e-05f, 1.30656109e+00f },
+ { -5.00279505e+02f, -4.59745390e-06f, 1.09090465e+00f },
+ };
+
+ const float bc[6][4] = {
+ { 0.0f, 0.0f, 0.0f, 0.0f }, /* zeros should be optimized by compiler */
+ { 0.0f, 0.0f, 0.0f, 0.0f },
+ { 0.0f, 0.0f, 0.0f, 0.0f },
+ { -2.02524603e-11f, 1.79435860e-07f, -2.60561875e-04f, -1.41761141e-02f },
+ { -2.22463426e-13f, -1.55078698e-08f, 3.81675160e-04f, -7.30646033e-01f },
+ { 6.72595954e-13f, -2.73059993e-08f, 4.24068546e-04f, -7.52204323e-01f },
+ };
+
+ if(t >= 12000.0f)
+ return make_float3(0.826270103f, 0.994478524f, 1.56626022f);
+
+ /* Define a macro to reduce stack usage for nvcc */
+#define MAKE_BB_RGB(i) make_float3(\
+ rc[i][0] / t + rc[i][1] * t + rc[i][2],\
+ gc[i][0] / t + gc[i][1] * t + gc[i][2],\
+ ((bc[i][0] * t + bc[i][1]) * t + bc[i][2]) * t + bc[i][3])
+
+ if(t >= 6365.0f)
+ return MAKE_BB_RGB(5);
+ if(t >= 3315.0f)
+ return MAKE_BB_RGB(4);
+ if(t >= 1902.0f)
+ return MAKE_BB_RGB(3);
+ if(t >= 1449.0f)
+ return MAKE_BB_RGB(2);
+ if(t >= 1167.0f)
+ return MAKE_BB_RGB(1);
+ if(t >= 965.0f)
+ return MAKE_BB_RGB(0);
+
+#undef MAKE_BB_RGB
+
+ /* For 800 <= t < 965 color does not change in OSL implementation, so keep color the same */
+ return make_float3(4.70366907f, 0.0f, 0.0f);
+}
+
+CCL_NAMESPACE_END
+
diff --git a/intern/cycles/kernel/svm/svm_mix.h b/intern/cycles/kernel/svm/svm_mix.h
index edc3903865e..6111214acba 100644
--- a/intern/cycles/kernel/svm/svm_mix.h
+++ b/intern/cycles/kernel/svm/svm_mix.h
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
CCL_NAMESPACE_BEGIN
@@ -254,16 +254,16 @@ ccl_device float3 svm_mix_clamp(float3 col)
{
float3 outcol = col;
- outcol.x = clamp(col.x, 0.0f, 1.0f);
- outcol.y = clamp(col.y, 0.0f, 1.0f);
- outcol.z = clamp(col.z, 0.0f, 1.0f);
+ outcol.x = saturate(col.x);
+ outcol.y = saturate(col.y);
+ outcol.z = saturate(col.z);
return outcol;
}
ccl_device float3 svm_mix(NodeMix type, float fac, float3 c1, float3 c2)
{
- float t = clamp(fac, 0.0f, 1.0f);
+ float t = saturate(fac);
switch(type) {
case NODE_MIX_BLEND: return svm_mix_blend(t, c1, c2);
diff --git a/intern/cycles/kernel/svm/svm_musgrave.h b/intern/cycles/kernel/svm/svm_musgrave.h
index 61171d6849c..09eba31945e 100644
--- a/intern/cycles/kernel/svm/svm_musgrave.h
+++ b/intern/cycles/kernel/svm/svm_musgrave.h
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
CCL_NAMESPACE_BEGIN
@@ -25,7 +25,7 @@ CCL_NAMESPACE_BEGIN
* from "Texturing and Modelling: A procedural approach"
*/
-ccl_device_noinline float noise_musgrave_fBm(float3 p, NodeNoiseBasis basis, float H, float lacunarity, float octaves)
+ccl_device_noinline float noise_musgrave_fBm(float3 p, float H, float lacunarity, float octaves)
{
float rmd;
float value = 0.0f;
@@ -53,7 +53,7 @@ ccl_device_noinline float noise_musgrave_fBm(float3 p, NodeNoiseBasis basis, flo
* octaves: number of frequencies in the fBm
*/
-ccl_device_noinline float noise_musgrave_multi_fractal(float3 p, NodeNoiseBasis basis, float H, float lacunarity, float octaves)
+ccl_device_noinline float noise_musgrave_multi_fractal(float3 p, float H, float lacunarity, float octaves)
{
float rmd;
float value = 1.0f;
@@ -82,7 +82,7 @@ ccl_device_noinline float noise_musgrave_multi_fractal(float3 p, NodeNoiseBasis
* offset: raises the terrain from `sea level'
*/
-ccl_device_noinline float noise_musgrave_hetero_terrain(float3 p, NodeNoiseBasis basis, float H, float lacunarity, float octaves, float offset)
+ccl_device_noinline float noise_musgrave_hetero_terrain(float3 p, float H, float lacunarity, float octaves, float offset)
{
float value, increment, rmd;
float pwHL = powf(lacunarity, -H);
@@ -117,7 +117,7 @@ ccl_device_noinline float noise_musgrave_hetero_terrain(float3 p, NodeNoiseBasis
* offset: raises the terrain from `sea level'
*/
-ccl_device_noinline float noise_musgrave_hybrid_multi_fractal(float3 p, NodeNoiseBasis basis, float H, float lacunarity, float octaves, float offset, float gain)
+ccl_device_noinline float noise_musgrave_hybrid_multi_fractal(float3 p, float H, float lacunarity, float octaves, float offset, float gain)
{
float result, signal, weight, rmd;
float pwHL = powf(lacunarity, -H);
@@ -154,7 +154,7 @@ ccl_device_noinline float noise_musgrave_hybrid_multi_fractal(float3 p, NodeNois
* offset: raises the terrain from `sea level'
*/
-ccl_device_noinline float noise_musgrave_ridged_multi_fractal(float3 p, NodeNoiseBasis basis, float H, float lacunarity, float octaves, float offset, float gain)
+ccl_device_noinline float noise_musgrave_ridged_multi_fractal(float3 p, float H, float lacunarity, float octaves, float offset, float gain)
{
float result, signal, weight;
float pwHL = powf(lacunarity, -H);
@@ -168,7 +168,7 @@ ccl_device_noinline float noise_musgrave_ridged_multi_fractal(float3 p, NodeNois
for(i = 1; i < float_to_int(octaves); i++) {
p *= lacunarity;
- weight = clamp(signal * gain, 0.0f, 1.0f);
+ weight = saturate(signal * gain);
signal = offset - fabsf(snoise(p));
signal *= signal;
signal *= weight;
@@ -183,18 +183,16 @@ ccl_device_noinline float noise_musgrave_ridged_multi_fractal(float3 p, NodeNois
ccl_device float svm_musgrave(NodeMusgraveType type, float dimension, float lacunarity, float octaves, float offset, float intensity, float gain, float3 p)
{
- NodeNoiseBasis basis = NODE_NOISE_PERLIN;
-
if(type == NODE_MUSGRAVE_MULTIFRACTAL)
- return intensity*noise_musgrave_multi_fractal(p, basis, dimension, lacunarity, octaves);
+ return intensity*noise_musgrave_multi_fractal(p, dimension, lacunarity, octaves);
else if(type == NODE_MUSGRAVE_FBM)
- return intensity*noise_musgrave_fBm(p, basis, dimension, lacunarity, octaves);
+ return intensity*noise_musgrave_fBm(p, dimension, lacunarity, octaves);
else if(type == NODE_MUSGRAVE_HYBRID_MULTIFRACTAL)
- return intensity*noise_musgrave_hybrid_multi_fractal(p, basis, dimension, lacunarity, octaves, offset, gain);
+ return intensity*noise_musgrave_hybrid_multi_fractal(p, dimension, lacunarity, octaves, offset, gain);
else if(type == NODE_MUSGRAVE_RIDGED_MULTIFRACTAL)
- return intensity*noise_musgrave_ridged_multi_fractal(p, basis, dimension, lacunarity, octaves, offset, gain);
+ return intensity*noise_musgrave_ridged_multi_fractal(p, dimension, lacunarity, octaves, offset, gain);
else if(type == NODE_MUSGRAVE_HETERO_TERRAIN)
- return intensity*noise_musgrave_hetero_terrain(p, basis, dimension, lacunarity, octaves, offset);
+ return intensity*noise_musgrave_hetero_terrain(p, dimension, lacunarity, octaves, offset);
return 0.0f;
}
diff --git a/intern/cycles/kernel/svm/svm_noise.h b/intern/cycles/kernel/svm/svm_noise.h
index 869341c81f4..c77c2a1c482 100644
--- a/intern/cycles/kernel/svm/svm_noise.h
+++ b/intern/cycles/kernel/svm/svm_noise.h
@@ -290,40 +290,6 @@ ccl_device_noinline float perlin(float x, float y, float z)
}
#endif
-#if 0 // unused
-ccl_device_noinline float perlin_periodic(float x, float y, float z, float3 pperiod)
-{
- int X; float fx = floorfrac(x, &X);
- int Y; float fy = floorfrac(y, &Y);
- int Z; float fz = floorfrac(z, &Z);
-
- int3 p;
-
- p.x = max(quick_floor(pperiod.x), 1);
- p.y = max(quick_floor(pperiod.y), 1);
- p.z = max(quick_floor(pperiod.z), 1);
-
- float u = fade(fx);
- float v = fade(fy);
- float w = fade(fz);
-
- float result;
-
- result = nerp (w, nerp (v, nerp (u, grad (phash (X , Y , Z , p), fx , fy , fz ),
- grad (phash (X+1, Y , Z , p), fx-1.0f, fy , fz )),
- nerp (u, grad (phash (X , Y+1, Z , p), fx , fy-1.0f, fz ),
- grad (phash (X+1, Y+1, Z , p), fx-1.0f, fy-1.0f, fz ))),
- nerp (v, nerp (u, grad (phash (X , Y , Z+1, p), fx , fy , fz-1.0f ),
- grad (phash (X+1, Y , Z+1, p), fx-1.0f, fy , fz-1.0f )),
- nerp (u, grad (phash (X , Y+1, Z+1, p), fx , fy-1.0f, fz-1.0f ),
- grad (phash (X+1, Y+1, Z+1, p), fx-1.0f, fy-1.0f, fz-1.0f ))));
- float r = scale3(result);
-
- /* can happen for big coordinates, things even out to 0.0 then anyway */
- return (isfinite(r))? r: 0.0f;
-}
-#endif
-
/* perlin noise in range 0..1 */
ccl_device float noise(float3 p)
{
@@ -367,20 +333,5 @@ ccl_device ssef cellnoise_color(const ssef& p)
}
#endif
-#if 0 // unused
-/* periodic perlin noise in range 0..1 */
-ccl_device float pnoise(float3 p, float3 pperiod)
-{
- float r = perlin_periodic(p.x, p.y, p.z, pperiod);
- return 0.5f*r + 0.5f;
-}
-
-/* periodic perlin noise in range -1..1 */
-ccl_device float psnoise(float3 p, float3 pperiod)
-{
- return perlin_periodic(p.x, p.y, p.z, pperiod);
-}
-#endif
-
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/svm/svm_noisetex.h b/intern/cycles/kernel/svm/svm_noisetex.h
index 5d5cfe6ffcc..62ff38cf1c5 100644
--- a/intern/cycles/kernel/svm/svm_noisetex.h
+++ b/intern/cycles/kernel/svm/svm_noisetex.h
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
CCL_NAMESPACE_BEGIN
@@ -20,23 +20,22 @@ CCL_NAMESPACE_BEGIN
ccl_device_inline void svm_noise(float3 p, float detail, float distortion, float *fac, float3 *color)
{
- NodeNoiseBasis basis = NODE_NOISE_PERLIN;
int hard = 0;
if(distortion != 0.0f) {
float3 r, offset = make_float3(13.5f, 13.5f, 13.5f);
- r.x = noise_basis(p + offset, basis) * distortion;
- r.y = noise_basis(p, basis) * distortion;
- r.z = noise_basis(p - offset, basis) * distortion;
+ r.x = noise(p + offset) * distortion;
+ r.y = noise(p) * distortion;
+ r.z = noise(p - offset) * distortion;
p += r;
}
- *fac = noise_turbulence(p, basis, detail, hard);
+ *fac = noise_turbulence(p, detail, hard);
*color = make_float3(*fac,
- noise_turbulence(make_float3(p.y, p.x, p.z), basis, detail, hard),
- noise_turbulence(make_float3(p.y, p.z, p.x), basis, detail, hard));
+ noise_turbulence(make_float3(p.y, p.x, p.z), detail, hard),
+ noise_turbulence(make_float3(p.y, p.z, p.x), detail, hard));
}
ccl_device void svm_node_tex_noise(KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node, int *offset)
diff --git a/intern/cycles/kernel/svm/svm_normal.h b/intern/cycles/kernel/svm/svm_normal.h
index 8695031b8b9..53abef71012 100644
--- a/intern/cycles/kernel/svm/svm_normal.h
+++ b/intern/cycles/kernel/svm/svm_normal.h
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
CCL_NAMESPACE_BEGIN
@@ -28,10 +28,10 @@ ccl_device void svm_node_normal(KernelGlobals *kg, ShaderData *sd, float *stack,
direction.z = __int_as_float(node1.z);
direction = normalize(direction);
- if (stack_valid(out_normal_offset))
+ if(stack_valid(out_normal_offset))
stack_store_float3(stack, out_normal_offset, direction);
- if (stack_valid(out_dot_offset))
+ if(stack_valid(out_dot_offset))
stack_store_float(stack, out_dot_offset, dot(direction, normalize(normal)));
}
diff --git a/intern/cycles/kernel/svm/svm_ramp.h b/intern/cycles/kernel/svm/svm_ramp.h
index 55eee3d24c3..062ab013b1f 100644
--- a/intern/cycles/kernel/svm/svm_ramp.h
+++ b/intern/cycles/kernel/svm/svm_ramp.h
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#ifndef __SVM_RAMP_H__
@@ -21,7 +21,7 @@ CCL_NAMESPACE_BEGIN
ccl_device float4 rgb_ramp_lookup(KernelGlobals *kg, int offset, float f, bool interpolate)
{
- f = clamp(f, 0.0f, 1.0f)*(RAMP_TABLE_SIZE-1);
+ f = saturate(f)*(RAMP_TABLE_SIZE-1);
/* clamp int as well in case of NaN */
int i = clamp(float_to_int(f), 0, RAMP_TABLE_SIZE-1);
diff --git a/intern/cycles/kernel/svm/svm_sepcomb_hsv.h b/intern/cycles/kernel/svm/svm_sepcomb_hsv.h
index 111d5d47988..6f51b163756 100644
--- a/intern/cycles/kernel/svm/svm_sepcomb_hsv.h
+++ b/intern/cycles/kernel/svm/svm_sepcomb_hsv.h
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
CCL_NAMESPACE_BEGIN
@@ -28,7 +28,7 @@ ccl_device void svm_node_combine_hsv(KernelGlobals *kg, ShaderData *sd, float *s
/* Combine, and convert back to RGB */
float3 color = hsv_to_rgb(make_float3(hue, saturation, value));
- if (stack_valid(color_out))
+ if(stack_valid(color_out))
stack_store_float3(stack, color_out, color);
}
@@ -42,11 +42,11 @@ ccl_device void svm_node_separate_hsv(KernelGlobals *kg, ShaderData *sd, float *
/* Convert to HSV */
color = rgb_to_hsv(color);
- if (stack_valid(hue_out))
+ if(stack_valid(hue_out))
stack_store_float(stack, hue_out, color.x);
- if (stack_valid(saturation_out))
+ if(stack_valid(saturation_out))
stack_store_float(stack, saturation_out, color.y);
- if (stack_valid(value_out))
+ if(stack_valid(value_out))
stack_store_float(stack, value_out, color.z);
}
diff --git a/intern/cycles/kernel/svm/svm_sepcomb_vector.h b/intern/cycles/kernel/svm/svm_sepcomb_vector.h
index c8e7e34f87d..63570dd6942 100644
--- a/intern/cycles/kernel/svm/svm_sepcomb_vector.h
+++ b/intern/cycles/kernel/svm/svm_sepcomb_vector.h
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
CCL_NAMESPACE_BEGIN
@@ -22,7 +22,7 @@ ccl_device void svm_node_combine_vector(ShaderData *sd, float *stack, uint in_of
{
float vector = stack_load_float(stack, in_offset);
- if (stack_valid(out_offset))
+ if(stack_valid(out_offset))
stack_store_float(stack, out_offset+vector_index, vector);
}
@@ -30,10 +30,10 @@ ccl_device void svm_node_separate_vector(ShaderData *sd, float *stack, uint ivec
{
float3 vector = stack_load_float3(stack, ivector_offset);
- if (stack_valid(out_offset)) {
- if (vector_index == 0)
+ if(stack_valid(out_offset)) {
+ if(vector_index == 0)
stack_store_float(stack, out_offset, vector.x);
- else if (vector_index == 1)
+ else if(vector_index == 1)
stack_store_float(stack, out_offset, vector.y);
else
stack_store_float(stack, out_offset, vector.z);
diff --git a/intern/cycles/kernel/svm/svm_sky.h b/intern/cycles/kernel/svm/svm_sky.h
index 500b5146931..4c8e3a32271 100644
--- a/intern/cycles/kernel/svm/svm_sky.h
+++ b/intern/cycles/kernel/svm/svm_sky.h
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
CCL_NAMESPACE_BEGIN
diff --git a/intern/cycles/kernel/svm/svm_tex_coord.h b/intern/cycles/kernel/svm/svm_tex_coord.h
index a17e4a25efe..eebd9bee420 100644
--- a/intern/cycles/kernel/svm/svm_tex_coord.h
+++ b/intern/cycles/kernel/svm/svm_tex_coord.h
@@ -11,67 +11,85 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
CCL_NAMESPACE_BEGIN
/* Texture Coordinate Node */
-ccl_device void svm_node_tex_coord(KernelGlobals *kg, ShaderData *sd, int path_flag, float *stack, uint type, uint out_offset)
+ccl_device void svm_node_tex_coord(KernelGlobals *kg,
+ ShaderData *sd,
+ int path_flag,
+ float *stack,
+ uint4 node,
+ int *offset)
{
float3 data;
+ uint type = node.y;
+ uint out_offset = node.z;
switch(type) {
case NODE_TEXCO_OBJECT: {
- data = sd->P;
- if(sd->object != OBJECT_NONE)
- object_inverse_position_transform(kg, sd, &data);
+ data = ccl_fetch(sd, P);
+ if(node.w == 0) {
+ if(ccl_fetch(sd, object) != OBJECT_NONE) {
+ object_inverse_position_transform(kg, sd, &data);
+ }
+ }
+ else {
+ Transform tfm;
+ tfm.x = read_node_float(kg, offset);
+ tfm.y = read_node_float(kg, offset);
+ tfm.z = read_node_float(kg, offset);
+ tfm.w = read_node_float(kg, offset);
+ data = transform_point(&tfm, data);
+ }
break;
}
case NODE_TEXCO_NORMAL: {
- data = sd->N;
- if(sd->object != OBJECT_NONE)
+ data = ccl_fetch(sd, N);
+ if(ccl_fetch(sd, object) != OBJECT_NONE)
object_inverse_normal_transform(kg, sd, &data);
break;
}
case NODE_TEXCO_CAMERA: {
Transform tfm = kernel_data.cam.worldtocamera;
- if(sd->object != OBJECT_NONE)
- data = transform_point(&tfm, sd->P);
+ if(ccl_fetch(sd, object) != OBJECT_NONE)
+ data = transform_point(&tfm, ccl_fetch(sd, P));
else
- data = transform_point(&tfm, sd->P + camera_position(kg));
+ data = transform_point(&tfm, ccl_fetch(sd, P) + camera_position(kg));
break;
}
case NODE_TEXCO_WINDOW: {
- if((path_flag & PATH_RAY_CAMERA) && sd->object == OBJECT_NONE && kernel_data.cam.type == CAMERA_ORTHOGRAPHIC)
- data = camera_world_to_ndc(kg, sd, sd->ray_P);
+ if((path_flag & PATH_RAY_CAMERA) && ccl_fetch(sd, object) == OBJECT_NONE && kernel_data.cam.type == CAMERA_ORTHOGRAPHIC)
+ data = camera_world_to_ndc(kg, sd, ccl_fetch(sd, ray_P));
else
- data = camera_world_to_ndc(kg, sd, sd->P);
+ data = camera_world_to_ndc(kg, sd, ccl_fetch(sd, P));
data.z = 0.0f;
break;
}
case NODE_TEXCO_REFLECTION: {
- if(sd->object != OBJECT_NONE)
- data = 2.0f*dot(sd->N, sd->I)*sd->N - sd->I;
+ if(ccl_fetch(sd, object) != OBJECT_NONE)
+ data = 2.0f*dot(ccl_fetch(sd, N), ccl_fetch(sd, I))*ccl_fetch(sd, N) - ccl_fetch(sd, I);
else
- data = sd->I;
+ data = ccl_fetch(sd, I);
break;
}
case NODE_TEXCO_DUPLI_GENERATED: {
- data = object_dupli_generated(kg, sd->object);
+ data = object_dupli_generated(kg, ccl_fetch(sd, object));
break;
}
case NODE_TEXCO_DUPLI_UV: {
- data = object_dupli_uv(kg, sd->object);
+ data = object_dupli_uv(kg, ccl_fetch(sd, object));
break;
}
case NODE_TEXCO_VOLUME_GENERATED: {
- data = sd->P;
+ data = ccl_fetch(sd, P);
#ifdef __VOLUME__
- if(sd->object != OBJECT_NONE)
+ if(ccl_fetch(sd, object) != OBJECT_NONE)
data = volume_normalized_position(kg, sd, data);
#endif
break;
@@ -81,61 +99,79 @@ ccl_device void svm_node_tex_coord(KernelGlobals *kg, ShaderData *sd, int path_f
stack_store_float3(stack, out_offset, data);
}
-ccl_device void svm_node_tex_coord_bump_dx(KernelGlobals *kg, ShaderData *sd, int path_flag, float *stack, uint type, uint out_offset)
+ccl_device void svm_node_tex_coord_bump_dx(KernelGlobals *kg,
+ ShaderData *sd,
+ int path_flag,
+ float *stack,
+ uint4 node,
+ int *offset)
{
#ifdef __RAY_DIFFERENTIALS__
float3 data;
+ uint type = node.y;
+ uint out_offset = node.z;
switch(type) {
case NODE_TEXCO_OBJECT: {
- data = sd->P + sd->dP.dx;
- if(sd->object != OBJECT_NONE)
- object_inverse_position_transform(kg, sd, &data);
+ data = ccl_fetch(sd, P) + ccl_fetch(sd, dP).dx;
+ if(node.w == 0) {
+ if(ccl_fetch(sd, object) != OBJECT_NONE) {
+ object_inverse_position_transform(kg, sd, &data);
+ }
+ }
+ else {
+ Transform tfm;
+ tfm.x = read_node_float(kg, offset);
+ tfm.y = read_node_float(kg, offset);
+ tfm.z = read_node_float(kg, offset);
+ tfm.w = read_node_float(kg, offset);
+ data = transform_point(&tfm, data);
+ }
break;
}
case NODE_TEXCO_NORMAL: {
- data = sd->N;
- if(sd->object != OBJECT_NONE)
+ data = ccl_fetch(sd, N);
+ if(ccl_fetch(sd, object) != OBJECT_NONE)
object_inverse_normal_transform(kg, sd, &data);
break;
}
case NODE_TEXCO_CAMERA: {
Transform tfm = kernel_data.cam.worldtocamera;
- if(sd->object != OBJECT_NONE)
- data = transform_point(&tfm, sd->P + sd->dP.dx);
+ if(ccl_fetch(sd, object) != OBJECT_NONE)
+ data = transform_point(&tfm, ccl_fetch(sd, P) + ccl_fetch(sd, dP).dx);
else
- data = transform_point(&tfm, sd->P + sd->dP.dx + camera_position(kg));
+ data = transform_point(&tfm, ccl_fetch(sd, P) + ccl_fetch(sd, dP).dx + camera_position(kg));
break;
}
case NODE_TEXCO_WINDOW: {
- if((path_flag & PATH_RAY_CAMERA) && sd->object == OBJECT_NONE && kernel_data.cam.type == CAMERA_ORTHOGRAPHIC)
- data = camera_world_to_ndc(kg, sd, sd->ray_P + sd->ray_dP.dx);
+ if((path_flag & PATH_RAY_CAMERA) && ccl_fetch(sd, object) == OBJECT_NONE && kernel_data.cam.type == CAMERA_ORTHOGRAPHIC)
+ data = camera_world_to_ndc(kg, sd, ccl_fetch(sd, ray_P) + ccl_fetch(sd, ray_dP).dx);
else
- data = camera_world_to_ndc(kg, sd, sd->P + sd->dP.dx);
+ data = camera_world_to_ndc(kg, sd, ccl_fetch(sd, P) + ccl_fetch(sd, dP).dx);
data.z = 0.0f;
break;
}
case NODE_TEXCO_REFLECTION: {
- if(sd->object != OBJECT_NONE)
- data = 2.0f*dot(sd->N, sd->I)*sd->N - sd->I;
+ if(ccl_fetch(sd, object) != OBJECT_NONE)
+ data = 2.0f*dot(ccl_fetch(sd, N), ccl_fetch(sd, I))*ccl_fetch(sd, N) - ccl_fetch(sd, I);
else
- data = sd->I;
+ data = ccl_fetch(sd, I);
break;
}
case NODE_TEXCO_DUPLI_GENERATED: {
- data = object_dupli_generated(kg, sd->object);
+ data = object_dupli_generated(kg, ccl_fetch(sd, object));
break;
}
case NODE_TEXCO_DUPLI_UV: {
- data = object_dupli_uv(kg, sd->object);
+ data = object_dupli_uv(kg, ccl_fetch(sd, object));
break;
}
case NODE_TEXCO_VOLUME_GENERATED: {
- data = sd->P + sd->dP.dx;
+ data = ccl_fetch(sd, P) + ccl_fetch(sd, dP).dx;
#ifdef __VOLUME__
- if(sd->object != OBJECT_NONE)
+ if(ccl_fetch(sd, object) != OBJECT_NONE)
data = volume_normalized_position(kg, sd, data);
#endif
break;
@@ -144,65 +180,83 @@ ccl_device void svm_node_tex_coord_bump_dx(KernelGlobals *kg, ShaderData *sd, in
stack_store_float3(stack, out_offset, data);
#else
- svm_node_tex_coord(kg, sd, stack, type, out_offset);
+ svm_node_tex_coord(kg, sd, path_flag, stack, node, offset);
#endif
}
-ccl_device void svm_node_tex_coord_bump_dy(KernelGlobals *kg, ShaderData *sd, int path_flag, float *stack, uint type, uint out_offset)
+ccl_device void svm_node_tex_coord_bump_dy(KernelGlobals *kg,
+ ShaderData *sd,
+ int path_flag,
+ float *stack,
+ uint4 node,
+ int *offset)
{
#ifdef __RAY_DIFFERENTIALS__
float3 data;
+ uint type = node.y;
+ uint out_offset = node.z;
switch(type) {
case NODE_TEXCO_OBJECT: {
- data = sd->P + sd->dP.dy;
- if(sd->object != OBJECT_NONE)
- object_inverse_position_transform(kg, sd, &data);
+ data = ccl_fetch(sd, P) + ccl_fetch(sd, dP).dy;
+ if(node.w == 0) {
+ if(ccl_fetch(sd, object) != OBJECT_NONE) {
+ object_inverse_position_transform(kg, sd, &data);
+ }
+ }
+ else {
+ Transform tfm;
+ tfm.x = read_node_float(kg, offset);
+ tfm.y = read_node_float(kg, offset);
+ tfm.z = read_node_float(kg, offset);
+ tfm.w = read_node_float(kg, offset);
+ data = transform_point(&tfm, data);
+ }
break;
}
case NODE_TEXCO_NORMAL: {
- data = sd->N;
- if(sd->object != OBJECT_NONE)
+ data = ccl_fetch(sd, N);
+ if(ccl_fetch(sd, object) != OBJECT_NONE)
object_inverse_normal_transform(kg, sd, &data);
break;
}
case NODE_TEXCO_CAMERA: {
Transform tfm = kernel_data.cam.worldtocamera;
- if(sd->object != OBJECT_NONE)
- data = transform_point(&tfm, sd->P + sd->dP.dy);
+ if(ccl_fetch(sd, object) != OBJECT_NONE)
+ data = transform_point(&tfm, ccl_fetch(sd, P) + ccl_fetch(sd, dP).dy);
else
- data = transform_point(&tfm, sd->P + sd->dP.dy + camera_position(kg));
+ data = transform_point(&tfm, ccl_fetch(sd, P) + ccl_fetch(sd, dP).dy + camera_position(kg));
break;
}
case NODE_TEXCO_WINDOW: {
- if((path_flag & PATH_RAY_CAMERA) && sd->object == OBJECT_NONE && kernel_data.cam.type == CAMERA_ORTHOGRAPHIC)
- data = camera_world_to_ndc(kg, sd, sd->ray_P + sd->ray_dP.dy);
+ if((path_flag & PATH_RAY_CAMERA) && ccl_fetch(sd, object) == OBJECT_NONE && kernel_data.cam.type == CAMERA_ORTHOGRAPHIC)
+ data = camera_world_to_ndc(kg, sd, ccl_fetch(sd, ray_P) + ccl_fetch(sd, ray_dP).dy);
else
- data = camera_world_to_ndc(kg, sd, sd->P + sd->dP.dy);
+ data = camera_world_to_ndc(kg, sd, ccl_fetch(sd, P) + ccl_fetch(sd, dP).dy);
data.z = 0.0f;
break;
}
case NODE_TEXCO_REFLECTION: {
- if(sd->object != OBJECT_NONE)
- data = 2.0f*dot(sd->N, sd->I)*sd->N - sd->I;
+ if(ccl_fetch(sd, object) != OBJECT_NONE)
+ data = 2.0f*dot(ccl_fetch(sd, N), ccl_fetch(sd, I))*ccl_fetch(sd, N) - ccl_fetch(sd, I);
else
- data = sd->I;
+ data = ccl_fetch(sd, I);
break;
}
case NODE_TEXCO_DUPLI_GENERATED: {
- data = object_dupli_generated(kg, sd->object);
+ data = object_dupli_generated(kg, ccl_fetch(sd, object));
break;
}
case NODE_TEXCO_DUPLI_UV: {
- data = object_dupli_uv(kg, sd->object);
+ data = object_dupli_uv(kg, ccl_fetch(sd, object));
break;
}
case NODE_TEXCO_VOLUME_GENERATED: {
- data = sd->P + sd->dP.dy;
+ data = ccl_fetch(sd, P) + ccl_fetch(sd, dP).dy;
#ifdef __VOLUME__
- if(sd->object != OBJECT_NONE)
+ if(ccl_fetch(sd, object) != OBJECT_NONE)
data = volume_normalized_position(kg, sd, data);
#endif
break;
@@ -211,7 +265,7 @@ ccl_device void svm_node_tex_coord_bump_dy(KernelGlobals *kg, ShaderData *sd, in
stack_store_float3(stack, out_offset, data);
#else
- svm_node_tex_coord(kg, sd, stack, type, out_offset);
+ svm_node_tex_coord(kg, sd, path_flag, stack, node, offset);
#endif
}
@@ -227,7 +281,7 @@ ccl_device void svm_node_normal_map(KernelGlobals *kg, ShaderData *sd, float *st
if(space == NODE_NORMAL_MAP_TANGENT) {
/* tangent space */
- if(sd->object == OBJECT_NONE) {
+ if(ccl_fetch(sd, object) == OBJECT_NONE) {
stack_store_float3(stack, normal_offset, make_float3(0.0f, 0.0f, 0.0f));
return;
}
@@ -248,11 +302,11 @@ ccl_device void svm_node_normal_map(KernelGlobals *kg, ShaderData *sd, float *st
float sign = primitive_attribute_float(kg, sd, attr_sign_elem, attr_sign_offset, NULL, NULL);
float3 normal;
- if(sd->shader & SHADER_SMOOTH_NORMAL) {
+ if(ccl_fetch(sd, shader) & SHADER_SMOOTH_NORMAL) {
normal = primitive_attribute_float3(kg, sd, attr_normal_elem, attr_normal_offset, NULL, NULL);
}
else {
- normal = sd->Ng;
+ normal = ccl_fetch(sd, Ng);
object_inverse_normal_transform(kg, sd, &normal);
}
@@ -283,7 +337,7 @@ ccl_device void svm_node_normal_map(KernelGlobals *kg, ShaderData *sd, float *st
if(strength != 1.0f) {
strength = max(strength, 0.0f);
- N = normalize(sd->N + (N - sd->N)*strength);
+ N = normalize(ccl_fetch(sd, N) + (N - ccl_fetch(sd, N))*strength);
}
stack_store_float3(stack, normal_offset, N);
@@ -313,7 +367,7 @@ ccl_device void svm_node_tangent(KernelGlobals *kg, ShaderData *sd, float *stack
float3 generated;
if(attr_offset == ATTR_STD_NOT_FOUND)
- generated = sd->P;
+ generated = ccl_fetch(sd, P);
else
generated = primitive_attribute_float3(kg, sd, attr_elem, attr_offset, NULL, NULL);
@@ -326,7 +380,7 @@ ccl_device void svm_node_tangent(KernelGlobals *kg, ShaderData *sd, float *stack
}
object_normal_transform(kg, sd, &tangent);
- tangent = cross(sd->N, normalize(cross(tangent, sd->N)));
+ tangent = cross(ccl_fetch(sd, N), normalize(cross(tangent, ccl_fetch(sd, N))));
stack_store_float3(stack, tangent_offset, tangent);
}
diff --git a/intern/cycles/kernel/svm/svm_texture.h b/intern/cycles/kernel/svm/svm_texture.h
index d97c85db36a..dcb00f7dd55 100644
--- a/intern/cycles/kernel/svm/svm_texture.h
+++ b/intern/cycles/kernel/svm/svm_texture.h
@@ -11,266 +11,14 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
CCL_NAMESPACE_BEGIN
-/* Voronoi Distances */
-
-#if 0
-ccl_device float voronoi_distance(NodeDistanceMetric distance_metric, float3 d, float e)
-{
-#if 0
- if(distance_metric == NODE_VORONOI_DISTANCE_SQUARED)
-#endif
- return dot(d, d);
-#if 0
- if(distance_metric == NODE_VORONOI_ACTUAL_DISTANCE)
- return len(d);
- if(distance_metric == NODE_VORONOI_MANHATTAN)
- return fabsf(d.x) + fabsf(d.y) + fabsf(d.z);
- if(distance_metric == NODE_VORONOI_CHEBYCHEV)
- return fmaxf(fabsf(d.x), fmaxf(fabsf(d.y), fabsf(d.z)));
- if(distance_metric == NODE_VORONOI_MINKOVSKY_H)
- return sqrtf(fabsf(d.x)) + sqrtf(fabsf(d.y)) + sqrtf(fabsf(d.y));
- if(distance_metric == NODE_VORONOI_MINKOVSKY_4)
- return sqrtf(sqrtf(dot(d*d, d*d)));
- if(distance_metric == NODE_VORONOI_MINKOVSKY)
- return powf(powf(fabsf(d.x), e) + powf(fabsf(d.y), e) + powf(fabsf(d.z), e), 1.0f/e);
-
- return 0.0f;
-#endif
-}
-
-/* Voronoi / Worley like */
-ccl_device_inline float4 voronoi_Fn(float3 p, float e, int n1, int n2)
-{
- float da[4];
- float3 pa[4];
- NodeDistanceMetric distance_metric = NODE_VORONOI_DISTANCE_SQUARED;
-
- /* returns distances in da and point coords in pa */
- int xx, yy, zz, xi, yi, zi;
-
- xi = floor_to_int(p.x);
- yi = floor_to_int(p.y);
- zi = floor_to_int(p.z);
-
- da[0] = 1e10f;
- da[1] = 1e10f;
- da[2] = 1e10f;
- da[3] = 1e10f;
-
- pa[0] = make_float3(0.0f, 0.0f, 0.0f);
- pa[1] = make_float3(0.0f, 0.0f, 0.0f);
- pa[2] = make_float3(0.0f, 0.0f, 0.0f);
- pa[3] = make_float3(0.0f, 0.0f, 0.0f);
-
- for(xx = xi-1; xx <= xi+1; xx++) {
- for(yy = yi-1; yy <= yi+1; yy++) {
- for(zz = zi-1; zz <= zi+1; zz++) {
- float3 ip = make_float3((float)xx, (float)yy, (float)zz);
- float3 vp = cellnoise_color(ip);
- float3 pd = p - (vp + ip);
- float d = voronoi_distance(distance_metric, pd, e);
-
- vp += ip;
-
- if(d < da[0]) {
- da[3] = da[2];
- da[2] = da[1];
- da[1] = da[0];
- da[0] = d;
-
- pa[3] = pa[2];
- pa[2] = pa[1];
- pa[1] = pa[0];
- pa[0] = vp;
- }
- else if(d < da[1]) {
- da[3] = da[2];
- da[2] = da[1];
- da[1] = d;
-
- pa[3] = pa[2];
- pa[2] = pa[1];
- pa[1] = vp;
- }
- else if(d < da[2]) {
- da[3] = da[2];
- da[2] = d;
-
- pa[3] = pa[2];
- pa[2] = vp;
- }
- else if(d < da[3]) {
- da[3] = d;
- pa[3] = vp;
- }
- }
- }
- }
-
- float4 result = make_float4(pa[n1].x, pa[n1].y, pa[n1].z, da[n1]);
-
- if(n2 != -1)
- result = make_float4(pa[n2].x, pa[n2].y, pa[n2].z, da[n2]) - result;
-
- return result;
-}
-#endif
-
-ccl_device float voronoi_F1_distance(float3 p)
-{
- /* returns squared distance in da */
- float da = 1e10f;
-
-#ifndef __KERNEL_SSE2__
- int ix = floor_to_int(p.x), iy = floor_to_int(p.y), iz = floor_to_int(p.z);
-
- for (int xx = -1; xx <= 1; xx++) {
- for (int yy = -1; yy <= 1; yy++) {
- for (int zz = -1; zz <= 1; zz++) {
- float3 ip = make_float3(ix + xx, iy + yy, iz + zz);
- float3 vp = ip + cellnoise_color(ip);
- float d = len_squared(p - vp);
- da = min(d, da);
- }
- }
- }
-#else
- ssef vec_p = load4f(p);
- ssei xyzi = quick_floor_sse(vec_p);
-
- for (int xx = -1; xx <= 1; xx++) {
- for (int yy = -1; yy <= 1; yy++) {
- for (int zz = -1; zz <= 1; zz++) {
- ssef ip = ssef(xyzi + ssei(xx, yy, zz, 0));
- ssef vp = ip + cellnoise_color(ip);
- float d = len_squared<1, 1, 1, 0>(vec_p - vp);
- da = min(d, da);
- }
- }
- }
-#endif
-
- return da;
-}
-
-ccl_device float3 voronoi_F1_color(float3 p)
-{
- /* returns color of the nearest point */
- float da = 1e10f;
-
-#ifndef __KERNEL_SSE2__
- float3 pa;
- int ix = floor_to_int(p.x), iy = floor_to_int(p.y), iz = floor_to_int(p.z);
-
- for (int xx = -1; xx <= 1; xx++) {
- for (int yy = -1; yy <= 1; yy++) {
- for (int zz = -1; zz <= 1; zz++) {
- float3 ip = make_float3(ix + xx, iy + yy, iz + zz);
- float3 vp = ip + cellnoise_color(ip);
- float d = len_squared(p - vp);
-
- if(d < da) {
- da = d;
- pa = vp;
- }
- }
- }
- }
-
- return cellnoise_color(pa);
-#else
- ssef pa, vec_p = load4f(p);
- ssei xyzi = quick_floor_sse(vec_p);
-
- for (int xx = -1; xx <= 1; xx++) {
- for (int yy = -1; yy <= 1; yy++) {
- for (int zz = -1; zz <= 1; zz++) {
- ssef ip = ssef(xyzi + ssei(xx, yy, zz, 0));
- ssef vp = ip + cellnoise_color(ip);
- float d = len_squared<1, 1, 1, 0>(vec_p - vp);
-
- if(d < da) {
- da = d;
- pa = vp;
- }
- }
- }
- }
-
- ssef color = cellnoise_color(pa);
- return (float3 &)color;
-#endif
-}
-
-#if 0
-ccl_device float voronoi_F1(float3 p) { return voronoi_Fn(p, 0.0f, 0, -1).w; }
-ccl_device float voronoi_F2(float3 p) { return voronoi_Fn(p, 0.0f, 1, -1).w; }
-ccl_device float voronoi_F3(float3 p) { return voronoi_Fn(p, 0.0f, 2, -1).w; }
-ccl_device float voronoi_F4(float3 p) { return voronoi_Fn(p, 0.0f, 3, -1).w; }
-ccl_device float voronoi_F1F2(float3 p) { return voronoi_Fn(p, 0.0f, 0, 1).w; }
-
-ccl_device float voronoi_Cr(float3 p)
-{
- /* crackle type pattern, just a scale/clamp of F2-F1 */
- float t = 10.0f*voronoi_F1F2(p);
- return (t > 1.0f)? 1.0f: t;
-}
-
-ccl_device float voronoi_F1S(float3 p) { return 2.0f*voronoi_F1(p) - 1.0f; }
-ccl_device float voronoi_F2S(float3 p) { return 2.0f*voronoi_F2(p) - 1.0f; }
-ccl_device float voronoi_F3S(float3 p) { return 2.0f*voronoi_F3(p) - 1.0f; }
-ccl_device float voronoi_F4S(float3 p) { return 2.0f*voronoi_F4(p) - 1.0f; }
-ccl_device float voronoi_F1F2S(float3 p) { return 2.0f*voronoi_F1F2(p) - 1.0f; }
-ccl_device float voronoi_CrS(float3 p) { return 2.0f*voronoi_Cr(p) - 1.0f; }
-#endif
-
-/* Noise Bases */
-
-ccl_device float noise_basis(float3 p, NodeNoiseBasis basis)
-{
- /* Only Perlin enabled for now, others break CUDA compile by making kernel
- * too big, with compile using > 4GB, due to everything being inlined. */
-
-#if 0
- if(basis == NODE_NOISE_PERLIN)
-#endif
- return noise(p);
-#if 0
- if(basis == NODE_NOISE_VORONOI_F1)
- return voronoi_F1S(p);
- if(basis == NODE_NOISE_VORONOI_F2)
- return voronoi_F2S(p);
- if(basis == NODE_NOISE_VORONOI_F3)
- return voronoi_F3S(p);
- if(basis == NODE_NOISE_VORONOI_F4)
- return voronoi_F4S(p);
- if(basis == NODE_NOISE_VORONOI_F2_F1)
- return voronoi_F1F2S(p);
- if(basis == NODE_NOISE_VORONOI_CRACKLE)
- return voronoi_CrS(p);
- if(basis == NODE_NOISE_CELL_NOISE)
- return cellnoise(p);
-
- return 0.0f;
-#endif
-}
-
-/* Soft/Hard Noise */
-
-ccl_device float noise_basis_hard(float3 p, NodeNoiseBasis basis, int hard)
-{
- float t = noise_basis(p, basis);
- return (hard)? fabsf(2.0f*t - 1.0f): t;
-}
-
/* Turbulence */
-ccl_device_noinline float noise_turbulence(float3 p, NodeNoiseBasis basis, float octaves, int hard)
+ccl_device_noinline float noise_turbulence(float3 p, float octaves, int hard)
{
float fscale = 1.0f;
float amp = 1.0f;
@@ -281,7 +29,7 @@ ccl_device_noinline float noise_turbulence(float3 p, NodeNoiseBasis basis, float
n = float_to_int(octaves);
for(i = 0; i <= n; i++) {
- float t = noise_basis(fscale*p, basis);
+ float t = noise(fscale*p);
if(hard)
t = fabsf(2.0f*t - 1.0f);
@@ -294,7 +42,7 @@ ccl_device_noinline float noise_turbulence(float3 p, NodeNoiseBasis basis, float
float rmd = octaves - floorf(octaves);
if(rmd != 0.0f) {
- float t = noise_basis(fscale*p, basis);
+ float t = noise(fscale*p);
if(hard)
t = fabsf(2.0f*t - 1.0f);
diff --git a/intern/cycles/kernel/svm/svm_types.h b/intern/cycles/kernel/svm/svm_types.h
index cd38ce4ba9b..33aa5e7c51c 100644
--- a/intern/cycles/kernel/svm/svm_types.h
+++ b/intern/cycles/kernel/svm/svm_types.h
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#ifndef __SVM_TYPES_H__
@@ -28,6 +28,29 @@ CCL_NAMESPACE_BEGIN
/* Nodes */
+/* Known frequencies of used nodes, used for selective nodes compilation
+ * in the kernel. Currently only affects split OpenCL kernel.
+ *
+ * Keep as defines so it's easy to check which nodes are to be compiled
+ * from preprocessor.
+ *
+ * Lower the number of group more often the node is used.
+ */
+#define NODE_GROUP_LEVEL_0 0
+#define NODE_GROUP_LEVEL_1 1
+#define NODE_GROUP_LEVEL_2 2
+#define NODE_GROUP_LEVEL_3 3
+#define NODE_GROUP_LEVEL_MAX NODE_GROUP_LEVEL_3
+
+#define NODE_FEATURE_VOLUME (1 << 0)
+#define NODE_FEATURE_HAIR (1 << 1)
+#define NODE_FEATURE_BUMP (1 << 2)
+/* TODO(sergey): Consider using something like ((uint)(-1)).
+ * Need to check carefully operand types around usage of this
+ * define first.
+ */
+#define NODE_FEATURE_ALL (NODE_FEATURE_VOLUME|NODE_FEATURE_HAIR|NODE_FEATURE_BUMP)
+
typedef enum NodeType {
NODE_END = 0,
NODE_CLOSURE_BSDF,
@@ -103,8 +126,8 @@ typedef enum NodeType {
NODE_NORMAL_MAP,
NODE_HAIR_INFO,
NODE_UVMAP,
+ NODE_TEX_VOXEL,
- /* Camera ray nodes. */
NODE_CAMERA_PATH_ATTRIBUTE,
NODE_CAMERA_SAMPLE_PERSPECTIVE,
NODE_CAMERA_RAY_OUTPUT,
@@ -262,27 +285,6 @@ typedef enum NodeConvert {
NODE_CONVERT_IV
} NodeConvert;
-typedef enum NodeDistanceMetric {
- NODE_VORONOI_DISTANCE_SQUARED,
- NODE_VORONOI_ACTUAL_DISTANCE,
- NODE_VORONOI_MANHATTAN,
- NODE_VORONOI_CHEBYCHEV,
- NODE_VORONOI_MINKOVSKY_H,
- NODE_VORONOI_MINKOVSKY_4,
- NODE_VORONOI_MINKOVSKY
-} NodeDistanceMetric;
-
-typedef enum NodeNoiseBasis {
- NODE_NOISE_PERLIN,
- NODE_NOISE_VORONOI_F1,
- NODE_NOISE_VORONOI_F2,
- NODE_NOISE_VORONOI_F3,
- NODE_NOISE_VORONOI_F4,
- NODE_NOISE_VORONOI_F2_F1,
- NODE_NOISE_VORONOI_CRACKLE,
- NODE_NOISE_CELL_NOISE
-} NodeNoiseBasis;
-
typedef enum NodeMusgraveType {
NODE_MUSGRAVE_MULTIFRACTAL,
NODE_MUSGRAVE_FBM,
@@ -340,6 +342,24 @@ typedef enum NodeNormalMapSpace {
NODE_NORMAL_MAP_BLENDER_WORLD,
} NodeNormalMapSpace;
+typedef enum NodeImageProjection {
+ NODE_IMAGE_PROJ_FLAT = 0,
+ NODE_IMAGE_PROJ_BOX = 1,
+ NODE_IMAGE_PROJ_SPHERE = 2,
+ NODE_IMAGE_PROJ_TUBE = 3,
+} NodeImageProjection;
+
+typedef enum NodeBumpOffset {
+ NODE_BUMP_OFFSET_CENTER,
+ NODE_BUMP_OFFSET_DX,
+ NODE_BUMP_OFFSET_DY,
+} NodeBumpOffset;
+
+typedef enum NodeTexVoxelSpace {
+ NODE_TEX_VOXEL_SPACE_OBJECT = 0,
+ NODE_TEX_VOXEL_SPACE_WORLD = 1,
+} NodeTexVoxelSpace;
+
typedef enum ShaderType {
SHADER_TYPE_SURFACE,
SHADER_TYPE_VOLUME,
@@ -355,7 +375,6 @@ typedef enum ClosureType {
/* Diffuse */
CLOSURE_BSDF_DIFFUSE_ID,
CLOSURE_BSDF_OREN_NAYAR_ID,
- CLOSURE_BSDF_WESTIN_SHEEN_ID,
CLOSURE_BSDF_DIFFUSE_RAMP_ID,
CLOSURE_BSDF_DIFFUSE_TOON_ID,
@@ -369,7 +388,6 @@ typedef enum ClosureType {
CLOSURE_BSDF_MICROFACET_BECKMANN_ANISO_ID,
CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ANISO_ID,
CLOSURE_BSDF_ASHIKHMIN_VELVET_ID,
- CLOSURE_BSDF_WESTIN_BACKSCATTER_ID,
CLOSURE_BSDF_PHONG_RAMP_ID,
CLOSURE_BSDF_GLOSSY_TOON_ID,
CLOSURE_BSDF_HAIR_REFLECTION_ID,
@@ -428,6 +446,7 @@ typedef enum NodePathAttribute {
#define CLOSURE_IS_BACKGROUND(type) (type == CLOSURE_BACKGROUND_ID)
#define CLOSURE_IS_AMBIENT_OCCLUSION(type) (type == CLOSURE_AMBIENT_OCCLUSION_ID)
#define CLOSURE_IS_PHASE(type) (type == CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID)
+#define CLOSURE_IS_GLASS(type) (type >= CLOSURE_BSDF_MICROFACET_BECKMANN_GLASS_ID && type <= CLOSURE_BSDF_SHARP_GLASS_ID)
#define CLOSURE_WEIGHT_CUTOFF 1e-5f
diff --git a/intern/cycles/kernel/svm/svm_value.h b/intern/cycles/kernel/svm/svm_value.h
index 7beed065288..c1c2b539df3 100644
--- a/intern/cycles/kernel/svm/svm_value.h
+++ b/intern/cycles/kernel/svm/svm_value.h
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
CCL_NAMESPACE_BEGIN
diff --git a/intern/cycles/kernel/svm/svm_vector_transform.h b/intern/cycles/kernel/svm/svm_vector_transform.h
index 61d33aeb8cf..4c32130d06d 100644
--- a/intern/cycles/kernel/svm/svm_vector_transform.h
+++ b/intern/cycles/kernel/svm/svm_vector_transform.h
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
CCL_NAMESPACE_BEGIN
@@ -33,7 +33,7 @@ ccl_device void svm_node_vector_transform(KernelGlobals *kg, ShaderData *sd, flo
NodeVectorTransformConvertSpace to = (NodeVectorTransformConvertSpace)ito;
Transform tfm;
- bool is_object = (sd->object != OBJECT_NONE);
+ bool is_object = (ccl_fetch(sd, object) != OBJECT_NONE);
bool is_direction = (type == NODE_VECTOR_TRANSFORM_TYPE_VECTOR || type == NODE_VECTOR_TRANSFORM_TYPE_NORMAL);
/* From world */
@@ -45,7 +45,7 @@ ccl_device void svm_node_vector_transform(KernelGlobals *kg, ShaderData *sd, flo
else
in = transform_point(&tfm, in);
}
- else if (to == NODE_VECTOR_TRANSFORM_CONVERT_SPACE_OBJECT && is_object) {
+ else if(to == NODE_VECTOR_TRANSFORM_CONVERT_SPACE_OBJECT && is_object) {
if(is_direction)
object_inverse_dir_transform(kg, sd, &in);
else
@@ -54,7 +54,7 @@ ccl_device void svm_node_vector_transform(KernelGlobals *kg, ShaderData *sd, flo
}
/* From camera */
- else if (from == NODE_VECTOR_TRANSFORM_CONVERT_SPACE_CAMERA) {
+ else if(from == NODE_VECTOR_TRANSFORM_CONVERT_SPACE_CAMERA) {
if(to == NODE_VECTOR_TRANSFORM_CONVERT_SPACE_WORLD || to == NODE_VECTOR_TRANSFORM_CONVERT_SPACE_OBJECT) {
tfm = kernel_data.cam.cameratoworld;
if(is_direction)
diff --git a/intern/cycles/kernel/svm/svm_voronoi.h b/intern/cycles/kernel/svm/svm_voronoi.h
index 083a2f30e06..d612d7e973f 100644
--- a/intern/cycles/kernel/svm/svm_voronoi.h
+++ b/intern/cycles/kernel/svm/svm_voronoi.h
@@ -11,13 +11,99 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
CCL_NAMESPACE_BEGIN
/* Voronoi */
+ccl_device float voronoi_F1_distance(float3 p)
+{
+ /* returns squared distance in da */
+ float da = 1e10f;
+
+#ifndef __KERNEL_SSE2__
+ int ix = floor_to_int(p.x), iy = floor_to_int(p.y), iz = floor_to_int(p.z);
+
+ for(int xx = -1; xx <= 1; xx++) {
+ for(int yy = -1; yy <= 1; yy++) {
+ for(int zz = -1; zz <= 1; zz++) {
+ float3 ip = make_float3(ix + xx, iy + yy, iz + zz);
+ float3 vp = ip + cellnoise_color(ip);
+ float d = len_squared(p - vp);
+ da = min(d, da);
+ }
+ }
+ }
+#else
+ ssef vec_p = load4f(p);
+ ssei xyzi = quick_floor_sse(vec_p);
+
+ for(int xx = -1; xx <= 1; xx++) {
+ for(int yy = -1; yy <= 1; yy++) {
+ for(int zz = -1; zz <= 1; zz++) {
+ ssef ip = ssef(xyzi + ssei(xx, yy, zz, 0));
+ ssef vp = ip + cellnoise_color(ip);
+ float d = len_squared<1, 1, 1, 0>(vec_p - vp);
+ da = min(d, da);
+ }
+ }
+ }
+#endif
+
+ return da;
+}
+
+ccl_device float3 voronoi_F1_color(float3 p)
+{
+ /* returns color of the nearest point */
+ float da = 1e10f;
+
+#ifndef __KERNEL_SSE2__
+ float3 pa;
+ int ix = floor_to_int(p.x), iy = floor_to_int(p.y), iz = floor_to_int(p.z);
+
+ for(int xx = -1; xx <= 1; xx++) {
+ for(int yy = -1; yy <= 1; yy++) {
+ for(int zz = -1; zz <= 1; zz++) {
+ float3 ip = make_float3(ix + xx, iy + yy, iz + zz);
+ float3 vp = ip + cellnoise_color(ip);
+ float d = len_squared(p - vp);
+
+ if(d < da) {
+ da = d;
+ pa = vp;
+ }
+ }
+ }
+ }
+
+ return cellnoise_color(pa);
+#else
+ ssef pa, vec_p = load4f(p);
+ ssei xyzi = quick_floor_sse(vec_p);
+
+ for(int xx = -1; xx <= 1; xx++) {
+ for(int yy = -1; yy <= 1; yy++) {
+ for(int zz = -1; zz <= 1; zz++) {
+ ssef ip = ssef(xyzi + ssei(xx, yy, zz, 0));
+ ssef vp = ip + cellnoise_color(ip);
+ float d = len_squared<1, 1, 1, 0>(vec_p - vp);
+
+ if(d < da) {
+ da = d;
+ pa = vp;
+ }
+ }
+ }
+ }
+
+ ssef color = cellnoise_color(pa);
+ return (float3 &)color;
+#endif
+}
+
ccl_device_noinline float4 svm_voronoi(NodeVoronoiColoring coloring, float3 p)
{
if(coloring == NODE_VORONOI_INTENSITY) {
diff --git a/intern/cycles/kernel/svm/svm_voxel.h b/intern/cycles/kernel/svm/svm_voxel.h
new file mode 100644
index 00000000000..bbb687dfce5
--- /dev/null
+++ b/intern/cycles/kernel/svm/svm_voxel.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2011-2015 Blender Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+CCL_NAMESPACE_BEGIN
+
+#if !defined(__KERNEL_GPU__)
+
+/* TODO(sergey): Think of making it more generic volume-type attribute
+ * sampler.
+ */
+ccl_device void svm_node_tex_voxel(KernelGlobals *kg,
+ ShaderData *sd,
+ float *stack,
+ uint4 node,
+ int *offset)
+{
+ uint co_offset, density_out_offset, color_out_offset, space;
+ decode_node_uchar4(node.z, &co_offset, &density_out_offset, &color_out_offset, &space);
+ int id = node.y;
+ float3 co = stack_load_float3(stack, co_offset);
+ if(space == NODE_TEX_VOXEL_SPACE_OBJECT) {
+ co = volume_normalized_position(kg, sd, co);
+ }
+ else {
+ kernel_assert(space == NODE_TEX_VOXEL_SPACE_WORLD);
+ Transform tfm;
+ tfm.x = read_node_float(kg, offset);
+ tfm.y = read_node_float(kg, offset);
+ tfm.z = read_node_float(kg, offset);
+ tfm.w = read_node_float(kg, offset);
+ co = transform_point(&tfm, co);
+ }
+ if(co.x < 0.0f || co.y < 0.0f || co.z < 0.0f ||
+ co.x > 1.0f || co.y > 1.0f || co.z > 1.0f)
+ {
+ if (stack_valid(density_out_offset))
+ stack_store_float(stack, density_out_offset, 0.0f);
+ if (stack_valid(color_out_offset))
+ stack_store_float3(stack, color_out_offset, make_float3(0.0f, 0.0f, 0.0f));
+ return;
+ }
+ float4 r = kernel_tex_image_interp_3d(id, co.x, co.y, co.z);
+ if (stack_valid(density_out_offset))
+ stack_store_float(stack, density_out_offset, r.w);
+ if (stack_valid(color_out_offset))
+ stack_store_float3(stack, color_out_offset, make_float3(r.x, r.y, r.z));
+}
+
+#endif /* !defined(__KERNEL_GPU__) */
+
+CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/svm/svm_wave.h b/intern/cycles/kernel/svm/svm_wave.h
index 7f9081539a4..6eaddaf301c 100644
--- a/intern/cycles/kernel/svm/svm_wave.h
+++ b/intern/cycles/kernel/svm/svm_wave.h
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
CCL_NAMESPACE_BEGIN
@@ -28,7 +28,7 @@ ccl_device_noinline float svm_wave(NodeWaveType type, float3 p, float detail, fl
n = len(p) * 20.0f;
if(distortion != 0.0f)
- n += distortion * noise_turbulence(p*dscale, NODE_NOISE_PERLIN, detail, 0);
+ n += distortion * noise_turbulence(p*dscale, detail, 0);
return 0.5f + 0.5f * sinf(n);
}
diff --git a/intern/cycles/kernel/svm/svm_wavelength.h b/intern/cycles/kernel/svm/svm_wavelength.h
index 9e57c470c0f..57030f3979d 100644
--- a/intern/cycles/kernel/svm/svm_wavelength.h
+++ b/intern/cycles/kernel/svm/svm_wavelength.h
@@ -77,7 +77,7 @@ ccl_device void svm_node_wavelength(ShaderData *sd, float *stack, uint wavelengt
int i = float_to_int(ii);
float3 color;
- if (i < 0 || i >= 80) {
+ if(i < 0 || i >= 80) {
color = make_float3(0.0f, 0.0f, 0.0f);
}
else {
diff --git a/intern/cycles/kernel/svm/svm_wireframe.h b/intern/cycles/kernel/svm/svm_wireframe.h
index 660e6e2ca47..30ccd523add 100644
--- a/intern/cycles/kernel/svm/svm_wireframe.h
+++ b/intern/cycles/kernel/svm/svm_wireframe.h
@@ -34,20 +34,16 @@ CCL_NAMESPACE_BEGIN
/* Wireframe Node */
-ccl_device void svm_node_wireframe(KernelGlobals *kg, ShaderData *sd, float *stack, uint in_size, uint out_fac, uint use_pixel_size)
+ccl_device float wireframe(KernelGlobals *kg,
+ ShaderData *sd,
+ float size,
+ int pixel_size,
+ float3 *P)
{
- /* Input Data */
- float size = stack_load_float(stack, in_size);
- int pixel_size = (int)use_pixel_size;
-
- /* Output */
- float f = 0.0f;
-
- /* Calculate wireframe */
#ifdef __HAIR__
- if (sd->prim != PRIM_NONE && sd->type & PRIMITIVE_ALL_TRIANGLE)
+ if(ccl_fetch(sd, prim) != PRIM_NONE && ccl_fetch(sd, type) & PRIMITIVE_ALL_TRIANGLE)
#else
- if (sd->prim != PRIM_NONE)
+ if(ccl_fetch(sd, prim) != PRIM_NONE)
#endif
{
float3 Co[3];
@@ -55,45 +51,85 @@ ccl_device void svm_node_wireframe(KernelGlobals *kg, ShaderData *sd, float *sta
/* Triangles */
int np = 3;
-
- if(sd->type & PRIMITIVE_TRIANGLE)
- triangle_vertices(kg, sd->prim, Co);
+
+ if(ccl_fetch(sd, type) & PRIMITIVE_TRIANGLE)
+ triangle_vertices(kg, ccl_fetch(sd, prim), Co);
else
- motion_triangle_vertices(kg, sd->object, sd->prim, sd->time, Co);
+ motion_triangle_vertices(kg, ccl_fetch(sd, object), ccl_fetch(sd, prim), ccl_fetch(sd, time), Co);
- if(!(sd->flag & SD_TRANSFORM_APPLIED)) {
+ if(!(ccl_fetch(sd, flag) & SD_TRANSFORM_APPLIED)) {
object_position_transform(kg, sd, &Co[0]);
object_position_transform(kg, sd, &Co[1]);
object_position_transform(kg, sd, &Co[2]);
}
-
+
if(pixel_size) {
// Project the derivatives of P to the viewing plane defined
// by I so we have a measure of how big is a pixel at this point
- float pixelwidth_x = len(sd->dP.dx - dot(sd->dP.dx, sd->I) * sd->I);
- float pixelwidth_y = len(sd->dP.dy - dot(sd->dP.dy, sd->I) * sd->I);
+ float pixelwidth_x = len(ccl_fetch(sd, dP).dx - dot(ccl_fetch(sd, dP).dx, ccl_fetch(sd, I)) * ccl_fetch(sd, I));
+ float pixelwidth_y = len(ccl_fetch(sd, dP).dy - dot(ccl_fetch(sd, dP).dy, ccl_fetch(sd, I)) * ccl_fetch(sd, I));
// Take the average of both axis' length
pixelwidth = (pixelwidth_x + pixelwidth_y) * 0.5f;
}
-
+
// Use half the width as the neighbor face will render the
// other half. And take the square for fast comparison
pixelwidth *= 0.5f * size;
pixelwidth *= pixelwidth;
- for (int i = 0; i < np; i++) {
+ for(int i = 0; i < np; i++) {
int i2 = i ? i - 1 : np - 1;
- float3 dir = sd->P - Co[i];
+ float3 dir = *P - Co[i];
float3 edge = Co[i] - Co[i2];
float3 crs = cross(edge, dir);
// At this point dot(crs, crs) / dot(edge, edge) is
// the square of area / length(edge) == square of the
// distance to the edge.
- if (dot(crs, crs) < (dot(edge, edge) * pixelwidth))
- f = 1.0f;
+ if(dot(crs, crs) < (dot(edge, edge) * pixelwidth))
+ return 1.0f;
}
}
-
- if (stack_valid(out_fac))
+ return 0.0f;
+}
+
+ccl_device void svm_node_wireframe(KernelGlobals *kg,
+ ShaderData *sd,
+ float *stack,
+ uint4 node)
+{
+ uint in_size = node.y;
+ uint out_fac = node.z;
+ uint use_pixel_size, bump_offset;
+ decode_node_uchar4(node.w, &use_pixel_size, &bump_offset, NULL, NULL);
+
+ /* Input Data */
+ float size = stack_load_float(stack, in_size);
+ int pixel_size = (int)use_pixel_size;
+
+ /* Calculate wireframe */
+#ifdef __SPLIT_KERNEL__
+ /* TODO(sergey): This is because sd is actually a global space,
+ * which makes it difficult to re-use same wireframe() function.
+ *
+ * With OpenCL 2.0 it's possible to avoid this change, but for until
+ * then we'll be living with such an exception.
+ */
+ float3 P = ccl_fetch(sd, P);
+ float f = wireframe(kg, sd, size, pixel_size, &P);
+#else
+ float f = wireframe(kg, sd, size, pixel_size, &ccl_fetch(sd, P));
+#endif
+
+ /* TODO(sergey): Think of faster way to calculate derivatives. */
+ if(bump_offset == NODE_BUMP_OFFSET_DX) {
+ float3 Px = ccl_fetch(sd, P) - ccl_fetch(sd, dP).dx;
+ f += (f - wireframe(kg, sd, size, pixel_size, &Px)) / len(ccl_fetch(sd, dP).dx);
+ }
+ else if(bump_offset == NODE_BUMP_OFFSET_DY) {
+ float3 Py = ccl_fetch(sd, P) - ccl_fetch(sd, dP).dy;
+ f += (f - wireframe(kg, sd, size, pixel_size, &Py)) / len(ccl_fetch(sd, dP).dy);
+ }
+
+ if(stack_valid(out_fac))
stack_store_float(stack, out_fac, f);
}
diff --git a/intern/cycles/render/CMakeLists.txt b/intern/cycles/render/CMakeLists.txt
index e4f847a783a..04c7ee724e3 100644
--- a/intern/cycles/render/CMakeLists.txt
+++ b/intern/cycles/render/CMakeLists.txt
@@ -7,17 +7,17 @@ set(INC
../kernel/osl
../bvh
../util
+ ../../glew-mx
)
set(INC_SYS
- ${GLEW_INCLUDE_PATH}
+ ${GLEW_INCLUDE_DIR}
)
set(SRC
attribute.cpp
background.cpp
bake.cpp
- blackbody.cpp
buffers.cpp
camera.cpp
camera_nodes.cpp
@@ -47,7 +47,6 @@ set(SRC_HEADERS
attribute.h
bake.h
background.h
- blackbody.h
buffers.h
camera.h
camera_nodes.h
@@ -78,5 +77,6 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${RTTI_DISABLE_FLAGS}")
include_directories(${INC})
include_directories(SYSTEM ${INC_SYS})
-add_library(cycles_render ${SRC} ${SRC_HEADERS})
+add_definitions(${GL_DEFINITIONS})
+add_library(cycles_render ${SRC} ${SRC_HEADERS})
diff --git a/intern/cycles/render/attribute.cpp b/intern/cycles/render/attribute.cpp
index 8abf869a775..6e94459da55 100644
--- a/intern/cycles/render/attribute.cpp
+++ b/intern/cycles/render/attribute.cpp
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#include "image.h"
@@ -52,7 +52,7 @@ void Attribute::set(ustring name_, TypeDesc type_, AttributeElement element_)
void Attribute::reserve(int numverts, int numtris, int numsteps, int numcurves, int numkeys, bool resize)
{
- if (resize) {
+ if(resize) {
buffer.resize(buffer_size(numverts, numtris, numsteps, numcurves, numkeys), 0);
}
else {
@@ -230,6 +230,8 @@ const char *Attribute::standard_name(AttributeStandard std)
return "heat";
case ATTR_STD_VOLUME_VELOCITY:
return "velocity";
+ case ATTR_STD_POINTINESS:
+ return "pointiness";
case ATTR_STD_NOT_FOUND:
case ATTR_STD_NONE:
case ATTR_STD_NUM:
@@ -375,6 +377,9 @@ Attribute *AttributeSet::add(AttributeStandard std, ustring name)
case ATTR_STD_VOLUME_VELOCITY:
attr = add(name, TypeDesc::TypeVector, ATTR_ELEMENT_VOXEL);
break;
+ case ATTR_STD_POINTINESS:
+ attr = add(name, TypeDesc::TypeFloat, ATTR_ELEMENT_VERTEX);
+ break;
default:
assert(0);
break;
@@ -395,6 +400,9 @@ Attribute *AttributeSet::add(AttributeStandard std, ustring name)
case ATTR_STD_GENERATED_TRANSFORM:
attr = add(name, TypeDesc::TypeMatrix, ATTR_ELEMENT_MESH);
break;
+ case ATTR_STD_POINTINESS:
+ attr = add(name, TypeDesc::TypeFloat, ATTR_ELEMENT_VERTEX);
+ break;
default:
assert(0);
break;
diff --git a/intern/cycles/render/attribute.h b/intern/cycles/render/attribute.h
index f5227ebde52..bbc6cf7f65f 100644
--- a/intern/cycles/render/attribute.h
+++ b/intern/cycles/render/attribute.h
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#ifndef __ATTRIBUTE_H__
diff --git a/intern/cycles/render/background.cpp b/intern/cycles/render/background.cpp
index 3926ecb99d6..5fd7bd8f16f 100644
--- a/intern/cycles/render/background.cpp
+++ b/intern/cycles/render/background.cpp
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#include "background.h"
@@ -72,21 +72,28 @@ void Background::device_update(Device *device, DeviceScene *dscene, Scene *scene
else
kbackground->volume_shader = SHADER_NONE;
- if(!(visibility & PATH_RAY_DIFFUSE))
- kbackground->surface_shader |= SHADER_EXCLUDE_DIFFUSE;
- if(!(visibility & PATH_RAY_GLOSSY))
- kbackground->surface_shader |= SHADER_EXCLUDE_GLOSSY;
- if(!(visibility & PATH_RAY_TRANSMIT))
- kbackground->surface_shader |= SHADER_EXCLUDE_TRANSMIT;
- if(!(visibility & PATH_RAY_VOLUME_SCATTER))
- kbackground->surface_shader |= SHADER_EXCLUDE_SCATTER;
- if(!(visibility & PATH_RAY_CAMERA))
- kbackground->surface_shader |= SHADER_EXCLUDE_CAMERA;
+ /* No background node, make world shader invisible to all rays, to skip evaluation in kernel. */
+ if(scene->shaders[shader]->graph->nodes.size() <= 1) {
+ kbackground->surface_shader |= SHADER_EXCLUDE_ANY;
+ }
+ /* Background present, check visibilities */
+ else {
+ if(!(visibility & PATH_RAY_DIFFUSE))
+ kbackground->surface_shader |= SHADER_EXCLUDE_DIFFUSE;
+ if(!(visibility & PATH_RAY_GLOSSY))
+ kbackground->surface_shader |= SHADER_EXCLUDE_GLOSSY;
+ if(!(visibility & PATH_RAY_TRANSMIT))
+ kbackground->surface_shader |= SHADER_EXCLUDE_TRANSMIT;
+ if(!(visibility & PATH_RAY_VOLUME_SCATTER))
+ kbackground->surface_shader |= SHADER_EXCLUDE_SCATTER;
+ if(!(visibility & PATH_RAY_CAMERA))
+ kbackground->surface_shader |= SHADER_EXCLUDE_CAMERA;
+ }
need_update = false;
}
-void Background::device_free(Device *device, DeviceScene *dscene)
+void Background::device_free(Device * /*device*/, DeviceScene * /*dscene*/)
{
}
diff --git a/intern/cycles/render/background.h b/intern/cycles/render/background.h
index cf627862513..26a727291ee 100644
--- a/intern/cycles/render/background.h
+++ b/intern/cycles/render/background.h
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#ifndef __BACKGROUND_H__
diff --git a/intern/cycles/render/bake.cpp b/intern/cycles/render/bake.cpp
index 5723a22dd84..4bbac0f91d1 100644
--- a/intern/cycles/render/bake.cpp
+++ b/intern/cycles/render/bake.cpp
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#include "bake.h"
@@ -55,6 +55,11 @@ void BakeData::set(int i, int prim, float uv[2], float dudx, float dudy, float d
m_dvdy[i] = dvdy;
}
+void BakeData::set_null(int i)
+{
+ m_primitive[i] = -1;
+}
+
int BakeData::object()
{
return m_object;
@@ -221,7 +226,10 @@ bool BakeManager::bake(Device *device, DeviceScene *dscene, Scene *scene, Progre
return true;
}
-void BakeManager::device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress)
+void BakeManager::device_update(Device * /*device*/,
+ DeviceScene * /*dscene*/,
+ Scene * /*scene*/,
+ Progress& progress)
{
if(!need_update)
return;
@@ -231,7 +239,7 @@ void BakeManager::device_update(Device *device, DeviceScene *dscene, Scene *scen
need_update = false;
}
-void BakeManager::device_free(Device *device, DeviceScene *dscene)
+void BakeManager::device_free(Device * /*device*/, DeviceScene * /*dscene*/)
{
}
diff --git a/intern/cycles/render/bake.h b/intern/cycles/render/bake.h
index 186fbbeea4d..14d975a4b4e 100644
--- a/intern/cycles/render/bake.h
+++ b/intern/cycles/render/bake.h
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#ifndef __BAKE_H__
@@ -31,6 +31,7 @@ public:
~BakeData();
void set(int i, int prim, float uv[2], float dudx, float dudy, float dvdx, float dvdy);
+ void set_null(int i);
int object();
size_t size();
uint4 data(int i);
diff --git a/intern/cycles/render/blackbody.cpp b/intern/cycles/render/blackbody.cpp
deleted file mode 100644
index 89af714e8ec..00000000000
--- a/intern/cycles/render/blackbody.cpp
+++ /dev/null
@@ -1,140 +0,0 @@
-/*
- * Adapted from Open Shading Language with this license:
- *
- * Copyright (c) 2009-2010 Sony Pictures Imageworks Inc., et al.
- * All Rights Reserved.
- *
- * Modifications Copyright 2013, Blender Foundation.
- *
- * 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 Sony Pictures Imageworks 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.
- */
-
-#include "blackbody.h"
-#include "util_color.h"
-#include "util_math.h"
-
-#include "kernel_types.h"
-
-CCL_NAMESPACE_BEGIN
-
-vector<float> blackbody_table()
-{
- /* quoted from OSLs opcolor.cpp
- In order to speed up the blackbody computation, we have a table
- storing the precomputed BB values for a range of temperatures. Less
- than BB_DRAPER always returns 0. Greater than BB_MAX_TABLE_RANGE
- does the full computation, we think it'll be rare to inquire higher
- temperatures.
-
- Since the bb function is so nonlinear, we actually space the table
- entries nonlinearly, with the relationship between the table index i
- and the temperature T as follows:
- i = ((T-Draper)/spacing)^(1/xpower)
- T = pow(i, xpower) * spacing + Draper
- And furthermore, we store in the table the true value raised ^(1/5).
- I tuned this a bit, and with the current values we can have all
- blackbody results accurate to within 0.1% with a table size of 317
- (about 5 KB of data).
- */
-
- const float cie_colour_match[81][3] = {
- {0.0014f,0.0000f,0.0065f}, {0.0022f,0.0001f,0.0105f}, {0.0042f,0.0001f,0.0201f},
- {0.0076f,0.0002f,0.0362f}, {0.0143f,0.0004f,0.0679f}, {0.0232f,0.0006f,0.1102f},
- {0.0435f,0.0012f,0.2074f}, {0.0776f,0.0022f,0.3713f}, {0.1344f,0.0040f,0.6456f},
- {0.2148f,0.0073f,1.0391f}, {0.2839f,0.0116f,1.3856f}, {0.3285f,0.0168f,1.6230f},
- {0.3483f,0.0230f,1.7471f}, {0.3481f,0.0298f,1.7826f}, {0.3362f,0.0380f,1.7721f},
- {0.3187f,0.0480f,1.7441f}, {0.2908f,0.0600f,1.6692f}, {0.2511f,0.0739f,1.5281f},
- {0.1954f,0.0910f,1.2876f}, {0.1421f,0.1126f,1.0419f}, {0.0956f,0.1390f,0.8130f},
- {0.0580f,0.1693f,0.6162f}, {0.0320f,0.2080f,0.4652f}, {0.0147f,0.2586f,0.3533f},
- {0.0049f,0.3230f,0.2720f}, {0.0024f,0.4073f,0.2123f}, {0.0093f,0.5030f,0.1582f},
- {0.0291f,0.6082f,0.1117f}, {0.0633f,0.7100f,0.0782f}, {0.1096f,0.7932f,0.0573f},
- {0.1655f,0.8620f,0.0422f}, {0.2257f,0.9149f,0.0298f}, {0.2904f,0.9540f,0.0203f},
- {0.3597f,0.9803f,0.0134f}, {0.4334f,0.9950f,0.0087f}, {0.5121f,1.0000f,0.0057f},
- {0.5945f,0.9950f,0.0039f}, {0.6784f,0.9786f,0.0027f}, {0.7621f,0.9520f,0.0021f},
- {0.8425f,0.9154f,0.0018f}, {0.9163f,0.8700f,0.0017f}, {0.9786f,0.8163f,0.0014f},
- {1.0263f,0.7570f,0.0011f}, {1.0567f,0.6949f,0.0010f}, {1.0622f,0.6310f,0.0008f},
- {1.0456f,0.5668f,0.0006f}, {1.0026f,0.5030f,0.0003f}, {0.9384f,0.4412f,0.0002f},
- {0.8544f,0.3810f,0.0002f}, {0.7514f,0.3210f,0.0001f}, {0.6424f,0.2650f,0.0000f},
- {0.5419f,0.2170f,0.0000f}, {0.4479f,0.1750f,0.0000f}, {0.3608f,0.1382f,0.0000f},
- {0.2835f,0.1070f,0.0000f}, {0.2187f,0.0816f,0.0000f}, {0.1649f,0.0610f,0.0000f},
- {0.1212f,0.0446f,0.0000f}, {0.0874f,0.0320f,0.0000f}, {0.0636f,0.0232f,0.0000f},
- {0.0468f,0.0170f,0.0000f}, {0.0329f,0.0119f,0.0000f}, {0.0227f,0.0082f,0.0000f},
- {0.0158f,0.0057f,0.0000f}, {0.0114f,0.0041f,0.0000f}, {0.0081f,0.0029f,0.0000f},
- {0.0058f,0.0021f,0.0000f}, {0.0041f,0.0015f,0.0000f}, {0.0029f,0.0010f,0.0000f},
- {0.0020f,0.0007f,0.0000f}, {0.0014f,0.0005f,0.0000f}, {0.0010f,0.0004f,0.0000f},
- {0.0007f,0.0002f,0.0000f}, {0.0005f,0.0002f,0.0000f}, {0.0003f,0.0001f,0.0000f},
- {0.0002f,0.0001f,0.0000f}, {0.0002f,0.0001f,0.0000f}, {0.0001f,0.0000f,0.0000f},
- {0.0001f,0.0000f,0.0000f}, {0.0001f,0.0000f,0.0000f}, {0.0000f,0.0000f,0.0000f}
- };
-
- const double c1 = 3.74183e-16; // 2*pi*h*c^2, W*m^2
- const double c2 = 1.4388e-2; // h*c/k, m*K
- // h is Planck's const, k is Boltzmann's
- const float dlambda = 5.0f * 1e-9f; // in meters
-
- /* Blackbody table from 800 to 12k Kelvin (319 entries (317+2 offset) * 3) */
- vector<float> blackbody_table(956);
-
- float X, Y, Z;
-
- /* ToDo: bring this back to what OSL does with the lastTemperature limit ? */
- for (int i = 0; i <= 317; ++i) {
- double Temperature = pow((double)i, (double)BB_TABLE_XPOWER) * (double)BB_TABLE_SPACING + (double)BB_DRAPPER;
- X = 0;
- Y = 0;
- Z = 0;
-
- /* from OSL "spectrum_to_XYZ" */
- for (int n = 0; n < 81; ++n) {
- float lambda = 380.0f + 5.0f * n;
- double wlm = lambda * 1e-9f; // Wavelength in meters
- // N.B. spec_intens returns result in W/m^2 but it's a differential,
- // needs to be scaled by dlambda!
- float spec_intens = float((c1 * pow(wlm, -5.0)) / (exp(c2 / (wlm * Temperature)) -1.0));
- float Me = spec_intens * dlambda;
-
- X += Me * cie_colour_match[n][0];
- Y += Me * cie_colour_match[n][1];
- Z += Me * cie_colour_match[n][2];
- }
-
- /* Convert from xyz color space */
- float3 col = xyz_to_rgb(X, Y, Z);
-
- /* Clamp to zero if values are smaller */
- col = max(col, make_float3(0.0f, 0.0f, 0.0f));
-
- col.x = powf(col.x, 1.0f / BB_TABLE_YPOWER);
- col.y = powf(col.y, 1.0f / BB_TABLE_YPOWER);
- col.z = powf(col.z, 1.0f / BB_TABLE_YPOWER);
-
- /* Store in table in RRRGGGBBB format */
- blackbody_table[i] = col.x;
- blackbody_table[i+319*1] = col.y;
- blackbody_table[i+319*2] = col.z;
- }
-
- return blackbody_table;
-}
-CCL_NAMESPACE_END
diff --git a/intern/cycles/render/buffers.cpp b/intern/cycles/render/buffers.cpp
index fc65922fc87..fab3f701757 100644
--- a/intern/cycles/render/buffers.cpp
+++ b/intern/cycles/render/buffers.cpp
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#include <stdlib.h>
@@ -187,9 +187,23 @@ bool RenderBuffers::get_pass_rect(PassType type, float exposure, int sample, int
else if(type == PASS_MIST) {
for(int i = 0; i < size; i++, in += pass_stride, pixels++) {
float f = *in;
- pixels[0] = clamp(f*scale_exposure, 0.0f, 1.0f);
+ pixels[0] = saturate(f*scale_exposure);
}
}
+#ifdef WITH_CYCLES_DEBUG
+ else if(type == PASS_BVH_TRAVERSAL_STEPS) {
+ for(int i = 0; i < size; i++, in += pass_stride, pixels++) {
+ float f = *in;
+ pixels[0] = f;
+ }
+ }
+ else if(type == PASS_RAY_BOUNCES) {
+ for(int i = 0; i < size; i++, in += pass_stride, pixels++) {
+ float f = *in;
+ pixels[0] = f;
+ }
+ }
+#endif
else {
for(int i = 0; i < size; i++, in += pass_stride, pixels++) {
float f = *in;
@@ -290,7 +304,7 @@ bool RenderBuffers::get_pass_rect(PassType type, float exposure, int sample, int
pixels[2] = f.z*scale_exposure;
/* clamp since alpha might be > 1.0 due to russian roulette */
- pixels[3] = clamp(f.w*scale, 0.0f, 1.0f);
+ pixels[3] = saturate(f.w*scale);
}
}
}
@@ -361,13 +375,9 @@ void DisplayBuffer::draw_set(int width, int height)
void DisplayBuffer::draw(Device *device, const DeviceDrawParams& draw_params)
{
if(draw_width != 0 && draw_height != 0) {
- glPushMatrix();
- glTranslatef(params.full_x, params.full_y, 0.0f);
device_memory& rgba = rgba_data();
- device->draw_pixels(rgba, 0, draw_width, draw_height, 0, params.width, params.height, transparent, draw_params);
-
- glPopMatrix();
+ device->draw_pixels(rgba, 0, draw_width, draw_height, params.full_x, params.full_y, params.width, params.height, transparent, draw_params);
}
}
diff --git a/intern/cycles/render/buffers.h b/intern/cycles/render/buffers.h
index 27ab20bbafd..4fa1c51d821 100644
--- a/intern/cycles/render/buffers.h
+++ b/intern/cycles/render/buffers.h
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#ifndef __BUFFERS_H__
diff --git a/intern/cycles/render/camera.cpp b/intern/cycles/render/camera.cpp
index 71442d490ee..3b42cfa3c7b 100644
--- a/intern/cycles/render/camera.cpp
+++ b/intern/cycles/render/camera.cpp
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#include "camera.h"
@@ -28,32 +28,6 @@
CCL_NAMESPACE_BEGIN
-namespace {
-
-bool object_has_volume(Scene *scene, Object *object)
-{
- Mesh *mesh = object->mesh;
- foreach(uint shader, mesh->used_shaders) {
- if(scene->shaders[shader]->has_volume) {
- return true;
- }
- }
- return false;
-}
-
-bool scene_has_volume(Scene *scene)
-{
- for(size_t i = 0; i < scene->objects.size(); ++i) {
- Object *object = scene->objects[i];
- if(object_has_volume(scene, object)) {
- return true;
- }
- }
- return false;
-}
-
-} // namespace
-
Camera::Camera()
{
shuttertime = 1.0f;
@@ -68,6 +42,7 @@ Camera::Camera()
motion.pre = transform_identity();
motion.post = transform_identity();
use_motion = false;
+ use_perspective_motion = false;
aperture_ratio = 1.0f;
@@ -75,7 +50,12 @@ Camera::Camera()
panorama_type = PANORAMA_EQUIRECTANGULAR;
fisheye_fov = M_PI_F;
fisheye_lens = 10.5f;
+ latitude_min = -M_PI_2_F;
+ latitude_max = M_PI_2_F;
+ longitude_min = -M_PI_F;
+ longitude_max = M_PI_F;
fov = M_PI_4_F;
+ fov_pre = fov_post = fov;
sensorwidth = 0.036f;
sensorheight = 0.024f;
@@ -104,6 +84,7 @@ Camera::Camera()
need_update = true;
need_device_update = true;
+ need_flags_update = true;
previous_need_motion = -1;
graph = NULL;
@@ -116,19 +97,26 @@ Camera::~Camera()
void Camera::compute_auto_viewplane()
{
- float aspect = (float)width/(float)height;
-
- if(width >= height) {
- viewplane.left = -aspect;
- viewplane.right = aspect;
- viewplane.bottom = -1.0f;
+ if(type == CAMERA_PANORAMA) {
+ viewplane.left = 0.0f;
+ viewplane.right = 1.0f;
+ viewplane.bottom = 0.0f;
viewplane.top = 1.0f;
}
else {
- viewplane.left = -1.0f;
- viewplane.right = 1.0f;
- viewplane.bottom = -1.0f/aspect;
- viewplane.top = 1.0f/aspect;
+ float aspect = (float)width/(float)height;
+ if(width >= height) {
+ viewplane.left = -aspect;
+ viewplane.right = aspect;
+ viewplane.bottom = -1.0f;
+ viewplane.top = 1.0f;
+ }
+ else {
+ viewplane.left = -1.0f;
+ viewplane.right = 1.0f;
+ viewplane.bottom = -1.0f/aspect;
+ viewplane.top = 1.0f/aspect;
+ }
}
}
@@ -136,16 +124,17 @@ void Camera::update()
{
if(!need_update)
return;
-
+
+ /* Full viewport to camera border in the viewport. */
+ Transform fulltoborder = transform_from_viewplane(viewport_camera_border);
+ Transform bordertofull = transform_inverse(fulltoborder);
+
/* ndc to raster */
Transform screentocamera;
- Transform ndctoraster = transform_scale(width, height, 1.0f);
+ Transform ndctoraster = transform_scale(width, height, 1.0f) * bordertofull;
/* raster to screen */
- Transform screentondc =
- transform_scale(1.0f/(viewplane.right - viewplane.left),
- 1.0f/(viewplane.top - viewplane.bottom), 1.0f) *
- transform_translate(-viewplane.left, -viewplane.bottom, 0.0f);
+ Transform screentondc = fulltoborder * transform_from_viewplane(viewplane);
Transform screentoraster = ndctoraster * screentondc;
Transform rastertoscreen = transform_inverse(screentoraster);
@@ -188,15 +177,33 @@ void Camera::update()
transform_perspective(&rastertocamera, make_float3(0, 0, 0));
}
else {
- dx = make_float3(0, 0, 0);
- dy = make_float3(0, 0, 0);
+ dx = make_float3(0.0f, 0.0f, 0.0f);
+ dy = make_float3(0.0f, 0.0f, 0.0f);
}
dx = transform_direction(&cameratoworld, dx);
dy = transform_direction(&cameratoworld, dy);
+ /* TODO(sergey): Support other types of camera. */
+ if(type == CAMERA_PERSPECTIVE) {
+ /* TODO(sergey): Move to an utility function and de-duplicate with
+ * calculation above.
+ */
+ Transform screentocamera_pre =
+ transform_inverse(transform_perspective(fov_pre,
+ nearclip,
+ farclip));
+ Transform screentocamera_post =
+ transform_inverse(transform_perspective(fov_post,
+ nearclip,
+ farclip));
+ perspective_motion.pre = screentocamera_pre * rastertoscreen;
+ perspective_motion.post = screentocamera_post * rastertoscreen;
+ }
+
need_update = false;
need_device_update = true;
+ need_flags_update = true;
}
void Camera::device_update(Device *device, DeviceScene *dscene, Scene *scene)
@@ -205,7 +212,7 @@ void Camera::device_update(Device *device, DeviceScene *dscene, Scene *scene)
update();
- if (previous_need_motion != need_motion) {
+ if(previous_need_motion != need_motion) {
/* scene's motion model could have been changed since previous device
* camera update this could happen for example in case when one render
* layer has got motion pass and another not */
@@ -229,8 +236,10 @@ void Camera::device_update(Device *device, DeviceScene *dscene, Scene *scene)
/* camera motion */
kcam->have_motion = 0;
+ kcam->have_perspective_motion = 0;
if(need_motion == Scene::MOTION_PASS) {
+ /* TODO(sergey): Support perspective (zoom, fov) motion. */
if(type == CAMERA_PANORAMA) {
if(use_motion) {
kcam->motion.pre = transform_inverse(motion.pre);
@@ -258,6 +267,10 @@ void Camera::device_update(Device *device, DeviceScene *dscene, Scene *scene)
transform_motion_decompose((DecompMotionTransform*)&kcam->motion, &motion, &matrix);
kcam->have_motion = 1;
}
+ if(use_perspective_motion) {
+ kcam->perspective_motion = perspective_motion;
+ kcam->have_perspective_motion = 1;
+ }
}
#endif
@@ -284,6 +297,8 @@ void Camera::device_update(Device *device, DeviceScene *dscene, Scene *scene)
kcam->panorama_type = panorama_type;
kcam->fisheye_fov = fisheye_fov;
kcam->fisheye_lens = fisheye_lens;
+ kcam->equirectangular_range = make_float4(longitude_min - longitude_max, -longitude_min,
+ latitude_min - latitude_max, -latitude_min + M_PI_2_F);
/* sensor size */
kcam->sensorwidth = sensorwidth;
@@ -302,45 +317,13 @@ void Camera::device_update(Device *device, DeviceScene *dscene, Scene *scene)
kcam->nearclip = nearclip;
kcam->cliplength = (farclip == FLT_MAX)? FLT_MAX: farclip - nearclip;
- /* focal length */
- kcam->focal_length = focal_length;
+ /* Camera in volume. */
+ kcam->is_inside_volume = 0;
- need_device_update = false;
previous_need_motion = need_motion;
- /* Camera in volume. */
- kcam->is_inside_volume = 0;
- if(use_camera_in_volume) {
- if(type == CAMERA_PANORAMA) {
- /* It's not clear how to do viewplace->object intersection for
- * panoramic cameras, for now let's just check for whether there
- * are any volumes in the scene.
- */
- kcam->is_inside_volume = scene_has_volume(scene);
- }
- else {
- /* TODO(sergey): Whole bunch of stuff here actually:
- * - We do rather stupid check with object AABB to camera viewplane
- * AABB intersection, which is quite fast to perform, but which
- * could give some false-positives checks here, More grained check
- * would help avoiding time wasted n the kernel to initialize the
- * volume stack.
- * - We could cache has_volume in the cache, would save quite a few
- * CPU ticks when having loads of instanced meshes.
- */
- BoundBox viewplane_boundbox = viewplane_bounds_get();
- for(size_t i = 0; i < scene->objects.size(); ++i) {
- Object *object = scene->objects[i];
- if(object_has_volume(scene, object)) {
- if(viewplane_boundbox.intersects(object->bounds)) {
- /* TODO(sergey): Consider adding more grained check. */
- kcam->is_inside_volume = 1;
- break;
- }
- }
- }
- }
- }
+ /* focal length */
+ kcam->focal_length = focal_length;
/* TODO(sergey): Make sure shaders are fully synced at this point. */
if(graph != NULL) {
@@ -351,7 +334,30 @@ void Camera::device_update(Device *device, DeviceScene *dscene, Scene *scene)
}
}
-void Camera::device_free(Device *device, DeviceScene *dscene)
+void Camera::device_update_volume(Device * /*device*/,
+ DeviceScene *dscene,
+ Scene *scene)
+{
+ if(!need_device_update && !need_flags_update) {
+ return;
+ }
+ KernelCamera *kcam = &dscene->data.cam;
+ BoundBox viewplane_boundbox = viewplane_bounds_get();
+ for(size_t i = 0; i < scene->objects.size(); ++i) {
+ Object *object = scene->objects[i];
+ if(object->mesh->has_volume &&
+ viewplane_boundbox.intersects(object->bounds))
+ {
+ /* TODO(sergey): Consider adding more grained check. */
+ kcam->is_inside_volume = 1;
+ break;
+ }
+ }
+ need_device_update = false;
+ need_flags_update = false;
+}
+
+void Camera::device_free(Device * /*device*/, DeviceScene * /*dscene*/)
{
/* nothing to free, only writing to constant memory */
}
@@ -379,7 +385,11 @@ bool Camera::modified(const Camera& cam)
(aperture_ratio == cam.aperture_ratio) &&
(panorama_type == cam.panorama_type) &&
(fisheye_fov == cam.fisheye_fov) &&
- (fisheye_lens == cam.fisheye_lens));
+ (fisheye_lens == cam.fisheye_lens) &&
+ (latitude_min == cam.latitude_min) &&
+ (latitude_max == cam.latitude_max) &&
+ (longitude_min == cam.longitude_min) &&
+ (longitude_max == cam.longitude_max));
}
bool Camera::motion_modified(const Camera& cam)
@@ -399,6 +409,7 @@ float3 Camera::transform_raster_to_world(float raster_x, float raster_y)
if(type == CAMERA_PERSPECTIVE) {
D = transform_perspective(&rastertocamera,
make_float3(raster_x, raster_y, 0.0f));
+ float3 Pclip = normalize(D);
P = make_float3(0.0f, 0.0f, 0.0f);
/* TODO(sergey): Aperture support? */
P = transform_point(&cameratoworld, P);
@@ -407,9 +418,9 @@ float3 Camera::transform_raster_to_world(float raster_x, float raster_y)
* be mistakes in here, currently leading to wrong camera-in-volume
* detection.
*/
- P += nearclip * D;
+ P += nearclip * D / Pclip.z;
}
- else if (type == CAMERA_ORTHOGRAPHIC) {
+ else if(type == CAMERA_ORTHOGRAPHIC) {
D = make_float3(0.0f, 0.0f, 1.0f);
/* TODO(sergey): Aperture support? */
P = transform_perspective(&rastertocamera,
@@ -425,21 +436,27 @@ float3 Camera::transform_raster_to_world(float raster_x, float raster_y)
BoundBox Camera::viewplane_bounds_get()
{
- assert(type != CAMERA_PANORAMA);
-
/* TODO(sergey): This is all rather stupid, but is there a way to perform
* checks we need in a more clear and smart fasion?
*/
BoundBox bounds = BoundBox::empty;
- bounds.grow(transform_raster_to_world(0.0f, 0.0f));
- bounds.grow(transform_raster_to_world(0.0f, (float)height));
- bounds.grow(transform_raster_to_world((float)width, (float)height));
- bounds.grow(transform_raster_to_world((float)width, 0.0f));
- if(type == CAMERA_PERSPECTIVE) {
- /* Center point has the most distancei in local Z axis,
- * use it to construct bounding box/
- */
- bounds.grow(transform_raster_to_world(0.5f*width, 0.5f*height));
+
+ if(type == CAMERA_PANORAMA) {
+ bounds.grow(make_float3(cameratoworld.x.w,
+ cameratoworld.y.w,
+ cameratoworld.z.w));
+ }
+ else {
+ bounds.grow(transform_raster_to_world(0.0f, 0.0f));
+ bounds.grow(transform_raster_to_world(0.0f, (float)height));
+ bounds.grow(transform_raster_to_world((float)width, (float)height));
+ bounds.grow(transform_raster_to_world((float)width, 0.0f));
+ if(type == CAMERA_PERSPECTIVE) {
+ /* Center point has the most distance in local Z axis,
+ * use it to construct bounding box/
+ */
+ bounds.grow(transform_raster_to_world(0.5f*width, 0.5f*height));
+ }
}
return bounds;
}
diff --git a/intern/cycles/render/camera.h b/intern/cycles/render/camera.h
index ff93420bccc..cca5417740c 100644
--- a/intern/cycles/render/camera.h
+++ b/intern/cycles/render/camera.h
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#ifndef __CAMERA_H__
@@ -55,6 +55,10 @@ public:
PanoramaType panorama_type;
float fisheye_fov;
float fisheye_lens;
+ float latitude_min;
+ float latitude_max;
+ float longitude_min;
+ float longitude_max;
/* anamorphic lens bokeh */
float aperture_ratio;
@@ -74,13 +78,16 @@ public:
/* border */
BoundBox2D border;
+ BoundBox2D viewport_camera_border;
/* transformation */
Transform matrix;
/* motion */
MotionTransform motion;
- bool use_motion;
+ bool use_motion, use_perspective_motion;
+ float fov_pre, fov_post;
+ PerspectiveMotionTransform perspective_motion;
/* computed camera parameters */
Transform screentoworld;
@@ -102,15 +109,9 @@ public:
/* update */
bool need_update;
bool need_device_update;
+ bool need_flags_update;
int previous_need_motion;
- /* Camera in volume. */
- /* TODO(sergey): Get rid of this argument once
- * cameras in volume considered fast enough for
- * the regular kernel.
- */
- bool use_camera_in_volume;
-
/* Camera ray nodes. */
CameraNodesGraph *graph;
@@ -120,19 +121,24 @@ public:
void compute_auto_viewplane();
+ void set_graph(CameraNodesGraph *graph);
+
void update();
void device_update(Device *device, DeviceScene *dscene, Scene *scene);
+ void device_update_volume(Device *device, DeviceScene *dscene, Scene *scene);
void device_free(Device *device, DeviceScene *dscene);
bool modified(const Camera& cam);
bool motion_modified(const Camera& cam);
void tag_update();
+ /* Public utility functions. */
BoundBox viewplane_bounds_get();
- float3 transform_raster_to_world(float raster_x, float raster_y);
- void set_graph(CameraNodesGraph *graph);
+private:
+ /* Private utility functions. */
+ float3 transform_raster_to_world(float raster_x, float raster_y);
};
CCL_NAMESPACE_END
diff --git a/intern/cycles/render/curves.cpp b/intern/cycles/render/curves.cpp
index dc7665fe144..f671eb19cae 100644
--- a/intern/cycles/render/curves.cpp
+++ b/intern/cycles/render/curves.cpp
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#include "device.h"
@@ -103,7 +103,10 @@ CurveSystemManager::~CurveSystemManager()
{
}
-void CurveSystemManager::device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress)
+void CurveSystemManager::device_update(Device *device,
+ DeviceScene *dscene,
+ Scene * /*scene*/,
+ Progress& progress)
{
if(!need_update)
return;
@@ -144,7 +147,8 @@ void CurveSystemManager::device_update(Device *device, DeviceScene *dscene, Scen
need_update = false;
}
-void CurveSystemManager::device_free(Device *device, DeviceScene *dscene)
+void CurveSystemManager::device_free(Device * /*device*/,
+ DeviceScene * /*dscene*/)
{
}
@@ -174,7 +178,7 @@ bool CurveSystemManager::modified_mesh(const CurveSystemManager& CurveSystemMana
use_curves == CurveSystemManager.use_curves);
}
-void CurveSystemManager::tag_update(Scene *scene)
+void CurveSystemManager::tag_update(Scene * /*scene*/)
{
need_update = true;
}
diff --git a/intern/cycles/render/curves.h b/intern/cycles/render/curves.h
index 6fd0fff57fb..22ab5d05f8a 100644
--- a/intern/cycles/render/curves.h
+++ b/intern/cycles/render/curves.h
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#ifndef __CURVES_H__
diff --git a/intern/cycles/render/film.cpp b/intern/cycles/render/film.cpp
index 09973e8bc86..58080289633 100644
--- a/intern/cycles/render/film.cpp
+++ b/intern/cycles/render/film.cpp
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#include "camera.h"
@@ -144,8 +144,28 @@ void Pass::add(PassType type, vector<Pass>& passes)
pass.exposure = false;
break;
case PASS_LIGHT:
- /* ignores */
+ /* This isn't a real pass, used by baking to see whether
+ * light data is needed or not.
+ *
+ * Set components to 0 so pass sort below happens in a
+ * determined way.
+ */
+ pass.components = 0;
+ break;
+#ifdef WITH_CYCLES_DEBUG
+ case PASS_BVH_TRAVERSAL_STEPS:
+ pass.components = 1;
+ pass.exposure = false;
break;
+ case PASS_BVH_TRAVERSED_INSTANCES:
+ pass.components = 1;
+ pass.exposure = false;
+ break;
+ case PASS_RAY_BOUNCES:
+ pass.components = 1;
+ pass.exposure = false;
+ break;
+#endif
}
passes.push_back(pass);
@@ -181,7 +201,7 @@ bool Pass::contains(const vector<Pass>& passes, PassType type)
/* Pixel Filter */
-static float filter_func_box(float v, float width)
+static float filter_func_box(float /*v*/, float /*width*/)
{
return 1.0f;
}
@@ -388,6 +408,19 @@ void Film::device_update(Device *device, DeviceScene *dscene, Scene *scene)
case PASS_LIGHT:
kfilm->use_light_pass = 1;
break;
+
+#ifdef WITH_CYCLES_DEBUG
+ case PASS_BVH_TRAVERSAL_STEPS:
+ kfilm->pass_bvh_traversal_steps = kfilm->pass_stride;
+ break;
+ case PASS_BVH_TRAVERSED_INSTANCES:
+ kfilm->pass_bvh_traversed_instances = kfilm->pass_stride;
+ break;
+ case PASS_RAY_BOUNCES:
+ kfilm->pass_ray_bounces = kfilm->pass_stride;
+ break;
+#endif
+
case PASS_NONE:
break;
}
@@ -411,7 +444,9 @@ void Film::device_update(Device *device, DeviceScene *dscene, Scene *scene)
need_update = false;
}
-void Film::device_free(Device *device, DeviceScene *dscene, Scene *scene)
+void Film::device_free(Device * /*device*/,
+ DeviceScene * /*dscene*/,
+ Scene *scene)
{
if(filter_table_offset != TABLE_OFFSET_INVALID) {
scene->lookup_tables->remove_table(filter_table_offset);
@@ -446,7 +481,7 @@ void Film::tag_passes_update(Scene *scene, const vector<Pass>& passes_)
passes = passes_;
}
-void Film::tag_update(Scene *scene)
+void Film::tag_update(Scene * /*scene*/)
{
need_update = true;
}
diff --git a/intern/cycles/render/film.h b/intern/cycles/render/film.h
index cc7183bfd95..e2cd63cc2ed 100644
--- a/intern/cycles/render/film.h
+++ b/intern/cycles/render/film.h
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#ifndef __FILM_H__
diff --git a/intern/cycles/render/graph.cpp b/intern/cycles/render/graph.cpp
index d6c6d019b03..dad1e2bafa0 100644
--- a/intern/cycles/render/graph.cpp
+++ b/intern/cycles/render/graph.cpp
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#include "attribute.h"
@@ -34,7 +34,7 @@ ShaderInput::ShaderInput(ShaderNode *parent_, const char *name_, ShaderSocketTyp
name = name_;
type = type_;
link = NULL;
- value = make_float3(0, 0, 0);
+ value = make_float3(0.0f, 0.0f, 0.0f);
stack_offset = SVM_STACK_INVALID;
default_value = NONE;
usage = USE_ALL;
@@ -228,6 +228,21 @@ void ShaderGraph::disconnect(ShaderInput *to)
from->links.erase(remove(from->links.begin(), from->links.end(), to), from->links.end());
}
+void ShaderGraph::relink(vector<ShaderInput*> inputs, vector<ShaderInput*> outputs, ShaderOutput *output)
+{
+ /* Remove nodes and re-link if output isn't NULL. */
+ foreach(ShaderInput *sock, inputs) {
+ if(sock->link)
+ disconnect(sock);
+ }
+
+ foreach(ShaderInput *sock, outputs) {
+ disconnect(sock);
+ if(output)
+ connect(output, sock);
+ }
+}
+
void ShaderGraph::finalize(bool do_bump, bool do_osl)
{
/* before compiling, the shader graph may undergo a number of modifications.
@@ -322,6 +337,8 @@ void ShaderGraph::remove_unneeded_nodes()
vector<bool> removed(num_node_ids, false);
bool any_node_removed = false;
+ ShaderNode *geom = NULL;
+
/* find and unlink proxy nodes */
foreach(ShaderNode *node, nodes) {
if(node->special_type == SHADER_SPECIAL_TYPE_PROXY) {
@@ -375,6 +392,58 @@ void ShaderGraph::remove_unneeded_nodes()
removed[proxy->id] = true;
any_node_removed = true;
}
+ else if(node->special_type == SHADER_SPECIAL_TYPE_BACKGROUND) {
+ BackgroundNode *bg = static_cast<BackgroundNode*>(node);
+
+ if(bg->outputs[0]->links.size()) {
+ /* Black color or zero strength, remove node */
+ if((!bg->inputs[0]->link && bg->inputs[0]->value == make_float3(0.0f, 0.0f, 0.0f)) ||
+ (!bg->inputs[1]->link && bg->inputs[1]->value.x == 0.0f)) {
+ vector<ShaderInput*> inputs = bg->outputs[0]->links;
+
+ relink(bg->inputs, inputs, NULL);
+ removed[bg->id] = true;
+ any_node_removed = true;
+ }
+ }
+ }
+ else if(node->special_type == SHADER_SPECIAL_TYPE_EMISSION) {
+ EmissionNode *em = static_cast<EmissionNode*>(node);
+
+ if(em->outputs[0]->links.size()) {
+ /* Black color or zero strength, remove node */
+ if((!em->inputs[0]->link && em->inputs[0]->value == make_float3(0.0f, 0.0f, 0.0f)) ||
+ (!em->inputs[1]->link && em->inputs[1]->value.x == 0.0f)) {
+ vector<ShaderInput*> inputs = em->outputs[0]->links;
+
+ relink(em->inputs, inputs, NULL);
+ removed[em->id] = true;
+ any_node_removed = true;
+ }
+ }
+ }
+ else if(node->special_type == SHADER_SPECIAL_TYPE_BUMP) {
+ BumpNode *bump = static_cast<BumpNode*>(node);
+
+ if(bump->outputs[0]->links.size()) {
+ /* Height inputs is not connected. */
+ /* TODO(sergey): Ignore bump with zero strength. */
+ if(bump->inputs[0]->link == NULL) {
+ vector<ShaderInput*> inputs = bump->outputs[0]->links;
+ if(bump->inputs[4]->link == NULL) {
+ if(geom == NULL) {
+ geom = new GeometryNode();
+ }
+ relink(bump->inputs, inputs, geom->output("Normal"));
+ }
+ else {
+ relink(bump->inputs, inputs, bump->input("Normal")->link);
+ }
+ removed[bump->id] = true;
+ any_node_removed = true;
+ }
+ }
+ }
else if(node->special_type == SHADER_SPECIAL_TYPE_MIX_CLOSURE) {
MixClosureNode *mix = static_cast<MixClosureNode*>(node);
@@ -383,15 +452,7 @@ void ShaderGraph::remove_unneeded_nodes()
ShaderOutput *output = mix->inputs[1]->link;
vector<ShaderInput*> inputs = mix->outputs[0]->links;
- foreach(ShaderInput *sock, mix->inputs)
- if(sock->link)
- disconnect(sock);
-
- foreach(ShaderInput *input, inputs) {
- disconnect(input);
- if(output)
- connect(output, input);
- }
+ relink(mix->inputs, inputs, output);
removed[mix->id] = true;
any_node_removed = true;
}
@@ -404,15 +465,7 @@ void ShaderGraph::remove_unneeded_nodes()
ShaderOutput *output = mix->inputs[1]->link;
vector<ShaderInput*> inputs = mix->outputs[0]->links;
- foreach(ShaderInput *sock, mix->inputs)
- if(sock->link)
- disconnect(sock);
-
- foreach(ShaderInput *input, inputs) {
- disconnect(input);
- if(output)
- connect(output, input);
- }
+ relink(mix->inputs, inputs, output);
removed[mix->id] = true;
any_node_removed = true;
}
@@ -420,16 +473,8 @@ void ShaderGraph::remove_unneeded_nodes()
else if(mix->inputs[0]->value.x == 1.0f) {
ShaderOutput *output = mix->inputs[2]->link;
vector<ShaderInput*> inputs = mix->outputs[0]->links;
-
- foreach(ShaderInput *sock, mix->inputs)
- if(sock->link)
- disconnect(sock);
-
- foreach(ShaderInput *input, inputs) {
- disconnect(input);
- if(output)
- connect(output, input);
- }
+
+ relink(mix->inputs, inputs, output);
removed[mix->id] = true;
any_node_removed = true;
}
@@ -446,15 +491,7 @@ void ShaderGraph::remove_unneeded_nodes()
ShaderOutput *output = mix->inputs[1]->link;
vector<ShaderInput*> inputs = mix->outputs[0]->links;
- foreach(ShaderInput *sock, mix->inputs)
- if(sock->link)
- disconnect(sock);
-
- foreach(ShaderInput *input, inputs) {
- disconnect(input);
- if(output)
- connect(output, input);
- }
+ relink(mix->inputs, inputs, output);
removed[mix->id] = true;
any_node_removed = true;
}
@@ -463,15 +500,7 @@ void ShaderGraph::remove_unneeded_nodes()
ShaderOutput *output = mix->inputs[2]->link;
vector<ShaderInput*> inputs = mix->outputs[0]->links;
- foreach(ShaderInput *sock, mix->inputs)
- if(sock->link)
- disconnect(sock);
-
- foreach(ShaderInput *input, inputs) {
- disconnect(input);
- if(output)
- connect(output, input);
- }
+ relink(mix->inputs, inputs, output);
removed[mix->id] = true;
any_node_removed = true;
}
@@ -492,6 +521,10 @@ void ShaderGraph::remove_unneeded_nodes()
nodes = newnodes;
}
+
+ if(geom != NULL) {
+ add(geom);
+ }
}
void ShaderGraph::break_cycles(ShaderNode *node, vector<bool>& visited, vector<bool>& on_stack)
@@ -520,7 +553,7 @@ void ShaderGraph::break_cycles(ShaderNode *node, vector<bool>& visited, vector<b
void ShaderGraph::clean()
{
- /* remove proxy and unnecessary mix nodes */
+ /* remove proxy and unnecessary nodes */
remove_unneeded_nodes();
/* we do two things here: find cycles and break them, and remove unused
@@ -556,7 +589,7 @@ void ShaderGraph::clean()
else
delete node;
}
-
+
nodes = newnodes;
}
@@ -685,7 +718,7 @@ void ShaderGraph::bump_from_displacement()
* different shifted coordinates.
*
* these 3 displacement values are then fed into the bump node, which will
- * output the the perturbed normal. */
+ * output the perturbed normal. */
ShaderInput *displacement_in = output()->input("Displacement");
@@ -738,10 +771,18 @@ void ShaderGraph::bump_from_displacement()
/* connect bump output to normal input nodes that aren't set yet. actually
* this will only set the normal input to the geometry node that we created
* and connected to all other normal inputs already. */
- foreach(ShaderNode *node, nodes)
- foreach(ShaderInput *input, node->inputs)
+ foreach(ShaderNode *node, nodes) {
+ /* Don't connect normal to the bump node we're coming from,
+ * otherwise it'll be a cycle in graph.
+ */
+ if(node == bump) {
+ continue;
+ }
+ foreach(ShaderInput *input, node->inputs) {
if(!input->link && input->default_value == ShaderInput::NORMAL)
connect(set_normal->output("Normal"), input);
+ }
+ }
/* for displacement bump, clear the normal input in case the above loop
* connected the setnormal out to the bump normalin */
@@ -836,6 +877,26 @@ void ShaderGraph::transform_multi_closure(ShaderNode *node, ShaderOutput *weight
}
}
+int ShaderGraph::get_num_closures()
+{
+ int num_closures = 0;
+ foreach(ShaderNode *node, nodes) {
+ if(node->special_type == SHADER_SPECIAL_TYPE_CLOSURE) {
+ BsdfNode *bsdf_node = static_cast<BsdfNode*>(node);
+ /* TODO(sergey): Make it more generic approach, maybe some utility
+ * macros like CLOSURE_IS_FOO()?
+ */
+ if(CLOSURE_IS_BSSRDF(bsdf_node->closure))
+ num_closures = num_closures + 3;
+ else if(CLOSURE_IS_GLASS(bsdf_node->closure))
+ num_closures = num_closures + 2;
+ else
+ num_closures = num_closures + 1;
+ }
+ }
+ return num_closures;
+}
+
void ShaderGraph::dump_graph(const char *filename)
{
FILE *fd = fopen(filename, "w");
@@ -845,31 +906,61 @@ void ShaderGraph::dump_graph(const char *filename)
return;
}
- fprintf(fd, "digraph dependencygraph {\n");
+ fprintf(fd, "digraph shader_graph {\n");
fprintf(fd, "ranksep=1.5\n");
+ fprintf(fd, "rankdir=LR\n");
fprintf(fd, "splines=false\n");
foreach(ShaderNode *node, nodes) {
fprintf(fd, "// NODE: %p\n", node);
- fprintf(fd,
- "\"%p\" [shape=record,label=\"%s\"]\n",
- node,
- node->name.c_str());
+ fprintf(fd, "\"%p\" [shape=record,label=\"{", node);
+ if(node->inputs.size()) {
+ fprintf(fd, "{");
+ foreach(ShaderInput *socket, node->inputs) {
+ if(socket != node->inputs[0]) {
+ fprintf(fd, "|");
+ }
+ fprintf(fd, "<IN_%p>%s", socket, socket->name);
+ }
+ fprintf(fd, "}|");
+ }
+ fprintf(fd, "%s", node->name.c_str());
+ if(node->bump == SHADER_BUMP_CENTER) {
+ fprintf(fd, " (bump:center)");
+ }
+ else if(node->bump == SHADER_BUMP_DX) {
+ fprintf(fd, " (bump:dx)");
+ }
+ else if(node->bump == SHADER_BUMP_DY) {
+ fprintf(fd, " (bump:dy)");
+ }
+ if(node->outputs.size()) {
+ fprintf(fd, "|{");
+ foreach(ShaderOutput *socket, node->outputs) {
+ if(socket != node->outputs[0]) {
+ fprintf(fd, "|");
+ }
+ fprintf(fd, "<OUT_%p>%s", socket, socket->name);
+ }
+ fprintf(fd, "}");
+ }
+ fprintf(fd, "}\"]");
}
foreach(ShaderNode *node, nodes) {
foreach(ShaderOutput *output, node->outputs) {
foreach(ShaderInput *input, output->links) {
fprintf(fd,
- "// CONNECTION: %p->%p (%s:%s)\n",
+ "// CONNECTION: OUT_%p->IN_%p (%s:%s)\n",
output,
input,
output->name, input->name);
fprintf(fd,
- "\"%p\":s -> \"%p\":n [label=\"%s:%s\"]\n",
+ "\"%p\":\"OUT_%p\":e -> \"%p\":\"IN_%p\":w [label=\"\"]\n",
output->parent,
+ output,
input->parent,
- output->name, input->name);
+ input);
}
}
}
diff --git a/intern/cycles/render/graph.h b/intern/cycles/render/graph.h
index 29fa1403597..e61c20c416a 100644
--- a/intern/cycles/render/graph.h
+++ b/intern/cycles/render/graph.h
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#ifndef __GRAPH_H__
@@ -80,7 +80,12 @@ enum ShaderNodeSpecialType {
SHADER_SPECIAL_TYPE_MIX_RGB, /* Only Mix subtype */
SHADER_SPECIAL_TYPE_AUTOCONVERT,
SHADER_SPECIAL_TYPE_GEOMETRY,
- SHADER_SPECIAL_TYPE_SCRIPT
+ SHADER_SPECIAL_TYPE_SCRIPT,
+ SHADER_SPECIAL_TYPE_BACKGROUND,
+ SHADER_SPECIAL_TYPE_IMAGE_SLOT,
+ SHADER_SPECIAL_TYPE_CLOSURE,
+ SHADER_SPECIAL_TYPE_EMISSION,
+ SHADER_SPECIAL_TYPE_BUMP,
};
/* Enum
@@ -193,9 +198,9 @@ public:
virtual bool has_surface_emission() { return false; }
virtual bool has_surface_transparent() { return false; }
virtual bool has_surface_bssrdf() { return false; }
- virtual bool has_converter_blackbody() { return false; }
virtual bool has_bssrdf_bump() { return false; }
virtual bool has_spatial_varying() { return false; }
+ virtual bool has_object_dependency() { return false; }
vector<ShaderInput*> inputs;
vector<ShaderOutput*> outputs;
@@ -205,6 +210,24 @@ public:
ShaderBump bump; /* for bump mapping utility */
ShaderNodeSpecialType special_type; /* special node type */
+
+ /* ** Selective nodes compilation ** */
+
+ /* TODO(sergey): More explicitly mention in the function names
+ * that those functions are for selective compilation only?
+ */
+
+ /* Nodes are split into several groups, group of level 0 contains
+ * nodes which are most commonly used, further levels are extension
+ * of previous one and includes less commonly used nodes.
+ */
+ virtual int get_group() { return NODE_GROUP_LEVEL_0; }
+
+ /* Node feature are used to disable huge nodes inside the group,
+ * so it's possible to disable huge nodes inside of the required
+ * nodes group.
+ */
+ virtual int get_feature() { return bump == SHADER_BUMP_NONE ? 0 : NODE_FEATURE_BUMP; }
};
@@ -247,10 +270,13 @@ public:
void connect(ShaderOutput *from, ShaderInput *to);
void disconnect(ShaderInput *to);
+ void relink(vector<ShaderInput*> inputs, vector<ShaderInput*> outputs, ShaderOutput *output);
void remove_unneeded_nodes();
void finalize(bool do_bump = false, bool do_osl = false);
+ int get_num_closures();
+
void dump_graph(const char *filename);
protected:
diff --git a/intern/cycles/render/image.cpp b/intern/cycles/render/image.cpp
index 076cc3d8b63..7bceb8a8bfa 100644
--- a/intern/cycles/render/image.cpp
+++ b/intern/cycles/render/image.cpp
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#include "device.h"
@@ -151,15 +151,27 @@ bool ImageManager::is_float_image(const string& filename, void *builtin_data, bo
return is_float;
}
-static bool image_equals(ImageManager::Image *image, const string& filename, void *builtin_data, InterpolationType interpolation)
+static bool image_equals(ImageManager::Image *image,
+ const string& filename,
+ void *builtin_data,
+ InterpolationType interpolation,
+ ExtensionType extension)
{
return image->filename == filename &&
image->builtin_data == builtin_data &&
- image->interpolation == interpolation;
+ image->interpolation == interpolation &&
+ image->extension == extension;
}
-int ImageManager::add_image(const string& filename, void *builtin_data, bool animated, float frame,
- bool& is_float, bool& is_linear, InterpolationType interpolation, bool use_alpha)
+int ImageManager::add_image(const string& filename,
+ void *builtin_data,
+ bool animated,
+ float frame,
+ bool& is_float,
+ bool& is_linear,
+ InterpolationType interpolation,
+ ExtensionType extension,
+ bool use_alpha)
{
Image *img;
size_t slot;
@@ -171,11 +183,20 @@ int ImageManager::add_image(const string& filename, void *builtin_data, bool ani
/* find existing image */
for(slot = 0; slot < float_images.size(); slot++) {
img = float_images[slot];
- if(img && image_equals(img, filename, builtin_data, interpolation)) {
+ if(img && image_equals(img,
+ filename,
+ builtin_data,
+ interpolation,
+ extension))
+ {
if(img->frame != frame) {
img->frame = frame;
img->need_load = true;
}
+ if(img->use_alpha != use_alpha) {
+ img->use_alpha = use_alpha;
+ img->need_load = true;
+ }
img->users++;
return slot;
}
@@ -206,6 +227,7 @@ int ImageManager::add_image(const string& filename, void *builtin_data, bool ani
img->animated = animated;
img->frame = frame;
img->interpolation = interpolation;
+ img->extension = extension;
img->users = 1;
img->use_alpha = use_alpha;
@@ -214,11 +236,20 @@ int ImageManager::add_image(const string& filename, void *builtin_data, bool ani
else {
for(slot = 0; slot < images.size(); slot++) {
img = images[slot];
- if(img && image_equals(img, filename, builtin_data, interpolation)) {
+ if(img && image_equals(img,
+ filename,
+ builtin_data,
+ interpolation,
+ extension))
+ {
if(img->frame != frame) {
img->frame = frame;
img->need_load = true;
}
+ if(img->use_alpha != use_alpha) {
+ img->use_alpha = use_alpha;
+ img->need_load = true;
+ }
img->users++;
return slot+tex_image_byte_start;
}
@@ -249,6 +280,7 @@ int ImageManager::add_image(const string& filename, void *builtin_data, bool ani
img->animated = animated;
img->frame = frame;
img->interpolation = interpolation;
+ img->extension = extension;
img->users = 1;
img->use_alpha = use_alpha;
@@ -292,12 +324,20 @@ void ImageManager::remove_image(int slot)
}
}
-void ImageManager::remove_image(const string& filename, void *builtin_data, InterpolationType interpolation)
+void ImageManager::remove_image(const string& filename,
+ void *builtin_data,
+ InterpolationType interpolation,
+ ExtensionType extension)
{
size_t slot;
for(slot = 0; slot < images.size(); slot++) {
- if(images[slot] && image_equals(images[slot], filename, builtin_data, interpolation)) {
+ if(images[slot] && image_equals(images[slot],
+ filename,
+ builtin_data,
+ interpolation,
+ extension))
+ {
remove_image(slot+tex_image_byte_start);
break;
}
@@ -306,7 +346,11 @@ void ImageManager::remove_image(const string& filename, void *builtin_data, Inte
if(slot == images.size()) {
/* see if it's in a float texture slot */
for(slot = 0; slot < float_images.size(); slot++) {
- if(float_images[slot] && image_equals(float_images[slot], filename, builtin_data, interpolation)) {
+ if(float_images[slot] && image_equals(float_images[slot],
+ filename,
+ builtin_data,
+ interpolation,
+ extension)) {
remove_image(slot);
break;
}
@@ -318,12 +362,19 @@ void ImageManager::remove_image(const string& filename, void *builtin_data, Inte
* without bunch of arguments passing around making code readability even
* more cluttered.
*/
-void ImageManager::tag_reload_image(const string& filename, void *builtin_data, InterpolationType interpolation)
+void ImageManager::tag_reload_image(const string& filename,
+ void *builtin_data,
+ InterpolationType interpolation,
+ ExtensionType extension)
{
size_t slot;
for(slot = 0; slot < images.size(); slot++) {
- if(images[slot] && image_equals(images[slot], filename, builtin_data, interpolation)) {
+ if(images[slot] && image_equals(images[slot],
+ filename,
+ builtin_data,
+ interpolation,
+ extension)) {
images[slot]->need_load = true;
break;
}
@@ -332,7 +383,11 @@ void ImageManager::tag_reload_image(const string& filename, void *builtin_data,
if(slot == images.size()) {
/* see if it's in a float texture slot */
for(slot = 0; slot < float_images.size(); slot++) {
- if(float_images[slot] && image_equals(float_images[slot], filename, builtin_data, interpolation)) {
+ if(float_images[slot] && image_equals(float_images[slot],
+ filename,
+ builtin_data,
+ interpolation,
+ extension)) {
float_images[slot]->need_load = true;
break;
}
@@ -399,7 +454,7 @@ bool ImageManager::file_load_image(Image *img, device_vector<uchar4>& tex_img)
int scanlinesize = width*components*sizeof(uchar);
in->read_image(TypeDesc::UINT8,
- (uchar*)pixels + (height-1)*scanlinesize,
+ (uchar*)pixels + (((size_t)height)-1)*scanlinesize,
AutoStride,
-scanlinesize,
AutoStride);
@@ -417,9 +472,10 @@ bool ImageManager::file_load_image(Image *img, device_vector<uchar4>& tex_img)
builtin_image_pixels_cb(img->filename, img->builtin_data, pixels);
}
+ size_t num_pixels = ((size_t)width) * height * depth;
if(cmyk) {
/* CMYK */
- for(int i = width*height*depth-1; i >= 0; i--) {
+ for(size_t i = num_pixels-1, pixel = 0; pixel < num_pixels; pixel++, i--) {
pixels[i*4+2] = (pixels[i*4+2]*pixels[i*4+3])/255;
pixels[i*4+1] = (pixels[i*4+1]*pixels[i*4+3])/255;
pixels[i*4+0] = (pixels[i*4+0]*pixels[i*4+3])/255;
@@ -428,7 +484,7 @@ bool ImageManager::file_load_image(Image *img, device_vector<uchar4>& tex_img)
}
else if(components == 2) {
/* grayscale + alpha */
- for(int i = width*height*depth-1; i >= 0; i--) {
+ for(size_t i = num_pixels-1, pixel = 0; pixel < num_pixels; pixel++, i--) {
pixels[i*4+3] = pixels[i*2+1];
pixels[i*4+2] = pixels[i*2+0];
pixels[i*4+1] = pixels[i*2+0];
@@ -437,7 +493,7 @@ bool ImageManager::file_load_image(Image *img, device_vector<uchar4>& tex_img)
}
else if(components == 3) {
/* RGB */
- for(int i = width*height*depth-1; i >= 0; i--) {
+ for(size_t i = num_pixels-1, pixel = 0; pixel < num_pixels; pixel++, i--) {
pixels[i*4+3] = 255;
pixels[i*4+2] = pixels[i*3+2];
pixels[i*4+1] = pixels[i*3+1];
@@ -446,7 +502,7 @@ bool ImageManager::file_load_image(Image *img, device_vector<uchar4>& tex_img)
}
else if(components == 1) {
/* grayscale */
- for(int i = width*height*depth-1; i >= 0; i--) {
+ for(size_t i = num_pixels-1, pixel = 0; pixel < num_pixels; pixel++, i--) {
pixels[i*4+3] = 255;
pixels[i*4+2] = pixels[i];
pixels[i*4+1] = pixels[i];
@@ -455,7 +511,7 @@ bool ImageManager::file_load_image(Image *img, device_vector<uchar4>& tex_img)
}
if(img->use_alpha == false) {
- for(int i = width*height*depth-1; i >= 0; i--) {
+ for(size_t i = num_pixels-1, pixel = 0; pixel < num_pixels; pixel++, i--) {
pixels[i*4+3] = 255;
}
}
@@ -521,7 +577,7 @@ bool ImageManager::file_load_float_image(Image *img, device_vector<float4>& tex_
vector<float> tmppixels;
if(components > 4) {
- tmppixels.resize(width*height*components);
+ tmppixels.resize(((size_t)width)*height*components);
readpixels = &tmppixels[0];
}
@@ -539,7 +595,8 @@ bool ImageManager::file_load_float_image(Image *img, device_vector<float4>& tex_
}
if(components > 4) {
- for(int i = width*height-1; i >= 0; i--) {
+ size_t dimensions = ((size_t)width)*height;
+ for(size_t i = dimensions-1, pixel = 0; pixel < dimensions; pixel++, i--) {
pixels[i*4+3] = tmppixels[i*components+3];
pixels[i*4+2] = tmppixels[i*components+2];
pixels[i*4+1] = tmppixels[i*components+1];
@@ -558,9 +615,10 @@ bool ImageManager::file_load_float_image(Image *img, device_vector<float4>& tex_
builtin_image_float_pixels_cb(img->filename, img->builtin_data, pixels);
}
+ size_t num_pixels = ((size_t)width) * height * depth;
if(cmyk) {
/* CMYK */
- for(int i = width*height*depth-1; i >= 0; i--) {
+ for(size_t i = num_pixels-1, pixel = 0; pixel < num_pixels; pixel++, i--) {
pixels[i*4+3] = 255;
pixels[i*4+2] = (pixels[i*4+2]*pixels[i*4+3])/255;
pixels[i*4+1] = (pixels[i*4+1]*pixels[i*4+3])/255;
@@ -569,7 +627,7 @@ bool ImageManager::file_load_float_image(Image *img, device_vector<float4>& tex_
}
else if(components == 2) {
/* grayscale + alpha */
- for(int i = width*height*depth-1; i >= 0; i--) {
+ for(size_t i = num_pixels-1, pixel = 0; pixel < num_pixels; pixel++, i--) {
pixels[i*4+3] = pixels[i*2+1];
pixels[i*4+2] = pixels[i*2+0];
pixels[i*4+1] = pixels[i*2+0];
@@ -578,7 +636,7 @@ bool ImageManager::file_load_float_image(Image *img, device_vector<float4>& tex_
}
else if(components == 3) {
/* RGB */
- for(int i = width*height*depth-1; i >= 0; i--) {
+ for(size_t i = num_pixels-1, pixel = 0; pixel < num_pixels; pixel++, i--) {
pixels[i*4+3] = 1.0f;
pixels[i*4+2] = pixels[i*3+2];
pixels[i*4+1] = pixels[i*3+1];
@@ -587,7 +645,7 @@ bool ImageManager::file_load_float_image(Image *img, device_vector<float4>& tex_
}
else if(components == 1) {
/* grayscale */
- for(int i = width*height*depth-1; i >= 0; i--) {
+ for(size_t i = num_pixels-1, pixel = 0; pixel < num_pixels; pixel++, i--) {
pixels[i*4+3] = 1.0f;
pixels[i*4+2] = pixels[i];
pixels[i*4+1] = pixels[i];
@@ -596,7 +654,7 @@ bool ImageManager::file_load_float_image(Image *img, device_vector<float4>& tex_
}
if(img->use_alpha == false) {
- for(int i = width*height*depth-1; i >= 0; i--) {
+ for(size_t i = num_pixels-1, pixel = 0; pixel < num_pixels; pixel++, i--) {
pixels[i*4+3] = 1.0f;
}
}
@@ -653,7 +711,10 @@ void ImageManager::device_load_image(Device *device, DeviceScene *dscene, int sl
if(!pack_images) {
thread_scoped_lock device_lock(device_mutex);
- device->tex_alloc(name.c_str(), tex_img, img->interpolation, true);
+ device->tex_alloc(name.c_str(),
+ tex_img,
+ img->interpolation,
+ img->extension);
}
}
else {
@@ -685,7 +746,10 @@ void ImageManager::device_load_image(Device *device, DeviceScene *dscene, int sl
if(!pack_images) {
thread_scoped_lock device_lock(device_mutex);
- device->tex_alloc(name.c_str(), tex_img, img->interpolation, true);
+ device->tex_alloc(name.c_str(),
+ tex_img,
+ img->interpolation,
+ img->extension);
}
}
@@ -783,7 +847,36 @@ void ImageManager::device_update(Device *device, DeviceScene *dscene, Progress&
need_update = false;
}
-void ImageManager::device_pack_images(Device *device, DeviceScene *dscene, Progress& progess)
+void ImageManager::device_update_slot(Device *device,
+ DeviceScene *dscene,
+ int slot,
+ Progress *progress)
+{
+ Image *image;
+ if(slot >= tex_image_byte_start) {
+ int byte_slot = slot - tex_image_byte_start;
+ assert(images[byte_slot] != NULL);
+ image = images[byte_slot];
+ }
+ else {
+ assert(float_images[slot] != NULL);
+ image = float_images[slot];
+ }
+ if(image->users == 0) {
+ device_free_image(device, dscene, slot);
+ }
+ else if(image->need_load) {
+ if(!osl_texture_system || float_images[slot]->builtin_data)
+ device_load_image(device,
+ dscene,
+ slot,
+ progress);
+ }
+}
+
+void ImageManager::device_pack_images(Device *device,
+ DeviceScene *dscene,
+ Progress& /*progess*/)
{
/* for OpenCL, we pack all image textures inside a single big texture, and
* will do our own interpolation in the kernel */
diff --git a/intern/cycles/render/image.h b/intern/cycles/render/image.h
index 535f0ff156d..bcc58ae951b 100644
--- a/intern/cycles/render/image.h
+++ b/intern/cycles/render/image.h
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#ifndef __IMAGE_H__
@@ -55,14 +55,28 @@ public:
ImageManager();
~ImageManager();
- int add_image(const string& filename, void *builtin_data, bool animated, float frame,
- bool& is_float, bool& is_linear, InterpolationType interpolation, bool use_alpha);
+ int add_image(const string& filename,
+ void *builtin_data,
+ bool animated,
+ float frame,
+ bool& is_float,
+ bool& is_linear,
+ InterpolationType interpolation,
+ ExtensionType extension,
+ bool use_alpha);
void remove_image(int slot);
- void remove_image(const string& filename, void *builtin_data, InterpolationType interpolation);
- void tag_reload_image(const string& filename, void *builtin_data, InterpolationType interpolation);
+ void remove_image(const string& filename,
+ void *builtin_data,
+ InterpolationType interpolation,
+ ExtensionType extension);
+ void tag_reload_image(const string& filename,
+ void *builtin_data,
+ InterpolationType interpolation,
+ ExtensionType extension);
bool is_float_image(const string& filename, void *builtin_data, bool& is_linear);
void device_update(Device *device, DeviceScene *dscene, Progress& progress);
+ void device_update_slot(Device *device, DeviceScene *dscene, int slot, Progress *progress);
void device_free(Device *device, DeviceScene *dscene);
void device_free_builtin(Device *device, DeviceScene *dscene);
@@ -73,9 +87,9 @@ public:
bool need_update;
- boost::function<void(const string &filename, void *data, bool &is_float, int &width, int &height, int &depth, int &channels)> builtin_image_info_cb;
- boost::function<bool(const string &filename, void *data, unsigned char *pixels)> builtin_image_pixels_cb;
- boost::function<bool(const string &filename, void *data, float *pixels)> builtin_image_float_pixels_cb;
+ function<void(const string &filename, void *data, bool &is_float, int &width, int &height, int &depth, int &channels)> builtin_image_info_cb;
+ function<bool(const string &filename, void *data, unsigned char *pixels)> builtin_image_pixels_cb;
+ function<bool(const string &filename, void *data, float *pixels)> builtin_image_float_pixels_cb;
struct Image {
string filename;
@@ -86,6 +100,7 @@ public:
bool animated;
float frame;
InterpolationType interpolation;
+ ExtensionType extension;
int users;
};
diff --git a/intern/cycles/render/integrator.cpp b/intern/cycles/render/integrator.cpp
index 03a8cd5d2d3..9f8d5b50ccd 100644
--- a/intern/cycles/render/integrator.cpp
+++ b/intern/cycles/render/integrator.cpp
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#include "device.h"
@@ -39,7 +39,6 @@ Integrator::Integrator()
transparent_max_bounce = max_bounce;
transparent_shadows = false;
- volume_homogeneous_sampling = 0;
volume_max_steps = 1024;
volume_step_size = 0.1f;
@@ -60,6 +59,10 @@ Integrator::Integrator()
mesh_light_samples = 1;
subsurface_samples = 1;
volume_samples = 1;
+
+ sample_all_lights_direct = true;
+ sample_all_lights_indirect = true;
+
method = PATH;
sampling_pattern = SAMPLING_PATTERN_SOBOL;
@@ -97,6 +100,7 @@ void Integrator::device_update(Device *device, DeviceScene *dscene, Scene *scene
* transparent shaders in the scene. Otherwise we can disable it
* to improve performance a bit. */
if(transparent_shadows) {
+ kintegrator->transparent_shadows = false;
foreach(Shader *shader, scene->shaders) {
/* keep this in sync with SD_HAS_TRANSPARENT_SHADOW in shader.cpp */
if((shader->has_surface_transparent && shader->use_transparent_shadow) || shader->has_volume) {
@@ -189,7 +193,6 @@ bool Integrator::modified(const Integrator& integrator)
transparent_min_bounce == integrator.transparent_min_bounce &&
transparent_max_bounce == integrator.transparent_max_bounce &&
transparent_shadows == integrator.transparent_shadows &&
- volume_homogeneous_sampling == integrator.volume_homogeneous_sampling &&
volume_max_steps == integrator.volume_max_steps &&
volume_step_size == integrator.volume_step_size &&
caustics_reflective == integrator.caustics_reflective &&
@@ -214,7 +217,7 @@ bool Integrator::modified(const Integrator& integrator)
sample_all_lights_indirect == integrator.sample_all_lights_indirect);
}
-void Integrator::tag_update(Scene *scene)
+void Integrator::tag_update(Scene * /*scene*/)
{
need_update = true;
}
diff --git a/intern/cycles/render/integrator.h b/intern/cycles/render/integrator.h
index 13c10e8ca94..fd2ad14488d 100644
--- a/intern/cycles/render/integrator.h
+++ b/intern/cycles/render/integrator.h
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#ifndef __INTEGRATOR_H__
@@ -39,7 +39,6 @@ public:
int transparent_max_bounce;
bool transparent_shadows;
- int volume_homogeneous_sampling;
int volume_max_steps;
float volume_step_size;
diff --git a/intern/cycles/render/light.cpp b/intern/cycles/render/light.cpp
index 1f006637e67..4e962616263 100644
--- a/intern/cycles/render/light.cpp
+++ b/intern/cycles/render/light.cpp
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#include "background.h"
@@ -26,6 +26,7 @@
#include "util_foreach.h"
#include "util_progress.h"
+#include "util_logging.h"
CCL_NAMESPACE_BEGIN
@@ -82,6 +83,8 @@ static void shade_background_pixels(Device *device, DeviceScene *dscene, int res
device->mem_free(d_input);
device->mem_free(d_output);
+ d_input.clear();
+
float4 *d_output_data = reinterpret_cast<float4*>(d_output.data_pointer);
pixels.resize(width*height);
@@ -125,6 +128,9 @@ Light::Light()
shader = 0;
samples = 1;
+ max_bounces = 1024;
+
+ is_portal = false;
}
void Light::tag_update(Scene *scene)
@@ -132,6 +138,17 @@ void Light::tag_update(Scene *scene)
scene->light_manager->need_update = true;
}
+bool Light::has_contribution(Scene *scene)
+{
+ if(is_portal) {
+ return false;
+ }
+ if(type == LIGHT_BACKGROUND) {
+ return true;
+ }
+ return scene->shaders[shader]->has_surface_emission;
+}
+
/* Light Manager */
LightManager::LightManager()
@@ -149,10 +166,17 @@ void LightManager::device_update_distribution(Device *device, DeviceScene *dscen
progress.set_status("Updating Lights", "Computing distribution");
/* count */
- size_t num_lights = scene->lights.size();
+ size_t num_lights = 0;
size_t num_background_lights = 0;
size_t num_triangles = 0;
+ bool background_mis = false;
+
+ foreach(Light *light, scene->lights) {
+ if(light->has_contribution(scene))
+ num_lights++;
+ }
+
foreach(Object *object, scene->objects) {
Mesh *mesh = object->mesh;
bool have_emission = false;
@@ -283,22 +307,29 @@ void LightManager::device_update_distribution(Device *device, DeviceScene *dscen
float trianglearea = totarea;
/* point lights */
- float lightarea = (totarea > 0.0f)? totarea/scene->lights.size(): 1.0f;
+ float lightarea = (totarea > 0.0f) ? totarea / num_lights : 1.0f;
bool use_lamp_mis = false;
- for(int i = 0; i < scene->lights.size(); i++, offset++) {
- Light *light = scene->lights[i];
+ int light_index = 0;
+ foreach(Light *light, scene->lights) {
+ if(!light->has_contribution(scene))
+ continue;
distribution[offset].x = totarea;
- distribution[offset].y = __int_as_float(~(int)i);
+ distribution[offset].y = __int_as_float(~light_index);
distribution[offset].z = 1.0f;
distribution[offset].w = light->size;
totarea += lightarea;
if(light->size > 0.0f && light->use_mis)
use_lamp_mis = true;
- if(light->type == LIGHT_BACKGROUND)
+ if(light->type == LIGHT_BACKGROUND) {
num_background_lights++;
+ background_mis = light->use_mis;
+ }
+
+ light_index++;
+ offset++;
}
/* normalize cumulative distribution functions */
@@ -360,6 +391,18 @@ void LightManager::device_update_distribution(Device *device, DeviceScene *dscen
/* CDF */
device->tex_alloc("__light_distribution", dscene->light_distribution);
+
+ /* Portals */
+ if(num_background_lights > 0 && light_index != scene->lights.size()) {
+ kintegrator->portal_offset = light_index;
+ kintegrator->num_portals = scene->lights.size() - light_index;
+ kintegrator->portal_pdf = background_mis? 0.5f: 1.0f;
+ }
+ else {
+ kintegrator->num_portals = 0;
+ kintegrator->portal_offset = 0;
+ kintegrator->portal_pdf = 0.0f;
+ }
}
else {
dscene->light_distribution.clear();
@@ -370,10 +413,53 @@ void LightManager::device_update_distribution(Device *device, DeviceScene *dscen
kintegrator->pdf_lights = 0.0f;
kintegrator->inv_pdf_lights = 0.0f;
kintegrator->use_lamp_mis = false;
+ kintegrator->num_portals = 0;
+ kintegrator->portal_offset = 0;
+ kintegrator->portal_pdf = 0.0f;
+
kfilm->pass_shadow_scale = 1.0f;
}
}
+static void background_cdf(int start,
+ int end,
+ int res,
+ int cdf_count,
+ const vector<float3> *pixels,
+ float2 *cond_cdf)
+{
+ /* Conditional CDFs (rows, U direction). */
+ for(int i = start; i < end; i++) {
+ float sin_theta = sinf(M_PI_F * (i + 0.5f) / res);
+ float3 env_color = (*pixels)[i * res];
+ float ave_luminance = average(env_color);
+
+ cond_cdf[i * cdf_count].x = ave_luminance * sin_theta;
+ cond_cdf[i * cdf_count].y = 0.0f;
+
+ for(int j = 1; j < res; j++) {
+ env_color = (*pixels)[i * res + j];
+ ave_luminance = average(env_color);
+
+ cond_cdf[i * cdf_count + j].x = ave_luminance * sin_theta;
+ cond_cdf[i * cdf_count + j].y = cond_cdf[i * cdf_count + j - 1].y + cond_cdf[i * cdf_count + j - 1].x / res;
+ }
+
+ float cdf_total = cond_cdf[i * cdf_count + res - 1].y + cond_cdf[i * cdf_count + res - 1].x / res;
+ float cdf_total_inv = 1.0f / cdf_total;
+
+ /* stuff the total into the brightness value for the last entry, because
+ * we are going to normalize the CDFs to 0.0 to 1.0 afterwards */
+ cond_cdf[i * cdf_count + res].x = cdf_total;
+
+ if(cdf_total > 0.0f)
+ for(int j = 1; j < res; j++)
+ cond_cdf[i * cdf_count + j].y *= cdf_total_inv;
+
+ cond_cdf[i * cdf_count + res].y = 1.0f;
+ }
+}
+
void LightManager::device_update_background(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress)
{
KernelIntegrator *kintegrator = &dscene->data.integrator;
@@ -414,34 +500,30 @@ void LightManager::device_update_background(Device *device, DeviceScene *dscene,
float2 *marg_cdf = dscene->light_background_marginal_cdf.resize(cdf_count);
float2 *cond_cdf = dscene->light_background_conditional_cdf.resize(cdf_count * cdf_count);
- /* conditional CDFs (rows, U direction) */
- for(int i = 0; i < res; i++) {
- float sin_theta = sinf(M_PI_F * (i + 0.5f) / res);
- float3 env_color = pixels[i * res];
- float ave_luminamce = average(env_color);
-
- cond_cdf[i * cdf_count].x = ave_luminamce * sin_theta;
- cond_cdf[i * cdf_count].y = 0.0f;
-
- for(int j = 1; j < res; j++) {
- env_color = pixels[i * res + j];
- ave_luminamce = average(env_color);
-
- cond_cdf[i * cdf_count + j].x = ave_luminamce * sin_theta;
- cond_cdf[i * cdf_count + j].y = cond_cdf[i * cdf_count + j - 1].y + cond_cdf[i * cdf_count + j - 1].x / res;
+ double time_start = time_dt();
+ if(res < 512) {
+ /* Small enough resolution, faster to do single-threaded. */
+ background_cdf(0, res, res, cdf_count, &pixels, cond_cdf);
+ }
+ else {
+ /* Threaded evaluation for large resolution. */
+ const int num_blocks = TaskScheduler::num_threads();
+ const int chunk_size = res / num_blocks;
+ int start_row = 0;
+ TaskPool pool;
+ for(int i = 0; i < num_blocks; ++i) {
+ const int current_chunk_size =
+ (i != num_blocks - 1) ? chunk_size
+ : (res - i * chunk_size);
+ pool.push(function_bind(&background_cdf,
+ start_row, start_row + current_chunk_size,
+ res,
+ cdf_count,
+ &pixels,
+ cond_cdf));
+ start_row += current_chunk_size;
}
-
- float cdf_total = cond_cdf[i * cdf_count + res - 1].y + cond_cdf[i * cdf_count + res - 1].x / res;
-
- /* stuff the total into the brightness value for the last entry, because
- * we are going to normalize the CDFs to 0.0 to 1.0 afterwards */
- cond_cdf[i * cdf_count + res].x = cdf_total;
-
- if(cdf_total > 0.0f)
- for(int j = 1; j < res; j++)
- cond_cdf[i * cdf_count + j].y /= cdf_total;
-
- cond_cdf[i * cdf_count + res].y = 1.0f;
+ pool.wait_work();
}
/* marginal CDFs (column, V direction, sum of rows) */
@@ -462,6 +544,8 @@ void LightManager::device_update_background(Device *device, DeviceScene *dscene,
marg_cdf[res].y = 1.0f;
+ VLOG(2) << "Background MIS build time " << time_dt() - time_start << "\n";
+
/* update device */
device->tex_alloc("__light_background_marginal_cdf", dscene->light_background_marginal_cdf);
device->tex_alloc("__light_background_conditional_cdf", dscene->light_background_conditional_cdf);
@@ -472,10 +556,8 @@ void LightManager::device_update_points(Device *device, DeviceScene *dscene, Sce
if(scene->lights.size() == 0)
return;
- float4 *light_data = dscene->light_data.resize(scene->lights.size()*LIGHT_SIZE);
-
- if(!device->info.advanced_shading) {
- /* remove unsupported light */
+ /* remove background light? */
+ if(!(device->info.advanced_shading)) {
foreach(Light *light, scene->lights) {
if(light->type == LIGHT_BACKGROUND) {
scene->lights.erase(std::remove(scene->lights.begin(), scene->lights.end(), light), scene->lights.end());
@@ -484,11 +566,18 @@ void LightManager::device_update_points(Device *device, DeviceScene *dscene, Sce
}
}
- for(size_t i = 0; i < scene->lights.size(); i++) {
- Light *light = scene->lights[i];
+ float4 *light_data = dscene->light_data.resize(scene->lights.size()*LIGHT_SIZE);
+ int light_index = 0;
+
+ foreach(Light *light, scene->lights) {
+ if(!light->has_contribution(scene)) {
+ continue;
+ }
+
float3 co = light->co;
- int shader_id = scene->shader_manager->get_shader_id(scene->lights[i]->shader);
+ int shader_id = scene->shader_manager->get_shader_id(light->shader);
float samples = __int_as_float(light->samples);
+ float max_bounces = __int_as_float(light->max_bounces);
if(!light->cast_shadow)
shader_id &= ~SHADER_CAST_SHADOW;
@@ -519,10 +608,11 @@ void LightManager::device_update_points(Device *device, DeviceScene *dscene, Sce
if(light->use_mis && radius > 0.0f)
shader_id |= SHADER_USE_MIS;
- light_data[i*LIGHT_SIZE + 0] = make_float4(__int_as_float(light->type), co.x, co.y, co.z);
- light_data[i*LIGHT_SIZE + 1] = make_float4(__int_as_float(shader_id), radius, invarea, 0.0f);
- light_data[i*LIGHT_SIZE + 2] = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
- light_data[i*LIGHT_SIZE + 3] = make_float4(samples, 0.0f, 0.0f, 0.0f);
+ light_data[light_index*LIGHT_SIZE + 0] = make_float4(__int_as_float(light->type), co.x, co.y, co.z);
+ light_data[light_index*LIGHT_SIZE + 1] = make_float4(__int_as_float(shader_id), radius, invarea, 0.0f);
+ light_data[light_index*LIGHT_SIZE + 2] = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
+ light_data[light_index*LIGHT_SIZE + 3] = make_float4(samples, 0.0f, 0.0f, 0.0f);
+ light_data[light_index*LIGHT_SIZE + 4] = make_float4(max_bounces, 0.0f, 0.0f, 0.0f);
}
else if(light->type == LIGHT_DISTANT) {
shader_id &= ~SHADER_AREA_LIGHT;
@@ -533,17 +623,17 @@ void LightManager::device_update_points(Device *device, DeviceScene *dscene, Sce
float area = M_PI_F*radius*radius;
float invarea = (area > 0.0f)? 1.0f/area: 1.0f;
float3 dir = light->dir;
-
- if(len(dir) > 0.0f)
- dir = normalize(dir);
+
+ dir = safe_normalize(dir);
if(light->use_mis && area > 0.0f)
shader_id |= SHADER_USE_MIS;
- light_data[i*LIGHT_SIZE + 0] = make_float4(__int_as_float(light->type), dir.x, dir.y, dir.z);
- light_data[i*LIGHT_SIZE + 1] = make_float4(__int_as_float(shader_id), radius, cosangle, invarea);
- light_data[i*LIGHT_SIZE + 2] = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
- light_data[i*LIGHT_SIZE + 3] = make_float4(samples, 0.0f, 0.0f, 0.0f);
+ light_data[light_index*LIGHT_SIZE + 0] = make_float4(__int_as_float(light->type), dir.x, dir.y, dir.z);
+ light_data[light_index*LIGHT_SIZE + 1] = make_float4(__int_as_float(shader_id), radius, cosangle, invarea);
+ light_data[light_index*LIGHT_SIZE + 2] = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
+ light_data[light_index*LIGHT_SIZE + 3] = make_float4(samples, 0.0f, 0.0f, 0.0f);
+ light_data[light_index*LIGHT_SIZE + 4] = make_float4(max_bounces, 0.0f, 0.0f, 0.0f);
}
else if(light->type == LIGHT_BACKGROUND) {
uint visibility = scene->background->visibility;
@@ -568,10 +658,11 @@ void LightManager::device_update_points(Device *device, DeviceScene *dscene, Sce
use_light_visibility = true;
}
- light_data[i*LIGHT_SIZE + 0] = make_float4(__int_as_float(light->type), 0.0f, 0.0f, 0.0f);
- light_data[i*LIGHT_SIZE + 1] = make_float4(__int_as_float(shader_id), 0.0f, 0.0f, 0.0f);
- light_data[i*LIGHT_SIZE + 2] = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
- light_data[i*LIGHT_SIZE + 3] = make_float4(samples, 0.0f, 0.0f, 0.0f);
+ light_data[light_index*LIGHT_SIZE + 0] = make_float4(__int_as_float(light->type), 0.0f, 0.0f, 0.0f);
+ light_data[light_index*LIGHT_SIZE + 1] = make_float4(__int_as_float(shader_id), 0.0f, 0.0f, 0.0f);
+ light_data[light_index*LIGHT_SIZE + 2] = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
+ light_data[light_index*LIGHT_SIZE + 3] = make_float4(samples, 0.0f, 0.0f, 0.0f);
+ light_data[light_index*LIGHT_SIZE + 4] = make_float4(max_bounces, 0.0f, 0.0f, 0.0f);
}
else if(light->type == LIGHT_AREA) {
float3 axisu = light->axisu*(light->sizeu*light->size);
@@ -580,16 +671,16 @@ void LightManager::device_update_points(Device *device, DeviceScene *dscene, Sce
float invarea = (area > 0.0f)? 1.0f/area: 1.0f;
float3 dir = light->dir;
- if(len(dir) > 0.0f)
- dir = normalize(dir);
+ dir = safe_normalize(dir);
if(light->use_mis && area > 0.0f)
shader_id |= SHADER_USE_MIS;
- light_data[i*LIGHT_SIZE + 0] = make_float4(__int_as_float(light->type), co.x, co.y, co.z);
- light_data[i*LIGHT_SIZE + 1] = make_float4(__int_as_float(shader_id), axisu.x, axisu.y, axisu.z);
- light_data[i*LIGHT_SIZE + 2] = make_float4(invarea, axisv.x, axisv.y, axisv.z);
- light_data[i*LIGHT_SIZE + 3] = make_float4(samples, dir.x, dir.y, dir.z);
+ light_data[light_index*LIGHT_SIZE + 0] = make_float4(__int_as_float(light->type), co.x, co.y, co.z);
+ light_data[light_index*LIGHT_SIZE + 1] = make_float4(__int_as_float(shader_id), axisu.x, axisu.y, axisu.z);
+ light_data[light_index*LIGHT_SIZE + 2] = make_float4(invarea, axisv.x, axisv.y, axisv.z);
+ light_data[light_index*LIGHT_SIZE + 3] = make_float4(samples, dir.x, dir.y, dir.z);
+ light_data[light_index*LIGHT_SIZE + 4] = make_float4(max_bounces, 0.0f, 0.0f, 0.0f);
}
else if(light->type == LIGHT_SPOT) {
shader_id &= ~SHADER_AREA_LIGHT;
@@ -600,24 +691,57 @@ void LightManager::device_update_points(Device *device, DeviceScene *dscene, Sce
float spot_smooth = (1.0f - spot_angle)*light->spot_smooth;
float3 dir = light->dir;
- if(len(dir) > 0.0f)
- dir = normalize(dir);
+ dir = safe_normalize(dir);
if(light->use_mis && radius > 0.0f)
shader_id |= SHADER_USE_MIS;
- light_data[i*LIGHT_SIZE + 0] = make_float4(__int_as_float(light->type), co.x, co.y, co.z);
- light_data[i*LIGHT_SIZE + 1] = make_float4(__int_as_float(shader_id), radius, invarea, spot_angle);
- light_data[i*LIGHT_SIZE + 2] = make_float4(spot_smooth, dir.x, dir.y, dir.z);
- light_data[i*LIGHT_SIZE + 3] = make_float4(samples, 0.0f, 0.0f, 0.0f);
+ light_data[light_index*LIGHT_SIZE + 0] = make_float4(__int_as_float(light->type), co.x, co.y, co.z);
+ light_data[light_index*LIGHT_SIZE + 1] = make_float4(__int_as_float(shader_id), radius, invarea, spot_angle);
+ light_data[light_index*LIGHT_SIZE + 2] = make_float4(spot_smooth, dir.x, dir.y, dir.z);
+ light_data[light_index*LIGHT_SIZE + 3] = make_float4(samples, 0.0f, 0.0f, 0.0f);
+ light_data[light_index*LIGHT_SIZE + 4] = make_float4(max_bounces, 0.0f, 0.0f, 0.0f);
}
+
+ light_index++;
}
-
+
+ /* TODO(sergey): Consider moving portals update to their own function
+ * keeping this one more manageable.
+ */
+ foreach(Light *light, scene->lights) {
+ if(!light->is_portal)
+ continue;
+ assert(light->type == LIGHT_AREA);
+
+ float3 co = light->co;
+ float3 axisu = light->axisu*(light->sizeu*light->size);
+ float3 axisv = light->axisv*(light->sizev*light->size);
+ float area = len(axisu)*len(axisv);
+ float invarea = (area > 0.0f) ? 1.0f / area : 1.0f;
+ float3 dir = light->dir;
+
+ dir = safe_normalize(dir);
+
+ light_data[light_index*LIGHT_SIZE + 0] = make_float4(__int_as_float(light->type), co.x, co.y, co.z);
+ light_data[light_index*LIGHT_SIZE + 1] = make_float4(area, axisu.x, axisu.y, axisu.z);
+ light_data[light_index*LIGHT_SIZE + 2] = make_float4(invarea, axisv.x, axisv.y, axisv.z);
+ light_data[light_index*LIGHT_SIZE + 3] = make_float4(-1, dir.x, dir.y, dir.z);
+ light_data[light_index*LIGHT_SIZE + 4] = make_float4(-1, 0.0f, 0.0f, 0.0f);
+
+ light_index++;
+ }
+
+ VLOG(1) << "Number of lights without contribution: "
+ << scene->lights.size() - light_index;
+
device->tex_alloc("__light_data", dscene->light_data);
}
void LightManager::device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress)
{
+ VLOG(1) << "Total " << scene->lights.size() << " lights.";
+
if(!need_update)
return;
@@ -655,7 +779,7 @@ void LightManager::device_free(Device *device, DeviceScene *dscene)
dscene->light_background_conditional_cdf.clear();
}
-void LightManager::tag_update(Scene *scene)
+void LightManager::tag_update(Scene * /*scene*/)
{
need_update = true;
}
diff --git a/intern/cycles/render/light.h b/intern/cycles/render/light.h
index 89091bb5f9e..afec3628dda 100644
--- a/intern/cycles/render/light.h
+++ b/intern/cycles/render/light.h
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#ifndef __LIGHT_H__
@@ -56,10 +56,16 @@ public:
bool use_transmission;
bool use_scatter;
+ bool is_portal;
+
int shader;
int samples;
+ int max_bounces;
void tag_update(Scene *scene);
+
+ /* Check whether the light has contribution the the scene. */
+ bool has_contribution(Scene *scene);
};
class LightManager {
diff --git a/intern/cycles/render/mesh.cpp b/intern/cycles/render/mesh.cpp
index 5602609c030..57f194651f8 100644
--- a/intern/cycles/render/mesh.cpp
+++ b/intern/cycles/render/mesh.cpp
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#include "bvh.h"
@@ -20,9 +20,11 @@
#include "camera.h"
#include "curves.h"
#include "device.h"
+#include "graph.h"
#include "shader.h"
#include "light.h"
#include "mesh.h"
+#include "nodes.h"
#include "object.h"
#include "scene.h"
@@ -30,6 +32,7 @@
#include "util_cache.h"
#include "util_foreach.h"
+#include "util_logging.h"
#include "util_progress.h"
#include "util_set.h"
@@ -93,6 +96,8 @@ Mesh::Mesh()
attributes.triangle_mesh = this;
curve_attributes.curve_mesh = this;
+
+ has_volume = false;
}
Mesh::~Mesh()
@@ -132,7 +137,7 @@ void Mesh::clear()
transform_applied = false;
transform_negative_scaled = false;
transform_normal = transform_identity();
- geometry_synced = false;
+ geometry_flags = GEOMETRY_NONE;
}
int Mesh::split_vertex(int vertex)
@@ -207,11 +212,11 @@ void Mesh::compute_bounds()
bnds.grow(float4_to_float3(curve_keys[i]), curve_keys[i].w);
Attribute *attr = attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
- if (use_motion_blur && attr) {
+ if(use_motion_blur && attr) {
size_t steps_size = verts.size() * (motion_steps - 1);
float3 *vert_steps = attr->data_float3();
- for (size_t i = 0; i < steps_size; i++)
+ for(size_t i = 0; i < steps_size; i++)
bnds.grow(vert_steps[i]);
}
@@ -220,7 +225,7 @@ void Mesh::compute_bounds()
size_t steps_size = curve_keys.size() * (motion_steps - 1);
float3 *key_steps = curve_attr->data_float3();
- for (size_t i = 0; i < steps_size; i++)
+ for(size_t i = 0; i < steps_size; i++)
bnds.grow(key_steps[i]);
}
@@ -234,19 +239,19 @@ void Mesh::compute_bounds()
for(size_t i = 0; i < curve_keys_size; i++)
bnds.grow_safe(float4_to_float3(curve_keys[i]), curve_keys[i].w);
- if (use_motion_blur && attr) {
+ if(use_motion_blur && attr) {
size_t steps_size = verts.size() * (motion_steps - 1);
float3 *vert_steps = attr->data_float3();
- for (size_t i = 0; i < steps_size; i++)
+ for(size_t i = 0; i < steps_size; i++)
bnds.grow_safe(vert_steps[i]);
}
- if (use_motion_blur && curve_attr) {
+ if(use_motion_blur && curve_attr) {
size_t steps_size = curve_keys.size() * (motion_steps - 1);
float3 *key_steps = curve_attr->data_float3();
- for (size_t i = 0; i < steps_size; i++)
+ for(size_t i = 0; i < steps_size; i++)
bnds.grow_safe(key_steps[i]);
}
}
@@ -508,7 +513,6 @@ void Mesh::compute_bvh(SceneParams *params, Progress *progress, int n, int total
progress->set_status(msg, "Building BVH");
BVHParams bparams;
- bparams.use_cache = params->use_bvh_cache;
bparams.use_spatial_split = params->use_bvh_spatial_split;
bparams.use_qbvh = params->use_qbvh;
@@ -553,6 +557,7 @@ MeshManager::MeshManager()
{
bvh = NULL;
need_update = true;
+ need_flags_update = true;
}
MeshManager::~MeshManager()
@@ -649,6 +654,10 @@ void MeshManager::update_osl_attributes(Device *device, Scene *scene, vector<Att
}
}
}
+#else
+ (void)device;
+ (void)scene;
+ (void)mesh_attributes;
#endif
}
@@ -746,8 +755,49 @@ void MeshManager::update_svm_attributes(Device *device, DeviceScene *dscene, Sce
device->tex_alloc("__attributes_map", dscene->attributes_map);
}
-static void update_attribute_element_offset(Mesh *mesh, vector<float>& attr_float, vector<float4>& attr_float3, vector<uchar4>& attr_uchar4,
- Attribute *mattr, TypeDesc& type, int& offset, AttributeElement& element)
+static void update_attribute_element_size(Mesh *mesh,
+ Attribute *mattr,
+ size_t *attr_float_size,
+ size_t *attr_float3_size,
+ size_t *attr_uchar4_size)
+{
+ if(mattr) {
+ size_t size = mattr->element_size(
+ mesh->verts.size(),
+ mesh->triangles.size(),
+ mesh->motion_steps,
+ mesh->curves.size(),
+ mesh->curve_keys.size());
+
+ if(mattr->element == ATTR_ELEMENT_VOXEL) {
+ /* pass */
+ }
+ else if(mattr->element == ATTR_ELEMENT_CORNER_BYTE) {
+ *attr_uchar4_size += size;
+ }
+ else if(mattr->type == TypeDesc::TypeFloat) {
+ *attr_float_size += size;
+ }
+ else if(mattr->type == TypeDesc::TypeMatrix) {
+ *attr_float3_size += size * 4;
+ }
+ else {
+ *attr_float3_size += size;
+ }
+ }
+}
+
+static void update_attribute_element_offset(Mesh *mesh,
+ vector<float>& attr_float,
+ size_t& attr_float_offset,
+ vector<float4>& attr_float3,
+ size_t& attr_float3_offset,
+ vector<uchar4>& attr_uchar4,
+ size_t& attr_uchar4_offset,
+ Attribute *mattr,
+ TypeDesc& type,
+ int& offset,
+ AttributeElement& element)
{
if(mattr) {
/* store element and type */
@@ -769,39 +819,43 @@ static void update_attribute_element_offset(Mesh *mesh, vector<float>& attr_floa
}
else if(mattr->element == ATTR_ELEMENT_CORNER_BYTE) {
uchar4 *data = mattr->data_uchar4();
- offset = attr_uchar4.size();
-
- attr_uchar4.resize(attr_uchar4.size() + size);
+ offset = attr_uchar4_offset;
- for(size_t k = 0; k < size; k++)
+ assert(attr_uchar4.capacity() >= offset + size);
+ for(size_t k = 0; k < size; k++) {
attr_uchar4[offset+k] = data[k];
+ }
+ attr_uchar4_offset += size;
}
else if(mattr->type == TypeDesc::TypeFloat) {
float *data = mattr->data_float();
- offset = attr_float.size();
+ offset = attr_float_offset;
- attr_float.resize(attr_float.size() + size);
-
- for(size_t k = 0; k < size; k++)
+ assert(attr_float.capacity() >= offset + size);
+ for(size_t k = 0; k < size; k++) {
attr_float[offset+k] = data[k];
+ }
+ attr_float_offset += size;
}
else if(mattr->type == TypeDesc::TypeMatrix) {
Transform *tfm = mattr->data_transform();
- offset = attr_float3.size();
-
- attr_float3.resize(attr_float3.size() + size*4);
+ offset = attr_float3_offset;
- for(size_t k = 0; k < size*4; k++)
+ assert(attr_float3.capacity() >= offset + size * 4);
+ for(size_t k = 0; k < size*4; k++) {
attr_float3[offset+k] = (&tfm->x)[k];
+ }
+ attr_float3_offset += size * 4;
}
else {
float4 *data = mattr->data_float4();
- offset = attr_float3.size();
-
- attr_float3.resize(attr_float3.size() + size);
+ offset = attr_float3_offset;
- for(size_t k = 0; k < size; k++)
+ assert(attr_float3.capacity() >= offset + size);
+ for(size_t k = 0; k < size; k++) {
attr_float3[offset+k] = data[k];
+ }
+ attr_float3_offset += size;
}
/* mesh vertex/curve index is global, not per object, so we sneak
@@ -851,16 +905,16 @@ void MeshManager::device_update_attributes(Device *device, DeviceScene *dscene,
/* mesh attribute are stored in a single array per data type. here we fill
* those arrays, and set the offset and element type to create attribute
* maps next */
- vector<float> attr_float;
- vector<float4> attr_float3;
- vector<uchar4> attr_uchar4;
+ /* Pre-allocate attributes to avoid arrays re-allocation which would
+ * take 2x of overall attribute memory usage.
+ */
+ size_t attr_float_size = 0;
+ size_t attr_float3_size = 0;
+ size_t attr_uchar4_size = 0;
for(size_t i = 0; i < scene->meshes.size(); i++) {
Mesh *mesh = scene->meshes[i];
AttributeRequestSet& attributes = mesh_attributes[i];
-
- /* todo: we now store std and name attributes from requests even if
- * they actually refer to the same mesh attributes, optimize */
foreach(AttributeRequest& req, attributes.requests) {
Attribute *triangle_mattr = mesh->attributes.find(req);
Attribute *curve_mattr = mesh->curve_attributes.find(req);
@@ -874,12 +928,56 @@ void MeshManager::device_update_attributes(Device *device, DeviceScene *dscene,
memcpy(triangle_mattr->data_float3(), &mesh->verts[0], sizeof(float3)*mesh->verts.size());
}
- update_attribute_element_offset(mesh, attr_float, attr_float3, attr_uchar4, triangle_mattr,
- req.triangle_type, req.triangle_offset, req.triangle_element);
+ update_attribute_element_size(mesh,
+ triangle_mattr,
+ &attr_float_size,
+ &attr_float3_size,
+ &attr_uchar4_size);
+ update_attribute_element_size(mesh,
+ curve_mattr,
+ &attr_float_size,
+ &attr_float3_size,
+ &attr_uchar4_size);
+ }
+ }
+
+ vector<float> attr_float(attr_float_size);
+ vector<float4> attr_float3(attr_float3_size);
+ vector<uchar4> attr_uchar4(attr_uchar4_size);
+
+ size_t attr_float_offset = 0;
+ size_t attr_float3_offset = 0;
+ size_t attr_uchar4_offset = 0;
+
+ /* Fill in attributes. */
+ for(size_t i = 0; i < scene->meshes.size(); i++) {
+ Mesh *mesh = scene->meshes[i];
+ AttributeRequestSet& attributes = mesh_attributes[i];
+
+ /* todo: we now store std and name attributes from requests even if
+ * they actually refer to the same mesh attributes, optimize */
+ foreach(AttributeRequest& req, attributes.requests) {
+ Attribute *triangle_mattr = mesh->attributes.find(req);
+ Attribute *curve_mattr = mesh->curve_attributes.find(req);
+
+ update_attribute_element_offset(mesh,
+ attr_float, attr_float_offset,
+ attr_float3, attr_float3_offset,
+ attr_uchar4, attr_uchar4_offset,
+ triangle_mattr,
+ req.triangle_type,
+ req.triangle_offset,
+ req.triangle_element);
+
+ update_attribute_element_offset(mesh,
+ attr_float, attr_float_offset,
+ attr_float3, attr_float3_offset,
+ attr_uchar4, attr_uchar4_offset,
+ curve_mattr,
+ req.curve_type,
+ req.curve_offset,
+ req.curve_element);
- update_attribute_element_offset(mesh, attr_float, attr_float3, attr_uchar4, curve_mattr,
- req.curve_type, req.curve_offset, req.curve_element);
-
if(progress.get_cancel()) return;
}
}
@@ -978,11 +1076,13 @@ void MeshManager::device_update_bvh(Device *device, DeviceScene *dscene, Scene *
/* bvh build */
progress.set_status("Updating Scene BVH", "Building");
+ VLOG(1) << (scene->params.use_qbvh ? "Using QBVH optimization structure"
+ : "Using regular BVH optimization structure");
+
BVHParams bparams;
bparams.top_level = true;
bparams.use_qbvh = scene->params.use_qbvh;
bparams.use_spatial_split = scene->params.use_bvh_spatial_split;
- bparams.use_cache = scene->params.use_bvh_cache;
delete bvh;
bvh = BVH::create(bparams, scene->objects);
@@ -999,6 +1099,10 @@ void MeshManager::device_update_bvh(Device *device, DeviceScene *dscene, Scene *
dscene->bvh_nodes.reference((float4*)&pack.nodes[0], pack.nodes.size());
device->tex_alloc("__bvh_nodes", dscene->bvh_nodes);
}
+ if(pack.leaf_nodes.size()) {
+ dscene->bvh_leaf_nodes.reference((float4*)&pack.leaf_nodes[0], pack.leaf_nodes.size());
+ device->tex_alloc("__bvh_leaf_nodes", dscene->bvh_leaf_nodes);
+ }
if(pack.object_node.size()) {
dscene->object_node.reference((uint*)&pack.object_node[0], pack.object_node.size());
device->tex_alloc("__object_node", dscene->object_node);
@@ -1025,18 +1129,91 @@ void MeshManager::device_update_bvh(Device *device, DeviceScene *dscene, Scene *
}
dscene->data.bvh.root = pack.root_index;
+ dscene->data.bvh.use_qbvh = scene->params.use_qbvh;
+}
+
+void MeshManager::device_update_flags(Device * /*device*/,
+ DeviceScene * /*dscene*/,
+ Scene * scene,
+ Progress& /*progress*/)
+{
+ if(!need_update && !need_flags_update) {
+ return;
+ }
+ /* update flags */
+ foreach(Mesh *mesh, scene->meshes) {
+ mesh->has_volume = false;
+ foreach(uint shader, mesh->used_shaders) {
+ if(scene->shaders[shader]->has_volume) {
+ mesh->has_volume = true;
+ }
+ }
+ }
+ need_flags_update = false;
+}
+
+void MeshManager::device_update_displacement_images(Device *device,
+ DeviceScene *dscene,
+ Scene *scene,
+ Progress& progress)
+{
+ progress.set_status("Updating Displacement Images");
+ TaskPool pool;
+ ImageManager *image_manager = scene->image_manager;
+ set<int> bump_images;
+ foreach(Mesh *mesh, scene->meshes) {
+ if(mesh->need_update) {
+ foreach(uint shader_index, mesh->used_shaders) {
+ Shader *shader = scene->shaders[shader_index];
+ if(shader->graph_bump == NULL) {
+ continue;
+ }
+ foreach(ShaderNode* node, shader->graph_bump->nodes) {
+ if(node->special_type != SHADER_SPECIAL_TYPE_IMAGE_SLOT) {
+ continue;
+ }
+ if(device->info.pack_images) {
+ /* If device requires packed images we need to update all
+ * images now, even if they're not used for displacement.
+ */
+ image_manager->device_update(device,
+ dscene,
+ progress);
+ return;
+ }
+ ImageSlotNode *image_node = static_cast<ImageSlotNode*>(node);
+ int slot = image_node->slot;
+ if(slot != -1) {
+ bump_images.insert(slot);
+ }
+ }
+ }
+ }
+ }
+ foreach(int slot, bump_images) {
+ pool.push(function_bind(&ImageManager::device_update_slot,
+ image_manager,
+ device,
+ dscene,
+ slot,
+ &progress));
+ }
+ pool.wait_work();
}
void MeshManager::device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress)
{
+ VLOG(1) << "Total " << scene->meshes.size() << " meshes.";
+
if(!need_update)
return;
/* update normals */
foreach(Mesh *mesh, scene->meshes) {
- foreach(uint shader, mesh->used_shaders)
+ foreach(uint shader, mesh->used_shaders) {
if(scene->shaders[shader]->need_update_attributes)
mesh->need_update = true;
+ }
if(mesh->need_update) {
mesh->add_face_normals();
@@ -1046,6 +1223,28 @@ void MeshManager::device_update(Device *device, DeviceScene *dscene, Scene *scen
}
}
+ /* Update images needed for true displacement. */
+ bool need_displacement_images = false;
+ bool old_need_object_flags_update = false;
+ foreach(Mesh *mesh, scene->meshes) {
+ if(mesh->need_update &&
+ mesh->displacement_method != Mesh::DISPLACE_BUMP)
+ {
+ need_displacement_images = true;
+ break;
+ }
+ }
+ if(need_displacement_images) {
+ VLOG(1) << "Updating images used for true displacement.";
+ device_update_displacement_images(device, dscene, scene, progress);
+ old_need_object_flags_update = scene->object_manager->need_flags_update;
+ scene->object_manager->device_update_flags(device,
+ dscene,
+ scene,
+ progress,
+ false);
+ }
+
/* device update */
device_free(device, dscene);
@@ -1087,13 +1286,19 @@ void MeshManager::device_update(Device *device, DeviceScene *dscene, Scene *scen
foreach(Mesh *mesh, scene->meshes) {
if(mesh->need_update) {
- pool.push(function_bind(&Mesh::compute_bvh, mesh, &scene->params, &progress, i, num_bvh));
- i++;
+ pool.push(function_bind(&Mesh::compute_bvh,
+ mesh,
+ &scene->params,
+ &progress,
+ i,
+ num_bvh));
+ if(!mesh->transform_applied) {
+ i++;
+ }
}
}
pool.wait_work();
-
foreach(Shader *shader, scene->shaders)
shader->need_update_attributes = false;
@@ -1104,6 +1309,8 @@ void MeshManager::device_update(Device *device, DeviceScene *dscene, Scene *scen
bool motion_blur = false;
#endif
+ /* update obejcts */
+ vector<Object *> volume_objects;
foreach(Object *object, scene->objects)
object->compute_bounds(motion_blur);
@@ -1112,11 +1319,22 @@ void MeshManager::device_update(Device *device, DeviceScene *dscene, Scene *scen
device_update_bvh(device, dscene, scene, progress);
need_update = false;
+
+ if(need_displacement_images) {
+ /* Re-tag flags for update, so they're re-evaluated
+ * for meshes with correct bounding boxes.
+ *
+ * This wouldn't cause wrong results, just true
+ * displacement might be less optimal ot calculate.
+ */
+ scene->object_manager->need_flags_update = old_need_object_flags_update;
+ }
}
void MeshManager::device_free(Device *device, DeviceScene *dscene)
{
device->tex_free(dscene->bvh_nodes);
+ device->tex_free(dscene->bvh_leaf_nodes);
device->tex_free(dscene->object_node);
device->tex_free(dscene->tri_woop);
device->tex_free(dscene->prim_type);
diff --git a/intern/cycles/render/mesh.h b/intern/cycles/render/mesh.h
index 28cee5745ea..76c186a3feb 100644
--- a/intern/cycles/render/mesh.h
+++ b/intern/cycles/render/mesh.h
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#ifndef __MESH_H__
@@ -71,14 +71,21 @@ public:
ustring name;
/* Mesh Data */
- bool geometry_synced; /* used to distinguish meshes with no verts
- and meshed for which geometry is not created */
+ enum GeometryFlags {
+ GEOMETRY_NONE = 0,
+ GEOMETRY_TRIANGLES = (1 << 0),
+ GEOMETRY_CURVES = (1 << 1),
+ };
+ int geometry_flags; /* used to distinguish meshes with no verts
+ and meshed for which geometry is not created */
vector<float3> verts;
vector<Triangle> triangles;
vector<uint> shader;
vector<bool> smooth;
+ bool has_volume; /* Set in the device_update_flags(). */
+
vector<float4> curve_keys; /* co + radius */
vector<Curve> curves;
@@ -143,6 +150,7 @@ public:
BVH *bvh;
bool need_update;
+ bool need_flags_update;
MeshManager();
~MeshManager();
@@ -158,6 +166,8 @@ public:
void device_update_mesh(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress);
void device_update_attributes(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress);
void device_update_bvh(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress);
+ void device_update_flags(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress);
+ void device_update_displacement_images(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress);
void device_free(Device *device, DeviceScene *dscene);
void tag_update(Scene *scene);
diff --git a/intern/cycles/render/mesh_displace.cpp b/intern/cycles/render/mesh_displace.cpp
index 4c0ee76299c..1ba0c7f7291 100644
--- a/intern/cycles/render/mesh_displace.cpp
+++ b/intern/cycles/render/mesh_displace.cpp
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#include "device.h"
diff --git a/intern/cycles/render/nodes.cpp b/intern/cycles/render/nodes.cpp
index e8476bfac4c..7ed07ab6453 100644
--- a/intern/cycles/render/nodes.cpp
+++ b/intern/cycles/render/nodes.cpp
@@ -11,12 +11,13 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#include "image.h"
#include "nodes.h"
#include "svm.h"
+#include "svm_math_util.h"
#include "osl.h"
#include "sky_model.h"
@@ -173,8 +174,10 @@ static ShaderEnum image_projection_init()
{
ShaderEnum enm;
- enm.insert("Flat", 0);
- enm.insert("Box", 1);
+ enm.insert("Flat", NODE_IMAGE_PROJ_FLAT);
+ enm.insert("Box", NODE_IMAGE_PROJ_BOX);
+ enm.insert("Sphere", NODE_IMAGE_PROJ_SPHERE);
+ enm.insert("Tube", NODE_IMAGE_PROJ_TUBE);
return enm;
}
@@ -183,7 +186,7 @@ ShaderEnum ImageTextureNode::color_space_enum = color_space_init();
ShaderEnum ImageTextureNode::projection_enum = image_projection_init();
ImageTextureNode::ImageTextureNode()
-: TextureNode("image_texture")
+: ImageSlotTextureNode("image_texture")
{
image_manager = NULL;
slot = -1;
@@ -195,6 +198,7 @@ ImageTextureNode::ImageTextureNode()
color_space = ustring("Color");
projection = ustring("Flat");
interpolation = INTERPOLATION_LINEAR;
+ extension = EXTENSION_REPEAT;
projection_blend = 0.0f;
animated = false;
@@ -205,8 +209,12 @@ ImageTextureNode::ImageTextureNode()
ImageTextureNode::~ImageTextureNode()
{
- if(image_manager)
- image_manager->remove_image(filename, builtin_data, interpolation);
+ if(image_manager) {
+ image_manager->remove_image(filename,
+ builtin_data,
+ interpolation,
+ extension);
+ }
}
ShaderNode *ImageTextureNode::clone() const
@@ -224,7 +232,7 @@ void ImageTextureNode::attributes(Shader *shader, AttributeRequestSet *attribute
#ifdef WITH_PTEX
/* todo: avoid loading other texture coordinates when using ptex,
* and hide texture coordinate socket in the UI */
- if (shader->has_surface && string_endswith(filename, ".ptx")) {
+ if(shader->has_surface && string_endswith(filename, ".ptx")) {
/* ptex */
attributes->add(ATTR_STD_PTEX_FACE_ID);
attributes->add(ATTR_STD_PTEX_UV);
@@ -243,9 +251,15 @@ void ImageTextureNode::compile(SVMCompiler& compiler)
image_manager = compiler.image_manager;
if(is_float == -1) {
bool is_float_bool;
- slot = image_manager->add_image(filename, builtin_data,
- animated, 0, is_float_bool, is_linear,
- interpolation, use_alpha);
+ slot = image_manager->add_image(filename,
+ builtin_data,
+ animated,
+ 0,
+ is_float_bool,
+ is_linear,
+ interpolation,
+ extension,
+ use_alpha);
is_float = (int)is_float_bool;
}
@@ -265,14 +279,15 @@ void ImageTextureNode::compile(SVMCompiler& compiler)
tex_mapping.compile(compiler, vector_in->stack_offset, vector_offset);
}
- if(projection == "Flat") {
+ if(projection != "Box") {
compiler.add_node(NODE_TEX_IMAGE,
slot,
compiler.encode_uchar4(
vector_offset,
color_out->stack_offset,
alpha_out->stack_offset,
- srgb));
+ srgb),
+ projection_enum[projection]);
}
else {
compiler.add_node(NODE_TEX_IMAGE_BOX,
@@ -284,7 +299,7 @@ void ImageTextureNode::compile(SVMCompiler& compiler)
srgb),
__float_as_int(projection_blend));
}
-
+
if(vector_offset != vector_in->stack_offset)
compiler.stack_clear_offset(vector_in->type, vector_offset);
}
@@ -314,9 +329,15 @@ void ImageTextureNode::compile(OSLCompiler& compiler)
}
else {
bool is_float_bool;
- slot = image_manager->add_image(filename, builtin_data,
- animated, 0, is_float_bool, is_linear,
- interpolation, use_alpha);
+ slot = image_manager->add_image(filename,
+ builtin_data,
+ animated,
+ 0,
+ is_float_bool,
+ is_linear,
+ interpolation,
+ extension,
+ use_alpha);
is_float = (int)is_float_bool;
}
}
@@ -357,6 +378,20 @@ void ImageTextureNode::compile(OSLCompiler& compiler)
compiler.parameter("interpolation", "linear");
break;
}
+
+ switch(extension) {
+ case EXTENSION_EXTEND:
+ compiler.parameter("wrap", "clamp");
+ break;
+ case EXTENSION_CLIP:
+ compiler.parameter("wrap", "black");
+ break;
+ case EXTENSION_REPEAT:
+ default:
+ compiler.parameter("wrap", "periodic");
+ break;
+ }
+
compiler.add(this, "node_image_texture");
}
@@ -376,7 +411,7 @@ ShaderEnum EnvironmentTextureNode::color_space_enum = color_space_init();
ShaderEnum EnvironmentTextureNode::projection_enum = env_projection_init();
EnvironmentTextureNode::EnvironmentTextureNode()
-: TextureNode("environment_texture")
+: ImageSlotTextureNode("environment_texture")
{
image_manager = NULL;
slot = -1;
@@ -396,8 +431,12 @@ EnvironmentTextureNode::EnvironmentTextureNode()
EnvironmentTextureNode::~EnvironmentTextureNode()
{
- if(image_manager)
- image_manager->remove_image(filename, builtin_data, INTERPOLATION_LINEAR);
+ if(image_manager) {
+ image_manager->remove_image(filename,
+ builtin_data,
+ INTERPOLATION_LINEAR,
+ EXTENSION_REPEAT);
+ }
}
ShaderNode *EnvironmentTextureNode::clone() const
@@ -413,7 +452,7 @@ ShaderNode *EnvironmentTextureNode::clone() const
void EnvironmentTextureNode::attributes(Shader *shader, AttributeRequestSet *attributes)
{
#ifdef WITH_PTEX
- if (shader->has_surface && string_endswith(filename, ".ptx")) {
+ if(shader->has_surface && string_endswith(filename, ".ptx")) {
/* ptex */
attributes->add(ATTR_STD_PTEX_FACE_ID);
attributes->add(ATTR_STD_PTEX_UV);
@@ -432,9 +471,15 @@ void EnvironmentTextureNode::compile(SVMCompiler& compiler)
image_manager = compiler.image_manager;
if(slot == -1) {
bool is_float_bool;
- slot = image_manager->add_image(filename, builtin_data,
- animated, 0, is_float_bool, is_linear,
- INTERPOLATION_LINEAR, use_alpha);
+ slot = image_manager->add_image(filename,
+ builtin_data,
+ animated,
+ 0,
+ is_float_bool,
+ is_linear,
+ INTERPOLATION_LINEAR,
+ EXTENSION_REPEAT,
+ use_alpha);
is_float = (int)is_float_bool;
}
@@ -495,9 +540,15 @@ void EnvironmentTextureNode::compile(OSLCompiler& compiler)
}
else {
bool is_float_bool;
- slot = image_manager->add_image(filename, builtin_data,
- animated, 0, is_float_bool, is_linear,
- INTERPOLATION_LINEAR, use_alpha);
+ slot = image_manager->add_image(filename,
+ builtin_data,
+ animated,
+ 0,
+ is_float_bool,
+ is_linear,
+ INTERPOLATION_LINEAR,
+ EXTENSION_REPEAT,
+ use_alpha);
is_float = (int)is_float_bool;
}
}
@@ -628,7 +679,7 @@ static void sky_texture_precompute_new(SunSky *sunsky, float3 dir, float turbidi
sky_state = arhosek_xyz_skymodelstate_alloc_init(turbidity, ground_albedo, solarElevation);
/* Copy values from sky_state to SunSky */
- for (int i = 0; i < 9; ++i) {
+ for(int i = 0; i < 9; ++i) {
sunsky->config_x[i] = (float)sky_state->configs[0][i];
sunsky->config_y[i] = (float)sky_state->configs[1][i];
sunsky->config_z[i] = (float)sky_state->configs[2][i];
@@ -1293,6 +1344,163 @@ void BrickTextureNode::compile(OSLCompiler& compiler)
compiler.add(this, "node_brick_texture");
}
+/* Point Density Texture */
+
+static ShaderEnum point_density_space_init()
+{
+ ShaderEnum enm;
+
+ enm.insert("Object", NODE_TEX_VOXEL_SPACE_OBJECT);
+ enm.insert("World", NODE_TEX_VOXEL_SPACE_WORLD);
+
+ return enm;
+}
+
+ShaderEnum PointDensityTextureNode::space_enum = point_density_space_init();
+
+PointDensityTextureNode::PointDensityTextureNode()
+: ShaderNode("point_density")
+{
+ image_manager = NULL;
+ slot = -1;
+ filename = "";
+ space = ustring("Object");
+ builtin_data = NULL;
+ interpolation = INTERPOLATION_LINEAR;
+
+ tfm = transform_identity();
+
+ add_input("Vector", SHADER_SOCKET_POINT, ShaderInput::POSITION);
+ add_output("Density", SHADER_SOCKET_FLOAT);
+ add_output("Color", SHADER_SOCKET_COLOR);
+}
+
+PointDensityTextureNode::~PointDensityTextureNode()
+{
+ if(image_manager) {
+ image_manager->remove_image(filename,
+ builtin_data,
+ interpolation,
+ EXTENSION_REPEAT);
+ }
+}
+
+ShaderNode *PointDensityTextureNode::clone() const
+{
+ PointDensityTextureNode *node = new PointDensityTextureNode(*this);
+ node->image_manager = NULL;
+ node->slot = -1;
+ return node;
+}
+
+void PointDensityTextureNode::attributes(Shader *shader,
+ AttributeRequestSet *attributes)
+{
+ if(shader->has_volume)
+ attributes->add(ATTR_STD_GENERATED_TRANSFORM);
+
+ ShaderNode::attributes(shader, attributes);
+}
+
+void PointDensityTextureNode::compile(SVMCompiler& compiler)
+{
+ ShaderInput *vector_in = input("Vector");
+ ShaderOutput *density_out = output("Density");
+ ShaderOutput *color_out = output("Color");
+
+ const bool use_density = !density_out->links.empty();
+ const bool use_color = !color_out->links.empty();
+
+ image_manager = compiler.image_manager;
+
+ if (use_density || use_color) {
+ if (use_density)
+ compiler.stack_assign(density_out);
+ if (use_color)
+ compiler.stack_assign(color_out);
+
+ if(slot == -1) {
+ bool is_float, is_linear;
+ slot = image_manager->add_image(filename, builtin_data,
+ false, 0,
+ is_float, is_linear,
+ interpolation,
+ EXTENSION_REPEAT,
+ true);
+ }
+
+ if(slot != -1) {
+ compiler.stack_assign(vector_in);
+ compiler.add_node(NODE_TEX_VOXEL,
+ slot,
+ compiler.encode_uchar4(vector_in->stack_offset,
+ density_out->stack_offset,
+ color_out->stack_offset,
+ space_enum[space]));
+ if(space == "World") {
+ compiler.add_node(tfm.x);
+ compiler.add_node(tfm.y);
+ compiler.add_node(tfm.z);
+ compiler.add_node(tfm.w);
+ }
+ }
+ else {
+ compiler.add_node(NODE_VALUE_F,
+ __float_as_int(0.0f),
+ density_out->stack_offset);
+ compiler.add_node(NODE_VALUE_V, color_out->stack_offset);
+ compiler.add_node(NODE_VALUE_V, make_float3(TEX_IMAGE_MISSING_R,
+ TEX_IMAGE_MISSING_G,
+ TEX_IMAGE_MISSING_B));
+ }
+ }
+}
+
+void PointDensityTextureNode::compile(OSLCompiler& compiler)
+{
+ ShaderOutput *density_out = output("Density");
+ ShaderOutput *color_out = output("Color");
+
+ const bool use_density = !density_out->links.empty();
+ const bool use_color = !color_out->links.empty();
+
+ image_manager = compiler.image_manager;
+
+ if (use_density || use_color) {
+ if(slot == -1) {
+ bool is_float, is_linear;
+ slot = image_manager->add_image(filename, builtin_data,
+ false, 0,
+ is_float, is_linear,
+ interpolation,
+ EXTENSION_REPEAT,
+ true);
+ }
+
+ if(slot != -1) {
+ compiler.parameter("filename", string_printf("@%d", slot).c_str());
+ }
+ if(space == "World") {
+ compiler.parameter("mapping", transform_transpose(tfm));
+ compiler.parameter("use_mapping", 1);
+ }
+ switch (interpolation) {
+ case INTERPOLATION_CLOSEST:
+ compiler.parameter("interpolation", "closest");
+ break;
+ case INTERPOLATION_CUBIC:
+ compiler.parameter("interpolation", "cubic");
+ break;
+ case INTERPOLATION_LINEAR:
+ default:
+ compiler.parameter("interpolation", "linear");
+ break;
+ }
+
+ compiler.add(this, "node_voxel_texture");
+ }
+}
+
/* Normal */
NormalNode::NormalNode()
@@ -1503,11 +1711,11 @@ ProxyNode::ProxyNode(ShaderSocketType type_)
add_output("Output", type);
}
-void ProxyNode::compile(SVMCompiler& compiler)
+void ProxyNode::compile(SVMCompiler& /*compiler*/)
{
}
-void ProxyNode::compile(OSLCompiler& compiler)
+void ProxyNode::compile(OSLCompiler& /*compiler*/)
{
}
@@ -1516,6 +1724,8 @@ void ProxyNode::compile(OSLCompiler& compiler)
BsdfNode::BsdfNode(bool scattering_)
: ShaderNode("bsdf"), scattering(scattering_)
{
+ special_type = SHADER_SPECIAL_TYPE_CLOSURE;
+
add_input("Color", SHADER_SOCKET_COLOR, make_float3(0.8f, 0.8f, 0.8f));
add_input("Normal", SHADER_SOCKET_NORMAL, ShaderInput::NORMAL);
add_input("SurfaceMixWeight", SHADER_SOCKET_FLOAT, 0.0f, ShaderInput::USE_SVM);
@@ -1583,7 +1793,7 @@ void BsdfNode::compile(SVMCompiler& compiler)
compile(compiler, NULL, NULL);
}
-void BsdfNode::compile(OSLCompiler& compiler)
+void BsdfNode::compile(OSLCompiler& /*compiler*/)
{
assert(0);
}
@@ -1605,6 +1815,7 @@ ShaderEnum AnisotropicBsdfNode::distribution_enum = aniso_distribution_init();
AnisotropicBsdfNode::AnisotropicBsdfNode()
{
+ closure = CLOSURE_BSDF_MICROFACET_GGX_ANISO_ID;
distribution = ustring("GGX");
add_input("Tangent", SHADER_SOCKET_VECTOR, ShaderInput::TANGENT);
@@ -1657,6 +1868,7 @@ ShaderEnum GlossyBsdfNode::distribution_enum = glossy_distribution_init();
GlossyBsdfNode::GlossyBsdfNode()
{
+ closure = CLOSURE_BSDF_MICROFACET_GGX_ID;
distribution = ustring("GGX");
add_input("Roughness", SHADER_SOCKET_FLOAT, 0.2f);
@@ -1695,6 +1907,7 @@ ShaderEnum GlassBsdfNode::distribution_enum = glass_distribution_init();
GlassBsdfNode::GlassBsdfNode()
{
+ closure = CLOSURE_BSDF_SHARP_GLASS_ID;
distribution = ustring("Sharp");
add_input("Roughness", SHADER_SOCKET_FLOAT, 0.0f);
@@ -1734,6 +1947,7 @@ ShaderEnum RefractionBsdfNode::distribution_enum = refraction_distribution_init(
RefractionBsdfNode::RefractionBsdfNode()
{
+ closure = CLOSURE_BSDF_REFRACTION_ID;
distribution = ustring("Sharp");
add_input("Roughness", SHADER_SOCKET_FLOAT, 0.0f);
@@ -1772,6 +1986,7 @@ ShaderEnum ToonBsdfNode::component_enum = toon_component_init();
ToonBsdfNode::ToonBsdfNode()
{
+ closure = CLOSURE_BSDF_DIFFUSE_TOON_ID;
component = ustring("Diffuse");
add_input("Size", SHADER_SOCKET_FLOAT, 0.5f);
@@ -1912,6 +2127,8 @@ bool SubsurfaceScatteringNode::has_bssrdf_bump()
EmissionNode::EmissionNode()
: ShaderNode("emission")
{
+ special_type = SHADER_SPECIAL_TYPE_EMISSION;
+
add_input("Color", SHADER_SOCKET_COLOR, make_float3(0.8f, 0.8f, 0.8f));
add_input("Strength", SHADER_SOCKET_FLOAT, 10.0f);
add_input("SurfaceMixWeight", SHADER_SOCKET_FLOAT, 0.0f, ShaderInput::USE_SVM);
@@ -1945,6 +2162,8 @@ void EmissionNode::compile(OSLCompiler& compiler)
BackgroundNode::BackgroundNode()
: ShaderNode("background")
{
+ special_type = SHADER_SPECIAL_TYPE_BACKGROUND;
+
add_input("Color", SHADER_SOCKET_COLOR, make_float3(0.8f, 0.8f, 0.8f));
add_input("Strength", SHADER_SOCKET_FLOAT, 1.0f);
add_input("SurfaceMixWeight", SHADER_SOCKET_FLOAT, 0.0f, ShaderInput::USE_SVM);
@@ -2072,7 +2291,7 @@ void VolumeNode::compile(SVMCompiler& compiler)
compile(compiler, NULL, NULL);
}
-void VolumeNode::compile(OSLCompiler& compiler)
+void VolumeNode::compile(OSLCompiler& /*compiler*/)
{
assert(0);
}
@@ -2129,6 +2348,7 @@ ShaderEnum HairBsdfNode::component_enum = hair_component_init();
HairBsdfNode::HairBsdfNode()
{
+ closure = CLOSURE_BSDF_HAIR_REFLECTION_ID;
component = ustring("Reflection");
add_input("Offset", SHADER_SOCKET_FLOAT);
@@ -2165,13 +2385,18 @@ GeometryNode::GeometryNode()
add_output("Incoming", SHADER_SOCKET_VECTOR);
add_output("Parametric", SHADER_SOCKET_POINT);
add_output("Backfacing", SHADER_SOCKET_FLOAT);
+ add_output("Pointiness", SHADER_SOCKET_FLOAT);
}
void GeometryNode::attributes(Shader *shader, AttributeRequestSet *attributes)
{
if(shader->has_surface) {
- if(!output("Tangent")->links.empty())
+ if(!output("Tangent")->links.empty()) {
attributes->add(ATTR_STD_GENERATED);
+ }
+ if(!output("Pointiness")->links.empty()) {
+ attributes->add(ATTR_STD_POINTINESS);
+ }
}
ShaderNode::attributes(shader, attributes);
@@ -2181,11 +2406,16 @@ void GeometryNode::compile(SVMCompiler& compiler)
{
ShaderOutput *out;
NodeType geom_node = NODE_GEOMETRY;
+ NodeType attr_node = NODE_ATTR;
- if(bump == SHADER_BUMP_DX)
+ if(bump == SHADER_BUMP_DX) {
geom_node = NODE_GEOMETRY_BUMP_DX;
- else if(bump == SHADER_BUMP_DY)
+ attr_node = NODE_ATTR_BUMP_DX;
+ }
+ else if(bump == SHADER_BUMP_DY) {
geom_node = NODE_GEOMETRY_BUMP_DY;
+ attr_node = NODE_ATTR_BUMP_DY;
+ }
out = output("Position");
if(!out->links.empty()) {
@@ -2228,6 +2458,20 @@ void GeometryNode::compile(SVMCompiler& compiler)
compiler.stack_assign(out);
compiler.add_node(NODE_LIGHT_PATH, NODE_LP_backfacing, out->stack_offset);
}
+
+ out = output("Pointiness");
+ if(!out->links.empty()) {
+ compiler.stack_assign(out);
+ if(compiler.output_type() != SHADER_TYPE_VOLUME) {
+ compiler.add_node(attr_node,
+ ATTR_STD_POINTINESS,
+ out->stack_offset,
+ NODE_ATTR_FLOAT);
+ }
+ else {
+ compiler.add_node(NODE_VALUE_F, __float_as_int(0.0f), out->stack_offset);
+ }
+ }
}
void GeometryNode::compile(OSLCompiler& compiler)
@@ -2257,6 +2501,8 @@ TextureCoordinateNode::TextureCoordinateNode()
add_output("Reflection", SHADER_SOCKET_NORMAL);
from_dupli = false;
+ use_transform = false;
+ ob_tfm = transform_identity();
}
void TextureCoordinateNode::attributes(Shader *shader, AttributeRequestSet *attributes)
@@ -2344,7 +2590,14 @@ void TextureCoordinateNode::compile(SVMCompiler& compiler)
out = output("Object");
if(!out->links.empty()) {
compiler.stack_assign(out);
- compiler.add_node(texco_node, NODE_TEXCO_OBJECT, out->stack_offset);
+ compiler.add_node(texco_node, NODE_TEXCO_OBJECT, out->stack_offset, use_transform);
+ if(use_transform) {
+ Transform ob_itfm = transform_inverse(ob_tfm);
+ compiler.add_node(ob_itfm.x);
+ compiler.add_node(ob_itfm.y);
+ compiler.add_node(ob_itfm.z);
+ compiler.add_node(ob_itfm.w);
+ }
}
out = output("Camera");
@@ -2385,7 +2638,10 @@ void TextureCoordinateNode::compile(OSLCompiler& compiler)
compiler.parameter("is_background", true);
if(compiler.output_type() == SHADER_TYPE_VOLUME)
compiler.parameter("is_volume", true);
-
+ compiler.parameter("use_transform", use_transform);
+ Transform ob_itfm = transform_transpose(transform_inverse(ob_tfm));
+ compiler.parameter("object_itfm", ob_itfm);
+
compiler.parameter("from_dupli", from_dupli);
compiler.add(this, "node_texture_coordinate");
@@ -2405,7 +2661,7 @@ void UVMapNode::attributes(Shader *shader, AttributeRequestSet *attributes)
if(shader->has_surface) {
if(!from_dupli) {
if(!output("UV")->links.empty()) {
- if (attribute != "")
+ if(attribute != "")
attributes->add(attribute);
else
attributes->add(ATTR_STD_UV);
@@ -2438,7 +2694,7 @@ void UVMapNode::compile(SVMCompiler& compiler)
compiler.add_node(texco_node, NODE_TEXCO_DUPLI_UV, out->stack_offset);
}
else {
- if (attribute != "")
+ if(attribute != "")
attr = compiler.attribute(attribute);
else
attr = compiler.attribute(ATTR_STD_UV);
@@ -2879,7 +3135,7 @@ AddClosureNode::AddClosureNode()
add_output("Closure", SHADER_SOCKET_CLOSURE);
}
-void AddClosureNode::compile(SVMCompiler& compiler)
+void AddClosureNode::compile(SVMCompiler& /*compiler*/)
{
/* handled in the SVM compiler */
}
@@ -2902,7 +3158,7 @@ MixClosureNode::MixClosureNode()
add_output("Closure", SHADER_SOCKET_CLOSURE);
}
-void MixClosureNode::compile(SVMCompiler& compiler)
+void MixClosureNode::compile(SVMCompiler& /*compiler*/)
{
/* handled in the SVM compiler */
}
@@ -2940,7 +3196,7 @@ void MixClosureWeightNode::compile(SVMCompiler& compiler)
weight1_out->stack_offset, weight2_out->stack_offset));
}
-void MixClosureWeightNode::compile(OSLCompiler& compiler)
+void MixClosureWeightNode::compile(OSLCompiler& /*compiler*/)
{
assert(0);
}
@@ -3540,14 +3796,34 @@ void WireframeNode::compile(SVMCompiler& compiler)
{
ShaderInput *size_in = input("Size");
ShaderOutput *fac_out = output("Fac");
-
+ NodeBumpOffset bump_offset = NODE_BUMP_OFFSET_CENTER;
+ if(bump == SHADER_BUMP_DX) {
+ bump_offset = NODE_BUMP_OFFSET_DX;
+ }
+ else if(bump == SHADER_BUMP_DY) {
+ bump_offset = NODE_BUMP_OFFSET_DY;
+ }
compiler.stack_assign(size_in);
compiler.stack_assign(fac_out);
- compiler.add_node(NODE_WIREFRAME, size_in->stack_offset, fac_out->stack_offset, use_pixel_size);
+ compiler.add_node(NODE_WIREFRAME,
+ size_in->stack_offset,
+ fac_out->stack_offset,
+ compiler.encode_uchar4(use_pixel_size,
+ bump_offset,
+ 0, 0));
}
void WireframeNode::compile(OSLCompiler& compiler)
{
+ if(bump == SHADER_BUMP_DX) {
+ compiler.parameter("bump_offset", "dx");
+ }
+ else if(bump == SHADER_BUMP_DY) {
+ compiler.parameter("bump_offset", "dy");
+ }
+ else {
+ compiler.parameter("bump_offset", "center");
+ }
compiler.parameter("use_pixel_size", use_pixel_size);
compiler.add(this, "node_wireframe");
}
@@ -3590,9 +3866,17 @@ void BlackbodyNode::compile(SVMCompiler& compiler)
ShaderInput *temperature_in = input("Temperature");
ShaderOutput *color_out = output("Color");
- compiler.stack_assign(temperature_in);
compiler.stack_assign(color_out);
- compiler.add_node(NODE_BLACKBODY, temperature_in->stack_offset, color_out->stack_offset);
+
+ if(temperature_in->link == NULL) {
+ float3 color = svm_math_blackbody_color(temperature_in->value.x);
+ compiler.add_node(NODE_VALUE_V, color_out->stack_offset);
+ compiler.add_node(NODE_VALUE_V, color);
+ }
+ else {
+ compiler.stack_assign(temperature_in);
+ compiler.add_node(NODE_BLACKBODY, temperature_in->stack_offset, color_out->stack_offset);
+ }
}
void BlackbodyNode::compile(OSLCompiler& compiler)
@@ -3669,7 +3953,7 @@ static ShaderEnum math_type_init()
enm.insert("Less Than", NODE_MATH_LESS_THAN);
enm.insert("Greater Than", NODE_MATH_GREATER_THAN);
enm.insert("Modulo", NODE_MATH_MODULO);
- enm.insert("Absolute", NODE_MATH_ABSOLUTE);
+ enm.insert("Absolute", NODE_MATH_ABSOLUTE);
return enm;
}
@@ -3682,9 +3966,24 @@ void MathNode::compile(SVMCompiler& compiler)
ShaderInput *value2_in = input("Value2");
ShaderOutput *value_out = output("Value");
+ compiler.stack_assign(value_out);
+
+ /* Optimize math node without links to a single value node. */
+ if(value1_in->link == NULL && value2_in->link == NULL) {
+ float optimized_value = svm_math((NodeMath)type_enum[type],
+ value1_in->value.x,
+ value2_in->value.x);
+ if(use_clamp) {
+ optimized_value = saturate(optimized_value);
+ }
+ compiler.add_node(NODE_VALUE_F,
+ __float_as_int(optimized_value),
+ value_out->stack_offset);
+ return;
+ }
+
compiler.stack_assign(value1_in);
compiler.stack_assign(value2_in);
- compiler.stack_assign(value_out);
compiler.add_node(NODE_MATH, type_enum[type], value1_in->stack_offset, value2_in->stack_offset);
compiler.add_node(NODE_MATH, value_out->stack_offset);
@@ -3738,11 +4037,31 @@ void VectorMathNode::compile(SVMCompiler& compiler)
ShaderOutput *value_out = output("Value");
ShaderOutput *vector_out = output("Vector");
- compiler.stack_assign(vector1_in);
- compiler.stack_assign(vector2_in);
compiler.stack_assign(value_out);
compiler.stack_assign(vector_out);
+ /* Optimize vector math node without links to a single value node. */
+ if(vector1_in->link == NULL && vector2_in->link == NULL) {
+ float optimized_value;
+ float3 optimized_vector;
+ svm_vector_math(&optimized_value,
+ &optimized_vector,
+ (NodeVectorMath)type_enum[type],
+ vector1_in->value,
+ vector2_in->value);
+
+ compiler.add_node(NODE_VALUE_F,
+ __float_as_int(optimized_value),
+ value_out->stack_offset);
+
+ compiler.add_node(NODE_VALUE_V, vector_out->stack_offset);
+ compiler.add_node(NODE_VALUE_V, optimized_vector);
+ return;
+ }
+
+ compiler.stack_assign(vector1_in);
+ compiler.stack_assign(vector2_in);
+
compiler.add_node(NODE_VECTOR_MATH, type_enum[type], vector1_in->stack_offset, vector2_in->stack_offset);
compiler.add_node(NODE_VECTOR_MATH, value_out->stack_offset, vector_out->stack_offset);
}
@@ -3819,6 +4138,8 @@ BumpNode::BumpNode()
{
invert = false;
+ special_type = SHADER_SPECIAL_TYPE_BUMP;
+
/* this input is used by the user, but after graph transform it is no longer
* used and moved to sampler center/x/y instead */
add_input("Height", SHADER_SOCKET_FLOAT);
@@ -3895,7 +4216,7 @@ void RGBCurvesNode::compile(OSLCompiler& compiler)
{
float ramp[RAMP_TABLE_SIZE][3];
- for (int i = 0; i < RAMP_TABLE_SIZE; ++i) {
+ for(int i = 0; i < RAMP_TABLE_SIZE; ++i) {
ramp[i][0] = curves[i].x;
ramp[i][1] = curves[i].y;
ramp[i][2] = curves[i].z;
@@ -3933,7 +4254,7 @@ void VectorCurvesNode::compile(OSLCompiler& compiler)
{
float ramp[RAMP_TABLE_SIZE][3];
- for (int i = 0; i < RAMP_TABLE_SIZE; ++i) {
+ for(int i = 0; i < RAMP_TABLE_SIZE; ++i) {
ramp[i][0] = curves[i].x;
ramp[i][1] = curves[i].y;
ramp[i][2] = curves[i].z;
@@ -3983,7 +4304,7 @@ void RGBRampNode::compile(OSLCompiler& compiler)
float ramp_color[RAMP_TABLE_SIZE][3];
float ramp_alpha[RAMP_TABLE_SIZE];
- for (int i = 0; i < RAMP_TABLE_SIZE; ++i) {
+ for(int i = 0; i < RAMP_TABLE_SIZE; ++i) {
ramp_color[i][0] = ramp[i].x;
ramp_color[i][1] = ramp[i].y;
ramp_color[i][2] = ramp[i].z;
@@ -4030,7 +4351,7 @@ OSLScriptNode::OSLScriptNode()
special_type = SHADER_SPECIAL_TYPE_SCRIPT;
}
-void OSLScriptNode::compile(SVMCompiler& compiler)
+void OSLScriptNode::compile(SVMCompiler& /*compiler*/)
{
/* doesn't work for SVM, obviously ... */
}
diff --git a/intern/cycles/render/nodes.h b/intern/cycles/render/nodes.h
index 31b6f4e50c4..5065e68345a 100644
--- a/intern/cycles/render/nodes.h
+++ b/intern/cycles/render/nodes.h
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#ifndef __NODES_H__
@@ -55,13 +55,28 @@ public:
/* Nodes */
+/* Any node which uses image manager's slot should be a subclass of this one. */
+class ImageSlotNode : public ShaderNode {
+public:
+ ImageSlotNode(const char *name_) : ShaderNode(name_) {
+ special_type = SHADER_SPECIAL_TYPE_IMAGE_SLOT;
+ }
+ int slot;
+};
+
class TextureNode : public ShaderNode {
public:
TextureNode(const char *name_) : ShaderNode(name_) {}
TextureMapping tex_mapping;
};
-class ImageTextureNode : public TextureNode {
+class ImageSlotTextureNode : public ImageSlotNode {
+public:
+ ImageSlotTextureNode(const char *name_) : ImageSlotNode(name_) {}
+ TextureMapping tex_mapping;
+};
+
+class ImageTextureNode : public ImageSlotTextureNode {
public:
SHADER_NODE_NO_CLONE_CLASS(ImageTextureNode)
~ImageTextureNode();
@@ -69,7 +84,6 @@ public:
void attributes(Shader *shader, AttributeRequestSet *attributes);
ImageManager *image_manager;
- int slot;
int is_float;
bool is_linear;
bool use_alpha;
@@ -78,6 +92,7 @@ public:
ustring color_space;
ustring projection;
InterpolationType interpolation;
+ ExtensionType extension;
float projection_blend;
bool animated;
@@ -85,15 +100,15 @@ public:
static ShaderEnum projection_enum;
};
-class EnvironmentTextureNode : public TextureNode {
+class EnvironmentTextureNode : public ImageSlotTextureNode {
public:
SHADER_NODE_NO_CLONE_CLASS(EnvironmentTextureNode)
~EnvironmentTextureNode();
ShaderNode *clone() const;
void attributes(Shader *shader, AttributeRequestSet *attributes);
+ virtual int get_group() { return NODE_GROUP_LEVEL_2; }
ImageManager *image_manager;
- int slot;
int is_float;
bool is_linear;
bool use_alpha;
@@ -111,6 +126,8 @@ class SkyTextureNode : public TextureNode {
public:
SHADER_NODE_CLASS(SkyTextureNode)
+ virtual int get_group() { return NODE_GROUP_LEVEL_2; }
+
float3 sun_direction;
float turbidity;
float ground_albedo;
@@ -128,6 +145,8 @@ class GradientTextureNode : public TextureNode {
public:
SHADER_NODE_CLASS(GradientTextureNode)
+ virtual int get_group() { return NODE_GROUP_LEVEL_2; }
+
ustring type;
static ShaderEnum type_enum;
};
@@ -141,6 +160,8 @@ class VoronoiTextureNode : public TextureNode {
public:
SHADER_NODE_CLASS(VoronoiTextureNode)
+ virtual int get_group() { return NODE_GROUP_LEVEL_2; }
+
ustring coloring;
static ShaderEnum coloring_enum;
@@ -150,6 +171,8 @@ class MusgraveTextureNode : public TextureNode {
public:
SHADER_NODE_CLASS(MusgraveTextureNode)
+ virtual int get_group() { return NODE_GROUP_LEVEL_2; }
+
ustring type;
static ShaderEnum type_enum;
@@ -159,6 +182,8 @@ class WaveTextureNode : public TextureNode {
public:
SHADER_NODE_CLASS(WaveTextureNode)
+ virtual int get_group() { return NODE_GROUP_LEVEL_2; }
+
ustring type;
static ShaderEnum type_enum;
};
@@ -167,12 +192,16 @@ class MagicTextureNode : public TextureNode {
public:
SHADER_NODE_CLASS(MagicTextureNode)
+ virtual int get_group() { return NODE_GROUP_LEVEL_2; }
+
int depth;
};
class CheckerTextureNode : public TextureNode {
public:
SHADER_NODE_CLASS(CheckerTextureNode)
+
+ virtual int get_group() { return NODE_GROUP_LEVEL_2; }
};
class BrickTextureNode : public TextureNode {
@@ -181,11 +210,37 @@ public:
float offset, squash;
int offset_frequency, squash_frequency;
+
+ virtual int get_group() { return NODE_GROUP_LEVEL_2; }
+};
+
+class PointDensityTextureNode : public ShaderNode {
+public:
+ SHADER_NODE_NO_CLONE_CLASS(PointDensityTextureNode)
+
+ ~PointDensityTextureNode();
+ ShaderNode *clone() const;
+ void attributes(Shader *shader, AttributeRequestSet *attributes);
+
+ bool has_spatial_varying() { return true; }
+ bool has_object_dependency() { return true; }
+
+ ImageManager *image_manager;
+ int slot;
+ string filename;
+ ustring space;
+ void *builtin_data;
+ InterpolationType interpolation;
+
+ Transform tfm;
+
+ static ShaderEnum space_enum;
};
class MappingNode : public ShaderNode {
public:
SHADER_NODE_CLASS(MappingNode)
+ virtual int get_group() { return NODE_GROUP_LEVEL_2; }
TextureMapping tex_mapping;
};
@@ -308,6 +363,7 @@ public:
class HoldoutNode : public ShaderNode {
public:
SHADER_NODE_CLASS(HoldoutNode)
+ virtual int get_group() { return NODE_GROUP_LEVEL_1; }
};
class AmbientOcclusionNode : public ShaderNode {
@@ -315,6 +371,7 @@ public:
SHADER_NODE_CLASS(AmbientOcclusionNode)
bool has_spatial_varying() { return true; }
+ virtual int get_group() { return NODE_GROUP_LEVEL_1; }
};
class VolumeNode : public ShaderNode {
@@ -322,6 +379,7 @@ public:
SHADER_NODE_CLASS(VolumeNode)
void compile(SVMCompiler& compiler, ShaderInput *param1, ShaderInput *param2);
+ virtual int get_group() { return NODE_GROUP_LEVEL_1; }
ClosureType closure;
};
@@ -357,8 +415,11 @@ public:
SHADER_NODE_CLASS(TextureCoordinateNode)
void attributes(Shader *shader, AttributeRequestSet *attributes);
bool has_spatial_varying() { return true; }
-
+ bool has_object_dependency() { return use_transform; }
+
bool from_dupli;
+ bool use_transform;
+ Transform ob_tfm;
};
class UVMapNode : public ShaderNode {
@@ -366,6 +427,7 @@ public:
SHADER_NODE_CLASS(UVMapNode)
void attributes(Shader *shader, AttributeRequestSet *attributes);
bool has_spatial_varying() { return true; }
+ virtual int get_group() { return NODE_GROUP_LEVEL_1; }
ustring attribute;
bool from_dupli;
@@ -374,6 +436,7 @@ public:
class LightPathNode : public ShaderNode {
public:
SHADER_NODE_CLASS(LightPathNode)
+ virtual int get_group() { return NODE_GROUP_LEVEL_1; }
};
class LightFalloffNode : public ShaderNode {
@@ -385,12 +448,14 @@ public:
class ObjectInfoNode : public ShaderNode {
public:
SHADER_NODE_CLASS(ObjectInfoNode)
+ virtual int get_group() { return NODE_GROUP_LEVEL_1; }
};
class ParticleInfoNode : public ShaderNode {
public:
SHADER_NODE_CLASS(ParticleInfoNode)
void attributes(Shader *shader, AttributeRequestSet *attributes);
+ virtual int get_group() { return NODE_GROUP_LEVEL_1; }
};
class HairInfoNode : public ShaderNode {
@@ -399,6 +464,10 @@ public:
void attributes(Shader *shader, AttributeRequestSet *attributes);
bool has_spatial_varying() { return true; }
+ virtual int get_group() { return NODE_GROUP_LEVEL_1; }
+ virtual int get_feature() {
+ return ShaderNode::get_feature() | NODE_FEATURE_HAIR;
+ }
};
class ValueNode : public ShaderNode {
@@ -433,12 +502,16 @@ public:
class InvertNode : public ShaderNode {
public:
SHADER_NODE_CLASS(InvertNode)
+
+ virtual int get_group() { return NODE_GROUP_LEVEL_3; }
};
class MixNode : public ShaderNode {
public:
SHADER_NODE_CLASS(MixNode)
+ virtual int get_group() { return NODE_GROUP_LEVEL_3; }
+
bool use_clamp;
ustring type;
@@ -448,41 +521,55 @@ public:
class CombineRGBNode : public ShaderNode {
public:
SHADER_NODE_CLASS(CombineRGBNode)
+
+ virtual int get_group() { return NODE_GROUP_LEVEL_3; }
};
class CombineHSVNode : public ShaderNode {
public:
SHADER_NODE_CLASS(CombineHSVNode)
+
+ virtual int get_group() { return NODE_GROUP_LEVEL_3; }
};
class CombineXYZNode : public ShaderNode {
public:
SHADER_NODE_CLASS(CombineXYZNode)
+
+ virtual int get_group() { return NODE_GROUP_LEVEL_3; }
};
class GammaNode : public ShaderNode {
public:
SHADER_NODE_CLASS(GammaNode)
+ virtual int get_group() { return NODE_GROUP_LEVEL_1; }
};
class BrightContrastNode : public ShaderNode {
public:
SHADER_NODE_CLASS(BrightContrastNode)
+ virtual int get_group() { return NODE_GROUP_LEVEL_1; }
};
class SeparateRGBNode : public ShaderNode {
public:
SHADER_NODE_CLASS(SeparateRGBNode)
+
+ virtual int get_group() { return NODE_GROUP_LEVEL_3; }
};
class SeparateHSVNode : public ShaderNode {
public:
SHADER_NODE_CLASS(SeparateHSVNode)
+
+ virtual int get_group() { return NODE_GROUP_LEVEL_3; }
};
class SeparateXYZNode : public ShaderNode {
public:
SHADER_NODE_CLASS(SeparateXYZNode)
+
+ virtual int get_group() { return NODE_GROUP_LEVEL_3; }
};
class HSVNode : public ShaderNode {
@@ -509,18 +596,21 @@ class FresnelNode : public ShaderNode {
public:
SHADER_NODE_CLASS(FresnelNode)
bool has_spatial_varying() { return true; }
+ virtual int get_group() { return NODE_GROUP_LEVEL_1; }
};
class LayerWeightNode : public ShaderNode {
public:
SHADER_NODE_CLASS(LayerWeightNode)
bool has_spatial_varying() { return true; }
+ virtual int get_group() { return NODE_GROUP_LEVEL_1; }
};
class WireframeNode : public ShaderNode {
public:
SHADER_NODE_CLASS(WireframeNode)
bool has_spatial_varying() { return true; }
+ virtual int get_group() { return NODE_GROUP_LEVEL_3; }
bool use_pixel_size;
};
@@ -528,18 +618,21 @@ public:
class WavelengthNode : public ShaderNode {
public:
SHADER_NODE_CLASS(WavelengthNode)
+
+ virtual int get_group() { return NODE_GROUP_LEVEL_3; }
};
class BlackbodyNode : public ShaderNode {
public:
SHADER_NODE_CLASS(BlackbodyNode)
-
- bool has_converter_blackbody() { return true; }
+
+ virtual int get_group() { return NODE_GROUP_LEVEL_3; }
};
class MathNode : public ShaderNode {
public:
SHADER_NODE_CLASS(MathNode)
+ virtual int get_group() { return NODE_GROUP_LEVEL_1; }
bool use_clamp;
@@ -550,6 +643,7 @@ public:
class NormalNode : public ShaderNode {
public:
SHADER_NODE_CLASS(NormalNode)
+ virtual int get_group() { return NODE_GROUP_LEVEL_2; }
float3 direction;
};
@@ -557,6 +651,7 @@ public:
class VectorMathNode : public ShaderNode {
public:
SHADER_NODE_CLASS(VectorMathNode)
+ virtual int get_group() { return NODE_GROUP_LEVEL_1; }
ustring type;
static ShaderEnum type_enum;
@@ -566,6 +661,8 @@ class VectorTransformNode : public ShaderNode {
public:
SHADER_NODE_CLASS(VectorTransformNode)
+ virtual int get_group() { return NODE_GROUP_LEVEL_3; }
+
ustring type;
ustring convert_from;
ustring convert_to;
@@ -578,6 +675,9 @@ class BumpNode : public ShaderNode {
public:
SHADER_NODE_CLASS(BumpNode)
bool has_spatial_varying() { return true; }
+ virtual int get_feature() {
+ return NODE_FEATURE_BUMP;
+ }
bool invert;
};
@@ -585,12 +685,18 @@ public:
class RGBCurvesNode : public ShaderNode {
public:
SHADER_NODE_CLASS(RGBCurvesNode)
+
+ virtual int get_group() { return NODE_GROUP_LEVEL_3; }
+
float4 curves[RAMP_TABLE_SIZE];
};
class VectorCurvesNode : public ShaderNode {
public:
SHADER_NODE_CLASS(VectorCurvesNode)
+
+ virtual int get_group() { return NODE_GROUP_LEVEL_3; }
+
float4 curves[RAMP_TABLE_SIZE];
};
@@ -599,6 +705,7 @@ public:
SHADER_NODE_CLASS(RGBRampNode)
float4 ramp[RAMP_TABLE_SIZE];
bool interpolate;
+ virtual int get_group() { return NODE_GROUP_LEVEL_1; }
};
class SetNormalNode : public ShaderNode {
@@ -627,6 +734,7 @@ public:
SHADER_NODE_CLASS(NormalMapNode)
void attributes(Shader *shader, AttributeRequestSet *attributes);
bool has_spatial_varying() { return true; }
+ virtual int get_group() { return NODE_GROUP_LEVEL_3; }
ustring space;
static ShaderEnum space_enum;
@@ -639,6 +747,7 @@ public:
SHADER_NODE_CLASS(TangentNode)
void attributes(Shader *shader, AttributeRequestSet *attributes);
bool has_spatial_varying() { return true; }
+ virtual int get_group() { return NODE_GROUP_LEVEL_3; }
ustring direction_type;
static ShaderEnum direction_type_enum;
diff --git a/intern/cycles/render/object.cpp b/intern/cycles/render/object.cpp
index 1f148d34ea6..ec85aa8f80b 100644
--- a/intern/cycles/render/object.cpp
+++ b/intern/cycles/render/object.cpp
@@ -11,9 +11,10 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
+#include "camera.h"
#include "device.h"
#include "light.h"
#include "mesh.h"
@@ -23,6 +24,7 @@
#include "scene.h"
#include "util_foreach.h"
+#include "util_logging.h"
#include "util_map.h"
#include "util_progress.h"
#include "util_vector.h"
@@ -75,8 +77,14 @@ void Object::compute_bounds(bool motion_blur)
bounds.grow(mbounds.transformed(&ttfm));
}
}
- else
- bounds = mbounds.transformed(&tfm);
+ else {
+ if(mesh->transform_applied) {
+ bounds = mbounds;
+ }
+ else {
+ bounds = mbounds.transformed(&tfm);
+ }
+ }
}
void Object::apply_transform(bool apply_to_motion)
@@ -98,11 +106,11 @@ void Object::apply_transform(bool apply_to_motion)
if(apply_to_motion) {
Attribute *attr = mesh->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
- if (attr) {
+ if(attr) {
size_t steps_size = mesh->verts.size() * (mesh->motion_steps - 1);
float3 *vert_steps = attr->data_float3();
- for (size_t i = 0; i < steps_size; i++)
+ for(size_t i = 0; i < steps_size; i++)
vert_steps[i] = transform_point(&tfm, vert_steps[i]);
}
@@ -113,7 +121,7 @@ void Object::apply_transform(bool apply_to_motion)
size_t steps_size = mesh->verts.size() * (mesh->motion_steps - 1);
float3 *normal_steps = attr_N->data_float3();
- for (size_t i = 0; i < steps_size; i++)
+ for(size_t i = 0; i < steps_size; i++)
normal_steps[i] = normalize(transform_direction(&ntfm, normal_steps[i]));
}
}
@@ -140,12 +148,12 @@ void Object::apply_transform(bool apply_to_motion)
if(apply_to_motion) {
Attribute *curve_attr = mesh->curve_attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
- if (curve_attr) {
+ if(curve_attr) {
/* apply transform to motion curve keys */
size_t steps_size = mesh->curve_keys.size() * (mesh->motion_steps - 1);
float4 *key_steps = curve_attr->data_float4();
- for (size_t i = 0; i < steps_size; i++) {
+ for(size_t i = 0; i < steps_size; i++) {
float3 co = transform_point(&tfm, float4_to_float3(key_steps[i]));
float radius = key_steps[i].w * scalar;
@@ -185,6 +193,7 @@ void Object::tag_update(Scene *scene)
}
}
+ scene->camera->need_flags_update = true;
scene->curve_system_manager->need_update = true;
scene->mesh_manager->need_update = true;
scene->object_manager->need_update = true;
@@ -215,6 +224,7 @@ vector<float> Object::motion_times()
ObjectManager::ObjectManager()
{
need_update = true;
+ need_flags_update = true;
}
ObjectManager::~ObjectManager()
@@ -312,6 +322,9 @@ void ObjectManager::device_update_transforms(Device *device, DeviceScene *dscene
mtfm_pre = mtfm_pre * itfm;
mtfm_post = mtfm_post * itfm;
}
+ else {
+ flag |= SD_OBJECT_HAS_VERTEX_MOTION;
+ }
memcpy(&objects_vector[i*OBJECT_VECTOR_SIZE+0], &mtfm_pre, sizeof(float4)*3);
memcpy(&objects_vector[i*OBJECT_VECTOR_SIZE+3], &mtfm_post, sizeof(float4)*3);
@@ -367,13 +380,13 @@ void ObjectManager::device_update_transforms(Device *device, DeviceScene *dscene
void ObjectManager::device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress)
{
+ VLOG(1) << "Total " << scene->objects.size() << " objects.";
+
if(!need_update)
return;
device_free(device, dscene);
- need_update = false;
-
if(scene->objects.size() == 0)
return;
@@ -392,6 +405,65 @@ void ObjectManager::device_update(Device *device, DeviceScene *dscene, Scene *sc
progress.set_status("Updating Objects", "Applying Static Transformations");
apply_static_transforms(dscene, scene, object_flag, progress);
}
+}
+
+void ObjectManager::device_update_flags(Device *device,
+ DeviceScene *dscene,
+ Scene *scene,
+ Progress& /*progress*/,
+ bool bounds_valid)
+{
+ if(!need_update && !need_flags_update)
+ return;
+
+ need_update = false;
+ need_flags_update = false;
+
+ if(scene->objects.size() == 0)
+ return;
+
+ /* object info flag */
+ uint *object_flag = dscene->object_flag.get_data();
+
+ vector<Object *> volume_objects;
+ bool has_volume_objects = false;
+ foreach(Object *object, scene->objects) {
+ if(object->mesh->has_volume) {
+ if(bounds_valid) {
+ volume_objects.push_back(object);
+ }
+ has_volume_objects = true;
+ }
+ }
+
+ int object_index = 0;
+ foreach(Object *object, scene->objects) {
+ if(object->mesh->has_volume) {
+ object_flag[object_index] |= SD_OBJECT_HAS_VOLUME;
+ }
+ else {
+ object_flag[object_index] &= ~SD_OBJECT_HAS_VOLUME;
+ }
+
+ if(bounds_valid) {
+ foreach(Object *volume_object, volume_objects) {
+ if(object == volume_object) {
+ continue;
+ }
+ if(object->bounds.intersects(volume_object->bounds)) {
+ object_flag[object_index] |= SD_OBJECT_INTERSECTS_VOLUME;
+ break;
+ }
+ }
+ }
+ else if(has_volume_objects) {
+ /* Not really valid, but can't make more reliable in the case
+ * of bounds not being up to date.
+ */
+ object_flag[object_index] |= SD_OBJECT_INTERSECTS_VOLUME;
+ }
+ ++object_index;
+ }
/* allocate object flag */
device->tex_alloc("__object_flag", dscene->object_flag);
@@ -422,6 +494,7 @@ void ObjectManager::apply_static_transforms(DeviceScene *dscene, Scene *scene, u
bool apply_to_motion = need_motion != Scene::MOTION_PASS;
#else
bool motion_blur = false;
+ bool apply_to_motion = false;
#endif
int i = 0;
bool have_instancing = false;
@@ -439,7 +512,9 @@ void ObjectManager::apply_static_transforms(DeviceScene *dscene, Scene *scene, u
/* apply transforms for objects with single user meshes */
foreach(Object *object, scene->objects) {
- if(mesh_users[object->mesh] == 1) {
+ if(mesh_users[object->mesh] == 1 &&
+ object->mesh->displacement_method == Mesh::DISPLACE_BUMP)
+ {
if(!(motion_blur && object->use_motion)) {
if(!object->mesh->transform_applied) {
object->apply_transform(apply_to_motion);
diff --git a/intern/cycles/render/object.h b/intern/cycles/render/object.h
index 677526b715f..379d1748cdd 100644
--- a/intern/cycles/render/object.h
+++ b/intern/cycles/render/object.h
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#ifndef __OBJECT_H__
@@ -70,12 +70,18 @@ public:
class ObjectManager {
public:
bool need_update;
+ bool need_flags_update;
ObjectManager();
~ObjectManager();
void device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress);
void device_update_transforms(Device *device, DeviceScene *dscene, Scene *scene, uint *object_flag, Progress& progress);
+ void device_update_flags(Device *device,
+ DeviceScene *dscene,
+ Scene *scene,
+ Progress& progress,
+ bool bounds_valid = true);
void device_free(Device *device, DeviceScene *dscene);
void tag_update(Scene *scene);
diff --git a/intern/cycles/render/osl.cpp b/intern/cycles/render/osl.cpp
index f57e16471a1..a02f91ad2cf 100644
--- a/intern/cycles/render/osl.cpp
+++ b/intern/cycles/render/osl.cpp
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#include "device.h"
@@ -30,6 +30,7 @@
#include "osl_shader.h"
#include "util_foreach.h"
+#include "util_logging.h"
#include "util_md5.h"
#include "util_path.h"
#include "util_progress.h"
@@ -66,7 +67,7 @@ OSLShaderManager::~OSLShaderManager()
texture_system_free();
}
-void OSLShaderManager::reset(Scene *scene)
+void OSLShaderManager::reset(Scene * /*scene*/)
{
shading_system_free();
shading_system_init();
@@ -74,6 +75,8 @@ void OSLShaderManager::reset(Scene *scene)
void OSLShaderManager::device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress)
{
+ VLOG(1) << "Total " << scene->shaders.size() << " shaders.";
+
if(!need_update)
return;
@@ -188,12 +191,14 @@ void OSLShaderManager::shading_system_init()
if(ss_shared_users == 0) {
services_shared = new OSLRenderServices();
- ss_shared = OSL::ShadingSystem::create(services_shared, ts_shared, &errhandler);
+ ss_shared = new OSL::ShadingSystem(services_shared, ts_shared, &errhandler);
ss_shared->attribute("lockgeom", 1);
ss_shared->attribute("commonspace", "world");
ss_shared->attribute("searchpath:shader", path_get("shader"));
//ss_shared->attribute("greedyjit", 1);
+ VLOG(1) << "Using shader search path: " << path_get("shader");
+
/* our own ray types */
static const char *raytypes[] = {
"camera", /* PATH_RAY_CAMERA */
@@ -208,9 +213,9 @@ void OSLShaderManager::shading_system_init()
"__unused__",
"__unused__",
- "diffuse_ancestor", /* PATH_RAY_DIFFUSE_ANCESTOR */
- "glossy_ancestor", /* PATH_RAY_GLOSSY_ANCESTOR */
- "bssrdf_ancestor", /* PATH_RAY_BSSRDF_ANCESTOR */
+ "diffuse_ancestor", /* PATH_RAY_DIFFUSE_ANCESTOR */
+ "__unused__",
+ "__unused__",
"__unused__", /* PATH_RAY_SINGLE_PASS_DONE */
"volume_scatter", /* PATH_RAY_VOLUME_SCATTER */
};
@@ -235,7 +240,7 @@ void OSLShaderManager::shading_system_free()
ss_shared_users--;
if(ss_shared_users == 0) {
- OSL::ShadingSystem::destroy(ss_shared);
+ delete ss_shared;
ss_shared = NULL;
delete services_shared;
@@ -248,11 +253,11 @@ void OSLShaderManager::shading_system_free()
bool OSLShaderManager::osl_compile(const string& inputfile, const string& outputfile)
{
-#if OSL_LIBRARY_VERSION_CODE < 10500
- typedef string string_view;
-#endif
-
+#if OSL_LIBRARY_VERSION_CODE < 10602
vector<string_view> options;
+#else
+ vector<string> options;
+#endif
string stdosl_path;
string shader_path = path_get("shader");
@@ -261,13 +266,13 @@ bool OSLShaderManager::osl_compile(const string& inputfile, const string& output
options.push_back(outputfile);
/* specify standard include path */
- options.push_back("-I");
- options.push_back(shader_path);
+ string include_path_arg = string("-I") + shader_path;
+ options.push_back(include_path_arg);
stdosl_path = path_get("shader/stdosl.h");
/* compile */
- OSL::OSLCompiler *compiler = OSL::OSLCompiler::create();
+ OSL::OSLCompiler *compiler = new OSL::OSLCompiler();
bool ok = compiler->compile(string_view(inputfile), options, string_view(stdosl_path));
delete compiler;
@@ -411,7 +416,7 @@ string OSLCompiler::compatible_name(ShaderNode *node, ShaderInput *input)
/* if output exists with the same name, add "In" suffix */
foreach(ShaderOutput *output, node->outputs) {
- if (strcmp(input->name, output->name)==0) {
+ if(strcmp(input->name, output->name)==0) {
sname += "In";
break;
}
@@ -431,7 +436,7 @@ string OSLCompiler::compatible_name(ShaderNode *node, ShaderOutput *output)
/* if input exists with the same name, add "Out" suffix */
foreach(ShaderInput *input, node->inputs) {
- if (strcmp(input->name, output->name)==0) {
+ if(strcmp(input->name, output->name)==0) {
sname += "Out";
break;
}
@@ -564,6 +569,10 @@ void OSLCompiler::add(ShaderNode *node, const char *name, bool isfilepath)
if(node->has_spatial_varying())
current_shader->has_heterogeneous_volume = true;
}
+
+ if(node->has_object_dependency()) {
+ current_shader->has_object_dependency = true;
+ }
}
void OSLCompiler::parameter(const char *name, float f)
@@ -748,11 +757,7 @@ OSL::ShadingAttribStateRef OSLCompiler::compile_type(Shader *shader, ShaderGraph
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;
@@ -780,13 +785,7 @@ OSL::ShadingAttribStateRef OSLCompiler::compile_type(Shader *shader, ShaderGraph
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)
@@ -815,6 +814,7 @@ void OSLCompiler::compile(OSLGlobals *og, Shader *shader)
shader->has_volume = false;
shader->has_displacement = false;
shader->has_heterogeneous_volume = false;
+ shader->has_object_dependency = false;
/* generate surface shader */
if(shader->used && graph && output->input("Surface")->link) {
@@ -862,75 +862,75 @@ void OSLCompiler::compile(OSLGlobals *og, Shader *shader)
#else
-void OSLCompiler::add(ShaderNode *node, const char *name, bool isfilepath)
+void OSLCompiler::add(ShaderNode * /*node*/, const char * /*name*/, bool /*isfilepath*/)
{
}
-void OSLCompiler::parameter(const char *name, float f)
+void OSLCompiler::parameter(const char * /*name*/, float /*f*/)
{
}
-void OSLCompiler::parameter_color(const char *name, float3 f)
+void OSLCompiler::parameter_color(const char * /*name*/, float3 /*f*/)
{
}
-void OSLCompiler::parameter_vector(const char *name, float3 f)
+void OSLCompiler::parameter_vector(const char * /*name*/, float3 /*f*/)
{
}
-void OSLCompiler::parameter_point(const char *name, float3 f)
+void OSLCompiler::parameter_point(const char * /*name*/, float3 /*f*/)
{
}
-void OSLCompiler::parameter_normal(const char *name, float3 f)
+void OSLCompiler::parameter_normal(const char * /*name*/, float3 /*f*/)
{
}
-void OSLCompiler::parameter(const char *name, int f)
+void OSLCompiler::parameter(const char * /*name*/, int /*f*/)
{
}
-void OSLCompiler::parameter(const char *name, const char *s)
+void OSLCompiler::parameter(const char * /*name*/, const char * /*s*/)
{
}
-void OSLCompiler::parameter(const char *name, ustring s)
+void OSLCompiler::parameter(const char * /*name*/, ustring /*s*/)
{
}
-void OSLCompiler::parameter(const char *name, const Transform& tfm)
+void OSLCompiler::parameter(const char * /*name*/, const Transform& /*tfm*/)
{
}
-void OSLCompiler::parameter_array(const char *name, const float f[], int arraylen)
+void OSLCompiler::parameter_array(const char * /*name*/, const float /*f*/[], int /*arraylen*/)
{
}
-void OSLCompiler::parameter_color_array(const char *name, const float f[][3], int arraylen)
+void OSLCompiler::parameter_color_array(const char * /*name*/, const float /*f*/[][3], int /*arraylen*/)
{
}
-void OSLCompiler::parameter_vector_array(const char *name, const float f[][3], int arraylen)
+void OSLCompiler::parameter_vector_array(const char * /*name*/, const float /*f*/[][3], int /*arraylen*/)
{
}
-void OSLCompiler::parameter_normal_array(const char *name, const float f[][3], int arraylen)
+void OSLCompiler::parameter_normal_array(const char * /*name*/, const float /*f*/[][3], int /*arraylen*/)
{
}
-void OSLCompiler::parameter_point_array(const char *name, const float f[][3], int arraylen)
+void OSLCompiler::parameter_point_array(const char * /*name*/, const float /*f*/[][3], int /*arraylen*/)
{
}
-void OSLCompiler::parameter_array(const char *name, const int f[], int arraylen)
+void OSLCompiler::parameter_array(const char * /*name*/, const int /*f*/[], int /*arraylen*/)
{
}
-void OSLCompiler::parameter_array(const char *name, const char * const s[], int arraylen)
+void OSLCompiler::parameter_array(const char * /*name*/, const char * const /*s*/[], int /*arraylen*/)
{
}
-void OSLCompiler::parameter_array(const char *name, const Transform tfm[], int arraylen)
+void OSLCompiler::parameter_array(const char * /*name*/, const Transform /*tfm*/[], int /*arraylen*/)
{
}
diff --git a/intern/cycles/render/osl.h b/intern/cycles/render/osl.h
index 5824e2ace64..bc6a9d8fbbd 100644
--- a/intern/cycles/render/osl.h
+++ b/intern/cycles/render/osl.h
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#ifndef __OSL_H__
diff --git a/intern/cycles/render/particles.cpp b/intern/cycles/render/particles.cpp
index 255effa86dd..8f9e8c6d639 100644
--- a/intern/cycles/render/particles.cpp
+++ b/intern/cycles/render/particles.cpp
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#include "device.h"
@@ -19,6 +19,7 @@
#include "scene.h"
#include "util_foreach.h"
+#include "util_logging.h"
#include "util_map.h"
#include "util_progress.h"
#include "util_vector.h"
@@ -92,6 +93,9 @@ void ParticleSystemManager::device_update_particles(Device *device, DeviceScene
void ParticleSystemManager::device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress)
{
+ VLOG(1) << "Total " << scene->particle_systems.size()
+ << " particle systems.";
+
if(!need_update)
return;
@@ -111,7 +115,7 @@ void ParticleSystemManager::device_free(Device *device, DeviceScene *dscene)
dscene->particles.clear();
}
-void ParticleSystemManager::tag_update(Scene *scene)
+void ParticleSystemManager::tag_update(Scene * /*scene*/)
{
need_update = true;
}
diff --git a/intern/cycles/render/particles.h b/intern/cycles/render/particles.h
index a606722f9c3..bf2b6b77015 100644
--- a/intern/cycles/render/particles.h
+++ b/intern/cycles/render/particles.h
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#ifndef __PARTICLES_H__
diff --git a/intern/cycles/render/scene.cpp b/intern/cycles/render/scene.cpp
index d0de8c51300..19d715d834b 100644
--- a/intern/cycles/render/scene.cpp
+++ b/intern/cycles/render/scene.cpp
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#include <stdlib.h>
@@ -36,6 +36,11 @@
#include "util_foreach.h"
#include "util_progress.h"
+#ifdef WITH_CYCLES_DEBUG
+# include "util_guarded_allocator.h"
+# include "util_logging.h"
+#endif
+
CCL_NAMESPACE_BEGIN
Scene::Scene(const SceneParams& params_, const DeviceInfo& device_info_)
@@ -153,76 +158,98 @@ void Scene::device_update(Device *device_, Progress& progress)
progress.set_status("Updating Shaders");
shader_manager->device_update(device, &dscene, this, progress);
- if(progress.get_cancel()) return;
-
- progress.set_status("Updating Images");
- image_manager->device_update(device, &dscene, progress);
-
- if(progress.get_cancel()) return;
+ if(progress.get_cancel() || device->have_error()) return;
progress.set_status("Updating Background");
background->device_update(device, &dscene, this);
- if(progress.get_cancel()) return;
+ if(progress.get_cancel() || device->have_error()) return;
+
+ progress.set_status("Updating Camera");
+ camera->device_update(device, &dscene, this);
+
+ if(progress.get_cancel() || device->have_error()) return;
progress.set_status("Updating Objects");
object_manager->device_update(device, &dscene, this, progress);
- if(progress.get_cancel()) return;
+ if(progress.get_cancel() || device->have_error()) return;
+
+ progress.set_status("Updating Meshes Flags");
+ mesh_manager->device_update_flags(device, &dscene, this, progress);
+
+ if(progress.get_cancel() || device->have_error()) return;
progress.set_status("Updating Meshes");
mesh_manager->device_update(device, &dscene, this, progress);
- if(progress.get_cancel()) return;
+ if(progress.get_cancel() || device->have_error()) return;
+
+ progress.set_status("Updating Objects Flags");
+ object_manager->device_update_flags(device, &dscene, this, progress);
+
+ if(progress.get_cancel() || device->have_error()) return;
+
+ progress.set_status("Updating Images");
+ image_manager->device_update(device, &dscene, progress);
+
+ if(progress.get_cancel() || device->have_error()) return;
+
+ progress.set_status("Updating Camera Volume");
+ camera->device_update_volume(device, &dscene, this);
+
+ if(progress.get_cancel() || device->have_error()) return;
progress.set_status("Updating Hair Systems");
curve_system_manager->device_update(device, &dscene, this, progress);
- if(progress.get_cancel()) return;
+ if(progress.get_cancel() || device->have_error()) return;
progress.set_status("Updating Lookup Tables");
lookup_tables->device_update(device, &dscene);
- if(progress.get_cancel()) return;
-
- /* TODO(sergey): Make sure camera is not needed above. */
- progress.set_status("Updating Camera");
- camera->device_update(device, &dscene, this);
-
- if(progress.get_cancel()) return;
+ if(progress.get_cancel() || device->have_error()) return;
progress.set_status("Updating Lights");
light_manager->device_update(device, &dscene, this, progress);
- if(progress.get_cancel()) return;
+ if(progress.get_cancel() || device->have_error()) return;
progress.set_status("Updating Particle Systems");
particle_system_manager->device_update(device, &dscene, this, progress);
- if(progress.get_cancel()) return;
+ if(progress.get_cancel() || device->have_error()) return;
progress.set_status("Updating Film");
film->device_update(device, &dscene, this);
- if(progress.get_cancel()) return;
+ if(progress.get_cancel() || device->have_error()) return;
progress.set_status("Updating Integrator");
integrator->device_update(device, &dscene, this);
- if(progress.get_cancel()) return;
+ if(progress.get_cancel() || device->have_error()) return;
progress.set_status("Updating Lookup Tables");
lookup_tables->device_update(device, &dscene);
- if(progress.get_cancel()) return;
+ if(progress.get_cancel() || device->have_error()) return;
progress.set_status("Updating Baking");
bake_manager->device_update(device, &dscene, this, progress);
- if(progress.get_cancel()) return;
+ if(progress.get_cancel() || device->have_error()) return;
+
+ if(device->have_error() == false) {
+ progress.set_status("Updating Device", "Writing constant memory");
+ device->const_copy_to("__data", &dscene.data, sizeof(dscene.data));
+ }
- progress.set_status("Updating Device", "Writing constant memory");
- device->const_copy_to("__data", &dscene.data, sizeof(dscene.data));
+#ifdef WITH_CYCLES_DEBUG
+ VLOG(1) << "System memory statistics after full device sync:\n"
+ << " Usage: " << util_guarded_get_mem_used() << "\n"
+ << " Peak: " << util_guarded_get_mem_peak();
+#endif
}
Scene::MotionType Scene::need_motion(bool advanced_shading)
@@ -272,7 +299,8 @@ bool Scene::need_reset()
|| shader_manager->need_update
|| particle_system_manager->need_update
|| curve_system_manager->need_update
- || bake_manager->need_update);
+ || bake_manager->need_update
+ || film->need_update);
}
void Scene::reset()
diff --git a/intern/cycles/render/scene.h b/intern/cycles/render/scene.h
index 5d205225d97..851e5ac0b72 100644
--- a/intern/cycles/render/scene.h
+++ b/intern/cycles/render/scene.h
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#ifndef __SCENE_H__
@@ -26,6 +26,7 @@
#include "util_param.h"
#include "util_string.h"
+#include "util_system.h"
#include "util_thread.h"
#include "util_types.h"
#include "util_vector.h"
@@ -61,6 +62,7 @@ class DeviceScene {
public:
/* BVH */
device_vector<float4> bvh_nodes;
+ device_vector<float4> bvh_leaf_nodes;
device_vector<uint> object_node;
device_vector<float4> tri_woop;
device_vector<uint> prim_type;
@@ -135,11 +137,7 @@ public:
bvh_type = BVH_DYNAMIC;
use_bvh_cache = false;
use_bvh_spatial_split = false;
-#ifdef __QBVH__
- use_qbvh = true;
-#else
use_qbvh = false;
-#endif
persistent_data = false;
}
diff --git a/intern/cycles/render/session.cpp b/intern/cycles/render/session.cpp
index 9fcd9fa85f5..837c2694894 100644
--- a/intern/cycles/render/session.cpp
+++ b/intern/cycles/render/session.cpp
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#include <string.h>
@@ -20,13 +20,17 @@
#include "buffers.h"
#include "camera.h"
#include "device.h"
+#include "graph.h"
#include "integrator.h"
+#include "mesh.h"
+#include "object.h"
#include "scene.h"
#include "session.h"
#include "bake.h"
#include "util_foreach.h"
#include "util_function.h"
+#include "util_logging.h"
#include "util_math.h"
#include "util_opengl.h"
#include "util_task.h"
@@ -77,6 +81,9 @@ Session::Session(const SessionParams& params_)
gpu_need_tonemap = false;
pause = false;
kernels_loaded = false;
+
+ /* TODO(sergey): Check if it's indeed optimal value for the split kernel. */
+ max_closure_global = 1;
}
Session::~Session()
@@ -199,8 +206,7 @@ void Session::run_gpu()
paused_time = 0.0;
last_update_time = time_dt();
- if(!params.background)
- progress.set_start_time(start_time + paused_time);
+ progress.set_render_start_time(start_time + paused_time);
while(!progress.get_cancel()) {
/* advance to next tile */
@@ -233,6 +239,7 @@ void Session::run_gpu()
if(!params.background)
progress.set_start_time(start_time + paused_time);
+ progress.set_render_start_time(start_time + paused_time);
update_status_time(pause, no_tiles);
progress.set_update();
@@ -251,7 +258,7 @@ void Session::run_gpu()
update_scene();
if(!device->error_message().empty())
- progress.set_cancel(device->error_message());
+ progress.set_error(device->error_message());
if(progress.get_cancel())
break;
@@ -292,7 +299,7 @@ void Session::run_gpu()
}
if(!device->error_message().empty())
- progress.set_cancel(device->error_message());
+ progress.set_error(device->error_message());
tiles_written = update_progressive_refine(progress.get_cancel());
@@ -405,6 +412,11 @@ bool Session::acquire_tile(Device *tile_device, RenderTile& rtile)
if(tile_buffers.size() == 0)
tile_buffers.resize(tile_manager.state.num_tiles, NULL);
+ /* In certain circumstances number of tiles in the tile manager could
+ * be changed. This is not supported by the progressive refine feature.
+ */
+ assert(tile_buffers.size() == tile_manager.state.num_tiles);
+
tilebuffers = tile_buffers[tile.index];
if(tilebuffers == NULL) {
tilebuffers = new RenderBuffers(tile_device);
@@ -517,6 +529,7 @@ void Session::run_cpu()
if(!params.background)
progress.set_start_time(start_time + paused_time);
+ progress.set_render_start_time(start_time + paused_time);
update_status_time(pause, no_tiles);
progress.set_update();
@@ -540,7 +553,7 @@ void Session::run_cpu()
update_scene();
if(!device->error_message().empty())
- progress.set_cancel(device->error_message());
+ progress.set_error(device->error_message());
if(progress.get_cancel())
break;
@@ -558,7 +571,7 @@ void Session::run_cpu()
need_tonemap = true;
if(!device->error_message().empty())
- progress.set_cancel(device->error_message());
+ progress.set_error(device->error_message());
}
device->task_wait();
@@ -580,7 +593,7 @@ void Session::run_cpu()
}
if(!device->error_message().empty())
- progress.set_cancel(device->error_message());
+ progress.set_error(device->error_message());
tiles_written = update_progressive_refine(progress.get_cancel());
}
@@ -592,6 +605,45 @@ void Session::run_cpu()
update_progressive_refine(true);
}
+DeviceRequestedFeatures Session::get_requested_device_features()
+{
+ /* TODO(sergey): Consider moving this to the Scene level. */
+ DeviceRequestedFeatures requested_features;
+ requested_features.experimental = params.experimental;
+ if(!params.background) {
+ requested_features.max_closure = 64;
+ requested_features.max_nodes_group = NODE_GROUP_LEVEL_MAX;
+ requested_features.nodes_features = NODE_FEATURE_ALL;
+ }
+ else {
+ requested_features.max_closure = get_max_closure_count();
+ scene->shader_manager->get_requested_features(
+ scene,
+ requested_features.max_nodes_group,
+ requested_features.nodes_features);
+ }
+
+ /* This features are not being tweaked as often as shaders,
+ * so could be done selective magic for the viewport as well.
+ */
+ requested_features.use_hair = false;
+ requested_features.use_object_motion = false;
+ requested_features.use_camera_motion = scene->camera->use_motion;
+ foreach(Object *object, scene->objects) {
+ Mesh *mesh = object->mesh;
+ if(mesh->curves.size() > 0) {
+ requested_features.use_hair = true;
+ }
+ requested_features.use_object_motion |= object->use_motion | mesh->use_motion_blur;
+ requested_features.use_camera_motion |= mesh->use_motion_blur;
+ }
+
+ BakeManager *bake_manager = scene->bake_manager;
+ requested_features.use_baking = bake_manager->get_baking();
+
+ return requested_features;
+}
+
void Session::load_kernels()
{
thread_scoped_lock scene_lock(scene->mutex);
@@ -599,12 +651,14 @@ void Session::load_kernels()
if(!kernels_loaded) {
progress.set_status("Loading render kernels (may take a few minutes the first time)");
- if(!device->load_kernels(params.experimental)) {
+ DeviceRequestedFeatures requested_features = get_requested_device_features();
+ VLOG(2) << "Requested features:\n" << requested_features;
+ if(!device->load_kernels(requested_features)) {
string message = device->error_message();
if(message.empty())
message = "Failed loading render kernel, see console for errors";
- progress.set_cancel(message);
+ progress.set_error(message);
progress.set_status("Error", message);
progress.set_update();
return;
@@ -665,7 +719,8 @@ void Session::reset_(BufferParams& buffer_params, int samples)
paused_time = 0.0;
if(!params.background)
- progress.set_start_time(start_time + paused_time);
+ progress.set_start_time(start_time);
+ progress.set_render_start_time(start_time);
}
void Session::reset(BufferParams& buffer_params, int samples)
@@ -776,13 +831,21 @@ void Session::update_status_time(bool show_pause, bool show_done)
string status, substatus;
if(!params.progressive) {
- bool is_gpu = params.device.type == DEVICE_CUDA || params.device.type == DEVICE_OPENCL;
- bool is_multidevice = params.device.multi_devices.size() > 1;
- bool is_cpu = params.device.type == DEVICE_CPU;
+ const int progress_sample = progress.get_sample(), num_samples = tile_manager.num_samples;
+ const bool is_gpu = params.device.type == DEVICE_CUDA || params.device.type == DEVICE_OPENCL;
+ const bool is_multidevice = params.device.multi_devices.size() > 1;
+ const bool is_cpu = params.device.type == DEVICE_CPU;
+ const bool is_last_tile = (num_samples * num_tiles - progress_sample) < num_samples;
substatus = string_printf("Path Tracing Tile %d/%d", tile, num_tiles);
- if((is_gpu && !is_multidevice) || (is_cpu && num_tiles == 1)) {
+ if((is_gpu && !is_multidevice && !device->info.use_split_kernel) ||
+ (is_cpu && (num_tiles == 1 || is_last_tile)))
+ {
+ /* When using split-kernel (OpenCL) each thread in a tile will be working on a different
+ * sample. Can't display sample number when device uses split-kernel
+ */
+
/* when rendering on GPU multithreading happens within single tile, as in
* tiles are handling sequentially and in this case we could display
* currently rendering sample number
@@ -790,17 +853,21 @@ void Session::update_status_time(bool show_pause, bool show_done)
* also display the info on CPU, when using 1 tile only
*/
- int sample = progress.get_sample(), num_samples = tile_manager.num_samples;
-
+ int status_sample = progress_sample;
if(tile > 1) {
/* sample counter is global for all tiles, subtract samples
* from already finished tiles to get sample counter for
* current tile only
*/
- sample -= (tile - 1) * num_samples;
+ if(is_cpu && is_last_tile && num_tiles > 1) {
+ status_sample = num_samples - (num_samples * num_tiles - progress_sample);
+ }
+ else {
+ status_sample -= (tile - 1) * num_samples;
+ }
}
- substatus += string_printf(", Sample %d/%d", sample, num_samples);
+ substatus += string_printf(", Sample %d/%d", status_sample, num_samples);
}
}
else if(tile_manager.num_samples == USHRT_MAX)
@@ -850,6 +917,7 @@ void Session::path_trace()
task.update_progress_sample = function_bind(&Session::update_progress_sample, this);
task.need_finish_queue = params.progressive_refine;
task.integrator_branched = scene->integrator->method == Integrator::BRANCHED_PATH;
+ task.requested_tile_size = params.tile_size;
device->task_add(task);
}
@@ -887,9 +955,9 @@ bool Session::update_progressive_refine(bool cancel)
double current_time = time_dt();
- if (current_time - last_update_time < 1.0) {
+ if(current_time - last_update_time < params.progressive_update_timeout) {
/* if last sample was processed, we need to write buffers anyway */
- if (!write)
+ if(!write && sample != 1)
return false;
}
@@ -899,10 +967,14 @@ bool Session::update_progressive_refine(bool cancel)
rtile.buffers = buffers;
rtile.sample = sample;
- if(write)
- write_render_tile_cb(rtile);
- else
- update_render_tile_cb(rtile);
+ if(write) {
+ if(write_render_tile_cb)
+ write_render_tile_cb(rtile);
+ }
+ else {
+ if(update_render_tile_cb)
+ update_render_tile_cb(rtile);
+ }
}
}
@@ -925,4 +997,15 @@ void Session::device_free()
*/
}
+int Session::get_max_closure_count()
+{
+ int max_closures = 0;
+ for(int i = 0; i < scene->shaders.size(); i++) {
+ int num_closures = scene->shaders[i]->graph->get_num_closures();
+ max_closures = max(max_closures, num_closures);
+ }
+ max_closure_global = max(max_closure_global, max_closures);
+ return max_closure_global;
+}
+
CCL_NAMESPACE_END
diff --git a/intern/cycles/render/session.h b/intern/cycles/render/session.h
index 9da7a0aafa3..c669bccd34b 100644
--- a/intern/cycles/render/session.h
+++ b/intern/cycles/render/session.h
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#ifndef __SESSION_H__
@@ -32,6 +32,7 @@ CCL_NAMESPACE_BEGIN
class BufferParams;
class Device;
class DeviceScene;
+class DeviceRequestedFeatures;
class DisplayBuffer;
class Progress;
class RenderBuffers;
@@ -59,6 +60,7 @@ public:
double cancel_timeout;
double reset_timeout;
double text_timeout;
+ double progressive_update_timeout;
ShadingSystem shadingsystem;
@@ -80,6 +82,7 @@ public:
cancel_timeout = 0.1;
reset_timeout = 0.1;
text_timeout = 1.0;
+ progressive_update_timeout = 1.0;
shadingsystem = SHADINGSYSTEM_SVM;
tile_order = TILE_CENTER;
@@ -101,6 +104,7 @@ public:
&& cancel_timeout == params.cancel_timeout
&& reset_timeout == params.reset_timeout
&& text_timeout == params.text_timeout
+ && progressive_update_timeout == params.progressive_update_timeout
&& tile_order == params.tile_order
&& shadingsystem == params.shadingsystem); }
@@ -122,8 +126,8 @@ public:
TileManager tile_manager;
Stats stats;
- boost::function<void(RenderTile&)> write_render_tile_cb;
- boost::function<void(RenderTile&)> update_render_tile_cb;
+ function<void(RenderTile&)> write_render_tile_cb;
+ function<void(RenderTile&)> update_render_tile_cb;
Session(const SessionParams& params);
~Session();
@@ -201,6 +205,16 @@ protected:
bool update_progressive_refine(bool cancel);
vector<RenderBuffers *> tile_buffers;
+
+ DeviceRequestedFeatures get_requested_device_features();
+
+ /* ** Split kernel routines ** */
+
+ /* Maximumnumber of closure during session lifetime. */
+ int max_closure_global;
+
+ /* Get maximum number of closures to be used in kernel. */
+ int get_max_closure_count();
};
CCL_NAMESPACE_END
diff --git a/intern/cycles/render/shader.cpp b/intern/cycles/render/shader.cpp
index d76e511859a..aba3e7237d2 100644
--- a/intern/cycles/render/shader.cpp
+++ b/intern/cycles/render/shader.cpp
@@ -11,16 +11,18 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#include "background.h"
-#include "blackbody.h"
+#include "camera.h"
#include "device.h"
#include "graph.h"
+#include "integrator.h"
#include "light.h"
#include "mesh.h"
#include "nodes.h"
+#include "object.h"
#include "osl.h"
#include "scene.h"
#include "shader.h"
@@ -31,6 +33,8 @@
CCL_NAMESPACE_BEGIN
+vector<float> ShaderManager::beckmann_table;
+
/* Beckmann sampling precomputed table, see bsdf_microfacet.h */
/* 2D slope distribution (alpha = 1.0) */
@@ -83,7 +87,7 @@ static void beckmann_table_rows(float *table, int row_from, int row_to)
}
/* CDF of P22_{omega_i}(x_slope, 1, 1), Eq. (10) */
- CDF_P22_omega_i[index_slope_x] = CDF_P22_omega_i[index_slope_x - 1] + P22_omega_i;
+ CDF_P22_omega_i[index_slope_x] = CDF_P22_omega_i[index_slope_x - 1] + (double)P22_omega_i;
}
/* renormalize CDF_P22_omega_i */
@@ -106,8 +110,8 @@ static void beckmann_table_rows(float *table, int row_from, int row_to)
/* store value */
table[index_U + index_theta*BECKMANN_TABLE_SIZE] = (float)(
- interp * slope_x[index_slope_x - 1]
- + (1.0f-interp) * slope_x[index_slope_x]);
+ interp * slope_x[index_slope_x - 1] +
+ (1.0 - interp) * slope_x[index_slope_x]);
}
}
}
@@ -138,17 +142,18 @@ Shader::Shader()
use_mis = true;
use_transparent_shadow = true;
heterogeneous_volume = true;
- volume_sampling_method = 0;
+ volume_sampling_method = VOLUME_SAMPLING_DISTANCE;
+ volume_interpolation_method = VOLUME_INTERPOLATION_LINEAR;
has_surface = false;
has_surface_transparent = false;
has_surface_emission = false;
has_surface_bssrdf = false;
- has_converter_blackbody = false;
has_volume = false;
has_displacement = false;
has_bssrdf_bump = false;
has_heterogeneous_volume = false;
+ has_object_dependency = false;
used = false;
@@ -193,6 +198,7 @@ void Shader::tag_update(Scene *scene)
* e.g. surface attributes when there is only a volume shader. this could
* be more fine grained but it's better than nothing */
OutputNode *output = graph->output();
+ bool prev_has_volume = has_volume;
has_surface = has_surface || output->input("Surface")->link;
has_volume = has_volume || output->input("Volume")->link;
has_displacement = has_displacement || output->input("Displacement")->link;
@@ -214,6 +220,11 @@ void Shader::tag_update(Scene *scene)
need_update_attributes = true;
scene->mesh_manager->need_update = true;
}
+
+ if(has_volume != prev_has_volume) {
+ scene->mesh_manager->need_flags_update = true;
+ scene->object_manager->need_flags_update = true;
+ }
}
void Shader::tag_used(Scene *scene)
@@ -231,7 +242,6 @@ void Shader::tag_used(Scene *scene)
ShaderManager::ShaderManager()
{
need_update = true;
- blackbody_table_offset = TABLE_OFFSET_INVALID;
beckmann_table_offset = TABLE_OFFSET_INVALID;
}
@@ -243,6 +253,8 @@ ShaderManager *ShaderManager::create(Scene *scene, int shadingsystem)
{
ShaderManager *manager;
+ (void)shadingsystem; /* Ignored when built without OSL. */
+
#ifdef WITH_OSL
if(shadingsystem == SHADINGSYSTEM_OSL)
manager = new OSLShaderManager();
@@ -312,7 +324,10 @@ void ShaderManager::device_update_shaders_used(Scene *scene)
scene->shaders[light->shader]->used = true;
}
-void ShaderManager::device_update_common(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress)
+void ShaderManager::device_update_common(Device *device,
+ DeviceScene *dscene,
+ Scene *scene,
+ Progress& /*progress*/)
{
device->tex_free(dscene->shader_flag);
dscene->shader_flag.clear();
@@ -323,8 +338,8 @@ void ShaderManager::device_update_common(Device *device, DeviceScene *dscene, Sc
uint shader_flag_size = scene->shaders.size()*4;
uint *shader_flag = dscene->shader_flag.resize(shader_flag_size);
uint i = 0;
- bool has_converter_blackbody = false;
bool has_volumes = false;
+ bool has_transparent_shadow = false;
foreach(Shader *shader, scene->shaders) {
uint flag = 0;
@@ -342,20 +357,22 @@ void ShaderManager::device_update_common(Device *device, DeviceScene *dscene, Sc
flag |= SD_HAS_ONLY_VOLUME;
/* todo: this could check more fine grained, to skip useless volumes
- * enclosed inside an opaque bsdf, although we still need to handle
- * the case with camera inside volumes too */
+ * enclosed inside an opaque bsdf.
+ */
flag |= SD_HAS_TRANSPARENT_SHADOW;
}
if(shader->heterogeneous_volume && shader->has_heterogeneous_volume)
flag |= SD_HETEROGENEOUS_VOLUME;
if(shader->has_bssrdf_bump)
flag |= SD_HAS_BSSRDF_BUMP;
- if(shader->has_converter_blackbody)
- has_converter_blackbody = true;
- if(shader->volume_sampling_method == 1)
+ if(shader->volume_sampling_method == VOLUME_SAMPLING_EQUIANGULAR)
flag |= SD_VOLUME_EQUIANGULAR;
- if(shader->volume_sampling_method == 2)
+ if(shader->volume_sampling_method == VOLUME_SAMPLING_MULTIPLE_IMPORTANCE)
flag |= SD_VOLUME_MIS;
+ if(shader->volume_interpolation_method == VOLUME_INTERPOLATION_CUBIC)
+ flag |= SD_VOLUME_CUBIC;
+ if(shader->graph_bump)
+ flag |= SD_HAS_BUMP;
/* regular shader */
shader_flag[i++] = flag;
@@ -367,45 +384,38 @@ void ShaderManager::device_update_common(Device *device, DeviceScene *dscene, Sc
shader_flag[i++] = flag;
shader_flag[i++] = shader->pass_id;
+
+ has_transparent_shadow |= (flag & SD_HAS_TRANSPARENT_SHADOW);
}
device->tex_alloc("__shader_flag", dscene->shader_flag);
- /* blackbody lookup table */
+ /* lookup tables */
KernelTables *ktables = &dscene->data.tables;
-
- if(has_converter_blackbody && blackbody_table_offset == TABLE_OFFSET_INVALID) {
- vector<float> table = blackbody_table();
- blackbody_table_offset = scene->lookup_tables->add_table(dscene, table);
-
- ktables->blackbody_offset = (int)blackbody_table_offset;
- }
- else if(!has_converter_blackbody && blackbody_table_offset != TABLE_OFFSET_INVALID) {
- scene->lookup_tables->remove_table(blackbody_table_offset);
- blackbody_table_offset = TABLE_OFFSET_INVALID;
- }
/* beckmann lookup table */
if(beckmann_table_offset == TABLE_OFFSET_INVALID) {
- vector<float> table;
- beckmann_table_build(table);
- beckmann_table_offset = scene->lookup_tables->add_table(dscene, table);
-
+ if(beckmann_table.size() == 0) {
+ thread_scoped_lock lock(lookup_table_mutex);
+ if(beckmann_table.size() == 0) {
+ beckmann_table_build(beckmann_table);
+ }
+ }
+ beckmann_table_offset = scene->lookup_tables->add_table(dscene, beckmann_table);
ktables->beckmann_offset = (int)beckmann_table_offset;
}
/* integrator */
KernelIntegrator *kintegrator = &dscene->data.integrator;
kintegrator->use_volumes = has_volumes;
+ /* TODO(sergey): De-duplicate with flags set in integrator.cpp. */
+ if(scene->integrator->transparent_shadows) {
+ kintegrator->transparent_shadows = has_transparent_shadow;
+ }
}
void ShaderManager::device_free_common(Device *device, DeviceScene *dscene, Scene *scene)
{
- if(blackbody_table_offset != TABLE_OFFSET_INVALID) {
- scene->lookup_tables->remove_table(blackbody_table_offset);
- blackbody_table_offset = TABLE_OFFSET_INVALID;
- }
-
if(beckmann_table_offset != TABLE_OFFSET_INVALID) {
scene->lookup_tables->remove_table(beckmann_table_offset);
beckmann_table_offset = TABLE_OFFSET_INVALID;
@@ -479,5 +489,45 @@ void ShaderManager::add_default(Scene *scene)
}
}
+/* NOTE: Expects max_group and features to be initialized in the callee. */
+void ShaderManager::get_requested_graph_features(ShaderGraph *graph,
+ int& max_group,
+ int& features)
+{
+ foreach(ShaderNode *node, graph->nodes) {
+ max_group = max(max_group, node->get_group());
+ features |= node->get_feature();
+ if(node->special_type == SHADER_SPECIAL_TYPE_CLOSURE) {
+ BsdfNode *bsdf_node = static_cast<BsdfNode*>(node);
+ if(CLOSURE_IS_VOLUME(bsdf_node->closure)) {
+ features |= NODE_FEATURE_VOLUME;
+ }
+ }
+ }
+}
+
+void ShaderManager::get_requested_features(Scene *scene,
+ int& max_group,
+ int& features)
+{
+ max_group = NODE_GROUP_LEVEL_0;
+ features = 0;
+ for(int i = 0; i < scene->shaders.size(); i++) {
+ Shader *shader = scene->shaders[i];
+ /* Gather requested features from all the nodes from the graph nodes. */
+ get_requested_graph_features(shader->graph, max_group, features);
+ /* Gather requested features from the graph itself. */
+ if(shader->graph_bump) {
+ get_requested_graph_features(shader->graph_bump,
+ max_group,
+ features);
+ }
+ ShaderNode *output_node = shader->graph->output();
+ if(output_node->input("Displacement")->link != NULL) {
+ features |= NODE_FEATURE_BUMP;
+ }
+ }
+}
+
CCL_NAMESPACE_END
diff --git a/intern/cycles/render/shader.h b/intern/cycles/render/shader.h
index 0ed6d2ddf01..64d45635ef1 100644
--- a/intern/cycles/render/shader.h
+++ b/intern/cycles/render/shader.h
@@ -11,24 +11,34 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#ifndef __SHADER_H__
#define __SHADER_H__
+#ifdef WITH_OSL
+# if defined(_MSC_VER)
+/* Prevent OSL from polluting the context with weird macros from windows.h.
+ * TODO(sergey): Ideally it's only enough to have class/struct declarations in
+ * the header and skip header include here.
+ */
+# define NOGDI
+# define NOMINMAX
+# define WIN32_LEAN_AND_MEAN
+# endif
+# include <OSL/oslexec.h>
+#endif
+
#include "attribute.h"
#include "kernel_types.h"
#include "util_map.h"
#include "util_param.h"
#include "util_string.h"
+#include "util_thread.h"
#include "util_types.h"
-#ifdef WITH_OSL
-#include <OSL/oslexec.h>
-#endif
-
CCL_NAMESPACE_BEGIN
class Device;
@@ -44,6 +54,18 @@ enum ShadingSystem {
SHADINGSYSTEM_SVM
};
+/* Keep those in sync with the python-defined enum. */
+enum VolumeSampling {
+ VOLUME_SAMPLING_DISTANCE = 0,
+ VOLUME_SAMPLING_EQUIANGULAR = 1,
+ VOLUME_SAMPLING_MULTIPLE_IMPORTANCE = 2,
+};
+
+enum VolumeInterpolation {
+ VOLUME_INTERPOLATION_LINEAR = 0,
+ VOLUME_INTERPOLATION_CUBIC = 1,
+};
+
/* Shader describing the appearance of a Mesh, Light or Background.
*
* While there is only a single shader graph, it has three outputs: surface,
@@ -68,7 +90,8 @@ public:
bool use_mis;
bool use_transparent_shadow;
bool heterogeneous_volume;
- int volume_sampling_method;
+ VolumeSampling volume_sampling_method;
+ int volume_interpolation_method;
/* synchronization */
bool need_update;
@@ -81,9 +104,9 @@ public:
bool has_volume;
bool has_displacement;
bool has_surface_bssrdf;
- bool has_converter_blackbody;
bool has_bssrdf_bump;
bool has_heterogeneous_volume;
+ bool has_object_dependency;
/* requested mesh attributes */
AttributeRequestSet attributes;
@@ -142,14 +165,25 @@ public:
* have any shader assigned explicitly */
static void add_default(Scene *scene);
+ /* Selective nodes compilation. */
+ void get_requested_features(Scene *scene,
+ int& max_group,
+ int& features);
+
protected:
ShaderManager();
typedef unordered_map<ustring, uint, ustringHash> AttributeIDMap;
AttributeIDMap unique_attribute_id;
- size_t blackbody_table_offset;
+ thread_mutex lookup_table_mutex;
+ static vector<float> beckmann_table;
+
size_t beckmann_table_offset;
+
+ void get_requested_graph_features(ShaderGraph *graph,
+ int& max_group,
+ int& features);
};
CCL_NAMESPACE_END
diff --git a/intern/cycles/render/sky_model.cpp b/intern/cycles/render/sky_model.cpp
index adb07d9e288..c8a5dbe55e0 100644
--- a/intern/cycles/render/sky_model.cpp
+++ b/intern/cycles/render/sky_model.cpp
@@ -4,7 +4,7 @@ This source is published under the following 3-clause BSD license.
Copyright (c) 2012 - 2013, Lukas Hosek and Alexander Wilkie
All rights reserved.
-Redistribution and use in source and binary forms, with or without
+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
@@ -12,8 +12,8 @@ modification, are permitted provided that the following conditions are met:
* 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.
- * None of the names of the contributors may be used to endorse or promote
- products derived from this software without specific prior written
+ * None of the names of the 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
@@ -40,24 +40,24 @@ and the 2013 IEEE CG&A paper
"Adding a Solar Radiance Function to the Hosek Skylight Model"
- both by
+ both by
Lukas Hosek and Alexander Wilkie
Charles University in Prague, Czech Republic
Version: 1.4a, February 22nd, 2013
-
+
Version history:
1.4a February 22nd, 2013
- Removed unnecessary and counter-intuitive solar radius parameters
+ Removed unnecessary and counter-intuitive solar radius parameters
from the interface of the colourspace sky dome initialisation functions.
1.4 February 11th, 2013
Fixed a bug which caused the relative brightness of the solar disc
- and the sky dome to be off by a factor of about 6. The sun was too
- bright: this affected both normal and alien sun scenarios. The
+ and the sky dome to be off by a factor of about 6. The sun was too
+ bright: this affected both normal and alien sun scenarios. The
coefficients of the solar radiance function were changed to fix this.
1.3 January 21st, 2013 (not released to the public)
@@ -81,7 +81,7 @@ Version history:
the result of a simple conversion from spectral data via the CIE 2 degree
standard observer matching functions. Therefore, after multiplication
with 683 lm / W, the Y channel now corresponds to luminance in lm.
-
+
1.0 May 11th, 2012
Initial release.
@@ -110,7 +110,7 @@ CCL_NAMESPACE_BEGIN
// Some macro definitions that occur elsewhere in ART, and that have to be
// replicated to make this a stand-alone module.
-#ifndef MATH_PI
+#ifndef MATH_PI
#define MATH_PI 3.141592653589793
#endif
@@ -138,250 +138,231 @@ typedef const double *ArHosekSkyModel_Radiance_Dataset;
// internal functions
static void ArHosekSkyModel_CookConfiguration(
- ArHosekSkyModel_Dataset dataset,
- ArHosekSkyModelConfiguration config,
- double turbidity,
- double albedo,
- double solar_elevation
- )
+ ArHosekSkyModel_Dataset dataset,
+ ArHosekSkyModelConfiguration config,
+ double turbidity,
+ double albedo,
+ double solar_elevation)
{
- const double * elev_matrix;
-
- int int_turbidity = (int)turbidity;
- double turbidity_rem = turbidity - (double)int_turbidity;
-
- solar_elevation = pow(solar_elevation / (MATH_PI / 2.0), (1.0 / 3.0));
-
- // alb 0 low turb
-
- elev_matrix = dataset + ( 9 * 6 * (int_turbidity-1) );
-
-
- for( unsigned int i = 0; i < 9; ++i )
- {
- //(1-t).^3* A1 + 3*(1-t).^2.*t * A2 + 3*(1-t) .* t .^ 2 * A3 + t.^3 * A4;
- config[i] =
- (1.0-albedo) * (1.0 - turbidity_rem)
- * ( pow(1.0-solar_elevation, 5.0) * elev_matrix[i] +
- 5.0 * pow(1.0-solar_elevation, 4.0) * solar_elevation * elev_matrix[i+9] +
- 10.0*pow(1.0-solar_elevation, 3.0)*pow(solar_elevation, 2.0) * elev_matrix[i+18] +
- 10.0*pow(1.0-solar_elevation, 2.0)*pow(solar_elevation, 3.0) * elev_matrix[i+27] +
- 5.0*(1.0-solar_elevation)*pow(solar_elevation, 4.0) * elev_matrix[i+36] +
- pow(solar_elevation, 5.0) * elev_matrix[i+45]);
- }
+ const double * elev_matrix;
- // alb 1 low turb
- elev_matrix = dataset + (9*6*10 + 9*6*(int_turbidity-1));
- for(unsigned int i = 0; i < 9; ++i)
- {
- //(1-t).^3* A1 + 3*(1-t).^2.*t * A2 + 3*(1-t) .* t .^ 2 * A3 + t.^3 * A4;
- config[i] +=
- (albedo) * (1.0 - turbidity_rem)
- * ( pow(1.0-solar_elevation, 5.0) * elev_matrix[i] +
- 5.0 * pow(1.0-solar_elevation, 4.0) * solar_elevation * elev_matrix[i+9] +
- 10.0*pow(1.0-solar_elevation, 3.0)*pow(solar_elevation, 2.0) * elev_matrix[i+18] +
- 10.0*pow(1.0-solar_elevation, 2.0)*pow(solar_elevation, 3.0) * elev_matrix[i+27] +
- 5.0*(1.0-solar_elevation)*pow(solar_elevation, 4.0) * elev_matrix[i+36] +
- pow(solar_elevation, 5.0) * elev_matrix[i+45]);
- }
+ int int_turbidity = (int)turbidity;
+ double turbidity_rem = turbidity - (double)int_turbidity;
- if(int_turbidity == 10)
- return;
-
- // alb 0 high turb
- elev_matrix = dataset + (9*6*(int_turbidity));
- for(unsigned int i = 0; i < 9; ++i)
- {
- //(1-t).^3* A1 + 3*(1-t).^2.*t * A2 + 3*(1-t) .* t .^ 2 * A3 + t.^3 * A4;
- config[i] +=
- (1.0-albedo) * (turbidity_rem)
- * ( pow(1.0-solar_elevation, 5.0) * elev_matrix[i] +
- 5.0 * pow(1.0-solar_elevation, 4.0) * solar_elevation * elev_matrix[i+9] +
- 10.0*pow(1.0-solar_elevation, 3.0)*pow(solar_elevation, 2.0) * elev_matrix[i+18] +
- 10.0*pow(1.0-solar_elevation, 2.0)*pow(solar_elevation, 3.0) * elev_matrix[i+27] +
- 5.0*(1.0-solar_elevation)*pow(solar_elevation, 4.0) * elev_matrix[i+36] +
- pow(solar_elevation, 5.0) * elev_matrix[i+45]);
- }
+ solar_elevation = pow(solar_elevation / (MATH_PI / 2.0), (1.0 / 3.0));
+
+ // alb 0 low turb
- // alb 1 high turb
- elev_matrix = dataset + (9*6*10 + 9*6*(int_turbidity));
- for(unsigned int i = 0; i < 9; ++i)
- {
- //(1-t).^3* A1 + 3*(1-t).^2.*t * A2 + 3*(1-t) .* t .^ 2 * A3 + t.^3 * A4;
- config[i] +=
- (albedo) * (turbidity_rem)
- * ( pow(1.0-solar_elevation, 5.0) * elev_matrix[i] +
- 5.0 * pow(1.0-solar_elevation, 4.0) * solar_elevation * elev_matrix[i+9] +
- 10.0*pow(1.0-solar_elevation, 3.0)*pow(solar_elevation, 2.0) * elev_matrix[i+18] +
- 10.0*pow(1.0-solar_elevation, 2.0)*pow(solar_elevation, 3.0) * elev_matrix[i+27] +
- 5.0*(1.0-solar_elevation)*pow(solar_elevation, 4.0) * elev_matrix[i+36] +
- pow(solar_elevation, 5.0) * elev_matrix[i+45]);
+ elev_matrix = dataset + ( 9 * 6 * (int_turbidity-1));
+
+ for(unsigned int i = 0; i < 9; ++i) {
+ //(1-t).^3* A1 + 3*(1-t).^2.*t * A2 + 3*(1-t) .* t .^ 2 * A3 + t.^3 * A4;
+ config[i] =
+ (1.0-albedo) * (1.0 - turbidity_rem)
+ * ( pow(1.0-solar_elevation, 5.0) * elev_matrix[i] +
+ 5.0 * pow(1.0-solar_elevation, 4.0) * solar_elevation * elev_matrix[i+9] +
+ 10.0*pow(1.0-solar_elevation, 3.0)*pow(solar_elevation, 2.0) * elev_matrix[i+18] +
+ 10.0*pow(1.0-solar_elevation, 2.0)*pow(solar_elevation, 3.0) * elev_matrix[i+27] +
+ 5.0*(1.0-solar_elevation)*pow(solar_elevation, 4.0) * elev_matrix[i+36] +
+ pow(solar_elevation, 5.0) * elev_matrix[i+45]);
}
+
+ // alb 1 low turb
+ elev_matrix = dataset + (9*6*10 + 9*6*(int_turbidity-1));
+ for(unsigned int i = 0; i < 9; ++i) {
+ //(1-t).^3* A1 + 3*(1-t).^2.*t * A2 + 3*(1-t) .* t .^ 2 * A3 + t.^3 * A4;
+ config[i] +=
+ (albedo) * (1.0 - turbidity_rem)
+ * ( pow(1.0-solar_elevation, 5.0) * elev_matrix[i] +
+ 5.0 * pow(1.0-solar_elevation, 4.0) * solar_elevation * elev_matrix[i+9] +
+ 10.0*pow(1.0-solar_elevation, 3.0)*pow(solar_elevation, 2.0) * elev_matrix[i+18] +
+ 10.0*pow(1.0-solar_elevation, 2.0)*pow(solar_elevation, 3.0) * elev_matrix[i+27] +
+ 5.0*(1.0-solar_elevation)*pow(solar_elevation, 4.0) * elev_matrix[i+36] +
+ pow(solar_elevation, 5.0) * elev_matrix[i+45]);
+ }
+
+ if(int_turbidity == 10)
+ return;
+
+ // alb 0 high turb
+ elev_matrix = dataset + (9*6*(int_turbidity));
+ for(unsigned int i = 0; i < 9; ++i) {
+ //(1-t).^3* A1 + 3*(1-t).^2.*t * A2 + 3*(1-t) .* t .^ 2 * A3 + t.^3 * A4;
+ config[i] +=
+ (1.0-albedo) * (turbidity_rem)
+ * ( pow(1.0-solar_elevation, 5.0) * elev_matrix[i] +
+ 5.0 * pow(1.0-solar_elevation, 4.0) * solar_elevation * elev_matrix[i+9] +
+ 10.0*pow(1.0-solar_elevation, 3.0)*pow(solar_elevation, 2.0) * elev_matrix[i+18] +
+ 10.0*pow(1.0-solar_elevation, 2.0)*pow(solar_elevation, 3.0) * elev_matrix[i+27] +
+ 5.0*(1.0-solar_elevation)*pow(solar_elevation, 4.0) * elev_matrix[i+36] +
+ pow(solar_elevation, 5.0) * elev_matrix[i+45]);
+ }
+
+ // alb 1 high turb
+ elev_matrix = dataset + (9*6*10 + 9*6*(int_turbidity));
+ for(unsigned int i = 0; i < 9; ++i) {
+ //(1-t).^3* A1 + 3*(1-t).^2.*t * A2 + 3*(1-t) .* t .^ 2 * A3 + t.^3 * A4;
+ config[i] +=
+ (albedo) * (turbidity_rem)
+ * ( pow(1.0-solar_elevation, 5.0) * elev_matrix[i] +
+ 5.0 * pow(1.0-solar_elevation, 4.0) * solar_elevation * elev_matrix[i+9] +
+ 10.0*pow(1.0-solar_elevation, 3.0)*pow(solar_elevation, 2.0) * elev_matrix[i+18] +
+ 10.0*pow(1.0-solar_elevation, 2.0)*pow(solar_elevation, 3.0) * elev_matrix[i+27] +
+ 5.0*(1.0-solar_elevation)*pow(solar_elevation, 4.0) * elev_matrix[i+36] +
+ pow(solar_elevation, 5.0) * elev_matrix[i+45]);
+ }
}
static double ArHosekSkyModel_CookRadianceConfiguration(
- ArHosekSkyModel_Radiance_Dataset dataset,
- double turbidity,
- double albedo,
- double solar_elevation
- )
+ ArHosekSkyModel_Radiance_Dataset dataset,
+ double turbidity,
+ double albedo,
+ double solar_elevation)
{
- const double* elev_matrix;
-
- int int_turbidity = (int)turbidity;
- double turbidity_rem = turbidity - (double)int_turbidity;
- double res;
- solar_elevation = pow(solar_elevation / (MATH_PI / 2.0), (1.0 / 3.0));
-
- // alb 0 low turb
- elev_matrix = dataset + (6*(int_turbidity-1));
- //(1-t).^3* A1 + 3*(1-t).^2.*t * A2 + 3*(1-t) .* t .^ 2 * A3 + t.^3 * A4;
- res = (1.0-albedo) * (1.0 - turbidity_rem) *
- ( pow(1.0-solar_elevation, 5.0) * elev_matrix[0] +
- 5.0*pow(1.0-solar_elevation, 4.0)*solar_elevation * elev_matrix[1] +
- 10.0*pow(1.0-solar_elevation, 3.0)*pow(solar_elevation, 2.0) * elev_matrix[2] +
- 10.0*pow(1.0-solar_elevation, 2.0)*pow(solar_elevation, 3.0) * elev_matrix[3] +
- 5.0*(1.0-solar_elevation)*pow(solar_elevation, 4.0) * elev_matrix[4] +
- pow(solar_elevation, 5.0) * elev_matrix[5]);
-
- // alb 1 low turb
- elev_matrix = dataset + (6*10 + 6*(int_turbidity-1));
- //(1-t).^3* A1 + 3*(1-t).^2.*t * A2 + 3*(1-t) .* t .^ 2 * A3 + t.^3 * A4;
- res += (albedo) * (1.0 - turbidity_rem) *
- ( pow(1.0-solar_elevation, 5.0) * elev_matrix[0] +
- 5.0*pow(1.0-solar_elevation, 4.0)*solar_elevation * elev_matrix[1] +
- 10.0*pow(1.0-solar_elevation, 3.0)*pow(solar_elevation, 2.0) * elev_matrix[2] +
- 10.0*pow(1.0-solar_elevation, 2.0)*pow(solar_elevation, 3.0) * elev_matrix[3] +
- 5.0*(1.0-solar_elevation)*pow(solar_elevation, 4.0) * elev_matrix[4] +
- pow(solar_elevation, 5.0) * elev_matrix[5]);
- if(int_turbidity == 10)
- return res;
-
- // alb 0 high turb
- elev_matrix = dataset + (6*(int_turbidity));
- //(1-t).^3* A1 + 3*(1-t).^2.*t * A2 + 3*(1-t) .* t .^ 2 * A3 + t.^3 * A4;
- res += (1.0-albedo) * (turbidity_rem) *
- ( pow(1.0-solar_elevation, 5.0) * elev_matrix[0] +
- 5.0*pow(1.0-solar_elevation, 4.0)*solar_elevation * elev_matrix[1] +
- 10.0*pow(1.0-solar_elevation, 3.0)*pow(solar_elevation, 2.0) * elev_matrix[2] +
- 10.0*pow(1.0-solar_elevation, 2.0)*pow(solar_elevation, 3.0) * elev_matrix[3] +
- 5.0*(1.0-solar_elevation)*pow(solar_elevation, 4.0) * elev_matrix[4] +
- pow(solar_elevation, 5.0) * elev_matrix[5]);
-
- // alb 1 high turb
- elev_matrix = dataset + (6*10 + 6*(int_turbidity));
- //(1-t).^3* A1 + 3*(1-t).^2.*t * A2 + 3*(1-t) .* t .^ 2 * A3 + t.^3 * A4;
- res += (albedo) * (turbidity_rem) *
- ( pow(1.0-solar_elevation, 5.0) * elev_matrix[0] +
- 5.0*pow(1.0-solar_elevation, 4.0)*solar_elevation * elev_matrix[1] +
- 10.0*pow(1.0-solar_elevation, 3.0)*pow(solar_elevation, 2.0) * elev_matrix[2] +
- 10.0*pow(1.0-solar_elevation, 2.0)*pow(solar_elevation, 3.0) * elev_matrix[3] +
- 5.0*(1.0-solar_elevation)*pow(solar_elevation, 4.0) * elev_matrix[4] +
- pow(solar_elevation, 5.0) * elev_matrix[5]);
- return res;
+ const double* elev_matrix;
+
+ int int_turbidity = (int)turbidity;
+ double turbidity_rem = turbidity - (double)int_turbidity;
+ double res;
+ solar_elevation = pow(solar_elevation / (MATH_PI / 2.0), (1.0 / 3.0));
+
+ // alb 0 low turb
+ elev_matrix = dataset + (6*(int_turbidity-1));
+ //(1-t).^3* A1 + 3*(1-t).^2.*t * A2 + 3*(1-t) .* t .^ 2 * A3 + t.^3 * A4;
+ res = (1.0-albedo) * (1.0 - turbidity_rem) *
+ ( pow(1.0-solar_elevation, 5.0) * elev_matrix[0] +
+ 5.0*pow(1.0-solar_elevation, 4.0)*solar_elevation * elev_matrix[1] +
+ 10.0*pow(1.0-solar_elevation, 3.0)*pow(solar_elevation, 2.0) * elev_matrix[2] +
+ 10.0*pow(1.0-solar_elevation, 2.0)*pow(solar_elevation, 3.0) * elev_matrix[3] +
+ 5.0*(1.0-solar_elevation)*pow(solar_elevation, 4.0) * elev_matrix[4] +
+ pow(solar_elevation, 5.0) * elev_matrix[5]);
+
+ // alb 1 low turb
+ elev_matrix = dataset + (6*10 + 6*(int_turbidity-1));
+ //(1-t).^3* A1 + 3*(1-t).^2.*t * A2 + 3*(1-t) .* t .^ 2 * A3 + t.^3 * A4;
+ res += (albedo) * (1.0 - turbidity_rem) *
+ ( pow(1.0-solar_elevation, 5.0) * elev_matrix[0] +
+ 5.0*pow(1.0-solar_elevation, 4.0)*solar_elevation * elev_matrix[1] +
+ 10.0*pow(1.0-solar_elevation, 3.0)*pow(solar_elevation, 2.0) * elev_matrix[2] +
+ 10.0*pow(1.0-solar_elevation, 2.0)*pow(solar_elevation, 3.0) * elev_matrix[3] +
+ 5.0*(1.0-solar_elevation)*pow(solar_elevation, 4.0) * elev_matrix[4] +
+ pow(solar_elevation, 5.0) * elev_matrix[5]);
+ if(int_turbidity == 10)
+ return res;
+
+ // alb 0 high turb
+ elev_matrix = dataset + (6*(int_turbidity));
+ //(1-t).^3* A1 + 3*(1-t).^2.*t * A2 + 3*(1-t) .* t .^ 2 * A3 + t.^3 * A4;
+ res += (1.0-albedo) * (turbidity_rem) *
+ ( pow(1.0-solar_elevation, 5.0) * elev_matrix[0] +
+ 5.0*pow(1.0-solar_elevation, 4.0)*solar_elevation * elev_matrix[1] +
+ 10.0*pow(1.0-solar_elevation, 3.0)*pow(solar_elevation, 2.0) * elev_matrix[2] +
+ 10.0*pow(1.0-solar_elevation, 2.0)*pow(solar_elevation, 3.0) * elev_matrix[3] +
+ 5.0*(1.0-solar_elevation)*pow(solar_elevation, 4.0) * elev_matrix[4] +
+ pow(solar_elevation, 5.0) * elev_matrix[5]);
+
+ // alb 1 high turb
+ elev_matrix = dataset + (6*10 + 6*(int_turbidity));
+ //(1-t).^3* A1 + 3*(1-t).^2.*t * A2 + 3*(1-t) .* t .^ 2 * A3 + t.^3 * A4;
+ res += (albedo) * (turbidity_rem) *
+ ( pow(1.0-solar_elevation, 5.0) * elev_matrix[0] +
+ 5.0*pow(1.0-solar_elevation, 4.0)*solar_elevation * elev_matrix[1] +
+ 10.0*pow(1.0-solar_elevation, 3.0)*pow(solar_elevation, 2.0) * elev_matrix[2] +
+ 10.0*pow(1.0-solar_elevation, 2.0)*pow(solar_elevation, 3.0) * elev_matrix[3] +
+ 5.0*(1.0-solar_elevation)*pow(solar_elevation, 4.0) * elev_matrix[4] +
+ pow(solar_elevation, 5.0) * elev_matrix[5]);
+ return res;
}
static double ArHosekSkyModel_GetRadianceInternal(
- ArHosekSkyModelConfiguration configuration,
- double theta,
- double gamma
- )
+ ArHosekSkyModelConfiguration configuration,
+ double theta,
+ double gamma)
{
- const double expM = exp(configuration[4] * gamma);
- const double rayM = cos(gamma)*cos(gamma);
- const double mieM = (1.0 + cos(gamma)*cos(gamma)) / pow((1.0 + configuration[8]*configuration[8] - 2.0*configuration[8]*cos(gamma)), 1.5);
- const double zenith = sqrt(cos(theta));
+ const double expM = exp(configuration[4] * gamma);
+ const double rayM = cos(gamma)*cos(gamma);
+ const double mieM = (1.0 + cos(gamma)*cos(gamma)) / pow((1.0 + configuration[8]*configuration[8] - 2.0*configuration[8]*cos(gamma)), 1.5);
+ const double zenith = sqrt(cos(theta));
- return (1.0 + configuration[0] * exp(configuration[1] / (cos(theta) + 0.01))) *
+ return (1.0 + configuration[0] * exp(configuration[1] / (cos(theta) + 0.01))) *
(configuration[2] + configuration[3] * expM + configuration[5] * rayM + configuration[6] * mieM + configuration[7] * zenith);
}
-void arhosekskymodelstate_free(
- ArHosekSkyModelState * state
- )
+void arhosekskymodelstate_free(ArHosekSkyModelState * state)
{
- free(state);
+ free(state);
}
-double arhosekskymodel_radiance(
- ArHosekSkyModelState * state,
- double theta,
- double gamma,
- double wavelength
- )
+double arhosekskymodel_radiance(ArHosekSkyModelState *state,
+ double theta,
+ double gamma,
+ double wavelength)
{
- int low_wl = (int)((wavelength - 320.0) / 40.0);
-
- if ( low_wl < 0 || low_wl >= 11 )
- return 0.0f;
-
- double interp = fmod((wavelength - 320.0 ) / 40.0, 1.0);
-
- double val_low =
- ArHosekSkyModel_GetRadianceInternal(
- state->configs[low_wl],
- theta,
- gamma
- )
- * state->radiances[low_wl]
- * state->emission_correction_factor_sky[low_wl];
-
- if ( interp < 1e-6 )
- return val_low;
-
- double result = ( 1.0 - interp ) * val_low;
-
- if ( low_wl+1 < 11 )
- {
- result +=
- interp
- * ArHosekSkyModel_GetRadianceInternal(
- state->configs[low_wl+1],
- theta,
- gamma
- )
- * state->radiances[low_wl+1]
- * state->emission_correction_factor_sky[low_wl+1];
- }
-
- return result;
+ int low_wl = (int)((wavelength - 320.0) / 40.0);
+
+ if(low_wl < 0 || low_wl >= 11)
+ return 0.0f;
+
+ double interp = fmod((wavelength - 320.0 ) / 40.0, 1.0);
+
+ double val_low =
+ ArHosekSkyModel_GetRadianceInternal(
+ state->configs[low_wl],
+ theta,
+ gamma)
+ * state->radiances[low_wl]
+ * state->emission_correction_factor_sky[low_wl];
+
+ if(interp < 1e-6)
+ return val_low;
+
+ double result = ( 1.0 - interp ) * val_low;
+
+ if(low_wl+1 < 11) {
+ result +=
+ interp
+ * ArHosekSkyModel_GetRadianceInternal(
+ state->configs[low_wl+1],
+ theta,
+ gamma)
+ * state->radiances[low_wl+1]
+ * state->emission_correction_factor_sky[low_wl+1];
+ }
+
+ return result;
}
// xyz and rgb versions
-ArHosekSkyModelState * arhosek_xyz_skymodelstate_alloc_init(
- const double turbidity,
- const double albedo,
- const double elevation
- )
+ArHosekSkyModelState * arhosek_xyz_skymodelstate_alloc_init(
+ const double turbidity,
+ const double albedo,
+ const double elevation)
{
- ArHosekSkyModelState * state = ALLOC(ArHosekSkyModelState);
-
- state->solar_radius = TERRESTRIAL_SOLAR_RADIUS;
- state->turbidity = turbidity;
- state->albedo = albedo;
- state->elevation = elevation;
-
- for( unsigned int channel = 0; channel < 3; ++channel )
- {
- ArHosekSkyModel_CookConfiguration(
- datasetsXYZ[channel],
- state->configs[channel],
- turbidity,
- albedo,
- elevation
- );
-
- state->radiances[channel] =
- ArHosekSkyModel_CookRadianceConfiguration(
- datasetsXYZRad[channel],
- turbidity,
- albedo,
- elevation
- );
+ ArHosekSkyModelState * state = ALLOC(ArHosekSkyModelState);
+
+ state->solar_radius = TERRESTRIAL_SOLAR_RADIUS;
+ state->turbidity = turbidity;
+ state->albedo = albedo;
+ state->elevation = elevation;
+
+ for(unsigned int channel = 0; channel < 3; ++channel) {
+ ArHosekSkyModel_CookConfiguration(
+ datasetsXYZ[channel],
+ state->configs[channel],
+ turbidity,
+ albedo,
+ elevation);
+
+ state->radiances[channel] =
+ ArHosekSkyModel_CookRadianceConfiguration(
+ datasetsXYZRad[channel],
+ turbidity,
+ albedo,
+ elevation);
}
-
+
return state;
}
diff --git a/intern/cycles/render/sky_model.h b/intern/cycles/render/sky_model.h
index 3814543c8b6..237e4e61bf5 100644
--- a/intern/cycles/render/sky_model.h
+++ b/intern/cycles/render/sky_model.h
@@ -4,7 +4,7 @@ This source is published under the following 3-clause BSD license.
Copyright (c) 2012 - 2013, Lukas Hosek and Alexander Wilkie
All rights reserved.
-Redistribution and use in source and binary forms, with or without
+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
@@ -12,8 +12,8 @@ modification, are permitted provided that the following conditions are met:
* 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.
- * None of the names of the contributors may be used to endorse or promote
- products derived from this software without specific prior written
+ * None of the names of the 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
@@ -41,24 +41,24 @@ and the 2013 IEEE CG&A paper
"Adding a Solar Radiance Function to the Hosek Skylight Model"
- both by
+ both by
Lukas Hosek and Alexander Wilkie
Charles University in Prague, Czech Republic
Version: 1.4a, February 22nd, 2013
-
+
Version history:
1.4a February 22nd, 2013
- Removed unnecessary and counter-intuitive solar radius parameters
+ Removed unnecessary and counter-intuitive solar radius parameters
from the interface of the colourspace sky dome initialisation functions.
1.4 February 11th, 2013
Fixed a bug which caused the relative brightness of the solar disc
- and the sky dome to be off by a factor of about 6. The sun was too
- bright: this affected both normal and alien sun scenarios. The
+ and the sky dome to be off by a factor of about 6. The sun was too
+ bright: this affected both normal and alien sun scenarios. The
coefficients of the solar radiance function were changed to fix this.
1.3 January 21st, 2013 (not released to the public)
@@ -82,7 +82,7 @@ Version history:
the result of a simple conversion from spectral data via the CIE 2 degree
standard observer matching functions. Therefore, after multiplication
with 683 lm / W, the Y channel now corresponds to luminance in lm.
-
+
1.0 May 11th, 2012
Initial release.
@@ -96,9 +96,9 @@ an updated version of this code has been published!
/*
This code is taken from ART, a rendering research system written in a
-mix of C99 / Objective C. Since ART is not a small system and is intended to
-be inter-operable with other libraries, and since C does not have namespaces,
-the structures and functions in ART all have to have somewhat wordy
+mix of C99 / Objective C. Since ART is not a small system and is intended to
+be inter-operable with other libraries, and since C does not have namespaces,
+the structures and functions in ART all have to have somewhat wordy
canonical names that begin with Ar.../ar..., like those seen in this example.
Usage information:
@@ -119,7 +119,7 @@ snippet, we assume that 'albedo' is defined as
double albedo[num_channels];
-with a ground albedo value between [0,1] for each channel. The solar elevation
+with a ground albedo value between [0,1] for each channel. The solar elevation
is given in radians.
for ( unsigned int i = 0; i < num_channels; i++ )
@@ -130,11 +130,11 @@ is given in radians.
solarElevation
);
-Note that starting with version 1.3, there is also a second initialisation
-function which generates skydome states for different solar emission spectra
+Note that starting with version 1.3, there is also a second initialisation
+function which generates skydome states for different solar emission spectra
and solar radii: 'arhosekskymodelstate_alienworld_alloc_init()'.
-See the notes about the "Alien World" functionality provided further down for a
+See the notes about the "Alien World" functionality provided further down for a
discussion of the usefulness and limits of that second initalisation function.
Sky model states that have been initialized with either function behave in a
completely identical fashion during use and cleanup.
@@ -155,7 +155,7 @@ on the skydome determined via the angles theta and gamma works as follows:
gamma,
channel_center[i]
);
-
+
The variable "channel_center" is assumed to hold the channel center wavelengths
for each of the num_channels samples of the spectrum we are building.
@@ -188,114 +188,114 @@ by calling arhosek_rgb_skymodelstate_alloc_init.
Solar Radiance Function
-----------------------
-For each position on the solar disc, this function returns the entire radiance
-one sees - direct emission, as well as in-scattered light in the area of the
-solar disc. The latter is important for low solar elevations - nice images of
-the setting sun would not be possible without this. This is also the reason why
-this function, just like the regular sky dome model evaluation function, needs
-access to the sky dome data structures, as these provide information on
+For each position on the solar disc, this function returns the entire radiance
+one sees - direct emission, as well as in-scattered light in the area of the
+solar disc. The latter is important for low solar elevations - nice images of
+the setting sun would not be possible without this. This is also the reason why
+this function, just like the regular sky dome model evaluation function, needs
+access to the sky dome data structures, as these provide information on
in-scattered radiance.
CAVEAT #1: in this release, this function is only provided in spectral form!
RGB/XYZ versions to follow at a later date.
-CAVEAT #2: (fixed from release 1.3 onwards)
+CAVEAT #2: (fixed from release 1.3 onwards)
CAVEAT #3: limb darkening renders the brightness of the solar disc
inhomogeneous even for high solar elevations - only taking a single
sample at the centre of the sun will yield an incorrect power
estimate for the solar disc! Always take multiple random samples
across the entire solar disc to estimate its power!
-
+
CAVEAT #4: in this version, the limb darkening calculations still use a fairly
- computationally expensive 5th order polynomial that was directly
+ computationally expensive 5th order polynomial that was directly
taken from astronomical literature. For the purposes of Computer
- Graphics, this is needlessly accurate, though, and will be replaced
+ Graphics, this is needlessly accurate, though, and will be replaced
by a cheaper approximation in a future release.
"Alien World" functionality
---------------------------
-The Hosek sky model can be used to roughly (!) predict the appearance of
-outdoor scenes on earth-like planets, i.e. planets of a similar size and
-atmospheric make-up. Since the spectral version of our model predicts sky dome
-luminance patterns and solar radiance independently for each waveband, and
-since the intensity of each waveband is solely dependent on the input radiance
-from the star that the world in question is orbiting, it is trivial to re-scale
+The Hosek sky model can be used to roughly (!) predict the appearance of
+outdoor scenes on earth-like planets, i.e. planets of a similar size and
+atmospheric make-up. Since the spectral version of our model predicts sky dome
+luminance patterns and solar radiance independently for each waveband, and
+since the intensity of each waveband is solely dependent on the input radiance
+from the star that the world in question is orbiting, it is trivial to re-scale
the wavebands to match a different star radiance.
-At least in theory, the spectral version of the model has always been capable
-of this sort of thing, and the actual sky dome and solar radiance models were
+At least in theory, the spectral version of the model has always been capable
+of this sort of thing, and the actual sky dome and solar radiance models were
actually not altered at all in this release. All we did was to add some support
-functionality for doing this more easily with the existing data and functions,
+functionality for doing this more easily with the existing data and functions,
and to add some explanations.
Just use 'arhosekskymodelstate_alienworld_alloc_init()' to initialise the sky
-model states (you will have to provide values for star temperature and solar
-intensity compared to the terrestrial sun), and do everything else as you
+model states (you will have to provide values for star temperature and solar
+intensity compared to the terrestrial sun), and do everything else as you
did before.
-CAVEAT #1: we assume the emission of the star that illuminates the alien world
- to be a perfect blackbody emission spectrum. This is never entirely
- realistic - real star emission spectra are considerably more complex
- than this, mainly due to absorption effects in the outer layers of
- stars. However, blackbody spectra are a reasonable first assumption
- in a usage scenario like this, where 100% accuracy is simply not
- necessary: for rendering purposes, there are likely no visible
- differences between a highly accurate solution based on a more
+CAVEAT #1: we assume the emission of the star that illuminates the alien world
+ to be a perfect blackbody emission spectrum. This is never entirely
+ realistic - real star emission spectra are considerably more complex
+ than this, mainly due to absorption effects in the outer layers of
+ stars. However, blackbody spectra are a reasonable first assumption
+ in a usage scenario like this, where 100% accuracy is simply not
+ necessary: for rendering purposes, there are likely no visible
+ differences between a highly accurate solution based on a more
involved simulation, and this approximation.
CAVEAT #2: we always use limb darkening data from our own sun to provide this
- "appearance feature", even for suns of strongly different
- temperature. Which is presumably not very realistic, but (as with
- the unaltered blackbody spectrum from caveat #1) probably not a bad
+ "appearance feature", even for suns of strongly different
+ temperature. Which is presumably not very realistic, but (as with
+ the unaltered blackbody spectrum from caveat #1) probably not a bad
first guess, either. If you need more accuracy than we provide here,
please make inquiries with a friendly astro-physicst of your choice.
-CAVEAT #3: you have to provide a value for the solar intensity of the star
- which illuminates the alien world. For this, please bear in mind
- that there is very likely a comparatively tight range of absolute
- solar irradiance values for which an earth-like planet with an
- atmosphere like the one we assume in our model can exist in the
+CAVEAT #3: you have to provide a value for the solar intensity of the star
+ which illuminates the alien world. For this, please bear in mind
+ that there is very likely a comparatively tight range of absolute
+ solar irradiance values for which an earth-like planet with an
+ atmosphere like the one we assume in our model can exist in the
first place!
-
- Too much irradiance, and the atmosphere probably boils off into
- space, too little, it freezes. Which means that stars of
- considerably different emission colour than our sun will have to be
- fairly different in size from it, to still provide a reasonable and
- inhabitable amount of irradiance. Red stars will need to be much
- larger than our sun, while white or blue stars will have to be
- comparatively tiny. The initialisation function handles this and
+
+ Too much irradiance, and the atmosphere probably boils off into
+ space, too little, it freezes. Which means that stars of
+ considerably different emission colour than our sun will have to be
+ fairly different in size from it, to still provide a reasonable and
+ inhabitable amount of irradiance. Red stars will need to be much
+ larger than our sun, while white or blue stars will have to be
+ comparatively tiny. The initialisation function handles this and
computes a plausible solar radius for a given emission spectrum. In
terms of absolute radiometric values, you should probably not stray
all too far from a solar intensity value of 1.0.
-CAVEAT #4: although we now support different solar radii for the actual solar
- disc, the sky dome luminance patterns are *not* parameterised by
- this value - i.e. the patterns stay exactly the same for different
- solar radii! Which is of course not correct. But in our experience,
- solar discs up to several degrees in diameter (! - our own sun is
- half a degree across) do not cause the luminance patterns on the sky
- to change perceptibly. The reason we know this is that we initially
- used unrealistically large suns in our brute force path tracer, in
- order to improve convergence speeds (which in the beginning were
- abysmal). Later, we managed to do the reference renderings much
- faster even with realistically small suns, and found that there was
- no real difference in skydome appearance anyway.
- Conclusion: changing the solar radius should not be over-done, so
- close orbits around red supergiants are a no-no. But for the
- purposes of getting a fairly credible first impression of what an
- alien world with a reasonably sized sun would look like, what we are
+CAVEAT #4: although we now support different solar radii for the actual solar
+ disc, the sky dome luminance patterns are *not* parameterised by
+ this value - i.e. the patterns stay exactly the same for different
+ solar radii! Which is of course not correct. But in our experience,
+ solar discs up to several degrees in diameter (! - our own sun is
+ half a degree across) do not cause the luminance patterns on the sky
+ to change perceptibly. The reason we know this is that we initially
+ used unrealistically large suns in our brute force path tracer, in
+ order to improve convergence speeds (which in the beginning were
+ abysmal). Later, we managed to do the reference renderings much
+ faster even with realistically small suns, and found that there was
+ no real difference in skydome appearance anyway.
+ Conclusion: changing the solar radius should not be over-done, so
+ close orbits around red supergiants are a no-no. But for the
+ purposes of getting a fairly credible first impression of what an
+ alien world with a reasonably sized sun would look like, what we are
doing here is probably still o.k.
-HINT #1: if you want to model the sky of an earth-like planet that orbits
- a binary star, just super-impose two of these models with solar
+HINT #1: if you want to model the sky of an earth-like planet that orbits
+ a binary star, just super-impose two of these models with solar
intensity of ~0.5 each, and closely spaced solar positions. Light is
additive, after all. Tattooine, here we come... :-)
P.S. according to Star Wars canon, Tattooine orbits a binary
- that is made up of a G and K class star, respectively.
- So ~5500K and ~4200K should be good first guesses for their
+ that is made up of a G and K class star, respectively.
+ So ~5500K and ~4200K should be good first guesses for their
temperature. Just in case you were wondering, after reading the
previous paragraph.
*/
@@ -316,37 +316,37 @@ typedef double ArHosekSkyModelConfiguration[9];
---------------------------
This struct holds the pre-computation data for one particular albedo value.
- Most fields are self-explanatory, but users should never directly
- manipulate any of them anyway. The only consistent way to manipulate such
- structs is via the functions 'arhosekskymodelstate_alloc_init' and
+ Most fields are self-explanatory, but users should never directly
+ manipulate any of them anyway. The only consistent way to manipulate such
+ structs is via the functions 'arhosekskymodelstate_alloc_init' and
'arhosekskymodelstate_free'.
-
+
'emission_correction_factor_sky'
'emission_correction_factor_sun'
- The original model coefficients were fitted against the emission of
+ The original model coefficients were fitted against the emission of
our local sun. If a different solar emission is desired (i.e. if the
- model is being used to predict skydome appearance for an earth-like
- planet that orbits a different star), these correction factors, which
- are determined during the alloc_init step, are applied to each waveband
- separately (they default to 1.0 in normal usage). This is the simplest
- way to retrofit this sort of capability to the existing model. The
- different factors for sky and sun are needed since the solar disc may
+ model is being used to predict skydome appearance for an earth-like
+ planet that orbits a different star), these correction factors, which
+ are determined during the alloc_init step, are applied to each waveband
+ separately (they default to 1.0 in normal usage). This is the simplest
+ way to retrofit this sort of capability to the existing model. The
+ different factors for sky and sun are needed since the solar disc may
be of a different size compared to the terrestrial sun.
---------------------------------------------------------------------------- */
typedef struct ArHosekSkyModelState
{
- ArHosekSkyModelConfiguration configs[11];
- double radiances[11];
- double turbidity;
- double solar_radius;
- double emission_correction_factor_sky[11];
- double emission_correction_factor_sun[11];
- double albedo;
- double elevation;
-}
+ ArHosekSkyModelConfiguration configs[11];
+ double radiances[11];
+ double turbidity;
+ double solar_radius;
+ double emission_correction_factor_sky[11];
+ double emission_correction_factor_sun[11];
+ double albedo;
+ double elevation;
+}
ArHosekSkyModelState;
/* ----------------------------------------------------------------------------
@@ -358,11 +358,10 @@ ArHosekSkyModelState;
---------------------------------------------------------------------------- */
-ArHosekSkyModelState * arhosekskymodelstate_alloc_init(
- const double solar_elevation,
- const double atmospheric_turbidity,
- const double ground_albedo
- );
+ArHosekSkyModelState *arhosekskymodelstate_alloc_init(
+ const double solar_elevation,
+ const double atmospheric_turbidity,
+ const double ground_albedo);
/* ----------------------------------------------------------------------------
@@ -375,78 +374,67 @@ ArHosekSkyModelState * arhosekskymodelstate_alloc_init(
'solar_intensity' controls the overall brightness of the sky, relative
to the solar irradiance on Earth. A value of 1.0 yields a sky dome that
is, on average over the wavelenghts covered in the model (!), as bright
- as the terrestrial sky in radiometric terms.
-
- Which means that the solar radius has to be adjusted, since the
- emissivity of a solar surface with a given temperature is more or less
- fixed. So hotter suns have to be smaller to be equally bright as the
+ as the terrestrial sky in radiometric terms.
+
+ Which means that the solar radius has to be adjusted, since the
+ emissivity of a solar surface with a given temperature is more or less
+ fixed. So hotter suns have to be smaller to be equally bright as the
terrestrial sun, while cooler suns have to be larger. Note that there are
limits to the validity of the luminance patterns of the underlying model:
see the discussion above for more on this. In particular, an alien sun with
a surface temperature of only 2000 Kelvin has to be very large if it is
- to be as bright as the terrestrial sun - so large that the luminance
+ to be as bright as the terrestrial sun - so large that the luminance
patterns are no longer a really good fit in that case.
-
+
If you need information about the solar radius that the model computes
- for a given temperature (say, for light source sampling purposes), you
- have to query the 'solar_radius' variable of the sky model state returned
+ for a given temperature (say, for light source sampling purposes), you
+ have to query the 'solar_radius' variable of the sky model state returned
*after* running this function.
---------------------------------------------------------------------------- */
-ArHosekSkyModelState * arhosekskymodelstate_alienworld_alloc_init(
- const double solar_elevation,
- const double solar_intensity,
- const double solar_surface_temperature_kelvin,
- const double atmospheric_turbidity,
- const double ground_albedo
- );
-
-void arhosekskymodelstate_free(
- ArHosekSkyModelState * state
- );
-
-double arhosekskymodel_radiance(
- ArHosekSkyModelState * state,
- double theta,
- double gamma,
- double wavelength
- );
+ArHosekSkyModelState* arhosekskymodelstate_alienworld_alloc_init(
+ const double solar_elevation,
+ const double solar_intensity,
+ const double solar_surface_temperature_kelvin,
+ const double atmospheric_turbidity,
+ const double ground_albedo);
+
+void arhosekskymodelstate_free(ArHosekSkyModelState *state);
+
+double arhosekskymodel_radiance(ArHosekSkyModelState *state,
+ double theta,
+ double gamma,
+ double wavelength);
// CIE XYZ and RGB versions
ArHosekSkyModelState * arhosek_xyz_skymodelstate_alloc_init(
- const double turbidity,
- const double albedo,
- const double elevation
- );
+ const double turbidity,
+ const double albedo,
+ const double elevation);
ArHosekSkyModelState * arhosek_rgb_skymodelstate_alloc_init(
- const double turbidity,
- const double albedo,
- const double elevation
- );
+ const double turbidity,
+ const double albedo,
+ const double elevation);
-double arhosek_tristim_skymodel_radiance(
- ArHosekSkyModelState * state,
- double theta,
- double gamma,
- int channel
- );
+double arhosek_tristim_skymodel_radiance(ArHosekSkyModelState* state,
+ double theta,
+ double gamma,
+ int channel);
// Delivers the complete function: sky + sun, including limb darkening.
// Please read the above description before using this - there are several
// caveats!
-double arhosekskymodel_solar_radiance(
- ArHosekSkyModelState * state,
- double theta,
- double gamma,
- double wavelength
- );
+double arhosekskymodel_solar_radiance(ArHosekSkyModelState* state,
+ double theta,
+ double gamma,
+ double wavelength);
#endif // _SKY_MODEL_H_
diff --git a/intern/cycles/render/sky_model_data.h b/intern/cycles/render/sky_model_data.h
index 4171bd12756..e6f3f761532 100644
--- a/intern/cycles/render/sky_model_data.h
+++ b/intern/cycles/render/sky_model_data.h
@@ -4,7 +4,7 @@ This source is published under the following 3-clause BSD license.
Copyright (c) 2012 - 2013, Lukas Hosek and Alexander Wilkie
All rights reserved.
-Redistribution and use in source and binary forms, with or without
+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
@@ -12,8 +12,8 @@ modification, are permitted provided that the following conditions are met:
* 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.
- * None of the names of the contributors may be used to endorse or promote
- products derived from this software without specific prior written
+ * None of the names of the 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
@@ -41,24 +41,24 @@ and the 2013 IEEE CG&A paper
"Adding a Solar Radiance Function to the Hosek Skylight Model"
- both by
+ both by
Lukas Hosek and Alexander Wilkie
Charles University in Prague, Czech Republic
Version: 1.4a, February 22nd, 2013
-
+
Version history:
1.4a February 22nd, 2013
- Removed unnecessary and counter-intuitive solar radius parameters
+ Removed unnecessary and counter-intuitive solar radius parameters
from the interface of the colourspace sky dome initialisation functions.
1.4 February 11th, 2013
Fixed a bug which caused the relative brightness of the solar disc
- and the sky dome to be off by a factor of about 6. The sun was too
- bright: this affected both normal and alien sun scenarios. The
+ and the sky dome to be off by a factor of about 6. The sun was too
+ bright: this affected both normal and alien sun scenarios. The
coefficients of the solar radiance function were changed to fix this.
1.3 January 21st, 2013 (not released to the public)
@@ -82,7 +82,7 @@ Version history:
the result of a simple conversion from spectral data via the CIE 2 degree
standard observer matching functions. Therefore, after multiplication
with 683 lm / W, the Y channel now corresponds to luminance in lm.
-
+
1.0 May 11th, 2012
Initial release.
@@ -96,15 +96,14 @@ CCL_NAMESPACE_BEGIN
/*
-This file contains the coefficient data for the XYZ colour space version of
+This file contains the coefficient data for the XYZ colour space version of
the model.
*/
// Uses Sep 9 pattern / Aug 23 mean dataset
-static const double datasetXYZ1[] =
-{
+static const double datasetXYZ1[] = {
// albedo 0, turbidity 1
-1.117001e+000,
-1.867262e-001,
@@ -3849,15 +3848,13 @@ static const double datasetXYZRad3[] =
-static const double* datasetsXYZ[] =
-{
+static const double* datasetsXYZ[] = {
datasetXYZ1,
datasetXYZ2,
datasetXYZ3
};
-static const double* datasetsXYZRad[] =
-{
+static const double* datasetsXYZRad[] = {
datasetXYZRad1,
datasetXYZRad2,
datasetXYZRad3
diff --git a/intern/cycles/render/sobol.h b/intern/cycles/render/sobol.h
index b5eaa67db3e..574f148b9a2 100644
--- a/intern/cycles/render/sobol.h
+++ b/intern/cycles/render/sobol.h
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#ifndef __SOBOL_H__
diff --git a/intern/cycles/render/svm.cpp b/intern/cycles/render/svm.cpp
index 204c8fa2ce7..2dfa9fc98cc 100644
--- a/intern/cycles/render/svm.cpp
+++ b/intern/cycles/render/svm.cpp
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#include "camera.h"
@@ -26,6 +26,7 @@
#include "svm.h"
#include "util_debug.h"
+#include "util_logging.h"
#include "util_foreach.h"
#include "util_progress.h"
@@ -41,12 +42,14 @@ SVMShaderManager::~SVMShaderManager()
{
}
-void SVMShaderManager::reset(Scene *scene)
+void SVMShaderManager::reset(Scene * /*scene*/)
{
}
void SVMShaderManager::device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress)
{
+ VLOG(1) << "Total " << scene->shaders.size() << " shaders.";
+
if(!need_update)
return;
@@ -367,7 +370,7 @@ uint SVMCompiler::attribute(AttributeStandard std)
return shader_manager->get_attribute_id(std);
}
-bool SVMCompiler::node_skip_input(ShaderNode *node, ShaderInput *input)
+bool SVMCompiler::node_skip_input(ShaderNode * /*node*/, ShaderInput *input)
{
/* nasty exception .. */
if(current_type == SHADER_TYPE_DISPLACEMENT && input->link && input->link->parent->name == ustring("bump"))
@@ -403,9 +406,9 @@ void SVMCompiler::generate_node(ShaderNode *node, set<ShaderNode*>& done)
current_shader->has_heterogeneous_volume = true;
}
- /* detect if we have a blackbody converter, to prepare lookup table */
- if(node->has_converter_blackbody())
- current_shader->has_converter_blackbody = true;
+ if(node->has_object_dependency()) {
+ current_shader->has_object_dependency = true;
+ }
}
void SVMCompiler::generate_svm_nodes(const set<ShaderNode*>& nodes, set<ShaderNode*>& done)
@@ -752,10 +755,10 @@ void SVMCompiler::compile(Shader *shader, vector<int4>& global_svm_nodes, int in
shader->has_surface_transparent = false;
shader->has_surface_bssrdf = false;
shader->has_bssrdf_bump = false;
- shader->has_converter_blackbody = false;
shader->has_volume = false;
shader->has_displacement = false;
shader->has_heterogeneous_volume = false;
+ shader->has_object_dependency = false;
/* generate surface shader */
compile_type(shader, shader->graph, SHADER_TYPE_SURFACE);
diff --git a/intern/cycles/render/svm.h b/intern/cycles/render/svm.h
index 4a666bade55..239e9781cef 100644
--- a/intern/cycles/render/svm.h
+++ b/intern/cycles/render/svm.h
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#ifndef __SVM_H__
diff --git a/intern/cycles/render/tables.cpp b/intern/cycles/render/tables.cpp
index a8d502c432d..ad3f4866072 100644
--- a/intern/cycles/render/tables.cpp
+++ b/intern/cycles/render/tables.cpp
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#include "device.h"
@@ -19,6 +19,7 @@
#include "tables.h"
#include "util_debug.h"
+#include "util_logging.h"
CCL_NAMESPACE_BEGIN
@@ -36,6 +37,8 @@ LookupTables::~LookupTables()
void LookupTables::device_update(Device *device, DeviceScene *dscene)
{
+ VLOG(1) << "Total " << lookup_tables.size() << " lookup tables.";
+
if(!need_update)
return;
diff --git a/intern/cycles/render/tables.h b/intern/cycles/render/tables.h
index 059940cbeb6..4efa09fa3c1 100644
--- a/intern/cycles/render/tables.h
+++ b/intern/cycles/render/tables.h
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#ifndef __TABLES_H__
diff --git a/intern/cycles/render/tile.cpp b/intern/cycles/render/tile.cpp
index d6094a4fa0a..7e68ce84d94 100644
--- a/intern/cycles/render/tile.cpp
+++ b/intern/cycles/render/tile.cpp
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#include "tile.h"
@@ -28,6 +28,7 @@ TileManager::TileManager(bool progressive_, int num_samples_, int2 tile_size_, i
tile_size = tile_size_;
tile_order = tile_order_;
start_resolution = start_resolution_;
+ num_samples = num_samples_;
num_devices = num_devices_;
preserve_tile_device = preserve_tile_device_;
background = background_;
@@ -200,8 +201,8 @@ list<Tile>::iterator TileManager::next_background_tile(int device, TileOrder til
switch (tile_order) {
case TILE_CENTER:
- distx = centx - (cur_tile.x + cur_tile.w);
- disty = centy - (cur_tile.y + cur_tile.h);
+ distx = centx - (cur_tile.x + (cur_tile.w / 2));
+ disty = centy - (cur_tile.y + (cur_tile.h / 2));
distx = (int64_t)sqrt((double)(distx * distx + disty * disty));
break;
case TILE_RIGHT_TO_LEFT:
@@ -234,7 +235,7 @@ bool TileManager::next_tile(Tile& tile, int device)
{
list<Tile>::iterator tile_it;
- if (background)
+ if(background)
tile_it = next_background_tile(device, tile_order);
else
tile_it = next_viewport_tile(device);
diff --git a/intern/cycles/render/tile.h b/intern/cycles/render/tile.h
index 7796518b6bc..c9bdc86f029 100644
--- a/intern/cycles/render/tile.h
+++ b/intern/cycles/render/tile.h
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#ifndef __TILE_H__
diff --git a/intern/cycles/subd/subd_dice.cpp b/intern/cycles/subd/subd_dice.cpp
index 05ff5ca4b65..44bab066dde 100644
--- a/intern/cycles/subd/subd_dice.cpp
+++ b/intern/cycles/subd/subd_dice.cpp
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#include "camera.h"
@@ -117,8 +117,8 @@ void EdgeDice::stitch_triangles(Patch *patch, vector<int>& outer, vector<int>& i
}
else {
/* length of diagonals */
- float len1 = len(mesh_P[inner[i]] - mesh_P[outer[j+1]]);
- float len2 = len(mesh_P[outer[j]] - mesh_P[inner[i+1]]);
+ float len1 = len_squared(mesh_P[inner[i]] - mesh_P[outer[j+1]]);
+ float len2 = len_squared(mesh_P[outer[j]] - mesh_P[inner[i+1]]);
/* use smallest diagonal */
if(len1 < len2)
diff --git a/intern/cycles/subd/subd_dice.h b/intern/cycles/subd/subd_dice.h
index 9cf5b0d50b8..b7e61748779 100644
--- a/intern/cycles/subd/subd_dice.h
+++ b/intern/cycles/subd/subd_dice.h
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#ifndef __SUBD_DICE_H__
diff --git a/intern/cycles/subd/subd_mesh.cpp b/intern/cycles/subd/subd_mesh.cpp
index 0db20656f39..17a730e5efe 100644
--- a/intern/cycles/subd/subd_mesh.cpp
+++ b/intern/cycles/subd/subd_mesh.cpp
@@ -109,8 +109,8 @@ public:
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]);
+ 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? */
@@ -234,7 +234,7 @@ bool OpenSubdMesh::finish()
void OpenSubdMesh::tessellate(DiagSplit *split)
{
- if (num_ptex_faces == 0)
+ if(num_ptex_faces == 0)
return;
const int level = 3;
diff --git a/intern/cycles/subd/subd_patch.cpp b/intern/cycles/subd/subd_patch.cpp
index fe9fa791813..0db46ec492d 100644
--- a/intern/cycles/subd/subd_patch.cpp
+++ b/intern/cycles/subd/subd_patch.cpp
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
/* Parts adapted from code in the public domain in NVidia Mesh Tools. */
diff --git a/intern/cycles/subd/subd_patch.h b/intern/cycles/subd/subd_patch.h
index 48f35d78711..9be4606c248 100644
--- a/intern/cycles/subd/subd_patch.h
+++ b/intern/cycles/subd/subd_patch.h
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#ifndef __SUBD_PATCH_H__
diff --git a/intern/cycles/subd/subd_split.cpp b/intern/cycles/subd/subd_split.cpp
index 6bbf4af3f85..df4d451e8eb 100644
--- a/intern/cycles/subd/subd_split.cpp
+++ b/intern/cycles/subd/subd_split.cpp
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#include "camera.h"
diff --git a/intern/cycles/subd/subd_split.h b/intern/cycles/subd/subd_split.h
index 3f9a2721977..df4935ee624 100644
--- a/intern/cycles/subd/subd_split.h
+++ b/intern/cycles/subd/subd_split.h
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#ifndef __SUBD_SPLIT_H__
diff --git a/intern/cycles/util/CMakeLists.txt b/intern/cycles/util/CMakeLists.txt
index 6120e7e8456..0acb9e9304c 100644
--- a/intern/cycles/util/CMakeLists.txt
+++ b/intern/cycles/util/CMakeLists.txt
@@ -1,16 +1,16 @@
set(INC
.
+ ../../glew-mx
)
set(INC_SYS
- ${GLEW_INCLUDE_PATH}
- ${OPENGL_INCLUDE_DIR}
+ ${GLEW_INCLUDE_DIR}
)
set(SRC
+ util_aligned_malloc.cpp
util_cache.cpp
- util_dynlib.cpp
util_logging.cpp
util_md5.cpp
util_path.cpp
@@ -22,6 +22,10 @@ set(SRC
util_transform.cpp
)
+if(NOT CYCLES_STANDALONE_REPOSITORY)
+ add_definitions(-DWITH_GLEW_MX)
+endif()
+
if(WITH_CYCLES_STANDALONE AND WITH_CYCLES_STANDALONE_GUI)
list(APPEND SRC
util_view.cpp
@@ -30,11 +34,12 @@ endif()
set(SRC_HEADERS
util_algorithm.h
+ util_aligned_malloc.h
util_args.h
+ util_atomic.h
util_boundbox.h
util_cache.h
util_debug.h
- util_dynlib.h
util_foreach.h
util_function.h
util_half.h
@@ -44,6 +49,7 @@ set(SRC_HEADERS
util_logging.h
util_map.h
util_math.h
+ util_math_fast.h
util_md5.h
util_opengl.h
util_optimization.h
@@ -68,7 +74,18 @@ set(SRC_HEADERS
util_xml.h
)
+if(WITH_CYCLES_DEBUG)
+ list(APPEND SRC
+ util_guarded_allocator.cpp
+ )
+ list(APPEND SRC_HEADERS
+ util_guarded_allocator.h
+ )
+endif()
+
include_directories(${INC})
include_directories(SYSTEM ${INC_SYS})
+add_definitions(${GL_DEFINITIONS})
+
add_library(cycles_util ${SRC} ${SRC_HEADERS})
diff --git a/intern/cycles/util/util_algorithm.h b/intern/cycles/util/util_algorithm.h
index 5865f3f04bb..5c79c00cc98 100644
--- a/intern/cycles/util/util_algorithm.h
+++ b/intern/cycles/util/util_algorithm.h
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#ifndef __UTIL_ALGORITHM_H__
diff --git a/intern/cycles/util/util_aligned_malloc.cpp b/intern/cycles/util/util_aligned_malloc.cpp
new file mode 100644
index 00000000000..b161a55c15e
--- /dev/null
+++ b/intern/cycles/util/util_aligned_malloc.cpp
@@ -0,0 +1,83 @@
+/*
+ * Copyright 2011-2015 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 "util_aligned_malloc.h"
+#include "util_guarded_allocator.h"
+
+#include <cassert>
+
+/* Adopted from Libmv. */
+
+#if !defined(__APPLE__) && !defined(__FreeBSD__) && !defined(__NetBSD__)
+/* Needed for memalign on Linux and _aligned_alloc on Windows. */
+# ifdef FREE_WINDOWS
+/* Make sure _aligned_malloc is included. */
+# ifdef __MSVCRT_VERSION__
+# undef __MSVCRT_VERSION__
+# endif
+# define __MSVCRT_VERSION__ 0x0700
+# endif /* FREE_WINDOWS */
+# include <malloc.h>
+#else
+/* Apple's malloc is 16-byte aligned, and does not have malloc.h, so include
+ * stdilb instead.
+ */
+# include <cstdlib>
+#endif
+
+CCL_NAMESPACE_BEGIN
+
+void *util_aligned_malloc(size_t size, int alignment)
+{
+#ifdef WITH_BLENDER_GUARDEDALLOC
+ return MEM_mallocN_aligned(size, alignment, "Cycles Aligned Alloc");
+#endif
+#ifdef _WIN32
+ return _aligned_malloc(size, alignment);
+#elif defined(__APPLE__)
+ /* On Mac OS X, both the heap and the stack are guaranteed 16-byte aligned so
+ * they work natively with SSE types with no further work.
+ */
+ assert(alignment == 16);
+ return malloc(size);
+#elif defined(__FreeBSD__) || defined(__NetBSD__)
+ void *result;
+ if(posix_memalign(&result, alignment, size)) {
+ /* Non-zero means allocation error
+ * either no allocation or bad alignment value.
+ */
+ return NULL;
+ }
+ return result;
+#else /* This is for Linux. */
+ return memalign(alignment, size);
+#endif
+}
+
+void util_aligned_free(void *ptr)
+{
+#if defined(WITH_BLENDER_GUARDEDALLOC)
+ if(ptr != NULL) {
+ MEM_freeN(ptr);
+ }
+#elif defined(_WIN32)
+ _aligned_free(ptr);
+#else
+ free(ptr);
+#endif
+}
+
+CCL_NAMESPACE_END
diff --git a/intern/cycles/util/util_aligned_malloc.h b/intern/cycles/util/util_aligned_malloc.h
new file mode 100644
index 00000000000..ecc0f28c376
--- /dev/null
+++ b/intern/cycles/util/util_aligned_malloc.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2011-2015 Blender Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __UTIL_ALIGNED_MALLOC_H__
+#define __UTIL_ALIGNED_MALLOC_H__
+
+#include "util_types.h"
+
+CCL_NAMESPACE_BEGIN
+
+/* Allocate block of size bytes at least aligned to a given value. */
+void *util_aligned_malloc(size_t size, int alignment);
+
+/* Free memory allocated by util_aligned_malloc. */
+void util_aligned_free(void *ptr);
+
+CCL_NAMESPACE_END
+
+#endif /* __UTIL_ALIGNED_MALLOC_H__ */
diff --git a/intern/cycles/util/util_args.h b/intern/cycles/util/util_args.h
index 55933c895bf..a53fc061758 100644
--- a/intern/cycles/util/util_args.h
+++ b/intern/cycles/util/util_args.h
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#ifndef __UTIL_ARGS_H__
diff --git a/intern/cycles/util/util_atomic.h b/intern/cycles/util/util_atomic.h
new file mode 100644
index 00000000000..1d1e2963348
--- /dev/null
+++ b/intern/cycles/util/util_atomic.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2014 Blender Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __UTIL_ATOMIC_H__
+#define __UTIL_ATOMIC_H__
+
+#ifndef __KERNEL_GPU__
+
+/* Using atomic ops header from Blender. */
+#include "atomic_ops.h"
+
+ATOMIC_INLINE void atomic_update_max_z(size_t *maximum_value, size_t value)
+{
+ size_t prev_value = *maximum_value;
+ while(prev_value < value) {
+ if(atomic_cas_z(maximum_value, prev_value, value) != prev_value) {
+ break;
+ }
+ }
+}
+
+#else /* __KERNEL_GPU__ */
+
+#ifdef __KERNEL_OPENCL__
+
+/* Float atomics implementation credits:
+ * http://suhorukov.blogspot.in/2011/12/opencl-11-atomic-operations-on-floating.html
+ */
+ccl_device_inline void atomic_add_float(volatile ccl_global float *source,
+ const float operand)
+{
+ union {
+ unsigned int int_value;
+ float float_value;
+ } new_value;
+ union {
+ unsigned int int_value;
+ float float_value;
+ } prev_value;
+ do {
+ prev_value.float_value = *source;
+ new_value.float_value = prev_value.float_value + operand;
+ } while(atomic_cmpxchg((volatile ccl_global unsigned int *)source,
+ prev_value.int_value,
+ new_value.int_value) != prev_value.int_value);
+}
+
+#endif /* __KERNEL_OPENCL__ */
+
+#endif /* __KERNEL_GPU__ */
+
+#endif /* __UTIL_ATOMIC_H__ */
diff --git a/intern/cycles/util/util_boundbox.h b/intern/cycles/util/util_boundbox.h
index a71e0399619..cef5adc0a61 100644
--- a/intern/cycles/util/util_boundbox.h
+++ b/intern/cycles/util/util_boundbox.h
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#ifndef __UTIL_BOUNDBOX_H__
diff --git a/intern/cycles/util/util_cache.cpp b/intern/cycles/util/util_cache.cpp
index e20c3a67b75..5eebfb18155 100644
--- a/intern/cycles/util/util_cache.cpp
+++ b/intern/cycles/util/util_cache.cpp
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#include <stdio.h>
@@ -24,12 +24,6 @@
#include "util_path.h"
#include "util_types.h"
-#include <boost/version.hpp>
-
-#if (BOOST_VERSION < 104400)
-# define BOOST_FILESYSTEM_VERSION 2
-#endif
-
#include <boost/filesystem.hpp>
#include <boost/algorithm/string.hpp>
diff --git a/intern/cycles/util/util_cache.h b/intern/cycles/util/util_cache.h
index bfb2877a22b..343fa36817d 100644
--- a/intern/cycles/util/util_cache.h
+++ b/intern/cycles/util/util_cache.h
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#ifndef __UTIL_CACHE_H__
@@ -105,7 +105,7 @@ public:
return false;
}
- if(!size)
+ if((size == 0) || (size % sizeof(T)) != 0)
return false;
data.resize(size/sizeof(T));
diff --git a/intern/cycles/util/util_color.h b/intern/cycles/util/util_color.h
index 53b3d72de67..d3598f84b94 100644
--- a/intern/cycles/util/util_color.h
+++ b/intern/cycles/util/util_color.h
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#ifndef __UTIL_COLOR_H__
diff --git a/intern/cycles/util/util_debug.h b/intern/cycles/util/util_debug.h
index 79fac506b98..6b61a49fcc3 100644
--- a/intern/cycles/util/util_debug.h
+++ b/intern/cycles/util/util_debug.h
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#ifndef __UTIL_DEBUG_H__
diff --git a/intern/cycles/util/util_dynlib.cpp b/intern/cycles/util/util_dynlib.cpp
deleted file mode 100644
index 587cad607c8..00000000000
--- a/intern/cycles/util/util_dynlib.cpp
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * Copyright 2011-2013 Blender Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-#include <stdlib.h>
-
-#include "util_dynlib.h"
-
-#ifdef _WIN32
-
-#include <windows.h>
-
-CCL_NAMESPACE_BEGIN
-
-struct DynamicLibrary {
- HMODULE module;
-};
-
-DynamicLibrary *dynamic_library_open(const char *name)
-{
- HMODULE module = LoadLibrary(name);
-
- if(!module)
- return NULL;
-
- DynamicLibrary *lib = new DynamicLibrary();
- lib->module = module;
-
- return lib;
-}
-
-void *dynamic_library_find(DynamicLibrary *lib, const char *name)
-{
- return (void*)GetProcAddress(lib->module, name);
-}
-
-void dynamic_library_close(DynamicLibrary *lib)
-{
- FreeLibrary(lib->module);
- delete lib;
-}
-
-CCL_NAMESPACE_END
-
-#else
-
-#include <dlfcn.h>
-
-CCL_NAMESPACE_BEGIN
-
-struct DynamicLibrary {
- void *module;
-};
-
-DynamicLibrary *dynamic_library_open(const char *name)
-{
- void *module = dlopen(name, RTLD_NOW);
-
- if(!module)
- return NULL;
-
- DynamicLibrary *lib = new DynamicLibrary();
- lib->module = module;
-
- return lib;
-}
-
-void *dynamic_library_find(DynamicLibrary *lib, const char *name)
-{
- return dlsym(lib->module, name);
-}
-
-void dynamic_library_close(DynamicLibrary *lib)
-{
- dlclose(lib->module);
- delete lib;
-}
-
-CCL_NAMESPACE_END
-
-#endif
-
diff --git a/intern/cycles/util/util_foreach.h b/intern/cycles/util/util_foreach.h
index df3277fbf37..4f7337107b3 100644
--- a/intern/cycles/util/util_foreach.h
+++ b/intern/cycles/util/util_foreach.h
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#ifndef __UTIL_FOREACH_H__
@@ -19,8 +19,12 @@
/* Use Boost to get nice foreach() loops for STL data structures. */
-#include <boost/foreach.hpp>
-#define foreach BOOST_FOREACH
+#if (__cplusplus > 199711L) || (defined(_MSC_VER) && _MSC_VER >= 1800)
+# define foreach(x, y) for(x : y)
+#else
+# include <boost/foreach.hpp>
+# define foreach BOOST_FOREACH
+#endif
#endif /* __UTIL_FOREACH_H__ */
diff --git a/intern/cycles/util/util_function.h b/intern/cycles/util/util_function.h
index 6aa014a08a6..6d0f0b444a9 100644
--- a/intern/cycles/util/util_function.h
+++ b/intern/cycles/util/util_function.h
@@ -11,20 +11,39 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#ifndef __UTIL_FUNCTION_H__
#define __UTIL_FUNCTION_H__
-#include <boost/bind.hpp>
-#include <boost/function.hpp>
+#if (__cplusplus > 199711L) || (defined(_MSC_VER) && _MSC_VER >= 1800)
+# include <functional>
+#else
+# include <boost/bind.hpp>
+# include <boost/function.hpp>
+#endif
CCL_NAMESPACE_BEGIN
+#if (__cplusplus > 199711L) || (defined(_MSC_VER) && _MSC_VER >= 1800)
+# define function_bind std::bind
+# define function_null nullptr
+using std::function;
+using std::placeholders::_1;
+using std::placeholders::_2;
+using std::placeholders::_3;
+using std::placeholders::_4;
+using std::placeholders::_5;
+using std::placeholders::_6;
+using std::placeholders::_7;
+using std::placeholders::_8;
+using std::placeholders::_9;
+#else
using boost::function;
-#define function_bind boost::bind
-
+# define function_bind boost::bind
+# define function_null NULL
+#endif
CCL_NAMESPACE_END
#endif /* __UTIL_FUNCTION_H__ */
diff --git a/intern/cycles/util/util_guarded_allocator.cpp b/intern/cycles/util/util_guarded_allocator.cpp
new file mode 100644
index 00000000000..8de6e254cbf
--- /dev/null
+++ b/intern/cycles/util/util_guarded_allocator.cpp
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2011-2015 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 "util_guarded_allocator.h"
+#include "util_stats.h"
+
+CCL_NAMESPACE_BEGIN
+
+static Stats global_stats;
+
+/* Internal API. */
+
+void util_guarded_mem_alloc(size_t n)
+{
+ global_stats.mem_alloc(n);
+}
+
+void util_guarded_mem_free(size_t n)
+{
+ global_stats.mem_free(n);
+}
+
+/* Public API. */
+
+size_t util_guarded_get_mem_used(void)
+{
+ return global_stats.mem_used;
+}
+
+size_t util_guarded_get_mem_peak(void)
+{
+ return global_stats.mem_peak;
+}
+
+
+CCL_NAMESPACE_END
diff --git a/intern/cycles/util/util_guarded_allocator.h b/intern/cycles/util/util_guarded_allocator.h
new file mode 100644
index 00000000000..2df717253e3
--- /dev/null
+++ b/intern/cycles/util/util_guarded_allocator.h
@@ -0,0 +1,86 @@
+/*
+ * Copyright 2011-2015 Blender Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __UTIL_GUARDED_ALLOCATOR_H__
+#define __UTIL_GUARDED_ALLOCATOR_H__
+
+/* Define this in order to use Blender's guarded allocator to keep
+ * track of allocated buffers, their sizes and peak memory usage.
+ *
+ * This is usually a bad level call, but it's really handy to keep
+ * track of overall peak memory consumption during the scene
+ * synchronization step.
+ */
+#undef WITH_BLENDER_GUARDEDALLOC
+
+#include <memory>
+
+#include "util_types.h"
+
+#ifdef WITH_BLENDER_GUARDEDALLOC
+# include "../../guardedalloc/MEM_guardedalloc.h"
+#endif
+
+CCL_NAMESPACE_BEGIN
+
+/* Internal use only. */
+void util_guarded_mem_alloc(size_t n);
+void util_guarded_mem_free(size_t n);
+
+/* Guarded allocator for the use with STL. */
+template <typename T>
+class GuardedAllocator : public std::allocator<T> {
+public:
+ template<typename _Tp1>
+ struct rebind {
+ typedef GuardedAllocator<_Tp1> other;
+ };
+
+ T *allocate(size_t n, const void *hint = 0)
+ {
+ util_guarded_mem_alloc(n * sizeof(T));
+#ifdef WITH_BLENDER_GUARDEDALLOC
+ (void)hint;
+ return (T*)MEM_mallocN_aligned(n * sizeof(T), 16, "Cycles Alloc");
+#else
+ return std::allocator<T>::allocate(n, hint);
+#endif
+ }
+
+ void deallocate(T *p, size_t n)
+ {
+ util_guarded_mem_free(n * sizeof(T));
+#ifdef WITH_BLENDER_GUARDEDALLOC
+ MEM_freeN((void*)p);
+#else
+ std::allocator<T>::deallocate(p, n);
+#endif
+ }
+
+ GuardedAllocator() : std::allocator<T>() { }
+ GuardedAllocator(const GuardedAllocator &a) : std::allocator<T>(a) { }
+ template <class U>
+ GuardedAllocator(const GuardedAllocator<U> &a) : std::allocator<T>(a) { }
+ ~GuardedAllocator() { }
+};
+
+/* Get memory usage and peak from the guarded STL allocator. */
+size_t util_guarded_get_mem_used(void);
+size_t util_guarded_get_mem_peak(void);
+
+CCL_NAMESPACE_END
+
+#endif /* __UTIL_GUARDED_ALLOCATOR_H__ */
diff --git a/intern/cycles/util/util_half.h b/intern/cycles/util/util_half.h
index 397133618be..f4bac9888a5 100644
--- a/intern/cycles/util/util_half.h
+++ b/intern/cycles/util/util_half.h
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#ifndef __UTIL_HALF_H__
@@ -56,7 +56,7 @@ ccl_device_inline void float4_store_half(half *h, float4 f, float scale)
* assumes no negative, no nan, no inf, and sets denormal to 0 */
union { uint i; float f; } in;
float fscale = f[i] * scale;
- in.f = (fscale > 0.0f)? ((fscale < 65500.0f)? fscale: 65500.0f): 0.0f;
+ in.f = (fscale > 0.0f)? ((fscale < 65504.0f)? fscale: 65504.0f): 0.0f;
int x = in.i;
int absolute = x & 0x7FFFFFFF;
@@ -68,20 +68,20 @@ ccl_device_inline void float4_store_half(half *h, float4 f, float scale)
}
#else
/* same as above with SSE */
- const ssef mm_scale = ssef(scale);
- const ssei mm_38800000 = ssei(0x38800000);
- const ssei mm_7FFF = ssei(0x7FFF);
- const ssei mm_7FFFFFFF = ssei(0x7FFFFFFF);
- const ssei mm_C8000000 = ssei(0xC8000000);
-
- ssef mm_fscale = load4f(f) * mm_scale;
- ssei x = cast(min(max(mm_fscale, ssef(0.0f)), ssef(65500.0f)));
- ssei absolute = x & mm_7FFFFFFF;
- ssei Z = absolute + mm_C8000000;
- ssei result = andnot(absolute < mm_38800000, Z);
- ssei rh = (result >> 13) & mm_7FFF;
-
- _mm_storel_pi((__m64*)h, _mm_castsi128_ps(_mm_packs_epi32(rh, rh)));
+ ssef fscale = load4f(f) * scale;
+ ssef x = min(max(fscale, 0.0f), 65504.0f);
+
+#ifdef __KERNEL_AVX2__
+ ssei rpack = _mm_cvtps_ph(x, 0);
+#else
+ ssei absolute = cast(x) & 0x7FFFFFFF;
+ ssei Z = absolute + 0xC8000000;
+ ssei result = andnot(absolute < 0x38800000, Z);
+ ssei rshift = (result >> 13) & 0x7FFF;
+ ssei rpack = _mm_packs_epi32(rshift, rshift);
+#endif
+
+ _mm_storel_pi((__m64*)h, _mm_castsi128_ps(rpack));
#endif
}
diff --git a/intern/cycles/util/util_hash.h b/intern/cycles/util/util_hash.h
index edd2448efa4..3ff2802b46d 100644
--- a/intern/cycles/util/util_hash.h
+++ b/intern/cycles/util/util_hash.h
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#ifndef __UTIL_HASH_H__
@@ -53,7 +53,7 @@ static inline uint hash_string(const char *str)
{
uint i = 0, c;
- while ((c = *str++))
+ while((c = *str++))
i = i * 37 + c;
return i;
diff --git a/intern/cycles/util/util_image.h b/intern/cycles/util/util_image.h
index 4b8140e7a7a..bb8a31c6fec 100644
--- a/intern/cycles/util/util_image.h
+++ b/intern/cycles/util/util_image.h
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#ifndef __UTIL_IMAGE_H__
diff --git a/intern/cycles/util/util_list.h b/intern/cycles/util/util_list.h
index 2aa0b7381e3..6cb27e6defe 100644
--- a/intern/cycles/util/util_list.h
+++ b/intern/cycles/util/util_list.h
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#ifndef __UTIL_LIST_H__
diff --git a/intern/cycles/util/util_logging.cpp b/intern/cycles/util/util_logging.cpp
index 0722f16cf45..03041723e15 100644
--- a/intern/cycles/util/util_logging.cpp
+++ b/intern/cycles/util/util_logging.cpp
@@ -11,15 +11,63 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#include <util_logging.h>
#include "util_math.h"
+#include <stdio.h>
+#ifdef _MSC_VER
+# define snprintf _snprintf
+#endif
+
CCL_NAMESPACE_BEGIN
+void util_logging_init(const char *argv0)
+{
+#ifdef WITH_CYCLES_LOGGING
+ using CYCLES_GFLAGS_NAMESPACE::SetCommandLineOption;
+
+ /* Make it so FATAL messages are always print into console. */
+ char severity_fatal[32];
+ snprintf(severity_fatal, sizeof(severity_fatal), "%d",
+ google::GLOG_FATAL);
+
+ google::InitGoogleLogging(argv0);
+ SetCommandLineOption("logtostderr", "1");
+ SetCommandLineOption("v", "0");
+ SetCommandLineOption("stderrthreshold", severity_fatal);
+ SetCommandLineOption("minloglevel", severity_fatal);
+#else
+ (void) argv0;
+#endif
+}
+
+void util_logging_start(void)
+{
+#ifdef WITH_CYCLES_LOGGING
+ using CYCLES_GFLAGS_NAMESPACE::SetCommandLineOption;
+ SetCommandLineOption("logtostderr", "1");
+ SetCommandLineOption("v", "2");
+ SetCommandLineOption("stderrthreshold", "1");
+ SetCommandLineOption("minloglevel", "0");
+#endif
+}
+
+void util_logging_verbosity_set(int verbosity)
+{
+#ifdef WITH_CYCLES_LOGGING
+ using CYCLES_GFLAGS_NAMESPACE::SetCommandLineOption;
+ char val[10];
+ snprintf(val, sizeof(val), "%d", verbosity);
+ SetCommandLineOption("v", val);
+#else
+ (void) verbosity;
+#endif
+}
+
std::ostream& operator <<(std::ostream &os,
const float3 &value)
{
diff --git a/intern/cycles/util/util_logging.h b/intern/cycles/util/util_logging.h
index 991789e7460..7fc42ac355a 100644
--- a/intern/cycles/util/util_logging.h
+++ b/intern/cycles/util/util_logging.h
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#ifndef __UTIL_LOGGING_H__
@@ -43,7 +43,11 @@ public:
#endif
-class float3;
+struct float3;
+
+void util_logging_init(const char *argv0);
+void util_logging_start(void);
+void util_logging_verbosity_set(int verbosity);
std::ostream& operator <<(std::ostream &os,
const float3 &value);
diff --git a/intern/cycles/util/util_map.h b/intern/cycles/util/util_map.h
index 77500e4712d..46c2885f8b0 100644
--- a/intern/cycles/util/util_map.h
+++ b/intern/cycles/util/util_map.h
@@ -11,20 +11,45 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#ifndef __UTIL_MAP_H__
#define __UTIL_MAP_H__
#include <map>
-#include <boost/tr1/unordered_map.hpp>
+
+#if defined(CYCLES_TR1_UNORDERED_MAP)
+# include <tr1/unordered_map>
+#endif
+
+#if defined(CYCLES_STD_UNORDERED_MAP) || defined(CYCLES_STD_UNORDERED_MAP_IN_TR1_NAMESPACE)
+# include <unordered_map>
+#endif
+
+#if !defined(CYCLES_NO_UNORDERED_MAP) && !defined(CYCLES_TR1_UNORDERED_MAP) && \
+ !defined(CYCLES_STD_UNORDERED_MAP) && !defined(CYCLES_STD_UNORDERED_MAP_IN_TR1_NAMESPACE) // NOLINT
+# error One of: CYCLES_NO_UNORDERED_MAP, CYCLES_TR1_UNORDERED_MAP,\
+ CYCLES_STD_UNORDERED_MAP, CYCLES_STD_UNORDERED_MAP_IN_TR1_NAMESPACE must be defined! // NOLINT
+#endif
+
CCL_NAMESPACE_BEGIN
using std::map;
using std::pair;
+
+#if defined(CYCLES_NO_UNORDERED_MAP)
+typedef std::map unordered_map;
+#endif
+
+#if defined(CYCLES_TR1_UNORDERED_MAP) || defined(CYCLES_STD_UNORDERED_MAP_IN_TR1_NAMESPACE)
using std::tr1::unordered_map;
+#endif
+
+#if defined(CYCLES_STD_UNORDERED_MAP)
+using std::unordered_map;
+#endif
CCL_NAMESPACE_END
diff --git a/intern/cycles/util/util_math.h b/intern/cycles/util/util_math.h
index c332e1709db..7d6dfd34e0e 100644
--- a/intern/cycles/util/util_math.h
+++ b/intern/cycles/util/util_math.h
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#ifndef __UTIL_MATH_H__
@@ -71,6 +71,13 @@ CCL_NAMESPACE_BEGIN
#define M_SQRT2_F ((float)1.41421356237309504880) /* sqrt(2) */
#endif
+#ifndef M_LN2_F
+#define M_LN2_F ((float)0.6931471805599453) /* ln(2) */
+#endif
+
+#ifndef M_LN10_F
+#define M_LN10_F ((float)2.3025850929940457) /* ln(10) */
+#endif
/* Scalar */
@@ -124,6 +131,24 @@ ccl_device_inline double min(double a, double b)
return (a < b)? a: b;
}
+/* These 2 guys are templated for usage with registers data.
+ *
+ * NOTE: Since this is CPU-only functions it is ok to use references here.
+ * But for other devices we'll need to be careful about this.
+ */
+
+template<typename T>
+ccl_device_inline T min4(const T& a, const T& b, const T& c, const T& d)
+{
+ return min(min(a,b),min(c,d));
+}
+
+template<typename T>
+ccl_device_inline T max4(const T& a, const T& b, const T& c, const T& d)
+{
+ return max(max(a,b),max(c,d));
+}
+
#endif
ccl_device_inline float min4(float a, float b, float c, float d)
@@ -150,6 +175,15 @@ ccl_device_inline float clamp(float a, float mn, float mx)
#endif
+#ifndef __KERNEL_CUDA__
+
+ccl_device_inline float saturate(float a)
+{
+ return clamp(a, 0.0f, 1.0f);
+}
+
+#endif
+
ccl_device_inline int float_to_int(float f)
{
return (int)f;
@@ -314,6 +348,12 @@ ccl_device_inline float2 normalize_len(const float2 a, float *t)
return a/(*t);
}
+ccl_device_inline float2 safe_normalize(const float2 a)
+{
+ float t = len(a);
+ return (t)? a/t: a;
+}
+
ccl_device_inline bool operator==(const float2 a, const float2 b)
{
return (a.x == b.x && a.y == b.y);
@@ -510,6 +550,12 @@ ccl_device_inline float3 normalize_len(const float3 a, float *t)
return a/(*t);
}
+ccl_device_inline float3 safe_normalize(const float3 a)
+{
+ float t = len(a);
+ return (t)? a/t: a;
+}
+
#ifndef __KERNEL_OPENCL__
ccl_device_inline bool operator==(const float3 a, const float3 b)
@@ -817,6 +863,12 @@ ccl_device_inline float4 normalize(const float4 a)
return a/len(a);
}
+ccl_device_inline float4 safe_normalize(const float4 a)
+{
+ float t = len(a);
+ return (t)? a/t: a;
+}
+
ccl_device_inline float4 min(float4 a, float4 b)
{
#ifdef __KERNEL_SSE__
@@ -1395,10 +1447,9 @@ ccl_device bool ray_triangle_intersect_uv(
return true;
}
-ccl_device bool ray_quad_intersect(
- float3 ray_P, float3 ray_D, float ray_t,
- float3 quad_P, float3 quad_u, float3 quad_v,
- float3 *isect_P, float *isect_t)
+ccl_device bool ray_quad_intersect(float3 ray_P, float3 ray_D, float ray_t,
+ float3 quad_P, float3 quad_u, float3 quad_v,
+ float3 *isect_P, float *isect_t)
{
float3 v0 = quad_P - quad_u*0.5f - quad_v*0.5f;
float3 v1 = quad_P + quad_u*0.5f - quad_v*0.5f;
@@ -1414,23 +1465,52 @@ ccl_device bool ray_quad_intersect(
}
/* projections */
-ccl_device bool map_to_sphere(float *r_u, float *r_v,
- const float x, const float y, const float z)
+ccl_device_inline float2 map_to_tube(const float3 co)
{
- float len = sqrtf(x * x + y * y + z * z);
+ float len, u, v;
+ len = sqrtf(co.x * co.x + co.y * co.y);
if(len > 0.0f) {
- if(UNLIKELY(x == 0.0f && y == 0.0f)) {
- *r_u = 0.0f; /* othwise domain error */
+ u = (1.0f - (atan2f(co.x / len, co.y / len) / M_PI_F)) * 0.5f;
+ v = (co.z + 1.0f) * 0.5f;
+ }
+ else {
+ u = v = 0.0f;
+ }
+ return make_float2(u, v);
+}
+
+ccl_device_inline float2 map_to_sphere(const float3 co)
+{
+ float l = len(co);
+ float u, v;
+ if(l > 0.0f) {
+ if(UNLIKELY(co.x == 0.0f && co.y == 0.0f)) {
+ u = 0.0f; /* othwise domain error */
}
else {
- *r_u = (1.0f - atan2f(x, y) / M_PI_F) / 2.0f;
+ u = (1.0f - atan2f(co.x, co.y) / M_PI_F) / 2.0f;
}
- *r_v = 1.0f - safe_acosf(z / len) / M_PI_F;
- return true;
+ v = 1.0f - safe_acosf(co.z / l) / M_PI_F;
}
else {
- *r_v = *r_u = 0.0f; /* to avoid un-initialized variables */
- return false;
+ u = v = 0.0f;
+ }
+ return make_float2(u, v);
+}
+
+ccl_device_inline int util_max_axis(float3 vec)
+{
+ if(vec.x > vec.y) {
+ if(vec.x > vec.z)
+ return 0;
+ else
+ return 2;
+ }
+ else {
+ if(vec.y > vec.z)
+ return 1;
+ else
+ return 2;
}
}
diff --git a/intern/cycles/util/util_math_fast.h b/intern/cycles/util/util_math_fast.h
new file mode 100644
index 00000000000..c1a1be603f4
--- /dev/null
+++ b/intern/cycles/util/util_math_fast.h
@@ -0,0 +1,611 @@
+/*
+ * Adapted from OpenImageIO library with this license:
+ *
+ * Copyright 2008-2014 Larry Gritz and the other authors and contributors.
+ * All Rights Reserved.
+
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of the software's owners 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.
+ *
+ * (This is the Modified BSD License)
+ *
+ * A few bits here are based upon code from NVIDIA that was also released
+ * under the same modified BSD license, and marked as:
+ * Copyright 2004 NVIDIA Corporation. All Rights Reserved.
+ *
+ * Some parts of this file were first open-sourced in Open Shading Language,
+ * then later moved here. The original copyright notice was:
+ * Copyright (c) 2009-2014 Sony Pictures Imageworks Inc., et al.
+ *
+ * Many of the math functions were copied from or inspired by other
+ * public domain sources or open source packages with compatible licenses.
+ * The individual functions give references were applicable.
+ */
+
+#ifndef __UTIL_FAST_MATH__
+#define __UTIL_FAST_MATH__
+
+CCL_NAMESPACE_BEGIN
+
+/* TODO(sergey): Make sure it does not conflict with SSE intrinsics. */
+ccl_device_inline float madd(const float a, const float b, const float c)
+{
+ /* NOTE: In the future we may want to explicitly ask for a fused
+ * multiply-add in a specialized version for float.
+ *
+ * NOTE: GCC/ICC will turn this (for float) into a FMA unless
+ * explicitly asked not to, clang seems to leave the code alone.
+ */
+ return a * b + c;
+}
+
+/*
+ * FAST & APPROXIMATE MATH
+ *
+ * The functions named "fast_*" provide a set of replacements to libm that
+ * are much faster at the expense of some accuracy and robust handling of
+ * extreme values. One design goal for these approximation was to avoid
+ * branches as much as possible and operate on single precision values only
+ * so that SIMD versions should be straightforward ports We also try to
+ * implement "safe" semantics (ie: clamp to valid range where possible)
+ * natively since wrapping these inline calls in another layer would be
+ * wasteful.
+ *
+ * Some functions are fast_safe_*, which is both a faster approximation as
+ * well as clamped input domain to ensure no NaN, Inf, or divide by zero.
+ */
+
+/* Round to nearest integer, returning as an int. */
+ccl_device_inline int fast_rint(float x)
+{
+ /* used by sin/cos/tan range reduction. */
+#ifdef __KERNEL_SSE4__
+ /* Single roundps instruction on SSE4.1+ (for gcc/clang at least). */
+ return float_to_int(rintf(x));
+#else
+ /* emulate rounding by adding/substracting 0.5. */
+ return float_to_int(x + copysignf(0.5f, x));
+#endif
+}
+
+ccl_device float fast_sinf(float x)
+{
+ /* Very accurate argument reduction from SLEEF,
+ * starts failing around x=262000
+ *
+ * Results on: [-2pi,2pi].
+ *
+ * Examined 2173837240 values of sin: 0.00662760244 avg ulp diff, 2 max ulp,
+ * 1.19209e-07 max error
+ */
+ int q = fast_rint(x * M_1_PI_F);
+ float qf = q;
+ x = madd(qf, -0.78515625f*4, x);
+ x = madd(qf, -0.00024187564849853515625f*4, x);
+ x = madd(qf, -3.7747668102383613586e-08f*4, x);
+ x = madd(qf, -1.2816720341285448015e-12f*4, x);
+ x = M_PI_2_F - (M_PI_2_F - x); /* Crush denormals */
+ float s = x * x;
+ if((q & 1) != 0) x = -x;
+ /* This polynomial approximation has very low error on [-pi/2,+pi/2]
+ * 1.19209e-07 max error in total over [-2pi,+2pi]. */
+ float u = 2.6083159809786593541503e-06f;
+ u = madd(u, s, -0.0001981069071916863322258f);
+ u = madd(u, s, +0.00833307858556509017944336f);
+ u = madd(u, s, -0.166666597127914428710938f);
+ u = madd(s, u * x, x);
+ /* For large x, the argument reduction can fail and the polynomial can be
+ * evaluated with arguments outside the valid internal. Just clamp the bad
+ * values away (setting to 0.0f means no branches need to be generated). */
+ if(fabsf(u) > 1.0f) {
+ u = 0.0f;
+ }
+ return u;
+}
+
+ccl_device float fast_cosf(float x)
+{
+ /* Same argument reduction as fast_sinf(). */
+ int q = fast_rint(x * M_1_PI_F);
+ float qf = q;
+ x = madd(qf, -0.78515625f*4, x);
+ x = madd(qf, -0.00024187564849853515625f*4, x);
+ x = madd(qf, -3.7747668102383613586e-08f*4, x);
+ x = madd(qf, -1.2816720341285448015e-12f*4, x);
+ x = M_PI_2_F - (M_PI_2_F - x); /* Crush denormals. */
+ float s = x * x;
+ /* Polynomial from SLEEF's sincosf, max error is
+ * 4.33127e-07 over [-2pi,2pi] (98% of values are "exact"). */
+ float u = -2.71811842367242206819355e-07f;
+ u = madd(u, s, +2.47990446951007470488548e-05f);
+ u = madd(u, s, -0.00138888787478208541870117f);
+ u = madd(u, s, +0.0416666641831398010253906f);
+ u = madd(u, s, -0.5f);
+ u = madd(u, s, +1.0f);
+ if((q & 1) != 0) {
+ u = -u;
+ }
+ if(fabsf(u) > 1.0f) {
+ u = 0.0f;
+ }
+ return u;
+}
+
+ccl_device void fast_sincosf(float x, float* sine, float* cosine)
+{
+ /* Same argument reduction as fast_sin. */
+ int q = fast_rint(x * M_1_PI_F);
+ float qf = q;
+ x = madd(qf, -0.78515625f*4, x);
+ x = madd(qf, -0.00024187564849853515625f*4, x);
+ x = madd(qf, -3.7747668102383613586e-08f*4, x);
+ x = madd(qf, -1.2816720341285448015e-12f*4, x);
+ x = M_PI_2_F - (M_PI_2_F - x); // crush denormals
+ float s = x * x;
+ /* NOTE: same exact polynomials as fast_sinf() and fast_cosf() above. */
+ if((q & 1) != 0) {
+ x = -x;
+ }
+ float su = 2.6083159809786593541503e-06f;
+ su = madd(su, s, -0.0001981069071916863322258f);
+ su = madd(su, s, +0.00833307858556509017944336f);
+ su = madd(su, s, -0.166666597127914428710938f);
+ su = madd(s, su * x, x);
+ float cu = -2.71811842367242206819355e-07f;
+ cu = madd(cu, s, +2.47990446951007470488548e-05f);
+ cu = madd(cu, s, -0.00138888787478208541870117f);
+ cu = madd(cu, s, +0.0416666641831398010253906f);
+ cu = madd(cu, s, -0.5f);
+ cu = madd(cu, s, +1.0f);
+ if((q & 1) != 0) {
+ cu = -cu;
+ }
+ if(fabsf(su) > 1.0f) {
+ su = 0.0f;
+ }
+ if(fabsf(cu) > 1.0f) {
+ cu = 0.0f;
+ }
+ *sine = su;
+ *cosine = cu;
+}
+
+/* NOTE: this approximation is only valid on [-8192.0,+8192.0], it starts
+ * becoming really poor outside of this range because the reciprocal amplifies
+ * errors.
+ */
+ccl_device float fast_tanf(float x)
+{
+ /* Derived from SLEEF implementation.
+ *
+ * Note that we cannot apply the "denormal crush" trick everywhere because
+ * we sometimes need to take the reciprocal of the polynomial
+ */
+ int q = fast_rint(x * 2.0f * M_1_PI_F);
+ float qf = q;
+ x = madd(qf, -0.78515625f*2, x);
+ x = madd(qf, -0.00024187564849853515625f*2, x);
+ x = madd(qf, -3.7747668102383613586e-08f*2, x);
+ x = madd(qf, -1.2816720341285448015e-12f*2, x);
+ if((q & 1) == 0) {
+ /* Crush denormals (only if we aren't inverting the result later). */
+ x = M_PI_4_F - (M_PI_4_F - x);
+ }
+ float s = x * x;
+ float u = 0.00927245803177356719970703f;
+ u = madd(u, s, 0.00331984995864331722259521f);
+ u = madd(u, s, 0.0242998078465461730957031f);
+ u = madd(u, s, 0.0534495301544666290283203f);
+ u = madd(u, s, 0.133383005857467651367188f);
+ u = madd(u, s, 0.333331853151321411132812f);
+ u = madd(s, u * x, x);
+ if((q & 1) != 0) {
+ u = -1.0f / u;
+ }
+ return u;
+}
+
+/* Fast, approximate sin(x*M_PI) with maximum absolute error of 0.000918954611.
+ *
+ * Adapted from http://devmaster.net/posts/9648/fast-and-accurate-sine-cosine#comment-76773
+ */
+ccl_device float fast_sinpif(float x)
+{
+ /* Fast trick to strip the integral part off, so our domain is [-1, 1]. */
+ const float z = x - ((x + 25165824.0f) - 25165824.0f);
+ const float y = z - z * fabsf(z);
+ const float Q = 3.10396624f;
+ const float P = 3.584135056f; /* P = 16-4*Q */
+ return y * (Q + P * fabsf(y));
+
+ /* The original article used used inferior constants for Q and P and
+ * so had max error 1.091e-3.
+ *
+ * The optimal value for Q was determined by exhaustive search, minimizing
+ * the absolute numerical error relative to float(std::sin(double(phi*M_PI)))
+ * over the interval [0,2] (which is where most of the invocations happen).
+ *
+ * The basic idea of this approximation starts with the coarse approximation:
+ * sin(pi*x) ~= f(x) = 4 * (x - x * abs(x))
+ *
+ * This approximation always _over_ estimates the target. On the otherhand,
+ * the curve:
+ * sin(pi*x) ~= f(x) * abs(f(x)) / 4
+ *
+ * always lies _under_ the target. Thus we can simply numerically search for
+ * the optimal constant to LERP these curves into a more precise
+ * approximation.
+ *
+ * After folding the constants together and simplifying the resulting math,
+ * we end up with the compact implementation above.
+ *
+ * NOTE: this function actually computes sin(x * pi) which avoids one or two
+ * mults in many cases and guarantees exact values at integer periods.
+ */
+}
+
+/* Fast approximate cos(x*M_PI) with ~0.1% absolute error. */
+ccl_device_inline float fast_cospif(float x)
+{
+ return fast_sinpif(x+0.5f);
+}
+
+ccl_device float fast_acosf(float x)
+{
+ const float f = fabsf(x);
+ /* clamp and crush denormals. */
+ const float m = (f < 1.0f) ? 1.0f - (1.0f - f) : 1.0f;
+ /* Based on http://www.pouet.net/topic.php?which=9132&page=2
+ * 85% accurate (ulp 0)
+ * Examined 2130706434 values of acos: 15.2000597 avg ulp diff, 4492 max ulp, 4.51803e-05 max error // without "denormal crush"
+ * Examined 2130706434 values of acos: 15.2007108 avg ulp diff, 4492 max ulp, 4.51803e-05 max error // with "denormal crush"
+ */
+ const float a = sqrtf(1.0f - m) *
+ (1.5707963267f + m * (-0.213300989f + m *
+ (0.077980478f + m * -0.02164095f)));
+ return x < 0 ? M_PI_F - a : a;
+}
+
+ccl_device float fast_asinf(float x)
+{
+ /* Based on acosf approximation above.
+ * Max error is 4.51133e-05 (ulps are higher because we are consistently off
+ * by a little amount).
+ */
+ const float f = fabsf(x);
+ /* Clamp and crush denormals. */
+ const float m = (f < 1.0f) ? 1.0f - (1.0f - f) : 1.0f;
+ const float a = M_PI_2_F - sqrtf(1.0f - m) *
+ (1.5707963267f + m * (-0.213300989f + m *
+ (0.077980478f + m * -0.02164095f)));
+ return copysignf(a, x);
+}
+
+ccl_device float fast_atanf(float x)
+{
+ const float a = fabsf(x);
+ const float k = a > 1.0f ? 1 / a : a;
+ const float s = 1.0f - (1.0f - k); /* Crush denormals. */
+ const float t = s * s;
+ /* http://mathforum.org/library/drmath/view/62672.html
+ * Examined 4278190080 values of atan: 2.36864877 avg ulp diff, 302 max ulp, 6.55651e-06 max error // (with denormals)
+ * Examined 4278190080 values of atan: 171160502 avg ulp diff, 855638016 max ulp, 6.55651e-06 max error // (crush denormals)
+ */
+ float r = s * madd(0.43157974f, t, 1.0f) /
+ madd(madd(0.05831938f, t, 0.76443945f), t, 1.0f);
+ if(a > 1.0f) {
+ /* TODO(sergey): Is it M_PI_2_F? */
+ r = 1.570796326794896557998982f - r;
+ }
+ return copysignf(r, x);
+}
+
+ccl_device float fast_atan2f(float y, float x)
+{
+ /* Based on atan approximation above.
+ *
+ * The special cases around 0 and infinity were tested explicitly.
+ *
+ * The only case not handled correctly is x=NaN,y=0 which returns 0 instead
+ * of nan.
+ */
+ const float a = fabsf(x);
+ const float b = fabsf(y);
+
+ const float k = (b == 0) ? 0.0f : ((a == b) ? 1.0f : (b > a ? a / b : b / a));
+ const float s = 1.0f - (1.0f - k); /* Crush denormals */
+ const float t = s * s;
+
+ float r = s * madd(0.43157974f, t, 1.0f) /
+ madd(madd(0.05831938f, t, 0.76443945f), t, 1.0f);
+
+ if(b > a) {
+ /* Account for arg reduction. */
+ /* TODO(sergey): Is it M_PI_2_F? */
+ r = 1.570796326794896557998982f - r;
+ }
+ /* Test sign bit of x. */
+ if(__float_as_uint(x) & 0x80000000u) {
+ r = M_PI_F - r;
+ }
+ return copysignf(r, y);
+}
+
+/* Based on:
+ *
+ * https://github.com/LiraNuna/glsl-sse2/blob/master/source/vec4.h
+ *
+ */
+ccl_device float fast_log2f(float x)
+{
+ /* NOTE: clamp to avoid special cases and make result "safe" from large
+ * negative values/nans. */
+ x = clamp(x, FLT_MIN, FLT_MAX);
+ unsigned bits = __float_as_uint(x);
+ int exponent = (int)(bits >> 23) - 127;
+ float f = __uint_as_float((bits & 0x007FFFFF) | 0x3f800000) - 1.0f;
+ /* Examined 2130706432 values of log2 on [1.17549435e-38,3.40282347e+38]:
+ * 0.0797524457 avg ulp diff, 3713596 max ulp, 7.62939e-06 max error.
+ * ulp histogram:
+ * 0 = 97.46%
+ * 1 = 2.29%
+ * 2 = 0.11%
+ */
+ float f2 = f * f;
+ float f4 = f2 * f2;
+ float hi = madd(f, -0.00931049621349f, 0.05206469089414f);
+ float lo = madd(f, 0.47868480909345f, -0.72116591947498f);
+ hi = madd(f, hi, -0.13753123777116f);
+ hi = madd(f, hi, 0.24187369696082f);
+ hi = madd(f, hi, -0.34730547155299f);
+ lo = madd(f, lo, 1.442689881667200f);
+ return ((f4 * hi) + (f * lo)) + exponent;
+}
+
+ccl_device_inline float fast_logf(float x)
+{
+ /* Examined 2130706432 values of logf on [1.17549435e-38,3.40282347e+38]:
+ * 0.313865375 avg ulp diff, 5148137 max ulp, 7.62939e-06 max error.
+ */
+ return fast_log2f(x) * M_LN2_F;
+}
+
+ccl_device_inline float fast_log10(float x)
+{
+ /* Examined 2130706432 values of log10f on [1.17549435e-38,3.40282347e+38]:
+ * 0.631237033 avg ulp diff, 4471615 max ulp, 3.8147e-06 max error.
+ */
+ return fast_log2f(x) * M_LN2_F / M_LN10_F;
+}
+
+ccl_device float fast_logb(float x)
+{
+ /* Don't bother with denormals. */
+ x = fabsf(x);
+ x = clamp(x, FLT_MIN, FLT_MAX);
+ unsigned bits = __float_as_uint(x);
+ return (int)(bits >> 23) - 127;
+}
+
+ccl_device float fast_exp2f(float x)
+{
+ /* Clamp to safe range for final addition. */
+ x = clamp(x, -126.0f, 126.0f);
+ /* Range reduction. */
+ int m = (int)x; x -= m;
+ x = 1.0f - (1.0f - x); /* Crush denormals (does not affect max ulps!). */
+ /* 5th degree polynomial generated with sollya
+ * Examined 2247622658 values of exp2 on [-126,126]: 2.75764912 avg ulp diff,
+ * 232 max ulp.
+ *
+ * ulp histogram:
+ * 0 = 87.81%
+ * 1 = 4.18%
+ */
+ float r = 1.33336498402e-3f;
+ r = madd(x, r, 9.810352697968e-3f);
+ r = madd(x, r, 5.551834031939e-2f);
+ r = madd(x, r, 0.2401793301105f);
+ r = madd(x, r, 0.693144857883f);
+ r = madd(x, r, 1.0f);
+ /* Multiply by 2 ^ m by adding in the exponent. */
+ /* NOTE: left-shift of negative number is undefined behavior. */
+ return __uint_as_float(__float_as_uint(r) + ((unsigned)m << 23));
+}
+
+ccl_device_inline float fast_expf(float x)
+{
+ /* Examined 2237485550 values of exp on [-87.3300018,87.3300018]:
+ * 2.6666452 avg ulp diff, 230 max ulp.
+ */
+ return fast_exp2f(x / M_LN2_F);
+}
+
+ccl_device_inline float fast_exp10(float x)
+{
+ /* Examined 2217701018 values of exp10 on [-37.9290009,37.9290009]:
+ * 2.71732409 avg ulp diff, 232 max ulp.
+ */
+ return fast_exp2f(x * M_LN10_F / M_LN2_F);
+}
+
+ccl_device_inline float fast_expm1f(float x)
+{
+ if(fabsf(x) < 1e-5f) {
+ x = 1.0f - (1.0f - x); /* Crush denormals. */
+ return madd(0.5f, x * x, x);
+ }
+ else {
+ return fast_expf(x) - 1.0f;
+ }
+}
+
+ccl_device float fast_sinhf(float x)
+{
+ float a = fabsf(x);
+ if(a > 1.0f) {
+ /* Examined 53389559 values of sinh on [1,87.3300018]:
+ * 33.6886442 avg ulp diff, 178 max ulp. */
+ float e = fast_expf(a);
+ return copysignf(0.5f * e - 0.5f / e, x);
+ }
+ else {
+ a = 1.0f - (1.0f - a); /* Crush denorms. */
+ float a2 = a * a;
+ /* Degree 7 polynomial generated with sollya. */
+ /* Examined 2130706434 values of sinh on [-1,1]: 1.19209e-07 max error. */
+ float r = 2.03945513931e-4f;
+ r = madd(r, a2, 8.32990277558e-3f);
+ r = madd(r, a2, 0.1666673421859f);
+ r = madd(r * a, a2, a);
+ return copysignf(r, x);
+ }
+}
+
+ccl_device_inline float fast_coshf(float x)
+{
+ /* Examined 2237485550 values of cosh on [-87.3300018,87.3300018]:
+ * 1.78256726 avg ulp diff, 178 max ulp.
+ */
+ float e = fast_expf(fabsf(x));
+ return 0.5f * e + 0.5f / e;
+}
+
+ccl_device_inline float fast_tanhf(float x)
+{
+ /* Examined 4278190080 values of tanh on [-3.40282347e+38,3.40282347e+38]:
+ * 3.12924e-06 max error.
+ */
+ /* NOTE: ulp error is high because of sub-optimal handling around the origin. */
+ float e = fast_expf(2.0f * fabsf(x));
+ return copysignf(1.0f - 2.0f / (1.0f + e), x);
+}
+
+ccl_device float fast_safe_powf(float x, float y)
+{
+ if(y == 0) return 1.0f; /* x^1=1 */
+ if(x == 0) return 0.0f; /* 0^y=0 */
+ float sign = 1.0f;
+ if(x < 0.0f) {
+ /* if x is negative, only deal with integer powers
+ * powf returns NaN for non-integers, we will return 0 instead.
+ */
+ int ybits = __float_as_int(y) & 0x7fffffff;
+ if(ybits >= 0x4b800000) {
+ // always even int, keep positive
+ }
+ else if(ybits >= 0x3f800000) {
+ /* Bigger than 1, check. */
+ int k = (ybits >> 23) - 127; /* Get exponent. */
+ int j = ybits >> (23 - k); /* Shift out possible fractional bits. */
+ if((j << (23 - k)) == ybits) { /* rebuild number and check for a match. */
+ /* +1 for even, -1 for odd. */
+ sign = __int_as_float(0x3f800000 | (j << 31));
+ }
+ else {
+ /* Not an integer. */
+ return 0.0f;
+ }
+ }
+ else {
+ /* Not an integer. */
+ return 0.0f;
+ }
+ }
+ return sign * fast_exp2f(y * fast_log2f(fabsf(x)));
+}
+
+/* TODO(sergey): Check speed with our erf functions implementation from
+ * bsdf_microfaset.h.
+ */
+
+ccl_device_inline float fast_erff(float x)
+{
+ /* Examined 1082130433 values of erff on [0,4]: 1.93715e-06 max error. */
+ /* Abramowitz and Stegun, 7.1.28. */
+ const float a1 = 0.0705230784f;
+ const float a2 = 0.0422820123f;
+ const float a3 = 0.0092705272f;
+ const float a4 = 0.0001520143f;
+ const float a5 = 0.0002765672f;
+ const float a6 = 0.0000430638f;
+ const float a = fabsf(x);
+ const float b = 1.0f - (1.0f - a); /* Crush denormals. */
+ const float r = madd(madd(madd(madd(madd(madd(a6, b, a5), b, a4), b, a3), b, a2), b, a1), b, 1.0f);
+ const float s = r * r; /* ^2 */
+ const float t = s * s; /* ^4 */
+ const float u = t * t; /* ^8 */
+ const float v = u * u; /* ^16 */
+ return copysignf(1.0f - 1.0f / v, x);
+}
+
+ccl_device_inline float fast_erfcf(float x)
+{
+ /* Examined 2164260866 values of erfcf on [-4,4]: 1.90735e-06 max error.
+ *
+ * ulp histogram:
+ *
+ * 0 = 80.30%
+ */
+ return 1.0f - fast_erff(x);
+}
+
+ccl_device_inline float fast_ierff(float x)
+{
+ /* From: Approximating the erfinv function by Mike Giles. */
+ /* To avoid trouble at the limit, clamp input to 1-eps. */
+ float a = fabsf(x);
+ if(a > 0.99999994f) {
+ a = 0.99999994f;
+ }
+ float w = -fast_logf((1.0f - a) * (1.0f + a)), p;
+ if(w < 5.0f) {
+ w = w - 2.5f;
+ p = 2.81022636e-08f;
+ p = madd(p, w, 3.43273939e-07f);
+ p = madd(p, w, -3.5233877e-06f);
+ p = madd(p, w, -4.39150654e-06f);
+ p = madd(p, w, 0.00021858087f);
+ p = madd(p, w, -0.00125372503f);
+ p = madd(p, w, -0.00417768164f);
+ p = madd(p, w, 0.246640727f);
+ p = madd(p, w, 1.50140941f);
+ }
+ else {
+ w = sqrtf(w) - 3.0f;
+ p = -0.000200214257f;
+ p = madd(p, w, 0.000100950558f);
+ p = madd(p, w, 0.00134934322f);
+ p = madd(p, w, -0.00367342844f);
+ p = madd(p, w, 0.00573950773f);
+ p = madd(p, w, -0.0076224613f);
+ p = madd(p, w, 0.00943887047f);
+ p = madd(p, w, 1.00167406f);
+ p = madd(p, w, 2.83297682f);
+ }
+ return p * x;
+}
+
+CCL_NAMESPACE_END
+
+#endif /* __UTIL_FAST_MATH__ */
diff --git a/intern/cycles/util/util_md5.cpp b/intern/cycles/util/util_md5.cpp
index add0d18c742..b2a32c45287 100644
--- a/intern/cycles/util/util_md5.cpp
+++ b/intern/cycles/util/util_md5.cpp
@@ -152,8 +152,8 @@ void MD5Hash::process(const uint8_t *data /*[64]*/)
* a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s). */
#define F(x, y, z) (((x) & (y)) | (~(x) & (z)))
#define SET(a, b, c, d, k, s, Ti)\
- t = a + F(b,c,d) + X[k] + Ti;\
- a = ROTATE_LEFT(t, s) + b
+ t = a + F(b,c,d) + X[k] + Ti;\
+ a = ROTATE_LEFT(t, s) + b
/* Do the following 16 operations. */
SET(a, b, c, d, 0, 7, T1);
SET(d, a, b, c, 1, 12, T2);
@@ -178,8 +178,8 @@ void MD5Hash::process(const uint8_t *data /*[64]*/)
* a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s). */
#define G(x, y, z) (((x) & (z)) | ((y) & ~(z)))
#define SET(a, b, c, d, k, s, Ti)\
- t = a + G(b,c,d) + X[k] + Ti;\
- a = ROTATE_LEFT(t, s) + b
+ t = a + G(b,c,d) + X[k] + Ti;\
+ a = ROTATE_LEFT(t, s) + b
/* Do the following 16 operations. */
SET(a, b, c, d, 1, 5, T17);
SET(d, a, b, c, 6, 9, T18);
@@ -230,8 +230,8 @@ void MD5Hash::process(const uint8_t *data /*[64]*/)
* a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s). */
#define I(x, y, z) ((y) ^ ((x) | ~(z)))
#define SET(a, b, c, d, k, s, Ti)\
- t = a + I(b,c,d) + X[k] + Ti;\
- a = ROTATE_LEFT(t, s) + b
+ t = a + I(b,c,d) + X[k] + Ti;\
+ a = ROTATE_LEFT(t, s) + b
/* Do the following 16 operations. */
SET(a, b, c, d, 0, 6, T49);
SET(d, a, b, c, 7, 10, T50);
diff --git a/intern/cycles/util/util_opengl.h b/intern/cycles/util/util_opengl.h
index 04a3e039c9d..0b5462e0a09 100644
--- a/intern/cycles/util/util_opengl.h
+++ b/intern/cycles/util/util_opengl.h
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#ifndef __UTIL_OPENGL_H__
@@ -20,7 +20,12 @@
/* OpenGL header includes, used everywhere we use OpenGL, to deal with
* platform differences in one central place. */
-#include <GL/glew.h>
+#ifdef WITH_GLEW_MX
+# include "glew-mx.h"
+#else
+# include <GL/glew.h>
+# define mxCreateContext() glewInit()
+# define mxMakeCurrentContext(x) (x)
+#endif
#endif /* __UTIL_OPENGL_H__ */
-
diff --git a/intern/cycles/util/util_optimization.h b/intern/cycles/util/util_optimization.h
index 2feb3d6ab7e..c951c35fc76 100644
--- a/intern/cycles/util/util_optimization.h
+++ b/intern/cycles/util/util_optimization.h
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#ifndef __UTIL_OPTIMIZATION_H__
@@ -102,34 +102,16 @@
#ifdef _MSC_VER
#include <intrin.h>
#else
-
-#ifdef __KERNEL_SSE2__
-#include <xmmintrin.h> /* SSE 1 */
-#include <emmintrin.h> /* SSE 2 */
-#endif
-
-#ifdef __KERNEL_SSE3__
-#include <pmmintrin.h> /* SSE 3 */
-#endif
-
-#ifdef __KERNEL_SSSE3__
-#include <tmmintrin.h> /* SSSE 3 */
-#endif
-
-#ifdef __KERNEL_SSE41__
-#include <smmintrin.h> /* SSE 4.1 */
-#endif
-
-#ifdef __KERNEL_AVX__
-#include <immintrin.h> /* AVX */
-#endif
-
+#include <x86intrin.h>
#endif
#else
/* MinGW64 has conflicting declarations for these SSE headers in <windows.h>.
* Since we can't avoid including <windows.h>, better only include that */
+#define NOGDI
+#define NOMINMAX
+#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#endif
diff --git a/intern/cycles/util/util_param.h b/intern/cycles/util/util_param.h
index ef20ff0fcd2..69bcbf80a78 100644
--- a/intern/cycles/util/util_param.h
+++ b/intern/cycles/util/util_param.h
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#ifndef __UTIL_PARAM_H__
diff --git a/intern/cycles/util/util_path.cpp b/intern/cycles/util/util_path.cpp
index 85d19b6a325..e8f1ec81763 100644
--- a/intern/cycles/util/util_path.cpp
+++ b/intern/cycles/util/util_path.cpp
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#include "util_debug.h"
@@ -25,12 +25,6 @@ OIIO_NAMESPACE_USING
#include <stdio.h>
-#include <boost/version.hpp>
-
-#if (BOOST_VERSION < 104400)
-# define BOOST_FILESYSTEM_VERSION 2
-#endif
-
#include <boost/filesystem.hpp>
#include <boost/algorithm/string.hpp>
@@ -41,21 +35,31 @@ static string cached_user_path = "";
static boost::filesystem::path to_boost(const string& path)
{
-#ifdef _MSC_VER
- std::wstring path_utf16 = Strutil::utf8_to_utf16(path.c_str());
- return boost::filesystem::path(path_utf16.c_str());
-#else
return boost::filesystem::path(path.c_str());
-#endif
}
static string from_boost(const boost::filesystem::path& path)
{
-#ifdef _MSC_VER
- return Strutil::utf16_to_utf8(path.wstring().c_str());
-#else
return path.string().c_str();
-#endif
+}
+
+static char *path_specials(const string& sub)
+{
+ static bool env_init = false;
+ static char *env_shader_path;
+ static char *env_kernel_path;
+ if(!env_init) {
+ env_shader_path = getenv("CYCLES_SHADER_PATH");
+ env_kernel_path = getenv("CYCLES_KERNEL_PATH");
+ env_init = true;
+ }
+ if(env_shader_path != NULL && sub == "shader") {
+ return env_shader_path;
+ }
+ else if(env_shader_path != NULL && sub == "kernel") {
+ return env_kernel_path;
+ }
+ return NULL;
}
void path_init(const string& path, const string& user_path)
@@ -71,6 +75,10 @@ void path_init(const string& path, const string& user_path)
string path_get(const string& sub)
{
+ char *special = path_specials(sub);
+ if(special != NULL)
+ return special;
+
if(cached_path == "")
cached_path = path_dirname(Sysutil::this_program_path());
@@ -87,11 +95,7 @@ string path_user_get(const string& sub)
string path_filename(const string& path)
{
-#if (BOOST_FILESYSTEM_VERSION == 2)
- return to_boost(path).filename();
-#else
return from_boost(to_boost(path).filename());
-#endif
}
string path_dirname(const string& path)
@@ -259,14 +263,7 @@ string path_source_replace_includes(const string& source_, const string& path)
FILE *path_fopen(const string& path, const string& mode)
{
-#ifdef _WIN32
- std::wstring path_utf16 = Strutil::utf8_to_utf16(path);
- std::wstring mode_utf16 = Strutil::utf8_to_utf16(mode);
-
- return _wfopen(path_utf16.c_str(), mode_utf16.c_str());
-#else
return fopen(path.c_str(), mode.c_str());
-#endif
}
void path_cache_clear_except(const string& name, const set<string>& except)
@@ -277,11 +274,7 @@ void path_cache_clear_except(const string& name, const set<string>& except)
boost::filesystem::directory_iterator it(dir), it_end;
for(; it != it_end; it++) {
-#if (BOOST_FILESYSTEM_VERSION == 2)
- string filename = from_boost(it->path().filename());
-#else
string filename = from_boost(it->path().filename().string());
-#endif
if(boost::starts_with(filename, name))
if(except.find(filename) == except.end())
diff --git a/intern/cycles/util/util_path.h b/intern/cycles/util/util_path.h
index fd9ea11740d..b81d71d1c0f 100644
--- a/intern/cycles/util/util_path.h
+++ b/intern/cycles/util/util_path.h
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#ifndef __UTIL_PATH_H__
diff --git a/intern/cycles/util/util_progress.h b/intern/cycles/util/util_progress.h
index e721a3f5047..0b35142ddb3 100644
--- a/intern/cycles/util/util_progress.h
+++ b/intern/cycles/util/util_progress.h
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#ifndef __UTIL_PROGRESS_H__
@@ -38,15 +38,18 @@ public:
sample = 0;
start_time = time_dt();
total_time = 0.0f;
+ render_time = 0.0f;
tile_time = 0.0f;
status = "Initializing";
substatus = "";
sync_status = "";
sync_substatus = "";
- update_cb = NULL;
+ update_cb = function_null;
cancel = false;
cancel_message = "";
- cancel_cb = NULL;
+ error = false;
+ error_message = "";
+ cancel_cb = function_null;
}
Progress(Progress& progress)
@@ -59,7 +62,7 @@ public:
thread_scoped_lock lock(progress.progress_mutex);
progress.get_status(status, substatus);
- progress.get_tile(tile, total_time, tile_time);
+ progress.get_tile(tile, total_time, render_time, tile_time);
sample = progress.get_sample();
@@ -71,7 +74,9 @@ public:
tile = 0;
sample = 0;
start_time = time_dt();
+ render_start_time = time_dt();
total_time = 0.0f;
+ render_time = 0.0f;
tile_time = 0.0f;
status = "Initializing";
substatus = "";
@@ -79,6 +84,8 @@ public:
sync_substatus = "";
cancel = false;
cancel_message = "";
+ error = false;
+ error_message = "";
}
/* cancel */
@@ -103,11 +110,33 @@ public:
return cancel_message;
}
- void set_cancel_callback(boost::function<void(void)> function)
+ void set_cancel_callback(function<void(void)> function)
{
cancel_cb = function;
}
+ /* error */
+ void set_error(const string& error_message_)
+ {
+ thread_scoped_lock lock(progress_mutex);
+ error_message = error_message_;
+ error = true;
+ /* If error happens we also stop rendering. */
+ cancel_message = error_message_;
+ cancel = true;
+ }
+
+ bool get_error()
+ {
+ return error;
+ }
+
+ string get_error_message()
+ {
+ thread_scoped_lock lock(progress_mutex);
+ return error_message;
+ }
+
/* tile and timing information */
void set_start_time(double start_time_)
@@ -117,24 +146,39 @@ public:
start_time = start_time_;
}
+ void set_render_start_time(double render_start_time_)
+ {
+ thread_scoped_lock lock(progress_mutex);
+
+ render_start_time = render_start_time_;
+ }
+
void set_tile(int tile_, double tile_time_)
{
thread_scoped_lock lock(progress_mutex);
tile = tile_;
total_time = time_dt() - start_time;
+ render_time = time_dt() - render_start_time;
tile_time = tile_time_;
}
- void get_tile(int& tile_, double& total_time_, double& tile_time_)
+ void get_tile(int& tile_, double& total_time_, double& render_time_, double& tile_time_)
{
thread_scoped_lock lock(progress_mutex);
tile_ = tile;
total_time_ = (total_time > 0.0)? total_time: 0.0;
+ render_time_ = (render_time > 0.0)? render_time: 0.0;
tile_time_ = tile_time;
}
+ void get_time(double& total_time_, double& render_time_)
+ {
+ total_time_ = (total_time > 0.0)? total_time: 0.0;
+ render_time_ = (render_time > 0.0)? render_time: 0.0;
+ }
+
void reset_sample()
{
thread_scoped_lock lock(progress_mutex);
@@ -169,6 +213,7 @@ public:
status = status_;
substatus = substatus_;
total_time = time_dt() - start_time;
+ render_time = time_dt() - render_start_time;
}
set_update();
@@ -180,6 +225,7 @@ public:
thread_scoped_lock lock(progress_mutex);
substatus = substatus_;
total_time = time_dt() - start_time;
+ render_time = time_dt() - render_start_time;
}
set_update();
@@ -192,6 +238,7 @@ public:
sync_status = status_;
sync_substatus = substatus_;
total_time = time_dt() - start_time;
+ render_time = time_dt() - render_start_time;
}
set_update();
@@ -204,6 +251,7 @@ public:
thread_scoped_lock lock(progress_mutex);
sync_substatus = substatus_;
total_time = time_dt() - start_time;
+ render_time = time_dt() - render_start_time;
}
set_update();
@@ -233,7 +281,7 @@ public:
}
}
- void set_update_callback(boost::function<void(void)> function)
+ void set_update_callback(function<void(void)> function)
{
update_cb = function;
}
@@ -241,14 +289,14 @@ public:
protected:
thread_mutex progress_mutex;
thread_mutex update_mutex;
- boost::function<void(void)> update_cb;
- boost::function<void(void)> cancel_cb;
+ function<void(void)> update_cb;
+ function<void(void)> cancel_cb;
int tile; /* counter for rendered tiles */
int sample; /* counter of rendered samples, global for all tiles */
- double start_time;
- double total_time;
+ double start_time, render_start_time;
+ double total_time, render_time;
double tile_time;
string status;
@@ -259,6 +307,9 @@ protected:
volatile bool cancel;
string cancel_message;
+
+ volatile bool error;
+ string error_message;
};
CCL_NAMESPACE_END
diff --git a/intern/cycles/util/util_set.h b/intern/cycles/util/util_set.h
index 6078114e714..b3cb8dd8af5 100644
--- a/intern/cycles/util/util_set.h
+++ b/intern/cycles/util/util_set.h
@@ -11,20 +11,26 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#ifndef __UTIL_SET_H__
#define __UTIL_SET_H__
#include <set>
-#include <boost/tr1/unordered_set.hpp>
-
+#if (__cplusplus > 199711L) || (defined(_MSC_VER) && _MSC_VER >= 1800)
+# include <unordered_set>
+#else
+# include <boost/tr1/unordered_set.hpp>
+#endif
CCL_NAMESPACE_BEGIN
using std::set;
+#if (__cplusplus > 199711L) || (defined(_MSC_VER) && _MSC_VER >= 1800)
+using std::unordered_set;
+#else
using std::tr1::unordered_set;
-
+#endif
CCL_NAMESPACE_END
#endif /* __UTIL_SET_H__ */
diff --git a/intern/cycles/util/util_simd.cpp b/intern/cycles/util/util_simd.cpp
index 0436823e62a..eb9e32800e1 100644
--- a/intern/cycles/util/util_simd.cpp
+++ b/intern/cycles/util/util_simd.cpp
@@ -12,7 +12,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#ifdef WITH_KERNEL_SSE2
diff --git a/intern/cycles/util/util_simd.h b/intern/cycles/util/util_simd.h
index 39506a6359b..a1c35b7174d 100644
--- a/intern/cycles/util/util_simd.h
+++ b/intern/cycles/util/util_simd.h
@@ -12,7 +12,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#ifndef __UTIL_SIMD_TYPES_H__
@@ -58,8 +58,12 @@ __forceinline operator int ( ) const { return std::numeric_limits<
/* Intrinsics Functions */
#if defined(__BMI__) && defined(__GNUC__)
-#define _tzcnt_u32 __tzcnt_u32
-#define _tzcnt_u64 __tzcnt_u64
+# ifndef _tzcnt_u32
+# define _tzcnt_u32 __tzcnt_u32
+# endif
+# ifndef _tzcnt_u64
+# define _tzcnt_u64 __tzcnt_u64
+# endif
#endif
#if defined(__LZCNT__)
@@ -133,7 +137,7 @@ __forceinline int clz(const int x)
#if defined(__KERNEL_AVX2__)
return _lzcnt_u32(x);
#else
- if (UNLIKELY(x == 0)) return 32;
+ if(UNLIKELY(x == 0)) return 32;
return 31 - __bsr(x);
#endif
}
@@ -286,7 +290,7 @@ __forceinline int clz(const int x)
#if defined(__KERNEL_AVX2__)
return _lzcnt_u32(x);
#else
- if (UNLIKELY(x == 0)) return 32;
+ if(UNLIKELY(x == 0)) return 32;
return 31 - __bsr(x);
#endif
}
@@ -358,7 +362,7 @@ __forceinline __m128i _mm_mullo_epi32( __m128i value, __m128i input ) {
char* _r = (char*)(&rvalue + 1);
char* _v = (char*)(& value + 1);
char* _i = (char*)(& input + 1);
- for ( ssize_t i = -16 ; i != 0 ; i += 4 ) *((int32*)(_r + i)) = *((int32*)(_v + i))* *((int32*)(_i + i));
+ for( ssize_t i = -16 ; i != 0 ; i += 4 ) *((int32*)(_r + i)) = *((int32*)(_v + i))* *((int32*)(_i + i));
return rvalue;
}
diff --git a/intern/cycles/util/util_sseb.h b/intern/cycles/util/util_sseb.h
index be510256dd3..6e669701f3b 100644
--- a/intern/cycles/util/util_sseb.h
+++ b/intern/cycles/util/util_sseb.h
@@ -12,7 +12,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#ifndef __UTIL_SSEB_H__
@@ -119,14 +119,29 @@ template<size_t i0, size_t i1, size_t i2, size_t i3> __forceinline const sseb sh
return _mm_shuffle_epi32(a, _MM_SHUFFLE(i3, i2, i1, i0));
}
+template<> __forceinline const sseb shuffle<0, 1, 0, 1>( const sseb& a ) {
+ return _mm_movelh_ps(a, a);
+}
+
+template<> __forceinline const sseb shuffle<2, 3, 2, 3>( const sseb& a ) {
+ return _mm_movehl_ps(a, a);
+}
+
template<size_t i0, size_t i1, size_t i2, size_t i3> __forceinline const sseb shuffle( const sseb& a, const sseb& b ) {
return _mm_shuffle_ps(a, b, _MM_SHUFFLE(i3, i2, i1, i0));
}
+template<> __forceinline const sseb shuffle<0, 1, 0, 1>( const sseb& a, const sseb& b ) {
+ return _mm_movelh_ps(a, b);
+}
+
+template<> __forceinline const sseb shuffle<2, 3, 2, 3>( const sseb& a, const sseb& b ) {
+ return _mm_movehl_ps(b, a);
+}
+
#if defined(__KERNEL_SSE3__)
template<> __forceinline const sseb shuffle<0, 0, 2, 2>( const sseb& a ) { return _mm_moveldup_ps(a); }
template<> __forceinline const sseb shuffle<1, 1, 3, 3>( const sseb& a ) { return _mm_movehdup_ps(a); }
-template<> __forceinline const sseb shuffle<0, 1, 0, 1>( const sseb& a ) { return _mm_castpd_ps(_mm_movedup_pd (a)); }
#endif
#if defined(__KERNEL_SSE41__)
@@ -153,6 +168,16 @@ __forceinline bool none ( const sseb& b ) { return _mm_movemask_ps(b) == 0x
__forceinline size_t movemask( const sseb& a ) { return _mm_movemask_ps(a); }
+////////////////////////////////////////////////////////////////////////////////
+/// Debug Functions
+////////////////////////////////////////////////////////////////////////////////
+
+ccl_device_inline void print_sseb(const char *label, const sseb &a)
+{
+ printf("%s: %df %df %df %d\n",
+ label, a[0], a[1], a[2], a[3]);
+}
+
#endif
CCL_NAMESPACE_END
diff --git a/intern/cycles/util/util_ssef.h b/intern/cycles/util/util_ssef.h
index f4236cc616e..e625fa63568 100644
--- a/intern/cycles/util/util_ssef.h
+++ b/intern/cycles/util/util_ssef.h
@@ -12,7 +12,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#ifndef __UTIL_SSEF_H__
@@ -119,6 +119,9 @@ __forceinline const ssef operator^(const ssef& a, const ssei& b) { return _mm_xo
__forceinline const ssef operator&(const ssef& a, const ssef& b) { return _mm_and_ps(a.m128,b.m128); }
__forceinline const ssef operator&(const ssef& a, const ssei& b) { return _mm_and_ps(a.m128,_mm_castsi128_ps(b.m128)); }
+__forceinline const ssef operator|(const ssef& a, const ssef& b) { return _mm_or_ps(a.m128,b.m128); }
+__forceinline const ssef operator|(const ssef& a, const ssei& b) { return _mm_or_ps(a.m128,_mm_castsi128_ps(b.m128)); }
+
__forceinline const ssef andnot(const ssef& a, const ssef& b) { return _mm_andnot_ps(a.m128,b.m128); }
__forceinline const ssef min(const ssef& a, const ssef& b) { return _mm_min_ps(a.m128,b.m128); }
@@ -159,8 +162,8 @@ __forceinline const ssef nmsub(const ssef& a, const ssef& b, const ssef& c) { re
#else
__forceinline const ssef madd (const ssef& a, const ssef& b, const ssef& c) { return a*b+c; }
__forceinline const ssef msub (const ssef& a, const ssef& b, const ssef& c) { return a*b-c; }
-__forceinline const ssef nmadd(const ssef& a, const ssef& b, const ssef& c) { return -a*b-c;}
-__forceinline const ssef nmsub(const ssef& a, const ssef& b, const ssef& c) { return c-a*b; }
+__forceinline const ssef nmadd(const ssef& a, const ssef& b, const ssef& c) { return c-a*b;}
+__forceinline const ssef nmsub(const ssef& a, const ssef& b, const ssef& c) { return -a*b-c; }
#endif
////////////////////////////////////////////////////////////////////////////////
@@ -267,10 +270,30 @@ template<size_t i0, size_t i1, size_t i2, size_t i3> __forceinline const ssef sh
return _mm_castsi128_ps(_mm_shuffle_epi32(_mm_castps_si128(b), _MM_SHUFFLE(i3, i2, i1, i0)));
}
+template<> __forceinline const ssef shuffle<0, 1, 0, 1>(const ssef& a) {
+ return _mm_movelh_ps(a, a);
+}
+
+template<> __forceinline const ssef shuffle<2, 3, 2, 3>(const ssef& a) {
+ return _mm_movehl_ps(a, a);
+}
+
template<size_t i0, size_t i1, size_t i2, size_t i3> __forceinline const ssef shuffle(const ssef& a, const ssef& b) {
return _mm_shuffle_ps(a, b, _MM_SHUFFLE(i3, i2, i1, i0));
}
+template<size_t i0> __forceinline const ssef shuffle(const ssef& a, const ssef& b) {
+ return _mm_shuffle_ps(a, b, _MM_SHUFFLE(i0, i0, i0, i0));
+}
+
+template<> __forceinline const ssef shuffle<0, 1, 0, 1>(const ssef& a, const ssef& b) {
+ return _mm_movelh_ps(a, b);
+}
+
+template<> __forceinline const ssef shuffle<2, 3, 2, 3>(const ssef& a, const ssef& b) {
+ return _mm_movehl_ps(b, a);
+}
+
#if defined(__KERNEL_SSSE3__)
__forceinline const ssef shuffle8(const ssef& a, const ssei& shuf) {
return _mm_castsi128_ps(_mm_shuffle_epi8(_mm_castps_si128(a), shuf));
@@ -280,18 +303,19 @@ __forceinline const ssef shuffle8(const ssef& a, const ssei& shuf) {
#if defined(__KERNEL_SSE3__)
template<> __forceinline const ssef shuffle<0, 0, 2, 2>(const ssef& b) { return _mm_moveldup_ps(b); }
template<> __forceinline const ssef shuffle<1, 1, 3, 3>(const ssef& b) { return _mm_movehdup_ps(b); }
-template<> __forceinline const ssef shuffle<0, 1, 0, 1>(const ssef& b) { return _mm_castpd_ps(_mm_movedup_pd(_mm_castps_pd(b))); }
#endif
template<size_t i0> __forceinline const ssef shuffle(const ssef& b) {
return shuffle<i0,i0,i0,i0>(b);
}
-#if defined(__KERNEL_SSE41__) && !defined(__GNUC__)
-template<size_t i> __forceinline float extract (const ssef& a) { return _mm_cvtss_f32(_mm_extract_ps(a,i)); }
-#else
-template<size_t i> __forceinline float extract (const ssef& a) { return _mm_cvtss_f32(shuffle<i,i,i,i>(a)); }
+#if defined(__KERNEL_AVX__)
+__forceinline const ssef shuffle(const ssef& a, const ssei& shuf) {
+ return _mm_permutevar_ps(a, shuf);
+}
#endif
+
+template<size_t i> __forceinline float extract (const ssef& a) { return _mm_cvtss_f32(shuffle<i,i,i,i>(a)); }
template<> __forceinline float extract<0>(const ssef& a) { return _mm_cvtss_f32(a); }
#if defined(__KERNEL_SSE41__)
@@ -347,6 +371,8 @@ __forceinline size_t select_max(const ssef& v) { return __bsf(movemask(v == vred
__forceinline size_t select_min(const sseb& valid, const ssef& v) { const ssef a = select(valid,v,ssef(pos_inf)); return __bsf(movemask(valid &(a == vreduce_min(a)))); }
__forceinline size_t select_max(const sseb& valid, const ssef& v) { const ssef a = select(valid,v,ssef(neg_inf)); return __bsf(movemask(valid &(a == vreduce_max(a)))); }
+__forceinline size_t movemask( const ssef& a ) { return _mm_movemask_ps(a); }
+
////////////////////////////////////////////////////////////////////////////////
/// Memory load and store operations
////////////////////////////////////////////////////////////////////////////////
@@ -580,6 +606,20 @@ ccl_device_inline const ssef set_sign_bit(const ssef &a)
return a ^ cast(ssei(S1 << 31, S2 << 31, S3 << 31, S4 << 31));
}
+////////////////////////////////////////////////////////////////////////////////
+/// Debug Functions
+////////////////////////////////////////////////////////////////////////////////
+
+ccl_device_inline void print_ssef(const char *label, const ssef &a)
+{
+ printf("%s: %.8f %.8f %.8f %.8f\n",
+ label,
+ (double)a[0],
+ (double)a[1],
+ (double)a[2],
+ (double)a[3]);
+}
+
#endif
CCL_NAMESPACE_END
diff --git a/intern/cycles/util/util_ssei.h b/intern/cycles/util/util_ssei.h
index 5f5a8686e35..5f62569268c 100644
--- a/intern/cycles/util/util_ssei.h
+++ b/intern/cycles/util/util_ssei.h
@@ -12,7 +12,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#ifndef __UTIL_SSEI_H__
@@ -190,8 +190,8 @@ __forceinline const ssei select( const int mask, const ssei& t, const ssei& f )
// Movement/Shifting/Shuffling Functions
////////////////////////////////////////////////////////////////////////////////
-__forceinline ssei unpacklo( const ssei& a, const ssei& b ) { return _mm_castps_si128(_mm_unpacklo_ps(_mm_castsi128_ps(a.m128), _mm_castsi128_ps(b.m128))); }
-__forceinline ssei unpackhi( const ssei& a, const ssei& b ) { return _mm_castps_si128(_mm_unpackhi_ps(_mm_castsi128_ps(a.m128), _mm_castsi128_ps(b.m128))); }
+__forceinline ssei unpacklo( const ssei& a, const ssei& b ) { return _mm_unpacklo_epi32(a, b); }
+__forceinline ssei unpackhi( const ssei& a, const ssei& b ) { return _mm_unpackhi_epi32(a, b); }
template<size_t i0, size_t i1, size_t i2, size_t i3> __forceinline const ssei shuffle( const ssei& a ) {
return _mm_shuffle_epi32(a, _MM_SHUFFLE(i3, i2, i1, i0));
@@ -201,12 +201,6 @@ template<size_t i0, size_t i1, size_t i2, size_t i3> __forceinline const ssei sh
return _mm_castps_si128(_mm_shuffle_ps(_mm_castsi128_ps(a), _mm_castsi128_ps(b), _MM_SHUFFLE(i3, i2, i1, i0)));
}
-#if defined(__KERNEL_SSE3__)
-template<> __forceinline const ssei shuffle<0, 0, 2, 2>( const ssei& a ) { return _mm_castps_si128(_mm_moveldup_ps(_mm_castsi128_ps(a))); }
-template<> __forceinline const ssei shuffle<1, 1, 3, 3>( const ssei& a ) { return _mm_castps_si128(_mm_movehdup_ps(_mm_castsi128_ps(a))); }
-template<> __forceinline const ssei shuffle<0, 1, 0, 1>( const ssei& a ) { return _mm_castpd_si128(_mm_movedup_pd (_mm_castsi128_pd(a))); }
-#endif
-
template<size_t i0> __forceinline const ssei shuffle( const ssei& b ) {
return shuffle<i0,i0,i0,i0>(b);
}
@@ -286,6 +280,16 @@ __forceinline void store4i_nt(void* ptr, const ssei& v) {
#endif
}
+////////////////////////////////////////////////////////////////////////////////
+/// Debug Functions
+////////////////////////////////////////////////////////////////////////////////
+
+ccl_device_inline void print_ssei(const char *label, const ssei &a)
+{
+ printf("%s: %df %df %df %d\n",
+ label, a[0], a[1], a[2], a[3]);
+}
+
#endif
CCL_NAMESPACE_END
diff --git a/intern/cycles/util/util_stats.h b/intern/cycles/util/util_stats.h
index 8758b823084..ce27067dc5e 100644
--- a/intern/cycles/util/util_stats.h
+++ b/intern/cycles/util/util_stats.h
@@ -11,12 +11,14 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#ifndef __UTIL_STATS_H__
#define __UTIL_STATS_H__
+#include "util_atomic.h"
+
CCL_NAMESPACE_BEGIN
class Stats {
@@ -24,14 +26,13 @@ public:
Stats() : mem_used(0), mem_peak(0) {}
void mem_alloc(size_t size) {
- mem_used += size;
- if(mem_used > mem_peak)
- mem_peak = mem_used;
+ atomic_add_z(&mem_used, size);
+ atomic_update_max_z(&mem_peak, mem_used);
}
void mem_free(size_t size) {
assert(mem_used >= size);
- mem_used -= size;
+ atomic_sub_z(&mem_used, size);
}
size_t mem_used;
diff --git a/intern/cycles/util/util_string.cpp b/intern/cycles/util/util_string.cpp
index f38d8d3282f..66856dd8331 100644
--- a/intern/cycles/util/util_string.cpp
+++ b/intern/cycles/util/util_string.cpp
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#include <stdarg.h>
@@ -105,5 +105,22 @@ string string_strip(const string& s)
}
+void string_replace(string& haystack, const string& needle, const string& other)
+{
+ size_t i;
+
+ while((i = haystack.find(needle)) != string::npos)
+ haystack.replace(i, needle.length(), other);
+}
+
+string string_remove_trademark(const string &s)
+{
+ string result = s;
+ string_replace(result, "(TM)", "");
+ string_replace(result, "(R)", "");
+
+ return string_strip(result);
+}
+
CCL_NAMESPACE_END
diff --git a/intern/cycles/util/util_string.h b/intern/cycles/util/util_string.h
index 6808f085834..6cb8d8df1e1 100644
--- a/intern/cycles/util/util_string.h
+++ b/intern/cycles/util/util_string.h
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#ifndef __UTIL_STRING_H__
@@ -40,8 +40,10 @@ 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 ");
+void string_replace(string& haystack, const string& needle, const string& other);
bool string_endswith(const string& s, const char *end);
string string_strip(const string& s);
+string string_remove_trademark(const string& s);
CCL_NAMESPACE_END
diff --git a/intern/cycles/util/util_system.cpp b/intern/cycles/util/util_system.cpp
index 7c0445577e2..cc88320b68e 100644
--- a/intern/cycles/util/util_system.cpp
+++ b/intern/cycles/util/util_system.cpp
@@ -11,11 +11,12 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#include "util_system.h"
#include "util_types.h"
+#include "util_string.h"
#ifdef _WIN32
#if(!defined(FREE_WINDOWS))
@@ -75,14 +76,6 @@ static void __cpuid(int data[4], int selector)
}
#endif
-static void replace_string(string& haystack, const string& needle, const string& other)
-{
- size_t i;
-
- while((i = haystack.find(needle)) != string::npos)
- haystack.replace(i, needle.length(), other);
-}
-
string system_cpu_brand_string()
{
char buf[48];
@@ -98,10 +91,7 @@ string system_cpu_brand_string()
string brand = buf;
/* make it a bit more presentable */
- replace_string(brand, "(TM)", "");
- replace_string(brand, "(R)", "");
-
- brand = string_strip(brand);
+ brand = string_remove_trademark(brand);
return brand;
}
@@ -127,6 +117,7 @@ struct CPUCapabilities {
bool sse42;
bool sse4a;
bool avx;
+ bool f16c;
bool avx2;
bool xop;
bool fma3;
@@ -135,24 +126,42 @@ struct CPUCapabilities {
bool bmi2;
};
+static void system_cpu_capabilities_override(CPUCapabilities *caps)
+{
+ /* Only capabilities which affects on cycles kernel. */
+ if(getenv("CYCLES_CPU_NO_AVX2")) {
+ caps->avx2 = false;
+ }
+ if(getenv("CYCLES_CPU_NO_AVX")) {
+ caps->avx = false;
+ }
+ if(getenv("CYCLES_CPU_NO_SSE41")) {
+ caps->sse41 = false;
+ }
+ if(getenv("CYCLES_CPU_NO_SSE3")) {
+ caps->sse3 = false;
+ }
+ if(getenv("CYCLES_CPU_NO_SSE2")) {
+ caps->sse2 = false;
+ }
+ if(getenv("CYCLES_CPU_NO_SSE")) {
+ caps->sse = false;
+ }
+}
+
static CPUCapabilities& system_cpu_capabilities()
{
static CPUCapabilities caps;
static bool caps_init = false;
if(!caps_init) {
- int result[4], num; //, num_ex;
+ int result[4], num;
memset(&caps, 0, sizeof(caps));
__cpuid(result, 0);
num = result[0];
-#if 0
- __cpuid(result, 0x80000000);
- num_ex = result[0];
-#endif
-
if(num >= 1) {
__cpuid(result, 0x00000001);
caps.mmx = (result[3] & ((int)1 << 23)) != 0;
@@ -184,21 +193,15 @@ static CPUCapabilities& system_cpu_capabilities()
caps.avx = (xcr_feature_mask & 0x6) == 0x6;
}
+ caps.f16c = (result[2] & ((int)1 << 29)) != 0;
+
__cpuid(result, 0x00000007);
caps.bmi1 = (result[1] & ((int)1 << 3)) != 0;
caps.bmi2 = (result[1] & ((int)1 << 8)) != 0;
caps.avx2 = (result[1] & ((int)1 << 5)) != 0;
}
-#if 0
- if(num_ex >= 0x80000001) {
- __cpuid(result, 0x80000001);
- caps.x64 = (result[3] & ((int)1 << 29)) != 0;
- caps.sse4a = (result[2] & ((int)1 << 6)) != 0;
- caps.fma4 = (result[2] & ((int)1 << 16)) != 0;
- caps.xop = (result[2] & ((int)1 << 11)) != 0;
- }
-#endif
+ system_cpu_capabilities_override(&caps);
caps_init = true;
}
@@ -232,7 +235,7 @@ bool system_cpu_support_avx()
bool system_cpu_support_avx2()
{
CPUCapabilities& caps = system_cpu_capabilities();
- return caps.sse && caps.sse2 && caps.sse3 && caps.ssse3 && caps.sse41 && caps.avx && caps.avx2 && caps.fma3 && caps.bmi1 && caps.bmi2;
+ return caps.sse && caps.sse2 && caps.sse3 && caps.ssse3 && caps.sse41 && caps.avx && caps.f16c && caps.avx2 && caps.fma3 && caps.bmi1 && caps.bmi2;
}
#else
diff --git a/intern/cycles/util/util_system.h b/intern/cycles/util/util_system.h
index 0e8868c7dfc..4e7e00f85fd 100644
--- a/intern/cycles/util/util_system.h
+++ b/intern/cycles/util/util_system.h
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#ifndef __UTIL_SYSTEM_H__
diff --git a/intern/cycles/util/util_task.cpp b/intern/cycles/util/util_task.cpp
index 14a81ecbb05..d56553d1d4a 100644
--- a/intern/cycles/util/util_task.cpp
+++ b/intern/cycles/util/util_task.cpp
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#include "util_debug.h"
@@ -237,7 +237,7 @@ bool TaskScheduler::thread_wait_pop(Entry& entry)
return true;
}
-void TaskScheduler::thread_run(int thread_id)
+void TaskScheduler::thread_run(int /*thread_id*/)
{
Entry entry;
diff --git a/intern/cycles/util/util_task.h b/intern/cycles/util/util_task.h
index 42a1e2f5a58..debcff3b776 100644
--- a/intern/cycles/util/util_task.h
+++ b/intern/cycles/util/util_task.h
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#ifndef __UTIL_TASK_H__
@@ -27,7 +27,7 @@ class Task;
class TaskPool;
class TaskScheduler;
-typedef boost::function<void(void)> TaskRunFunction;
+typedef function<void(void)> TaskRunFunction;
/* Task
*
diff --git a/intern/cycles/util/util_thread.h b/intern/cycles/util/util_thread.h
index f2698d043fb..9c19235d41d 100644
--- a/intern/cycles/util/util_thread.h
+++ b/intern/cycles/util/util_thread.h
@@ -11,13 +11,20 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#ifndef __UTIL_THREAD_H__
#define __UTIL_THREAD_H__
-#include <boost/thread.hpp>
+#if (__cplusplus > 199711L) || (defined(_MSC_VER) && _MSC_VER >= 1800)
+# include <thread>
+# include <mutex>
+# include <condition_variable>
+# include <functional>
+#else
+# include <boost/thread.hpp>
+#endif
#include <pthread.h>
#include <queue>
@@ -25,18 +32,24 @@
CCL_NAMESPACE_BEGIN
+#if (__cplusplus > 199711L) || (defined(_MSC_VER) && _MSC_VER >= 1800)
+typedef std::mutex thread_mutex;
+typedef std::unique_lock<std::mutex> thread_scoped_lock;
+typedef std::condition_variable thread_condition_variable;
+#else
/* use boost for mutexes */
-
typedef boost::mutex thread_mutex;
typedef boost::mutex::scoped_lock thread_scoped_lock;
typedef boost::condition_variable thread_condition_variable;
+#endif
/* own pthread based implementation, to avoid boost version conflicts with
* dynamically loaded blender plugins */
class thread {
public:
- thread(boost::function<void(void)> run_cb_)
+ thread(function<void(void)> run_cb_)
+
{
joined = false;
run_cb = run_cb_;
@@ -63,7 +76,7 @@ public:
}
protected:
- boost::function<void(void)> run_cb;
+ function<void(void)> run_cb;
pthread_t pthread_id;
bool joined;
};
diff --git a/intern/cycles/util/util_time.cpp b/intern/cycles/util/util_time.cpp
index dd91b024940..964f9f1a7af 100644
--- a/intern/cycles/util/util_time.cpp
+++ b/intern/cycles/util/util_time.cpp
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#include <stdlib.h>
@@ -71,7 +71,7 @@ void time_sleep(double t)
/* get microseconds */
int us = (int)(t * 1e6);
- if (us > 0)
+ if(us > 0)
usleep(us);
}
diff --git a/intern/cycles/util/util_time.h b/intern/cycles/util/util_time.h
index 3df17272e2f..14ffea7f3da 100644
--- a/intern/cycles/util/util_time.h
+++ b/intern/cycles/util/util_time.h
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#ifndef __UTIL_TIME_H__
diff --git a/intern/cycles/util/util_transform.cpp b/intern/cycles/util/util_transform.cpp
index 14613558501..acaca69464c 100644
--- a/intern/cycles/util/util_transform.cpp
+++ b/intern/cycles/util/util_transform.cpp
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
/*
@@ -46,9 +46,11 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include "util_math.h"
#include "util_transform.h"
+#include "util_boundbox.h"
+#include "util_math.h"
+
CCL_NAMESPACE_BEGIN
/* Transform Inverse */
@@ -271,5 +273,15 @@ void transform_motion_decompose(DecompMotionTransform *decomp, const MotionTrans
decomp->post_y = post.y;
}
-CCL_NAMESPACE_END
+Transform transform_from_viewplane(BoundBox2D& viewplane)
+{
+ return
+ transform_scale(1.0f / (viewplane.right - viewplane.left),
+ 1.0f / (viewplane.top - viewplane.bottom),
+ 1.0f) *
+ transform_translate(-viewplane.left,
+ -viewplane.bottom,
+ 0.0f);
+}
+CCL_NAMESPACE_END
diff --git a/intern/cycles/util/util_transform.h b/intern/cycles/util/util_transform.h
index 5b3dbe42f69..ba8d04b5c16 100644
--- a/intern/cycles/util/util_transform.h
+++ b/intern/cycles/util/util_transform.h
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#ifndef __UTIL_TRANSFORM_H__
@@ -55,6 +55,11 @@ typedef struct DecompMotionTransform {
float4 post_x, post_y;
} DecompMotionTransform;
+typedef struct PerspectiveMotionTransform {
+ Transform pre;
+ Transform post;
+} PerspectiveMotionTransform;
+
/* Functions */
ccl_device_inline float3 transform_perspective(const Transform *t, const float3 a)
@@ -216,12 +221,13 @@ ccl_device_inline Transform transform_rotate(float angle, float3 axis)
0.0f, 0.0f, 0.0f, 1.0f);
}
+/* Euler is assumed to be in XYZ order. */
ccl_device_inline Transform transform_euler(float3 euler)
{
return
- transform_rotate(euler.x, make_float3(1.0f, 0.0f, 0.0f)) *
+ transform_rotate(euler.z, make_float3(0.0f, 0.0f, 1.0f)) *
transform_rotate(euler.y, make_float3(0.0f, 1.0f, 0.0f)) *
- transform_rotate(euler.z, make_float3(0.0f, 0.0f, 1.0f));
+ transform_rotate(euler.x, make_float3(1.0f, 0.0f, 0.0f));
}
ccl_device_inline Transform transform_orthographic(float znear, float zfar)
@@ -448,6 +454,8 @@ ccl_device void transform_motion_interpolate(Transform *tfm, const DecompMotionT
#ifndef __KERNEL_GPU__
+class BoundBox2D;
+
ccl_device_inline bool operator==(const MotionTransform& A, const MotionTransform& B)
{
return (A.pre == B.pre && A.post == B.post);
@@ -455,9 +463,41 @@ ccl_device_inline bool operator==(const MotionTransform& A, const MotionTransfor
float4 transform_to_quat(const Transform& tfm);
void transform_motion_decompose(DecompMotionTransform *decomp, const MotionTransform *motion, const Transform *mid);
+Transform transform_from_viewplane(BoundBox2D& viewplane);
#endif
+/* TODO(sergey): This is only for until we've got OpenCL 2.0
+ * on all devices we consider supported. It'll be replaced with
+ * generic address space.
+ */
+
+#ifdef __KERNEL_OPENCL__
+
+#define OPENCL_TRANSFORM_ADDRSPACE_GLUE(a, b) a ## b
+#define OPENCL_TRANSFORM_ADDRSPACE_DECLARE(function) \
+ccl_device_inline float3 OPENCL_TRANSFORM_ADDRSPACE_GLUE(function, _addrspace)( \
+ ccl_addr_space const Transform *t, const float3 a) \
+{ \
+ Transform private_tfm = *t; \
+ return function(&private_tfm, a); \
+}
+
+OPENCL_TRANSFORM_ADDRSPACE_DECLARE(transform_point)
+OPENCL_TRANSFORM_ADDRSPACE_DECLARE(transform_direction)
+OPENCL_TRANSFORM_ADDRSPACE_DECLARE(transform_direction_transposed)
+
+# undef OPENCL_TRANSFORM_ADDRSPACE_DECLARE
+# undef OPENCL_TRANSFORM_ADDRSPACE_GLUE
+# define transform_point_auto transform_point_addrspace
+# define transform_direction_auto transform_direction_addrspace
+# define transform_direction_transposed_auto transform_direction_transposed_addrspace
+#else
+# define transform_point_auto transform_point
+# define transform_direction_auto transform_direction
+# define transform_direction_transposed_auto transform_direction_transposed
+#endif
+
CCL_NAMESPACE_END
#endif /* __UTIL_TRANSFORM_H__ */
diff --git a/intern/cycles/util/util_types.h b/intern/cycles/util/util_types.h
index 2a199e591bf..6f474f873a6 100644
--- a/intern/cycles/util/util_types.h
+++ b/intern/cycles/util/util_types.h
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#ifndef __UTIL_TYPES_H__
@@ -33,11 +33,7 @@
#ifndef __KERNEL_GPU__
-# ifdef NDEBUG
-# define ccl_device static inline
-# else
-# define ccl_device static
-# endif
+#define ccl_device static inline
#define ccl_device_noinline static
#define ccl_global
#define ccl_constant
@@ -53,11 +49,7 @@
#define ccl_try_align(...) /* not support for function arguments (error C2719) */
#endif
#define ccl_may_alias
-# ifdef NDEBUG
-# define ccl_always_inline __forceinline
-# else
-# define ccl_always_inline
-# endif
+#define ccl_always_inline __forceinline
#define ccl_maybe_unused
#else
@@ -272,6 +264,19 @@ struct ccl_try_align(16) float4 {
__forceinline float& operator[](int i) { return *(&x + i); }
};
+template<typename T>
+class vector3
+{
+public:
+ T x, y, z;
+
+ ccl_always_inline vector3() {}
+ ccl_always_inline vector3(const T& a)
+ : x(a), y(a), z(a) {}
+ ccl_always_inline vector3(const T& x, const T& y, const T& z)
+ : x(x), y(y), z(z) {}
+};
+
#endif
#ifndef __KERNEL_GPU__
@@ -465,6 +470,19 @@ enum InterpolationType {
INTERPOLATION_SMART = 3,
};
+/* Extension types for textures.
+ *
+ * Defines how the image is extrapolated past its original bounds.
+ */
+enum ExtensionType {
+ /* Cause the image to repeat horizontally and vertically. */
+ EXTENSION_REPEAT = 0,
+ /* Extend by repeating edge pixels of the image. */
+ EXTENSION_EXTEND = 1,
+ /* Clip to image size and set exterior pixels as transparent. */
+ EXTENSION_CLIP = 2,
+};
+
/* macros */
/* hints for branch prediction, only use in code that runs a _lot_ */
@@ -476,18 +494,32 @@ enum InterpolationType {
# define UNLIKELY(x) (x)
#endif
+#if defined(__cplusplus) && ((__cplusplus >= 201103L) || (defined(_MSC_VER) && _MSC_VER >= 1800))
+# define HAS_CPP11_FEATURES
+#endif
+
+#if defined(__GNUC__) || defined(__clang__)
+# if defined(HAS_CPP11_FEATURES)
+/* Some magic to be sure we don't have reference in the type. */
+template<typename T> static inline T decltype_helper(T x) { return x; }
+# define TYPEOF(x) decltype(decltype_helper(x))
+# else
+# define TYPEOF(x) typeof(x)
+# endif
+#endif
+
/* Causes warning:
* incompatible types when assigning to type 'Foo' from type 'Bar'
* ... the compiler optimizes away the temp var */
#ifdef __GNUC__
#define CHECK_TYPE(var, type) { \
- typeof(var) *__tmp; \
+ TYPEOF(var) *__tmp; \
__tmp = (type *)NULL; \
(void)__tmp; \
} (void)0
#define CHECK_TYPE_PAIR(var_a, var_b) { \
- typeof(var_a) *__tmp; \
+ TYPEOF(var_a) *__tmp; \
__tmp = (typeof(var_b) *)NULL; \
(void)__tmp; \
} (void)0
diff --git a/intern/cycles/util/util_vector.h b/intern/cycles/util/util_vector.h
index cc6e8a371ed..ee1f997721d 100644
--- a/intern/cycles/util/util_vector.h
+++ b/intern/cycles/util/util_vector.h
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#ifndef __UTIL_VECTOR_H__
@@ -19,34 +19,74 @@
/* Vector */
-#include <string.h>
+#include <cassert>
+#include <cstring>
#include <vector>
+#include "util_aligned_malloc.h"
#include "util_types.h"
-CCL_NAMESPACE_BEGIN
+#ifdef WITH_CYCLES_DEBUG
+# include "util_guarded_allocator.h"
+#endif
-using std::vector;
+CCL_NAMESPACE_BEGIN
-static inline void *malloc_aligned(size_t size, size_t alignment)
+/* Vector
+ *
+ * Own subclass-ed vestion of std::vector. Subclass is needed because:
+ *
+ * - When building with WITH_CYCLES_DEBUG we need to use own allocator which
+ * keeps track of used/peak memory.
+ *
+ * - Have method to ensure capacity is re-set to 0.
+ */
+template<typename value_type,
+#ifdef WITH_CYCLES_DEBUG
+ typename allocator_type = GuardedAllocator<value_type>
+#else
+ typename allocator_type = std::allocator<value_type>
+#endif
+ >
+class vector : public std::vector<value_type, allocator_type>
{
- void *data = (void*)malloc(size + sizeof(void*) + alignment - 1);
+public:
+ /* Default constructor. */
+ explicit vector() : std::vector<value_type, allocator_type>() { }
- union { void *ptr; size_t offset; } u;
- u.ptr = (char*)data + sizeof(void*);
- u.offset = (u.offset + alignment - 1) & ~(alignment - 1);
- *(((void**)u.ptr) - 1) = data;
+ /* Fill constructor. */
+ explicit vector(size_t n, const value_type& val = value_type())
+ : std::vector<value_type, allocator_type>(n, val) { }
- return u.ptr;
-}
+ /* Range constructor. */
+ template <class InputIterator>
+ vector(InputIterator first, InputIterator last)
+ : std::vector<value_type, allocator_type>(first, last) { }
-static inline void free_aligned(void *ptr)
-{
- if(ptr) {
- void *data = *(((void**)ptr) - 1);
- free(data);
+ /* Copy constructor. */
+ vector(const vector &x) : std::vector<value_type, allocator_type>(x) { }
+
+ void shrink_to_fit(void)
+ {
+#if __cplusplus < 201103L
+ vector<value_type>().swap(*this);
+#else
+ std::vector<value_type, allocator_type>::shrink_to_fit();
+#endif
}
-}
+
+ void free_memory(void)
+ {
+ std::vector<value_type, allocator_type>::resize(0);
+ shrink_to_fit();
+ }
+
+ /* Some external API might demand working with std::vector. */
+ operator std::vector<value_type>()
+ {
+ return std::vector<value_type>(*this);
+ }
+};
/* Array
*
@@ -65,6 +105,7 @@ public:
{
data = NULL;
datasize = 0;
+ capacity = 0;
}
array(size_t newsize)
@@ -72,10 +113,12 @@ public:
if(newsize == 0) {
data = NULL;
datasize = 0;
+ capacity = 0;
}
else {
- data = (T*)malloc_aligned(sizeof(T)*newsize, alignment);
+ data = (T*)util_aligned_malloc(sizeof(T)*newsize, alignment);
datasize = newsize;
+ capacity = datasize;
}
}
@@ -89,11 +132,13 @@ public:
if(from.datasize == 0) {
data = NULL;
datasize = 0;
+ capacity = 0;
}
else {
- data = (T*)malloc_aligned(sizeof(T)*from.datasize, alignment);
+ data = (T*)util_aligned_malloc(sizeof(T)*from.datasize, alignment);
memcpy(data, from.data, from.datasize*sizeof(T));
datasize = from.datasize;
+ capacity = datasize;
}
return *this;
@@ -102,13 +147,11 @@ public:
array& operator=(const vector<T>& from)
{
datasize = from.size();
+ capacity = datasize;
data = NULL;
if(datasize > 0) {
- data = (T*)malloc_aligned(sizeof(T)*datasize, alignment);
- memcpy(data, &from[0], datasize*sizeof(T));
- free_aligned(data);
- data = (T*)malloc_aligned(sizeof(T)*datasize, alignment);
+ data = (T*)util_aligned_malloc(sizeof(T)*datasize, alignment);
memcpy(data, &from[0], datasize*sizeof(T));
}
@@ -117,7 +160,7 @@ public:
~array()
{
- free_aligned(data);
+ util_aligned_free(data);
}
void resize(size_t newsize)
@@ -126,22 +169,25 @@ public:
clear();
}
else if(newsize != datasize) {
- T *newdata = (T*)malloc_aligned(sizeof(T)*newsize, alignment);
- if(data) {
- memcpy(newdata, data, ((datasize < newsize)? datasize: newsize)*sizeof(T));
- free_aligned(data);
+ if(newsize > capacity) {
+ T *newdata = (T*)util_aligned_malloc(sizeof(T)*newsize, alignment);
+ if(data) {
+ memcpy(newdata, data, ((datasize < newsize)? datasize: newsize)*sizeof(T));
+ util_aligned_free(data);
+ }
+ data = newdata;
+ capacity = newsize;
}
-
- data = newdata;
datasize = newsize;
}
}
void clear()
{
- free_aligned(data);
+ util_aligned_free(data);
data = NULL;
datasize = 0;
+ capacity = 0;
}
size_t size() const
@@ -151,12 +197,26 @@ public:
T& operator[](size_t i) const
{
+ assert(i < datasize);
return data[i];
}
+ void reserve(size_t newcapacity) {
+ if(newcapacity > capacity) {
+ T *newdata = (T*)util_aligned_malloc(sizeof(T)*newcapacity, alignment);
+ if(data) {
+ memcpy(newdata, data, ((datasize < newcapacity)? datasize: newcapacity)*sizeof(T));
+ util_aligned_free(data);
+ }
+ data = newdata;
+ capacity = newcapacity;
+ }
+ }
+
protected:
T *data;
size_t datasize;
+ size_t capacity;
};
CCL_NAMESPACE_END
diff --git a/intern/cycles/util/util_view.cpp b/intern/cycles/util/util_view.cpp
index 6bf9c9ed8c0..9b5cd22fb4a 100644
--- a/intern/cycles/util/util_view.cpp
+++ b/intern/cycles/util/util_view.cpp
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#include <stdio.h>
@@ -98,7 +98,7 @@ void view_display_help()
glColor3f(0.8f, 0.8f, 0.8f);
view_display_text(x1+20, y2-20, "Cycles Renderer");
- view_display_text(x1+20, y2-40, "(C) 2011-2014 Blender Foundation");
+ view_display_text(x1+20, y2-40, "(C) 2011-2015 Blender Foundation");
view_display_text(x1+20, y2-80, "Controls:");
view_display_text(x1+20, y2-100, "h: Info/Help");
view_display_text(x1+20, y2-120, "r: Reset");
@@ -110,6 +110,7 @@ void view_display_help()
view_display_text(x1+20, y2-230, "Left mouse: Move camera");
view_display_text(x1+20, y2-250, "Right mouse: Rotate camera");
view_display_text(x1+20, y2-270, "W/A/S/D: Move camera");
+ view_display_text(x1+20, y2-290, "0/1/2/3: Set max bounces");
glColor3f(1.0f, 1.0f, 1.0f);
}
@@ -248,7 +249,7 @@ void view_main_loop(const char *title, int width, int height,
glutInitDisplayMode(GLUT_RGB|GLUT_DOUBLE|GLUT_DEPTH);
glutCreateWindow(title);
- glewInit();
+ mxMakeCurrentContext(mxCreateContext());
view_reshape(width, height);
diff --git a/intern/cycles/util/util_view.h b/intern/cycles/util/util_view.h
index 65d890eb6af..5def0564175 100644
--- a/intern/cycles/util/util_view.h
+++ b/intern/cycles/util/util_view.h
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#ifndef __UTIL_VIEW_H__
diff --git a/intern/cycles/util/util_xml.h b/intern/cycles/util/util_xml.h
index 9d1ebc2114a..cfd0afc95f7 100644
--- a/intern/cycles/util/util_xml.h
+++ b/intern/cycles/util/util_xml.h
@@ -11,15 +11,15 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#ifndef __UTIL_XML_H__
#define __UTIL_XML_H__
-/* PugiXML from OpenImageIO is used for XML parsing. */
+/* PugiXML is used for XML parsing. */
-#include <OpenImageIO/pugixml.hpp>
+#include <pugixml.hpp>
CCL_NAMESPACE_BEGIN
diff --git a/intern/dualcon/CMakeLists.txt b/intern/dualcon/CMakeLists.txt
index da5e10fe6a7..40c8ef8ff9c 100644
--- a/intern/dualcon/CMakeLists.txt
+++ b/intern/dualcon/CMakeLists.txt
@@ -22,7 +22,7 @@ set(INC
)
set(INC_SYS
- ../../extern/Eigen3
+ ${EIGEN3_INCLUDE_DIRS}
)
set(SRC
diff --git a/intern/dualcon/dualcon.h b/intern/dualcon/dualcon.h
index c1452a72970..6ec63f4fdac 100644
--- a/intern/dualcon/dualcon.h
+++ b/intern/dualcon/dualcon.h
@@ -32,17 +32,25 @@ extern "C" {
#endif
typedef float (*DualConCo)[3];
-typedef unsigned int (*DualConFaces)[4];
+
+typedef unsigned int (*DualConTri)[3];
+
+typedef unsigned int (*DualConLoop);
+
struct DerivedMesh;
typedef struct DualConInput {
+ DualConLoop mloop;
+
DualConCo co;
int co_stride;
int totco;
- DualConFaces faces;
- int face_stride;
- int totface;
+ DualConTri looptri;
+ int tri_stride;
+ int tottri;
+
+ int loop_stride;
float min[3], max[3];
} DualConInput;
diff --git a/intern/dualcon/intern/Projections.cpp b/intern/dualcon/intern/Projections.cpp
index e85589e3ff5..601812e1e21 100644
--- a/intern/dualcon/intern/Projections.cpp
+++ b/intern/dualcon/intern/Projections.cpp
@@ -158,7 +158,7 @@ static void create_projection_axes(int64_t axes[NUM_AXES][3], const int64_t tri[
/**
* Construction from a cube (axes aligned) and triangle
*/
-CubeTriangleIsect::CubeTriangleIsect(int64_t cube[2][3], int64_t tri[3][3], int64_t error, int triind)
+CubeTriangleIsect::CubeTriangleIsect(int64_t cube[2][3], int64_t tri[3][3], int64_t /*error*/, int triind)
{
int i;
inherit = new TriangleProjection;
diff --git a/intern/dualcon/intern/dualcon_c_api.cpp b/intern/dualcon/intern/dualcon_c_api.cpp
index 6c3ec4dcc3b..e55de2ed354 100644
--- a/intern/dualcon/intern/dualcon_c_api.cpp
+++ b/intern/dualcon/intern/dualcon_c_api.cpp
@@ -39,17 +39,20 @@ static void veccopy(float dst[3], const float src[3])
dst[2] = src[2];
}
-#define GET_FACE(_mesh, _n) \
- (*(DualConFaces)(((char *)(_mesh)->faces) + ((_n) * (_mesh)->face_stride)))
+#define GET_TRI(_mesh, _n) \
+ (*(DualConTri)(((char *)(_mesh)->looptri) + ((_n) * (_mesh)->tri_stride)))
#define GET_CO(_mesh, _n) \
(*(DualConCo)(((char *)(_mesh)->co) + ((_n) * (_mesh)->co_stride)))
+#define GET_LOOP(_mesh, _n) \
+ (*(DualConLoop)(((char *)(_mesh)->mloop) + ((_n) * (_mesh)->loop_stride)))
+
class DualConInputReader : public ModelReader
{
private:
const DualConInput *input_mesh;
-int tottri, curface, offset;
+int tottri, curtri;
float min[3], max[3], maxsize;
float scale;
public:
@@ -61,14 +64,9 @@ DualConInputReader(const DualConInput *mesh, float _scale)
void reset()
{
- tottri = 0;
- curface = 0;
- offset = 0;
+ curtri = 0;
maxsize = 0;
-
- /* initialize tottri */
- for (int i = 0; i < input_mesh->totface; i++)
- tottri += GET_FACE(input_mesh, i)[3] ? 2 : 1;
+ tottri = input_mesh->tottri;
veccopy(min, input_mesh->min);
veccopy(max, input_mesh->max);
@@ -94,29 +92,17 @@ void reset()
Triangle *getNextTriangle()
{
- if (curface == input_mesh->totface)
- return 0;
+ if (curtri == input_mesh->tottri)
+ return NULL;
Triangle *t = new Triangle();
- unsigned int *f = GET_FACE(input_mesh, curface);
- if (offset == 0) {
- veccopy(t->vt[0], GET_CO(input_mesh, f[0]));
- veccopy(t->vt[1], GET_CO(input_mesh, f[1]));
- veccopy(t->vt[2], GET_CO(input_mesh, f[2]));
- }
- else {
- veccopy(t->vt[0], GET_CO(input_mesh, f[2]));
- veccopy(t->vt[1], GET_CO(input_mesh, f[3]));
- veccopy(t->vt[2], GET_CO(input_mesh, f[0]));
- }
+ unsigned int *tr = GET_TRI(input_mesh, curtri);
+ veccopy(t->vt[0], GET_CO(input_mesh, GET_LOOP(input_mesh, tr[0])));
+ veccopy(t->vt[1], GET_CO(input_mesh, GET_LOOP(input_mesh, tr[1])));
+ veccopy(t->vt[2], GET_CO(input_mesh, GET_LOOP(input_mesh, tr[2])));
- if (offset == 0 && f[3])
- offset++;
- else {
- offset = 0;
- curface++;
- }
+ curtri++;
/* remove triangle if it contains invalid coords */
for (int i = 0; i < 3; i++) {
@@ -132,27 +118,15 @@ Triangle *getNextTriangle()
int getNextTriangle(int t[3])
{
- if (curface == input_mesh->totface)
+ if (curtri == input_mesh->tottri)
return 0;
- unsigned int *f = GET_FACE(input_mesh, curface);
- if (offset == 0) {
- t[0] = f[0];
- t[1] = f[1];
- t[2] = f[2];
- }
- else {
- t[0] = f[2];
- t[1] = f[3];
- t[2] = f[0];
- }
+ unsigned int *tr = GET_TRI(input_mesh, curtri);
+ t[0] = tr[0];
+ t[1] = tr[1];
+ t[2] = tr[2];
- if (offset == 0 && f[3])
- offset++;
- else {
- offset = 0;
- curface++;
- }
+ curtri++;
return 1;
}
@@ -174,7 +148,7 @@ float getBoundingBox(float origin[3])
}
/* output */
-void getNextVertex(float v[3])
+void getNextVertex(float /*v*/[3])
{
/* not used */
}
diff --git a/intern/dualcon/intern/octree.cpp b/intern/dualcon/intern/octree.cpp
index bd7194cf3fd..da8638ebc4f 100644
--- a/intern/dualcon/intern/octree.cpp
+++ b/intern/dualcon/intern/octree.cpp
@@ -1448,7 +1448,7 @@ Node *Octree::locateCell(InternalNode *node, int st[3], int len, int ori[3], int
return (Node *)node;
}
-void Octree::checkElement(PathElement *ele)
+void Octree::checkElement(PathElement * /*ele*/)
{
/*
if(ele != NULL && locateLeafCheck(ele->pos) != ele->node) {
@@ -1797,7 +1797,7 @@ void Octree::clearProcessBits(Node *node, int height)
}
}
-int Octree::floodFill(LeafNode *leaf, int st[3], int len, int height, int threshold)
+int Octree::floodFill(LeafNode *leaf, int st[3], int len, int /*height*/, int threshold)
{
int i, j;
int maxtotal = 0;
@@ -2317,7 +2317,7 @@ void Octree::generateMinimizer(Node *node, int st[3], int len, int height, int&
}
}
-void Octree::processEdgeWrite(Node *node[4], int depth[4], int maxdep, int dir)
+void Octree::processEdgeWrite(Node *node[4], int /*depth*/[4], int /*maxdep*/, int dir)
{
//int color = 0;
@@ -2553,7 +2553,7 @@ void Octree::cellProcContour(Node *node, int leaf, int depth)
}
-void Octree::processEdgeParity(LeafNode *node[4], int depth[4], int maxdep, int dir)
+void Octree::processEdgeParity(LeafNode *node[4], int /*depth*/[4], int /*maxdep*/, int dir)
{
int con = 0;
for (int i = 0; i < 4; i++) {
diff --git a/intern/ghost/CMakeLists.txt b/intern/ghost/CMakeLists.txt
index cfa2f54f53e..761bcb4dd27 100644
--- a/intern/ghost/CMakeLists.txt
+++ b/intern/ghost/CMakeLists.txt
@@ -25,6 +25,7 @@
set(INC
.
+ ../glew-mx
../string
../../source/blender/imbuf
../../source/blender/makesdna
@@ -38,6 +39,8 @@ set(SRC
intern/GHOST_Buttons.cpp
intern/GHOST_C-api.cpp
intern/GHOST_CallbackEventConsumer.cpp
+ intern/GHOST_Context.cpp
+ intern/GHOST_ContextNone.cpp
intern/GHOST_DisplayManager.cpp
intern/GHOST_EventManager.cpp
intern/GHOST_ISystem.cpp
@@ -63,6 +66,8 @@ set(SRC
intern/GHOST_Buttons.h
intern/GHOST_CallbackEventConsumer.h
+ intern/GHOST_Context.h
+ intern/GHOST_ContextNone.h
intern/GHOST_Debug.h
intern/GHOST_DisplayManager.h
intern/GHOST_Event.h
@@ -120,68 +125,48 @@ if(WITH_HEADLESS OR WITH_GHOST_SDL)
intern/GHOST_DisplayManagerSDL.cpp
intern/GHOST_SystemSDL.cpp
intern/GHOST_WindowSDL.cpp
+ intern/GHOST_ContextSDL.cpp
intern/GHOST_DisplayManagerSDL.h
intern/GHOST_SystemSDL.h
intern/GHOST_WindowSDL.h
+ intern/GHOST_ContextSDL.h
)
add_definitions(-DWITH_GHOST_SDL)
endif()
-
- # ack, this is still system dependent
- if(APPLE)
- list(APPEND SRC
- intern/GHOST_SystemPathsCocoa.mm
- intern/GHOST_SystemPathsCocoa.h
- )
-
- elseif(UNIX)
- list(APPEND SRC
- intern/GHOST_SystemPathsX11.cpp
- intern/GHOST_SystemPathsX11.h
- )
-
- if(NOT WITH_INSTALL_PORTABLE)
- add_definitions(-DPREFIX="${CMAKE_INSTALL_PREFIX}")
- endif()
-
- elseif(WIN32)
- list(APPEND SRC
- intern/GHOST_SystemPathsWin32.cpp
-
- intern/GHOST_SystemPathsWin32.h
- )
-
- list(APPEND INC
- ../utfconv
- )
- endif()
-
if(NOT WITH_HEADLESS)
list(APPEND INC_SYS
${SDL_INCLUDE_DIR}
)
endif()
-elseif(APPLE)
+elseif(APPLE AND NOT WITH_X11)
list(APPEND SRC
intern/GHOST_DisplayManagerCocoa.mm
intern/GHOST_SystemCocoa.mm
- intern/GHOST_SystemPathsCocoa.mm
intern/GHOST_WindowCocoa.mm
intern/GHOST_DisplayManagerCocoa.h
intern/GHOST_SystemCocoa.h
- intern/GHOST_SystemPathsCocoa.h
intern/GHOST_WindowCocoa.h
)
+ if(NOT WITH_GL_EGL)
+ list(APPEND SRC
+ intern/GHOST_ContextCGL.mm
+
+ intern/GHOST_ContextCGL.h
+ )
+ endif()
+
if(WITH_INPUT_NDOF)
list(APPEND SRC
intern/GHOST_NDOFManagerCocoa.mm
+
intern/GHOST_NDOFManagerCocoa.h
)
+
list(APPEND SRC_NDOF3DCONNEXION
intern/GHOST_NDOFManager3Dconnexion.c
intern/GHOST_NDOFManager3Dconnexion.h
@@ -192,8 +177,7 @@ elseif(APPLE)
add_definitions(-DWITH_QUICKTIME)
endif()
-elseif(UNIX)
-
+elseif(WITH_X11)
list(APPEND INC_SYS
${X11_X11_INCLUDE_PATH}
)
@@ -201,15 +185,21 @@ elseif(UNIX)
list(APPEND SRC
intern/GHOST_DisplayManagerX11.cpp
intern/GHOST_SystemX11.cpp
- intern/GHOST_SystemPathsX11.cpp
intern/GHOST_WindowX11.cpp
intern/GHOST_DisplayManagerX11.h
intern/GHOST_SystemX11.h
- intern/GHOST_SystemPathsX11.h
intern/GHOST_WindowX11.h
)
+ if(NOT WITH_GL_EGL)
+ list(APPEND SRC
+ intern/GHOST_ContextGLX.cpp
+
+ intern/GHOST_ContextGLX.h
+ )
+ endif()
+
if(WITH_GHOST_XDND)
add_definitions(-DWITH_XDND)
@@ -257,6 +247,8 @@ elseif(UNIX)
)
endif()
+ add_definitions(-DWITH_X11)
+
elseif(WIN32)
## Warnings as errors, this is too strict!
#if(MSVC)
@@ -267,25 +259,37 @@ elseif(WIN32)
${WINTAB_INC}
)
- list(APPEND INC
- ../utfconv
- )
-
list(APPEND SRC
intern/GHOST_DisplayManagerWin32.cpp
intern/GHOST_SystemWin32.cpp
- intern/GHOST_SystemPathsWin32.cpp
intern/GHOST_WindowWin32.cpp
intern/GHOST_DropTargetWin32.cpp
intern/GHOST_DisplayManagerWin32.h
intern/GHOST_DropTargetWin32.h
intern/GHOST_SystemWin32.h
- intern/GHOST_SystemPathsWin32.h
intern/GHOST_WindowWin32.h
intern/GHOST_TaskbarWin32.h
)
+ if(NOT WITH_GL_EGL)
+ list(APPEND SRC
+ intern/GHOST_ContextWGL.cpp
+
+ intern/GHOST_ContextWGL.h
+ )
+ endif()
+
+ if(WITH_INPUT_IME)
+ add_definitions(-DWITH_INPUT_IME)
+
+ list(APPEND SRC
+ intern/GHOST_ImeWin32.cpp
+
+ intern/GHOST_ImeWin32.h
+ )
+ endif()
+
if(WITH_INPUT_NDOF)
list(APPEND SRC
intern/GHOST_NDOFManagerWin32.cpp
@@ -293,10 +297,45 @@ elseif(WIN32)
intern/GHOST_NDOFManagerWin32.h
)
endif()
+endif()
+
+if(WITH_GL_EGL AND NOT (WITH_HEADLESS OR WITH_GHOST_SDL))
+ list(APPEND SRC
+ intern/GHOST_ContextEGL.cpp
+
+ intern/GHOST_ContextEGL.h
+ )
+endif()
+
+if(APPLE)
+ list(APPEND SRC
+ intern/GHOST_SystemPathsCocoa.mm
+ intern/GHOST_SystemPathsCocoa.h
+ )
+
+elseif(UNIX)
+ list(APPEND SRC
+ intern/GHOST_SystemPathsX11.cpp
+ intern/GHOST_SystemPathsX11.h
+ )
+
+ if(NOT WITH_INSTALL_PORTABLE)
+ add_definitions(-DPREFIX="${CMAKE_INSTALL_PREFIX}")
+ endif()
+
+elseif(WIN32)
+ list(APPEND SRC
+ intern/GHOST_SystemPathsWin32.cpp
+ intern/GHOST_SystemPathsWin32.h
+ )
+
+ list(APPEND INC
+ ../utfconv
+ )
endif()
-add_definitions(-DGLEW_STATIC)
+add_definitions(${GL_DEFINITIONS})
blender_add_lib(bf_intern_ghost "${SRC}" "${INC}" "${INC_SYS}")
diff --git a/intern/ghost/GHOST_C-api.h b/intern/ghost/GHOST_C-api.h
index c877a3b8fad..ff0dc575005 100644
--- a/intern/ghost/GHOST_C-api.h
+++ b/intern/ghost/GHOST_C-api.h
@@ -40,7 +40,7 @@ extern "C" {
#endif
/**
- * Creates a &quot;handle&quot; for a C++ GHOST object.
+ * Creates a "handle" for a C++ GHOST object.
* A handle is just an opaque pointer to an empty struct.
* In the API the pointer is casted to the actual C++ class.
* \param name Name of the handle to create.
@@ -174,20 +174,19 @@ extern void GHOST_GetAllDisplayDimensions(GHOST_SystemHandle systemhandle,
* \param height The height the window.
* \param state The state of the window when opened.
* \param type The type of drawing context installed in this window.
- * \param stereoVisual Stereo visual for quad buffered stereo.
- * \param numOfAASamples Number of samples used for AA (zero if no AA)
+ * \param glSettings: Misc OpenGL options.
* \return A handle to the new window ( == NULL if creation failed).
*/
-extern GHOST_WindowHandle GHOST_CreateWindow(GHOST_SystemHandle systemhandle,
- const char *title,
- GHOST_TInt32 left,
- GHOST_TInt32 top,
- GHOST_TUns32 width,
- GHOST_TUns32 height,
- GHOST_TWindowState state,
- GHOST_TDrawingContextType type,
- const int stereoVisual,
- const GHOST_TUns16 numOfAASamples);
+extern GHOST_WindowHandle GHOST_CreateWindow(
+ GHOST_SystemHandle systemhandle,
+ const char *title,
+ GHOST_TInt32 left,
+ GHOST_TInt32 top,
+ GHOST_TUns32 width,
+ GHOST_TUns32 height,
+ GHOST_TWindowState state,
+ GHOST_TDrawingContextType type,
+ GHOST_GLSettings glSettings);
/**
* Returns the window user data.
@@ -435,6 +434,16 @@ extern GHOST_TSuccess GHOST_GetButtonState(GHOST_SystemHandle systemhandle,
GHOST_TButtonMask mask,
int *isDown);
+/***************************************************************************************
+ * Access to 3D mouse.
+ ***************************************************************************************/
+
+/**
+ * Sets 3D mouse deadzone
+ * \param deadzone Deadzone of the 3D mouse (both for rotation and pan) relative to full range
+ */
+extern void GHOST_setNDOFDeadZone(float deadzone);
+
/***************************************************************************************
* Drag'n'drop operations
@@ -661,7 +670,7 @@ extern GHOST_TSuccess GHOST_SetWindowOrder(GHOST_WindowHandle windowhandle,
/**
* Swaps front and back buffers of a window.
* \param windowhandle The handle to the window
- * \return An intean success indicator.
+ * \return A success indicator.
*/
extern GHOST_TSuccess GHOST_SwapWindowBuffers(GHOST_WindowHandle windowhandle);
@@ -674,14 +683,22 @@ extern GHOST_TSuccess GHOST_SetSwapInterval(GHOST_WindowHandle windowhandle, int
/**
* Gets the current swap interval for swapBuffers.
- * \return An integer.
+ * \param windowhandle The handle to the window
+ * \param intervalOut pointer to location to return swap interval (left untouched if there is an error)
+ * \return A boolean success indicator of if swap interval was successfully read.
+ */
+extern GHOST_TSuccess GHOST_GetSwapInterval(GHOST_WindowHandle windowhandle, int* intervalOut);
+
+/**
+ * Gets the current swap interval for swapBuffers.
+ * \return Number of AA Samples (0 if there is no multisample buffer)
*/
-extern int GHOST_GetSwapInterval(GHOST_WindowHandle windowhandle);
+extern GHOST_TUns16 GHOST_GetNumOfAASamples(GHOST_WindowHandle windowhandle);
/**
* Activates the drawing context of this window.
* \param windowhandle The handle to the window
- * \return An intean success indicator.
+ * \return A success indicator.
*/
extern GHOST_TSuccess GHOST_ActivateWindowDrawingContext(GHOST_WindowHandle windowhandle);
@@ -745,7 +762,7 @@ extern void GHOST_SetRectangle(GHOST_RectangleHandle rectanglehandle,
* Returns whether this rectangle is empty.
* Empty rectangles are rectangles that have width==0 and/or height==0.
* \param rectanglehandle The handle to the rectangle
- * \return intean value (true == empty rectangle)
+ * \return Success value (true == empty rectangle)
*/
extern GHOST_TSuccess GHOST_IsEmptyRectangle(GHOST_RectangleHandle rectanglehandle);
@@ -753,7 +770,7 @@ extern GHOST_TSuccess GHOST_IsEmptyRectangle(GHOST_RectangleHandle rectanglehand
* Returns whether this rectangle is valid.
* Valid rectangles are rectangles that have m_l <= m_r and m_t <= m_b. Thus, empty rectangles are valid.
* \param rectanglehandle The handle to the rectangle
- * \return intean value (true == valid rectangle)
+ * \return Success value (true == valid rectangle)
*/
extern GHOST_TSuccess GHOST_IsValidRectangle(GHOST_RectangleHandle rectanglehandle);
@@ -791,7 +808,7 @@ extern void GHOST_UnionPointRectangle(GHOST_RectangleHandle rectanglehandle,
* \param rectanglehandle The handle to the rectangle
* \param x x-coordinate of point to test.
* \param y y-coordinate of point to test.
- * \return intean value (true if point is inside).
+ * \return Success value (true if point is inside).
*/
extern GHOST_TSuccess GHOST_IsInsideRectangle(GHOST_RectangleHandle rectanglehandle,
GHOST_TInt32 x,
@@ -889,6 +906,30 @@ extern int GHOST_UseNativePixels(void);
*/
extern float GHOST_GetNativePixelSize(GHOST_WindowHandle windowhandle);
+/**
+ * Enable IME attached to the given window, i.e. allows user-input
+ * events to be dispatched to the IME.
+ * \param windowhandle Window handle of the caller
+ * \param x Requested x-coordinate of the rectangle
+ * \param y Requested y-coordinate of the rectangle
+ * \param w Requested width of the rectangle
+ * \param h Requested height of the rectangle
+ * \param complete Whether or not to complete the ongoing composition
+ * true: Start a new composition
+ * false: Move the IME windows to the given position without finishing it.
+ */
+extern void GHOST_BeginIME(GHOST_WindowHandle windowhandle,
+ GHOST_TInt32 x,
+ GHOST_TInt32 y,
+ GHOST_TInt32 w,
+ GHOST_TInt32 h,
+ int complete);
+/**
+ * Disable the IME attached to the given window, i.e. prohibits any user-input
+ * events from being dispatched to the IME.
+ * \param windowhandle The window handle of the caller
+ */
+extern void GHOST_EndIME(GHOST_WindowHandle windowhandle);
#ifdef __cplusplus
}
diff --git a/intern/ghost/GHOST_ISystem.h b/intern/ghost/GHOST_ISystem.h
index 19f36319949..6825e8a0384 100644
--- a/intern/ghost/GHOST_ISystem.h
+++ b/intern/ghost/GHOST_ISystem.h
@@ -241,8 +241,8 @@ public:
* \param height The height the window.
* \param state The state of the window when opened.
* \param type The type of drawing context installed in this window.
- * \param stereoVisual Create a stereo visual for quad buffered stereo.
- * \param numOfAASamples Number of samples used for AA (zero if no AA)
+ * \param glSettings: Misc OpenGL settings.
+ * \param exclusive: Use to show the window ontop and ignore others (used fullscreen).
* \param parentWindow Parent (embedder) window
* \return The new window (or 0 if creation failed).
*/
@@ -250,9 +250,8 @@ public:
const STR_String& title,
GHOST_TInt32 left, GHOST_TInt32 top, GHOST_TUns32 width, GHOST_TUns32 height,
GHOST_TWindowState state, GHOST_TDrawingContextType type,
- const bool stereoVisual = false,
+ GHOST_GLSettings glSettings,
const bool exclusive = false,
- const GHOST_TUns16 numOfAASamples = 0,
const GHOST_TEmbedderWindowID parentWindow = 0) = 0;
/**
@@ -380,6 +379,12 @@ public:
virtual GHOST_TSuccess getButtonState(GHOST_TButtonMask mask, bool& isDown) const = 0;
/**
+ * Sets 3D mouse deadzone
+ * \param deadzone: Deadzone of the 3D mouse (both for rotation and pan) relative to full range
+ */
+ virtual void setNDOFDeadZone(float deadzone) = 0;
+
+ /**
* Toggles console
* \param action
* - 0: Hides
@@ -397,7 +402,7 @@ public:
/**
* Returns the selection buffer
- * \return Returns "unsinged char" from X11 XA_CUT_BUFFER0 buffer
+ * \return "unsigned char" from X11 XA_CUT_BUFFER0 buffer
*
*/
virtual GHOST_TUns8 *getClipboard(bool selection) const = 0;
diff --git a/intern/ghost/GHOST_ITimerTask.h b/intern/ghost/GHOST_ITimerTask.h
index fcd42db59da..9bea697cbc8 100644
--- a/intern/ghost/GHOST_ITimerTask.h
+++ b/intern/ghost/GHOST_ITimerTask.h
@@ -80,7 +80,7 @@ public:
/**
* Changes the time user data.
- * \param data The timer user data.
+ * \param userData: The timer user data.
*/
virtual void setUserData(const GHOST_TUserDataPtr userData) = 0;
diff --git a/intern/ghost/GHOST_IWindow.h b/intern/ghost/GHOST_IWindow.h
index c6befff6871..688ebecf557 100644
--- a/intern/ghost/GHOST_IWindow.h
+++ b/intern/ghost/GHOST_IWindow.h
@@ -212,9 +212,16 @@ public:
/**
* Gets the current swap interval for swapBuffers.
- * \return An integer.
+ * \param intervalOut pointer to location to return swap interval (left untouched if there is an error)
+ * \return A boolean success indicator of if swap interval was successfully read.
*/
- virtual int getSwapInterval() = 0;
+ virtual GHOST_TSuccess getSwapInterval(int& intervalOut) = 0;
+
+ /**
+ * Gets the current swap interval for swapBuffers.
+ * \return Number of AA Samples (0 if there is no multisample buffer)
+ */
+ virtual GHOST_TUns16 getNumOfAASamples() = 0;
/**
* Activates the drawing context of this window.
@@ -236,7 +243,7 @@ public:
/**
* Changes the window user data.
- * \param data The window user data.
+ * \param userData The window user data.
*/
virtual void setUserData(const GHOST_TUserDataPtr userData) = 0;
@@ -273,8 +280,8 @@ public:
/**
* Set the shape of the cursor.
- * \param cursor The new cursor shape type id.
- * \return Indication of success.
+ * \param cursorShape: The new cursor shape type id.
+ * \return Indication of success.
*/
virtual GHOST_TSuccess setCursorShape(GHOST_TStandardCursor cursorShape) = 0;
@@ -315,7 +322,9 @@ public:
* \param grab The new grab state of the cursor.
* \return Indication of success.
*/
- virtual GHOST_TSuccess setCursorGrab(GHOST_TGrabCursorMode mode, GHOST_Rect *bounds, GHOST_TInt32 mouse_ungrab_xy[2]) { return GHOST_kSuccess; }
+ virtual GHOST_TSuccess setCursorGrab(GHOST_TGrabCursorMode /*mode*/,
+ GHOST_Rect * /*bounds*/,
+ GHOST_TInt32 /*mouse_ungrab_xy*/[2]) { return GHOST_kSuccess; }
/** */
virtual GHOST_TSuccess beginFullScreen() const = 0;
@@ -323,6 +332,29 @@ public:
virtual float getNativePixelSize(void) = 0;
+#ifdef WITH_INPUT_IME
+ /**
+ * Enable IME attached to the given window, i.e. allows user-input
+ * events to be dispatched to the IME.
+ * \param x Requested x-coordinate of the rectangle
+ * \param y Requested y-coordinate of the rectangle
+ * \param w Requested width of the rectangle
+ * \param h Requested height of the rectangle
+ * \param complete Whether or not to complete the ongoing composition
+ * true: Start a new composition
+ * false: Move the IME windows to the given position without finishing it.
+ */
+ virtual void beginIME(
+ GHOST_TInt32 x, GHOST_TInt32 y,
+ GHOST_TInt32 w, GHOST_TInt32 h,
+ int completed) = 0;
+
+ /**
+ * Disable the IME attached to the given window, i.e. prohibits any user-input
+ * events from being dispatched to the IME.
+ */
+ virtual void endIME() = 0;
+#endif /* WITH_INPUT_IME */
#ifdef WITH_CXX_GUARDEDALLOC
MEM_CXX_CLASS_ALLOC_FUNCS("GHOST:GHOST_IWindow")
diff --git a/intern/ghost/GHOST_Types.h b/intern/ghost/GHOST_Types.h
index 7333ba025a5..7a73af3f249 100644
--- a/intern/ghost/GHOST_Types.h
+++ b/intern/ghost/GHOST_Types.h
@@ -50,6 +50,18 @@ typedef unsigned short GHOST_TUns16;
typedef int GHOST_TInt32;
typedef unsigned int GHOST_TUns32;
+typedef struct {
+ GHOST_TUns16 numOfAASamples;
+ int flags;
+} GHOST_GLSettings;
+
+typedef enum {
+ GHOST_glStereoVisual = (1 << 0),
+ GHOST_glWarnSupport = (1 << 1),
+ GHOST_glDebugContext = (1 << 2),
+} GHOST_GLFlags;
+
+
#ifdef _MSC_VER
typedef __int64 GHOST_TInt64;
typedef unsigned __int64 GHOST_TUns64;
@@ -115,12 +127,8 @@ typedef enum {
GHOST_kWindowStateMinimized,
GHOST_kWindowStateFullScreen,
GHOST_kWindowStateEmbedded,
- GHOST_kWindowState8Normal = 8,
- GHOST_kWindowState8Maximized,
- GHOST_kWindowState8Minimized,
- GHOST_kWindowState8FullScreen,
- GHOST_kWindowStateModified,
- GHOST_kWindowStateUnModified
+ // GHOST_kWindowStateModified,
+ // GHOST_kWindowStateUnModified,
} GHOST_TWindowState;
@@ -190,6 +198,10 @@ typedef enum {
GHOST_kEventTimer,
+ GHOST_kEventImeCompositionStart,
+ GHOST_kEventImeComposition,
+ GHOST_kEventImeCompositionEnd,
+
GHOST_kNumEventTypes
} GHOST_TEventType;
@@ -436,6 +448,22 @@ typedef struct {
GHOST_TEventDataPtr data;
} GHOST_TEventDragnDropData;
+/** similar to wmImeData */
+typedef struct {
+ /** size_t */
+ GHOST_TUserDataPtr result_len, composite_len;
+ /** char * utf8 encoding */
+ GHOST_TUserDataPtr result, composite;
+ /** Cursor position in the IME composition. */
+ int cursor_position;
+ /** Represents the position of the beginning of the selection */
+ int target_start;
+ /** Represents the position of the end of the selection */
+ int target_end;
+ /** custom temporal data */
+ GHOST_TUserDataPtr tmp;
+} GHOST_TEventImeData;
+
typedef struct {
int count;
GHOST_TUns8 **strings;
diff --git a/intern/ghost/SConscript b/intern/ghost/SConscript
index 80756472edb..78566210047 100644
--- a/intern/ghost/SConscript
+++ b/intern/ghost/SConscript
@@ -36,22 +36,34 @@ sources = env.Glob('intern/*.cpp')
sources2 = env.Glob('intern/GHOST_NDOFManager3Dconnexion.c')
if window_system == 'darwin':
sources += env.Glob('intern/*.mm')
+ #remove, will be readded below if needed.
+ sources.remove('intern' + os.sep + 'GHOST_ContextCGL.mm')
+if not env['WITH_BF_GL_EGL']:
+ sources.remove('intern' + os.sep + 'GHOST_ContextEGL.cpp')
-pf = ['GHOST_DisplayManager', 'GHOST_System', 'GHOST_SystemPaths', 'GHOST_Window', 'GHOST_DropTarget', 'GHOST_NDOFManager']
-defs=['_USE_MATH_DEFINES', 'GLEW_STATIC']
+# seems cleaner to remove these now then add back the one that is needed
+sources.remove('intern' + os.sep + 'GHOST_ContextGLX.cpp')
+sources.remove('intern' + os.sep + 'GHOST_ContextWGL.cpp')
+
+pf = ['GHOST_DisplayManager', 'GHOST_System', 'GHOST_SystemPaths', 'GHOST_Window', 'GHOST_DropTarget', 'GHOST_NDOFManager', 'GHOST_Context']
+
+defs = []
+defs += env['BF_GL_DEFINITIONS']
+
+if env['WITH_BF_GL_EGL']:
+ defs.append('WITH_EGL')
incs = [
'.',
- '#extern/glew/include',
+ env['BF_GLEW_INC'],
+ '../glew-mx',
'#source/blender/imbuf',
'#source/blender/makesdna',
'../string',
]
incs = ' '.join(incs)
-incs += ' ' + env['BF_OPENGL_INC']
-
if env['WITH_GHOST_SDL']:
for f in pf:
try:
@@ -65,9 +77,16 @@ elif window_system in ('linux', 'openbsd3', 'sunos5', 'freebsd7', 'freebsd8', 'f
for f in pf:
try:
sources.remove('intern' + os.sep + f + 'Win32.cpp')
+ except ValueError:
+ pass
+
+ try:
sources.remove('intern' + os.sep + f + 'SDL.cpp')
except ValueError:
pass
+
+ defs += ['WITH_X11']
+
## removing because scons does not support system installation
## if this is used for blender.org builds it means our distrobution
## will find any locally installed blender and double up its script path.
@@ -88,23 +107,45 @@ elif window_system in ('linux', 'openbsd3', 'sunos5', 'freebsd7', 'freebsd8', 'f
else:
sources.remove('intern' + os.sep + 'GHOST_DropTargetX11.cpp')
+ if not env['WITH_BF_GL_EGL']:
+ sources.append('intern' + os.sep + 'GHOST_ContextGLX.cpp')
+
elif window_system in ('win32-vc', 'win32-mingw', 'cygwin', 'linuxcross', 'win64-vc', 'win64-mingw'):
for f in pf:
try:
sources.remove('intern' + os.sep + f + 'X11.cpp')
+ except ValueError:
+ pass
+
+ try:
sources.remove('intern' + os.sep + f + 'SDL.cpp')
except ValueError:
pass
+
+ if not env['WITH_BF_GL_EGL']:
+ sources.append('intern' + os.sep + 'GHOST_ContextWGL.cpp')
+
elif window_system == 'darwin':
- if env['WITH_BF_QUICKTIME']:
- defs.append('WITH_QUICKTIME')
- for f in pf:
- try:
- sources.remove('intern' + os.sep + f + 'Win32.cpp')
- sources.remove('intern' + os.sep + f + 'X11.cpp')
- sources.remove('intern' + os.sep + f + 'SDL.cpp')
- except ValueError:
- pass
+ if env['WITH_BF_QUICKTIME']:
+ defs.append('WITH_QUICKTIME')
+ for f in pf:
+ try:
+ sources.remove('intern' + os.sep + f + 'Win32.cpp')
+ except ValueError:
+ pass
+
+ try:
+ sources.remove('intern' + os.sep + f + 'X11.cpp')
+ except ValueError:
+ pass
+ try:
+ sources.remove('intern' + os.sep + f + 'SDL.cpp')
+ except ValueError:
+ pass
+
+ if not env['WITH_BF_GL_EGL']:
+ sources.append('intern' + os.sep + 'GHOST_ContextCGL.mm')
+
else:
print "Unknown window system specified."
Exit()
@@ -114,6 +155,14 @@ if env['BF_GHOST_DEBUG']:
else:
sources.remove('intern' + os.sep + 'GHOST_EventPrinter.cpp')
+if env['WITH_BF_IME'] and window_system in ('win32-vc', 'win32-mingw', 'win64-vc', 'win64-mingw'):
+ defs.append('WITH_INPUT_IME')
+elif env['WITH_BF_IME']:
+ print "IME input is only supported on Windows! Please disable WITH_BF_IME!"
+ Exit()
+else:
+ sources.remove('intern' + os.sep + 'GHOST_ImeWin32.cpp')
+
if env['WITH_BF_3DMOUSE']:
defs.append('WITH_INPUT_NDOF')
diff --git a/intern/ghost/intern/GHOST_Buttons.h b/intern/ghost/intern/GHOST_Buttons.h
index 6b0d74e7eb9..0aa93a2fad0 100644
--- a/intern/ghost/intern/GHOST_Buttons.h
+++ b/intern/ghost/intern/GHOST_Buttons.h
@@ -48,26 +48,26 @@ struct GHOST_Buttons {
*/
GHOST_Buttons();
- virtual ~GHOST_Buttons();
+ ~GHOST_Buttons();
/**
* Returns the state of a single button.
* \param mask Key button to return.
* \return The state of the button (pressed == true).
*/
- virtual bool get(GHOST_TButtonMask mask) const;
+ bool get(GHOST_TButtonMask mask) const;
/**
* Updates the state of a single button.
* \param mask Button state to update.
* \param down The new state of the button.
*/
- virtual void set(GHOST_TButtonMask mask, bool down);
+ void set(GHOST_TButtonMask mask, bool down);
/**
* Sets the state of all buttons to up.
*/
- virtual void clear();
+ void clear();
GHOST_TUns8 m_ButtonLeft : 1;
GHOST_TUns8 m_ButtonMiddle : 1;
diff --git a/intern/ghost/intern/GHOST_C-api.cpp b/intern/ghost/intern/GHOST_C-api.cpp
index eaa59f096aa..af992bf5a3c 100644
--- a/intern/ghost/intern/GHOST_C-api.cpp
+++ b/intern/ghost/intern/GHOST_C-api.cpp
@@ -140,20 +140,12 @@ GHOST_WindowHandle GHOST_CreateWindow(GHOST_SystemHandle systemhandle,
GHOST_TUns32 height,
GHOST_TWindowState state,
GHOST_TDrawingContextType type,
- const int stereoVisual,
- const GHOST_TUns16 numOfAASamples)
+ GHOST_GLSettings glSettings)
{
GHOST_ISystem *system = (GHOST_ISystem *) systemhandle;
- bool bstereoVisual;
-
- if (stereoVisual)
- bstereoVisual = true;
- else
- bstereoVisual = false;
return (GHOST_WindowHandle) system->createWindow(title, left, top, width, height,
- state, type, bstereoVisual, false,
- numOfAASamples);
+ state, type, glSettings, false);
}
GHOST_TUserDataPtr GHOST_GetWindowUserData(GHOST_WindowHandle windowhandle)
@@ -421,6 +413,13 @@ GHOST_TSuccess GHOST_GetButtonState(GHOST_SystemHandle systemhandle,
}
+void GHOST_setNDOFDeadZone(float deadzone)
+{
+ GHOST_ISystem *system = GHOST_ISystem::getSystem();
+ system->setNDOFDeadZone(deadzone);
+}
+
+
void GHOST_setAcceptDragOperation(GHOST_WindowHandle windowhandle, GHOST_TInt8 canAccept)
{
GHOST_IWindow *window = (GHOST_IWindow *) windowhandle;
@@ -698,14 +697,21 @@ GHOST_TSuccess GHOST_SetSwapInterval(GHOST_WindowHandle windowhandle, int interv
return window->setSwapInterval(interval);
}
-int GHOST_GetSwapInterval(GHOST_WindowHandle windowhandle)
+GHOST_TSuccess GHOST_GetSwapInterval(GHOST_WindowHandle windowhandle, int* intervalOut)
{
GHOST_IWindow *window = (GHOST_IWindow *) windowhandle;
- return window->getSwapInterval();
+ return window->getSwapInterval(*intervalOut);
}
+GHOST_TUns16 GHOST_GetNumOfAASamples(GHOST_WindowHandle windowhandle)
+{
+ GHOST_IWindow *window = (GHOST_IWindow *) windowhandle;
+
+ return window->getNumOfAASamples();
+}
+
GHOST_TSuccess GHOST_ActivateWindowDrawingContext(GHOST_WindowHandle windowhandle)
{
GHOST_IWindow *window = (GHOST_IWindow *) windowhandle;
@@ -914,3 +920,21 @@ float GHOST_GetNativePixelSize(GHOST_WindowHandle windowhandle)
return 1.0f;
}
+#ifdef WITH_INPUT_IME
+
+void GHOST_BeginIME(GHOST_WindowHandle windowhandle,
+ GHOST_TInt32 x, GHOST_TInt32 y,
+ GHOST_TInt32 w, GHOST_TInt32 h,
+ int complete)
+{
+ GHOST_IWindow *window = (GHOST_IWindow *) windowhandle;
+ window->beginIME(x, y, w, h, complete);
+}
+
+void GHOST_EndIME(GHOST_WindowHandle windowhandle)
+{
+ GHOST_IWindow *window = (GHOST_IWindow *) windowhandle;
+ window->endIME();
+}
+
+#endif /* WITH_INPUT_IME */
diff --git a/intern/ghost/intern/GHOST_CallbackEventConsumer.h b/intern/ghost/intern/GHOST_CallbackEventConsumer.h
index 770ebdc8b78..3505d651fa3 100644
--- a/intern/ghost/intern/GHOST_CallbackEventConsumer.h
+++ b/intern/ghost/intern/GHOST_CallbackEventConsumer.h
@@ -57,7 +57,7 @@ public:
/**
* Destructor.
*/
- virtual ~GHOST_CallbackEventConsumer(void)
+ ~GHOST_CallbackEventConsumer(void)
{
}
@@ -66,7 +66,7 @@ public:
* \param event The event that can be handled or ignored.
* \return Indication as to whether the event was handled.
*/
- virtual bool processEvent(GHOST_IEvent *event);
+ bool processEvent(GHOST_IEvent *event);
protected:
/** The call-back routine invoked. */
diff --git a/intern/ghost/intern/GHOST_Context.cpp b/intern/ghost/intern/GHOST_Context.cpp
new file mode 100644
index 00000000000..f69f2181ef7
--- /dev/null
+++ b/intern/ghost/intern/GHOST_Context.cpp
@@ -0,0 +1,159 @@
+/*
+ * ***** 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): Jason Wilkins
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file ghost/intern/GHOST_Context.cpp
+ * \ingroup GHOST
+ *
+ * Definition of GHOST_Context class.
+ */
+
+#include "GHOST_Context.h"
+
+#ifdef _WIN32
+# include <GL/wglew.h> // only for symbolic constants, do not use API functions
+# include <tchar.h>
+#
+# ifndef ERROR_PROFILE_DOES_NOT_MATCH_DEVICE
+# define ERROR_PROFILE_DOES_NOT_MATCH_DEVICE 0x7E7 // Mingw64 headers may have had this
+# endif
+#endif
+
+#include <cstdio>
+#include <cstring>
+
+
+#ifdef _WIN32
+
+bool win32_chk(bool result, const char *file, int line, const char *text)
+{
+ if (!result) {
+ LPTSTR formattedMsg = NULL;
+
+ DWORD error = GetLastError();
+
+ const char *msg;
+
+ DWORD count = 0;
+
+ switch (error) {
+ case ERROR_INVALID_VERSION_ARB:
+ msg = "The specified OpenGL version and feature set are either invalid or not supported.\n";
+ break;
+
+ case ERROR_INVALID_PROFILE_ARB:
+ msg = "The specified OpenGL profile and feature set are either invalid or not supported.\n";
+ break;
+
+ case ERROR_INVALID_PIXEL_TYPE_ARB:
+ msg = "The specified pixel type is invalid.\n";
+ break;
+
+ case ERROR_INCOMPATIBLE_DEVICE_CONTEXTS_ARB:
+ msg = ("The device contexts specified are not compatible. "
+ "This can occur if the device contexts are managed by "
+ "different drivers or possibly on different graphics adapters.\n");
+ break;
+
+#ifdef WITH_GLEW_ES
+ case ERROR_INCOMPATIBLE_AFFINITY_MASKS_NV:
+ msg = "The device context(s) and rendering context have non-matching affinity masks.\n";
+ break;
+
+ case ERROR_MISSING_AFFINITY_MASK_NV:
+ msg = "The rendering context does not have an affinity mask set.\n";
+ break;
+#endif
+
+ case ERROR_PROFILE_DOES_NOT_MATCH_DEVICE:
+ msg = ("The specified profile is intended for a device of a "
+ "different type than the specified device.\n");
+ break;
+
+ default:
+ {
+ count =
+ FormatMessage(
+ (FORMAT_MESSAGE_ALLOCATE_BUFFER |
+ FORMAT_MESSAGE_FROM_SYSTEM |
+ FORMAT_MESSAGE_IGNORE_INSERTS),
+ NULL,
+ error,
+ MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+ (LPTSTR)(&formattedMsg),
+ 0,
+ NULL);
+
+ msg = count > 0 ? formattedMsg : "<no system message>\n";
+ break;
+ }
+ }
+
+#ifndef NDEBUG
+ _ftprintf(
+ stderr,
+ "%s(%d):[%s] -> Win32 Error# (%lu): %s",
+ file,
+ line,
+ text,
+ (unsigned long)error,
+ msg);
+#else
+ _ftprintf(
+ stderr,
+ "Win32 Error# (%lu): %s",
+ (unsigned long)error,
+ msg);
+#endif
+
+ SetLastError(NO_ERROR);
+
+ if (count != 0)
+ LocalFree(formattedMsg);
+ }
+
+ return result;
+}
+
+#endif // _WIN32
+
+
+void GHOST_Context::initContextGLEW()
+{
+ mxDestroyContext(m_mxContext); // no-op if m_mxContext is NULL
+
+ mxMakeCurrentContext(mxCreateContext());
+
+ m_mxContext = mxGetCurrentContext();
+}
+
+
+void GHOST_Context::initClearGL()
+{
+ glClearColor(0.447, 0.447, 0.447, 0.000);
+ glClear(GL_COLOR_BUFFER_BIT);
+ glClearColor(0.000, 0.000, 0.000, 0.000);
+}
diff --git a/intern/ghost/intern/GHOST_Context.h b/intern/ghost/intern/GHOST_Context.h
new file mode 100644
index 00000000000..18d36c40e9c
--- /dev/null
+++ b/intern/ghost/intern/GHOST_Context.h
@@ -0,0 +1,161 @@
+/*
+ * ***** 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): Jason Wilkins
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file ghost/intern/GHOST_Context.h
+ * \ingroup GHOST
+ * Declaration of GHOST_Context class.
+ */
+
+#ifndef __GHOST_CONTEXT_H__
+#define __GHOST_CONTEXT_H__
+
+#include "GHOST_Types.h"
+
+#include "glew-mx.h"
+
+#include <cstdlib> // for NULL
+
+
+class GHOST_Context
+{
+public:
+ /**
+ * Constructor.
+ * \param stereoVisual Stereo visual for quad buffered stereo.
+ * \param numOfAASamples Number of samples used for AA (zero if no AA)
+ */
+ GHOST_Context(bool stereoVisual, GHOST_TUns16 numOfAASamples)
+ : m_stereoVisual(stereoVisual),
+ m_numOfAASamples(numOfAASamples),
+ m_mxContext(NULL)
+ {}
+
+ /**
+ * Destructor.
+ */
+ virtual ~GHOST_Context() {
+ mxDestroyContext(m_mxContext);
+ }
+
+ /**
+ * Swaps front and back buffers of a window.
+ * \return A boolean success indicator.
+ */
+ virtual GHOST_TSuccess swapBuffers() = 0;
+
+ /**
+ * Activates the drawing context of this window.
+ * \return A boolean success indicator.
+ */
+ virtual GHOST_TSuccess activateDrawingContext() = 0;
+
+ /**
+ * Call immediately after new to initialize. If this fails then immediately delete the object.
+ * \return Indication as to whether initialization has succeeded.
+ */
+ virtual GHOST_TSuccess initializeDrawingContext() = 0;
+
+ /**
+ * Updates the drawing context of this window. Needed
+ * whenever the window is changed.
+ * \return Indication of success.
+ */
+ virtual GHOST_TSuccess updateDrawingContext() {
+ return GHOST_kFailure;
+ }
+
+ /**
+ * Checks if it is OK for a remove the native display
+ * \return Indication as to whether removal has succeeded.
+ */
+ virtual GHOST_TSuccess releaseNativeHandles() = 0;
+
+ /**
+ * Sets the swap interval for swapBuffers.
+ * \param interval The swap interval to use.
+ * \return A boolean success indicator.
+ */
+ virtual GHOST_TSuccess setSwapInterval(int /*interval*/) {
+ return GHOST_kFailure;
+ }
+
+ /**
+ * Gets the current swap interval for swapBuffers.
+ * \param intervalOut Variable to store the swap interval if it can be read.
+ * \return Whether the swap interval can be read.
+ */
+ virtual GHOST_TSuccess getSwapInterval(int&) {
+ return GHOST_kFailure;
+ }
+
+ /** Stereo visual created. Only necessary for 'real' stereo support,
+ * ie quad buffered stereo. This is not always possible, depends on
+ * the graphics h/w
+ */
+ inline bool isStereoVisual() const {
+ return m_stereoVisual;
+ }
+
+ /** Number of samples used in anti-aliasing, set to 0 if no AA **/
+ inline GHOST_TUns16 getNumOfAASamples() const {
+ return m_numOfAASamples;
+ }
+
+protected:
+ void initContextGLEW();
+
+ inline void activateGLEW() const {
+ mxMakeCurrentContext(m_mxContext);
+ }
+
+ bool m_stereoVisual;
+
+ GHOST_TUns16 m_numOfAASamples;
+
+ static void initClearGL();
+
+private:
+ MXContext *m_mxContext;
+
+#ifdef WITH_CXX_GUARDEDALLOC
+ MEM_CXX_CLASS_ALLOC_FUNCS("GHOST:GHOST_Context")
+#endif
+};
+
+
+#ifdef _WIN32
+bool win32_chk(bool result, const char *file = NULL, int line = 0, const char *text = NULL);
+
+# ifndef NDEBUG
+# define WIN32_CHK(x) win32_chk((x), __FILE__, __LINE__, #x)
+# else
+# define WIN32_CHK(x) win32_chk(x)
+# endif
+#endif /* _WIN32 */
+
+
+#endif // __GHOST_CONTEXT_H__
diff --git a/intern/ghost/intern/GHOST_ContextCGL.h b/intern/ghost/intern/GHOST_ContextCGL.h
new file mode 100644
index 00000000000..92fdbfc53de
--- /dev/null
+++ b/intern/ghost/intern/GHOST_ContextCGL.h
@@ -0,0 +1,153 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2014 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Jason Wilkins
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file ghost/intern/GHOST_ContextCGL.h
+ * \ingroup GHOST
+ */
+
+#ifndef __GHOST_CONTEXTCGL_H__
+#define __GHOST_CONTEXTCGL_H__
+
+#include "GHOST_Context.h"
+
+//#define cglewGetContext() cglewContext
+//#include <GL/cglew.h>
+//extern "C" CGLEWContext *cglewContext;
+
+#ifndef GHOST_OPENGL_CGL_CONTEXT_FLAGS
+#define GHOST_OPENGL_CGL_CONTEXT_FLAGS 0
+#endif
+
+#ifndef GHOST_OPENGL_CGL_RESET_NOTIFICATION_STRATEGY
+#define GHOST_OPENGL_CGL_RESET_NOTIFICATION_STRATEGY 0
+#endif
+
+
+@class NSWindow;
+@class NSOpenGLView;
+@class NSOpenGLContext;
+
+
+class GHOST_ContextCGL : public GHOST_Context
+{
+public:
+ /**
+ * Constructor.
+ */
+ GHOST_ContextCGL(
+ bool stereoVisual,
+ GHOST_TUns16 numOfAASamples,
+ NSWindow *window,
+ NSOpenGLView *openGLView,
+ int contextProfileMask,
+ int contextMajorVersion,
+ int contextMinorVersion,
+ int contextFlags,
+ int contextResetNotificationStrategy);
+
+ /**
+ * Destructor.
+ */
+ ~GHOST_ContextCGL();
+
+ /**
+ * Swaps front and back buffers of a window.
+ * \return A boolean success indicator.
+ */
+ GHOST_TSuccess swapBuffers();
+
+ /**
+ * Activates the drawing context of this window.
+ * \return A boolean success indicator.
+ */
+ GHOST_TSuccess activateDrawingContext();
+
+ /**
+ * Call immediately after new to initialize. If this fails then immediately delete the object.
+ * \return Indication as to whether initialization has succeeded.
+ */
+ GHOST_TSuccess initializeDrawingContext();
+
+ /**
+ * Removes references to native handles from this context and then returns
+ * \return GHOST_kSuccess if it is OK for the parent to release the handles and
+ * GHOST_kFailure if releasing the handles will interfere with sharing
+ */
+ GHOST_TSuccess releaseNativeHandles();
+
+ /**
+ * Sets the swap interval for swapBuffers.
+ * \param interval The swap interval to use.
+ * \return A boolean success indicator.
+ */
+ GHOST_TSuccess setSwapInterval(int interval);
+
+ /**
+ * Gets the current swap interval for swapBuffers.
+ * \param intervalOut Variable to store the swap interval if it can be read.
+ * \return Whether the swap interval can be read.
+ */
+ GHOST_TSuccess getSwapInterval(int&);
+
+ /**
+ * Updates the drawing context of this window.
+ * Needed whenever the window is changed.
+ * \return Indication of success.
+ */
+ GHOST_TSuccess updateDrawingContext();
+
+//protected:
+// inline void activateCGLEW() const {
+// cglewContext = m_cglewContext;
+// }
+
+private:
+ //void initContextCGLEW()
+
+ /** The window containing the OpenGL view */
+ NSWindow *m_window;
+
+ /** The openGL view */
+ NSOpenGLView *m_openGLView;
+
+ const int m_contextProfileMask;
+ const int m_contextMajorVersion;
+ const int m_contextMinorVersion;
+ const int m_contextFlags;
+ const int m_contextResetNotificationStrategy;
+
+ /** The OpenGL drawing context */
+ NSOpenGLContext *m_openGLContext;
+
+ //static CGLEWContext *s_cglewContext;
+
+ /** The first created OpenGL context (for sharing display lists) */
+ static NSOpenGLContext *s_sharedOpenGLContext;
+ static int s_sharedCount;
+};
+
+#endif // __GHOST_CONTEXTCGL_H__
diff --git a/intern/ghost/intern/GHOST_ContextCGL.mm b/intern/ghost/intern/GHOST_ContextCGL.mm
new file mode 100644
index 00000000000..51895e5fa1a
--- /dev/null
+++ b/intern/ghost/intern/GHOST_ContextCGL.mm
@@ -0,0 +1,354 @@
+/*
+ * ***** 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): Jason Wilkins
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file ghost/intern/GHOST_ContextCGL.mm
+ * \ingroup GHOST
+ *
+ * Definition of GHOST_ContextCGL class.
+ */
+
+#include "GHOST_ContextCGL.h"
+
+#include <Cocoa/Cocoa.h>
+
+#ifdef GHOST_MULTITHREADED_OPENGL
+#include <OpenGL/OpenGL.h>
+#endif
+
+#include <vector>
+#include <cassert>
+
+
+NSOpenGLContext *GHOST_ContextCGL::s_sharedOpenGLContext = nil;
+int GHOST_ContextCGL::s_sharedCount = 0;
+
+
+GHOST_ContextCGL::GHOST_ContextCGL(
+ bool stereoVisual,
+ GHOST_TUns16 numOfAASamples,
+ NSWindow *window,
+ NSOpenGLView *openGLView,
+ int contextProfileMask,
+ int contextMajorVersion,
+ int contextMinorVersion,
+ int contextFlags,
+ int contextResetNotificationStrategy)
+ : GHOST_Context(stereoVisual, numOfAASamples),
+ m_window(window),
+ m_openGLView(openGLView),
+ m_contextProfileMask(contextProfileMask),
+ m_contextMajorVersion(contextMajorVersion),
+ m_contextMinorVersion(contextMinorVersion),
+ m_contextFlags(contextFlags),
+ m_contextResetNotificationStrategy(contextResetNotificationStrategy),
+ m_openGLContext(nil)
+{
+ assert(window != nil);
+ assert(openGLView != nil);
+}
+
+
+GHOST_ContextCGL::~GHOST_ContextCGL()
+{
+ if (m_openGLContext != nil) {
+ if (m_openGLContext == [NSOpenGLContext currentContext]) {
+ [NSOpenGLContext clearCurrentContext];
+ [m_openGLView clearGLContext];
+ }
+
+ if (m_openGLContext != s_sharedOpenGLContext || s_sharedCount == 1) {
+ assert(s_sharedCount > 0);
+
+ s_sharedCount--;
+
+ if (s_sharedCount == 0)
+ s_sharedOpenGLContext = nil;
+
+ [m_openGLContext release];
+ }
+ }
+}
+
+
+GHOST_TSuccess GHOST_ContextCGL::swapBuffers()
+{
+ if (m_openGLContext != nil) {
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+ [m_openGLContext flushBuffer];
+ [pool drain];
+ return GHOST_kSuccess;
+ }
+ else {
+ return GHOST_kFailure;
+ }
+}
+
+
+GHOST_TSuccess GHOST_ContextCGL::setSwapInterval(int interval)
+{
+ if (m_openGLContext != nil) {
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+ [m_openGLContext setValues:&interval forParameter:NSOpenGLCPSwapInterval];
+ [pool drain];
+ return GHOST_kSuccess;
+ }
+ else {
+ return GHOST_kFailure;
+ }
+}
+
+
+GHOST_TSuccess GHOST_ContextCGL::getSwapInterval(int &intervalOut)
+{
+ if (m_openGLContext != nil) {
+ GLint interval;
+
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+
+ [m_openGLContext setValues:&interval forParameter:NSOpenGLCPSwapInterval];
+
+ [pool drain];
+
+ intervalOut = static_cast<int>(interval);
+
+ return GHOST_kSuccess;
+ }
+ else {
+ return GHOST_kFailure;
+ }
+}
+
+
+GHOST_TSuccess GHOST_ContextCGL::activateDrawingContext()
+{
+ if (m_openGLContext != nil) {
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+ [m_openGLContext makeCurrentContext];
+
+ activateGLEW();
+
+ [pool drain];
+ return GHOST_kSuccess;
+ }
+ else {
+ return GHOST_kFailure;
+ }
+}
+
+
+GHOST_TSuccess GHOST_ContextCGL::updateDrawingContext()
+{
+ if (m_openGLContext != nil) {
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+ [m_openGLContext update];
+ [pool drain];
+ return GHOST_kSuccess;
+ }
+ else {
+ return GHOST_kFailure;
+ }
+}
+
+
+static void makeAttribList(
+ std::vector<NSOpenGLPixelFormatAttribute>& attribs,
+ bool stereoVisual,
+ int numOfAASamples,
+ bool needAlpha,
+ bool needStencil)
+{
+ // Pixel Format Attributes for the windowed NSOpenGLContext
+ attribs.push_back(NSOpenGLPFADoubleBuffer);
+
+ // Guarantees the back buffer contents to be valid after a call to NSOpenGLContext object's flushBuffer
+ // needed for 'Draw Overlap' drawing method
+ attribs.push_back(NSOpenGLPFABackingStore);
+
+ // Force software OpenGL, for debugging
+ /* XXX jwilkins: fixed this to work on Intel macs? useful feature for Windows and Linux too?
+ * Maybe a command line flag is better... */
+ if (getenv("BLENDER_SOFTWAREGL")) {
+ attribs.push_back(NSOpenGLPFARendererID);
+ attribs.push_back(kCGLRendererGenericFloatID);
+ }
+ else {
+ attribs.push_back(NSOpenGLPFAAccelerated);
+ }
+
+ /* Removed to allow 10.4 builds, and 2 GPUs rendering is not used anyway */
+ //attribs.push_back(NSOpenGLPFAAllowOfflineRenderers);
+
+ attribs.push_back(NSOpenGLPFADepthSize);
+ attribs.push_back((NSOpenGLPixelFormatAttribute) 32);
+
+ attribs.push_back(NSOpenGLPFAAccumSize);
+ attribs.push_back((NSOpenGLPixelFormatAttribute) 32);
+
+ if (stereoVisual)
+ attribs.push_back(NSOpenGLPFAStereo);
+
+ if (needAlpha) {
+ attribs.push_back(NSOpenGLPFAAlphaSize);
+ attribs.push_back((NSOpenGLPixelFormatAttribute) 8);
+ }
+
+ if (needStencil) {
+ attribs.push_back(NSOpenGLPFAStencilSize);
+ attribs.push_back((NSOpenGLPixelFormatAttribute) 8);
+ }
+
+ if (numOfAASamples > 0) {
+ // Multisample anti-aliasing
+ attribs.push_back(NSOpenGLPFAMultisample);
+
+ attribs.push_back(NSOpenGLPFASampleBuffers);
+ attribs.push_back((NSOpenGLPixelFormatAttribute) 1);
+
+ attribs.push_back(NSOpenGLPFASamples);
+ attribs.push_back((NSOpenGLPixelFormatAttribute) numOfAASamples);
+
+ attribs.push_back(NSOpenGLPFANoRecovery);
+ }
+
+ attribs.push_back((NSOpenGLPixelFormatAttribute) 0);
+}
+
+
+GHOST_TSuccess GHOST_ContextCGL::initializeDrawingContext()
+{
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+
+ std::vector<NSOpenGLPixelFormatAttribute> attribs;
+ attribs.reserve(40);
+
+ NSOpenGLContext *prev_openGLContext = [m_openGLView openGLContext];
+
+#ifdef GHOST_OPENGL_ALPHA
+ static const bool needAlpha = true;
+#else
+ static const bool needAlpha = false;
+#endif
+
+#ifdef GHOST_OPENGL_STENCIL
+ static const bool needStencil = true;
+#else
+ static const bool needStencil = false;
+#endif
+
+ makeAttribList(attribs, m_stereoVisual, m_numOfAASamples, needAlpha, needStencil);
+
+ NSOpenGLPixelFormat *pixelFormat;
+
+ pixelFormat = [[NSOpenGLPixelFormat alloc] initWithAttributes:&attribs[0]];
+
+ // Fall back to no multisampling if Antialiasing init failed
+ if (m_numOfAASamples > 0 && pixelFormat == nil) {
+ // XXX jwilkins: Does CGL only succeed when it makes an exact match on the number of samples?
+ // Does this need to explicitly try for a lesser match before giving up?
+ // (Now that I think about it, does WGL really require the code that it has for finding a lesser match?)
+
+ attribs.clear();
+ makeAttribList(attribs, m_stereoVisual, 0, needAlpha, needStencil);
+ pixelFormat = [[NSOpenGLPixelFormat alloc] initWithAttributes:&attribs[0]];
+ }
+
+ if (pixelFormat == nil)
+ goto error;
+
+ if (m_numOfAASamples > 0) { //Set m_numOfAASamples to the actual value
+ GLint actualSamples;
+ [pixelFormat getValues:&actualSamples forAttribute:NSOpenGLPFASamples forVirtualScreen:0];
+
+ if (m_numOfAASamples != (GHOST_TUns16)actualSamples) {
+ fprintf(stderr,
+ "Warning! Unable to find a multisample pixel format that supports exactly %d samples. "
+ "Substituting one that uses %d samples.\n",
+ m_numOfAASamples, actualSamples);
+
+ m_numOfAASamples = (GHOST_TUns16)actualSamples;
+ }
+ }
+
+ [m_openGLView setPixelFormat:pixelFormat];
+
+ m_openGLContext = [[NSOpenGLContext alloc] initWithFormat:pixelFormat shareContext:s_sharedOpenGLContext]; // +1 refCount to pixelFormat
+
+ if (m_openGLContext == nil)
+ goto error;
+
+ if (s_sharedCount == 0)
+ s_sharedOpenGLContext = m_openGLContext;
+
+ [pixelFormat release]; // -1 refCount to pixelFormat
+
+ s_sharedCount++;
+
+#ifdef GHOST_MULTITHREADED_OPENGL
+ //Switch openGL to multhreaded mode
+ CGLContextObj cglCtx = (CGLContextObj)[tmpOpenGLContext CGLContextObj];
+ if (CGLEnable(cglCtx, kCGLCEMPEngine) == kCGLNoError)
+ printf("\nSwitched openGL to multithreaded mode\n");
+#endif
+
+#ifdef GHOST_WAIT_FOR_VSYNC
+ {
+ GLint swapInt = 1;
+ /* wait for vsync, to avoid tearing artifacts */
+ [m_openGLContext setValues:&swapInt forParameter:NSOpenGLCPSwapInterval];
+ }
+#endif
+
+ [m_openGLView setOpenGLContext:m_openGLContext];
+ [m_openGLContext setView:m_openGLView];
+
+ initContextGLEW();
+
+ initClearGL();
+ [m_openGLContext flushBuffer];
+
+ [pool drain];
+
+ return GHOST_kSuccess;
+
+error:
+
+ [m_openGLView setOpenGLContext:prev_openGLContext];
+ [pixelFormat release];
+
+ [pool drain];
+
+ return GHOST_kFailure;
+}
+
+
+GHOST_TSuccess GHOST_ContextCGL::releaseNativeHandles()
+{
+ m_openGLContext = NULL;
+ m_openGLView = NULL;
+
+ return GHOST_kSuccess;
+}
diff --git a/intern/ghost/intern/GHOST_ContextEGL.cpp b/intern/ghost/intern/GHOST_ContextEGL.cpp
new file mode 100644
index 00000000000..520aa0fffb2
--- /dev/null
+++ b/intern/ghost/intern/GHOST_ContextEGL.cpp
@@ -0,0 +1,640 @@
+/*
+ * ***** 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): Jason Wilkins
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file ghost/intern/GHOST_ContextEGL.cpp
+ * \ingroup GHOST
+ *
+ * Definition of GHOST_ContextEGL class.
+ */
+
+#include "GHOST_ContextEGL.h"
+
+#include <set>
+#include <sstream>
+#include <vector>
+
+#include <cassert>
+#include <cstdio>
+#include <cstring>
+
+
+#ifdef WITH_GLEW_MX
+EGLEWContext *eglewContext = NULL;
+#endif
+
+
+#define CASE_CODE_RETURN_STR(code) case code: return #code;
+
+static const char *get_egl_error_enum_string(EGLenum error)
+{
+ switch (error) {
+ CASE_CODE_RETURN_STR(EGL_SUCCESS)
+ CASE_CODE_RETURN_STR(EGL_NOT_INITIALIZED)
+ CASE_CODE_RETURN_STR(EGL_BAD_ACCESS)
+ CASE_CODE_RETURN_STR(EGL_BAD_ALLOC)
+ CASE_CODE_RETURN_STR(EGL_BAD_ATTRIBUTE)
+ CASE_CODE_RETURN_STR(EGL_BAD_CONTEXT)
+ CASE_CODE_RETURN_STR(EGL_BAD_CONFIG)
+ CASE_CODE_RETURN_STR(EGL_BAD_CURRENT_SURFACE)
+ CASE_CODE_RETURN_STR(EGL_BAD_DISPLAY)
+ CASE_CODE_RETURN_STR(EGL_BAD_SURFACE)
+ CASE_CODE_RETURN_STR(EGL_BAD_MATCH)
+ CASE_CODE_RETURN_STR(EGL_BAD_PARAMETER)
+ CASE_CODE_RETURN_STR(EGL_BAD_NATIVE_PIXMAP)
+ CASE_CODE_RETURN_STR(EGL_BAD_NATIVE_WINDOW)
+ CASE_CODE_RETURN_STR(EGL_CONTEXT_LOST)
+ default:
+ return NULL;
+ }
+}
+
+static const char *get_egl_error_message_string(EGLenum error)
+{
+ switch (error) {
+ case EGL_SUCCESS:
+ return "The last function succeeded without error.";
+
+ case EGL_NOT_INITIALIZED:
+ return ("EGL is not initialized, or could not be initialized, "
+ "for the specified EGL display connection.");
+
+ case EGL_BAD_ACCESS:
+ return ("EGL cannot access a requested resource "
+ "(for example a context is bound in another thread).");
+
+ case EGL_BAD_ALLOC:
+ return "EGL failed to allocate resources for the requested operation.";
+
+ case EGL_BAD_ATTRIBUTE:
+ return "An unrecognized attribute or attribute value was passed in the attribute list.";
+
+ case EGL_BAD_CONTEXT:
+ return "An EGLContext argument does not name a valid EGL rendering context.";
+
+ case EGL_BAD_CONFIG:
+ return "An EGLConfig argument does not name a valid EGL frame buffer configuration.";
+
+ case EGL_BAD_CURRENT_SURFACE:
+ return ("The current surface of the calling thread is a window, "
+ "pixel buffer or pixmap that is no longer valid.");
+
+ case EGL_BAD_DISPLAY:
+ return "An EGLDisplay argument does not name a valid EGL display connection.";
+
+ case EGL_BAD_SURFACE:
+ return ("An EGLSurface argument does not name a valid surface "
+ "(window, pixel buffer or pixmap) configured for GL rendering.");
+
+ case EGL_BAD_MATCH:
+ return ("Arguments are inconsistent "
+ "(for example, a valid context requires buffers not supplied by a valid surface).");
+
+ case EGL_BAD_PARAMETER:
+ return "One or more argument values are invalid.";
+
+ case EGL_BAD_NATIVE_PIXMAP:
+ return "A NativePixmapType argument does not refer to a valid native pixmap.";
+
+ case EGL_BAD_NATIVE_WINDOW:
+ return "A NativeWindowType argument does not refer to a valid native window.";
+
+ case EGL_CONTEXT_LOST:
+ return ("A power management event has occurred. "
+ "The application must destroy all contexts and reinitialise OpenGL ES state "
+ "and objects to continue rendering.");
+
+ default:
+ return NULL;
+ }
+}
+
+
+static bool egl_chk(bool result, const char *file = NULL, int line = 0, const char *text = NULL)
+{
+ if (!result) {
+ EGLenum error = eglGetError();
+
+ const char *code = get_egl_error_enum_string(error);
+ const char *msg = get_egl_error_message_string(error);
+
+#ifndef NDEBUG
+ fprintf(stderr,
+ "%s(%d):[%s] -> EGL Error (0x%04X): %s: %s\n",
+ file, line, text, error,
+ code ? code : "<Unknown>",
+ msg ? msg : "<Unknown>");
+#else
+ fprintf(stderr,
+ "EGL Error (0x%04X): %s: %s\n",
+ error,
+ code ? code : "<Unknown>",
+ msg ? msg : "<Unknown>");
+#endif
+ }
+
+ return result;
+}
+
+#ifndef NDEBUG
+#define EGL_CHK(x) egl_chk((x), __FILE__, __LINE__, #x)
+#else
+#define EGL_CHK(x) egl_chk(x)
+#endif
+
+
+static inline bool bindAPI(EGLenum api)
+{
+#ifdef WITH_GLEW_MX
+ if (eglewContext != NULL)
+#endif
+ {
+ if (EGLEW_VERSION_1_2) {
+ return (EGL_CHK(eglBindAPI(api)) == EGL_TRUE);
+ }
+ }
+
+ return false;
+}
+
+
+#ifdef WITH_GL_ANGLE
+HMODULE GHOST_ContextEGL::s_d3dcompiler = NULL;
+#endif
+
+
+EGLContext GHOST_ContextEGL::s_gl_sharedContext = EGL_NO_CONTEXT;
+EGLint GHOST_ContextEGL::s_gl_sharedCount = 0;
+
+EGLContext GHOST_ContextEGL::s_gles_sharedContext = EGL_NO_CONTEXT;
+EGLint GHOST_ContextEGL::s_gles_sharedCount = 0;
+
+EGLContext GHOST_ContextEGL::s_vg_sharedContext = EGL_NO_CONTEXT;
+EGLint GHOST_ContextEGL::s_vg_sharedCount = 0;
+
+
+#pragma warning(disable : 4715)
+
+template <typename T>
+T &choose_api(EGLenum api, T &a, T &b, T &c)
+{
+ switch (api) {
+ case EGL_OPENGL_API:
+ return a;
+ case EGL_OPENGL_ES_API:
+ return b;
+ case EGL_OPENVG_API:
+ return c;
+ default:
+ abort();
+ }
+}
+
+
+GHOST_ContextEGL::GHOST_ContextEGL(
+ bool stereoVisual,
+ GHOST_TUns16 numOfAASamples,
+ EGLNativeWindowType nativeWindow,
+ EGLNativeDisplayType nativeDisplay,
+ EGLint contextProfileMask,
+ EGLint contextMajorVersion,
+ EGLint contextMinorVersion,
+ EGLint contextFlags,
+ EGLint contextResetNotificationStrategy,
+ EGLenum api)
+ : GHOST_Context(stereoVisual, numOfAASamples),
+ m_nativeDisplay(nativeDisplay),
+ m_nativeWindow (nativeWindow),
+ m_contextProfileMask(contextProfileMask),
+ m_contextMajorVersion(contextMajorVersion),
+ m_contextMinorVersion(contextMinorVersion),
+ m_contextFlags(contextFlags),
+ m_contextResetNotificationStrategy(contextResetNotificationStrategy),
+ m_api(api),
+ m_context(EGL_NO_CONTEXT),
+ m_surface(EGL_NO_SURFACE),
+ m_display(EGL_NO_DISPLAY),
+ m_swap_interval(1),
+#ifdef WITH_GLEW_MX
+ m_eglewContext(NULL),
+#endif
+ m_sharedContext(choose_api(api, s_gl_sharedContext, s_gles_sharedContext, s_vg_sharedContext)),
+ m_sharedCount (choose_api(api, s_gl_sharedCount, s_gles_sharedCount, s_vg_sharedCount))
+{
+ assert(m_nativeWindow != 0);
+ assert(m_nativeDisplay != NULL);
+}
+
+
+GHOST_ContextEGL::~GHOST_ContextEGL()
+{
+ if (m_display != EGL_NO_DISPLAY) {
+ activateEGLEW();
+
+ bindAPI(m_api);
+
+ if (m_context != EGL_NO_CONTEXT) {
+ if (m_context == ::eglGetCurrentContext())
+ EGL_CHK(::eglMakeCurrent(m_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT));
+
+ if (m_context != m_sharedContext || m_sharedCount == 1) {
+ assert(m_sharedCount > 0);
+
+ m_sharedCount--;
+
+ if (m_sharedCount == 0)
+ m_sharedContext = EGL_NO_CONTEXT;
+
+ EGL_CHK(::eglDestroyContext(m_display, m_context));
+ }
+ }
+
+ if (m_surface != EGL_NO_SURFACE)
+ EGL_CHK(::eglDestroySurface(m_display, m_surface));
+
+ EGL_CHK(::eglTerminate(m_display));
+
+#ifdef WITH_GLEW_MX
+ delete m_eglewContext;
+#endif
+ }
+}
+
+
+GHOST_TSuccess GHOST_ContextEGL::swapBuffers()
+{
+ return EGL_CHK(::eglSwapBuffers(m_display, m_surface)) ? GHOST_kSuccess : GHOST_kFailure;
+}
+
+
+GHOST_TSuccess GHOST_ContextEGL::setSwapInterval(int interval)
+{
+ if (EGLEW_VERSION_1_1) {
+ if (EGL_CHK(::eglSwapInterval(m_display, interval))) {
+ m_swap_interval = interval;
+
+ return GHOST_kSuccess;
+ }
+ else {
+ return GHOST_kFailure;
+ }
+ }
+ else {
+ return GHOST_kFailure;
+ }
+}
+
+
+GHOST_TSuccess GHOST_ContextEGL::getSwapInterval(int &intervalOut)
+{
+ // This is a bit of a kludge because there does not seem to
+ // be a way to query the swap interval with EGL.
+ intervalOut = m_swap_interval;
+
+ return GHOST_kSuccess;
+}
+
+
+GHOST_TSuccess GHOST_ContextEGL::activateDrawingContext()
+{
+ if (m_display) {
+ activateEGLEW();
+ activateGLEW();
+
+ bindAPI(m_api);
+
+ return EGL_CHK(::eglMakeCurrent(m_display, m_surface, m_surface, m_context)) ? GHOST_kSuccess : GHOST_kFailure;
+ }
+ else {
+ return GHOST_kFailure;
+ }
+}
+
+
+void GHOST_ContextEGL::initContextEGLEW()
+{
+#ifdef WITH_GLEW_MX
+ eglewContext = new EGLEWContext;
+ memset(eglewContext, 0, sizeof(EGLEWContext));
+
+ delete m_eglewContext;
+ m_eglewContext = eglewContext;
+#endif
+
+ if (GLEW_CHK(eglewInit(m_display)) != GLEW_OK)
+ fprintf(stderr, "Warning! EGLEW failed to initialize properly.\n");
+}
+
+
+static const std::string &api_string(EGLenum api)
+{
+ static const std::string a("OpenGL");
+ static const std::string b("OpenGL ES");
+ static const std::string c("OpenVG");
+
+ return choose_api(api, a, b, c);
+}
+
+GHOST_TSuccess GHOST_ContextEGL::initializeDrawingContext()
+{
+ // objects have to be declared here due to the use of goto
+ std::vector<EGLint> attrib_list;
+ EGLint num_config = 0;
+
+ if (m_stereoVisual)
+ fprintf(stderr, "Warning! Stereo OpenGL ES contexts are not supported.\n");
+
+ m_stereoVisual = false; // It doesn't matter what the Window wants.
+
+#ifdef WITH_GL_ANGLE
+ // d3dcompiler_XX.dll needs to be loaded before ANGLE will work
+ if (s_d3dcompiler == NULL) {
+ s_d3dcompiler = LoadLibrary(D3DCOMPILER);
+
+ WIN32_CHK(s_d3dcompiler != NULL);
+
+ if (s_d3dcompiler == NULL) {
+ fprintf(stderr, "LoadLibrary(\"" D3DCOMPILER "\") failed!\n");
+ return GHOST_kFailure;
+ }
+ }
+#endif
+
+ EGLDisplay prev_display = eglGetCurrentDisplay();
+ EGLSurface prev_draw = eglGetCurrentSurface(EGL_DRAW);
+ EGLSurface prev_read = eglGetCurrentSurface(EGL_READ);
+ EGLContext prev_context = eglGetCurrentContext();
+
+ m_display = ::eglGetDisplay(m_nativeDisplay);
+
+ if (!EGL_CHK(m_display != EGL_NO_DISPLAY))
+ return GHOST_kFailure;
+
+ EGLint egl_major, egl_minor;
+
+ if (!EGL_CHK(::eglInitialize(m_display, &egl_major, &egl_minor)))
+ goto error;
+
+ fprintf(stderr, "EGL Version %d.%d\n", egl_major, egl_minor);
+
+ if (!EGL_CHK(::eglMakeCurrent(m_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT)))
+ goto error;
+
+ initContextEGLEW();
+
+ if (!bindAPI(m_api))
+ goto error;
+
+
+ // build attribute list
+
+ attrib_list.reserve(20);
+
+ if (m_api == EGL_OPENGL_ES_API && EGLEW_VERSION_1_2) {
+ // According to the spec it seems that you are required to set EGL_RENDERABLE_TYPE,
+ // but some implementations (ANGLE) do not seem to care.
+
+ if (m_contextMajorVersion == 1) {
+ attrib_list.push_back(EGL_RENDERABLE_TYPE);
+ attrib_list.push_back(EGL_OPENGL_ES_BIT);
+ }
+ else if (m_contextMajorVersion == 2) {
+ attrib_list.push_back(EGL_RENDERABLE_TYPE);
+ attrib_list.push_back(EGL_OPENGL_ES2_BIT);
+ }
+ else if (m_contextMajorVersion == 3) {
+ attrib_list.push_back(EGL_RENDERABLE_TYPE);
+ attrib_list.push_back(EGL_OPENGL_ES3_BIT_KHR);
+ }
+ else {
+ fprintf(stderr,
+ "Warning! Unable to request an ES context of version %d.%d\n",
+ m_contextMajorVersion, m_contextMinorVersion);
+ }
+
+ if (!((m_contextMajorVersion == 1) ||
+ (m_contextMajorVersion == 2 && EGLEW_VERSION_1_3) ||
+ (m_contextMajorVersion == 3 && /*EGLEW_VERSION_1_4 &&*/ EGLEW_KHR_create_context) ||
+ (m_contextMajorVersion == 3 && EGLEW_VERSION_1_5)))
+ {
+ fprintf(stderr,
+ "Warning! May not be able to create a version %d.%d ES context with version %d.%d of EGL\n",
+ m_contextMajorVersion, m_contextMinorVersion, egl_major, egl_minor);
+ }
+ }
+
+ attrib_list.push_back(EGL_RED_SIZE);
+ attrib_list.push_back(8);
+
+ attrib_list.push_back(EGL_GREEN_SIZE);
+ attrib_list.push_back(8);
+
+ attrib_list.push_back(EGL_BLUE_SIZE);
+ attrib_list.push_back(8);
+
+#ifdef GHOST_OPENGL_ALPHA
+ attrib_list.push_back(EGL_ALPHA_SIZE);
+ attrib_list.push_back(8);
+#endif
+
+ attrib_list.push_back(EGL_DEPTH_SIZE);
+ attrib_list.push_back(24);
+
+#ifdef GHOST_OPENGL_STENCIL
+ attrib_list.push_back(EGL_STENCIL_SIZE);
+ attrib_list.push_back(8);
+#endif
+
+ if (m_numOfAASamples > 0) {
+ attrib_list.push_back(EGL_SAMPLE_BUFFERS);
+ attrib_list.push_back(1);
+
+ attrib_list.push_back(EGL_SAMPLES);
+ attrib_list.push_back(m_numOfAASamples);
+ }
+
+ attrib_list.push_back(EGL_NONE);
+
+ EGLConfig config;
+
+ if (!EGL_CHK(::eglChooseConfig(m_display, &(attrib_list[0]), &config, 1, &num_config)))
+ goto error;
+
+ // A common error is to assume that ChooseConfig worked because it returned EGL_TRUE
+ if (num_config != 1) // num_config should be exactly 1
+ goto error;
+
+ if (m_numOfAASamples > 0) {
+ EGLint actualSamples;
+
+ if (!EGL_CHK(::eglGetConfigAttrib(m_display, config, EGL_SAMPLE_BUFFERS, &actualSamples)))
+ goto error;
+
+ if (m_numOfAASamples != actualSamples) {
+ fprintf(stderr,
+ "Warning! Unable to find a multisample pixel format that supports exactly %d samples. "
+ "Substituting one that uses %d samples.\n",
+ m_numOfAASamples,
+ actualSamples);
+
+ m_numOfAASamples = (GHOST_TUns16)actualSamples;
+ }
+ }
+
+ m_surface = ::eglCreateWindowSurface(m_display, config, m_nativeWindow, NULL);
+
+ if (!EGL_CHK(m_surface != EGL_NO_SURFACE))
+ goto error;
+
+ attrib_list.clear();
+
+ if (EGLEW_VERSION_1_5 || EGLEW_KHR_create_context) {
+ if (m_api == EGL_OPENGL_API || m_api == EGL_OPENGL_ES_API) {
+ if (m_contextMajorVersion != 0) {
+ attrib_list.push_back(EGL_CONTEXT_MAJOR_VERSION_KHR);
+ attrib_list.push_back(m_contextMajorVersion);
+ }
+
+ if (m_contextMinorVersion != 0) {
+ attrib_list.push_back(EGL_CONTEXT_MINOR_VERSION_KHR);
+ attrib_list.push_back(m_contextMinorVersion);
+ }
+
+ if (m_contextFlags != 0) {
+ attrib_list.push_back(EGL_CONTEXT_FLAGS_KHR);
+ attrib_list.push_back(m_contextFlags);
+ }
+ }
+ else {
+ if (m_contextMajorVersion != 0 || m_contextMinorVersion != 0) {
+ fprintf(stderr,
+ "Warning! Cannot request specific versions of %s contexts.",
+ api_string(m_api).c_str());
+ }
+
+ if (m_contextFlags != 0) {
+ fprintf(stderr,
+ "Warning! Flags cannot be set on %s contexts.",
+ api_string(m_api).c_str());
+ }
+ }
+
+ if (m_api == EGL_OPENGL_API) {
+ if (m_contextProfileMask != 0) {
+ attrib_list.push_back(EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR);
+ attrib_list.push_back(m_contextProfileMask);
+ }
+ }
+ else {
+ if (m_contextProfileMask != 0)
+ fprintf(stderr,
+ "Warning! Cannot select profile for %s contexts.",
+ api_string(m_api).c_str());
+ }
+
+ if (m_api == EGL_OPENGL_API || EGLEW_VERSION_1_5) {
+ if (m_contextResetNotificationStrategy != 0) {
+ attrib_list.push_back(EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR);
+ attrib_list.push_back(m_contextResetNotificationStrategy);
+ }
+ }
+ else {
+ if (m_contextResetNotificationStrategy != 0) {
+ fprintf(stderr,
+ "Warning! EGL %d.%d cannot set the reset notification strategy on %s contexts.",
+ egl_major, egl_minor, api_string(m_api).c_str());
+ }
+ }
+ }
+ else {
+ if (m_api == EGL_OPENGL_ES_API) {
+ if (m_contextMajorVersion != 0) {
+ attrib_list.push_back(EGL_CONTEXT_CLIENT_VERSION);
+ attrib_list.push_back(m_contextMajorVersion);
+ }
+ }
+ else {
+ if (m_contextMajorVersion != 0 || m_contextMinorVersion != 0) {
+ fprintf(stderr,
+ "Warning! EGL %d.%d is unable to select between versions of %s.",
+ egl_major, egl_minor, api_string(m_api).c_str());
+ }
+ }
+
+ if (m_contextFlags != 0) {
+ fprintf(stderr,
+ "Warning! EGL %d.%d is unable to set context flags.",
+ egl_major, egl_minor);
+ }
+ if (m_contextProfileMask != 0) {
+ fprintf(stderr,
+ "Warning! EGL %d.%d is unable to select between profiles.",
+ egl_major, egl_minor);
+ }
+ if (m_contextResetNotificationStrategy != 0) {
+ fprintf(stderr,
+ "Warning! EGL %d.%d is unable to set the reset notification strategies.",
+ egl_major, egl_minor);
+ }
+ }
+
+ attrib_list.push_back(EGL_NONE);
+
+ m_context = ::eglCreateContext(m_display, config, m_sharedContext, &(attrib_list[0]));
+
+ if (!EGL_CHK(m_context != EGL_NO_CONTEXT))
+ goto error;
+
+ if (m_sharedContext == EGL_NO_CONTEXT)
+ m_sharedContext = m_context;
+
+ m_sharedCount++;
+
+ if (!EGL_CHK(::eglMakeCurrent(m_display, m_surface, m_surface, m_context)))
+ goto error;
+
+ initContextGLEW();
+
+ initClearGL();
+ ::eglSwapBuffers(m_display, m_surface);
+
+ return GHOST_kSuccess;
+
+error:
+ if (prev_display != EGL_NO_DISPLAY)
+ EGL_CHK(eglMakeCurrent(prev_display, prev_draw, prev_read, prev_context));
+
+ return GHOST_kFailure;
+}
+
+
+GHOST_TSuccess GHOST_ContextEGL::releaseNativeHandles()
+{
+ m_nativeWindow = 0;
+ m_nativeDisplay = NULL;
+
+ return GHOST_kSuccess;
+}
diff --git a/intern/ghost/intern/GHOST_ContextEGL.h b/intern/ghost/intern/GHOST_ContextEGL.h
new file mode 100644
index 00000000000..70c26c940fc
--- /dev/null
+++ b/intern/ghost/intern/GHOST_ContextEGL.h
@@ -0,0 +1,167 @@
+/*
+ * ***** 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): Jason Wilkins
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file ghost/intern/GHOST_ContextEGL.h
+ * \ingroup GHOST
+ */
+
+#ifndef __GHOST_CONTEXTEGL_H__
+#define __GHOST_CONTEXTEGL_H__
+
+#include "GHOST_Context.h"
+
+#ifdef WITH_GLEW_MX
+# define eglewGetContext() eglewContext
+#endif
+
+#include <GL/eglew.h>
+
+#ifdef WITH_GLEW_MX
+extern "C" EGLEWContext *eglewContext;
+#endif
+
+
+#ifndef GHOST_OPENGL_EGL_CONTEXT_FLAGS
+#define GHOST_OPENGL_EGL_CONTEXT_FLAGS 0
+#endif
+
+#ifndef GHOST_OPENGL_EGL_RESET_NOTIFICATION_STRATEGY
+#define GHOST_OPENGL_EGL_RESET_NOTIFICATION_STRATEGY 0
+#endif
+
+
+class GHOST_ContextEGL : public GHOST_Context
+{
+public:
+ /**
+ * Constructor.
+ */
+ GHOST_ContextEGL(
+ bool stereoVisual,
+ GHOST_TUns16 numOfAASamples,
+ EGLNativeWindowType nativeWindow,
+ EGLNativeDisplayType nativeDisplay,
+ EGLint contextProfileMask,
+ EGLint contextMajorVersion,
+ EGLint contextMinorVersion,
+ EGLint contextFlags,
+ EGLint contextResetNotificationStrategy,
+ EGLenum api);
+
+ /**
+ * Destructor.
+ */
+ ~GHOST_ContextEGL();
+
+ /**
+ * Swaps front and back buffers of a window.
+ * \return A boolean success indicator.
+ */
+ GHOST_TSuccess swapBuffers();
+
+ /**
+ * Activates the drawing context of this window.
+ * \return A boolean success indicator.
+ */
+ GHOST_TSuccess activateDrawingContext();
+
+ /**
+ * Call immediately after new to initialize. If this fails then immediately delete the object.
+ * \return Indication as to whether initialization has succeeded.
+ */
+ GHOST_TSuccess initializeDrawingContext();
+
+ /**
+ * Removes references to native handles from this context and then returns
+ * \return GHOST_kSuccess if it is OK for the parent to release the handles and
+ * GHOST_kFailure if releasing the handles will interfere with sharing
+ */
+ GHOST_TSuccess releaseNativeHandles();
+
+ /**
+ * Sets the swap interval for swapBuffers.
+ * \param interval The swap interval to use.
+ * \return A boolean success indicator.
+ */
+ GHOST_TSuccess setSwapInterval(int interval);
+
+ /**
+ * Gets the current swap interval for swapBuffers.
+ * \param intervalOut Variable to store the swap interval if it can be read.
+ * \return Whether the swap interval can be read.
+ */
+ GHOST_TSuccess getSwapInterval(int &intervalOut);
+
+protected:
+ inline void activateEGLEW() const {
+#ifdef WITH_GLEW_MX
+ eglewContext = m_eglewContext;
+#endif
+ }
+
+private:
+ void initContextEGLEW();
+
+ EGLNativeDisplayType m_nativeDisplay;
+ EGLNativeWindowType m_nativeWindow;
+
+ const EGLint m_contextProfileMask;
+ const EGLint m_contextMajorVersion;
+ const EGLint m_contextMinorVersion;
+ const EGLint m_contextFlags;
+ const EGLint m_contextResetNotificationStrategy;
+
+ const EGLenum m_api;
+
+ EGLContext m_context;
+ EGLSurface m_surface;
+ EGLDisplay m_display;
+
+ EGLint m_swap_interval;
+
+#ifdef WITH_GLEW_MX
+ EGLEWContext *m_eglewContext;
+#endif
+
+ EGLContext &m_sharedContext;
+ EGLint &m_sharedCount;
+
+ static EGLContext s_gl_sharedContext;
+ static EGLint s_gl_sharedCount;
+
+ static EGLContext s_gles_sharedContext;
+ static EGLint s_gles_sharedCount;
+
+ static EGLContext s_vg_sharedContext;
+ static EGLint s_vg_sharedCount;
+
+#ifdef WITH_GL_ANGLE
+ static HMODULE s_d3dcompiler;
+#endif
+};
+
+#endif // __GHOST_CONTEXTEGL_H__
diff --git a/intern/ghost/intern/GHOST_ContextGLX.cpp b/intern/ghost/intern/GHOST_ContextGLX.cpp
new file mode 100644
index 00000000000..02b43abec6c
--- /dev/null
+++ b/intern/ghost/intern/GHOST_ContextGLX.cpp
@@ -0,0 +1,411 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2014 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Jason Wilkins
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file ghost/intern/GHOST_ContextGLX.cpp
+ * \ingroup GHOST
+ *
+ * Definition of GHOST_ContextGLX class.
+ */
+
+#include "GHOST_ContextGLX.h"
+#include "GHOST_SystemX11.h"
+
+#include <vector>
+
+#include <cassert>
+#include <cstdio>
+#include <cstring>
+
+
+#ifdef WITH_GLEW_MX
+GLXEWContext *glxewContext = NULL;
+#endif
+
+GLXContext GHOST_ContextGLX::s_sharedContext = None;
+int GHOST_ContextGLX::s_sharedCount = 0;
+
+
+GHOST_ContextGLX::GHOST_ContextGLX(
+ bool stereoVisual,
+ GHOST_TUns16 numOfAASamples,
+ Window window,
+ Display *display,
+ XVisualInfo *visualInfo,
+ int contextProfileMask,
+ int contextMajorVersion,
+ int contextMinorVersion,
+ int contextFlags,
+ int contextResetNotificationStrategy)
+ : GHOST_Context(stereoVisual, numOfAASamples),
+ m_display(display),
+ m_visualInfo(visualInfo),
+ m_window(window),
+ m_contextProfileMask(contextProfileMask),
+ m_contextMajorVersion(contextMajorVersion),
+ m_contextMinorVersion(contextMinorVersion),
+ m_contextFlags(contextFlags),
+ m_contextResetNotificationStrategy(contextResetNotificationStrategy),
+ m_context(None)
+#ifdef WITH_GLEW_MX
+ ,
+ m_glxewContext(NULL)
+#endif
+{
+ assert(m_window != 0);
+ assert(m_display != NULL);
+}
+
+
+GHOST_ContextGLX::~GHOST_ContextGLX()
+{
+ if (m_display != NULL) {
+ activateGLXEW();
+
+ if (m_context != None) {
+ if (m_window != 0 && m_context == ::glXGetCurrentContext())
+ ::glXMakeCurrent(m_display, m_window, NULL);
+
+ if (m_context != s_sharedContext || s_sharedCount == 1) {
+ assert(s_sharedCount > 0);
+
+ s_sharedCount--;
+
+ if (s_sharedCount == 0)
+ s_sharedContext = NULL;
+
+ ::glXDestroyContext(m_display, m_context);
+ }
+ }
+
+#ifdef WITH_GLEW_MX
+ if (m_glxewContext)
+ delete m_glxewContext;
+#endif
+ }
+}
+
+
+GHOST_TSuccess GHOST_ContextGLX::swapBuffers()
+{
+ ::glXSwapBuffers(m_display, m_window);
+
+ return GHOST_kSuccess;
+}
+
+
+GHOST_TSuccess GHOST_ContextGLX::activateDrawingContext()
+{
+ if (m_display) {
+ activateGLXEW();
+ activateGLEW();
+
+ return ::glXMakeCurrent(m_display, m_window, m_context) ? GHOST_kSuccess : GHOST_kFailure;
+ }
+ else {
+ return GHOST_kFailure;
+ }
+}
+
+void GHOST_ContextGLX::initContextGLXEW()
+{
+#ifdef WITH_GLEW_MX
+ glxewContext = new GLXEWContext;
+ memset(glxewContext, 0, sizeof(GLXEWContext));
+
+ if (m_glxewContext)
+ delete m_glxewContext;
+ m_glxewContext = glxewContext;
+#endif
+
+ initContextGLEW();
+}
+
+GHOST_TSuccess GHOST_ContextGLX::initializeDrawingContext()
+{
+#ifdef WITH_X11_XINPUT
+ /* use our own event handlers to avoid exiting blender,
+ * this would happen for eg:
+ * if you open blender, unplug a tablet, then open a new window. */
+ XErrorHandler old_handler = XSetErrorHandler (GHOST_X11_ApplicationErrorHandler );
+ XIOErrorHandler old_handler_io = XSetIOErrorHandler(GHOST_X11_ApplicationIOErrorHandler);
+#endif
+
+ /* needed so 'GLXEW_ARB_create_context' is valid */
+ mxIgnoreNoVersion(1);
+ initContextGLXEW();
+ mxIgnoreNoVersion(0);
+
+ if (GLXEW_ARB_create_context) {
+ int profileBitCore = m_contextProfileMask & GLX_CONTEXT_CORE_PROFILE_BIT_ARB;
+ int profileBitCompat = m_contextProfileMask & GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB;
+
+#ifdef WITH_GLEW_ES
+ int profileBitES = m_contextProfileMask & GLX_CONTEXT_ES_PROFILE_BIT_EXT;
+#endif
+
+ if (!GLXEW_ARB_create_context_profile && profileBitCore)
+ fprintf(stderr, "Warning! OpenGL core profile not available.\n");
+
+ if (!GLXEW_ARB_create_context_profile && profileBitCompat)
+ fprintf(stderr, "Warning! OpenGL compatibility profile not available.\n");
+
+#ifdef WITH_GLEW_ES
+ if (!GLXEW_EXT_create_context_es_profile && profileBitES && m_contextMajorVersion == 1)
+ fprintf(stderr, "Warning! OpenGL ES profile not available.\n");
+
+ if (!GLXEW_EXT_create_context_es2_profile && profileBitES && m_contextMajorVersion == 2)
+ fprintf(stderr, "Warning! OpenGL ES2 profile not available.\n");
+#endif
+
+ int profileMask = 0;
+
+ if (GLXEW_ARB_create_context_profile && profileBitCore)
+ profileMask |= profileBitCore;
+
+ if (GLXEW_ARB_create_context_profile && profileBitCompat)
+ profileMask |= profileBitCompat;
+
+#ifdef WITH_GLEW_ES
+ if (GLXEW_EXT_create_context_es_profile && profileBitES)
+ profileMask |= profileBitES;
+#endif
+
+ if (profileMask != m_contextProfileMask)
+ fprintf(stderr, "Warning! Ignoring untested OpenGL context profile mask bits.");
+
+
+ /* max 10 attributes plus terminator */
+ int attribs[11];
+ int i = 0;
+
+ if (profileMask) {
+ attribs[i++] = GLX_CONTEXT_PROFILE_MASK_ARB;
+ attribs[i++] = profileMask;
+ }
+
+ if (m_contextMajorVersion != 0) {
+ attribs[i++] = GLX_CONTEXT_MAJOR_VERSION_ARB;
+ attribs[i++] = m_contextMajorVersion;
+ }
+
+ if (m_contextMinorVersion != 0) {
+ attribs[i++] = GLX_CONTEXT_MINOR_VERSION_ARB;
+ attribs[i++] = m_contextMinorVersion;
+ }
+
+ if (m_contextFlags != 0) {
+ attribs[i++] = GLX_CONTEXT_FLAGS_ARB;
+ attribs[i++] = m_contextFlags;
+ }
+
+ if (m_contextResetNotificationStrategy != 0) {
+ if (GLXEW_ARB_create_context_robustness) {
+ attribs[i++] = GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB;
+ attribs[i++] = m_contextResetNotificationStrategy;
+ }
+ else {
+ fprintf(stderr, "Warning! Cannot set the reset notification strategy.");
+ }
+ }
+ attribs[i++] = 0;
+
+ /* Create a GL 3.x context */
+ GLXFBConfig *framebuffer_config = NULL;
+ {
+ int glx_attribs[64];
+ int fbcount = 0;
+
+ GHOST_X11_GL_GetAttributes(glx_attribs, 64, m_numOfAASamples, m_stereoVisual, true);
+
+ framebuffer_config = glXChooseFBConfig(m_display, DefaultScreen(m_display), glx_attribs, &fbcount);
+ }
+
+ if (framebuffer_config) {
+ m_context = glXCreateContextAttribsARB(m_display, framebuffer_config[0], s_sharedContext, True, attribs);
+ XFree(framebuffer_config);
+ }
+ }
+ else {
+ /* Create legacy context */
+ m_context = glXCreateContext(m_display, m_visualInfo, s_sharedContext, True);
+ }
+
+ GHOST_TSuccess success;
+
+ if (m_context != NULL) {
+ if (!s_sharedContext)
+ s_sharedContext = m_context;
+
+ s_sharedCount++;
+
+ glXMakeCurrent(m_display, m_window, m_context);
+
+ initClearGL();
+ ::glXSwapBuffers(m_display, m_window);
+
+ /* re initialize to get the extensions properly */
+ initContextGLXEW();
+
+ success = GHOST_kSuccess;
+ }
+ else {
+ /* freeing well clean up the context initialized above */
+ success = GHOST_kFailure;
+ }
+
+#ifdef WITH_X11_XINPUT
+ /* Restore handler */
+ XSetErrorHandler (old_handler);
+ XSetIOErrorHandler(old_handler_io);
+#endif
+
+ return success;
+}
+
+
+GHOST_TSuccess GHOST_ContextGLX::releaseNativeHandles()
+{
+ m_window = 0;
+
+ return GHOST_kSuccess;
+}
+
+
+GHOST_TSuccess GHOST_ContextGLX::setSwapInterval(int interval)
+{
+ if (GLXEW_EXT_swap_control) {
+ ::glXSwapIntervalEXT(m_display, m_window, interval);
+
+ return GHOST_kSuccess;
+ }
+ else {
+ return GHOST_kFailure;
+ }
+}
+
+
+GHOST_TSuccess GHOST_ContextGLX::getSwapInterval(int &intervalOut)
+{
+ if (GLXEW_EXT_swap_control) {
+ unsigned int interval = 0;
+
+ ::glXQueryDrawable(m_display, m_window, GLX_SWAP_INTERVAL_EXT, &interval);
+
+ intervalOut = static_cast<int>(interval);
+
+ return GHOST_kSuccess;
+ }
+ else {
+ return GHOST_kFailure;
+ }
+}
+
+/**
+ * Utility function to get GLX attributes.
+ *
+ * \param for_fb_config: There are some small differences in
+ * #glXChooseVisual and #glXChooseFBConfig's attribute encoding.
+ *
+ * \note Similar to SDL's 'X11_GL_GetAttributes'
+ */
+int GHOST_X11_GL_GetAttributes(
+ int *attribs, int attribs_max,
+ int samples, bool is_stereo_visual,
+ bool for_fb_config)
+{
+ int i = 0;
+
+#ifdef GHOST_OPENGL_ALPHA
+ const bool need_alpha = true;
+#else
+ const bool need_alpha = false;
+#endif
+
+#ifdef GHOST_OPENGL_STENCIL
+ const bool need_stencil = true;
+#else
+ const bool need_stencil = false;
+#endif
+
+ if (is_stereo_visual) {
+ attribs[i++] = GLX_STEREO;
+ if (for_fb_config) {
+ attribs[i++] = True;
+ }
+ }
+
+ if (for_fb_config) {
+ attribs[i++] = GLX_RENDER_TYPE;
+ attribs[i++] = GLX_RGBA_BIT;
+ }
+ else {
+ attribs[i++] = GLX_RGBA;
+ }
+
+ attribs[i++] = GLX_DOUBLEBUFFER;
+ if (for_fb_config) {
+ attribs[i++] = True;
+ }
+
+ attribs[i++] = GLX_RED_SIZE;
+ attribs[i++] = True;
+
+ attribs[i++] = GLX_BLUE_SIZE;
+ attribs[i++] = True;
+
+ attribs[i++] = GLX_GREEN_SIZE;
+ attribs[i++] = True;
+
+ attribs[i++] = GLX_DEPTH_SIZE;
+ attribs[i++] = True;
+
+ if (need_alpha) {
+ attribs[i++] = GLX_ALPHA_SIZE;
+ attribs[i++] = True;
+ }
+
+ if (need_stencil) {
+ attribs[i++] = GLX_STENCIL_SIZE;
+ attribs[i++] = True;
+ }
+
+ if (samples) {
+ attribs[i++] = GLX_SAMPLE_BUFFERS_ARB;
+ attribs[i++] = True;
+
+ attribs[i++] = GLX_SAMPLES_ARB;
+ attribs[i++] = samples;
+ }
+
+ attribs[i++] = 0;
+
+ GHOST_ASSERT(i <= attribs_max, "attribute size too small");
+
+ (void)attribs_max;
+
+ return i;
+}
diff --git a/intern/ghost/intern/GHOST_ContextGLX.h b/intern/ghost/intern/GHOST_ContextGLX.h
new file mode 100644
index 00000000000..8c2231a0b01
--- /dev/null
+++ b/intern/ghost/intern/GHOST_ContextGLX.h
@@ -0,0 +1,156 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2014 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Jason Wilkins
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file ghost/intern/GHOST_ContextGLX.h
+ * \ingroup GHOST
+ */
+
+#ifndef __GHOST_CONTEXTGLX_H__
+#define __GHOST_CONTEXTGLX_H__
+
+#include "GHOST_Context.h"
+
+#ifdef WITH_GLEW_MX
+# define glxewGetContext() glxewContext
+#endif
+
+#include <GL/glxew.h>
+
+#ifdef WITH_GLEW_MX
+extern "C" GLXEWContext *glxewContext;
+#endif
+
+
+#ifndef GHOST_OPENGL_GLX_CONTEXT_FLAGS
+/* leave as convenience define for the future */
+#define GHOST_OPENGL_GLX_CONTEXT_FLAGS 0
+#endif
+
+#ifndef GHOST_OPENGL_GLX_RESET_NOTIFICATION_STRATEGY
+#define GHOST_OPENGL_GLX_RESET_NOTIFICATION_STRATEGY 0
+#endif
+
+class GHOST_ContextGLX : public GHOST_Context
+{
+public:
+ /**
+ * Constructor.
+ */
+ GHOST_ContextGLX(
+ bool stereoVisual,
+ GHOST_TUns16 numOfAASamples,
+ Window window,
+ Display *display,
+ XVisualInfo *visualInfo,
+ int contextProfileMask,
+ int contextMajorVersion,
+ int contextMinorVersion,
+ int contextFlags,
+ int contextResetNotificationStrategy);
+
+ /**
+ * Destructor.
+ */
+ ~GHOST_ContextGLX();
+
+ /**
+ * Swaps front and back buffers of a window.
+ * \return A boolean success indicator.
+ */
+ GHOST_TSuccess swapBuffers();
+
+ /**
+ * Activates the drawing context of this window.
+ * \return A boolean success indicator.
+ */
+ GHOST_TSuccess activateDrawingContext();
+
+ /**
+ * Call immediately after new to initialize. If this fails then immediately delete the object.
+ * \return Indication as to whether initialization has succeeded.
+ */
+ GHOST_TSuccess initializeDrawingContext();
+
+ /**
+ * Removes references to native handles from this context and then returns
+ * \return GHOST_kSuccess if it is OK for the parent to release the handles and
+ * GHOST_kFailure if releasing the handles will interfere with sharing
+ */
+ GHOST_TSuccess releaseNativeHandles();
+
+ /**
+ * Sets the swap interval for swapBuffers.
+ * \param interval The swap interval to use.
+ * \return A boolean success indicator.
+ */
+ GHOST_TSuccess setSwapInterval(int interval);
+
+ /**
+ * Gets the current swap interval for swapBuffers.
+ * \param intervalOut Variable to store the swap interval if it can be read.
+ * \return Whether the swap interval can be read.
+ */
+ GHOST_TSuccess getSwapInterval(int &intervalOut);
+
+protected:
+ inline void activateGLXEW() const {
+#ifdef WITH_GLEW_MX
+ glxewContext = m_glxewContext;
+#endif
+ }
+
+private:
+ void initContextGLXEW();
+
+ Display *m_display;
+ XVisualInfo *m_visualInfo;
+ Window m_window;
+
+ const int m_contextProfileMask;
+ const int m_contextMajorVersion;
+ const int m_contextMinorVersion;
+ const int m_contextFlags;
+ const int m_contextResetNotificationStrategy;
+
+ GLXContext m_context;
+
+#ifdef WITH_GLEW_MX
+ GLXEWContext *m_glxewContext;
+#endif
+
+ /** The first created OpenGL context (for sharing display lists) */
+ static GLXContext s_sharedContext;
+ static int s_sharedCount;
+};
+
+/* used to get GLX info */
+int GHOST_X11_GL_GetAttributes(
+ int *attribs, int attribs_max,
+ int samples, bool is_stereo_visual,
+ bool for_fb_config);
+
+#endif // __GHOST_CONTEXTGLX_H__
diff --git a/intern/ghost/intern/GHOST_ContextNone.cpp b/intern/ghost/intern/GHOST_ContextNone.cpp
new file mode 100644
index 00000000000..380ab532f7a
--- /dev/null
+++ b/intern/ghost/intern/GHOST_ContextNone.cpp
@@ -0,0 +1,79 @@
+/*
+ * ***** 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): Jason Wilkins
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file ghost/intern/GHOST_ContextNone.cpp
+ * \ingroup GHOST
+ *
+ * Definition of GHOST_ContextNone class.
+ */
+
+#include "GHOST_ContextNone.h"
+
+
+GHOST_TSuccess GHOST_ContextNone::swapBuffers()
+{
+ return GHOST_kSuccess;
+}
+
+
+GHOST_TSuccess GHOST_ContextNone::activateDrawingContext()
+{
+ return GHOST_kSuccess;
+}
+
+
+GHOST_TSuccess GHOST_ContextNone::updateDrawingContext()
+{
+ return GHOST_kSuccess;
+}
+
+
+GHOST_TSuccess GHOST_ContextNone::initializeDrawingContext()
+{
+ return GHOST_kSuccess;
+}
+
+
+GHOST_TSuccess GHOST_ContextNone::releaseNativeHandles()
+{
+ return GHOST_kSuccess;
+}
+
+
+GHOST_TSuccess GHOST_ContextNone::setSwapInterval(int interval)
+{
+ m_swapInterval = interval;
+
+ return GHOST_kSuccess;
+}
+
+
+GHOST_TSuccess GHOST_ContextNone::getSwapInterval(int &intervalOut)
+{
+ intervalOut = m_swapInterval;
+ return GHOST_kSuccess;
+}
diff --git a/intern/ghost/intern/GHOST_ContextNone.h b/intern/ghost/intern/GHOST_ContextNone.h
new file mode 100644
index 00000000000..80cce76190d
--- /dev/null
+++ b/intern/ghost/intern/GHOST_ContextNone.h
@@ -0,0 +1,97 @@
+/*
+ * ***** 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): Jason Wilkins
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file ghost/intern/GHOST_ContextNone.h
+ * \ingroup GHOST
+ *
+ * Declaration of GHOST_Context class.
+ */
+
+#ifndef __GHOST_CONTEXTNONE_H__
+#define __GHOST_CONTEXTNONE_H__
+
+#include "GHOST_Context.h"
+
+class GHOST_ContextNone : public GHOST_Context
+{
+public:
+
+ GHOST_ContextNone(
+ bool stereoVisual,
+ GHOST_TUns16 numOfAASamples)
+ : GHOST_Context(stereoVisual, numOfAASamples),
+ m_swapInterval(1)
+ {}
+
+ /**
+ * Dummy function
+ * \return Always succeeds
+ */
+ GHOST_TSuccess swapBuffers();
+
+ /**
+ * Dummy function
+ * \return Always succeeds
+ */
+ GHOST_TSuccess activateDrawingContext();
+
+ /**
+ * Dummy function
+ * \return Always succeeds
+ */
+ GHOST_TSuccess updateDrawingContext();
+
+ /**
+ * Dummy function
+ * \return Always succeeds
+ */
+ GHOST_TSuccess initializeDrawingContext();
+
+ /**
+ * Dummy function
+ * \return Always succeeds
+ */
+ GHOST_TSuccess releaseNativeHandles();
+
+ /**
+ * Dummy function
+ * \return Always succeeds
+ */
+ GHOST_TSuccess setSwapInterval(int interval);
+
+ /**
+ * Dummy function
+ * \param intervalOut Gets whatever was set by setSwapInterval
+ * \return Always succeeds
+ */
+ GHOST_TSuccess getSwapInterval(int &intervalOut);
+
+private:
+ int m_swapInterval;
+};
+
+#endif // __GHOST_CONTEXTNONE_H__
diff --git a/intern/ghost/intern/GHOST_ContextSDL.cpp b/intern/ghost/intern/GHOST_ContextSDL.cpp
new file mode 100644
index 00000000000..d80a638818c
--- /dev/null
+++ b/intern/ghost/intern/GHOST_ContextSDL.cpp
@@ -0,0 +1,204 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2014 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Jason Wilkins
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file ghost/intern/GHOST_ContextSDL.cpp
+ * \ingroup GHOST
+ *
+ * Definition of GHOST_ContextSDL class.
+ */
+
+#include "GHOST_ContextSDL.h"
+
+#include <vector>
+
+#include <cassert>
+#include <cstdio>
+#include <cstring>
+
+
+SDL_GLContext GHOST_ContextSDL::s_sharedContext = NULL;
+int GHOST_ContextSDL::s_sharedCount = 0;
+
+
+GHOST_ContextSDL::GHOST_ContextSDL(
+ bool stereoVisual,
+ GHOST_TUns16 numOfAASamples,
+ SDL_Window *window,
+ int contextProfileMask,
+ int contextMajorVersion,
+ int contextMinorVersion,
+ int contextFlags,
+ int contextResetNotificationStrategy)
+ : GHOST_Context(stereoVisual, numOfAASamples),
+ m_window(window),
+ m_contextProfileMask(contextProfileMask),
+ m_contextMajorVersion(contextMajorVersion),
+ m_contextMinorVersion(contextMinorVersion),
+ m_contextFlags(contextFlags),
+ m_contextResetNotificationStrategy(contextResetNotificationStrategy),
+ m_context(NULL)
+{
+ assert(m_window != NULL);
+}
+
+
+GHOST_ContextSDL::~GHOST_ContextSDL()
+{
+ if (m_context != NULL) {
+ if (m_window != 0 && m_context == SDL_GL_GetCurrentContext())
+ SDL_GL_MakeCurrent(m_window, m_context);
+
+ if (m_context != s_sharedContext || s_sharedCount == 1) {
+ assert(s_sharedCount > 0);
+
+ s_sharedCount--;
+
+ if (s_sharedCount == 0)
+ s_sharedContext = NULL;
+
+ SDL_GL_DeleteContext(m_context);
+ }
+ }
+}
+
+
+GHOST_TSuccess GHOST_ContextSDL::swapBuffers()
+{
+ SDL_GL_SwapWindow(m_window);
+
+ return GHOST_kSuccess;
+}
+
+
+GHOST_TSuccess GHOST_ContextSDL::activateDrawingContext()
+{
+ if (m_context) {
+ activateGLEW();
+
+ return SDL_GL_MakeCurrent(m_window, m_context) ? GHOST_kSuccess : GHOST_kFailure;
+ }
+ else {
+ return GHOST_kFailure;
+ }
+}
+
+
+GHOST_TSuccess GHOST_ContextSDL::initializeDrawingContext()
+{
+#ifdef GHOST_OPENGL_ALPHA
+ const bool needAlpha = true;
+#else
+ const bool needAlpha = false;
+#endif
+
+#ifdef GHOST_OPENGL_STENCIL
+ const bool needStencil = true;
+#else
+ const bool needStencil = false;
+#endif
+
+ SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, m_contextProfileMask);
+ SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, m_contextMajorVersion);
+ SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, m_contextMinorVersion);
+ SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, m_contextFlags);
+
+ SDL_GL_SetAttribute(SDL_GL_SHARE_WITH_CURRENT_CONTEXT, 1);
+ SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
+ SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
+ SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
+ SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
+ SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
+
+ if (needAlpha) {
+ SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8);
+ }
+
+ if (needStencil) {
+ SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 1);
+ }
+
+ if (m_stereoVisual) {
+ SDL_GL_SetAttribute(SDL_GL_STEREO, 1);
+ }
+
+ if (m_numOfAASamples) {
+ SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1);
+ SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, m_numOfAASamples);
+ }
+
+ m_context = SDL_GL_CreateContext(m_window);
+
+ GHOST_TSuccess success;
+
+ if (m_context != NULL) {
+ if (!s_sharedContext)
+ s_sharedContext = m_context;
+
+ s_sharedCount++;
+
+ success = (SDL_GL_MakeCurrent(m_window, m_context) < 0) ?
+ GHOST_kFailure : GHOST_kSuccess;
+
+ initContextGLEW();
+
+ initClearGL();
+ SDL_GL_SwapWindow(m_window);
+
+ success = GHOST_kSuccess;
+ }
+ else {
+ success = GHOST_kFailure;
+ }
+
+ return success;
+}
+
+
+GHOST_TSuccess GHOST_ContextSDL::releaseNativeHandles()
+{
+ m_window = NULL;
+
+ return GHOST_kSuccess;
+}
+
+
+GHOST_TSuccess GHOST_ContextSDL::setSwapInterval(int interval)
+{
+ if (SDL_GL_SetSwapInterval(interval) != -1) {
+ return GHOST_kSuccess;
+ }
+ else {
+ return GHOST_kFailure;
+ }
+}
+
+
+GHOST_TSuccess GHOST_ContextSDL::getSwapInterval(int &intervalOut)
+{
+ intervalOut = SDL_GL_GetSwapInterval();
+ return GHOST_kSuccess;
+}
diff --git a/intern/ghost/intern/GHOST_ContextSDL.h b/intern/ghost/intern/GHOST_ContextSDL.h
new file mode 100644
index 00000000000..61f339c1bc2
--- /dev/null
+++ b/intern/ghost/intern/GHOST_ContextSDL.h
@@ -0,0 +1,131 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2014 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Jason Wilkins
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file ghost/intern/GHOST_ContextSDL.h
+ * \ingroup GHOST
+ */
+
+#ifndef __GHOST_CONTEXTSDL_H__
+#define __GHOST_CONTEXTSDL_H__
+
+#include "GHOST_Context.h"
+
+extern "C" {
+ #include "SDL.h"
+}
+
+
+#ifndef GHOST_OPENGL_SDL_CONTEXT_FLAGS
+# ifdef WITH_GPU_DEBUG
+# define GHOST_OPENGL_SDL_CONTEXT_FLAGS SDL_GL_CONTEXT_DEBUG_FLAG
+# else
+# define GHOST_OPENGL_SDL_CONTEXT_FLAGS 0
+# endif
+#endif
+
+#ifndef GHOST_OPENGL_SDL_RESET_NOTIFICATION_STRATEGY
+#define GHOST_OPENGL_SDL_RESET_NOTIFICATION_STRATEGY 0
+#endif
+
+
+class GHOST_ContextSDL : public GHOST_Context
+{
+public:
+ /**
+ * Constructor.
+ */
+ GHOST_ContextSDL(
+ bool stereoVisual,
+ GHOST_TUns16 numOfAASamples,
+ SDL_Window *window,
+ int contextProfileMask,
+ int contextMajorVersion,
+ int contextMinorVersion,
+ int contextFlags,
+ int contextResetNotificationStrategy);
+
+ /**
+ * Destructor.
+ */
+ ~GHOST_ContextSDL();
+
+ /**
+ * Swaps front and back buffers of a window.
+ * \return A boolean success indicator.
+ */
+ GHOST_TSuccess swapBuffers();
+
+ /**
+ * Activates the drawing context of this window.
+ * \return A boolean success indicator.
+ */
+ GHOST_TSuccess activateDrawingContext();
+
+ /**
+ * Call immediately after new to initialize. If this fails then immediately delete the object.
+ * \return Indication as to whether initialization has succeeded.
+ */
+ GHOST_TSuccess initializeDrawingContext();
+
+ /**
+ * Removes references to native handles from this context and then returns
+ * \return GHOST_kSuccess if it is OK for the parent to release the handles and
+ * GHOST_kFailure if releasing the handles will interfere with sharing
+ */
+ GHOST_TSuccess releaseNativeHandles();
+
+ /**
+ * Sets the swap interval for swapBuffers.
+ * \param interval The swap interval to use.
+ * \return A boolean success indicator.
+ */
+ GHOST_TSuccess setSwapInterval(int interval);
+
+ /**
+ * Gets the current swap interval for swapBuffers.
+ * \param intervalOut Variable to store the swap interval if it can be read.
+ * \return Whether the swap interval can be read.
+ */
+ GHOST_TSuccess getSwapInterval(int &intervalOut);
+
+private:
+ SDL_Window *m_window;
+
+ const int m_contextProfileMask;
+ const int m_contextMajorVersion;
+ const int m_contextMinorVersion;
+ const int m_contextFlags;
+ const int m_contextResetNotificationStrategy;
+
+ SDL_GLContext m_context; /* m_sdl_glcontext */
+
+ /** The first created OpenGL context (for sharing display lists) */
+ static SDL_GLContext s_sharedContext;
+ static int s_sharedCount;
+};
+
+#endif // __GHOST_CONTEXTSDL_H__
diff --git a/intern/ghost/intern/GHOST_ContextWGL.cpp b/intern/ghost/intern/GHOST_ContextWGL.cpp
new file mode 100644
index 00000000000..d2a9eed95d9
--- /dev/null
+++ b/intern/ghost/intern/GHOST_ContextWGL.cpp
@@ -0,0 +1,956 @@
+/*
+ * ***** 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): Jason Wilkins
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file ghost/intern/GHOST_ContextWGL.cpp
+ * \ingroup GHOST
+ *
+ * Definition of GHOST_ContextWGL class.
+ */
+
+#include "GHOST_ContextWGL.h"
+
+#include <tchar.h>
+
+#include <cstdio>
+#include <cassert>
+#include <vector>
+
+
+#ifdef WITH_GLEW_MX
+WGLEWContext *wglewContext = NULL;
+#endif
+
+HGLRC GHOST_ContextWGL::s_sharedHGLRC = NULL;
+int GHOST_ContextWGL::s_sharedCount = 0;
+
+bool GHOST_ContextWGL::s_singleContextMode = false;
+bool GHOST_ContextWGL::s_warn_old = false;
+
+
+/* Intel video-cards don't work fine with multiple contexts and
+ * have to share the same context for all windows.
+ * But if we just share context for all windows it could work incorrect
+ * with multiple videocards configuration. Suppose, that Intel videocards
+ * can't be in multiple-devices configuration. */
+static bool is_crappy_intel_card()
+{
+ return strstr((const char *)glGetString(GL_VENDOR), "Intel") != NULL;
+}
+
+
+GHOST_ContextWGL::GHOST_ContextWGL(
+ bool stereoVisual,
+ GHOST_TUns16 numOfAASamples,
+ HWND hWnd,
+ HDC hDC,
+ int contextProfileMask,
+ int contextMajorVersion,
+ int contextMinorVersion,
+ int contextFlags,
+ int contextResetNotificationStrategy)
+ : GHOST_Context(stereoVisual, numOfAASamples),
+ m_hWnd(hWnd),
+ m_hDC(hDC),
+ m_contextProfileMask(contextProfileMask),
+ m_contextMajorVersion(contextMajorVersion),
+ m_contextMinorVersion(contextMinorVersion),
+ m_contextFlags(contextFlags),
+ m_contextResetNotificationStrategy(contextResetNotificationStrategy),
+ m_hGLRC(NULL)
+#ifdef WITH_GLEW_MX
+ ,
+ m_wglewContext(NULL)
+#endif
+#ifndef NDEBUG
+ ,
+ m_dummyVendor(NULL),
+ m_dummyRenderer(NULL),
+ m_dummyVersion(NULL)
+#endif
+{
+ assert(m_hWnd);
+ assert(m_hDC);
+}
+
+
+GHOST_ContextWGL::~GHOST_ContextWGL()
+{
+ if (m_hGLRC != NULL) {
+ if (m_hGLRC == ::wglGetCurrentContext())
+ WIN32_CHK(::wglMakeCurrent(NULL, NULL));
+
+ if (m_hGLRC != s_sharedHGLRC || s_sharedCount == 1) {
+ assert(s_sharedCount > 0);
+
+ s_sharedCount--;
+
+ if (s_sharedCount == 0)
+ s_sharedHGLRC = NULL;
+
+ WIN32_CHK(::wglDeleteContext(m_hGLRC));
+ }
+ }
+
+#ifdef WITH_GLEW_MX
+ delete m_wglewContext;
+#endif
+
+#ifndef NDEBUG
+ free((void*)m_dummyRenderer);
+ free((void*)m_dummyVendor);
+ free((void*)m_dummyVersion);
+#endif
+}
+
+
+GHOST_TSuccess GHOST_ContextWGL::swapBuffers()
+{
+ return WIN32_CHK(::SwapBuffers(m_hDC)) ? GHOST_kSuccess : GHOST_kFailure;
+}
+
+
+GHOST_TSuccess GHOST_ContextWGL::setSwapInterval(int interval)
+{
+ if (WGLEW_EXT_swap_control)
+ return WIN32_CHK(::wglSwapIntervalEXT(interval)) == TRUE ? GHOST_kSuccess : GHOST_kFailure;
+ else
+ return GHOST_kFailure;
+}
+
+
+GHOST_TSuccess GHOST_ContextWGL::getSwapInterval(int &intervalOut)
+{
+ if (WGLEW_EXT_swap_control) {
+ intervalOut = ::wglGetSwapIntervalEXT();
+ return GHOST_kSuccess;
+ }
+ else {
+ return GHOST_kFailure;
+ }
+}
+
+
+GHOST_TSuccess GHOST_ContextWGL::activateDrawingContext()
+{
+ if (WIN32_CHK(::wglMakeCurrent(m_hDC, m_hGLRC))) {
+ activateGLEW();
+ return GHOST_kSuccess;
+ }
+ else {
+ return GHOST_kFailure;
+ }
+}
+
+
+/* Ron Fosner's code for weighting pixel formats and forcing software.
+ * See http://www.opengl.org/resources/faq/technical/weight.cpp
+ */
+static int weight_pixel_format(PIXELFORMATDESCRIPTOR &pfd)
+{
+ int weight = 0;
+
+ /* assume desktop color depth is 32 bits per pixel */
+
+ /* cull unusable pixel formats */
+ /* if no formats can be found, can we determine why it was rejected? */
+ if (!(pfd.dwFlags & PFD_SUPPORT_OPENGL) ||
+ !(pfd.dwFlags & PFD_DRAW_TO_WINDOW) ||
+ !(pfd.dwFlags & PFD_DOUBLEBUFFER) || /* Blender _needs_ this */
+ !(pfd.iPixelType == PFD_TYPE_RGBA) ||
+ (pfd.cDepthBits < 16) ||
+ (pfd.dwFlags & PFD_GENERIC_FORMAT)) /* no software renderers */
+ {
+ return 0;
+ }
+
+ weight = 1; /* it's usable */
+
+ /* the bigger the depth buffer the better */
+ /* give no weight to a 16-bit depth buffer, because those are crap */
+ weight += pfd.cDepthBits - 16;
+
+ weight += pfd.cColorBits - 8;
+
+#ifdef GHOST_OPENGL_ALPHA
+ if (pfd.cAlphaBits > 0)
+ weight++;
+#endif
+
+#ifdef GHOST_OPENGL_STENCIL
+ if (pfd.cStencilBits >= 8)
+ weight++;
+#endif
+
+ /* want swap copy capability -- it matters a lot */
+ if (pfd.dwFlags & PFD_SWAP_COPY)
+ weight += 16;
+
+ return weight;
+}
+
+
+/*
+ * A modification of Ron Fosner's replacement for ChoosePixelFormat
+ * returns 0 on error, else returns the pixel format number to be used
+ */
+static int choose_pixel_format_legacy(HDC hDC, PIXELFORMATDESCRIPTOR &preferredPFD)
+{
+ int iPixelFormat = 0;
+ int weight = 0;
+
+ int iStereoPixelFormat = 0;
+ int stereoWeight = 0;
+
+ /* choose a pixel format using the useless Windows function in case we come up empty handed */
+ int iLastResortPixelFormat = ::ChoosePixelFormat(hDC, &preferredPFD);
+
+ WIN32_CHK(iLastResortPixelFormat != 0);
+
+ int lastPFD = ::DescribePixelFormat(hDC, 1, sizeof(PIXELFORMATDESCRIPTOR), NULL);
+
+ WIN32_CHK(lastPFD != 0);
+
+ for (int i = 1; i <= lastPFD; i++) {
+ PIXELFORMATDESCRIPTOR pfd;
+ int check = ::DescribePixelFormat(hDC, i, sizeof(PIXELFORMATDESCRIPTOR), &pfd);
+
+ WIN32_CHK(check == lastPFD);
+
+ int w = weight_pixel_format(pfd);
+
+ if (w > weight) {
+ weight = w;
+ iPixelFormat = i;
+ }
+
+ if (w > stereoWeight && (preferredPFD.dwFlags & pfd.dwFlags & PFD_STEREO)) {
+ stereoWeight = w;
+ iStereoPixelFormat = i;
+ }
+ }
+
+ /* choose any available stereo format over a non-stereo format */
+ if (iStereoPixelFormat != 0)
+ iPixelFormat = iStereoPixelFormat;
+
+ if (iPixelFormat == 0) {
+ fprintf(stderr, "Warning! Using result of ChoosePixelFormat.\n");
+ iPixelFormat = iLastResortPixelFormat;
+ }
+
+ return iPixelFormat;
+}
+
+
+/*
+ * Clone a window for the purpose of creating a temporary context to initialize WGL extensions.
+ * There is no generic way to clone the lpParam parameter, so the caller is responsible for cloning it themselves.
+ */
+
+static HWND clone_window(HWND hWnd, LPVOID lpParam)
+{
+ int count;
+
+ SetLastError(NO_ERROR);
+
+ DWORD dwExStyle = GetWindowLong(hWnd, GWL_EXSTYLE);
+ WIN32_CHK(GetLastError() == NO_ERROR);
+
+ WCHAR lpClassName[100] = L"";
+ count = GetClassNameW(hWnd, lpClassName, sizeof(lpClassName));
+ WIN32_CHK(count != 0);
+
+ WCHAR lpWindowName[100] = L"";
+ count = GetWindowTextW(hWnd, lpWindowName, sizeof(lpWindowName));
+ WIN32_CHK(count != 0);
+
+ DWORD dwStyle = GetWindowLong(hWnd, GWL_STYLE);
+ WIN32_CHK(GetLastError() == NO_ERROR);
+
+ RECT rect;
+ GetWindowRect(hWnd, &rect);
+ WIN32_CHK(GetLastError() == NO_ERROR);
+
+ HWND hWndParent = (HWND)GetWindowLongPtr(hWnd, GWLP_HWNDPARENT);
+ WIN32_CHK(GetLastError() == NO_ERROR);
+
+ HMENU hMenu = GetMenu(hWnd);
+ WIN32_CHK(GetLastError() == NO_ERROR);
+
+ HINSTANCE hInstance = (HINSTANCE)GetWindowLongPtr(hWnd, GWLP_HINSTANCE);
+ WIN32_CHK(GetLastError() == NO_ERROR);
+
+ HWND hwndCloned = CreateWindowExW(
+ dwExStyle,
+ lpClassName,
+ lpWindowName,
+ dwStyle,
+ rect.left,
+ rect.top,
+ rect.right - rect.left,
+ rect.bottom - rect.top,
+ hWndParent,
+ hMenu,
+ hInstance,
+ lpParam);
+
+ WIN32_CHK(hwndCloned != NULL);
+
+ return hwndCloned;
+}
+
+
+void GHOST_ContextWGL::initContextWGLEW(PIXELFORMATDESCRIPTOR &preferredPFD)
+{
+ HWND dummyHWND = NULL;
+ HDC dummyHDC = NULL;
+ HGLRC dummyHGLRC = NULL;
+
+ HDC prevHDC;
+ HGLRC prevHGLRC;
+
+ int iPixelFormat;
+
+
+#ifdef WITH_GLEW_MX
+ wglewContext = new WGLEWContext;
+ memset(wglewContext, 0, sizeof(WGLEWContext));
+
+ delete m_wglewContext;
+ m_wglewContext = wglewContext;
+#endif
+
+ SetLastError(NO_ERROR);
+
+ prevHDC = ::wglGetCurrentDC();
+ WIN32_CHK(GetLastError() == NO_ERROR);
+
+ prevHGLRC = ::wglGetCurrentContext();
+ WIN32_CHK(GetLastError() == NO_ERROR);
+
+ dummyHWND = clone_window(m_hWnd, NULL);
+
+ if (dummyHWND == NULL)
+ goto finalize;
+
+ dummyHDC = GetDC(dummyHWND);
+
+ if (!WIN32_CHK(dummyHDC != NULL))
+ goto finalize;
+
+ iPixelFormat = choose_pixel_format_legacy(dummyHDC, preferredPFD);
+
+ if (iPixelFormat == 0)
+ goto finalize;
+
+ PIXELFORMATDESCRIPTOR chosenPFD;
+ if (!WIN32_CHK(::DescribePixelFormat(dummyHDC, iPixelFormat, sizeof(PIXELFORMATDESCRIPTOR), &chosenPFD)))
+ goto finalize;
+
+ if (!WIN32_CHK(::SetPixelFormat(dummyHDC, iPixelFormat, &chosenPFD)))
+ goto finalize;
+
+ dummyHGLRC = ::wglCreateContext(dummyHDC);
+
+ if (!WIN32_CHK(dummyHGLRC != NULL))
+ goto finalize;
+
+ if (!WIN32_CHK(::wglMakeCurrent(dummyHDC, dummyHGLRC)))
+ goto finalize;
+
+#ifdef WITH_GLEW_MX
+ if (GLEW_CHK(wglewInit()) != GLEW_OK)
+ fprintf(stderr, "Warning! WGLEW failed to initialize properly.\n");
+#else
+ if (GLEW_CHK(glewInit()) != GLEW_OK)
+ fprintf(stderr, "Warning! Dummy GLEW/WGLEW failed to initialize properly.\n");
+#endif
+
+ // the following are not technially WGLEW, but they also require a context to work
+
+#ifndef NDEBUG
+ free((void*)m_dummyRenderer);
+ free((void*)m_dummyVendor);
+ free((void*)m_dummyVersion);
+
+ m_dummyRenderer = _strdup(reinterpret_cast<const char *>(glGetString(GL_RENDERER)));
+ m_dummyVendor = _strdup(reinterpret_cast<const char *>(glGetString(GL_VENDOR)));
+ m_dummyVersion = _strdup(reinterpret_cast<const char *>(glGetString(GL_VERSION)));
+#endif
+
+ s_singleContextMode = is_crappy_intel_card();
+
+finalize:
+ WIN32_CHK(::wglMakeCurrent(prevHDC, prevHGLRC));
+
+ if (dummyHGLRC != NULL)
+ WIN32_CHK(::wglDeleteContext(dummyHGLRC));
+
+ if (dummyHWND != NULL) {
+ if (dummyHDC != NULL)
+ WIN32_CHK(::ReleaseDC(dummyHWND, dummyHDC));
+
+ WIN32_CHK(::DestroyWindow(dummyHWND));
+ }
+}
+
+
+static void makeAttribList(
+ std::vector<int>& out,
+ bool stereoVisual,
+ int numOfAASamples,
+ int swapMethod,
+ bool needAlpha,
+ bool needStencil,
+ bool sRGB)
+{
+ out.clear();
+ out.reserve(30);
+
+ out.push_back(WGL_SUPPORT_OPENGL_ARB);
+ out.push_back(GL_TRUE);
+
+ out.push_back(WGL_DRAW_TO_WINDOW_ARB);
+ out.push_back(GL_TRUE);
+
+ out.push_back(WGL_DOUBLE_BUFFER_ARB);
+ out.push_back(GL_TRUE);
+
+ out.push_back(WGL_ACCELERATION_ARB);
+ out.push_back(WGL_FULL_ACCELERATION_ARB);
+
+ out.push_back(WGL_SWAP_METHOD_ARB);
+ out.push_back(swapMethod);
+
+ if (stereoVisual) {
+ out.push_back(WGL_STEREO_ARB);
+ out.push_back(GL_TRUE);
+ }
+
+ out.push_back(WGL_PIXEL_TYPE_ARB);
+ out.push_back(WGL_TYPE_RGBA_ARB);
+
+ out.push_back(WGL_COLOR_BITS_ARB);
+ out.push_back(24);
+
+ out.push_back(WGL_DEPTH_BITS_ARB);
+ out.push_back(24);
+
+ if (needAlpha) {
+ out.push_back(WGL_ALPHA_BITS_ARB);
+ out.push_back(8);
+ }
+
+ if (needStencil) {
+ out.push_back(WGL_STENCIL_BITS_ARB);
+ out.push_back(8);
+ }
+
+ if (numOfAASamples > 0) {
+ out.push_back(WGL_SAMPLES_ARB);
+ out.push_back(numOfAASamples);
+
+ out.push_back(WGL_SAMPLE_BUFFERS_ARB);
+ out.push_back(GL_TRUE);
+ }
+
+ if (sRGB) {
+ out.push_back(WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB);
+ out.push_back(GL_TRUE);
+ }
+
+ out.push_back(0);
+}
+
+
+int GHOST_ContextWGL::_choose_pixel_format_arb_2(
+ bool stereoVisual,
+ int *numOfAASamples,
+ bool needAlpha,
+ bool needStencil,
+ bool sRGB,
+ int swapMethod)
+{
+ std::vector<int> iAttributes;
+
+ int iPixelFormat = 0;
+
+ int samples;
+
+ // guard against some insanely high number of samples
+ if (*numOfAASamples > 64) {
+ fprintf(stderr, "Warning! Clamping number of samples to 64.\n");
+ samples = 64;
+ }
+ else {
+ samples = *numOfAASamples;
+ }
+
+ // request a format with as many samples as possible, but not more than requested
+ while (samples >= 0) {
+ makeAttribList(
+ iAttributes,
+ stereoVisual,
+ samples,
+ swapMethod,
+ needAlpha,
+ needStencil,
+ sRGB);
+
+ UINT nNumFormats;
+ WIN32_CHK(wglChoosePixelFormatARB(m_hDC, &(iAttributes[0]), NULL, 1, &iPixelFormat, &nNumFormats));
+
+ /* total number of formats that match (regardless of size of iPixelFormat array)
+ * see: WGL_ARB_pixel_format extension spec */
+ if (nNumFormats > 0)
+ break;
+
+ /* if not reset, then the state of iPixelFormat is undefined after call to wglChoosePixelFormatARB
+ * see: WGL_ARB_pixel_format extension spec */
+ iPixelFormat = 0;
+
+ samples--;
+ }
+
+ // check how many samples were actually gotten
+ if (iPixelFormat != 0) {
+ int iQuery[] = { WGL_SAMPLES_ARB };
+ int actualSamples;
+ wglGetPixelFormatAttribivARB(m_hDC, iPixelFormat, 0, 1, iQuery, &actualSamples);
+
+ if (actualSamples != *numOfAASamples) {
+ fprintf(stderr,
+ "Warning! Unable to find a multisample pixel format that supports exactly %d samples. "
+ "Substituting one that uses %d samples.\n",
+ *numOfAASamples, actualSamples);
+
+ *numOfAASamples = actualSamples; // set context property to actual value
+ }
+ }
+ else {
+ *numOfAASamples = 0;
+ }
+ return iPixelFormat;
+}
+
+
+int GHOST_ContextWGL::_choose_pixel_format_arb_1(bool stereoVisual,
+ int numOfAASamples,
+ bool needAlpha,
+ bool needStencil,
+ bool sRGB,
+ int *swapMethodOut)
+{
+ int iPixelFormat;
+ int copyPixelFormat = 0;
+ int undefPixelFormat = 0;
+ int exchPixelFormat = 0;
+ int copyNumOfAASamples = 0;
+ int undefNumOfAASamples = 0;
+ int exchNumOfAASamples = 0;
+
+ *swapMethodOut = WGL_SWAP_COPY_ARB;
+ copyNumOfAASamples = numOfAASamples;
+ copyPixelFormat = _choose_pixel_format_arb_2(
+ stereoVisual, &copyNumOfAASamples, needAlpha, needStencil, sRGB, *swapMethodOut);
+
+ if (copyPixelFormat == 0 || copyNumOfAASamples < numOfAASamples) {
+ *swapMethodOut = WGL_SWAP_UNDEFINED_ARB;
+ undefNumOfAASamples = numOfAASamples;
+ undefPixelFormat = _choose_pixel_format_arb_2(
+ stereoVisual, &undefNumOfAASamples, needAlpha, needStencil, sRGB, *swapMethodOut);
+
+ if (undefPixelFormat == 0 || undefNumOfAASamples < numOfAASamples) {
+ *swapMethodOut = WGL_SWAP_EXCHANGE_ARB;
+ exchNumOfAASamples = numOfAASamples;
+ exchPixelFormat = _choose_pixel_format_arb_2(
+ stereoVisual, &exchNumOfAASamples, needAlpha, needStencil, sRGB, *swapMethodOut);
+ if (exchPixelFormat == 0 || exchNumOfAASamples < numOfAASamples) {
+ // the number of AA samples cannot be met, take the highest
+ if (undefPixelFormat != 0 && undefNumOfAASamples >= exchNumOfAASamples) {
+ exchNumOfAASamples = undefNumOfAASamples;
+ exchPixelFormat = undefPixelFormat;
+ *swapMethodOut = WGL_SWAP_UNDEFINED_ARB;
+ }
+ if (copyPixelFormat != 0 && copyNumOfAASamples >= exchNumOfAASamples) {
+ exchNumOfAASamples = copyNumOfAASamples;
+ exchPixelFormat = copyPixelFormat;
+ *swapMethodOut = WGL_SWAP_COPY_ARB;
+ }
+ }
+ iPixelFormat = exchPixelFormat;
+ m_numOfAASamples = exchNumOfAASamples;
+ }
+ else {
+ iPixelFormat = undefPixelFormat;
+ m_numOfAASamples = undefNumOfAASamples;
+ }
+ }
+ else {
+ iPixelFormat = copyPixelFormat;
+ m_numOfAASamples = copyNumOfAASamples;
+ }
+ return iPixelFormat;
+}
+
+
+int GHOST_ContextWGL::choose_pixel_format_arb(
+ bool stereoVisual,
+ int numOfAASamples,
+ bool needAlpha,
+ bool needStencil,
+ bool sRGB)
+{
+ int iPixelFormat;
+ int swapMethodOut;
+
+ iPixelFormat = _choose_pixel_format_arb_1(
+ stereoVisual,
+ numOfAASamples,
+ needAlpha,
+ needStencil,
+ sRGB,
+ &swapMethodOut);
+
+ if (iPixelFormat == 0 && stereoVisual) {
+ fprintf(stderr, "Warning! Unable to find a stereo pixel format.\n");
+
+ iPixelFormat = _choose_pixel_format_arb_1(
+ false,
+ numOfAASamples,
+ needAlpha,
+ needStencil,
+ sRGB,
+ &swapMethodOut);
+
+ m_stereoVisual = false; // set context property to actual value
+ }
+
+ if (swapMethodOut != WGL_SWAP_COPY_ARB) {
+ fprintf(stderr,
+ "Warning! Unable to find a pixel format that supports WGL_SWAP_COPY_ARB. "
+ "Substituting one that uses %s.\n",
+ swapMethodOut == WGL_SWAP_UNDEFINED_ARB ? "WGL_SWAP_UNDEFINED_ARB" : "WGL_SWAP_EXCHANGE_ARB");
+ }
+
+ return iPixelFormat;
+}
+
+
+int GHOST_ContextWGL::choose_pixel_format(
+ bool stereoVisual,
+ int numOfAASamples,
+ bool needAlpha,
+ bool needStencil,
+ bool sRGB)
+{
+ PIXELFORMATDESCRIPTOR preferredPFD = {
+ sizeof(PIXELFORMATDESCRIPTOR), /* size */
+ 1, /* version */
+ PFD_SUPPORT_OPENGL |
+ PFD_DRAW_TO_WINDOW |
+ PFD_SWAP_COPY | /* support swap copy */
+ PFD_DOUBLEBUFFER | /* support double-buffering */
+ (stereoVisual ? PFD_STEREO : 0), /* support stereo */
+ PFD_TYPE_RGBA, /* color type */
+ 24, /* preferred color depth */
+ 0, 0, 0, 0, 0, 0, /* color bits (ignored) */
+ needAlpha ? 8 : 0, /* alpha buffer */
+ 0, /* alpha shift (ignored) */
+ 0, /* no accumulation buffer */
+ 0, 0, 0, 0, /* accum bits (ignored) */
+ 24, /* depth buffer */
+ needStencil ? 8 : 0, /* stencil buffer */
+ 0, /* no auxiliary buffers */
+ PFD_MAIN_PLANE, /* main layer */
+ 0, /* reserved */
+ 0, 0, 0 /* layer, visible, and damage masks (ignored) */
+ };
+
+ initContextWGLEW(preferredPFD);
+
+ if (numOfAASamples > 0 && !WGLEW_ARB_multisample) {
+ fprintf(stderr, "Warning! Unable to request a multisample framebuffer.\n");
+ numOfAASamples = 0;
+ }
+
+ if (sRGB && !(WGLEW_ARB_framebuffer_sRGB || WGLEW_EXT_framebuffer_sRGB)) {
+ fprintf(stderr, "Warning! Unable to request an sRGB framebuffer.\n");
+ sRGB = false;
+ }
+
+ int iPixelFormat = 0;
+
+ if (WGLEW_ARB_pixel_format)
+ iPixelFormat = choose_pixel_format_arb(stereoVisual, numOfAASamples, needAlpha, needStencil, sRGB);
+
+ if (iPixelFormat == 0)
+ iPixelFormat = choose_pixel_format_legacy(m_hDC, preferredPFD);
+
+ return iPixelFormat;
+}
+
+
+#ifndef NDEBUG
+static void reportContextString(const char *name, const char *dummy, const char *context)
+{
+ fprintf(stderr, "%s: %s\n", name, context);
+
+ if (strcmp(dummy, context) != 0)
+ fprintf(stderr, "Warning! Dummy %s: %s\n", name, dummy);
+}
+#endif
+
+
+GHOST_TSuccess GHOST_ContextWGL::initializeDrawingContext()
+{
+#ifdef GHOST_OPENGL_ALPHA
+ const bool needAlpha = true;
+#else
+ const bool needAlpha = false;
+#endif
+
+#ifdef GHOST_OPENGL_STENCIL
+ const bool needStencil = true;
+#else
+ const bool needStencil = false;
+#endif
+
+#ifdef GHOST_OPENGL_SRGB
+ const bool sRGB = true;
+#else
+ const bool sRGB = false;
+#endif
+
+ HGLRC prevHGLRC;
+ HDC prevHDC;
+
+ int iPixelFormat;
+ int lastPFD;
+
+ PIXELFORMATDESCRIPTOR chosenPFD;
+
+
+ SetLastError(NO_ERROR);
+
+ prevHGLRC = ::wglGetCurrentContext();
+ WIN32_CHK(GetLastError() == NO_ERROR);
+
+ prevHDC = ::wglGetCurrentDC();
+ WIN32_CHK(GetLastError() == NO_ERROR);
+
+ iPixelFormat = choose_pixel_format(m_stereoVisual, m_numOfAASamples, needAlpha, needStencil, sRGB);
+
+ if (iPixelFormat == 0) {
+ ::wglMakeCurrent(prevHDC, prevHGLRC);
+ return GHOST_kFailure;
+ }
+
+ lastPFD = ::DescribePixelFormat(m_hDC, iPixelFormat, sizeof(PIXELFORMATDESCRIPTOR), &chosenPFD);
+
+ if (!WIN32_CHK(lastPFD != 0)) {
+ ::wglMakeCurrent(prevHDC, prevHGLRC);
+ return GHOST_kFailure;
+ }
+
+ if (needAlpha && chosenPFD.cAlphaBits == 0)
+ fprintf(stderr, "Warning! Unable to find a pixel format with an alpha channel.\n");
+
+ if (needStencil && chosenPFD.cStencilBits == 0)
+ fprintf(stderr, "Warning! Unable to find a pixel format with a stencil buffer.\n");
+
+ if (!WIN32_CHK(::SetPixelFormat(m_hDC, iPixelFormat, &chosenPFD))) {
+ ::wglMakeCurrent(prevHDC, prevHGLRC);
+ return GHOST_kFailure;
+ }
+
+ activateWGLEW();
+
+ if (WGLEW_ARB_create_context) {
+ int profileBitCore = m_contextProfileMask & WGL_CONTEXT_CORE_PROFILE_BIT_ARB;
+ int profileBitCompat = m_contextProfileMask & WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB;
+
+#ifdef WITH_GLEW_ES
+ int profileBitES = m_contextProfileMask & WGL_CONTEXT_ES_PROFILE_BIT_EXT;
+#endif
+
+ if (!WGLEW_ARB_create_context_profile && profileBitCore)
+ fprintf(stderr, "Warning! OpenGL core profile not available.\n");
+
+ if (!WGLEW_ARB_create_context_profile && profileBitCompat)
+ fprintf(stderr, "Warning! OpenGL compatibility profile not available.\n");
+
+#ifdef WITH_GLEW_ES
+ if (!WGLEW_EXT_create_context_es_profile && profileBitES && m_contextMajorVersion == 1)
+ fprintf(stderr, "Warning! OpenGL ES profile not available.\n");
+
+ if (!WGLEW_EXT_create_context_es2_profile && profileBitES && m_contextMajorVersion == 2)
+ fprintf(stderr, "Warning! OpenGL ES2 profile not available.\n");
+#endif
+
+ int profileMask = 0;
+
+ if (WGLEW_ARB_create_context_profile && profileBitCore)
+ profileMask |= profileBitCore;
+
+ if (WGLEW_ARB_create_context_profile && profileBitCompat)
+ profileMask |= profileBitCompat;
+
+#ifdef WITH_GLEW_ES
+ if (WGLEW_EXT_create_context_es_profile && profileBitES)
+ profileMask |= profileBitES;
+#endif
+
+ if (profileMask != m_contextProfileMask)
+ fprintf(stderr, "Warning! Ignoring untested OpenGL context profile mask bits.");
+
+ std::vector<int> iAttributes;
+
+ if (profileMask) {
+ iAttributes.push_back(WGL_CONTEXT_PROFILE_MASK_ARB);
+ iAttributes.push_back(profileMask);
+ }
+
+ if (m_contextMajorVersion != 0) {
+ iAttributes.push_back(WGL_CONTEXT_MAJOR_VERSION_ARB);
+ iAttributes.push_back(m_contextMajorVersion);
+ }
+
+ if (m_contextMinorVersion != 0) {
+ iAttributes.push_back(WGL_CONTEXT_MINOR_VERSION_ARB);
+ iAttributes.push_back(m_contextMinorVersion);
+ }
+
+ if (m_contextFlags != 0) {
+ iAttributes.push_back(WGL_CONTEXT_FLAGS_ARB);
+ iAttributes.push_back(m_contextFlags);
+ }
+
+ if (m_contextResetNotificationStrategy != 0) {
+ if (WGLEW_ARB_create_context_robustness) {
+ iAttributes.push_back(WGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB);
+ iAttributes.push_back(m_contextResetNotificationStrategy);
+ }
+ else {
+ fprintf(stderr, "Warning! Cannot set the reset notification strategy.");
+ }
+ }
+
+ iAttributes.push_back(0);
+
+ if (!s_singleContextMode || s_sharedHGLRC == NULL)
+ m_hGLRC = ::wglCreateContextAttribsARB(m_hDC, NULL, &(iAttributes[0]));
+ else
+ m_hGLRC = s_sharedHGLRC;
+ }
+ else {
+ if (m_contextProfileMask != 0)
+ fprintf(stderr, "Warning! Legacy WGL is unable to select between OpenGL profiles.");
+
+ if (m_contextMajorVersion != 0 || m_contextMinorVersion != 0)
+ fprintf(stderr, "Warning! Legacy WGL is unable to select between OpenGL versions.");
+
+ if (m_contextFlags != 0)
+ fprintf(stderr, "Warning! Legacy WGL is unable to set context flags.");
+
+ if (!s_singleContextMode || s_sharedHGLRC == NULL)
+ m_hGLRC = ::wglCreateContext(m_hDC);
+ else
+ m_hGLRC = s_sharedHGLRC;
+ }
+
+ if (!WIN32_CHK(m_hGLRC != NULL)) {
+ ::wglMakeCurrent(prevHDC, prevHGLRC);
+ return GHOST_kFailure;
+ }
+
+ if (s_sharedHGLRC == NULL)
+ s_sharedHGLRC = m_hGLRC;
+
+ s_sharedCount++;
+
+ if (!s_singleContextMode && s_sharedHGLRC != m_hGLRC && !WIN32_CHK(::wglShareLists(s_sharedHGLRC, m_hGLRC))) {
+ ::wglMakeCurrent(prevHDC, prevHGLRC);
+ return GHOST_kFailure;
+ }
+
+ if (!WIN32_CHK(::wglMakeCurrent(m_hDC, m_hGLRC))) {
+ ::wglMakeCurrent(prevHDC, prevHGLRC);
+ return GHOST_kFailure;
+ }
+
+ initContextGLEW();
+
+ initClearGL();
+ ::SwapBuffers(m_hDC);
+
+ const char *vendor = reinterpret_cast<const char*>(glGetString(GL_VENDOR));
+ const char *renderer = reinterpret_cast<const char*>(glGetString(GL_RENDERER));
+ const char *version = reinterpret_cast<const char*>(glGetString(GL_VERSION));
+
+#ifndef NDEBUG
+ reportContextString("Vendor", m_dummyVendor, vendor);
+ reportContextString("Renderer", m_dummyRenderer, renderer);
+ reportContextString("Version", m_dummyVersion, version);
+#endif
+
+ if (!s_warn_old) {
+ if ((strcmp(vendor, "Microsoft Corporation") == 0 ||
+ strcmp(renderer, "GDI Generic") == 0) && version[0] == '1' && version[2] == '1')
+ {
+ MessageBox(m_hWnd, "Your system does not use 3D hardware acceleration.\n"
+ "Such systems can cause stability problems in Blender and they are unsupported.\n\n"
+ "This may be caused by:\n"
+ "* A missing or faulty graphics driver installation.\n"
+ " Blender needs a graphics card driver to work correctly.\n"
+ "* Accessing Blender through a remote connection.\n"
+ "* Using Blender through a virtual machine.\n\n"
+ "Disable this message in <User Preferences - Interface - Warn On Deprecated OpenGL>",
+ "Blender - Can't detect 3D hardware accelerated Driver!", MB_OK | MB_ICONWARNING);
+ }
+ else if (version[0] == '1' && version[2] < '4') {
+ MessageBox(m_hWnd, "The OpenGL version provided by your graphics driver version is too low\n"
+ "Blender requires version 1.4 and may not work correctly\n\n"
+ "Disable this message in <User Preferences - Interface - Warn On Deprecated OpenGL>",
+ "Blender - Unsupported Graphics Driver!", MB_OK | MB_ICONWARNING);
+ }
+ s_warn_old = true;
+ }
+
+ return GHOST_kSuccess;
+}
+
+
+GHOST_TSuccess GHOST_ContextWGL::releaseNativeHandles()
+{
+ GHOST_TSuccess success = m_hGLRC != s_sharedHGLRC || s_sharedCount == 1 ? GHOST_kSuccess : GHOST_kFailure;
+
+ m_hWnd = NULL;
+ m_hDC = NULL;
+
+ return success;
+}
diff --git a/intern/ghost/intern/GHOST_ContextWGL.h b/intern/ghost/intern/GHOST_ContextWGL.h
new file mode 100644
index 00000000000..c457ddab2f7
--- /dev/null
+++ b/intern/ghost/intern/GHOST_ContextWGL.h
@@ -0,0 +1,190 @@
+/*
+ * ***** 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): Jason Wilkins
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file ghost/intern/GHOST_ContextWGL.h
+ * \ingroup GHOST
+ */
+
+#ifndef __GHOST_CONTEXTWGL_H__
+#define __GHOST_CONTEXTWGL_H__
+
+#include "GHOST_Context.h"
+
+#ifdef WITH_GLEW_MX
+#define wglewGetContext() wglewContext
+#endif
+
+#include <GL/wglew.h>
+
+#ifdef WITH_GLEW_MX
+extern "C" WGLEWContext *wglewContext;
+#endif
+
+#ifndef GHOST_OPENGL_WGL_CONTEXT_FLAGS
+# ifdef WITH_GPU_DEBUG
+# define GHOST_OPENGL_WGL_CONTEXT_FLAGS WGL_CONTEXT_DEBUG_BIT_ARB
+# else
+# define GHOST_OPENGL_WGL_CONTEXT_FLAGS 0
+# endif
+#endif
+
+#ifndef GHOST_OPENGL_WGL_RESET_NOTIFICATION_STRATEGY
+#define GHOST_OPENGL_WGL_RESET_NOTIFICATION_STRATEGY 0
+#endif
+
+
+class GHOST_ContextWGL : public GHOST_Context
+{
+public:
+ /**
+ * Constructor.
+ */
+ GHOST_ContextWGL(
+ bool stereoVisual,
+ GHOST_TUns16 numOfAASamples,
+ HWND hWnd,
+ HDC hDC,
+ int contextProfileMask,
+ int contextMajorVersion,
+ int contextMinorVersion,
+ int contextFlags,
+ int contextResetNotificationStrategy);
+
+ /**
+ * Destructor.
+ */
+ ~GHOST_ContextWGL();
+
+ /**
+ * Swaps front and back buffers of a window.
+ * \return A boolean success indicator.
+ */
+ GHOST_TSuccess swapBuffers();
+
+ /**
+ * Activates the drawing context of this window.
+ * \return A boolean success indicator.
+ */
+ GHOST_TSuccess activateDrawingContext();
+
+ /**
+ * Call immediately after new to initialize. If this fails then immediately delete the object.
+ * \return Indication as to whether initialization has succeeded.
+ */
+ GHOST_TSuccess initializeDrawingContext();
+
+ /**
+ * Removes references to native handles from this context and then returns
+ * \return GHOST_kSuccess if it is OK for the parent to release the handles and
+ * GHOST_kFailure if releasing the handles will interfere with sharing
+ */
+ GHOST_TSuccess releaseNativeHandles();
+
+ /**
+ * Sets the swap interval for swapBuffers.
+ * \param interval The swap interval to use.
+ * \return A boolean success indicator.
+ */
+ GHOST_TSuccess setSwapInterval(int interval);
+
+ /**
+ * Gets the current swap interval for swapBuffers.
+ * \param intervalOut Variable to store the swap interval if it can be read.
+ * \return Whether the swap interval can be read.
+ */
+ GHOST_TSuccess getSwapInterval(int &intervalOut);
+
+ static void unSetWarningOld(){s_warn_old = true;}
+
+protected:
+ inline void activateWGLEW() const {
+#ifdef WITH_GLEW_MX
+ wglewContext = m_wglewContext;
+#endif
+ }
+
+private:
+ int choose_pixel_format(
+ bool stereoVisual,
+ int numOfAASamples,
+ bool needAlpha,
+ bool needStencil,
+ bool sRGB);
+
+ int choose_pixel_format_arb(
+ bool stereoVisual,
+ int numOfAASamples,
+ bool needAlpha,
+ bool needStencil,
+ bool sRGB);
+
+ int _choose_pixel_format_arb_1(
+ bool stereoVisual,
+ int numOfAASamples,
+ bool needAlpha,
+ bool needStencil,
+ bool sRGB,
+ int *swapMethodOut);
+
+ int _choose_pixel_format_arb_2(bool stereoVisual,
+ int *numOfAASamples,
+ bool needAlpha,
+ bool needStencil,
+ bool sRGB,
+ int swapMethod);
+
+ void initContextWGLEW(PIXELFORMATDESCRIPTOR &preferredPFD);
+
+ HWND m_hWnd;
+ HDC m_hDC;
+
+ const int m_contextProfileMask;
+ const int m_contextMajorVersion;
+ const int m_contextMinorVersion;
+ const int m_contextFlags;
+ const int m_contextResetNotificationStrategy;
+
+ HGLRC m_hGLRC;
+
+#ifdef WITH_GLEW_MX
+ WGLEWContext *m_wglewContext;
+#endif
+
+#ifndef NDEBUG
+ const char *m_dummyVendor;
+ const char *m_dummyRenderer;
+ const char *m_dummyVersion;
+#endif
+
+ static HGLRC s_sharedHGLRC;
+ static int s_sharedCount;
+
+ static bool s_singleContextMode;
+ static bool s_warn_old;
+};
+
+#endif // __GHOST_CONTEXTWGL_H__
diff --git a/intern/ghost/intern/GHOST_Debug.h b/intern/ghost/intern/GHOST_Debug.h
index 9292235a9c7..db49627b378 100644
--- a/intern/ghost/intern/GHOST_Debug.h
+++ b/intern/ghost/intern/GHOST_Debug.h
@@ -80,7 +80,7 @@
} \
} (void)0
#else // GHOST_DEBUG
-# define GHOST_ASSERT(x, info)
+# define GHOST_ASSERT(x, info) ((void)0)
#endif // GHOST_DEBUG
#endif // __GHOST_DEBUG_H__
diff --git a/intern/ghost/intern/GHOST_DisplayManagerCocoa.h b/intern/ghost/intern/GHOST_DisplayManagerCocoa.h
index 1f17b4dd976..f580820d8f6 100644
--- a/intern/ghost/intern/GHOST_DisplayManagerCocoa.h
+++ b/intern/ghost/intern/GHOST_DisplayManagerCocoa.h
@@ -58,15 +58,15 @@ public:
* \param numDisplays The number of displays on this system.
* \return Indication of success.
*/
- virtual GHOST_TSuccess getNumDisplays(GHOST_TUns8& numDisplays) const;
+ GHOST_TSuccess getNumDisplays(GHOST_TUns8& numDisplays) const;
/**
* Returns the number of display settings for this display device.
* \param display The index of the display to query with 0 <= display < getNumDisplays().
- * \param setting The number of settings of the display device with this index.
+ * \param numSetting: The number of settings of the display device with this index.
* \return Indication of success.
*/
- virtual GHOST_TSuccess getNumDisplaySettings(GHOST_TUns8 display, GHOST_TInt32& numSettings) const;
+ GHOST_TSuccess getNumDisplaySettings(GHOST_TUns8 display, GHOST_TInt32& numSettings) const;
/**
* Returns the current setting for this display device.
@@ -75,7 +75,7 @@ public:
* \param setting The setting of the display device with this index.
* \return Indication of success.
*/
- virtual GHOST_TSuccess getDisplaySetting(GHOST_TUns8 display, GHOST_TInt32 index, GHOST_DisplaySetting& setting) const;
+ GHOST_TSuccess getDisplaySetting(GHOST_TUns8 display, GHOST_TInt32 index, GHOST_DisplaySetting& setting) const;
/**
* Returns the current setting for this display device.
@@ -83,7 +83,7 @@ public:
* \param setting The current setting of the display device with this index.
* \return Indication of success.
*/
- virtual GHOST_TSuccess getCurrentDisplaySetting(GHOST_TUns8 display, GHOST_DisplaySetting& setting) const;
+ GHOST_TSuccess getCurrentDisplaySetting(GHOST_TUns8 display, GHOST_DisplaySetting& setting) const;
/**
* Changes the current setting for this display device.
@@ -91,7 +91,7 @@ public:
* \param setting The current setting of the display device with this index.
* \return Indication of success.
*/
- virtual GHOST_TSuccess setCurrentDisplaySetting(GHOST_TUns8 display, const GHOST_DisplaySetting& setting);
+ GHOST_TSuccess setCurrentDisplaySetting(GHOST_TUns8 display, const GHOST_DisplaySetting& setting);
protected:
//Do not cache values as OS X supports screen hot plug
diff --git a/intern/ghost/intern/GHOST_DisplayManagerWin32.h b/intern/ghost/intern/GHOST_DisplayManagerWin32.h
index ced4ceac044..ff8849f03c9 100644
--- a/intern/ghost/intern/GHOST_DisplayManagerWin32.h
+++ b/intern/ghost/intern/GHOST_DisplayManagerWin32.h
@@ -58,15 +58,15 @@ public:
* \param numDisplays The number of displays on this system.
* \return Indication of success.
*/
- virtual GHOST_TSuccess getNumDisplays(GHOST_TUns8& numDisplays) const;
+ GHOST_TSuccess getNumDisplays(GHOST_TUns8& numDisplays) const;
/**
* Returns the number of display settings for this display device.
* \param display The index of the display to query with 0 <= display < getNumDisplays().
- * \param setting The number of settings of the display device with this index.
+ * \param numSetting: The number of settings of the display device with this index.
* \return Indication of success.
*/
- virtual GHOST_TSuccess getNumDisplaySettings(GHOST_TUns8 display, GHOST_TInt32& numSettings) const;
+ GHOST_TSuccess getNumDisplaySettings(GHOST_TUns8 display, GHOST_TInt32& numSettings) const;
/**
* Returns the current setting for this display device.
@@ -75,7 +75,7 @@ public:
* \param setting The setting of the display device with this index.
* \return Indication of success.
*/
- virtual GHOST_TSuccess getDisplaySetting(GHOST_TUns8 display, GHOST_TInt32 index, GHOST_DisplaySetting& setting) const;
+ GHOST_TSuccess getDisplaySetting(GHOST_TUns8 display, GHOST_TInt32 index, GHOST_DisplaySetting& setting) const;
/**
* Returns the current setting for this display device.
@@ -83,7 +83,7 @@ public:
* \param setting The current setting of the display device with this index.
* \return Indication of success.
*/
- virtual GHOST_TSuccess getCurrentDisplaySetting(GHOST_TUns8 display, GHOST_DisplaySetting& setting) const;
+ GHOST_TSuccess getCurrentDisplaySetting(GHOST_TUns8 display, GHOST_DisplaySetting& setting) const;
/**
* Changes the current setting for this display device.
@@ -91,7 +91,7 @@ public:
* \param setting The current setting of the display device with this index.
* \return Indication of success.
*/
- virtual GHOST_TSuccess setCurrentDisplaySetting(GHOST_TUns8 display, const GHOST_DisplaySetting& setting);
+ GHOST_TSuccess setCurrentDisplaySetting(GHOST_TUns8 display, const GHOST_DisplaySetting& setting);
protected:
};
diff --git a/intern/ghost/intern/GHOST_DisplayManagerX11.cpp b/intern/ghost/intern/GHOST_DisplayManagerX11.cpp
index 24289e6b006..b3e6f2e53fa 100644
--- a/intern/ghost/intern/GHOST_DisplayManagerX11.cpp
+++ b/intern/ghost/intern/GHOST_DisplayManagerX11.cpp
@@ -90,6 +90,7 @@ getNumDisplaySettings(
numSettings = 1;
#endif
+ (void) display;
return GHOST_kSuccess;
}
@@ -116,6 +117,8 @@ getDisplaySetting(
if (dpy == NULL)
return GHOST_kFailure;
+ (void)display;
+
#ifdef WITH_X11_XF86VMODE
int majorVersion, minorVersion;
@@ -146,6 +149,7 @@ getDisplaySetting(
GHOST_ASSERT(display < 1, "Only single display systems are currently supported.\n");
GHOST_ASSERT(index < 1, "Requested setting outside of valid range.\n");
+ (void)index;
setting.xPixels = DisplayWidth(dpy, DefaultScreen(dpy));
setting.yPixels = DisplayHeight(dpy, DefaultScreen(dpy));
@@ -171,7 +175,7 @@ getCurrentDisplaySetting(
GHOST_TSuccess
GHOST_DisplayManagerX11::
setCurrentDisplaySetting(
- GHOST_TUns8 display,
+ GHOST_TUns8 /*display*/,
const GHOST_DisplaySetting& setting)
{
#ifdef WITH_X11_XF86VMODE
@@ -264,6 +268,8 @@ setCurrentDisplaySetting(
return GHOST_kSuccess;
#else
+ (void)setting;
+
/* Just pretend the request was successful. */
return GHOST_kSuccess;
#endif
diff --git a/intern/ghost/intern/GHOST_DisplayManagerX11.h b/intern/ghost/intern/GHOST_DisplayManagerX11.h
index 66fd1e5c15e..b54c53c67bd 100644
--- a/intern/ghost/intern/GHOST_DisplayManagerX11.h
+++ b/intern/ghost/intern/GHOST_DisplayManagerX11.h
@@ -66,7 +66,7 @@ public:
/**
* Returns the number of display settings for this display device.
* \param display The index of the display to query with 0 <= display < getNumDisplays().
- * \param setting The number of settings of the display device with this index.
+ * \param numSetting: The number of settings of the display device with this index.
* \return Indication of success.
*/
GHOST_TSuccess
diff --git a/intern/ghost/intern/GHOST_DropTargetWin32.h b/intern/ghost/intern/GHOST_DropTargetWin32.h
index fb85feffde0..56bae1fd1b2 100644
--- a/intern/ghost/intern/GHOST_DropTargetWin32.h
+++ b/intern/ghost/intern/GHOST_DropTargetWin32.h
@@ -89,7 +89,7 @@ public:
* Destructor
* Do NOT destroy directly. Use Release() instead to make COM happy.
*/
- virtual ~GHOST_DropTargetWin32();
+ ~GHOST_DropTargetWin32();
private:
diff --git a/intern/ghost/intern/GHOST_DropTargetX11.cpp b/intern/ghost/intern/GHOST_DropTargetX11.cpp
index 639fd503759..0efc8a78df5 100644
--- a/intern/ghost/intern/GHOST_DropTargetX11.cpp
+++ b/intern/ghost/intern/GHOST_DropTargetX11.cpp
@@ -132,7 +132,8 @@ void GHOST_DropTargetX11::UrlDecode(char *decodedOut, int bufferSize, const char
unsigned int i;
unsigned int len = strlen(encodedIn);
DecodeState_e state = STATE_SEARCH;
- int j, asciiCharacter;
+ int j;
+ unsigned int asciiCharacter;
char tempNumBuf[3] = {0};
bool bothDigits = true;
diff --git a/intern/ghost/intern/GHOST_Event.h b/intern/ghost/intern/GHOST_Event.h
index ea4d603be83..6a715498b87 100644
--- a/intern/ghost/intern/GHOST_Event.h
+++ b/intern/ghost/intern/GHOST_Event.h
@@ -59,7 +59,7 @@ public:
* Returns the event type.
* \return The event type.
*/
- virtual GHOST_TEventType getType()
+ GHOST_TEventType getType()
{
return m_type;
}
@@ -68,7 +68,7 @@ public:
* Returns the time this event was generated.
* \return The event generation time.
*/
- virtual GHOST_TUns64 getTime()
+ GHOST_TUns64 getTime()
{
return m_time;
}
@@ -78,7 +78,7 @@ public:
* or NULL if it is a 'system' event.
* \return The generating window.
*/
- virtual GHOST_IWindow *getWindow()
+ GHOST_IWindow *getWindow()
{
return m_window;
}
@@ -87,7 +87,7 @@ public:
* Returns the event data.
* \return The event data.
*/
- virtual GHOST_TEventDataPtr getData()
+ GHOST_TEventDataPtr getData()
{
return m_data;
}
diff --git a/intern/ghost/intern/GHOST_EventButton.h b/intern/ghost/intern/GHOST_EventButton.h
index f88fe6e201d..ef5c5efa202 100644
--- a/intern/ghost/intern/GHOST_EventButton.h
+++ b/intern/ghost/intern/GHOST_EventButton.h
@@ -47,9 +47,8 @@ public:
* Constructor.
* \param time The time this event was generated.
* \param type The type of this event.
- * \param x The x-coordinate of the location the cursor was at at the time of the event.
- * \param y The y-coordinate of the location the cursor was at at the time of the event.
- * \param buttons The state of the buttons was at at the time of the event.
+ * \param window: The window of this event.
+ * \param button: The state of the buttons were at at the time of the event.
*/
GHOST_EventButton(GHOST_TUns64 time, GHOST_TEventType type, GHOST_IWindow *window, GHOST_TButtonMask button)
: GHOST_Event(time, type, window)
diff --git a/intern/ghost/intern/GHOST_EventDragnDrop.h b/intern/ghost/intern/GHOST_EventDragnDrop.h
index c51f9568087..b7bf37c99d8 100644
--- a/intern/ghost/intern/GHOST_EventDragnDrop.h
+++ b/intern/ghost/intern/GHOST_EventDragnDrop.h
@@ -112,6 +112,7 @@ public:
for (i = 0; i < strArray->count; i++)
free(strArray->strings[i]);
+ free(strArray->strings);
free(strArray);
}
break;
diff --git a/intern/ghost/intern/GHOST_EventManager.h b/intern/ghost/intern/GHOST_EventManager.h
index 8e513b4ee76..c8b5d1debe5 100644
--- a/intern/ghost/intern/GHOST_EventManager.h
+++ b/intern/ghost/intern/GHOST_EventManager.h
@@ -58,27 +58,27 @@ public:
/**
* Destructor.
*/
- virtual ~GHOST_EventManager();
+ ~GHOST_EventManager();
/**
* Returns the number of events currently on the stack.
* \return The number of events on the stack.
*/
- virtual GHOST_TUns32 getNumEvents();
+ GHOST_TUns32 getNumEvents();
/**
* Returns the number of events of a certain type currently on the stack.
* \param type The type of events to be counted.
* \return The number of events on the stack of this type.
*/
- virtual GHOST_TUns32 getNumEvents(GHOST_TEventType type);
+ GHOST_TUns32 getNumEvents(GHOST_TEventType type);
/**
* Return the event at the top of the stack without removal.
* Do not delete the event!
* \return The event at the top of the stack.
*/
- virtual GHOST_IEvent *peekEvent();
+ GHOST_IEvent *peekEvent();
/**
* Pushes an event on the stack.
@@ -86,47 +86,47 @@ public:
* Do not delete the event!
* \param event The event to push on the stack.
*/
- virtual GHOST_TSuccess pushEvent(GHOST_IEvent *event);
+ GHOST_TSuccess pushEvent(GHOST_IEvent *event);
/**
* Dispatches the given event directly, bypassing the event stack.
* \return Indication as to whether any of the consumers handled the event.
*/
- virtual bool dispatchEvent(GHOST_IEvent *event);
+ bool dispatchEvent(GHOST_IEvent *event);
/**
* Dispatches the event at the back of the stack.
* The event will be removed from the stack.
* \return Indication as to whether any of the consumers handled the event.
*/
- virtual bool dispatchEvent();
+ bool dispatchEvent();
/**
* Dispatches all the events on the stack.
* The event stack will be empty afterwards.
* \return Indication as to whether any of the consumers handled the events.
*/
- virtual bool dispatchEvents();
+ bool dispatchEvents();
/**
* Adds a consumer to the list of event consumers.
* \param consumer The consumer added to the list.
* \return Indication as to whether addition has succeeded.
*/
- virtual GHOST_TSuccess addConsumer(GHOST_IEventConsumer *consumer);
+ GHOST_TSuccess addConsumer(GHOST_IEventConsumer *consumer);
/**
* Removes a consumer from the list of event consumers.
* \param consumer The consumer removed from the list.
* \return Indication as to whether removal has succeeded.
*/
- virtual GHOST_TSuccess removeConsumer(GHOST_IEventConsumer *consumer);
+ GHOST_TSuccess removeConsumer(GHOST_IEventConsumer *consumer);
/**
* Removes all events for a window from the stack.
* \param window The window to remove events for.
*/
- virtual void
+ void
removeWindowEvents(
GHOST_IWindow *window
);
@@ -138,7 +138,7 @@ public:
* \param type The type of events to be removed.
* \param window The window to remove the events for.
*/
- virtual void
+ void
removeTypeEvents(
GHOST_TEventType type,
GHOST_IWindow *window = NULL
@@ -150,12 +150,12 @@ protected:
* Delete the event after use!
* \return The event at the top of the stack.
*/
- virtual GHOST_IEvent *popEvent();
+ GHOST_IEvent *popEvent();
/**
* Removes all events from the stack.
*/
- virtual void disposeEvents();
+ void disposeEvents();
/** A stack with events. */
typedef std::deque<GHOST_IEvent *> TEventStack;
diff --git a/intern/ghost/intern/GHOST_EventPrinter.cpp b/intern/ghost/intern/GHOST_EventPrinter.cpp
index 4b7be84ac81..f25f6637cb1 100644
--- a/intern/ghost/intern/GHOST_EventPrinter.cpp
+++ b/intern/ghost/intern/GHOST_EventPrinter.cpp
@@ -179,6 +179,9 @@ bool GHOST_EventPrinter::processEvent(GHOST_IEvent *event)
std::cout << "not found"; handled = false;
break;
}
+
+ std::cout.flush();
+
return handled;
}
diff --git a/intern/ghost/intern/GHOST_EventPrinter.h b/intern/ghost/intern/GHOST_EventPrinter.h
index 280d4208413..0cbb7ca467d 100644
--- a/intern/ghost/intern/GHOST_EventPrinter.h
+++ b/intern/ghost/intern/GHOST_EventPrinter.h
@@ -49,7 +49,7 @@ public:
* \param event The event that can be handled or not.
* \return Indication as to whether the event was handled.
*/
- virtual bool processEvent(GHOST_IEvent *event);
+ bool processEvent(GHOST_IEvent *event);
protected:
/**
diff --git a/intern/ghost/intern/GHOST_EventTrackpad.h b/intern/ghost/intern/GHOST_EventTrackpad.h
index dc8b1649754..b4e80b5fd06 100644
--- a/intern/ghost/intern/GHOST_EventTrackpad.h
+++ b/intern/ghost/intern/GHOST_EventTrackpad.h
@@ -45,7 +45,7 @@ public:
/**
* Constructor.
* \param msec The time this event was generated.
- * \param type The type of this event.
+ * \param window: The window of this event.
* \param subtype The subtype of the event.
* \param x The x-delta of the pan event.
* \param y The y-delta of the pan event.
diff --git a/intern/ghost/intern/GHOST_EventWheel.h b/intern/ghost/intern/GHOST_EventWheel.h
index 216f13fda4e..a632492acb9 100644
--- a/intern/ghost/intern/GHOST_EventWheel.h
+++ b/intern/ghost/intern/GHOST_EventWheel.h
@@ -47,9 +47,9 @@ class GHOST_EventWheel : public GHOST_Event
public:
/**
* Constructor.
- * \param msec The time this event was generated.
- * \param type The type of this event.
- * \param z The displacement of the mouse wheel.
+ * \param msec: The time this event was generated.
+ * \param window: The window of this event.
+ * \param z: The displacement of the mouse wheel.
*/
GHOST_EventWheel(GHOST_TUns64 msec, GHOST_IWindow *window, GHOST_TInt32 z)
: GHOST_Event(msec, GHOST_kEventWheel, window)
diff --git a/intern/ghost/intern/GHOST_ISystem.cpp b/intern/ghost/intern/GHOST_ISystem.cpp
index 009753cb29e..d7dd2b1cde1 100644
--- a/intern/ghost/intern/GHOST_ISystem.cpp
+++ b/intern/ghost/intern/GHOST_ISystem.cpp
@@ -38,21 +38,22 @@
#include "GHOST_ISystem.h"
-#ifdef WITH_HEADLESS
-# include "GHOST_SystemNULL.h"
-#elif defined(WITH_GHOST_SDL)
-# include "GHOST_SystemSDL.h"
-#elif defined(WIN32)
-# include "GHOST_SystemWin32.h"
+#ifdef WITH_X11
+# include "GHOST_SystemX11.h"
#else
-# ifdef __APPLE__
-# include "GHOST_SystemCocoa.h"
+# ifdef WITH_HEADLESS
+# include "GHOST_SystemNULL.h"
+# elif defined(WITH_GHOST_SDL)
+# include "GHOST_SystemSDL.h"
+# elif defined(WIN32)
+# include "GHOST_SystemWin32.h"
# else
-# include "GHOST_SystemX11.h"
+# ifdef __APPLE__
+# include "GHOST_SystemCocoa.h"
+# endif
# endif
#endif
-
GHOST_ISystem *GHOST_ISystem::m_system = 0;
@@ -60,19 +61,21 @@ GHOST_TSuccess GHOST_ISystem::createSystem()
{
GHOST_TSuccess success;
if (!m_system) {
-#ifdef WITH_HEADLESS
+#ifdef WITH_X11
+ m_system = new GHOST_SystemX11();
+#else
+# ifdef WITH_HEADLESS
m_system = new GHOST_SystemNULL();
-#elif defined(WITH_GHOST_SDL)
+# elif defined(WITH_GHOST_SDL)
m_system = new GHOST_SystemSDL();
-#elif defined(WIN32)
+# elif defined(WIN32)
m_system = new GHOST_SystemWin32();
-#else
-# ifdef __APPLE__
- m_system = new GHOST_SystemCocoa();
# else
- m_system = new GHOST_SystemX11();
+# ifdef __APPLE__
+ m_system = new GHOST_SystemCocoa();
+# endif
# endif
-#endif
+#endif
success = m_system != 0 ? GHOST_kSuccess : GHOST_kFailure;
}
else {
diff --git a/intern/ghost/intern/GHOST_ImeWin32.cpp b/intern/ghost/intern/GHOST_ImeWin32.cpp
new file mode 100644
index 00000000000..af5a2ed7097
--- /dev/null
+++ b/intern/ghost/intern/GHOST_ImeWin32.cpp
@@ -0,0 +1,520 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (c) 2010 The Chromium Authors. All rights reserved.
+ * All rights reserved.
+ *
+ * The Original Code is: some of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+
+/** \file ghost/intern/GHOST_ImeWin32.cpp
+ * \ingroup GHOST
+ */
+
+#ifdef WITH_INPUT_IME
+
+#include "GHOST_C-api.h"
+#include "GHOST_ImeWin32.h"
+#include "GHOST_WindowWin32.h"
+#include "utfconv.h"
+
+
+GHOST_ImeWin32::GHOST_ImeWin32()
+ : ime_status_(false),
+ input_language_id_(LANG_USER_DEFAULT),
+ is_composing_(false),
+ system_caret_(false),
+ caret_rect_(-1, -1, 0, 0),
+ is_first(true),
+ is_enable(true)
+{
+}
+
+
+GHOST_ImeWin32::~GHOST_ImeWin32()
+{
+}
+
+
+bool GHOST_ImeWin32::SetInputLanguage()
+{
+ /**
+ * Retrieve the current keyboard layout from Windows and determine whether
+ * or not the current input context has IMEs.
+ * Also save its input language for language-specific operations required
+ * while composing a text.
+ */
+ HKL keyboard_layout = ::GetKeyboardLayout(0);
+ input_language_id_ = reinterpret_cast<LANGID>(keyboard_layout);
+ ime_status_ = ::ImmIsIME(keyboard_layout);
+ return ime_status_;
+}
+
+
+void GHOST_ImeWin32::CreateImeWindow(HWND window_handle)
+{
+ /**
+ * When a user disables TSF (Text Service Framework) and CUAS (Cicero
+ * Unaware Application Support), Chinese IMEs somehow ignore function calls
+ * to ::ImmSetCandidateWindow(), i.e. they do not move their candidate
+ * window to the position given as its parameters, and use the position
+ * of the current system caret instead, i.e. it uses ::GetCaretPos() to
+ * retrieve the position of their IME candidate window.
+ * Therefore, we create a temporary system caret for Chinese IMEs and use
+ * it during this input context.
+ * Since some third-party Japanese IME also uses ::GetCaretPos() to determine
+ * their window position, we also create a caret for Japanese IMEs.
+ */
+ if (PRIMARYLANGID(input_language_id_) == LANG_CHINESE ||
+ PRIMARYLANGID(input_language_id_) == LANG_JAPANESE) {
+ if (!system_caret_) {
+ if (::CreateCaret(window_handle, NULL, 1, 1)) {
+ system_caret_ = true;
+ }
+ }
+ }
+ /* Restore the positions of the IME windows. */
+ UpdateImeWindow(window_handle);
+}
+
+
+void GHOST_ImeWin32::SetImeWindowStyle(HWND window_handle, UINT message, WPARAM wparam, LPARAM lparam, BOOL *handled)
+{
+ /**
+ * To prevent the IMM (Input Method Manager) from displaying the IME
+ * composition window, Update the styles of the IME windows and EXPLICITLY
+ * call ::DefWindowProc() here.
+ * NOTE(hbono): We can NEVER let WTL call ::DefWindowProc() when we update
+ * the styles of IME windows because the 'lparam' variable is a local one
+ * and all its updates disappear in returning from this function, i.e. WTL
+ * does not call ::DefWindowProc() with our updated 'lparam' value but call
+ * the function with its original value and over-writes our window styles.
+ */
+ *handled = TRUE;
+ lparam &= ~ISC_SHOWUICOMPOSITIONWINDOW;
+ ::DefWindowProc(window_handle, message, wparam, lparam);
+}
+
+
+void GHOST_ImeWin32::DestroyImeWindow(HWND window_handle)
+{
+ /* Destroy the system caret if we have created for this IME input context. */
+ if (system_caret_) {
+ ::DestroyCaret();
+ system_caret_ = false;
+ }
+}
+
+
+void GHOST_ImeWin32::MoveImeWindow(HWND window_handle, HIMC imm_context)
+{
+ int x = caret_rect_.m_l;
+ int y = caret_rect_.m_t;
+ const int kCaretMargin = 1;
+ /**
+ * As written in a comment in GHOST_ImeWin32::CreateImeWindow(),
+ * Chinese IMEs ignore function calls to ::ImmSetCandidateWindow()
+ * when a user disables TSF (Text Service Framework) and CUAS (Cicero
+ * Unaware Application Support).
+ * On the other hand, when a user enables TSF and CUAS, Chinese IMEs
+ * ignore the position of the current system caret and uses the
+ * parameters given to ::ImmSetCandidateWindow() with its 'dwStyle'
+ * parameter CFS_CANDIDATEPOS.
+ * Therefore, we do not only call ::ImmSetCandidateWindow() but also
+ * set the positions of the temporary system caret if it exists.
+ */
+ CANDIDATEFORM candidate_position = { 0, CFS_CANDIDATEPOS, { x, y },
+ { 0, 0, 0, 0 } };
+ ::ImmSetCandidateWindow(imm_context, &candidate_position);
+ if (system_caret_) {
+ switch (PRIMARYLANGID(input_language_id_)) {
+ case LANG_JAPANESE:
+ ::SetCaretPos(x, y + caret_rect_.getHeight());
+ break;
+ default:
+ ::SetCaretPos(x, y);
+ break;
+ }
+ }
+ if (PRIMARYLANGID(input_language_id_) == LANG_KOREAN) {
+ /**
+ * Chinese IMEs and Japanese IMEs require the upper-left corner of
+ * the caret to move the position of their candidate windows.
+ * On the other hand, Korean IMEs require the lower-left corner of the
+ * caret to move their candidate windows.
+ */
+ y += kCaretMargin;
+ }
+ /**
+ * Japanese IMEs and Korean IMEs also use the rectangle given to
+ * ::ImmSetCandidateWindow() with its 'dwStyle' parameter CFS_EXCLUDE
+ * to move their candidate windows when a user disables TSF and CUAS.
+ * Therefore, we also set this parameter here.
+ */
+ CANDIDATEFORM exclude_rectangle = { 0, CFS_EXCLUDE, { x, y },
+ { x, y, x + caret_rect_.getWidth(), y + caret_rect_.getHeight() } };
+ ::ImmSetCandidateWindow(imm_context, &exclude_rectangle);
+}
+
+
+void GHOST_ImeWin32::UpdateImeWindow(HWND window_handle)
+{
+ /* Just move the IME window attached to the given window. */
+ if (caret_rect_.m_l >= 0 && caret_rect_.m_t >= 0) {
+ HIMC imm_context = ::ImmGetContext(window_handle);
+ if (imm_context) {
+ MoveImeWindow(window_handle, imm_context);
+ ::ImmReleaseContext(window_handle, imm_context);
+ }
+ }
+}
+
+
+void GHOST_ImeWin32::CleanupComposition(HWND window_handle)
+{
+ /**
+ * Notify the IMM attached to the given window to complete the ongoing
+ * composition, (this case happens when the given window is de-activated
+ * while composing a text and re-activated), and reset the omposition status.
+ */
+ if (is_composing_) {
+ HIMC imm_context = ::ImmGetContext(window_handle);
+ if (imm_context) {
+ ::ImmNotifyIME(imm_context, NI_COMPOSITIONSTR, CPS_COMPLETE, 0);
+ ::ImmReleaseContext(window_handle, imm_context);
+ }
+ ResetComposition(window_handle);
+ }
+}
+
+
+void GHOST_ImeWin32::CheckFirst(HWND window_handle)
+{
+ if (is_first) {
+ this->EndIME(window_handle);
+ is_first = false;
+ }
+}
+
+
+void GHOST_ImeWin32::ResetComposition(HWND window_handle)
+{
+ /* Currently, just reset the composition status. */
+ is_composing_ = false;
+}
+
+
+void GHOST_ImeWin32::CompleteComposition(HWND window_handle, HIMC imm_context)
+{
+ /**
+ * We have to confirm there is an ongoing composition before completing it.
+ * This is for preventing some IMEs from getting confused while completing an
+ * ongoing composition even if they do not have any ongoing compositions.)
+ */
+ if (is_composing_) {
+ ::ImmNotifyIME(imm_context, NI_COMPOSITIONSTR, CPS_COMPLETE, 0);
+ ResetComposition(window_handle);
+ }
+}
+
+
+void GHOST_ImeWin32::GetCaret(HIMC imm_context, LPARAM lparam, ImeComposition *composition)
+{
+ /**
+ * This operation is optional and language-dependent because the caret
+ * style is depended on the language, e.g.:
+ * * Korean IMEs: the caret is a blinking block,
+ * (It contains only one hangul character);
+ * * Chinese IMEs: the caret is a blinking line,
+ * (i.e. they do not need to retrieve the target selection);
+ * * Japanese IMEs: the caret is a selection (or underlined) block,
+ * (which can contain one or more Japanese characters).
+ */
+ int target_start = -1;
+ int target_end = -1;
+ switch (PRIMARYLANGID(input_language_id_)) {
+ case LANG_KOREAN:
+ if (lparam & CS_NOMOVECARET) {
+ target_start = 0;
+ target_end = 1;
+ }
+ break;
+ case LANG_CHINESE:
+ {
+ int clause_size = ImmGetCompositionStringW(imm_context, GCS_COMPCLAUSE, NULL, 0);
+ if (clause_size) {
+ static std::vector<unsigned long> clauses;
+ clause_size = clause_size / sizeof(clauses[0]);
+ clauses.resize(clause_size);
+ ImmGetCompositionStringW(imm_context, GCS_COMPCLAUSE, &clauses[0],
+ sizeof(clauses[0]) *clause_size);
+ if (composition->cursor_position == composition->ime_string.size()) {
+ target_start = clauses[clause_size - 2];
+ target_end = clauses[clause_size - 1];
+ }
+ else {
+ for (int i = 0; i < clause_size - 1; i++) {
+ if (clauses[i] == composition->cursor_position) {
+ target_start = clauses[i];
+ target_end = clauses[i + 1];
+ break;
+ }
+ }
+ }
+ }
+ else {
+ if (composition->cursor_position != -1) {
+ target_start = composition->cursor_position;
+ target_end = composition->ime_string.size();
+ }
+ }
+ break;
+ }
+ case LANG_JAPANESE:
+
+ /**
+ * For Japanese IMEs, the robustest way to retrieve the caret
+ * is scanning the attribute of the latest composition string and
+ * retrieving the begining and the end of the target clause, i.e.
+ * a clause being converted.
+ */
+ if (lparam & GCS_COMPATTR) {
+ int attribute_size = ::ImmGetCompositionStringW(imm_context,
+ GCS_COMPATTR,
+ NULL, 0);
+ if (attribute_size > 0) {
+ char *attribute_data = new char[attribute_size];
+ if (attribute_data) {
+ ::ImmGetCompositionStringW(imm_context, GCS_COMPATTR,
+ attribute_data, attribute_size);
+ for (target_start = 0; target_start < attribute_size;
+ ++target_start) {
+ if (IsTargetAttribute(attribute_data[target_start]))
+ break;
+ }
+ for (target_end = target_start; target_end < attribute_size;
+ ++target_end) {
+ if (!IsTargetAttribute(attribute_data[target_end]))
+ break;
+ }
+ if (target_start == attribute_size) {
+ /**
+ * This composition clause does not contain any target clauses,
+ * i.e. this clauses is an input clause.
+ * We treat whole this clause as a target clause.
+ */
+ target_end = target_start;
+ target_start = 0;
+ }
+ if (target_start != -1 && target_start < attribute_size &&
+ attribute_data[target_start] == ATTR_TARGET_NOTCONVERTED)
+ {
+ composition->cursor_position = target_start;
+ }
+ }
+ delete[] attribute_data;
+ }
+ }
+ break;
+ }
+ composition->target_start = target_start;
+ composition->target_end = target_end;
+}
+
+
+bool GHOST_ImeWin32::GetString(HIMC imm_context, WPARAM lparam, int type, ImeComposition *composition)
+{
+ bool result = false;
+ if (lparam & type) {
+ int string_size = ::ImmGetCompositionStringW(imm_context, type, NULL, 0);
+ if (string_size > 0) {
+ int string_length = string_size / sizeof(wchar_t);
+ wchar_t *string_data = new wchar_t[string_length + 1];
+ string_data[string_length] = '\0';
+ if (string_data) {
+ /* Fill the given ImeComposition object. */
+ ::ImmGetCompositionStringW(imm_context, type,
+ string_data, string_size);
+ composition->string_type = type;
+ composition->ime_string = string_data;
+ result = true;
+ }
+ delete[] string_data;
+ }
+ }
+ return result;
+}
+
+
+bool GHOST_ImeWin32::GetResult(HWND window_handle, LPARAM lparam, ImeComposition *composition)
+{
+ bool result = false;
+ HIMC imm_context = ::ImmGetContext(window_handle);
+ if (imm_context) {
+ /* Copy the result string to the ImeComposition object. */
+ result = GetString(imm_context, lparam, GCS_RESULTSTR, composition);
+ /**
+ * Reset all the other parameters because a result string does not
+ * have composition attributes.
+ */
+ composition->cursor_position = -1;
+ composition->target_start = -1;
+ composition->target_end = -1;
+ ::ImmReleaseContext(window_handle, imm_context);
+ }
+ return result;
+}
+
+
+bool GHOST_ImeWin32::GetComposition(HWND window_handle, LPARAM lparam, ImeComposition *composition)
+{
+ bool result = false;
+ HIMC imm_context = ::ImmGetContext(window_handle);
+ if (imm_context) {
+ /* Copy the composition string to the ImeComposition object. */
+ result = GetString(imm_context, lparam, GCS_COMPSTR, composition);
+
+ /* Retrieve the cursor position in the IME composition. */
+ int cursor_position = ::ImmGetCompositionStringW(imm_context, GCS_CURSORPOS, NULL, 0);
+ composition->cursor_position = cursor_position;
+ composition->target_start = -1;
+ composition->target_end = -1;
+
+ /* Retrieve the target selection and Update the ImeComposition object. */
+ GetCaret(imm_context, lparam, composition);
+
+ /* Mark that there is an ongoing composition. */
+ is_composing_ = true;
+
+ ::ImmReleaseContext(window_handle, imm_context);
+ }
+ return result;
+}
+
+
+void GHOST_ImeWin32::EndIME(HWND window_handle)
+{
+ /**
+ * A renderer process have moved its input focus to a password input
+ * when there is an ongoing composition, e.g. a user has clicked a
+ * mouse button and selected a password input while composing a text.
+ * For this case, we have to complete the ongoing composition and
+ * clean up the resources attached to this object BEFORE DISABLING THE IME.
+ */
+ if (!is_enable) return;
+ is_enable = false;
+ CleanupComposition(window_handle);
+ ::ImmAssociateContextEx(window_handle, NULL, 0);
+ eventImeData.composite_len = 0;
+}
+
+
+void GHOST_ImeWin32::BeginIME(HWND window_handle, const GHOST_Rect &caret_rect, bool complete)
+{
+ if (is_enable && complete) return;
+ is_enable = true;
+ /**
+ * Load the default IME context.
+ * NOTE(hbono)
+ * IMM ignores this call if the IME context is loaded. Therefore, we do
+ * not have to check whether or not the IME context is loaded.
+ */
+ ::ImmAssociateContextEx(window_handle, NULL, IACE_DEFAULT);
+ /* Complete the ongoing composition and move the IME windows. */
+ HIMC imm_context = ::ImmGetContext(window_handle);
+ if (imm_context) {
+ if (complete) {
+ /**
+ * A renderer process have moved its input focus to another edit
+ * control when there is an ongoing composition, e.g. a user has
+ * clicked a mouse button and selected another edit control while
+ * composing a text.
+ * For this case, we have to complete the ongoing composition and
+ * hide the IME windows BEFORE MOVING THEM.
+ */
+ CompleteComposition(window_handle, imm_context);
+ }
+ /**
+ * Save the caret position, and Update the position of the IME window.
+ * This update is used for moving an IME window when a renderer process
+ * resize/moves the input caret.
+ */
+ if (caret_rect.m_l >= 0 && caret_rect.m_t >= 0) {
+ caret_rect_ = caret_rect;
+ MoveImeWindow(window_handle, imm_context);
+ }
+ ::ImmReleaseContext(window_handle, imm_context);
+ }
+}
+
+
+static void convert_utf16_to_utf8_len(std::wstring s, int &len)
+{
+ if (len >= 0 && len <= s.size())
+ len = count_utf_8_from_16(s.substr(0, len).c_str()) - 1;
+ else
+ len = -1;
+}
+
+
+static size_t updateUtf8Buf(ImeComposition &info)
+{
+ size_t len = count_utf_8_from_16(info.ime_string.c_str());
+ info.utf8_buf.resize(len);
+ conv_utf_16_to_8(info.ime_string.c_str(), &info.utf8_buf[0], len);
+ convert_utf16_to_utf8_len(info.ime_string, info.cursor_position);
+ convert_utf16_to_utf8_len(info.ime_string, info.target_start);
+ convert_utf16_to_utf8_len(info.ime_string, info.target_end);
+ return len - 1;
+}
+
+
+void GHOST_ImeWin32::UpdateInfo(HWND window_handle)
+{
+ int res = this->GetResult(window_handle, GCS_RESULTSTR, &resultInfo);
+ int comp = this->GetComposition(window_handle, GCS_COMPSTR | GCS_COMPATTR, &compInfo);
+ /* convert wchar to utf8 */
+ if (res) {
+ eventImeData.result_len = (GHOST_TUserDataPtr)updateUtf8Buf(resultInfo);
+ eventImeData.result = &resultInfo.utf8_buf[0];
+ }
+ else {
+ eventImeData.result = 0;
+ eventImeData.result_len = 0;
+ }
+ if (comp) {
+ eventImeData.composite_len = (GHOST_TUserDataPtr)updateUtf8Buf(compInfo);
+ eventImeData.composite = &compInfo.utf8_buf[0];
+ eventImeData.cursor_position = compInfo.cursor_position;
+ eventImeData.target_start = compInfo.target_start;
+ eventImeData.target_end = compInfo.target_end;
+ }
+ else {
+ eventImeData.composite = 0;
+ eventImeData.composite_len = 0;
+ eventImeData.cursor_position = -1;
+ eventImeData.target_start = -1;
+ eventImeData.target_end = -1;
+ }
+}
+
+#endif // WITH_INPUT_IME
diff --git a/intern/ghost/intern/GHOST_ImeWin32.h b/intern/ghost/intern/GHOST_ImeWin32.h
new file mode 100644
index 00000000000..bfd9a49d785
--- /dev/null
+++ b/intern/ghost/intern/GHOST_ImeWin32.h
@@ -0,0 +1,405 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (c) 2010 The Chromium Authors. All rights reserved.
+ * All rights reserved.
+ *
+ * The Original Code is: some of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+*/
+
+/** \file ghost/intern/GHOST_ImeWin32.h
+ * \ingroup GHOST
+ */
+
+#ifndef __GHOST_IME_H__
+#define __GHOST_IME_H__
+
+#ifdef WITH_INPUT_IME
+
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+
+#include <string>
+
+#include "GHOST_Event.h"
+#include "GHOST_Rect.h"
+#include <vector>
+
+class GHOST_EventIME : public GHOST_Event
+{
+public:
+ /**
+ * Constructor.
+ * \param msec The time this event was generated.
+ * \param type The type of key event.
+ * \param key The key code of the key.
+ */
+ GHOST_EventIME(GHOST_TUns64 msec,
+ GHOST_TEventType type,
+ GHOST_IWindow *window, void *customdata)
+ : GHOST_Event(msec, type, window)
+ {
+ this->m_data = customdata;
+ }
+
+};
+
+
+/**
+ * This header file defines a struct and a class used for encapsulating IMM32
+ * APIs, controls IMEs attached to a window, and enables the 'on-the-spot'
+ * input without deep knowledge about the APIs, i.e. knowledge about the
+ * language-specific and IME-specific behaviors.
+ * The following items enumerates the simplest steps for an (window)
+ * application to control its IMEs with the struct and the class defined
+ * this file.
+ * 1. Add an instance of the GHOST_ImeWin32 class to its window class.
+ * (The GHOST_ImeWin32 class needs a window handle.)
+ * 2. Add messages handlers listed in the following subsections, follow the
+ * instructions written in each subsection, and use the GHOST_ImeWin32 class.
+ * 2.1. WM_IME_SETCONTEXT (0x0281)
+ * Call the functions listed below:
+ * - GHOST_ImeWin32::CreateImeWindow();
+ * - GHOST_ImeWin32::CleanupComposition(), and;
+ * - GHOST_ImeWin32::SetImeWindowStyle().
+ * An application MUST prevent from calling ::DefWindowProc().
+ * 2.2. WM_IME_STARTCOMPOSITION (0x010D)
+ * Call the functions listed below:
+ * - GHOST_ImeWin32::CreateImeWindow(), and;
+ * - GHOST_ImeWin32::ResetComposition().
+ * An application MUST prevent from calling ::DefWindowProc().
+ * 2.3. WM_IME_COMPOSITION (0x010F)
+ * Call the functions listed below:
+ * - GHOST_ImeWin32::UpdateImeWindow();
+ * - GHOST_ImeWin32::GetResult();
+ * - GHOST_ImeWin32::GetComposition(), and;
+ * - GHOST_ImeWin32::ResetComposition() (optional).
+ * An application MUST prevent from calling ::DefWindowProc().
+ * 2.4. WM_IME_ENDCOMPOSITION (0x010E)
+ * Call the functions listed below:
+ * - GHOST_ImeWin32::ResetComposition(), and;
+ * - GHOST_ImeWin32::DestroyImeWindow().
+ * An application CAN call ::DefWindowProc().
+ * 2.5. WM_INPUTLANGCHANGE (0x0051)
+ * Call the functions listed below:
+ * - GHOST_ImeWin32::SetInputLanguage().
+ * An application CAN call ::DefWindowProc().
+ */
+
+/* This struct represents the status of an ongoing composition. */
+struct ImeComposition {
+ /* Represents the cursor position in the IME composition. */
+ int cursor_position;
+
+ /* Represents the position of the beginning of the selection */
+ int target_start;
+
+ /* Represents the position of the end of the selection */
+ int target_end;
+
+ /**
+ * Represents the type of the string in the 'ime_string' parameter.
+ * Its possible values and description are listed below:
+ * Value Description
+ * 0 The parameter is not used.
+ * GCS_RESULTSTR The parameter represents a result string.
+ * GCS_COMPSTR The parameter represents a composition string.
+ */
+ int string_type;
+
+ /* Represents the string retrieved from IME (Input Method Editor) */
+ std::wstring ime_string;
+ std::vector<char> utf8_buf;
+ std::vector<unsigned char> format;
+};
+
+/**
+ * This class controls the IMM (Input Method Manager) through IMM32 APIs and
+ * enables it to retrieve the string being controled by the IMM. (I wrote
+ * a note to describe the reason why I do not use 'IME' but 'IMM' below.)
+ * NOTE(hbono):
+ * Fortunately or unfortunately, TSF (Text Service Framework) and
+ * CUAS (Cicero Unaware Application Support) allows IMM32 APIs for
+ * retrieving not only the inputs from IMEs (Input Method Editors), used
+ * only for inputting East-Asian language texts, but also the ones from
+ * tablets (on Windows XP Tablet PC Edition and Windows Vista), voice
+ * recognizers (e.g. ViaVoice and Microsoft Office), etc.
+ * We can disable TSF and CUAS in Windows XP Tablet PC Edition. On the other
+ * hand, we can NEVER disable either TSF or CUAS in Windows Vista, i.e.
+ * THIS CLASS IS NOT ONLY USED ON THE INPUT CONTEXTS OF EAST-ASIAN
+ * LANGUAGES BUT ALSO USED ON THE INPUT CONTEXTS OF ALL LANGUAGES.
+ */
+class GHOST_ImeWin32 {
+public:
+ GHOST_ImeWin32();
+ ~GHOST_ImeWin32();
+
+ /* Retrieves whether or not there is an ongoing composition. */
+ bool is_composing() const {return is_composing_;}
+
+ /**
+ * Retrieves the input language from Windows and update it.
+ * Return values
+ * * true
+ * The given input language has IMEs.
+ * * false
+ * The given input language does not have IMEs.
+ */
+ bool SetInputLanguage();
+
+ /**
+ * Create the IME windows, and allocate required resources for them.
+ * Parameters
+ * * window_handle [in] (HWND)
+ * Represents the window handle of the caller.
+ */
+ void CreateImeWindow(HWND window_handle);
+
+ /**
+ * Update the style of the IME windows.
+ * Parameters
+ * * window_handle [in] (HWND)
+ * Represents the window handle of the caller.
+ * * message [in] (UINT)
+ * * wparam [in] (WPARAM)
+ * * lparam [in] (LPARAM)
+ * Represent the windows message of the caller.
+ * These parameters are used for verifying if this function is called
+ * in a handler function for WM_IME_SETCONTEXT messages because this
+ * function uses ::DefWindowProc() to update the style.
+ * A caller just has to pass the input parameters for the handler
+ * function without modifications.
+ * * handled [out] (BOOL*)
+ * Returns ::DefWindowProc() is really called in this function.
+ * PLEASE DO NOT CALL ::DefWindowProc() IF THIS VALUE IS TRUE!
+ * All the window styles set in this function are over-written when
+ * calling ::DefWindowProc() after returning this function.
+ */
+ void SetImeWindowStyle(HWND window_handle, UINT message,
+ WPARAM wparam, LPARAM lparam, BOOL* handled);
+
+ /**
+ * Destroy the IME windows and all the resources attached to them.
+ * Parameters
+ * * window_handle [in] (HWND)
+ * Represents the window handle of the caller.
+ */
+ void DestroyImeWindow(HWND window_handle);
+
+ /**
+ * Update the position of the IME windows.
+ * Parameters
+ * * window_handle [in] (HWND)
+ * Represents the window handle of the caller.
+ */
+ void UpdateImeWindow(HWND window_handle);
+
+ /**
+ * Clean up the all resources attached to the given GHOST_ImeWin32 object, and
+ * reset its composition status.
+ * Parameters
+ * * window_handle [in] (HWND)
+ * Represents the window handle of the caller.
+ */
+ void CleanupComposition(HWND window_handle);
+
+ /**
+ * Reset the composition status.
+ * Cancel the ongoing composition if it exists.
+ * NOTE(hbono): This method does not release the allocated resources.
+ * Parameters
+ * * window_handle [in] (HWND)
+ * Represents the window handle of the caller.
+ */
+ void ResetComposition(HWND window_handle);
+
+ /**
+ * Retrieve a composition result of the ongoing composition if it exists.
+ * Parameters
+ * * window_handle [in] (HWND)
+ * Represents the window handle of the caller.
+ * * lparam [in] (LPARAM)
+ * Specifies the updated members of the ongoing composition, and must be
+ * the same parameter of a WM_IME_COMPOSITION message handler.
+ * This parameter is used for checking if the ongoing composition has
+ * its result string,
+ * * composition [out] (ImeComposition)
+ * Represents the struct contains the composition result.
+ * Return values
+ * * true
+ * The ongoing composition has a composition result.
+ * * false
+ * The ongoing composition does not have composition results.
+ * Remarks
+ * This function is designed for being called from WM_IME_COMPOSITION
+ * message handlers.
+ */
+ bool GetResult(HWND window_handle, LPARAM lparam,
+ ImeComposition* composition);
+
+ /**
+ * Retrieve the current composition status of the ongoing composition.
+ * Parameters
+ * * window_handle [in] (HWND)
+ * Represents the window handle of the caller.
+ * * lparam [in] (LPARAM)
+ * Specifies the updated members of the ongoing composition, and must be
+ * the same parameter of a WM_IME_COMPOSITION message handler.
+ * This parameter is used for checking if the ongoing composition has
+ * its result string,
+ * * composition [out] (ImeComposition)
+ * Represents the struct contains the composition status.
+ * Return values
+ * * true
+ * The status of the ongoing composition is updated.
+ * * false
+ * The status of the ongoing composition is not updated.
+ * Remarks
+ * This function is designed for being called from WM_IME_COMPOSITION
+ * message handlers.
+ */
+ bool GetComposition(HWND window_handle, LPARAM lparam,
+ ImeComposition* composition);
+
+ /**
+ * Enable the IME attached to the given window, i.e. allows user-input
+ * events to be dispatched to the IME.
+ * In Chrome, this function is used when:
+ * * a renderer process moves its input focus to another edit control, or;
+ * * a renrerer process moves the position of the focused edit control.
+ * Parameters
+ * * window_handle [in] (HWND)
+ * Represents the window handle of the caller.
+ * * caret_rect [in] (const gfx::Rect&)
+ * Represent the rectangle of the input caret.
+ * This rectangle is used for controlling the positions of IME windows.
+ * * complete [in] (bool)
+ * Represents whether or not to complete the ongoing composition.
+ * + true
+ * After finishing the ongoing composition and close its IME windows,
+ * start another composition and display its IME windows to the given
+ * position.
+ * + false
+ * Just move the IME windows of the ongoing composition to the given
+ * position without finishing it.
+ */
+ void BeginIME(HWND window_handle,
+ const GHOST_Rect& caret_rect,
+ bool complete);
+
+ /**
+ * Disable the IME attached to the given window, i.e. prohibits any user-input
+ * events from being dispatched to the IME.
+ * In Chrome, this function is used when:
+ * * a renreder process sets its input focus to a password input.
+ * Parameters
+ * * window_handle [in] (HWND)
+ * Represents the window handle of the caller.
+ */
+ void EndIME(HWND window_handle);
+
+ /* Updatg resultInfo and compInfo */
+ void UpdateInfo(HWND window_handle);
+
+ /* disable ime when start up */
+ void CheckFirst(HWND window_handle);
+
+ ImeComposition resultInfo, compInfo;
+ GHOST_TEventImeData eventImeData;
+
+protected:
+ /* Determines whether or not the given attribute represents a target (a.k.a. a selection). */
+ bool IsTargetAttribute(char attribute) const {
+ return (attribute == ATTR_TARGET_CONVERTED ||
+ attribute == ATTR_TARGET_NOTCONVERTED);
+ }
+
+ /* Retrieve the target area. */
+ void GetCaret(HIMC imm_context, LPARAM lparam,
+ ImeComposition* composition);
+
+ /* Update the position of the IME windows. */
+ void MoveImeWindow(HWND window_handle, HIMC imm_context);
+
+ /* Complete the ongoing composition if it exists. */
+ void CompleteComposition(HWND window_handle, HIMC imm_context);
+
+ /* Retrieve a string from the IMM. */
+ bool GetString(HIMC imm_context, WPARAM lparam, int type,
+ ImeComposition* composition);
+
+private:
+ /**
+ * Represents whether or not there is an ongoing composition in a browser
+ * process, i.e. whether or not a browser process is composing a text.
+ */
+ bool is_composing_;
+
+ /**
+ * This value represents whether or not the current input context has IMEs.
+ * The following table shows the list of IME status:
+ * Value Description
+ * false The current input language does not have IMEs.
+ * true The current input language has IMEs.
+ */
+ bool ime_status_;
+
+ /**
+ * The current input Language ID retrieved from Windows, which consists of:
+ * * Primary Language ID (bit 0 to bit 9), which shows a natunal language
+ * (English, Korean, Chinese, Japanese, etc.) and;
+ * * Sub-Language ID (bit 10 to bit 15), which shows a geometrical region
+ * the language is spoken (For English, United States, United Kingdom,
+ * Australia, Canada, etc.)
+ * The following list enumerates some examples for the Language ID:
+ * * "en-US" (0x0409)
+ * MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US);
+ * * "ko-KR" (0x0412)
+ * MAKELANGID(LANG_KOREAN, SUBLANG_KOREAN);
+ * * "zh-TW" (0x0404)
+ * MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_TRADITIONAL);
+ * * "zh-CN" (0x0804)
+ * MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED);
+ * * "ja-JP" (0x0411)
+ * MAKELANGID(LANG_JAPANESE, SUBLANG_JAPANESE_JAPAN), etc.
+ * (See <winnt.h> for other available values.)
+ * This Language ID is used for processing language-specific operations in
+ * IME functions.
+ */
+ LANGID input_language_id_;
+
+ /**
+ * Represents whether or not the current input context has created a system
+ * caret to set the position of its IME candidate window.
+ * * true: it creates a system caret.
+ * * false: it does not create a system caret.
+ */
+ bool system_caret_;
+
+ /* The rectangle of the input caret retrieved from a renderer process. */
+ GHOST_Rect caret_rect_;
+
+ /* used for disable ime when start up */
+ bool is_first, is_enable;
+};
+
+#endif // WITH_INPUT_IME
+#endif // __GHOST_IME_H__
diff --git a/intern/ghost/intern/GHOST_ModifierKeys.h b/intern/ghost/intern/GHOST_ModifierKeys.h
index 8189006f602..a30b66c4634 100644
--- a/intern/ghost/intern/GHOST_ModifierKeys.h
+++ b/intern/ghost/intern/GHOST_ModifierKeys.h
@@ -47,7 +47,7 @@ struct GHOST_ModifierKeys {
*/
GHOST_ModifierKeys();
- virtual ~GHOST_ModifierKeys();
+ ~GHOST_ModifierKeys();
/**
* Returns the modifier key's key code from a modifier key mask.
@@ -59,29 +59,29 @@ struct GHOST_ModifierKeys {
/**
* Returns the state of a single modifier key.
- * \param mask. Key state to return.
+ * \param mask: Key state to return.
* \return The state of the key (pressed == true).
*/
- virtual bool get(GHOST_TModifierKeyMask mask) const;
+ bool get(GHOST_TModifierKeyMask mask) const;
/**
* Updates the state of a single modifier key.
- * \param mask. Key state to update.
- * \param down. The new state of the key.
+ * \param mask: Key state to update.
+ * \param down: The new state of the key.
*/
- virtual void set(GHOST_TModifierKeyMask mask, bool down);
+ void set(GHOST_TModifierKeyMask mask, bool down);
/**
* Sets the state of all modifier keys to up.
*/
- virtual void clear();
+ void clear();
/**
* Determines whether to modifier key states are equal.
- * \param keys. The modifier key state to compare to.
+ * \param keys: The modifier key state to compare to.
* \return Indication of equality.
*/
- virtual bool equals(const GHOST_ModifierKeys& keys) const;
+ bool equals(const GHOST_ModifierKeys& keys) const;
/** Bitfield that stores the appropriate key state. */
GHOST_TUns8 m_LeftShift : 1;
diff --git a/intern/ghost/intern/GHOST_NDOFManager.cpp b/intern/ghost/intern/GHOST_NDOFManager.cpp
index 9bd6226d5c2..27285e49e9e 100644
--- a/intern/ghost/intern/GHOST_NDOFManager.cpp
+++ b/intern/ghost/intern/GHOST_NDOFManager.cpp
@@ -146,8 +146,8 @@ static const NDOF_ButtonT SpaceExplorer_HID_map[] = {
NDOF_BUTTON_ROTATE
};
-/* this is the older SpacePilot (sans Pro)
- * thanks to polosson for info about this device */
+// this is the older SpacePilot (sans Pro)
+// thanks to polosson for info about this device
static const NDOF_ButtonT SpacePilot_HID_map[] = {
NDOF_BUTTON_1,
NDOF_BUTTON_2,
@@ -190,17 +190,17 @@ static const NDOF_ButtonT Generic_HID_map[] = {
static const int genericButtonCount = sizeof(Generic_HID_map) / sizeof(NDOF_ButtonT);
GHOST_NDOFManager::GHOST_NDOFManager(GHOST_System &sys)
- : m_system(sys),
- m_deviceType(NDOF_UnknownDevice), /* each platform has its own device detection code */
- m_buttonCount(genericButtonCount),
- m_buttonMask(0),
- m_hidMap(Generic_HID_map),
- m_buttons(0),
- m_motionTime(0),
- m_prevMotionTime(0),
- m_motionState(GHOST_kNotStarted),
- m_motionEventPending(false),
- m_deadZone(0.0f)
+ : m_system(sys),
+ m_deviceType(NDOF_UnknownDevice), // each platform has its own device detection code
+ m_buttonCount(genericButtonCount),
+ m_buttonMask(0),
+ m_hidMap(Generic_HID_map),
+ m_buttons(0),
+ m_motionTime(0),
+ m_prevMotionTime(0),
+ m_motionState(GHOST_kNotStarted),
+ m_motionEventPending(false),
+ m_deadZone(0.0f)
{
// to avoid the rare situation where one triple is updated and
// the other is not, initialize them both here:
@@ -228,7 +228,7 @@ bool GHOST_NDOFManager::setDevice(unsigned short vendor_id, unsigned short produ
// that I don't have access to. Thanks!
switch (vendor_id) {
- case 0x046D: // Logitech (3Dconnexion)
+ case 0x046D: // Logitech (3Dconnexion was a subsidiary)
switch (product_id) {
// -- current devices --
case 0xC626: // full-size SpaceNavigator
@@ -281,6 +281,29 @@ bool GHOST_NDOFManager::setDevice(unsigned short vendor_id, unsigned short produ
printf("ndof: unknown Logitech product %04hx\n", product_id);
}
break;
+ case 0x256F: // 3Dconnexion
+ switch (product_id) {
+ case 0xC62E: // plugged in
+ case 0xC62F: // wireless
+ puts("ndof: using SpaceMouse Wireless");
+ m_deviceType = NDOF_SpaceMouseWireless;
+ m_buttonCount = 2;
+ m_hidMap = Modern3Dx_HID_map;
+ break;
+ case 0xC631: // plugged in
+ case 0xC632: // wireless
+ puts("ndof: using SpaceMouse Pro Wireless");
+ m_deviceType = NDOF_SpaceMouseProWireless;
+ m_buttonCount = 27;
+ // ^^ actually has 15 buttons, but their HID codes range from 0 to 26
+ m_buttonMask = 0x07C0F137;
+ m_hidMap = Modern3Dx_HID_map;
+ break;
+
+ default:
+ printf("ndof: unknown 3Dconnexion product %04hx\n", product_id);
+ }
+ break;
default:
printf("ndof: unknown device %04hx:%04hx\n", vendor_id, product_id);
}
@@ -390,9 +413,9 @@ void GHOST_NDOFManager::updateButtons(int button_bits, GHOST_TUns64 time)
void GHOST_NDOFManager::setDeadZone(float dz)
{
- if (dz < 0.f) {
+ if (dz < 0.0f) {
// negative values don't make sense, so clamp at zero
- dz = 0.f;
+ dz = 0.0f;
}
else if (dz > 0.5f) {
// warn the rogue user/developer, but allow it
@@ -405,14 +428,14 @@ void GHOST_NDOFManager::setDeadZone(float dz)
static bool atHomePosition(GHOST_TEventNDOFMotionData *ndof)
{
-#define HOME(foo) (ndof->foo == 0.f)
+#define HOME(foo) (ndof->foo == 0.0f)
return HOME(tx) && HOME(ty) && HOME(tz) && HOME(rx) && HOME(ry) && HOME(rz);
#undef HOME
}
static bool nearHomePosition(GHOST_TEventNDOFMotionData *ndof, float threshold)
{
- if (threshold == 0.f) {
+ if (threshold == 0.0f) {
return atHomePosition(ndof);
}
else {
@@ -442,7 +465,7 @@ bool GHOST_NDOFManager::sendMotionEvent()
// scale axis values here to normalize them to around +/- 1
// they are scaled again for overall sensitivity in the WM based on user prefs
- const float scale = 1.f / 350.f; // 3Dconnexion devices send +/- 350 usually
+ const float scale = 1.0f / 350.0f; // 3Dconnexion devices send +/- 350 usually
data->tx = scale * m_translation[0];
data->ty = scale * m_translation[1];
diff --git a/intern/ghost/intern/GHOST_NDOFManager.h b/intern/ghost/intern/GHOST_NDOFManager.h
index 0b2080e36a9..48a4881afb1 100644
--- a/intern/ghost/intern/GHOST_NDOFManager.h
+++ b/intern/ghost/intern/GHOST_NDOFManager.h
@@ -20,7 +20,7 @@
*
* ***** END GPL LICENSE BLOCK *****
*/
-
+
#ifndef __GHOST_NDOFMANAGER_H__
#define __GHOST_NDOFMANAGER_H__
@@ -38,6 +38,8 @@ typedef enum {
NDOF_SpaceExplorer,
NDOF_SpacePilotPro,
NDOF_SpaceMousePro,
+ NDOF_SpaceMouseWireless,
+ NDOF_SpaceMouseProWireless,
// older devices
NDOF_SpacePilot,
diff --git a/intern/ghost/intern/GHOST_NDOFManagerWin32.cpp b/intern/ghost/intern/GHOST_NDOFManagerWin32.cpp
index 6c1627905e0..7ccd2e602b4 100644
--- a/intern/ghost/intern/GHOST_NDOFManagerWin32.cpp
+++ b/intern/ghost/intern/GHOST_NDOFManagerWin32.cpp
@@ -30,7 +30,7 @@
GHOST_NDOFManagerWin32::GHOST_NDOFManagerWin32(GHOST_System& sys)
: GHOST_NDOFManager(sys)
{
- setDeadZone(0.1f);
+ /* pass */
}
// whether multi-axis functionality is available (via the OS or driver)
diff --git a/intern/ghost/intern/GHOST_NDOFManagerX11.cpp b/intern/ghost/intern/GHOST_NDOFManagerX11.cpp
index 8e6f9994e51..753321be58e 100644
--- a/intern/ghost/intern/GHOST_NDOFManagerX11.cpp
+++ b/intern/ghost/intern/GHOST_NDOFManagerX11.cpp
@@ -33,8 +33,6 @@ GHOST_NDOFManagerX11::GHOST_NDOFManagerX11(GHOST_System& sys)
: GHOST_NDOFManager(sys),
m_available(false)
{
- setDeadZone(0.1f); /* how to calibrate on Linux? throw away slight motion! */
-
if (spnav_open() != -1) {
m_available = true;
@@ -42,8 +40,8 @@ GHOST_NDOFManagerX11::GHOST_NDOFManagerX11(GHOST_System& sys)
#define MAX_LINE_LENGTH 100
- /* look for USB devices with Logitech's vendor ID */
- FILE *command_output = popen("lsusb -d 046d:", "r");
+ /* look for USB devices with Logitech or 3Dconnexion's vendor ID */
+ FILE *command_output = popen("lsusb | grep '046d:\\|256f:'", "r");
if (command_output) {
char line[MAX_LINE_LENGTH] = {0};
while (fgets(line, MAX_LINE_LENGTH, command_output)) {
@@ -58,7 +56,7 @@ GHOST_NDOFManagerX11::GHOST_NDOFManagerX11(GHOST_System& sys)
}
else {
#ifdef DEBUG
- /* annoying for official builds, just adds noise and most prople don't own these */
+ /* annoying for official builds, just adds noise and most people don't own these */
puts("ndof: spacenavd not found");
/* This isn't a hard error, just means the user doesn't have a 3D mouse. */
#endif
@@ -81,11 +79,11 @@ bool GHOST_NDOFManagerX11::available()
* this causes any proceeding event to have a very high 'dt' (time delta),
* many seconds for eg, causing the view to jump.
*
- * this workaround expect's continuous events, if we miss a motion event,
+ * this workaround expects continuous events, if we miss a motion event,
* immediately send a dummy event with no motion to ensure the finished state is reached.
*/
#define USE_FINISH_GLITCH_WORKAROUND
-
+/* TODO: make this available on all platforms */
#ifdef USE_FINISH_GLITCH_WORKAROUND
static bool motion_test_prev = false;
diff --git a/intern/ghost/intern/GHOST_System.cpp b/intern/ghost/intern/GHOST_System.cpp
index d1f2d5d87c8..1698d2f0f31 100644
--- a/intern/ghost/intern/GHOST_System.cpp
+++ b/intern/ghost/intern/GHOST_System.cpp
@@ -169,7 +169,7 @@ GHOST_TSuccess GHOST_System::beginFullScreen(const GHOST_DisplaySetting& setting
}
-GHOST_TSuccess GHOST_System::updateFullScreen(const GHOST_DisplaySetting& setting, GHOST_IWindow **window)
+GHOST_TSuccess GHOST_System::updateFullScreen(const GHOST_DisplaySetting& setting, GHOST_IWindow ** /*window*/)
{
GHOST_TSuccess success = GHOST_kFailure;
GHOST_ASSERT(m_windowManager, "GHOST_System::updateFullScreen(): invalid window manager");
@@ -295,6 +295,15 @@ GHOST_TSuccess GHOST_System::getButtonState(GHOST_TButtonMask mask, bool& isDown
return success;
}
+void GHOST_System::setNDOFDeadZone(float deadzone)
+{
+#ifdef WITH_INPUT_NDOF
+ this->m_ndofManager->setDeadZone(deadzone);
+#else
+ (void)deadzone;
+#endif
+}
+
GHOST_TSuccess GHOST_System::init()
{
m_timerManager = new GHOST_TimerManager();
@@ -350,6 +359,12 @@ GHOST_TSuccess GHOST_System::exit()
GHOST_TSuccess GHOST_System::createFullScreenWindow(GHOST_Window **window, const GHOST_DisplaySetting &settings,
const bool stereoVisual, const GHOST_TUns16 numOfAASamples)
{
+ GHOST_GLSettings glSettings = {0};
+
+ if (stereoVisual)
+ glSettings.flags |= GHOST_glStereoVisual;
+ glSettings.numOfAASamples = numOfAASamples;
+
/* note: don't use getCurrentDisplaySetting() because on X11 we may
* be zoomed in and the desktop may be bigger then the viewport. */
GHOST_ASSERT(m_displayManager, "GHOST_System::createFullScreenWindow(): invalid display manager");
@@ -359,14 +374,13 @@ GHOST_TSuccess GHOST_System::createFullScreenWindow(GHOST_Window **window, const
0, 0, settings.xPixels, settings.yPixels,
GHOST_kWindowStateNormal,
GHOST_kDrawingContextTypeOpenGL,
- stereoVisual,
- true, /* exclusive */
- numOfAASamples);
+ glSettings,
+ true /* exclusive */);
return (*window == NULL) ? GHOST_kFailure : GHOST_kSuccess;
}
-int GHOST_System::confirmQuit(GHOST_IWindow *window) const
+int GHOST_System::confirmQuit(GHOST_IWindow * /*window*/) const
{
return 1;
}
diff --git a/intern/ghost/intern/GHOST_System.h b/intern/ghost/intern/GHOST_System.h
index 79230b0f505..9dcba11527c 100644
--- a/intern/ghost/intern/GHOST_System.h
+++ b/intern/ghost/intern/GHOST_System.h
@@ -97,7 +97,7 @@ public:
* \param userData Placeholder for user data.
* \return A timer task (0 if timer task installation failed).
*/
- virtual GHOST_ITimerTask *installTimer(GHOST_TUns64 delay,
+ GHOST_ITimerTask *installTimer(GHOST_TUns64 delay,
GHOST_TUns64 interval,
GHOST_TimerProcPtr timerProc,
GHOST_TUserDataPtr userData = NULL);
@@ -107,7 +107,7 @@ public:
* \param timerTask Timer task to be removed.
* \return Indication of success.
*/
- virtual GHOST_TSuccess removeTimer(GHOST_ITimerTask *timerTask);
+ GHOST_TSuccess removeTimer(GHOST_ITimerTask *timerTask);
/***************************************************************************************
* Display/window management functionality
@@ -126,14 +126,14 @@ public:
* \param window Pointer to the window to be disposed.
* \return Indication of success.
*/
- virtual GHOST_TSuccess disposeWindow(GHOST_IWindow *window);
+ GHOST_TSuccess disposeWindow(GHOST_IWindow *window);
/**
* Returns whether a window is valid.
* \param window Pointer to the window to be checked.
* \return Indication of validity.
*/
- virtual bool validWindow(GHOST_IWindow *window);
+ bool validWindow(GHOST_IWindow *window);
/**
* Begins full screen mode.
@@ -143,7 +143,7 @@ public:
* This window is invalid after full screen has been ended.
* \return Indication of success.
*/
- virtual GHOST_TSuccess beginFullScreen(const GHOST_DisplaySetting& setting, GHOST_IWindow **window,
+ GHOST_TSuccess beginFullScreen(const GHOST_DisplaySetting& setting, GHOST_IWindow **window,
const bool stereoVisual, const GHOST_TUns16 numOfAASamples = 0);
/**
@@ -153,26 +153,26 @@ public:
*
* \return Indication of success.
*/
- virtual GHOST_TSuccess updateFullScreen(const GHOST_DisplaySetting& setting, GHOST_IWindow **window);
+ GHOST_TSuccess updateFullScreen(const GHOST_DisplaySetting& setting, GHOST_IWindow **window);
/**
* Ends full screen mode.
* \return Indication of success.
*/
- virtual GHOST_TSuccess endFullScreen(void);
+ GHOST_TSuccess endFullScreen(void);
/**
* Returns current full screen mode status.
* \return The current status.
*/
- virtual bool getFullScreen(void);
+ bool getFullScreen(void);
/**
* Native pixel size support (MacBook 'retina').
* \return The pixel size in float.
*/
- virtual bool useNativePixel(void);
+ bool useNativePixel(void);
bool m_nativePixel;
/***************************************************************************************
@@ -192,21 +192,21 @@ public:
* The event stack will be empty afterwards.
* \return Indication as to whether any of the consumers handled the events.
*/
- virtual bool dispatchEvents();
+ bool dispatchEvents();
/**
* Adds the given event consumer to our list.
* \param consumer The event consumer to add.
* \return Indication of success.
*/
- virtual GHOST_TSuccess addEventConsumer(GHOST_IEventConsumer *consumer);
+ GHOST_TSuccess addEventConsumer(GHOST_IEventConsumer *consumer);
/**
* Remove the given event consumer to our list.
* \param consumer The event consumer to remove.
* \return Indication of success.
*/
- virtual GHOST_TSuccess removeEventConsumer(GHOST_IEventConsumer *consumer);
+ GHOST_TSuccess removeEventConsumer(GHOST_IEventConsumer *consumer);
/***************************************************************************************
* Cursor management functionality
@@ -227,7 +227,7 @@ public:
* \param isDown The state of a modifier key (true == pressed).
* \return Indication of success.
*/
- virtual GHOST_TSuccess getModifierKeyState(GHOST_TModifierKeyMask mask, bool& isDown) const;
+ GHOST_TSuccess getModifierKeyState(GHOST_TModifierKeyMask mask, bool& isDown) const;
/**
* Returns the state of a mouse button (ouside the message queue).
@@ -235,9 +235,19 @@ public:
* \param isDown Button state.
* \return Indication of success.
*/
- virtual GHOST_TSuccess getButtonState(GHOST_TButtonMask mask, bool& isDown) const;
+ GHOST_TSuccess getButtonState(GHOST_TButtonMask mask, bool& isDown) const;
/***************************************************************************************
+ * Access to 3D mouse.
+ ***************************************************************************************/
+
+ /**
+ * Sets 3D mouse deadzone
+ * \param deadzone: Deadzone of the 3D mouse (both for rotation and pan) relative to full range
+ */
+ void setNDOFDeadZone(float deadzone);
+
+ /***************************************************************************************
* Other (internal) functionality.
***************************************************************************************/
@@ -247,28 +257,28 @@ public:
* Do not delete the event!
* \param event The event to push on the stack.
*/
- virtual GHOST_TSuccess pushEvent(GHOST_IEvent *event);
+ GHOST_TSuccess pushEvent(GHOST_IEvent *event);
/**
* \return The timer manager.
*/
- inline virtual GHOST_TimerManager *getTimerManager() const;
+ inline GHOST_TimerManager *getTimerManager() const;
/**
* \return A pointer to our event manager.
*/
- virtual inline GHOST_EventManager *getEventManager() const;
+ inline GHOST_EventManager *getEventManager() const;
/**
* \return A pointer to our window manager.
*/
- virtual inline GHOST_WindowManager *getWindowManager() const;
+ inline GHOST_WindowManager *getWindowManager() const;
#ifdef WITH_INPUT_NDOF
/**
* \return A pointer to our n-degree of freedom manager.
*/
- virtual inline GHOST_NDOFManager *getNDOFManager() const;
+ inline GHOST_NDOFManager *getNDOFManager() const;
#endif
/**
@@ -326,7 +336,7 @@ protected:
* \param window The window created.
* \return Indication of success.
*/
- virtual GHOST_TSuccess createFullScreenWindow(GHOST_Window **window, const GHOST_DisplaySetting &settings,
+ GHOST_TSuccess createFullScreenWindow(GHOST_Window **window, const GHOST_DisplaySetting &settings,
const bool stereoVisual, const GHOST_TUns16 numOfAASamples = 0);
/** The display manager (platform dependent). */
diff --git a/intern/ghost/intern/GHOST_SystemCocoa.h b/intern/ghost/intern/GHOST_SystemCocoa.h
index 9b30abe75d5..3d6b40ee541 100644
--- a/intern/ghost/intern/GHOST_SystemCocoa.h
+++ b/intern/ghost/intern/GHOST_SystemCocoa.h
@@ -71,7 +71,7 @@ public:
* Based on ANSI clock() routine.
* \return The number of milliseconds.
*/
- virtual GHOST_TUns64 getMilliSeconds() const;
+ GHOST_TUns64 getMilliSeconds() const;
/***************************************************************************************
* Display/window management functionality
@@ -81,18 +81,18 @@ public:
* Returns the number of displays on this system.
* \return The number of displays.
*/
- virtual GHOST_TUns8 getNumDisplays() const;
+ GHOST_TUns8 getNumDisplays() const;
/**
* Returns the dimensions of the main display on this system.
* \return The dimension of the main display.
*/
- virtual void getMainDisplayDimensions(GHOST_TUns32& width, GHOST_TUns32& height) const;
+ void getMainDisplayDimensions(GHOST_TUns32& width, GHOST_TUns32& height) const;
/** Returns the combine dimensions of all monitors.
* \return The dimension of the workspace.
*/
- virtual void getAllDisplayDimensions(GHOST_TUns32& width, GHOST_TUns32& height) const;
+ void getAllDisplayDimensions(GHOST_TUns32& width, GHOST_TUns32& height) const;
/**
* Create a new window.
@@ -105,12 +105,12 @@ public:
* \param height The height the window.
* \param state The state of the window when opened.
* \param type The type of drawing context installed in this window.
- * \param stereoVisual Stereo visual for quad buffered stereo.
- * \param numOfAASamples Number of samples used for AA (zero if no AA)
+ * \param glSettings: Misc OpenGL settings.
+ * \param exclusive: Use to show the window ontop and ignore others (used fullscreen).
* \param parentWindow Parent (embedder) window
* \return The new window (or 0 if creation failed).
*/
- virtual GHOST_IWindow *createWindow(
+ GHOST_IWindow *createWindow(
const STR_String& title,
GHOST_TInt32 left,
GHOST_TInt32 top,
@@ -118,9 +118,8 @@ public:
GHOST_TUns32 height,
GHOST_TWindowState state,
GHOST_TDrawingContextType type,
- const bool stereoVisual = false,
- const bool exclusive = false,
- const GHOST_TUns16 numOfAASamples = 0,
+ GHOST_GLSettings glSettings,
+ const bool exclusive = false,
const GHOST_TEmbedderWindowID parentWindow = 0
);
@@ -133,7 +132,7 @@ public:
* \param waitForEvent Flag to wait for an event (or return immediately).
* \return Indication of the presence of events.
*/
- virtual bool processEvents(bool waitForEvent);
+ bool processEvents(bool waitForEvent);
/**
* Handle User request to quit, from Menu bar Quit, and Cmd+Q
@@ -169,7 +168,7 @@ public:
* \param y The y-coordinate of the cursor.
* \return Indication of success.
*/
- virtual GHOST_TSuccess getCursorPosition(GHOST_TInt32& x, GHOST_TInt32& y) const;
+ GHOST_TSuccess getCursorPosition(GHOST_TInt32& x, GHOST_TInt32& y) const;
/**
* Updates the location of the cursor (location in screen coordinates).
@@ -177,7 +176,7 @@ public:
* \param y The y-coordinate of the cursor.
* \return Indication of success.
*/
- virtual GHOST_TSuccess setCursorPosition(GHOST_TInt32 x, GHOST_TInt32 y);
+ GHOST_TSuccess setCursorPosition(GHOST_TInt32 x, GHOST_TInt32 y);
/***************************************************************************************
* Access to mouse button and keyboard states.
@@ -188,28 +187,28 @@ public:
* \param keys The state of all modifier keys (true == pressed).
* \return Indication of success.
*/
- virtual GHOST_TSuccess getModifierKeys(GHOST_ModifierKeys& keys) const;
+ GHOST_TSuccess getModifierKeys(GHOST_ModifierKeys& keys) const;
/**
* Returns the state of the mouse buttons (ouside the message queue).
* \param buttons The state of the buttons.
* \return Indication of success.
*/
- virtual GHOST_TSuccess getButtons(GHOST_Buttons& buttons) const;
+ GHOST_TSuccess getButtons(GHOST_Buttons& buttons) const;
/**
* Returns Clipboard data
* \param selection Indicate which buffer to return
* \return Returns the selected buffer
*/
- virtual GHOST_TUns8 *getClipboard(bool selection) const;
+ GHOST_TUns8 *getClipboard(bool selection) const;
/**
* Puts buffer to system clipboard
* \param buffer The buffer to be copied
* \param selection Indicates which buffer to copy too, only used on X11
*/
- virtual void putClipboard(GHOST_TInt8 *buffer, bool selection) const;
+ void putClipboard(GHOST_TInt8 *buffer, bool selection) const;
/**
* Handles a window event. Called by GHOST_WindowCocoa window delegate
@@ -268,7 +267,7 @@ protected:
* For now, it just registers the window class (WNDCLASS).
* \return A success value.
*/
- virtual GHOST_TSuccess init();
+ GHOST_TSuccess init();
/**
* Performs the actual cursor position update (location in screen coordinates).
diff --git a/intern/ghost/intern/GHOST_SystemCocoa.mm b/intern/ghost/intern/GHOST_SystemCocoa.mm
index 7b08c46b65d..b9686e5af9b 100644
--- a/intern/ghost/intern/GHOST_SystemCocoa.mm
+++ b/intern/ghost/intern/GHOST_SystemCocoa.mm
@@ -22,6 +22,7 @@
*
* Contributors: Maarten Gribnau 05/2001
* Damien Plisson 09/2009
+ * Jens Verwiebe 10/2014
*
* ***** END GPL LICENSE BLOCK *****
*/
@@ -56,6 +57,7 @@
#include "AssertMacros.h"
+
#pragma mark KeyMap, mouse converters
static GHOST_TButtonMask convertButton(int button)
@@ -71,6 +73,10 @@ static GHOST_TButtonMask convertButton(int button)
return GHOST_kButtonMaskButton4;
case 4:
return GHOST_kButtonMaskButton5;
+ case 5:
+ return GHOST_kButtonMaskButton6;
+ case 6:
+ return GHOST_kButtonMaskButton7;
default:
return GHOST_kButtonMaskLeft;
}
@@ -203,6 +209,7 @@ static GHOST_TKey convertKey(int rawCode, unichar recvChar, UInt16 keyAction)
return GHOST_kKeyUnknown;
default:
+ {
/* alphanumerical or punctuation key that is remappable in int'l keyboards */
if ((recvChar >= 'A') && (recvChar <= 'Z')) {
return (GHOST_TKey) (recvChar - 'A' + GHOST_kKeyA);
@@ -211,27 +218,25 @@ static GHOST_TKey convertKey(int rawCode, unichar recvChar, UInt16 keyAction)
return (GHOST_TKey) (recvChar - 'a' + GHOST_kKeyA);
}
else {
-
- /* Leopard and Snow Leopard 64bit compatible API*/
- CFDataRef uchrHandle; /*the keyboard layout*/
- TISInputSourceRef kbdTISHandle;
-
- kbdTISHandle = TISCopyCurrentKeyboardLayoutInputSource();
- uchrHandle = (CFDataRef)TISGetInputSourceProperty(kbdTISHandle,kTISPropertyUnicodeKeyLayoutData);
- CFRelease(kbdTISHandle);
-
- /*get actual character value of the "remappable" keys in int'l keyboards,
- if keyboard layout is not correctly reported (e.g. some non Apple keyboards in Tiger),
- then fallback on using the received charactersIgnoringModifiers */
- if (uchrHandle)
- {
- UInt32 deadKeyState=0;
- UniCharCount actualStrLength=0;
+ /* Leopard and Snow Leopard 64bit compatible API*/
+ CFDataRef uchrHandle; /*the keyboard layout*/
+ TISInputSourceRef kbdTISHandle;
- UCKeyTranslate((UCKeyboardLayout*)CFDataGetBytePtr(uchrHandle), rawCode, keyAction, 0,
- LMGetKbdType(), kUCKeyTranslateNoDeadKeysBit, &deadKeyState, 1, &actualStrLength, &recvChar);
+ kbdTISHandle = TISCopyCurrentKeyboardLayoutInputSource();
+ uchrHandle = (CFDataRef)TISGetInputSourceProperty(kbdTISHandle,kTISPropertyUnicodeKeyLayoutData);
+ CFRelease(kbdTISHandle);
- }
+ /*get actual character value of the "remappable" keys in int'l keyboards,
+ if keyboard layout is not correctly reported (e.g. some non Apple keyboards in Tiger),
+ then fallback on using the received charactersIgnoringModifiers */
+ if (uchrHandle) {
+ UInt32 deadKeyState=0;
+ UniCharCount actualStrLength=0;
+
+ UCKeyTranslate((UCKeyboardLayout*)CFDataGetBytePtr(uchrHandle), rawCode, keyAction, 0,
+ LMGetKbdType(), kUCKeyTranslateNoDeadKeysBit, &deadKeyState, 1, &actualStrLength, &recvChar);
+
+ }
switch (recvChar) {
case '-': return GHOST_kKeyMinus;
@@ -249,13 +254,11 @@ static GHOST_TKey convertKey(int rawCode, unichar recvChar, UInt16 keyAction)
return GHOST_kKeyUnknown;
}
}
+ }
}
return GHOST_kKeyUnknown;
}
-
-#pragma mark defines for 10.6 api not documented in 10.5
-
#pragma mark Utility functions
#define FIRSTFILEBUFLG 512
@@ -271,7 +274,7 @@ extern "C" int GHOST_HACK_getFirstFile(char buf[FIRSTFILEBUFLG])
return 1;
}
else {
- return 0;
+ return 0;
}
}
@@ -334,12 +337,8 @@ extern "C" int GHOST_HACK_getFirstFile(char buf[FIRSTFILEBUFLG])
@end
-
-
#pragma mark initialization/finalization
-char GHOST_user_locale[128]; // Global current user locale
-
GHOST_SystemCocoa::GHOST_SystemCocoa()
{
int mib[2];
@@ -377,15 +376,6 @@ GHOST_SystemCocoa::GHOST_SystemCocoa()
rstring = NULL;
m_ignoreWindowSizedMessages = false;
-
- //Get current locale
- NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
- CFLocaleRef myCFLocale = CFLocaleCopyCurrent();
- NSLocale * myNSLocale = (NSLocale *) myCFLocale;
- [myNSLocale autorelease];
- NSString *nsIdentifier = [myNSLocale localeIdentifier];
- strncpy(GHOST_user_locale, [nsIdentifier UTF8String], sizeof(GHOST_user_locale) - 1);
- [pool drain];
}
GHOST_SystemCocoa::~GHOST_SystemCocoa()
@@ -544,9 +534,8 @@ GHOST_IWindow* GHOST_SystemCocoa::createWindow(
GHOST_TUns32 height,
GHOST_TWindowState state,
GHOST_TDrawingContextType type,
- bool stereoVisual,
+ GHOST_GLSettings glSettings,
const bool exclusive,
- const GHOST_TUns16 numOfAASamples,
const GHOST_TEmbedderWindowID parentWindow
)
{
@@ -565,27 +554,23 @@ GHOST_IWindow* GHOST_SystemCocoa::createWindow(
// Add contentRect.origin.y to respect docksize
bottom = bottom > contentRect.origin.y ? bottom + contentRect.origin.y : contentRect.origin.y;
- window = new GHOST_WindowCocoa (this, title, left, bottom, width, height, state, type, stereoVisual, numOfAASamples);
+ window = new GHOST_WindowCocoa (this, title, left, bottom, width, height, state, type, ((glSettings.flags & GHOST_glStereoVisual) != 0), glSettings.numOfAASamples);
- if (window) {
- if (window->getValid()) {
- // Store the pointer to the window
- GHOST_ASSERT(m_windowManager, "m_windowManager not initialized");
- m_windowManager->addWindow(window);
- m_windowManager->setActiveWindow(window);
- //Need to tell window manager the new window is the active one (Cocoa does not send the event activate upon window creation)
- pushEvent(new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowActivate, window));
- pushEvent(new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowSize, window));
- }
- else {
- GHOST_PRINT("GHOST_SystemCocoa::createWindow(): window invalid\n");
- delete window;
- window = 0;
- }
+ if (window->getValid()) {
+ // Store the pointer to the window
+ GHOST_ASSERT(m_windowManager, "m_windowManager not initialized");
+ m_windowManager->addWindow(window);
+ m_windowManager->setActiveWindow(window);
+ //Need to tell window manager the new window is the active one (Cocoa does not send the event activate upon window creation)
+ pushEvent(new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowActivate, window));
+ pushEvent(new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowSize, window));
}
else {
- GHOST_PRINT("GHOST_SystemCocoa::createWindow(): could not create window\n");
+ GHOST_PRINT("GHOST_SystemCocoa::createWindow(): window invalid\n");
+ delete window;
+ window = 0;
}
+
[pool drain];
return window;
}
@@ -672,7 +657,6 @@ GHOST_TSuccess GHOST_SystemCocoa::getButtons(GHOST_Buttons& buttons) const
}
-
#pragma mark Event handlers
/**
@@ -740,7 +724,7 @@ bool GHOST_SystemCocoa::processEvents(bool waitForEvent)
// For some reason NSApp is swallowing the key up events when modifier
// key is pressed, even if there seems to be no apparent reason to do
// so, as a workaround we always handle these up events.
- if ([event type] == NSKeyUp && (([event modifierFlags] & NSCommandKeyMask) || ([event modifierFlags] & NSAlternateKeyMask)))
+ if ([event type] == NSKeyUp && ([event modifierFlags] & (NSCommandKeyMask | NSAlternateKeyMask)))
handleKeyEvent(event);
[NSApp sendEvent:event];
@@ -812,58 +796,57 @@ GHOST_TSuccess GHOST_SystemCocoa::handleWindowEvent(GHOST_TEventType eventType,
if (!validWindow(window)) {
return GHOST_kFailure;
}
- switch (eventType) {
- case GHOST_kEventWindowClose:
- // check for index of mainwindow as it would quit blender without dialog and discard
- if ([windowsList count] > 1 && window->getCocoaWindow() != [windowsList objectAtIndex:[windowsList count] - 1]) {
- pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowClose, window) );
- }
- else {
- handleQuitRequest(); // -> quit dialog
- }
- break;
- case GHOST_kEventWindowActivate:
- m_windowManager->setActiveWindow(window);
- window->loadCursor(window->getCursorVisibility(), window->getCursorShape());
- pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowActivate, window) );
- break;
- case GHOST_kEventWindowDeactivate:
- m_windowManager->setWindowInactive(window);
- pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowDeactivate, window) );
- break;
- case GHOST_kEventWindowUpdate:
- if (m_nativePixel) {
- window->setNativePixelSize();
- pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventNativeResolutionChange, window) );
- }
- pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowUpdate, window) );
- break;
- case GHOST_kEventWindowMove:
- pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowMove, window) );
- break;
- case GHOST_kEventWindowSize:
- if (!m_ignoreWindowSizedMessages)
- {
- //Enforce only one resize message per event loop (coalescing all the live resize messages)
- window->updateDrawingContext();
- pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowSize, window) );
- //Mouse up event is trapped by the resizing event loop, so send it anyway to the window manager
- pushEvent(new GHOST_EventButton(getMilliSeconds(), GHOST_kEventButtonUp, window, convertButton(0)));
- //m_ignoreWindowSizedMessages = true;
- }
- break;
- case GHOST_kEventNativeResolutionChange:
-
- if (m_nativePixel) {
- window->setNativePixelSize();
- pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventNativeResolutionChange, window) );
- }
+ switch (eventType) {
+ case GHOST_kEventWindowClose:
+ // check for index of mainwindow as it would quit blender without dialog and discard
+ if ([windowsList count] > 1 && window->getCocoaWindow() != [windowsList objectAtIndex:[windowsList count] - 1]) {
+ pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowClose, window) );
+ }
+ else {
+ handleQuitRequest(); // -> quit dialog
+ }
+ break;
+ case GHOST_kEventWindowActivate:
+ m_windowManager->setActiveWindow(window);
+ window->loadCursor(window->getCursorVisibility(), window->getCursorShape());
+ pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowActivate, window) );
+ break;
+ case GHOST_kEventWindowDeactivate:
+ m_windowManager->setWindowInactive(window);
+ pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowDeactivate, window) );
+ break;
+ case GHOST_kEventWindowUpdate:
+ if (m_nativePixel) {
+ window->setNativePixelSize();
+ pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventNativeResolutionChange, window) );
+ }
+ pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowUpdate, window) );
+ break;
+ case GHOST_kEventWindowMove:
+ pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowMove, window) );
+ break;
+ case GHOST_kEventWindowSize:
+ if (!m_ignoreWindowSizedMessages) {
+ //Enforce only one resize message per event loop (coalescing all the live resize messages)
+ window->updateDrawingContext();
+ pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowSize, window) );
+ //Mouse up event is trapped by the resizing event loop, so send it anyway to the window manager
+ pushEvent(new GHOST_EventButton(getMilliSeconds(), GHOST_kEventButtonUp, window, convertButton(0)));
+ //m_ignoreWindowSizedMessages = true;
+ }
+ break;
+ case GHOST_kEventNativeResolutionChange:
+
+ if (m_nativePixel) {
+ window->setNativePixelSize();
+ pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventNativeResolutionChange, window) );
+ }
+
+ default:
+ return GHOST_kFailure;
+ break;
+ }
- default:
- return GHOST_kFailure;
- break;
- }
-
m_outsideLoopEventProcessed = true;
return GHOST_kSuccess;
}
@@ -902,7 +885,10 @@ GHOST_TSuccess GHOST_SystemCocoa::handleDraggingEvent(GHOST_TEventType eventType
if (!strArray) return GHOST_kFailure;
strArray->count = [droppedArray count];
- if (strArray->count == 0) return GHOST_kFailure;
+ if (strArray->count == 0) {
+ free(strArray);
+ return GHOST_kFailure;
+ }
strArray->strings = (GHOST_TUns8**) malloc(strArray->count*sizeof(GHOST_TUns8*));
@@ -1059,16 +1045,17 @@ GHOST_TSuccess GHOST_SystemCocoa::handleDraggingEvent(GHOST_TEventType eventType
}
eventData = (GHOST_TEventDataPtr) ibuf;
- }
+
break;
-
+ }
default:
return GHOST_kFailure;
break;
}
pushEvent(new GHOST_EventDragnDrop(getMilliSeconds(),eventType,draggedObjectType,window,mouseX,mouseY,eventData));
- }
+
break;
+ }
default:
return GHOST_kFailure;
}
@@ -1251,12 +1238,12 @@ bool GHOST_SystemCocoa::handleTabletEvent(void *eventPtr)
#if MAC_OS_X_VERSION_MAX_ALLOWED < 1070
enum {
- NSEventPhaseNone = 0,
- NSEventPhaseBegan = 0x1 << 0,
- NSEventPhaseStationary = 0x1 << 1,
- NSEventPhaseChanged = 0x1 << 2,
- NSEventPhaseEnded = 0x1 << 3,
- NSEventPhaseCancelled = 0x1 << 4,
+ NSEventPhaseNone = 0,
+ NSEventPhaseBegan = 0x1 << 0,
+ NSEventPhaseStationary = 0x1 << 1,
+ NSEventPhaseChanged = 0x1 << 2,
+ NSEventPhaseEnded = 0x1 << 3,
+ NSEventPhaseCancelled = 0x1 << 4,
};
typedef NSUInteger NSEventPhase;
@@ -1609,7 +1596,6 @@ GHOST_TSuccess GHOST_SystemCocoa::handleKeyEvent(void *eventPtr)
}
-
#pragma mark Clipboard get/set
GHOST_TUns8* GHOST_SystemCocoa::getClipboard(bool selection) const
diff --git a/intern/ghost/intern/GHOST_SystemNULL.h b/intern/ghost/intern/GHOST_SystemNULL.h
index 77a741c2efb..868416cd227 100644
--- a/intern/ghost/intern/GHOST_SystemNULL.h
+++ b/intern/ghost/intern/GHOST_SystemNULL.h
@@ -75,12 +75,12 @@ public:
GHOST_TUns32 height,
GHOST_TWindowState state,
GHOST_TDrawingContextType type,
- bool stereoVisual,
+ GHOST_GLSettings glSettings,
bool exclusive,
- const GHOST_TUns16 numOfAASamples,
const GHOST_TEmbedderWindowID parentWindow)
{
- return new GHOST_WindowNULL(this, title, left, top, width, height, state, parentWindow, type, stereoVisual, 1);
+ return new GHOST_WindowNULL(this, title, left, top, width, height, state, parentWindow, type,
+ ((glSettings.flags & GHOST_glStereoVisual) != 0), 1);
}
};
diff --git a/intern/ghost/intern/GHOST_SystemPathsCocoa.h b/intern/ghost/intern/GHOST_SystemPathsCocoa.h
index cd8d161ff9c..1c76284857c 100644
--- a/intern/ghost/intern/GHOST_SystemPathsCocoa.h
+++ b/intern/ghost/intern/GHOST_SystemPathsCocoa.h
@@ -57,20 +57,20 @@ public:
* "unpack and run" path, then look for properly installed path, including versioning.
* \return Unsigned char string pointing to system dir (eg /usr/share/blender/).
*/
- virtual const GHOST_TUns8 *getSystemDir(int version, const char *versionstr) const;
+ const GHOST_TUns8 *getSystemDir(int version, const char *versionstr) const;
/**
* Determine the base dir in which user configuration is stored, including versioning.
* If needed, it will create the base directory.
* \return Unsigned char string pointing to user dir (eg ~/.blender/).
*/
- virtual const GHOST_TUns8 *getUserDir(int version, const char *versionstr) const;
+ const GHOST_TUns8 *getUserDir(int version, const char *versionstr) const;
/**
* Determine the directory of the current binary
* \return Unsigned char string pointing to the binary dir
*/
- virtual const GHOST_TUns8 *getBinaryDir() const;
+ const GHOST_TUns8 *getBinaryDir() const;
/**
* Add the file to the operating system most recently used files
diff --git a/intern/ghost/intern/GHOST_SystemPathsCocoa.mm b/intern/ghost/intern/GHOST_SystemPathsCocoa.mm
index 50ad91eeb99..36ae534da87 100644
--- a/intern/ghost/intern/GHOST_SystemPathsCocoa.mm
+++ b/intern/ghost/intern/GHOST_SystemPathsCocoa.mm
@@ -24,14 +24,7 @@
* ***** END GPL LICENSE BLOCK *****
*/
-#import <Cocoa/Cocoa.h>
-
-/*For the currently not ported to Cocoa keyboard layout functions (64bit & 10.6 compatible)*/
-#include <Carbon/Carbon.h>
-
-#include <sys/time.h>
-#include <sys/types.h>
-#include <sys/sysctl.h>
+#import <Foundation/Foundation.h>
#include "GHOST_SystemPathsCocoa.h"
diff --git a/intern/ghost/intern/GHOST_SystemPathsWin32.h b/intern/ghost/intern/GHOST_SystemPathsWin32.h
index c074a7902b8..b63d20bfcbd 100644
--- a/intern/ghost/intern/GHOST_SystemPathsWin32.h
+++ b/intern/ghost/intern/GHOST_SystemPathsWin32.h
@@ -60,7 +60,7 @@ public:
/**
* Destructor.
*/
- virtual ~GHOST_SystemPathsWin32();
+ ~GHOST_SystemPathsWin32();
/**
* Determine the base dir in which shared resources are located. It will first try to use
diff --git a/intern/ghost/intern/GHOST_SystemPathsX11.cpp b/intern/ghost/intern/GHOST_SystemPathsX11.cpp
index e2d9733a9b2..5473e404593 100644
--- a/intern/ghost/intern/GHOST_SystemPathsX11.cpp
+++ b/intern/ghost/intern/GHOST_SystemPathsX11.cpp
@@ -121,7 +121,7 @@ const GHOST_TUns8 *GHOST_SystemPathsX11::getBinaryDir() const
return NULL;
}
-void GHOST_SystemPathsX11::addToSystemRecentFiles(const char *filename) const
+void GHOST_SystemPathsX11::addToSystemRecentFiles(const char * /*filename*/) const
{
/* XXXXX TODO: Implementation for X11 if possible */
diff --git a/intern/ghost/intern/GHOST_SystemPathsX11.h b/intern/ghost/intern/GHOST_SystemPathsX11.h
index 1b5710e0f57..23cc2e4b104 100644
--- a/intern/ghost/intern/GHOST_SystemPathsX11.h
+++ b/intern/ghost/intern/GHOST_SystemPathsX11.h
@@ -48,7 +48,7 @@ public:
/**
* Destructor.
*/
- virtual ~GHOST_SystemPathsX11();
+ ~GHOST_SystemPathsX11();
/**
* Determine the base dir in which shared resources are located. It will first try to use
diff --git a/intern/ghost/intern/GHOST_SystemSDL.cpp b/intern/ghost/intern/GHOST_SystemSDL.cpp
index 1d2401e6f71..e9768e4b845 100644
--- a/intern/ghost/intern/GHOST_SystemSDL.cpp
+++ b/intern/ghost/intern/GHOST_SystemSDL.cpp
@@ -67,9 +67,8 @@ GHOST_SystemSDL::createWindow(const STR_String& title,
GHOST_TUns32 height,
GHOST_TWindowState state,
GHOST_TDrawingContextType type,
- const bool stereoVisual,
+ GHOST_GLSettings glSettings,
const bool exclusive,
- const GHOST_TUns16 numOfAASamples,
const GHOST_TEmbedderWindowID parentWindow
)
{
@@ -78,8 +77,8 @@ GHOST_SystemSDL::createWindow(const STR_String& title,
window = new GHOST_WindowSDL(this, title,
left, top, width, height,
state, parentWindow, type,
- stereoVisual, exclusive,
- numOfAASamples);
+ ((glSettings.flags & GHOST_glStereoVisual) != 0), exclusive,
+ glSettings.numOfAASamples);
if (window) {
if (GHOST_kWindowStateFullScreen == state) {
@@ -321,8 +320,9 @@ GHOST_SystemSDL::processEvent(SDL_Event *sdl_event)
g_event = new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowClose, window);
break;
}
- }
+
break;
+ }
case SDL_QUIT:
g_event = new GHOST_Event(getMilliSeconds(), GHOST_kEventQuit, NULL);
break;
@@ -418,8 +418,8 @@ GHOST_SystemSDL::processEvent(SDL_Event *sdl_event)
GHOST_WindowSDL *window = findGhostWindow(SDL_GetWindowFromID_fallback(sdl_sub_evt.windowID));
assert(window != NULL);
g_event = new GHOST_EventWheel(getMilliSeconds(), window, sdl_sub_evt.y);
- }
break;
+ }
case SDL_KEYDOWN:
case SDL_KEYUP:
{
@@ -489,8 +489,8 @@ GHOST_SystemSDL::processEvent(SDL_Event *sdl_event)
}
g_event = new GHOST_EventKey(getMilliSeconds(), type, window, gkey, sym, NULL);
- }
break;
+ }
}
if (g_event) {
diff --git a/intern/ghost/intern/GHOST_SystemSDL.h b/intern/ghost/intern/GHOST_SystemSDL.h
index 5ad4fe09833..6f4ecec586b 100644
--- a/intern/ghost/intern/GHOST_SystemSDL.h
+++ b/intern/ghost/intern/GHOST_SystemSDL.h
@@ -108,9 +108,8 @@ private:
GHOST_TUns32 height,
GHOST_TWindowState state,
GHOST_TDrawingContextType type,
- const bool stereoVisual,
+ GHOST_GLSettings glSettings,
const bool exclusive = false,
- const GHOST_TUns16 numOfAASamples = 0,
const GHOST_TEmbedderWindowID parentWindow = 0
);
diff --git a/intern/ghost/intern/GHOST_SystemWin32.cpp b/intern/ghost/intern/GHOST_SystemWin32.cpp
index 3b95373f800..4f3b1127a18 100644
--- a/intern/ghost/intern/GHOST_SystemWin32.cpp
+++ b/intern/ghost/intern/GHOST_SystemWin32.cpp
@@ -31,11 +31,6 @@
* \author Maarten Gribnau
*/
-#ifdef WITH_GHOST_DEBUG
-# include <iostream>
-#endif
-
-#include <stdio.h> // [mce] temporary debug, remove soon!
#include "GHOST_SystemWin32.h"
#include "GHOST_EventDragnDrop.h"
@@ -152,7 +147,7 @@ static void initRawInput()
if (RegisterRawInputDevices(devices, DEVICE_COUNT, sizeof(RAWINPUTDEVICE)))
; // yay!
else
- printf("could not register for RawInput: %d\n", (int)GetLastError());
+ GHOST_PRINTF("could not register for RawInput: %d\n", (int)GetLastError());
#undef DEVICE_COUNT
}
@@ -231,44 +226,37 @@ GHOST_IWindow *GHOST_SystemWin32::createWindow(
GHOST_TInt32 left, GHOST_TInt32 top,
GHOST_TUns32 width, GHOST_TUns32 height,
GHOST_TWindowState state, GHOST_TDrawingContextType type,
- bool stereoVisual,
+ GHOST_GLSettings glSettings,
const bool exclusive,
- const GHOST_TUns16 numOfAASamples,
const GHOST_TEmbedderWindowID parentWindow)
{
- GHOST_Window *window = 0;
- window = new GHOST_WindowWin32(this, title, left, top, width, height, state, type, stereoVisual, numOfAASamples, parentWindow);
- if (window) {
- if (window->getValid()) {
- // Store the pointer to the window
-// if (state != GHOST_kWindowStateFullScreen) {
- m_windowManager->addWindow(window);
- m_windowManager->setActiveWindow(window);
-// }
- }
- else {
-
- // Invalid parent window hwnd
- if (((GHOST_WindowWin32 *)window)->getNextWindow() == NULL) {
- delete window;
- window = 0;
- return window;
- }
-
- // An invalid window could be one that was used to test for AA
- window = ((GHOST_WindowWin32 *)window)->getNextWindow();
-
- // If another window is found, let the wm know about that one, but not the old one
- if (window->getValid()) {
- m_windowManager->addWindow(window);
- }
- else {
- delete window;
- window = 0;
- }
-
- }
+ GHOST_WindowWin32 *window =
+ new GHOST_WindowWin32(
+ this,
+ title,
+ left,
+ top,
+ width,
+ height,
+ state,
+ type,
+ ((glSettings.flags & GHOST_glStereoVisual) != 0),
+ ((glSettings.flags & GHOST_glWarnSupport) != 0),
+ glSettings.numOfAASamples,
+ parentWindow,
+ ((glSettings.flags & GHOST_glDebugContext) != 0));
+
+ if (window->getValid()) {
+ // Store the pointer to the window
+ m_windowManager->addWindow(window);
+ m_windowManager->setActiveWindow(window);
}
+ else {
+ GHOST_PRINT("GHOST_SystemWin32::createWindow(): window invalid\n");
+ delete window;
+ window = 0;
+ }
+
return window;
}
@@ -440,7 +428,7 @@ GHOST_TSuccess GHOST_SystemWin32::exit()
return GHOST_System::exit();
}
-GHOST_TKey GHOST_SystemWin32::hardKey(GHOST_IWindow *window, RAWINPUT const &raw, int *keyDown, char *vk)
+GHOST_TKey GHOST_SystemWin32::hardKey(RAWINPUT const &raw, int *keyDown, char *vk)
{
GHOST_SystemWin32 *system = (GHOST_SystemWin32 *)getSystem();
GHOST_TKey key = GHOST_kKeyUnknown;
@@ -452,7 +440,7 @@ GHOST_TKey GHOST_SystemWin32::hardKey(GHOST_IWindow *window, RAWINPUT const &raw
unsigned int msg = raw.data.keyboard.Message;
*keyDown = !(raw.data.keyboard.Flags & RI_KEY_BREAK) && msg != WM_KEYUP && msg != WM_SYSKEYUP;
- key = this->convertKey(window, raw.data.keyboard.VKey, raw.data.keyboard.MakeCode, (raw.data.keyboard.Flags & (RI_KEY_E1 | RI_KEY_E0)));
+ key = this->convertKey(raw.data.keyboard.VKey, raw.data.keyboard.MakeCode, (raw.data.keyboard.Flags & (RI_KEY_E1 | RI_KEY_E0)));
// extra handling of modifier keys: don't send repeats out from GHOST
if (key >= GHOST_kKeyLeftShift && key <= GHOST_kKeyRightAlt) {
@@ -516,19 +504,24 @@ GHOST_TKey GHOST_SystemWin32::hardKey(GHOST_IWindow *window, RAWINPUT const &raw
//! note: this function can be extended to include other exotic cases as they arise.
// This function was added in response to bug [#25715]
-GHOST_TKey GHOST_SystemWin32::processSpecialKey(GHOST_IWindow *window, short vKey, short scanCode) const
+// This is going to be a long list [T42426]
+GHOST_TKey GHOST_SystemWin32::processSpecialKey(short vKey, short scanCode) const
{
GHOST_TKey key = GHOST_kKeyUnknown;
switch (PRIMARYLANGID(m_langId)) {
case LANG_FRENCH:
if (vKey == VK_OEM_8) key = GHOST_kKeyF13; // oem key; used purely for shortcuts .
break;
+ case LANG_ENGLISH:
+ if (SUBLANGID(m_langId) == SUBLANG_ENGLISH_UK && vKey == VK_OEM_8) // "`¬"
+ key = GHOST_kKeyAccentGrave;
+ break;
}
return key;
}
-GHOST_TKey GHOST_SystemWin32::convertKey(GHOST_IWindow *window, short vKey, short scanCode, short extend) const
+GHOST_TKey GHOST_SystemWin32::convertKey(short vKey, short scanCode, short extend) const
{
GHOST_TKey key;
@@ -636,7 +629,7 @@ GHOST_TKey GHOST_SystemWin32::convertKey(GHOST_IWindow *window, short vKey, shor
case VK_SCROLL: key = GHOST_kKeyScrollLock; break;
case VK_CAPITAL: key = GHOST_kKeyCapsLock; break;
case VK_OEM_8:
- key = ((GHOST_SystemWin32 *)getSystem())->processSpecialKey(window, vKey, scanCode);
+ key = ((GHOST_SystemWin32 *)getSystem())->processSpecialKey(vKey, scanCode);
break;
case VK_MEDIA_PLAY_PAUSE: key = GHOST_kKeyMediaPlay; break;
case VK_MEDIA_STOP: key = GHOST_kKeyMediaStop; break;
@@ -653,18 +646,17 @@ GHOST_TKey GHOST_SystemWin32::convertKey(GHOST_IWindow *window, short vKey, shor
GHOST_EventButton *GHOST_SystemWin32::processButtonEvent(
GHOST_TEventType type,
- GHOST_IWindow *window,
+ GHOST_WindowWin32 *window,
GHOST_TButtonMask mask)
{
return new GHOST_EventButton(getSystem()->getMilliSeconds(), type, window, mask);
}
-GHOST_EventCursor *GHOST_SystemWin32::processCursorEvent(GHOST_TEventType type, GHOST_IWindow *Iwindow)
+GHOST_EventCursor *GHOST_SystemWin32::processCursorEvent(GHOST_TEventType type, GHOST_WindowWin32 *window)
{
GHOST_TInt32 x_screen, y_screen;
GHOST_SystemWin32 *system = (GHOST_SystemWin32 *) getSystem();
- GHOST_WindowWin32 *window = (GHOST_WindowWin32 *) Iwindow;
system->getCursorPosition(x_screen, y_screen);
@@ -716,27 +708,27 @@ GHOST_EventCursor *GHOST_SystemWin32::processCursorEvent(GHOST_TEventType type,
}
-GHOST_EventWheel *GHOST_SystemWin32::processWheelEvent(GHOST_IWindow *window, WPARAM wParam, LPARAM lParam)
+GHOST_EventWheel *GHOST_SystemWin32::processWheelEvent(GHOST_WindowWin32 *window, WPARAM wParam, LPARAM lParam)
{
// short fwKeys = LOWORD(wParam); // key flags
int zDelta = (short) HIWORD(wParam); // wheel rotation
// zDelta /= WHEEL_DELTA;
// temporary fix below: microsoft now has added more precision, making the above division not work
- if (zDelta <= 0) zDelta = -1; else zDelta = 1;
-
+ zDelta = (zDelta <= 0) ? -1 : 1;
+
// short xPos = (short) LOWORD(lParam); // horizontal position of pointer
// short yPos = (short) HIWORD(lParam); // vertical position of pointer
return new GHOST_EventWheel(getSystem()->getMilliSeconds(), window, zDelta);
}
-GHOST_EventKey *GHOST_SystemWin32::processKeyEvent(GHOST_IWindow *window, RAWINPUT const &raw)
+GHOST_EventKey *GHOST_SystemWin32::processKeyEvent(GHOST_WindowWin32 *window, RAWINPUT const &raw)
{
int keyDown = 0;
char vk;
GHOST_SystemWin32 *system = (GHOST_SystemWin32 *)getSystem();
- GHOST_TKey key = system->hardKey(window, raw, &keyDown, &vk);
+ GHOST_TKey key = system->hardKey(raw, &keyDown, &vk);
GHOST_EventKey *event;
if (key != GHOST_kKeyUnknown) {
@@ -771,10 +763,8 @@ GHOST_EventKey *GHOST_SystemWin32::processKeyEvent(GHOST_IWindow *window, RAWINP
}
event = new GHOST_EventKey(system->getMilliSeconds(), keyDown ? GHOST_kEventKeyDown : GHOST_kEventKeyUp, window, key, ascii, utf8_char);
-
-#ifdef GHOST_DEBUG
- std::cout << ascii << std::endl;
-#endif
+
+ // GHOST_PRINTF("%c\n", ascii); // we already get this info via EventPrinter
}
else {
event = 0;
@@ -783,26 +773,35 @@ GHOST_EventKey *GHOST_SystemWin32::processKeyEvent(GHOST_IWindow *window, RAWINP
}
-GHOST_Event *GHOST_SystemWin32::processWindowEvent(GHOST_TEventType type, GHOST_IWindow *window)
+GHOST_Event *GHOST_SystemWin32::processWindowEvent(GHOST_TEventType type, GHOST_WindowWin32 *window)
{
- GHOST_System *system = (GHOST_System *)getSystem();
+ GHOST_SystemWin32 *system = (GHOST_SystemWin32 *)getSystem();
if (type == GHOST_kEventWindowActivate) {
system->getWindowManager()->setActiveWindow(window);
- ((GHOST_WindowWin32 *)window)->bringTabletContextToFront();
+ window->bringTabletContextToFront();
}
return new GHOST_Event(system->getMilliSeconds(), type, window);
}
+#ifdef WITH_INPUT_IME
+GHOST_Event *GHOST_SystemWin32::processImeEvent(GHOST_TEventType type, GHOST_WindowWin32 *window, GHOST_TEventImeData *data)
+{
+ GHOST_SystemWin32 *system = (GHOST_SystemWin32 *)getSystem();
+ return new GHOST_EventIME(system->getMilliSeconds(), type, window, data);
+}
+#endif
+
+
GHOST_TSuccess GHOST_SystemWin32::pushDragDropEvent(
GHOST_TEventType eventType,
GHOST_TDragnDropTypes draggedObjectType,
- GHOST_IWindow *window,
+ GHOST_WindowWin32 *window,
int mouseX, int mouseY,
void *data)
{
- GHOST_SystemWin32 *system = ((GHOST_SystemWin32 *)getSystem());
+ GHOST_SystemWin32 *system = (GHOST_SystemWin32 *)getSystem();
return system->pushEvent(new GHOST_EventDragnDrop(system->getMilliSeconds(),
eventType,
draggedObjectType,
@@ -832,7 +831,7 @@ bool GHOST_SystemWin32::processNDOF(RAWINPUT const &raw)
if (info.dwType == RIM_TYPEHID)
m_ndofManager->setDevice(info.hid.dwVendorId, info.hid.dwProductId);
else
- puts("<!> not a HID device... mouse/kb perhaps?");
+ GHOST_PRINT("<!> not a HID device... mouse/kb perhaps?\n");
firstEvent = false;
}
@@ -877,7 +876,7 @@ bool GHOST_SystemWin32::processNDOF(RAWINPUT const &raw)
m_ndofManager->updateRotation(r, now);
// I've never gotten one of these, has anyone else?
- puts("ndof: combined T + R");
+ GHOST_PRINT("ndof: combined T + R\n");
}
break;
}
@@ -906,7 +905,8 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam,
bool eventHandled = false;
LRESULT lResult = 0;
- GHOST_SystemWin32 *system = ((GHOST_SystemWin32 *)getSystem());
+ GHOST_SystemWin32 *system = (GHOST_SystemWin32 *)getSystem();
+ GHOST_EventManager *eventManager = system->getEventManager();
GHOST_ASSERT(system, "GHOST_SystemWin32::s_wndProc(): system not initialized");
if (hwnd) {
@@ -915,8 +915,13 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam,
switch (msg) {
// we need to check if new key layout has AltGr
case WM_INPUTLANGCHANGE:
+ {
system->handleKeyboardChange();
+#ifdef WITH_INPUT_IME
+ window->getImeInput()->SetInputLanguage();
+#endif
break;
+ }
////////////////////////////////////////////////////////////////////////
// Keyboard events, processed
////////////////////////////////////////////////////////////////////////
@@ -952,6 +957,64 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam,
}
break;
}
+#ifdef WITH_INPUT_IME
+ ////////////////////////////////////////////////////////////////////////
+ // IME events, processed, read more in GHOST_IME.h
+ ////////////////////////////////////////////////////////////////////////
+ case WM_IME_SETCONTEXT:
+ {
+ GHOST_ImeWin32 *ime = window->getImeInput();
+ ime->SetInputLanguage();
+ ime->CreateImeWindow(hwnd);
+ ime->CleanupComposition(hwnd);
+ ime->CheckFirst(hwnd);
+ break;
+ }
+ case WM_IME_STARTCOMPOSITION:
+ {
+ GHOST_ImeWin32 *ime = window->getImeInput();
+ eventHandled = true;
+ /* remove input event before start comp event, avoid redundant input */
+ eventManager->removeTypeEvents(GHOST_kEventKeyDown, window);
+ ime->CreateImeWindow(hwnd);
+ ime->ResetComposition(hwnd);
+ event = processImeEvent(
+ GHOST_kEventImeCompositionStart,
+ window,
+ &ime->eventImeData);
+ break;
+ }
+ case WM_IME_COMPOSITION:
+ {
+ GHOST_ImeWin32 *ime = window->getImeInput();
+ eventHandled = true;
+ ime->UpdateImeWindow(hwnd);
+ ime->UpdateInfo(hwnd);
+ if (ime->eventImeData.result_len) {
+ /* remove redundant IME event */
+ eventManager->removeTypeEvents(GHOST_kEventImeComposition, window);
+ }
+ event = processImeEvent(
+ GHOST_kEventImeComposition,
+ window,
+ &ime->eventImeData);
+ break;
+ }
+ case WM_IME_ENDCOMPOSITION:
+ {
+ GHOST_ImeWin32 *ime = window->getImeInput();
+ eventHandled = true;
+ /* remove input event after end comp event, avoid redundant input */
+ eventManager->removeTypeEvents(GHOST_kEventKeyDown, window);
+ ime->ResetComposition(hwnd);
+ ime->DestroyImeWindow(hwnd);
+ event = processImeEvent(
+ GHOST_kEventImeCompositionEnd,
+ window,
+ &ime->eventImeData);
+ break;
+ }
+#endif /* WITH_INPUT_IME */
////////////////////////////////////////////////////////////////////////
// Keyboard events, ignored
////////////////////////////////////////////////////////////////////////
@@ -1002,11 +1065,11 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam,
// Tablet events, processed
////////////////////////////////////////////////////////////////////////
case WT_PACKET:
- ((GHOST_WindowWin32 *)window)->processWin32TabletEvent(wParam, lParam);
+ window->processWin32TabletEvent(wParam, lParam);
break;
case WT_CSRCHANGE:
case WT_PROXIMITY:
- ((GHOST_WindowWin32 *)window)->processWin32TabletInitEvent();
+ window->processWin32TabletInitEvent();
break;
////////////////////////////////////////////////////////////////////////
// Mouse events, processed
@@ -1066,19 +1129,15 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam,
* until it finds a window that processes it.
*/
- /* Get the winow under the mouse and send event to it's queue. */
+ /* Get the window under the mouse and send event to its queue. */
POINT mouse_pos = {GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)};
- HWND mouse_hwnd = WindowFromPoint(mouse_pos);
+ HWND mouse_hwnd = ChildWindowFromPoint(HWND_DESKTOP, mouse_pos);
GHOST_WindowWin32 *mouse_window = (GHOST_WindowWin32 *)::GetWindowLongPtr(mouse_hwnd, GWLP_USERDATA);
if (mouse_window != NULL) {
event = processWheelEvent(mouse_window, wParam, lParam);
}
else {
- /* If it happened so window under the mouse is not found (which i'm not
- * really sure might happen), then we add event to the focused window
- * in order to avoid some possible negative side effects.
- * - sergey -
- */
+ /* Happens when mouse is not over any of blender's windows. */
event = processWheelEvent(window, wParam, lParam);
}
diff --git a/intern/ghost/intern/GHOST_SystemWin32.h b/intern/ghost/intern/GHOST_SystemWin32.h
index 79fed06c6a5..0a8837294db 100644
--- a/intern/ghost/intern/GHOST_SystemWin32.h
+++ b/intern/ghost/intern/GHOST_SystemWin32.h
@@ -53,6 +53,8 @@ class GHOST_EventWheel;
class GHOST_EventWindow;
class GHOST_EventDragnDrop;
+class GHOST_WindowWin32;
+
/**
* WIN32 Implementation of GHOST_System class.
* \see GHOST_System.
@@ -69,7 +71,7 @@ public:
/**
* Destructor.
*/
- virtual ~GHOST_SystemWin32();
+ ~GHOST_SystemWin32();
/***************************************************************************************
** Time(r) functionality
@@ -81,7 +83,7 @@ public:
* This overloaded method uses the high frequency timer if available.
* \return The number of milliseconds.
*/
- virtual GHOST_TUns64 getMilliSeconds() const;
+ GHOST_TUns64 getMilliSeconds() const;
/***************************************************************************************
** Display/window management functionality
@@ -91,19 +93,19 @@ public:
* Returns the number of displays on this system.
* \return The number of displays.
*/
- virtual GHOST_TUns8 getNumDisplays() const;
+ GHOST_TUns8 getNumDisplays() const;
/**
* Returns the dimensions of the main display on this system.
* \return The dimension of the main display.
*/
- virtual void getMainDisplayDimensions(GHOST_TUns32& width, GHOST_TUns32& height) const;
+ void getMainDisplayDimensions(GHOST_TUns32& width, GHOST_TUns32& height) const;
/**
* Returns the dimensions of all displays on this system.
* \return The dimension of the main display.
*/
- virtual void getAllDisplayDimensions(GHOST_TUns32& width, GHOST_TUns32& height) const;
+ void getAllDisplayDimensions(GHOST_TUns32& width, GHOST_TUns32& height) const;
/**
* Create a new window.
@@ -116,18 +118,17 @@ public:
* \param height The height the window.
* \param state The state of the window when opened.
* \param type The type of drawing context installed in this window.
- * \param stereoVisual Stereo visual for quad buffered stereo.
- * \param numOfAASamples Number of samples used for AA (zero if no AA)
+ * \param glSettings: Misc OpenGL settings.
+ * \param exclusive: Use to show the window ontop and ignore others (used fullscreen).
* \param parentWindow Parent (embedder) window
* \return The new window (or 0 if creation failed).
*/
- virtual GHOST_IWindow *createWindow(
+ GHOST_IWindow *createWindow(
const STR_String& title,
GHOST_TInt32 left, GHOST_TInt32 top, GHOST_TUns32 width, GHOST_TUns32 height,
GHOST_TWindowState state, GHOST_TDrawingContextType type,
- const bool stereoVisual = false,
- const bool exclusive = false,
- const GHOST_TUns16 numOfAASamples = 0,
+ GHOST_GLSettings glSettings,
+ const bool exclusive = false,
const GHOST_TEmbedderWindowID parentWindow = 0);
/***************************************************************************************
@@ -139,7 +140,7 @@ public:
* \param waitForEvent Flag to wait for an event (or return immediately).
* \return Indication of the presence of events.
*/
- virtual bool processEvents(bool waitForEvent);
+ bool processEvents(bool waitForEvent);
/***************************************************************************************
@@ -152,7 +153,7 @@ public:
* \param y The y-coordinate of the cursor.
* \return Indication of success.
*/
- virtual GHOST_TSuccess getCursorPosition(GHOST_TInt32& x, GHOST_TInt32& y) const;
+ GHOST_TSuccess getCursorPosition(GHOST_TInt32& x, GHOST_TInt32& y) const;
/**
* Updates the location of the cursor (location in screen coordinates).
@@ -160,7 +161,7 @@ public:
* \param y The y-coordinate of the cursor.
* \return Indication of success.
*/
- virtual GHOST_TSuccess setCursorPosition(GHOST_TInt32 x, GHOST_TInt32 y);
+ GHOST_TSuccess setCursorPosition(GHOST_TInt32 x, GHOST_TInt32 y);
/***************************************************************************************
** Access to mouse button and keyboard states.
@@ -171,28 +172,28 @@ public:
* \param keys The state of all modifier keys (true == pressed).
* \return Indication of success.
*/
- virtual GHOST_TSuccess getModifierKeys(GHOST_ModifierKeys& keys) const;
+ GHOST_TSuccess getModifierKeys(GHOST_ModifierKeys& keys) const;
/**
* Returns the state of the mouse buttons (ouside the message queue).
* \param buttons The state of the buttons.
* \return Indication of success.
*/
- virtual GHOST_TSuccess getButtons(GHOST_Buttons& buttons) const;
+ GHOST_TSuccess getButtons(GHOST_Buttons& buttons) const;
/**
- * Returns unsinged char from CUT_BUFFER0
+ * Returns unsigned char from CUT_BUFFER0
* \param selection Used by X11 only
* \return Returns the Clipboard
*/
- virtual GHOST_TUns8 *getClipboard(bool selection) const;
+ GHOST_TUns8 *getClipboard(bool selection) const;
/**
* Puts buffer to system clipboard
* \param selection Used by X11 only
* \return No return
*/
- virtual void putClipboard(GHOST_TInt8 *buffer, bool selection) const;
+ void putClipboard(GHOST_TInt8 *buffer, bool selection) const;
/**
* Creates a drag'n'drop event and pushes it immediately onto the event queue.
@@ -204,13 +205,13 @@ public:
* \param window The window on which the event occurred
* \return Indication whether the event was handled.
*/
- static GHOST_TSuccess pushDragDropEvent(GHOST_TEventType eventType, GHOST_TDragnDropTypes draggedObjectType, GHOST_IWindow *window, int mouseX, int mouseY, void *data);
+ static GHOST_TSuccess pushDragDropEvent(GHOST_TEventType eventType, GHOST_TDragnDropTypes draggedObjectType, GHOST_WindowWin32 *window, int mouseX, int mouseY, void *data);
/**
* Confirms quitting he program when there is just one window left open
* in the application
*/
- virtual int confirmQuit(GHOST_IWindow *window) const;
+ int confirmQuit(GHOST_IWindow *window) const;
protected:
/**
@@ -218,42 +219,31 @@ protected:
* For now, it just registers the window class (WNDCLASS).
* \return A success value.
*/
- virtual GHOST_TSuccess init();
+ GHOST_TSuccess init();
/**
* Closes the system down.
* \return A success value.
*/
- virtual GHOST_TSuccess exit();
+ GHOST_TSuccess exit();
/**
* Converts raw WIN32 key codes from the wndproc to GHOST keys.
- * \param window-> The window for this handling
* \param vKey The virtual key from hardKey
- * \param ScanCode The ScanCode of pressed key (simular to PS/2 Set 1)
+ * \param ScanCode The ScanCode of pressed key (similar to PS/2 Set 1)
* \param extend Flag if key is not primly (left or right)
* \return The GHOST key (GHOST_kKeyUnknown if no match).
*/
- virtual GHOST_TKey convertKey(GHOST_IWindow *window, short vKey, short ScanCode, short extend) const;
+ GHOST_TKey convertKey(short vKey, short ScanCode, short extend) const;
/**
* Catches raw WIN32 key codes from WM_INPUT in the wndproc.
- * \param window The window for this handling
* \param raw RawInput structure with detailed info about the key event
* \param keyDown Pointer flag that specify if a key is down
* \param vk Pointer to virtual key
* \return The GHOST key (GHOST_kKeyUnknown if no match).
*/
- virtual GHOST_TKey hardKey(GHOST_IWindow *window, RAWINPUT const& raw, int *keyDown, char *vk);
-
- /**
- * Creates modifier key event(s) and updates the key data stored locally (m_modifierKeys).
- * With the modifier keys, we want to distinguish left and right keys.
- * Sometimes this is not possible (Windows ME for instance). Then, we want
- * events generated for both keys.
- * \param window The window receiving the event (the active window).
- */
- GHOST_EventKey *processModifierKeys(GHOST_IWindow *window);
+ GHOST_TKey hardKey(RAWINPUT const& raw, int *keyDown, char *vk);
/**
* Creates mouse button event.
@@ -262,7 +252,7 @@ protected:
* \param mask The button mask of this event.
* \return The event created.
*/
- static GHOST_EventButton *processButtonEvent(GHOST_TEventType type, GHOST_IWindow *window, GHOST_TButtonMask mask);
+ static GHOST_EventButton *processButtonEvent(GHOST_TEventType type, GHOST_WindowWin32 *window, GHOST_TButtonMask mask);
/**
* Creates cursor event.
@@ -270,7 +260,7 @@ protected:
* \param window The window receiving the event (the active window).
* \return The event created.
*/
- static GHOST_EventCursor *processCursorEvent(GHOST_TEventType type, GHOST_IWindow *Iwindow);
+ static GHOST_EventCursor *processCursorEvent(GHOST_TEventType type, GHOST_WindowWin32 *window);
/**
* Creates a mouse wheel event.
@@ -278,7 +268,7 @@ protected:
* \param wParam The wParam from the wndproc
* \param lParam The lParam from the wndproc
*/
- static GHOST_EventWheel *processWheelEvent(GHOST_IWindow *window, WPARAM wParam, LPARAM lParam);
+ static GHOST_EventWheel *processWheelEvent(GHOST_WindowWin32 *window, WPARAM wParam, LPARAM lParam);
/**
* Creates a key event and updates the key data stored locally (m_modifierKeys).
@@ -287,16 +277,15 @@ protected:
* \param window The window receiving the event (the active window).
* \param raw RawInput structure with detailed info about the key event
*/
- static GHOST_EventKey *processKeyEvent(GHOST_IWindow *window, RAWINPUT const& raw);
+ static GHOST_EventKey *processKeyEvent(GHOST_WindowWin32 *window, RAWINPUT const& raw);
/**
* Process special keys (VK_OEM_*), to see if current key layout
* gives us anything special, like ! on french AZERTY.
- * \param window The window receiving the event (the active window).
* \param vKey The virtual key from hardKey
- * \param ScanCode The ScanCode of pressed key (simular to PS/2 Set 1)
+ * \param scanCode The ScanCode of pressed key (simular to PS/2 Set 1)
*/
- virtual GHOST_TKey processSpecialKey(GHOST_IWindow *window, short vKey, short scanCode) const;
+ GHOST_TKey processSpecialKey(short vKey, short scanCode) const;
/**
* Creates a window event.
@@ -304,7 +293,18 @@ protected:
* \param window The window receiving the event (the active window).
* \return The event created.
*/
- static GHOST_Event *processWindowEvent(GHOST_TEventType type, GHOST_IWindow *window);
+ static GHOST_Event *processWindowEvent(GHOST_TEventType type, GHOST_WindowWin32 *window);
+
+#ifdef WITH_INPUT_IME
+ /**
+ * Creates a IME event.
+ * \param type The type of event to create.
+ * \param window The window receiving the event (the active window).
+ * \param data IME data.
+ * \return The event created.
+ */
+ static GHOST_Event *processImeEvent(GHOST_TEventType type, GHOST_WindowWin32 *window, GHOST_TEventImeData *data);
+#endif // WITH_INPUT_IME
/**
* Handles minimum window size.
@@ -327,19 +327,19 @@ protected:
* Returns the local state of the modifier keys (from the message queue).
* \param keys The state of the keys.
*/
- inline virtual void retrieveModifierKeys(GHOST_ModifierKeys& keys) const;
+ inline void retrieveModifierKeys(GHOST_ModifierKeys& keys) const;
/**
* Stores the state of the modifier keys locally.
* For internal use only!
* param keys The new state of the modifier keys.
*/
- inline virtual void storeModifierKeys(const GHOST_ModifierKeys& keys);
+ inline void storeModifierKeys(const GHOST_ModifierKeys& keys);
/**
* Check current key layout for AltGr
*/
- inline virtual void handleKeyboardChange(void);
+ inline void handleKeyboardChange(void);
/**
* Windows call back routine for our window class.
diff --git a/intern/ghost/intern/GHOST_SystemX11.cpp b/intern/ghost/intern/GHOST_SystemX11.cpp
index f797d8074e1..325cba0c631 100644
--- a/intern/ghost/intern/GHOST_SystemX11.cpp
+++ b/intern/ghost/intern/GHOST_SystemX11.cpp
@@ -32,6 +32,11 @@
* \ingroup GHOST
*/
+#include <X11/Xatom.h>
+#include <X11/keysym.h>
+#include <X11/XKBlib.h> /* allow detectable autorepeate */
+#include <X11/Xutil.h>
+
#include "GHOST_SystemX11.h"
#include "GHOST_WindowX11.h"
#include "GHOST_WindowManager.h"
@@ -52,10 +57,6 @@
#include "GHOST_Debug.h"
-#include <X11/Xatom.h>
-#include <X11/keysym.h>
-#include <X11/XKBlib.h> /* allow detectable autorepeate */
-
#ifdef WITH_XF86KEYSYM
#include <X11/XF86keysym.h>
#endif
@@ -279,40 +280,33 @@ getAllDisplayDimensions(
* \param height The height the window.
* \param state The state of the window when opened.
* \param type The type of drawing context installed in this window.
- * \param stereoVisual Stereo visual for quad buffered stereo.
- * \param exclusive Use to show the window ontop and ignore others
- * (used fullscreen).
- * \param numOfAASamples Number of samples used for AA (zero if no AA)
+ * \param glSettings: Misc OpenGL settings.
+ * \param exclusive: Use to show the window ontop and ignore others (used fullscreen).
* \param parentWindow Parent (embedder) window
* \return The new window (or 0 if creation failed).
*/
GHOST_IWindow *
GHOST_SystemX11::
-createWindow(
- const STR_String& title,
+createWindow(const STR_String& title,
GHOST_TInt32 left,
GHOST_TInt32 top,
GHOST_TUns32 width,
GHOST_TUns32 height,
GHOST_TWindowState state,
GHOST_TDrawingContextType type,
- const bool stereoVisual,
+ GHOST_GLSettings glSettings,
const bool exclusive,
- const GHOST_TUns16 numOfAASamples,
const GHOST_TEmbedderWindowID parentWindow)
{
GHOST_WindowX11 *window = 0;
if (!m_display) return 0;
-
-
-
window = new GHOST_WindowX11(this, m_display, title,
left, top, width, height,
state, parentWindow, type,
- stereoVisual, exclusive,
- numOfAASamples);
+ ((glSettings.flags & GHOST_glStereoVisual) != 0), exclusive,
+ glSettings.numOfAASamples, (glSettings.flags & GHOST_glDebugContext) != 0);
if (window) {
/* Both are now handle in GHOST_WindowX11.cpp
@@ -333,7 +327,7 @@ createWindow(
}
#if defined(WITH_X11_XINPUT) && defined(X_HAVE_UTF8_STRING)
-static void destroyIMCallback(XIM xim, XPointer ptr, XPointer data)
+static void destroyIMCallback(XIM /*xim*/, XPointer ptr, XPointer /*data*/)
{
GHOST_PRINT("XIM server died\n");
@@ -1180,7 +1174,11 @@ GHOST_SystemX11::processEvent(XEvent *xe)
default:
{
#ifdef WITH_X11_XINPUT
- if (xe->type == m_xtablet.MotionEvent) {
+ if (xe->type == m_xtablet.MotionEvent ||
+ xe->type == m_xtablet.MotionEventEraser ||
+ xe->type == m_xtablet.PressEvent ||
+ xe->type == m_xtablet.PressEventEraser)
+ {
XDeviceMotionEvent *data = (XDeviceMotionEvent *)xe;
const unsigned char axis_first = data->first_axis;
const unsigned char axes_end = axis_first + data->axes_count; /* after the last */
@@ -1873,13 +1871,16 @@ GHOST_TSuccess GHOST_SystemX11::pushDragDropEvent(GHOST_TEventType eventType,
}
#endif
-#ifdef WITH_X11_XINPUT
-/*
+#if defined(USE_X11_ERROR_HANDLERS) || defined(WITH_X11_XINPUT)
+/*
+ * These callbacks can be used for debugging, so we can breakpoint on an X11 error.
+
+ *
* Dummy function to get around IO Handler exiting if device invalid
* Basically it will not crash blender now if you have a X device that
* is configured but not plugged in.
*/
-int GHOST_X11_ApplicationErrorHandler(Display *display, XErrorEvent *theEvent)
+int GHOST_X11_ApplicationErrorHandler(Display * /*display*/, XErrorEvent *theEvent)
{
fprintf(stderr, "Ignoring Xlib error: error code %d request code %d\n",
theEvent->error_code, theEvent->request_code);
@@ -1888,14 +1889,16 @@ int GHOST_X11_ApplicationErrorHandler(Display *display, XErrorEvent *theEvent)
return 0;
}
-int GHOST_X11_ApplicationIOErrorHandler(Display *display)
+int GHOST_X11_ApplicationIOErrorHandler(Display * /*display*/)
{
fprintf(stderr, "Ignoring Xlib error: error IO\n");
/* No exit! - but keep lint happy */
return 0;
}
+#endif
+#ifdef WITH_X11_XINPUT
/* These C functions are copied from Wine 1.1.13's wintab.c */
#define BOOL int
#define TRUE 1
diff --git a/intern/ghost/intern/GHOST_SystemX11.h b/intern/ghost/intern/GHOST_SystemX11.h
index a21300e36f0..a0088dbe8f0 100644
--- a/intern/ghost/intern/GHOST_SystemX11.h
+++ b/intern/ghost/intern/GHOST_SystemX11.h
@@ -34,7 +34,6 @@
#define __GHOST_SYSTEMX11_H__
#include <X11/Xlib.h>
-#include <GL/glx.h>
#include "GHOST_System.h"
#include "../GHOST_Types.h"
@@ -53,6 +52,7 @@
int GHOST_X11_ApplicationErrorHandler(Display *display, XErrorEvent *theEvent);
int GHOST_X11_ApplicationIOErrorHandler(Display *display);
+
class GHOST_WindowX11;
/**
@@ -76,7 +76,7 @@ public:
/**
* Destructor.
*/
- virtual ~GHOST_SystemX11();
+ ~GHOST_SystemX11();
GHOST_TSuccess
@@ -152,17 +152,12 @@ public:
GHOST_TUns32 height,
GHOST_TWindowState state,
GHOST_TDrawingContextType type,
- const bool stereoVisual,
+ GHOST_GLSettings glSettings,
const bool exclusive = false,
- const GHOST_TUns16 numOfAASamples = 0,
const GHOST_TEmbedderWindowID parentWindow = 0
);
/**
- * \section Interface Inherited from GHOST_ISystem
- */
-
- /**
* Retrieves events from the system and stores them in the queue.
* \param waitForEvent Flag to wait for an event (or return immediately).
* \return Indication of the presence of events.
@@ -172,9 +167,6 @@ public:
bool waitForEvent
);
- /**
- * \section Interface Inherited from GHOST_System
- */
GHOST_TSuccess
getCursorPosition(
GHOST_TInt32& x,
@@ -208,7 +200,6 @@ public:
) const;
/**
- * \section Interface Dirty
* Flag a window as dirty. This will
* generate a GHOST window update event on a call to processEvents()
*/
@@ -243,7 +234,7 @@ public:
unsigned int *context) const;
/**
- * Returns unsinged char from CUT_BUFFER0
+ * Returns unsigned char from CUT_BUFFER0
* \param selection Get selection, X11 only feature
* \return Returns the Clipboard indicated by Flag
*/
@@ -273,7 +264,7 @@ public:
/**
* \see GHOST_ISystem
*/
- int toggleConsole(int action) {
+ int toggleConsole(int /*action*/) {
return 0;
}
@@ -287,6 +278,12 @@ public:
int MotionEvent;
int ProxInEvent;
int ProxOutEvent;
+ int PressEvent;
+
+ int MotionEventEraser;
+ int ProxInEventEraser;
+ int ProxOutEventEraser;
+ int PressEventEraser;
int PressureLevels;
int XtiltLevels, YtiltLevels;
diff --git a/intern/ghost/intern/GHOST_TimerManager.h b/intern/ghost/intern/GHOST_TimerManager.h
index b94175e9ff8..6cf4bcf40eb 100644
--- a/intern/ghost/intern/GHOST_TimerManager.h
+++ b/intern/ghost/intern/GHOST_TimerManager.h
@@ -58,19 +58,19 @@ public:
/**
* Destructor.
*/
- virtual ~GHOST_TimerManager();
+ ~GHOST_TimerManager();
/**
* Returns the number of timer tasks.
* \return The number of events on the stack.
*/
- virtual GHOST_TUns32 getNumTimers();
+ GHOST_TUns32 getNumTimers();
/**
* Returns whether this timer task ins in our list.
* \return Indication of presence.
*/
- virtual bool getTimerFound(GHOST_TimerTask *timer);
+ bool getTimerFound(GHOST_TimerTask *timer);
/**
* Adds a timer task to the list.
@@ -78,7 +78,7 @@ public:
* \param timer The timer task added to the list.
* \return Indication as to whether addition has succeeded.
*/
- virtual GHOST_TSuccess addTimer(GHOST_TimerTask *timer);
+ GHOST_TSuccess addTimer(GHOST_TimerTask *timer);
/**
* Removes a timer task from the list.
@@ -86,21 +86,21 @@ public:
* \param timer The timer task to be removed from the list.
* \return Indication as to whether removal has succeeded.
*/
- virtual GHOST_TSuccess removeTimer(GHOST_TimerTask *timer);
+ GHOST_TSuccess removeTimer(GHOST_TimerTask *timer);
/**
* Finds the soonest time the next timer would fire.
* \return The soonest time the next timer would fire,
* or GHOST_kFireTimeNever if no timers exist.
*/
- virtual GHOST_TUns64 nextFireTime();
+ GHOST_TUns64 nextFireTime();
/**
* Checks all timer tasks to see if they are expired and fires them if needed.
* \param time The current time.
* \return True if any timers were fired.
*/
- virtual bool fireTimers(GHOST_TUns64 time);
+ bool fireTimers(GHOST_TUns64 time);
/**
* Checks this timer task to see if they are expired and fires them if needed.
@@ -108,7 +108,7 @@ public:
* \param task The timer task to check and optionally fire.
* \return True if the timer fired.
*/
- virtual bool fireTimer(GHOST_TUns64 time, GHOST_TimerTask *task);
+ bool fireTimer(GHOST_TUns64 time, GHOST_TimerTask *task);
protected:
/**
diff --git a/intern/ghost/intern/GHOST_TimerTask.h b/intern/ghost/intern/GHOST_TimerTask.h
index e33788ec826..45aa66e4630 100644
--- a/intern/ghost/intern/GHOST_TimerTask.h
+++ b/intern/ghost/intern/GHOST_TimerTask.h
@@ -49,7 +49,7 @@ public:
* \param start The timer start time.
* \param interval The interval between calls to the timerProc
* \param timerProc The callback invoked when the interval expires.
- * \param data The timer user data.
+ * \param userData: The timer user data.
*/
GHOST_TimerTask(GHOST_TUns64 start,
GHOST_TUns64 interval,
@@ -68,7 +68,7 @@ public:
* Returns the timer start time.
* \return The timer start time.
*/
- inline virtual GHOST_TUns64 getStart() const
+ inline GHOST_TUns64 getStart() const
{
return m_start;
}
@@ -77,7 +77,7 @@ public:
* Changes the timer start time.
* \param start The timer start time.
*/
- virtual void setStart(GHOST_TUns64 start)
+ void setStart(GHOST_TUns64 start)
{
m_start = start;
}
@@ -86,7 +86,7 @@ public:
* Returns the timer interval.
* \return The timer interval.
*/
- inline virtual GHOST_TUns64 getInterval() const
+ inline GHOST_TUns64 getInterval() const
{
return m_interval;
}
@@ -95,7 +95,7 @@ public:
* Changes the timer interval.
* \param interval The timer interval.
*/
- virtual void setInterval(GHOST_TUns64 interval)
+ void setInterval(GHOST_TUns64 interval)
{
m_interval = interval;
}
@@ -104,7 +104,7 @@ public:
* Returns the time the timerProc will be called.
* \return The time the timerProc will be called.
*/
- inline virtual GHOST_TUns64 getNext() const
+ inline GHOST_TUns64 getNext() const
{
return m_next;
}
@@ -113,7 +113,7 @@ public:
* Changes the time the timerProc will be called.
* \param next The time the timerProc will be called.
*/
- virtual void setNext(GHOST_TUns64 next)
+ void setNext(GHOST_TUns64 next)
{
m_next = next;
}
@@ -122,16 +122,16 @@ public:
* Returns the timer callback.
* \return the timer callback.
*/
- inline virtual GHOST_TimerProcPtr getTimerProc() const
+ inline GHOST_TimerProcPtr getTimerProc() const
{
return m_timerProc;
}
/**
* Changes the timer callback.
- * \param The timer callback.
+ * \param timerProc: The timer callback.
*/
- inline virtual void setTimerProc(const GHOST_TimerProcPtr timerProc)
+ inline void setTimerProc(const GHOST_TimerProcPtr timerProc)
{
m_timerProc = timerProc;
}
@@ -140,16 +140,16 @@ public:
* Returns the timer user data.
* \return The timer user data.
*/
- inline virtual GHOST_TUserDataPtr getUserData() const
+ inline GHOST_TUserDataPtr getUserData() const
{
return m_userData;
}
/**
* Changes the time user data.
- * \param data The timer user data.
+ * \param userData: The timer user data.
*/
- virtual void setUserData(const GHOST_TUserDataPtr userData)
+ void setUserData(const GHOST_TUserDataPtr userData)
{
m_userData = userData;
}
@@ -158,7 +158,7 @@ public:
* Returns the auxiliary storage room.
* \return The auxiliary storage room.
*/
- inline virtual GHOST_TUns32 getAuxData() const
+ inline GHOST_TUns32 getAuxData() const
{
return m_auxData;
}
@@ -167,7 +167,7 @@ public:
* Changes the auxiliary storage room.
* \param auxData The auxiliary storage room.
*/
- virtual void setAuxData(GHOST_TUns32 auxData)
+ void setAuxData(GHOST_TUns32 auxData)
{
m_auxData = auxData;
}
diff --git a/intern/ghost/intern/GHOST_Window.cpp b/intern/ghost/intern/GHOST_Window.cpp
index 3673831c7b1..71fa260f0f2 100644
--- a/intern/ghost/intern/GHOST_Window.cpp
+++ b/intern/ghost/intern/GHOST_Window.cpp
@@ -38,21 +38,23 @@
#include "GHOST_Window.h"
+#include "GHOST_ContextNone.h"
+
#include <assert.h>
GHOST_Window::GHOST_Window(
GHOST_TUns32 width, GHOST_TUns32 height,
GHOST_TWindowState state,
- GHOST_TDrawingContextType type,
- const bool stereoVisual,
- const bool exclusive,
- const GHOST_TUns16 numOfAASamples)
- : m_drawingContextType(type),
+ const bool wantStereoVisual,
+ const bool /*exclusive*/,
+ const GHOST_TUns16 wantNumOfAASamples)
+ : m_drawingContextType(GHOST_kDrawingContextTypeNone),
m_cursorVisible(true),
m_cursorGrab(GHOST_kGrabDisable),
m_cursorShape(GHOST_kStandardCursorDefault),
- m_stereoVisual(stereoVisual),
- m_numOfAASamples(numOfAASamples)
+ m_wantStereoVisual(wantStereoVisual),
+ m_wantNumOfAASamples(wantNumOfAASamples),
+ m_context(new GHOST_ContextNone(false, 0))
{
m_isUnsavedChanges = false;
m_canAcceptDragOperation = false;
@@ -74,6 +76,7 @@ GHOST_Window::GHOST_Window(
GHOST_Window::~GHOST_Window()
{
+ delete m_context;
}
void *GHOST_Window::getOSWindow() const
@@ -83,18 +86,61 @@ void *GHOST_Window::getOSWindow() const
GHOST_TSuccess GHOST_Window::setDrawingContextType(GHOST_TDrawingContextType type)
{
- GHOST_TSuccess success = GHOST_kSuccess;
if (type != m_drawingContextType) {
- success = removeDrawingContext();
- if (success) {
- success = installDrawingContext(type);
+ delete m_context;
+ m_context = NULL;
+
+ if (type != GHOST_kDrawingContextTypeNone)
+ m_context = newDrawingContext(type);
+
+ if (m_context != NULL) {
m_drawingContextType = type;
}
else {
+ m_context = new GHOST_ContextNone(m_wantStereoVisual, m_wantNumOfAASamples);
m_drawingContextType = GHOST_kDrawingContextTypeNone;
}
+
+ return (type == m_drawingContextType) ? GHOST_kSuccess : GHOST_kFailure;
+ }
+ else {
+ return GHOST_kSuccess;
}
- return success;
+}
+
+GHOST_TSuccess GHOST_Window::swapBuffers()
+{
+ return m_context->swapBuffers();
+}
+
+GHOST_TSuccess GHOST_Window::setSwapInterval(int interval)
+{
+ return m_context->setSwapInterval(interval);
+}
+
+GHOST_TSuccess GHOST_Window::getSwapInterval(int& intervalOut)
+{
+ return m_context->getSwapInterval(intervalOut);
+}
+
+GHOST_TUns16 GHOST_Window::getNumOfAASamples()
+{
+ return m_context->getNumOfAASamples();
+}
+
+GHOST_TSuccess GHOST_Window::activateDrawingContext()
+{
+ return m_context->activateDrawingContext();
+}
+
+GHOST_TSuccess GHOST_Window::updateDrawingContext()
+{
+ return m_context->updateDrawingContext();
+}
+
+GHOST_TSuccess GHOST_Window::releaseNativeHandles()
+{
+ return m_context->releaseNativeHandles();
}
GHOST_TSuccess GHOST_Window::setCursorVisibility(bool visible)
diff --git a/intern/ghost/intern/GHOST_Window.h b/intern/ghost/intern/GHOST_Window.h
index 77ee4db8543..52cb9cbf54b 100644
--- a/intern/ghost/intern/GHOST_Window.h
+++ b/intern/ghost/intern/GHOST_Window.h
@@ -36,6 +36,7 @@
#include "GHOST_IWindow.h"
class STR_String;
+class GHOST_Context;
/**
* Platform independent implementation of GHOST_IWindow.
@@ -49,29 +50,6 @@ class STR_String;
class GHOST_Window : public GHOST_IWindow
{
public:
- /**
- * \section Interface inherited from GHOST_IWindow left for derived class
- * implementation.
- * virtual bool getValid() const = 0;
- * virtual void setTitle(const STR_String& title) = 0;
- * virtual void getTitle(STR_String& title) const = 0;
- * virtual void getWindowBounds(GHOST_Rect& bounds) const = 0;
- * virtual void getClientBounds(GHOST_Rect& bounds) const = 0;
- * virtual GHOST_TSuccess setClientWidth(GHOST_TUns32 width) = 0;
- * virtual GHOST_TSuccess setClientHeight(GHOST_TUns32 height) = 0;
- * virtual GHOST_TSuccess setClientSize(GHOST_TUns32 width, GHOST_TUns32 height) = 0;
- * virtual void screenToClient(GHOST_TInt32 inX, GHOST_TInt32 inY, GHOST_TInt32& outX, GHOST_TInt32& outY) const = 0;
- * virtual void clientToScreen(GHOST_TInt32 inX, GHOST_TInt32 inY, GHOST_TInt32& outX, GHOST_TInt32& outY) const = 0;
- * virtual GHOST_TWindowState getState() const = 0;
- * virtual GHOST_TSuccess setState(GHOST_TWindowState state) = 0;
- * virtual GHOST_TWindowOrder getOrder(void) = 0;
- * virtual GHOST_TSuccess setOrder(GHOST_TWindowOrder order) = 0;
- * virtual GHOST_TSuccess swapBuffers() = 0;
- * virtual GHOST_TSuccess setSwapInterval() = 0;
- * virtual int getSwapInterval() = 0;
- * virtual GHOST_TSuccess activateDrawingContext() = 0;
- * virtual GHOST_TSuccess invalidate() = 0;
- */
/**
* Constructor.
@@ -90,10 +68,9 @@ public:
GHOST_TUns32 width,
GHOST_TUns32 height,
GHOST_TWindowState state,
- GHOST_TDrawingContextType type = GHOST_kDrawingContextTypeNone,
- const bool stereoVisual = false,
+ const bool wantStereoVisual = false,
const bool exclusive = false,
- const GHOST_TUns16 numOfAASamples = 0);
+ const GHOST_TUns16 wantNumOfAASamples = 0);
/**
* \section Interface inherited from GHOST_IWindow left for derived class
@@ -113,7 +90,7 @@ public:
* virtual GHOST_TSuccess setOrder(GHOST_TWindowOrder order) = 0;
* virtual GHOST_TSuccess swapBuffers() = 0;
* virtual GHOST_TSuccess setSwapInterval() = 0;
- * virtual int getSwapInterval() = 0;
+ * virtual GHOST_TSuccess getSwapInterval(int& intervalOut) = 0;
* virtual GHOST_TSuccess activateDrawingContext() = 0;
* virtual GHOST_TSuccess invalidate() = 0;
*/
@@ -125,6 +102,14 @@ public:
virtual ~GHOST_Window();
/**
+ * Returns indication as to whether the window is valid.
+ * \return The validity of the window.
+ */
+ virtual bool getValid() const {
+ return m_context != 0;
+ }
+
+ /**
* Returns the associated OS object/handle
* \return The associated OS object/handle
*/
@@ -134,14 +119,14 @@ public:
* Returns the current cursor shape.
* \return The current cursor shape.
*/
- inline virtual GHOST_TStandardCursor getCursorShape() const;
+ inline GHOST_TStandardCursor getCursorShape() const;
/**
* Set the shape of the cursor.
- * \param cursor The new cursor shape type id.
+ * \param cursorShape: The new cursor shape type id.
* \return Indication of success.
*/
- virtual GHOST_TSuccess setCursorShape(GHOST_TStandardCursor cursorShape);
+ GHOST_TSuccess setCursorShape(GHOST_TStandardCursor cursorShape);
/**
* Set the shape of the cursor to a custom cursor.
@@ -151,53 +136,53 @@ public:
* \param hotY The Y coordinate of the cursor hotspot.
* \return Indication of success.
*/
- virtual GHOST_TSuccess setCustomCursorShape(GHOST_TUns8 bitmap[16][2],
- GHOST_TUns8 mask[16][2],
- int hotX,
- int hotY);
-
- virtual GHOST_TSuccess setCustomCursorShape(GHOST_TUns8 *bitmap,
- GHOST_TUns8 *mask,
- int sizex, int sizey,
- int hotX, int hotY,
- int fg_color, int bg_color);
-
+ GHOST_TSuccess setCustomCursorShape(GHOST_TUns8 bitmap[16][2],
+ GHOST_TUns8 mask[16][2],
+ int hotX,
+ int hotY);
+
+ GHOST_TSuccess setCustomCursorShape(GHOST_TUns8 *bitmap,
+ GHOST_TUns8 *mask,
+ int sizex, int sizey,
+ int hotX, int hotY,
+ int fg_color, int bg_color);
+
/**
* Returns the visibility state of the cursor.
* \return The visibility state of the cursor.
*/
- inline virtual bool getCursorVisibility() const;
- inline virtual GHOST_TGrabCursorMode getCursorGrabMode() const;
- inline virtual bool getCursorGrabModeIsWarp() const;
- inline virtual void getCursorGrabInitPos(GHOST_TInt32 &x, GHOST_TInt32 &y) const;
- inline virtual void getCursorGrabAccum(GHOST_TInt32 &x, GHOST_TInt32 &y) const;
- inline virtual void setCursorGrabAccum(GHOST_TInt32 x, GHOST_TInt32 y);
+ inline bool getCursorVisibility() const;
+ inline GHOST_TGrabCursorMode getCursorGrabMode() const;
+ inline bool getCursorGrabModeIsWarp() const;
+ inline void getCursorGrabInitPos(GHOST_TInt32 &x, GHOST_TInt32 &y) const;
+ inline void getCursorGrabAccum(GHOST_TInt32 &x, GHOST_TInt32 &y) const;
+ inline void setCursorGrabAccum(GHOST_TInt32 x, GHOST_TInt32 y);
/**
* Shows or hides the cursor.
* \param visible The new visibility state of the cursor.
* \return Indication of success.
*/
- virtual GHOST_TSuccess setCursorVisibility(bool visible);
+ GHOST_TSuccess setCursorVisibility(bool visible);
/**
* Sets the cursor grab.
* \param mode The new grab state of the cursor.
* \return Indication of success.
*/
- virtual GHOST_TSuccess setCursorGrab(GHOST_TGrabCursorMode mode, GHOST_Rect *bounds, GHOST_TInt32 mouse_ungrab_xy[2]);
+ GHOST_TSuccess setCursorGrab(GHOST_TGrabCursorMode mode, GHOST_Rect *bounds, GHOST_TInt32 mouse_ungrab_xy[2]);
/**
* Gets the cursor grab region, if unset the window is used.
* reset when grab is disabled.
*/
- virtual GHOST_TSuccess getCursorGrabBounds(GHOST_Rect& bounds);
+ GHOST_TSuccess getCursorGrabBounds(GHOST_Rect& bounds);
/**
* Sets the progress bar value displayed in the window/application icon
* \param progress The progress % (0.0 to 1.0)
*/
- virtual GHOST_TSuccess setProgressBar(float progress) {
+ virtual GHOST_TSuccess setProgressBar(float /*progress*/) {
return GHOST_kFailure;
}
@@ -213,28 +198,30 @@ public:
* \param interval The swap interval to use.
* \return A boolean success indicator.
*/
- virtual GHOST_TSuccess setSwapInterval(int interval) {
- return GHOST_kFailure;
- }
-
+ GHOST_TSuccess setSwapInterval(int interval);
+
/**
* Gets the current swap interval for swapBuffers.
* \return An integer.
*/
- virtual int getSwapInterval() {
- return 0;
- }
-
+ GHOST_TSuccess getSwapInterval(int& intervalOut);
+
+ /**
+ * Gets the current swap interval for swapBuffers.
+ * \return Number of AA Samples (0 if there is no multisample buffer)
+ */
+ GHOST_TUns16 getNumOfAASamples();
+
/**
* Tells if the ongoing drag'n'drop object can be accepted upon mouse drop
*/
- virtual void setAcceptDragOperation(bool canAccept);
+ void setAcceptDragOperation(bool canAccept);
/**
* Returns acceptance of the dropped object
* Usually called by the "object dropped" event handling function
*/
- virtual bool canAcceptDragOperation() const;
+ bool canAcceptDragOperation() const;
/**
* Sets the window "modified" status, indicating unsaved changes
@@ -253,55 +240,84 @@ public:
* Returns the type of drawing context used in this window.
* \return The current type of drawing context.
*/
- inline virtual GHOST_TDrawingContextType getDrawingContextType();
+ inline GHOST_TDrawingContextType getDrawingContextType();
/**
* Tries to install a rendering context in this window.
- * Child classes do not need to overload this method.
- * They should overload the installDrawingContext and removeDrawingContext instead.
+ * Child classes do not need to overload this method,
+ * They should overload newDrawingContext instead.
* \param type The type of rendering context installed.
* \return Indication as to whether installation has succeeded.
*/
- virtual GHOST_TSuccess setDrawingContextType(GHOST_TDrawingContextType type);
+ GHOST_TSuccess setDrawingContextType(GHOST_TDrawingContextType type);
+
+ /**
+ * Swaps front and back buffers of a window.
+ * \return A boolean success indicator.
+ */
+ virtual GHOST_TSuccess swapBuffers();
+
+ /**
+ * Activates the drawing context of this window.
+ * \return A boolean success indicator.
+ */
+ virtual GHOST_TSuccess activateDrawingContext();
+
+ /**
+ * Updates the drawing context of this window. Needed
+ * whenever the window is changed.
+ * \return Indication of success.
+ */
+ GHOST_TSuccess updateDrawingContext();
/**
* Returns the window user data.
* \return The window user data.
*/
- inline virtual GHOST_TUserDataPtr getUserData() const
+ inline GHOST_TUserDataPtr getUserData() const
{
return m_userData;
}
/**
* Changes the window user data.
- * \param data The window user data.
+ * \param userData: The window user data.
*/
- virtual void setUserData(const GHOST_TUserDataPtr userData)
+ void setUserData(const GHOST_TUserDataPtr userData)
{
m_userData = userData;
}
- virtual float getNativePixelSize(void)
+ float getNativePixelSize(void)
{
if (m_nativePixelSize > 0.0f)
return m_nativePixelSize;
return 1.0f;
}
+#ifdef WITH_INPUT_IME
+ virtual void beginIME(GHOST_TInt32 x,
+ GHOST_TInt32 y,
+ GHOST_TInt32 w,
+ GHOST_TInt32 h,
+ int completed)
+ {
+ /* do nothing temporarily if not in windows */
+ }
+
+ virtual void endIME()
+ {
+ /* do nothing temporarily if not in windows */
+ }
+#endif /* WITH_INPUT_IME */
+
protected:
/**
* Tries to install a rendering context in this window.
* \param type The type of rendering context installed.
* \return Indication as to whether installation has succeeded.
*/
- virtual GHOST_TSuccess installDrawingContext(GHOST_TDrawingContextType type) = 0;
-
- /**
- * Removes the current drawing context.
- * \return Indication as to whether removal has succeeded.
- */
- virtual GHOST_TSuccess removeDrawingContext() = 0;
+ virtual GHOST_Context *newDrawingContext(GHOST_TDrawingContextType type) = 0;
/**
* Sets the cursor visibility on the window using
@@ -313,7 +329,7 @@ protected:
* Sets the cursor grab on the window using
* native window system calls.
*/
- virtual GHOST_TSuccess setWindowCursorGrab(GHOST_TGrabCursorMode mode) {
+ virtual GHOST_TSuccess setWindowCursorGrab(GHOST_TGrabCursorMode /*mode*/) {
return GHOST_kSuccess;
}
@@ -333,7 +349,10 @@ protected:
virtual GHOST_TSuccess setWindowCustomCursorShape(GHOST_TUns8 *bitmap, GHOST_TUns8 *mask,
int szx, int szy, int hotX, int hotY, int fg, int bg) = 0;
- /** The the of drawing context installed in this window. */
+
+ GHOST_TSuccess releaseNativeHandles();
+
+ /** The drawing context installed in this window. */
GHOST_TDrawingContextType m_drawingContextType;
/** The window user data */
@@ -369,14 +388,11 @@ protected:
/** Stores whether this is a full screen window. */
bool m_fullScreen;
- /** Stereo visual created. Only necessary for 'real' stereo support,
- * ie quad buffered stereo. This is not always possible, depends on
- * the graphics h/w
- */
- bool m_stereoVisual;
-
- /** Number of samples used in anti-aliasing, set to 0 if no AA **/
- GHOST_TUns16 m_numOfAASamples;
+ /** Whether to attempt to initialize a context with a stereo framebuffer. */
+ bool m_wantStereoVisual;
+
+ /** Attempt to initialize a context with this many samples. */
+ GHOST_TUns16 m_wantNumOfAASamples;
/** Full-screen width */
GHOST_TUns32 m_fullScreenWidth;
@@ -385,6 +401,9 @@ protected:
/* OSX only, retina screens */
float m_nativePixelSize;
+
+private:
+ GHOST_Context *m_context;
};
diff --git a/intern/ghost/intern/GHOST_WindowCocoa.h b/intern/ghost/intern/GHOST_WindowCocoa.h
index b30f6a340ad..3ed88086184 100644
--- a/intern/ghost/intern/GHOST_WindowCocoa.h
+++ b/intern/ghost/intern/GHOST_WindowCocoa.h
@@ -20,7 +20,7 @@
*
* The Original Code is: all of this file.
*
- * Contributor(s): none yet.
+ * Contributor(s): Maarten Gribnau, Jason Wilkins
*
* ***** END GPL LICENSE BLOCK *****
*/
@@ -42,20 +42,11 @@
@class CocoaWindow;
@class CocoaOpenGLView;
+@class NSCursor;
+@class NSScreen;
class GHOST_SystemCocoa;
-/**
- * Window on Mac OSX/Cocoa.
- * Carbon windows have a size widget in the lower right corner of the window.
- * To force it to be visible, the height of the client rectangle is reduced so
- * that applications do not draw in that area. GHOST will manage that area
- * which is called the gutter.
- * When OpenGL contexts are active, GHOST will use AGL_BUFFER_RECT to prevent
- * OpenGL drawing outside the reduced client rectangle.
- * \author Maarten Gribnau
- * \date May 23, 2001
- */
class GHOST_WindowCocoa : public GHOST_Window {
public:
/**
@@ -90,77 +81,77 @@ public:
* Destructor.
* Closes the window and disposes resources allocated.
*/
- virtual ~GHOST_WindowCocoa();
+ ~GHOST_WindowCocoa();
/**
* Returns indication as to whether the window is valid.
* \return The validity of the window.
*/
- virtual bool getValid() const;
+ bool getValid() const;
/**
* Returns the associated NSWindow object
* \return The associated NSWindow object
*/
- virtual void *getOSWindow() const;
+ void *getOSWindow() const;
/**
* Sets the title displayed in the title bar.
* \param title The title to display in the title bar.
*/
- virtual void setTitle(const STR_String& title);
+ void setTitle(const STR_String& title);
/**
* Returns the title displayed in the title bar.
* \param title The title displayed in the title bar.
*/
- virtual void getTitle(STR_String& title) const;
+ void getTitle(STR_String& title) const;
/**
* Returns the window rectangle dimensions.
* The dimensions are given in screen coordinates that are relative to the upper-left corner of the screen.
* \param bounds The bounding rectangle of the window.
*/
- virtual void getWindowBounds(GHOST_Rect& bounds) const;
+ void getWindowBounds(GHOST_Rect& bounds) const;
/**
* Returns the client rectangle dimensions.
* The left and top members of the rectangle are always zero.
* \param bounds The bounding rectangle of the client area of the window.
*/
- virtual void getClientBounds(GHOST_Rect& bounds) const;
+ void getClientBounds(GHOST_Rect& bounds) const;
/**
* Resizes client rectangle width.
* \param width The new width of the client area of the window.
*/
- virtual GHOST_TSuccess setClientWidth(GHOST_TUns32 width);
+ GHOST_TSuccess setClientWidth(GHOST_TUns32 width);
/**
* Resizes client rectangle height.
* \param height The new height of the client area of the window.
*/
- virtual GHOST_TSuccess setClientHeight(GHOST_TUns32 height);
+ GHOST_TSuccess setClientHeight(GHOST_TUns32 height);
/**
* Resizes client rectangle.
* \param width The new width of the client area of the window.
* \param height The new height of the client area of the window.
*/
- virtual GHOST_TSuccess setClientSize(GHOST_TUns32 width, GHOST_TUns32 height);
+ GHOST_TSuccess setClientSize(GHOST_TUns32 width, GHOST_TUns32 height);
/**
* Returns the state of the window (normal, minimized, maximized).
* \return The state of the window.
*/
- virtual GHOST_TWindowState getState() const;
+ GHOST_TWindowState getState() const;
/**
* Sets the window "modified" status, indicating unsaved changes
* \param isUnsavedChanges Unsaved changes or not
* \return Indication of success.
*/
- virtual GHOST_TSuccess setModifiedState(bool isUnsavedChanges);
+ GHOST_TSuccess setModifiedState(bool isUnsavedChanges);
/**
* Converts a point in screen coordinates to client rectangle coordinates
@@ -169,7 +160,7 @@ public:
* \param outX The x-coordinate in the client rectangle.
* \param outY The y-coordinate in the client rectangle.
*/
- virtual void screenToClient(GHOST_TInt32 inX, GHOST_TInt32 inY, GHOST_TInt32& outX, GHOST_TInt32& outY) const;
+ void screenToClient(GHOST_TInt32 inX, GHOST_TInt32 inY, GHOST_TInt32& outX, GHOST_TInt32& outY) const;
/**
* Converts a point in screen coordinates to client rectangle coordinates
@@ -178,7 +169,7 @@ public:
* \param outX The x-coordinate on the screen.
* \param outY The y-coordinate on the screen.
*/
- virtual void clientToScreen(GHOST_TInt32 inX, GHOST_TInt32 inY, GHOST_TInt32& outX, GHOST_TInt32& outY) const;
+ void clientToScreen(GHOST_TInt32 inX, GHOST_TInt32 inY, GHOST_TInt32& outX, GHOST_TInt32& outY) const;
/**
* Converts a point in screen coordinates to client rectangle coordinates
@@ -211,37 +202,17 @@ public:
* \param state The state of the window.
* \return Indication of success.
*/
- virtual GHOST_TSuccess setState(GHOST_TWindowState state);
+ GHOST_TSuccess setState(GHOST_TWindowState state);
/**
* Sets the order of the window (bottom, top).
* \param order The order of the window.
* \return Indication of success.
*/
- virtual GHOST_TSuccess setOrder(GHOST_TWindowOrder order);
-
- /**
- * Swaps front and back buffers of a window.
- * \return A boolean success indicator.
- */
- virtual GHOST_TSuccess swapBuffers();
-
- /**
- * Updates the drawing context of this window. Needed
- * whenever the window is changed.
- * \return Indication of success.
- */
- GHOST_TSuccess updateDrawingContext();
-
- /**
- * Activates the drawing context of this window.
- * \return A boolean success indicator.
- */
- virtual GHOST_TSuccess activateDrawingContext();
+ GHOST_TSuccess setOrder(GHOST_TWindowOrder order);
- virtual void loadCursor(bool visible, GHOST_TStandardCursor cursor) const;
+ void loadCursor(bool visible, GHOST_TStandardCursor cursor) const;
-
const GHOST_TabletData *GetTabletData()
{
return &m_tablet;
@@ -256,15 +227,15 @@ public:
* Sets the progress bar value displayed in the window/application icon
* \param progress The progress % (0.0 to 1.0)
*/
- virtual GHOST_TSuccess setProgressBar(float progress);
+ GHOST_TSuccess setProgressBar(float progress);
/**
* Hides the progress bar icon
*/
- virtual GHOST_TSuccess endProgressBar();
+ GHOST_TSuccess endProgressBar();
- virtual void setNativePixelSize(void);
+ void setNativePixelSize(void);
GHOST_TSuccess beginFullScreen() const {return GHOST_kFailure;}
@@ -278,51 +249,45 @@ public:
bool getImmediateDraw(void) const { return m_immediateDraw; }
protected:
- /**
- * Tries to install a rendering context in this window.
- * \param type The type of rendering context installed.
- * \return Indication as to whether installation has succeeded.
- */
- virtual GHOST_TSuccess installDrawingContext(GHOST_TDrawingContextType type);
/**
- * Removes the current drawing context.
- * \return Indication as to whether removal has succeeded.
+ * \param type The type of rendering context create.
+ * \return Indication of success.
*/
- virtual GHOST_TSuccess removeDrawingContext();
-
+ GHOST_Context *newDrawingContext(GHOST_TDrawingContextType type);
+
/**
* Invalidates the contents of this window.
* \return Indication of success.
*/
- virtual GHOST_TSuccess invalidate();
+ GHOST_TSuccess invalidate();
/**
* Sets the cursor visibility on the window using
* native window system calls.
*/
- virtual GHOST_TSuccess setWindowCursorVisibility(bool visible);
+ GHOST_TSuccess setWindowCursorVisibility(bool visible);
/**
* Sets the cursor grab on the window using
* native window system calls.
*/
- virtual GHOST_TSuccess setWindowCursorGrab(GHOST_TGrabCursorMode mode);
+ GHOST_TSuccess setWindowCursorGrab(GHOST_TGrabCursorMode mode);
/**
* Sets the cursor shape on the window using
* native window system calls.
*/
- virtual GHOST_TSuccess setWindowCursorShape(GHOST_TStandardCursor shape);
+ GHOST_TSuccess setWindowCursorShape(GHOST_TStandardCursor shape);
/**
* Sets the cursor shape on the window using
* native window system calls.
*/
- virtual GHOST_TSuccess setWindowCustomCursorShape(GHOST_TUns8 *bitmap, GHOST_TUns8 *mask,
+ GHOST_TSuccess setWindowCustomCursorShape(GHOST_TUns8 *bitmap, GHOST_TUns8 *mask,
int sizex, int sizey, int hotX, int hotY, int fg_color, int bg_color);
- virtual GHOST_TSuccess setWindowCustomCursorShape(GHOST_TUns8 bitmap[16][2], GHOST_TUns8 mask[16][2], int hotX, int hotY);
+ GHOST_TSuccess setWindowCustomCursorShape(GHOST_TUns8 bitmap[16][2], GHOST_TUns8 mask[16][2], int hotX, int hotY);
/** The window containing the OpenGL view */
CocoaWindow *m_window;
@@ -330,15 +295,9 @@ protected:
/** The openGL view */
CocoaOpenGLView *m_openGLView;
- /** The opgnGL drawing context */
- NSOpenGLContext *m_openGLContext;
-
/** The mother SystemCocoa class to send events */
GHOST_SystemCocoa *m_systemCocoa;
-
- /** The first created OpenGL context (for sharing display lists) */
- static NSOpenGLContext *s_firstOpenGLcontext;
-
+
NSCursor *m_customCursor;
GHOST_TabletData m_tablet;
@@ -349,4 +308,3 @@ protected:
};
#endif // __GHOST_WINDOWCOCOA_H__
-
diff --git a/intern/ghost/intern/GHOST_WindowCocoa.mm b/intern/ghost/intern/GHOST_WindowCocoa.mm
index f9b8899fbe5..9c7b5c3fee7 100644
--- a/intern/ghost/intern/GHOST_WindowCocoa.mm
+++ b/intern/ghost/intern/GHOST_WindowCocoa.mm
@@ -20,29 +20,31 @@
*
* The Original Code is: all of this file.
*
- * Contributor(s): Maarten Gribnau 05/2001
- Damien Plisson 10/2009
+ * Contributor(s): Maarten Gribnau 05/2001
+ * Damien Plisson 10/2009
+ * Jason Wilkins 02/2014
+ * Jens Verwiebe 10/2014
*
* ***** END GPL LICENSE BLOCK *****
*/
-#include <Cocoa/Cocoa.h>
+#include "GHOST_WindowCocoa.h"
+#include "GHOST_SystemCocoa.h"
+#include "GHOST_ContextNone.h"
+#include "GHOST_Debug.h"
-#if MAC_OS_X_VERSION_MIN_REQUIRED <= 1050
-//Use of the SetSystemUIMode function (64bit compatible)
-#include <Carbon/Carbon.h>
+#if defined(WITH_GL_EGL)
+# include "GHOST_ContextEGL.h"
+#else
+# include "GHOST_ContextCGL.h"
#endif
-#include <OpenGL/gl.h>
-#include <OpenGL/CGLRenderers.h>
-/***** Multithreaded opengl code : uncomment for enabling
-#include <OpenGL/OpenGL.h>
-*/
+#include <Cocoa/Cocoa.h>
-
-#include "GHOST_WindowCocoa.h"
-#include "GHOST_SystemCocoa.h"
-#include "GHOST_Debug.h"
+#if MAC_OS_X_VERSION_MIN_REQUIRED <= 1050
+ //Use of the SetSystemUIMode function (64bit compatible)
+# include <Carbon/Carbon.h>
+#endif
#include <sys/sysctl.h>
@@ -74,7 +76,6 @@ enum {
- (void)windowDidChangeBackingProperties:(NSNotification *)notification;
@end
-
@implementation CocoaWindowDelegate : NSObject
- (void)setSystemAndWindowCocoa:(GHOST_SystemCocoa *)sysCocoa windowCocoa:(GHOST_WindowCocoa *)winCocoa
{
@@ -85,6 +86,8 @@ enum {
- (void)windowDidBecomeKey:(NSNotification *)notification
{
systemCocoa->handleWindowEvent(GHOST_kEventWindowActivate, associatedWindow);
+ // work around for broken appswitching when combining cmd-tab and missioncontrol
+ [(NSWindow*)associatedWindow->getOSWindow() orderFrontRegardless];
}
- (void)windowDidResignKey:(NSNotification *)notification
@@ -168,6 +171,7 @@ enum {
- (void)setSystemAndWindowCocoa:(GHOST_SystemCocoa *)sysCocoa windowCocoa:(GHOST_WindowCocoa *)winCocoa;
- (GHOST_SystemCocoa*)systemCocoa;
@end
+
@implementation CocoaWindow
- (void)setSystemAndWindowCocoa:(GHOST_SystemCocoa *)sysCocoa windowCocoa:(GHOST_WindowCocoa *)winCocoa
{
@@ -258,8 +262,6 @@ enum {
@end
-
-
#pragma mark NSOpenGLView subclass
//We need to subclass it in order to give Cocoa the feeling key events are trapped
@interface CocoaOpenGLView : NSOpenGLView <NSTextInput>
@@ -274,6 +276,7 @@ enum {
}
- (void)setSystemAndWindowCocoa:(GHOST_SystemCocoa *)sysCocoa windowCocoa:(GHOST_WindowCocoa *)winCocoa;
@end
+
@implementation CocoaOpenGLView
- (void)setSystemAndWindowCocoa:(GHOST_SystemCocoa *)sysCocoa windowCocoa:(GHOST_WindowCocoa *)winCocoa
@@ -535,8 +538,6 @@ enum {
@end
#endif
-NSOpenGLContext* GHOST_WindowCocoa::s_firstOpenGLcontext = nil;
-
GHOST_WindowCocoa::GHOST_WindowCocoa(
GHOST_SystemCocoa *systemCocoa,
const STR_String& title,
@@ -548,13 +549,9 @@ GHOST_WindowCocoa::GHOST_WindowCocoa(
GHOST_TDrawingContextType type,
const bool stereoVisual, const GHOST_TUns16 numOfAASamples
) :
- GHOST_Window(width, height, state, GHOST_kDrawingContextTypeNone, stereoVisual, false, numOfAASamples),
+ GHOST_Window(width, height, state, stereoVisual, false, numOfAASamples),
m_customCursor(0)
{
- NSOpenGLPixelFormatAttribute pixelFormatAttrsWindow[40];
- NSOpenGLPixelFormat *pixelFormat = nil;
- int i;
-
m_systemCocoa = systemCocoa;
m_fullScreen = false;
m_immediateDraw = false;
@@ -572,8 +569,9 @@ GHOST_WindowCocoa::GHOST_WindowCocoa(
rect.size.height = height;
m_window = [[CocoaWindow alloc] initWithContentRect:rect
- styleMask:NSTitledWindowMask | NSClosableWindowMask | NSResizableWindowMask | NSMiniaturizableWindowMask
- backing:NSBackingStoreBuffered defer:NO];
+ styleMask:NSTitledWindowMask | NSClosableWindowMask | NSResizableWindowMask | NSMiniaturizableWindowMask
+ backing:NSBackingStoreBuffered defer:NO];
+
if (m_window == nil) {
[pool drain];
return;
@@ -586,104 +584,10 @@ GHOST_WindowCocoa::GHOST_WindowCocoa(
minSize.height = 240;
[m_window setContentMinSize:minSize];
- setTitle(title);
-
-
- // Pixel Format Attributes for the windowed NSOpenGLContext
- i=0;
- pixelFormatAttrsWindow[i++] = NSOpenGLPFADoubleBuffer;
-
- // Guarantees the back buffer contents to be valid after a call to NSOpenGLContext object's flushBuffer
- // needed for 'Draw Overlap' drawing method
- pixelFormatAttrsWindow[i++] = NSOpenGLPFABackingStore;
-
- // Force software OpenGL, for debugging
- if (getenv("BLENDER_SOFTWAREGL")) {
- pixelFormatAttrsWindow[i++] = NSOpenGLPFARendererID;
- pixelFormatAttrsWindow[i++] = kCGLRendererAppleSWID;
- }
- else
- pixelFormatAttrsWindow[i++] = NSOpenGLPFAAccelerated;
-
- //pixelFormatAttrsWindow[i++] = NSOpenGLPFAAllowOfflineRenderers,; // Removed to allow 10.4 builds, and 2 GPUs rendering is not used anyway
-
- pixelFormatAttrsWindow[i++] = NSOpenGLPFADepthSize;
- pixelFormatAttrsWindow[i++] = (NSOpenGLPixelFormatAttribute) 32;
-
- pixelFormatAttrsWindow[i++] = NSOpenGLPFAAccumSize;
- pixelFormatAttrsWindow[i++] = (NSOpenGLPixelFormatAttribute) 32;
-
- if (stereoVisual) pixelFormatAttrsWindow[i++] = NSOpenGLPFAStereo;
-
- if (numOfAASamples > 0) {
- // Multisample anti-aliasing
- pixelFormatAttrsWindow[i++] = NSOpenGLPFAMultisample;
-
- pixelFormatAttrsWindow[i++] = NSOpenGLPFASampleBuffers;
- pixelFormatAttrsWindow[i++] = (NSOpenGLPixelFormatAttribute) 1;
-
- pixelFormatAttrsWindow[i++] = NSOpenGLPFASamples;
- pixelFormatAttrsWindow[i++] = (NSOpenGLPixelFormatAttribute) numOfAASamples;
-
- pixelFormatAttrsWindow[i++] = NSOpenGLPFANoRecovery;
- }
-
- pixelFormatAttrsWindow[i] = (NSOpenGLPixelFormatAttribute) 0;
-
- pixelFormat = [[NSOpenGLPixelFormat alloc] initWithAttributes:pixelFormatAttrsWindow];
-
-
- //Fall back to no multisampling if Antialiasing init failed
- if (pixelFormat == nil) {
- i=0;
- pixelFormatAttrsWindow[i++] = NSOpenGLPFADoubleBuffer;
-
- // Guarantees the back buffer contents to be valid after a call to NSOpenGLContext object's flushBuffer
- // needed for 'Draw Overlap' drawing method
- pixelFormatAttrsWindow[i++] = NSOpenGLPFABackingStore;
-
- // Force software OpenGL, for debugging
- if (getenv("BLENDER_SOFTWAREGL")) {
- pixelFormatAttrsWindow[i++] = NSOpenGLPFARendererID;
- pixelFormatAttrsWindow[i++] = kCGLRendererAppleSWID;
- }
- else
- pixelFormatAttrsWindow[i++] = NSOpenGLPFAAccelerated;
-
- //pixelFormatAttrsWindow[i++] = NSOpenGLPFAAllowOfflineRenderers,; // Removed to allow 10.4 builds, and 2 GPUs rendering is not used anyway
-
- pixelFormatAttrsWindow[i++] = NSOpenGLPFADepthSize;
- pixelFormatAttrsWindow[i++] = (NSOpenGLPixelFormatAttribute) 32;
-
- pixelFormatAttrsWindow[i++] = NSOpenGLPFAAccumSize;
- pixelFormatAttrsWindow[i++] = (NSOpenGLPixelFormatAttribute) 32;
-
- if (stereoVisual) pixelFormatAttrsWindow[i++] = NSOpenGLPFAStereo;
-
- pixelFormatAttrsWindow[i] = (NSOpenGLPixelFormatAttribute) 0;
-
- pixelFormat = [[NSOpenGLPixelFormat alloc] initWithAttributes:pixelFormatAttrsWindow];
-
- }
-
- if (numOfAASamples > 0) { //Set m_numOfAASamples to the actual value
- GLint gli;
- [pixelFormat getValues:&gli forAttribute:NSOpenGLPFASamples forVirtualScreen:0];
- if (m_numOfAASamples != (GHOST_TUns16)gli) {
- m_numOfAASamples = (GHOST_TUns16)gli;
- printf("GHOST_Window could be created with anti-aliasing of only %i samples\n",m_numOfAASamples);
- }
- }
-
//Creates the OpenGL View inside the window
- m_openGLView = [[CocoaOpenGLView alloc] initWithFrame:rect
- pixelFormat:pixelFormat];
-
- [m_openGLView setSystemAndWindowCocoa:systemCocoa windowCocoa:this];
-
- [pixelFormat release];
+ m_openGLView = [[CocoaOpenGLView alloc] initWithFrame:rect];
- m_openGLContext = [m_openGLView openGLContext]; //This context will be replaced by the proper one just after
+ [m_openGLView setSystemAndWindowCocoa:systemCocoa windowCocoa:this];
[m_window setContentView:m_openGLView];
[m_window setInitialFirstResponder:m_openGLView];
@@ -694,6 +598,7 @@ GHOST_WindowCocoa::GHOST_WindowCocoa(
updateDrawingContext();
activateDrawingContext();
+ // XXX jwilkins: This seems like it belongs in GHOST_ContextCGL, but probably not GHOST_ContextEGL
if (m_systemCocoa->m_nativePixel) {
if ([m_openGLView respondsToSelector:@selector(setWantsBestResolutionOpenGLSurface:)]) {
[m_openGLView setWantsBestResolutionOpenGLSurface:YES];
@@ -703,6 +608,8 @@ GHOST_WindowCocoa::GHOST_WindowCocoa(
}
}
+ setTitle(title);
+
m_tablet.Active = GHOST_kTabletModeNone;
CocoaWindowDelegate *windowDelegate = [[CocoaWindowDelegate alloc] init];
@@ -717,7 +624,7 @@ GHOST_WindowCocoa::GHOST_WindowCocoa(
#endif
[m_window registerForDraggedTypes:[NSArray arrayWithObjects:NSFilenamesPboardType,
- NSStringPboardType, NSTIFFPboardType, nil]];
+ NSStringPboardType, NSTIFFPboardType, nil]];
#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060
if (state != GHOST_kWindowStateFullScreen) {
@@ -728,15 +635,18 @@ GHOST_WindowCocoa::GHOST_WindowCocoa(
if (state == GHOST_kWindowStateFullScreen)
setState(GHOST_kWindowStateFullScreen);
- //Starting with 10.9 (darwin 13.x.x), we always use Lion fullscreen, since it
- //now has proper multi-monitor support for fullscreen
- char darwin_ver[10];
- size_t len = sizeof(darwin_ver);
- sysctlbyname("kern.osrelease", &darwin_ver, &len, NULL, 0);
- if(darwin_ver[0] == '1' && darwin_ver[1] >= '3') {
+ // Starting with 10.9 (darwin 13.x.x), we can use Lion fullscreen,
+ // since it now has better multi-monitor support
+ // if the screens are spawned, additional screens get useless,
+ // so we only use lionStyleFullScreen when screens have separate spaces
+
+ if ([NSScreen respondsToSelector:@selector(screensHaveSeparateSpaces)] && [NSScreen screensHaveSeparateSpaces]) {
+ // implies we are on >= OSX 10.9
m_lionStyleFullScreen = true;
}
+ [NSApp activateIgnoringOtherApps:YES]; // raise application to front, important for new blender instance animation play case
+
[pool drain];
}
@@ -750,6 +660,8 @@ GHOST_WindowCocoa::~GHOST_WindowCocoa()
m_customCursor = nil;
}
+ releaseNativeHandles();
+
[m_openGLView release];
if (m_window) {
@@ -774,7 +686,7 @@ GHOST_WindowCocoa::~GHOST_WindowCocoa()
bool GHOST_WindowCocoa::getValid() const
{
- return (m_window != 0);
+ return GHOST_Window::getValid() && m_window != 0 && m_openGLView != 0;
}
void* GHOST_WindowCocoa::getOSWindow() const
@@ -877,7 +789,7 @@ void GHOST_WindowCocoa::getClientBounds(GHOST_Rect& bounds) const
//Max window contents as screen size (excluding title bar...)
NSRect contentRect = [CocoaWindow contentRectForFrameRect:screenSize
- styleMask:(NSTitledWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask | NSResizableWindowMask)];
+ styleMask:(NSTitledWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask | NSResizableWindowMask)];
rect = [m_window contentRectForFrameRect:[m_window frame]];
@@ -962,7 +874,12 @@ GHOST_TWindowState GHOST_WindowCocoa::getState() const
if (masks & NSFullScreenWindowMask) {
// Lion style fullscreen
- state = GHOST_kWindowStateFullScreen;
+ if (!m_immediateDraw) {
+ state = GHOST_kWindowStateFullScreen;
+ }
+ else {
+ state = GHOST_kWindowStateNormal;
+ }
}
else
#endif
@@ -976,7 +893,12 @@ GHOST_TWindowState GHOST_WindowCocoa::getState() const
state = GHOST_kWindowStateMaximized;
}
else {
- state = GHOST_kWindowStateNormal;
+ if (m_immediateDraw) {
+ state = GHOST_kWindowStateFullScreen;
+ }
+ else {
+ state = GHOST_kWindowStateNormal;
+ }
}
[pool drain];
return state;
@@ -1119,10 +1041,10 @@ GHOST_TSuccess GHOST_WindowCocoa::setState(GHOST_TWindowState state)
}
//Create a fullscreen borderless window
CocoaWindow *tmpWindow = [[CocoaWindow alloc]
- initWithContentRect:[[m_window screen] frame]
- styleMask:NSBorderlessWindowMask
- backing:NSBackingStoreBuffered
- defer:YES];
+ initWithContentRect:[[m_window screen] frame]
+ styleMask:NSBorderlessWindowMask
+ backing:NSBackingStoreBuffered
+ defer:YES];
//Copy current window parameters
[tmpWindow setTitle:[m_window title]];
[tmpWindow setRepresentedFilename:[m_window representedFilename]];
@@ -1189,10 +1111,10 @@ GHOST_TSuccess GHOST_WindowCocoa::setState(GHOST_TWindowState state)
}
//Create a fullscreen borderless window
CocoaWindow *tmpWindow = [[CocoaWindow alloc]
- initWithContentRect:[[m_window screen] frame]
- styleMask:(NSTitledWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask | NSResizableWindowMask)
- backing:NSBackingStoreBuffered
- defer:YES];
+ initWithContentRect:[[m_window screen] frame]
+ styleMask:(NSTitledWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask | NSResizableWindowMask)
+ backing:NSBackingStoreBuffered
+ defer:YES];
//Copy current window parameters
[tmpWindow setTitle:[m_window title]];
[tmpWindow setRepresentedFilename:[m_window representedFilename]];
@@ -1200,7 +1122,7 @@ GHOST_TSuccess GHOST_WindowCocoa::setState(GHOST_TWindowState state)
[tmpWindow setDelegate:[m_window delegate]];
[tmpWindow setSystemAndWindowCocoa:[m_window systemCocoa] windowCocoa:this];
[tmpWindow registerForDraggedTypes:[NSArray arrayWithObjects:NSFilenamesPboardType,
- NSStringPboardType, NSTIFFPboardType, nil]];
+ NSStringPboardType, NSTIFFPboardType, nil]];
//Forbid to resize the window below the blender defined minimum one
[tmpWindow setContentMinSize:NSMakeSize(320, 240)];
@@ -1266,131 +1188,95 @@ GHOST_TSuccess GHOST_WindowCocoa::setOrder(GHOST_TWindowOrder order)
#pragma mark Drawing context
-/*#define WAIT_FOR_VSYNC 1*/
-
-GHOST_TSuccess GHOST_WindowCocoa::swapBuffers()
-{
- if (m_drawingContextType == GHOST_kDrawingContextTypeOpenGL) {
- if (m_openGLContext != nil) {
- NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
- [m_openGLContext flushBuffer];
- [pool drain];
- return GHOST_kSuccess;
- }
- }
- return GHOST_kFailure;
-}
-
-GHOST_TSuccess GHOST_WindowCocoa::updateDrawingContext()
-{
- if (m_drawingContextType == GHOST_kDrawingContextTypeOpenGL) {
- if (m_openGLContext != nil) {
- NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
- [m_openGLContext update];
- [pool drain];
- return GHOST_kSuccess;
- }
- }
- return GHOST_kFailure;
-}
+GHOST_Context *GHOST_WindowCocoa::newDrawingContext(GHOST_TDrawingContextType type)
+{
+ if (type == GHOST_kDrawingContextTypeOpenGL) {
+#if !defined(WITH_GL_EGL)
+
+#if defined(WITH_GL_PROFILE_CORE)
+ GHOST_Context *context = new GHOST_ContextCGL(
+ m_wantStereoVisual,
+ m_wantNumOfAASamples,
+ m_window,
+ m_openGLView,
+ GL_CONTEXT_CORE_PROFILE_BIT,
+ 3, 2,
+ GHOST_OPENGL_CGL_CONTEXT_FLAGS,
+ GHOST_OPENGL_CGL_RESET_NOTIFICATION_STRATEGY);
+#elif defined(WITH_GL_PROFILE_ES20)
+ GHOST_Context *context = new GHOST_ContextCGL(
+ m_wantStereoVisual,
+ m_wantNumOfAASamples,
+ m_window,
+ m_openGLView,
+ CGL_CONTEXT_ES2_PROFILE_BIT_EXT,
+ 2, 0,
+ GHOST_OPENGL_CGL_CONTEXT_FLAGS,
+ GHOST_OPENGL_CGL_RESET_NOTIFICATION_STRATEGY);
+#elif defined(WITH_GL_PROFILE_COMPAT)
+ GHOST_Context *context = new GHOST_ContextCGL(
+ m_wantStereoVisual,
+ m_wantNumOfAASamples,
+ m_window,
+ m_openGLView,
+ 0, // profile bit
+ 0, 0,
+ GHOST_OPENGL_CGL_CONTEXT_FLAGS,
+ GHOST_OPENGL_CGL_RESET_NOTIFICATION_STRATEGY);
+#else
+# error
+#endif
-GHOST_TSuccess GHOST_WindowCocoa::activateDrawingContext()
-{
- if (m_drawingContextType == GHOST_kDrawingContextTypeOpenGL) {
- if (m_openGLContext != nil) {
- NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
- [m_openGLContext makeCurrentContext];
-
- // Disable AA by default
- if (m_numOfAASamples > 0) glDisable(GL_MULTISAMPLE_ARB);
- [pool drain];
- return GHOST_kSuccess;
- }
- }
- return GHOST_kFailure;
-}
+#else
+#if defined(WITH_GL_PROFILE_CORE)
+ GHOST_Context *context = new GHOST_ContextEGL(
+ m_wantStereoVisual,
+ m_wantNumOfAASamples,
+ m_window,
+ m_openGLView,
+ EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT,
+ 3, 2,
+ GHOST_OPENGL_EGL_CONTEXT_FLAGS,
+ GHOST_OPENGL_EGL_RESET_NOTIFICATION_STRATEGY,
+ EGL_OPENGL_API);
+#elif defined(WITH_GL_PROFILE_ES20)
+ GHOST_Context *context = new GHOST_ContextEGL(
+ m_wantStereoVisual,
+ m_wantNumOfAASamples,
+ m_window,
+ m_openGLView,
+ 0, // profile bit
+ 2, 0,
+ GHOST_OPENGL_EGL_CONTEXT_FLAGS,
+ GHOST_OPENGL_EGL_RESET_NOTIFICATION_STRATEGY,
+ EGL_OPENGL_ES_API);
+#elif defined(WITH_GL_PROFILE_COMPAT)
+ GHOST_Context *context = new GHOST_ContextEGL(
+ m_wantStereoVisual,
+ m_wantNumOfAASamples,
+ m_window,
+ m_openGLView,
+ 0, // profile bit
+ 0, 0,
+ GHOST_OPENGL_EGL_CONTEXT_FLAGS,
+ GHOST_OPENGL_EGL_RESET_NOTIFICATION_STRATEGY,
+ EGL_OPENGL_API);
+#else
+# error
+#endif
-GHOST_TSuccess GHOST_WindowCocoa::installDrawingContext(GHOST_TDrawingContextType type)
-{
- GHOST_TSuccess success = GHOST_kFailure;
-
- NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
-
- NSOpenGLPixelFormat *pixelFormat;
- NSOpenGLContext *tmpOpenGLContext;
-
- /***** Multithreaded opengl code : uncomment for enabling
- CGLContextObj cglCtx;
- */
-
- switch (type) {
- case GHOST_kDrawingContextTypeOpenGL:
- if (!getValid()) break;
-
- pixelFormat = [m_openGLView pixelFormat];
- tmpOpenGLContext = [[NSOpenGLContext alloc] initWithFormat:pixelFormat
- shareContext:s_firstOpenGLcontext];
- if (tmpOpenGLContext == nil) {
- success = GHOST_kFailure;
- break;
- }
-
- //Switch openGL to multhreaded mode
- /******* Multithreaded opengl code : uncomment for enabling
- cglCtx = (CGLContextObj)[tmpOpenGLContext CGLContextObj];
- if (CGLEnable(cglCtx, kCGLCEMPEngine) == kCGLNoError)
- printf("\nSwitched openGL to multithreaded mode\n");
- */
-
- if (!s_firstOpenGLcontext) s_firstOpenGLcontext = tmpOpenGLContext;
-#ifdef WAIT_FOR_VSYNC
- {
- GLint swapInt = 1;
- /* wait for vsync, to avoid tearing artifacts */
- [tmpOpenGLContext setValues:&swapInt forParameter:NSOpenGLCPSwapInterval];
- }
#endif
- [m_openGLView setOpenGLContext:tmpOpenGLContext];
- [tmpOpenGLContext setView:m_openGLView];
-
- m_openGLContext = tmpOpenGLContext;
- break;
-
- case GHOST_kDrawingContextTypeNone:
- success = GHOST_kSuccess;
- break;
-
- default:
- break;
+ if (context->initializeDrawingContext())
+ return context;
+ else
+ delete context;
}
- [pool drain];
- return success;
-}
-
-GHOST_TSuccess GHOST_WindowCocoa::removeDrawingContext()
-{
- NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
- switch (m_drawingContextType) {
- case GHOST_kDrawingContextTypeOpenGL:
- if (m_openGLContext) {
- [m_openGLView clearGLContext];
- if (s_firstOpenGLcontext == m_openGLContext) s_firstOpenGLcontext = nil;
- m_openGLContext = nil;
- }
- [pool drain];
- return GHOST_kSuccess;
- case GHOST_kDrawingContextTypeNone:
- [pool drain];
- return GHOST_kSuccess;
- break;
- default:
- [pool drain];
- return GHOST_kFailure;
- }
+ return NULL;
}
+#pragma mark invalidate
GHOST_TSuccess GHOST_WindowCocoa::invalidate()
{
@@ -1442,6 +1328,17 @@ GHOST_TSuccess GHOST_WindowCocoa::setProgressBar(float progress)
return GHOST_kSuccess;
}
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1080
+static void postNotification()
+{
+ NSUserNotification *notification = [[NSUserNotification alloc] init];
+ notification.title = @"Blender progress notification";
+ notification.informativeText = @"Calculation is finished";
+ notification.soundName = NSUserNotificationDefaultSoundName;
+ [[NSUserNotificationCenter defaultUserNotificationCenter] deliverNotification:notification];
+ [notification release];
+}
+#endif
GHOST_TSuccess GHOST_WindowCocoa::endProgressBar()
{
@@ -1455,14 +1352,23 @@ GHOST_TSuccess GHOST_WindowCocoa::endProgressBar()
[[NSImage imageNamed:@"NSApplicationIcon"] drawAtPoint:NSZeroPoint fromRect:NSZeroRect operation:NSCompositeSourceOver fraction:1.0];
[dockIcon unlockFocus];
[NSApp setApplicationIconImage:dockIcon];
+
+
+ // With OSX 10.8 and later, we can use notifications to inform the user when the progress reached 100%
+ // Atm. just fire this when the progressbar ends, the behavior is controlled in the NotificationCenter
+ // If Blender is not frontmost window, a message pops up with sound, in any case an entry in notifications
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1080
+ if ([NSUserNotificationCenter respondsToSelector:@selector(defaultUserNotificationCenter)]) {
+ postNotification();
+ }
+#endif
+
[dockIcon release];
[pool drain];
return GHOST_kSuccess;
}
-
-
#pragma mark Cursor handling
void GHOST_WindowCocoa::loadCursor(bool visible, GHOST_TStandardCursor cursor) const
@@ -1650,15 +1556,15 @@ GHOST_TSuccess GHOST_WindowCocoa::setWindowCustomCursorShape(GHOST_TUns8 *bitmap
cursorImageRep = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:nil
- pixelsWide:sizex
- pixelsHigh:sizey
- bitsPerSample:1
- samplesPerPixel:2
- hasAlpha:YES
- isPlanar:YES
- colorSpaceName:NSDeviceWhiteColorSpace
+ pixelsWide:sizex
+ pixelsHigh:sizey
+ bitsPerSample:1
+ samplesPerPixel:2
+ hasAlpha:YES
+ isPlanar:YES
+ colorSpaceName:NSDeviceWhiteColorSpace
bytesPerRow:(sizex/8 + (sizex%8 >0 ?1:0))
- bitsPerPixel:1];
+ bitsPerPixel:1];
cursorBitmap = (GHOST_TUns16*)[cursorImageRep bitmapData];
@@ -1686,7 +1592,7 @@ GHOST_TSuccess GHOST_WindowCocoa::setWindowCustomCursorShape(GHOST_TUns8 *bitmap
//foreground and background color parameter is not handled for now (10.6)
m_customCursor = [[NSCursor alloc] initWithImage:cursorImage
- hotSpot:hotSpotPoint];
+ hotSpot:hotSpotPoint];
[cursorImageRep release];
[cursorImage release];
diff --git a/intern/ghost/intern/GHOST_WindowManager.cpp b/intern/ghost/intern/GHOST_WindowManager.cpp
index 1f20e01ca73..83490cecce5 100644
--- a/intern/ghost/intern/GHOST_WindowManager.cpp
+++ b/intern/ghost/intern/GHOST_WindowManager.cpp
@@ -121,7 +121,7 @@ GHOST_IWindow *GHOST_WindowManager::getFullScreenWindow(void) const
GHOST_TSuccess GHOST_WindowManager::beginFullScreen(GHOST_IWindow *window,
- bool stereoVisual)
+ bool /*stereoVisual*/)
{
GHOST_TSuccess success = GHOST_kFailure;
GHOST_ASSERT(window, "GHOST_WindowManager::beginFullScreen(): invalid window");
diff --git a/intern/ghost/intern/GHOST_WindowManager.h b/intern/ghost/intern/GHOST_WindowManager.h
index 8297e4d24d2..e868a9b0416 100644
--- a/intern/ghost/intern/GHOST_WindowManager.h
+++ b/intern/ghost/intern/GHOST_WindowManager.h
@@ -55,7 +55,7 @@ public:
/**
* Destructor.
*/
- virtual ~GHOST_WindowManager();
+ ~GHOST_WindowManager();
/**
* Add a window to our list.
@@ -63,67 +63,67 @@ public:
* \param window Pointer to the window to be added.
* \return Indication of success.
*/
- virtual GHOST_TSuccess addWindow(GHOST_IWindow *window);
+ GHOST_TSuccess addWindow(GHOST_IWindow *window);
/**
* Remove a window from our list.
* \param window Pointer to the window to be removed.
* \return Indication of success.
*/
- virtual GHOST_TSuccess removeWindow(const GHOST_IWindow *window);
+ GHOST_TSuccess removeWindow(const GHOST_IWindow *window);
/**
* Returns whether the window is in our list.
* \param window Pointer to the window to query.
* \return A boolean indicator.
*/
- virtual bool getWindowFound(const GHOST_IWindow *window) const;
+ bool getWindowFound(const GHOST_IWindow *window) const;
/**
* Returns whether one of the windows is fullscreen.
* \return A boolean indicator.
*/
- virtual bool getFullScreen(void) const;
+ bool getFullScreen(void) const;
/**
* Returns pointer to the full-screen window.
* \return The full-screen window (NULL if not in full-screen).
*/
- virtual GHOST_IWindow *getFullScreenWindow(void) const;
+ GHOST_IWindow *getFullScreenWindow(void) const;
/**
* Activates fullscreen mode for a window.
* \param window The window displayed fullscreen.
* \return Indication of success.
*/
- virtual GHOST_TSuccess beginFullScreen(GHOST_IWindow *window, const bool stereoVisual);
+ GHOST_TSuccess beginFullScreen(GHOST_IWindow *window, const bool stereoVisual);
/**
* Closes fullscreen mode down.
* \return Indication of success.
*/
- virtual GHOST_TSuccess endFullScreen(void);
+ GHOST_TSuccess endFullScreen(void);
/**
* Sets new window as active window (the window receiving events).
* There can be only one window active which should be in the current window list.
* \param window The new active window.
*/
- virtual GHOST_TSuccess setActiveWindow(GHOST_IWindow *window);
+ GHOST_TSuccess setActiveWindow(GHOST_IWindow *window);
/**
* Returns the active window (the window receiving events).
* There can be only one window active which should be in the current window list.
* \return window The active window (or NULL if there is none).
*/
- virtual GHOST_IWindow *getActiveWindow(void) const;
+ GHOST_IWindow *getActiveWindow(void) const;
/**
* Set this window to be inactive (not receiving events).
* \param window The window to deactivate.
*/
- virtual void setWindowInactive(const GHOST_IWindow *window);
+ void setWindowInactive(const GHOST_IWindow *window);
/**
@@ -140,7 +140,7 @@ public:
* \param osWindow The OS window object/handle
* \return The associated window, null if none corresponds
*/
- virtual GHOST_IWindow *getWindowAssociatedWithOSWindow(void *osWindow);
+ GHOST_IWindow *getWindowAssociatedWithOSWindow(void *osWindow);
/**
* Return true if any windows has a modified status
diff --git a/intern/ghost/intern/GHOST_WindowNULL.h b/intern/ghost/intern/GHOST_WindowNULL.h
index c848d773bd6..80a1274a2a9 100644
--- a/intern/ghost/intern/GHOST_WindowNULL.h
+++ b/intern/ghost/intern/GHOST_WindowNULL.h
@@ -53,7 +53,7 @@ public:
const bool stereoVisual,
const GHOST_TUns16 numOfAASamples
) :
- GHOST_Window(width, height, state, type, stereoVisual, false, numOfAASamples),
+ GHOST_Window(width, height, state, stereoVisual, false, numOfAASamples),
m_system(system)
{
setTitle(title);
@@ -91,6 +91,12 @@ protected:
private:
GHOST_SystemNULL *m_system;
+
+ /**
+ * \param type The type of rendering context create.
+ * \return Indication of success.
+ */
+ GHOST_Context *newDrawingContext(GHOST_TDrawingContextType type) {return NULL;}
};
diff --git a/intern/ghost/intern/GHOST_WindowSDL.cpp b/intern/ghost/intern/GHOST_WindowSDL.cpp
index 4a1086144f4..1335c38d977 100644
--- a/intern/ghost/intern/GHOST_WindowSDL.cpp
+++ b/intern/ghost/intern/GHOST_WindowSDL.cpp
@@ -26,10 +26,11 @@
#include "GHOST_WindowSDL.h"
#include "SDL_mouse.h"
-#include <GL/glew.h>
-#include <assert.h>
+#include "glew-mx.h"
+
+#include "GHOST_ContextSDL.h"
-static SDL_GLContext s_firstContext = NULL;
+#include <assert.h>
GHOST_WindowSDL::GHOST_WindowSDL(GHOST_SystemSDL *system,
const STR_String& title,
@@ -44,39 +45,29 @@ GHOST_WindowSDL::GHOST_WindowSDL(GHOST_SystemSDL *system,
const bool exclusive,
const GHOST_TUns16 numOfAASamples
)
- :
- GHOST_Window(width, height, state, type, stereoVisual, exclusive, numOfAASamples),
- m_system(system),
- m_invalid_window(false),
- m_sdl_custom_cursor(NULL)
+ : GHOST_Window(width, height, state, stereoVisual, exclusive, numOfAASamples),
+ m_system(system),
+ m_valid_setup(false),
+ m_invalid_window(false),
+ m_sdl_custom_cursor(NULL)
{
- SDL_GL_SetAttribute(SDL_GL_SHARE_WITH_CURRENT_CONTEXT, 1);
- SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
- SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
- SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
- SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
- SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
- SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8);
-
- if (numOfAASamples) {
- SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1);
- SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, numOfAASamples);
- }
/* creating the window _must_ come after setting attributes */
- m_sdl_win = SDL_CreateWindow(title,
- left,
- top,
- width,
- height,
- SDL_WINDOW_RESIZABLE | SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN);
-
-
-
- m_sdl_glcontext = SDL_GL_CreateContext(m_sdl_win);
+ m_sdl_win = SDL_CreateWindow(
+ title,
+ left, top,
+ width, height,
+ SDL_WINDOW_RESIZABLE | SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN);
+
+ /* now set up the rendering context. */
+ if (setDrawingContextType(type) == GHOST_kSuccess) {
+ m_valid_setup = true;
+ GHOST_PRINT("Created window\n");
+ }
- //fprintf(stderr, "Ignoring Xlib error: error code %d request code %d\n",
- // theEvent->error_code, theEvent->request_code);
+ if (exclusive) {
+ SDL_RaiseWindow(m_sdl_win);
+ }
setTitle(title);
}
@@ -87,64 +78,38 @@ GHOST_WindowSDL::~GHOST_WindowSDL()
SDL_FreeCursor(m_sdl_custom_cursor);
}
- if (m_sdl_glcontext != s_firstContext) {
- SDL_GL_DeleteContext(m_sdl_glcontext);
- }
+ releaseNativeHandles();
SDL_DestroyWindow(m_sdl_win);
}
-GHOST_TSuccess
-GHOST_WindowSDL::installDrawingContext(GHOST_TDrawingContextType type)
+GHOST_Context *
+GHOST_WindowSDL::newDrawingContext(GHOST_TDrawingContextType type)
{
- // only support openGL for now.
- GHOST_TSuccess success;
- switch (type) {
- case GHOST_kDrawingContextTypeOpenGL:
- m_sdl_glcontext = SDL_GL_CreateContext(m_sdl_win);
-
- if (m_sdl_glcontext != NULL) {
- if (!s_firstContext) {
- s_firstContext = m_sdl_glcontext;
- }
-
- success = (SDL_GL_MakeCurrent(m_sdl_win, m_sdl_glcontext) < 0) ?
- GHOST_kFailure : GHOST_kSuccess;
- }
- else {
- success = GHOST_kFailure;
- }
-
- break;
-
- case GHOST_kDrawingContextTypeNone:
- success = GHOST_kSuccess;
- break;
-
- default:
- success = GHOST_kFailure;
+ if (type == GHOST_kDrawingContextTypeOpenGL) {
+ GHOST_Context *context = new GHOST_ContextSDL(
+ m_wantStereoVisual,
+ m_wantNumOfAASamples,
+ m_sdl_win,
+ 0, // profile bit
+ 0, 0,
+ GHOST_OPENGL_SDL_CONTEXT_FLAGS,
+ GHOST_OPENGL_SDL_RESET_NOTIFICATION_STRATEGY);
+
+ if (context->initializeDrawingContext())
+ return context;
+ else
+ delete context;
}
- return success;
+
+ return NULL;
}
GHOST_TSuccess
GHOST_WindowSDL::invalidate(void)
{
- // So the idea of this function is to generate an expose event
- // for the window.
- // Unfortunately X does not handle expose events for you and
- // it is the client's job to refresh the dirty part of the window.
- // We need to queue up invalidate calls and generate GHOST events
- // for them in the system.
-
- // We implement this by setting a boolean in this class to concatenate
- // all such calls into a single event for this window.
-
- // At the same time we queue the dirty windows in the system class
- // and generate events for them at the next processEvents call.
-
if (m_invalid_window == false) {
m_system->addDirtyWindow(this);
m_invalid_window = true;
@@ -153,52 +118,6 @@ GHOST_WindowSDL::invalidate(void)
return GHOST_kSuccess;
}
-
-GHOST_TSuccess
-GHOST_WindowSDL::swapBuffers()
-{
- if (getDrawingContextType() == GHOST_kDrawingContextTypeOpenGL) {
- SDL_GL_SwapWindow(m_sdl_win);
- return GHOST_kSuccess;
- }
- else {
- return GHOST_kFailure;
- }
-}
-
-
-GHOST_TSuccess
-GHOST_WindowSDL::activateDrawingContext()
-{
- if (m_sdl_glcontext != NULL) {
- int status = SDL_GL_MakeCurrent(m_sdl_win, m_sdl_glcontext);
- (void)status;
- /* Disable AA by default */
- if (m_numOfAASamples > 0) {
- glDisable(GL_MULTISAMPLE_ARB);
- }
- return GHOST_kSuccess;
- }
- return GHOST_kFailure;
-}
-
-
-GHOST_TSuccess
-GHOST_WindowSDL::removeDrawingContext()
-{
- GHOST_TSuccess success;
-
- if (m_sdl_glcontext != NULL) {
- SDL_GL_DeleteContext(m_sdl_glcontext);
- success = GHOST_kSuccess;
- }
- else {
- success = GHOST_kFailure;
- }
- return success;
-}
-
-
GHOST_TSuccess
GHOST_WindowSDL::setState(GHOST_TWindowState state)
{
@@ -236,6 +155,12 @@ GHOST_WindowSDL::getState() const
return GHOST_kWindowStateNormal;
}
+bool
+GHOST_WindowSDL::
+getValid() const
+{
+ return GHOST_Window::getValid() && m_valid_setup;
+}
void
GHOST_WindowSDL::setTitle(const STR_String& title)
@@ -638,16 +563,3 @@ GHOST_WindowSDL::setWindowCursorVisibility(bool visible)
SDL_ShowCursor(visible);
return GHOST_kSuccess;
}
-
-GHOST_TSuccess
-GHOST_WindowSDL::setSwapInterval(int interval)
-{
- SDL_GL_SetSwapInterval(interval);
- return GHOST_kSuccess;
-}
-
-int
-GHOST_WindowSDL::getSwapInterval()
-{
- return SDL_GL_GetSwapInterval();
-}
diff --git a/intern/ghost/intern/GHOST_WindowSDL.h b/intern/ghost/intern/GHOST_WindowSDL.h
index 0c11ce19b50..5f658e8ad01 100644
--- a/intern/ghost/intern/GHOST_WindowSDL.h
+++ b/intern/ghost/intern/GHOST_WindowSDL.h
@@ -30,6 +30,7 @@
#include "GHOST_Window.h"
#include "GHOST_SystemSDL.h"
+
#include <map>
extern "C" {
@@ -47,10 +48,10 @@ class GHOST_WindowSDL : public GHOST_Window
{
private:
GHOST_SystemSDL *m_system;
+ bool m_valid_setup;
bool m_invalid_window;
SDL_Window *m_sdl_win;
- SDL_GLContext m_sdl_glcontext;
SDL_Cursor *m_sdl_custom_cursor;
public:
@@ -93,17 +94,18 @@ public:
m_invalid_window = false;
}
- bool getValid() const
- {
- return (m_sdl_win != NULL);
- }
+ bool getValid() const;
void getWindowBounds(GHOST_Rect& bounds) const;
void getClientBounds(GHOST_Rect& bounds) const;
protected:
- GHOST_TSuccess installDrawingContext(GHOST_TDrawingContextType type);
- GHOST_TSuccess removeDrawingContext();
+
+ /**
+ * \param type The type of rendering context create.
+ * \return Indication of success.
+ */
+ GHOST_Context *newDrawingContext(GHOST_TDrawingContextType type);
GHOST_TSuccess
setWindowCursorGrab(GHOST_TGrabCursorMode mode);
@@ -151,12 +153,6 @@ protected:
GHOST_TInt32& outX, GHOST_TInt32& outY) const;
GHOST_TSuccess
- swapBuffers();
-
- GHOST_TSuccess
- activateDrawingContext();
-
- GHOST_TSuccess
setState(GHOST_TWindowState state);
GHOST_TWindowState
@@ -172,9 +168,6 @@ protected:
GHOST_TSuccess beginFullScreen() const { return GHOST_kFailure; }
GHOST_TSuccess endFullScreen() const { return GHOST_kFailure; }
-
- GHOST_TSuccess setSwapInterval(int interval);
- int getSwapInterval();
};
diff --git a/intern/ghost/intern/GHOST_WindowWin32.cpp b/intern/ghost/intern/GHOST_WindowWin32.cpp
index 8e7e824186c..54689a96b66 100644
--- a/intern/ghost/intern/GHOST_WindowWin32.cpp
+++ b/intern/ghost/intern/GHOST_WindowWin32.cpp
@@ -29,90 +29,40 @@
* \ingroup GHOST
*/
-#include <string.h>
+#define _USE_MATH_DEFINES
+
#include "GHOST_WindowWin32.h"
#include "GHOST_SystemWin32.h"
#include "GHOST_DropTargetWin32.h"
+#include "GHOST_ContextNone.h"
#include "utfconv.h"
#include "utf_winfunc.h"
-// Need glew for some defines
-#include <GL/glew.h>
-#include <GL/wglew.h>
+#if defined(WITH_GL_EGL)
+# include "GHOST_ContextEGL.h"
+#else
+# include "GHOST_ContextWGL.h"
+#endif
+
+
#include <math.h>
+#include <string.h>
+#include <assert.h>
-// MSVC6 still doesn't define M_PI
-#ifndef M_PI
-# define M_PI 3.1415926536
-#endif
-// Some more multisample defines
-#define WGL_SAMPLE_BUFFERS_ARB 0x2041
-#define WGL_SAMPLES_ARB 0x2042
const wchar_t *GHOST_WindowWin32::s_windowClassName = L"GHOST_WindowClass";
const int GHOST_WindowWin32::s_maxTitleLength = 128;
-HGLRC GHOST_WindowWin32::s_firsthGLRc = NULL;
-HDC GHOST_WindowWin32::s_firstHDC = NULL;
-static int WeightPixelFormat(PIXELFORMATDESCRIPTOR &pfd);
-static int EnumPixelFormats(HDC hdc);
-/*
- * Color and depth bit values are not to be trusted.
- * For instance, on TNT2:
- * When the screen color depth is set to 16 bit, we get 5 color bits
- * and 16 depth bits.
- * When the screen color depth is set to 32 bit, we get 8 color bits
- * and 24 depth bits.
- * Just to be safe, we request high quality settings.
- */
-static PIXELFORMATDESCRIPTOR sPreferredFormat = {
- sizeof(PIXELFORMATDESCRIPTOR), /* size */
- 1, /* version */
- PFD_SUPPORT_OPENGL |
- PFD_DRAW_TO_WINDOW |
- PFD_SWAP_COPY | /* support swap copy */
- PFD_DOUBLEBUFFER, /* support double-buffering */
- PFD_TYPE_RGBA, /* color type */
- 32, /* prefered color depth */
- 0, 0, 0, 0, 0, 0, /* color bits (ignored) */
- 0, /* no alpha buffer */
- 0, /* alpha bits (ignored) */
- 0, /* no accumulation buffer */
- 0, 0, 0, 0, /* accum bits (ignored) */
- 32, /* depth buffer */
- 0, /* no stencil buffer */
- 0, /* no auxiliary buffers */
- PFD_MAIN_PLANE, /* main layer */
- 0, /* reserved */
- 0, 0, 0 /* no layer, visible, damage masks */
-};
-
-/* Intel videocards don't work fine with multiple contexts and
- * have to share the same context for all windows.
- * But if we just share context for all windows it could work incorrect
- * with multiple videocards configuration. Suppose, that Intel videocards
- * can't be in multiple-devices configuration. */
-static int is_crappy_intel_card(void)
-{
- static short is_crappy = -1;
-
- if (is_crappy == -1) {
- const char *vendor = (const char *)glGetString(GL_VENDOR);
- is_crappy = (strstr(vendor, "Intel") != NULL);
- }
- return is_crappy;
-}
/* force NVidia Optimus to used dedicated graphics */
extern "C" {
__declspec(dllexport) DWORD NvOptimusEnablement = 0x00000001;
}
-GHOST_WindowWin32::GHOST_WindowWin32(
- GHOST_SystemWin32 *system,
+GHOST_WindowWin32::GHOST_WindowWin32(GHOST_SystemWin32 *system,
const STR_String &title,
GHOST_TInt32 left,
GHOST_TInt32 top,
@@ -120,17 +70,15 @@ GHOST_WindowWin32::GHOST_WindowWin32(
GHOST_TUns32 height,
GHOST_TWindowState state,
GHOST_TDrawingContextType type,
- const bool stereoVisual,
- const GHOST_TUns16 numOfAASamples,
+ bool wantStereoVisual, bool warnOld,
+ GHOST_TUns16 wantNumOfAASamples,
GHOST_TEmbedderWindowID parentwindowhwnd,
- GHOST_TSuccess msEnabled,
- int msPixelFormat)
- : GHOST_Window(width, height, state, GHOST_kDrawingContextTypeNone,
- stereoVisual, false, numOfAASamples),
+ bool is_debug)
+ : GHOST_Window(width, height, state,
+ wantStereoVisual, false, wantNumOfAASamples),
m_inLiveResize(false),
m_system(system),
m_hDC(0),
- m_hGlRc(0),
m_hasMouseCaptured(false),
m_hasGrabMouse(false),
m_nPressedButtons(0),
@@ -139,19 +87,9 @@ GHOST_WindowWin32::GHOST_WindowWin32(
m_tabletData(NULL),
m_tablet(0),
m_maxPressure(0),
- m_multisample(numOfAASamples),
- m_multisampleEnabled(msEnabled),
- m_msPixelFormat(msPixelFormat),
- //For recreation
- m_title(title),
- m_left(left),
- m_top(top),
- m_width(width),
- m_height(height),
m_normal_state(GHOST_kWindowStateNormal),
- m_stereo(stereoVisual),
- m_nextWindow(NULL),
- m_parentWindowHwnd(parentwindowhwnd)
+ m_parentWindowHwnd(parentwindowhwnd),
+ m_debug_context(is_debug)
{
OSVERSIONINFOEX versionInfo;
bool hasMinVersionForTaskbar = false;
@@ -160,6 +98,13 @@ GHOST_WindowWin32::GHOST_WindowWin32(
versionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
+#if !defined(WITH_GL_EGL)
+ if (!warnOld)
+ GHOST_ContextWGL::unSetWarningOld();
+#else
+ (void)(warnOld);
+#endif
+
if (!GetVersionEx((OSVERSIONINFO *)&versionInfo)) {
versionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
if (GetVersionEx((OSVERSIONINFO *)&versionInfo)) {
@@ -286,35 +231,32 @@ GHOST_WindowWin32::GHOST_WindowWin32(
// Store the device context
m_hDC = ::GetDC(m_hWnd);
- if (!s_firstHDC) {
- s_firstHDC = m_hDC;
- }
-
- // Show the window
- int nCmdShow;
- switch (state) {
- case GHOST_kWindowStateMaximized:
- nCmdShow = SW_SHOWMAXIMIZED;
- break;
- case GHOST_kWindowStateMinimized:
- nCmdShow = SW_SHOWMINIMIZED;
- break;
- case GHOST_kWindowStateNormal:
- default:
- nCmdShow = SW_SHOWNORMAL;
- break;
- }
- GHOST_TSuccess success;
- success = setDrawingContextType(type);
+ GHOST_TSuccess success = setDrawingContextType(type);
if (success) {
+ // Show the window
+ int nCmdShow;
+ switch (state) {
+ case GHOST_kWindowStateMaximized:
+ nCmdShow = SW_SHOWMAXIMIZED;
+ break;
+ case GHOST_kWindowStateMinimized:
+ nCmdShow = SW_SHOWMINIMIZED;
+ break;
+ case GHOST_kWindowStateNormal:
+ default:
+ nCmdShow = SW_SHOWNORMAL;
+ break;
+ }
+
::ShowWindow(m_hWnd, nCmdShow);
// Force an initial paint of the window
::UpdateWindow(m_hWnd);
}
else {
//invalidate the window
- m_hWnd = 0;
+ ::DestroyWindow(m_hWnd);
+ m_hWnd = NULL;
}
}
@@ -415,14 +357,8 @@ GHOST_WindowWin32::~GHOST_WindowWin32()
m_customCursor = NULL;
}
- ::wglMakeCurrent(NULL, NULL);
- m_multisampleEnabled = GHOST_kFailure;
- m_multisample = 0;
- setDrawingContextType(GHOST_kDrawingContextTypeNone);
-
- if (m_hDC && m_hDC != s_firstHDC) {
+ if (m_hWnd != NULL && m_hDC != NULL && releaseNativeHandles()) {
::ReleaseDC(m_hWnd, m_hDC);
- m_hDC = 0;
}
if (m_hWnd) {
@@ -438,14 +374,9 @@ GHOST_WindowWin32::~GHOST_WindowWin32()
}
}
-GHOST_Window *GHOST_WindowWin32::getNextWindow()
-{
- return m_nextWindow;
-}
-
bool GHOST_WindowWin32::getValid() const
{
- return m_hWnd != 0;
+ return GHOST_Window::getValid() && m_hWnd != 0 && m_hDC != 0;
}
HWND GHOST_WindowWin32::getHWND() const
@@ -678,49 +609,6 @@ GHOST_TSuccess GHOST_WindowWin32::setOrder(GHOST_TWindowOrder order)
}
-GHOST_TSuccess GHOST_WindowWin32::swapBuffers()
-{
- HDC hDC = m_hDC;
-
- if (is_crappy_intel_card())
- hDC = ::wglGetCurrentDC();
-
- return ::SwapBuffers(hDC) == TRUE ? GHOST_kSuccess : GHOST_kFailure;
-}
-
-GHOST_TSuccess GHOST_WindowWin32::setSwapInterval(int interval)
-{
- if (!WGL_EXT_swap_control)
- return GHOST_kFailure;
- return wglSwapIntervalEXT(interval) == TRUE ? GHOST_kSuccess : GHOST_kFailure;
-}
-
-int GHOST_WindowWin32::getSwapInterval()
-{
- if (WGL_EXT_swap_control)
- return wglGetSwapIntervalEXT();
-
- return 0;
-}
-
-GHOST_TSuccess GHOST_WindowWin32::activateDrawingContext()
-{
- GHOST_TSuccess success;
- if (m_drawingContextType == GHOST_kDrawingContextTypeOpenGL) {
- if (m_hDC && m_hGlRc) {
- success = ::wglMakeCurrent(m_hDC, m_hGlRc) == TRUE ? GHOST_kSuccess : GHOST_kFailure;
- }
- else {
- success = GHOST_kFailure;
- }
- }
- else {
- success = GHOST_kSuccess;
- }
- return success;
-}
-
-
GHOST_TSuccess GHOST_WindowWin32::invalidate()
{
GHOST_TSuccess success;
@@ -733,257 +621,93 @@ GHOST_TSuccess GHOST_WindowWin32::invalidate()
return success;
}
-GHOST_TSuccess GHOST_WindowWin32::initMultisample(PIXELFORMATDESCRIPTOR pfd)
-{
- int pixelFormat;
- bool success = FALSE;
- UINT numFormats;
- HDC hDC = GetDC(getHWND());
- float fAttributes[] = {0, 0};
- UINT nMaxFormats = 1;
-
- // The attributes to look for
- int iAttributes[] = {
- WGL_DRAW_TO_WINDOW_ARB, GL_TRUE,
- WGL_SUPPORT_OPENGL_ARB, GL_TRUE,
- WGL_ACCELERATION_ARB, WGL_FULL_ACCELERATION_ARB,
- WGL_COLOR_BITS_ARB, pfd.cColorBits,
- WGL_DEPTH_BITS_ARB, pfd.cDepthBits,
-#ifdef GHOST_OPENGL_ALPHA
- WGL_ALPHA_BITS_ARB, pfd.cAlphaBits,
-#endif
- WGL_STENCIL_BITS_ARB, pfd.cStencilBits,
- WGL_DOUBLE_BUFFER_ARB, GL_TRUE,
- WGL_SAMPLE_BUFFERS_ARB, GL_TRUE,
- WGL_SAMPLES_ARB, m_multisample,
- 0, 0
- };
-
- // Get the function
- PFNWGLCHOOSEPIXELFORMATARBPROC wglChoosePixelFormatARB = (PFNWGLCHOOSEPIXELFORMATARBPROC)wglGetProcAddress("wglChoosePixelFormatARB");
-
- if (!wglChoosePixelFormatARB) {
- m_multisampleEnabled = GHOST_kFailure;
- return GHOST_kFailure;
- }
-
- // iAttributes[17] is the initial multisample. If not valid try to use the closest valid value under it.
- while (iAttributes[17] > 0) {
- // See if the format is valid
- success = wglChoosePixelFormatARB(hDC, iAttributes, fAttributes, nMaxFormats, &pixelFormat, &numFormats);
- GHOST_PRINTF("WGL_SAMPLES_ARB = %i --> success = %i, %i formats\n", iAttributes[17], success, numFormats);
-
- if (success && numFormats >= 1 && m_multisampleEnabled == GHOST_kFailure) {
- GHOST_PRINTF("valid pixel format with %i multisamples\n", iAttributes[17]);
- m_multisampleEnabled = GHOST_kSuccess;
- m_msPixelFormat = pixelFormat;
- }
- iAttributes[17] -= 1;
- success = GHOST_kFailure;
- }
- if (m_multisampleEnabled == GHOST_kSuccess) {
- return GHOST_kSuccess;
- }
- GHOST_PRINT("no available pixel format\n");
- return GHOST_kFailure;
-}
-GHOST_TSuccess GHOST_WindowWin32::installDrawingContext(GHOST_TDrawingContextType type)
+GHOST_Context *GHOST_WindowWin32::newDrawingContext(GHOST_TDrawingContextType type)
{
- GHOST_TSuccess success;
- switch (type) {
- case GHOST_kDrawingContextTypeOpenGL:
- {
- // If this window has multisample enabled, use the supplied format
- if (m_multisampleEnabled)
- {
- if (SetPixelFormat(m_hDC, m_msPixelFormat, &sPreferredFormat) == FALSE)
- {
- success = GHOST_kFailure;
- break;
- }
-
- // Create the context
- m_hGlRc = ::wglCreateContext(m_hDC);
- if (m_hGlRc) {
- if (::wglMakeCurrent(m_hDC, m_hGlRc) == TRUE) {
- if (s_firsthGLRc) {
- if (is_crappy_intel_card()) {
- if (::wglMakeCurrent(NULL, NULL) == TRUE) {
- ::wglDeleteContext(m_hGlRc);
- m_hGlRc = s_firsthGLRc;
- }
- else {
- ::wglDeleteContext(m_hGlRc);
- m_hGlRc = NULL;
- }
- }
- else {
- ::wglCopyContext(s_firsthGLRc, m_hGlRc, GL_ALL_ATTRIB_BITS);
- ::wglShareLists(s_firsthGLRc, m_hGlRc);
- }
- }
- else {
- s_firsthGLRc = m_hGlRc;
- }
-
- if (m_hGlRc) {
- success = ::wglMakeCurrent(m_hDC, m_hGlRc) == TRUE ? GHOST_kSuccess : GHOST_kFailure;
- }
- else {
- success = GHOST_kFailure;
- }
- }
- else {
- success = GHOST_kFailure;
- }
- }
- else {
- success = GHOST_kFailure;
- }
-
- if (success == GHOST_kFailure) {
- printf("Failed to get a context....\n");
- }
- }
- else {
- if (m_stereoVisual)
- sPreferredFormat.dwFlags |= PFD_STEREO;
-
- // Attempt to match device context pixel format to the preferred format
- int iPixelFormat = EnumPixelFormats(m_hDC);
- if (iPixelFormat == 0) {
- success = GHOST_kFailure;
- break;
- }
- if (::SetPixelFormat(m_hDC, iPixelFormat, &sPreferredFormat) == FALSE) {
- success = GHOST_kFailure;
- break;
- }
- // For debugging only: retrieve the pixel format chosen
- PIXELFORMATDESCRIPTOR preferredFormat;
- ::DescribePixelFormat(m_hDC, iPixelFormat, sizeof(PIXELFORMATDESCRIPTOR), &preferredFormat);
-
- // Create the context
- m_hGlRc = ::wglCreateContext(m_hDC);
- if (m_hGlRc) {
- if (::wglMakeCurrent(m_hDC, m_hGlRc) == TRUE) {
- if (s_firsthGLRc) {
- if (is_crappy_intel_card()) {
- if (::wglMakeCurrent(NULL, NULL) == TRUE) {
- ::wglDeleteContext(m_hGlRc);
- m_hGlRc = s_firsthGLRc;
- }
- else {
- ::wglDeleteContext(m_hGlRc);
- m_hGlRc = NULL;
- }
- }
- else {
- ::wglShareLists(s_firsthGLRc, m_hGlRc);
- }
- }
- else {
- s_firsthGLRc = m_hGlRc;
- }
-
- if (m_hGlRc) {
- success = ::wglMakeCurrent(m_hDC, m_hGlRc) == TRUE ? GHOST_kSuccess : GHOST_kFailure;
- }
- else {
- success = GHOST_kFailure;
- }
- }
- else {
- success = GHOST_kFailure;
- }
- }
- else {
- success = GHOST_kFailure;
- }
-
- if (success == GHOST_kFailure) {
- printf("Failed to get a context....\n");
- }
-
- // Attempt to enable multisample
- if (m_multisample && WGL_ARB_multisample && !m_multisampleEnabled && !is_crappy_intel_card())
- {
- success = initMultisample(preferredFormat);
-
- if (success)
- {
-
- // Make sure we don't screw up the context
- if (m_hGlRc == s_firsthGLRc)
- s_firsthGLRc = NULL;
- m_drawingContextType = GHOST_kDrawingContextTypeOpenGL;
- removeDrawingContext();
-
- // Create a new window
- GHOST_TWindowState new_state = getState();
-
- m_nextWindow = new GHOST_WindowWin32((GHOST_SystemWin32 *)GHOST_ISystem::getSystem(),
- m_title,
- m_left,
- m_top,
- m_width,
- m_height,
- new_state,
- type,
- m_stereo,
- m_multisample,
- m_parentWindowHwnd,
- m_multisampleEnabled,
- m_msPixelFormat);
-
- // Return failure so we can trash this window.
- success = GHOST_kFailure;
- break;
- }
- else {
- m_multisampleEnabled = GHOST_kSuccess;
- printf("Multisample failed to initialize\n");
- success = GHOST_kSuccess;
- }
- }
- }
+ if (type == GHOST_kDrawingContextTypeOpenGL) {
+#if !defined(WITH_GL_EGL)
+
+#if defined(WITH_GL_PROFILE_CORE)
+ GHOST_Context *context = new GHOST_ContextWGL(
+ m_wantStereoVisual,
+ m_wantNumOfAASamples,
+ m_hWnd,
+ m_hDC,
+ WGL_CONTEXT_OPENGL_CORE_PROFILE_BIT,
+ 3, 2,
+ GHOST_OPENGL_WGL_CONTEXT_FLAGS,
+ GHOST_OPENGL_WGL_RESET_NOTIFICATION_STRATEGY);
+#elif defined(WITH_GL_PROFILE_ES20)
+ GHOST_Context *context = new GHOST_ContextWGL(
+ m_wantStereoVisual,
+ m_wantNumOfAASamples,
+ m_hWnd,
+ m_hDC,
+ WGL_CONTEXT_ES2_PROFILE_BIT_EXT,
+ 2, 0,
+ GHOST_OPENGL_WGL_CONTEXT_FLAGS,
+ GHOST_OPENGL_WGL_RESET_NOTIFICATION_STRATEGY);
+#elif defined(WITH_GL_PROFILE_COMPAT)
+ GHOST_Context *context = new GHOST_ContextWGL(
+ m_wantStereoVisual,
+ m_wantNumOfAASamples,
+ m_hWnd,
+ m_hDC,
+ 0, // profile bit
+ 0, 0,
+ GHOST_OPENGL_WGL_CONTEXT_FLAGS,
+ GHOST_OPENGL_WGL_RESET_NOTIFICATION_STRATEGY);
+#else
+# error
+#endif
- }
- break;
+#else
- case GHOST_kDrawingContextTypeNone:
- success = GHOST_kSuccess;
- break;
+#if defined(WITH_GL_PROFILE_CORE)
+ GHOST_Context *context = new GHOST_ContextEGL(
+ m_wantStereoVisual,
+ m_wantNumOfAASamples,
+ m_hWnd,
+ m_hDC,
+ EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT,
+ 3, 2,
+ GHOST_OPENGL_EGL_CONTEXT_FLAGS,
+ GHOST_OPENGL_EGL_RESET_NOTIFICATION_STRATEGY,
+ EGL_OPENGL_API);
+#elif defined(WITH_GL_PROFILE_ES20)
+ GHOST_Context *context = new GHOST_ContextEGL(
+ m_wantStereoVisual,
+ m_wantNumOfAASamples,
+ m_hWnd,
+ m_hDC,
+ 0, // profile bit
+ 2, 0,
+ GHOST_OPENGL_EGL_CONTEXT_FLAGS,
+ GHOST_OPENGL_EGL_RESET_NOTIFICATION_STRATEGY,
+ EGL_OPENGL_ES_API);
+#elif defined(WITH_GL_PROFILE_COMPAT)
+ GHOST_Context *context = new GHOST_ContextEGL(
+ m_wantStereoVisual,
+ m_wantNumOfAASamples,
+ m_hWnd,
+ m_hDC,
+ 0, // profile bit
+ 0, 0,
+ GHOST_OPENGL_EGL_CONTEXT_FLAGS,
+ GHOST_OPENGL_EGL_RESET_NOTIFICATION_STRATEGY,
+ EGL_OPENGL_API);
+#else
+# error
+#endif
- default:
- success = GHOST_kFailure;
+#endif
+ if (context->initializeDrawingContext())
+ return context;
+ else
+ delete context;
}
- return success;
-}
-GHOST_TSuccess GHOST_WindowWin32::removeDrawingContext()
-{
- GHOST_TSuccess success;
- switch (m_drawingContextType) {
- case GHOST_kDrawingContextTypeOpenGL:
- // we shouldn't remove the drawing context if it's the first OpenGL context
- // If we do, we get corrupted drawing. See #19997
- if (m_hGlRc && m_hGlRc != s_firsthGLRc) {
- success = ::wglDeleteContext(m_hGlRc) == TRUE ? GHOST_kSuccess : GHOST_kFailure;
- m_hGlRc = 0;
- }
- else {
- success = GHOST_kFailure;
- }
- break;
- case GHOST_kDrawingContextTypeNone:
- success = GHOST_kSuccess;
- break;
- default:
- success = GHOST_kFailure;
- }
- return success;
+ return NULL;
}
void GHOST_WindowWin32::lostMouseCapture()
@@ -1334,93 +1058,16 @@ GHOST_TSuccess GHOST_WindowWin32::endProgressBar()
return GHOST_kFailure;
}
-/* Ron Fosner's code for weighting pixel formats and forcing software.
- * See http://www.opengl.org/resources/faq/technical/weight.cpp */
-static int WeightPixelFormat(PIXELFORMATDESCRIPTOR &pfd)
+#ifdef WITH_INPUT_IME
+void GHOST_WindowWin32::beginIME(GHOST_TInt32 x, GHOST_TInt32 y, GHOST_TInt32 w, GHOST_TInt32 h, int completed)
{
- int weight = 0;
-
- /* assume desktop color depth is 32 bits per pixel */
-
- /* cull unusable pixel formats */
- /* if no formats can be found, can we determine why it was rejected? */
- if (!(pfd.dwFlags & PFD_SUPPORT_OPENGL) ||
- !(pfd.dwFlags & PFD_DRAW_TO_WINDOW) ||
- !(pfd.dwFlags & PFD_DOUBLEBUFFER) || /* Blender _needs_ this */
- (pfd.cDepthBits <= 8) ||
- !(pfd.iPixelType == PFD_TYPE_RGBA))
- {
- return 0;
- }
-
- weight = 1; /* it's usable */
-
- /* the bigger the depth buffer the better */
- /* give no weight to a 16-bit depth buffer, because those are crap */
- weight += pfd.cDepthBits - 16;
-
- weight += pfd.cColorBits - 8;
-
-#ifdef GHOST_OPENGL_ALPHA
- if (pfd.cAlphaBits > 0)
- weight ++;
-#endif
-
- /* want swap copy capability -- it matters a lot */
- if (pfd.dwFlags & PFD_SWAP_COPY) weight += 16;
-
- /* but if it's a generic (not accelerated) view, it's really bad */
- if (pfd.dwFlags & PFD_GENERIC_FORMAT) weight /= 10;
-
- return weight;
+ m_imeImput.BeginIME(m_hWnd, GHOST_Rect(x, y - h, x, y), (bool)completed);
}
-/* A modification of Ron Fosner's replacement for ChoosePixelFormat */
-/* returns 0 on error, else returns the pixel format number to be used */
-static int EnumPixelFormats(HDC hdc)
+
+void GHOST_WindowWin32::endIME()
{
- int iPixelFormat;
- int i, n, w, weight = 0;
- PIXELFORMATDESCRIPTOR pfd;
-
- /* we need a device context to do anything */
- if (!hdc) return 0;
-
- iPixelFormat = 1; /* careful! PFD numbers are 1 based, not zero based */
-
- /* obtain detailed information about
- * the device context's first pixel format */
- n = 1 + ::DescribePixelFormat(hdc, iPixelFormat,
- sizeof(PIXELFORMATDESCRIPTOR), &pfd);
-
- /* choose a pixel format using the useless Windows function in case
- * we come up empty handed */
- iPixelFormat = ::ChoosePixelFormat(hdc, &sPreferredFormat);
-
- if (!iPixelFormat) return 0; /* couldn't find one to use */
-
- for (i = 1; i <= n; i++) { /* not the idiom, but it's right */
- ::DescribePixelFormat(hdc, i, sizeof(PIXELFORMATDESCRIPTOR), &pfd);
- w = WeightPixelFormat(pfd);
- // be strict on stereo
- if (!((sPreferredFormat.dwFlags ^ pfd.dwFlags) & PFD_STEREO)) {
- if (w > weight) {
- weight = w;
- iPixelFormat = i;
- }
- }
- }
- if (weight == 0) {
- // we could find the correct stereo setting, just find any suitable format
- for (i = 1; i <= n; i++) { /* not the idiom, but it's right */
- ::DescribePixelFormat(hdc, i, sizeof(PIXELFORMATDESCRIPTOR), &pfd);
- w = WeightPixelFormat(pfd);
- if (w > weight) {
- weight = w;
- iPixelFormat = i;
- }
- }
- }
- return iPixelFormat;
+ m_imeImput.EndIME(m_hWnd);
}
+#endif /* WITH_INPUT_IME */
diff --git a/intern/ghost/intern/GHOST_WindowWin32.h b/intern/ghost/intern/GHOST_WindowWin32.h
index cb6c09b335c..3666fa753f3 100644
--- a/intern/ghost/intern/GHOST_WindowWin32.h
+++ b/intern/ghost/intern/GHOST_WindowWin32.h
@@ -39,13 +39,9 @@
#include "GHOST_Window.h"
#include "GHOST_TaskbarWin32.h"
-
-#ifndef __MINGW64__
-#define _WIN32_WINNT 0x501 // require Windows XP or newer
+#ifdef WITH_INPUT_IME
+# include "GHOST_ImeWin32.h"
#endif
-#define WIN32_LEAN_AND_MEAN
-#include <windows.h>
-
#include <wintab.h>
#define PACKETDATA (PK_BUTTONS | PK_NORMAL_PRESSURE | PK_ORIENTATION | PK_CURSOR)
@@ -80,11 +76,11 @@ public:
* \param height The height the window.
* \param state The state the window is initially opened with.
* \param type The type of drawing context installed in this window.
- * \param stereoVisual Stereo visual for quad buffered stereo.
- * \param numOfAASamples Number of samples used for AA (zero if no AA)
+ * \param wantStereoVisual Stereo visual for quad buffered stereo.
+ * \param wantNumOfAASamples Number of samples used for AA (zero if no AA)
+ * \param parentWindowHwnd
*/
- GHOST_WindowWin32(
- GHOST_SystemWin32 *system,
+ GHOST_WindowWin32(GHOST_SystemWin32 *system,
const STR_String& title,
GHOST_TInt32 left,
GHOST_TInt32 top,
@@ -92,88 +88,80 @@ public:
GHOST_TUns32 height,
GHOST_TWindowState state,
GHOST_TDrawingContextType type = GHOST_kDrawingContextTypeNone,
- const bool stereoVisual = false,
- const GHOST_TUns16 numOfAASamples = 0,
+ bool wantStereoVisual = false,
+ bool warnOld = false,
+ GHOST_TUns16 wantNumOfAASamples = 0,
GHOST_TEmbedderWindowID parentWindowHwnd = 0,
- GHOST_TSuccess msEnabled = GHOST_kFailure,
- int msPixelFormat = 0
- );
+ bool is_debug = false);
/**
* Destructor.
* Closes the window and disposes resources allocated.
*/
- virtual ~GHOST_WindowWin32();
-
- /**
- * Returns the window to replace this one if it's getting replaced
- * \return The window replacing this one.
- */
-
- GHOST_Window *getNextWindow();
+ ~GHOST_WindowWin32();
/**
* Returns indication as to whether the window is valid.
* \return The validity of the window.
*/
- virtual bool getValid() const;
+ bool getValid() const;
/**
* Access to the handle of the window.
* \return The handle of the window.
*/
- virtual HWND getHWND() const;
+ HWND getHWND() const;
/**
* Sets the title displayed in the title bar.
* \param title The title to display in the title bar.
*/
- virtual void setTitle(const STR_String& title);
+ void setTitle(const STR_String& title);
/**
* Returns the title displayed in the title bar.
* \param title The title displayed in the title bar.
*/
- virtual void getTitle(STR_String& title) const;
+ void getTitle(STR_String& title) const;
/**
* Returns the window rectangle dimensions.
* The dimensions are given in screen coordinates that are relative to the upper-left corner of the screen.
* \param bounds The bounding rectangle of the window.
*/
- virtual void getWindowBounds(GHOST_Rect& bounds) const;
+ void getWindowBounds(GHOST_Rect& bounds) const;
/**
* Returns the client rectangle dimensions.
* The left and top members of the rectangle are always zero.
* \param bounds The bounding rectangle of the client area of the window.
*/
- virtual void getClientBounds(GHOST_Rect& bounds) const;
+ void getClientBounds(GHOST_Rect& bounds) const;
/**
* Resizes client rectangle width.
* \param width The new width of the client area of the window.
*/
- virtual GHOST_TSuccess setClientWidth(GHOST_TUns32 width);
+ GHOST_TSuccess setClientWidth(GHOST_TUns32 width);
/**
* Resizes client rectangle height.
* \param height The new height of the client area of the window.
*/
- virtual GHOST_TSuccess setClientHeight(GHOST_TUns32 height);
+ GHOST_TSuccess setClientHeight(GHOST_TUns32 height);
/**
* Resizes client rectangle.
* \param width The new width of the client area of the window.
* \param height The new height of the client area of the window.
*/
- virtual GHOST_TSuccess setClientSize(GHOST_TUns32 width, GHOST_TUns32 height);
+ GHOST_TSuccess setClientSize(GHOST_TUns32 width, GHOST_TUns32 height);
/**
* Returns the state of the window (normal, minimized, maximized).
* \return The state of the window.
*/
- virtual GHOST_TWindowState getState() const;
+ GHOST_TWindowState getState() const;
/**
* Converts a point in screen coordinates to client rectangle coordinates
@@ -182,7 +170,7 @@ public:
* \param outX The x-coordinate in the client rectangle.
* \param outY The y-coordinate in the client rectangle.
*/
- virtual void screenToClient(GHOST_TInt32 inX, GHOST_TInt32 inY, GHOST_TInt32& outX, GHOST_TInt32& outY) const;
+ void screenToClient(GHOST_TInt32 inX, GHOST_TInt32 inY, GHOST_TInt32& outX, GHOST_TInt32& outY) const;
/**
* Converts a point in screen coordinates to client rectangle coordinates
@@ -191,70 +179,38 @@ public:
* \param outX The x-coordinate on the screen.
* \param outY The y-coordinate on the screen.
*/
- virtual void clientToScreen(GHOST_TInt32 inX, GHOST_TInt32 inY, GHOST_TInt32& outX, GHOST_TInt32& outY) const;
+ void clientToScreen(GHOST_TInt32 inX, GHOST_TInt32 inY, GHOST_TInt32& outX, GHOST_TInt32& outY) const;
/**
* Sets the state of the window (normal, minimized, maximized).
* \param state The state of the window.
* \return Indication of success.
*/
- virtual GHOST_TSuccess setState(GHOST_TWindowState state);
+ GHOST_TSuccess setState(GHOST_TWindowState state);
/**
* Sets the order of the window (bottom, top).
* \param order The order of the window.
* \return Indication of success.
*/
- virtual GHOST_TSuccess setOrder(GHOST_TWindowOrder order);
-
- /**
- * Swaps front and back buffers of a window.
- * \return Indication of success.
- */
- virtual GHOST_TSuccess swapBuffers();
-
- /**
- * Sets the swap interval for swapBuffers.
- * \param interval The swap interval to use.
- * \return A boolean success indicator.
- */
- virtual GHOST_TSuccess setSwapInterval(int interval);
-
- /**
- * Gets the current swap interval for swapBuffers.
- * \return An integer.
- */
- virtual int getSwapInterval();
-
- /**
- * Activates the drawing context of this window.
- * \return Indication of success.
- */
- virtual GHOST_TSuccess activateDrawingContext();
+ GHOST_TSuccess setOrder(GHOST_TWindowOrder order);
/**
* Invalidates the contents of this window.
*/
- virtual GHOST_TSuccess invalidate();
+ GHOST_TSuccess invalidate();
/**
* Sets the progress bar value displayed in the window/application icon
* \param progress The progress %
*/
- virtual GHOST_TSuccess setProgressBar(float progress);
+ GHOST_TSuccess setProgressBar(float progress);
/**
* Hides the progress bar in the icon
*/
- virtual GHOST_TSuccess endProgressBar();
+ GHOST_TSuccess endProgressBar();
- /**
- * Returns the name of the window class.
- * \return The name of the window class.
- */
- static const wchar_t *getWindowClassName() {
- return s_windowClassName;
- }
/**
* Register a mouse click event (should be called
@@ -298,50 +254,53 @@ public:
/** if the window currently resizing */
bool m_inLiveResize;
-protected:
- GHOST_TSuccess initMultisample(PIXELFORMATDESCRIPTOR pfd);
+#ifdef WITH_INPUT_IME
+ GHOST_ImeWin32 *getImeInput() {return &m_imeImput;}
- /**
- * Tries to install a rendering context in this window.
- * \param type The type of rendering context installed.
- * \return Indication of success.
- */
- virtual GHOST_TSuccess installDrawingContext(GHOST_TDrawingContextType type);
+ void beginIME(
+ GHOST_TInt32 x, GHOST_TInt32 y,
+ GHOST_TInt32 w, GHOST_TInt32 h,
+ int completed);
+
+ void endIME();
+#endif /* WITH_INPUT_IME */
+
+private:
/**
- * Removes the current drawing context.
+ * \param type The type of rendering context create.
* \return Indication of success.
*/
- virtual GHOST_TSuccess removeDrawingContext();
+ GHOST_Context *newDrawingContext(GHOST_TDrawingContextType type);
/**
* Sets the cursor visibility on the window using
* native window system calls.
*/
- virtual GHOST_TSuccess setWindowCursorVisibility(bool visible);
+ GHOST_TSuccess setWindowCursorVisibility(bool visible);
/**
* Sets the cursor grab on the window using native window system calls.
* Using registerMouseClickEvent.
* \param mode GHOST_TGrabCursorMode.
*/
- virtual GHOST_TSuccess setWindowCursorGrab(GHOST_TGrabCursorMode mode);
+ GHOST_TSuccess setWindowCursorGrab(GHOST_TGrabCursorMode mode);
/**
* Sets the cursor shape on the window using
* native window system calls.
*/
- virtual GHOST_TSuccess setWindowCursorShape(GHOST_TStandardCursor shape);
+ GHOST_TSuccess setWindowCursorShape(GHOST_TStandardCursor shape);
/**
* Sets the cursor shape on the window using
* native window system calls.
*/
- virtual GHOST_TSuccess setWindowCustomCursorShape(GHOST_TUns8 bitmap[16][2],
+ GHOST_TSuccess setWindowCustomCursorShape(GHOST_TUns8 bitmap[16][2],
GHOST_TUns8 mask[16][2],
int hotX, int hotY);
- virtual GHOST_TSuccess setWindowCustomCursorShape(
+ GHOST_TSuccess setWindowCustomCursorShape(
GHOST_TUns8 *bitmap,
GHOST_TUns8 *mask,
int sizex,
@@ -360,12 +319,7 @@ protected:
HWND m_hWnd;
/** Device context handle. */
HDC m_hDC;
- /** OpenGL rendering context. */
- HGLRC m_hGlRc;
- /** The first created OpenGL context (for sharing display lists) */
- static HGLRC s_firsthGLRc;
- /** The first created device context handle. */
- static HDC s_firstHDC;
+
/** Flag for if window has captured the mouse */
bool m_hasMouseCaptured;
/** Flag if an operator grabs the mouse with WM_cursor_grab_enable/ungrab()
@@ -393,29 +347,16 @@ protected:
LONG m_maxPressure;
LONG m_maxAzimuth, m_maxAltitude;
- /** Preferred number of samples */
- GHOST_TUns16 m_multisample;
-
- /** Check if multisample is supported */
- GHOST_TSuccess m_multisampleEnabled;
-
- /** The pixelFormat to use for multisample */
- int m_msPixelFormat;
-
- /** We need to following to recreate the window */
- const STR_String& m_title;
- GHOST_TInt32 m_left;
- GHOST_TInt32 m_top;
- GHOST_TUns32 m_width;
- GHOST_TUns32 m_height;
GHOST_TWindowState m_normal_state;
- bool m_stereo;
-
- /** The GHOST_System passes this to wm if this window is being replaced */
- GHOST_Window *m_nextWindow;
/** Hwnd to parent window */
GHOST_TEmbedderWindowID m_parentWindowHwnd;
+
+#ifdef WITH_INPUT_IME
+ /** Handle input method editors event */
+ GHOST_ImeWin32 m_imeImput;
+#endif
+ bool m_debug_context;
};
#endif // __GHOST_WINDOWWIN32_H__
diff --git a/intern/ghost/intern/GHOST_WindowX11.cpp b/intern/ghost/intern/GHOST_WindowX11.cpp
index 86c940b7396..fe99a8bee1e 100644
--- a/intern/ghost/intern/GHOST_WindowX11.cpp
+++ b/intern/ghost/intern/GHOST_WindowX11.cpp
@@ -29,8 +29,10 @@
* \ingroup GHOST
*/
-
-#include <GL/glxew.h>
+/* For standard X11 cursors */
+#include <X11/cursorfont.h>
+#include <X11/Xatom.h>
+#include <X11/Xutil.h>
#include "GHOST_WindowX11.h"
#include "GHOST_SystemX11.h"
@@ -38,20 +40,25 @@
#include "GHOST_Debug.h"
#ifdef WITH_XDND
-#include "GHOST_DropTargetX11.h"
+# include "GHOST_DropTargetX11.h"
#endif
-/* For standard X11 cursors */
-#include <X11/cursorfont.h>
-#include <X11/Xatom.h>
+#if defined(WITH_GL_EGL)
+# include "GHOST_ContextEGL.h"
+#else
+# include "GHOST_ContextGLX.h"
+#endif
#if defined(__sun__) || defined(__sun) || defined(__sparc) || defined(__sparc__) || defined(_AIX)
-#include <strings.h>
+# include <strings.h>
#endif
#include <cstring>
#include <cstdio>
+/* gethostname */
+#include <unistd.h>
+
#include <algorithm>
#include <string>
@@ -65,16 +72,11 @@ typedef struct {
long input_mode;
} MotifWmHints;
-// Workaround for MESA bug #54080
-// https://bugs.freedesktop.org/show_bug.cgi?id=54080()
-#define SWAP_INTERVALS_WORKAROUND
-
-#ifdef SWAP_INTERVALS_WORKAROUND
-static bool g_swap_interval_disabled = false;
-#endif // SWAP_INTERVALS_WORKAROUND
-
#define MWM_HINTS_DECORATIONS (1L << 1)
+#ifndef HOST_NAME_MAX
+# define HOST_NAME_MAX 64
+#endif
// #define GHOST_X11_GRAB
@@ -156,14 +158,79 @@ static long BLENDER_ICON_48x48x32[] = {
4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303,
};
+static XVisualInfo *x11_visualinfo_from_glx(
+ Display *display,
+ bool stereoVisual, GHOST_TUns16 *r_numOfAASamples)
+{
+ XVisualInfo *visualInfo = NULL;
+ GHOST_TUns16 numOfAASamples = *r_numOfAASamples;
+ GHOST_TUns16 actualSamples;
+
+ /* Set up the minimum attributes that we require and see if
+ * X can find us a visual matching those requirements. */
+ int glx_major, glx_minor; /* GLX version: major.minor */
+
+ if (!glXQueryVersion(display, &glx_major, &glx_minor)) {
+ fprintf(stderr,
+ "%s:%d: X11 glXQueryVersion() failed, "
+ "verify working openGL system!\n",
+ __FILE__, __LINE__);
+
+ return NULL;
+ }
+
+ /* GLX >= 1.4 required for multi-sample */
+ if ((glx_major > 1) || (glx_major == 1 && glx_minor >= 4)) {
+ actualSamples = numOfAASamples;
+ }
+ else {
+ numOfAASamples = 0;
+ actualSamples = 0;
+ }
+
+ /* Find the display with highest samples, starting at level requested */
+ for (;;) {
+ int glx_attribs[64];
+
+ GHOST_X11_GL_GetAttributes(glx_attribs, 64, actualSamples, stereoVisual, false);
+
+ visualInfo = glXChooseVisual(display, DefaultScreen(display), glx_attribs);
+
+ /* Any sample level or even zero, which means oversampling disabled, is good
+ * but we need a valid visual to continue */
+ if (visualInfo != NULL) {
+ if (actualSamples < numOfAASamples) {
+ fprintf(stderr,
+ "Warning! Unable to find a multisample pixel format that supports exactly %d samples. "
+ "Substituting one that uses %d samples.\n",
+ numOfAASamples, actualSamples);
+ }
+ break;
+ }
+
+ if (actualSamples == 0) {
+ /* All options exhausted, cannot continue */
+ fprintf(stderr,
+ "%s:%d: X11 glXChooseVisual() failed, "
+ "verify working openGL system!\n",
+ __FILE__, __LINE__);
+
+ return NULL;
+ }
+ else {
+ --actualSamples;
+ }
+ }
+
+ *r_numOfAASamples = actualSamples;
-GLXContext GHOST_WindowX11::s_firstContext = NULL;
+ return visualInfo;
+}
GHOST_WindowX11::
-GHOST_WindowX11(
- GHOST_SystemX11 *system,
+GHOST_WindowX11(GHOST_SystemX11 *system,
Display *display,
- const STR_String& title,
+ const STR_String &title,
GHOST_TInt32 left,
GHOST_TInt32 top,
GHOST_TUns32 width,
@@ -173,109 +240,51 @@ GHOST_WindowX11(
GHOST_TDrawingContextType type,
const bool stereoVisual,
const bool exclusive,
- const GHOST_TUns16 numOfAASamples)
- : GHOST_Window(width, height, state, type, stereoVisual, exclusive, numOfAASamples),
- m_context(NULL),
+ const GHOST_TUns16 numOfAASamples, const bool is_debug)
+ : GHOST_Window(width, height, state, stereoVisual, exclusive, numOfAASamples),
m_display(display),
+ m_visualInfo(NULL),
m_normal_state(GHOST_kWindowStateNormal),
m_system(system),
- m_valid_setup(false),
m_invalid_window(false),
m_empty_cursor(None),
m_custom_cursor(None),
- m_visible_cursor(None)
+ m_visible_cursor(None),
+#ifdef WITH_XDND
+ m_dropTarget(NULL),
+#endif
+#if defined(WITH_X11_XINPUT) && defined(X_HAVE_UTF8_STRING)
+ m_xic(NULL),
+#endif
+ m_valid_setup(false),
+ m_is_debug_context(is_debug)
{
-
- /* Set up the minimum attributes that we require and see if
- * X can find us a visual matching those requirements. */
-
- int attributes[40], i, samples;
- int natom;
- int glxVersionMajor, glxVersionMinor; /* As in GLX major.minor */
-
- m_visual = NULL;
-
- if (!glXQueryVersion(m_display, &glxVersionMajor, &glxVersionMinor)) {
- printf("%s:%d: X11 glXQueryVersion() failed, verify working openGL system!\n", __FILE__, __LINE__);
-
- /* exit if this is the first window */
- if (s_firstContext == NULL) {
- printf("initial window could not find the GLX extension, exit!\n");
- exit(1);
- }
-
- return;
+ if (type == GHOST_kDrawingContextTypeOpenGL) {
+ m_visualInfo = x11_visualinfo_from_glx(m_display, stereoVisual, &m_wantNumOfAASamples);
}
-
- /* Find the display with highest samples, starting at level requested */
- for (samples = m_numOfAASamples; samples >= 0; samples--) {
- i = 0; /* Reusing attributes array, so reset counter */
-
- if (m_stereoVisual)
- attributes[i++] = GLX_STEREO;
-
- attributes[i++] = GLX_RGBA;
- attributes[i++] = GLX_DOUBLEBUFFER;
- attributes[i++] = GLX_RED_SIZE; attributes[i++] = 1;
- attributes[i++] = GLX_BLUE_SIZE; attributes[i++] = 1;
- attributes[i++] = GLX_GREEN_SIZE; attributes[i++] = 1;
- attributes[i++] = GLX_DEPTH_SIZE; attributes[i++] = 1;
-#ifdef GHOST_OPENGL_ALPHA
- attributes[i++] = GLX_ALPHA_SIZE; attributes[i++] = 1;
-#endif
- /* GLX >= 1.4 required for multi-sample */
- if (samples && (glxVersionMajor >= 1) && (glxVersionMinor >= 4)) {
- attributes[i++] = GLX_SAMPLE_BUFFERS; attributes[i++] = 1;
- attributes[i++] = GLX_SAMPLES; attributes[i++] = samples;
- }
- attributes[i] = None;
-
- m_visual = glXChooseVisual(m_display, DefaultScreen(m_display), attributes);
-
- /* Any sample level or even zero, which means oversampling disabled, is good
- * but we need a valid visual to continue */
- if (m_visual == NULL) {
- if (samples == 0) {
- /* All options exhausted, cannot continue */
- printf("%s:%d: X11 glXChooseVisual() failed, verify working openGL system!\n", __FILE__, __LINE__);
-
- if (s_firstContext == NULL) {
- printf("initial window could not find the GLX extension, exit!\n");
- exit(1);
- }
-
- return;
- }
- }
- else {
- if (m_numOfAASamples && (m_numOfAASamples > samples)) {
- printf("%s:%d: oversampling requested %i but using %i samples\n",
- __FILE__, __LINE__, m_numOfAASamples, samples);
- }
- break;
- }
+ else {
+ XVisualInfo tmp = {0};
+ int n;
+ m_visualInfo = XGetVisualInfo(m_display, 0, &tmp, &n);
}
- /* Create a bunch of attributes needed to create an X window. */
-
+ /* caller needs to check 'getValid()' */
+ if (m_visualInfo == NULL) {
+ fprintf(stderr, "initial window could not find the GLX extension\n");
+ return;
+ }
- /* First create a colormap for the window and visual.
- * This seems pretty much a legacy feature as we are in rgba mode anyway. */
+ unsigned int xattributes_valuemask = 0;
XSetWindowAttributes xattributes;
- unsigned int xattributes_valuemask = (CWBorderPixel | CWColormap | CWEventMask);
memset(&xattributes, 0, sizeof(xattributes));
- xattributes.colormap = XCreateColormap(m_display,
- RootWindow(m_display, m_visual->screen),
- m_visual->visual,
- AllocNone
- );
-
+ xattributes_valuemask |= CWBorderPixel;
xattributes.border_pixel = 0;
/* Specify which events we are interested in hearing. */
+ xattributes_valuemask |= CWEventMask;
xattributes.event_mask =
ExposureMask | StructureNotifyMask |
KeyPressMask | KeyReleaseMask |
@@ -289,24 +298,28 @@ GHOST_WindowX11(
xattributes.override_redirect = True;
}
+ xattributes_valuemask |= CWColormap;
+ xattributes.colormap = XCreateColormap(
+ m_display,
+ RootWindow(m_display, m_visualInfo->screen),
+ m_visualInfo->visual,
+ AllocNone
+ );
+
/* create the window! */
if (parentWindow == 0) {
- m_window = XCreateWindow(m_display,
- RootWindow(m_display, m_visual->screen),
- left,
- top,
- width,
- height,
- 0, /* no border. */
- m_visual->depth,
- InputOutput,
- m_visual->visual,
- xattributes_valuemask,
- &xattributes
- );
+ m_window = XCreateWindow(
+ m_display,
+ RootWindow(m_display, m_visualInfo->screen),
+ left, top, width, height,
+ 0, /* no border. */
+ m_visualInfo->depth,
+ InputOutput,
+ m_visualInfo->visual,
+ xattributes_valuemask,
+ &xattributes);
}
else {
-
Window root_return;
int x_return, y_return;
unsigned int w_return, h_return, border_w_return, depth_return;
@@ -320,19 +333,16 @@ GHOST_WindowX11(
height = h_return;
- m_window = XCreateWindow(m_display,
- parentWindow, /* reparent against embedder */
- left,
- top,
- width,
- height,
- 0, /* no border. */
- m_visual->depth,
- InputOutput,
- m_visual->visual,
- xattributes_valuemask,
- &xattributes
- );
+ m_window = XCreateWindow(
+ m_display,
+ parentWindow, /* reparent against embedder */
+ left, top, width, height,
+ 0, /* no border. */
+ m_visualInfo->depth,
+ InputOutput,
+ m_visualInfo->visual,
+ xattributes_valuemask,
+ &xattributes);
XSelectInput(m_display, parentWindow, SubstructureNotifyMask);
@@ -384,36 +394,43 @@ GHOST_WindowX11(
m_post_state = GHOST_kWindowStateNormal;
}
+
/* Create some hints for the window manager on how
* we want this window treated. */
+ {
+ XSizeHints *xsizehints = XAllocSizeHints();
+ xsizehints->flags = PPosition | PSize | PMinSize | PMaxSize;
+ xsizehints->x = left;
+ xsizehints->y = top;
+ xsizehints->width = width;
+ xsizehints->height = height;
+ xsizehints->min_width = 320; /* size hints, could be made apart of the ghost api */
+ xsizehints->min_height = 240; /* limits are also arbitrary, but should not allow 1x1 window */
+ xsizehints->max_width = 65535;
+ xsizehints->max_height = 65535;
+ XSetWMNormalHints(m_display, m_window, xsizehints);
+ XFree(xsizehints);
+ }
+
+
+ /* XClassHint, title */
+ {
+ XClassHint *xclasshint = XAllocClassHint();
+ const int len = title.Length() + 1;
+ char *wmclass = (char *)malloc(sizeof(char) * len);
+ memcpy(wmclass, title.ReadPtr(), len * sizeof(char));
+ xclasshint->res_name = wmclass;
+ xclasshint->res_class = wmclass;
+ XSetClassHint(m_display, m_window, xclasshint);
+ free(wmclass);
+ XFree(xclasshint);
+ }
- XSizeHints *xsizehints = XAllocSizeHints();
- xsizehints->flags = PPosition | PSize | PMinSize | PMaxSize;
- xsizehints->x = left;
- xsizehints->y = top;
- xsizehints->width = width;
- xsizehints->height = height;
- xsizehints->min_width = 320; /* size hints, could be made apart of the ghost api */
- xsizehints->min_height = 240; /* limits are also arbitrary, but should not allow 1x1 window */
- xsizehints->max_width = 65535;
- xsizehints->max_height = 65535;
- XSetWMNormalHints(m_display, m_window, xsizehints);
- XFree(xsizehints);
-
- XClassHint *xclasshint = XAllocClassHint();
- const int len = title.Length() + 1;
- char *wmclass = (char *)malloc(sizeof(char) * len);
- strncpy(wmclass, (const char *)title, sizeof(char) * len);
- xclasshint->res_name = wmclass;
- xclasshint->res_class = wmclass;
- XSetClassHint(m_display, m_window, xclasshint);
- free(wmclass);
- XFree(xclasshint);
/* The basic for a good ICCCM "work" */
if (m_system->m_atom.WM_PROTOCOLS) {
Atom atoms[2];
- natom = 0;
+ int natom = 0;
if (m_system->m_atom.WM_DELETE_WINDOW) {
atoms[natom] = m_system->m_atom.WM_DELETE_WINDOW;
@@ -431,27 +448,48 @@ GHOST_WindowX11(
}
}
-#if defined(WITH_X11_XINPUT) && defined(X_HAVE_UTF8_STRING)
- m_xic = NULL;
-#endif
-
/* Set the window hints */
- XWMHints *xwmhints = XAllocWMHints();
- xwmhints->initial_state = NormalState;
- xwmhints->input = True;
- xwmhints->flags = InputHint | StateHint;
- XSetWMHints(display, m_window, xwmhints);
- XFree(xwmhints);
- /* done setting the hints */
+ {
+ XWMHints *xwmhints = XAllocWMHints();
+ xwmhints->initial_state = NormalState;
+ xwmhints->input = True;
+ xwmhints->flags = InputHint | StateHint;
+ XSetWMHints(display, m_window, xwmhints);
+ XFree(xwmhints);
+ }
+
/* set the icon */
- Atom _NET_WM_ICON = XInternAtom(m_display, "_NET_WM_ICON", False);
- XChangeProperty(m_display, m_window, _NET_WM_ICON, XA_CARDINAL,
- 32, PropModeReplace, (unsigned char *)BLENDER_ICON_48x48x32,
- BLENDER_ICON_48x48x32[0] * BLENDER_ICON_48x48x32[1] + 2);
- /* done setting the icon */
+ {
+ Atom _NET_WM_ICON = XInternAtom(m_display, "_NET_WM_ICON", False);
+ XChangeProperty(m_display, m_window, _NET_WM_ICON, XA_CARDINAL,
+ 32, PropModeReplace, (unsigned char *)BLENDER_ICON_48x48x32,
+ BLENDER_ICON_48x48x32[0] * BLENDER_ICON_48x48x32[1] + 2);
+ }
- setTitle(title);
+ /* set the process ID (_NET_WM_PID) */
+ {
+ Atom _NET_WM_PID = XInternAtom(m_display, "_NET_WM_PID", False);
+ pid_t pid = getpid();
+ XChangeProperty(m_display, m_window, _NET_WM_PID, XA_CARDINAL,
+ 32, PropModeReplace, (unsigned char *)&pid, 1);
+ }
+
+
+ /* set the hostname (WM_CLIENT_MACHINE) */
+ {
+ char hostname[HOST_NAME_MAX];
+ char *text_array[1];
+ XTextProperty text_prop;
+
+ gethostname(hostname, sizeof(hostname));
+ hostname[sizeof(hostname) - 1] = '\0';
+ text_array[0] = hostname;
+
+ XStringListToTextProperty(text_array, 1, &text_prop);
+ XSetWMClientMachine(m_display, m_window, &text_prop);
+ XFree(text_prop.value);
+ }
#ifdef WITH_X11_XINPUT
initXInputDevices();
@@ -459,12 +497,15 @@ GHOST_WindowX11(
m_tabletData.Active = GHOST_kTabletModeNone;
#endif
+
/* now set up the rendering context. */
- if (installDrawingContext(type) == GHOST_kSuccess) {
+ if (setDrawingContextType(type) == GHOST_kSuccess) {
m_valid_setup = true;
GHOST_PRINT("Created window\n");
}
+ setTitle(title);
+
if (exclusive) {
XMapRaised(m_display, m_window);
}
@@ -477,7 +518,7 @@ GHOST_WindowX11(
}
#if defined(WITH_X11_XINPUT) && defined(X_HAVE_UTF8_STRING)
-static void destroyICCallback(XIC xic, XPointer ptr, XPointer data)
+static void destroyICCallback(XIC /*xic*/, XPointer ptr, XPointer /*data*/)
{
GHOST_PRINT("XIM input context destroyed\n");
@@ -525,23 +566,32 @@ void GHOST_WindowX11::initXInputDevices()
if (version && (version != (XExtensionVersion *)NoSuchExtension)) {
if (version->present) {
GHOST_SystemX11::GHOST_TabletX11 &xtablet = m_system->GetXTablet();
- XEventClass xevents[10], ev;
+ XEventClass xevents[8], ev;
int dcount = 0;
+ /* With modern XInput (xlib 1.6.2 at least and/or evdev 2.9.0) and some 'no-name' tablets
+ * like 'UC-LOGIC Tablet WP5540U', we also need to 'select' ButtonPress for motion event,
+ * otherwise we do not get any tablet motion event once pen is pressed... See T43367.
+ */
+
if (xtablet.StylusDevice) {
DeviceMotionNotify(xtablet.StylusDevice, xtablet.MotionEvent, ev);
if (ev) xevents[dcount++] = ev;
+ DeviceButtonPress(xtablet.StylusDevice, xtablet.PressEvent, ev);
+ if (ev) xevents[dcount++] = ev;
ProximityIn(xtablet.StylusDevice, xtablet.ProxInEvent, ev);
if (ev) xevents[dcount++] = ev;
ProximityOut(xtablet.StylusDevice, xtablet.ProxOutEvent, ev);
if (ev) xevents[dcount++] = ev;
}
if (xtablet.EraserDevice) {
- DeviceMotionNotify(xtablet.EraserDevice, xtablet.MotionEvent, ev);
+ DeviceMotionNotify(xtablet.EraserDevice, xtablet.MotionEventEraser, ev);
if (ev) xevents[dcount++] = ev;
- ProximityIn(xtablet.EraserDevice, xtablet.ProxInEvent, ev);
+ DeviceButtonPress(xtablet.EraserDevice, xtablet.PressEventEraser, ev);
if (ev) xevents[dcount++] = ev;
- ProximityOut(xtablet.EraserDevice, xtablet.ProxOutEvent, ev);
+ ProximityIn(xtablet.EraserDevice, xtablet.ProxInEventEraser, ev);
+ if (ev) xevents[dcount++] = ev;
+ ProximityOut(xtablet.EraserDevice, xtablet.ProxOutEventEraser, ev);
if (ev) xevents[dcount++] = ev;
}
@@ -564,7 +614,7 @@ bool
GHOST_WindowX11::
getValid() const
{
- return m_valid_setup;
+ return GHOST_Window::getValid() && m_valid_setup;
}
void
@@ -685,7 +735,7 @@ screenToClient(
Window temp;
XTranslateCoordinates(m_display,
- RootWindow(m_display, m_visual->screen),
+ RootWindow(m_display, m_visualInfo->screen),
m_window,
inX, inY,
&ax, &ay,
@@ -708,7 +758,7 @@ clientToScreen(
XTranslateCoordinates(
m_display,
m_window,
- RootWindow(m_display, m_visual->screen),
+ RootWindow(m_display, m_visualInfo->screen),
inX, inY,
&ax, &ay,
&temp);
@@ -731,7 +781,7 @@ void GHOST_WindowX11::icccmSetState(int state)
xev.xclient.format = 32;
xev.xclient.message_type = m_system->m_atom.WM_CHANGE_STATE;
xev.xclient.data.l[0] = state;
- XSendEvent(m_display, RootWindow(m_display, DefaultScreen(m_display)),
+ XSendEvent(m_display, RootWindow(m_display, m_visualInfo->screen),
False, SubstructureNotifyMask | SubstructureRedirectMask, &xev);
}
@@ -777,7 +827,7 @@ void GHOST_WindowX11::netwmMaximized(bool set)
xev.xclient.data.l[2] = m_system->m_atom._NET_WM_STATE_MAXIMIZED_VERT;
xev.xclient.data.l[3] = 0;
xev.xclient.data.l[4] = 0;
- XSendEvent(m_display, RootWindow(m_display, DefaultScreen(m_display)),
+ XSendEvent(m_display, RootWindow(m_display, m_visualInfo->screen),
False, SubstructureRedirectMask | SubstructureNotifyMask, &xev);
}
@@ -833,7 +883,7 @@ void GHOST_WindowX11::netwmFullScreen(bool set)
xev.xclient.data.l[2] = 0;
xev.xclient.data.l[3] = 0;
xev.xclient.data.l[4] = 0;
- XSendEvent(m_display, RootWindow(m_display, DefaultScreen(m_display)),
+ XSendEvent(m_display, RootWindow(m_display, m_visualInfo->screen),
False, SubstructureRedirectMask | SubstructureNotifyMask, &xev);
}
@@ -1052,7 +1102,7 @@ setOrder(
xev.xclient.data.l[3] = 0;
xev.xclient.data.l[4] = 0;
- root = RootWindow(m_display, m_visual->screen),
+ root = RootWindow(m_display, m_visualInfo->screen),
eventmask = SubstructureRedirectMask | SubstructureNotifyMask;
XSendEvent(m_display, root, False, eventmask, &xev);
@@ -1079,34 +1129,6 @@ setOrder(
GHOST_TSuccess
GHOST_WindowX11::
-swapBuffers()
-{
- if (getDrawingContextType() == GHOST_kDrawingContextTypeOpenGL) {
- glXSwapBuffers(m_display, m_window);
- return GHOST_kSuccess;
- }
- else {
- return GHOST_kFailure;
- }
-}
-
-GHOST_TSuccess
-GHOST_WindowX11::
-activateDrawingContext()
-{
- if (m_context != NULL) {
- glXMakeCurrent(m_display, m_window, m_context);
- /* Disable AA by default */
- if (m_numOfAASamples > 0) {
- glDisable(GL_MULTISAMPLE_ARB);
- }
- return GHOST_kSuccess;
- }
- return GHOST_kFailure;
-}
-
-GHOST_TSuccess
-GHOST_WindowX11::
invalidate()
{
/* So the idea of this function is to generate an expose event
@@ -1151,15 +1173,6 @@ validate()
GHOST_WindowX11::
~GHOST_WindowX11()
{
- static Atom Primary_atom, Clipboard_atom;
- Window p_owner, c_owner;
- /*Change the owner of the Atoms to None if we are the owner*/
- Primary_atom = XInternAtom(m_display, "PRIMARY", False);
- Clipboard_atom = XInternAtom(m_display, "CLIPBOARD", False);
-
- p_owner = XGetSelectionOwner(m_display, Primary_atom);
- c_owner = XGetSelectionOwner(m_display, Clipboard_atom);
-
std::map<unsigned int, Cursor>::iterator it = m_standard_cursors.begin();
for (; it != m_standard_cursors.end(); ++it) {
XFreeCursor(m_display, it->second);
@@ -1172,17 +1185,29 @@ GHOST_WindowX11::
XFreeCursor(m_display, m_custom_cursor);
}
- if (m_context != s_firstContext) {
- glXDestroyContext(m_display, m_context);
+ if (m_valid_setup) {
+ static Atom Primary_atom, Clipboard_atom;
+ Window p_owner, c_owner;
+ /*Change the owner of the Atoms to None if we are the owner*/
+ Primary_atom = XInternAtom(m_display, "PRIMARY", False);
+ Clipboard_atom = XInternAtom(m_display, "CLIPBOARD", False);
+
+
+ p_owner = XGetSelectionOwner(m_display, Primary_atom);
+ c_owner = XGetSelectionOwner(m_display, Clipboard_atom);
+
+ if (p_owner == m_window) {
+ XSetSelectionOwner(m_display, Primary_atom, None, CurrentTime);
+ }
+ if (c_owner == m_window) {
+ XSetSelectionOwner(m_display, Clipboard_atom, None, CurrentTime);
+ }
}
- if (p_owner == m_window) {
- XSetSelectionOwner(m_display, Primary_atom, None, CurrentTime);
- }
- if (c_owner == m_window) {
- XSetSelectionOwner(m_display, Clipboard_atom, None, CurrentTime);
+ if (m_visualInfo) {
+ XFree(m_visualInfo);
}
-
+
#if defined(WITH_X11_XINPUT) && defined(X_HAVE_UTF8_STRING)
if (m_xic) {
XDestroyIC(m_xic);
@@ -1193,88 +1218,103 @@ GHOST_WindowX11::
delete m_dropTarget;
#endif
- XDestroyWindow(m_display, m_window);
- XFree(m_visual);
-}
-
+ releaseNativeHandles();
+ if (m_valid_setup) {
+ XDestroyWindow(m_display, m_window);
+ }
+}
-/**
- * Tries to install a rendering context in this window.
- * \param type The type of rendering context installed.
- * \return Indication as to whether installation has succeeded.
- */
-GHOST_TSuccess
-GHOST_WindowX11::
-installDrawingContext(
- GHOST_TDrawingContextType type)
+GHOST_Context *GHOST_WindowX11::newDrawingContext(GHOST_TDrawingContextType type)
{
- /* only support openGL for now. */
- GHOST_TSuccess success;
- switch (type) {
- case GHOST_kDrawingContextTypeOpenGL:
- {
-#ifdef WITH_X11_XINPUT
- /* use our own event handlers to avoid exiting blender,
- * this would happen for eg:
- * if you open blender, unplug a tablet, then open a new window. */
- XErrorHandler old_handler = XSetErrorHandler(GHOST_X11_ApplicationErrorHandler);
- XIOErrorHandler old_handler_io = XSetIOErrorHandler(GHOST_X11_ApplicationIOErrorHandler);
+ if (type == GHOST_kDrawingContextTypeOpenGL) {
+#if !defined(WITH_GL_EGL)
+
+#if defined(WITH_GL_PROFILE_CORE)
+ GHOST_Context *context = new GHOST_ContextGLX(
+ m_wantStereoVisual,
+ m_wantNumOfAASamples,
+ m_window,
+ m_display,
+ m_visualInfo,
+ GLX_CONTEXT_CORE_PROFILE_BIT_ARB,
+ 3, 2,
+ GHOST_OPENGL_GLX_CONTEXT_FLAGS | (m_is_debug_context ? GLX_CONTEXT_DEBUG_BIT_ARB : 0),
+ GHOST_OPENGL_GLX_RESET_NOTIFICATION_STRATEGY);
+#elif defined(WITH_GL_PROFILE_ES20)
+ GHOST_Context *context = new GHOST_ContextGLX(
+ m_wantStereoVisual,
+ m_wantNumOfAASamples,
+ m_window,
+ m_display,
+ m_visualInfo,
+ GLX_CONTEXT_ES2_PROFILE_BIT_EXT,
+ 2, 0,
+ GHOST_OPENGL_GLX_CONTEXT_FLAGS | (m_is_debug_context ? GLX_CONTEXT_DEBUG_BIT_ARB : 0),
+ GHOST_OPENGL_GLX_RESET_NOTIFICATION_STRATEGY);
+#elif defined(WITH_GL_PROFILE_COMPAT)
+ GHOST_Context *context = new GHOST_ContextGLX(
+ m_wantStereoVisual,
+ m_wantNumOfAASamples,
+ m_window,
+ m_display,
+ m_visualInfo,
+ 0, // profile bit
+ 0, 0,
+ GHOST_OPENGL_GLX_CONTEXT_FLAGS | (m_is_debug_context ? GLX_CONTEXT_DEBUG_BIT_ARB : 0),
+ GHOST_OPENGL_GLX_RESET_NOTIFICATION_STRATEGY);
+#else
+# error
#endif
- m_context = glXCreateContext(m_display, m_visual, s_firstContext, True);
- if (m_context != NULL) {
- if (!s_firstContext) {
- s_firstContext = m_context;
- }
- glXMakeCurrent(m_display, m_window, m_context);
- glClearColor(0.447, 0.447, 0.447, 0);
- glClear(GL_COLOR_BUFFER_BIT);
- success = GHOST_kSuccess;
- }
- else {
- success = GHOST_kFailure;
- }
+#else
+
+#if defined(WITH_GL_PROFILE_CORE)
+ GHOST_Context *context = new GHOST_ContextEGL(
+ m_wantStereoVisual,
+ m_wantNumOfAASamples,
+ m_window,
+ m_display,
+ EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT,
+ 3, 2,
+ GHOST_OPENGL_EGL_CONTEXT_FLAGS,
+ GHOST_OPENGL_EGL_RESET_NOTIFICATION_STRATEGY,
+ EGL_OPENGL_API);
+#elif defined(WITH_GL_PROFILE_ES20)
+ GHOST_Context *context = new GHOST_ContextEGL(
+ m_wantStereoVisual,
+ m_wantNumOfAASamples,
+ m_window,
+ m_display,
+ 0, // profile bit
+ 2, 0,
+ GHOST_OPENGL_EGL_CONTEXT_FLAGS,
+ GHOST_OPENGL_EGL_RESET_NOTIFICATION_STRATEGY,
+ EGL_OPENGL_ES_API);
+#elif defined(WITH_GL_PROFILE_COMPAT)
+ GHOST_Context *context = new GHOST_ContextEGL(
+ m_wantStereoVisual,
+ m_wantNumOfAASamples,
+ m_window,
+ m_display,
+ 0, // profile bit
+ 0, 0,
+ GHOST_OPENGL_EGL_CONTEXT_FLAGS,
+ GHOST_OPENGL_EGL_RESET_NOTIFICATION_STRATEGY,
+ EGL_OPENGL_API);
+#else
+# error
+#endif
-#ifdef WITH_X11_XINPUT
- /* Restore handler */
- (void) XSetErrorHandler(old_handler);
- (void) XSetIOErrorHandler(old_handler_io);
#endif
- break;
- }
- case GHOST_kDrawingContextTypeNone:
- {
- success = GHOST_kSuccess;
- break;
- }
- default:
- success = GHOST_kFailure;
+ if (context->initializeDrawingContext())
+ return context;
+ else
+ delete context;
}
- return success;
-}
-
-
-
-/**
- * Removes the current drawing context.
- * \return Indication as to whether removal has succeeded.
- */
-GHOST_TSuccess
-GHOST_WindowX11::
-removeDrawingContext()
-{
- GHOST_TSuccess success;
- if (m_context != NULL) {
- glXDestroyContext(m_display, m_context);
- success = GHOST_kSuccess;
- }
- else {
- success = GHOST_kFailure;
- }
- return success;
+ return NULL;
}
@@ -1336,13 +1376,13 @@ getEmptyCursor(
) {
if (!m_empty_cursor) {
Pixmap blank;
- XColor dummy;
+ XColor dummy = {0};
char data[1] = {0};
/* make a blank cursor */
blank = XCreateBitmapFromData(
m_display,
- RootWindow(m_display, DefaultScreen(m_display)),
+ RootWindow(m_display, m_visualInfo->screen),
data, 1, 1
);
@@ -1458,10 +1498,10 @@ setWindowCustomCursorShape(
int sizey,
int hotX,
int hotY,
- int fg_color,
- int bg_color)
+ int /*fg_color*/,
+ int /*bg_color*/)
{
- Colormap colormap = DefaultColormap(m_display, DefaultScreen(m_display));
+ Colormap colormap = DefaultColormap(m_display, m_visualInfo->screen);
Pixmap bitmap_pix, mask_pix;
XColor fg, bg;
@@ -1530,72 +1570,3 @@ endFullScreen() const
return GHOST_kSuccess;
}
-
-GHOST_TSuccess
-GHOST_WindowX11::
-setSwapInterval(int interval) {
- if (!GLX_EXT_swap_control || !glXSwapIntervalEXT
-#ifdef SWAP_INTERVALS_WORKAROUND
- || g_swap_interval_disabled
-#endif // SWAP_INTERVALS_WORKAROUND
- )
- {
- return GHOST_kFailure;
- }
- glXSwapIntervalEXT(m_display, m_window, interval);
- return GHOST_kSuccess;
-}
-
-#ifdef SWAP_INTERVALS_WORKAROUND
-static int QueryDrawable_ApplicationErrorHandler(Display *display, XErrorEvent *theEvent)
-{
- fprintf(stderr, "Ignoring Xlib error: error code %d request code %d\n",
- theEvent->error_code, theEvent->request_code);
- if (!g_swap_interval_disabled) {
- fprintf(stderr, "Disabling SWAP INTERVALS extension\n");
- g_swap_interval_disabled = true;
- }
- return 0;
-}
-
-static int QueryDrawable_ApplicationIOErrorHandler(Display *display)
-{
- fprintf(stderr, "Ignoring Xlib error: error IO\n");
- if (!g_swap_interval_disabled) {
- fprintf(stderr, "Disabling SWAP INTERVALS extension\n");
- g_swap_interval_disabled = true;
- }
- return 0;
-}
-#endif // SWAP_INTERVALS_WORKAROUND
-
-int
-GHOST_WindowX11::
-getSwapInterval() {
- if (GLX_EXT_swap_control) {
-#ifdef SWAP_INTERVALS_WORKAROUND
- /* XXX: Current MESA driver will give GLXBadDrawable for all
- * the glXQueryDrawable requests with direct contexts.
- *
- * To prevent crashes and unexpected behaviors, we will
- * disable swap intervals extension if query fails here.
- * (because if we will override interval without having
- * old value we couldn't restore it properly).
- */
- XErrorHandler old_handler = XSetErrorHandler(QueryDrawable_ApplicationErrorHandler);
- XIOErrorHandler old_handler_io = XSetIOErrorHandler(QueryDrawable_ApplicationIOErrorHandler);
-#endif // SWAP_INTERVALS_WORKAROUND
-
- unsigned int value = 0;
- glXQueryDrawable(m_display, m_window, GLX_SWAP_INTERVAL_EXT, &value);
-
-#ifdef SWAP_INTERVALS_WORKAROUND
- /* Restore handler */
- (void) XSetErrorHandler(old_handler);
- (void) XSetIOErrorHandler(old_handler_io);
-#endif // SWAP_INTERVALS_WORKAROUND
-
- return (int)value;
- }
- return 0;
-}
diff --git a/intern/ghost/intern/GHOST_WindowX11.h b/intern/ghost/intern/GHOST_WindowX11.h
index faaa05efe82..5beb7b43032 100644
--- a/intern/ghost/intern/GHOST_WindowX11.h
+++ b/intern/ghost/intern/GHOST_WindowX11.h
@@ -35,7 +35,7 @@
#include "GHOST_Window.h"
#include <X11/Xlib.h>
-#include <GL/glx.h>
+#include <X11/Xutil.h>
// For tablets
#ifdef WITH_X11_XINPUT
# include <X11/extensions/XInput.h>
@@ -88,7 +88,8 @@ public:
GHOST_TDrawingContextType type = GHOST_kDrawingContextTypeNone,
const bool stereoVisual = false,
const bool exclusive = false,
- const GHOST_TUns16 numOfAASamples = 0
+ const GHOST_TUns16 numOfAASamples = 0,
+ const bool is_debug = false
);
bool
@@ -160,13 +161,6 @@ public:
);
GHOST_TSuccess
- swapBuffers(
- );
-
- GHOST_TSuccess
- activateDrawingContext(
- );
- GHOST_TSuccess
invalidate(
);
@@ -235,37 +229,12 @@ public:
GHOST_TSuccess endFullScreen() const;
- /**
- * Sets the swap interval for swapBuffers.
- * \param interval The swap interval to use.
- * \return A boolean success indicator.
- */
- virtual GHOST_TSuccess setSwapInterval(int interval);
-
- /**
- * Gets the current swap interval for swapBuffers.
- * \return An integer.
- */
- virtual int getSwapInterval();
-
protected:
/**
- * Tries to install a rendering context in this window.
- * \param type The type of rendering context installed.
- * \return Indication as to whether installation has succeeded.
+ * \param type The type of rendering context create.
+ * \return Indication of success.
*/
- GHOST_TSuccess
- installDrawingContext(
- GHOST_TDrawingContextType type
- );
-
- /**
- * Removes the current drawing context.
- * \return Indication as to whether removal has succeeded.
- */
- GHOST_TSuccess
- removeDrawingContext(
- );
+ GHOST_Context *newDrawingContext(GHOST_TDrawingContextType type);
/**
* Sets the cursor visibility on the window using
@@ -279,7 +248,6 @@ protected:
/**
* Sets the cursor grab on the window using
* native window system calls.
- * \param warp Only used when grab is enabled, hides the mouse and allows dragging outside the screen.
*/
GHOST_TSuccess
setWindowCursorGrab(
@@ -350,21 +318,15 @@ private:
void initXInputDevices();
#endif
- GLXContext m_context;
Window m_window;
- Display *m_display;
- XVisualInfo *m_visual;
- GHOST_TWindowState m_normal_state;
+ Display *m_display;
+ XVisualInfo *m_visualInfo;
- /** The first created OpenGL context (for sharing display lists) */
- static GLXContext s_firstContext;
+ GHOST_TWindowState m_normal_state;
- /// A pointer to the typed system class.
-
+ /** A pointer to the typed system class. */
GHOST_SystemX11 *m_system;
- bool m_valid_setup;
-
/** Used to concatenate calls to invalidate() on this window. */
bool m_invalid_window;
@@ -392,6 +354,9 @@ private:
XIC m_xic;
#endif
+ bool m_valid_setup;
+ bool m_is_debug_context;
+
void icccmSetState(int state);
int icccmGetState() const;
diff --git a/intern/ghost/test/CMakeLists.txt b/intern/ghost/test/CMakeLists.txt
index 84b6f663ff2..e1475966d47 100644
--- a/intern/ghost/test/CMakeLists.txt
+++ b/intern/ghost/test/CMakeLists.txt
@@ -74,6 +74,12 @@ endif()
# -----------------------------------------------------------------------------
# Libraries
+if(UNIX AND NOT APPLE)
+ set(WITH_X11 ON)
+endif()
+# for now... default to this
+add_definitions(-DWITH_GL_PROFILE_COMPAT)
+
# ghost
include(${CMAKE_SOURCE_DIR}/../CMakeLists.txt)
suffix_relpaths(INC_NEW "${INC}" "../")
@@ -109,6 +115,13 @@ suffix_relpaths(SRC_NEW "${SRC}" "../../../extern/wcwidth/")
include_directories(${INC_NEW})
add_library(wcwidth_lib ${SRC_NEW})
+# glew-mx
+include(${CMAKE_SOURCE_DIR}/../../../intern/glew-mx/CMakeLists.txt)
+suffix_relpaths(INC_NEW "${INC}" "../../../intern/glew-mx/")
+suffix_relpaths(SRC_NEW "${SRC}" "../../../intern/glew-mx/")
+include_directories(${INC_NEW})
+add_library(glewmx_lib ${SRC_NEW})
+
# grr, blenfont needs BLI
include_directories(
"../../../source/blender/blenlib"
@@ -130,6 +143,7 @@ add_library(bli_lib
"../../../source/blender/blenlib/intern/BLI_linklist.c"
"../../../source/blender/blenlib/intern/BLI_memarena.c"
"../../../source/blender/blenlib/intern/BLI_mempool.c"
+ "../../../source/blender/blenlib/intern/system.c"
)
set(PLATFORM_CGLAGS)
@@ -184,6 +198,7 @@ add_executable(gears_c
target_link_libraries(gears_c
ghost_lib
+ glewmx_lib
string_lib
${OPENGL_gl_LIBRARY}
${OPENGL_glu_LIBRARY}
@@ -197,6 +212,7 @@ add_executable(gears_cpp
target_link_libraries(gears_cpp
ghost_lib
+ glewmx_lib
string_lib
${OPENGL_gl_LIBRARY}
${OPENGL_glu_LIBRARY}
@@ -225,6 +241,7 @@ target_link_libraries(multitest_c
blenfont_lib
bli_lib
ghost_lib
+ glewmx_lib
string_lib
guardedalloc_lib
wcwidth_lib
diff --git a/intern/ghost/test/gears/GHOST_C-Test.c b/intern/ghost/test/gears/GHOST_C-Test.c
index 00ae4bb25b4..c635ab9be5b 100644
--- a/intern/ghost/test/gears/GHOST_C-Test.c
+++ b/intern/ghost/test/gears/GHOST_C-Test.c
@@ -448,6 +448,7 @@ int processEvent(GHOST_EventHandle hEvent, GHOST_TUserDataPtr userData)
int main(int argc, char **argv)
{
+ GHOST_GLSettings glSettings = {0};
char *title1 = "gears - main window";
char *title2 = "gears - secondary window";
GHOST_EventConsumerHandle consumer = GHOST_CreateEventConsumer(processEvent, NULL);
@@ -459,16 +460,12 @@ int main(int argc, char **argv)
if (shSystem)
{
/* Create the main window */
- sMainWindow = GHOST_CreateWindow(shSystem,
- title1,
- 10,
- 64,
- 320,
- 200,
- GHOST_kWindowStateNormal,
- GHOST_kDrawingContextTypeOpenGL,
- FALSE,
- FALSE);
+ sMainWindow = GHOST_CreateWindow(
+ shSystem, title1,
+ 10, 64, 320, 200,
+ GHOST_kWindowStateNormal,
+ GHOST_kDrawingContextTypeOpenGL,
+ glSettings);
if (!sMainWindow)
{
printf("could not create main window\n");
@@ -476,16 +473,13 @@ int main(int argc, char **argv)
}
/* Create a secondary window */
- sSecondaryWindow = GHOST_CreateWindow(shSystem,
- title2,
- 340,
- 64,
- 320,
- 200,
- GHOST_kWindowStateNormal,
- GHOST_kDrawingContextTypeOpenGL,
- FALSE,
- FALSE);
+ sSecondaryWindow = GHOST_CreateWindow(
+ shSystem,
+ title2,
+ 340, 64, 320, 200,
+ GHOST_kWindowStateNormal,
+ GHOST_kDrawingContextTypeOpenGL,
+ glSettings);
if (!sSecondaryWindow)
{
printf("could not create secondary window\n");
diff --git a/intern/ghost/test/gears/GHOST_Test.cpp b/intern/ghost/test/gears/GHOST_Test.cpp
index a81aaa85ecf..f58a220055f 100644
--- a/intern/ghost/test/gears/GHOST_Test.cpp
+++ b/intern/ghost/test/gears/GHOST_Test.cpp
@@ -418,12 +418,17 @@ Application::Application(GHOST_ISystem *system)
m_gearsTimer(0), m_testTimer(0), m_cursor(GHOST_kStandardCursorFirstCursor),
m_exitRequested(false), stereo(false)
{
+ GHOST_GLSettings glSettings = {0};
fApp = this;
// Create the main window
STR_String title1("gears - main window");
- m_mainWindow = system->createWindow(title1, 10, 64, 320, 200, GHOST_kWindowStateNormal,
- GHOST_kDrawingContextTypeOpenGL, false, false);
+ m_mainWindow = system->createWindow(
+ title1,
+ 10, 64, 320, 200,
+ GHOST_kWindowStateNormal,
+ GHOST_kDrawingContextTypeOpenGL,
+ glSettings);
if (!m_mainWindow) {
std::cout << "could not create main window\n";
@@ -432,8 +437,12 @@ Application::Application(GHOST_ISystem *system)
// Create a secondary window
STR_String title2("gears - secondary window");
- m_secondaryWindow = system->createWindow(title2, 340, 64, 320, 200, GHOST_kWindowStateNormal,
- GHOST_kDrawingContextTypeOpenGL, false, false);
+ m_secondaryWindow = system->createWindow(
+ title2,
+ 340, 64, 320, 200,
+ GHOST_kWindowStateNormal,
+ GHOST_kDrawingContextTypeOpenGL,
+ glSettings);
if (!m_secondaryWindow) {
std::cout << "could not create secondary window\n";
exit(-1);
@@ -689,19 +698,19 @@ int main(int /*argc*/, char ** /*argv*/)
KEY_ALL_ACCESS);
if (lresult == ERROR_SUCCESS)
- printf("Succesfully opened key\n");
+ printf("Successfully opened key\n");
#if 0
lresult = regkey.QueryValue(&keyValue, "StereoEnable");
if (lresult == ERROR_SUCCESS)
- printf("Succesfully queried key\n");
+ printf("Successfully queried key\n");
#endif
lresult = regkey.SetValue(HKEY_LOCAL_MACHINE, "SOFTWARE\\NVIDIA Corporation\\Global\\Stereo3D\\StereoEnable",
"1");
if (lresult == ERROR_SUCCESS)
- printf("Succesfully set value for key\n");
+ printf("Successfully set value for key\n");
regkey.Close();
if (lresult == ERROR_SUCCESS)
- printf("Succesfully closed key\n");
+ printf("Successfully closed key\n");
// regkey.Write("2");
}
#endif // WIN32
diff --git a/intern/ghost/test/multitest/MultiTest.c b/intern/ghost/test/multitest/MultiTest.c
index 9a192c17180..a5b5a511cb2 100644
--- a/intern/ghost/test/multitest/MultiTest.c
+++ b/intern/ghost/test/multitest/MultiTest.c
@@ -309,13 +309,18 @@ static void mainwindow_timer_proc(GHOST_TimerTaskHandle task, GHOST_TUns64 time)
mainwindow_log(mw, buf);
}
-MainWindow *mainwindow_new(MultiTestApp *app) {
+MainWindow *mainwindow_new(MultiTestApp *app)
+{
GHOST_SystemHandle sys = multitestapp_get_system(app);
GHOST_WindowHandle win;
+ GHOST_GLSettings glSettings = {0};
- win = GHOST_CreateWindow(sys, "MultiTest:Main", 40, 40, 400, 400,
- GHOST_kWindowStateNormal, GHOST_kDrawingContextTypeOpenGL,
- FALSE, FALSE);
+ win = GHOST_CreateWindow(
+ sys, "MultiTest:Main",
+ 40, 40, 400, 400,
+ GHOST_kWindowStateNormal,
+ GHOST_kDrawingContextTypeOpenGL,
+ glSettings);
if (win) {
MainWindow *mw = MEM_callocN(sizeof(*mw), "mainwindow_new");
@@ -577,15 +582,20 @@ static void loggerwindow_handle(void *priv, GHOST_EventHandle evt)
/**/
-LoggerWindow *loggerwindow_new(MultiTestApp *app) {
+LoggerWindow *loggerwindow_new(MultiTestApp *app)
+{
+ GHOST_GLSettings glSettings = {0};
GHOST_SystemHandle sys = multitestapp_get_system(app);
GHOST_TUns32 screensize[2];
GHOST_WindowHandle win;
GHOST_GetMainDisplayDimensions(sys, &screensize[0], &screensize[1]);
- win = GHOST_CreateWindow(sys, "MultiTest:Logger", 40, screensize[1] - 432,
- 800, 300, GHOST_kWindowStateNormal,
- GHOST_kDrawingContextTypeOpenGL, FALSE, FALSE);
+ win = GHOST_CreateWindow(
+ sys, "MultiTest:Logger",
+ 40, screensize[1] - 432, 800, 300,
+ GHOST_kWindowStateNormal,
+ GHOST_kDrawingContextTypeOpenGL,
+ glSettings);
if (win) {
LoggerWindow *lw = MEM_callocN(sizeof(*lw), "loggerwindow_new");
@@ -775,13 +785,18 @@ static void extrawindow_handle(void *priv, GHOST_EventHandle evt)
/**/
-ExtraWindow *extrawindow_new(MultiTestApp *app) {
+ExtraWindow *extrawindow_new(MultiTestApp *app)
+{
+ GHOST_GLSettings glSettings = {0};
GHOST_SystemHandle sys = multitestapp_get_system(app);
GHOST_WindowHandle win;
- win = GHOST_CreateWindow(sys, "MultiTest:Extra", 500, 40, 400, 400,
- GHOST_kWindowStateNormal, GHOST_kDrawingContextTypeOpenGL,
- FALSE, FALSE);
+ win = GHOST_CreateWindow(
+ sys, "MultiTest:Extra",
+ 500, 40, 400, 400,
+ GHOST_kWindowStateNormal,
+ GHOST_kDrawingContextTypeOpenGL,
+ glSettings);
if (win) {
ExtraWindow *ew = MEM_callocN(sizeof(*ew), "mainwindow_new");
diff --git a/intern/glew-mx/CMakeLists.txt b/intern/glew-mx/CMakeLists.txt
new file mode 100644
index 00000000000..8b692b5136c
--- /dev/null
+++ b/intern/glew-mx/CMakeLists.txt
@@ -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.
+#
+# The Original Code is Copyright (C) 2014, Blender Foundation
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): Jason Wilkins
+#
+# ***** END GPL LICENSE BLOCK *****
+
+set(INC
+ .
+)
+
+set(INC_SYS
+ ${GLEW_INCLUDE_PATH}
+)
+
+set(SRC
+ intern/glew-mx.c
+
+ glew-mx.h
+ intern/gl-deprecated.h
+ intern/symbol-binding.h
+)
+
+add_definitions(${GL_DEFINITIONS})
+
+blender_add_lib(bf_intern_glew_mx "${SRC}" "${INC}" "${INC_SYS}")
diff --git a/intern/glew-mx/SConscript b/intern/glew-mx/SConscript
new file mode 100644
index 00000000000..546470d020c
--- /dev/null
+++ b/intern/glew-mx/SConscript
@@ -0,0 +1,15 @@
+#!/usr/bin/python
+import sys
+import os
+
+Import('env')
+
+sources = ['intern/glew-mx.c']
+defs = []
+defs += env['BF_GL_DEFINITIONS']
+incs = [
+ '.',
+ env['BF_GLEW_INC'],
+ ]
+
+env.BlenderLib('intern_glew_mx', sources, incs, defs, libtype=['intern','player'], priority=[50, 185])
diff --git a/intern/glew-mx/glew-mx.h b/intern/glew-mx/glew-mx.h
new file mode 100644
index 00000000000..92450d67812
--- /dev/null
+++ b/intern/glew-mx/glew-mx.h
@@ -0,0 +1,113 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2014 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Jason Wilkins
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file glew-mx.h
+ * \ingroup glew-mx
+ *
+ * Support for GLEW Multiple rendering conteXts (MX)
+ * Maintained as a Blender Library.
+ *
+ * Different rendering contexts may have different entry points
+ * to extension functions of the same name. So it can cause
+ * problems if, for example, a second context uses a pointer to
+ * say, glActiveTextureARB, that was queried from the first context.
+ *
+ * GLEW has basic support for multiple contexts by enabling WITH_GLEW_MX,
+ * but it does not provide a full implementation. This is because
+ * there are too many questions about thread safety and memory
+ * allocation that are up to the user of GLEW.
+ *
+ * This implementation is very basic and isn't thread safe.
+ * For a single context the overhead should be
+ * no more than using GLEW without WITH_GLEW_MX enabled.
+ */
+
+#ifndef __GLEW_MX_H__
+#define __GLEW_MX_H__
+
+#ifdef WITH_GLEW_MX
+/* glew itself expects this */
+# define GLEW_MX 1
+# define glewGetContext() (&(_mx_context->glew_context))
+#endif
+
+#include <GL/glew.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* MXContext is used instead of GLEWContext directly so that
+ extending what data is held by a context is easier.
+ */
+typedef struct MXContext {
+#ifdef WITH_GLEW_MX
+ GLEWContext glew_context;
+#endif
+
+ int reserved; /* structs need at least one member */
+
+} MXContext;
+
+#ifdef WITH_GLEW_MX
+extern MXContext *_mx_context;
+#endif
+
+
+#include "intern/symbol-binding.h"
+
+
+/* If compiling only for OpenGL 3.2 Core Profile then we should make sure
+ * no legacy API entries or symbolic constants are used.
+ */
+#if defined(WITH_GL_PROFILE_CORE) && !defined(WITH_GL_PROFILE_COMPAT) && !defined(WITH_GL_PROFILE_ES20)
+# include "intern/gl-deprecated.h"
+#endif
+
+
+MXContext *mxCreateContext (void);
+MXContext *mxGetCurrentContext (void);
+void mxMakeCurrentContext(MXContext *ctx);
+void mxDestroyContext (MXContext *ctx);
+
+void mxIgnoreNoVersion(int ignore);
+
+GLenum glew_chk(GLenum error, const char *file, int line, const char *text);
+
+#ifndef NDEBUG
+# define GLEW_CHK(x) glew_chk((x), __FILE__, __LINE__, #x)
+#else
+# define GLEW_CHK(x) glew_chk((x), NULL, 0, NULL)
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* __GLEW_MX_H__ */
diff --git a/intern/glew-mx/intern/gl-deprecated.h b/intern/glew-mx/intern/gl-deprecated.h
new file mode 100644
index 00000000000..1a23642fbfc
--- /dev/null
+++ b/intern/glew-mx/intern/gl-deprecated.h
@@ -0,0 +1,872 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2014 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Jason Wilkins
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file intern/gl-deprecated.h
+ * \ingroup glew-mx
+ * Utility used to check for use of deprecated functions.
+ */
+
+#ifndef __GL_DEPRECATED_H__
+#define __GL_DEPRECATED_H__
+
+// GL Version 1.0
+#undef glAccum
+#define glAccum DO_NOT_USE_glAccum
+#undef glAlphaFunc
+#define glAlphaFunc DO_NOT_USE_glAlphaFunc
+#undef glBegin
+#define glBegin DO_NOT_USE_glBegin
+#undef glBitmap
+#define glBitmap DO_NOT_USE_glBitmap
+#undef glCallList
+#define glCallList DO_NOT_USE_glCallList
+#undef glCallLists
+#define glCallLists DO_NOT_USE_glCallLists
+#undef glClearAccum
+#define glClearAccum DO_NOT_USE_glClearAccum
+#undef glClearIndex
+#define glClearIndex DO_NOT_USE_glClearIndex
+#undef glClipPlane
+#define glClipPlane DO_NOT_USE_glClipPlane
+#undef glColor3b
+#define glColor3b DO_NOT_USE_glColor3b
+#undef glColor3bv
+#define glColor3bv DO_NOT_USE_glColor3bv
+#undef glColor3d
+#define glColor3d DO_NOT_USE_glColor3d
+#undef glColor3dv
+#define glColor3dv DO_NOT_USE_glColor3dv
+#undef glColor3f
+#define glColor3f DO_NOT_USE_glColor3f
+#undef glColor3fv
+#define glColor3fv DO_NOT_USE_glColor3fv
+#undef glColor3i
+#define glColor3i DO_NOT_USE_glColor3i
+#undef glColor3iv
+#define glColor3iv DO_NOT_USE_glColor3iv
+#undef glColor3s
+#define glColor3s DO_NOT_USE_glColor3s
+#undef glColor3sv
+#define glColor3sv DO_NOT_USE_glColor3sv
+#undef glColor3ub
+#define glColor3ub DO_NOT_USE_glColor3ub
+#undef glColor3ubv
+#define glColor3ubv DO_NOT_USE_glColor3ubv
+#undef glColor3ui
+#define glColor3ui DO_NOT_USE_glColor3ui
+#undef glColor3uiv
+#define glColor3uiv DO_NOT_USE_glColor3uiv
+#undef glColor3us
+#define glColor3us DO_NOT_USE_glColor3us
+#undef glColor3usv
+#define glColor3usv DO_NOT_USE_glColor3usv
+#undef glColor4b
+#define glColor4b DO_NOT_USE_glColor4b
+#undef glColor4bv
+#define glColor4bv DO_NOT_USE_glColor4bv
+#undef glColor4d
+#define glColor4d DO_NOT_USE_glColor4d
+#undef glColor4dv
+#define glColor4dv DO_NOT_USE_glColor4dv
+#undef glColor4f
+#define glColor4f DO_NOT_USE_glColor4f
+#undef glColor4fv
+#define glColor4fv DO_NOT_USE_glColor4fv
+#undef glColor4i
+#define glColor4i DO_NOT_USE_glColor4i
+#undef glColor4iv
+#define glColor4iv DO_NOT_USE_glColor4iv
+#undef glColor4s
+#define glColor4s DO_NOT_USE_glColor4s
+#undef glColor4sv
+#define glColor4sv DO_NOT_USE_glColor4sv
+#undef glColor4ub
+#define glColor4ub DO_NOT_USE_glColor4ub
+#undef glColor4ubv
+#define glColor4ubv DO_NOT_USE_glColor4ubv
+#undef glColor4ui
+#define glColor4ui DO_NOT_USE_glColor4ui
+#undef glColor4uiv
+#define glColor4uiv DO_NOT_USE_glColor4uiv
+#undef glColor4us
+#define glColor4us DO_NOT_USE_glColor4us
+#undef glColor4usv
+#define glColor4usv DO_NOT_USE_glColor4usv
+#undef glColorMaterial
+#define glColorMaterial DO_NOT_USE_glColorMaterial
+#undef glCopyPixels
+#define glCopyPixels DO_NOT_USE_glCopyPixels
+#undef glDeleteLists
+#define glDeleteLists DO_NOT_USE_glDeleteLists
+#undef glDrawPixels
+#define glDrawPixels DO_NOT_USE_glDrawPixels
+#undef glEdgeFlag
+#define glEdgeFlag DO_NOT_USE_glEdgeFlag
+#undef glEdgeFlagv
+#define glEdgeFlagv DO_NOT_USE_glEdgeFlagv
+#undef glEnd
+#define glEnd DO_NOT_USE_glEnd
+#undef glEndList
+#define glEndList DO_NOT_USE_glEndList
+#undef glEvalCoord1d
+#define glEvalCoord1d DO_NOT_USE_glEvalCoord1d
+#undef glEvalCoord1dv
+#define glEvalCoord1dv DO_NOT_USE_glEvalCoord1dv
+#undef glEvalCoord1f
+#define glEvalCoord1f DO_NOT_USE_glEvalCoord1f
+#undef glEvalCoord1fv
+#define glEvalCoord1fv DO_NOT_USE_glEvalCoord1fv
+#undef glEvalCoord2d
+#define glEvalCoord2d DO_NOT_USE_glEvalCoord2d
+#undef glEvalCoord2dv
+#define glEvalCoord2dv DO_NOT_USE_glEvalCoord2dv
+#undef glEvalCoord2f
+#define glEvalCoord2f DO_NOT_USE_glEvalCoord2f
+#undef glEvalCoord2fv
+#define glEvalCoord2fv DO_NOT_USE_glEvalCoord2fv
+#undef glEvalMesh1
+#define glEvalMesh1 DO_NOT_USE_glEvalMesh1
+#undef glEvalMesh2
+#define glEvalMesh2 DO_NOT_USE_glEvalMesh2
+#undef glEvalPoint1
+#define glEvalPoint1 DO_NOT_USE_glEvalPoint1
+#undef glEvalPoint2
+#define glEvalPoint2 DO_NOT_USE_glEvalPoint2
+#undef glFeedbackBuffer
+#define glFeedbackBuffer DO_NOT_USE_glFeedbackBuffer
+#undef glFogf
+#define glFogf DO_NOT_USE_glFogf
+#undef glFogfv
+#define glFogfv DO_NOT_USE_glFogfv
+#undef glFogi
+#define glFogi DO_NOT_USE_glFogi
+#undef glFogiv
+#define glFogiv DO_NOT_USE_glFogiv
+#undef glFrustum
+#define glFrustum DO_NOT_USE_glFrustum
+#undef glGenLists
+#define glGenLists DO_NOT_USE_glGenLists
+#undef glGetClipPlane
+#define glGetClipPlane DO_NOT_USE_glGetClipPlane
+#undef glGetLightfv
+#define glGetLightfv DO_NOT_USE_glGetLightfv
+#undef glGetLightiv
+#define glGetLightiv DO_NOT_USE_glGetLightiv
+#undef glGetMapdv
+#define glGetMapdv DO_NOT_USE_glGetMapdv
+#undef glGetMapfv
+#define glGetMapfv DO_NOT_USE_glGetMapfv
+#undef glGetMapiv
+#define glGetMapiv DO_NOT_USE_glGetMapiv
+#undef glGetMaterialfv
+#define glGetMaterialfv DO_NOT_USE_glGetMaterialfv
+#undef glGetMaterialiv
+#define glGetMaterialiv DO_NOT_USE_glGetMaterialiv
+#undef glGetPixelMapfv
+#define glGetPixelMapfv DO_NOT_USE_glGetPixelMapfv
+#undef glGetPixelMapuiv
+#define glGetPixelMapuiv DO_NOT_USE_glGetPixelMapuiv
+#undef glGetPixelMapusv
+#define glGetPixelMapusv DO_NOT_USE_glGetPixelMapusv
+#undef glGetPolygonStipple
+#define glGetPolygonStipple DO_NOT_USE_glGetPolygonStipple
+#undef glGetTexEnvfv
+#define glGetTexEnvfv DO_NOT_USE_glGetTexEnvfv
+#undef glGetTexEnviv
+#define glGetTexEnviv DO_NOT_USE_glGetTexEnviv
+#undef glGetTexGendv
+#define glGetTexGendv DO_NOT_USE_glGetTexGendv
+#undef glGetTexGenfv
+#define glGetTexGenfv DO_NOT_USE_glGetTexGenfv
+#undef glGetTexGeniv
+#define glGetTexGeniv DO_NOT_USE_glGetTexGeniv
+#undef glIndexMask
+#define glIndexMask DO_NOT_USE_glIndexMask
+#undef glIndexd
+#define glIndexd DO_NOT_USE_glIndexd
+#undef glIndexdv
+#define glIndexdv DO_NOT_USE_glIndexdv
+#undef glIndexf
+#define glIndexf DO_NOT_USE_glIndexf
+#undef glIndexfv
+#define glIndexfv DO_NOT_USE_glIndexfv
+#undef glIndexi
+#define glIndexi DO_NOT_USE_glIndexi
+#undef glIndexiv
+#define glIndexiv DO_NOT_USE_glIndexiv
+#undef glIndexs
+#define glIndexs DO_NOT_USE_glIndexs
+#undef glIndexsv
+#define glIndexsv DO_NOT_USE_glIndexsv
+#undef glInitNames
+#define glInitNames DO_NOT_USE_glInitNames
+#undef glIsList
+#define glIsList DO_NOT_USE_glIsList
+#undef glLightModelf
+#define glLightModelf DO_NOT_USE_glLightModelf
+#undef glLightModelfv
+#define glLightModelfv DO_NOT_USE_glLightModelfv
+#undef glLightModeli
+#define glLightModeli DO_NOT_USE_glLightModeli
+#undef glLightModeliv
+#define glLightModeliv DO_NOT_USE_glLightModeliv
+#undef glLightf
+#define glLightf DO_NOT_USE_glLightf
+#undef glLightfv
+#define glLightfv DO_NOT_USE_glLightfv
+#undef glLighti
+#define glLighti DO_NOT_USE_glLighti
+#undef glLightiv
+#define glLightiv DO_NOT_USE_glLightiv
+#undef glLineStipple
+#define glLineStipple DO_NOT_USE_glLineStipple
+#undef glListBase
+#define glListBase DO_NOT_USE_glListBase
+#undef glLoadIdentity
+#define glLoadIdentity DO_NOT_USE_glLoadIdentity
+#undef glLoadMatrixd
+#define glLoadMatrixd DO_NOT_USE_glLoadMatrixd
+#undef glLoadMatrixf
+#define glLoadMatrixf DO_NOT_USE_glLoadMatrixf
+#undef glLoadName
+#define glLoadName DO_NOT_USE_glLoadName
+#undef glMap1d
+#define glMap1d DO_NOT_USE_glMap1d
+#undef glMap1f
+#define glMap1f DO_NOT_USE_glMap1f
+#undef glMap2d
+#define glMap2d DO_NOT_USE_glMap2d
+#undef glMap2f
+#define glMap2f DO_NOT_USE_glMap2f
+#undef glMapGrid1d
+#define glMapGrid1d DO_NOT_USE_glMapGrid1d
+#undef glMapGrid1f
+#define glMapGrid1f DO_NOT_USE_glMapGrid1f
+#undef glMapGrid2d
+#define glMapGrid2d DO_NOT_USE_glMapGrid2d
+#undef glMapGrid2f
+#define glMapGrid2f DO_NOT_USE_glMapGrid2f
+#undef glMaterialf
+#define glMaterialf DO_NOT_USE_glMaterialf
+#undef glMaterialfv
+#define glMaterialfv DO_NOT_USE_glMaterialfv
+#undef glMateriali
+#define glMateriali DO_NOT_USE_glMateriali
+#undef glMaterialiv
+#define glMaterialiv DO_NOT_USE_glMaterialiv
+#undef glMatrixMode
+#define glMatrixMode DO_NOT_USE_glMatrixMode
+#undef glMultMatrixd
+#define glMultMatrixd DO_NOT_USE_glMultMatrixd
+#undef glMultMatrixf
+#define glMultMatrixf DO_NOT_USE_glMultMatrixf
+#undef glNewList
+#define glNewList DO_NOT_USE_glNewList
+#undef glNormal3b
+#define glNormal3b DO_NOT_USE_glNormal3b
+#undef glNormal3bv
+#define glNormal3bv DO_NOT_USE_glNormal3bv
+#undef glNormal3d
+#define glNormal3d DO_NOT_USE_glNormal3d
+#undef glNormal3dv
+#define glNormal3dv DO_NOT_USE_glNormal3dv
+#undef glNormal3f
+#define glNormal3f DO_NOT_USE_glNormal3f
+#undef glNormal3fv
+#define glNormal3fv DO_NOT_USE_glNormal3fv
+#undef glNormal3i
+#define glNormal3i DO_NOT_USE_glNormal3i
+#undef glNormal3iv
+#define glNormal3iv DO_NOT_USE_glNormal3iv
+#undef glNormal3s
+#define glNormal3s DO_NOT_USE_glNormal3s
+#undef glNormal3sv
+#define glNormal3sv DO_NOT_USE_glNormal3sv
+#undef glOrtho
+#define glOrtho DO_NOT_USE_glOrtho
+#undef glPassThrough
+#define glPassThrough DO_NOT_USE_glPassThrough
+#undef glPixelMapfv
+#define glPixelMapfv DO_NOT_USE_glPixelMapfv
+#undef glPixelMapuiv
+#define glPixelMapuiv DO_NOT_USE_glPixelMapuiv
+#undef glPixelMapusv
+#define glPixelMapusv DO_NOT_USE_glPixelMapusv
+#undef glPixelTransferf
+#define glPixelTransferf DO_NOT_USE_glPixelTransferf
+#undef glPixelTransferi
+#define glPixelTransferi DO_NOT_USE_glPixelTransferi
+#undef glPixelZoom
+#define glPixelZoom DO_NOT_USE_glPixelZoom
+#undef glPolygonStipple
+#define glPolygonStipple DO_NOT_USE_glPolygonStipple
+#undef glPopAttrib
+#define glPopAttrib DO_NOT_USE_glPopAttrib
+#undef glPopMatrix
+#define glPopMatrix DO_NOT_USE_glPopMatrix
+#undef glPopName
+#define glPopName DO_NOT_USE_glPopName
+#undef glPushAttrib
+#define glPushAttrib DO_NOT_USE_glPushAttrib
+#undef glPushMatrix
+#define glPushMatrix DO_NOT_USE_glPushMatrix
+#undef glPushName
+#define glPushName DO_NOT_USE_glPushName
+#undef glRasterPos2d
+#define glRasterPos2d DO_NOT_USE_glRasterPos2d
+#undef glRasterPos2dv
+#define glRasterPos2dv DO_NOT_USE_glRasterPos2dv
+#undef glRasterPos2f
+#define glRasterPos2f DO_NOT_USE_glRasterPos2f
+#undef glRasterPos2fv
+#define glRasterPos2fv DO_NOT_USE_glRasterPos2fv
+#undef glRasterPos2i
+#define glRasterPos2i DO_NOT_USE_glRasterPos2i
+#undef glRasterPos2iv
+#define glRasterPos2iv DO_NOT_USE_glRasterPos2iv
+#undef glRasterPos2s
+#define glRasterPos2s DO_NOT_USE_glRasterPos2s
+#undef glRasterPos2sv
+#define glRasterPos2sv DO_NOT_USE_glRasterPos2sv
+#undef glRasterPos3d
+#define glRasterPos3d DO_NOT_USE_glRasterPos3d
+#undef glRasterPos3dv
+#define glRasterPos3dv DO_NOT_USE_glRasterPos3dv
+#undef glRasterPos3f
+#define glRasterPos3f DO_NOT_USE_glRasterPos3f
+#undef glRasterPos3fv
+#define glRasterPos3fv DO_NOT_USE_glRasterPos3fv
+#undef glRasterPos3i
+#define glRasterPos3i DO_NOT_USE_glRasterPos3i
+#undef glRasterPos3iv
+#define glRasterPos3iv DO_NOT_USE_glRasterPos3iv
+#undef glRasterPos3s
+#define glRasterPos3s DO_NOT_USE_glRasterPos3s
+#undef glRasterPos3sv
+#define glRasterPos3sv DO_NOT_USE_glRasterPos3sv
+#undef glRasterPos4d
+#define glRasterPos4d DO_NOT_USE_glRasterPos4d
+#undef glRasterPos4dv
+#define glRasterPos4dv DO_NOT_USE_glRasterPos4dv
+#undef glRasterPos4f
+#define glRasterPos4f DO_NOT_USE_glRasterPos4f
+#undef glRasterPos4fv
+#define glRasterPos4fv DO_NOT_USE_glRasterPos4fv
+#undef glRasterPos4i
+#define glRasterPos4i DO_NOT_USE_glRasterPos4i
+#undef glRasterPos4iv
+#define glRasterPos4iv DO_NOT_USE_glRasterPos4iv
+#undef glRasterPos4s
+#define glRasterPos4s DO_NOT_USE_glRasterPos4s
+#undef glRasterPos4sv
+#define glRasterPos4sv DO_NOT_USE_glRasterPos4sv
+#undef glRectd
+#define glRectd DO_NOT_USE_glRectd
+#undef glRectdv
+#define glRectdv DO_NOT_USE_glRectdv
+#undef glRectf
+#define glRectf DO_NOT_USE_glRectf
+#undef glRectfv
+#define glRectfv DO_NOT_USE_glRectfv
+#undef glRecti
+#define glRecti DO_NOT_USE_glRecti
+#undef glRectiv
+#define glRectiv DO_NOT_USE_glRectiv
+#undef glRects
+#define glRects DO_NOT_USE_glRects
+#undef glRectsv
+#define glRectsv DO_NOT_USE_glRectsv
+#undef glRenderMode
+#define glRenderMode DO_NOT_USE_glRenderMode
+#undef glRotated
+#define glRotated DO_NOT_USE_glRotated
+#undef glRotatef
+#define glRotatef DO_NOT_USE_glRotatef
+#undef glScaled
+#define glScaled DO_NOT_USE_glScaled
+#undef glScalef
+#define glScalef DO_NOT_USE_glScalef
+#undef glSelectBuffer
+#define glSelectBuffer DO_NOT_USE_glSelectBuffer
+#undef glShadeModel
+#define glShadeModel DO_NOT_USE_glShadeModel
+#undef glTexCoord1d
+#define glTexCoord1d DO_NOT_USE_glTexCoord1d
+#undef glTexCoord1dv
+#define glTexCoord1dv DO_NOT_USE_glTexCoord1dv
+#undef glTexCoord1f
+#define glTexCoord1f DO_NOT_USE_glTexCoord1f
+#undef glTexCoord1fv
+#define glTexCoord1fv DO_NOT_USE_glTexCoord1fv
+#undef glTexCoord1i
+#define glTexCoord1i DO_NOT_USE_glTexCoord1i
+#undef glTexCoord1iv
+#define glTexCoord1iv DO_NOT_USE_glTexCoord1iv
+#undef glTexCoord1s
+#define glTexCoord1s DO_NOT_USE_glTexCoord1s
+#undef glTexCoord1sv
+#define glTexCoord1sv DO_NOT_USE_glTexCoord1sv
+#undef glTexCoord2d
+#define glTexCoord2d DO_NOT_USE_glTexCoord2d
+#undef glTexCoord2dv
+#define glTexCoord2dv DO_NOT_USE_glTexCoord2dv
+#undef glTexCoord2f
+#define glTexCoord2f DO_NOT_USE_glTexCoord2f
+#undef glTexCoord2fv
+#define glTexCoord2fv DO_NOT_USE_glTexCoord2fv
+#undef glTexCoord2i
+#define glTexCoord2i DO_NOT_USE_glTexCoord2i
+#undef glTexCoord2iv
+#define glTexCoord2iv DO_NOT_USE_glTexCoord2iv
+#undef glTexCoord2s
+#define glTexCoord2s DO_NOT_USE_glTexCoord2s
+#undef glTexCoord2sv
+#define glTexCoord2sv DO_NOT_USE_glTexCoord2sv
+#undef glTexCoord3d
+#define glTexCoord3d DO_NOT_USE_glTexCoord3d
+#undef glTexCoord3dv
+#define glTexCoord3dv DO_NOT_USE_glTexCoord3dv
+#undef glTexCoord3f
+#define glTexCoord3f DO_NOT_USE_glTexCoord3f
+#undef glTexCoord3fv
+#define glTexCoord3fv DO_NOT_USE_glTexCoord3fv
+#undef glTexCoord3i
+#define glTexCoord3i DO_NOT_USE_glTexCoord3i
+#undef glTexCoord3iv
+#define glTexCoord3iv DO_NOT_USE_glTexCoord3iv
+#undef glTexCoord3s
+#define glTexCoord3s DO_NOT_USE_glTexCoord3s
+#undef glTexCoord3sv
+#define glTexCoord3sv DO_NOT_USE_glTexCoord3sv
+#undef glTexCoord4d
+#define glTexCoord4d DO_NOT_USE_glTexCoord4d
+#undef glTexCoord4dv
+#define glTexCoord4dv DO_NOT_USE_glTexCoord4dv
+#undef glTexCoord4f
+#define glTexCoord4f DO_NOT_USE_glTexCoord4f
+#undef glTexCoord4fv
+#define glTexCoord4fv DO_NOT_USE_glTexCoord4fv
+#undef glTexCoord4i
+#define glTexCoord4i DO_NOT_USE_glTexCoord4i
+#undef glTexCoord4iv
+#define glTexCoord4iv DO_NOT_USE_glTexCoord4iv
+#undef glTexCoord4s
+#define glTexCoord4s DO_NOT_USE_glTexCoord4s
+#undef glTexCoord4sv
+#define glTexCoord4sv DO_NOT_USE_glTexCoord4sv
+#undef glTexEnvf
+#define glTexEnvf DO_NOT_USE_glTexEnvf
+#undef glTexEnvfv
+#define glTexEnvfv DO_NOT_USE_glTexEnvfv
+#undef glTexEnvi
+#define glTexEnvi DO_NOT_USE_glTexEnvi
+#undef glTexEnviv
+#define glTexEnviv DO_NOT_USE_glTexEnviv
+#undef glTexGend
+#define glTexGend DO_NOT_USE_glTexGend
+#undef glTexGendv
+#define glTexGendv DO_NOT_USE_glTexGendv
+#undef glTexGenf
+#define glTexGenf DO_NOT_USE_glTexGenf
+#undef glTexGenfv
+#define glTexGenfv DO_NOT_USE_glTexGenfv
+#undef glTexGeni
+#define glTexGeni DO_NOT_USE_glTexGeni
+#undef glTexGeniv
+#define glTexGeniv DO_NOT_USE_glTexGeniv
+#undef glTranslated
+#define glTranslated DO_NOT_USE_glTranslated
+#undef glTranslatef
+#define glTranslatef DO_NOT_USE_glTranslatef
+#undef glVertex2d
+#define glVertex2d DO_NOT_USE_glVertex2d
+#undef glVertex2dv
+#define glVertex2dv DO_NOT_USE_glVertex2dv
+#undef glVertex2f
+#define glVertex2f DO_NOT_USE_glVertex2f
+#undef glVertex2fv
+#define glVertex2fv DO_NOT_USE_glVertex2fv
+#undef glVertex2i
+#define glVertex2i DO_NOT_USE_glVertex2i
+#undef glVertex2iv
+#define glVertex2iv DO_NOT_USE_glVertex2iv
+#undef glVertex2s
+#define glVertex2s DO_NOT_USE_glVertex2s
+#undef glVertex2sv
+#define glVertex2sv DO_NOT_USE_glVertex2sv
+#undef glVertex3d
+#define glVertex3d DO_NOT_USE_glVertex3d
+#undef glVertex3dv
+#define glVertex3dv DO_NOT_USE_glVertex3dv
+#undef glVertex3f
+#define glVertex3f DO_NOT_USE_glVertex3f
+#undef glVertex3fv
+#define glVertex3fv DO_NOT_USE_glVertex3fv
+#undef glVertex3i
+#define glVertex3i DO_NOT_USE_glVertex3i
+#undef glVertex3iv
+#define glVertex3iv DO_NOT_USE_glVertex3iv
+#undef glVertex3s
+#define glVertex3s DO_NOT_USE_glVertex3s
+#undef glVertex3sv
+#define glVertex3sv DO_NOT_USE_glVertex3sv
+#undef glVertex4d
+#define glVertex4d DO_NOT_USE_glVertex4d
+#undef glVertex4dv
+#define glVertex4dv DO_NOT_USE_glVertex4dv
+#undef glVertex4f
+#define glVertex4f DO_NOT_USE_glVertex4f
+#undef glVertex4fv
+#define glVertex4fv DO_NOT_USE_glVertex4fv
+#undef glVertex4i
+#define glVertex4i DO_NOT_USE_glVertex4i
+#undef glVertex4iv
+#define glVertex4iv DO_NOT_USE_glVertex4iv
+#undef glVertex4s
+#define glVertex4s DO_NOT_USE_glVertex4s
+#undef glVertex4sv
+#define glVertex4sv DO_NOT_USE_glVertex4sv
+
+// GL Version 1.1
+#undef glAreTexturesResident
+#define glAreTexturesResident DO_NOT_USE_glAreTexturesResident
+#undef glArrayElement
+#define glArrayElement DO_NOT_USE_glArrayElement
+#undef glColorPointer
+#define glColorPointer DO_NOT_USE_glColorPointer
+#undef glDisableClientState
+#define glDisableClientState DO_NOT_USE_glDisableClientState
+#undef glEdgeFlagPointer
+#define glEdgeFlagPointer DO_NOT_USE_glEdgeFlagPointer
+#undef glEnableClientState
+#define glEnableClientState DO_NOT_USE_glEnableClientState
+#undef glIndexPointer
+#define glIndexPointer DO_NOT_USE_glIndexPointer
+#undef glIndexub
+#define glIndexub DO_NOT_USE_glIndexub
+#undef glIndexubv
+#define glIndexubv DO_NOT_USE_glIndexubv
+#undef glInterleavedArrays
+#define glInterleavedArrays DO_NOT_USE_glInterleavedArrays
+#undef glNormalPointer
+#define glNormalPointer DO_NOT_USE_glNormalPointer
+#undef glPopClientAttrib
+#define glPopClientAttrib DO_NOT_USE_glPopClientAttrib
+#undef glPrioritizeTextures
+#define glPrioritizeTextures DO_NOT_USE_glPrioritizeTextures
+#undef glPushClientAttrib
+#define glPushClientAttrib DO_NOT_USE_glPushClientAttrib
+#undef glTexCoordPointer
+#define glTexCoordPointer DO_NOT_USE_glTexCoordPointer
+#undef glVertexPointer
+#define glVertexPointer DO_NOT_USE_glVertexPointer
+
+// GL Version1.2
+#undef glColorSubTable
+#define glColorSubTable DO_NOT_USE_glColorSubTable
+#undef glColorTable
+#define glColorTable DO_NOT_USE_glColorTable
+#undef glColorTableParameterfv
+#define glColorTableParameterfv DO_NOT_USE_glColorTableParameterfv
+#undef glColorTableParameteriv
+#define glColorTableParameteriv DO_NOT_USE_glColorTableParameteriv
+#undef glConvolutionFilter1D
+#define glConvolutionFilter1D DO_NOT_USE_glConvolutionFilter1D
+#undef glConvolutionFilter2D
+#define glConvolutionFilter2D DO_NOT_USE_glConvolutionFilter2D
+#undef glConvolutionParameterf
+#define glConvolutionParameterf DO_NOT_USE_glConvolutionParameterf
+#undef glConvolutionParameterfv
+#define glConvolutionParameterfv DO_NOT_USE_glConvolutionParameterfv
+#undef glConvolutionParameteri
+#define glConvolutionParameteri DO_NOT_USE_glConvolutionParameteri
+#undef glConvolutionParameteriv
+#define glConvolutionParameteriv DO_NOT_USE_glConvolutionParameteriv
+#undef glCopyColorSubTable
+#define glCopyColorSubTable DO_NOT_USE_glCopyColorSubTable
+#undef glCopyColorTable
+#define glCopyColorTable DO_NOT_USE_glCopyColorTable
+#undef glCopyConvolutionFilter1D
+#define glCopyConvolutionFilter1D DO_NOT_USE_glCopyConvolutionFilter1D
+#undef glCopyConvolutionFilter2D
+#define glCopyConvolutionFilter2D DO_NOT_USE_glCopyConvolutionFilter2D
+#undef glGetColorTable
+#define glGetColorTable DO_NOT_USE_glGetColorTable
+#undef glGetColorTableParameterfv
+#define glGetColorTableParameterfv DO_NOT_USE_glGetColorTableParameterfv
+#undef glGetColorTableParameteriv
+#define glGetColorTableParameteriv DO_NOT_USE_glGetColorTableParameteriv
+#undef glGetConvolutionFilter
+#define glGetConvolutionFilter DO_NOT_USE_glGetConvolutionFilter
+#undef glGetConvolutionParameterfv
+#define glGetConvolutionParameterfv DO_NOT_USE_glGetConvolutionParameterfv
+#undef glGetConvolutionParameteriv
+#define glGetConvolutionParameteriv DO_NOT_USE_glGetConvolutionParameteriv
+#undef glGetHistogram
+#define glGetHistogram DO_NOT_USE_glGetHistogram
+#undef glGetHistogramParameterfv
+#define glGetHistogramParameterfv DO_NOT_USE_glGetHistogramParameterfv
+#undef glGetHistogramParameteriv
+#define glGetHistogramParameteriv DO_NOT_USE_glGetHistogramParameteriv
+#undef glGetMinmax
+#define glGetMinmax DO_NOT_USE_glGetMinmax
+#undef glGetMinmaxParameterfv
+#define glGetMinmaxParameterfv DO_NOT_USE_glGetMinmaxParameterfv
+#undef glGetMinmaxParameteriv
+#define glGetMinmaxParameteriv DO_NOT_USE_glGetMinmaxParameteriv
+#undef glGetSeparableFilter
+#define glGetSeparableFilter DO_NOT_USE_glGetSeparableFilter
+#undef glHistogram
+#define glHistogram DO_NOT_USE_glHistogram
+#undef glMinmax
+#define glMinmax DO_NOT_USE_glMinmax
+#undef glResetHistogram
+#define glResetHistogram DO_NOT_USE_glResetHistogram
+#undef glResetMinmax
+#define glResetMinmax DO_NOT_USE_glResetMinmax
+#undef glSeparableFilter2D
+#define glSeparableFilter2D DO_NOT_USE_glSeparableFilter2D
+
+// GL Version1.3
+#undef glClientActiveTexture
+#define glClientActiveTexture DO_NOT_USE_glClientActiveTexture
+#undef glLoadTransposeMatrixd
+#define glLoadTransposeMatrixd DO_NOT_USE_glLoadTransposeMatrixd
+#undef glLoadTransposeMatrixf
+#define glLoadTransposeMatrixf DO_NOT_USE_glLoadTransposeMatrixf
+#undef glMultTransposeMatrixd
+#define glMultTransposeMatrixd DO_NOT_USE_glMultTransposeMatrixd
+#undef glMultTransposeMatrixf
+#define glMultTransposeMatrixf DO_NOT_USE_glMultTransposeMatrixf
+#undef glMultiTexCoord1d
+#define glMultiTexCoord1d DO_NOT_USE_glMultiTexCoord1d
+#undef glMultiTexCoord1dv
+#define glMultiTexCoord1dv DO_NOT_USE_glMultiTexCoord1dv
+#undef glMultiTexCoord1f
+#define glMultiTexCoord1f DO_NOT_USE_glMultiTexCoord1f
+#undef glMultiTexCoord1fv
+#define glMultiTexCoord1fv DO_NOT_USE_glMultiTexCoord1fv
+#undef glMultiTexCoord1i
+#define glMultiTexCoord1i DO_NOT_USE_glMultiTexCoord1i
+#undef glMultiTexCoord1iv
+#define glMultiTexCoord1iv DO_NOT_USE_glMultiTexCoord1iv
+#undef glMultiTexCoord1s
+#define glMultiTexCoord1s DO_NOT_USE_glMultiTexCoord1s
+#undef glMultiTexCoord1sv
+#define glMultiTexCoord1sv DO_NOT_USE_glMultiTexCoord1sv
+#undef glMultiTexCoord2d
+#define glMultiTexCoord2d DO_NOT_USE_glMultiTexCoord2d
+#undef glMultiTexCoord2dv
+#define glMultiTexCoord2dv DO_NOT_USE_glMultiTexCoord2dv
+#undef glMultiTexCoord2f
+#define glMultiTexCoord2f DO_NOT_USE_glMultiTexCoord2f
+#undef glMultiTexCoord2fv
+#define glMultiTexCoord2fv DO_NOT_USE_glMultiTexCoord2fv
+#undef glMultiTexCoord2i
+#define glMultiTexCoord2i DO_NOT_USE_glMultiTexCoord2i
+#undef glMultiTexCoord2iv
+#define glMultiTexCoord2iv DO_NOT_USE_glMultiTexCoord2iv
+#undef glMultiTexCoord2s
+#define glMultiTexCoord2s DO_NOT_USE_glMultiTexCoord2s
+#undef glMultiTexCoord2sv
+#define glMultiTexCoord2sv DO_NOT_USE_glMultiTexCoord2sv
+#undef glMultiTexCoord3d
+#define glMultiTexCoord3d DO_NOT_USE_glMultiTexCoord3d
+#undef glMultiTexCoord3dv
+#define glMultiTexCoord3dv DO_NOT_USE_glMultiTexCoord3dv
+#undef glMultiTexCoord3f
+#define glMultiTexCoord3f DO_NOT_USE_glMultiTexCoord3f
+#undef glMultiTexCoord3fv
+#define glMultiTexCoord3fv DO_NOT_USE_glMultiTexCoord3fv
+#undef glMultiTexCoord3i
+#define glMultiTexCoord3i DO_NOT_USE_glMultiTexCoord3i
+#undef glMultiTexCoord3iv
+#define glMultiTexCoord3iv DO_NOT_USE_glMultiTexCoord3iv
+#undef glMultiTexCoord3s
+#define glMultiTexCoord3s DO_NOT_USE_glMultiTexCoord3s
+#undef glMultiTexCoord3sv
+#define glMultiTexCoord3sv DO_NOT_USE_glMultiTexCoord3sv
+#undef glMultiTexCoord4d
+#define glMultiTexCoord4d DO_NOT_USE_glMultiTexCoord4d
+#undef glMultiTexCoord4dv
+#define glMultiTexCoord4dv DO_NOT_USE_glMultiTexCoord4dv
+#undef glMultiTexCoord4f
+#define glMultiTexCoord4f DO_NOT_USE_glMultiTexCoord4f
+#undef glMultiTexCoord4fv
+#define glMultiTexCoord4fv DO_NOT_USE_glMultiTexCoord4fv
+#undef glMultiTexCoord4i
+#define glMultiTexCoord4i DO_NOT_USE_glMultiTexCoord4i
+#undef glMultiTexCoord4iv
+#define glMultiTexCoord4iv DO_NOT_USE_glMultiTexCoord4iv
+#undef glMultiTexCoord4s
+#define glMultiTexCoord4s DO_NOT_USE_glMultiTexCoord4s
+#undef glMultiTexCoord4sv
+#define glMultiTexCoord4sv DO_NOT_USE_glMultiTexCoord4sv
+
+// GL Version 1.4
+#undef glFogCoordPointer
+#define glFogCoordPointer DO_NOT_USE_glFogCoordPointer
+#undef glFogCoordd
+#define glFogCoordd DO_NOT_USE_glFogCoordd
+#undef glFogCoorddv
+#define glFogCoorddv DO_NOT_USE_glFogCoorddv
+#undef glFogCoordf
+#define glFogCoordf DO_NOT_USE_glFogCoordf
+#undef glFogCoordfv
+#define glFogCoordfv DO_NOT_USE_glFogCoordfv
+#undef glSecondaryColor3b
+#define glSecondaryColor3b DO_NOT_USE_glSecondaryColor3b
+#undef glSecondaryColor3bv
+#define glSecondaryColor3bv DO_NOT_USE_glSecondaryColor3bv
+#undef glSecondaryColor3d
+#define glSecondaryColor3d DO_NOT_USE_glSecondaryColor3d
+#undef glSecondaryColor3dv
+#define glSecondaryColor3dv DO_NOT_USE_glSecondaryColor3dv
+#undef glSecondaryColor3f
+#define glSecondaryColor3f DO_NOT_USE_glSecondaryColor3f
+#undef glSecondaryColor3fv
+#define glSecondaryColor3fv DO_NOT_USE_glSecondaryColor3fv
+#undef glSecondaryColor3i
+#define glSecondaryColor3i DO_NOT_USE_glSecondaryColor3i
+#undef glSecondaryColor3iv
+#define glSecondaryColor3iv DO_NOT_USE_glSecondaryColor3iv
+#undef glSecondaryColor3s
+#define glSecondaryColor3s DO_NOT_USE_glSecondaryColor3s
+#undef glSecondaryColor3sv
+#define glSecondaryColor3sv DO_NOT_USE_glSecondaryColor3sv
+#undef glSecondaryColor3ub
+#define glSecondaryColor3ub DO_NOT_USE_glSecondaryColor3ub
+#undef glSecondaryColor3ubv
+#define glSecondaryColor3ubv DO_NOT_USE_glSecondaryColor3ubv
+#undef glSecondaryColor3ui
+#define glSecondaryColor3ui DO_NOT_USE_glSecondaryColor3ui
+#undef glSecondaryColor3uiv
+#define glSecondaryColor3uiv DO_NOT_USE_glSecondaryColor3uiv
+#undef glSecondaryColor3us
+#define glSecondaryColor3us DO_NOT_USE_glSecondaryColor3us
+#undef glSecondaryColor3usv
+#define glSecondaryColor3usv DO_NOT_USE_glSecondaryColor3usv
+#undef glSecondaryColorPointer
+#define glSecondaryColorPointer DO_NOT_USE_glSecondaryColorPointer
+#undef glWindowPos2d
+#define glWindowPos2d DO_NOT_USE_glWindowPos2d
+#undef glWindowPos2dv
+#define glWindowPos2dv DO_NOT_USE_glWindowPos2dv
+#undef glWindowPos2f
+#define glWindowPos2f DO_NOT_USE_glWindowPos2f
+#undef glWindowPos2fv
+#define glWindowPos2fv DO_NOT_USE_glWindowPos2fv
+#undef glWindowPos2i
+#define glWindowPos2i DO_NOT_USE_glWindowPos2i
+#undef glWindowPos2iv
+#define glWindowPos2iv DO_NOT_USE_glWindowPos2iv
+#undef glWindowPos2s
+#define glWindowPos2s DO_NOT_USE_glWindowPos2s
+#undef glWindowPos2sv
+#define glWindowPos2sv DO_NOT_USE_glWindowPos2sv
+#undef glWindowPos3d
+#define glWindowPos3d DO_NOT_USE_glWindowPos3d
+#undef glWindowPos3dv
+#define glWindowPos3dv DO_NOT_USE_glWindowPos3dv
+#undef glWindowPos3f
+#define glWindowPos3f DO_NOT_USE_glWindowPos3f
+#undef glWindowPos3fv
+#define glWindowPos3fv DO_NOT_USE_glWindowPos3fv
+#undef glWindowPos3i
+#define glWindowPos3i DO_NOT_USE_glWindowPos3i
+#undef glWindowPos3iv
+#define glWindowPos3iv DO_NOT_USE_glWindowPos3iv
+#undef glWindowPos3s
+#define glWindowPos3s DO_NOT_USE_glWindowPos3s
+#undef glWindowPos3sv
+#define glWindowPos3sv DO_NOT_USE_glWindowPos3sv
+
+// Old Token Names 1.2
+#undef GL_POINT_SIZE_RANGE
+#define GL_POINT_SIZE_RANGE DO_NOT_USE_GL_POINT_SIZE_RANGE
+#undef GL_POINT_SIZE_GRANULARITY
+#define GL_POINT_SIZE_GRANULARITY DO_NOT_USE_GL_POINT_SIZE_GRANULARITY
+
+// Old Token Names 1.5
+#undef GL_CURRENT_FOG_COORDINATE
+#define GL_CURRENT_FOG_COORDINATE DO_NOT_USE_GL_CURRENT_FOG_COORDINATE
+#undef GL_FOG_COORDINATE
+#define GL_FOG_COORDINATE DO_NOT_USE_GL_FOG_COORDINATE
+#undef GL_FOG_COORDINATE_ARRAY
+#define GL_FOG_COORDINATE_ARRAY DO_NOT_USE_GL_FOG_COORDINATE_ARRAY
+#undef GL_FOG_COORDINATE_ARRAY_BUFFER_BINDING
+#define GL_FOG_COORDINATE_ARRAY_BUFFER_BINDING DO_NOT_USE_GL_FOG_COORDINATE_ARRAY_BUFFER_BINDING
+#undef GL_FOG_COORDINATE_ARRAY_POINTER
+#define GL_FOG_COORDINATE_ARRAY_POINTER DO_NOT_USE_GL_FOG_COORDINATE_ARRAY_POINTER
+#undef GL_FOG_COORDINATE_ARRAY_STRIDE
+#define GL_FOG_COORDINATE_ARRAY_STRIDE DO_NOT_USE_GL_FOG_COORDINATE_ARRAY_STRIDE
+#undef GL_FOG_COORDINATE_ARRAY_TYPE
+#define GL_FOG_COORDINATE_ARRAY_TYPE DO_NOT_USE_GL_FOG_COORDINATE_ARRAY_TYPE
+#undef GL_FOG_COORDINATE_SOURCE
+#define GL_FOG_COORDINATE_SOURCE DO_NOT_USE_GL_FOG_COORDINATE_SOURCE
+#undef GL_SOURCE0_ALPHA
+#define GL_SOURCE0_ALPHA DO_NOT_USE_GL_SOURCE0_ALPHA
+#undef GL_SOURCE0_RGB
+#define GL_SOURCE0_RGB DO_NOT_USE_GL_SOURCE0_RGB
+#undef GL_SOURCE1_ALPHA
+#define GL_SOURCE1_ALPHA DO_NOT_USE_GL_SOURCE1_ALPHA
+#undef GL_SOURCE1_RGB
+#define GL_SOURCE1_RGB DO_NOT_USE_GL_SOURCE1_RGB
+#undef GL_SOURCE2_ALPHA
+#define GL_SOURCE2_ALPHA DO_NOT_USE_GL_SOURCE2_ALPHA
+#undef GL_SOURCE2_RGB
+#define GL_SOURCE2_RGB DO_NOT_USE_GL_SOURCE2_RGB
+
+// Old Token Names 3.0
+#undef GL_CLIP_PLANE0
+#define GL_CLIP_PLANE0 USE_GL_CLIP_DISTANCE0
+#undef GL_CLIP_PLANE1
+#define GL_CLIP_PLANE1 USE_GL_CLIP_DISTANCE1
+#undef GL_CLIP_PLANE2
+#define GL_CLIP_PLANE2 USE_GL_CLIP_DISTANCE2
+#undef GL_CLIP_PLANE3
+#define GL_CLIP_PLANE3 USE_GL_CLIP_DISTANCE3
+#undef GL_CLIP_PLANE4
+#define GL_CLIP_PLANE4 USE_GL_CLIP_DISTANCE4
+#undef GL_CLIP_PLANE5
+#define GL_CLIP_PLANE5 USE_GL_CLIP_DISTANCE5
+#undef GL_COMPARE_R_TO_TEXTURE
+#define GL_COMPARE_R_TO_TEXTURE USE_GL_COMPARE_REF_TO_TEXTURE
+#undef GL_MAX_CLIP_PLANES
+#define GL_MAX_CLIP_PLANES USE_GL_MAX_CLIP_DISTANCES
+#undef GL_MAX_VARYING_FLOATS
+#define GL_MAX_VARYING_FLOATS USE__MAX_VARYING_COMPONENTS
+
+// Old Token Names 3.2
+#undef GL_VERTEX_PROGRAM_POINT_SIZE
+#define GL_VERTEX_PROGRAM_POINT_SIZE USE_GL_PROGRAM_POINT_SIZE
+
+// Old Token Names 4.1
+#undef GL_CURRENT_PROGRAM
+#define GL_CURRENT_PROGRAM DO_NOT_USE_GL_CURRENT_PROGRAM
+
+#endif /* __GL_DEPRECATED_H__ */
diff --git a/intern/glew-mx/intern/glew-mx.c b/intern/glew-mx/intern/glew-mx.c
new file mode 100644
index 00000000000..78920670f68
--- /dev/null
+++ b/intern/glew-mx/intern/glew-mx.c
@@ -0,0 +1,151 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2014 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Jason Wilkins
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file glew-mx.c
+ * \ingroup glew-mx
+ */
+
+#include "glew-mx.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+
+static int ignore_version = 0;
+
+#define CASE_CODE_RETURN_STR(code) case code: return #code;
+
+static const char *get_glew_error_enum_string(GLenum error)
+{
+ switch (error) {
+ CASE_CODE_RETURN_STR(GLEW_OK) /* also GLEW_NO_ERROR */
+ CASE_CODE_RETURN_STR(GLEW_ERROR_NO_GL_VERSION)
+ CASE_CODE_RETURN_STR(GLEW_ERROR_GL_VERSION_10_ONLY)
+ CASE_CODE_RETURN_STR(GLEW_ERROR_GLX_VERSION_11_ONLY)
+#ifdef WITH_GLEW_ES
+ CASE_CODE_RETURN_STR(GLEW_ERROR_NOT_GLES_VERSION)
+ CASE_CODE_RETURN_STR(GLEW_ERROR_GLES_VERSION)
+ CASE_CODE_RETURN_STR(GLEW_ERROR_NO_EGL_VERSION)
+ CASE_CODE_RETURN_STR(GLEW_ERROR_EGL_VERSION_10_ONLY)
+#endif
+ default:
+ return NULL;
+ }
+}
+
+
+GLenum glew_chk(GLenum error, const char *file, int line, const char *text)
+{
+ if (error != GLEW_OK) {
+ const char *code = get_glew_error_enum_string(error);
+ const char *msg = (const char *)glewGetErrorString(error);
+
+ if (error == GLEW_ERROR_NO_GL_VERSION && ignore_version)
+ return GLEW_OK;
+
+#ifndef NDEBUG
+ fprintf(stderr,
+ "%s(%d):[%s] -> GLEW Error (0x%04X): %s: %s\n",
+ file, line, text, error,
+ code ? code : "<no symbol>",
+ msg ? msg : "<no message>");
+#else
+ (void) file;
+ (void) line;
+ (void) text;
+ fprintf(stderr,
+ "GLEW Error (0x%04X): %s: %s\n",
+ error,
+ code ? code : "<no symbol>",
+ msg ? msg : "<no message>");
+#endif
+ }
+
+ return error;
+}
+
+
+#ifdef WITH_GLEW_MX
+MXContext *_mx_context = NULL;
+#endif
+
+
+MXContext *mxCreateContext(void)
+{
+#ifdef WITH_GLEW_MX
+ MXContext* new_ctx = calloc(1, sizeof(MXContext));
+
+ if (new_ctx != NULL) {
+ MXContext* cur_ctx = _mx_context;
+ _mx_context = new_ctx;
+ GLEW_CHK(glewInit());
+ _mx_context = cur_ctx;
+ }
+
+ return new_ctx;
+#else
+ GLEW_CHK(glewInit());
+ return NULL;
+#endif
+}
+
+
+MXContext *mxGetCurrentContext(void)
+{
+#ifdef WITH_GLEW_MX
+ return _mx_context;
+#else
+ return NULL;
+#endif
+}
+
+
+void mxMakeCurrentContext(MXContext *ctx)
+{
+#ifdef WITH_GLEW_MX
+ _mx_context = ctx;
+#else
+ (void)ctx;
+#endif
+}
+
+
+void mxDestroyContext(MXContext *ctx)
+{
+#ifdef WITH_GLEW_MX
+ if (_mx_context == ctx)
+ _mx_context = NULL;
+
+ free(ctx);
+#else
+ (void)ctx;
+#endif
+}
+
+void mxIgnoreNoVersion(int ignore)
+{
+ ignore_version = ignore;
+}
diff --git a/intern/glew-mx/intern/symbol-binding.h b/intern/glew-mx/intern/symbol-binding.h
new file mode 100644
index 00000000000..87cba20c41a
--- /dev/null
+++ b/intern/glew-mx/intern/symbol-binding.h
@@ -0,0 +1,305 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2014 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Jason Wilkins
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file intern/symbol-binding.h
+ * \ingroup glew-mx
+ *
+ * This file is for any simple stuff that is missing from GLEW when
+ * compiled with either the GLEW_ES_ONLY or the GLEW_NO_ES flag.
+ *
+ * Should be limited to symbolic constants.
+ *
+ * This file is NOT for checking DEPRECATED OpenGL symbolic constants.
+ */
+
+#ifndef __SYMBOL_BINDING_H__
+#define __SYMBOL_BINDING_H__
+
+#ifndef __GLEW_MX_H__
+#error This file is meant to be included from glew-mx.h
+#endif
+
+
+#ifdef GLEW_ES_ONLY
+
+/* ES does not support the GLdouble type. */
+#ifndef GLdouble
+#define GLdouble double
+#endif
+
+/*
+ * Need stubs for these version checks if compiling with only ES support.
+ * Rely on compiler to eliminate unreachable code when version checks become constants.
+ */
+
+#ifndef GLEW_VERSION_1_1
+#define GLEW_VERSION_1_1 0
+#endif
+
+#ifndef GLEW_VERSION_1_2
+#define GLEW_VERSION_1_2 0
+#endif
+
+#ifndef GLEW_VERSION_1_3
+#define GLEW_VERSION_1_3 0
+#endif
+
+#ifndef GLEW_VERSION_1_4
+#define GLEW_VERSION_1_4 0
+#endif
+
+#ifndef GLEW_VERSION_1_5
+#define GLEW_VERSION_1_5 0
+#endif
+
+#ifndef GLEW_VERSION_2_0
+#define GLEW_VERSION_2_0 0
+#endif
+
+#ifndef GLEW_VERSION_3_0
+#define GLEW_VERSION_3_0 0
+#endif
+
+#ifndef GLEW_ARB_shader_objects
+#define GLEW_ARB_shader_objects 0
+#endif
+
+#ifndef GLEW_ARB_vertex_shader
+#define GLEW_ARB_vertex_shader 0
+#endif
+
+#ifndef GLEW_ARB_vertex_program
+#define GLEW_ARB_vertex_program 0
+#endif
+
+#ifndef GLEW_ARB_fragment_program
+#define GLEW_ARB_fragment_program 0
+#endif
+
+#ifndef GLEW_ARB_vertex_buffer_object
+#define GLEW_ARB_vertex_buffer_object 0
+#endif
+
+#ifndef GLEW_ARB_framebuffer_object
+#define GLEW_ARB_framebuffer_object 0
+#endif
+
+#ifndef GLEW_ARB_multitexture
+#define GLEW_ARB_multitexture 0
+#endif
+
+#ifndef GLEW_EXT_framebuffer_object
+#define GLEW_EXT_framebuffer_object 0
+#endif
+
+#ifndef GLEW_ARB_depth_texture
+#define GLEW_ARB_depth_texture 0
+#endif
+
+#ifndef GLEW_ARB_shadow
+#define GLEW_ARB_shadow 0
+#endif
+
+#ifndef GLEW_ARB_texture_float
+#define GLEW_ARB_texture_float 0
+#endif
+
+#ifndef GLEW_ARB_texture_non_power_of_two
+#define GLEW_ARB_texture_non_power_of_two 0
+#endif
+
+#ifndef GLEW_ARB_texture3D
+#define GLEW_ARB_texture3D 0
+#endif
+
+#ifndef GLEW_EXT_texture3D
+#define GLEW_EXT_texture3D 0
+#endif
+
+#ifndef GLEW_ARB_texture_rg
+#define GLEW_ARB_texture_rg 0
+#endif
+
+#ifndef GLEW_ARB_texture_query_lod
+#define GLEW_ARB_texture_query_lod 0
+#endif
+
+
+/*
+ * The following symbolic constants are missing from an ES only header,
+ * so alias them to their (same valued) extension versions which are available in the header.
+ *
+ * Be careful that this does not lead to unguarded use of what are extensions in ES!
+ *
+ * Some of these may be here simply to patch inconsistencies in the header files.
+ */
+
+#ifndef GL_TEXTURE_3D
+#define GL_TEXTURE_3D GL_TEXTURE_3D_OES
+#endif
+
+#ifndef GL_TEXTURE_WRAP_R
+#define GL_TEXTURE_WRAP_R GL_TEXTURE_WRAP_R_OES
+#endif
+
+#ifndef GL_TEXTURE_COMPARE_MODE
+#define GL_TEXTURE_COMPARE_MODE GL_TEXTURE_COMPARE_MODE_EXT
+#endif
+
+#ifndef GL_COMPARE_REF_TO_TEXTURE
+#define GL_COMPARE_REF_TO_TEXTURE GL_COMPARE_REF_TO_TEXTURE_EXT
+#endif
+
+#ifndef GL_TEXTURE_COMPARE_FUNC
+#define GL_TEXTURE_COMPARE_FUNC GL_TEXTURE_COMPARE_FUNC_EXT
+#endif
+
+#ifndef GL_RGBA8
+#define GL_RGBA8 GL_RGBA8_OES
+#endif
+
+#ifndef GL_RGBA16F
+#define GL_RGBA16F GL_RGBA16F_EXT
+#endif
+
+#ifndef GL_RG32F
+#define GL_RG32F GL_RG32F_EXT
+#endif
+
+#ifndef GL_RGB8
+#define GL_RGB8 GL_RGB8_OES
+#endif
+
+#ifndef GL_RG
+#define GL_RG GL_RG_EXT
+#endif
+
+#ifndef GL_RED
+#define GL_RED GL_RED_EXT
+#endif
+
+#ifndef GL_FRAMEBUFFER_INCOMPLETE_FORMATS
+#define GL_FRAMEBUFFER_INCOMPLETE_FORMATS GL_FRAMEBUFFER_INCOMPLETE_FORMATS_OES
+#endif
+
+#ifndef GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER
+#define GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_OES
+#endif
+
+#ifndef GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER
+#define GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_OES
+#endif
+
+#ifndef GL_WRITE_ONLY
+#define GL_WRITE_ONLY GL_WRITE_ONLY_OES
+#endif
+
+#ifndef GLEW_ARB_vertex_array_object
+#define GLEW_ARB_vertex_array_object 0
+#endif
+
+
+/* end of ifdef GLEW_ES_ONLY */
+#elif defined(GLEW_NO_ES)
+
+
+/*
+ * Need stubs for these version checks if compiling without any support.
+ * Rely on compiler to eliminate unreachable code when version checks become constants
+ */
+
+#ifndef GLEW_ES_VERSION_2_0
+#define GLEW_ES_VERSION_2_0 0
+#endif
+
+#ifndef GLEW_EXT_texture_storage
+#define GLEW_EXT_texture_storage 0
+#endif
+
+#ifndef GLEW_OES_framebuffer_object
+#define GLEW_OES_framebuffer_object 0
+#endif
+
+#ifndef GLEW_OES_mapbuffer
+#define GLEW_OES_mapbuffer 0
+#endif
+
+#ifndef GLEW_OES_required_internalformat
+#define GLEW_OES_required_internalformat 0
+#endif
+
+#ifndef GLEW_EXT_color_buffer_half_float
+#define GLEW_EXT_color_buffer_half_float 0
+#endif
+
+#ifndef GLEW_OES_depth_texture
+#define GLEW_OES_depth_texture 0
+#endif
+
+#ifndef GLEW_EXT_shadow_samplers
+#define GLEW_EXT_shadow_samplers 0
+#endif
+
+#ifndef GLEW_ARB_texture3D
+#define GLEW_ARB_texture3D 0
+#endif
+
+#ifndef GLEW_OES_texture_3D
+#define GLEW_OES_texture_3D 0
+#endif
+
+#ifndef GLEW_EXT_texture_rg
+#define GLEW_EXT_texture_rg 0
+#endif
+
+#ifndef GLEW_OES_vertex_array_object
+#define GLEW_OES_vertex_array_object 0
+#endif
+
+
+/*
+ * The following symbolic constants are missing when there is no ES support,
+ * so alias them to their (same valued) extension versions which are available in the header.
+ *
+ * Desktop GL typically does not have any extensions that originated from ES,
+ * unlike ES which has many extensions to replace what was taken out.
+ *
+ * For that reason these aliases are more likely just patching inconsistencies in the header files.
+ */
+
+#ifndef GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS
+#define GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT
+#endif
+
+#ifndef GL_FRAMEBUFFER_INCOMPLETE_FORMATS
+#define GL_FRAMEBUFFER_INCOMPLETE_FORMATS GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT
+#endif
+
+#endif /* ifdef GLEW_NO_ES */
+
+
+#endif /* __SYMBOL_BINDING_H__*/
diff --git a/intern/guardedalloc/MEM_guardedalloc.h b/intern/guardedalloc/MEM_guardedalloc.h
index 3b56362e3d6..05a98c1a4e5 100644
--- a/intern/guardedalloc/MEM_guardedalloc.h
+++ b/intern/guardedalloc/MEM_guardedalloc.h
@@ -165,9 +165,9 @@ extern "C" {
* Memory usage stats
* - MEM_get_memory_in_use is all memory
* - MEM_get_mapped_memory_in_use is a subset of all memory */
- extern uintptr_t (*MEM_get_memory_in_use)(void);
+ extern size_t (*MEM_get_memory_in_use)(void);
/** Get mapped memory usage. */
- extern uintptr_t (*MEM_get_mapped_memory_in_use)(void);
+ extern size_t (*MEM_get_mapped_memory_in_use)(void);
/** Get amount of memory blocks in use. */
extern unsigned int (*MEM_get_memory_blocks_in_use)(void);
@@ -177,7 +177,23 @@ extern "C" {
/** Get the peak memory usage in bytes, including mmap allocations. */
extern size_t (*MEM_get_peak_memory)(void) ATTR_WARN_UNUSED_RESULT;
-#define MEM_SAFE_FREE(v) if (v) { MEM_freeN(v); v = NULL; } (void)0
+#ifdef __GNUC__
+#define MEM_SAFE_FREE(v) do { \
+ typeof(&(v)) _v = &(v); \
+ if (*_v) { \
+ MEM_freeN(*_v); \
+ *_v = NULL; \
+ } \
+} while (0)
+#else
+#define MEM_SAFE_FREE(v) do { \
+ void ** _v = (void **)&(v); \
+ if (*_v) { \
+ MEM_freeN(*_v); \
+ *_v = NULL; \
+ } \
+} while (0)
+#endif
/* overhead for lockfree allocator (use to avoid slop-space) */
#define MEM_SIZE_OVERHEAD sizeof(size_t)
diff --git a/intern/guardedalloc/intern/mallocn.c b/intern/guardedalloc/intern/mallocn.c
index be0a8aadf84..1fd85a0c9f5 100644
--- a/intern/guardedalloc/intern/mallocn.c
+++ b/intern/guardedalloc/intern/mallocn.c
@@ -17,6 +17,7 @@
*
* Contributor(s): Brecht Van Lommel
* Campbell Barton
+ * Sergey Sharybin
*
* ***** END GPL LICENSE BLOCK *****
*/
@@ -53,11 +54,11 @@ void (*MEM_set_error_callback)(void (*func)(const char *)) = MEM_lockfree_set_er
bool (*MEM_check_memory_integrity)(void) = MEM_lockfree_check_memory_integrity;
void (*MEM_set_lock_callback)(void (*lock)(void), void (*unlock)(void)) = MEM_lockfree_set_lock_callback;
void (*MEM_set_memory_debug)(void) = MEM_lockfree_set_memory_debug;
-uintptr_t (*MEM_get_memory_in_use)(void) = MEM_lockfree_get_memory_in_use;
-uintptr_t (*MEM_get_mapped_memory_in_use)(void) = MEM_lockfree_get_mapped_memory_in_use;
+size_t (*MEM_get_memory_in_use)(void) = MEM_lockfree_get_memory_in_use;
+size_t (*MEM_get_mapped_memory_in_use)(void) = MEM_lockfree_get_mapped_memory_in_use;
unsigned int (*MEM_get_memory_blocks_in_use)(void) = MEM_lockfree_get_memory_blocks_in_use;
void (*MEM_reset_peak_memory)(void) = MEM_lockfree_reset_peak_memory;
-uintptr_t (*MEM_get_peak_memory)(void) = MEM_lockfree_get_peak_memory;
+size_t (*MEM_get_peak_memory)(void) = MEM_lockfree_get_peak_memory;
#ifndef NDEBUG
const char *(*MEM_name_ptr)(void *vmemh) = MEM_lockfree_name_ptr;
diff --git a/intern/guardedalloc/intern/mallocn_guarded_impl.c b/intern/guardedalloc/intern/mallocn_guarded_impl.c
index 10781a9cc54..1933e9d3ee3 100644
--- a/intern/guardedalloc/intern/mallocn_guarded_impl.c
+++ b/intern/guardedalloc/intern/mallocn_guarded_impl.c
@@ -22,6 +22,7 @@
*
* Contributor(s): Brecht Van Lommel
* Campbell Barton
+ * Sergey Sharybin
*
* ***** END GPL LICENSE BLOCK *****
*/
@@ -710,10 +711,12 @@ void MEM_guarded_printmemlist_stats(void)
totpb++;
pb++;
- if (!membl->mmap) {
+#ifdef USE_MALLOC_USABLE_SIZE
+ if (!membl->mmap && membl->alignment == 0) {
mem_in_use_slop += (sizeof(MemHead) + sizeof(MemTail) +
malloc_usable_size((void *)membl)) - membl->len;
}
+#endif
if (membl->next)
membl = MEMNEXT(membl->next);
@@ -1147,13 +1150,13 @@ size_t MEM_guarded_get_peak_memory(void)
void MEM_guarded_reset_peak_memory(void)
{
mem_lock_thread();
- peak_mem = 0;
+ peak_mem = mem_in_use;
mem_unlock_thread();
}
-uintptr_t MEM_guarded_get_memory_in_use(void)
+size_t MEM_guarded_get_memory_in_use(void)
{
- uintptr_t _mem_in_use;
+ size_t _mem_in_use;
mem_lock_thread();
_mem_in_use = mem_in_use;
@@ -1162,9 +1165,9 @@ uintptr_t MEM_guarded_get_memory_in_use(void)
return _mem_in_use;
}
-uintptr_t MEM_guarded_get_mapped_memory_in_use(void)
+size_t MEM_guarded_get_mapped_memory_in_use(void)
{
- uintptr_t _mmap_in_use;
+ size_t _mmap_in_use;
mem_lock_thread();
_mmap_in_use = mmap_in_use;
diff --git a/intern/guardedalloc/intern/mallocn_intern.h b/intern/guardedalloc/intern/mallocn_intern.h
index 7da74f7cc4c..3f7e462c1c7 100644
--- a/intern/guardedalloc/intern/mallocn_intern.h
+++ b/intern/guardedalloc/intern/mallocn_intern.h
@@ -50,6 +50,7 @@
#endif
#undef HAVE_MALLOC_STATS
+#define USE_MALLOC_USABLE_SIZE /* internal, when we have malloc_usable_size() */
#if defined(__linux__) || (defined(__FreeBSD_kernel__) && !defined(__FreeBSD__)) || defined(__GLIBC__)
# include <malloc.h>
@@ -63,7 +64,8 @@
# include <malloc.h>
# define malloc_usable_size _msize
#else
-# error "We don't know how to use malloc_usable_size on your platform"
+# pragma message "We don't know how to use malloc_usable_size on your platform"
+# undef USE_MALLOC_USABLE_SIZE
#endif
/* Blame Microsoft for LLP64 and no inttypes.h, quick workaround needed: */
@@ -139,11 +141,11 @@ void MEM_lockfree_set_error_callback(void (*func)(const char *));
bool MEM_lockfree_check_memory_integrity(void);
void MEM_lockfree_set_lock_callback(void (*lock)(void), void (*unlock)(void));
void MEM_lockfree_set_memory_debug(void);
-uintptr_t MEM_lockfree_get_memory_in_use(void);
-uintptr_t MEM_lockfree_get_mapped_memory_in_use(void);
+size_t MEM_lockfree_get_memory_in_use(void);
+size_t MEM_lockfree_get_mapped_memory_in_use(void);
unsigned int MEM_lockfree_get_memory_blocks_in_use(void);
void MEM_lockfree_reset_peak_memory(void);
-uintptr_t MEM_lockfree_get_peak_memory(void) ATTR_WARN_UNUSED_RESULT;
+size_t MEM_lockfree_get_peak_memory(void) ATTR_WARN_UNUSED_RESULT;
#ifndef NDEBUG
const char *MEM_lockfree_name_ptr(void *vmemh);
#endif
@@ -166,11 +168,11 @@ void MEM_guarded_set_error_callback(void (*func)(const char *));
bool MEM_guarded_check_memory_integrity(void);
void MEM_guarded_set_lock_callback(void (*lock)(void), void (*unlock)(void));
void MEM_guarded_set_memory_debug(void);
-uintptr_t MEM_guarded_get_memory_in_use(void);
-uintptr_t MEM_guarded_get_mapped_memory_in_use(void);
+size_t MEM_guarded_get_memory_in_use(void);
+size_t MEM_guarded_get_mapped_memory_in_use(void);
unsigned int MEM_guarded_get_memory_blocks_in_use(void);
void MEM_guarded_reset_peak_memory(void);
-uintptr_t MEM_guarded_get_peak_memory(void) ATTR_WARN_UNUSED_RESULT;
+size_t MEM_guarded_get_peak_memory(void) ATTR_WARN_UNUSED_RESULT;
#ifndef NDEBUG
const char *MEM_guarded_name_ptr(void *vmemh);
#endif
diff --git a/intern/guardedalloc/intern/mallocn_lockfree_impl.c b/intern/guardedalloc/intern/mallocn_lockfree_impl.c
index c0f6aeeaa9d..a80d67c3e80 100644
--- a/intern/guardedalloc/intern/mallocn_lockfree_impl.c
+++ b/intern/guardedalloc/intern/mallocn_lockfree_impl.c
@@ -71,7 +71,7 @@ enum {
#define MEMHEAD_IS_ALIGNED(memhead) ((memhead)->len & (size_t) MEMHEAD_ALIGN_FLAG)
/* Uncomment this to have proper peak counter. */
-//#define USE_ATOMIC_MAX
+#define USE_ATOMIC_MAX
MEM_INLINE void update_maximum(size_t *maximum_value, size_t value)
{
@@ -134,6 +134,14 @@ void MEM_lockfree_freeN(void *vmemh)
MemHead *memh = MEMHEAD_FROM_PTR(vmemh);
size_t len = MEM_lockfree_allocN_len(vmemh);
+ if (vmemh == NULL) {
+ print_error("Attempt to free NULL pointer\n");
+#ifdef WITH_ASSERT_ABORT
+ abort();
+#endif
+ return;
+ }
+
atomic_sub_u(&totblock, 1);
atomic_sub_z(&mem_in_use, len);
@@ -452,12 +460,12 @@ void MEM_lockfree_set_memory_debug(void)
malloc_debug_memset = true;
}
-uintptr_t MEM_lockfree_get_memory_in_use(void)
+size_t MEM_lockfree_get_memory_in_use(void)
{
return mem_in_use;
}
-uintptr_t MEM_lockfree_get_mapped_memory_in_use(void)
+size_t MEM_lockfree_get_mapped_memory_in_use(void)
{
return mmap_in_use;
}
@@ -470,10 +478,10 @@ unsigned int MEM_lockfree_get_memory_blocks_in_use(void)
/* dummy */
void MEM_lockfree_reset_peak_memory(void)
{
- peak_mem = 0;
+ peak_mem = mem_in_use;
}
-uintptr_t MEM_lockfree_get_peak_memory(void)
+size_t MEM_lockfree_get_peak_memory(void)
{
return peak_mem;
}
diff --git a/intern/iksolver/extern/IK_solver.h b/intern/iksolver/extern/IK_solver.h
index 4de9f143e77..55223806d5c 100644
--- a/intern/iksolver/extern/IK_solver.h
+++ b/intern/iksolver/extern/IK_solver.h
@@ -35,10 +35,10 @@
* Copyright (C) 2001 NaN Technologies B.V.
*
- * @author Laurence, Brecht
- * @mainpage IK - Blender inverse kinematics module.
+ * \author Laurence, Brecht
+ * \page IK - Blender inverse kinematics module.
*
- * @section about About the IK module
+ * \section about About the IK module
*
* This module allows you to create segments and form them into
* tree. You can then define a goal points that the end of a given
@@ -47,7 +47,7 @@
* to get the as near as possible to the goal. This solver uses an
* inverse jacobian method to find a solution.
*
- * @section issues Known issues with this IK solver.
+ * \section issues Known issues with this IK solver.
*
* - There is currently no support for joint constraints in the
* solver. This is within the realms of possibility - please ask
@@ -60,7 +60,7 @@
* Other algorithms exist which are more suitable for real-time
* applications, please ask if this functionality is required.
*
- * @section dependencies Dependencies
+ * \section dependencies Dependencies
*
* This module only depends on Moto.
*/
diff --git a/intern/iksolver/intern/IK_Solver.cpp b/intern/iksolver/intern/IK_Solver.cpp
index 65ea4d64ab1..eb18cde3356 100644
--- a/intern/iksolver/intern/IK_Solver.cpp
+++ b/intern/iksolver/intern/IK_Solver.cpp
@@ -292,6 +292,7 @@ void IK_SolverAddGoal(IK_Solver *solver, IK_Segment *tip, float goal[3], float w
IK_QSolver *qsolver = (IK_QSolver *)solver;
IK_QSegment *qtip = (IK_QSegment *)tip;
+ // in case of composite segment the second segment is the tip
if (qtip->Composite())
qtip = qtip->Composite();
@@ -310,6 +311,7 @@ void IK_SolverAddGoalOrientation(IK_Solver *solver, IK_Segment *tip, float goal[
IK_QSolver *qsolver = (IK_QSolver *)solver;
IK_QSegment *qtip = (IK_QSegment *)tip;
+ // in case of composite segment the second segment is the tip
if (qtip->Composite())
qtip = qtip->Composite();
@@ -331,6 +333,10 @@ void IK_SolverSetPoleVectorConstraint(IK_Solver *solver, IK_Segment *tip, float
IK_QSolver *qsolver = (IK_QSolver *)solver;
IK_QSegment *qtip = (IK_QSegment *)tip;
+ // in case of composite segment the second segment is the tip
+ if (qtip->Composite())
+ qtip = qtip->Composite();
+
MT_Vector3 qgoal(goal);
MT_Vector3 qpolegoal(polegoal);
diff --git a/intern/itasc/CMakeLists.txt b/intern/itasc/CMakeLists.txt
index bc3ea0cf24c..bdf0f88e516 100644
--- a/intern/itasc/CMakeLists.txt
+++ b/intern/itasc/CMakeLists.txt
@@ -28,9 +28,244 @@ set(INC
)
set(INC_SYS
- ../../extern/Eigen3
+ ${EIGEN3_INCLUDE_DIRS}
)
+if(NOT WITH_SYSTEM_EIGEN3)
+ set(EIGEN3_HEADERS
+ # until we have another user...
+ ../../extern/Eigen3/Eigen/src/Cholesky/LDLT.h
+ ../../extern/Eigen3/Eigen/src/Cholesky/LLT.h
+ ../../extern/Eigen3/Eigen/src/Cholesky/LLT_MKL.h
+ ../../extern/Eigen3/Eigen/src/CholmodSupport/CholmodSupport.h
+ ../../extern/Eigen3/Eigen/src/Core/Array.h
+ ../../extern/Eigen3/Eigen/src/Core/ArrayBase.h
+ ../../extern/Eigen3/Eigen/src/Core/ArrayWrapper.h
+ ../../extern/Eigen3/Eigen/src/Core/Assign.h
+ ../../extern/Eigen3/Eigen/src/Core/Assign_MKL.h
+ ../../extern/Eigen3/Eigen/src/Core/BandMatrix.h
+ ../../extern/Eigen3/Eigen/src/Core/Block.h
+ ../../extern/Eigen3/Eigen/src/Core/BooleanRedux.h
+ ../../extern/Eigen3/Eigen/src/Core/CommaInitializer.h
+ ../../extern/Eigen3/Eigen/src/Core/CwiseBinaryOp.h
+ ../../extern/Eigen3/Eigen/src/Core/CwiseNullaryOp.h
+ ../../extern/Eigen3/Eigen/src/Core/CwiseUnaryOp.h
+ ../../extern/Eigen3/Eigen/src/Core/CwiseUnaryView.h
+ ../../extern/Eigen3/Eigen/src/Core/DenseBase.h
+ ../../extern/Eigen3/Eigen/src/Core/DenseCoeffsBase.h
+ ../../extern/Eigen3/Eigen/src/Core/DenseStorage.h
+ ../../extern/Eigen3/Eigen/src/Core/Diagonal.h
+ ../../extern/Eigen3/Eigen/src/Core/DiagonalMatrix.h
+ ../../extern/Eigen3/Eigen/src/Core/DiagonalProduct.h
+ ../../extern/Eigen3/Eigen/src/Core/Dot.h
+ ../../extern/Eigen3/Eigen/src/Core/EigenBase.h
+ ../../extern/Eigen3/Eigen/src/Core/Flagged.h
+ ../../extern/Eigen3/Eigen/src/Core/ForceAlignedAccess.h
+ ../../extern/Eigen3/Eigen/src/Core/Functors.h
+ ../../extern/Eigen3/Eigen/src/Core/Fuzzy.h
+ ../../extern/Eigen3/Eigen/src/Core/GeneralProduct.h
+ ../../extern/Eigen3/Eigen/src/Core/GenericPacketMath.h
+ ../../extern/Eigen3/Eigen/src/Core/GlobalFunctions.h
+ ../../extern/Eigen3/Eigen/src/Core/IO.h
+ ../../extern/Eigen3/Eigen/src/Core/Map.h
+ ../../extern/Eigen3/Eigen/src/Core/MapBase.h
+ ../../extern/Eigen3/Eigen/src/Core/MathFunctions.h
+ ../../extern/Eigen3/Eigen/src/Core/Matrix.h
+ ../../extern/Eigen3/Eigen/src/Core/MatrixBase.h
+ ../../extern/Eigen3/Eigen/src/Core/NestByValue.h
+ ../../extern/Eigen3/Eigen/src/Core/NoAlias.h
+ ../../extern/Eigen3/Eigen/src/Core/NumTraits.h
+ ../../extern/Eigen3/Eigen/src/Core/PermutationMatrix.h
+ ../../extern/Eigen3/Eigen/src/Core/PlainObjectBase.h
+ ../../extern/Eigen3/Eigen/src/Core/Product.h
+ ../../extern/Eigen3/Eigen/src/Core/ProductBase.h
+ ../../extern/Eigen3/Eigen/src/Core/Random.h
+ ../../extern/Eigen3/Eigen/src/Core/Redux.h
+ ../../extern/Eigen3/Eigen/src/Core/Replicate.h
+ ../../extern/Eigen3/Eigen/src/Core/ReturnByValue.h
+ ../../extern/Eigen3/Eigen/src/Core/Reverse.h
+ ../../extern/Eigen3/Eigen/src/Core/Select.h
+ ../../extern/Eigen3/Eigen/src/Core/SelfAdjointView.h
+ ../../extern/Eigen3/Eigen/src/Core/SelfCwiseBinaryOp.h
+ ../../extern/Eigen3/Eigen/src/Core/SolveTriangular.h
+ ../../extern/Eigen3/Eigen/src/Core/StableNorm.h
+ ../../extern/Eigen3/Eigen/src/Core/Stride.h
+ ../../extern/Eigen3/Eigen/src/Core/Swap.h
+ ../../extern/Eigen3/Eigen/src/Core/Transpose.h
+ ../../extern/Eigen3/Eigen/src/Core/Transpositions.h
+ ../../extern/Eigen3/Eigen/src/Core/TriangularMatrix.h
+ ../../extern/Eigen3/Eigen/src/Core/VectorBlock.h
+ ../../extern/Eigen3/Eigen/src/Core/VectorwiseOp.h
+ ../../extern/Eigen3/Eigen/src/Core/Visitor.h
+ ../../extern/Eigen3/Eigen/src/Core/arch/AltiVec/Complex.h
+ ../../extern/Eigen3/Eigen/src/Core/arch/AltiVec/PacketMath.h
+ ../../extern/Eigen3/Eigen/src/Core/arch/Default/Settings.h
+ ../../extern/Eigen3/Eigen/src/Core/arch/NEON/Complex.h
+ ../../extern/Eigen3/Eigen/src/Core/arch/NEON/PacketMath.h
+ ../../extern/Eigen3/Eigen/src/Core/arch/SSE/Complex.h
+ ../../extern/Eigen3/Eigen/src/Core/arch/SSE/MathFunctions.h
+ ../../extern/Eigen3/Eigen/src/Core/arch/SSE/PacketMath.h
+ ../../extern/Eigen3/Eigen/src/Core/products/CoeffBasedProduct.h
+ ../../extern/Eigen3/Eigen/src/Core/products/GeneralBlockPanelKernel.h
+ ../../extern/Eigen3/Eigen/src/Core/products/GeneralMatrixMatrix.h
+ ../../extern/Eigen3/Eigen/src/Core/products/GeneralMatrixMatrixTriangular.h
+ ../../extern/Eigen3/Eigen/src/Core/products/GeneralMatrixMatrixTriangular_MKL.h
+ ../../extern/Eigen3/Eigen/src/Core/products/GeneralMatrixMatrix_MKL.h
+ ../../extern/Eigen3/Eigen/src/Core/products/GeneralMatrixVector.h
+ ../../extern/Eigen3/Eigen/src/Core/products/GeneralMatrixVector_MKL.h
+ ../../extern/Eigen3/Eigen/src/Core/products/Parallelizer.h
+ ../../extern/Eigen3/Eigen/src/Core/products/SelfadjointMatrixMatrix.h
+ ../../extern/Eigen3/Eigen/src/Core/products/SelfadjointMatrixMatrix_MKL.h
+ ../../extern/Eigen3/Eigen/src/Core/products/SelfadjointMatrixVector.h
+ ../../extern/Eigen3/Eigen/src/Core/products/SelfadjointMatrixVector_MKL.h
+ ../../extern/Eigen3/Eigen/src/Core/products/SelfadjointProduct.h
+ ../../extern/Eigen3/Eigen/src/Core/products/SelfadjointRank2Update.h
+ ../../extern/Eigen3/Eigen/src/Core/products/TriangularMatrixMatrix.h
+ ../../extern/Eigen3/Eigen/src/Core/products/TriangularMatrixMatrix_MKL.h
+ ../../extern/Eigen3/Eigen/src/Core/products/TriangularMatrixVector.h
+ ../../extern/Eigen3/Eigen/src/Core/products/TriangularMatrixVector_MKL.h
+ ../../extern/Eigen3/Eigen/src/Core/products/TriangularSolverMatrix.h
+ ../../extern/Eigen3/Eigen/src/Core/products/TriangularSolverMatrix_MKL.h
+ ../../extern/Eigen3/Eigen/src/Core/products/TriangularSolverVector.h
+ ../../extern/Eigen3/Eigen/src/Core/util/BlasUtil.h
+ ../../extern/Eigen3/Eigen/src/Core/util/Constants.h
+ ../../extern/Eigen3/Eigen/src/Core/util/DisableStupidWarnings.h
+ ../../extern/Eigen3/Eigen/src/Core/util/ForwardDeclarations.h
+ ../../extern/Eigen3/Eigen/src/Core/util/Macros.h
+ ../../extern/Eigen3/Eigen/src/Core/util/Memory.h
+ ../../extern/Eigen3/Eigen/src/Core/util/Meta.h
+ ../../extern/Eigen3/Eigen/src/Core/util/MKL_support.h
+ ../../extern/Eigen3/Eigen/src/Core/util/NonMPL2.h
+ ../../extern/Eigen3/Eigen/src/Core/util/ReenableStupidWarnings.h
+ ../../extern/Eigen3/Eigen/src/Core/util/StaticAssert.h
+ ../../extern/Eigen3/Eigen/src/Core/util/XprHelper.h
+ ../../extern/Eigen3/Eigen/src/Eigen2Support/Block.h
+ ../../extern/Eigen3/Eigen/src/Eigen2Support/Cwise.h
+ ../../extern/Eigen3/Eigen/src/Eigen2Support/CwiseOperators.h
+ ../../extern/Eigen3/Eigen/src/Eigen2Support/Lazy.h
+ ../../extern/Eigen3/Eigen/src/Eigen2Support/LeastSquares.h
+ ../../extern/Eigen3/Eigen/src/Eigen2Support/LU.h
+ ../../extern/Eigen3/Eigen/src/Eigen2Support/Macros.h
+ ../../extern/Eigen3/Eigen/src/Eigen2Support/MathFunctions.h
+ ../../extern/Eigen3/Eigen/src/Eigen2Support/Memory.h
+ ../../extern/Eigen3/Eigen/src/Eigen2Support/Meta.h
+ ../../extern/Eigen3/Eigen/src/Eigen2Support/Minor.h
+ ../../extern/Eigen3/Eigen/src/Eigen2Support/QR.h
+ ../../extern/Eigen3/Eigen/src/Eigen2Support/SVD.h
+ ../../extern/Eigen3/Eigen/src/Eigen2Support/TriangularSolver.h
+ ../../extern/Eigen3/Eigen/src/Eigen2Support/VectorBlock.h
+ ../../extern/Eigen3/Eigen/src/Eigen2Support/Geometry/AlignedBox.h
+ ../../extern/Eigen3/Eigen/src/Eigen2Support/Geometry/All.h
+ ../../extern/Eigen3/Eigen/src/Eigen2Support/Geometry/AngleAxis.h
+ ../../extern/Eigen3/Eigen/src/Eigen2Support/Geometry/Hyperplane.h
+ ../../extern/Eigen3/Eigen/src/Eigen2Support/Geometry/ParametrizedLine.h
+ ../../extern/Eigen3/Eigen/src/Eigen2Support/Geometry/Quaternion.h
+ ../../extern/Eigen3/Eigen/src/Eigen2Support/Geometry/Rotation2D.h
+ ../../extern/Eigen3/Eigen/src/Eigen2Support/Geometry/RotationBase.h
+ ../../extern/Eigen3/Eigen/src/Eigen2Support/Geometry/Scaling.h
+ ../../extern/Eigen3/Eigen/src/Eigen2Support/Geometry/Transform.h
+ ../../extern/Eigen3/Eigen/src/Eigen2Support/Geometry/Translation.h
+ ../../extern/Eigen3/Eigen/src/Eigenvalues/ComplexEigenSolver.h
+ ../../extern/Eigen3/Eigen/src/Eigenvalues/ComplexSchur.h
+ ../../extern/Eigen3/Eigen/src/Eigenvalues/ComplexSchur_MKL.h
+ ../../extern/Eigen3/Eigen/src/Eigenvalues/EigenSolver.h
+ ../../extern/Eigen3/Eigen/src/Eigenvalues/GeneralizedSelfAdjointEigenSolver.h
+ ../../extern/Eigen3/Eigen/src/Eigenvalues/HessenbergDecomposition.h
+ ../../extern/Eigen3/Eigen/src/Eigenvalues/MatrixBaseEigenvalues.h
+ ../../extern/Eigen3/Eigen/src/Eigenvalues/RealSchur.h
+ ../../extern/Eigen3/Eigen/src/Eigenvalues/RealSchur_MKL.h
+ ../../extern/Eigen3/Eigen/src/Eigenvalues/SelfAdjointEigenSolver.h
+ ../../extern/Eigen3/Eigen/src/Eigenvalues/SelfAdjointEigenSolver_MKL.h
+ ../../extern/Eigen3/Eigen/src/Eigenvalues/Tridiagonalization.h
+ ../../extern/Eigen3/Eigen/src/Geometry/AlignedBox.h
+ ../../extern/Eigen3/Eigen/src/Geometry/AngleAxis.h
+ ../../extern/Eigen3/Eigen/src/Geometry/EulerAngles.h
+ ../../extern/Eigen3/Eigen/src/Geometry/Homogeneous.h
+ ../../extern/Eigen3/Eigen/src/Geometry/Hyperplane.h
+ ../../extern/Eigen3/Eigen/src/Geometry/OrthoMethods.h
+ ../../extern/Eigen3/Eigen/src/Geometry/ParametrizedLine.h
+ ../../extern/Eigen3/Eigen/src/Geometry/Quaternion.h
+ ../../extern/Eigen3/Eigen/src/Geometry/Rotation2D.h
+ ../../extern/Eigen3/Eigen/src/Geometry/RotationBase.h
+ ../../extern/Eigen3/Eigen/src/Geometry/Scaling.h
+ ../../extern/Eigen3/Eigen/src/Geometry/Transform.h
+ ../../extern/Eigen3/Eigen/src/Geometry/Translation.h
+ ../../extern/Eigen3/Eigen/src/Geometry/Umeyama.h
+ ../../extern/Eigen3/Eigen/src/Geometry/arch/Geometry_SSE.h
+ ../../extern/Eigen3/Eigen/src/Householder/BlockHouseholder.h
+ ../../extern/Eigen3/Eigen/src/Householder/Householder.h
+ ../../extern/Eigen3/Eigen/src/Householder/HouseholderSequence.h
+ ../../extern/Eigen3/Eigen/src/IterativeLinearSolvers/BasicPreconditioners.h
+ ../../extern/Eigen3/Eigen/src/IterativeLinearSolvers/BiCGSTAB.h
+ ../../extern/Eigen3/Eigen/src/IterativeLinearSolvers/ConjugateGradient.h
+ ../../extern/Eigen3/Eigen/src/IterativeLinearSolvers/IncompleteLUT.h
+ ../../extern/Eigen3/Eigen/src/IterativeLinearSolvers/IterativeSolverBase.h
+ ../../extern/Eigen3/Eigen/src/Jacobi/Jacobi.h
+ ../../extern/Eigen3/Eigen/src/LU/Determinant.h
+ ../../extern/Eigen3/Eigen/src/LU/FullPivLU.h
+ ../../extern/Eigen3/Eigen/src/LU/Inverse.h
+ ../../extern/Eigen3/Eigen/src/LU/PartialPivLU.h
+ ../../extern/Eigen3/Eigen/src/LU/PartialPivLU_MKL.h
+ ../../extern/Eigen3/Eigen/src/LU/arch/Inverse_SSE.h
+ ../../extern/Eigen3/Eigen/src/misc/blas.h
+ ../../extern/Eigen3/Eigen/src/misc/Image.h
+ ../../extern/Eigen3/Eigen/src/misc/Kernel.h
+ ../../extern/Eigen3/Eigen/src/misc/Solve.h
+ ../../extern/Eigen3/Eigen/src/misc/SparseSolve.h
+ ../../extern/Eigen3/Eigen/src/OrderingMethods/Amd.h
+ ../../extern/Eigen3/Eigen/src/PardisoSupport/PardisoSupport.h
+ ../../extern/Eigen3/Eigen/src/PaStiXSupport/PaStiXSupport.h
+ ../../extern/Eigen3/Eigen/src/plugins/ArrayCwiseBinaryOps.h
+ ../../extern/Eigen3/Eigen/src/plugins/ArrayCwiseUnaryOps.h
+ ../../extern/Eigen3/Eigen/src/plugins/BlockMethods.h
+ ../../extern/Eigen3/Eigen/src/plugins/CommonCwiseBinaryOps.h
+ ../../extern/Eigen3/Eigen/src/plugins/CommonCwiseUnaryOps.h
+ ../../extern/Eigen3/Eigen/src/plugins/MatrixCwiseBinaryOps.h
+ ../../extern/Eigen3/Eigen/src/plugins/MatrixCwiseUnaryOps.h
+ ../../extern/Eigen3/Eigen/src/QR/ColPivHouseholderQR.h
+ ../../extern/Eigen3/Eigen/src/QR/ColPivHouseholderQR_MKL.h
+ ../../extern/Eigen3/Eigen/src/QR/FullPivHouseholderQR.h
+ ../../extern/Eigen3/Eigen/src/QR/HouseholderQR.h
+ ../../extern/Eigen3/Eigen/src/QR/HouseholderQR_MKL.h
+ ../../extern/Eigen3/Eigen/src/SparseCholesky/SimplicialCholesky.h
+ ../../extern/Eigen3/Eigen/src/SparseCore/AmbiVector.h
+ ../../extern/Eigen3/Eigen/src/SparseCore/CompressedStorage.h
+ ../../extern/Eigen3/Eigen/src/SparseCore/ConservativeSparseSparseProduct.h
+ ../../extern/Eigen3/Eigen/src/SparseCore/CoreIterators.h
+ ../../extern/Eigen3/Eigen/src/SparseCore/MappedSparseMatrix.h
+ ../../extern/Eigen3/Eigen/src/SparseCore/SparseAssign.h
+ ../../extern/Eigen3/Eigen/src/SparseCore/SparseBlock.h
+ ../../extern/Eigen3/Eigen/src/SparseCore/SparseCwiseBinaryOp.h
+ ../../extern/Eigen3/Eigen/src/SparseCore/SparseCwiseUnaryOp.h
+ ../../extern/Eigen3/Eigen/src/SparseCore/SparseDenseProduct.h
+ ../../extern/Eigen3/Eigen/src/SparseCore/SparseDiagonalProduct.h
+ ../../extern/Eigen3/Eigen/src/SparseCore/SparseDot.h
+ ../../extern/Eigen3/Eigen/src/SparseCore/SparseFuzzy.h
+ ../../extern/Eigen3/Eigen/src/SparseCore/SparseMatrix.h
+ ../../extern/Eigen3/Eigen/src/SparseCore/SparseMatrixBase.h
+ ../../extern/Eigen3/Eigen/src/SparseCore/SparsePermutation.h
+ ../../extern/Eigen3/Eigen/src/SparseCore/SparseProduct.h
+ ../../extern/Eigen3/Eigen/src/SparseCore/SparseRedux.h
+ ../../extern/Eigen3/Eigen/src/SparseCore/SparseSelfAdjointView.h
+ ../../extern/Eigen3/Eigen/src/SparseCore/SparseSparseProductWithPruning.h
+ ../../extern/Eigen3/Eigen/src/SparseCore/SparseTranspose.h
+ ../../extern/Eigen3/Eigen/src/SparseCore/SparseTriangularView.h
+ ../../extern/Eigen3/Eigen/src/SparseCore/SparseUtil.h
+ ../../extern/Eigen3/Eigen/src/SparseCore/SparseVector.h
+ ../../extern/Eigen3/Eigen/src/SparseCore/SparseView.h
+ ../../extern/Eigen3/Eigen/src/SparseCore/TriangularSolver.h
+ ../../extern/Eigen3/Eigen/src/StlSupport/details.h
+ ../../extern/Eigen3/Eigen/src/StlSupport/StdDeque.h
+ ../../extern/Eigen3/Eigen/src/StlSupport/StdList.h
+ ../../extern/Eigen3/Eigen/src/StlSupport/StdVector.h
+ ../../extern/Eigen3/Eigen/src/SuperLUSupport/SuperLUSupport.h
+ ../../extern/Eigen3/Eigen/src/SVD/JacobiSVD.h
+ ../../extern/Eigen3/Eigen/src/SVD/JacobiSVD_MKL.h
+ ../../extern/Eigen3/Eigen/src/SVD/UpperBidiagonalization.h
+ ../../extern/Eigen3/Eigen/src/UmfPackSupport/UmfPackSupport.h
+ )
+endif()
+
set(SRC
Armature.cpp
Cache.cpp
@@ -120,237 +355,9 @@ set(SRC
kdl/frames.inl
kdl/framevel.inl
- # until we have another user...
- ../../extern/Eigen3/Eigen/src/Cholesky/LDLT.h
- ../../extern/Eigen3/Eigen/src/Cholesky/LLT.h
- ../../extern/Eigen3/Eigen/src/Cholesky/LLT_MKL.h
- ../../extern/Eigen3/Eigen/src/CholmodSupport/CholmodSupport.h
- ../../extern/Eigen3/Eigen/src/Core/Array.h
- ../../extern/Eigen3/Eigen/src/Core/ArrayBase.h
- ../../extern/Eigen3/Eigen/src/Core/ArrayWrapper.h
- ../../extern/Eigen3/Eigen/src/Core/Assign.h
- ../../extern/Eigen3/Eigen/src/Core/Assign_MKL.h
- ../../extern/Eigen3/Eigen/src/Core/BandMatrix.h
- ../../extern/Eigen3/Eigen/src/Core/Block.h
- ../../extern/Eigen3/Eigen/src/Core/BooleanRedux.h
- ../../extern/Eigen3/Eigen/src/Core/CommaInitializer.h
- ../../extern/Eigen3/Eigen/src/Core/CwiseBinaryOp.h
- ../../extern/Eigen3/Eigen/src/Core/CwiseNullaryOp.h
- ../../extern/Eigen3/Eigen/src/Core/CwiseUnaryOp.h
- ../../extern/Eigen3/Eigen/src/Core/CwiseUnaryView.h
- ../../extern/Eigen3/Eigen/src/Core/DenseBase.h
- ../../extern/Eigen3/Eigen/src/Core/DenseCoeffsBase.h
- ../../extern/Eigen3/Eigen/src/Core/DenseStorage.h
- ../../extern/Eigen3/Eigen/src/Core/Diagonal.h
- ../../extern/Eigen3/Eigen/src/Core/DiagonalMatrix.h
- ../../extern/Eigen3/Eigen/src/Core/DiagonalProduct.h
- ../../extern/Eigen3/Eigen/src/Core/Dot.h
- ../../extern/Eigen3/Eigen/src/Core/EigenBase.h
- ../../extern/Eigen3/Eigen/src/Core/Flagged.h
- ../../extern/Eigen3/Eigen/src/Core/ForceAlignedAccess.h
- ../../extern/Eigen3/Eigen/src/Core/Functors.h
- ../../extern/Eigen3/Eigen/src/Core/Fuzzy.h
- ../../extern/Eigen3/Eigen/src/Core/GeneralProduct.h
- ../../extern/Eigen3/Eigen/src/Core/GenericPacketMath.h
- ../../extern/Eigen3/Eigen/src/Core/GlobalFunctions.h
- ../../extern/Eigen3/Eigen/src/Core/IO.h
- ../../extern/Eigen3/Eigen/src/Core/Map.h
- ../../extern/Eigen3/Eigen/src/Core/MapBase.h
- ../../extern/Eigen3/Eigen/src/Core/MathFunctions.h
- ../../extern/Eigen3/Eigen/src/Core/Matrix.h
- ../../extern/Eigen3/Eigen/src/Core/MatrixBase.h
- ../../extern/Eigen3/Eigen/src/Core/NestByValue.h
- ../../extern/Eigen3/Eigen/src/Core/NoAlias.h
- ../../extern/Eigen3/Eigen/src/Core/NumTraits.h
- ../../extern/Eigen3/Eigen/src/Core/PermutationMatrix.h
- ../../extern/Eigen3/Eigen/src/Core/PlainObjectBase.h
- ../../extern/Eigen3/Eigen/src/Core/Product.h
- ../../extern/Eigen3/Eigen/src/Core/ProductBase.h
- ../../extern/Eigen3/Eigen/src/Core/Random.h
- ../../extern/Eigen3/Eigen/src/Core/Redux.h
- ../../extern/Eigen3/Eigen/src/Core/Replicate.h
- ../../extern/Eigen3/Eigen/src/Core/ReturnByValue.h
- ../../extern/Eigen3/Eigen/src/Core/Reverse.h
- ../../extern/Eigen3/Eigen/src/Core/Select.h
- ../../extern/Eigen3/Eigen/src/Core/SelfAdjointView.h
- ../../extern/Eigen3/Eigen/src/Core/SelfCwiseBinaryOp.h
- ../../extern/Eigen3/Eigen/src/Core/SolveTriangular.h
- ../../extern/Eigen3/Eigen/src/Core/StableNorm.h
- ../../extern/Eigen3/Eigen/src/Core/Stride.h
- ../../extern/Eigen3/Eigen/src/Core/Swap.h
- ../../extern/Eigen3/Eigen/src/Core/Transpose.h
- ../../extern/Eigen3/Eigen/src/Core/Transpositions.h
- ../../extern/Eigen3/Eigen/src/Core/TriangularMatrix.h
- ../../extern/Eigen3/Eigen/src/Core/VectorBlock.h
- ../../extern/Eigen3/Eigen/src/Core/VectorwiseOp.h
- ../../extern/Eigen3/Eigen/src/Core/Visitor.h
- ../../extern/Eigen3/Eigen/src/Core/arch/AltiVec/Complex.h
- ../../extern/Eigen3/Eigen/src/Core/arch/AltiVec/PacketMath.h
- ../../extern/Eigen3/Eigen/src/Core/arch/Default/Settings.h
- ../../extern/Eigen3/Eigen/src/Core/arch/NEON/Complex.h
- ../../extern/Eigen3/Eigen/src/Core/arch/NEON/PacketMath.h
- ../../extern/Eigen3/Eigen/src/Core/arch/SSE/Complex.h
- ../../extern/Eigen3/Eigen/src/Core/arch/SSE/MathFunctions.h
- ../../extern/Eigen3/Eigen/src/Core/arch/SSE/PacketMath.h
- ../../extern/Eigen3/Eigen/src/Core/products/CoeffBasedProduct.h
- ../../extern/Eigen3/Eigen/src/Core/products/GeneralBlockPanelKernel.h
- ../../extern/Eigen3/Eigen/src/Core/products/GeneralMatrixMatrix.h
- ../../extern/Eigen3/Eigen/src/Core/products/GeneralMatrixMatrixTriangular.h
- ../../extern/Eigen3/Eigen/src/Core/products/GeneralMatrixMatrixTriangular_MKL.h
- ../../extern/Eigen3/Eigen/src/Core/products/GeneralMatrixMatrix_MKL.h
- ../../extern/Eigen3/Eigen/src/Core/products/GeneralMatrixVector.h
- ../../extern/Eigen3/Eigen/src/Core/products/GeneralMatrixVector_MKL.h
- ../../extern/Eigen3/Eigen/src/Core/products/Parallelizer.h
- ../../extern/Eigen3/Eigen/src/Core/products/SelfadjointMatrixMatrix.h
- ../../extern/Eigen3/Eigen/src/Core/products/SelfadjointMatrixMatrix_MKL.h
- ../../extern/Eigen3/Eigen/src/Core/products/SelfadjointMatrixVector.h
- ../../extern/Eigen3/Eigen/src/Core/products/SelfadjointMatrixVector_MKL.h
- ../../extern/Eigen3/Eigen/src/Core/products/SelfadjointProduct.h
- ../../extern/Eigen3/Eigen/src/Core/products/SelfadjointRank2Update.h
- ../../extern/Eigen3/Eigen/src/Core/products/TriangularMatrixMatrix.h
- ../../extern/Eigen3/Eigen/src/Core/products/TriangularMatrixMatrix_MKL.h
- ../../extern/Eigen3/Eigen/src/Core/products/TriangularMatrixVector.h
- ../../extern/Eigen3/Eigen/src/Core/products/TriangularMatrixVector_MKL.h
- ../../extern/Eigen3/Eigen/src/Core/products/TriangularSolverMatrix.h
- ../../extern/Eigen3/Eigen/src/Core/products/TriangularSolverMatrix_MKL.h
- ../../extern/Eigen3/Eigen/src/Core/products/TriangularSolverVector.h
- ../../extern/Eigen3/Eigen/src/Core/util/BlasUtil.h
- ../../extern/Eigen3/Eigen/src/Core/util/Constants.h
- ../../extern/Eigen3/Eigen/src/Core/util/DisableStupidWarnings.h
- ../../extern/Eigen3/Eigen/src/Core/util/ForwardDeclarations.h
- ../../extern/Eigen3/Eigen/src/Core/util/Macros.h
- ../../extern/Eigen3/Eigen/src/Core/util/Memory.h
- ../../extern/Eigen3/Eigen/src/Core/util/Meta.h
- ../../extern/Eigen3/Eigen/src/Core/util/MKL_support.h
- ../../extern/Eigen3/Eigen/src/Core/util/NonMPL2.h
- ../../extern/Eigen3/Eigen/src/Core/util/ReenableStupidWarnings.h
- ../../extern/Eigen3/Eigen/src/Core/util/StaticAssert.h
- ../../extern/Eigen3/Eigen/src/Core/util/XprHelper.h
- ../../extern/Eigen3/Eigen/src/Eigen2Support/Block.h
- ../../extern/Eigen3/Eigen/src/Eigen2Support/Cwise.h
- ../../extern/Eigen3/Eigen/src/Eigen2Support/CwiseOperators.h
- ../../extern/Eigen3/Eigen/src/Eigen2Support/Lazy.h
- ../../extern/Eigen3/Eigen/src/Eigen2Support/LeastSquares.h
- ../../extern/Eigen3/Eigen/src/Eigen2Support/LU.h
- ../../extern/Eigen3/Eigen/src/Eigen2Support/Macros.h
- ../../extern/Eigen3/Eigen/src/Eigen2Support/MathFunctions.h
- ../../extern/Eigen3/Eigen/src/Eigen2Support/Memory.h
- ../../extern/Eigen3/Eigen/src/Eigen2Support/Meta.h
- ../../extern/Eigen3/Eigen/src/Eigen2Support/Minor.h
- ../../extern/Eigen3/Eigen/src/Eigen2Support/QR.h
- ../../extern/Eigen3/Eigen/src/Eigen2Support/SVD.h
- ../../extern/Eigen3/Eigen/src/Eigen2Support/TriangularSolver.h
- ../../extern/Eigen3/Eigen/src/Eigen2Support/VectorBlock.h
- ../../extern/Eigen3/Eigen/src/Eigen2Support/Geometry/AlignedBox.h
- ../../extern/Eigen3/Eigen/src/Eigen2Support/Geometry/All.h
- ../../extern/Eigen3/Eigen/src/Eigen2Support/Geometry/AngleAxis.h
- ../../extern/Eigen3/Eigen/src/Eigen2Support/Geometry/Hyperplane.h
- ../../extern/Eigen3/Eigen/src/Eigen2Support/Geometry/ParametrizedLine.h
- ../../extern/Eigen3/Eigen/src/Eigen2Support/Geometry/Quaternion.h
- ../../extern/Eigen3/Eigen/src/Eigen2Support/Geometry/Rotation2D.h
- ../../extern/Eigen3/Eigen/src/Eigen2Support/Geometry/RotationBase.h
- ../../extern/Eigen3/Eigen/src/Eigen2Support/Geometry/Scaling.h
- ../../extern/Eigen3/Eigen/src/Eigen2Support/Geometry/Transform.h
- ../../extern/Eigen3/Eigen/src/Eigen2Support/Geometry/Translation.h
- ../../extern/Eigen3/Eigen/src/Eigenvalues/ComplexEigenSolver.h
- ../../extern/Eigen3/Eigen/src/Eigenvalues/ComplexSchur.h
- ../../extern/Eigen3/Eigen/src/Eigenvalues/ComplexSchur_MKL.h
- ../../extern/Eigen3/Eigen/src/Eigenvalues/EigenSolver.h
- ../../extern/Eigen3/Eigen/src/Eigenvalues/GeneralizedSelfAdjointEigenSolver.h
- ../../extern/Eigen3/Eigen/src/Eigenvalues/HessenbergDecomposition.h
- ../../extern/Eigen3/Eigen/src/Eigenvalues/MatrixBaseEigenvalues.h
- ../../extern/Eigen3/Eigen/src/Eigenvalues/RealSchur.h
- ../../extern/Eigen3/Eigen/src/Eigenvalues/RealSchur_MKL.h
- ../../extern/Eigen3/Eigen/src/Eigenvalues/SelfAdjointEigenSolver.h
- ../../extern/Eigen3/Eigen/src/Eigenvalues/SelfAdjointEigenSolver_MKL.h
- ../../extern/Eigen3/Eigen/src/Eigenvalues/Tridiagonalization.h
- ../../extern/Eigen3/Eigen/src/Geometry/AlignedBox.h
- ../../extern/Eigen3/Eigen/src/Geometry/AngleAxis.h
- ../../extern/Eigen3/Eigen/src/Geometry/EulerAngles.h
- ../../extern/Eigen3/Eigen/src/Geometry/Homogeneous.h
- ../../extern/Eigen3/Eigen/src/Geometry/Hyperplane.h
- ../../extern/Eigen3/Eigen/src/Geometry/OrthoMethods.h
- ../../extern/Eigen3/Eigen/src/Geometry/ParametrizedLine.h
- ../../extern/Eigen3/Eigen/src/Geometry/Quaternion.h
- ../../extern/Eigen3/Eigen/src/Geometry/Rotation2D.h
- ../../extern/Eigen3/Eigen/src/Geometry/RotationBase.h
- ../../extern/Eigen3/Eigen/src/Geometry/Scaling.h
- ../../extern/Eigen3/Eigen/src/Geometry/Transform.h
- ../../extern/Eigen3/Eigen/src/Geometry/Translation.h
- ../../extern/Eigen3/Eigen/src/Geometry/Umeyama.h
- ../../extern/Eigen3/Eigen/src/Geometry/arch/Geometry_SSE.h
- ../../extern/Eigen3/Eigen/src/Householder/BlockHouseholder.h
- ../../extern/Eigen3/Eigen/src/Householder/Householder.h
- ../../extern/Eigen3/Eigen/src/Householder/HouseholderSequence.h
- ../../extern/Eigen3/Eigen/src/IterativeLinearSolvers/BasicPreconditioners.h
- ../../extern/Eigen3/Eigen/src/IterativeLinearSolvers/BiCGSTAB.h
- ../../extern/Eigen3/Eigen/src/IterativeLinearSolvers/ConjugateGradient.h
- ../../extern/Eigen3/Eigen/src/IterativeLinearSolvers/IncompleteLUT.h
- ../../extern/Eigen3/Eigen/src/IterativeLinearSolvers/IterativeSolverBase.h
- ../../extern/Eigen3/Eigen/src/Jacobi/Jacobi.h
- ../../extern/Eigen3/Eigen/src/LU/Determinant.h
- ../../extern/Eigen3/Eigen/src/LU/FullPivLU.h
- ../../extern/Eigen3/Eigen/src/LU/Inverse.h
- ../../extern/Eigen3/Eigen/src/LU/PartialPivLU.h
- ../../extern/Eigen3/Eigen/src/LU/PartialPivLU_MKL.h
- ../../extern/Eigen3/Eigen/src/LU/arch/Inverse_SSE.h
- ../../extern/Eigen3/Eigen/src/misc/blas.h
- ../../extern/Eigen3/Eigen/src/misc/Image.h
- ../../extern/Eigen3/Eigen/src/misc/Kernel.h
- ../../extern/Eigen3/Eigen/src/misc/Solve.h
- ../../extern/Eigen3/Eigen/src/misc/SparseSolve.h
- ../../extern/Eigen3/Eigen/src/OrderingMethods/Amd.h
- ../../extern/Eigen3/Eigen/src/PardisoSupport/PardisoSupport.h
- ../../extern/Eigen3/Eigen/src/PaStiXSupport/PaStiXSupport.h
- ../../extern/Eigen3/Eigen/src/plugins/ArrayCwiseBinaryOps.h
- ../../extern/Eigen3/Eigen/src/plugins/ArrayCwiseUnaryOps.h
- ../../extern/Eigen3/Eigen/src/plugins/BlockMethods.h
- ../../extern/Eigen3/Eigen/src/plugins/CommonCwiseBinaryOps.h
- ../../extern/Eigen3/Eigen/src/plugins/CommonCwiseUnaryOps.h
- ../../extern/Eigen3/Eigen/src/plugins/MatrixCwiseBinaryOps.h
- ../../extern/Eigen3/Eigen/src/plugins/MatrixCwiseUnaryOps.h
- ../../extern/Eigen3/Eigen/src/QR/ColPivHouseholderQR.h
- ../../extern/Eigen3/Eigen/src/QR/ColPivHouseholderQR_MKL.h
- ../../extern/Eigen3/Eigen/src/QR/FullPivHouseholderQR.h
- ../../extern/Eigen3/Eigen/src/QR/HouseholderQR.h
- ../../extern/Eigen3/Eigen/src/QR/HouseholderQR_MKL.h
- ../../extern/Eigen3/Eigen/src/SparseCholesky/SimplicialCholesky.h
- ../../extern/Eigen3/Eigen/src/SparseCore/AmbiVector.h
- ../../extern/Eigen3/Eigen/src/SparseCore/CompressedStorage.h
- ../../extern/Eigen3/Eigen/src/SparseCore/ConservativeSparseSparseProduct.h
- ../../extern/Eigen3/Eigen/src/SparseCore/CoreIterators.h
- ../../extern/Eigen3/Eigen/src/SparseCore/MappedSparseMatrix.h
- ../../extern/Eigen3/Eigen/src/SparseCore/SparseAssign.h
- ../../extern/Eigen3/Eigen/src/SparseCore/SparseBlock.h
- ../../extern/Eigen3/Eigen/src/SparseCore/SparseCwiseBinaryOp.h
- ../../extern/Eigen3/Eigen/src/SparseCore/SparseCwiseUnaryOp.h
- ../../extern/Eigen3/Eigen/src/SparseCore/SparseDenseProduct.h
- ../../extern/Eigen3/Eigen/src/SparseCore/SparseDiagonalProduct.h
- ../../extern/Eigen3/Eigen/src/SparseCore/SparseDot.h
- ../../extern/Eigen3/Eigen/src/SparseCore/SparseFuzzy.h
- ../../extern/Eigen3/Eigen/src/SparseCore/SparseMatrix.h
- ../../extern/Eigen3/Eigen/src/SparseCore/SparseMatrixBase.h
- ../../extern/Eigen3/Eigen/src/SparseCore/SparsePermutation.h
- ../../extern/Eigen3/Eigen/src/SparseCore/SparseProduct.h
- ../../extern/Eigen3/Eigen/src/SparseCore/SparseRedux.h
- ../../extern/Eigen3/Eigen/src/SparseCore/SparseSelfAdjointView.h
- ../../extern/Eigen3/Eigen/src/SparseCore/SparseSparseProductWithPruning.h
- ../../extern/Eigen3/Eigen/src/SparseCore/SparseTranspose.h
- ../../extern/Eigen3/Eigen/src/SparseCore/SparseTriangularView.h
- ../../extern/Eigen3/Eigen/src/SparseCore/SparseUtil.h
- ../../extern/Eigen3/Eigen/src/SparseCore/SparseVector.h
- ../../extern/Eigen3/Eigen/src/SparseCore/SparseView.h
- ../../extern/Eigen3/Eigen/src/SparseCore/TriangularSolver.h
- ../../extern/Eigen3/Eigen/src/StlSupport/details.h
- ../../extern/Eigen3/Eigen/src/StlSupport/StdDeque.h
- ../../extern/Eigen3/Eigen/src/StlSupport/StdList.h
- ../../extern/Eigen3/Eigen/src/StlSupport/StdVector.h
- ../../extern/Eigen3/Eigen/src/SuperLUSupport/SuperLUSupport.h
- ../../extern/Eigen3/Eigen/src/SVD/JacobiSVD.h
- ../../extern/Eigen3/Eigen/src/SVD/JacobiSVD_MKL.h
- ../../extern/Eigen3/Eigen/src/SVD/UpperBidiagonalization.h
- ../../extern/Eigen3/Eigen/src/UmfPackSupport/UmfPackSupport.h
+ ${EIGEN3_HEADERS}
)
+unset(EIGEN3_HEADERS)
blender_add_lib(bf_intern_itasc "${SRC}" "${INC}" "${INC_SYS}")
diff --git a/intern/locale/CMakeLists.txt b/intern/locale/CMakeLists.txt
index 217fe9a8c71..6896702fcbf 100644
--- a/intern/locale/CMakeLists.txt
+++ b/intern/locale/CMakeLists.txt
@@ -36,6 +36,13 @@ set(SRC
boost_locale_wrapper.h
)
+if(APPLE)
+ # Cocoa code to read the locale on OSX
+ list(APPEND SRC
+ osx_user_locale.mm
+ )
+endif()
+
if(WITH_HEADLESS)
add_definitions(-DWITH_HEADLESS)
endif()
@@ -56,6 +63,12 @@ blender_add_lib(bf_intern_locale "${SRC}" "${INC}" "${INC_SYS}")
# -----------------------------------------------------------------------------
# Build msgfmt executable
+
+if(CMAKE_COMPILER_IS_GNUCC)
+ # workaroud ld.gold linker bug
+ string(REPLACE "-fuse-ld=gold" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
+endif()
+
set(MSFFMT_SRC
msgfmt.cc
)
diff --git a/intern/locale/SConscript b/intern/locale/SConscript
index 24828c120ec..02b4d6cda1b 100644
--- a/intern/locale/SConscript
+++ b/intern/locale/SConscript
@@ -29,6 +29,10 @@ Import('env')
sources = env.Glob('*.cpp')
+if env['OURPLATFORM'] in ['darwin']:
+ # Cocoa code to read user locale on OSX
+ sources.append('osx_user_locale.mm')
+
incs = '.'
defs = []
diff --git a/intern/locale/boost_locale_wrapper.cpp b/intern/locale/boost_locale_wrapper.cpp
index 25843d60578..5eb2f7fe9d9 100644
--- a/intern/locale/boost_locale_wrapper.cpp
+++ b/intern/locale/boost_locale_wrapper.cpp
@@ -65,8 +65,7 @@ void bl_locale_set(const char *locale)
}
else {
#if defined(__APPLE__) && !defined(WITH_HEADLESS) && !defined(WITH_GHOST_SDL)
- extern char GHOST_user_locale[128]; // pulled from Ghost_SystemCocoa
- std::string locale_osx = GHOST_user_locale + std::string(".UTF-8");
+ std::string locale_osx = osx_user_locale() + std::string(".UTF-8");
_locale = gen(locale_osx.c_str());
#else
_locale = gen("");
diff --git a/intern/locale/boost_locale_wrapper.h b/intern/locale/boost_locale_wrapper.h
index ff3645a5983..f7bc7b45eb6 100644
--- a/intern/locale/boost_locale_wrapper.h
+++ b/intern/locale/boost_locale_wrapper.h
@@ -42,7 +42,11 @@ void bl_locale_init(const char *messages_path, const char *default_domain);
void bl_locale_set(const char *locale);
const char *bl_locale_get(void);
const char *bl_locale_pgettext(const char *msgctxt, const char *msgid);
-
+
+#if defined(__APPLE__) && !defined(WITH_HEADLESS) && !defined(WITH_GHOST_SDL)
+const char* osx_user_locale(void);
+#endif
+
#ifdef __cplusplus
}
#endif
diff --git a/intern/locale/msgfmt.cc b/intern/locale/msgfmt.cc
index 17720adfa48..4779450bd1b 100644
--- a/intern/locale/msgfmt.cc
+++ b/intern/locale/msgfmt.cc
@@ -228,7 +228,7 @@ void make(const char *input_file_name,
}
// Record a fuzzy mark.
if (starts_with(l, "#,") && l.find("fuzzy") != std::string::npos) {
- fuzzy = 1;
+ fuzzy = true;
}
// Skip comments
if (l[0] == '#') {
@@ -316,6 +316,12 @@ void make(const char *input_file_name,
// Skip empty lines.
l = trim(l);
if (l.empty()) {
+ if (section == SECTION_STR) {
+ add(msgctxt, msgid, msgstr, fuzzy);
+ msgctxt = msgid = msgstr = "";
+ section = SECTION_NONE;
+ fuzzy = false;
+ }
continue;
}
l = unescape(l);
diff --git a/intern/locale/osx_user_locale.mm b/intern/locale/osx_user_locale.mm
new file mode 100644
index 00000000000..1ed33bb1713
--- /dev/null
+++ b/intern/locale/osx_user_locale.mm
@@ -0,0 +1,22 @@
+#include "boost_locale_wrapper.h"
+
+#import <Cocoa/Cocoa.h>
+
+#include <cstdlib>
+
+static char* user_locale = NULL;
+
+// get current locale
+const char* osx_user_locale()
+{
+ ::free(user_locale);
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+ CFLocaleRef myCFLocale = CFLocaleCopyCurrent();
+ NSLocale * myNSLocale = (NSLocale *) myCFLocale;
+ [myNSLocale autorelease];
+ NSString *nsIdentifier = [myNSLocale localeIdentifier];
+ user_locale = ::strdup([nsIdentifier UTF8String]);
+ [pool drain];
+
+ return user_locale;
+}
diff --git a/intern/memutil/MEM_CacheLimiter.h b/intern/memutil/MEM_CacheLimiter.h
index bbe6ace2456..d5a44375885 100644
--- a/intern/memutil/MEM_CacheLimiter.h
+++ b/intern/memutil/MEM_CacheLimiter.h
@@ -29,20 +29,22 @@
#define __MEM_CACHELIMITER_H__
/**
- * @section MEM_CacheLimiter
+ * \section MEM_CacheLimiter
* This class defines a generic memory cache management system
* to limit memory usage to a fixed global maximum.
*
- * Please use the C-API in MEM_CacheLimiterC-Api.h for code written in C.
+ * \note Please use the C-API in MEM_CacheLimiterC-Api.h for code written in C.
*
* Usage example:
*
+ * \code{.cpp}
* class BigFatImage {
* public:
* ~BigFatImage() { tell_everyone_we_are_gone(this); }
* };
*
- * void doit() {
+ * void doit()
+ * {
* MEM_Cache<BigFatImage> BigFatImages;
*
* MEM_Cache_Handle<BigFatImage>* h = BigFatImages.insert(new BigFatImage);
@@ -50,11 +52,12 @@
* BigFatImages.enforce_limits();
* h->ref();
*
- * work with image...
+ * // work with image...
*
* h->unref();
*
- * leave image in cache.
+ * // leave image in cache.
+ * \endcode
*/
#include <list>
@@ -130,7 +133,7 @@ private:
T * data;
int refcount;
- typename std::list<MEM_CacheLimiterHandle<T> *, MEM_Allocator<MEM_CacheLimiterHandle<T> *> >::iterator me;
+ int pos;
MEM_CacheLimiter<T> * parent;
};
@@ -146,29 +149,32 @@ public:
}
~MEM_CacheLimiter() {
- for (iterator it = queue.begin(); it != queue.end(); it++) {
- delete *it;
+ int i;
+ for (i = 0; i < queue.size(); i++) {
+ delete queue[i];
}
}
MEM_CacheLimiterHandle<T> *insert(T * elem) {
queue.push_back(new MEM_CacheLimiterHandle<T>(elem, this));
- iterator it = queue.end();
- --it;
- queue.back()->me = it;
+ queue.back()->pos = queue.size() - 1;
return queue.back();
}
void unmanage(MEM_CacheLimiterHandle<T> *handle) {
- queue.erase(handle->me);
+ int pos = handle->pos;
+ queue[pos] = queue.back();
+ queue[pos]->pos = pos;
+ queue.pop_back();
delete handle;
}
size_t 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());
+ int i;
+ for (i = 0; i < queue.size(); i++) {
+ size += data_size_func(queue[i]->get()->get_data());
}
}
else {
@@ -226,11 +232,11 @@ public:
* least priority element anyway.
*/
if (item_priority_func == NULL) {
+ queue[handle->pos] = queue.back();
+ queue[handle->pos]->pos = handle->pos;
+ queue.pop_back();
queue.push_back(handle);
- queue.erase(handle->me);
- iterator it = queue.end();
- --it;
- handle->me = it;
+ handle->pos = queue.size() - 1;
}
}
@@ -244,7 +250,7 @@ public:
private:
typedef MEM_CacheLimiterHandle<T> *MEM_CacheElementPtr;
- typedef std::list<MEM_CacheElementPtr, MEM_Allocator<MEM_CacheElementPtr> > MEM_CacheQueue;
+ typedef std::vector<MEM_CacheElementPtr, MEM_Allocator<MEM_CacheElementPtr> > MEM_CacheQueue;
typedef typename MEM_CacheQueue::iterator iterator;
/* Check whether element can be destroyed when enforcing cache limits */
@@ -277,11 +283,10 @@ private:
}
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;
+ for (i = 0; i < queue.size(); i++) {
+ MEM_CacheElementPtr elem = queue[i];
if (!can_destroy_element(elem))
continue;
diff --git a/intern/memutil/MEM_CacheLimiterC-Api.h b/intern/memutil/MEM_CacheLimiterC-Api.h
index ce7782e3183..0fe5469a4d4 100644
--- a/intern/memutil/MEM_CacheLimiterC-Api.h
+++ b/intern/memutil/MEM_CacheLimiterC-Api.h
@@ -134,7 +134,7 @@ void MEM_CacheLimiter_unref(MEM_CacheLimiterHandleC *handle);
/**
* Get reference counter.
*
- * @param This "This" pointer, handle of object
+ * @param handle of object
*/
int MEM_CacheLimiter_get_refcount(MEM_CacheLimiterHandleC *handle);
diff --git a/intern/memutil/MEM_RefCountPtr.h b/intern/memutil/MEM_RefCountPtr.h
index da10e689fbf..ea865eadd47 100644
--- a/intern/memutil/MEM_RefCountPtr.h
+++ b/intern/memutil/MEM_RefCountPtr.h
@@ -30,9 +30,9 @@
*/
/**
- * @file MEM_RefCountPtr.h
+ * \file MEM_RefCountPtr.h
* Declaration of MEM_RefCounted and MEM_RefCountable classes.
- * @author Laurence
+ * \author Laurence
*/
#ifndef __MEM_REFCOUNTPTR_H__
@@ -41,7 +41,7 @@
#include <stdlib.h> // for NULL !
/**
- * @section MEM_RefCountable
+ * \section MEM_RefCountable
* This is a base class for reference countable objects.
* If you want an object to be shared using a reference
* counted system derrivce from this class. All subclasses
@@ -50,9 +50,9 @@
* defining a static New() method that returns a ref counted
* ptr to a new()ly allocated instance.
*
- * @section Example subclass
- *
+ * \section Example subclass
*
+ * \code{.cpp}
* class MySharedObject : public MEM_RefCountable {
*
* private :
@@ -68,6 +68,7 @@
*
* // other member functions
* };
+ * \endcode
*
* Alternitively you may first wish to define a fully functional
* class and then define a reference counting wrapper for this class.
@@ -75,6 +76,8 @@
* counting.
*
* E.g.
+ *
+ * \code{.cpp}
* class UsefullClass {
* private :
* ...
@@ -108,7 +111,7 @@
* // mechanism to handle object lifetime.
* ~RcUsefullClass();
* };
- *
+ * \endcode
*
*/
@@ -168,7 +171,7 @@ public :
};
/**
- * @section MEM_RefCountPtr
+ * \section MEM_RefCountPtr
*/
template
diff --git a/intern/memutil/MEM_RefCounted.h b/intern/memutil/MEM_RefCounted.h
index 9da0103f6a3..88eaccf9732 100644
--- a/intern/memutil/MEM_RefCounted.h
+++ b/intern/memutil/MEM_RefCounted.h
@@ -41,7 +41,7 @@
* An object with reference counting.
* Base class for objects with reference counting.
* When a shared object is ceated, it has reference count == 1.
- * If the the reference count of a shared object reaches zero, the object self-destructs.
+ * If the reference count of a shared object reaches zero, the object self-destructs.
* The default destructor of this object has been made protected on purpose.
* This disables the creation of shared objects on the stack.
*
@@ -72,7 +72,7 @@ public:
/**
* Decreases the reference count of this object.
- * If the the reference count reaches zero, the object self-destructs.
+ * If the reference count reaches zero, the object self-destructs.
* @return the new reference count.
*/
inline virtual int decRef();
diff --git a/intern/memutil/MEM_RefCountedC-Api.h b/intern/memutil/MEM_RefCountedC-Api.h
index a611482a991..79b0b6efb66 100644
--- a/intern/memutil/MEM_RefCountedC-Api.h
+++ b/intern/memutil/MEM_RefCountedC-Api.h
@@ -64,7 +64,7 @@ extern int MEM_RefCountedIncRef(MEM_TRefCountedObjectPtr shared);
/**
* Decreases the reference count of this object.
- * If the the reference count reaches zero, the object self-destructs.
+ * If the reference count reaches zero, the object self-destructs.
* @param shared The object to query.
* @return The new reference count.
*/
diff --git a/intern/memutil/MEM_SmartPtr.h b/intern/memutil/MEM_SmartPtr.h
index dd19aae9db9..e0d7b81290f 100644
--- a/intern/memutil/MEM_SmartPtr.h
+++ b/intern/memutil/MEM_SmartPtr.h
@@ -43,7 +43,7 @@
/**
- * @section MEM_SmartPtr
+ * \section MEM_SmartPtr
* This class defines a smart pointer similar to that defined in
* the Standard Template Library but without the painful get()
* semantics to access the internal c style pointer.
@@ -58,8 +58,9 @@
* should not be shared. This is not reliably enforceable in C++
* but this class attempts to make the 1-1 relationship clear.
*
- * @section Example usage
+ * \section Example usage
*
+ * \code{.cpp}
* class foo {
* ...constructors accessors etc.
* int x[1000];
@@ -86,18 +87,21 @@
* private :
* MEM_SmartPtr<foo> m_foo;
* }
+ * \endcode
*
* You may also safely construct vectors of MEM_SmartPtrs and
* have the vector own stuff you put into it.
*
* e.g.
+ * \code{.cpp}
* {
- * std::vector<MEM_SmartPtr<foo> > foo_vector;
- * foo_vector.push_back( new foo());
- * foo_vector.push_back( new foo());
+ * std::vector<MEM_SmartPtr<foo> > foo_vector;
+ * foo_vector.push_back( new foo());
+ * foo_vector.push_back( new foo());
*
- * foo_vector[0]->bla();
+ * foo_vector[0]->bla();
* } // foo_vector out of scope => heap memory freed for both foos
+ * \endcode
*
* @warning this class should only be used for objects created
* on the heap via the new function. It will not behave correctly
diff --git a/intern/opencolorio/CMakeLists.txt b/intern/opencolorio/CMakeLists.txt
index 3a139dc64cf..61a8d995f40 100644
--- a/intern/opencolorio/CMakeLists.txt
+++ b/intern/opencolorio/CMakeLists.txt
@@ -25,6 +25,7 @@
set(INC
.
+ ../glew-mx
../guardedalloc
../../source/blender/blenlib
)
@@ -44,9 +45,10 @@ set(SRC
if(WITH_OPENCOLORIO)
add_definitions(
-DWITH_OCIO
- -DGLEW_STATIC
)
+ add_definitions(${GL_DEFINITIONS})
+
list(APPEND INC_SYS
${OPENCOLORIO_INCLUDE_DIRS}
${GLEW_INCLUDE_PATH}
diff --git a/intern/opencolorio/SConscript b/intern/opencolorio/SConscript
index 70aa9000719..6be6a5ed90c 100644
--- a/intern/opencolorio/SConscript
+++ b/intern/opencolorio/SConscript
@@ -30,12 +30,15 @@ Import('env')
sources = env.Glob('*.cc')
incs = '. ../guardedalloc ../../source/blender/blenlib'
-defs = [ 'GLEW_STATIC' ]
+defs = []
+
+defs += env['BF_GL_DEFINITIONS']
if env['WITH_BF_OCIO']:
defs.append('WITH_OCIO')
incs += ' ' + env['BF_OCIO_INC']
- incs += ' ' + '#/extern/glew/include'
+ incs += ' ' + env['BF_GLEW_INC']
+ incs += ' ' + '#/intern/glew-mx'
if env['OURPLATFORM'] in ('win32-vc', 'win64-vc'):
incs += ' ' + env['BF_BOOST_INC']
diff --git a/intern/opencolorio/fallback_impl.cc b/intern/opencolorio/fallback_impl.cc
index d1493cb3ad5..1124e7fd8ab 100644
--- a/intern/opencolorio/fallback_impl.cc
+++ b/intern/opencolorio/fallback_impl.cc
@@ -162,6 +162,19 @@ const char *FallbackImpl::configGetDisplayColorSpaceName(OCIO_ConstConfigRcPtr *
return "sRGB";
}
+void FallbackImpl::configGetDefaultLumaCoefs(OCIO_ConstConfigRcPtr * /*config*/, float *rgb)
+{
+ /* Here we simply use the older Blender assumed primaries of
+ * ITU-BT.709 / sRGB, or 0.2126729 0.7151522 0.0721750. Brute
+ * force stupid, but only plausible option given no color management
+ * system in place.
+ */
+
+ rgb[0] = 0.2126f;
+ rgb[1] = 0.7152f;
+ rgb[2] = 0.0722f;
+}
+
int FallbackImpl::configGetNumLooks(OCIO_ConstConfigRcPtr * /*config*/)
{
return 0;
@@ -177,7 +190,7 @@ OCIO_ConstLookRcPtr *FallbackImpl::configGetLook(OCIO_ConstConfigRcPtr * /*confi
return NULL;
}
-const char *FallbackImpl::lookGetProcessSpace(OCIO_ConstLookRcPtr *look)
+const char *FallbackImpl::lookGetProcessSpace(OCIO_ConstLookRcPtr * /*look*/)
{
return NULL;
}
diff --git a/intern/opencolorio/ocio_capi.cc b/intern/opencolorio/ocio_capi.cc
index a4f2db456e8..7a0b9faa5fc 100644
--- a/intern/opencolorio/ocio_capi.cc
+++ b/intern/opencolorio/ocio_capi.cc
@@ -132,6 +132,11 @@ const char *OCIO_configGetDisplayColorSpaceName(OCIO_ConstConfigRcPtr *config, c
return impl->configGetDisplayColorSpaceName(config, display, view);
}
+void OCIO_configGetDefaultLumaCoefs(OCIO_ConstConfigRcPtr *config, float *rgb)
+{
+ impl->configGetDefaultLumaCoefs(config, rgb);
+}
+
int OCIO_configGetNumLooks(OCIO_ConstConfigRcPtr *config)
{
return impl->configGetNumLooks(config);
diff --git a/intern/opencolorio/ocio_capi.h b/intern/opencolorio/ocio_capi.h
index d667dece62a..52a86727902 100644
--- a/intern/opencolorio/ocio_capi.h
+++ b/intern/opencolorio/ocio_capi.h
@@ -140,6 +140,8 @@ int OCIO_configGetNumViews(OCIO_ConstConfigRcPtr *config, const char *di
const char *OCIO_configGetView(OCIO_ConstConfigRcPtr *config, const char *display, int index);
const char *OCIO_configGetDisplayColorSpaceName(OCIO_ConstConfigRcPtr *config, const char *display, const char *view);
+void OCIO_configGetDefaultLumaCoefs(OCIO_ConstConfigRcPtr *config, float *rgb);
+
int OCIO_configGetNumLooks(OCIO_ConstConfigRcPtr *config);
const char *OCIO_configGetLookNameByIndex(OCIO_ConstConfigRcPtr *config, int index);
OCIO_ConstLookRcPtr *OCIO_configGetLook(OCIO_ConstConfigRcPtr *config, const char *name);
diff --git a/intern/opencolorio/ocio_impl.cc b/intern/opencolorio/ocio_impl.cc
index 663ca2d1c75..bf5590077ef 100644
--- a/intern/opencolorio/ocio_impl.cc
+++ b/intern/opencolorio/ocio_impl.cc
@@ -29,13 +29,6 @@
#include <sstream>
#include <string.h>
-#ifdef __APPLE__
-#include <OpenGL/gl.h>
-#include <OpenGL/glu.h>
-#else
-#include <GL/glew.h>
-#endif
-
#include <OpenColorIO/OpenColorIO.h>
using namespace OCIO_NAMESPACE;
@@ -279,6 +272,16 @@ const char *OCIOImpl::configGetDisplayColorSpaceName(OCIO_ConstConfigRcPtr *conf
return NULL;
}
+void OCIOImpl::configGetDefaultLumaCoefs(OCIO_ConstConfigRcPtr *config, float *rgb)
+{
+ try {
+ (*(ConstConfigRcPtr *) config)->getDefaultLumaCoefs(rgb);
+ }
+ catch (Exception &exception) {
+ OCIO_reportException(exception);
+ }
+}
+
int OCIOImpl::configGetNumLooks(OCIO_ConstConfigRcPtr *config)
{
try {
diff --git a/intern/opencolorio/ocio_impl.h b/intern/opencolorio/ocio_impl.h
index 47e6d829902..f086bbb1a26 100644
--- a/intern/opencolorio/ocio_impl.h
+++ b/intern/opencolorio/ocio_impl.h
@@ -58,6 +58,8 @@ public:
virtual const char *configGetView(OCIO_ConstConfigRcPtr *config, const char *display, int index) = 0;
virtual const char *configGetDisplayColorSpaceName(OCIO_ConstConfigRcPtr *config, const char *display, const char *view) = 0;
+ virtual void configGetDefaultLumaCoefs(OCIO_ConstConfigRcPtr *config, float *rgb) = 0;
+
virtual int configGetNumLooks(OCIO_ConstConfigRcPtr *config) = 0;
virtual const char *configGetLookNameByIndex(OCIO_ConstConfigRcPtr *config, int index) = 0;
virtual OCIO_ConstLookRcPtr *configGetLook(OCIO_ConstConfigRcPtr *config, const char *name) = 0;
@@ -145,6 +147,8 @@ public:
const char *configGetView(OCIO_ConstConfigRcPtr *config, const char *display, int index);
const char *configGetDisplayColorSpaceName(OCIO_ConstConfigRcPtr *config, const char *display, const char *view);
+ void configGetDefaultLumaCoefs(OCIO_ConstConfigRcPtr *config, float *rgb);
+
int configGetNumLooks(OCIO_ConstConfigRcPtr *config);
const char *configGetLookNameByIndex(OCIO_ConstConfigRcPtr *config, int index);
OCIO_ConstLookRcPtr *configGetLook(OCIO_ConstConfigRcPtr *config, const char *name);
@@ -233,6 +237,8 @@ public:
const char *configGetView(OCIO_ConstConfigRcPtr *config, const char *display, int index);
const char *configGetDisplayColorSpaceName(OCIO_ConstConfigRcPtr *config, const char *display, const char *view);
+ void configGetDefaultLumaCoefs(OCIO_ConstConfigRcPtr *config, float *rgb);
+
int configGetNumLooks(OCIO_ConstConfigRcPtr *config);
const char *configGetLookNameByIndex(OCIO_ConstConfigRcPtr *config, int index);
OCIO_ConstLookRcPtr *configGetLook(OCIO_ConstConfigRcPtr *config, const char *name);
diff --git a/intern/opencolorio/ocio_impl_glsl.cc b/intern/opencolorio/ocio_impl_glsl.cc
index 677be0bf9ed..de89ea72f3c 100644
--- a/intern/opencolorio/ocio_impl_glsl.cc
+++ b/intern/opencolorio/ocio_impl_glsl.cc
@@ -37,7 +37,7 @@
#include <sstream>
#include <string.h>
-#include <GL/glew.h>
+#include "glew-mx.h"
#include <OpenColorIO/OpenColorIO.h>
@@ -260,7 +260,7 @@ bool OCIOImpl::setupGLSLDraw(OCIO_GLSLDrawState **state_r, OCIO_ConstProcessorRc
*state_r = allocateOpenGLState();
state = *state_r;
- glGetIntegerv(GL_TEXTURE_2D, &state->last_texture);
+ glGetIntegerv(GL_TEXTURE_BINDING_2D, &state->last_texture);
glGetIntegerv(GL_ACTIVE_TEXTURE, &state->last_texture_unit);
if (!ensureLUT3DAllocated(state)) {
diff --git a/intern/opennl/superlu/heap_relax_snode.c b/intern/opennl/superlu/heap_relax_snode.c
index d4b3e229224..cd88179bbb7 100644
--- a/intern/opennl/superlu/heap_relax_snode.c
+++ b/intern/opennl/superlu/heap_relax_snode.c
@@ -99,7 +99,7 @@ heap_relax_snode (
}
j++;
/* Search for a new leaf */
- while ( descendants[j] != 0 && j < n ) j++;
+ while ( j < n && descendants[j] != 0 ) j++;
}
#if ( PRNTlevel>=1 )
diff --git a/intern/opennl/superlu/relax_snode.c b/intern/opennl/superlu/relax_snode.c
index 49f600533a8..4a9265e0fde 100644
--- a/intern/opennl/superlu/relax_snode.c
+++ b/intern/opennl/superlu/relax_snode.c
@@ -66,7 +66,7 @@ relax_snode (
relax_end[snode_start] = j; /* Last column is recorded */
j++;
/* Search for a new leaf */
- while ( descendants[j] != 0 && j < n ) j++;
+ while ( j < n && descendants[j] != 0 ) j++;
}
/*printf("No of relaxed snodes: %d; relaxed columns: %d\n",
diff --git a/intern/opennl/superlu/smemory.c b/intern/opennl/superlu/smemory.c
index a76f60a1758..c3b28a90e62 100644
--- a/intern/opennl/superlu/smemory.c
+++ b/intern/opennl/superlu/smemory.c
@@ -483,7 +483,7 @@ void
else lword = sizeof(double);
if ( Glu->MemModel == SYSTEM ) {
- new_mem = (void *) SUPERLU_MALLOC(new_len * lword);
+ new_mem = (void *) SUPERLU_MALLOC((size_t)new_len * (size_t)lword);
/* new_mem = (void *) calloc(new_len, lword); */
if ( no_expand != 0 ) {
tries = 0;
@@ -494,7 +494,7 @@ void
if ( ++tries > 10 ) return (NULL);
alpha = Reduce(alpha);
new_len = alpha * *prev_len;
- new_mem = (void *) SUPERLU_MALLOC(new_len * lword);
+ new_mem = (void *) SUPERLU_MALLOC((size_t)new_len * (size_t)lword);
/* new_mem = (void *) calloc(new_len, lword); */
}
}
@@ -509,7 +509,7 @@ void
} else { /* MemModel == USER */
if ( no_expand == 0 ) {
- new_mem = suser_malloc(new_len * lword, HEAD);
+ new_mem = suser_malloc((size_t)new_len * (size_t)lword, HEAD);
if ( NotDoubleAlign(new_mem) &&
(type == LUSUP || type == UCOL) ) {
old_mem = new_mem;
diff --git a/intern/opensubdiv/CMakeLists.txt b/intern/opensubdiv/CMakeLists.txt
new file mode 100644
index 00000000000..a4dfe339728
--- /dev/null
+++ b/intern/opensubdiv/CMakeLists.txt
@@ -0,0 +1,94 @@
+# ***** 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): Sergey Sharybin.
+#
+# ***** END GPL LICENSE BLOCK *****
+
+set(INC
+ .
+ ../guardedalloc
+)
+
+set(INC_SYS
+ ${OPENSUBDIV_INCLUDE_DIR}
+ ${GLEW_INCLUDE_PATH}
+)
+
+set(SRC
+ opensubdiv_capi.cc
+ opensubdiv_converter.cc
+ opensubdiv_device_context_cuda.cc
+ opensubdiv_device_context_opencl.cc
+ opensubdiv_evaluator_capi.cc
+ opensubdiv_gpu_capi.cc
+ opensubdiv_utils_capi.cc
+
+ opensubdiv_capi.h
+ opensubdiv_converter_capi.h
+ opensubdiv_device_context_cuda.h
+ opensubdiv_device_context_opencl.h
+ opensubdiv_intern.h
+)
+
+if(WITH_SUBSURF_WERROR)
+ ADD_CHECK_C_COMPILER_FLAG(CMAKE_C_FLAGS C_WERROR -Werror)
+ ADD_CHECK_CXX_COMPILER_FLAG(CMAKE_CXX_FLAGS C_WERROR -Werror)
+endif()
+
+macro(OPENSUBDIV_DEFINE_COMPONENT component)
+ if(${${component}})
+ add_definitions(-D${component})
+ endif()
+endmacro()
+
+OPENSUBDIV_DEFINE_COMPONENT(OPENSUBDIV_HAS_OPENMP)
+# TODO(sergey): OpenCL is not tested and totally unstable atm.
+# OPENSUBDIV_DEFINE_COMPONENT(OPENSUBDIV_HAS_OPENCL)
+# TODO(sergey): CUDA stays disabled for util it's ported to drievr API.
+# OPENSUBDIV_DEFINE_COMPONENT(OPENSUBDIV_HAS_CUDA)
+OPENSUBDIV_DEFINE_COMPONENT(OPENSUBDIV_HAS_GLSL_TRANSFORM_FEEDBACK)
+OPENSUBDIV_DEFINE_COMPONENT(OPENSUBDIV_HAS_GLSL_COMPUTE)
+
+data_to_c_simple(gpu_shader_opensubd_display.glsl SRC)
+
+add_definitions(-DGLEW_STATIC)
+
+if(WIN32)
+ add_definitions(-DNOMINMAX)
+endif()
+
+# TODO(sergey): Put CUEW back when CUDA is officially supported by OSD.
+#if(OPENSUBDIV_HAS_CUDA)
+# list(APPEND INC
+# ../../extern/cuew/include
+# )
+# add_definitions(-DOPENSUBDIV_HAS_CUEW)
+#endif()
+
+if(OPENSUBDIV_HAS_OPENCL)
+ list(APPEND INC
+ ../../extern/clew/include
+ )
+ add_definitions(-DOPENSUBDIV_HAS_CLEW)
+endif()
+
+blender_add_lib(bf_intern_opensubdiv "${SRC}" "${INC}" "${INC_SYS}")
diff --git a/intern/opensubdiv/SConscript b/intern/opensubdiv/SConscript
new file mode 100644
index 00000000000..0532bae1c29
--- /dev/null
+++ b/intern/opensubdiv/SConscript
@@ -0,0 +1,69 @@
+#!/usr/bin/env python
+#
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# The Original Code is Copyright (C) 2013, Blender Foundation
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): Sergey Sharybin.
+#
+# ***** END GPL LICENSE BLOCK *****
+
+import os
+
+Import('env')
+
+sources = env.Glob('*.cc')
+
+defs = [ 'GLEW_STATIC' ]
+
+if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'linuxcross', 'win64-vc', 'win64-mingw'):
+ defs += [ 'NOMINMAX' ]
+
+incs = '. ../guardedalloc #extern/clew/include/'
+incs += ' ' + env['BF_OPENSUBDIV_INC']
+incs += ' #/extern/glew/include'
+
+def checkOpenSubdivHeaderDefine(header, define):
+ include_path = Dir(env.subst(env['BF_OPENSUBDIV_INC'])).abspath
+ header_path = os.path.join(include_path, 'opensubdiv', 'osd', header)
+ if os.path.exists(header_path):
+ defs.append(define)
+ return True
+ return False
+
+checkOpenSubdivHeaderDefine("tbbEvaluator.h", 'OPENSUBDIV_HAS_TBB')
+#if checkOpenSubdivHeaderDefine("clEvaluator.h", 'OPENSUBDIV_HAS_OPENCL'):
+# defs += ['OPENSUBDIV_HAS_CLEW']
+# incs += ' #/extern/clew/include'
+#if checkOpenSubdivHeaderDefine("cudaEvaluator.h", 'OPENSUBDIV_HAS_CUDA'):
+# defs += ['OPENSUBDIV_HAS_CUEW']
+# incs += ' #/extern/cuew/include'
+checkOpenSubdivHeaderDefine("glXFBEvaluator.h", 'OPENSUBDIV_HAS_GLSL_TRANSFORM_FEEDBACK')
+checkOpenSubdivHeaderDefine("glComputeEvaluator.h", 'OPENSUBDIV_HAS_GLSL_COMPUTE')
+
+if env['WITH_BF_LIBMV']:
+ defs += ['OPENSUBDIV_HAS_OPENMP']
+
+# generated data files
+sources.extend((
+ os.path.join(env['DATA_SOURCES'], "gpu_shader_opensubd_display.glsl.c"),
+))
+
+env.BlenderLib('bf_intern_opensubdiv', sources, Split(incs), defs, libtype=['extern','player'], priority=[10, 185])
diff --git a/intern/opensubdiv/gpu_shader_opensubd_display.glsl b/intern/opensubdiv/gpu_shader_opensubd_display.glsl
new file mode 100644
index 00000000000..e2574b5989e
--- /dev/null
+++ b/intern/opensubdiv/gpu_shader_opensubd_display.glsl
@@ -0,0 +1,333 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2014 Blender Foundation.
+ * All rights reserved.
+ *
+ * Contributor(s): Sergey Sharybin
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/* ***** Vertex shader ***** */
+
+#extension GL_EXT_geometry_shader4 : enable
+#extension GL_ARB_gpu_shader5 : enable
+#extension GL_ARB_explicit_attrib_location : require
+#extension GL_ARB_uniform_buffer_object : require
+
+struct VertexData {
+ vec4 position;
+ vec3 normal;
+ vec2 uv;
+};
+
+#ifdef VERTEX_SHADER
+
+in vec3 normal;
+in vec4 position;
+
+uniform mat4 modelViewMatrix;
+uniform mat3 normalMatrix;
+
+out block {
+ VertexData v;
+} outpt;
+
+void main()
+{
+ outpt.v.position = modelViewMatrix * position;
+ outpt.v.normal = normalize(normalMatrix * normal);
+ /* Some compilers expects gl_Position to be written.
+ * It's not needed once we explicitly switch to GLSL 1.40 or above.
+ */
+ gl_Position = outpt.v.position;
+}
+
+#endif /* VERTEX_SHADER */
+
+/* ***** geometry shader ***** */
+#ifdef GEOMETRY_SHADER
+
+#ifndef GLSL_COMPAT_WORKAROUND
+layout(lines_adjacency) in;
+#ifndef WIREFRAME
+layout(triangle_strip, max_vertices = 4) out;
+#else
+layout(line_strip, max_vertices = 8) out;
+#endif
+#endif
+
+uniform mat4 modelViewMatrix;
+uniform mat4 projectionMatrix;
+uniform int PrimitiveIdBase;
+uniform int osd_fvar_count;
+uniform int osd_active_uv_offset;
+
+in block {
+ VertexData v;
+} inpt[4];
+
+#define INTERP_FACE_VARYING_2(result, fvarOffset, tessCoord) \
+ { \
+ vec2 v[4]; \
+ int primOffset = (gl_PrimitiveID + PrimitiveIdBase) * 4; \
+ for (int i = 0; i < 4; ++i) { \
+ int index = (primOffset + i) * osd_fvar_count + fvarOffset; \
+ v[i] = vec2(texelFetch(FVarDataBuffer, index).s, \
+ texelFetch(FVarDataBuffer, index + 1).s); \
+ } \
+ result = mix(mix(v[0], v[1], tessCoord.s), \
+ mix(v[3], v[2], tessCoord.s), \
+ tessCoord.t); \
+ }
+
+uniform samplerBuffer FVarDataBuffer;
+
+out block {
+ VertexData v;
+} outpt;
+
+#ifdef FLAT_SHADING
+void emit(int index, vec3 normal)
+{
+ outpt.v.position = inpt[index].v.position;
+ outpt.v.normal = normal;
+
+ /* TODO(sergey): Only uniform subdivisions atm. */
+ vec2 quadst[4] = vec2[](vec2(0,0), vec2(1,0), vec2(1,1), vec2(0,1));
+ vec2 st = quadst[index];
+
+ INTERP_FACE_VARYING_2(outpt.v.uv, osd_active_uv_offset, st);
+
+ gl_Position = projectionMatrix * inpt[index].v.position;
+ EmitVertex();
+}
+
+# ifdef WIREFRAME
+void emit_edge(int v0, int v1, vec3 normal)
+{
+ emit(v0, normal);
+ emit(v1, normal);
+}
+# endif
+
+#else
+void emit(int index)
+{
+ outpt.v.position = inpt[index].v.position;
+ outpt.v.normal = inpt[index].v.normal;
+
+ /* TODO(sergey): Only uniform subdivisions atm. */
+ vec2 quadst[4] = vec2[](vec2(0,0), vec2(1,0), vec2(1,1), vec2(0,1));
+ vec2 st = quadst[index];
+
+ INTERP_FACE_VARYING_2(outpt.v.uv, osd_active_uv_offset, st);
+
+ gl_Position = projectionMatrix * inpt[index].v.position;
+ EmitVertex();
+}
+
+# ifdef WIREFRAME
+void emit_edge(int v0, int v1)
+{
+ emit(v0);
+ emit(v1);
+}
+# endif
+
+#endif
+
+void main()
+{
+ gl_PrimitiveID = gl_PrimitiveIDIn;
+
+#ifdef FLAT_SHADING
+ vec3 A = (inpt[0].v.position - inpt[1].v.position).xyz;
+ vec3 B = (inpt[3].v.position - inpt[1].v.position).xyz;
+ vec3 flat_normal = normalize(cross(B, A));
+# ifndef WIREFRAME
+ emit(0, flat_normal);
+ emit(1, flat_normal);
+ emit(3, flat_normal);
+ emit(2, flat_normal);
+# else
+ emit_edge(0, 1, flat_normal);
+ emit_edge(1, 2, flat_normal);
+ emit_edge(2, 3, flat_normal);
+ emit_edge(3, 0, flat_normal);
+# endif
+#else
+# ifndef WIREFRAME
+ emit(0);
+ emit(1);
+ emit(3);
+ emit(2);
+# else
+ emit_edge(0, 1);
+ emit_edge(1, 2);
+ emit_edge(2, 3);
+ emit_edge(3, 0);
+# endif
+#endif
+
+ EndPrimitive();
+}
+
+#endif /* GEOMETRY_SHADER */
+
+/* ***** Fragment shader ***** */
+#ifdef FRAGMENT_SHADER
+
+#define MAX_LIGHTS 8
+#define NUM_SOLID_LIGHTS 3
+
+struct LightSource {
+ vec4 position;
+ vec4 ambient;
+ vec4 diffuse;
+ vec4 specular;
+ vec4 spotDirection;
+#ifdef SUPPORT_COLOR_MATERIAL
+ float constantAttenuation;
+ float linearAttenuation;
+ float quadraticAttenuation;
+ float spotCutoff;
+ float spotExponent;
+ float spotCosCutoff;
+#endif
+};
+
+layout(std140) uniform Lighting {
+ LightSource lightSource[MAX_LIGHTS];
+ int num_enabled_lights;
+};
+
+uniform vec4 diffuse;
+uniform vec4 specular;
+uniform float shininess;
+
+uniform sampler2D texture_buffer;
+
+in block {
+ VertexData v;
+} inpt;
+
+void main()
+{
+#ifdef WIREFRAME
+ gl_FragColor = diffuse;
+#else
+ vec3 N = inpt.v.normal;
+
+ if (!gl_FrontFacing)
+ N = -N;
+
+ /* Compute diffuse and specular lighting. */
+ vec3 L_diffuse = vec3(0.0);
+ vec3 L_specular = vec3(0.0);
+
+#ifndef USE_COLOR_MATERIAL
+ /* Assume NUM_SOLID_LIGHTS directional lights. */
+ for (int i = 0; i < NUM_SOLID_LIGHTS; i++) {
+ vec4 Plight = lightSource[i].position;
+#ifdef USE_DIRECTIONAL_LIGHT
+ vec3 l = (Plight.w == 0.0)
+ ? normalize(Plight.xyz)
+ : normalize(inpt.v.position.xyz);
+#else /* USE_DIRECTIONAL_LIGHT */
+ /* TODO(sergey): We can normalize it outside of the shader. */
+ vec3 l = normalize(Plight.xyz);
+#endif /* USE_DIRECTIONAL_LIGHT */
+ vec3 h = normalize(l + vec3(0, 0, 1));
+ float d = max(0.0, dot(N, l));
+ float s = pow(max(0.0, dot(N, h)), shininess);
+ L_diffuse += d * lightSource[i].diffuse.rgb;
+ L_specular += s * lightSource[i].specular.rgb;
+ }
+#else /* USE_COLOR_MATERIAL */
+ vec3 varying_position = inpt.v.position.xyz;
+ vec3 V = (gl_ProjectionMatrix[3][3] == 0.0) ?
+ normalize(varying_position): vec3(0.0, 0.0, -1.0);
+ for (int i = 0; i < num_enabled_lights; i++) {
+ /* todo: this is a slow check for disabled lights */
+ if (lightSource[i].specular.a == 0.0)
+ continue;
+
+ float intensity = 1.0;
+ vec3 light_direction;
+
+ if (lightSource[i].position.w == 0.0) {
+ /* directional light */
+ light_direction = lightSource[i].position.xyz;
+ }
+ else {
+ /* point light */
+ vec3 d = lightSource[i].position.xyz - varying_position;
+ light_direction = normalize(d);
+
+ /* spot light cone */
+ if (lightSource[i].spotCutoff < 90.0) {
+ float cosine = max(dot(light_direction,
+ -lightSource[i].spotDirection.xyz),
+ 0.0);
+ intensity = pow(cosine, lightSource[i].spotExponent);
+ intensity *= step(lightSource[i].spotCosCutoff, cosine);
+ }
+
+ /* falloff */
+ float distance = length(d);
+
+ intensity /= lightSource[i].constantAttenuation +
+ lightSource[i].linearAttenuation * distance +
+ lightSource[i].quadraticAttenuation * distance * distance;
+ }
+
+ /* diffuse light */
+ vec3 light_diffuse = lightSource[i].diffuse.rgb;
+ float diffuse_bsdf = max(dot(N, light_direction), 0.0);
+ L_diffuse += light_diffuse*diffuse_bsdf*intensity;
+
+ /* specular light */
+ vec3 light_specular = lightSource[i].specular.rgb;
+ vec3 H = normalize(light_direction - V);
+
+ float specular_bsdf = pow(max(dot(N, H), 0.0),
+ gl_FrontMaterial.shininess);
+ L_specular += light_specular*specular_bsdf * intensity;
+ }
+#endif /* USE_COLOR_MATERIAL */
+
+ /* Compute diffuse color. */
+#ifdef USE_TEXTURE_2D
+ L_diffuse *= texture2D(texture_buffer, inpt.v.uv).rgb;
+#else
+ L_diffuse *= diffuse.rgb;
+#endif
+
+ /* Sum lighting. */
+ vec3 L = L_diffuse;
+ if (shininess != 0) {
+ L += L_specular * specular.rgb;
+ }
+
+ /* Write out fragment color. */
+ gl_FragColor = vec4(L, diffuse.a);
+#endif
+}
+
+#endif // FRAGMENT_SHADER
diff --git a/intern/opensubdiv/opensubdiv_capi.cc b/intern/opensubdiv/opensubdiv_capi.cc
new file mode 100644
index 00000000000..66598948daf
--- /dev/null
+++ b/intern/opensubdiv/opensubdiv_capi.cc
@@ -0,0 +1,323 @@
+/*
+ * ***** 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.
+ *
+ * Contributor(s): Sergey Sharybin.
+ * Brecht van Lommel
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include "opensubdiv_capi.h"
+
+#ifdef _MSC_VER
+# include "iso646.h"
+#endif
+
+#include <stdlib.h>
+#include <GL/glew.h>
+
+#include <opensubdiv/osd/glMesh.h>
+
+/* CPU Backend */
+#include <opensubdiv/osd/cpuGLVertexBuffer.h>
+#include <opensubdiv/osd/cpuEvaluator.h>
+
+#ifdef OPENSUBDIV_HAS_OPENMP
+# include <opensubdiv/osd/ompEvaluator.h>
+#endif /* OPENSUBDIV_HAS_OPENMP */
+
+#ifdef OPENSUBDIV_HAS_OPENCL
+# include <opensubdiv/osd/clGLVertexBuffer.h>
+# include <opensubdiv/osd/clEvaluator.h>
+# include "opensubdiv_device_context_opencl.h"
+#endif /* OPENSUBDIV_HAS_OPENCL */
+
+#ifdef OPENSUBDIV_HAS_CUDA
+# include <opensubdiv/osd/cudaGLVertexBuffer.h>
+# include <opensubdiv/osd/cudaEvaluator.h>
+# include "opensubdiv_device_context_cuda.h"
+#endif /* OPENSUBDIV_HAS_CUDA */
+
+#ifdef OPENSUBDIV_HAS_GLSL_TRANSFORM_FEEDBACK
+# include <opensubdiv/osd/glXFBEvaluator.h>
+# include <opensubdiv/osd/glVertexBuffer.h>
+#endif /* OPENSUBDIV_HAS_GLSL_TRANSFORM_FEEDBACK */
+
+#ifdef OPENSUBDIV_HAS_GLSL_COMPUTE
+# include <opensubdiv/osd/glComputeEvaluator.h>
+# include <opensubdiv/osd/glVertexBuffer.h>
+#endif /* OPENSUBDIV_HAS_GLSL_COMPUTE */
+
+#include <opensubdiv/osd/glPatchTable.h>
+#include <opensubdiv/far/stencilTable.h>
+
+#include "opensubdiv_intern.h"
+
+#include "MEM_guardedalloc.h"
+
+/* **************** Types declaration **************** */
+
+using OpenSubdiv::Osd::GLMeshInterface;
+using OpenSubdiv::Osd::Mesh;
+using OpenSubdiv::Osd::MeshBitset;
+using OpenSubdiv::Far::StencilTable;
+using OpenSubdiv::Osd::GLPatchTable;
+
+using OpenSubdiv::Osd::Mesh;
+
+/* CPU backend */
+using OpenSubdiv::Osd::CpuGLVertexBuffer;
+using OpenSubdiv::Osd::CpuEvaluator;
+typedef Mesh<CpuGLVertexBuffer,
+ StencilTable,
+ CpuEvaluator,
+ GLPatchTable> OsdCpuMesh;
+
+#ifdef OPENSUBDIV_HAS_OPENMP
+using OpenSubdiv::Osd::OmpEvaluator;
+typedef Mesh<CpuGLVertexBuffer,
+ StencilTable,
+ OmpEvaluator,
+ GLPatchTable> OsdOmpMesh;
+#endif /* OPENSUBDIV_HAS_OPENMP */
+
+#ifdef OPENSUBDIV_HAS_OPENCL
+using OpenSubdiv::Osd::CLEvaluator;
+using OpenSubdiv::Osd::CLGLVertexBuffer;
+using OpenSubdiv::Osd::CLStencilTable;
+/* TODO(sergey): Use CLDeviceCOntext similar to OSD examples? */
+typedef Mesh<CLGLVertexBuffer,
+ CLStencilTable,
+ CLEvaluator,
+ GLPatchTable,
+ CLDeviceContext> OsdCLMesh;
+static CLDeviceContext g_clDeviceContext;
+#endif /* OPENSUBDIV_HAS_OPENCL */
+
+#ifdef OPENSUBDIV_HAS_CUDA
+using OpenSubdiv::Osd::CudaEvaluator;
+using OpenSubdiv::Osd::CudaGLVertexBuffer;
+using OpenSubdiv::Osd::CudaStencilTable;
+typedef Mesh<CudaGLVertexBuffer,
+ CudaStencilTable,
+ CudaEvaluator,
+ GLPatchTable> OsdCudaMesh;
+static CudaDeviceContext g_cudaDeviceContext;
+#endif /* OPENSUBDIV_HAS_CUDA */
+
+#ifdef OPENSUBDIV_HAS_GLSL_TRANSFORM_FEEDBACK
+using OpenSubdiv::Osd::GLXFBEvaluator;
+using OpenSubdiv::Osd::GLStencilTableTBO;
+using OpenSubdiv::Osd::GLVertexBuffer;
+typedef Mesh<GLVertexBuffer,
+ GLStencilTableTBO,
+ GLXFBEvaluator,
+ GLPatchTable> OsdGLSLTransformFeedbackMesh;
+#endif /* OPENSUBDIV_HAS_GLSL_TRANSFORM_FEEDBACK */
+
+#ifdef OPENSUBDIV_HAS_GLSL_COMPUTE
+using OpenSubdiv::Osd::GLComputeEvaluator;
+using OpenSubdiv::Osd::GLStencilTableSSBO;
+using OpenSubdiv::Osd::GLVertexBuffer;
+typedef Mesh<GLVertexBuffer,
+ GLStencilTableSSBO,
+ GLComputeEvaluator,
+ GLPatchTable> OsdGLSLComputeMesh;
+#endif
+
+struct OpenSubdiv_GLMesh *openSubdiv_createOsdGLMeshFromTopologyRefiner(
+ OpenSubdiv_TopologyRefinerDescr *topology_refiner,
+ int evaluator_type,
+ int level,
+ int /*subdivide_uvs*/)
+{
+ using OpenSubdiv::Far::TopologyRefiner;
+
+ MeshBitset bits;
+ /* TODO(sergey): Adaptive subdivisions are not currently
+ * possible because of the lack of tessellation shader.
+ */
+ bits.set(OpenSubdiv::Osd::MeshAdaptive, 0);
+ bits.set(OpenSubdiv::Osd::MeshUseSingleCreasePatch, 0);
+ bits.set(OpenSubdiv::Osd::MeshInterleaveVarying, 1);
+ bits.set(OpenSubdiv::Osd::MeshFVarData, 1);
+ bits.set(OpenSubdiv::Osd::MeshEndCapBSplineBasis, 1);
+
+ const int num_vertex_elements = 3;
+ const int num_varying_elements = 3;
+
+ GLMeshInterface *mesh = NULL;
+ TopologyRefiner *refiner = (TopologyRefiner*)topology_refiner;
+
+ switch(evaluator_type) {
+#define CHECK_EVALUATOR_TYPE(type, class) \
+ case OPENSUBDIV_EVALUATOR_ ## type: \
+ mesh = new class(refiner, \
+ num_vertex_elements, \
+ num_varying_elements, \
+ level, \
+ bits); \
+ break;
+
+ CHECK_EVALUATOR_TYPE(CPU, OsdCpuMesh)
+
+#ifdef OPENSUBDIV_HAS_OPENMP
+ CHECK_EVALUATOR_TYPE(OPENMP, OsdOmpMesh)
+#endif
+
+#ifdef OPENSUBDIV_HAS_OPENCL
+ CHECK_EVALUATOR_TYPE(OPENCL, OsdCLMesh)
+#endif
+
+#ifdef OPENSUBDIV_HAS_CUDA
+ CHECK_EVALUATOR_TYPE(CUDA, OsdCudaMesh)
+#endif
+
+#ifdef OPENSUBDIV_HAS_GLSL_TRANSFORM_FEEDBACK
+ CHECK_EVALUATOR_TYPE(GLSL_TRANSFORM_FEEDBACK,
+ OsdGLSLTransformFeedbackMesh)
+#endif
+
+#ifdef OPENSUBDIV_HAS_GLSL_COMPUTE
+ CHECK_EVALUATOR_TYPE(GLSL_COMPUTE, OsdGLSLComputeMesh)
+#endif
+
+#undef CHECK_EVALUATOR_TYPE
+ }
+
+ if (mesh == NULL) {
+ return NULL;
+ }
+
+ OpenSubdiv_GLMesh *gl_mesh =
+ (OpenSubdiv_GLMesh *) OBJECT_GUARDED_NEW(OpenSubdiv_GLMesh);
+ gl_mesh->evaluator_type = evaluator_type;
+ gl_mesh->descriptor = (OpenSubdiv_GLMeshDescr *) mesh;
+ gl_mesh->topology_refiner = (OpenSubdiv_TopologyRefinerDescr*)refiner;
+
+ return gl_mesh;
+}
+
+void openSubdiv_deleteOsdGLMesh(struct OpenSubdiv_GLMesh *gl_mesh)
+{
+ switch (gl_mesh->evaluator_type) {
+#define CHECK_EVALUATOR_TYPE(type, class) \
+ case OPENSUBDIV_EVALUATOR_ ## type: \
+ delete (class *) gl_mesh->descriptor; \
+ break;
+
+ CHECK_EVALUATOR_TYPE(CPU, OsdCpuMesh)
+
+#ifdef OPENSUBDIV_HAS_OPENMP
+ CHECK_EVALUATOR_TYPE(OPENMP, OsdOmpMesh)
+#endif
+
+#ifdef OPENSUBDIV_HAS_OPENCL
+ CHECK_EVALUATOR_TYPE(OPENCL, OsdCLMesh)
+#endif
+
+#ifdef OPENSUBDIV_HAS_CUDA
+ CHECK_EVALUATOR_TYPE(CUDA, OsdCudaMesh)
+#endif
+
+#ifdef OPENSUBDIV_HAS_GLSL_TRANSFORM_FEEDBACK
+ CHECK_EVALUATOR_TYPE(GLSL_TRANSFORM_FEEDBACK,
+ OsdGLSLTransformFeedbackMesh)
+#endif
+
+#ifdef OPENSUBDIV_HAS_GLSL_COMPUTE
+ CHECK_EVALUATOR_TYPE(GLSL_COMPUTE, OsdGLSLComputeMesh)
+#endif
+
+#undef CHECK_EVALUATOR_TYPE
+ }
+
+ OBJECT_GUARDED_DELETE(gl_mesh, OpenSubdiv_GLMesh);
+}
+
+unsigned int openSubdiv_getOsdGLMeshPatchIndexBuffer(struct OpenSubdiv_GLMesh *gl_mesh)
+{
+ return ((GLMeshInterface *)gl_mesh->descriptor)->GetPatchTable()->GetPatchIndexBuffer();
+}
+
+unsigned int openSubdiv_getOsdGLMeshVertexBuffer(struct OpenSubdiv_GLMesh *gl_mesh)
+{
+ return ((GLMeshInterface *)gl_mesh->descriptor)->BindVertexBuffer();
+}
+
+void openSubdiv_osdGLMeshUpdateVertexBuffer(struct OpenSubdiv_GLMesh *gl_mesh,
+ const float *vertex_data,
+ int start_vertex,
+ int num_verts)
+{
+ ((GLMeshInterface *)gl_mesh->descriptor)->UpdateVertexBuffer(vertex_data,
+ start_vertex,
+ num_verts);
+}
+
+void openSubdiv_osdGLMeshRefine(struct OpenSubdiv_GLMesh *gl_mesh)
+{
+ ((GLMeshInterface *)gl_mesh->descriptor)->Refine();
+}
+
+void openSubdiv_osdGLMeshSynchronize(struct OpenSubdiv_GLMesh *gl_mesh)
+{
+ ((GLMeshInterface *)gl_mesh->descriptor)->Synchronize();
+}
+
+void openSubdiv_osdGLMeshBindVertexBuffer(OpenSubdiv_GLMesh *gl_mesh)
+{
+ ((GLMeshInterface *)gl_mesh->descriptor)->BindVertexBuffer();
+}
+
+const struct OpenSubdiv_TopologyRefinerDescr *openSubdiv_getGLMeshTopologyRefiner(
+ OpenSubdiv_GLMesh *gl_mesh)
+{
+ return gl_mesh->topology_refiner;
+}
+
+int openSubdiv_supportGPUDisplay(void)
+{
+ {
+ /* Currently Intel GPUs has hard time working on Windows.
+ *
+ * For until we've got access to a hardware which demonstrates
+ * the issue we disable OpenSubdiv on Intel GPUs.
+ */
+ static bool vendor_checked = false;
+ static bool is_intel = false;
+ if (!vendor_checked) {
+ vendor_checked = true;
+ const char *vendor = (const char *)glGetString(GL_VENDOR);
+ if (vendor != NULL && strstr(vendor, "Intel")) {
+ if(getenv("OPENSUBDIV_ALLOW_INTEL") == NULL) {
+ is_intel = true;
+ }
+ }
+ }
+ if (is_intel) {
+ return false;
+ }
+ }
+
+ return GLEW_EXT_geometry_shader4 &&
+ GLEW_ARB_gpu_shader5 &&
+ GLEW_ARB_uniform_buffer_object;
+}
diff --git a/intern/opensubdiv/opensubdiv_capi.h b/intern/opensubdiv/opensubdiv_capi.h
new file mode 100644
index 00000000000..8010c39647d
--- /dev/null
+++ b/intern/opensubdiv/opensubdiv_capi.h
@@ -0,0 +1,151 @@
+/*
+ * ***** 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.
+ *
+ * Contributor(s): Sergey Sharybin
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __OPENSUBDIV_CAPI_H__
+#define __OPENSUBDIV_CAPI_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// Types declaration.
+struct OpenSubdiv_GLMesh;
+struct OpenSubdiv_TopologyRefinerDescr;
+
+typedef struct OpenSubdiv_GLMesh OpenSubdiv_GLMesh;
+
+#ifdef __cplusplus
+struct OpenSubdiv_GLMeshDescr;
+typedef struct OpenSubdiv_GLMesh {
+ int evaluator_type;
+ OpenSubdiv_GLMeshDescr *descriptor;
+ OpenSubdiv_TopologyRefinerDescr *topology_refiner;
+} OpenSubdiv_GLMesh;
+#endif
+
+// Keep this a bitmask os it's possible to pass available
+// evaluators to Blender.
+enum {
+ OPENSUBDIV_EVALUATOR_CPU = (1 << 0),
+ OPENSUBDIV_EVALUATOR_OPENMP = (1 << 1),
+ OPENSUBDIV_EVALUATOR_OPENCL = (1 << 2),
+ OPENSUBDIV_EVALUATOR_CUDA = (1 << 3),
+ OPENSUBDIV_EVALUATOR_GLSL_TRANSFORM_FEEDBACK = (1 << 4),
+ OPENSUBDIV_EVALUATOR_GLSL_COMPUTE = (1 << 5),
+};
+
+enum {
+ OPENSUBDIV_SCHEME_CATMARK,
+ OPENSUBDIV_SCHEME_BILINEAR,
+ OPENSUBDIV_SCHEME_LOOP,
+};
+
+/* TODO(sergey): Re-name and avoid bad level data access. */
+OpenSubdiv_GLMesh *openSubdiv_createOsdGLMeshFromTopologyRefiner(
+ struct OpenSubdiv_TopologyRefinerDescr *topology_refiner,
+ int evaluator_type,
+ int level,
+ int subdivide_uvs);
+
+void openSubdiv_deleteOsdGLMesh(OpenSubdiv_GLMesh *gl_mesh);
+unsigned int openSubdiv_getOsdGLMeshPatchIndexBuffer(
+ OpenSubdiv_GLMesh *gl_mesh);
+unsigned int openSubdiv_getOsdGLMeshVertexBuffer(OpenSubdiv_GLMesh *gl_mesh);
+void openSubdiv_osdGLMeshUpdateVertexBuffer(OpenSubdiv_GLMesh *gl_mesh,
+ const float *vertex_data,
+ int start_vertex,
+ int num_verts);
+void openSubdiv_osdGLMeshRefine(OpenSubdiv_GLMesh *gl_mesh);
+void openSubdiv_osdGLMeshSynchronize(OpenSubdiv_GLMesh *gl_mesh);
+void openSubdiv_osdGLMeshBindVertexBuffer(OpenSubdiv_GLMesh *gl_mesh);
+
+const struct OpenSubdiv_TopologyRefinerDescr *openSubdiv_getGLMeshTopologyRefiner(
+ OpenSubdiv_GLMesh *gl_mesh);
+
+/* ** Initialize/Deinitialize global OpenGL drawing buffers/GLSL programs ** */
+bool openSubdiv_osdGLDisplayInit(void);
+void openSubdiv_osdGLDisplayDeinit(void);
+
+/* ** Evaluator API ** */
+
+struct OpenSubdiv_EvaluatorDescr;
+typedef struct OpenSubdiv_EvaluatorDescr OpenSubdiv_EvaluatorDescr;
+
+/* TODO(sergey): Avoid bad-level data access, */
+OpenSubdiv_EvaluatorDescr *openSubdiv_createEvaluatorDescr(
+ struct OpenSubdiv_TopologyRefinerDescr *topology_refiner,
+ int subsurf_level);
+
+void openSubdiv_deleteEvaluatorDescr(OpenSubdiv_EvaluatorDescr *evaluator_descr);
+
+void openSubdiv_setEvaluatorCoarsePositions(OpenSubdiv_EvaluatorDescr *evaluator_descr,
+ float *positions,
+ int start_vert,
+ int num_vert);
+
+void openSubdiv_setEvaluatorVaryingData(OpenSubdiv_EvaluatorDescr *evaluator_descr,
+ float *varying_data,
+ int start_vert,
+ int num_vert);
+
+void openSubdiv_evaluateLimit(OpenSubdiv_EvaluatorDescr *evaluator_descr,
+ int osd_face_index,
+ float face_u, float face_v,
+ float P[3],
+ float dPdu[3],
+ float dPdv[3]);
+
+void openSubdiv_evaluateVarying(OpenSubdiv_EvaluatorDescr *evaluator_descr,
+ int osd_face_index,
+ float face_u, float face_v,
+ float varying[3]);
+
+/* ** Actual drawing ** */
+
+/* Initialize all the invariants which stays the same for every single path,
+ * for example lighting model stays untouched for the whole mesh.
+ *
+ * TODO(sergey): Some of the stuff could be initialized once for all meshes.
+ */
+void openSubdiv_osdGLMeshDisplayPrepare(int use_osd_glsl,
+ int active_uv_index);
+
+/* Draw specified patches. */
+void openSubdiv_osdGLMeshDisplay(OpenSubdiv_GLMesh *gl_mesh,
+ int fill_quads,
+ int start_patch,
+ int num_patches);
+
+/* ** Utility functions ** */
+int openSubdiv_supportGPUDisplay(void);
+int openSubdiv_getAvailableEvaluators(void);
+void openSubdiv_init(void);
+void openSubdiv_cleanup(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // __OPENSUBDIV_CAPI_H__
diff --git a/intern/opensubdiv/opensubdiv_converter.cc b/intern/opensubdiv/opensubdiv_converter.cc
new file mode 100644
index 00000000000..3fadde68d32
--- /dev/null
+++ b/intern/opensubdiv/opensubdiv_converter.cc
@@ -0,0 +1,682 @@
+/*
+ * ***** 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) 2015 Blender Foundation.
+ * All rights reserved.
+ *
+ * Contributor(s): Sergey Sharybin.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <cstdio>
+#include <vector>
+
+#ifdef _MSC_VER
+# include "iso646.h"
+#endif
+
+#include <opensubdiv/far/topologyRefinerFactory.h>
+
+#include "opensubdiv_converter_capi.h"
+#include "opensubdiv_intern.h"
+
+#include <stack>
+
+#ifdef OPENSUBDIV_ORIENT_TOPOLOGY
+namespace {
+
+inline void reverse_face_verts(int *face_verts, int num_verts)
+{
+ int last_vert = face_verts[num_verts - 1];
+ for (int i = num_verts - 1; i > 0; --i) {
+ face_verts[i] = face_verts[i - 1];
+ }
+ face_verts[0] = last_vert;
+}
+
+} /* namespace */
+#endif /* OPENSUBDIV_ORIENT_TOPOLOGY */
+
+namespace OpenSubdiv {
+namespace OPENSUBDIV_VERSION {
+namespace Far {
+
+namespace {
+
+template <typename T>
+inline int findInArray(T array, int value)
+{
+ return (int)(std::find(array.begin(), array.end(), value) - array.begin());
+}
+
+#ifdef OPENSUBDIV_ORIENT_TOPOLOGY
+inline int get_loop_winding(int vert0_of_face, int vert1_of_face)
+{
+ int delta_face = vert1_of_face - vert0_of_face;
+ if (abs(delta_face) != 1) {
+ if (delta_face > 0) {
+ delta_face = -1;
+ }
+ else {
+ delta_face = 1;
+ }
+ }
+ return delta_face;
+}
+
+inline void reverse_face_loops(IndexArray face_verts, IndexArray face_edges)
+{
+ for (int i = 0; i < face_verts.size() / 2; ++i) {
+ int j = face_verts.size() - i - 1;
+ if (i != j) {
+ std::swap(face_verts[i], face_verts[j]);
+ std::swap(face_edges[i], face_edges[j]);
+ }
+ }
+ reverse_face_verts(&face_verts[0], face_verts.size());
+}
+
+inline void check_oriented_vert_connectivity(const int num_vert_edges,
+ const int num_vert_faces,
+ const int *vert_edges,
+ const int *vert_faces,
+ const int *dst_vert_edges,
+ const int *dst_vert_faces)
+{
+# ifndef NDEBUG
+ for (int i = 0; i < num_vert_faces; ++i) {
+ bool found = false;
+ for (int j = 0; j < num_vert_faces; ++j) {
+ if (vert_faces[i] == dst_vert_faces[j]) {
+ found = true;
+ break;
+ }
+ }
+ if (!found) {
+ assert(!"vert-faces connectivity ruined");
+ }
+ }
+ for (int i = 0; i < num_vert_edges; ++i) {
+ bool found = false;
+ for (int j = 0; j < num_vert_edges; ++j) {
+ if (vert_edges[i] == dst_vert_edges[j]) {
+ found = true;
+ break;
+ }
+ }
+ if (!found) {
+ assert(!"vert-edges connectivity ruined");
+ }
+ }
+# else
+ (void)num_vert_edges;
+ (void)num_vert_faces;
+ (void)vert_edges;
+ (void)vert_faces;
+ (void)dst_vert_edges;
+ (void)dst_vert_faces;
+# endif
+}
+#endif
+
+} /* namespace */
+
+template <>
+inline bool TopologyRefinerFactory<OpenSubdiv_Converter>::resizeComponentTopology(
+ TopologyRefiner& refiner,
+ const OpenSubdiv_Converter& conv)
+{
+ /* Faces and face-verts */
+ const int num_faces = conv.get_num_faces(&conv);
+ setNumBaseFaces(refiner, num_faces);
+ for (int face = 0; face < num_faces; ++face) {
+ const int num_verts = conv.get_num_face_verts(&conv, face);
+ setNumBaseFaceVertices(refiner, face, num_verts);
+ }
+ /* Edges and edge-faces. */
+ const int num_edges = conv.get_num_edges(&conv);
+ setNumBaseEdges(refiner, num_edges);
+ for (int edge = 0; edge < num_edges; ++edge) {
+ const int num_edge_faces = conv.get_num_edge_faces(&conv, edge);
+ setNumBaseEdgeFaces(refiner, edge, num_edge_faces);
+ }
+ /* Vertices and vert-faces and vert-edges/ */
+ const int num_verts = conv.get_num_verts(&conv);
+ setNumBaseVertices(refiner, num_verts);
+ for (int vert = 0; vert < num_verts; ++vert) {
+ const int num_vert_edges = conv.get_num_vert_edges(&conv, vert),
+ num_vert_faces = conv.get_num_vert_faces(&conv, vert);
+ setNumBaseVertexEdges(refiner, vert, num_vert_edges);
+ setNumBaseVertexFaces(refiner, vert, num_vert_faces);
+ }
+ return true;
+}
+
+template <>
+inline bool TopologyRefinerFactory<OpenSubdiv_Converter>::assignComponentTopology(
+ TopologyRefiner& refiner,
+ const OpenSubdiv_Converter& conv)
+{
+ using Far::IndexArray;
+ /* Face relations. */
+ const int num_faces = conv.get_num_faces(&conv);
+ for (int face = 0; face < num_faces; ++face) {
+ IndexArray dst_face_verts = getBaseFaceVertices(refiner, face);
+ conv.get_face_verts(&conv, face, &dst_face_verts[0]);
+ IndexArray dst_face_edges = getBaseFaceEdges(refiner, face);
+ conv.get_face_edges(&conv, face, &dst_face_edges[0]);
+ }
+ /* Edge relations. */
+ const int num_edges = conv.get_num_edges(&conv);
+ for (int edge = 0; edge < num_edges; ++edge) {
+ /* Edge-vertices */
+ IndexArray dst_edge_verts = getBaseEdgeVertices(refiner, edge);
+ conv.get_edge_verts(&conv, edge, &dst_edge_verts[0]);
+ /* Edge-faces */
+ IndexArray dst_edge_faces = getBaseEdgeFaces(refiner, edge);
+ conv.get_edge_faces(&conv, edge, &dst_edge_faces[0]);
+ }
+#ifdef OPENSUBDIV_ORIENT_TOPOLOGY
+ /* Make face normals consistent. */
+ bool *face_used = new bool[num_faces];
+ memset(face_used, 0, sizeof(bool) * num_faces);
+ std::stack<int> traverse_stack;
+ int face_start = 0, num_traversed_faces = 0;
+ /* Traverse all islands. */
+ while (num_traversed_faces != num_faces) {
+ /* Find first face of any untraversed islands. */
+ while (face_used[face_start]) {
+ ++face_start;
+ }
+ /* Add first face to the stack. */
+ traverse_stack.push(face_start);
+ face_used[face_start] = true;
+ /* Go over whole connected component. */
+ while (!traverse_stack.empty()) {
+ int face = traverse_stack.top();
+ traverse_stack.pop();
+ IndexArray face_edges = getBaseFaceEdges(refiner, face);
+ ConstIndexArray face_verts = getBaseFaceVertices(refiner, face);
+ for (int edge_index = 0; edge_index < face_edges.size(); ++edge_index) {
+ const int edge = face_edges[edge_index];
+ ConstIndexArray edge_faces = getBaseEdgeFaces(refiner, edge);
+ if (edge_faces.size() != 2) {
+ /* Can't make consistent normals for non-manifolds. */
+ continue;
+ }
+ ConstIndexArray edge_verts = getBaseEdgeVertices(refiner, edge);
+ /* Get winding of the reference face. */
+ int vert0_of_face = findInArray(face_verts, edge_verts[0]),
+ vert1_of_face = findInArray(face_verts, edge_verts[1]);
+ int delta_face = get_loop_winding(vert0_of_face, vert1_of_face);
+ for (int edge_face = 0; edge_face < edge_faces.size(); ++edge_face) {
+ int other_face = edge_faces[edge_face];
+ /* Never re-traverse faces, only move forward. */
+ if (face_used[other_face]) {
+ continue;
+ }
+ IndexArray other_face_verts = getBaseFaceVertices(refiner,
+ other_face);
+ int vert0_of_other_face = findInArray(other_face_verts,
+ edge_verts[0]),
+ vert1_of_other_face = findInArray(other_face_verts,
+ edge_verts[1]);
+ int delta_other_face = get_loop_winding(vert0_of_other_face,
+ vert1_of_other_face);
+ if (delta_face * delta_other_face > 0) {
+ IndexArray other_face_verts = getBaseFaceVertices(refiner,
+ other_face),
+ other_face_edges = getBaseFaceEdges(refiner,
+ other_face);
+ reverse_face_loops(other_face_verts,
+ other_face_edges);
+ }
+ traverse_stack.push(other_face);
+ face_used[other_face] = true;
+ }
+ }
+ ++num_traversed_faces;
+ }
+ }
+#endif /* OPENSUBDIV_ORIENT_TOPOLOGY */
+ /* Vertex relations */
+ const int num_verts = conv.get_num_verts(&conv);
+ for (int vert = 0; vert < num_verts; ++vert) {
+
+ /* Vert-Faces */
+ IndexArray dst_vert_faces = getBaseVertexFaces(refiner, vert);
+ int num_vert_faces = conv.get_num_vert_faces(&conv, vert);
+ int *vert_faces = new int[num_vert_faces];
+ conv.get_vert_faces(&conv, vert, vert_faces);
+ /* Vert-Edges */
+ IndexArray dst_vert_edges = getBaseVertexEdges(refiner, vert);
+ int num_vert_edges = conv.get_num_vert_edges(&conv, vert);
+ int *vert_edges = new int[num_vert_edges];
+ conv.get_vert_edges(&conv, vert, vert_edges);
+#ifdef OPENSUBDIV_ORIENT_TOPOLOGY
+ /* ** Order vertex edges and faces in a CCW order. ** */
+ memset(face_used, 0, sizeof(bool) * num_faces);
+ /* Number of edges and faces added to the ordered array. */
+ int edge_count_ordered = 0, face_count_ordered = 0;
+ /* Add loose edges straight into the edges array. */
+ bool has_fan_connections = false;
+ for (int i = 0; i < num_vert_edges; ++i) {
+ IndexArray edge_faces = getBaseEdgeFaces(refiner, vert_edges[i]);
+ if (edge_faces.size() == 0) {
+ dst_vert_edges[edge_count_ordered++] = vert_edges[i];
+ }
+ else if (edge_faces.size() > 2) {
+ has_fan_connections = true;
+ }
+ }
+ if (has_fan_connections) {
+ /* OpenSubdiv currently doesn't give us clues how to handle
+ * fan face connections. and since handling such connections
+ * complicates the loop below we simply don't do special
+ * orientation for them.
+ */
+ memcpy(&dst_vert_edges[0], vert_edges, sizeof(int) * num_vert_edges);
+ memcpy(&dst_vert_faces[0], vert_faces, sizeof(int) * num_vert_faces);
+ delete [] vert_edges;
+ delete [] vert_faces;
+ continue;
+ }
+ /* Perform at max numbder of vert-edges iteration and try to avoid
+ * deadlock here for malformed mesh.
+ */
+ for (int global_iter = 0; global_iter < num_vert_edges; ++global_iter) {
+ /* Numbr of edges and faces which are still to be ordered. */
+ int num_vert_edges_remained = num_vert_edges - edge_count_ordered,
+ num_vert_faces_remained = num_vert_faces - face_count_ordered;
+ if (num_vert_edges_remained == 0 && num_vert_faces_remained == 0) {
+ /* All done, nothing to do anymore. */
+ break;
+ }
+ /* Face, edge and face-vertex inndex to start traversal from. */
+ int face_start = -1, edge_start = -1, face_vert_start = -1;
+ if (num_vert_edges_remained == num_vert_faces_remained) {
+ /* Vertex is eitehr complete manifold or is connected to seevral
+ * manifold islands (hourglass-like configuration), can pick up
+ * random edge unused and start from it.
+ */
+ /* TODO(sergey): Start from previous edge from which traversal
+ * began at previous iteration.
+ */
+ for (int i = 0; i < num_vert_edges; ++i) {
+ face_start = vert_faces[i];
+ if (!face_used[face_start]) {
+ ConstIndexArray
+ face_verts = getBaseFaceVertices(refiner, face_start),
+ face_edges = getBaseFaceEdges(refiner, face_start);
+ face_vert_start = findInArray(face_verts, vert);
+ edge_start = face_edges[face_vert_start];
+ break;
+ }
+ }
+ }
+ else {
+ /* Special handle of non-manifold vertex. */
+ for (int i = 0; i < num_vert_edges; ++i) {
+ bool start_found = false;
+ edge_start = vert_edges[i];
+ IndexArray edge_faces = getBaseEdgeFaces(refiner, edge_start);
+ if (edge_faces.size() == 1) {
+ face_start = edge_faces[0];
+ if (!face_used[face_start]) {
+ ConstIndexArray
+ face_verts = getBaseFaceVertices(refiner, face_start),
+ face_edges = getBaseFaceEdges(refiner, face_start);
+ face_vert_start = findInArray(face_verts, vert);
+ if (edge_start == face_edges[face_vert_start]) {
+ start_found = true;
+ break;
+ }
+ }
+ }
+ if (start_found) {
+ break;
+ }
+ /* Reset indices for sanity check below. */
+ face_start = edge_start = face_vert_start = -1;
+ }
+ }
+ /* Sanity check. */
+ assert(face_start != -1 &&
+ edge_start != -1 &&
+ face_vert_start != -1);
+ /* Traverse faces starting from the current one. */
+ int edge_first = edge_start;
+ dst_vert_faces[face_count_ordered++] = face_start;
+ dst_vert_edges[edge_count_ordered++] = edge_start;
+ face_used[face_start] = true;
+ while (edge_count_ordered < num_vert_edges) {
+ IndexArray face_verts = getBaseFaceVertices(refiner, face_start);
+ IndexArray face_edges = getBaseFaceEdges(refiner, face_start);
+ int face_edge_start = face_vert_start;
+ int face_edge_next = (face_edge_start > 0) ? (face_edge_start - 1) : (face_verts.size() - 1);
+ Index edge_next = face_edges[face_edge_next];
+ if (edge_next == edge_first) {
+ /* Multiple manifolds found, stop for now and handle rest
+ * in the next iteration.
+ */
+ break;
+ }
+ dst_vert_edges[edge_count_ordered++] = edge_next;
+ if (face_count_ordered < num_vert_faces) {
+ IndexArray edge_faces = getBaseEdgeFaces(refiner, edge_next);
+ assert(edge_faces.size() != 0);
+ if (edge_faces.size() == 1) {
+ assert(edge_faces[0] == face_start);
+ break;
+ }
+ else if (edge_faces.size() != 2) {
+ break;
+ }
+ assert(edge_faces.size() == 2);
+ face_start = edge_faces[(edge_faces[0] == face_start) ? 1 : 0];
+ face_vert_start = findInArray(getBaseFaceEdges(refiner, face_start), edge_next);
+ dst_vert_faces[face_count_ordered++] = face_start;
+ face_used[face_start] = true;
+ }
+ edge_start = edge_next;
+ }
+ }
+ /* Verify ordering doesn't ruin connectivity information. */
+ assert(face_count_ordered == num_vert_faces);
+ assert(edge_count_ordered == num_vert_edges);
+ check_oriented_vert_connectivity(num_vert_edges,
+ num_vert_faces,
+ vert_edges,
+ vert_faces,
+ &dst_vert_edges[0],
+ &dst_vert_faces[0]);
+ /* For the release builds we're failing mesh construction so instead
+ * of nasty bugs the unsupported mesh will simply disappear from the
+ * viewport.
+ */
+ if (face_count_ordered != num_vert_faces ||
+ edge_count_ordered != num_vert_edges)
+ {
+ delete [] vert_edges;
+ delete [] vert_faces;
+ return false;
+ }
+#else /* OPENSUBDIV_ORIENT_TOPOLOGY */
+ memcpy(&dst_vert_edges[0], vert_edges, sizeof(int) * num_vert_edges);
+ memcpy(&dst_vert_faces[0], vert_faces, sizeof(int) * num_vert_faces);
+#endif /* OPENSUBDIV_ORIENT_TOPOLOGY */
+ delete [] vert_edges;
+ delete [] vert_faces;
+ }
+#ifdef OPENSUBDIV_ORIENT_TOPOLOGY
+ delete [] face_used;
+#endif
+ populateBaseLocalIndices(refiner);
+ return true;
+};
+
+template <>
+inline bool TopologyRefinerFactory<OpenSubdiv_Converter>::assignComponentTags(
+ TopologyRefiner& refiner,
+ const OpenSubdiv_Converter& conv)
+{
+ typedef OpenSubdiv::Sdc::Crease Crease;
+
+ int num_edges = conv.get_num_edges(&conv);
+ for (int edge = 0; edge < num_edges; ++edge) {
+ float sharpness;
+ ConstIndexArray edge_faces = getBaseEdgeFaces(refiner, edge);
+ if (edge_faces.size() == 2) {
+ sharpness = conv.get_edge_sharpness(&conv, edge);
+ }
+ else {
+ /* Non-manifold edges must be sharp. */
+ sharpness = Crease::SHARPNESS_INFINITE;
+ }
+ setBaseEdgeSharpness(refiner, edge, sharpness);
+ }
+
+ /* OpenSubdiv expects non-manifold vertices to be sharp but at the
+ * time it handles correct cases when vertex is a corner of plane.
+ * Currently mark verts which are adjacent to a loose edge as sharp,
+ * but this decision needs some more investigation.
+ */
+ int num_vert = conv.get_num_verts(&conv);
+ for (int vert = 0; vert < num_vert; ++vert) {
+ ConstIndexArray vert_edges = getBaseVertexEdges(refiner, vert);
+ for (int edge_index = 0; edge_index < vert_edges.size(); ++edge_index) {
+ int edge = vert_edges[edge_index];
+ ConstIndexArray edge_faces = getBaseEdgeFaces(refiner, edge);
+ if (edge_faces.size() == 0) {
+ setBaseVertexSharpness(refiner, vert, Crease::SHARPNESS_INFINITE);
+ break;
+ }
+ }
+ if (vert_edges.size() == 2) {
+ int edge0 = vert_edges[0],
+ edge1 = vert_edges[1];
+ float sharpness0 = conv.get_edge_sharpness(&conv, edge0),
+ sharpness1 = conv.get_edge_sharpness(&conv, edge1);
+ float sharpness = std::min(sharpness0, sharpness1);
+ setBaseVertexSharpness(refiner, vert, sharpness);
+ }
+ }
+
+ return true;
+}
+
+template <>
+inline void TopologyRefinerFactory<OpenSubdiv_Converter>::reportInvalidTopology(
+ TopologyError /*errCode*/,
+ const char *msg,
+ const OpenSubdiv_Converter& /*mesh*/)
+{
+ printf("OpenSubdiv Error: %s\n", msg);
+}
+
+} /* namespace Far */
+} /* namespace OPENSUBDIV_VERSION */
+} /* namespace OpenSubdiv */
+
+namespace {
+
+OpenSubdiv::Sdc::SchemeType get_capi_scheme_type(OpenSubdiv_SchemeType type)
+{
+ switch(type) {
+ case OSD_SCHEME_BILINEAR:
+ return OpenSubdiv::Sdc::SCHEME_BILINEAR;
+ case OSD_SCHEME_CATMARK:
+ return OpenSubdiv::Sdc::SCHEME_CATMARK;
+ case OSD_SCHEME_LOOP:
+ return OpenSubdiv::Sdc::SCHEME_LOOP;
+ }
+ assert(!"Unknown sceme type passed via C-API");
+ return OpenSubdiv::Sdc::SCHEME_CATMARK;
+}
+
+} /* namespace */
+
+struct OpenSubdiv_TopologyRefinerDescr *openSubdiv_createTopologyRefinerDescr(
+ OpenSubdiv_Converter *converter)
+{
+ typedef OpenSubdiv::Sdc::Options Options;
+
+ using OpenSubdiv::Far::TopologyRefinerFactory;
+ OpenSubdiv::Sdc::SchemeType scheme_type =
+ get_capi_scheme_type(converter->get_type(converter));
+ Options options;
+ options.SetVtxBoundaryInterpolation(Options::VTX_BOUNDARY_EDGE_ONLY);
+ options.SetCreasingMethod(Options::CREASE_UNIFORM);
+ options.SetFVarLinearInterpolation(Options::FVAR_LINEAR_ALL);
+
+ TopologyRefinerFactory<OpenSubdiv_Converter>::Options
+ topology_options(scheme_type, options);
+#ifdef OPENSUBDIV_VALIDATE_TOPOLOGY
+ topology_options.validateFullTopology = true;
+#endif
+ /* We don't use guarded allocation here so we can re-use the refiner
+ * for GL mesh creation directly.
+ */
+ return (struct OpenSubdiv_TopologyRefinerDescr*)
+ TopologyRefinerFactory<OpenSubdiv_Converter>::Create(
+ *converter,
+ topology_options);
+}
+
+void openSubdiv_deleteTopologyRefinerDescr(
+ OpenSubdiv_TopologyRefinerDescr *topology_refiner)
+{
+ delete (OpenSubdiv::Far::TopologyRefiner *)topology_refiner;
+}
+
+int openSubdiv_topologyRefinerGetSubdivLevel(
+ const OpenSubdiv_TopologyRefinerDescr *topology_refiner)
+{
+ using OpenSubdiv::Far::TopologyRefiner;
+ const TopologyRefiner *refiner = (const TopologyRefiner *)topology_refiner;
+ return refiner->GetMaxLevel();
+}
+
+int openSubdiv_topologyRefinerGetNumVerts(
+ const OpenSubdiv_TopologyRefinerDescr *topology_refiner)
+{
+ using OpenSubdiv::Far::TopologyLevel;
+ using OpenSubdiv::Far::TopologyRefiner;
+ const TopologyRefiner *refiner = (const TopologyRefiner *)topology_refiner;
+ const TopologyLevel &base_level = refiner->GetLevel(0);
+ return base_level.GetNumVertices();
+}
+
+int openSubdiv_topologyRefinerGetNumEdges(
+ const OpenSubdiv_TopologyRefinerDescr *topology_refiner)
+{
+ using OpenSubdiv::Far::TopologyLevel;
+ using OpenSubdiv::Far::TopologyRefiner;
+ const TopologyRefiner *refiner = (const TopologyRefiner *)topology_refiner;
+ const TopologyLevel &base_level = refiner->GetLevel(0);
+ return base_level.GetNumEdges();
+}
+
+int openSubdiv_topologyRefinerGetNumFaces(
+ const OpenSubdiv_TopologyRefinerDescr *topology_refiner)
+{
+ using OpenSubdiv::Far::TopologyLevel;
+ using OpenSubdiv::Far::TopologyRefiner;
+ const TopologyRefiner *refiner = (const TopologyRefiner *)topology_refiner;
+ const TopologyLevel &base_level = refiner->GetLevel(0);
+ return base_level.GetNumFaces();
+}
+
+int openSubdiv_topologyRefinerGetNumFaceVerts(
+ const OpenSubdiv_TopologyRefinerDescr *topology_refiner,
+ int face)
+{
+ using OpenSubdiv::Far::TopologyLevel;
+ using OpenSubdiv::Far::TopologyRefiner;
+ const TopologyRefiner *refiner = (const TopologyRefiner *)topology_refiner;
+ const TopologyLevel &base_level = refiner->GetLevel(0);
+ return base_level.GetFaceVertices(face).size();
+}
+
+int openSubdiv_topologyRefnerCompareConverter(
+ const OpenSubdiv_TopologyRefinerDescr *topology_refiner,
+ OpenSubdiv_Converter *converter)
+{
+ using OpenSubdiv::Far::ConstIndexArray;
+ using OpenSubdiv::Far::TopologyRefiner;
+ using OpenSubdiv::Far::TopologyLevel;
+ const TopologyRefiner *refiner = (const TopologyRefiner *)topology_refiner;
+ const TopologyLevel &base_level = refiner->GetLevel(0);
+ const int num_verts = base_level.GetNumVertices();
+ const int num_edges = base_level.GetNumEdges();
+ const int num_faces = base_level.GetNumFaces();
+ /* Quick preliminary check. */
+ OpenSubdiv::Sdc::SchemeType scheme_type =
+ get_capi_scheme_type(converter->get_type(converter));
+ if (scheme_type != refiner->GetSchemeType()) {
+ return false;
+ }
+ if (converter->get_num_verts(converter) != num_verts ||
+ converter->get_num_edges(converter) != num_edges ||
+ converter->get_num_faces(converter) != num_faces)
+ {
+ return false;
+ }
+ /* Compare all edges. */
+ for (int edge = 0; edge < num_edges; ++edge) {
+ ConstIndexArray edge_verts = base_level.GetEdgeVertices(edge);
+ int conv_edge_verts[2];
+ converter->get_edge_verts(converter, edge, conv_edge_verts);
+ if (conv_edge_verts[0] != edge_verts[0] ||
+ conv_edge_verts[1] != edge_verts[1])
+ {
+ return false;
+ }
+ }
+ /* Compare all faces. */
+ std::vector<int> conv_face_verts;
+ for (int face = 0; face < num_faces; ++face) {
+ ConstIndexArray face_verts = base_level.GetFaceVertices(face);
+ if (face_verts.size() != converter->get_num_face_verts(converter,
+ face))
+ {
+ return false;
+ }
+ conv_face_verts.resize(face_verts.size());
+ converter->get_face_verts(converter, face, &conv_face_verts[0]);
+ bool direct_match = true;
+ for (int i = 0; i < face_verts.size(); ++i) {
+ if (conv_face_verts[i] != face_verts[i]) {
+ direct_match = false;
+ break;
+ }
+ }
+ if (!direct_match) {
+ /* If face didn't match in direct direction we also test if it
+ * matches in reversed direction. This is because conversion might
+ * reverse loops to make normals consistent.
+ */
+#ifdef OPENSUBDIV_ORIENT_TOPOLOGY
+ reverse_face_verts(&conv_face_verts[0], conv_face_verts.size());
+ for (int i = 0; i < face_verts.size(); ++i) {
+ if (conv_face_verts[i] != face_verts[i]) {
+ return false;
+ }
+ }
+#else
+ return false;
+#endif
+ }
+ }
+ /* Compare sharpness. */
+ for (int edge = 0; edge < num_edges; ++edge) {
+ ConstIndexArray edge_faces = base_level.GetEdgeFaces(edge);
+ float sharpness = base_level.GetEdgeSharpness(edge);
+ float conv_sharpness;
+ if (edge_faces.size() == 2) {
+ conv_sharpness = converter->get_edge_sharpness(converter, edge);
+ }
+ else {
+ conv_sharpness = OpenSubdiv::Sdc::Crease::SHARPNESS_INFINITE;
+ }
+ if (sharpness != conv_sharpness) {
+ return false;
+ }
+ }
+ return true;
+}
diff --git a/intern/opensubdiv/opensubdiv_converter_capi.h b/intern/opensubdiv/opensubdiv_converter_capi.h
new file mode 100644
index 00000000000..ac1e8301a42
--- /dev/null
+++ b/intern/opensubdiv/opensubdiv_converter_capi.h
@@ -0,0 +1,124 @@
+/*
+ * ***** 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) 2015 Blender Foundation.
+ * All rights reserved.
+ *
+ * Contributor(s): Sergey Sharybin.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __OPENSUBDIV_CONVERTER_CAPI_H__
+#define __OPENSUBDIV_CONVERTER_CAPI_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct OpenSubdiv_TopologyRefinerDescr;
+typedef struct OpenSubdiv_TopologyRefinerDescr OpenSubdiv_TopologyRefinerDescr;
+
+typedef struct OpenSubdiv_Converter OpenSubdiv_Converter;
+
+typedef enum OpenSubdiv_SchemeType {
+ OSD_SCHEME_BILINEAR,
+ OSD_SCHEME_CATMARK,
+ OSD_SCHEME_LOOP,
+} OpenSubdiv_SchemeType;
+
+typedef struct OpenSubdiv_Converter {
+ /* TODO(sergey): Needs to be implemented. */
+ /* OpenSubdiv::Sdc::Options get_options() const; */
+
+ OpenSubdiv_SchemeType (*get_type)(const OpenSubdiv_Converter *converter);
+
+ int (*get_num_faces)(const OpenSubdiv_Converter *converter);
+ int (*get_num_edges)(const OpenSubdiv_Converter *converter);
+ int (*get_num_verts)(const OpenSubdiv_Converter *converter);
+
+ /* Face relationships. */
+ int (*get_num_face_verts)(const OpenSubdiv_Converter *converter,
+ int face);
+ void (*get_face_verts)(const OpenSubdiv_Converter *converter,
+ int face,
+ int *face_verts);
+ void (*get_face_edges)(const OpenSubdiv_Converter *converter,
+ int face,
+ int *face_edges);
+
+ /* Edge relationships. */
+ void (*get_edge_verts)(const OpenSubdiv_Converter *converter,
+ int edge,
+ int *edge_verts);
+ int (*get_num_edge_faces)(const OpenSubdiv_Converter *converter,
+ int edge);
+ void (*get_edge_faces)(const OpenSubdiv_Converter *converter,
+ int edge,
+ int *edge_faces);
+ float (*get_edge_sharpness)(const OpenSubdiv_Converter *converter,
+ int edge);
+
+ /* Vertex relationships. */
+ int (*get_num_vert_edges)(const OpenSubdiv_Converter *converter, int vert);
+ void (*get_vert_edges)(const OpenSubdiv_Converter *converter,
+ int vert,
+ int *vert_edges);
+ int (*get_num_vert_faces)(const OpenSubdiv_Converter *converter, int vert);
+ void (*get_vert_faces)(const OpenSubdiv_Converter *converter,
+ int vert,
+ int *vert_faces);
+
+ void (*free_user_data)(const OpenSubdiv_Converter *converter);
+ void *user_data;
+} OpenSubdiv_Converter;
+
+OpenSubdiv_TopologyRefinerDescr *openSubdiv_createTopologyRefinerDescr(
+ OpenSubdiv_Converter *converter);
+
+void openSubdiv_deleteTopologyRefinerDescr(
+ OpenSubdiv_TopologyRefinerDescr *topology_refiner);
+
+/* TODO(sergey): Those calls are not strictly related on conversion.
+ * needs some dedicated file perhaps.
+ */
+
+int openSubdiv_topologyRefinerGetSubdivLevel(
+ const OpenSubdiv_TopologyRefinerDescr *topology_refiner);
+
+int openSubdiv_topologyRefinerGetNumVerts(
+ const OpenSubdiv_TopologyRefinerDescr *topology_refiner);
+
+int openSubdiv_topologyRefinerGetNumEdges(
+ const OpenSubdiv_TopologyRefinerDescr *topology_refiner);
+
+int openSubdiv_topologyRefinerGetNumFaces(
+ const OpenSubdiv_TopologyRefinerDescr *topology_refiner);
+
+int openSubdiv_topologyRefinerGetNumFaceVerts(
+ const OpenSubdiv_TopologyRefinerDescr *topology_refiner,
+ int face);
+
+int openSubdiv_topologyRefnerCompareConverter(
+ const OpenSubdiv_TopologyRefinerDescr *topology_refiner,
+ OpenSubdiv_Converter *converter);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __OPENSUBDIV_CONVERTER_CAPI_H__ */
diff --git a/intern/opensubdiv/opensubdiv_device_context_cuda.cc b/intern/opensubdiv/opensubdiv_device_context_cuda.cc
new file mode 100644
index 00000000000..81c52f5d6cf
--- /dev/null
+++ b/intern/opensubdiv/opensubdiv_device_context_cuda.cc
@@ -0,0 +1,237 @@
+/*
+ * Adopted from OpenSubdiv with the following license:
+ *
+ * Copyright 2015 Pixar
+ *
+ * Licensed under the Apache License, Version 2.0 (the "Apache License")
+ * with the following modification; you may not use this file except in
+ * compliance with the Apache License and the following modification to it:
+ * Section 6. Trademarks. is deleted and replaced with:
+ *
+ * 6. Trademarks. This License does not grant permission to use the trade
+ * names, trademarks, service marks, or product names of the Licensor
+ * and its affiliates, except as required to comply with Section 4(c) of
+ * the License and to reproduce the content of the NOTICE file.
+ *
+ * You may obtain a copy of the Apache License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Apache License with the above modification is
+ * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the Apache License for the specific
+ * language governing permissions and limitations under the Apache License.
+ */
+
+#ifdef OPENSUBDIV_HAS_CUDA
+
+#ifdef _MSC_VER
+# include "iso646.h"
+#endif
+
+#include "opensubdiv_device_context_cuda.h"
+
+#if defined(_WIN32)
+# include <windows.h>
+#elif defined(__APPLE__)
+# include <OpenGL/OpenGL.h>
+#else
+# include <X11/Xlib.h>
+# include <GL/glx.h>
+#endif
+
+#include <cstdio>
+#include <algorithm>
+#include <cuda.h>
+#include <cuda_runtime_api.h>
+#include <cuda_gl_interop.h>
+
+#define message(fmt, ...)
+//#define message(fmt, ...) fprintf(stderr, fmt, __VA_ARGS__)
+#define error(fmt, ...) fprintf(stderr, fmt, __VA_ARGS__)
+
+static int _GetCudaDeviceForCurrentGLContext()
+{
+ // Find and use the CUDA device for the current GL context
+ unsigned int interopDeviceCount = 0;
+ int interopDevices[1];
+ cudaError_t status = cudaGLGetDevices(&interopDeviceCount, interopDevices,
+ 1, cudaGLDeviceListCurrentFrame);
+ if (status == cudaErrorNoDevice or interopDeviceCount != 1) {
+ message("CUDA no interop devices found.\n");
+ return 0;
+ }
+ int device = interopDevices[0];
+
+#if defined(_WIN32)
+ return device;
+
+#elif defined(__APPLE__)
+ return device;
+
+#else // X11
+ Display * display = glXGetCurrentDisplay();
+ int screen = DefaultScreen(display);
+ if (device != screen) {
+ error("The CUDA interop device (%d) does not match "
+ "the screen used by the current GL context (%d), "
+ "which may cause slow performance on systems "
+ "with multiple GPU devices.", device, screen);
+ }
+ message("CUDA init using device for current GL context: %d\n", device);
+ return device;
+#endif
+}
+
+/* From "NVIDIA GPU Computing SDK 4.2/C/common/inc/cutil_inline_runtime.h": */
+
+/* Beginning of GPU Architecture definitions */
+inline int _ConvertSMVer2Cores_local(int major, int minor)
+{
+ /* Defines for GPU Architecture types (using the SM version to determine
+ * the # of cores per SM
+ */
+ typedef struct {
+ int SM; /* 0xMm (hexidecimal notation),
+ * M = SM Major version,
+ * and m = SM minor version
+ */
+ int Cores;
+ } sSMtoCores;
+
+ sSMtoCores nGpuArchCoresPerSM[] =
+ { { 0x10, 8 }, /* Tesla Generation (SM 1.0) G80 class */
+ { 0x11, 8 }, /* Tesla Generation (SM 1.1) G8x class */
+ { 0x12, 8 }, /* Tesla Generation (SM 1.2) G9x class */
+ { 0x13, 8 }, /* Tesla Generation (SM 1.3) GT200 class */
+ { 0x20, 32 }, /* Fermi Generation (SM 2.0) GF100 class */
+ { 0x21, 48 }, /* Fermi Generation (SM 2.1) GF10x class */
+ { 0x30, 192}, /* Fermi Generation (SM 3.0) GK10x class */
+ { -1, -1 }
+ };
+
+ int index = 0;
+ while (nGpuArchCoresPerSM[index].SM != -1) {
+ if (nGpuArchCoresPerSM[index].SM == ((major << 4) + minor)) {
+ return nGpuArchCoresPerSM[index].Cores;
+ }
+ index++;
+ }
+ printf("MapSMtoCores undefined SMversion %d.%d!\n", major, minor);
+ return -1;
+}
+/* End of GPU Architecture definitions. */
+
+/* This function returns the best GPU (with maximum GFLOPS) */
+inline int cutGetMaxGflopsDeviceId()
+{
+ int current_device = 0, sm_per_multiproc = 0;
+ int max_compute_perf = 0, max_perf_device = -1;
+ int device_count = 0, best_SM_arch = 0;
+ int compat_major, compat_minor;
+
+ cuDeviceGetCount(&device_count);
+ /* Find the best major SM Architecture GPU device. */
+ while (current_device < device_count) {
+ cuDeviceComputeCapability(&compat_major, &compat_minor, current_device);
+ if (compat_major > 0 && compat_major < 9999) {
+ best_SM_arch = std::max(best_SM_arch, compat_major);
+ }
+ current_device++;
+ }
+
+ /* Find the best CUDA capable GPU device. */
+ current_device = 0;
+ while (current_device < device_count) {
+ cuDeviceComputeCapability(&compat_major, &compat_minor, current_device);
+ if (compat_major == 9999 && compat_minor == 9999) {
+ sm_per_multiproc = 1;
+ } else {
+ sm_per_multiproc = _ConvertSMVer2Cores_local(compat_major,
+ compat_minor);
+ }
+ int multi_processor_count;
+ cuDeviceGetAttribute(&multi_processor_count,
+ CU_DEVICE_ATTRIBUTE_MULTIPROCESSOR_COUNT,
+ current_device);
+ int clock_rate;
+ cuDeviceGetAttribute(&clock_rate,
+ CU_DEVICE_ATTRIBUTE_CLOCK_RATE,
+ current_device);
+ int compute_perf = multi_processor_count * sm_per_multiproc * clock_rate;
+ if (compute_perf > max_compute_perf) {
+ /* If we find GPU with SM major > 2, search only these */
+ if (best_SM_arch > 2) {
+ /* If our device==dest_SM_arch, choose this, or else pass. */
+ if (compat_major == best_SM_arch) {
+ max_compute_perf = compute_perf;
+ max_perf_device = current_device;
+ }
+ } else {
+ max_compute_perf = compute_perf;
+ max_perf_device = current_device;
+ }
+ }
+ ++current_device;
+ }
+ return max_perf_device;
+}
+
+bool CudaDeviceContext::HAS_CUDA_VERSION_4_0()
+{
+#ifdef OPENSUBDIV_HAS_CUDA
+ static bool cudaInitialized = false;
+ static bool cudaLoadSuccess = true;
+ if (!cudaInitialized) {
+ cudaInitialized = true;
+
+# ifdef OPENSUBDIV_HAS_CUEW
+ cudaLoadSuccess = cuewInit() == CUEW_SUCCESS;
+ if (!cudaLoadSuccess) {
+ fprintf(stderr, "Loading CUDA failed.\n");
+ }
+# endif
+ // Need to initialize CUDA here so getting device
+ // with the maximum FPLOS works fine.
+ if (cuInit(0) == CUDA_SUCCESS) {
+ // This is to deal with cases like NVidia Optimus,
+ // when there might be CUDA library installed but
+ // NVidia card is not being active.
+ if (cutGetMaxGflopsDeviceId() < 0) {
+ cudaLoadSuccess = false;
+ }
+ }
+ else {
+ cudaLoadSuccess = false;
+ }
+ }
+ return cudaLoadSuccess;
+#else
+ return false;
+#endif
+}
+
+CudaDeviceContext::CudaDeviceContext()
+ : _initialized(false) {
+}
+
+CudaDeviceContext::~CudaDeviceContext() {
+ cudaDeviceReset();
+}
+
+bool CudaDeviceContext::Initialize()
+{
+ /* See if any cuda device is available. */
+ int deviceCount = 0;
+ cudaGetDeviceCount(&deviceCount);
+ message("CUDA device count: %d\n", deviceCount);
+ if (deviceCount <= 0) {
+ return false;
+ }
+ cudaGLSetGLDevice(_GetCudaDeviceForCurrentGLContext());
+ _initialized = true;
+ return true;
+}
+
+#endif /* OPENSUBDIV_HAS_CUDA */
diff --git a/intern/opensubdiv/opensubdiv_device_context_cuda.h b/intern/opensubdiv/opensubdiv_device_context_cuda.h
new file mode 100644
index 00000000000..eb30b76f507
--- /dev/null
+++ b/intern/opensubdiv/opensubdiv_device_context_cuda.h
@@ -0,0 +1,54 @@
+/*
+ * Adopted from OpenSubdiv with the following license:
+ *
+ * Copyright 2013 Pixar
+ *
+ * Licensed under the Apache License, Version 2.0 (the "Apache License")
+ * with the following modification; you may not use this file except in
+ * compliance with the Apache License and the following modification to it:
+ * Section 6. Trademarks. is deleted and replaced with:
+ *
+ * 6. Trademarks. This License does not grant permission to use the trade
+ * names, trademarks, service marks, or product names of the Licensor
+ * and its affiliates, except as required to comply with Section 4(c) of
+ * the License and to reproduce the content of the NOTICE file.
+ *
+ * You may obtain a copy of the Apache License at
+ *
+ * http: //www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Apache License with the above modification is
+ * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the Apache License for the specific
+ * language governing permissions and limitations under the Apache License.
+ *
+ */
+
+#ifndef __OPENSUBDIV_DEV_CE_CONTEXT_CUDA_H__
+#define __OPENSUBDIV_DEV_CE_CONTEXT_CUDA_H__
+
+struct ID3D11Device;
+
+class CudaDeviceContext {
+public:
+ CudaDeviceContext();
+ ~CudaDeviceContext();
+
+ static bool HAS_CUDA_VERSION_4_0();
+
+ /* Initialze cuda device from the current GL context. */
+ bool Initialize();
+
+ /* Initialze cuda device from the ID3D11Device/ */
+ bool Initialize(ID3D11Device *device);
+
+ /* Returns true if the cuda device has already been initialized. */
+ bool IsInitialized() const {
+ return _initialized;
+ }
+private:
+ bool _initialized;
+};
+
+#endif /* __OPENSUBDIV_DEV_CE_CONTEXT_OPENCL_H__ */
diff --git a/intern/opensubdiv/opensubdiv_device_context_opencl.cc b/intern/opensubdiv/opensubdiv_device_context_opencl.cc
new file mode 100644
index 00000000000..4cacdc9e845
--- /dev/null
+++ b/intern/opensubdiv/opensubdiv_device_context_opencl.cc
@@ -0,0 +1,251 @@
+/*
+ * Adopted from OpenSubdiv with the following license:
+ *
+ * Copyright 2015 Pixar
+ *
+ * Licensed under the Apache License, Version 2.0 (the "Apache License")
+ * with the following modification; you may not use this file except in
+ * compliance with the Apache License and the following modification to it:
+ * Section 6. Trademarks. is deleted and replaced with:
+ *
+ * 6. Trademarks. This License does not grant permission to use the trade
+ * names, trademarks, service marks, or product names of the Licensor
+ * and its affiliates, except as required to comply with Section 4(c) of
+ * the License and to reproduce the content of the NOTICE file.
+ *
+ * You may obtain a copy of the Apache License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Apache License with the above modification is
+ * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the Apache License for the specific
+ * language governing permissions and limitations under the Apache License.
+ *
+ */
+
+#ifdef OPENSUBDIV_HAS_OPENCL
+
+#ifdef _MSC_VER
+# include "iso646.h"
+#endif
+
+#include "opensubdiv_device_context_opencl.h"
+
+#if defined(_WIN32)
+# include <windows.h>
+#elif defined(__APPLE__)
+# include <OpenGL/OpenGL.h>
+#else
+# include <GL/glx.h>
+#endif
+
+#include <cstdio>
+#include <cstring>
+#include <string>
+
+#define message(...) // fprintf(stderr, __VA_ARGS__)
+#define error(...) fprintf(stderr, __VA_ARGS__)
+
+/* Returns the first found platform. */
+static cl_platform_id findPlatform() {
+ cl_uint numPlatforms;
+ cl_int ciErrNum = clGetPlatformIDs(0, NULL, &numPlatforms);
+ if (ciErrNum != CL_SUCCESS) {
+ error("Error %d in clGetPlatformIDs call.\n", ciErrNum);
+ return NULL;
+ }
+ if (numPlatforms == 0) {
+ error("No OpenCL platform found.\n");
+ return NULL;
+ }
+ cl_platform_id *clPlatformIDs = new cl_platform_id[numPlatforms];
+ ciErrNum = clGetPlatformIDs(numPlatforms, clPlatformIDs, NULL);
+ char chBuffer[1024];
+ for (cl_uint i = 0; i < numPlatforms; ++i) {
+ ciErrNum = clGetPlatformInfo(clPlatformIDs[i], CL_PLATFORM_NAME,
+ 1024, chBuffer,NULL);
+ if (ciErrNum == CL_SUCCESS) {
+ cl_platform_id platformId = clPlatformIDs[i];
+ delete[] clPlatformIDs;
+ return platformId;
+ }
+ }
+ delete[] clPlatformIDs;
+ return NULL;
+}
+
+/* Return. the device in clDevices which supports the extension. */
+static int findExtensionSupportedDevice(cl_device_id *clDevices,
+ int numDevices,
+ const char *extensionName) {
+ /* Find a device that supports sharing with GL/D3D11
+ * (SLI / X-fire configurations)
+ */
+ cl_int ciErrNum;
+ for (int i = 0; i < numDevices; ++i) {
+ /* Get extensions string size. */
+ size_t extensionSize;
+ ciErrNum = clGetDeviceInfo(clDevices[i],
+ CL_DEVICE_EXTENSIONS, 0, NULL,
+ &extensionSize);
+ if (ciErrNum != CL_SUCCESS) {
+ error("Error %d in clGetDeviceInfo\n", ciErrNum);
+ return -1;
+ }
+ if (extensionSize > 0) {
+ /* Get extensions string. */
+ char *extensions = new char[extensionSize];
+ ciErrNum = clGetDeviceInfo(clDevices[i], CL_DEVICE_EXTENSIONS,
+ extensionSize, extensions,
+ &extensionSize);
+ if (ciErrNum != CL_SUCCESS) {
+ error("Error %d in clGetDeviceInfo\n", ciErrNum);
+ delete[] extensions;
+ continue;
+ }
+ std::string extString(extensions);
+ delete[] extensions;
+ /* Parse string. This is bit deficient since the extentions
+ * is space separated.
+ *
+ * The actual string would be "cl_khr_d3d11_sharing"
+ * or "cl_nv_d3d11_sharing"
+ */
+ if (extString.find(extensionName) != std::string::npos) {
+ return i;
+ }
+ }
+ }
+ return -1;
+}
+
+CLDeviceContext::CLDeviceContext()
+ : _clContext(NULL),
+ _clCommandQueue(NULL) {
+}
+
+CLDeviceContext::~CLDeviceContext() {
+ if (_clCommandQueue)
+ clReleaseCommandQueue(_clCommandQueue);
+ if (_clContext)
+ clReleaseContext(_clContext);
+}
+
+bool CLDeviceContext::HAS_CL_VERSION_1_1()
+{
+#ifdef OPENSUBDIV_HAS_CLEW
+ static bool clewInitialized = false;
+ static bool clewLoadSuccess;
+ if (not clewInitialized) {
+ clewInitialized = true;
+ clewLoadSuccess = clewInit() == CLEW_SUCCESS;
+ if (!clewLoadSuccess) {
+ error("Loading OpenCL failed.\n");
+ }
+ }
+ return clewLoadSuccess;
+#endif
+ return true;
+}
+
+bool CLDeviceContext::Initialize()
+{
+#ifdef OPENSUBDIV_HAS_CLEW
+ if (!clGetPlatformIDs) {
+ error("Error clGetPlatformIDs function not bound.\n");
+ return false;
+ }
+#endif
+ cl_int ciErrNum;
+ cl_platform_id cpPlatform = findPlatform();
+
+#if defined(_WIN32)
+ cl_context_properties props[] = {
+ CL_GL_CONTEXT_KHR, (cl_context_properties)wglGetCurrentContext(),
+ CL_WGL_HDC_KHR, (cl_context_properties)wglGetCurrentDC(),
+ CL_CONTEXT_PLATFORM, (cl_context_properties)cpPlatform,
+ 0
+ };
+#elif defined(__APPLE__)
+ CGLContextObj kCGLContext = CGLGetCurrentContext();
+ CGLShareGroupObj kCGLShareGroup = CGLGetShareGroup(kCGLContext);
+ cl_context_properties props[] = {
+ CL_CONTEXT_PROPERTY_USE_CGL_SHAREGROUP_APPLE, (cl_context_properties)kCGLShareGroup,
+ 0
+ };
+#else
+ cl_context_properties props[] = {
+ CL_GL_CONTEXT_KHR, (cl_context_properties)glXGetCurrentContext(),
+ CL_GLX_DISPLAY_KHR, (cl_context_properties)glXGetCurrentDisplay(),
+ CL_CONTEXT_PLATFORM, (cl_context_properties)cpPlatform,
+ 0
+ };
+#endif
+
+#if defined(__APPLE__)
+ _clContext = clCreateContext(props, 0, NULL, clLogMessagesToStdoutAPPLE,
+ NULL, &ciErrNum);
+ if (ciErrNum != CL_SUCCESS) {
+ error("Error %d in clCreateContext\n", ciErrNum);
+ return false;
+ }
+
+ size_t devicesSize = 0;
+ clGetGLContextInfoAPPLE(_clContext, kCGLContext,
+ CL_CGL_DEVICES_FOR_SUPPORTED_VIRTUAL_SCREENS_APPLE,
+ 0, NULL, &devicesSize);
+ int numDevices = int(devicesSize / sizeof(cl_device_id));
+ if (numDevices == 0) {
+ error("No sharable devices.\n");
+ return false;
+ }
+ cl_device_id *clDevices = new cl_device_id[numDevices];
+ clGetGLContextInfoAPPLE(_clContext, kCGLContext,
+ CL_CGL_DEVICES_FOR_SUPPORTED_VIRTUAL_SCREENS_APPLE,
+ numDevices * sizeof(cl_device_id), clDevices, NULL);
+ int clDeviceUsed = 0;
+
+#else // not __APPLE__
+ /* Get the number of GPU devices available to the platform. */
+ cl_uint numDevices = 0;
+ clGetDeviceIDs(cpPlatform, CL_DEVICE_TYPE_GPU, 0, NULL, &numDevices);
+ if (numDevices == 0) {
+ error("No CL GPU device found.\n");
+ return false;
+ }
+
+ /* Create the device list. */
+ cl_device_id *clDevices = new cl_device_id[numDevices];
+ clGetDeviceIDs(cpPlatform, CL_DEVICE_TYPE_GPU, numDevices, clDevices, NULL);
+
+ const char *extension = "cl_khr_gl_sharing";
+ int clDeviceUsed = findExtensionSupportedDevice(clDevices, numDevices,
+ extension);
+
+ if (clDeviceUsed < 0) {
+ error("No device found that supports CL/GL context sharing\n");
+ delete[] clDevices;
+ return false;
+ }
+
+ _clContext = clCreateContext(props, 1, &clDevices[clDeviceUsed],
+ NULL, NULL, &ciErrNum);
+#endif // not __APPLE__
+ if (ciErrNum != CL_SUCCESS) {
+ error("Error %d in clCreateContext\n", ciErrNum);
+ delete[] clDevices;
+ return false;
+ }
+ _clCommandQueue = clCreateCommandQueue(_clContext, clDevices[clDeviceUsed],
+ 0, &ciErrNum);
+ delete[] clDevices;
+ if (ciErrNum != CL_SUCCESS) {
+ error("Error %d in clCreateCommandQueue\n", ciErrNum);
+ return false;
+ }
+ return true;
+}
+
+#endif /* OPENSUBDIV_HAS_OPENCL */
diff --git a/intern/opensubdiv/opensubdiv_device_context_opencl.h b/intern/opensubdiv/opensubdiv_device_context_opencl.h
new file mode 100644
index 00000000000..a640dce1f07
--- /dev/null
+++ b/intern/opensubdiv/opensubdiv_device_context_opencl.h
@@ -0,0 +1,58 @@
+/*
+ * Adopted from OpenSubdiv with the following license:
+ *
+ * Copyright 2015 Pixar
+ *
+ * Licensed under the Apache License, Version 2.0 (the "Apache License")
+ * with the following modification; you may not use this file except in
+ * compliance with the Apache License and the following modification to it:
+ * Section 6. Trademarks. is deleted and replaced with:
+ *
+ * 6. Trademarks. This License does not grant permission to use the trade
+ * names, trademarks, service marks, or product names of the Licensor
+ * and its affiliates, except as required to comply with Section 4(c) of
+ * the License and to reproduce the content of the NOTICE file.
+ *
+ * You may obtain a copy of the Apache License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Apache License with the above modification is
+ * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the Apache License for the specific
+ * language governing permissions and limitations under the Apache License.
+ *
+ */
+
+#ifndef __OPENSUBDIV_DEV_CE_CONTEXT_OPENCL_H__
+#define __OPENSUBDIV_DEV_CE_CONTEXT_OPENCL_H__
+
+#include <opensubdiv/osd/opencl.h>
+
+class CLDeviceContext {
+public:
+ CLDeviceContext();
+ ~CLDeviceContext();
+
+ static bool HAS_CL_VERSION_1_1 ();
+
+ bool Initialize();
+
+ bool IsInitialized() const {
+ return (_clContext != NULL);
+ }
+
+ cl_context GetContext() const {
+ return _clContext;
+ }
+ cl_command_queue GetCommandQueue() const {
+ return _clCommandQueue;
+ }
+
+protected:
+ cl_context _clContext;
+ cl_command_queue _clCommandQueue;
+};
+
+#endif /* __OPENSUBDIV_DEV_CE_CONTEXT_OPENCL_H__ */
diff --git a/intern/opensubdiv/opensubdiv_evaluator_capi.cc b/intern/opensubdiv/opensubdiv_evaluator_capi.cc
new file mode 100644
index 00000000000..0da6b9daba8
--- /dev/null
+++ b/intern/opensubdiv/opensubdiv_evaluator_capi.cc
@@ -0,0 +1,495 @@
+/*
+ * ***** 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) 2015 Blender Foundation.
+ * All rights reserved.
+ *
+ * Contributor(s): Sergey Sharybin.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include "opensubdiv_capi.h"
+
+#include <cstdio>
+#include <vector>
+
+#ifdef _MSC_VER
+# include "iso646.h"
+#endif
+
+#include <opensubdiv/far/patchMap.h>
+#include <opensubdiv/far/patchTable.h>
+#include <opensubdiv/far/patchTableFactory.h>
+#include <opensubdiv/osd/cpuEvaluator.h>
+#include <opensubdiv/osd/cpuPatchTable.h>
+#include <opensubdiv/osd/cpuVertexBuffer.h>
+#include <opensubdiv/osd/mesh.h>
+#include <opensubdiv/osd/types.h>
+
+#include "opensubdiv_intern.h"
+
+#include "MEM_guardedalloc.h"
+
+using OpenSubdiv::Osd::BufferDescriptor;
+using OpenSubdiv::Osd::PatchCoord;
+using OpenSubdiv::Far::PatchMap;
+using OpenSubdiv::Far::PatchTable;
+using OpenSubdiv::Far::PatchTableFactory;
+using OpenSubdiv::Far::StencilTable;
+using OpenSubdiv::Far::StencilTableFactory;
+using OpenSubdiv::Far::TopologyRefiner;
+
+namespace {
+
+/* Helper class to wrap numerous of patch coords into a buffer.
+ * Used to pass coordinates to the CPU evaluator. Other evaluators
+ * are not supported.
+ */
+class PatchCoordBuffer : public std::vector<PatchCoord> {
+public:
+ static PatchCoordBuffer *Create(int size)
+ {
+ PatchCoordBuffer *buffer = new PatchCoordBuffer();
+ buffer->resize(size);
+ return buffer;
+ }
+ PatchCoord *BindCpuBuffer() {
+ return (PatchCoord*)&(*this)[0];
+ }
+ int GetNumVertices() {
+ return size();
+ }
+ void UpdateData(const PatchCoord *patch_coords,
+ int num_patch_coords)
+ {
+ memcpy(&(*this)[0],
+ (void*)patch_coords,
+ num_patch_coords * sizeof(PatchCoord));
+ }
+};
+
+/* Helper class to wrap single of patch coord into a buffer.
+ * Used to pass coordinates to the CPU evaluator. Other evaluators
+ * are not supported.
+ */
+class SinglePatchCoordBuffer {
+public:
+ SinglePatchCoordBuffer() {
+ }
+ SinglePatchCoordBuffer(const PatchCoord& patch_coord)
+ : patch_coord_(patch_coord){
+ }
+ static SinglePatchCoordBuffer *Create()
+ {
+ SinglePatchCoordBuffer *buffer = new SinglePatchCoordBuffer();
+ return buffer;
+ }
+ PatchCoord *BindCpuBuffer() {
+ return (PatchCoord*)&patch_coord_;
+ }
+ int GetNumVertices() {
+ return 1;
+ }
+ void UpdateData(const PatchCoord& patch_coord)
+ {
+ patch_coord_ = patch_coord;
+ }
+protected:
+ PatchCoord patch_coord_;
+};
+
+/* Helper class which is aimed to be used in cases when buffer
+ * is small enough and better to be allocated in stack rather
+ * than in heap.
+ *
+ * TODO(sergey): Check if bare arrays could be sued by CPU evalautor.
+ */
+template <int element_size, int num_verts>
+class StackAllocatedBuffer {
+public:
+ static PatchCoordBuffer *Create(int size)
+ {
+ StackAllocatedBuffer<element_size, num_verts> *buffer =
+ new StackAllocatedBuffer<element_size, num_verts>();
+ return buffer;
+ }
+ float *BindCpuBuffer() {
+ return &data_[0];
+ }
+ int GetNumVertices() {
+ return num_verts;
+ }
+ /* TODO(sergey): Support UpdateData(). */
+protected:
+ float data_[element_size * num_verts];
+};
+
+/* Volatile evaluator which can be used from threads.
+ *
+ * TODO(sergey): Make it possible to evaluate coordinates in chuncks.
+ */
+template<typename SRC_VERTEX_BUFFER,
+ typename EVAL_VERTEX_BUFFER,
+ typename STENCIL_TABLE,
+ typename PATCH_TABLE,
+ typename EVALUATOR,
+ typename DEVICE_CONTEXT = void>
+class VolatileEvalOutput {
+public:
+ typedef OpenSubdiv::Osd::EvaluatorCacheT<EVALUATOR> EvaluatorCache;
+
+ VolatileEvalOutput(const StencilTable *vertex_stencils,
+ const StencilTable *varying_stencils,
+ int num_coarse_verts,
+ int num_total_verts,
+ const PatchTable *patch_table,
+ EvaluatorCache *evaluator_cache = NULL,
+ DEVICE_CONTEXT *device_context = NULL)
+ : src_desc_( /*offset*/ 0, /*length*/ 3, /*stride*/ 3),
+ src_varying_desc_(/*offset*/ 0, /*length*/ 3, /*stride*/ 3),
+ num_coarse_verts_(num_coarse_verts),
+ evaluator_cache_ (evaluator_cache),
+ device_context_(device_context)
+ {
+ using OpenSubdiv::Osd::convertToCompatibleStencilTable;
+ src_data_ = SRC_VERTEX_BUFFER::Create(3, num_total_verts, device_context_);
+ src_varying_data_ = SRC_VERTEX_BUFFER::Create(3, num_total_verts, device_context_);
+ patch_table_ = PATCH_TABLE::Create(patch_table, device_context_);
+ patch_coords_ = NULL;
+ vertex_stencils_ = convertToCompatibleStencilTable<STENCIL_TABLE>(vertex_stencils,
+ device_context_);
+ varying_stencils_ = convertToCompatibleStencilTable<STENCIL_TABLE>(varying_stencils,
+ device_context_);
+ }
+
+ ~VolatileEvalOutput()
+ {
+ delete src_data_;
+ delete src_varying_data_;
+ delete patch_table_;
+ delete vertex_stencils_;
+ delete varying_stencils_;
+ }
+
+ void UpdateData(const float *src, int start_vertex, int num_vertices)
+ {
+ src_data_->UpdateData(src, start_vertex, num_vertices, device_context_);
+ }
+
+ void UpdateVaryingData(const float *src, int start_vertex, int num_vertices)
+ {
+ src_varying_data_->UpdateData(src,
+ start_vertex,
+ num_vertices,
+ device_context_);
+ }
+
+ void Refine()
+ {
+ BufferDescriptor dst_desc = src_desc_;
+ dst_desc.offset += num_coarse_verts_ * src_desc_.stride;
+
+ const EVALUATOR *eval_instance =
+ OpenSubdiv::Osd::GetEvaluator<EVALUATOR>(evaluator_cache_,
+ src_desc_,
+ dst_desc,
+ device_context_);
+
+ EVALUATOR::EvalStencils(src_data_, src_desc_,
+ src_data_, dst_desc,
+ vertex_stencils_,
+ eval_instance,
+ device_context_);
+
+ dst_desc = src_varying_desc_;
+ dst_desc.offset += num_coarse_verts_ * src_varying_desc_.stride;
+ eval_instance =
+ OpenSubdiv::Osd::GetEvaluator<EVALUATOR>(evaluator_cache_,
+ src_varying_desc_,
+ dst_desc,
+ device_context_);
+
+ EVALUATOR::EvalStencils(src_varying_data_, src_varying_desc_,
+ src_varying_data_, dst_desc,
+ varying_stencils_,
+ eval_instance,
+ device_context_);
+ }
+
+ void EvalPatchCoord(PatchCoord& patch_coord, float P[3])
+ {
+ StackAllocatedBuffer<6, 1> vertex_data;
+ BufferDescriptor vertex_desc(0, 3, 6);
+ SinglePatchCoordBuffer patch_coord_buffer(patch_coord);
+ const EVALUATOR *eval_instance =
+ OpenSubdiv::Osd::GetEvaluator<EVALUATOR>(evaluator_cache_,
+ src_desc_,
+ vertex_desc,
+ device_context_);
+ EVALUATOR::EvalPatches(src_data_, src_desc_,
+ &vertex_data, vertex_desc,
+ patch_coord_buffer.GetNumVertices(),
+ &patch_coord_buffer,
+ patch_table_, eval_instance, device_context_);
+ float *refined_verts = vertex_data.BindCpuBuffer();
+ memcpy(P, refined_verts, sizeof(float) * 3);
+ }
+
+ void EvalPatchesWithDerivatives(PatchCoord& patch_coord,
+ float P[3],
+ float dPdu[3],
+ float dPdv[3])
+ {
+ StackAllocatedBuffer<6, 1> vertex_data, derivatives;
+ BufferDescriptor vertex_desc(0, 3, 6),
+ du_desc(0, 3, 6),
+ dv_desc(3, 3, 6);
+ SinglePatchCoordBuffer patch_coord_buffer(patch_coord);
+ const EVALUATOR *eval_instance =
+ OpenSubdiv::Osd::GetEvaluator<EVALUATOR>(evaluator_cache_,
+ src_desc_,
+ vertex_desc,
+ du_desc,
+ dv_desc,
+ device_context_);
+ EVALUATOR::EvalPatches(src_data_, src_desc_,
+ &vertex_data, vertex_desc,
+ &derivatives, du_desc,
+ &derivatives, dv_desc,
+ patch_coord_buffer.GetNumVertices(),
+ &patch_coord_buffer,
+ patch_table_, eval_instance, device_context_);
+ float *refined_verts = vertex_data.BindCpuBuffer();
+ memcpy(P, refined_verts, sizeof(float) * 3);
+ if (dPdu != NULL || dPdv != NULL) {
+ float *refined_drivatives = derivatives.BindCpuBuffer();
+ if (dPdu) {
+ memcpy(dPdu, refined_drivatives, sizeof(float) * 3);
+ }
+ if (dPdv) {
+ memcpy(dPdv, refined_drivatives + 3, sizeof(float) * 3);
+ }
+ }
+ }
+
+ void EvalPatchVarying(PatchCoord& patch_coord,
+ float varying[3]) {
+ StackAllocatedBuffer<3, 1> varying_data;
+ BufferDescriptor varying_desc(0, 3, 3);
+ SinglePatchCoordBuffer patch_coord_buffer(patch_coord);
+ EVALUATOR const *eval_instance =
+ OpenSubdiv::Osd::GetEvaluator<EVALUATOR>(evaluator_cache_,
+ src_varying_desc_,
+ varying_desc,
+ device_context_);
+
+ EVALUATOR::EvalPatches(src_varying_data_, src_varying_desc_,
+ &varying_data, varying_desc,
+ patch_coord_buffer.GetNumVertices(),
+ &patch_coord_buffer,
+ patch_table_, eval_instance, device_context_);
+ float *refined_varying = varying_data.BindCpuBuffer();
+ memcpy(varying, refined_varying, sizeof(float) * 3);
+ }
+private:
+ SRC_VERTEX_BUFFER *src_data_;
+ SRC_VERTEX_BUFFER *src_varying_data_;
+ PatchCoordBuffer *patch_coords_;
+ PATCH_TABLE *patch_table_;
+ BufferDescriptor src_desc_;
+ BufferDescriptor src_varying_desc_;
+ int num_coarse_verts_;
+
+ const STENCIL_TABLE *vertex_stencils_;
+ const STENCIL_TABLE *varying_stencils_;
+
+ EvaluatorCache *evaluator_cache_;
+ DEVICE_CONTEXT *device_context_;
+};
+
+} /* namespace */
+
+typedef VolatileEvalOutput<OpenSubdiv::Osd::CpuVertexBuffer,
+ OpenSubdiv::Osd::CpuVertexBuffer,
+ OpenSubdiv::Far::StencilTable,
+ OpenSubdiv::Osd::CpuPatchTable,
+ OpenSubdiv::Osd::CpuEvaluator> CpuEvalOutput;
+
+typedef struct OpenSubdiv_EvaluatorDescr {
+ CpuEvalOutput *eval_output;
+ const PatchMap *patch_map;
+ const PatchTable *patch_table;
+} OpenSubdiv_EvaluatorDescr;
+
+OpenSubdiv_EvaluatorDescr *openSubdiv_createEvaluatorDescr(
+ OpenSubdiv_TopologyRefinerDescr *topology_refiner,
+ int subsurf_level)
+{
+ /* TODO(sergey): Look into re-using refiner with GLMesh. */
+ TopologyRefiner *refiner = (TopologyRefiner *)topology_refiner;
+ if(refiner == NULL) {
+ /* Happens on bad topology. */
+ return NULL;
+ }
+
+ const StencilTable *vertex_stencils = NULL;
+ const StencilTable *varying_stencils = NULL;
+ int num_total_verts = 0;
+
+ /* Apply uniform refinement to the mesh so that we can use the
+ * limit evaluation API features.
+ */
+ TopologyRefiner::UniformOptions options(subsurf_level);
+ refiner->RefineUniform(options);
+
+ /* Generate stencil table to update the bi-cubic patches control
+ * vertices after they have been re-posed (both for vertex & varying
+ * interpolation).
+ */
+ StencilTableFactory::Options soptions;
+ soptions.generateOffsets = true;
+ soptions.generateIntermediateLevels = false;
+
+ vertex_stencils = StencilTableFactory::Create(*refiner, soptions);
+
+ soptions.interpolationMode = StencilTableFactory::INTERPOLATE_VARYING;
+ varying_stencils = StencilTableFactory::Create(*refiner, soptions);
+
+ /* Generate bi-cubic patch table for the limit surface. */
+ PatchTableFactory::Options poptions;
+ poptions.SetEndCapType(PatchTableFactory::Options::ENDCAP_BSPLINE_BASIS);
+
+ const PatchTable *patch_table = PatchTableFactory::Create(*refiner, poptions);
+
+ /* Append local points stencils. */
+ /* TODO(sergey): Do we really need to worry about local points stencils? */
+ if (const StencilTable *local_point_stencil_table =
+ patch_table->GetLocalPointStencilTable())
+ {
+ const StencilTable *table =
+ StencilTableFactory::AppendLocalPointStencilTable(*refiner,
+ vertex_stencils,
+ local_point_stencil_table);
+ delete vertex_stencils;
+ vertex_stencils = table;
+ }
+ if (const StencilTable *local_point_varying_stencil_table =
+ patch_table->GetLocalPointVaryingStencilTable())
+ {
+ const StencilTable *table =
+ StencilTableFactory::AppendLocalPointStencilTable(*refiner,
+ varying_stencils,
+ local_point_varying_stencil_table);
+ delete varying_stencils;
+ varying_stencils = table;
+ }
+
+ /* Total number of vertices = coarse verts + refined verts + gregory basis verts. */
+ num_total_verts = vertex_stencils->GetNumControlVertices() +
+ vertex_stencils->GetNumStencils();
+
+ const int num_coarse_verts = refiner->GetLevel(0).GetNumVertices();
+
+ CpuEvalOutput *eval_output = new CpuEvalOutput(vertex_stencils,
+ varying_stencils,
+ num_coarse_verts,
+ num_total_verts,
+ patch_table);
+
+ OpenSubdiv::Far::PatchMap *patch_map = new PatchMap(*patch_table);
+
+ OpenSubdiv_EvaluatorDescr *evaluator_descr;
+ evaluator_descr = OBJECT_GUARDED_NEW(OpenSubdiv_EvaluatorDescr);
+ evaluator_descr->eval_output = eval_output;
+ evaluator_descr->patch_map = patch_map;
+ evaluator_descr->patch_table = patch_table;
+
+ /* TOOD(sergey): Look into whether w've got duplicated stencils arrays. */
+ delete varying_stencils;
+ delete vertex_stencils;
+
+ delete refiner;
+
+ return evaluator_descr;
+}
+
+void openSubdiv_deleteEvaluatorDescr(OpenSubdiv_EvaluatorDescr *evaluator_descr)
+{
+ delete evaluator_descr->eval_output;
+ delete evaluator_descr->patch_map;
+ delete evaluator_descr->patch_table;
+ OBJECT_GUARDED_DELETE(evaluator_descr, OpenSubdiv_EvaluatorDescr);
+}
+
+void openSubdiv_setEvaluatorCoarsePositions(OpenSubdiv_EvaluatorDescr *evaluator_descr,
+ float *positions,
+ int start_vert,
+ int num_verts)
+{
+ /* TODO(sergey): Add sanity check on indices. */
+ evaluator_descr->eval_output->UpdateData(positions, start_vert, num_verts);
+ /* TODO(sergey): Consider moving this to a separate call,
+ * so we can updatwe coordinates in chunks.
+ */
+ evaluator_descr->eval_output->Refine();
+}
+
+void openSubdiv_setEvaluatorVaryingData(OpenSubdiv_EvaluatorDescr *evaluator_descr,
+ float *varying_data,
+ int start_vert,
+ int num_verts)
+{
+ /* TODO(sergey): Add sanity check on indices. */
+ evaluator_descr->eval_output->UpdateVaryingData(varying_data, start_vert, num_verts);
+ /* TODO(sergey): Get rid of this ASAP. */
+ evaluator_descr->eval_output->Refine();
+}
+
+void openSubdiv_evaluateLimit(OpenSubdiv_EvaluatorDescr *evaluator_descr,
+ int osd_face_index,
+ float face_u, float face_v,
+ float P[3],
+ float dPdu[3],
+ float dPdv[3])
+{
+ assert((face_u >= 0.0f) && (face_u <= 1.0f) && (face_v >= 0.0f) && (face_v <= 1.0f));
+ const PatchTable::PatchHandle *handle =
+ evaluator_descr->patch_map->FindPatch(osd_face_index, face_u, face_v);
+ PatchCoord patch_coord(*handle, face_u, face_v);
+ if (dPdu != NULL || dPdv != NULL) {
+ evaluator_descr->eval_output->EvalPatchesWithDerivatives(patch_coord,
+ P,
+ dPdu,
+ dPdv);
+ }
+ else {
+ evaluator_descr->eval_output->EvalPatchCoord(patch_coord, P);
+ }
+}
+
+void openSubdiv_evaluateVarying(OpenSubdiv_EvaluatorDescr *evaluator_descr,
+ int osd_face_index,
+ float face_u, float face_v,
+ float varying[3])
+{
+ assert((face_u >= 0.0f) && (face_u <= 1.0f) && (face_v >= 0.0f) && (face_v <= 1.0f));
+ const PatchTable::PatchHandle *handle =
+ evaluator_descr->patch_map->FindPatch(osd_face_index, face_u, face_v);
+ PatchCoord patch_coord(*handle, face_u, face_v);
+ evaluator_descr->eval_output->EvalPatchVarying(patch_coord, varying);
+}
diff --git a/intern/opensubdiv/opensubdiv_gpu_capi.cc b/intern/opensubdiv/opensubdiv_gpu_capi.cc
new file mode 100644
index 00000000000..31996a1bab8
--- /dev/null
+++ b/intern/opensubdiv/opensubdiv_gpu_capi.cc
@@ -0,0 +1,674 @@
+/*
+ * ***** 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.
+ *
+ * Contributor(s): Sergey Sharybin
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/* Do some compatibility hacks in order to make
+ * the code working with GPU_material pipeline.
+ */
+#define GLSL_COMPAT_WORKAROUND
+
+#include "opensubdiv_capi.h"
+
+#ifdef _MSC_VER
+# include "iso646.h"
+#endif
+
+#include <cstdio>
+#include <cmath>
+#include <GL/glew.h>
+
+#include <opensubdiv/osd/glMesh.h>
+
+#ifdef OPENSUBDIV_HAS_CUDA
+# include <opensubdiv/osd/cudaGLVertexBuffer.h>
+#endif /* OPENSUBDIV_HAS_CUDA */
+
+#include <opensubdiv/osd/cpuGLVertexBuffer.h>
+#include <opensubdiv/osd/cpuEvaluator.h>
+
+using OpenSubdiv::Osd::GLMeshInterface;
+
+extern "C" char datatoc_gpu_shader_opensubd_display_glsl[];
+
+#define MAX_LIGHTS 8
+typedef struct Light {
+ float position[4];
+ float ambient[4];
+ float diffuse[4];
+ float specular[4];
+ float spot_direction[4];
+#ifdef SUPPORT_COLOR_MATERIAL
+ float constant_attenuation;
+ float linear_attenuation;
+ float quadratic_attenuation;
+ float spot_cutoff;
+ float spot_exponent;
+ float spot_cos_cutoff;
+#endif
+} Light;
+
+typedef struct Lighting {
+ Light lights[MAX_LIGHTS];
+ int num_enabled;
+} Lighting;
+
+typedef struct Transform {
+ float projection_matrix[16];
+ float model_view_matrix[16];
+ float normal_matrix[9];
+} Transform;
+
+static bool g_use_osd_glsl = false;
+static int g_active_uv_index = -1;
+
+static GLuint g_flat_fill_solid_program = 0;
+static GLuint g_flat_fill_texture2d_program = 0;
+static GLuint g_smooth_fill_solid_program = 0;
+static GLuint g_smooth_fill_texture2d_program = 0;
+static GLuint g_wireframe_program = 0;
+
+static GLuint g_lighting_ub = 0;
+static Lighting g_lighting_data;
+static Transform g_transform;
+
+/* TODO(sergey): This is actually duplicated code from BLI. */
+namespace {
+void copy_m3_m3(float m1[3][3], float m2[3][3])
+{
+ /* destination comes first: */
+ memcpy(&m1[0], &m2[0], 9 * sizeof(float));
+}
+
+void copy_m3_m4(float m1[3][3], float m2[4][4])
+{
+ m1[0][0] = m2[0][0];
+ m1[0][1] = m2[0][1];
+ m1[0][2] = m2[0][2];
+
+ m1[1][0] = m2[1][0];
+ m1[1][1] = m2[1][1];
+ m1[1][2] = m2[1][2];
+
+ m1[2][0] = m2[2][0];
+ m1[2][1] = m2[2][1];
+ m1[2][2] = m2[2][2];
+}
+
+void adjoint_m3_m3(float m1[3][3], float m[3][3])
+{
+ m1[0][0] = m[1][1] * m[2][2] - m[1][2] * m[2][1];
+ m1[0][1] = -m[0][1] * m[2][2] + m[0][2] * m[2][1];
+ m1[0][2] = m[0][1] * m[1][2] - m[0][2] * m[1][1];
+
+ m1[1][0] = -m[1][0] * m[2][2] + m[1][2] * m[2][0];
+ m1[1][1] = m[0][0] * m[2][2] - m[0][2] * m[2][0];
+ m1[1][2] = -m[0][0] * m[1][2] + m[0][2] * m[1][0];
+
+ m1[2][0] = m[1][0] * m[2][1] - m[1][1] * m[2][0];
+ m1[2][1] = -m[0][0] * m[2][1] + m[0][1] * m[2][0];
+ m1[2][2] = m[0][0] * m[1][1] - m[0][1] * m[1][0];
+}
+
+float determinant_m3_array(float m[3][3])
+{
+ return (m[0][0] * (m[1][1] * m[2][2] - m[1][2] * m[2][1]) -
+ m[1][0] * (m[0][1] * m[2][2] - m[0][2] * m[2][1]) +
+ m[2][0] * (m[0][1] * m[1][2] - m[0][2] * m[1][1]));
+}
+
+bool invert_m3_m3(float m1[3][3], float m2[3][3])
+{
+ float det;
+ int a, b;
+ bool success;
+
+ /* calc adjoint */
+ adjoint_m3_m3(m1, m2);
+
+ /* then determinant old matrix! */
+ det = determinant_m3_array(m2);
+
+ success = (det != 0.0f);
+
+ if (det != 0.0f) {
+ det = 1.0f / det;
+ for (a = 0; a < 3; a++) {
+ for (b = 0; b < 3; b++) {
+ m1[a][b] *= det;
+ }
+ }
+ }
+
+ return success;
+}
+
+bool invert_m3(float m[3][3])
+{
+ float tmp[3][3];
+ bool success;
+
+ success = invert_m3_m3(tmp, m);
+ copy_m3_m3(m, tmp);
+
+ return success;
+}
+
+void transpose_m3(float mat[3][3])
+{
+ float t;
+
+ t = mat[0][1];
+ mat[0][1] = mat[1][0];
+ mat[1][0] = t;
+ t = mat[0][2];
+ mat[0][2] = mat[2][0];
+ mat[2][0] = t;
+ t = mat[1][2];
+ mat[1][2] = mat[2][1];
+ mat[2][1] = t;
+}
+
+GLuint compileShader(GLenum shaderType,
+ const char *section,
+ const char *define)
+{
+ const char *sources[3];
+ char sdefine[64];
+ sprintf(sdefine, "#define %s\n#define GLSL_COMPAT_WORKAROUND\n", section);
+
+ sources[0] = define;
+ sources[1] = sdefine;
+ sources[2] = datatoc_gpu_shader_opensubd_display_glsl;
+
+ GLuint shader = glCreateShader(shaderType);
+ glShaderSource(shader, 3, sources, NULL);
+ glCompileShader(shader);
+
+ GLint status;
+ glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
+ if (status == GL_FALSE) {
+ GLchar emsg[1024];
+ glGetShaderInfoLog(shader, sizeof(emsg), 0, emsg);
+ fprintf(stderr, "Error compiling GLSL shader (%s): %s\n", section, emsg);
+ fprintf(stderr, "Section: %s\n", sdefine);
+ fprintf(stderr, "Defines: %s\n", define);
+ fprintf(stderr, "Source: %s\n", sources[2]);
+ return 0;
+ }
+
+ return shader;
+}
+
+GLuint linkProgram(const char *define)
+{
+ GLuint vertexShader = compileShader(GL_VERTEX_SHADER,
+ "VERTEX_SHADER",
+ define);
+ if (vertexShader == 0) {
+ return 0;
+ }
+ GLuint geometryShader = compileShader(GL_GEOMETRY_SHADER,
+ "GEOMETRY_SHADER",
+ define);
+ if (geometryShader == 0) {
+ return 0;
+ }
+ GLuint fragmentShader = compileShader(GL_FRAGMENT_SHADER,
+ "FRAGMENT_SHADER",
+ define);
+ if (fragmentShader == 0) {
+ return 0;
+ }
+
+ GLuint program = glCreateProgram();
+
+ glAttachShader(program, vertexShader);
+ glAttachShader(program, geometryShader);
+ glAttachShader(program, fragmentShader);
+
+ glBindAttribLocation(program, 0, "position");
+ glBindAttribLocation(program, 1, "normal");
+
+#ifdef GLSL_COMPAT_WORKAROUND
+ glProgramParameteriEXT(program,
+ GL_GEOMETRY_INPUT_TYPE_EXT,
+ GL_LINES_ADJACENCY_EXT);
+
+ if (strstr(define, "WIREFRAME") == NULL) {
+ glProgramParameteriEXT(program,
+ GL_GEOMETRY_OUTPUT_TYPE_EXT,
+ GL_TRIANGLE_STRIP);
+
+ glProgramParameteriEXT(program,
+ GL_GEOMETRY_VERTICES_OUT_EXT,
+ 4);
+ }
+ else {
+ glProgramParameteriEXT(program,
+ GL_GEOMETRY_OUTPUT_TYPE_EXT,
+ GL_LINE_STRIP);
+
+ glProgramParameteriEXT(program,
+ GL_GEOMETRY_VERTICES_OUT_EXT,
+ 8);
+ }
+#endif
+
+ glLinkProgram(program);
+
+ glDeleteShader(vertexShader);
+ glDeleteShader(geometryShader);
+ glDeleteShader(fragmentShader);
+
+ GLint status;
+ glGetProgramiv(program, GL_LINK_STATUS, &status);
+ if (status == GL_FALSE) {
+ GLchar emsg[1024];
+ glGetProgramInfoLog(program, sizeof(emsg), 0, emsg);
+ fprintf(stderr, "Error linking GLSL program : %s\n", emsg);
+ fprintf(stderr, "Defines: %s\n", define);
+ glDeleteProgram(program);
+ return 0;
+ }
+
+ glUniformBlockBinding(program,
+ glGetUniformBlockIndex(program, "Lighting"),
+ 0);
+
+ glProgramUniform1i(program,
+ glGetUniformLocation(program, "texture_buffer"),
+ 0); /* GL_TEXTURE0 */
+
+ glProgramUniform1i(program,
+ glGetUniformLocation(program, "FVarDataBuffer"),
+ 31); /* GL_TEXTURE31 */
+
+ return program;
+}
+
+void bindProgram(GLMeshInterface * /*mesh*/,
+ int program)
+{
+ glUseProgram(program);
+
+ /* Matricies */
+ glUniformMatrix4fv(glGetUniformLocation(program, "modelViewMatrix"),
+ 1, false,
+ g_transform.model_view_matrix);
+ glUniformMatrix4fv(glGetUniformLocation(program, "projectionMatrix"),
+ 1, false,
+ g_transform.projection_matrix);
+ glUniformMatrix3fv(glGetUniformLocation(program, "normalMatrix"),
+ 1, false,
+ g_transform.normal_matrix);
+
+ /* Ligthing */
+ glBindBuffer(GL_UNIFORM_BUFFER, g_lighting_ub);
+ glBufferSubData(GL_UNIFORM_BUFFER,
+ 0, sizeof(g_lighting_data), &g_lighting_data);
+ glBindBuffer(GL_UNIFORM_BUFFER, 0);
+
+ glBindBufferBase(GL_UNIFORM_BUFFER, 0, g_lighting_ub);
+
+ /* Color */
+ GLboolean use_lighting;
+ glGetBooleanv(GL_LIGHTING, &use_lighting);
+
+ if (use_lighting) {
+ float color[4];
+ glGetMaterialfv(GL_FRONT, GL_DIFFUSE, color);
+ glUniform4fv(glGetUniformLocation(program, "diffuse"), 1, color);
+
+ glGetMaterialfv(GL_FRONT, GL_SPECULAR, color);
+ glUniform4fv(glGetUniformLocation(program, "specular"), 1, color);
+
+ glGetMaterialfv(GL_FRONT, GL_SHININESS, color);
+ glUniform1f(glGetUniformLocation(program, "shininess"), color[0]);
+ }
+ else {
+ float color[4];
+ glGetFloatv(GL_CURRENT_COLOR, color);
+ glUniform4fv(glGetUniformLocation(program, "diffuse"), 1, color);
+ }
+
+ /* TODO(sergey): Bring face varying back. */
+#if 0
+ /* Face-vertex data */
+ if (mesh->GetDrawContext()->GetFvarDataTextureBuffer()) {
+ glActiveTexture(GL_TEXTURE31);
+ glBindTexture(GL_TEXTURE_BUFFER,
+ mesh->GetDrawContext()->GetFvarDataTextureBuffer());
+ glActiveTexture(GL_TEXTURE0);
+ }
+#endif
+
+ /* TODO(sergey): Bring face varying back. */
+ glUniform1i(glGetUniformLocation(program, "osd_fvar_count"),
+ 0/* * mesh->GetFVarCount()*/);
+
+ glUniform1i(glGetUniformLocation(program, "osd_active_uv_offset"),
+ g_active_uv_index * 2);
+}
+
+} /* namespace */
+
+bool openSubdiv_osdGLDisplayInit(void)
+{
+ static bool need_init = true;
+ static bool init_success = false;
+ if (need_init) {
+ g_flat_fill_solid_program = linkProgram("#define FLAT_SHADING\n");
+ g_flat_fill_texture2d_program = linkProgram("#define USE_TEXTURE_2D\n#define FLAT_SHADING\n");
+ g_smooth_fill_solid_program = linkProgram("#define SMOOTH_SHADING\n");
+ g_smooth_fill_texture2d_program = linkProgram("#define USE_TEXTURE_2D\n#define SMOOTH_SHADING\n");
+ g_wireframe_program = linkProgram("#define WIREFRAME\n");
+
+ glGenBuffers(1, &g_lighting_ub);
+ glBindBuffer(GL_UNIFORM_BUFFER, g_lighting_ub);
+ glBufferData(GL_UNIFORM_BUFFER,
+ sizeof(g_lighting_data), NULL, GL_STATIC_DRAW);
+
+ need_init = false;
+ init_success = g_flat_fill_solid_program != 0 &&
+ g_flat_fill_texture2d_program != 0 &&
+ g_smooth_fill_solid_program != 0 &&
+ g_smooth_fill_texture2d_program != 0 &&
+ g_wireframe_program;
+ }
+ return init_success;
+}
+
+void openSubdiv_osdGLDisplayDeinit(void)
+{
+ if (g_lighting_ub != 0) {
+ glDeleteBuffers(1, &g_lighting_ub);
+ }
+ if (g_flat_fill_solid_program) {
+ glDeleteProgram(g_flat_fill_solid_program);
+ }
+ if (g_flat_fill_texture2d_program) {
+ glDeleteProgram(g_flat_fill_texture2d_program);
+ }
+ if (g_smooth_fill_solid_program) {
+ glDeleteProgram(g_flat_fill_solid_program);
+ }
+ if (g_smooth_fill_texture2d_program) {
+ glDeleteProgram(g_smooth_fill_texture2d_program);
+ }
+ if (g_wireframe_program) {
+ glDeleteProgram(g_wireframe_program);
+ }
+}
+
+void openSubdiv_osdGLMeshDisplayPrepare(int use_osd_glsl,
+ int active_uv_index)
+{
+ g_use_osd_glsl = use_osd_glsl != 0;
+ g_active_uv_index = active_uv_index;
+
+ /* Update transformation matricies. */
+ glGetFloatv(GL_PROJECTION_MATRIX, g_transform.projection_matrix);
+ glGetFloatv(GL_MODELVIEW_MATRIX, g_transform.model_view_matrix);
+
+ copy_m3_m4((float (*)[3])g_transform.normal_matrix,
+ (float (*)[4])g_transform.model_view_matrix);
+ invert_m3((float (*)[3])g_transform.normal_matrix);
+ transpose_m3((float (*)[3])g_transform.normal_matrix);
+
+ /* Update OpenGL lights positions, colors etc. */
+ g_lighting_data.num_enabled = 0;
+ for (int i = 0; i < MAX_LIGHTS; ++i) {
+ GLboolean enabled;
+ glGetBooleanv(GL_LIGHT0 + i, &enabled);
+ if (enabled) {
+ g_lighting_data.num_enabled++;
+ }
+
+ glGetLightfv(GL_LIGHT0 + i,
+ GL_POSITION,
+ g_lighting_data.lights[i].position);
+ glGetLightfv(GL_LIGHT0 + i,
+ GL_AMBIENT,
+ g_lighting_data.lights[i].ambient);
+ glGetLightfv(GL_LIGHT0 + i,
+ GL_DIFFUSE,
+ g_lighting_data.lights[i].diffuse);
+ glGetLightfv(GL_LIGHT0 + i,
+ GL_SPECULAR,
+ g_lighting_data.lights[i].specular);
+ glGetLightfv(GL_LIGHT0 + i,
+ GL_SPOT_DIRECTION,
+ g_lighting_data.lights[i].spot_direction);
+#ifdef SUPPORT_COLOR_MATERIAL
+ glGetLightfv(GL_LIGHT0 + i,
+ GL_CONSTANT_ATTENUATION,
+ &g_lighting_data.lights[i].constant_attenuation);
+ glGetLightfv(GL_LIGHT0 + i,
+ GL_LINEAR_ATTENUATION,
+ &g_lighting_data.lights[i].linear_attenuation);
+ glGetLightfv(GL_LIGHT0 + i,
+ GL_QUADRATIC_ATTENUATION,
+ &g_lighting_data.lights[i].quadratic_attenuation);
+ glGetLightfv(GL_LIGHT0 + i,
+ GL_SPOT_CUTOFF,
+ &g_lighting_data.lights[i].spot_cutoff);
+ glGetLightfv(GL_LIGHT0 + i,
+ GL_SPOT_EXPONENT,
+ &g_lighting_data.lights[i].spot_exponent);
+ g_lighting_data.lights[i].spot_cos_cutoff =
+ cos(g_lighting_data.lights[i].spot_cutoff);
+#endif
+ }
+}
+
+static GLuint preapre_patchDraw(GLMeshInterface *mesh,
+ bool fill_quads)
+{
+ GLint program = 0;
+ if (!g_use_osd_glsl) {
+ glGetIntegerv(GL_CURRENT_PROGRAM, &program);
+ if (program) {
+ GLint model;
+ glGetIntegerv(GL_SHADE_MODEL, &model);
+
+ GLint location = glGetUniformLocation(program, "osd_flat_shading");
+ if (location != -1) {
+ glUniform1i(location, model == GL_FLAT);
+ }
+
+ /* TODO(sergey): Bring this back. */
+#if 0
+ /* Face-vertex data */
+ if (mesh->GetDrawContext()->GetFvarDataTextureBuffer()) {
+ glActiveTexture(GL_TEXTURE31);
+ glBindTexture(GL_TEXTURE_BUFFER,
+ mesh->GetDrawContext()->GetFvarDataTextureBuffer());
+ glActiveTexture(GL_TEXTURE0);
+
+ GLint location = glGetUniformLocation(program, "osd_fvar_count");
+ if (location != -1) {
+ glUniform1i(location, mesh->GetFVarCount());
+ }
+
+ location = glGetUniformLocation(program, "osd_active_uv_offset");
+ if (location != -1) {
+ glUniform1i(location,
+ g_active_uv_index * 2);
+ }
+ }
+#endif
+
+ }
+ return program;
+ }
+
+ if (fill_quads) {
+ int model;
+ GLboolean use_texture_2d;
+ glGetIntegerv(GL_SHADE_MODEL, &model);
+ glGetBooleanv(GL_TEXTURE_2D, &use_texture_2d);
+ if (model == GL_FLAT) {
+ if (use_texture_2d) {
+ program = g_flat_fill_texture2d_program;
+ }
+ else {
+ program = g_flat_fill_solid_program;
+ }
+ }
+ else {
+ if (use_texture_2d) {
+ program = g_smooth_fill_texture2d_program;
+ }
+ else {
+ program = g_smooth_fill_solid_program;
+ }
+ }
+ }
+ else {
+ glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
+ program = g_wireframe_program;
+ }
+
+ bindProgram(mesh, program);
+
+ return program;
+}
+
+static void perform_drawElements(GLuint program,
+ int patch_index,
+ int num_elements,
+ int start_element)
+{
+ if (program) {
+ glUniform1i(glGetUniformLocation(program, "PrimitiveIdBase"),
+ patch_index);
+ }
+ glDrawElements(GL_LINES_ADJACENCY,
+ num_elements,
+ GL_UNSIGNED_INT,
+ (void *)(start_element * sizeof(unsigned int)));
+}
+
+static void finish_patchDraw(bool fill_quads)
+{
+ /* TODO(sergey): Some of the stuff could be done once after the whole
+ * mesh is displayed.
+ */
+
+ /* Restore state. */
+ if (!fill_quads) {
+ glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
+ }
+ glBindVertexArray(0);
+
+ if (g_use_osd_glsl) {
+ /* TODO(sergey): Store previously used program and roll back to it? */
+ glUseProgram(0);
+ }
+}
+
+static void draw_partition_patches_range(GLMeshInterface *mesh,
+ GLuint program,
+ int start_patch,
+ int num_patches)
+{
+ int traversed_patches = 0, num_remained_patches = num_patches;
+ const OpenSubdiv::Osd::PatchArrayVector& patches =
+ mesh->GetPatchTable()->GetPatchArrays();
+ for (int i = 0; i < (int)patches.size(); ++i) {
+ const OpenSubdiv::Osd::PatchArray& patch = patches[i];
+ OpenSubdiv::Far::PatchDescriptor desc = patch.GetDescriptor();
+ OpenSubdiv::Far::PatchDescriptor::Type patchType = desc.GetType();
+
+ if (patchType == OpenSubdiv::Far::PatchDescriptor::QUADS) {
+ const int num_block_patches = patch.GetNumPatches();
+ if (start_patch >= traversed_patches &&
+ start_patch < traversed_patches + num_block_patches)
+ {
+ const int num_control_verts = desc.GetNumControlVertices();
+ const int start_draw_patch = start_patch - traversed_patches;
+ const int num_draw_patches = std::min(num_remained_patches,
+ num_block_patches - start_draw_patch);
+ perform_drawElements(program,
+ i,
+ num_draw_patches * num_control_verts,
+ patch.GetIndexBase() + start_draw_patch * num_control_verts);
+ num_remained_patches -= num_draw_patches;
+ }
+ if (num_remained_patches == 0) {
+ break;
+ }
+ traversed_patches += num_block_patches;
+ }
+ }
+}
+
+static void draw_all_patches(GLMeshInterface *mesh,
+ GLuint program)
+{
+ const OpenSubdiv::Osd::PatchArrayVector& patches =
+ mesh->GetPatchTable()->GetPatchArrays();
+ for (int i = 0; i < (int)patches.size(); ++i) {
+ const OpenSubdiv::Osd::PatchArray& patch = patches[i];
+ OpenSubdiv::Far::PatchDescriptor desc = patch.GetDescriptor();
+ OpenSubdiv::Far::PatchDescriptor::Type patchType = desc.GetType();
+
+ if (patchType == OpenSubdiv::Far::PatchDescriptor::QUADS) {
+ perform_drawElements(program,
+ i,
+ patch.GetNumPatches() * desc.GetNumControlVertices(),
+ patch.GetIndexBase());
+ }
+ }
+}
+
+void openSubdiv_osdGLMeshDisplay(OpenSubdiv_GLMesh *gl_mesh,
+ int fill_quads,
+ int start_patch,
+ int num_patches)
+{
+ GLMeshInterface *mesh =
+ (GLMeshInterface *)(gl_mesh->descriptor);
+
+ /* Make sure all global invariants are initialized. */
+ if (!openSubdiv_osdGLDisplayInit()) {
+ return;
+ }
+
+ /* Setup GLSL/OpenGL to draw patches in current context. */
+ GLuint program = preapre_patchDraw(mesh, fill_quads != 0);
+
+ if (start_patch != -1) {
+ draw_partition_patches_range(mesh,
+ program,
+ start_patch,
+ num_patches);
+ }
+ else {
+ draw_all_patches(mesh, program);
+ }
+
+ /* Finish patch drawing by restoring all changes to the OpenGL context. */
+ finish_patchDraw(fill_quads != 0);
+}
diff --git a/intern/opensubdiv/opensubdiv_intern.h b/intern/opensubdiv/opensubdiv_intern.h
new file mode 100644
index 00000000000..ccb32f9d0ac
--- /dev/null
+++ b/intern/opensubdiv/opensubdiv_intern.h
@@ -0,0 +1,46 @@
+/*
+ * ***** 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) 2015 Blender Foundation.
+ * All rights reserved.
+ *
+ * Contributor(s): Sergey Sharybin.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __OPENSUBDIV_INTERN_H__
+#define __OPENSUBDIV_INTERN_H__
+
+/* Perform full topology validation when exporting it to OpenSubdiv. */
+#ifdef NDEBUG
+# undef OPENSUBDIV_VALIDATE_TOPOLOGY
+#else
+/* TODO(sergey): Always disabled for now, the check doesn't handle
+ * multiple non-manifolds from the OpenSubdiv side currently.
+ */
+# undef OPENSUBDIV_VALIDATE_TOPOLOGY
+#endif
+
+/* Currently OpenSubdiv expects topology to be oriented,
+ * but sometimes it's handy to disable orientation code
+ * to check whether it causes some weird issues by using
+ * pre-oriented model.
+ */
+#define OPENSUBDIV_ORIENT_TOPOLOGY
+
+#endif /* __OPENSUBDIV_INTERN_H__ */
diff --git a/intern/opensubdiv/opensubdiv_utils_capi.cc b/intern/opensubdiv/opensubdiv_utils_capi.cc
new file mode 100644
index 00000000000..a945484ba61
--- /dev/null
+++ b/intern/opensubdiv/opensubdiv_utils_capi.cc
@@ -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) 2013 Blender Foundation.
+ * All rights reserved.
+ *
+ * Contributor(s): Sergey Sharybin.
+ * Brecht van Lommel
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include "opensubdiv_capi.h"
+
+#include <cstring>
+#include <GL/glew.h>
+
+#ifdef _MSC_VER
+# include "iso646.h"
+#endif
+
+#ifdef OPENSUBDIV_HAS_OPENCL
+# include "opensubdiv_device_context_opencl.h"
+#endif /* OPENSUBDIV_HAS_OPENCL */
+
+#ifdef OPENSUBDIV_HAS_CUDA
+# include "opensubdiv_device_context_cuda.h"
+#endif /* OPENSUBDIV_HAS_CUDA */
+
+int openSubdiv_getAvailableEvaluators(void)
+{
+ if (!openSubdiv_supportGPUDisplay()) {
+ return 0;
+ }
+
+ int flags = OPENSUBDIV_EVALUATOR_CPU;
+
+#ifdef OPENSUBDIV_HAS_OPENMP
+ flags |= OPENSUBDIV_EVALUATOR_OPENMP;
+#endif /* OPENSUBDIV_HAS_OPENMP */
+
+#ifdef OPENSUBDIV_HAS_OPENCL
+ if (CLDeviceContext::HAS_CL_VERSION_1_1()) {
+ flags |= OPENSUBDIV_EVALUATOR_OPENCL;
+ }
+#endif /* OPENSUBDIV_HAS_OPENCL */
+
+#ifdef OPENSUBDIV_HAS_CUDA
+ if (CudaDeviceContext::HAS_CUDA_VERSION_4_0()) {
+ flags |= OPENSUBDIV_EVALUATOR_CUDA;
+ }
+#endif /* OPENSUBDIV_HAS_OPENCL */
+
+#ifdef OPENSUBDIV_HAS_GLSL_TRANSFORM_FEEDBACK
+ if (GLEW_ARB_texture_buffer_object) {
+ flags |= OPENSUBDIV_EVALUATOR_GLSL_TRANSFORM_FEEDBACK;
+ }
+#endif /* OPENSUBDIV_HAS_GLSL_TRANSFORM_FEEDBACK */
+
+#ifdef OPENSUBDIV_HAS_GLSL_COMPUTE
+ static bool vendor_checked = false;
+ static bool disable_glsl_compute = false;
+ /* Force disable GLSL Compute on AMD hardware because it has really
+ * hard time evaluating required shaders.
+ */
+ if (!vendor_checked) {
+ vendor_checked = true;
+ const char *vendor = (const char *)glGetString(GL_VENDOR);
+ const char *renderer = (const char *)glGetString(GL_RENDERER);
+ if (vendor != NULL && renderer != NULL) {
+ if (strstr(vendor, "ATI") ||
+ strstr(renderer, "Mesa DRI R") ||
+ (strstr(renderer, "Gallium ") && strstr(renderer, " on ATI ")))
+ {
+ disable_glsl_compute = true;
+ }
+ }
+ }
+ if (!disable_glsl_compute) {
+ flags |= OPENSUBDIV_EVALUATOR_GLSL_COMPUTE;
+ }
+#endif /* OPENSUBDIV_HAS_GLSL_COMPUTE */
+
+ return flags;
+}
+
+void openSubdiv_init(void)
+{
+ /* Ensure all OpenGL strings are cached. */
+ (void)openSubdiv_getAvailableEvaluators();
+}
+
+void openSubdiv_cleanup(void)
+{
+ openSubdiv_osdGLDisplayDeinit();
+}
diff --git a/intern/smoke/intern/FLUID_3D.cpp b/intern/smoke/intern/FLUID_3D.cpp
index a43d94a7790..4faec894801 100644
--- a/intern/smoke/intern/FLUID_3D.cpp
+++ b/intern/smoke/intern/FLUID_3D.cpp
@@ -1587,7 +1587,7 @@ void FLUID_3D::advectMacCormackEnd2(int zBegin, int zEnd)
}
-void FLUID_3D::processBurn(float *fuel, float *smoke, float *react, float *flame, float *heat,
+void FLUID_3D::processBurn(float *fuel, float *smoke, float *react, float *heat,
float *r, float *g, float *b, int total_cells, float dt)
{
float burning_rate = *_burning_rate;
@@ -1600,7 +1600,7 @@ void FLUID_3D::processBurn(float *fuel, float *smoke, float *react, float *flame
float orig_fuel = fuel[index];
float orig_smoke = smoke[index];
float smoke_emit = 0.0f;
- float react_coord = 0.0f;
+ float flame = 0.0f;
/* process fuel */
fuel[index] -= burning_rate * dt;
@@ -1608,7 +1608,7 @@ void FLUID_3D::processBurn(float *fuel, float *smoke, float *react, float *flame
/* process reaction coordinate */
if (orig_fuel > FLT_EPSILON) {
react[index] *= fuel[index]/orig_fuel;
- react_coord = react[index];
+ flame = pow(react[index], 0.5f);
}
else {
react[index] = 0.0f;
@@ -1620,17 +1620,9 @@ void FLUID_3D::processBurn(float *fuel, float *smoke, float *react, float *flame
smoke[index] += smoke_emit;
CLAMP(smoke[index], 0.0f, 1.0f);
- /* model flame temperature curve from the reaction coordinate (fuel) */
- if (react_coord>0.0f) {
- /* do a smooth falloff for rest of the values */
- flame[index] = pow(react_coord, 0.5f);
- }
- else
- flame[index] = 0.0f;
-
/* set fluid temperature from the flame temperature profile */
- if (heat && flame[index])
- heat[index] = (1.0f-flame[index])*ignition_point + flame[index]*temp_max;
+ if (heat && flame)
+ heat[index] = (1.0f - flame)*ignition_point + flame*temp_max;
/* mix new color */
if (r && smoke_emit > FLT_EPSILON) {
@@ -1641,3 +1633,21 @@ void FLUID_3D::processBurn(float *fuel, float *smoke, float *react, float *flame
}
}
}
+
+void FLUID_3D::updateFlame(float *react, float *flame, int total_cells)
+{
+ for (int index = 0; index < total_cells; index++)
+ {
+ /* model flame temperature curve from the reaction coordinate (fuel)
+ * TODO: Would probably be best to get rid of whole "flame" data field.
+ * Currently it's just sqrt mirror of reaction coordinate, and therefore
+ * basically just waste of memory and disk space...
+ */
+ if (react[index]>0.0f) {
+ /* do a smooth falloff for rest of the values */
+ flame[index] = pow(react[index], 0.5f);
+ }
+ else
+ flame[index] = 0.0f;
+ }
+} \ No newline at end of file
diff --git a/intern/smoke/intern/FLUID_3D.h b/intern/smoke/intern/FLUID_3D.h
index d98a39930de..cd2147b2bee 100644
--- a/intern/smoke/intern/FLUID_3D.h
+++ b/intern/smoke/intern/FLUID_3D.h
@@ -209,8 +209,9 @@ struct FLUID_3D
float *_flame_vorticity; // RNA pointer
float *_ignition_temp; // RNA pointer
float *_max_temp; // RNA pointer
- void processBurn(float *fuel, float *smoke, float *react, float *flame, float *heat,
+ void processBurn(float *fuel, float *smoke, float *react, float *heat,
float *r, float *g, float *b, int total_cells, float dt);
+ void updateFlame(float *react, float *flame, int total_cells);
// boundary setting functions
static void copyBorderX(float* field, Vec3Int res, int zBegin, int zEnd);
diff --git a/intern/smoke/intern/smoke_API.cpp b/intern/smoke/intern/smoke_API.cpp
index e25dff00d23..d79aaf76d56 100644
--- a/intern/smoke/intern/smoke_API.cpp
+++ b/intern/smoke/intern/smoke_API.cpp
@@ -77,19 +77,27 @@ extern "C" size_t smoke_get_index2d(int x, int max_x, int y /*, int max_y, int z
extern "C" void smoke_step(FLUID_3D *fluid, float gravity[3], float dtSubdiv)
{
if (fluid->_fuel) {
- fluid->processBurn(fluid->_fuel, fluid->_density, fluid->_react, fluid->_flame, fluid->_heat,
+ fluid->processBurn(fluid->_fuel, fluid->_density, fluid->_react, fluid->_heat,
fluid->_color_r, fluid->_color_g, fluid->_color_b, fluid->_totalCells, (*fluid->_dtFactor)*dtSubdiv);
}
fluid->step(dtSubdiv, gravity);
+
+ if (fluid->_fuel) {
+ fluid->updateFlame(fluid->_react, fluid->_flame, fluid->_totalCells);
+ }
}
extern "C" void smoke_turbulence_step(WTURBULENCE *wt, FLUID_3D *fluid)
{
if (wt->_fuelBig) {
- fluid->processBurn(wt->_fuelBig, wt->_densityBig, wt->_reactBig, wt->_flameBig, 0,
+ fluid->processBurn(wt->_fuelBig, wt->_densityBig, wt->_reactBig, 0,
wt->_color_rBig, wt->_color_gBig, wt->_color_bBig, wt->_totalCellsBig, fluid->_dt);
}
- wt->stepTurbulenceFull(fluid->_dt/fluid->_dx, fluid->_xVelocity, fluid->_yVelocity, fluid->_zVelocity, fluid->_obstacles);
+ wt->stepTurbulenceFull(fluid->_dt/fluid->_dx, fluid->_xVelocity, fluid->_yVelocity, fluid->_zVelocity, fluid->_obstacles);
+
+ if (wt->_fuelBig) {
+ fluid->updateFlame(wt->_reactBig, wt->_flameBig, wt->_totalCellsBig);
+ }
}
extern "C" void smoke_initBlenderRNA(FLUID_3D *fluid, float *alpha, float *beta, float *dt_factor, float *vorticity, int *border_colli, float *burning_rate,
diff --git a/intern/smoke/intern/spectrum.cpp b/intern/smoke/intern/spectrum.cpp
index e1c2b4d1e42..15e4d0cf2e5 100644
--- a/intern/smoke/intern/spectrum.cpp
+++ b/intern/smoke/intern/spectrum.cpp
@@ -363,7 +363,7 @@ static void spectrum_to_xyz(double (*spec_intens)(double wavelength),
Calculate, by Planck's radiation law, the emittance of a black body
of temperature bbTemp at the given wavelength (in metres). */
-double bbTemp = 5000; /* Hidden temperature argument
+static double bbTemp = 5000; /* Hidden temperature argument
to BB_SPECTRUM. */
static double bb_spectrum(double wavelength)
{
diff --git a/release/bin/blender-thumbnailer.py b/release/bin/blender-thumbnailer.py
index 779c6156e70..fe5d462bba9 100755
--- a/release/bin/blender-thumbnailer.py
+++ b/release/bin/blender-thumbnailer.py
@@ -88,9 +88,8 @@ def blend_extract_thumb(path):
import os
open_wrapper = open_wrapper_get()
- # def MAKE_ID(tag): ord(tag[0])<<24 | ord(tag[1])<<16 | ord(tag[2])<<8 | ord(tag[3])
- REND = 1145980242 # MAKE_ID(b'REND')
- TEST = 1414743380 # MAKE_ID(b'TEST')
+ REND = b'REND'
+ TEST = b'TEST'
blendfile = open_wrapper(path, 'rb')
@@ -116,7 +115,8 @@ def blend_extract_thumb(path):
return None, 0, 0
sizeof_bhead = 24 if is_64_bit else 20
- int_endian_pair = '>ii' if is_big_endian else '<ii'
+ int_endian = '>i' if is_big_endian else '<i'
+ int_endian_pair = int_endian + 'i'
while True:
bhead = blendfile.read(sizeof_bhead)
@@ -124,7 +124,8 @@ def blend_extract_thumb(path):
if len(bhead) < sizeof_bhead:
return None, 0, 0
- code, length = struct.unpack(int_endian_pair, bhead[0:8]) # 8 == sizeof(int) * 2
+ code = bhead[:4]
+ length = struct.unpack(int_endian, bhead[4:8])[0] # 4 == sizeof(int)
if code == REND:
blendfile.seek(length, os.SEEK_CUR)
@@ -170,7 +171,7 @@ def write_png(buf, width, height):
png_pack(b'IEND', b'')])
-if __name__ == '__main__':
+def main():
import sys
if len(sys.argv) < 3:
@@ -186,3 +187,7 @@ if __name__ == '__main__':
f = open(file_out, "wb")
f.write(write_png(buf, width, height))
f.close()
+
+
+if __name__ == '__main__':
+ main()
diff --git a/release/datafiles/LICENSE-droidsans.ttf.txt b/release/datafiles/LICENSE-droidsans.ttf.txt
index ca0d6bbaea1..cf6f53e8644 100644
--- a/release/datafiles/LICENSE-droidsans.ttf.txt
+++ b/release/datafiles/LICENSE-droidsans.ttf.txt
@@ -6,6 +6,8 @@ Blender Main I18n font ("droidsans.ttf") includes glyphs imported from the follo
4. Droid Sans Hebrew Regular
5. Droid Sans Ethiopic Regular
6. Samyak-tamil
+7. KhmerOSsys
+8. tlwg' Loma (Thaï)
These were merged using FontForge in (approximately) the above order. For each glyph,
a license of the font from which it was imported is applied.
@@ -40,6 +42,19 @@ Copyright: 2005-2006, Rahul Bhalerao <b.rahul.pm@gmail.com>
License: GPL-3 with font embedding exception
See Appendices B.
+(7) KhmerOSsys
+Copyright: 2005, 2006 Danh Hong
+ 2005, 2006 Open Forum of Cambodia
+
+License: GPL-2.1+
+ See Appendices C.
+
+(8) tlwg Loma (Thaï)
+Copyright: 2003 National Electronics and Computer Technology Center
+
+License: GPL-2+ with Font exception
+ See Appendices C.
+
----------------------------------------------------------------------
Appendix A. Apache License Version 2.0
@@ -82,3 +97,20 @@ Font embedding exception:
modify this font, you may extend this exception to your version of
the font, but you are not obligated to do so. If you do not wish to
do so, delete this exception statement from your version.
+
+----------------------------------------------------------------------
+Appendix C. GNU GPL Version 2.1
+
+This font is free software; you can redistribute it and/or modify it
+under the terms of the GNU Lesser General Public License as published
+by the Free Software Foundation; either version 2.1 of the License, or
+(at your option) any later version.
+
+This library 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 Lesser General Public
+License for more details.
+
+On Debian systems, the complete text of the GNU Lesser General Public
+License can be found in the file /usr/share/common-licenses/LGPL-2.
+
diff --git a/release/datafiles/blender_icons.svg b/release/datafiles/blender_icons.svg
index 4a1e2cd1d9a..1923b93577a 100644
--- a/release/datafiles/blender_icons.svg
+++ b/release/datafiles/blender_icons.svg
@@ -14,7 +14,7 @@
height="640"
id="svg2"
sodipodi:version="0.32"
- inkscape:version="0.48.5 r10040"
+ inkscape:version="0.91 r13725"
version="1.0"
sodipodi:docname="blender_icons.svg"
inkscape:output_extension="org.inkscape.output.svg.inkscape"
@@ -27,6 +27,149 @@
<defs
id="defs4">
<linearGradient
+ id="linearGradient31767"
+ inkscape:collect="always">
+ <stop
+ id="stop31769"
+ offset="0"
+ style="stop-color:#4d4d4d;stop-opacity:0" />
+ <stop
+ id="stop31771"
+ offset="1"
+ style="stop-color:#4d4d4d;stop-opacity:1" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient20043">
+ <stop
+ style="stop-color:#f6e18c;stop-opacity:1;"
+ offset="0"
+ id="stop20045" />
+ <stop
+ style="stop-color:#f6e18c;stop-opacity:0;"
+ offset="1"
+ id="stop20047" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient20020">
+ <stop
+ style="stop-color:#f6e18c;stop-opacity:1;"
+ offset="0"
+ id="stop20022" />
+ <stop
+ style="stop-color:#f6e18c;stop-opacity:0;"
+ offset="1"
+ id="stop20024" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient18512">
+ <stop
+ id="stop18514"
+ offset="0"
+ style="stop-color:#ffffff;stop-opacity:1;" />
+ <stop
+ id="stop18516"
+ offset="1"
+ style="stop-color:#f20000;stop-opacity:1;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient18495"
+ inkscape:collect="always">
+ <stop
+ id="stop18497"
+ offset="0"
+ style="stop-color:#000000;stop-opacity:1;" />
+ <stop
+ id="stop18499"
+ offset="1"
+ style="stop-color:#000000;stop-opacity:0;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient18479"
+ inkscape:collect="always">
+ <stop
+ id="stop18481"
+ offset="0"
+ style="stop-color:#8d8d8d;stop-opacity:1;" />
+ <stop
+ id="stop18483"
+ offset="1"
+ style="stop-color:#8d8d8d;stop-opacity:0;" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient18414">
+ <stop
+ style="stop-color:#000000;stop-opacity:1;"
+ offset="0"
+ id="stop18416" />
+ <stop
+ style="stop-color:#000000;stop-opacity:0;"
+ offset="1"
+ id="stop18418" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient18370"
+ inkscape:collect="always">
+ <stop
+ id="stop18372"
+ offset="0"
+ style="stop-color:#afafaf;stop-opacity:1;" />
+ <stop
+ id="stop18374"
+ offset="1"
+ style="stop-color:#afafaf;stop-opacity:0;" />
+ </linearGradient>
+ <marker
+ inkscape:stockid="Arrow1Lstart"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="Arrow1Lstart"
+ style="overflow:visible">
+ <path
+ id="path17576"
+ d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt"
+ transform="scale(0.8) translate(12.5,0)" />
+ </marker>
+ <linearGradient
+ id="linearGradient17566"
+ inkscape:collect="always">
+ <stop
+ id="stop17568"
+ offset="0"
+ style="stop-color:#cad8ee;stop-opacity:1;" />
+ <stop
+ id="stop17570"
+ offset="1"
+ style="stop-color:#cad8ee;stop-opacity:0;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient17560">
+ <stop
+ id="stop17562"
+ offset="0"
+ style="stop-color:#ffe991;stop-opacity:1;" />
+ <stop
+ id="stop17564"
+ offset="1"
+ style="stop-color:#ffe991;stop-opacity:0;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient17542"
+ inkscape:collect="always">
+ <stop
+ id="stop17544"
+ offset="0"
+ style="stop-color:#799ed3;stop-opacity:1;" />
+ <stop
+ id="stop17546"
+ offset="1"
+ style="stop-color:#799ed3;stop-opacity:0;" />
+ </linearGradient>
+ <linearGradient
id="linearGradient17265">
<stop
style="stop-color:#ffb769;stop-opacity:1;"
@@ -4796,26 +4939,6 @@
y1="-35.483223"
x2="408.75"
y2="-40.000008" />
- <linearGradient
- inkscape:collect="always"
- xlink:href="#linearGradient37542"
- id="linearGradient17429"
- gradientUnits="userSpaceOnUse"
- gradientTransform="matrix(1.081988,0,0,1.0833333,-394.58897,440.54169)"
- x1="326.51352"
- y1="32.007874"
- x2="347.91187"
- y2="57.261913" />
- <linearGradient
- inkscape:collect="always"
- xlink:href="#linearGradient319"
- id="linearGradient17431"
- gradientUnits="userSpaceOnUse"
- gradientTransform="matrix(1.0983862,0,0,1.0999999,-400.00857,439.95001)"
- x1="317.30908"
- y1="22.7787"
- x2="330.87869"
- y2="38.161732" />
<mask
maskUnits="userSpaceOnUse"
id="mask17570">
@@ -21987,15 +22110,6 @@
y2="360.82117" />
<linearGradient
inkscape:collect="always"
- xlink:href="#linearGradient29757"
- id="linearGradient29763"
- x1="-224.85715"
- y1="205.71428"
- x2="-214.42857"
- y2="206"
- gradientUnits="userSpaceOnUse" />
- <linearGradient
- inkscape:collect="always"
xlink:href="#linearGradient23705-0"
id="linearGradient22892-4"
gradientUnits="userSpaceOnUse"
@@ -28316,6 +28430,2513 @@
r="3.5"
gradientTransform="matrix(1.4878857,2.6976762,-1.4698319,0.81067624,95.409128,-2969.0604)"
gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542-5-7-1"
+ id="linearGradient27886-9-1"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,1,1,0,146.99795,-188.00607)"
+ x1="392.0101"
+ y1="222.99998"
+ x2="392.0101"
+ y2="247.99998" />
+ <linearGradient
+ id="linearGradient37542-5-7-1">
+ <stop
+ id="stop37544-1-4-3"
+ offset="0"
+ style="stop-color:#000000;stop-opacity:1;" />
+ <stop
+ id="stop37546-71-0-8"
+ offset="1"
+ style="stop-color:#ffffff;stop-opacity:1;" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient27896-8-4"
+ id="linearGradient27902-4-7"
+ x1="388.70071"
+ y1="244.85669"
+ x2="391.17557"
+ y2="249.54126"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient27896-8-4">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop27898-8-2" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop27900-2-7" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542-5-7-3-9"
+ id="linearGradient16731"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,1,1,0,146.99795,-188.00607)"
+ x1="392.0101"
+ y1="222.99998"
+ x2="392.0101"
+ y2="247.99998" />
+ <linearGradient
+ id="linearGradient37542-5-7-3-9">
+ <stop
+ id="stop37544-1-4-8-3"
+ offset="0"
+ style="stop-color:#000000;stop-opacity:1;" />
+ <stop
+ id="stop37546-71-0-2-1"
+ offset="1"
+ style="stop-color:#ffffff;stop-opacity:1;" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient27896-8-2-8"
+ id="linearGradient27902-4-6-9"
+ x1="388.70071"
+ y1="244.85669"
+ x2="391.17557"
+ y2="249.54126"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient27896-8-2-8">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop27898-8-7-6" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop27900-2-5-5" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542-5-7-7-4"
+ id="linearGradient17449-1-5"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-271.98012,212.40154)"
+ x1="392.0101"
+ y1="222.99998"
+ x2="392.0101"
+ y2="247.99998" />
+ <linearGradient
+ id="linearGradient37542-5-7-7-4">
+ <stop
+ id="stop37544-1-4-40-3"
+ offset="0"
+ style="stop-color:#000000;stop-opacity:1;" />
+ <stop
+ id="stop37546-71-0-9-1"
+ offset="1"
+ style="stop-color:#ffffff;stop-opacity:1;" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542-5-7-5-8-3"
+ id="linearGradient17451-4-2"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-271.98739,215.4952)"
+ x1="392.0101"
+ y1="222.99998"
+ x2="392.0101"
+ y2="247.99998" />
+ <linearGradient
+ id="linearGradient37542-5-7-5-8-3">
+ <stop
+ id="stop37544-1-4-4-8-3"
+ offset="0"
+ style="stop-color:#000000;stop-opacity:1;" />
+ <stop
+ id="stop37546-71-0-3-2-4"
+ offset="1"
+ style="stop-color:#ffffff;stop-opacity:1;" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542-5-7-7-4"
+ id="linearGradient16559"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-271.98012,212.40154)"
+ x1="392.0101"
+ y1="222.99998"
+ x2="392.0101"
+ y2="247.99998" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542-5-7-5-8-3"
+ id="linearGradient16562"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-271.98739,215.4952)"
+ x1="392.0101"
+ y1="222.99998"
+ x2="392.0101"
+ y2="247.99998" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542-29"
+ id="linearGradient15742-2"
+ gradientUnits="userSpaceOnUse"
+ x1="392.0101"
+ y1="224.99998"
+ x2="392.0101"
+ y2="249.99998" />
+ <linearGradient
+ id="linearGradient37542-29">
+ <stop
+ id="stop37544-67"
+ offset="0"
+ style="stop-color:#000000;stop-opacity:1;" />
+ <stop
+ id="stop37546-45"
+ offset="1"
+ style="stop-color:#ffffff;stop-opacity:1;" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient27854-0"
+ id="linearGradient27860-8"
+ x1="392.02036"
+ y1="241.13428"
+ x2="386.30408"
+ y2="241.31801"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient27854-0">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop27856-5" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop27858-3" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542-5-3"
+ id="linearGradient27886-8"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,1,1,0,146.99795,-188.00607)"
+ x1="392.0101"
+ y1="222.99998"
+ x2="392.0101"
+ y2="247.99998" />
+ <linearGradient
+ id="linearGradient37542-5-3">
+ <stop
+ id="stop37544-1-6"
+ offset="0"
+ style="stop-color:#000000;stop-opacity:1;" />
+ <stop
+ id="stop37546-71-6"
+ offset="1"
+ style="stop-color:#ffffff;stop-opacity:1;" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient27896-9"
+ id="linearGradient27902-9"
+ x1="388.70071"
+ y1="244.85669"
+ x2="391.17557"
+ y2="249.54126"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient27896-9">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop27898-2" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop27900-5" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542-92"
+ id="linearGradient27872-8"
+ gradientUnits="userSpaceOnUse"
+ x1="392.0101"
+ y1="224.99998"
+ x2="392.0101"
+ y2="249.99998"
+ gradientTransform="matrix(-1,0,0,1,782.02022,0)" />
+ <linearGradient
+ id="linearGradient37542-92">
+ <stop
+ id="stop37544-71"
+ offset="0"
+ style="stop-color:#000000;stop-opacity:1;" />
+ <stop
+ id="stop37546-57"
+ offset="1"
+ style="stop-color:#ffffff;stop-opacity:1;" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient27854-7"
+ id="linearGradient27874-3"
+ gradientUnits="userSpaceOnUse"
+ x1="390.87131"
+ y1="241.13428"
+ x2="386.74603"
+ y2="242.46706"
+ gradientTransform="matrix(-1,0,0,1,782.02022,0)" />
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient27854-7">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop27856-6" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop27858-1" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542-5-3"
+ id="linearGradient15742-5-4"
+ gradientUnits="userSpaceOnUse"
+ x1="392.0101"
+ y1="222.99998"
+ x2="392.0101"
+ y2="247.99998"
+ gradientTransform="matrix(0,1,-1,0,634.98585,-146.00607)" />
+ <linearGradient
+ id="linearGradient16550">
+ <stop
+ id="stop16552"
+ offset="0"
+ style="stop-color:#000000;stop-opacity:1;" />
+ <stop
+ id="stop16554"
+ offset="1"
+ style="stop-color:#ffffff;stop-opacity:1;" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542-51"
+ id="linearGradient15691-9"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.222225,0,0,1,-87.33412,169)"
+ x1="215.07817"
+ y1="109.00085"
+ x2="235.90916"
+ y2="121.88217" />
+ <linearGradient
+ id="linearGradient37542-51">
+ <stop
+ id="stop37544-63"
+ offset="0"
+ style="stop-color:#000000;stop-opacity:1;" />
+ <stop
+ id="stop37546-08"
+ offset="1"
+ style="stop-color:#ffffff;stop-opacity:1;" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-36"
+ id="linearGradient15693-2"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,1.253963,1,0,169,-94.7765)"
+ x1="228.5468"
+ y1="118.5"
+ x2="235"
+ y2="118.5" />
+ <linearGradient
+ id="linearGradient319-36">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop320-18" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop321-390" />
+ </linearGradient>
+ <linearGradient
+ y2="118.5"
+ x2="235"
+ y1="118.5"
+ x1="228.5468"
+ gradientTransform="matrix(0,1.253963,1,0,169,-94.7765)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient16667"
+ xlink:href="#linearGradient319-36"
+ inkscape:collect="always" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542-51"
+ id="linearGradient16712"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.222225,0,0,1,-87.33412,169)"
+ x1="215.07817"
+ y1="109.00085"
+ x2="235.90916"
+ y2="121.88217" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-36"
+ id="linearGradient16714"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,1.253963,1,0,169,-94.7765)"
+ x1="228.5468"
+ y1="118.5"
+ x2="235"
+ y2="118.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542-51-7"
+ id="linearGradient16712-3"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.222225,0,0,1,-87.33412,169)"
+ x1="215.07817"
+ y1="109.00085"
+ x2="235.90916"
+ y2="121.88217" />
+ <linearGradient
+ id="linearGradient37542-51-7">
+ <stop
+ id="stop37544-63-0"
+ offset="0"
+ style="stop-color:#000000;stop-opacity:1;" />
+ <stop
+ id="stop37546-08-1"
+ offset="1"
+ style="stop-color:#ffffff;stop-opacity:1;" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-36-1"
+ id="linearGradient16714-5"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,1.253963,1,0,169,-94.7765)"
+ x1="228.5468"
+ y1="118.5"
+ x2="235"
+ y2="118.5" />
+ <linearGradient
+ id="linearGradient319-36-1">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop320-18-2" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop321-390-9" />
+ </linearGradient>
+ <linearGradient
+ y2="119.8485"
+ x2="228.5468"
+ y1="118.94354"
+ x1="228.5468"
+ gradientTransform="matrix(0,-1.253963,1,0,169,484.55432)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient16763"
+ xlink:href="#linearGradient319-36-1"
+ inkscape:collect="always" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542-29"
+ id="linearGradient17562"
+ gradientUnits="userSpaceOnUse"
+ x1="392.0101"
+ y1="224.99998"
+ x2="392.0101"
+ y2="249.99998" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient27854-0"
+ id="linearGradient17564"
+ gradientUnits="userSpaceOnUse"
+ x1="392.02036"
+ y1="241.13428"
+ x2="386.30408"
+ y2="241.31801" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient27854-0"
+ id="linearGradient17567"
+ gradientUnits="userSpaceOnUse"
+ x1="392.02036"
+ y1="241.13428"
+ x2="386.30408"
+ y2="241.31801"
+ gradientTransform="matrix(-1,0,0,1,461.01011,-167)" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542-29"
+ id="linearGradient17570"
+ gradientUnits="userSpaceOnUse"
+ x1="392.0101"
+ y1="224.99998"
+ x2="392.0101"
+ y2="249.99998"
+ gradientTransform="matrix(-1,0,0,1,461.01011,-167)" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542-51"
+ id="linearGradient17572"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.222225,0,0,1,-87.33412,169)"
+ x1="215.07817"
+ y1="109.00085"
+ x2="235.90916"
+ y2="121.88217" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-36"
+ id="linearGradient17574"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,1.253963,1,0,169,-94.7765)"
+ x1="228.5468"
+ y1="118.5"
+ x2="235"
+ y2="118.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-36"
+ id="linearGradient17577"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,1.1418188,0.91056814,0,-34.152024,-186.34771)"
+ x1="228.5468"
+ y1="118.5"
+ x2="235"
+ y2="118.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542-51"
+ id="linearGradient17580"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.1129191,0,0,0.91056814,-179.57092,-34.152024)"
+ x1="215.07817"
+ y1="109.00085"
+ x2="235.90916"
+ y2="121.88217" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542-29"
+ id="linearGradient17610"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-1,0,0,1,461.01011,-167)"
+ x1="392.0101"
+ y1="224.99998"
+ x2="392.0101"
+ y2="249.99998" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-36"
+ id="linearGradient17612"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,1.1418188,0.91056814,0,-34.152024,-186.34771)"
+ x1="228.5468"
+ y1="118.5"
+ x2="235"
+ y2="118.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient27854-0"
+ id="linearGradient17614"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-1,0,0,1,461.01011,-167)"
+ x1="392.02036"
+ y1="241.13428"
+ x2="386.30408"
+ y2="241.31801" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542-29-1"
+ id="linearGradient17610-2"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-1,0,0,1,461.01011,-167)"
+ x1="409.93588"
+ y1="249.99998"
+ x2="385.11514"
+ y2="249.99998" />
+ <linearGradient
+ id="linearGradient37542-29-1">
+ <stop
+ id="stop37544-67-8"
+ offset="0"
+ style="stop-color:#000000;stop-opacity:1;" />
+ <stop
+ id="stop37546-45-9"
+ offset="1"
+ style="stop-color:#ffffff;stop-opacity:1;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient319-36-4">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop320-18-4" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop321-390-6" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542-29-7"
+ id="linearGradient17610-0"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-1,0,0,1,461.01011,-167)"
+ x1="392.0101"
+ y1="224.99998"
+ x2="392.0101"
+ y2="249.99998" />
+ <linearGradient
+ id="linearGradient37542-29-7">
+ <stop
+ id="stop37544-67-3"
+ offset="0"
+ style="stop-color:#000000;stop-opacity:1;" />
+ <stop
+ id="stop37546-45-0"
+ offset="1"
+ style="stop-color:#ffffff;stop-opacity:1;" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-36-40"
+ id="linearGradient17612-5"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,1.1418188,-0.91056814,0,182.56319,-186.34771)"
+ x1="228.5468"
+ y1="118.5"
+ x2="235"
+ y2="118.5" />
+ <linearGradient
+ id="linearGradient319-36-40">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop320-18-7" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop321-390-4" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient27854-0-6"
+ id="linearGradient17614-0"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-1,0,0,1,461.01011,-167)"
+ x1="391.49002"
+ y1="240.9575"
+ x2="395.27548"
+ y2="242.57755" />
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient27854-0-6">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop27856-5-3" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop27858-3-6" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542-29-7-8"
+ id="linearGradient17610-0-6"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-1,0,0,1,461.01011,-167)"
+ x1="368.97806"
+ y1="249.99998"
+ x2="393.85385"
+ y2="249.99998" />
+ <linearGradient
+ id="linearGradient37542-29-7-8">
+ <stop
+ id="stop37544-67-3-0"
+ offset="0"
+ style="stop-color:#000000;stop-opacity:1;" />
+ <stop
+ id="stop37546-45-0-9"
+ offset="1"
+ style="stop-color:#ffffff;stop-opacity:1;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient319-36-40-3">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop320-18-7-2" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop321-390-4-0" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient27854-0-6-9"
+ id="linearGradient17614-0-2"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-1,0,0,1,461.01011,-167)"
+ x1="388.86502"
+ y1="244.02"
+ x2="391.43173"
+ y2="239.2338" />
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient27854-0-6-9">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop27856-5-3-8" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop27858-3-6-3" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-36-40-2"
+ id="linearGradient17612-5-3"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,1.1418188,-0.91056814,0,182.56319,-186.34771)"
+ x1="228.5468"
+ y1="118.5"
+ x2="235"
+ y2="118.5" />
+ <linearGradient
+ id="linearGradient319-36-40-2">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop320-18-7-8" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop321-390-4-6" />
+ </linearGradient>
+ <linearGradient
+ y2="119.99294"
+ x2="228.5468"
+ y1="118.91647"
+ x1="228.5468"
+ gradientTransform="matrix(1.180548,0,0,0.90042534,265.27784,265.13062)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient17838"
+ xlink:href="#linearGradient319-36-40-2"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="119.99294"
+ x2="228.5468"
+ y1="118.91647"
+ x1="228.5468"
+ gradientTransform="matrix(1.180548,0,0,0.90042534,265.27784,265.13062)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient17838-1"
+ xlink:href="#linearGradient319-36-40-2-4"
+ inkscape:collect="always" />
+ <linearGradient
+ id="linearGradient319-36-40-2-4">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop320-18-7-8-5" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop321-390-4-6-6" />
+ </linearGradient>
+ <linearGradient
+ y2="119.99294"
+ x2="228.5468"
+ y1="118.91647"
+ x1="228.5468"
+ gradientTransform="matrix(1.180548,0,0,0.90042534,223.26222,270.47438)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient17872"
+ xlink:href="#linearGradient319-36-40-2-4"
+ inkscape:collect="always" />
+ <linearGradient
+ id="linearGradient23974-41">
+ <stop
+ id="stop23976-66"
+ offset="0"
+ style="stop-color:#2561b7;stop-opacity:1;" />
+ <stop
+ id="stop23978-15"
+ offset="1"
+ style="stop-color:#f9fbff;stop-opacity:1" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient319-68">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop320-221" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop321-90" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient1610-84">
+ <stop
+ style="stop-color:black;stop-opacity:1;"
+ offset="0"
+ id="stop1611-86" />
+ <stop
+ style="stop-color:white;stop-opacity:1;"
+ offset="1"
+ id="stop1612-6" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient9030-4">
+ <stop
+ style="stop-color:white;stop-opacity:1;"
+ offset="0"
+ id="stop9032-3" />
+ <stop
+ style="stop-color:white;stop-opacity:0;"
+ offset="1"
+ id="stop9034-9" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient16500-8">
+ <stop
+ style="stop-color:black;stop-opacity:1;"
+ offset="0"
+ id="stop16502-0" />
+ <stop
+ style="stop-color:black;stop-opacity:0;"
+ offset="1"
+ id="stop16504-648" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient16605">
+ <stop
+ id="stop16607"
+ offset="0"
+ style="stop-color:#2561b7;stop-opacity:1;" />
+ <stop
+ id="stop16609"
+ offset="1"
+ style="stop-color:#f9fbff;stop-opacity:1" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient18105-1">
+ <stop
+ id="stop18107-7"
+ offset="0"
+ style="stop-color:#162d50;stop-opacity:1" />
+ <stop
+ id="stop18109-8"
+ offset="1"
+ style="stop-color:#1e3e70;stop-opacity:0;" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient17542"
+ id="linearGradient18237"
+ gradientUnits="userSpaceOnUse"
+ x1="231.35262"
+ y1="465.73871"
+ x2="246.08743"
+ y2="465.14655"
+ gradientTransform="matrix(0.86988738,-0.49325039,0.49325039,0.86988738,0,0.02266763)" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient17566"
+ id="linearGradient18239"
+ gradientUnits="userSpaceOnUse"
+ x1="430.78629"
+ y1="290.24094"
+ x2="440.83713"
+ y2="286.97058" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient23974-41"
+ id="linearGradient18243"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.728189,0,0,1.727271,-142.53857,-4.802156)"
+ x1="107.39532"
+ y1="58.065113"
+ x2="127.70434"
+ y2="58.065113" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-68"
+ id="linearGradient18245"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-1.1000194,0,0,1.0998287,110.29549,-8.6726854)"
+ x1="30.389694"
+ y1="95.008034"
+ x2="65.52562"
+ y2="93.69249" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610-84"
+ id="linearGradient18247"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-6,0)"
+ x1="483.00034"
+ y1="163"
+ x2="476.68781"
+ y2="162.85956" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient9030-4"
+ id="linearGradient18249"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(342.00029,383.00889)"
+ x1="123.36729"
+ y1="-219.24783"
+ x2="134.30893"
+ y2="-218.00888" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500-8"
+ id="linearGradient18251"
+ gradientUnits="userSpaceOnUse"
+ x1="475.00034"
+ y1="155"
+ x2="469.75034"
+ y2="155" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient23974-41"
+ id="linearGradient18253"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(14.285126,-0.22103087)"
+ x1="442.81525"
+ y1="290.49384"
+ x2="436.5"
+ y2="290.5249" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient18105-1"
+ id="linearGradient18255"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(20.285126,-0.22097087)"
+ x1="445.99902"
+ y1="288.5"
+ x2="407.3793"
+ y2="288.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient17560-4"
+ id="linearGradient18241-0"
+ gradientUnits="userSpaceOnUse"
+ x1="327.77432"
+ y1="251.04707"
+ x2="335.80118"
+ y2="247.0696" />
+ <linearGradient
+ id="linearGradient17560-4">
+ <stop
+ id="stop17562-3"
+ offset="0"
+ style="stop-color:#ffe991;stop-opacity:1;" />
+ <stop
+ id="stop17564-1"
+ offset="1"
+ style="stop-color:#ffe991;stop-opacity:0;" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient18370"
+ id="linearGradient18368"
+ x1="432.83759"
+ y1="289.15814"
+ x2="441.44028"
+ y2="283.54819"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ y2="245.78732"
+ x2="335.8941"
+ y1="251.04707"
+ x1="327.77432"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient18313-9"
+ xlink:href="#linearGradient17560-4-9"
+ inkscape:collect="always" />
+ <linearGradient
+ id="linearGradient17560-4-9">
+ <stop
+ id="stop17562-3-7"
+ offset="0"
+ style="stop-color:#ffe991;stop-opacity:1;" />
+ <stop
+ id="stop17564-1-4"
+ offset="1"
+ style="stop-color:#ffe991;stop-opacity:0;" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient18414"
+ id="linearGradient18420"
+ x1="333.8428"
+ y1="253.4225"
+ x2="327.0369"
+ y2="243.12526"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient18414-5"
+ id="linearGradient18420-1"
+ x1="333.8428"
+ y1="253.4225"
+ x2="327.0369"
+ y2="243.12526"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient18414-5">
+ <stop
+ style="stop-color:#000000;stop-opacity:1;"
+ offset="0"
+ id="stop18416-8" />
+ <stop
+ style="stop-color:#000000;stop-opacity:0;"
+ offset="1"
+ id="stop18418-4" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient18479"
+ id="linearGradient18476"
+ x1="427.86765"
+ y1="284.7648"
+ x2="431.31277"
+ y2="278.92789"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(0.46468729,2.0195829)" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient18495"
+ id="linearGradient18493"
+ x1="323.68958"
+ y1="248.71513"
+ x2="335.125"
+ y2="245.5"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient20020"
+ id="linearGradient20026"
+ x1="331.22147"
+ y1="249.03816"
+ x2="336.11465"
+ y2="244.64084"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient20043"
+ id="linearGradient20049"
+ x1="148.21956"
+ y1="506.48343"
+ x2="155.67555"
+ y2="506.45177"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ y2="30.023426"
+ x2="278.25537"
+ y1="3.6831069"
+ x1="253.78497"
+ gradientTransform="matrix(0.888889,0,0,1,513.5,184.50451)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient39254-5"
+ xlink:href="#linearGradient17555"
+ inkscape:collect="always" />
+ <linearGradient
+ id="linearGradient17555">
+ <stop
+ style="stop-color:#000000;stop-opacity:0.49803922;"
+ offset="0"
+ id="stop17557" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0.49803922;"
+ offset="1"
+ id="stop17559" />
+ </linearGradient>
+ <radialGradient
+ r="6.9000001"
+ fy="206.40076"
+ fx="756.83508"
+ cy="206.40076"
+ cx="756.83508"
+ gradientTransform="matrix(0.3817213,-0.4377393,0.4780868,0.4169055,368.09749,451.76937)"
+ gradientUnits="userSpaceOnUse"
+ id="radialGradient39256-9"
+ xlink:href="#linearGradient17549"
+ inkscape:collect="always" />
+ <linearGradient
+ id="linearGradient17549">
+ <stop
+ id="stop17551"
+ offset="0"
+ style="stop-color:#7f7f7f;stop-opacity:1;" />
+ <stop
+ id="stop17553"
+ offset="1"
+ style="stop-color:#7f7f7f;stop-opacity:0;" />
+ </linearGradient>
+ <linearGradient
+ y2="249"
+ x2="93.0625"
+ y1="241.125"
+ x1="87"
+ gradientTransform="translate(670,-33)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient39258-0"
+ xlink:href="#linearGradient17543"
+ inkscape:collect="always" />
+ <linearGradient
+ id="linearGradient17543">
+ <stop
+ id="stop17545"
+ offset="0.0000000"
+ style="stop-color:#ffffff;stop-opacity:0.87628865;" />
+ <stop
+ id="stop17547"
+ offset="1.0000000"
+ style="stop-color:#fffffe;stop-opacity:0.0000000;" />
+ </linearGradient>
+ <linearGradient
+ y2="305"
+ x2="758"
+ y1="300.83292"
+ x1="754.28558"
+ gradientTransform="translate(0,-95.999998)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient16784"
+ xlink:href="#linearGradient17530"
+ inkscape:collect="always" />
+ <linearGradient
+ id="linearGradient17530">
+ <stop
+ style="stop-color:#7f7f7f;stop-opacity:1;"
+ offset="0"
+ id="stop17532" />
+ <stop
+ style="stop-color:#7f7f7f;stop-opacity:0;"
+ offset="1"
+ id="stop17534" />
+ </linearGradient>
+ <linearGradient
+ y2="305"
+ x2="758"
+ y1="300.83292"
+ x1="754.28558"
+ gradientTransform="translate(0,-95.999998)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient16880"
+ xlink:href="#linearGradient17530"
+ inkscape:collect="always" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient18370"
+ id="linearGradient16720"
+ gradientUnits="userSpaceOnUse"
+ x1="432.83759"
+ y1="289.15814"
+ x2="441.44028"
+ y2="283.54819" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610-4"
+ id="linearGradient16940"
+ gradientUnits="userSpaceOnUse"
+ x1="258.94861"
+ y1="285.63672"
+ x2="237.92474"
+ y2="261.44183" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610-4-3"
+ id="linearGradient16943"
+ gradientUnits="userSpaceOnUse"
+ x1="258.94861"
+ y1="285.63672"
+ x2="237.92474"
+ y2="261.44183" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient17073"
+ id="linearGradient16945"
+ gradientUnits="userSpaceOnUse"
+ x1="240.40633"
+ y1="261.35129"
+ x2="240.41891"
+ y2="273.68066" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#radialGradient16824-1"
+ id="linearGradient16947"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-1.1749798,0,0,-1.2083376,211.53456,46.373264)"
+ x1="4.9106402"
+ y1="8.3244486"
+ x2="8.5571098"
+ y2="12.702949" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16850-5"
+ id="linearGradient16949"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-1.0895881,0,0,-1.1205216,210.97915,45.429444)"
+ x1="5.1938357"
+ y1="8.7375145"
+ x2="7.5092869"
+ y2="11.3536" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient20756-2-8"
+ id="linearGradient16951"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-1.0850614,-0.0361511,0.02414524,-1.0240584,201.95206,45.554604)"
+ x1="4.155818"
+ y1="5.3683834"
+ x2="6.5799594"
+ y2="7.7035389" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient43009-7"
+ id="linearGradient16953"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-1.7118707,-0.00216237,-0.00556412,-1.3288889,207.1884,56.557374)"
+ x1="5.6458621"
+ y1="11.418204"
+ x2="7.3551626"
+ y2="13.092201" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient17073"
+ id="linearGradient17001"
+ gradientUnits="userSpaceOnUse"
+ x1="240.40633"
+ y1="261.35129"
+ x2="240.41891"
+ y2="273.68066" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#radialGradient16824-1"
+ id="linearGradient17003"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-1.1749798,0,0,-1.2083376,211.53456,46.373264)"
+ x1="4.9106402"
+ y1="8.3244486"
+ x2="8.5571098"
+ y2="12.702949" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16850-5"
+ id="linearGradient17005"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-1.0895881,0,0,-1.1205216,210.97915,45.429444)"
+ x1="5.1938357"
+ y1="8.7375145"
+ x2="7.5092869"
+ y2="11.3536" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient20756-2-8"
+ id="linearGradient17007"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-1.0850614,-0.0361511,0.02414524,-1.0240584,201.95206,45.554604)"
+ x1="4.155818"
+ y1="5.3683834"
+ x2="6.5799594"
+ y2="7.7035389" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient43009-7"
+ id="linearGradient17009"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-1.7118707,-0.00216237,-0.00556412,-1.3288889,207.1884,56.557374)"
+ x1="5.6458621"
+ y1="11.418204"
+ x2="7.3551626"
+ y2="13.092201" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient43009-7"
+ id="linearGradient17014"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.7118707,0.00216237,0.00556412,1.3288889,342.98254,460.43356)"
+ x1="5.6458621"
+ y1="11.418204"
+ x2="7.3551626"
+ y2="13.092201" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient20756-2-8"
+ id="linearGradient17018"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.0850614,0.0361511,-0.02414524,1.0240584,348.21888,471.43633)"
+ x1="4.155818"
+ y1="5.3683834"
+ x2="6.5799594"
+ y2="7.7035389" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16850-5"
+ id="linearGradient17022"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.0895881,0,0,1.1205216,339.19179,471.56149)"
+ x1="5.1938357"
+ y1="8.7375145"
+ x2="7.5092869"
+ y2="11.3536" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#radialGradient16824-1"
+ id="linearGradient17026"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.1749798,0,0,1.2083376,338.63638,470.61767)"
+ x1="4.9106402"
+ y1="8.3244486"
+ x2="8.5571098"
+ y2="12.702949" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient17073"
+ id="linearGradient17030"
+ gradientUnits="userSpaceOnUse"
+ x1="240.40633"
+ y1="261.35129"
+ x2="240.41891"
+ y2="273.68066"
+ gradientTransform="matrix(-0.9285719,0,0,-0.9072647,533.78355,492.13787)" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient17073"
+ id="linearGradient17055"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-0.9285719,0,0,-0.9072647,533.78355,492.13787)"
+ x1="240.40633"
+ y1="261.35129"
+ x2="240.41891"
+ y2="273.68066" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610-4"
+ id="linearGradient17057"
+ gradientUnits="userSpaceOnUse"
+ x1="258.94861"
+ y1="285.63672"
+ x2="237.92474"
+ y2="261.44183" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610-4-3"
+ id="linearGradient17059"
+ gradientUnits="userSpaceOnUse"
+ x1="258.94861"
+ y1="285.63672"
+ x2="237.92474"
+ y2="261.44183" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient17073"
+ id="linearGradient17079"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-0.9285719,0,0,-0.9072647,533.78355,492.13787)"
+ x1="240.40633"
+ y1="261.35129"
+ x2="240.41891"
+ y2="273.68066" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542-29-7-8"
+ id="linearGradient17149"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-1,0,0,1,461.01011,-167)"
+ x1="368.97806"
+ y1="249.99998"
+ x2="393.85385"
+ y2="249.99998" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient27854-0-6-9"
+ id="linearGradient17151"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-1,0,0,1,461.01011,-167)"
+ x1="388.86502"
+ y1="244.02"
+ x2="391.43173"
+ y2="239.2338" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542-29-7-8"
+ id="linearGradient17157"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-1,0,0,1,461.01011,-167)"
+ x1="368.97806"
+ y1="249.99998"
+ x2="393.85385"
+ y2="249.99998" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient27854-0-6-9"
+ id="linearGradient17159"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-1,0,0,1,461.01011,-167)"
+ x1="388.86502"
+ y1="244.02"
+ x2="391.43173"
+ y2="239.2338" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient27854-0-6-9"
+ id="linearGradient17162"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,1,-1,0,782.48614,-14.46331)"
+ x1="388.86502"
+ y1="244.02"
+ x2="391.43173"
+ y2="239.2338" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542-29-7-8"
+ id="linearGradient17165"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,1,-1,0,782.48614,-14.46331)"
+ x1="368.97806"
+ y1="249.99998"
+ x2="393.85385"
+ y2="249.99998" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542-29-1"
+ id="linearGradient17175"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-1,0,0,1,461.01011,-167)"
+ x1="409.93588"
+ y1="249.99998"
+ x2="385.11514"
+ y2="249.99998" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542-29-1"
+ id="linearGradient17181"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-1,0,0,1,461.01011,-167)"
+ x1="409.93588"
+ y1="249.99998"
+ x2="385.11514"
+ y2="249.99998" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542-29-1"
+ id="linearGradient17185"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,-1,-1,0,740.48614,764.46331)"
+ x1="409.93588"
+ y1="249.99998"
+ x2="385.11514"
+ y2="249.99998" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient18414"
+ id="linearGradient17206"
+ gradientUnits="userSpaceOnUse"
+ x1="333.8428"
+ y1="253.4225"
+ x2="327.0369"
+ y2="243.12526" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient18479"
+ id="linearGradient17208"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(0.46468729,2.0195829)"
+ x1="427.86765"
+ y1="284.7648"
+ x2="431.31277"
+ y2="278.92789" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient18495"
+ id="linearGradient17210"
+ gradientUnits="userSpaceOnUse"
+ x1="323.68958"
+ y1="248.71513"
+ x2="335.125"
+ y2="245.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient20020"
+ id="linearGradient17212"
+ gradientUnits="userSpaceOnUse"
+ x1="331.22147"
+ y1="249.03816"
+ x2="336.11465"
+ y2="244.64084" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient17555"
+ id="linearGradient17215"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.888889,0,0,1,513.5,184.50451)"
+ x1="253.78497"
+ y1="3.6831069"
+ x2="278.25537"
+ y2="30.023426" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient17549"
+ id="radialGradient17217"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.3817213,-0.4377393,0.4780868,0.4169055,368.09749,451.76937)"
+ cx="756.83508"
+ cy="206.40076"
+ fx="756.83508"
+ fy="206.40076"
+ r="6.9000001" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient17543"
+ id="linearGradient17219"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(670,-33)"
+ x1="87"
+ y1="241.125"
+ x2="93.0625"
+ y2="249" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient17530"
+ id="linearGradient17221"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(0,-95.999998)"
+ x1="754.28558"
+ y1="300.83292"
+ x2="758"
+ y2="305" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient18370"
+ id="linearGradient17223"
+ gradientUnits="userSpaceOnUse"
+ x1="432.83759"
+ y1="289.15814"
+ x2="441.44028"
+ y2="283.54819" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient18370"
+ id="linearGradient17225"
+ gradientUnits="userSpaceOnUse"
+ x1="432.83759"
+ y1="289.15814"
+ x2="441.44028"
+ y2="283.54819" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient20020"
+ id="linearGradient17236"
+ gradientUnits="userSpaceOnUse"
+ x1="331.22147"
+ y1="249.03816"
+ x2="336.11465"
+ y2="244.64084"
+ gradientTransform="translate(-0.01702303,0.01679543)" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient18495"
+ id="linearGradient17239"
+ gradientUnits="userSpaceOnUse"
+ x1="323.68958"
+ y1="248.71513"
+ x2="335.125"
+ y2="245.5"
+ gradientTransform="translate(4.554861e-6,8.3724231e-8)" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient18479"
+ id="linearGradient17243"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.0087429,0,0,0.97482999,-108.39487,-30.511198)"
+ x1="427.86765"
+ y1="284.7648"
+ x2="431.31277"
+ y2="278.92789" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient18414"
+ id="linearGradient17247"
+ gradientUnits="userSpaceOnUse"
+ x1="333.8428"
+ y1="253.4225"
+ x2="327.0369"
+ y2="243.12526"
+ gradientTransform="translate(4.554861e-6,8.3724231e-8)" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient17442"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.081988,0,0,1.0833333,-394.58897,440.54169)"
+ x1="326.51352"
+ y1="32.007874"
+ x2="347.91187"
+ y2="57.261913" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient17444"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.0983862,0,0,1.0999999,-400.00857,439.95001)"
+ x1="317.30908"
+ y1="22.7787"
+ x2="330.87869"
+ y2="38.161732" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient18105-2-9"
+ id="linearGradient18618"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-0.04935997,1.9792524)"
+ x1="492.95264"
+ y1="267.42996"
+ x2="496.73859"
+ y2="270.36874" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient15531-9-5"
+ id="linearGradient18620"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.9993234,0,0,1.0050357,383.02168,218.70121)"
+ x1="116.41398"
+ y1="53.197613"
+ x2="109.72195"
+ y2="43.434277" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient23974-27-5"
+ id="linearGradient18622"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.9993234,0,0,1.0050357,383.02168,218.70121)"
+ x1="116.41398"
+ y1="53.197613"
+ x2="104.06187"
+ y2="53.601826" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient27277-1-8"
+ id="linearGradient18624"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-0.04935997,1.9965991)"
+ x1="501.19104"
+ y1="270.69452"
+ x2="488.93024"
+ y2="272.60611" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient21327-63-5"
+ id="linearGradient18626"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-0.04935997,0.97920913)"
+ x1="500.71924"
+ y1="270.24997"
+ x2="477"
+ y2="274" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient27301-6-2"
+ id="linearGradient18628"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-0.04936017,-0.04091017)"
+ x1="497"
+ y1="264"
+ x2="507.125"
+ y2="276.75" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient18663"
+ gradientUnits="userSpaceOnUse"
+ x1="98.858559"
+ y1="80.045052"
+ x2="135.00615"
+ y2="122.92735" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient18665"
+ gradientUnits="userSpaceOnUse"
+ x1="130.75166"
+ y1="245.03757"
+ x2="129.24866"
+ y2="243.31177" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient18667"
+ gradientUnits="userSpaceOnUse"
+ x1="126.37006"
+ y1="112.31642"
+ x2="144.22272"
+ y2="129.82761" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient9030"
+ id="linearGradient18669"
+ gradientUnits="userSpaceOnUse"
+ x1="190.68166"
+ y1="244.14676"
+ x2="174.75458"
+ y2="226.33672" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient23974-39"
+ id="linearGradient18721-2"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-1.004219,0,0,0.980922,244.3928,19.4113)"
+ x1="-88.73024"
+ y1="-120.6127"
+ x2="-78.787354"
+ y2="-128.30418" />
+ <linearGradient
+ id="linearGradient23974-39">
+ <stop
+ id="stop23976-8"
+ offset="0"
+ style="stop-color:#2561b7;stop-opacity:1;" />
+ <stop
+ id="stop23978-23"
+ offset="1"
+ style="stop-color:#f9fbff;stop-opacity:1" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient31320-9"
+ id="linearGradient18728-1"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-1.004219,0,0,0.980922,222.97812,19.5574)"
+ x1="68.688324"
+ y1="51.42366"
+ x2="72.671516"
+ y2="55.501457" />
+ <linearGradient
+ id="linearGradient31320-9">
+ <stop
+ style="stop-color:white;stop-opacity:1;"
+ offset="0"
+ id="stop31322-6" />
+ <stop
+ style="stop-color:white;stop-opacity:0;"
+ offset="1"
+ id="stop31324-2" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient14262-6"
+ id="linearGradient18765-5"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-1.004219,0,0,0.980922,309.42934,-349.44584)"
+ x1="-26.207859"
+ y1="252.77303"
+ x2="-5.4963508"
+ y2="253.15045" />
+ <linearGradient
+ id="linearGradient14262-6">
+ <stop
+ id="stop14264-29"
+ offset="0"
+ style="stop-color:#2661b6;stop-opacity:1;" />
+ <stop
+ id="stop14266-9"
+ offset="1"
+ style="stop-color:#c1d7f8;stop-opacity:0;" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-61"
+ id="linearGradient18712-6"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8167109,0,0,0.8433415,239.34332,-149.78578)"
+ x1="103.65562"
+ y1="49.547874"
+ x2="120.79755"
+ y2="57.84819" />
+ <linearGradient
+ id="linearGradient319-61">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop320-47" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop321-45" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient23974-39"
+ id="linearGradient16862"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-1.004219,0,0,0.980922,244.3928,19.4113)"
+ x1="-88.73024"
+ y1="-120.6127"
+ x2="-78.787354"
+ y2="-128.30418" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient31320-9"
+ id="linearGradient16864"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-1.004219,0,0,0.980922,222.97812,19.5574)"
+ x1="68.688324"
+ y1="51.42366"
+ x2="72.671516"
+ y2="55.501457" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient14262-6"
+ id="linearGradient16866"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-1.004219,0,0,0.980922,309.42934,-349.44584)"
+ x1="-26.207859"
+ y1="252.77303"
+ x2="-5.4963508"
+ y2="253.15045" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-61"
+ id="linearGradient16868"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8167109,0,0,0.8433415,239.34332,-149.78578)"
+ x1="103.65562"
+ y1="49.547874"
+ x2="120.79755"
+ y2="57.84819" />
+ <filter
+ style="color-interpolation-filters:sRGB"
+ inkscape:collect="always"
+ x="-0.71999419"
+ width="2.4399884"
+ y="-0.72000581"
+ height="2.4400115"
+ id="filter31351-1">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="0.83077614"
+ id="feGaussianBlur31353-2" />
+ </filter>
+ <mask
+ maskUnits="userSpaceOnUse"
+ id="mask43822-9">
+ <rect
+ y="208"
+ x="754"
+ height="9"
+ width="12"
+ id="rect43824-7"
+ style="display:inline;overflow:visible;visibility:visible;opacity:0.93999993;fill:url(#linearGradient43826);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;enable-background:new" />
+ </mask>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient30825"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.888889,0,0,1,60.913822,345.30299)"
+ x1="246.89435"
+ y1="-4.4418921"
+ x2="277.68143"
+ y2="30.743095" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient30827"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(217.4611,127.95934)"
+ x1="87.03125"
+ y1="241"
+ x2="92.8125"
+ y2="245.625" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient30849"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.888889,0,0,1,62.093241,347.52307)"
+ x1="246.89435"
+ y1="-4.4418921"
+ x2="277.68143"
+ y2="30.743095" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient31767"
+ id="linearGradient17886"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-453.47657,163.11565)"
+ x1="755.49371"
+ y1="212.5"
+ x2="759.46533"
+ y2="212.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient31767"
+ id="linearGradient17892"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-473.38792,258.10925)"
+ x1="755.49371"
+ y1="212.5"
+ x2="759.46533"
+ y2="212.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient31767"
+ id="linearGradient17894"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-473.38792,258.10925)"
+ x1="755.49371"
+ y1="212.5"
+ x2="759.46533"
+ y2="212.5" />
+ <filter
+ inkscape:collect="always"
+ style="color-interpolation-filters:sRGB"
+ id="filter17889"
+ x="-0.044615405"
+ width="1.0892308"
+ y="-0.091578864"
+ height="1.1831577">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="0.25149387"
+ id="feGaussianBlur17891" />
+ </filter>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath15455">
+ <rect
+ style="color:#000000;fill:#d8d8d8;fill-opacity:1;stroke:none;stroke-width:1.20000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:new"
+ id="rect15457"
+ width="16"
+ height="16"
+ x="301.96045"
+ y="236.91833" />
+ </clipPath>
+ <mask
+ maskUnits="userSpaceOnUse"
+ id="mask15700">
+ <path
+ style="color:#000000;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1.20000005;marker:none;visibility:visible;display:inline;overflow:visible;filter:url(#filter15613);enable-background:new"
+ d="m 302.9292,245.91834 -2.4375,-1.125 -0.53125,-9.84375 19.95312,-0.0469 0.0156,9.95313 -2.9375,1.09375 0,5.96875 -14,0 z"
+ id="path15702"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccccccc" />
+ </mask>
+ <filter
+ color-interpolation-filters="sRGB"
+ inkscape:collect="always"
+ id="filter15613"
+ x="-0.092011765"
+ width="1.1840235"
+ y="-0.097762503"
+ height="1.1955251">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="0.65175"
+ id="feGaussianBlur15615" />
+ </filter>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542-55"
+ id="linearGradient15678"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.6025789,0,0,0.668336,262.51944,86.612922)"
+ x1="49.543404"
+ y1="230.81766"
+ x2="73.932747"
+ y2="247.27646" />
+ <linearGradient
+ id="linearGradient37542-55">
+ <stop
+ id="stop37544-61"
+ offset="0"
+ style="stop-color:#000000;stop-opacity:1;" />
+ <stop
+ id="stop37546-03"
+ offset="1"
+ style="stop-color:#ffffff;stop-opacity:1;" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-74"
+ id="linearGradient15680"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.9120445,0,0,1,24.780995,9.8636515)"
+ x1="305.12527"
+ y1="239.03134"
+ x2="308.97327"
+ y2="242" />
+ <linearGradient
+ id="linearGradient319-74">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop320-42" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop321-67" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542-55"
+ id="linearGradient15682"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.584271,0,0,0.661005,267.80323,78.438648)"
+ x1="51.682816"
+ y1="229.19724"
+ x2="73.932762"
+ y2="247.35141" />
+ <linearGradient
+ id="linearGradient14195">
+ <stop
+ id="stop14197"
+ offset="0"
+ style="stop-color:#000000;stop-opacity:1;" />
+ <stop
+ id="stop14199"
+ offset="1"
+ style="stop-color:#ffffff;stop-opacity:1;" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-74"
+ id="linearGradient15684"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.9103441,0,0,0.989031,29.299938,2.5312404)"
+ x1="305.12527"
+ y1="239.03134"
+ x2="307.25021"
+ y2="241.62509" />
+ <linearGradient
+ id="linearGradient14202">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop14204" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop14206" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient21609-6"
+ id="linearGradient15688"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.6025789,0,0,0.668336,273.45693,86.644181)"
+ x1="49.543404"
+ y1="230.81766"
+ x2="73.932747"
+ y2="247.27646" />
+ <linearGradient
+ id="linearGradient21609-6">
+ <stop
+ id="stop21611-3"
+ offset="0"
+ style="stop-color:black;stop-opacity:1" />
+ <stop
+ id="stop21613-0"
+ offset="1"
+ style="stop-color:white;stop-opacity:1;" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient29312-0"
+ id="linearGradient15690"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.9120445,0,0,1,35.718484,9.8949108)"
+ x1="305.12527"
+ y1="239.03134"
+ x2="308.97327"
+ y2="242" />
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient29312-0">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop29314-8" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop29316-3" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16019"
+ id="linearGradient15692"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(0.59375,1.375)"
+ x1="308.85309"
+ y1="245.43437"
+ x2="314.06238"
+ y2="245.43437" />
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient16019">
+ <stop
+ style="stop-color:#c6d7ef;stop-opacity:1"
+ offset="0"
+ id="stop16021" />
+ <stop
+ style="stop-color:#7fa4dc;stop-opacity:1"
+ offset="1"
+ id="stop16023" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient15996"
+ id="linearGradient15694"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(0.59375,1.375)"
+ x1="304.86005"
+ y1="245.47992"
+ x2="310.04089"
+ y2="245.47992" />
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient15996">
+ <stop
+ style="stop-color:#5f8dd3;stop-opacity:1"
+ offset="0"
+ id="stop15998" />
+ <stop
+ style="stop-color:#d7e3f4;stop-opacity:1"
+ offset="1"
+ id="stop16000" />
+ </linearGradient>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath15455-9">
+ <rect
+ style="color:#000000;fill:#d8d8d8;fill-opacity:1;stroke:none;stroke-width:1.20000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:new"
+ id="rect15457-6"
+ width="16"
+ height="16"
+ x="301.96045"
+ y="236.91833" />
+ </clipPath>
+ <mask
+ maskUnits="userSpaceOnUse"
+ id="mask15700-4">
+ <path
+ style="color:#000000;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1.20000005000000010;marker:none;visibility:visible;display:inline;overflow:visible;filter:url(#filter15613-8);enable-background:new"
+ d="m 302.9292,245.91834 -2.4375,-1.125 -0.53125,-9.84375 19.95312,-0.0469 0.0156,9.95313 -2.9375,1.09375 0,5.96875 -14,0 z"
+ id="path15702-5"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccccccc" />
+ </mask>
+ <filter
+ color-interpolation-filters="sRGB"
+ inkscape:collect="always"
+ id="filter15613-8"
+ x="-0.092011765"
+ width="1.1840235"
+ y="-0.097762503"
+ height="1.1955251">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="0.65175"
+ id="feGaussianBlur15615-1" />
+ </filter>
+ <filter
+ color-interpolation-filters="sRGB"
+ inkscape:label="Greyscale"
+ id="filter15388">
+ <feColorMatrix
+ values="0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0 0 0 1 0 "
+ id="feColorMatrix15390"
+ result="fbSourceGraphic" />
+ <feColorMatrix
+ result="fbSourceGraphicAlpha"
+ in="fbSourceGraphic"
+ values="0 0 0 -1 0 0 0 0 -1 0 0 0 0 -1 0 0 0 0 1 0"
+ id="feColorMatrix15392" />
+ <feColorMatrix
+ id="feColorMatrix15394"
+ values="0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0 0 0 1 0 "
+ in="fbSourceGraphic" />
+ </filter>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542-91"
+ id="linearGradient15371"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.6025789,0,0,0.668336,262.51944,86.612922)"
+ x1="49.543404"
+ y1="230.81766"
+ x2="73.932747"
+ y2="247.27646" />
+ <linearGradient
+ id="linearGradient37542-91">
+ <stop
+ id="stop37544-81"
+ offset="0"
+ style="stop-color:#000000;stop-opacity:1;" />
+ <stop
+ id="stop37546-75"
+ offset="1"
+ style="stop-color:#ffffff;stop-opacity:1;" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-223"
+ id="linearGradient15373"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.9120445,0,0,1,24.780995,9.8636515)"
+ x1="305.12527"
+ y1="239.03134"
+ x2="308.97327"
+ y2="242" />
+ <linearGradient
+ id="linearGradient319-223">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop320-84" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop321-34" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542-91"
+ id="linearGradient15375"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.584271,0,0,0.661005,267.80323,78.438648)"
+ x1="51.682816"
+ y1="229.19724"
+ x2="73.932762"
+ y2="247.35141" />
+ <linearGradient
+ id="linearGradient14275">
+ <stop
+ id="stop14277"
+ offset="0"
+ style="stop-color:#000000;stop-opacity:1;" />
+ <stop
+ id="stop14279"
+ offset="1"
+ style="stop-color:#ffffff;stop-opacity:1;" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-223"
+ id="linearGradient15377"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.9103441,0,0,0.989031,29.299938,2.5312404)"
+ x1="305.12527"
+ y1="239.03134"
+ x2="307.25021"
+ y2="241.62509" />
+ <linearGradient
+ id="linearGradient14282">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop14284" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop14286" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient21609-3"
+ id="linearGradient15379"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.6025789,0,0,0.668336,273.45693,86.644181)"
+ x1="49.543404"
+ y1="230.81766"
+ x2="73.932747"
+ y2="247.27646" />
+ <linearGradient
+ id="linearGradient21609-3">
+ <stop
+ id="stop21611-9"
+ offset="0"
+ style="stop-color:black;stop-opacity:1" />
+ <stop
+ id="stop21613-8"
+ offset="1"
+ style="stop-color:white;stop-opacity:1;" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient29312-7"
+ id="linearGradient15381"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.9120445,0,0,1,35.718484,9.8949108)"
+ x1="305.12527"
+ y1="239.03134"
+ x2="308.97327"
+ y2="242" />
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient29312-7">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop29314-6" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop29316-8" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16019-5"
+ id="linearGradient15384"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(0.59375,1.375)"
+ x1="308.85309"
+ y1="245.43437"
+ x2="314.06238"
+ y2="245.43437" />
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient16019-5">
+ <stop
+ style="stop-color:#c6d7ef;stop-opacity:1"
+ offset="0"
+ id="stop16021-1" />
+ <stop
+ style="stop-color:#7fa4dc;stop-opacity:1"
+ offset="1"
+ id="stop16023-8" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient15996-5"
+ id="linearGradient15386"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(0.59375,1.375)"
+ x1="304.86005"
+ y1="245.47992"
+ x2="310.04089"
+ y2="245.47992" />
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient15996-5">
+ <stop
+ style="stop-color:#5f8dd3;stop-opacity:1"
+ offset="0"
+ id="stop15998-9" />
+ <stop
+ style="stop-color:#d7e3f4;stop-opacity:1"
+ offset="1"
+ id="stop16000-1" />
+ </linearGradient>
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16023"
+ id="radialGradient16031"
+ cx="139"
+ cy="137.5"
+ fx="139"
+ fy="137.5"
+ r="7"
+ gradientTransform="matrix(1.9285714,0,0,0.5,-129.07143,68.75)"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient16023">
+ <stop
+ style="stop-color:#d8d8d8;stop-opacity:1"
+ offset="0"
+ id="stop16025" />
+ <stop
+ style="stop-color:#9a9a9a;stop-opacity:1"
+ offset="1"
+ id="stop16027" />
+ </linearGradient>
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16023"
+ id="radialGradient14148"
+ cx="139"
+ cy="137.5"
+ fx="139"
+ fy="137.5"
+ r="7"
+ gradientTransform="matrix(1.9285714,0,0,0.5,-129.07143,68.75)"
+ gradientUnits="userSpaceOnUse" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16023"
+ id="radialGradient14156"
+ cx="139"
+ cy="137.5"
+ fx="139"
+ fy="137.5"
+ r="7"
+ gradientTransform="matrix(1.9285714,0,0,0.5,-129.07143,68.75)"
+ gradientUnits="userSpaceOnUse" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16023"
+ id="radialGradient14164"
+ cx="139"
+ cy="137.5"
+ fx="139"
+ fy="137.5"
+ r="7"
+ gradientTransform="matrix(1.9285714,0,0,0.5,-129.07143,68.75)"
+ gradientUnits="userSpaceOnUse" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16023"
+ id="radialGradient14172"
+ cx="139"
+ cy="137.5"
+ fx="139"
+ fy="137.5"
+ r="7"
+ gradientTransform="matrix(1.9285714,0,0,0.5,-129.07143,68.75)"
+ gradientUnits="userSpaceOnUse" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16023"
+ id="radialGradient14180"
+ cx="139"
+ cy="137.5"
+ fx="139"
+ fy="137.5"
+ r="7"
+ gradientTransform="matrix(1.9285714,0,0,0.5,-129.07143,68.75)"
+ gradientUnits="userSpaceOnUse" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient15984"
+ id="radialGradient15990"
+ cx="139"
+ cy="137.5"
+ fx="139"
+ fy="137.5"
+ r="1"
+ gradientTransform="matrix(14.5,0,0,5.5,-1876.5,-618.75)"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient15984">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1"
+ offset="0"
+ id="stop15986" />
+ <stop
+ style="stop-color:#a8cafb;stop-opacity:1"
+ offset="1"
+ id="stop15988" />
+ </linearGradient>
+ <radialGradient
+ r="7"
+ fy="137.5"
+ fx="139"
+ cy="137.5"
+ cx="139"
+ gradientTransform="matrix(1.9285714,0,0,0.5,-129.07143,68.75)"
+ gradientUnits="userSpaceOnUse"
+ id="radialGradient14206"
+ xlink:href="#linearGradient16023"
+ inkscape:collect="always" />
+ <radialGradient
+ r="7"
+ fy="137.5"
+ fx="139"
+ cy="137.5"
+ cx="139"
+ gradientTransform="matrix(1.9285714,0,0,0.5,-129.07143,68.75)"
+ gradientUnits="userSpaceOnUse"
+ id="radialGradient14208"
+ xlink:href="#linearGradient16023"
+ inkscape:collect="always" />
+ <radialGradient
+ r="7"
+ fy="137.5"
+ fx="139"
+ cy="137.5"
+ cx="139"
+ gradientTransform="matrix(1.9285714,0,0,0.5,-129.07143,68.75)"
+ gradientUnits="userSpaceOnUse"
+ id="radialGradient14210"
+ xlink:href="#linearGradient16023"
+ inkscape:collect="always" />
+ <radialGradient
+ r="7"
+ fy="137.5"
+ fx="139"
+ cy="137.5"
+ cx="139"
+ gradientTransform="matrix(1.9285714,0,0,0.5,-129.07143,68.75)"
+ gradientUnits="userSpaceOnUse"
+ id="radialGradient14212"
+ xlink:href="#linearGradient16023"
+ inkscape:collect="always" />
+ <radialGradient
+ r="7"
+ fy="137.5"
+ fx="139"
+ cy="137.5"
+ cx="139"
+ gradientTransform="matrix(1.9285714,0,0,0.5,-129.07143,68.75)"
+ gradientUnits="userSpaceOnUse"
+ id="radialGradient14214"
+ xlink:href="#linearGradient16023"
+ inkscape:collect="always" />
+ <radialGradient
+ r="1"
+ fy="137.5"
+ fx="139"
+ cy="137.5"
+ cx="139"
+ gradientTransform="matrix(14.5,0,0,5.5,-1876.5,-618.75)"
+ gradientUnits="userSpaceOnUse"
+ id="radialGradient14216"
+ xlink:href="#linearGradient15984"
+ inkscape:collect="always" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16023"
+ id="radialGradient16945"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.9285714,0,0,0.5,-129.59176,68.75)"
+ cx="139"
+ cy="137.5"
+ fx="139"
+ fy="137.5"
+ r="7" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16023"
+ id="radialGradient16947"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.9285714,0,0,0.5,-128.51641,68.75)"
+ cx="139"
+ cy="137.5"
+ fx="139"
+ fy="137.5"
+ r="7" />
</defs>
<sodipodi:namedview
id="base"
@@ -28327,16 +30948,16 @@
objecttolerance="10000"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
- inkscape:zoom="9.9557"
- inkscape:cx="101.55361"
- inkscape:cy="425.39887"
+ inkscape:zoom="40.768576"
+ inkscape:cx="236.56738"
+ inkscape:cy="163.14077"
inkscape:document-units="px"
- inkscape:current-layer="layer1"
+ inkscape:current-layer="g24024-1"
showgrid="true"
- inkscape:window-width="1600"
- inkscape:window-height="845"
- inkscape:window-x="-8"
- inkscape:window-y="-8"
+ inkscape:window-width="1920"
+ inkscape:window-height="982"
+ inkscape:window-x="0"
+ inkscape:window-y="28"
inkscape:snap-nodes="false"
inkscape:snap-bbox="true"
showguides="true"
@@ -28399,26 +31020,9 @@
</dc:publisher>
<dc:coverage />
<cc:license
- rdf:resource="http://creativecommons.org/licenses/by-nc-sa/3.0/" />
- <dc:description>This content is under CC Attribution-NonCommercial ShareAlike licence 3.0 as long as it's used for Blender 3D GUI. Any other uses are not allowed.</dc:description>
+ rdf:resource="http://www.gnu.org/licenses/old-licenses/gpl-2.0.html" />
+ <dc:description>GNU General Public License, version 2 or later.</dc:description>
</cc:Work>
- <cc:License
- rdf:about="http://creativecommons.org/licenses/by-nc-sa/3.0/">
- <cc:permits
- rdf:resource="http://creativecommons.org/ns#Reproduction" />
- <cc:permits
- rdf:resource="http://creativecommons.org/ns#Distribution" />
- <cc:requires
- rdf:resource="http://creativecommons.org/ns#Notice" />
- <cc:requires
- rdf:resource="http://creativecommons.org/ns#Attribution" />
- <cc:prohibits
- rdf:resource="http://creativecommons.org/ns#CommercialUse" />
- <cc:permits
- rdf:resource="http://creativecommons.org/ns#DerivativeWorks" />
- <cc:requires
- rdf:resource="http://creativecommons.org/ns#ShareAlike" />
- </cc:License>
</rdf:RDF>
</metadata>
<g
@@ -36353,7 +38957,7 @@
<g
transform="matrix(0,1,1,0,-174,194)"
style="display:inline;enable-background:new"
- id="g106468-0">
+ id="ICON_DOWNARROW_HLT">
<g
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
@@ -36388,7 +38992,7 @@
inkscape:export-xdpi="90"
inkscape:export-filename="/home/georg/Arbeitsfläche/2012/Blender Coding/Patch #2a/icon_redone 5a.png"
transform="translate(440.42789,-242.41778)"
- id="g14713">
+ id="ICON_FILE_BACKUP">
<g
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
@@ -36502,7 +39106,7 @@
id="path14745" />
<path
transform="matrix(3.625,0,0,3.1690202,-67.8125,318.31703)"
- d="m 14.5,57.5 c 0,0.552285 -0.447715,1 -1,1 -0.552285,0 -1,-0.447715 -1,-1 0,-0.552285 0.447715,-1 1,-1 0.552285,0 1,0.447715 1,1 z"
+ d="m 14.5,57.5 a 1,1.0000004 0 0 1 -1,1 1,1.0000004 0 0 1 -1,-1 1,1.0000004 0 0 1 1,-1 1,1.0000004 0 0 1 1,1 z"
sodipodi:ry="1.0000004"
sodipodi:rx="1"
sodipodi:cy="57.5"
@@ -36519,7 +39123,7 @@
</g>
<path
transform="matrix(3.5999897,0,0,3.1249932,-67.499871,320.6879)"
- d="m 14.5,57.5 c 0,0.552285 -0.447715,1 -1,1 -0.552285,0 -1,-0.447715 -1,-1 0,-0.552285 0.447715,-1 1,-1 0.552285,0 1,0.447715 1,1 z"
+ d="m 14.5,57.5 a 1,1 0 0 1 -1,1 1,1 0 0 1 -1,-1 1,1 0 0 1 1,-1 1,1 0 0 1 1,1 z"
sodipodi:ry="1"
sodipodi:rx="1"
sodipodi:cy="57.5"
@@ -36541,11 +39145,11 @@
sodipodi:cy="57.5"
sodipodi:rx="1"
sodipodi:ry="1"
- d="m 14.5,57.5 c 0,0.552285 -0.447715,1 -1,1 -0.552285,0 -1,-0.447715 -1,-1 0,-0.552285 0.447715,-1 1,-1 0.552285,0 1,0.447715 1,1 z"
+ d="m 14.5,57.5 a 1,1 0 0 1 -1,1 1,1 0 0 1 -1,-1 1,1 0 0 1 1,-1 1,1 0 0 1 1,1 z"
transform="matrix(3.25,0,0,3.25,-62.875,313.125)" />
<path
transform="matrix(2,0,0,2,-46,385)"
- d="m 14.5,57.5 c 0,0.552285 -0.447715,1 -1,1 -0.552285,0 -1,-0.447715 -1,-1 0,-0.552285 0.447715,-1 1,-1 0.552285,0 1,0.447715 1,1 z"
+ d="m 14.5,57.5 a 1,1 0 0 1 -1,1 1,1 0 0 1 -1,-1 1,1 0 0 1 1,-1 1,1 0 0 1 1,1 z"
sodipodi:ry="1"
sodipodi:rx="1"
sodipodi:cy="57.5"
@@ -36561,7 +39165,7 @@
sodipodi:cy="57.5"
sodipodi:rx="1"
sodipodi:ry="1"
- d="m 14.5,57.5 c 0,0.552285 -0.447715,1 -1,1 -0.552285,0 -1,-0.447715 -1,-1 0,-0.552285 0.447715,-1 1,-1 0.552285,0 1,0.447715 1,1 z"
+ d="m 14.5,57.5 a 1,1 0 0 1 -1,1 1,1 0 0 1 -1,-1 1,1 0 0 1 1,-1 1,1 0 0 1 1,1 z"
transform="matrix(4.7519907,0,0,4.1435313,-83.051884,262.12196)" />
<path
inkscape:connector-curvature="0"
@@ -36581,149 +39185,7 @@
inkscape:export-ydpi="90" />
</g>
<g
- style="display:inline;enable-background:new"
- id="g14765"
- inkscape:export-filename="/home/georg/Arbeitsfläche/2012/Blender Coding/Patch #2a/icon_big_redone 5a.png"
- inkscape:export-xdpi="90"
- inkscape:export-ydpi="90"
- transform="translate(1090.1244,-109.28264)">
- <rect
- ry="0"
- rx="2.4004419"
- y="336.28265"
- x="-78.124435"
- height="48"
- width="48"
- id="rect14767"
- style="opacity:0;fill:#cccccc;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.00000012;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
- <path
- inkscape:export-ydpi="90"
- inkscape:export-xdpi="90"
- inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png"
- sodipodi:nodetypes="cccccc"
- id="path14769"
- d="m -60.624426,339.78264 22.999995,0 0,41 -32.999995,0 0,-31 10,-10 z"
- style="fill:url(#linearGradient14814);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;display:inline"
- inkscape:connector-curvature="0" />
- <path
- sodipodi:nodetypes="cccc"
- id="path14771"
- style="opacity:0.7;fill:none;stroke:url(#linearGradient14816);stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:0.56470588"
- d="m -38.874431,340.78264 c -4.875,0 -21.749995,0 -21.749995,0 m -8.9447,8.5 -0.0553,30"
- inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png"
- inkscape:export-xdpi="90"
- inkscape:export-ydpi="90"
- inkscape:connector-curvature="0" />
- <path
- style="opacity:0.2;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;filter:url(#filter63011-8)"
- d="m 115,444 12,0 -1,-11 -11,11 z"
- id="path14773"
- sodipodi:nodetypes="cccc"
- inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png"
- inkscape:export-xdpi="90"
- inkscape:export-ydpi="90"
- clip-path="url(#clipPath13106-0)"
- inkscape:connector-curvature="0"
- transform="translate(-186.12444,-93.717362)" />
- <path
- sodipodi:nodetypes="ccc"
- id="path14775"
- style="fill:none;stroke:url(#linearGradient14818);stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
- d="m -68.624426,350.03264 9,-2.5 0,-6"
- inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png"
- inkscape:export-xdpi="90"
- inkscape:export-ydpi="90"
- clip-path="none"
- inkscape:connector-curvature="0" />
- <path
- inkscape:export-ydpi="90"
- inkscape:export-xdpi="90"
- inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png"
- d="m -70.624426,349.03264 0,31.75 32.999995,0 0,-41 -23.749995,0 -9.25,9.25 z"
- style="fill:none;stroke:#333333;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
- id="path14777"
- sodipodi:nodetypes="cccccc"
- inkscape:connector-curvature="0" />
- <path
- style="opacity:0.16000001;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;display:inline;filter:url(#filter63011-8)"
- d="m 116,443 11,1 -2,-10 -9,9 z"
- id="path14779"
- sodipodi:nodetypes="cccc"
- inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png"
- inkscape:export-xdpi="90"
- inkscape:export-ydpi="90"
- clip-path="url(#clipPath13106-0)"
- inkscape:connector-curvature="0"
- transform="translate(-186.12444,-93.717362)" />
- <path
- inkscape:export-ydpi="90"
- inkscape:export-xdpi="90"
- inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png"
- sodipodi:nodetypes="cccccc"
- id="path14781"
- d="m -70.124426,349.28264 0.0108,0.72434 9.9892,-2.72434 0,-7 -1,0 -9,9 z"
- style="fill:#ffffff;fill-opacity:0.75294118;fill-rule:evenodd;stroke:none"
- inkscape:connector-curvature="0" />
- <path
- inkscape:export-ydpi="90"
- inkscape:export-xdpi="90"
- inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png"
- d="m -38.624431,341.28264 0,38.5 -30.499995,0"
- style="opacity:0.15;fill:none;stroke:#000000;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
- id="path14783"
- sodipodi:nodetypes="ccc"
- inkscape:connector-curvature="0" />
- <g
- transform="matrix(0.5406242,0,0,0.5829534,-67.987756,347.93806)"
- inkscape:label="Layer 1"
- id="g14785">
- <path
- sodipodi:type="arc"
- style="opacity:0.54857142;fill:url(#radialGradient14820);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- id="path14788"
- sodipodi:cx="28.019106"
- sodipodi:cy="38.98439"
- sodipodi:rx="15.467961"
- sodipodi:ry="5.3033009"
- d="m 43.487067,38.98439 c 0,2.928932 -6.925242,5.303301 -15.467961,5.303301 -8.542719,0 -15.467961,-2.374369 -15.467961,-5.303301 0,-2.928932 6.925242,-5.303301 15.467961,-5.303301 8.542719,0 15.467961,2.374369 15.467961,5.303301 z"
- transform="matrix(1.274286,0,0,1.377124,-7.569123,-16.70193)" />
- <path
- style="fill:#f57900;fill-rule:evenodd;stroke:#aa4400;stroke-width:1.7812928;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none"
- id="path14790"
- d="m 16.048489,28.093447 c 0.0098,0.576682 0.196474,1.697902 0.471116,2.577425 0.581566,1.854137 1.56684,3.572658 2.939126,5.086496 1.407488,1.553118 3.138519,2.803227 5.139315,3.68976 2.105357,0.931573 4.384795,1.407488 6.750134,1.403741 2.365339,-0.005 4.644601,-0.488686 6.74896,-1.427017 2.00002,-0.895288 3.731043,-2.148391 5.13754,-3.705517 1.369207,-1.519844 2.352576,-3.241114 2.934089,-5.096258 0.294262,-0.938353 0.476921,-1.889392 0.553238,-2.845308 0.07331,-0.939306 0.04204,-1.883511 -0.09183,-2.823792 -0.259981,-1.835599 -0.896294,-3.556847 -1.872652,-5.12758 -0.895541,-1.441699 -2.047808,-2.70454 -3.417268,-3.766975 0,0 0.002,-0.002 0.002,-0.002 0,0 -13.828458,-10.6197195 -13.828458,-10.6197195 -0.01176,-0.00978 -0.02252,-0.019551 -0.03529,-0.028344 -0.909003,-0.6959264 -3.879837,-0.7738945 -4.87679,-0.075035 -1.01067,0.7057021 -1.091821,1.8092613 -0.195527,2.5482146 1.899775,1.4997633 2.656207,2.2801589 4.566507,3.7797379 0,0 -14.852491,0.167033 -14.852491,0.167033 -1.994685,0 -3.1682609,0.947915 -3.4153947,2.333683 -0.2180771,1.222836 0.7479213,2.738129 2.4800217,2.738129 2.956573,0.0039 5.942111,-0.0069 8.909215,-0.01272 0,0 -16.01999,12.453223 -16.01999,12.453223 -0.020527,0.01564 -0.041053,0.02933 -0.06158,0.04497 -1.4974197,1.148389 -1.9831951,3.059322 -1.0399808,4.268393 0.9598323,1.22959 2.9977653,1.230588 4.5147288,0.006 0,0 8.677593,-7.102098 8.677593,-7.102098 0,0 -0.12511,0.959824 -0.116333,1.535532 l 1e-6,2.6e-5 0,0 0,0 z"
- sodipodi:nodetypes="csssssssssscccsscccscccssccc"
- inkscape:connector-curvature="0" />
- <path
- sodipodi:type="arc"
- style="fill:url(#linearGradient14822);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- id="path14792"
- sodipodi:cx="31.1875"
- sodipodi:cy="25.75"
- sodipodi:rx="11.5625"
- sodipodi:ry="10.125"
- d="m 42.75,25.75 c 0,5.591883 -5.176708,10.125 -11.5625,10.125 -6.385792,0 -11.5625,-4.533117 -11.5625,-10.125 0,-5.591883 5.176708,-10.125 11.5625,-10.125 6.385792,0 11.5625,4.533117 11.5625,10.125 z"
- transform="matrix(0.8018194,0,0,0.8471126,6.257567,4.5089892)" />
- <path
- sodipodi:nodetypes="csssssscssscsssccssscscccsccssssccscsscccssssc"
- id="path14794"
- d="m 25.8125,6.40625 c -0.334829,4.572e-4 -0.72202,0.089606 -0.90625,0.21875 4.5e-4,0.010412 4.5e-4,0.020838 0,0.03125 -0.212626,0.1484635 -0.188235,0.1956271 -0.1875,0.1875 0.0092,0.010621 -0.0072,-4.246e-4 0.03125,0.03125 0.01962,0.00828 0.03527,0.012546 0.0625,0.03125 0.01676,0.01151 0.01357,0.014555 0.03125,0.03125 0.193748,0.1576058 4.954976,4.005164 4.954976,4.005164 0.489837,0.39864 0.677395,1.066352 0.46875,1.65625 -0.115662,0.32703 -0.422813,0.541217 -0.6875,0.59375 -0.264687,0.05253 -0.498447,0.03054 -0.71875,0.03125 -5.639658,0.05119 -16.87989,0.03851 -16.87989,0.03851 -0.4102,2.75e-4 -0.935835,0.115997 -1.34375,0.34375 -0.407915,0.227753 -0.6637862,0.523861 -0.6875002,0.90625 -0.024417,0.393728 0.098829,0.605767 0.3437502,0.78125 0.244921,0.175483 0.614978,0.25 0.875,0.25 0,0 8.8125,0 8.8125,0 0.600305,-7.28e-4 1.223895,0.311058 1.4375,0.9375 0.04676,0.137121 0.06335,0.269976 0.0625,0.40625 -8.49e-4,0.136274 -0.02214,0.268794 -0.09375,0.375 -0.143211,0.212412 -0.319507,0.298568 -0.5,0.4375 0,0 -15.7871819,12.746851 -15.856336,12.800078 C 5.0310984,30.500117 5,30.53125 5,30.53125 5.0100745,30.519077 5.000335,30.499512 5,30.5 L 4.8125,30.3125 c 0.012336,0.02165 0.014481,0.03307 0.03125,0.0625 0.063558,0.0774 0.125,0.15625 0.125,0.15625 -0.00585,0.0056 -0.031233,0.03124 -0.03125,0.03125 0,0 -0.043442,-0.09921 -0.09375,-0.1875 0.037843,0.09884 0.06253,0.218739 0.0625,0.21875 -0.4662091,0.37119 -0.7783348,0.889746 -0.875,1.28125 -0.1043319,0.422581 -0.046,0.62455 0.125,0.84375 0.2999827,0.384295 1.3975356,0.595547 2.40625,-0.21875 0,0 8.65625,-7.09375 8.65625,-7.09375 0.473718,-0.387074 1.1446,-0.458625 1.6875,-0.15625 0.544608,0.303331 0.798054,0.927572 0.71875,1.53125 0,0 -0.0626,0.908319 -0.0625,1.25 2e-6,0.0085 -1.19e-4,0.02348 0,0.03125 0.192796,2.523718 1.400736,4.762818 3.03125,6.71875 2.801818,3.089095 6.627659,4.401619 10.75,4.5625 4.113324,-0.043 7.964529,-1.606111 10.75,-4.625 2.546631,-3.125326 3.513872,-6.363859 3.15625,-9.375 C 44.891575,22.325847 43.222923,19.516566 40.4375,17.25 35.951885,13.599946 31.206991,10.168434 26.59375,6.625 26.57515,6.610386 26.56455,6.59802 26.5625,6.59375 26.43835,6.498703 26.144223,6.4057899 25.8125,6.40625 z"
- style="opacity:0.4857143;fill:none;stroke:url(#linearGradient14825);stroke-width:1.7812928;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1"
- inkscape:connector-curvature="0" />
- <path
- style="fill:#3465a4;fill-rule:evenodd;stroke:none"
- id="path14796"
- d="m 25.708956,26.064593 c 0.07649,-1.397943 0.759369,-2.631914 1.78592,-3.505519 1.010226,-0.858782 2.366788,-1.383145 3.848625,-1.383145 1.480894,0 2.837456,0.524363 3.847446,1.383145 1.027685,0.873605 1.709741,2.106651 1.787122,3.504594 0.07927,1.438713 -0.49591,2.77459 -1.504012,3.764001 -1.027686,1.007933 -2.493008,1.640678 -4.130556,1.640678 -1.63849,0 -3.103814,-0.632745 -4.131451,-1.640678 -1.00914,-0.989411 -1.58234,-2.325288 -1.503094,-3.763076 l 0,0 0,0 0,0 z"
- inkscape:connector-curvature="0" />
- <path
- style="opacity:0.51999996;fill:url(#radialGradient14827);fill-opacity:1;fill-rule:evenodd;stroke:none"
- d="m 25.8125,6.03125 c -0.404852,5.53e-4 -2.204797,-0.059029 -2.48145,0.1349032 -0.280209,0.195652 -0.335403,0.376484 -0.34375,0.46875 -0.0083,0.092266 -0.01539,0.17648 0.1875,0.34375 0.01899,0.015735 0.04457,0.014317 0.0625,0.03125 0.124258,0.101028 4.748869,4.1248618 4.748869,4.1248618 0.373658,0.304091 0.504393,0.795817 0.34375,1.25 -0.160635,0.454191 -0.580748,0.373449 -1.0625,0.375 -5.634142,0.05114 -15.087371,-0.129601 -15.087371,-0.129601 -0.952967,6.38e-4 -2.339958,0.524782 -2.4062504,1.59375 -0.063562,1.024947 0.9247974,1.4375 1.5937504,1.4375 0,-1e-6 8.8125,0 8.8125,0 0.488364,-5.92e-4 0.936141,0.225277 1.09375,0.6875 0.157609,0.462231 -0.01926,0.514621 -0.40625,0.8125 0,0 -16.086298,13.088586 -16.086298,13.088586 -0.00142,0.0014 -0.029829,-0.0014 -0.03125,0 -0.064037,0.04879 -0.054226,0.04875 -0.03125,0.03125 -0.5536758,0.424619 -0.9087886,1.004019 -1.03125,1.5 -0.1224536,0.495981 -0.04661,0.856152 0.1875,1.15625 0.4788333,0.613413 1.777612,0.754857 2.90625,-0.15625 1e-7,10e-7 8.65625,-7.09375 8.65625,-7.09375 0.361955,-0.295753 0.872897,-0.352437 1.28125,-0.125 0.408345,0.227436 0.623381,0.692814 0.5625,1.15625 0,-1e-6 -0.0997,0.953636 -0.09375,1.34375 0.09498,1.301756 0.451616,2.521825 0.989039,3.664234 C 20.799917,36.321089 27.770982,19.392853 44.1875,21.03125 43.339652,19.54368 42.151282,18.185293 40.65625,16.96875 36.159865,13.309932 31.42016,9.882897 26.8125,6.34375 26.805335,6.338858 26.788292,6.317553 26.78125,6.3125 26.570707,6.151312 26.216591,6.030689 25.8125,6.03125 z"
- id="path14798"
- sodipodi:nodetypes="csssscsccsscsccssssscsscccsssc"
- inkscape:connector-curvature="0" />
- </g>
- </g>
- <g
- id="g20347"
+ id="ICON_SMOOTHCURVE"
transform="translate(0,2)">
<rect
style="opacity:0;fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
@@ -36757,7 +39219,7 @@
</g>
</g>
<g
- id="g20291"
+ id="ICON_LINCURVE"
transform="translate(0,2)">
<rect
style="opacity:0;fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
@@ -36789,7 +39251,7 @@
</g>
</g>
<g
- id="g20301"
+ id="ICON_SHARPCURVE"
transform="translate(0,2)">
<rect
y="176"
@@ -36823,7 +39285,7 @@
</g>
</g>
<g
- id="g20337"
+ id="ICON_SPHERECURVE"
transform="translate(0,2)">
<rect
y="176"
@@ -36844,7 +39306,7 @@
sodipodi:cy="40"
sodipodi:rx="6"
sodipodi:ry="6"
- d="m 36.5,40 c 0,3.313708 -2.686292,6 -6,6 -3.313708,0 -6,-2.686292 -6,-6 0,0 0,0 0,0"
+ d="m 36.5,40 a 6,6 0 0 1 -3,5.196152 6,6 0 0 1 -6,0 A 6,6 0 0 1 24.5,40"
sodipodi:start="0"
sodipodi:end="3.1415927"
sodipodi:open="true"
@@ -36860,7 +39322,7 @@
sodipodi:open="true"
sodipodi:end="3.1415927"
sodipodi:start="0"
- d="m 36.5,40 c 0,3.313708 -2.686292,6 -6,6 -3.313708,0 -6,-2.686292 -6,-6 0,0 0,0 0,0"
+ d="m 36.5,40 a 6,6 0 0 1 -3,5.196152 6,6 0 0 1 -6,0 A 6,6 0 0 1 24.5,40"
sodipodi:ry="6"
sodipodi:rx="6"
sodipodi:cy="40"
@@ -36871,7 +39333,7 @@
</g>
</g>
<g
- id="g20311"
+ id="ICON_ROOTCURVE"
transform="translate(0,2)">
<rect
style="opacity:0;fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
@@ -36888,7 +39350,7 @@
sodipodi:open="true"
sodipodi:end="3.1415927"
sodipodi:start="0"
- d="m 36.5,40 c 0,3.313708 -2.686292,6 -6,6 -3.313708,0 -6,-2.686292 -6,-6 0,0 0,0 0,0"
+ d="m 36.5,40 a 6,6 0 0 1 -3,5.196152 6,6 0 0 1 -6,0 A 6,6 0 0 1 24.5,40"
sodipodi:ry="6"
sodipodi:rx="6"
sodipodi:cy="40"
@@ -36912,7 +39374,7 @@
sodipodi:cy="40"
sodipodi:rx="6"
sodipodi:ry="6"
- d="m 36.5,40 c 0,3.313708 -2.686292,6 -6,6 -3.313708,0 -6,-2.686292 -6,-6 0,0 0,0 0,0"
+ d="m 36.5,40 a 6,6 0 0 1 -3,5.196152 6,6 0 0 1 -6,0 A 6,6 0 0 1 24.5,40"
sodipodi:start="0"
sodipodi:end="3.1415927"
sodipodi:open="true" />
@@ -36920,7 +39382,7 @@
</g>
<g
style="display:inline"
- id="g18862"
+ id="ICON_NOCURVE"
transform="translate(259,151)">
<rect
y="28"
@@ -36955,7 +39417,7 @@
</g>
<g
style="display:inline"
- id="g18856"
+ id="ICON_RNDCURVE"
transform="translate(260,151)">
<rect
style="opacity:0;fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
@@ -36989,7 +39451,7 @@
</g>
</g>
<g
- id="g33683"
+ id="ICON_PROP_CON"
transform="translate(0,2)">
<rect
y="176"
@@ -37015,7 +39477,7 @@
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
sodipodi:ry="8"
sodipodi:rx="8"
sodipodi:cy="118"
@@ -37033,14 +39495,14 @@
sodipodi:cy="118"
sodipodi:rx="8"
sodipodi:ry="8"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90" />
</g>
</g>
<g
- id="g33690"
+ id="ICON_PROP_ON"
transform="translate(0,2)">
<rect
style="opacity:0;fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
@@ -37067,7 +39529,7 @@
sodipodi:cy="118"
sodipodi:rx="8"
sodipodi:ry="8"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90"
@@ -37076,7 +39538,7 @@
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
sodipodi:ry="8"
sodipodi:rx="8"
sodipodi:cy="118"
@@ -37090,7 +39552,7 @@
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
sodipodi:ry="8"
sodipodi:rx="8"
sodipodi:cy="118"
@@ -37108,7 +39570,7 @@
sodipodi:cy="118"
sodipodi:rx="8"
sodipodi:ry="8"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90" />
@@ -37121,14 +39583,14 @@
sodipodi:cy="118"
sodipodi:rx="8"
sodipodi:ry="8"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90" />
</g>
</g>
<g
- id="g12431"
+ id="ICON_OUTLINER_OB_EMPTY"
transform="translate(0,128)">
<rect
style="opacity:0;fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
@@ -37164,7 +39626,7 @@
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png"
transform="matrix(1.0911926,0,0,1.176776,253.08415,-79.548088)"
- d="M 72,14.5 C 72,15.328427 71.328427,16 70.5,16 69.671573,16 69,15.328427 69,14.5 69,13.671573 69.671573,13 70.5,13 c 0.828427,0 1.5,0.671573 1.5,1.5 z"
+ d="M 72,14.5 A 1.5,1.5 0 0 1 70.5,16 1.5,1.5 0 0 1 69,14.5 1.5,1.5 0 0 1 70.5,13 1.5,1.5 0 0 1 72,14.5 Z"
sodipodi:ry="1.5"
sodipodi:rx="1.5"
sodipodi:cy="14.5"
@@ -37322,7 +39784,7 @@
</g>
</g>
<g
- id="g24997"
+ id="ICON_OUTLINER_OB_CURVE"
transform="translate(0,128)">
<rect
ry="0"
@@ -37433,7 +39895,7 @@
</g>
</g>
<g
- id="g10687"
+ id="ICON_OUTLINER_DATA_CURVE"
transform="translate(0,128)">
<rect
style="opacity:0;fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
@@ -37511,7 +39973,7 @@
</g>
</g>
<g
- id="g21376"
+ id="ICON_GHOST"
transform="translate(0,2)">
<rect
style="opacity:0;fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
@@ -37608,10 +40070,7 @@
</g>
</g>
<g
- id="g10203"
- transform="translate(-211.20006,170)" />
- <g
- id="g21567"
+ id="ICON_ROTATECOLLECTION"
transform="translate(-0.9687515,1.9789998)">
<g
transform="matrix(1.0019536,0,0,1,-173.76637,169.95095)"
@@ -37631,7 +40090,7 @@
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
sodipodi:ry="8"
sodipodi:rx="8"
sodipodi:cy="118"
@@ -37656,7 +40115,7 @@
sodipodi:cy="118"
sodipodi:rx="8"
sodipodi:ry="8"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90" />
@@ -37665,7 +40124,7 @@
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
sodipodi:ry="8"
sodipodi:rx="8"
sodipodi:cy="118"
@@ -37717,7 +40176,7 @@
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
sodipodi:ry="8"
sodipodi:rx="8"
sodipodi:cy="118"
@@ -37734,7 +40193,7 @@
sodipodi:cy="118"
sodipodi:rx="8"
sodipodi:ry="8"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90"
@@ -37775,7 +40234,7 @@
</g>
</g>
<g
- id="g21647"
+ id="ICON_ROTATECENTER"
transform="translate(-1,1.9790001)">
<rect
style="opacity:0;fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
@@ -37807,7 +40266,7 @@
sodipodi:cy="118"
sodipodi:rx="8"
sodipodi:ry="8"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90" />
@@ -37816,7 +40275,7 @@
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
sodipodi:ry="8"
sodipodi:rx="8"
sodipodi:cy="118"
@@ -37836,7 +40295,7 @@
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
sodipodi:ry="8"
sodipodi:rx="8"
sodipodi:cy="118"
@@ -37853,7 +40312,7 @@
sodipodi:cy="118"
sodipodi:rx="8"
sodipodi:ry="8"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90"
@@ -37894,7 +40353,7 @@
</g>
</g>
<g
- id="g21623"
+ id="ICON_ROTACTIVE"
transform="translate(-0.9999786,1.9982099)">
<g
transform="matrix(0.9999986,0,0,1,-170.19957,169.98079)"
@@ -37924,7 +40383,7 @@
sodipodi:cy="118"
sodipodi:rx="8"
sodipodi:ry="8"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90" />
@@ -37939,7 +40398,7 @@
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
sodipodi:ry="8"
sodipodi:rx="8"
sodipodi:cy="118"
@@ -37956,7 +40415,7 @@
sodipodi:cy="118"
sodipodi:rx="8"
sodipodi:ry="8"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90"
@@ -37978,7 +40437,7 @@
sodipodi:cy="118"
sodipodi:rx="8"
sodipodi:ry="8"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90" />
@@ -37987,7 +40446,7 @@
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
sodipodi:ry="8"
sodipodi:rx="8"
sodipodi:cy="118"
@@ -38034,7 +40493,7 @@
</g>
</g>
<g
- id="g21519"
+ id="ICON_CURSOR"
transform="translate(0,2)">
<rect
style="opacity:0;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline"
@@ -38058,7 +40517,7 @@
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
- d="m 141.08637,118 c 0,5.0181 -4.06811,9.08607 -9.08637,9.08607 -5.01826,0 -9.08637,-4.06797 -9.08637,-9.08607 0,-5.0181 4.06811,-9.08607 9.08637,-9.08607 5.01826,0 9.08637,4.06797 9.08637,9.08607 z"
+ d="M 141.08637,118 A 9.0863705,9.0860729 0 0 1 132,127.08607 9.0863705,9.0860729 0 0 1 122.91363,118 9.0863705,9.0860729 0 0 1 132,108.91393 9.0863705,9.0860729 0 0 1 141.08637,118 Z"
sodipodi:ry="9.0860729"
sodipodi:rx="9.0863705"
sodipodi:cy="118"
@@ -38084,113 +40543,14 @@
sodipodi:cy="118"
sodipodi:rx="9.0863705"
sodipodi:ry="9.0860729"
- d="m 141.08637,118 c 0,5.0181 -4.06811,9.08607 -9.08637,9.08607 -5.01826,0 -9.08637,-4.06797 -9.08637,-9.08607 0,-5.0181 4.06811,-9.08607 9.08637,-9.08607 5.01826,0 9.08637,4.06797 9.08637,9.08607 z"
+ d="M 141.08637,118 A 9.0863705,9.0860729 0 0 1 132,127.08607 9.0863705,9.0860729 0 0 1 122.91363,118 9.0863705,9.0860729 0 0 1 132,108.91393 9.0863705,9.0860729 0 0 1 141.08637,118 Z"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90" />
</g>
</g>
<g
- id="g21663"
- transform="translate(0,2)">
- <rect
- style="opacity:0;fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- id="rect21661"
- width="16"
- height="16"
- x="215"
- y="176" />
- <g
- transform="translate(-87.98837,-19.85)"
- id="g21392"
- style="display:inline">
- <g
- id="g11189"
- style="opacity:0.05"
- transform="translate(-62.011627,236.84995)">
- <rect
- style="fill:none;stroke:#447cce;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:7.40000265;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- id="rect11191"
- width="2.9998775"
- height="3"
- x="366.5"
- y="-39.5"
- ry="1.375"
- rx="1.375" />
- <rect
- ry="1.375"
- y="-39.5"
- x="371.5"
- height="3"
- width="2.9998775"
- id="rect11193"
- style="fill:none;stroke:#447cce;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:7.40000265;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- rx="1.375" />
- <rect
- style="fill:none;stroke:#447cce;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:7.40000265;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- id="rect11195"
- width="2.9998775"
- height="3"
- x="376.5"
- y="-39.5"
- ry="1.375"
- rx="1.375" />
- </g>
- <rect
- style="fill:none;stroke:#22467e;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:7.40000265;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- id="rect11197"
- width="2.9998775"
- height="3"
- x="304.48837"
- y="197.34995"
- ry="1.375"
- rx="1.375" />
- <path
- inkscape:export-ydpi="90"
- inkscape:export-xdpi="90"
- inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
- id="path11199"
- d="m 304.98827,197.84994 c 0.6667,0 1.3334,1e-5 2.0001,1e-5 0,0.66668 0,1.33337 0,2.00005 -0.6667,0 -1.3334,-1e-5 -2.0001,-1e-5 0,-0.66668 0,-1.33337 0,-2.00005 z"
- style="fill:#c3dbff;fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline"
- inkscape:connector-curvature="0" />
- <rect
- ry="1.375"
- y="197.34995"
- x="309.48837"
- height="3"
- width="2.9998775"
- id="rect11201"
- style="fill:none;stroke:#22467e;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:7.40000265;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- rx="1.375" />
- <path
- style="fill:#c3dbff;fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline"
- d="m 309.98827,197.84994 c 0.6667,0 1.3334,1e-5 2.0001,1e-5 0,0.66668 0,1.33337 0,2.00005 -0.6667,0 -1.3334,-1e-5 -2.0001,-1e-5 0,-0.66668 0,-1.33337 0,-2.00005 z"
- id="path11203"
- inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
- inkscape:export-xdpi="90"
- inkscape:export-ydpi="90"
- inkscape:connector-curvature="0" />
- <rect
- style="fill:none;stroke:#22467e;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:7.40000265;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- id="rect11205"
- width="2.9998775"
- height="3"
- x="314.48837"
- y="197.34995"
- ry="1.375"
- rx="1.375" />
- <path
- inkscape:export-ydpi="90"
- inkscape:export-xdpi="90"
- inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
- id="path11207"
- d="m 314.98827,197.84994 c 0.6667,0 1.3334,1e-5 2.0001,1e-5 0,0.66668 0,1.33337 0,2.00005 -0.6667,0 -1.3334,-1e-5 -2.0001,-1e-5 0,-0.66668 0,-1.33337 0,-2.00005 z"
- style="fill:#c3dbff;fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline"
- inkscape:connector-curvature="0" />
- </g>
- </g>
- <g
- id="g11724"
+ id="ICON_LAYER_ACTIVE"
transform="translate(0,2)">
<rect
style="opacity:0;fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
@@ -38224,7 +40584,7 @@
</g>
</g>
<g
- id="g11718"
+ id="ICON_LAYER_USED"
transform="translate(0,2)">
<rect
y="113"
@@ -38258,7 +40618,7 @@
</g>
</g>
<g
- id="g11764"
+ id="ICON_NDOF_TURN"
transform="translate(0,2)">
<rect
y="113"
@@ -38331,7 +40691,7 @@
sodipodi:cy="-222"
sodipodi:rx="3.3084693"
sodipodi:ry="1.2798798"
- d="m 111.30847,-222 c 0,0.70686 -1.48125,1.27988 -3.30847,1.27988 -1.82722,0 -3.30847,-0.57302 -3.30847,-1.27988 0,-0.70686 1.48125,-1.27988 3.30847,-1.27988 1.82722,0 3.30847,0.57302 3.30847,1.27988 z"
+ d="M 111.30847,-222 A 3.3084693,1.2798798 0 0 1 108,-220.72012 3.3084693,1.2798798 0 0 1 104.69153,-222 3.3084693,1.2798798 0 0 1 108,-223.27988 3.3084693,1.2798798 0 0 1 111.30847,-222 Z"
transform="matrix(1.0307577,0,0,0.9140456,39.651558,-39.251735)" />
<path
sodipodi:nodetypes="cssss"
@@ -38355,7 +40715,7 @@
</g>
</g>
<g
- id="g11730"
+ id="ICON_NDOF_TRANS"
transform="translate(0,2)">
<rect
y="113"
@@ -38396,7 +40756,7 @@
sodipodi:cy="-222"
sodipodi:rx="3.3084693"
sodipodi:ry="1.2798798"
- d="m 111.30847,-222 c 0,0.70686 -1.48125,1.27988 -3.30847,1.27988 -1.82722,0 -3.30847,-0.57302 -3.30847,-1.27988 0,-0.70686 1.48125,-1.27988 3.30847,-1.27988 1.82722,0 3.30847,0.57302 3.30847,1.27988 z"
+ d="M 111.30847,-222 A 3.3084693,1.2798798 0 0 1 108,-220.72012 3.3084693,1.2798798 0 0 1 104.69153,-222 3.3084693,1.2798798 0 0 1 108,-223.27988 3.3084693,1.2798798 0 0 1 111.30847,-222 Z"
transform="matrix(1.0307577,0,0,0.9140456,39.651558,-39.251735)" />
<path
sodipodi:nodetypes="cssss"
@@ -38455,7 +40815,7 @@
</g>
</g>
<g
- id="g11749"
+ id="ICON_NDOF_FLY"
transform="translate(0,2)">
<rect
style="opacity:0;fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
@@ -38490,7 +40850,7 @@
inkscape:connector-curvature="0" />
<path
transform="matrix(1.0307577,0,0,0.9140456,39.651558,-39.251735)"
- d="m 111.30847,-222 c 0,0.70686 -1.48125,1.27988 -3.30847,1.27988 -1.82722,0 -3.30847,-0.57302 -3.30847,-1.27988 0,-0.70686 1.48125,-1.27988 3.30847,-1.27988 1.82722,0 3.30847,0.57302 3.30847,1.27988 z"
+ d="M 111.30847,-222 A 3.3084693,1.2798798 0 0 1 108,-220.72012 3.3084693,1.2798798 0 0 1 104.69153,-222 3.3084693,1.2798798 0 0 1 108,-223.27988 3.3084693,1.2798798 0 0 1 111.30847,-222 Z"
sodipodi:ry="1.2798798"
sodipodi:rx="3.3084693"
sodipodi:cy="-222"
@@ -38535,7 +40895,7 @@
</g>
</g>
<g
- id="g23801"
+ id="ICON_NDOF_DOM"
transform="translate(0,2)">
<rect
style="opacity:0;fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
@@ -38578,7 +40938,7 @@
sodipodi:cy="14.5"
sodipodi:rx="1.5"
sodipodi:ry="1.5"
- d="M 72,14.5 C 72,15.328427 71.328427,16 70.5,16 69.671573,16 69,15.328427 69,14.5 69,13.671573 69.671573,13 70.5,13 c 0.828427,0 1.5,0.671573 1.5,1.5 z"
+ d="M 72,14.5 A 1.5,1.5 0 0 1 70.5,16 1.5,1.5 0 0 1 69,14.5 1.5,1.5 0 0 1 70.5,13 1.5,1.5 0 0 1 72,14.5 Z"
transform="matrix(1.176776,0,0,1.176776,-12.47787,-2.548088)"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png"
inkscape:export-xdpi="90"
@@ -38646,7 +41006,7 @@
sodipodi:cy="14.5"
sodipodi:rx="1.5"
sodipodi:ry="1.5"
- d="M 72,14.5 C 72,15.328427 71.328427,16 70.5,16 69.671573,16 69,15.328427 69,14.5 69,13.671573 69.671573,13 70.5,13 c 0.828427,0 1.5,0.671573 1.5,1.5 z"
+ d="M 72,14.5 A 1.5,1.5 0 0 1 70.5,16 1.5,1.5 0 0 1 69,14.5 1.5,1.5 0 0 1 70.5,13 1.5,1.5 0 0 1 72,14.5 Z"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90" />
@@ -38717,16 +41077,8 @@
ry="0" />
</g>
</g>
- <rect
- style="opacity:0;fill:#4d4d4d;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:6;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- id="rect15876"
- width="16"
- height="16"
- x="110"
- y="409"
- ry="0" />
- <g
- id="g20862"
+ <g
+ id="ICON_ANIM_DATA"
transform="translate(168,65.000007)">
<rect
style="opacity:0;fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
@@ -38757,7 +41109,7 @@
</g>
</g>
<g
- id="g10534"
+ id="ICON_SCRIPT"
transform="translate(0,128.00001)">
<rect
y="428"
@@ -38836,7 +41188,7 @@
</g>
</g>
<g
- id="g10512"
+ id="ICON_RADIO"
transform="translate(0,128.00001)">
<rect
style="opacity:0;fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
@@ -38875,7 +41227,7 @@
inkscape:export-xdpi="90"
inkscape:export-ydpi="90">
<path
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
sodipodi:ry="8"
sodipodi:rx="8"
sodipodi:cy="118"
@@ -38899,7 +41251,7 @@
sodipodi:cy="118"
sodipodi:rx="8"
sodipodi:ry="8"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z" />
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z" />
</g>
<path
style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
@@ -38948,7 +41300,7 @@
</g>
</g>
<path
- d="m 139.7074,118 c 0,4.26593 -3.45072,7.72414 -7.7074,7.72414 -4.25668,0 -7.7074,-3.45821 -7.7074,-7.72414 0,-4.26593 3.45072,-7.72414 7.7074,-7.72414 4.25668,0 7.7074,3.45821 7.7074,7.72414 z"
+ d="M 139.7074,118 A 7.7074003,7.7241406 0 0 1 132,125.72414 7.7074003,7.7241406 0 0 1 124.2926,118 7.7074003,7.7241406 0 0 1 132,110.27586 7.7074003,7.7241406 0 0 1 139.7074,118 Z"
sodipodi:ry="7.7241406"
sodipodi:rx="7.7074003"
sodipodi:cy="118"
@@ -39002,7 +41354,7 @@
</g>
<g
style="display:inline"
- id="g21197"
+ id="ICON_BONE_DATA"
transform="translate(20,319.00001)">
<rect
style="opacity:0;fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
@@ -39077,7 +41429,7 @@
</g>
<g
style="display:inline"
- id="g24682"
+ id="ICON_DISCLOSURE_TRI_RIGHT"
transform="translate(-166,402)">
<rect
y="217"
@@ -39104,7 +41456,7 @@
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
sodipodi:ry="8"
sodipodi:rx="8"
sodipodi:cy="118"
@@ -39144,7 +41496,7 @@
sodipodi:cy="118"
sodipodi:rx="8"
sodipodi:ry="8"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90" />
@@ -39162,7 +41514,7 @@
</g>
<g
style="display:inline"
- id="g24609"
+ id="ICON_INLINK"
transform="translate(307.00001,487.05412)">
<rect
y="111"
@@ -39200,7 +41552,7 @@
</g>
</g>
<g
- id="g106468">
+ id="ICON_RIGHTARROW">
<g
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
@@ -39230,7 +41582,7 @@
style="opacity:0;fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
</g>
<g
- id="g29910">
+ id="ICON_DOWNARROW">
<rect
transform="matrix(0,1,-1,0,0,0)"
style="opacity:0;fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
@@ -39262,7 +41614,7 @@
</g>
<g
style="display:inline"
- id="g24559"
+ id="ICON_DOT"
transform="translate(259,508.00001)">
<rect
y="111"
@@ -39276,7 +41628,7 @@
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
sodipodi:ry="8"
sodipodi:rx="8"
sodipodi:cy="118"
@@ -39287,7 +41639,7 @@
</g>
<g
style="display:inline"
- id="g24623"
+ id="ICON_ZOOMOUT"
transform="translate(-112,487.00001)">
<rect
style="opacity:0;fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
@@ -39325,7 +41677,7 @@
</g>
<g
style="display:inline"
- id="g24617"
+ id="ICON_ZOOMIN"
transform="translate(-113,487.00001)">
<rect
y="111"
@@ -39360,7 +41712,7 @@
</g>
<g
style="display:inline"
- id="g24629"
+ id="ICON_PLUS"
transform="translate(-128,487.00001)">
<rect
y="132"
@@ -39387,7 +41739,7 @@
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
sodipodi:ry="8"
sodipodi:rx="8"
sodipodi:cy="118"
@@ -39427,7 +41779,7 @@
sodipodi:cy="118"
sodipodi:rx="8"
sodipodi:ry="8"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90" />
@@ -39445,7 +41797,7 @@
</g>
<g
style="display:inline"
- id="g24604"
+ id="ICON_LINK"
transform="translate(305,487.00001)">
<rect
y="111"
@@ -39466,13 +41818,13 @@
sodipodi:cy="119.5"
sodipodi:rx="5.5"
sodipodi:ry="5.5"
- d="m 196,119.5 c 0,3.03757 -2.46243,5.5 -5.5,5.5 -3.03757,0 -5.5,-2.46243 -5.5,-5.5 0,-3.03757 2.46243,-5.5 5.5,-5.5 3.03757,0 5.5,2.46243 5.5,5.5 z"
+ d="m 196,119.5 a 5.5,5.5 0 0 1 -5.5,5.5 5.5,5.5 0 0 1 -5.5,-5.5 5.5,5.5 0 0 1 5.5,-5.5 5.5,5.5 0 0 1 5.5,5.5 z"
transform="matrix(0.61819,0,0,0.618186,73.23488,45.12681)" />
</g>
</g>
<g
style="display:inline"
- id="g24582"
+ id="ICON_RADIOBUT_OFF"
transform="translate(114.02028,508.00993)">
<rect
y="111"
@@ -39485,7 +41837,7 @@
id="g24576">
<path
transform="matrix(1.4256767,0,0,1.4314068,-320.1963,68.175135)"
- d="m 333.29445,35.5 c 0,1.543333 -1.25112,2.794451 -2.79445,2.794451 -1.54333,0 -2.79445,-1.251118 -2.79445,-2.794451 0,-1.543333 1.25112,-2.794451 2.79445,-2.794451 1.54333,0 2.79445,1.251118 2.79445,2.794451 z"
+ d="M 333.29445,35.5 A 2.7944512,2.7944512 0 0 1 330.5,38.294451 2.7944512,2.7944512 0 0 1 327.70555,35.5 2.7944512,2.7944512 0 0 1 330.5,32.705549 2.7944512,2.7944512 0 0 1 333.29445,35.5 Z"
sodipodi:ry="2.7944512"
sodipodi:rx="2.7944512"
sodipodi:cy="35.5"
@@ -39495,7 +41847,7 @@
sodipodi:type="arc" />
<path
transform="matrix(1.2885487,0,0,1.2885617,-274.87525,73.246084)"
- d="m 334,35.5 c 0,1.932997 -1.567,3.5 -3.5,3.5 -1.933,0 -3.5,-1.567003 -3.5,-3.5 0,-1.932997 1.567,-3.5 3.5,-3.5 1.933,0 3.5,1.567003 3.5,3.5 z"
+ d="M 334,35.5 A 3.5,3.5 0 0 1 330.5,39 3.5,3.5 0 0 1 327,35.5 3.5,3.5 0 0 1 330.5,32 3.5,3.5 0 0 1 334,35.5 Z"
sodipodi:ry="3.5"
sodipodi:rx="3.5"
sodipodi:cy="35.5"
@@ -39511,13 +41863,13 @@
sodipodi:cy="35.5"
sodipodi:rx="3.5"
sodipodi:ry="3.5"
- d="m 334,35.5 c 0,1.932997 -1.567,3.5 -3.5,3.5 -1.933,0 -3.5,-1.567003 -3.5,-3.5 0,-1.932997 1.567,-3.5 3.5,-3.5 1.933,0 3.5,1.567003 3.5,3.5 z"
+ d="M 334,35.5 A 3.5,3.5 0 0 1 330.5,39 3.5,3.5 0 0 1 327,35.5 3.5,3.5 0 0 1 330.5,32 3.5,3.5 0 0 1 334,35.5 Z"
transform="matrix(-1.288521,0,0,-1.2885339,576.8463,164.73299)" />
</g>
</g>
<g
style="opacity:0.6;display:inline"
- id="g24923"
+ id="ICON_RIGHTARROW_THIN"
transform="translate(4,529.00001)">
<rect
style="opacity:0;fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
@@ -39561,7 +41913,7 @@
</g>
<g
style="display:inline"
- id="g24911"
+ id="ICON_TRIA_DOWN"
transform="translate(28,550.00001)">
<rect
style="opacity:0;fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
@@ -39593,7 +41945,7 @@
</g>
<g
style="display:inline"
- id="g24917"
+ id="ICON_TRIA_RIGHT"
transform="translate(27,550.00001)">
<rect
style="opacity:0;fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
@@ -39625,7 +41977,7 @@
</g>
<g
style="display:inline"
- id="g25461"
+ id="ICON_DOTSDOWN"
transform="translate(444,424.00001)">
<rect
y="174"
@@ -39690,7 +42042,7 @@
</g>
<g
style="display:inline"
- id="g25412"
+ id="ICON_DOTSUP"
transform="translate(443,424.00001)">
<rect
y="174"
@@ -39759,7 +42111,7 @@
</g>
<g
style="display:inline"
- id="g25528"
+ id="ICON_AUTO"
transform="translate(93,445.00001)">
<rect
style="opacity:0;fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
@@ -39789,7 +42141,7 @@
sodipodi:cy="165"
sodipodi:rx="1"
sodipodi:ry="1"
- d="m 148,165 c 0,0.55228 -0.44772,1 -1,1 -0.55228,0 -1,-0.44772 -1,-1 0,-0.55228 0.44772,-1 1,-1 0.55228,0 1,0.44772 1,1 z"
+ d="m 148,165 a 1,1 0 0 1 -1,1 1,1 0 0 1 -1,-1 1,1 0 0 1 1,-1 1,1 0 0 1 1,1 z"
transform="matrix(1.5,0,0,1.5,-73.5,-83.5)"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
inkscape:export-xdpi="90"
@@ -39808,7 +42160,7 @@
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
transform="matrix(1.5,0,0,1.5,-66.5,-83.5)"
- d="m 148,165 c 0,0.55228 -0.44772,1 -1,1 -0.55228,0 -1,-0.44772 -1,-1 0,-0.55228 0.44772,-1 1,-1 0.55228,0 1,0.44772 1,1 z"
+ d="m 148,165 a 1,1 0 0 1 -1,1 1,1 0 0 1 -1,-1 1,1 0 0 1 1,-1 1,1 0 0 1 1,1 z"
sodipodi:ry="1"
sodipodi:rx="1"
sodipodi:cy="165"
@@ -39819,7 +42171,7 @@
</g>
</g>
<g
- id="g35472"
+ id="ICON_VIEWZOOM"
transform="translate(0,128.00001)">
<rect
style="opacity:0;fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
@@ -39849,7 +42201,7 @@
sodipodi:cy="78.5"
sodipodi:rx="3.5"
sodipodi:ry="3.5"
- d="m 262,78.5 c 0,1.932997 -1.567,3.5 -3.5,3.5 -1.933,0 -3.5,-1.567003 -3.5,-3.5 0,-1.932997 1.567,-3.5 3.5,-3.5 1.933,0 3.5,1.567003 3.5,3.5 z"
+ d="M 262,78.5 A 3.5,3.5 0 0 1 258.5,82 3.5,3.5 0 0 1 255,78.5 3.5,3.5 0 0 1 258.5,75 3.5,3.5 0 0 1 262,78.5 Z"
transform="matrix(-1.4308622,0,0,1.4308687,469.36987,363.18486)"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
inkscape:export-xdpi="90"
@@ -39877,7 +42229,7 @@
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
transform="matrix(-1.4308622,0,0,1.4308687,469.36987,363.18486)"
- d="m 262,78.5 c 0,1.932997 -1.567,3.5 -3.5,3.5 -1.933,0 -3.5,-1.567003 -3.5,-3.5 0,-1.932997 1.567,-3.5 3.5,-3.5 1.933,0 3.5,1.567003 3.5,3.5 z"
+ d="M 262,78.5 A 3.5,3.5 0 0 1 258.5,82 3.5,3.5 0 0 1 255,78.5 3.5,3.5 0 0 1 258.5,75 3.5,3.5 0 0 1 262,78.5 Z"
sodipodi:ry="3.5"
sodipodi:rx="3.5"
sodipodi:cy="78.5"
@@ -39903,13 +42255,13 @@
sodipodi:cy="78.5"
sodipodi:rx="3.5"
sodipodi:ry="3.5"
- d="m 262,78.5 c 0,1.932997 -1.567,3.5 -3.5,3.5 -1.933,0 -3.5,-1.567003 -3.5,-3.5 0,-1.932997 1.567,-3.5 3.5,-3.5 1.933,0 3.5,1.567003 3.5,3.5 z"
+ d="M 262,78.5 A 3.5,3.5 0 0 1 258.5,82 3.5,3.5 0 0 1 255,78.5 3.5,3.5 0 0 1 258.5,75 3.5,3.5 0 0 1 262,78.5 Z"
transform="matrix(-1.14287,0,0,1.142863,463.9317,115.7853)" />
<g
id="g35307">
<path
transform="matrix(1.1162596,0,0,1.1065394,80.948334,-350.49863)"
- d="m 80.53125,502 c 0,1.38071 -1.133279,2.5 -2.53125,2.5 -1.397971,0 -2.53125,-1.11929 -2.53125,-2.5 0,-1.38071 1.133279,-2.5 2.53125,-2.5 1.397971,0 2.53125,1.11929 2.53125,2.5 z"
+ d="M 80.53125,502 A 2.5312502,2.5 0 0 1 78,504.5 2.5312502,2.5 0 0 1 75.46875,502 2.5312502,2.5 0 0 1 78,499.5 2.5312502,2.5 0 0 1 80.53125,502 Z"
sodipodi:ry="2.5"
sodipodi:rx="2.5312502"
sodipodi:cy="502"
@@ -39925,13 +42277,13 @@
sodipodi:cy="502"
sodipodi:rx="2.5312502"
sodipodi:ry="2.5"
- d="m 80.53125,502 c 0,1.38071 -1.133279,2.5 -2.53125,2.5 -1.397971,0 -2.53125,-1.11929 -2.53125,-2.5 0,-1.38071 1.133279,-2.5 2.53125,-2.5 1.397971,0 2.53125,1.11929 2.53125,2.5 z"
+ d="M 80.53125,502 A 2.5312502,2.5 0 0 1 78,504.5 2.5312502,2.5 0 0 1 75.46875,502 2.5312502,2.5 0 0 1 78,499.5 2.5312502,2.5 0 0 1 80.53125,502 Z"
transform="matrix(-1.087144,-0.2518404,0.2525206,-1.0776772,126.97246,766.619)" />
</g>
<path
inkscape:transform-center-y="-6.490455"
inkscape:transform-center-x="-3.3976162"
- d="m 65,135 c 0,0.55228 -0.447715,1 -1,1 -0.552285,0 -1,-0.44772 -1,-1 0,-0.55228 0.447715,-1 1,-1 0.552285,0 1,0.44772 1,1 z"
+ d="m 65,135 a 1,1 0 0 1 -1,1 1,1 0 0 1 -1,-1 1,1 0 0 1 1,-1 1,1 0 0 1 1,1 z"
sodipodi:ry="1"
sodipodi:rx="1"
sodipodi:cy="135"
@@ -39963,7 +42315,7 @@
</g>
<g
style="display:inline"
- id="g21566"
+ id="ICON_WORDWRAP_OFF"
transform="translate(-206,-205)">
<rect
style="opacity:0;fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
@@ -40007,7 +42359,7 @@
</g>
<g
style="display:inline"
- id="g21557"
+ id="ICON_WORDWRAP_ON"
transform="translate(-205,-205)">
<rect
y="236"
@@ -40054,7 +42406,7 @@
</g>
<g
style="display:inline"
- id="g21497"
+ id="ICON_SYNTAX_ON"
transform="translate(97,5)">
<rect
style="opacity:0;fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
@@ -40152,7 +42504,7 @@
</g>
<g
style="display:inline"
- id="g21514"
+ id="ICON_SYNTAX_OFF"
transform="translate(96.030183,5)">
<rect
y="26"
@@ -40235,7 +42587,7 @@
</g>
</g>
<g
- id="g11969"
+ id="ICON_LINENUMBERS_ON"
transform="translate(0,2)">
<rect
style="opacity:0;fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
@@ -40288,7 +42640,7 @@
</g>
</g>
<g
- id="g11979"
+ id="ICON_LINENUMBERS_OFF"
transform="translate(0,2)">
<rect
style="opacity:0;fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
@@ -40338,24 +42690,9 @@
</g>
</g>
<g
- id="g15785"
- transform="translate(-168.02763,373.00001)" />
- <g
- id="g15789"
- transform="translate(-168.02763,380.00001)" />
- <g
- transform="translate(-163.02763,375.00001)"
- id="g15795" />
- <g
- id="g15801"
- transform="translate(-163.02763,371.00001)" />
- <g
- transform="translate(-163.02763,382.00001)"
- id="g15807" />
- <g
style="display:inline"
transform="translate(150,389)"
- id="g22272">
+ id="ICON_MOD_CURVE">
<g
id="g22274"
transform="translate(-30,0)">
@@ -40458,7 +42795,7 @@
</g>
<g
style="display:inline"
- id="g31233"
+ id="ICON_MATPLANE"
transform="translate(-58,-17)">
<rect
style="opacity:0;fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
@@ -40497,7 +42834,7 @@
</g>
<g
style="display:inline"
- id="g31226"
+ id="ICON_MATSPHERE"
transform="translate(-57,-17)">
<rect
style="opacity:0;fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
@@ -40517,7 +42854,7 @@
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
sodipodi:ry="8"
sodipodi:rx="8"
sodipodi:cy="118"
@@ -40534,7 +42871,7 @@
sodipodi:cy="118"
sodipodi:rx="8"
sodipodi:ry="8"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90"
@@ -40548,14 +42885,14 @@
sodipodi:cy="118"
sodipodi:rx="8"
sodipodi:ry="8"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90" />
</g>
</g>
<g
- id="g31393"
+ id="ICON_ALIASED"
transform="translate(0,2)">
<rect
style="opacity:0;fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
@@ -40609,7 +42946,7 @@
</g>
<g
style="display:inline"
- id="g31442"
+ id="ICON_SEQ_LUMA_WAVEFORM"
transform="translate(-235,4)">
<rect
style="opacity:0;fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
@@ -40650,7 +42987,7 @@
</g>
<g
style="display:inline"
- id="g31515"
+ id="ICON_CLIPUV_DEHLT"
transform="translate(18,130)">
<rect
y="27"
@@ -40678,7 +43015,7 @@
sodipodi:cy="35.5"
sodipodi:rx="3.5"
sodipodi:ry="3.5"
- d="m 334,35.5 c 0,1.932997 -1.567,3.5 -3.5,3.5 -1.933,0 -3.5,-1.567003 -3.5,-3.5 0,-1.932997 1.567,-3.5 3.5,-3.5 1.933,0 3.5,1.567003 3.5,3.5 z"
+ d="M 334,35.5 A 3.5,3.5 0 0 1 330.5,39 3.5,3.5 0 0 1 327,35.5 3.5,3.5 0 0 1 330.5,32 3.5,3.5 0 0 1 334,35.5 Z"
transform="matrix(1.000048,0,0,0.999998,-0.01591645,12.000064)" />
<path
style="opacity:0.6;fill:none;stroke:url(#linearGradient15711);stroke-width:1;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dashoffset:0.5;display:inline"
@@ -40694,78 +43031,76 @@
sodipodi:cy="35.5"
sodipodi:rx="3.5"
sodipodi:ry="3.5"
- d="m 334,35.5 c 0,1.932997 -1.567,3.5 -3.5,3.5 -1.933,0 -3.5,-1.567003 -3.5,-3.5 0,-1.932997 1.567,-3.5 3.5,-3.5 1.933,0 3.5,1.567003 3.5,3.5 z"
+ d="M 334,35.5 A 3.5,3.5 0 0 1 330.5,39 3.5,3.5 0 0 1 327,35.5 3.5,3.5 0 0 1 330.5,32 3.5,3.5 0 0 1 334,35.5 Z"
transform="matrix(0.857099,0,0,0.857147,47.22893,17.071296)" />
</g>
</g>
<g
- transform="translate(39,130)"
- id="g27524"
- style="opacity:0.2;display:inline">
- <rect
- style="opacity:0;fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- id="rect27526"
- width="16"
- height="16"
- x="323"
- y="27" />
+ id="ICON_CLIPUV_HLT">
<g
- style="display:inline"
- id="g27528"
- transform="translate(0.01612278,-12)">
+ style="opacity:0.2;display:inline"
+ id="g27524"
+ transform="translate(39,130)">
<rect
- y="41.500015"
- x="324.50003"
- height="12"
- width="12"
- id="rect27530"
- style="fill:none;stroke:#000000;stroke-width:0.80000001;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0.5;display:inline" />
- <path
- transform="matrix(1.000048,0,0,0.999998,-0.01591645,12.000064)"
- d="m 334,35.5 c 0,1.932997 -1.567,3.5 -3.5,3.5 -1.933,0 -3.5,-1.567003 -3.5,-3.5 0,-1.932997 1.567,-3.5 3.5,-3.5 1.933,0 3.5,1.567003 3.5,3.5 z"
- sodipodi:ry="3.5"
- sodipodi:rx="3.5"
- sodipodi:cy="35.5"
- sodipodi:cx="330.5"
- id="path27532"
- style="fill:url(#linearGradient27540);fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline"
- sodipodi:type="arc" />
- <path
- sodipodi:nodetypes="ccc"
- id="path27534"
- d="m 335.50002,42.500013 -10,0 0,10 L 335.5,52.5 l 0,-10"
- style="opacity:0.6;fill:none;stroke:url(#linearGradient27542);stroke-width:1;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dashoffset:0.5;display:inline"
- inkscape:connector-curvature="0" />
- <path
- transform="matrix(0.857099,0,0,0.857147,47.22893,17.071296)"
- d="m 334,35.5 c 0,1.932997 -1.567,3.5 -3.5,3.5 -1.933,0 -3.5,-1.567003 -3.5,-3.5 0,-1.932997 1.567,-3.5 3.5,-3.5 1.933,0 3.5,1.567003 3.5,3.5 z"
- sodipodi:ry="3.5"
- sodipodi:rx="3.5"
- sodipodi:cy="35.5"
- sodipodi:cx="330.5"
- id="path27536"
- style="fill:none;stroke:url(#linearGradient27544);stroke-width:1.16669464;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0.5;display:inline"
- sodipodi:type="arc" />
+ y="27"
+ x="323"
+ height="16"
+ width="16"
+ id="rect27526"
+ style="opacity:0;fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <g
+ transform="translate(0.01612278,-12)"
+ id="g27528"
+ style="display:inline">
+ <rect
+ style="fill:none;stroke:#000000;stroke-width:0.80000001;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0.5;display:inline"
+ id="rect27530"
+ width="12"
+ height="12"
+ x="324.50003"
+ y="41.500015" />
+ <path
+ sodipodi:type="arc"
+ style="fill:url(#linearGradient27540);fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline"
+ id="path27532"
+ sodipodi:cx="330.5"
+ sodipodi:cy="35.5"
+ sodipodi:rx="3.5"
+ sodipodi:ry="3.5"
+ d="M 334,35.5 A 3.5,3.5 0 0 1 330.5,39 3.5,3.5 0 0 1 327,35.5 3.5,3.5 0 0 1 330.5,32 3.5,3.5 0 0 1 334,35.5 Z"
+ transform="matrix(1.000048,0,0,0.999998,-0.01591645,12.000064)" />
+ <path
+ inkscape:connector-curvature="0"
+ style="opacity:0.6;fill:none;stroke:url(#linearGradient27542);stroke-width:1;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dashoffset:0.5;display:inline"
+ d="m 335.50002,42.500013 -10,0 0,10 L 335.5,52.5 l 0,-10"
+ id="path27534"
+ sodipodi:nodetypes="ccc" />
+ <path
+ sodipodi:type="arc"
+ style="fill:none;stroke:url(#linearGradient27544);stroke-width:1.16669464;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0.5;display:inline"
+ id="path27536"
+ sodipodi:cx="330.5"
+ sodipodi:cy="35.5"
+ sodipodi:rx="3.5"
+ sodipodi:ry="3.5"
+ d="M 334,35.5 A 3.5,3.5 0 0 1 330.5,39 3.5,3.5 0 0 1 327,35.5 3.5,3.5 0 0 1 330.5,32 3.5,3.5 0 0 1 334,35.5 Z"
+ transform="matrix(0.857099,0,0,0.857147,47.22893,17.071296)" />
+ </g>
</g>
- </g>
- <g
- style="display:inline"
- id="g31523"
- transform="translate(19,130)">
<rect
style="opacity:0;fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
id="rect31513"
width="16"
height="16"
- x="343"
- y="27" />
+ x="362"
+ y="157" />
<g
- transform="translate(0.01612278,0)"
+ transform="translate(19.016123,130)"
id="g10864"
style="display:inline">
<path
transform="matrix(1.142871,0,0,1.142855,-27.218817,-5.0713453)"
- d="m 334,35.5 c 0,1.932997 -1.567,3.5 -3.5,3.5 -1.933,0 -3.5,-1.567003 -3.5,-3.5 0,-1.932997 1.567,-3.5 3.5,-3.5 1.933,0 3.5,1.567003 3.5,3.5 z"
+ d="M 334,35.5 A 3.5,3.5 0 0 1 330.5,39 3.5,3.5 0 0 1 327,35.5 3.5,3.5 0 0 1 330.5,32 3.5,3.5 0 0 1 334,35.5 Z"
sodipodi:ry="3.5"
sodipodi:rx="3.5"
sodipodi:cy="35.5"
@@ -40781,12 +43116,12 @@
sodipodi:cy="35.5"
sodipodi:rx="3.5"
sodipodi:ry="3.5"
- d="m 334,35.5 c 0,1.932997 -1.567,3.5 -3.5,3.5 -1.933,0 -3.5,-1.567003 -3.5,-3.5 0,-1.932997 1.567,-3.5 3.5,-3.5 1.933,0 3.5,1.567003 3.5,3.5 z"
+ d="M 334,35.5 A 3.5,3.5 0 0 1 330.5,39 3.5,3.5 0 0 1 327,35.5 3.5,3.5 0 0 1 330.5,32 3.5,3.5 0 0 1 334,35.5 Z"
transform="matrix(0.857099,0,0,0.857147,67.228993,5.071249)" />
</g>
</g>
<g
- id="g31658"
+ id="ICON_SEQ_HISTOGRAM"
transform="translate(63,2)">
<rect
style="opacity:0;fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
@@ -40828,7 +43163,7 @@
</g>
<g
style="display:inline"
- id="g31429"
+ id="ICON_SEQ_CHROMA_SCOPE"
transform="translate(-234,4)">
<rect
y="6"
@@ -40903,7 +43238,7 @@
</g>
<g
transform="translate(-21,-418)"
- id="g31674">
+ id="ICON_SEQ_PREVIEW">
<rect
y="428"
x="47"
@@ -40944,7 +43279,7 @@
</g>
</g>
<g
- id="g11938"
+ id="ICON_IMAGEFILE"
transform="translate(0,2)">
<rect
y="8"
@@ -41011,7 +43346,7 @@
</g>
</g>
<g
- id="g10845"
+ id="ICON_MOD_WAVE"
transform="translate(0,2)">
<rect
style="opacity:0;fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
@@ -41054,7 +43389,7 @@
</g>
</g>
<g
- id="g13136"
+ id="ICON_MOD_SUBSURF"
transform="translate(0,2)">
<rect
y="260"
@@ -41127,7 +43462,7 @@
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
sodipodi:ry="8"
sodipodi:rx="8"
sodipodi:cy="118"
@@ -41145,7 +43480,7 @@
sodipodi:cy="118"
sodipodi:rx="8"
sodipodi:ry="8"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90" />
@@ -41153,100 +43488,7 @@
</g>
</g>
<g
- id="g10823"
- transform="translate(0,2)">
- <rect
- style="opacity:0;fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- id="rect31968"
- width="16"
- height="16"
- x="68"
- y="260" />
- <path
- inkscape:export-ydpi="90"
- inkscape:export-xdpi="90"
- inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
- id="path12863"
- d="m 70.562559,271.5 0.24994,0.25 9,-9 -0.24994,-0.25 -9,0 0,9 z"
- style="fill:url(#linearGradient24189);fill-opacity:1;fill-rule:evenodd;stroke:none;display:inline"
- sodipodi:nodetypes="cccccc"
- inkscape:connector-curvature="0" />
- <path
- sodipodi:nodetypes="ccccccc"
- inkscape:export-ydpi="90"
- inkscape:export-xdpi="90"
- inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
- d="m 70.562559,271.5 -6e-5,-9 9,5e-5 m -4.99994,4.89995 0,-4.8 m 0.89997,3.9 -4.8,0"
- style="fill:none;stroke:#0b1728;stroke-width:0.80000001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:7.40000265;display:inline"
- id="path12865"
- inkscape:connector-curvature="0" />
- <path
- inkscape:export-ydpi="90"
- inkscape:export-xdpi="90"
- inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
- id="path12867"
- d="m 71.562559,265.51369 0,-2.01369 1.99998,0"
- style="opacity:0.7;fill:none;stroke:#ffffff;stroke-width:1.00000119px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
- inkscape:connector-curvature="0" />
- <g
- id="g24198"
- style="opacity:0.4">
- <path
- id="path12861"
- d="m 72.562559,273.5 -0.25006,-0.25 9,-9 0.25006,0.25 0,9 -9,0 z"
- style="fill:url(#linearGradient24209);fill-opacity:1;fill-rule:evenodd;stroke:none;display:inline"
- sodipodi:nodetypes="cccccc"
- inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
- inkscape:export-xdpi="90"
- inkscape:export-ydpi="90"
- inkscape:connector-curvature="0" />
- <path
- inkscape:export-ydpi="90"
- inkscape:export-xdpi="90"
- inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
- style="fill:none;stroke:url(#linearGradient24192);stroke-width:0.99999875;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dashoffset:7.40000265;display:inline"
- d="m 80.499999,265.5 0,7 -7,0"
- id="path27953"
- sodipodi:nodetypes="ccc"
- inkscape:connector-curvature="0" />
- <path
- sodipodi:nodetypes="ccc"
- id="path12869"
- d="m 81.562559,264.5 0,9 -9,-5e-5"
- style="fill:none;stroke:#000000;stroke-width:0.80000001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:7.40000265;display:inline"
- inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
- inkscape:export-xdpi="90"
- inkscape:export-ydpi="90"
- inkscape:connector-curvature="0" />
- </g>
- <path
- style="opacity:0.7;fill:none;stroke:#ffffff;stroke-width:1.00000119px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
- d="m 75.562559,265.51369 0,-2.01369 1.99998,0"
- id="path12871"
- inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
- inkscape:export-xdpi="90"
- inkscape:export-ydpi="90"
- inkscape:connector-curvature="0" />
- <path
- inkscape:export-ydpi="90"
- inkscape:export-xdpi="90"
- inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
- id="path12873"
- d="m 71.562579,269.51369 0,-2.01369 1.99998,0"
- style="opacity:0.7;fill:none;stroke:#ffffff;stroke-width:1.00000119px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
- inkscape:connector-curvature="0" />
- </g>
- <path
- style="opacity:0.2;fill:none;stroke:#000000;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- d="M 71,277 83,265"
- id="path42252"
- sodipodi:nodetypes="cc"
- inkscape:connector-curvature="0" />
- <g
- id="g14009"
- transform="translate(1,-0.01245054)" />
- <g
- id="g17702"
+ id="ICON_FACESEL_HLT"
transform="translate(-1e-5,127)">
<rect
style="opacity:0;fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
@@ -41306,7 +43548,7 @@
</g>
<g
style="display:inline"
- id="g23022"
+ id="ICON_SPACE3"
transform="translate(19,-17)">
<rect
style="opacity:0;fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
@@ -41335,7 +43577,7 @@
</g>
<g
style="display:inline"
- id="g23028"
+ id="ICON_SPACE2"
transform="translate(18.067322,-17)">
<rect
y="237"
@@ -41364,7 +43606,7 @@
</g>
<g
style="display:inline"
- id="g23056"
+ id="ICON_MARKER_HLT"
transform="translate(118,4)">
<rect
y="216"
@@ -41408,7 +43650,7 @@
</g>
<g
style="display:inline"
- id="g23048"
+ id="ICON_PMARKER_ACT"
transform="translate(35,4.96982)">
<rect
style="opacity:0;fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
@@ -41452,7 +43694,7 @@
</g>
<g
style="display:inline"
- id="g23040"
+ id="ICON_PMARKER_SEL"
transform="translate(36,4.96982)">
<rect
y="215.03018"
@@ -41496,7 +43738,7 @@
</g>
<g
style="display:inline"
- id="g23034"
+ id="ICON_PMARKER"
transform="translate(37,5)">
<rect
y="215"
@@ -41528,7 +43770,7 @@
</g>
<g
style="display:inline"
- id="g23114"
+ id="ICON_MARKER"
transform="translate(-81,46)">
<rect
y="174"
@@ -41560,7 +43802,7 @@
</g>
<g
style="display:inline"
- id="g23160"
+ id="ICON_FF"
transform="translate(-316,25)">
<rect
style="opacity:0;fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
@@ -41610,7 +43852,7 @@
</g>
<g
style="display:inline"
- id="g23168"
+ id="ICON_REW"
transform="translate(-315.95126,25)">
<rect
y="195"
@@ -41670,7 +43912,7 @@
</g>
<g
style="display:inline"
- id="g23154"
+ id="ICON_PLAY"
transform="translate(-317,25)">
<rect
y="195"
@@ -41702,7 +43944,7 @@
</g>
<g
style="display:inline"
- id="g23136"
+ id="ICON_PAUSE"
transform="translate(-194,25)">
<rect
style="opacity:0;fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
@@ -41771,7 +44013,7 @@
</g>
<g
style="display:inline"
- id="g23146"
+ id="ICON_REC"
transform="translate(-318,25)">
<rect
style="opacity:0;fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
@@ -41798,7 +44040,7 @@
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
sodipodi:ry="8"
sodipodi:rx="8"
sodipodi:cy="118"
@@ -41824,7 +44066,7 @@
sodipodi:cy="118"
sodipodi:rx="8"
sodipodi:ry="8"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90" />
@@ -41832,7 +44074,7 @@
</g>
</g>
<g
- id="g24423">
+ id="ICON_NEXT_KEYFRAME">
<rect
y="220"
x="131"
@@ -41875,7 +44117,7 @@
</g>
<g
style="display:inline"
- id="g23235"
+ id="ICON_PREV_KEYFRAME"
transform="translate(-74,46)">
<rect
style="opacity:0;fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
@@ -41918,99 +44160,80 @@
</g>
</g>
<g
- id="g23738"
- transform="matrix(0.9375966,0,0,0.937515,141.13219,-26.987026)"
- style="fill:none;stroke:#000000;stroke-width:0.99968439;stroke-opacity:1">
+ id="ICON_ANTIALIASED">
+ <rect
+ y="31"
+ x="131"
+ height="16"
+ width="16"
+ id="rect10527"
+ style="opacity:0;fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
<g
- transform="matrix(0.83365,0,0,0.857522,-5.083283,31.57021)"
- id="g23740"
- style="fill:none;stroke:#000000;stroke-width:0.99968439;stroke-opacity:1">
- <g
- transform="translate(-1.863085e-7,0.53333)"
- id="g23742"
- style="fill:none;stroke:#000000;stroke-width:0.99968439;stroke-opacity:1">
- <g
- transform="translate(0.533324,-1.066663)"
- id="g23744"
- style="fill:none;stroke:#000000;stroke-width:0.99968439;stroke-opacity:1" />
- </g>
- </g>
- </g>
- <rect
- style="opacity:0;fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- id="rect10527"
- width="16"
- height="16"
- x="131"
- y="31" />
- <g
- style="display:inline"
- id="g10530"
- transform="matrix(1.1658027,0,0,1.1657997,-11.289717,-221.05607)"
- inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
- inkscape:export-xdpi="90"
- inkscape:export-ydpi="90">
- <path
- transform="matrix(0.629932,0,0,0.6236653,45.764188,149.53247)"
- sodipodi:type="arc"
- style="opacity:0.1;fill:none;stroke:#ffffff;stroke-width:5.47410154;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
- id="path23603"
- sodipodi:cx="132"
- sodipodi:cy="118"
- sodipodi:rx="8"
- sodipodi:ry="8"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
- inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
- inkscape:export-xdpi="90"
- inkscape:export-ydpi="90" />
- <path
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
- inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
- sodipodi:ry="8"
- sodipodi:rx="8"
- sodipodi:cy="118"
- sodipodi:cx="132"
- id="path10532"
- style="fill:none;stroke:#000000;stroke-width:2.25806689;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
- sodipodi:type="arc"
- transform="matrix(0.629932,0,0,0.6236653,45.764188,149.53247)" />
- <g
- id="g11317">
- <path
- sodipodi:type="arc"
- style="opacity:0.8;fill:url(#linearGradient11333);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.6060524;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- id="path11331"
- sodipodi:cx="132"
- sodipodi:cy="118"
- sodipodi:rx="8"
- sodipodi:ry="8"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
- inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
- inkscape:export-xdpi="90"
- inkscape:export-ydpi="90"
- transform="matrix(-0.5326189,-0.05995148,0.06070777,-0.5287352,192.0574,293.4132)" />
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
+ transform="matrix(1.1658027,0,0,1.1657997,-11.289717,-221.05607)"
+ id="g10530"
+ style="display:inline">
<path
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
sodipodi:ry="8"
sodipodi:rx="8"
sodipodi:cy="118"
sodipodi:cx="132"
- id="path10536"
- style="fill:none;stroke:url(#linearGradient10540);stroke-width:1.78041101;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ id="path23603"
+ style="opacity:0.1;fill:none;stroke:#ffffff;stroke-width:5.47410154;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
sodipodi:type="arc"
- transform="matrix(0.4812861,0,0,0.4822895,65.395173,166.1609)" />
+ transform="matrix(0.629932,0,0,0.6236653,45.764188,149.53247)" />
+ <path
+ transform="matrix(0.629932,0,0,0.6236653,45.764188,149.53247)"
+ sodipodi:type="arc"
+ style="fill:none;stroke:#000000;stroke-width:2.25806689;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ id="path10532"
+ sodipodi:cx="132"
+ sodipodi:cy="118"
+ sodipodi:rx="8"
+ sodipodi:ry="8"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <g
+ id="g11317">
+ <path
+ transform="matrix(-0.5326189,-0.05995148,0.06070777,-0.5287352,192.0574,293.4132)"
+ inkscape:export-ydpi="90"
+ inkscape:export-xdpi="90"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
+ sodipodi:ry="8"
+ sodipodi:rx="8"
+ sodipodi:cy="118"
+ sodipodi:cx="132"
+ id="path11331"
+ style="opacity:0.8;fill:url(#linearGradient11333);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.6060524;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ sodipodi:type="arc" />
+ <path
+ transform="matrix(0.4812861,0,0,0.4822895,65.395173,166.1609)"
+ sodipodi:type="arc"
+ style="fill:none;stroke:url(#linearGradient10540);stroke-width:1.78041101;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ id="path10536"
+ sodipodi:cx="132"
+ sodipodi:cy="118"
+ sodipodi:rx="8"
+ sodipodi:ry="8"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ </g>
</g>
</g>
<g
- id="g16279"
- transform="translate(318,7.00009)" />
- <g
- id="g28089"
+ id="ICON_MOD_DISPLACE"
transform="translate(0,2)">
<rect
y="260"
@@ -42092,66 +44315,7 @@
</g>
</g>
<g
- id="g16397"
- transform="matrix(1.045454,0,0,1.0610941,-16.32706,109.05266)"
- style="opacity:0.45"
- inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
- inkscape:export-xdpi="90"
- inkscape:export-ydpi="90" />
- <g
- id="g16403"
- transform="matrix(1.000037,0,0,1.0187902,152.96764,39.785579)"
- inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\jendrzych's iconset.png"
- inkscape:export-xdpi="90"
- inkscape:export-ydpi="90">
- <g
- inkscape:export-ydpi="90"
- inkscape:export-xdpi="90"
- inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
- transform="matrix(0.9375,0,0,0.9375,192.125,77.25821)"
- id="g16405"
- style="display:inline">
- <g
- id="g16407"
- style="fill:#000000;fill-opacity:1"
- transform="matrix(1,0,0,1.037041,0,-6.074721)" />
- <g
- transform="translate(-84.26666,-72.24656)"
- id="g16409">
- <g
- transform="translate(1.070738,1.59725)"
- id="g16411">
- <g
- id="g16413"
- transform="matrix(0.83365,0,0,0.857522,-5.083283,31.57021)">
- <g
- id="g16415"
- transform="translate(-1.863085e-7,0.53333)">
- <g
- id="g16417"
- transform="translate(0.533324,-1.066663)" />
- </g>
- </g>
- </g>
- </g>
- <g
- id="g16419"
- transform="matrix(0.903797,0,0,0.872724,-4.64464,27.13735)" />
- <g
- id="g16421" />
- </g>
- </g>
- <g
- id="g16425"
- transform="matrix(1.000872,0,0,1.0462972,140.88404,50.499099)"
- inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
- inkscape:export-xdpi="90"
- inkscape:export-ydpi="90" />
- <g
- id="g28330"
- transform="translate(315.99999,18.99998)" />
- <g
- id="g28446"
+ id="ICON_MOD_UVPROJECT"
transform="translate(0,-18.999939)">
<rect
style="opacity:0;fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
@@ -42290,145 +44454,8 @@
</g>
</g>
<g
- id="g12156"
- transform="translate(-130.97687,-108)" />
- <g
- transform="translate(-517,612.99998)"
- id="g12564"
- style="display:inline">
- <rect
- y="-183"
- x="543"
- height="16"
- width="16"
- id="rect12566"
- style="opacity:0;fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
- <g
- id="g12568">
- <rect
- style="fill:#dfa535;fill-opacity:1;fill-rule:nonzero;stroke:#2b1600;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:7.40000265;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- id="rect12570"
- width="2.9998772"
- height="3"
- x="554.50031"
- y="-181.49998"
- ry="1.4999386"
- rx="1.4999386" />
- <path
- sodipodi:nodetypes="cccc"
- id="path12572"
- d="m 546.00017,-179.49999 5,9.5 5,-9.5 -10,0 z"
- style="fill:none;stroke:#2b1600;stroke-width:3.20000005;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
- inkscape:connector-curvature="0" />
- <rect
- rx="1.4999386"
- ry="1.4999386"
- y="-181.49998"
- x="544.50043"
- height="3"
- width="2.9998772"
- id="rect12574"
- style="fill:#dfa535;fill-opacity:1;fill-rule:nonzero;stroke:#2b1600;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:7.40000265;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
- <rect
- style="fill:#dfa535;fill-opacity:1;fill-rule:nonzero;stroke:#2b1600;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:7.40000265;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- id="rect12576"
- width="2.9998772"
- height="3"
- x="549.5"
- y="-171.5"
- ry="1.4999386"
- rx="1.4999386" />
- <path
- style="fill:none;stroke:#ffad55;stroke-width:1.60000002;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- d="m 546.00017,-179.53678 5,9.5 5,-9.5 -10,0 z"
- id="path12578"
- sodipodi:nodetypes="cccc"
- inkscape:connector-curvature="0" />
- <path
- inkscape:export-ydpi="90"
- inkscape:export-xdpi="90"
- inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
- id="path12580"
- d="m 557.00046,-180.99998 c -0.6694,0 -1.3388,1e-5 -2.0082,1e-5 0,0.66939 0,1.33877 0,2.00817 0.6694,0 1.3388,-10e-6 2.0082,-10e-6 0,-0.66939 0,-1.33878 0,-2.00817 z"
- style="fill:#ffca91;fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline"
- inkscape:connector-curvature="0" />
- <path
- style="fill:#ffca91;fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline"
- d="m 552.00029,-170.99999 c -0.6694,0 -1.3388,1e-5 -2.0082,1e-5 0,0.66939 0,1.33877 0,2.00817 0.6694,0 1.3388,-1e-5 2.0082,-1e-5 0,-0.66939 0,-1.33878 0,-2.00817 z"
- id="path12582"
- inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
- inkscape:export-xdpi="90"
- inkscape:export-ydpi="90"
- inkscape:connector-curvature="0" />
- <path
- style="fill:#ffca91;fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline"
- d="m 547.00059,-180.99998 c -0.6694,0 -1.3388,1e-5 -2.0082,1e-5 0,0.66939 0,1.33877 0,2.00817 0.6694,0 1.3388,-10e-6 2.0082,-10e-6 0,-0.66939 0,-1.33878 0,-2.00817 z"
- id="path12584"
- inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
- inkscape:export-xdpi="90"
- inkscape:export-ydpi="90"
- inkscape:connector-curvature="0" />
- <path
- sodipodi:nodetypes="cccc"
- id="path12586"
- d="m 546.00017,-179.53678 5,9.5 5,-9.5 -10,0 z"
- style="fill:none;stroke:url(#linearGradient12602);stroke-width:1.70000005;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- inkscape:connector-curvature="0" />
- <path
- style="opacity:0.8;fill:none;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1;display:inline"
- d="m 555.5,-179.5 0,-1 1,0"
- id="path12588"
- inkscape:connector-curvature="0" />
- <path
- id="path12590"
- d="m 545.5,-179.5 0,-1 1,0"
- style="opacity:0.8;fill:none;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1;display:inline"
- inkscape:connector-curvature="0" />
- <path
- style="opacity:0.8;fill:none;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1;display:inline"
- d="m 550.5,-169.5 0,-1 1,0"
- id="path12592"
- inkscape:connector-curvature="0" />
- <path
- style="opacity:0.2;fill:#964e00;fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline"
- d="m 555,-180.34409 -0.96003,1e-5 0,2.34418 2.21003,-1e-4 0.36569,-1 -1.61569,0 0,-1.34409 z"
- id="path12594"
- inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
- inkscape:export-xdpi="90"
- inkscape:export-ydpi="90"
- sodipodi:nodetypes="ccccccc"
- inkscape:connector-curvature="0" />
- <path
- style="opacity:0.5;fill:#964e00;fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline"
- d="m 552,-172 c -0.65334,0 -1.30669,1e-5 -1.96003,1e-5 0,0.33321 0,0.66641 0,0.99963 0.65334,0 1.30669,0 1.96003,0 0,-0.33322 0,-0.66643 0,-0.99964 z"
- id="path12596"
- inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
- inkscape:export-xdpi="90"
- inkscape:export-ydpi="90"
- inkscape:connector-curvature="0" />
- <path
- sodipodi:nodetypes="ccccc"
- inkscape:export-ydpi="90"
- inkscape:export-xdpi="90"
- inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
- id="path12598"
- d="m 547.03997,-180.34409 0.96003,1e-5 0,2.34418 -0.96003,-1.0001 0,-1.34409 z"
- style="opacity:0.2;fill:#964e00;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.00000072;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- inkscape:connector-curvature="0" />
- <path
- style="opacity:0.5;fill:#964e00;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.00000072;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- d="m 545.65591,-179 1e-5,0.96003 2.34418,0 L 547,-179 l -1.34409,0 z"
- id="path12600"
- inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
- inkscape:export-xdpi="90"
- inkscape:export-ydpi="90"
- sodipodi:nodetypes="ccccc"
- inkscape:connector-curvature="0" />
- </g>
- </g>
- <g
transform="translate(-537,592)"
- id="g12618"
+ id="ICON_OUTLINER_DATA_MESH"
style="display:inline">
<rect
y="-183"
@@ -42509,16 +44536,153 @@
inkscape:connector-curvature="0" />
</g>
</g>
- <rect
- transform="scale(1,-1)"
- style="opacity:0;fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- id="rect12777"
- width="16"
- height="16"
- x="26"
- y="-446" />
- <g
- id="g12053"
+ <g
+ id="ICON_OUTLINER_OB_MESH">
+ <g
+ style="display:inline"
+ id="g12564"
+ transform="translate(-517,612.99998)">
+ <rect
+ style="opacity:0;fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect12566"
+ width="16"
+ height="16"
+ x="543"
+ y="-183" />
+ <g
+ id="g12568">
+ <rect
+ rx="1.4999386"
+ ry="1.4999386"
+ y="-181.49998"
+ x="554.50031"
+ height="3"
+ width="2.9998772"
+ id="rect12570"
+ style="fill:#dfa535;fill-opacity:1;fill-rule:nonzero;stroke:#2b1600;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:7.40000265;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#2b1600;stroke-width:3.20000005;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 546.00017,-179.49999 5,9.5 5,-9.5 -10,0 z"
+ id="path12572"
+ sodipodi:nodetypes="cccc" />
+ <rect
+ style="fill:#dfa535;fill-opacity:1;fill-rule:nonzero;stroke:#2b1600;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:7.40000265;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect12574"
+ width="2.9998772"
+ height="3"
+ x="544.50043"
+ y="-181.49998"
+ ry="1.4999386"
+ rx="1.4999386" />
+ <rect
+ rx="1.4999386"
+ ry="1.4999386"
+ y="-171.5"
+ x="549.5"
+ height="3"
+ width="2.9998772"
+ id="rect12576"
+ style="fill:#dfa535;fill-opacity:1;fill-rule:nonzero;stroke:#2b1600;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:7.40000265;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cccc"
+ id="path12578"
+ d="m 546.00017,-179.53678 5,9.5 5,-9.5 -10,0 z"
+ style="fill:none;stroke:#ffad55;stroke-width:1.60000002;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:#ffca91;fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline"
+ d="m 557.00046,-180.99998 c -0.6694,0 -1.3388,1e-5 -2.0082,1e-5 0,0.66939 0,1.33877 0,2.00817 0.6694,0 1.3388,-10e-6 2.0082,-10e-6 0,-0.66939 0,-1.33878 0,-2.00817 z"
+ id="path12580"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <path
+ inkscape:connector-curvature="0"
+ inkscape:export-ydpi="90"
+ inkscape:export-xdpi="90"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
+ id="path12582"
+ d="m 552.00029,-170.99999 c -0.6694,0 -1.3388,1e-5 -2.0082,1e-5 0,0.66939 0,1.33877 0,2.00817 0.6694,0 1.3388,-1e-5 2.0082,-1e-5 0,-0.66939 0,-1.33878 0,-2.00817 z"
+ style="fill:#ffca91;fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline" />
+ <path
+ inkscape:connector-curvature="0"
+ inkscape:export-ydpi="90"
+ inkscape:export-xdpi="90"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
+ id="path12584"
+ d="m 547.00059,-180.99998 c -0.6694,0 -1.3388,1e-5 -2.0082,1e-5 0,0.66939 0,1.33877 0,2.00817 0.6694,0 1.3388,-10e-6 2.0082,-10e-6 0,-0.66939 0,-1.33878 0,-2.00817 z"
+ style="fill:#ffca91;fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline" />
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:url(#linearGradient12602);stroke-width:1.70000005;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 546.00017,-179.53678 5,9.5 5,-9.5 -10,0 z"
+ id="path12586"
+ sodipodi:nodetypes="cccc" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path12588"
+ d="m 555.5,-179.5 0,-1 1,0"
+ style="opacity:0.8;fill:none;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1;display:inline" />
+ <path
+ inkscape:connector-curvature="0"
+ style="opacity:0.8;fill:none;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1;display:inline"
+ d="m 545.5,-179.5 0,-1 1,0"
+ id="path12590" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path12592"
+ d="m 550.5,-169.5 0,-1 1,0"
+ style="opacity:0.8;fill:none;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1;display:inline" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccccc"
+ inkscape:export-ydpi="90"
+ inkscape:export-xdpi="90"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
+ id="path12594"
+ d="m 555,-180.34409 -0.96003,1e-5 0,2.34418 2.21003,-1e-4 0.36569,-1 -1.61569,0 0,-1.34409 z"
+ style="opacity:0.2;fill:#964e00;fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline" />
+ <path
+ inkscape:connector-curvature="0"
+ inkscape:export-ydpi="90"
+ inkscape:export-xdpi="90"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
+ id="path12596"
+ d="m 552,-172 c -0.65334,0 -1.30669,1e-5 -1.96003,1e-5 0,0.33321 0,0.66641 0,0.99963 0.65334,0 1.30669,0 1.96003,0 0,-0.33322 0,-0.66643 0,-0.99964 z"
+ style="opacity:0.5;fill:#964e00;fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline" />
+ <path
+ inkscape:connector-curvature="0"
+ style="opacity:0.2;fill:#964e00;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.00000072;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 547.03997,-180.34409 0.96003,1e-5 0,2.34418 -0.96003,-1.0001 0,-1.34409 z"
+ id="path12598"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"
+ sodipodi:nodetypes="ccccc" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccc"
+ inkscape:export-ydpi="90"
+ inkscape:export-xdpi="90"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
+ id="path12600"
+ d="m 545.65591,-179 1e-5,0.96003 2.34418,0 L 547,-179 l -1.34409,0 z"
+ style="opacity:0.5;fill:#964e00;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.00000072;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ </g>
+ </g>
+ <rect
+ y="-446"
+ x="26"
+ height="16"
+ width="16"
+ id="rect12777"
+ style="opacity:0;fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ transform="scale(1,-1)" />
+ </g>
+ <g
+ id="ICON_OUTLINER_OB_SURFACE"
transform="translate(-21,128)">
<rect
y="302"
@@ -42587,7 +44751,7 @@
</g>
</g>
<g
- id="g12219"
+ id="ICON_OUTLINER_DATA_SURFACE"
transform="translate(-20.999998,128)">
<rect
transform="scale(-1,1)"
@@ -42736,23 +44900,7 @@
</g>
</g>
<g
- id="g12249"
- style="opacity:0.65;display:inline"
- transform="translate(-98,462.06404)" />
- <g
- style="display:inline"
- transform="translate(-53.00012,422.06403)"
- id="g12255" />
- <g
- transform="translate(-98,483.06404)"
- style="opacity:0.65;display:inline"
- id="g12325" />
- <g
- id="g12327"
- transform="translate(-53.00012,443.06403)"
- style="display:inline" />
- <g
- id="g24293"
+ id="ICON_MOD_ARRAY"
transform="translate(0,2)">
<rect
y="260"
@@ -42857,66 +45005,66 @@
inkscape:connector-curvature="0" />
</g>
</g>
- <rect
- ry="0"
- rx="0.80014729"
- y="73"
- x="257"
- height="16"
- width="16"
- id="rect11420"
- style="opacity:0;fill:#ffaaaa;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.00000012;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
- <g
- id="g16042"
- transform="translate(-147,2)">
- <path
- style="fill:url(#linearGradient16039);fill-rule:evenodd;stroke:#000000;stroke-width:0.80000001;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
- d="m 412,73.5 c -4.5,0 -7.25,0.75 -5.75,2.5 l 4.25,4.5 0,6.25 3,-2 0,-4.25 c 1.48333,-1.72541 2.75638,-2.81017 4.25,-4.5 1.5,-1.75 -1.25,-2.5 -5.75,-2.5 z"
- id="path11422"
- sodipodi:nodetypes="cccccccc"
- inkscape:connector-curvature="0" />
- <path
- style="fill:url(#radialGradient16034);fill-opacity:1;stroke:url(#linearGradient16036);stroke-width:1;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
- d="m 418.24999,74.499997 c -0.005,1.49998 -1.49999,2.000009 -6.25,2.000009 -4.74999,0 -6.25738,-0.500029 -6.24999,-2.000009 0.005,-1.000014 1.5,-1.999986 6.24999,-1.999986 4.75001,0 6.24506,0.999972 6.25,1.999986 z"
- id="path11424"
- sodipodi:nodetypes="csssc"
- inkscape:connector-curvature="0" />
- <path
- sodipodi:nodetypes="cccccc"
- id="path11426"
- d="m 410.89062,80.47656 0,5.75 2.20704,-1.585938 0,-4.164062 -0.40829,0 -1.79875,0 z"
- style="fill:url(#linearGradient16031);fill-rule:evenodd;stroke:none"
- inkscape:connector-curvature="0" />
- <path
- sodipodi:nodetypes="cc"
- id="path11428"
- d="m 412.5,85.25 0,-4.25"
- style="opacity:0.15;fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
- inkscape:connector-curvature="0" />
- <path
- style="fill:none;stroke:#cccccc;stroke-width:0.99999988;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
- d="m 406.5,75 c 0,-1.75 2.5,-1.5 5.5,-1.49999 3,1e-5 5.5,-0.25001 5.5,1.25001"
- id="path12224"
- sodipodi:nodetypes="csc"
- inkscape:connector-curvature="0" />
- <path
- sodipodi:nodetypes="csssc"
- id="path12211"
- d="m 417.49999,74.50002 c 10e-6,1.74998 -1.4838,1.99999 -5.50001,1.99999 -4.01617,0 -5.49583,-0.50001 -5.49999,-1.99999 -0.004,-1.50002 1.48382,-2.00001 5.49999,-2.00001 4.01621,0 5.49583,0.49999 5.50001,2.00001 z"
- style="fill:none;stroke:url(#linearGradient16027);stroke-width:1;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
- inkscape:connector-curvature="0" />
- <path
- style="opacity:0.15;fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
- d="m 411.27412,80.5 2.13816,0"
- id="path12238"
- sodipodi:nodetypes="cc"
- inkscape:connector-curvature="0" />
- </g>
<g
- id="g11534"
- transform="translate(21,-1)" />
+ id="ICON_FILTER">
+ <rect
+ style="opacity:0;fill:#ffaaaa;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.00000012;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect11420"
+ width="16"
+ height="16"
+ x="257"
+ y="73"
+ rx="0.80014729"
+ ry="0" />
+ <g
+ transform="translate(-147,2)"
+ id="g16042">
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cccccccc"
+ id="path11422"
+ d="m 412,73.5 c -4.5,0 -7.25,0.75 -5.75,2.5 l 4.25,4.5 0,6.25 3,-2 0,-4.25 c 1.48333,-1.72541 2.75638,-2.81017 4.25,-4.5 1.5,-1.75 -1.25,-2.5 -5.75,-2.5 z"
+ style="fill:url(#linearGradient16039);fill-rule:evenodd;stroke:#000000;stroke-width:0.80000001;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="csssc"
+ id="path11424"
+ d="m 418.24999,74.499997 c -0.005,1.49998 -1.49999,2.000009 -6.25,2.000009 -4.74999,0 -6.25738,-0.500029 -6.24999,-2.000009 0.005,-1.000014 1.5,-1.999986 6.24999,-1.999986 4.75001,0 6.24506,0.999972 6.25,1.999986 z"
+ style="fill:url(#radialGradient16034);fill-opacity:1;stroke:url(#linearGradient16036);stroke-width:1;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none" />
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:url(#linearGradient16031);fill-rule:evenodd;stroke:none"
+ d="m 410.89062,80.47656 0,5.75 2.20704,-1.585938 0,-4.164062 -0.40829,0 -1.79875,0 z"
+ id="path11426"
+ sodipodi:nodetypes="cccccc" />
+ <path
+ inkscape:connector-curvature="0"
+ style="opacity:0.15;fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ d="m 412.5,85.25 0,-4.25"
+ id="path11428"
+ sodipodi:nodetypes="cc" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="csc"
+ id="path12224"
+ d="m 406.5,75 c 0,-1.75 2.5,-1.5 5.5,-1.49999 3,1e-5 5.5,-0.25001 5.5,1.25001"
+ style="fill:none;stroke:#cccccc;stroke-width:0.99999988;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none" />
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:url(#linearGradient16027);stroke-width:1;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 417.49999,74.50002 c 10e-6,1.74998 -1.4838,1.99999 -5.50001,1.99999 -4.01617,0 -5.49583,-0.50001 -5.49999,-1.99999 -0.004,-1.50002 1.48382,-2.00001 5.49999,-2.00001 4.01621,0 5.49583,0.49999 5.50001,2.00001 z"
+ id="path12211"
+ sodipodi:nodetypes="csssc" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cc"
+ id="path12238"
+ d="m 411.27412,80.5 2.13816,0"
+ style="opacity:0.15;fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" />
+ </g>
+ </g>
<g
- id="g17375"
+ id="ICON_OUTLINER_OB_FONT"
transform="translate(10.000031,192.5)"
inkscape:export-filename="C:\Documents and Settings\Pracowniaa\Pulpit\Browser icons ver 1\font_file SMALL.png"
inkscape:export-xdpi="90"
@@ -42962,23 +45110,7 @@
inkscape:connector-curvature="0" />
</g>
<g
- id="g31245"
- transform="matrix(0.425032,0.424791,0.425032,-0.424791,-342.55466,249.47119)"
- style="display:inline" />
- <g
- transform="translate(-157,15.000007)"
- style="opacity:0.5"
- id="g13244" />
- <g
- id="g13375"
- style="opacity:0.3"
- transform="translate(-177.01509,15.000007)" />
- <g
- id="g13383"
- style="opacity:0.5"
- transform="translate(-143,15.000007)" />
- <g
- id="g14144"
+ id="ICON_SCULPTMODE_HLT"
transform="translate(289,331.00001)">
<rect
y="183"
@@ -43041,22 +45173,7 @@
</g>
</g>
<g
- transform="matrix(-1.0226846,0,0,1.0218469,-86.775576,130.3547)"
- id="g17210">
- <g
- id="g17212"
- transform="matrix(0.83365,0,0,0.857522,-5.083283,31.57021)">
- <g
- id="g17214"
- transform="translate(-1.863085e-7,0.53333)">
- <g
- id="g17216"
- transform="translate(0.533324,-1.066663)" />
- </g>
- </g>
- </g>
- <g
- id="g13705"
+ id="ICON_MATCUBE"
transform="translate(0,2)">
<rect
style="opacity:0;fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
@@ -43110,7 +45227,7 @@
</g>
</g>
<g
- id="g17610"
+ id="ICON_SETTINGS"
transform="translate(-20.999893,190.97867)"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90">
@@ -43250,7 +45367,7 @@
</g>
</g>
<g
- id="g13494"
+ id="ICON_CHECKBOX_DEHLT"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90"
transform="translate(0,128.00001)">
@@ -43293,7 +45410,7 @@
transform="scale(-1,-1)" />
</g>
<g
- id="g28870"
+ id="ICON_CHECKBOX_HLT"
inkscape:export-filename="C:\Documents and Settings\Pracownia\Moje dokumenty\Moje obrazy\BLENDER ICONS redesign\RELEASES\g13494.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90"
@@ -43346,62 +45463,65 @@
inkscape:connector-curvature="0" />
</g>
<g
- transform="translate(135,508.00993)"
- id="g13515"
- style="display:inline">
- <rect
- style="opacity:0;fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- id="rect13517"
- width="16"
- height="16"
- x="143"
- y="111" />
+ id="ICON_RADIOBUT_ON">
<g
- id="g13519">
- <path
- sodipodi:type="arc"
- style="fill:#e6e6e6;fill-opacity:0.25490196;fill-rule:nonzero;stroke:none;display:inline"
- id="path13521"
- sodipodi:cx="330.5"
- sodipodi:cy="35.5"
- sodipodi:rx="2.7944512"
- sodipodi:ry="2.7944512"
- d="m 333.29445,35.5 c 0,1.543333 -1.25112,2.794451 -2.79445,2.794451 -1.54333,0 -2.79445,-1.251118 -2.79445,-2.794451 0,-1.543333 1.25112,-2.794451 2.79445,-2.794451 1.54333,0 2.79445,1.251118 2.79445,2.794451 z"
- transform="matrix(1.4256767,0,0,1.4314068,-320.1963,68.175135)" />
- <path
- sodipodi:type="arc"
- style="opacity:0.4;fill:none;stroke:url(#linearGradient13527);stroke-width:0.77606368;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0.5;display:inline"
- id="path13523"
- sodipodi:cx="330.5"
- sodipodi:cy="35.5"
- sodipodi:rx="3.5"
- sodipodi:ry="3.5"
- d="m 334,35.5 c 0,1.932997 -1.567,3.5 -3.5,3.5 -1.933,0 -3.5,-1.567003 -3.5,-3.5 0,-1.932997 1.567,-3.5 3.5,-3.5 1.933,0 3.5,1.567003 3.5,3.5 z"
- transform="matrix(1.2885487,0,0,1.2885617,-274.87525,73.246084)" />
- <path
- transform="matrix(-1.288521,0,0,-1.2885339,576.8463,164.73299)"
- d="m 334,35.5 c 0,1.932997 -1.567,3.5 -3.5,3.5 -1.933,0 -3.5,-1.567003 -3.5,-3.5 0,-1.932997 1.567,-3.5 3.5,-3.5 1.933,0 3.5,1.567003 3.5,3.5 z"
- sodipodi:ry="3.5"
- sodipodi:rx="3.5"
- sodipodi:cy="35.5"
- sodipodi:cx="330.5"
- id="path13525"
- style="opacity:0.6;fill:none;stroke:url(#linearGradient13529);stroke-width:0.77608043;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0.5;display:inline"
- sodipodi:type="arc" />
+ style="display:inline"
+ id="g13515"
+ transform="translate(135,508.00993)">
+ <rect
+ y="111"
+ x="143"
+ height="16"
+ width="16"
+ id="rect13517"
+ style="opacity:0;fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <g
+ id="g13519">
+ <path
+ transform="matrix(1.4256767,0,0,1.4314068,-320.1963,68.175135)"
+ d="M 333.29445,35.5 A 2.7944512,2.7944512 0 0 1 330.5,38.294451 2.7944512,2.7944512 0 0 1 327.70555,35.5 2.7944512,2.7944512 0 0 1 330.5,32.705549 2.7944512,2.7944512 0 0 1 333.29445,35.5 Z"
+ sodipodi:ry="2.7944512"
+ sodipodi:rx="2.7944512"
+ sodipodi:cy="35.5"
+ sodipodi:cx="330.5"
+ id="path13521"
+ style="fill:#e6e6e6;fill-opacity:0.25490196;fill-rule:nonzero;stroke:none;display:inline"
+ sodipodi:type="arc" />
+ <path
+ transform="matrix(1.2885487,0,0,1.2885617,-274.87525,73.246084)"
+ d="M 334,35.5 A 3.5,3.5 0 0 1 330.5,39 3.5,3.5 0 0 1 327,35.5 3.5,3.5 0 0 1 330.5,32 3.5,3.5 0 0 1 334,35.5 Z"
+ sodipodi:ry="3.5"
+ sodipodi:rx="3.5"
+ sodipodi:cy="35.5"
+ sodipodi:cx="330.5"
+ id="path13523"
+ style="opacity:0.4;fill:none;stroke:url(#linearGradient13527);stroke-width:0.77606368;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0.5;display:inline"
+ sodipodi:type="arc" />
+ <path
+ sodipodi:type="arc"
+ style="opacity:0.6;fill:none;stroke:url(#linearGradient13529);stroke-width:0.77608043;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0.5;display:inline"
+ id="path13525"
+ sodipodi:cx="330.5"
+ sodipodi:cy="35.5"
+ sodipodi:rx="3.5"
+ sodipodi:ry="3.5"
+ d="M 334,35.5 A 3.5,3.5 0 0 1 330.5,39 3.5,3.5 0 0 1 327,35.5 3.5,3.5 0 0 1 330.5,32 3.5,3.5 0 0 1 334,35.5 Z"
+ transform="matrix(-1.288521,0,0,-1.2885339,576.8463,164.73299)" />
+ </g>
</g>
+ <path
+ transform="matrix(0.8543143,0,0,0.8543231,3.66123,596.67148)"
+ d="m 334,35.5 a 3.5,3.5 0 1 1 -7,0 3.5,3.5 0 1 1 7,0 z"
+ sodipodi:ry="3.5"
+ sodipodi:rx="3.5"
+ sodipodi:cy="35.5"
+ sodipodi:cx="330.5"
+ id="path15120"
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline"
+ sodipodi:type="arc" />
</g>
- <path
- sodipodi:type="arc"
- style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline"
- id="path15120"
- sodipodi:cx="330.5"
- sodipodi:cy="35.5"
- sodipodi:rx="3.5"
- sodipodi:ry="3.5"
- d="m 334,35.5 a 3.5,3.5 0 1 1 -7,0 3.5,3.5 0 1 1 7,0 z"
- transform="matrix(0.8543143,0,0,0.8543231,3.66123,596.67148)" />
- <g
- id="g18811"
+ <g
+ id="ICON_MOD_EDGESPLIT"
transform="translate(0,2)">
<rect
style="opacity:0;fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
@@ -43473,7 +45593,7 @@
</g>
</g>
<g
- id="g14548"
+ id="ICON_HOOK"
transform="translate(0,23)">
<rect
y="239"
@@ -43492,7 +45612,7 @@
inkscape:connector-curvature="0" />
<path
transform="matrix(0.8675713,0,0,-1.199958,80.598976,391.9948)"
- d="m 93.25,125 c 0,0.69036 -0.783502,1.25 -1.75,1.25 -0.966498,0 -1.75,-0.55964 -1.75,-1.25 0,-0.69036 0.783502,-1.25 1.75,-1.25 0.966498,0 1.75,0.55964 1.75,1.25 z"
+ d="M 93.25,125 A 1.75,1.25 0 0 1 91.5,126.25 1.75,1.25 0 0 1 89.75,125 1.75,1.25 0 0 1 91.5,123.75 1.75,1.25 0 0 1 93.25,125 Z"
sodipodi:ry="1.25"
sodipodi:rx="1.75"
sodipodi:cy="125"
@@ -43514,11 +45634,11 @@
sodipodi:cy="125"
sodipodi:rx="1.75"
sodipodi:ry="1.25"
- d="m 93.25,125 c 0,0.69036 -0.783502,1.25 -1.75,1.25 -0.966498,0 -1.75,-0.55964 -1.75,-1.25 0,-0.69036 0.783502,-1.25 1.75,-1.25 0.966498,0 1.75,0.55964 1.75,1.25 z"
+ d="M 93.25,125 A 1.75,1.25 0 0 1 91.5,126.25 1.75,1.25 0 0 1 89.75,125 1.75,1.25 0 0 1 91.5,123.75 1.75,1.25 0 0 1 93.25,125 Z"
transform="matrix(0.8540253,0,0,-1.199954,81.814709,391.9942)" />
<path
transform="matrix(0.8540253,0,0,-1.199954,81.814709,391.9942)"
- d="m 93.25,125 c 0,0.69036 -0.783502,1.25 -1.75,1.25 -0.966498,0 -1.75,-0.55964 -1.75,-1.25 0,-0.69036 0.783502,-1.25 1.75,-1.25 0.966498,0 1.75,0.55964 1.75,1.25 z"
+ d="M 93.25,125 A 1.75,1.25 0 0 1 91.5,126.25 1.75,1.25 0 0 1 89.75,125 1.75,1.25 0 0 1 91.5,123.75 1.75,1.25 0 0 1 93.25,125 Z"
sodipodi:ry="1.25"
sodipodi:rx="1.75"
sodipodi:cy="125"
@@ -43543,7 +45663,7 @@
</g>
<g
transform="translate(349,127.99988)"
- id="g26256">
+ id="ICON_BLENDER">
<rect
style="opacity:0;fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
id="rect26258"
@@ -43563,7 +45683,7 @@
inkscape:connector-curvature="0" />
<path
transform="matrix(3.625,0,0,3.1690202,-67.8125,318.31703)"
- d="m 14.5,57.5 c 0,0.552285 -0.447715,1 -1,1 -0.552285,0 -1,-0.447715 -1,-1 0,-0.552285 0.447715,-1 1,-1 0.552285,0 1,0.447715 1,1 z"
+ d="m 14.5,57.5 a 1,1.0000004 0 0 1 -1,1 1,1.0000004 0 0 1 -1,-1 1,1.0000004 0 0 1 1,-1 1,1.0000004 0 0 1 1,1 z"
sodipodi:ry="1.0000004"
sodipodi:rx="1"
sodipodi:cy="57.5"
@@ -43580,7 +45700,7 @@
</g>
<path
transform="matrix(3.5999897,0,0,3.1249932,-67.499871,320.6879)"
- d="m 14.5,57.5 c 0,0.552285 -0.447715,1 -1,1 -0.552285,0 -1,-0.447715 -1,-1 0,-0.552285 0.447715,-1 1,-1 0.552285,0 1,0.447715 1,1 z"
+ d="m 14.5,57.5 a 1,1 0 0 1 -1,1 1,1 0 0 1 -1,-1 1,1 0 0 1 1,-1 1,1 0 0 1 1,1 z"
sodipodi:ry="1"
sodipodi:rx="1"
sodipodi:cy="57.5"
@@ -43602,11 +45722,11 @@
sodipodi:cy="57.5"
sodipodi:rx="1"
sodipodi:ry="1"
- d="m 14.5,57.5 c 0,0.552285 -0.447715,1 -1,1 -0.552285,0 -1,-0.447715 -1,-1 0,-0.552285 0.447715,-1 1,-1 0.552285,0 1,0.447715 1,1 z"
+ d="m 14.5,57.5 a 1,1 0 0 1 -1,1 1,1 0 0 1 -1,-1 1,1 0 0 1 1,-1 1,1 0 0 1 1,1 z"
transform="matrix(3.25,0,0,3.25,-62.875,313.125)" />
<path
transform="matrix(2,0,0,2,-46,385)"
- d="m 14.5,57.5 c 0,0.552285 -0.447715,1 -1,1 -0.552285,0 -1,-0.447715 -1,-1 0,-0.552285 0.447715,-1 1,-1 0.552285,0 1,0.447715 1,1 z"
+ d="m 14.5,57.5 a 1,1 0 0 1 -1,1 1,1 0 0 1 -1,-1 1,1 0 0 1 1,-1 1,1 0 0 1 1,1 z"
sodipodi:ry="1"
sodipodi:rx="1"
sodipodi:cy="57.5"
@@ -43622,7 +45742,7 @@
sodipodi:cy="57.5"
sodipodi:rx="1"
sodipodi:ry="1"
- d="m 14.5,57.5 c 0,0.552285 -0.447715,1 -1,1 -0.552285,0 -1,-0.447715 -1,-1 0,-0.552285 0.447715,-1 1,-1 0.552285,0 1,0.447715 1,1 z"
+ d="m 14.5,57.5 a 1,1 0 0 1 -1,1 1,1 0 0 1 -1,-1 1,1 0 0 1 1,-1 1,1 0 0 1 1,1 z"
transform="matrix(4.7519907,0,0,4.1435313,-83.051884,262.12196)" />
<path
sodipodi:nodetypes="cccccc"
@@ -43633,7 +45753,7 @@
</g>
</g>
<g
- id="g15201"
+ id="ICON_TEXTURE_DATA"
transform="translate(0,128.00001)">
<rect
style="opacity:0;fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
@@ -43676,10 +45796,7 @@
</g>
</g>
<g
- transform="translate(-174.00091,22.99815)"
- id="g15532" />
- <g
- id="g15356"
+ id="ICON_FCURVE"
transform="translate(-21,128.00001)">
<rect
y="344"
@@ -43726,7 +45843,7 @@
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Pracowniaa\Pulpit\Browser icons ver 1\font_file SMALL.png"
transform="translate(-73.999969,234.50001)"
- id="g15369">
+ id="ICON_FONT_DATA">
<rect
y="237.5"
x="162.99997"
@@ -43767,7 +45884,7 @@
inkscape:connector-curvature="0" />
</g>
<g
- id="g14355"
+ id="ICON_ANIM"
transform="translate(0,128.00001)">
<rect
y="428"
@@ -43798,17 +45915,8 @@
</g>
</g>
<g
- transform="translate(-111.96756,-108)"
- id="g15923">
- <g
- id="g15925" />
- </g>
- <g
- transform="translate(189.19394,55.494451)"
- id="g15616" />
- <g
style="display:inline"
- id="g16518"
+ id="ICON_SCENE"
transform="translate(0,64.000007)">
<rect
style="opacity:0;fill:#b3b3b3;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
@@ -43862,7 +45970,7 @@
sodipodi:cy="502"
sodipodi:rx="2.5312502"
sodipodi:ry="2.5"
- d="m 80.53125,502 c 0,1.38071 -1.133279,2.5 -2.53125,2.5 -1.397971,0 -2.53125,-1.11929 -2.53125,-2.5 0,-1.38071 1.133279,-2.5 2.53125,-2.5 1.397971,0 2.53125,1.11929 2.53125,2.5 z"
+ d="M 80.53125,502 A 2.5312502,2.5 0 0 1 78,504.5 2.5312502,2.5 0 0 1 75.46875,502 2.5312502,2.5 0 0 1 78,499.5 2.5312502,2.5 0 0 1 80.53125,502 Z"
transform="matrix(1.3955004,0,0,1.2452423,11.18333,-121.72474)" />
<rect
rx="0.5078125"
@@ -43875,7 +45983,7 @@
style="opacity:0.25;fill:none;stroke:#ffffff;stroke-width:0.99999988;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
<path
transform="matrix(1.5770887,0,0,1.5999841,-3.50675,-301.69208)"
- d="m 80.53125,502 c 0,1.38071 -1.133279,2.5 -2.53125,2.5 -1.397971,0 -2.53125,-1.11929 -2.53125,-2.5 0,-1.38071 1.133279,-2.5 2.53125,-2.5 1.397971,0 2.53125,1.11929 2.53125,2.5 z"
+ d="M 80.53125,502 A 2.5312502,2.5 0 0 1 78,504.5 2.5312502,2.5 0 0 1 75.46875,502 2.5312502,2.5 0 0 1 78,499.5 2.5312502,2.5 0 0 1 80.53125,502 Z"
sodipodi:ry="2.5"
sodipodi:rx="2.5312502"
sodipodi:cy="502"
@@ -43891,11 +45999,11 @@
sodipodi:cy="502"
sodipodi:rx="2.5312502"
sodipodi:ry="2.5"
- d="m 80.53125,502 c 0,1.38071 -1.133279,2.5 -2.53125,2.5 -1.397971,0 -2.53125,-1.11929 -2.53125,-2.5 0,-1.38071 1.133279,-2.5 2.53125,-2.5 1.397971,0 2.53125,1.11929 2.53125,2.5 z"
+ d="M 80.53125,502 A 2.5312502,2.5 0 0 1 78,504.5 2.5312502,2.5 0 0 1 75.46875,502 2.5312502,2.5 0 0 1 78,499.5 2.5312502,2.5 0 0 1 80.53125,502 Z"
transform="matrix(1.1794014,0,0,0.8999954,27.50686,48.952303)" />
<path
transform="matrix(1.1827463,0,0,1.2,27.245789,-99.900024)"
- d="m 80.53125,502 c 0,1.38071 -1.133279,2.5 -2.53125,2.5 -1.397971,0 -2.53125,-1.11929 -2.53125,-2.5 0,-1.38071 1.133279,-2.5 2.53125,-2.5 1.397971,0 2.53125,1.11929 2.53125,2.5 z"
+ d="M 80.53125,502 A 2.5312502,2.5 0 0 1 78,504.5 2.5312502,2.5 0 0 1 75.46875,502 2.5312502,2.5 0 0 1 78,499.5 2.5312502,2.5 0 0 1 80.53125,502 Z"
sodipodi:ry="2.5"
sodipodi:rx="2.5312502"
sodipodi:cy="502"
@@ -43911,7 +46019,7 @@
sodipodi:cy="502"
sodipodi:rx="2.5312502"
sodipodi:ry="2.5"
- d="m 80.53125,502 c 0,1.38071 -1.133279,2.5 -2.53125,2.5 -1.397971,0 -2.53125,-1.11929 -2.53125,-2.5 0,-1.38071 1.133279,-2.5 2.53125,-2.5 1.397971,0 2.53125,1.11929 2.53125,2.5 z"
+ d="M 80.53125,502 A 2.5312502,2.5 0 0 1 78,504.5 2.5312502,2.5 0 0 1 75.46875,502 2.5312502,2.5 0 0 1 78,499.5 2.5312502,2.5 0 0 1 80.53125,502 Z"
transform="matrix(0.790122,0,0,0.787736,57.870479,107.05649)" />
<g
id="g16548"
@@ -43924,7 +46032,7 @@
sodipodi:cy="502"
sodipodi:rx="2.5312502"
sodipodi:ry="2.5"
- d="m 80.53125,502 c 0,1.38071 -1.133279,2.5 -2.53125,2.5 -1.397971,0 -2.53125,-1.11929 -2.53125,-2.5 0,-1.38071 1.133279,-2.5 2.53125,-2.5 1.397971,0 2.53125,1.11929 2.53125,2.5 z"
+ d="M 80.53125,502 A 2.5312502,2.5 0 0 1 78,504.5 2.5312502,2.5 0 0 1 75.46875,502 2.5312502,2.5 0 0 1 78,499.5 2.5312502,2.5 0 0 1 80.53125,502 Z"
transform="matrix(0.7901234,0,0,0.2000006,9.8760061,395.5997)" />
<path
sodipodi:nodetypes="csccc"
@@ -43969,11 +46077,11 @@
sodipodi:cy="502"
sodipodi:rx="2.5312502"
sodipodi:ry="2.5"
- d="m 80.53125,502 c 0,1.38071 -1.133279,2.5 -2.53125,2.5 -1.397971,0 -2.53125,-1.11929 -2.53125,-2.5 0,-1.38071 1.133279,-2.5 2.53125,-2.5 1.397971,0 2.53125,1.11929 2.53125,2.5 z"
+ d="M 80.53125,502 A 2.5312502,2.5 0 0 1 78,504.5 2.5312502,2.5 0 0 1 75.46875,502 2.5312502,2.5 0 0 1 78,499.5 2.5312502,2.5 0 0 1 80.53125,502 Z"
transform="matrix(1.1827463,0,0,1.2,27.245789,-99.900024)" />
<path
transform="matrix(0.8888868,0,0,0.8862026,50.166822,57.626266)"
- d="m 80.53125,502 c 0,1.38071 -1.133279,2.5 -2.53125,2.5 -1.397971,0 -2.53125,-1.11929 -2.53125,-2.5 0,-1.38071 1.133279,-2.5 2.53125,-2.5 1.397971,0 2.53125,1.11929 2.53125,2.5 z"
+ d="M 80.53125,502 A 2.5312502,2.5 0 0 1 78,504.5 2.5312502,2.5 0 0 1 75.46875,502 2.5312502,2.5 0 0 1 78,499.5 2.5312502,2.5 0 0 1 80.53125,502 Z"
sodipodi:ry="2.5"
sodipodi:rx="2.5312502"
sodipodi:cy="502"
@@ -43989,7 +46097,7 @@
sodipodi:cy="502"
sodipodi:rx="2.5312502"
sodipodi:ry="2.5"
- d="m 80.53125,502 c 0,1.38071 -1.133279,2.5 -2.53125,2.5 -1.397971,0 -2.53125,-1.11929 -2.53125,-2.5 0,-1.38071 1.133279,-2.5 2.53125,-2.5 1.397971,0 2.53125,1.11929 2.53125,2.5 z"
+ d="M 80.53125,502 A 2.5312502,2.5 0 0 1 78,504.5 2.5312502,2.5 0 0 1 75.46875,502 2.5312502,2.5 0 0 1 78,499.5 2.5312502,2.5 0 0 1 80.53125,502 Z"
transform="matrix(0.1975308,0,0,0.1999991,103.0926,401.10045)" />
<path
sodipodi:type="arc"
@@ -43999,13 +46107,13 @@
sodipodi:cy="502"
sodipodi:rx="2.5312502"
sodipodi:ry="2.5"
- d="m 80.53125,502 c 0,1.38071 -1.133279,2.5 -2.53125,2.5 -1.397971,0 -2.53125,-1.11929 -2.53125,-2.5 0,-1.38071 1.133279,-2.5 2.53125,-2.5 1.397971,0 2.53125,1.11929 2.53125,2.5 z"
+ d="M 80.53125,502 A 2.5312502,2.5 0 0 1 78,504.5 2.5312502,2.5 0 0 1 75.46875,502 2.5312502,2.5 0 0 1 78,499.5 2.5312502,2.5 0 0 1 80.53125,502 Z"
transform="matrix(-0.8867575,0.06148883,-0.06130315,-0.8840797,219.44126,941.51187)" />
</g>
</g>
<g
style="display:inline"
- id="g21847"
+ id="ICON_RESTRICT_RENDER_OFF"
transform="translate(24,422.99999)"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90">
@@ -44073,7 +46181,7 @@
sodipodi:cy="502"
sodipodi:rx="2.5312502"
sodipodi:ry="2.5"
- d="m 80.53125,502 c 0,1.38071 -1.133279,2.5 -2.53125,2.5 -1.397971,0 -2.53125,-1.11929 -2.53125,-2.5 0,-1.38071 1.133279,-2.5 2.53125,-2.5 1.397971,0 2.53125,1.11929 2.53125,2.5 z"
+ d="M 80.53125,502 A 2.5312502,2.5 0 0 1 78,504.5 2.5312502,2.5 0 0 1 75.46875,502 2.5312502,2.5 0 0 1 78,499.5 2.5312502,2.5 0 0 1 80.53125,502 Z"
transform="matrix(0.7834486,0,0,0.2000006,10.413535,395.5997)" />
<path
sodipodi:nodetypes="csccc"
@@ -44119,7 +46227,7 @@
transform="translate(1.1408497e-7,0.5000446)">
<path
transform="matrix(1.187982,0,0,1.0569758,379.83032,-513.21497)"
- d="m 80.53125,502 c 0,1.38071 -1.133279,2.5 -2.53125,2.5 -1.397971,0 -2.53125,-1.11929 -2.53125,-2.5 0,-1.38071 1.133279,-2.5 2.53125,-2.5 1.397971,0 2.53125,1.11929 2.53125,2.5 z"
+ d="M 80.53125,502 A 2.5312502,2.5 0 0 1 78,504.5 2.5312502,2.5 0 0 1 75.46875,502 2.5312502,2.5 0 0 1 78,499.5 2.5312502,2.5 0 0 1 80.53125,502 Z"
sodipodi:ry="2.5"
sodipodi:rx="2.5312502"
sodipodi:cy="502"
@@ -44135,11 +46243,11 @@
sodipodi:cy="502"
sodipodi:rx="2.5312502"
sodipodi:ry="2.5"
- d="m 80.53125,502 c 0,1.38071 -1.133279,2.5 -2.53125,2.5 -1.397971,0 -2.53125,-1.11929 -2.53125,-2.5 0,-1.38071 1.133279,-2.5 2.53125,-2.5 1.397971,0 2.53125,1.11929 2.53125,2.5 z"
+ d="M 80.53125,502 A 2.5312502,2.5 0 0 1 78,504.5 2.5312502,2.5 0 0 1 75.46875,502 2.5312502,2.5 0 0 1 78,499.5 2.5312502,2.5 0 0 1 80.53125,502 Z"
transform="matrix(1.3827154,0,0,1.4028327,364.1482,-688.72206)" />
<path
transform="matrix(0.987526,0,0,0.8124641,394.9733,-392.80617)"
- d="m 80.53125,502 c 0,1.38071 -1.133279,2.5 -2.53125,2.5 -1.397971,0 -2.53125,-1.11929 -2.53125,-2.5 0,-1.38071 1.133279,-2.5 2.53125,-2.5 1.397971,0 2.53125,1.11929 2.53125,2.5 z"
+ d="M 80.53125,502 A 2.5312502,2.5 0 0 1 78,504.5 2.5312502,2.5 0 0 1 75.46875,502 2.5312502,2.5 0 0 1 78,499.5 2.5312502,2.5 0 0 1 80.53125,502 Z"
sodipodi:ry="2.5"
sodipodi:rx="2.5312502"
sodipodi:cy="502"
@@ -44155,11 +46263,11 @@
sodipodi:cy="502"
sodipodi:rx="2.5312502"
sodipodi:ry="2.5"
- d="m 80.53125,502 c 0,1.38071 -1.133279,2.5 -2.53125,2.5 -1.397971,0 -2.53125,-1.11929 -2.53125,-2.5 0,-1.38071 1.133279,-2.5 2.53125,-2.5 1.397971,0 2.53125,1.11929 2.53125,2.5 z"
+ d="M 80.53125,502 A 2.5312502,2.5 0 0 1 78,504.5 2.5312502,2.5 0 0 1 75.46875,502 2.5312502,2.5 0 0 1 78,499.5 2.5312502,2.5 0 0 1 80.53125,502 Z"
transform="matrix(0.9848328,0,0,0.9992585,395.19018,-485.12778)" />
<path
transform="matrix(0.591154,0,0,0.5887513,425.87219,-279.05319)"
- d="m 80.53125,502 c 0,1.38071 -1.133279,2.5 -2.53125,2.5 -1.397971,0 -2.53125,-1.11929 -2.53125,-2.5 0,-1.38071 1.133279,-2.5 2.53125,-2.5 1.397971,0 2.53125,1.11929 2.53125,2.5 z"
+ d="M 80.53125,502 A 2.5312502,2.5 0 0 1 78,504.5 2.5312502,2.5 0 0 1 75.46875,502 2.5312502,2.5 0 0 1 78,499.5 2.5312502,2.5 0 0 1 80.53125,502 Z"
sodipodi:ry="2.5"
sodipodi:rx="2.5312502"
sodipodi:cy="502"
@@ -44169,7 +46277,7 @@
sodipodi:type="arc" />
<path
transform="matrix(0.9913883,0,0,1.0058976,394.67318,-488.46061)"
- d="m 80.53125,502 c 0,1.38071 -1.133279,2.5 -2.53125,2.5 -1.397971,0 -2.53125,-1.11929 -2.53125,-2.5 0,-1.38071 1.133279,-2.5 2.53125,-2.5 1.397971,0 2.53125,1.11929 2.53125,2.5 z"
+ d="M 80.53125,502 A 2.5312502,2.5 0 0 1 78,504.5 2.5312502,2.5 0 0 1 75.46875,502 2.5312502,2.5 0 0 1 78,499.5 2.5312502,2.5 0 0 1 80.53125,502 Z"
sodipodi:ry="2.5"
sodipodi:rx="2.5312502"
sodipodi:cy="502"
@@ -44185,11 +46293,11 @@
sodipodi:cy="502"
sodipodi:rx="2.5312502"
sodipodi:ry="2.5"
- d="m 80.53125,502 c 0,1.38071 -1.133279,2.5 -2.53125,2.5 -1.397971,0 -2.53125,-1.11929 -2.53125,-2.5 0,-1.38071 1.133279,-2.5 2.53125,-2.5 1.397971,0 2.53125,1.11929 2.53125,2.5 z"
+ d="M 80.53125,502 A 2.5312502,2.5 0 0 1 78,504.5 2.5312502,2.5 0 0 1 75.46875,502 2.5312502,2.5 0 0 1 78,499.5 2.5312502,2.5 0 0 1 80.53125,502 Z"
transform="matrix(0.6941559,0,0,0.6920597,417.67198,-331.15708)" />
<path
transform="matrix(0.1975308,0,0,0.1999991,456.0926,-84.399595)"
- d="m 80.53125,502 c 0,1.38071 -1.133279,2.5 -2.53125,2.5 -1.397971,0 -2.53125,-1.11929 -2.53125,-2.5 0,-1.38071 1.133279,-2.5 2.53125,-2.5 1.397971,0 2.53125,1.11929 2.53125,2.5 z"
+ d="M 80.53125,502 A 2.5312502,2.5 0 0 1 78,504.5 2.5312502,2.5 0 0 1 75.46875,502 2.5312502,2.5 0 0 1 78,499.5 2.5312502,2.5 0 0 1 80.53125,502 Z"
sodipodi:ry="2.5"
sodipodi:rx="2.5312502"
sodipodi:cy="502"
@@ -44199,7 +46307,7 @@
sodipodi:type="arc" />
<path
transform="matrix(-0.6760501,-0.1575078,0.1570322,-0.6740085,446.07727,367.34791)"
- d="m 80.53125,502 c 0,1.38071 -1.133279,2.5 -2.53125,2.5 -1.397971,0 -2.53125,-1.11929 -2.53125,-2.5 0,-1.38071 1.133279,-2.5 2.53125,-2.5 1.397971,0 2.53125,1.11929 2.53125,2.5 z"
+ d="M 80.53125,502 A 2.5312502,2.5 0 0 1 78,504.5 2.5312502,2.5 0 0 1 75.46875,502 2.5312502,2.5 0 0 1 78,499.5 2.5312502,2.5 0 0 1 80.53125,502 Z"
sodipodi:ry="2.5"
sodipodi:rx="2.5312502"
sodipodi:cy="502"
@@ -44218,7 +46326,7 @@
</g>
<g
transform="translate(45,422.99999)"
- id="g22102"
+ id="ICON_RESTRICT_RENDER_ON"
style="opacity:0.25;display:inline">
<rect
ry="0"
@@ -44278,7 +46386,7 @@
id="g22118">
<path
transform="matrix(0.7834486,0,0,0.2000006,10.413535,395.5997)"
- d="m 80.53125,502 c 0,1.38071 -1.133279,2.5 -2.53125,2.5 -1.397971,0 -2.53125,-1.11929 -2.53125,-2.5 0,-1.38071 1.133279,-2.5 2.53125,-2.5 1.397971,0 2.53125,1.11929 2.53125,2.5 z"
+ d="M 80.53125,502 A 2.5312502,2.5 0 0 1 78,504.5 2.5312502,2.5 0 0 1 75.46875,502 2.5312502,2.5 0 0 1 78,499.5 2.5312502,2.5 0 0 1 80.53125,502 Z"
sodipodi:ry="2.5"
sodipodi:rx="2.5312502"
sodipodi:cy="502"
@@ -44336,11 +46444,11 @@
sodipodi:cy="502"
sodipodi:rx="2.5312502"
sodipodi:ry="2.5"
- d="m 80.53125,502 c 0,1.38071 -1.133279,2.5 -2.53125,2.5 -1.397971,0 -2.53125,-1.11929 -2.53125,-2.5 0,-1.38071 1.133279,-2.5 2.53125,-2.5 1.397971,0 2.53125,1.11929 2.53125,2.5 z"
+ d="M 80.53125,502 A 2.5312502,2.5 0 0 1 78,504.5 2.5312502,2.5 0 0 1 75.46875,502 2.5312502,2.5 0 0 1 78,499.5 2.5312502,2.5 0 0 1 80.53125,502 Z"
transform="matrix(1.187982,0,0,1.0569758,379.83032,-513.21497)" />
<path
transform="matrix(1.3827154,0,0,1.4028327,364.1482,-688.72206)"
- d="m 80.53125,502 c 0,1.38071 -1.133279,2.5 -2.53125,2.5 -1.397971,0 -2.53125,-1.11929 -2.53125,-2.5 0,-1.38071 1.133279,-2.5 2.53125,-2.5 1.397971,0 2.53125,1.11929 2.53125,2.5 z"
+ d="M 80.53125,502 A 2.5312502,2.5 0 0 1 78,504.5 2.5312502,2.5 0 0 1 75.46875,502 2.5312502,2.5 0 0 1 78,499.5 2.5312502,2.5 0 0 1 80.53125,502 Z"
sodipodi:ry="2.5"
sodipodi:rx="2.5312502"
sodipodi:cy="502"
@@ -44356,11 +46464,11 @@
sodipodi:cy="502"
sodipodi:rx="2.5312502"
sodipodi:ry="2.5"
- d="m 80.53125,502 c 0,1.38071 -1.133279,2.5 -2.53125,2.5 -1.397971,0 -2.53125,-1.11929 -2.53125,-2.5 0,-1.38071 1.133279,-2.5 2.53125,-2.5 1.397971,0 2.53125,1.11929 2.53125,2.5 z"
+ d="M 80.53125,502 A 2.5312502,2.5 0 0 1 78,504.5 2.5312502,2.5 0 0 1 75.46875,502 2.5312502,2.5 0 0 1 78,499.5 2.5312502,2.5 0 0 1 80.53125,502 Z"
transform="matrix(0.987526,0,0,0.8124641,394.9733,-392.80617)" />
<path
transform="matrix(0.9848328,0,0,0.9992585,395.19018,-485.12778)"
- d="m 80.53125,502 c 0,1.38071 -1.133279,2.5 -2.53125,2.5 -1.397971,0 -2.53125,-1.11929 -2.53125,-2.5 0,-1.38071 1.133279,-2.5 2.53125,-2.5 1.397971,0 2.53125,1.11929 2.53125,2.5 z"
+ d="M 80.53125,502 A 2.5312502,2.5 0 0 1 78,504.5 2.5312502,2.5 0 0 1 75.46875,502 2.5312502,2.5 0 0 1 78,499.5 2.5312502,2.5 0 0 1 80.53125,502 Z"
sodipodi:ry="2.5"
sodipodi:rx="2.5312502"
sodipodi:cy="502"
@@ -44376,7 +46484,7 @@
sodipodi:cy="502"
sodipodi:rx="2.5312502"
sodipodi:ry="2.5"
- d="m 80.53125,502 c 0,1.38071 -1.133279,2.5 -2.53125,2.5 -1.397971,0 -2.53125,-1.11929 -2.53125,-2.5 0,-1.38071 1.133279,-2.5 2.53125,-2.5 1.397971,0 2.53125,1.11929 2.53125,2.5 z"
+ d="M 80.53125,502 A 2.5312502,2.5 0 0 1 78,504.5 2.5312502,2.5 0 0 1 75.46875,502 2.5312502,2.5 0 0 1 78,499.5 2.5312502,2.5 0 0 1 80.53125,502 Z"
transform="matrix(0.591154,0,0,0.5887513,425.87219,-279.05319)" />
<path
sodipodi:type="arc"
@@ -44386,11 +46494,11 @@
sodipodi:cy="502"
sodipodi:rx="2.5312502"
sodipodi:ry="2.5"
- d="m 80.53125,502 c 0,1.38071 -1.133279,2.5 -2.53125,2.5 -1.397971,0 -2.53125,-1.11929 -2.53125,-2.5 0,-1.38071 1.133279,-2.5 2.53125,-2.5 1.397971,0 2.53125,1.11929 2.53125,2.5 z"
+ d="M 80.53125,502 A 2.5312502,2.5 0 0 1 78,504.5 2.5312502,2.5 0 0 1 75.46875,502 2.5312502,2.5 0 0 1 78,499.5 2.5312502,2.5 0 0 1 80.53125,502 Z"
transform="matrix(0.9913883,0,0,1.0058976,394.67318,-488.46061)" />
<path
transform="matrix(0.6941559,0,0,0.6920597,417.84876,-330.91401)"
- d="m 80.53125,502 c 0,1.38071 -1.133279,2.5 -2.53125,2.5 -1.397971,0 -2.53125,-1.11929 -2.53125,-2.5 0,-1.38071 1.133279,-2.5 2.53125,-2.5 1.397971,0 2.53125,1.11929 2.53125,2.5 z"
+ d="M 80.53125,502 A 2.5312502,2.5 0 0 1 78,504.5 2.5312502,2.5 0 0 1 75.46875,502 2.5312502,2.5 0 0 1 78,499.5 2.5312502,2.5 0 0 1 80.53125,502 Z"
sodipodi:ry="2.5"
sodipodi:rx="2.5312502"
sodipodi:cy="502"
@@ -44406,7 +46514,7 @@
sodipodi:cy="502"
sodipodi:rx="2.5312502"
sodipodi:ry="2.5"
- d="m 80.53125,502 c 0,1.38071 -1.133279,2.5 -2.53125,2.5 -1.397971,0 -2.53125,-1.11929 -2.53125,-2.5 0,-1.38071 1.133279,-2.5 2.53125,-2.5 1.397971,0 2.53125,1.11929 2.53125,2.5 z"
+ d="M 80.53125,502 A 2.5312502,2.5 0 0 1 78,504.5 2.5312502,2.5 0 0 1 75.46875,502 2.5312502,2.5 0 0 1 78,499.5 2.5312502,2.5 0 0 1 80.53125,502 Z"
transform="matrix(0.1975308,0,0,0.1999991,456.07844,-84.89955)" />
</g>
<path
@@ -44419,7 +46527,7 @@
</g>
<g
transform="translate(-272,478.06251)"
- id="g30185"
+ id="ICON_OUTLINER_OB_CAMERA"
style="opacity:0.98000004;display:inline"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90">
@@ -44439,9 +46547,9 @@
sodipodi:cy="108.5"
sodipodi:rx="3"
sodipodi:ry="3"
- d="m 446.5,108.5 c 0,1.65685 -1.34315,3 -3,3 -1.65685,0 -3,-1.34315 -3,-3 0,-1.65685 1.34315,-3 3,-3 1.65685,0 3,1.34315 3,3 z" />
+ d="m 446.5,108.5 a 3,3 0 0 1 -3,3 3,3 0 0 1 -3,-3 3,3 0 0 1 3,-3 3,3 0 0 1 3,3 z" />
<path
- d="m 446.5,108.5 c 0,1.65685 -1.34315,3 -3,3 -1.65685,0 -3,-1.34315 -3,-3 0,-1.65685 1.34315,-3 3,-3 1.65685,0 3,1.34315 3,3 z"
+ d="m 446.5,108.5 a 3,3 0 0 1 -3,3 3,3 0 0 1 -3,-3 3,3 0 0 1 3,-3 3,3 0 0 1 3,3 z"
sodipodi:ry="3"
sodipodi:rx="3"
sodipodi:cy="108.5"
@@ -44451,7 +46559,7 @@
sodipodi:type="arc"
transform="matrix(1.3340954,0,0,1.3333333,-184.1736,-187.16666)" />
<path
- d="m 446.5,108.5 c 0,1.65685 -1.34315,3 -3,3 -1.65685,0 -3,-1.34315 -3,-3 0,-1.65685 1.34315,-3 3,-3 1.65685,0 3,1.34315 3,3 z"
+ d="m 446.5,108.5 a 3,3 0 0 1 -3,3 3,3 0 0 1 -3,-3 3,3 0 0 1 3,-3 3,3 0 0 1 3,3 z"
sodipodi:ry="3"
sodipodi:rx="3"
sodipodi:cy="108.5"
@@ -44478,7 +46586,7 @@
sodipodi:cy="108.5"
sodipodi:rx="3"
sodipodi:ry="3"
- d="m 440.514,108.7895 c -0.15988,-1.64913 1.04738,-3.11561 2.6965,-3.2755 1.64913,-0.15988 3.11561,1.04738 3.2755,2.6965 0.15988,1.64913 -1.04738,3.11561 -2.6965,3.2755 -0.37605,0.0365 -0.75561,0.002 -1.1187,-0.10287" />
+ d="m 440.514,108.7895 a 3,3 0 0 1 1.83109,-3.05829 3,3 0 0 1 3.46157,0.85063 3,3 0 0 1 0.20507,3.55865 3,3 0 0 1 -3.34093,1.24264" />
<path
transform="matrix(1.1662469,0,0,1.1666676,-109.73384,-169.08343)"
sodipodi:type="arc"
@@ -44488,12 +46596,12 @@
sodipodi:cy="108.5"
sodipodi:rx="3"
sodipodi:ry="3"
- d="m 446.5,108.5 c 0,1.65685 -1.34315,3 -3,3 -1.65685,0 -3,-1.34315 -3,-3 0,-1.65685 1.34315,-3 3,-3 1.65685,0 3,1.34315 3,3 z" />
+ d="m 446.5,108.5 a 3,3 0 0 1 -3,3 3,3 0 0 1 -3,-3 3,3 0 0 1 3,-3 3,3 0 0 1 3,3 z" />
<path
sodipodi:open="true"
sodipodi:end="5.930273"
sodipodi:start="0.96146912"
- d="m 445.21695,110.9601 c -1.35868,0.94824 -3.22881,0.61552 -4.17705,-0.74315 -0.94824,-1.35868 -0.61552,-3.22881 0.74315,-4.17705 1.35868,-0.94824 3.22881,-0.61552 4.17705,0.74315 0.14695,0.21056 0.26626,0.43911 0.35501,0.68005"
+ d="m 445.21695,110.9601 a 3,3 0 0 1 -3.49134,-0.0411 3,3 0 0 1 -1.0878,-3.3178 3,3 0 0 1 2.78925,-2.1003 3,3 0 0 1 2.88805,1.96221"
sodipodi:ry="3"
sodipodi:rx="3"
sodipodi:cy="108.5"
@@ -44518,7 +46626,7 @@
sodipodi:cy="108.5"
sodipodi:rx="3"
sodipodi:ry="3"
- d="m 446.5,108.5 c 0,1.65685 -1.34315,3 -3,3 -1.65685,0 -3,-1.34315 -3,-3 0,-1.65685 1.34315,-3 3,-3 1.65685,0 3,1.34315 3,3 z" />
+ d="m 446.5,108.5 a 3,3 0 0 1 -3,3 3,3 0 0 1 -3,-3 3,3 0 0 1 3,-3 3,3 0 0 1 3,3 z" />
<rect
y="-43"
x="407"
@@ -44527,7 +46635,7 @@
id="rect30207"
style="fill:#2b2200;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
<path
- d="m 446.5,108.5 c 0,1.65685 -1.34315,3 -3,3 -1.65685,0 -3,-1.34315 -3,-3 0,-1.65685 1.34315,-3 3,-3 1.65685,0 3,1.34315 3,3 z"
+ d="m 446.5,108.5 a 3,3 0 0 1 -3,3 3,3 0 0 1 -3,-3 3,3 0 0 1 3,-3 3,3 0 0 1 3,3 z"
sodipodi:ry="3"
sodipodi:rx="3"
sodipodi:cy="108.5"
@@ -44600,7 +46708,7 @@
</g>
<g
style="opacity:0.98000004;display:inline"
- id="g30282"
+ id="ICON_OUTLINER_DATA_CAMERA"
transform="translate(-271.99542,457.0625)">
<rect
style="opacity:0;fill:#1a1a1a;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
@@ -44610,7 +46718,7 @@
x="403"
y="-48" />
<path
- d="m 446.5,108.5 c 0,1.65685 -1.34315,3 -3,3 -1.65685,0 -3,-1.34315 -3,-3 0,-1.65685 1.34315,-3 3,-3 1.65685,0 3,1.34315 3,3 z"
+ d="m 446.5,108.5 a 3,3 0 0 1 -3,3 3,3 0 0 1 -3,-3 3,3 0 0 1 3,-3 3,3 0 0 1 3,3 z"
sodipodi:ry="3"
sodipodi:rx="3"
sodipodi:cy="108.5"
@@ -44628,7 +46736,7 @@
sodipodi:cy="108.5"
sodipodi:rx="3"
sodipodi:ry="3"
- d="m 446.5,108.5 c 0,1.65685 -1.34315,3 -3,3 -1.65685,0 -3,-1.34315 -3,-3 0,-1.65685 1.34315,-3 3,-3 1.65685,0 3,1.34315 3,3 z" />
+ d="m 446.5,108.5 a 3,3 0 0 1 -3,3 3,3 0 0 1 -3,-3 3,3 0 0 1 3,-3 3,3 0 0 1 3,3 z" />
<path
transform="matrix(1.1662469,0,0,1.1666676,-103.72925,-170.08344)"
sodipodi:type="arc"
@@ -44638,7 +46746,7 @@
sodipodi:cy="108.5"
sodipodi:rx="3"
sodipodi:ry="3"
- d="m 446.5,108.5 c 0,1.65685 -1.34315,3 -3,3 -1.65685,0 -3,-1.34315 -3,-3 0,-1.65685 1.34315,-3 3,-3 1.65685,0 3,1.34315 3,3 z" />
+ d="m 446.5,108.5 a 3,3 0 0 1 -3,3 3,3 0 0 1 -3,-3 3,3 0 0 1 3,-3 3,3 0 0 1 3,3 z" />
<path
style="fill:#787878;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:0.80000001;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
d="m 407.5,-39.5 0,1.999993 -2,0 0,2 2,0 0,1 1,1 5,7e-6 0,-1 2.99542,0 1.5,1 0.25,0 0,-5 -0.25,0 -1.5,1 -2.99542,0 0,-2 -6,0 z"
@@ -44646,7 +46754,7 @@
sodipodi:nodetypes="cccccccccccccccccc"
inkscape:connector-curvature="0" />
<path
- d="m 440.514,108.7895 c -0.15988,-1.64913 1.04738,-3.11561 2.6965,-3.2755 1.64913,-0.15988 3.11561,1.04738 3.2755,2.6965 0.15988,1.64913 -1.04738,3.11561 -2.6965,3.2755 -0.37605,0.0365 -0.75561,0.002 -1.1187,-0.10287"
+ d="m 440.514,108.7895 a 3,3 0 0 1 1.83109,-3.05829 3,3 0 0 1 3.46157,0.85063 3,3 0 0 1 0.20507,3.55865 3,3 0 0 1 -3.34093,1.24264"
sodipodi:ry="3"
sodipodi:rx="3"
sodipodi:cy="108.5"
@@ -44659,7 +46767,7 @@
sodipodi:end="8.1340281"
sodipodi:open="true" />
<path
- d="m 446.5,108.5 c 0,1.65685 -1.34315,3 -3,3 -1.65685,0 -3,-1.34315 -3,-3 0,-1.65685 1.34315,-3 3,-3 1.65685,0 3,1.34315 3,3 z"
+ d="m 446.5,108.5 a 3,3 0 0 1 -3,3 3,3 0 0 1 -3,-3 3,3 0 0 1 3,-3 3,3 0 0 1 3,3 z"
sodipodi:ry="3"
sodipodi:rx="3"
sodipodi:cy="108.5"
@@ -44677,7 +46785,7 @@
sodipodi:cy="108.5"
sodipodi:rx="3"
sodipodi:ry="3"
- d="m 445.21695,110.9601 c -1.35868,0.94824 -3.22881,0.61552 -4.17705,-0.74315 -0.94824,-1.35868 -0.61552,-3.22881 0.74315,-4.17705 1.35868,-0.94824 3.22881,-0.61552 4.17705,0.74315 0.14695,0.21056 0.26626,0.43911 0.35501,0.68005"
+ d="m 445.21695,110.9601 a 3,3 0 0 1 -3.49134,-0.0411 3,3 0 0 1 -1.0878,-3.3178 3,3 0 0 1 2.78925,-2.1003 3,3 0 0 1 2.88805,1.96221"
sodipodi:start="0.96146912"
sodipodi:end="5.930273"
sodipodi:open="true" />
@@ -44689,7 +46797,7 @@
x="409"
y="-41" />
<path
- d="m 446.5,108.5 c 0,1.65685 -1.34315,3 -3,3 -1.65685,0 -3,-1.34315 -3,-3 0,-1.65685 1.34315,-3 3,-3 1.65685,0 3,1.34315 3,3 z"
+ d="m 446.5,108.5 a 3,3 0 0 1 -3,3 3,3 0 0 1 -3,-3 3,3 0 0 1 3,-3 3,3 0 0 1 3,3 z"
sodipodi:ry="3"
sodipodi:rx="3"
sodipodi:cy="108.5"
@@ -44714,7 +46822,7 @@
sodipodi:cy="108.5"
sodipodi:rx="3"
sodipodi:ry="3"
- d="m 446.5,108.5 c 0,1.65685 -1.34315,3 -3,3 -1.65685,0 -3,-1.34315 -3,-3 0,-1.65685 1.34315,-3 3,-3 1.65685,0 3,1.34315 3,3 z" />
+ d="m 446.5,108.5 a 3,3 0 0 1 -3,3 3,3 0 0 1 -3,-3 3,3 0 0 1 3,-3 3,3 0 0 1 3,3 z" />
<rect
y="-43.99012"
x="413.00003"
@@ -44779,7 +46887,7 @@
</g>
<g
style="opacity:0.98000004;display:inline"
- id="g30350"
+ id="ICON_CAMERA_DATA"
transform="translate(-145.99542,541.00002)">
<rect
style="opacity:0;fill:#1a1a1a;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
@@ -44789,7 +46897,7 @@
x="403"
y="-48" />
<path
- d="m 446.5,108.5 c 0,1.65685 -1.34315,3 -3,3 -1.65685,0 -3,-1.34315 -3,-3 0,-1.65685 1.34315,-3 3,-3 1.65685,0 3,1.34315 3,3 z"
+ d="m 446.5,108.5 a 3,3 0 0 1 -3,3 3,3 0 0 1 -3,-3 3,3 0 0 1 3,-3 3,3 0 0 1 3,3 z"
sodipodi:ry="3"
sodipodi:rx="3"
sodipodi:cy="108.5"
@@ -44807,7 +46915,7 @@
sodipodi:cy="108.5"
sodipodi:rx="3"
sodipodi:ry="3"
- d="m 446.5,108.5 c 0,1.65685 -1.34315,3 -3,3 -1.65685,0 -3,-1.34315 -3,-3 0,-1.65685 1.34315,-3 3,-3 1.65685,0 3,1.34315 3,3 z" />
+ d="m 446.5,108.5 a 3,3 0 0 1 -3,3 3,3 0 0 1 -3,-3 3,3 0 0 1 3,-3 3,3 0 0 1 3,3 z" />
<path
transform="matrix(1.1662469,0,0,1.1666676,-103.72925,-170.08344)"
sodipodi:type="arc"
@@ -44817,7 +46925,7 @@
sodipodi:cy="108.5"
sodipodi:rx="3"
sodipodi:ry="3"
- d="m 446.5,108.5 c 0,1.65685 -1.34315,3 -3,3 -1.65685,0 -3,-1.34315 -3,-3 0,-1.65685 1.34315,-3 3,-3 1.65685,0 3,1.34315 3,3 z" />
+ d="m 446.5,108.5 a 3,3 0 0 1 -3,3 3,3 0 0 1 -3,-3 3,3 0 0 1 3,-3 3,3 0 0 1 3,3 z" />
<path
style="fill:#787878;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:0.80000001;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
d="m 407.5,-39.5 0,1.999993 -2,0 0,2 2,0 0,1 1,1 5,7e-6 0,-1 2.99542,0 1.5,1 0.25,0 0,-5 -0.25,0 -1.5,1 -2.99542,0 0,-2 -6,0 z"
@@ -44825,7 +46933,7 @@
sodipodi:nodetypes="cccccccccccccccccc"
inkscape:connector-curvature="0" />
<path
- d="m 440.514,108.7895 c -0.15988,-1.64913 1.04738,-3.11561 2.6965,-3.2755 1.64913,-0.15988 3.11561,1.04738 3.2755,2.6965 0.15988,1.64913 -1.04738,3.11561 -2.6965,3.2755 -0.37605,0.0365 -0.75561,0.002 -1.1187,-0.10287"
+ d="m 440.514,108.7895 a 3,3 0 0 1 1.83109,-3.05829 3,3 0 0 1 3.46157,0.85063 3,3 0 0 1 0.20507,3.55865 3,3 0 0 1 -3.34093,1.24264"
sodipodi:ry="3"
sodipodi:rx="3"
sodipodi:cy="108.5"
@@ -44838,7 +46946,7 @@
sodipodi:end="8.1340281"
sodipodi:open="true" />
<path
- d="m 446.5,108.5 c 0,1.65685 -1.34315,3 -3,3 -1.65685,0 -3,-1.34315 -3,-3 0,-1.65685 1.34315,-3 3,-3 1.65685,0 3,1.34315 3,3 z"
+ d="m 446.5,108.5 a 3,3 0 0 1 -3,3 3,3 0 0 1 -3,-3 3,3 0 0 1 3,-3 3,3 0 0 1 3,3 z"
sodipodi:ry="3"
sodipodi:rx="3"
sodipodi:cy="108.5"
@@ -44856,7 +46964,7 @@
sodipodi:cy="108.5"
sodipodi:rx="3"
sodipodi:ry="3"
- d="m 445.21695,110.9601 c -1.35868,0.94824 -3.22881,0.61552 -4.17705,-0.74315 -0.94824,-1.35868 -0.61552,-3.22881 0.74315,-4.17705 1.35868,-0.94824 3.22881,-0.61552 4.17705,0.74315 0.14695,0.21056 0.26626,0.43911 0.35501,0.68005"
+ d="m 445.21695,110.9601 a 3,3 0 0 1 -3.49134,-0.0411 3,3 0 0 1 -1.0878,-3.3178 3,3 0 0 1 2.78925,-2.1003 3,3 0 0 1 2.88805,1.96221"
sodipodi:start="0.96146912"
sodipodi:end="5.930273"
sodipodi:open="true" />
@@ -44868,7 +46976,7 @@
x="409"
y="-41" />
<path
- d="m 446.5,108.5 c 0,1.65685 -1.34315,3 -3,3 -1.65685,0 -3,-1.34315 -3,-3 0,-1.65685 1.34315,-3 3,-3 1.65685,0 3,1.34315 3,3 z"
+ d="m 446.5,108.5 a 3,3 0 0 1 -3,3 3,3 0 0 1 -3,-3 3,3 0 0 1 3,-3 3,3 0 0 1 3,3 z"
sodipodi:ry="3"
sodipodi:rx="3"
sodipodi:cy="108.5"
@@ -44893,7 +47001,7 @@
sodipodi:cy="108.5"
sodipodi:rx="3"
sodipodi:ry="3"
- d="m 446.5,108.5 c 0,1.65685 -1.34315,3 -3,3 -1.65685,0 -3,-1.34315 -3,-3 0,-1.65685 1.34315,-3 3,-3 1.65685,0 3,1.34315 3,3 z" />
+ d="m 446.5,108.5 a 3,3 0 0 1 -3,3 3,3 0 0 1 -3,-3 3,3 0 0 1 3,-3 3,3 0 0 1 3,3 z" />
<rect
y="-43.99012"
x="413.00003"
@@ -44956,153 +47064,107 @@
id="rect30392"
style="fill:#666666;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
</g>
- <rect
- style="opacity:0;fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- id="rect17352"
- width="16"
- height="16"
- x="194"
- y="10" />
- <g
- id="g40205">
- <rect
- y="11.546152"
- x="195.49998"
- height="12.953857"
- width="13.016124"
- id="rect17356"
- style="fill:#f2f2f2;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:0.80000001;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- ry="0" />
- <rect
- ry="0"
- style="fill:url(#linearGradient40202);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.00207269;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- id="rect17358"
- width="11.000001"
- height="11.046139"
- x="197.01611"
- y="12.00001" />
- <g
- transform="translate(146.99999,-417.99999)"
- id="g40036">
- <g
- id="g39822"
- transform="translate(-146.99999,417.99999)">
- <rect
- y="12"
- x="196"
- height="3"
- width="3"
- id="rect39628"
- style="fill:#106386;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.89999998;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
- <rect
- y="15"
- x="199"
- height="3"
- width="3"
- id="rect39636"
- style="fill:#ba0036;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.89999998;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
- <rect
- style="fill:#9f0022;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.89999998;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- id="rect39670"
- width="3"
- height="3"
- x="202"
- y="12" />
- <rect
- style="fill:#688c7f;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.89999998;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- id="rect39676"
- width="3"
- height="3"
- x="205"
- y="15" />
- <rect
- style="fill:#b77100;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.89999998;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- id="rect39678"
- width="3"
- height="3"
- x="196"
- y="18" />
- <rect
- style="fill:#a67c58;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.89999998;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- id="rect39684"
- width="3"
- height="3"
- x="199"
- y="21" />
- <rect
- y="18"
- x="202"
- height="3"
- width="3"
- id="rect39686"
- style="fill:#7a2537;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.89999998;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
- <rect
- y="21"
- x="205"
- height="3"
- width="3"
- id="rect39692"
- style="fill:#869c2b;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.89999998;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
- </g>
- </g>
- <path
- sodipodi:nodetypes="ccc"
- id="path17363"
- d="m 207.51769,12.50001 -11.0177,0 0,11 11.0177,0 0,-11"
- style="fill:none;stroke:url(#linearGradient40189);stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
- inkscape:connector-curvature="0" />
- </g>
- <rect
- y="10"
- x="174"
- height="16"
- width="16"
- id="rect39978"
- style="opacity:0;fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
<g
- id="g17366"
- transform="translate(286,-429)">
+ id="ICON_IMAGE_RGB">
+ <rect
+ y="10"
+ x="194"
+ height="16"
+ width="16"
+ id="rect17352"
+ style="opacity:0;fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
<g
- id="g17368"
- transform="translate(16,-32)">
+ id="g40205">
<rect
- y="471"
- x="-45"
- height="16"
- width="16"
- id="rect17370"
- style="opacity:0;fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ ry="0"
+ style="fill:#f2f2f2;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:0.80000001;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect17356"
+ width="13.016124"
+ height="12.953857"
+ x="195.49998"
+ y="11.546152" />
<rect
- y="472.5"
- x="-43.483856"
- height="13"
- width="12.983856"
- id="rect17372"
- style="fill:url(#linearGradient17429);fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:0.80000001;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0.5;display:inline" />
+ y="12.00001"
+ x="197.01611"
+ height="11.046139"
+ width="11.000001"
+ id="rect17358"
+ style="fill:url(#linearGradient40202);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.00207269;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ ry="0" />
+ <g
+ id="g40036"
+ transform="translate(146.99999,-417.99999)">
+ <g
+ transform="translate(-146.99999,417.99999)"
+ id="g39822">
+ <rect
+ style="fill:#106386;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.89999998;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect39628"
+ width="3"
+ height="3"
+ x="196"
+ y="12" />
+ <rect
+ style="fill:#ba0036;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.89999998;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect39636"
+ width="3"
+ height="3"
+ x="199"
+ y="15" />
+ <rect
+ y="12"
+ x="202"
+ height="3"
+ width="3"
+ id="rect39670"
+ style="fill:#9f0022;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.89999998;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <rect
+ y="15"
+ x="205"
+ height="3"
+ width="3"
+ id="rect39676"
+ style="fill:#688c7f;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.89999998;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <rect
+ y="18"
+ x="196"
+ height="3"
+ width="3"
+ id="rect39678"
+ style="fill:#b77100;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.89999998;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <rect
+ y="21"
+ x="199"
+ height="3"
+ width="3"
+ id="rect39684"
+ style="fill:#a67c58;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.89999998;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <rect
+ style="fill:#7a2537;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.89999998;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect39686"
+ width="3"
+ height="3"
+ x="202"
+ y="18" />
+ <rect
+ style="fill:#869c2b;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.89999998;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect39692"
+ width="3"
+ height="3"
+ x="205"
+ y="21" />
+ </g>
+ </g>
<path
- sodipodi:nodetypes="cccc"
- id="path17374"
- d="m -31.5,473.50001 -10.983862,0 0,11"
- style="fill:none;stroke:url(#linearGradient17431);stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dashoffset:0.5;display:inline"
- inkscape:connector-curvature="0" />
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:url(#linearGradient40189);stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ d="m 207.51769,12.50001 -11.0177,0 0,11 11.0177,0 0,-11"
+ id="path17363"
+ sodipodi:nodetypes="ccc" />
</g>
- <rect
- y="443"
- x="-25"
- height="5"
- width="5"
- id="rect17376"
- style="fill:#999999;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.89999998;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
- <rect
- style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.89999998;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- id="rect17379"
- width="5"
- height="5"
- x="-22"
- y="446" />
</g>
<g
- id="g32743"
+ id="ICON_IMAGE_ALPHA"
transform="translate(9.471,32.00923)">
<rect
y="-22.009235"
@@ -45135,55 +47197,7 @@
inkscape:connector-curvature="0" />
</g>
<g
- id="g17336"
- transform="translate(275,-385.99999)"
- style="opacity:0.25">
- <rect
- style="opacity:0;fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- id="rect17338"
- width="16"
- height="16"
- x="-60"
- y="396" />
- <g
- id="g17340">
- <rect
- y="397.54614"
- x="-58.500015"
- height="12.953857"
- width="13.016124"
- id="rect17342"
- style="fill:url(#linearGradient32725);fill-opacity:1;fill-rule:nonzero;stroke:#333333;stroke-width:0.99999994;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- ry="0" />
- <rect
- ry="0"
- style="fill:url(#linearGradient32727);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.00207269;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- id="rect17344"
- width="11.000001"
- height="11.046139"
- x="-56.983894"
- y="398" />
- <path
- style="fill:url(#linearGradient32729);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- d="m -58,398 0,2 2,0 0,-2 -2,0 z m 2,2 0,2 2,0 0,-2 -2,0 z m 2,0 2,0 0,-2 -2,0 0,2 z m 2,0 0,2 2,0 0,-2 -2,0 z m 2,0 2,0 0,-2 -2,0 0,2 z m 2,0 0,2 2,0 0,-2 -2,0 z m 0,2 -2,0 0,2 2,0 0,-2 z m 0,2 0,2 2,0 0,-2 -2,0 z m 0,2 -2,0 0,2 2,0 0,-2 z m 0,2 0,2 2,0 0,-2 -2,0 z m -2,0 -2,0 0,2 2,0 0,-2 z m -2,0 0,-2 -2,0 0,2 2,0 z m -2,0 -2,0 0,2 2,0 0,-2 z m -2,0 0,-2 -2,0 0,2 2,0 z m 0,-2 2,0 0,-2 -2,0 0,2 z m 0,-2 0,-2 -2,0 0,2 2,0 z m 2,0 2,0 0,-2 -2,0 0,2 z m 2,0 0,2 2,0 0,-2 -2,0 z"
- id="path17346"
- inkscape:connector-curvature="0" />
- <path
- sodipodi:nodetypes="ccc"
- id="path17348"
- d="m -46.482307,398.50001 -11.017704,0 0,11 11.017704,0 0,-11"
- style="opacity:0.45;fill:none;stroke:url(#linearGradient32731);stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
- inkscape:connector-curvature="0" />
- </g>
- </g>
- <path
- style="opacity:0.65;fill:none;stroke:#000000;stroke-width:1.79999995;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
- d="m 217.5,24.000005 11.5,-11.5"
- id="path17578"
- sodipodi:nodetypes="cc"
- inkscape:connector-curvature="0" />
- <g
- id="g17152"
+ id="ICON_LOCKVIEW_ON"
transform="translate(339,-210)">
<rect
style="opacity:0;fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
@@ -45308,7 +47322,7 @@
</g>
</g>
<g
- id="g18489"
+ id="ICON_LOCKVIEW_OFF"
transform="translate(287,-54.93125)">
<g
id="g18491"
@@ -45453,7 +47467,7 @@
</g>
</g>
<g
- id="g18658"
+ id="ICON_FONTPREVIEW"
transform="translate(-147.04123,1.9815)">
<rect
y="71.018501"
@@ -45527,7 +47541,7 @@
</g>
<g
transform="translate(2,529.00001)"
- id="g18738"
+ id="ICON_FULLSCREEN"
style="display:inline">
<rect
style="opacity:0;fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
@@ -45588,7 +47602,7 @@
</g>
<g
transform="translate(256.9902,446.00001)"
- id="g18759"
+ id="ICON_MENU_PANEL"
style="display:inline">
<rect
style="opacity:0;fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
@@ -45652,7 +47666,7 @@
inkscape:connector-curvature="0" />
</g>
<g
- id="g18864"
+ id="ICON_SPLITSCREEN"
transform="translate(210,253.00005)">
<rect
y="345"
@@ -45741,7 +47755,7 @@
inkscape:connector-curvature="0" />
</g>
<g
- id="g17204"
+ id="ICON_LONGDISPLAY"
transform="translate(290,-291)">
<g
transform="translate(-204,295)"
@@ -45807,7 +47821,7 @@
inkscape:connector-curvature="0" />
</g>
<g
- id="g17183"
+ id="ICON_SHORTDISPLAY"
transform="translate(294,-291)">
<g
style="display:inline"
@@ -45898,7 +47912,7 @@
inkscape:connector-curvature="0" />
</g>
<g
- id="g41473">
+ id="ICON_SCENE_DATA">
<g
id="g20803"
transform="translate(-116.99998,424.00001)">
@@ -45913,11 +47927,11 @@
sodipodi:cy="192.5"
sodipodi:rx="1.75"
sodipodi:ry="1.75"
- d="m 466.25,192.5 c 0,0.9665 -0.7835,1.75 -1.75,1.75 -0.9665,0 -1.75,-0.7835 -1.75,-1.75 0,-0.9665 0.7835,-1.75 1.75,-1.75 0.9665,0 1.75,0.7835 1.75,1.75 z"
+ d="m 466.25,192.5 a 1.75,1.75 0 0 1 -1.75,1.75 1.75,1.75 0 0 1 -1.75,-1.75 1.75,1.75 0 0 1 1.75,-1.75 1.75,1.75 0 0 1 1.75,1.75 z"
transform="matrix(1.9999998,0,0,2.0000014,-462.99991,-192.00026)" />
<path
transform="matrix(1.4285718,0,0,1.4285718,-197.57158,-82.000059)"
- d="m 466.25,192.5 c 0,0.9665 -0.7835,1.75 -1.75,1.75 -0.9665,0 -1.75,-0.7835 -1.75,-1.75 0,-0.9665 0.7835,-1.75 1.75,-1.75 0.9665,0 1.75,0.7835 1.75,1.75 z"
+ d="m 466.25,192.5 a 1.75,1.75 0 0 1 -1.75,1.75 1.75,1.75 0 0 1 -1.75,-1.75 1.75,1.75 0 0 1 1.75,-1.75 1.75,1.75 0 0 1 1.75,1.75 z"
sodipodi:ry="1.75"
sodipodi:rx="1.75"
sodipodi:cy="192.5"
@@ -45933,7 +47947,7 @@
sodipodi:cy="192.5"
sodipodi:rx="1.75"
sodipodi:ry="1.75"
- d="m 466.25,192.5 c 0,0.9665 -0.7835,1.75 -1.75,1.75 -0.9665,0 -1.75,-0.7835 -1.75,-1.75 0,-0.9665 0.7835,-1.75 1.75,-1.75 0.9665,0 1.75,0.7835 1.75,1.75 z"
+ d="m 466.25,192.5 a 1.75,1.75 0 0 1 -1.75,1.75 1.75,1.75 0 0 1 -1.75,-1.75 1.75,1.75 0 0 1 1.75,-1.75 1.75,1.75 0 0 1 1.75,1.75 z"
transform="matrix(0.8571429,0,0,0.8571429,67.857123,27.999992)" />
</g>
<rect
@@ -45975,7 +47989,7 @@
sodipodi:cy="-222"
sodipodi:rx="3.3084693"
sodipodi:ry="1.2798798"
- d="m 111.30847,-222 c 0,0.70686 -1.48125,1.27988 -3.30847,1.27988 -1.82722,0 -3.30847,-0.57302 -3.30847,-1.27988 0,-0.70686 1.48125,-1.27988 3.30847,-1.27988 1.82722,0 3.30847,0.57302 3.30847,1.27988 z"
+ d="M 111.30847,-222 A 3.3084693,1.2798798 0 0 1 108,-220.72012 3.3084693,1.2798798 0 0 1 104.69153,-222 3.3084693,1.2798798 0 0 1 108,-223.27988 3.3084693,1.2798798 0 0 1 111.30847,-222 Z"
transform="matrix(0.9067635,0,0,1.3047091,374.56954,447.97555)" />
<path
sodipodi:nodetypes="cccsccc"
@@ -45991,7 +48005,7 @@
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
sodipodi:ry="8"
sodipodi:rx="8"
sodipodi:cy="118"
@@ -46005,7 +48019,7 @@
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
sodipodi:ry="8"
sodipodi:rx="8"
sodipodi:cy="118"
@@ -46017,7 +48031,7 @@
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
sodipodi:ry="8"
sodipodi:rx="8"
sodipodi:cy="118"
@@ -46037,7 +48051,7 @@
</g>
</g>
<g
- id="g17123"
+ id="ICON_PARTICLEMODE"
transform="translate(207.01492,72.000007)">
<rect
y="442"
@@ -46066,7 +48080,7 @@
inkscape:connector-curvature="0" />
</g>
<g
- id="g17299"
+ id="ICON_GO_LEFT"
transform="translate(-21,128.00001)">
<g
transform="translate(464,422)"
@@ -46155,22 +48169,8 @@
</g>
</g>
<g
- id="g17117" />
- <g
- id="g17121"
- transform="translate(9,0)" />
- <g
- transform="translate(6,4)"
- id="g17128" />
- <g
- id="g17136"
- transform="translate(1,6)" />
- <g
- id="g17149"
- transform="translate(8,7)" />
- <g
style="display:inline"
- id="g22103"
+ id="ICON_GAME"
transform="translate(-10,466.00001)">
<rect
style="opacity:0;fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
@@ -46265,7 +48265,7 @@
y="328.03571" />
<path
transform="matrix(1.6666708,0,0,1.6666633,-190.66784,-215.66559)"
- d="m 287.5,325 c 0,0.82843 -0.67157,1.5 -1.5,1.5 -0.82843,0 -1.5,-0.67157 -1.5,-1.5 0,-0.82843 0.67157,-1.5 1.5,-1.5 0.82843,0 1.5,0.67157 1.5,1.5 z"
+ d="m 287.5,325 a 1.5,1.5 0 0 1 -1.5,1.5 1.5,1.5 0 0 1 -1.5,-1.5 1.5,1.5 0 0 1 1.5,-1.5 1.5,1.5 0 0 1 1.5,1.5 z"
sodipodi:ry="1.5"
sodipodi:rx="1.5"
sodipodi:cy="325"
@@ -46295,7 +48295,7 @@
sodipodi:cy="325"
sodipodi:rx="1.5"
sodipodi:ry="1.5"
- d="m 287.5,325 c 0,0.82843 -0.67157,1.5 -1.5,1.5 -0.82843,0 -1.5,-0.67157 -1.5,-1.5 0,-0.82843 0.67157,-1.5 1.5,-1.5 0.82843,0 1.5,0.67157 1.5,1.5 z"
+ d="m 287.5,325 a 1.5,1.5 0 0 1 -1.5,1.5 1.5,1.5 0 0 1 -1.5,-1.5 1.5,1.5 0 0 1 1.5,-1.5 1.5,1.5 0 0 1 1.5,1.5 z"
transform="matrix(1.333351,0,0,1.333345,-95.338377,-107.33714)" />
<rect
y="331"
@@ -46344,7 +48344,7 @@
</g>
</g>
<g
- id="g34058"
+ id="ICON_SORTBYEXT"
transform="translate(0,12)">
<path
sodipodi:nodetypes="cccccc"
@@ -46447,7 +48447,7 @@
</g>
<g
style="display:inline"
- id="g22429"
+ id="ICON_UGLYPACKAGE"
transform="translate(542.99004,484.00118)">
<rect
y="9"
@@ -46529,16 +48529,9 @@
inkscape:connector-curvature="0" />
</g>
</g>
- <rect
- style="opacity:0;fill:#999999;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.80000001;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- id="rect17123"
- width="1"
- height="0"
- x="90"
- y="523" />
<g
style="display:inline"
- id="g18470"
+ id="ICON_HAIR"
transform="matrix(-1,0,0,1,269,-561)">
<rect
style="opacity:0;fill:#ff0000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
@@ -46568,7 +48561,7 @@
</g>
<g
style="display:inline"
- id="g22771"
+ id="ICON_PHYSICS"
transform="translate(-186,487.00001)">
<g
id="g21832"
@@ -46652,7 +48645,7 @@
sodipodi:cy="118"
sodipodi:rx="8"
sodipodi:ry="8"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90"
@@ -46665,7 +48658,7 @@
sodipodi:cy="118"
sodipodi:rx="8"
sodipodi:ry="8"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90"
@@ -46675,7 +48668,7 @@
</g>
<g
style="display:inline"
- id="g35565"
+ id="ICON_PINNED"
transform="translate(147,527.00001)"
inkscape:export-filename="/home/wolter/Documenten/Blender/Icons/Fake2.png"
inkscape:export-xdpi="90"
@@ -46694,7 +48687,7 @@
id="g34916">
<path
transform="translate(58.032932,-27.838387)"
- d="m 3.5,-32 c 0,1.932997 -1.5670034,3.5 -3.5,3.5 -1.9329966,0 -3.5,-1.567003 -3.5,-3.5 0,-1.932997 1.5670034,-3.5 3.5,-3.5 1.9329966,0 3.5,1.567003 3.5,3.5 z"
+ d="M 3.5,-32 A 3.5,3.5 0 0 1 0,-28.5 3.5,3.5 0 0 1 -3.5,-32 3.5,3.5 0 0 1 0,-35.5 3.5,3.5 0 0 1 3.5,-32 Z"
sodipodi:ry="3.5"
sodipodi:rx="3.5"
sodipodi:cy="-32"
@@ -46710,7 +48703,7 @@
sodipodi:cy="-32"
sodipodi:rx="3.5"
sodipodi:ry="3.5"
- d="m 3.5,-32 c 0,1.932997 -1.5670034,3.5 -3.5,3.5 -1.9329966,0 -3.5,-1.567003 -3.5,-3.5 0,-1.932997 1.5670034,-3.5 3.5,-3.5 1.9329966,0 3.5,1.567003 3.5,3.5 z"
+ d="M 3.5,-32 A 3.5,3.5 0 0 1 0,-28.5 3.5,3.5 0 0 1 -3.5,-32 3.5,3.5 0 0 1 0,-35.5 3.5,3.5 0 0 1 3.5,-32 Z"
transform="matrix(1.4285714,0,0,1.4274429,55.5,-11.825777)" />
</g>
<g
@@ -46724,11 +48717,11 @@
sodipodi:cy="-32"
sodipodi:rx="3.5"
sodipodi:ry="3.5"
- d="m 3.5,-32 c 0,1.932997 -1.5670034,3.5 -3.5,3.5 -1.9329966,0 -3.5,-1.567003 -3.5,-3.5 0,-1.932997 1.5670034,-3.5 3.5,-3.5 1.9329966,0 3.5,1.567003 3.5,3.5 z"
+ d="M 3.5,-32 A 3.5,3.5 0 0 1 0,-28.5 3.5,3.5 0 0 1 -3.5,-32 3.5,3.5 0 0 1 0,-35.5 3.5,3.5 0 0 1 3.5,-32 Z"
transform="matrix(1.1751782,0,0,1.1751782,56.000001,-1.2882925)" />
<path
transform="matrix(0.9994022,0,0,0.9994021,56.002092,-6.9152216)"
- d="m 3.5,-32 c 0,1.932997 -1.5670034,3.5 -3.5,3.5 -1.9329966,0 -3.5,-1.567003 -3.5,-3.5 0,-1.932997 1.5670034,-3.5 3.5,-3.5 1.9329966,0 3.5,1.567003 3.5,3.5 z"
+ d="M 3.5,-32 A 3.5,3.5 0 0 1 0,-28.5 3.5,3.5 0 0 1 -3.5,-32 3.5,3.5 0 0 1 0,-35.5 3.5,3.5 0 0 1 3.5,-32 Z"
sodipodi:ry="3.5"
sodipodi:rx="3.5"
sodipodi:cy="-32"
@@ -46744,7 +48737,7 @@
sodipodi:cy="-32"
sodipodi:rx="3.5"
sodipodi:ry="3.5"
- d="m 3.5,-32 c 0,1.932997 -1.5670034,3.5 -3.5,3.5 -1.9329966,0 -3.5,-1.567003 -3.5,-3.5 0,-1.932997 1.5670034,-3.5 3.5,-3.5 1.9329966,0 3.5,1.567003 3.5,3.5 z"
+ d="M 3.5,-32 A 3.5,3.5 0 0 1 0,-28.5 3.5,3.5 0 0 1 -3.5,-32 3.5,3.5 0 0 1 0,-35.5 3.5,3.5 0 0 1 3.5,-32 Z"
transform="matrix(0.774689,0,0,0.7805148,56.890573,-14.812697)" />
<path
sodipodi:type="arc"
@@ -46754,11 +48747,11 @@
sodipodi:cy="-32"
sodipodi:rx="3.5"
sodipodi:ry="3.5"
- d="m 3.5,-32 c 0,1.932997 -1.5670034,3.5 -3.5,3.5 -1.9329966,0 -3.5,-1.567003 -3.5,-3.5 0,-1.932997 1.5670034,-3.5 3.5,-3.5 1.9329966,0 3.5,1.567003 3.5,3.5 z"
+ d="M 3.5,-32 A 3.5,3.5 0 0 1 0,-28.5 3.5,3.5 0 0 1 -3.5,-32 3.5,3.5 0 0 1 0,-35.5 3.5,3.5 0 0 1 3.5,-32 Z"
transform="matrix(1.0042021,0,0,1.0042021,55.985293,-6.7448206)" />
<path
transform="matrix(0.9108044,0,0,0.9108044,55.985293,-9.7335486)"
- d="m 3.5,-32 c 0,1.932997 -1.5670034,3.5 -3.5,3.5 -1.9329966,0 -3.5,-1.567003 -3.5,-3.5 0,-1.932997 1.5670034,-3.5 3.5,-3.5 1.9329966,0 3.5,1.567003 3.5,3.5 z"
+ d="M 3.5,-32 A 3.5,3.5 0 0 1 0,-28.5 3.5,3.5 0 0 1 -3.5,-32 3.5,3.5 0 0 1 0,-35.5 3.5,3.5 0 0 1 3.5,-32 Z"
sodipodi:ry="3.5"
sodipodi:rx="3.5"
sodipodi:cy="-32"
@@ -46772,7 +48765,7 @@
id="g34934">
<path
transform="matrix(0.8571429,0,0,0.8571429,58.032932,-32.409816)"
- d="m 3.5,-32 c 0,1.932997 -1.5670034,3.5 -3.5,3.5 -1.9329966,0 -3.5,-1.567003 -3.5,-3.5 0,-1.932997 1.5670034,-3.5 3.5,-3.5 1.9329966,0 3.5,1.567003 3.5,3.5 z"
+ d="M 3.5,-32 A 3.5,3.5 0 0 1 0,-28.5 3.5,3.5 0 0 1 -3.5,-32 3.5,3.5 0 0 1 0,-35.5 3.5,3.5 0 0 1 3.5,-32 Z"
sodipodi:ry="3.5"
sodipodi:rx="3.5"
sodipodi:cy="-32"
@@ -46788,11 +48781,11 @@
sodipodi:cy="-32"
sodipodi:rx="3.5"
sodipodi:ry="3.5"
- d="m 3.5,-32 c 0,1.932997 -1.5670034,3.5 -3.5,3.5 -1.9329966,0 -3.5,-1.567003 -3.5,-3.5 0,-1.932997 1.5670034,-3.5 3.5,-3.5 1.9329966,0 3.5,1.567003 3.5,3.5 z"
+ d="M 3.5,-32 A 3.5,3.5 0 0 1 0,-28.5 3.5,3.5 0 0 1 -3.5,-32 3.5,3.5 0 0 1 0,-35.5 3.5,3.5 0 0 1 3.5,-32 Z"
transform="matrix(0.7142853,0,0,0.7142853,58.032932,-36.981258)" />
<path
transform="translate(58.032932,-27.838387)"
- d="m 3.5,-32 c 0,1.932997 -1.5670034,3.5 -3.5,3.5 -1.9329966,0 -3.5,-1.567003 -3.5,-3.5 0,-1.932997 1.5670034,-3.5 3.5,-3.5 1.9329966,0 3.5,1.567003 3.5,3.5 z"
+ d="M 3.5,-32 A 3.5,3.5 0 0 1 0,-28.5 3.5,3.5 0 0 1 -3.5,-32 3.5,3.5 0 0 1 0,-35.5 3.5,3.5 0 0 1 3.5,-32 Z"
sodipodi:ry="3.5"
sodipodi:rx="3.5"
sodipodi:cy="-32"
@@ -46808,14 +48801,14 @@
sodipodi:cy="-32"
sodipodi:rx="3.5"
sodipodi:ry="3.5"
- d="m 3.5,-32 c 0,1.932997 -1.5670034,3.5 -3.5,3.5 -1.9329966,0 -3.5,-1.567003 -3.5,-3.5 0,-1.932997 1.5670034,-3.5 3.5,-3.5 1.9329966,0 3.5,1.567003 3.5,3.5 z"
+ d="M 3.5,-32 A 3.5,3.5 0 0 1 0,-28.5 3.5,3.5 0 0 1 -3.5,-32 3.5,3.5 0 0 1 0,-35.5 3.5,3.5 0 0 1 3.5,-32 Z"
transform="matrix(0.8571429,0,0,0.8571429,58.032932,-32.409816)" />
</g>
</g>
</g>
<g
style="display:inline"
- id="g35712"
+ id="ICON_UNPINNED"
transform="translate(307,636)"
inkscape:export-filename="/home/wolter/Documenten/Blender/Icons/Fake1.png"
inkscape:export-xdpi="90"
@@ -46926,19 +48919,8 @@
inkscape:connector-curvature="0" />
</g>
<g
- style="fill:#d45500;fill-opacity:1;display:inline"
- transform="translate(47,-247.0151)"
- id="g51988" />
- <rect
- y="73"
- x="277.99997"
- height="16"
- width="16"
- id="rect51964"
- style="opacity:0.01000001;fill:#cccccc;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.80000001;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
- <g
style="opacity:0.65;display:inline"
- id="g11875"
+ id="ICON_SNAP_OFF"
transform="translate(-334,109.04419)">
<path
style="fill:#ff0000;fill-opacity:0.75;fill-rule:evenodd;stroke:url(#linearGradient68937);stroke-width:2.4000001;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
@@ -47005,7 +48987,7 @@
</g>
<g
transform="translate(-313,109)"
- id="g51645"
+ id="ICON_SNAP_ON"
style="display:inline">
<rect
style="opacity:0;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible"
@@ -47074,7 +49056,7 @@
</g>
</g>
<g
- id="g28545"
+ id="ICON_SNAP_SURFACE"
transform="translate(21,-19)">
<g
style="opacity:0.8;display:inline"
@@ -47092,7 +49074,7 @@
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
sodipodi:ry="8"
sodipodi:rx="8"
sodipodi:cy="118"
@@ -47109,7 +49091,7 @@
sodipodi:cy="118"
sodipodi:rx="8"
sodipodi:ry="8"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90"
@@ -47118,7 +49100,7 @@
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
sodipodi:ry="8"
sodipodi:rx="8"
sodipodi:cy="118"
@@ -47207,7 +49189,7 @@
</g>
<g
style="display:inline"
- id="g20285"
+ id="ICON_SPEAKER"
transform="translate(0,107.00001)">
<rect
y="449"
@@ -47325,7 +49307,7 @@
inkscape:connector-curvature="0" />
</g>
<g
- id="g38213"
+ id="ICON_EDITMODE_HLT"
transform="translate(0,-1.00005)">
<rect
y="513.99988"
@@ -47521,7 +49503,7 @@
</g>
</g>
<g
- id="g39255"
+ id="ICON_IMGDISPLAY"
transform="translate(-21,2)">
<rect
style="opacity:0;fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
@@ -47659,7 +49641,7 @@
<g
style="display:inline"
transform="translate(168,-37)"
- id="g39106">
+ id="ICON_SNAP_VERTEX">
<g
style="opacity:0.5;display:inline"
id="g39108"
@@ -47788,7 +49770,7 @@
<g
style="display:inline"
transform="translate(168,-37)"
- id="g39140">
+ id="ICON_SNAP_EDGE">
<g
transform="translate(90,-142)"
id="g39142"
@@ -47932,7 +49914,7 @@
<g
style="display:inline"
transform="translate(168,-37)"
- id="g39172">
+ id="ICON_SNAP_FACE">
<g
style="opacity:0.5;display:inline"
id="g39174"
@@ -48032,7 +50014,7 @@
</g>
</g>
<g
- id="g28811"
+ id="ICON_MATERIAL_DATA"
transform="translate(0,128.00001)">
<rect
y="365"
@@ -48049,7 +50031,7 @@
inkscape:export-ydpi="90"
transform="matrix(1.0004639,0,0,0.9963165,-69.122722,304.28985)">
<path
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
sodipodi:ry="8"
sodipodi:rx="8"
sodipodi:cy="118"
@@ -48075,7 +50057,7 @@
sodipodi:cy="118"
sodipodi:rx="8"
sodipodi:ry="8"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90"
@@ -48085,7 +50067,7 @@
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
sodipodi:ry="8"
sodipodi:rx="8"
sodipodi:cy="118"
@@ -48098,7 +50080,7 @@
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
sodipodi:ry="8"
sodipodi:rx="8"
sodipodi:cy="118"
@@ -48122,7 +50104,7 @@
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
sodipodi:ry="8"
sodipodi:rx="8"
sodipodi:cy="118"
@@ -48134,7 +50116,7 @@
</g>
</g>
<g
- id="g40234">
+ id="ICON_OBJECT_DATAMODE">
<rect
y="514.00012"
x="5"
@@ -48209,17 +50191,13 @@
</g>
<g
style="display:inline"
- id="g57337"
- transform="translate(10,254)" />
- <g
- style="display:inline"
- id="g57399"
+ id="ICON_MATERIAL"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90"
transform="matrix(1.0004639,0,0,0.9963165,-237.12363,495.28986)">
<path
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
sodipodi:ry="8"
sodipodi:rx="8"
sodipodi:cy="118"
@@ -48245,7 +50223,7 @@
sodipodi:cy="118"
sodipodi:rx="8"
sodipodi:ry="8"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90"
@@ -48255,7 +50233,7 @@
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
sodipodi:ry="8"
sodipodi:rx="8"
sodipodi:cy="118"
@@ -48268,7 +50246,7 @@
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
sodipodi:ry="8"
sodipodi:rx="8"
sodipodi:cy="118"
@@ -48292,7 +50270,7 @@
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
sodipodi:ry="8"
sodipodi:rx="8"
sodipodi:cy="118"
@@ -48304,7 +50282,7 @@
</g>
<g
style="display:inline"
- id="g22832"
+ id="ICON_MOD_CLOTH"
transform="translate(73,-15)">
<rect
style="opacity:0;fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
@@ -48396,7 +50374,7 @@
</g>
<g
transform="translate(-105,-229)"
- id="g22900"
+ id="ICON_PLAY_AUDIO"
style="display:inline">
<rect
style="opacity:0;fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
@@ -48514,7 +50492,7 @@
inkscape:connector-curvature="0" />
</g>
<g
- id="g23411"
+ id="ICON_MOD_EXPLODE"
transform="translate(-399,-19)">
<rect
transform="scale(-1,1)"
@@ -48549,7 +50527,7 @@
sodipodi:cy="-222"
sodipodi:rx="3.3084693"
sodipodi:ry="1.2798798"
- d="m 111.30847,-222 c 0,0.70686 -1.48125,1.27988 -3.30847,1.27988 -1.82722,0 -3.30847,-0.57302 -3.30847,-1.27988 0,-0.70686 1.48125,-1.27988 3.30847,-1.27988 1.82722,0 3.30847,0.57302 3.30847,1.27988 z"
+ d="M 111.30847,-222 A 3.3084693,1.2798798 0 0 1 108,-220.72012 3.3084693,1.2798798 0 0 1 104.69153,-222 3.3084693,1.2798798 0 0 1 108,-223.27988 3.3084693,1.2798798 0 0 1 111.30847,-222 Z"
transform="matrix(0.9067635,0,0,1.3047091,374.56954,447.97555)" />
<path
sodipodi:nodetypes="cccsccc"
@@ -48743,7 +50721,7 @@
</g>
</g>
<g
- id="g22853"
+ id="ICON_MOD_MESHDEFORM"
transform="translate(4.2e-4,2.056923)">
<g
style="display:inline"
@@ -48878,7 +50856,7 @@
</g>
</g>
<g
- id="g40939"
+ id="ICON_MOD_BUILD"
transform="translate(0,2)">
<rect
style="opacity:0;fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
@@ -48976,7 +50954,7 @@
</g>
</g>
<g
- id="g40825"
+ id="ICON_MOD_BOOLEAN"
transform="translate(0,1)">
<rect
y="260"
@@ -49047,11 +51025,9 @@
</g>
</g>
<g
- id="g23613" />
- <g
style="display:inline;enable-background:new"
transform="translate(404,214.02012)"
- id="g13021">
+ id="ICON_MOD_BEVEL">
<rect
style="opacity:0;fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
id="rect12989"
@@ -49103,116 +51079,7 @@
</g>
</g>
<g
- style="display:inline;enable-background:new"
- transform="translate(-0.9999998,2.020123)"
- id="g23516">
- <rect
- style="opacity:0;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.29999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- id="rect23518"
- width="16"
- height="16"
- x="489"
- y="260" />
- <path
- sodipodi:nodetypes="cssc"
- d="m 499.5,261.50004 -4.5,2 c -1.94148,0.86288 -2.18285,2.53884 -3,4.5 l -1.25,3"
- style="fill:none;stroke:#0b1728;stroke-width:2.79999995;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- id="path23520"
- inkscape:connector-curvature="0" />
- <path
- sodipodi:nodetypes="cccccccccc"
- id="path23522"
- d="m 503,268.00008 0,2.99996 -3,1.5 c -3,1.5 -6.25,1.5 -10,1.49996 l 0,-2.49996 c 0.5,-0.99996 1.75,-2.75004 5,-4.00004 l 4,-1.5 1,0 3,1.25 0,0.75008 z"
- style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#0b1728;stroke-width:1.79999995;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline;enable-background:new"
- inkscape:connector-curvature="0" />
- <path
- id="path23524"
- d="m 495,267.5 4,-1.5 1,0 3,1.25 0,0.75004 0,2.75 -3,1.5 -10,1.5 0,-1.75 c 0.5,-1 1.77456,-3.24182 5,-4.50004 z"
- style="fill:#c2d4ef;fill-opacity:1;fill-rule:evenodd;stroke:none;display:inline;enable-background:new"
- sodipodi:nodetypes="cccccccccc"
- inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\4.png"
- inkscape:export-xdpi="90"
- inkscape:export-ydpi="90"
- inkscape:connector-curvature="0" />
- <path
- id="path23542"
- style="fill:none;stroke:url(#linearGradient23555);stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- d="m 496.75,263.00004 c -3,1.5 -2.75,8.5 2.25,7"
- sodipodi:nodetypes="cc"
- inkscape:connector-curvature="0" />
- <path
- style="fill:url(#linearGradient23581);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.89207077px;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- d="m 519.82031,262 c 0.5,-0.16016 0.35115,-1.44373 -0.66015,-1 l -3.91016,1.75 c -2.5,0.75 -2.85099,2.90496 -3.82813,5.08203 L 510,271 l 0,3 c 3.76795,10e-6 7,0 10,-1.5 0.59071,-0.29535 2.31945,-1.15973 3,-1.5 l 0,-3 c -0.71506,0.35798 -2.3836,1.1918 -3,1.5 -0.45529,0.22765 -0.90706,0.42996 -1.375,0.59375 -4.60397,1.02313 -4.54405,-5.38421 -1.625,-6.84375 l 2.82031,-1.25 z"
- transform="translate(-20,0)"
- id="path23526"
- sodipodi:nodetypes="cccsccsccsccc"
- inkscape:connector-curvature="0" />
- <path
- inkscape:export-ydpi="90"
- inkscape:export-xdpi="90"
- inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\4.png"
- style="fill:none;stroke:url(#linearGradient23550);stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- d="m 490.5,273.51739 c 3.76795,0 5.75,-4e-5 8.75,-1.25004 0.60963,-0.25401 2.56945,-1.15973 3.25,-1.5"
- id="path23528"
- sodipodi:nodetypes="csc"
- inkscape:connector-curvature="0" />
- <rect
- style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.20000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- id="rect23530"
- width="2"
- height="1"
- x="497"
- y="267" />
- <g
- id="g23575"
- style="fill:#000000">
- <rect
- style="opacity:0.8;fill:#162d50;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.20000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- id="rect23532"
- width="2"
- height="1"
- x="497"
- y="268" />
- <rect
- y="267"
- x="496"
- height="1.5"
- width="1"
- id="rect23534"
- style="opacity:0.6;fill:#162d50;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.20000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
- <rect
- style="opacity:0.6;fill:#162d50;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.20000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- id="rect23536"
- width="1"
- height="1.5"
- x="499"
- y="267" />
- <rect
- y="266.5"
- x="497"
- height="0.5"
- width="2"
- id="rect23538"
- style="opacity:0.5;fill:#162d50;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.20000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
- </g>
- <path
- sodipodi:nodetypes="csc"
- id="path23540"
- d="m 490.5,272.5 c 3.76795,0 5.75,-4e-5 8.75,-1.25004 0.60963,-0.25401 2.56945,-1.15973 3.25,-1.5"
- style="fill:none;stroke:url(#linearGradient23585);stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\4.png"
- inkscape:export-xdpi="90"
- inkscape:export-ydpi="90"
- inkscape:connector-curvature="0" />
- <path
- id="path23546"
- style="opacity:0.8;fill:none;stroke:#ffffff;stroke-width:1.20000005;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- d="m 499.5,261.50004 -3.07779,1.36791 L 495,263.50004 c -1.94148,0.86288 -2.18285,2.53884 -3,4.5 l -1.25,3"
- sodipodi:nodetypes="ccssc"
- inkscape:connector-curvature="0" />
- </g>
- <g
- id="g23587"
+ id="ICON_CONSTRAINT_DATA"
transform="translate(-42.01991,-103.9242)">
<rect
transform="matrix(0,-1,1,0,0,0)"
@@ -49289,7 +51156,7 @@
</g>
</g>
<g
- id="g22800"
+ id="ICON_MOD_SIMPLEDEFORM"
transform="translate(-21,2)">
<rect
y="260"
@@ -49331,7 +51198,7 @@
inkscape:connector-curvature="0" />
</g>
<g
- id="g23347"
+ id="ICON_TEXTURE_SHADED"
transform="translate(251.98387,128)"
style="display:inline">
<rect
@@ -49356,7 +51223,7 @@
inkscape:export-ydpi="90"
transform="matrix(1.0004639,0,0,0.9963165,-237.11238,367.28985)">
<path
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
sodipodi:ry="8"
sodipodi:rx="8"
sodipodi:cy="118"
@@ -49377,7 +51244,7 @@
sodipodi:cy="118"
sodipodi:rx="8"
sodipodi:ry="8"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90" />
@@ -49386,7 +51253,7 @@
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
sodipodi:ry="8"
sodipodi:rx="8"
sodipodi:cy="118"
@@ -49414,7 +51281,7 @@
sodipodi:cy="118"
sodipodi:rx="8"
sodipodi:ry="8"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90"
@@ -49423,7 +51290,7 @@
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
sodipodi:ry="8"
sodipodi:rx="8"
sodipodi:cy="118"
@@ -49440,7 +51307,7 @@
</g>
</g>
<g
- id="g22826"
+ id="ICON_MOD_MASK"
transform="translate(21,-18.979877)">
<rect
y="281"
@@ -49550,7 +51417,7 @@
</g>
</g>
<g
- id="g24003"
+ id="ICON_SNAP_VOLUME"
transform="translate(210,-37)"
style="display:inline">
<g
@@ -49648,7 +51515,7 @@
transform="translate(-1081.9421,-238.02038)" />
</g>
<g
- id="g24311"
+ id="ICON_ORTHO"
transform="translate(-16.99965,-228.99997)">
<g
style="opacity:0.55"
@@ -49828,21 +51695,8 @@
inkscape:connector-curvature="0" />
</g>
</g>
- <rect
- style="opacity:0.01000001;fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- id="rect23719"
- width="0"
- height="0"
- x="547"
- y="255" />
- <g
- id="g24088"
- transform="translate(341,-57.00032)" />
<g
- transform="translate(361,-56.00032)"
- id="g24276" />
- <g
- id="g23953"
+ id="ICON_MONKEY"
transform="translate(-60,60)">
<rect
y="-29"
@@ -49902,11 +51756,11 @@
sodipodi:cy="-23"
sodipodi:rx="1"
sodipodi:ry="1"
- d="m 134,-23 c 0,0.552285 -0.44772,1 -1,1 -0.55228,0 -1,-0.447715 -1,-1 0,-0.552285 0.44772,-1 1,-1 0.55228,0 1,0.447715 1,1 z"
+ d="m 134,-23 a 1,1 0 0 1 -1,1 1,1 0 0 1 -1,-1 1,1 0 0 1 1,-1 1,1 0 0 1 1,1 z"
transform="translate(0.5,-0.46875)" />
<path
transform="matrix(1.2143583,0,0,1.1512108,-28.054112,2.9290602)"
- d="m 134,-23 c 0,0.552285 -0.44772,1 -1,1 -0.55228,0 -1,-0.447715 -1,-1 0,-0.552285 0.44772,-1 1,-1 0.55228,0 1,0.447715 1,1 z"
+ d="m 134,-23 a 1,1 0 0 1 -1,1 1,1 0 0 1 -1,-1 1,1 0 0 1 1,-1 1,1 0 0 1 1,1 z"
sodipodi:ry="1"
sodipodi:rx="1"
sodipodi:cy="-23"
@@ -49916,7 +51770,7 @@
sodipodi:type="arc" />
<path
transform="matrix(0.8392157,0,0,0.8382979,21.884318,-4.2140957)"
- d="m 134,-23 c 0,0.552285 -0.44772,1 -1,1 -0.55228,0 -1,-0.447715 -1,-1 0,-0.552285 0.44772,-1 1,-1 0.55228,0 1,0.447715 1,1 z"
+ d="m 134,-23 a 1,1 0 0 1 -1,1 1,1 0 0 1 -1,-1 1,1 0 0 1 1,-1 1,1 0 0 1 1,1 z"
sodipodi:ry="1"
sodipodi:rx="1"
sodipodi:cy="-23"
@@ -49945,7 +51799,7 @@
sodipodi:cy="-23"
sodipodi:rx="1"
sodipodi:ry="1"
- d="m 134,-23 c 0,0.552285 -0.44772,1 -1,1 -0.55228,0 -1,-0.447715 -1,-1 0,-0.552285 0.44772,-1 1,-1 0.55228,0 1,0.447715 1,1 z"
+ d="m 134,-23 a 1,1 0 0 1 -1,1 1,1 0 0 1 -1,-1 1,1 0 0 1 1,-1 1,1 0 0 1 1,1 z"
transform="matrix(1.2116904,0,0,1.1282344,-22.693138,2.3776257)" />
<path
sodipodi:type="arc"
@@ -49955,7 +51809,7 @@
sodipodi:cy="-23"
sodipodi:rx="1"
sodipodi:ry="1"
- d="m 134,-23 c 0,0.552285 -0.44772,1 -1,1 -0.55228,0 -1,-0.447715 -1,-1 0,-0.552285 0.44772,-1 1,-1 0.55228,0 1,0.447715 1,1 z"
+ d="m 134,-23 a 1,1 0 0 1 -1,1 1,1 0 0 1 -1,-1 1,1 0 0 1 1,-1 1,1 0 0 1 1,1 z"
transform="matrix(0.8392157,0,0,0.8382979,26.893134,-4.2140957)" />
<path
style="fill:none;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
@@ -49979,7 +51833,7 @@
</g>
<g
style="display:inline;enable-background:new"
- id="g24504"
+ id="ICON_MOD_SHRINKWRAP"
transform="translate(-21,-19)">
<rect
style="opacity:0;fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
@@ -50032,7 +51886,7 @@
inkscape:connector-curvature="0" />
<path
transform="matrix(0.9067635,0,0,1.2421435,374.56954,430.00586)"
- d="m 111.30847,-222 c 0,0.70686 -1.48125,1.27988 -3.30847,1.27988 -1.82722,0 -3.30847,-0.57302 -3.30847,-1.27988 0,-0.70686 1.48125,-1.27988 3.30847,-1.27988 1.82722,0 3.30847,0.57302 3.30847,1.27988 z"
+ d="M 111.30847,-222 A 3.3084693,1.2798798 0 0 1 108,-220.72012 3.3084693,1.2798798 0 0 1 104.69153,-222 3.3084693,1.2798798 0 0 1 108,-223.27988 3.3084693,1.2798798 0 0 1 111.30847,-222 Z"
sodipodi:ry="1.2798798"
sodipodi:rx="3.3084693"
sodipodi:cy="-222"
@@ -50085,7 +51939,7 @@
</g>
</g>
<g
- id="g24095"
+ id="ICON_MOD_CAST"
transform="translate(126,23)">
<g
style="opacity:0.45;display:inline"
@@ -50109,7 +51963,7 @@
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
sodipodi:ry="8"
sodipodi:rx="8"
sodipodi:cy="118"
@@ -50126,7 +51980,7 @@
sodipodi:cy="118"
sodipodi:rx="8"
sodipodi:ry="8"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90"
@@ -50140,7 +51994,7 @@
sodipodi:cy="118"
sodipodi:rx="8"
sodipodi:ry="8"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90" />
@@ -50182,7 +52036,7 @@
sodipodi:cy="118"
sodipodi:rx="8"
sodipodi:ry="8"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90" />
@@ -50195,7 +52049,7 @@
sodipodi:cy="118"
sodipodi:rx="8"
sodipodi:ry="8"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90" />
@@ -50216,7 +52070,7 @@
</g>
<g
style="display:inline;enable-background:new"
- id="g41107"
+ id="ICON_MOD_SOFT"
transform="translate(0,2)">
<rect
style="opacity:0;fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
@@ -50271,7 +52125,7 @@
</g>
<g
style="display:inline;enable-background:new"
- id="g41132"
+ id="ICON_POSE_DATA"
transform="translate(237.98389,298.06154)">
<rect
inkscape:export-ydpi="90"
@@ -50327,7 +52181,7 @@
</g>
<g
style="display:inline;enable-background:new"
- id="g41146"
+ id="ICON_ARMATURE_DATA"
transform="translate(78,299.00001)">
<rect
style="opacity:0;fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
@@ -50400,7 +52254,7 @@
</g>
<g
transform="translate(28.983879,319.02657)"
- id="g41999"
+ id="ICON_POSE_HLT"
style="display:inline;enable-background:new">
<rect
style="opacity:0;fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
@@ -50497,7 +52351,7 @@
</g>
<g
transform="translate(120,68)"
- id="g42071"
+ id="ICON_MOD_ARMATURE"
style="display:inline;enable-background:new">
<rect
y="194"
@@ -50570,7 +52424,7 @@
</g>
<g
transform="translate(-111,236)"
- id="g42095"
+ id="ICON_OUTLINER_OB_ARMATURE"
style="display:inline;enable-background:new">
<rect
y="194"
@@ -50652,7 +52506,7 @@
</g>
<g
transform="translate(113.22629,214.3098)"
- id="g42123"
+ id="ICON_OUTLINER_DATA_POSE"
style="display:inline;enable-background:new">
<rect
style="opacity:0;fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
@@ -50746,7 +52600,7 @@
</g>
</g>
<g
- id="g42258"
+ id="ICON_OUTLINER_DATA_ARMATURE"
transform="translate(0,86)">
<g
transform="translate(-111,129)"
@@ -50860,26 +52714,7 @@
</g>
</g>
<g
- id="g22051"
- transform="translate(67,200.06499)"
- inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
- inkscape:export-xdpi="90"
- inkscape:export-ydpi="90"
- style="display:inline" />
- <g
- id="g40816"
- transform="translate(-23,0)">
- <g
- id="g40830" />
- </g>
- <g
- id="g23451"
- transform="translate(-393.99971,438.98222)" />
- <g
- id="g23461"
- transform="matrix(0.8342485,0,0,0.8354168,-433.47749,469.22699)" />
- <g
- id="g23710"
+ id="ICON_PLUG"
transform="translate(399,24.000007)"
inkscape:export-filename="C:\Documents and Settings\Pracownia\Moje dokumenty\Moje obrazy\BLENDER ICONS redesign\RELEASES\x.png"
inkscape:export-xdpi="90"
@@ -50924,7 +52759,7 @@
</g>
<path
transform="matrix(0.9,0,0,0.9,7.6,60.3)"
- d="m 80.166667,603 c 0,2.30119 -1.865481,4.16667 -4.166667,4.16667 -2.301186,0 -4.166667,-1.86548 -4.166667,-4.16667 0,-2.30119 1.865481,-4.16667 4.166667,-4.16667 2.301186,0 4.166667,1.86548 4.166667,4.16667 z"
+ d="M 80.166667,603 A 4.1666665,4.1666665 0 0 1 76,607.16667 4.1666665,4.1666665 0 0 1 71.833333,603 4.1666665,4.1666665 0 0 1 76,598.83333 4.1666665,4.1666665 0 0 1 80.166667,603 Z"
sodipodi:ry="4.1666665"
sodipodi:rx="4.1666665"
sodipodi:cy="603"
@@ -50947,18 +52782,8 @@
x="77"
y="602" />
</g>
- <rect
- inkscape:export-ydpi="90"
- inkscape:export-xdpi="90"
- inkscape:export-filename="C:\Documents and Settings\Pracownia\Pulpit\s.png"
- y="262"
- x="194"
- height="16"
- width="16"
- id="rect23619"
- style="opacity:0;fill:#808080;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.89401144px;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
- <g
- id="g23350"
+ <g
+ id="ICON_PARTICLES"
transform="translate(0,128.00001)">
<rect
y="427.99997"
@@ -51319,7 +53144,7 @@
</g>
</g>
<g
- id="g23415"
+ id="ICON_PARTICLE_DATA"
transform="translate(62.999992,65.000007)">
<rect
style="opacity:0;fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.89401144px;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
@@ -51680,368 +53505,381 @@
</g>
</g>
<g
- transform="translate(-21.000008,-166)"
- id="g23639">
+ id="ICON_MOD_PARTICLES">
<rect
- y="427.99997"
- x="215"
- height="16"
+ style="opacity:0;fill:#808080;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.89401144px;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect23619"
width="16"
- id="rect23641"
- style="opacity:0;fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.89401144px;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
- <rect
- inkscape:export-ydpi="90"
- inkscape:export-xdpi="90"
- inkscape:export-filename="C:\Documents and Settings\Pracownia\Pulpit\s.png"
- y="427.99997"
- x="215"
height="16"
- width="16"
- id="rect23643"
- style="opacity:0;fill:#808080;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.89401144px;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ x="194"
+ y="262"
+ inkscape:export-filename="C:\Documents and Settings\Pracownia\Pulpit\s.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
<g
- id="g23645">
- <g
- id="g23647">
- <g
- id="g23649">
- <path
- inkscape:transform-center-y="-1.75"
- sodipodi:nodetypes="ccccccc"
- id="path23651"
- d="m 229.97728,432.50003 0,0 -2.86364,-0.81818 -1.22727,0.20455 0,1.22727 1.22727,0.20455 2.86364,-0.81819 0,0 0,0 0,0 z"
- style="fill:none;stroke:url(#linearGradient23797);stroke-width:2.04545569;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- inkscape:connector-curvature="0" />
- <path
- inkscape:transform-center-y="-1.75"
- sodipodi:nodetypes="ccccccc"
- id="path23653"
- d="m 226.5,435.97731 0,0 0.81819,-2.86364 -0.20455,-1.22727 -1.22727,0 -0.20455,1.22727 0.81818,2.86364 0,0 0,0 0,0 z"
- style="fill:none;stroke:url(#linearGradient23799);stroke-width:2.04545569;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- inkscape:connector-curvature="0" />
- <path
- inkscape:transform-center-y="-1.75"
- sodipodi:nodetypes="ccccccc"
- id="path23655"
- d="m 223.02273,432.50003 0,0 2.86364,0.81819 1.22727,-0.20455 0,-1.22727 -1.22727,-0.20455 -2.86364,0.81818 0,0 0,0 0,0 z"
- style="fill:none;stroke:url(#linearGradient23801);stroke-width:2.04545569;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- inkscape:connector-curvature="0" />
- <path
- inkscape:transform-center-y="-1.75"
- sodipodi:nodetypes="ccccccc"
- id="path23668"
- d="m 226.5,429.02276 0,0 -0.81818,2.86364 0.20455,1.22727 1.22727,0 0.20455,-1.22727 -0.81819,-2.86364 0,0 0,0 0,0 z"
- style="fill:none;stroke:url(#linearGradient23803);stroke-width:2.04500008;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- inkscape:connector-curvature="0" />
- </g>
- <g
- id="g23670">
- <path
- inkscape:transform-center-y="-1.75"
- id="path23672"
- d="m 226.09091,428.00003 -0.4091,3.68182 0.20455,1.43182 1.22727,0 0.20455,-1.43182 -0.40909,-3.68182 -0.81818,0 0,0 0,0 0,0 z"
- style="fill:url(#linearGradient23805);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- sodipodi:nodetypes="ccccccc"
- inkscape:connector-curvature="0" />
- <path
- inkscape:transform-center-y="-1.75"
- id="path23674"
- d="m 231,432.09094 -3.68182,-0.40909 -1.43182,0.20454 0,1.22728 1.43182,0.20454 3.68182,-0.40909 0,-0.81818 0,0 0,0 0,0 z"
- style="fill:url(#linearGradient23807);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- sodipodi:nodetypes="ccccccc"
- inkscape:connector-curvature="0" />
- <path
- inkscape:transform-center-y="-1.75"
- id="path23676"
- d="m 226.09091,437.00003 -0.4091,-3.68182 0.20455,-1.43182 1.22727,0 0.20455,1.43182 -0.40909,3.68182 -0.81818,0 0,0 0,0 0,0 z"
- style="fill:url(#linearGradient23809);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- sodipodi:nodetypes="ccccccc"
- inkscape:connector-curvature="0" />
- <path
- inkscape:transform-center-y="-1.75"
- id="path23678"
- d="m 221.99999,432.90912 3.68182,0.40909 1.43182,-0.20454 0,-1.22728 -1.43182,-0.20454 -3.68182,0.40909 0,0.81818 0,0 0,0 0,0 z"
- style="fill:url(#linearGradient23811);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- sodipodi:nodetypes="ccccccc"
- inkscape:connector-curvature="0" />
- </g>
- <g
- transform="translate(141,-197.00002)"
- id="g23680">
- <rect
- y="628.25"
- x="85"
- height="2.5"
- width="1"
- id="rect23682"
- style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:5;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
- <rect
- transform="matrix(0,1,-1,0,0,0)"
- style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:5;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- id="rect23684"
- width="1"
- height="2.5"
- x="629"
- y="-86.75" />
- </g>
- </g>
+ id="g23639"
+ transform="translate(-21.000008,-166)">
+ <rect
+ style="opacity:0;fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.89401144px;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect23641"
+ width="16"
+ height="16"
+ x="215"
+ y="427.99997" />
+ <rect
+ style="opacity:0;fill:#808080;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.89401144px;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect23643"
+ width="16"
+ height="16"
+ x="215"
+ y="427.99997"
+ inkscape:export-filename="C:\Documents and Settings\Pracownia\Pulpit\s.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
<g
- id="g23686"
- transform="translate(0,-4)">
- <g
- id="g23688">
- <path
- inkscape:transform-center-y="-1.75"
- sodipodi:nodetypes="ccccccc"
- id="path23690"
- d="m 224.75,442.5 0,0 -3.5,-1 -1.5,0.25 0,1.5 1.5,0.25 3.5,-1 z"
- style="fill:none;stroke:url(#linearGradient23813);stroke-width:2.5;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- inkscape:connector-curvature="0" />
- <path
- inkscape:transform-center-y="-1.75"
- sodipodi:nodetypes="ccccccc"
- id="path23692"
- d="m 220.5,446.75 0,0 0.75001,-3.5 -1e-5,-1.5 -1.5,0 1e-5,1.5 0.74999,3.5 z"
- style="fill:none;stroke:url(#linearGradient23815);stroke-width:2.5;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- inkscape:connector-curvature="0" />
- <path
- inkscape:transform-center-y="-1.75"
- sodipodi:nodetypes="ccccccc"
- id="path23695"
- d="m 216.25,442.5 0,0 3.50001,0.75 1.49999,0 0,-1.5 -1.49999,0 -3.50001,0.75 z"
- style="fill:none;stroke:url(#linearGradient23817);stroke-width:2.5;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- inkscape:connector-curvature="0" />
- <path
- inkscape:transform-center-y="-1.75"
- sodipodi:nodetypes="ccccccc"
- id="path23697"
- d="m 220.5,438.25 0,0 -0.74999,3.75 -1e-5,1.25 1.5,0 1e-5,-1.25 -0.75001,-3.75 z"
- style="fill:none;stroke:url(#linearGradient23819);stroke-width:2.5;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- inkscape:connector-curvature="0" />
- </g>
+ id="g23645">
<g
- id="g23700">
- <path
- inkscape:transform-center-y="-1.75"
- id="path23702"
- d="m 220,437 -0.5,4.5 0.25,1.75 1.5,0 0.25,-1.75 -0.5,-4.5 -1,0 z"
- style="fill:url(#linearGradient23821);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- sodipodi:nodetypes="ccccccc"
- inkscape:connector-curvature="0" />
- <path
- inkscape:transform-center-y="-1.75"
- id="path23704"
- d="m 226,442 -4.5,-0.5 -1.75,0.25 0,1.5 1.75,0.25 4.5,-0.5 0,-1 z"
- style="fill:url(#linearGradient23823);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- sodipodi:nodetypes="ccccccc"
- inkscape:connector-curvature="0" />
- <path
- inkscape:transform-center-y="-1.75"
- id="path23706"
- d="m 220,448 -0.5,-4.5 0.25,-1.75 1.5,0 0.25,1.75 -0.5,4.5 -1,0 z"
- style="fill:url(#linearGradient23825);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- sodipodi:nodetypes="ccccccc"
- inkscape:connector-curvature="0" />
- <path
- inkscape:transform-center-y="-1.75"
- id="path23708"
- d="m 215,443 4.5,0.5 1.75,-0.25 0,-1.5 -1.75,-0.25 -4.5,0.5 0,1 z"
- style="fill:url(#linearGradient23827);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- sodipodi:nodetypes="ccccccc"
- inkscape:connector-curvature="0" />
- </g>
- <g
- transform="translate(135,-187.00002)"
- id="g23713">
- <rect
- y="628"
- x="85"
- height="2.9999599"
- width="1"
- id="rect23715"
- style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:5;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
- <rect
- transform="matrix(0,1,-1,0,0,0)"
- style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:5;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- id="rect23717"
- width="1"
- height="3"
- x="629"
- y="-87" />
+ id="g23647">
+ <g
+ id="g23649">
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:url(#linearGradient23797);stroke-width:2.04545569;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 229.97728,432.50003 0,0 -2.86364,-0.81818 -1.22727,0.20455 0,1.22727 1.22727,0.20455 2.86364,-0.81819 0,0 0,0 0,0 z"
+ id="path23651"
+ sodipodi:nodetypes="ccccccc"
+ inkscape:transform-center-y="-1.75" />
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:url(#linearGradient23799);stroke-width:2.04545569;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 226.5,435.97731 0,0 0.81819,-2.86364 -0.20455,-1.22727 -1.22727,0 -0.20455,1.22727 0.81818,2.86364 0,0 0,0 0,0 z"
+ id="path23653"
+ sodipodi:nodetypes="ccccccc"
+ inkscape:transform-center-y="-1.75" />
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:url(#linearGradient23801);stroke-width:2.04545569;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 223.02273,432.50003 0,0 2.86364,0.81819 1.22727,-0.20455 0,-1.22727 -1.22727,-0.20455 -2.86364,0.81818 0,0 0,0 0,0 z"
+ id="path23655"
+ sodipodi:nodetypes="ccccccc"
+ inkscape:transform-center-y="-1.75" />
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:url(#linearGradient23803);stroke-width:2.04500008;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 226.5,429.02276 0,0 -0.81818,2.86364 0.20455,1.22727 1.22727,0 0.20455,-1.22727 -0.81819,-2.86364 0,0 0,0 0,0 z"
+ id="path23668"
+ sodipodi:nodetypes="ccccccc"
+ inkscape:transform-center-y="-1.75" />
+ </g>
+ <g
+ id="g23670">
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccccc"
+ style="fill:url(#linearGradient23805);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 226.09091,428.00003 -0.4091,3.68182 0.20455,1.43182 1.22727,0 0.20455,-1.43182 -0.40909,-3.68182 -0.81818,0 0,0 0,0 0,0 z"
+ id="path23672"
+ inkscape:transform-center-y="-1.75" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccccc"
+ style="fill:url(#linearGradient23807);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 231,432.09094 -3.68182,-0.40909 -1.43182,0.20454 0,1.22728 1.43182,0.20454 3.68182,-0.40909 0,-0.81818 0,0 0,0 0,0 z"
+ id="path23674"
+ inkscape:transform-center-y="-1.75" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccccc"
+ style="fill:url(#linearGradient23809);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 226.09091,437.00003 -0.4091,-3.68182 0.20455,-1.43182 1.22727,0 0.20455,1.43182 -0.40909,3.68182 -0.81818,0 0,0 0,0 0,0 z"
+ id="path23676"
+ inkscape:transform-center-y="-1.75" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccccc"
+ style="fill:url(#linearGradient23811);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 221.99999,432.90912 3.68182,0.40909 1.43182,-0.20454 0,-1.22728 -1.43182,-0.20454 -3.68182,0.40909 0,0.81818 0,0 0,0 0,0 z"
+ id="path23678"
+ inkscape:transform-center-y="-1.75" />
+ </g>
+ <g
+ id="g23680"
+ transform="translate(141,-197.00002)">
+ <rect
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:5;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect23682"
+ width="1"
+ height="2.5"
+ x="85"
+ y="628.25" />
+ <rect
+ y="-86.75"
+ x="629"
+ height="2.5"
+ width="1"
+ id="rect23684"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:5;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ transform="matrix(0,1,-1,0,0,0)" />
+ </g>
</g>
- </g>
- <g
- id="g23719"
- transform="translate(0,4)">
- <path
- inkscape:transform-center-y="-1.25"
- sodipodi:nodetypes="ccccccc"
- id="path23728"
- d="m 218.75004,424.50004 -0.5,0 -0.50004,1.74996 0.25004,1.75004 1,0 0.24996,-1.75004 -0.49996,-1.74996 z"
- style="fill:none;stroke:url(#linearGradient23829);stroke-width:1.58491683;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- inkscape:connector-curvature="0" />
- <path
- style="fill:none;stroke:url(#linearGradient23831);stroke-width:1.58491683;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- d="m 221.50004,427.75004 0,-0.5 -1.74996,-0.50004 -1.75004,0.25004 0,1 1.75004,0.24996 1.74996,-0.49996 z"
- id="path23736"
- sodipodi:nodetypes="ccccccc"
- inkscape:transform-center-y="-1.25"
- inkscape:connector-curvature="0" />
- <path
- style="fill:none;stroke:url(#linearGradient23833);stroke-width:1.58491683;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- d="m 215.50004,427.25004 0,0.5 1.74996,0.50004 1.75004,-0.25004 0,-1 -1.75004,-0.24996 -1.74996,0.49996 z"
- id="path23738"
- sodipodi:nodetypes="ccccccc"
- inkscape:transform-center-y="-1.25"
- inkscape:connector-curvature="0" />
- <path
- style="fill:none;stroke:url(#linearGradient23835);stroke-width:1.58491683;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- d="m 218.25004,430.50004 0.5,0 0.50004,-1.74996 -0.25004,-1.75004 -1,0 -0.24996,1.75004 0.49996,1.74996 z"
- id="path23740"
- sodipodi:nodetypes="ccccccc"
- inkscape:transform-center-y="-1.25"
- inkscape:connector-curvature="0" />
- <path
- inkscape:transform-center-y="-1.49998"
- id="path23742"
- d="m 218.00004,424.00004 -0.12109,2.86328 0.1211,1.13676 0.99999,-4e-5 0.125,-1.125 -0.125,-2.875 -1,0 0,0 0,0 0,0 z"
- style="fill:url(#linearGradient23837);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- sodipodi:nodetypes="ccccccc"
- inkscape:connector-curvature="0" />
- <path
- sodipodi:nodetypes="ccccccc"
- style="fill:url(#linearGradient23839);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- d="m 222.00004,427.00004 -2.86328,-0.12109 -1.13676,0.12109 4e-5,1 1.125,0.125 2.875,-0.125 0,-1 z"
- id="path23744"
- inkscape:transform-center-y="-1.49998"
- inkscape:connector-curvature="0" />
- <path
- sodipodi:nodetypes="ccccccc"
- style="fill:url(#linearGradient23841);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- d="m 219.00004,431.00004 0.12109,-2.86328 -0.1211,-1.13676 -0.99999,4e-5 -0.125,1.125 0.125,2.875 1,0 0,0 0,0 0,0 z"
- id="path23746"
- inkscape:transform-center-y="-1.49998"
- inkscape:connector-curvature="0" />
- <path
- sodipodi:nodetypes="ccccccc"
- style="fill:url(#linearGradient23843);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- d="m 215.00004,428.00004 2.86328,0.12109 1.13676,-0.12109 -4e-5,-1 -1.125,-0.125 -2.875,0.125 0,1 z"
- id="path23748"
- inkscape:transform-center-y="-1.49998"
- inkscape:connector-curvature="0" />
<g
- transform="translate(133.00004,-201.99996)"
- id="g23751">
- <rect
- y="628.5"
- x="85"
- height="2"
- width="1"
- id="rect23753"
- style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:5;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
- <rect
- transform="matrix(0,1,-1,0,0,0)"
- style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:5;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- id="rect23755"
- width="1"
- height="2"
- x="629"
- y="-86.5" />
+ transform="translate(0,-4)"
+ id="g23686">
+ <g
+ id="g23688">
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:url(#linearGradient23813);stroke-width:2.5;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 224.75,442.5 0,0 -3.5,-1 -1.5,0.25 0,1.5 1.5,0.25 3.5,-1 z"
+ id="path23690"
+ sodipodi:nodetypes="ccccccc"
+ inkscape:transform-center-y="-1.75" />
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:url(#linearGradient23815);stroke-width:2.5;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 220.5,446.75 0,0 0.75001,-3.5 -1e-5,-1.5 -1.5,0 1e-5,1.5 0.74999,3.5 z"
+ id="path23692"
+ sodipodi:nodetypes="ccccccc"
+ inkscape:transform-center-y="-1.75" />
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:url(#linearGradient23817);stroke-width:2.5;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 216.25,442.5 0,0 3.50001,0.75 1.49999,0 0,-1.5 -1.49999,0 -3.50001,0.75 z"
+ id="path23695"
+ sodipodi:nodetypes="ccccccc"
+ inkscape:transform-center-y="-1.75" />
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:url(#linearGradient23819);stroke-width:2.5;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 220.5,438.25 0,0 -0.74999,3.75 -1e-5,1.25 1.5,0 1e-5,-1.25 -0.75001,-3.75 z"
+ id="path23697"
+ sodipodi:nodetypes="ccccccc"
+ inkscape:transform-center-y="-1.75" />
+ </g>
+ <g
+ id="g23700">
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccccc"
+ style="fill:url(#linearGradient23821);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 220,437 -0.5,4.5 0.25,1.75 1.5,0 0.25,-1.75 -0.5,-4.5 -1,0 z"
+ id="path23702"
+ inkscape:transform-center-y="-1.75" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccccc"
+ style="fill:url(#linearGradient23823);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 226,442 -4.5,-0.5 -1.75,0.25 0,1.5 1.75,0.25 4.5,-0.5 0,-1 z"
+ id="path23704"
+ inkscape:transform-center-y="-1.75" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccccc"
+ style="fill:url(#linearGradient23825);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 220,448 -0.5,-4.5 0.25,-1.75 1.5,0 0.25,1.75 -0.5,4.5 -1,0 z"
+ id="path23706"
+ inkscape:transform-center-y="-1.75" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccccc"
+ style="fill:url(#linearGradient23827);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 215,443 4.5,0.5 1.75,-0.25 0,-1.5 -1.75,-0.25 -4.5,0.5 0,1 z"
+ id="path23708"
+ inkscape:transform-center-y="-1.75" />
+ </g>
+ <g
+ id="g23713"
+ transform="translate(135,-187.00002)">
+ <rect
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:5;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect23715"
+ width="1"
+ height="2.9999599"
+ x="85"
+ y="628" />
+ <rect
+ y="-87"
+ x="629"
+ height="3"
+ width="1"
+ id="rect23717"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:5;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ transform="matrix(0,1,-1,0,0,0)" />
+ </g>
</g>
- </g>
- <g
- id="g23757"
- transform="translate(0,-4)">
<g
- transform="translate(0,-6.4549394)"
- id="g23759">
+ transform="translate(0,4)"
+ id="g23719">
<path
- inkscape:transform-center-y="-1.75"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:url(#linearGradient23829);stroke-width:1.58491683;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 218.75004,424.50004 -0.5,0 -0.50004,1.74996 0.25004,1.75004 1,0 0.24996,-1.75004 -0.49996,-1.74996 z"
+ id="path23728"
sodipodi:nodetypes="ccccccc"
- id="path23767"
- d="m 230.20453,450.95187 0,0 -2.22727,-0.63574 -0.95454,0.15894 0,0.9536 0.95454,0.15893 2.22727,-0.63573 0,0 0,0 0,0 z"
- style="fill:none;stroke:url(#linearGradient23845);stroke-width:1.59012127;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- inkscape:connector-curvature="0" />
+ inkscape:transform-center-y="-1.25" />
<path
- inkscape:transform-center-y="-1.75"
+ inkscape:connector-curvature="0"
+ inkscape:transform-center-y="-1.25"
sodipodi:nodetypes="ccccccc"
- id="path23770"
- d="m 227.49999,453.65374 0,0 0.63637,-2.22507 -0.15909,-0.9536 -0.95455,0 -0.15909,0.9536 0.63636,2.22507 z"
- style="fill:none;stroke:url(#linearGradient23847);stroke-width:1.59012127;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- inkscape:connector-curvature="0" />
+ id="path23736"
+ d="m 221.50004,427.75004 0,-0.5 -1.74996,-0.50004 -1.75004,0.25004 0,1 1.75004,0.24996 1.74996,-0.49996 z"
+ style="fill:none;stroke:url(#linearGradient23831);stroke-width:1.58491683;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
<path
- inkscape:transform-center-y="-1.75"
+ inkscape:connector-curvature="0"
+ inkscape:transform-center-y="-1.25"
sodipodi:nodetypes="ccccccc"
- id="path23774"
- d="m 224.79546,450.95187 0,0 2.22727,0.63574 0.95454,-0.15894 0,-0.9536 -0.95454,-0.15893 -2.22727,0.63573 0,0 0,0 0,0 z"
- style="fill:none;stroke:url(#linearGradient23849);stroke-width:1.59012127;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- inkscape:connector-curvature="0" />
+ id="path23738"
+ d="m 215.50004,427.25004 0,0.5 1.74996,0.50004 1.75004,-0.25004 0,-1 -1.75004,-0.24996 -1.74996,0.49996 z"
+ style="fill:none;stroke:url(#linearGradient23833);stroke-width:1.58491683;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
<path
- style="fill:none;stroke:url(#linearGradient23851);stroke-width:1.59012127;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- d="m 227.5,448.25 0,0 -0.63637,2.22507 0.15909,0.9536 0.95455,0 0.15909,-0.9536 L 227.5,448.25 z"
- id="path23776"
+ inkscape:connector-curvature="0"
+ inkscape:transform-center-y="-1.25"
sodipodi:nodetypes="ccccccc"
- inkscape:transform-center-y="-1.75"
- inkscape:connector-curvature="0" />
- </g>
- <g
- id="g23778">
+ id="path23740"
+ d="m 218.25004,430.50004 0.5,0 0.50004,-1.74996 -0.25004,-1.75004 -1,0 -0.24996,1.75004 0.49996,1.74996 z"
+ style="fill:none;stroke:url(#linearGradient23835);stroke-width:1.58491683;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
<path
- inkscape:transform-center-y="-1.75"
- id="path23780"
- d="m 227.18182,441.00653 -0.31818,2.86081 0.15909,1.11253 0.95454,0 0.15909,-1.11253 -0.31818,-2.86081 -0.63636,0 0,0 0,0 0,0 z"
- style="fill:url(#linearGradient23853);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccccc"
- inkscape:connector-curvature="0" />
+ style="fill:url(#linearGradient23837);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 218.00004,424.00004 -0.12109,2.86328 0.1211,1.13676 0.99999,-4e-5 0.125,-1.125 -0.125,-2.875 -1,0 0,0 0,0 0,0 z"
+ id="path23742"
+ inkscape:transform-center-y="-1.49998" />
<path
- inkscape:transform-center-y="-1.75"
- id="path23782"
- d="m 231,444.1852 -2.86364,-0.31786 -1.11363,0.15893 0,0.9536 1.11363,0.15894 2.86364,-0.31787 0,-0.63574 0,0 0,0 0,0 z"
- style="fill:url(#linearGradient23856);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- sodipodi:nodetypes="ccccccc"
- inkscape:connector-curvature="0" />
+ inkscape:connector-curvature="0"
+ inkscape:transform-center-y="-1.49998"
+ id="path23744"
+ d="m 222.00004,427.00004 -2.86328,-0.12109 -1.13676,0.12109 4e-5,1 1.125,0.125 2.875,-0.125 0,-1 z"
+ style="fill:url(#linearGradient23839);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ sodipodi:nodetypes="ccccccc" />
<path
- inkscape:transform-center-y="-1.75"
- id="path23784"
- d="m 227.18182,447.99961 -0.31818,-2.8608 0.15909,-1.11254 0.95454,0 0.15909,1.11254 -0.31818,2.8608 -0.63636,0 0,0 0,0 0,0 z"
- style="fill:url(#linearGradient23858);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- sodipodi:nodetypes="ccccccc"
- inkscape:connector-curvature="0" />
+ inkscape:connector-curvature="0"
+ inkscape:transform-center-y="-1.49998"
+ id="path23746"
+ d="m 219.00004,431.00004 0.12109,-2.86328 -0.1211,-1.13676 -0.99999,4e-5 -0.125,1.125 0.125,2.875 1,0 0,0 0,0 0,0 z"
+ style="fill:url(#linearGradient23841);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ sodipodi:nodetypes="ccccccc" />
<path
- inkscape:transform-center-y="-1.75"
- id="path23786"
- d="m 224.00001,444.82094 2.86363,0.31787 1.11363,-0.15894 0,-0.9536 -1.11363,-0.15893 -2.86363,0.31786 0,0.63574 0,0 0,0 0,0 z"
- style="fill:url(#linearGradient23860);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- sodipodi:nodetypes="ccccccc"
- inkscape:connector-curvature="0" />
- </g>
- <g
- id="g23788">
+ inkscape:connector-curvature="0"
+ inkscape:transform-center-y="-1.49998"
+ id="path23748"
+ d="m 215.00004,428.00004 2.86328,0.12109 1.13676,-0.12109 -4e-5,-1 -1.125,-0.125 -2.875,0.125 0,1 z"
+ style="fill:url(#linearGradient23843);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ sodipodi:nodetypes="ccccccc" />
<g
- transform="translate(141.99999,-184.99353)"
- id="g23791">
+ id="g23751"
+ transform="translate(133.00004,-201.99996)">
<rect
- y="628.5"
- x="85"
- height="2"
- width="1"
- id="rect23793"
- style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:5;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
- <rect
- transform="matrix(0,1,-1,0,0,0)"
style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:5;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- id="rect23795"
+ id="rect23753"
width="1"
height="2"
+ x="85"
+ y="628.5" />
+ <rect
+ y="-86.5"
x="629"
- y="-86.5" />
+ height="2"
+ width="1"
+ id="rect23755"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:5;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ transform="matrix(0,1,-1,0,0,0)" />
+ </g>
+ </g>
+ <g
+ transform="translate(0,-4)"
+ id="g23757">
+ <g
+ id="g23759"
+ transform="translate(0,-6.4549394)">
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:url(#linearGradient23845);stroke-width:1.59012127;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 230.20453,450.95187 0,0 -2.22727,-0.63574 -0.95454,0.15894 0,0.9536 0.95454,0.15893 2.22727,-0.63573 0,0 0,0 0,0 z"
+ id="path23767"
+ sodipodi:nodetypes="ccccccc"
+ inkscape:transform-center-y="-1.75" />
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:url(#linearGradient23847);stroke-width:1.59012127;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 227.49999,453.65374 0,0 0.63637,-2.22507 -0.15909,-0.9536 -0.95455,0 -0.15909,0.9536 0.63636,2.22507 z"
+ id="path23770"
+ sodipodi:nodetypes="ccccccc"
+ inkscape:transform-center-y="-1.75" />
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:url(#linearGradient23849);stroke-width:1.59012127;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 224.79546,450.95187 0,0 2.22727,0.63574 0.95454,-0.15894 0,-0.9536 -0.95454,-0.15893 -2.22727,0.63573 0,0 0,0 0,0 z"
+ id="path23774"
+ sodipodi:nodetypes="ccccccc"
+ inkscape:transform-center-y="-1.75" />
+ <path
+ inkscape:connector-curvature="0"
+ inkscape:transform-center-y="-1.75"
+ sodipodi:nodetypes="ccccccc"
+ id="path23776"
+ d="m 227.5,448.25 0,0 -0.63637,2.22507 0.15909,0.9536 0.95455,0 0.15909,-0.9536 L 227.5,448.25 z"
+ style="fill:none;stroke:url(#linearGradient23851);stroke-width:1.59012127;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ </g>
+ <g
+ id="g23778">
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccccc"
+ style="fill:url(#linearGradient23853);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 227.18182,441.00653 -0.31818,2.86081 0.15909,1.11253 0.95454,0 0.15909,-1.11253 -0.31818,-2.86081 -0.63636,0 0,0 0,0 0,0 z"
+ id="path23780"
+ inkscape:transform-center-y="-1.75" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccccc"
+ style="fill:url(#linearGradient23856);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 231,444.1852 -2.86364,-0.31786 -1.11363,0.15893 0,0.9536 1.11363,0.15894 2.86364,-0.31787 0,-0.63574 0,0 0,0 0,0 z"
+ id="path23782"
+ inkscape:transform-center-y="-1.75" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccccc"
+ style="fill:url(#linearGradient23858);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 227.18182,447.99961 -0.31818,-2.8608 0.15909,-1.11254 0.95454,0 0.15909,1.11254 -0.31818,2.8608 -0.63636,0 0,0 0,0 0,0 z"
+ id="path23784"
+ inkscape:transform-center-y="-1.75" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccccc"
+ style="fill:url(#linearGradient23860);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 224.00001,444.82094 2.86363,0.31787 1.11363,-0.15894 0,-0.9536 -1.11363,-0.15893 -2.86363,0.31786 0,0.63574 0,0 0,0 0,0 z"
+ id="path23786"
+ inkscape:transform-center-y="-1.75" />
+ </g>
+ <g
+ id="g23788">
+ <g
+ id="g23791"
+ transform="translate(141.99999,-184.99353)">
+ <rect
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:5;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect23793"
+ width="1"
+ height="2"
+ x="85"
+ y="628.5" />
+ <rect
+ y="-86.5"
+ x="629"
+ height="2"
+ width="1"
+ id="rect23795"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:5;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ transform="matrix(0,1,-1,0,0,0)" />
+ </g>
</g>
</g>
</g>
</g>
</g>
<g
- id="g24300"
+ id="ICON_BUTS"
transform="translate(-49,6.0000069)"
inkscape:export-filename="C:\Documents and Settings\Pracownia\Moje dokumenty\Moje obrazy\BLENDER ICONS redesign\RELEASES\g42357.png"
inkscape:export-xdpi="90"
@@ -52184,7 +54022,7 @@
</g>
</g>
<g
- id="g24339"
+ id="ICON_IMASEL"
transform="translate(0,128.00001)">
<rect
y="407"
@@ -52285,11 +54123,7 @@
</g>
</g>
<g
- style="fill:#d45500;fill-opacity:1;display:inline"
- transform="translate(-65,-169.00755)"
- id="g24176" />
- <g
- id="g24393"
+ id="ICON_FILESEL"
inkscape:export-filename="C:\Documents and Settings\Pracownia\Moje dokumenty\Moje obrazy\BLENDER ICONS redesign\RELEASES\g42357.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90"
@@ -52386,208 +54220,219 @@
</g>
</g>
<g
- id="g22846"
- transform="translate(84,86)">
+ id="ICON_OUTLINER_DATA_LAMP">
<rect
ry="0"
- y="323"
- x="26"
+ y="409"
+ x="110"
height="16"
width="16"
- id="rect22783"
+ id="rect15876"
style="opacity:0;fill:#4d4d4d;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:6;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
<g
- id="g22817">
- <path
- style="opacity:0.3;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
- d="m 38.5,327.9 c 0,1.37785 -0.5625,2.19999 -1.6875,3.29999 -1.125,1.1 0,3.3 -1.40625,3.3 l -2.8125,0 c -1.40625,0 -0.28125,-2.2 -1.40625,-3.3 -1.125,-1.1 -1.6875,-1.93254 -1.6875,-3.29999 0,-2.4288 2.016,-4.4 4.5,-4.4 2.484,0 4.5,1.9712 4.5,4.4 z"
- id="path22788"
- sodipodi:nodetypes="cssssssc"
- inkscape:connector-curvature="0" />
- <path
- sodipodi:nodetypes="cssssssc"
- id="path22790"
- d="m 38.5,327.9 c 0,1.37785 -0.5625,2.19999 -1.6875,3.29999 -1.125,1.1 0,3.3 -1.40625,3.3 l -2.8125,0 c -1.40625,0 -0.28125,-2.2 -1.40625,-3.3 -1.125,-1.1 -1.6875,-1.93254 -1.6875,-3.29999 0,-2.4288 2.016,-4.4 4.5,-4.4 2.484,0 4.5,1.9712 4.5,4.4 z"
- style="opacity:0.9;fill:none;stroke:#000000;stroke-width:0.80000001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
- inkscape:connector-curvature="0" />
- <path
- style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
- d="m 33,338 2,0 0,1 -2,-10e-6 L 33,338 z"
- id="path22792"
- sodipodi:nodetypes="ccccc"
- inkscape:connector-curvature="0" />
- <rect
- style="fill:#24221c;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- id="rect22794"
- width="6"
- height="4.75"
- x="31"
- y="333.25"
- rx="0.765625"
- ry="0.765625" />
- <rect
- y="334"
- x="32"
- height="3"
- width="4"
- id="rect22796"
- style="fill:#736c54;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
- <path
- transform="matrix(1.0666667,0,0,1,-233.7,254.00667)"
- style="fill:url(#linearGradient22892);fill-opacity:1;fill-rule:nonzero;stroke:none"
- d="m 249.09375,80 c -0.37566,0.05708 -0.59375,0.300736 -0.59375,0.5 0,0.227729 0.26882,0.500002 0.75,0.5 0.48959,-2e-6 2.86976,-0.0067 3.35937,-0.0067 0.4812,0 0.75,-0.272259 0.75,-0.5 0,-0.227736 -0.2688,-0.499998 -0.75,-0.5 L 249.25,80 c -0.0601,0 -0.10258,-0.0082 -0.15625,0 z m 0,2 c -0.37566,0.05708 -0.59375,0.300738 -0.59375,0.5 0,0.227729 0.26882,0.500003 0.75,0.5 l 3.35937,-0.0067 c 0.4812,0 0.75,-0.272257 0.75,-0.5 0,-0.227736 -0.2688,-0.499997 -0.75,-0.5 C 252.11976,81.993327 249.7396,82 249.25,82 c -0.0601,0 -0.10258,-0.0082 -0.15625,0 z"
- id="path22798"
- sodipodi:nodetypes="cssssccccsccsssc"
- inkscape:connector-curvature="0" />
- <path
- inkscape:export-ydpi="90"
- inkscape:export-xdpi="90"
- inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png"
- id="path22800"
- d="m 32.25,336.24999 1.25,0"
- style="fill:none;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
- inkscape:connector-curvature="0" />
- <path
- inkscape:export-ydpi="90"
- inkscape:export-xdpi="90"
- inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png"
- style="fill:none;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
- d="m 32.25,334.24999 1.25,0"
- id="path22802"
- inkscape:connector-curvature="0" />
- <rect
- y="336"
- x="37"
- height="1"
- width="0.25"
- id="rect22804"
- style="fill:#1a1a1a;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ transform="translate(84,86)"
+ id="g22846">
<rect
- style="fill:#1a1a1a;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- id="rect22807"
- width="0.25"
- height="1"
- x="37"
- y="334" />
- <rect
- style="fill:#1a1a1a;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- id="rect22809"
- width="0.25"
- height="1"
- x="30.75"
- y="336" />
- <rect
- y="334"
- x="30.75"
- height="1"
- width="0.25"
- id="rect22812"
- style="fill:#1a1a1a;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
- <path
- transform="matrix(1.1428575,0,0,1.1249998,-252.2858,245.25001)"
- d="m 250.5,70 c -1.92579,0 -3.5,1.570388 -3.5,3.5 0,1.036273 0.43284,1.981065 1.15625,2.625 0.12299,0.109481 0.35065,0.504334 0.5,0.875 0.0747,0.185333 0.1355,0.365966 0.21875,0.53125 0.0416,0.08264 0.0782,0.159602 0.15625,0.25 0.0781,0.0904 0.22443,0.218751 0.46875,0.21875 l 2,0 c 0.24442,0 0.3907,-0.128341 0.46875,-0.21875 0.078,-0.09041 0.11462,-0.167341 0.15625,-0.25 0.0832,-0.165318 0.14407,-0.345883 0.21875,-0.53125 0.14936,-0.370734 0.3774,-0.765984 0.5,-0.875 C 253.56794,75.481034 254,74.536495 254,73.5 254,71.570387 252.42579,70 250.5,70 z"
- id="path22814"
- style="fill:url(#linearGradient22954);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.61155295;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- inkscape:original="M 250.5 70.5 C 248.844 70.5 247.5 71.84032 247.5 73.5 C 247.5 74.394207 247.88111 75.199102 248.5 75.75 C 249.02979 76.22159 249.25 77.500001 249.5 77.5 C 249.75 77.5 251.25 77.500001 251.5 77.5 C 251.75 77.5 251.97036 76.220976 252.5 75.75 C 253.11956 75.199071 253.5 74.394767 253.5 73.5 C 253.5 71.840318 252.156 70.5 250.5 70.5 z "
- inkscape:radius="0.5"
- sodipodi:type="inkscape:offset" />
- <path
- sodipodi:type="inkscape:offset"
- inkscape:radius="0.5"
- inkscape:original="M 250.5 70.5 C 248.844 70.5 247.5 71.84032 247.5 73.5 C 247.5 74.394207 247.88111 75.199102 248.5 75.75 C 249.02979 76.22159 249.25 77.500001 249.5 77.5 C 249.75 77.5 251.25 77.500001 251.5 77.5 C 251.75 77.5 251.97036 76.220976 252.5 75.75 C 253.11956 75.199071 253.5 74.394767 253.5 73.5 C 253.5 71.840318 252.156 70.5 250.5 70.5 z "
- style="opacity:0.6;fill:url(#radialGradient22952);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.61155295;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- id="path22816"
- d="m 250.5,70 c -1.92579,0 -3.5,1.570388 -3.5,3.5 0,1.036273 0.43284,1.981065 1.15625,2.625 0.12299,0.109481 0.35065,0.504334 0.5,0.875 0.0747,0.185333 0.1355,0.365966 0.21875,0.53125 0.0416,0.08264 0.0782,0.159602 0.15625,0.25 0.0781,0.0904 0.22443,0.218751 0.46875,0.21875 l 2,0 c 0.24442,0 0.3907,-0.128341 0.46875,-0.21875 0.078,-0.09041 0.11462,-0.167341 0.15625,-0.25 0.0832,-0.165318 0.14407,-0.345883 0.21875,-0.53125 0.14936,-0.370734 0.3774,-0.765984 0.5,-0.875 C 253.56794,75.481034 254,74.536495 254,73.5 254,71.570387 252.42579,70 250.5,70 z"
- transform="matrix(1.1428578,0,0,1.1562502,-252.28587,242.81248)" />
- <path
- d="m 34.000001,324.48827 c 1.932,0 3.5,1.50111 3.5,3.35068 0,0.99715 -0.455735,1.89301 -1.178554,2.50697 -0.617914,0.52487 -1.154779,1.38605 -1.154779,2.77907 m -1.166667,-8.63672 c -1.932001,0 -3.500001,1.50111 -3.500001,3.35068 0,0.99715 0.455736,1.89301 1.178556,2.50697 0.617913,0.52487 1.154778,1.38605 1.154778,2.77907"
- style="fill:none;stroke:url(#linearGradient22928);stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dashoffset:0;display:inline"
- id="path22818"
- inkscape:connector-curvature="0" />
- <path
- transform="matrix(0.9552133,0,0,0.9315985,-40.901258,-140.2522)"
- d="m 80.53125,502 c 0,1.38071 -1.133279,2.5 -2.53125,2.5 -1.397971,0 -2.53125,-1.11929 -2.53125,-2.5 0,-1.38071 1.133279,-2.5 2.53125,-2.5 1.397971,0 2.53125,1.11929 2.53125,2.5 z"
- sodipodi:ry="2.5"
- sodipodi:rx="2.5312502"
- sodipodi:cy="502"
- sodipodi:cx="78"
- id="path22820"
- style="opacity:0.25;fill:url(#radialGradient22950);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.26754272;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- sodipodi:type="arc" />
- <path
- inkscape:export-ydpi="90"
- inkscape:export-xdpi="90"
- inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png"
- d="m 65,135 c 0,0.55228 -0.447715,1 -1,1 -0.552285,0 -1,-0.44772 -1,-1 0,-0.55228 0.447715,-1 1,-1 0.552285,0 1,0.44772 1,1 z"
- sodipodi:ry="1"
- sodipodi:rx="1"
- sodipodi:cy="135"
- sodipodi:cx="64"
- id="path22822"
- style="opacity:0.9;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.74699998;marker:none;display:inline"
- sodipodi:type="arc"
- transform="matrix(0.99567,0,-0.00787885,1,-30.663533,191)" />
- <path
- id="path22824"
- style="fill:none;stroke:url(#radialGradient22922);stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dashoffset:0;display:inline"
- d="m 34.000001,324.48827 c 1.932,0 3.5,1.50111 3.5,3.35068 0,0.99715 -0.455735,1.89301 -1.178554,2.50697 -0.617914,0.52487 -1.154779,1.38605 -1.154779,2.77907 m -1.166667,-8.63672 c -1.932001,0 -3.500001,1.50111 -3.500001,3.35068 0,0.99715 0.455736,1.89301 1.178556,2.50697 0.617913,0.52487 1.154778,1.38605 1.154778,2.77907"
- inkscape:connector-curvature="0" />
- <rect
- y="333"
- x="31.5"
- height="0.75"
- width="5"
- id="rect22826"
- style="opacity:0.85;fill:#3d3829;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.69999999;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
- <path
- sodipodi:nodetypes="ccccc"
- id="path22828"
- d="m 32.5,337.01145 3,-0.0115 0,1 -3,0.0114 0,-0.99999 0,9e-5 0,0 0,0 z"
- style="fill:#6c6753;fill-opacity:1;fill-rule:nonzero;stroke:none"
- inkscape:connector-curvature="0" />
- <path
- sodipodi:nodetypes="ccccc"
- id="path22830"
- d="m 33,330 0,2.75 2,0 0,-2.75 -2,0 z"
- style="opacity:0.2;fill:url(#linearGradient22917);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.69999999;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- inkscape:connector-curvature="0" />
- <rect
- y="328"
- x="32"
- height="1"
- width="1"
- id="rect22832"
- style="opacity:0.6;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:3.20000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
- <path
- d="m 32.875,333.12498 c 0,-1.39113 -0.517691,-2.25114 -1.113536,-2.77529 C 31.064459,329.73656 30.5,328.93567 30.5,327.93988 c 0,-1.84706 1.637,-3.43989 3.5,-3.43989 1.863,0 3.5,1.59283 3.5,3.43989 0,0.99579 -0.564459,1.79668 -1.261464,2.40981 -0.595845,0.52415 -1.113536,1.38416 -1.113536,2.77529"
- style="fill:none;stroke:url(#radialGradient23727);stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dashoffset:0;display:inline"
- id="path22836"
- sodipodi:nodetypes="csscssc"
- inkscape:connector-curvature="0" />
- <path
- sodipodi:nodetypes="ccccc"
- id="path22838"
- d="m 33,338.00001 0.5,0 0,1 L 33,339 l 0,-0.99999 z"
- style="opacity:0.3;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
- inkscape:connector-curvature="0" />
- <rect
- y="329"
- x="33"
- height="1"
- width="2"
- id="rect23759"
- style="opacity:0.8;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:3.20000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
- <rect
- style="opacity:0.6;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:3.20000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- id="rect23761"
- width="1"
- height="1"
- x="35"
- y="328" />
+ style="opacity:0;fill:#4d4d4d;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:6;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect22783"
+ width="16"
+ height="16"
+ x="26"
+ y="323"
+ ry="0" />
+ <g
+ id="g22817">
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cssssssc"
+ id="path22788"
+ d="m 38.5,327.9 c 0,1.37785 -0.5625,2.19999 -1.6875,3.29999 -1.125,1.1 0,3.3 -1.40625,3.3 l -2.8125,0 c -1.40625,0 -0.28125,-2.2 -1.40625,-3.3 -1.125,-1.1 -1.6875,-1.93254 -1.6875,-3.29999 0,-2.4288 2.016,-4.4 4.5,-4.4 2.484,0 4.5,1.9712 4.5,4.4 z"
+ style="opacity:0.3;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none" />
+ <path
+ inkscape:connector-curvature="0"
+ style="opacity:0.9;fill:none;stroke:#000000;stroke-width:0.80000001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ d="m 38.5,327.9 c 0,1.37785 -0.5625,2.19999 -1.6875,3.29999 -1.125,1.1 0,3.3 -1.40625,3.3 l -2.8125,0 c -1.40625,0 -0.28125,-2.2 -1.40625,-3.3 -1.125,-1.1 -1.6875,-1.93254 -1.6875,-3.29999 0,-2.4288 2.016,-4.4 4.5,-4.4 2.484,0 4.5,1.9712 4.5,4.4 z"
+ id="path22790"
+ sodipodi:nodetypes="cssssssc" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccc"
+ id="path22792"
+ d="m 33,338 2,0 0,1 -2,-10e-6 L 33,338 z"
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" />
+ <rect
+ ry="0.765625"
+ rx="0.765625"
+ y="333.25"
+ x="31"
+ height="4.75"
+ width="6"
+ id="rect22794"
+ style="fill:#24221c;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <rect
+ style="fill:#736c54;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect22796"
+ width="4"
+ height="3"
+ x="32"
+ y="334" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cssssccccsccsssc"
+ id="path22798"
+ d="m 249.09375,80 c -0.37566,0.05708 -0.59375,0.300736 -0.59375,0.5 0,0.227729 0.26882,0.500002 0.75,0.5 0.48959,-2e-6 2.86976,-0.0067 3.35937,-0.0067 0.4812,0 0.75,-0.272259 0.75,-0.5 0,-0.227736 -0.2688,-0.499998 -0.75,-0.5 L 249.25,80 c -0.0601,0 -0.10258,-0.0082 -0.15625,0 z m 0,2 c -0.37566,0.05708 -0.59375,0.300738 -0.59375,0.5 0,0.227729 0.26882,0.500003 0.75,0.5 l 3.35937,-0.0067 c 0.4812,0 0.75,-0.272257 0.75,-0.5 0,-0.227736 -0.2688,-0.499997 -0.75,-0.5 C 252.11976,81.993327 249.7396,82 249.25,82 c -0.0601,0 -0.10258,-0.0082 -0.15625,0 z"
+ style="fill:url(#linearGradient22892);fill-opacity:1;fill-rule:nonzero;stroke:none"
+ transform="matrix(1.0666667,0,0,1,-233.7,254.00667)" />
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ d="m 32.25,336.24999 1.25,0"
+ id="path22800"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path22802"
+ d="m 32.25,334.24999 1.25,0"
+ style="fill:none;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <rect
+ style="fill:#1a1a1a;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect22804"
+ width="0.25"
+ height="1"
+ x="37"
+ y="336" />
+ <rect
+ y="334"
+ x="37"
+ height="1"
+ width="0.25"
+ id="rect22807"
+ style="fill:#1a1a1a;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <rect
+ y="336"
+ x="30.75"
+ height="1"
+ width="0.25"
+ id="rect22809"
+ style="fill:#1a1a1a;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <rect
+ style="fill:#1a1a1a;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect22812"
+ width="0.25"
+ height="1"
+ x="30.75"
+ y="334" />
+ <path
+ sodipodi:type="inkscape:offset"
+ inkscape:radius="0.5"
+ inkscape:original="M 250.5 70.5 C 248.844 70.5 247.5 71.84032 247.5 73.5 C 247.5 74.394207 247.88111 75.199102 248.5 75.75 C 249.02979 76.22159 249.25 77.500001 249.5 77.5 C 249.75 77.5 251.25 77.500001 251.5 77.5 C 251.75 77.5 251.97036 76.220976 252.5 75.75 C 253.11956 75.199071 253.5 74.394767 253.5 73.5 C 253.5 71.840318 252.156 70.5 250.5 70.5 z "
+ style="fill:url(#linearGradient22954);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.61155295;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="path22814"
+ d="m 250.5,70 c -1.92579,0 -3.5,1.570388 -3.5,3.5 0,1.036273 0.43284,1.981065 1.15625,2.625 0.12299,0.109481 0.35065,0.504334 0.5,0.875 0.0747,0.185333 0.1355,0.365966 0.21875,0.53125 0.0416,0.08264 0.0782,0.159602 0.15625,0.25 0.0781,0.0904 0.22443,0.218751 0.46875,0.21875 l 2,0 c 0.24442,0 0.3907,-0.128341 0.46875,-0.21875 0.078,-0.09041 0.11462,-0.167341 0.15625,-0.25 0.0832,-0.165318 0.14407,-0.345883 0.21875,-0.53125 0.14936,-0.370734 0.3774,-0.765984 0.5,-0.875 C 253.56794,75.481034 254,74.536495 254,73.5 254,71.570387 252.42579,70 250.5,70 z"
+ transform="matrix(1.1428575,0,0,1.1249998,-252.2858,245.25001)" />
+ <path
+ transform="matrix(1.1428578,0,0,1.1562502,-252.28587,242.81248)"
+ d="m 250.5,70 c -1.92579,0 -3.5,1.570388 -3.5,3.5 0,1.036273 0.43284,1.981065 1.15625,2.625 0.12299,0.109481 0.35065,0.504334 0.5,0.875 0.0747,0.185333 0.1355,0.365966 0.21875,0.53125 0.0416,0.08264 0.0782,0.159602 0.15625,0.25 0.0781,0.0904 0.22443,0.218751 0.46875,0.21875 l 2,0 c 0.24442,0 0.3907,-0.128341 0.46875,-0.21875 0.078,-0.09041 0.11462,-0.167341 0.15625,-0.25 0.0832,-0.165318 0.14407,-0.345883 0.21875,-0.53125 0.14936,-0.370734 0.3774,-0.765984 0.5,-0.875 C 253.56794,75.481034 254,74.536495 254,73.5 254,71.570387 252.42579,70 250.5,70 z"
+ id="path22816"
+ style="opacity:0.6;fill:url(#radialGradient22952);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.61155295;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:original="M 250.5 70.5 C 248.844 70.5 247.5 71.84032 247.5 73.5 C 247.5 74.394207 247.88111 75.199102 248.5 75.75 C 249.02979 76.22159 249.25 77.500001 249.5 77.5 C 249.75 77.5 251.25 77.500001 251.5 77.5 C 251.75 77.5 251.97036 76.220976 252.5 75.75 C 253.11956 75.199071 253.5 74.394767 253.5 73.5 C 253.5 71.840318 252.156 70.5 250.5 70.5 z "
+ inkscape:radius="0.5"
+ sodipodi:type="inkscape:offset" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path22818"
+ style="fill:none;stroke:url(#linearGradient22928);stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dashoffset:0;display:inline"
+ d="m 34.000001,324.48827 c 1.932,0 3.5,1.50111 3.5,3.35068 0,0.99715 -0.455735,1.89301 -1.178554,2.50697 -0.617914,0.52487 -1.154779,1.38605 -1.154779,2.77907 m -1.166667,-8.63672 c -1.932001,0 -3.500001,1.50111 -3.500001,3.35068 0,0.99715 0.455736,1.89301 1.178556,2.50697 0.617913,0.52487 1.154778,1.38605 1.154778,2.77907" />
+ <path
+ sodipodi:type="arc"
+ style="opacity:0.25;fill:url(#radialGradient22950);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.26754272;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="path22820"
+ sodipodi:cx="78"
+ sodipodi:cy="502"
+ sodipodi:rx="2.5312502"
+ sodipodi:ry="2.5"
+ d="M 80.53125,502 A 2.5312502,2.5 0 0 1 78,504.5 2.5312502,2.5 0 0 1 75.46875,502 2.5312502,2.5 0 0 1 78,499.5 2.5312502,2.5 0 0 1 80.53125,502 Z"
+ transform="matrix(0.9552133,0,0,0.9315985,-40.901258,-140.2522)" />
+ <path
+ transform="matrix(0.99567,0,-0.00787885,1,-30.663533,191)"
+ sodipodi:type="arc"
+ style="opacity:0.9;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.74699998;marker:none;display:inline"
+ id="path22822"
+ sodipodi:cx="64"
+ sodipodi:cy="135"
+ sodipodi:rx="1"
+ sodipodi:ry="1"
+ d="m 65,135 a 1,1 0 0 1 -1,1 1,1 0 0 1 -1,-1 1,1 0 0 1 1,-1 1,1 0 0 1 1,1 z"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <path
+ inkscape:connector-curvature="0"
+ d="m 34.000001,324.48827 c 1.932,0 3.5,1.50111 3.5,3.35068 0,0.99715 -0.455735,1.89301 -1.178554,2.50697 -0.617914,0.52487 -1.154779,1.38605 -1.154779,2.77907 m -1.166667,-8.63672 c -1.932001,0 -3.500001,1.50111 -3.500001,3.35068 0,0.99715 0.455736,1.89301 1.178556,2.50697 0.617913,0.52487 1.154778,1.38605 1.154778,2.77907"
+ style="fill:none;stroke:url(#radialGradient22922);stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dashoffset:0;display:inline"
+ id="path22824" />
+ <rect
+ style="opacity:0.85;fill:#3d3829;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.69999999;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect22826"
+ width="5"
+ height="0.75"
+ x="31.5"
+ y="333" />
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:#6c6753;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ d="m 32.5,337.01145 3,-0.0115 0,1 -3,0.0114 0,-0.99999 0,9e-5 0,0 0,0 z"
+ id="path22828"
+ sodipodi:nodetypes="ccccc" />
+ <path
+ inkscape:connector-curvature="0"
+ style="opacity:0.2;fill:url(#linearGradient22917);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.69999999;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 33,330 0,2.75 2,0 0,-2.75 -2,0 z"
+ id="path22830"
+ sodipodi:nodetypes="ccccc" />
+ <rect
+ style="opacity:0.6;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:3.20000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect22832"
+ width="1"
+ height="1"
+ x="32"
+ y="328" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="csscssc"
+ id="path22836"
+ style="fill:none;stroke:url(#radialGradient23727);stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dashoffset:0;display:inline"
+ d="m 32.875,333.12498 c 0,-1.39113 -0.517691,-2.25114 -1.113536,-2.77529 C 31.064459,329.73656 30.5,328.93567 30.5,327.93988 c 0,-1.84706 1.637,-3.43989 3.5,-3.43989 1.863,0 3.5,1.59283 3.5,3.43989 0,0.99579 -0.564459,1.79668 -1.261464,2.40981 -0.595845,0.52415 -1.113536,1.38416 -1.113536,2.77529" />
+ <path
+ inkscape:connector-curvature="0"
+ style="opacity:0.3;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ d="m 33,338.00001 0.5,0 0,1 L 33,339 l 0,-0.99999 z"
+ id="path22838"
+ sodipodi:nodetypes="ccccc" />
+ <rect
+ style="opacity:0.8;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:3.20000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect23759"
+ width="2"
+ height="1"
+ x="33"
+ y="329" />
+ <rect
+ y="328"
+ x="35"
+ height="1"
+ width="1"
+ id="rect23761"
+ style="opacity:0.6;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:3.20000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ </g>
</g>
</g>
<g
- id="g23767"
+ id="ICON_OUTLINER_OB_LAMP"
transform="translate(84,107.00001)">
<rect
style="opacity:0;fill:#4d4d4d;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:6;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
@@ -52713,7 +54558,7 @@
sodipodi:cy="502"
sodipodi:rx="2.5312502"
sodipodi:ry="2.5"
- d="m 80.53125,502 c 0,1.38071 -1.133279,2.5 -2.53125,2.5 -1.397971,0 -2.53125,-1.11929 -2.53125,-2.5 0,-1.38071 1.133279,-2.5 2.53125,-2.5 1.397971,0 2.53125,1.11929 2.53125,2.5 z"
+ d="M 80.53125,502 A 2.5312502,2.5 0 0 1 78,504.5 2.5312502,2.5 0 0 1 75.46875,502 2.5312502,2.5 0 0 1 78,499.5 2.5312502,2.5 0 0 1 80.53125,502 Z"
transform="matrix(0.9552133,0,0,0.9315985,-40.901258,-140.2522)" />
<path
transform="matrix(0.99567,0,-0.00787885,1,-30.654936,191)"
@@ -52724,7 +54569,7 @@
sodipodi:cy="135"
sodipodi:rx="1"
sodipodi:ry="1"
- d="m 65,135 c 0,0.55228 -0.447715,1 -1,1 -0.552285,0 -1,-0.44772 -1,-1 0,-0.55228 0.447715,-1 1,-1 0.552285,0 1,0.44772 1,1 z"
+ d="m 65,135 a 1,1 0 0 1 -1,1 1,1 0 0 1 -1,-1 1,1 0 0 1 1,-1 1,1 0 0 1 1,1 z"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90" />
@@ -52788,7 +54633,7 @@
</g>
</g>
<g
- id="g23912"
+ id="ICON_LAMP"
transform="translate(-21,233.00001)">
<rect
style="opacity:0;fill:#4d4d4d;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:6;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
@@ -52914,7 +54759,7 @@
sodipodi:cy="502"
sodipodi:rx="2.5312502"
sodipodi:ry="2.5"
- d="m 80.53125,502 c 0,1.38071 -1.133279,2.5 -2.53125,2.5 -1.397971,0 -2.53125,-1.11929 -2.53125,-2.5 0,-1.38071 1.133279,-2.5 2.53125,-2.5 1.397971,0 2.53125,1.11929 2.53125,2.5 z"
+ d="M 80.53125,502 A 2.5312502,2.5 0 0 1 78,504.5 2.5312502,2.5 0 0 1 75.46875,502 2.5312502,2.5 0 0 1 78,499.5 2.5312502,2.5 0 0 1 80.53125,502 Z"
transform="matrix(0.9552133,0,0,0.9315985,-40.901258,-140.2522)" />
<path
transform="matrix(0.99567,0,-0.00787885,1,-30.663533,191)"
@@ -52925,7 +54770,7 @@
sodipodi:cy="135"
sodipodi:rx="1"
sodipodi:ry="1"
- d="m 65,135 c 0,0.55228 -0.447715,1 -1,1 -0.552285,0 -1,-0.44772 -1,-1 0,-0.55228 0.447715,-1 1,-1 0.552285,0 1,0.44772 1,1 z"
+ d="m 65,135 a 1,1 0 0 1 -1,1 1,1 0 0 1 -1,-1 1,1 0 0 1 1,-1 1,1 0 0 1 1,1 z"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90" />
@@ -52989,113 +54834,123 @@
</g>
</g>
<g
- id="g25056"
- transform="translate(-168,2)">
+ id="ICON_NEWFOLDER">
+ <rect
+ style="opacity:0.01000001;fill:#cccccc;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.80000001;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect51964"
+ width="16"
+ height="16"
+ x="277.99997"
+ y="73" />
<g
- style="opacity:0.75"
- id="g24996">
- <rect
- y="71"
- x="446"
- height="16"
- width="16"
- id="rect24939"
- style="opacity:0;fill:#cccccc;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.80000001;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ transform="translate(-168,2)"
+ id="g25056">
<g
- id="g24941"
- transform="translate(359,-336)">
- <path
- style="fill:url(#linearGradient25073);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.00000012;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- d="m 89.5,410.5 0,9.49245 1.5,1.5 8.5,0 0,-9.99245 -7,0 0,-1 -3,0 z"
- id="path24943"
- sodipodi:nodetypes="cccccccc"
- inkscape:connector-curvature="0" />
+ id="g24996"
+ style="opacity:0.75">
+ <rect
+ style="opacity:0;fill:#cccccc;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.80000001;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect24939"
+ width="16"
+ height="16"
+ x="446"
+ y="71" />
<g
- transform="translate(-361,287.99994)"
- id="g24945"
- style="display:inline" />
- <path
- style="fill:#d1c595;fill-opacity:1;fill-rule:nonzero;stroke:url(#linearGradient25075);stroke-width:0.80000001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- d="m 92.5,414.4849 10,0.0151 0,5.50755 -1.5,1.49245 -10,0 0,-2 1.5,0 0,-5.0151 z"
- id="path24947"
- sodipodi:nodetypes="cccccccc"
- inkscape:connector-curvature="0" />
- <path
- sodipodi:nodetypes="cccccc"
- style="opacity:0.5;fill:none;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1;display:inline"
- d="m 91.5,420.49245 -1.01563,-0.98437 0,-8.02344 1.01563,0.0154 0,1 7,0"
- id="path24949"
- inkscape:connector-curvature="0" />
+ transform="translate(359,-336)"
+ id="g24941">
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cccccccc"
+ id="path24943"
+ d="m 89.5,410.5 0,9.49245 1.5,1.5 8.5,0 0,-9.99245 -7,0 0,-1 -3,0 z"
+ style="fill:url(#linearGradient25073);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.00000012;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <g
+ style="display:inline"
+ id="g24945"
+ transform="translate(-361,287.99994)" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cccccccc"
+ id="path24947"
+ d="m 92.5,414.4849 10,0.0151 0,5.50755 -1.5,1.49245 -10,0 0,-2 1.5,0 0,-5.0151 z"
+ style="fill:#d1c595;fill-opacity:1;fill-rule:nonzero;stroke:url(#linearGradient25075);stroke-width:0.80000001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path24949"
+ d="m 91.5,420.49245 -1.01563,-0.98437 0,-8.02344 1.01563,0.0154 0,1 7,0"
+ style="opacity:0.5;fill:none;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1;display:inline"
+ sodipodi:nodetypes="cccccc" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path24951"
+ d="m 93,420.5 7.5,0"
+ style="opacity:0.18999999;fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1;display:inline"
+ sodipodi:nodetypes="cc" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccc"
+ style="opacity:0.8;fill:none;stroke:url(#linearGradient25077);stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1;display:inline"
+ d="m 101.5,415.50755 -8,-0.008 0,4 -1.5,1.5 -1.5,-1.5"
+ id="path24953" />
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#2a2512;stroke-width:0.80000001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 89.5,410.5 0,9.49245 1.5,1.5 10,0.0151 1.5,-1.49245 0,-5.50755 -3,-0.008 0,-2.9849 -7,-0.0151 0,-1 -3,0 0,4.5e-4 0,0 0,0 z"
+ id="path24957"
+ sodipodi:nodetypes="ccccccccccc" />
+ </g>
+ </g>
+ <g
+ transform="matrix(0.9986805,0,0,1,129.4308,-202)"
+ id="g25007"
+ style="display:inline">
+ <rect
+ ry="1.2018067"
+ style="opacity:0.4;fill:none;stroke:#fac900;stroke-width:4.00264168;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:7.39511889;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect25009"
+ width="3.0039635"
+ height="3"
+ x="318.99011"
+ y="275"
+ rx="1.2018067" />
+ <rect
+ ry="1.2018068"
+ rx="1.2018068"
+ y="275"
+ x="318.99011"
+ height="3"
+ width="3.0039637"
+ id="rect25011"
+ style="opacity:0.8;fill:none;stroke:#e6b800;stroke-width:2.00132084;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:7.39511889;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
<path
- sodipodi:nodetypes="cc"
- style="opacity:0.18999999;fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1;display:inline"
- d="m 93,420.5 7.5,0"
- id="path24951"
- inkscape:connector-curvature="0" />
+ inkscape:connector-curvature="0"
+ inkscape:export-ydpi="90"
+ inkscape:export-xdpi="90"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
+ id="path32046"
+ d="m 318.99011,278 c 0,-1.00003 3e-5,-2.00003 3e-5,-3.00006 1.00131,0 2.00262,0 3.00393,0 0,1.00003 -3e-5,2.00003 -3e-5,3.00006 -1.00131,0 -2.00262,0 -3.00393,0 z"
+ style="fill:#aa8800;fill-opacity:1;fill-rule:nonzero;stroke:none" />
<path
- id="path24953"
- d="m 101.5,415.50755 -8,-0.008 0,4 -1.5,1.5 -1.5,-1.5"
- style="opacity:0.8;fill:none;stroke:url(#linearGradient25077);stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1;display:inline"
- sodipodi:nodetypes="ccccc"
- inkscape:connector-curvature="0" />
+ inkscape:connector-curvature="0"
+ inkscape:export-ydpi="90"
+ inkscape:export-xdpi="90"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
+ id="path25013"
+ d="m 318.48945,276 c 1.33509,0 2.67017,10e-6 4.00526,10e-6 0,0.33335 0,0.6667 0,1.00005 -1.33509,0 -2.67017,-1e-5 -4.00526,-1e-5 0,-0.33335 0,-0.6667 0,-1.00005 z"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none" />
<path
- sodipodi:nodetypes="ccccccccccc"
- id="path24957"
- d="m 89.5,410.5 0,9.49245 1.5,1.5 10,0.0151 1.5,-1.49245 0,-5.50755 -3,-0.008 0,-2.9849 -7,-0.0151 0,-1 -3,0 0,4.5e-4 0,0 0,0 z"
- style="fill:none;stroke:#2a2512;stroke-width:0.80000001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- inkscape:connector-curvature="0" />
+ inkscape:connector-curvature="0"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ d="m 319.99139,278.50006 c 0,-1.33337 10e-6,-2.66669 10e-6,-4.00006 0.33379,0 0.66758,0 1.00137,0 0,1.33337 -1e-5,2.66669 -1e-5,4.00006 -0.33379,0 -0.66758,0 -1.00137,0 z"
+ id="path25015"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
</g>
</g>
- <g
- style="display:inline"
- id="g25007"
- transform="matrix(0.9986805,0,0,1,129.4308,-202)">
- <rect
- rx="1.2018067"
- y="275"
- x="318.99011"
- height="3"
- width="3.0039635"
- id="rect25009"
- style="opacity:0.4;fill:none;stroke:#fac900;stroke-width:4.00264168;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:7.39511889;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- ry="1.2018067" />
- <rect
- style="opacity:0.8;fill:none;stroke:#e6b800;stroke-width:2.00132084;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:7.39511889;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- id="rect25011"
- width="3.0039637"
- height="3"
- x="318.99011"
- y="275"
- rx="1.2018068"
- ry="1.2018068" />
- <path
- style="fill:#aa8800;fill-opacity:1;fill-rule:nonzero;stroke:none"
- d="m 318.99011,278 c 0,-1.00003 3e-5,-2.00003 3e-5,-3.00006 1.00131,0 2.00262,0 3.00393,0 0,1.00003 -3e-5,2.00003 -3e-5,3.00006 -1.00131,0 -2.00262,0 -3.00393,0 z"
- id="path32046"
- inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
- inkscape:export-xdpi="90"
- inkscape:export-ydpi="90"
- inkscape:connector-curvature="0" />
- <path
- style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
- d="m 318.48945,276 c 1.33509,0 2.67017,10e-6 4.00526,10e-6 0,0.33335 0,0.6667 0,1.00005 -1.33509,0 -2.67017,-1e-5 -4.00526,-1e-5 0,-0.33335 0,-0.6667 0,-1.00005 z"
- id="path25013"
- inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
- inkscape:export-xdpi="90"
- inkscape:export-ydpi="90"
- inkscape:connector-curvature="0" />
- <path
- inkscape:export-ydpi="90"
- inkscape:export-xdpi="90"
- inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
- id="path25015"
- d="m 319.99139,278.50006 c 0,-1.33337 10e-6,-2.66669 10e-6,-4.00006 0.33379,0 0.66758,0 1.00137,0 0,1.33337 -1e-5,2.66669 -1e-5,4.00006 -0.33379,0 -0.66758,0 -1.00137,0 z"
- style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
- inkscape:connector-curvature="0" />
- </g>
</g>
<g
- id="g42026"
+ id="ICON_BOOKMARKS"
transform="translate(-126,2)"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90">
@@ -53249,7 +55104,7 @@
</g>
</g>
<g
- id="g62487"
+ id="ICON_OUTLINER_DATA_LATTICE"
transform="translate(0,128)">
<rect
transform="matrix(0,1,1,0,0,0)"
@@ -53315,7 +55170,7 @@
</g>
</g>
<g
- id="g62412"
+ id="ICON_OUTLINER_OB_LATTICE"
transform="translate(1,127)">
<rect
transform="matrix(0,1,1,0,0,0)"
@@ -53464,7 +55319,7 @@
</g>
</g>
<g
- id="g62543"
+ id="ICON_MOD_LATTICE"
transform="translate(1,2)">
<rect
transform="matrix(0,1,1,0,0,0)"
@@ -53532,7 +55387,7 @@
</g>
<g
style="display:inline;enable-background:new"
- id="g24707"
+ id="ICON_OUTLINER_OB_META"
transform="translate(-210,128)">
<rect
y="302"
@@ -53570,9 +55425,9 @@
sodipodi:cy="79.5"
sodipodi:rx="3.5"
sodipodi:ry="3.5"
- d="m 211,79.5 c 0,1.932997 -1.567,3.5 -3.5,3.5 -1.933,0 -3.5,-1.567003 -3.5,-3.5 0,-1.932997 1.567,-3.5 3.5,-3.5 1.933,0 3.5,1.567003 3.5,3.5 z" />
+ d="M 211,79.5 A 3.5,3.5 0 0 1 207.5,83 3.5,3.5 0 0 1 204,79.5 3.5,3.5 0 0 1 207.5,76 3.5,3.5 0 0 1 211,79.5 Z" />
<path
- d="m 211,79.5 c 0,1.932997 -1.567,3.5 -3.5,3.5 -1.933,0 -3.5,-1.567003 -3.5,-3.5 0,-1.932997 1.567,-3.5 3.5,-3.5 1.933,0 3.5,1.567003 3.5,3.5 z"
+ d="M 211,79.5 A 3.5,3.5 0 0 1 207.5,83 3.5,3.5 0 0 1 204,79.5 3.5,3.5 0 0 1 207.5,76 3.5,3.5 0 0 1 211,79.5 Z"
sodipodi:ry="3.5"
sodipodi:rx="3.5"
sodipodi:cy="79.5"
@@ -53600,7 +55455,7 @@
</g>
<g
style="display:inline;enable-background:new"
- id="g23140"
+ id="ICON_IPO"
transform="translate(32,248.99993)"
mask="url(#mask23189)"
inkscape:export-filename="C:\Documents and Settings\Pracownia\Moje dokumenty\Moje obrazy\BLENDER ICONS redesign\RELEASES\g42357.png"
@@ -53662,7 +55517,7 @@
<g
style="display:inline;enable-background:new"
transform="translate(54,277.99993)"
- id="g24129"
+ id="ICON_NLA"
inkscape:export-filename="C:\Documents and Settings\Pracownia\Moje dokumenty\Moje obrazy\BLENDER ICONS redesign\RELEASES\g42357.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90">
@@ -53744,7 +55599,7 @@
</g>
<g
transform="translate(2,298)"
- id="g40315"
+ id="ICON_VIEW3D"
style="display:inline;enable-background:new"
inkscape:export-filename="C:\Documents and Settings\Pracownia\Moje dokumenty\Moje obrazy\BLENDER ICONS redesign\RELEASES\g42357.png"
inkscape:export-xdpi="90"
@@ -53824,7 +55679,7 @@
<g
style="display:inline;enable-background:new"
transform="translate(12.401337,137.46985)"
- id="g40381"
+ id="ICON_SCRIPTWIN"
inkscape:export-filename="C:\Documents and Settings\Pracownia\Moje dokumenty\Moje obrazy\BLENDER ICONS redesign\RELEASES\g42357.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90">
@@ -53886,162 +55741,165 @@
inkscape:connector-curvature="0" />
</g>
</g>
- <rect
- y="535"
- x="320"
- height="16"
- width="16"
- id="rect40397"
- style="opacity:0;fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- inkscape:export-filename="C:\Documents and Settings\Pracownia\Moje dokumenty\Moje obrazy\BLENDER ICONS redesign\RELEASES\g42357.png"
- inkscape:export-xdpi="90"
- inkscape:export-ydpi="90" />
<g
- transform="translate(18.016113,298.07385)"
- id="g40399"
- style="display:inline;enable-background:new"
- inkscape:export-filename="C:\Documents and Settings\Pracownia\Moje dokumenty\Moje obrazy\BLENDER ICONS redesign\RELEASES\g42357.png"
- inkscape:export-xdpi="90"
- inkscape:export-ydpi="90">
- <path
- sodipodi:nodetypes="cccccc"
- id="path40401"
- d="m 309.21778,249.41313 5.01611,0.013 c 1.29844,0 2.25,-0.80274 2.25,-2.25 l 0.0161,-4.48698 c 0,-1.29844 -0.95156,-2.25 -2.25,-2.25 l -1.75,0"
- style="opacity:0.6;fill:none;stroke:#191919;stroke-width:2.79999995;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- inkscape:connector-curvature="0" />
- <rect
- style="opacity:0.01000001;fill:none;stroke:#e8a930;stroke-width:2.99999928;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:7.40000265;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- id="rect40403"
- width="1.9930685"
- height="1.9947703"
- x="309.50693"
- y="239.5"
- ry="0.99734437"
- rx="0.98426884" />
- <path
- style="fill:none;stroke:#bcd0f5;stroke-width:1.39999998;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- d="m 310.98389,249.42615 3,0 c 1.29844,0 2.5,-1.20156 2.5,-2.5 l 0.0161,-3.93424 c 0,-1.29844 -1.20156,-2.55274 -2.5,-2.55274 l -1.5,0"
- id="path40406"
- sodipodi:nodetypes="cccccc"
- inkscape:connector-curvature="0" />
- <rect
- style="fill:none;stroke:#000000;stroke-width:0.99999946;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
- id="rect40408"
- width="7.0161614"
- height="5.9999523"
- x="302.46777"
- y="246.42619"
- ry="1.5185405"
- rx="1.7691951"
- inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
- inkscape:export-xdpi="90"
- inkscape:export-ydpi="90" />
+ id="ICON_NODETREE">
<rect
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
- inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
- rx="0.0128693"
- ry="0.010695697"
- y="246.92615"
- x="302.96777"
- height="4.9999976"
- width="6.0161119"
- id="rect40410"
- style="fill:url(#linearGradient40736);fill-opacity:1;fill-rule:nonzero;stroke:none" />
- <rect
- inkscape:export-ydpi="90"
- inkscape:export-xdpi="90"
- inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
- rx="1.5194846"
- ry="1.4892343"
- y="237.42615"
- x="305.49991"
- height="5.9341388"
- width="6.9999981"
- id="rect40412"
- style="fill:none;stroke:#000000;stroke-width:0.99999958;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
- <rect
- style="fill:#4d4d4d;fill-opacity:1;fill-rule:nonzero;stroke:none"
- id="rect40414"
- width="4.0322218"
- height="0.99999762"
- x="303.96777"
- y="247.92615"
- ry="0.0053478414"
- rx="0.0086254831"
- inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
- inkscape:export-xdpi="90"
- inkscape:export-ydpi="90" />
- <rect
- inkscape:export-ydpi="90"
- inkscape:export-xdpi="90"
- inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
- rx="0"
- ry="0"
- y="247.42625"
- x="303.46777"
- height="3.9999583"
- width="5.0161114"
- id="rect40416"
- style="opacity:0.8;fill:none;stroke:url(#linearGradient40738);stroke-width:1.00000024;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
- <rect
- style="fill:url(#linearGradient40740);fill-opacity:1;fill-rule:nonzero;stroke:none"
- id="rect40418"
- width="5.9999843"
- height="5.0000072"
- x="306"
- y="237.92615"
- ry="0"
- rx="0"
- inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
- inkscape:export-xdpi="90"
- inkscape:export-ydpi="90" />
- <rect
+ inkscape:export-filename="C:\Documents and Settings\Pracownia\Moje dokumenty\Moje obrazy\BLENDER ICONS redesign\RELEASES\g42357.png"
+ style="opacity:0;fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect40397"
+ width="16"
+ height="16"
+ x="320"
+ y="535" />
+ <g
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
- inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
- rx="0.0071879062"
- ry="0.0053478414"
- y="238.92615"
- x="306.98389"
- height="0.99999762"
- width="4.0322237"
- id="rect40420"
- style="fill:#4d4d4d;fill-opacity:1;fill-rule:nonzero;stroke:none" />
- <rect
- style="opacity:0.8;fill:none;stroke:url(#linearGradient40742);stroke-width:1.00000036;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
- id="rect40422"
- width="5.0067563"
- height="3.9560828"
- x="306.5"
- y="238.41525"
- ry="0"
- rx="0"
- inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
- inkscape:export-xdpi="90"
- inkscape:export-ydpi="90" />
- <rect
- ry="0"
- y="248.43787"
- x="309.48389"
- height="1.9882908"
- width="2"
- id="rect40424"
- style="fill:#ffb72a;fill-opacity:1;fill-rule:nonzero;stroke:#553800;stroke-width:0.80000001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:7.40000265;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- rx="0" />
- <rect
- rx="0"
- style="fill:#ffb72a;fill-opacity:1;fill-rule:nonzero;stroke:#553800;stroke-width:0.80000001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:7.40000265;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- id="rect40426"
- width="2"
- height="1.9882908"
- x="312.48389"
- y="239.43787"
- ry="0" />
+ inkscape:export-filename="C:\Documents and Settings\Pracownia\Moje dokumenty\Moje obrazy\BLENDER ICONS redesign\RELEASES\g42357.png"
+ style="display:inline;enable-background:new"
+ id="g40399"
+ transform="translate(18.016113,298.07385)">
+ <path
+ inkscape:connector-curvature="0"
+ style="opacity:0.6;fill:none;stroke:#191919;stroke-width:2.79999995;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 309.21778,249.41313 5.01611,0.013 c 1.29844,0 2.25,-0.80274 2.25,-2.25 l 0.0161,-4.48698 c 0,-1.29844 -0.95156,-2.25 -2.25,-2.25 l -1.75,0"
+ id="path40401"
+ sodipodi:nodetypes="cccccc" />
+ <rect
+ rx="0.98426884"
+ ry="0.99734437"
+ y="239.5"
+ x="309.50693"
+ height="1.9947703"
+ width="1.9930685"
+ id="rect40403"
+ style="opacity:0.01000001;fill:none;stroke:#e8a930;stroke-width:2.99999928;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:7.40000265;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cccccc"
+ id="path40406"
+ d="m 310.98389,249.42615 3,0 c 1.29844,0 2.5,-1.20156 2.5,-2.5 l 0.0161,-3.93424 c 0,-1.29844 -1.20156,-2.55274 -2.5,-2.55274 l -1.5,0"
+ style="fill:none;stroke:#bcd0f5;stroke-width:1.39999998;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <rect
+ inkscape:export-ydpi="90"
+ inkscape:export-xdpi="90"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
+ rx="1.7691951"
+ ry="1.5185405"
+ y="246.42619"
+ x="302.46777"
+ height="5.9999523"
+ width="7.0161614"
+ id="rect40408"
+ style="fill:none;stroke:#000000;stroke-width:0.99999946;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
+ <rect
+ style="fill:url(#linearGradient40736);fill-opacity:1;fill-rule:nonzero;stroke:none"
+ id="rect40410"
+ width="6.0161119"
+ height="4.9999976"
+ x="302.96777"
+ y="246.92615"
+ ry="0.010695697"
+ rx="0.0128693"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <rect
+ style="fill:none;stroke:#000000;stroke-width:0.99999958;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ id="rect40412"
+ width="6.9999981"
+ height="5.9341388"
+ x="305.49991"
+ y="237.42615"
+ ry="1.4892343"
+ rx="1.5194846"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <rect
+ inkscape:export-ydpi="90"
+ inkscape:export-xdpi="90"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
+ rx="0.0086254831"
+ ry="0.0053478414"
+ y="247.92615"
+ x="303.96777"
+ height="0.99999762"
+ width="4.0322218"
+ id="rect40414"
+ style="fill:#4d4d4d;fill-opacity:1;fill-rule:nonzero;stroke:none" />
+ <rect
+ style="opacity:0.8;fill:none;stroke:url(#linearGradient40738);stroke-width:1.00000024;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ id="rect40416"
+ width="5.0161114"
+ height="3.9999583"
+ x="303.46777"
+ y="247.42625"
+ ry="0"
+ rx="0"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <rect
+ inkscape:export-ydpi="90"
+ inkscape:export-xdpi="90"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
+ rx="0"
+ ry="0"
+ y="237.92615"
+ x="306"
+ height="5.0000072"
+ width="5.9999843"
+ id="rect40418"
+ style="fill:url(#linearGradient40740);fill-opacity:1;fill-rule:nonzero;stroke:none" />
+ <rect
+ style="fill:#4d4d4d;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ id="rect40420"
+ width="4.0322237"
+ height="0.99999762"
+ x="306.98389"
+ y="238.92615"
+ ry="0.0053478414"
+ rx="0.0071879062"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <rect
+ inkscape:export-ydpi="90"
+ inkscape:export-xdpi="90"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
+ rx="0"
+ ry="0"
+ y="238.41525"
+ x="306.5"
+ height="3.9560828"
+ width="5.0067563"
+ id="rect40422"
+ style="opacity:0.8;fill:none;stroke:url(#linearGradient40742);stroke-width:1.00000036;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
+ <rect
+ rx="0"
+ style="fill:#ffb72a;fill-opacity:1;fill-rule:nonzero;stroke:#553800;stroke-width:0.80000001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:7.40000265;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect40424"
+ width="2"
+ height="1.9882908"
+ x="309.48389"
+ y="248.43787"
+ ry="0" />
+ <rect
+ ry="0"
+ y="239.43787"
+ x="312.48389"
+ height="1.9882908"
+ width="2"
+ id="rect40426"
+ style="fill:#ffb72a;fill-opacity:1;fill-rule:nonzero;stroke:#553800;stroke-width:0.80000001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:7.40000265;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ rx="0" />
+ </g>
</g>
<g
style="display:inline;enable-background:new"
- id="g40520"
+ id="ICON_SOUND"
transform="translate(-1,128)"
inkscape:export-filename="C:\Documents and Settings\Pracownia\Moje dokumenty\Moje obrazy\BLENDER ICONS redesign\RELEASES\g42357.png"
inkscape:export-xdpi="90"
@@ -54086,7 +55944,7 @@
</g>
<g
style="opacity:0.96000001;display:inline;enable-background:new"
- id="g40602"
+ id="ICON_TIME"
transform="translate(0,128)"
inkscape:export-filename="C:\Documents and Settings\Pracownia\Moje dokumenty\Moje obrazy\BLENDER ICONS redesign\RELEASES\g42357.png"
inkscape:export-xdpi="90"
@@ -54114,7 +55972,7 @@
sodipodi:cy="118"
sodipodi:rx="8"
sodipodi:ry="8"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90" />
@@ -54130,7 +55988,7 @@
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
sodipodi:ry="8"
sodipodi:rx="8"
sodipodi:cy="118"
@@ -54218,7 +56076,7 @@
</g>
<g
transform="translate(9,297.99992)"
- id="g40632"
+ id="ICON_TEXT"
style="display:inline;enable-background:new"
inkscape:export-filename="C:\Documents and Settings\Pracownia\Moje dokumenty\Moje obrazy\BLENDER ICONS redesign\RELEASES\g42357.png"
inkscape:export-xdpi="90"
@@ -54309,7 +56167,7 @@
</g>
<g
style="display:inline;enable-background:new"
- id="g40518"
+ id="ICON_CONSOLE"
transform="translate(18.999997,-40.99992)">
<g
style="display:inline"
@@ -54399,7 +56257,7 @@
</g>
<g
style="display:inline;enable-background:new"
- id="g24081"
+ id="ICON_NODE"
transform="translate(405,-17.000053)"
inkscape:export-filename="C:\Documents and Settings\Pracownia\Moje dokumenty\Moje obrazy\BLENDER ICONS redesign\RELEASES\x.png"
inkscape:export-xdpi="90"
@@ -54479,19 +56337,9 @@
y="641.5" />
</g>
</g>
- <rect
- y="534.99994"
- x="131"
- height="16"
- width="16"
- id="rect23324"
- style="opacity:0;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- inkscape:export-filename="C:\Documents and Settings\Pracownia\Moje dokumenty\Moje obrazy\BLENDER ICONS redesign\RELEASES\g22298.png"
- inkscape:export-xdpi="90"
- inkscape:export-ydpi="90" />
<g
style="display:inline;enable-background:new"
- id="g23326"
+ id="ICON_NODE_SEL"
transform="translate(426,-17.000053)"
inkscape:export-filename="C:\Documents and Settings\Pracownia\Moje dokumenty\Moje obrazy\BLENDER ICONS redesign\RELEASES\x.png"
inkscape:export-xdpi="90"
@@ -54575,7 +56423,7 @@
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Pracownia\Moje dokumenty\Moje obrazy\BLENDER ICONS redesign\RELEASES\g42357.png"
- id="g42663"
+ id="ICON_SEQ_SEQUENCER"
transform="translate(-198,-247)"
style="display:inline;enable-background:new">
<rect
@@ -54656,7 +56504,7 @@
</g>
<g
style="display:inline;enable-background:new"
- id="g25594"
+ id="ICON_FILE_MOVIE"
transform="translate(-306,-275)">
<g
style="display:inline"
@@ -54885,7 +56733,7 @@
inkscape:connector-curvature="0" />
</g>
<g
- id="g25988"
+ id="ICON_FILE_SOUND"
transform="translate(-152,-151)">
<g
transform="translate(-272,34)"
@@ -55002,13 +56850,13 @@
sodipodi:cy="554"
sodipodi:rx="4.5"
sodipodi:ry="2.25"
- d="m 57.5,554 c 0,1.24264 -2.014719,2.25 -4.5,2.25 -2.485281,0 -4.5,-1.00736 -4.5,-2.25 0,-1.24264 2.014719,-2.25 4.5,-2.25 2.485281,0 4.5,1.00736 4.5,2.25 z"
+ d="M 57.5,554 A 4.5,2.25 0 0 1 53,556.25 4.5,2.25 0 0 1 48.5,554 4.5,2.25 0 0 1 53,551.75 4.5,2.25 0 0 1 57.5,554 Z"
transform="matrix(0.7630859,-0.2494396,0.2996015,0.9926766,-151.92281,17.77746)" />
<path
clip-path="url(#clipPath20586)"
inkscape:transform-center-y="0.3813435"
transform="matrix(0.3848865,-0.1700959,0.2278131,0.3626733,-93.107467,361.59408)"
- d="m 57.5,554 c 0,1.24264 -2.014719,2.25 -4.5,2.25 -2.485281,0 -4.5,-1.00736 -4.5,-2.25 0,-1.24264 2.014719,-2.25 4.5,-2.25 2.485281,0 4.5,1.00736 4.5,2.25 z"
+ d="M 57.5,554 A 4.5,2.25 0 0 1 53,556.25 4.5,2.25 0 0 1 48.5,554 4.5,2.25 0 0 1 53,551.75 4.5,2.25 0 0 1 57.5,554 Z"
sodipodi:ry="2.25"
sodipodi:rx="4.5"
sodipodi:cy="554"
@@ -55030,7 +56878,7 @@
inkscape:connector-curvature="0" />
</g>
<g
- id="g25963"
+ id="ICON_FILE_TEXT"
transform="translate(-86,-139)">
<g
transform="translate(-262,-147)"
@@ -55140,7 +56988,7 @@
inkscape:connector-curvature="0" />
</g>
<g
- id="g25933"
+ id="ICON_FILE_FONT"
transform="translate(-107,-115)">
<g
id="g25393"
@@ -55285,7 +57133,7 @@
</g>
<g
style="display:inline;enable-background:new"
- id="g25672"
+ id="ICON_FILE_BLEND"
transform="translate(-348,-155)">
<g
transform="translate(-126,60.000002)"
@@ -55411,7 +57259,7 @@
sodipodi:cy="57.5"
sodipodi:rx="1"
sodipodi:ry="1.0000004"
- d="m 14.5,57.5 c 0,0.552285 -0.447715,1 -1,1 -0.552285,0 -1,-0.447715 -1,-1 0,-0.552285 0.447715,-1 1,-1 0.552285,0 1,0.447715 1,1 z"
+ d="m 14.5,57.5 a 1,1.0000004 0 0 1 -1,1 1,1.0000004 0 0 1 -1,-1 1,1.0000004 0 0 1 1,-1 1,1.0000004 0 0 1 1,1 z"
transform="matrix(3.625,0,0,3.1690202,-67.8125,318.31703)" />
<path
sodipodi:nodetypes="cccc"
@@ -55428,7 +57276,7 @@
sodipodi:cy="57.5"
sodipodi:rx="1"
sodipodi:ry="1"
- d="m 14.5,57.5 c 0,0.552285 -0.447715,1 -1,1 -0.552285,0 -1,-0.447715 -1,-1 0,-0.552285 0.447715,-1 1,-1 0.552285,0 1,0.447715 1,1 z"
+ d="m 14.5,57.5 a 1,1 0 0 1 -1,1 1,1 0 0 1 -1,-1 1,1 0 0 1 1,-1 1,1 0 0 1 1,1 z"
transform="matrix(3.5999897,0,0,3.1249932,-67.499871,320.6879)" />
<path
id="path25721"
@@ -55438,7 +57286,7 @@
inkscape:connector-curvature="0" />
<path
transform="matrix(3.25,0,0,3.25,-62.875,313.125)"
- d="m 14.5,57.5 c 0,0.552285 -0.447715,1 -1,1 -0.552285,0 -1,-0.447715 -1,-1 0,-0.552285 0.447715,-1 1,-1 0.552285,0 1,0.447715 1,1 z"
+ d="m 14.5,57.5 a 1,1 0 0 1 -1,1 1,1 0 0 1 -1,-1 1,1 0 0 1 1,-1 1,1 0 0 1 1,1 z"
sodipodi:ry="1"
sodipodi:rx="1"
sodipodi:cy="57.5"
@@ -55454,11 +57302,11 @@
sodipodi:cy="57.5"
sodipodi:rx="1"
sodipodi:ry="1"
- d="m 14.5,57.5 c 0,0.552285 -0.447715,1 -1,1 -0.552285,0 -1,-0.447715 -1,-1 0,-0.552285 0.447715,-1 1,-1 0.552285,0 1,0.447715 1,1 z"
+ d="m 14.5,57.5 a 1,1 0 0 1 -1,1 1,1 0 0 1 -1,-1 1,1 0 0 1 1,-1 1,1 0 0 1 1,1 z"
transform="matrix(2,0,0,2,-46,385)" />
<path
transform="matrix(4.7519907,0,0,4.1435313,-83.051884,262.12196)"
- d="m 14.5,57.5 c 0,0.552285 -0.447715,1 -1,1 -0.552285,0 -1,-0.447715 -1,-1 0,-0.552285 0.447715,-1 1,-1 0.552285,0 1,0.447715 1,1 z"
+ d="m 14.5,57.5 a 1,1 0 0 1 -1,1 1,1 0 0 1 -1,-1 1,1 0 0 1 1,-1 1,1 0 0 1 1,1 z"
sodipodi:ry="1"
sodipodi:rx="1"
sodipodi:cy="57.5"
@@ -55483,7 +57331,7 @@
</g>
<g
style="display:inline;enable-background:new"
- id="g25822"
+ id="ICON_FILE_FOLDER"
transform="translate(273,-334)">
<rect
y="407"
@@ -55544,7 +57392,7 @@
</g>
<g
transform="translate(371,90.000008)"
- id="g26093">
+ id="ICON_UI">
<rect
style="opacity:0;fill:#cccccc;fill-opacity:0.75;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
id="rect26095"
@@ -55683,7 +57531,7 @@
</g>
</g>
<g
- id="g28119"
+ id="ICON_RESTRICT_VIEW_OFF"
transform="translate(0,127.99999)">
<rect
y="302"
@@ -55701,7 +57549,7 @@
sodipodi:nodetypes="ccscz"
inkscape:connector-curvature="0" />
<path
- d="m 434.99991,14.5 c 0,1.609518 -1.79082,2.91429 -3.99991,2.91429 -2.20909,0 -3.99991,-1.304772 -3.99991,-2.91429 0,-1.609518 1.79082,-2.91429 3.99991,-2.91429 2.20909,0 3.99991,1.304772 3.99991,2.91429 z"
+ d="M 434.99991,14.5 A 3.9999149,2.91429 0 0 1 431,17.41429 3.9999149,2.91429 0 0 1 427.00009,14.5 3.9999149,2.91429 0 0 1 431,11.58571 3.9999149,2.91429 0 0 1 434.99991,14.5 Z"
sodipodi:ry="2.91429"
sodipodi:rx="3.9999149"
sodipodi:cy="14.5"
@@ -55711,7 +57559,7 @@
sodipodi:type="arc"
transform="matrix(0.7500463,0,0,1.0294111,88.73017,294.07354)" />
<path
- d="m 65,135 c 0,0.55228 -0.447715,1 -1,1 -0.552285,0 -1,-0.44772 -1,-1 0,-0.55228 0.447715,-1 1,-1 0.552285,0 1,0.44772 1,1 z"
+ d="m 65,135 a 1,1 0 0 1 -1,1 1,1 0 0 1 -1,-1 1,1 0 0 1 1,-1 1,1 0 0 1 1,1 z"
sodipodi:ry="1"
sodipodi:rx="1"
sodipodi:cy="135"
@@ -55734,7 +57582,7 @@
id="rect27926"
style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" />
<path
- d="m 65,135 c 0,0.55228 -0.447715,1 -1,1 -0.552285,0 -1,-0.44772 -1,-1 0,-0.55228 0.447715,-1 1,-1 0.552285,0 1,0.44772 1,1 z"
+ d="m 65,135 a 1,1 0 0 1 -1,1 1,1 0 0 1 -1,-1 1,1 0 0 1 1,-1 1,1 0 0 1 1,1 z"
sodipodi:ry="1"
sodipodi:rx="1"
sodipodi:cy="135"
@@ -55746,7 +57594,7 @@
</g>
</g>
<g
- id="g27932"
+ id="ICON_RESTRICT_VIEW_ON"
transform="translate(4e-6,127.99999)">
<g
transform="translate(0.4838899,-6.2084382e-8)"
@@ -55785,7 +57633,7 @@
y="302" />
</g>
<g
- id="g27416"
+ id="ICON_VISIBLE_IPO_ON"
transform="translate(105,-82)">
<rect
style="opacity:0;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline"
@@ -55811,7 +57659,7 @@
sodipodi:cy="14.5"
sodipodi:rx="3.9999149"
sodipodi:ry="2.91429"
- d="m 434.99991,14.5 c 0,1.609518 -1.79082,2.91429 -3.99991,2.91429 -2.20909,0 -3.99991,-1.304772 -3.99991,-2.91429 0,-1.609518 1.79082,-2.91429 3.99991,-2.91429 2.20909,0 3.99991,1.304772 3.99991,2.91429 z" />
+ d="M 434.99991,14.5 A 3.9999149,2.91429 0 0 1 431,17.41429 3.9999149,2.91429 0 0 1 427.00009,14.5 3.9999149,2.91429 0 0 1 431,11.58571 3.9999149,2.91429 0 0 1 434.99991,14.5 Z" />
<path
transform="matrix(2.249956,0,0,2.251405,267.75278,4.81032)"
sodipodi:type="arc"
@@ -55821,7 +57669,7 @@
sodipodi:cy="135"
sodipodi:rx="1"
sodipodi:ry="1"
- d="m 65,135 c 0,0.55228 -0.447715,1 -1,1 -0.552285,0 -1,-0.44772 -1,-1 0,-0.55228 0.447715,-1 1,-1 0.552285,0 1,0.44772 1,1 z" />
+ d="m 65,135 a 1,1 0 0 1 -1,1 1,1 0 0 1 -1,-1 1,1 0 0 1 1,-1 1,1 0 0 1 1,1 z" />
<path
id="path27428"
d="m 412,306.5 c -3.5,0 -5,1.5 -6.5,3 1.5,1.5 2.75,4 6.5,4 3.75,0 5,-2.5 6.5,-4 -1.5,-1.5 -3,-3 -6.5,-3 z"
@@ -55844,12 +57692,12 @@
sodipodi:cy="135"
sodipodi:rx="1"
sodipodi:ry="1"
- d="m 65,135 c 0,0.55228 -0.447715,1 -1,1 -0.552285,0 -1,-0.44772 -1,-1 0,-0.55228 0.447715,-1 1,-1 0.552285,0 1,0.44772 1,1 z" />
+ d="m 65,135 a 1,1 0 0 1 -1,1 1,1 0 0 1 -1,-1 1,1 0 0 1 1,-1 1,1 0 0 1 1,1 z" />
</g>
</g>
<g
transform="translate(62.983887,-82)"
- id="g27434">
+ id="ICON_VISIBLE_IPO_OFF">
<g
id="g27436"
transform="translate(0.4838899,-6.2084382e-8)">
@@ -55888,7 +57736,7 @@
</g>
<g
transform="translate(147,170.00001)"
- id="g27500">
+ id="ICON_LAMP_DATA">
<rect
style="opacity:0;fill:#4d4d4d;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:6;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
id="rect27514"
@@ -56013,7 +57861,7 @@
sodipodi:cy="502"
sodipodi:rx="2.5312502"
sodipodi:ry="2.5"
- d="m 80.53125,502 c 0,1.38071 -1.133279,2.5 -2.53125,2.5 -1.397971,0 -2.53125,-1.11929 -2.53125,-2.5 0,-1.38071 1.133279,-2.5 2.53125,-2.5 1.397971,0 2.53125,1.11929 2.53125,2.5 z"
+ d="M 80.53125,502 A 2.5312502,2.5 0 0 1 78,504.5 2.5312502,2.5 0 0 1 75.46875,502 2.5312502,2.5 0 0 1 78,499.5 2.5312502,2.5 0 0 1 80.53125,502 Z"
transform="matrix(0.9552133,0,0,0.9315985,-40.901258,-140.2522)" />
<path
transform="matrix(0.99567,0,-0.00787885,1,-30.663533,191)"
@@ -56024,7 +57872,7 @@
sodipodi:cy="135"
sodipodi:rx="1"
sodipodi:ry="1"
- d="m 65,135 c 0,0.55228 -0.447715,1 -1,1 -0.552285,0 -1,-0.44772 -1,-1 0,-0.55228 0.447715,-1 1,-1 0.552285,0 1,0.44772 1,1 z"
+ d="m 65,135 a 1,1 0 0 1 -1,1 1,1 0 0 1 -1,-1 1,1 0 0 1 1,-1 1,1 0 0 1 1,1 z"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90" />
@@ -56087,14 +57935,55 @@
style="opacity:0.6;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:3.20000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
</g>
</g>
- <path
- style="opacity:0.25;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.89999998;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- d="m 263,16 0,3 1,0 0,-2 2,0 0,-1 -3,0 z"
- id="rect28902"
- inkscape:connector-curvature="0" />
+ <g
+ id="ICON_IMAGE_ZDEPTH">
+ <g
+ id="g17368"
+ transform="translate(302,-461)">
+ <rect
+ y="471"
+ x="-45"
+ height="16"
+ width="16"
+ id="rect17370"
+ style="opacity:0;fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <rect
+ y="472.5"
+ x="-43.483856"
+ height="13"
+ width="12.983856"
+ id="rect17372"
+ style="fill:url(#linearGradient17442);fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:0.80000001;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0.5;display:inline" />
+ <path
+ sodipodi:nodetypes="cccc"
+ id="path17374"
+ d="m -31.5,473.50001 -10.983862,0 0,11"
+ style="fill:none;stroke:url(#linearGradient17444);stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dashoffset:0.5;display:inline"
+ inkscape:connector-curvature="0" />
+ </g>
+ <rect
+ y="14"
+ x="261"
+ height="5"
+ width="5"
+ id="rect17376"
+ style="fill:#999999;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.89999998;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <rect
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.89999998;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect17379"
+ width="5"
+ height="5"
+ x="264"
+ y="17" />
+ <path
+ inkscape:connector-curvature="0"
+ id="rect28902"
+ d="m 263,16 0,3 1,0 0,-2 2,0 0,-1 -3,0 z"
+ style="opacity:0.25;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.89999998;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ </g>
<g
style="display:inline;enable-background:new"
- id="g28080"
+ id="ICON_MOD_FLUIDSIM"
transform="translate(-823,-175)">
<rect
y="416"
@@ -56109,7 +57998,7 @@
id="g28085">
<path
transform="matrix(1.1162596,0,0,1.1065394,67.801614,-350.49863)"
- d="m 80.53125,502 c 0,1.38071 -1.133279,2.5 -2.53125,2.5 -1.397971,0 -2.53125,-1.11929 -2.53125,-2.5 0,-1.38071 1.133279,-2.5 2.53125,-2.5 1.397971,0 2.53125,1.11929 2.53125,2.5 z"
+ d="M 80.53125,502 A 2.5312502,2.5 0 0 1 78,504.5 2.5312502,2.5 0 0 1 75.46875,502 2.5312502,2.5 0 0 1 78,499.5 2.5312502,2.5 0 0 1 80.53125,502 Z"
sodipodi:ry="2.5"
sodipodi:rx="2.5312502"
sodipodi:cy="502"
@@ -56125,7 +58014,7 @@
sodipodi:cy="502"
sodipodi:rx="2.5312502"
sodipodi:ry="2.5"
- d="m 80.53125,502 c 0,1.38071 -1.133279,2.5 -2.53125,2.5 -1.397971,0 -2.53125,-1.11929 -2.53125,-2.5 0,-1.38071 1.133279,-2.5 2.53125,-2.5 1.397971,0 2.53125,1.11929 2.53125,2.5 z"
+ d="M 80.53125,502 A 2.5312502,2.5 0 0 1 78,504.5 2.5312502,2.5 0 0 1 75.46875,502 2.5312502,2.5 0 0 1 78,499.5 2.5312502,2.5 0 0 1 80.53125,502 Z"
transform="matrix(-1.3568764,-0.3150232,0.3151738,-1.348049,102.81491,906.57916)" />
</g>
<path
@@ -56148,7 +58037,7 @@
sodipodi:cy="425"
sodipodi:rx="1.5"
sodipodi:ry="1"
- d="m 880,425 c 0,0.55228 -0.67157,1 -1.5,1 -0.82843,0 -1.5,-0.44772 -1.5,-1 0,-0.55228 0.67157,-1 1.5,-1 0.82843,0 1.5,0.44772 1.5,1 z"
+ d="m 880,425 a 1.5,1 0 0 1 -1.5,1 1.5,1 0 0 1 -1.5,-1 1.5,1 0 0 1 1.5,-1 1.5,1 0 0 1 1.5,1 z"
transform="matrix(0.6434675,-0.7329672,0.7942866,0.5945179,-26.858149,815.24158)" />
<path
inkscape:transform-center-y="-7.1785015"
@@ -56160,7 +58049,7 @@
sodipodi:cy="78.5"
sodipodi:rx="3.5"
sodipodi:ry="3.5"
- d="m 262,78.5 c 0,1.932997 -1.567,3.5 -3.5,3.5 -1.933,0 -3.5,-1.567003 -3.5,-3.5 0,-1.932997 1.567,-3.5 3.5,-3.5 1.933,0 3.5,1.567003 3.5,3.5 z"
+ d="M 262,78.5 A 3.5,3.5 0 0 1 258.5,82 3.5,3.5 0 0 1 255,78.5 3.5,3.5 0 0 1 258.5,75 3.5,3.5 0 0 1 262,78.5 Z"
transform="matrix(-1.2857095,0,0,1.2857143,1210.8559,325.57143)"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
inkscape:export-xdpi="90"
@@ -56168,7 +58057,7 @@
</g>
<g
transform="translate(-94.999994,403.00001)"
- id="g30296"
+ id="ICON_BORDERMOVE"
style="display:inline;enable-background:new">
<rect
style="opacity:0;fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
@@ -56368,7 +58257,7 @@
sodipodi:cy="78.5"
sodipodi:rx="3.5"
sodipodi:ry="3.5"
- d="m 262,78.5 c 0,1.932997 -1.567,3.5 -3.5,3.5 -1.933,0 -3.5,-1.567003 -3.5,-3.5 0,-1.932997 1.567,-3.5 3.5,-3.5 1.933,0 3.5,1.567003 3.5,3.5 z"
+ d="M 262,78.5 A 3.5,3.5 0 0 1 258.5,82 3.5,3.5 0 0 1 255,78.5 3.5,3.5 0 0 1 258.5,75 3.5,3.5 0 0 1 262,78.5 Z"
transform="matrix(-1.4627004,0,0,1.4628053,551.73128,85.525552)"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
inkscape:export-xdpi="90"
@@ -56414,7 +58303,7 @@
sodipodi:cy="78.5"
sodipodi:rx="3.5"
sodipodi:ry="3.5"
- d="m 262,78.5 c 0,1.932997 -1.567,3.5 -3.5,3.5 -1.933,0 -3.5,-1.567003 -3.5,-3.5 0,-1.932997 1.567,-3.5 3.5,-3.5 1.933,0 3.5,1.567003 3.5,3.5 z"
+ d="M 262,78.5 A 3.5,3.5 0 0 1 258.5,82 3.5,3.5 0 0 1 255,78.5 3.5,3.5 0 0 1 258.5,75 3.5,3.5 0 0 1 262,78.5 Z"
transform="matrix(-1.2468441,0,0,1.246865,503.16273,106.89331)" />
</g>
<path
@@ -56440,7 +58329,7 @@
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
transform="matrix(-1.4627004,0,0,1.4628053,551.73128,85.525552)"
- d="m 262,78.5 c 0,1.932997 -1.567,3.5 -3.5,3.5 -1.933,0 -3.5,-1.567003 -3.5,-3.5 0,-1.932997 1.567,-3.5 3.5,-3.5 1.933,0 3.5,1.567003 3.5,3.5 z"
+ d="M 262,78.5 A 3.5,3.5 0 0 1 258.5,82 3.5,3.5 0 0 1 255,78.5 3.5,3.5 0 0 1 258.5,75 3.5,3.5 0 0 1 262,78.5 Z"
sodipodi:ry="3.5"
sodipodi:rx="3.5"
sodipodi:cy="78.5"
@@ -56462,11 +58351,11 @@
sodipodi:cy="502"
sodipodi:rx="2.5312502"
sodipodi:ry="2.5"
- d="m 80.53125,502 c 0,1.38071 -1.133279,2.5 -2.53125,2.5 -1.397971,0 -2.53125,-1.11929 -2.53125,-2.5 0,-1.38071 1.133279,-2.5 2.53125,-2.5 1.397971,0 2.53125,1.11929 2.53125,2.5 z"
+ d="M 80.53125,502 A 2.5312502,2.5 0 0 1 78,504.5 2.5312502,2.5 0 0 1 75.46875,502 2.5312502,2.5 0 0 1 78,499.5 2.5312502,2.5 0 0 1 80.53125,502 Z"
transform="matrix(1.1162596,0,0,1.1065394,80.948334,-350.49863)" />
<path
transform="matrix(-1.087144,-0.2518404,0.2525206,-1.0776772,126.97246,766.619)"
- d="m 80.53125,502 c 0,1.38071 -1.133279,2.5 -2.53125,2.5 -1.397971,0 -2.53125,-1.11929 -2.53125,-2.5 0,-1.38071 1.133279,-2.5 2.53125,-2.5 1.397971,0 2.53125,1.11929 2.53125,2.5 z"
+ d="M 80.53125,502 A 2.5312502,2.5 0 0 1 78,504.5 2.5312502,2.5 0 0 1 75.46875,502 2.5312502,2.5 0 0 1 78,499.5 2.5312502,2.5 0 0 1 80.53125,502 Z"
sodipodi:ry="2.5"
sodipodi:rx="2.5312502"
sodipodi:cy="502"
@@ -56476,7 +58365,7 @@
sodipodi:type="arc" />
</g>
<path
- d="m 65,135 c 0,0.55228 -0.447715,1 -1,1 -0.552285,0 -1,-0.44772 -1,-1 0,-0.55228 0.447715,-1 1,-1 0.552285,0 1,0.44772 1,1 z"
+ d="m 65,135 a 1,1 0 0 1 -1,1 1,1 0 0 1 -1,-1 1,1 0 0 1 1,-1 1,1 0 0 1 1,1 z"
sodipodi:ry="1"
sodipodi:rx="1"
sodipodi:cy="135"
@@ -56495,7 +58384,7 @@
</g>
</g>
<g
- id="g28857">
+ id="ICON_MOD_MULTIRES">
<rect
y="241.00877"
x="68.001282"
@@ -56520,7 +58409,7 @@
sodipodi:cy="118"
sodipodi:rx="8"
sodipodi:ry="8"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90"
@@ -56535,7 +58424,7 @@
sodipodi:cy="118"
sodipodi:rx="8"
sodipodi:ry="8"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90" />
@@ -56594,7 +58483,7 @@
</g>
</g>
<g
- id="g56105">
+ id="ICON_DISK_DRIVE">
<rect
style="opacity:0;fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
id="rect29107"
@@ -56670,7 +58559,7 @@
</g>
<g
transform="translate(-0.1658249,128.41502)"
- id="g27744">
+ id="ICON_WORLD_DATA">
<rect
style="opacity:0;fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
id="rect27746"
@@ -56692,13 +58581,13 @@
sodipodi:cy="118"
sodipodi:rx="8"
sodipodi:ry="8"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90"
transform="matrix(0.787566,0,0,0.779223,26.709197,21.3179)" />
<path
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
sodipodi:ry="8"
sodipodi:rx="8"
sodipodi:cy="118"
@@ -56722,7 +58611,7 @@
sodipodi:cy="118"
sodipodi:rx="8"
sodipodi:ry="8"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z" />
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z" />
<path
sodipodi:nodetypes="cc"
id="path27757"
@@ -56740,7 +58629,7 @@
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
sodipodi:ry="8"
sodipodi:rx="8"
sodipodi:cy="118"
@@ -56750,7 +58639,7 @@
sodipodi:type="arc"
transform="matrix(0.6657538,0,0,0.6588051,42.794535,35.527157)" />
<path
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
sodipodi:ry="8"
sodipodi:rx="8"
sodipodi:cy="118"
@@ -56765,24 +58654,7 @@
</g>
</g>
<g
- style="fill:none;stroke:#ffffff;stroke-width:1.50000143;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:7.40000034;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- transform="translate(-323.1613,214)"
- inkscape:export-ydpi="90"
- inkscape:export-xdpi="90"
- inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
- id="g28643" />
- <g
- id="g29500" />
- <g
- transform="translate(1,24.000004)"
- id="g29613"
- style="opacity:0.3" />
- <g
- style="opacity:0.3"
- id="g29692"
- transform="translate(0,18)" />
- <g
- id="g34067"
+ id="ICON_SNAP_PEEL_OBJECT"
transform="translate(0,2)">
<g
id="g31771"
@@ -56885,24 +58757,7 @@
</g>
</g>
<g
- transform="matrix(-0.767131,0,0,0.788662,369.34347,270.08667)"
- style="fill:#000000;fill-opacity:1"
- id="g33443"
- inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
- inkscape:export-xdpi="90"
- inkscape:export-ydpi="90" />
- <g
- transform="matrix(-0.693332,0,0,0.663699,372.90657,295.34421)"
- id="g33445"
- inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
- inkscape:export-xdpi="90"
- inkscape:export-ydpi="90" />
- <g
- id="g33447"
- style="opacity:0.3"
- transform="matrix(-1,0,0,1,762.99997,233.00003)" />
- <g
- id="g31977"
+ id="ICON_CURVE_DATA"
transform="translate(63,212.00001)">
<rect
ry="0"
@@ -56981,7 +58836,7 @@
</g>
<g
style="display:inline"
- id="g32016"
+ id="ICON_MESH_DATA"
transform="translate(-474,676.00001)">
<rect
style="opacity:0;fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
@@ -57063,7 +58918,7 @@
</g>
</g>
<g
- id="g32042"
+ id="ICON_LATTICE_DATA"
transform="translate(83,212.00001)">
<rect
y="68"
@@ -57129,7 +58984,7 @@
</g>
</g>
<g
- id="g25012"
+ id="ICON_SURFACE_DATA"
transform="translate(-83.999998,191)">
<rect
transform="scale(-1,1)"
@@ -57278,7 +59133,7 @@
</g>
</g>
<g
- id="g32145"
+ id="ICON_EMPTY_DATA"
transform="translate(147,191.00001)">
<g
transform="translate(-138,212)"
@@ -57317,7 +59172,7 @@
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png"
transform="matrix(1.176776,0,0,1.176776,-12.47787,-2.548088)"
- d="M 72,14.5 C 72,15.328427 71.328427,16 70.5,16 69.671573,16 69,15.328427 69,14.5 69,13.671573 69.671573,13 70.5,13 c 0.828427,0 1.5,0.671573 1.5,1.5 z"
+ d="M 72,14.5 A 1.5,1.5 0 0 1 70.5,16 1.5,1.5 0 0 1 69,14.5 1.5,1.5 0 0 1 70.5,13 1.5,1.5 0 0 1 72,14.5 Z"
sodipodi:ry="1.5"
sodipodi:rx="1.5"
sodipodi:cy="14.5"
@@ -57496,7 +59351,7 @@
</g>
<g
style="display:inline;enable-background:new"
- id="g52805"
+ id="ICON_WPAINT_HLT"
transform="translate(185,94.000007)">
<rect
style="opacity:0;fill:#1a1a1a;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
@@ -57606,94 +59461,97 @@
</g>
</g>
</g>
- <rect
- style="opacity:0;fill:#1a1a1a;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- id="rect52845"
- width="16"
- height="16"
- x="89"
- y="514" />
<g
- mask="url(#mask38474)"
- transform="translate(-254.01612,339.00001)"
- id="g52847">
+ id="ICON_TPAINT_HLT">
<rect
- style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:#1a1a1a;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;display:inline"
- id="rect52849"
- width="12.871031"
- height="13.001007"
- x="343.51614"
- y="175.49899" />
- <path
- style="fill:url(#linearGradient53129);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- d="m 344.01612,176 0,3 3,0 0,-3 -3,0 z m 3,3 0,3 3,0 0,-3 -3,0 z m 3,0 3,0 0,-3 -3,0 0,3 z m -3,3 -3,0 0,3 3,0 0,-3 z"
- id="path52851"
- inkscape:connector-curvature="0" />
- <path
- inkscape:export-ydpi="90"
- inkscape:export-xdpi="90"
- inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
- id="path52853"
- d="m 344.50621,187.50705 0,-11.00155 10.89034,0"
- style="opacity:0.9;fill:none;stroke:url(#linearGradient53131);stroke-width:0.9999997px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1;display:inline"
- inkscape:connector-curvature="0" />
- </g>
- <g
- transform="translate(-414.98389,546.98571)"
- style="display:inline;enable-background:new"
- id="g52855">
- <path
- sodipodi:nodetypes="ccccc"
- id="path52857"
- d="m 506.48389,-17.45862 0,-1 c 4.75,-1 2.25,-4.5 6.31852,-4.187139 0.70341,0.496889 0.93148,1.187139 0.93148,2.122782 0,3.064357 -2.5,3.314357 -7.25,3.064357 l 0,0 0,0 0,0 z"
- style="fill:#9d6c53;fill-opacity:1;fill-rule:evenodd;stroke:#241f1c;stroke-width:0.80000001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
- inkscape:connector-curvature="0" />
- <path
- style="opacity:0.7;fill:url(#radialGradient53133);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- d="m 505.98389,-17.522977 c 5.75,-0.75 2.71305,-4.172284 6.75,-5.25 0.70341,0.496889 1.61991,1.711436 1.75268,2.186272 0,3.572675 -4.12319,3.136436 -8.50268,3.063728 l 0,0 0,0 0,0 z"
- id="path52859"
- sodipodi:nodetypes="cccc"
- inkscape:connector-curvature="0" />
- <path
- sodipodi:nodetypes="cccc"
- id="path52861"
- d="m 515.48389,-25.95862 -2.75,3.25 1.75,2.25 3,-3"
- style="fill:none;stroke:#0b1728;stroke-width:0.89999998;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- inkscape:connector-curvature="0" />
- <path
- style="fill:url(#linearGradient53135);fill-opacity:1;fill-rule:evenodd;stroke:none"
- d="m 514.98389,-24.95862 -2.25,2.5 1.37109,1.875 2.37891,-2.375 -1.5,-2 z"
- id="path52863"
- sodipodi:nodetypes="ccccc"
- inkscape:connector-curvature="0" />
- <path
- style="fill:none;stroke:#2b0000;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- d="m 519.48389,-30.45862 -5,5.75 2,2.25 3,-3"
- id="path52865"
- sodipodi:nodetypes="cccc"
- inkscape:connector-curvature="0" />
- <path
- sodipodi:nodetypes="ccccc"
- id="path52867"
- d="m 519.98389,-30.70862 -5.75,6.5 1.75,1.75 4,-3.75 0,-4.5 z"
- style="fill:url(#linearGradient53137);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.23326063;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- inkscape:connector-curvature="0" />
- <path
- style="opacity:0.6;fill:none;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
- d="m 513.48389,-22.45862 6,-7"
- id="path52869"
- sodipodi:nodetypes="cc"
- inkscape:connector-curvature="0" />
- <path
- style="opacity:0.4;fill:none;stroke:url(#linearGradient53139);stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1;display:inline"
- d="m 511.98389,-21.772977 -1.25,1.25 c -0.96702,0.819679 -0.76749,2.123051 -3.25,2.314357"
- id="path52871"
- sodipodi:nodetypes="ccc"
- inkscape:connector-curvature="0" />
+ y="514"
+ x="89"
+ height="16"
+ width="16"
+ id="rect52845"
+ style="opacity:0;fill:#1a1a1a;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <g
+ id="g52847"
+ transform="translate(-254.01612,339.00001)"
+ mask="url(#mask38474)">
+ <rect
+ y="175.49899"
+ x="343.51614"
+ height="13.001007"
+ width="12.871031"
+ id="rect52849"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:#1a1a1a;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;display:inline" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path52851"
+ d="m 344.01612,176 0,3 3,0 0,-3 -3,0 z m 3,3 0,3 3,0 0,-3 -3,0 z m 3,0 3,0 0,-3 -3,0 0,3 z m -3,3 -3,0 0,3 3,0 0,-3 z"
+ style="fill:url(#linearGradient53129);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <path
+ inkscape:connector-curvature="0"
+ style="opacity:0.9;fill:none;stroke:url(#linearGradient53131);stroke-width:0.9999997px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1;display:inline"
+ d="m 344.50621,187.50705 0,-11.00155 10.89034,0"
+ id="path52853"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ </g>
+ <g
+ id="g52855"
+ style="display:inline;enable-background:new"
+ transform="translate(-414.98389,546.98571)">
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:#9d6c53;fill-opacity:1;fill-rule:evenodd;stroke:#241f1c;stroke-width:0.80000001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 506.48389,-17.45862 0,-1 c 4.75,-1 2.25,-4.5 6.31852,-4.187139 0.70341,0.496889 0.93148,1.187139 0.93148,2.122782 0,3.064357 -2.5,3.314357 -7.25,3.064357 l 0,0 0,0 0,0 z"
+ id="path52857"
+ sodipodi:nodetypes="ccccc" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cccc"
+ id="path52859"
+ d="m 505.98389,-17.522977 c 5.75,-0.75 2.71305,-4.172284 6.75,-5.25 0.70341,0.496889 1.61991,1.711436 1.75268,2.186272 0,3.572675 -4.12319,3.136436 -8.50268,3.063728 l 0,0 0,0 0,0 z"
+ style="opacity:0.7;fill:url(#radialGradient53133);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#0b1728;stroke-width:0.89999998;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 515.48389,-25.95862 -2.75,3.25 1.75,2.25 3,-3"
+ id="path52861"
+ sodipodi:nodetypes="cccc" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccc"
+ id="path52863"
+ d="m 514.98389,-24.95862 -2.25,2.5 1.37109,1.875 2.37891,-2.375 -1.5,-2 z"
+ style="fill:url(#linearGradient53135);fill-opacity:1;fill-rule:evenodd;stroke:none" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cccc"
+ id="path52865"
+ d="m 519.48389,-30.45862 -5,5.75 2,2.25 3,-3"
+ style="fill:none;stroke:#2b0000;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:url(#linearGradient53137);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.23326063;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 519.98389,-30.70862 -5.75,6.5 1.75,1.75 4,-3.75 0,-4.5 z"
+ id="path52867"
+ sodipodi:nodetypes="ccccc" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cc"
+ id="path52869"
+ d="m 513.48389,-22.45862 6,-7"
+ style="opacity:0.6;fill:none;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccc"
+ id="path52871"
+ d="m 511.98389,-21.772977 -1.25,1.25 c -0.96702,0.819679 -0.76749,2.123051 -3.25,2.314357"
+ style="opacity:0.4;fill:none;stroke:url(#linearGradient53139);stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1;display:inline" />
+ </g>
</g>
<g
style="display:inline;enable-background:new"
- id="g52873"
+ id="ICON_VPAINT_HLT"
transform="translate(120,94.000007)">
<rect
y="420"
@@ -57784,7 +59642,7 @@
</g>
<g
transform="translate(318,94.000007)"
- id="g52903"
+ id="ICON_LIGHTPAINT"
style="display:inline;enable-background:new">
<rect
style="opacity:0;fill:#1a1a1a;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
@@ -57906,7 +59764,7 @@
inkscape:connector-curvature="0" />
<path
transform="matrix(0.8490785,0,0,0.8469086,71.921104,-98.093334)"
- d="m 80.53125,502 c 0,1.38071 -1.133279,2.5 -2.53125,2.5 -1.397971,0 -2.53125,-1.11929 -2.53125,-2.5 0,-1.38071 1.133279,-2.5 2.53125,-2.5 1.397971,0 2.53125,1.11929 2.53125,2.5 z"
+ d="M 80.53125,502 A 2.5312502,2.5 0 0 1 78,504.5 2.5312502,2.5 0 0 1 75.46875,502 2.5312502,2.5 0 0 1 78,499.5 2.5312502,2.5 0 0 1 80.53125,502 Z"
sodipodi:ry="2.5"
sodipodi:rx="2.5312502"
sodipodi:cy="502"
@@ -57918,7 +59776,7 @@
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png"
- d="m 65,135 c 0,0.55228 -0.447715,1 -1,1 -0.552285,0 -1,-0.44772 -1,-1 0,-0.55228 0.447715,-1 1,-1 0.552285,0 1,0.44772 1,1 z"
+ d="m 65,135 a 1,1 0 0 1 -1,1 1,1 0 0 1 -1,-1 1,1 0 0 1 1,-1 1,1 0 0 1 1,1 z"
sodipodi:ry="1"
sodipodi:rx="1"
sodipodi:cy="135"
@@ -58032,11 +59890,7 @@
</g>
</g>
<g
- id="g77742"
- style="fill:#ffeeaa;display:inline"
- transform="translate(-870.9421,-297.02038)" />
- <g
- id="g33404"
+ id="ICON_RETOPO"
transform="translate(-20.999997,23)">
<rect
style="opacity:0;fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
@@ -58056,7 +59910,7 @@
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
sodipodi:ry="8"
sodipodi:rx="8"
sodipodi:cy="118"
@@ -58073,7 +59927,7 @@
sodipodi:cy="118"
sodipodi:rx="8"
sodipodi:ry="8"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90"
@@ -58087,7 +59941,7 @@
sodipodi:cy="118"
sodipodi:rx="8"
sodipodi:ry="8"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90" />
@@ -58183,7 +60037,7 @@
</g>
<g
style="display:inline;enable-background:new"
- id="g50822"
+ id="ICON_OOPS"
transform="translate(74,89.000007)">
<rect
style="opacity:0;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.80000001;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
@@ -58336,7 +60190,7 @@
style="opacity:0.1;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
</g>
<g
- id="g33837"
+ id="ICON_SNAP_NORMAL"
transform="translate(-42,23)">
<rect
style="opacity:0.01000001;fill:#4d4d4d;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.29999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
@@ -58357,7 +60211,7 @@
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
sodipodi:ry="8"
sodipodi:rx="8"
sodipodi:cy="118"
@@ -58374,7 +60228,7 @@
sodipodi:cy="118"
sodipodi:rx="8"
sodipodi:ry="8"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90"
@@ -58388,7 +60242,7 @@
sodipodi:cy="118"
sodipodi:rx="8"
sodipodi:ry="8"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90" />
@@ -58439,7 +60293,7 @@
<g
style="display:inline;enable-background:new"
transform="translate(84,-124)"
- id="g36191"
+ id="ICON_GRID"
mask="url(#mask25369)">
<rect
y="281"
@@ -58473,190 +60327,193 @@
id="path36201"
inkscape:connector-curvature="0" />
</g>
- <path
- inkscape:transform-center-y="-6.547647"
- inkscape:transform-center-x="-6.5102284"
- sodipodi:type="arc"
- style="fill:url(#radialGradient24523);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.63636374;marker:none;display:inline"
- id="path36205"
- sodipodi:cx="258.5"
- sodipodi:cy="78.5"
- sodipodi:rx="3.5"
- sodipodi:ry="3.5"
- d="m 262,78.5 a 3.5,3.5 0 1 1 -7,0 3.5,3.5 0 1 1 7,0 z"
- transform="matrix(-1.5002341,0,0,1.5000004,549.81053,465.24998)"
- inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
- inkscape:export-xdpi="90"
- inkscape:export-ydpi="90" />
- <path
- style="opacity:0.96000001;fill:#ff8400;fill-opacity:1;fill-rule:evenodd;stroke:#2b2200;stroke-width:0.80000001;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- d="m 159.5,582.50001 0,5.40625 c 0.75032,0.38395 1.59977,0.59375 2.5,0.59375 0.90022,0 1.74968,-0.2098 2.5,-0.59375 l 0,-5.40625 -5,0 z"
- id="path36207"
- inkscape:connector-curvature="0" />
- <path
- id="path36209"
- d="m 160.5,586.25001 0,-2.75 3,0"
- style="opacity:0.76799999;fill:none;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
- sodipodi:nodetypes="ccc"
- inkscape:connector-curvature="0" />
- <path
- style="opacity:0.96000001;fill:#ff8400;fill-opacity:1;fill-rule:evenodd;stroke:#2b2200;stroke-width:0.80000001;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- d="m 165.5,587.25001 c -1.25,1 -2.5,1.25 -3,1.25 l 0,3 2.98688,0 0.0131,-4.25 2e-5,0 0,0 0,0 z"
- id="path36211"
- sodipodi:nodetypes="ccccc"
- inkscape:connector-curvature="0" />
- <path
- style="opacity:0.672;fill:none;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
- d="m 163.5,590.50001 0,-2"
- id="path36213"
- sodipodi:nodetypes="cc"
- inkscape:connector-curvature="0" />
- <rect
- y="577"
- x="152"
- height="16"
- width="16"
- id="rect36215"
- style="opacity:0;fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
- <path
- inkscape:export-ydpi="90"
- inkscape:export-xdpi="90"
- inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
- sodipodi:nodetypes="cc"
- id="path36217"
- d="m 156.5,588.50001 1.5,-1.5"
- style="opacity:0.96000001;fill:none;stroke:#000000;stroke-width:2;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
- inkscape:connector-curvature="0" />
- <path
- inkscape:export-ydpi="90"
- inkscape:export-xdpi="90"
- inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
- transform="matrix(-1.5002341,0,0,1.5000004,549.81053,465.24998)"
- d="m 262,78.5 a 3.5,3.5 0 1 1 -7,0 3.5,3.5 0 1 1 7,0 z"
- sodipodi:ry="3.5"
- sodipodi:rx="3.5"
- sodipodi:cy="78.5"
- sodipodi:cx="258.5"
- id="path36220"
- style="opacity:0.48000004;fill:url(#radialGradient24519);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.63636374;marker:none;display:inline"
- sodipodi:type="arc"
- inkscape:transform-center-x="-6.5102284"
- inkscape:transform-center-y="-6.547647" />
- <path
- inkscape:transform-center-y="-6.8594309"
- inkscape:transform-center-x="-6.8191649"
- sodipodi:type="arc"
- style="opacity:0.96000001;fill:none;stroke:#000000;stroke-width:0.57272732;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;display:inline"
- id="path36222"
- sodipodi:cx="258.5"
- sodipodi:cy="78.5"
- sodipodi:rx="3.5"
- sodipodi:ry="3.5"
- d="m 262,78.5 a 3.5,3.5 0 1 1 -7,0 3.5,3.5 0 1 1 7,0 z"
- transform="matrix(-1.5714299,0,0,1.5714268,568.21462,459.64301)"
- inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
- inkscape:export-xdpi="90"
- inkscape:export-ydpi="90" />
- <path
- style="opacity:0.96000001;fill:none;stroke:#28170b;stroke-width:3.70000005;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
- d="M 153.86319,591.13808 156.25,588.75001"
- id="path36224"
- sodipodi:nodetypes="cc"
- inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
- inkscape:export-xdpi="90"
- inkscape:export-ydpi="90"
- inkscape:connector-curvature="0" />
- <path
- style="opacity:0.96000001;fill:none;stroke:#cccccc;stroke-width:1.29999995;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
- d="m 156.5,588.50001 1.5,-1.5"
- id="path36226"
- sodipodi:nodetypes="cc"
- inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
- inkscape:export-xdpi="90"
- inkscape:export-ydpi="90"
- inkscape:connector-curvature="0" />
<g
- style="opacity:0.96000001"
- id="g36228"
- inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
- inkscape:export-xdpi="90"
- inkscape:export-ydpi="90"
- transform="matrix(1.0988734,0,0,1.0981343,-23.179949,357.33845)">
+ id="ICON_ZOOM_SELECTED">
+ <path
+ inkscape:export-ydpi="90"
+ inkscape:export-xdpi="90"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
+ transform="matrix(-1.5002341,0,0,1.5000004,549.81053,465.24998)"
+ d="m 262,78.5 a 3.5,3.5 0 1 1 -7,0 3.5,3.5 0 1 1 7,0 z"
+ sodipodi:ry="3.5"
+ sodipodi:rx="3.5"
+ sodipodi:cy="78.5"
+ sodipodi:cx="258.5"
+ id="path36205"
+ style="fill:url(#radialGradient24523);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.63636374;marker:none;display:inline"
+ sodipodi:type="arc"
+ inkscape:transform-center-x="-6.5102284"
+ inkscape:transform-center-y="-6.547647" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path36207"
+ d="m 159.5,582.50001 0,5.40625 c 0.75032,0.38395 1.59977,0.59375 2.5,0.59375 0.90022,0 1.74968,-0.2098 2.5,-0.59375 l 0,-5.40625 -5,0 z"
+ style="opacity:0.96000001;fill:#ff8400;fill-opacity:1;fill-rule:evenodd;stroke:#2b2200;stroke-width:0.80000001;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccc"
+ style="opacity:0.76799999;fill:none;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 160.5,586.25001 0,-2.75 3,0"
+ id="path36209" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccc"
+ id="path36211"
+ d="m 165.5,587.25001 c -1.25,1 -2.5,1.25 -3,1.25 l 0,3 2.98688,0 0.0131,-4.25 2e-5,0 0,0 0,0 z"
+ style="opacity:0.96000001;fill:#ff8400;fill-opacity:1;fill-rule:evenodd;stroke:#2b2200;stroke-width:0.80000001;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cc"
+ id="path36213"
+ d="m 163.5,590.50001 0,-2"
+ style="opacity:0.672;fill:none;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1" />
+ <rect
+ style="opacity:0;fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect36215"
+ width="16"
+ height="16"
+ x="152"
+ y="577" />
+ <path
+ inkscape:connector-curvature="0"
+ style="opacity:0.96000001;fill:none;stroke:#000000;stroke-width:2;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 156.5,588.50001 1.5,-1.5"
+ id="path36217"
+ sodipodi:nodetypes="cc"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
<path
- inkscape:transform-center-y="-4.9844055"
- inkscape:transform-center-x="-4.9755572"
+ inkscape:transform-center-y="-6.547647"
+ inkscape:transform-center-x="-6.5102284"
sodipodi:type="arc"
- style="fill:url(#linearGradient24511);fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient24513);stroke-width:0.79652983;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;display:inline"
- id="path36230"
+ style="opacity:0.48000004;fill:url(#radialGradient24519);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.63636374;marker:none;display:inline"
+ id="path36220"
sodipodi:cx="258.5"
sodipodi:cy="78.5"
sodipodi:rx="3.5"
sodipodi:ry="3.5"
- d="m 262,78.5 c 0,1.932997 -1.567,3.5 -3.5,3.5 -1.933,0 -3.5,-1.567003 -3.5,-3.5 0,-1.932997 1.567,-3.5 3.5,-3.5 1.933,0 3.5,1.567003 3.5,3.5 z"
- transform="matrix(-1.14287,0,0,1.142863,463.9317,115.80133)" />
+ d="m 262,78.5 a 3.5,3.5 0 1 1 -7,0 3.5,3.5 0 1 1 7,0 z"
+ transform="matrix(-1.5002341,0,0,1.5000004,549.81053,465.24998)"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <path
+ inkscape:export-ydpi="90"
+ inkscape:export-xdpi="90"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
+ transform="matrix(-1.5714299,0,0,1.5714268,568.21462,459.64301)"
+ d="m 262,78.5 a 3.5,3.5 0 1 1 -7,0 3.5,3.5 0 1 1 7,0 z"
+ sodipodi:ry="3.5"
+ sodipodi:rx="3.5"
+ sodipodi:cy="78.5"
+ sodipodi:cx="258.5"
+ id="path36222"
+ style="opacity:0.96000001;fill:none;stroke:#000000;stroke-width:0.57272732;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;display:inline"
+ sodipodi:type="arc"
+ inkscape:transform-center-x="-6.8191649"
+ inkscape:transform-center-y="-6.8594309" />
+ <path
+ inkscape:connector-curvature="0"
+ inkscape:export-ydpi="90"
+ inkscape:export-xdpi="90"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
+ sodipodi:nodetypes="cc"
+ id="path36224"
+ d="M 153.86319,591.13808 156.25,588.75001"
+ style="opacity:0.96000001;fill:none;stroke:#28170b;stroke-width:3.70000005;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+ <path
+ inkscape:connector-curvature="0"
+ inkscape:export-ydpi="90"
+ inkscape:export-xdpi="90"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
+ sodipodi:nodetypes="cc"
+ id="path36226"
+ d="m 156.5,588.50001 1.5,-1.5"
+ style="opacity:0.96000001;fill:none;stroke:#cccccc;stroke-width:1.29999995;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
<g
- id="g36232">
+ transform="matrix(1.0988734,0,0,1.0981343,-23.179949,357.33845)"
+ inkscape:export-ydpi="90"
+ inkscape:export-xdpi="90"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
+ id="g36228"
+ style="opacity:0.96000001">
<path
- transform="matrix(1.1162596,0,0,1.1065394,80.948334,-350.49863)"
- d="m 80.53125,502 c 0,1.38071 -1.133279,2.5 -2.53125,2.5 -1.397971,0 -2.53125,-1.11929 -2.53125,-2.5 0,-1.38071 1.133279,-2.5 2.53125,-2.5 1.397971,0 2.53125,1.11929 2.53125,2.5 z"
- sodipodi:ry="2.5"
- sodipodi:rx="2.5312502"
- sodipodi:cy="502"
- sodipodi:cx="78"
- id="path36234"
- style="opacity:0.25;fill:url(#radialGradient24515);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.26754272;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- sodipodi:type="arc" />
+ transform="matrix(-1.14287,0,0,1.142863,463.9317,115.80133)"
+ d="M 262,78.5 A 3.5,3.5 0 0 1 258.5,82 3.5,3.5 0 0 1 255,78.5 3.5,3.5 0 0 1 258.5,75 3.5,3.5 0 0 1 262,78.5 Z"
+ sodipodi:ry="3.5"
+ sodipodi:rx="3.5"
+ sodipodi:cy="78.5"
+ sodipodi:cx="258.5"
+ id="path36230"
+ style="fill:url(#linearGradient24511);fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient24513);stroke-width:0.79652983;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;display:inline"
+ sodipodi:type="arc"
+ inkscape:transform-center-x="-4.9755572"
+ inkscape:transform-center-y="-4.9844055" />
+ <g
+ id="g36232">
+ <path
+ sodipodi:type="arc"
+ style="opacity:0.25;fill:url(#radialGradient24515);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.26754272;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="path36234"
+ sodipodi:cx="78"
+ sodipodi:cy="502"
+ sodipodi:rx="2.5312502"
+ sodipodi:ry="2.5"
+ d="M 80.53125,502 A 2.5312502,2.5 0 0 1 78,504.5 2.5312502,2.5 0 0 1 75.46875,502 2.5312502,2.5 0 0 1 78,499.5 2.5312502,2.5 0 0 1 80.53125,502 Z"
+ transform="matrix(1.1162596,0,0,1.1065394,80.948334,-350.49863)" />
+ <path
+ transform="matrix(-1.087144,-0.2518404,0.2525206,-1.0776772,126.97246,766.619)"
+ d="M 80.53125,502 A 2.5312502,2.5 0 0 1 78,504.5 2.5312502,2.5 0 0 1 75.46875,502 2.5312502,2.5 0 0 1 78,499.5 2.5312502,2.5 0 0 1 80.53125,502 Z"
+ sodipodi:ry="2.5"
+ sodipodi:rx="2.5312502"
+ sodipodi:cy="502"
+ sodipodi:cx="78"
+ id="path36236"
+ style="opacity:0.25;fill:url(#radialGradient24517);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.26754272;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ sodipodi:type="arc" />
+ </g>
<path
+ transform="matrix(0.9100226,0,0,0.9106329,108.4468,80.751664)"
sodipodi:type="arc"
- style="opacity:0.25;fill:url(#radialGradient24517);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.26754272;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- id="path36236"
- sodipodi:cx="78"
- sodipodi:cy="502"
- sodipodi:rx="2.5312502"
- sodipodi:ry="2.5"
- d="m 80.53125,502 c 0,1.38071 -1.133279,2.5 -2.53125,2.5 -1.397971,0 -2.53125,-1.11929 -2.53125,-2.5 0,-1.38071 1.133279,-2.5 2.53125,-2.5 1.397971,0 2.53125,1.11929 2.53125,2.5 z"
- transform="matrix(-1.087144,-0.2518404,0.2525206,-1.0776772,126.97246,766.619)" />
+ style="opacity:0.7;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.74699998;marker:none;display:inline"
+ id="path36238"
+ sodipodi:cx="64"
+ sodipodi:cy="135"
+ sodipodi:rx="1"
+ sodipodi:ry="1"
+ d="m 65,135 a 1,1 0 0 1 -1,1 1,1 0 0 1 -1,-1 1,1 0 0 1 1,-1 1,1 0 0 1 1,1 z"
+ inkscape:transform-center-x="-3.1120555"
+ inkscape:transform-center-y="-5.7593212" />
</g>
<path
- inkscape:transform-center-y="-5.7593212"
- inkscape:transform-center-x="-3.1120555"
- d="m 65,135 c 0,0.55228 -0.447715,1 -1,1 -0.552285,0 -1,-0.44772 -1,-1 0,-0.55228 0.447715,-1 1,-1 0.552285,0 1,0.44772 1,1 z"
- sodipodi:ry="1"
- sodipodi:rx="1"
- sodipodi:cy="135"
- sodipodi:cx="64"
- id="path36238"
- style="opacity:0.7;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.74699998;marker:none;display:inline"
- sodipodi:type="arc"
- transform="matrix(0.9100226,0,0,0.9106329,108.4468,80.751664)" />
+ inkscape:connector-curvature="0"
+ style="opacity:0.96000001;fill:none;stroke:#a05a2c;stroke-width:2;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 153.75,591.25001 2.5,-2.5"
+ id="path36240"
+ sodipodi:nodetypes="cc"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <path
+ inkscape:connector-curvature="0"
+ inkscape:export-ydpi="90"
+ inkscape:export-xdpi="90"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
+ sodipodi:nodetypes="cc"
+ id="path36242"
+ d="m 153.25,591.00001 2.75,-2.75"
+ style="opacity:0.672;fill:none;stroke:#ffffff;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cccc"
+ style="opacity:0.48000004;fill:none;stroke:#2b2200;stroke-width:0.80000001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 164.5,585.25001 0,-2.75 -5,0 0,2.75"
+ id="path36244" />
</g>
- <path
- inkscape:export-ydpi="90"
- inkscape:export-xdpi="90"
- inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
- sodipodi:nodetypes="cc"
- id="path36240"
- d="m 153.75,591.25001 2.5,-2.5"
- style="opacity:0.96000001;fill:none;stroke:#a05a2c;stroke-width:2;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
- inkscape:connector-curvature="0" />
- <path
- style="opacity:0.672;fill:none;stroke:#ffffff;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
- d="m 153.25,591.00001 2.75,-2.75"
- id="path36242"
- sodipodi:nodetypes="cc"
- inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
- inkscape:export-xdpi="90"
- inkscape:export-ydpi="90"
- inkscape:connector-curvature="0" />
- <path
- id="path36244"
- d="m 164.5,585.25001 0,-2.75 -5,0 0,2.75"
- style="opacity:0.48000004;fill:none;stroke:#2b2200;stroke-width:0.80000001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- sodipodi:nodetypes="cccc"
- inkscape:connector-curvature="0" />
<g
style="opacity:0.96000001;display:inline;enable-background:new"
- id="g36246"
+ id="ICON_ZOOM_ALL"
transform="translate(60,59)">
<rect
style="opacity:0;fill:#999999;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.80000001;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
@@ -58764,7 +60621,7 @@
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
transform="matrix(-1.4627004,0,0,1.4628053,551.73128,85.525552)"
- d="m 262,78.5 c 0,1.932997 -1.567,3.5 -3.5,3.5 -1.933,0 -3.5,-1.567003 -3.5,-3.5 0,-1.932997 1.567,-3.5 3.5,-3.5 1.933,0 3.5,1.567003 3.5,3.5 z"
+ d="M 262,78.5 A 3.5,3.5 0 0 1 258.5,82 3.5,3.5 0 0 1 255,78.5 3.5,3.5 0 0 1 258.5,75 3.5,3.5 0 0 1 262,78.5 Z"
sodipodi:ry="3.5"
sodipodi:rx="3.5"
sodipodi:cy="78.5"
@@ -58809,7 +60666,7 @@
id="g36286">
<path
transform="matrix(-1.2468441,0,0,1.246865,503.16273,106.89331)"
- d="m 262,78.5 c 0,1.932997 -1.567,3.5 -3.5,3.5 -1.933,0 -3.5,-1.567003 -3.5,-3.5 0,-1.932997 1.567,-3.5 3.5,-3.5 1.933,0 3.5,1.567003 3.5,3.5 z"
+ d="M 262,78.5 A 3.5,3.5 0 0 1 258.5,82 3.5,3.5 0 0 1 255,78.5 3.5,3.5 0 0 1 258.5,75 3.5,3.5 0 0 1 262,78.5 Z"
sodipodi:ry="3.5"
sodipodi:rx="3.5"
sodipodi:cy="78.5"
@@ -58846,7 +60703,7 @@
sodipodi:cy="78.5"
sodipodi:rx="3.5"
sodipodi:ry="3.5"
- d="m 262,78.5 c 0,1.932997 -1.567,3.5 -3.5,3.5 -1.933,0 -3.5,-1.567003 -3.5,-3.5 0,-1.932997 1.567,-3.5 3.5,-3.5 1.933,0 3.5,1.567003 3.5,3.5 z"
+ d="M 262,78.5 A 3.5,3.5 0 0 1 258.5,82 3.5,3.5 0 0 1 255,78.5 3.5,3.5 0 0 1 258.5,75 3.5,3.5 0 0 1 262,78.5 Z"
transform="matrix(-1.4627004,0,0,1.4628053,551.73128,85.525552)"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
inkscape:export-xdpi="90"
@@ -58857,7 +60714,7 @@
id="g36296">
<path
transform="matrix(1.1162596,0,0,1.1065394,80.948334,-350.49863)"
- d="m 80.53125,502 c 0,1.38071 -1.133279,2.5 -2.53125,2.5 -1.397971,0 -2.53125,-1.11929 -2.53125,-2.5 0,-1.38071 1.133279,-2.5 2.53125,-2.5 1.397971,0 2.53125,1.11929 2.53125,2.5 z"
+ d="M 80.53125,502 A 2.5312502,2.5 0 0 1 78,504.5 2.5312502,2.5 0 0 1 75.46875,502 2.5312502,2.5 0 0 1 78,499.5 2.5312502,2.5 0 0 1 80.53125,502 Z"
sodipodi:ry="2.5"
sodipodi:rx="2.5312502"
sodipodi:cy="502"
@@ -58873,7 +60730,7 @@
sodipodi:cy="502"
sodipodi:rx="2.5312502"
sodipodi:ry="2.5"
- d="m 80.53125,502 c 0,1.38071 -1.133279,2.5 -2.53125,2.5 -1.397971,0 -2.53125,-1.11929 -2.53125,-2.5 0,-1.38071 1.133279,-2.5 2.53125,-2.5 1.397971,0 2.53125,1.11929 2.53125,2.5 z"
+ d="M 80.53125,502 A 2.5312502,2.5 0 0 1 78,504.5 2.5312502,2.5 0 0 1 75.46875,502 2.5312502,2.5 0 0 1 78,499.5 2.5312502,2.5 0 0 1 80.53125,502 Z"
transform="matrix(-1.087144,-0.2518404,0.2525206,-1.0776772,126.97246,766.619)" />
</g>
<path
@@ -58885,13 +60742,13 @@
sodipodi:cy="135"
sodipodi:rx="1"
sodipodi:ry="1"
- d="m 65,135 c 0,0.55228 -0.447715,1 -1,1 -0.552285,0 -1,-0.44772 -1,-1 0,-0.55228 0.447715,-1 1,-1 0.552285,0 1,0.44772 1,1 z" />
+ d="m 65,135 a 1,1 0 0 1 -1,1 1,1 0 0 1 -1,-1 1,1 0 0 1 1,-1 1,1 0 0 1 1,1 z" />
</g>
</g>
</g>
<g
transform="translate(42,41)"
- id="g36304"
+ id="ICON_ZOOM_PREVIOUS"
style="opacity:0.96000001;display:inline;enable-background:new">
<path
inkscape:transform-center-y="-6.5435007"
@@ -58903,7 +60760,7 @@
sodipodi:cy="78.5"
sodipodi:rx="3.5"
sodipodi:ry="3.5"
- d="m 262,78.5 c 0,1.932997 -1.567,3.5 -3.5,3.5 -1.933,0 -3.5,-1.567003 -3.5,-3.5 0,-1.932997 1.567,-3.5 3.5,-3.5 1.933,0 3.5,1.567003 3.5,3.5 z"
+ d="M 262,78.5 A 3.5,3.5 0 0 1 258.5,82 3.5,3.5 0 0 1 255,78.5 3.5,3.5 0 0 1 258.5,75 3.5,3.5 0 0 1 262,78.5 Z"
transform="matrix(-1.5000024,0,0,1.4990511,528.75064,424.32781)"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
inkscape:export-xdpi="90"
@@ -58937,7 +60794,7 @@
sodipodi:cy="78.5"
sodipodi:rx="3.5"
sodipodi:ry="3.5"
- d="m 262,78.5 c 0,1.932997 -1.567,3.5 -3.5,3.5 -1.933,0 -3.5,-1.567003 -3.5,-3.5 0,-1.932997 1.567,-3.5 3.5,-3.5 1.933,0 3.5,1.567003 3.5,3.5 z"
+ d="M 262,78.5 A 3.5,3.5 0 0 1 258.5,82 3.5,3.5 0 0 1 255,78.5 3.5,3.5 0 0 1 258.5,75 3.5,3.5 0 0 1 262,78.5 Z"
transform="matrix(-1.5714299,0,0,1.5714268,505.21462,331.643)"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
inkscape:export-xdpi="90"
@@ -58976,13 +60833,13 @@
sodipodi:cy="78.5"
sodipodi:rx="3.5"
sodipodi:ry="3.5"
- d="m 262,78.5 c 0,1.932997 -1.567,3.5 -3.5,3.5 -1.933,0 -3.5,-1.567003 -3.5,-3.5 0,-1.932997 1.567,-3.5 3.5,-3.5 1.933,0 3.5,1.567003 3.5,3.5 z"
+ d="M 262,78.5 A 3.5,3.5 0 0 1 258.5,82 3.5,3.5 0 0 1 255,78.5 3.5,3.5 0 0 1 258.5,75 3.5,3.5 0 0 1 262,78.5 Z"
transform="matrix(-1.14287,0,0,1.142863,463.9317,115.7853)" />
<g
id="g36324">
<path
transform="matrix(1.1162596,0,0,1.1065394,80.948334,-350.49863)"
- d="m 80.53125,502 c 0,1.38071 -1.133279,2.5 -2.53125,2.5 -1.397971,0 -2.53125,-1.11929 -2.53125,-2.5 0,-1.38071 1.133279,-2.5 2.53125,-2.5 1.397971,0 2.53125,1.11929 2.53125,2.5 z"
+ d="M 80.53125,502 A 2.5312502,2.5 0 0 1 78,504.5 2.5312502,2.5 0 0 1 75.46875,502 2.5312502,2.5 0 0 1 78,499.5 2.5312502,2.5 0 0 1 80.53125,502 Z"
sodipodi:ry="2.5"
sodipodi:rx="2.5312502"
sodipodi:cy="502"
@@ -58998,13 +60855,13 @@
sodipodi:cy="502"
sodipodi:rx="2.5312502"
sodipodi:ry="2.5"
- d="m 80.53125,502 c 0,1.38071 -1.133279,2.5 -2.53125,2.5 -1.397971,0 -2.53125,-1.11929 -2.53125,-2.5 0,-1.38071 1.133279,-2.5 2.53125,-2.5 1.397971,0 2.53125,1.11929 2.53125,2.5 z"
+ d="M 80.53125,502 A 2.5312502,2.5 0 0 1 78,504.5 2.5312502,2.5 0 0 1 75.46875,502 2.5312502,2.5 0 0 1 78,499.5 2.5312502,2.5 0 0 1 80.53125,502 Z"
transform="matrix(-1.087144,-0.2518404,0.2525206,-1.0776772,126.97246,766.619)" />
</g>
<path
inkscape:transform-center-y="-5.7593212"
inkscape:transform-center-x="-3.1120555"
- d="m 65,135 c 0,0.55228 -0.447715,1 -1,1 -0.552285,0 -1,-0.44772 -1,-1 0,-0.55228 0.447715,-1 1,-1 0.552285,0 1,0.44772 1,1 z"
+ d="m 65,135 a 1,1 0 0 1 -1,1 1,1 0 0 1 -1,-1 1,1 0 0 1 1,-1 1,1 0 0 1 1,1 z"
sodipodi:ry="1"
sodipodi:rx="1"
sodipodi:cy="135"
@@ -59042,7 +60899,7 @@
</g>
<g
style="display:inline;enable-background:new"
- id="g36339"
+ id="ICON_COLOR"
transform="translate(-294,339)">
<rect
style="opacity:0;fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
@@ -59065,7 +60922,7 @@
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
- d="m 132,110 c 2.85812,0 5.49914,1.52479 6.9282,4 L 132,118 z"
+ d="m 132,110 a 8,8 0 0 1 6.9282,4 L 132,118 Z"
sodipodi:ry="8"
sodipodi:rx="8"
sodipodi:cy="118"
@@ -59083,7 +60940,7 @@
sodipodi:cy="118"
sodipodi:rx="8"
sodipodi:ry="8"
- d="m 132,110 c 2.85812,0 5.49914,1.52479 6.9282,4 L 132,118 z"
+ d="m 132,110 a 8,8 0 0 1 6.9282,4 L 132,118 Z"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90"
@@ -59099,7 +60956,7 @@
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
- d="m 132,110 c 2.85812,0 5.49914,1.52479 6.9282,4 L 132,118 z"
+ d="m 132,110 a 8,8 0 0 1 6.9282,4 L 132,118 Z"
sodipodi:ry="8"
sodipodi:rx="8"
sodipodi:cy="118"
@@ -59117,7 +60974,7 @@
sodipodi:cy="118"
sodipodi:rx="8"
sodipodi:ry="8"
- d="m 132,110 c 2.85812,0 5.49914,1.52479 6.9282,4 L 132,118 z"
+ d="m 132,110 a 8,8 0 0 1 6.9282,4 L 132,118 Z"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90"
@@ -59132,7 +60989,7 @@
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
- d="m 132,110 c 2.85812,0 5.49914,1.52479 6.9282,4 L 132,118 z"
+ d="m 132,110 a 8,8 0 0 1 6.9282,4 L 132,118 Z"
sodipodi:ry="8"
sodipodi:rx="8"
sodipodi:cy="118"
@@ -59151,7 +61008,7 @@
sodipodi:cy="118"
sodipodi:rx="8"
sodipodi:ry="8"
- d="m 132,110 c 2.85812,0 5.49914,1.52479 6.9282,4 L 132,118 z"
+ d="m 132,110 a 8,8 0 0 1 6.9282,4 L 132,118 Z"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90"
@@ -59168,7 +61025,7 @@
sodipodi:cy="118"
sodipodi:rx="8"
sodipodi:ry="8"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90" />
@@ -59177,7 +61034,7 @@
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
sodipodi:ry="8"
sodipodi:rx="8"
sodipodi:cy="118"
@@ -59189,7 +61046,7 @@
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
sodipodi:ry="8"
sodipodi:rx="8"
sodipodi:cy="118"
@@ -59202,7 +61059,7 @@
</g>
<g
transform="translate(105,41)"
- id="g36367"
+ id="ICON_ZOOM_IN"
style="opacity:0.96000001;display:inline;enable-background:new">
<g
id="g36369"
@@ -59233,7 +61090,7 @@
sodipodi:cy="78.5"
sodipodi:rx="3.5"
sodipodi:ry="3.5"
- d="m 262,78.5 c 0,1.932997 -1.567,3.5 -3.5,3.5 -1.933,0 -3.5,-1.567003 -3.5,-3.5 0,-1.932997 1.567,-3.5 3.5,-3.5 1.933,0 3.5,1.567003 3.5,3.5 z"
+ d="M 262,78.5 A 3.5,3.5 0 0 1 258.5,82 3.5,3.5 0 0 1 255,78.5 3.5,3.5 0 0 1 258.5,75 3.5,3.5 0 0 1 262,78.5 Z"
transform="matrix(-1.5714299,0,0,1.5714268,505.21462,331.643)"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
inkscape:export-xdpi="90"
@@ -59272,13 +61129,13 @@
sodipodi:cy="78.5"
sodipodi:rx="3.5"
sodipodi:ry="3.5"
- d="m 262,78.5 c 0,1.932997 -1.567,3.5 -3.5,3.5 -1.933,0 -3.5,-1.567003 -3.5,-3.5 0,-1.932997 1.567,-3.5 3.5,-3.5 1.933,0 3.5,1.567003 3.5,3.5 z"
+ d="M 262,78.5 A 3.5,3.5 0 0 1 258.5,82 3.5,3.5 0 0 1 255,78.5 3.5,3.5 0 0 1 258.5,75 3.5,3.5 0 0 1 262,78.5 Z"
transform="matrix(-1.14287,0,0,1.142863,463.9317,115.7853)" />
<g
id="g36385">
<path
transform="matrix(1.1162596,0,0,1.1065394,80.948334,-350.49863)"
- d="m 80.53125,502 c 0,1.38071 -1.133279,2.5 -2.53125,2.5 -1.397971,0 -2.53125,-1.11929 -2.53125,-2.5 0,-1.38071 1.133279,-2.5 2.53125,-2.5 1.397971,0 2.53125,1.11929 2.53125,2.5 z"
+ d="M 80.53125,502 A 2.5312502,2.5 0 0 1 78,504.5 2.5312502,2.5 0 0 1 75.46875,502 2.5312502,2.5 0 0 1 78,499.5 2.5312502,2.5 0 0 1 80.53125,502 Z"
sodipodi:ry="2.5"
sodipodi:rx="2.5312502"
sodipodi:cy="502"
@@ -59294,13 +61151,13 @@
sodipodi:cy="502"
sodipodi:rx="2.5312502"
sodipodi:ry="2.5"
- d="m 80.53125,502 c 0,1.38071 -1.133279,2.5 -2.53125,2.5 -1.397971,0 -2.53125,-1.11929 -2.53125,-2.5 0,-1.38071 1.133279,-2.5 2.53125,-2.5 1.397971,0 2.53125,1.11929 2.53125,2.5 z"
+ d="M 80.53125,502 A 2.5312502,2.5 0 0 1 78,504.5 2.5312502,2.5 0 0 1 75.46875,502 2.5312502,2.5 0 0 1 78,499.5 2.5312502,2.5 0 0 1 80.53125,502 Z"
transform="matrix(-1.087144,-0.2518404,0.2525206,-1.0776772,126.97246,766.619)" />
</g>
<path
inkscape:transform-center-y="-5.7593212"
inkscape:transform-center-x="-3.1120555"
- d="m 65,135 c 0,0.55228 -0.447715,1 -1,1 -0.552285,0 -1,-0.44772 -1,-1 0,-0.55228 0.447715,-1 1,-1 0.552285,0 1,0.44772 1,1 z"
+ d="m 65,135 a 1,1 0 0 1 -1,1 1,1 0 0 1 -1,-1 1,1 0 0 1 1,-1 1,1 0 0 1 1,1 z"
sodipodi:ry="1"
sodipodi:rx="1"
sodipodi:cy="135"
@@ -59339,7 +61196,7 @@
sodipodi:cy="78.5"
sodipodi:rx="3.5"
sodipodi:ry="3.5"
- d="m 262,78.5 c 0,1.932997 -1.567,3.5 -3.5,3.5 -1.933,0 -3.5,-1.567003 -3.5,-3.5 0,-1.932997 1.567,-3.5 3.5,-3.5 1.933,0 3.5,1.567003 3.5,3.5 z"
+ d="M 262,78.5 A 3.5,3.5 0 0 1 258.5,82 3.5,3.5 0 0 1 255,78.5 3.5,3.5 0 0 1 258.5,75 3.5,3.5 0 0 1 262,78.5 Z"
transform="matrix(-1.5002341,0,0,1.5000004,486.81053,424.24997)"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
inkscape:export-xdpi="90"
@@ -59373,14 +61230,14 @@
</g>
<g
transform="translate(105,41)"
- id="g36407"
+ id="ICON_ZOOM_OUT"
style="opacity:0.96000001;display:inline;enable-background:new">
<path
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
transform="matrix(-1.5000024,0,0,1.4990511,507.75064,424.32781)"
- d="m 262,78.5 c 0,1.932997 -1.567,3.5 -3.5,3.5 -1.933,0 -3.5,-1.567003 -3.5,-3.5 0,-1.932997 1.567,-3.5 3.5,-3.5 1.933,0 3.5,1.567003 3.5,3.5 z"
+ d="M 262,78.5 A 3.5,3.5 0 0 1 258.5,82 3.5,3.5 0 0 1 255,78.5 3.5,3.5 0 0 1 258.5,75 3.5,3.5 0 0 1 262,78.5 Z"
sodipodi:ry="3.5"
sodipodi:rx="3.5"
sodipodi:cy="78.5"
@@ -59414,7 +61271,7 @@
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
transform="matrix(-1.5714299,0,0,1.5714268,505.21462,331.643)"
- d="m 262,78.5 c 0,1.932997 -1.567,3.5 -3.5,3.5 -1.933,0 -3.5,-1.567003 -3.5,-3.5 0,-1.932997 1.567,-3.5 3.5,-3.5 1.933,0 3.5,1.567003 3.5,3.5 z"
+ d="M 262,78.5 A 3.5,3.5 0 0 1 258.5,82 3.5,3.5 0 0 1 255,78.5 3.5,3.5 0 0 1 258.5,75 3.5,3.5 0 0 1 262,78.5 Z"
sodipodi:ry="3.5"
sodipodi:rx="3.5"
sodipodi:cy="78.5"
@@ -59450,7 +61307,7 @@
id="g36423">
<path
transform="matrix(-1.14287,0,0,1.142863,463.9317,115.7853)"
- d="m 262,78.5 c 0,1.932997 -1.567,3.5 -3.5,3.5 -1.933,0 -3.5,-1.567003 -3.5,-3.5 0,-1.932997 1.567,-3.5 3.5,-3.5 1.933,0 3.5,1.567003 3.5,3.5 z"
+ d="M 262,78.5 A 3.5,3.5 0 0 1 258.5,82 3.5,3.5 0 0 1 255,78.5 3.5,3.5 0 0 1 258.5,75 3.5,3.5 0 0 1 262,78.5 Z"
sodipodi:ry="3.5"
sodipodi:rx="3.5"
sodipodi:cy="78.5"
@@ -59470,11 +61327,11 @@
sodipodi:cy="502"
sodipodi:rx="2.5312502"
sodipodi:ry="2.5"
- d="m 80.53125,502 c 0,1.38071 -1.133279,2.5 -2.53125,2.5 -1.397971,0 -2.53125,-1.11929 -2.53125,-2.5 0,-1.38071 1.133279,-2.5 2.53125,-2.5 1.397971,0 2.53125,1.11929 2.53125,2.5 z"
+ d="M 80.53125,502 A 2.5312502,2.5 0 0 1 78,504.5 2.5312502,2.5 0 0 1 75.46875,502 2.5312502,2.5 0 0 1 78,499.5 2.5312502,2.5 0 0 1 80.53125,502 Z"
transform="matrix(1.1162596,0,0,1.1065394,80.948334,-350.49863)" />
<path
transform="matrix(-1.087144,-0.2518404,0.2525206,-1.0776772,126.97246,766.619)"
- d="m 80.53125,502 c 0,1.38071 -1.133279,2.5 -2.53125,2.5 -1.397971,0 -2.53125,-1.11929 -2.53125,-2.5 0,-1.38071 1.133279,-2.5 2.53125,-2.5 1.397971,0 2.53125,1.11929 2.53125,2.5 z"
+ d="M 80.53125,502 A 2.5312502,2.5 0 0 1 78,504.5 2.5312502,2.5 0 0 1 75.46875,502 2.5312502,2.5 0 0 1 78,499.5 2.5312502,2.5 0 0 1 80.53125,502 Z"
sodipodi:ry="2.5"
sodipodi:rx="2.5312502"
sodipodi:cy="502"
@@ -59492,7 +61349,7 @@
sodipodi:cy="135"
sodipodi:rx="1"
sodipodi:ry="1"
- d="m 65,135 c 0,0.55228 -0.447715,1 -1,1 -0.552285,0 -1,-0.44772 -1,-1 0,-0.55228 0.447715,-1 1,-1 0.552285,0 1,0.44772 1,1 z"
+ d="m 65,135 a 1,1 0 0 1 -1,1 1,1 0 0 1 -1,-1 1,1 0 0 1 1,-1 1,1 0 0 1 1,1 z"
inkscape:transform-center-x="-3.1120555"
inkscape:transform-center-y="-5.7593212" />
</g>
@@ -59527,7 +61384,7 @@
</g>
<g
style="display:inline;enable-background:new"
- id="g36441"
+ id="ICON_SNAP_INCREMENT"
transform="translate(107,-124)">
<g
style="opacity:0.85;display:inline;enable-background:new"
@@ -59575,7 +61432,7 @@
style="display:inline">
<path
transform="matrix(1.142871,0,0,1.142855,-27.218817,-5.0713453)"
- d="m 334,35.5 c 0,1.932997 -1.567,3.5 -3.5,3.5 -1.933,0 -3.5,-1.567003 -3.5,-3.5 0,-1.932997 1.567,-3.5 3.5,-3.5 1.933,0 3.5,1.567003 3.5,3.5 z"
+ d="M 334,35.5 A 3.5,3.5 0 0 1 330.5,39 3.5,3.5 0 0 1 327,35.5 3.5,3.5 0 0 1 330.5,32 3.5,3.5 0 0 1 334,35.5 Z"
sodipodi:ry="3.5"
sodipodi:rx="3.5"
sodipodi:cy="35.5"
@@ -59591,7 +61448,7 @@
sodipodi:cy="35.5"
sodipodi:rx="3.5"
sodipodi:ry="3.5"
- d="m 334,35.5 c 0,1.932997 -1.567,3.5 -3.5,3.5 -1.933,0 -3.5,-1.567003 -3.5,-3.5 0,-1.932997 1.567,-3.5 3.5,-3.5 1.933,0 3.5,1.567003 3.5,3.5 z"
+ d="M 334,35.5 A 3.5,3.5 0 0 1 330.5,39 3.5,3.5 0 0 1 327,35.5 3.5,3.5 0 0 1 330.5,32 3.5,3.5 0 0 1 334,35.5 Z"
transform="matrix(0.857099,0,0,0.857147,67.228993,5.071249)" />
</g>
<g
@@ -59669,7 +61526,7 @@
</g>
<g
style="display:inline;enable-background:new"
- id="g36486"
+ id="ICON_HELP"
transform="translate(-44.309303,267.47333)">
<rect
y="309.52667"
@@ -59815,7 +61672,7 @@
sodipodi:cy="118"
sodipodi:rx="8"
sodipodi:ry="8"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90" />
@@ -59823,7 +61680,7 @@
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
sodipodi:ry="8"
sodipodi:rx="8"
sodipodi:cy="118"
@@ -59842,7 +61699,7 @@
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
sodipodi:ry="8"
sodipodi:rx="8"
sodipodi:cy="118"
@@ -59860,7 +61717,7 @@
sodipodi:cy="118"
sodipodi:rx="8"
sodipodi:ry="8"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90" />
@@ -59869,7 +61726,7 @@
</g>
<g
style="opacity:0.96000001;display:inline;enable-background:new"
- id="g36540"
+ id="ICON_STRANDS"
inkscape:label="Layer 1"
transform="translate(-211.14286,264.78067)">
<g
@@ -59964,7 +61821,7 @@
</g>
<g
style="display:inline;enable-background:new"
- id="g36570"
+ id="ICON_UNLINKED"
transform="translate(21,254)">
<rect
y="321"
@@ -60060,7 +61917,7 @@
</g>
<g
style="display:inline;enable-background:new"
- id="g36612"
+ id="ICON_LINKED"
transform="translate(0,275)">
<g
transform="translate(-226,210)"
@@ -60211,7 +62068,7 @@
<g
transform="matrix(-1,0,0,1,530,548)"
style="opacity:0.9;display:inline;enable-background:new"
- id="g36668">
+ id="ICON_GHOST_ENABLED">
<rect
style="opacity:0;fill:#aaccff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.4000001;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
id="rect36670"
@@ -60297,7 +62154,7 @@
</g>
<g
transform="translate(47,571)"
- id="g36699"
+ id="ICON_HAND"
style="display:inline;enable-background:new">
<path
style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.79999995;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
@@ -60352,7 +62209,7 @@
</g>
<g
style="display:inline;enable-background:new"
- id="g36882"
+ id="ICON_RENDER_REGION"
transform="translate(-21,254)">
<rect
ry="0"
@@ -60529,7 +62386,7 @@
id="g36930">
<path
transform="matrix(0.7834486,0,0,0.2000006,10.413535,395.5997)"
- d="m 80.53125,502 c 0,1.38071 -1.133279,2.5 -2.53125,2.5 -1.397971,0 -2.53125,-1.11929 -2.53125,-2.5 0,-1.38071 1.133279,-2.5 2.53125,-2.5 1.397971,0 2.53125,1.11929 2.53125,2.5 z"
+ d="M 80.53125,502 A 2.5312502,2.5 0 0 1 78,504.5 2.5312502,2.5 0 0 1 75.46875,502 2.5312502,2.5 0 0 1 78,499.5 2.5312502,2.5 0 0 1 80.53125,502 Z"
sodipodi:ry="2.5"
sodipodi:rx="2.5312502"
sodipodi:cy="502"
@@ -60587,11 +62444,11 @@
sodipodi:cy="502"
sodipodi:rx="2.5312502"
sodipodi:ry="2.5"
- d="m 80.53125,502 c 0,1.38071 -1.133279,2.5 -2.53125,2.5 -1.397971,0 -2.53125,-1.11929 -2.53125,-2.5 0,-1.38071 1.133279,-2.5 2.53125,-2.5 1.397971,0 2.53125,1.11929 2.53125,2.5 z"
+ d="M 80.53125,502 A 2.5312502,2.5 0 0 1 78,504.5 2.5312502,2.5 0 0 1 75.46875,502 2.5312502,2.5 0 0 1 78,499.5 2.5312502,2.5 0 0 1 80.53125,502 Z"
transform="matrix(1.187982,0,0,1.0569758,379.83032,-513.21497)" />
<path
transform="matrix(1.3827154,0,0,1.4028327,364.1482,-688.72206)"
- d="m 80.53125,502 c 0,1.38071 -1.133279,2.5 -2.53125,2.5 -1.397971,0 -2.53125,-1.11929 -2.53125,-2.5 0,-1.38071 1.133279,-2.5 2.53125,-2.5 1.397971,0 2.53125,1.11929 2.53125,2.5 z"
+ d="M 80.53125,502 A 2.5312502,2.5 0 0 1 78,504.5 2.5312502,2.5 0 0 1 75.46875,502 2.5312502,2.5 0 0 1 78,499.5 2.5312502,2.5 0 0 1 80.53125,502 Z"
sodipodi:ry="2.5"
sodipodi:rx="2.5312502"
sodipodi:cy="502"
@@ -60607,11 +62464,11 @@
sodipodi:cy="502"
sodipodi:rx="2.5312502"
sodipodi:ry="2.5"
- d="m 80.53125,502 c 0,1.38071 -1.133279,2.5 -2.53125,2.5 -1.397971,0 -2.53125,-1.11929 -2.53125,-2.5 0,-1.38071 1.133279,-2.5 2.53125,-2.5 1.397971,0 2.53125,1.11929 2.53125,2.5 z"
+ d="M 80.53125,502 A 2.5312502,2.5 0 0 1 78,504.5 2.5312502,2.5 0 0 1 75.46875,502 2.5312502,2.5 0 0 1 78,499.5 2.5312502,2.5 0 0 1 80.53125,502 Z"
transform="matrix(0.987526,0,0,0.8124641,394.9733,-392.80617)" />
<path
transform="matrix(0.9848328,0,0,0.9992585,395.19018,-485.12778)"
- d="m 80.53125,502 c 0,1.38071 -1.133279,2.5 -2.53125,2.5 -1.397971,0 -2.53125,-1.11929 -2.53125,-2.5 0,-1.38071 1.133279,-2.5 2.53125,-2.5 1.397971,0 2.53125,1.11929 2.53125,2.5 z"
+ d="M 80.53125,502 A 2.5312502,2.5 0 0 1 78,504.5 2.5312502,2.5 0 0 1 75.46875,502 2.5312502,2.5 0 0 1 78,499.5 2.5312502,2.5 0 0 1 80.53125,502 Z"
sodipodi:ry="2.5"
sodipodi:rx="2.5312502"
sodipodi:cy="502"
@@ -60627,7 +62484,7 @@
sodipodi:cy="502"
sodipodi:rx="2.5312502"
sodipodi:ry="2.5"
- d="m 80.53125,502 c 0,1.38071 -1.133279,2.5 -2.53125,2.5 -1.397971,0 -2.53125,-1.11929 -2.53125,-2.5 0,-1.38071 1.133279,-2.5 2.53125,-2.5 1.397971,0 2.53125,1.11929 2.53125,2.5 z"
+ d="M 80.53125,502 A 2.5312502,2.5 0 0 1 78,504.5 2.5312502,2.5 0 0 1 75.46875,502 2.5312502,2.5 0 0 1 78,499.5 2.5312502,2.5 0 0 1 80.53125,502 Z"
transform="matrix(0.591154,0,0,0.5887513,425.87219,-279.05319)" />
<path
sodipodi:type="arc"
@@ -60637,11 +62494,11 @@
sodipodi:cy="502"
sodipodi:rx="2.5312502"
sodipodi:ry="2.5"
- d="m 80.53125,502 c 0,1.38071 -1.133279,2.5 -2.53125,2.5 -1.397971,0 -2.53125,-1.11929 -2.53125,-2.5 0,-1.38071 1.133279,-2.5 2.53125,-2.5 1.397971,0 2.53125,1.11929 2.53125,2.5 z"
+ d="M 80.53125,502 A 2.5312502,2.5 0 0 1 78,504.5 2.5312502,2.5 0 0 1 75.46875,502 2.5312502,2.5 0 0 1 78,499.5 2.5312502,2.5 0 0 1 80.53125,502 Z"
transform="matrix(0.9913883,0,0,1.0058976,394.67318,-488.46061)" />
<path
transform="matrix(0.6941559,0,0,0.6920597,417.67198,-331.15708)"
- d="m 80.53125,502 c 0,1.38071 -1.133279,2.5 -2.53125,2.5 -1.397971,0 -2.53125,-1.11929 -2.53125,-2.5 0,-1.38071 1.133279,-2.5 2.53125,-2.5 1.397971,0 2.53125,1.11929 2.53125,2.5 z"
+ d="M 80.53125,502 A 2.5312502,2.5 0 0 1 78,504.5 2.5312502,2.5 0 0 1 75.46875,502 2.5312502,2.5 0 0 1 78,499.5 2.5312502,2.5 0 0 1 80.53125,502 Z"
sodipodi:ry="2.5"
sodipodi:rx="2.5312502"
sodipodi:cy="502"
@@ -60657,7 +62514,7 @@
sodipodi:cy="502"
sodipodi:rx="2.5312502"
sodipodi:ry="2.5"
- d="m 80.53125,502 c 0,1.38071 -1.133279,2.5 -2.53125,2.5 -1.397971,0 -2.53125,-1.11929 -2.53125,-2.5 0,-1.38071 1.133279,-2.5 2.53125,-2.5 1.397971,0 2.53125,1.11929 2.53125,2.5 z"
+ d="M 80.53125,502 A 2.5312502,2.5 0 0 1 78,504.5 2.5312502,2.5 0 0 1 75.46875,502 2.5312502,2.5 0 0 1 78,499.5 2.5312502,2.5 0 0 1 80.53125,502 Z"
transform="matrix(0.1975308,0,0,0.1999991,456.0926,-84.399595)" />
<path
sodipodi:type="arc"
@@ -60667,7 +62524,7 @@
sodipodi:cy="502"
sodipodi:rx="2.5312502"
sodipodi:ry="2.5"
- d="m 80.53125,502 c 0,1.38071 -1.133279,2.5 -2.53125,2.5 -1.397971,0 -2.53125,-1.11929 -2.53125,-2.5 0,-1.38071 1.133279,-2.5 2.53125,-2.5 1.397971,0 2.53125,1.11929 2.53125,2.5 z"
+ d="M 80.53125,502 A 2.5312502,2.5 0 0 1 78,504.5 2.5312502,2.5 0 0 1 75.46875,502 2.5312502,2.5 0 0 1 78,499.5 2.5312502,2.5 0 0 1 80.53125,502 Z"
transform="matrix(-0.6760501,-0.1575078,0.1570322,-0.6740085,446.07727,367.34791)" />
</g>
<path
@@ -60685,275 +62542,273 @@
inkscape:connector-curvature="0" />
</g>
<g
- style="display:inline;enable-background:new"
- id="g36970"
- transform="translate(62.999998,254)">
- <rect
- style="opacity:0;fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- id="rect36972"
- width="16"
- height="16"
- x="215"
- y="-339"
- transform="scale(1,-1)" />
- <path
- style="opacity:0.2;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.80000001;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- d="m 220,324 0,1 -2,0 0,2 -1,0 0,2 -1,0 0,6 1,0 0,2 1,0 2,0 0,-1 1,0 0,-2 1,0 0,-2 1,0 0,-1 1,0 3,0 0,-1 1,0 1,0 0,-4 -1,0 0,-1 -1,0 0,-1 -3,0 -1,0 -1,0 -1,0 -1,0 z"
- id="path36974"
- sodipodi:nodetypes="cccccccccccccccccccccccccccccccccc"
- inkscape:connector-curvature="0" />
+ id="ICON_BORDER_LASSO">
<g
- id="g36976"
- transform="translate(1,84)">
+ id="g16722">
<g
- transform="translate(5,-6.0000002e-7)"
- style="fill:#1a1a1a;display:inline;enable-background:new"
- id="g36980" />
- </g>
- <g
- id="g37010"
- style="fill:#321900">
- <rect
- transform="scale(1,-1)"
- y="-324"
- x="223"
- height="1"
- width="2"
- id="rect37012"
- style="fill:#321900;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
- <rect
- transform="scale(1,-1)"
- style="fill:#321900;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- id="rect37014"
- width="2"
- height="1"
- x="219"
- y="-325" />
- <rect
- style="fill:#321900;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- id="rect37016"
- width="1"
- height="1"
- x="324"
- y="227"
- transform="matrix(0,1,1,0,0,0)" />
- <rect
- y="226"
- x="323"
- height="1"
- width="1"
- id="rect37018"
- style="fill:#321900;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- transform="matrix(0,1,1,0,0,0)" />
- <rect
- y="229"
- x="328"
- height="1"
- width="1"
- id="rect37020"
- style="fill:#321900;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- transform="matrix(0,1,1,0,0,0)" />
- <rect
- style="fill:#321900;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- id="rect37022"
- width="1"
- height="2"
- x="216"
- y="-329"
- transform="scale(1,-1)" />
- <rect
- transform="scale(1,-1)"
- y="-337"
- x="216"
- height="2"
- width="1"
- id="rect37024"
- style="fill:#321900;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
- <rect
- style="fill:#321900;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- id="rect37026"
- width="1"
- height="1"
- x="220"
- y="-337"
- transform="scale(1,-1)" />
- <rect
- transform="scale(1,-1)"
- y="-338"
- x="219"
- height="1"
- width="1"
- id="rect37028"
- style="fill:#321900;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
- <rect
- style="fill:#321900;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- id="rect37030"
- width="1"
- height="1"
- x="221"
- y="-334"
- transform="scale(1,-1)" />
- <rect
- style="fill:#321900;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- id="rect37032"
- width="1"
- height="2"
- x="215"
- y="-333"
- transform="scale(1,-1)" />
- <rect
- transform="matrix(0,1,1,0,0,0)"
- y="228"
- x="325"
- height="1"
- width="1"
- id="rect37034"
- style="fill:#321900;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
- <rect
- transform="matrix(0,1,1,0,0,0)"
- style="fill:#321900;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- id="rect37036"
- width="1"
- height="1"
- x="329"
- y="228" />
- <rect
- transform="scale(1,-1)"
- y="-333"
- x="222"
- height="1"
- width="1"
- id="rect37038"
- style="fill:#321900;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
- </g>
- <g
- id="g37040"
- style="fill:#ffd42a;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate">
- <rect
- transform="scale(1,-1)"
- style="fill:#ff982a;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- id="rect37042"
- width="2"
- height="1"
- x="221"
- y="-324" />
- <rect
- style="fill:#ff982a;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- id="rect37044"
- width="1"
- height="2"
- x="323"
- y="225"
- transform="matrix(0,1,1,0,0,0)" />
- <rect
- transform="matrix(0,1,1,0,0,0)"
- style="fill:#ff982a;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- id="rect37046"
- width="1"
- height="1"
- x="329"
- y="227" />
- <rect
- transform="scale(1,-1)"
- y="-331"
- x="215"
- height="2"
- width="1"
- id="rect37048"
- style="fill:#ff982a;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
- <rect
- style="fill:#ff982a;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- id="rect37050"
- width="1"
- height="2"
- x="215"
- y="-335"
- transform="scale(1,-1)" />
- <rect
- style="fill:#ff982a;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- id="rect37052"
- width="2"
- height="1"
- x="217"
- y="-338"
- transform="scale(1,-1)" />
- <rect
- transform="scale(1,-1)"
- y="-336"
- x="221"
- height="2"
- width="1"
- id="rect37054"
- style="fill:#ff982a;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
- <rect
- y="-332"
- x="222"
- height="1"
- width="1"
- id="rect37056"
- style="fill:#ff982a;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- transform="scale(1,-1)" />
- <rect
- style="fill:#ff982a;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- id="rect37058"
- width="1"
- height="1"
- x="217"
- y="-327"
- transform="scale(1,-1)" />
- <rect
- transform="scale(1,-1)"
- y="-326"
- x="218"
- height="1"
- width="1"
- id="rect37060"
- style="fill:#ff982a;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
- <rect
- transform="matrix(0,1,1,0,0,0)"
- style="fill:#ff982a;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- id="rect37062"
- width="2"
- height="1"
- x="326"
- y="229" />
- <rect
- transform="scale(1,-1)"
- style="fill:#ff982a;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- id="rect37064"
- width="1"
- height="1"
- x="223"
- y="-331" />
+ style="display:inline;enable-background:new"
+ id="g36970"
+ transform="translate(62.999998,254)">
+ <rect
+ style="opacity:0;fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect36972"
+ width="16"
+ height="16"
+ x="215"
+ y="-339"
+ transform="scale(1,-1)" />
+ <path
+ style="opacity:0.2;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.80000001;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 220,324 0,1 -2,0 0,2 -1,0 0,2 -1,0 0,6 1,0 0,2 1,0 2,0 0,-1 1,0 0,-2 1,0 0,-2 1,0 0,-1 1,0 3,0 0,-1 1,0 1,0 0,-4 -1,0 0,-1 -1,0 0,-1 -3,0 -1,0 -1,0 -1,0 -1,0 z"
+ id="path36974"
+ sodipodi:nodetypes="cccccccccccccccccccccccccccccccccc"
+ inkscape:connector-curvature="0" />
+ <g
+ id="g37010"
+ style="fill:#321900">
+ <rect
+ transform="scale(1,-1)"
+ y="-324"
+ x="223"
+ height="1"
+ width="2"
+ id="rect37012"
+ style="fill:#321900;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <rect
+ transform="scale(1,-1)"
+ style="fill:#321900;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect37014"
+ width="2"
+ height="1"
+ x="219"
+ y="-325" />
+ <rect
+ style="fill:#321900;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect37016"
+ width="1"
+ height="1"
+ x="324"
+ y="227"
+ transform="matrix(0,1,1,0,0,0)" />
+ <rect
+ y="226"
+ x="323"
+ height="1"
+ width="1"
+ id="rect37018"
+ style="fill:#321900;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ transform="matrix(0,1,1,0,0,0)" />
+ <rect
+ y="229"
+ x="328"
+ height="1"
+ width="1"
+ id="rect37020"
+ style="fill:#321900;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ transform="matrix(0,1,1,0,0,0)" />
+ <rect
+ style="fill:#321900;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect37022"
+ width="1"
+ height="2"
+ x="216"
+ y="-329"
+ transform="scale(1,-1)" />
+ <rect
+ transform="scale(1,-1)"
+ y="-337"
+ x="216"
+ height="2"
+ width="1"
+ id="rect37024"
+ style="fill:#321900;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <rect
+ style="fill:#321900;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect37026"
+ width="1"
+ height="1"
+ x="220"
+ y="-337"
+ transform="scale(1,-1)" />
+ <rect
+ transform="scale(1,-1)"
+ y="-338"
+ x="219"
+ height="1"
+ width="1"
+ id="rect37028"
+ style="fill:#321900;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <rect
+ style="fill:#321900;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect37030"
+ width="1"
+ height="1"
+ x="221"
+ y="-334"
+ transform="scale(1,-1)" />
+ <rect
+ style="fill:#321900;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect37032"
+ width="1"
+ height="2"
+ x="215"
+ y="-333"
+ transform="scale(1,-1)" />
+ <rect
+ transform="matrix(0,1,1,0,0,0)"
+ y="228"
+ x="325"
+ height="1"
+ width="1"
+ id="rect37034"
+ style="fill:#321900;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <rect
+ transform="matrix(0,1,1,0,0,0)"
+ style="fill:#321900;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect37036"
+ width="1"
+ height="1"
+ x="329"
+ y="228" />
+ <rect
+ transform="scale(1,-1)"
+ y="-333"
+ x="222"
+ height="1"
+ width="1"
+ id="rect37038"
+ style="fill:#321900;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ </g>
+ <g
+ id="g37040"
+ style="fill:#ffd42a;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate">
+ <rect
+ transform="scale(1,-1)"
+ style="fill:#ff982a;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect37042"
+ width="2"
+ height="1"
+ x="221"
+ y="-324" />
+ <rect
+ style="fill:#ff982a;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect37044"
+ width="1"
+ height="2"
+ x="323"
+ y="225"
+ transform="matrix(0,1,1,0,0,0)" />
+ <rect
+ transform="matrix(0,1,1,0,0,0)"
+ style="fill:#ff982a;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect37046"
+ width="1"
+ height="1"
+ x="329"
+ y="227" />
+ <rect
+ transform="scale(1,-1)"
+ y="-331"
+ x="215"
+ height="2"
+ width="1"
+ id="rect37048"
+ style="fill:#ff982a;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <rect
+ style="fill:#ff982a;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect37050"
+ width="1"
+ height="2"
+ x="215"
+ y="-335"
+ transform="scale(1,-1)" />
+ <rect
+ style="fill:#ff982a;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect37052"
+ width="2"
+ height="1"
+ x="217"
+ y="-338"
+ transform="scale(1,-1)" />
+ <rect
+ transform="scale(1,-1)"
+ y="-336"
+ x="221"
+ height="2"
+ width="1"
+ id="rect37054"
+ style="fill:#ff982a;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <rect
+ y="-332"
+ x="222"
+ height="1"
+ width="1"
+ id="rect37056"
+ style="fill:#ff982a;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ transform="scale(1,-1)" />
+ <rect
+ style="fill:#ff982a;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect37058"
+ width="1"
+ height="1"
+ x="217"
+ y="-327"
+ transform="scale(1,-1)" />
+ <rect
+ transform="scale(1,-1)"
+ y="-326"
+ x="218"
+ height="1"
+ width="1"
+ id="rect37060"
+ style="fill:#ff982a;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <rect
+ transform="matrix(0,1,1,0,0,0)"
+ style="fill:#ff982a;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect37062"
+ width="2"
+ height="1"
+ x="326"
+ y="229" />
+ <rect
+ transform="scale(1,-1)"
+ style="fill:#ff982a;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect37064"
+ width="1"
+ height="1"
+ x="223"
+ y="-331" />
+ </g>
+ <path
+ sodipodi:nodetypes="cccccccccccccccccccccccccccccccccccccccc"
+ id="path37066"
+ d="m 220.9438,324.0562 0,1 6,0 0,-1 -6,0 z m 6,1 0,1 1,0 0,-1 -1,0 z m 1,1 0,1 1,0 0,-1 -1,0 z m -7,-1 -2,0 0,1 2,0 0,-1 z m -2,1 -1,0 0,1 1,0 0,-1 z m -1,1 -1,0 0,2 1,0 0,-2 z m -1,2 -1,0 0,6 1,0 0,-6 z m 0,5.75 0,2.25 1,0 0,-2 -1,-0.25 z"
+ style="opacity:0.15;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ </g>
+ <path
+ style="fill:url(#linearGradient106628);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.80000001;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 287.75,590.75 1.75,-1.5 1.99177,3.7253 1.75,-1 L 291.5,588.5 l 2.5,0 -6.25,-6.25 z"
+ id="path45378-1-5-6-2"
+ sodipodi:nodetypes="cccccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:none;stroke:#ffffff;stroke-width:0.80000001;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 288.34375,583.75 0,5.75"
+ id="path17845-9-1"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cc" />
</g>
<path
- sodipodi:nodetypes="cccccccccccccccccccccccccccccccccccccccc"
- id="path37066"
- d="m 220.9438,324.0562 0,1 6,0 0,-1 -6,0 z m 6,1 0,1 1,0 0,-1 -1,0 z m 1,1 0,1 1,0 0,-1 -1,0 z m -7,-1 -2,0 0,1 2,0 0,-1 z m -2,1 -1,0 0,1 1,0 0,-1 z m -1,1 -1,0 0,2 1,0 0,-2 z m -1,2 -1,0 0,6 1,0 0,-6 z m 0,5.75 0,2.25 1,0 0,-2 -1,-0.25 z"
- style="opacity:0.15;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- inkscape:connector-curvature="0" />
+ sodipodi:nodetypes="cccccccc"
+ inkscape:connector-curvature="0"
+ id="path17835-7-2"
+ d="m 287.54419,581.36742 7,7.25 -3,0 1.69346,3.25845 -1.75,1 -1.69346,-3.50845 -2.25,2.25 z"
+ style="fill:none;stroke:#000000;stroke-width:0.89999998;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
</g>
- <path
- style="fill:url(#linearGradient106628);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.80000001;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- d="m 287.75,590.75 1.75,-1.5 1.99177,3.7253 1.75,-1 L 291.5,588.5 l 2.5,0 -6.25,-6.25 z"
- id="path45378-1-5-6-2"
- sodipodi:nodetypes="cccccccc"
- inkscape:connector-curvature="0" />
- <path
- style="fill:none;stroke:#000000;stroke-width:0.89999998;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
- d="m 287.54419,581.36742 7,7.25 -3,0 1.69346,3.25845 -1.75,1 -1.69346,-3.50845 -2.25,2.25 z"
- id="path17835-7-2"
- inkscape:connector-curvature="0"
- sodipodi:nodetypes="cccccccc" />
- <path
- style="fill:none;stroke:#ffffff;stroke-width:0.80000001;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
- d="m 288.34375,583.75 0,5.75"
- id="path17845-9-1"
- inkscape:connector-curvature="0"
- sodipodi:nodetypes="cc" />
<g
style="opacity:0.96000001;display:inline;enable-background:new"
- id="g37068"
+ id="ICON_FREEZE"
transform="translate(126,86)">
<rect
style="opacity:0;fill:#666666;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.20000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
@@ -61076,7 +62931,7 @@
sodipodi:cy="330.5"
sodipodi:rx="2"
sodipodi:ry="2"
- d="m 266.5,330.5 c 0,1.10457 -0.89543,2 -2,2 -1.10457,0 -2,-0.89543 -2,-2 0,-1.10457 0.89543,-2 2,-2 1.10457,0 2,0.89543 2,2 z" />
+ d="m 266.5,330.5 a 2,2 0 0 1 -2,2 2,2 0 0 1 -2,-2 2,2 0 0 1 2,-2 2,2 0 0 1 2,2 z" />
</g>
<path
style="fill:none;stroke:#ffffff;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
@@ -61127,7 +62982,7 @@
style="fill:none;stroke:#ffffff;stroke-width:1.20000005;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
inkscape:connector-curvature="0" />
<path
- d="m 266.5,330.5 c 0,1.10457 -0.89543,2 -2,2 -1.10457,0 -2,-0.89543 -2,-2 0,-1.10457 0.89543,-2 2,-2 1.10457,0 2,0.89543 2,2 z"
+ d="m 266.5,330.5 a 2,2 0 0 1 -2,2 2,2 0 0 1 -2,-2 2,2 0 0 1 2,-2 2,2 0 0 1 2,2 z"
sodipodi:ry="2"
sodipodi:rx="2"
sodipodi:cy="330.5"
@@ -61158,7 +63013,7 @@
</g>
<g
style="display:inline;enable-background:new"
- id="g37138"
+ id="ICON_GROUP_VERTEX"
transform="translate(147.01612,401.00818)">
<rect
transform="scale(1,-1)"
@@ -61241,7 +63096,7 @@
<g
style="display:inline;enable-background:new"
transform="translate(420,44)"
- id="g37166">
+ id="ICON_GROUP_UVS">
<rect
style="opacity:0;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
id="rect37168"
@@ -61275,12 +63130,12 @@
sodipodi:cy="118"
sodipodi:rx="8"
sodipodi:ry="8"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z" />
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z" />
<path
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
sodipodi:ry="8"
sodipodi:rx="8"
sodipodi:cy="118"
@@ -61297,7 +63152,7 @@
sodipodi:cy="118"
sodipodi:rx="8"
sodipodi:ry="8"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90"
@@ -61319,7 +63174,7 @@
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
sodipodi:ry="8"
sodipodi:rx="8"
sodipodi:cy="118"
@@ -61336,7 +63191,7 @@
sodipodi:cy="118"
sodipodi:rx="8"
sodipodi:ry="8"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90" />
@@ -61350,7 +63205,7 @@
<g
transform="translate(-499.98389,503.95862)"
style="display:inline;enable-background:new"
- id="g37229">
+ id="ICON_BRUSH_DATA">
<path
sodipodi:nodetypes="ccccc"
id="path37231"
@@ -61402,7 +63257,7 @@
</g>
<g
style="display:inline;enable-background:new"
- id="g37307"
+ id="ICON_GROUP_BONE"
transform="translate(-42,86)">
<g
id="g37309"
@@ -61497,7 +63352,7 @@
</g>
<g
style="display:inline;enable-background:new"
- id="g37339"
+ id="ICON_GROUP_VCOL"
transform="translate(-84,65)">
<rect
transform="scale(-1,-1)"
@@ -61593,7 +63448,7 @@
sodipodi:cy="118"
sodipodi:rx="8"
sodipodi:ry="8"
- d="m 132,110 c 2.85812,0 5.49914,1.52479 6.9282,4 L 132,118 z"
+ d="m 132,110 a 8,8 0 0 1 6.9282,4 L 132,118 Z"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90"
@@ -61609,7 +63464,7 @@
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
- d="m 132,110 c 2.85812,0 5.49914,1.52479 6.9282,4 L 132,118 z"
+ d="m 132,110 a 8,8 0 0 1 6.9282,4 L 132,118 Z"
sodipodi:ry="8"
sodipodi:rx="8"
sodipodi:cy="118"
@@ -61627,7 +63482,7 @@
sodipodi:cy="118"
sodipodi:rx="8"
sodipodi:ry="8"
- d="m 132,110 c 2.85812,0 5.49914,1.52479 6.9282,4 L 132,118 z"
+ d="m 132,110 a 8,8 0 0 1 6.9282,4 L 132,118 Z"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90"
@@ -61643,7 +63498,7 @@
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
- d="m 132,110 c 2.85812,0 5.49914,1.52479 6.9282,4 L 132,118 z"
+ d="m 132,110 a 8,8 0 0 1 6.9282,4 L 132,118 Z"
sodipodi:ry="8"
sodipodi:rx="8"
sodipodi:cy="118"
@@ -61661,7 +63516,7 @@
sodipodi:cy="118"
sodipodi:rx="8"
sodipodi:ry="8"
- d="m 132,110 c 2.85812,0 5.49914,1.52479 6.9282,4 L 132,118 z"
+ d="m 132,110 a 8,8 0 0 1 6.9282,4 L 132,118 Z"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90"
@@ -61675,7 +63530,7 @@
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
- d="m 132,110 c 2.85812,0 5.49914,1.52479 6.9282,4 L 132,118 z"
+ d="m 132,110 a 8,8 0 0 1 6.9282,4 L 132,118 Z"
sodipodi:ry="8"
sodipodi:rx="8"
sodipodi:cy="118"
@@ -61690,7 +63545,7 @@
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
sodipodi:ry="8"
sodipodi:rx="8"
sodipodi:cy="118"
@@ -61708,14 +63563,14 @@
sodipodi:cy="118"
sodipodi:rx="8"
sodipodi:ry="8"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90" />
</g>
</g>
<g
- id="g37816"
+ id="ICON_ARROW_LEFTRIGHT"
transform="translate(0,2)">
<rect
style="opacity:0;fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
@@ -61767,7 +63622,7 @@
</g>
<g
transform="translate(-58,340)"
- id="g41151"
+ id="ICON_MESH_PLANE"
style="display:inline;enable-background:new">
<rect
y="48"
@@ -61806,7 +63661,7 @@
</g>
<g
transform="translate(-15,340)"
- id="g41161"
+ id="ICON_MESH_UVSPHERE"
style="display:inline;enable-background:new">
<rect
y="48"
@@ -61831,7 +63686,7 @@
sodipodi:cy="118"
sodipodi:rx="8"
sodipodi:ry="8"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90" />
@@ -61840,7 +63695,7 @@
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
sodipodi:ry="8"
sodipodi:rx="8"
sodipodi:cy="118"
@@ -61857,7 +63712,7 @@
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
sodipodi:ry="8"
sodipodi:rx="8"
sodipodi:cy="118"
@@ -61870,7 +63725,7 @@
</g>
<g
style="display:inline;enable-background:new"
- id="g41175"
+ id="ICON_MESH_CUBE"
transform="translate(-21,359)">
<rect
y="29"
@@ -61926,7 +63781,7 @@
<g
style="display:inline;enable-background:new"
transform="translate(3,417)"
- id="g41191">
+ id="ICON_MESH_MONKEY">
<rect
style="opacity:0;fill:#cccccc;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.69999999;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
id="rect41193"
@@ -61979,7 +63834,7 @@
style="fill:#f9f9f9;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.69999999;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
<path
transform="translate(0.5,-0.46875)"
- d="m 134,-23 c 0,0.552285 -0.44772,1 -1,1 -0.55228,0 -1,-0.447715 -1,-1 0,-0.552285 0.44772,-1 1,-1 0.55228,0 1,0.447715 1,1 z"
+ d="m 134,-23 a 1,1 0 0 1 -1,1 1,1 0 0 1 -1,-1 1,1 0 0 1 1,-1 1,1 0 0 1 1,1 z"
sodipodi:ry="1"
sodipodi:rx="1"
sodipodi:cy="-23"
@@ -61995,7 +63850,7 @@
sodipodi:cy="-23"
sodipodi:rx="1"
sodipodi:ry="1"
- d="m 134,-23 c 0,0.552285 -0.44772,1 -1,1 -0.55228,0 -1,-0.447715 -1,-1 0,-0.552285 0.44772,-1 1,-1 0.55228,0 1,0.447715 1,1 z"
+ d="m 134,-23 a 1,1 0 0 1 -1,1 1,1 0 0 1 -1,-1 1,1 0 0 1 1,-1 1,1 0 0 1 1,1 z"
transform="matrix(1.2143583,0,0,1.1512108,-28.054112,2.9290602)" />
<path
sodipodi:type="arc"
@@ -62005,7 +63860,7 @@
sodipodi:cy="-23"
sodipodi:rx="1"
sodipodi:ry="1"
- d="m 134,-23 c 0,0.552285 -0.44772,1 -1,1 -0.55228,0 -1,-0.447715 -1,-1 0,-0.552285 0.44772,-1 1,-1 0.55228,0 1,0.447715 1,1 z"
+ d="m 134,-23 a 1,1 0 0 1 -1,1 1,1 0 0 1 -1,-1 1,1 0 0 1 1,-1 1,1 0 0 1 1,1 z"
transform="matrix(0.8392157,0,0,0.8382979,21.884318,-4.2140957)" />
<rect
style="opacity:0.5;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.69999999;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
@@ -62022,7 +63877,7 @@
inkscape:connector-curvature="0" />
<path
transform="matrix(1.2116904,0,0,1.1282344,-22.693138,2.3776257)"
- d="m 134,-23 c 0,0.552285 -0.44772,1 -1,1 -0.55228,0 -1,-0.447715 -1,-1 0,-0.552285 0.44772,-1 1,-1 0.55228,0 1,0.447715 1,1 z"
+ d="m 134,-23 a 1,1 0 0 1 -1,1 1,1 0 0 1 -1,-1 1,1 0 0 1 1,-1 1,1 0 0 1 1,1 z"
sodipodi:ry="1"
sodipodi:rx="1"
sodipodi:cy="-23"
@@ -62032,7 +63887,7 @@
sodipodi:type="arc" />
<path
transform="matrix(0.8392157,0,0,0.8382979,26.893134,-4.2140957)"
- d="m 134,-23 c 0,0.552285 -0.44772,1 -1,1 -0.55228,0 -1,-0.447715 -1,-1 0,-0.552285 0.44772,-1 1,-1 0.55228,0 1,0.447715 1,1 z"
+ d="m 134,-23 a 1,1 0 0 1 -1,1 1,1 0 0 1 -1,-1 1,1 0 0 1 1,-1 1,1 0 0 1 1,1 z"
sodipodi:ry="1"
sodipodi:rx="1"
sodipodi:cy="-23"
@@ -62062,7 +63917,7 @@
</g>
<g
style="display:inline;enable-background:new"
- id="g41229"
+ id="ICON_MESH_ICOSPHERE"
transform="translate(169,365)">
<rect
y="23"
@@ -62153,7 +64008,7 @@
</g>
<g
style="display:inline;enable-background:new"
- id="g41255"
+ id="ICON_MESH_GRID"
transform="translate(231,348)">
<rect
y="40"
@@ -62269,7 +64124,7 @@
</g>
<g
style="display:inline;enable-background:new"
- id="g41283"
+ id="ICON_MESH_CIRCLE"
transform="translate(275,332)">
<rect
y="56"
@@ -62282,7 +64137,7 @@
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
sodipodi:ry="8"
sodipodi:rx="8"
sodipodi:cy="118"
@@ -62299,7 +64154,7 @@
sodipodi:cy="118"
sodipodi:rx="8"
sodipodi:ry="8"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90"
@@ -62313,7 +64168,7 @@
sodipodi:cy="118"
sodipodi:rx="8"
sodipodi:ry="8"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90" />
@@ -62321,7 +64176,7 @@
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
sodipodi:ry="8"
sodipodi:rx="8"
sodipodi:cy="118"
@@ -62333,7 +64188,7 @@
</g>
<g
style="display:inline;enable-background:new"
- id="g41295"
+ id="ICON_MESH_CYLINDER"
transform="translate(380,233)">
<rect
y="155"
@@ -62375,7 +64230,7 @@
</g>
<g
style="display:inline;enable-background:new"
- id="g41309"
+ id="ICON_MESH_TORUS"
transform="translate(401,212)">
<rect
style="opacity:0;fill:#ff0000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
@@ -62416,12 +64271,12 @@
sodipodi:cy="40.5"
sodipodi:rx="6.5"
sodipodi:ry="2.5"
- d="m -213.5,40.5 c 0,1.380712 -2.91015,2.5 -6.5,2.5 -3.58985,0 -6.5,-1.119288 -6.5,-2.5 0,-1.380712 2.91015,-2.5 6.5,-2.5 3.58985,0 6.5,1.119288 6.5,2.5 z"
+ d="m -213.5,40.5 a 6.5,2.5 0 0 1 -6.5,2.5 6.5,2.5 0 0 1 -6.5,-2.5 6.5,2.5 0 0 1 6.5,-2.5 6.5,2.5 0 0 1 6.5,2.5 z"
transform="matrix(0.9999986,0,0,1.799999,-2.971883e-4,111.10004)" />
</g>
<g
style="display:inline;enable-background:new"
- id="g41323"
+ id="ICON_MESH_CONE"
transform="translate(422,192)">
<rect
y="196"
@@ -62451,7 +64306,7 @@
</g>
<g
style="display:inline;enable-background:new"
- id="g41333"
+ id="ICON_CURVE_BEZCURVE"
transform="translate(472,230)">
<rect
style="opacity:0.01000001;fill:#ff0000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
@@ -62606,7 +64461,7 @@
</g>
<g
style="display:inline;enable-background:new"
- id="g41381"
+ id="ICON_CURVE_NCURVE"
transform="matrix(0,1,1,0,99,651)">
<rect
y="137"
@@ -62760,7 +64615,7 @@
</g>
<g
style="display:inline;enable-background:new"
- id="g41431"
+ id="ICON_CURVE_NCIRCLE"
transform="translate(565.49991,277.875)">
<g
transform="translate(-23.5,-18.875)"
@@ -62826,7 +64681,7 @@
sodipodi:cy="118"
sodipodi:rx="8"
sodipodi:ry="8"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90" />
@@ -62834,7 +64689,7 @@
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
sodipodi:ry="8"
sodipodi:rx="8"
sodipodi:cy="118"
@@ -62847,7 +64702,7 @@
</g>
<g
style="display:inline;enable-background:new"
- id="g41459"
+ id="ICON_SURFACE_NCIRCLE"
transform="translate(311,278)">
<g
transform="translate(0,-19)"
@@ -62915,7 +64770,7 @@
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
sodipodi:ry="8"
sodipodi:rx="8"
sodipodi:cy="118"
@@ -62932,7 +64787,7 @@
sodipodi:cy="118"
sodipodi:rx="8"
sodipodi:ry="8"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90"
@@ -62946,7 +64801,7 @@
sodipodi:cy="118"
sodipodi:rx="8"
sodipodi:ry="8"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90" />
@@ -62954,7 +64809,7 @@
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
sodipodi:ry="8"
sodipodi:rx="8"
sodipodi:cy="118"
@@ -62967,7 +64822,7 @@
</g>
<g
style="display:inline;enable-background:new"
- id="g41493"
+ id="ICON_CURVE_BEZCIRCLE"
transform="translate(455,122.97748)">
<rect
y="244.02252"
@@ -63040,7 +64895,7 @@
sodipodi:cy="118"
sodipodi:rx="8"
sodipodi:ry="8"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90" />
@@ -63048,7 +64903,7 @@
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
sodipodi:ry="8"
sodipodi:rx="8"
sodipodi:cy="118"
@@ -63079,7 +64934,7 @@
</g>
<g
style="display:inline;enable-background:new"
- id="g41527"
+ id="ICON_SURFACE_NCURVE"
transform="translate(70.968338,302.76882)">
<rect
transform="matrix(0,1,1,0,0,0)"
@@ -63275,7 +65130,7 @@
</g>
<g
style="display:inline;enable-background:new"
- id="g41587"
+ id="ICON_SURFACE_NCYLINDER"
transform="translate(375,231.00851)">
<rect
style="opacity:0;fill:#ff0000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
@@ -63372,7 +65227,7 @@
</g>
<g
style="display:inline;enable-background:new"
- id="g41623"
+ id="ICON_SURFACE_NSURFACE"
transform="translate(258.99995,102)">
<rect
transform="scale(-1,1)"
@@ -63540,7 +65395,7 @@
</g>
<g
style="display:inline;enable-background:new"
- id="g41680"
+ id="ICON_SURFACE_NTORUS"
transform="translate(338.00016,191)">
<g
id="g41682"
@@ -63627,7 +65482,7 @@
inkscape:connector-curvature="0" />
<path
transform="matrix(0.9999986,0,0,1.799999,-2.971883e-4,111.10004)"
- d="m -213.5,40.5 c 0,1.380712 -2.91015,2.5 -6.5,2.5 -3.58985,0 -6.5,-1.119288 -6.5,-2.5 0,-1.380712 2.91015,-2.5 6.5,-2.5 3.58985,0 6.5,1.119288 6.5,2.5 z"
+ d="m -213.5,40.5 a 6.5,2.5 0 0 1 -6.5,2.5 6.5,2.5 0 0 1 -6.5,-2.5 6.5,2.5 0 0 1 6.5,-2.5 6.5,2.5 0 0 1 6.5,2.5 z"
sodipodi:ry="2.5"
sodipodi:rx="6.5"
sodipodi:cy="40.5"
@@ -63638,7 +65493,7 @@
</g>
<g
style="display:inline;enable-background:new"
- id="g41715"
+ id="ICON_SURFACE_NSPHERE"
transform="translate(300.99985,63)">
<rect
style="opacity:0;fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
@@ -63710,7 +65565,7 @@
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
sodipodi:ry="8"
sodipodi:rx="8"
sodipodi:cy="118"
@@ -63727,7 +65582,7 @@
sodipodi:cy="118"
sodipodi:rx="8"
sodipodi:ry="8"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90"
@@ -63741,7 +65596,7 @@
sodipodi:cy="118"
sodipodi:rx="8"
sodipodi:ry="8"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90" />
@@ -63755,7 +65610,7 @@
</g>
<g
style="display:inline;enable-background:new"
- id="g41749"
+ id="ICON_CURVE_PATH"
transform="matrix(1,0,0,-1,496,768)">
<rect
transform="scale(-1,1)"
@@ -63859,7 +65714,7 @@
</g>
<g
style="display:inline;enable-background:new"
- id="g42152"
+ id="ICON_META_CUBE"
transform="translate(272.99917,170)">
<g
transform="translate(83.990361,105)"
@@ -63874,7 +65729,7 @@
sodipodi:cy="118"
sodipodi:rx="8"
sodipodi:ry="8"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90" />
@@ -63882,7 +65737,7 @@
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
sodipodi:ry="8"
sodipodi:rx="8"
sodipodi:cy="118"
@@ -63900,7 +65755,7 @@
sodipodi:cy="118"
sodipodi:rx="8"
sodipodi:ry="8"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90" />
@@ -63913,7 +65768,7 @@
sodipodi:cy="118"
sodipodi:rx="8"
sodipodi:ry="8"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90" />
@@ -63963,7 +65818,7 @@
</g>
<g
style="display:inline;enable-background:new"
- id="g42181"
+ id="ICON_META_CAPSULE"
transform="translate(335.99917,149.00001)">
<g
style="opacity:0.5"
@@ -63973,7 +65828,7 @@
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
sodipodi:ry="8"
sodipodi:rx="8"
sodipodi:cy="118"
@@ -63991,7 +65846,7 @@
sodipodi:cy="118"
sodipodi:rx="8"
sodipodi:ry="8"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90" />
@@ -63999,7 +65854,7 @@
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
sodipodi:ry="8"
sodipodi:rx="8"
sodipodi:cy="118"
@@ -64012,7 +65867,7 @@
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
sodipodi:ry="8"
sodipodi:rx="8"
sodipodi:cy="118"
@@ -64064,7 +65919,7 @@
</g>
<g
style="display:inline;enable-background:new"
- id="g42207"
+ id="ICON_META_PLANE"
transform="translate(251.99917,191.00001)">
<g
transform="translate(83.990364,83.999999)"
@@ -64079,7 +65934,7 @@
sodipodi:cy="118"
sodipodi:rx="8"
sodipodi:ry="8"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90" />
@@ -64087,7 +65942,7 @@
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
sodipodi:ry="8"
sodipodi:rx="8"
sodipodi:cy="118"
@@ -64105,7 +65960,7 @@
sodipodi:cy="118"
sodipodi:rx="8"
sodipodi:ry="8"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90" />
@@ -64118,7 +65973,7 @@
sodipodi:cy="118"
sodipodi:rx="8"
sodipodi:ry="8"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90" />
@@ -64153,7 +66008,7 @@
</g>
<g
style="display:inline;enable-background:new"
- id="g42225"
+ id="ICON_META_BALL"
transform="translate(293.99917,128.01655)">
<g
id="g42227">
@@ -64170,7 +66025,7 @@
sodipodi:cy="118"
sodipodi:rx="8"
sodipodi:ry="8"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90" />
@@ -64178,7 +66033,7 @@
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
sodipodi:ry="8"
sodipodi:rx="8"
sodipodi:cy="118"
@@ -64196,7 +66051,7 @@
sodipodi:cy="118"
sodipodi:rx="8"
sodipodi:ry="8"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90" />
@@ -64209,7 +66064,7 @@
sodipodi:cy="118"
sodipodi:rx="8"
sodipodi:ry="8"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90" />
@@ -64226,7 +66081,7 @@
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
sodipodi:ry="8"
sodipodi:rx="8"
sodipodi:cy="118"
@@ -64243,7 +66098,7 @@
sodipodi:cy="118"
sodipodi:rx="8"
sodipodi:ry="8"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90"
@@ -64257,7 +66112,7 @@
sodipodi:cy="118"
sodipodi:rx="8"
sodipodi:ry="8"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90" />
@@ -64265,7 +66120,7 @@
</g>
<g
style="display:inline;enable-background:new"
- id="g42247"
+ id="ICON_META_ELLIPSOID"
transform="translate(315,107)">
<g
transform="translate(83.990364,168)"
@@ -64280,7 +66135,7 @@
sodipodi:cy="118"
sodipodi:rx="8"
sodipodi:ry="8"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90" />
@@ -64288,7 +66143,7 @@
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
sodipodi:ry="8"
sodipodi:rx="8"
sodipodi:cy="118"
@@ -64306,7 +66161,7 @@
sodipodi:cy="118"
sodipodi:rx="8"
sodipodi:ry="8"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90" />
@@ -64319,7 +66174,7 @@
sodipodi:cy="118"
sodipodi:rx="8"
sodipodi:ry="8"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90" />
@@ -64382,7 +66237,7 @@
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Pracowniaa\Pulpit\Browser icons ver 1\font_file SMALL.png"
transform="translate(10.00003,171.5)"
- id="g42279">
+ id="ICON_OUTLINER_DATA_FONT">
<rect
y="237.5"
x="162.99997"
@@ -64507,7 +66362,7 @@
</g>
<g
style="display:inline;enable-background:new"
- id="g35366"
+ id="ICON_META_DATA"
transform="translate(333.02099,358)">
<rect
y="135"
@@ -64529,7 +66384,7 @@
sodipodi:cy="118"
sodipodi:rx="8"
sodipodi:ry="8"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90" />
@@ -64537,7 +66392,7 @@
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
sodipodi:ry="8"
sodipodi:rx="8"
sodipodi:cy="118"
@@ -64555,7 +66410,7 @@
sodipodi:cy="118"
sodipodi:rx="8"
sodipodi:ry="8"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90" />
@@ -64603,7 +66458,7 @@
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
sodipodi:ry="8"
sodipodi:rx="8"
sodipodi:cy="118"
@@ -64621,7 +66476,7 @@
sodipodi:cy="118"
sodipodi:rx="8"
sodipodi:ry="8"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90" />
@@ -64629,7 +66484,7 @@
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
sodipodi:ry="8"
sodipodi:rx="8"
sodipodi:cy="118"
@@ -64651,7 +66506,7 @@
sodipodi:cy="292.5"
sodipodi:rx="4"
sodipodi:ry="4"
- d="m 223.5,292.5 c 0,2.20914 -1.79086,4 -4,4 -2.20914,0 -4,-1.79086 -4,-4 0,-2.20914 1.79086,-4 4,-4 2.20914,0 4,1.79086 4,4 z"
+ d="m 223.5,292.5 a 4,4 0 0 1 -4,4 4,4 0 0 1 -4,-4 4,4 0 0 1 4,-4 4,4 0 0 1 4,4 z"
transform="translate(20,0)" />
<path
sodipodi:type="arc"
@@ -64661,11 +66516,11 @@
sodipodi:cy="292.5"
sodipodi:rx="4"
sodipodi:ry="4"
- d="m 223.5,292.5 c 0,2.20914 -1.79086,4 -4,4 -2.20914,0 -4,-1.79086 -4,-4 0,-2.20914 1.79086,-4 4,-4 2.20914,0 4,1.79086 4,4 z"
+ d="m 223.5,292.5 a 4,4 0 0 1 -4,4 4,4 0 0 1 -4,-4 4,4 0 0 1 4,-4 4,4 0 0 1 4,4 z"
transform="matrix(0.875,0,0,0.875,47.4375,36.5625)" />
<path
transform="matrix(0.7060003,0,0,0.7060647,84.532933,85.976064)"
- d="m 223.5,292.5 c 0,2.20914 -1.79086,4 -4,4 -2.20914,0 -4,-1.79086 -4,-4 0,-2.20914 1.79086,-4 4,-4 2.20914,0 4,1.79086 4,4 z"
+ d="m 223.5,292.5 a 4,4 0 0 1 -4,4 4,4 0 0 1 -4,-4 4,4 0 0 1 4,-4 4,4 0 0 1 4,4 z"
sodipodi:ry="4"
sodipodi:rx="4"
sodipodi:cy="292.5"
@@ -64675,7 +66530,7 @@
sodipodi:type="arc" />
<path
transform="matrix(0.875,0,0,0.875,47.4375,36.5625)"
- d="m 223.5,292.5 c 0,2.20914 -1.79086,4 -4,4 -2.20914,0 -4,-1.79086 -4,-4 0,-2.20914 1.79086,-4 4,-4 2.20914,0 4,1.79086 4,4 z"
+ d="m 223.5,292.5 a 4,4 0 0 1 -4,4 4,4 0 0 1 -4,-4 4,4 0 0 1 4,-4 4,4 0 0 1 4,4 z"
sodipodi:ry="4"
sodipodi:rx="4"
sodipodi:cy="292.5"
@@ -64687,7 +66542,7 @@
</g>
<g
transform="translate(291,273.9804)"
- id="g35428"
+ id="ICON_OUTLINER_DATA_META"
style="display:inline;enable-background:new">
<rect
style="opacity:0;fill:#dcdcdc;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.80000001;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
@@ -64704,7 +66559,7 @@
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
sodipodi:ry="8"
sodipodi:rx="8"
sodipodi:cy="118"
@@ -64722,7 +66577,7 @@
sodipodi:cy="118"
sodipodi:rx="8"
sodipodi:ry="8"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90" />
@@ -64730,7 +66585,7 @@
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
sodipodi:ry="8"
sodipodi:rx="8"
sodipodi:cy="118"
@@ -64788,7 +66643,7 @@
sodipodi:cy="118"
sodipodi:rx="8"
sodipodi:ry="8"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90" />
@@ -64796,7 +66651,7 @@
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
sodipodi:ry="8"
sodipodi:rx="8"
sodipodi:cy="118"
@@ -64814,7 +66669,7 @@
sodipodi:cy="118"
sodipodi:rx="8"
sodipodi:ry="8"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90" />
@@ -64825,7 +66680,7 @@
style="opacity:0.9;display:inline;enable-background:new">
<path
transform="translate(20,0)"
- d="m 223.5,292.5 c 0,2.20914 -1.79086,4 -4,4 -2.20914,0 -4,-1.79086 -4,-4 0,-2.20914 1.79086,-4 4,-4 2.20914,0 4,1.79086 4,4 z"
+ d="m 223.5,292.5 a 4,4 0 0 1 -4,4 4,4 0 0 1 -4,-4 4,4 0 0 1 4,-4 4,4 0 0 1 4,4 z"
sodipodi:ry="4"
sodipodi:rx="4"
sodipodi:cy="292.5"
@@ -64835,7 +66690,7 @@
sodipodi:type="arc" />
<path
transform="matrix(0.875,0,0,0.875,47.4375,36.5625)"
- d="m 223.5,292.5 c 0,2.20914 -1.79086,4 -4,4 -2.20914,0 -4,-1.79086 -4,-4 0,-2.20914 1.79086,-4 4,-4 2.20914,0 4,1.79086 4,4 z"
+ d="m 223.5,292.5 a 4,4 0 0 1 -4,4 4,4 0 0 1 -4,-4 4,4 0 0 1 4,-4 4,4 0 0 1 4,4 z"
sodipodi:ry="4"
sodipodi:rx="4"
sodipodi:cy="292.5"
@@ -64851,7 +66706,7 @@
sodipodi:cy="292.5"
sodipodi:rx="4"
sodipodi:ry="4"
- d="m 223.5,292.5 c 0,2.20914 -1.79086,4 -4,4 -2.20914,0 -4,-1.79086 -4,-4 0,-2.20914 1.79086,-4 4,-4 2.20914,0 4,1.79086 4,4 z"
+ d="m 223.5,292.5 a 4,4 0 0 1 -4,4 4,4 0 0 1 -4,-4 4,4 0 0 1 4,-4 4,4 0 0 1 4,4 z"
transform="matrix(0.7060003,0,0,0.7060647,84.532933,85.976064)" />
<path
sodipodi:type="arc"
@@ -64861,12 +66716,12 @@
sodipodi:cy="292.5"
sodipodi:rx="4"
sodipodi:ry="4"
- d="m 223.5,292.5 c 0,2.20914 -1.79086,4 -4,4 -2.20914,0 -4,-1.79086 -4,-4 0,-2.20914 1.79086,-4 4,-4 2.20914,0 4,1.79086 4,4 z"
+ d="m 223.5,292.5 a 4,4 0 0 1 -4,4 4,4 0 0 1 -4,-4 4,4 0 0 1 4,-4 4,4 0 0 1 4,4 z"
transform="matrix(0.875,0,0,0.875,47.4375,36.5625)" />
</g>
</g>
<g
- id="g34702"
+ id="ICON_MAT_SPHERE_SKY"
inkscape:export-filename="C:\Documents and Settings\Pracownia\Moje dokumenty\Moje obrazy\BLENDER ICONS redesign\ver 3\sphere with sky.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90">
@@ -64885,11 +66740,11 @@
sodipodi:cy="192.5"
sodipodi:rx="1.75"
sodipodi:ry="1.75"
- d="m 466.25,192.5 c 0,0.9665 -0.7835,1.75 -1.75,1.75 -0.9665,0 -1.75,-0.7835 -1.75,-1.75 0,-0.9665 0.7835,-1.75 1.75,-1.75 0.9665,0 1.75,0.7835 1.75,1.75 z"
+ d="m 466.25,192.5 a 1.75,1.75 0 0 1 -1.75,1.75 1.75,1.75 0 0 1 -1.75,-1.75 1.75,1.75 0 0 1 1.75,-1.75 1.75,1.75 0 0 1 1.75,1.75 z"
transform="matrix(1.7142856,0,0,1.7142871,-330.83199,-136.46043)" />
<path
transform="matrix(1.4285718,0,0,1.4285718,-198.61789,-81.960223)"
- d="m 466.25,192.5 c 0,0.9665 -0.7835,1.75 -1.75,1.75 -0.9665,0 -1.75,-0.7835 -1.75,-1.75 0,-0.9665 0.7835,-1.75 1.75,-1.75 0.9665,0 1.75,0.7835 1.75,1.75 z"
+ d="m 466.25,192.5 a 1.75,1.75 0 0 1 -1.75,1.75 1.75,1.75 0 0 1 -1.75,-1.75 1.75,1.75 0 0 1 1.75,-1.75 1.75,1.75 0 0 1 1.75,1.75 z"
sodipodi:ry="1.75"
sodipodi:rx="1.75"
sodipodi:cy="192.5"
@@ -64905,7 +66760,7 @@
sodipodi:cy="192.5"
sodipodi:rx="1.75"
sodipodi:ry="1.75"
- d="m 466.25,192.5 c 0,0.9665 -0.7835,1.75 -1.75,1.75 -0.9665,0 -1.75,-0.7835 -1.75,-1.75 0,-0.9665 0.7835,-1.75 1.75,-1.75 0.9665,0 1.75,0.7835 1.75,1.75 z"
+ d="m 466.25,192.5 a 1.75,1.75 0 0 1 -1.75,1.75 1.75,1.75 0 0 1 -1.75,-1.75 1.75,1.75 0 0 1 1.75,-1.75 1.75,1.75 0 0 1 1.75,1.75 z"
transform="matrix(0.8571429,0,0,0.8571429,66.810813,28.039828)" />
</g>
<rect
@@ -64929,7 +66784,7 @@
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
sodipodi:ry="8"
sodipodi:rx="8"
sodipodi:cy="118"
@@ -64947,7 +66802,7 @@
sodipodi:cy="118"
sodipodi:rx="8"
sodipodi:ry="8"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90" />
@@ -64960,7 +66815,7 @@
sodipodi:cy="118"
sodipodi:rx="8"
sodipodi:ry="8"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90" />
@@ -64968,7 +66823,7 @@
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
sodipodi:ry="8"
sodipodi:rx="8"
sodipodi:cy="118"
@@ -65008,7 +66863,7 @@
sodipodi:cy="118"
sodipodi:rx="8"
sodipodi:ry="8"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90" />
@@ -65017,7 +66872,7 @@
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
sodipodi:ry="8"
sodipodi:rx="8"
sodipodi:cy="118"
@@ -65029,7 +66884,7 @@
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
sodipodi:ry="8"
sodipodi:rx="8"
sodipodi:cy="118"
@@ -65041,38 +66896,8 @@
</g>
</g>
<g
- style="stroke:#ffffff;display:inline"
- transform="matrix(-1,0,0,-1,104.1613,262.99999)"
- inkscape:export-ydpi="90"
- inkscape:export-xdpi="90"
- inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
- id="g34782">
- <path
- d=""
- sodipodi:nodetypes="cz"
- id="path34784"
- style="fill:none;stroke:#ffffff;stroke-width:1.60000002;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:7.40000034;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- inkscape:connector-curvature="0" />
- </g>
- <path
- style="fill:none;stroke:#ffffff;stroke-width:1.60000002;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:7.40000034;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- id="path34806"
- sodipodi:nodetypes="cz"
- d=""
- inkscape:connector-curvature="0" />
- <path
- d=""
- sodipodi:nodetypes="cz"
- id="path34696"
- style="fill:none;stroke:#ffffff;stroke-width:1.60000002;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:7.40000034;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- inkscape:connector-curvature="0" />
- <g
- transform="matrix(-1,0,0,1,-155,-228)"
- style="opacity:0.12000002"
- id="g36040" />
- <g
style="display:inline;enable-background:new"
- id="g36398"
+ id="ICON_MANIPUL"
transform="translate(-20.999985,0)">
<rect
y="157"
@@ -65222,7 +67047,7 @@
sodipodi:cy="14.5"
sodipodi:rx="1.5"
sodipodi:ry="1.5"
- d="M 72,14.5 C 72,15.328427 71.328427,16 70.5,16 69.671573,16 69,15.328427 69,14.5 69,13.671573 69.671573,13 70.5,13 c 0.828427,0 1.5,0.671573 1.5,1.5 z"
+ d="M 72,14.5 A 1.5,1.5 0 0 1 70.5,16 1.5,1.5 0 0 1 69,14.5 1.5,1.5 0 0 1 70.5,13 1.5,1.5 0 0 1 72,14.5 Z"
transform="matrix(1.3333333,0,0,1.3333343,3,147.66665)"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png"
inkscape:export-xdpi="90"
@@ -65236,7 +67061,7 @@
sodipodi:cy="14.5"
sodipodi:rx="1.5"
sodipodi:ry="1.5"
- d="M 72,14.5 C 72,15.328427 71.328427,16 70.5,16 69.671573,16 69,15.328427 69,14.5 69,13.671573 69.671573,13 70.5,13 c 0.828427,0 1.5,0.671573 1.5,1.5 z"
+ d="M 72,14.5 A 1.5,1.5 0 0 1 70.5,16 1.5,1.5 0 0 1 69,14.5 1.5,1.5 0 0 1 70.5,13 1.5,1.5 0 0 1 72,14.5 Z"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90" />
@@ -65284,7 +67109,7 @@
</g>
<g
transform="translate(105,337.99999)"
- id="g35291"
+ id="ICON_LAMP_SPOT"
style="display:inline;enable-background:new">
<rect
style="opacity:0;fill:#ff0000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
@@ -65329,14 +67154,14 @@
sodipodi:cy="35"
sodipodi:rx="1.2111344"
sodipodi:ry="4.9951267"
- d="m 182.21113,35 c 0,2.758732 -0.54224,4.995127 -1.21113,4.995127 -0.66889,0 -1.21113,-2.236395 -1.21113,-4.995127 0,-2.758732 0.54224,-4.995127 1.21113,-4.995127 0.66788,0 1.20971,2.229902 1.21113,4.984465"
+ d="m 182.21113,35 a 1.2111344,4.9951267 0 0 1 -1.21048,4.995126 1.2111344,4.9951267 0 0 1 -1.21178,-4.989795 1.2111344,4.9951267 0 0 1 1.20919,-5.000451 1.2111344,4.9951267 0 0 1 1.21307,4.984458"
transform="matrix(1.2491741,-1.2491602,0.7680871,0.768079,-75.108556,239.34027)"
sodipodi:start="0"
sodipodi:end="6.2810509"
sodipodi:open="true" />
<path
transform="matrix(0.9589476,-0.9192618,0.5776079,0.5780619,-15.42366,185.77921)"
- d="m 182.17638,35 c 0,3.053777 -0.52668,5.529352 -1.17638,5.529352 -0.6497,0 -1.17638,-2.475575 -1.17638,-5.529352 0,-3.053777 0.52668,-5.529352 1.17638,-5.529352 0.6497,0 1.17638,2.475575 1.17638,5.529352 z"
+ d="M 182.17638,35 A 1.1763829,5.5293522 0 0 1 181,40.529352 1.1763829,5.5293522 0 0 1 179.82362,35 1.1763829,5.5293522 0 0 1 181,29.470648 1.1763829,5.5293522 0 0 1 182.17638,35 Z"
sodipodi:ry="5.5293522"
sodipodi:rx="1.1763829"
sodipodi:cy="35"
@@ -65447,7 +67272,7 @@
y="59.75" />
</g>
<g
- id="g35343"
+ id="ICON_LAMP_POINT"
transform="translate(0,-7e-6)">
<rect
transform="scale(-1,-1)"
@@ -65684,7 +67509,7 @@
transform="translate(-340.00002,-121.00001)">
<path
transform="matrix(1.9999998,0,0,2.0000014,-462.99991,-192.00026)"
- d="m 466.25,192.5 c 0,0.9665 -0.7835,1.75 -1.75,1.75 -0.9665,0 -1.75,-0.7835 -1.75,-1.75 0,-0.9665 0.7835,-1.75 1.75,-1.75 0.9665,0 1.75,0.7835 1.75,1.75 z"
+ d="m 466.25,192.5 a 1.75,1.75 0 0 1 -1.75,1.75 1.75,1.75 0 0 1 -1.75,-1.75 1.75,1.75 0 0 1 1.75,-1.75 1.75,1.75 0 0 1 1.75,1.75 z"
sodipodi:ry="1.75"
sodipodi:rx="1.75"
sodipodi:cy="192.5"
@@ -65700,11 +67525,11 @@
sodipodi:cy="192.5"
sodipodi:rx="1.75"
sodipodi:ry="1.75"
- d="m 466.25,192.5 c 0,0.9665 -0.7835,1.75 -1.75,1.75 -0.9665,0 -1.75,-0.7835 -1.75,-1.75 0,-0.9665 0.7835,-1.75 1.75,-1.75 0.9665,0 1.75,0.7835 1.75,1.75 z"
+ d="m 466.25,192.5 a 1.75,1.75 0 0 1 -1.75,1.75 1.75,1.75 0 0 1 -1.75,-1.75 1.75,1.75 0 0 1 1.75,-1.75 1.75,1.75 0 0 1 1.75,1.75 z"
transform="matrix(2.5714449,0,0,2.5714449,-728.43612,-302.00313)" />
<path
transform="matrix(1.9999748,0,0,1.9999748,-462.98824,-191.99513)"
- d="m 466.25,192.5 c 0,0.9665 -0.7835,1.75 -1.75,1.75 -0.9665,0 -1.75,-0.7835 -1.75,-1.75 0,-0.9665 0.7835,-1.75 1.75,-1.75 0.9665,0 1.75,0.7835 1.75,1.75 z"
+ d="m 466.25,192.5 a 1.75,1.75 0 0 1 -1.75,1.75 1.75,1.75 0 0 1 -1.75,-1.75 1.75,1.75 0 0 1 1.75,-1.75 1.75,1.75 0 0 1 1.75,1.75 z"
sodipodi:ry="1.75"
sodipodi:rx="1.75"
sodipodi:cy="192.5"
@@ -65714,7 +67539,7 @@
sodipodi:type="arc" />
<path
transform="matrix(1.428566,0,0,1.428566,-197.56891,-81.998957)"
- d="m 466.25,192.5 c 0,0.9665 -0.7835,1.75 -1.75,1.75 -0.9665,0 -1.75,-0.7835 -1.75,-1.75 0,-0.9665 0.7835,-1.75 1.75,-1.75 0.9665,0 1.75,0.7835 1.75,1.75 z"
+ d="m 466.25,192.5 a 1.75,1.75 0 0 1 -1.75,1.75 1.75,1.75 0 0 1 -1.75,-1.75 1.75,1.75 0 0 1 1.75,-1.75 1.75,1.75 0 0 1 1.75,1.75 z"
sodipodi:ry="1.75"
sodipodi:rx="1.75"
sodipodi:cy="192.5"
@@ -65734,7 +67559,7 @@
</g>
<g
transform="translate(147,337.99999)"
- id="g35443"
+ id="ICON_LAMP_SUN"
style="display:inline;enable-background:new">
<rect
style="opacity:0;fill:#ffe680;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.60000002;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
@@ -65759,11 +67584,11 @@
sodipodi:cy="192.5"
sodipodi:rx="1.75"
sodipodi:ry="1.75"
- d="m 466.25,192.5 c 0,0.9665 -0.7835,1.75 -1.75,1.75 -0.9665,0 -1.75,-0.7835 -1.75,-1.75 0,-0.9665 0.7835,-1.75 1.75,-1.75 0.9665,0 1.75,0.7835 1.75,1.75 z"
+ d="m 466.25,192.5 a 1.75,1.75 0 0 1 -1.75,1.75 1.75,1.75 0 0 1 -1.75,-1.75 1.75,1.75 0 0 1 1.75,-1.75 1.75,1.75 0 0 1 1.75,1.75 z"
transform="matrix(1.9999998,0,0,2.0000014,-790.00001,-327.00035)" />
<path
transform="matrix(2.5714622,0,0,2.5714622,-1055.4442,-437.00638)"
- d="m 466.25,192.5 c 0,0.9665 -0.7835,1.75 -1.75,1.75 -0.9665,0 -1.75,-0.7835 -1.75,-1.75 0,-0.9665 0.7835,-1.75 1.75,-1.75 0.9665,0 1.75,0.7835 1.75,1.75 z"
+ d="m 466.25,192.5 a 1.75,1.75 0 0 1 -1.75,1.75 1.75,1.75 0 0 1 -1.75,-1.75 1.75,1.75 0 0 1 1.75,-1.75 1.75,1.75 0 0 1 1.75,1.75 z"
sodipodi:ry="1.75"
sodipodi:rx="1.75"
sodipodi:cy="192.5"
@@ -65773,7 +67598,7 @@
sodipodi:type="arc" />
<path
transform="matrix(2.0000089,0,0,2.0000089,-790.00413,-327.00163)"
- d="m 466.25,192.5 c 0,0.9665 -0.7835,1.75 -1.75,1.75 -0.9665,0 -1.75,-0.7835 -1.75,-1.75 0,-0.9665 0.7835,-1.75 1.75,-1.75 0.9665,0 1.75,0.7835 1.75,1.75 z"
+ d="m 466.25,192.5 a 1.75,1.75 0 0 1 -1.75,1.75 1.75,1.75 0 0 1 -1.75,-1.75 1.75,1.75 0 0 1 1.75,-1.75 1.75,1.75 0 0 1 1.75,1.75 z"
sodipodi:ry="1.75"
sodipodi:rx="1.75"
sodipodi:cy="192.5"
@@ -65810,7 +67635,7 @@
</g>
<g
transform="translate(189,295.99999)"
- id="g35463"
+ id="ICON_LAMP_AREA"
style="display:inline;enable-background:new">
<rect
y="92"
@@ -65832,11 +67657,11 @@
sodipodi:cy="192.5"
sodipodi:rx="1.75"
sodipodi:ry="1.75"
- d="m 466.25,192.5 c 0,0.9665 -0.7835,1.75 -1.75,1.75 -0.9665,0 -1.75,-0.7835 -1.75,-1.75 0,-0.9665 0.7835,-1.75 1.75,-1.75 0.9665,0 1.75,0.7835 1.75,1.75 z"
+ d="m 466.25,192.5 a 1.75,1.75 0 0 1 -1.75,1.75 1.75,1.75 0 0 1 -1.75,-1.75 1.75,1.75 0 0 1 1.75,-1.75 1.75,1.75 0 0 1 1.75,1.75 z"
transform="matrix(2.2376043,0,0,2.2484492,-801.20081,-335.84886)" />
<path
transform="matrix(1.9004611,0,0,1.899214,-644.62036,-268.6269)"
- d="m 466.25,192.5 c 0,0.9665 -0.7835,1.75 -1.75,1.75 -0.9665,0 -1.75,-0.7835 -1.75,-1.75 0,-0.9665 0.7835,-1.75 1.75,-1.75 0.9665,0 1.75,0.7835 1.75,1.75 z"
+ d="m 466.25,192.5 a 1.75,1.75 0 0 1 -1.75,1.75 1.75,1.75 0 0 1 -1.75,-1.75 1.75,1.75 0 0 1 1.75,-1.75 1.75,1.75 0 0 1 1.75,1.75 z"
sodipodi:ry="1.75"
sodipodi:rx="1.75"
sodipodi:cy="192.5"
@@ -65846,7 +67671,7 @@
sodipodi:type="arc" />
<path
transform="matrix(1.5591172,0,0,1.559203,-486.06699,-203.16445)"
- d="m 466.25,192.5 c 0,0.9665 -0.7835,1.75 -1.75,1.75 -0.9665,0 -1.75,-0.7835 -1.75,-1.75 0,-0.9665 0.7835,-1.75 1.75,-1.75 0.9665,0 1.75,0.7835 1.75,1.75 z"
+ d="m 466.25,192.5 a 1.75,1.75 0 0 1 -1.75,1.75 1.75,1.75 0 0 1 -1.75,-1.75 1.75,1.75 0 0 1 1.75,-1.75 1.75,1.75 0 0 1 1.75,1.75 z"
sodipodi:ry="1.75"
sodipodi:rx="1.75"
sodipodi:cy="192.5"
@@ -66014,7 +67839,7 @@
</g>
<g
transform="translate(168,274.99999)"
- id="g35538"
+ id="ICON_LAMP_HEMI"
style="display:inline;enable-background:new">
<rect
style="opacity:0.01000001;fill:#333333;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.80000001;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
@@ -66122,7 +67947,7 @@
</g>
</g>
<g
- id="g36448"
+ id="ICON_ASSET_MANAGER"
transform="translate(41.84997,0.15003049)">
<g
transform="translate(105,416)"
@@ -66253,225 +68078,227 @@
</g>
</g>
<g
- style="fill:#d45500;fill-opacity:1;display:inline"
- transform="translate(250,-41.00755)"
- id="g36511" />
- <g
- style="opacity:0.55;display:inline"
- id="g35729"
- transform="translate(69,-158)">
- <rect
- style="opacity:0;fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- id="rect35731"
- width="16"
- height="16"
- x="-64"
- y="336" />
+ id="ICON_VERTEXSEL">
<g
- transform="translate(1,0)"
- id="g35733">
+ transform="translate(69,-158)"
+ id="g35729"
+ style="opacity:0.55;display:inline">
+ <rect
+ y="336"
+ x="-64"
+ height="16"
+ width="16"
+ id="rect35731"
+ style="opacity:0;fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
<g
- transform="translate(-386,446.5)"
- id="g35735">
- <path
- id="path35737"
- d="m 329.5,-108.25 -5.5,2 0,6.75 5.5,3 5.5,-3 0,-6.75 -5.5,-2 z"
- style="fill:#552200;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:2;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
- sodipodi:nodetypes="ccccccc"
- inkscape:connector-curvature="0" />
- <path
- sodipodi:nodetypes="cccccc"
- style="fill:#c9c9c9;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.06898749px;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- d="m 324,-99.5 0,-7 6,-1.75 0,11.5 -0.5,0.25 -5.5,-3 z"
- id="path35739"
- inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\4.png"
- inkscape:export-xdpi="90"
- inkscape:export-ydpi="90"
- inkscape:connector-curvature="0" />
+ id="g35733"
+ transform="translate(1,0)">
<g
- transform="translate(179,-179)"
- id="g35741">
+ id="g35735"
+ transform="translate(-386,446.5)">
<path
- inkscape:export-ydpi="90"
- inkscape:export-xdpi="90"
- inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\4.png"
- style="fill:#666666;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.89401144px;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- d="m 156,79.5 0,-7 -5,-1.75 0,11.5 5,-2.75 z"
- id="path35743"
- sodipodi:nodetypes="ccccc"
- inkscape:connector-curvature="0" />
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccccc"
+ style="fill:#552200;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:2;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 329.5,-108.25 -5.5,2 0,6.75 5.5,3 5.5,-3 0,-6.75 -5.5,-2 z"
+ id="path35737" />
<path
+ inkscape:connector-curvature="0"
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\4.png"
+ id="path35739"
+ d="m 324,-99.5 0,-7 6,-1.75 0,11.5 -0.5,0.25 -5.5,-3 z"
+ style="fill:#c9c9c9;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.06898749px;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ sodipodi:nodetypes="cccccc" />
+ <g
+ id="g35741"
+ transform="translate(179,-179)">
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccc"
+ id="path35743"
+ d="m 156,79.5 0,-7 -5,-1.75 0,11.5 5,-2.75 z"
+ style="fill:#666666;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.89401144px;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\4.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path35745"
+ d="m 145,72.5 5.5,-2 5.5,2 -5.5,2.5 -5.5,-2.5 z"
+ style="fill:#e6e6e6;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ sodipodi:nodetypes="ccccc"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\4.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ </g>
+ <path
+ inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccc"
- style="fill:#e6e6e6;fill-opacity:1;fill-rule:evenodd;stroke:none"
- d="m 145,72.5 5.5,-2 5.5,2 -5.5,2.5 -5.5,-2.5 z"
- id="path35745"
- inkscape:connector-curvature="0" />
+ id="path35747"
+ d="m 334.5,-106.5 0,6.75 -5,2.75 -5,-2.75 0,-6.75"
+ style="fill:none;stroke:url(#linearGradient36713);stroke-width:0.99999982px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
</g>
+ <rect
+ y="342"
+ x="-57"
+ height="7.75"
+ width="1"
+ id="rect35749"
+ style="fill:url(#linearGradient36715);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.06666696px;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
<path
- style="fill:none;stroke:url(#linearGradient36713);stroke-width:0.99999982px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
- d="m 334.5,-106.5 0,6.75 -5,2.75 -5,-2.75 0,-6.75"
- id="path35747"
- sodipodi:nodetypes="ccccc"
- inkscape:connector-curvature="0" />
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccc"
+ id="path35751"
+ d="m -61,340.65468 c 0,0 4.5,2 4.5,2 l 4.5,-2"
+ style="fill:none;stroke:url(#linearGradient36717);stroke-width:1.10000002;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
</g>
- <rect
- style="fill:url(#linearGradient36715);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.06666696px;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- id="rect35749"
- width="1"
- height="7.75"
- x="-57"
- y="342" />
+ </g>
+ <rect
+ style="opacity:0.12000002;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect37868-0"
+ width="3.9785564"
+ height="4"
+ x="7.0214434"
+ y="181" />
+ <g
+ id="g35803">
<path
- style="fill:none;stroke:url(#linearGradient36717);stroke-width:1.10000002;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
- d="m -61,340.65468 c 0,0 4.5,2 4.5,2 l 4.5,-2"
- id="path35751"
- sodipodi:nodetypes="ccc"
- inkscape:connector-curvature="0" />
+ inkscape:connector-curvature="0"
+ id="path35805"
+ d="m 8.0048608,180.50566 0.036785,0 c 0.8181814,0 1.476865,0.66665 1.476865,1.49473 l 0,1.2e-4 c 0,0.82808 -0.6586836,1.49472 -1.476865,1.49472 l -0.036785,0 c -0.8181897,0 -1.4768733,-0.66664 -1.4768733,-1.49472 l 0,-1.2e-4 c 0,-0.82808 0.6586836,-1.49473 1.4768733,-1.49473 z"
+ style="fill:none;stroke:#542b00;stroke-width:1.495;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:7.40000265;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <path
+ inkscape:connector-curvature="0"
+ inkscape:export-ydpi="90"
+ inkscape:export-xdpi="90"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
+ id="path35807"
+ d="m 9.0203881,181.00394 c -0.6673195,0 -1.334639,1e-5 -2.0019585,1e-5 0,0.66706 0,1.33411 0,2.00119 0.6673195,0 1.334639,-1e-5 2.0019585,-1e-5 0,-0.66707 0,-1.33413 0,-2.00119 z"
+ style="fill:#ffc17d;fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline" />
</g>
</g>
<g
- transform="translate(90,-158)"
- id="g35753"
- style="opacity:0.55;display:inline">
- <rect
- y="336"
- x="-64"
- height="16"
- width="16"
- id="rect35755"
- style="opacity:0;fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ id="ICON_EDGESEL">
<g
- id="g35757"
- transform="translate(1,0)">
+ style="opacity:0.55;display:inline"
+ id="g35753"
+ transform="translate(90,-158)">
+ <rect
+ style="opacity:0;fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect35755"
+ width="16"
+ height="16"
+ x="-64"
+ y="336" />
<g
- id="g35759"
- transform="translate(-386,446.5)">
- <path
- sodipodi:nodetypes="ccccccc"
- style="fill:#552200;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:2;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
- d="m 329.5,-108.25 -5.5,2 0,6.75 5.5,3 5.5,-3 0,-6.75 -5.5,-2 z"
- id="path35761"
- inkscape:connector-curvature="0" />
- <path
- inkscape:export-ydpi="90"
- inkscape:export-xdpi="90"
- inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\4.png"
- id="path35763"
- d="m 324,-99.5 0,-7 6,-1.75 0,11.5 -0.5,0.25 -5.5,-3 z"
- style="fill:#c9c9c9;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.06898749px;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- sodipodi:nodetypes="cccccc"
- inkscape:connector-curvature="0" />
+ transform="translate(1,0)"
+ id="g35757">
<g
- id="g35765"
- transform="translate(179,-179)">
+ transform="translate(-386,446.5)"
+ id="g35759">
<path
- sodipodi:nodetypes="ccccc"
- id="path35767"
- d="m 156,79.5 0,-7 -5,-1.75 0,11.5 5,-2.75 z"
- style="fill:#666666;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.89401144px;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\4.png"
- inkscape:export-xdpi="90"
- inkscape:export-ydpi="90"
- inkscape:connector-curvature="0" />
+ inkscape:connector-curvature="0"
+ id="path35761"
+ d="m 329.5,-108.25 -5.5,2 0,6.75 5.5,3 5.5,-3 0,-6.75 -5.5,-2 z"
+ style="fill:#552200;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:2;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ sodipodi:nodetypes="ccccccc" />
<path
- id="path35769"
- d="m 145,72.5 5.5,-2 5.5,2 -5.5,2.5 -5.5,-2.5 z"
- style="fill:#e6e6e6;fill-opacity:1;fill-rule:evenodd;stroke:none"
- sodipodi:nodetypes="ccccc"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cccccc"
+ style="fill:#c9c9c9;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.06898749px;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 324,-99.5 0,-7 6,-1.75 0,11.5 -0.5,0.25 -5.5,-3 z"
+ id="path35763"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\4.png"
inkscape:export-xdpi="90"
- inkscape:export-ydpi="90"
- inkscape:connector-curvature="0" />
+ inkscape:export-ydpi="90" />
+ <g
+ transform="translate(179,-179)"
+ id="g35765">
+ <path
+ inkscape:connector-curvature="0"
+ inkscape:export-ydpi="90"
+ inkscape:export-xdpi="90"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\4.png"
+ style="fill:#666666;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.89401144px;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 156,79.5 0,-7 -5,-1.75 0,11.5 5,-2.75 z"
+ id="path35767"
+ sodipodi:nodetypes="ccccc" />
+ <path
+ inkscape:connector-curvature="0"
+ inkscape:export-ydpi="90"
+ inkscape:export-xdpi="90"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\4.png"
+ sodipodi:nodetypes="ccccc"
+ style="fill:#e6e6e6;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ d="m 145,72.5 5.5,-2 5.5,2 -5.5,2.5 -5.5,-2.5 z"
+ id="path35769" />
+ </g>
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:url(#linearGradient36719);stroke-width:0.99999982px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 334.5,-106.5 0,6.75 -5,2.75 -5,-2.75 0,-6.75"
+ id="path35772"
+ sodipodi:nodetypes="ccccc" />
</g>
+ <rect
+ style="fill:url(#linearGradient36721);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.06666696px;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect35774"
+ width="1"
+ height="7.75"
+ x="-57"
+ y="342" />
<path
- sodipodi:nodetypes="ccccc"
- id="path35772"
- d="m 334.5,-106.5 0,6.75 -5,2.75 -5,-2.75 0,-6.75"
- style="fill:none;stroke:url(#linearGradient36719);stroke-width:0.99999982px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
- inkscape:connector-curvature="0" />
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:url(#linearGradient36723);stroke-width:1.10000002;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m -61,340.65468 c 0,0 4.5,2 4.5,2 l 4.5,-2"
+ id="path35776"
+ sodipodi:nodetypes="ccc" />
</g>
+ </g>
+ <rect
+ style="opacity:0.12000002;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect37868-0-4"
+ width="3.0000007"
+ height="8"
+ x="28"
+ y="182" />
+ <g
+ transform="translate(65.984093,-55.50004)"
+ id="g35809">
<rect
- y="342"
- x="-57"
- height="7.75"
- width="1"
- id="rect35774"
- style="fill:url(#linearGradient36721);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.06666696px;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ transform="matrix(1,2.1226448e-5,0,1,0,0)"
+ y="237.00038"
+ x="-38.454918"
+ height="8.0116062"
+ width="1.9820247"
+ id="rect35811"
+ style="fill:none;stroke:#542b00;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:0.90196078;stroke-dasharray:none;stroke-dashoffset:7.40000265;display:inline"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <rect
+ inkscape:export-ydpi="90"
+ inkscape:export-xdpi="90"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
+ style="fill:#ffc17d;fill-opacity:1;fill-rule:nonzero;display:inline"
+ id="rect35814"
+ width="0.99999994"
+ height="7.0000257"
+ x="-37.984093"
+ y="237.50137"
+ transform="matrix(1,3.6759233e-5,0,1,0,0)" />
<path
- sodipodi:nodetypes="ccc"
- id="path35776"
- d="m -61,340.65468 c 0,0 4.5,2 4.5,2 l 4.5,-2"
- style="fill:none;stroke:url(#linearGradient36723);stroke-width:1.10000002;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
- inkscape:connector-curvature="0" />
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#462400;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dashoffset:7.40000265;display:inline"
+ d="m -37.5,245 -0.9549,0.0112 0,-8.01161 1.982,4e-5"
+ id="path35816"
+ sodipodi:nodetypes="cccc" />
</g>
</g>
- <rect
- y="181"
- x="7.0214434"
- height="4"
- width="3.9785564"
- id="rect37868-0"
- style="opacity:0.12000002;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
- <g
- id="g35803">
- <path
- style="fill:none;stroke:#542b00;stroke-width:1.495;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:7.40000265;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- d="m 8.0048608,180.50566 0.036785,0 c 0.8181814,0 1.476865,0.66665 1.476865,1.49473 l 0,1.2e-4 c 0,0.82808 -0.6586836,1.49472 -1.476865,1.49472 l -0.036785,0 c -0.8181897,0 -1.4768733,-0.66664 -1.4768733,-1.49472 l 0,-1.2e-4 c 0,-0.82808 0.6586836,-1.49473 1.4768733,-1.49473 z"
- id="path35805"
- inkscape:connector-curvature="0" />
- <path
- style="fill:#ffc17d;fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline"
- d="m 9.0203881,181.00394 c -0.6673195,0 -1.334639,1e-5 -2.0019585,1e-5 0,0.66706 0,1.33411 0,2.00119 0.6673195,0 1.334639,-1e-5 2.0019585,-1e-5 0,-0.66707 0,-1.33413 0,-2.00119 z"
- id="path35807"
- inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
- inkscape:export-xdpi="90"
- inkscape:export-ydpi="90"
- inkscape:connector-curvature="0" />
- </g>
- <rect
- y="182"
- x="28"
- height="8"
- width="3.0000007"
- id="rect37868-0-4"
- style="opacity:0.12000002;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
- <g
- id="g35809"
- transform="translate(65.984093,-55.50004)">
- <rect
- inkscape:export-ydpi="90"
- inkscape:export-xdpi="90"
- inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
- style="fill:none;stroke:#542b00;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:0.90196078;stroke-dasharray:none;stroke-dashoffset:7.40000265;display:inline"
- id="rect35811"
- width="1.9820247"
- height="8.0116062"
- x="-38.454918"
- y="237.00038"
- transform="matrix(1,2.1226448e-5,0,1,0,0)" />
- <rect
- transform="matrix(1,3.6759233e-5,0,1,0,0)"
- y="237.50137"
- x="-37.984093"
- height="7.0000257"
- width="0.99999994"
- id="rect35814"
- style="fill:#ffc17d;fill-opacity:1;fill-rule:nonzero;display:inline"
- inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
- inkscape:export-xdpi="90"
- inkscape:export-ydpi="90" />
- <path
- sodipodi:nodetypes="cccc"
- id="path35816"
- d="m -37.5,245 -0.9549,0.0112 0,-8.01161 1.982,4e-5"
- style="fill:none;stroke:#462400;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dashoffset:7.40000265;display:inline"
- inkscape:connector-curvature="0" />
- </g>
<g
- id="g106643">
+ id="ICON_FACESEL">
<g
transform="translate(111,-158)"
id="g35778"
@@ -66581,7 +68408,7 @@
</g>
<g
transform="matrix(-1,0,0,1,532,25)"
- id="g37386"
+ id="ICON_PLAY_REVERSE"
style="display:inline">
<rect
style="opacity:0;fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
@@ -66611,23 +68438,9 @@
inkscape:connector-curvature="0" />
</g>
</g>
- <rect
- style="opacity:0;fill:#fffeaa;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.80000001;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:new"
- id="rect39658"
- width="1"
- height="0"
- x="-25"
- y="67" />
- <rect
- style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.80000001;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:new"
- id="rect39660"
- width="0"
- height="1"
- x="-24"
- y="66" />
<g
style="display:inline;enable-background:new"
- id="g39029"
+ id="ICON_STYLUS_PRESSURE"
transform="matrix(0,1,1,0,248,835)">
<rect
style="opacity:0.01000001;fill:#909090;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
@@ -66733,7 +68546,7 @@
</g>
<g
style="display:inline;enable-background:new"
- id="g39803"
+ id="ICON_MOD_SMOKE"
transform="translate(-66,268)"
inkscape:export-filename="C:\Documents and Settings\Pracownia\Pulpit\sss.png"
inkscape:export-xdpi="90"
@@ -66762,7 +68575,7 @@
sodipodi:cy="118"
sodipodi:rx="8"
sodipodi:ry="8"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90" />
@@ -66770,7 +68583,7 @@
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
sodipodi:ry="8"
sodipodi:rx="8"
sodipodi:cy="118"
@@ -66843,7 +68656,7 @@
</g>
<g
transform="translate(-249,193)"
- id="g41505"
+ id="ICON_MOD_PHYSICS"
style="display:inline">
<g
style="opacity:0.85"
@@ -66929,7 +68742,7 @@
sodipodi:cy="118"
sodipodi:rx="8"
sodipodi:ry="8"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90"
@@ -66942,35 +68755,128 @@
sodipodi:cy="118"
sodipodi:rx="8"
sodipodi:ry="8"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90"
transform="matrix(-0.3127677,0,0,0.3125443,475.3332,36.070149)" />
</g>
<g
- transform="translate(-21.1375,-0.42)"
- id="g42277">
+ id="ICON_MOD_DECIM">
+ <g
+ transform="translate(0,2)"
+ id="g10823">
+ <rect
+ y="260"
+ x="68"
+ height="16"
+ width="16"
+ id="rect31968"
+ style="opacity:0;fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cccccc"
+ style="fill:url(#linearGradient24189);fill-opacity:1;fill-rule:evenodd;stroke:none;display:inline"
+ d="m 70.562559,271.5 0.24994,0.25 9,-9 -0.24994,-0.25 -9,0 0,9 z"
+ id="path12863"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path12865"
+ style="fill:none;stroke:#0b1728;stroke-width:0.80000001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:7.40000265;display:inline"
+ d="m 70.562559,271.5 -6e-5,-9 9,5e-5 m -4.99994,4.89995 0,-4.8 m 0.89997,3.9 -4.8,0"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"
+ sodipodi:nodetypes="ccccccc" />
+ <path
+ inkscape:connector-curvature="0"
+ style="opacity:0.7;fill:none;stroke:#ffffff;stroke-width:1.00000119px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ d="m 71.562559,265.51369 0,-2.01369 1.99998,0"
+ id="path12867"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <g
+ style="opacity:0.4"
+ id="g24198">
+ <path
+ inkscape:connector-curvature="0"
+ inkscape:export-ydpi="90"
+ inkscape:export-xdpi="90"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
+ sodipodi:nodetypes="cccccc"
+ style="fill:url(#linearGradient24209);fill-opacity:1;fill-rule:evenodd;stroke:none;display:inline"
+ d="m 72.562559,273.5 -0.25006,-0.25 9,-9 0.25006,0.25 0,9 -9,0 z"
+ id="path12861" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccc"
+ id="path27953"
+ d="m 80.499999,265.5 0,7 -7,0"
+ style="fill:none;stroke:url(#linearGradient24192);stroke-width:0.99999875;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dashoffset:7.40000265;display:inline"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <path
+ inkscape:connector-curvature="0"
+ inkscape:export-ydpi="90"
+ inkscape:export-xdpi="90"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
+ style="fill:none;stroke:#000000;stroke-width:0.80000001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:7.40000265;display:inline"
+ d="m 81.562559,264.5 0,9 -9,-5e-5"
+ id="path12869"
+ sodipodi:nodetypes="ccc" />
+ </g>
+ <path
+ inkscape:connector-curvature="0"
+ inkscape:export-ydpi="90"
+ inkscape:export-xdpi="90"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
+ id="path12871"
+ d="m 75.562559,265.51369 0,-2.01369 1.99998,0"
+ style="opacity:0.7;fill:none;stroke:#ffffff;stroke-width:1.00000119px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" />
+ <path
+ inkscape:connector-curvature="0"
+ style="opacity:0.7;fill:none;stroke:#ffffff;stroke-width:1.00000119px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ d="m 71.562579,269.51369 0,-2.01369 1.99998,0"
+ id="path12873"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ </g>
<path
- sodipodi:nodetypes="cccccccccc"
- id="path42279"
- style="opacity:0.75;fill:none;stroke:#28220b;stroke-width:3;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:new"
- d="m 99.6375,267.92 1,-1 m -4,4 1,-1 m 5,-5 1,-1 m -10,10 1,-1 m -4,4 1,-1"
- inkscape:connector-curvature="0" />
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cc"
+ id="path42252"
+ d="M 71,277 83,265"
+ style="opacity:0.2;fill:none;stroke:#000000;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <g
+ id="g42277"
+ transform="translate(-21.1375,-0.42)">
+ <path
+ inkscape:connector-curvature="0"
+ d="m 99.6375,267.92 1,-1 m -4,4 1,-1 m 5,-5 1,-1 m -10,10 1,-1 m -4,4 1,-1"
+ style="opacity:0.75;fill:none;stroke:#28220b;stroke-width:3;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:new"
+ id="path42279"
+ sodipodi:nodetypes="cccccccccc" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path42281"
+ style="fill:none;stroke:#ffefaf;stroke-width:1.39999998;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 99.6375,267.92 1,-1 m -4,4 1,-1 m 5,-5 1,-1 m -10,10 1,-1 m -4,4 1,-1"
+ sodipodi:nodetypes="cccccccccc" />
+ </g>
<path
- sodipodi:nodetypes="cccccccccc"
- d="m 99.6375,267.92 1,-1 m -4,4 1,-1 m 5,-5 1,-1 m -10,10 1,-1 m -4,4 1,-1"
- style="fill:none;stroke:#ffefaf;stroke-width:1.39999998;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- id="path42281"
- inkscape:connector-curvature="0" />
+ inkscape:connector-curvature="0"
+ id="path42595"
+ d="M 69.435939,276.52168 71.5,274.5"
+ style="stroke-width:1px" />
</g>
- <path
- style="stroke-width:1px"
- d="M 69.435939,276.52168 71.5,274.5"
- id="path42595"
- inkscape:connector-curvature="0" />
<g
- id="g38699"
+ id="ICON_WORLD"
transform="translate(41.834175,191.41501)">
<rect
y="364.58499"
@@ -66990,7 +68896,7 @@
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
sodipodi:ry="8"
sodipodi:rx="8"
sodipodi:cy="118"
@@ -67010,9 +68916,9 @@
sodipodi:cy="118"
sodipodi:rx="8"
sodipodi:ry="8"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z" />
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z" />
<path
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
sodipodi:ry="8"
sodipodi:rx="8"
sodipodi:cy="118"
@@ -67046,7 +68952,7 @@
sodipodi:cy="118"
sodipodi:rx="8"
sodipodi:ry="8"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90" />
@@ -67062,12 +68968,12 @@
sodipodi:cy="118"
sodipodi:rx="8"
sodipodi:ry="8"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z" />
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z" />
</g>
</g>
<g
transform="translate(179.00003,444.99999)"
- id="g37955"
+ id="ICON_LOGIC"
style="display:inline">
<rect
y="90"
@@ -67168,7 +69074,7 @@
sodipodi:cy="325"
sodipodi:rx="1.5"
sodipodi:ry="1.5"
- d="m 287.5,325 c 0,0.82843 -0.67157,1.5 -1.5,1.5 -0.82843,0 -1.5,-0.67157 -1.5,-1.5 0,-0.82843 0.67157,-1.5 1.5,-1.5 0.82843,0 1.5,0.67157 1.5,1.5 z"
+ d="m 287.5,325 a 1.5,1.5 0 0 1 -1.5,1.5 1.5,1.5 0 0 1 -1.5,-1.5 1.5,1.5 0 0 1 1.5,-1.5 1.5,1.5 0 0 1 1.5,1.5 z"
transform="matrix(1.6666708,0,0,1.6666633,-190.66784,-215.66559)" />
<rect
y="328.49997"
@@ -67186,7 +69092,7 @@
y="328.49997" />
<path
transform="matrix(1.333351,0,0,1.333345,-95.338377,-107.33714)"
- d="m 287.5,325 c 0,0.82843 -0.67157,1.5 -1.5,1.5 -0.82843,0 -1.5,-0.67157 -1.5,-1.5 0,-0.82843 0.67157,-1.5 1.5,-1.5 0.82843,0 1.5,0.67157 1.5,1.5 z"
+ d="m 287.5,325 a 1.5,1.5 0 0 1 -1.5,1.5 1.5,1.5 0 0 1 -1.5,-1.5 1.5,1.5 0 0 1 1.5,-1.5 1.5,1.5 0 0 1 1.5,1.5 z"
sodipodi:ry="1.5"
sodipodi:rx="1.5"
sodipodi:cy="325"
@@ -67240,27 +69146,9 @@
inkscape:connector-curvature="0" />
</g>
</g>
- <rect
- style="opacity:0;fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- id="rect38023"
- width="16"
- height="16"
- x="233.39999"
- y="113.08"
- rx="0"
- ry="0" />
- <rect
- style="opacity:0;fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- id="rect38847"
- width="16"
- height="16"
- x="190"
- y="94.362419"
- rx="0"
- ry="0" />
<g
style="display:inline;enable-background:new"
- id="g43388-8"
+ id="ICON_RNA"
transform="translate(588,446)">
<rect
y="26"
@@ -67337,7 +69225,7 @@
<g
style="display:inline;enable-background:new"
transform="translate(273,441)"
- id="g40240">
+ id="ICON_GREASEPENCIL">
<path
id="path40242"
style="fill:#89a02c;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
@@ -67425,7 +69313,7 @@
</g>
<g
style="display:inline;enable-background:new"
- id="g40603-2"
+ id="ICON_RENDER_ANIMATION"
transform="translate(238,594)">
<rect
y="-122"
@@ -67575,7 +69463,7 @@
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
transform="translate(56,-67)"
- id="g42945"
+ id="ICON_PREFERENCES"
style="display:inline;enable-background:new">
<rect
y="602"
@@ -67665,89 +69553,87 @@
</g>
</g>
<g
- style="display:inline"
- id="g29389"
- transform="translate(-167,402.00001)">
- <rect
- style="opacity:0;fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- id="rect29391"
- width="16"
- height="16"
- x="382"
- y="217" />
+ id="ICON_DISCLOSURE_TRI_DOWN">
<g
- style="opacity:0.8;display:inline"
- transform="matrix(0.6184922,0,0,0.6183145,308.52384,72.984237)"
- inkscape:export-ydpi="90"
- inkscape:export-xdpi="90"
- inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
- id="g29393">
+ transform="translate(-167,402.00001)"
+ id="g29389"
+ style="display:inline">
+ <rect
+ y="217"
+ x="382"
+ height="16"
+ width="16"
+ id="rect29391"
+ style="opacity:0;fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
<g
- inkscape:export-ydpi="90"
+ id="g29393"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
inkscape:export-xdpi="90"
- inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
- transform="matrix(0.927848,0,0,0.916217,-28.19594,40.73172)"
- id="g29395"
- style="display:inline">
- <path
- transform="matrix(0.872933,0,0,0.883992,56.29135,118.6984)"
- sodipodi:type="arc"
- style="fill:url(#linearGradient29407);fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.99653149;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
- id="path29397"
- sodipodi:cx="132"
- sodipodi:cy="118"
- sodipodi:rx="8"
- sodipodi:ry="8"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ inkscape:export-ydpi="90"
+ transform="matrix(0.6184922,0,0,0.6183145,308.52384,72.984237)"
+ style="opacity:0.8;display:inline">
+ <g
+ style="display:inline"
+ id="g29395"
+ transform="matrix(0.927848,0,0,0.916217,-28.19594,40.73172)"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
inkscape:export-xdpi="90"
- inkscape:export-ydpi="90" />
- </g>
- <path
- sodipodi:nodetypes="cc"
- id="path29399"
- style="fill:none;stroke:url(#linearGradient29409);stroke-width:4.85120249;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1"
- d="m 134.19651,245.03757 -6.46038,0"
- inkscape:connector-curvature="0" />
- <g
- style="fill:none;stroke:url(#linearGradient29413);stroke-width:1.90771151;stroke-opacity:1;display:inline"
- id="g29401"
- transform="matrix(0.784039,0,0,0.779055,-3.508124,71.29625)"
- inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
- inkscape:export-xdpi="90"
- inkscape:export-ydpi="90">
+ inkscape:export-ydpi="90">
+ <path
+ inkscape:export-ydpi="90"
+ inkscape:export-xdpi="90"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
+ sodipodi:ry="8"
+ sodipodi:rx="8"
+ sodipodi:cy="118"
+ sodipodi:cx="132"
+ id="path29397"
+ style="fill:url(#linearGradient29407);fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.99653149;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ sodipodi:type="arc"
+ transform="matrix(0.872933,0,0,0.883992,56.29135,118.6984)" />
+ </g>
<path
+ inkscape:connector-curvature="0"
+ d="m 134.19651,245.03757 -6.46038,0"
+ style="fill:none;stroke:url(#linearGradient29409);stroke-width:4.85120249;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1"
+ id="path29399"
+ sodipodi:nodetypes="cc" />
+ <g
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
- sodipodi:ry="8"
- sodipodi:rx="8"
- sodipodi:cy="118"
- sodipodi:cx="132"
- id="path29403"
- style="fill:none;stroke:url(#linearGradient29411);stroke-width:2.48091555;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
- sodipodi:type="arc"
- transform="matrix(0.8313677,0,0,0.8366298,61.774434,124.29322)" />
+ transform="matrix(0.784039,0,0,0.779055,-3.508124,71.29625)"
+ id="g29401"
+ style="fill:none;stroke:url(#linearGradient29413);stroke-width:1.90771151;stroke-opacity:1;display:inline">
+ <path
+ transform="matrix(0.8313677,0,0,0.8366298,61.774434,124.29322)"
+ sodipodi:type="arc"
+ style="fill:none;stroke:url(#linearGradient29411);stroke-width:2.48091555;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ id="path29403"
+ sodipodi:cx="132"
+ sodipodi:cy="118"
+ sodipodi:rx="8"
+ sodipodi:ry="8"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ </g>
+ <path
+ inkscape:connector-curvature="0"
+ id="path29405"
+ style="fill:none;stroke:#000000;stroke-width:2.42560124;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 133.78064,245.05849 -5.65893,0"
+ sodipodi:nodetypes="cc"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
</g>
- <path
- inkscape:export-ydpi="90"
- inkscape:export-xdpi="90"
- inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
- sodipodi:nodetypes="cc"
- d="m 133.78064,245.05849 -5.65893,0"
- style="fill:none;stroke:#000000;stroke-width:2.42560124;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
- id="path29405"
- inkscape:connector-curvature="0" />
</g>
- </g>
- <g
- transform="translate(-167,402.00001)"
- id="g41246"
- style="display:inline">
<rect
- y="217"
- x="382"
+ y="619"
+ x="215"
height="16"
width="16"
id="rect41249"
@@ -67757,7 +69643,7 @@
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90"
- transform="matrix(0.6184922,0,0,0.6183145,308.52384,72.984237)"
+ transform="matrix(0.6184922,0,0,0.6183145,141.52384,474.98425)"
style="opacity:0.8;display:inline">
<g
style="display:inline"
@@ -67770,19 +69656,19 @@
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
sodipodi:ry="8"
sodipodi:rx="8"
sodipodi:cy="118"
sodipodi:cx="132"
id="path41255"
- style="fill:url(#linearGradient41266);fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.99653149;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ style="fill:url(#linearGradient18663);fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.99653149;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
sodipodi:type="arc"
transform="matrix(0.872933,0,0,0.883992,56.29135,118.6984)" />
</g>
<path
d="m 134.19651,245.03757 -6.46038,0"
- style="fill:none;stroke:url(#linearGradient41268);stroke-width:4.85120249;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1"
+ style="fill:none;stroke:url(#linearGradient18665);stroke-width:4.85120249;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1"
id="path41257"
sodipodi:nodetypes="cc"
inkscape:connector-curvature="0" />
@@ -67792,17 +69678,17 @@
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
transform="matrix(0.784039,0,0,0.779055,-3.508124,71.29625)"
id="g41260"
- style="fill:none;stroke:url(#linearGradient41272);stroke-width:1.90771151;stroke-opacity:1;display:inline">
+ style="fill:none;stroke:url(#linearGradient18669);stroke-width:1.90771151;stroke-opacity:1;display:inline">
<path
transform="matrix(0.8313677,0,0,0.8366298,61.774434,124.29322)"
sodipodi:type="arc"
- style="fill:none;stroke:url(#linearGradient41270);stroke-width:2.48091555;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ style="fill:none;stroke:url(#linearGradient18667);stroke-width:2.48091555;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
id="path41262"
sodipodi:cx="132"
sodipodi:cy="118"
sodipodi:rx="8"
sodipodi:ry="8"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90" />
@@ -67819,7 +69705,7 @@
</g>
</g>
<g
- id="g40887">
+ id="ICON_RENDER_STILL">
<g
id="g40668">
<rect
@@ -68062,34 +69948,8 @@
</g>
</g>
<g
- transform="translate(259,168)"
- mask="url(#mask38561)"
- id="g40090" />
- <rect
- inkscape:export-ydpi="90"
- inkscape:export-xdpi="90"
- inkscape:export-filename="C:\Documents and Settings\Pracownia\Moje dokumenty\Moje obrazy\BLENDER ICONS redesign\RELEASES\g22298.png"
- transform="scale(-1,1)"
- style="opacity:0;fill:#808080;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.80000001;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- id="rect40274"
- width="16"
- height="16"
- x="-252"
- y="514" />
- <rect
- y="514"
- x="-272"
- height="16"
- width="16"
- id="rect41293"
- style="opacity:0;fill:#808080;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.80000001;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- transform="scale(-1,1)"
- inkscape:export-filename="C:\Documents and Settings\Pracownia\Moje dokumenty\Moje obrazy\BLENDER ICONS redesign\RELEASES\g22298.png"
- inkscape:export-xdpi="90"
- inkscape:export-ydpi="90" />
- <g
transform="translate(1,0)"
- id="g36512">
+ id="ICON_RENDER_RESULT">
<rect
style="opacity:0.01000001;fill:#2affd5;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
id="rect36514"
@@ -68152,7 +70012,7 @@
sodipodi:cy="118"
sodipodi:rx="8"
sodipodi:ry="8"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90" />
@@ -68172,7 +70032,7 @@
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
sodipodi:ry="8"
sodipodi:rx="8"
sodipodi:cy="118"
@@ -68185,7 +70045,7 @@
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
sodipodi:ry="8"
sodipodi:rx="8"
sodipodi:cy="118"
@@ -68199,7 +70059,7 @@
id="g36537">
<path
transform="matrix(1.1428645,0,0,1.1428645,-416.36057,256.4986)"
- d="m 466.25,192.5 c 0,0.9665 -0.7835,1.75 -1.75,1.75 -0.9665,0 -1.75,-0.7835 -1.75,-1.75 0,-0.9665 0.7835,-1.75 1.75,-1.75 0.9665,0 1.75,0.7835 1.75,1.75 z"
+ d="m 466.25,192.5 a 1.75,1.75 0 0 1 -1.75,1.75 1.75,1.75 0 0 1 -1.75,-1.75 1.75,1.75 0 0 1 1.75,-1.75 1.75,1.75 0 0 1 1.75,1.75 z"
sodipodi:ry="1.75"
sodipodi:rx="1.75"
sodipodi:cy="192.5"
@@ -68215,7 +70075,7 @@
sodipodi:cy="192.5"
sodipodi:rx="1.75"
sodipodi:ry="1.75"
- d="m 466.25,192.5 c 0,0.9665 -0.7835,1.75 -1.75,1.75 -0.9665,0 -1.75,-0.7835 -1.75,-1.75 0,-0.9665 0.7835,-1.75 1.75,-1.75 0.9665,0 1.75,0.7835 1.75,1.75 z"
+ d="m 466.25,192.5 a 1.75,1.75 0 0 1 -1.75,1.75 1.75,1.75 0 0 1 -1.75,-1.75 1.75,1.75 0 0 1 1.75,-1.75 1.75,1.75 0 0 1 1.75,1.75 z"
transform="matrix(0.5714297,0,0,0.5714297,-150.92912,366.49979)" />
<rect
y="476"
@@ -68236,7 +70096,7 @@
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
sodipodi:ry="8"
sodipodi:rx="8"
sodipodi:cy="118"
@@ -68248,17 +70108,8 @@
</g>
</g>
<g
- transform="translate(-810.9,-131)"
- id="g40730"
- style="display:inline;enable-background:new">
- <g
- id="g40736"
- transform="translate(583.99999,91.500124)"
- style="display:inline;enable-background:new" />
- </g>
- <g
style="display:inline;enable-background:new"
- id="g39239"
+ id="ICON_FILE_BLANK"
transform="translate(-369,-131)">
<path
inkscape:export-ydpi="90"
@@ -68307,7 +70158,7 @@
</g>
<g
transform="translate(-705,268)"
- id="g36639"
+ id="ICON_FILE"
style="display:inline;enable-background:new">
<path
style="fill:url(#linearGradient36657);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;display:inline"
@@ -68355,7 +70206,7 @@
inkscape:connector-curvature="0" />
</g>
<g
- id="g37112"
+ id="ICON_GHOST_DISABLED"
transform="translate(-42,0)">
<g
transform="matrix(-1,0,0,1,887,548.02778)"
@@ -68459,7 +70310,7 @@
</g>
<g
transform="translate(87.000001,33.999969)"
- id="g37053"
+ id="ICON_RENDERLAYERS"
inkscape:export-filename="C:\Documents and Settings\Pracownia\Moje dokumenty\Moje obrazy\BLENDER ICONS redesign\ver 3\render layers 2.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90">
@@ -68516,7 +70367,7 @@
inkscape:connector-curvature="0" />
<path
transform="matrix(0.5714297,0,0,0.5714297,-362.92909,351.49978)"
- d="m 466.25,192.5 c 0,0.9665 -0.7835,1.75 -1.75,1.75 -0.9665,0 -1.75,-0.7835 -1.75,-1.75 0,-0.9665 0.7835,-1.75 1.75,-1.75 0.9665,0 1.75,0.7835 1.75,1.75 z"
+ d="m 466.25,192.5 a 1.75,1.75 0 0 1 -1.75,1.75 1.75,1.75 0 0 1 -1.75,-1.75 1.75,1.75 0 0 1 1.75,-1.75 1.75,1.75 0 0 1 1.75,1.75 z"
sodipodi:ry="1.75"
sodipodi:rx="1.75"
sodipodi:cy="192.5"
@@ -68571,7 +70422,7 @@
sodipodi:cy="118"
sodipodi:rx="8"
sodipodi:ry="8"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90" />
@@ -68593,7 +70444,7 @@
sodipodi:cy="118"
sodipodi:rx="8"
sodipodi:ry="8"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90" />
@@ -68601,7 +70452,7 @@
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
sodipodi:ry="8"
sodipodi:rx="8"
sodipodi:cy="118"
@@ -68614,7 +70465,7 @@
</g>
<g
style="display:inline;enable-background:new"
- id="g37514"
+ id="ICON_FILE_IMAGE"
transform="translate(-327.01257,-130.96121)">
<path
inkscape:export-ydpi="90"
@@ -68735,7 +70586,7 @@
</g>
<g
style="display:inline;enable-background:new"
- id="g37514-4"
+ id="ICON_IMAGE_DATA"
transform="translate(-726.01257,268.03879)">
<path
inkscape:export-ydpi="90"
@@ -68856,7 +70707,7 @@
</g>
<g
transform="translate(-167.99999,190.99999)"
- id="g71820">
+ id="ICON_TEXTURE">
<rect
y="365"
x="215"
@@ -68897,145 +70748,148 @@
inkscape:connector-curvature="0" />
</g>
</g>
- <rect
- y="493"
- x="488.00015"
- height="16"
- width="16"
- id="rect37119"
- style="opacity:0;fill:#666666;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.5;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
- <path
- sodipodi:nodetypes="ccccccc"
- id="path37123"
- d="m 490.00015,501 7,-3 6,2.5 0,3.74998 -6.99999,3.74999 -6.00001,-3.24999 0,-3.74998 z"
- style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#2a2512;stroke-width:1.79999995;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
- inkscape:connector-curvature="0" />
- <path
- id="path37125"
- d="m 490.00015,501 6,-2.5 6,2.5 0,0.5 -6,3 -6,-2.93442 0,-0.56558 z"
- style="fill:#999999;fill-opacity:1;fill-rule:evenodd;stroke:none"
- sodipodi:nodetypes="ccccccc"
- inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\4.png"
- inkscape:export-xdpi="90"
- inkscape:export-ydpi="90"
- inkscape:connector-curvature="0" />
- <path
- sodipodi:nodetypes="ccccc"
- id="path37127"
- d="m 497.00015,501.25 0,-3.24998 -6.5,2.74998 3.5,1.75 3,-1.25 z"
- style="fill:#1a1a1a;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.89207077px;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\4.png"
- inkscape:export-xdpi="90"
- inkscape:export-ydpi="90"
- inkscape:connector-curvature="0" />
- <path
- inkscape:export-ydpi="90"
- inkscape:export-xdpi="90"
- inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\4.png"
- style="fill:#666666;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.06666696px;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- d="m 497.00015,501.24998 0,-3.24998 5.5,2.24998 -3.5,1.75 -2,-0.75 z"
- id="path37129"
- sodipodi:nodetypes="ccccc"
- inkscape:connector-curvature="0" />
- <path
- sodipodi:nodetypes="ccc"
- id="path37131"
- d="m 502.50015,500.5 -5.5,-2.25 -6.5,2.75"
- style="fill:none;stroke:url(#linearGradient37201);stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
- inkscape:connector-curvature="0" />
<g
- style="display:inline;enable-background:new"
- id="g39239-1"
- transform="translate(-260.99985,289)">
+ id="ICON_PACKAGE">
+ <rect
+ style="opacity:0;fill:#666666;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.5;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect37119"
+ width="16"
+ height="16"
+ x="488.00015"
+ y="493" />
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#2a2512;stroke-width:1.79999995;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 490.00015,501 7,-3 6,2.5 0,3.74998 -6.99999,3.74999 -6.00001,-3.24999 0,-3.74998 z"
+ id="path37123"
+ sodipodi:nodetypes="ccccccc" />
<path
+ inkscape:connector-curvature="0"
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
- inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png"
- sodipodi:nodetypes="cccccc"
- id="path39241-6"
- d="m 756.16666,204.50001 6.33334,-1e-5 0,11.24999 -9,1e-5 -10e-6,-8.24999 2.66667,-3 z"
- style="fill:url(#linearGradient37317);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;display:inline"
- inkscape:connector-curvature="0" />
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\4.png"
+ sodipodi:nodetypes="ccccccc"
+ style="fill:#999999;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ d="m 490.00015,501 6,-2.5 6,2.5 0,0.5 -6,3 -6,-2.93442 0,-0.56558 z"
+ id="path37125" />
<path
- style="opacity:0.3;fill:url(#radialGradient37319);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- d="M 756.16666,204.50001 762.5,204.75 l 0,10.75 -9,0 -10e-6,-7.99999 2.66667,-3 z"
- id="path39243-8"
- sodipodi:nodetypes="cccccc"
- inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png"
- inkscape:export-xdpi="90"
+ inkscape:connector-curvature="0"
inkscape:export-ydpi="90"
- inkscape:connector-curvature="0" />
+ inkscape:export-xdpi="90"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\4.png"
+ style="fill:#1a1a1a;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.89207077px;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 497.00015,501.25 0,-3.24998 -6.5,2.74998 3.5,1.75 3,-1.25 z"
+ id="path37127"
+ sodipodi:nodetypes="ccccc" />
<path
- sodipodi:nodetypes="cccc"
- d="m 754.5,209 0,5.5 m 3.5,-9 3.5,0"
- style="fill:none;stroke:url(#linearGradient37321);stroke-width:1px;stroke-linecap:square;stroke-linejoin:miter;stroke-opacity:1;display:inline"
- id="path39245-5"
- inkscape:connector-curvature="0" />
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccc"
+ id="path37129"
+ d="m 497.00015,501.24998 0,-3.24998 5.5,2.24998 -3.5,1.75 -2,-0.75 z"
+ style="fill:#666666;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.06666696px;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\4.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
<path
- style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;display:inline"
- d="m 753,208 4,0 0,-4 -4,4 z"
- id="path39247-7"
- sodipodi:nodetypes="cccc"
- inkscape:connector-curvature="0" />
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:url(#linearGradient37201);stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ d="m 502.50015,500.5 -5.5,-2.25 -6.5,2.75"
+ id="path37131"
+ sodipodi:nodetypes="ccc" />
+ <g
+ transform="translate(-260.99985,289)"
+ id="g39239-1"
+ style="display:inline;enable-background:new">
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:url(#linearGradient37317);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;display:inline"
+ d="m 756.16666,204.50001 6.33334,-1e-5 0,11.24999 -9,1e-5 -10e-6,-8.24999 2.66667,-3 z"
+ id="path39241-6"
+ sodipodi:nodetypes="cccccc"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <path
+ inkscape:connector-curvature="0"
+ inkscape:export-ydpi="90"
+ inkscape:export-xdpi="90"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png"
+ sodipodi:nodetypes="cccccc"
+ id="path39243-8"
+ d="M 756.16666,204.50001 762.5,204.75 l 0,10.75 -9,0 -10e-6,-7.99999 2.66667,-3 z"
+ style="opacity:0.3;fill:url(#radialGradient37319);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path39245-5"
+ style="fill:none;stroke:url(#linearGradient37321);stroke-width:1px;stroke-linecap:square;stroke-linejoin:miter;stroke-opacity:1;display:inline"
+ d="m 754.5,209 0,5.5 m 3.5,-9 3.5,0"
+ sodipodi:nodetypes="cccc" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cccc"
+ id="path39247-7"
+ d="m 753,208 4,0 0,-4 -4,4 z"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;display:inline" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cccccc"
+ id="path39249-6"
+ style="fill:none;stroke:#000000;stroke-width:0.80000001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 753.5,207.00001 0,8.49999 9,0 0,-11 -6.5,1e-5 -2.5,2.5 z"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:url(#linearGradient37323);stroke-width:1px;stroke-linecap:square;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 757.5,206.5 0,2 -2,0"
+ id="path39251-1" />
+ </g>
+ <path
+ inkscape:connector-curvature="0"
+ style="opacity:0.7;fill:url(#linearGradient37338);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;display:inline"
+ d="m 493.00015,494 7.99985,0 0,11 -7.99981,0 -4e-5,-11 0,0 0,0 0,0 z"
+ id="path37141"
+ sodipodi:nodetypes="ccccc" />
<path
+ inkscape:connector-curvature="0"
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
- inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png"
- d="m 753.5,207.00001 0,8.49999 9,0 0,-11 -6.5,1e-5 -2.5,2.5 z"
- style="fill:none;stroke:#000000;stroke-width:0.80000001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
- id="path39249-6"
- sodipodi:nodetypes="cccccc"
- inkscape:connector-curvature="0" />
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\4.png"
+ id="path37143"
+ d="m 490.00016,504.74998 -10e-6,-3.24998 6,3 0.01,3.49883 -6.00995,-3.24885 -4e-5,0 z"
+ style="fill:#c6b77c;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.06666696px;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ sodipodi:nodetypes="ccccc" />
<path
- id="path39251-1"
- d="m 757.5,206.5 0,2 -2,0"
- style="fill:none;stroke:url(#linearGradient37323);stroke-width:1px;stroke-linecap:square;stroke-linejoin:miter;stroke-opacity:1"
- inkscape:connector-curvature="0" />
+ inkscape:connector-curvature="0"
+ inkscape:export-ydpi="90"
+ inkscape:export-xdpi="90"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\4.png"
+ style="fill:#595235;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.06666696px;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 503.00015,504.25 0,-3.24998 -7,3.49998 c 0,2.58362 0,2.93288 0,3.49998 l 7,-3.74998 z"
+ id="path37145"
+ sodipodi:nodetypes="ccccc" />
+ <path
+ inkscape:connector-curvature="0"
+ style="opacity:0.96000001;fill:none;stroke:url(#linearGradient37191);stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 490.50015,501.5 0,2.99998 5.5,3 6.5,-3.49998 0,-2.99998"
+ id="path37147"
+ sodipodi:nodetypes="ccccc" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccc"
+ id="path37149"
+ d="m 490.50015,501.5 5.5,3 6.5,-3.5"
+ style="fill:none;stroke:url(#linearGradient37188);stroke-width:1.14999998;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+ <path
+ inkscape:connector-curvature="0"
+ style="opacity:0.25;fill:none;stroke:#000000;stroke-width:1.10000002;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 491.5,500.75 4.5,2.5 5.5,-3"
+ id="path38348"
+ sodipodi:nodetypes="ccc" />
</g>
- <path
- sodipodi:nodetypes="ccccc"
- id="path37141"
- d="m 493.00015,494 7.99985,0 0,11 -7.99981,0 -4e-5,-11 0,0 0,0 0,0 z"
- style="opacity:0.7;fill:url(#linearGradient37338);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;display:inline"
- inkscape:connector-curvature="0" />
- <path
- sodipodi:nodetypes="ccccc"
- style="fill:#c6b77c;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.06666696px;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- d="m 490.00016,504.74998 -10e-6,-3.24998 6,3 0.01,3.49883 -6.00995,-3.24885 -4e-5,0 z"
- id="path37143"
- inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\4.png"
- inkscape:export-xdpi="90"
- inkscape:export-ydpi="90"
- inkscape:connector-curvature="0" />
- <path
- sodipodi:nodetypes="ccccc"
- id="path37145"
- d="m 503.00015,504.25 0,-3.24998 -7,3.49998 c 0,2.58362 0,2.93288 0,3.49998 l 7,-3.74998 z"
- style="fill:#595235;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.06666696px;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\4.png"
- inkscape:export-xdpi="90"
- inkscape:export-ydpi="90"
- inkscape:connector-curvature="0" />
- <path
- sodipodi:nodetypes="ccccc"
- id="path37147"
- d="m 490.50015,501.5 0,2.99998 5.5,3 6.5,-3.49998 0,-2.99998"
- style="opacity:0.96000001;fill:none;stroke:url(#linearGradient37191);stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
- inkscape:connector-curvature="0" />
- <path
- style="fill:none;stroke:url(#linearGradient37188);stroke-width:1.14999998;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
- d="m 490.50015,501.5 5.5,3 6.5,-3.5"
- id="path37149"
- sodipodi:nodetypes="ccc"
- inkscape:connector-curvature="0" />
- <path
- sodipodi:nodetypes="ccc"
- id="path38348"
- d="m 491.5,500.75 4.5,2.5 5.5,-3"
- style="opacity:0.25;fill:none;stroke:#000000;stroke-width:1.10000002;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
- inkscape:connector-curvature="0" />
<g
- id="g38317"
+ id="ICON_IMAGE_COL"
transform="translate(131,-30)">
<g
transform="translate(-45.97248,412)"
@@ -69144,7 +70998,7 @@
id="g38358" />
</g>
<g
- id="g38738"
+ id="ICON_RNA_ADD"
transform="translate(41.000016,-2e-5)">
<rect
y="472"
@@ -69267,7 +71121,7 @@
</g>
</g>
<g
- id="g28606">
+ id="ICON_SEQUENCE">
<rect
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
@@ -69382,332 +71236,335 @@
style="opacity:0.4;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.9999994px;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
</g>
<g
- style="display:inline;enable-background:new"
- id="g37741"
- transform="translate(197.70204,-38.325069)">
+ id="ICON_STICKY_UVS_VERT">
<g
- id="g37905"
- transform="translate(0.999999,1.000006)">
- <g
- id="g37699"
- transform="translate(-40.718137,21.311275)"
- style="opacity:0.6;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate">
- <rect
- y="181.01379"
- x="166.0161"
- height="1"
- width="1"
- id="rect37701"
- style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
- <rect
- style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- id="rect37703"
- width="0.99999899"
- height="1"
- x="170.0161"
- y="177.01379" />
- <rect
- y="177.01379"
- x="168.0161"
- height="1"
- width="1"
- id="rect37705"
- style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
- <rect
- style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- id="rect37707"
- width="1"
- height="1"
- x="166.0161"
- y="177.01379" />
- <rect
- y="179.01379"
- x="166.0161"
- height="1"
- width="1"
- id="rect37709"
- style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
- <rect
- y="177.01379"
- x="174.0161"
- height="1"
- width="0.99999899"
- id="rect37869"
- style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
- <rect
- style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- id="rect37871"
- width="1"
- height="1"
- x="172.0161"
- y="177.01379" />
- <rect
- style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- id="rect37873"
- width="1"
- height="1"
- x="166.0161"
- y="185.01379" />
- <rect
- style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- id="rect37875"
- width="1"
- height="1"
- x="166.0161"
- y="183.01379" />
- </g>
- <g
- transform="translate(-40.702034,21.325063)"
- id="g37711"
- style="fill:#000000">
- <rect
- style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
- id="rect37713"
- width="1"
- height="1"
- x="166.00002"
- y="178.00002" />
- <rect
- y="180.00002"
- x="166.00002"
- height="1"
- width="1"
- id="rect37715"
- style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" />
- <rect
- style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
- id="rect37717"
- width="1"
- height="1"
- x="167.00002"
- y="177.00002" />
- <rect
- y="177.00002"
- x="169.00002"
- height="1"
- width="1"
- id="rect37719"
- style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" />
- <rect
- style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
- id="rect37725"
- width="1"
- height="1"
- x="171.00002"
- y="177.00002" />
- <rect
- y="182.00002"
- x="166.00002"
- height="1"
- width="1"
- id="rect37727"
- style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" />
- <rect
- style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
- id="rect37865"
- width="1"
- height="1"
- x="173"
- y="177.00002" />
- <rect
- y="177.00002"
- x="175"
- height="1"
- width="1"
- id="rect37867"
- style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" />
- <rect
- style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
- id="rect37877"
- width="1"
- height="1"
- x="166"
- y="184" />
- <rect
- style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
- id="rect37879"
- width="1"
- height="1"
- x="166"
- y="186" />
- </g>
- </g>
- <path
- id="path37737"
- d="m 127.79796,207.82507 4e-5,-7.01372 6.99956,0.009 4e-4,0.0507 -4e-4,6.95427 -6.9996,0 0,-2.5e-4 z"
- style="opacity:0.1;fill:none;stroke:#000000;stroke-width:1.00000048px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1;display:inline"
- sodipodi:nodetypes="ccc"
- inkscape:connector-curvature="0" />
- <g
- id="g37928"
- transform="matrix(-1,0,0,-1,260.59592,405.65013)">
+ transform="translate(197.70204,-38.325069)"
+ id="g37741"
+ style="display:inline;enable-background:new">
<g
- transform="translate(-39.718138,21.311267)"
- id="g37930"
- style="opacity:0.6;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate">
- <rect
- style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- id="rect37932"
- width="1"
- height="1"
- x="166.0161"
- y="181.01379" />
- <rect
- y="177.01379"
- x="170.0161"
- height="1"
- width="0.99999899"
- id="rect37934"
- style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
- <rect
- style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- id="rect37936"
- width="1"
- height="1"
- x="168.0161"
- y="177.01379" />
- <rect
- y="177.01379"
- x="166.0161"
- height="1"
- width="1"
- id="rect37938"
- style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
- <rect
- style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- id="rect37941"
- width="1"
- height="1"
- x="166.0161"
- y="179.01379" />
- <rect
- style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- id="rect37943"
- width="0.99999899"
- height="1"
- x="174.0161"
- y="177.01379" />
- <rect
- y="177.01379"
- x="172.0161"
- height="1"
- width="1"
- id="rect37945"
- style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
- <rect
- y="185.01379"
- x="166.0161"
- height="1"
- width="1"
- id="rect37947"
- style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
- <rect
- y="183.01379"
- x="166.0161"
- height="1"
- width="1"
- id="rect37949"
- style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ transform="translate(0.999999,1.000006)"
+ id="g37905">
+ <g
+ style="opacity:0.6;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ transform="translate(-40.718137,21.311275)"
+ id="g37699">
+ <rect
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect37701"
+ width="1"
+ height="1"
+ x="166.0161"
+ y="181.01379" />
+ <rect
+ y="177.01379"
+ x="170.0161"
+ height="1"
+ width="0.99999899"
+ id="rect37703"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <rect
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect37705"
+ width="1"
+ height="1"
+ x="168.0161"
+ y="177.01379" />
+ <rect
+ y="177.01379"
+ x="166.0161"
+ height="1"
+ width="1"
+ id="rect37707"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <rect
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect37709"
+ width="1"
+ height="1"
+ x="166.0161"
+ y="179.01379" />
+ <rect
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect37869"
+ width="0.99999899"
+ height="1"
+ x="174.0161"
+ y="177.01379" />
+ <rect
+ y="177.01379"
+ x="172.0161"
+ height="1"
+ width="1"
+ id="rect37871"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <rect
+ y="185.01379"
+ x="166.0161"
+ height="1"
+ width="1"
+ id="rect37873"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <rect
+ y="183.01379"
+ x="166.0161"
+ height="1"
+ width="1"
+ id="rect37875"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ </g>
+ <g
+ style="fill:#000000"
+ id="g37711"
+ transform="translate(-40.702034,21.325063)">
+ <rect
+ y="178.00002"
+ x="166.00002"
+ height="1"
+ width="1"
+ id="rect37713"
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" />
+ <rect
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ id="rect37715"
+ width="1"
+ height="1"
+ x="166.00002"
+ y="180.00002" />
+ <rect
+ y="177.00002"
+ x="167.00002"
+ height="1"
+ width="1"
+ id="rect37717"
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" />
+ <rect
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ id="rect37719"
+ width="1"
+ height="1"
+ x="169.00002"
+ y="177.00002" />
+ <rect
+ y="177.00002"
+ x="171.00002"
+ height="1"
+ width="1"
+ id="rect37725"
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" />
+ <rect
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ id="rect37727"
+ width="1"
+ height="1"
+ x="166.00002"
+ y="182.00002" />
+ <rect
+ y="177.00002"
+ x="173"
+ height="1"
+ width="1"
+ id="rect37865"
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" />
+ <rect
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ id="rect37867"
+ width="1"
+ height="1"
+ x="175"
+ y="177.00002" />
+ <rect
+ y="184"
+ x="166"
+ height="1"
+ width="1"
+ id="rect37877"
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" />
+ <rect
+ y="186"
+ x="166"
+ height="1"
+ width="1"
+ id="rect37879"
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" />
+ </g>
</g>
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccc"
+ style="opacity:0.1;fill:none;stroke:#000000;stroke-width:1.00000048px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1;display:inline"
+ d="m 127.79796,207.82507 4e-5,-7.01372 6.99956,0.009 4e-4,0.0507 -4e-4,6.95427 -6.9996,0 0,-2.5e-4 z"
+ id="path37737" />
<g
- style="fill:#000000"
- id="g37951"
- transform="translate(-39.702035,21.325055)">
- <rect
- y="178.00002"
- x="166.00002"
- height="1"
- width="1"
- id="rect37953"
- style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" />
- <rect
- style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
- id="rect37955"
- width="1"
- height="1"
- x="166.00002"
- y="180.00002" />
- <rect
- y="177.00002"
- x="167.00002"
- height="1"
- width="1"
- id="rect37958"
- style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" />
- <rect
- style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
- id="rect37960"
- width="1"
- height="1"
- x="169.00002"
- y="177.00002" />
- <rect
- y="177.00002"
- x="171.00002"
- height="1"
- width="1"
- id="rect37962"
- style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" />
- <rect
- style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
- id="rect37964"
- width="1"
- height="1"
- x="166.00002"
- y="182.00002" />
- <rect
- y="177.00002"
- x="173"
- height="1"
- width="1"
- id="rect37966"
- style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" />
- <rect
- style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
- id="rect37968"
- width="1"
- height="1"
- x="175"
- y="177.00002" />
- <rect
- y="184"
- x="166"
- height="1"
- width="1"
- id="rect37970"
- style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" />
- <rect
- y="186"
- x="166"
- height="1"
- width="1"
- id="rect37972"
- style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" />
+ transform="matrix(-1,0,0,-1,260.59592,405.65013)"
+ id="g37928">
+ <g
+ style="opacity:0.6;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="g37930"
+ transform="translate(-39.718138,21.311267)">
+ <rect
+ y="181.01379"
+ x="166.0161"
+ height="1"
+ width="1"
+ id="rect37932"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <rect
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect37934"
+ width="0.99999899"
+ height="1"
+ x="170.0161"
+ y="177.01379" />
+ <rect
+ y="177.01379"
+ x="168.0161"
+ height="1"
+ width="1"
+ id="rect37936"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <rect
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect37938"
+ width="1"
+ height="1"
+ x="166.0161"
+ y="177.01379" />
+ <rect
+ y="179.01379"
+ x="166.0161"
+ height="1"
+ width="1"
+ id="rect37941"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <rect
+ y="177.01379"
+ x="174.0161"
+ height="1"
+ width="0.99999899"
+ id="rect37943"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <rect
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect37945"
+ width="1"
+ height="1"
+ x="172.0161"
+ y="177.01379" />
+ <rect
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect37947"
+ width="1"
+ height="1"
+ x="166.0161"
+ y="185.01379" />
+ <rect
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect37949"
+ width="1"
+ height="1"
+ x="166.0161"
+ y="183.01379" />
+ </g>
+ <g
+ transform="translate(-39.702035,21.325055)"
+ id="g37951"
+ style="fill:#000000">
+ <rect
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ id="rect37953"
+ width="1"
+ height="1"
+ x="166.00002"
+ y="178.00002" />
+ <rect
+ y="180.00002"
+ x="166.00002"
+ height="1"
+ width="1"
+ id="rect37955"
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" />
+ <rect
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ id="rect37958"
+ width="1"
+ height="1"
+ x="167.00002"
+ y="177.00002" />
+ <rect
+ y="177.00002"
+ x="169.00002"
+ height="1"
+ width="1"
+ id="rect37960"
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" />
+ <rect
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ id="rect37962"
+ width="1"
+ height="1"
+ x="171.00002"
+ y="177.00002" />
+ <rect
+ y="182.00002"
+ x="166.00002"
+ height="1"
+ width="1"
+ id="rect37964"
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" />
+ <rect
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ id="rect37966"
+ width="1"
+ height="1"
+ x="173"
+ y="177.00002" />
+ <rect
+ y="177.00002"
+ x="175"
+ height="1"
+ width="1"
+ id="rect37968"
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" />
+ <rect
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ id="rect37970"
+ width="1"
+ height="1"
+ x="166"
+ y="184" />
+ <rect
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ id="rect37972"
+ width="1"
+ height="1"
+ x="166"
+ y="186" />
+ </g>
</g>
</g>
+ <rect
+ rx="0"
+ ry="0"
+ y="-161.5"
+ x="331.50012"
+ height="3"
+ width="2.9998772"
+ id="rect37338"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:7.40000265;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ transform="scale(1,-1)" />
+ <rect
+ transform="scale(-1,1)"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:7.40000265;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect37368"
+ width="2.9998772"
+ height="3"
+ x="-324.49988"
+ y="168.5"
+ ry="0"
+ rx="0" />
</g>
- <rect
- transform="scale(1,-1)"
- style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:7.40000265;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- id="rect37338"
- width="2.9998772"
- height="3"
- x="331.50012"
- y="-161.5"
- ry="0"
- rx="0" />
- <rect
- rx="0"
- ry="0"
- y="168.5"
- x="-324.49988"
- height="3"
- width="2.9998772"
- id="rect37368"
- style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:7.40000265;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- transform="scale(-1,1)" />
- <g
- id="g38402"
+ <g
+ id="ICON_STICKY_UVS_LOC"
transform="translate(-21,0)">
<g
style="display:inline;enable-background:new"
@@ -70113,7 +71970,7 @@
rx="0" />
</g>
<g
- id="g38397"
+ id="ICON_STICKY_UVS_DISABLE"
transform="translate(20.999878,0)">
<rect
rx="0"
@@ -70144,7 +72001,7 @@
style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:7.40000265;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
</g>
<g
- id="g38011"
+ id="ICON_UV_SYNC_SELECT"
transform="translate(436,-380)">
<rect
y="516"
@@ -70392,7 +72249,7 @@
</g>
</g>
<g
- id="g37508"
+ id="ICON_SHAPEKEY_DATA"
transform="translate(525,27.999998)">
<g
style="opacity:0.7"
@@ -70511,7 +72368,7 @@
</g>
<path
transform="matrix(1.99999,0,0,1.99999,571.48293,-823.49525)"
- d="m -92,477.5 c 0,0.27614 -0.223858,0.5 -0.5,0.5 -0.276142,0 -0.5,-0.22386 -0.5,-0.5 0,-0.27614 0.223858,-0.5 0.5,-0.5 0.276142,0 0.5,0.22386 0.5,0.5 z"
+ d="m -92,477.5 a 0.5,0.5 0 0 1 -0.5,0.5 0.5,0.5 0 0 1 -0.5,-0.5 0.5,0.5 0 0 1 0.5,-0.5 0.5,0.5 0 0 1 0.5,0.5 z"
sodipodi:ry="0.5"
sodipodi:rx="0.5"
sodipodi:cy="477.5"
@@ -70523,7 +72380,7 @@
</g>
</g>
<g
- id="g37565">
+ id="ICON_ROTATE">
<g
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
@@ -70540,7 +72397,7 @@
sodipodi:cy="118"
sodipodi:rx="8"
sodipodi:ry="8"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90" />
@@ -70549,7 +72406,7 @@
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
sodipodi:ry="8"
sodipodi:rx="8"
sodipodi:cy="118"
@@ -70615,58 +72472,160 @@
inkscape:connector-curvature="0" />
</g>
<g
- transform="translate(41.928411,-437)"
- id="g37575">
- <rect
- y="617"
- x="173"
- height="16"
- width="16"
- id="rect37577"
- style="opacity:0;fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ id="ICON_ALIGN">
<g
- transform="translate(-290,397)"
- id="g37579"
- style="display:inline">
+ transform="translate(0,2)"
+ id="g21663">
+ <rect
+ y="176"
+ x="215"
+ height="16"
+ width="16"
+ id="rect21661"
+ style="opacity:0;fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
<g
- id="g37582">
+ style="display:inline"
+ id="g21392"
+ transform="translate(-87.98837,-19.85)">
<g
- transform="translate(20.029029,0)"
- style="opacity:0.85"
- id="g37584">
- <path
- d="m 447.72097,225.25 -3.25,3.25 3.25,3.25 m 6.5,-6.5 3.25,3.25 -3.25,3.25"
- style="fill:none;stroke:#000000;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:12.66808051;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- id="path37586"
- sodipodi:nodetypes="cccccc"
- inkscape:connector-curvature="0" />
- <path
- id="path37588"
- d="m 444.54256,228.5 11.66489,0 0,0"
- style="fill:none;stroke:#000000;stroke-width:2.4000001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:12.66808051;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- inkscape:connector-curvature="0" />
+ transform="translate(-62.011627,236.84995)"
+ style="opacity:0.05"
+ id="g11189">
+ <rect
+ rx="1.375"
+ ry="1.375"
+ y="-39.5"
+ x="366.5"
+ height="3"
+ width="2.9998775"
+ id="rect11191"
+ style="fill:none;stroke:#447cce;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:7.40000265;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <rect
+ rx="1.375"
+ style="fill:none;stroke:#447cce;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:7.40000265;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect11193"
+ width="2.9998775"
+ height="3"
+ x="371.5"
+ y="-39.5"
+ ry="1.375" />
+ <rect
+ rx="1.375"
+ ry="1.375"
+ y="-39.5"
+ x="376.5"
+ height="3"
+ width="2.9998775"
+ id="rect11195"
+ style="fill:none;stroke:#447cce;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:7.40000265;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
</g>
+ <rect
+ rx="1.375"
+ ry="1.375"
+ y="197.34995"
+ x="304.48837"
+ height="3"
+ width="2.9998775"
+ id="rect11197"
+ style="fill:none;stroke:#22467e;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:7.40000265;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:#c3dbff;fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline"
+ d="m 304.98827,197.84994 c 0.6667,0 1.3334,1e-5 2.0001,1e-5 0,0.66668 0,1.33337 0,2.00005 -0.6667,0 -1.3334,-1e-5 -2.0001,-1e-5 0,-0.66668 0,-1.33337 0,-2.00005 z"
+ id="path11199"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <rect
+ rx="1.375"
+ style="fill:none;stroke:#22467e;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:7.40000265;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect11201"
+ width="2.9998775"
+ height="3"
+ x="309.48837"
+ y="197.34995"
+ ry="1.375" />
+ <path
+ inkscape:connector-curvature="0"
+ inkscape:export-ydpi="90"
+ inkscape:export-xdpi="90"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
+ id="path11203"
+ d="m 309.98827,197.84994 c 0.6667,0 1.3334,1e-5 2.0001,1e-5 0,0.66668 0,1.33337 0,2.00005 -0.6667,0 -1.3334,-1e-5 -2.0001,-1e-5 0,-0.66668 0,-1.33337 0,-2.00005 z"
+ style="fill:#c3dbff;fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline" />
+ <rect
+ rx="1.375"
+ ry="1.375"
+ y="197.34995"
+ x="314.48837"
+ height="3"
+ width="2.9998775"
+ id="rect11205"
+ style="fill:none;stroke:#22467e;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:7.40000265;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:#c3dbff;fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline"
+ d="m 314.98827,197.84994 c 0.6667,0 1.3334,1e-5 2.0001,1e-5 0,0.66668 0,1.33337 0,2.00005 -0.6667,0 -1.3334,-1e-5 -2.0001,-1e-5 0,-0.66668 0,-1.33337 0,-2.00005 z"
+ id="path11207"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ </g>
+ </g>
+ <g
+ id="g37575"
+ transform="translate(41.928411,-437)">
+ <rect
+ style="opacity:0;fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect37577"
+ width="16"
+ height="16"
+ x="173"
+ y="617" />
+ <g
+ style="display:inline"
+ id="g37579"
+ transform="translate(-290,397)">
<g
- transform="translate(20.029029,0)"
- id="g37591">
- <path
- sodipodi:nodetypes="cc"
- style="fill:none;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
- d="m 444.47097,228.5 13,0"
- id="path37593"
- inkscape:connector-curvature="0" />
- <path
- sodipodi:nodetypes="cccccc"
- id="path37606"
- style="fill:none;stroke:#ffffff;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
- d="m 447.72097,225.25 -3.25,3.25 3.25,3.25 m 6.5,-6.5 3.25,3.25 -3.25,3.25"
- inkscape:connector-curvature="0" />
+ id="g37582">
+ <g
+ id="g37584"
+ style="opacity:0.85"
+ transform="translate(20.029029,0)">
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cccccc"
+ id="path37586"
+ style="fill:none;stroke:#000000;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:12.66808051;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 447.72097,225.25 -3.25,3.25 3.25,3.25 m 6.5,-6.5 3.25,3.25 -3.25,3.25" />
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#000000;stroke-width:2.4000001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:12.66808051;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 444.54256,228.5 11.66489,0 0,0"
+ id="path37588" />
+ </g>
+ <g
+ id="g37591"
+ transform="translate(20.029029,0)">
+ <path
+ inkscape:connector-curvature="0"
+ id="path37593"
+ d="m 444.47097,228.5 13,0"
+ style="fill:none;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+ sodipodi:nodetypes="cc" />
+ <path
+ inkscape:connector-curvature="0"
+ d="m 447.72097,225.25 -3.25,3.25 3.25,3.25 m 6.5,-6.5 3.25,3.25 -3.25,3.25"
+ style="fill:none;stroke:#ffffff;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ id="path37606"
+ sodipodi:nodetypes="cccccc" />
+ </g>
</g>
</g>
</g>
</g>
<g
- id="g37577"
+ id="ICON_BBOX"
transform="translate(-105,-63)">
<g
style="opacity:0.8;display:inline;enable-background:new"
@@ -70679,7 +72638,7 @@
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
sodipodi:ry="8"
sodipodi:rx="8"
sodipodi:cy="118"
@@ -70696,14 +72655,14 @@
sodipodi:cy="118"
sodipodi:rx="8"
sodipodi:ry="8"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90"
transform="matrix(-0.683022,-0.07745026,0.0778507,-0.683064,209.4726,314.325)" />
<path
transform="matrix(0.5705005,0,0,0.5705012,53.193935,156.18087)"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
sodipodi:ry="8"
sodipodi:rx="8"
sodipodi:cy="118"
@@ -70737,7 +72696,7 @@
</g>
<g
style="display:inline;enable-background:new"
- id="g14409"
+ id="ICON_SOLID"
transform="translate(4.7892764e-7,23)">
<rect
style="opacity:0;fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
@@ -70757,7 +72716,7 @@
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
sodipodi:ry="8"
sodipodi:rx="8"
sodipodi:cy="118"
@@ -70774,7 +72733,7 @@
sodipodi:cy="118"
sodipodi:rx="8"
sodipodi:ry="8"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90"
@@ -70783,7 +72742,7 @@
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
sodipodi:ry="8"
sodipodi:rx="8"
sodipodi:cy="118"
@@ -70796,7 +72755,7 @@
</g>
<g
style="display:inline;enable-background:new"
- id="g14396"
+ id="ICON_SMOOTH"
transform="translate(4.7892764e-7,23)">
<rect
y="92"
@@ -70816,7 +72775,7 @@
transform="matrix(0.928617,0,0,0.931035,10.2435,15.47372)"
id="g15313">
<path
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
sodipodi:ry="8"
sodipodi:rx="8"
sodipodi:cy="118"
@@ -70833,7 +72792,7 @@
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
sodipodi:ry="8"
sodipodi:rx="8"
sodipodi:cy="118"
@@ -70849,7 +72808,7 @@
sodipodi:cy="118"
sodipodi:rx="8"
sodipodi:ry="8"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90"
@@ -70858,7 +72817,7 @@
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
sodipodi:ry="8"
sodipodi:rx="8"
sodipodi:cy="118"
@@ -70884,7 +72843,7 @@
</g>
<g
style="display:inline;enable-background:new"
- id="g37996"
+ id="ICON_POTATO"
transform="translate(113.00001,1)">
<rect
style="opacity:0;fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
@@ -70894,7 +72853,7 @@
x="-24.00001"
y="114" />
<path
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
sodipodi:ry="8"
sodipodi:rx="8"
sodipodi:cy="118"
@@ -70923,12 +72882,12 @@
sodipodi:cy="118"
sodipodi:rx="8"
sodipodi:ry="8"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z" />
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z" />
<path
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
sodipodi:ry="8"
sodipodi:rx="8"
sodipodi:cy="118"
@@ -70946,7 +72905,7 @@
</g>
<g
transform="translate(4.7892764e-7,23)"
- id="g38272"
+ id="ICON_WIRE"
style="display:inline;enable-background:new">
<g
id="g37676">
@@ -70962,7 +72921,7 @@
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
sodipodi:ry="8"
sodipodi:rx="8"
sodipodi:cy="118"
@@ -70981,7 +72940,7 @@
sodipodi:cy="118"
sodipodi:rx="8"
sodipodi:ry="8"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
transform="matrix(0.8125001,0,0,0.8125002,-73.250026,4.1249738)" />
<path
inkscape:export-ydpi="90"
@@ -70994,7 +72953,7 @@
sodipodi:cy="118"
sodipodi:rx="8"
sodipodi:ry="10.07671"
- d="m 140,118 c 0,5.56521 -3.58172,10.07671 -8,10.07671 -4.37076,0 -7.9325,-4.4185 -7.99907,-9.92322"
+ d="m 140,118 a 8,10.07671 0 0 1 -7.93907,10.07642 8,10.07671 0 0 1 -8.06,-9.92293"
sodipodi:start="0"
sodipodi:end="3.12636"
transform="matrix(0.8077059,0,0,-0.2072667,-72.578821,124.6156)"
@@ -71004,7 +72963,7 @@
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
sodipodi:ry="8"
sodipodi:rx="8"
sodipodi:cy="118"
@@ -71021,7 +72980,7 @@
sodipodi:cy="118"
sodipodi:rx="8"
sodipodi:ry="8"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.37076,0 -7.9325,-3.50789 -7.99907,-7.87814"
+ d="m 140,118 a 8,8 0 0 1 -7.93907,7.99977 8,8 0 0 1 -8.06,-7.87791"
sodipodi:start="0"
sodipodi:end="3.12636"
sodipodi:open="true"
@@ -71039,7 +72998,7 @@
sodipodi:cy="118"
sodipodi:rx="8"
sodipodi:ry="8"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
transform="matrix(0.6875009,0,0,0.687501,-56.75013,18.874887)" />
<path
inkscape:export-ydpi="90"
@@ -71052,14 +73011,14 @@
sodipodi:cy="118"
sodipodi:rx="8"
sodipodi:ry="8"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.38113,0 7.94728,3.52395 7.99943,7.90477"
+ d="m 140,118 a 8,8 0 0 1 -7.97619,7.99996 8,8 0 0 1 -8.02367,-7.95235 8,8 0 0 1 7.92844,-8.04729 8,8 0 0 1 8.07085,7.90445"
sodipodi:start="0"
sodipodi:end="6.2712816"
sodipodi:open="true"
transform="matrix(0,0.7811136,-0.34375,0,74.562502,-3.1287373)" />
<path
transform="matrix(0.9374995,0,0,0.9374996,-89.749939,-10.62495)"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
sodipodi:ry="8"
sodipodi:rx="8"
sodipodi:cy="118"
@@ -71073,7 +73032,7 @@
</g>
</g>
<g
- id="g39510"
+ id="ICON_CANCEL"
transform="translate(-570,274)">
<path
sodipodi:nodetypes="ccccccccc"
@@ -71111,7 +73070,7 @@
</g>
</g>
<g
- id="g40247"
+ id="ICON_OBJECT_DATA"
transform="translate(63,-21.000002)">
<rect
style="opacity:0;fill:#f6d0a6;fill-opacity:1;fill-rule:evenodd;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
@@ -71187,7 +73146,7 @@
</g>
<g
transform="translate(508.99432,90)"
- id="g38556">
+ id="ICON_UV_FACESEL">
<rect
transform="matrix(0,1,1,0,0,0)"
style="opacity:0;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:3.0999999;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
@@ -71284,7 +73243,7 @@
</g>
<g
transform="translate(505.99432,90)"
- id="g38644">
+ id="ICON_UV_ISLANDSEL">
<rect
y="-185.99432"
x="46"
@@ -71370,7 +73329,7 @@
</g>
</g>
<g
- id="g39152"
+ id="ICON_UV_EDGESEL"
transform="translate(507.99432,90)">
<rect
transform="matrix(0,1,1,0,0,0)"
@@ -71545,7 +73504,7 @@
</g>
</g>
<g
- id="g29977">
+ id="ICON_UV_VERTEXSEL">
<rect
y="257"
x="136"
@@ -71702,7 +73661,7 @@
inkscape:connector-curvature="0" />
</g>
<g
- id="g39098"
+ id="ICON_PLUGIN"
transform="translate(42,63)">
<rect
ry="0"
@@ -71796,7 +73755,7 @@
</g>
<g
transform="translate(-105,212.00008)"
- id="g39237"
+ id="ICON_QUESTION"
style="display:inline;enable-background:new">
<g
inkscape:export-ydpi="90"
@@ -71835,7 +73794,7 @@
sodipodi:cy="118"
sodipodi:rx="8"
sodipodi:ry="8"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90" />
@@ -71851,7 +73810,7 @@
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
sodipodi:ry="8"
sodipodi:rx="8"
sodipodi:cy="118"
@@ -71880,7 +73839,7 @@
</g>
<g
transform="translate(-3.0078133e-8,128.00008)"
- id="g39694"
+ id="ICON_INFO"
style="display:inline;enable-background:new">
<g
inkscape:export-ydpi="90"
@@ -71919,7 +73878,7 @@
sodipodi:cy="118"
sodipodi:rx="8"
sodipodi:ry="8"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90" />
@@ -71935,7 +73894,7 @@
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
sodipodi:ry="8"
sodipodi:rx="8"
sodipodi:cy="118"
@@ -71986,98 +73945,149 @@
</g>
</g>
<g
- id="g40264"
- transform="translate(21,0)"
- mask="url(#mask40306)">
- <rect
- ry="0"
- style="fill:#f2f2f2;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:0.80000001;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- id="rect40266"
- width="13.016124"
- height="12.953857"
- x="195.49998"
- y="11.546152" />
- <rect
- y="12.00001"
- x="197.01611"
- height="11.046139"
- width="11.000001"
- id="rect40268"
- style="fill:url(#linearGradient40295);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.00207269;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- ry="0" />
+ id="ICON_IMAGE_RGB_ALPHA">
<g
- id="g40270"
- transform="translate(146.99999,-417.99999)">
+ style="opacity:0.25"
+ transform="translate(275,-385.99999)"
+ id="g17336">
+ <rect
+ y="396"
+ x="-60"
+ height="16"
+ width="16"
+ id="rect17338"
+ style="opacity:0;fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
<g
- transform="translate(-146.99999,417.99999)"
- id="g40272">
- <rect
- style="fill:#106386;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.89999998;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- id="rect40276"
- width="3"
- height="3"
- x="196"
- y="12" />
- <rect
- style="fill:#ba0036;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.89999998;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- id="rect40278"
- width="3"
- height="3"
- x="199"
- y="15" />
+ id="g17340">
<rect
- y="12"
- x="202"
- height="3"
- width="3"
- id="rect40280"
- style="fill:#9f0022;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.89999998;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
- <rect
- y="15"
- x="205"
- height="3"
- width="3"
- id="rect40282"
- style="fill:#688c7f;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.89999998;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
- <rect
- y="18"
- x="196"
- height="3"
- width="3"
- id="rect40284"
- style="fill:#b77100;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.89999998;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
- <rect
- y="21"
- x="199"
- height="3"
- width="3"
- id="rect40286"
- style="fill:#a67c58;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.89999998;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
- <rect
- style="fill:#7a2537;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.89999998;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- id="rect40288"
- width="3"
- height="3"
- x="202"
- y="18" />
+ ry="0"
+ style="fill:url(#linearGradient32725);fill-opacity:1;fill-rule:nonzero;stroke:#333333;stroke-width:0.99999994;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect17342"
+ width="13.016124"
+ height="12.953857"
+ x="-58.500015"
+ y="397.54614" />
<rect
- style="fill:#869c2b;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.89999998;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- id="rect40290"
- width="3"
- height="3"
- x="205"
- y="21" />
+ y="398"
+ x="-56.983894"
+ height="11.046139"
+ width="11.000001"
+ id="rect17344"
+ style="fill:url(#linearGradient32727);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.00207269;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ ry="0" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path17346"
+ d="m -58,398 0,2 2,0 0,-2 -2,0 z m 2,2 0,2 2,0 0,-2 -2,0 z m 2,0 2,0 0,-2 -2,0 0,2 z m 2,0 0,2 2,0 0,-2 -2,0 z m 2,0 2,0 0,-2 -2,0 0,2 z m 2,0 0,2 2,0 0,-2 -2,0 z m 0,2 -2,0 0,2 2,0 0,-2 z m 0,2 0,2 2,0 0,-2 -2,0 z m 0,2 -2,0 0,2 2,0 0,-2 z m 0,2 0,2 2,0 0,-2 -2,0 z m -2,0 -2,0 0,2 2,0 0,-2 z m -2,0 0,-2 -2,0 0,2 2,0 z m -2,0 -2,0 0,2 2,0 0,-2 z m -2,0 0,-2 -2,0 0,2 2,0 z m 0,-2 2,0 0,-2 -2,0 0,2 z m 0,-2 0,-2 -2,0 0,2 2,0 z m 2,0 2,0 0,-2 -2,0 0,2 z m 2,0 0,2 2,0 0,-2 -2,0 z"
+ style="fill:url(#linearGradient32729);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <path
+ inkscape:connector-curvature="0"
+ style="opacity:0.45;fill:none;stroke:url(#linearGradient32731);stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ d="m -46.482307,398.50001 -11.017704,0 0,11 11.017704,0 0,-11"
+ id="path17348"
+ sodipodi:nodetypes="ccc" />
</g>
</g>
<path
- style="fill:none;stroke:url(#linearGradient40297);stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
- d="m 207.51769,12.50001 -11.0177,0 0,11 11.0177,0 0,-11"
- id="path40292"
- sodipodi:nodetypes="ccc"
- inkscape:connector-curvature="0" />
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cc"
+ id="path17578"
+ d="m 217.5,24.000005 11.5,-11.5"
+ style="opacity:0.65;fill:none;stroke:#000000;stroke-width:1.79999995;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+ <g
+ mask="url(#mask40306)"
+ transform="translate(21,0)"
+ id="g40264">
+ <rect
+ y="11.546152"
+ x="195.49998"
+ height="12.953857"
+ width="13.016124"
+ id="rect40266"
+ style="fill:#f2f2f2;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:0.80000001;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ ry="0" />
+ <rect
+ ry="0"
+ style="fill:url(#linearGradient40295);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.00207269;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect40268"
+ width="11.000001"
+ height="11.046139"
+ x="197.01611"
+ y="12.00001" />
+ <g
+ transform="translate(146.99999,-417.99999)"
+ id="g40270">
+ <g
+ id="g40272"
+ transform="translate(-146.99999,417.99999)">
+ <rect
+ y="12"
+ x="196"
+ height="3"
+ width="3"
+ id="rect40276"
+ style="fill:#106386;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.89999998;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <rect
+ y="15"
+ x="199"
+ height="3"
+ width="3"
+ id="rect40278"
+ style="fill:#ba0036;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.89999998;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <rect
+ style="fill:#9f0022;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.89999998;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect40280"
+ width="3"
+ height="3"
+ x="202"
+ y="12" />
+ <rect
+ style="fill:#688c7f;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.89999998;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect40282"
+ width="3"
+ height="3"
+ x="205"
+ y="15" />
+ <rect
+ style="fill:#b77100;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.89999998;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect40284"
+ width="3"
+ height="3"
+ x="196"
+ y="18" />
+ <rect
+ style="fill:#a67c58;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.89999998;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect40286"
+ width="3"
+ height="3"
+ x="199"
+ y="21" />
+ <rect
+ y="18"
+ x="202"
+ height="3"
+ width="3"
+ id="rect40288"
+ style="fill:#7a2537;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.89999998;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <rect
+ y="21"
+ x="205"
+ height="3"
+ width="3"
+ id="rect40290"
+ style="fill:#869c2b;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.89999998;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ </g>
+ </g>
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccc"
+ id="path40292"
+ d="m 207.51769,12.50001 -11.0177,0 0,11 11.0177,0 0,-11"
+ style="fill:none;stroke:url(#linearGradient40297);stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" />
+ </g>
</g>
<g
- id="g39333"
+ id="ICON_COPYDOWN"
transform="translate(0,-62.1)">
<rect
style="opacity:0.01000001;fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
@@ -72220,7 +74230,7 @@
</g>
</g>
<g
- id="g39306"
+ id="ICON_PASTEDOWN"
transform="translate(-1,-62)">
<rect
y="198"
@@ -72363,7 +74373,7 @@
</g>
<g
style="display:inline;enable-background:new"
- id="g40848"
+ id="ICON_LINK_AREA"
transform="translate(232,503)">
<rect
style="opacity:0;fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
@@ -72556,7 +74566,7 @@
</g>
<g
style="display:inline;enable-background:new"
- id="g40697"
+ id="ICON_URL"
transform="translate(455.99408,547.99927)"
inkscape:export-filename="C:\Documents and Settings\Pracownia\Moje dokumenty\Moje obrazy\BLENDER ICONS redesign\ver 3\URL link 1.png"
inkscape:export-xdpi="90"
@@ -72630,13 +74640,13 @@
sodipodi:cy="118"
sodipodi:rx="8"
sodipodi:ry="8"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90"
transform="matrix(0.787566,0,0,0.779223,26.709197,21.3179)" />
<path
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
sodipodi:ry="8"
sodipodi:rx="8"
sodipodi:cy="118"
@@ -72660,7 +74670,7 @@
sodipodi:cy="118"
sodipodi:rx="8"
sodipodi:ry="8"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z" />
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z" />
<path
sodipodi:nodetypes="cc"
id="path40271"
@@ -72678,7 +74688,7 @@
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
sodipodi:ry="8"
sodipodi:rx="8"
sodipodi:cy="118"
@@ -72688,7 +74698,7 @@
sodipodi:type="arc"
transform="matrix(0.6429129,0,0,0.6362007,45.809534,38.194473)" />
<path
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
sodipodi:ry="8"
sodipodi:rx="8"
sodipodi:cy="118"
@@ -72704,7 +74714,7 @@
</g>
<g
style="display:inline;enable-background:new"
- id="g41840"
+ id="ICON_NEW"
transform="translate(497,652)">
<rect
y="-75"
@@ -72830,7 +74840,7 @@
<g
transform="translate(378,684)"
style="display:inline;enable-background:new"
- id="g39156">
+ id="ICON_COPY_ID">
<rect
style="opacity:0;fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
id="rect40773"
@@ -72953,7 +74963,7 @@
</g>
</g>
<g
- id="g39528">
+ id="ICON_PASTEFLIPDOWN">
<g
clip-path="url(#clipPath40902)"
id="g40560"
@@ -73121,7 +75131,7 @@
</g>
</g>
<g
- id="g39560">
+ id="ICON_PASTEFLIPUP">
<g
clip-path="url(#clipPath40897)"
id="g40506"
@@ -73289,15 +75299,8 @@
</g>
</g>
<g
- inkscape:export-ydpi="90"
- inkscape:export-xdpi="90"
- inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
- transform="matrix(0.5478212,-0.56064,0.5419177,0.5545983,197.19518,557.21673)"
- id="g38570"
- style="stroke-width:5.41920376;stroke-miterlimit:4;stroke-dasharray:none;display:inline" />
- <g
transform="translate(-1.0992584e-6,128)"
- id="g44264">
+ id="ICON_OUTLINER_DATA_EMPTY">
<g
id="g44266"
style="opacity:0.8;display:inline"
@@ -73338,7 +75341,7 @@
sodipodi:cy="14.5"
sodipodi:rx="1.5"
sodipodi:ry="1.5"
- d="M 72,14.5 C 72,15.328427 71.328427,16 70.5,16 69.671573,16 69,15.328427 69,14.5 69,13.671573 69.671573,13 70.5,13 c 0.828427,0 1.5,0.671573 1.5,1.5 z"
+ d="M 72,14.5 A 1.5,1.5 0 0 1 70.5,16 1.5,1.5 0 0 1 69,14.5 1.5,1.5 0 0 1 70.5,13 1.5,1.5 0 0 1 72,14.5 Z"
transform="matrix(1.176776,0,0,1.176776,-12.47787,-2.548088)"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png"
inkscape:export-xdpi="90"
@@ -73513,7 +75516,7 @@
rx="0" />
</g>
<g
- id="g43843">
+ id="ICON_ERROR">
<g
transform="translate(20,-30.990313)"
id="g39499">
@@ -73573,7 +75576,7 @@
inkscape:connector-curvature="0" />
</g>
<g
- id="g44081"
+ id="ICON_FILE_PARENT"
transform="translate(0,1)">
<rect
style="opacity:0;fill:#1a1a1a;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.20000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
@@ -73635,7 +75638,7 @@
</g>
</g>
<g
- id="g44124">
+ id="ICON_FILE_REFRESH">
<rect
y="73"
x="341"
@@ -73751,7 +75754,7 @@
</g>
</g>
<g
- id="g44097">
+ id="ICON_BACK">
<rect
y="52"
x="320"
@@ -73820,7 +75823,7 @@
</g>
<g
transform="translate(-1,0)"
- id="g44111">
+ id="ICON_FORWARD">
<rect
style="opacity:0;fill:#1a1a1a;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.20000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
id="rect44093"
@@ -74634,7 +76637,7 @@
transform="matrix(1.1428564,0,0,1.2000001,822.71436,-355.40005)">
<path
transform="matrix(0.7630859,-0.2494396,0.2996015,0.9926766,-151.92281,17.77746)"
- d="m 57.5,554 c 0,1.24264 -2.014719,2.25 -4.5,2.25 -2.485281,0 -4.5,-1.00736 -4.5,-2.25 0,-1.24264 2.014719,-2.25 4.5,-2.25 2.485281,0 4.5,1.00736 4.5,2.25 z"
+ d="M 57.5,554 A 4.5,2.25 0 0 1 53,556.25 4.5,2.25 0 0 1 48.5,554 4.5,2.25 0 0 1 53,551.75 4.5,2.25 0 0 1 57.5,554 Z"
sodipodi:ry="2.25"
sodipodi:rx="4.5"
sodipodi:cy="554"
@@ -74650,7 +76653,7 @@
sodipodi:cy="554"
sodipodi:rx="4.5"
sodipodi:ry="2.25"
- d="m 57.5,554 c 0,1.24264 -2.014719,2.25 -4.5,2.25 -2.485281,0 -4.5,-1.00736 -4.5,-2.25 0,-1.24264 2.014719,-2.25 4.5,-2.25 2.485281,0 4.5,1.00736 4.5,2.25 z"
+ d="M 57.5,554 A 4.5,2.25 0 0 1 53,556.25 4.5,2.25 0 0 1 48.5,554 4.5,2.25 0 0 1 53,551.75 4.5,2.25 0 0 1 57.5,554 Z"
transform="matrix(0.3848865,-0.1700959,0.2278131,0.3626733,-93.107467,361.59408)"
inkscape:transform-center-y="0.3813435"
clip-path="url(#clipPath20586)" />
@@ -74672,13 +76675,13 @@
sodipodi:cy="554"
sodipodi:rx="4.5"
sodipodi:ry="2.25"
- d="m 57.5,554 c 0,1.24264 -2.014719,2.25 -4.5,2.25 -2.485281,0 -4.5,-1.00736 -4.5,-2.25 0,-1.24264 2.014719,-2.25 4.5,-2.25 2.485281,0 4.5,1.00736 4.5,2.25 z"
+ d="M 57.5,554 A 4.5,2.25 0 0 1 53,556.25 4.5,2.25 0 0 1 48.5,554 4.5,2.25 0 0 1 53,551.75 4.5,2.25 0 0 1 57.5,554 Z"
transform="matrix(0.7630859,-0.2494396,0.2996015,0.9926766,-151.92281,17.77746)" />
<path
clip-path="url(#clipPath20586)"
inkscape:transform-center-y="0.3813435"
transform="matrix(0.3848865,-0.1700959,0.2278131,0.3626733,-93.107467,361.59408)"
- d="m 57.5,554 c 0,1.24264 -2.014719,2.25 -4.5,2.25 -2.485281,0 -4.5,-1.00736 -4.5,-2.25 0,-1.24264 2.014719,-2.25 4.5,-2.25 2.485281,0 4.5,1.00736 4.5,2.25 z"
+ d="M 57.5,554 A 4.5,2.25 0 0 1 53,556.25 4.5,2.25 0 0 1 48.5,554 4.5,2.25 0 0 1 53,551.75 4.5,2.25 0 0 1 57.5,554 Z"
sodipodi:ry="2.25"
sodipodi:rx="4.5"
sodipodi:cy="554"
@@ -74849,7 +76852,7 @@
sodipodi:cy="118"
sodipodi:rx="8"
sodipodi:ry="8"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90" />
@@ -74857,7 +76860,7 @@
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
sodipodi:ry="8"
sodipodi:rx="8"
sodipodi:cy="118"
@@ -74891,7 +76894,7 @@
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
sodipodi:ry="8"
sodipodi:rx="8"
sodipodi:cy="118"
@@ -75011,7 +77014,7 @@
transform="matrix(0.5406242,0,0,0.5829534,814.13667,247.65542)">
<path
transform="matrix(1.274286,0,0,1.377124,-7.569123,-16.70193)"
- d="m 43.487067,38.98439 c 0,2.928932 -6.925242,5.303301 -15.467961,5.303301 -8.542719,0 -15.467961,-2.374369 -15.467961,-5.303301 0,-2.928932 6.925242,-5.303301 15.467961,-5.303301 8.542719,0 15.467961,2.374369 15.467961,5.303301 z"
+ d="M 43.487067,38.98439 A 15.467961,5.3033009 0 0 1 28.019106,44.287691 15.467961,5.3033009 0 0 1 12.551145,38.98439 15.467961,5.3033009 0 0 1 28.019106,33.681089 15.467961,5.3033009 0 0 1 43.487067,38.98439 Z"
sodipodi:ry="5.3033009"
sodipodi:rx="15.467961"
sodipodi:cy="38.98439"
@@ -75027,7 +77030,7 @@
style="fill:#f57900;fill-rule:evenodd;stroke:#aa4400;stroke-width:1.7812928;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none" />
<path
transform="matrix(0.8018194,0,0,0.8471126,6.257567,4.5089892)"
- d="m 42.75,25.75 c 0,5.591883 -5.176708,10.125 -11.5625,10.125 -6.385792,0 -11.5625,-4.533117 -11.5625,-10.125 0,-5.591883 5.176708,-10.125 11.5625,-10.125 6.385792,0 11.5625,4.533117 11.5625,10.125 z"
+ d="M 42.75,25.75 A 11.5625,10.125 0 0 1 31.1875,35.875 11.5625,10.125 0 0 1 19.625,25.75 11.5625,10.125 0 0 1 31.1875,15.625 11.5625,10.125 0 0 1 42.75,25.75 Z"
sodipodi:ry="10.125"
sodipodi:rx="11.5625"
sodipodi:cy="25.75"
@@ -75589,7 +77592,7 @@
d="m 930.5,344.5 0,3 c 0,1.73575 -1.26424,3 -3,3 l -5,0 c -1.73576,0 -3,1.26425 -3,3 l 0,3"
style="fill:none;stroke:#000000;stroke-width:0.80000001;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:0.78431373;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
<path
- d="m 923,342 c 0,0.55228 -0.44772,1 -1,1 -0.55228,0 -1,-0.44772 -1,-1 0,-0.55228 0.44772,-1 1,-1 0.55228,0 1,0.44772 1,1 z"
+ d="m 923,342 a 1,1 0 0 1 -1,1 1,1 0 0 1 -1,-1 1,1 0 0 1 1,-1 1,1 0 0 1 1,1 z"
sodipodi:ry="1"
sodipodi:rx="1"
sodipodi:cy="342"
@@ -75598,7 +77601,7 @@
style="color:#000000;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.80000001;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
sodipodi:type="arc" />
<path
- d="m 929,359 c 0,0.55228 -0.44772,1 -1,1 -0.55228,0 -1,-0.44772 -1,-1 0,-0.55228 0.44772,-1 1,-1 0.55228,0 1,0.44772 1,1 z"
+ d="m 929,359 a 1,1 0 0 1 -1,1 1,1 0 0 1 -1,-1 1,1 0 0 1 1,-1 1,1 0 0 1 1,1 z"
sodipodi:ry="1"
sodipodi:rx="1"
sodipodi:cy="359"
@@ -75641,7 +77644,7 @@
sodipodi:cy="342"
sodipodi:rx="1"
sodipodi:ry="1"
- d="m 923,342 c 0,0.55228 -0.44772,1 -1,1 -0.55228,0 -1,-0.44772 -1,-1 0,-0.55228 0.44772,-1 1,-1 0.55228,0 1,0.44772 1,1 z" />
+ d="m 923,342 a 1,1 0 0 1 -1,1 1,1 0 0 1 -1,-1 1,1 0 0 1 1,-1 1,1 0 0 1 1,1 z" />
</g>
<g
style="opacity:0.8;stroke:#ff0000"
@@ -75671,7 +77674,7 @@
d="m 918.5,355.5 0,-2 c 0,-2.25 1.75,-4 4,-4 l 4.5,0 c 1.75,0 2.5,-0.75 2.5,-2.5 l 0,-0.5"
style="fill:none;stroke:url(#radialGradient34973-2-5-7);stroke-linecap:round;stroke-linejoin:round" />
<path
- d="m 923,342 c 0,0.55228 -0.44772,1 -1,1 -0.55228,0 -1,-0.44772 -1,-1 0,-0.55228 0.44772,-1 1,-1 0.55228,0 1,0.44772 1,1 z"
+ d="m 923,342 a 1,1 0 0 1 -1,1 1,1 0 0 1 -1,-1 1,1 0 0 1 1,-1 1,1 0 0 1 1,1 z"
sodipodi:ry="1"
sodipodi:rx="1"
sodipodi:cy="342"
@@ -75689,9 +77692,151 @@
</g>
</g>
</g>
+ <g
+ style="display:inline;enable-background:new"
+ id="g14765"
+ inkscape:export-filename="/home/georg/Arbeitsfläche/2012/Blender Coding/Patch #2a/icon_big_redone 5a.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"
+ transform="translate(1090.1244,-109.28264)">
+ <rect
+ ry="0"
+ rx="2.4004419"
+ y="336.28265"
+ x="-78.124435"
+ height="48"
+ width="48"
+ id="rect14767"
+ style="opacity:0;fill:#cccccc;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.00000012;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <path
+ inkscape:export-ydpi="90"
+ inkscape:export-xdpi="90"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png"
+ sodipodi:nodetypes="cccccc"
+ id="path14769"
+ d="m -60.624426,339.78264 22.999995,0 0,41 -32.999995,0 0,-31 10,-10 z"
+ style="fill:url(#linearGradient14814);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;display:inline"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cccc"
+ id="path14771"
+ style="opacity:0.7;fill:none;stroke:url(#linearGradient14816);stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:0.56470588"
+ d="m -38.874431,340.78264 c -4.875,0 -21.749995,0 -21.749995,0 m -8.9447,8.5 -0.0553,30"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.2;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;filter:url(#filter63011-8)"
+ d="m 115,444 12,0 -1,-11 -11,11 z"
+ id="path14773"
+ sodipodi:nodetypes="cccc"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"
+ clip-path="url(#clipPath13106-0)"
+ inkscape:connector-curvature="0"
+ transform="translate(-186.12444,-93.717362)" />
+ <path
+ sodipodi:nodetypes="ccc"
+ id="path14775"
+ style="fill:none;stroke:url(#linearGradient14818);stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m -68.624426,350.03264 9,-2.5 0,-6"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"
+ clip-path="none"
+ inkscape:connector-curvature="0" />
+ <path
+ inkscape:export-ydpi="90"
+ inkscape:export-xdpi="90"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png"
+ d="m -70.624426,349.03264 0,31.75 32.999995,0 0,-41 -23.749995,0 -9.25,9.25 z"
+ style="fill:none;stroke:#333333;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ id="path14777"
+ sodipodi:nodetypes="cccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.16000001;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;display:inline;filter:url(#filter63011-8)"
+ d="m 116,443 11,1 -2,-10 -9,9 z"
+ id="path14779"
+ sodipodi:nodetypes="cccc"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"
+ clip-path="url(#clipPath13106-0)"
+ inkscape:connector-curvature="0"
+ transform="translate(-186.12444,-93.717362)" />
+ <path
+ inkscape:export-ydpi="90"
+ inkscape:export-xdpi="90"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png"
+ sodipodi:nodetypes="cccccc"
+ id="path14781"
+ d="m -70.124426,349.28264 0.0108,0.72434 9.9892,-2.72434 0,-7 -1,0 -9,9 z"
+ style="fill:#ffffff;fill-opacity:0.75294118;fill-rule:evenodd;stroke:none"
+ inkscape:connector-curvature="0" />
+ <path
+ inkscape:export-ydpi="90"
+ inkscape:export-xdpi="90"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png"
+ d="m -38.624431,341.28264 0,38.5 -30.499995,0"
+ style="opacity:0.15;fill:none;stroke:#000000;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ id="path14783"
+ sodipodi:nodetypes="ccc"
+ inkscape:connector-curvature="0" />
+ <g
+ transform="matrix(0.5406242,0,0,0.5829534,-67.987756,347.93806)"
+ inkscape:label="Layer 1"
+ id="g14785">
+ <path
+ sodipodi:type="arc"
+ style="opacity:0.54857142;fill:url(#radialGradient14820);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="path14788"
+ sodipodi:cx="28.019106"
+ sodipodi:cy="38.98439"
+ sodipodi:rx="15.467961"
+ sodipodi:ry="5.3033009"
+ d="M 43.487067,38.98439 A 15.467961,5.3033009 0 0 1 28.019106,44.287691 15.467961,5.3033009 0 0 1 12.551145,38.98439 15.467961,5.3033009 0 0 1 28.019106,33.681089 15.467961,5.3033009 0 0 1 43.487067,38.98439 Z"
+ transform="matrix(1.274286,0,0,1.377124,-7.569123,-16.70193)" />
+ <path
+ style="fill:#f57900;fill-rule:evenodd;stroke:#aa4400;stroke-width:1.7812928;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none"
+ id="path14790"
+ d="m 16.048489,28.093447 c 0.0098,0.576682 0.196474,1.697902 0.471116,2.577425 0.581566,1.854137 1.56684,3.572658 2.939126,5.086496 1.407488,1.553118 3.138519,2.803227 5.139315,3.68976 2.105357,0.931573 4.384795,1.407488 6.750134,1.403741 2.365339,-0.005 4.644601,-0.488686 6.74896,-1.427017 2.00002,-0.895288 3.731043,-2.148391 5.13754,-3.705517 1.369207,-1.519844 2.352576,-3.241114 2.934089,-5.096258 0.294262,-0.938353 0.476921,-1.889392 0.553238,-2.845308 0.07331,-0.939306 0.04204,-1.883511 -0.09183,-2.823792 -0.259981,-1.835599 -0.896294,-3.556847 -1.872652,-5.12758 -0.895541,-1.441699 -2.047808,-2.70454 -3.417268,-3.766975 0,0 0.002,-0.002 0.002,-0.002 0,0 -13.828458,-10.6197195 -13.828458,-10.6197195 -0.01176,-0.00978 -0.02252,-0.019551 -0.03529,-0.028344 -0.909003,-0.6959264 -3.879837,-0.7738945 -4.87679,-0.075035 -1.01067,0.7057021 -1.091821,1.8092613 -0.195527,2.5482146 1.899775,1.4997633 2.656207,2.2801589 4.566507,3.7797379 0,0 -14.852491,0.167033 -14.852491,0.167033 -1.994685,0 -3.1682609,0.947915 -3.4153947,2.333683 -0.2180771,1.222836 0.7479213,2.738129 2.4800217,2.738129 2.956573,0.0039 5.942111,-0.0069 8.909215,-0.01272 0,0 -16.01999,12.453223 -16.01999,12.453223 -0.020527,0.01564 -0.041053,0.02933 -0.06158,0.04497 -1.4974197,1.148389 -1.9831951,3.059322 -1.0399808,4.268393 0.9598323,1.22959 2.9977653,1.230588 4.5147288,0.006 0,0 8.677593,-7.102098 8.677593,-7.102098 0,0 -0.12511,0.959824 -0.116333,1.535532 l 1e-6,2.6e-5 0,0 0,0 z"
+ sodipodi:nodetypes="csssssssssscccsscccscccssccc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:type="arc"
+ style="fill:url(#linearGradient14822);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="path14792"
+ sodipodi:cx="31.1875"
+ sodipodi:cy="25.75"
+ sodipodi:rx="11.5625"
+ sodipodi:ry="10.125"
+ d="M 42.75,25.75 A 11.5625,10.125 0 0 1 31.1875,35.875 11.5625,10.125 0 0 1 19.625,25.75 11.5625,10.125 0 0 1 31.1875,15.625 11.5625,10.125 0 0 1 42.75,25.75 Z"
+ transform="matrix(0.8018194,0,0,0.8471126,6.257567,4.5089892)" />
+ <path
+ sodipodi:nodetypes="csssssscssscsssccssscscccsccssssccscsscccssssc"
+ id="path14794"
+ d="m 25.8125,6.40625 c -0.334829,4.572e-4 -0.72202,0.089606 -0.90625,0.21875 4.5e-4,0.010412 4.5e-4,0.020838 0,0.03125 -0.212626,0.1484635 -0.188235,0.1956271 -0.1875,0.1875 0.0092,0.010621 -0.0072,-4.246e-4 0.03125,0.03125 0.01962,0.00828 0.03527,0.012546 0.0625,0.03125 0.01676,0.01151 0.01357,0.014555 0.03125,0.03125 0.193748,0.1576058 4.954976,4.005164 4.954976,4.005164 0.489837,0.39864 0.677395,1.066352 0.46875,1.65625 -0.115662,0.32703 -0.422813,0.541217 -0.6875,0.59375 -0.264687,0.05253 -0.498447,0.03054 -0.71875,0.03125 -5.639658,0.05119 -16.87989,0.03851 -16.87989,0.03851 -0.4102,2.75e-4 -0.935835,0.115997 -1.34375,0.34375 -0.407915,0.227753 -0.6637862,0.523861 -0.6875002,0.90625 -0.024417,0.393728 0.098829,0.605767 0.3437502,0.78125 0.244921,0.175483 0.614978,0.25 0.875,0.25 0,0 8.8125,0 8.8125,0 0.600305,-7.28e-4 1.223895,0.311058 1.4375,0.9375 0.04676,0.137121 0.06335,0.269976 0.0625,0.40625 -8.49e-4,0.136274 -0.02214,0.268794 -0.09375,0.375 -0.143211,0.212412 -0.319507,0.298568 -0.5,0.4375 0,0 -15.7871819,12.746851 -15.856336,12.800078 C 5.0310984,30.500117 5,30.53125 5,30.53125 5.0100745,30.519077 5.000335,30.499512 5,30.5 L 4.8125,30.3125 c 0.012336,0.02165 0.014481,0.03307 0.03125,0.0625 0.063558,0.0774 0.125,0.15625 0.125,0.15625 -0.00585,0.0056 -0.031233,0.03124 -0.03125,0.03125 0,0 -0.043442,-0.09921 -0.09375,-0.1875 0.037843,0.09884 0.06253,0.218739 0.0625,0.21875 -0.4662091,0.37119 -0.7783348,0.889746 -0.875,1.28125 -0.1043319,0.422581 -0.046,0.62455 0.125,0.84375 0.2999827,0.384295 1.3975356,0.595547 2.40625,-0.21875 0,0 8.65625,-7.09375 8.65625,-7.09375 0.473718,-0.387074 1.1446,-0.458625 1.6875,-0.15625 0.544608,0.303331 0.798054,0.927572 0.71875,1.53125 0,0 -0.0626,0.908319 -0.0625,1.25 2e-6,0.0085 -1.19e-4,0.02348 0,0.03125 0.192796,2.523718 1.400736,4.762818 3.03125,6.71875 2.801818,3.089095 6.627659,4.401619 10.75,4.5625 4.113324,-0.043 7.964529,-1.606111 10.75,-4.625 2.546631,-3.125326 3.513872,-6.363859 3.15625,-9.375 C 44.891575,22.325847 43.222923,19.516566 40.4375,17.25 35.951885,13.599946 31.206991,10.168434 26.59375,6.625 26.57515,6.610386 26.56455,6.59802 26.5625,6.59375 26.43835,6.498703 26.144223,6.4057899 25.8125,6.40625 z"
+ style="opacity:0.4857143;fill:none;stroke:url(#linearGradient14825);stroke-width:1.7812928;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#3465a4;fill-rule:evenodd;stroke:none"
+ id="path14796"
+ d="m 25.708956,26.064593 c 0.07649,-1.397943 0.759369,-2.631914 1.78592,-3.505519 1.010226,-0.858782 2.366788,-1.383145 3.848625,-1.383145 1.480894,0 2.837456,0.524363 3.847446,1.383145 1.027685,0.873605 1.709741,2.106651 1.787122,3.504594 0.07927,1.438713 -0.49591,2.77459 -1.504012,3.764001 -1.027686,1.007933 -2.493008,1.640678 -4.130556,1.640678 -1.63849,0 -3.103814,-0.632745 -4.131451,-1.640678 -1.00914,-0.989411 -1.58234,-2.325288 -1.503094,-3.763076 l 0,0 0,0 0,0 z"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.51999996;fill:url(#radialGradient14827);fill-opacity:1;fill-rule:evenodd;stroke:none"
+ d="m 25.8125,6.03125 c -0.404852,5.53e-4 -2.204797,-0.059029 -2.48145,0.1349032 -0.280209,0.195652 -0.335403,0.376484 -0.34375,0.46875 -0.0083,0.092266 -0.01539,0.17648 0.1875,0.34375 0.01899,0.015735 0.04457,0.014317 0.0625,0.03125 0.124258,0.101028 4.748869,4.1248618 4.748869,4.1248618 0.373658,0.304091 0.504393,0.795817 0.34375,1.25 -0.160635,0.454191 -0.580748,0.373449 -1.0625,0.375 -5.634142,0.05114 -15.087371,-0.129601 -15.087371,-0.129601 -0.952967,6.38e-4 -2.339958,0.524782 -2.4062504,1.59375 -0.063562,1.024947 0.9247974,1.4375 1.5937504,1.4375 0,-1e-6 8.8125,0 8.8125,0 0.488364,-5.92e-4 0.936141,0.225277 1.09375,0.6875 0.157609,0.462231 -0.01926,0.514621 -0.40625,0.8125 0,0 -16.086298,13.088586 -16.086298,13.088586 -0.00142,0.0014 -0.029829,-0.0014 -0.03125,0 -0.064037,0.04879 -0.054226,0.04875 -0.03125,0.03125 -0.5536758,0.424619 -0.9087886,1.004019 -1.03125,1.5 -0.1224536,0.495981 -0.04661,0.856152 0.1875,1.15625 0.4788333,0.613413 1.777612,0.754857 2.90625,-0.15625 1e-7,10e-7 8.65625,-7.09375 8.65625,-7.09375 0.361955,-0.295753 0.872897,-0.352437 1.28125,-0.125 0.408345,0.227436 0.623381,0.692814 0.5625,1.15625 0,-1e-6 -0.0997,0.953636 -0.09375,1.34375 0.09498,1.301756 0.451616,2.521825 0.989039,3.664234 C 20.799917,36.321089 27.770982,19.392853 44.1875,21.03125 43.339652,19.54368 42.151282,18.185293 40.65625,16.96875 36.159865,13.309932 31.42016,9.882897 26.8125,6.34375 26.805335,6.338858 26.788292,6.317553 26.78125,6.3125 26.570707,6.151312 26.216591,6.030689 25.8125,6.03125 z"
+ id="path14798"
+ sodipodi:nodetypes="csssscsccsscsccssssscsscccsssc"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
</g>
<g
- id="g44575"
+ id="ICON_FULLSCREEN_ENTER"
inkscape:export-filename="C:\Documents and Settings\Pracownia\Moje dokumenty\Moje obrazy\BLENDER ICONS redesign\ver 3\fullscreen.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90"
@@ -75796,7 +77941,7 @@
inkscape:connector-curvature="0" />
</g>
<g
- id="g44633"
+ id="ICON_FULLSCREEN_EXIT"
transform="translate(189.0625,-42)"
inkscape:export-filename="C:\Documents and Settings\Pracownia\Moje dokumenty\Moje obrazy\BLENDER ICONS redesign\ver 3\fullscreen.png"
inkscape:export-xdpi="90"
@@ -75910,7 +78055,7 @@
</g>
<g
clip-path="url(#clipPath45147)"
- id="g45199">
+ id="ICON_MODIFIER">
<g
id="g45201"
clip-path="none"
@@ -75970,7 +78115,7 @@
</g>
</g>
<g
- id="g45262">
+ id="ICON_QUIT">
<rect
style="opacity:0;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline"
id="rect45264"
@@ -76008,7 +78153,7 @@
sodipodi:cy="118"
sodipodi:rx="8"
sodipodi:ry="8"
- d="m 139.98403,118.50525 c -0.27904,4.40946 -4.07982,7.75782 -8.48928,7.47878 -4.40946,-0.27904 -7.75782,-4.07982 -7.47878,-8.48928 0.25664,-4.05547 3.51283,-7.27428 7.571,-7.48408"
+ d="m 139.98403,118.50525 a 8,8 0 0 1 -8.18333,7.49227 8,8 0 0 1 -7.79999,-7.89057 8,8 0 0 1 7.58626,-8.09628"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90"
@@ -76020,7 +78165,7 @@
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
- d="m 139.98403,118.50525 c -0.27904,4.40946 -4.07982,7.75782 -8.48928,7.47878 -4.40946,-0.27904 -7.75782,-4.07982 -7.47878,-8.48928 0.25664,-4.05547 3.51283,-7.27428 7.571,-7.48408"
+ d="m 139.98403,118.50525 a 8,8 0 0 1 -8.18333,7.49227 8,8 0 0 1 -7.79999,-7.89057 8,8 0 0 1 7.58626,-8.09628"
sodipodi:ry="8"
sodipodi:rx="8"
sodipodi:cy="118"
@@ -76040,7 +78185,7 @@
sodipodi:cy="118"
sodipodi:rx="8"
sodipodi:ry="8"
- d="m 139.98403,118.50525 c -0.27904,4.40946 -4.07982,7.75782 -8.48928,7.47878 -4.40946,-0.27904 -7.75782,-4.07982 -7.47878,-8.48928 0.25664,-4.05547 3.51283,-7.27428 7.571,-7.48408"
+ d="m 139.98403,118.50525 a 8,8 0 0 1 -8.18333,7.49227 8,8 0 0 1 -7.79999,-7.89057 8,8 0 0 1 7.58626,-8.09628"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90"
@@ -76053,7 +78198,7 @@
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
- d="m 139.98403,118.50525 c -0.27904,4.40946 -4.07982,7.75782 -8.48928,7.47878 -4.40946,-0.27904 -7.75782,-4.07982 -7.47878,-8.48928 0.25664,-4.05547 3.51283,-7.27428 7.571,-7.48408"
+ d="m 139.98403,118.50525 a 8,8 0 0 1 -8.18333,7.49227 8,8 0 0 1 -7.79999,-7.89057 8,8 0 0 1 7.58626,-8.09628"
sodipodi:ry="8"
sodipodi:rx="8"
sodipodi:cy="118"
@@ -76073,7 +78218,7 @@
<g
style="display:inline;enable-background:new"
transform="translate(517.99163,649)"
- id="g45287">
+ id="ICON_FILE_TICK">
<path
sodipodi:nodetypes="cccccccc"
d="m -120.49163,-67.5 c -3.75159,0.954856 -7.20393,6.261452 -9,9 l -3.5,-3.5 -0.25,0.5 3.99163,4 0.5,0 c 1.0421,-2.617689 4.16191,-8.585412 8.25837,-10 l 0,0 z"
@@ -76094,7 +78239,7 @@
inkscape:connector-curvature="0" />
</g>
<g
- id="g42952"
+ id="ICON_GROUP"
style="display:inline;enable-background:new"
transform="translate(433,-61)">
<rect
@@ -76191,7 +78336,7 @@
sodipodi:cy="118"
sodipodi:rx="8"
sodipodi:ry="8"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90" />
@@ -76200,7 +78345,7 @@
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
sodipodi:ry="8"
sodipodi:rx="8"
sodipodi:cy="118"
@@ -76212,7 +78357,7 @@
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
sodipodi:ry="8"
sodipodi:rx="8"
sodipodi:cy="118"
@@ -76229,7 +78374,7 @@
inkscape:connector-curvature="0" />
</g>
<g
- id="g43828">
+ id="ICON_LIBRARY_DATA_DIRECT">
<g
transform="translate(0,128)"
id="g24024">
@@ -76290,7 +78435,7 @@
inkscape:connector-curvature="0" />
</g>
<g
- id="g43838"
+ id="ICON_LIBRARY_DATA_INDIRECT"
transform="translate(0,-21)"
style="opacity:0.4">
<g
@@ -76353,12 +78498,7 @@
inkscape:connector-curvature="0" />
</g>
<g
- id="g46790"
- transform="translate(0,12)" />
- <g
- id="g46890" />
- <g
- id="g46912"
+ id="ICON_PARTICLE_TIP"
transform="translate(547.9924,59.00343)"
inkscape:export-filename="C:\Documents and Settings\Pracownia\Moje dokumenty\Moje obrazy\BLENDER ICONS redesign\ver 3\strands selection modes.png"
inkscape:export-xdpi="90"
@@ -76458,7 +78598,7 @@
</g>
</g>
<g
- id="g46928"
+ id="ICON_PARTICLE_POINT"
transform="translate(547.9924,59.00343)"
inkscape:export-filename="C:\Documents and Settings\Pracownia\Moje dokumenty\Moje obrazy\BLENDER ICONS redesign\ver 3\strands selection modes.png"
inkscape:export-xdpi="90"
@@ -76580,7 +78720,7 @@
</g>
</g>
<g
- id="g46958"
+ id="ICON_PARTICLE_PATH"
transform="translate(547.9924,59.00343)"
inkscape:export-filename="C:\Documents and Settings\Pracownia\Moje dokumenty\Moje obrazy\BLENDER ICONS redesign\ver 3\strands selection modes.png"
inkscape:export-xdpi="90"
@@ -76694,7 +78834,7 @@
</g>
<g
transform="translate(-1,0)"
- id="g24914">
+ id="ICON_CONSTRAINT_BONE">
<g
id="g25430"
transform="translate(0,-21)">
@@ -76816,7 +78956,7 @@
</g>
<g
transform="translate(0.00572791,126.98898)"
- id="g25026">
+ id="ICON_CONSTRAINT">
<rect
y="403.99695"
x="-382.01102"
@@ -76894,7 +79034,7 @@
</g>
</g>
<g
- id="g23496"
+ id="ICON_LOOP_FORWARDS"
transform="matrix(-1,0,0,1,614,0)">
<rect
transform="matrix(0,1,1,0,0,0)"
@@ -76985,7 +79125,7 @@
</g>
</g>
<g
- id="g23511"
+ id="ICON_LOOP_BACK"
transform="translate(-21,0)">
<rect
style="opacity:0;fill:#1a1a1a;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.20000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
@@ -77064,30 +79204,8 @@
</g>
</g>
<g
- style="display:inline;enable-background:new"
- id="g21623-4"
- transform="translate(-83.999976,274.99821)">
- <g
- transform="matrix(0.9999986,0,0,1,-170.19957,169.98079)"
- id="g10260-6">
- <g
- transform="translate(39.10005,-0.04905017)"
- id="g10262-3">
- <rect
- y="6.0700502"
- x="325.10001"
- height="15.979"
- width="16.000025"
- id="rect10264-4"
- style="opacity:0;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" />
- </g>
- <g
- id="g10266-9" />
- </g>
- </g>
- <g
transform="matrix(-1,0,0,1,209,550)"
- id="g27862"
+ id="ICON_TRIA_LEFT"
style="display:inline">
<rect
y="69"
@@ -77119,7 +79237,7 @@
</g>
<g
transform="matrix(1,0,0,-1,70,704.00001)"
- id="g27876"
+ id="ICON_TRIA_UP"
style="display:inline">
<rect
y="69"
@@ -77151,7 +79269,7 @@
</g>
<g
transform="translate(-231,-21)"
- id="g29960"
+ id="ICON_MOD_MIRROR"
inkscape:export-filename="C:\Documents and Settings\Pracownia\Moje dokumenty\Moje obrazy\BLENDER ICONS redesign\ver 3\screw modifier.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90">
@@ -77211,7 +79329,7 @@
sodipodi:cy="118"
sodipodi:rx="8"
sodipodi:ry="8"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90" />
@@ -77220,7 +79338,7 @@
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
sodipodi:ry="8"
sodipodi:rx="8"
sodipodi:cy="118"
@@ -77239,7 +79357,7 @@
sodipodi:cy="118"
sodipodi:rx="8"
sodipodi:ry="8"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
transform="matrix(0.5705005,0,0,0.5705012,51.746079,156.18087)" />
</g>
<g
@@ -77253,7 +79371,7 @@
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
sodipodi:ry="8"
sodipodi:rx="8"
sodipodi:cy="118"
@@ -77270,14 +79388,14 @@
sodipodi:cy="118"
sodipodi:rx="8"
sodipodi:ry="8"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90"
transform="matrix(-0.683022,-0.07745026,0.0778507,-0.683064,209.4726,314.325)" />
<path
transform="matrix(0.5705005,0,0,0.5705012,53.193935,156.18087)"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
sodipodi:ry="8"
sodipodi:rx="8"
sodipodi:cy="118"
@@ -77291,7 +79409,7 @@
</g>
</g>
<g
- id="g29313"
+ id="ICON_PROP_OFF"
transform="translate(-21,2)"
style="opacity:0.5">
<rect
@@ -77316,7 +79434,7 @@
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
sodipodi:ry="8"
sodipodi:rx="8"
sodipodi:cy="118"
@@ -77333,7 +79451,7 @@
sodipodi:cy="118"
sodipodi:rx="8"
sodipodi:ry="8"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90" />
@@ -77347,7 +79465,7 @@
sodipodi:cy="118"
sodipodi:rx="8"
sodipodi:ry="8"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90" />
@@ -77355,7 +79473,7 @@
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
sodipodi:ry="8"
sodipodi:rx="8"
sodipodi:cy="118"
@@ -77368,7 +79486,7 @@
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
sodipodi:ry="8"
sodipodi:rx="8"
sodipodi:cy="118"
@@ -77379,287 +79497,274 @@
transform="matrix(0.424906,0,0,-0.424074,114.01316,85.183325)" />
</g>
</g>
- <rect
- transform="matrix(0,1,-1,0,0,0)"
- y="-252"
- x="52"
- height="16"
- width="16"
- id="rect28680"
- style="opacity:0;fill:#1a1a1a;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.20000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
<g
- transform="translate(97.00005,0)"
- id="g32009">
+ transform="translate(2.00005,151)"
+ id="ICON_MAN_TRANS"
+ style="display:inline">
+ <rect
+ y="6"
+ x="3"
+ height="16"
+ width="16"
+ id="rect32013"
+ style="opacity:0;fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
<g
style="display:inline"
- id="g32011"
- transform="translate(-95,151)">
- <rect
- style="opacity:0;fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- id="rect32013"
- width="16"
- height="16"
- x="3"
- y="6" />
- <g
- transform="translate(64,9.999984)"
- id="g32015"
- style="display:inline">
- <path
- sodipodi:nodetypes="cccc"
- id="path32032"
- d="M -55,1 -47.000051,-1.999984 -50,6 -55,1 z"
- style="fill:none;stroke:#002255;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
- inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
- inkscape:export-xdpi="90"
- inkscape:export-ydpi="90"
- inkscape:connector-curvature="0" />
- <path
- style="fill:none;stroke:#002255;stroke-width:3.70000005;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
- d="M -58.250048,9.250016 -50,0.999884"
- id="path32044"
- sodipodi:nodetypes="cc"
- inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
- inkscape:export-xdpi="90"
- inkscape:export-ydpi="90"
- inkscape:connector-curvature="0" />
- <path
- sodipodi:nodetypes="cc"
- id="path32050"
- d="M -58.250048,9.250016 -50,0.999884"
- style="fill:none;stroke:#4989e9;stroke-width:1.89999998;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
- inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
- inkscape:export-xdpi="90"
- inkscape:export-ydpi="90"
- inkscape:connector-curvature="0" />
- <path
- style="opacity:0.5;fill:none;stroke:url(#linearGradient32140);stroke-width:1.89999998;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
- d="m -58,8.999884 8,-8"
- id="path32055"
- sodipodi:nodetypes="cc"
- inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
- inkscape:export-xdpi="90"
- inkscape:export-ydpi="90"
- inkscape:connector-curvature="0" />
- <path
- style="fill:#4989e9;fill-opacity:1;fill-rule:evenodd;stroke:none"
- d="M -55,1 -47.000051,-1.999984 -50,6 -55,1 z"
- id="path32057"
- sodipodi:nodetypes="cccc"
- inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
- inkscape:export-xdpi="90"
- inkscape:export-ydpi="90"
- inkscape:connector-curvature="0" />
- <path
- sodipodi:nodetypes="cccc"
- id="path32059"
- d="M -55,1 -47.000051,-1.999984 -50,6 -55,1 z"
- style="opacity:0.5;fill:url(#linearGradient32142);fill-opacity:1;fill-rule:evenodd;stroke:none"
- inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
- inkscape:export-xdpi="90"
- inkscape:export-ydpi="90"
- inkscape:connector-curvature="0" />
- <path
- style="fill:none;stroke:#ffffff;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
- d="M -47.25,-1.75 -54.75,1"
- id="path32063"
- sodipodi:nodetypes="cc"
- inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
- inkscape:export-xdpi="90"
- inkscape:export-ydpi="90"
- inkscape:connector-curvature="0" />
- <path
- sodipodi:nodetypes="cc"
- id="path32068"
- d="m -53,3 -5.750048,5.750016 0,0.75"
- style="fill:none;stroke:#ffffff;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
- inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
- inkscape:export-xdpi="90"
- inkscape:export-ydpi="90"
- inkscape:connector-curvature="0" />
- </g>
+ id="g32015"
+ transform="translate(64,9.999984)">
+ <path
+ inkscape:connector-curvature="0"
+ inkscape:export-ydpi="90"
+ inkscape:export-xdpi="90"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
+ style="fill:none;stroke:#002255;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="M -55,1 -47.000051,-1.999984 -50,6 -55,1 z"
+ id="path32032"
+ sodipodi:nodetypes="cccc" />
+ <path
+ inkscape:connector-curvature="0"
+ inkscape:export-ydpi="90"
+ inkscape:export-xdpi="90"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
+ sodipodi:nodetypes="cc"
+ id="path32044"
+ d="M -58.250048,9.250016 -50,0.999884"
+ style="fill:none;stroke:#002255;stroke-width:3.70000005;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+ <path
+ inkscape:connector-curvature="0"
+ inkscape:export-ydpi="90"
+ inkscape:export-xdpi="90"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
+ style="fill:none;stroke:#4989e9;stroke-width:1.89999998;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="M -58.250048,9.250016 -50,0.999884"
+ id="path32050"
+ sodipodi:nodetypes="cc" />
+ <path
+ inkscape:connector-curvature="0"
+ inkscape:export-ydpi="90"
+ inkscape:export-xdpi="90"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
+ sodipodi:nodetypes="cc"
+ id="path32055"
+ d="m -58,8.999884 8,-8"
+ style="opacity:0.5;fill:none;stroke:url(#linearGradient32140);stroke-width:1.89999998;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+ <path
+ inkscape:connector-curvature="0"
+ inkscape:export-ydpi="90"
+ inkscape:export-xdpi="90"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
+ sodipodi:nodetypes="cccc"
+ id="path32057"
+ d="M -55,1 -47.000051,-1.999984 -50,6 -55,1 z"
+ style="fill:#4989e9;fill-opacity:1;fill-rule:evenodd;stroke:none" />
+ <path
+ inkscape:connector-curvature="0"
+ inkscape:export-ydpi="90"
+ inkscape:export-xdpi="90"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
+ style="opacity:0.5;fill:url(#linearGradient32142);fill-opacity:1;fill-rule:evenodd;stroke:none"
+ d="M -55,1 -47.000051,-1.999984 -50,6 -55,1 z"
+ id="path32059"
+ sodipodi:nodetypes="cccc" />
+ <path
+ inkscape:connector-curvature="0"
+ inkscape:export-ydpi="90"
+ inkscape:export-xdpi="90"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
+ sodipodi:nodetypes="cc"
+ id="path32063"
+ d="M -47.25,-1.75 -54.75,1"
+ style="fill:none;stroke:#ffffff;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+ <path
+ inkscape:connector-curvature="0"
+ inkscape:export-ydpi="90"
+ inkscape:export-xdpi="90"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
+ style="fill:none;stroke:#ffffff;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m -53,3 -5.750048,5.750016 0,0.75"
+ id="path32068"
+ sodipodi:nodetypes="cc" />
</g>
+ </g>
+ <g
+ transform="translate(4.000002,151)"
+ id="ICON_MAN_SCALE"
+ style="display:inline">
+ <rect
+ y="6"
+ x="43"
+ height="16"
+ width="16"
+ id="rect32072"
+ style="opacity:0;fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
<g
style="display:inline"
- id="g32070"
- transform="translate(-93.000048,151)">
- <rect
- style="opacity:0;fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- id="rect32072"
- width="16"
- height="16"
- x="43"
- y="6" />
- <g
- transform="translate(64,10)"
- id="g32074"
- style="display:inline">
- <path
- sodipodi:nodetypes="cc"
- id="path32077"
- d="m -18.25,9.25 8.249996,-8.2304767"
- style="fill:none;stroke:#002255;stroke-width:3.70000005;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
- inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
- inkscape:export-xdpi="90"
- inkscape:export-ydpi="90"
- inkscape:connector-curvature="0" />
- <path
- style="fill:none;stroke:#002255;stroke-width:1.79999995;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
- d="m -12.999997,-2.000002 5.9999268,1.448e-4 6.72e-5,5.9998542 -6.000002,0 8e-6,-5.999999 0,0 0,0 0,0 z"
- id="path32079"
- sodipodi:nodetypes="ccccc"
- inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
- inkscape:export-xdpi="90"
- inkscape:export-ydpi="90"
- inkscape:connector-curvature="0" />
- <path
- style="fill:none;stroke:#4989e9;stroke-width:1.89999998;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
- d="m -18.25,9.25 8.249996,-8.24999"
- id="path32081"
- sodipodi:nodetypes="cc"
- inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
- inkscape:export-xdpi="90"
- inkscape:export-ydpi="90"
- inkscape:connector-curvature="0" />
- <path
- sodipodi:nodetypes="cc"
- id="path32087"
- d="m -18.000004,9.00001 8,-8"
- style="opacity:0.5;fill:none;stroke:url(#linearGradient32144);stroke-width:1.89999998;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
- inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
- inkscape:export-xdpi="90"
- inkscape:export-ydpi="90"
- inkscape:connector-curvature="0" />
- <path
- sodipodi:nodetypes="ccccc"
- id="path32089"
- d="m -12.999992,-2 5.9999248,1.448e-4 L -7,4 l -6,0 8e-6,-6 z"
- style="fill:#4989e9;fill-opacity:1;fill-rule:evenodd;stroke:none"
- inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
- inkscape:export-xdpi="90"
- inkscape:export-ydpi="90"
- inkscape:connector-curvature="0" />
- <path
- style="opacity:0.5;fill:url(#linearGradient32146);fill-opacity:1;fill-rule:evenodd;stroke:none"
- d="m -12.999992,-2 5.9999248,1.452e-4 L -7,4 l -6,0 8e-6,-6 z"
- id="path32104"
- sodipodi:nodetypes="ccccc"
- inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
- inkscape:export-xdpi="90"
- inkscape:export-ydpi="90"
- inkscape:connector-curvature="0" />
- <path
- sodipodi:nodetypes="ccc"
- id="path32114"
- d="m -12.749999,2.750002 0,-4.4999957 5.4999946,0"
- style="fill:none;stroke:#ffffff;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
- inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
- inkscape:export-xdpi="90"
- inkscape:export-ydpi="90"
- inkscape:connector-curvature="0" />
- <path
- style="fill:none;stroke:#ffffff;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
- d="m -12.75,2.75 -6,6 0,0.75"
- id="path32118"
- sodipodi:nodetypes="cc"
- inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
- inkscape:export-xdpi="90"
- inkscape:export-ydpi="90"
- inkscape:connector-curvature="0" />
- </g>
+ id="g32074"
+ transform="translate(64,10)">
+ <path
+ inkscape:connector-curvature="0"
+ inkscape:export-ydpi="90"
+ inkscape:export-xdpi="90"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
+ style="fill:none;stroke:#002255;stroke-width:3.70000005;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m -18.25,9.25 8.249996,-8.2304767"
+ id="path32077"
+ sodipodi:nodetypes="cc" />
+ <path
+ inkscape:connector-curvature="0"
+ inkscape:export-ydpi="90"
+ inkscape:export-xdpi="90"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
+ sodipodi:nodetypes="ccccc"
+ id="path32079"
+ d="m -12.999997,-2.000002 5.9999268,1.448e-4 6.72e-5,5.9998542 -6.000002,0 8e-6,-5.999999 0,0 0,0 0,0 z"
+ style="fill:none;stroke:#002255;stroke-width:1.79999995;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+ <path
+ inkscape:connector-curvature="0"
+ inkscape:export-ydpi="90"
+ inkscape:export-xdpi="90"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
+ sodipodi:nodetypes="cc"
+ id="path32081"
+ d="m -18.25,9.25 8.249996,-8.24999"
+ style="fill:none;stroke:#4989e9;stroke-width:1.89999998;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+ <path
+ inkscape:connector-curvature="0"
+ inkscape:export-ydpi="90"
+ inkscape:export-xdpi="90"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
+ style="opacity:0.5;fill:none;stroke:url(#linearGradient32144);stroke-width:1.89999998;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m -18.000004,9.00001 8,-8"
+ id="path32087"
+ sodipodi:nodetypes="cc" />
+ <path
+ inkscape:connector-curvature="0"
+ inkscape:export-ydpi="90"
+ inkscape:export-xdpi="90"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
+ style="fill:#4989e9;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ d="m -12.999992,-2 5.9999248,1.448e-4 L -7,4 l -6,0 8e-6,-6 z"
+ id="path32089"
+ sodipodi:nodetypes="ccccc" />
+ <path
+ inkscape:connector-curvature="0"
+ inkscape:export-ydpi="90"
+ inkscape:export-xdpi="90"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
+ sodipodi:nodetypes="ccccc"
+ id="path32104"
+ d="m -12.999992,-2 5.9999248,1.452e-4 L -7,4 l -6,0 8e-6,-6 z"
+ style="opacity:0.5;fill:url(#linearGradient32146);fill-opacity:1;fill-rule:evenodd;stroke:none" />
+ <path
+ inkscape:connector-curvature="0"
+ inkscape:export-ydpi="90"
+ inkscape:export-xdpi="90"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
+ style="fill:none;stroke:#ffffff;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m -12.749999,2.750002 0,-4.4999957 5.4999946,0"
+ id="path32114"
+ sodipodi:nodetypes="ccc" />
+ <path
+ inkscape:connector-curvature="0"
+ inkscape:export-ydpi="90"
+ inkscape:export-xdpi="90"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
+ sodipodi:nodetypes="cc"
+ id="path32118"
+ d="m -12.75,2.75 -6,6 0,0.75"
+ style="fill:none;stroke:#ffffff;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
</g>
+ </g>
+ <g
+ id="ICON_MAN_ROT">
+ <rect
+ y="157"
+ x="26"
+ height="16"
+ width="16"
+ id="rect32122"
+ style="opacity:0;fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
<g
- id="g32120"
- transform="translate(-97.000051,0)">
- <rect
- style="opacity:0;fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- id="rect32122"
- width="16"
- height="16"
- x="26"
- y="157" />
- <g
- transform="matrix(0.9187785,0,0,0.9204344,64.322274,161.35151)"
- id="g32124"
- style="display:inline">
- <path
- sodipodi:open="true"
- inkscape:transform-center-y="-5.4395256"
- inkscape:transform-center-x="5.4369478"
- sodipodi:end="1.5729572"
- sodipodi:start="0"
- transform="matrix(-2.421633,0,0,-2.417581,92.2682,-69.13182)"
- d="m 54,-32.5 c 0,2.485281 -2.014719,4.5 -4.5,4.5 -0.0032,0 -0.0065,-4e-6 -0.0097,-1.1e-5"
- sodipodi:ry="4.5"
- sodipodi:rx="4.5"
- sodipodi:cy="-32.5"
- sodipodi:cx="49.5"
- id="path32126"
- style="fill:none;stroke:#002255;stroke-width:1.79768455;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0.5"
- sodipodi:type="arc"
- inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
- inkscape:export-xdpi="90"
- inkscape:export-ydpi="90" />
- <path
- sodipodi:type="arc"
- style="fill:none;stroke:#4989e9;stroke-width:0.9887265;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0.5"
- id="path32128"
- sodipodi:cx="49.5"
- sodipodi:cy="-32.5"
- sodipodi:rx="4.5"
- sodipodi:ry="4.5"
- d="m 54,-32.5 c 0,2.485281 -2.014719,4.5 -4.5,4.5 -0.0032,0 -0.0065,-4e-6 -0.0097,-1.1e-5"
- transform="matrix(-2.421633,0,0,-2.417581,92.2682,-69.13182)"
- sodipodi:start="0"
- sodipodi:end="1.5729572"
- inkscape:transform-center-x="5.4369478"
- inkscape:transform-center-y="-5.4395256"
- sodipodi:open="true"
- inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
- inkscape:export-xdpi="90"
- inkscape:export-ydpi="90" />
- <path
- sodipodi:open="true"
- inkscape:transform-center-y="-5.4395256"
- inkscape:transform-center-x="5.4369478"
- sodipodi:end="1.5729572"
- sodipodi:start="0"
- transform="matrix(-2.421633,0,0,-2.417581,92.2682,-69.13182)"
- d="m 54,-32.5 c 0,2.485281 -2.014719,4.5 -4.5,4.5 -0.0032,0 -0.0065,-4e-6 -0.0097,-1.1e-5"
- sodipodi:ry="4.5"
- sodipodi:rx="4.5"
- sodipodi:cy="-32.5"
- sodipodi:cx="49.5"
- id="path32136"
- style="opacity:0.5;fill:none;stroke:url(#linearGradient32148);stroke-width:0.9887265;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0.5"
- sodipodi:type="arc"
- inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
- inkscape:export-xdpi="90"
- inkscape:export-ydpi="90" />
- <path
- sodipodi:type="arc"
- style="fill:none;stroke:#ffffff;stroke-width:0.29357874;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0.5"
- id="path32138"
- sodipodi:cx="49.5"
- sodipodi:cy="-32.5"
- sodipodi:rx="4.5"
- sodipodi:ry="4.5"
- d="m 54,-32.5 c 0,2.485281 -2.014719,4.5 -4.5,4.5 -0.0032,0 -0.0065,-4e-6 -0.0097,-1.1e-5"
- transform="matrix(-2.587958,0,0,-2.597682,100.48861,-75.018268)"
- sodipodi:start="0"
- sodipodi:end="1.5729572"
- inkscape:transform-center-x="5.8103423"
- inkscape:transform-center-y="-5.8447483"
- sodipodi:open="true"
- inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
- inkscape:export-xdpi="90"
- inkscape:export-ydpi="90" />
- </g>
+ style="display:inline"
+ id="g32124"
+ transform="matrix(0.9187785,0,0,0.9204344,64.322274,161.35151)">
+ <path
+ inkscape:export-ydpi="90"
+ inkscape:export-xdpi="90"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
+ sodipodi:type="arc"
+ style="fill:none;stroke:#002255;stroke-width:1.79768455;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0.5"
+ id="path32126"
+ sodipodi:cx="49.5"
+ sodipodi:cy="-32.5"
+ sodipodi:rx="4.5"
+ sodipodi:ry="4.5"
+ d="m 54,-32.5 a 4.5,4.5 0 0 1 -1.321459,3.185417 4.5,4.5 0 0 1 -3.188265,1.314572"
+ transform="matrix(-2.421633,0,0,-2.417581,92.2682,-69.13182)"
+ sodipodi:start="0"
+ sodipodi:end="1.5729572"
+ inkscape:transform-center-x="5.4369478"
+ inkscape:transform-center-y="-5.4395256"
+ sodipodi:open="true" />
+ <path
+ inkscape:export-ydpi="90"
+ inkscape:export-xdpi="90"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
+ sodipodi:open="true"
+ inkscape:transform-center-y="-5.4395256"
+ inkscape:transform-center-x="5.4369478"
+ sodipodi:end="1.5729572"
+ sodipodi:start="0"
+ transform="matrix(-2.421633,0,0,-2.417581,92.2682,-69.13182)"
+ d="m 54,-32.5 a 4.5,4.5 0 0 1 -1.321459,3.185417 4.5,4.5 0 0 1 -3.188265,1.314572"
+ sodipodi:ry="4.5"
+ sodipodi:rx="4.5"
+ sodipodi:cy="-32.5"
+ sodipodi:cx="49.5"
+ id="path32128"
+ style="fill:none;stroke:#4989e9;stroke-width:0.9887265;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0.5"
+ sodipodi:type="arc" />
+ <path
+ inkscape:export-ydpi="90"
+ inkscape:export-xdpi="90"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
+ sodipodi:type="arc"
+ style="opacity:0.5;fill:none;stroke:url(#linearGradient32148);stroke-width:0.9887265;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0.5"
+ id="path32136"
+ sodipodi:cx="49.5"
+ sodipodi:cy="-32.5"
+ sodipodi:rx="4.5"
+ sodipodi:ry="4.5"
+ d="m 54,-32.5 a 4.5,4.5 0 0 1 -1.321459,3.185417 4.5,4.5 0 0 1 -3.188265,1.314572"
+ transform="matrix(-2.421633,0,0,-2.417581,92.2682,-69.13182)"
+ sodipodi:start="0"
+ sodipodi:end="1.5729572"
+ inkscape:transform-center-x="5.4369478"
+ inkscape:transform-center-y="-5.4395256"
+ sodipodi:open="true" />
+ <path
+ inkscape:export-ydpi="90"
+ inkscape:export-xdpi="90"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
+ sodipodi:open="true"
+ inkscape:transform-center-y="-5.8447483"
+ inkscape:transform-center-x="5.8103423"
+ sodipodi:end="1.5729572"
+ sodipodi:start="0"
+ transform="matrix(-2.587958,0,0,-2.597682,100.48861,-75.018268)"
+ d="m 54,-32.5 a 4.5,4.5 0 0 1 -1.321459,3.185417 4.5,4.5 0 0 1 -3.188265,1.314572"
+ sodipodi:ry="4.5"
+ sodipodi:rx="4.5"
+ sodipodi:cy="-32.5"
+ sodipodi:cx="49.5"
+ id="path32138"
+ style="fill:none;stroke:#ffffff;stroke-width:0.29357874;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0.5"
+ sodipodi:type="arc" />
</g>
</g>
<g
transform="translate(315,-441)"
- id="g31816">
+ id="ICON_SORTSIZE">
<rect
style="opacity:0;color:#000000;fill:#ff0000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:3.5999999;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
id="rect31818"
@@ -77739,7 +79844,7 @@
</g>
</g>
<g
- id="g31846"
+ id="ICON_SORTALPHA"
transform="translate(191,-420)"
inkscape:export-filename="C:\Documents and Settings\Pracownia\Moje dokumenty\Moje obrazy\BLENDER ICONS redesign\ver 3\sort a-z.png"
inkscape:export-xdpi="90"
@@ -77809,7 +79914,7 @@
inkscape:connector-curvature="0" />
</g>
<g
- id="g31883"
+ id="ICON_SORTTIME"
transform="translate(189,-315)">
<g
style="opacity:0.96000001;display:inline;enable-background:new"
@@ -78004,7 +80109,7 @@
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Pracownia\Moje dokumenty\Moje obrazy\BLENDER ICONS redesign\ver 3\screw modifier.png"
transform="translate(-105,-42)"
- id="g31976">
+ id="ICON_MOD_SCREW">
<rect
y="283"
x="236"
@@ -78087,7 +80192,7 @@
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Pracownia\Moje dokumenty\Moje obrazy\BLENDER ICONS redesign\ver 3\sequencer + image preview.png"
- id="g32260"
+ id="ICON_SEQ_SPLITVIEW"
transform="translate(147,0)">
<g
style="display:inline;enable-background:new"
@@ -78196,7 +80301,7 @@
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Pracownia\Moje dokumenty\Moje obrazy\BLENDER ICONS redesign\ver 3\mysterious PR.png"
transform="translate(-118,-465)"
- id="g32309">
+ id="ICON_PREVIEW_RANGE">
<rect
style="opacity:0;fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
id="rect32311"
@@ -78217,7 +80322,7 @@
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
sodipodi:ry="8"
sodipodi:rx="8"
sodipodi:cy="118"
@@ -78231,7 +80336,7 @@
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
sodipodi:ry="8"
sodipodi:rx="8"
sodipodi:cy="118"
@@ -78321,7 +80426,7 @@
sodipodi:cy="118"
sodipodi:rx="8"
sodipodi:ry="8"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90" />
@@ -78332,7 +80437,7 @@
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Pracownia\Moje dokumenty\Moje obrazy\BLENDER ICONS redesign\ver 3\recently used.png"
transform="translate(32,-86.95)"
- id="g32361">
+ id="ICON_RECOVER_LAST">
<rect
y="664"
x="414"
@@ -78357,7 +80462,7 @@
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
sodipodi:ry="8"
sodipodi:rx="8"
sodipodi:cy="118"
@@ -78383,7 +80488,7 @@
sodipodi:cy="118"
sodipodi:rx="8"
sodipodi:ry="8"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90" />
@@ -78520,7 +80625,7 @@
</g>
<g
transform="translate(0,2)"
- id="g31005">
+ id="ICON_KEY_HLT">
<rect
style="opacity:0;fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
id="rect31007"
@@ -78563,7 +80668,7 @@
</g>
<path
transform="matrix(1.4399775,0,0,1.4399775,-171.50748,-44.947546)"
- d="m 388.20316,122.5078 c 0,0.39264 -0.3148,0.71093 -0.70313,0.71093 -0.38832,0 -0.70312,-0.31829 -0.70312,-0.71093 0,-0.39264 0.3148,-0.71094 0.70312,-0.71094 0.38833,0 0.70313,0.3183 0.70313,0.71094 z"
+ d="m 388.20316,122.5078 a 0.70312506,0.71093756 0 0 1 -0.70313,0.71093 0.70312506,0.71093756 0 0 1 -0.70312,-0.71093 0.70312506,0.71093756 0 0 1 0.70312,-0.71094 0.70312506,0.71093756 0 0 1 0.70313,0.71094 z"
sodipodi:ry="0.71093756"
sodipodi:rx="0.70312506"
sodipodi:cy="122.5078"
@@ -78574,7 +80679,7 @@
</g>
</g>
<g
- id="g31159">
+ id="ICON_KEY_DEHLT">
<g
style="opacity:0.8"
transform="translate(-21,2)"
@@ -78621,7 +80726,7 @@
</g>
<path
transform="matrix(1.4399775,0,0,1.4399775,-171.50748,-44.947546)"
- d="m 388.20316,122.5078 c 0,0.39264 -0.3148,0.71093 -0.70313,0.71093 -0.38832,0 -0.70312,-0.31829 -0.70312,-0.71093 0,-0.39264 0.3148,-0.71094 0.70312,-0.71094 0.38833,0 0.70313,0.3183 0.70313,0.71094 z"
+ d="m 388.20316,122.5078 a 0.70312506,0.71093756 0 0 1 -0.70313,0.71093 0.70312506,0.71093756 0 0 1 -0.70312,-0.71093 0.70312506,0.71093756 0 0 1 0.70312,-0.71094 0.70312506,0.71093756 0 0 1 0.70313,0.71094 z"
sodipodi:ry="0.71093756"
sodipodi:rx="0.70312506"
sodipodi:cy="122.5078"
@@ -78649,7 +80754,7 @@
</g>
</g>
<g
- id="g31133"
+ id="ICON_KEYINGSET"
transform="translate(0,-21)">
<rect
y="241"
@@ -78699,7 +80804,7 @@
sodipodi:cy="122.5078"
sodipodi:rx="0.70312506"
sodipodi:ry="0.71093756"
- d="m 388.20316,122.5078 c 0,0.39264 -0.3148,0.71093 -0.70313,0.71093 -0.38832,0 -0.70312,-0.31829 -0.70312,-0.71093 0,-0.39264 0.3148,-0.71094 0.70312,-0.71094 0.38833,0 0.70313,0.3183 0.70313,0.71094 z"
+ d="m 388.20316,122.5078 a 0.70312506,0.71093756 0 0 1 -0.70313,0.71093 0.70312506,0.71093756 0 0 1 -0.70312,-0.71093 0.70312506,0.71093756 0 0 1 0.70312,-0.71094 0.70312506,0.71093756 0 0 1 0.70313,0.71094 z"
transform="matrix(1.4399775,0,0,1.4399775,-171.50748,-44.947546)" />
</g>
<path
@@ -78744,7 +80849,7 @@
sodipodi:cy="122.5078"
sodipodi:rx="0.70312506"
sodipodi:ry="0.71093756"
- d="m 388.20316,122.5078 c 0,0.39264 -0.3148,0.71093 -0.70313,0.71093 -0.38832,0 -0.70312,-0.31829 -0.70312,-0.71093 0,-0.39264 0.3148,-0.71094 0.70312,-0.71094 0.38833,0 0.70313,0.3183 0.70313,0.71094 z"
+ d="m 388.20316,122.5078 a 0.70312506,0.71093756 0 0 1 -0.70313,0.71093 0.70312506,0.71093756 0 0 1 -0.70312,-0.71093 0.70312506,0.71093756 0 0 1 0.70312,-0.71094 0.70312506,0.71093756 0 0 1 0.70313,0.71094 z"
transform="matrix(1.7719122,0,0,1.7719122,-300.13217,-85.612134)" />
<path
sodipodi:nodetypes="czzzz"
@@ -78756,15 +80861,9 @@
</g>
</g>
</g>
- <path
- inkscape:connector-curvature="0"
- d=""
- style="fill:none;stroke:#ffffff;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- id="path34332"
- sodipodi:nodetypes="cc" />
<g
style="display:inline;enable-background:new"
- id="g40603-2-4"
+ id="ICON_CLIP"
transform="translate(448,657)">
<rect
y="-122"
@@ -78912,7 +81011,7 @@
</g>
<g
style="display:inline;enable-background:new"
- id="g55801">
+ id="ICON_LINK_BLEND">
<rect
style="opacity:0;fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
id="rect26258-7"
@@ -78933,7 +81032,7 @@
inkscape:connector-curvature="0" />
<path
transform="matrix(3.625,0,0,3.1690202,-67.8125,318.31703)"
- d="m 14.5,57.5 c 0,0.552285 -0.447715,1 -1,1 -0.552285,0 -1,-0.447715 -1,-1 0,-0.552285 0.447715,-1 1,-1 0.552285,0 1,0.447715 1,1 z"
+ d="m 14.5,57.5 a 1,1.0000004 0 0 1 -1,1 1,1.0000004 0 0 1 -1,-1 1,1.0000004 0 0 1 1,-1 1,1.0000004 0 0 1 1,1 z"
sodipodi:ry="1.0000004"
sodipodi:rx="1"
sodipodi:cy="57.5"
@@ -78950,7 +81049,7 @@
</g>
<path
transform="matrix(3.5999897,0,0,3.1249932,-67.499871,320.6879)"
- d="m 14.5,57.5 c 0,0.552285 -0.447715,1 -1,1 -0.552285,0 -1,-0.447715 -1,-1 0,-0.552285 0.447715,-1 1,-1 0.552285,0 1,0.447715 1,1 z"
+ d="m 14.5,57.5 a 1,1 0 0 1 -1,1 1,1 0 0 1 -1,-1 1,1 0 0 1 1,-1 1,1 0 0 1 1,1 z"
sodipodi:ry="1"
sodipodi:rx="1"
sodipodi:cy="57.5"
@@ -78972,11 +81071,11 @@
sodipodi:cy="57.5"
sodipodi:rx="1"
sodipodi:ry="1"
- d="m 14.5,57.5 c 0,0.552285 -0.447715,1 -1,1 -0.552285,0 -1,-0.447715 -1,-1 0,-0.552285 0.447715,-1 1,-1 0.552285,0 1,0.447715 1,1 z"
+ d="m 14.5,57.5 a 1,1 0 0 1 -1,1 1,1 0 0 1 -1,-1 1,1 0 0 1 1,-1 1,1 0 0 1 1,1 z"
transform="matrix(3.25,0,0,3.25,-62.875,313.125)" />
<path
transform="matrix(2,0,0,2,-46,385)"
- d="m 14.5,57.5 c 0,0.552285 -0.447715,1 -1,1 -0.552285,0 -1,-0.447715 -1,-1 0,-0.552285 0.447715,-1 1,-1 0.552285,0 1,0.447715 1,1 z"
+ d="m 14.5,57.5 a 1,1 0 0 1 -1,1 1,1 0 0 1 -1,-1 1,1 0 0 1 1,-1 1,1 0 0 1 1,1 z"
sodipodi:ry="1"
sodipodi:rx="1"
sodipodi:cy="57.5"
@@ -78992,7 +81091,7 @@
sodipodi:cy="57.5"
sodipodi:rx="1"
sodipodi:ry="1"
- d="m 14.5,57.5 c 0,0.552285 -0.447715,1 -1,1 -0.552285,0 -1,-0.447715 -1,-1 0,-0.552285 0.447715,-1 1,-1 0.552285,0 1,0.447715 1,1 z"
+ d="m 14.5,57.5 a 1,1 0 0 1 -1,1 1,1 0 0 1 -1,-1 1,1 0 0 1 1,-1 1,1 0 0 1 1,1 z"
transform="matrix(4.7519907,0,0,4.1435313,-83.051884,262.12196)" />
<path
sodipodi:nodetypes="cccccc"
@@ -79050,7 +81149,7 @@
</g>
<g
style="display:inline;enable-background:new"
- id="g55835">
+ id="ICON_APPEND_BLEND">
<rect
style="opacity:0;fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
id="rect26258-7-4"
@@ -79071,7 +81170,7 @@
inkscape:connector-curvature="0" />
<path
transform="matrix(3.625,0,0,3.1690202,-67.8125,318.31703)"
- d="m 14.5,57.5 c 0,0.552285 -0.447715,1 -1,1 -0.552285,0 -1,-0.447715 -1,-1 0,-0.552285 0.447715,-1 1,-1 0.552285,0 1,0.447715 1,1 z"
+ d="m 14.5,57.5 a 1,1.0000004 0 0 1 -1,1 1,1.0000004 0 0 1 -1,-1 1,1.0000004 0 0 1 1,-1 1,1.0000004 0 0 1 1,1 z"
sodipodi:ry="1.0000004"
sodipodi:rx="1"
sodipodi:cy="57.5"
@@ -79088,7 +81187,7 @@
</g>
<path
transform="matrix(3.5999897,0,0,3.1249932,-67.499871,320.6879)"
- d="m 14.5,57.5 c 0,0.552285 -0.447715,1 -1,1 -0.552285,0 -1,-0.447715 -1,-1 0,-0.552285 0.447715,-1 1,-1 0.552285,0 1,0.447715 1,1 z"
+ d="m 14.5,57.5 a 1,1 0 0 1 -1,1 1,1 0 0 1 -1,-1 1,1 0 0 1 1,-1 1,1 0 0 1 1,1 z"
sodipodi:ry="1"
sodipodi:rx="1"
sodipodi:cy="57.5"
@@ -79110,11 +81209,11 @@
sodipodi:cy="57.5"
sodipodi:rx="1"
sodipodi:ry="1"
- d="m 14.5,57.5 c 0,0.552285 -0.447715,1 -1,1 -0.552285,0 -1,-0.447715 -1,-1 0,-0.552285 0.447715,-1 1,-1 0.552285,0 1,0.447715 1,1 z"
+ d="m 14.5,57.5 a 1,1 0 0 1 -1,1 1,1 0 0 1 -1,-1 1,1 0 0 1 1,-1 1,1 0 0 1 1,1 z"
transform="matrix(3.25,0,0,3.25,-62.875,313.125)" />
<path
transform="matrix(2,0,0,2,-46,385)"
- d="m 14.5,57.5 c 0,0.552285 -0.447715,1 -1,1 -0.552285,0 -1,-0.447715 -1,-1 0,-0.552285 0.447715,-1 1,-1 0.552285,0 1,0.447715 1,1 z"
+ d="m 14.5,57.5 a 1,1 0 0 1 -1,1 1,1 0 0 1 -1,-1 1,1 0 0 1 1,-1 1,1 0 0 1 1,1 z"
sodipodi:ry="1"
sodipodi:rx="1"
sodipodi:cy="57.5"
@@ -79130,7 +81229,7 @@
sodipodi:cy="57.5"
sodipodi:rx="1"
sodipodi:ry="1"
- d="m 14.5,57.5 c 0,0.552285 -0.447715,1 -1,1 -0.552285,0 -1,-0.447715 -1,-1 0,-0.552285 0.447715,-1 1,-1 0.552285,0 1,0.447715 1,1 z"
+ d="m 14.5,57.5 a 1,1 0 0 1 -1,1 1,1 0 0 1 -1,-1 1,1 0 0 1 1,-1 1,1 0 0 1 1,1 z"
transform="matrix(4.7519907,0,0,4.1435313,-83.051884,262.12196)" />
<path
sodipodi:nodetypes="cccccc"
@@ -79248,7 +81347,7 @@
</g>
<g
style="display:inline;enable-background:new"
- id="g55731">
+ id="ICON_SAVE_PREFS">
<rect
y="51.97921"
x="25.950649"
@@ -79362,7 +81461,7 @@
</g>
<g
style="display:inline;enable-background:new"
- id="g55696">
+ id="ICON_RECOVER_AUTO">
<rect
transform="scale(-1,-1)"
style="opacity:0;fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
@@ -79472,7 +81571,7 @@
</g>
<g
style="display:inline;enable-background:new"
- id="g17770">
+ id="ICON_IMPORT">
<rect
y="51.979202"
x="88.95063"
@@ -79567,7 +81666,7 @@
sodipodi:cy="118"
sodipodi:rx="8"
sodipodi:ry="8"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90" />
@@ -79575,7 +81674,7 @@
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
sodipodi:ry="8"
sodipodi:rx="8"
sodipodi:cy="118"
@@ -79589,7 +81688,7 @@
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
sodipodi:ry="8"
sodipodi:rx="8"
sodipodi:cy="118"
@@ -79659,7 +81758,7 @@
</g>
<g
style="display:inline;enable-background:new"
- id="g56020">
+ id="ICON_EXPORT">
<g
transform="translate(-28.94936,-39.370919)"
id="g42956-6-7">
@@ -79747,7 +81846,7 @@
sodipodi:cy="118"
sodipodi:rx="8"
sodipodi:ry="8"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90" />
@@ -79755,7 +81854,7 @@
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
sodipodi:ry="8"
sodipodi:rx="8"
sodipodi:cy="118"
@@ -79769,7 +81868,7 @@
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
sodipodi:ry="8"
sodipodi:rx="8"
sodipodi:cy="118"
@@ -79839,7 +81938,7 @@
</g>
<g
style="display:inline;enable-background:new"
- id="g56270">
+ id="ICON_EXTERNAL_DATA">
<rect
style="opacity:0;fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
id="rect29107-06"
@@ -79903,7 +82002,7 @@
sodipodi:cy="420.25"
sodipodi:rx="2.5"
sodipodi:ry="1.75"
- d="m 751.5,420.25 c 0,0.9665 -1.11929,1.75 -2.5,1.75 -1.38071,0 -2.5,-0.7835 -2.5,-1.75 0,-0.9665 1.11929,-1.75 2.5,-1.75 1.38071,0 2.5,0.7835 2.5,1.75 z"
+ d="m 751.5,420.25 a 2.5,1.75 0 0 1 -2.5,1.75 2.5,1.75 0 0 1 -2.5,-1.75 2.5,1.75 0 0 1 2.5,-1.75 2.5,1.75 0 0 1 2.5,1.75 z"
transform="matrix(1,0,0,0.8571429,-212,-302.2143)" />
<rect
style="fill:#66ff00;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
@@ -80129,7 +82228,7 @@
</g>
<g
style="display:inline;enable-background:new"
- id="g56314">
+ id="ICON_LOAD_FACTORY">
<rect
style="opacity:0;fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
id="rect29107-4"
@@ -80193,7 +82292,7 @@
sodipodi:cy="420.25"
sodipodi:rx="2.5"
sodipodi:ry="1.75"
- d="m 751.5,420.25 c 0,0.9665 -1.11929,1.75 -2.5,1.75 -1.38071,0 -2.5,-0.7835 -2.5,-1.75 0,-0.9665 1.11929,-1.75 2.5,-1.75 1.38071,0 2.5,0.7835 2.5,1.75 z"
+ d="m 751.5,420.25 a 2.5,1.75 0 0 1 -2.5,1.75 2.5,1.75 0 0 1 -2.5,-1.75 2.5,1.75 0 0 1 2.5,-1.75 2.5,1.75 0 0 1 2.5,1.75 z"
transform="matrix(1,0,0,0.8571429,-212,-302.2143)" />
<rect
style="fill:#66ff00;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
@@ -80281,7 +82380,7 @@
</g>
<g
style="display:inline;enable-background:new"
- id="g56410">
+ id="ICON_SAVE_COPY">
<g
transform="translate(190.95065,3.97921)"
id="g18875-2"
@@ -80370,7 +82469,7 @@
</g>
<g
style="display:inline;enable-background:new"
- id="g56383">
+ id="ICON_SAVE_AS">
<rect
style="opacity:0;color:#000000;fill:#808080;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:3.5999999;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
id="rect31818-2"
@@ -80460,7 +82559,7 @@
</g>
<g
style="display:inline;enable-background:new"
- id="g56477">
+ id="ICON_OPEN_RECENT">
<rect
y="73"
x="299"
@@ -80513,7 +82612,7 @@
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
sodipodi:ry="8"
sodipodi:rx="8"
sodipodi:cy="118"
@@ -80539,7 +82638,7 @@
sodipodi:cy="118"
sodipodi:rx="8"
sodipodi:ry="8"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90" />
@@ -80662,7 +82761,7 @@
</g>
<g
style="display:inline;enable-background:new"
- id="g36339-2"
+ id="ICON_COLOR_RED"
transform="translate(63.000002,128.99999)">
<rect
style="opacity:0;fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
@@ -80679,7 +82778,7 @@
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
sodipodi:ry="8"
sodipodi:rx="8"
sodipodi:cy="118"
@@ -80698,7 +82797,7 @@
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
- d="m 132,110 c 2.85812,0 5.49914,1.52479 6.9282,4 L 132,118 z"
+ d="m 132,110 a 8,8 0 0 1 6.9282,4 L 132,118 Z"
sodipodi:ry="8"
sodipodi:rx="8"
sodipodi:cy="118"
@@ -80716,7 +82815,7 @@
sodipodi:cy="118"
sodipodi:rx="8"
sodipodi:ry="8"
- d="m 132,110 c 2.85812,0 5.49914,1.52479 6.9282,4 L 132,118 z"
+ d="m 132,110 a 8,8 0 0 1 6.9282,4 L 132,118 Z"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90"
@@ -80732,7 +82831,7 @@
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
- d="m 132,110 c 2.85812,0 5.49914,1.52479 6.9282,4 L 132,118 z"
+ d="m 132,110 a 8,8 0 0 1 6.9282,4 L 132,118 Z"
sodipodi:ry="8"
sodipodi:rx="8"
sodipodi:cy="118"
@@ -80750,7 +82849,7 @@
sodipodi:cy="118"
sodipodi:rx="8"
sodipodi:ry="8"
- d="m 132,110 c 2.85812,0 5.49914,1.52479 6.9282,4 L 132,118 z"
+ d="m 132,110 a 8,8 0 0 1 6.9282,4 L 132,118 Z"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90"
@@ -80765,7 +82864,7 @@
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
- d="m 132,110 c 2.85812,0 5.49914,1.52479 6.9282,4 L 132,118 z"
+ d="m 132,110 a 8,8 0 0 1 6.9282,4 L 132,118 Z"
sodipodi:ry="8"
sodipodi:rx="8"
sodipodi:cy="118"
@@ -80784,7 +82883,7 @@
sodipodi:cy="118"
sodipodi:rx="8"
sodipodi:ry="8"
- d="m 132,110 c 2.85812,0 5.49914,1.52479 6.9282,4 L 132,118 z"
+ d="m 132,110 a 8,8 0 0 1 6.9282,4 L 132,118 Z"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90"
@@ -80801,7 +82900,7 @@
sodipodi:cy="118"
sodipodi:rx="8"
sodipodi:ry="8"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90" />
@@ -80809,7 +82908,7 @@
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
sodipodi:ry="8"
sodipodi:rx="8"
sodipodi:cy="118"
@@ -80822,7 +82921,7 @@
</g>
<g
style="display:inline;enable-background:new"
- id="g36339-2-8"
+ id="ICON_COLOR_GREEN"
transform="translate(84.000002,128.99999)">
<rect
style="opacity:0;fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
@@ -80839,7 +82938,7 @@
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
sodipodi:ry="8"
sodipodi:rx="8"
sodipodi:cy="118"
@@ -80858,7 +82957,7 @@
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
- d="m 132,110 c 2.85812,0 5.49914,1.52479 6.9282,4 L 132,118 z"
+ d="m 132,110 a 8,8 0 0 1 6.9282,4 L 132,118 Z"
sodipodi:ry="8"
sodipodi:rx="8"
sodipodi:cy="118"
@@ -80876,7 +82975,7 @@
sodipodi:cy="118"
sodipodi:rx="8"
sodipodi:ry="8"
- d="m 132,110 c 2.85812,0 5.49914,1.52479 6.9282,4 L 132,118 z"
+ d="m 132,110 a 8,8 0 0 1 6.9282,4 L 132,118 Z"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90"
@@ -80892,7 +82991,7 @@
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
- d="m 132,110 c 2.85812,0 5.49914,1.52479 6.9282,4 L 132,118 z"
+ d="m 132,110 a 8,8 0 0 1 6.9282,4 L 132,118 Z"
sodipodi:ry="8"
sodipodi:rx="8"
sodipodi:cy="118"
@@ -80910,7 +83009,7 @@
sodipodi:cy="118"
sodipodi:rx="8"
sodipodi:ry="8"
- d="m 132,110 c 2.85812,0 5.49914,1.52479 6.9282,4 L 132,118 z"
+ d="m 132,110 a 8,8 0 0 1 6.9282,4 L 132,118 Z"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90"
@@ -80925,7 +83024,7 @@
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
- d="m 132,110 c 2.85812,0 5.49914,1.52479 6.9282,4 L 132,118 z"
+ d="m 132,110 a 8,8 0 0 1 6.9282,4 L 132,118 Z"
sodipodi:ry="8"
sodipodi:rx="8"
sodipodi:cy="118"
@@ -80944,7 +83043,7 @@
sodipodi:cy="118"
sodipodi:rx="8"
sodipodi:ry="8"
- d="m 132,110 c 2.85812,0 5.49914,1.52479 6.9282,4 L 132,118 z"
+ d="m 132,110 a 8,8 0 0 1 6.9282,4 L 132,118 Z"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90"
@@ -80961,7 +83060,7 @@
sodipodi:cy="118"
sodipodi:rx="8"
sodipodi:ry="8"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90" />
@@ -80969,7 +83068,7 @@
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
sodipodi:ry="8"
sodipodi:rx="8"
sodipodi:cy="118"
@@ -80982,7 +83081,7 @@
</g>
<g
style="display:inline;enable-background:new"
- id="g36339-2-9"
+ id="ICON_COLOR_BLUE"
transform="translate(104.99111,129.00001)">
<rect
style="opacity:0;fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
@@ -80999,7 +83098,7 @@
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
sodipodi:ry="8"
sodipodi:rx="8"
sodipodi:cy="118"
@@ -81018,7 +83117,7 @@
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
- d="m 132,110 c 2.85812,0 5.49914,1.52479 6.9282,4 L 132,118 z"
+ d="m 132,110 a 8,8 0 0 1 6.9282,4 L 132,118 Z"
sodipodi:ry="8"
sodipodi:rx="8"
sodipodi:cy="118"
@@ -81036,7 +83135,7 @@
sodipodi:cy="118"
sodipodi:rx="8"
sodipodi:ry="8"
- d="m 132,110 c 2.85812,0 5.49914,1.52479 6.9282,4 L 132,118 z"
+ d="m 132,110 a 8,8 0 0 1 6.9282,4 L 132,118 Z"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90"
@@ -81052,7 +83151,7 @@
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
- d="m 132,110 c 2.85812,0 5.49914,1.52479 6.9282,4 L 132,118 z"
+ d="m 132,110 a 8,8 0 0 1 6.9282,4 L 132,118 Z"
sodipodi:ry="8"
sodipodi:rx="8"
sodipodi:cy="118"
@@ -81070,7 +83169,7 @@
sodipodi:cy="118"
sodipodi:rx="8"
sodipodi:ry="8"
- d="m 132,110 c 2.85812,0 5.49914,1.52479 6.9282,4 L 132,118 z"
+ d="m 132,110 a 8,8 0 0 1 6.9282,4 L 132,118 Z"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90"
@@ -81085,7 +83184,7 @@
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
- d="m 132,110 c 2.85812,0 5.49914,1.52479 6.9282,4 L 132,118 z"
+ d="m 132,110 a 8,8 0 0 1 6.9282,4 L 132,118 Z"
sodipodi:ry="8"
sodipodi:rx="8"
sodipodi:cy="118"
@@ -81104,7 +83203,7 @@
sodipodi:cy="118"
sodipodi:rx="8"
sodipodi:ry="8"
- d="m 132,110 c 2.85812,0 5.49914,1.52479 6.9282,4 L 132,118 z"
+ d="m 132,110 a 8,8 0 0 1 6.9282,4 L 132,118 Z"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90"
@@ -81121,7 +83220,7 @@
sodipodi:cy="118"
sodipodi:rx="8"
sodipodi:ry="8"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90" />
@@ -81129,7 +83228,7 @@
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
sodipodi:ry="8"
sodipodi:rx="8"
sodipodi:cy="118"
@@ -81142,7 +83241,7 @@
</g>
<g
style="display:inline;enable-background:new"
- id="g42207-2"
+ id="ICON_META_EMPTY"
transform="translate(230.94982,190.97922)">
<g
transform="translate(83.990364,83.999999)"
@@ -81157,7 +83256,7 @@
sodipodi:cy="118"
sodipodi:rx="8"
sodipodi:ry="8"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90" />
@@ -81165,7 +83264,7 @@
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
sodipodi:ry="8"
sodipodi:rx="8"
sodipodi:cy="118"
@@ -81183,7 +83282,7 @@
sodipodi:cy="118"
sodipodi:rx="8"
sodipodi:ry="8"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90" />
@@ -81196,7 +83295,7 @@
sodipodi:cy="118"
sodipodi:rx="8"
sodipodi:ry="8"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90" />
@@ -81204,7 +83303,7 @@
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
sodipodi:ry="8"
sodipodi:rx="8"
sodipodi:cy="118"
@@ -81224,7 +83323,7 @@
</g>
<g
style="display:inline;enable-background:new"
- id="g16164">
+ id="ICON_MOD_DYNAMICPAINT">
<rect
style="opacity:0;fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
id="rect18695-5"
@@ -81334,7 +83433,7 @@
</g>
<g
style="display:inline;enable-background:new"
- id="g16082">
+ id="ICON_MOD_VERTEX_WEIGHT">
<rect
style="opacity:0;fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
id="rect18695-2"
@@ -81529,7 +83628,7 @@
</g>
<g
style="display:inline;enable-background:new"
- id="g16224">
+ id="ICON_MOD_REMESH">
<rect
y="241"
x="194"
@@ -81668,7 +83767,7 @@
</g>
<g
style="display:inline;enable-background:new"
- id="g16281">
+ id="ICON_MOD_WARP">
<rect
y="241"
x="236"
@@ -81771,7 +83870,7 @@
</g>
</g>
<g
- id="g81264">
+ id="ICON_MOD_TRIANGULATE">
<rect
y="241"
x="278"
@@ -81885,7 +83984,7 @@
</g>
<g
style="display:inline;enable-background:new"
- id="g16263">
+ id="ICON_MOD_OCEAN">
<rect
y="241"
x="215"
@@ -81940,8 +84039,116 @@
</g>
</g>
<g
- style="display:inline;enable-background:new"
- id="g16592">
+ id="ICON_MOD_SMOOTH">
+ <g
+ id="g23516"
+ transform="translate(-0.9999998,2.020123)"
+ style="display:inline;enable-background:new">
+ <rect
+ y="260"
+ x="489"
+ height="16"
+ width="16"
+ id="rect23518"
+ style="opacity:0;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.29999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path23520"
+ style="fill:none;stroke:#0b1728;stroke-width:2.79999995;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 499.5,261.50004 -4.5,2 c -1.94148,0.86288 -2.18285,2.53884 -3,4.5 l -1.25,3"
+ sodipodi:nodetypes="cssc" />
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#0b1728;stroke-width:1.79999995;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline;enable-background:new"
+ d="m 503,268.00008 0,2.99996 -3,1.5 c -3,1.5 -6.25,1.5 -10,1.49996 l 0,-2.49996 c 0.5,-0.99996 1.75,-2.75004 5,-4.00004 l 4,-1.5 1,0 3,1.25 0,0.75008 z"
+ id="path23522"
+ sodipodi:nodetypes="cccccccccc" />
+ <path
+ inkscape:connector-curvature="0"
+ inkscape:export-ydpi="90"
+ inkscape:export-xdpi="90"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\4.png"
+ sodipodi:nodetypes="cccccccccc"
+ style="fill:#c2d4ef;fill-opacity:1;fill-rule:evenodd;stroke:none;display:inline;enable-background:new"
+ d="m 495,267.5 4,-1.5 1,0 3,1.25 0,0.75004 0,2.75 -3,1.5 -10,1.5 0,-1.75 c 0.5,-1 1.77456,-3.24182 5,-4.50004 z"
+ id="path23524" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cc"
+ d="m 496.75,263.00004 c -3,1.5 -2.75,8.5 2.25,7"
+ style="fill:none;stroke:url(#linearGradient23555);stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="path23542" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cccsccsccsccc"
+ id="path23526"
+ transform="translate(-20,0)"
+ d="m 519.82031,262 c 0.5,-0.16016 0.35115,-1.44373 -0.66015,-1 l -3.91016,1.75 c -2.5,0.75 -2.85099,2.90496 -3.82813,5.08203 L 510,271 l 0,3 c 3.76795,10e-6 7,0 10,-1.5 0.59071,-0.29535 2.31945,-1.15973 3,-1.5 l 0,-3 c -0.71506,0.35798 -2.3836,1.1918 -3,1.5 -0.45529,0.22765 -0.90706,0.42996 -1.375,0.59375 -4.60397,1.02313 -4.54405,-5.38421 -1.625,-6.84375 l 2.82031,-1.25 z"
+ style="fill:url(#linearGradient23581);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.89207077px;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="csc"
+ id="path23528"
+ d="m 490.5,273.51739 c 3.76795,0 5.75,-4e-5 8.75,-1.25004 0.60963,-0.25401 2.56945,-1.15973 3.25,-1.5"
+ style="fill:none;stroke:url(#linearGradient23550);stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\4.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <rect
+ y="267"
+ x="497"
+ height="1"
+ width="2"
+ id="rect23530"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.20000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <g
+ style="fill:#000000"
+ id="g23575">
+ <rect
+ y="268"
+ x="497"
+ height="1"
+ width="2"
+ id="rect23532"
+ style="opacity:0.8;fill:#162d50;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.20000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <rect
+ style="opacity:0.6;fill:#162d50;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.20000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect23534"
+ width="1"
+ height="1.5"
+ x="496"
+ y="267" />
+ <rect
+ y="267"
+ x="499"
+ height="1.5"
+ width="1"
+ id="rect23536"
+ style="opacity:0.6;fill:#162d50;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.20000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <rect
+ style="opacity:0.5;fill:#162d50;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.20000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect23538"
+ width="2"
+ height="0.5"
+ x="497"
+ y="266.5" />
+ </g>
+ <path
+ inkscape:connector-curvature="0"
+ inkscape:export-ydpi="90"
+ inkscape:export-xdpi="90"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\4.png"
+ style="fill:none;stroke:url(#linearGradient23585);stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 490.5,272.5 c 3.76795,0 5.75,-4e-5 8.75,-1.25004 0.60963,-0.25401 2.56945,-1.15973 3.25,-1.5"
+ id="path23540"
+ sodipodi:nodetypes="csc" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccssc"
+ d="m 499.5,261.50004 -3.07779,1.36791 L 495,263.50004 c -1.94148,0.86288 -2.18285,2.53884 -3,4.5 l -1.25,3"
+ style="opacity:0.8;fill:none;stroke:#ffffff;stroke-width:1.20000005;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="path23546" />
+ </g>
<rect
style="opacity:0;fill:#292929;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.29999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
id="rect23518-8"
@@ -81977,25 +84184,25 @@
inkscape:connector-curvature="0"
sodipodi:nodetypes="csc"
d="m 495.70064,264.97925 c -1.59411,1.20331 -2.85352,5.00657 -1.83419,6.55562 0.84654,1.28647 2.26188,0.99107 4.08419,0.44438"
- style="fill:none;stroke:url(#linearGradient16573);stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ style="fill:none;stroke:url(#linearGradient18618);stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
id="path23542-7" />
<path
id="path14759-8"
d="m 497.43868,264.59926 c 0.80576,0.30416 1.37557,1.03323 1.48798,2.92233 l 3.02398,2.65977 c -0.14914,-2.63927 0.0915,-5.8212 -3.12879,-7.01803 -0.39922,-0.14837 -1.04358,-0.0621 -1.33996,0.0614 z"
- style="fill:url(#linearGradient16570);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.89207077px;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ style="fill:url(#linearGradient18620);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.89207077px;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
inkscape:connector-curvature="0" />
<path
sodipodi:nodetypes="cssccsccscsscc"
id="path23526-4"
d="m 497.47415,263.23002 c -0.0305,0.0127 -2.69071,1.0899 -3.08515,1.28834 -0.97345,0.48973 -2.73962,3.32869 -3.70177,5.33135 l -1.74953,3.64155 0.013,2.49908 c 3.76795,10e-6 7,0 10,-1.5 l 3,-1.5 0,-3 c -0.71506,0.35798 -2.3836,1.1918 -3,1.5 -0.45529,0.22765 -0.90706,0.42996 -1.375,0.59375 -1.77534,0.39453 -3.51362,0.44764 -3.974,-0.67129 -0.58429,-1.42008 0.52872,-4.89528 2.24297,-6.11564 0.23077,-0.16428 1.56009,-0.67849 1.59569,-0.69629 z"
- style="fill:url(#linearGradient16567);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.89207077px;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ style="fill:url(#linearGradient18622);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.89207077px;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
inkscape:connector-curvature="0" />
<path
inkscape:connector-curvature="0"
sodipodi:nodetypes="csc"
id="path23528-6"
d="m 489.45064,275.4966 c 3.76795,0 5.75,-4e-5 8.75,-1.25004 0.60963,-0.25401 2.56945,-1.15973 3.25,-1.5"
- style="fill:none;stroke:url(#linearGradient16564);stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ style="fill:none;stroke:url(#linearGradient18624);stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\4.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90" />
@@ -82004,7 +84211,7 @@
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\4.png"
- style="fill:none;stroke:url(#linearGradient16561);stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ style="fill:none;stroke:url(#linearGradient18626);stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
d="m 489.45064,274.47921 c 3.76795,0 5.75,-4e-5 8.75,-1.25004 0.60963,-0.25401 2.56945,-1.15973 3.25,-1.5"
id="path23540-9"
sodipodi:nodetypes="csc" />
@@ -82012,7 +84219,7 @@
inkscape:connector-curvature="0"
sodipodi:nodetypes="csscsc"
d="m 489.67253,273.44041 2.07721,-4.14016 c 0.98497,-1.9632 2.11086,-3.89476 3.15802,-4.3308 l 2.83577,-1.18084 c 0.92808,-0.35355 2.39677,0.78516 2.88291,1.66904 0.48613,0.88389 0.68121,2.03922 0.85799,4.29312"
- style="opacity:0.8;fill:none;stroke:url(#linearGradient16558);stroke-width:1.20000005;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ style="opacity:0.8;fill:none;stroke:url(#linearGradient18628);stroke-width:1.20000005;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
id="path23546-3" />
<path
style="fill:#ffffff;fill-opacity:1;stroke:#1b4685;stroke-width:0.80000001;stroke-linecap:round;stroke-miterlimit:4;stroke-opacity:1"
@@ -82030,7 +84237,7 @@
</g>
<g
style="display:inline;enable-background:new"
- id="g14953">
+ id="ICON_SOLO_OFF">
<rect
y="198.9792"
x="4.9506397"
@@ -82070,7 +84277,7 @@
<g
transform="translate(-0.04936017,-0.02079917)"
style="display:inline;enable-background:new"
- id="g16432">
+ id="ICON_FRAME_NEXT">
<rect
y="199"
x="68"
@@ -82127,7 +84334,7 @@
<g
transform="translate(-0.04936017,-0.02079917)"
style="display:inline;enable-background:new"
- id="g16424">
+ id="ICON_FRAME_PREV">
<rect
transform="scale(-1,1)"
y="198.89999"
@@ -82184,7 +84391,7 @@
</g>
<g
style="display:inline;enable-background:new"
- id="g56653">
+ id="ICON_AXIS_FRONT">
<path
inkscape:connector-curvature="0"
d="m 289.95065,114.97921 0,1 2,0 0,1 1,0 0,-1 0,-1 -3,0 z m 2,2 -1,0 0,1 1,0 0,-1 z m -1,1 -1,0 0,1 0,1 3,0 0,-1 -2,0 0,-1 z m -1,3 0,2 1,0 0,-2 -1,0 z m 1,2 0,1 1,0 0,-1 -1,0 z m 1,0 1,0 0,-2 -1,0 0,2 z m 0,1 0,2 1,0 0,-2 -1,0 z m -1,0 -1,0 0,2 1,0 0,-2 z"
@@ -82323,7 +84530,7 @@
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png"
transform="matrix(1.3333333,0,0,1.3333343,3,147.66665)"
- d="M 72,14.5 C 72,15.328427 71.328427,16 70.5,16 69.671573,16 69,15.328427 69,14.5 69,13.671573 69.671573,13 70.5,13 c 0.828427,0 1.5,0.671573 1.5,1.5 z"
+ d="M 72,14.5 A 1.5,1.5 0 0 1 70.5,16 1.5,1.5 0 0 1 69,14.5 1.5,1.5 0 0 1 70.5,13 1.5,1.5 0 0 1 72,14.5 Z"
sodipodi:ry="1.5"
sodipodi:rx="1.5"
sodipodi:cy="14.5"
@@ -82335,7 +84542,7 @@
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png"
- d="M 72,14.5 C 72,15.328427 71.328427,16 70.5,16 69.671573,16 69,15.328427 69,14.5 69,13.671573 69.671573,13 70.5,13 c 0.828427,0 1.5,0.671573 1.5,1.5 z"
+ d="M 72,14.5 A 1.5,1.5 0 0 1 70.5,16 1.5,1.5 0 0 1 69,14.5 1.5,1.5 0 0 1 70.5,13 1.5,1.5 0 0 1 72,14.5 Z"
sodipodi:ry="1.5"
sodipodi:rx="1.5"
sodipodi:cy="14.5"
@@ -82383,7 +84590,7 @@
</g>
<g
style="display:inline;enable-background:new"
- id="g56628">
+ id="ICON_AXIS_SIDE">
<g
transform="translate(-0.04936017,-1.0207992)"
id="g18315"
@@ -82522,7 +84729,7 @@
sodipodi:cy="14.5"
sodipodi:rx="1.5"
sodipodi:ry="1.5"
- d="M 72,14.5 C 72,15.328427 71.328427,16 70.5,16 69.671573,16 69,15.328427 69,14.5 69,13.671573 69.671573,13 70.5,13 c 0.828427,0 1.5,0.671573 1.5,1.5 z"
+ d="M 72,14.5 A 1.5,1.5 0 0 1 70.5,16 1.5,1.5 0 0 1 69,14.5 1.5,1.5 0 0 1 70.5,13 1.5,1.5 0 0 1 72,14.5 Z"
transform="matrix(1.3333333,0,0,1.3333343,170.99998,105.66665)"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png"
inkscape:export-xdpi="90"
@@ -82536,7 +84743,7 @@
sodipodi:cy="14.5"
sodipodi:rx="1.5"
sodipodi:ry="1.5"
- d="M 72,14.5 C 72,15.328427 71.328427,16 70.5,16 69.671573,16 69,15.328427 69,14.5 69,13.671573 69.671573,13 70.5,13 c 0.828427,0 1.5,0.671573 1.5,1.5 z"
+ d="M 72,14.5 A 1.5,1.5 0 0 1 70.5,16 1.5,1.5 0 0 1 69,14.5 1.5,1.5 0 0 1 70.5,13 1.5,1.5 0 0 1 72,14.5 Z"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90" />
@@ -82574,7 +84781,7 @@
</g>
<g
style="display:inline;enable-background:new"
- id="g56680">
+ id="ICON_AXIS_TOP">
<g
transform="translate(-0.04936017,-1.0207992)"
id="g18312"
@@ -82713,7 +84920,7 @@
sodipodi:cy="14.5"
sodipodi:rx="1.5"
sodipodi:ry="1.5"
- d="M 72,14.5 C 72,15.328427 71.328427,16 70.5,16 69.671573,16 69,15.328427 69,14.5 69,13.671573 69.671573,13 70.5,13 c 0.828427,0 1.5,0.671573 1.5,1.5 z"
+ d="M 72,14.5 A 1.5,1.5 0 0 1 70.5,16 1.5,1.5 0 0 1 69,14.5 1.5,1.5 0 0 1 70.5,13 1.5,1.5 0 0 1 72,14.5 Z"
transform="matrix(1.3333333,0,0,1.3333343,209.98999,105.66665)"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png"
inkscape:export-xdpi="90"
@@ -82727,7 +84934,7 @@
sodipodi:cy="14.5"
sodipodi:rx="1.5"
sodipodi:ry="1.5"
- d="M 72,14.5 C 72,15.328427 71.328427,16 70.5,16 69.671573,16 69,15.328427 69,14.5 69,13.671573 69.671573,13 70.5,13 c 0.828427,0 1.5,0.671573 1.5,1.5 z"
+ d="M 72,14.5 A 1.5,1.5 0 0 1 70.5,16 1.5,1.5 0 0 1 69,14.5 1.5,1.5 0 0 1 70.5,13 1.5,1.5 0 0 1 72,14.5 Z"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90" />
@@ -82763,17 +84970,10 @@
inkscape:connector-curvature="0" />
</g>
</g>
- <rect
- style="opacity:0;fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- id="rect23018-5-4-2"
- width="16"
- height="16"
- x="29.270542"
- y="209.19434" />
<g
transform="translate(21.04936,0.02079773)"
style="display:inline;enable-background:new"
- id="g14953-0">
+ id="ICON_SOLO_ON">
<rect
y="198.9792"
x="4.9506397"
@@ -82812,7 +85012,7 @@
</g>
<g
transform="translate(189,-229)"
- id="g22900-8"
+ id="ICON_MUTE_IPO_OFF"
style="display:inline;enable-background:new">
<rect
style="opacity:0;fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
@@ -82931,7 +85131,7 @@
</g>
<g
transform="translate(210,-229)"
- id="g22900-8-5"
+ id="ICON_MUTE_IPO_ON"
style="display:inline;enable-background:new">
<rect
style="opacity:0;fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
@@ -83013,7 +85213,7 @@
</g>
<g
transform="translate(-42,-40)"
- id="g22900-8-3"
+ id="ICON_OUTLINER_DATA_SPEAKER"
style="display:inline;enable-background:new">
<rect
style="opacity:0;fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
@@ -83132,7 +85332,7 @@
</g>
<g
style="display:inline;enable-background:new"
- id="g17563">
+ id="ICON_OUTLINER_OB_SPEAKER">
<rect
style="opacity:0;fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
id="rect22902-0-2"
@@ -83264,105 +85464,108 @@
inkscape:connector-curvature="0" />
</g>
</g>
- <rect
- y="597"
- x="383"
- height="16"
- width="16"
- id="rect18740-5"
- style="opacity:0;fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
- <g
- transform="matrix(0.78985507,0,0,0.78985507,384.77042,545.63116)"
- id="g18742-8"
- style="display:inline;enable-background:new">
- <rect
- y="70.999992"
- x="4.9838772"
- height="9.0000172"
- width="11.999999"
- id="rect38458-5"
- style="opacity:0.7;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.9999994px;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
- <path
- inkscape:connector-curvature="0"
- sodipodi:nodetypes="cccccccccc"
- style="fill:url(#linearGradient17715);fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.01284409;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
- d="m 17.209985,82.052175 -1.174018,1.202898 -10.0887566,0 -1.2028894,-1.202898 -1e-7,-12.622124 12.4766491,0 -0.01099,12.622124 -5e-6,0 0,0 z"
- id="path18744-0"
- inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png"
- inkscape:export-xdpi="90"
- inkscape:export-ydpi="90" />
- <path
- inkscape:connector-curvature="0"
- sodipodi:nodetypes="ccccc"
- style="fill:#666666;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.9999994px;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- d="m 15.536259,81.328571 -6.3832127,2e-6 0,-0.999998 6.3832127,-2e-6 0,0.999998 z"
- id="path18746-7"
- inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png"
- inkscape:export-xdpi="90"
- inkscape:export-ydpi="90" />
- <path
- inkscape:connector-curvature="0"
- sodipodi:nodetypes="ccccc"
- inkscape:export-ydpi="90"
- inkscape:export-xdpi="90"
- inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png"
- id="path18748-3"
- d="m 5.9039809,82.132474 0.025569,-11.527305 10.1868001,5.7e-5 0,11.527247 z"
- style="fill:none;stroke:url(#linearGradient17717);stroke-width:1.26605475px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" />
- <rect
- inkscape:export-ydpi="90"
- inkscape:export-xdpi="90"
- inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png"
- y="80.356544"
- x="6.7951851"
- height="1"
- width="1"
- id="rect18750-1"
- style="fill:#d40000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
- </g>
<g
- style="display:inline;enable-background:new"
- id="g43488-2-2"
- transform="matrix(0,-0.75485957,0.75485957,0,327.67313,852.33908)">
- <path
- inkscape:connector-curvature="0"
- style="fill:none;stroke:#000000;stroke-width:3.57682419;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
- d="M 326.98536,85.889717 327,76"
- id="path43490-2-2"
- sodipodi:nodetypes="cc" />
- <path
- inkscape:connector-curvature="0"
- style="fill:none;stroke:#000000;stroke-width:3.57682419;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
- d="m 330.97424,79.255626 -3.97425,-3.974249 -3.97424,3.974249"
- id="path43492-1-0"
- sodipodi:nodetypes="ccc" />
- </g>
- <g
- style="display:inline;enable-background:new"
- id="g43494-2-5"
- transform="matrix(0,-0.75485957,0.75485957,0,327.67313,852.33908)">
- <path
- inkscape:connector-curvature="0"
- sodipodi:nodetypes="cc"
- id="path43496-7-5"
- d="M 327,85.889717 327,76"
- style="fill:none;stroke:#ebebeb;stroke-width:1.72217464;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
- <path
- inkscape:connector-curvature="0"
- sodipodi:nodetypes="ccc"
- id="path43498-9-6"
- d="m 330.97424,79.255626 -3.97425,-3.974249 -3.97424,3.974249"
- style="fill:none;stroke:#ebebeb;stroke-width:1.72217464;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
- <path
- style="fill:none;stroke:#ffffff;stroke-width:1.32474971;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- d="m 330.97424,79.255626 -2.24089,-2.206598"
- id="path17874"
- sodipodi:nodetypes="cc"
- inkscape:connector-curvature="0" />
+ id="ICON_SCREEN_BACK">
+ <rect
+ style="opacity:0;fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect18740-5"
+ width="16"
+ height="16"
+ x="383"
+ y="597" />
+ <g
+ style="display:inline;enable-background:new"
+ id="g18742-8"
+ transform="matrix(0.78985507,0,0,0.78985507,384.77042,545.63116)">
+ <rect
+ style="opacity:0.7;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.9999994px;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect38458-5"
+ width="11.999999"
+ height="9.0000172"
+ x="4.9838772"
+ y="70.999992" />
+ <path
+ inkscape:export-ydpi="90"
+ inkscape:export-xdpi="90"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png"
+ id="path18744-0"
+ d="m 17.209985,82.052175 -1.174018,1.202898 -10.0887566,0 -1.2028894,-1.202898 -1e-7,-12.622124 12.4766491,0 -0.01099,12.622124 -5e-6,0 0,0 z"
+ style="fill:url(#linearGradient17715);fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.01284409;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ sodipodi:nodetypes="cccccccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ inkscape:export-ydpi="90"
+ inkscape:export-xdpi="90"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png"
+ id="path18746-7"
+ d="m 15.536259,81.328571 -6.3832127,2e-6 0,-0.999998 6.3832127,-2e-6 0,0.999998 z"
+ style="fill:#666666;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.9999994px;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ sodipodi:nodetypes="ccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:none;stroke:url(#linearGradient17717);stroke-width:1.26605475px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ d="m 5.9039809,82.132474 0.025569,-11.527305 10.1868001,5.7e-5 0,11.527247 z"
+ id="path18748-3"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"
+ sodipodi:nodetypes="ccccc"
+ inkscape:connector-curvature="0" />
+ <rect
+ style="fill:#d40000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect18750-1"
+ width="1"
+ height="1"
+ x="6.7951851"
+ y="80.356544"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ </g>
+ <g
+ transform="matrix(0,-0.75485957,0.75485957,0,327.67313,852.33908)"
+ id="g43488-2-2"
+ style="display:inline;enable-background:new">
+ <path
+ sodipodi:nodetypes="cc"
+ id="path43490-2-2"
+ d="M 326.98536,85.889717 327,76"
+ style="fill:none;stroke:#000000;stroke-width:3.57682419;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccc"
+ id="path43492-1-0"
+ d="m 330.97424,79.255626 -3.97425,-3.974249 -3.97424,3.974249"
+ style="fill:none;stroke:#000000;stroke-width:3.57682419;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ transform="matrix(0,-0.75485957,0.75485957,0,327.67313,852.33908)"
+ id="g43494-2-5"
+ style="display:inline;enable-background:new">
+ <path
+ style="fill:none;stroke:#ebebeb;stroke-width:1.72217464;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="M 327,85.889717 327,76"
+ id="path43496-7-5"
+ sodipodi:nodetypes="cc"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:none;stroke:#ebebeb;stroke-width:1.72217464;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 330.97424,79.255626 -3.97425,-3.974249 -3.97424,3.974249"
+ id="path43498-9-6"
+ sodipodi:nodetypes="ccc"
+ inkscape:connector-curvature="0" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cc"
+ id="path17874"
+ d="m 330.97424,79.255626 -2.24089,-2.206598"
+ style="fill:none;stroke:#ffffff;stroke-width:1.32474971;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ </g>
</g>
<g
style="display:inline;enable-background:new"
- id="g17941">
+ id="ICON_DRIVER">
<rect
transform="scale(-1,1)"
y="220.00047"
@@ -83406,7 +85609,7 @@
</g>
</g>
<g
- id="g20086">
+ id="ICON_UNLOCKED">
<rect
y="598"
x="299"
@@ -83494,7 +85697,7 @@
<g
transform="translate(21,0)"
style="display:inline;enable-background:new"
- id="g20086-7">
+ id="ICON_LOCKED">
<rect
y="598"
x="299"
@@ -83582,7 +85785,7 @@
<g
transform="translate(-105.02687,272.93951)"
style="display:inline;enable-background:new"
- id="g17107">
+ id="ICON_EYEDROPPER">
<rect
style="opacity:0;fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
id="rect18696-0-4-1"
@@ -83635,7 +85838,7 @@
<g
transform="translate(-42,231)"
style="display:inline;enable-background:new"
- id="g17942-1">
+ id="ICON_ACTION">
<rect
y="304"
x="278"
@@ -83709,7 +85912,7 @@
</g>
</g>
<g
- id="g16806">
+ id="ICON_BOIDS">
<rect
y="472"
x="257"
@@ -83778,26 +85981,9 @@
id="path16745-9" />
</g>
<g
- id="g37076-6-0-2"
- style="opacity:0.96000001;stroke:#1a1a1a;stroke-width:3;stroke-miterlimit:4;stroke-dasharray:none;display:inline;enable-background:new"
- transform="translate(127.00485,107.03779)" />
- <g
- style="opacity:0.96000001;stroke:#c8c8c8;stroke-opacity:1;display:inline;enable-background:new"
- id="g37094-7-8-1"
- transform="translate(190.00485,-60.962214)">
- <g
- transform="translate(-63.000001,168)"
- id="g37096-1-5-3"
- style="stroke:#c8c8c8;stroke-width:1.5;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
- <g
- id="g37104-2-9-1"
- transform="matrix(0,1,-1,0,511,255)"
- style="stroke:#c8c8c8;stroke-width:1.5;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
- </g>
- <g
transform="translate(105,0)"
style="opacity:0.3;display:inline;enable-background:new"
- id="g17847-0">
+ id="ICON_RESTRICT_SELECT_ON">
<path
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccccccc"
@@ -83827,7 +86013,7 @@
<g
transform="translate(84,0)"
style="display:inline;enable-background:new"
- id="g17847-9">
+ id="ICON_RESTRICT_SELECT_OFF">
<path
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccccccc"
@@ -83856,7 +86042,7 @@
</g>
<g
style="display:inline;enable-background:new"
- id="g10534-1"
+ id="ICON_SCRIPTPLUGINS"
transform="translate(189.0161,-397)">
<rect
y="428"
@@ -83935,119 +86121,9 @@
</g>
</g>
<g
- style="display:inline;enable-background:new"
- id="g79830">
- <rect
- y="73"
- x="467"
- height="16"
- width="16"
- id="rect52984-1"
- style="opacity:0;fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
- <g
- id="g79032">
- <g
- style="display:inline;enable-background:new"
- id="g39239-9"
- transform="translate(-285,-131)">
- <path
- inkscape:export-ydpi="90"
- inkscape:export-xdpi="90"
- inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png"
- sodipodi:nodetypes="cccccc"
- id="path39241-0"
- d="m 756.16666,204.50001 10.33334,0 0,14.99999 -13,0 -10e-6,-11.99999 2.66667,-3 z"
- style="fill:url(#linearGradient39254-3);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;display:inline"
- inkscape:connector-curvature="0" />
- <path
- style="opacity:0.3;fill:url(#radialGradient39256-2);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- d="m 756.16666,204.50001 10.33334,0 0,14.99999 -13,0 -10e-6,-11.99999 2.66667,-3 z"
- id="path39243-2"
- sodipodi:nodetypes="cccccc"
- inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png"
- inkscape:export-xdpi="90"
- inkscape:export-ydpi="90"
- inkscape:connector-curvature="0" />
- <path
- sodipodi:nodetypes="cccc"
- d="m 754.5,209 0,9.5 m 3.5,-13 7.5,0"
- style="fill:none;stroke:url(#linearGradient39258-9);stroke-width:1px;stroke-linecap:square;stroke-linejoin:miter;stroke-opacity:1;display:inline"
- id="path39245-4"
- inkscape:connector-curvature="0" />
- <path
- style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;display:inline"
- d="m 753,208 4,0 0,-4 -4,4 z"
- id="path39247-4"
- sodipodi:nodetypes="cccc"
- inkscape:connector-curvature="0" />
- <path
- inkscape:export-ydpi="90"
- inkscape:export-xdpi="90"
- inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png"
- d="m 753.5,207.00001 0,12.49999 13,0 0,-14.99999 -10.5,0 -2.5,2.5 z"
- style="fill:none;stroke:#000000;stroke-width:0.80000001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
- id="path39249-3"
- sodipodi:nodetypes="cccccc"
- inkscape:connector-curvature="0" />
- <path
- id="path39251-7"
- d="m 757.5,206.5 0,2 -2,0"
- style="fill:none;stroke:url(#linearGradient16151);stroke-width:1px;stroke-linecap:square;stroke-linejoin:miter;stroke-opacity:1"
- inkscape:connector-curvature="0" />
- </g>
- <path
- sodipodi:nodetypes="cccccccccccccccccssc"
- inkscape:connector-curvature="0"
- id="path52980-3"
- d="m 481.21875,81.25 c -0.34507,-0.155271 -0.69504,-0.245578 -1.125,-0.34375 L 479.9375,79 l -1,0 -1,0 -0.15625,1.90625 c -0.6231,0.14227 -1.07677,0.25145 -1.59375,0.59375 l -1.75,-1.75 -1.75,1.75 1.75,1.75 c -0.34229,0.51699 -0.45148,0.97065 -0.59375,1.59375 L 471.9375,85 l 0,1 0,1 1.90625,0.15625 c 0.092,0.4031 0.17505,0.738019 0.3125,1.0625 m 2.96875,0 C 476.47574,87.692174 476.0625,86.902037 476.0625,86 c 0,-1.58782 1.28718,-2.875 2.875,-2.875 0.94357,0 1.75793,0.454854 2.28125,1.15625"
- style="color:#000000;fill:none;stroke:#000000;stroke-width:1.70000005;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
- <path
- inkscape:connector-curvature="0"
- id="path52982-4"
- d="m 477.9375,79 -0.15625,1.90625 c -0.6231,0.14227 -1.07677,0.25145 -1.59375,0.59375 l -1.75,-1.5 -1.5,1.5 1.5,1.75 c -0.34229,0.51699 -0.45148,0.97065 -0.59375,1.59375 L 471.9375,85 l 0,1 0,1 1.90625,0.15625 c 0.0981,0.429533 0.18992,0.780253 0.34375,1.125 l 2.8125,0 C 476.34893,87.730943 475.9375,86.919238 475.9375,86 c 0,-1.65685 1.34315,-3 3,-3 0.96105,0 1.7947,0.453338 2.34375,1.15625 l 0,-2.875 c -0.36595,-0.173211 -0.73124,-0.270823 -1.1875,-0.375 L 479.9375,79 l -1,0 -1,0 z m 3.34375,8.8125 c -0.12902,0.1662 -0.24569,0.333041 -0.40625,0.46875 l 0.40625,0 0,-0.46875 z"
- style="color:#000000;fill:url(#linearGradient79029);fill-opacity:1;fill-rule:nonzero;stroke:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
- <path
- sodipodi:nodetypes="cssc"
- inkscape:connector-curvature="0"
- id="rect52986-8"
- d="M 481.28125,83.40625 C 480.661,82.839183 479.84801,82.5 478.9375,82.5 c -1.93397,0 -3.5,1.566029 -3.5,3.5 0,0.881253 0.34008,1.6682 0.875,2.28125"
- style="fill:none;stroke:url(#linearGradient79025);stroke-width:0.99999994;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:7.26976086;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
- <path
- sodipodi:nodetypes="ccccccccccccc"
- inkscape:connector-curvature="0"
- id="path52988-6"
- d="m 476.4375,81.75 c 0.49914,-0.213 1.64896,-0.6698 2,-0.75 l 0,-0.75 0,-0.75 1,0 m -5.25,1.25 -0.5,0.5 z m 0.5,2.75 c -0.20864,0.49552 -0.6715,1.65605 -0.75,2 l -0.75,0 -0.75,0 0,1"
- style="fill:none;stroke:#ffffff;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
- <path
- inkscape:connector-curvature="0"
- inkscape:export-ydpi="90"
- inkscape:export-xdpi="90"
- inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png"
- style="fill:none;stroke:#ffffff;stroke-width:1.10000002;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
- d="m 473.43328,81.74394 1.25,-1.25"
- id="path52990-8"
- sodipodi:nodetypes="cc" />
- <path
- sodipodi:nodetypes="cssc"
- inkscape:connector-curvature="0"
- id="rect52992-4"
- d="M 481.28125,83.40625 C 480.661,82.839183 479.84801,82.5 478.9375,82.5 c -1.93397,0 -3.5,1.566029 -3.5,3.5 0,0.881253 0.34008,1.6682 0.875,2.28125"
- style="opacity:0.4;fill:none;stroke:url(#linearGradient79020);stroke-width:0.99999994;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:7.26976086;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
- <path
- inkscape:export-ydpi="90"
- inkscape:export-xdpi="90"
- inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png"
- d="m 468.49796,75.999224 0,12.49999 13,0 0,-14.99999 -10.5,0 -2.5,2.5 z"
- style="fill:none;stroke:#000000;stroke-width:0.80000001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline;enable-background:new"
- id="path39249-3-7"
- sodipodi:nodetypes="cccccc"
- inkscape:connector-curvature="0" />
- </g>
- </g>
- <g
transform="translate(-42.000002,-84)"
style="display:inline;enable-background:new"
- id="g81158-5">
+ id="ICON_MOD_SKIN">
<rect
y="325"
x="299"
@@ -84109,22 +86185,135 @@
y="332.52499" />
</g>
</g>
- <path
- sodipodi:type="arc"
- style="fill:none;stroke:#000000;stroke-width:0.9560194;stroke-linecap:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
- id="path81543"
- sodipodi:cx="478.90625"
- sodipodi:cy="86.03125"
- sodipodi:rx="2.34375"
- sodipodi:ry="2.34375"
- d="m 478.63139,88.358828 a 2.34375,2.34375 0 1 1 2.61786,-2.38697"
- transform="matrix(1.0460001,0,0,1.0460077,-22.029739,-4.0047766)"
- sodipodi:start="1.6883393"
- sodipodi:end="6.2578421"
- sodipodi:open="true" />
+ <g
+ id="ICON_FILE_SCRIPT">
+ <g
+ id="g79830"
+ style="display:inline;enable-background:new">
+ <rect
+ style="opacity:0;fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect52984-1"
+ width="16"
+ height="16"
+ x="467"
+ y="73" />
+ <g
+ id="g79032">
+ <g
+ transform="translate(-285,-131)"
+ id="g39239-9"
+ style="display:inline;enable-background:new">
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:url(#linearGradient39254-3);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;display:inline"
+ d="m 756.16666,204.50001 10.33334,0 0,14.99999 -13,0 -10e-6,-11.99999 2.66667,-3 z"
+ id="path39241-0"
+ sodipodi:nodetypes="cccccc"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <path
+ inkscape:connector-curvature="0"
+ inkscape:export-ydpi="90"
+ inkscape:export-xdpi="90"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png"
+ sodipodi:nodetypes="cccccc"
+ id="path39243-2"
+ d="m 756.16666,204.50001 10.33334,0 0,14.99999 -13,0 -10e-6,-11.99999 2.66667,-3 z"
+ style="opacity:0.3;fill:url(#radialGradient39256-2);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path39245-4"
+ style="fill:none;stroke:url(#linearGradient39258-9);stroke-width:1px;stroke-linecap:square;stroke-linejoin:miter;stroke-opacity:1;display:inline"
+ d="m 754.5,209 0,9.5 m 3.5,-13 7.5,0"
+ sodipodi:nodetypes="cccc" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cccc"
+ id="path39247-4"
+ d="m 753,208 4,0 0,-4 -4,4 z"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;display:inline" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cccccc"
+ id="path39249-3"
+ style="fill:none;stroke:#000000;stroke-width:0.80000001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 753.5,207.00001 0,12.49999 13,0 0,-14.99999 -10.5,0 -2.5,2.5 z"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:url(#linearGradient16151);stroke-width:1px;stroke-linecap:square;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 757.5,206.5 0,2 -2,0"
+ id="path39251-7" />
+ </g>
+ <path
+ style="color:#000000;fill:none;stroke:#000000;stroke-width:1.70000005;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 481.21875,81.25 c -0.34507,-0.155271 -0.69504,-0.245578 -1.125,-0.34375 L 479.9375,79 l -1,0 -1,0 -0.15625,1.90625 c -0.6231,0.14227 -1.07677,0.25145 -1.59375,0.59375 l -1.75,-1.75 -1.75,1.75 1.75,1.75 c -0.34229,0.51699 -0.45148,0.97065 -0.59375,1.59375 L 471.9375,85 l 0,1 0,1 1.90625,0.15625 c 0.092,0.4031 0.17505,0.738019 0.3125,1.0625 m 2.96875,0 C 476.47574,87.692174 476.0625,86.902037 476.0625,86 c 0,-1.58782 1.28718,-2.875 2.875,-2.875 0.94357,0 1.75793,0.454854 2.28125,1.15625"
+ id="path52980-3"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cccccccccccccccccssc" />
+ <path
+ style="color:#000000;fill:url(#linearGradient79029);fill-opacity:1;fill-rule:nonzero;stroke:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 477.9375,79 -0.15625,1.90625 c -0.6231,0.14227 -1.07677,0.25145 -1.59375,0.59375 l -1.75,-1.5 -1.5,1.5 1.5,1.75 c -0.34229,0.51699 -0.45148,0.97065 -0.59375,1.59375 L 471.9375,85 l 0,1 0,1 1.90625,0.15625 c 0.0981,0.429533 0.18992,0.780253 0.34375,1.125 l 2.8125,0 C 476.34893,87.730943 475.9375,86.919238 475.9375,86 c 0,-1.65685 1.34315,-3 3,-3 0.96105,0 1.7947,0.453338 2.34375,1.15625 l 0,-2.875 c -0.36595,-0.173211 -0.73124,-0.270823 -1.1875,-0.375 L 479.9375,79 l -1,0 -1,0 z m 3.34375,8.8125 c -0.12902,0.1662 -0.24569,0.333041 -0.40625,0.46875 l 0.40625,0 0,-0.46875 z"
+ id="path52982-4"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:none;stroke:url(#linearGradient79025);stroke-width:0.99999994;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:7.26976086;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="M 481.28125,83.40625 C 480.661,82.839183 479.84801,82.5 478.9375,82.5 c -1.93397,0 -3.5,1.566029 -3.5,3.5 0,0.881253 0.34008,1.6682 0.875,2.28125"
+ id="rect52986-8"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cssc" />
+ <path
+ style="fill:none;stroke:#ffffff;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ d="m 476.4375,81.75 c 0.49914,-0.213 1.64896,-0.6698 2,-0.75 l 0,-0.75 0,-0.75 1,0 m -5.25,1.25 -0.5,0.5 z m 0.5,2.75 c -0.20864,0.49552 -0.6715,1.65605 -0.75,2 l -0.75,0 -0.75,0 0,1"
+ id="path52988-6"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccccccccccc" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path52990-8"
+ d="m 473.43328,81.74394 1.25,-1.25"
+ style="fill:none;stroke:#ffffff;stroke-width:1.10000002;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.4;fill:none;stroke:url(#linearGradient79020);stroke-width:0.99999994;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:7.26976086;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="M 481.28125,83.40625 C 480.661,82.839183 479.84801,82.5 478.9375,82.5 c -1.93397,0 -3.5,1.566029 -3.5,3.5 0,0.881253 0.34008,1.6682 0.875,2.28125"
+ id="rect52992-4"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cssc" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cccccc"
+ id="path39249-3-7"
+ style="fill:none;stroke:#000000;stroke-width:0.80000001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline;enable-background:new"
+ d="m 468.49796,75.999224 0,12.49999 13,0 0,-14.99999 -10.5,0 -2.5,2.5 z"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ </g>
+ </g>
+ <path
+ sodipodi:open="true"
+ sodipodi:end="6.2578421"
+ sodipodi:start="1.6883393"
+ transform="matrix(1.0460001,0,0,1.0460077,-22.029739,-4.0047766)"
+ d="m 478.63139,88.358828 a 2.34375,2.34375 0 1 1 2.61786,-2.38697"
+ sodipodi:ry="2.34375"
+ sodipodi:rx="2.34375"
+ sodipodi:cy="86.03125"
+ sodipodi:cx="478.90625"
+ id="path81543"
+ style="fill:none;stroke:#000000;stroke-width:0.9560194;stroke-linecap:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ sodipodi:type="arc" />
+ </g>
<g
style="display:inline;enable-background:new"
- id="g16724-8-3">
+ id="ICON_PANEL_CLOSE">
<rect
y="598"
x="152"
@@ -84174,7 +86363,7 @@
<g
transform="translate(252,21)"
style="display:inline;enable-background:new"
- id="g16724-8-1">
+ id="ICON_X">
<rect
y="598"
x="152"
@@ -84222,7 +86411,7 @@
</g>
</g>
<g
- id="g27438">
+ id="ICON_BORDER_RECT">
<g
transform="translate(0,-21)"
id="g23604">
@@ -84474,7 +86663,7 @@
<g
transform="translate(0.02855492,0)"
style="display:inline;enable-background:new"
- id="g15868-5">
+ id="ICON_MOD_SOLIDIFY">
<rect
style="opacity:0;fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
id="rect18695-6-9-6"
@@ -84552,15 +86741,8 @@
sodipodi:nodetypes="cc" />
</g>
</g>
- <path
- d="m -220,198.65625 -5.3125,8.6875 5.3125,3 5.28125,-3.0625 -5.28125,-8.625 z"
- id="path29747"
- style="opacity:0.55438597;fill:none;stroke:url(#linearGradient29763);stroke-width:1.14285719;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- inkscape:original="M -220 196.6875 L -226.71875 207.6875 L -220 211.5 L -213.3125 207.625 L -220 196.6875 z "
- inkscape:radius="-1.0141826"
- sodipodi:type="inkscape:offset" />
<g
- id="g27538">
+ id="ICON_EDIT">
<rect
style="opacity:0;fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
id="rect39543"
@@ -84963,7 +87145,7 @@
id="path32864"
inkscape:connector-curvature="0" />
<path
- d="m -177.09897,651.49231 c 0,1.37646 -1.09713,2.49231 -2.45051,2.49231 -1.35339,0 -2.45052,-1.11585 -2.45052,-2.49231 0,-1.37646 1.09713,-2.49231 2.45052,-2.49231 1.35338,0 2.45051,1.11585 2.45051,2.49231 z"
+ d="m -177.09897,651.49231 a 2.4505157,2.4923096 0 0 1 -2.45051,2.49231 A 2.4505157,2.4923096 0 0 1 -182,651.49231 2.4505157,2.4923096 0 0 1 -179.54948,649 a 2.4505157,2.4923096 0 0 1 2.45051,2.49231 z"
sodipodi:ry="2.4923096"
sodipodi:rx="2.4505157"
sodipodi:cy="651.49231"
@@ -84993,7 +87175,7 @@
inkscape:connector-curvature="0" />
<path
transform="matrix(1.2638889,0,0,1.2222222,32.853009,-140.1836)"
- d="m -201.22313,628.93835 c 0,0.44702 -0.36237,0.80939 -0.80939,0.80939 -0.44701,0 -0.80939,-0.36237 -0.80939,-0.80939 0,-0.44701 0.36238,-0.80938 0.80939,-0.80938 0.44702,0 0.80939,0.36237 0.80939,0.80938 z"
+ d="m -201.22313,628.93835 a 0.80938911,0.80938911 0 0 1 -0.80939,0.80939 0.80938911,0.80938911 0 0 1 -0.80939,-0.80939 0.80938911,0.80938911 0 0 1 0.80939,-0.80938 0.80938911,0.80938911 0 0 1 0.80939,0.80938 z"
sodipodi:ry="0.80938911"
sodipodi:rx="0.80938911"
sodipodi:cy="628.93835"
@@ -85009,11 +87191,11 @@
sodipodi:cy="628.93835"
sodipodi:rx="0.80938911"
sodipodi:ry="0.80938911"
- d="m -201.22313,628.93835 c 0,0.44702 -0.36237,0.80939 -0.80939,0.80939 -0.44701,0 -0.80939,-0.36237 -0.80939,-0.80939 0,-0.44701 0.36238,-0.80938 0.80939,-0.80938 0.44702,0 0.80939,0.36237 0.80939,0.80938 z"
+ d="m -201.22313,628.93835 a 0.80938911,0.80938911 0 0 1 -0.80939,0.80939 0.80938911,0.80938911 0 0 1 -0.80939,-0.80939 0.80938911,0.80938911 0 0 1 0.80939,-0.80938 0.80938911,0.80938911 0 0 1 0.80939,0.80938 z"
transform="matrix(0.77047663,0,0,0.74507628,-63.8586,161.95861)" />
<path
transform="matrix(0.77047663,0,0,0.74507628,-64.708233,162.88548)"
- d="m -201.22313,628.93835 c 0,0.44702 -0.36237,0.80939 -0.80939,0.80939 -0.44701,0 -0.80939,-0.36237 -0.80939,-0.80939 0,-0.44701 0.36238,-0.80938 0.80939,-0.80938 0.44702,0 0.80939,0.36237 0.80939,0.80938 z"
+ d="m -201.22313,628.93835 a 0.80938911,0.80938911 0 0 1 -0.80939,0.80939 0.80938911,0.80938911 0 0 1 -0.80939,-0.80939 0.80938911,0.80938911 0 0 1 0.80939,-0.80938 0.80938911,0.80938911 0 0 1 0.80939,0.80938 z"
sodipodi:ry="0.80938911"
sodipodi:rx="0.80938911"
sodipodi:cy="628.93835"
@@ -85067,37 +87249,9 @@
y="624.98871" />
</g>
</g>
- <path
- inkscape:connector-curvature="0"
- d=""
- sodipodi:nodetypes="cz"
- id="path39078-8-8-1"
- style="fill:none;stroke:#f2f2f2;stroke-width:1.60000002;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:7.40000034;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
- <g
- transform="matrix(0.90885089,0,0,0.92442422,-334.35843,100.27347)"
- style="opacity:0.85"
- id="g37781-7-2-5" />
- <g
- transform="translate(-118.46,211)"
- style="opacity:0.6"
- id="g35477-3">
- <g
- id="g35480-0" />
- <g
- id="g35486-7" />
- </g>
- <g
- transform="matrix(0,1,-1,0,197.54,88)"
- id="g35493-0"
- style="opacity:0.6">
- <g
- id="g35496-1" />
- <g
- id="g35502-6" />
- </g>
<g
style="display:inline;enable-background:new"
- id="g43585-6"
+ id="ICON_FORCE_WIND"
transform="translate(72,509.96991)">
<rect
y="148"
@@ -85165,7 +87319,7 @@
inkscape:connector-curvature="0" />
<path
transform="matrix(2.5815738,0,0,1.0580577,65.140965,9.1698698)"
- d="m -40.52941,-158 c 0,2.34721 -0.434548,4.25 -0.97059,4.25 -0.536042,0 -0.97059,-1.90279 -0.97059,-4.25 0,-2.34721 0.434548,-4.25 0.97059,-4.25 0.536042,0 0.97059,1.90279 0.97059,4.25 z"
+ d="m -40.52941,-158 a 0.9705897,4.25 0 0 1 -0.97059,4.25 0.9705897,4.25 0 0 1 -0.97059,-4.25 0.9705897,4.25 0 0 1 0.97059,-4.25 0.9705897,4.25 0 0 1 0.97059,4.25 z"
sodipodi:ry="4.25"
sodipodi:rx="0.9705897"
sodipodi:cy="-158"
@@ -85190,7 +87344,7 @@
</g>
<g
style="display:inline;enable-background:new"
- id="g24573-8"
+ id="ICON_FORCE_DRAG"
transform="translate(189,104.96991)">
<g
id="g24558-2">
@@ -85292,7 +87446,7 @@
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
sodipodi:ry="8"
sodipodi:rx="8"
sodipodi:cy="118"
@@ -85309,14 +87463,14 @@
sodipodi:cy="118"
sodipodi:rx="8"
sodipodi:ry="8"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90"
transform="matrix(-0.6011908,-0.06817113,0.06852359,-0.6012277,199.77148,303.44348)" />
<path
transform="matrix(0.4463965,0,0,0.4463971,69.575658,170.82515)"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
sodipodi:ry="8"
sodipodi:rx="8"
sodipodi:cy="118"
@@ -85331,7 +87485,7 @@
</g>
<g
style="display:inline;enable-background:new"
- id="g43234-2"
+ id="ICON_FORCE_TURBULENCE"
transform="matrix(-1,0,0,1,185,310)">
<rect
transform="scale(1,-1)"
@@ -85427,7 +87581,7 @@
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
sodipodi:ry="8"
sodipodi:rx="8"
sodipodi:cy="118"
@@ -85444,14 +87598,14 @@
sodipodi:cy="118"
sodipodi:rx="8"
sodipodi:ry="8"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90"
transform="matrix(-0.6011908,-0.06817113,0.06852359,-0.6012277,199.77148,303.44348)" />
<path
transform="matrix(0.4463965,0,0,0.4463971,69.575658,170.82515)"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
sodipodi:ry="8"
sodipodi:rx="8"
sodipodi:cy="118"
@@ -85467,7 +87621,7 @@
<g
transform="translate(0,336)"
style="display:inline;enable-background:new"
- id="g21835-7">
+ id="ICON_FORCE_FORCE">
<g
transform="translate(51,10)"
style="opacity:0.8"
@@ -85624,7 +87778,7 @@
sodipodi:cy="118"
sodipodi:rx="8"
sodipodi:ry="8"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90" />
@@ -85633,7 +87787,7 @@
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
sodipodi:ry="8"
sodipodi:rx="8"
sodipodi:cy="118"
@@ -85652,13 +87806,13 @@
sodipodi:cy="118"
sodipodi:rx="8"
sodipodi:ry="8"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
transform="matrix(0.4463965,0,0,0.4463971,69.575658,170.82515)" />
</g>
</g>
<g
style="display:inline;enable-background:new"
- id="g45967-8"
+ id="ICON_FORCE_TEXTURE"
transform="translate(198,390)">
<g
mask="url(#mask45447-7)"
@@ -85729,7 +87883,7 @@
sodipodi:cy="118"
sodipodi:rx="8"
sodipodi:ry="8"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90" />
@@ -85738,7 +87892,7 @@
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
sodipodi:ry="8"
sodipodi:rx="8"
sodipodi:cy="118"
@@ -85757,13 +87911,13 @@
sodipodi:cy="118"
sodipodi:rx="8"
sodipodi:ry="8"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
transform="matrix(0.4463965,0,0,0.4463971,69.575658,170.82515)" />
</g>
</g>
<g
style="display:inline;enable-background:new"
- id="g43252-2"
+ id="ICON_FORCE_VORTEX"
transform="matrix(-1,0,0,1,16.999998,490)">
<rect
transform="scale(1,-1)"
@@ -85832,7 +87986,7 @@
</g>
<g
style="display:inline;enable-background:new"
- id="g45137-8"
+ id="ICON_FORCE_CHARGE"
transform="translate(156,308)">
<rect
transform="scale(1,-1)"
@@ -85863,7 +88017,7 @@
sodipodi:cy="118"
sodipodi:rx="8"
sodipodi:ry="8"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90" />
@@ -85872,7 +88026,7 @@
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
sodipodi:ry="8"
sodipodi:rx="8"
sodipodi:cy="118"
@@ -85891,7 +88045,7 @@
sodipodi:cy="118"
sodipodi:rx="8"
sodipodi:ry="8"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
transform="matrix(0.5650525,0,0,0.5650532,53.91307,156.82373)" />
</g>
<g
@@ -85947,7 +88101,7 @@
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
sodipodi:ry="8"
sodipodi:rx="8"
sodipodi:cy="118"
@@ -85964,14 +88118,14 @@
sodipodi:cy="118"
sodipodi:rx="8"
sodipodi:ry="8"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90"
transform="matrix(-0.683022,-0.07745026,0.0778507,-0.683064,209.4726,314.325)" />
<path
transform="matrix(0.5719769,0,0,0.5719777,52.999044,156.00665)"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
sodipodi:ry="8"
sodipodi:rx="8"
sodipodi:cy="118"
@@ -86004,7 +88158,7 @@
</g>
<g
style="display:inline;enable-background:new"
- id="g24618-1"
+ id="ICON_FORCE_CURVE"
transform="translate(168,176)">
<rect
ry="0"
@@ -86126,7 +88280,7 @@
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
sodipodi:ry="8"
sodipodi:rx="8"
sodipodi:cy="118"
@@ -86143,14 +88297,14 @@
sodipodi:cy="118"
sodipodi:rx="8"
sodipodi:ry="8"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90"
transform="matrix(-0.683022,-0.07745026,0.0778507,-0.683064,209.4726,314.325)" />
<path
transform="matrix(0.4963171,0,0,0.4963178,62.986138,164.93452)"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
sodipodi:ry="8"
sodipodi:rx="8"
sodipodi:cy="118"
@@ -86165,7 +88319,7 @@
</g>
<g
style="display:inline;enable-background:new"
- id="g43314-2"
+ id="ICON_FORCE_LENNARDJONES"
transform="translate(177,410)">
<rect
transform="scale(1,-1)"
@@ -86183,7 +88337,7 @@
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
sodipodi:ry="8"
sodipodi:rx="8"
sodipodi:cy="118"
@@ -86200,14 +88354,14 @@
sodipodi:cy="118"
sodipodi:rx="8"
sodipodi:ry="8"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90"
transform="matrix(-0.2610878,-0.02960567,0.02975872,-0.2611039,35.872259,-102.36161)" />
<path
transform="matrix(0.2102357,0,0,0.2102362,-22.830954,-161.8877)"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
sodipodi:ry="8"
sodipodi:rx="8"
sodipodi:cy="118"
@@ -86226,7 +88380,7 @@
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
sodipodi:ry="8"
sodipodi:rx="8"
sodipodi:cy="118"
@@ -86243,14 +88397,14 @@
sodipodi:cy="118"
sodipodi:rx="8"
sodipodi:ry="8"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90"
transform="matrix(-0.5000291,-0.05669783,0.0569932,-0.5000402,23.278522,10.488883)" />
<path
transform="matrix(0.4374781,0,0,0.4374622,-93.747286,-107.62054)"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
sodipodi:ry="8"
sodipodi:rx="8"
sodipodi:cy="118"
@@ -86297,7 +88451,7 @@
sodipodi:cy="118"
sodipodi:rx="8"
sodipodi:ry="8"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90" />
@@ -86306,7 +88460,7 @@
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
sodipodi:ry="8"
sodipodi:rx="8"
sodipodi:cy="118"
@@ -86325,14 +88479,14 @@
sodipodi:cy="118"
sodipodi:rx="8"
sodipodi:ry="8"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
transform="matrix(0.2102357,0,0,0.2102362,-22.830954,-161.8877)" />
</g>
</g>
<g
style="display:inline;enable-background:new"
transform="translate(135,431)"
- id="g49017-5">
+ id="ICON_FORCE_HARMONIC">
<rect
transform="scale(1,-1)"
style="opacity:0;fill:#666666;stroke:none;stroke-width:2.29999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
@@ -86371,7 +88525,7 @@
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
sodipodi:ry="8"
sodipodi:rx="8"
sodipodi:cy="118"
@@ -86388,14 +88542,14 @@
sodipodi:cy="118"
sodipodi:rx="8"
sodipodi:ry="8"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90"
transform="matrix(-0.2610878,-0.02960567,0.02975872,-0.2611039,35.872259,-102.36161)" />
<path
transform="matrix(0.2102357,0,0,0.2102362,-22.830954,-161.8877)"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
sodipodi:ry="8"
sodipodi:rx="8"
sodipodi:cy="118"
@@ -86444,7 +88598,7 @@
sodipodi:cy="118"
sodipodi:rx="8"
sodipodi:ry="8"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90" />
@@ -86453,7 +88607,7 @@
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
sodipodi:ry="8"
sodipodi:rx="8"
sodipodi:cy="118"
@@ -86472,7 +88626,7 @@
sodipodi:cy="118"
sodipodi:rx="8"
sodipodi:ry="8"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
transform="matrix(0.2102357,0,0,0.2102362,-22.830954,-161.8877)" />
</g>
</g>
@@ -86508,7 +88662,7 @@
sodipodi:cy="118"
sodipodi:rx="8"
sodipodi:ry="8"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90" />
@@ -86517,7 +88671,7 @@
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
sodipodi:ry="8"
sodipodi:rx="8"
sodipodi:cy="118"
@@ -86536,7 +88690,7 @@
sodipodi:cy="118"
sodipodi:rx="8"
sodipodi:ry="8"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
transform="matrix(0.2102357,0,0,0.2102362,-22.830954,-161.8877)" />
</g>
</g>
@@ -86570,7 +88724,7 @@
</g>
<g
style="display:inline;enable-background:new"
- id="g33096-6"
+ id="ICON_FORCE_BOID"
transform="translate(189,147)">
<g
transform="translate(51,203)"
@@ -86744,7 +88898,7 @@
sodipodi:cy="118"
sodipodi:rx="8"
sodipodi:ry="8"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90" />
@@ -86753,7 +88907,7 @@
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
sodipodi:ry="8"
sodipodi:rx="8"
sodipodi:cy="118"
@@ -86772,13 +88926,13 @@
sodipodi:cy="118"
sodipodi:rx="8"
sodipodi:ry="8"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
transform="matrix(0.4463965,0,0,0.4463971,69.575658,170.82515)" />
</g>
</g>
<g
style="display:inline;enable-background:new"
- id="g24982-9"
+ id="ICON_FORCE_MAGNETIC"
transform="translate(21,273)">
<rect
y="73"
@@ -86835,7 +88989,7 @@
sodipodi:cy="-117.5"
sodipodi:rx="1.5"
sodipodi:ry="1.5"
- d="m -9,-117.5 c 0,0.82843 -0.6715729,1.5 -1.5,1.5 -0.828427,0 -1.5,-0.67157 -1.5,-1.5 0,-0.82843 0.671573,-1.5 1.5,-1.5 0.8284271,0 1.5,0.67157 1.5,1.5 z"
+ d="m -9,-117.5 a 1.5,1.5 0 0 1 -1.5,1.5 1.5,1.5 0 0 1 -1.5,-1.5 1.5,1.5 0 0 1 1.5,-1.5 1.5,1.5 0 0 1 1.5,1.5 z"
transform="matrix(1,0,0,1.4166681,-22,49.0835)" />
<g
id="g24584-3">
@@ -86869,22 +89023,8 @@
inkscape:connector-curvature="0" />
</g>
</g>
- <rect
- style="opacity:0;fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- id="rect37577-3"
- width="16"
- height="16"
- x="214.71344"
- y="139.35567" />
- <rect
- y="134.50435"
- x="196.07863"
- height="16"
- width="16"
- id="rect33341-6"
- style="opacity:0;fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
- <g
- id="g30024"
+ <g
+ id="ICON_AUTOMERGE_ON"
transform="translate(0.03262657,-0.06636782)">
<g
inkscape:export-ydpi="90"
@@ -87047,20 +89187,20 @@
</g>
</g>
<g
- id="g30336">
+ id="ICON_AUTOMERGE_OFF">
<g
- style="opacity:1;stroke:#646464;stroke-opacity:1"
+ style="stroke:#646464;stroke-opacity:1"
id="g44641-6-3"
transform="matrix(-1,0,0,1,565.35356,49.06678)">
<path
inkscape:connector-curvature="0"
- style="fill:none;stroke:#646464;stroke-width:3.50000000000000000;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ style="fill:none;stroke:#646464;stroke-width:3.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
d="m 347.25,100.25 -4,-4"
id="path44643-3-8"
sodipodi:nodetypes="cc" />
<path
inkscape:connector-curvature="0"
- style="fill:none;stroke:#646464;stroke-width:3.40000010000000019;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ style="fill:none;stroke:#646464;stroke-width:3.4000001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
d="m 343,100.25 0,-4.25 4.25,0"
id="path44645-3-3"
sodipodi:nodetypes="ccc" />
@@ -87107,7 +89247,7 @@
height="3"
width="2.9998772"
id="rect39229-9-81"
- style="fill:#e6e6e6;stroke:#969696;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:7.40000265000000024;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ style="fill:#e6e6e6;stroke:#969696;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:7.40000265;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
<path
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
@@ -87123,13 +89263,13 @@
transform="matrix(1,0,0,-1,-118.64644,239.06678)"
style="stroke:#646464;stroke-opacity:1">
<path
- style="fill:none;stroke:#646464;stroke-width:3.50000000000000000;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ style="fill:none;stroke:#646464;stroke-width:3.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
d="m 347.25,100.25 -4,-4"
id="path44637-0-8"
sodipodi:nodetypes="cc"
inkscape:connector-curvature="0" />
<path
- style="fill:none;stroke:#646464;stroke-width:3.40000010000000019;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ style="fill:none;stroke:#646464;stroke-width:3.4000001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
d="m 343,100.25 0,-4.25 4.25,0"
id="path44639-9-5"
sodipodi:nodetypes="ccc"
@@ -87186,222 +89326,225 @@
height="3"
width="2.9998772"
id="rect39229-9-8-3"
- style="fill:#e6e6e6;stroke:#969696;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:7.40000265000000024;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ style="fill:#e6e6e6;stroke:#969696;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:7.40000265;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
</g>
- <rect
- style="opacity:0;fill:#b3b3b3;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- id="rect17868"
- width="16"
- height="16"
- x="467"
- y="493"
- rx="0"
- ry="0" />
- <rect
- rx="1.7356256"
- style="fill:url(#linearGradient18011);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- id="rect17872"
- width="15"
- height="12"
- x="467.5"
- y="495.5"
- ry="1.7356256" />
- <path
- inkscape:connector-curvature="0"
- style="fill:url(#linearGradient18008);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- d="M 468,499.48148 468,505 c 0,0.56404 0.36784,1.00001 0.84375,1 l 12.3125,0 C 481.63216,506 482,505.56405 482,505 l 0,-5.51852 c -0.31371,0.37179 -0.76923,0.59259 -1.25,0.59259 l -11.5,0 c -0.48077,0 -0.93629,-0.2208 -1.25,-0.59259 z"
- id="path17875"
- sodipodi:nodetypes="ccccccccc" />
- <rect
- ry="1"
- y="495.5"
- x="467.5"
- height="2"
- width="15"
- id="rect17877"
- style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- rx="1.5817194" />
- <rect
- rx="1.503511"
- ry="1.503511"
- y="495.5"
- x="467.5"
- height="12"
- width="15"
- id="rect17879"
- style="fill:none;stroke:#000000;stroke-width:0.80000001;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
- <rect
- style="opacity:0.25;fill:none;stroke:#ffffff;stroke-width:0.99999988;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- id="rect17883"
- width="13.000001"
- height="10"
- x="468.5"
- y="496.5"
- ry="0.4910686"
- rx="0.5078125" />
- <g
- transform="matrix(0.7547901,0,0,1,416.02177,0)"
- id="g17893">
- <path
- transform="matrix(0.7901234,0,0,0.2000006,9.8760061,395.5997)"
- d="m 80.53125,502 c 0,1.38071 -1.133279,2.5 -2.53125,2.5 -1.397971,0 -2.53125,-1.11929 -2.53125,-2.5 0,-1.38071 1.133279,-2.5 2.53125,-2.5 1.397971,0 2.53125,1.11929 2.53125,2.5 z"
- sodipodi:ry="2.5"
- sodipodi:rx="2.5312502"
- sodipodi:cy="502"
- sodipodi:cx="78"
- id="path17895"
- style="fill:none;stroke:#999999;stroke-width:2.89550138;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- sodipodi:type="arc" />
+ <g
+ id="ICON_CAMERA_STEREO">
+ <rect
+ ry="0"
+ rx="0"
+ y="493"
+ x="467"
+ height="16"
+ width="16"
+ id="rect17868"
+ style="opacity:0;fill:#b3b3b3;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <rect
+ ry="1.7356256"
+ y="495.5"
+ x="467.5"
+ height="12"
+ width="15"
+ id="rect17872"
+ style="fill:url(#linearGradient18011);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ rx="1.7356256" />
<path
- inkscape:connector-curvature="0"
- style="fill:none;stroke:#000000;stroke-width:1.15103066;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- d="m 69.505631,495.5 0,-0.50001 c 0,-0.276 0.896,-0.5 2,-0.5 1.104,0 2,0.224 2,0.5 l 0,0.50001"
- id="path17897"
- sodipodi:nodetypes="csccc" />
+ sodipodi:nodetypes="ccccccccc"
+ id="path17875"
+ d="M 468,499.48148 468,505 c 0,0.56404 0.36784,1.00001 0.84375,1 l 12.3125,0 C 481.63216,506 482,505.56405 482,505 l 0,-5.51852 c -0.31371,0.37179 -0.76923,0.59259 -1.25,0.59259 l -11.5,0 c -0.48077,0 -0.93629,-0.2208 -1.25,-0.59259 z"
+ style="fill:url(#linearGradient18008);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <rect
+ rx="1.5817194"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect17877"
+ width="15"
+ height="2"
+ x="467.5"
+ y="495.5"
+ ry="1" />
+ <rect
+ style="fill:none;stroke:#000000;stroke-width:0.80000001;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect17879"
+ width="15"
+ height="12"
+ x="467.5"
+ y="495.5"
+ ry="1.503511"
+ rx="1.503511" />
+ <rect
+ rx="0.5078125"
+ ry="0.4910686"
+ y="496.5"
+ x="468.5"
+ height="10"
+ width="13.000001"
+ id="rect17883"
+ style="opacity:0.25;fill:none;stroke:#ffffff;stroke-width:0.99999988;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <g
+ id="g17893"
+ transform="matrix(0.7547901,0,0,1,416.02177,0)">
+ <path
+ sodipodi:type="arc"
+ style="fill:none;stroke:#999999;stroke-width:2.89550138;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="path17895"
+ sodipodi:cx="78"
+ sodipodi:cy="502"
+ sodipodi:rx="2.5312502"
+ sodipodi:ry="2.5"
+ d="M 80.53125,502 A 2.5312502,2.5 0 0 1 78,504.5 2.5312502,2.5 0 0 1 75.46875,502 2.5312502,2.5 0 0 1 78,499.5 2.5312502,2.5 0 0 1 80.53125,502 Z"
+ transform="matrix(0.7901234,0,0,0.2000006,9.8760061,395.5997)" />
+ <path
+ sodipodi:nodetypes="csccc"
+ id="path17897"
+ d="m 69.505631,495.5 0,-0.50001 c 0,-0.276 0.896,-0.5 2,-0.5 1.104,0 2,0.224 2,0.5 l 0,0.50001"
+ style="fill:none;stroke:#000000;stroke-width:1.15103066;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <rect
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect17899"
+ width="2.6497433"
+ height="1"
+ x="70.189362"
+ y="495" />
+ </g>
<rect
- y="495"
- x="70.189362"
+ y="497.5"
+ x="479"
+ height="1.5"
+ width="2"
+ id="rect17901"
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <rect
+ style="fill:url(#radialGradient17992);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.00000012;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect17903"
+ width="2"
+ height="1.5"
+ x="479"
+ y="497.5" />
+ <rect
+ y="498"
+ x="470"
height="1"
- width="2.6497433"
- id="rect17899"
- style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
- </g>
- <rect
- style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- id="rect17901"
- width="2"
- height="1.5"
- x="479"
- y="497.5" />
- <rect
- y="497.5"
- x="479"
- height="1.5"
- width="2"
- id="rect17903"
- style="fill:url(#radialGradient17992);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.00000012;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
- <rect
- style="fill:#ff0000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.00000012;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- id="rect17905"
- width="1"
- height="1"
- x="470"
- y="498" />
- <use
- x="0"
- y="0"
- xlink:href="#g18103"
- id="use18134"
- transform="translate(-6.1847313,0)"
- width="602"
- height="640" />
- <g
- id="g18103"
- transform="matrix(0.81050804,0,0,0.81050804,91.905464,90.739248)">
- <path
- transform="matrix(1.5770887,0,0,1.5999841,353.49325,-294.69208)"
- d="m 80.53125,502 c 0,1.38071 -1.133279,2.5 -2.53125,2.5 -1.397971,0 -2.53125,-1.11929 -2.53125,-2.5 0,-1.38071 1.133279,-2.5 2.53125,-2.5 1.397971,0 2.53125,1.11929 2.53125,2.5 z"
- sodipodi:ry="2.5"
- sodipodi:rx="2.5312502"
- sodipodi:cy="502"
- sodipodi:cx="78"
- id="path17885"
- style="opacity:0.1;fill:none;stroke:#000000;stroke-width:0.62952667;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- sodipodi:type="arc" />
- <path
- sodipodi:type="arc"
- style="opacity:0.7;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:0.75859177;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- id="path17881"
- sodipodi:cx="78"
- sodipodi:cy="502"
- sodipodi:rx="2.5312502"
- sodipodi:ry="2.5"
- d="m 80.53125,502 c 0,1.38071 -1.133279,2.5 -2.53125,2.5 -1.397971,0 -2.53125,-1.11929 -2.53125,-2.5 0,-1.38071 1.133279,-2.5 2.53125,-2.5 1.397971,0 2.53125,1.11929 2.53125,2.5 z"
- transform="matrix(1.3955004,0,0,1.2452423,368.18333,-114.72474)" />
- <path
- sodipodi:type="arc"
- style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:url(#linearGradient18146);stroke-width:0.97061968;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- id="path17887"
- sodipodi:cx="78"
- sodipodi:cy="502"
- sodipodi:rx="2.5312502"
- sodipodi:ry="2.5"
- d="m 80.53125,502 c 0,1.38071 -1.133279,2.5 -2.53125,2.5 -1.397971,0 -2.53125,-1.11929 -2.53125,-2.5 0,-1.38071 1.133279,-2.5 2.53125,-2.5 1.397971,0 2.53125,1.11929 2.53125,2.5 z"
- transform="matrix(1.1794014,0,0,0.8999954,384.50686,55.952303)" />
- <path
- transform="matrix(1.1827463,0,0,1.2,384.24579,-92.900024)"
- d="m 80.53125,502 c 0,1.38071 -1.133279,2.5 -2.53125,2.5 -1.397971,0 -2.53125,-1.11929 -2.53125,-2.5 0,-1.38071 1.133279,-2.5 2.53125,-2.5 1.397971,0 2.53125,1.11929 2.53125,2.5 z"
- sodipodi:ry="2.5"
- sodipodi:rx="2.5312502"
- sodipodi:cy="502"
- sodipodi:cx="78"
- id="path17889"
- style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#b3b3b3;stroke-width:0.83938956;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- sodipodi:type="arc" />
- <path
- sodipodi:type="arc"
- style="fill:none;stroke:url(#linearGradient18149);stroke-width:1.26754272;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- id="path17891"
- sodipodi:cx="78"
- sodipodi:cy="502"
- sodipodi:rx="2.5312502"
- sodipodi:ry="2.5"
- d="m 80.53125,502 c 0,1.38071 -1.133279,2.5 -2.53125,2.5 -1.397971,0 -2.53125,-1.11929 -2.53125,-2.5 0,-1.38071 1.133279,-2.5 2.53125,-2.5 1.397971,0 2.53125,1.11929 2.53125,2.5 z"
- transform="matrix(0.790122,0,0,0.787736,414.87048,114.05649)" />
- <path
- sodipodi:type="arc"
- style="fill:none;stroke:url(#radialGradient18151);stroke-width:0.67151165;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- id="path17907"
- sodipodi:cx="78"
- sodipodi:cy="502"
- sodipodi:rx="2.5312502"
- sodipodi:ry="2.5"
- d="m 80.53125,502 c 0,1.38071 -1.133279,2.5 -2.53125,2.5 -1.397971,0 -2.53125,-1.11929 -2.53125,-2.5 0,-1.38071 1.133279,-2.5 2.53125,-2.5 1.397971,0 2.53125,1.11929 2.53125,2.5 z"
- transform="matrix(1.1827463,0,0,1.2,384.24579,-92.900024)" />
+ width="1"
+ id="rect17905"
+ style="fill:#ff0000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.00000012;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <use
+ height="640"
+ width="602"
+ transform="translate(-6.1847313,0)"
+ id="use18134"
+ xlink:href="#g18103"
+ y="0"
+ x="0" />
+ <g
+ transform="matrix(0.81050804,0,0,0.81050804,91.905464,90.739248)"
+ id="g18103">
+ <path
+ sodipodi:type="arc"
+ style="opacity:0.1;fill:none;stroke:#000000;stroke-width:0.62952667;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="path17885"
+ sodipodi:cx="78"
+ sodipodi:cy="502"
+ sodipodi:rx="2.5312502"
+ sodipodi:ry="2.5"
+ d="M 80.53125,502 A 2.5312502,2.5 0 0 1 78,504.5 2.5312502,2.5 0 0 1 75.46875,502 2.5312502,2.5 0 0 1 78,499.5 2.5312502,2.5 0 0 1 80.53125,502 Z"
+ transform="matrix(1.5770887,0,0,1.5999841,353.49325,-294.69208)" />
+ <path
+ transform="matrix(1.3955004,0,0,1.2452423,368.18333,-114.72474)"
+ d="M 80.53125,502 A 2.5312502,2.5 0 0 1 78,504.5 2.5312502,2.5 0 0 1 75.46875,502 2.5312502,2.5 0 0 1 78,499.5 2.5312502,2.5 0 0 1 80.53125,502 Z"
+ sodipodi:ry="2.5"
+ sodipodi:rx="2.5312502"
+ sodipodi:cy="502"
+ sodipodi:cx="78"
+ id="path17881"
+ style="opacity:0.7;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:0.75859177;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ sodipodi:type="arc" />
+ <path
+ transform="matrix(1.1794014,0,0,0.8999954,384.50686,55.952303)"
+ d="M 80.53125,502 A 2.5312502,2.5 0 0 1 78,504.5 2.5312502,2.5 0 0 1 75.46875,502 2.5312502,2.5 0 0 1 78,499.5 2.5312502,2.5 0 0 1 80.53125,502 Z"
+ sodipodi:ry="2.5"
+ sodipodi:rx="2.5312502"
+ sodipodi:cy="502"
+ sodipodi:cx="78"
+ id="path17887"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:url(#linearGradient18146);stroke-width:0.97061968;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ sodipodi:type="arc" />
+ <path
+ sodipodi:type="arc"
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#b3b3b3;stroke-width:0.83938956;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="path17889"
+ sodipodi:cx="78"
+ sodipodi:cy="502"
+ sodipodi:rx="2.5312502"
+ sodipodi:ry="2.5"
+ d="M 80.53125,502 A 2.5312502,2.5 0 0 1 78,504.5 2.5312502,2.5 0 0 1 75.46875,502 2.5312502,2.5 0 0 1 78,499.5 2.5312502,2.5 0 0 1 80.53125,502 Z"
+ transform="matrix(1.1827463,0,0,1.2,384.24579,-92.900024)" />
+ <path
+ transform="matrix(0.790122,0,0,0.787736,414.87048,114.05649)"
+ d="M 80.53125,502 A 2.5312502,2.5 0 0 1 78,504.5 2.5312502,2.5 0 0 1 75.46875,502 2.5312502,2.5 0 0 1 78,499.5 2.5312502,2.5 0 0 1 80.53125,502 Z"
+ sodipodi:ry="2.5"
+ sodipodi:rx="2.5312502"
+ sodipodi:cy="502"
+ sodipodi:cx="78"
+ id="path17891"
+ style="fill:none;stroke:url(#linearGradient18149);stroke-width:1.26754272;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ sodipodi:type="arc" />
+ <path
+ transform="matrix(1.1827463,0,0,1.2,384.24579,-92.900024)"
+ d="M 80.53125,502 A 2.5312502,2.5 0 0 1 78,504.5 2.5312502,2.5 0 0 1 75.46875,502 2.5312502,2.5 0 0 1 78,499.5 2.5312502,2.5 0 0 1 80.53125,502 Z"
+ sodipodi:ry="2.5"
+ sodipodi:rx="2.5312502"
+ sodipodi:cy="502"
+ sodipodi:cx="78"
+ id="path17907"
+ style="fill:none;stroke:url(#radialGradient18151);stroke-width:0.67151165;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ sodipodi:type="arc" />
+ <path
+ sodipodi:type="arc"
+ style="fill:url(#radialGradient18153);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.26754272;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="path17909"
+ sodipodi:cx="78"
+ sodipodi:cy="502"
+ sodipodi:rx="2.5312502"
+ sodipodi:ry="2.5"
+ d="M 80.53125,502 A 2.5312502,2.5 0 0 1 78,504.5 2.5312502,2.5 0 0 1 75.46875,502 2.5312502,2.5 0 0 1 78,499.5 2.5312502,2.5 0 0 1 80.53125,502 Z"
+ transform="matrix(0.8888868,0,0,0.8862026,407.16682,64.626266)" />
+ <path
+ transform="matrix(0.1975308,0,0,0.1999991,460.0926,408.10045)"
+ d="M 80.53125,502 A 2.5312502,2.5 0 0 1 78,504.5 2.5312502,2.5 0 0 1 75.46875,502 2.5312502,2.5 0 0 1 78,499.5 2.5312502,2.5 0 0 1 80.53125,502 Z"
+ sodipodi:ry="2.5"
+ sodipodi:rx="2.5312502"
+ sodipodi:cy="502"
+ sodipodi:cx="78"
+ id="path17911"
+ style="opacity:0.5;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.26754272;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ sodipodi:type="arc" />
+ </g>
<path
- transform="matrix(0.8888868,0,0,0.8862026,407.16682,64.626266)"
- d="m 80.53125,502 c 0,1.38071 -1.133279,2.5 -2.53125,2.5 -1.397971,0 -2.53125,-1.11929 -2.53125,-2.5 0,-1.38071 1.133279,-2.5 2.53125,-2.5 1.397971,0 2.53125,1.11929 2.53125,2.5 z"
+ transform="matrix(-0.71872408,0.04983719,-0.0496867,-0.7165537,559.14667,859.50468)"
+ d="m 80.53125,502 a 2.5312502,2.5 0 1 1 -5.0625,0 2.5312502,2.5 0 1 1 5.0625,0 z"
sodipodi:ry="2.5"
sodipodi:rx="2.5312502"
sodipodi:cy="502"
sodipodi:cx="78"
- id="path17909"
- style="fill:url(#radialGradient18153);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.26754272;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="path17913-5"
+ style="opacity:0.7;fill:url(#linearGradient18220);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.98985863;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
sodipodi:type="arc" />
<path
sodipodi:type="arc"
- style="opacity:0.5;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.26754272;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- id="path17911"
+ style="opacity:0.7;fill:url(#linearGradient18212);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.98985863;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="path18197"
sodipodi:cx="78"
sodipodi:cy="502"
sodipodi:rx="2.5312502"
sodipodi:ry="2.5"
- d="m 80.53125,502 c 0,1.38071 -1.133279,2.5 -2.53125,2.5 -1.397971,0 -2.53125,-1.11929 -2.53125,-2.5 0,-1.38071 1.133279,-2.5 2.53125,-2.5 1.397971,0 2.53125,1.11929 2.53125,2.5 z"
- transform="matrix(0.1975308,0,0,0.1999991,460.0926,408.10045)" />
+ d="m 80.53125,502 a 2.5312502,2.5 0 1 1 -5.0625,0 2.5312502,2.5 0 1 1 5.0625,0 z"
+ transform="matrix(-0.71872408,0.04983719,-0.0496867,-0.7165537,552.92989,859.50468)" />
</g>
- <path
- sodipodi:type="arc"
- style="opacity:0.69999999999999996;fill:url(#linearGradient18220);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.98985862999999996;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- id="path17913-5"
- sodipodi:cx="78"
- sodipodi:cy="502"
- sodipodi:rx="2.5312502"
- sodipodi:ry="2.5"
- d="m 80.53125,502 a 2.5312502,2.5 0 1 1 -5.0625,0 2.5312502,2.5 0 1 1 5.0625,0 z"
- transform="matrix(-0.71872408,0.04983719,-0.0496867,-0.7165537,559.14667,859.50468)" />
- <path
- transform="matrix(-0.71872408,0.04983719,-0.0496867,-0.7165537,552.92989,859.50468)"
- d="m 80.53125,502 a 2.5312502,2.5 0 1 1 -5.0625,0 2.5312502,2.5 0 1 1 5.0625,0 z"
- sodipodi:ry="2.5"
- sodipodi:rx="2.5312502"
- sodipodi:cy="502"
- sodipodi:cx="78"
- id="path18197"
- style="opacity:0.7;fill:url(#linearGradient18212);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.98985863;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- sodipodi:type="arc" />
<g
style="display:inline;enable-background:new"
- id="g24559-2-1"
+ id="ICON_COLLAPSEMENU"
transform="translate(279.8665,506.92392)">
<rect
y="111"
@@ -87440,7 +89583,7 @@
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Pracownia\Pulpit\sss.png"
transform="translate(102.25002,373)"
- id="g28949"
+ id="ICON_FORCE_SMOKEFLOW"
style="display:inline;enable-background:new">
<rect
style="opacity:0;fill:#808000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.89999998;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:new"
@@ -87461,7 +89604,7 @@
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
sodipodi:ry="8"
sodipodi:rx="8"
sodipodi:cy="118"
@@ -87479,7 +89622,7 @@
sodipodi:cy="118"
sodipodi:rx="8"
sodipodi:ry="8"
- d="m 140,118 c 0,4.41828 -3.58172,8 -8,8 -4.41828,0 -8,-3.58172 -8,-8 0,-4.41828 3.58172,-8 8,-8 4.41828,0 8,3.58172 8,8 z"
+ d="m 140,118 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90" />
@@ -87547,10 +89690,10 @@
</g>
<g
style="display:inline;enable-background:new"
- id="g24559-2"
+ id="ICON_GRIP"
transform="translate(238,508)">
<path
- style="fill:none;stroke:#c8c8c8;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:0.8509804;display:inline;enable-background:new"
+ style="fill:none;stroke:#c8c8c8;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:0.85098039;display:inline;enable-background:new"
d="m 104,121.5 14,0"
id="path16004-2-9"
inkscape:connector-curvature="0"
@@ -87576,185 +89719,177 @@
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc" />
<path
- style="fill:#c6cbd2;stroke:#c8c8c8;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:0.8509804;display:inline;enable-background:new;fill-opacity:1"
+ style="fill:#c6cbd2;fill-opacity:1;stroke:#c8c8c8;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:0.85098039;display:inline;enable-background:new"
d="m 104,118.5 14,0"
id="path16004-2"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc" />
</g>
<g
- transform="translate(231.0079,-1.8032526e-6)"
- style="display:inline;enable-background:new"
- id="g28857-3">
+ id="ICON_LINE_DATA">
+ <path
+ id="path16893"
+ style="fill:none;stroke:#000000;stroke-width:0.87399995;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline;enable-background:new"
+ d="m 348.62424,478.9785 -2.79722,2.25264 c -0.45164,0.43278 -2.06766,1.48999 -2.83488,3.34099 -0.70812,2.10437 -1.91584,2.91305 -1.91584,2.91305 l 0.6563,0.74552 c 0,0 0.95526,-1.09547 3.13241,-1.53112 1.93333,-0.52639 3.65608,-2.44913 3.65608,-2.44913 l 2.68203,-2.62741"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cccccccc" />
+ <path
+ sodipodi:nodetypes="cccccccc"
+ inkscape:connector-curvature="0"
+ d="m 348.55771,479.10238 -2.72231,2.19232 c -0.43955,0.42119 -2.0123,1.45009 -2.75897,3.25153 -0.68915,2.048 -1.86454,2.83504 -1.86454,2.83504 l 0.63873,0.72555 c 0,0 0.92968,-1.06614 3.04853,-1.49013 1.88155,-0.51228 3.33445,-2.20812 3.57503,-2.32453 l 2.52591,-2.50648"
+ style="fill:url(#linearGradient17026);fill-opacity:1;stroke:none;display:inline;enable-background:new"
+ id="path16897" />
+ <path
+ id="path16907"
+ style="fill:url(#linearGradient17022);fill-opacity:1;stroke:none;display:inline;enable-background:new"
+ d="m 348.39209,479.42958 -2.52447,2.03299 c -0.4076,0.39058 -1.86605,1.34471 -2.55845,3.01522 -0.63908,1.89917 -1.72904,2.62901 -1.72904,2.62901 l 0.59231,0.67282 c 0,0 0.86211,-0.98866 2.82697,-1.38183 1.74481,-0.47506 3.31522,-2.1556 3.31522,-2.1556 l 2.66283,-2.30087"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cccccccc" />
+ <path
+ sodipodi:nodetypes="cccccc"
+ inkscape:connector-curvature="0"
+ id="path42945"
+ d="m 356.4118,471.99599 -8.85401,6.78865 m 0,0 c 0.48204,0.79328 2.52273,3.35178 3.70101,3.87765 m 0,0 5.60266,-5.62151"
+ style="fill:none;stroke:#000000;stroke-width:1.05365074px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new" />
+ <path
+ sodipodi:nodetypes="ccccc"
+ inkscape:connector-curvature="0"
+ id="path42949"
+ d="m 356.83119,471.7858 -9.22534,7.0573 c 0.35109,1.06864 2.63524,3.37319 3.7137,3.72187 l 5.84295,-5.72212 c 0,0 -0.0685,-1.274 -0.33131,-5.05705 z"
+ style="fill:url(#linearGradient17018);fill-opacity:1;stroke:none;display:inline;enable-background:new" />
+ <path
+ style="fill:url(#linearGradient17014);fill-opacity:1;stroke:none;display:inline;enable-background:new"
+ d="m 356.93013,474.76525 c 3.9e-4,3.18201 -3.54751,10.33668 -9.15362,4.50809 0.22597,-0.4981 8.93557,-6.84627 8.93557,-6.84627 0.11742,0.85263 0.1517,1.2913 0.21806,2.33818 z"
+ id="path43017"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cccc" />
+ <path
+ sodipodi:nodetypes="cc"
+ inkscape:connector-curvature="0"
+ id="path42981"
+ d="m 345.11258,484.70023 c 1.615,-1.38333 1.89187,-1.62391 1.89187,-1.62391"
+ style="fill:none;stroke:#000000;stroke-width:0.73395383;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline;enable-background:new"
+ inkscape:transform-center-y="0.24985078"
+ inkscape:transform-center-x="0.0087216242" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:0.48930255;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline;enable-background:new"
+ d="m 341.55701,487.70395 c 1.57524,-1.41883 3.88653,-3.26666 3.88653,-3.26666"
+ id="path16832"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cc" />
+ </g>
+ <g
+ id="ICON_MOD_WIREFRAME">
+ <path
+ style="fill:url(#linearGradient17079);fill-opacity:1;fill-rule:nonzero;stroke:#0b1728;stroke-width:0.80000001;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 307.67222,254.4997 6,3e-4 0,-11 -6,-3e-4 m 0,2.45891 3.65084,0 0,6.10992 -3.71241,0"
+ id="path27671-4-9-2"
+ sodipodi:nodetypes="cccccccc"
+ inkscape:connector-curvature="0" />
+ <rect
+ y="241.00877"
+ x="298.83606"
+ height="16"
+ width="16"
+ id="rect27661-8"
+ style="opacity:0;fill:#ff0000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
<g
- id="g17097">
- <rect
- style="opacity:0;fill:#ff0000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- id="rect27661-8"
- width="16"
- height="16"
- x="67.828156"
- y="241.00877" />
- <g
- id="g27669-35"
- style="opacity:0.55"
- transform="translate(-167.17184,-18.991228)">
- <path
- inkscape:connector-curvature="0"
- transform="matrix(0.9285719,0,0,0.9072647,16.387388,24.853058)"
- sodipodi:nodetypes="cccc"
- id="path27671-4"
- d="m 243.50439,274.05251 -6.46154,-3.3e-4 0,-12.12435 6.46154,3.3e-4"
- style="fill:url(#linearGradient42432-1);fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:0.87159598;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
- <path
- inkscape:connector-curvature="0"
- transform="matrix(0.9285719,0,0,0.9072647,16.387388,24.853058)"
- style="fill:none;stroke:#ffffff;stroke-width:1.08949494;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- d="m 243.50439,272.9503 -5.38461,-3.3e-4 0.001,-4.9503 -0.001,-4.96963 5.38461,3.3e-4"
- id="path27673-3"
- sodipodi:nodetypes="ccccc" />
- </g>
- <rect
- style="opacity:0;fill:#ff0000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- id="rect27661-8-9"
- width="16"
- height="16"
- x="67.828156"
- y="241.00877" />
- <g
- id="g27669-35-7"
- style="opacity:0.55;display:inline;enable-background:new"
- transform="translate(-167.17184,-18.99123)">
- <path
- inkscape:connector-curvature="0"
- transform="matrix(0.9285719,0,0,0.9072647,16.387388,24.853058)"
- sodipodi:nodetypes="cccc"
- id="path27671-4-9"
- d="m 243.50439,274.05251 -6.46154,-3.3e-4 0,-12.12435 6.46154,3.3e-4"
- style="fill:url(#linearGradient42432-1-2);fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:0.87159598;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
- <path
- inkscape:connector-curvature="0"
- transform="matrix(0.9285719,0,0,0.9072647,16.387388,24.853058)"
- style="fill:none;stroke:#ffffff;stroke-width:1.08949494;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- d="m 243.50439,272.9503 -5.38461,-3.3e-4 0.001,-4.9503 -0.001,-4.96963 5.38461,3.3e-4"
- id="path27673-3-9"
- sodipodi:nodetypes="ccccc" />
- </g>
- <g
- id="g27669-35-7-7"
- style="display:inline;enable-background:new"
- transform="matrix(-1,0,0,-1,319.16304,516.99093)">
- <path
- inkscape:connector-curvature="0"
- transform="matrix(0.9285719,0,0,0.9072647,16.387388,24.853058)"
- sodipodi:nodetypes="cccccccc"
- id="path27671-4-9-2"
- d="m 243.50439,261.92816 -6.46154,-3.3e-4 0,12.12435 6.46154,3.3e-4 m 0,-2.71024 -3.93168,0 0,-6.73444 3.99798,0"
- style="fill:url(#linearGradient17037);fill-opacity:1;fill-rule:nonzero;stroke:#0b1728;stroke-width:0.87159598;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
- <path
- id="path16893"
- style="fill:none;stroke:#000000;stroke-width:0.87399995;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline;enable-background:new"
- d="m 201.5467,38.012434 2.79722,-2.25264 c 0.45164,-0.43278 2.06766,-1.48999 2.83488,-3.34099 0.70812,-2.10437 1.91584,-2.91305 1.91584,-2.91305 l -0.6563,-0.74552 c 0,0 -0.95526,1.09547 -3.13241,1.53112 -1.93333,0.52639 -3.65608,2.44913 -3.65608,2.44913 l -2.68203,2.62741"
- inkscape:connector-curvature="0"
- sodipodi:nodetypes="cccccccc" />
- <path
- sodipodi:nodetypes="cccccccc"
- inkscape:connector-curvature="0"
- d="m 201.61323,37.888554 2.72231,-2.19232 c 0.43955,-0.42119 2.0123,-1.45009 2.75897,-3.25153 0.68915,-2.048 1.86454,-2.83504 1.86454,-2.83504 l -0.63873,-0.72555 c 0,0 -0.92968,1.06614 -3.04853,1.49013 -1.88155,0.51228 -3.33445,2.20812 -3.57503,2.32453 l -2.52591,2.50648"
- style="fill:url(#linearGradient16942-1);fill-opacity:1;stroke:none;display:inline;enable-background:new"
- id="path16897" />
- <path
- id="path16907"
- style="fill:url(#linearGradient16939-4);fill-opacity:1;stroke:none;display:inline;enable-background:new"
- d="m 201.77885,37.561354 2.52447,-2.03299 c 0.4076,-0.39058 1.86605,-1.34471 2.55845,-3.01522 0.63908,-1.89917 1.72904,-2.62901 1.72904,-2.62901 l -0.59231,-0.67282 c 0,0 -0.86211,0.98866 -2.82697,1.38183 -1.74481,0.47506 -3.31522,2.1556 -3.31522,2.1556 l -2.66283,2.30087"
- inkscape:connector-curvature="0"
- sodipodi:nodetypes="cccccccc" />
- <path
- sodipodi:nodetypes="cccccc"
- inkscape:connector-curvature="0"
- id="path42945"
- d="m 193.75914,44.994944 8.85401,-6.78865 m 0,0 c -0.48204,-0.79328 -2.52273,-3.35178 -3.70101,-3.87765 m 0,0 -5.60266,5.62151"
- style="fill:none;stroke:#000000;stroke-width:1.05365074px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new" />
- <path
- sodipodi:nodetypes="ccccc"
- inkscape:connector-curvature="0"
- id="path42949"
- d="m 193.33975,45.205134 9.22534,-7.0573 c -0.35109,-1.06864 -2.63524,-3.37319 -3.7137,-3.72187 l -5.84295,5.72212 c 0,0 0.0685,1.274 0.33131,5.05705 z"
- style="fill:url(#linearGradient16935-4);fill-opacity:1;stroke:none;display:inline;enable-background:new" />
- <path
- style="fill:url(#linearGradient16932-1);fill-opacity:1;stroke:none;display:inline;enable-background:new"
- d="m 193.24081,42.225684 c -3.9e-4,-3.18201 3.54751,-10.33668 9.15362,-4.50809 -0.22597,0.4981 -8.93557,6.84627 -8.93557,6.84627 -0.11742,-0.85263 -0.1517,-1.2913 -0.21806,-2.33818 z"
- id="path43017"
- inkscape:connector-curvature="0"
- sodipodi:nodetypes="cccc" />
- <path
- sodipodi:nodetypes="cc"
- inkscape:connector-curvature="0"
- id="path42981"
- d="m 205.05836,32.290704 c -1.615,1.38333 -1.89187,1.62391 -1.89187,1.62391"
- style="fill:none;stroke:#000000;stroke-width:0.73395383;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline;enable-background:new"
- inkscape:transform-center-y="0.24985078"
- inkscape:transform-center-x="0.0087216242" />
- <path
- style="fill:none;stroke:#000000;stroke-width:0.48930255;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline;enable-background:new"
- d="m 208.61393,29.286984 c -1.57524,1.41883 -3.88653,3.26666 -3.88653,3.26666"
- id="path16832"
- inkscape:connector-curvature="0"
- sodipodi:nodetypes="cc" />
- </g>
+ transform="translate(63.83606,-18.99123)"
+ style="opacity:0.55"
+ id="g27669-35">
<path
- inkscape:connector-curvature="0"
- style="opacity:0.55;fill:none;stroke:#ffffff;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- d="m 76.711836,244.47852 5,3e-4 -9.3e-4,4.49123 9.3e-4,4.50877 -5,-3e-4"
- id="path27673-3-9-1"
- sodipodi:nodetypes="ccccc" />
- <g
- id="g27675-8"
- style="display:inline;enable-background:new"
- transform="matrix(0.7071068,-0.7071068,0.7071068,0.7071068,-167.52833,113.52244)">
- <path
- inkscape:connector-curvature="0"
- style="opacity:0.1;fill:none;stroke:#000000;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- d="m 72.837944,271.51561 7.071067,-7.07107"
- id="path27679-6"
- sodipodi:nodetypes="cc" />
- <path
- inkscape:connector-curvature="0"
- id="path42388-4"
- style="opacity:0.75;fill:none;stroke:#28220b;stroke-width:3;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:new"
- d="m 71.600508,272.3995 0.707107,-0.7071 m 2.121319,-2.12133 0.707107,-0.7071 m 2.121321,-2.12133 0.707107,-0.7071 m 2.121319,-2.12133 0.707107,-0.7071" />
- <path
- inkscape:connector-curvature="0"
- d="m 71.600508,272.3995 0.707107,-0.7071 m 2.121319,-2.12133 0.707107,-0.7071 m 2.121321,-2.12133 0.707107,-0.7071 m 2.121319,-2.12133 0.707107,-0.7071"
- style="fill:none;stroke:#ffe991;stroke-width:1.19999993;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- id="path42359-16" />
- </g>
- <g
- id="g27675-8-5"
- style="display:inline;enable-background:new"
- transform="matrix(0.7071068,-0.7071068,0.7071068,0.7071068,-167.52833,113.52244)">
- <path
- inkscape:connector-curvature="0"
- style="opacity:0.1;fill:none;stroke:#000000;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- d="m 72.837944,271.51561 7.071067,-7.07107"
- id="path27679-6-3"
- sodipodi:nodetypes="cc" />
- <path
- inkscape:connector-curvature="0"
- id="path42388-4-5"
- style="opacity:0.75;fill:none;stroke:#28220b;stroke-width:3;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:new"
- d="m 71.600508,272.3995 0.707107,-0.7071 m 2.121319,-2.12133 0.707107,-0.7071 m 2.121321,-2.12133 0.707107,-0.7071 m 2.121319,-2.12133 0.707107,-0.7071" />
- <path
- inkscape:connector-curvature="0"
- d="m 71.600508,272.3995 0.707107,-0.7071 m 2.121319,-2.12133 0.707107,-0.7071 m 2.121321,-2.12133 0.707107,-0.7071 m 2.121319,-2.12133 0.707107,-0.7071"
- style="fill:none;stroke:#ffe991;stroke-width:1.19999993;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- id="path42359-16-5" />
- </g>
+ style="fill:url(#linearGradient17057);fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:0.87159598;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 243.50439,274.05251 -6.46154,-3.3e-4 0,-12.12435 6.46154,3.3e-4"
+ id="path27671-4"
+ sodipodi:nodetypes="cccc"
+ transform="matrix(0.9285719,0,0,0.9072647,16.387388,24.853058)"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccccc"
+ id="path27673-3"
+ d="m 243.50439,272.9503 -5.38461,-3.3e-4 0.001,-4.9503 -0.001,-4.96963 5.38461,3.3e-4"
+ style="fill:none;stroke:#ffffff;stroke-width:1.08949494;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ transform="matrix(0.9285719,0,0,0.9072647,16.387388,24.853058)"
+ inkscape:connector-curvature="0" />
+ </g>
+ <rect
+ y="241.00877"
+ x="298.83606"
+ height="16"
+ width="16"
+ id="rect27661-8-9"
+ style="opacity:0;fill:#ff0000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <g
+ transform="translate(63.83606,-18.991232)"
+ style="opacity:0.55;display:inline;enable-background:new"
+ id="g27669-35-7">
+ <path
+ style="fill:url(#linearGradient17059);fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:0.87159598;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 243.50439,274.05251 -6.46154,-3.3e-4 0,-12.12435 6.46154,3.3e-4"
+ id="path27671-4-9"
+ sodipodi:nodetypes="cccc"
+ transform="matrix(0.9285719,0,0,0.9072647,16.387388,24.853058)"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccccc"
+ id="path27673-3-9"
+ d="m 243.50439,272.9503 -5.38461,-3.3e-4 0.001,-4.9503 -0.001,-4.96963 5.38461,3.3e-4"
+ style="fill:none;stroke:#ffffff;stroke-width:1.08949494;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ transform="matrix(0.9285719,0,0,0.9072647,16.387388,24.853058)"
+ inkscape:connector-curvature="0" />
+ </g>
+ <path
+ sodipodi:nodetypes="ccccc"
+ id="path27673-3-9-1"
+ d="m 307.71974,244.47852 5,3e-4 -9.3e-4,4.49123 9.3e-4,4.50877 -5,-3e-4"
+ style="opacity:0.55;fill:none;stroke:#ffffff;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <g
+ transform="matrix(0.7071068,-0.7071068,0.7071068,0.7071068,63.47957,113.52244)"
+ style="display:inline;enable-background:new"
+ id="g27675-8">
+ <path
+ sodipodi:nodetypes="cc"
+ id="path27679-6"
+ d="m 72.837944,271.51561 7.071067,-7.07107"
+ style="opacity:0.1;fill:none;stroke:#000000;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ d="m 71.600508,272.3995 0.707107,-0.7071 m 2.121319,-2.12133 0.707107,-0.7071 m 2.121321,-2.12133 0.707107,-0.7071 m 2.121319,-2.12133 0.707107,-0.7071"
+ style="opacity:0.75;fill:none;stroke:#28220b;stroke-width:3;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:new"
+ id="path42388-4"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path42359-16"
+ style="fill:none;stroke:#ffe991;stroke-width:1.19999993;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 71.600508,272.3995 0.707107,-0.7071 m 2.121319,-2.12133 0.707107,-0.7071 m 2.121321,-2.12133 0.707107,-0.7071 m 2.121319,-2.12133 0.707107,-0.7071"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ transform="matrix(0.7071068,-0.7071068,0.7071068,0.7071068,63.47957,113.52244)"
+ style="display:inline;enable-background:new"
+ id="g27675-8-5">
+ <path
+ sodipodi:nodetypes="cc"
+ id="path27679-6-3"
+ d="m 72.837944,271.51561 7.071067,-7.07107"
+ style="opacity:0.1;fill:none;stroke:#000000;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ d="m 71.600508,272.3995 0.707107,-0.7071 m 2.121319,-2.12133 0.707107,-0.7071 m 2.121321,-2.12133 0.707107,-0.7071 m 2.121319,-2.12133 0.707107,-0.7071"
+ style="opacity:0.75;fill:none;stroke:#28220b;stroke-width:3;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:new"
+ id="path42388-4-5"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path42359-16-5"
+ style="fill:none;stroke:#ffe991;stroke-width:1.19999993;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 71.600508,272.3995 0.707107,-0.7071 m 2.121319,-2.12133 0.707107,-0.7071 m 2.121321,-2.12133 0.707107,-0.7071 m 2.121319,-2.12133 0.707107,-0.7071"
+ inkscape:connector-curvature="0" />
</g>
</g>
<g
style="display:inline;enable-background:new"
- id="g6603"
+ id="ICON_IPO_BOUNCE"
transform="translate(168.02769,-748.47766)">
<g
id="g16520">
@@ -87790,7 +89925,7 @@
</g>
<g
style="display:inline;enable-background:new"
- id="g6624"
+ id="ICON_IPO_LINEAR"
transform="translate(84.027695,-748.47996)">
<g
id="g6562">
@@ -87823,7 +89958,7 @@
</g>
<g
style="display:inline;enable-background:new"
- id="g6558"
+ id="ICON_IPO_CONSTANT"
transform="translate(84.027695,-748.47989)">
<path
sodipodi:nodetypes="cccc"
@@ -87854,7 +89989,7 @@
<g
style="display:inline;enable-background:new"
transform="translate(126.02769,-748.47996)"
- id="g4551">
+ id="ICON_IPO_SINE">
<g
id="g4553">
<path
@@ -87886,7 +90021,7 @@
</g>
<g
style="display:inline;enable-background:new"
- id="g7689"
+ id="ICON_IPO_QUAD"
transform="translate(147.02769,-748.47996)">
<g
id="g7691">
@@ -87930,7 +90065,7 @@
<g
style="display:inline;enable-background:new"
transform="translate(168.02769,-748.47989)"
- id="g7707">
+ id="ICON_IPO_CUBIC">
<g
id="g7709">
<path
@@ -87972,7 +90107,7 @@
</g>
<g
style="display:inline;enable-background:new"
- id="g15886"
+ id="ICON_IPO_QUINT"
transform="translate(210.02769,-748.47996)">
<g
id="g15888">
@@ -88016,7 +90151,7 @@
<g
style="display:inline;enable-background:new"
transform="translate(231.02769,-748.47989)"
- id="g15961">
+ id="ICON_IPO_EXPO">
<g
id="g15963">
<path
@@ -88048,7 +90183,7 @@
</g>
<g
style="display:inline;enable-background:new"
- id="g16027-0"
+ id="ICON_IPO_CIRC"
transform="translate(252.02766,-748.47989)">
<g
id="g16029">
@@ -88082,7 +90217,7 @@
<g
style="display:inline;enable-background:new"
transform="translate(189.02769,-748.48231)"
- id="g16464">
+ id="ICON_IPO_ELASTIC">
<path
sodipodi:nodetypes="ccsssssc"
style="color:#000000;fill:none;stroke:url(#linearGradient17044);stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
@@ -88111,7 +90246,7 @@
</g>
<g
style="display:inline;enable-background:new"
- id="g16576"
+ id="ICON_IPO_BACK"
transform="translate(210.02769,-748.47898)">
<path
inkscape:connector-curvature="0"
@@ -88142,7 +90277,7 @@
<g
style="display:inline;enable-background:new"
transform="translate(189.02769,-748.47989)"
- id="g4468">
+ id="ICON_IPO_QUART">
<g
id="g4470">
<path
@@ -88184,7 +90319,7 @@
</g>
<g
transform="translate(336.02769,-748.47858)"
- id="g20295-7-9"
+ id="ICON_IPO_EASE_IN"
style="display:inline;enable-background:new">
<g
id="g20297-2-1">
@@ -88216,7 +90351,7 @@
style="opacity:0;fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
</g>
<g
- id="g20305-4-1"
+ id="ICON_IPO_EASE_OUT"
transform="matrix(-1,0,0,-1,467.02769,1162.2412)"
style="display:inline;enable-background:new">
<g
@@ -88250,7 +90385,7 @@
</g>
<g
transform="matrix(-1,0,0,-1,488.02769,1162.2445)"
- id="g20315-6-2"
+ id="ICON_IPO_EASE_IN_OUT"
style="display:inline;enable-background:new">
<g
id="g20317-6-4">
@@ -88284,7 +90419,7 @@
<g
style="display:inline;enable-background:new"
transform="translate(84.027695,-748.48019)"
- id="g20443-5-0">
+ id="ICON_IPO_BEZIER">
<path
style="color:#000000;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#201308;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
d="m 78.565213,960.8622 -8.130425,0"
@@ -88299,7 +90434,7 @@
style="color:#000000;fill:none;stroke:#c86800;stroke-width:1.20000005;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
<path
transform="matrix(-0.83333333,0,0,0.83333,9.5,430.86427)"
- d="m -81,636 c 0,1.65685 -1.343146,3 -3,3 -1.656854,0 -3,-1.34315 -3,-3 0,-1.65685 1.343146,-3 3,-3 1.656854,0 3,1.34315 3,3 z"
+ d="m -81,636 a 3,3 0 0 1 -3,3 3,3 0 0 1 -3,-3 3,3 0 0 1 3,-3 3,3 0 0 1 3,3 z"
sodipodi:ry="3"
sodipodi:rx="3"
sodipodi:cy="636"
@@ -88332,7 +90467,7 @@
sodipodi:cy="636"
sodipodi:rx="3"
sodipodi:ry="3"
- d="m -81,636 c 0,1.65685 -1.343146,3 -3,3 -1.656854,0 -3,-1.34315 -3,-3 0,-1.65685 1.343146,-3 3,-3 1.656854,0 3,1.34315 3,3 z"
+ d="m -81,636 a 3,3 0 0 1 -3,3 3,3 0 0 1 -3,-3 3,3 0 0 1 3,-3 3,3 0 0 1 3,3 z"
transform="matrix(0.83333333,0,0,0.83333,142.49996,419.86427)" />
<path
inkscape:connector-curvature="0"
@@ -88380,7 +90515,7 @@
<g
transform="translate(-63.051518,-85.06394)"
style="display:inline;enable-background:new"
- id="g17942-1-7">
+ id="ICON_ACTION_TWEAK">
<rect
y="304"
x="278"
@@ -88550,7 +90685,7 @@
</g>
<g
style="display:inline;enable-background:new"
- id="g44081-2"
+ id="ICON_NLA_PUSHDOWN"
transform="translate(-231.54762,126.06411)">
<rect
style="opacity:0;fill:#1a1a1a;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.20000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
@@ -88630,7 +90765,7 @@
<g
transform="translate(21,0)"
style="display:inline;enable-background:new"
- id="g106643-9">
+ id="ICON_LOOPSEL">
<g
transform="translate(111,-158)"
id="g35778-7"
@@ -88716,12 +90851,12 @@
y="185" />
<g
id="g35818-3"
- style="fill:url(#radialGradient17275);display:inline;fill-opacity:1"
+ style="fill:url(#radialGradient17275);fill-opacity:1;display:inline"
transform="translate(-1080.9861,-256)">
<path
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccc"
- style="fill:url(#radialGradient17275);fill-opacity:1;fill-rule:nonzero;stroke:#542b00;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:0.86274510000000004;stroke-dasharray:none;stroke-dashoffset:7.40000265000000024;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ style="fill:url(#radialGradient17275);fill-opacity:1;fill-rule:nonzero;stroke:#542b00;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:0.8627451;stroke-dasharray:none;stroke-dashoffset:7.40000265;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
d="m 1130.4859,445.25 0,-7.5 6,2.75 0,8 -6,-3.25 z"
id="path35820-8"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
@@ -88734,7 +90869,7 @@
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
id="path35822-7"
d="m 1136.4859,448.5 -6,-3.25 0,-7.5"
- style="fill:url(#radialGradient17275);stroke:#462400;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:7.40000265000000024;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;fill-opacity:1"
+ style="fill:url(#radialGradient17275);fill-opacity:1;stroke:#462400;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:7.40000265;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
sodipodi:nodetypes="ccc" />
</g>
<g
@@ -88756,6 +90891,1039 @@
inkscape:connector-curvature="0" />
</g>
</g>
+ <g
+ style="display:inline;enable-background:new"
+ id="ICON_TRIA_RIGHT_BAR"
+ transform="translate(405,298)">
+ <rect
+ style="opacity:0;fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect24907-8"
+ width="16"
+ height="16"
+ x="62"
+ y="69" />
+ <g
+ id="g17605"
+ transform="translate(-1.5467961,-0.48613592)">
+ <path
+ sodipodi:nodetypes="ccccccccccc"
+ inkscape:connector-curvature="0"
+ d="m 72.839729,82.521675 2.731705,0 0,-10.016275 -2.731705,0 L 72.84,76.59374 68.51011,72.5 67.4632,72.53125 67.5,82.49999 68.51011,82.5 72.84,78.43749 z"
+ style="fill:url(#linearGradient17610);fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.80000001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ id="path11011-6" />
+ <path
+ sodipodi:nodetypes="ccc"
+ style="fill:none;stroke:url(#linearGradient17612);stroke-width:0.91056824px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ d="m 73.7503,81.408784 0,-7.99274 0.910568,-6.3e-5"
+ id="path10830-6"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:none;stroke:url(#linearGradient17614);stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ d="m 68.5,81.24999 0,-7.5 4,3.75"
+ id="path11013-5"
+ sodipodi:nodetypes="ccc"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <g
+ style="display:inline;enable-background:new"
+ id="ICON_TRIA_LEFT_BAR"
+ transform="matrix(-1,0,0,1,587.07183,298.10012)">
+ <rect
+ style="opacity:0;fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect24907-8-5"
+ width="16"
+ height="16"
+ x="62"
+ y="69" />
+ <g
+ id="g17605-3"
+ transform="translate(-1.5467961,-0.48613592)">
+ <path
+ sodipodi:nodetypes="ccccccccccc"
+ inkscape:connector-curvature="0"
+ d="m 72.839729,82.521675 2.731705,0 0,-10.016275 -2.731705,0 L 72.84,76.59374 68.51011,72.5 67.4632,72.53125 67.5,82.49999 68.51011,82.5 72.84,78.43749 z"
+ style="fill:url(#linearGradient17610-0);fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.80000001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ id="path11011-6-2" />
+ <path
+ sodipodi:nodetypes="ccc"
+ style="fill:none;stroke:url(#linearGradient17612-5);stroke-width:0.91056824px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ d="m 74.660868,81.408784 0,-7.99274 -0.910568,-6.3e-5"
+ id="path10830-6-2"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:none;stroke:url(#linearGradient17614-0);stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ d="m 68.5,81.24999 0,-7.5 4,3.75"
+ id="path11013-5-7"
+ sodipodi:nodetypes="ccc"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <g
+ id="ICON_TRIA_UP_BAR">
+ <rect
+ style="opacity:0;fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect24907-8-5-7"
+ width="16"
+ height="16"
+ x="-383"
+ y="-546"
+ transform="matrix(0,-1,-1,0,0,0)" />
+ <path
+ id="path11011-6-2-1"
+ style="fill:url(#linearGradient17165);fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.80000001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 532.96447,373.70707 0,-2.7317 10.01627,0 0,2.7317 -4.08834,-2.7e-4 4.09374,4.32989 -0.0312,1.04691 -9.96874,-0.0368 -1e-5,-1.01011 4.06251,-4.32989 z"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccccccccc" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccc"
+ id="path11013-5-7-1"
+ d="m 541.73615,378.0468 -3.75,-4 -3.75,4"
+ style="fill:none;stroke:url(#linearGradient17162);stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" />
+ <path
+ inkscape:connector-curvature="0"
+ inkscape:export-ydpi="90"
+ inkscape:export-xdpi="90"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png"
+ id="path10830-6-2-8"
+ d="m 542.11634,371.83103 -8.26386,0 -6e-5,0.90043"
+ style="fill:none;stroke:url(#linearGradient17838);stroke-width:0.92071104px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1;display:inline;enable-background:new"
+ sodipodi:nodetypes="ccc" />
+ </g>
+ <g
+ id="ICON_TRIA_DOWN_BAR">
+ <rect
+ style="opacity:0;fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect24907-8-8"
+ width="16"
+ height="16"
+ x="367"
+ y="-504"
+ transform="matrix(0,1,-1,0,0,0)" />
+ <path
+ id="path11011-6-8"
+ style="fill:url(#linearGradient17185);fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.80000001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 490.96446,376.29293 0,2.7317 10.01628,0 0,-2.7317 -4.08834,2.7e-4 4.09374,-4.32989 -0.0312,-1.04691 -9.96874,0.0368 -10e-6,1.01011 4.06251,4.32989 z"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccccccccc" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cc"
+ id="path11013-5-6"
+ d="m 492.23615,371.9532 7.5,0"
+ style="fill:none;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" />
+ <path
+ inkscape:connector-curvature="0"
+ inkscape:export-ydpi="90"
+ inkscape:export-xdpi="90"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png"
+ id="path10830-6-2-8-8"
+ d="m 500.10071,377.17478 -8.26386,0 -6e-5,0.90043"
+ style="fill:none;stroke:url(#linearGradient17872);stroke-width:0.92071104px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1;display:inline;enable-background:new"
+ sodipodi:nodetypes="ccc" />
+ </g>
+ <g
+ id="ICON_MOD_DATA_TRANSFER">
+ <rect
+ ry="1.4918556"
+ rx="1.4927195"
+ y="241"
+ x="320"
+ height="16"
+ width="16"
+ id="rect18203"
+ style="fill:none;stroke:none" />
+ <g
+ id="g18198"
+ transform="matrix(1.0087429,0,0,0.97482999,-108.8466,-32.496743)">
+ <path
+ style="fill:url(#linearGradient18237);fill-opacity:1;stroke:#000000;stroke-width:0.69999999;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 425.50477,292.38372 15.04989,-10.90405 -0.0101,6.77582 -9.51239,8.38266 z"
+ id="rect16727"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccc" />
+ <path
+ style="fill:none;stroke:url(#linearGradient18239);stroke-width:0.94270116;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline;enable-background:new"
+ d="m 439.79125,287.61126 -8.80214,7.81233 -3.87477,-2.96997 12.64026,-9.16307"
+ id="rect16727-8"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cccc" />
+ <path
+ transform="matrix(0.74622014,-0.66569926,0.64008794,0.76830165,0,0)"
+ style="fill:url(#linearGradient20049);fill-opacity:1;stroke:none"
+ d="m 155.67553,506.23194 -0.63498,0.7272 c 0,0 -7.96167,0.0866 -11.40538,0.0765 -1.63408,-0.005 -1.64706,-1.90745 -0.31608,-1.84971 3.85215,0.16711 12.35647,1.04592 12.35647,1.04592 z"
+ id="rect20031"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccsscc" />
+ </g>
+ <path
+ sodipodi:nodetypes="ccccc"
+ inkscape:connector-curvature="0"
+ id="path18412"
+ d="m 321.20705,242.0789 c 2.69584,0.64081 4.09152,0.77931 6.28874,0.55186 0.26517,2.2318 0.84364,4.80456 2.06664,6.25861 -2.05408,-0.68406 -3.57488,-1.60349 -4.80908,-2.47909 -1.36678,-1.11314 -2.52984,-2.47523 -3.5463,-4.33138 z"
+ style="fill:url(#linearGradient17247);fill-opacity:1;stroke:none" />
+ <path
+ sodipodi:nodetypes="ccccccc"
+ inkscape:connector-curvature="0"
+ id="rect16727-5"
+ d="m 328.56164,246.05078 c 0.74079,0.0537 1.77983,-0.45053 6.98113,-4.18925 0,3.08648 -0.0102,4.09418 -0.0102,6.60528 -0.44523,0.50349 -6.55549,5.26941 -7.72056,-6.20333 -3.16507,0.27726 -4.58746,0.0819 -7.26323,-0.75675 1.35238,2.92568 2.86698,4.41322 4.56976,5.5869 2.04461,1.35744 4.27186,2.25425 6.46319,2.69448"
+ style="fill:none;stroke:#1a1a1a;stroke-width:0.69999999;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:0.49803922;stroke-dasharray:none" />
+ <path
+ sodipodi:nodetypes="cccc"
+ inkscape:connector-curvature="0"
+ id="path18412-1"
+ d="m 324.68994,246.54277 c -0.64862,-0.68224 -1.98282,-2.30701 -2.71202,-3.8538 2.07872,0.5568 3.84489,0.49023 5.15615,0.37259 0.26517,2.2318 0.88783,4.31843 1.67994,5.209"
+ style="fill:none;stroke:url(#linearGradient17243);stroke-width:0.69999999;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:0.49803922;stroke-dasharray:none;display:inline;enable-background:new" />
+ <path
+ sodipodi:nodetypes="ccccc"
+ inkscape:connector-curvature="0"
+ id="path18485"
+ d="m 335.20234,242.58443 c 0,0.84375 -0.005,3.9971 -0.005,5.75999 -2.37119,1.76035 -4.7166,1.79719 -6.03803,-1.54307 1.55369,-1.16687 6.02002,-4.2052 6.02002,-4.2052 z"
+ style="fill:url(#linearGradient17239);fill-opacity:1;stroke:none" />
+ <path
+ sodipodi:nodetypes="ccccc"
+ inkscape:connector-curvature="0"
+ id="path20010"
+ d="m 335.21342,245.56494 c 0,0 0.0166,0.39923 0.0166,1.01647 -0.82312,0.76235 -3.0673,2.74764 -4.18325,2.66033 -0.29848,-0.14345 -0.39809,-0.20898 -0.62335,-0.46278 1.10175,-0.45288 2.17708,-1.29548 4.79,-3.21402 z"
+ style="fill:url(#linearGradient17236);fill-opacity:1;stroke:none" />
+ <path
+ sodipodi:nodetypes="cssc"
+ inkscape:connector-curvature="0"
+ id="path18570"
+ d="m 329.53955,248.87963 c -1.41211,-0.48222 -3.92872,-1.40598 -4.73299,-4.22946 -0.39317,-1.38024 1.7085,-1.41702 1.92756,-0.24049 0.45159,2.42548 1.89945,3.56397 2.80543,4.46995 z"
+ style="fill:#ffe991;fill-opacity:1;stroke:none" />
+ </g>
+ <g
+ transform="translate(-264,-151.9)"
+ id="ICON_FILE_HIDDEN"
+ style="fill:url(#linearGradient17223);fill-opacity:1;display:inline;enable-background:new">
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:url(#linearGradient17215);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;display:inline"
+ d="m 756.16666,204.50001 10.33334,0 0,14.99999 -13,0 -10e-6,-11.99999 2.66667,-3 z"
+ id="path39241-60"
+ sodipodi:nodetypes="cccccc"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <path
+ inkscape:connector-curvature="0"
+ inkscape:export-ydpi="90"
+ inkscape:export-xdpi="90"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png"
+ sodipodi:nodetypes="cccccc"
+ id="path39243-9"
+ d="m 756.16666,204.50001 10.33334,0 0,14.99999 -13,0 -10e-6,-11.99999 2.66667,-3 z"
+ style="opacity:0.3;fill:url(#radialGradient17217);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path39245-1"
+ style="fill:none;stroke:url(#linearGradient17219);stroke-width:1px;stroke-linecap:square;stroke-linejoin:miter;stroke-opacity:1;display:inline"
+ d="m 754.5,209 0,9.5 m 3.5,-13 7.5,0"
+ sodipodi:nodetypes="cccc" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cccc"
+ id="path39247-8"
+ d="m 753,208 4,0 0,-4 -4,4 z"
+ style="fill:#ffffff;fill-opacity:0.49803922;fill-rule:evenodd;stroke:none;display:inline" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cccccc"
+ id="path39249-0"
+ style="fill:none;stroke:#7f7f7f;stroke-width:0.80000001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 753.5,207.00001 0,12.49999 13,0 0,-14.99999 -10.5,0 -2.5,2.5 z"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:url(#linearGradient17221);stroke-width:1px;stroke-linecap:square;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 757.5,206.5 0,2 -2,0"
+ id="path39251-2" />
+ </g>
+ <g
+ id="ICON_BLANK1"
+ transform="matrix(1.0063645,0,0,0.9519664,-3.4857036,27.417198)">
+ <rect
+ y="577.31323"
+ x="530.11182"
+ height="16.807316"
+ width="15.898812"
+ id="rect17730"
+ style="fill:none;stroke:none" />
+ </g>
+ <g
+ id="ICON_SCULPT_DYNTOPO">
+ <rect
+ y="178"
+ x="467"
+ height="16"
+ width="16"
+ id="rect18509"
+ style="fill:none;stroke:none" />
+ </g>
+ <g
+ style="display:inline;enable-background:new"
+ id="ICON_MOD_NORMALEDIT"
+ transform="translate(105,-19)">
+ <rect
+ style="opacity:0;fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect18695-8"
+ width="16"
+ height="16"
+ x="236"
+ y="260" />
+ <g
+ id="g18697-9"
+ transform="translate(-86,370.75)">
+ <path
+ style="fill:none;stroke:#0b1728;stroke-width:1.70000005;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 330,-107.75 -5,2 0.0372,6.324398 5,2.71875 4.99999,-2.71875 L 335,-105.75 l -5,-2 z"
+ id="path18699-5"
+ sodipodi:nodetypes="ccccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path18719-5"
+ d="m 330.03717,-107.6131 -5,1.875 0,6.312498 5,2.71875 4.99999,-2.71875 0,-6.312498 -4.99999,-1.875 z"
+ style="fill:url(#linearGradient16862);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.06666696px;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <g
+ id="g18703-7"
+ transform="translate(179,-179)">
+ <path
+ id="path18707-1"
+ d="m 146.0019,73.295281 5,-1.894157 5,1.894157 -5,2.073959 -5,-2.073959 z"
+ style="fill:url(#linearGradient16864);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.06666696px;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ sodipodi:nodetypes="ccccc"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\4.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"
+ inkscape:connector-curvature="0" />
+ </g>
+ <path
+ id="path18763-1"
+ d="m 335,-105.5 -5,2 0,6.75 5,-2.75 0,-6 z"
+ style="fill:url(#linearGradient16866);fill-opacity:1;fill-rule:evenodd;stroke:none;display:inline"
+ sodipodi:nodetypes="ccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccccccc"
+ id="path18709-8"
+ d="m 334.5,-105.25 0.002,5.587357 -4.5,2.480073 -4.5,-2.480073 -0.002,-5.587357 4.5,-1.75 4.5,1.75 z"
+ style="fill:none;stroke:url(#linearGradient16868);stroke-width:0.99999982px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path18758-5"
+ style="opacity:0.8;fill:none;stroke:#d7e3f4;stroke-width:3.29999995;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline"
+ d="m 330.25,-103.25 3.25,-1.5"
+ sodipodi:nodetypes="cc"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"
+ inkscape:connector-curvature="0" />
+ <g
+ id="g18737-4"
+ style="opacity:0.7" />
+ <path
+ inkscape:export-ydpi="90"
+ inkscape:export-xdpi="90"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
+ sodipodi:nodetypes="cc"
+ d="M 330.25,-103.25 335,-105.5"
+ style="fill:#0b1728;fill-opacity:1;fill-rule:evenodd;stroke:#0b1728;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="path18760-7"
+ inkscape:connector-curvature="0" />
+ <path
+ inkscape:export-ydpi="90"
+ inkscape:export-xdpi="90"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
+ sodipodi:nodetypes="cc"
+ d="m 325.34712,-100.90914 4.75,-2.25"
+ style="fill:#dd23dd;fill-opacity:1;fill-rule:evenodd;stroke:#dd23dd;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="path18760-7-5"
+ inkscape:connector-curvature="0" />
+ <path
+ inkscape:export-ydpi="90"
+ inkscape:export-xdpi="90"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
+ sodipodi:nodetypes="cc"
+ d="m 330.29093,-103.24155 -0.0238,-5.2559"
+ style="fill:#dd23dd;fill-opacity:1;fill-rule:evenodd;stroke:#dd23dd;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="path18760-7-5-6"
+ inkscape:connector-curvature="0" />
+ <path
+ inkscape:export-ydpi="90"
+ inkscape:export-xdpi="90"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
+ sodipodi:nodetypes="cc"
+ d="m 330.36378,-103.20969 4.94432,1.78292"
+ style="fill:#dd23dd;fill-opacity:1;fill-rule:evenodd;stroke:#dd23dd;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="path18760-7-5-6-3"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <g
+ transform="translate(-63,-21)"
+ style="display:inline;enable-background:new"
+ id="ICON_LIBRARY_DATA_BROKEN"
+ inkscape:label="#ICON_LIBRARY_DATA_BROKEN">
+ <g
+ transform="translate(0,128)"
+ id="g24024-1">
+ <path
+ style="display:inline;overflow:visible;visibility:visible;opacity:0;fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;enable-background:accumulate"
+ d="m 299,365 16,0 0,16 -16,0 z"
+ id="rect22150-8"
+ inkscape:connector-curvature="0" />
+ <g
+ id="g31699">
+ <path
+ style="display:inline;fill:url(#linearGradient30825);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none"
+ d="m 303.58068,365.2991 -2.66602,3 0,6.26171 1.57617,0.53516 0.97266,-3.95312 5.41016,1.87304 1.17968,-4.50976 1.86133,0.91015 0,-4.11718 -8.33398,0 z"
+ id="path12337-3"
+ inkscape:connector-curvature="0" />
+ <path
+ inkscape:connector-curvature="0"
+ d="M -48.500031,260.50809 -46.5,260.5 l -3.1e-5,-1.99191"
+ style="display:inline;opacity:0.7;fill:none;stroke:#000000;stroke-width:0.76923829px;stroke-linecap:square;stroke-linejoin:round;stroke-opacity:1;filter:url(#filter31351-1)"
+ id="path12339-6"
+ sodipodi:nodetypes="ccc"
+ transform="matrix(1.2999758,0,0,1.2999988,365.56499,31.43979)" />
+ <path
+ sodipodi:nodetypes="cccc"
+ id="path12343-1"
+ style="display:inline;fill:none;stroke:url(#linearGradient30827);stroke-width:1px;stroke-linecap:square;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 301.9611,369.95935 0,4.75958 m 3.5,-8.25958 5.5,0"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cccc"
+ id="path12341-0"
+ d="m 300.39172,369.09809 4,0 0,-4 -4,4 z"
+ style="display:inline;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ inkscape:connector-curvature="0" />
+ <g
+ id="g17888"
+ transform="translate(18.739924,-97.15625)">
+ <path
+ id="path17882"
+ d="m 284.54204,469.10845 -3.90821,0 0.01,2.22656 2.27734,0.77344 0.88477,0 0.73633,-3 z"
+ mask="none"
+ style="display:inline;opacity:0.93999993;fill:url(#linearGradient17892);fill-opacity:1;fill-rule:nonzero;stroke:none;enable-background:new"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path17879"
+ d="m 290.335,469.48345 -2.71093,-2.375 -0.004,2 -0.95312,0 3.45312,1.19531 0.21484,-0.82031 z"
+ mask="none"
+ style="display:inline;opacity:0.93999993;fill:url(#linearGradient17894);fill-opacity:1;fill-rule:nonzero;stroke:none;enable-background:new"
+ inkscape:connector-curvature="0" />
+ </g>
+ <path
+ inkscape:connector-curvature="0"
+ id="path12345-7"
+ d="m 303.41467,365.43786 -2.5,2.5 0,6.76171 1.57617,0.53516 0.97266,-3.95312 5.41016,1.87304 1.17968,-4.50976 1.86133,0.91015 0,-4.11718 -8.5,0 z"
+ style="fill:none;stroke:#000000;stroke-width:0.80000001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ </g>
+ <g
+ id="g31703">
+ <path
+ style="display:inline;fill:url(#linearGradient30849);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none"
+ d="m 313.09408,371.63636 -1.86133,-0.91015 -1.17968,4.50976 -5.41016,-1.87304 -0.97266,3.95312 -1.57617,-0.53516 0,3.73829 11,0 0,-8.88282 z"
+ id="path30847"
+ inkscape:connector-curvature="0" />
+ <path
+ style="display:inline;opacity:0.93999993;fill:url(#linearGradient17886);fill-opacity:1;fill-rule:nonzero;stroke:none;enable-background:new"
+ mask="none"
+ d="m 310.24635,374.48985 -0.21484,0.82031 -3.45312,-1.19531 -2.125,0 -0.73633,3 3.81445,0 0.0176,2 3.98242,-3.5 -1.28516,-1.125 z"
+ id="path31751"
+ inkscape:connector-curvature="0" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path30842"
+ d="m 313.09408,371.70574 -1.86133,-0.91015 -1.17968,4.50976 -5.41016,-1.87304 -0.97266,3.95312 -1.57617,-0.53516 0,3.73829 11,0 0,-8.88282 z"
+ style="fill:none;stroke:#000000;stroke-width:0.80000001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ </g>
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#fe0000;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;filter:url(#filter17889)"
+ d="m 313.8621,371.34594 -3.26074,-1.59569 -1.17942,4.50955 -5.41146,-1.8732 -0.97129,3.95453 -2.70572,-0.90191"
+ id="path30830"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cccccc" />
+ <g
+ mask="url(#mask15700)"
+ transform="translate(-149.97053,-18.918247)"
+ id="g15634"
+ style="display:inline;enable-background:new"
+ inkscape:export-filename="C:\Documents and Settings\Pracownia\Moje dokumenty\Moje obrazy\BLENDER ICONS redesign\RELEASES\g42357.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"
+ clip-path="url(#clipPath15455)">
+ <rect
+ style="opacity:0.01000001;fill:none;stroke:#e8a930;stroke-width:2.99999928;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:7.40000248;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect15636"
+ width="1.9930685"
+ height="1.9947703"
+ x="309.50693"
+ y="239.5"
+ ry="0.99734437"
+ rx="0.98426884" />
+ <rect
+ style="fill:none;stroke:#000000;stroke-width:0.99999946;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ id="rect15638"
+ width="7.9999909"
+ height="8.000001"
+ x="299.4917"
+ y="247.35583"
+ ry="1.5185405"
+ rx="1.7691951"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <rect
+ inkscape:export-ydpi="90"
+ inkscape:export-xdpi="90"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
+ rx="0.0128693"
+ ry="0.010695697"
+ y="247.85583"
+ x="299.9917"
+ height="7.000001"
+ width="6.9999909"
+ id="rect15640"
+ style="fill:url(#linearGradient15678);fill-opacity:1;fill-rule:nonzero;stroke:none" />
+ <rect
+ inkscape:export-ydpi="90"
+ inkscape:export-xdpi="90"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
+ rx="1.5194846"
+ ry="1.4892343"
+ y="237.42615"
+ x="305.49991"
+ height="6.9921885"
+ width="8.9605312"
+ id="rect15642"
+ style="fill:none;stroke:#000000;stroke-width:0.99999958;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
+ <rect
+ style="fill:#4d4d4d;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ id="rect15644"
+ width="5.0000091"
+ height="0.99999899"
+ x="300.9917"
+ y="248.85583"
+ ry="0.0053478414"
+ rx="0.0086254831"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <rect
+ inkscape:export-ydpi="90"
+ inkscape:export-xdpi="90"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
+ rx="0"
+ ry="0"
+ y="248.35583"
+ x="300.4917"
+ height="6.000001"
+ width="5.9999909"
+ id="rect15646"
+ style="opacity:0.8;fill:none;stroke:url(#linearGradient15680);stroke-width:1.00000024;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
+ <rect
+ style="fill:url(#linearGradient15682);fill-opacity:1;fill-rule:nonzero;stroke:none"
+ id="rect15648"
+ width="7.9604402"
+ height="5.9921885"
+ x="306"
+ y="237.92615"
+ ry="0"
+ rx="0"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <rect
+ inkscape:export-ydpi="90"
+ inkscape:export-xdpi="90"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
+ rx="0.0071879062"
+ ry="0.0053478414"
+ y="238.92615"
+ x="306.98389"
+ height="0.99218851"
+ width="5.9765534"
+ id="rect15650"
+ style="fill:#4d4d4d;fill-opacity:1;fill-rule:nonzero;stroke:none" />
+ <rect
+ style="opacity:0.8;fill:none;stroke:url(#linearGradient15684);stroke-width:1.00000036;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ id="rect15652"
+ width="5.9604402"
+ height="4.0030832"
+ x="306.5"
+ y="238.41525"
+ ry="0"
+ rx="0"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <rect
+ rx="0"
+ style="fill:#ffb72a;fill-opacity:1;fill-rule:nonzero;stroke:#553800;stroke-width:0.80000001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:7.40000248;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect15654"
+ width="2"
+ height="1.9882908"
+ x="313.45264"
+ y="240.50037"
+ ry="0" />
+ <rect
+ style="fill:none;stroke:#000000;stroke-width:0.99999946;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;display:inline;enable-background:new"
+ id="rect15656"
+ width="8.9614162"
+ height="7.9608927"
+ x="312.43652"
+ y="247.39494"
+ ry="1.5185405"
+ rx="1.7691951"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <rect
+ inkscape:export-ydpi="90"
+ inkscape:export-xdpi="90"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
+ rx="0.0128693"
+ ry="0.010695697"
+ y="247.8949"
+ x="312.93652"
+ height="6.9609385"
+ width="7.9614167"
+ id="rect15658"
+ style="fill:url(#linearGradient15688);fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline;enable-background:new" />
+ <rect
+ style="fill:#4d4d4d;fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline;enable-background:new"
+ id="rect15660"
+ width="5.9614167"
+ height="0.96093851"
+ x="313.93652"
+ y="248.8949"
+ ry="0.0053478414"
+ rx="0.0086254831"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <rect
+ inkscape:export-ydpi="90"
+ inkscape:export-xdpi="90"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
+ rx="0"
+ ry="0"
+ y="248.395"
+ x="313.43652"
+ height="5.9608316"
+ width="6.9614167"
+ id="rect15662"
+ style="opacity:0.8;fill:none;stroke:url(#linearGradient15690);stroke-width:1.00000024;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;display:inline;enable-background:new" />
+ <rect
+ rx="0"
+ style="fill:#ffb72a;fill-opacity:1;fill-rule:nonzero;stroke:#553800;stroke-width:0.80000001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:7.40000248;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect15664"
+ width="2"
+ height="1.9882908"
+ x="304.42139"
+ y="240.46912"
+ ry="0" />
+ <path
+ style="fill:#000000;fill-rule:evenodd;stroke:#000000;stroke-width:3;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline;enable-background:new"
+ d="m 304.05985,242.89398 5.95666,5.92541"
+ id="path15666"
+ sodipodi:nodetypes="cc"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#000000;fill-rule:evenodd;stroke:#000000;stroke-width:3;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline;enable-background:new"
+ d="m 316.05011,242.91732 -6.03144,5.909"
+ id="path15668"
+ sodipodi:nodetypes="cc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path15670"
+ d="m 315.98761,242.94305 -5.93475,5.88889"
+ style="fill:none;stroke:url(#linearGradient15692);stroke-width:1.20000005;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:new"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path15672"
+ d="m 304.05985,242.89398 5.96875,5.95312"
+ style="fill:none;stroke:url(#linearGradient15694);stroke-width:1.20000005;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:new"
+ inkscape:connector-curvature="0" />
+ <ellipse
+ sodipodi:ry="0.61330098"
+ sodipodi:rx="0.59120387"
+ sodipodi:cy="242.89087"
+ sodipodi:cx="304.0946"
+ style="opacity:0.51799999;color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="ellipse15674"
+ cx="304.0946"
+ cy="242.89087"
+ rx="0.59120387"
+ ry="0.61330098"
+ d="m 304.68581,242.89087 c 0,0.33872 -0.26469,0.6133 -0.59121,0.6133 -0.32651,0 -0.5912,-0.27458 -0.5912,-0.6133 0,-0.33872 0.26469,-0.6133 0.5912,-0.6133 0.32652,0 0.59121,0.27458 0.59121,0.6133 z" />
+ <ellipse
+ sodipodi:ry="0.61330098"
+ sodipodi:rx="0.59120387"
+ sodipodi:cy="242.95337"
+ sodipodi:cx="315.98523"
+ style="opacity:0.51799999;color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="ellipse15676"
+ cx="315.98523"
+ cy="242.95337"
+ rx="0.59120387"
+ ry="0.61330098"
+ d="m 316.57643,242.95337 c 0,0.33872 -0.26469,0.6133 -0.5912,0.6133 -0.32651,0 -0.5912,-0.27458 -0.5912,-0.6133 0,-0.33872 0.26469,-0.6133 0.5912,-0.6133 0.32651,0 0.5912,0.27458 0.5912,0.6133 z" />
+ </g>
+ <g
+ clip-path="url(#clipPath15455-9)"
+ inkscape:export-ydpi="90"
+ inkscape:export-xdpi="90"
+ inkscape:export-filename="C:\Documents and Settings\Pracownia\Moje dokumenty\Moje obrazy\BLENDER ICONS redesign\RELEASES\g42357.png"
+ style="opacity:0.65;display:inline;filter:url(#filter15388);enable-background:new"
+ id="g15325"
+ transform="translate(-170.98527,-18.905399)"
+ mask="url(#mask15700-4)">
+ <rect
+ rx="0.98426884"
+ ry="0.99734437"
+ y="239.5"
+ x="309.50693"
+ height="1.9947703"
+ width="1.9930685"
+ id="rect15327"
+ style="opacity:0.01000001;fill:none;stroke:#e8a930;stroke-width:2.99999928;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:7.40000248;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <rect
+ inkscape:export-ydpi="90"
+ inkscape:export-xdpi="90"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
+ rx="1.7691951"
+ ry="1.5185405"
+ y="247.35583"
+ x="299.4917"
+ height="8.000001"
+ width="7.9999909"
+ id="rect15329"
+ style="fill:none;stroke:#000000;stroke-width:0.99999946;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
+ <rect
+ style="fill:url(#linearGradient15371);fill-opacity:1;fill-rule:nonzero;stroke:none"
+ id="rect15331"
+ width="6.9999909"
+ height="7.000001"
+ x="299.9917"
+ y="247.85583"
+ ry="0.010695697"
+ rx="0.0128693"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <rect
+ style="fill:none;stroke:#000000;stroke-width:0.99999958;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ id="rect15333"
+ width="8.9605312"
+ height="6.9921885"
+ x="305.49991"
+ y="237.42615"
+ ry="1.4892343"
+ rx="1.5194846"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <rect
+ inkscape:export-ydpi="90"
+ inkscape:export-xdpi="90"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
+ rx="0.0086254831"
+ ry="0.0053478414"
+ y="248.85583"
+ x="300.9917"
+ height="0.99999899"
+ width="5.0000091"
+ id="rect15335"
+ style="fill:#4d4d4d;fill-opacity:1;fill-rule:nonzero;stroke:none" />
+ <rect
+ style="opacity:0.8;fill:none;stroke:url(#linearGradient15373);stroke-width:1.00000024;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ id="rect15337"
+ width="5.9999909"
+ height="6.000001"
+ x="300.4917"
+ y="248.35583"
+ ry="0"
+ rx="0"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <rect
+ inkscape:export-ydpi="90"
+ inkscape:export-xdpi="90"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
+ rx="0"
+ ry="0"
+ y="237.92615"
+ x="306"
+ height="5.9921885"
+ width="7.9604402"
+ id="rect15339"
+ style="fill:url(#linearGradient15375);fill-opacity:1;fill-rule:nonzero;stroke:none" />
+ <rect
+ style="fill:#4d4d4d;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ id="rect15341"
+ width="5.9765534"
+ height="0.99218851"
+ x="306.98389"
+ y="238.92615"
+ ry="0.0053478414"
+ rx="0.0071879062"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <rect
+ inkscape:export-ydpi="90"
+ inkscape:export-xdpi="90"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
+ rx="0"
+ ry="0"
+ y="238.41525"
+ x="306.5"
+ height="4.0030832"
+ width="5.9604402"
+ id="rect15343"
+ style="opacity:0.8;fill:none;stroke:url(#linearGradient15377);stroke-width:1.00000036;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
+ <rect
+ ry="0"
+ y="240.50037"
+ x="313.45264"
+ height="1.9882908"
+ width="2"
+ id="rect15345"
+ style="fill:#ffb72a;fill-opacity:1;fill-rule:nonzero;stroke:#553800;stroke-width:0.80000001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:7.40000248;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ rx="0" />
+ <rect
+ inkscape:export-ydpi="90"
+ inkscape:export-xdpi="90"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
+ rx="1.7691951"
+ ry="1.5185405"
+ y="247.39494"
+ x="312.43652"
+ height="7.9608927"
+ width="8.9614162"
+ id="rect15347"
+ style="fill:none;stroke:#000000;stroke-width:0.99999946;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;display:inline;enable-background:new" />
+ <rect
+ style="fill:url(#linearGradient15379);fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline;enable-background:new"
+ id="rect15349"
+ width="7.9614167"
+ height="6.9609385"
+ x="312.93652"
+ y="247.8949"
+ ry="0.010695697"
+ rx="0.0128693"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <rect
+ inkscape:export-ydpi="90"
+ inkscape:export-xdpi="90"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
+ rx="0.0086254831"
+ ry="0.0053478414"
+ y="248.8949"
+ x="313.93652"
+ height="0.96093851"
+ width="5.9614167"
+ id="rect15351"
+ style="fill:#4d4d4d;fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline;enable-background:new" />
+ <rect
+ style="opacity:0.8;fill:none;stroke:url(#linearGradient15381);stroke-width:1.00000024;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;display:inline;enable-background:new"
+ id="rect15354"
+ width="6.9614167"
+ height="5.9608316"
+ x="313.43652"
+ y="248.395"
+ ry="0"
+ rx="0"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <rect
+ ry="0"
+ y="240.46912"
+ x="304.42139"
+ height="1.9882908"
+ width="2"
+ id="rect15356"
+ style="fill:#ffb72a;fill-opacity:1;fill-rule:nonzero;stroke:#553800;stroke-width:0.80000001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:7.40000248;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ rx="0" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cc"
+ id="path15358"
+ d="m 304.05985,242.89398 5.95666,5.92541"
+ style="fill:#000000;fill-rule:evenodd;stroke:#000000;stroke-width:3;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline;enable-background:new" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cc"
+ id="path15360"
+ d="m 316.05011,242.91732 -6.03144,5.909"
+ style="fill:#000000;fill-rule:evenodd;stroke:#000000;stroke-width:3;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline;enable-background:new" />
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:url(#linearGradient15384);stroke-width:1.20000005;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:new"
+ d="m 315.98761,242.94305 -5.93475,5.88889"
+ id="path15362"
+ sodipodi:nodetypes="cc" />
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:url(#linearGradient15386);stroke-width:1.20000005;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:new"
+ d="m 304.05985,242.89398 5.96875,5.95312"
+ id="path15364"
+ sodipodi:nodetypes="cc" />
+ <ellipse
+ sodipodi:ry="0.61330098"
+ sodipodi:rx="0.59120387"
+ sodipodi:cy="242.89087"
+ sodipodi:cx="304.0946"
+ ry="0.61330098"
+ rx="0.59120387"
+ cy="242.89087"
+ cx="304.0946"
+ id="ellipse15366"
+ style="opacity:0.51799999;color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 304.68581,242.89087 c 0,0.33872 -0.26469,0.6133 -0.59121,0.6133 -0.32651,0 -0.5912,-0.27458 -0.5912,-0.6133 0,-0.33872 0.26469,-0.6133 0.5912,-0.6133 0.32652,0 0.59121,0.27458 0.59121,0.6133 z" />
+ <ellipse
+ sodipodi:ry="0.61330098"
+ sodipodi:rx="0.59120387"
+ sodipodi:cy="242.95337"
+ sodipodi:cx="315.98523"
+ ry="0.61330098"
+ rx="0.59120387"
+ cy="242.95337"
+ cx="315.98523"
+ id="ellipse15368"
+ style="opacity:0.51799999;color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 316.57643,242.95337 c 0,0.33872 -0.26469,0.6133 -0.5912,0.6133 -0.32651,0 -0.5912,-0.27458 -0.5912,-0.6133 0,-0.33872 0.26469,-0.6133 0.5912,-0.6133 0.32651,0 0.5912,0.27458 0.5912,0.6133 z" />
+ </g>
+ <g
+ transform="translate(189.00803,-79.37555)"
+ style="display:inline;enable-background:new"
+ id="g14119">
+ <g
+ id="g16949">
+ <rect
+ style="color:#000000;fill:#272727;fill-opacity:1;stroke:none;stroke-width:1.20000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:new"
+ id="rect15992"
+ width="2"
+ height="7"
+ x="134.47968"
+ y="134"
+ ry="1" />
+ <rect
+ style="color:#000000;fill:#272727;fill-opacity:1;stroke:none;stroke-width:1.20000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:new"
+ id="rect15994"
+ width="2"
+ height="7"
+ x="141.55502"
+ y="134"
+ ry="1" />
+ <rect
+ ry="1"
+ y="136"
+ x="131.25"
+ height="3"
+ width="15.5"
+ id="rect15926"
+ style="color:#000000;fill:#272727;fill-opacity:1;stroke:none;stroke-width:1.20000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:new" />
+ <rect
+ ry="1"
+ y="132.25"
+ x="131.25"
+ height="10.5"
+ width="2.5"
+ id="rect15930"
+ style="color:#000000;fill:#272727;fill-opacity:1;stroke:none;stroke-width:1.20000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:new" />
+ <rect
+ ry="1"
+ y="132.25"
+ x="144.25"
+ height="10.5"
+ width="2.5"
+ id="rect15938"
+ style="color:#000000;fill:#272727;fill-opacity:1;stroke:none;stroke-width:1.20000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:new" />
+ <g
+ id="g16016-6"
+ style="fill:url(#radialGradient16031);fill-opacity:1">
+ <rect
+ style="color:#000000;fill:url(#radialGradient14206);fill-opacity:1;stroke:none;stroke-width:1.20000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:new"
+ id="rect15946"
+ width="1"
+ height="9"
+ x="132"
+ y="133"
+ ry="0.5" />
+ <rect
+ style="color:#000000;fill:url(#radialGradient14208);fill-opacity:1;stroke:none;stroke-width:1.20000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:new"
+ id="rect15946-7"
+ width="1"
+ height="9"
+ x="145"
+ y="133"
+ ry="0.5" />
+ <rect
+ ry="0.5"
+ y="137"
+ x="132"
+ height="1"
+ width="14"
+ id="rect15972"
+ style="color:#000000;fill:url(#radialGradient14210);fill-opacity:1;stroke:none;stroke-width:1.20000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:new" />
+ <rect
+ ry="1"
+ y="135"
+ x="134.97968"
+ height="5"
+ width="1"
+ id="rect15996"
+ style="color:#000000;fill:url(#radialGradient16945);fill-opacity:1;stroke:none;stroke-width:1.20000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:new" />
+ <rect
+ ry="1"
+ y="135"
+ x="142.05502"
+ height="5"
+ width="1"
+ id="rect15998"
+ style="color:#000000;fill:url(#radialGradient16947);fill-opacity:1;stroke:none;stroke-width:1.20000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:new" />
+ </g>
+ <rect
+ style="opacity:0.51499999;color:#000000;fill:#0065ff;fill-opacity:1;stroke:none;stroke-width:1.20000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:new"
+ id="rect15974"
+ width="4"
+ height="11"
+ x="137"
+ y="132"
+ ry="1" />
+ <rect
+ ry="1"
+ y="133"
+ x="138"
+ height="9"
+ width="2"
+ id="rect15944"
+ style="color:#000000;fill:url(#radialGradient14216);fill-opacity:1;stroke:none;stroke-width:1.20000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:new" />
+ </g>
+ </g>
+ </g>
+ </g>
</g>
<g
inkscape:groupmode="layer"
diff --git a/release/datafiles/blender_icons16/icon16_border_lasso.dat b/release/datafiles/blender_icons16/icon16_border_lasso.dat
index ef9aca6f770..d9f85920e42 100644
--- a/release/datafiles/blender_icons16/icon16_border_lasso.dat
+++ b/release/datafiles/blender_icons16/icon16_border_lasso.dat
Binary files differ
diff --git a/release/datafiles/blender_icons16/icon16_camera_stereo.dat b/release/datafiles/blender_icons16/icon16_camera_stereo.dat
index 0ccc1a69ee6..77fe8c0b686 100644
--- a/release/datafiles/blender_icons16/icon16_camera_stereo.dat
+++ b/release/datafiles/blender_icons16/icon16_camera_stereo.dat
Binary files differ
diff --git a/release/datafiles/blender_icons16/icon16_disclosure_tri_down.dat b/release/datafiles/blender_icons16/icon16_disclosure_tri_down.dat
index 7d2df0227b1..9933c973832 100644
--- a/release/datafiles/blender_icons16/icon16_disclosure_tri_down.dat
+++ b/release/datafiles/blender_icons16/icon16_disclosure_tri_down.dat
Binary files differ
diff --git a/release/datafiles/blender_icons16/icon16_file_hidden.dat b/release/datafiles/blender_icons16/icon16_file_hidden.dat
new file mode 100644
index 00000000000..19b5eda9d6b
--- /dev/null
+++ b/release/datafiles/blender_icons16/icon16_file_hidden.dat
Binary files differ
diff --git a/release/datafiles/blender_icons16/icon16_image_rgb_alpha.dat b/release/datafiles/blender_icons16/icon16_image_rgb_alpha.dat
index d1c0facfba9..600c1af21fa 100644
--- a/release/datafiles/blender_icons16/icon16_image_rgb_alpha.dat
+++ b/release/datafiles/blender_icons16/icon16_image_rgb_alpha.dat
Binary files differ
diff --git a/release/datafiles/blender_icons16/icon16_library_data_broken.dat b/release/datafiles/blender_icons16/icon16_library_data_broken.dat
new file mode 100644
index 00000000000..613fac48c21
--- /dev/null
+++ b/release/datafiles/blender_icons16/icon16_library_data_broken.dat
Binary files differ
diff --git a/release/datafiles/blender_icons16/icon16_mod_data_transfer.dat b/release/datafiles/blender_icons16/icon16_mod_data_transfer.dat
new file mode 100644
index 00000000000..bc80043da78
--- /dev/null
+++ b/release/datafiles/blender_icons16/icon16_mod_data_transfer.dat
Binary files differ
diff --git a/release/datafiles/blender_icons16/icon16_mod_normaledit.dat b/release/datafiles/blender_icons16/icon16_mod_normaledit.dat
new file mode 100644
index 00000000000..1c4898f80d8
--- /dev/null
+++ b/release/datafiles/blender_icons16/icon16_mod_normaledit.dat
Binary files differ
diff --git a/release/datafiles/blender_icons16/icon16_node_insert_off.dat b/release/datafiles/blender_icons16/icon16_node_insert_off.dat
new file mode 100644
index 00000000000..ce045a21185
--- /dev/null
+++ b/release/datafiles/blender_icons16/icon16_node_insert_off.dat
Binary files differ
diff --git a/release/datafiles/blender_icons16/icon16_node_insert_on.dat b/release/datafiles/blender_icons16/icon16_node_insert_on.dat
new file mode 100644
index 00000000000..d876a3fc121
--- /dev/null
+++ b/release/datafiles/blender_icons16/icon16_node_insert_on.dat
Binary files differ
diff --git a/release/datafiles/blender_icons16/icon16_snap_grid.dat b/release/datafiles/blender_icons16/icon16_snap_grid.dat
new file mode 100644
index 00000000000..4def9b8df2e
--- /dev/null
+++ b/release/datafiles/blender_icons16/icon16_snap_grid.dat
Binary files differ
diff --git a/release/datafiles/blender_icons16/icon16_snap_increment.dat b/release/datafiles/blender_icons16/icon16_snap_increment.dat
index 4def9b8df2e..5216afb6d72 100644
--- a/release/datafiles/blender_icons16/icon16_snap_increment.dat
+++ b/release/datafiles/blender_icons16/icon16_snap_increment.dat
Binary files differ
diff --git a/release/datafiles/blender_icons16/icon16_tria_down_bar.dat b/release/datafiles/blender_icons16/icon16_tria_down_bar.dat
new file mode 100644
index 00000000000..3b734da490a
--- /dev/null
+++ b/release/datafiles/blender_icons16/icon16_tria_down_bar.dat
Binary files differ
diff --git a/release/datafiles/blender_icons16/icon16_tria_left_bar.dat b/release/datafiles/blender_icons16/icon16_tria_left_bar.dat
new file mode 100644
index 00000000000..15826007e7b
--- /dev/null
+++ b/release/datafiles/blender_icons16/icon16_tria_left_bar.dat
Binary files differ
diff --git a/release/datafiles/blender_icons16/icon16_tria_right_bar.dat b/release/datafiles/blender_icons16/icon16_tria_right_bar.dat
new file mode 100644
index 00000000000..75b180afbd7
--- /dev/null
+++ b/release/datafiles/blender_icons16/icon16_tria_right_bar.dat
Binary files differ
diff --git a/release/datafiles/blender_icons16/icon16_tria_up_bar.dat b/release/datafiles/blender_icons16/icon16_tria_up_bar.dat
new file mode 100644
index 00000000000..b0730cafdd4
--- /dev/null
+++ b/release/datafiles/blender_icons16/icon16_tria_up_bar.dat
Binary files differ
diff --git a/release/datafiles/blender_icons32/icon32_border_lasso.dat b/release/datafiles/blender_icons32/icon32_border_lasso.dat
index 186e16524fd..8be83a26fd2 100644
--- a/release/datafiles/blender_icons32/icon32_border_lasso.dat
+++ b/release/datafiles/blender_icons32/icon32_border_lasso.dat
Binary files differ
diff --git a/release/datafiles/blender_icons32/icon32_camera_stereo.dat b/release/datafiles/blender_icons32/icon32_camera_stereo.dat
index 72464c72e06..b78b473e085 100644
--- a/release/datafiles/blender_icons32/icon32_camera_stereo.dat
+++ b/release/datafiles/blender_icons32/icon32_camera_stereo.dat
Binary files differ
diff --git a/release/datafiles/blender_icons32/icon32_disclosure_tri_down.dat b/release/datafiles/blender_icons32/icon32_disclosure_tri_down.dat
index adcfe24f575..61ef16becbe 100644
--- a/release/datafiles/blender_icons32/icon32_disclosure_tri_down.dat
+++ b/release/datafiles/blender_icons32/icon32_disclosure_tri_down.dat
Binary files differ
diff --git a/release/datafiles/blender_icons32/icon32_file_hidden.dat b/release/datafiles/blender_icons32/icon32_file_hidden.dat
new file mode 100644
index 00000000000..373fa44f192
--- /dev/null
+++ b/release/datafiles/blender_icons32/icon32_file_hidden.dat
Binary files differ
diff --git a/release/datafiles/blender_icons32/icon32_image_rgb_alpha.dat b/release/datafiles/blender_icons32/icon32_image_rgb_alpha.dat
index 9822cb5843e..1ea37a941a4 100644
--- a/release/datafiles/blender_icons32/icon32_image_rgb_alpha.dat
+++ b/release/datafiles/blender_icons32/icon32_image_rgb_alpha.dat
Binary files differ
diff --git a/release/datafiles/blender_icons32/icon32_library_data_broken.dat b/release/datafiles/blender_icons32/icon32_library_data_broken.dat
new file mode 100644
index 00000000000..89702a9ff9e
--- /dev/null
+++ b/release/datafiles/blender_icons32/icon32_library_data_broken.dat
Binary files differ
diff --git a/release/datafiles/blender_icons32/icon32_mod_data_transfer.dat b/release/datafiles/blender_icons32/icon32_mod_data_transfer.dat
new file mode 100644
index 00000000000..48881cfcc3b
--- /dev/null
+++ b/release/datafiles/blender_icons32/icon32_mod_data_transfer.dat
Binary files differ
diff --git a/release/datafiles/blender_icons32/icon32_mod_normaledit.dat b/release/datafiles/blender_icons32/icon32_mod_normaledit.dat
new file mode 100644
index 00000000000..26cce5507be
--- /dev/null
+++ b/release/datafiles/blender_icons32/icon32_mod_normaledit.dat
Binary files differ
diff --git a/release/datafiles/blender_icons32/icon32_node_insert_off.dat b/release/datafiles/blender_icons32/icon32_node_insert_off.dat
new file mode 100644
index 00000000000..5644724df66
--- /dev/null
+++ b/release/datafiles/blender_icons32/icon32_node_insert_off.dat
Binary files differ
diff --git a/release/datafiles/blender_icons32/icon32_node_insert_on.dat b/release/datafiles/blender_icons32/icon32_node_insert_on.dat
new file mode 100644
index 00000000000..d93798fa624
--- /dev/null
+++ b/release/datafiles/blender_icons32/icon32_node_insert_on.dat
Binary files differ
diff --git a/release/datafiles/blender_icons32/icon32_snap_grid.dat b/release/datafiles/blender_icons32/icon32_snap_grid.dat
new file mode 100644
index 00000000000..cc4c0efe3c4
--- /dev/null
+++ b/release/datafiles/blender_icons32/icon32_snap_grid.dat
Binary files differ
diff --git a/release/datafiles/blender_icons32/icon32_snap_increment.dat b/release/datafiles/blender_icons32/icon32_snap_increment.dat
index cc4c0efe3c4..eb88877e3ad 100644
--- a/release/datafiles/blender_icons32/icon32_snap_increment.dat
+++ b/release/datafiles/blender_icons32/icon32_snap_increment.dat
Binary files differ
diff --git a/release/datafiles/blender_icons32/icon32_tria_down_bar.dat b/release/datafiles/blender_icons32/icon32_tria_down_bar.dat
new file mode 100644
index 00000000000..7a00e79b711
--- /dev/null
+++ b/release/datafiles/blender_icons32/icon32_tria_down_bar.dat
Binary files differ
diff --git a/release/datafiles/blender_icons32/icon32_tria_left_bar.dat b/release/datafiles/blender_icons32/icon32_tria_left_bar.dat
new file mode 100644
index 00000000000..591b2e2b1bd
--- /dev/null
+++ b/release/datafiles/blender_icons32/icon32_tria_left_bar.dat
Binary files differ
diff --git a/release/datafiles/blender_icons32/icon32_tria_right_bar.dat b/release/datafiles/blender_icons32/icon32_tria_right_bar.dat
new file mode 100644
index 00000000000..1dae635d600
--- /dev/null
+++ b/release/datafiles/blender_icons32/icon32_tria_right_bar.dat
Binary files differ
diff --git a/release/datafiles/blender_icons32/icon32_tria_up_bar.dat b/release/datafiles/blender_icons32/icon32_tria_up_bar.dat
new file mode 100644
index 00000000000..1c7b3072f31
--- /dev/null
+++ b/release/datafiles/blender_icons32/icon32_tria_up_bar.dat
Binary files differ
diff --git a/release/datafiles/colormanagement/config.ocio b/release/datafiles/colormanagement/config.ocio
index 1d2c730ecab..1cf9a3bb36e 100644
--- a/release/datafiles/colormanagement/config.ocio
+++ b/release/datafiles/colormanagement/config.ocio
@@ -25,7 +25,7 @@ roles:
# Default color space sequencer is working in
default_sequencer: sRGB
- # Color spaces for color picking and exture painting (not internally supported yet)
+ # Color spaces for color picking and texture painting (not internally supported yet)
color_picking: Raw
texture_paint: Raw
diff --git a/release/datafiles/ctodata.py b/release/datafiles/ctodata.py
index a81a10102dc..079f6c3b918 100755
--- a/release/datafiles/ctodata.py
+++ b/release/datafiles/ctodata.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python
# -*- coding: utf-8 -*-
# ***** BEGIN GPL LICENSE BLOCK *****
diff --git a/release/datafiles/datatoc.py b/release/datafiles/datatoc.py
index f1fce08d7dd..0caef70c912 100755
--- a/release/datafiles/datatoc.py
+++ b/release/datafiles/datatoc.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python
# -*- coding: utf-8 -*-
# ***** BEGIN GPL LICENSE BLOCK *****
diff --git a/release/datafiles/fonts/droidsans.ttf.gz b/release/datafiles/fonts/droidsans.ttf.gz
index c76cf67992c..5b942162141 100644
--- a/release/datafiles/fonts/droidsans.ttf.gz
+++ b/release/datafiles/fonts/droidsans.ttf.gz
Binary files differ
diff --git a/release/datafiles/locale b/release/datafiles/locale
-Subproject 841b1b9f494b6f980da4e244bbd86ecb8a8ac0b
+Subproject c651e63a9a537624f639950f3127a1dee29205d
diff --git a/release/datafiles/prvicons.png b/release/datafiles/prvicons.png
index f8f744aadb3..7209385da9c 100644
--- a/release/datafiles/prvicons.png
+++ b/release/datafiles/prvicons.png
Binary files differ
diff --git a/release/datafiles/prvicons.svg b/release/datafiles/prvicons.svg
index 4e7bac725bd..e0894ff2dc8 100644
--- a/release/datafiles/prvicons.svg
+++ b/release/datafiles/prvicons.svg
@@ -17956,26 +17956,9 @@
</dc:publisher>
<dc:coverage />
<cc:license
- rdf:resource="http://creativecommons.org/licenses/by-nc-sa/3.0/" />
- <dc:description>This content is under CC Attribution-NonCommercial ShareAlike licence 3.0 as long as it's used for Blender 3D GUI. Any other uses are not allowed.</dc:description>
+ rdf:resource="http://www.gnu.org/licenses/old-licenses/gpl-2.0.html" />
+ <dc:description>GNU General Public License, version 2 or later.</dc:description>
</cc:Work>
- <cc:License
- rdf:about="http://creativecommons.org/licenses/by-nc-sa/3.0/">
- <cc:permits
- rdf:resource="http://creativecommons.org/ns#Reproduction" />
- <cc:permits
- rdf:resource="http://creativecommons.org/ns#Distribution" />
- <cc:requires
- rdf:resource="http://creativecommons.org/ns#Notice" />
- <cc:requires
- rdf:resource="http://creativecommons.org/ns#Attribution" />
- <cc:prohibits
- rdf:resource="http://creativecommons.org/ns#CommercialUse" />
- <cc:permits
- rdf:resource="http://creativecommons.org/ns#DerivativeWorks" />
- <cc:requires
- rdf:resource="http://creativecommons.org/ns#ShareAlike" />
- </cc:License>
</rdf:RDF>
</metadata>
<g
diff --git a/release/datafiles/splash.png b/release/datafiles/splash.png
index 76bb67b7263..f84f092d5f8 100644
--- a/release/datafiles/splash.png
+++ b/release/datafiles/splash.png
Binary files differ
diff --git a/release/datafiles/splash_2x.png b/release/datafiles/splash_2x.png
index c0eaba50460..f4c611c8cc1 100644
--- a/release/datafiles/splash_2x.png
+++ b/release/datafiles/splash_2x.png
Binary files differ
diff --git a/release/datafiles/startup.blend b/release/datafiles/startup.blend
index 8b58493fe3a..23bb2646a54 100644
--- a/release/datafiles/startup.blend
+++ b/release/datafiles/startup.blend
Binary files differ
diff --git a/release/freedesktop/blender.desktop b/release/freedesktop/blender.desktop
index 1620815517e..d661a157bfb 100644
--- a/release/freedesktop/blender.desktop
+++ b/release/freedesktop/blender.desktop
@@ -1,14 +1,85 @@
[Desktop Entry]
Name=Blender
-GenericName=3D modeller
-GenericName[es]=modelador 3D
+GenericName=3D modeler
+GenericName[ar]=3D المنمذج ثلاثي الأبعاد
+GenericName[ca]=Modelador 3D
+GenericName[cs]=3D modelování
+GenericName[da]=3D-modellering
GenericName[de]=3D-Modellierer
-GenericName[fr]=modeleur 3D
+GenericName[el]=Μοντελοποιητής 3D
+GenericName[es]=Modelador 3D
+GenericName[et]=3D modelleerija
+GenericName[fi]=3D-mallintaja
+GenericName[fr]=Modeleur 3D
+GenericName[gl]=Modelador 3D
+GenericName[hu]=3D modellező
+GenericName[it]=Modellatore 3D
+GenericName[ja]=3D モデラー
+GenericName[lt]=3D modeliavimas
+GenericName[nb]=3D-modellering
+GenericName[nl]=3D-modeller
+GenericName[pl]=Modelowanie 3D
+GenericName[pt_BR]=Modelador 3D
+GenericName[ro]=Arhitect 3D
GenericName[ru]=Редактор 3D-моделей
+GenericName[tr]=3D modelleyici
+GenericName[uk]=Редактор 3D-моделей
+GenericName[wa]=Modeleu 3D
+GenericName[zh_CN]=3D 建模
+GenericName[zh_TW]=3D 模型
Comment=3D modeling, animation, rendering and post-production
-Comment[es]=modelado 3D, animación, renderizado y post-producción
+Comment[ar]=3D النمذجة، الرسوم المتحركة، والتجسيد، وما بعد الإنتاج
+Comment[ast]=Modeláu 3D, animación, renderizáu y postproducción
+Comment[eu]=3D modelatzea, animazioa, errendatzea eta post-produkzioa
+Comment[be]=Праграма праÑторавага мадÑлÑваннÑ, анімацыі, апрацоўкі відÑа Ñ– давÑÐ´Ð·ÐµÐ½Ð½Ñ Ð²Ñ–Ð´Ñапрадукцыі
+Comment[bn]=তà§à¦°à¦¿à¦®à¦¾à¦¤à§à¦°à¦¿à¦• মডেল, অà§à¦¯à¦¾à¦¨à¦¿à¦®à§‡à¦¶à¦¨, রেনà§à¦¡à¦¾à¦°à¦¿à¦‚ à¦à¦¬à¦‚ পোসà§à¦Ÿ-উৎপাদন
+Comment[bs]=3D modeliranje, animacija, obrada i postprodukcija
+Comment[bg]=3D моделиране, анимиране, рендиране и поÑÑ‚-продукциÑ
+Comment[ca]=Modelat 3D, animació, renderització i post-producció
+Comment[ca@valencia]=Modelat 3D, animació, renderització i post-producció
+Comment[crh]=3B modelleme, animasyon, işleme ve son üretim
+Comment[cs]=3D modelování, animace, rederování a postprodukce
+Comment[da]=3D-modellering, animation, rendering og efterbehandling
Comment[de]=3D-Modellierung, Animation, Rendering und Nachbearbeitung
-Exec=blender
+Comment[nl]=3d-modelleren, animeren, renderen en post-productie
+Comment[el]=Μοντελοποίηση 3D, κινοÏμενα σχέδια, αποτÏπωση και οÏγάνωση διαδικασίας μετά-την-παÏαγωγή
+Comment[eo]=3D-modelado, animacio, renderado kaj postproduktado
+Comment[es]=Modelado 3D, animación, renderizado y post-producción
+Comment[et]=Kolmemõõtmeline modelleerimine, animeerimine, esitlemine ja järeltöötlemine
+Comment[fi]=3D-mallinnus, -animaatiot, -renderöinti ja -tuotanto
+Comment[fr]=Modélisation 3D, animation, rendu et post-production
+Comment[fr_CA]=Modélisation 3D, animation, rendu et post-production
+Comment[gl]=Modelado 3D, animación, renderizado e postprodución
+Comment[hu]=3D modellek és animációk létrehozása és szerkesztése
+Comment[is]=Þrívíddarmódel, hreyfimyndir, myndgerð og frágangur myndskeiða
+Comment[it]=Modellazione 3D, animazione, rendering e post-produzione
+Comment[ja]=3Dモデリングã€ã‚¢ãƒ‹ãƒ¡ãƒ¼ã‚·ãƒ§ãƒ³ã€ãƒ¬ãƒ³ãƒ€ãƒªãƒ³ã‚°ã€ãƒã‚¹ãƒˆãƒ—ロダクションã®ãƒ„ール
+Comment[ko]=3D 모ë¸ë§, 애니메ì´ì…˜, ë Œë”ë§ê³¼ í¬ìŠ¤íŠ¸ 프로ë•ì…˜
+Comment[lt]=3D modeliavimas, animacijų kūrimas, atvaizdavimas ir tobulinimas
+Comment[lv]=3D modelÄ“Å¡ana, animÄcija, renderÄ“Å¡ana un pÄ“capstrÄde
+Comment[ms]=Pemodelan, animasi, penerapan dan post-produksi 3D
+Comment[nb]=3D-modellering, animasjon, rendering og postproduksjon
+Comment[oc]=Modelizacion 3D, animacion, rendut e post-produccion
+Comment[pl]=Modelowanie 3D, animacja, renderowanie i postprodukcja
+Comment[pt]=Modelação 3D, animação, renderização e pós-produção
+Comment[pt_BR]=Modelagem 3D, animação, renderização e pós-produção
+Comment[ro]=Modelare, animare, afișare și post-producție 3D
+Comment[ru]=3D-моделирование, анимациÑ, рендеринг и компоновка
+Comment[sl]=3D modeliranje, animacija, izrisovanje in nadaljnje obdelovanje
+Comment[sq]=Animacion i modeleve 3D, rregullim dhe më pas prodhim
+Comment[sr]=3Д моделовање, анимација, иÑцртавање и поÑтпродукција
+Comment[sv]=3d-modellering, animering, rendering och efterbehandling
+Comment[ta]=à®®à¯à®ªà¯à®ªà®°à®¿à®®à®¾à®£ ஒபà¯à®ªà¯à®°à¯à®µà®¾à®•à¯à®•à®®à¯, அசைவூடà¯à®Ÿà®®à¯, காடà¯à®šà®¿à®¯à®¾à®•à¯à®•à®®à¯ மறà¯à®±à¯à®®à¯ உரà¯à®µà®¾à®•à¯à®•à®¤à¯à®¤à¯à®•à¯à®•à¯ பிநà¯à®¤à¯ˆà®¯ செயலà¯à®ªà®¾à®Ÿà¯à®•à®³à¯
+Comment[tg]=МоделÑозии 3D, аниматÑиÑ, пешниҳод ва иÑтеҳÑоли баъдӣ
+Comment[tr]=3B modelleme, animasyon, işleme ve son üretim
+Comment[uk]=Програма проÑторового моделюваннÑ, анімації, обробки відео та Ð´Ð¾Ð²ÐµÐ´ÐµÐ½Ð½Ñ Ð²Ñ–Ð´ÐµÐ¾Ð¿Ñ€Ð¾Ð´ÑƒÐºÑ‚Ñ–Ð²
+Comment[vi]=Tạo hình mẫu 3D, hoạt há»a, dá»±ng hình và các công việc hậu kỳ
+Comment[wa]=Modelaedje 3D, animåcion, rindou eyet après-produccion
+Comment[zh_HK]=3D 模型ã€å‹•ç•«ã€ç®—圖和後製
+Comment[zh_CN]=3D 建模ã€åŠ¨ç”»ã€æ¸²æŸ“å’ŒåŽæœŸåˆ¶ä½œ
+Comment[zh_TW]=3D 模型ã€å‹•ç•«ã€ç®—圖和後製
+Keywords=3d;cg;modeling;animation;painting;sculpting;texturing;video editing;video tracking;rendering;render engine;cycles;game engine;python;
+Exec=blender %f
Icon=blender
Terminal=false
Type=Application
diff --git a/release/scripts/addons b/release/scripts/addons
-Subproject fd695c3a81b63db072311e8516e0dbb8d447404
+Subproject 0eef469a5d444f396152376a49d7faad0ba51ab
diff --git a/release/scripts/addons_contrib b/release/scripts/addons_contrib
-Subproject 8f33ffcebed445755d3453b8f486306bcf2b142
+Subproject cf842d8bb7b0033ca4fa99f7ebedcbd3810fd27
diff --git a/release/scripts/freestyle/modules/freestyle/chainingiterators.py b/release/scripts/freestyle/modules/freestyle/chainingiterators.py
index 52f22b3e8be..fc9de6475b2 100644
--- a/release/scripts/freestyle/modules/freestyle/chainingiterators.py
+++ b/release/scripts/freestyle/modules/freestyle/chainingiterators.py
@@ -275,7 +275,7 @@ class pySketchyChainSilhouetteIterator(ChainingIterator):
class pySketchyChainingIterator(ChainingIterator):
"""
- Chaining iterator designed for sketchy style. It chaines the same
+ Chaining iterator designed for sketchy style. It chains the same
ViewEdge several times in order to produce multiple strokes per
ViewEdge.
"""
@@ -320,7 +320,7 @@ class pyFillOcclusionsRelativeChainingIterator(ChainingIterator):
Builds a pyFillOcclusionsRelativeChainingIterator object.
- :arg percent: The maximul length of the occluded part, expressed
+ :arg percent: The maximal length of the occluded part, expressed
in a percentage of the total chain length.
:type percent: float
"""
@@ -454,7 +454,7 @@ class pyFillOcclusionsAbsoluteAndRelativeChainingIterator(ChainingIterator):
Builds a pyFillOcclusionsAbsoluteAndRelativeChainingIterator object.
- :arg percent: The maximul length of the occluded part as a
+ :arg percent: The maximal length of the occluded part as a
percentage of the total chain length.
:type percent: float
:arg l: Absolute length.
@@ -524,7 +524,7 @@ class pyFillQi0AbsoluteAndRelativeChainingIterator(ChainingIterator):
Builds a pyFillQi0AbsoluteAndRelativeChainingIterator object.
- :arg percent: The maximul length of the occluded part as a
+ :arg percent: The maximal length of the occluded part as a
percentage of the total chain length.
:type percent: float
:arg l: Absolute length.
diff --git a/release/scripts/freestyle/modules/freestyle/functions.py b/release/scripts/freestyle/modules/freestyle/functions.py
index 48d9b2e2b39..426d344e8ab 100644
--- a/release/scripts/freestyle/modules/freestyle/functions.py
+++ b/release/scripts/freestyle/modules/freestyle/functions.py
@@ -189,11 +189,13 @@ class CurveMaterialF0D(UnaryFunction0DMaterial):
priority is used to pick one of the two materials at material
boundaries.
- Note: expects instances of CurvePoint to be iterated over
+ Notes: expects instances of CurvePoint to be iterated over
+ can return None if no fedge can be found
"""
def __call__(self, inter):
fe = inter.object.fedge
- assert(fe is not None), "CurveMaterialF0D: fe is None"
+ if fe is None:
+ return None
if fe.is_smooth:
return fe.material
else:
diff --git a/release/scripts/freestyle/modules/freestyle/predicates.py b/release/scripts/freestyle/modules/freestyle/predicates.py
index 68ec9e05f6e..5cbe577b956 100644
--- a/release/scripts/freestyle/modules/freestyle/predicates.py
+++ b/release/scripts/freestyle/modules/freestyle/predicates.py
@@ -43,6 +43,7 @@ __all__ = (
"FalseUP0D",
"FalseUP1D",
"Length2DBP1D",
+ "MaterialBP1D",
"NotBP1D",
"NotUP1D",
"ObjectNamesUP1D",
@@ -82,6 +83,8 @@ __all__ = (
"pyNatureUP1D",
"pyParameterUP0D",
"pyParameterUP0DGoodOne",
+ "pyProjectedXBP1D",
+ "pyProjectedYBP1D",
"pyShapeIdListUP1D",
"pyShapeIdUP1D",
"pyShuffleBP1D",
@@ -135,6 +138,8 @@ from freestyle.functions import (
GetCurvilinearAbscissaF0D,
GetDirectionalViewMapDensityF1D,
GetOccludersF1D,
+ GetProjectedXF1D,
+ GetProjectedYF1D,
GetProjectedZF1D,
GetShapeF1D,
GetSteerableViewMapDensityF1D,
@@ -146,12 +151,13 @@ from freestyle.functions import (
pyViewMapGradientNormF1D,
)
+from freestyle.utils import material_from_fedge
+
import random
# -- Unary predicates for 0D elements (vertices) -- #
-
class pyHigherCurvature2DAngleUP0D(UnaryPredicate0D):
def __init__(self, a):
UnaryPredicate0D.__init__(self)
@@ -230,9 +236,10 @@ class AndUP1D(UnaryPredicate1D):
def __init__(self, *predicates):
UnaryPredicate1D.__init__(self)
self.predicates = predicates
- # there are cases in which only one predicate is supplied (in the parameter editor)
- if len(self.predicates) < 1:
- raise ValueError("Expected one or more UnaryPredicate1D, got ", len(predicates))
+ correct_types = all(isinstance(p, UnaryPredicate1D) for p in self.predicates)
+ if not (correct_types and predicates):
+ raise TypeError("%s: Expected one or more UnaryPredicate1D, got %r" %
+ (self.__class__.__name__, self.predicates))
def __call__(self, inter):
return all(pred(inter) for pred in self.predicates)
@@ -242,9 +249,10 @@ class OrUP1D(UnaryPredicate1D):
def __init__(self, *predicates):
UnaryPredicate1D.__init__(self)
self.predicates = predicates
- # there are cases in which only one predicate is supplied (in the parameter editor)
- if len(self.predicates) < 1:
- raise ValueError("Expected one or more UnaryPredicate1D, got ", len(predicates))
+ correct_types = all(isinstance(p, UnaryPredicate1D) for p in self.predicates)
+ if not (correct_types and predicates):
+ raise TypeError("%s: Expected one or more UnaryPredicate1D, got %r" %
+ (self.__class__.__name__, self.predicates))
def __call__(self, inter):
return any(pred(inter) for pred in self.predicates)
@@ -253,10 +261,10 @@ class OrUP1D(UnaryPredicate1D):
class NotUP1D(UnaryPredicate1D):
def __init__(self, pred):
UnaryPredicate1D.__init__(self)
- self.__pred = pred
+ self.predicate = pred
def __call__(self, inter):
- return not self.__pred(inter)
+ return not self.predicate(inter)
class ObjectNamesUP1D(UnaryPredicate1D):
@@ -559,32 +567,36 @@ class pyClosedCurveUP1D(UnaryPredicate1D):
class AndBP1D(BinaryPredicate1D):
def __init__(self, *predicates):
BinaryPredicate1D.__init__(self)
- self._predicates = predicates
- if len(self.predicates) < 2:
- raise ValueError("Expected two or more BinaryPredicate1D, got ", len(predictates))
+ self.predicates = tuple(predicates)
+ correct_types = all(isinstance(p, BinaryPredicate1D) for p in self.predicates)
+ if not (correct_types and predicates):
+ raise TypeError("%s: Expected one or more BinaryPredicate1D, got %r" %
+ (self.__class__.__name__, self.predicates))
def __call__(self, i1, i2):
- return all(pred(i1, i2) for pred in self._predicates)
+ return all(pred(i1, i2) for pred in self.predicates)
class OrBP1D(BinaryPredicate1D):
def __init__(self, *predicates):
BinaryPredicate1D.__init__(self)
- self._predicates = predicates
- if len(self.predicates) < 2:
- raise ValueError("Expected two or more BinaryPredicate1D, got ", len(predictates))
+ self.predicates = tuple(predicates)
+ correct_types = all(isinstance(p, BinaryPredicate1D) for p in self.predicates)
+ if not (correct_types and predicates):
+ raise TypeError("%s: Expected one or more BinaryPredicate1D, got %r" %
+ (self.__class__.__name__, self.predicates))
def __call__(self, i1, i2):
- return any(pred(i1, i2) for pred in self._predicates)
+ return any(pred(i1, i2) for pred in self.predicates)
class NotBP1D(BinaryPredicate1D):
def __init__(self, predicate):
BinaryPredicate1D.__init__(self)
- self._predicate = predicate
+ self.predicate = predicate
def __call__(self, i1, i2):
- return (not self._precicate(i1, i2))
+ return (not self.predicate(i1, i2))
class pyZBP1D(BinaryPredicate1D):
@@ -596,6 +608,24 @@ class pyZBP1D(BinaryPredicate1D):
return (self.func(i1) > self.func(i2))
+class pyProjectedXBP1D(BinaryPredicate1D):
+ def __init__(self, iType=IntegrationType.MEAN):
+ BinaryPredicate1D.__init__(self)
+ self.func = GetProjectedXF1D(iType)
+
+ def __call__(self, i1, i2):
+ return (self.func(i1) > self.func(i2))
+
+
+class pyProjectedYBP1D(BinaryPredicate1D):
+ def __init__(self, iType=IntegrationType.MEAN):
+ BinaryPredicate1D.__init__(self)
+ self.func = GetProjectedYF1D(iType)
+
+ def __call__(self, i1, i2):
+ return (self.func(i1) > self.func(i2))
+
+
class pyZDiscontinuityBP1D(BinaryPredicate1D):
def __init__(self, iType=IntegrationType.MEAN):
BinaryPredicate1D.__init__(self)
@@ -641,3 +671,10 @@ class pyShuffleBP1D(BinaryPredicate1D):
def __call__(self, inter1, inter2):
return (random.uniform(0, 1) < random.uniform(0, 1))
+
+class MaterialBP1D(BinaryPredicate1D):
+ """Checks whether the two supplied ViewEdges have the same material."""
+ def __call__(self, i1, i2):
+ fedges = (fe for ve in (i1, i2) for fe in (ve.first_fedge, ve.last_fedge))
+ materials = {material_from_fedge(fe) for fe in fedges}
+ return len(materials) < 2
diff --git a/release/scripts/freestyle/modules/freestyle/shaders.py b/release/scripts/freestyle/modules/freestyle/shaders.py
index 508df7feca0..633def38b5b 100644
--- a/release/scripts/freestyle/modules/freestyle/shaders.py
+++ b/release/scripts/freestyle/modules/freestyle/shaders.py
@@ -36,7 +36,6 @@ __all__ = (
"BlenderTextureShader",
"CalligraphicShader",
"ColorNoiseShader",
- "ColorVariationPatternShader",
"ConstantColorShader",
"ConstantThicknessShader",
"ConstrainedIncreasingThicknessShader",
@@ -49,13 +48,9 @@ __all__ = (
"SmoothingShader",
"SpatialNoiseShader",
"SquareCapShader",
- "StrokeTextureShader",
"StrokeTextureStepShader",
- "TextureAssignerShader",
"ThicknessNoiseShader",
- "ThicknessVariationPatternShader",
"TipRemoverShader",
- "fstreamShader",
"py2DCurvatureColorShader",
"pyBackboneStretcherNoCuspShader",
"pyBackboneStretcherShader",
@@ -92,7 +87,6 @@ __all__ = (
"pyTimeColorShader",
"pyTipRemoverShader",
"pyZDependingThicknessShader",
- "streamShader",
)
@@ -103,7 +97,6 @@ from _freestyle import (
BlenderTextureShader,
CalligraphicShader,
ColorNoiseShader,
- ColorVariationPatternShader,
ConstantColorShader,
ConstantThicknessShader,
ConstrainedIncreasingThicknessShader,
@@ -114,14 +107,9 @@ from _freestyle import (
SamplingShader,
SmoothingShader,
SpatialNoiseShader,
- StrokeTextureShader,
StrokeTextureStepShader,
- TextureAssignerShader,
ThicknessNoiseShader,
- ThicknessVariationPatternShader,
TipRemoverShader,
- fstreamShader,
- streamShader,
)
# constructs for shader definition in Python
@@ -150,7 +138,8 @@ from freestyle.predicates import (
from freestyle.utils import (
bound,
- bounding_box,
+ BoundingBox,
+ pairwise,
phase_to_direction,
)
@@ -201,7 +190,7 @@ class pyConstantThicknessShader(StrokeShader):
class pyFXSVaryingThicknessWithDensityShader(StrokeShader):
"""
- Assings thickness to a stroke based on the density of the diffuse map.
+ Assigns thickness to a stroke based on the density of the diffuse map.
"""
def __init__(self, wsize, threshold_min, threshold_max, thicknessMin, thicknessMax):
StrokeShader.__init__(self)
@@ -612,7 +601,7 @@ class pyTimeColorShader(StrokeShader):
class pySamplingShader(StrokeShader):
"""
- Resamples the stroke, which gives the stroke the ammount of
+ Resamples the stroke, which gives the stroke the amount of
vertices specified.
"""
def __init__(self, sampling):
@@ -788,7 +777,7 @@ class pyTVertexRemoverShader(StrokeShader):
class pyHLRShader(StrokeShader):
"""
- Controlls visibility based upon the quantative invisibility (QI)
+ Controls visibility based upon the quantitative invisibility (QI)
based on hidden line removal (HLR).
"""
def shade(self, stroke):
@@ -877,7 +866,7 @@ class pyBluePrintCirclesShader(StrokeShader):
def shade(self, stroke):
# get minimum and maximum coordinates
- p_min, p_max = bounding_box(stroke)
+ p_min, p_max = BoundingBox.from_sequence(svert.point for svert in stroke).corners
stroke.resample(32 * self.__turns)
sv_nb = len(stroke) // self.__turns
@@ -886,7 +875,7 @@ class pyBluePrintCirclesShader(StrokeShader):
R = self.__random_radius
C = self.__random_center
- # The directions (and phases) are calculated using a seperate
+ # The directions (and phases) are calculated using a separate
# function decorated with an lru-cache. This guarantees that
# the directions (involving sin and cos) are calculated as few
# times as possible.
@@ -929,7 +918,7 @@ class pyBluePrintEllipsesShader(StrokeShader):
self.__random_radius = random_radius
def shade(self, stroke):
- p_min, p_max = bounding_box(stroke)
+ p_min, p_max = BoundingBox.from_sequence(svert.point for svert in stroke).corners
stroke.resample(32 * self.__turns)
sv_nb = len(stroke) // self.__turns
@@ -954,7 +943,7 @@ class pyBluePrintEllipsesShader(StrokeShader):
c = prev_center + (center - prev_center) * phase
svert.point = (c.x + r.x * direction.x, c.y + r.y * direction.y)
- # remove exessive vertices
+ # remove excess vertices
if not it.is_end:
it.increment()
for sv in tuple(it):
@@ -976,7 +965,7 @@ class pyBluePrintSquaresShader(StrokeShader):
return
# get minimum and maximum coordinates
- p_min, p_max = bounding_box(stroke)
+ p_min, p_max = BoundingBox.from_sequence(svert.point for svert in stroke).corners
stroke.resample(32 * self.__turns)
num_segments = len(stroke) // self.__turns
@@ -1016,7 +1005,7 @@ class pyBluePrintSquaresShader(StrokeShader):
points = tuple(p + rand for (p, rand) in zip(points, randomization_mat))
- # substract even from uneven; result is length four tuple of vectors
+ # subtract even from uneven; result is length four tuple of vectors
it = iter(points)
old_vecs = tuple(next(it) - current for current in it)
@@ -1040,7 +1029,7 @@ class pyBluePrintSquaresShader(StrokeShader):
# special case; remove these vertices
verticesToRemove.append(svert)
- # remove exessive vertices (if any)
+ # remove excess vertices (if any)
if not it.is_end:
it.increment()
verticesToRemove += [svert for svert in it]
@@ -1078,7 +1067,7 @@ class pyBluePrintDirectedSquaresShader(StrokeShader):
sqrt_coeff = sqrt(trace * trace - 4 * det)
lambda1, lambda2 = (trace + sqrt_coeff) / 2, (trace - sqrt_coeff) / 2
- # make sure those numers aren't to small, if they are, rooting them will yield complex numbers
+ # make sure those numbers aren't to small, if they are, rooting them will yield complex numbers
lambda1, lambda2 = max(1e-12, lambda1), max(1e-12, lambda2)
theta = atan(2 * p_var_xy / (p_var.x - p_var.y)) / 2
@@ -1131,7 +1120,7 @@ class pyBluePrintDirectedSquaresShader(StrokeShader):
# special case; remove these vertices
verticesToRemove.append(svert)
- # remove exessive vertices
+ # remove excess vertices
if not it.is_end:
it.increment()
verticesToRemove += [svert for svert in it]
@@ -1143,6 +1132,13 @@ class pyBluePrintDirectedSquaresShader(StrokeShader):
# -- various (used in the parameter editor) -- #
+def iter_stroke_vertices(stroke, epsilon=1e-6):
+ yield stroke[0]
+ for prev, svert in pairwise(stroke):
+ if (prev.point - svert.point).length > epsilon:
+ yield svert
+
+
class RoundCapShader(StrokeShader):
def round_cap_thickness(self, x):
x = max(0.0, min(x, 1.0))
@@ -1150,7 +1146,8 @@ class RoundCapShader(StrokeShader):
def shade(self, stroke):
# save the location and attribute of stroke vertices
- buffer = tuple((Vector(sv.point), StrokeAttribute(sv.attribute)) for sv in stroke)
+ buffer = tuple((Vector(sv.point), StrokeAttribute(sv.attribute))
+ for sv in iter_stroke_vertices(stroke))
nverts = len(buffer)
if nverts < 2:
return
@@ -1198,7 +1195,8 @@ class RoundCapShader(StrokeShader):
class SquareCapShader(StrokeShader):
def shade(self, stroke):
# save the location and attribute of stroke vertices
- buffer = tuple((Vector(sv.point), StrokeAttribute(sv.attribute)) for sv in stroke)
+ buffer = tuple((Vector(sv.point), StrokeAttribute(sv.attribute))
+ for sv in iter_stroke_vertices(stroke))
nverts = len(buffer)
if nverts < 2:
return
diff --git a/release/scripts/freestyle/modules/freestyle/utils.py b/release/scripts/freestyle/modules/freestyle/utils.py
index e0679a53954..d3eba187f70 100644
--- a/release/scripts/freestyle/modules/freestyle/utils.py
+++ b/release/scripts/freestyle/modules/freestyle/utils.py
@@ -22,28 +22,37 @@ writing.
"""
__all__ = (
- "ContextFunctions",
+ "angle_x_normal",
"bound",
"bounding_box",
+ "BoundingBox",
+ "ContextFunctions",
+ "curvature_from_stroke_vertex",
"find_matching_vertex",
- "getCurrentScene",
"get_chain_length",
+ "get_object_name",
+ "get_strokes",
"get_test_stroke",
+ "getCurrentScene",
"integrate",
+ "is_poly_clockwise",
"iter_distance_along_stroke",
"iter_distance_from_camera",
"iter_distance_from_object",
"iter_material_value",
"iter_t2d_along_stroke",
+ "material_from_fedge",
+ "normal_at_I0D",
"pairwise",
"phase_to_direction",
"rgb_to_bw",
+ "simplify",
"stroke_curvature",
"stroke_normal",
+ "StrokeCollector",
"tripplewise",
)
-
# module members
from _freestyle import (
ContextFunctions,
@@ -55,13 +64,29 @@ from _freestyle import (
from freestyle.types import (
Interface0DIterator,
Stroke,
+ StrokeShader,
StrokeVertexIterator,
)
from mathutils import Vector
from functools import lru_cache, namedtuple
-from math import cos, sin, pi
-from itertools import tee
+from math import cos, sin, pi, atan2
+from itertools import tee, compress
+
+
+# -- types -- #
+
+# A named tuple primitive used for storing data that has an upper and
+# lower bound (e.g., thickness, range and certain other values)
+class BoundedProperty(namedtuple("BoundedProperty", ["min", "max", "delta"])):
+ def __new__(cls, minimum, maximum, delta=None):
+ if delta is None:
+ delta = abs(maximum - minimum)
+ return super().__new__(cls, minimum, maximum, delta)
+
+ def interpolate(self, val):
+ result = (self.max - val) / self.delta
+ return 1.0 - bound(0, result, 1)
# -- real utility functions -- #
@@ -79,6 +104,40 @@ def bound(lower, x, higher):
return (lower if x <= lower else higher if x >= higher else x)
+def get_strokes():
+ """Get all strokes that are currently available"""
+ return tuple(map(Operators().get_stroke_from_index, range(Operators().get_strokes_size())))
+
+
+def is_poly_clockwise(stroke):
+ """True if the stroke is orientated in a clockwise way, False otherwise"""
+ v = sum((v2.point.x - v1.point.x) * (v1.point.y + v2.point.y) for v1, v2 in pairwise(stroke))
+ v1, v2 = stroke[0], stroke[-1]
+ if (v1.point - v2.point).length > 1e-3:
+ v += (v2.point.x - v1.point.x) * (v1.point.y + v2.point.y)
+ return v > 0
+
+
+def get_object_name(stroke):
+ """Returns the name of the object that this stroke is drawn on."""
+ fedge = stroke[0].fedge
+ if fedge is None:
+ return None
+ return fedge.viewedge.viewshape.name
+
+
+def material_from_fedge(fe):
+ "get the diffuse rgba color from an FEdge"
+ if fe is None:
+ return None
+ if fe.is_smooth:
+ material = fe.material
+ else:
+ right, left = fe.material_right, fe.material_left
+ material = right if (right.priority > left.priority) else left
+ return material
+
+
def bounding_box(stroke):
"""
Returns the maximum and minimum coordinates (the bounding box) of the stroke's vertices
@@ -86,8 +145,57 @@ def bounding_box(stroke):
x, y = zip(*(svert.point for svert in stroke))
return (Vector((min(x), min(y))), Vector((max(x), max(y))))
-# -- General helper functions -- #
+def normal_at_I0D(it: Interface0DIterator) -> Vector:
+ """Normal at an Interface0D object. In contrast to Normal2DF0D this
+ function uses the actual data instead of underlying Fedge objects.
+ """
+ if it.at_last and it.is_begin:
+ # corner-case
+ return Vector((0, 0))
+ elif it.at_last:
+ it.decrement()
+ a, b = it.object, next(it)
+ elif it.is_begin:
+ a, b = it.object, next(it)
+ # give iterator back in original state
+ it.decrement()
+ elif it.is_end:
+ # just fail hard: this shouldn not happen
+ raise StopIteration()
+ else:
+ # this case sometimes has a small difference with Normal2DF0D (1e-3 -ish)
+ it.decrement()
+ a = it.object
+ curr, b = next(it), next(it)
+ # give iterator back in original state
+ it.decrement()
+ return (b.point - a.point).orthogonal().normalized()
+
+
+def angle_x_normal(it: Interface0DIterator):
+ """unsigned angle between a Point's normal and the X axis, in radians"""
+ normal = normal_at_I0D(it)
+ return abs(atan2(normal[1], normal[0]))
+
+
+def curvature_from_stroke_vertex(svert):
+ """The 3D curvature of an stroke vertex' underlying geometry
+ The result is None or in the range [-inf, inf]"""
+ c1 = svert.first_svertex.curvatures
+ c2 = svert.second_svertex.curvatures
+ if c1 is None and c2 is None:
+ Kr = None
+ elif c1 is None:
+ Kr = c2[4]
+ elif c2 is None:
+ Kr = c1[4]
+ else:
+ Kr = c1[4] + svert.t2d * (c2[4] - c1[4])
+ return Kr
+
+
+# -- General helper functions -- #
@lru_cache(maxsize=32)
def phase_to_direction(length):
@@ -102,9 +210,122 @@ def phase_to_direction(length):
results.append((phase, Vector((cos(2 * pi * phase), sin(2 * pi * phase)))))
return results
-# A named tuple primitive used for storing data that has an upper and
-# lower bound (e.g., thickness, range and certain values)
-BoundedProperty = namedtuple("BoundedProperty", ["min", "max", "delta"])
+
+# -- simplification of a set of points; based on simplify.js by Vladimir Agafonkin --
+# https://mourner.github.io/simplify-js/
+
+def getSquareSegmentDistance(p, p1, p2):
+ """
+ Square distance between point and a segment
+ """
+ x, y = p1
+
+ dx, dy = (p2 - p1)
+
+ if dx or dy:
+ t = ((p.x - x) * dx + (p.y - y) * dy) / (dx * dx + dy * dy)
+
+ if t > 1:
+ x, y = p2
+ elif t > 0:
+ x += dx * t
+ y += dy * t
+
+ dx, dy = p.x - x, p.y - y
+ return dx * dx + dy * dy
+
+
+def simplifyDouglasPeucker(points, tolerance):
+ length = len(points)
+ markers = [0] * length
+
+ first = 0
+ last = length - 1
+
+ first_stack = []
+ last_stack = []
+
+ new_points = []
+
+ markers[first] = 1
+ markers[last] = 1
+
+ while last:
+ max_sqdist = 0
+
+ for i in range(first, last):
+ sqdist = getSquareSegmentDistance(points[i], points[first], points[last])
+
+ if sqdist > max_sqdist:
+ index = i
+ max_sqdist = sqdist
+
+ if max_sqdist > tolerance:
+ markers[index] = 1
+
+ first_stack.append(first)
+ last_stack.append(index)
+
+ first_stack.append(index)
+ last_stack.append(last)
+
+ first = first_stack.pop() if first_stack else None
+ last = last_stack.pop() if last_stack else None
+
+ return tuple(compress(points, markers))
+
+
+def simplify(points, tolerance):
+ """Simplifies a set of points"""
+ return simplifyDouglasPeucker(points, tolerance * tolerance)
+
+
+class BoundingBox:
+ """Object representing a bounding box consisting out of 2 2D vectors"""
+
+ __slots__ = (
+ "minimum",
+ "maximum",
+ "size",
+ "corners",
+ )
+
+ def __init__(self, minimum: Vector, maximum: Vector):
+ self.minimum = minimum
+ self.maximum = maximum
+ if len(minimum) != len(maximum):
+ raise TypeError("Expected two vectors of size 2, got", minimum, maximum)
+ self.size = len(minimum)
+ self.corners = (minimum, maximum)
+
+ def __repr__(self):
+ return "BoundingBox(%r, %r)" % (self.minimum, self.maximum)
+
+ @classmethod
+ def from_sequence(cls, sequence):
+ """BoundingBox from sequence of 2D or 3D Vector objects"""
+ x, y = zip(*sequence)
+ mini = Vector((min(x), min(y)))
+ maxi = Vector((max(x), max(y)))
+ return cls(mini, maxi)
+
+ def inside(self, other):
+ """True if self inside other, False otherwise"""
+ if self.size != other.size:
+ raise TypeError("Expected two BoundingBox of the same size, got", self, other)
+ return (self.minimum.x >= other.minimum.x and self.minimum.y >= other.minimum.y and
+ self.maximum.x <= other.maximum.x and self.maximum.y <= other.maximum.y)
+
+
+class StrokeCollector(StrokeShader):
+ "Collects and Stores stroke objects"
+ def __init__(self):
+ StrokeShader.__init__(self)
+ self.strokes = []
+
+ def shade(self, stroke):
+ self.strokes.append(stroke)
+
# -- helper functions for chaining -- #
@@ -147,6 +368,7 @@ def find_matching_vertex(id, it):
"""Finds the matching vertex, or returns None."""
return next((ve for ve in it if ve.id == id), None)
+
# -- helper functions for iterating -- #
def pairwise(iterable, types={Stroke, StrokeVertexIterator}):
@@ -210,34 +432,36 @@ def iter_distance_from_object(stroke, location, range_min, range_max, normfac):
def iter_material_value(stroke, func, attribute):
- "Yields a specific material attribute from the vertex' underlying material."
+ """Yields a specific material attribute from the vertex' underlying material."""
it = Interface0DIterator(stroke)
for svert in it:
material = func(it)
# main
if attribute == 'LINE':
value = rgb_to_bw(*material.line[0:3])
- elif attribute == 'ALPHA':
- value = material.line[3]
elif attribute == 'DIFF':
value = rgb_to_bw(*material.diffuse[0:3])
elif attribute == 'SPEC':
value = rgb_to_bw(*material.specular[0:3])
- # line seperate
+ # line separate
elif attribute == 'LINE_R':
value = material.line[0]
elif attribute == 'LINE_G':
value = material.line[1]
elif attribute == 'LINE_B':
value = material.line[2]
- # diffuse seperate
+ elif attribute == 'LINE_A':
+ value = material.line[3]
+ # diffuse separate
elif attribute == 'DIFF_R':
value = material.diffuse[0]
elif attribute == 'DIFF_G':
value = material.diffuse[1]
elif attribute == 'DIFF_B':
value = material.diffuse[2]
- # specular seperate
+ elif attribute == 'ALPHA':
+ value = material.diffuse[3]
+ # specular separate
elif attribute == 'SPEC_R':
value = material.specular[0]
elif attribute == 'SPEC_G':
@@ -250,8 +474,9 @@ def iter_material_value(stroke, func, attribute):
raise ValueError("unexpected material attribute: " + attribute)
yield (svert, value)
+
def iter_distance_along_stroke(stroke):
- "Yields the absolute distance along the stroke up to the current vertex."
+ """Yields the absolute distance along the stroke up to the current vertex."""
distance = 0.0
# the positions need to be copied, because they are changed in the calling function
points = tuple(svert.point.copy() for svert in stroke)
@@ -260,8 +485,8 @@ def iter_distance_along_stroke(stroke):
distance += (prev - curr).length
yield distance
-# -- mathmatical operations -- #
+# -- mathematical operations -- #
def stroke_curvature(it):
"""
@@ -293,6 +518,7 @@ def stroke_curvature(it):
yield abs(K)
+
def stroke_normal(stroke):
"""
Compute the 2D normal at the stroke vertex pointed by the iterator
@@ -302,31 +528,19 @@ def stroke_normal(stroke):
The returned normals are dynamic: they update when the
vertex position (and therefore the vertex normal) changes.
- for use in geometry modifiers it is advised to
+ for use in geometry modifiers it is advised to
cast this generator function to a tuple or list
"""
- n = len(stroke) - 1
-
- for i, svert in enumerate(stroke):
- if i == 0:
- e = stroke[i + 1].point - svert.point
- yield Vector((e[1], -e[0])).normalized()
- elif i == n:
- e = svert.point - stroke[i - 1].point
- yield Vector((e[1], -e[0])).normalized()
- else:
- e1 = stroke[i + 1].point - svert.point
- e2 = svert.point - stroke[i - 1].point
- n1 = Vector((e1[1], -e1[0])).normalized()
- n2 = Vector((e2[1], -e2[0])).normalized()
- yield (n1 + n2).normalized()
+ it = iter(stroke)
+ yield from (normal_at_I0D(it) for _ in it)
+
def get_test_stroke():
"""Returns a static stroke object for testing """
from freestyle.types import Stroke, Interface0DIterator, StrokeVertexIterator, SVertex, Id, StrokeVertex
# points for our fake stroke
points = (Vector((1.0, 5.0, 3.0)), Vector((1.0, 2.0, 9.0)),
- Vector((6.0, 2.0, 3.0)), Vector((7.0, 2.0, 3.0)),
+ Vector((6.0, 2.0, 3.0)), Vector((7.0, 2.0, 3.0)),
Vector((2.0, 6.0, 3.0)), Vector((2.0, 8.0, 3.0)))
ids = (Id(0, 0), Id(1, 1), Id(2, 2), Id(3, 3), Id(4, 4), Id(5, 5))
diff --git a/release/scripts/freestyle/modules/parameter_editor.py b/release/scripts/freestyle/modules/parameter_editor.py
index ebd09bd0181..fe6c6f641ac 100644
--- a/release/scripts/freestyle/modules/parameter_editor.py
+++ b/release/scripts/freestyle/modules/parameter_editor.py
@@ -62,7 +62,10 @@ from freestyle.predicates import (
TrueBP1D,
TrueUP1D,
WithinImageBoundaryUP1D,
+ pyNFirstUP1D,
pyNatureUP1D,
+ pyProjectedXBP1D,
+ pyProjectedYBP1D,
pyZBP1D,
)
from freestyle.shaders import (
@@ -72,29 +75,34 @@ from freestyle.shaders import (
ConstantColorShader,
GuidingLinesShader,
PolygonalizationShader,
- SamplingShader,
- SpatialNoiseShader,
- StrokeShader,
- StrokeTextureStepShader,
- TipRemoverShader,
pyBluePrintCirclesShader,
pyBluePrintEllipsesShader,
pyBluePrintSquaresShader,
RoundCapShader,
+ SamplingShader,
+ SpatialNoiseShader,
SquareCapShader,
+ StrokeShader,
+ StrokeTextureStepShader,
+ ThicknessNoiseShader as thickness_noise,
+ TipRemoverShader,
)
from freestyle.utils import (
+ angle_x_normal,
+ bound,
+ BoundedProperty,
ContextFunctions,
+ curvature_from_stroke_vertex,
getCurrentScene,
iter_distance_along_stroke,
- iter_t2d_along_stroke,
iter_distance_from_camera,
iter_distance_from_object,
iter_material_value,
- stroke_normal,
- bound,
+ iter_t2d_along_stroke,
+ normal_at_I0D,
pairwise,
- BoundedProperty
+ simplify,
+ stroke_normal,
)
from _freestyle import (
blendRamp,
@@ -103,10 +111,20 @@ from _freestyle import (
)
import time
+import bpy
+import random
+
from mathutils import Vector
-from math import pi, sin, cos, acos, radians
+from math import pi, sin, cos, acos, radians, atan2
from itertools import cycle, tee
+# WARNING: highly experimental, not a stable API
+# lists of callback functions
+# used by the render_freestyle_svg addon
+callbacks_lineset_pre = []
+callbacks_modifiers_post = []
+callbacks_lineset_post = []
+
class ColorRampModifier(StrokeShader):
"""Primitive for the color modifiers."""
@@ -167,7 +185,13 @@ class CurveMappingModifier(ScalarBlendModifier):
return (1.0 - t) if self.invert else t
def CURVE(self, t):
- return evaluateCurveMappingF(self.curve, 0, t)
+ # deprecated: return evaluateCurveMappingF(self.curve, 0, t)
+ curve = self.curve
+ curve.initialize()
+ result = curve.curves[0].evaluate(t)
+ # float precision errors in t can give a very weird result for evaluate.
+ # therefore, bound the result by the curve's min and max values
+ return bound(curve.clip_min_y, result, curve.clip_max_y)
class ThicknessModifierMixIn:
@@ -200,10 +224,19 @@ class ThicknessBlenderMixIn(ThicknessModifierMixIn):
self.position = position
self.ratio = ratio
- def blend_thickness(self, svert, v):
- """Blends and sets the thickness."""
+ def blend_thickness(self, svert, thickness, asymmetric=False):
+ """Blends and sets the thickness with respect to the position, blend mode and symmetry."""
+ if asymmetric:
+ right, left = thickness
+ self.blend_thickness_asymmetric(svert, right, left)
+ else:
+ if type(thickness) not in {int, float}:
+ thickness = sum(thickness)
+ self.blend_thickness_symmetric(svert, thickness)
+
+ def blend_thickness_symmetric(self, svert, v):
+ """Blends and sets the thickness. Thickness is equal on each side of the backbone"""
outer, inner = svert.attribute.thickness
- fe = svert.fedge
v = self.blend(outer + inner, v)
# Part 1: blend
@@ -218,21 +251,29 @@ class ThicknessBlenderMixIn(ThicknessModifierMixIn):
else:
raise ValueError("unknown thickness position: " + position)
- # Part 2: set
- if (fe.nature & Nature.BORDER):
+ self.set_thickness(svert, outer, inner)
+
+ def blend_thickness_asymmetric(self, svert, right, left):
+ """Blends and sets the thickness. Thickness may be unequal on each side of the backbone"""
+ # blend the thickness values for both sides. This way, the blend mode is supported.
+ old = svert.attribute.thickness
+ new = (right, left)
+ right, left = (self.blend(*val) for val in zip(old, new))
+
+ fe = svert.fedge
+ nature = fe.nature
+ if (nature & Nature.BORDER):
if self.persp_camera:
point = -svert.point_3d.normalized()
dir = point.dot(fe.normal_left)
else:
dir = fe.normal_left.z
if dir < 0.0: # the back side is visible
- outer, inner = inner, outer
- elif (fe.nature & Nature.SILHOUETTE):
+ right, left = left, right
+ elif (nature & Nature.SILHOUETTE):
if fe.is_smooth: # TODO more tests needed
- outer, inner = inner, outer
- else:
- outer = inner = (outer + inner) / 2
- svert.attribute.thickness = (outer, inner)
+ right, left = left, right
+ svert.attribute.thickness = (right, left)
class BaseThicknessShader(StrokeShader, ThicknessModifierMixIn):
@@ -271,7 +312,7 @@ class ColorAlongStrokeShader(ColorRampModifier):
class AlphaAlongStrokeShader(CurveMappingModifier):
- """Maps a curve to the alpha/transparancy of the stroke, using the curvilinear abscissa (t)."""
+ """Maps a curve to the alpha/transparency of the stroke, using the curvilinear abscissa (t)."""
def shade(self, stroke):
for svert, t in zip(stroke, iter_t2d_along_stroke(stroke)):
a = svert.attribute.alpha
@@ -285,7 +326,7 @@ class ThicknessAlongStrokeShader(ThicknessBlenderMixIn, CurveMappingModifier):
blend, influence, mapping, invert, curve, value_min, value_max):
ThicknessBlenderMixIn.__init__(self, thickness_position, thickness_ratio)
CurveMappingModifier.__init__(self, blend, influence, mapping, invert, curve)
- self.value = BoundedProperty(value_min, value_max, value_max - value_min)
+ self.value = BoundedProperty(value_min, value_max)
def shade(self, stroke):
for svert, t in zip(stroke, iter_t2d_along_stroke(stroke)):
@@ -299,7 +340,7 @@ class ColorDistanceFromCameraShader(ColorRampModifier):
"""Picks a color value from a ramp based on the vertex' distance from the camera."""
def __init__(self, blend, influence, ramp, range_min, range_max):
ColorRampModifier.__init__(self, blend, influence, ramp)
- self.range = BoundedProperty(range_min, range_max, range_max - range_min)
+ self.range = BoundedProperty(range_min, range_max)
def shade(self, stroke):
it = iter_distance_from_camera(stroke, *self.range)
@@ -313,7 +354,7 @@ class AlphaDistanceFromCameraShader(CurveMappingModifier):
"""Picks an alpha value from a curve based on the vertex' distance from the camera"""
def __init__(self, blend, influence, mapping, invert, curve, range_min, range_max):
CurveMappingModifier.__init__(self, blend, influence, mapping, invert, curve)
- self.range = BoundedProperty(range_min, range_max, range_max - range_min)
+ self.range = BoundedProperty(range_min, range_max)
def shade(self, stroke):
it = iter_distance_from_camera(stroke, *self.range)
@@ -329,8 +370,8 @@ class ThicknessDistanceFromCameraShader(ThicknessBlenderMixIn, CurveMappingModif
blend, influence, mapping, invert, curve, range_min, range_max, value_min, value_max):
ThicknessBlenderMixIn.__init__(self, thickness_position, thickness_ratio)
CurveMappingModifier.__init__(self, blend, influence, mapping, invert, curve)
- self.range = BoundedProperty(range_min, range_max, range_max - range_min)
- self.value = BoundedProperty(value_min, value_max, value_max - value_min)
+ self.range = BoundedProperty(range_min, range_max)
+ self.value = BoundedProperty(value_min, value_max)
def shade(self, stroke):
for (svert, t) in iter_distance_from_camera(stroke, *self.range):
@@ -346,7 +387,7 @@ class ColorDistanceFromObjectShader(ColorRampModifier):
ColorRampModifier.__init__(self, blend, influence, ramp)
if target is None:
raise ValueError("ColorDistanceFromObjectShader: target can't be None ")
- self.range = BoundedProperty(range_min, range_max, range_max - range_min)
+ self.range = BoundedProperty(range_min, range_max)
# construct a model-view matrix
matrix = getCurrentScene().camera.matrix_world.inverted()
# get the object location in the camera coordinate
@@ -366,7 +407,7 @@ class AlphaDistanceFromObjectShader(CurveMappingModifier):
CurveMappingModifier.__init__(self, blend, influence, mapping, invert, curve)
if target is None:
raise ValueError("AlphaDistanceFromObjectShader: target can't be None ")
- self.range = BoundedProperty(range_min, range_max, range_max - range_min)
+ self.range = BoundedProperty(range_min, range_max)
# construct a model-view matrix
matrix = getCurrentScene().camera.matrix_world.inverted()
# get the object location in the camera coordinate
@@ -388,8 +429,8 @@ class ThicknessDistanceFromObjectShader(ThicknessBlenderMixIn, CurveMappingModif
CurveMappingModifier.__init__(self, blend, influence, mapping, invert, curve)
if target is None:
raise ValueError("ThicknessDistanceFromObjectShader: target can't be None ")
- self.range = BoundedProperty(range_min, range_max, range_max - range_min)
- self.value = BoundedProperty(value_min, value_max, value_max - value_min)
+ self.range = BoundedProperty(range_min, range_max)
+ self.value = BoundedProperty(value_min, value_max)
# construct a model-view matrix
matrix = getCurrentScene().camera.matrix_world.inverted()
# get the object location in the camera coordinate
@@ -401,6 +442,7 @@ class ThicknessDistanceFromObjectShader(ThicknessBlenderMixIn, CurveMappingModif
b = self.value.min + self.evaluate(t) * self.value.delta
self.blend_thickness(svert, b)
+
# Material modifiers
class ColorMaterialShader(ColorRampModifier):
"""Assigns a color to the vertices based on their underlying material."""
@@ -416,7 +458,7 @@ class ColorMaterialShader(ColorRampModifier):
for svert in it:
material = self.func(it)
if self.attribute == 'LINE':
- b = material.line[0:3]
+ b = material.line[0:3]
elif self.attribute == 'DIFF':
b = material.diffuse[0:3]
else:
@@ -429,6 +471,7 @@ class ColorMaterialShader(ColorRampModifier):
b = self.evaluate(value)
svert.attribute.color = self.blend_ramp(a, b)
+
class AlphaMaterialShader(CurveMappingModifier):
"""Assigns an alpha value to the vertices based on their underlying material."""
def __init__(self, blend, influence, mapping, invert, curve, material_attribute):
@@ -450,7 +493,7 @@ class ThicknessMaterialShader(ThicknessBlenderMixIn, CurveMappingModifier):
ThicknessBlenderMixIn.__init__(self, thickness_position, thickness_ratio)
CurveMappingModifier.__init__(self, blend, influence, mapping, invert, curve)
self.attribute = material_attribute
- self.value = BoundedProperty(value_min, value_max, value_max - value_min)
+ self.value = BoundedProperty(value_min, value_max)
self.func = CurveMaterialF0D()
def shade(self, stroke):
@@ -461,7 +504,6 @@ class ThicknessMaterialShader(ThicknessBlenderMixIn, CurveMappingModifier):
# Calligraphic thickness modifier
-
class CalligraphicThicknessShader(ThicknessBlenderMixIn, ScalarBlendModifier):
"""Thickness modifier for achieving a calligraphy-like effect."""
def __init__(self, thickness_position, thickness_ratio,
@@ -469,7 +511,7 @@ class CalligraphicThicknessShader(ThicknessBlenderMixIn, ScalarBlendModifier):
ThicknessBlenderMixIn.__init__(self, thickness_position, thickness_ratio)
ScalarBlendModifier.__init__(self, blend_type, influence)
self.orientation = Vector((cos(orientation), sin(orientation)))
- self.thickness = BoundedProperty(thickness_min, thickness_max, thickness_max - thickness_min)
+ self.thickness = BoundedProperty(thickness_min, thickness_max)
self.func = VertexOrientation2DF0D()
def shade(self, stroke):
@@ -485,10 +527,253 @@ class CalligraphicThicknessShader(ThicknessBlenderMixIn, ScalarBlendModifier):
self.blend_thickness(svert, b)
+# - Tangent Modifiers - #
+
+class TangentColorShader(ColorRampModifier):
+ """Color based on the direction of the stroke"""
+ def shade(self, stroke):
+ it = Interface0DIterator(stroke)
+ for svert in it:
+ angle = angle_x_normal(it)
+ fac = self.evaluate(angle / pi)
+ a = svert.attribute.color
+ svert.attribute.color = self.blend_ramp(a, fac)
+
+
+class TangentAlphaShader(CurveMappingModifier):
+ """Alpha transparency based on the direction of the stroke"""
+ def shade(self, stroke):
+ it = Interface0DIterator(stroke)
+ for svert in it:
+ angle = angle_x_normal(it)
+ fac = self.evaluate(angle / pi)
+ a = svert.attribute.alpha
+ svert.attribute.alpha = self.blend(a, fac)
+
+
+class TangentThicknessShader(ThicknessBlenderMixIn, CurveMappingModifier):
+ """Thickness based on the direction of the stroke"""
+ def __init__(self, thickness_position, thickness_ratio, blend, influence, mapping, invert, curve,
+ thickness_min, thickness_max):
+ ThicknessBlenderMixIn.__init__(self, thickness_position, thickness_ratio)
+ CurveMappingModifier.__init__(self, blend, influence, mapping, invert, curve)
+ self.thickness = BoundedProperty(thickness_min, thickness_max)
+
+ def shade(self, stroke):
+ it = Interface0DIterator(stroke)
+ for svert in it:
+ angle = angle_x_normal(it)
+ thickness = self.thickness.min + self.evaluate(angle / pi) * self.thickness.delta
+ self.blend_thickness(svert, thickness)
+
+
+# - Noise Modifiers - #
+
+class NoiseShader:
+ """Base class for noise shaders"""
+ def __init__(self, amplitude, period, seed=512):
+ self.amplitude = amplitude
+ self.scale = 1 / period / seed
+ self.seed = seed
+
+ def noisegen(self, stroke, n1=Noise(), n2=Noise()):
+ """Produces two noise values per StrokeVertex for every vertex in the stroke"""
+ initU1 = stroke.length_2d * self.seed + n1.rand(512) * self.seed
+ initU2 = stroke.length_2d * self.seed + n2.rand() * self.seed
+
+ for svert in stroke:
+ a = n1.turbulence_smooth(self.scale * svert.curvilinear_abscissa + initU1, 2)
+ b = n2.turbulence_smooth(self.scale * svert.curvilinear_abscissa + initU2, 2)
+ yield (svert, a, b)
+
+
+class ThicknessNoiseShader(ThicknessBlenderMixIn, ScalarBlendModifier, NoiseShader):
+ """Thickness based on pseudo-noise"""
+ def __init__(self, thickness_position, thickness_ratio, blend_type, influence, amplitude, period, seed=512, asymmetric=True):
+ ScalarBlendModifier.__init__(self, blend_type, influence)
+ ThicknessBlenderMixIn.__init__(self, thickness_position, thickness_ratio)
+ NoiseShader.__init__(self, amplitude, period, seed)
+ self.asymmetric = asymmetric
+
+ def shade(self, stroke):
+ for svert, noiseval1, noiseval2 in self.noisegen(stroke):
+ (r, l) = svert.attribute.thickness
+ l += noiseval1 * self.amplitude
+ r += noiseval2 * self.amplitude
+ self.blend_thickness(svert, (r, l), self.asymmetric)
+
+
+class ColorNoiseShader(ColorRampModifier, NoiseShader):
+ """Color based on pseudo-noise"""
+ def __init__(self, blend, influence, ramp, amplitude, period, seed=512):
+ ColorRampModifier.__init__(self, blend, influence, ramp)
+ NoiseShader.__init__(self, amplitude, period, seed)
+
+ def shade(self, stroke):
+ for svert, noiseval1, noiseval2 in self.noisegen(stroke):
+ position = abs(noiseval1 + noiseval2)
+ svert.attribute.color = self.blend_ramp(svert.attribute.color, self.evaluate(position))
+
+
+class AlphaNoiseShader(CurveMappingModifier, NoiseShader):
+ """Alpha transparency on based pseudo-noise"""
+ def __init__(self, blend, influence, mapping, invert, curve, amplitude, period, seed=512):
+ CurveMappingModifier.__init__(self, blend, influence, mapping, invert, curve)
+ NoiseShader.__init__(self, amplitude, period, seed)
+
+ def shade(self, stroke, n1=Noise(), n2=Noise()):
+ for svert, noiseval1, noiseval2 in self.noisegen(stroke):
+ position = abs(noiseval1 + noiseval2)
+ svert.attribute.alpha = self.blend(svert.attribute.alpha, self.evaluate(position))
+
+
+# - Crease Angle Modifiers - #
+
+def crease_angle(svert):
+ """Returns the crease angle between the StrokeVertex' two adjacent faces (in radians)"""
+ fe = svert.fedge
+ if not fe or fe.is_smooth or not (fe.nature & Nature.CREASE):
+ return None
+ # make sure that the input is within the domain of the acos function
+ product = bound(-1.0, -fe.normal_left.dot(fe.normal_right), 1.0)
+ return acos(product)
+
+
+class CreaseAngleColorShader(ColorRampModifier):
+ """Color based on the crease angle between two adjacent faces on the underlying geometry"""
+ def __init__(self, blend, influence, ramp, angle_min, angle_max):
+ ColorRampModifier.__init__(self, blend, influence, ramp)
+ # angles are (already) in radians
+ self.angle = BoundedProperty(angle_min, angle_max)
+
+ def shade(self, stroke):
+ for svert in stroke:
+ angle = crease_angle(svert)
+ if angle is None:
+ continue
+ t = self.angle.interpolate(angle)
+ svert.attribute.color = self.blend_ramp(svert.attribute.color, self.evaluate(t))
+
+
+class CreaseAngleAlphaShader(CurveMappingModifier):
+ """Alpha transparency based on the crease angle between two adjacent faces on the underlying geometry"""
+ def __init__(self, blend, influence, mapping, invert, curve, angle_min, angle_max):
+ CurveMappingModifier.__init__(self, blend, influence, mapping, invert, curve)
+ # angles are (already) in radians
+ self.angle = BoundedProperty(angle_min, angle_max)
+
+ def shade(self, stroke):
+ for svert in stroke:
+ angle = crease_angle(svert)
+ if angle is None:
+ continue
+ t = self.angle.interpolate(angle)
+ svert.attribute.alpha = self.blend(svert.attribute.alpha, self.evaluate(t))
+
+
+class CreaseAngleThicknessShader(ThicknessBlenderMixIn, CurveMappingModifier):
+ """Thickness based on the crease angle between two adjacent faces on the underlying geometry"""
+ def __init__(self, thickness_position, thickness_ratio, blend, influence, mapping, invert, curve,
+ angle_min, angle_max, thickness_min, thickness_max):
+ ThicknessBlenderMixIn.__init__(self, thickness_position, thickness_ratio)
+ CurveMappingModifier.__init__(self, blend, influence, mapping, invert, curve)
+ # angles are (already) in radians
+ self.angle = BoundedProperty(angle_min, angle_max)
+ self.thickness = BoundedProperty(thickness_min, thickness_max)
+
+ def shade(self, stroke):
+ for svert in stroke:
+ angle = crease_angle(svert)
+ if angle is None:
+ continue
+ t = self.angle.interpolate(angle)
+ thickness = self.thickness.min + self.evaluate(t) * self.thickness.delta
+ self.blend_thickness(svert, thickness)
+
+
+# - Curvature3D Modifiers - #
+
+def normalized_absolute_curvature(svert, bounded_curvature):
+ """
+ Gives the absolute curvature in range [0, 1].
+
+ The actual curvature (Kr) value can be anywhere in the range [-inf, inf], where convex curvature
+ yields a positive value, and concave a negative one. These shaders only look for the magnitude
+ of the 3D curvature, hence the abs()
+ """
+ curvature = curvature_from_stroke_vertex(svert)
+ if curvature is None:
+ return 0.0
+ return bounded_curvature.interpolate(abs(curvature))
+
+
+class Curvature3DColorShader(ColorRampModifier):
+ """Color based on the 3D curvature of the underlying geometry"""
+ def __init__(self, blend, influence, ramp, curvature_min, curvature_max):
+ ColorRampModifier.__init__(self, blend, influence, ramp)
+ self.curvature = BoundedProperty(curvature_min, curvature_max)
+
+ def shade(self, stroke):
+ for svert in stroke:
+ t = normalized_absolute_curvature(svert, self.curvature)
+ a = svert.attribute.color
+ b = self.evaluate(t)
+ svert.attribute.color = self.blend_ramp(a, b)
+
+
+class Curvature3DAlphaShader(CurveMappingModifier):
+ """Alpha based on the 3D curvature of the underlying geometry"""
+ def __init__(self, blend, influence, mapping, invert, curve, curvature_min, curvature_max):
+ CurveMappingModifier.__init__(self, blend, influence, mapping, invert, curve)
+ self.curvature = BoundedProperty(curvature_min, curvature_max)
+
+ def shade(self, stroke):
+ for svert in stroke:
+ t = normalized_absolute_curvature(svert, self.curvature)
+ a = svert.attribute.alpha
+ b = self.evaluate(t)
+ svert.attribute.alpha = self.blend(a, b)
+
+
+class Curvature3DThicknessShader(ThicknessBlenderMixIn, CurveMappingModifier):
+ """Alpha based on the 3D curvature of the underlying geometry"""
+ def __init__(self, thickness_position, thickness_ratio, blend, influence, mapping, invert, curve,
+ curvature_min, curvature_max, thickness_min, thickness_max):
+ ThicknessBlenderMixIn.__init__(self, thickness_position, thickness_ratio)
+ CurveMappingModifier.__init__(self, blend, influence, mapping, invert, curve)
+ self.curvature = BoundedProperty(curvature_min, curvature_max)
+ self.thickness = BoundedProperty(thickness_min, thickness_max)
+
+
+ def shade(self, stroke):
+ for svert in stroke:
+ t = normalized_absolute_curvature(svert, self.curvature)
+ thickness = self.thickness.min + self.evaluate(t) * self.thickness.delta
+ self.blend_thickness(svert, thickness)
+
+
# Geometry modifiers
+class SimplificationShader(StrokeShader):
+ """Simplifies a stroke by merging points together"""
+ def __init__(self, tolerance):
+ StrokeShader.__init__(self)
+ self.tolerance = tolerance
+
+ def shade(self, stroke):
+ points = tuple(svert.point for svert in stroke)
+ points_simplified = simplify(points, tolerance=self.tolerance)
+
+ it = iter(stroke)
+ for svert, point in zip(it, points_simplified):
+ svert.point = point
+
+ for svert in tuple(it):
+ stroke.remove_vertex(svert)
+
+
class SinusDisplacementShader(StrokeShader):
- """Displaces the stroke in a sinewave-like shape."""
+ """Displaces the stroke in a sine wave-like shape."""
def __init__(self, wavelength, amplitude, phase):
StrokeShader.__init__(self)
self.wavelength = wavelength
@@ -531,7 +816,7 @@ class PerlinNoise1DShader(StrokeShader):
class PerlinNoise2DShader(StrokeShader):
"""
Displaces the stroke using the strokes coordinates. This means
- that in a scene no strokes will be distorded identically.
+ that in a scene no strokes will be distorted identically.
More information on the noise shaders can be found at:
freestyleintegration.wordpress.com/2011/09/25/development-updates-on-september-25/
@@ -758,8 +1043,8 @@ class AngleLargerThanBP1D(BinaryPredicate1D):
x = (dir1 * dir2) / denom
return acos(bound(-1.0, x, 1.0)) > self.angle
-# predicates for selection
+# predicates for selection
class LengthThresholdUP1D(UnaryPredicate1D):
def __init__(self, length_min=None, length_max=None):
@@ -874,6 +1159,20 @@ class Seed:
_seed = Seed()
+def get_dashed_pattern(linestyle):
+ """Extracts the dashed pattern from the various UI options """
+ pattern = []
+ if linestyle.dash1 > 0 and linestyle.gap1 > 0:
+ pattern.append(linestyle.dash1)
+ pattern.append(linestyle.gap1)
+ if linestyle.dash2 > 0 and linestyle.gap2 > 0:
+ pattern.append(linestyle.dash2)
+ pattern.append(linestyle.gap2)
+ if linestyle.dash3 > 0 and linestyle.gap3 > 0:
+ pattern.append(linestyle.dash3)
+ pattern.append(linestyle.gap3)
+ return pattern
+
integration_types = {
'MEAN': IntegrationType.MEAN,
@@ -884,13 +1183,16 @@ integration_types = {
# main function for parameter processing
-
def process(layer_name, lineset_name):
scene = getCurrentScene()
layer = scene.render.layers[layer_name]
lineset = layer.freestyle_settings.linesets[lineset_name]
linestyle = lineset.linestyle
+ # execute line set pre-processing callback functions
+ for fn in callbacks_lineset_pre:
+ fn(scene, layer, lineset)
+
selection_criteria = []
# prepare selection criteria by visibility
if lineset.select_by_visibility:
@@ -933,11 +1235,11 @@ def process(layer_name, lineset_name):
if lineset.select_external_contour:
upred = ExternalContourUP1D()
edge_type_criteria.append(NotUP1D(upred) if lineset.exclude_external_contour else upred)
- if lineset.edge_type_combination == 'OR':
- upred = OrUP1D(*edge_type_criteria)
- else:
- upred = AndUP1D(*edge_type_criteria)
- if upred is not None:
+ if edge_type_criteria:
+ if lineset.edge_type_combination == 'OR':
+ upred = OrUP1D(*edge_type_criteria)
+ else:
+ upred = AndUP1D(*edge_type_criteria)
if lineset.edge_type_negation == 'EXCLUSIVE':
upred = NotUP1D(upred)
selection_criteria.append(upred)
@@ -962,8 +1264,9 @@ def process(layer_name, lineset_name):
upred = WithinImageBoundaryUP1D(*ContextFunctions.get_border())
selection_criteria.append(upred)
# select feature edges
- upred = AndUP1D(*selection_criteria)
- if upred is None:
+ if selection_criteria:
+ upred = AndUP1D(*selection_criteria)
+ else:
upred = TrueUP1D()
Operators.select(upred)
# join feature edges to form chains
@@ -1006,11 +1309,6 @@ def process(layer_name, lineset_name):
Operators.sequential_split(SplitPatternStartingUP0D(controller),
SplitPatternStoppingUP0D(controller),
sampling)
- # select chains
- if linestyle.use_length_min or linestyle.use_length_max:
- length_min = linestyle.length_min if linestyle.use_length_min else None
- length_max = linestyle.length_max if linestyle.use_length_max else None
- Operators.select(LengthThresholdUP1D(length_min, length_max))
# sort selected chains
if linestyle.use_sorting:
integration = integration_types.get(linestyle.integration_type, IntegrationType.MEAN)
@@ -1018,9 +1316,20 @@ def process(layer_name, lineset_name):
bpred = pyZBP1D(integration)
elif linestyle.sort_key == '2D_LENGTH':
bpred = Length2DBP1D()
+ elif linestyle.sort_key == 'PROJECTED_X':
+ bpred = pyProjectedXBP1D(integration)
+ elif linestyle.sort_key == 'PROJECTED_Y':
+ bpred = pyProjectedYBP1D(integration)
if linestyle.sort_order == 'REVERSE':
bpred = NotBP1D(bpred)
Operators.sort(bpred)
+ # select chains
+ if linestyle.use_length_min or linestyle.use_length_max:
+ length_min = linestyle.length_min if linestyle.use_length_min else None
+ length_max = linestyle.length_max if linestyle.use_length_max else None
+ Operators.select(LengthThresholdUP1D(length_min, length_max))
+ if linestyle.use_chain_count:
+ Operators.select(pyNFirstUP1D(linestyle.chain_count))
# prepare a list of stroke shaders
shaders_list = []
for m in linestyle.geometry_modifiers:
@@ -1032,6 +1341,8 @@ def process(layer_name, lineset_name):
elif m.type == 'BEZIER_CURVE':
shaders_list.append(BezierCurveShader(
m.error))
+ elif m.type == 'SIMPLIFICATION':
+ shaders_list.append(SimplificationShader(m.tolerance))
elif m.type == 'SINUS_DISPLACEMENT':
shaders_list.append(SinusDisplacementShader(
m.wavelength, m.amplitude, m.phase))
@@ -1103,6 +1414,21 @@ def process(layer_name, lineset_name):
shaders_list.append(ColorMaterialShader(
m.blend, m.influence, m.color_ramp, m.material_attribute,
m.use_ramp))
+ elif m.type == 'TANGENT':
+ shaders_list.append(TangentColorShader(
+ m.blend, m.influence, m.color_ramp))
+ elif m.type == 'CREASE_ANGLE':
+ shaders_list.append(CreaseAngleColorShader(
+ m.blend, m.influence, m.color_ramp,
+ m.angle_min, m.angle_max))
+ elif m.type == 'CURVATURE_3D':
+ shaders_list.append(Curvature3DColorShader(
+ m.blend, m.influence, m.color_ramp,
+ m.curvature_min, m.curvature_max))
+ elif m.type == 'NOISE':
+ shaders_list.append(ColorNoiseShader(
+ m.blend, m.influence, m.color_ramp,
+ m.amplitude, m.period, m.seed))
for m in linestyle.alpha_modifiers:
if not m.use:
continue
@@ -1121,6 +1447,21 @@ def process(layer_name, lineset_name):
shaders_list.append(AlphaMaterialShader(
m.blend, m.influence, m.mapping, m.invert, m.curve,
m.material_attribute))
+ elif m.type == 'TANGENT':
+ shaders_list.append(TangentAlphaShader(
+ m.blend, m.influence, m.mapping, m.invert, m.curve,))
+ elif m.type == 'CREASE_ANGLE':
+ shaders_list.append(CreaseAngleAlphaShader(
+ m.blend, m.influence, m.mapping, m.invert, m.curve,
+ m.angle_min, m.angle_max))
+ elif m.type == 'CURVATURE_3D':
+ shaders_list.append(Curvature3DAlphaShader(
+ m.blend, m.influence, m.mapping, m.invert, m.curve,
+ m.curvature_min, m.curvature_max))
+ elif m.type == 'NOISE':
+ shaders_list.append(AlphaNoiseShader(
+ m.blend, m.influence, m.mapping, m.invert, m.curve,
+ m.amplitude, m.period, m.seed))
for m in linestyle.thickness_modifiers:
if not m.use:
continue
@@ -1149,6 +1490,28 @@ def process(layer_name, lineset_name):
thickness_position, linestyle.thickness_ratio,
m.blend, m.influence,
m.orientation, m.thickness_min, m.thickness_max))
+ elif m.type == 'TANGENT':
+ shaders_list.append(TangentThicknessShader(
+ thickness_position, linestyle.thickness_ratio,
+ m.blend, m.influence, m.mapping, m.invert, m.curve,
+ m.thickness_min, m.thickness_max))
+ elif m.type == 'NOISE':
+ shaders_list.append(ThicknessNoiseShader(
+ thickness_position, linestyle.thickness_ratio,
+ m.blend, m.influence,
+ m.amplitude, m.period, m.seed, m.use_asymmetric))
+ elif m.type == 'CREASE_ANGLE':
+ shaders_list.append(CreaseAngleThicknessShader(
+ thickness_position, linestyle.thickness_ratio,
+ m.blend, m.influence, m.mapping, m.invert, m.curve,
+ m.angle_min, m.angle_max, m.thickness_min, m.thickness_max))
+ elif m.type == 'CURVATURE_3D':
+ shaders_list.append(Curvature3DThicknessShader(
+ thickness_position, linestyle.thickness_ratio,
+ m.blend, m.influence, m.mapping, m.invert, m.curve,
+ m.curvature_min, m.curvature_max, m.thickness_min, m.thickness_max))
+ else:
+ raise RuntimeError("No Thickness modifier with type", type(m), m)
# -- Textures -- #
has_tex = False
if scene.render.use_shading_nodes:
@@ -1163,24 +1526,26 @@ def process(layer_name, lineset_name):
has_tex = True
if has_tex:
shaders_list.append(StrokeTextureStepShader(linestyle.texture_spacing))
+
+ # execute post-base stylization callbacks
+ for fn in callbacks_modifiers_post:
+ shaders_list.extend(fn(scene, layer, lineset))
+
# -- Stroke caps -- #
if linestyle.caps == 'ROUND':
shaders_list.append(RoundCapShader())
elif linestyle.caps == 'SQUARE':
shaders_list.append(SquareCapShader())
+
# -- Dashed line -- #
if linestyle.use_dashed_line:
- pattern = []
- if linestyle.dash1 > 0 and linestyle.gap1 > 0:
- pattern.append(linestyle.dash1)
- pattern.append(linestyle.gap1)
- if linestyle.dash2 > 0 and linestyle.gap2 > 0:
- pattern.append(linestyle.dash2)
- pattern.append(linestyle.gap2)
- if linestyle.dash3 > 0 and linestyle.gap3 > 0:
- pattern.append(linestyle.dash3)
- pattern.append(linestyle.gap3)
+ pattern = get_dashed_pattern(linestyle)
if len(pattern) > 0:
shaders_list.append(DashedLineShader(pattern))
+
# create strokes using the shaders list
Operators.create(TrueUP1D(), shaders_list)
+
+ # execute line set post-processing callback functions
+ for fn in callbacks_lineset_post:
+ fn(scene, layer, lineset)
diff --git a/release/scripts/freestyle/styles/anisotropic_diffusion.py b/release/scripts/freestyle/styles/anisotropic_diffusion.py
index b17e5c2a38c..fc136b23d82 100644
--- a/release/scripts/freestyle/styles/anisotropic_diffusion.py
+++ b/release/scripts/freestyle/styles/anisotropic_diffusion.py
@@ -19,7 +19,7 @@
# Filename : anisotropic_diffusion.py
# Author : Fredo Durand
# Date : 12/08/2004
-# Purpose : Smoothes lines using an anisotropic diffusion scheme
+# Purpose : Smooth lines using an anisotropic diffusion scheme
from freestyle.chainingiterators import ChainPredicateIterator
from freestyle.predicates import (
@@ -34,7 +34,6 @@ from freestyle.shaders import (
ConstantThicknessShader,
IncreasingColorShader,
SamplingShader,
- StrokeTextureShader,
pyDiffusion2Shader,
)
from freestyle.types import Operators, Stroke
@@ -50,7 +49,6 @@ bpred = TrueBP1D()
Operators.bidirectional_chain(ChainPredicateIterator(upred, bpred), NotUP1D(upred))
shaders_list = [
ConstantThicknessShader(4),
- StrokeTextureShader("smoothAlpha.bmp", Stroke.OPAQUE_MEDIUM, False),
SamplingShader(2),
pyDiffusion2Shader(offset, nbIter),
IncreasingColorShader(1, 0, 0, 1, 0, 1, 0, 1),
diff --git a/release/scripts/freestyle/styles/apriori_density.py b/release/scripts/freestyle/styles/apriori_density.py
index b52bcfbeb4e..1de2c4c0334 100644
--- a/release/scripts/freestyle/styles/apriori_density.py
+++ b/release/scripts/freestyle/styles/apriori_density.py
@@ -19,7 +19,7 @@
# Filename : apriori_density.py
# Author : Stephane Grabli
# Date : 04/08/2005
-# Purpose : Draws lines having a high a priori density
+# Purpose : Draws lines having a high a prior density
from freestyle.chainingiterators import ChainPredicateIterator
from freestyle.predicates import (
diff --git a/release/scripts/freestyle/styles/backbone_stretcher.py b/release/scripts/freestyle/styles/backbone_stretcher.py
index 3eb921ddb34..cc495f33716 100644
--- a/release/scripts/freestyle/styles/backbone_stretcher.py
+++ b/release/scripts/freestyle/styles/backbone_stretcher.py
@@ -30,7 +30,6 @@ from freestyle.predicates import (
from freestyle.shaders import (
BackboneStretcherShader,
ConstantColorShader,
- TextureAssignerShader,
)
from freestyle.types import Operators
@@ -38,7 +37,6 @@ from freestyle.types import Operators
Operators.select(QuantitativeInvisibilityUP1D(0))
Operators.bidirectional_chain(ChainSilhouetteIterator(), NotUP1D(QuantitativeInvisibilityUP1D(0)))
shaders_list = [
- TextureAssignerShader(4),
ConstantColorShader(0.5, 0.5, 0.5),
BackboneStretcherShader(20),
]
diff --git a/release/scripts/freestyle/styles/blueprint_circles.py b/release/scripts/freestyle/styles/blueprint_circles.py
index aade164698a..f39cda5cff9 100644
--- a/release/scripts/freestyle/styles/blueprint_circles.py
+++ b/release/scripts/freestyle/styles/blueprint_circles.py
@@ -34,7 +34,6 @@ from freestyle.predicates import (
from freestyle.shaders import (
ConstantThicknessShader,
IncreasingColorShader,
- TextureAssignerShader,
pyBluePrintCirclesShader,
pyPerlinNoise1DShader,
)
@@ -50,7 +49,6 @@ shaders_list = [
ConstantThicknessShader(5),
pyBluePrintCirclesShader(3),
pyPerlinNoise1DShader(0.1, 15, 8),
- TextureAssignerShader(4),
IncreasingColorShader(0.8, 0.8, 0.3, 0.4, 0.3, 0.3, 0.3, 0.1),
]
Operators.create(TrueUP1D(), shaders_list)
diff --git a/release/scripts/freestyle/styles/blueprint_ellipses.py b/release/scripts/freestyle/styles/blueprint_ellipses.py
index d0bd0c45c6c..3d977a10d1c 100644
--- a/release/scripts/freestyle/styles/blueprint_ellipses.py
+++ b/release/scripts/freestyle/styles/blueprint_ellipses.py
@@ -34,7 +34,6 @@ from freestyle.predicates import (
from freestyle.shaders import (
ConstantThicknessShader,
IncreasingColorShader,
- TextureAssignerShader,
pyBluePrintEllipsesShader,
pyPerlinNoise1DShader,
)
@@ -50,7 +49,6 @@ shaders_list = [
ConstantThicknessShader(5),
pyBluePrintEllipsesShader(3),
pyPerlinNoise1DShader(0.1, 10, 8),
- TextureAssignerShader(4),
IncreasingColorShader(0.6, 0.3, 0.3, 0.7, 0.3, 0.3, 0.3, 0.1),
]
Operators.create(TrueUP1D(), shaders_list)
diff --git a/release/scripts/freestyle/styles/blueprint_squares.py b/release/scripts/freestyle/styles/blueprint_squares.py
index 82ab6a80dd7..7110fe413fc 100644
--- a/release/scripts/freestyle/styles/blueprint_squares.py
+++ b/release/scripts/freestyle/styles/blueprint_squares.py
@@ -34,7 +34,6 @@ from freestyle.predicates import (
from freestyle.shaders import (
ConstantThicknessShader,
IncreasingColorShader,
- TextureAssignerShader,
pyBluePrintSquaresShader,
pyPerlinNoise1DShader,
)
@@ -50,7 +49,6 @@ shaders_list = [
ConstantThicknessShader(8),
pyBluePrintSquaresShader(2, 20),
pyPerlinNoise1DShader(0.07, 10, 8),
- TextureAssignerShader(4),
IncreasingColorShader(0.6, 0.3, 0.3, 0.7, 0.6, 0.3, 0.3, 0.3),
ConstantThicknessShader(4),
]
diff --git a/release/scripts/freestyle/styles/cartoon.py b/release/scripts/freestyle/styles/cartoon.py
index 2e2962cefe5..e630127db1a 100644
--- a/release/scripts/freestyle/styles/cartoon.py
+++ b/release/scripts/freestyle/styles/cartoon.py
@@ -20,7 +20,7 @@
# Author : Stephane Grabli
# Date : 04/08/2005
# Purpose : Draws colored lines. The color is automatically
-# infered from each object's material in a cartoon-like
+# inferred from each object's material in a cartoon-like
# fashion.
from freestyle.chainingiterators import ChainSilhouetteIterator
diff --git a/release/scripts/freestyle/styles/curvature2d.py b/release/scripts/freestyle/styles/curvature2d.py
index 66c8a6c6544..faf1223b735 100644
--- a/release/scripts/freestyle/styles/curvature2d.py
+++ b/release/scripts/freestyle/styles/curvature2d.py
@@ -30,7 +30,6 @@ from freestyle.predicates import (
)
from freestyle.shaders import (
ConstantThicknessShader,
- StrokeTextureShader,
py2DCurvatureColorShader,
)
from freestyle.types import Operators, Stroke
@@ -39,7 +38,6 @@ from freestyle.types import Operators, Stroke
Operators.select(QuantitativeInvisibilityUP1D(0))
Operators.bidirectional_chain(ChainSilhouetteIterator(), NotUP1D(QuantitativeInvisibilityUP1D(0)))
shaders_list = [
- StrokeTextureShader("smoothAlpha.bmp", Stroke.OPAQUE_MEDIUM, False),
ConstantThicknessShader(5),
py2DCurvatureColorShader()
]
diff --git a/release/scripts/freestyle/styles/external_contour_sketchy.py b/release/scripts/freestyle/styles/external_contour_sketchy.py
index 6a7a2333bb5..44dbda4709f 100644
--- a/release/scripts/freestyle/styles/external_contour_sketchy.py
+++ b/release/scripts/freestyle/styles/external_contour_sketchy.py
@@ -37,7 +37,6 @@ from freestyle.shaders import (
SamplingShader,
SmoothingShader,
SpatialNoiseShader,
- TextureAssignerShader,
)
from freestyle.types import Operators
@@ -51,6 +50,5 @@ shaders_list = [
IncreasingThicknessShader(4, 10),
SmoothingShader(400, 0.1, 0, 0.2, 0, 0, 0, 1),
IncreasingColorShader(1, 0, 0, 1, 0, 1, 0, 1),
- TextureAssignerShader(4),
]
Operators.create(TrueUP1D(), shaders_list)
diff --git a/release/scripts/freestyle/styles/japanese_bigbrush.py b/release/scripts/freestyle/styles/japanese_bigbrush.py
index 80afeff48d0..a312bcd4358 100644
--- a/release/scripts/freestyle/styles/japanese_bigbrush.py
+++ b/release/scripts/freestyle/styles/japanese_bigbrush.py
@@ -37,7 +37,6 @@ from freestyle.shaders import (
ConstantColorShader,
ConstantThicknessShader,
SamplingShader,
- TextureAssignerShader,
TipRemoverShader,
pyNonLinearVaryingThicknessShader,
pySamplingShader,
@@ -47,7 +46,7 @@ from freestyle.types import IntegrationType, Operators
Operators.select(QuantitativeInvisibilityUP1D(0))
Operators.bidirectional_chain(ChainSilhouetteIterator(), NotUP1D(QuantitativeInvisibilityUP1D(0)))
-## Splits strokes at points of highest 2D curavture
+## Splits strokes at points of highest 2D curvature
## when there are too many abrupt turns in it
func = pyInverseCurvature2DAngleF0D()
Operators.recursive_split(func, pyParameterUP0D(0.2, 0.8), NotUP1D(pyHigherNumberOfTurnsUP1D(3, 0.5)), 2)
@@ -62,7 +61,6 @@ shaders_list = [
SamplingShader(50),
ConstantThicknessShader(10),
pyNonLinearVaryingThicknessShader(4, 25, 0.6),
- TextureAssignerShader(6),
ConstantColorShader(0.2, 0.2, 0.2,1.0),
TipRemoverShader(10),
]
diff --git a/release/scripts/freestyle/styles/multiple_parameterization.py b/release/scripts/freestyle/styles/multiple_parameterization.py
index bf0691f2ce1..0e224c74bbf 100644
--- a/release/scripts/freestyle/styles/multiple_parameterization.py
+++ b/release/scripts/freestyle/styles/multiple_parameterization.py
@@ -37,7 +37,6 @@ from freestyle.shaders import (
IncreasingColorShader,
IncreasingThicknessShader,
SamplingShader,
- TextureAssignerShader,
pyHLRShader,
)
from freestyle.types import Operators
@@ -52,7 +51,6 @@ shaders_list = [
IncreasingThicknessShader(1.5, 30),
ConstantColorShader(0.0, 0.0, 0.0),
IncreasingColorShader(1, 0, 0, 1, 0, 1, 0, 1),
- TextureAssignerShader(-1),
pyHLRShader(), ## this shader draws only visible portions
]
Operators.create(TrueUP1D(), shaders_list)
diff --git a/release/scripts/freestyle/styles/near_lines.py b/release/scripts/freestyle/styles/near_lines.py
index b91eaea4023..5e260a22382 100644
--- a/release/scripts/freestyle/styles/near_lines.py
+++ b/release/scripts/freestyle/styles/near_lines.py
@@ -33,7 +33,6 @@ from freestyle.predicates import (
from freestyle.shaders import (
ConstantColorShader,
ConstantThicknessShader,
- TextureAssignerShader,
)
from freestyle.types import IntegrationType, Operators
@@ -42,7 +41,6 @@ upred = AndUP1D(QuantitativeInvisibilityUP1D(0), pyZSmallerUP1D(0.5, Integration
Operators.select(upred)
Operators.bidirectional_chain(ChainSilhouetteIterator(), NotUP1D(upred))
shaders_list = [
- TextureAssignerShader(-1),
ConstantThicknessShader(5),
ConstantColorShader(0.0, 0.0, 0.0),
]
diff --git a/release/scripts/freestyle/styles/qi0_not_external_contour.py b/release/scripts/freestyle/styles/qi0_not_external_contour.py
index fb3e3279b6c..3c9b8873485 100644
--- a/release/scripts/freestyle/styles/qi0_not_external_contour.py
+++ b/release/scripts/freestyle/styles/qi0_not_external_contour.py
@@ -36,7 +36,6 @@ from freestyle.shaders import (
IncreasingThicknessShader,
SamplingShader,
SpatialNoiseShader,
- TextureAssignerShader,
)
from freestyle.types import Operators
@@ -50,6 +49,5 @@ shaders_list = [
IncreasingThicknessShader(2, 5),
BackboneStretcherShader(20),
IncreasingColorShader(1, 0, 0, 1, 0, 1, 0, 1),
- TextureAssignerShader(4),
]
Operators.create(TrueUP1D(), shaders_list)
diff --git a/release/scripts/freestyle/styles/sequentialsplit_sketchy.py b/release/scripts/freestyle/styles/sequentialsplit_sketchy.py
index e97e8f6da39..b980fdc87d7 100644
--- a/release/scripts/freestyle/styles/sequentialsplit_sketchy.py
+++ b/release/scripts/freestyle/styles/sequentialsplit_sketchy.py
@@ -35,7 +35,6 @@ from freestyle.shaders import (
ConstantColorShader,
IncreasingThicknessShader,
SpatialNoiseShader,
- TextureAssignerShader,
)
from freestyle.types import Nature, Operators
@@ -51,6 +50,5 @@ shaders_list = [
SpatialNoiseShader(7, 120, 2, True, True),
IncreasingThicknessShader(5, 8),
ConstantColorShader(0.2, 0.2, 0.2, 1),
- TextureAssignerShader(4),
]
Operators.create(TrueUP1D(), shaders_list)
diff --git a/release/scripts/freestyle/styles/sketchy_multiple_parameterization.py b/release/scripts/freestyle/styles/sketchy_multiple_parameterization.py
index 0beb6e37c21..a3ce6112165 100644
--- a/release/scripts/freestyle/styles/sketchy_multiple_parameterization.py
+++ b/release/scripts/freestyle/styles/sketchy_multiple_parameterization.py
@@ -34,7 +34,6 @@ from freestyle.shaders import (
SamplingShader,
SmoothingShader,
SpatialNoiseShader,
- TextureAssignerShader,
pyHLRShader,
)
from freestyle.types import Operators
@@ -48,7 +47,6 @@ shaders_list = [
IncreasingThicknessShader(5, 30),
SmoothingShader(100, 0.05, 0, 0.2, 0, 0, 0, 1),
IncreasingColorShader(0, 0.2, 0, 1, 0.2, 0.7, 0.2, 1),
- TextureAssignerShader(6),
pyHLRShader(),
]
Operators.create(TrueUP1D(), shaders_list)
diff --git a/release/scripts/freestyle/styles/sketchy_topology_broken.py b/release/scripts/freestyle/styles/sketchy_topology_broken.py
index 671bc2b1592..191d2d8bcbe 100644
--- a/release/scripts/freestyle/styles/sketchy_topology_broken.py
+++ b/release/scripts/freestyle/styles/sketchy_topology_broken.py
@@ -20,7 +20,7 @@
# Author : Stephane Grabli
# Date : 04/08/2005
# Purpose : The topology of the strokes is, first, built
-# independantly from the 3D topology of objects,
+# independently from the 3D topology of objects,
# and, second, so as to chain several times the same ViewEdge.
from freestyle.chainingiterators import pySketchyChainingIterator
@@ -34,14 +34,13 @@ from freestyle.shaders import (
SamplingShader,
SmoothingShader,
SpatialNoiseShader,
- TextureAssignerShader,
- pyBackboneStretcherNoCuspShader
+ pyBackboneStretcherNoCuspShader,
)
from freestyle.types import Operators
Operators.select(QuantitativeInvisibilityUP1D(0))
-## Chain 3 times each ViewEdge indpendantly from the
+## Chain 3 times each ViewEdge independently from the
## initial objects topology
Operators.bidirectional_chain(pySketchyChainingIterator(3))
shaders_list = [
@@ -50,9 +49,6 @@ shaders_list = [
IncreasingThicknessShader(4, 10),
SmoothingShader(100, 0.1, 0, 0.2, 0, 0, 0, 1),
pyBackboneStretcherNoCuspShader(20),
- #ConstantColorShader(0.0, 0.0, 0.0)
IncreasingColorShader(0.2, 0.2, 0.2, 1, 0.5, 0.5, 0.5, 1),
- #IncreasingColorShader(1, 0, 0, 1, 0, 1, 0, 1),
- TextureAssignerShader(4),
]
Operators.create(TrueUP1D(), shaders_list)
diff --git a/release/scripts/freestyle/styles/sketchy_topology_preserved.py b/release/scripts/freestyle/styles/sketchy_topology_preserved.py
index 161654f1f97..26c7fd37964 100644
--- a/release/scripts/freestyle/styles/sketchy_topology_preserved.py
+++ b/release/scripts/freestyle/styles/sketchy_topology_preserved.py
@@ -34,7 +34,6 @@ from freestyle.shaders import (
SamplingShader,
SmoothingShader,
SpatialNoiseShader,
- TextureAssignerShader,
)
from freestyle.types import Operators
@@ -48,6 +47,5 @@ shaders_list = [
IncreasingThicknessShader(4, 8),
SmoothingShader(300, 0.05, 0, 0.2, 0, 0, 0, 0.5),
ConstantColorShader(0.6, 0.2, 0.0),
- TextureAssignerShader(4),
]
Operators.create(TrueUP1D(), shaders_list)
diff --git a/release/scripts/freestyle/styles/split_at_highest_2d_curvatures.py b/release/scripts/freestyle/styles/split_at_highest_2d_curvatures.py
index 3bfdb05a2db..68a80d89ea7 100644
--- a/release/scripts/freestyle/styles/split_at_highest_2d_curvatures.py
+++ b/release/scripts/freestyle/styles/split_at_highest_2d_curvatures.py
@@ -34,7 +34,6 @@ from freestyle.predicates import (
from freestyle.shaders import (
ConstantThicknessShader,
IncreasingColorShader,
- TextureAssignerShader,
)
from freestyle.types import Operators
@@ -46,6 +45,5 @@ Operators.recursive_split(func, pyParameterUP0D(0.4, 0.6), NotUP1D(pyHigherLengt
shaders_list = [
ConstantThicknessShader(10),
IncreasingColorShader(1, 0, 0, 1, 0, 1, 0, 1),
- TextureAssignerShader(3),
]
Operators.create(TrueUP1D(), shaders_list)
diff --git a/release/scripts/freestyle/styles/split_at_tvertices.py b/release/scripts/freestyle/styles/split_at_tvertices.py
index 213922a03b1..8978b98f56b 100644
--- a/release/scripts/freestyle/styles/split_at_tvertices.py
+++ b/release/scripts/freestyle/styles/split_at_tvertices.py
@@ -31,7 +31,6 @@ from freestyle.predicates import (
from freestyle.shaders import (
ConstantThicknessShader,
IncreasingColorShader,
- TextureAssignerShader,
)
from freestyle.types import Nature, Operators
@@ -45,6 +44,5 @@ Operators.sequential_split(start, start, 10)
shaders_list = [
ConstantThicknessShader(5),
IncreasingColorShader(1, 0, 0, 1, 0, 1, 0, 1),
- TextureAssignerShader(3),
]
Operators.create(TrueUP1D(), shaders_list)
diff --git a/release/scripts/freestyle/styles/stroke_texture.py b/release/scripts/freestyle/styles/stroke_texture.py
deleted file mode 100644
index 614c34a6654..00000000000
--- a/release/scripts/freestyle/styles/stroke_texture.py
+++ /dev/null
@@ -1,49 +0,0 @@
-# ##### BEGIN GPL LICENSE BLOCK #####
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software Foundation,
-# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-#
-# ##### END GPL LICENSE BLOCK #####
-
-# Filename : stroke_texture.py
-# Author : Stephane Grabli
-# Date : 04/08/2005
-# Purpose : Draws textured strokes (illustrate the StrokeTextureShader shader)
-
-from freestyle.chainingiterators import ChainSilhouetteIterator
-from freestyle.predicates import (
- NotUP1D,
- QuantitativeInvisibilityUP1D,
- TrueUP1D,
- )
-from freestyle.shaders import (
- BezierCurveShader,
- ConstantColorShader,
- ConstantThicknessShader,
- SamplingShader,
- StrokeTextureShader,
- )
-from freestyle.types import Operators, Stroke
-
-
-Operators.select(QuantitativeInvisibilityUP1D(0))
-Operators.bidirectional_chain(ChainSilhouetteIterator(), NotUP1D(QuantitativeInvisibilityUP1D(0)))
-shaders_list = [
- SamplingShader(3),
- BezierCurveShader(4),
- StrokeTextureShader("washbrushAlpha.bmp", Stroke.DRY_MEDIUM, True),
- ConstantThicknessShader(40),
- ConstantColorShader(0, 0, 0, 1),
- ]
-Operators.create(TrueUP1D(), shaders_list)
diff --git a/release/scripts/freestyle/styles/uniformpruning_zsort.py b/release/scripts/freestyle/styles/uniformpruning_zsort.py
index 29b634b765b..814e140ee49 100644
--- a/release/scripts/freestyle/styles/uniformpruning_zsort.py
+++ b/release/scripts/freestyle/styles/uniformpruning_zsort.py
@@ -30,7 +30,6 @@ from freestyle.shaders import (
ConstantColorShader,
ConstantThicknessShader,
SamplingShader,
- StrokeTextureShader,
)
from freestyle.types import IntegrationType, Operators, Stroke
@@ -40,10 +39,8 @@ Operators.bidirectional_chain(ChainSilhouetteIterator())
#Operators.sequential_split(pyVertexNatureUP0D(Nature.VIEW_VERTEX), 2)
Operators.sort(pyZBP1D())
shaders_list = [
- StrokeTextureShader("smoothAlpha.bmp", Stroke.OPAQUE_MEDIUM, False),
ConstantThicknessShader(3),
SamplingShader(5.0),
ConstantColorShader(0, 0, 0, 1),
]
Operators.create(pyDensityUP1D(2, 0.05, IntegrationType.MEAN, 4), shaders_list)
-#Operators.create(pyDensityFunctorUP1D(8, 0.03, pyGetInverseProjectedZF1D(), 0, 1, IntegrationType.MEAN), shaders_list)
diff --git a/release/scripts/modules/addon_utils.py b/release/scripts/modules/addon_utils.py
index 88356b676d2..123b3cb953c 100644
--- a/release/scripts/modules/addon_utils.py
+++ b/release/scripts/modules/addon_utils.py
@@ -36,6 +36,15 @@ error_encoding = False
addons_fake_modules = {}
+# called only once at startup, avoids calling 'reset_all', correct but slower.
+def _initialize():
+ path_list = paths()
+ for path in path_list:
+ _bpy.utils._sys_path_ensure(path)
+ for addon in _user_preferences.addons:
+ enable(addon.module)
+
+
def paths():
# RELEASE SCRIPTS: official scripts distributed in Blender releases
addon_paths = _bpy.utils.script_paths("addons")
@@ -44,10 +53,6 @@ def paths():
# if folder addons_contrib/ exists, scripts in there will be loaded too
addon_paths += _bpy.utils.script_paths("addons_contrib")
- # EXTERN SCRIPTS: external projects scripts
- # if folder addons_extern/ exists, scripts in there will be loaded too
- addon_paths += _bpy.utils.script_paths("addons_extern")
-
return addon_paths
@@ -69,40 +74,43 @@ def modules_refresh(module_cache=addons_fake_modules):
print("fake_module", mod_path, mod_name)
import ast
ModuleType = type(ast)
- file_mod = open(mod_path, "r", encoding='UTF-8')
- if speedy:
- lines = []
- line_iter = iter(file_mod)
- l = ""
- while not l.startswith("bl_info"):
- try:
- l = line_iter.readline()
- except UnicodeDecodeError as e:
- if not error_encoding:
- error_encoding = True
- print("Error reading file as UTF-8:", mod_path, e)
- file_mod.close()
- return None
-
- if len(l) == 0:
- break
- while l.rstrip():
- lines.append(l)
- try:
- l = line_iter.readline()
- except UnicodeDecodeError as e:
- if not error_encoding:
- error_encoding = True
- print("Error reading file as UTF-8:", mod_path, e)
- file_mod.close()
- return None
-
- data = "".join(lines)
-
- else:
- data = file_mod.read()
+ try:
+ file_mod = open(mod_path, "r", encoding='UTF-8')
+ except OSError as e:
+ print("Error opening file %r: %s" % (mod_path, e))
+ return None
- file_mod.close()
+ with file_mod:
+ if speedy:
+ lines = []
+ line_iter = iter(file_mod)
+ l = ""
+ while not l.startswith("bl_info"):
+ try:
+ l = line_iter.readline()
+ except UnicodeDecodeError as e:
+ if not error_encoding:
+ error_encoding = True
+ print("Error reading file as UTF-8:", mod_path, e)
+ return None
+
+ if len(l) == 0:
+ break
+ while l.rstrip():
+ lines.append(l)
+ try:
+ l = line_iter.readline()
+ except UnicodeDecodeError as e:
+ if not error_encoding:
+ error_encoding = True
+ print("Error reading file as UTF-8:", mod_path, e)
+ return None
+
+ data = "".join(lines)
+
+ else:
+ data = file_mod.read()
+ del file_mod
try:
ast_data = ast.parse(data, filename=mod_path)
@@ -148,13 +156,13 @@ def modules_refresh(module_cache=addons_fake_modules):
for path in path_list:
# force all contrib addons to be 'TESTING'
- if path.endswith(("addons_contrib", "addons_extern")):
+ if path.endswith(("addons_contrib", )):
force_support = 'TESTING'
else:
force_support = None
for mod_name, mod_path in _bpy.path.module_names(path):
- modules_stale -= {mod_name}
+ modules_stale.discard(mod_name)
mod = module_cache.get(mod_name)
if mod:
if mod.__file__ != mod_path:
@@ -186,14 +194,16 @@ def modules_refresh(module_cache=addons_fake_modules):
def modules(module_cache=addons_fake_modules, refresh=True):
- if refresh:
+ if refresh or ((module_cache is addons_fake_modules) and modules._is_first):
modules_refresh(module_cache)
+ modules._is_first = False
mod_list = list(module_cache.values())
mod_list.sort(key=lambda mod: (mod.bl_info["category"],
mod.bl_info["name"],
))
return mod_list
+modules._is_first = True
def check(module_name):
@@ -209,7 +219,8 @@ def check(module_name):
loaded_default = module_name in _user_preferences.addons
mod = sys.modules.get(module_name)
- loaded_state = mod and getattr(mod, "__addon_enabled__", Ellipsis)
+ loaded_state = ((mod is not None) and
+ getattr(mod, "__addon_enabled__", Ellipsis))
if loaded_state is Ellipsis:
print("Warning: addon-module %r found module "
@@ -244,7 +255,7 @@ def _addon_remove(module_name):
addons.remove(addon)
-def enable(module_name, default_set=True, persistent=False, handle_error=None):
+def enable(module_name, default_set=False, persistent=False, handle_error=None):
"""
Enables an addon by name.
@@ -267,15 +278,29 @@ def enable(module_name, default_set=True, persistent=False, handle_error=None):
mod = sys.modules.get(module_name)
# chances of the file _not_ existing are low, but it could be removed
if mod and os.path.exists(mod.__file__):
+
+ if getattr(mod, "__addon_enabled__", False):
+ # This is an unlikely situation,
+ # re-register if the module is enabled.
+ # Note: the UI doesn't allow this to happen,
+ # in most cases the caller should 'check()' first.
+ try:
+ mod.unregister()
+ except:
+ print("Exception in module unregister(): %r" %
+ getattr(mod, "__file__", module_name))
+ handle_error()
+ return None
+
mod.__addon_enabled__ = False
mtime_orig = getattr(mod, "__time__", 0)
mtime_new = os.path.getmtime(mod.__file__)
if mtime_orig != mtime_new:
- import imp
+ import importlib
print("module changed on disk:", mod.__file__, "reloading...")
try:
- imp.reload(mod)
+ importlib.reload(mod)
except:
handle_error()
del sys.modules[module_name]
@@ -299,9 +324,15 @@ def enable(module_name, default_set=True, persistent=False, handle_error=None):
mod = __import__(module_name)
mod.__time__ = os.path.getmtime(mod.__file__)
mod.__addon_enabled__ = False
- except:
- handle_error()
- _addon_remove(module_name)
+ except Exception as ex:
+ # if the addon doesn't exist, dont print full traceback
+ if type(ex) is ImportError and ex.name == module_name:
+ print("addon not found: %r" % module_name)
+ else:
+ handle_error()
+
+ if default_set:
+ _addon_remove(module_name)
return None
# 2) try register collected modules
@@ -315,7 +346,8 @@ def enable(module_name, default_set=True, persistent=False, handle_error=None):
getattr(mod, "__file__", module_name))
handle_error()
del sys.modules[module_name]
- _addon_remove(module_name)
+ if default_set:
+ _addon_remove(module_name)
return None
# * OK loaded successfully! *
@@ -328,7 +360,7 @@ def enable(module_name, default_set=True, persistent=False, handle_error=None):
return mod
-def disable(module_name, default_set=True, handle_error=None):
+def disable(module_name, default_set=False, handle_error=None):
"""
Disables an addon by name.
@@ -388,10 +420,10 @@ def reset_all(reload_scripts=False):
# first check if reload is needed before changing state.
if reload_scripts:
- import imp
+ import importlib
mod = sys.modules.get(mod_name)
if mod:
- imp.reload(mod)
+ importlib.reload(mod)
if is_enabled == is_loaded:
pass
@@ -402,19 +434,21 @@ def reset_all(reload_scripts=False):
disable(mod_name)
-def module_bl_info(mod, info_basis={"name": "",
- "author": "",
- "version": (),
- "blender": (),
- "location": "",
- "description": "",
- "wiki_url": "",
- "support": 'COMMUNITY',
- "category": "",
- "warning": "",
- "show_expanded": False,
- }
- ):
+def module_bl_info(mod, info_basis=None):
+ if info_basis is None:
+ info_basis = {
+ "name": "",
+ "author": "",
+ "version": (),
+ "blender": (),
+ "location": "",
+ "description": "",
+ "wiki_url": "",
+ "support": 'COMMUNITY',
+ "category": "",
+ "warning": "",
+ "show_expanded": False,
+ }
addon_info = getattr(mod, "bl_info", {})
diff --git a/release/scripts/modules/animsys_refactor.py b/release/scripts/modules/animsys_refactor.py
index aaa06c32312..39f0ad2f049 100644
--- a/release/scripts/modules/animsys_refactor.py
+++ b/release/scripts/modules/animsys_refactor.py
@@ -51,7 +51,7 @@ def classes_recursive(base_type, clss=None):
return clss
-class DataPathBuilder(object):
+class DataPathBuilder:
"""Dummy class used to parse fcurve and driver data paths."""
__slots__ = ("data_path", )
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 8874ecceb77..43a09a1acbd 100644
--- a/release/scripts/modules/bl_i18n_utils/bl_extract_messages.py
+++ b/release/scripts/modules/bl_i18n_utils/bl_extract_messages.py
@@ -62,8 +62,9 @@ def _gen_check_ctxt(settings):
"spell_errors": {},
}
+
def _diff_check_ctxt(check_ctxt, minus_check_ctxt):
- """Returns check_ctxt - minus_check_ctxt"""
+ """Removes minus_check_ctxt from check_ctxt"""
for key in check_ctxt:
if isinstance(check_ctxt[key], set):
for warning in minus_check_ctxt[key]:
@@ -74,6 +75,7 @@ def _diff_check_ctxt(check_ctxt, minus_check_ctxt):
if warning in check_ctxt[key]:
del check_ctxt[key][warning]
+
def _gen_reports(check_ctxt):
return {
"check_ctxt": check_ctxt,
@@ -256,7 +258,7 @@ def dump_rna_messages(msgs, reports, settings, verbose=False):
bpy.types.Panel.__subclasses__() +
bpy.types.Menu.__subclasses__() +
bpy.types.UIList.__subclasses__()
- if cls.__name__ not in _rna_clss_ids}
+ if cls.__name__ not in _rna_clss_ids}
# Collect internal operators
# extend with all internal operators
@@ -264,8 +266,8 @@ def dump_rna_messages(msgs, reports, settings, verbose=False):
# XXX Do not skip INTERNAL's anymore, some of those ops show up in UI now!
# all possible operator names
#op_ids = (set(cls.bl_rna.identifier for cls in bpy.types.OperatorProperties.__subclasses__()) |
- #set(cls.bl_rna.identifier for cls in bpy.types.Operator.__subclasses__()) |
- #set(cls.bl_rna.identifier for cls in bpy.types.OperatorMacro.__subclasses__()))
+ # set(cls.bl_rna.identifier for cls in bpy.types.Operator.__subclasses__()) |
+ # set(cls.bl_rna.identifier for cls in bpy.types.OperatorMacro.__subclasses__()))
#get_instance = __import__("_bpy").ops.get_instance
#path_resolve = type(bpy.context).__base__.path_resolve
@@ -473,7 +475,6 @@ def dump_py_messages_from_files(msgs, reports, files, settings):
return [_extract_string_merge(estr_ls, nds_ls) for estr_ls, nds_ls in bag]
-
i18n_ctxt_ids = {v for v in bpy.app.translations.contexts_C_to_py.values()}
def _ctxt_to_ctxt(node):
# We must try, to some extend, to get contexts from vars instead of only literal strings...
@@ -575,8 +576,9 @@ def dump_py_messages_from_files(msgs, reports, files, settings):
#print(func_translate_args)
# Break recursive nodes look up on some kind of nodes.
- # E.g. we don’t want to get strings inside subscripts (blah["foo"])!
- stopper_nodes = {ast.Subscript}
+ # E.g. we don't want to get strings inside subscripts (blah["foo"])!
+ # we don't want to get strings from comparisons (foo.type == 'BAR').
+ stopper_nodes = {ast.Subscript, ast.Compare}
# Consider strings separate: ("a" if test else "b")
separate_nodes = {ast.IfExp}
@@ -821,9 +823,9 @@ def dump_messages(do_messages, do_checks, settings):
# Get strings from addons' categories.
for uid, label, tip in bpy.types.WindowManager.addon_filter[1]['items'](bpy.context.window_manager, bpy.context):
- process_msg(msgs, settings.DEFAULT_CONTEXT, label, "Addons' categories", reports, None, settings)
+ process_msg(msgs, settings.DEFAULT_CONTEXT, label, "Add-ons' categories", reports, None, settings)
if tip:
- process_msg(msgs, settings.DEFAULT_CONTEXT, tip, "Addons' categories", reports, None, settings)
+ process_msg(msgs, settings.DEFAULT_CONTEXT, tip, "Add-ons' categories", reports, None, settings)
# Get strings specific to translations' menu.
for lng in settings.LANGUAGES:
@@ -896,7 +898,7 @@ def dump_addon_messages(module_name, do_checks, settings):
del msgs[key]
if check_ctxt:
- check_ctxt = _diff_check_ctxt(check_ctxt, minus_check_ctxt)
+ _diff_check_ctxt(check_ctxt, minus_check_ctxt)
# and we are done with those!
del minus_pot
@@ -923,18 +925,18 @@ def main():
return
import sys
- back_argv = sys.argv
+ import argparse
+
# Get rid of Blender args!
- sys.argv = sys.argv[sys.argv.index("--") + 1:]
+ argv = sys.argv[sys.argv.index("--") + 1:] if "--" in sys.argv else []
- import argparse
parser = argparse.ArgumentParser(description="Process UI messages from inside Blender.")
parser.add_argument('-c', '--no_checks', default=True, action="store_false", help="No checks over UI messages.")
parser.add_argument('-m', '--no_messages', default=True, action="store_false", help="No export of UI messages.")
parser.add_argument('-o', '--output', default=None, help="Output POT file path.")
parser.add_argument('-s', '--settings', default=None,
help="Override (some) default settings. Either a JSon file name, or a JSon string.")
- args = parser.parse_args()
+ args = parser.parse_args(argv)
settings = settings_i18n.I18nSettings()
settings.from_json(args.settings)
@@ -944,8 +946,6 @@ def main():
dump_messages(do_messages=args.no_messages, do_checks=args.no_checks, settings=settings)
- sys.argv = back_argv
-
if __name__ == "__main__":
print("\n\n *** Running {} *** \n".format(__file__))
diff --git a/release/scripts/modules/bl_i18n_utils/merge_po.py b/release/scripts/modules/bl_i18n_utils/merge_po.py
index d7dade22ffd..2fda42199bb 100755
--- a/release/scripts/modules/bl_i18n_utils/merge_po.py
+++ b/release/scripts/modules/bl_i18n_utils/merge_po.py
@@ -30,17 +30,20 @@
import sys
-try:
+if __package__ is None:
import settings
import utils
-except:
- from . import (settings, utils)
+else:
+ from . import (
+ settings,
+ utils,
+ )
# XXX This is a quick hack to make it work with new I18n... objects! To be reworked!
def main():
import argparse
- parser = argparse.ArgumentParser(description=""
+ parser = argparse.ArgumentParser(description=
"Merge one or more .po files into the first dest one.\n"
"If a msgkey (msgctxt, msgid) is present in more than one merged po, the one in the first file "
"wins, unless it’s marked as fuzzy and one later is not.\n"
diff --git a/release/scripts/modules/bl_i18n_utils/settings.py b/release/scripts/modules/bl_i18n_utils/settings.py
index 300cd7ae955..49dbfbe62af 100644
--- a/release/scripts/modules/bl_i18n_utils/settings.py
+++ b/release/scripts/modules/bl_i18n_utils/settings.py
@@ -88,6 +88,7 @@ LANGUAGES = (
(38, "Uzbek (Oʻzbek)", "uz_UZ"),
(39, "Uzbek Cyrillic (Ўзбек)", "uz_UZ@cyrillic"),
(40, "Hindi (मानक हिनà¥à¤¦à¥€)", "hi_IN"),
+ (41, "Vietnamese (tiếng Việt)", "vi_VN"),
)
# Default context, in py!
@@ -101,7 +102,7 @@ IMPORT_MIN_LEVEL = 0.0
# Languages in /branches we do not want to import in /trunk currently...
IMPORT_LANGUAGES_SKIP = {
- 'am_ET', 'bg_BG', 'fi_FI', 'el_GR', 'et_EE', 'ne_NP', 'pl_PL', 'ro_RO', 'uz_UZ', 'uz_UZ@cyrillic',
+ 'am_ET', 'bg_BG', 'fi_FI', 'el_GR', 'et_EE', 'ne_NP', 'ro_RO', 'uz_UZ', 'uz_UZ@cyrillic',
}
# Languages that need RTL pre-processing.
@@ -183,15 +184,15 @@ DOMAIN = "blender"
# File type (ext) to parse.
PYGETTEXT_ALLOWED_EXTS = {".c", ".cpp", ".cxx", ".hpp", ".hxx", ".h"}
-# Max number of contexts into a BLF_I18N_MSGID_MULTI_CTXT macro...
+# Max number of contexts into a BLT_I18N_MSGID_MULTI_CTXT macro...
PYGETTEXT_MAX_MULTI_CTXT = 16
# Where to search contexts definitions, relative to SOURCE_DIR (defined below).
-PYGETTEXT_CONTEXTS_DEFSRC = os.path.join("source", "blender", "blenfont", "BLF_translation.h")
+PYGETTEXT_CONTEXTS_DEFSRC = os.path.join("source", "blender", "blentranslation", "BLT_translation.h")
-# Regex to extract contexts defined in BLF_translation.h
+# Regex to extract contexts defined in BLT_translation.h
# XXX Not full-proof, but should be enough here!
-PYGETTEXT_CONTEXTS = "#define\\s+(BLF_I18NCONTEXT_[A-Z_0-9]+)\\s+\"([^\"]*)\""
+PYGETTEXT_CONTEXTS = "#define\\s+(BLT_I18NCONTEXT_[A-Z_0-9]+)\\s+\"([^\"]*)\""
# Keywords' regex.
# XXX Most unfortunately, we can't use named backreferences inside character sets,
@@ -254,7 +255,7 @@ PYGETTEXT_KEYWORDS = (() +
tuple((r"{}\(\s*" + _msg_re + r"\s*,\s*(?:" +
r"\s*,\s*)?(?:".join(_ctxt_re_gen(i) for i in range(PYGETTEXT_MAX_MULTI_CTXT)) + r")?\s*\)").format(it)
- for it in ("BLF_I18N_MSGID_MULTI_CTXT",))
+ for it in ("BLT_I18N_MSGID_MULTI_CTXT",))
)
# Check printf mismatches between msgid and msgstr.
@@ -284,13 +285,13 @@ WARN_MSGID_NOT_CAPITALIZED_ALLOWED = {
"ascii",
"author", # Addons' field. :/
"bItasc",
+ "dbl-", # Compacted for 'double', for keymap items.
"description", # Addons' field. :/
"dx",
"fBM",
"flac",
"fps: %.2f",
"fps: %i",
- "fStop",
"gimbal",
"global",
"iScale",
@@ -325,14 +326,18 @@ WARN_MSGID_NOT_CAPITALIZED_ALLOWED = {
"y",
# Sub-strings.
"available with",
+ "brown fox",
"can't save image while rendering",
"expected a timeline/animation area to be active",
"expected a view3d region",
"expected a view3d region & editcurve",
"expected a view3d region & editmesh",
"image file not found",
+ "image format is read-only",
"image path can't be written to",
"in memory to enable editing!",
+ "jumps over",
+ "the lazy dog",
"unable to load movie clip",
"unable to load text",
"unable to open the file",
@@ -349,12 +354,13 @@ WARN_MSGID_NOT_CAPITALIZED_ALLOWED = {
WARN_MSGID_NOT_CAPITALIZED_ALLOWED |= set(lng[2] for lng in LANGUAGES)
WARN_MSGID_END_POINT_ALLOWED = {
- "Numpad .",
"Circle|Alt .",
- "Temp. Diff.",
"Float Neg. Exp.",
- " RNA Path: bpy.types.",
"Max Ext.",
+ "Numpad .",
+ "Pad.",
+ " RNA Path: bpy.types.",
+ "Temp. Diff.",
}
PARSER_CACHE_HASH = 'sha1'
@@ -413,6 +419,15 @@ REL_TRUNK_PO_DIR = os.path.join(REL_TRUNK_DIR, "po")
# The /trunk/mo path (relative to I18N_DIR).
REL_TRUNK_MO_DIR = os.path.join(REL_TRUNK_DIR, "locale")
+
+# The path to the *git* translation repository (relative to SOURCE_DIR).
+REL_GIT_I18N_DIR = os.path.join("release/datafiles/locale")
+
+
+# The /po path of the *git* translation repository (relative to REL_GIT_I18N_DIR).
+REL_GIT_I18N_PO_DIR = os.path.join("po")
+
+
# The Blender source path to check for i18n macros (relative to SOURCE_DIR).
REL_POTFILES_SOURCE_DIR = os.path.join("source")
@@ -473,6 +488,7 @@ for p in set(INTERN_PY_SYS_PATHS.split(";")):
def _do_get(ref, path):
return os.path.normpath(os.path.join(ref, path))
+
def _do_set(ref, path):
path = os.path.normpath(path)
# If given path is absolute, make it relative to current ref one (else we consider it is already the case!)
@@ -484,6 +500,7 @@ def _do_set(ref, path):
pass
return path
+
def _gen_get_set_path(ref, name):
def _get(self):
return _do_get(getattr(self, ref), getattr(self, name))
@@ -491,12 +508,6 @@ def _gen_get_set_path(ref, name):
setattr(self, name, _do_set(getattr(self, ref), value))
return _get, _set
-def _gen_get_set_paths(ref, name):
- def _get(self):
- return [_do_get(getattr(self, ref), p) for p in getattr(self, name)]
- def _set(self, value):
- setattr(self, name, [_do_set(getattr(self, ref), p) for p in value])
- return _get, _set
class I18nSettings:
"""
@@ -549,6 +560,8 @@ class I18nSettings:
TRUNK_DIR = property(*(_gen_get_set_path("I18N_DIR", "REL_TRUNK_DIR")))
TRUNK_PO_DIR = property(*(_gen_get_set_path("I18N_DIR", "REL_TRUNK_PO_DIR")))
TRUNK_MO_DIR = property(*(_gen_get_set_path("I18N_DIR", "REL_TRUNK_MO_DIR")))
+ GIT_I18N_ROOT = property(*(_gen_get_set_path("SOURCE_DIR", "REL_GIT_I18N_DIR")))
+ GIT_I18N_PO_DIR = property(*(_gen_get_set_path("GIT_I18N_ROOT", "REL_GIT_I18N_PO_DIR")))
POTFILES_SOURCE_DIR = property(*(_gen_get_set_path("SOURCE_DIR", "REL_POTFILES_SOURCE_DIR")))
FILE_NAME_POT = property(*(_gen_get_set_path("I18N_DIR", "REL_FILE_NAME_POT")))
MO_PATH_ROOT = property(*(_gen_get_set_path("I18N_DIR", "REL_MO_PATH_ROOT")))
diff --git a/release/scripts/modules/bl_i18n_utils/utils.py b/release/scripts/modules/bl_i18n_utils/utils.py
index 911e1764698..5fdb6b88cbf 100644
--- a/release/scripts/modules/bl_i18n_utils/utils.py
+++ b/release/scripts/modules/bl_i18n_utils/utils.py
@@ -31,9 +31,10 @@ import sys
import tempfile
#import time
-from bl_i18n_utils import (settings,
- utils_rtl,
- )
+from bl_i18n_utils import (
+ settings,
+ utils_rtl,
+ )
import bpy
@@ -161,7 +162,7 @@ def get_po_files_from_dir(root_dir, langs=set()):
yield uid, po_file
-def enable_addons(addons={}, support={}, disable=False, check_only=False):
+def enable_addons(addons=None, support=None, disable=False, check_only=False):
"""
Enable (or disable) addons based either on a set of names, or a set of 'support' types.
Returns the list of all affected addons (as fake modules)!
@@ -169,6 +170,11 @@ def enable_addons(addons={}, support={}, disable=False, check_only=False):
"""
import addon_utils
+ if addons is None:
+ addons = {}
+ if support is None:
+ support = {}
+
userpref = bpy.context.user_preferences
used_ext = {ext.module for ext in userpref.addons}
@@ -211,13 +217,13 @@ class I18nMessage:
__slots__ = ("msgctxt_lines", "msgid_lines", "msgstr_lines", "comment_lines", "is_fuzzy", "is_commented",
"settings")
- def __init__(self, msgctxt_lines=[], msgid_lines=[], msgstr_lines=[], comment_lines=[],
+ def __init__(self, msgctxt_lines=None, msgid_lines=None, msgstr_lines=None, comment_lines=None,
is_commented=False, is_fuzzy=False, settings=settings):
self.settings = settings
- self.msgctxt_lines = msgctxt_lines
- self.msgid_lines = msgid_lines
- self.msgstr_lines = msgstr_lines
- self.comment_lines = comment_lines
+ self.msgctxt_lines = msgctxt_lines or []
+ self.msgid_lines = msgid_lines or []
+ self.msgstr_lines = msgstr_lines or []
+ self.comment_lines = comment_lines or []
self.is_fuzzy = is_fuzzy
self.is_commented = is_commented
@@ -975,13 +981,13 @@ class I18nMessages:
def write(self, kind, dest):
self.writers[kind](self, dest)
- def write_messages_to_po(self, fname):
+ def write_messages_to_po(self, fname, compact=False):
"""
Write messages in fname po file.
"""
default_context = self.settings.DEFAULT_CONTEXT
- def _write(self, f):
+ def _write(self, f, compact):
_msgctxt = self.settings.PO_MSGCTXT
_msgid = self.settings.PO_MSGID
_msgstr = self.settings.PO_MSGSTR
@@ -990,9 +996,12 @@ class I18nMessages:
self.escape()
for num, msg in enumerate(self.msgs.values()):
- f.write("\n".join(msg.comment_lines))
+ if compact and (msg.is_commented or msg.is_fuzzy or not msg.msgstr_lines):
+ continue
+ if not compact:
+ f.write("\n".join(msg.comment_lines))
# Only mark as fuzzy if msgstr is not empty!
- if msg.is_fuzzy and msg.msgstr:
+ if msg.is_fuzzy and msg.msgstr_lines:
f.write("\n" + self.settings.PO_COMMENT_FUZZY)
_p = _comm if msg.is_commented else ""
chunks = []
@@ -1029,10 +1038,10 @@ class I18nMessages:
self.normalize(max_len=0) # No wrapping for now...
if isinstance(fname, str):
with open(fname, 'w', encoding="utf-8") as f:
- _write(self, f)
+ _write(self, f, compact)
# Else assume fname is already a file(like) object!
else:
- _write(self, fname)
+ _write(self, fname, compact)
def write_messages_to_mo(self, fname):
"""
@@ -1111,6 +1120,7 @@ class I18nMessages:
writers = {
"PO": write_messages_to_po,
+ "PO_COMPACT": lambda s, fn: s.write_messages_to_po(fn, True),
"MO": write_messages_to_mo,
}
diff --git a/release/scripts/modules/bl_i18n_utils/utils_languages_menu.py b/release/scripts/modules/bl_i18n_utils/utils_languages_menu.py
index 24255d9be61..4f499476ad9 100755
--- a/release/scripts/modules/bl_i18n_utils/utils_languages_menu.py
+++ b/release/scripts/modules/bl_i18n_utils/utils_languages_menu.py
@@ -95,3 +95,5 @@ def gen_menu_file(stats, settings):
data_lines.append("# {} #{}:{}:{}".format(FLAG_MESSAGES[flag], uid_num, label, uid))
with open(os.path.join(settings.TRUNK_MO_DIR, settings.LANGUAGES_FILE), 'w') as f:
f.write("\n".join(data_lines))
+ with open(os.path.join(settings.GIT_I18N_ROOT, settings.LANGUAGES_FILE), 'w') as f:
+ f.write("\n".join(data_lines))
diff --git a/release/scripts/modules/bl_i18n_utils/utils_spell_check.py b/release/scripts/modules/bl_i18n_utils/utils_spell_check.py
index a887ebde449..b1aa4e02cee 100644
--- a/release/scripts/modules/bl_i18n_utils/utils_spell_check.py
+++ b/release/scripts/modules/bl_i18n_utils/utils_spell_check.py
@@ -24,7 +24,7 @@ import pickle
import re
-class SpellChecker():
+class SpellChecker:
"""
A basic spell checker.
"""
@@ -91,11 +91,13 @@ class SpellChecker():
"customdata",
"dataset", "datasets",
"de",
+ "deadzone",
"deconstruct",
"defocus",
"denoise",
"deselect", "deselecting", "deselection",
"despill", "despilling",
+ "dirtree",
"editcurve",
"editmesh",
"filebrowser",
@@ -112,7 +114,7 @@ class SpellChecker():
"libdata",
"lightless",
"lineset",
- "linestyle",
+ "linestyle", "linestyles",
"localview",
"lookup", "lookups",
"mathutils",
@@ -125,7 +127,9 @@ class SpellChecker():
"multisampling",
"multitexture",
"multiuser",
+ "multiview",
"namespace",
+ "nodetree", "nodetrees",
"keyconfig",
"online",
"playhead",
@@ -186,6 +190,7 @@ class SpellChecker():
"unhide",
"unindent",
"unkeyed",
+ "unmute",
"unpremultiply",
"unprojected",
"unreacted",
@@ -217,10 +222,10 @@ class SpellChecker():
"passepartout",
"perspectively",
"pixelate",
+ "pointiness",
"polycount",
"polygonization", "polygonalization", # yuck!
"selectability",
- "slurph",
"stitchable",
"symmetrize",
"trackability",
@@ -260,12 +265,14 @@ class SpellChecker():
"loc", "rot", "pos",
"lorem",
"luma",
+ "mbs", # mouse button 'select'.
"mem",
"multicam",
"num",
"ok",
"orco",
"ortho",
+ "pano",
"persp",
"pref", "prefs",
"prev",
@@ -281,6 +288,7 @@ class SpellChecker():
"struct", "structs",
"sys",
"tex",
+ "tmr", # timer
"tri", "tris",
"uv", "uvs", "uvw", "uw", "uvmap",
"ve",
@@ -454,6 +462,7 @@ class SpellChecker():
"vcol", "vcols",
"vgroup", "vgroups",
"vinterlace",
+ "vse",
"wasd", "wasdqe", # keys...
"wetmap", "wetmaps",
"wpaint",
@@ -509,6 +518,7 @@ class SpellChecker():
"fov",
"fft",
"futura",
+ "fx",
"gfx",
"gl",
"glsl",
@@ -539,6 +549,7 @@ class SpellChecker():
"sdl",
"sl",
"smpte",
+ "ssao",
"svn",
"ui",
"unix",
@@ -572,6 +583,8 @@ class SpellChecker():
"btx",
"cineon",
"dpx",
+ "dwaa",
+ "dwab",
"dxf",
"eps",
"exr",
diff --git a/release/scripts/modules/bl_previews_utils/bl_previews_render.py b/release/scripts/modules/bl_previews_utils/bl_previews_render.py
new file mode 100644
index 00000000000..627a6ab2d3d
--- /dev/null
+++ b/release/scripts/modules/bl_previews_utils/bl_previews_render.py
@@ -0,0 +1,491 @@
+# ***** 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 *****
+
+# <pep8 compliant>
+
+# Populate a template file (POT format currently) from Blender RNA/py/C data.
+# Note: This script is meant to be used from inside Blender!
+
+import collections
+import os
+import sys
+
+import bpy
+from mathutils import Vector, Euler
+
+
+INTERN_PREVIEW_TYPES = {'MATERIAL', 'LAMP', 'WORLD', 'TEXTURE', 'IMAGE'}
+OBJECT_TYPES_RENDER = {'MESH', 'CURVE', 'SURFACE', 'META', 'FONT'}
+
+
+def ids_nolib(bids):
+ return (bid for bid in bids if not bid.library)
+
+
+def rna_backup_gen(data, include_props=None, exclude_props=None, root=()):
+ # only writable properties...
+ for p in data.bl_rna.properties:
+ pid = p.identifier
+ if pid in {'rna_type', }:
+ continue
+ path = root + (pid,)
+ if include_props is not None and path not in include_props:
+ continue
+ if exclude_props is not None and path in exclude_props:
+ continue
+ val = getattr(data, pid)
+ if val is not None and p.type == 'POINTER':
+ # recurse!
+ yield from rna_backup_gen(val, include_props, exclude_props, root=path)
+ elif data.is_property_readonly(pid):
+ continue
+ else:
+ yield path, val
+
+
+def rna_backup_restore(data, backup):
+ for path, val in backup:
+ dt = data
+ for pid in path[:-1]:
+ dt = getattr(dt, pid)
+ setattr(dt, path[-1], val)
+
+
+def do_previews(do_objects, do_groups, do_scenes, do_data_intern):
+ # Helpers.
+ RenderContext = collections.namedtuple("RenderContext", (
+ "scene", "world", "camera", "lamp", "camera_data", "lamp_data", "image", # All those are names!
+ "backup_scene", "backup_world", "backup_camera", "backup_lamp", "backup_camera_data", "backup_lamp_data",
+ ))
+
+ RENDER_PREVIEW_SIZE = bpy.app.render_preview_size
+
+ def render_context_create(engine, objects_ignored):
+ if engine == '__SCENE':
+ backup_scene, backup_world, backup_camera, backup_lamp, backup_camera_data, backup_lamp_data = [()] * 6
+ scene = bpy.context.screen.scene
+ exclude_props = {('world',), ('camera',), ('tool_settings',), ('preview',)}
+ backup_scene = tuple(rna_backup_gen(scene, exclude_props=exclude_props))
+ world = scene.world
+ camera = scene.camera
+ if camera:
+ camera_data = camera.data
+ else:
+ backup_camera, backup_camera_data = [None] * 2
+ camera_data = bpy.data.cameras.new("TEMP_preview_render_camera")
+ camera = bpy.data.objects.new("TEMP_preview_render_camera", camera_data)
+ camera.rotation_euler = Euler((1.1635528802871704, 0.0, 0.7853981852531433), 'XYZ') # (66.67, 0.0, 45.0)
+ scene.camera = camera
+ scene.objects.link(camera)
+ # TODO: add lamp if none found in scene?
+ lamp = None
+ lamp_data = None
+ else:
+ backup_scene, backup_world, backup_camera, backup_lamp, backup_camera_data, backup_lamp_data = [None] * 6
+
+ scene = bpy.data.scenes.new("TEMP_preview_render_scene")
+ world = bpy.data.worlds.new("TEMP_preview_render_world")
+ camera_data = bpy.data.cameras.new("TEMP_preview_render_camera")
+ camera = bpy.data.objects.new("TEMP_preview_render_camera", camera_data)
+ lamp_data = bpy.data.lamps.new("TEMP_preview_render_lamp", 'SPOT')
+ lamp = bpy.data.objects.new("TEMP_preview_render_lamp", lamp_data)
+
+ objects_ignored.add((camera.name, lamp.name))
+
+ scene.world = world
+
+ camera.rotation_euler = Euler((1.1635528802871704, 0.0, 0.7853981852531433), 'XYZ') # (66.67, 0.0, 45.0)
+ scene.camera = camera
+ scene.objects.link(camera)
+
+ lamp.rotation_euler = Euler((0.7853981852531433, 0.0, 1.7453292608261108), 'XYZ') # (45.0, 0.0, 100.0)
+ lamp_data.falloff_type = 'CONSTANT'
+ lamp_data.spot_size = 1.0471975803375244 # 60
+ scene.objects.link(lamp)
+
+ if engine == 'BLENDER_RENDER':
+ scene.render.engine = 'BLENDER_RENDER'
+ scene.render.alpha_mode = 'TRANSPARENT'
+
+ world.use_sky_blend = True
+ world.horizon_color = 0.9, 0.9, 0.9
+ world.zenith_color = 0.5, 0.5, 0.5
+ world.ambient_color = 0.1, 0.1, 0.1
+ world.light_settings.use_environment_light = True
+ world.light_settings.environment_energy = 1.0
+ world.light_settings.environment_color = 'SKY_COLOR'
+ elif engine == 'CYCLES':
+ scene.render.engine = 'CYCLES'
+ scene.cycles.film_transparent = True
+ # TODO: define Cycles world?
+
+ scene.render.image_settings.file_format = 'PNG'
+ scene.render.image_settings.color_depth = '8'
+ scene.render.image_settings.color_mode = 'RGBA'
+ scene.render.image_settings.compression = 25
+ scene.render.resolution_x = RENDER_PREVIEW_SIZE
+ scene.render.resolution_y = RENDER_PREVIEW_SIZE
+ scene.render.resolution_percentage = 100
+ scene.render.filepath = os.path.join(bpy.app.tempdir, 'TEMP_preview_render.png')
+ scene.render.use_overwrite = True
+ scene.render.use_stamp = False
+
+ image = bpy.data.images.new("TEMP_render_image", RENDER_PREVIEW_SIZE, RENDER_PREVIEW_SIZE, alpha=True)
+ image.source = 'FILE'
+ image.filepath = scene.render.filepath
+
+ return RenderContext(
+ scene.name, world.name if world else None, camera.name, lamp.name if lamp else None,
+ camera_data.name, lamp_data.name if lamp_data else None, image.name,
+ backup_scene, backup_world, backup_camera, backup_lamp, backup_camera_data, backup_lamp_data,
+ )
+
+ def render_context_delete(render_context):
+ # We use try/except blocks here to avoid crash, too much things can go wrong, and we want to leave the current
+ # .blend as clean as possible!
+ success = True
+
+ scene = bpy.data.scenes[render_context.scene, None]
+ try:
+ if render_context.backup_scene is None:
+ scene.world = None
+ scene.camera = None
+ if render_context.camera:
+ scene.objects.unlink(bpy.data.objects[render_context.camera, None])
+ if render_context.lamp:
+ scene.objects.unlink(bpy.data.objects[render_context.lamp, None])
+ bpy.data.scenes.remove(scene)
+ scene = None
+ else:
+ rna_backup_restore(scene, render_context.backup_scene)
+ except Exception as e:
+ print("ERROR:", e)
+ success = False
+
+ if render_context.world is not None:
+ try:
+ world = bpy.data.worlds[render_context.world, None]
+ if render_context.backup_world is None:
+ if scene is not None:
+ scene.world = None
+ world.user_clear()
+ bpy.data.worlds.remove(world)
+ else:
+ rna_backup_restore(world, render_context.backup_world)
+ except Exception as e:
+ print("ERROR:", e)
+ success = False
+
+ if render_context.camera:
+ try:
+ camera = bpy.data.objects[render_context.camera, None]
+ if render_context.backup_camera is None:
+ if scene is not None:
+ scene.camera = None
+ scene.objects.unlink(camera)
+ camera.user_clear()
+ bpy.data.objects.remove(camera)
+ bpy.data.cameras.remove(bpy.data.cameras[render_context.camera_data, None])
+ else:
+ rna_backup_restore(camera, render_context.backup_camera)
+ rna_backup_restore(bpy.data.cameras[render_context.camera_data, None],
+ render_context.backup_camera_data)
+ except Exception as e:
+ print("ERROR:", e)
+ success = False
+
+ if render_context.lamp:
+ try:
+ lamp = bpy.data.objects[render_context.lamp, None]
+ if render_context.backup_lamp is None:
+ if scene is not None:
+ scene.objects.unlink(lamp)
+ lamp.user_clear()
+ bpy.data.objects.remove(lamp)
+ bpy.data.lamps.remove(bpy.data.lamps[render_context.lamp_data, None])
+ else:
+ rna_backup_restore(lamp, render_context.backup_lamp)
+ rna_backup_restore(bpy.data.lamps[render_context.lamp_data, None], render_context.backup_lamp_data)
+ except Exception as e:
+ print("ERROR:", e)
+ success = False
+
+ try:
+ image = bpy.data.images[render_context.image, None]
+ image.user_clear()
+ bpy.data.images.remove(image)
+ except Exception as e:
+ print("ERROR:", e)
+ success = False
+
+ return success
+
+ def objects_render_engine_guess(obs):
+ for obname in obs:
+ ob = bpy.data.objects[obname, None]
+ for matslot in ob.material_slots:
+ mat = matslot.material
+ if mat and mat.use_nodes and mat.node_tree:
+ for nd in mat.node_tree.nodes:
+ if nd.shading_compatibility == {'NEW_SHADING'}:
+ return 'CYCLES'
+ return 'BLENDER_RENDER'
+
+ def object_bbox_merge(bbox, ob, ob_space):
+ if ob.bound_box:
+ ob_bbox = ob.bound_box
+ else:
+ ob_bbox = ((-ob.scale.x, -ob.scale.y, -ob.scale.z), (ob.scale.x, ob.scale.y, ob.scale.z))
+ for v in ob.bound_box:
+ v = ob_space.matrix_world.inverted() * ob.matrix_world * Vector(v)
+ if bbox[0].x > v.x:
+ bbox[0].x = v.x
+ if bbox[0].y > v.y:
+ bbox[0].y = v.y
+ if bbox[0].z > v.z:
+ bbox[0].z = v.z
+ if bbox[1].x < v.x:
+ bbox[1].x = v.x
+ if bbox[1].y < v.y:
+ bbox[1].y = v.y
+ if bbox[1].z < v.z:
+ bbox[1].z = v.z
+
+ def objects_bbox_calc(camera, objects):
+ bbox = (Vector((1e9, 1e9, 1e9)), Vector((-1e9, -1e9, -1e9)))
+ for obname in objects:
+ ob = bpy.data.objects[obname, None]
+ object_bbox_merge(bbox, ob, camera)
+ # Our bbox has been generated in camera local space, bring it back in world one
+ bbox[0][:] = camera.matrix_world * bbox[0]
+ bbox[1][:] = camera.matrix_world * bbox[1]
+ cos = (
+ bbox[0].x, bbox[0].y, bbox[0].z,
+ bbox[0].x, bbox[0].y, bbox[1].z,
+ bbox[0].x, bbox[1].y, bbox[0].z,
+ bbox[0].x, bbox[1].y, bbox[1].z,
+ bbox[1].x, bbox[0].y, bbox[0].z,
+ bbox[1].x, bbox[0].y, bbox[1].z,
+ bbox[1].x, bbox[1].y, bbox[0].z,
+ bbox[1].x, bbox[1].y, bbox[1].z,
+ )
+ return cos
+
+ def preview_render_do(render_context, item_container, item_name, objects):
+ scene = bpy.data.scenes[render_context.scene, None]
+ if objects is not None:
+ camera = bpy.data.objects[render_context.camera, None]
+ lamp = bpy.data.objects[render_context.lamp, None] if render_context.lamp is not None else None
+ cos = objects_bbox_calc(camera, objects)
+ loc, ortho_scale = camera.camera_fit_coords(scene, cos)
+ camera.location = loc
+ if lamp:
+ loc, ortho_scale = lamp.camera_fit_coords(scene, cos)
+ lamp.location = loc
+ scene.update()
+
+ bpy.ops.render.render(write_still=True)
+
+ image = bpy.data.images[render_context.image, None]
+ item = getattr(bpy.data, item_container)[item_name, None]
+ image.reload()
+ item.preview.image_size = (RENDER_PREVIEW_SIZE, RENDER_PREVIEW_SIZE)
+ item.preview.image_pixels_float[:] = image.pixels
+
+ # And now, main code!
+ do_save = True
+
+ if do_data_intern:
+ bpy.ops.wm.previews_clear(id_type=INTERN_PREVIEW_TYPES)
+ bpy.ops.wm.previews_ensure()
+
+ render_contexts = {}
+
+ objects_ignored = set()
+ groups_ignored = set()
+
+ prev_scenename = bpy.context.screen.scene.name
+
+ if do_objects:
+ prev_shown = tuple(ob.hide_render for ob in ids_nolib(bpy.data.objects))
+ for ob in ids_nolib(bpy.data.objects):
+ if ob in objects_ignored:
+ continue
+ ob.hide_render = True
+ for root in ids_nolib(bpy.data.objects):
+ if root.name in objects_ignored:
+ continue
+ if root.type not in OBJECT_TYPES_RENDER:
+ continue
+ objects = (root.name,)
+
+ render_engine = objects_render_engine_guess(objects)
+ render_context = render_contexts.get(render_engine, None)
+ if render_context is None:
+ render_context = render_context_create(render_engine, objects_ignored)
+ render_contexts[render_engine] = render_context
+
+ scene = bpy.data.scenes[render_context.scene, None]
+ bpy.context.screen.scene = scene
+
+ for obname in objects:
+ ob = bpy.data.objects[obname, None]
+ if obname not in scene.objects:
+ scene.objects.link(ob)
+ ob.hide_render = False
+ scene.update()
+
+ preview_render_do(render_context, 'objects', root.name, objects)
+
+ # XXX Hyper Super Uber Suspicious Hack!
+ # Without this, on windows build, script excepts with following message:
+ # Traceback (most recent call last):
+ # File "<string>", line 1, in <module>
+ # File "<string>", line 451, in <module>
+ # File "<string>", line 443, in main
+ # File "<string>", line 327, in do_previews
+ # OverflowError: Python int too large to convert to C long
+ # ... :(
+ import sys
+ scene = bpy.data.scenes[render_context.scene, None]
+ for obname in objects:
+ ob = bpy.data.objects[obname, None]
+ scene.objects.unlink(ob)
+ ob.hide_render = True
+
+ for ob, is_rendered in zip(tuple(ids_nolib(bpy.data.objects)), prev_shown):
+ ob.hide_render = is_rendered
+
+ if do_groups:
+ for grp in ids_nolib(bpy.data.groups):
+ if grp.name in groups_ignored:
+ continue
+ objects = tuple(ob.name for ob in grp.objects)
+
+ render_engine = objects_render_engine_guess(objects)
+ render_context = render_contexts.get(render_engine, None)
+ if render_context is None:
+ render_context = render_context_create(render_engine, objects_ignored)
+ render_contexts[render_engine] = render_context
+
+ scene = bpy.data.scenes[render_context.scene, None]
+ bpy.context.screen.scene = scene
+
+ bpy.ops.object.group_instance_add(group=grp.name)
+ grp_ob = next((ob for ob in scene.objects if ob.dupli_group and ob.dupli_group.name == grp.name))
+ grp_obname = grp_ob.name
+ scene.update()
+
+ preview_render_do(render_context, 'groups', grp.name, objects)
+
+ scene = bpy.data.scenes[render_context.scene, None]
+ scene.objects.unlink(bpy.data.objects[grp_obname, None])
+
+ bpy.context.screen.scene = bpy.data.scenes[prev_scenename, None]
+ for render_context in render_contexts.values():
+ if not render_context_delete(render_context):
+ do_save = False # Do not save file if something went wrong here, we could 'pollute' it with temp data...
+
+ if do_scenes:
+ for scene in ids_nolib(bpy.data.scenes):
+ has_camera = scene.camera is not None
+ bpy.context.screen.scene = scene
+ render_context = render_context_create('__SCENE', objects_ignored)
+ scene.update()
+
+ objects = None
+ if not has_camera:
+ # We had to add a temp camera, now we need to place it to see interesting objects!
+ objects = tuple(ob.name for ob in scene.objects
+ if (not ob.hide_render) and (ob.type in OBJECT_TYPES_RENDER))
+
+ preview_render_do(render_context, 'scenes', scene.name, objects)
+
+ if not render_context_delete(render_context):
+ do_save = False
+
+ bpy.context.screen.scene = bpy.data.scenes[prev_scenename, None]
+ if do_save:
+ print("Saving %s..." % bpy.data.filepath)
+ try:
+ bpy.ops.wm.save_mainfile()
+ except Exception as e:
+ # Might fail in some odd cases, like e.g. in regression files we have glsl/ram_glsl.blend which
+ # references an inexistent texture... Better not break in this case, just spit error to console.
+ print("ERROR:", e)
+ else:
+ print("*NOT* Saving %s, because some error(s) happened while deleting temp render data..." % bpy.data.filepath)
+
+
+def do_clear_previews(do_objects, do_groups, do_scenes, do_data_intern):
+ if do_data_intern:
+ bpy.ops.wm.previews_clear(id_type=INTERN_PREVIEW_TYPES)
+
+ if do_objects:
+ for ob in ids_nolib(bpy.data.objects):
+ ob.preview.image_size = (0, 0)
+
+ if do_groups:
+ for grp in ids_nolib(bpy.data.groups):
+ grp.preview.image_size = (0, 0)
+
+ if do_scenes:
+ for scene in ids_nolib(bpy.data.scenes):
+ scene.preview.image_size = (0, 0)
+
+ print("Saving %s..." % bpy.data.filepath)
+ bpy.ops.wm.save_mainfile()
+
+
+def main():
+ try:
+ import bpy
+ except ImportError:
+ print("This script must run from inside blender")
+ return
+
+ import sys
+ import argparse
+
+ # Get rid of Blender args!
+ argv = sys.argv[sys.argv.index("--") + 1:] if "--" in sys.argv else []
+
+ parser = argparse.ArgumentParser(description="Use Blender to generate previews for currently open Blender file's items.")
+ parser.add_argument('--clear', default=False, action="store_true", help="Clear previews instead of generating them.")
+ parser.add_argument('--no_scenes', default=True, action="store_false", help="Do not generate/clear previews for scene IDs.")
+ parser.add_argument('--no_groups', default=True, action="store_false", help="Do not generate/clear previews for group IDs.")
+ parser.add_argument('--no_objects', default=True, action="store_false", help="Do not generate/clear previews for object IDs.")
+ parser.add_argument('--no_data_intern', default=True, action="store_false",
+ help="Do not generate/clear previews for mat/tex/image/etc. IDs (those handled by core Blender code).")
+ args = parser.parse_args(argv)
+
+ if args.clear:
+ print("clear!")
+ do_clear_previews(do_objects=args.no_objects, do_groups=args.no_groups, do_scenes=args.no_scenes,
+ do_data_intern=args.no_data_intern)
+ else:
+ print("render!")
+ do_previews(do_objects=args.no_objects, do_groups=args.no_groups, do_scenes=args.no_scenes,
+ do_data_intern=args.no_data_intern)
+
+
+if __name__ == "__main__":
+ print("\n\n *** Running {} *** \n".format(__file__))
+ print(" *** Blend file {} *** \n".format(bpy.data.filepath))
+ main()
+ bpy.ops.wm.quit_blender()
diff --git a/release/scripts/modules/bpy/__init__.py b/release/scripts/modules/bpy/__init__.py
index 3a2f9bde2c7..b0d2233b380 100644
--- a/release/scripts/modules/bpy/__init__.py
+++ b/release/scripts/modules/bpy/__init__.py
@@ -38,10 +38,10 @@ __all__ = (
from _bpy import types, props, app, data, context
# python modules
-from . import utils, path, ops
+from . import utils, path
# fake operator module
-ops = ops.ops_fake_module
+from .ops import ops_fake_module as ops
def main():
diff --git a/release/scripts/modules/bpy/ops.py b/release/scripts/modules/bpy/ops.py
index f5455ce5018..d3d9255123b 100644
--- a/release/scripts/modules/bpy/ops.py
+++ b/release/scripts/modules/bpy/ops.py
@@ -30,12 +30,13 @@ op_get_rna = ops_module.get_rna
op_get_instance = ops_module.get_instance
-class BPyOps(object):
+class BPyOps:
"""
Fake module like class.
bpy.ops
"""
+ __slots__ = ()
def __getattr__(self, module):
"""
@@ -68,7 +69,7 @@ class BPyOps(object):
return "<module like class 'bpy.ops'>"
-class BPyOpsSubMod(object):
+class BPyOpsSubMod:
"""
Utility class to fake submodules.
@@ -104,7 +105,7 @@ class BPyOpsSubMod(object):
return "<module like class 'bpy.ops.%s'>" % self._module
-class BPyOpsSubModOp(object):
+class BPyOpsSubModOp:
"""
Utility class to fake submodule operators.
diff --git a/release/scripts/modules/bpy/path.py b/release/scripts/modules/bpy/path.py
index 874efc2e131..d7c6101115d 100644
--- a/release/scripts/modules/bpy/path.py
+++ b/release/scripts/modules/bpy/path.py
@@ -43,10 +43,11 @@ __all__ = (
import bpy as _bpy
import os as _os
-from _bpy_path import (extensions_audio,
- extensions_movie,
- extensions_image,
- )
+from _bpy_path import (
+ extensions_audio,
+ extensions_movie,
+ extensions_image,
+ )
def _getattr_bytes(var, attr):
@@ -60,7 +61,7 @@ def abspath(path, start=None, library=None):
:arg start: Relative to this path,
when not set the current filename is used.
- :type start: string
+ :type start: string or bytes
:arg library: The library this path is from. This is only included for
convenience, when the library is not None its path replaces *start*.
:type library: :class:`bpy.types.Library`
@@ -89,9 +90,11 @@ def relpath(path, start=None):
"""
Returns the path relative to the current blend file using the "//" prefix.
+ :arg path: An absolute path.
+ :type path: string or bytes
:arg start: Relative to this path,
when not set the current filename is used.
- :type start: string
+ :type start: string or bytes
"""
if isinstance(path, bytes):
if not path.startswith(b"//"):
@@ -111,11 +114,18 @@ def is_subdir(path, directory):
"""
Returns true if *path* in a subdirectory of *directory*.
Both paths must be absolute.
+
+ :arg path: An absolute path.
+ :type path: string or bytes
"""
from os.path import normpath, normcase
path = normpath(normcase(path))
directory = normpath(normcase(directory))
- return path.startswith(directory)
+ if len(path) > len(directory):
+ if path.startswith(directory):
+ sep = ord(_os.sep) if isinstance(directory, bytes) else _os.sep
+ return (path[len(directory)] == sep)
+ return False
def clean_name(name, replace="_"):
@@ -124,26 +134,50 @@ def clean_name(name, replace="_"):
may cause problems under various circumstances,
such as writing to a file.
All characters besides A-Z/a-z, 0-9 are replaced with "_"
- or the replace argument if defined.
+ or the *replace* argument if defined.
"""
- bad_chars = ("\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e"
- "\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d"
- "\x1e\x1f\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c"
- "\x2e\x2f\x3a\x3b\x3c\x3d\x3e\x3f\x40\x5b\x5c\x5d\x5e\x60\x7b"
- "\x7c\x7d\x7e\x7f\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a"
- "\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99"
- "\x9a\x9b\x9c\x9d\x9e\x9f\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8"
- "\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7"
- "\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0\xc1\xc2\xc3\xc4\xc5\xc6"
- "\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5"
- "\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0\xe1\xe2\xe3\xe4"
- "\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3"
- "\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe")
-
- for ch in bad_chars:
- name = name.replace(ch, replace)
- return name
+ if replace != "_":
+ if len(replace) != 1 or ord(replace) > 255:
+ raise ValueError("Value must be a single ascii character")
+
+ def maketrans_init():
+ trans_cache = clean_name._trans_cache
+ trans = trans_cache.get(replace)
+ if trans is None:
+ bad_chars = (
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+ 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+ 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
+ 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2e, 0x2f, 0x3a,
+ 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40, 0x5b, 0x5c,
+ 0x5d, 0x5e, 0x60, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
+ 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
+ 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
+ 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
+ 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
+ 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
+ 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
+ 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
+ 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
+ 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
+ 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
+ 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
+ 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
+ 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
+ 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
+ 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
+ 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe,
+ )
+ trans = str.maketrans({char: replace for char in bad_chars})
+ trans_cache[replace] = trans
+ return trans
+
+ trans = maketrans_init()
+ return name.translate(trans)
+clean_name._trans_cache = {}
def _clean_utf8(name):
@@ -221,7 +255,8 @@ def resolve_ncase(path):
if _os.path.isdir(dirpath):
try:
files = _os.listdir(dirpath)
- except PermissionError: # We might not have the permission to list dirpath...
+ except PermissionError:
+ # We might not have the permission to list dirpath...
return path, False
else:
return path, False
@@ -248,22 +283,21 @@ def ensure_ext(filepath, ext, case_sensitive=False):
"""
Return the path with the extension added if it is not already set.
- :arg ext: The extension to check for.
+ :arg ext: The extension to check for, can be a compound extension. Should
+ start with a dot, such as '.blend' or '.tar.gz'.
:type ext: string
:arg case_sensitive: Check for matching case when comparing extensions.
:type case_sensitive: bool
"""
- fn_base, fn_ext = _os.path.splitext(filepath)
- if fn_base and fn_ext:
- if ((case_sensitive and ext == fn_ext) or
- (ext.lower() == fn_ext.lower())):
+ if case_sensitive:
+ if filepath.endswith(ext):
return filepath
- else:
- return fn_base + ext
-
else:
- return filepath + ext
+ if filepath[-len(ext):].lower().endswith(ext.lower()):
+ return filepath
+
+ return filepath + ext
def module_names(path, recursive=False):
diff --git a/release/scripts/modules/bpy/utils.py b/release/scripts/modules/bpy/utils/__init__.py
index b3a7a13e331..481db4659af 100644
--- a/release/scripts/modules/bpy/utils.py
+++ b/release/scripts/modules/bpy/utils/__init__.py
@@ -38,6 +38,7 @@ __all__ = (
"unregister_manual_map",
"make_rna_paths",
"manual_map",
+ "previews",
"resource_path",
"script_path_user",
"script_path_pref",
@@ -51,12 +52,12 @@ __all__ = (
)
from _bpy import (
- escape_identifier,
- register_class,
- unregister_class,
- blend_paths,
- resource_path,
- )
+ escape_identifier,
+ register_class,
+ unregister_class,
+ blend_paths,
+ resource_path,
+ )
from _bpy import script_paths as _bpy_script_paths
from _bpy import user_resource as _user_resource
from _bpy import _utils_units as units
@@ -160,7 +161,7 @@ def load_scripts(reload_scripts=False, refresh_scripts=False):
# modification time changes. This `won't` work for packages so...
# its not perfect.
for module_name in [ext.module for ext in _user_preferences.addons]:
- _addon_utils.disable(module_name, default_set=False)
+ _addon_utils.disable(module_name)
def register_module_call(mod):
register = getattr(mod, "register", None)
@@ -185,7 +186,7 @@ def load_scripts(reload_scripts=False, refresh_scripts=False):
traceback.print_exc()
def test_reload(mod):
- import imp
+ import importlib
# reloading this causes internal errors
# because the classes from this module are stored internally
# possibly to refresh internal references too but for now, best not to.
@@ -193,7 +194,7 @@ def load_scripts(reload_scripts=False, refresh_scripts=False):
return mod
try:
- return imp.reload(mod)
+ return importlib.reload(mod)
except:
import traceback
traceback.print_exc()
@@ -244,7 +245,14 @@ def load_scripts(reload_scripts=False, refresh_scripts=False):
test_register(mod)
# deal with addons separately
- _addon_utils.reset_all(reload_scripts)
+ _initialize = getattr(_addon_utils, "_initialize", None)
+ if _initialize is not None:
+ # first time, use fast-path
+ _initialize()
+ del _addon_utils._initialize
+ else:
+ _addon_utils.reset_all(reload_scripts)
+ del _initialize
# run the active integration preset
filepath = preset_find(_user_preferences.inputs.active_keyconfig,
@@ -369,46 +377,31 @@ def preset_paths(subdir):
def smpte_from_seconds(time, fps=None):
"""
- Returns an SMPTE formatted string from the time in seconds: "HH:MM:SS:FF".
+ Returns an SMPTE formatted string from the *time*:
+ ``HH:MM:SS:FF``.
If the *fps* is not given the current scene is used.
- """
- import math
-
- if fps is None:
- fps = _bpy.context.scene.render.fps
-
- hours = minutes = seconds = frames = 0
-
- if time < 0:
- time = - time
- neg = "-"
- else:
- neg = ""
- if time >= 3600.0: # hours
- hours = int(time / 3600.0)
- time = time % 3600.0
- if time >= 60.0: # minutes
- minutes = int(time / 60.0)
- time = time % 60.0
-
- seconds = int(time)
- frames = int(round(math.floor(((time - seconds) * fps))))
+ :arg time: time in seconds.
+ :type time: int, float or ``datetime.timedelta``.
+ :return: the frame string.
+ :rtype: string
+ """
- return "%s%02d:%02d:%02d:%02d" % (neg, hours, minutes, seconds, frames)
+ return smpte_from_frame(time_to_frame(time, fps=fps), fps)
def smpte_from_frame(frame, fps=None, fps_base=None):
"""
- Returns an SMPTE formatted string from the frame: "HH:MM:SS:FF".
+ Returns an SMPTE formatted string from the *frame*:
+ ``HH:MM:SS:FF``.
If *fps* and *fps_base* are not given the current scene is used.
- :arg time: time in seconds.
- :type time: number or timedelta object
- :return: the frame.
- :rtype: float
+ :arg frame: frame number.
+ :type frame: int or float.
+ :return: the frame string.
+ :rtype: string
"""
if fps is None:
@@ -417,7 +410,17 @@ def smpte_from_frame(frame, fps=None, fps_base=None):
if fps_base is None:
fps_base = _bpy.context.scene.render.fps_base
- return smpte_from_seconds((frame * fps_base) / fps, fps)
+ sign = "-" if frame < 0 else ""
+ frame = abs(frame * fps_base)
+
+ return (
+ "%s%02d:%02d:%02d:%02d" % (
+ sign,
+ int(frame / (3600 * fps)), # HH
+ int((frame / (60 * fps)) % 60), # MM
+ int((frame / fps) % 60), # SS
+ int(frame % fps), # FF
+ ))
def time_from_frame(frame, fps=None, fps_base=None):
@@ -427,7 +430,7 @@ def time_from_frame(frame, fps=None, fps_base=None):
If *fps* and *fps_base* are not given the current scene is used.
:arg frame: number.
- :type frame: the frame number
+ :type frame: int or float.
:return: the time in seconds.
:rtype: datetime.timedelta
"""
@@ -451,7 +454,7 @@ def time_to_frame(time, fps=None, fps_base=None):
If *fps* and *fps_base* are not given the current scene is used.
:arg time: time in seconds.
- :type time: number or a datetime.timedelta object
+ :type time: number or a ``datetime.timedelta`` object
:return: the frame.
:rtype: float
"""
@@ -633,10 +636,10 @@ def unregister_module(module, verbose=False):
# we start with the built-in default mapping
def _blender_default_map():
import sys
- import rna_wiki_reference as ref_mod
+ import rna_manual_reference as ref_mod
ret = (ref_mod.url_manual_prefix, ref_mod.url_manual_mapping)
# avoid storing in memory
- del sys.modules["rna_wiki_reference"]
+ del sys.modules["rna_manual_reference"]
return ret
# hooks for doc lookups
diff --git a/release/scripts/modules/bpy/utils/previews.py b/release/scripts/modules/bpy/utils/previews.py
new file mode 100644
index 00000000000..965971139e4
--- /dev/null
+++ b/release/scripts/modules/bpy/utils/previews.py
@@ -0,0 +1,153 @@
+# ##### 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 #####
+
+# <pep8 compliant>
+
+"""
+This module contains utility functions to handle custom previews.
+
+It behaves as a high-level 'cached' previews manager.
+
+This allows scripts to generate their own previews, and use them as icons in UI widgets
+('icon_value' for UILayout functions).
+
+
+Custom Icon Example
+-------------------
+
+.. literalinclude:: ../../../release/scripts/templates_py/ui_previews_custom_icon.py
+"""
+
+__all__ = (
+ "new",
+ "remove",
+ "ImagePreviewCollection",
+ )
+
+import _bpy
+_utils_previews = _bpy._utils_previews
+del _bpy
+
+
+_uuid_open = set()
+
+
+# High-level previews manager.
+# not accessed directly
+class ImagePreviewCollection(dict):
+ """
+ Dictionary-like class of previews.
+
+ This is a subclass of Python's built-in dict type,
+ used to store multiple image previews.
+
+ .. note::
+
+ - instance with :mod:`bpy.utils.previews.new`
+ - keys must be ``str`` type.
+ - values will be :class:`bpy.types.ImagePreview`
+ """
+
+ # Internal notes:
+ # - Blender's internal 'PreviewImage' struct uses 'self._uuid' prefix.
+
+ def __init__(self):
+ super().__init__()
+ self._uuid = hex(id(self))
+ _uuid_open.add(self._uuid)
+
+ def __del__(self):
+ if self._uuid not in _uuid_open:
+ return
+
+ raise ResourceWarning(
+ "<%s id=%s[%d]>: left open, remove with "
+ "'bpy.utils.previews.remove()'" %
+ (self.__class__.__name__, self._uuid, len(self)))
+ self.close()
+
+ def _gen_key(self, name):
+ return ":".join((self._uuid, name))
+
+ def new(self, name):
+ if name in self:
+ raise KeyException("key %r already exists")
+ p = self[name] = _utils_previews.new(
+ self._gen_key(name))
+ return p
+ new.__doc__ = _utils_previews.new.__doc__
+
+ def load(self, name, path, path_type, force_reload=False):
+ if name in self:
+ raise KeyException("key %r already exists")
+ p = self[name] = _utils_previews.load(
+ self._gen_key(name), path, path_type, force_reload)
+ return p
+ load.__doc__ = _utils_previews.load.__doc__
+
+ def clear(self):
+ """Clear all previews."""
+ for name in self.keys():
+ _utils_previews.release(self._gen_key(name))
+ super().clear()
+
+ def close(self):
+ """Close the collection and clear all previews."""
+ self.clear()
+ _uuid_open.remove(self._uuid)
+
+ def __delitem__(self, key):
+ _utils_previews.release(self._gen_key(key))
+ super().__delitem__(key)
+
+ def __repr__(self):
+ return "<%s id=%s[%d], %s>" % (
+ self.__class__.__name__,
+ self._uuid,
+ len(self),
+ super().__repr__())
+
+
+def new():
+ """
+ :return: a new preview collection.
+ :rtype: :class:`ImagePreviewCollection`
+ """
+
+ return ImagePreviewCollection()
+
+
+def remove(pcoll):
+ """
+ Remove the specified previews collection.
+
+ :arg pcoll: Preview collection to close.
+ :type pcoll: :class:`ImagePreviewCollection`
+ """
+ pcoll.close()
+
+
+# don't complain about resources on exit (only unregister)
+import atexit
+
+
+def exit_clear_warning():
+ del ImagePreviewCollection.__del__
+
+atexit.register(exit_clear_warning)
+del atexit, exit_clear_warning
diff --git a/release/scripts/modules/bpy_extras/anim_utils.py b/release/scripts/modules/bpy_extras/anim_utils.py
index d87c207e2d0..021a8bbb530 100644
--- a/release/scripts/modules/bpy_extras/anim_utils.py
+++ b/release/scripts/modules/bpy_extras/anim_utils.py
@@ -25,6 +25,7 @@ __all__ = (
import bpy
+# XXX visual keying is actually always considered as True in this code...
def bake_action(frame_start,
frame_end,
frame_step=1,
@@ -73,7 +74,7 @@ def bake_action(frame_start,
# -------------------------------------------------------------------------
# Helper Functions and vars
- def pose_frame_info(obj, do_visual_keying):
+ def pose_frame_info(obj):
matrix = {}
for name, pbone in obj.pose.bones.items():
if do_visual_keying:
@@ -84,16 +85,29 @@ def bake_action(frame_start,
return matrix
if do_parents_clear:
- def obj_frame_info(obj, do_visual_keying):
- parent = obj.parent
- matrix = obj.matrix_local if do_visual_keying else obj.matrix_local
- if parent:
- return parent.matrix_world * matrix
- else:
- return matrix.copy()
+ if do_visual_keying:
+ def obj_frame_info(obj):
+ return obj.matrix_world.copy()
+ else:
+ def obj_frame_info(obj):
+ parent = obj.parent
+ matrix = obj.matrix_basis
+ if parent:
+ return parent.matrix_world * matrix
+ else:
+ return matrix.copy()
else:
- def obj_frame_info(obj, do_visual_keying):
- return obj.matrix_local.copy() if do_visual_keying else obj.matrix_local.copy()
+ if do_visual_keying:
+ def obj_frame_info(obj):
+ parent = obj.parent
+ matrix = obj.matrix_world
+ if parent:
+ return parent.matrix_world.inverted_safe() * matrix
+ else:
+ return matrix.copy()
+ else:
+ def obj_frame_info(obj):
+ return obj.matrix_basis.copy()
# -------------------------------------------------------------------------
# Setup the Context
@@ -123,9 +137,16 @@ def bake_action(frame_start,
scene.frame_set(f)
scene.update()
if do_pose:
- pose_info.append(pose_frame_info(obj, do_visual_keying))
+ pose_info.append(pose_frame_info(obj))
if do_object:
- obj_info.append(obj_frame_info(obj, do_visual_keying))
+ obj_info.append(obj_frame_info(obj))
+
+ # -------------------------------------------------------------------------
+ # Clean (store initial data)
+ if do_clean and action is not None:
+ clean_orig_data = {fcu: {p.co[1] for p in fcu.keyframe_points} for fcu in action.fcurves}
+ else:
+ clean_orig_data = {}
# -------------------------------------------------------------------------
# Create action
@@ -216,12 +237,19 @@ def bake_action(frame_start,
if do_clean:
for fcu in action.fcurves:
+ fcu_orig_data = clean_orig_data.get(fcu, set())
+
keyframe_points = fcu.keyframe_points
i = 1
- while i < len(fcu.keyframe_points) - 1:
+ while i < len(keyframe_points) - 1:
+ val = keyframe_points[i].co[1]
+
+ if val in fcu_orig_data:
+ i += 1
+ continue
+
val_prev = keyframe_points[i - 1].co[1]
val_next = keyframe_points[i + 1].co[1]
- val = keyframe_points[i].co[1]
if abs(val - val_prev) + abs(val - val_next) < 0.0001:
keyframe_points.remove(keyframe_points[i])
diff --git a/release/scripts/modules/bpy_extras/io_utils.py b/release/scripts/modules/bpy_extras/io_utils.py
index b1877a9d439..65ccc3f8dc3 100644
--- a/release/scripts/modules/bpy_extras/io_utils.py
+++ b/release/scripts/modules/bpy_extras/io_utils.py
@@ -21,6 +21,7 @@
__all__ = (
"ExportHelper",
"ImportHelper",
+ "orientation_helper_factory",
"axis_conversion",
"axis_conversion_ensure",
"create_derived_objects",
@@ -34,7 +35,11 @@ __all__ = (
)
import bpy
-from bpy.props import StringProperty, BoolProperty, EnumProperty
+from bpy.props import (
+ StringProperty,
+ BoolProperty,
+ EnumProperty,
+ )
def _check_axis_conversion(op):
@@ -60,6 +65,12 @@ class ExportHelper:
options={'HIDDEN'},
)
+ # needed for mix-ins
+ order = [
+ "filepath",
+ "check_existing",
+ ]
+
# subclasses can override with decorator
# True == use ext, False == no ext, None == do nothing.
check_extension = True
@@ -108,6 +119,11 @@ class ImportHelper:
subtype='FILE_PATH',
)
+ # needed for mix-ins
+ order = [
+ "filepath",
+ ]
+
def invoke(self, context, event):
context.window_manager.fileselect_add(self)
return {'RUNNING_MODAL'}
@@ -116,6 +132,51 @@ class ImportHelper:
return _check_axis_conversion(self)
+def orientation_helper_factory(name, axis_forward='Y', axis_up='Z'):
+ members = {}
+
+ def _update_axis_forward(self, context):
+ if self.axis_forward[-1] == self.axis_up[-1]:
+ self.axis_up = self.axis_up[0:-1] + 'XYZ'[('XYZ'.index(self.axis_up[-1]) + 1) % 3]
+
+ members['axis_forward'] = EnumProperty(
+ name="Forward",
+ items=(('X', "X Forward", ""),
+ ('Y', "Y Forward", ""),
+ ('Z', "Z Forward", ""),
+ ('-X', "-X Forward", ""),
+ ('-Y', "-Y Forward", ""),
+ ('-Z', "-Z Forward", ""),
+ ),
+ default=axis_forward,
+ update=_update_axis_forward,
+ )
+
+ def _update_axis_up(self, context):
+ if self.axis_up[-1] == self.axis_forward[-1]:
+ self.axis_forward = self.axis_forward[0:-1] + 'XYZ'[('XYZ'.index(self.axis_forward[-1]) + 1) % 3]
+
+ members['axis_up'] = EnumProperty(
+ name="Up",
+ items=(('X', "X Up", ""),
+ ('Y', "Y Up", ""),
+ ('Z', "Z Up", ""),
+ ('-X', "-X Up", ""),
+ ('-Y', "-Y Up", ""),
+ ('-Z', "-Z Up", ""),
+ ),
+ default=axis_up,
+ update=_update_axis_up,
+ )
+
+ members["order"] = [
+ "axis_forward",
+ "axis_up",
+ ]
+
+ return type(name, (object,), members)
+
+
# Axis conversion function, not pretty LUT
# use lookup table to convert between any axis
_axis_convert_matrix = (
@@ -311,7 +372,7 @@ def unpack_list(list_of_tuples):
# same as above except that it adds 0 for triangle faces
def unpack_face_list(list_of_tuples):
- #allocate the entire list
+ # allocate the entire list
flat_ls = [0] * (len(list_of_tuples) * 4)
i = 0
diff --git a/release/scripts/modules/bpy_extras/keyconfig_utils.py b/release/scripts/modules/bpy_extras/keyconfig_utils.py
index c50b320dceb..7e4c9e885e7 100644
--- a/release/scripts/modules/bpy_extras/keyconfig_utils.py
+++ b/release/scripts/modules/bpy_extras/keyconfig_utils.py
@@ -32,7 +32,10 @@ KM_HIERARCHY = [
('View2D', 'EMPTY', 'WINDOW', []), # view 2d navigation (per region)
('View2D Buttons List', 'EMPTY', 'WINDOW', []), # view 2d with buttons navigation
('Header', 'EMPTY', 'WINDOW', []), # header stuff (per region)
- ('Grease Pencil', 'EMPTY', 'WINDOW', []), # grease pencil stuff (per region)
+
+ ('Grease Pencil', 'EMPTY', 'WINDOW', [ # grease pencil stuff (per region)
+ ('Grease Pencil Stroke Edit Mode', 'EMPTY', 'WINDOW', []),
+ ]),
('3D View', 'VIEW_3D', 'WINDOW', [ # view 3d navigation and generic stuff (select, transform)
('Object Mode', 'EMPTY', 'WINDOW', []),
@@ -56,6 +59,7 @@ KM_HIERARCHY = [
('Knife Tool Modal Map', 'EMPTY', 'WINDOW', []),
('Paint Stroke Modal', 'EMPTY', 'WINDOW', []),
+ ('Paint Curve', 'EMPTY', 'WINDOW', []),
('Object Non-modal', 'EMPTY', 'WINDOW', []), # mode change
@@ -241,7 +245,7 @@ def keyconfig_export(wm, kc, filepath):
# the default blender keyconfig, recreating the current setup from a fresh blender
# without needing to export keymaps which haven't been edited.
- class FakeKeyConfig():
+ class FakeKeyConfig:
keymaps = []
edited_kc = FakeKeyConfig()
for km in wm.keyconfigs.user.keymaps:
diff --git a/release/scripts/modules/bpy_extras/object_utils.py b/release/scripts/modules/bpy_extras/object_utils.py
index 01390760c76..c2c306e5145 100644
--- a/release/scripts/modules/bpy_extras/object_utils.py
+++ b/release/scripts/modules/bpy_extras/object_utils.py
@@ -31,7 +31,11 @@ __all__ = (
import bpy
-from bpy.props import BoolProperty, FloatVectorProperty
+from bpy.props import (
+ BoolProperty,
+ BoolVectorProperty,
+ FloatVectorProperty,
+ )
def add_object_align_init(context, operator):
@@ -99,7 +103,7 @@ def add_object_align_init(context, operator):
return location * rotation
-def object_data_add(context, obdata, operator=None, use_active_layer=True):
+def object_data_add(context, obdata, operator=None, use_active_layer=True, name=None):
"""
Add an object using the view context and preference to to initialize the
location, rotation and layer.
@@ -110,6 +114,8 @@ def object_data_add(context, obdata, operator=None, use_active_layer=True):
:type obdata: valid object data type or None.
:arg operator: The operator, checked for location and rotation properties.
:type operator: :class:`bpy.types.Operator`
+ :arg name: Optional name
+ :type name: string
:return: the newly created object in the scene.
:rtype: :class:`bpy.types.ObjectBase`
"""
@@ -119,7 +125,10 @@ def object_data_add(context, obdata, operator=None, use_active_layer=True):
for ob in scene.objects:
ob.select = False
- obj_new = bpy.data.objects.new(obdata.name, obdata)
+ if name is None:
+ name = "Object" if obdata is None else obdata.name
+
+ obj_new = bpy.data.objects.new(name, obdata)
base = scene.objects.link(obj_new)
base.select = True
@@ -128,16 +137,22 @@ def object_data_add(context, obdata, operator=None, use_active_layer=True):
if context.space_data and context.space_data.type == 'VIEW_3D':
v3d = context.space_data
- if use_active_layer:
- if v3d and v3d.local_view:
- base.layers_from_view(context.space_data)
- base.layers[scene.active_layer] = True
- else:
- base.layers = [True if i == scene.active_layer
- else False for i in range(len(scene.layers))]
+ if operator is not None and any(operator.layers):
+ base.layers = operator.layers
else:
- if v3d:
- base.layers_from_view(context.space_data)
+ if use_active_layer:
+ if v3d and v3d.local_view:
+ base.layers_from_view(context.space_data)
+ base.layers[scene.active_layer] = True
+ else:
+ base.layers = [True if i == scene.active_layer
+ else False for i in range(len(scene.layers))]
+ else:
+ if v3d:
+ base.layers_from_view(context.space_data)
+
+ if operator is not None:
+ operator.layers = base.layers
obj_new.matrix_world = add_object_align_init(context, operator)
@@ -150,7 +165,7 @@ def object_data_add(context, obdata, operator=None, use_active_layer=True):
obj_act.mode == 'EDIT' and
obj_act.type == obj_new.type):
- _obdata = bpy.data.meshes.new(obdata.name)
+ _obdata = bpy.data.meshes.new(name)
obj_act = bpy.data.objects.new(_obdata.name, _obdata)
obj_act.matrix_world = obj_new.matrix_world
scene.objects.link(obj_act)
@@ -166,10 +181,11 @@ def object_data_add(context, obdata, operator=None, use_active_layer=True):
obj_act.select = True
scene.update() # apply location
- #scene.objects.active = obj_new
+ # scene.objects.active = obj_new
bpy.ops.object.join() # join into the active.
- bpy.data.meshes.remove(obdata)
+ if obdata:
+ bpy.data.meshes.remove(obdata)
# base is freed, set to active object
base = scene.object_bases.active
@@ -200,6 +216,12 @@ class AddObjectHelper:
name="Rotation",
subtype='EULER',
)
+ layers = BoolVectorProperty(
+ name="Layers",
+ size=20,
+ subtype='LAYER',
+ options={'HIDDEN', 'SKIP_SAVE'},
+ )
@classmethod
def poll(self, context):
@@ -281,7 +303,8 @@ def world_to_camera_view(scene, obj, coord):
Returns the camera space coords for a 3d point.
(also known as: normalized device coordinates - NDC).
- Where (0, 0) is the bottom left and (1, 1) is the top right of the camera frame.
+ Where (0, 0) is the bottom left and (1, 1)
+ is the top right of the camera frame.
values outside 0-1 are also supported.
A negative 'z' value means the point is behind the camera.
@@ -294,7 +317,8 @@ def world_to_camera_view(scene, obj, coord):
:type obj: :class:`bpy.types.Object`
:arg coord: World space location.
:type coord: :class:`mathutils.Vector`
- :return: a vector where X and Y map to the view plane and Z is the depth on the view axis.
+ :return: a vector where X and Y map to the view plane and
+ Z is the depth on the view axis.
:rtype: :class:`mathutils.Vector`
"""
from mathutils import Vector
diff --git a/release/scripts/modules/bpy_extras/view3d_utils.py b/release/scripts/modules/bpy_extras/view3d_utils.py
index b25024fca9b..4aa06262970 100644
--- a/release/scripts/modules/bpy_extras/view3d_utils.py
+++ b/release/scripts/modules/bpy_extras/view3d_utils.py
@@ -63,10 +63,20 @@ def region_2d_to_vector_3d(region, rv3d, coord):
return view_vector
-def region_2d_to_origin_3d(region, rv3d, coord):
+def region_2d_to_origin_3d(region, rv3d, coord, clamp=None):
"""
Return the 3d view origin from the region relative 2d coords.
+ .. note::
+
+ Orthographic views have a less obvious origin,
+ the far clip is used to define the viewport near/far extents.
+ Since far clip can be a very large value,
+ the result may give with numeric precision issues.
+
+ To avoid this problem, you can optionally clamp the far clip to a
+ smaller value based on the data you're operating on.
+
:arg region: region of the 3D viewport, typically bpy.context.region.
:type region: :class:`bpy.types.Region`
:arg rv3d: 3D region data, typically bpy.context.space_data.region_3d.
@@ -74,6 +84,9 @@ def region_2d_to_origin_3d(region, rv3d, coord):
:arg coord: 2d coordinates relative to the region;
(event.mouse_region_x, event.mouse_region_y) for example.
:type coord: 2d vector
+ :arg clamp: Clamp the maximum far-clip value used.
+ (negative value will move the offset away from the view_location)
+ :type clamp: float or None
:return: The origin of the viewpoint in 3d space.
:rtype: :class:`mathutils.Vector`
"""
@@ -89,6 +102,20 @@ def region_2d_to_origin_3d(region, rv3d, coord):
origin_start = ((persinv.col[0].xyz * dx) +
(persinv.col[1].xyz * dy) +
viewinv.translation)
+
+ if clamp != 0.0:
+ if rv3d.view_perspective != 'CAMERA':
+ # this value is scaled to the far clip already
+ origin_offset = persinv.col[2].xyz
+ if clamp is not None:
+ if clamp < 0.0:
+ origin_offset.negate()
+ clamp = -clamp
+ if origin_offset.length > clamp:
+ origin_offset.length = clamp
+
+ origin_start -= origin_offset
+
return origin_start
@@ -135,7 +162,7 @@ def region_2d_to_location_3d(region, rv3d, coord, depth_location):
)[0]
-def location_3d_to_region_2d(region, rv3d, coord):
+def location_3d_to_region_2d(region, rv3d, coord, default=None):
"""
Return the *region* relative 2d location of a 3d position.
@@ -145,8 +172,10 @@ def location_3d_to_region_2d(region, rv3d, coord):
:type rv3d: :class:`bpy.types.RegionView3D`
:arg coord: 3d worldspace location.
:type coord: 3d vector
+ :arg default: Return this value if ``coord``
+ is behind the origin of a perspective view.
:return: 2d location
- :rtype: :class:`mathutils.Vector`
+ :rtype: :class:`mathutils.Vector` or ``default`` argument.
"""
from mathutils import Vector
@@ -159,4 +188,4 @@ def location_3d_to_region_2d(region, rv3d, coord):
height_half + height_half * (prj.y / prj.w),
))
else:
- return None
+ return default
diff --git a/release/scripts/modules/bpy_restrict_state.py b/release/scripts/modules/bpy_restrict_state.py
index 4aa3c5de573..4658fddf0dc 100644
--- a/release/scripts/modules/bpy_restrict_state.py
+++ b/release/scripts/modules/bpy_restrict_state.py
@@ -29,7 +29,7 @@ __all__ = (
import bpy as _bpy
-class _RestrictContext():
+class _RestrictContext:
__slots__ = ()
_real_data = _bpy.data
# safe, the pointer never changes
@@ -44,7 +44,7 @@ class _RestrictContext():
return self._real_pref
-class _RestrictData():
+class _RestrictData:
__slots__ = ()
@@ -52,7 +52,7 @@ _context_restrict = _RestrictContext()
_data_restrict = _RestrictData()
-class RestrictBlend():
+class RestrictBlend:
__slots__ = ("context", "data")
def __enter__(self):
diff --git a/release/scripts/modules/bpy_types.py b/release/scripts/modules/bpy_types.py
index e19766310ec..92dbd2dbd0e 100644
--- a/release/scripts/modules/bpy_types.py
+++ b/release/scripts/modules/bpy_types.py
@@ -144,10 +144,11 @@ class WindowManager(bpy_types.ID):
import bpy
pie = self.piemenu_begin__internal(title, icon, event)
- try:
- draw_func(pie, bpy.context)
- finally:
- self.piemenu_end__internal(pie)
+ if pie:
+ try:
+ draw_func(pie, bpy.context)
+ finally:
+ self.piemenu_end__internal(pie)
class _GenericBone:
@@ -714,7 +715,7 @@ class Menu(StructRNA, _GenericUI, metaclass=RNAMeta):
__slots__ = ()
def path_menu(self, searchpaths, operator,
- props_default={}, filter_ext=None):
+ props_default=None, filter_ext=None):
layout = self.layout
# hard coded to set the operators 'filepath' to the filename.
@@ -744,8 +745,9 @@ class Menu(StructRNA, _GenericUI, metaclass=RNAMeta):
text=bpy.path.display_name(f),
translate=False)
- for attr, value in props_default.items():
- setattr(props, attr, value)
+ if props_default is not None:
+ for attr, value in props_default.items():
+ setattr(props, attr, value)
props.filepath = filepath
if operator == "script.execute_preset":
@@ -753,14 +755,21 @@ class Menu(StructRNA, _GenericUI, metaclass=RNAMeta):
def draw_preset(self, context):
"""
- Define these on the subclass
- - preset_operator
- - preset_subdir
+ Define these on the subclass:
+ - preset_operator (string)
+ - preset_subdir (string)
+
+ Optionally:
+ - preset_extensions (set of strings)
+ - preset_operator_defaults (dict of keyword args)
"""
import bpy
+ ext_valid = getattr(self, "preset_extensions", {".py", ".xml"})
+ props_default = getattr(self, "preset_operator_defaults", None)
self.path_menu(bpy.utils.preset_paths(self.preset_subdir),
self.preset_operator,
- filter_ext=lambda ext: ext.lower() in {".py", ".xml"})
+ props_default=props_default,
+ filter_ext=lambda ext: ext.lower() in ext_valid)
@classmethod
def draw_collapsible(cls, context, layout):
@@ -772,24 +781,6 @@ class Menu(StructRNA, _GenericUI, metaclass=RNAMeta):
layout.menu(cls.__name__, icon='COLLAPSEMENU')
-class Region(StructRNA):
- __slots__ = ()
-
- def callback_add(self, cb, args, draw_mode):
- """
- Append a draw function to this region,
- deprecated, instead use bpy.types.SpaceView3D.draw_handler_add
- """
- for area in self.id_data.areas:
- for region in area.regions:
- if region == self:
- spacetype = type(area.spaces[0])
- return spacetype.draw_handler_add(cb, args, self.type,
- draw_mode)
-
- return None
-
-
class NodeTree(bpy_types.ID, metaclass=RNAMetaPropGroup):
__slots__ = ()
diff --git a/release/scripts/modules/bpyml.py b/release/scripts/modules/bpyml.py
index e942006010b..f2a73501672 100644
--- a/release/scripts/modules/bpyml.py
+++ b/release/scripts/modules/bpyml.py
@@ -57,7 +57,7 @@ class ReturnStore(tuple):
return tuple.__getitem__(self, key)
-class FunctionStore(object):
+class FunctionStore:
def __call__(self, **kwargs):
return ReturnStore((self.__class__.__name__, kwargs, []))
diff --git a/release/scripts/modules/bpyml_ui.py b/release/scripts/modules/bpyml_ui.py
index b4ad4e0b54a..dd5fc38d0eb 100644
--- a/release/scripts/modules/bpyml_ui.py
+++ b/release/scripts/modules/bpyml_ui.py
@@ -84,7 +84,7 @@ def _call_recursive(context, base, py_node):
_call_recursive(context, base_new, py_node_child)
-class BPyML_BaseUI():
+class BPyML_BaseUI:
"""
This is a mix-in class that defines a draw function
which checks for draw_data
diff --git a/release/scripts/modules/console_python.py b/release/scripts/modules/console_python.py
index 66956899076..59e4f2314d8 100644
--- a/release/scripts/modules/console_python.py
+++ b/release/scripts/modules/console_python.py
@@ -226,6 +226,8 @@ execute.hooks = []
def autocomplete(context):
+ _readline_bypass()
+
from console import intellisense
sc = context.space_data
@@ -356,3 +358,14 @@ def banner(context):
sc.prompt = PROMPT
return {'FINISHED'}
+
+
+# workaround for readline crashing, see: T43491
+def _readline_bypass():
+ if "rlcompleter" in sys.modules or "readline" in sys.modules:
+ return
+
+ # prevent 'rlcompleter' from loading the real 'readline' module.
+ sys.modules["readline"] = None
+ import rlcompleter
+ del sys.modules["readline"]
diff --git a/release/scripts/modules/nodeitems_utils.py b/release/scripts/modules/nodeitems_utils.py
index 1fef6c3a019..be6f031217c 100644
--- a/release/scripts/modules/nodeitems_utils.py
+++ b/release/scripts/modules/nodeitems_utils.py
@@ -20,7 +20,7 @@
import bpy
-class NodeCategory():
+class NodeCategory:
@classmethod
def poll(cls, context):
return True
@@ -37,13 +37,17 @@ class NodeCategory():
else:
def items_gen(context):
for item in items:
- if item.poll is None or item.poll(context):
+ if item.poll is None or context is None or item.poll(context):
yield item
self.items = items_gen
-class NodeItem():
- def __init__(self, nodetype, label=None, settings={}, poll=None):
+class NodeItem:
+ def __init__(self, nodetype, label=None, settings=None, poll=None):
+
+ if settings is None:
+ settings = {}
+
self.nodetype = nodetype
self._label = label
self.settings = settings
@@ -73,7 +77,7 @@ class NodeItem():
ops.value = setting[1]
-class NodeItemCustom():
+class NodeItemCustom:
def __init__(self, poll=None, draw=None):
self.poll = poll
self.draw = draw
@@ -127,8 +131,6 @@ def register_node_categories(identifier, cat_list):
if cat.poll(context):
layout.menu("NODE_MT_category_%s" % cat.identifier)
- bpy.types.NODE_MT_add.append(draw_add_menu)
-
# stores: (categories list, menu draw function, submenu types, panel types)
_node_categories[identifier] = (cat_list, draw_add_menu, menu_types, panel_types)
@@ -136,7 +138,7 @@ def register_node_categories(identifier, cat_list):
def node_categories_iter(context):
for cat_type in _node_categories.values():
for cat in cat_type[0]:
- if cat.poll and cat.poll(context):
+ if cat.poll and ((context is None) or cat.poll(context)):
yield cat
@@ -147,7 +149,6 @@ def node_items_iter(context):
def unregister_node_cat_types(cats):
- bpy.types.NODE_MT_add.remove(cats[1])
for mt in cats[2]:
bpy.utils.unregister_class(mt)
for pt in cats[3]:
@@ -166,3 +167,8 @@ def unregister_node_categories(identifier=None):
for cat_types in _node_categories.values():
unregister_node_cat_types(cat_types)
_node_categories.clear()
+
+
+def draw_node_categories_menu(self, context):
+ for cats in _node_categories.values():
+ cats[1](self, context)
diff --git a/release/scripts/modules/progress_report.py b/release/scripts/modules/progress_report.py
new file mode 100644
index 00000000000..578eb967fec
--- /dev/null
+++ b/release/scripts/modules/progress_report.py
@@ -0,0 +1,166 @@
+# ##### BEGIN GPL LICENSE BLOCK #####
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# ##### END GPL LICENSE BLOCK #####
+
+# <pep8 compliant>
+
+import time
+
+
+class ProgressReport:
+ """
+ A basic 'progress report' using either simple prints in console, or WindowManager's 'progress' API.
+
+ This object can be used as a context manager.
+
+ It supports multiple levels of 'substeps' - you shall always enter at least one substep (because level 0
+ has only one single step, representing the whole 'area' of the progress stuff).
+
+ You should give the expected number of substeps each time you enter a new one (you may then step more or less then
+ given number, but this will give incoherent progression).
+
+ Leaving a substep automatically steps by one the parent level.
+
+ with ProgressReport() as progress: # Not giving a WindowManager here will default to console printing.
+ progress.enter_substeps(10)
+ for i in range(10):
+ progress.enter_substeps(100)
+ for j in range(100):
+ progress.step()
+ progress.leave_substeps() # No need to step here, this implicitly does it.
+ progress.leave_substeps("Finished!") # You may pass some message too.
+ """
+ __slots__ = ('wm', 'running', 'steps', 'curr_step', 'start_time')
+
+ def __init__(self, wm=None):
+ self_wm = getattr(self, 'wm', None)
+ if self_wm:
+ self.finalize()
+ self.running = False
+
+ self.wm = wm
+ self.steps = [100000]
+ self.curr_step = [0]
+
+ initialize = __init__
+
+ def __enter__(self):
+ self.start_time = [time.time()]
+ if self.wm:
+ self.wm.progress_begin(0, self.steps[0])
+ self.update()
+ self.running = True
+ return self
+
+ def __exit__(self, exc_type=None, exc_value=None, traceback=None):
+ self.running = False
+ if self.wm:
+ self.wm.progress_end()
+ self.wm = None
+ print("\n")
+ self.steps = [100000]
+ self.curr_step = [0]
+ self.start_time = [time.time()]
+
+ def start(self):
+ self.__enter__()
+
+ def finalize(self):
+ self.__exit__()
+
+ def update(self, msg=""):
+ steps = sum(s * cs for (s, cs) in zip(self.steps, self.curr_step))
+ steps_percent = steps / self.steps[0] * 100.0
+ tm = time.time()
+ loc_tm = tm - self.start_time[-1]
+ tm -= self.start_time[0]
+ if self.wm and self.running:
+ self.wm.progress_update(steps)
+ if msg:
+ prefix = " " * (len(self.steps) - 1)
+ print(prefix + "(%8.4f sec | %8.4f sec) %s\nProgress: %6.2f%%\r" % (tm, loc_tm, msg, steps_percent), end='')
+ else:
+ print("Progress: %6.2f%%\r" % (steps_percent,), end='')
+
+ def enter_substeps(self, nbr, msg=""):
+ if msg:
+ self.update(msg)
+ self.steps.append(self.steps[-1] / nbr)
+ self.curr_step.append(0)
+ self.start_time.append(time.time())
+
+ def step(self, msg="", nbr=1):
+ self.curr_step[-1] += nbr
+ self.update(msg)
+
+ def leave_substeps(self, msg=""):
+ if (msg):
+ self.update(msg)
+ assert(len(self.steps) > 1)
+ del self.steps[-1]
+ del self.curr_step[-1]
+ del self.start_time[-1]
+ self.step()
+
+
+class ProgressReportSubstep:
+ """
+ A sub-step context manager for ProgressReport.
+
+ It can be used to generate other sub-step contexts too, and can act as a (limited) proxy of its real ProgressReport.
+
+ Its exit method always ensure ProgressReport is back on 'level' it was before entering this context.
+ This means it is especially useful to ensure a coherent behavior around code that could return/continue/break
+ from many places, without having to bother to explicitly leave substep in each and every possible place!
+
+ with ProgressReport() as progress: # Not giving a WindowManager here will default to console printing.
+ with ProgressReportSubstep(progress, 10, final_msg="Finished!") as subprogress1:
+ for i in range(10):
+ with ProgressReportSubstep(subprogress1, 100) as subprogress2:
+ for j in range(100):
+ subprogress2.step()
+ """
+ __slots__ = ('progress', 'nbr', 'msg', 'final_msg', 'level')
+
+ def __init__(self, progress, nbr, msg="", final_msg=""):
+ # Allows to generate a subprogress context handler from another one.
+ progress = getattr(progress, 'progress', progress)
+
+ self.progress = progress
+ self.nbr = nbr
+ self.msg = msg
+ self.final_msg = final_msg
+
+ def __enter__(self):
+ self.level = len(self.progress.steps)
+ self.progress.enter_substeps(self.nbr, self.msg)
+ return self
+
+ def __exit__(self, exc_type, exc_value, traceback):
+ assert(len(self.progress.steps) > self.level)
+ while len(self.progress.steps) > self.level + 1:
+ self.progress.leave_substeps()
+ self.progress.leave_substeps(self.final_msg)
+
+ def enter_substeps(self, nbr, msg=""):
+ self.progress.enter_substeps(nbr, msg)
+
+ def step(self, msg="", nbr=1):
+ self.progress.step(msg, nbr)
+
+ def leave_substeps(self, msg=""):
+ self.progress.leave_substeps(msg)
diff --git a/release/scripts/modules/rna_info.py b/release/scripts/modules/rna_info.py
index 3643ad89ea6..dae262e93d7 100644
--- a/release/scripts/modules/rna_info.py
+++ b/release/scripts/modules/rna_info.py
@@ -268,7 +268,8 @@ class InfoPropertyRNA:
self.default_str = "\"%s\"" % self.default
elif self.type == "enum":
if self.is_enum_flag:
- self.default_str = "%r" % self.default # repr or set()
+ # self.default_str = "%r" % self.default # repr or set()
+ self.default_str = "{%s}" % repr(list(sorted(self.default)))[1:-1]
else:
self.default_str = "'%s'" % self.default
elif self.array_length:
@@ -487,6 +488,12 @@ def GetInfoOperatorRNA(bl_rna):
def BuildRNAInfo():
+
+ # needed on successive calls to prevent stale data access
+ for cls in (InfoStructRNA, InfoFunctionRNA, InfoOperatorRNA, InfoPropertyRNA):
+ cls.global_lookup.clear()
+ del cls
+
# Use for faster lookups
# use rna_struct.identifier as the key for each dict
rna_struct_dict = {} # store identifier:rna lookups
@@ -689,7 +696,7 @@ def BuildRNAInfo():
return InfoStructRNA.global_lookup, InfoFunctionRNA.global_lookup, InfoOperatorRNA.global_lookup, InfoPropertyRNA.global_lookup
-if __name__ == "__main__":
+def main():
import rna_info
struct = rna_info.BuildRNAInfo()[0]
data = []
@@ -717,3 +724,7 @@ if __name__ == "__main__":
else:
text = bpy.data.texts.new(name="api.py")
text.from_string(data)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/release/scripts/modules/rna_keymap_ui.py b/release/scripts/modules/rna_keymap_ui.py
index 12d99a00d44..21d1959a037 100644
--- a/release/scripts/modules/rna_keymap_ui.py
+++ b/release/scripts/modules/rna_keymap_ui.py
@@ -236,7 +236,7 @@ def draw_filtered(display_keymaps, filter_type, filter_text, layout):
"MMB": 'MIDDLEMOUSE',
})
_EVENT_TYPE_MAP_EXTRA.update({
- "%d" % i: "NUMPAD_%d" % i for i in range(9)
+ "%d" % i: "NUMPAD_%d" % i for i in range(10)
})
# done with once off init
diff --git a/release/scripts/modules/rna_prop_ui.py b/release/scripts/modules/rna_prop_ui.py
index e278b0d20fe..195b5767189 100644
--- a/release/scripts/modules/rna_prop_ui.py
+++ b/release/scripts/modules/rna_prop_ui.py
@@ -32,6 +32,18 @@ def rna_idprop_ui_get(item, create=True):
return None
+def rna_idprop_ui_del(item):
+ try:
+ del item['_RNA_UI']
+ except KeyError:
+ pass
+
+
+def rna_idprop_ui_prop_update(item, prop):
+ prop_rna = item.path_resolve("[\"%s\"]" % prop.replace("\"", "\\\""), False)
+ prop_rna.update()
+
+
def rna_idprop_ui_prop_get(item, prop, create=True):
rna_ui = rna_idprop_ui_get(item, create)
@@ -46,7 +58,7 @@ def rna_idprop_ui_prop_get(item, prop, create=True):
return rna_ui[prop]
-def rna_idprop_ui_prop_clear(item, prop):
+def rna_idprop_ui_prop_clear(item, prop, remove=True):
rna_ui = rna_idprop_ui_get(item, False)
if rna_ui is None:
@@ -54,8 +66,10 @@ def rna_idprop_ui_prop_clear(item, prop):
try:
del rna_ui[prop]
- except:
+ except KeyError:
pass
+ if remove and len(item.keys()) == 1:
+ rna_idprop_ui_del(item)
def rna_idprop_context_value(context, context_member, property_type):
@@ -168,7 +182,7 @@ def draw(layout, context, context_member, property_type, use_edit=True):
assign_props(props, val_draw, key)
-class PropertyPanel():
+class PropertyPanel:
"""
The subclass should have its own poll function
and the variable '_context_path' MUST be set.
diff --git a/release/scripts/modules/rna_xml.py b/release/scripts/modules/rna_xml.py
index 41f890de51f..ad4809efbe1 100644
--- a/release/scripts/modules/rna_xml.py
+++ b/release/scripts/modules/rna_xml.py
@@ -32,7 +32,7 @@ def build_property_typemap(skip_classes, skip_typemap):
if issubclass(cls, skip_classes):
continue
- ## to support skip-save we cant get all props
+ # # to support skip-save we cant get all props
# properties = cls.bl_rna.properties.keys()
properties = []
for prop_id, prop in cls.bl_rna.properties.items():
@@ -331,7 +331,7 @@ def xml2rna(root_xml,
rna2xml_node(child_xml_real, subsubvalue)
else:
-# print(elems)
+ # print(elems)
if len(elems) == 1:
# sub node named by its type
diff --git a/release/scripts/modules/sys_info.py b/release/scripts/modules/sys_info.py
index 7fd97c4d347..8ca3014a31e 100644
--- a/release/scripts/modules/sys_info.py
+++ b/release/scripts/modules/sys_info.py
@@ -26,29 +26,9 @@ import bgl
import sys
-def cutPoint(text, length):
- """Returns position of the last space found before 'length' chars"""
- l = length
- c = text[l]
- while c != ' ':
- l -= 1
- if l == 0:
- return length # no space found
- c = text[l]
- return l
-
-
-def textWrap(text, length=70):
- lines = []
- while len(text) > 70:
- cpt = cutPoint(text, length)
- line, text = text[:cpt], text[cpt + 1:]
- lines.append(line)
- lines.append(text)
- return lines
-
-
def write_sysinfo(op):
+ import textwrap
+
output_filename = "system-info.txt"
output = bpy.data.texts.get(output_filename)
@@ -57,6 +37,17 @@ def write_sysinfo(op):
else:
output = bpy.data.texts.new(name=output_filename)
+ # pretty repr
+ def prepr(v):
+ r = repr(v)
+ vt = type(v)
+ if vt is bytes:
+ r = r[2:-1]
+ elif vt is list or vt is tuple:
+ r = r[1:-1]
+ return r
+
+
header = "= Blender %s System Information =\n" % bpy.app.version_string
lilies = "%s\n\n" % (len(header) * "=")
firstlilies = "%s\n" % (len(header) * "=")
@@ -67,27 +58,22 @@ def write_sysinfo(op):
# build info
output.write("\nBlender:\n")
output.write(lilies)
- if bpy.app.build_branch and bpy.app.build_branch != "Unknown":
- output.write("version %s, branch %r, commit date %r %r, hash %r, %r\n" %
- (bpy.app.version_string,
- bpy.app.build_branch,
- bpy.app.build_commit_date,
- bpy.app.build_commit_time,
- bpy.app.build_hash,
- bpy.app.build_type))
- else:
- output.write("version %s, revision %r. %r\n" %
- (bpy.app.version_string,
- bpy.app.build_change,
- bpy.app.build_type))
-
- output.write("build date: %r, %r\n" % (bpy.app.build_date, bpy.app.build_time))
- output.write("platform: %r\n" % (bpy.app.build_platform))
- output.write("binary path: %r\n" % (bpy.app.binary_path))
- output.write("build cflags: %r\n" % (bpy.app.build_cflags))
- output.write("build cxxflags: %r\n" % (bpy.app.build_cxxflags))
- output.write("build linkflags: %r\n" % (bpy.app.build_linkflags))
- output.write("build system: %r\n" % (bpy.app.build_system))
+ output.write("version: %s, branch: %s, commit date: %s %s, hash: %s, type: %s\n" %
+ (bpy.app.version_string,
+ prepr(bpy.app.build_branch),
+ prepr(bpy.app.build_commit_date),
+ prepr(bpy.app.build_commit_time),
+ prepr(bpy.app.build_hash),
+ prepr(bpy.app.build_type),
+ ))
+
+ output.write("build date: %s, %s\n" % (prepr(bpy.app.build_date), prepr(bpy.app.build_time)))
+ output.write("platform: %s\n" % prepr(bpy.app.build_platform))
+ output.write("binary path: %s\n" % prepr(bpy.app.binary_path))
+ output.write("build cflags: %s\n" % prepr(bpy.app.build_cflags))
+ output.write("build cxxflags: %s\n" % prepr(bpy.app.build_cxxflags))
+ output.write("build linkflags: %s\n" % prepr(bpy.app.build_linkflags))
+ output.write("build system: %s\n" % prepr(bpy.app.build_system))
# python info
output.write("\nPython:\n")
@@ -113,11 +99,23 @@ def write_sysinfo(op):
ffmpeg = bpy.app.ffmpeg
if ffmpeg.supported:
for lib in ("avcodec", "avdevice", "avformat", "avutil", "swscale"):
- output.write("%r:%r%r\n" % (lib, " " * (10 - len(lib)),
+ output.write("%s:%s%r\n" % (lib, " " * (10 - len(lib)),
getattr(ffmpeg, lib + "_version_string")))
else:
output.write("Blender was built without FFmpeg support\n")
+ if bpy.app.build_options.sdl:
+ output.write("\nSDL\n")
+ output.write(lilies)
+ output.write("Version: %s\n" % bpy.app.sdl.version_string)
+ output.write("Loading method: ")
+ if bpy.app.build_options.sdl_dynload:
+ output.write("dynamically loaded by Blender (WITH_SDL_DYNLOAD=ON)\n")
+ else:
+ output.write("linked (WITH_SDL_DYNLOAD=OFF)\n")
+ if not bpy.app.sdl.available:
+ output.write("WARNING: Blender could not load SDL library\n")
+
output.write("\nOther Libraries:\n")
output.write(lilies)
ocio = bpy.app.ocio
@@ -148,21 +146,24 @@ def write_sysinfo(op):
else:
output.write("Blender was built without Cycles support\n")
+ if not bpy.app.build_options.sdl:
+ output.write("SDL: Blender was built without SDL support\n")
+
if bpy.app.background:
output.write("\nOpenGL: missing, background mode\n")
else:
output.write("\nOpenGL\n")
output.write(lilies)
- version = bgl.glGetString(bgl.GL_RENDERER);
+ version = bgl.glGetString(bgl.GL_RENDERER)
output.write("renderer:\t%r\n" % version)
output.write("vendor:\t\t%r\n" % (bgl.glGetString(bgl.GL_VENDOR)))
output.write("version:\t%r\n" % (bgl.glGetString(bgl.GL_VERSION)))
output.write("extensions:\n")
glext = bgl.glGetString(bgl.GL_EXTENSIONS)
- glext = textWrap(glext, 70)
+ glext = textwrap.wrap(glext, 70)
for l in glext:
- output.write("\t\t%r\n" % (l))
+ output.write("\t%s\n" % l)
output.write("\nImplementation Dependent OpenGL Limits:\n")
output.write(lilies)
@@ -187,6 +188,12 @@ def write_sysinfo(op):
bgl.glGetIntegerv(bgl.GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, limit)
output.write("Maximum Pipeline Image Units:\t%d\n" % limit[0])
+ if bpy.app.build_options.cycles:
+ import cycles
+ output.write("\nCycles\n")
+ output.write(lilies)
+ output.write(cycles.engine.system_info())
+
output.current_line_index = 0
op.report({'INFO'}, "System information generated in 'system-info.txt'")
diff --git a/release/scripts/presets/hair_dynamics/default.py b/release/scripts/presets/hair_dynamics/default.py
new file mode 100644
index 00000000000..830d28a76f0
--- /dev/null
+++ b/release/scripts/presets/hair_dynamics/default.py
@@ -0,0 +1,17 @@
+import bpy
+psys = bpy.context.particle_system
+cloth = bpy.context.particle_system.cloth
+settings = bpy.context.particle_system.cloth.settings
+collision = bpy.context.particle_system.cloth.collision_settings
+
+settings.quality = 5
+settings.mass = 0.30000001192092896
+settings.bending_stiffness = 0.5
+psys.settings.bending_random = 0.0
+settings.bending_damping = 0.5
+settings.air_damping = 1.0
+settings.internal_friction = 0.0
+settings.density_target = 0.0
+settings.density_strength = 0.0
+settings.voxel_cell_size = 0.10000000149011612
+settings.pin_stiffness = 0.0
diff --git a/release/scripts/presets/interface_theme/back_to_black.xml b/release/scripts/presets/interface_theme/back_to_black.xml
index 152e944a7ba..05613e79411 100644
--- a/release/scripts/presets/interface_theme/back_to_black.xml
+++ b/release/scripts/presets/interface_theme/back_to_black.xml
@@ -5,6 +5,7 @@
menu_shadow_width="12"
icon_file=""
icon_alpha="1"
+ widget_emboss="#ffffff05"
axis_x="#dc0000"
axis_y="#00dc00"
axis_z="#0000dc">
@@ -156,7 +157,7 @@
<ThemeWidgetColors outline="#0a0a0a"
inner="#191919e6"
inner_sel="#8c8c8cff"
- item="#2d2d2de6"
+ item="#33406be6"
text="#a0a0a0"
text_sel="#ffffff"
show_shaded="TRUE"
@@ -240,6 +241,9 @@
<ThemeView3D grid="#222222"
wire="#888888"
wire_edit="#000000"
+ gp_vertex="#000000"
+ gp_vertex_select="#ff8500"
+ gp_vertex_size="3"
lamp="#c1d40028"
speaker="#535353"
camera="#000000"
@@ -286,6 +290,7 @@
editmesh_active="#ff020080"
normal="#22dddd"
vertex_normal="#2361dd"
+ split_normal="#dd23dd"
bone_solid="#c8c8c8"
bone_pose="#50c8ff"
bone_pose_active="#8cffff"
@@ -294,6 +299,7 @@
bundle_solid="#c8c8c8"
camera_path="#5a5a5a"
skin_root="#000000"
+ clipping_border_3d="#313131ff"
paint_curve_handle="#7fff7f7f"
paint_curve_pivot="#ff7f7f7f">
<space>
@@ -310,7 +316,7 @@
tab_active="#212947"
tab_inactive="#000000"
tab_back="#060606ff"
- tab_outline="#3a3a3a">
+ tab_outline="#000000">
<gradients>
<ThemeGradientColors show_grad="TRUE"
gradient="#0a0a0a"
@@ -540,7 +546,10 @@
</ThemeDopeSheet>
</dopesheet_editor>
<image_editor>
- <ThemeImageEditor vertex="#0f13bb"
+ <ThemeImageEditor gp_vertex="#000000"
+ gp_vertex_select="#ff8500"
+ gp_vertex_size="3"
+ vertex="#0f13bb"
vertex_select="#ff8500"
vertex_size="3"
vertex_unreferenced="#000000"
@@ -603,7 +612,10 @@
</ThemeImageEditor>
</image_editor>
<sequence_editor>
- <ThemeSequenceEditor grid="#282828"
+ <ThemeSequenceEditor gp_vertex="#000000"
+ gp_vertex_select="#ff8500"
+ gp_vertex_size="3"
+ grid="#282828"
window_sliders="#a0a0a0"
movie_strip="#516987"
movieclip_strip="#20208f"
@@ -714,7 +726,9 @@
</text_editor>
<timeline>
<ThemeTimeline grid="#272727"
- frame_current="#2e5820">
+ frame_current="#2e5820"
+ time_keyframe="#ddd700"
+ time_grease_pencil="#b5e61d">
<space>
<ThemeSpaceGeneric back="#000000"
title="#5d5d5d"
@@ -743,9 +757,13 @@
</ThemeTimeline>
</timeline>
<node_editor>
- <ThemeNodeEditor node_selected="#ffffff"
+ <ThemeNodeEditor gp_vertex="#000000"
+ gp_vertex_select="#ff8500"
+ gp_vertex_size="3"
+ node_selected="#ffffff"
node_active="#ffffff"
wire="#6eafff"
+ wire_inner="#737373"
wire_select="#0019ff"
selected_text="#7f7070"
node_backdrop="#202030bc"
@@ -961,7 +979,10 @@
</ThemeConsole>
</console>
<clip_editor>
- <ThemeClipEditor marker_outline="#0094af"
+ <ThemeClipEditor gp_vertex="#000000"
+ gp_vertex_select="#000000"
+ gp_vertex_size="1"
+ marker_outline="#0094af"
marker="#7f7f00"
active_marker="#ffffff"
selected_marker="#ffff00"
@@ -969,7 +990,6 @@
locked_marker="#7f7f7f"
path_before="#ff0000"
path_after="#0000ff"
- grid="#5e5e5e"
frame_current="#1b501b"
strips="#0c0a0a"
strips_selected="#ff8c00"
diff --git a/release/scripts/presets/interface_theme/blender_24x.xml b/release/scripts/presets/interface_theme/blender_24x.xml
index 9cb3276b103..1ea335c7d73 100644
--- a/release/scripts/presets/interface_theme/blender_24x.xml
+++ b/release/scripts/presets/interface_theme/blender_24x.xml
@@ -5,6 +5,7 @@
menu_shadow_width="12"
icon_file=""
icon_alpha="1"
+ widget_emboss="#ffffff05"
axis_x="#dc0000"
axis_y="#00dc00"
axis_z="#0000dc">
@@ -153,11 +154,11 @@
</ThemeWidgetColors>
</wcol_menu_back>
<wcol_pie_menu>
- <ThemeWidgetColors outline="#0a0a0a"
- inner="#191919e6"
- inner_sel="#8c8c8cff"
- item="#2d2d2de6"
- text="#a0a0a0"
+ <ThemeWidgetColors outline="#262626"
+ inner="#b4b4b42e"
+ inner_sel="#646464b4"
+ item="#b4b4b4ff"
+ text="#000000"
text_sel="#ffffff"
show_shaded="TRUE"
shadetop="10"
@@ -237,31 +238,34 @@
</ThemeUserInterface>
</user_interface>
<view_3d>
- <ThemeView3D grid="#5c5c5c"
+ <ThemeView3D grid="#4c4c4c"
wire="#000000"
wire_edit="#000000"
+ gp_vertex="#000000"
+ gp_vertex_select="#ff8500"
+ gp_vertex_size="3"
lamp="#00000028"
speaker="#000000"
camera="#000000"
view_overlay="#000000"
empty="#000000"
- object_selected="#ff88ff"
- object_active="#ffbbff"
- object_grouped="#104010"
+ object_selected="#dcaedc"
+ object_active="#ff88ff"
+ object_grouped="#083008"
object_grouped_active="#55bb55"
transform="#ffffff"
- vertex="#ff70ff"
- vertex_select="#ffff70"
- vertex_size="2"
+ vertex="#000000"
+ vertex_select="#ff8500"
+ vertex_size="3"
vertex_unreferenced="#000000"
- edge_select="#cece38"
- edge_seam="#e69632"
- edge_sharp="#ff2020"
+ edge_select="#ffa000"
+ edge_seam="#db2512"
+ edge_sharp="#00abc0"
edge_crease="#cc0099"
edge_facesel="#4b4b4b"
freestyle_edge_mark="#7fff7f"
- face="#0032961e"
- face_select="#c864c83c"
+ face="#00000000"
+ face_select="#ff85003c"
face_dot="#ff8a30"
facedot_size="4"
freestyle_face_mark="#7fff7f33"
@@ -286,6 +290,7 @@
editmesh_active="#ffffff80"
normal="#22dddd"
vertex_normal="#2361dd"
+ split_normal="#dd23dd"
bone_solid="#c8c8c8"
bone_pose="#50c8ff"
bone_pose_active="#8cffff"
@@ -293,7 +298,8 @@
outline_width="1"
bundle_solid="#c8c8c8"
camera_path="#000000"
- skin_root="#000000"
+ skin_root="#b44d4d"
+ clipping_border_3d="#313131ff"
paint_curve_handle="#7fff7f7f"
paint_curve_pivot="#ff7f7f7f">
<space>
@@ -314,7 +320,7 @@
<gradients>
<ThemeGradientColors show_grad="FALSE"
gradient="#000000"
- high_gradient="#757575">
+ high_gradient="#7e7e7e">
</ThemeGradientColors>
</gradients>
<panelcolors>
@@ -432,18 +438,18 @@
<nla_editor>
<ThemeNLAEditor grid="#5e5e5e"
view_sliders="#969696"
- active_action="#00000000"
- active_action_unset="#00000000"
+ active_action="#cc701a66"
+ active_action_unset="#9987614d"
strips="#0c0a0a"
strips_selected="#ff8c00"
- transition_strips="#000000"
- transition_strips_selected="#000000"
- meta_strips="#000000"
- meta_strips_selected="#000000"
- sound_strips="#000000"
- sound_strips_selected="#000000"
- tweak="#000000"
- tweak_duplicate="#000000"
+ transition_strips="#1c2630"
+ transition_strips_selected="#2e75db"
+ meta_strips="#332642"
+ meta_strips_selected="#692196"
+ sound_strips="#2b3d3d"
+ sound_strips_selected="#1f7a7a"
+ tweak="#4df31a"
+ tweak_duplicate="#d90000"
keyframe_border="#000000ff"
keyframe_border_selected="#000000ff"
frame_current="#60c040">
@@ -504,7 +510,7 @@
keyframe_jitter_selected="#61c042"
keyframe_border="#000000ff"
keyframe_border_selected="#000000ff"
- summary="#00000000">
+ summary="#cc701a66">
<space>
<ThemeSpaceGeneric back="#a0a0a0"
title="#000000"
@@ -540,7 +546,10 @@
</ThemeDopeSheet>
</dopesheet_editor>
<image_editor>
- <ThemeImageEditor vertex="#000000"
+ <ThemeImageEditor gp_vertex="#000000"
+ gp_vertex_select="#ff8500"
+ gp_vertex_size="3"
+ vertex="#000000"
vertex_select="#ff8500"
vertex_size="3"
vertex_unreferenced="#000000"
@@ -603,7 +612,10 @@
</ThemeImageEditor>
</image_editor>
<sequence_editor>
- <ThemeSequenceEditor grid="#404040"
+ <ThemeSequenceEditor gp_vertex="#000000"
+ gp_vertex_select="#ff8500"
+ gp_vertex_size="3"
+ grid="#404040"
window_sliders="#a0a0a0"
movie_strip="#516987"
movieclip_strip="#20208f"
@@ -714,7 +726,9 @@
</text_editor>
<timeline>
<ThemeTimeline grid="#5b5b5b"
- frame_current="#60c040">
+ frame_current="#60c040"
+ time_keyframe="#ddd700"
+ time_grease_pencil="#b5e61d">
<space>
<ThemeSpaceGeneric back="#999999"
title="#000000"
@@ -743,14 +757,18 @@
</ThemeTimeline>
</timeline>
<node_editor>
- <ThemeNodeEditor node_selected="#ffffff"
+ <ThemeNodeEditor gp_vertex="#000000"
+ gp_vertex_select="#ff8500"
+ gp_vertex_size="3"
+ node_selected="#ffffff"
node_active="#ffffff"
wire="#000000"
+ wire_inner="#737373"
wire_select="#ffffff"
selected_text="#7f7070"
node_backdrop="#9b9b9ba0"
- converter_node="#686a75"
- color_node="#6c696f"
+ converter_node="#c6bfbf"
+ color_node="#457b95"
group_node="#69756e"
group_socket_node="#dfca35"
frame_node="#9a9b9ba0"
@@ -760,12 +778,12 @@
input_node="#646464"
output_node="#646464"
filter_node="#6c696f"
- vector_node="#6c696f"
- texture_node="#6c696f"
- shader_node="#6c696f"
+ vector_node="#6f578c"
+ texture_node="#8395bf"
+ shader_node="#4f9370"
script_node="#6c696f"
pattern_node="#6c696f"
- layout_node="#6c696f">
+ layout_node="#6e6f69">
<space>
<ThemeSpaceGeneric back="#757575"
title="#000000"
@@ -961,7 +979,10 @@
</ThemeConsole>
</console>
<clip_editor>
- <ThemeClipEditor marker_outline="#000000"
+ <ThemeClipEditor gp_vertex="#000000"
+ gp_vertex_select="#000000"
+ gp_vertex_size="1"
+ marker_outline="#000000"
marker="#7f7f00"
active_marker="#ffffff"
selected_marker="#ffff00"
@@ -969,7 +990,6 @@
locked_marker="#7f7f7f"
path_before="#ff0000"
path_after="#0000ff"
- grid="#5e5e5e"
frame_current="#60c040"
strips="#0c0a0a"
strips_selected="#ff8c00"
@@ -983,7 +1003,7 @@
handle_sel_auto_clamped="#000000"
handle_vertex="#000000"
handle_vertex_select="#ffff00"
- handle_vertex_size="4">
+ handle_vertex_size="5">
<space>
<ThemeSpaceGeneric back="#757575"
title="#000000"
diff --git a/release/scripts/presets/interface_theme/elsyiun.xml b/release/scripts/presets/interface_theme/elsyiun.xml
index 2d213d0ed70..5cb7af1ccc2 100644
--- a/release/scripts/presets/interface_theme/elsyiun.xml
+++ b/release/scripts/presets/interface_theme/elsyiun.xml
@@ -5,6 +5,7 @@
menu_shadow_width="12"
icon_file=""
icon_alpha="1"
+ widget_emboss="#ffffff05"
axis_x="#dc0000"
axis_y="#00dc00"
axis_z="#0000dc">
@@ -154,9 +155,9 @@
</wcol_menu_back>
<wcol_pie_menu>
<ThemeWidgetColors outline="#0a0a0a"
- inner="#191919e6"
+ inner="#414141e6"
inner_sel="#8c8c8cff"
- item="#2d2d2de6"
+ item="#b67e3ee6"
text="#a0a0a0"
text_sel="#ffffff"
show_shaded="TRUE"
@@ -240,6 +241,9 @@
<ThemeView3D grid="#585858"
wire="#000000"
wire_edit="#000000"
+ gp_vertex="#000000"
+ gp_vertex_select="#ff8500"
+ gp_vertex_size="3"
lamp="#00000028"
speaker="#000000"
camera="#000000"
@@ -286,6 +290,7 @@
editmesh_active="#ffffff80"
normal="#22dddd"
vertex_normal="#2361dd"
+ split_normal="#dd23dd"
bone_solid="#c8c8c8"
bone_pose="#50c8ff"
bone_pose_active="#8cffff"
@@ -294,6 +299,7 @@
bundle_solid="#c8c8c8"
camera_path="#000000"
skin_root="#000000"
+ clipping_border_3d="#313131ff"
paint_curve_handle="#7fff7f7f"
paint_curve_pivot="#ff7f7f7f">
<space>
@@ -305,9 +311,9 @@
header_text_hi="#ffffff"
button="#3b3b3b57"
button_title="#979797"
- button_text="#979797"
+ button_text="#c5c5c5"
button_text_hi="#ffffff"
- tab_active="#464646"
+ tab_active="#b67e3e"
tab_inactive="#393939"
tab_back="#404040ff"
tab_outline="#323232">
@@ -432,18 +438,18 @@
<nla_editor>
<ThemeNLAEditor grid="#585858"
view_sliders="#969696"
- active_action="#00000000"
- active_action_unset="#00000000"
+ active_action="#cc701a66"
+ active_action_unset="#9987614d"
strips="#0c0a0a"
strips_selected="#ff8c00"
- transition_strips="#000000"
- transition_strips_selected="#000000"
- meta_strips="#000000"
- meta_strips_selected="#000000"
- sound_strips="#000000"
- sound_strips_selected="#000000"
- tweak="#000000"
- tweak_duplicate="#000000"
+ transition_strips="#1c2630"
+ transition_strips_selected="#2e75db"
+ meta_strips="#332642"
+ meta_strips_selected="#692196"
+ sound_strips="#2b3d3d"
+ sound_strips_selected="#1f7a7a"
+ tweak="#4df31a"
+ tweak_duplicate="#d90000"
keyframe_border="#000000ff"
keyframe_border_selected="#000000ff"
frame_current="#60c040">
@@ -504,7 +510,7 @@
keyframe_jitter_selected="#61c042"
keyframe_border="#000000ff"
keyframe_border_selected="#000000ff"
- summary="#00000000">
+ summary="#cc701a66">
<space>
<ThemeSpaceGeneric back="#4b4b4b"
title="#000000"
@@ -540,7 +546,10 @@
</ThemeDopeSheet>
</dopesheet_editor>
<image_editor>
- <ThemeImageEditor vertex="#32adec"
+ <ThemeImageEditor gp_vertex="#000000"
+ gp_vertex_select="#ff8500"
+ gp_vertex_size="3"
+ vertex="#32adec"
vertex_select="#be6925"
vertex_size="3"
vertex_unreferenced="#000000"
@@ -603,7 +612,10 @@
</ThemeImageEditor>
</image_editor>
<sequence_editor>
- <ThemeSequenceEditor grid="#818181"
+ <ThemeSequenceEditor gp_vertex="#000000"
+ gp_vertex_select="#ff8500"
+ gp_vertex_size="3"
+ grid="#818181"
window_sliders="#a0a0a0"
movie_strip="#516987"
movieclip_strip="#20208f"
@@ -714,7 +726,9 @@
</text_editor>
<timeline>
<ThemeTimeline grid="#5b5b5b"
- frame_current="#60c040">
+ frame_current="#60c040"
+ time_keyframe="#ddd700"
+ time_grease_pencil="#b5e61d">
<space>
<ThemeSpaceGeneric back="#4b4b4b"
title="#000000"
@@ -743,9 +757,13 @@
</ThemeTimeline>
</timeline>
<node_editor>
- <ThemeNodeEditor node_selected="#ffffff"
+ <ThemeNodeEditor gp_vertex="#000000"
+ gp_vertex_select="#ff8500"
+ gp_vertex_size="3"
+ node_selected="#ffffff"
node_active="#ffffff"
wire="#000000"
+ wire_inner="#737373"
wire_select="#ffffff"
selected_text="#7f7070"
node_backdrop="#9b9b9ba0"
@@ -961,7 +979,10 @@
</ThemeConsole>
</console>
<clip_editor>
- <ThemeClipEditor marker_outline="#000000"
+ <ThemeClipEditor gp_vertex="#000000"
+ gp_vertex_select="#000000"
+ gp_vertex_size="1"
+ marker_outline="#000000"
marker="#7f7f00"
active_marker="#ffffff"
selected_marker="#ffff00"
@@ -969,7 +990,6 @@
locked_marker="#7f7f7f"
path_before="#ff0000"
path_after="#0000ff"
- grid="#5e5e5e"
frame_current="#60c040"
strips="#0c0a0a"
strips_selected="#ff8c00"
diff --git a/release/scripts/presets/interface_theme/flatty_light.xml b/release/scripts/presets/interface_theme/flatty_light.xml
new file mode 100644
index 00000000000..deb1101302a
--- /dev/null
+++ b/release/scripts/presets/interface_theme/flatty_light.xml
@@ -0,0 +1,1176 @@
+<bpy>
+ <Theme>
+ <user_interface>
+ <ThemeUserInterface menu_shadow_fac="0.3"
+ menu_shadow_width="4"
+ icon_file=""
+ icon_alpha="1"
+ widget_emboss="#00000005"
+ axis_x="#dc0000"
+ axis_y="#00dc00"
+ axis_z="#0000dc">
+ <wcol_regular>
+ <ThemeWidgetColors outline="#9d9d9d"
+ inner="#b3b3b3ff"
+ inner_sel="#5680c2ff"
+ item="#191919ff"
+ text="#000000"
+ text_sel="#ffffff"
+ show_shaded="FALSE"
+ shadetop="0"
+ shadedown="-5">
+ </ThemeWidgetColors>
+ </wcol_regular>
+ <wcol_tool>
+ <ThemeWidgetColors outline="#c7c7c7"
+ inner="#dbdbdbff"
+ inner_sel="#5680c2ff"
+ item="#191919ff"
+ text="#000000"
+ text_sel="#ffffff"
+ show_shaded="FALSE"
+ shadetop="0"
+ shadedown="-5">
+ </ThemeWidgetColors>
+ </wcol_tool>
+ <wcol_radio>
+ <ThemeWidgetColors outline="#4d4d4d"
+ inner="#464646ff"
+ inner_sel="#5680c2ff"
+ item="#ffffffff"
+ text="#ffffff"
+ text_sel="#ffffff"
+ show_shaded="FALSE"
+ shadetop="5"
+ shadedown="-5">
+ </ThemeWidgetColors>
+ </wcol_radio>
+ <wcol_text>
+ <ThemeWidgetColors outline="#666666"
+ inner="#2f2f2fff"
+ inner_sel="#5680c2ff"
+ item="#80b1ffff"
+ text="#dddddd"
+ text_sel="#ffffff"
+ show_shaded="FALSE"
+ shadetop="-8"
+ shadedown="0">
+ </ThemeWidgetColors>
+ </wcol_text>
+ <wcol_option>
+ <ThemeWidgetColors outline="#999999"
+ inner="#434343ff"
+ inner_sel="#5680c2ff"
+ item="#ffffffff"
+ text="#000000"
+ text_sel="#ffffff"
+ show_shaded="FALSE"
+ shadetop="0"
+ shadedown="-15">
+ </ThemeWidgetColors>
+ </wcol_option>
+ <wcol_toggle>
+ <ThemeWidgetColors outline="#808080"
+ inner="#b3b3b3ff"
+ inner_sel="#5680c2ff"
+ item="#191919ff"
+ text="#000000"
+ text_sel="#ffffff"
+ show_shaded="FALSE"
+ shadetop="0"
+ shadedown="0">
+ </ThemeWidgetColors>
+ </wcol_toggle>
+ <wcol_num>
+ <ThemeWidgetColors outline="#b8b8b8"
+ inner="#d3d3d3ff"
+ inner_sel="#5680c2ff"
+ item="#999999ff"
+ text="#1a1a1a"
+ text_sel="#ffffff"
+ show_shaded="FALSE"
+ shadetop="-10"
+ shadedown="0">
+ </ThemeWidgetColors>
+ </wcol_num>
+ <wcol_numslider>
+ <ThemeWidgetColors outline="#999999"
+ inner="#3c3c3cff"
+ inner_sel="#333333ff"
+ item="#5680c2ff"
+ text="#ffffff"
+ text_sel="#ffffff"
+ show_shaded="TRUE"
+ shadetop="-4"
+ shadedown="0">
+ </ThemeWidgetColors>
+ </wcol_numslider>
+ <wcol_box>
+ <ThemeWidgetColors outline="#959595"
+ inner="#cccccccc"
+ inner_sel="#5680c2ff"
+ item="#191919ff"
+ text="#333333"
+ text_sel="#ffffff"
+ show_shaded="FALSE"
+ shadetop="0"
+ shadedown="0">
+ </ThemeWidgetColors>
+ </wcol_box>
+ <wcol_menu>
+ <ThemeWidgetColors outline="#2d2d2d"
+ inner="#434343ff"
+ inner_sel="#596880ff"
+ item="#ffffffff"
+ text="#e6e6e6"
+ text_sel="#cccccc"
+ show_shaded="FALSE"
+ shadetop="10"
+ shadedown="-10">
+ </ThemeWidgetColors>
+ </wcol_menu>
+ <wcol_pulldown>
+ <ThemeWidgetColors outline="#000000"
+ inner="#3f3f3fff"
+ inner_sel="#5680c2ff"
+ item="#ffffffff"
+ text="#000000"
+ text_sel="#ffffff"
+ show_shaded="FALSE"
+ shadetop="25"
+ shadedown="-20">
+ </ThemeWidgetColors>
+ </wcol_pulldown>
+ <wcol_menu_back>
+ <ThemeWidgetColors outline="#1f1f1f"
+ inner="#1f1f1fef"
+ inner_sel="#5680c2ff"
+ item="#646464ff"
+ text="#e6e6e6"
+ text_sel="#ffffff"
+ show_shaded="FALSE"
+ shadetop="25"
+ shadedown="-20">
+ </ThemeWidgetColors>
+ </wcol_menu_back>
+ <wcol_pie_menu>
+ <ThemeWidgetColors outline="#4d4d4d"
+ inner="#1a1a1aff"
+ inner_sel="#5680c2ff"
+ item="#5680c2ff"
+ text="#e6e6e6"
+ text_sel="#ffffff"
+ show_shaded="FALSE"
+ shadetop="10"
+ shadedown="-10">
+ </ThemeWidgetColors>
+ </wcol_pie_menu>
+ <wcol_tooltip>
+ <ThemeWidgetColors outline="#000000"
+ inner="#1f1f1fef"
+ inner_sel="#2d2d2de6"
+ item="#646464ff"
+ text="#ffffff"
+ text_sel="#ffffff"
+ show_shaded="FALSE"
+ shadetop="25"
+ shadedown="-20">
+ </ThemeWidgetColors>
+ </wcol_tooltip>
+ <wcol_menu_item>
+ <ThemeWidgetColors outline="#000000"
+ inner="#00000000"
+ inner_sel="#5680c2ff"
+ item="#acacac80"
+ text="#ffffff"
+ text_sel="#ffffff"
+ show_shaded="FALSE"
+ shadetop="38"
+ shadedown="0">
+ </ThemeWidgetColors>
+ </wcol_menu_item>
+ <wcol_scroll>
+ <ThemeWidgetColors outline="#999999"
+ inner="#50505000"
+ inner_sel="#646464b3"
+ item="#c2c2c299"
+ text="#000000"
+ text_sel="#ffffff"
+ show_shaded="FALSE"
+ shadetop="5"
+ shadedown="-5">
+ </ThemeWidgetColors>
+ </wcol_scroll>
+ <wcol_progress>
+ <ThemeWidgetColors outline="#b3b3b3"
+ inner="#ccccccff"
+ inner_sel="#646464b4"
+ item="#5094ffff"
+ text="#000000"
+ text_sel="#ffffff"
+ show_shaded="FALSE"
+ shadetop="0"
+ shadedown="0">
+ </ThemeWidgetColors>
+ </wcol_progress>
+ <wcol_list_item>
+ <ThemeWidgetColors outline="#e6e6e6"
+ inner="#00000000"
+ inner_sel="#5680c2ff"
+ item="#cccccc80"
+ text="#1a1a1a"
+ text_sel="#ffffff"
+ show_shaded="FALSE"
+ shadetop="0"
+ shadedown="0">
+ </ThemeWidgetColors>
+ </wcol_list_item>
+ <wcol_state>
+ <ThemeWidgetStateColors inner_anim="#73be4c"
+ inner_anim_sel="#5aa633"
+ inner_key="#f0eb64"
+ inner_key_sel="#d7d34b"
+ inner_driven="#b400ff"
+ inner_driven_sel="#9900e6"
+ blend="0.5">
+ </ThemeWidgetStateColors>
+ </wcol_state>
+ </ThemeUserInterface>
+ </user_interface>
+ <view_3d>
+ <ThemeView3D grid="#414141"
+ wire="#000000"
+ wire_edit="#808080"
+ gp_vertex="#000000"
+ gp_vertex_select="#ff8500"
+ gp_vertex_size="3"
+ lamp="#00000028"
+ speaker="#000000"
+ camera="#000000"
+ view_overlay="#808080"
+ empty="#000000"
+ object_selected="#f15800"
+ object_active="#ffaa40"
+ object_grouped="#083008"
+ object_grouped_active="#55bb55"
+ transform="#ffffff"
+ vertex="#000000"
+ vertex_select="#ff8500"
+ vertex_size="3"
+ vertex_unreferenced="#000000"
+ edge_select="#ffa000"
+ edge_seam="#db2512"
+ edge_sharp="#00ffff"
+ edge_crease="#cc0099"
+ edge_facesel="#4b4b4b"
+ freestyle_edge_mark="#7fff7f"
+ face="#00000012"
+ face_select="#ff85004d"
+ face_dot="#ff8500"
+ facedot_size="4"
+ freestyle_face_mark="#7fff7f33"
+ nurb_uline="#909000"
+ nurb_vline="#803060"
+ nurb_sel_uline="#f0ff40"
+ nurb_sel_vline="#f090a0"
+ act_spline="#db2512"
+ handle_free="#000000"
+ handle_auto="#909000"
+ handle_vect="#409030"
+ handle_sel_vect="#40c030"
+ handle_align="#803060"
+ handle_sel_free="#000000"
+ handle_sel_auto="#f0ff40"
+ handle_sel_align="#f090a0"
+ lastsel_point="#ffffff"
+ extra_edge_len="#150806"
+ extra_edge_angle="#4d4d00"
+ extra_face_angle="#0000cc"
+ extra_face_area="#004d00"
+ editmesh_active="#ffffff80"
+ normal="#22dddd"
+ vertex_normal="#2361dd"
+ split_normal="#dd23dd"
+ bone_solid="#c8c8c8"
+ bone_pose="#50c8ff"
+ bone_pose_active="#8cffff"
+ frame_current="#60c040"
+ outline_width="1"
+ bundle_solid="#c8c8c8"
+ camera_path="#000000"
+ skin_root="#b44d4d"
+ clipping_border_3d="#313131ff"
+ paint_curve_handle="#7fff7f7f"
+ paint_curve_pivot="#ff7f7f7f">
+ <space>
+ <ThemeSpaceGradient title="#000000"
+ text="#000000"
+ text_hi="#ffffff"
+ header="#999999"
+ header_text="#000000"
+ header_text_hi="#ffffff"
+ button="#999999e6"
+ button_title="#1a1a1a"
+ button_text="#000000"
+ button_text_hi="#ffffff"
+ tab_active="#6697e6"
+ tab_inactive="#cccccc"
+ tab_back="#999999ff"
+ tab_outline="#999999">
+ <gradients>
+ <ThemeGradientColors show_grad="TRUE"
+ gradient="#1b1b1b"
+ high_gradient="#3a3a3a">
+ </ThemeGradientColors>
+ </gradients>
+ <panelcolors>
+ <ThemePanelColors header="#c2c2c2ea"
+ back="#99999980"
+ show_header="TRUE"
+ show_back="TRUE">
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGradient>
+ </space>
+ </ThemeView3D>
+ </view_3d>
+ <graph_editor>
+ <ThemeGraphEditor grid="#5e5e5e"
+ frame_current="#60c040"
+ window_sliders="#969696"
+ channels_region="#999999"
+ dopesheet_channel="#2e6399"
+ dopesheet_subchannel="#7aa4cc"
+ channel_group="#278c0e"
+ active_channels_group="#4db135"
+ vertex="#000000"
+ vertex_select="#ff8500"
+ vertex_size="6"
+ vertex_unreferenced="#000000"
+ handle_free="#000000"
+ handle_auto="#909000"
+ handle_vect="#409030"
+ handle_sel_vect="#40c030"
+ handle_align="#803060"
+ handle_sel_free="#000000"
+ handle_sel_auto="#f0ff40"
+ handle_sel_align="#f090a0"
+ handle_auto_clamped="#994030"
+ handle_sel_auto_clamped="#f0af90"
+ lastsel_point="#ffffff"
+ handle_vertex="#000000"
+ handle_vertex_select="#ff8500"
+ handle_vertex_size="5">
+ <space>
+ <ThemeSpaceGeneric back="#6b6b6b"
+ title="#000000"
+ text="#000000"
+ text_hi="#ffffff"
+ header="#adadad"
+ header_text="#000000"
+ header_text_hi="#ffffff"
+ button="#999999e6"
+ button_title="#000000"
+ button_text="#000000"
+ button_text_hi="#ffffff"
+ tab_active="#727272"
+ tab_inactive="#535353"
+ tab_back="#404040ff"
+ tab_outline="#3c3c3c">
+ <panelcolors>
+ <ThemePanelColors header="#c2c2c2ea"
+ back="#999999ff"
+ show_header="TRUE"
+ show_back="TRUE">
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ <space_list>
+ <ThemeSpaceListGeneric list="#adadad"
+ list_title="#000000"
+ list_text="#050505"
+ list_text_hi="#ffffff">
+ </ThemeSpaceListGeneric>
+ </space_list>
+ </ThemeGraphEditor>
+ </graph_editor>
+ <file_browser>
+ <ThemeFileBrowser selected_file="#ff8c19"
+ scrollbar="#a0a0a0"
+ scroll_handle="#7f7070"
+ active_file="#828282"
+ active_file_text="#fafafa">
+ <space>
+ <ThemeSpaceGeneric back="#404040"
+ title="#000000"
+ text="#f1f1f1"
+ text_hi="#0f0f0f"
+ header="#b3b3b3"
+ header_text="#000000"
+ header_text_hi="#ffffff"
+ button="#7272727f"
+ button_title="#000000"
+ button_text="#000000"
+ button_text_hi="#ffffff"
+ tab_active="#6697e6"
+ tab_inactive="#535353"
+ tab_back="#404040ff"
+ tab_outline="#3c3c3c">
+ <panelcolors>
+ <ThemePanelColors header="#c2c2c2ea"
+ back="#99999980"
+ show_header="TRUE"
+ show_back="TRUE">
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ <space_list>
+ <ThemeSpaceListGeneric list="#808080"
+ list_title="#000000"
+ list_text="#000000"
+ list_text_hi="#ffffff">
+ </ThemeSpaceListGeneric>
+ </space_list>
+ </ThemeFileBrowser>
+ </file_browser>
+ <nla_editor>
+ <ThemeNLAEditor grid="#5e5e5e"
+ view_sliders="#969696"
+ active_action="#cc701a66"
+ active_action_unset="#9987614d"
+ strips="#0c0a0a"
+ strips_selected="#ff8c00"
+ transition_strips="#1c2630"
+ transition_strips_selected="#2e75db"
+ meta_strips="#332642"
+ meta_strips_selected="#692196"
+ sound_strips="#2b3d3d"
+ sound_strips_selected="#1f7a7a"
+ tweak="#4df31a"
+ tweak_duplicate="#d90000"
+ keyframe_border="#000000ff"
+ keyframe_border_selected="#000000ff"
+ frame_current="#60c040">
+ <space>
+ <ThemeSpaceGeneric back="#6b6b6b"
+ title="#000000"
+ text="#000000"
+ text_hi="#ffffff"
+ header="#adadad"
+ header_text="#000000"
+ header_text_hi="#ffffff"
+ button="#7272727f"
+ button_title="#000000"
+ button_text="#000000"
+ button_text_hi="#ffffff"
+ tab_active="#6697e6"
+ tab_inactive="#535353"
+ tab_back="#404040ff"
+ tab_outline="#3c3c3c">
+ <panelcolors>
+ <ThemePanelColors header="#c2c2c2ea"
+ back="#99999980"
+ show_header="TRUE"
+ show_back="TRUE">
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ <space_list>
+ <ThemeSpaceListGeneric list="#adadad"
+ list_title="#000000"
+ list_text="#000000"
+ list_text_hi="#ffffff">
+ </ThemeSpaceListGeneric>
+ </space_list>
+ </ThemeNLAEditor>
+ </nla_editor>
+ <dopesheet_editor>
+ <ThemeDopeSheet grid="#5e5e5e"
+ frame_current="#60c040"
+ value_sliders="#000000"
+ view_sliders="#969696"
+ dopesheet_channel="#2e6399"
+ dopesheet_subchannel="#7aa4cc"
+ channels="#707070"
+ channels_selected="#60c040"
+ channel_group="#278c0e"
+ active_channels_group="#4eb335"
+ long_key="#1a1515"
+ long_key_selected="#ff8c00"
+ keyframe="#e8e8e8"
+ keyframe_selected="#ffbe33"
+ keyframe_extreme="#e8b3cc"
+ keyframe_extreme_selected="#f28080"
+ keyframe_breakdown="#b3dbe8"
+ keyframe_breakdown_selected="#54bfed"
+ keyframe_jitter="#94e575"
+ keyframe_jitter_selected="#61c042"
+ keyframe_border="#000000ff"
+ keyframe_border_selected="#000000ff"
+ summary="#d3660066">
+ <space>
+ <ThemeSpaceGeneric back="#6b6b6b"
+ title="#000000"
+ text="#000000"
+ text_hi="#ffffff"
+ header="#adadad"
+ header_text="#000000"
+ header_text_hi="#ffffff"
+ button="#7272727f"
+ button_title="#000000"
+ button_text="#000000"
+ button_text_hi="#ffffff"
+ tab_active="#6697e6"
+ tab_inactive="#535353"
+ tab_back="#404040ff"
+ tab_outline="#3c3c3c">
+ <panelcolors>
+ <ThemePanelColors header="#c2c2c2ea"
+ back="#99999980"
+ show_header="TRUE"
+ show_back="TRUE">
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ <space_list>
+ <ThemeSpaceListGeneric list="#adadad"
+ list_title="#000000"
+ list_text="#000000"
+ list_text_hi="#ffffff">
+ </ThemeSpaceListGeneric>
+ </space_list>
+ </ThemeDopeSheet>
+ </dopesheet_editor>
+ <image_editor>
+ <ThemeImageEditor gp_vertex="#000000"
+ gp_vertex_select="#ff8500"
+ gp_vertex_size="3"
+ vertex="#000000"
+ vertex_select="#ff8500"
+ vertex_size="3"
+ vertex_unreferenced="#000000"
+ face="#ffffff0a"
+ face_select="#ff85003c"
+ face_dot="#ff8500"
+ facedot_size="3"
+ freestyle_face_mark="#7fff7f33"
+ editmesh_active="#ffffff80"
+ wire_edit="#c0c0c0"
+ edge_select="#ff8500"
+ scope_back="#727272ff"
+ preview_stitch_face="#7f7f0033"
+ preview_stitch_edge="#ff00ff33"
+ preview_stitch_vert="#0000ff33"
+ preview_stitch_stitchable="#00ff00ff"
+ preview_stitch_unstitchable="#ff0000ff"
+ preview_stitch_active="#e1d2c323"
+ uv_shadow="#707070ff"
+ uv_others="#606060ff"
+ frame_current="#60c040"
+ handle_free="#000000"
+ handle_auto="#909000"
+ handle_align="#803060"
+ handle_sel_free="#000000"
+ handle_sel_auto="#f0ff40"
+ handle_sel_align="#f090a0"
+ handle_auto_clamped="#000000"
+ handle_sel_auto_clamped="#000000"
+ handle_vertex="#000000"
+ handle_vertex_select="#ffff00"
+ handle_vertex_size="5"
+ paint_curve_handle="#7fff7f7f"
+ paint_curve_pivot="#ff7f7f7f">
+ <space>
+ <ThemeSpaceGeneric back="#353535"
+ title="#000000"
+ text="#000000"
+ text_hi="#ffffff"
+ header="#b3b3b3"
+ header_text="#000000"
+ header_text_hi="#ffffff"
+ button="#999999b3"
+ button_title="#000000"
+ button_text="#000000"
+ button_text_hi="#ffffff"
+ tab_active="#6697e6"
+ tab_inactive="#535353"
+ tab_back="#404040ff"
+ tab_outline="#3c3c3c">
+ <panelcolors>
+ <ThemePanelColors header="#c2c2c2ea"
+ back="#99999980"
+ show_header="TRUE"
+ show_back="TRUE">
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ </ThemeImageEditor>
+ </image_editor>
+ <sequence_editor>
+ <ThemeSequenceEditor gp_vertex="#000000"
+ gp_vertex_select="#ff8500"
+ gp_vertex_size="3"
+ grid="#404040"
+ window_sliders="#a0a0a0"
+ movie_strip="#516987"
+ movieclip_strip="#20208f"
+ image_strip="#6d5881"
+ scene_strip="#4e983e"
+ audio_strip="#2e8f8f"
+ effect_strip="#a9547c"
+ transition_strip="#a25f6f"
+ meta_strip="#6d9183"
+ frame_current="#60c040"
+ keyframe="#ff8500"
+ draw_action="#50c8ff"
+ preview_back="#000000">
+ <space>
+ <ThemeSpaceGeneric back="#747474"
+ title="#000000"
+ text="#000000"
+ text_hi="#ffffff"
+ header="#b3b3b3"
+ header_text="#000000"
+ header_text_hi="#ffffff"
+ button="#959595e6"
+ button_title="#000000"
+ button_text="#000000"
+ button_text_hi="#ffffff"
+ tab_active="#6697e6"
+ tab_inactive="#535353"
+ tab_back="#404040ff"
+ tab_outline="#3c3c3c">
+ <panelcolors>
+ <ThemePanelColors header="#c2c2c2ea"
+ back="#99999980"
+ show_header="TRUE"
+ show_back="TRUE">
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ </ThemeSequenceEditor>
+ </sequence_editor>
+ <properties>
+ <ThemeProperties>
+ <space>
+ <ThemeSpaceGeneric back="#999999"
+ title="#181818"
+ text="#000000"
+ text_hi="#ffffff"
+ header="#b3b3b3"
+ header_text="#000000"
+ header_text_hi="#ffffff"
+ button="#7272727f"
+ button_title="#000000"
+ button_text="#000000"
+ button_text_hi="#ffffff"
+ tab_active="#6697e6"
+ tab_inactive="#535353"
+ tab_back="#404040ff"
+ tab_outline="#3c3c3c">
+ <panelcolors>
+ <ThemePanelColors header="#c2c2c2ea"
+ back="#99999980"
+ show_header="TRUE"
+ show_back="TRUE">
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ </ThemeProperties>
+ </properties>
+ <text_editor>
+ <ThemeTextEditor line_numbers_background="#313133"
+ selected_text="#19191a"
+ cursor="#ff0000"
+ syntax_builtin="#ff1961"
+ syntax_symbols="#ff734d"
+ syntax_special="#95d600"
+ syntax_preprocessor="#ad80ff"
+ syntax_reserved="#c4753b"
+ syntax_comment="#939393"
+ syntax_string="#f6e162"
+ syntax_numbers="#50dbff">
+ <space>
+ <ThemeSpaceGeneric back="#313133"
+ title="#000000"
+ text="#e6e6e6"
+ text_hi="#ffffff"
+ header="#b3b3b3"
+ header_text="#000000"
+ header_text_hi="#ffffff"
+ button="#7272727f"
+ button_title="#000000"
+ button_text="#000000"
+ button_text_hi="#ffffff"
+ tab_active="#6697e6"
+ tab_inactive="#535353"
+ tab_back="#404040ff"
+ tab_outline="#3c3c3c">
+ <panelcolors>
+ <ThemePanelColors header="#c2c2c2ea"
+ back="#99999980"
+ show_header="TRUE"
+ show_back="TRUE">
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ </ThemeTextEditor>
+ </text_editor>
+ <timeline>
+ <ThemeTimeline grid="#5b5b5b"
+ frame_current="#60c040"
+ time_keyframe="#ddd700"
+ time_grease_pencil="#b5e61d">
+ <space>
+ <ThemeSpaceGeneric back="#727272"
+ title="#000000"
+ text="#000000"
+ text_hi="#ffffff"
+ header="#a6a6a6"
+ header_text="#0b0b0b"
+ header_text_hi="#ffffff"
+ button="#7272727f"
+ button_title="#000000"
+ button_text="#000000"
+ button_text_hi="#ffffff"
+ tab_active="#6697e6"
+ tab_inactive="#535353"
+ tab_back="#404040ff"
+ tab_outline="#3c3c3c">
+ <panelcolors>
+ <ThemePanelColors header="#c2c2c2ea"
+ back="#99999980"
+ show_header="TRUE"
+ show_back="TRUE">
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ </ThemeTimeline>
+ </timeline>
+ <node_editor>
+ <ThemeNodeEditor gp_vertex="#000000"
+ gp_vertex_select="#ff8500"
+ gp_vertex_size="3"
+ node_selected="#f15800"
+ node_active="#f15800"
+ wire="#a7a7a7"
+ wire_inner="#999999"
+ wire_select="#ffa733"
+ selected_text="#7f7070"
+ node_backdrop="#e6e6e6ff"
+ converter_node="#66c4ff"
+ color_node="#ffcb4d"
+ group_node="#59b36a"
+ group_socket_node="#dfc300"
+ frame_node="#9b9b9ba0"
+ matte_node="#977474"
+ distor_node="#749797"
+ noodle_curving="0"
+ input_node="#ff6675"
+ output_node="#ff6675"
+ filter_node="#6c696f"
+ vector_node="#9999ff"
+ texture_node="#ffc399"
+ shader_node="#a7ff99"
+ script_node="#6c696f"
+ pattern_node="#6c696f"
+ layout_node="#6c696f">
+ <space>
+ <ThemeSpaceGeneric back="#474747"
+ title="#000000"
+ text="#0d0d0d"
+ text_hi="#ffffff"
+ header="#b3b3b3"
+ header_text="#000000"
+ header_text_hi="#ffffff"
+ button="#7272727f"
+ button_title="#000000"
+ button_text="#000000"
+ button_text_hi="#ffffff"
+ tab_active="#6697e6"
+ tab_inactive="#cccccc"
+ tab_back="#999999ff"
+ tab_outline="#999999">
+ <panelcolors>
+ <ThemePanelColors header="#c2c2c2ea"
+ back="#999999ff"
+ show_header="TRUE"
+ show_back="TRUE">
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ <space_list>
+ <ThemeSpaceListGeneric list="#a5a5a5"
+ list_title="#000000"
+ list_text="#000000"
+ list_text_hi="#ffffff">
+ </ThemeSpaceListGeneric>
+ </space_list>
+ </ThemeNodeEditor>
+ </node_editor>
+ <logic_editor>
+ <ThemeLogicEditor>
+ <space>
+ <ThemeSpaceGeneric back="#646464"
+ title="#000000"
+ text="#000000"
+ text_hi="#ffffff"
+ header="#b3b3b3"
+ header_text="#000000"
+ header_text_hi="#ffffff"
+ button="#7272727f"
+ button_title="#000000"
+ button_text="#000000"
+ button_text_hi="#ffffff"
+ tab_active="#6697e6"
+ tab_inactive="#535353"
+ tab_back="#404040ff"
+ tab_outline="#3c3c3c">
+ <panelcolors>
+ <ThemePanelColors header="#c2c2c2ea"
+ back="#99999980"
+ show_header="TRUE"
+ show_back="TRUE">
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ </ThemeLogicEditor>
+ </logic_editor>
+ <outliner>
+ <ThemeOutliner match="#337f33"
+ selected_highlight="#7297d0">
+ <space>
+ <ThemeSpaceGeneric back="#b3b3b3"
+ title="#000000"
+ text="#1a1a1a"
+ text_hi="#ffffff"
+ header="#b3b3b3"
+ header_text="#000000"
+ header_text_hi="#ffffff"
+ button="#7272727f"
+ button_title="#000000"
+ button_text="#000000"
+ button_text_hi="#ffffff"
+ tab_active="#6697e6"
+ tab_inactive="#535353"
+ tab_back="#404040ff"
+ tab_outline="#3c3c3c">
+ <panelcolors>
+ <ThemePanelColors header="#c2c2c2ea"
+ back="#99999980"
+ show_header="TRUE"
+ show_back="TRUE">
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ </ThemeOutliner>
+ </outliner>
+ <info>
+ <ThemeInfo info_selected="#6080ff"
+ info_selected_text="#ffffff"
+ info_error="#990000"
+ info_error_text="#ffffff"
+ info_warning="#b36a00"
+ info_warning_text="#ffffff"
+ info_info="#668000"
+ info_info_text="#ffffff"
+ info_debug="#d3d3d3"
+ info_debug_text="#000000">
+ <space>
+ <ThemeSpaceGeneric back="#727272"
+ title="#000000"
+ text="#000000"
+ text_hi="#ffffff"
+ header="#b3b3b3"
+ header_text="#1a1a1a"
+ header_text_hi="#ffffff"
+ button="#7272727f"
+ button_title="#000000"
+ button_text="#000000"
+ button_text_hi="#ffffff"
+ tab_active="#6697e6"
+ tab_inactive="#535353"
+ tab_back="#404040ff"
+ tab_outline="#3c3c3c">
+ <panelcolors>
+ <ThemePanelColors header="#c2c2c2ea"
+ back="#99999980"
+ show_header="TRUE"
+ show_back="TRUE">
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ </ThemeInfo>
+ </info>
+ <user_preferences>
+ <ThemeUserPreferences>
+ <space>
+ <ThemeSpaceGeneric back="#999999"
+ title="#000000"
+ text="#000000"
+ text_hi="#ffffff"
+ header="#b3b3b3"
+ header_text="#000000"
+ header_text_hi="#ffffff"
+ button="#7272727f"
+ button_title="#000000"
+ button_text="#000000"
+ button_text_hi="#ffffff"
+ tab_active="#6697e6"
+ tab_inactive="#535353"
+ tab_back="#404040ff"
+ tab_outline="#3c3c3c">
+ <panelcolors>
+ <ThemePanelColors header="#c2c2c2ea"
+ back="#99999980"
+ show_header="TRUE"
+ show_back="TRUE">
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ </ThemeUserPreferences>
+ </user_preferences>
+ <console>
+ <ThemeConsole line_output="#6080ff"
+ line_input="#ffffff"
+ line_info="#00aa00"
+ line_error="#dc6060"
+ cursor="#dc6060"
+ select="#ffffff30">
+ <space>
+ <ThemeSpaceGeneric back="#000000"
+ title="#000000"
+ text="#000000"
+ text_hi="#ffffff"
+ header="#727272"
+ header_text="#000000"
+ header_text_hi="#ffffff"
+ button="#7272727f"
+ button_title="#000000"
+ button_text="#000000"
+ button_text_hi="#ffffff"
+ tab_active="#6697e6"
+ tab_inactive="#535353"
+ tab_back="#404040ff"
+ tab_outline="#3c3c3c">
+ <panelcolors>
+ <ThemePanelColors header="#c2c2c2ea"
+ back="#99999980"
+ show_header="TRUE"
+ show_back="TRUE">
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ </ThemeConsole>
+ </console>
+ <clip_editor>
+ <ThemeClipEditor gp_vertex="#000000"
+ gp_vertex_select="#000000"
+ gp_vertex_size="1"
+ marker_outline="#000000"
+ marker="#7f7f00"
+ active_marker="#ffffff"
+ selected_marker="#ffff00"
+ disabled_marker="#7f0000"
+ locked_marker="#7f7f7f"
+ path_before="#ff0000"
+ path_after="#0000ff"
+ frame_current="#60c040"
+ strips="#0c0a0a"
+ strips_selected="#ff8c00"
+ handle_free="#000000"
+ handle_auto="#909000"
+ handle_align="#803060"
+ handle_sel_free="#000000"
+ handle_sel_auto="#f0ff40"
+ handle_sel_align="#f090a0"
+ handle_auto_clamped="#000000"
+ handle_sel_auto_clamped="#000000"
+ handle_vertex="#000000"
+ handle_vertex_select="#ffff00"
+ handle_vertex_size="5">
+ <space>
+ <ThemeSpaceGeneric back="#393939"
+ title="#000000"
+ text="#000000"
+ text_hi="#ffffff"
+ header="#727272"
+ header_text="#000000"
+ header_text_hi="#ffffff"
+ button="#7272727f"
+ button_title="#000000"
+ button_text="#000000"
+ button_text_hi="#ffffff"
+ tab_active="#6697e6"
+ tab_inactive="#535353"
+ tab_back="#404040ff"
+ tab_outline="#3c3c3c">
+ <panelcolors>
+ <ThemePanelColors header="#c2c2c2ea"
+ back="#99999980"
+ show_header="TRUE"
+ show_back="TRUE">
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ <space_list>
+ <ThemeSpaceListGeneric list="#666666"
+ list_title="#000000"
+ list_text="#000000"
+ list_text_hi="#ffffff">
+ </ThemeSpaceListGeneric>
+ </space_list>
+ </ThemeClipEditor>
+ </clip_editor>
+ <bone_color_sets>
+ <ThemeBoneColorSet normal="#9a0000"
+ select="#bd1111"
+ active="#f70a0a"
+ show_colored_constraints="FALSE">
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet normal="#f74018"
+ select="#f66913"
+ active="#fa9900"
+ show_colored_constraints="FALSE">
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet normal="#1e9109"
+ select="#59b70b"
+ active="#83ef1d"
+ show_colored_constraints="FALSE">
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet normal="#0a3694"
+ select="#3667df"
+ active="#5ec1ef"
+ show_colored_constraints="FALSE">
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet normal="#a9294e"
+ select="#c1416a"
+ active="#f05d91"
+ show_colored_constraints="FALSE">
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet normal="#430c78"
+ select="#543aa3"
+ active="#8764d5"
+ show_colored_constraints="FALSE">
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet normal="#24785a"
+ select="#3c9579"
+ active="#6fb6ab"
+ show_colored_constraints="FALSE">
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet normal="#4b707c"
+ select="#6a8691"
+ active="#9bc2cd"
+ show_colored_constraints="FALSE">
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet normal="#f4c90c"
+ select="#eec236"
+ active="#f3ff00"
+ show_colored_constraints="FALSE">
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet normal="#1e2024"
+ select="#484c56"
+ active="#ffffff"
+ show_colored_constraints="FALSE">
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet normal="#6f2f6a"
+ select="#9845be"
+ active="#d330d6"
+ show_colored_constraints="FALSE">
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet normal="#6c8e22"
+ select="#7fb022"
+ active="#bbef5b"
+ show_colored_constraints="FALSE">
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet normal="#8d8d8d"
+ select="#b0b0b0"
+ active="#dedede"
+ show_colored_constraints="FALSE">
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet normal="#834326"
+ select="#8b5811"
+ active="#bd6a11"
+ show_colored_constraints="FALSE">
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet normal="#08310e"
+ select="#1c430b"
+ active="#34622b"
+ show_colored_constraints="FALSE">
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet normal="#000000"
+ select="#000000"
+ active="#000000"
+ show_colored_constraints="FALSE">
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet normal="#000000"
+ select="#000000"
+ active="#000000"
+ show_colored_constraints="FALSE">
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet normal="#000000"
+ select="#000000"
+ active="#000000"
+ show_colored_constraints="FALSE">
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet normal="#000000"
+ select="#000000"
+ active="#000000"
+ show_colored_constraints="FALSE">
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet normal="#000000"
+ select="#000000"
+ active="#000000"
+ show_colored_constraints="FALSE">
+ </ThemeBoneColorSet>
+ </bone_color_sets>
+ </Theme>
+ <ThemeStyle>
+ <panel_title>
+ <ThemeFontStyle points="12"
+ font_kerning_style="FITTED"
+ shadow="1"
+ shadow_offset_x="0"
+ shadow_offset_y="-1"
+ shadow_alpha="0.15"
+ shadow_value="1">
+ </ThemeFontStyle>
+ </panel_title>
+ <widget_label>
+ <ThemeFontStyle points="11"
+ font_kerning_style="FITTED"
+ shadow="3"
+ shadow_offset_x="0"
+ shadow_offset_y="-1"
+ shadow_alpha="0.15"
+ shadow_value="1">
+ </ThemeFontStyle>
+ </widget_label>
+ <widget>
+ <ThemeFontStyle points="11"
+ font_kerning_style="FITTED"
+ shadow="0"
+ shadow_offset_x="0"
+ shadow_offset_y="0"
+ shadow_alpha="0.25"
+ shadow_value="0">
+ </ThemeFontStyle>
+ </widget>
+ </ThemeStyle>
+</bpy>
diff --git a/release/scripts/presets/interface_theme/graph.xml b/release/scripts/presets/interface_theme/graph.xml
new file mode 100644
index 00000000000..063524a9187
--- /dev/null
+++ b/release/scripts/presets/interface_theme/graph.xml
@@ -0,0 +1,1176 @@
+<bpy>
+ <Theme>
+ <user_interface>
+ <ThemeUserInterface menu_shadow_fac="0.5"
+ menu_shadow_width="12"
+ icon_file=""
+ icon_alpha="1"
+ widget_emboss="#ffffff05"
+ axis_x="#dc0000"
+ axis_y="#00dc00"
+ axis_z="#0000dc">
+ <wcol_regular>
+ <ThemeWidgetColors outline="#3b3b3b"
+ inner="#5e5e5eff"
+ inner_sel="#607f9eff"
+ item="#ffffffff"
+ text="#b8b8b8"
+ text_sel="#ffffff"
+ show_shaded="FALSE"
+ shadetop="0"
+ shadedown="0">
+ </ThemeWidgetColors>
+ </wcol_regular>
+ <wcol_tool>
+ <ThemeWidgetColors outline="#3b3b3b"
+ inner="#444444ff"
+ inner_sel="#607f9eff"
+ item="#ffffffff"
+ text="#b8b8b8"
+ text_sel="#ffffff"
+ show_shaded="FALSE"
+ shadetop="5"
+ shadedown="0">
+ </ThemeWidgetColors>
+ </wcol_tool>
+ <wcol_radio>
+ <ThemeWidgetColors outline="#3b3b3b"
+ inner="#444444ff"
+ inner_sel="#607f9eff"
+ item="#ffffffff"
+ text="#b8b8b8"
+ text_sel="#ffffff"
+ show_shaded="FALSE"
+ shadetop="5"
+ shadedown="0">
+ </ThemeWidgetColors>
+ </wcol_radio>
+ <wcol_text>
+ <ThemeWidgetColors outline="#3b3b3b"
+ inner="#5e5e5eff"
+ inner_sel="#999999ff"
+ item="#414141ff"
+ text="#b8b8b8"
+ text_sel="#ffffff"
+ show_shaded="FALSE"
+ shadetop="5"
+ shadedown="0">
+ </ThemeWidgetColors>
+ </wcol_text>
+ <wcol_option>
+ <ThemeWidgetColors outline="#3b3b3b"
+ inner="#5e5e5eff"
+ inner_sel="#607f9eff"
+ item="#ffffffff"
+ text="#b8b8b8"
+ text_sel="#ffffff"
+ show_shaded="FALSE"
+ shadetop="5"
+ shadedown="0">
+ </ThemeWidgetColors>
+ </wcol_option>
+ <wcol_toggle>
+ <ThemeWidgetColors outline="#3b3b3b"
+ inner="#5e5e5eff"
+ inner_sel="#607f9eff"
+ item="#ffffffff"
+ text="#b8b8b8"
+ text_sel="#ffffff"
+ show_shaded="TRUE"
+ shadetop="5"
+ shadedown="0">
+ </ThemeWidgetColors>
+ </wcol_toggle>
+ <wcol_num>
+ <ThemeWidgetColors outline="#3b3b3b"
+ inner="#444444ff"
+ inner_sel="#999999ff"
+ item="#6d6d6dff"
+ text="#b8b8b8"
+ text_sel="#ffffff"
+ show_shaded="FALSE"
+ shadetop="5"
+ shadedown="0">
+ </ThemeWidgetColors>
+ </wcol_num>
+ <wcol_numslider>
+ <ThemeWidgetColors outline="#3b3b3b"
+ inner="#5e5e5eff"
+ inner_sel="#999999ff"
+ item="#414141ff"
+ text="#b8b8b8"
+ text_sel="#ffffff"
+ show_shaded="FALSE"
+ shadetop="-10"
+ shadedown="0">
+ </ThemeWidgetColors>
+ </wcol_numslider>
+ <wcol_box>
+ <ThemeWidgetColors outline="#3b3b3b"
+ inner="#505050ff"
+ inner_sel="#4e4e4eff"
+ item="#ffffffff"
+ text="#b8b8b8"
+ text_sel="#ffffff"
+ show_shaded="FALSE"
+ shadetop="0"
+ shadedown="-7">
+ </ThemeWidgetColors>
+ </wcol_box>
+ <wcol_menu>
+ <ThemeWidgetColors outline="#444444"
+ inner="#444444ff"
+ inner_sel="#464646ff"
+ item="#7a7a7aff"
+ text="#b8b8b8"
+ text_sel="#ffffff"
+ show_shaded="FALSE"
+ shadetop="5"
+ shadedown="0">
+ </ThemeWidgetColors>
+ </wcol_menu>
+ <wcol_pulldown>
+ <ThemeWidgetColors outline="#3b3b3b"
+ inner="#3f3f3fff"
+ inner_sel="#607f9eff"
+ item="#ffffffff"
+ text="#b8b8b8"
+ text_sel="#ffffff"
+ show_shaded="FALSE"
+ shadetop="25"
+ shadedown="0">
+ </ThemeWidgetColors>
+ </wcol_pulldown>
+ <wcol_menu_back>
+ <ThemeWidgetColors outline="#3b3b3b"
+ inner="#3b3b3bff"
+ inner_sel="#2d2d2de6"
+ item="#646464ff"
+ text="#b8b8b8"
+ text_sel="#ffffff"
+ show_shaded="FALSE"
+ shadetop="25"
+ shadedown="-20">
+ </ThemeWidgetColors>
+ </wcol_menu_back>
+ <wcol_pie_menu>
+ <ThemeWidgetColors outline="#2a2a2a"
+ inner="#2a2a2aff"
+ inner_sel="#8c8c8cff"
+ item="#607f9ee6"
+ text="#b8b8b8"
+ text_sel="#ffffff"
+ show_shaded="FALSE"
+ shadetop="10"
+ shadedown="-10">
+ </ThemeWidgetColors>
+ </wcol_pie_menu>
+ <wcol_tooltip>
+ <ThemeWidgetColors outline="#202020"
+ inner="#202020ff"
+ inner_sel="#202020ff"
+ item="#646464ff"
+ text="#ffffff"
+ text_sel="#ffffff"
+ show_shaded="FALSE"
+ shadetop="25"
+ shadedown="-20">
+ </ThemeWidgetColors>
+ </wcol_tooltip>
+ <wcol_menu_item>
+ <ThemeWidgetColors outline="#3b3b3b"
+ inner="#3f3f3f00"
+ inner_sel="#607f9eff"
+ item="#ffffffff"
+ text="#b8b8b8"
+ text_sel="#ffffff"
+ show_shaded="FALSE"
+ shadetop="0"
+ shadedown="20">
+ </ThemeWidgetColors>
+ </wcol_menu_item>
+ <wcol_scroll>
+ <ThemeWidgetColors outline="#3b3b3b"
+ inner="#444444ff"
+ inner_sel="#607f9eff"
+ item="#5e5e5eff"
+ text="#b8b8b8"
+ text_sel="#ffffff"
+ show_shaded="FALSE"
+ shadetop="0"
+ shadedown="0">
+ </ThemeWidgetColors>
+ </wcol_scroll>
+ <wcol_progress>
+ <ThemeWidgetColors outline="#3b3b3b"
+ inner="#607f9eff"
+ inner_sel="#646464b4"
+ item="#444444ff"
+ text="#b8b8b8"
+ text_sel="#ffffff"
+ show_shaded="FALSE"
+ shadetop="0"
+ shadedown="0">
+ </ThemeWidgetColors>
+ </wcol_progress>
+ <wcol_list_item>
+ <ThemeWidgetColors outline="#3b3b3b"
+ inner="#3f3f3f00"
+ inner_sel="#607f9eff"
+ item="#ffffffff"
+ text="#b8b8b8"
+ text_sel="#ffffff"
+ show_shaded="TRUE"
+ shadetop="0"
+ shadedown="-10">
+ </ThemeWidgetColors>
+ </wcol_list_item>
+ <wcol_state>
+ <ThemeWidgetStateColors inner_anim="#607f9e"
+ inner_anim_sel="#607f9e"
+ inner_key="#4291dc"
+ inner_key_sel="#4291dc"
+ inner_driven="#b400ff"
+ inner_driven_sel="#9900e6"
+ blend="0.6">
+ </ThemeWidgetStateColors>
+ </wcol_state>
+ </ThemeUserInterface>
+ </user_interface>
+ <view_3d>
+ <ThemeView3D grid="#585858"
+ wire="#000000"
+ wire_edit="#161616"
+ gp_vertex="#000000"
+ gp_vertex_select="#ff8500"
+ gp_vertex_size="3"
+ lamp="#00000028"
+ speaker="#000000"
+ camera="#8d8c8d"
+ view_overlay="#000000"
+ empty="#000000"
+ object_selected="#00b5ff"
+ object_active="#fbf1ff"
+ object_grouped="#083008"
+ object_grouped_active="#55bb55"
+ transform="#ffffff"
+ vertex="#000000"
+ vertex_select="#0067cb"
+ vertex_size="3"
+ vertex_unreferenced="#000000"
+ edge_select="#0067cb"
+ edge_seam="#00ace4"
+ edge_sharp="#9c00ff"
+ edge_crease="#f1f4ff"
+ edge_facesel="#4b4b4b"
+ freestyle_edge_mark="#7fff7f"
+ face="#b6b4af49"
+ face_select="#005fa43e"
+ face_dot="#00beb0"
+ facedot_size="3"
+ freestyle_face_mark="#7fff7f33"
+ nurb_uline="#89908a"
+ nurb_vline="#fff8f4"
+ nurb_sel_uline="#2400ff"
+ nurb_sel_vline="#f0deeb"
+ act_spline="#00c6db"
+ handle_free="#000000"
+ handle_auto="#1c00ff"
+ handle_vect="#409030"
+ handle_sel_vect="#40c030"
+ handle_align="#7b807e"
+ handle_sel_free="#000000"
+ handle_sel_auto="#9aa3a1"
+ handle_sel_align="#f0e6e9"
+ lastsel_point="#ffffff"
+ extra_edge_len="#fff3fa"
+ extra_edge_angle="#202000"
+ extra_face_angle="#000080"
+ extra_face_area="#002000"
+ editmesh_active="#00f6ff5e"
+ normal="#22dddd"
+ vertex_normal="#2361dd"
+ split_normal="#dd23dd"
+ bone_solid="#ffffff"
+ bone_pose="#00b5ff"
+ bone_pose_active="#fff3fa"
+ frame_current="#60c040"
+ outline_width="2"
+ bundle_solid="#c8c8c8"
+ camera_path="#000000"
+ skin_root="#000000"
+ clipping_border_3d="#313131ff"
+ paint_curve_handle="#7fff7f7f"
+ paint_curve_pivot="#ff7f7f7f">
+ <space>
+ <ThemeSpaceGradient title="#000000"
+ text="#e4e4e4"
+ text_hi="#b9b9b9"
+ header="#3b3b3b"
+ header_text="#bababa"
+ header_text_hi="#ffffff"
+ button="#3b3b3b45"
+ button_title="#c7c7c7"
+ button_text="#b4b4b4"
+ button_text_hi="#9e9e9e"
+ tab_active="#3b3b3b"
+ tab_inactive="#222222"
+ tab_back="#222222ff"
+ tab_outline="#222222">
+ <gradients>
+ <ThemeGradientColors show_grad="TRUE"
+ gradient="#414141"
+ high_gradient="#545d69">
+ </ThemeGradientColors>
+ </gradients>
+ <panelcolors>
+ <ThemePanelColors header="#00000019"
+ back="#72727280"
+ show_header="FALSE"
+ show_back="FALSE">
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGradient>
+ </space>
+ </ThemeView3D>
+ </view_3d>
+ <graph_editor>
+ <ThemeGraphEditor grid="#6d6d6d"
+ frame_current="#4291dc"
+ window_sliders="#969696"
+ channels_region="#707070"
+ dopesheet_channel="#607f9e"
+ dopesheet_subchannel="#42566d"
+ channel_group="#42566d"
+ active_channels_group="#326799"
+ vertex="#333333"
+ vertex_select="#fdf4ff"
+ vertex_size="6"
+ vertex_unreferenced="#000000"
+ handle_free="#000000"
+ handle_auto="#8d8e90"
+ handle_vect="#409030"
+ handle_sel_vect="#40c030"
+ handle_align="#b6b5b6"
+ handle_sel_free="#000000"
+ handle_sel_auto="#fdfffc"
+ handle_sel_align="#148bce"
+ handle_auto_clamped="#7e7e7e"
+ handle_sel_auto_clamped="#148bce"
+ lastsel_point="#ffffff"
+ handle_vertex="#242324"
+ handle_vertex_select="#ffeeee"
+ handle_vertex_size="5">
+ <space>
+ <ThemeSpaceGeneric back="#5d5d5d"
+ title="#ffffff"
+ text="#ffffff"
+ text_hi="#fcfcfc"
+ header="#3b3b3b"
+ header_text="#ffffff"
+ header_text_hi="#b7b7b7"
+ button="#3b3b3bff"
+ button_title="#c7c7c7"
+ button_text="#b4b4b4"
+ button_text_hi="#ffffff"
+ tab_active="#727272"
+ tab_inactive="#535353"
+ tab_back="#404040ff"
+ tab_outline="#3c3c3c">
+ <panelcolors>
+ <ThemePanelColors header="#00000019"
+ back="#72727280"
+ show_header="FALSE"
+ show_back="FALSE">
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ <space_list>
+ <ThemeSpaceListGeneric list="#3b3b3b"
+ list_title="#8b8b8b"
+ list_text="#979797"
+ list_text_hi="#ffffff">
+ </ThemeSpaceListGeneric>
+ </space_list>
+ </ThemeGraphEditor>
+ </graph_editor>
+ <file_browser>
+ <ThemeFileBrowser selected_file="#607f9e"
+ scrollbar="#a0a0a0"
+ scroll_handle="#7f7070"
+ active_file="#ffffff"
+ active_file_text="#ffffff">
+ <space>
+ <ThemeSpaceGeneric back="#4b4b4b"
+ title="#e4e4e4"
+ text="#cacaca"
+ text_hi="#0f0f0f"
+ header="#3b3b3b"
+ header_text="#8b8b8b"
+ header_text_hi="#ffffff"
+ button="#303030ff"
+ button_title="#c7c7c7"
+ button_text="#000000"
+ button_text_hi="#ffffff"
+ tab_active="#727272"
+ tab_inactive="#535353"
+ tab_back="#404040ff"
+ tab_outline="#3c3c3c">
+ <panelcolors>
+ <ThemePanelColors header="#00000019"
+ back="#72727280"
+ show_header="FALSE"
+ show_back="FALSE">
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ <space_list>
+ <ThemeSpaceListGeneric list="#3b3b3b"
+ list_title="#8b8b8b"
+ list_text="#8b8b8b"
+ list_text_hi="#ffffff">
+ </ThemeSpaceListGeneric>
+ </space_list>
+ </ThemeFileBrowser>
+ </file_browser>
+ <nla_editor>
+ <ThemeNLAEditor grid="#6e6e6e"
+ view_sliders="#969696"
+ active_action="#cc701a66"
+ active_action_unset="#9987614d"
+ strips="#0c0a0a"
+ strips_selected="#ff8c00"
+ transition_strips="#1c2630"
+ transition_strips_selected="#2e75db"
+ meta_strips="#332642"
+ meta_strips_selected="#692196"
+ sound_strips="#2b3d3d"
+ sound_strips_selected="#1f7a7a"
+ tweak="#4df31a"
+ tweak_duplicate="#d90000"
+ keyframe_border="#000000ff"
+ keyframe_border_selected="#000000ff"
+ frame_current="#4291dc">
+ <space>
+ <ThemeSpaceGeneric back="#5d5d5d"
+ title="#ffffff"
+ text="#ffffff"
+ text_hi="#ffffff"
+ header="#3b3b3b"
+ header_text="#ffffff"
+ header_text_hi="#b7b7b7"
+ button="#3b3b3bff"
+ button_title="#c7c7c7"
+ button_text="#b4b4b4"
+ button_text_hi="#ffffff"
+ tab_active="#727272"
+ tab_inactive="#535353"
+ tab_back="#404040ff"
+ tab_outline="#3c3c3c">
+ <panelcolors>
+ <ThemePanelColors header="#00000019"
+ back="#72727280"
+ show_header="FALSE"
+ show_back="FALSE">
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ <space_list>
+ <ThemeSpaceListGeneric list="#3b3b3b"
+ list_title="#000000"
+ list_text="#000000"
+ list_text_hi="#ffffff">
+ </ThemeSpaceListGeneric>
+ </space_list>
+ </ThemeNLAEditor>
+ </nla_editor>
+ <dopesheet_editor>
+ <ThemeDopeSheet grid="#6d6d6d"
+ frame_current="#4291dc"
+ value_sliders="#000000"
+ view_sliders="#929292"
+ dopesheet_channel="#607f9e"
+ dopesheet_subchannel="#42566d"
+ channels="#707070"
+ channels_selected="#9accff"
+ channel_group="#42566d"
+ active_channels_group="#326799"
+ long_key="#9b9b9b"
+ long_key_selected="#4291dc"
+ keyframe="#2c2c2c"
+ keyframe_selected="#fff1f1"
+ keyframe_extreme="#fbf9fd"
+ keyframe_extreme_selected="#f2efef"
+ keyframe_breakdown="#b3dbe8"
+ keyframe_breakdown_selected="#54bfed"
+ keyframe_jitter="#e5e2e2"
+ keyframe_jitter_selected="#beb8c0"
+ keyframe_border="#2c2c2cff"
+ keyframe_border_selected="#f2efefff"
+ summary="#3b3b3b6d">
+ <space>
+ <ThemeSpaceGeneric back="#5d5d5d"
+ title="#ffffff"
+ text="#ffffff"
+ text_hi="#fcfcfc"
+ header="#3b3b3b"
+ header_text="#ffffff"
+ header_text_hi="#b7b7b7"
+ button="#3b3b3bff"
+ button_title="#c7c7c7"
+ button_text="#b4b4b4"
+ button_text_hi="#ffffff"
+ tab_active="#727272"
+ tab_inactive="#535353"
+ tab_back="#404040ff"
+ tab_outline="#3c3c3c">
+ <panelcolors>
+ <ThemePanelColors header="#00000019"
+ back="#72727280"
+ show_header="FALSE"
+ show_back="FALSE">
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ <space_list>
+ <ThemeSpaceListGeneric list="#3b3b3b"
+ list_title="#000000"
+ list_text="#979797"
+ list_text_hi="#ffffff">
+ </ThemeSpaceListGeneric>
+ </space_list>
+ </ThemeDopeSheet>
+ </dopesheet_editor>
+ <image_editor>
+ <ThemeImageEditor gp_vertex="#000000"
+ gp_vertex_select="#ff8500"
+ gp_vertex_size="3"
+ vertex="#000000"
+ vertex_select="#0094ff"
+ vertex_size="3"
+ vertex_unreferenced="#000000"
+ face="#a47c5b0a"
+ face_select="#005fa480"
+ face_dot="#1fcbff"
+ facedot_size="2"
+ freestyle_face_mark="#7fff7f33"
+ editmesh_active="#ffffff80"
+ wire_edit="#5c5c5c"
+ edge_select="#005fa4"
+ scope_back="#303030ff"
+ preview_stitch_face="#1242b026"
+ preview_stitch_edge="#ff8500b2"
+ preview_stitch_vert="#ff85007f"
+ preview_stitch_stitchable="#00ff00ff"
+ preview_stitch_unstitchable="#ff0000ff"
+ preview_stitch_active="#e1d2c323"
+ uv_shadow="#707070ff"
+ uv_others="#606060ff"
+ frame_current="#60c040"
+ handle_free="#000000"
+ handle_auto="#909000"
+ handle_align="#803060"
+ handle_sel_free="#000000"
+ handle_sel_auto="#f0ff40"
+ handle_sel_align="#f090a0"
+ handle_auto_clamped="#000000"
+ handle_sel_auto_clamped="#000000"
+ handle_vertex="#000000"
+ handle_vertex_select="#ffff00"
+ handle_vertex_size="5"
+ paint_curve_handle="#7fff7f7f"
+ paint_curve_pivot="#ff7f7f7f">
+ <space>
+ <ThemeSpaceGeneric back="#5e5e5e"
+ title="#ffffff"
+ text="#8b8b8b"
+ text_hi="#ffffff"
+ header="#303030"
+ header_text="#000000"
+ header_text_hi="#b8b8b8"
+ button="#3b3b3bff"
+ button_title="#c7c7c7"
+ button_text="#b4b4b4"
+ button_text_hi="#ffffff"
+ tab_active="#3b3b3b"
+ tab_inactive="#222222"
+ tab_back="#222222ff"
+ tab_outline="#222222">
+ <panelcolors>
+ <ThemePanelColors header="#00000019"
+ back="#72727280"
+ show_header="FALSE"
+ show_back="FALSE">
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ </ThemeImageEditor>
+ </image_editor>
+ <sequence_editor>
+ <ThemeSequenceEditor gp_vertex="#000000"
+ gp_vertex_select="#ff8500"
+ gp_vertex_size="3"
+ grid="#6e6e6e"
+ window_sliders="#a0a0a0"
+ movie_strip="#5794c3"
+ movieclip_strip="#20208f"
+ image_strip="#bdb7b6"
+ scene_strip="#777777"
+ audio_strip="#6057c3"
+ effect_strip="#ffffff"
+ transition_strip="#726d70"
+ meta_strip="#6d9183"
+ frame_current="#4291dc"
+ keyframe="#ff8500"
+ draw_action="#607f9e"
+ preview_back="#3b3b3b">
+ <space>
+ <ThemeSpaceGeneric back="#5d5d5d"
+ title="#e4e4e4"
+ text="#ffffff"
+ text_hi="#ffffff"
+ header="#3b3b3b"
+ header_text="#000000"
+ header_text_hi="#b7b7b7"
+ button="#3b3b3b42"
+ button_title="#c7c7c7"
+ button_text="#b4b4b4"
+ button_text_hi="#ffffff"
+ tab_active="#3b3b3b"
+ tab_inactive="#222222"
+ tab_back="#222222ff"
+ tab_outline="#232323">
+ <panelcolors>
+ <ThemePanelColors header="#00000019"
+ back="#3b3b3bff"
+ show_header="FALSE"
+ show_back="FALSE">
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ </ThemeSequenceEditor>
+ </sequence_editor>
+ <properties>
+ <ThemeProperties>
+ <space>
+ <ThemeSpaceGeneric back="#3b3b3b"
+ title="#c7c7c7"
+ text="#b8b8b8"
+ text_hi="#ffffff"
+ header="#3b3b3b"
+ header_text="#000000"
+ header_text_hi="#ffffff"
+ button="#727272ff"
+ button_title="#c7c7c7"
+ button_text="#969696"
+ button_text_hi="#ffffff"
+ tab_active="#727272"
+ tab_inactive="#535353"
+ tab_back="#404040ff"
+ tab_outline="#3c3c3c">
+ <panelcolors>
+ <ThemePanelColors header="#00000019"
+ back="#72727280"
+ show_header="FALSE"
+ show_back="FALSE">
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ </ThemeProperties>
+ </properties>
+ <text_editor>
+ <ThemeTextEditor line_numbers_background="#2e2e2e"
+ selected_text="#607f9e"
+ cursor="#8b8bff"
+ syntax_builtin="#009eed"
+ syntax_symbols="#607f9e"
+ syntax_special="#009eed"
+ syntax_preprocessor="#409090"
+ syntax_reserved="#8c3c00"
+ syntax_comment="#757575"
+ syntax_string="#f0ad6d"
+ syntax_numbers="#f0ad6d">
+ <space>
+ <ThemeSpaceGeneric back="#3b3b3b"
+ title="#fefefe"
+ text="#cfcfcf"
+ text_hi="#ffffff"
+ header="#3b3b3b"
+ header_text="#ffffff"
+ header_text_hi="#b7b7b7"
+ button="#3b3b3bff"
+ button_title="#c7c7c7"
+ button_text="#b4b4b4"
+ button_text_hi="#ffffff"
+ tab_active="#3b3b3b"
+ tab_inactive="#222222"
+ tab_back="#222222ff"
+ tab_outline="#222222">
+ <panelcolors>
+ <ThemePanelColors header="#00000019"
+ back="#72727280"
+ show_header="FALSE"
+ show_back="FALSE">
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ </ThemeTextEditor>
+ </text_editor>
+ <timeline>
+ <ThemeTimeline grid="#6d6d6d"
+ frame_current="#4291dc"
+ time_keyframe="#ddd700"
+ time_grease_pencil="#b5e61d">
+ <space>
+ <ThemeSpaceGeneric back="#5d5d5d"
+ title="#e4e4e4"
+ text="#b8b8b8"
+ text_hi="#ffffff"
+ header="#3b3b3b"
+ header_text="#000000"
+ header_text_hi="#b8b8b8"
+ button="#727272ff"
+ button_title="#b4b4b4"
+ button_text="#b4b4b4"
+ button_text_hi="#ffffff"
+ tab_active="#727272"
+ tab_inactive="#535353"
+ tab_back="#404040ff"
+ tab_outline="#3b3b3b">
+ <panelcolors>
+ <ThemePanelColors header="#00000019"
+ back="#72727280"
+ show_header="FALSE"
+ show_back="FALSE">
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ </ThemeTimeline>
+ </timeline>
+ <node_editor>
+ <ThemeNodeEditor gp_vertex="#000000"
+ gp_vertex_select="#ff8500"
+ gp_vertex_size="3"
+ node_selected="#fff4f8"
+ node_active="#ffffff"
+ wire="#292929"
+ wire_inner="#737373"
+ wire_select="#ffffff"
+ selected_text="#909090"
+ node_backdrop="#444444ff"
+ converter_node="#292929"
+ color_node="#292929"
+ group_node="#5d5d5d"
+ group_socket_node="#1f00c7"
+ frame_node="#505050aa"
+ matte_node="#0076b6"
+ distor_node="#292929"
+ noodle_curving="4"
+ input_node="#009e9e"
+ output_node="#1f00c7"
+ filter_node="#0076b6"
+ vector_node="#292929"
+ texture_node="#009e9e"
+ shader_node="#0076b6"
+ script_node="#0076b6"
+ pattern_node="#008db6"
+ layout_node="#50b1b6">
+ <space>
+ <ThemeSpaceGeneric back="#5e5e5e"
+ title="#ffffff"
+ text="#ffffff"
+ text_hi="#ffffff"
+ header="#383838"
+ header_text="#3b3b3b"
+ header_text_hi="#b7b7b7"
+ button="#3b3b3bff"
+ button_title="#c7c7c7"
+ button_text="#b4b4b4"
+ button_text_hi="#ffffff"
+ tab_active="#3b3b3b"
+ tab_inactive="#222222"
+ tab_back="#222222ff"
+ tab_outline="#212121">
+ <panelcolors>
+ <ThemePanelColors header="#00000019"
+ back="#72727280"
+ show_header="FALSE"
+ show_back="FALSE">
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ <space_list>
+ <ThemeSpaceListGeneric list="#a5a5a5"
+ list_title="#000000"
+ list_text="#000000"
+ list_text_hi="#ffffff">
+ </ThemeSpaceListGeneric>
+ </space_list>
+ </ThemeNodeEditor>
+ </node_editor>
+ <logic_editor>
+ <ThemeLogicEditor>
+ <space>
+ <ThemeSpaceGeneric back="#3b3b3b"
+ title="#ffffff"
+ text="#000000"
+ text_hi="#ffffff"
+ header="#3b3b3b"
+ header_text="#ffffff"
+ header_text_hi="#b7b7b7"
+ button="#3b3b3bff"
+ button_title="#c7c7c7"
+ button_text="#727272"
+ button_text_hi="#ffffff"
+ tab_active="#727272"
+ tab_inactive="#222222"
+ tab_back="#222222ff"
+ tab_outline="#222222">
+ <panelcolors>
+ <ThemePanelColors header="#00000019"
+ back="#72727280"
+ show_header="FALSE"
+ show_back="FALSE">
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ </ThemeLogicEditor>
+ </logic_editor>
+ <outliner>
+ <ThemeOutliner match="#337f33"
+ selected_highlight="#607f9e">
+ <space>
+ <ThemeSpaceGeneric back="#4b4b4b"
+ title="#e4e4e4"
+ text="#cacaca"
+ text_hi="#ffffff"
+ header="#3b3b3b"
+ header_text="#000000"
+ header_text_hi="#ffffff"
+ button="#727272ff"
+ button_title="#c7c7c7"
+ button_text="#000000"
+ button_text_hi="#e4e4e4"
+ tab_active="#727272"
+ tab_inactive="#535353"
+ tab_back="#404040ff"
+ tab_outline="#3c3c3c">
+ <panelcolors>
+ <ThemePanelColors header="#00000019"
+ back="#72727280"
+ show_header="FALSE"
+ show_back="FALSE">
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ </ThemeOutliner>
+ </outliner>
+ <info>
+ <ThemeInfo info_selected="#607f9e"
+ info_selected_text="#ffffff"
+ info_error="#3b3b3b"
+ info_error_text="#ff0000"
+ info_warning="#3b3b3b"
+ info_warning_text="#ffe100"
+ info_info="#3b3b3b"
+ info_info_text="#25ff00"
+ info_debug="#c4c4c4"
+ info_debug_text="#000000">
+ <space>
+ <ThemeSpaceGeneric back="#3b3b3b"
+ title="#e4e4e4"
+ text="#868686"
+ text_hi="#ffffff"
+ header="#3b3b3b"
+ header_text="#ffffff"
+ header_text_hi="#000000"
+ button="#3b3b3bff"
+ button_title="#c7c7c7"
+ button_text="#000000"
+ button_text_hi="#000000"
+ tab_active="#727272"
+ tab_inactive="#535353"
+ tab_back="#404040ff"
+ tab_outline="#3c3c3c">
+ <panelcolors>
+ <ThemePanelColors header="#00000019"
+ back="#72727280"
+ show_header="FALSE"
+ show_back="FALSE">
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ </ThemeInfo>
+ </info>
+ <user_preferences>
+ <ThemeUserPreferences>
+ <space>
+ <ThemeSpaceGeneric back="#3b3b3b"
+ title="#e4e4e4"
+ text="#b8b8b8"
+ text_hi="#ffffff"
+ header="#3b3b3b"
+ header_text="#000000"
+ header_text_hi="#ffffff"
+ button="#727272ff"
+ button_title="#c7c7c7"
+ button_text="#000000"
+ button_text_hi="#ffffff"
+ tab_active="#727272"
+ tab_inactive="#535353"
+ tab_back="#404040ff"
+ tab_outline="#3c3c3c">
+ <panelcolors>
+ <ThemePanelColors header="#00000019"
+ back="#72727280"
+ show_header="FALSE"
+ show_back="FALSE">
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ </ThemeUserPreferences>
+ </user_preferences>
+ <console>
+ <ThemeConsole line_output="#838383"
+ line_input="#ffffff"
+ line_info="#607f9e"
+ line_error="#ff0013"
+ cursor="#2e2e2e"
+ select="#4e4e8f80">
+ <space>
+ <ThemeSpaceGeneric back="#3b3b3b"
+ title="#e4e4e4"
+ text="#000000"
+ text_hi="#ffffff"
+ header="#303030"
+ header_text="#000000"
+ header_text_hi="#ffffff"
+ button="#3b3b3bff"
+ button_title="#c7c7c7"
+ button_text="#000000"
+ button_text_hi="#ffffff"
+ tab_active="#727272"
+ tab_inactive="#535353"
+ tab_back="#404040ff"
+ tab_outline="#3c3c3c">
+ <panelcolors>
+ <ThemePanelColors header="#00000019"
+ back="#72727280"
+ show_header="FALSE"
+ show_back="FALSE">
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ </ThemeConsole>
+ </console>
+ <clip_editor>
+ <ThemeClipEditor gp_vertex="#000000"
+ gp_vertex_select="#000000"
+ gp_vertex_size="1"
+ marker_outline="#000000"
+ marker="#7f7f00"
+ active_marker="#ffffff"
+ selected_marker="#ffff00"
+ disabled_marker="#7f0000"
+ locked_marker="#7f7f7f"
+ path_before="#ff0000"
+ path_after="#0000ff"
+ frame_current="#60c040"
+ strips="#0c0a0a"
+ strips_selected="#ff8c00"
+ handle_free="#000000"
+ handle_auto="#909000"
+ handle_align="#803060"
+ handle_sel_free="#000000"
+ handle_sel_auto="#f0ff40"
+ handle_sel_align="#f090a0"
+ handle_auto_clamped="#000000"
+ handle_sel_auto_clamped="#000000"
+ handle_vertex="#000000"
+ handle_vertex_select="#ffff00"
+ handle_vertex_size="5">
+ <space>
+ <ThemeSpaceGeneric back="#5e5e5e"
+ title="#ffffff"
+ text="#8b8b8b"
+ text_hi="#ffffff"
+ header="#303030"
+ header_text="#000000"
+ header_text_hi="#b8b8b8"
+ button="#3b3b3bff"
+ button_title="#c7c7c7"
+ button_text="#b4b4b4"
+ button_text_hi="#ffffff"
+ tab_active="#3b3b3b"
+ tab_inactive="#222222"
+ tab_back="#222222ff"
+ tab_outline="#222222">
+ <panelcolors>
+ <ThemePanelColors header="#00000019"
+ back="#72727280"
+ show_header="FALSE"
+ show_back="FALSE">
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ <space_list>
+ <ThemeSpaceListGeneric list="#666666"
+ list_title="#000000"
+ list_text="#000000"
+ list_text_hi="#ffffff">
+ </ThemeSpaceListGeneric>
+ </space_list>
+ </ThemeClipEditor>
+ </clip_editor>
+ <bone_color_sets>
+ <ThemeBoneColorSet normal="#9a0000"
+ select="#bd1111"
+ active="#f70a0a"
+ show_colored_constraints="FALSE">
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet normal="#f74018"
+ select="#f66913"
+ active="#fa9900"
+ show_colored_constraints="FALSE">
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet normal="#1e9109"
+ select="#59b70b"
+ active="#83ef1d"
+ show_colored_constraints="FALSE">
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet normal="#0a3694"
+ select="#3667df"
+ active="#5ec1ef"
+ show_colored_constraints="FALSE">
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet normal="#a9294e"
+ select="#c1416a"
+ active="#f05d91"
+ show_colored_constraints="FALSE">
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet normal="#430c78"
+ select="#543aa3"
+ active="#8764d5"
+ show_colored_constraints="FALSE">
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet normal="#24785a"
+ select="#3c9579"
+ active="#6fb6ab"
+ show_colored_constraints="FALSE">
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet normal="#4b707c"
+ select="#6a8691"
+ active="#9bc2cd"
+ show_colored_constraints="FALSE">
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet normal="#f4c90c"
+ select="#eec236"
+ active="#f3ff00"
+ show_colored_constraints="FALSE">
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet normal="#1e2024"
+ select="#484c56"
+ active="#ffffff"
+ show_colored_constraints="FALSE">
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet normal="#6f2f6a"
+ select="#9845be"
+ active="#d330d6"
+ show_colored_constraints="FALSE">
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet normal="#6c8e22"
+ select="#7fb022"
+ active="#bbef5b"
+ show_colored_constraints="FALSE">
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet normal="#8d8d8d"
+ select="#b0b0b0"
+ active="#dedede"
+ show_colored_constraints="FALSE">
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet normal="#834326"
+ select="#8b5811"
+ active="#bd6a11"
+ show_colored_constraints="FALSE">
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet normal="#08310e"
+ select="#1c430b"
+ active="#34622b"
+ show_colored_constraints="FALSE">
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet normal="#000000"
+ select="#000000"
+ active="#000000"
+ show_colored_constraints="FALSE">
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet normal="#000000"
+ select="#000000"
+ active="#000000"
+ show_colored_constraints="FALSE">
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet normal="#000000"
+ select="#000000"
+ active="#000000"
+ show_colored_constraints="FALSE">
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet normal="#000000"
+ select="#000000"
+ active="#000000"
+ show_colored_constraints="FALSE">
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet normal="#000000"
+ select="#000000"
+ active="#000000"
+ show_colored_constraints="FALSE">
+ </ThemeBoneColorSet>
+ </bone_color_sets>
+ </Theme>
+ <ThemeStyle>
+ <panel_title>
+ <ThemeFontStyle points="12"
+ font_kerning_style="FITTED"
+ shadow="1"
+ shadow_offset_x="0"
+ shadow_offset_y="-1"
+ shadow_alpha="0.15"
+ shadow_value="1">
+ </ThemeFontStyle>
+ </panel_title>
+ <widget_label>
+ <ThemeFontStyle points="11"
+ font_kerning_style="FITTED"
+ shadow="3"
+ shadow_offset_x="0"
+ shadow_offset_y="-1"
+ shadow_alpha="0.15"
+ shadow_value="1">
+ </ThemeFontStyle>
+ </widget_label>
+ <widget>
+ <ThemeFontStyle points="11"
+ font_kerning_style="FITTED"
+ shadow="0"
+ shadow_offset_x="0"
+ shadow_offset_y="0"
+ shadow_alpha="0.25"
+ shadow_value="0">
+ </ThemeFontStyle>
+ </widget>
+ </ThemeStyle>
+</bpy>
diff --git a/release/scripts/presets/interface_theme/hexagon.xml b/release/scripts/presets/interface_theme/hexagon.xml
index d2221bc9935..74adb9f9d27 100644
--- a/release/scripts/presets/interface_theme/hexagon.xml
+++ b/release/scripts/presets/interface_theme/hexagon.xml
@@ -5,6 +5,7 @@
menu_shadow_width="12"
icon_file=""
icon_alpha="1"
+ widget_emboss="#ffffff05"
axis_x="#dc0000"
axis_y="#00dc00"
axis_z="#0000dc">
@@ -154,11 +155,11 @@
</wcol_menu_back>
<wcol_pie_menu>
<ThemeWidgetColors outline="#0a0a0a"
- inner="#191919e6"
+ inner="#5a5e6ae6"
inner_sel="#8c8c8cff"
- item="#2d2d2de6"
- text="#a0a0a0"
- text_sel="#ffffff"
+ item="#8f92a1e6"
+ text="#d6d6d6"
+ text_sel="#000000"
show_shaded="TRUE"
shadetop="10"
shadedown="-10">
@@ -240,6 +241,9 @@
<ThemeView3D grid="#5e5e83"
wire="#000000"
wire_edit="#000000"
+ gp_vertex="#000000"
+ gp_vertex_select="#ff8500"
+ gp_vertex_size="3"
lamp="#00000028"
speaker="#000000"
camera="#000000"
@@ -286,6 +290,7 @@
editmesh_active="#00e8ff80"
normal="#00ffff"
vertex_normal="#2361dd"
+ split_normal="#dd23dd"
bone_solid="#c8c8c8"
bone_pose="#50c8ff"
bone_pose_active="#8cffff"
@@ -294,6 +299,7 @@
bundle_solid="#c8c8c8"
camera_path="#000000"
skin_root="#000000"
+ clipping_border_3d="#313131ff"
paint_curve_handle="#7fff7f7f"
paint_curve_pivot="#ff7f7f7f">
<space>
@@ -432,18 +438,18 @@
<nla_editor>
<ThemeNLAEditor grid="#5e5e5e"
view_sliders="#969696"
- active_action="#00000000"
- active_action_unset="#00000000"
+ active_action="#cc701a66"
+ active_action_unset="#9987614d"
strips="#0c0a0a"
strips_selected="#ff8c00"
- transition_strips="#000000"
- transition_strips_selected="#000000"
- meta_strips="#000000"
- meta_strips_selected="#000000"
- sound_strips="#000000"
- sound_strips_selected="#000000"
- tweak="#000000"
- tweak_duplicate="#000000"
+ transition_strips="#1c2630"
+ transition_strips_selected="#2e75db"
+ meta_strips="#332642"
+ meta_strips_selected="#692196"
+ sound_strips="#2b3d3d"
+ sound_strips_selected="#1f7a7a"
+ tweak="#4df31a"
+ tweak_duplicate="#d90000"
keyframe_border="#000000ff"
keyframe_border_selected="#000000ff"
frame_current="#60c040">
@@ -504,7 +510,7 @@
keyframe_jitter_selected="#61c042"
keyframe_border="#000000ff"
keyframe_border_selected="#000000ff"
- summary="#00000000">
+ summary="#cc701a66">
<space>
<ThemeSpaceGeneric back="#7c7e88"
title="#000000"
@@ -540,7 +546,10 @@
</ThemeDopeSheet>
</dopesheet_editor>
<image_editor>
- <ThemeImageEditor vertex="#334cca"
+ <ThemeImageEditor gp_vertex="#000000"
+ gp_vertex_select="#ff8500"
+ gp_vertex_size="3"
+ vertex="#334cca"
vertex_select="#50c8ff"
vertex_size="3"
vertex_unreferenced="#000000"
@@ -603,7 +612,10 @@
</ThemeImageEditor>
</image_editor>
<sequence_editor>
- <ThemeSequenceEditor grid="#404040"
+ <ThemeSequenceEditor gp_vertex="#000000"
+ gp_vertex_select="#ff8500"
+ gp_vertex_size="3"
+ grid="#404040"
window_sliders="#a0a0a0"
movie_strip="#516987"
movieclip_strip="#20208f"
@@ -714,7 +726,9 @@
</text_editor>
<timeline>
<ThemeTimeline grid="#58587c"
- frame_current="#60c040">
+ frame_current="#60c040"
+ time_keyframe="#ddd700"
+ time_grease_pencil="#b5e61d">
<space>
<ThemeSpaceGeneric back="#646875"
title="#000000"
@@ -743,9 +757,13 @@
</ThemeTimeline>
</timeline>
<node_editor>
- <ThemeNodeEditor node_selected="#ffffff"
+ <ThemeNodeEditor gp_vertex="#000000"
+ gp_vertex_select="#ff8500"
+ gp_vertex_size="3"
+ node_selected="#ffffff"
node_active="#ffffff"
wire="#000000"
+ wire_inner="#737373"
wire_select="#ffffff"
selected_text="#7f7070"
node_backdrop="#9b9baca0"
@@ -961,7 +979,10 @@
</ThemeConsole>
</console>
<clip_editor>
- <ThemeClipEditor marker_outline="#000000"
+ <ThemeClipEditor gp_vertex="#000000"
+ gp_vertex_select="#000000"
+ gp_vertex_size="1"
+ marker_outline="#000000"
marker="#7f7f00"
active_marker="#ffffff"
selected_marker="#ffff00"
@@ -969,7 +990,6 @@
locked_marker="#7f7f7f"
path_before="#ff0000"
path_after="#0000ff"
- grid="#5e5e5e"
frame_current="#60c040"
strips="#0c0a0a"
strips_selected="#ff8c00"
diff --git a/release/scripts/presets/interface_theme/rtheme.xml b/release/scripts/presets/interface_theme/rtheme.xml
new file mode 100644
index 00000000000..c25806729b9
--- /dev/null
+++ b/release/scripts/presets/interface_theme/rtheme.xml
@@ -0,0 +1,1176 @@
+<bpy>
+ <Theme>
+ <user_interface>
+ <ThemeUserInterface menu_shadow_fac="0.5"
+ menu_shadow_width="12"
+ icon_file=""
+ icon_alpha="1"
+ widget_emboss="#ffffff05"
+ axis_x="#dc403e"
+ axis_y="#68dc50"
+ axis_z="#4040dc">
+ <wcol_regular>
+ <ThemeWidgetColors outline="#222222"
+ inner="#3f3f3fff"
+ inner_sel="#222222ff"
+ item="#000000ff"
+ text="#ffffff"
+ text_sel="#ffffff"
+ show_shaded="FALSE"
+ shadetop="0"
+ shadedown="0">
+ </ThemeWidgetColors>
+ </wcol_regular>
+ <wcol_tool>
+ <ThemeWidgetColors outline="#222222"
+ inner="#666666ff"
+ inner_sel="#08c1ffff"
+ item="#000000ff"
+ text="#000000"
+ text_sel="#000000"
+ show_shaded="TRUE"
+ shadetop="10"
+ shadedown="-10">
+ </ThemeWidgetColors>
+ </wcol_tool>
+ <wcol_radio>
+ <ThemeWidgetColors outline="#222222"
+ inner="#464646ff"
+ inner_sel="#05c4ffff"
+ item="#ffffffff"
+ text="#ffffff"
+ text_sel="#000000"
+ show_shaded="FALSE"
+ shadetop="15"
+ shadedown="-15">
+ </ThemeWidgetColors>
+ </wcol_radio>
+ <wcol_text>
+ <ThemeWidgetColors outline="#3d3d3b"
+ inner="#666666ff"
+ inner_sel="#999999ff"
+ item="#5a5a5aff"
+ text="#fdfdfd"
+ text_sel="#ffffff"
+ show_shaded="FALSE"
+ shadetop="0"
+ shadedown="25">
+ </ThemeWidgetColors>
+ </wcol_text>
+ <wcol_option>
+ <ThemeWidgetColors outline="#222222"
+ inner="#686868ff"
+ inner_sel="#05c4ffff"
+ item="#000000ff"
+ text="#ffffff"
+ text_sel="#ffffff"
+ show_shaded="FALSE"
+ shadetop="15"
+ shadedown="-15">
+ </ThemeWidgetColors>
+ </wcol_option>
+ <wcol_toggle>
+ <ThemeWidgetColors outline="#302e2e"
+ inner="#999999ff"
+ inner_sel="#05c4ffff"
+ item="#5a5a5aff"
+ text="#000000"
+ text_sel="#ffffff"
+ show_shaded="FALSE"
+ shadetop="0"
+ shadedown="0">
+ </ThemeWidgetColors>
+ </wcol_toggle>
+ <wcol_num>
+ <ThemeWidgetColors outline="#222222"
+ inner="#666666ff"
+ inner_sel="#05c4ffff"
+ item="#5a5a5aff"
+ text="#000000"
+ text_sel="#ffffff"
+ show_shaded="FALSE"
+ shadetop="-10"
+ shadedown="10">
+ </ThemeWidgetColors>
+ </wcol_num>
+ <wcol_numslider>
+ <ThemeWidgetColors outline="#222222"
+ inner="#606060ff"
+ inner_sel="#999999ff"
+ item="#3a3a3aff"
+ text="#e6e6e6"
+ text_sel="#ffffff"
+ show_shaded="TRUE"
+ shadetop="-10"
+ shadedown="10">
+ </ThemeWidgetColors>
+ </wcol_numslider>
+ <wcol_box>
+ <ThemeWidgetColors outline="#222222"
+ inner="#464646ff"
+ inner_sel="#646464ff"
+ item="#000000ff"
+ text="#ffffff"
+ text_sel="#ffffff"
+ show_shaded="FALSE"
+ shadetop="0"
+ shadedown="0">
+ </ThemeWidgetColors>
+ </wcol_box>
+ <wcol_menu>
+ <ThemeWidgetColors outline="#222222"
+ inner="#606060ff"
+ inner_sel="#08bfffff"
+ item="#ffffffff"
+ text="#ffffff"
+ text_sel="#000000"
+ show_shaded="FALSE"
+ shadetop="15"
+ shadedown="-15">
+ </ThemeWidgetColors>
+ </wcol_menu>
+ <wcol_pulldown>
+ <ThemeWidgetColors outline="#222222"
+ inner="#606060ff"
+ inner_sel="#0bc6ffff"
+ item="#ffffffff"
+ text="#888888"
+ text_sel="#000000"
+ show_shaded="FALSE"
+ shadetop="25"
+ shadedown="-20">
+ </ThemeWidgetColors>
+ </wcol_pulldown>
+ <wcol_menu_back>
+ <ThemeWidgetColors outline="#3d3d3d"
+ inner="#3d3d3de6"
+ inner_sel="#2d2d2de6"
+ item="#5f5f5fff"
+ text="#a0a0a0"
+ text_sel="#ffffff"
+ show_shaded="FALSE"
+ shadetop="25"
+ shadedown="-20">
+ </ThemeWidgetColors>
+ </wcol_menu_back>
+ <wcol_pie_menu>
+ <ThemeWidgetColors outline="#0a0a0a"
+ inner="#aaaaaae6"
+ inner_sel="#8c8c8cff"
+ item="#a2a2a2e6"
+ text="#000000"
+ text_sel="#ffffff"
+ show_shaded="TRUE"
+ shadetop="10"
+ shadedown="-10">
+ </ThemeWidgetColors>
+ </wcol_pie_menu>
+ <wcol_tooltip>
+ <ThemeWidgetColors outline="#000000"
+ inner="#191919e6"
+ inner_sel="#2d2d2de6"
+ item="#646464ff"
+ text="#ffffff"
+ text_sel="#ffffff"
+ show_shaded="FALSE"
+ shadetop="25"
+ shadedown="-20">
+ </ThemeWidgetColors>
+ </wcol_tooltip>
+ <wcol_menu_item>
+ <ThemeWidgetColors outline="#222222"
+ inner="#00000000"
+ inner_sel="#0bc3ffff"
+ item="#ffffffff"
+ text="#ffffff"
+ text_sel="#000000"
+ show_shaded="FALSE"
+ shadetop="38"
+ shadedown="0">
+ </ThemeWidgetColors>
+ </wcol_menu_item>
+ <wcol_scroll>
+ <ThemeWidgetColors outline="#323232"
+ inner="#505050b4"
+ inner_sel="#646464b4"
+ item="#606060ff"
+ text="#000000"
+ text_sel="#ffffff"
+ show_shaded="FALSE"
+ shadetop="5"
+ shadedown="-5">
+ </ThemeWidgetColors>
+ </wcol_scroll>
+ <wcol_progress>
+ <ThemeWidgetColors outline="#222222"
+ inner="#bebebeff"
+ inner_sel="#646464b4"
+ item="#444444ff"
+ text="#000000"
+ text_sel="#ffffff"
+ show_shaded="FALSE"
+ shadetop="5"
+ shadedown="-5">
+ </ThemeWidgetColors>
+ </wcol_progress>
+ <wcol_list_item>
+ <ThemeWidgetColors outline="#222222"
+ inner="#00000000"
+ inner_sel="#0abeffff"
+ item="#ffffffff"
+ text="#000000"
+ text_sel="#000000"
+ show_shaded="FALSE"
+ shadetop="0"
+ shadedown="0">
+ </ThemeWidgetColors>
+ </wcol_list_item>
+ <wcol_state>
+ <ThemeWidgetStateColors inner_anim="#73be4c"
+ inner_anim_sel="#5aa633"
+ inner_key="#c9ce20"
+ inner_key_sel="#d7d34b"
+ inner_driven="#b400ff"
+ inner_driven_sel="#9900e6"
+ blend="0.5">
+ </ThemeWidgetStateColors>
+ </wcol_state>
+ </ThemeUserInterface>
+ </user_interface>
+ <view_3d>
+ <ThemeView3D grid="#4c4c4c"
+ wire="#7e7e7e"
+ wire_edit="#1d1d1d"
+ gp_vertex="#000000"
+ gp_vertex_select="#ff8500"
+ gp_vertex_size="3"
+ lamp="#00000028"
+ speaker="#000000"
+ camera="#000000"
+ view_overlay="#000000"
+ empty="#000000"
+ object_selected="#69adc2"
+ object_active="#08c1ff"
+ object_grouped="#08583d"
+ object_grouped_active="#19ffce"
+ transform="#ffffff"
+ vertex="#000000"
+ vertex_select="#f0f8ff"
+ vertex_size="3"
+ vertex_unreferenced="#000000"
+ edge_select="#08c1ff"
+ edge_seam="#ff5b00"
+ edge_sharp="#ff1600"
+ edge_crease="#52514d"
+ edge_facesel="#4b4b4b"
+ freestyle_edge_mark="#7fff7f"
+ face="#00000012"
+ face_select="#08c1ff66"
+ face_dot="#49caff"
+ facedot_size="4"
+ freestyle_face_mark="#7fff7f33"
+ nurb_uline="#909000"
+ nurb_vline="#803060"
+ nurb_sel_uline="#f0ff40"
+ nurb_sel_vline="#f090a0"
+ act_spline="#db2512"
+ handle_free="#000000"
+ handle_auto="#909000"
+ handle_vect="#409030"
+ handle_sel_vect="#40c030"
+ handle_align="#803060"
+ handle_sel_free="#000000"
+ handle_sel_auto="#f0ff40"
+ handle_sel_align="#f090a0"
+ lastsel_point="#ffffff"
+ extra_edge_len="#200000"
+ extra_edge_angle="#000000"
+ extra_face_angle="#002000"
+ extra_face_area="#000080"
+ editmesh_active="#08c1ffff"
+ normal="#22dddd"
+ vertex_normal="#2361dd"
+ split_normal="#dd23dd"
+ bone_solid="#c8c8c8"
+ bone_pose="#50c8ff"
+ bone_pose_active="#8cffff"
+ frame_current="#60c040"
+ outline_width="1"
+ bundle_solid="#c8c8c8"
+ camera_path="#000000"
+ skin_root="#b44d4d"
+ clipping_border_3d="#313131ff"
+ paint_curve_handle="#7fff7f7f"
+ paint_curve_pivot="#ff7f7f7f">
+ <space>
+ <ThemeSpaceGradient title="#000000"
+ text="#0e0e0e"
+ text_hi="#dddddd"
+ header="#484848"
+ header_text="#000000"
+ header_text_hi="#ffffff"
+ button="#484848a7"
+ button_title="#000000"
+ button_text="#c2c2c2"
+ button_text_hi="#ffffff"
+ tab_active="#474747"
+ tab_inactive="#333333"
+ tab_back="#31313100"
+ tab_outline="#000000">
+ <gradients>
+ <ThemeGradientColors show_grad="FALSE"
+ gradient="#000000"
+ high_gradient="#36383a">
+ </ThemeGradientColors>
+ </gradients>
+ <panelcolors>
+ <ThemePanelColors header="#ffffff79"
+ back="#72727280"
+ show_header="FALSE"
+ show_back="FALSE">
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGradient>
+ </space>
+ </ThemeView3D>
+ </view_3d>
+ <graph_editor>
+ <ThemeGraphEditor grid="#5b6672"
+ frame_current="#60c040"
+ window_sliders="#969696"
+ channels_region="#707070"
+ dopesheet_channel="#52606e"
+ dopesheet_subchannel="#7c8996"
+ channel_group="#4f6549"
+ active_channels_group="#87b17d"
+ vertex="#000000"
+ vertex_select="#ff8500"
+ vertex_size="3"
+ vertex_unreferenced="#000000"
+ handle_free="#000000"
+ handle_auto="#909000"
+ handle_vect="#409030"
+ handle_sel_vect="#40c030"
+ handle_align="#803060"
+ handle_sel_free="#000000"
+ handle_sel_auto="#f0ff40"
+ handle_sel_align="#f090a0"
+ handle_auto_clamped="#994030"
+ handle_sel_auto_clamped="#f0af90"
+ lastsel_point="#ffffff"
+ handle_vertex="#000000"
+ handle_vertex_select="#ff8500"
+ handle_vertex_size="3">
+ <space>
+ <ThemeSpaceGeneric back="#9098a0"
+ title="#000000"
+ text="#000000"
+ text_hi="#ffffff"
+ header="#484848"
+ header_text="#000000"
+ header_text_hi="#ffffff"
+ button="#484848a7"
+ button_title="#000000"
+ button_text="#000000"
+ button_text_hi="#ffffff"
+ tab_active="#727272"
+ tab_inactive="#535353"
+ tab_back="#404040ff"
+ tab_outline="#3c3c3c">
+ <panelcolors>
+ <ThemePanelColors header="#ffffff79"
+ back="#72727280"
+ show_header="FALSE"
+ show_back="FALSE">
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ <space_list>
+ <ThemeSpaceListGeneric list="#484848"
+ list_title="#000000"
+ list_text="#000000"
+ list_text_hi="#ffffff">
+ </ThemeSpaceListGeneric>
+ </space_list>
+ </ThemeGraphEditor>
+ </graph_editor>
+ <file_browser>
+ <ThemeFileBrowser selected_file="#ff8c19"
+ scrollbar="#a0a0a0"
+ scroll_handle="#7f7070"
+ active_file="#828282"
+ active_file_text="#fafafa">
+ <space>
+ <ThemeSpaceGeneric back="#9098a0"
+ title="#000000"
+ text="#fafafa"
+ text_hi="#0f0f0f"
+ header="#484848"
+ header_text="#000000"
+ header_text_hi="#ffffff"
+ button="#726f6dff"
+ button_title="#000000"
+ button_text="#000000"
+ button_text_hi="#ffffff"
+ tab_active="#727272"
+ tab_inactive="#535353"
+ tab_back="#404040ff"
+ tab_outline="#3c3c3c">
+ <panelcolors>
+ <ThemePanelColors header="#ffffff79"
+ back="#72727280"
+ show_header="FALSE"
+ show_back="FALSE">
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ <space_list>
+ <ThemeSpaceListGeneric list="#484848"
+ list_title="#000000"
+ list_text="#000000"
+ list_text_hi="#ffffff">
+ </ThemeSpaceListGeneric>
+ </space_list>
+ </ThemeFileBrowser>
+ </file_browser>
+ <nla_editor>
+ <ThemeNLAEditor grid="#5b6672"
+ view_sliders="#969696"
+ active_action="#cc701a66"
+ active_action_unset="#00000000"
+ strips="#0c0a0a"
+ strips_selected="#ff8c00"
+ transition_strips="#000000"
+ transition_strips_selected="#000000"
+ meta_strips="#000000"
+ meta_strips_selected="#000000"
+ sound_strips="#000000"
+ sound_strips_selected="#000000"
+ tweak="#000000"
+ tweak_duplicate="#000000"
+ keyframe_border="#000000ff"
+ keyframe_border_selected="#000000ff"
+ frame_current="#60c040">
+ <space>
+ <ThemeSpaceGeneric back="#9098a0"
+ title="#000000"
+ text="#000000"
+ text_hi="#ffffff"
+ header="#484848"
+ header_text="#000000"
+ header_text_hi="#ffffff"
+ button="#484848a7"
+ button_title="#000000"
+ button_text="#000000"
+ button_text_hi="#ffffff"
+ tab_active="#727272"
+ tab_inactive="#535353"
+ tab_back="#404040ff"
+ tab_outline="#3c3c3c">
+ <panelcolors>
+ <ThemePanelColors header="#ffffff79"
+ back="#72727280"
+ show_header="FALSE"
+ show_back="FALSE">
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ <space_list>
+ <ThemeSpaceListGeneric list="#484848"
+ list_title="#000000"
+ list_text="#000000"
+ list_text_hi="#ffffff">
+ </ThemeSpaceListGeneric>
+ </space_list>
+ </ThemeNLAEditor>
+ </nla_editor>
+ <dopesheet_editor>
+ <ThemeDopeSheet grid="#5b6672"
+ frame_current="#60c040"
+ value_sliders="#000000"
+ view_sliders="#969696"
+ dopesheet_channel="#52606e"
+ dopesheet_subchannel="#7c8996"
+ channels="#707070"
+ channels_selected="#60c040"
+ channel_group="#4f6549"
+ active_channels_group="#87b17d"
+ long_key="#0c0a0a"
+ long_key_selected="#ff8c00"
+ keyframe="#f1f9ff"
+ keyframe_selected="#00dfff"
+ keyframe_extreme="#e5e2e8"
+ keyframe_extreme_selected="#f2efef"
+ keyframe_breakdown="#b3dbe8"
+ keyframe_breakdown_selected="#54bfed"
+ keyframe_jitter="#e5e2e2"
+ keyframe_jitter_selected="#beb8c0"
+ keyframe_border="#f1f9ffff"
+ keyframe_border_selected="#00dfffff"
+ summary="#cc701a66">
+ <space>
+ <ThemeSpaceGeneric back="#9098a0"
+ title="#000000"
+ text="#000000"
+ text_hi="#ffffff"
+ header="#484848"
+ header_text="#000000"
+ header_text_hi="#ffffff"
+ button="#484848a7"
+ button_title="#000000"
+ button_text="#000000"
+ button_text_hi="#ffffff"
+ tab_active="#727272"
+ tab_inactive="#535353"
+ tab_back="#404040ff"
+ tab_outline="#3c3c3c">
+ <panelcolors>
+ <ThemePanelColors header="#ffffff79"
+ back="#72727280"
+ show_header="FALSE"
+ show_back="FALSE">
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ <space_list>
+ <ThemeSpaceListGeneric list="#484848"
+ list_title="#000000"
+ list_text="#000000"
+ list_text_hi="#ffffff">
+ </ThemeSpaceListGeneric>
+ </space_list>
+ </ThemeDopeSheet>
+ </dopesheet_editor>
+ <image_editor>
+ <ThemeImageEditor gp_vertex="#000000"
+ gp_vertex_select="#ff8500"
+ gp_vertex_size="3"
+ vertex="#000000"
+ vertex_select="#08c1ff"
+ vertex_size="3"
+ vertex_unreferenced="#000000"
+ face="#ffffff0a"
+ face_select="#08c1ff40"
+ face_dot="#08c1ff"
+ facedot_size="3"
+ freestyle_face_mark="#00000000"
+ editmesh_active="#08c1ffff"
+ wire_edit="#5c5c5c"
+ edge_select="#0067cb"
+ scope_back="#727272ff"
+ preview_stitch_face="#1242b026"
+ preview_stitch_edge="#08c1ff97"
+ preview_stitch_vert="#08c1ff91"
+ preview_stitch_stitchable="#00ff00ff"
+ preview_stitch_unstitchable="#ff0000ff"
+ preview_stitch_active="#e1d2c323"
+ uv_shadow="#707070ff"
+ uv_others="#606060ff"
+ frame_current="#60c040"
+ handle_free="#000000"
+ handle_auto="#909000"
+ handle_align="#803060"
+ handle_sel_free="#000000"
+ handle_sel_auto="#f0ff40"
+ handle_sel_align="#f090a0"
+ handle_auto_clamped="#000000"
+ handle_sel_auto_clamped="#000000"
+ handle_vertex="#000000"
+ handle_vertex_select="#ffff00"
+ handle_vertex_size="5"
+ paint_curve_handle="#7fff7f7f"
+ paint_curve_pivot="#ff7f7f7f">
+ <space>
+ <ThemeSpaceGeneric back="#1d1d1d"
+ title="#000000"
+ text="#000000"
+ text_hi="#ffffff"
+ header="#484848"
+ header_text="#000000"
+ header_text_hi="#ffffff"
+ button="#484848a7"
+ button_title="#000000"
+ button_text="#000000"
+ button_text_hi="#ffffff"
+ tab_active="#727272"
+ tab_inactive="#535353"
+ tab_back="#404040ff"
+ tab_outline="#3c3c3c">
+ <panelcolors>
+ <ThemePanelColors header="#ffffff79"
+ back="#72727280"
+ show_header="FALSE"
+ show_back="FALSE">
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ </ThemeImageEditor>
+ </image_editor>
+ <sequence_editor>
+ <ThemeSequenceEditor gp_vertex="#000000"
+ gp_vertex_select="#ff8500"
+ gp_vertex_size="3"
+ grid="#9098a0"
+ window_sliders="#a0a0a0"
+ movie_strip="#516987"
+ movieclip_strip="#20208f"
+ image_strip="#6d5881"
+ scene_strip="#4e983e"
+ audio_strip="#2e8f8f"
+ effect_strip="#a9547c"
+ transition_strip="#a25f6f"
+ meta_strip="#6d9183"
+ frame_current="#60c040"
+ keyframe="#ff8500"
+ draw_action="#50c8ff"
+ preview_back="#000000">
+ <space>
+ <ThemeSpaceGeneric back="#9098a0"
+ title="#000000"
+ text="#000000"
+ text_hi="#ffffff"
+ header="#484848"
+ header_text="#000000"
+ header_text_hi="#ffffff"
+ button="#484848a7"
+ button_title="#000000"
+ button_text="#000000"
+ button_text_hi="#ffffff"
+ tab_active="#727272"
+ tab_inactive="#535353"
+ tab_back="#404040ff"
+ tab_outline="#3c3c3c">
+ <panelcolors>
+ <ThemePanelColors header="#ffffff79"
+ back="#72727280"
+ show_header="FALSE"
+ show_back="FALSE">
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ </ThemeSequenceEditor>
+ </sequence_editor>
+ <properties>
+ <ThemeProperties>
+ <space>
+ <ThemeSpaceGeneric back="#484848"
+ title="#000000"
+ text="#000000"
+ text_hi="#000000"
+ header="#484848"
+ header_text="#000000"
+ header_text_hi="#dff5ff"
+ button="#484848a7"
+ button_title="#3f3a2f"
+ button_text="#000000"
+ button_text_hi="#ffffff"
+ tab_active="#727272"
+ tab_inactive="#535353"
+ tab_back="#404040ff"
+ tab_outline="#3c3c3c">
+ <panelcolors>
+ <ThemePanelColors header="#ffffff79"
+ back="#72727280"
+ show_header="FALSE"
+ show_back="FALSE">
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ </ThemeProperties>
+ </properties>
+ <text_editor>
+ <ThemeTextEditor line_numbers_background="#404040"
+ selected_text="#c67777"
+ cursor="#ff0000"
+ syntax_builtin="#800050"
+ syntax_symbols="#4c4c4c"
+ syntax_special="#5f5f00"
+ syntax_preprocessor="#32008c"
+ syntax_reserved="#8c3c00"
+ syntax_comment="#006432"
+ syntax_string="#640000"
+ syntax_numbers="#0000c8">
+ <space>
+ <ThemeSpaceGeneric back="#9098a0"
+ title="#000000"
+ text="#000000"
+ text_hi="#ffffff"
+ header="#484848"
+ header_text="#000000"
+ header_text_hi="#ffffff"
+ button="#484848a7"
+ button_title="#000000"
+ button_text="#000000"
+ button_text_hi="#ffffff"
+ tab_active="#727272"
+ tab_inactive="#535353"
+ tab_back="#404040ff"
+ tab_outline="#3c3c3c">
+ <panelcolors>
+ <ThemePanelColors header="#ffffff79"
+ back="#72727280"
+ show_header="FALSE"
+ show_back="FALSE">
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ </ThemeTextEditor>
+ </text_editor>
+ <timeline>
+ <ThemeTimeline grid="#5b6672"
+ frame_current="#60c040"
+ time_keyframe="#ddd700"
+ time_grease_pencil="#b5e61d">
+ <space>
+ <ThemeSpaceGeneric back="#9098a0"
+ title="#000000"
+ text="#000000"
+ text_hi="#ffffff"
+ header="#484848"
+ header_text="#000000"
+ header_text_hi="#ffffff"
+ button="#484848a7"
+ button_title="#000000"
+ button_text="#000000"
+ button_text_hi="#ffffff"
+ tab_active="#727272"
+ tab_inactive="#535353"
+ tab_back="#404040ff"
+ tab_outline="#3c3c3c">
+ <panelcolors>
+ <ThemePanelColors header="#ffffff79"
+ back="#72727280"
+ show_header="FALSE"
+ show_back="FALSE">
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ </ThemeTimeline>
+ </timeline>
+ <node_editor>
+ <ThemeNodeEditor gp_vertex="#000000"
+ gp_vertex_select="#ff8500"
+ gp_vertex_size="3"
+ node_selected="#69adc2"
+ node_active="#08c1ff"
+ wire="#7c7c7c"
+ wire_inner="#737373"
+ wire_select="#08c1ff"
+ selected_text="#7f7070"
+ node_backdrop="#9b9b9ba0"
+ converter_node="#575757"
+ color_node="#575757"
+ group_node="#729c91"
+ group_socket_node="#19ffce"
+ frame_node="#96969600"
+ matte_node="#977474"
+ distor_node="#749797"
+ noodle_curving="5"
+ input_node="#575757"
+ output_node="#ffce18"
+ filter_node="#575757"
+ vector_node="#575757"
+ texture_node="#00c6ff"
+ shader_node="#356cff"
+ script_node="#575757"
+ pattern_node="#575757"
+ layout_node="#727272">
+ <space>
+ <ThemeSpaceGeneric back="#9098a0"
+ title="#000000"
+ text="#000000"
+ text_hi="#ffffff"
+ header="#484848"
+ header_text="#000000"
+ header_text_hi="#ffffff"
+ button="#484848a7"
+ button_title="#000000"
+ button_text="#000000"
+ button_text_hi="#ffffff"
+ tab_active="#727272"
+ tab_inactive="#535353"
+ tab_back="#404040ff"
+ tab_outline="#3c3c3c">
+ <panelcolors>
+ <ThemePanelColors header="#ffffff79"
+ back="#72727280"
+ show_header="FALSE"
+ show_back="FALSE">
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ <space_list>
+ <ThemeSpaceListGeneric list="#484848"
+ list_title="#000000"
+ list_text="#000000"
+ list_text_hi="#ffffff">
+ </ThemeSpaceListGeneric>
+ </space_list>
+ </ThemeNodeEditor>
+ </node_editor>
+ <logic_editor>
+ <ThemeLogicEditor>
+ <space>
+ <ThemeSpaceGeneric back="#9098a0"
+ title="#000000"
+ text="#000000"
+ text_hi="#ffffff"
+ header="#484848"
+ header_text="#000000"
+ header_text_hi="#ffffff"
+ button="#484848a7"
+ button_title="#000000"
+ button_text="#000000"
+ button_text_hi="#ffffff"
+ tab_active="#727272"
+ tab_inactive="#535353"
+ tab_back="#404040ff"
+ tab_outline="#3c3c3c">
+ <panelcolors>
+ <ThemePanelColors header="#ffffff79"
+ back="#72727280"
+ show_header="FALSE"
+ show_back="FALSE">
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ </ThemeLogicEditor>
+ </logic_editor>
+ <outliner>
+ <ThemeOutliner match="#337f33"
+ selected_highlight="#9098a0">
+ <space>
+ <ThemeSpaceGeneric back="#9098a0"
+ title="#0e0e0e"
+ text="#000000"
+ text_hi="#69deff"
+ header="#484848"
+ header_text="#000000"
+ header_text_hi="#ffffff"
+ button="#484848a7"
+ button_title="#070707"
+ button_text="#000000"
+ button_text_hi="#fdfcff"
+ tab_active="#727272"
+ tab_inactive="#535353"
+ tab_back="#404040ff"
+ tab_outline="#3c3c3c">
+ <panelcolors>
+ <ThemePanelColors header="#ffffff79"
+ back="#72727280"
+ show_header="FALSE"
+ show_back="FALSE">
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ </ThemeOutliner>
+ </outliner>
+ <info>
+ <ThemeInfo info_selected="#08c1ff"
+ info_selected_text="#ffffff"
+ info_error="#dc0000"
+ info_error_text="#000000"
+ info_warning="#dc8060"
+ info_warning_text="#000000"
+ info_info="#00aa00"
+ info_info_text="#000000"
+ info_debug="#c4c4c4"
+ info_debug_text="#000000">
+ <space>
+ <ThemeSpaceGeneric back="#9098a0"
+ title="#c8c6c9"
+ text="#333333"
+ text_hi="#ffffff"
+ header="#484848"
+ header_text="#888888"
+ header_text_hi="#ffffff"
+ button="#725864ff"
+ button_title="#f1c2d8"
+ button_text="#f0f0f0"
+ button_text_hi="#ffffff"
+ tab_active="#727272"
+ tab_inactive="#535353"
+ tab_back="#404040ff"
+ tab_outline="#3c3c3c">
+ <panelcolors>
+ <ThemePanelColors header="#ffffff79"
+ back="#72727280"
+ show_header="FALSE"
+ show_back="FALSE">
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ </ThemeInfo>
+ </info>
+ <user_preferences>
+ <ThemeUserPreferences>
+ <space>
+ <ThemeSpaceGeneric back="#484848"
+ title="#000000"
+ text="#ffffff"
+ text_hi="#ffffff"
+ header="#484848"
+ header_text="#000000"
+ header_text_hi="#fdffff"
+ button="#484848a7"
+ button_title="#000000"
+ button_text="#000000"
+ button_text_hi="#ffffff"
+ tab_active="#727272"
+ tab_inactive="#535353"
+ tab_back="#404040ff"
+ tab_outline="#3c3c3c">
+ <panelcolors>
+ <ThemePanelColors header="#ffffff79"
+ back="#72727280"
+ show_header="FALSE"
+ show_back="FALSE">
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ </ThemeUserPreferences>
+ </user_preferences>
+ <console>
+ <ThemeConsole line_output="#6080ff"
+ line_input="#ffffff"
+ line_info="#00aa00"
+ line_error="#dc6060"
+ cursor="#dc6060"
+ select="#ffffff30">
+ <space>
+ <ThemeSpaceGeneric back="#000000"
+ title="#000000"
+ text="#000000"
+ text_hi="#ffffff"
+ header="#484848"
+ header_text="#000000"
+ header_text_hi="#ffffff"
+ button="#727272ff"
+ button_title="#000000"
+ button_text="#000000"
+ button_text_hi="#ffffff"
+ tab_active="#727272"
+ tab_inactive="#535353"
+ tab_back="#404040ff"
+ tab_outline="#3c3c3c">
+ <panelcolors>
+ <ThemePanelColors header="#ffffff79"
+ back="#72727280"
+ show_header="FALSE"
+ show_back="FALSE">
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ </ThemeConsole>
+ </console>
+ <clip_editor>
+ <ThemeClipEditor gp_vertex="#000000"
+ gp_vertex_select="#000000"
+ gp_vertex_size="1"
+ marker_outline="#000000"
+ marker="#7f7f00"
+ active_marker="#ffffff"
+ selected_marker="#ffff00"
+ disabled_marker="#7f0000"
+ locked_marker="#7f7f7f"
+ path_before="#ff0000"
+ path_after="#0000ff"
+ frame_current="#60c040"
+ strips="#0c0a0a"
+ strips_selected="#ff8c00"
+ handle_free="#000000"
+ handle_auto="#909000"
+ handle_align="#803060"
+ handle_sel_free="#000000"
+ handle_sel_auto="#f0ff40"
+ handle_sel_align="#f090a0"
+ handle_auto_clamped="#000000"
+ handle_sel_auto_clamped="#000000"
+ handle_vertex="#000000"
+ handle_vertex_select="#ffff00"
+ handle_vertex_size="5">
+ <space>
+ <ThemeSpaceGeneric back="#40464e"
+ title="#000000"
+ text="#000000"
+ text_hi="#ffffff"
+ header="#484848"
+ header_text="#000000"
+ header_text_hi="#ffffff"
+ button="#48484880"
+ button_title="#000000"
+ button_text="#000000"
+ button_text_hi="#ffffff"
+ tab_active="#727272"
+ tab_inactive="#535353"
+ tab_back="#404040ff"
+ tab_outline="#3c3c3c">
+ <panelcolors>
+ <ThemePanelColors header="#ffffff79"
+ back="#72727280"
+ show_header="FALSE"
+ show_back="FALSE">
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ <space_list>
+ <ThemeSpaceListGeneric list="#666666"
+ list_title="#000000"
+ list_text="#000000"
+ list_text_hi="#ffffff">
+ </ThemeSpaceListGeneric>
+ </space_list>
+ </ThemeClipEditor>
+ </clip_editor>
+ <bone_color_sets>
+ <ThemeBoneColorSet normal="#9a0000"
+ select="#bd1111"
+ active="#f70a0a"
+ show_colored_constraints="FALSE">
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet normal="#f74018"
+ select="#f66913"
+ active="#fa9900"
+ show_colored_constraints="FALSE">
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet normal="#1e9109"
+ select="#59b70b"
+ active="#83ef1d"
+ show_colored_constraints="FALSE">
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet normal="#0a3694"
+ select="#3667df"
+ active="#5ec1ef"
+ show_colored_constraints="FALSE">
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet normal="#a9294e"
+ select="#c1416a"
+ active="#f05d91"
+ show_colored_constraints="FALSE">
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet normal="#430c78"
+ select="#543aa3"
+ active="#8764d5"
+ show_colored_constraints="FALSE">
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet normal="#24785a"
+ select="#3c9579"
+ active="#6fb6ab"
+ show_colored_constraints="FALSE">
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet normal="#4b707c"
+ select="#6a8691"
+ active="#9bc2cd"
+ show_colored_constraints="FALSE">
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet normal="#f4c90c"
+ select="#eec236"
+ active="#f3ff00"
+ show_colored_constraints="FALSE">
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet normal="#1e2024"
+ select="#484c56"
+ active="#ffffff"
+ show_colored_constraints="FALSE">
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet normal="#6f2f6a"
+ select="#9845be"
+ active="#d330d6"
+ show_colored_constraints="FALSE">
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet normal="#6c8e22"
+ select="#7fb022"
+ active="#bbef5b"
+ show_colored_constraints="FALSE">
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet normal="#8d8d8d"
+ select="#b0b0b0"
+ active="#dedede"
+ show_colored_constraints="FALSE">
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet normal="#834326"
+ select="#8b5811"
+ active="#bd6a11"
+ show_colored_constraints="FALSE">
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet normal="#08310e"
+ select="#1c430b"
+ active="#34622b"
+ show_colored_constraints="FALSE">
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet normal="#000000"
+ select="#000000"
+ active="#000000"
+ show_colored_constraints="FALSE">
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet normal="#000000"
+ select="#000000"
+ active="#000000"
+ show_colored_constraints="FALSE">
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet normal="#000000"
+ select="#000000"
+ active="#000000"
+ show_colored_constraints="FALSE">
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet normal="#000000"
+ select="#000000"
+ active="#000000"
+ show_colored_constraints="FALSE">
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet normal="#000000"
+ select="#000000"
+ active="#000000"
+ show_colored_constraints="FALSE">
+ </ThemeBoneColorSet>
+ </bone_color_sets>
+ </Theme>
+ <ThemeStyle>
+ <panel_title>
+ <ThemeFontStyle points="12"
+ font_kerning_style="FITTED"
+ shadow="1"
+ shadow_offset_x="0"
+ shadow_offset_y="-1"
+ shadow_alpha="0.15"
+ shadow_value="1">
+ </ThemeFontStyle>
+ </panel_title>
+ <widget_label>
+ <ThemeFontStyle points="11"
+ font_kerning_style="FITTED"
+ shadow="3"
+ shadow_offset_x="0"
+ shadow_offset_y="-1"
+ shadow_alpha="0.15"
+ shadow_value="1">
+ </ThemeFontStyle>
+ </widget_label>
+ <widget>
+ <ThemeFontStyle points="11"
+ font_kerning_style="FITTED"
+ shadow="0"
+ shadow_offset_x="0"
+ shadow_offset_y="0"
+ shadow_alpha="0.25"
+ shadow_value="0">
+ </ThemeFontStyle>
+ </widget>
+ </ThemeStyle>
+</bpy>
diff --git a/release/scripts/presets/interface_theme/science_lab.xml b/release/scripts/presets/interface_theme/science_lab.xml
new file mode 100644
index 00000000000..b767e4a837b
--- /dev/null
+++ b/release/scripts/presets/interface_theme/science_lab.xml
@@ -0,0 +1,1176 @@
+<bpy>
+ <Theme>
+ <user_interface>
+ <ThemeUserInterface menu_shadow_fac="0.5"
+ menu_shadow_width="12"
+ icon_file=""
+ icon_alpha="1"
+ widget_emboss="#ffffff05"
+ axis_x="#dc4800"
+ axis_y="#73dc00"
+ axis_z="#00c2ff">
+ <wcol_regular>
+ <ThemeWidgetColors outline="#191919"
+ inner="#6c6c6cff"
+ inner_sel="#678db2ff"
+ item="#191919ff"
+ text="#e6f1ff"
+ text_sel="#ffffff"
+ show_shaded="FALSE"
+ shadetop="0"
+ shadedown="0">
+ </ThemeWidgetColors>
+ </wcol_regular>
+ <wcol_tool>
+ <ThemeWidgetColors outline="#000000"
+ inner="#2b3944ff"
+ inner_sel="#678db2ff"
+ item="#1f313eff"
+ text="#e4e4e4"
+ text_sel="#ffffff"
+ show_shaded="FALSE"
+ shadetop="15"
+ shadedown="-15">
+ </ThemeWidgetColors>
+ </wcol_tool>
+ <wcol_radio>
+ <ThemeWidgetColors outline="#000000"
+ inner="#2b3944ff"
+ inner_sel="#5484afff"
+ item="#ffffffff"
+ text="#ffffff"
+ text_sel="#000000"
+ show_shaded="FALSE"
+ shadetop="-5"
+ shadedown="-20">
+ </ThemeWidgetColors>
+ </wcol_radio>
+ <wcol_text>
+ <ThemeWidgetColors outline="#191919"
+ inner="#526d80ff"
+ inner_sel="#1b1b1bff"
+ item="#597384ff"
+ text="#d6ebff"
+ text_sel="#ffffff"
+ show_shaded="FALSE"
+ shadetop="-24"
+ shadedown="9">
+ </ThemeWidgetColors>
+ </wcol_text>
+ <wcol_option>
+ <ThemeWidgetColors outline="#678db2"
+ inner="#171616ff"
+ inner_sel="#678db2ff"
+ item="#ffffffff"
+ text="#dcdcdc"
+ text_sel="#ffffff"
+ show_shaded="FALSE"
+ shadetop="15"
+ shadedown="-15">
+ </ThemeWidgetColors>
+ </wcol_option>
+ <wcol_toggle>
+ <ThemeWidgetColors outline="#555555"
+ inner="#2e2c2bff"
+ inner_sel="#678db2ff"
+ item="#191919ff"
+ text="#a4a4a4"
+ text_sel="#cbdaff"
+ show_shaded="FALSE"
+ shadetop="0"
+ shadedown="0">
+ </ThemeWidgetColors>
+ </wcol_toggle>
+ <wcol_num>
+ <ThemeWidgetColors outline="#000000"
+ inner="#2b3944ff"
+ inner_sel="#1b1b1bff"
+ item="#597384ff"
+ text="#99d3ff"
+ text_sel="#ffffff"
+ show_shaded="FALSE"
+ shadetop="-20"
+ shadedown="0">
+ </ThemeWidgetColors>
+ </wcol_num>
+ <wcol_numslider>
+ <ThemeWidgetColors outline="#292929"
+ inner="#333333ff"
+ inner_sel="#717171ff"
+ item="#678db2ff"
+ text="#dddddd"
+ text_sel="#ffffff"
+ show_shaded="TRUE"
+ shadetop="-20"
+ shadedown="0">
+ </ThemeWidgetColors>
+ </wcol_numslider>
+ <wcol_box>
+ <ThemeWidgetColors outline="#090909"
+ inner="#303030ff"
+ inner_sel="#678db2ff"
+ item="#191919ff"
+ text="#272727"
+ text_sel="#ffffff"
+ show_shaded="FALSE"
+ shadetop="0"
+ shadedown="0">
+ </ThemeWidgetColors>
+ </wcol_box>
+ <wcol_menu>
+ <ThemeWidgetColors outline="#292929"
+ inner="#38516aff"
+ inner_sel="#678db2ff"
+ item="#ffffffff"
+ text="#ffffff"
+ text_sel="#cccccc"
+ show_shaded="TRUE"
+ shadetop="10"
+ shadedown="-10">
+ </ThemeWidgetColors>
+ </wcol_menu>
+ <wcol_pulldown>
+ <ThemeWidgetColors outline="#000000"
+ inner="#3f3f3fff"
+ inner_sel="#678db2ff"
+ item="#ffffffff"
+ text="#dddddd"
+ text_sel="#000000"
+ show_shaded="FALSE"
+ shadetop="25"
+ shadedown="-20">
+ </ThemeWidgetColors>
+ </wcol_pulldown>
+ <wcol_menu_back>
+ <ThemeWidgetColors outline="#000000"
+ inner="#2f3a46e6"
+ inner_sel="#2d2d2de6"
+ item="#646464ff"
+ text="#a0a0a0"
+ text_sel="#ffffff"
+ show_shaded="FALSE"
+ shadetop="25"
+ shadedown="-20">
+ </ThemeWidgetColors>
+ </wcol_menu_back>
+ <wcol_pie_menu>
+ <ThemeWidgetColors outline="#59a3ff"
+ inner="#222222e6"
+ inner_sel="#8cc0f3ff"
+ item="#2c5e82ff"
+ text="#93c9ff"
+ text_sel="#ffffff"
+ show_shaded="FALSE"
+ shadetop="-20"
+ shadedown="17">
+ </ThemeWidgetColors>
+ </wcol_pie_menu>
+ <wcol_tooltip>
+ <ThemeWidgetColors outline="#000000"
+ inner="#2a2a2ae6"
+ inner_sel="#2d2d2de6"
+ item="#646464ff"
+ text="#ffffff"
+ text_sel="#ffffff"
+ show_shaded="FALSE"
+ shadetop="25"
+ shadedown="-20">
+ </ThemeWidgetColors>
+ </wcol_tooltip>
+ <wcol_menu_item>
+ <ThemeWidgetColors outline="#000000"
+ inner="#00000000"
+ inner_sel="#678db2ff"
+ item="#ffffffff"
+ text="#ffffff"
+ text_sel="#000000"
+ show_shaded="FALSE"
+ shadetop="38"
+ shadedown="0">
+ </ThemeWidgetColors>
+ </wcol_menu_item>
+ <wcol_scroll>
+ <ThemeWidgetColors outline="#000000"
+ inner="#12192250"
+ inner_sel="#646464b4"
+ item="#444444ff"
+ text="#e5e5e5"
+ text_sel="#ffffff"
+ show_shaded="TRUE"
+ shadetop="5"
+ shadedown="-5">
+ </ThemeWidgetColors>
+ </wcol_scroll>
+ <wcol_progress>
+ <ThemeWidgetColors outline="#000000"
+ inner="#8abe00ff"
+ inner_sel="#646464b4"
+ item="#444444ff"
+ text="#bbbbbb"
+ text_sel="#ffffff"
+ show_shaded="FALSE"
+ shadetop="0"
+ shadedown="0">
+ </ThemeWidgetColors>
+ </wcol_progress>
+ <wcol_list_item>
+ <ThemeWidgetColors outline="#485c6f"
+ inner="#00000000"
+ inner_sel="#678db2ff"
+ item="#000000ff"
+ text="#e5e5e5"
+ text_sel="#000000"
+ show_shaded="FALSE"
+ shadetop="0"
+ shadedown="0">
+ </ThemeWidgetColors>
+ </wcol_list_item>
+ <wcol_state>
+ <ThemeWidgetStateColors inner_anim="#73be4c"
+ inner_anim_sel="#5aa633"
+ inner_key="#f07e33"
+ inner_key_sel="#d7b600"
+ inner_driven="#b400ff"
+ inner_driven_sel="#9900e6"
+ blend="0.5">
+ </ThemeWidgetStateColors>
+ </wcol_state>
+ </ThemeUserInterface>
+ </user_interface>
+ <view_3d>
+ <ThemeView3D grid="#416064"
+ wire="#439ad2"
+ wire_edit="#7f7f7f"
+ gp_vertex="#000000"
+ gp_vertex_select="#ff8500"
+ gp_vertex_size="3"
+ lamp="#dbac00b9"
+ speaker="#229cd8"
+ camera="#e28400"
+ view_overlay="#666666"
+ empty="#87a6cd"
+ object_selected="#409aff"
+ object_active="#c0fffe"
+ object_grouped="#339443"
+ object_grouped_active="#84ff00"
+ transform="#ffffff"
+ vertex="#718485"
+ vertex_select="#e2b100"
+ vertex_size="6"
+ vertex_unreferenced="#464646"
+ edge_select="#8cd846"
+ edge_seam="#f65d00"
+ edge_sharp="#56fff8"
+ edge_crease="#6379d8"
+ edge_facesel="#4b4b4b"
+ freestyle_edge_mark="#ffc747"
+ face="#0c172761"
+ face_select="#4e7e9796"
+ face_dot="#fffbc1"
+ facedot_size="4"
+ freestyle_face_mark="#d9ff6e33"
+ nurb_uline="#909000"
+ nurb_vline="#803060"
+ nurb_sel_uline="#f0ff40"
+ nurb_sel_vline="#f090a0"
+ act_spline="#c4c4c2"
+ handle_free="#808080"
+ handle_auto="#09a800"
+ handle_vect="#8934d1"
+ handle_sel_vect="#e85bff"
+ handle_align="#d15f16"
+ handle_sel_free="#ffffff"
+ handle_sel_auto="#10f000"
+ handle_sel_align="#ffa947"
+ lastsel_point="#ffffff"
+ extra_edge_len="#adff0c"
+ extra_edge_angle="#84ebbf"
+ extra_face_angle="#ffe133"
+ extra_face_area="#fcff07"
+ editmesh_active="#e4ffebab"
+ normal="#22dddd"
+ vertex_normal="#2361dd"
+ split_normal="#dd23dd"
+ bone_solid="#2890e8"
+ bone_pose="#50c8ff"
+ bone_pose_active="#8cffff"
+ frame_current="#d0ddc4"
+ outline_width="2"
+ bundle_solid="#6e6e6e"
+ camera_path="#9f5500"
+ skin_root="#f1b66e"
+ clipping_border_3d="#313131ff"
+ paint_curve_handle="#7fff7f7f"
+ paint_curve_pivot="#ff7f7f7f">
+ <space>
+ <ThemeSpaceGradient title="#000000"
+ text="#000000"
+ text_hi="#ffffff"
+ header="#444444"
+ header_text="#000000"
+ header_text_hi="#ffffff"
+ button="#2d2d2d99"
+ button_title="#eff6ff"
+ button_text="#dddddd"
+ button_text_hi="#ffffff"
+ tab_active="#516882"
+ tab_inactive="#2d2d2d"
+ tab_back="#000000ff"
+ tab_outline="#3c3c3c">
+ <gradients>
+ <ThemeGradientColors show_grad="TRUE"
+ gradient="#3d4c5a"
+ high_gradient="#000000">
+ </ThemeGradientColors>
+ </gradients>
+ <panelcolors>
+ <ThemePanelColors header="#0000008e"
+ back="#44444480"
+ show_header="TRUE"
+ show_back="FALSE">
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGradient>
+ </space>
+ </ThemeView3D>
+ </view_3d>
+ <graph_editor>
+ <ThemeGraphEditor grid="#000000"
+ frame_current="#8b9483"
+ window_sliders="#adadad"
+ channels_region="#727272"
+ dopesheet_channel="#52606e"
+ dopesheet_subchannel="#7c8996"
+ channel_group="#395a86"
+ active_channels_group="#5193b1"
+ vertex="#94ca4c"
+ vertex_select="#ffffef"
+ vertex_size="6"
+ vertex_unreferenced="#000000"
+ handle_free="#808080"
+ handle_auto="#963417"
+ handle_vect="#8549b8"
+ handle_sel_vect="#c55eff"
+ handle_align="#b25014"
+ handle_sel_free="#ffffff"
+ handle_sel_auto="#ff6041"
+ handle_sel_align="#ffc094"
+ handle_auto_clamped="#09a800"
+ handle_sel_auto_clamped="#10f000"
+ lastsel_point="#ffffff"
+ handle_vertex="#84b836"
+ handle_vertex_select="#c4e8ff"
+ handle_vertex_size="10">
+ <space>
+ <ThemeSpaceGeneric back="#36434f"
+ title="#000000"
+ text="#000000"
+ text_hi="#ffffff"
+ header="#2f2f2f"
+ header_text="#000000"
+ header_text_hi="#ffffff"
+ button="#2d2d2dff"
+ button_title="#dddddd"
+ button_text="#ffffff"
+ button_text_hi="#ffffff"
+ tab_active="#727272"
+ tab_inactive="#646464"
+ tab_back="#464646ff"
+ tab_outline="#3c3c3c">
+ <panelcolors>
+ <ThemePanelColors header="#00000062"
+ back="#44444480"
+ show_header="TRUE"
+ show_back="FALSE">
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ <space_list>
+ <ThemeSpaceListGeneric list="#444444"
+ list_title="#000000"
+ list_text="#c6dbe9"
+ list_text_hi="#c6f4ed">
+ </ThemeSpaceListGeneric>
+ </space_list>
+ </ThemeGraphEditor>
+ </graph_editor>
+ <file_browser>
+ <ThemeFileBrowser selected_file="#517da1"
+ scrollbar="#a0a0a0"
+ scroll_handle="#7f7070"
+ active_file="#828282"
+ active_file_text="#fafafa">
+ <space>
+ <ThemeSpaceGeneric back="#363636"
+ title="#646464"
+ text="#beddff"
+ text_hi="#bdbdbd"
+ header="#4b4b4b"
+ header_text="#1d1d1d"
+ header_text_hi="#ffffff"
+ button="#313131ff"
+ button_title="#dddddd"
+ button_text="#dddddd"
+ button_text_hi="#ffffff"
+ tab_active="#727272"
+ tab_inactive="#646464"
+ tab_back="#464646ff"
+ tab_outline="#3c3c3c">
+ <panelcolors>
+ <ThemePanelColors header="#00000019"
+ back="#44444480"
+ show_header="FALSE"
+ show_back="FALSE">
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ <space_list>
+ <ThemeSpaceListGeneric list="#444444"
+ list_title="#c0c0c0"
+ list_text="#999999"
+ list_text_hi="#ffffff">
+ </ThemeSpaceListGeneric>
+ </space_list>
+ </ThemeFileBrowser>
+ </file_browser>
+ <nla_editor>
+ <ThemeNLAEditor grid="#5e5e5e"
+ view_sliders="#969696"
+ active_action="#cc701a66"
+ active_action_unset="#9373574d"
+ strips="#0c0a0a"
+ strips_selected="#af7200"
+ transition_strips="#1c2630"
+ transition_strips_selected="#2e75db"
+ meta_strips="#332642"
+ meta_strips_selected="#692196"
+ sound_strips="#2b3d3d"
+ sound_strips_selected="#1f7a7a"
+ tweak="#5d9030"
+ tweak_duplicate="#d90000"
+ keyframe_border="#f8ffe7ff"
+ keyframe_border_selected="#000000ff"
+ frame_current="#8b9483">
+ <space>
+ <ThemeSpaceGeneric back="#36434f"
+ title="#000000"
+ text="#000000"
+ text_hi="#ffffff"
+ header="#2f2f2f"
+ header_text="#000000"
+ header_text_hi="#ffffff"
+ button="#2d2d2dff"
+ button_title="#fcfcfc"
+ button_text="#dadada"
+ button_text_hi="#ffffff"
+ tab_active="#727272"
+ tab_inactive="#646464"
+ tab_back="#464646ff"
+ tab_outline="#3c3c3c">
+ <panelcolors>
+ <ThemePanelColors header="#00000019"
+ back="#44444480"
+ show_header="FALSE"
+ show_back="FALSE">
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ <space_list>
+ <ThemeSpaceListGeneric list="#444444"
+ list_title="#000000"
+ list_text="#c6dbe9"
+ list_text_hi="#ffffff">
+ </ThemeSpaceListGeneric>
+ </space_list>
+ </ThemeNLAEditor>
+ </nla_editor>
+ <dopesheet_editor>
+ <ThemeDopeSheet grid="#5e5e5e"
+ frame_current="#8b9483"
+ value_sliders="#000000"
+ view_sliders="#969696"
+ dopesheet_channel="#6d9648"
+ dopesheet_subchannel="#264972"
+ channels="#727272"
+ channels_selected="#e8f668"
+ channel_group="#395a86"
+ active_channels_group="#5193b1"
+ long_key="#99af48"
+ long_key_selected="#e2b100"
+ keyframe="#e8e8e8"
+ keyframe_selected="#8cd846"
+ keyframe_extreme="#e8b3cc"
+ keyframe_extreme_selected="#f23e0f"
+ keyframe_breakdown="#b3dbe8"
+ keyframe_breakdown_selected="#54bfed"
+ keyframe_jitter="#94e575"
+ keyframe_jitter_selected="#61c042"
+ keyframe_border="#2db653ff"
+ keyframe_border_selected="#000000ff"
+ summary="#7a663d66">
+ <space>
+ <ThemeSpaceGeneric back="#36434f"
+ title="#000000"
+ text="#000000"
+ text_hi="#ffffff"
+ header="#2f2f2f"
+ header_text="#000000"
+ header_text_hi="#ffffff"
+ button="#2d2d2dff"
+ button_title="#dddddd"
+ button_text="#dddddd"
+ button_text_hi="#ffffff"
+ tab_active="#727272"
+ tab_inactive="#646464"
+ tab_back="#464646ff"
+ tab_outline="#3c3c3c">
+ <panelcolors>
+ <ThemePanelColors header="#00000019"
+ back="#44444480"
+ show_header="FALSE"
+ show_back="FALSE">
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ <space_list>
+ <ThemeSpaceListGeneric list="#444444"
+ list_title="#000000"
+ list_text="#c6dbe9"
+ list_text_hi="#ffffff">
+ </ThemeSpaceListGeneric>
+ </space_list>
+ </ThemeDopeSheet>
+ </dopesheet_editor>
+ <image_editor>
+ <ThemeImageEditor gp_vertex="#000000"
+ gp_vertex_select="#ff8500"
+ gp_vertex_size="3"
+ vertex="#bcf7fa"
+ vertex_select="#ffc700"
+ vertex_size="5"
+ vertex_unreferenced="#000000"
+ face="#0c172761"
+ face_select="#63a0c1ba"
+ face_dot="#fffbc1"
+ facedot_size="5"
+ freestyle_face_mark="#00000000"
+ editmesh_active="#ffffff80"
+ wire_edit="#35effa"
+ edge_select="#8cd846"
+ scope_back="#666666ff"
+ preview_stitch_face="#1242b026"
+ preview_stitch_edge="#ff8500b2"
+ preview_stitch_vert="#ff85007f"
+ preview_stitch_stitchable="#00ff00ff"
+ preview_stitch_unstitchable="#ff0000ff"
+ preview_stitch_active="#e1d2c323"
+ uv_shadow="#707070ff"
+ uv_others="#606060ff"
+ frame_current="#60c040"
+ handle_free="#000000"
+ handle_auto="#909000"
+ handle_align="#803060"
+ handle_sel_free="#000000"
+ handle_sel_auto="#f0ff40"
+ handle_sel_align="#f090a0"
+ handle_auto_clamped="#10f000"
+ handle_sel_auto_clamped="#09a800"
+ handle_vertex="#000000"
+ handle_vertex_select="#ffff00"
+ handle_vertex_size="5"
+ paint_curve_handle="#7fff7f7f"
+ paint_curve_pivot="#ff7f7f7f">
+ <space>
+ <ThemeSpaceGeneric back="#353535"
+ title="#000000"
+ text="#000000"
+ text_hi="#ffffff"
+ header="#4b4b4b"
+ header_text="#000000"
+ header_text_hi="#ffffff"
+ button="#44444480"
+ button_title="#dddddd"
+ button_text="#dddddd"
+ button_text_hi="#ffffff"
+ tab_active="#727272"
+ tab_inactive="#646464"
+ tab_back="#464646ff"
+ tab_outline="#3c3c3c">
+ <panelcolors>
+ <ThemePanelColors header="#00000019"
+ back="#44444480"
+ show_header="FALSE"
+ show_back="FALSE">
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ </ThemeImageEditor>
+ </image_editor>
+ <sequence_editor>
+ <ThemeSequenceEditor gp_vertex="#000000"
+ gp_vertex_select="#ff8500"
+ gp_vertex_size="3"
+ grid="#404040"
+ window_sliders="#a0a0a0"
+ movie_strip="#516987"
+ movieclip_strip="#20208f"
+ image_strip="#6d5881"
+ scene_strip="#4e983e"
+ audio_strip="#2e8f8f"
+ effect_strip="#a9547c"
+ transition_strip="#a25f6f"
+ meta_strip="#6d9183"
+ frame_current="#60c040"
+ keyframe="#ff8500"
+ draw_action="#50c8ff"
+ preview_back="#000000">
+ <space>
+ <ThemeSpaceGeneric back="#666666"
+ title="#000000"
+ text="#000000"
+ text_hi="#ffffff"
+ header="#4b4b4b"
+ header_text="#000000"
+ header_text_hi="#ffffff"
+ button="#44444480"
+ button_title="#dddddd"
+ button_text="#dddddd"
+ button_text_hi="#ffffff"
+ tab_active="#727272"
+ tab_inactive="#646464"
+ tab_back="#464646ff"
+ tab_outline="#3c3c3c">
+ <panelcolors>
+ <ThemePanelColors header="#00000019"
+ back="#44444480"
+ show_header="FALSE"
+ show_back="FALSE">
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ </ThemeSequenceEditor>
+ </sequence_editor>
+ <properties>
+ <ThemeProperties>
+ <space>
+ <ThemeSpaceGeneric back="#444444"
+ title="#dddddd"
+ text="#cecece"
+ text_hi="#ffffff"
+ header="#383838"
+ header_text="#000000"
+ header_text_hi="#ffffff"
+ button="#444444ff"
+ button_title="#dddddd"
+ button_text="#dddddd"
+ button_text_hi="#ffffff"
+ tab_active="#727272"
+ tab_inactive="#646464"
+ tab_back="#383838ff"
+ tab_outline="#949494">
+ <panelcolors>
+ <ThemePanelColors header="#0000008e"
+ back="#0c1d3180"
+ show_header="TRUE"
+ show_back="FALSE">
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ </ThemeProperties>
+ </properties>
+ <text_editor>
+ <ThemeTextEditor line_numbers_background="#36434f"
+ selected_text="#73b4e9"
+ cursor="#74a8ff"
+ syntax_builtin="#e850a8"
+ syntax_symbols="#d7d7d7"
+ syntax_special="#5ed5f3"
+ syntax_preprocessor="#d50087"
+ syntax_reserved="#a74600"
+ syntax_comment="#567160"
+ syntax_string="#ceaf49"
+ syntax_numbers="#c661ff">
+ <space>
+ <ThemeSpaceGeneric back="#1c1c1c"
+ title="#000000"
+ text="#b3b3b3"
+ text_hi="#ffffff"
+ header="#4b4b4b"
+ header_text="#000000"
+ header_text_hi="#ffffff"
+ button="#444444ff"
+ button_title="#dddddd"
+ button_text="#dddddd"
+ button_text_hi="#ffffff"
+ tab_active="#727272"
+ tab_inactive="#646464"
+ tab_back="#464646ff"
+ tab_outline="#3c3c3c">
+ <panelcolors>
+ <ThemePanelColors header="#00000019"
+ back="#44444480"
+ show_header="FALSE"
+ show_back="FALSE">
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ </ThemeTextEditor>
+ </text_editor>
+ <timeline>
+ <ThemeTimeline grid="#5b5b5b"
+ frame_current="#bac6af"
+ time_keyframe="#ddd700"
+ time_grease_pencil="#b5e61d">
+ <space>
+ <ThemeSpaceGeneric back="#333333"
+ title="#000000"
+ text="#000000"
+ text_hi="#ffffff"
+ header="#4b4b4b"
+ header_text="#000000"
+ header_text_hi="#ffffff"
+ button="#222222ff"
+ button_title="#dddddd"
+ button_text="#dddddd"
+ button_text_hi="#ffffff"
+ tab_active="#727272"
+ tab_inactive="#646464"
+ tab_back="#464646ff"
+ tab_outline="#3c3c3c">
+ <panelcolors>
+ <ThemePanelColors header="#00000019"
+ back="#44444480"
+ show_header="FALSE"
+ show_back="FALSE">
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ </ThemeTimeline>
+ </timeline>
+ <node_editor>
+ <ThemeNodeEditor gp_vertex="#000000"
+ gp_vertex_select="#ff8500"
+ gp_vertex_size="3"
+ node_selected="#6ebdff"
+ node_active="#fefff3"
+ wire="#9effc5"
+ wire_inner="#737373"
+ wire_select="#99d9ff"
+ selected_text="#7f7070"
+ node_backdrop="#9b9b9bb9"
+ converter_node="#413172"
+ color_node="#882a5b"
+ group_node="#1d4e55"
+ group_socket_node="#006299"
+ frame_node="#9b9b9bb9"
+ matte_node="#b25750"
+ distor_node="#62afac"
+ noodle_curving="5"
+ input_node="#272727"
+ output_node="#5c9e54"
+ filter_node="#6c696f"
+ vector_node="#3250bd"
+ texture_node="#c77e08"
+ shader_node="#548ec0"
+ script_node="#3d2e97"
+ pattern_node="#6c696f"
+ layout_node="#6d92b3">
+ <space>
+ <ThemeSpaceGeneric back="#2b363f"
+ title="#000000"
+ text="#d2e7ff"
+ text_hi="#ffffff"
+ header="#444444"
+ header_text="#000000"
+ header_text_hi="#ffffff"
+ button="#444444ff"
+ button_title="#dddddd"
+ button_text="#dddddd"
+ button_text_hi="#ffffff"
+ tab_active="#727272"
+ tab_inactive="#646464"
+ tab_back="#464646ff"
+ tab_outline="#3c3c3c">
+ <panelcolors>
+ <ThemePanelColors header="#00000099"
+ back="#44444480"
+ show_header="TRUE"
+ show_back="FALSE">
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ <space_list>
+ <ThemeSpaceListGeneric list="#a5a5a5"
+ list_title="#000000"
+ list_text="#000000"
+ list_text_hi="#ffffff">
+ </ThemeSpaceListGeneric>
+ </space_list>
+ </ThemeNodeEditor>
+ </node_editor>
+ <logic_editor>
+ <ThemeLogicEditor>
+ <space>
+ <ThemeSpaceGeneric back="#36434f"
+ title="#000000"
+ text="#000000"
+ text_hi="#ffffff"
+ header="#4b4b4b"
+ header_text="#000000"
+ header_text_hi="#ffffff"
+ button="#444444ff"
+ button_title="#dddddd"
+ button_text="#dddddd"
+ button_text_hi="#ffffff"
+ tab_active="#727272"
+ tab_inactive="#646464"
+ tab_back="#464646ff"
+ tab_outline="#3c3c3c">
+ <panelcolors>
+ <ThemePanelColors header="#00000019"
+ back="#44444480"
+ show_header="FALSE"
+ show_back="FALSE">
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ </ThemeLogicEditor>
+ </logic_editor>
+ <outliner>
+ <ThemeOutliner match="#337f33"
+ selected_highlight="#32475a">
+ <space>
+ <ThemeSpaceGeneric back="#171717"
+ title="#4f4f4f"
+ text="#5e99cc"
+ text_hi="#d2eeff"
+ header="#383838"
+ header_text="#000000"
+ header_text_hi="#ffffff"
+ button="#727272ff"
+ button_title="#dddddd"
+ button_text="#dddddd"
+ button_text_hi="#ffffff"
+ tab_active="#7c7c7c"
+ tab_inactive="#000000"
+ tab_back="#282828ff"
+ tab_outline="#3f3f3f">
+ <panelcolors>
+ <ThemePanelColors header="#00000019"
+ back="#44444480"
+ show_header="FALSE"
+ show_back="FALSE">
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ </ThemeOutliner>
+ </outliner>
+ <info>
+ <ThemeInfo info_selected="#6080ff"
+ info_selected_text="#ffffff"
+ info_error="#dc0000"
+ info_error_text="#000000"
+ info_warning="#dc8060"
+ info_warning_text="#000000"
+ info_info="#00aa00"
+ info_info_text="#000000"
+ info_debug="#c4c4c4"
+ info_debug_text="#000000">
+ <space>
+ <ThemeSpaceGeneric back="#444444"
+ title="#1a1a1a"
+ text="#a8a8a8"
+ text_hi="#ffffff"
+ header="#4b4b4b"
+ header_text="#dddddd"
+ header_text_hi="#ffffff"
+ button="#727272ff"
+ button_title="#dddddd"
+ button_text="#dddddd"
+ button_text_hi="#ffffff"
+ tab_active="#727272"
+ tab_inactive="#646464"
+ tab_back="#464646ff"
+ tab_outline="#3c3c3c">
+ <panelcolors>
+ <ThemePanelColors header="#00000019"
+ back="#44444480"
+ show_header="FALSE"
+ show_back="FALSE">
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ </ThemeInfo>
+ </info>
+ <user_preferences>
+ <ThemeUserPreferences>
+ <space>
+ <ThemeSpaceGeneric back="#444444"
+ title="#000000"
+ text="#cbedff"
+ text_hi="#ffffff"
+ header="#444444"
+ header_text="#000000"
+ header_text_hi="#ffffff"
+ button="#444444ff"
+ button_title="#a0dfff"
+ button_text="#7d7d7d"
+ button_text_hi="#ffffff"
+ tab_active="#5c6982"
+ tab_inactive="#3f3f3f"
+ tab_back="#4c4c4cff"
+ tab_outline="#414141">
+ <panelcolors>
+ <ThemePanelColors header="#00000019"
+ back="#44444480"
+ show_header="FALSE"
+ show_back="FALSE">
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ </ThemeUserPreferences>
+ </user_preferences>
+ <console>
+ <ThemeConsole line_output="#6080ff"
+ line_input="#ffffff"
+ line_info="#00aa00"
+ line_error="#dc6060"
+ cursor="#dc6060"
+ select="#ffffff30">
+ <space>
+ <ThemeSpaceGeneric back="#000000"
+ title="#000000"
+ text="#000000"
+ text_hi="#ffffff"
+ header="#4b4b4b"
+ header_text="#000000"
+ header_text_hi="#ffffff"
+ button="#727272ff"
+ button_title="#dddddd"
+ button_text="#dddddd"
+ button_text_hi="#ffffff"
+ tab_active="#727272"
+ tab_inactive="#646464"
+ tab_back="#464646ff"
+ tab_outline="#3c3c3c">
+ <panelcolors>
+ <ThemePanelColors header="#00000019"
+ back="#44444480"
+ show_header="FALSE"
+ show_back="FALSE">
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ </ThemeConsole>
+ </console>
+ <clip_editor>
+ <ThemeClipEditor gp_vertex="#000000"
+ gp_vertex_select="#000000"
+ gp_vertex_size="1"
+ marker_outline="#000000"
+ marker="#7f7f00"
+ active_marker="#ffffff"
+ selected_marker="#ffff00"
+ disabled_marker="#7f0000"
+ locked_marker="#7f7f7f"
+ path_before="#ff0000"
+ path_after="#0000ff"
+ frame_current="#60c040"
+ strips="#0c0a0a"
+ strips_selected="#ff8c00"
+ handle_free="#000000"
+ handle_auto="#909000"
+ handle_align="#803060"
+ handle_sel_free="#000000"
+ handle_sel_auto="#f0ff40"
+ handle_sel_align="#f090a0"
+ handle_auto_clamped="#000000"
+ handle_sel_auto_clamped="#000000"
+ handle_vertex="#000000"
+ handle_vertex_select="#ffff00"
+ handle_vertex_size="5">
+ <space>
+ <ThemeSpaceGeneric back="#393939"
+ title="#000000"
+ text="#000000"
+ text_hi="#ffffff"
+ header="#414141"
+ header_text="#000000"
+ header_text_hi="#ffffff"
+ button="#44444480"
+ button_title="#000000"
+ button_text="#000000"
+ button_text_hi="#ffffff"
+ tab_active="#727272"
+ tab_inactive="#646464"
+ tab_back="#464646ff"
+ tab_outline="#3c3c3c">
+ <panelcolors>
+ <ThemePanelColors header="#00000019"
+ back="#44444480"
+ show_header="FALSE"
+ show_back="FALSE">
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ <space_list>
+ <ThemeSpaceListGeneric list="#666666"
+ list_title="#000000"
+ list_text="#000000"
+ list_text_hi="#ffffff">
+ </ThemeSpaceListGeneric>
+ </space_list>
+ </ThemeClipEditor>
+ </clip_editor>
+ <bone_color_sets>
+ <ThemeBoneColorSet normal="#9a0000"
+ select="#bd1111"
+ active="#f70a0a"
+ show_colored_constraints="TRUE">
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet normal="#f74018"
+ select="#f66913"
+ active="#fa9900"
+ show_colored_constraints="TRUE">
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet normal="#1e9109"
+ select="#59b70b"
+ active="#83ef1d"
+ show_colored_constraints="TRUE">
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet normal="#0a3694"
+ select="#3667df"
+ active="#5ec1ef"
+ show_colored_constraints="TRUE">
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet normal="#a9294e"
+ select="#c1416a"
+ active="#f05d91"
+ show_colored_constraints="TRUE">
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet normal="#430c78"
+ select="#543aa3"
+ active="#8764d5"
+ show_colored_constraints="TRUE">
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet normal="#24785a"
+ select="#3c9579"
+ active="#6fb6ab"
+ show_colored_constraints="TRUE">
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet normal="#4b707c"
+ select="#6a8691"
+ active="#9bc2cd"
+ show_colored_constraints="TRUE">
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet normal="#f4c90c"
+ select="#eec236"
+ active="#f3ff00"
+ show_colored_constraints="TRUE">
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet normal="#1e2024"
+ select="#484c56"
+ active="#ffffff"
+ show_colored_constraints="TRUE">
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet normal="#6f2f6a"
+ select="#9845be"
+ active="#d330d6"
+ show_colored_constraints="TRUE">
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet normal="#6c8e22"
+ select="#7fb022"
+ active="#bbef5b"
+ show_colored_constraints="TRUE">
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet normal="#8d8d8d"
+ select="#b0b0b0"
+ active="#dedede"
+ show_colored_constraints="TRUE">
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet normal="#834326"
+ select="#8b5811"
+ active="#bd6a11"
+ show_colored_constraints="TRUE">
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet normal="#08310e"
+ select="#1c430b"
+ active="#34622b"
+ show_colored_constraints="TRUE">
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet normal="#000000"
+ select="#000000"
+ active="#000000"
+ show_colored_constraints="FALSE">
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet normal="#000000"
+ select="#000000"
+ active="#000000"
+ show_colored_constraints="FALSE">
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet normal="#000000"
+ select="#000000"
+ active="#000000"
+ show_colored_constraints="FALSE">
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet normal="#000000"
+ select="#000000"
+ active="#000000"
+ show_colored_constraints="FALSE">
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet normal="#000000"
+ select="#000000"
+ active="#000000"
+ show_colored_constraints="FALSE">
+ </ThemeBoneColorSet>
+ </bone_color_sets>
+ </Theme>
+ <ThemeStyle>
+ <panel_title>
+ <ThemeFontStyle points="12"
+ font_kerning_style="FITTED"
+ shadow="1"
+ shadow_offset_x="0"
+ shadow_offset_y="-1"
+ shadow_alpha="0.15"
+ shadow_value="1">
+ </ThemeFontStyle>
+ </panel_title>
+ <widget_label>
+ <ThemeFontStyle points="11"
+ font_kerning_style="FITTED"
+ shadow="3"
+ shadow_offset_x="0"
+ shadow_offset_y="-1"
+ shadow_alpha="0.15"
+ shadow_value="1">
+ </ThemeFontStyle>
+ </widget_label>
+ <widget>
+ <ThemeFontStyle points="11"
+ font_kerning_style="FITTED"
+ shadow="0"
+ shadow_offset_x="0"
+ shadow_offset_y="0"
+ shadow_alpha="0.25"
+ shadow_value="0">
+ </ThemeFontStyle>
+ </widget>
+ </ThemeStyle>
+</bpy>
diff --git a/release/scripts/presets/interface_theme/softimage.xml b/release/scripts/presets/interface_theme/softimage.xml
new file mode 100644
index 00000000000..5b63a775680
--- /dev/null
+++ b/release/scripts/presets/interface_theme/softimage.xml
@@ -0,0 +1,1176 @@
+<bpy>
+ <Theme>
+ <user_interface>
+ <ThemeUserInterface menu_shadow_fac="0.5"
+ menu_shadow_width="12"
+ icon_file=""
+ icon_alpha="1"
+ widget_emboss="#ffffff05"
+ axis_x="#ff5a5a"
+ axis_y="#58ff58"
+ axis_z="#6262ff">
+ <wcol_regular>
+ <ThemeWidgetColors outline="#949190"
+ inner="#aca8a7ff"
+ inner_sel="#ffffffff"
+ item="#aca8a7ff"
+ text="#1a1a1a"
+ text_sel="#1a1a1a"
+ show_shaded="FALSE"
+ shadetop="-6"
+ shadedown="2">
+ </ThemeWidgetColors>
+ </wcol_regular>
+ <wcol_tool>
+ <ThemeWidgetColors outline="#969392"
+ inner="#8b99a3ff"
+ inner_sel="#abb9c5ff"
+ item="#aca8a7ff"
+ text="#000000"
+ text_sel="#ffffff"
+ show_shaded="TRUE"
+ shadetop="30"
+ shadedown="-3">
+ </ThemeWidgetColors>
+ </wcol_tool>
+ <wcol_radio>
+ <ThemeWidgetColors outline="#a7a7a7"
+ inner="#bfbfbfff"
+ inner_sel="#f8f8f8ff"
+ item="#aca8a7ff"
+ text="#000000"
+ text_sel="#000000"
+ show_shaded="FALSE"
+ shadetop="-2"
+ shadedown="1">
+ </ThemeWidgetColors>
+ </wcol_radio>
+ <wcol_text>
+ <ThemeWidgetColors outline="#989594"
+ inner="#8a888aff"
+ inner_sel="#919fa9ff"
+ item="#4849ceff"
+ text="#ffffff"
+ text_sel="#ffffff"
+ show_shaded="TRUE"
+ shadetop="-2"
+ shadedown="0">
+ </ThemeWidgetColors>
+ </wcol_text>
+ <wcol_option>
+ <ThemeWidgetColors outline="#383530"
+ inner="#9ab997ff"
+ inner_sel="#b4d8b1ff"
+ item="#000000ff"
+ text="#676767"
+ text_sel="#000000"
+ show_shaded="TRUE"
+ shadetop="-2"
+ shadedown="0">
+ </ThemeWidgetColors>
+ </wcol_option>
+ <wcol_toggle>
+ <ThemeWidgetColors outline="#888888"
+ inner="#aca8a5ff"
+ inner_sel="#ffffffff"
+ item="#aca8a7ff"
+ text="#1c1c1c"
+ text_sel="#1a1a1a"
+ show_shaded="TRUE"
+ shadetop="-3"
+ shadedown="0">
+ </ThemeWidgetColors>
+ </wcol_toggle>
+ <wcol_num>
+ <ThemeWidgetColors outline="#4b4b4b"
+ inner="#898789ff"
+ inner_sel="#93a0aaff"
+ item="#101010ff"
+ text="#ffffff"
+ text_sel="#ffffff"
+ show_shaded="FALSE"
+ shadetop="-5"
+ shadedown="5">
+ </ThemeWidgetColors>
+ </wcol_num>
+ <wcol_numslider>
+ <ThemeWidgetColors outline="#4b4b4b"
+ inner="#898789ff"
+ inner_sel="#93a0aaff"
+ item="#635c5fff"
+ text="#f9f9f9"
+ text_sel="#ffffff"
+ show_shaded="FALSE"
+ shadetop="-5"
+ shadedown="5">
+ </ThemeWidgetColors>
+ </wcol_numslider>
+ <wcol_box>
+ <ThemeWidgetColors outline="#aca8a7"
+ inner="#aca8a7ff"
+ inner_sel="#aaa8a6ff"
+ item="#ccccccff"
+ text="#474747"
+ text_sel="#ffffff"
+ show_shaded="FALSE"
+ shadetop="0"
+ shadedown="6">
+ </ThemeWidgetColors>
+ </wcol_box>
+ <wcol_menu>
+ <ThemeWidgetColors outline="#9a9796"
+ inner="#aca8a7ff"
+ inner_sel="#aca8a7ff"
+ item="#5c5a59ff"
+ text="#000000"
+ text_sel="#000000"
+ show_shaded="TRUE"
+ shadetop="0"
+ shadedown="0">
+ </ThemeWidgetColors>
+ </wcol_menu>
+ <wcol_pulldown>
+ <ThemeWidgetColors outline="#474747"
+ inner="#aaa8a6ff"
+ inner_sel="#aaa8a6ff"
+ item="#ccccccff"
+ text="#000000"
+ text_sel="#ffffff"
+ show_shaded="FALSE"
+ shadetop="25"
+ shadedown="-20">
+ </ThemeWidgetColors>
+ </wcol_pulldown>
+ <wcol_menu_back>
+ <ThemeWidgetColors outline="#474747"
+ inner="#aaa8a6ff"
+ inner_sel="#aaa8a6ff"
+ item="#ccccccff"
+ text="#000000"
+ text_sel="#ffffff"
+ show_shaded="FALSE"
+ shadetop="0"
+ shadedown="0">
+ </ThemeWidgetColors>
+ </wcol_menu_back>
+ <wcol_pie_menu>
+ <ThemeWidgetColors outline="#0a0a0a"
+ inner="#aca8a7ff"
+ inner_sel="#b1d1d8ff"
+ item="#b4d8b1ff"
+ text="#000000"
+ text_sel="#000000"
+ show_shaded="FALSE"
+ shadetop="10"
+ shadedown="-10">
+ </ThemeWidgetColors>
+ </wcol_pie_menu>
+ <wcol_tooltip>
+ <ThemeWidgetColors outline="#000000"
+ inner="#191919e6"
+ inner_sel="#2d2d2de6"
+ item="#646464ff"
+ text="#ffffff"
+ text_sel="#ffffff"
+ show_shaded="FALSE"
+ shadetop="25"
+ shadedown="-20">
+ </ThemeWidgetColors>
+ </wcol_tooltip>
+ <wcol_menu_item>
+ <ThemeWidgetColors outline="#474747"
+ inner="#00000000"
+ inner_sel="#aaa8a6ff"
+ item="#000000ff"
+ text="#000000"
+ text_sel="#ffffff"
+ show_shaded="TRUE"
+ shadetop="-10"
+ shadedown="10">
+ </ThemeWidgetColors>
+ </wcol_menu_item>
+ <wcol_scroll>
+ <ThemeWidgetColors outline="#82807f"
+ inner="#a4a2a0ff"
+ inner_sel="#aaa8a6ff"
+ item="#a2a19fff"
+ text="#000000"
+ text_sel="#ffffff"
+ show_shaded="TRUE"
+ shadetop="4"
+ shadedown="-5">
+ </ThemeWidgetColors>
+ </wcol_scroll>
+ <wcol_progress>
+ <ThemeWidgetColors outline="#474747"
+ inner="#aaa8a6ff"
+ inner_sel="#aaa8a6ff"
+ item="#96c78eff"
+ text="#000000"
+ text_sel="#ffffff"
+ show_shaded="TRUE"
+ shadetop="3"
+ shadedown="-3">
+ </ThemeWidgetColors>
+ </wcol_progress>
+ <wcol_list_item>
+ <ThemeWidgetColors outline="#aca8a7"
+ inner="#f1e59333"
+ inner_sel="#fff29c9a"
+ item="#ffffffff"
+ text="#000000"
+ text_sel="#000000"
+ show_shaded="FALSE"
+ shadetop="0"
+ shadedown="0">
+ </ThemeWidgetColors>
+ </wcol_list_item>
+ <wcol_state>
+ <ThemeWidgetStateColors inner_anim="#adb4c7"
+ inner_anim_sel="#c4cee0"
+ inner_key="#c0bb83"
+ inner_key_sel="#dad37d"
+ inner_driven="#c69cb1"
+ inner_driven_sel="#ecaacd"
+ blend="1">
+ </ThemeWidgetStateColors>
+ </wcol_state>
+ </ThemeUserInterface>
+ </user_interface>
+ <view_3d>
+ <ThemeView3D grid="#6b6b6b"
+ wire="#242424"
+ wire_edit="#000000"
+ gp_vertex="#000000"
+ gp_vertex_select="#ff8500"
+ gp_vertex_size="3"
+ lamp="#ffe56666"
+ speaker="#c2e787"
+ camera="#000000"
+ view_overlay="#000000"
+ empty="#000000"
+ object_selected="#ffffff"
+ object_active="#ffffff"
+ object_grouped="#000000"
+ object_grouped_active="#ffffff"
+ transform="#ffffff"
+ vertex="#343434"
+ vertex_select="#ff2f7a"
+ vertex_size="4"
+ vertex_unreferenced="#000000"
+ edge_select="#f3f3f3"
+ edge_seam="#f0703b"
+ edge_sharp="#49a1ec"
+ edge_crease="#eb3bdd"
+ edge_facesel="#272727"
+ freestyle_edge_mark="#7fff7f"
+ face="#90909099"
+ face_select="#a1a1a180"
+ face_dot="#52f27e"
+ facedot_size="4"
+ freestyle_face_mark="#7fff7f33"
+ nurb_uline="#a3a3a3"
+ nurb_vline="#d77ab1"
+ nurb_sel_uline="#ffffff"
+ nurb_sel_vline="#f090a0"
+ act_spline="#95daa0"
+ handle_free="#c6c6c6"
+ handle_auto="#30b6e5"
+ handle_vect="#afafaf"
+ handle_sel_vect="#ffffff"
+ handle_align="#e277b1"
+ handle_sel_free="#ffffff"
+ handle_sel_auto="#ffffff"
+ handle_sel_align="#ffffff"
+ lastsel_point="#ffffff"
+ extra_edge_len="#200000"
+ extra_edge_angle="#000000"
+ extra_face_angle="#cccccc"
+ extra_face_area="#cccccc"
+ editmesh_active="#ffffffb3"
+ normal="#9cfcc8"
+ vertex_normal="#68a1db"
+ split_normal="#dd23dd"
+ bone_solid="#c8c8c8"
+ bone_pose="#50c8ff"
+ bone_pose_active="#8cffff"
+ frame_current="#53c03b"
+ outline_width="1"
+ bundle_solid="#c8c8c8"
+ camera_path="#000000"
+ skin_root="#000000"
+ clipping_border_3d="#313131ff"
+ paint_curve_handle="#7fff7f7f"
+ paint_curve_pivot="#ff7f7f7f">
+ <space>
+ <ThemeSpaceGradient title="#ffffff"
+ text="#ffffff"
+ text_hi="#ffffff"
+ header="#aca8a7"
+ header_text="#000000"
+ header_text_hi="#ffffff"
+ button="#aaa8a6ff"
+ button_title="#313131"
+ button_text="#222222"
+ button_text_hi="#ffffff"
+ tab_active="#aca8a7"
+ tab_inactive="#bfbfbf"
+ tab_back="#bfbfbfff"
+ tab_outline="#d1cccb">
+ <gradients>
+ <ThemeGradientColors show_grad="FALSE"
+ gradient="#484848"
+ high_gradient="#7f7f7f">
+ </ThemeGradientColors>
+ </gradients>
+ <panelcolors>
+ <ThemePanelColors header="#00000004"
+ back="#72727280"
+ show_header="TRUE"
+ show_back="FALSE">
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGradient>
+ </space>
+ </ThemeView3D>
+ </view_3d>
+ <graph_editor>
+ <ThemeGraphEditor grid="#918d8c"
+ frame_current="#f06868"
+ window_sliders="#4d4d4d"
+ channels_region="#4d4d4d"
+ dopesheet_channel="#aaa8a6"
+ dopesheet_subchannel="#aaa8a6"
+ channel_group="#8a9dac"
+ active_channels_group="#95adc1"
+ vertex="#575757"
+ vertex_select="#ffffff"
+ vertex_size="6"
+ vertex_unreferenced="#000000"
+ handle_free="#252525"
+ handle_auto="#696969"
+ handle_vect="#191919"
+ handle_sel_vect="#ffffff"
+ handle_align="#1d1d1d"
+ handle_sel_free="#ececec"
+ handle_sel_auto="#d4d4d4"
+ handle_sel_align="#f3f3f3"
+ handle_auto_clamped="#000000"
+ handle_sel_auto_clamped="#000000"
+ lastsel_point="#000000"
+ handle_vertex="#525252"
+ handle_vertex_select="#f1f1f1"
+ handle_vertex_size="5">
+ <space>
+ <ThemeSpaceGeneric back="#aca8a7"
+ title="#000000"
+ text="#222222"
+ text_hi="#ffffff"
+ header="#aca8a7"
+ header_text="#000000"
+ header_text_hi="#ffffff"
+ button="#aca8a7ff"
+ button_title="#0e0e0e"
+ button_text="#222222"
+ button_text_hi="#ffffff"
+ tab_active="#aca8a7"
+ tab_inactive="#bfbfbf"
+ tab_back="#bfbfbfff"
+ tab_outline="#d1cccb">
+ <panelcolors>
+ <ThemePanelColors header="#00000004"
+ back="#72727280"
+ show_header="TRUE"
+ show_back="FALSE">
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ <space_list>
+ <ThemeSpaceListGeneric list="#aaa8a6"
+ list_title="#676767"
+ list_text="#222222"
+ list_text_hi="#ffffff">
+ </ThemeSpaceListGeneric>
+ </space_list>
+ </ThemeGraphEditor>
+ </graph_editor>
+ <file_browser>
+ <ThemeFileBrowser selected_file="#f1e593"
+ scrollbar="#4d4b4d"
+ scroll_handle="#8c8a88"
+ active_file="#f1e593"
+ active_file_text="#ffffff">
+ <space>
+ <ThemeSpaceGeneric back="#aca8a7"
+ title="#ffffff"
+ text="#222222"
+ text_hi="#ffffff"
+ header="#aca8a7"
+ header_text="#afafaf"
+ header_text_hi="#ffffff"
+ button="#aca8a7ff"
+ button_title="#222222"
+ button_text="#cccccc"
+ button_text_hi="#ffffff"
+ tab_active="#aca8a7"
+ tab_inactive="#bfbfbf"
+ tab_back="#bfbfbfff"
+ tab_outline="#d1cccb">
+ <panelcolors>
+ <ThemePanelColors header="#00000004"
+ back="#72727280"
+ show_header="TRUE"
+ show_back="FALSE">
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ <space_list>
+ <ThemeSpaceListGeneric list="#aaa8a6"
+ list_title="#3a3a3a"
+ list_text="#7f7f7f"
+ list_text_hi="#ffffff">
+ </ThemeSpaceListGeneric>
+ </space_list>
+ </ThemeFileBrowser>
+ </file_browser>
+ <nla_editor>
+ <ThemeNLAEditor grid="#918d8c"
+ view_sliders="#b5b5b5"
+ active_action="#ffffff00"
+ active_action_unset="#edad7545"
+ strips="#62be62"
+ strips_selected="#af7474"
+ transition_strips="#1800ff"
+ transition_strips_selected="#1800ff"
+ meta_strips="#1800ff"
+ meta_strips_selected="#1800ff"
+ sound_strips="#1800ff"
+ sound_strips_selected="#1800ff"
+ tweak="#1800ff"
+ tweak_duplicate="#6258ba"
+ keyframe_border="#e7eaa7ff"
+ keyframe_border_selected="#ffffffff"
+ frame_current="#f06868">
+ <space>
+ <ThemeSpaceGeneric back="#aca8a7"
+ title="#000000"
+ text="#333333"
+ text_hi="#000000"
+ header="#aca8a7"
+ header_text="#a3a3a3"
+ header_text_hi="#cccccc"
+ button="#aca8a7ff"
+ button_title="#000000"
+ button_text="#000000"
+ button_text_hi="#ffffff"
+ tab_active="#aca8a7"
+ tab_inactive="#bfbfbf"
+ tab_back="#bfbfbfff"
+ tab_outline="#ded8d7">
+ <panelcolors>
+ <ThemePanelColors header="#00000000"
+ back="#72727200"
+ show_header="TRUE"
+ show_back="FALSE">
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ <space_list>
+ <ThemeSpaceListGeneric list="#aca8a7"
+ list_title="#000000"
+ list_text="#000000"
+ list_text_hi="#000000">
+ </ThemeSpaceListGeneric>
+ </space_list>
+ </ThemeNLAEditor>
+ </nla_editor>
+ <dopesheet_editor>
+ <ThemeDopeSheet grid="#7f7f7f"
+ frame_current="#f06868"
+ value_sliders="#141414"
+ view_sliders="#4c4c4c"
+ dopesheet_channel="#9baeb9"
+ dopesheet_subchannel="#aaa8a6"
+ channels="#9baeb9"
+ channels_selected="#a0e7d9"
+ channel_group="#8a9dac"
+ active_channels_group="#95adc1"
+ long_key="#000000"
+ long_key_selected="#ecfc37"
+ keyframe="#bddae8"
+ keyframe_selected="#ffbe32"
+ keyframe_extreme="#e8b3cc"
+ keyframe_extreme_selected="#f28080"
+ keyframe_breakdown="#b3dbe8"
+ keyframe_breakdown_selected="#54bfed"
+ keyframe_jitter="#ace493"
+ keyframe_jitter_selected="#61c042"
+ keyframe_border="#000000ff"
+ keyframe_border_selected="#000000ff"
+ summary="#a4cbbb75">
+ <space>
+ <ThemeSpaceGeneric back="#aca8a7"
+ title="#ffffff"
+ text="#222222"
+ text_hi="#ffffff"
+ header="#aca8a7"
+ header_text="#000000"
+ header_text_hi="#ffffff"
+ button="#aca8a7ff"
+ button_title="#000000"
+ button_text="#111111"
+ button_text_hi="#a3a3a3"
+ tab_active="#aca8a7"
+ tab_inactive="#bfbfbf"
+ tab_back="#bfbfbfff"
+ tab_outline="#d1cccb">
+ <panelcolors>
+ <ThemePanelColors header="#00000004"
+ back="#72727280"
+ show_header="TRUE"
+ show_back="FALSE">
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ <space_list>
+ <ThemeSpaceListGeneric list="#aaa8a6"
+ list_title="#cccccc"
+ list_text="#131313"
+ list_text_hi="#ffffff">
+ </ThemeSpaceListGeneric>
+ </space_list>
+ </ThemeDopeSheet>
+ </dopesheet_editor>
+ <image_editor>
+ <ThemeImageEditor gp_vertex="#000000"
+ gp_vertex_select="#ff8500"
+ gp_vertex_size="3"
+ vertex="#000000"
+ vertex_select="#ffffff"
+ vertex_size="3"
+ vertex_unreferenced="#000000"
+ face="#00000032"
+ face_select="#ffffff3c"
+ face_dot="#ffffff"
+ facedot_size="2"
+ freestyle_face_mark="#00000000"
+ editmesh_active="#ffffff80"
+ wire_edit="#c0c0c0"
+ edge_select="#ff8500"
+ scope_back="#aca8a7ff"
+ preview_stitch_face="#1242b026"
+ preview_stitch_edge="#ff8500b2"
+ preview_stitch_vert="#ff85007f"
+ preview_stitch_stitchable="#00ff00ff"
+ preview_stitch_unstitchable="#ff0000ff"
+ preview_stitch_active="#e1d2c323"
+ uv_shadow="#707070ff"
+ uv_others="#606060ff"
+ frame_current="#60c040"
+ handle_free="#000000"
+ handle_auto="#909000"
+ handle_align="#803060"
+ handle_sel_free="#000000"
+ handle_sel_auto="#f0ff40"
+ handle_sel_align="#f090a0"
+ handle_auto_clamped="#000000"
+ handle_sel_auto_clamped="#000000"
+ handle_vertex="#000000"
+ handle_vertex_select="#ffff00"
+ handle_vertex_size="5"
+ paint_curve_handle="#7fff7f7f"
+ paint_curve_pivot="#ff7f7f7f">
+ <space>
+ <ThemeSpaceGeneric back="#aca8a7"
+ title="#000000"
+ text="#ffffff"
+ text_hi="#ffffff"
+ header="#aca8a7"
+ header_text="#000000"
+ header_text_hi="#ffffff"
+ button="#aca8a7ff"
+ button_title="#383838"
+ button_text="#222222"
+ button_text_hi="#ffffff"
+ tab_active="#aca8a7"
+ tab_inactive="#bfbfbf"
+ tab_back="#bfbfbfff"
+ tab_outline="#d1cccb">
+ <panelcolors>
+ <ThemePanelColors header="#00000004"
+ back="#72727280"
+ show_header="TRUE"
+ show_back="FALSE">
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ </ThemeImageEditor>
+ </image_editor>
+ <sequence_editor>
+ <ThemeSequenceEditor gp_vertex="#000000"
+ gp_vertex_select="#ff8500"
+ gp_vertex_size="3"
+ grid="#afafaf"
+ window_sliders="#777777"
+ movie_strip="#87a4c3"
+ movieclip_strip="#95add0"
+ image_strip="#c99ac0"
+ scene_strip="#91b1a0"
+ audio_strip="#e0d2a0"
+ effect_strip="#be8c76"
+ transition_strip="#d9777a"
+ meta_strip="#91918d"
+ frame_current="#a3ff96"
+ keyframe="#ffeb89"
+ draw_action="#50c8ff"
+ preview_back="#000000">
+ <space>
+ <ThemeSpaceGeneric back="#aca8a7"
+ title="#000000"
+ text="#333333"
+ text_hi="#ffffff"
+ header="#aca8a7"
+ header_text="#a3a3a3"
+ header_text_hi="#ffffff"
+ button="#aca8a7ff"
+ button_title="#111111"
+ button_text="#111111"
+ button_text_hi="#ffffff"
+ tab_active="#aca8a7"
+ tab_inactive="#bfbfbf"
+ tab_back="#bfbfbfff"
+ tab_outline="#d1cccb">
+ <panelcolors>
+ <ThemePanelColors header="#00000004"
+ back="#72727280"
+ show_header="TRUE"
+ show_back="FALSE">
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ </ThemeSequenceEditor>
+ </sequence_editor>
+ <properties>
+ <ThemeProperties>
+ <space>
+ <ThemeSpaceGeneric back="#aca8a7"
+ title="#222222"
+ text="#222222"
+ text_hi="#ffffff"
+ header="#d1cccb"
+ header_text="#222222"
+ header_text_hi="#000000"
+ button="#aca8a7ff"
+ button_title="#222222"
+ button_text="#222222"
+ button_text_hi="#ffffff"
+ tab_active="#aca8a7"
+ tab_inactive="#bfbfbf"
+ tab_back="#bfbfbfff"
+ tab_outline="#d1cccb">
+ <panelcolors>
+ <ThemePanelColors header="#00000004"
+ back="#72727280"
+ show_header="TRUE"
+ show_back="FALSE">
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ </ThemeProperties>
+ </properties>
+ <text_editor>
+ <ThemeTextEditor line_numbers_background="#a3a3a3"
+ selected_text="#f1e593"
+ cursor="#54da70"
+ syntax_builtin="#3162b2"
+ syntax_symbols="#4c4c4c"
+ syntax_special="#ca0c97"
+ syntax_preprocessor="#32008c"
+ syntax_reserved="#8c3c00"
+ syntax_comment="#535353"
+ syntax_string="#c31736"
+ syntax_numbers="#b62440">
+ <space>
+ <ThemeSpaceGeneric back="#aca8a7"
+ title="#000000"
+ text="#222222"
+ text_hi="#ffffff"
+ header="#aca8a7"
+ header_text="#000000"
+ header_text_hi="#ffffff"
+ button="#aca8a7ff"
+ button_title="#222222"
+ button_text="#333333"
+ button_text_hi="#ffffff"
+ tab_active="#aca8a7"
+ tab_inactive="#bfbfbf"
+ tab_back="#bfbfbfff"
+ tab_outline="#d1cccb">
+ <panelcolors>
+ <ThemePanelColors header="#00000004"
+ back="#72727280"
+ show_header="TRUE"
+ show_back="FALSE">
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ </ThemeTextEditor>
+ </text_editor>
+ <timeline>
+ <ThemeTimeline grid="#918d8c"
+ frame_current="#f06868"
+ time_keyframe="#ddd700"
+ time_grease_pencil="#b5e61d">
+ <space>
+ <ThemeSpaceGeneric back="#aca8a7"
+ title="#cccccc"
+ text="#3a3a3a"
+ text_hi="#ffffff"
+ header="#aca8a7"
+ header_text="#030303"
+ header_text_hi="#ffffff"
+ button="#aca8a7ff"
+ button_title="#aeacaa"
+ button_text="#222222"
+ button_text_hi="#000000"
+ tab_active="#aca8a7"
+ tab_inactive="#bfbfbf"
+ tab_back="#bfbfbfff"
+ tab_outline="#d1cccb">
+ <panelcolors>
+ <ThemePanelColors header="#00000004"
+ back="#72727280"
+ show_header="TRUE"
+ show_back="FALSE">
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ </ThemeTimeline>
+ </timeline>
+ <node_editor>
+ <ThemeNodeEditor gp_vertex="#000000"
+ gp_vertex_select="#ff8500"
+ gp_vertex_size="3"
+ node_selected="#ffffff"
+ node_active="#ffffff"
+ wire="#222222"
+ wire_inner="#737373"
+ wire_select="#ffffff"
+ selected_text="#ffffff"
+ node_backdrop="#d4d4d4ff"
+ converter_node="#e3a1ff"
+ color_node="#f2b077"
+ group_node="#aca8a7"
+ group_socket_node="#79bef2"
+ frame_node="#d3cecdff"
+ matte_node="#79f2a0"
+ distor_node="#eef279"
+ noodle_curving="5"
+ input_node="#79bef2"
+ output_node="#79bef2"
+ filter_node="#ff0000"
+ vector_node="#6de8e4"
+ texture_node="#f2b077"
+ shader_node="#e88daa"
+ script_node="#f2b077"
+ pattern_node="#a67c49"
+ layout_node="#000000">
+ <space>
+ <ThemeSpaceGeneric back="#aca8a7"
+ title="#a3a3a3"
+ text="#222222"
+ text_hi="#ffffff"
+ header="#aca8a7"
+ header_text="#333333"
+ header_text_hi="#ffffff"
+ button="#aca8a7ff"
+ button_title="#222222"
+ button_text="#222222"
+ button_text_hi="#c5c5c5"
+ tab_active="#aca8a7"
+ tab_inactive="#bfbfbf"
+ tab_back="#bfbfbfff"
+ tab_outline="#d1cccb">
+ <panelcolors>
+ <ThemePanelColors header="#00000004"
+ back="#72727280"
+ show_header="TRUE"
+ show_back="FALSE">
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ <space_list>
+ <ThemeSpaceListGeneric list="#4d4d4d"
+ list_title="#383838"
+ list_text="#676767"
+ list_text_hi="#ffffff">
+ </ThemeSpaceListGeneric>
+ </space_list>
+ </ThemeNodeEditor>
+ </node_editor>
+ <logic_editor>
+ <ThemeLogicEditor>
+ <space>
+ <ThemeSpaceGeneric back="#aca8a7"
+ title="#202020"
+ text="#222222"
+ text_hi="#ffffff"
+ header="#aca8a7"
+ header_text="#000000"
+ header_text_hi="#ffffff"
+ button="#aca8a7ff"
+ button_title="#111111"
+ button_text="#222222"
+ button_text_hi="#ffffff"
+ tab_active="#aca8a7"
+ tab_inactive="#bfbfbf"
+ tab_back="#bfbfbfff"
+ tab_outline="#d1cccb">
+ <panelcolors>
+ <ThemePanelColors header="#00000004"
+ back="#72727280"
+ show_header="TRUE"
+ show_back="FALSE">
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ </ThemeLogicEditor>
+ </logic_editor>
+ <outliner>
+ <ThemeOutliner match="#aff193"
+ selected_highlight="#98b5cf">
+ <space>
+ <ThemeSpaceGeneric back="#aca8a7"
+ title="#ffffff"
+ text="#000000"
+ text_hi="#ffffff"
+ header="#aca8a7"
+ header_text="#000000"
+ header_text_hi="#ffffff"
+ button="#aca8a7ff"
+ button_title="#0f0f0f"
+ button_text="#000000"
+ button_text_hi="#ffffff"
+ tab_active="#aca8a7"
+ tab_inactive="#bfbfbf"
+ tab_back="#bfbfbfff"
+ tab_outline="#d1cccb">
+ <panelcolors>
+ <ThemePanelColors header="#00000004"
+ back="#72727280"
+ show_header="TRUE"
+ show_back="FALSE">
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ </ThemeOutliner>
+ </outliner>
+ <info>
+ <ThemeInfo info_selected="#6080ff"
+ info_selected_text="#ffffff"
+ info_error="#dc0000"
+ info_error_text="#000000"
+ info_warning="#dc8060"
+ info_warning_text="#000000"
+ info_info="#00aa00"
+ info_info_text="#000000"
+ info_debug="#c4c4c4"
+ info_debug_text="#000000">
+ <space>
+ <ThemeSpaceGeneric back="#aca8a7"
+ title="#000000"
+ text="#000000"
+ text_hi="#ffffff"
+ header="#aca8a7"
+ header_text="#000000"
+ header_text_hi="#ffffff"
+ button="#aca8a7ff"
+ button_title="#000000"
+ button_text="#000000"
+ button_text_hi="#ffffff"
+ tab_active="#aca8a7"
+ tab_inactive="#bfbfbf"
+ tab_back="#bfbfbfff"
+ tab_outline="#d1cccb">
+ <panelcolors>
+ <ThemePanelColors header="#00000004"
+ back="#72727280"
+ show_header="TRUE"
+ show_back="FALSE">
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ </ThemeInfo>
+ </info>
+ <user_preferences>
+ <ThemeUserPreferences>
+ <space>
+ <ThemeSpaceGeneric back="#aca8a7"
+ title="#222222"
+ text="#222222"
+ text_hi="#ffffff"
+ header="#aca8a7"
+ header_text="#000000"
+ header_text_hi="#ffffff"
+ button="#aca8a7ff"
+ button_title="#000000"
+ button_text="#000000"
+ button_text_hi="#ffffff"
+ tab_active="#aca8a7"
+ tab_inactive="#bfbfbf"
+ tab_back="#bfbfbfff"
+ tab_outline="#d1cccb">
+ <panelcolors>
+ <ThemePanelColors header="#00000004"
+ back="#72727280"
+ show_header="TRUE"
+ show_back="FALSE">
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ </ThemeUserPreferences>
+ </user_preferences>
+ <console>
+ <ThemeConsole line_output="#6080ff"
+ line_input="#ffffff"
+ line_info="#00aa00"
+ line_error="#dc3a77"
+ cursor="#9cfcc8"
+ select="#ffffff30">
+ <space>
+ <ThemeSpaceGeneric back="#0c0c0c"
+ title="#000000"
+ text="#000000"
+ text_hi="#ffffff"
+ header="#aca8a7"
+ header_text="#000000"
+ header_text_hi="#ffffff"
+ button="#4d4d4dff"
+ button_title="#131313"
+ button_text="#131313"
+ button_text_hi="#ffffff"
+ tab_active="#aca8a7"
+ tab_inactive="#bfbfbf"
+ tab_back="#bfbfbfff"
+ tab_outline="#d1cccb">
+ <panelcolors>
+ <ThemePanelColors header="#00000004"
+ back="#72727280"
+ show_header="TRUE"
+ show_back="FALSE">
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ </ThemeConsole>
+ </console>
+ <clip_editor>
+ <ThemeClipEditor gp_vertex="#000000"
+ gp_vertex_select="#000000"
+ gp_vertex_size="1"
+ marker_outline="#000000"
+ marker="#71cd7f"
+ active_marker="#ffffff"
+ selected_marker="#ff2f7a"
+ disabled_marker="#b54636"
+ locked_marker="#7f7f7f"
+ path_before="#22d8d1"
+ path_after="#5a7575"
+ frame_current="#f06868"
+ strips="#0c0a0a"
+ strips_selected="#ff8c00"
+ handle_free="#000000"
+ handle_auto="#909000"
+ handle_align="#803060"
+ handle_sel_free="#000000"
+ handle_sel_auto="#f0ff40"
+ handle_sel_align="#f090a0"
+ handle_auto_clamped="#000000"
+ handle_sel_auto_clamped="#000000"
+ handle_vertex="#000000"
+ handle_vertex_select="#ffff00"
+ handle_vertex_size="5">
+ <space>
+ <ThemeSpaceGeneric back="#aca8a7"
+ title="#1a1a1a"
+ text="#1a1a1a"
+ text_hi="#ffffff"
+ header="#aca8a7"
+ header_text="#000000"
+ header_text_hi="#ffffff"
+ button="#aca8a7ff"
+ button_title="#222222"
+ button_text="#222222"
+ button_text_hi="#ffffff"
+ tab_active="#aca8a7"
+ tab_inactive="#bfbfbf"
+ tab_back="#bfbfbfff"
+ tab_outline="#d1cccb">
+ <panelcolors>
+ <ThemePanelColors header="#00000004"
+ back="#72727280"
+ show_header="TRUE"
+ show_back="FALSE">
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ <space_list>
+ <ThemeSpaceListGeneric list="#666666"
+ list_title="#000000"
+ list_text="#000000"
+ list_text_hi="#ffffff">
+ </ThemeSpaceListGeneric>
+ </space_list>
+ </ThemeClipEditor>
+ </clip_editor>
+ <bone_color_sets>
+ <ThemeBoneColorSet normal="#9a0000"
+ select="#bd1111"
+ active="#f70a0a"
+ show_colored_constraints="FALSE">
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet normal="#f74018"
+ select="#f66913"
+ active="#fa9900"
+ show_colored_constraints="FALSE">
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet normal="#1e9109"
+ select="#59b70b"
+ active="#83ef1d"
+ show_colored_constraints="FALSE">
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet normal="#0a3694"
+ select="#3667df"
+ active="#5ec1ef"
+ show_colored_constraints="FALSE">
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet normal="#a9294e"
+ select="#c1416a"
+ active="#f05d91"
+ show_colored_constraints="FALSE">
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet normal="#430c78"
+ select="#543aa3"
+ active="#8764d5"
+ show_colored_constraints="FALSE">
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet normal="#24785a"
+ select="#3c9579"
+ active="#6fb6ab"
+ show_colored_constraints="FALSE">
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet normal="#4b707c"
+ select="#6a8691"
+ active="#9bc2cd"
+ show_colored_constraints="FALSE">
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet normal="#f4c90c"
+ select="#eec236"
+ active="#f3ff00"
+ show_colored_constraints="FALSE">
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet normal="#1e2024"
+ select="#484c56"
+ active="#ffffff"
+ show_colored_constraints="FALSE">
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet normal="#6f2f6a"
+ select="#9845be"
+ active="#d330d6"
+ show_colored_constraints="FALSE">
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet normal="#6c8e22"
+ select="#7fb022"
+ active="#bbef5b"
+ show_colored_constraints="FALSE">
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet normal="#8d8d8d"
+ select="#b0b0b0"
+ active="#dedede"
+ show_colored_constraints="FALSE">
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet normal="#834326"
+ select="#8b5811"
+ active="#bd6a11"
+ show_colored_constraints="FALSE">
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet normal="#08310e"
+ select="#1c430b"
+ active="#34622b"
+ show_colored_constraints="FALSE">
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet normal="#000000"
+ select="#000000"
+ active="#000000"
+ show_colored_constraints="FALSE">
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet normal="#000000"
+ select="#000000"
+ active="#000000"
+ show_colored_constraints="FALSE">
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet normal="#000000"
+ select="#000000"
+ active="#000000"
+ show_colored_constraints="FALSE">
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet normal="#000000"
+ select="#000000"
+ active="#000000"
+ show_colored_constraints="FALSE">
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet normal="#000000"
+ select="#000000"
+ active="#000000"
+ show_colored_constraints="FALSE">
+ </ThemeBoneColorSet>
+ </bone_color_sets>
+ </Theme>
+ <ThemeStyle>
+ <panel_title>
+ <ThemeFontStyle points="12"
+ font_kerning_style="FITTED"
+ shadow="1"
+ shadow_offset_x="0"
+ shadow_offset_y="-1"
+ shadow_alpha="0.15"
+ shadow_value="1">
+ </ThemeFontStyle>
+ </panel_title>
+ <widget_label>
+ <ThemeFontStyle points="11"
+ font_kerning_style="FITTED"
+ shadow="3"
+ shadow_offset_x="0"
+ shadow_offset_y="-1"
+ shadow_alpha="0.15"
+ shadow_value="1">
+ </ThemeFontStyle>
+ </widget_label>
+ <widget>
+ <ThemeFontStyle points="11"
+ font_kerning_style="FITTED"
+ shadow="0"
+ shadow_offset_x="0"
+ shadow_offset_y="0"
+ shadow_alpha="0.25"
+ shadow_value="0">
+ </ThemeFontStyle>
+ </widget>
+ </ThemeStyle>
+</bpy>
diff --git a/release/scripts/presets/interface_theme/ubuntu_ambiance.xml b/release/scripts/presets/interface_theme/ubuntu_ambiance.xml
index 06d29a97745..d1c8b0a23ff 100644
--- a/release/scripts/presets/interface_theme/ubuntu_ambiance.xml
+++ b/release/scripts/presets/interface_theme/ubuntu_ambiance.xml
@@ -5,6 +5,7 @@
menu_shadow_width="12"
icon_file=""
icon_alpha="1"
+ widget_emboss="#ffffff05"
axis_x="#dc0000"
axis_y="#00dc00"
axis_z="#0000dc">
@@ -156,7 +157,7 @@
<ThemeWidgetColors outline="#0a0a0a"
inner="#191919e6"
inner_sel="#8c8c8cff"
- item="#2d2d2de6"
+ item="#6a3859e6"
text="#a0a0a0"
text_sel="#ffffff"
show_shaded="TRUE"
@@ -240,6 +241,9 @@
<ThemeView3D grid="#3c3b37"
wire="#93237f"
wire_edit="#93237f"
+ gp_vertex="#000000"
+ gp_vertex_select="#ff8500"
+ gp_vertex_size="3"
lamp="#ffffff34"
speaker="#93237f"
camera="#159dce"
@@ -286,6 +290,7 @@
editmesh_active="#ffffff80"
normal="#19b6ee"
vertex_normal="#19b6ee"
+ split_normal="#dd23dd"
bone_solid="#c8c8c8"
bone_pose="#50c8ff"
bone_pose_active="#8cffff"
@@ -294,6 +299,7 @@
bundle_solid="#c8c8c8"
camera_path="#7dbd00"
skin_root="#000000"
+ clipping_border_3d="#313131ff"
paint_curve_handle="#7fff7f7f"
paint_curve_pivot="#ff7f7f7f">
<space>
@@ -432,18 +438,18 @@
<nla_editor>
<ThemeNLAEditor grid="#5c5c52"
view_sliders="#969696"
- active_action="#00000000"
- active_action_unset="#00000000"
+ active_action="#cc701a66"
+ active_action_unset="#9987614d"
strips="#0c0a0a"
strips_selected="#6b395a"
- transition_strips="#000000"
- transition_strips_selected="#000000"
- meta_strips="#000000"
- meta_strips_selected="#000000"
- sound_strips="#000000"
- sound_strips_selected="#000000"
- tweak="#000000"
- tweak_duplicate="#000000"
+ transition_strips="#1c2630"
+ transition_strips_selected="#2e75db"
+ meta_strips="#332642"
+ meta_strips_selected="#692196"
+ sound_strips="#2b3d3d"
+ sound_strips_selected="#1f7a7a"
+ tweak="#4df31a"
+ tweak_duplicate="#d90000"
keyframe_border="#000000ff"
keyframe_border_selected="#000000ff"
frame_current="#f58032">
@@ -504,7 +510,7 @@
keyframe_jitter_selected="#61c042"
keyframe_border="#000000ff"
keyframe_border_selected="#000000ff"
- summary="#00000000">
+ summary="#cc701a66">
<space>
<ThemeSpaceGeneric back="#131311"
title="#9c9c9c"
@@ -540,7 +546,10 @@
</ThemeDopeSheet>
</dopesheet_editor>
<image_editor>
- <ThemeImageEditor vertex="#000000"
+ <ThemeImageEditor gp_vertex="#000000"
+ gp_vertex_select="#ff8500"
+ gp_vertex_size="3"
+ vertex="#000000"
vertex_select="#f47421"
vertex_size="3"
vertex_unreferenced="#000000"
@@ -603,7 +612,10 @@
</ThemeImageEditor>
</image_editor>
<sequence_editor>
- <ThemeSequenceEditor grid="#282828"
+ <ThemeSequenceEditor gp_vertex="#000000"
+ gp_vertex_select="#ff8500"
+ gp_vertex_size="3"
+ grid="#282828"
window_sliders="#a0a0a0"
movie_strip="#516987"
movieclip_strip="#20208f"
@@ -714,7 +726,9 @@
</text_editor>
<timeline>
<ThemeTimeline grid="#272727"
- frame_current="#f47421">
+ frame_current="#f47421"
+ time_keyframe="#ddd700"
+ time_grease_pencil="#b5e61d">
<space>
<ThemeSpaceGeneric back="#131311"
title="#000000"
@@ -743,9 +757,13 @@
</ThemeTimeline>
</timeline>
<node_editor>
- <ThemeNodeEditor node_selected="#ffffff"
+ <ThemeNodeEditor gp_vertex="#000000"
+ gp_vertex_select="#ff8500"
+ gp_vertex_size="3"
+ node_selected="#ffffff"
node_active="#ffffff"
wire="#f45b00"
+ wire_inner="#737373"
wire_select="#f4b696"
selected_text="#7f7070"
node_backdrop="#52524ed1"
@@ -961,7 +979,10 @@
</ThemeConsole>
</console>
<clip_editor>
- <ThemeClipEditor marker_outline="#000000"
+ <ThemeClipEditor gp_vertex="#000000"
+ gp_vertex_select="#000000"
+ gp_vertex_size="1"
+ marker_outline="#000000"
marker="#76243b"
active_marker="#ffffff"
selected_marker="#d5ff00"
@@ -969,7 +990,6 @@
locked_marker="#7f7f7f"
path_before="#ff5100"
path_after="#19b6ee"
- grid="#302e2c"
frame_current="#f47421"
strips="#0c0a0a"
strips_selected="#ff8c00"
diff --git a/release/scripts/presets/keyconfig/3dsmax.py b/release/scripts/presets/keyconfig/3dsmax.py
index f85d3b43041..7694e338d68 100644
--- a/release/scripts/presets/keyconfig/3dsmax.py
+++ b/release/scripts/presets/keyconfig/3dsmax.py
@@ -754,8 +754,6 @@ kmi = km.keymap_items.new('anim.channels_move', 'PAGE_DOWN', 'PRESS', shift=True
kmi.properties.direction = 'BOTTOM'
kmi = km.keymap_items.new('anim.channels_group', 'G', 'PRESS', ctrl=True)
kmi = km.keymap_items.new('anim.channels_ungroup', 'G', 'PRESS', alt=True)
-kmi = km.keymap_items.new('anim.channels_visibility_set', 'V', 'PRESS')
-kmi = km.keymap_items.new('anim.channels_visibility_toggle', 'V', 'PRESS', shift=True)
# Map UV Editor
km = kc.keymaps.new('UV Editor', space_type='EMPTY', region_type='WINDOW', modal=False)
@@ -1055,7 +1053,6 @@ kmi.properties.name = 'NODE_MT_add'
kmi = km.keymap_items.new('node.duplicate_move', 'D', 'PRESS', shift=True)
kmi = km.keymap_items.new('node.duplicate_move_keep_inputs', 'D', 'PRESS', shift=True, ctrl=True)
kmi = km.keymap_items.new('node.parent_set', 'P', 'PRESS', ctrl=True)
-kmi = km.keymap_items.new('node.parent_clear', 'P', 'PRESS', alt=True)
kmi = km.keymap_items.new('node.join', 'J', 'PRESS', ctrl=True)
kmi = km.keymap_items.new('node.hide_toggle', 'H', 'PRESS')
kmi = km.keymap_items.new('node.mute_toggle', 'M', 'PRESS')
diff --git a/release/scripts/presets/keyconfig/maya.py b/release/scripts/presets/keyconfig/maya.py
index 436541d85f8..cdd16f26877 100644
--- a/release/scripts/presets/keyconfig/maya.py
+++ b/release/scripts/presets/keyconfig/maya.py
@@ -142,9 +142,9 @@ kmi = km.keymap_items.new('screen.frame_offset', 'LEFT_ARROW', 'PRESS')
kmi.properties.delta = -1
kmi = km.keymap_items.new('screen.frame_offset', 'RIGHT_ARROW', 'PRESS')
kmi.properties.delta = 1
-kmi = km.keymap_items.new('screen.frame_offset', 'WHEELDOWNMOUSE', 'PRESS', alt=True)
+kmi = km.keymap_items.new('screen.frame_offset', 'WHEELDOWNMOUSE', 'PRESS', ctrl=True, alt=True)
kmi.properties.delta = 1
-kmi = km.keymap_items.new('screen.frame_offset', 'WHEELUPMOUSE', 'PRESS', alt=True)
+kmi = km.keymap_items.new('screen.frame_offset', 'WHEELUPMOUSE', 'PRESS', ctrl=True, alt=True)
kmi.properties.delta = -1
kmi = km.keymap_items.new('screen.frame_jump', 'V', 'PRESS', shift=True, alt=True)
kmi.properties.end = False
@@ -698,10 +698,10 @@ kmi.properties.level = 5
km = kc.keymaps.new('Knife Tool Modal Map', space_type='EMPTY', region_type='WINDOW', modal=True)
kmi = km.keymap_items.new_modal('CANCEL', 'ESC', 'ANY', any=True)
+kmi = km.keymap_items.new_modal('ADD_CUT', 'LEFTMOUSE', 'ANY')
kmi = km.keymap_items.new_modal('PANNING', 'LEFTMOUSE', 'ANY', alt=True)
kmi = km.keymap_items.new_modal('PANNING', 'MIDDLEMOUSE', 'ANY', alt=True)
kmi = km.keymap_items.new_modal('PANNING', 'RIGHTMOUSE', 'ANY', alt=True)
-kmi = km.keymap_items.new_modal('ADD_CUT', 'LEFTMOUSE', 'PRESS', any=True)
kmi = km.keymap_items.new_modal('CANCEL', 'RIGHTMOUSE', 'ANY')
kmi = km.keymap_items.new_modal('CONFIRM', 'RET', 'PRESS', any=True)
kmi = km.keymap_items.new_modal('CONFIRM', 'NUMPAD_ENTER', 'PRESS', any=True)
@@ -957,6 +957,10 @@ kmi = km.keymap_items.new('view3d.zoom', 'WHEELINMOUSE', 'PRESS')
kmi.properties.delta = 1
kmi = km.keymap_items.new('view3d.zoom', 'WHEELOUTMOUSE', 'PRESS')
kmi.properties.delta = -1
+kmi = km.keymap_items.new('view3d.zoom', 'WHEELINMOUSE', 'PRESS', alt=True)
+kmi.properties.delta = 1
+kmi = km.keymap_items.new('view3d.zoom', 'WHEELOUTMOUSE', 'PRESS', alt=True)
+kmi.properties.delta = -1
kmi = km.keymap_items.new('view3d.view_all', 'A', 'PRESS')
kmi.properties.center = False
kmi = km.keymap_items.new('view3d.viewnumpad', 'ZERO', 'PRESS', ctrl=True)
@@ -1133,8 +1137,6 @@ kmi = km.keymap_items.new('anim.channels_move', 'PAGE_UP', 'PRESS', shift=True)
kmi.properties.direction = 'TOP'
kmi = km.keymap_items.new('anim.channels_move', 'PAGE_DOWN', 'PRESS', shift=True)
kmi.properties.direction = 'BOTTOM'
-kmi = km.keymap_items.new('anim.channels_visibility_set', 'V', 'PRESS')
-kmi = km.keymap_items.new('anim.channels_visibility_toggle', 'V', 'PRESS', shift=True)
# Map UV Editor
km = kc.keymaps.new('UV Editor', space_type='EMPTY', region_type='WINDOW', modal=False)
@@ -1419,32 +1421,29 @@ kmi = km.keymap_items.new('object.mode_set', 'TAB', 'PRESS')
kmi.properties.mode = 'EDIT'
kmi.properties.toggle = True
kmi = km.keymap_items.new('wm.context_set_int', 'ONE', 'PRESS')
-kmi.properties.data_path = 'space_data.image.render_slot'
+kmi.properties.data_path = 'space_data.image.render_slots.active_index'
kmi.properties.value = 0
kmi = km.keymap_items.new('wm.context_set_int', 'TWO', 'PRESS')
-kmi.properties.data_path = 'space_data.image.render_slot'
+kmi.properties.data_path = 'space_data.image.render_slots.active_index'
kmi.properties.value = 1
kmi = km.keymap_items.new('wm.context_set_int', 'THREE', 'PRESS')
-kmi.properties.data_path = 'space_data.image.render_slot'
+kmi.properties.data_path = 'space_data.image.render_slots.active_index'
kmi.properties.value = 2
kmi = km.keymap_items.new('wm.context_set_int', 'FOUR', 'PRESS')
-kmi.properties.data_path = 'space_data.image.render_slot'
+kmi.properties.data_path = 'space_data.image.render_slots.active_index'
kmi.properties.value = 3
kmi = km.keymap_items.new('wm.context_set_int', 'FIVE', 'PRESS')
-kmi.properties.data_path = 'space_data.image.render_slot'
+kmi.properties.data_path = 'space_data.image.render_slots.active_index'
kmi.properties.value = 4
kmi = km.keymap_items.new('wm.context_set_int', 'SIX', 'PRESS')
-kmi.properties.data_path = 'space_data.image.render_slot'
+kmi.properties.data_path = 'space_data.image.render_slots.active_index'
kmi.properties.value = 5
kmi = km.keymap_items.new('wm.context_set_int', 'SEVEN', 'PRESS')
-kmi.properties.data_path = 'space_data.image.render_slot'
+kmi.properties.data_path = 'space_data.image.render_slots.active_index'
kmi.properties.value = 6
kmi = km.keymap_items.new('wm.context_set_int', 'EIGHT', 'PRESS')
-kmi.properties.data_path = 'space_data.image.render_slot'
+kmi.properties.data_path = 'space_data.image.render_slots.active_index'
kmi.properties.value = 7
-kmi = km.keymap_items.new('wm.context_set_int', 'NINE', 'PRESS')
-kmi.properties.data_path = 'space_data.image.render_slot'
-kmi.properties.value = 8
# Map Node Editor
km = kc.keymaps.new('Node Editor', space_type='NODE_EDITOR', region_type='WINDOW', modal=False)
@@ -1498,11 +1497,9 @@ kmi = km.keymap_items.new('node.group_edit', 'TAB', 'PRESS')
kmi = km.keymap_items.new('node.read_renderlayers', 'R', 'PRESS', ctrl=True)
kmi = km.keymap_items.new('node.read_fullsamplelayers', 'R', 'PRESS', shift=True)
kmi = km.keymap_items.new('node.render_changed', 'Z', 'PRESS')
-kmi = km.keymap_items.new('transform.translate', 'W', 'PRESS')
-kmi = km.keymap_items.new('transform.translate', 'EVT_TWEAK_A', 'ANY')
-kmi.properties.release_confirm = True
-kmi = km.keymap_items.new('transform.translate', 'EVT_TWEAK_S', 'ANY')
-kmi.properties.release_confirm = True
+kmi = km.keymap_items.new('node.translate_attach', 'W', 'PRESS')
+kmi = km.keymap_items.new('node.translate_attach', 'EVT_TWEAK_A', 'ANY')
+kmi = km.keymap_items.new('node.translate_attach', 'EVT_TWEAK_S', 'ANY')
kmi = km.keymap_items.new('transform.rotate', 'E', 'PRESS')
kmi = km.keymap_items.new('transform.resize', 'R', 'PRESS')
kmi = km.keymap_items.new('node.move_detach_links', 'D', 'PRESS', alt=True)
diff --git a/release/scripts/presets/safe_areas/14_colon_9_in_16_colon_9.py b/release/scripts/presets/safe_areas/14_colon_9_in_16_colon_9.py
new file mode 100644
index 00000000000..e486b413de8
--- /dev/null
+++ b/release/scripts/presets/safe_areas/14_colon_9_in_16_colon_9.py
@@ -0,0 +1,7 @@
+import bpy
+safe_areas = bpy.context.scene.safe_areas
+
+safe_areas.title = (0.035, 0.035)
+safe_areas.action = (0.1, 0.05)
+safe_areas.title_center = (0.15, 0.05)
+safe_areas.action_center = (0.1, 0.05)
diff --git a/release/scripts/presets/safe_areas/16_colon_9.py b/release/scripts/presets/safe_areas/16_colon_9.py
new file mode 100644
index 00000000000..221b8db84bd
--- /dev/null
+++ b/release/scripts/presets/safe_areas/16_colon_9.py
@@ -0,0 +1,7 @@
+import bpy
+safe_areas = bpy.context.scene.safe_areas
+
+safe_areas.title = (0.035, 0.035)
+safe_areas.action = (0.1, 0.05)
+safe_areas.title_center = (0.0, 0.0)
+safe_areas.action_center = (0.0, 0.0)
diff --git a/release/scripts/presets/safe_areas/4_colon_3_in_16_colon_9.py b/release/scripts/presets/safe_areas/4_colon_3_in_16_colon_9.py
new file mode 100644
index 00000000000..c10bc6cf285
--- /dev/null
+++ b/release/scripts/presets/safe_areas/4_colon_3_in_16_colon_9.py
@@ -0,0 +1,7 @@
+import bpy
+safe_areas = bpy.context.scene.safe_areas
+
+safe_areas.title = (0.035, 0.035)
+safe_areas.action = (0.1, 0.05)
+safe_areas.title_center = (0.175, 0.05)
+safe_areas.action_center = (0.15, 0.05)
diff --git a/release/scripts/startup/bl_operators/__init__.py b/release/scripts/startup/bl_operators/__init__.py
index e44fce63acd..35c7a55b6da 100644
--- a/release/scripts/startup/bl_operators/__init__.py
+++ b/release/scripts/startup/bl_operators/__init__.py
@@ -19,14 +19,16 @@
# <pep8 compliant>
if "bpy" in locals():
- from imp import reload as _reload
+ from importlib import reload
for val in _modules_loaded.values():
- _reload(val)
+ reload(val)
+ del reload
_modules = [
"add_mesh_torus",
"anim",
"clip",
"console",
+ "file",
"image",
"mask",
"mesh",
@@ -53,7 +55,7 @@ if bpy.app.build_options.freestyle:
_modules.append("freestyle")
__import__(name=__name__, fromlist=_modules)
_namespace = globals()
-_modules_loaded = {name: _namespace[name] for name in _modules if name != 'bpy'}
+_modules_loaded = {name: _namespace[name] for name in _modules if name != "bpy"}
del _namespace
diff --git a/release/scripts/startup/bl_operators/add_mesh_torus.py b/release/scripts/startup/bl_operators/add_mesh_torus.py
index 449a4cef1ef..82014c87be9 100644
--- a/release/scripts/startup/bl_operators/add_mesh_torus.py
+++ b/release/scripts/startup/bl_operators/add_mesh_torus.py
@@ -20,9 +20,10 @@
import bpy
from bpy.types import Operator
-from bpy.props import (FloatProperty,
- IntProperty,
- )
+from bpy.props import (
+ FloatProperty,
+ IntProperty,
+ )
from bpy.app.translations import pgettext_data as data_
from bpy_extras import object_utils
@@ -152,40 +153,40 @@ class AddTorus(Operator, object_utils.AddObjectHelper):
col = layout.column(align=True)
col.label(text="Location")
- col.prop(self, 'location', text="")
+ col.prop(self, "location", text="")
col = layout.column(align=True)
col.label(text="Rotation")
- col.prop(self, 'rotation', text="")
+ col.prop(self, "rotation", text="")
col = layout.column(align=True)
col.label(text="Major Segments")
- col.prop(self, 'major_segments', text="")
+ col.prop(self, "major_segments", text="")
col = layout.column(align=True)
col.label(text="Minor Segments")
- col.prop(self, 'minor_segments', text="")
+ col.prop(self, "minor_segments", text="")
col = layout.column(align=True)
col.label(text="Torus Dimensions")
- col.row().prop(self, 'mode', expand=True)
+ col.row().prop(self, "mode", expand=True)
if self.mode == 'MAJOR_MINOR':
col = layout.column(align=True)
col.label(text="Major Radius")
- col.prop(self, 'major_radius', text="")
+ col.prop(self, "major_radius", text="")
col = layout.column(align=True)
col.label(text="Minor Radius")
- col.prop(self, 'minor_radius', text="")
+ col.prop(self, "minor_radius", text="")
else:
col = layout.column(align=True)
col.label(text="Exterior Radius")
- col.prop(self, 'abso_major_rad', text="")
+ col.prop(self, "abso_major_rad", text="")
col = layout.column(align=True)
col.label(text="Interior Radius")
- col.prop(self, 'abso_minor_rad', text="")
+ col.prop(self, "abso_minor_rad", text="")
def invoke(self, context, event):
object_utils.object_add_grid_scale_apply_operator(self, context)
diff --git a/release/scripts/startup/bl_operators/anim.py b/release/scripts/startup/bl_operators/anim.py
index 756b75b8d03..f3575f26890 100644
--- a/release/scripts/startup/bl_operators/anim.py
+++ b/release/scripts/startup/bl_operators/anim.py
@@ -19,18 +19,20 @@
# <pep8-80 compliant>
if "bpy" in locals():
- import imp
+ from importlib import reload
if "anim_utils" in locals():
- imp.reload(anim_utils)
+ reload(anim_utils)
+ del reload
import bpy
from bpy.types import Operator
-from bpy.props import (IntProperty,
- BoolProperty,
- EnumProperty,
- StringProperty,
- )
+from bpy.props import (
+ IntProperty,
+ BoolProperty,
+ EnumProperty,
+ StringProperty,
+ )
class ANIM_OT_keying_set_export(Operator):
@@ -83,7 +85,9 @@ class ANIM_OT_keying_set_export(Operator):
f.write("ks.is_path_absolute = False\n")
f.write("\n")
- f.write("ks.bl_options = %r\n" % ks.bl_options)
+ f.write("ks.use_insertkey_needed = %s\n" % ks.use_insertkey_needed)
+ f.write("ks.use_insertkey_visual = %s\n" % ks.use_insertkey_visual)
+ f.write("ks.use_insertkey_xyz_to_rgb = %s\n" % ks.use_insertkey_xyz_to_rgb)
f.write("\n")
# --------------------------------------------------------
@@ -206,6 +210,12 @@ class BakeAction(Operator):
description="Bake animation onto the object then clear parents (objects only)",
default=False,
)
+ use_current_action = BoolProperty(
+ name="Overwrite Current Action",
+ description="Bake animation into current action, instead of creating a new one "
+ "(useful for baking only part of bones in an armature)",
+ default=False,
+ )
bake_types = EnumProperty(
name="Bake Data",
description="Which data's transformations to bake",
@@ -220,6 +230,12 @@ class BakeAction(Operator):
from bpy_extras import anim_utils
+ action = None
+ if self.use_current_action:
+ obj = context.object
+ if obj.animation_data:
+ action = obj.animation_data.action
+
action = anim_utils.bake_action(self.frame_start,
self.frame_end,
frame_step=self.step,
@@ -230,6 +246,7 @@ class BakeAction(Operator):
do_constraint_clear=self.clear_constraints,
do_parents_clear=self.clear_parents,
do_clean=True,
+ action=action,
)
if action is None:
diff --git a/release/scripts/startup/bl_operators/clip.py b/release/scripts/startup/bl_operators/clip.py
index 4ce300ecce2..0c77ea2ab7e 100644
--- a/release/scripts/startup/bl_operators/clip.py
+++ b/release/scripts/startup/bl_operators/clip.py
@@ -20,7 +20,7 @@
import bpy
import os
from bpy.types import Operator
-
+from bpy.props import FloatProperty
from mathutils import Vector, Matrix
@@ -124,6 +124,100 @@ def CLIP_default_settings_from_track(clip, track, framenr):
settings.default_weight = track.weight
+class CLIP_OT_filter_tracks(bpy.types.Operator):
+ """Filter tracks which has weirdly looking spikes in motion curves"""
+ bl_label = "Filter Tracks"
+ bl_idname = "clip.filter_tracks"
+ bl_options = {'UNDO', 'REGISTER'}
+
+ track_threshold = FloatProperty(
+ name="Track Threshold",
+ description="Filter Threshold to select problematic tracks",
+ default=5.0,
+ )
+
+ @staticmethod
+ def _filter_values(context, threshold):
+
+ def get_marker_coordinates_in_pixels(clip_size, track, frame_number):
+ marker = track.markers.find_frame(frame_number)
+ return Vector((marker.co[0] * clip_size[0], marker.co[1] * clip_size[1]))
+
+ def marker_velocity(clip_size, track, frame):
+ marker_a = get_marker_coordinates_in_pixels(clip_size, track, frame)
+ marker_b = get_marker_coordinates_in_pixels(clip_size, track, frame - 1)
+ return marker_a - marker_b
+
+ scene = context.scene
+ frame_start = scene.frame_start
+ frame_end = scene.frame_end
+ clip = context.space_data.clip
+ clip_size = clip.size[:]
+
+ bpy.ops.clip.clean_tracks(frames=10, action='DELETE_TRACK')
+
+ tracks_to_clean = set()
+
+ for frame in range(frame_start, frame_end + 1):
+
+ # Find tracks with markers in both this frame and the previous one.
+ relevant_tracks = [
+ track for track in clip.tracking.tracks
+ if (track.markers.find_frame(frame) and
+ track.markers.find_frame(frame - 1))]
+
+ if not relevant_tracks:
+ continue
+
+ # Get average velocity and deselect track.
+ average_velocity = Vector((0.0, 0.0))
+ for track in relevant_tracks:
+ track.select = False
+ average_velocity += marker_velocity(clip_size, track, frame)
+ if len(relevant_tracks) >= 1:
+ average_velocity = average_velocity / len(relevant_tracks)
+
+ # Then find all markers that behave differently than the average.
+ for track in relevant_tracks:
+ track_velocity = marker_velocity(clip_size, track, frame)
+ distance = (average_velocity - track_velocity).length
+
+ if distance > threshold:
+ tracks_to_clean.add(track)
+
+ for track in tracks_to_clean:
+ track.select = True
+ return len(tracks_to_clean)
+
+ @classmethod
+ def poll(cls, context):
+ space = context.space_data
+ return (space.type == 'CLIP_EDITOR') and space.clip
+
+ def execute(self, context):
+ num_tracks = self._filter_values(context, self.track_threshold)
+ self.report({'INFO'}, "Identified %d problematic tracks" % num_tracks)
+ return {'FINISHED'}
+
+
+class CLIP_OT_set_active_clip(bpy.types.Operator):
+ bl_label = "Set Active Clip"
+ bl_idname = "clip.set_active_clip"
+
+ @classmethod
+ def poll(cls, context):
+ space = context.space_data
+ return space.type == 'CLIP_EDITOR'
+
+ def execute(self, context):
+ clip = context.space_data.clip
+ scene = context.scene
+ scene.active_clip = clip
+ scene.render.resolution_x = clip.size[0]
+ scene.render.resolution_y = clip.size[1]
+ return {'FINISHED'}
+
+
class CLIP_OT_track_to_empty(Operator):
"""Create an Empty object which will be copying movement of active track"""
@@ -131,7 +225,8 @@ class CLIP_OT_track_to_empty(Operator):
bl_label = "Link Empty to Track"
bl_options = {'UNDO', 'REGISTER'}
- def _link_track(self, context, clip, tracking_object, track):
+ @staticmethod
+ def _link_track(context, clip, tracking_object, track):
sc = context.space_data
constraint = None
ob = None
@@ -237,7 +332,8 @@ class CLIP_OT_delete_proxy(Operator):
return wm.invoke_confirm(self, event)
- def _rmproxy(self, abspath):
+ @staticmethod
+ def _rmproxy(abspath):
import shutil
if not os.path.exists(abspath):
@@ -458,8 +554,8 @@ class CLIP_OT_setup_tracking_scene(Operator):
world.light_settings.sample_method = 'ADAPTIVE_QMC'
world.light_settings.samples = 7
world.light_settings.threshold = 0.005
- if hasattr(scene, 'cycles'):
- world.light_settings.ao_factor = 0.05
+ if hasattr(scene, "cycles"):
+ world.light_settings.ao_factor = 0.05
@staticmethod
def _findOrCreateCamera(context):
@@ -747,7 +843,7 @@ class CLIP_OT_setup_tracking_scene(Operator):
self._offsetNodes(tree)
scene.render.alpha_mode = 'TRANSPARENT'
- if hasattr(scene, 'cycles'):
+ if hasattr(scene, "cycles"):
scene.cycles.film_transparent = True
@staticmethod
@@ -920,3 +1016,58 @@ class CLIP_OT_track_settings_as_default(Operator):
CLIP_default_settings_from_track(clip, track, framenr)
return {'FINISHED'}
+
+
+class CLIP_OT_track_settings_to_track(bpy.types.Operator):
+ """Copy tracking settings from active track to selected tracks"""
+
+ bl_label = "Copy Track Settings"
+ bl_idname = "clip.track_settings_to_track"
+ bl_options = {'UNDO', 'REGISTER'}
+
+ _attrs_track = (
+ "correlation_min",
+ "frames_limit",
+ "pattern_match",
+ "margin",
+ "motion_model",
+ "use_brute",
+ "use_normalization",
+ "use_mask",
+ "use_red_channel",
+ "use_green_channel",
+ "use_blue_channel",
+ "weight"
+ )
+
+ _attrs_marker = (
+ "pattern_corners",
+ "search_min",
+ "search_max",
+ )
+
+ @classmethod
+ def poll(cls, context):
+ space = context.space_data
+ if space.type != 'CLIP_EDITOR':
+ return False
+ clip = space.clip
+ return clip and clip.tracking.tracks.active
+
+ def execute(self, context):
+ space = context.space_data
+ clip = space.clip
+ track = clip.tracking.tracks.active
+
+ framenr = context.scene.frame_current - clip.frame_start + 1
+ marker = track.markers.find_frame(framenr, False)
+
+ for t in clip.tracking.tracks:
+ if t.select and t != track:
+ marker_selected = t.markers.find_frame(framenr, False)
+ for attr in self._attrs_track:
+ setattr(t, attr, getattr(track, attr))
+ for attr in self._attrs_marker:
+ setattr(marker_selected, attr, getattr(marker, attr))
+
+ return {'FINISHED'}
diff --git a/release/scripts/startup/bl_operators/console.py b/release/scripts/startup/bl_operators/console.py
index 4e99acd4f36..8cfc977294a 100644
--- a/release/scripts/startup/bl_operators/console.py
+++ b/release/scripts/startup/bl_operators/console.py
@@ -20,9 +20,10 @@
import bpy
from bpy.types import Operator
-from bpy.props import (BoolProperty,
- StringProperty,
- )
+from bpy.props import (
+ BoolProperty,
+ StringProperty,
+ )
def _lang_module_get(sc):
diff --git a/release/scripts/startup/bl_operators/file.py b/release/scripts/startup/bl_operators/file.py
new file mode 100644
index 00000000000..efcc7d5c65e
--- /dev/null
+++ b/release/scripts/startup/bl_operators/file.py
@@ -0,0 +1,244 @@
+# ##### 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 #####
+
+# <pep8 compliant>
+
+import bpy
+from bpy.types import Operator
+from bpy.props import (
+ StringProperty,
+ BoolProperty,
+ CollectionProperty,
+ )
+
+# ########## Datablock previews... ##########
+
+
+class WM_OT_previews_batch_generate(Operator):
+ """Generate selected .blend file's previews"""
+ bl_idname = "wm.previews_batch_generate"
+ bl_label = "Batch-Generate Previews"
+ bl_options = {'REGISTER'}
+
+ # -----------
+ # File props.
+ files = CollectionProperty(
+ type=bpy.types.OperatorFileListElement,
+ options={'HIDDEN', 'SKIP_SAVE'},
+ )
+
+ directory = StringProperty(
+ maxlen=1024,
+ subtype='FILE_PATH',
+ options={'HIDDEN', 'SKIP_SAVE'},
+ )
+
+ # Show only images/videos, and directories!
+ filter_blender = BoolProperty(
+ default=True,
+ options={'HIDDEN', 'SKIP_SAVE'},
+ )
+ filter_folder = BoolProperty(
+ default=True,
+ options={'HIDDEN', 'SKIP_SAVE'},
+ )
+
+ # -----------
+ # Own props.
+ use_scenes = BoolProperty(
+ default=True,
+ name="Scenes",
+ description="Generate scenes' previews",
+ )
+ use_groups = BoolProperty(
+ default=True,
+ name="Groups",
+ description="Generate groups' previews",
+ )
+ use_objects = BoolProperty(
+ default=True,
+ name="Objects",
+ description="Generate objects' previews",
+ )
+ use_intern_data = BoolProperty(
+ default=True,
+ name="Mat/Tex/...",
+ description="Generate 'internal' previews (materials, textures, images, etc.)",
+ )
+
+ use_trusted = BoolProperty(
+ default=False,
+ name="Trusted Blend Files",
+ description="Enable python evaluation for selected files",
+ )
+
+ def invoke(self, context, event):
+ context.window_manager.fileselect_add(self)
+ return {'RUNNING_MODAL'}
+
+ def execute(self, context):
+ if "subprocess" in locals():
+ import imp
+ imp.reload(preview_render)
+ else:
+ import os
+ import subprocess
+ from bl_previews_utils import bl_previews_render as preview_render
+
+ context.window_manager.progress_begin(0, len(self.files))
+ context.window_manager.progress_update(0)
+ for i, fn in enumerate(self.files):
+ blen_path = os.path.join(self.directory, fn.name)
+ cmd = [
+ bpy.app.binary_path,
+ "--background",
+ "--factory-startup",
+ "-noaudio",
+ ]
+ if self.use_trusted:
+ cmd.append("--enable-autoexec")
+ cmd.extend([
+ blen_path,
+ "--python",
+ os.path.join(os.path.dirname(preview_render.__file__), "bl_previews_render.py"),
+ "--",
+ ])
+ if not self.use_scenes:
+ cmd.append('--no_scenes')
+ if not self.use_groups:
+ cmd.append('--no_groups')
+ if not self.use_objects:
+ cmd.append('--no_objects')
+ if not self.use_intern_data:
+ cmd.append('--no_data_intern')
+ if subprocess.call(cmd):
+ self.report({'ERROR'}, "Previews generation process failed for file '%s'!" % blen_path)
+ context.window_manager.progress_end()
+ return {'CANCELLED'}
+ context.window_manager.progress_update(i + 1)
+ context.window_manager.progress_end()
+
+ return {'FINISHED'}
+
+
+class WM_OT_previews_batch_clear(Operator):
+ """Clear selected .blend file's previews"""
+ bl_idname = "wm.previews_batch_clear"
+ bl_label = "Batch-Clear Previews"
+ bl_options = {'REGISTER'}
+
+ # -----------
+ # File props.
+ files = CollectionProperty(
+ type=bpy.types.OperatorFileListElement,
+ options={'HIDDEN', 'SKIP_SAVE'},
+ )
+
+ directory = StringProperty(
+ maxlen=1024,
+ subtype='FILE_PATH',
+ options={'HIDDEN', 'SKIP_SAVE'},
+ )
+
+ # Show only images/videos, and directories!
+ filter_blender = BoolProperty(
+ default=True,
+ options={'HIDDEN', 'SKIP_SAVE'},
+ )
+ filter_folder = BoolProperty(
+ default=True,
+ options={'HIDDEN', 'SKIP_SAVE'},
+ )
+
+ # -----------
+ # Own props.
+ use_scenes = BoolProperty(
+ default=True,
+ name="Scenes",
+ description="Clear scenes' previews",
+ )
+ use_groups = BoolProperty(default=True,
+ name="Groups",
+ description="Clear groups' previews",
+ )
+ use_objects = BoolProperty(
+ default=True,
+ name="Objects",
+ description="Clear objects' previews",
+ )
+ use_intern_data = BoolProperty(
+ default=True,
+ name="Mat/Tex/...",
+ description="Clear 'internal' previews (materials, textures, images, etc.)",
+ )
+
+ use_trusted = BoolProperty(
+ default=False,
+ name="Trusted Blend Files",
+ description="Enable python evaluation for selected files",
+ )
+
+ def invoke(self, context, event):
+ context.window_manager.fileselect_add(self)
+ return {'RUNNING_MODAL'}
+
+ def execute(self, context):
+ if "subprocess" in locals():
+ import imp
+ imp.reload(preview_render)
+ else:
+ import os
+ import subprocess
+ from bl_previews_utils import bl_previews_render as preview_render
+
+ context.window_manager.progress_begin(0, len(self.files))
+ context.window_manager.progress_update(0)
+ for i, fn in enumerate(self.files):
+ blen_path = os.path.join(self.directory, fn.name)
+ cmd = [
+ bpy.app.binary_path,
+ "--background",
+ "--factory-startup",
+ "-noaudio",
+ ]
+ if self.use_trusted:
+ cmd.append("--enable-autoexec")
+ cmd.extend([
+ blen_path,
+ "--python",
+ os.path.join(os.path.dirname(preview_render.__file__), "bl_previews_render.py"),
+ "--",
+ "--clear",
+ ])
+ if not self.use_scenes:
+ cmd.append('--no_scenes')
+ if not self.use_groups:
+ cmd.append('--no_groups')
+ if not self.use_objects:
+ cmd.append('--no_objects')
+ if not self.use_intern_data:
+ cmd.append('--no_data_intern')
+ if subprocess.call(cmd):
+ self.report({'ERROR'}, "Previews clear process failed for file '%s'!" % blen_path)
+ context.window_manager.progress_end()
+ return {'CANCELLED'}
+ context.window_manager.progress_update(i + 1)
+ context.window_manager.progress_end()
+
+ return {'FINISHED'}
+
diff --git a/release/scripts/startup/bl_operators/freestyle.py b/release/scripts/startup/bl_operators/freestyle.py
index 453be519abf..edda92284d2 100644
--- a/release/scripts/startup/bl_operators/freestyle.py
+++ b/release/scripts/startup/bl_operators/freestyle.py
@@ -16,10 +16,13 @@
#
# ##### END GPL LICENSE BLOCK #####
-import sys
import bpy
-from bpy.props import (BoolProperty, EnumProperty, StringProperty)
+from bpy.props import (
+ BoolProperty,
+ EnumProperty,
+ StringProperty,
+ )
class SCENE_OT_freestyle_fill_range_by_selection(bpy.types.Operator):
@@ -29,11 +32,16 @@ class SCENE_OT_freestyle_fill_range_by_selection(bpy.types.Operator):
bl_label = "Fill Range by Selection"
bl_options = {'INTERNAL'}
- type = EnumProperty(name="Type", description="Type of the modifier to work on",
- items=(("COLOR", "Color", "Color modifier type"),
- ("ALPHA", "Alpha", "Alpha modifier type"),
- ("THICKNESS", "Thickness", "Thickness modifier type")))
- name = StringProperty(name="Name", description="Name of the modifier to work on")
+ type = EnumProperty(
+ name="Type", description="Type of the modifier to work on",
+ items=(("COLOR", "Color", "Color modifier type"),
+ ("ALPHA", "Alpha", "Alpha modifier type"),
+ ("THICKNESS", "Thickness", "Thickness modifier type")),
+ )
+ name = StringProperty(
+ name="Name",
+ description="Name of the modifier to work on",
+ )
@classmethod
def poll(cls, context):
@@ -41,6 +49,8 @@ class SCENE_OT_freestyle_fill_range_by_selection(bpy.types.Operator):
return rl and rl.freestyle_settings.linesets.active
def execute(self, context):
+ import sys
+
scene = context.scene
rl = scene.render.layers.active
lineset = rl.freestyle_settings.linesets.active
diff --git a/release/scripts/startup/bl_operators/image.py b/release/scripts/startup/bl_operators/image.py
index 1653459bd71..f00f5d97c5e 100644
--- a/release/scripts/startup/bl_operators/image.py
+++ b/release/scripts/startup/bl_operators/image.py
@@ -33,7 +33,8 @@ class EditExternally(Operator):
subtype='FILE_PATH',
)
- def _editor_guess(self, context):
+ @staticmethod
+ def _editor_guess(context):
import sys
image_editor = context.user_preferences.filepaths.image_editor
diff --git a/release/scripts/startup/bl_operators/mask.py b/release/scripts/startup/bl_operators/mask.py
index 60208d27338..aa984659430 100644
--- a/release/scripts/startup/bl_operators/mask.py
+++ b/release/scripts/startup/bl_operators/mask.py
@@ -18,7 +18,6 @@
# <pep8-80 compliant>
-import bpy
from bpy.types import Menu
diff --git a/release/scripts/startup/bl_operators/mesh.py b/release/scripts/startup/bl_operators/mesh.py
index f86c31cd9cc..ea504d48448 100644
--- a/release/scripts/startup/bl_operators/mesh.py
+++ b/release/scripts/startup/bl_operators/mesh.py
@@ -75,7 +75,6 @@ class MeshMirrorUV(Operator):
double_warn += co in mirror_lt
mirror_lt[co] = i
- #for i, v in enumerate(mesh.vertices):
vmap = {}
for mirror_a, mirror_b in ((mirror_gt, mirror_lt),
(mirror_lt, mirror_gt)):
diff --git a/release/scripts/startup/bl_operators/node.py b/release/scripts/startup/bl_operators/node.py
index 9bdd9289700..d6aeab5c02b 100644
--- a/release/scripts/startup/bl_operators/node.py
+++ b/release/scripts/startup/bl_operators/node.py
@@ -20,15 +20,17 @@
import bpy
import nodeitems_utils
-from bpy.types import (Operator,
- PropertyGroup,
- )
-from bpy.props import (BoolProperty,
- CollectionProperty,
- EnumProperty,
- IntProperty,
- StringProperty,
- )
+from bpy.types import (
+ Operator,
+ PropertyGroup,
+ )
+from bpy.props import (
+ BoolProperty,
+ CollectionProperty,
+ EnumProperty,
+ IntProperty,
+ StringProperty,
+ )
class NodeSetting(PropertyGroup):
@@ -40,7 +42,7 @@ class NodeSetting(PropertyGroup):
# Base class for node 'Add' operators
-class NodeAddOperator():
+class NodeAddOperator:
type = StringProperty(
name="Node Type",
@@ -122,8 +124,8 @@ class NodeAddOperator():
result = self.execute(context)
if self.use_transform and ('FINISHED' in result):
- # removes the node again if transform is cancelled
- bpy.ops.transform.translate('INVOKE_DEFAULT', remove_on_cancel=True)
+ # removes the node again if transform is canceled
+ bpy.ops.node.translate_attach_remove_on_cancel('INVOKE_DEFAULT')
return result
@@ -218,7 +220,7 @@ class NODE_OT_add_search(NodeAddOperator, Operator):
self.create_node(context, item.nodetype)
if self.use_transform:
- bpy.ops.transform.translate('INVOKE_DEFAULT', remove_on_cancel=True)
+ bpy.ops.node.translate_attach_remove_on_cancel('INVOKE_DEFAULT')
return {'FINISHED'}
else:
diff --git a/release/scripts/startup/bl_operators/object.py b/release/scripts/startup/bl_operators/object.py
index c1f75c74bb4..b89890a223c 100644
--- a/release/scripts/startup/bl_operators/object.py
+++ b/release/scripts/startup/bl_operators/object.py
@@ -20,11 +20,13 @@
import bpy
from bpy.types import Operator
-from bpy.props import (StringProperty,
- BoolProperty,
- EnumProperty,
- IntProperty,
- FloatProperty)
+from bpy.props import (
+ StringProperty,
+ BoolProperty,
+ EnumProperty,
+ IntProperty,
+ FloatProperty,
+ )
class SelectPattern(Operator):
@@ -250,7 +252,7 @@ class SubdivisionSet(Operator):
if not relative:
if level > mod.total_levels:
sub = level - mod.total_levels
- for i in range (0, sub):
+ for i in range(sub):
bpy.ops.object.multires_subdivide(modifier="Multires")
if obj.mode == 'SCULPT':
@@ -577,7 +579,8 @@ class MakeDupliFace(Operator):
bl_label = "Make Dupli-Face"
bl_options = {'REGISTER', 'UNDO'}
- def _main(self, context):
+ @staticmethod
+ def _main(context):
from mathutils import Vector
SCALE_FAC = 0.01
@@ -641,6 +644,9 @@ class MakeDupliFace(Operator):
ob_new.use_dupli_faces_scale = True
ob_new.dupli_faces_scale = 1.0 / SCALE_FAC
+ ob_inst.select = True
+ ob_new.select = True
+
def execute(self, context):
self._main(context)
return {'FINISHED'}
@@ -922,7 +928,7 @@ class LodGenerate(Operator):
lod.location.y = ob.location.y + 3.0 * i
if i == 1:
- modifier = lod.modifiers.new("lod_decimate", "DECIMATE")
+ modifier = lod.modifiers.new("lod_decimate", 'DECIMATE')
else:
modifier = lod.modifiers[-1]
diff --git a/release/scripts/startup/bl_operators/object_align.py b/release/scripts/startup/bl_operators/object_align.py
index e843209da3c..3c84e5dc553 100644
--- a/release/scripts/startup/bl_operators/object_align.py
+++ b/release/scripts/startup/bl_operators/object_align.py
@@ -70,7 +70,8 @@ def GlobalBB_HQ(obj):
# Initialize the variables with the last vertex
- verts = obj.data.vertices
+ me = obj.to_mesh(scene=bpy.context.scene, apply_modifiers=True, settings='PREVIEW')
+ verts = me.vertices
val = matrix_world * verts[-1].co
@@ -111,6 +112,8 @@ def GlobalBB_HQ(obj):
if val > up:
up = val
+ bpy.data.meshes.remove(me)
+
return Vector((left, front, up)), Vector((right, back, down))
@@ -338,7 +341,10 @@ def align_objects(context,
return True
-from bpy.props import EnumProperty, BoolProperty
+from bpy.props import (
+ EnumProperty,
+ BoolProperty
+ )
class AlignObjects(Operator):
diff --git a/release/scripts/startup/bl_operators/object_quick_effects.py b/release/scripts/startup/bl_operators/object_quick_effects.py
index 06dc82d2b77..414855c7e35 100644
--- a/release/scripts/startup/bl_operators/object_quick_effects.py
+++ b/release/scripts/startup/bl_operators/object_quick_effects.py
@@ -21,12 +21,13 @@
from mathutils import Vector
import bpy
from bpy.types import Operator
-from bpy.props import (BoolProperty,
- EnumProperty,
- IntProperty,
- FloatProperty,
- FloatVectorProperty,
- )
+from bpy.props import (
+ BoolProperty,
+ EnumProperty,
+ IntProperty,
+ FloatProperty,
+ FloatVectorProperty,
+ )
def object_ensure_material(obj, mat_name):
@@ -74,7 +75,7 @@ class QuickFur(Operator):
def execute(self, context):
fake_context = context.copy()
mesh_objects = [obj for obj in context.selected_objects
- if obj.type == 'MESH']
+ if obj.type == 'MESH' and obj.mode == 'OBJECT']
if not mesh_objects:
self.report({'ERROR'}, "Select at least one mesh object")
@@ -387,7 +388,7 @@ class QuickSmoke(Operator):
links.new(node_add_shader_1.outputs["Shader"],
node_out.inputs["Volume"])
- if self.style in {'SMOKE', 'BOTH'}:
+ if self.style in {'SMOKE', 'FIRE', 'BOTH'}:
# Smoke
# Add shader 2
diff --git a/release/scripts/startup/bl_operators/presets.py b/release/scripts/startup/bl_operators/presets.py
index f89792bea6e..63c1945d2d2 100644
--- a/release/scripts/startup/bl_operators/presets.py
+++ b/release/scripts/startup/bl_operators/presets.py
@@ -23,7 +23,7 @@ from bpy.types import Menu, Operator
from bpy.props import StringProperty, BoolProperty
-class AddPresetBase():
+class AddPresetBase:
"""Base preset class, only for subclassing
subclasses must define
- preset_values
@@ -45,11 +45,28 @@ class AddPresetBase():
options={'HIDDEN', 'SKIP_SAVE'},
)
+ # needed for mix-ins
+ order = [
+ "name",
+ "remove_active",
+ ]
+
@staticmethod
def as_filename(name): # could reuse for other presets
- for char in " !@#$%^&*(){}:\";'[]<>,.\\/?":
- name = name.replace(char, '_')
- return name.lower().strip()
+
+ # lazy init maketrans
+ def maketrans_init():
+ cls = AddPresetBase
+ attr = "_as_filename_trans"
+
+ trans = getattr(cls, attr, None)
+ if trans is None:
+ trans = str.maketrans({char: "_" for char in " !@#$%^&*(){}:\";'[]<>,.\\/?"})
+ setattr(cls, attr, trans)
+ return trans
+
+ trans = maketrans_init()
+ return name.lower().strip().translate(trans)
def execute(self, context):
import os
@@ -277,6 +294,26 @@ class AddPresetCamera(AddPresetBase, Operator):
return preset_values
+class AddPresetSafeAreas(AddPresetBase, Operator):
+ """Add or remove a Safe Areas Preset"""
+ bl_idname = "safe_areas.preset_add"
+ bl_label = "Add Safe Area Preset"
+ preset_menu = "SAFE_AREAS_MT_presets"
+
+ preset_defines = [
+ "safe_areas = bpy.context.scene.safe_areas"
+ ]
+
+ preset_values = [
+ "safe_areas.title",
+ "safe_areas.action",
+ "safe_areas.title_center",
+ "safe_areas.action_center",
+ ]
+
+ preset_subdir = "safe_areas"
+
+
class AddPresetSSS(AddPresetBase, Operator):
"""Add or remove a Subsurface Scattering Preset"""
bl_idname = "material.sss_preset_add"
@@ -345,6 +382,36 @@ class AddPresetFluid(AddPresetBase, Operator):
preset_subdir = "fluid"
+class AddPresetHairDynamics(AddPresetBase, Operator):
+ """Add or remove a Hair Dynamics Preset"""
+ bl_idname = "particle.hair_dynamics_preset_add"
+ bl_label = "Add Hair Dynamics Preset"
+ preset_menu = "PARTICLE_MT_hair_dynamics_presets"
+
+ preset_defines = [
+ "psys = bpy.context.particle_system",
+ "cloth = bpy.context.particle_system.cloth",
+ "settings = bpy.context.particle_system.cloth.settings",
+ "collision = bpy.context.particle_system.cloth.collision_settings",
+ ]
+
+ preset_subdir = "hair_dynamics"
+
+ preset_values = [
+ "settings.quality",
+ "settings.mass",
+ "settings.bending_stiffness",
+ "psys.settings.bending_random",
+ "settings.bending_damping",
+ "settings.air_damping",
+ "settings.internal_friction",
+ "settings.density_target",
+ "settings.density_strength",
+ "settings.voxel_cell_size",
+ "settings.pin_stiffness",
+ ]
+
+
class AddPresetSunSky(AddPresetBase, Operator):
"""Add or remove a Sky & Atmosphere Preset"""
bl_idname = "lamp.sunsky_preset_add"
diff --git a/release/scripts/startup/bl_operators/rigidbody.py b/release/scripts/startup/bl_operators/rigidbody.py
index 9a3aae53ceb..237c2d55672 100644
--- a/release/scripts/startup/bl_operators/rigidbody.py
+++ b/release/scripts/startup/bl_operators/rigidbody.py
@@ -64,17 +64,19 @@ class CopyRigidbodySettings(Operator):
for o in context.selected_objects:
if o.type != 'MESH':
o.select = False
+ elif o.rigid_body is None:
+ # Add rigidbody to object!
+ scene.objects.active = o
+ bpy.ops.rigidbody.object_add()
+ scene.objects.active = obj_act
objects = context.selected_objects
if objects:
- # add selected objects to active one groups and recalculate
- bpy.ops.group.objects_add_active()
- scene.frame_set(scene.frame_current)
rb_from = obj_act.rigid_body
# copy settings
for o in objects:
rb_to = o.rigid_body
- if (o == obj_act) or (rb_to is None):
+ if o == obj_act:
continue
for attr in self._attrs:
setattr(rb_to, attr, getattr(rb_from, attr))
diff --git a/release/scripts/startup/bl_operators/screen_play_rendered_anim.py b/release/scripts/startup/bl_operators/screen_play_rendered_anim.py
index 3a7a9b99cde..a5565699364 100644
--- a/release/scripts/startup/bl_operators/screen_play_rendered_anim.py
+++ b/release/scripts/startup/bl_operators/screen_play_rendered_anim.py
@@ -107,11 +107,20 @@ class PlayRenderedAnim(Operator):
del file_a, file_b, frame_tmp
file = bpy.path.abspath(file) # expand '//'
else:
+ path_valid = True
# works for movies and images
- file = rd.frame_path(frame=scene.frame_start)
+ file = rd.frame_path(frame=scene.frame_start, preview=scene.use_preview_range)
file = bpy.path.abspath(file) # expand '//'
if not os.path.exists(file):
self.report({'WARNING'}, "File %r not found" % file)
+ path_valid = False
+
+ #one last try for full range if we used preview range
+ if scene.use_preview_range and not path_valid:
+ file = rd.frame_path(frame=scene.frame_start, preview=False)
+ file = bpy.path.abspath(file) # expand '//'
+ if not os.path.exists(file):
+ self.report({'WARNING'}, "File %r not found" % file)
cmd = [player_path]
# extra options, fps controls etc.
diff --git a/release/scripts/startup/bl_operators/uvcalc_lightmap.py b/release/scripts/startup/bl_operators/uvcalc_lightmap.py
index 8f618e0632e..a120e2b2461 100644
--- a/release/scripts/startup/bl_operators/uvcalc_lightmap.py
+++ b/release/scripts/startup/bl_operators/uvcalc_lightmap.py
@@ -23,7 +23,7 @@ from bpy.types import Operator
import mathutils
-class prettyface(object):
+class prettyface:
__slots__ = (
"uv",
"width",
diff --git a/release/scripts/startup/bl_operators/uvcalc_smart_project.py b/release/scripts/startup/bl_operators/uvcalc_smart_project.py
index aa8a1742c1e..73e6bcd9b0c 100644
--- a/release/scripts/startup/bl_operators/uvcalc_smart_project.py
+++ b/release/scripts/startup/bl_operators/uvcalc_smart_project.py
@@ -670,7 +670,7 @@ def VectoQuat(vec):
return vec.to_track_quat('Z', 'X' if abs(vec.x) > 0.5 else 'Y').inverted()
-class thickface(object):
+class thickface:
__slost__= "v", "uv", "no", "area", "edge_keys"
def __init__(self, face, uv_layer, mesh_verts):
self.v = [mesh_verts[i] for i in face.vertices]
@@ -708,6 +708,7 @@ def main(context,
island_margin,
projection_limit,
user_area_weight,
+ use_aspect
):
global USER_FILL_HOLES
global USER_FILL_HOLES_QUALITY
@@ -720,7 +721,6 @@ def main(context,
global dict_matrix
dict_matrix = {}
-
# Constants:
# Takes a list of faces that make up a UV island and rotate
# until they optimally fit inside a square.
@@ -992,9 +992,31 @@ def main(context,
print("Smart Projection time: %.2f" % (time.time() - time1))
# Window.DrawProgressBar(0.9, "Smart Projections done, time: %.2f sec" % (time.time() - time1))
+ # aspect correction is only done in edit mode - and only smart unwrap supports currently
if is_editmode:
bpy.ops.object.mode_set(mode='EDIT')
+ if use_aspect:
+ import bmesh
+ aspect = context.scene.uvedit_aspect(context.active_object)
+ if aspect[0] > aspect[1]:
+ aspect[0] = aspect[1]/aspect[0];
+ aspect[1] = 1.0
+ else:
+ aspect[1] = aspect[0]/aspect[1];
+ aspect[0] = 1.0
+
+ bm = bmesh.from_edit_mesh(me)
+
+ uv_act = bm.loops.layers.uv.active
+
+ faces = [f for f in bm.faces if f.select]
+
+ for f in faces:
+ for l in f.loops:
+ l[uv_act].uv[0] *= aspect[0]
+ l[uv_act].uv[1] *= aspect[1]
+
dict_matrix.clear()
#XXX Window.DrawProgressBar(1.0, "")
@@ -1017,7 +1039,7 @@ def main(context,
]
"""
-from bpy.props import FloatProperty
+from bpy.props import FloatProperty, BoolProperty
class SmartProject(Operator):
@@ -1046,6 +1068,11 @@ class SmartProject(Operator):
min=0.0, max=1.0,
default=0.0,
)
+ use_aspect = BoolProperty(
+ name="Correct Aspect",
+ description="Map UVs taking image aspect ratio into account",
+ default=True
+ )
@classmethod
def poll(cls, context):
@@ -1056,6 +1083,7 @@ class SmartProject(Operator):
self.island_margin,
self.angle_limit,
self.user_area_weight,
+ self.use_aspect
)
return {'FINISHED'}
diff --git a/release/scripts/startup/bl_operators/vertexpaint_dirt.py b/release/scripts/startup/bl_operators/vertexpaint_dirt.py
index ecb1ecf7f47..892e1822d68 100644
--- a/release/scripts/startup/bl_operators/vertexpaint_dirt.py
+++ b/release/scripts/startup/bl_operators/vertexpaint_dirt.py
@@ -27,11 +27,9 @@
def applyVertexDirt(me, blur_iterations, blur_strength, clamp_dirt, clamp_clean, dirt_only):
from mathutils import Vector
from math import acos
+ import array
- vert_tone = [0.0] * len(me.vertices)
-
- min_tone = 180.0
- max_tone = 0.0
+ vert_tone = array.array("f", [0.0]) * len(me.vertices)
# create lookup table for each vertex's connected vertices (via edges)
con = []
@@ -74,7 +72,7 @@ def applyVertexDirt(me, blur_iterations, blur_strength, clamp_dirt, clamp_clean,
# blur tones
for i in range(blur_iterations):
# backup the original tones
- orig_vert_tone = list(vert_tone)
+ orig_vert_tone = vert_tone[:]
# use connected verts look up for blurring
for j, c in enumerate(con):
@@ -82,20 +80,18 @@ def applyVertexDirt(me, blur_iterations, blur_strength, clamp_dirt, clamp_clean,
vert_tone[j] += blur_strength * orig_vert_tone[v]
vert_tone[j] /= len(c) * blur_strength + 1
+ del orig_vert_tone
min_tone = min(vert_tone)
max_tone = max(vert_tone)
- # debug information
- # print(min_tone * 2 * math.pi)
- # print(max_tone * 2 * math.pi)
- # print(clamp_clean)
- # print(clamp_dirt)
-
tone_range = max_tone - min_tone
- if not tone_range:
- return {'CANCELLED'}
+ if tone_range < 0.0001:
+ # weak, don't cancel, see T43345
+ tone_range = 0.0
+ else:
+ tone_range = 1.0 / tone_range
active_col_layer = None
@@ -112,7 +108,6 @@ def applyVertexDirt(me, blur_iterations, blur_strength, clamp_dirt, clamp_clean,
return {'CANCELLED'}
use_paint_mask = me.use_paint_mask
-
for i, p in enumerate(me.polygons):
if not use_paint_mask or p.select:
for loop_index in p.loop_indices:
@@ -120,11 +115,10 @@ def applyVertexDirt(me, blur_iterations, blur_strength, clamp_dirt, clamp_clean,
v = loop.vertex_index
col = active_col_layer[loop_index].color
tone = vert_tone[v]
- tone = (tone - min_tone) / tone_range
+ tone = (tone - min_tone) * tone_range
if dirt_only:
- tone = min(tone, 0.5)
- tone *= 2.0
+ tone = min(tone, 0.5) * 2.0
col[0] = tone * col[0]
col[1] = tone * col[1]
@@ -182,15 +176,9 @@ class VertexPaintDirt(Operator):
return (obj and obj.type == 'MESH')
def execute(self, context):
- import time
-
obj = context.object
mesh = obj.data
- t = time.time()
-
ret = applyVertexDirt(mesh, self.blur_iterations, self.blur_strength, self.dirt_angle, self.clean_angle, self.dirt_only)
- print('Dirt calculated in %.6f' % (time.time() - t))
-
return ret
diff --git a/release/scripts/startup/bl_operators/wm.py b/release/scripts/startup/bl_operators/wm.py
index 8d04cb132e6..c228e33965f 100644
--- a/release/scripts/startup/bl_operators/wm.py
+++ b/release/scripts/startup/bl_operators/wm.py
@@ -20,12 +20,13 @@
import bpy
from bpy.types import Operator
-from bpy.props import (StringProperty,
- BoolProperty,
- IntProperty,
- FloatProperty,
- EnumProperty,
- )
+from bpy.props import (
+ StringProperty,
+ BoolProperty,
+ IntProperty,
+ FloatProperty,
+ EnumProperty,
+ )
from bpy.app.translations import pgettext_tip as tip_
@@ -718,7 +719,7 @@ class WM_OT_context_modal_mouse(Operator):
"""Adjust arbitrary values with mouse input"""
bl_idname = "wm.context_modal_mouse"
bl_label = "Context Modal Mouse"
- bl_options = {'GRAB_POINTER', 'BLOCKING', 'UNDO', 'INTERNAL'}
+ bl_options = {'GRAB_CURSOR', 'BLOCKING', 'UNDO', 'INTERNAL'}
data_path_iter = data_path_iter
data_path_item = data_path_item
@@ -973,10 +974,12 @@ class WM_OT_doc_view_manual(Operator):
url = self._lookup_rna_url(rna_id)
if url is None:
- self.report({'WARNING'}, "No reference available %r, "
- "Update info in 'rna_wiki_reference.py' "
- " or callback to bpy.utils.manual_map()" %
- self.doc_id)
+ self.report(
+ {'WARNING'},
+ "No reference available %r, "
+ "Update info in 'rna_manual_reference.py' "
+ "or callback to bpy.utils.manual_map()" %
+ self.doc_id)
return {'CANCELLED'}
else:
import webbrowser
@@ -1129,7 +1132,11 @@ class WM_OT_properties_edit(Operator):
)
def execute(self, context):
- from rna_prop_ui import rna_idprop_ui_prop_get, rna_idprop_ui_prop_clear
+ from rna_prop_ui import (
+ rna_idprop_ui_prop_get,
+ rna_idprop_ui_prop_clear,
+ rna_idprop_ui_prop_update,
+ )
data_path = self.data_path
value = self.value
@@ -1161,6 +1168,9 @@ class WM_OT_properties_edit(Operator):
exec_str = "item[%r] = %s" % (prop, repr(value_eval))
# print(exec_str)
exec(exec_str)
+
+ rna_idprop_ui_prop_update(item, prop)
+
self._last_prop[:] = [prop]
prop_type = type(item[prop])
@@ -1242,7 +1252,10 @@ class WM_OT_properties_add(Operator):
data_path = rna_path
def execute(self, context):
- from rna_prop_ui import rna_idprop_ui_prop_get
+ from rna_prop_ui import (
+ rna_idprop_ui_prop_get,
+ rna_idprop_ui_prop_update,
+ )
data_path = self.data_path
item = eval("context.%s" % data_path)
@@ -1260,6 +1273,7 @@ class WM_OT_properties_add(Operator):
prop = unique_name(item.keys())
item[prop] = 1.0
+ rna_idprop_ui_prop_update(item, prop)
# not essential, but without this we get [#31661]
prop_ui = rna_idprop_ui_prop_get(item, prop)
@@ -1295,9 +1309,17 @@ class WM_OT_properties_remove(Operator):
property = rna_property
def execute(self, context):
+ from rna_prop_ui import (
+ rna_idprop_ui_prop_clear,
+ rna_idprop_ui_prop_update,
+ )
data_path = self.data_path
item = eval("context.%s" % data_path)
- del item[self.property]
+ prop = self.property
+ rna_idprop_ui_prop_update(item, prop)
+ del item[prop]
+ rna_idprop_ui_prop_clear(item, prop)
+
return {'FINISHED'}
@@ -1737,7 +1759,7 @@ class WM_OT_addon_enable(Operator):
err_str = traceback.format_exc()
print(err_str)
- mod = addon_utils.enable(self.module, handle_error=err_cb)
+ mod = addon_utils.enable(self.module, default_set=True, handle_error=err_cb)
if mod:
info = addon_utils.module_bl_info(mod)
@@ -1781,7 +1803,7 @@ class WM_OT_addon_disable(Operator):
err_str = traceback.format_exc()
print(err_str)
- addon_utils.disable(self.module, handle_error=err_cb)
+ addon_utils.disable(self.module, default_set=True, handle_error=err_cb)
if err_str:
self.report({'ERROR'}, err_str)
@@ -1987,7 +2009,6 @@ class WM_OT_addon_install(Operator):
# if not compressed file just copy into the addon path
try:
shutil.copyfile(pyfile, path_dest)
-
except:
traceback.print_exc()
return {'CANCELLED'}
@@ -1998,7 +2019,7 @@ class WM_OT_addon_install(Operator):
# disable any addons we may have enabled previously and removed.
# this is unlikely but do just in case. bug [#23978]
for new_addon in addons_new:
- addon_utils.disable(new_addon)
+ addon_utils.disable(new_addon, default_set=True)
# possible the zip contains multiple addons, we could disallow this
# but for now just use the first
@@ -2062,7 +2083,7 @@ class WM_OT_addon_remove(Operator):
return {'CANCELLED'}
# in case its enabled
- addon_utils.disable(self.module)
+ addon_utils.disable(self.module, default_set=True)
import shutil
if isdir:
@@ -2102,15 +2123,9 @@ class WM_OT_addon_expand(Operator):
module_name = self.module
- # unlikely to fail, module should have already been imported
- try:
- # mod = __import__(module_name)
- mod = addon_utils.addons_fake_modules.get(module_name)
- except:
- import traceback
- traceback.print_exc()
- return {'CANCELLED'}
+ mod = addon_utils.addons_fake_modules.get(module_name)
+ if mod is not None:
+ info = addon_utils.module_bl_info(mod)
+ info["show_expanded"] = not info["show_expanded"]
- info = addon_utils.module_bl_info(mod)
- info["show_expanded"] = not info["show_expanded"]
return {'FINISHED'}
diff --git a/release/scripts/startup/bl_ui/__init__.py b/release/scripts/startup/bl_ui/__init__.py
index 6b72ef12dcc..c110b429aad 100644
--- a/release/scripts/startup/bl_ui/__init__.py
+++ b/release/scripts/startup/bl_ui/__init__.py
@@ -21,9 +21,10 @@
# note, properties_animviz is a helper module only.
if "bpy" in locals():
- from imp import reload as _reload
+ from importlib import reload
for val in _modules_loaded.values():
- _reload(val)
+ reload(val)
+ del reload
_modules = [
"properties_animviz",
"properties_constraint",
@@ -85,7 +86,7 @@ if bpy.app.build_options.freestyle:
_modules.append("properties_freestyle")
__import__(name=__name__, fromlist=_modules)
_namespace = globals()
-_modules_loaded = {name: _namespace[name] for name in _modules if name != 'bpy'}
+_modules_loaded = {name: _namespace[name] for name in _modules if name != "bpy"}
del _namespace
@@ -99,10 +100,10 @@ def register():
def addon_filter_items(self, context):
import addon_utils
- items = [('All', "All", "All Addons"),
- ('User', "User", "All Addons Installed by User"),
- ('Enabled', "Enabled", "All Enabled Addons"),
- ('Disabled', "Disabled", "All Disabled Addons"),
+ items = [('All', "All", "All Add-ons"),
+ ('User', "User", "All Add-ons Installed by User"),
+ ('Enabled', "Enabled", "All Enabled Add-ons"),
+ ('Disabled', "Disabled", "All Disabled Add-ons"),
]
items_unique = set()
@@ -117,6 +118,7 @@ def register():
WindowManager.addon_search = StringProperty(
name="Search",
description="Search within the selected filter",
+ options={'TEXTEDIT_UPDATE'},
)
WindowManager.addon_filter = EnumProperty(
items=addon_filter_items,
diff --git a/release/scripts/startup/bl_ui/properties_animviz.py b/release/scripts/startup/bl_ui/properties_animviz.py
index 8308c7fc425..11081232f12 100644
--- a/release/scripts/startup/bl_ui/properties_animviz.py
+++ b/release/scripts/startup/bl_ui/properties_animviz.py
@@ -25,7 +25,7 @@
# don't register these classes since they are only helpers.
-class MotionPathButtonsPanel():
+class MotionPathButtonsPanel:
bl_space_type = 'PROPERTIES'
bl_region_type = 'WINDOW'
bl_label = "Motion Paths"
@@ -97,7 +97,7 @@ class MotionPathButtonsPanel():
# FIXME: this panel still needs to be ported so that it will work correctly with animviz
-class OnionSkinButtonsPanel():
+class OnionSkinButtonsPanel:
bl_space_type = 'PROPERTIES'
bl_region_type = 'WINDOW'
bl_label = "Onion Skinning"
diff --git a/release/scripts/startup/bl_ui/properties_constraint.py b/release/scripts/startup/bl_ui/properties_constraint.py
index 4baf31a591b..7ade444d7ae 100644
--- a/release/scripts/startup/bl_ui/properties_constraint.py
+++ b/release/scripts/startup/bl_ui/properties_constraint.py
@@ -21,7 +21,7 @@ import bpy
from bpy.types import Panel
-class ConstraintButtonsPanel():
+class ConstraintButtonsPanel:
bl_space_type = 'PROPERTIES'
bl_region_type = 'WINDOW'
bl_context = "constraint"
@@ -38,7 +38,8 @@ class ConstraintButtonsPanel():
if con.type not in {'RIGID_BODY_JOINT', 'NULL'}:
box.prop(con, "influence")
- def space_template(self, layout, con, target=True, owner=True):
+ @staticmethod
+ def space_template(layout, con, target=True, owner=True):
if target or owner:
split = layout.split(percentage=0.2)
@@ -55,7 +56,8 @@ class ConstraintButtonsPanel():
if owner:
row.prop(con, "owner_space", text="")
- def target_template(self, layout, con, subtargets=True):
+ @staticmethod
+ def target_template(layout, con, subtargets=True):
layout.prop(con, "target") # XXX limiting settings for only 'curves' or some type of object
if con.target and subtargets:
@@ -69,7 +71,8 @@ class ConstraintButtonsPanel():
elif con.target.type in {'MESH', 'LATTICE'}:
layout.prop_search(con, "subtarget", con.target, "vertex_groups", text="Vertex Group")
- def ik_template(self, layout, con):
+ @staticmethod
+ def ik_template(layout, con):
# only used for iTaSC
layout.prop(con, "pole_target")
@@ -502,6 +505,20 @@ class ConstraintButtonsPanel():
row.operator("constraint.stretchto_reset", text="Reset")
layout.prop(con, "bulge", text="Volume Variation")
+ split = layout.split()
+ col = split.column(align=True)
+ col.prop(con, "use_bulge_min", text="Volume Min")
+ sub = col.column()
+ sub.active = con.use_bulge_min
+ sub.prop(con, "bulge_min", text="")
+ col = split.column(align=True)
+ col.prop(con, "use_bulge_max", text="Volume Max")
+ sub = col.column()
+ sub.active = con.use_bulge_max
+ sub.prop(con, "bulge_max", text="")
+ col = layout.column()
+ col.active = con.use_bulge_min or con.use_bulge_max
+ col.prop(con, "bulge_smooth", text="Smooth")
row = layout.row()
row.label(text="Volume:")
@@ -754,9 +771,27 @@ class ConstraintButtonsPanel():
col = layout.column()
col.label(text="Chain Scaling:")
col.prop(con, "use_y_stretch")
- col.prop(con, "xz_scale_mode")
col.prop(con, "use_curve_radius")
+ layout.prop(con, "xz_scale_mode")
+
+ if con.xz_scale_mode == 'VOLUME_PRESERVE':
+ layout.prop(con, "bulge", text="Volume Variation")
+ split = layout.split()
+ col = split.column(align=True)
+ col.prop(con, "use_bulge_min", text="Volume Min")
+ sub = col.column()
+ sub.active = con.use_bulge_min
+ sub.prop(con, "bulge_min", text="")
+ col = split.column(align=True)
+ col.prop(con, "use_bulge_max", text="Volume Max")
+ sub = col.column()
+ sub.active = con.use_bulge_max
+ sub.prop(con, "bulge_max", text="")
+ col = layout.column()
+ col.active = con.use_bulge_min or con.use_bulge_max
+ col.prop(con, "bulge_smooth", text="Smooth")
+
def PIVOT(self, context, layout, con):
self.target_template(layout, con)
@@ -862,7 +897,7 @@ class OBJECT_PT_constraints(ConstraintButtonsPanel, Panel):
obj = context.object
- if obj.type == 'ARMATURE' and obj.mode in {'POSE'}:
+ if obj.type == 'ARMATURE' and obj.mode == 'POSE':
box = layout.box()
box.alert = True # XXX: this should apply to the box background
box.label(icon='INFO', text="Constraints for active bone do not live here")
diff --git a/release/scripts/startup/bl_ui/properties_data_armature.py b/release/scripts/startup/bl_ui/properties_data_armature.py
index c6823f17153..3c9e2eb8f8b 100644
--- a/release/scripts/startup/bl_ui/properties_data_armature.py
+++ b/release/scripts/startup/bl_ui/properties_data_armature.py
@@ -22,7 +22,7 @@ from bpy.types import Panel, Menu
from rna_prop_ui import PropertyPanel
-class ArmatureButtonsPanel():
+class ArmatureButtonsPanel:
bl_space_type = 'PROPERTIES'
bl_region_type = 'WINDOW'
bl_context = "data"
@@ -144,6 +144,7 @@ class DATA_PT_bone_groups(ArmatureButtonsPanel, Panel):
if group.color_set:
col = split.column()
sub = col.row(align=True)
+ sub.enabled = group.is_custom_color_set # only custom colors are editable
sub.prop(group.colors, "normal", text="")
sub.prop(group.colors, "select", text="")
sub.prop(group.colors, "active", text="")
@@ -185,7 +186,6 @@ class DATA_PT_pose_library(ArmatureButtonsPanel, Panel):
# column of operators for active pose
# - goes beside list
col = row.column(align=True)
- col.active = (poselib.library is None)
# invoke should still be used for 'add', as it is needed to allow
# add/replace options to be used properly
@@ -277,9 +277,10 @@ class DATA_PT_iksolver_itasc(ArmatureButtonsPanel, Panel):
row.prop(itasc, "damping_max", text="Damp", slider=True)
row.prop(itasc, "damping_epsilon", text="Eps", slider=True)
-from bl_ui.properties_animviz import (MotionPathButtonsPanel,
- OnionSkinButtonsPanel,
- )
+from bl_ui.properties_animviz import (
+ MotionPathButtonsPanel,
+ OnionSkinButtonsPanel,
+ )
class DATA_PT_motion_paths(MotionPathButtonsPanel, Panel):
diff --git a/release/scripts/startup/bl_ui/properties_data_bone.py b/release/scripts/startup/bl_ui/properties_data_bone.py
index c07e9d677e7..2c7f18b3dfe 100644
--- a/release/scripts/startup/bl_ui/properties_data_bone.py
+++ b/release/scripts/startup/bl_ui/properties_data_bone.py
@@ -23,7 +23,7 @@ from bpy.types import Panel
from rna_prop_ui import PropertyPanel
-class BoneButtonsPanel():
+class BoneButtonsPanel:
bl_space_type = 'PROPERTIES'
bl_region_type = 'WINDOW'
bl_context = "bone"
@@ -229,6 +229,8 @@ class BONE_PT_display(BoneButtonsPanel, Panel):
col.label(text="Custom Shape:")
col.prop(pchan, "custom_shape", text="")
if pchan.custom_shape:
+ col.prop(pchan, "use_custom_shape_bone_size", text="Bone Size")
+ col.prop(pchan, "custom_shape_scale", text="Scale")
col.prop_search(pchan, "custom_shape_transform", ob.pose, "bones", text="At")
diff --git a/release/scripts/startup/bl_ui/properties_data_camera.py b/release/scripts/startup/bl_ui/properties_data_camera.py
index 0600c87244b..108e8bdfc74 100644
--- a/release/scripts/startup/bl_ui/properties_data_camera.py
+++ b/release/scripts/startup/bl_ui/properties_data_camera.py
@@ -22,7 +22,7 @@ from bpy.types import Panel, Menu
from rna_prop_ui import PropertyPanel
-class CameraButtonsPanel():
+class CameraButtonsPanel:
bl_space_type = 'PROPERTIES'
bl_region_type = 'WINDOW'
bl_context = "data"
@@ -41,6 +41,14 @@ class CAMERA_MT_presets(Menu):
draw = Menu.draw_preset
+class SAFE_AREAS_MT_presets(Menu):
+ bl_label = "Camera Presets"
+ preset_subdir = "safe_areas"
+ preset_operator = "script.execute_preset"
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
+ draw = Menu.draw_preset
+
+
class DATA_PT_context_camera(CameraButtonsPanel, Panel):
bl_label = ""
bl_options = {'HIDE_HEADER'}
@@ -98,6 +106,14 @@ class DATA_PT_lens(CameraButtonsPanel, Panel):
row = layout.row()
row.prop(ccam, "fisheye_lens", text="Lens")
row.prop(ccam, "fisheye_fov")
+ elif ccam.panorama_type == 'EQUIRECTANGULAR':
+ row = layout.row()
+ sub = row.column(align=True)
+ sub.prop(ccam, "latitude_min")
+ sub.prop(ccam, "latitude_max")
+ sub = row.column(align=True)
+ sub.prop(ccam, "longitude_min")
+ sub.prop(ccam, "longitude_max")
elif engine == 'BLENDER_RENDER':
row = col.row()
if cam.lens_unit == 'MILLIMETERS':
@@ -119,6 +135,34 @@ class DATA_PT_lens(CameraButtonsPanel, Panel):
col.prop(cam, "clip_end", text="End")
+class DATA_PT_camera_stereoscopy(CameraButtonsPanel, Panel):
+ bl_label = "Stereoscopy"
+ COMPAT_ENGINES = {'BLENDER_RENDER'}
+
+ @classmethod
+ def poll(cls, context):
+ render = context.scene.render
+ return (super().poll(context) and render.use_multiview and
+ render.views_format == 'STEREO_3D')
+
+ def draw(self, context):
+ layout = self.layout
+ # render = context.scene.render
+ st = context.camera.stereo
+
+ col = layout.column()
+ col.row().prop(st, "convergence_mode", expand=True)
+
+ sub = col.column()
+ sub.active = st.convergence_mode != 'PARALLEL'
+ sub.prop(st, "convergence_distance")
+
+ col.prop(st, "interocular_distance")
+
+ col.label(text="Pivot:")
+ col.row().prop(st, "pivot", expand=True)
+
+
class DATA_PT_camera(CameraButtonsPanel, Panel):
bl_label = "Camera"
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
@@ -161,16 +205,26 @@ class DATA_PT_camera_dof(CameraButtonsPanel, Panel):
layout = self.layout
cam = context.camera
-
- layout.label(text="Focus:")
+ dof_options = cam.gpu_dof
split = layout.split()
- split.prop(cam, "dof_object", text="")
col = split.column()
+ col.label(text="Focus:")
+ col.prop(cam, "dof_object", text="")
+ sub = col.column()
+ sub.active = (cam.dof_object is None)
+ sub.prop(cam, "dof_distance", text="Distance")
- col.active = cam.dof_object is None
- col.prop(cam, "dof_distance", text="Distance")
+ hq_support = dof_options.is_hq_supported
+ col = split.column(align=True)
+ col.label("Viewport:")
+ sub = col.column()
+ sub.active = hq_support
+ sub.prop(dof_options, "use_high_quality")
+ col.prop(dof_options, "fstop")
+ if dof_options.use_high_quality and hq_support:
+ col.prop(dof_options, "blades")
class DATA_PT_camera_display(CameraButtonsPanel, Panel):
@@ -187,7 +241,7 @@ class DATA_PT_camera_display(CameraButtonsPanel, Panel):
col = split.column()
col.prop(cam, "show_limits", text="Limits")
col.prop(cam, "show_mist", text="Mist")
- col.prop(cam, "show_title_safe", text="Safe Areas")
+
col.prop(cam, "show_sensor", text="Sensor")
col.prop(cam, "show_name", text="Name")
@@ -202,10 +256,56 @@ class DATA_PT_camera_display(CameraButtonsPanel, Panel):
sub.prop(cam, "passepartout_alpha", text="Alpha", slider=True)
+class DATA_PT_camera_safe_areas(CameraButtonsPanel, Panel):
+ bl_label = "Safe Areas"
+ bl_options = {'DEFAULT_CLOSED'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
+
+ def draw_header(self, context):
+ cam = context.camera
+
+ self.layout.prop(cam, "show_safe_areas", text="")
+
+ def draw(self, context):
+ layout = self.layout
+ safe_data = context.scene.safe_areas
+ camera = context.camera
+
+ draw_display_safe_settings(layout, safe_data, camera)
+
+
class DATA_PT_custom_props_camera(CameraButtonsPanel, PropertyPanel, Panel):
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
_context_path = "object.data"
_property_type = bpy.types.Camera
+
+def draw_display_safe_settings(layout, safe_data, settings):
+ show_safe_areas = settings.show_safe_areas
+ show_safe_center = settings.show_safe_center
+
+ split = layout.split()
+
+ col = split.column()
+ row = col.row(align=True)
+ row.menu("SAFE_AREAS_MT_presets", text=bpy.types.SAFE_AREAS_MT_presets.bl_label)
+ row.operator("safe_areas.preset_add", text="", icon='ZOOMIN')
+ row.operator("safe_areas.preset_add", text="", icon='ZOOMOUT').remove_active = True
+
+ col = split.column()
+ col.prop(settings, "show_safe_center", text="Center-Cut Safe Areas")
+
+ split = layout.split()
+ col = split.column()
+ col.active = show_safe_areas
+ col.prop(safe_data, "title", slider=True)
+ col.prop(safe_data, "action", slider=True)
+
+ col = split.column()
+ col.active = show_safe_areas and show_safe_center
+ col.prop(safe_data, "title_center", slider=True)
+ col.prop(safe_data, "action_center", slider=True)
+
+
if __name__ == "__main__": # only for live edit.
bpy.utils.register_module(__name__)
diff --git a/release/scripts/startup/bl_ui/properties_data_curve.py b/release/scripts/startup/bl_ui/properties_data_curve.py
index 7cfdcccfb94..f83dea996e6 100644
--- a/release/scripts/startup/bl_ui/properties_data_curve.py
+++ b/release/scripts/startup/bl_ui/properties_data_curve.py
@@ -24,7 +24,7 @@ from rna_prop_ui import PropertyPanel
from bpy.types import Curve, SurfaceCurve, TextCurve
-class CurveButtonsPanel():
+class CurveButtonsPanel:
bl_space_type = 'PROPERTIES'
bl_region_type = 'WINDOW'
bl_context = "data"
@@ -286,7 +286,7 @@ class DATA_PT_active_spline(CurveButtonsPanelActive, Panel):
sub.prop(act_spline, "order_v", text="V")
sub.prop(act_spline, "resolution_v", text="V")
- if not is_surf:
+ if act_spline.type == 'BEZIER':
col = layout.column()
col.label(text="Interpolation:")
@@ -321,7 +321,7 @@ class DATA_PT_font(CurveButtonsPanelText, Panel):
row.label(text="Bold & Italic")
row.template_ID(text, "font_bold_italic", open="font.open", unlink="font.unlink")
- #layout.prop(text, "font")
+ # layout.prop(text, "font")
split = layout.split()
diff --git a/release/scripts/startup/bl_ui/properties_data_empty.py b/release/scripts/startup/bl_ui/properties_data_empty.py
index c93bebf2673..a752d3517de 100644
--- a/release/scripts/startup/bl_ui/properties_data_empty.py
+++ b/release/scripts/startup/bl_ui/properties_data_empty.py
@@ -21,7 +21,7 @@ import bpy
from bpy.types import Panel
-class DataButtonsPanel():
+class DataButtonsPanel:
bl_space_type = 'PROPERTIES'
bl_region_type = 'WINDOW'
bl_context = "data"
diff --git a/release/scripts/startup/bl_ui/properties_data_lamp.py b/release/scripts/startup/bl_ui/properties_data_lamp.py
index 3aa0b71ae04..0121ad46c86 100644
--- a/release/scripts/startup/bl_ui/properties_data_lamp.py
+++ b/release/scripts/startup/bl_ui/properties_data_lamp.py
@@ -30,7 +30,7 @@ class LAMP_MT_sunsky_presets(Menu):
draw = Menu.draw_preset
-class DataButtonsPanel():
+class DataButtonsPanel:
bl_space_type = 'PROPERTIES'
bl_region_type = 'WINDOW'
bl_context = "data"
@@ -355,6 +355,7 @@ class DATA_PT_spot(DataButtonsPanel, Panel):
col = split.column()
+ col.active = (lamp.shadow_method != 'BUFFER_SHADOW' or lamp.shadow_buffer_type != 'DEEP')
col.prop(lamp, "use_halo")
sub = col.column(align=True)
sub.active = lamp.use_halo
diff --git a/release/scripts/startup/bl_ui/properties_data_lattice.py b/release/scripts/startup/bl_ui/properties_data_lattice.py
index 14d6ea66894..cbfa6961e8c 100644
--- a/release/scripts/startup/bl_ui/properties_data_lattice.py
+++ b/release/scripts/startup/bl_ui/properties_data_lattice.py
@@ -22,7 +22,7 @@ from bpy.types import Panel
from rna_prop_ui import PropertyPanel
-class DataButtonsPanel():
+class DataButtonsPanel:
bl_space_type = 'PROPERTIES'
bl_region_type = 'WINDOW'
bl_context = "data"
diff --git a/release/scripts/startup/bl_ui/properties_data_mesh.py b/release/scripts/startup/bl_ui/properties_data_mesh.py
index 909c6ab0b56..5416735494b 100644
--- a/release/scripts/startup/bl_ui/properties_data_mesh.py
+++ b/release/scripts/startup/bl_ui/properties_data_mesh.py
@@ -29,8 +29,8 @@ class MESH_MT_vertex_group_specials(Menu):
def draw(self, context):
layout = self.layout
- layout.operator("object.vertex_group_sort", icon='SORTALPHA').sort_type = "NAME"
- layout.operator("object.vertex_group_sort", icon='ARMATURE_DATA', text="Sort by Bone Hierarchy").sort_type = "BONE_HIERARCHY"
+ layout.operator("object.vertex_group_sort", icon='SORTALPHA', text="Sort by Name").sort_type = 'NAME'
+ layout.operator("object.vertex_group_sort", icon='ARMATURE_DATA', text="Sort by Bone Hierarchy").sort_type = 'BONE_HIERARCHY'
layout.operator("object.vertex_group_copy", icon='COPY_ID')
layout.operator("object.vertex_group_copy_to_linked", icon='LINK_AREA')
layout.operator("object.vertex_group_copy_to_selected", icon='LINK_AREA')
@@ -58,6 +58,8 @@ class MESH_MT_shape_key_specials(Menu):
layout.operator("object.shape_key_mirror", text="Mirror Shape Key (Topology)", icon='ARROW_LEFTRIGHT').use_topology = True
layout.operator("object.shape_key_add", icon='ZOOMIN', text="New Shape From Mix").from_mix = True
layout.operator("object.shape_key_remove", icon='X', text="Delete All Shapes").all = True
+ layout.operator("object.shape_key_move", icon='TRIA_UP_BAR', text="Move To Top").type = 'TOP'
+ layout.operator("object.shape_key_move", icon='TRIA_DOWN_BAR', text="Move To Bottom").type = 'BOTTOM'
class MESH_UL_vgroups(UIList):
@@ -68,7 +70,7 @@ class MESH_UL_vgroups(UIList):
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'}:
+ elif self.layout_type == 'GRID':
layout.alignment = 'CENTER'
layout.label(text="", icon_value=icon)
@@ -92,7 +94,7 @@ class MESH_UL_shape_keys(UIList):
else:
row.label(text="")
row.prop(key_block, "mute", text="", emboss=False)
- elif self.layout_type in {'GRID'}:
+ elif self.layout_type == 'GRID':
layout.alignment = 'CENTER'
layout.label(text="", icon_value=icon)
@@ -104,12 +106,12 @@ class MESH_UL_uvmaps_vcols(UIList):
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'}:
+ elif self.layout_type == 'GRID':
layout.alignment = 'CENTER'
layout.label(text="", icon_value=icon)
-class MeshButtonsPanel():
+class MeshButtonsPanel:
bl_space_type = 'PROPERTIES'
bl_region_type = 'WINDOW'
bl_context = "data"
@@ -152,7 +154,7 @@ class DATA_PT_normals(MeshButtonsPanel, Panel):
col = split.column()
col.prop(mesh, "use_auto_smooth")
sub = col.column()
- sub.active = mesh.use_auto_smooth
+ sub.active = mesh.use_auto_smooth and not mesh.has_custom_normals
sub.prop(mesh, "auto_smooth_angle", text="Angle")
split.prop(mesh, "show_double_sided")
@@ -315,7 +317,6 @@ class DATA_PT_shape_keys(MeshButtonsPanel, Panel):
row = layout.column()
row.active = enable_edit_value
row.prop(key, "eval_time")
- row.prop(key, "slurph")
class DATA_PT_uv_texture(MeshButtonsPanel, Panel):
@@ -368,8 +369,13 @@ class DATA_PT_customdata(MeshButtonsPanel, Panel):
me = context.mesh
col = layout.column()
- col.operator("mesh.customdata_clear_mask", icon='X')
- col.operator("mesh.customdata_clear_skin", icon='X')
+ col.operator("mesh.customdata_mask_clear", icon='X')
+ col.operator("mesh.customdata_skin_clear", icon='X')
+
+ if me.has_custom_normals:
+ col.operator("mesh.customdata_custom_splitnormals_clear", icon='X')
+ else:
+ col.operator("mesh.customdata_custom_splitnormals_add", icon='ZOOMIN')
col = layout.column()
diff --git a/release/scripts/startup/bl_ui/properties_data_metaball.py b/release/scripts/startup/bl_ui/properties_data_metaball.py
index cd894e60dbb..b42258c386a 100644
--- a/release/scripts/startup/bl_ui/properties_data_metaball.py
+++ b/release/scripts/startup/bl_ui/properties_data_metaball.py
@@ -22,7 +22,7 @@ from bpy.types import Panel
from rna_prop_ui import PropertyPanel
-class DataButtonsPanel():
+class DataButtonsPanel:
bl_space_type = 'PROPERTIES'
bl_region_type = 'WINDOW'
bl_context = "data"
diff --git a/release/scripts/startup/bl_ui/properties_data_modifier.py b/release/scripts/startup/bl_ui/properties_data_modifier.py
index efc430db50f..de8617ecc52 100644
--- a/release/scripts/startup/bl_ui/properties_data_modifier.py
+++ b/release/scripts/startup/bl_ui/properties_data_modifier.py
@@ -22,7 +22,7 @@ from bpy.types import Panel
from bpy.app.translations import pgettext_iface as iface_
-class ModifierButtonsPanel():
+class ModifierButtonsPanel:
bl_space_type = 'PROPERTIES'
bl_region_type = 'WINDOW'
bl_context = "modifier"
@@ -132,6 +132,7 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel):
col = split.column()
col.prop(md, "use_only_vertices")
col.prop(md, "use_clamp_overlap")
+ col.prop(md, "loop_slide")
layout.label(text="Limit Method:")
layout.row().prop(md, "limit_method", expand=True)
@@ -262,24 +263,37 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel):
row.prop(md, "decimate_type", expand=True)
if decimate_type == 'COLLAPSE':
+ has_vgroup = bool(md.vertex_group)
layout.prop(md, "ratio")
split = layout.split()
- row = split.row(align=True)
+
+ col = split.column()
+ row = col.row(align=True)
row.prop_search(md, "vertex_group", ob, "vertex_groups", text="")
row.prop(md, "invert_vertex_group", text="", icon='ARROW_LEFTRIGHT')
- split.prop(md, "use_collapse_triangulate")
+ layout_info = col
+
+ col = split.column()
+ row = col.row()
+ row.active = has_vgroup
+ row.prop(md, "vertex_group_factor")
+
+ col.prop(md, "use_collapse_triangulate")
+
elif decimate_type == 'UNSUBDIV':
layout.prop(md, "iterations")
+ layout_info = layout
else: # decimate_type == 'DISSOLVE':
layout.prop(md, "angle_limit")
layout.prop(md, "use_dissolve_boundaries")
layout.label("Delimit:")
row = layout.row()
row.prop(md, "delimit")
+ layout_info = layout
- layout.label(text=iface_("Face Count: %d") % md.face_count, translate=False)
+ layout_info.label(text=iface_("Faces: %d") % md.face_count, translate=False)
def DISPLACE(self, layout, ob, md):
has_texture = (md.texture is not None)
@@ -352,6 +366,7 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel):
layout.label(text="Settings are inside the Physics tab")
def HOOK(self, layout, ob, md):
+ use_falloff = (md.falloff_type != 'NONE')
split = layout.split()
col = split.column()
@@ -366,19 +381,28 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel):
layout.separator()
- split = layout.split()
+ row = layout.row(align=True)
+ if use_falloff:
+ row.prop(md, "falloff_radius")
+ row.prop(md, "strength", slider=True)
+ layout.prop(md, "falloff_type")
- col = split.column()
- col.prop(md, "falloff")
- col.prop(md, "force", slider=True)
+ col = layout.column()
+ if use_falloff:
+ if md.falloff_type == 'CURVE':
+ col.template_curve_mapping(md, "falloff_curve")
+
+ split = layout.split()
col = split.column()
- col.operator("object.hook_reset", text="Reset")
- col.operator("object.hook_recenter", text="Recenter")
+ col.prop(md, "use_falloff_uniform")
if ob.mode == 'EDIT':
- layout.separator()
- row = layout.row()
+ row = col.row(align=True)
+ row.operator("object.hook_reset", text="Reset")
+ row.operator("object.hook_recenter", text="Recenter")
+
+ row = layout.row(align=True)
row.operator("object.hook_select", text="Select")
row.operator("object.hook_assign", text="Assign")
@@ -448,7 +472,11 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel):
col = split.column()
if md.mode == 'ARMATURE':
col.label(text="Armature:")
- col.prop(md, "armature", text="")
+ row = col.row(align=True)
+ row.prop(md, "armature", text="")
+ sub = row.row(align=True)
+ sub.active = (md.armature is not None)
+ sub.prop(md, "invert_vertex_group", text="", icon='ARROW_LEFTRIGHT')
elif md.mode == 'VERTEX_GROUP':
col.label(text="Vertex Group:")
row = col.row(align=True)
@@ -846,6 +874,8 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel):
col.label(text="Options:")
col.prop(md, "use_subsurf_uv")
col.prop(md, "show_only_control_edges")
+ if hasattr(md, "use_opensubdiv"):
+ col.prop(md, "use_opensubdiv")
def SURFACE(self, layout, ob, md):
layout.label(text="Settings are inside the Physics tab")
@@ -962,7 +992,7 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel):
col = split.column()
col.template_ID(md, "texture", new="texture.new")
layout.prop(md, "texture_coords")
- if md.texture_coords == 'MAP_UV' and ob.type == 'MESH':
+ if md.texture_coords == 'UV' and ob.type == 'MESH':
layout.prop_search(md, "uv_layer", ob.data, "uv_textures")
elif md.texture_coords == 'OBJECT':
layout.prop(md, "texture_coords_object")
@@ -1117,13 +1147,15 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel):
self.vertex_weight_mask(layout, ob, md)
def SKIN(self, layout, ob, md):
- layout.operator("object.skin_armature_create", text="Create Armature")
+ row = layout.row()
+ row.operator("object.skin_armature_create", text="Create Armature")
+ row.operator("mesh.customdata_skin_add")
layout.separator()
- col = layout.column(align=True)
- col.prop(md, "branch_smoothing")
- col.prop(md, "use_smooth_shade")
+ row = layout.row(align=True)
+ row.prop(md, "branch_smoothing")
+ row.prop(md, "use_smooth_shade")
split = layout.split()
@@ -1225,6 +1257,178 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel):
col.prop(md, "material_offset", text="Material Offset")
+ def DATA_TRANSFER(self, layout, ob, md):
+ row = layout.row(align=True)
+ row.prop(md, "object")
+ sub = row.row(align=True)
+ sub.active = bool(md.object)
+ sub.prop(md, "use_object_transform", text="", icon='GROUP')
+
+ layout.separator()
+
+ split = layout.split(0.333)
+ split.prop(md, "use_vert_data")
+ use_vert = md.use_vert_data
+ row = split.row()
+ row.active = use_vert
+ row.prop(md, "vert_mapping", text="")
+ if use_vert:
+ col = layout.column(align=True)
+ split = col.split(0.333, align=True)
+ sub = split.column(align=True)
+ sub.prop(md, "data_types_verts_vgroup")
+ row = split.row(align=True)
+ row.prop(md, "layers_vgroup_select_src", text="")
+ row.label(icon='RIGHTARROW_THIN')
+ row.prop(md, "layers_vgroup_select_dst", text="")
+ split = col.split(0.333, align=True)
+ sub = split.column(align=True)
+ sub.prop(md, "data_types_verts")
+
+ layout.separator()
+
+ split = layout.split(0.333)
+ split.prop(md, "use_edge_data")
+ use_edge = md.use_edge_data
+ row = split.row()
+ row.active = use_edge
+ row.prop(md, "edge_mapping", text="")
+ if use_edge:
+ col = layout.column(align=True)
+ split = col.split(0.333, align=True)
+ sub = split.column(align=True)
+ sub.prop(md, "data_types_edges")
+
+ layout.separator()
+
+ split = layout.split(0.333)
+ split.prop(md, "use_loop_data")
+ use_loop = md.use_loop_data
+ row = split.row()
+ row.active = use_loop
+ row.prop(md, "loop_mapping", text="")
+ if use_loop:
+ col = layout.column(align=True)
+ split = col.split(0.333, align=True)
+ sub = split.column(align=True)
+ sub.prop(md, "data_types_loops")
+ split = col.split(0.333, align=True)
+ sub = split.column(align=True)
+ sub.prop(md, "data_types_loops_vcol")
+ row = split.row(align=True)
+ row.prop(md, "layers_vcol_select_src", text="")
+ row.label(icon='RIGHTARROW')
+ row.prop(md, "layers_vcol_select_dst", text="")
+ split = col.split(0.333, align=True)
+ sub = split.column(align=True)
+ sub.prop(md, "data_types_loops_uv")
+ row = split.row(align=True)
+ row.prop(md, "layers_uv_select_src", text="")
+ row.label(icon='RIGHTARROW')
+ row.prop(md, "layers_uv_select_dst", text="")
+ col.prop(md, "islands_precision")
+
+ layout.separator()
+
+ split = layout.split(0.333)
+ split.prop(md, "use_poly_data")
+ use_poly = md.use_poly_data
+ row = split.row()
+ row.active = use_poly
+ row.prop(md, "poly_mapping", text="")
+ if use_poly:
+ col = layout.column(align=True)
+ split = col.split(0.333, align=True)
+ sub = split.column(align=True)
+ sub.prop(md, "data_types_polys")
+
+ layout.separator()
+
+ split = layout.split()
+ col = split.column()
+ row = col.row(align=True)
+ sub = row.row(align=True)
+ sub.active = md.use_max_distance
+ sub.prop(md, "max_distance")
+ row.prop(md, "use_max_distance", text="", icon='STYLUS_PRESSURE')
+
+ col = split.column()
+ col.prop(md, "ray_radius")
+
+ layout.separator()
+
+ split = layout.split()
+ col = split.column()
+ col.prop(md, "mix_mode")
+ col.prop(md, "mix_factor")
+
+ col = split.column()
+ row = col.row()
+ row.active = bool(md.object)
+ row.operator("object.datalayout_transfer", text="Generate Data Layers")
+ row = col.row(align=True)
+ row.prop_search(md, "vertex_group", ob, "vertex_groups", text="")
+ sub = row.row(align=True)
+ sub.active = bool(md.vertex_group)
+ sub.prop(md, "invert_vertex_group", text="", icon='ARROW_LEFTRIGHT')
+
+ def NORMAL_EDIT(self, layout, ob, md):
+ has_vgroup = bool(md.vertex_group)
+ needs_object_offset = (((md.mode == 'RADIAL') and not md.target) or
+ ((md.mode == 'DIRECTIONAL') and md.use_direction_parallel))
+
+ row = layout.row()
+ row.prop(md, "mode", expand=True)
+
+ split = layout.split()
+
+ col = split.column()
+ col.prop(md, "target", text="")
+ sub = col.column(align=True)
+ sub.active = needs_object_offset
+ sub.prop(md, "offset")
+ row = col.row(align=True)
+
+ col = split.column()
+ row = col.row()
+ row.active = (md.mode == 'DIRECTIONAL')
+ row.prop(md, "use_direction_parallel")
+
+ subcol = col.column(align=True)
+ subcol.label("Mix Mode:")
+ subcol.prop(md, "mix_mode", text="")
+ subcol.prop(md, "mix_factor")
+ row = subcol.row(align=True)
+ row.prop_search(md, "vertex_group", ob, "vertex_groups", text="")
+ sub = row.row(align=True)
+ sub.active = has_vgroup
+ sub.prop(md, "invert_vertex_group", text="", icon='ARROW_LEFTRIGHT')
+
+ def CORRECTIVE_SMOOTH(self, layout, ob, md):
+ is_bind = md.is_bind
+
+ layout.prop(md, "factor", text="Factor")
+ layout.prop(md, "iterations")
+
+ row = layout.row()
+ row.prop(md, "smooth_type")
+
+ split = layout.split()
+
+ col = split.column()
+ col.label(text="Vertex Group:")
+ row = col.row(align=True)
+ row.prop_search(md, "vertex_group", ob, "vertex_groups", text="")
+ row.prop(md, "invert_vertex_group", text="", icon='ARROW_LEFTRIGHT')
+
+ col = split.column()
+ col.prop(md, "use_only_smooth")
+ col.prop(md, "use_pin_boundary")
+
+ layout.prop(md, "rest_source")
+ if md.rest_source == 'BIND':
+ layout.operator("object.correctivesmooth_bind", text="Unbind" if is_bind else "Bind")
+
if __name__ == "__main__": # only for live edit.
bpy.utils.register_module(__name__)
diff --git a/release/scripts/startup/bl_ui/properties_data_speaker.py b/release/scripts/startup/bl_ui/properties_data_speaker.py
index ca922dfb544..5ed0f8c3265 100644
--- a/release/scripts/startup/bl_ui/properties_data_speaker.py
+++ b/release/scripts/startup/bl_ui/properties_data_speaker.py
@@ -22,7 +22,7 @@ from bpy.types import Panel
from rna_prop_ui import PropertyPanel
-class DataButtonsPanel():
+class DataButtonsPanel:
bl_space_type = 'PROPERTIES'
bl_region_type = 'WINDOW'
bl_context = "data"
diff --git a/release/scripts/startup/bl_ui/properties_freestyle.py b/release/scripts/startup/bl_ui/properties_freestyle.py
index 58818e90440..e0620447185 100644
--- a/release/scripts/startup/bl_ui/properties_freestyle.py
+++ b/release/scripts/startup/bl_ui/properties_freestyle.py
@@ -23,7 +23,7 @@ from bpy.types import Menu, Panel, UIList
# Render properties
-class RenderFreestyleButtonsPanel():
+class RenderFreestyleButtonsPanel:
bl_space_type = 'PROPERTIES'
bl_region_type = 'WINDOW'
bl_context = "render"
@@ -39,7 +39,7 @@ class RenderFreestyleButtonsPanel():
class RENDER_PT_freestyle(RenderFreestyleButtonsPanel, Panel):
bl_label = "Freestyle"
bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER', 'CYCLES'}
+ COMPAT_ENGINES = {'BLENDER_RENDER'}
def draw_header(self, context):
rd = context.scene.render
@@ -62,7 +62,7 @@ class RENDER_PT_freestyle(RenderFreestyleButtonsPanel, Panel):
# Render layer properties
-class RenderLayerFreestyleButtonsPanel():
+class RenderLayerFreestyleButtonsPanel:
bl_space_type = 'PROPERTIES'
bl_region_type = 'WINDOW'
bl_context = "render_layer"
@@ -74,8 +74,8 @@ class RenderLayerFreestyleButtonsPanel():
rd = context.scene.render
with_freestyle = bpy.app.build_options.freestyle
- return (scene and with_freestyle and rd.use_freestyle
- and rd.layers.active and(scene.render.engine in cls.COMPAT_ENGINES))
+ return (scene and with_freestyle and rd.use_freestyle and
+ rd.layers.active and(scene.render.engine in cls.COMPAT_ENGINES))
class RenderLayerFreestyleEditorButtonsPanel(RenderLayerFreestyleButtonsPanel):
@@ -95,7 +95,7 @@ class RENDERLAYER_UL_linesets(UIList):
if self.layout_type in {'DEFAULT', 'COMPACT'}:
layout.prop(lineset, "name", text="", emboss=False, icon_value=icon)
layout.prop(lineset, "show_render", text="", index=index)
- elif self.layout_type in {'GRID'}:
+ elif self.layout_type == 'GRID':
layout.alignment = 'CENTER'
layout.label("", icon_value=icon)
@@ -111,7 +111,7 @@ class RENDER_MT_lineset_specials(Menu):
class RENDERLAYER_PT_freestyle(RenderLayerFreestyleButtonsPanel, Panel):
bl_label = "Freestyle"
- COMPAT_ENGINES = {'BLENDER_RENDER', 'CYCLES'}
+ COMPAT_ENGINES = {'BLENDER_RENDER'}
def draw(self, context):
layout = self.layout
@@ -122,7 +122,9 @@ class RENDERLAYER_PT_freestyle(RenderLayerFreestyleButtonsPanel, Panel):
layout.active = rl.use_freestyle
+ row = layout.row()
layout.prop(freestyle, "mode", text="Control mode")
+ layout.prop(freestyle, "use_view_map_cache", text="View Map Cache")
layout.label(text="Edge Detection Options:")
split = layout.split()
@@ -165,7 +167,7 @@ class RENDERLAYER_PT_freestyle(RenderLayerFreestyleButtonsPanel, Panel):
class RENDERLAYER_PT_freestyle_lineset(RenderLayerFreestyleEditorButtonsPanel, Panel):
bl_label = "Freestyle Line Set"
- COMPAT_ENGINES = {'BLENDER_RENDER', 'CYCLES'}
+ COMPAT_ENGINES = {'BLENDER_RENDER'}
def draw_edge_type_buttons(self, box, lineset, edge_type):
# property names
@@ -257,7 +259,7 @@ class RENDERLAYER_PT_freestyle_lineset(RenderLayerFreestyleEditorButtonsPanel, P
class RENDERLAYER_PT_freestyle_linestyle(RenderLayerFreestyleEditorButtonsPanel, Panel):
bl_label = "Freestyle Line Style"
bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER', 'CYCLES'}
+ COMPAT_ENGINES = {'BLENDER_RENDER'}
def draw_modifier_box_header(self, box, modifier):
row = box.row()
@@ -281,6 +283,10 @@ class RENDERLAYER_PT_freestyle_linestyle(RenderLayerFreestyleEditorButtonsPanel,
sub.operator("scene.freestyle_modifier_move", icon='TRIA_DOWN', text="").direction = 'DOWN'
sub.operator("scene.freestyle_modifier_remove", icon='X', text="")
+ def draw_modifier_box_error(self, box, modifier, message):
+ row = box.row()
+ row.label(text=message, icon="ERROR")
+
def draw_modifier_common(self, box, modifier):
row = box.row()
row.prop(modifier, "blend", text="")
@@ -349,6 +355,32 @@ class RENDERLAYER_PT_freestyle_linestyle(RenderLayerFreestyleEditorButtonsPanel,
if show_ramp:
self.draw_modifier_color_ramp_common(box, modifier, False)
+ elif modifier.type == 'TANGENT':
+ self.draw_modifier_color_ramp_common(box, modifier, False)
+
+ elif modifier.type == 'NOISE':
+ self.draw_modifier_color_ramp_common(box, modifier, False)
+ row = box.row(align=False)
+ row.prop(modifier, "amplitude")
+ row.prop(modifier, "period")
+ row.prop(modifier, "seed")
+
+ elif modifier.type == 'CREASE_ANGLE':
+ self.draw_modifier_color_ramp_common(box, modifier, False)
+ row = box.row(align=True)
+ row.prop(modifier, "angle_min")
+ row.prop(modifier, "angle_max")
+
+ elif modifier.type == 'CURVATURE_3D':
+ self.draw_modifier_color_ramp_common(box, modifier, False)
+ row = box.row(align=True)
+ row.prop(modifier, "curvature_min")
+ row.prop(modifier, "curvature_max")
+ freestyle = context.scene.render.layers.active.freestyle_settings
+ if not freestyle.use_smoothness:
+ message = "Enable Face Smoothness to use this modifier"
+ self.draw_modifier_box_error(col.box(), modifier, message)
+
def draw_alpha_modifier(self, context, modifier):
layout = self.layout
@@ -378,6 +410,32 @@ class RENDERLAYER_PT_freestyle_linestyle(RenderLayerFreestyleEditorButtonsPanel,
box.prop(modifier, "material_attribute", text="")
self.draw_modifier_curve_common(box, modifier, False, False)
+ elif modifier.type == 'TANGENT':
+ self.draw_modifier_curve_common(box, modifier, False, False)
+
+ elif modifier.type == 'NOISE':
+ self.draw_modifier_curve_common(box, modifier, False, False)
+ row = box.row(align=False)
+ row.prop(modifier, "amplitude")
+ row.prop(modifier, "period")
+ row.prop(modifier, "seed")
+
+ elif modifier.type == 'CREASE_ANGLE':
+ self.draw_modifier_curve_common(box, modifier, False, False)
+ row = box.row(align=True)
+ row.prop(modifier, "angle_min")
+ row.prop(modifier, "angle_max")
+
+ elif modifier.type == 'CURVATURE_3D':
+ self.draw_modifier_curve_common(box, modifier, False, False)
+ row = box.row(align=True)
+ row.prop(modifier, "curvature_min")
+ row.prop(modifier, "curvature_max")
+ freestyle = context.scene.render.layers.active.freestyle_settings
+ if not freestyle.use_smoothness:
+ message = "Enable Face Smoothness to use this modifier"
+ self.draw_modifier_box_error(col.box(), modifier, message)
+
def draw_thickness_modifier(self, context, modifier):
layout = self.layout
@@ -413,6 +471,43 @@ class RENDERLAYER_PT_freestyle_linestyle(RenderLayerFreestyleEditorButtonsPanel,
row.prop(modifier, "thickness_min")
row.prop(modifier, "thickness_max")
+ elif modifier.type == 'TANGENT':
+ self.draw_modifier_curve_common(box, modifier, False, False)
+ self.mapping = 'CURVE'
+ row = box.row(align=True)
+ row.prop(modifier, "thickness_min")
+ row.prop(modifier, "thickness_max")
+
+ elif modifier.type == 'NOISE':
+ row = box.row(align=False)
+ row.prop(modifier, "amplitude")
+ row.prop(modifier, "period")
+ row = box.row(align=False)
+ row.prop(modifier, "seed")
+ row.prop(modifier, "use_asymmetric")
+
+ elif modifier.type == 'CREASE_ANGLE':
+ self.draw_modifier_curve_common(box, modifier, False, False)
+ row = box.row(align=True)
+ row.prop(modifier, "thickness_min")
+ row.prop(modifier, "thickness_max")
+ row = box.row(align=True)
+ row.prop(modifier, "angle_min")
+ row.prop(modifier, "angle_max")
+
+ elif modifier.type == 'CURVATURE_3D':
+ self.draw_modifier_curve_common(box, modifier, False, False)
+ row = box.row(align=True)
+ row.prop(modifier, "thickness_min")
+ row.prop(modifier, "thickness_max")
+ row = box.row(align=True)
+ row.prop(modifier, "curvature_min")
+ row.prop(modifier, "curvature_max")
+ freestyle = context.scene.render.layers.active.freestyle_settings
+ if not freestyle.use_smoothness:
+ message = "Enable Face Smoothness to use this modifier"
+ self.draw_modifier_box_error(col.box(), modifier, message)
+
def draw_geometry_modifier(self, context, modifier):
layout = self.layout
@@ -510,6 +605,9 @@ class RENDERLAYER_PT_freestyle_linestyle(RenderLayerFreestyleEditorButtonsPanel,
row.prop(modifier, "scale_y")
box.prop(modifier, "angle")
+ elif modifier.type == 'SIMPLIFICATION':
+ box.prop(modifier, "tolerance")
+
def draw(self, context):
layout = self.layout
@@ -579,6 +677,20 @@ class RENDERLAYER_PT_freestyle_linestyle(RenderLayerFreestyleEditorButtonsPanel,
sub.prop(linestyle, "split_dash3", text="D3")
sub.prop(linestyle, "split_gap3", text="G3")
+ ## Sorting
+ layout.prop(linestyle, "use_sorting", text="Sorting:")
+ col = layout.column()
+ col.active = linestyle.use_sorting
+ row = col.row(align=True)
+ row.prop(linestyle, "sort_key", text="")
+ sub = row.row()
+ sub.active = linestyle.sort_key in {'DISTANCE_FROM_CAMERA',
+ 'PROJECTED_X',
+ 'PROJECTED_Y'}
+ sub.prop(linestyle, "integration_type", text="")
+ row = col.row(align=True)
+ row.prop(linestyle, "sort_order", expand=True)
+
## Selection
layout.label(text="Selection:")
split = layout.split(align=True)
@@ -589,25 +701,18 @@ class RENDERLAYER_PT_freestyle_linestyle(RenderLayerFreestyleEditorButtonsPanel,
sub = row.row()
sub.active = linestyle.use_length_min
sub.prop(linestyle, "length_min")
- # Second column
- col = split.column()
row = col.row(align=True)
row.prop(linestyle, "use_length_max", text="")
sub = row.row()
sub.active = linestyle.use_length_max
sub.prop(linestyle, "length_max")
-
- ## Sorting
- layout.prop(linestyle, "use_sorting", text="Sorting:")
- col = layout.column()
- col.active = linestyle.use_sorting
+ # Second column
+ col = split.column()
row = col.row(align=True)
- row.prop(linestyle, "sort_key", text="")
+ row.prop(linestyle, "use_chain_count", text="")
sub = row.row()
- sub.active = linestyle.sort_key in {'DISTANCE_FROM_CAMERA'}
- sub.prop(linestyle, "integration_type", text="")
- row = col.row(align=True)
- row.prop(linestyle, "sort_order", expand=True)
+ sub.active = linestyle.use_chain_count
+ sub.prop(linestyle, "chain_count")
## Caps
layout.label(text="Caps:")
@@ -681,10 +786,11 @@ class RENDERLAYER_PT_freestyle_linestyle(RenderLayerFreestyleEditorButtonsPanel,
row.prop(linestyle, "texture_spacing", text="Spacing Along Stroke")
row = layout.row()
- op = row.operator("wm.properties_context_change",
- text="Go to Linestyle Textures Properties",
- icon='TEXTURE')
- op.context = 'TEXTURE'
+ props = row.operator(
+ "wm.properties_context_change",
+ text="Go to Linestyle Textures Properties",
+ icon='TEXTURE')
+ props.context = 'TEXTURE'
elif linestyle.panel == 'MISC':
pass
@@ -692,7 +798,7 @@ class RENDERLAYER_PT_freestyle_linestyle(RenderLayerFreestyleEditorButtonsPanel,
# Material properties
-class MaterialFreestyleButtonsPanel():
+class MaterialFreestyleButtonsPanel:
bl_space_type = 'PROPERTIES'
bl_region_type = 'WINDOW'
bl_context = "material"
@@ -710,7 +816,7 @@ class MaterialFreestyleButtonsPanel():
class MATERIAL_PT_freestyle_line(MaterialFreestyleButtonsPanel, Panel):
bl_label = "Freestyle Line"
bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER', 'CYCLES'}
+ COMPAT_ENGINES = {'BLENDER_RENDER'}
def draw(self, context):
layout = self.layout
diff --git a/release/scripts/startup/bl_ui/properties_game.py b/release/scripts/startup/bl_ui/properties_game.py
index 503b3cd234c..56cd4d0f491 100644
--- a/release/scripts/startup/bl_ui/properties_game.py
+++ b/release/scripts/startup/bl_ui/properties_game.py
@@ -21,7 +21,7 @@ import bpy
from bpy.types import Panel, Menu
-class PhysicsButtonsPanel():
+class PhysicsButtonsPanel:
bl_space_type = 'PROPERTIES'
bl_region_type = 'WINDOW'
bl_context = "physics"
@@ -89,10 +89,14 @@ class PHYSICS_PT_game_physics(PhysicsButtonsPanel, Panel):
split = layout.split()
col = split.column()
- col.label(text="Velocity:")
+ col.label(text="Linear velocity:")
sub = col.column(align=True)
sub.prop(game, "velocity_min", text="Minimum")
sub.prop(game, "velocity_max", text="Maximum")
+ col.label(text="Angular velocity:")
+ sub = col.column(align=True)
+ sub.prop(game, "angular_velocity_min", text="Minimum")
+ sub.prop(game, "angular_velocity_max", text="Maximum")
col = split.column()
col.label(text="Damping:")
@@ -110,6 +114,7 @@ class PHYSICS_PT_game_physics(PhysicsButtonsPanel, Panel):
col.prop(game, "lock_location_y", text="Y")
col.prop(game, "lock_location_z", text="Z")
+ if physics_type == 'RIGID_BODY':
col = split.column()
col.label(text="Lock Rotation:")
col.prop(game, "lock_rotation_x", text="X")
@@ -179,7 +184,7 @@ class PHYSICS_PT_game_physics(PhysicsButtonsPanel, Panel):
col.prop(game, "use_actor", text="Detect Actors")
col.prop(ob, "hide_render", text="Invisible")
- elif physics_type in {'INVISIBLE', 'NO_COLLISION', 'OCCLUDE'}:
+ elif physics_type in {'INVISIBLE', 'NO_COLLISION', 'OCCLUDER'}:
layout.prop(ob, "hide_render", text="Invisible")
elif physics_type == 'NAVMESH':
@@ -191,15 +196,6 @@ class PHYSICS_PT_game_physics(PhysicsButtonsPanel, Panel):
layout.operator("mesh.navmesh_reset")
layout.operator("mesh.navmesh_clear")
- if physics_type not in {'NO_COLLISION', 'OCCLUDE'}:
- layout.separator()
- split = layout.split()
-
- col = split.column()
- col.prop(game, "collision_group")
- col = split.column()
- col.prop(game, "collision_mask")
-
class PHYSICS_PT_game_collision_bounds(PhysicsButtonsPanel, Panel):
bl_label = "Collision Bounds"
@@ -209,7 +205,8 @@ class PHYSICS_PT_game_collision_bounds(PhysicsButtonsPanel, Panel):
def poll(cls, context):
game = context.object.game
rd = context.scene.render
- return (game.physics_type in {'DYNAMIC', 'RIGID_BODY', 'SENSOR', 'SOFT_BODY', 'STATIC', 'CHARACTER'}) and (rd.engine in cls.COMPAT_ENGINES)
+ return (rd.engine in cls.COMPAT_ENGINES) \
+ and (game.physics_type in {'SENSOR', 'STATIC', 'DYNAMIC', 'RIGID_BODY', 'CHARACTER', 'SOFT_BODY'})
def draw_header(self, context):
game = context.active_object.game
@@ -220,13 +217,25 @@ class PHYSICS_PT_game_collision_bounds(PhysicsButtonsPanel, Panel):
layout = self.layout
game = context.active_object.game
+ split = layout.split()
+ split.active = game.use_collision_bounds
- layout.active = game.use_collision_bounds
- layout.prop(game, "collision_bounds_type", text="Bounds")
+ col = split.column()
+ col.prop(game, "collision_bounds_type", text="Bounds")
- row = layout.row()
+ row = col.row()
row.prop(game, "collision_margin", text="Margin", slider=True)
- row.prop(game, "use_collision_compound", text="Compound")
+
+ sub = row.row()
+ sub.active = game.physics_type not in {'SOFT_BODY', 'CHARACTER'}
+ sub.prop(game, "use_collision_compound", text="Compound")
+
+ layout.separator()
+ split = layout.split()
+ col = split.column()
+ col.prop(game, "collision_group")
+ col = split.column()
+ col.prop(game, "collision_mask")
class PHYSICS_PT_game_obstacles(PhysicsButtonsPanel, Panel):
@@ -237,7 +246,8 @@ class PHYSICS_PT_game_obstacles(PhysicsButtonsPanel, Panel):
def poll(cls, context):
game = context.object.game
rd = context.scene.render
- return (game.physics_type in {'DYNAMIC', 'RIGID_BODY', 'SENSOR', 'SOFT_BODY', 'STATIC'}) and (rd.engine in cls.COMPAT_ENGINES)
+ return (rd.engine in cls.COMPAT_ENGINES) \
+ and (game.physics_type in {'SENSOR', 'STATIC', 'DYNAMIC', 'RIGID_BODY', 'SOFT_BODY', 'CHARACTER', 'NO_COLLISION'})
def draw_header(self, context):
game = context.active_object.game
@@ -256,7 +266,7 @@ class PHYSICS_PT_game_obstacles(PhysicsButtonsPanel, Panel):
row.label()
-class RenderButtonsPanel():
+class RenderButtonsPanel:
bl_space_type = 'PROPERTIES'
bl_region_type = 'WINDOW'
bl_context = "render"
@@ -393,7 +403,6 @@ class RENDER_PT_game_shading(RenderButtonsPanel, Panel):
col.prop(gs, "use_glsl_lights", text="Lights")
col.prop(gs, "use_glsl_shaders", text="Shaders")
col.prop(gs, "use_glsl_shadows", text="Shadows")
- col.prop(gs, "use_glsl_color_management", text="Color Management")
col = split.column()
col.prop(gs, "use_glsl_ramps", text="Ramps")
@@ -455,7 +464,7 @@ class RENDER_PT_game_display(RenderButtonsPanel, Panel):
col.prop(gs, "frame_color", text="")
-class SceneButtonsPanel():
+class SceneButtonsPanel:
bl_space_type = 'PROPERTIES'
bl_region_type = 'WINDOW'
bl_context = "scene"
@@ -519,23 +528,27 @@ class SCENE_PT_game_navmesh(SceneButtonsPanel, Panel):
row.prop(rd, "sample_max_error")
-class RENDER_PT_game_sound(RenderButtonsPanel, Panel):
- bl_label = "Sound"
+class SCENE_PT_game_hysteresis(SceneButtonsPanel, Panel):
+ bl_label = "Level of Detail"
COMPAT_ENGINES = {'BLENDER_GAME'}
- def draw(self, context):
- layout = self.layout
-
+ @classmethod
+ def poll(cls, context):
scene = context.scene
+ return (scene and scene.render.engine in cls.COMPAT_ENGINES)
- layout.prop(scene, "audio_distance_model")
+ def draw(self, context):
+ layout = self.layout
+ gs = context.scene.game_settings
- col = layout.column(align=True)
- col.prop(scene, "audio_doppler_speed", text="Speed")
- col.prop(scene, "audio_doppler_factor")
+ row = layout.row()
+ row.prop(gs, "use_scene_hysteresis", text="Hysteresis")
+ row = layout.row()
+ row.active = gs.use_scene_hysteresis
+ row.prop(gs, "scene_hysteresis_percentage", text="")
-class WorldButtonsPanel():
+class WorldButtonsPanel:
bl_space_type = 'PROPERTIES'
bl_region_type = 'WINDOW'
bl_context = "world"
@@ -691,7 +704,7 @@ class WORLD_PT_game_physics_obstacles(WorldButtonsPanel, Panel):
layout.prop(gs, "show_obstacle_simulation")
-class DataButtonsPanel():
+class DataButtonsPanel:
bl_space_type = 'PROPERTIES'
bl_region_type = 'WINDOW'
bl_context = "data"
@@ -724,6 +737,8 @@ class DATA_PT_shadow_game(DataButtonsPanel, Panel):
col = split.column()
col.prop(lamp, "shadow_color", text="")
+ if lamp.type == 'SUN':
+ col.prop(lamp, "show_shadow_box")
col = split.column()
col.prop(lamp, "use_shadow_layer", text="This Layer Only")
@@ -749,7 +764,7 @@ class DATA_PT_shadow_game(DataButtonsPanel, Panel):
row.prop(lamp, "shadow_frustum_size", text="Frustum Size")
-class ObjectButtonsPanel():
+class ObjectButtonsPanel:
bl_space_type = 'PROPERTIES'
bl_region_type = 'WINDOW'
bl_context = "object"
@@ -777,6 +792,7 @@ class OBJECT_PT_levels_of_detail(ObjectButtonsPanel, Panel):
def draw(self, context):
layout = self.layout
ob = context.object
+ gs = context.scene.game_settings
col = layout.column()
@@ -794,6 +810,13 @@ class OBJECT_PT_levels_of_detail(ObjectButtonsPanel, Panel):
row.prop(level, "use_mesh", text="")
row.prop(level, "use_material", text="")
+ row = box.row()
+ row.active = gs.use_scene_hysteresis
+ row.prop(level, "use_object_hysteresis", text="Hysteresis Override")
+ row = box.row()
+ row.active = gs.use_scene_hysteresis and level.use_object_hysteresis
+ row.prop(level, "object_hysteresis_percentage", text="")
+
row = col.row(align=True)
row.operator("object.lod_add", text="Add", icon='ZOOMIN')
row.menu("OBJECT_MT_lod_tools", text="", icon='TRIA_DOWN')
diff --git a/release/scripts/startup/bl_ui/properties_grease_pencil_common.py b/release/scripts/startup/bl_ui/properties_grease_pencil_common.py
index 4789d119192..91a986d8e50 100644
--- a/release/scripts/startup/bl_ui/properties_grease_pencil_common.py
+++ b/release/scripts/startup/bl_ui/properties_grease_pencil_common.py
@@ -19,11 +19,34 @@
# <pep8 compliant>
-class GreasePencilPanel():
+from bpy.types import Menu, UIList
+
+
+def gpencil_stroke_placement_settings(context, layout, gpd):
+ col = layout.column(align=True)
+
+ col.label(text="Stroke Placement:")
+
+ row = col.row(align=True)
+ row.prop_enum(gpd, "draw_mode", 'VIEW')
+ row.prop_enum(gpd, "draw_mode", 'CURSOR')
+
+ if context.space_data.type == 'VIEW_3D':
+ row = col.row(align=True)
+ row.prop_enum(gpd, "draw_mode", 'SURFACE')
+ row.prop_enum(gpd, "draw_mode", 'STROKE')
+
+ row = col.row(align=False)
+ row.active = gpd.draw_mode in {'SURFACE', 'STROKE'}
+ row.prop(gpd, "use_stroke_endpoints")
+
+
+class GreasePencilDrawingToolsPanel:
# subclass must set
# bl_space_type = 'IMAGE_EDITOR'
- # bl_region_type = 'TOOLS'
bl_label = "Grease Pencil"
+ bl_category = "Grease Pencil"
+ bl_region_type = 'TOOLS'
@staticmethod
def draw(self, context):
@@ -31,19 +54,442 @@ class GreasePencilPanel():
col = layout.column(align=True)
+ col.label(text="Draw:")
row = col.row(align=True)
row.operator("gpencil.draw", text="Draw").mode = 'DRAW'
- row.operator("gpencil.draw", text="Line").mode = 'DRAW_STRAIGHT'
+ row.operator("gpencil.draw", text="Erase").mode = 'ERASER'
row = col.row(align=True)
+ row.operator("gpencil.draw", text="Line").mode = 'DRAW_STRAIGHT'
row.operator("gpencil.draw", text="Poly").mode = 'DRAW_POLY'
- row.operator("gpencil.draw", text="Erase").mode = 'ERASER'
row = col.row(align=True)
- row.prop(context.tool_settings, "use_grease_pencil_sessions")
+ row.prop(context.tool_settings, "use_grease_pencil_sessions", text="Continuous Drawing")
+
+ if context.space_data.type in {'VIEW_3D', 'CLIP_EDITOR'}:
+ col.separator()
+ col.label("Data Source:")
+ row = col.row(align=True)
+ if context.space_data.type == 'VIEW_3D':
+ row.prop(context.tool_settings, "grease_pencil_source", expand=True)
+ elif context.space_data.type == 'CLIP_EDITOR':
+ row.prop(context.space_data, "grease_pencil_source", expand=True)
+
+ gpd = context.gpencil_data
+ if gpd:
+ col.separator()
+ gpencil_stroke_placement_settings(context, col, gpd)
if context.space_data.type == 'VIEW_3D':
col.separator()
+ col.separator()
- col.label(text="Measure:")
+ col.label(text="Tools:")
+ col.operator("gpencil.convert", text="Convert...")
col.operator("view3d.ruler")
+
+
+class GreasePencilStrokeEditPanel:
+ # subclass must set
+ # bl_space_type = 'IMAGE_EDITOR'
+ bl_label = "Edit Strokes"
+ bl_category = "Grease Pencil"
+ bl_region_type = 'TOOLS'
+
+ @classmethod
+ def poll(cls, context):
+ return (context.gpencil_data is not None)
+
+ @staticmethod
+ def draw(self, context):
+ layout = self.layout
+
+ gpd = context.gpencil_data
+ edit_ok = bool(context.editable_gpencil_strokes) and bool(gpd.use_stroke_edit_mode)
+
+ col = layout.column(align=True)
+ col.prop(gpd, "use_stroke_edit_mode", text="Enable Editing", icon='EDIT', toggle=True)
+
+ col.separator()
+
+ col.label(text="Select:")
+ subcol = col.column(align=True)
+ subcol.active = edit_ok
+ subcol.operator("gpencil.select_all", text="Select All")
+ subcol.operator("gpencil.select_border")
+ subcol.operator("gpencil.select_circle")
+
+ col.separator()
+
+ subcol = col.column(align=True)
+ subcol.active = edit_ok
+ subcol.operator("gpencil.select_linked")
+ subcol.operator("gpencil.select_more")
+ subcol.operator("gpencil.select_less")
+
+ col.separator()
+
+ col.label(text="Edit:")
+ row = col.row(align=True)
+ row.active = edit_ok
+ row.operator("gpencil.copy", text="Copy")
+ row.operator("gpencil.paste", text="Paste")
+
+ subcol = col.column(align=True)
+ subcol.active = edit_ok
+ subcol.operator("gpencil.delete", text="Delete")
+ subcol.operator("gpencil.duplicate_move", text="Duplicate")
+ subcol.operator("transform.mirror", text="Mirror").gpencil_strokes = True
+
+ col.separator()
+
+ subcol = col.column(align=True)
+ subcol.active = edit_ok
+ subcol.operator("transform.translate").gpencil_strokes = True # icon='MAN_TRANS'
+ subcol.operator("transform.rotate").gpencil_strokes = True # icon='MAN_ROT'
+ subcol.operator("transform.resize", text="Scale").gpencil_strokes = True # icon='MAN_SCALE'
+
+ col.separator()
+
+ subcol = col.column(align=True)
+ subcol.active = edit_ok
+ subcol.operator("transform.bend", text="Bend").gpencil_strokes = True
+ subcol.operator("transform.shear", text="Shear").gpencil_strokes = True
+ subcol.operator("transform.tosphere", text="To Sphere").gpencil_strokes = True
+
+
+###############################
+
+class GPENCIL_PIE_tool_palette(Menu):
+ """A pie menu for quick access to Grease Pencil tools"""
+ bl_label = "Grease Pencil Tools"
+
+ def draw(self, context):
+ layout = self.layout
+
+ pie = layout.menu_pie()
+ gpd = context.gpencil_data
+
+ # W - Drawing Types
+ col = pie.column()
+ col.operator("gpencil.draw", text="Draw", icon='GREASEPENCIL').mode = 'DRAW'
+ col.operator("gpencil.draw", text="Straight Lines", icon='LINE_DATA').mode = 'DRAW_STRAIGHT'
+ col.operator("gpencil.draw", text="Poly", icon='MESH_DATA').mode = 'DRAW_POLY'
+
+ # E - Eraser
+ # XXX: needs a dedicated icon...
+ col = pie.column()
+ col.operator("gpencil.draw", text="Eraser", icon='FORCE_CURVE').mode = 'ERASER'
+
+ # E - "Settings" Palette is included here too, since it needs to be in a stable position...
+ if gpd and gpd.layers.active:
+ col.separator()
+ col.operator("wm.call_menu_pie", text="Settings...", icon='SCRIPTWIN').name = "GPENCIL_PIE_settings_palette"
+
+ # Editing tools
+ if gpd:
+ if gpd.use_stroke_edit_mode and context.editable_gpencil_strokes:
+ # S - Exit Edit Mode
+ pie.prop(gpd, "use_stroke_edit_mode", text="Exit Edit Mode", icon='EDIT')
+
+ # N - Transforms
+ col = pie.column()
+ row = col.row(align=True)
+ row.operator("transform.translate", icon='MAN_TRANS').gpencil_strokes = True
+ row.operator("transform.rotate", icon='MAN_ROT').gpencil_strokes = True
+ row.operator("transform.resize", text="Scale", icon='MAN_SCALE').gpencil_strokes = True
+ row = col.row(align=True)
+ row.label("Proportional Edit:")
+ row.prop(context.tool_settings, "proportional_edit", text="", icon_only=True)
+ row.prop(context.tool_settings, "proportional_edit_falloff", text="", icon_only=True)
+
+ # NW - Select (Non-Modal)
+ col = pie.column()
+ col.operator("gpencil.select_all", text="Select All", icon='PARTICLE_POINT')
+ col.operator("gpencil.select_all", text="Select Inverse", icon='BLANK1')
+ col.operator("gpencil.select_linked", text="Select Linked", icon='LINKED')
+
+ # NE - Select (Modal)
+ col = pie.column()
+ col.operator("gpencil.select_border", text="Border Select", icon='BORDER_RECT')
+ col.operator("gpencil.select_circle", text="Circle Select", icon='META_EMPTY')
+ col.operator("gpencil.select_lasso", text="Lasso Select", icon='BORDER_LASSO')
+
+ # SW - Edit Tools
+ col = pie.column()
+ col.operator("gpencil.duplicate_move", icon='PARTICLE_PATH', text="Duplicate")
+ col.operator("gpencil.delete", icon='X', text="Delete...")
+
+ # SE - More Tools
+ pie.operator("wm.call_menu_pie", text="More...").name = "GPENCIL_PIE_tools_more"
+ else:
+ # Toggle Edit Mode
+ pie.prop(gpd, "use_stroke_edit_mode", text="Enable Stroke Editing", icon='EDIT')
+
+
+class GPENCIL_PIE_settings_palette(Menu):
+ """A pie menu for quick access to Grease Pencil settings"""
+ bl_label = "Grease Pencil Settings"
+
+ @classmethod
+ def poll(cls, context):
+ return bool(context.gpencil_data and context.active_gpencil_layer)
+
+ def draw(self, context):
+ layout = self.layout
+
+ pie = layout.menu_pie()
+ # gpd = context.gpencil_data
+ gpl = context.active_gpencil_layer
+
+ # W - Stroke draw settings
+ col = pie.column(align=True)
+ col.label(text="Stroke")
+ col.prop(gpl, "color", text="")
+ col.prop(gpl, "alpha", text="", slider=True)
+
+ # E - Fill draw settings
+ col = pie.column(align=True)
+ col.label(text="Fill")
+ col.prop(gpl, "fill_color", text="")
+ col.prop(gpl, "fill_alpha", text="", slider=True)
+
+ # S - Layer settings
+ col = pie.column()
+ col.prop(gpl, "line_width", slider=True)
+ # col.prop(gpl, "use_volumetric_strokes")
+ col.prop(gpl, "use_onion_skinning")
+
+ # N - Active Layer
+ # XXX: this should show an operator to change the active layer instead
+ col = pie.column()
+ col.label("Active Layer: ")
+ col.prop(gpl, "info", text="")
+ # col.prop(gpd, "layers")
+ row = col.row()
+ row.prop(gpl, "lock")
+ row.prop(gpl, "hide")
+
+
+class GPENCIL_PIE_tools_more(Menu):
+ """A pie menu for accessing more Grease Pencil tools"""
+ bl_label = "More Grease Pencil Tools"
+
+ @classmethod
+ def poll(cls, context):
+ gpd = context.gpencil_data
+ return bool(gpd and gpd.use_stroke_edit_mode and context.editable_gpencil_strokes)
+
+ def draw(self, context):
+ layout = self.layout
+
+ pie = layout.menu_pie()
+ # gpd = context.gpencil_data
+
+ col = pie.column(align=True)
+ col.operator("gpencil.copy", icon='COPYDOWN', text="Copy")
+ col.operator("gpencil.paste", icon='PASTEDOWN', text="Paste")
+
+ col = pie.column(align=True)
+ col.operator("gpencil.select_more", icon='ZOOMIN')
+ col.operator("gpencil.select_less", icon='ZOOMOUT')
+
+ pie.operator("transform.mirror", icon='MOD_MIRROR').gpencil_strokes = True
+ pie.operator("transform.bend", icon='MOD_SIMPLEDEFORM').gpencil_strokes = True
+ pie.operator("transform.shear", icon='MOD_TRIANGULATE').gpencil_strokes = True
+ pie.operator("transform.tosphere", icon='MOD_MULTIRES').gpencil_strokes = True
+
+ pie.operator("gpencil.convert", icon='OUTLINER_OB_CURVE', text="Convert...")
+ pie.operator("wm.call_menu_pie", text="Back to Main Palette...").name = "GPENCIL_PIE_tool_palette"
+
+
+###############################
+
+class GPENCIL_UL_layer(UIList):
+ def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index):
+ # assert(isinstance(item, bpy.types.GPencilLayer)
+ gpl = item
+
+ if self.layout_type in {'DEFAULT', 'COMPACT'}:
+ if gpl.lock:
+ layout.active = False
+
+ split = layout.split(percentage=0.25)
+ row = split.row(align=True)
+ row.prop(gpl, "color", text="", emboss=gpl.is_stroke_visible)
+ row.prop(gpl, "fill_color", text="", emboss=gpl.is_fill_visible)
+ split.prop(gpl, "info", text="", emboss=False)
+
+ row = layout.row(align=True)
+ row.prop(gpl, "lock", text="", emboss=False)
+ row.prop(gpl, "hide", text="", emboss=False)
+ elif self.layout_type == 'GRID':
+ layout.alignment = 'CENTER'
+ layout.label(text="", icon_value=icon)
+
+
+class GreasePencilDataPanel:
+ # subclass must set
+ # bl_space_type = 'IMAGE_EDITOR'
+ bl_label = "Grease Pencil"
+ bl_region_type = 'UI'
+
+ @staticmethod
+ def draw_header(self, context):
+ self.layout.prop(context.space_data, "show_grease_pencil", text="")
+
+ @staticmethod
+ def draw(self, context):
+ layout = self.layout
+
+ # owner of Grease Pencil data
+ gpd_owner = context.gpencil_data_owner
+ gpd = context.gpencil_data
+
+ # Owner Selector
+ if context.space_data.type == 'VIEW_3D':
+ layout.prop(context.tool_settings, "grease_pencil_source", expand=True)
+ elif context.space_data.type == 'CLIP_EDITOR':
+ layout.prop(context.space_data, "grease_pencil_source", expand=True)
+
+ # Grease Pencil data selector
+ layout.template_ID(gpd_owner, "grease_pencil", new="gpencil.data_add", unlink="gpencil.data_unlink")
+
+ # Grease Pencil data...
+ if (gpd is None) or (not gpd.layers):
+ layout.operator("gpencil.layer_add", text="New Layer")
+ else:
+ self.draw_layers(context, layout, gpd)
+
+ def draw_layers(self, context, layout, gpd):
+ row = layout.row()
+
+ col = row.column()
+ if len(gpd.layers) >= 2:
+ layer_rows = 5
+ else:
+ layer_rows = 2
+ col.template_list("GPENCIL_UL_layer", "", gpd, "layers", gpd.layers, "active_index", rows=layer_rows)
+
+ col = row.column()
+
+ sub = col.column(align=True)
+ sub.operator("gpencil.layer_add", icon='ZOOMIN', text="")
+ sub.operator("gpencil.layer_remove", icon='ZOOMOUT', text="")
+
+ gpl = context.active_gpencil_layer
+ if gpl:
+ sub.operator("gpencil.layer_duplicate", icon='COPY_ID', text="") # XXX: needs a dedicated icon
+
+ if len(gpd.layers) > 1:
+ col.separator()
+
+ sub = col.column(align=True)
+ sub.operator("gpencil.layer_move", icon='TRIA_UP', text="").type = 'UP'
+ sub.operator("gpencil.layer_move", icon='TRIA_DOWN', text="").type = 'DOWN'
+
+ if gpl:
+ self.draw_layer(layout, gpl)
+
+ def draw_layer(self, layout, gpl):
+ # layer settings
+ split = layout.split(percentage=0.5)
+ split.active = not gpl.lock
+
+ # Column 1 - Stroke
+ col = split.column(align=True)
+ col.label(text="Stroke:")
+ col.prop(gpl, "color", text="")
+ col.prop(gpl, "alpha", slider=True)
+
+ # Column 2 - Fill
+ col = split.column(align=True)
+ col.label(text="Fill:")
+ col.prop(gpl, "fill_color", text="")
+ col.prop(gpl, "fill_alpha", text="Opacity", slider=True)
+
+ # Options
+ split = layout.split(percentage=0.5)
+ split.active = not gpl.lock
+
+ col = split.column(align=True)
+ col.prop(gpl, "line_width", slider=True)
+ col.prop(gpl, "use_volumetric_strokes")
+
+ col = split.column(align=True)
+ col.prop(gpl, "show_x_ray")
+ col.prop(gpl, "show_points", text="Points")
+
+ layout.separator()
+
+ # Full-Row - Frame Locking (and Delete Frame)
+ row = layout.row(align=True)
+ row.active = not gpl.lock
+
+ if gpl.active_frame:
+ lock_status = "Locked" if gpl.lock_frame else "Unlocked"
+ lock_label = "Frame: %d (%s)" % (gpl.active_frame.frame_number, lock_status)
+ else:
+ lock_label = "Lock Frame"
+ row.prop(gpl, "lock_frame", text=lock_label, icon='UNLOCKED')
+ row.operator("gpencil.active_frame_delete", text="", icon='X')
+
+ layout.separator()
+
+ # Onion skinning
+ col = layout.column(align=True)
+ col.active = not gpl.lock
+
+ row = col.row()
+ row.prop(gpl, "use_onion_skinning")
+ row.prop(gpl, "use_ghost_custom_colors", text="", icon='COLOR')
+
+ split = col.split(percentage=0.5)
+ split.active = gpl.use_onion_skinning
+
+ # - Before Frames
+ sub = split.column(align=True)
+ row = sub.row(align=True)
+ row.active = gpl.use_ghost_custom_colors
+ row.prop(gpl, "before_color", text="")
+ sub.prop(gpl, "ghost_before_range", text="Before")
+
+ # - After Frames
+ sub = split.column(align=True)
+ row = sub.row(align=True)
+ row.active = gpl.use_ghost_custom_colors
+ row.prop(gpl, "after_color", text="")
+ sub.prop(gpl, "ghost_after_range", text="After")
+
+
+class GreasePencilToolsPanel:
+ # subclass must set
+ # bl_space_type = 'IMAGE_EDITOR'
+ # bl_options = {'DEFAULT_CLOSED'}
+ bl_label = "Grease Pencil Settings"
+ bl_region_type = 'UI'
+
+ @classmethod
+ def poll(cls, context):
+ return (context.gpencil_data is not None)
+
+ @staticmethod
+ def draw(self, context):
+ layout = self.layout
+
+ # gpd_owner = context.gpencil_data_owner
+ gpd = context.gpencil_data
+
+ layout.prop(gpd, "use_stroke_edit_mode", text="Enable Editing", icon='EDIT', toggle=True)
+
+ layout.separator()
+
+ layout.label("Proportional Edit:")
+ row = layout.row()
+ row.prop(context.tool_settings, "proportional_edit", text="")
+ row.prop(context.tool_settings, "proportional_edit_falloff", text="")
+
+ layout.separator()
+ layout.separator()
+
+ gpencil_stroke_placement_settings(context, layout, gpd)
diff --git a/release/scripts/startup/bl_ui/properties_mask_common.py b/release/scripts/startup/bl_ui/properties_mask_common.py
index 9a2857cc7b8..f4836da50bc 100644
--- a/release/scripts/startup/bl_ui/properties_mask_common.py
+++ b/release/scripts/startup/bl_ui/properties_mask_common.py
@@ -36,7 +36,7 @@ class MASK_UL_layers(UIList):
row.prop(mask, "hide", text="", emboss=False)
row.prop(mask, "hide_select", text="", emboss=False)
row.prop(mask, "hide_render", text="", emboss=False)
- elif self.layout_type in {'GRID'}:
+ elif self.layout_type == 'GRID':
layout.alignment = 'CENTER'
layout.label(text="", icon_value=icon)
@@ -112,7 +112,7 @@ class MASK_PT_layers:
row.prop(active_layer, "use_fill_holes", text="Holes")
-class MASK_PT_spline():
+class MASK_PT_spline:
# subclasses must define...
#~ bl_space_type = 'CLIP_EDITOR'
#~ bl_region_type = 'UI'
@@ -146,7 +146,7 @@ class MASK_PT_spline():
col.prop(spline, "use_self_intersection_check")
-class MASK_PT_point():
+class MASK_PT_point:
# subclasses must define...
#~ bl_space_type = 'CLIP_EDITOR'
#~ bl_region_type = 'UI'
@@ -173,8 +173,8 @@ class MASK_PT_point():
parent = point.parent
col = layout.column()
- # Currently only parenting yo movie clip is allowed, so do not
- # ver-oplicate things for now and use single template_ID
+ # Currently only parenting the movie-clip is allowed,
+ # so do not over-complicate things for now by using single template_ID
#col.template_any_ID(parent, "id", "id_type", text="")
col.label("Parent:")
@@ -190,7 +190,7 @@ class MASK_PT_point():
col.prop_search(parent, "parent", tracking,
"objects", icon='OBJECT_DATA', text="Object:")
- tracks_list = "tracks" if parent.type == 'POINT_TRACK' else 'plane_tracks'
+ tracks_list = "tracks" if parent.type == 'POINT_TRACK' else "plane_tracks"
if parent.parent in tracking.objects:
object = tracking.objects[parent.parent]
@@ -201,7 +201,7 @@ class MASK_PT_point():
tracks_list, icon='ANIM_DATA', text="Track:")
-class MASK_PT_display():
+class MASK_PT_display:
# subclasses must define...
#~ bl_space_type = 'CLIP_EDITOR'
#~ bl_region_type = 'UI'
@@ -227,7 +227,7 @@ class MASK_PT_display():
sub.prop(space_data, "mask_overlay_mode", text="")
-class MASK_PT_transforms():
+class MASK_PT_transforms:
# subclasses must define...
#~ bl_space_type = 'CLIP_EDITOR'
#~ bl_region_type = 'TOOLS'
@@ -251,7 +251,7 @@ class MASK_PT_transforms():
col.operator("transform.transform", text="Scale Feather").mode = 'MASK_SHRINKFATTEN'
-class MASK_PT_tools():
+class MASK_PT_tools:
# subclasses must define...
#~ bl_space_type = 'CLIP_EDITOR'
#~ bl_region_type = 'TOOLS'
@@ -289,7 +289,7 @@ class MASK_PT_tools():
col.operator("mask.shape_key_rekey", text="Re-Key Shape Points")
-class MASK_PT_add():
+class MASK_PT_add:
# subclasses must define...
#~ bl_space_type = 'CLIP_EDITOR'
#~ bl_region_type = 'TOOLS'
@@ -344,7 +344,7 @@ class MASK_MT_visibility(Menu):
layout = self.layout
layout.operator("mask.hide_view_clear", text="Show Hidden")
- layout.operator("mask.hide_view_set", text="Hide Selected")
+ layout.operator("mask.hide_view_set", text="Hide Selected").unselected = False
layout.operator("mask.hide_view_set", text="Hide Unselected").unselected = True
diff --git a/release/scripts/startup/bl_ui/properties_material.py b/release/scripts/startup/bl_ui/properties_material.py
index e3fcb0ef53e..d916007ea41 100644
--- a/release/scripts/startup/bl_ui/properties_material.py
+++ b/release/scripts/startup/bl_ui/properties_material.py
@@ -87,12 +87,12 @@ class MATERIAL_UL_matslots(UIList):
layout.label(text=iface_("Node %s") % manode.name, translate=False, icon_value=layout.icon(manode))
elif ma.use_nodes:
layout.label(text="Node <none>")
- elif self.layout_type in {'GRID'}:
+ elif self.layout_type == 'GRID':
layout.alignment = 'CENTER'
layout.label(text="", icon_value=icon)
-class MaterialButtonsPanel():
+class MaterialButtonsPanel:
bl_space_type = 'PROPERTIES'
bl_region_type = 'WINDOW'
bl_context = "material"
@@ -123,11 +123,16 @@ class MATERIAL_PT_context_material(MaterialButtonsPanel, Panel):
ob = context.object
slot = context.material_slot
space = context.space_data
+ is_sortable = (len(ob.material_slots) > 1)
if ob:
+ rows = 1
+ if is_sortable:
+ rows = 4
+
row = layout.row()
- row.template_list("MATERIAL_UL_matslots", "", ob, "material_slots", ob, "active_material_index", rows=1)
+ row.template_list("MATERIAL_UL_matslots", "", ob, "material_slots", ob, "active_material_index", rows=rows)
col = row.column(align=True)
col.operator("object.material_slot_add", icon='ZOOMIN', text="")
@@ -135,6 +140,12 @@ class MATERIAL_PT_context_material(MaterialButtonsPanel, Panel):
col.menu("MATERIAL_MT_specials", icon='DOWNARROW_HLT', text="")
+ if is_sortable:
+ col.separator()
+
+ col.operator("object.material_slot_move", icon='TRIA_UP', text="").direction = 'UP'
+ col.operator("object.material_slot_move", icon='TRIA_DOWN', text="").direction = 'DOWN'
+
if ob.mode == 'EDIT':
row = layout.row(align=True)
row.operator("object.material_slot_assign", text="Assign")
@@ -867,15 +878,17 @@ class MATERIAL_PT_transp_game(MaterialButtonsPanel, Panel):
base_mat = context.material
mat = active_node_mat(base_mat)
+ layout.active = mat.use_transparency
+
if simple_material(base_mat):
row = layout.row()
- row.active = mat.use_transparency
row.prop(mat, "transparency_method", expand=True)
layout.prop(mat, "alpha")
+ layout.prop(mat, "specular_alpha", text="Specular")
-class VolumeButtonsPanel():
+class VolumeButtonsPanel:
bl_space_type = 'PROPERTIES'
bl_region_type = 'WINDOW'
bl_context = "material"
diff --git a/release/scripts/startup/bl_ui/properties_object.py b/release/scripts/startup/bl_ui/properties_object.py
index 25367a58a54..3ff7a248c60 100644
--- a/release/scripts/startup/bl_ui/properties_object.py
+++ b/release/scripts/startup/bl_ui/properties_object.py
@@ -22,7 +22,7 @@ from bpy.types import Panel, Menu
from rna_prop_ui import PropertyPanel
-class ObjectButtonsPanel():
+class ObjectButtonsPanel:
bl_space_type = 'PROPERTIES'
bl_region_type = 'WINDOW'
bl_context = "object"
@@ -323,8 +323,10 @@ class OBJECT_PT_relations_extras(ObjectButtonsPanel, Panel):
layout.prop(ob, "use_extra_recalc_data")
-from bl_ui.properties_animviz import (MotionPathButtonsPanel,
- OnionSkinButtonsPanel)
+from bl_ui.properties_animviz import (
+ MotionPathButtonsPanel,
+ OnionSkinButtonsPanel,
+ )
class OBJECT_PT_motion_paths(MotionPathButtonsPanel, Panel):
diff --git a/release/scripts/startup/bl_ui/properties_paint_common.py b/release/scripts/startup/bl_ui/properties_paint_common.py
index 81bbc7754a7..cca142b645c 100644
--- a/release/scripts/startup/bl_ui/properties_paint_common.py
+++ b/release/scripts/startup/bl_ui/properties_paint_common.py
@@ -20,7 +20,7 @@
from bpy.types import Menu
-class UnifiedPaintPanel():
+class UnifiedPaintPanel:
# subclass must set
# bl_space_type = 'IMAGE_EDITOR'
# bl_region_type = 'UI'
@@ -36,7 +36,10 @@ class UnifiedPaintPanel():
elif context.weight_paint_object:
return toolsettings.weight_paint
elif context.image_paint_object:
- return toolsettings.image_paint
+ if (toolsettings.image_paint and toolsettings.image_paint.detect_data()):
+ return toolsettings.image_paint
+
+ return None
elif context.particle_edit_object:
return toolsettings.particle_edit
@@ -130,7 +133,7 @@ def brush_texpaint_common(panel, context, layout, brush, settings, projpaint=Fal
else:
row = col.row(align=True)
panel.prop_unified_color(row, context, brush, "color", text="")
- if brush.image_tool == 'FILL':
+ if brush.image_tool == 'FILL' and not projpaint:
col.prop(brush, "fill_threshold")
else:
panel.prop_unified_color(row, context, brush, "secondary_color", text="")
@@ -213,7 +216,9 @@ def brush_texpaint_common(panel, context, layout, brush, settings, projpaint=Fal
col = layout.column(align=True)
col.prop(brush, "use_accumulate")
- col.prop(brush, "use_alpha")
+ if projpaint:
+ col.prop(brush, "use_alpha")
+
col.prop(brush, "use_gradient")
col.separator()
@@ -240,24 +245,23 @@ def brush_texture_settings(layout, brush, sculpt):
layout.operator("brush.stencil_reset_transform")
# angle and texture_angle_source
- if brush.brush_capabilities.has_texture_angle:
+ if tex_slot.has_texture_angle:
col = layout.column()
col.label(text="Angle:")
- row = col.row(align=True)
- if brush.brush_capabilities.has_texture_angle_source:
- if brush.brush_capabilities.has_random_texture_angle:
+ col.prop(tex_slot, "angle", text="")
+ if tex_slot.has_texture_angle_source:
+ col.prop(tex_slot, "use_rake", text="Rake")
+
+ if brush.brush_capabilities.has_random_texture_angle and tex_slot.has_random_texture_angle:
if sculpt:
if brush.sculpt_capabilities.has_random_texture_angle:
- row.prop(brush, "texture_angle_source_random", text="")
- else:
- row.prop(brush, "texture_angle_source_no_random", text="")
-
+ col.prop(tex_slot, "use_random", text="Random")
+ if tex_slot.use_random:
+ col.prop(tex_slot, "random_angle", text="")
else:
- row.prop(brush, "texture_angle_source_random", text="")
- else:
- row.prop(brush, "texture_angle_source_no_random", text="")
-
- row.prop(tex_slot, "angle", text="")
+ col.prop(tex_slot, "use_random", text="Random")
+ if tex_slot.use_random:
+ col.prop(tex_slot, "random_angle", text="")
# scale and offset
split = layout.split()
@@ -287,9 +291,18 @@ def brush_mask_texture_settings(layout, brush):
col = layout.column()
col.prop(brush, "use_pressure_masking", text="")
- col.label(text="Angle:")
- col.active = brush.brush_capabilities.has_texture_angle
- col.prop(mask_tex_slot, "angle", text="")
+ # angle and texture_angle_source
+ if mask_tex_slot.has_texture_angle:
+ col = layout.column()
+ col.label(text="Angle:")
+ col.prop(mask_tex_slot, "angle", text="")
+ if mask_tex_slot.has_texture_angle_source:
+ col.prop(mask_tex_slot, "use_rake", text="Rake")
+
+ if brush.brush_capabilities.has_random_texture_angle and mask_tex_slot.has_random_texture_angle:
+ col.prop(mask_tex_slot, "use_random", text="Random")
+ if mask_tex_slot.use_random:
+ col.prop(mask_tex_slot, "random_angle", text="")
# scale and offset
split = layout.split()
diff --git a/release/scripts/startup/bl_ui/properties_particle.py b/release/scripts/startup/bl_ui/properties_particle.py
index 30fc3a9e373..e294f5487a6 100644
--- a/release/scripts/startup/bl_ui/properties_particle.py
+++ b/release/scripts/startup/bl_ui/properties_particle.py
@@ -18,15 +18,16 @@
# <pep8 compliant>
import bpy
-from bpy.types import Panel
+from bpy.types import Panel, Menu
from rna_prop_ui import PropertyPanel
from bpy.app.translations import pgettext_iface as iface_
-from bl_ui.properties_physics_common import (point_cache_ui,
- effector_weights_ui,
- basic_force_field_settings_ui,
- basic_force_field_falloff_ui,
- )
+from bl_ui.properties_physics_common import (
+ point_cache_ui,
+ effector_weights_ui,
+ basic_force_field_settings_ui,
+ basic_force_field_falloff_ui,
+ )
def particle_panel_enabled(context, psys):
@@ -63,7 +64,31 @@ def particle_get_settings(context):
return None
-class ParticleButtonsPanel():
+class PARTICLE_MT_specials(Menu):
+ bl_label = "Particle Specials"
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
+
+ def draw(self, context):
+ layout = self.layout
+
+ props = layout.operator("particle.copy_particle_systems", text="Copy Active to Selected Objects")
+ props.use_active = True
+ props.remove_target_particles = False
+
+ props = layout.operator("particle.copy_particle_systems", text="Copy All to Selected Objects")
+ props.use_active = False
+ props.remove_target_particles = True
+
+
+class PARTICLE_MT_hair_dynamics_presets(Menu):
+ bl_label = "Hair Dynamics Presets"
+ preset_subdir = "hair_dynamics"
+ preset_operator = "script.execute_preset"
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
+ draw = Menu.draw_preset
+
+
+class ParticleButtonsPanel:
bl_space_type = 'PROPERTIES'
bl_region_type = 'WINDOW'
bl_context = "particle"
@@ -73,6 +98,31 @@ class ParticleButtonsPanel():
return particle_panel_poll(cls, context)
+def find_modifier(ob, psys):
+ for md in ob.modifiers:
+ if md.type == 'PARTICLE_SYSTEM':
+ if md.particle_system == psys:
+ return md
+
+
+class PARTICLE_UL_particle_systems(bpy.types.UIList):
+ def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index, flt_flag):
+ ob = data
+ psys = item
+
+ if self.layout_type in {'DEFAULT', 'COMPACT'}:
+ md = find_modifier(ob, psys)
+
+ layout.prop(psys, "name", text="", emboss=False, icon_value=icon)
+ if md:
+ layout.prop(md, "show_render", emboss=False, icon_only=True, icon='RESTRICT_RENDER_OFF' if md.show_render else 'RESTRICT_RENDER_ON')
+ layout.prop(md, "show_viewport", emboss=False, icon_only=True, icon='RESTRICT_VIEW_OFF' if md.show_viewport else 'RESTRICT_VIEW_ON')
+
+ elif self.layout_type == 'GRID':
+ layout.alignment = 'CENTER'
+ layout.label(text="", icon_value=icon)
+
+
class PARTICLE_PT_context_particles(ParticleButtonsPanel, Panel):
bl_label = ""
bl_options = {'HIDE_HEADER'}
@@ -97,12 +147,13 @@ class PARTICLE_PT_context_particles(ParticleButtonsPanel, Panel):
if ob:
row = layout.row()
- row.template_list("UI_UL_list", "particle_systems", ob, "particle_systems",
+ row.template_list("PARTICLE_UL_particle_systems", "particle_systems", ob, "particle_systems",
ob.particle_systems, "active_index", rows=1)
col = row.column(align=True)
col.operator("object.particle_system_add", icon='ZOOMIN', text="")
col.operator("object.particle_system_remove", icon='ZOOMOUT', text="")
+ col.menu("PARTICLE_MT_specials", icon='DOWNARROW_HLT', text="")
if psys is None:
part = particle_get_settings(context)
@@ -278,30 +329,75 @@ class PARTICLE_PT_hair_dynamics(ParticleButtonsPanel, Panel):
if not psys.cloth:
return
- cloth = psys.cloth.settings
+ cloth_md = psys.cloth
+ cloth = cloth_md.settings
+ result = cloth_md.solver_result
layout.enabled = psys.use_hair_dynamics and psys.point_cache.is_baked is False
- split = layout.split()
+ row = layout.row(align=True)
+ row.menu("PARTICLE_MT_hair_dynamics_presets", text=bpy.types.PARTICLE_MT_hair_dynamics_presets.bl_label)
+ row.operator("particle.hair_dynamics_preset_add", text="", icon='ZOOMIN')
+ row.operator("particle.hair_dynamics_preset_add", text="", icon='ZOOMOUT').remove_active = True
+
+ split = layout.column()
col = split.column()
- col.label(text="Material:")
+ col.label(text="Structure")
+ col.prop(cloth, "mass")
sub = col.column(align=True)
- sub.prop(cloth, "pin_stiffness", text="Stiffness")
- sub.prop(cloth, "mass")
- sub.prop(cloth, "bending_stiffness", text="Bending")
- sub.prop(cloth, "internal_friction", slider=True)
- sub.prop(cloth, "collider_friction", slider=True)
+ subsub = sub.row(align=True)
+ subsub.prop(cloth, "bending_stiffness", text="Stiffness")
+ subsub.prop(psys.settings, "bending_random", text="Random")
+ sub.prop(cloth, "bending_damping", text="Damping")
+ # XXX has no noticeable effect with stiff hair structure springs
+ #col.prop(cloth, "spring_damping", text="Damping")
+
+ split.separator()
col = split.column()
- col.label(text="Damping:")
+ col.label(text="Volume")
+ col.prop(cloth, "air_damping", text="Air Drag")
+ col.prop(cloth, "internal_friction", slider=True)
sub = col.column(align=True)
- sub.prop(cloth, "spring_damping", text="Spring")
- sub.prop(cloth, "air_damping", text="Air")
+ sub.prop(cloth, "density_target", text="Density Target")
+ sub.prop(cloth, "density_strength", slider=True, text="Strength")
+ col.prop(cloth, "voxel_cell_size")
+
+ split.separator()
+
+ col = split.column()
+ col.label(text="Pinning")
+ col.prop(cloth, "pin_stiffness", text="Goal Strength")
+
+ split.separator()
+ col = split.column()
col.label(text="Quality:")
col.prop(cloth, "quality", text="Steps", slider=True)
+ row = col.row()
+ row.prop(psys.settings, "show_hair_grid", text="HairGrid")
+
+ if result:
+ box = layout.box()
+
+ if not result.status:
+ label = " "
+ icon = 'NONE'
+ elif result.status == {'SUCCESS'}:
+ label = "Success"
+ icon = 'NONE'
+ elif result.status - {'SUCCESS'} == {'NO_CONVERGENCE'}:
+ label = "No Convergence"
+ icon = 'ERROR'
+ else:
+ label = "ERROR"
+ icon = 'ERROR'
+ box.label(label, icon=icon)
+ box.label("Iterations: %d .. %d (avg. %d)" % (result.min_iterations, result.max_iterations, result.avg_iterations))
+ box.label("Error: %.5f .. %.5f (avg. %.5f)" % (result.min_error, result.max_error, result.avg_error))
+
class PARTICLE_PT_cache(ParticleButtonsPanel, Panel):
bl_label = "Cache"
@@ -999,6 +1095,7 @@ class PARTICLE_PT_draw(ParticleButtonsPanel, Panel):
row = layout.row()
row.prop(part, "draw_method", expand=True)
+ row.prop(part, "show_guide_hairs")
if part.draw_method == 'NONE' or (part.render_type == 'NONE' and part.draw_method == 'RENDER'):
return
@@ -1083,8 +1180,17 @@ class PARTICLE_PT_children(ParticleButtonsPanel, Panel):
col.label(text="Effects:")
sub = col.column(align=True)
- sub.prop(part, "clump_factor", slider=True)
- sub.prop(part, "clump_shape", slider=True)
+ sub.prop(part, "use_clump_curve")
+ if part.use_clump_curve:
+ sub.template_curve_mapping(part, "clump_curve")
+ else:
+ sub.prop(part, "clump_factor", slider=True)
+ sub.prop(part, "clump_shape", slider=True)
+ sub = col.column(align=True)
+ sub.prop(part, "use_clump_noise")
+ subsub = sub.column()
+ subsub.enabled = part.use_clump_noise
+ subsub.prop(part, "clump_noise_size")
sub = col.column(align=True)
sub.prop(part, "child_length", slider=True)
@@ -1108,20 +1214,28 @@ class PARTICLE_PT_children(ParticleButtonsPanel, Panel):
sub.prop(part, "child_parting_max", text="Max")
col = split.column()
- col.label(text="Roughness:")
- sub = col.column(align=True)
- sub.prop(part, "roughness_1", text="Uniform")
- sub.prop(part, "roughness_1_size", text="Size")
+ col.prop(part, "use_roughness_curve")
+ if part.use_roughness_curve:
+ sub = col.column()
+ sub.template_curve_mapping(part, "roughness_curve")
+ sub.prop(part, "roughness_1", text="Roughness")
+ sub.prop(part, "roughness_1_size", text="Size")
+ else:
+ col.label(text="Roughness:")
- sub = col.column(align=True)
- sub.prop(part, "roughness_endpoint", "Endpoint")
- sub.prop(part, "roughness_end_shape")
+ sub = col.column(align=True)
+ sub.prop(part, "roughness_1", text="Uniform")
+ sub.prop(part, "roughness_1_size", text="Size")
- sub = col.column(align=True)
- sub.prop(part, "roughness_2", text="Random")
- sub.prop(part, "roughness_2_size", text="Size")
- sub.prop(part, "roughness_2_threshold", slider=True)
+ sub = col.column(align=True)
+ sub.prop(part, "roughness_endpoint", "Endpoint")
+ sub.prop(part, "roughness_end_shape")
+
+ sub = col.column(align=True)
+ sub.prop(part, "roughness_2", text="Random")
+ sub.prop(part, "roughness_2_size", text="Size")
+ sub.prop(part, "roughness_2_threshold", slider=True)
layout.row().label(text="Kink:")
layout.row().prop(part, "kink", expand=True)
@@ -1129,14 +1243,27 @@ class PARTICLE_PT_children(ParticleButtonsPanel, Panel):
split = layout.split()
split.active = part.kink != 'NO'
- col = split.column()
- sub = col.column(align=True)
- sub.prop(part, "kink_amplitude")
- sub.prop(part, "kink_amplitude_clump", text="Clump", slider=True)
- col.prop(part, "kink_flat", slider=True)
- col = split.column(align=True)
- col.prop(part, "kink_frequency")
- col.prop(part, "kink_shape", slider=True)
+ if part.kink == 'SPIRAL':
+ col = split.column()
+ sub = col.column(align=True)
+ sub.prop(part, "kink_amplitude", text="Radius")
+ sub.prop(part, "kink_amplitude_random", text="Random", slider=True)
+ sub = col.column(align=True)
+ sub.prop(part, "kink_axis")
+ sub.prop(part, "kink_axis_random", text="Random", slider=True)
+ col = split.column(align=True)
+ col.prop(part, "kink_frequency", text="Frequency")
+ col.prop(part, "kink_shape", text="Shape", slider=True)
+ col.prop(part, "kink_extra_steps", text="Steps")
+ else:
+ col = split.column()
+ sub = col.column(align=True)
+ sub.prop(part, "kink_amplitude")
+ sub.prop(part, "kink_amplitude_clump", text="Clump", slider=True)
+ col.prop(part, "kink_flat", slider=True)
+ col = split.column(align=True)
+ col.prop(part, "kink_frequency")
+ col.prop(part, "kink_shape", slider=True)
class PARTICLE_PT_field_weights(ParticleButtonsPanel, Panel):
diff --git a/release/scripts/startup/bl_ui/properties_physics_cloth.py b/release/scripts/startup/bl_ui/properties_physics_cloth.py
index 327ee4035ef..a5cbffb2e2c 100644
--- a/release/scripts/startup/bl_ui/properties_physics_cloth.py
+++ b/release/scripts/startup/bl_ui/properties_physics_cloth.py
@@ -20,8 +20,10 @@
import bpy
from bpy.types import Menu, Panel
-from bl_ui.properties_physics_common import (point_cache_ui,
- effector_weights_ui)
+from bl_ui.properties_physics_common import (
+ point_cache_ui,
+ effector_weights_ui,
+ )
def cloth_panel_enabled(md):
@@ -35,7 +37,7 @@ class CLOTH_MT_presets(Menu):
draw = Menu.draw_preset
-class PhysicButtonsPanel():
+class PhysicButtonsPanel:
bl_space_type = 'PROPERTIES'
bl_region_type = 'WINDOW'
bl_context = "physics"
@@ -90,9 +92,6 @@ class PHYSICS_PT_cloth(PhysicButtonsPanel, Panel):
sub.prop_search(cloth, "vertex_group_mass", ob, "vertex_groups", text="")
sub.prop(cloth, "pin_stiffness", text="Stiffness")
- col.label(text="Pre roll:")
- col.prop(cloth, "pre_roll", text="Frames")
-
# Disabled for now
"""
if cloth.vertex_group_mass:
diff --git a/release/scripts/startup/bl_ui/properties_physics_common.py b/release/scripts/startup/bl_ui/properties_physics_common.py
index 4df8eab7d10..82eecf0fb5a 100644
--- a/release/scripts/startup/bl_ui/properties_physics_common.py
+++ b/release/scripts/startup/bl_ui/properties_physics_common.py
@@ -23,7 +23,7 @@ from bpy.types import Panel
from bpy.app.translations import contexts as i18n_contexts
-class PhysicButtonsPanel():
+class PhysicButtonsPanel:
bl_space_type = 'PROPERTIES'
bl_region_type = 'WINDOW'
bl_context = "physics"
@@ -191,7 +191,7 @@ def point_cache_ui(self, context, cache, enabled, cachetype):
col.operator("ptcache.bake", text="Bake").bake = True
sub = col.row()
- sub.enabled = (cache.frames_skipped or cache.is_outdated) and enabled
+ sub.enabled = (cache.is_frame_skip or cache.is_outdated) and enabled
sub.operator("ptcache.bake", text="Calculate To Frame").bake = False
sub = col.column()
diff --git a/release/scripts/startup/bl_ui/properties_physics_dynamicpaint.py b/release/scripts/startup/bl_ui/properties_physics_dynamicpaint.py
index 6a6d8dcff4a..269ffa6d371 100644
--- a/release/scripts/startup/bl_ui/properties_physics_dynamicpaint.py
+++ b/release/scripts/startup/bl_ui/properties_physics_dynamicpaint.py
@@ -20,9 +20,10 @@
import bpy
from bpy.types import Panel, UIList
-from bl_ui.properties_physics_common import (point_cache_ui,
- effector_weights_ui,
- )
+from bl_ui.properties_physics_common import (
+ point_cache_ui,
+ effector_weights_ui,
+ )
class PHYSICS_UL_dynapaint_surfaces(UIList):
@@ -39,14 +40,14 @@ class PHYSICS_UL_dynapaint_surfaces(UIList):
row.prop(surf, "show_preview", text="", emboss=False,
icon='RESTRICT_VIEW_OFF' if surf.show_preview else 'RESTRICT_VIEW_ON')
row.prop(surf, "is_active", text="")
- elif self.layout_type in {'GRID'}:
+ elif self.layout_type == 'GRID':
layout.alignment = 'CENTER'
row = layout.row(align=True)
row.label(text="", icon_value=icon)
row.label(text="", icon_value=sticon)
-class PhysicButtonsPanel():
+class PhysicButtonsPanel:
bl_space_type = 'PROPERTIES'
bl_region_type = 'WINDOW'
bl_context = "physics"
diff --git a/release/scripts/startup/bl_ui/properties_physics_field.py b/release/scripts/startup/bl_ui/properties_physics_field.py
index 933a9aa12a3..348f66da145 100644
--- a/release/scripts/startup/bl_ui/properties_physics_field.py
+++ b/release/scripts/startup/bl_ui/properties_physics_field.py
@@ -20,12 +20,13 @@
import bpy
from bpy.types import Panel
-from bl_ui.properties_physics_common import (basic_force_field_settings_ui,
- basic_force_field_falloff_ui,
- )
+from bl_ui.properties_physics_common import (
+ basic_force_field_settings_ui,
+ basic_force_field_falloff_ui,
+ )
-class PhysicButtonsPanel():
+class PhysicButtonsPanel:
bl_space_type = 'PROPERTIES'
bl_region_type = 'WINDOW'
bl_context = "physics"
diff --git a/release/scripts/startup/bl_ui/properties_physics_fluid.py b/release/scripts/startup/bl_ui/properties_physics_fluid.py
index 7b96d784fed..d6fd8f3792c 100644
--- a/release/scripts/startup/bl_ui/properties_physics_fluid.py
+++ b/release/scripts/startup/bl_ui/properties_physics_fluid.py
@@ -29,7 +29,7 @@ class FLUID_MT_presets(Menu):
draw = Menu.draw_preset
-class PhysicButtonsPanel():
+class PhysicButtonsPanel:
bl_space_type = 'PROPERTIES'
bl_region_type = 'WINDOW'
bl_context = "physics"
diff --git a/release/scripts/startup/bl_ui/properties_physics_rigidbody.py b/release/scripts/startup/bl_ui/properties_physics_rigidbody.py
index 5f589c499d3..e7225d73e41 100644
--- a/release/scripts/startup/bl_ui/properties_physics_rigidbody.py
+++ b/release/scripts/startup/bl_ui/properties_physics_rigidbody.py
@@ -21,7 +21,7 @@ import bpy
from bpy.types import Panel
-class PHYSICS_PT_rigidbody_panel():
+class PHYSICS_PT_rigidbody_panel:
bl_space_type = 'PROPERTIES'
bl_region_type = 'WINDOW'
bl_context = "physics"
diff --git a/release/scripts/startup/bl_ui/properties_physics_rigidbody_constraint.py b/release/scripts/startup/bl_ui/properties_physics_rigidbody_constraint.py
index dcf63f25079..3f5e0f1fc9b 100644
--- a/release/scripts/startup/bl_ui/properties_physics_rigidbody_constraint.py
+++ b/release/scripts/startup/bl_ui/properties_physics_rigidbody_constraint.py
@@ -21,7 +21,7 @@ import bpy
from bpy.types import Panel
-class PHYSICS_PT_rigidbody_constraint_panel():
+class PHYSICS_PT_rigidbody_constraint_panel:
bl_space_type = 'PROPERTIES'
bl_region_type = 'WINDOW'
bl_context = "physics"
diff --git a/release/scripts/startup/bl_ui/properties_physics_smoke.py b/release/scripts/startup/bl_ui/properties_physics_smoke.py
index 5bdbbd70ee6..85d3c1d7dc4 100644
--- a/release/scripts/startup/bl_ui/properties_physics_smoke.py
+++ b/release/scripts/startup/bl_ui/properties_physics_smoke.py
@@ -20,11 +20,13 @@
import bpy
from bpy.types import Panel
-from bl_ui.properties_physics_common import (point_cache_ui,
- effector_weights_ui)
+from bl_ui.properties_physics_common import (
+ point_cache_ui,
+ effector_weights_ui,
+ )
-class PhysicButtonsPanel():
+class PhysicButtonsPanel:
bl_space_type = 'PROPERTIES'
bl_region_type = 'WINDOW'
bl_context = "physics"
@@ -79,12 +81,12 @@ class PHYSICS_PT_smoke(PhysicButtonsPanel, Panel):
layout.prop(flow, "smoke_flow_type", expand=False)
- if flow.smoke_flow_type != "OUTFLOW":
+ if flow.smoke_flow_type != 'OUTFLOW':
split = layout.split()
col = split.column()
col.label(text="Flow Source:")
col.prop(flow, "smoke_flow_source", expand=False, text="")
- if flow.smoke_flow_source == "PARTICLES":
+ if flow.smoke_flow_source == 'PARTICLES':
col.label(text="Particle System:")
col.prop_search(flow, "particle_system", ob, "particle_systems", text="")
col.prop(flow, "use_particle_size", text="Set Size")
@@ -101,7 +103,7 @@ class PHYSICS_PT_smoke(PhysicButtonsPanel, Panel):
sub = sub.column()
sub.active = flow.use_initial_velocity
sub.prop(flow, "velocity_factor")
- if flow.smoke_flow_source == "MESH":
+ if flow.smoke_flow_source == 'MESH':
sub.prop(flow, "velocity_normal")
#sub.prop(flow, "velocity_random")
@@ -133,7 +135,7 @@ class PHYSICS_PT_smoke_flow_advanced(PhysicButtonsPanel, Panel):
@classmethod
def poll(cls, context):
md = context.smoke
- return md and (md.smoke_type == 'FLOW') and (md.flow_settings.smoke_flow_source == "MESH")
+ return md and (md.smoke_type == 'FLOW') and (md.flow_settings.smoke_flow_source == 'MESH')
def draw(self, context):
layout = self.layout
@@ -149,9 +151,9 @@ class PHYSICS_PT_smoke_flow_advanced(PhysicButtonsPanel, Panel):
sub.prop(flow, "noise_texture", text="")
sub.label(text="Mapping:")
sub.prop(flow, "texture_map_type", expand=False, text="")
- if flow.texture_map_type == "UV":
+ if flow.texture_map_type == 'UV':
sub.prop_search(flow, "uv_layer", ob.data, "uv_textures", text="")
- if flow.texture_map_type == "AUTO":
+ if flow.texture_map_type == 'AUTO':
sub.prop(flow, "texture_size")
sub.prop(flow, "texture_offset")
diff --git a/release/scripts/startup/bl_ui/properties_physics_softbody.py b/release/scripts/startup/bl_ui/properties_physics_softbody.py
index 17366f59016..e74cac3d06b 100644
--- a/release/scripts/startup/bl_ui/properties_physics_softbody.py
+++ b/release/scripts/startup/bl_ui/properties_physics_softbody.py
@@ -20,15 +20,17 @@
import bpy
from bpy.types import Panel
-from bl_ui.properties_physics_common import (point_cache_ui,
- effector_weights_ui)
+from bl_ui.properties_physics_common import (
+ point_cache_ui,
+ effector_weights_ui,
+ )
def softbody_panel_enabled(md):
return (md.point_cache.is_baked is False)
-class PhysicButtonsPanel():
+class PhysicButtonsPanel:
bl_space_type = 'PROPERTIES'
bl_region_type = 'WINDOW'
bl_context = "physics"
diff --git a/release/scripts/startup/bl_ui/properties_render.py b/release/scripts/startup/bl_ui/properties_render.py
index 9ffd244d78f..1f1802aa373 100644
--- a/release/scripts/startup/bl_ui/properties_render.py
+++ b/release/scripts/startup/bl_ui/properties_render.py
@@ -43,7 +43,7 @@ class RENDER_MT_framerate_presets(Menu):
draw = Menu.draw_preset
-class RenderButtonsPanel():
+class RenderButtonsPanel:
bl_space_type = 'PROPERTIES'
bl_region_type = 'WINDOW'
bl_context = "render"
@@ -274,7 +274,7 @@ class RENDER_PT_performance(RenderButtonsPanel, Panel):
col.prop(rd, "tile_y", text="Y")
col.separator()
- col.prop(rd, 'preview_start_resolution')
+ col.prop(rd, "preview_start_resolution")
col = split.column()
col.label(text="Memory:")
@@ -334,28 +334,25 @@ class RENDER_PT_post_processing(RenderButtonsPanel, Panel):
class RENDER_PT_stamp(RenderButtonsPanel, Panel):
- bl_label = "Stamp"
+ bl_label = "Metadata"
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER'}
- def draw_header(self, context):
- rd = context.scene.render
-
- self.layout.prop(rd, "use_stamp", text="")
-
def draw(self, context):
layout = self.layout
rd = context.scene.render
- layout.active = rd.use_stamp
+ layout.prop(rd, "use_stamp")
+ col = layout.column()
+ col.active = rd.use_stamp
+ col.prop(rd, "stamp_font_size", text="Font Size")
- layout.prop(rd, "stamp_font_size", text="Font Size")
-
- row = layout.row()
+ row = col.row()
row.column().prop(rd, "stamp_foreground", slider=True)
row.column().prop(rd, "stamp_background", slider=True)
+ layout.label("Enabled Metadata")
split = layout.split()
col = split.column()
@@ -377,6 +374,9 @@ class RENDER_PT_stamp(RenderButtonsPanel, Panel):
sub = row.row()
sub.active = rd.use_stamp_note
sub.prop(rd, "stamp_note_text", text="")
+ if rd.use_sequencer:
+ layout.label("Sequencer")
+ layout.prop(rd, "use_stamp_strip_meta")
class RENDER_PT_output(RenderButtonsPanel, Panel):
@@ -404,6 +404,8 @@ class RENDER_PT_output(RenderButtonsPanel, Panel):
col.prop(rd, "use_render_cache")
layout.template_image_settings(image_settings, color_management=False)
+ if rd.use_multiview:
+ layout.template_image_views(image_settings)
if file_format == 'QUICKTIME':
quicktime = rd.quicktime
@@ -457,8 +459,12 @@ class RENDER_PT_encoding(RenderButtonsPanel, Panel):
split = layout.split()
split.prop(rd.ffmpeg, "format")
- if ffmpeg.format in {'AVI', 'QUICKTIME', 'MKV', 'OGG'}:
+ if ffmpeg.format in {'AVI', 'QUICKTIME', 'MKV', 'OGG', 'MPEG4'}:
split.prop(ffmpeg, "codec")
+ if ffmpeg.codec == 'H264':
+ row = layout.row()
+ row.label()
+ row.prop(ffmpeg, "use_lossless_output")
elif rd.ffmpeg.format == 'H264':
split.prop(ffmpeg, "use_lossless_output")
else:
diff --git a/release/scripts/startup/bl_ui/properties_render_layer.py b/release/scripts/startup/bl_ui/properties_render_layer.py
index 2494e49d812..9b8bc237db9 100644
--- a/release/scripts/startup/bl_ui/properties_render_layer.py
+++ b/release/scripts/startup/bl_ui/properties_render_layer.py
@@ -21,7 +21,7 @@ import bpy
from bpy.types import Panel, UIList
-class RenderLayerButtonsPanel():
+class RenderLayerButtonsPanel:
bl_space_type = 'PROPERTIES'
bl_region_type = 'WINDOW'
bl_context = "render_layer"
@@ -40,7 +40,7 @@ class RENDERLAYER_UL_renderlayers(UIList):
if self.layout_type in {'DEFAULT', 'COMPACT'}:
layout.prop(layer, "name", text="", icon_value=icon, emboss=False)
layout.prop(layer, "use", text="", index=index)
- elif self.layout_type in {'GRID'}:
+ elif self.layout_type == 'GRID':
layout.alignment = 'CENTER'
layout.label("", icon_value=icon)
@@ -48,7 +48,7 @@ class RENDERLAYER_UL_renderlayers(UIList):
class RENDERLAYER_PT_layers(RenderLayerButtonsPanel, Panel):
bl_label = "Layer List"
bl_options = {'HIDE_HEADER'}
- COMPAT_ENGINES = {'BLENDER_RENDER'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
def draw(self, context):
layout = self.layout
@@ -56,6 +56,10 @@ class RENDERLAYER_PT_layers(RenderLayerButtonsPanel, Panel):
scene = context.scene
rd = scene.render
+ if rd.engine == 'BLENDER_GAME':
+ layout.label("Not available in the Game Engine")
+ return
+
row = layout.row()
col = row.column()
col.template_list("RENDERLAYER_UL_renderlayers", "", rd, "layers", rd.layers, "active_index", rows=2)
@@ -83,7 +87,7 @@ class RENDERLAYER_PT_layer_options(RenderLayerButtonsPanel, Panel):
col = split.column()
col.prop(scene, "layers", text="Scene")
col.label(text="")
- col.prop(rl, "light_override", text="Light")
+ col.prop(rl, "light_override", text="Lights")
col.prop(rl, "material_override", text="Material")
col = split.column()
@@ -122,7 +126,8 @@ class RENDERLAYER_PT_layer_passes(RenderLayerButtonsPanel, Panel):
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER'}
- def draw_pass_type_buttons(self, box, rl, pass_type):
+ @staticmethod
+ def draw_pass_type_buttons(box, rl, pass_type):
# property names
use_pass_type = "use_pass_" + pass_type
exclude_pass_type = "exclude_" + pass_type
@@ -163,5 +168,64 @@ class RENDERLAYER_PT_layer_passes(RenderLayerButtonsPanel, Panel):
self.draw_pass_type_buttons(col, rl, "refraction")
+class RENDERLAYER_UL_renderviews(UIList):
+ def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index):
+ # assert(isinstance(item, bpy.types.SceneRenderView)
+ view = item
+ if self.layout_type in {'DEFAULT', 'COMPACT'}:
+ if view.name in {'left', 'right'}:
+ layout.label(view.name, icon_value=icon + (not view.use))
+ else:
+ layout.prop(view, "name", text="", index=index, icon_value=icon, emboss=False)
+ layout.prop(view, "use", text="", index=index)
+
+ elif self.layout_type == 'GRID':
+ layout.alignment = 'CENTER'
+ layout.label("", icon_value=icon + (not view.use))
+
+
+class RENDERLAYER_PT_views(RenderLayerButtonsPanel, Panel):
+ bl_label = "Views"
+ COMPAT_ENGINES = {'BLENDER_RENDER'}
+ bl_options = {'DEFAULT_CLOSED'}
+
+ def draw_header(self, context):
+ rd = context.scene.render
+ self.layout.prop(rd, "use_multiview", text="")
+
+ def draw(self, context):
+ layout = self.layout
+
+ scene = context.scene
+ rd = scene.render
+ rv = rd.views.active
+
+ layout.active = rd.use_multiview
+ basic_stereo = rd.views_format == 'STEREO_3D'
+
+ row = layout.row()
+ row.prop(rd, "views_format", expand=True)
+
+ if basic_stereo:
+ row = layout.row()
+ row.template_list("RENDERLAYER_UL_renderviews", "name", rd, "stereo_views", rd.views, "active_index", rows=2)
+
+ row = layout.row()
+ row.label(text="File Suffix:")
+ row.prop(rv, "file_suffix", text="")
+
+ else:
+ row = layout.row()
+ row.template_list("RENDERLAYER_UL_renderviews", "name", rd, "views", rd.views, "active_index", rows=2)
+
+ col = row.column(align=True)
+ col.operator("scene.render_view_add", icon='ZOOMIN', text="")
+ col.operator("scene.render_view_remove", icon='ZOOMOUT', text="")
+
+ row = layout.row()
+ row.label(text="Camera Suffix:")
+ row.prop(rv, "camera_suffix", text="")
+
+
if __name__ == "__main__": # only for live edit.
bpy.utils.register_module(__name__)
diff --git a/release/scripts/startup/bl_ui/properties_scene.py b/release/scripts/startup/bl_ui/properties_scene.py
index 049161fdce8..bbf11abe6d9 100644
--- a/release/scripts/startup/bl_ui/properties_scene.py
+++ b/release/scripts/startup/bl_ui/properties_scene.py
@@ -22,9 +22,9 @@ from bpy.types import Panel, UIList
from rna_prop_ui import PropertyPanel
from bl_ui.properties_physics_common import (
- point_cache_ui,
- effector_weights_ui,
- )
+ point_cache_ui,
+ effector_weights_ui,
+ )
class SCENE_UL_keying_set_paths(UIList):
@@ -35,12 +35,12 @@ class SCENE_UL_keying_set_paths(UIList):
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'}:
+ elif self.layout_type == 'GRID':
layout.alignment = 'CENTER'
layout.label(text="", icon_value=icon)
-class SceneButtonsPanel():
+class SceneButtonsPanel:
bl_space_type = 'PROPERTIES'
bl_region_type = 'WINDOW'
bl_context = "scene"
@@ -62,7 +62,8 @@ class SCENE_PT_scene(SceneButtonsPanel, Panel):
layout.prop(scene, "camera")
layout.prop(scene, "background_set", text="Background")
- layout.prop(scene, "active_clip", text="Active Clip")
+ if context.scene.render.engine != 'BLENDER_GAME':
+ layout.prop(scene, "active_clip", text="Active Clip")
class SCENE_PT_unit(SceneButtonsPanel, Panel):
@@ -84,7 +85,59 @@ class SCENE_PT_unit(SceneButtonsPanel, Panel):
row.prop(unit, "use_separate")
-class SCENE_PT_keying_sets(SceneButtonsPanel, Panel):
+class SceneKeyingSetsPanel:
+
+ @staticmethod
+ def draw_keyframing_settings(context, layout, ks, ksp):
+ SceneKeyingSetsPanel._draw_keyframing_setting(
+ context, layout, ks, ksp, "Needed",
+ "use_insertkey_override_needed", "use_insertkey_needed",
+ userpref_fallback="use_keyframe_insert_needed")
+
+ SceneKeyingSetsPanel._draw_keyframing_setting(
+ context, layout, ks, ksp, "Visual",
+ "use_insertkey_override_visual", "use_insertkey_visual",
+ userpref_fallback="use_visual_keying")
+
+ SceneKeyingSetsPanel._draw_keyframing_setting(
+ context, layout, ks, ksp, "XYZ to RGB",
+ "use_insertkey_override_xyz_to_rgb", "use_insertkey_xyz_to_rgb")
+
+ @staticmethod
+ def _draw_keyframing_setting(context, layout, ks, ksp, label, toggle_prop, prop, userpref_fallback=None):
+ if ksp:
+ item = ksp
+
+ if getattr(ks, toggle_prop):
+ owner = ks
+ propname = prop
+ else:
+ owner = context.user_preferences.edit
+ if userpref_fallback:
+ propname = userpref_fallback
+ else:
+ propname = prop
+ else:
+ item = ks
+
+ owner = context.user_preferences.edit
+ if userpref_fallback:
+ propname = userpref_fallback
+ else:
+ propname = prop
+
+ row = layout.row(align=True)
+ row.prop(item, toggle_prop, text="", icon='STYLUS_PRESSURE', toggle=True) # XXX: needs dedicated icon
+
+ subrow = row.row()
+ subrow.active = getattr(item, toggle_prop)
+ if subrow.active:
+ subrow.prop(item, prop, text=label)
+ else:
+ subrow.prop(owner, propname, text=label)
+
+
+class SCENE_PT_keying_sets(SceneButtonsPanel, SceneKeyingSetsPanel, Panel):
bl_label = "Keying Sets"
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
@@ -114,10 +167,10 @@ class SCENE_PT_keying_sets(SceneButtonsPanel, Panel):
col = row.column()
col.label(text="Keyframing Settings:")
- col.prop(ks, "bl_options")
+ self.draw_keyframing_settings(context, col, ks, None)
-class SCENE_PT_keying_set_paths(SceneButtonsPanel, Panel):
+class SCENE_PT_keying_set_paths(SceneButtonsPanel, SceneKeyingSetsPanel, Panel):
bl_label = "Active Keying Set"
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
@@ -170,7 +223,7 @@ class SCENE_PT_keying_set_paths(SceneButtonsPanel, Panel):
col = row.column()
col.label(text="Keyframing Settings:")
- col.prop(ksp, "bl_options")
+ self.draw_keyframing_settings(context, col, ks, ksp)
class SCENE_PT_color_management(SceneButtonsPanel, Panel):
@@ -216,10 +269,11 @@ class SCENE_PT_audio(SceneButtonsPanel, Panel):
split = layout.split()
col = split.column()
- col.label("Listener:")
+ col.label("Distance Model:")
col.prop(scene, "audio_distance_model", text="")
- col.prop(scene, "audio_doppler_speed", text="Speed")
- col.prop(scene, "audio_doppler_factor", text="Doppler")
+ sub = col.column(align=True)
+ sub.prop(scene, "audio_doppler_speed", text="Speed")
+ sub.prop(scene, "audio_doppler_factor", text="Doppler")
col = split.column()
col.label("Format:")
@@ -344,14 +398,17 @@ class SCENE_PT_simplify(SceneButtonsPanel, Panel):
split = layout.split()
col = split.column()
+ col.label(text="Viewport:")
col.prop(rd, "simplify_subdivision", text="Subdivision")
col.prop(rd, "simplify_child_particles", text="Child Particles")
- col.prop(rd, "use_simplify_triangulate")
-
col = split.column()
+ col.label(text="Render:")
+ col.prop(rd, "simplify_subdivision_render", text="Subdivision")
+ col.prop(rd, "simplify_child_particles_render", text="Child Particles")
col.prop(rd, "simplify_shadow_samples", text="Shadow Samples")
col.prop(rd, "simplify_ao_sss", text="AO and SSS")
+ col.prop(rd, "use_simplify_triangulate")
class SCENE_PT_custom_props(SceneButtonsPanel, PropertyPanel, Panel):
diff --git a/release/scripts/startup/bl_ui/properties_texture.py b/release/scripts/startup/bl_ui/properties_texture.py
index faf0d4cb0e8..78ea4fa6c3f 100644
--- a/release/scripts/startup/bl_ui/properties_texture.py
+++ b/release/scripts/startup/bl_ui/properties_texture.py
@@ -20,14 +20,16 @@
import bpy
from bpy.types import Menu, Panel, UIList
-from bpy.types import (Brush,
- Lamp,
- Material,
- Object,
- ParticleSettings,
- FreestyleLineStyle,
- Texture,
- World)
+from bpy.types import (
+ Brush,
+ FreestyleLineStyle,
+ Lamp,
+ Material,
+ Object,
+ ParticleSettings,
+ Texture,
+ World,
+ )
from rna_prop_ui import PropertyPanel
@@ -70,7 +72,7 @@ class TEXTURE_UL_texslots(UIList):
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'}:
+ elif self.layout_type == 'GRID':
layout.alignment = 'CENTER'
layout.label(text="", icon_value=icon)
@@ -114,7 +116,7 @@ def id_tex_datablock(bid):
return bid
-class TextureButtonsPanel():
+class TextureButtonsPanel:
bl_space_type = 'PROPERTIES'
bl_region_type = 'WINDOW'
bl_context = "texture"
@@ -133,8 +135,8 @@ class TEXTURE_PT_context_texture(TextureButtonsPanel, Panel):
@classmethod
def poll(cls, context):
engine = context.scene.render.engine
- #if not (hasattr(context, "texture_slot") or hasattr(context, "texture_node")):
- #return False
+ # if not (hasattr(context, "texture_slot") or hasattr(context, "texture_node")):
+ # return False
return ((context.material or
context.world or
context.lamp or
@@ -172,14 +174,13 @@ class TEXTURE_PT_context_texture(TextureButtonsPanel, Panel):
if user or pin_id:
layout.separator()
- split = layout.split(percentage=0.65)
- col = split.column()
+ row = layout.row()
if pin_id:
- col.template_ID(space, "pin_id")
+ row.template_ID(space, "pin_id")
else:
propname = context.texture_user_property.identifier
- col.template_ID(user, propname, new="texture.new")
+ row.template_ID(user, propname, new="texture.new")
if tex:
split = layout.split(percentage=0.2)
@@ -227,7 +228,7 @@ class TEXTURE_PT_context_texture(TextureButtonsPanel, Panel):
class TEXTURE_PT_preview(TextureButtonsPanel, Panel):
bl_label = "Preview"
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME', 'CYCLES'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
def draw(self, context):
layout = self.layout
@@ -675,8 +676,7 @@ class TEXTURE_PT_musgrave(TextureTypePanel, Panel):
col = split.column()
if musgrave_type in {'HETERO_TERRAIN', 'RIDGED_MULTIFRACTAL', 'HYBRID_MULTIFRACTAL'}:
col.prop(tex, "offset")
- if musgrave_type in {'MULTIFRACTAL', 'RIDGED_MULTIFRACTAL', 'HYBRID_MULTIFRACTAL'}:
- col.prop(tex, "noise_intensity", text="Intensity")
+ col.prop(tex, "noise_intensity", text="Intensity")
if musgrave_type in {'RIDGED_MULTIFRACTAL', 'HYBRID_MULTIFRACTAL'}:
col.prop(tex, "gain")
@@ -771,6 +771,9 @@ class TEXTURE_PT_voxeldata(TextureButtonsPanel, Panel):
elif vd.file_format == 'SMOKE':
layout.prop(vd, "domain_object")
layout.prop(vd, "smoke_data_type")
+ elif vd.file_format == 'HAIR':
+ layout.prop(vd, "domain_object")
+ layout.prop(vd, "hair_data_type")
elif vd.file_format == 'IMAGE_SEQUENCE':
layout.template_ID(tex, "image", open="image.open")
layout.template_image(tex, "image", tex.image_user, compact=True)
@@ -1161,7 +1164,8 @@ class TEXTURE_PT_influence(TextureSlotPanel, Panel):
factor_but(col, "use_map_clump", "clump_factor", "Clump")
col = split.column()
- factor_but(col, "use_map_kink", "kink_factor", "Kink")
+ factor_but(col, "use_map_kink_amp", "kink_amp_factor", "Kink Amplitude")
+ factor_but(col, "use_map_kink_freq", "kink_freq_factor", "Kink Frequency")
factor_but(col, "use_map_rough", "rough_factor", "Rough")
elif isinstance(idblock, FreestyleLineStyle):
diff --git a/release/scripts/startup/bl_ui/properties_world.py b/release/scripts/startup/bl_ui/properties_world.py
index 0b6ce41eb5d..2c8a6fac967 100644
--- a/release/scripts/startup/bl_ui/properties_world.py
+++ b/release/scripts/startup/bl_ui/properties_world.py
@@ -22,7 +22,7 @@ from bpy.types import Panel
from rna_prop_ui import PropertyPanel
-class WorldButtonsPanel():
+class WorldButtonsPanel:
bl_space_type = 'PROPERTIES'
bl_region_type = 'WINDOW'
bl_context = "world"
@@ -49,7 +49,6 @@ class WORLD_PT_context_world(WorldButtonsPanel, Panel):
scene = context.scene
world = context.world
space = context.space_data
- rd = context.scene.render
texture_count = world and len(world.texture_slots.keys())
@@ -59,7 +58,7 @@ class WORLD_PT_context_world(WorldButtonsPanel, Panel):
elif world:
split.template_ID(space, "pin_id")
- if texture_count and rd.engine != 'CYCLES':
+ if texture_count:
split.label(text=str(texture_count), icon='TEXTURE')
diff --git a/release/scripts/startup/bl_ui/space_clip.py b/release/scripts/startup/bl_ui/space_clip.py
index 3382633af60..ed4a78420d8 100644
--- a/release/scripts/startup/bl_ui/space_clip.py
+++ b/release/scripts/startup/bl_ui/space_clip.py
@@ -21,7 +21,11 @@
import bpy
from bpy.types import Panel, Header, Menu, UIList
from bpy.app.translations import pgettext_iface as iface_
-from bl_ui.properties_grease_pencil_common import GreasePencilPanel
+from bl_ui.properties_grease_pencil_common import (
+ GreasePencilDrawingToolsPanel,
+ GreasePencilStrokeEditPanel,
+ GreasePencilDataPanel
+ )
class CLIP_UL_tracking_objects(UIList):
@@ -33,7 +37,7 @@ class CLIP_UL_tracking_objects(UIList):
layout.prop(tobj, "name", text="", emboss=False,
icon='CAMERA_DATA' if tobj.is_camera
else 'OBJECT_DATA')
- elif self.layout_type in {'GRID'}:
+ elif self.layout_type == 'GRID':
layout.alignment = 'CENTER'
layout.label(text="",
icon='CAMERA_DATA' if tobj.is_camera
@@ -143,7 +147,7 @@ class CLIP_HT_header(Header):
sc = context.space_data
- if sc.mode in {'TRACKING'}:
+ if sc.mode == 'TRACKING':
self._draw_tracking(context)
else:
self._draw_masking(context)
@@ -422,7 +426,9 @@ class CLIP_PT_tools_solve(CLIP_PT_tracking_panel, Panel):
col = layout.column()
row = col.row()
row.prop(settings, "use_tripod_solver", text="Tripod")
- row.prop(settings, "use_keyframe_selection", text="Keyframe")
+ sub = row.row()
+ sub.active = not settings.use_tripod_solver
+ sub.prop(settings, "use_keyframe_selection", text="Keyframe")
col = layout.column(align=True)
col.active = (not settings.use_tripod_solver and
@@ -461,6 +467,7 @@ class CLIP_PT_tools_cleanup(CLIP_PT_tracking_panel, Panel):
layout.prop(settings, "clean_frames", text="Frames")
layout.prop(settings, "clean_error", text="Error")
layout.prop(settings, "clean_action", text="")
+ layout.operator("clip.filter_tracks")
class CLIP_PT_tools_geometry(CLIP_PT_tracking_panel, Panel):
@@ -709,7 +716,7 @@ class CLIP_PT_tracking_camera(Panel):
if CLIP_PT_clip_view_panel.poll(context):
sc = context.space_data
- return sc.mode in {'TRACKING'} and sc.clip
+ return sc.mode == 'TRACKING' and sc.clip
return False
@@ -749,7 +756,7 @@ class CLIP_PT_tracking_lens(Panel):
if CLIP_PT_clip_view_panel.poll(context):
sc = context.space_data
- return sc.mode in {'TRACKING'} and sc.clip
+ return sc.mode == 'TRACKING' and sc.clip
return False
@@ -886,7 +893,7 @@ class CLIP_PT_stabilization(CLIP_PT_reconstruction_panel, Panel):
if CLIP_PT_clip_view_panel.poll(context):
sc = context.space_data
- return sc.mode in {'TRACKING'} and sc.clip
+ return sc.mode == 'TRACKING' and sc.clip
return False
@@ -980,7 +987,9 @@ class CLIP_PT_proxy(CLIP_PT_clip_view_panel, Panel):
if clip.use_proxy_custom_directory:
col.prop(clip.proxy, "directory")
- col.operator("clip.rebuild_proxy", text="Build Proxy")
+ col.operator("clip.rebuild_proxy",
+ text="Build Proxy / Timecode" if clip.source == 'MOVIE'
+ else "Build Proxy")
if clip.source == 'MOVIE':
col2 = col.column()
@@ -997,15 +1006,16 @@ class CLIP_PT_proxy(CLIP_PT_clip_view_panel, Panel):
# -----------------------------------------------------------------------------
# Mask (similar code in space_image.py, keep in sync)
-
-from bl_ui.properties_mask_common import (MASK_PT_mask,
- MASK_PT_layers,
- MASK_PT_spline,
- MASK_PT_point,
- MASK_PT_display,
- MASK_PT_tools,
- MASK_PT_transforms,
- MASK_PT_add)
+from bl_ui.properties_mask_common import (
+ MASK_PT_mask,
+ MASK_PT_layers,
+ MASK_PT_spline,
+ MASK_PT_point,
+ MASK_PT_display,
+ MASK_PT_tools,
+ MASK_PT_transforms,
+ MASK_PT_add,
+ )
class CLIP_PT_mask_layers(MASK_PT_layers, Panel):
@@ -1050,12 +1060,6 @@ class CLIP_PT_tools_mask(MASK_PT_tools, Panel):
# --- end mask ---
-class CLIP_PT_tools_grease_pencil(GreasePencilPanel, Panel):
- bl_space_type = 'CLIP_EDITOR'
- bl_region_type = 'TOOLS'
- bl_category = "Grease Pencil"
-
-
class CLIP_PT_footage(CLIP_PT_clip_view_panel, Panel):
bl_space_type = 'CLIP_EDITOR'
bl_region_type = 'UI'
@@ -1110,6 +1114,26 @@ class CLIP_PT_tools_scenesetup(Panel):
layout.operator("clip.setup_tracking_scene")
+# Grease Pencil properties
+class CLIP_PT_grease_pencil(GreasePencilDataPanel, CLIP_PT_clip_view_panel, Panel):
+ bl_space_type = 'CLIP_EDITOR'
+ bl_region_type = 'UI'
+ bl_options = {'DEFAULT_CLOSED'}
+
+ # NOTE: this is just a wrapper around the generic GP Panel
+ # But, this should only be visible in "clip" view
+
+
+# Grease Pencil drawing tools
+class CLIP_PT_tools_grease_pencil_draw(GreasePencilDrawingToolsPanel, Panel):
+ bl_space_type = 'CLIP_EDITOR'
+
+
+# Grease Pencil stroke editing tools
+class CLIP_PT_tools_grease_pencil_edit(GreasePencilStrokeEditPanel, Panel):
+ bl_space_type = 'CLIP_EDITOR'
+
+
class CLIP_MT_view(Menu):
bl_label = "View"
@@ -1125,12 +1149,15 @@ class CLIP_MT_view(Menu):
layout.operator("clip.view_selected")
layout.operator("clip.view_all")
+ layout.operator("clip.view_all", text="View Fit").fit_view = True
layout.separator()
layout.operator("clip.view_zoom_in")
layout.operator("clip.view_zoom_out")
layout.separator()
+ layout.prop(sc, "show_metadata")
+ layout.separator()
ratios = ((1, 8), (1, 4), (1, 2), (1, 1), (2, 1), (4, 1), (8, 1))
@@ -1152,7 +1179,8 @@ class CLIP_MT_view(Menu):
layout.separator()
layout.operator("screen.area_dupli")
- layout.operator("screen.screen_full_area")
+ layout.operator("screen.screen_full_area", text="Toggle Maximize Area")
+ layout.operator("screen.screen_full_area").use_hide_panels = True
class CLIP_MT_clip(Menu):
@@ -1193,14 +1221,17 @@ class CLIP_MT_track(Menu):
layout.operator("clip.solve_camera")
layout.separator()
- layout.operator("clip.clear_track_path",
- text="Clear After").action = 'REMAINED'
+ props = layout.operator("clip.clear_track_path", text="Clear After")
+ props.clear_active = False
+ props.action = 'REMAINED'
- layout.operator("clip.clear_track_path",
- text="Clear Before").action = 'UPTO'
+ props = layout.operator("clip.clear_track_path", text="Clear Before")
+ props.clear_active = False
+ props.action = 'UPTO'
- layout.operator("clip.clear_track_path",
- text="Clear Track Path").action = 'ALL'
+ props = layout.operator("clip.clear_track_path", text="Clear Track Path")
+ props.clear_active = False
+ props.action = 'ALL'
layout.separator()
layout.operator("clip.join_tracks")
@@ -1213,16 +1244,21 @@ class CLIP_MT_track(Menu):
layout.operator("clip.paste_tracks")
layout.separator()
- layout.operator("clip.track_markers",
- text="Track Frame Backwards").backwards = True
+ props = layout.operator("clip.track_markers", text="Track Frame Backwards")
+ props.backwards = True
+ props.sequence = False
props = layout.operator("clip.track_markers", text="Track Backwards")
props.backwards = True
props.sequence = True
- layout.operator("clip.track_markers",
- text="Track Forwards").sequence = True
- layout.operator("clip.track_markers", text="Track Frame Forwards")
+ props = layout.operator("clip.track_markers", text="Track Forwards")
+ props.backwards = False
+ props.sequence = True
+
+ props = layout.operator("clip.track_markers", text="Track Frame Forwards")
+ props.backwards = False
+ props.sequence = False
layout.separator()
layout.operator("clip.delete_track")
@@ -1246,8 +1282,8 @@ class CLIP_MT_reconstruction(Menu):
layout.operator("clip.set_plane", text="Set Floor").plane = 'FLOOR'
layout.operator("clip.set_plane", text="Set Wall").plane = 'WALL'
- layout.operator("clip.set_axis", text="Set X Axis").axis = "X"
- layout.operator("clip.set_axis", text="Set Y Axis").axis = "Y"
+ layout.operator("clip.set_axis", text="Set X Axis").axis = 'X'
+ layout.operator("clip.set_axis", text="Set Y Axis").axis = 'Y'
layout.operator("clip.set_scale")
@@ -1264,10 +1300,8 @@ class CLIP_MT_track_visibility(Menu):
layout = self.layout
layout.operator("clip.hide_tracks_clear", text="Show Hidden")
- layout.operator("clip.hide_tracks", text="Hide Selected")
-
- layout.operator("clip.hide_tracks",
- text="Hide Unselected").unselected = True
+ layout.operator("clip.hide_tracks", text="Hide Selected").unselected = False
+ layout.operator("clip.hide_tracks", text="Hide Unselected").unselected = True
class CLIP_MT_track_transform(Menu):
diff --git a/release/scripts/startup/bl_ui/space_console.py b/release/scripts/startup/bl_ui/space_console.py
index ec16cfd89be..327fb94cb95 100644
--- a/release/scripts/startup/bl_ui/space_console.py
+++ b/release/scripts/startup/bl_ui/space_console.py
@@ -70,7 +70,8 @@ class CONSOLE_MT_console(Menu):
layout.separator()
layout.operator("screen.area_dupli")
- layout.operator("screen.screen_full_area")
+ layout.operator("screen.screen_full_area", text="Toggle Maximize Area")
+ layout.operator("screen.screen_full_area").use_hide_panels = True
class CONSOLE_MT_language(Menu):
diff --git a/release/scripts/startup/bl_ui/space_dopesheet.py b/release/scripts/startup/bl_ui/space_dopesheet.py
index eeb08916416..7fd9719a6e3 100644
--- a/release/scripts/startup/bl_ui/space_dopesheet.py
+++ b/release/scripts/startup/bl_ui/space_dopesheet.py
@@ -51,6 +51,11 @@ def dopesheet_filter(layout, context, genericFiltersOnly=False):
row.prop(dopesheet, "show_only_matching_fcurves", text="")
if dopesheet.show_only_matching_fcurves:
row.prop(dopesheet, "filter_fcurve_name", text="")
+ else:
+ row = layout.row(align=True)
+ row.prop(dopesheet, "use_filter_text", text="")
+ if dopesheet.use_filter_text:
+ row.prop(dopesheet, "filter_text", text="")
if not genericFiltersOnly:
row = layout.row(align=True)
@@ -91,6 +96,8 @@ def dopesheet_filter(layout, context, genericFiltersOnly=False):
row.prop(dopesheet, "show_speakers", text="")
if bpy.data.linestyles:
row.prop(dopesheet, "show_linestyles", text="")
+ if bpy.data.grease_pencil:
+ row.prop(dopesheet, "show_gpencil", text="")
#######################################
@@ -103,6 +110,7 @@ class DOPESHEET_HT_header(Header):
layout = self.layout
st = context.space_data
+ toolsettings = context.tool_settings
row = layout.row(align=True)
row.template_header()
@@ -110,6 +118,18 @@ class DOPESHEET_HT_header(Header):
DOPESHEET_MT_editor_menus.draw_collapsible(context, layout)
layout.prop(st, "mode", text="")
+
+ if st.mode in {'ACTION', 'SHAPEKEY'}:
+ row = layout.row(align=True)
+ row.operator("action.layer_prev", text="", icon='TRIA_DOWN')
+ row.operator("action.layer_next", text="", icon='TRIA_UP')
+
+ layout.template_ID(st, "action", new="action.new", unlink="action.unlink")
+
+ row = layout.row(align=True)
+ row.operator("action.push_down", text="Push Down", icon='NLA_PUSHDOWN')
+ row.operator("action.stash", text="Stash", icon='FREEZE')
+
layout.prop(st.dopesheet, "show_summary", text="Summary")
if st.mode == 'DOPESHEET':
@@ -119,8 +139,12 @@ class DOPESHEET_HT_header(Header):
# filters which will work here and are useful (especially for character animation)
dopesheet_filter(layout, context, genericFiltersOnly=True)
- if st.mode in {'ACTION', 'SHAPEKEY'}:
- layout.template_ID(st, "action", new="action.new")
+ row = layout.row(align=True)
+ row.prop(toolsettings, "use_proportional_action",
+ text="", icon_only=True)
+ if toolsettings.use_proportional_action:
+ row.prop(toolsettings, "proportional_edit_falloff",
+ text="", icon_only=True)
# Grease Pencil mode doesn't need snapping, as it's frame-aligned only
if st.mode != 'GPENCIL':
@@ -129,6 +153,7 @@ class DOPESHEET_HT_header(Header):
row = layout.row(align=True)
row.operator("action.copy", text="", icon='COPYDOWN')
row.operator("action.paste", text="", icon='PASTEDOWN')
+ row.operator("action.paste", text="", icon='PASTEFLIPDOWN').flipped = True
class DOPESHEET_MT_editor_menus(Menu):
@@ -183,10 +208,12 @@ class DOPESHEET_MT_view(Menu):
layout.separator()
layout.operator("action.view_all")
layout.operator("action.view_selected")
+ layout.operator("action.view_frame")
layout.separator()
layout.operator("screen.area_dupli")
- layout.operator("screen.screen_full_area")
+ layout.operator("screen.screen_full_area", text="Toggle Maximize Area")
+ layout.operator("screen.screen_full_area").use_hide_panels = True
class DOPESHEET_MT_select(Menu):
@@ -211,8 +238,12 @@ class DOPESHEET_MT_select(Menu):
layout.operator("action.select_column", text="Between Selected Markers").mode = 'MARKERS_BETWEEN'
layout.separator()
- layout.operator("action.select_leftright", text="Before Current Frame").mode = 'LEFT'
- layout.operator("action.select_leftright", text="After Current Frame").mode = 'RIGHT'
+ props = layout.operator("action.select_leftright", text="Before Current Frame")
+ props.extend = False
+ props.mode = 'LEFT'
+ props = layout.operator("action.select_leftright", text="After Current Frame")
+ props.extend = False
+ props.mode = 'RIGHT'
# FIXME: grease pencil mode isn't supported for these yet, so skip for that mode only
if context.space_data.mode != 'GPENCIL':
@@ -308,6 +339,7 @@ class DOPESHEET_MT_key(Menu):
layout.separator()
layout.operator("action.clean")
+ layout.operator("action.clean", text="Clean Channels").channels = True
layout.operator("action.sample")
layout.separator()
@@ -364,17 +396,34 @@ class DOPESHEET_MT_gpencil_frame(Menu):
layout = self.layout
layout.menu("DOPESHEET_MT_key_transform", text="Transform")
-
- #layout.operator_menu_enum("action.snap", "type", text="Snap")
- #layout.operator_menu_enum("action.mirror", "type", text="Mirror")
+ layout.operator_menu_enum("action.snap", "type", text="Snap")
+ layout.operator_menu_enum("action.mirror", "type", text="Mirror")
layout.separator()
layout.operator("action.duplicate")
layout.operator("action.delete")
+ layout.separator()
+ layout.operator("action.keyframe_type")
+
#layout.separator()
#layout.operator("action.copy")
#layout.operator("action.paste")
+
+class DOPESHEET_MT_delete(Menu):
+ bl_label = "Delete"
+
+ def draw(self, context):
+ layout = self.layout
+
+ layout.operator("action.delete")
+
+ layout.separator()
+
+ layout.operator("action.clean")
+ layout.operator("action.clean", text="Clean Channels").channels = True
+
+
if __name__ == "__main__": # only for live edit.
bpy.utils.register_module(__name__)
diff --git a/release/scripts/startup/bl_ui/space_filebrowser.py b/release/scripts/startup/bl_ui/space_filebrowser.py
index b90eb7a89c3..ca695208a67 100644
--- a/release/scripts/startup/bl_ui/space_filebrowser.py
+++ b/release/scripts/startup/bl_ui/space_filebrowser.py
@@ -18,7 +18,7 @@
# <pep8 compliant>
import bpy
-from bpy.types import Header
+from bpy.types import Header, Panel, Menu
class FILEBROWSER_HT_header(Header):
@@ -40,22 +40,27 @@ class FILEBROWSER_HT_header(Header):
row.operator("file.parent", text="", icon='FILE_PARENT')
row.operator("file.refresh", text="", icon='FILE_REFRESH')
- row = layout.row()
- row.separator()
-
- row = layout.row(align=True)
- layout.operator_context = "EXEC_DEFAULT"
- row.operator("file.directory_new", icon='NEWFOLDER')
+ layout.separator()
+ layout.operator_context = 'EXEC_DEFAULT'
+ layout.operator("file.directory_new", icon='NEWFOLDER', text="")
+ layout.separator()
- layout.operator_context = "INVOKE_DEFAULT"
+ layout.operator_context = 'INVOKE_DEFAULT'
params = st.params
# can be None when save/reload with a file selector open
if params:
+ is_lib_browser = params.use_library_browsing
+
+ layout.prop(params, "recursion_level", text="")
+
layout.prop(params, "display_type", expand=True, text="")
+
+ layout.prop(params, "thumbnail_size", text="")
+
layout.prop(params, "sort_method", expand=True, text="")
- layout.prop(params, "show_hidden")
+ layout.prop(params, "show_hidden", text="", icon='FILE_HIDDEN')
layout.prop(params, "use_filter", text="", icon='FILTER')
row = layout.row(align=True)
@@ -64,8 +69,8 @@ class FILEBROWSER_HT_header(Header):
row.prop(params, "use_filter_folder", text="")
if params.filter_glob:
- #if st.active_operator and hasattr(st.active_operator, "filter_glob"):
- # row.prop(params, "filter_glob", text="")
+ # if st.active_operator and hasattr(st.active_operator, "filter_glob"):
+ # row.prop(params, "filter_glob", text="")
row.label(params.filter_glob)
else:
row.prop(params, "use_filter_blender", text="")
@@ -77,5 +82,165 @@ class FILEBROWSER_HT_header(Header):
row.prop(params, "use_filter_sound", text="")
row.prop(params, "use_filter_text", text="")
+ if is_lib_browser:
+ row.prop(params, "use_filter_blendid", text="")
+ if params.use_filter_blendid:
+ row.separator()
+ row.prop(params, "filter_id_category", text="")
+
+ row.separator()
+ row.prop(params, "filter_search", text="", icon='VIEWZOOM')
+
+ layout.template_running_jobs()
+
+
+class FILEBROWSER_UL_dir(bpy.types.UIList):
+ def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index):
+ direntry = item
+ # space = context.space_data
+ icon = 'NONE'
+ if active_propname == "system_folders_active":
+ icon = 'DISK_DRIVE'
+ if active_propname == "system_bookmarks_active":
+ icon = 'BOOKMARKS'
+ if active_propname == "bookmarks_active":
+ icon = 'BOOKMARKS'
+ if active_propname == "recent_folders_active":
+ icon = 'FILE_FOLDER'
+
+ if self.layout_type in {'DEFAULT', 'COMPACT'}:
+ row = layout.row(align=True)
+ row.enabled = direntry.is_valid
+ # Non-editable entries would show grayed-out, which is bad in this specific case, so switch to mere label.
+ if direntry.is_property_readonly("name"):
+ row.label(text=direntry.name, icon=icon)
+ else:
+ row.prop(direntry, "name", text="", emboss=False, icon=icon)
+
+ elif self.layout_type == 'GRID':
+ layout.alignment = 'CENTER'
+ layout.prop(direntry, "path", text="")
+
+
+class FILEBROWSER_PT_system_folders(Panel):
+ bl_space_type = 'FILE_BROWSER'
+ bl_region_type = 'TOOLS'
+ bl_category = "Bookmarks"
+ bl_label = "System"
+
+ def draw(self, context):
+ layout = self.layout
+ space = context.space_data
+
+ if space.system_folders:
+ row = layout.row()
+ row.template_list("FILEBROWSER_UL_dir", "system_folders", space, "system_folders",
+ space, "system_folders_active", item_dyntip_propname="path", rows=1, maxrows=10)
+
+
+class FILEBROWSER_PT_system_bookmarks(Panel):
+ bl_space_type = 'FILE_BROWSER'
+ bl_region_type = 'TOOLS'
+ bl_category = "Bookmarks"
+ bl_label = "System Bookmarks"
+
+ @classmethod
+ def poll(cls, context):
+ return not context.user_preferences.filepaths.hide_system_bookmarks
+
+ def draw(self, context):
+ layout = self.layout
+ space = context.space_data
+
+ if space.system_bookmarks:
+ row = layout.row()
+ row.template_list("FILEBROWSER_UL_dir", "system_bookmarks", space, "system_bookmarks",
+ space, "system_bookmarks_active", item_dyntip_propname="path", rows=1, maxrows=10)
+
+
+class FILEBROWSER_MT_bookmarks_specials(Menu):
+ bl_label = "Bookmarks Specials"
+
+ def draw(self, context):
+ layout = self.layout
+ layout.operator("file.bookmark_cleanup", icon='X', text="Cleanup")
+
+ layout.separator()
+ layout.operator("file.bookmark_move", icon='TRIA_UP_BAR', text="Move To Top").direction = 'TOP'
+ layout.operator("file.bookmark_move", icon='TRIA_DOWN_BAR', text="Move To Bottom").direction = 'BOTTOM'
+
+
+class FILEBROWSER_PT_bookmarks(Panel):
+ bl_space_type = 'FILE_BROWSER'
+ bl_region_type = 'TOOLS'
+ bl_category = "Bookmarks"
+ bl_label = "Bookmarks"
+
+ def draw(self, context):
+ layout = self.layout
+ space = context.space_data
+
+ if space.bookmarks:
+ row = layout.row()
+ num_rows = len(space.bookmarks)
+ row.template_list("FILEBROWSER_UL_dir", "bookmarks", space, "bookmarks",
+ space, "bookmarks_active", item_dyntip_propname="path",
+ rows=(2 if num_rows < 2 else 4), maxrows=10)
+
+ col = row.column(align=True)
+ col.operator("file.bookmark_add", icon='ZOOMIN', text="")
+ col.operator("file.bookmark_delete", icon='ZOOMOUT', text="")
+ col.menu("FILEBROWSER_MT_bookmarks_specials", icon='DOWNARROW_HLT', text="")
+
+ if num_rows > 1:
+ col.separator()
+ col.operator("file.bookmark_move", icon='TRIA_UP', text="").direction = 'UP'
+ col.operator("file.bookmark_move", icon='TRIA_DOWN', text="").direction = 'DOWN'
+ else:
+ layout.operator("file.bookmark_add", icon='ZOOMIN')
+
+
+class FILEBROWSER_PT_recent_folders(Panel):
+ bl_space_type = 'FILE_BROWSER'
+ bl_region_type = 'TOOLS'
+ bl_category = "Bookmarks"
+ bl_label = "Recent"
+
+ @classmethod
+ def poll(cls, context):
+ return not context.user_preferences.filepaths.hide_recent_locations
+
+ def draw(self, context):
+ layout = self.layout
+ space = context.space_data
+
+ if space.recent_folders:
+ row = layout.row()
+ row.template_list("FILEBROWSER_UL_dir", "recent_folders", space, "recent_folders",
+ space, "recent_folders_active", item_dyntip_propname="path", rows=1, maxrows=10)
+
+ col = row.column(align=True)
+ col.operator("file.reset_recent", icon='X', text="")
+
+
+class FILEBROWSER_PT_advanced_filter(Panel):
+ bl_space_type = 'FILE_BROWSER'
+ bl_region_type = 'TOOLS'
+ bl_category = "Filter"
+ bl_label = "Advanced Filter"
+
+ def draw(self, context):
+ layout = self.layout
+ space = context.space_data
+ params = space.params
+
+ if params and params.use_library_browsing:
+ layout.prop(params, "use_filter_blendid")
+ if params.use_filter_blendid:
+ layout.separator()
+ col = layout.column()
+ col.prop(params, "filter_id")
+
+
if __name__ == "__main__": # only for live edit.
bpy.utils.register_module(__name__)
diff --git a/release/scripts/startup/bl_ui/space_graph.py b/release/scripts/startup/bl_ui/space_graph.py
index 3d39234ce08..104fd14797e 100644
--- a/release/scripts/startup/bl_ui/space_graph.py
+++ b/release/scripts/startup/bl_ui/space_graph.py
@@ -29,6 +29,7 @@ class GRAPH_HT_header(Header):
from bl_ui.space_dopesheet import dopesheet_filter
layout = self.layout
+ toolsettings = context.tool_settings
st = context.space_data
@@ -46,12 +47,21 @@ class GRAPH_HT_header(Header):
row.active = st.use_normalization
row.prop(st, "use_auto_normalization", text="Auto")
+ row = layout.row(align=True)
+
+ row.prop(toolsettings, "use_proportional_fcurve",
+ text="", icon_only=True)
+ if toolsettings.use_proportional_fcurve:
+ row.prop(toolsettings, "proportional_edit_falloff",
+ text="", icon_only=True)
+
layout.prop(st, "auto_snap", text="")
layout.prop(st, "pivot_point", icon_only=True)
row = layout.row(align=True)
row.operator("graph.copy", text="", icon='COPYDOWN')
row.operator("graph.paste", text="", icon='PASTEDOWN')
+ row.operator("graph.paste", text="", icon='PASTEFLIPDOWN').flipped = True
row = layout.row(align=True)
if st.has_ghost_curves:
@@ -115,10 +125,12 @@ class GRAPH_MT_view(Menu):
layout.separator()
layout.operator("graph.view_all")
layout.operator("graph.view_selected")
+ layout.operator("graph.view_frame")
layout.separator()
layout.operator("screen.area_dupli")
- layout.operator("screen.screen_full_area")
+ layout.operator("screen.screen_full_area", text="Toggle Maximize Area")
+ layout.operator("screen.screen_full_area").use_hide_panels = True
class GRAPH_MT_select(Menu):
@@ -132,9 +144,15 @@ class GRAPH_MT_select(Menu):
layout.operator("graph.select_all_toggle", text="Invert Selection").invert = True
layout.separator()
- layout.operator("graph.select_border")
- layout.operator("graph.select_border", text="Border Axis Range").axis_range = True
- layout.operator("graph.select_border", text="Border (Include Handles)").include_handles = True
+ props = layout.operator("graph.select_border")
+ props.axis_range = False
+ props.include_handles = False
+ props = layout.operator("graph.select_border", text="Border Axis Range")
+ props.axis_range = True
+ props.include_handles = False
+ props = layout.operator("graph.select_border", text="Border (Include Handles)")
+ props.axis_range = False
+ props.include_handles = True
layout.separator()
layout.operator("graph.select_column", text="Columns on Selected Keys").mode = 'KEYS'
@@ -144,8 +162,12 @@ class GRAPH_MT_select(Menu):
layout.operator("graph.select_column", text="Between Selected Markers").mode = 'MARKERS_BETWEEN'
layout.separator()
- layout.operator("graph.select_leftright", text="Before Current Frame").mode = 'LEFT'
- layout.operator("graph.select_leftright", text="After Current Frame").mode = 'RIGHT'
+ props = layout.operator("graph.select_leftright", text="Before Current Frame")
+ props.extend = False
+ props.mode = 'LEFT'
+ props = layout.operator("graph.select_leftright", text="After Current Frame")
+ props.extend = False
+ props.mode = 'RIGHT'
layout.separator()
layout.operator("graph.select_more")
@@ -188,10 +210,14 @@ class GRAPH_MT_channel(Menu):
layout.separator()
layout.operator("anim.channels_editable_toggle")
- layout.operator("anim.channels_visibility_set")
layout.operator_menu_enum("graph.extrapolation_type", "type", text="Extrapolation Mode")
layout.separator()
+ layout.operator("graph.hide", text="Hide Selected Curves").unselected = False
+ layout.operator("graph.hide", text="Hide Unselected Curves").unselected = True
+ layout.operator("graph.reveal")
+
+ layout.separator()
layout.operator("anim.channels_expand")
layout.operator("anim.channels_collapse")
@@ -232,6 +258,7 @@ class GRAPH_MT_key(Menu):
layout.separator()
layout.operator("graph.clean")
+ layout.operator("graph.clean", text="Clean Channels").channels = True
layout.operator("graph.smooth")
layout.operator("graph.sample")
layout.operator("graph.bake")
@@ -255,5 +282,20 @@ class GRAPH_MT_key_transform(Menu):
layout.operator("transform.rotate", text="Rotate")
layout.operator("transform.resize", text="Scale")
+
+class GRAPH_MT_delete(Menu):
+ bl_label = "Delete"
+
+ def draw(self, context):
+ layout = self.layout
+
+ layout.operator("graph.delete")
+
+ layout.separator()
+
+ layout.operator("graph.clean")
+ layout.operator("graph.clean", text="Clean Channels").channels = True
+
+
if __name__ == "__main__": # only for live edit.
bpy.utils.register_module(__name__)
diff --git a/release/scripts/startup/bl_ui/space_image.py b/release/scripts/startup/bl_ui/space_image.py
index 927e517ef21..c3024b25282 100644
--- a/release/scripts/startup/bl_ui/space_image.py
+++ b/release/scripts/startup/bl_ui/space_image.py
@@ -25,7 +25,11 @@ from bl_ui.properties_paint_common import (
brush_texpaint_common,
brush_mask_texture_settings,
)
-from bl_ui.properties_grease_pencil_common import GreasePencilPanel
+from bl_ui.properties_grease_pencil_common import (
+ GreasePencilDrawingToolsPanel,
+ GreasePencilStrokeEditPanel,
+ GreasePencilDataPanel,
+ )
from bpy.app.translations import pgettext_iface as iface_
@@ -80,8 +84,10 @@ class IMAGE_MT_view(Menu):
layout.prop(toolsettings, "show_uv_local_view")
layout.prop(uv, "show_other_objects")
+ layout.prop(uv, "show_metadata")
if paint.brush and (context.image_paint_object or sima.mode == 'PAINT'):
layout.prop(uv, "show_texpaint")
+ layout.prop(toolsettings, "show_uv_local_view", text="Show same material")
layout.separator()
@@ -101,6 +107,7 @@ class IMAGE_MT_view(Menu):
layout.operator("image.view_selected")
layout.operator("image.view_all")
+ layout.operator("image.view_all", text="View Fit").fit_view = True
layout.separator()
@@ -110,7 +117,8 @@ class IMAGE_MT_view(Menu):
layout.separator()
layout.operator("screen.area_dupli")
- layout.operator("screen.screen_full_area")
+ layout.operator("screen.screen_full_area", text="Toggle Maximize Area")
+ layout.operator("screen.screen_full_area").use_hide_panels = True
class IMAGE_MT_select(Menu):
@@ -121,6 +129,7 @@ class IMAGE_MT_select(Menu):
layout.operator("uv.select_border").pinned = False
layout.operator("uv.select_border", text="Border Select Pinned").pinned = True
+ layout.operator("uv.circle_select")
layout.separator()
@@ -130,7 +139,7 @@ class IMAGE_MT_select(Menu):
layout.separator()
layout.operator("uv.select_pinned")
- layout.operator("uv.select_linked")
+ layout.operator("uv.select_linked").extend = False
layout.separator()
@@ -329,7 +338,8 @@ class IMAGE_MT_uvs(Menu):
layout.operator("uv.average_islands_scale")
layout.operator("uv.minimize_stretch")
layout.operator("uv.stitch")
- layout.operator("uv.mark_seam")
+ layout.operator("uv.mark_seam").clear = False
+ layout.operator("uv.mark_seam", text="Clear Seam").clear = True
layout.operator("uv.seams_from_islands")
layout.operator("mesh.faces_mirror_uv")
@@ -452,6 +462,10 @@ class IMAGE_HT_header(Header):
layout.prop_search(mesh.uv_textures, "active", mesh, "uv_textures", text="")
if ima:
+ if ima.is_stereo_3d:
+ row = layout.row()
+ row.prop(sima, "show_stereo_3d", text="")
+
# layers
layout.template_image_layers(ima, iuser)
@@ -509,12 +523,14 @@ class MASK_MT_editor_menus(Menu):
# Mask (similar code in space_clip.py, keep in sync)
# note! - panel placement does _not_ fit well with image panels... need to fix
-from bl_ui.properties_mask_common import (MASK_PT_mask,
- MASK_PT_layers,
- MASK_PT_spline,
- MASK_PT_point,
- MASK_PT_display,
- MASK_PT_tools)
+from bl_ui.properties_mask_common import (
+ MASK_PT_mask,
+ MASK_PT_layers,
+ MASK_PT_spline,
+ MASK_PT_point,
+ MASK_PT_display,
+ MASK_PT_tools,
+ )
class IMAGE_PT_mask(MASK_PT_mask, Panel):
@@ -558,7 +574,7 @@ class IMAGE_PT_image_properties(Panel):
sima = context.space_data
iuser = sima.image_user
- layout.template_image(sima, "image", iuser)
+ layout.template_image(sima, "image", iuser, multiview=True)
class IMAGE_PT_game_properties(Panel):
@@ -617,6 +633,8 @@ class IMAGE_PT_view_properties(Panel):
sima = context.space_data
ima = sima.image
+
+ show_render = sima.show_render
show_uvedit = sima.show_uvedit
show_maskedit = sima.show_maskedit
uvedit = sima.uv_editor
@@ -661,6 +679,11 @@ class IMAGE_PT_view_properties(Panel):
sub.active = uvedit.show_stretch
sub.row().prop(uvedit, "draw_stretch_type", expand=True)
+ if show_render and ima:
+ layout.separator()
+ render_slot = ima.render_slots.active
+ layout.prop(render_slot, "name", text="Slot Name")
+
class IMAGE_PT_tools_transform_uvs(Panel, UVToolsPanel):
bl_label = "Transform"
@@ -682,7 +705,7 @@ class IMAGE_PT_tools_transform_uvs(Panel, UVToolsPanel):
col.operator("transform.shear")
-class IMAGE_PT_paint(Panel, BrushButtonsPanel):
+class IMAGE_PT_paint(Panel, ImagePaintPanel):
bl_label = "Paint"
bl_category = "Tools"
@@ -698,6 +721,11 @@ class IMAGE_PT_paint(Panel, BrushButtonsPanel):
if brush:
brush_texpaint_common(self, context, layout, brush, settings)
+ @classmethod
+ def poll(cls, context):
+ sima = context.space_data
+ toolsettings = context.tool_settings.image_paint
+ return sima.show_paint
class IMAGE_PT_tools_brush_overlay(BrushButtonsPanel, Panel):
bl_label = "Overlay"
@@ -897,6 +925,24 @@ class IMAGE_PT_paint_curve(BrushButtonsPanel, Panel):
row.operator("brush.curve_preset", icon='NOCURVE', text="").shape = 'MAX'
+class IMAGE_PT_tools_imagepaint_symmetry(BrushButtonsPanel, Panel):
+ bl_category = "Tools"
+ bl_context = "imagepaint"
+ bl_label = "Tiling"
+ bl_options = {'DEFAULT_CLOSED'}
+
+ def draw(self, context):
+ layout = self.layout
+
+ toolsettings = context.tool_settings
+ ipaint = toolsettings.image_paint
+
+ col = layout.column(align=True)
+ row = col.row(align=True)
+ row.prop(ipaint, "tile_x", text="X", toggle=True)
+ row.prop(ipaint, "tile_y", text="Y", toggle=True)
+
+
class IMAGE_PT_tools_brush_appearance(BrushButtonsPanel, Panel):
bl_label = "Appearance"
bl_options = {'DEFAULT_CLOSED'}
@@ -940,10 +986,6 @@ class IMAGE_PT_tools_paint_options(BrushButtonsPanel, Panel):
ups = toolsettings.unified_paint_settings
col = layout.column(align=True)
-
- col.prop(brush, "use_wrap")
- col.separator()
-
col.label(text="Unified Settings:")
row = col.row()
row.prop(ups, "use_unified_size", text="Size")
@@ -1031,17 +1073,27 @@ class IMAGE_PT_tools_mask(MASK_PT_tools, Panel):
# --- end mask ---
-class IMAGE_PT_view_histogram(Panel):
+class ImageScopesPanel:
+ @classmethod
+ def poll(cls, context):
+ sima = context.space_data
+ if not (sima and sima.image):
+ return False
+ # scopes are not updated in paint modes, hide
+ if sima.mode == 'PAINT':
+ return False
+ ob = context.active_object
+ if ob and ob.mode in {'TEXTURE_PAINT', 'EDIT'}:
+ return False
+ return True
+
+
+class IMAGE_PT_view_histogram(ImageScopesPanel, Panel):
bl_space_type = 'IMAGE_EDITOR'
bl_region_type = 'TOOLS'
bl_label = "Histogram"
bl_category = "Scopes"
- @classmethod
- def poll(cls, context):
- sima = context.space_data
- return (sima and sima.image)
-
def draw(self, context):
layout = self.layout
@@ -1054,17 +1106,12 @@ class IMAGE_PT_view_histogram(Panel):
row.prop(hist, "show_line", text="")
-class IMAGE_PT_view_waveform(Panel):
+class IMAGE_PT_view_waveform(ImageScopesPanel, Panel):
bl_space_type = 'IMAGE_EDITOR'
bl_region_type = 'TOOLS'
bl_label = "Waveform"
bl_category = "Scopes"
- @classmethod
- def poll(cls, context):
- sima = context.space_data
- return (sima and sima.image)
-
def draw(self, context):
layout = self.layout
@@ -1076,17 +1123,12 @@ class IMAGE_PT_view_waveform(Panel):
row.prop(sima.scopes, "waveform_mode", text="")
-class IMAGE_PT_view_vectorscope(Panel):
+class IMAGE_PT_view_vectorscope(ImageScopesPanel, Panel):
bl_space_type = 'IMAGE_EDITOR'
bl_region_type = 'TOOLS'
bl_label = "Vectorscope"
bl_category = "Scopes"
- @classmethod
- def poll(cls, context):
- sima = context.space_data
- return (sima and sima.image)
-
def draw(self, context):
layout = self.layout
@@ -1095,17 +1137,12 @@ class IMAGE_PT_view_vectorscope(Panel):
layout.prop(sima.scopes, "vectorscope_alpha")
-class IMAGE_PT_sample_line(Panel):
+class IMAGE_PT_sample_line(ImageScopesPanel, Panel):
bl_space_type = 'IMAGE_EDITOR'
bl_region_type = 'TOOLS'
bl_label = "Sample Line"
bl_category = "Scopes"
- @classmethod
- def poll(cls, context):
- sima = context.space_data
- return (sima and sima.image)
-
def draw(self, context):
layout = self.layout
@@ -1119,17 +1156,12 @@ class IMAGE_PT_sample_line(Panel):
row.prop(hist, "show_line", text="")
-class IMAGE_PT_scope_sample(Panel):
+class IMAGE_PT_scope_sample(ImageScopesPanel, Panel):
bl_space_type = 'IMAGE_EDITOR'
bl_region_type = 'TOOLS'
bl_label = "Scope Samples"
bl_category = "Scopes"
- @classmethod
- def poll(cls, context):
- sima = context.space_data
- return sima
-
def draw(self, context):
layout = self.layout
@@ -1142,10 +1174,22 @@ class IMAGE_PT_scope_sample(Panel):
sub.prop(sima.scopes, "accuracy")
-class IMAGE_PT_tools_grease_pencil(GreasePencilPanel, Panel):
+# Grease Pencil properties
+class IMAGE_PT_grease_pencil(GreasePencilDataPanel, Panel):
+ bl_space_type = 'IMAGE_EDITOR'
+ bl_region_type = 'UI'
+
+ # NOTE: this is just a wrapper around the generic GP Panel
+
+
+# Grease Pencil drawing tools
+class IMAGE_PT_tools_grease_pencil_draw(GreasePencilDrawingToolsPanel, Panel):
+ bl_space_type = 'IMAGE_EDITOR'
+
+
+# Grease Pencil stroke editing tools
+class IMAGE_PT_tools_grease_pencil_edit(GreasePencilStrokeEditPanel, Panel):
bl_space_type = 'IMAGE_EDITOR'
- bl_region_type = 'TOOLS'
- bl_category = "Grease Pencil"
if __name__ == "__main__": # only for live edit.
diff --git a/release/scripts/startup/bl_ui/space_info.py b/release/scripts/startup/bl_ui/space_info.py
index 67b2bbe1905..d295cc19fb7 100644
--- a/release/scripts/startup/bl_ui/space_info.py
+++ b/release/scripts/startup/bl_ui/space_info.py
@@ -57,12 +57,15 @@ class INFO_HT_header(Header):
row = layout.row(align=True)
if bpy.app.autoexec_fail is True and bpy.app.autoexec_fail_quiet is False:
- row.label("Auto-run disabled: %s" % bpy.app.autoexec_fail_message, icon='ERROR')
+ row.label("Auto-run disabled", icon='ERROR')
if bpy.data.is_saved:
props = row.operator("wm.revert_mainfile", icon='SCREEN_BACK', text="Reload Trusted")
props.use_scripts = True
row.operator("script.autoexec_warn_clear", text="Ignore")
+
+ # include last so text doesn't push buttons out of the header
+ row.label(bpy.app.autoexec_fail_message)
return
row.operator("wm.splash", text="", icon='BLENDER', emboss=False)
@@ -129,6 +132,7 @@ class INFO_MT_file(Menu):
layout.operator_context = 'INVOKE_AREA'
layout.operator("wm.link", text="Link", icon='LINK_BLEND')
layout.operator("wm.append", text="Append", icon='APPEND_BLEND')
+ layout.menu("INFO_MT_file_previews")
layout.separator()
@@ -192,6 +196,21 @@ class INFO_MT_file_external_data(Menu):
layout.operator("file.find_missing_files")
+class INFO_MT_file_previews(Menu):
+ bl_label = "Data Previews"
+
+ def draw(self, context):
+ layout = self.layout
+
+ layout.operator("wm.previews_ensure")
+ layout.operator("wm.previews_batch_generate")
+
+ layout.separator()
+
+ layout.operator("wm.previews_clear")
+ layout.operator("wm.previews_batch_clear")
+
+
class INFO_MT_game(Menu):
bl_label = "Game"
@@ -262,13 +281,17 @@ class INFO_MT_window(Menu):
layout.separator()
- layout.operator("screen.screenshot").full = True
- layout.operator("screen.screencast").full = True
+ layout.operator("screen.screenshot")
+ layout.operator("screen.screencast")
if sys.platform[:3] == "win":
layout.separator()
layout.operator("wm.console_toggle", icon='CONSOLE')
+ if context.scene.render.use_multiview:
+ layout.separator()
+ layout.operator("wm.set_stereo_3d", icon='CAMERA_STEREO')
+
class INFO_MT_help(Menu):
bl_label = "Help"
@@ -276,7 +299,7 @@ class INFO_MT_help(Menu):
def draw(self, context):
layout = self.layout
- layout.operator("wm.url_open", text="Manual", icon='HELP').url = "http://wiki.blender.org/index.php/Doc:2.6/Manual"
+ layout.operator("wm.url_open", text="Manual", icon='HELP').url = "http://www.blender.org/manual"
layout.operator("wm.url_open", text="Release Log", icon='URL').url = "http://wiki.blender.org/index.php/Dev:Ref/Release_Notes/%d.%d" % bpy.app.version[:2]
layout.separator()
diff --git a/release/scripts/startup/bl_ui/space_logic.py b/release/scripts/startup/bl_ui/space_logic.py
index 9792a26d224..48b54feba17 100644
--- a/release/scripts/startup/bl_ui/space_logic.py
+++ b/release/scripts/startup/bl_ui/space_logic.py
@@ -54,11 +54,11 @@ class LOGIC_PT_properties(Panel):
row.label("See Text Object")
else:
props = layout.operator("object.game_property_new", text="Add Text Game Property", icon='ZOOMIN')
- props.name = 'Text'
+ props.name = "Text"
props.type = 'STRING'
props = layout.operator("object.game_property_new", text="Add Game Property", icon='ZOOMIN')
- props.name = ''
+ props.name = ""
for i, prop in enumerate(game.properties):
@@ -71,6 +71,13 @@ class LOGIC_PT_properties(Panel):
row.prop(prop, "type", text="")
row.prop(prop, "value", text="")
row.prop(prop, "show_debug", text="", toggle=True, icon='INFO')
+ sub = row.row(align=True)
+ props = sub.operator("object.game_property_move", text="", icon='TRIA_UP')
+ props.index = i
+ props.direction = 'UP'
+ props = sub.operator("object.game_property_move", text="", icon='TRIA_DOWN')
+ props.index = i
+ props.direction = 'DOWN'
row.operator("object.game_property_remove", text="", icon='X', emboss=False).index = i
@@ -120,7 +127,8 @@ class LOGIC_MT_view(Menu):
layout.separator()
layout.operator("screen.area_dupli")
- layout.operator("screen.screen_full_area")
+ layout.operator("screen.screen_full_area", text="Toggle Maximize Area")
+ layout.operator("screen.screen_full_area").use_hide_panels = True
if __name__ == "__main__": # only for live edit.
bpy.utils.register_module(__name__)
diff --git a/release/scripts/startup/bl_ui/space_nla.py b/release/scripts/startup/bl_ui/space_nla.py
index 7634620cf0d..c083907f017 100644
--- a/release/scripts/startup/bl_ui/space_nla.py
+++ b/release/scripts/startup/bl_ui/space_nla.py
@@ -89,7 +89,8 @@ class NLA_MT_view(Menu):
layout.separator()
layout.operator("screen.area_dupli")
- layout.operator("screen.screen_full_area")
+ layout.operator("screen.screen_full_area", text="Toggle Maximize Area")
+ layout.operator("screen.screen_full_area").use_hide_panels = True
class NLA_MT_select(Menu):
@@ -107,8 +108,12 @@ class NLA_MT_select(Menu):
layout.operator("nla.select_border", text="Border Axis Range").axis_range = True
layout.separator()
- layout.operator("nla.select_leftright", text="Before Current Frame").mode = 'LEFT'
- layout.operator("nla.select_leftright", text="After Current Frame").mode = 'RIGHT'
+ props = layout.operator("nla.select_leftright", text="Before Current Frame")
+ props.extend = False
+ props.mode = 'LEFT'
+ props = layout.operator("nla.select_leftright", text="After Current Frame")
+ props.extend = False
+ props.mode = 'RIGHT'
class NLA_MT_marker(Menu):
@@ -134,7 +139,7 @@ class NLA_MT_edit(Menu):
layout.operator_menu_enum("nla.snap", "type", text="Snap")
layout.separator()
- layout.operator("nla.duplicate", text="Duplicate")
+ layout.operator("nla.duplicate", text="Duplicate").linked = False
layout.operator("nla.duplicate", text="Linked Duplicate").linked = True
layout.operator("nla.split")
layout.operator("nla.delete")
@@ -163,8 +168,10 @@ class NLA_MT_edit(Menu):
layout.separator()
# TODO: names of these tools for 'tweak-mode' need changing?
if scene.is_nla_tweakmode:
+ layout.operator("nla.tweakmode_exit", text="Stop Editing Stashed Action").isolate_action = True
layout.operator("nla.tweakmode_exit", text="Stop Tweaking Strip Actions")
else:
+ layout.operator("nla.tweakmode_enter", text="Start Editing Stashed Action").isolate_action = True
layout.operator("nla.tweakmode_enter", text="Start Tweaking Strip Actions")
diff --git a/release/scripts/startup/bl_ui/space_node.py b/release/scripts/startup/bl_ui/space_node.py
index 24e8d2e4a53..3941e618b5b 100644
--- a/release/scripts/startup/bl_ui/space_node.py
+++ b/release/scripts/startup/bl_ui/space_node.py
@@ -18,7 +18,15 @@
# <pep8 compliant>
import bpy
+import nodeitems_utils
from bpy.types import Header, Menu, Panel
+from bpy.app.translations import pgettext_iface as iface_
+from bl_ui.properties_grease_pencil_common import (
+ GreasePencilDrawingToolsPanel,
+ GreasePencilStrokeEditPanel,
+ GreasePencilDataPanel,
+ GreasePencilToolsPanel,
+ )
class NODE_HT_header(Header):
@@ -60,7 +68,7 @@ class NODE_HT_header(Header):
if snode_id and not (scene.render.use_shading_nodes == 0 and ob.type == 'LAMP'):
layout.prop(snode_id, "use_nodes")
- if snode.shader_type == 'WORLD':
+ if scene.render.use_shading_nodes and snode.shader_type == 'WORLD':
row = layout.row()
row.enabled = not snode.pin
row.template_ID(scene, "world", new="world.new")
@@ -107,6 +115,9 @@ class NODE_HT_header(Header):
layout.separator()
+ # Auto-offset nodes (called "insert_offset" in code)
+ layout.prop(snode, "use_insert_offset", text="")
+
# Snap
row = layout.row(align=True)
row.prop(toolsettings, "use_snap", text="")
@@ -147,7 +158,8 @@ class NODE_MT_add(bpy.types.Menu):
props = layout.operator("node.add_search", text="Search ...")
props.use_transform = True
- # actual node submenus are added by draw functions from node categories
+ # actual node submenus are defined by draw functions from node categories
+ nodeitems_utils.draw_node_categories_menu(self, context)
class NODE_MT_view(Menu):
@@ -180,7 +192,8 @@ class NODE_MT_view(Menu):
layout.separator()
layout.operator("screen.area_dupli")
- layout.operator("screen.screen_full_area")
+ layout.operator("screen.screen_full_area", text="Toggle Maximize Area")
+ layout.operator("screen.screen_full_area").use_hide_panels = True
class NODE_MT_select(Menu):
@@ -189,7 +202,7 @@ class NODE_MT_select(Menu):
def draw(self, context):
layout = self.layout
- layout.operator("node.select_border")
+ layout.operator("node.select_border").tweak = False
layout.operator("node.select_circle")
layout.separator()
@@ -200,9 +213,9 @@ class NODE_MT_select(Menu):
layout.separator()
- layout.operator("node.select_grouped")
- layout.operator("node.select_same_type_step").prev = True
- layout.operator("node.select_same_type_step").prev = False
+ layout.operator("node.select_grouped").extend = False
+ layout.operator("node.select_same_type_step", text="Activate Same Type Previous").prev = True
+ layout.operator("node.select_same_type_step", text="Activate Same Type Next").prev = False
layout.separator()
@@ -232,14 +245,14 @@ class NODE_MT_node(Menu):
layout.separator()
- layout.operator("node.link_make")
+ layout.operator("node.link_make").replace = False
layout.operator("node.link_make", text="Make and Replace Links").replace = True
layout.operator("node.links_cut")
layout.operator("node.links_detach")
layout.separator()
- layout.operator("node.group_edit")
+ layout.operator("node.group_edit").exit = False
layout.operator("node.group_ungroup")
layout.operator("node.group_make")
layout.operator("node.group_insert")
@@ -351,7 +364,7 @@ class NODE_PT_active_node_properties(Panel):
layout.label("Inputs:")
for socket in value_inputs:
row = layout.row()
- socket.draw(context, row, node, socket.name)
+ socket.draw(context, row, node, iface_(socket.name, socket.bl_rna.translation_context))
# Node Backdrop options
@@ -433,11 +446,51 @@ class NODE_UL_interface_sockets(bpy.types.UIList):
if socket.is_output:
row.template_node_socket(color)
- elif self.layout_type in {'GRID'}:
+ elif self.layout_type == 'GRID':
layout.alignment = 'CENTER'
layout.template_node_socket(color)
+# Grease Pencil properties
+class NODE_PT_grease_pencil(GreasePencilDataPanel, Panel):
+ bl_space_type = 'NODE_EDITOR'
+ bl_region_type = 'UI'
+
+ # NOTE: this is just a wrapper around the generic GP Panel
+
+ @classmethod
+ def poll(cls, context):
+ snode = context.space_data
+ return snode is not None and snode.node_tree is not None
+
+
+class NODE_PT_grease_pencil_tools(GreasePencilToolsPanel, Panel):
+ bl_space_type = 'NODE_EDITOR'
+ bl_region_type = 'UI'
+ bl_options = {'DEFAULT_CLOSED'}
+
+ # NOTE: this is just a wrapper around the generic GP tools panel
+ # It contains access to some essential tools usually found only in
+ # toolbar, but which may not necessarily be open
+
+
+# Tool Shelf ------------------
+
+
+# Grease Pencil drawing tools
+class NODE_PT_tools_grease_pencil_draw(GreasePencilDrawingToolsPanel, Panel):
+ bl_space_type = 'NODE_EDITOR'
+ bl_region_type = 'TOOLS'
+
+
+# Grease Pencil stroke editing tools
+class NODE_PT_tools_grease_pencil_edit(GreasePencilStrokeEditPanel, Panel):
+ bl_space_type = 'NODE_EDITOR'
+ bl_region_type = 'TOOLS'
+
+# -----------------------------
+
+
def node_draw_tree_view(layout, context):
pass
diff --git a/release/scripts/startup/bl_ui/space_outliner.py b/release/scripts/startup/bl_ui/space_outliner.py
index 01165bf2889..7b1dfb9579a 100644
--- a/release/scripts/startup/bl_ui/space_outliner.py
+++ b/release/scripts/startup/bl_ui/space_outliner.py
@@ -57,6 +57,8 @@ class OUTLINER_HT_header(Header):
else:
row = layout.row()
row.label(text="No Keying Set active")
+ elif space.display_mode == 'ORPHAN_DATA':
+ layout.operator("outliner.orphans_purge")
class OUTLINER_MT_editor_menus(Menu):
@@ -86,6 +88,7 @@ class OUTLINER_MT_view(Menu):
space = context.space_data
if space.display_mode not in {'DATABLOCKS', 'USER_PREFERENCES', 'KEYMAPS'}:
+ layout.prop(space, "use_sort_alpha")
layout.prop(space, "show_restrict_columns")
layout.separator()
layout.operator("outliner.show_active")
@@ -96,7 +99,8 @@ class OUTLINER_MT_view(Menu):
layout.separator()
layout.operator("screen.area_dupli")
- layout.operator("screen.screen_full_area")
+ layout.operator("screen.screen_full_area", text="Toggle Maximize Area")
+ layout.operator("screen.screen_full_area").use_hide_panels = True
class OUTLINER_MT_search(Menu):
diff --git a/release/scripts/startup/bl_ui/space_sequencer.py b/release/scripts/startup/bl_ui/space_sequencer.py
index ce00d4eb8e7..5bf095dc6b5 100644
--- a/release/scripts/startup/bl_ui/space_sequencer.py
+++ b/release/scripts/startup/bl_ui/space_sequencer.py
@@ -19,6 +19,8 @@
# <pep8 compliant>
import bpy
from bpy.types import Header, Menu, Panel
+from rna_prop_ui import PropertyPanel
+from bl_ui.properties_grease_pencil_common import GreasePencilDataPanel, GreasePencilToolsPanel
from bpy.app.translations import pgettext_iface as iface_
@@ -82,6 +84,7 @@ class SEQUENCER_HT_header(Header):
layout.separator()
layout.operator("sequencer.refresh_all")
+ layout.prop(st, "show_backdrop")
else:
if st.view_type == 'SEQUENCER_PREVIEW':
layout.separator()
@@ -101,6 +104,17 @@ class SEQUENCER_HT_header(Header):
row = layout.row()
row.prop(st, "overlay_type", text="")
+ if st.view_type in {'PREVIEW', 'SEQUENCER_PREVIEW'}:
+ gpd = context.gpencil_data
+ toolsettings = context.tool_settings
+
+ # Proportional editing
+ if gpd and gpd.use_stroke_edit_mode:
+ row = layout.row(align=True)
+ row.prop(toolsettings, "proportional_edit", icon_only=True)
+ if toolsettings.proportional_edit != 'DISABLED':
+ row.prop(toolsettings, "proportional_edit_falloff", icon_only=True)
+
row = layout.row(align=True)
row.operator("render.opengl", text="", icon='RENDER_STILL').sequencer = True
props = row.operator("render.opengl", text="", icon='RENDER_ANIMATION')
@@ -149,8 +163,10 @@ class SEQUENCER_MT_view(Menu):
layout = self.layout
st = context.space_data
+ is_preview = st.view_type in {'PREVIEW', 'SEQUENCER_PREVIEW'}
+ is_sequencer_view = st.view_type in {'SEQUENCER', 'SEQUENCER_PREVIEW'}
- if st.view_type in {'PREVIEW'}:
+ if st.view_type == 'PREVIEW':
# Specifying the REGION_PREVIEW context is needed in preview-only
# mode, else the lookup for the shortcut will fail in
# wm_keymap_item_find_props() (see #32595).
@@ -160,10 +176,12 @@ class SEQUENCER_MT_view(Menu):
layout.separator()
- if st.view_type in {'SEQUENCER', 'SEQUENCER_PREVIEW'}:
+ if is_sequencer_view:
+ layout.operator_context = 'INVOKE_REGION_WIN'
layout.operator("sequencer.view_all", text="View all Sequences")
layout.operator("sequencer.view_selected")
- if st.view_type in {'PREVIEW', 'SEQUENCER_PREVIEW'}:
+ layout.operator_context = 'INVOKE_DEFAULT'
+ if is_preview:
layout.operator_context = 'INVOKE_REGION_PREVIEW'
layout.operator("sequencer.view_all_preview", text="Fit preview in window")
@@ -181,24 +199,29 @@ class SEQUENCER_MT_view(Menu):
# # XXX, invokes in the header view
# layout.operator("sequencer.view_ghost_border", text="Overlay Border")
- if st.view_type in {'SEQUENCER', 'SEQUENCER_PREVIEW'}:
+ if is_sequencer_view:
layout.prop(st, "show_seconds")
layout.prop(st, "show_frame_indicator")
+ layout.prop(st, "show_strip_offset")
- if st.view_type in {'PREVIEW', 'SEQUENCER_PREVIEW'}:
+ layout.prop_menu_enum(st, "waveform_draw_type")
+
+ if is_preview:
if st.display_mode == 'IMAGE':
- layout.prop(st, "show_safe_margin")
+ layout.prop(st, "show_safe_areas")
+ layout.prop(st, "show_metadata")
elif st.display_mode == 'WAVEFORM':
layout.prop(st, "show_separate_color")
layout.separator()
- if st.view_type in {'SEQUENCER', 'SEQUENCER_PREVIEW'}:
+ if is_sequencer_view:
layout.prop(st, "use_marker_sync")
layout.separator()
layout.operator("screen.area_dupli")
- layout.operator("screen.screen_full_area")
+ layout.operator("screen.screen_full_area", text="Toggle Maximize Area")
+ layout.operator("screen.screen_full_area").use_hide_panels = True
class SEQUENCER_MT_select(Menu):
@@ -209,12 +232,12 @@ class SEQUENCER_MT_select(Menu):
layout.operator("sequencer.select_active_side", text="Strips to the Left").side = 'LEFT'
layout.operator("sequencer.select_active_side", text="Strips to the Right").side = 'RIGHT'
- op = layout.operator("sequencer.select", text="All strips to the Left")
- op.left_right = 'LEFT'
- op.linked_time = True
- op = layout.operator("sequencer.select", text="All strips to the Right")
- op.left_right = 'RIGHT'
- op.linked_time = True
+ props = layout.operator("sequencer.select", text="All strips to the Left")
+ props.left_right = 'LEFT'
+ props.linked_time = True
+ props = layout.operator("sequencer.select", text="All strips to the Right")
+ props.left_right = 'RIGHT'
+ props.linked_time = True
layout.separator()
layout.operator("sequencer.select_handles", text="Surrounding Handles").side = 'BOTH'
@@ -223,6 +246,8 @@ class SEQUENCER_MT_select(Menu):
layout.separator()
layout.operator_menu_enum("sequencer.select_grouped", "type", text="Grouped")
layout.operator("sequencer.select_linked")
+ layout.operator("sequencer.select_less")
+ layout.operator("sequencer.select_more")
layout.operator("sequencer.select_all").action = 'TOGGLE'
layout.operator("sequencer.select_all", text="Inverse").action = 'INVERT'
@@ -312,6 +337,7 @@ class SEQUENCER_MT_add_effect(Menu):
layout.operator("sequencer.effect_strip_add", text="Over Drop").type = 'OVER_DROP'
layout.operator("sequencer.effect_strip_add", text="Wipe").type = 'WIPE'
layout.operator("sequencer.effect_strip_add", text="Glow").type = 'GLOW'
+ layout.operator("sequencer.effect_strip_add", text="Text").type = 'TEXT'
layout.operator("sequencer.effect_strip_add", text="Transform").type = 'TRANSFORM'
layout.operator("sequencer.effect_strip_add", text="Color").type = 'COLOR'
layout.operator("sequencer.effect_strip_add", text="Speed Control").type = 'SPEED'
@@ -329,7 +355,7 @@ class SEQUENCER_MT_strip(Menu):
layout.operator("transform.transform", text="Grab/Move").mode = 'TRANSLATION'
layout.operator("transform.transform", text="Grab/Extend from frame").mode = 'TIME_EXTEND'
- layout.operator("sequencer.gap_remove")
+ layout.operator("sequencer.gap_remove").all = False
layout.operator("sequencer.gap_insert")
# uiItemO(layout, NULL, 0, "sequencer.strip_snap"); // TODO - add this operator
@@ -337,6 +363,7 @@ class SEQUENCER_MT_strip(Menu):
layout.operator("sequencer.cut", text="Cut (hard) at frame").type = 'HARD'
layout.operator("sequencer.cut", text="Cut (soft) at frame").type = 'SOFT'
+ layout.operator("sequencer.slip", text="Slip Strip Contents")
layout.operator("sequencer.images_separate")
layout.operator("sequencer.offset_clear")
layout.operator("sequencer.deinterlace_selected_movies")
@@ -384,7 +411,7 @@ class SEQUENCER_MT_strip(Menu):
#}
layout.separator()
- layout.operator("sequencer.reload", text="Reload Strips").adjust_length = False
+ layout.operator("sequencer.reload", text="Reload Strips")
layout.operator("sequencer.reload", text="Reload Strips and Adjust Length").adjust_length = True
layout.operator("sequencer.reassign_inputs")
layout.operator("sequencer.swap_inputs")
@@ -393,7 +420,7 @@ class SEQUENCER_MT_strip(Menu):
layout.operator("sequencer.lock")
layout.operator("sequencer.unlock")
layout.operator("sequencer.mute").unselected = False
- layout.operator("sequencer.unmute")
+ layout.operator("sequencer.unmute").unselected = False
layout.operator("sequencer.mute", text="Mute Deselected Strips").unselected = True
@@ -407,7 +434,7 @@ class SEQUENCER_MT_strip(Menu):
layout.menu("SEQUENCER_MT_change")
-class SequencerButtonsPanel():
+class SequencerButtonsPanel:
bl_space_type = 'SEQUENCE_EDITOR'
bl_region_type = 'UI'
@@ -420,13 +447,14 @@ class SequencerButtonsPanel():
return cls.has_sequencer(context) and (act_strip(context) is not None)
-class SequencerButtonsPanel_Output():
+class SequencerButtonsPanel_Output:
bl_space_type = 'SEQUENCE_EDITOR'
bl_region_type = 'UI'
@staticmethod
def has_preview(context):
- return (context.space_data.view_type in {'PREVIEW', 'SEQUENCER_PREVIEW'})
+ st = context.space_data
+ return (st.view_type in {'PREVIEW', 'SEQUENCER_PREVIEW'}) or st.show_backdrop
@classmethod
def poll(cls, context):
@@ -451,7 +479,7 @@ class SEQUENCER_PT_edit(SequencerButtonsPanel, Panel):
split.label(text="Type:")
split.prop(strip, "type", text="")
- if strip.type not in {'SOUND'}:
+ if strip.type != 'SOUND':
split = layout.split(percentage=0.3)
split.label(text="Blend:")
split.prop(strip, "blend_type", text="")
@@ -514,7 +542,7 @@ class SEQUENCER_PT_effect(SequencerButtonsPanel, Panel):
return strip.type in {'ADD', 'SUBTRACT', 'ALPHA_OVER', 'ALPHA_UNDER',
'CROSS', 'GAMMA_CROSS', 'MULTIPLY', 'OVER_DROP',
'WIPE', 'GLOW', 'TRANSFORM', 'COLOR', 'SPEED',
- 'MULTICAM', 'GAUSSIAN_BLUR'}
+ 'MULTICAM', 'GAUSSIAN_BLUR', 'TEXT'}
def draw(self, context):
layout = self.layout
@@ -605,6 +633,17 @@ class SEQUENCER_PT_effect(SequencerButtonsPanel, Panel):
for i in range(1, strip.channel):
row.operator("sequencer.cut_multicam", text="%d" % i).camera = i
+ elif strip.type == 'TEXT':
+ col = layout.column()
+ col.prop(strip, "text")
+ col.prop(strip, "font_size")
+ col.prop(strip, "use_shadow")
+ col.prop(strip, "align_x")
+ col.prop(strip, "align_y")
+ col.prop(strip, "location")
+ col.prop(strip, "wrap_width")
+ layout.operator("sequencer.export_subtitles")
+
col = layout.column(align=True)
if strip.type == 'SPEED':
col.prop(strip, "multiply_speed")
@@ -615,7 +654,7 @@ class SEQUENCER_PT_effect(SequencerButtonsPanel, Panel):
elif strip.type == 'GAUSSIAN_BLUR':
col.prop(strip, "size_x")
col.prop(strip, "size_y")
-
+
class SEQUENCER_PT_input(SequencerButtonsPanel, Panel):
bl_label = "Strip Input"
@@ -637,6 +676,7 @@ class SEQUENCER_PT_input(SequencerButtonsPanel, Panel):
def draw(self, context):
layout = self.layout
+ scene = context.scene
strip = act_strip(context)
@@ -650,7 +690,7 @@ class SEQUENCER_PT_input(SequencerButtonsPanel, Panel):
# Current element for the filename
- elem = strip.strip_elem_from_frame(context.scene.frame_current)
+ elem = strip.strip_elem_from_frame(scene.frame_current)
if elem:
split = layout.split(percentage=0.2)
split.label(text="File:")
@@ -696,6 +736,19 @@ class SEQUENCER_PT_input(SequencerButtonsPanel, Panel):
col.prop(strip, "frame_offset_start", text="Start")
col.prop(strip, "frame_offset_end", text="End")
+ if scene.render.use_multiview and seq_type in {'IMAGE', 'MOVIE'}:
+ layout.prop(strip, "use_multiview")
+
+ col = layout.column()
+ col.active = strip.use_multiview
+
+ col.label(text="Views Format:")
+ col.row().prop(strip, "views_format", expand=True)
+
+ box = col.box()
+ box.active = strip.views_format == 'STEREO_3D'
+ box.template_image_stereo_3d(strip.stereo_3d_format)
+
class SEQUENCER_PT_sound(SequencerButtonsPanel, Panel):
bl_label = "Sound"
@@ -714,6 +767,7 @@ class SEQUENCER_PT_sound(SequencerButtonsPanel, Panel):
def draw(self, context):
layout = self.layout
+ st = context.space_data
strip = act_strip(context)
sound = strip.sound
@@ -732,7 +786,9 @@ class SEQUENCER_PT_sound(SequencerButtonsPanel, Panel):
row.prop(sound, "use_memory_cache")
- layout.prop(strip, "show_waveform")
+ if st.waveform_draw_type == 'DEFAULT_WAVEFORMS':
+ layout.prop(strip, "show_waveform")
+
layout.prop(strip, "volume")
layout.prop(strip, "pitch")
layout.prop(strip, "pan")
@@ -774,6 +830,8 @@ class SEQUENCER_PT_scene(SequencerButtonsPanel, Panel):
layout.label(text="Camera Override")
layout.template_ID(strip, "scene_camera")
+ layout.prop(strip, "use_grease_pencil", text="Show Grease Pencil")
+
if scene:
layout.prop(scene, "audio_volume", text="Audio Volume")
@@ -887,16 +945,25 @@ class SEQUENCER_PT_proxy(SequencerButtonsPanel, Panel):
def draw(self, context):
layout = self.layout
+ sequencer = context.scene.sequence_editor
+
strip = act_strip(context)
- flow = layout.column_flow()
- flow.prop(strip, "use_proxy_custom_directory")
- flow.prop(strip, "use_proxy_custom_file")
if strip.proxy:
- if strip.use_proxy_custom_directory and not strip.use_proxy_custom_file:
- flow.prop(strip.proxy, "directory")
- if strip.use_proxy_custom_file:
- flow.prop(strip.proxy, "filepath")
+ proxy = strip.proxy
+
+ flow = layout.column_flow()
+ flow.prop(sequencer, "proxy_storage")
+ if sequencer.proxy_storage == 'PROJECT':
+ flow.prop(sequencer, "proxy_dir")
+ else:
+ flow.prop(proxy, "use_proxy_custom_directory")
+ flow.prop(proxy, "use_proxy_custom_file")
+
+ if proxy.use_proxy_custom_directory and not proxy.use_proxy_custom_file:
+ flow.prop(proxy, "directory")
+ if proxy.use_proxy_custom_file:
+ flow.prop(proxy, "filepath")
row = layout.row()
row.prop(strip.proxy, "build_25")
@@ -904,15 +971,21 @@ class SEQUENCER_PT_proxy(SequencerButtonsPanel, Panel):
row.prop(strip.proxy, "build_75")
row.prop(strip.proxy, "build_100")
+ layout.prop(proxy, "use_overwrite")
+
col = layout.column()
col.label(text="Build JPEG quality")
- col.prop(strip.proxy, "quality")
+ col.prop(proxy, "quality")
if strip.type == 'MOVIE':
col = layout.column()
col.label(text="Use timecode index:")
- col.prop(strip.proxy, "timecode")
+ col.prop(proxy, "timecode")
+
+ col = layout.column()
+ col.operator("sequencer.enable_proxies")
+ col.operator("sequencer.rebuild_proxy")
class SEQUENCER_PT_preview(SequencerButtonsPanel_Output, Panel):
@@ -947,12 +1020,41 @@ class SEQUENCER_PT_view(SequencerButtonsPanel_Output, Panel):
col = layout.column()
if st.display_mode == 'IMAGE':
col.prop(st, "draw_overexposed")
- col.prop(st, "show_safe_margin")
+ col.separator()
+
elif st.display_mode == 'WAVEFORM':
col.prop(st, "show_separate_color")
+
+ col = layout.column()
+ col.separator()
col.prop(st, "proxy_render_size")
+class SEQUENCER_PT_view_safe_areas(SequencerButtonsPanel_Output, Panel):
+ bl_label = "Safe Areas"
+ bl_options = {'DEFAULT_CLOSED'}
+
+ @classmethod
+ def poll(cls, context):
+ st = context.space_data
+ is_preview = st.view_type in {'PREVIEW', 'SEQUENCER_PREVIEW'}
+ return is_preview and (st.display_mode == 'IMAGE')
+
+ def draw_header(self, context):
+ st = context.space_data
+
+ self.layout.prop(st, "show_safe_areas", text="")
+
+ def draw(self, context):
+ from bl_ui.properties_data_camera import draw_display_safe_settings
+
+ layout = self.layout
+ st = context.space_data
+ safe_data = context.scene.safe_areas
+
+ draw_display_safe_settings(layout, safe_data, st)
+
+
class SEQUENCER_PT_modifiers(SequencerButtonsPanel, Panel):
bl_label = "Modifiers"
@@ -965,6 +1067,7 @@ class SEQUENCER_PT_modifiers(SequencerButtonsPanel, Panel):
layout.prop(strip, "use_linear_modifiers")
layout.operator_menu_enum("sequencer.strip_modifier_add", "type")
+ layout.operator("sequencer.strip_modifier_copy")
for mod in strip.modifiers:
box = layout.box()
@@ -1010,5 +1113,28 @@ class SEQUENCER_PT_modifiers(SequencerButtonsPanel, Panel):
col.prop(mod, "contrast")
+class SEQUENCER_PT_grease_pencil(GreasePencilDataPanel, SequencerButtonsPanel_Output, Panel):
+ bl_space_type = 'SEQUENCE_EDITOR'
+ bl_region_type = 'UI'
+
+ # NOTE: this is just a wrapper around the generic GP Panel
+ # But, it should only show up when there are images in the preview region
+
+
+class SEQUENCER_PT_grease_pencil_tools(GreasePencilToolsPanel, SequencerButtonsPanel_Output, Panel):
+ bl_space_type = 'SEQUENCE_EDITOR'
+ bl_region_type = 'UI'
+
+ # NOTE: this is just a wrapper around the generic GP tools panel
+ # It contains access to some essential tools usually found only in
+ # toolbar, which doesn't exist here...
+
+
+class SEQUENCER_PT_custom_props(SequencerButtonsPanel, PropertyPanel, Panel):
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
+ _context_path = "scene.sequence_editor.active_strip"
+ _property_type = (bpy.types.Sequence,)
+
+
if __name__ == "__main__": # only for live edit.
bpy.utils.register_module(__name__)
diff --git a/release/scripts/startup/bl_ui/space_text.py b/release/scripts/startup/bl_ui/space_text.py
index a430fb09165..5eb4e333130 100644
--- a/release/scripts/startup/bl_ui/space_text.py
+++ b/release/scripts/startup/bl_ui/space_text.py
@@ -181,7 +181,8 @@ class TEXT_MT_view(Menu):
layout.separator()
layout.operator("screen.area_dupli")
- layout.operator("screen.screen_full_area")
+ layout.operator("screen.screen_full_area", text="Toggle Maximize Area")
+ layout.operator("screen.screen_full_area").use_hide_panels = True
class TEXT_MT_text(Menu):
diff --git a/release/scripts/startup/bl_ui/space_time.py b/release/scripts/startup/bl_ui/space_time.py
index cfb147b3566..817c28c6359 100644
--- a/release/scripts/startup/bl_ui/space_time.py
+++ b/release/scripts/startup/bl_ui/space_time.py
@@ -30,6 +30,7 @@ class TIME_HT_header(Header):
scene = context.scene
toolsettings = context.tool_settings
screen = context.screen
+ userprefs = context.user_preferences
row = layout.row(align=True)
row.template_header()
@@ -82,7 +83,7 @@ class TIME_HT_header(Header):
if toolsettings.use_keyframe_insert_auto:
row.prop(toolsettings, "use_keyframe_insert_keyingset", text="", toggle=True)
- if screen.is_animation_playing:
+ if screen.is_animation_playing and not userprefs.edit.use_keyframe_insert_available:
subsub = row.row(align=True)
subsub.prop(toolsettings, "use_record_with_nla", toggle=True)
@@ -145,7 +146,8 @@ class TIME_MT_view(Menu):
layout.separator()
layout.operator("screen.area_dupli")
- layout.operator("screen.screen_full_area")
+ layout.operator("screen.screen_full_area", text="Toggle Maximize Area")
+ layout.operator("screen.screen_full_area").use_hide_panels = True
class TIME_MT_cache(Menu):
@@ -206,6 +208,8 @@ class TIME_MT_playback(Menu):
layout.prop(screen, "use_play_clip_editors")
layout.separator()
+ layout.prop(screen, "use_follow")
+ layout.separator()
layout.prop(scene, "use_frame_drop", text="Frame Dropping")
layout.prop(scene, "use_audio_sync", text="AV-sync", icon='SPEAKER')
@@ -226,7 +230,7 @@ class TIME_MT_autokey(Menu):
def marker_menu_generic(layout):
- #layout.operator_context = 'EXEC_REGION_WIN'
+ # layout.operator_context = 'EXEC_REGION_WIN'
layout.column()
layout.operator("marker.add", "Add Marker")
@@ -250,6 +254,10 @@ def marker_menu_generic(layout):
layout.operator("screen.marker_jump", text="Jump to Next Marker").next = True
layout.operator("screen.marker_jump", text="Jump to Previous Marker").next = False
+ layout.separator()
+ ts = bpy.context.tool_settings
+ layout.prop(ts, "lock_markers")
+
if __name__ == "__main__": # only for live edit.
bpy.utils.register_module(__name__)
diff --git a/release/scripts/startup/bl_ui/space_userpref.py b/release/scripts/startup/bl_ui/space_userpref.py
index 59b842a7a5b..1259e743152 100644
--- a/release/scripts/startup/bl_ui/space_userpref.py
+++ b/release/scripts/startup/bl_ui/space_userpref.py
@@ -113,11 +113,19 @@ class USERPREF_MT_splash(Menu):
row.label("")
row = split.row()
row.label("Interaction:")
- # XXX, no redraws
- # text = bpy.path.display_name(context.window_manager.keyconfigs.active.name)
- # if not text:
- # text = "Blender (default)"
- row.menu("USERPREF_MT_appconfigs", text="Preset")
+
+ text = bpy.path.display_name(context.window_manager.keyconfigs.active.name)
+ if not text:
+ text = "Blender (default)"
+ row.menu("USERPREF_MT_appconfigs", text=text)
+
+
+# only for addons
+class USERPREF_MT_splash_footer(Menu):
+ bl_label = ""
+
+ def draw(self, context):
+ pass
class USERPREF_PT_interface(Panel):
@@ -162,6 +170,12 @@ class USERPREF_PT_interface(Panel):
sub.prop(view, "mini_axis_brightness", text="Brightness")
col.separator()
+
+ if sys.platform[:3] == "win":
+ col.label("Warnings")
+ col.prop(view, "use_quit_dialog")
+ col.prop(view, "use_gl_warn_support")
+
row.separator()
row.separator()
@@ -186,6 +200,11 @@ class USERPREF_PT_interface(Panel):
col.label(text="2D Viewports:")
col.prop(view, "view2d_grid_spacing_min", text="Minimum Grid Spacing")
col.prop(view, "timecode_style")
+ col.prop(view, "view_frame_type")
+ if (view.view_frame_type == 'SECONDS'):
+ col.prop(view, "view_frame_seconds")
+ elif (view.view_frame_type == 'KEYFRAMES'):
+ col.prop(view, "view_frame_keyframes")
row.separator()
row.separator()
@@ -223,15 +242,13 @@ class USERPREF_PT_interface(Panel):
sub.prop(view, "pie_initial_timeout")
sub.prop(view, "pie_menu_radius")
sub.prop(view, "pie_menu_threshold")
+ sub.prop(view, "pie_menu_confirm")
col.separator()
col.separator()
col.separator()
col.prop(view, "show_splash")
- if sys.platform[:3] == "win":
- col.prop(view, "use_quit_dialog")
-
class USERPREF_PT_edit(Panel):
bl_space_type = 'USER_PREFERENCES'
@@ -296,6 +313,8 @@ class USERPREF_PT_edit(Panel):
col.separator()
col.separator()
col.separator()
+ col.label(text="Node Editor:")
+ col.prop(edit, "node_margin")
col.label(text="Animation Editors:")
col.prop(edit, "fcurve_unselected_alpha", text="F-Curve Visibility")
@@ -383,15 +402,20 @@ class USERPREF_PT_system(Panel):
col = colsplit.column()
col.label(text="General:")
col.prop(system, "dpi")
+ col.label("Virtual Pixel Mode:")
+ col.prop(system, "virtual_pixel_mode", text="")
+
+ col.separator()
+
col.prop(system, "frame_server_port")
col.prop(system, "scrollback", text="Console Scrollback")
col.separator()
col.label(text="Sound:")
- col.row().prop(system, "audio_device", expand=True)
+ col.row().prop(system, "audio_device", expand=False)
sub = col.column()
- sub.active = system.audio_device != 'NONE'
+ sub.active = system.audio_device != 'NONE' and system.audio_device != 'Null'
#sub.prop(system, "use_preview_images")
sub.prop(system, "audio_channels", text="Channels")
sub.prop(system, "audio_mixing_buffer", text="Mixing Buffer")
@@ -413,6 +437,10 @@ class USERPREF_PT_system(Panel):
sub.active = system.compute_device_type != 'CPU'
sub.prop(system, "compute_device", text="")
+ if hasattr(system, "opensubdiv_compute_type"):
+ col.label(text="OpenSubdiv compute:")
+ col.row().prop(system, "opensubdiv_compute_type", text="")
+
# 2. Column
column = split.column()
colsplit = column.split(percentage=0.85)
@@ -465,7 +493,8 @@ class USERPREF_PT_system(Panel):
col.separator()
col.label(text="Sequencer / Clip Editor:")
- col.prop(system, "prefetch_frames")
+ # currently disabled in the code
+ # col.prop(system, "prefetch_frames")
col.prop(system, "memory_cache_limit")
# 3. Column
@@ -738,7 +767,7 @@ class USERPREF_PT_theme(Panel):
col.separator()
col.separator()
- col.label("Menu Shadow:")
+ col.label("Styles:")
row = col.row()
@@ -756,11 +785,6 @@ class USERPREF_PT_theme(Panel):
colsub = padding.column()
colsub.row().prop(ui, "menu_shadow_width")
- col.separator()
- col.separator()
-
- col.label("Icons:")
-
row = col.row()
subsplit = row.split(percentage=0.95)
@@ -768,16 +792,14 @@ class USERPREF_PT_theme(Panel):
padding = subsplit.split(percentage=0.15)
colsub = padding.column()
colsub = padding.column()
- # Not working yet.
- #~ colsub.active = False
- #~ colsub.row().prop(ui, "icon_file")
+ colsub.row().prop(ui, "icon_alpha")
subsplit = row.split(percentage=0.85)
padding = subsplit.split(percentage=0.15)
colsub = padding.column()
colsub = padding.column()
- colsub.row().prop(ui, "icon_alpha")
+ colsub.row().prop(ui, "widget_emboss")
col.separator()
col.separator()
@@ -973,6 +995,7 @@ class USERPREF_MT_ndof_settings(Menu):
layout.prop(input_prefs, "ndof_sensitivity")
layout.prop(input_prefs, "ndof_orbit_sensitivity")
+ layout.prop(input_prefs, "ndof_deadzone")
if is_view3d:
layout.separator()
@@ -1031,7 +1054,8 @@ class USERPREF_PT_input(Panel):
userpref = context.user_preferences
return (userpref.active_section == 'INPUT')
- def draw_input_prefs(self, inputs, layout):
+ @staticmethod
+ def draw_input_prefs(inputs, layout):
import sys
# General settings
@@ -1114,10 +1138,12 @@ class USERPREF_PT_input(Panel):
sub.prop(walk, "jump_height")
col.separator()
- sub = col.column()
- sub.label(text="NDOF Device:")
+ col.label(text="NDOF Device:")
+ sub = col.column(align=True)
sub.prop(inputs, "ndof_sensitivity", text="NDOF Sensitivity")
sub.prop(inputs, "ndof_orbit_sensitivity", text="NDOF Orbit Sensitivity")
+ sub.prop(inputs, "ndof_deadzone", text="NDOF Deadzone")
+ sub = col.column(align=True)
sub.row().prop(inputs, "ndof_view_navigate_method", expand=True)
sub.row().prop(inputs, "ndof_view_rotate_method", expand=True)
@@ -1154,14 +1180,14 @@ class USERPREF_MT_addons_dev_guides(Menu):
def draw(self, context):
layout = self.layout
- layout.operator("wm.url_open", text="API Concepts", icon='URL').url = "http://wiki.blender.org/index.php/Dev:2.5/Py/API/Intro"
+ layout.operator("wm.url_open", text="API Concepts", icon='URL').url = bpy.types.WM_OT_doc_view._prefix + "/info_quickstart.html"
layout.operator("wm.url_open", text="Addon Guidelines", icon='URL').url = "http://wiki.blender.org/index.php/Dev:2.5/Py/Scripts/Guidelines/Addons"
layout.operator("wm.url_open", text="How to share your addon", icon='URL').url = "http://wiki.blender.org/index.php/Dev:Py/Sharing"
class USERPREF_PT_addons(Panel):
bl_space_type = 'USER_PREFERENCES'
- bl_label = "Addons"
+ bl_label = "Add-ons"
bl_region_type = 'WINDOW'
bl_options = {'HIDE_HEADER'}
diff --git a/release/scripts/startup/bl_ui/space_view3d.py b/release/scripts/startup/bl_ui/space_view3d.py
index 3d0e767f5e1..bb0ad001c34 100644
--- a/release/scripts/startup/bl_ui/space_view3d.py
+++ b/release/scripts/startup/bl_ui/space_view3d.py
@@ -19,6 +19,7 @@
# <pep8 compliant>
import bpy
from bpy.types import Header, Menu, Panel
+from bl_ui.properties_grease_pencil_common import GreasePencilDataPanel
from bl_ui.properties_paint_common import UnifiedPaintPanel
from bpy.app.translations import contexts as i18n_contexts
@@ -56,7 +57,12 @@ class VIEW3D_HT_header(Header):
row.prop(view, "use_occlude_geometry", text="")
# Proportional editing
- if mode in {'EDIT', 'PARTICLE_EDIT'}:
+ if context.gpencil_data and context.gpencil_data.use_stroke_edit_mode:
+ row = layout.row(align=True)
+ row.prop(toolsettings, "proportional_edit", icon_only=True)
+ if toolsettings.proportional_edit != 'DISABLED':
+ row.prop(toolsettings, "proportional_edit_falloff", icon_only=True)
+ elif mode in {'EDIT', 'PARTICLE_EDIT'}:
row = layout.row(align=True)
row.prop(toolsettings, "proportional_edit", icon_only=True)
if toolsettings.proportional_edit != 'DISABLED':
@@ -66,6 +72,13 @@ class VIEW3D_HT_header(Header):
row.prop(toolsettings, "use_proportional_edit_objects", icon_only=True)
if toolsettings.use_proportional_edit_objects:
row.prop(toolsettings, "proportional_edit_falloff", icon_only=True)
+ else:
+ # Proportional editing
+ if context.gpencil_data and context.gpencil_data.use_stroke_edit_mode:
+ row = layout.row(align=True)
+ row.prop(toolsettings, "proportional_edit", icon_only=True)
+ if toolsettings.proportional_edit != 'DISABLED':
+ row.prop(toolsettings, "proportional_edit_falloff", icon_only=True)
# Snap
if not obj or mode not in {'SCULPT', 'VERTEX_PAINT', 'WEIGHT_PAINT', 'TEXTURE_PAINT'}:
@@ -73,7 +86,9 @@ class VIEW3D_HT_header(Header):
row = layout.row(align=True)
row.prop(toolsettings, "use_snap", text="")
row.prop(toolsettings, "snap_element", icon_only=True)
- if snap_element != 'INCREMENT':
+ if snap_element == 'INCREMENT':
+ row.prop(toolsettings, "use_snap_grid_absolute", text="")
+ else:
row.prop(toolsettings, "snap_target", text="")
if obj:
if mode in {'OBJECT', 'POSE'} and snap_element != 'VOLUME':
@@ -100,8 +115,8 @@ class VIEW3D_HT_header(Header):
if obj and mode == 'POSE':
row = layout.row(align=True)
row.operator("pose.copy", text="", icon='COPYDOWN')
- row.operator("pose.paste", text="", icon='PASTEDOWN')
- row.operator("pose.paste", text="", icon='PASTEFLIPDOWN').flipped = 1
+ row.operator("pose.paste", text="", icon='PASTEDOWN').flipped = False
+ row.operator("pose.paste", text="", icon='PASTEFLIPDOWN').flipped = True
class VIEW3D_MT_editor_menus(Menu):
@@ -145,7 +160,7 @@ class VIEW3D_MT_editor_menus(Menu):
if edit_object:
layout.menu("VIEW3D_MT_edit_%s" % edit_object.type.lower())
elif obj:
- if mode_string not in {'PAINT_TEXTURE'}:
+ if mode_string != 'PAINT_TEXTURE':
layout.menu("VIEW3D_MT_%s" % mode_string.lower())
if mode_string in {'SCULPT', 'PAINT_VERTEX', 'PAINT_WEIGHT', 'PAINT_TEXTURE'}:
layout.menu("VIEW3D_MT_brush")
@@ -161,7 +176,7 @@ class VIEW3D_MT_editor_menus(Menu):
# ********** Utilities **********
-class ShowHideMenu():
+class ShowHideMenu:
bl_label = "Show/Hide"
_operator_name = ""
@@ -195,8 +210,10 @@ class VIEW3D_MT_transform_base(Menu):
layout.operator("transform.shear", text="Shear")
layout.operator("transform.bend", text="Bend")
layout.operator("transform.push_pull", text="Push/Pull")
- layout.operator("object.vertex_warp", text="Warp")
- layout.operator("object.vertex_random", text="Randomize")
+
+ if context.mode != 'OBJECT':
+ layout.operator("transform.vertex_warp", text="Warp")
+ layout.operator("transform.vertex_random", text="Randomize")
# Generic transform menu - geometry types
@@ -401,7 +418,7 @@ class VIEW3D_MT_view(Menu):
layout.operator("view3d.clip_border", text="Clipping Border...")
layout.operator("view3d.zoom_border", text="Zoom Border...")
- layout.operator("view3d.render_border", text="Render Border...")
+ layout.operator("view3d.render_border", text="Render Border...").camera_only = False
layout.separator()
@@ -410,8 +427,8 @@ class VIEW3D_MT_view(Menu):
layout.separator()
layout.operator("view3d.localview", text="View Global/Local")
- layout.operator("view3d.view_selected")
- layout.operator("view3d.view_all")
+ layout.operator("view3d.view_selected").use_all_regions = False
+ layout.operator("view3d.view_all").center = False
layout.separator()
@@ -421,7 +438,8 @@ class VIEW3D_MT_view(Menu):
layout.operator("screen.area_dupli")
layout.operator("screen.region_quadview")
- layout.operator("screen.screen_full_area")
+ layout.operator("screen.screen_full_area", text="Toggle Maximize Area")
+ layout.operator("screen.screen_full_area").use_hide_panels = True
class VIEW3D_MT_view_navigation(Menu):
@@ -432,6 +450,9 @@ class VIEW3D_MT_view_navigation(Menu):
layout = self.layout
layout.operator_enum("view3d.view_orbit", "type")
+ props = layout.operator("view3d.view_orbit", "Orbit Opposite")
+ props.type = 'ORBITRIGHT'
+ props.angle = pi
layout.separator()
@@ -564,8 +585,13 @@ class VIEW3D_MT_select_pose(Menu):
layout.separator()
- layout.operator("pose.select_hierarchy", text="Parent").direction = 'PARENT'
- layout.operator("pose.select_hierarchy", text="Child").direction = 'CHILD'
+ props = layout.operator("pose.select_hierarchy", text="Parent")
+ props.extend = False
+ props.direction = 'PARENT'
+
+ props = layout.operator("pose.select_hierarchy", text="Child")
+ props.extend = False
+ props.direction = 'CHILD'
layout.separator()
@@ -604,10 +630,27 @@ class VIEW3D_MT_select_particle(Menu):
layout.separator()
+ layout.operator("particle.select_random")
+
+ layout.separator()
+
layout.operator("particle.select_roots", text="Roots")
layout.operator("particle.select_tips", text="Tips")
+class VIEW3D_MT_edit_mesh_select_similar(Menu):
+ bl_label = "Select Similar"
+
+ def draw(self, context):
+ layout = self.layout
+
+ layout.operator_enum("mesh.select_similar", "type")
+
+ layout.separator()
+
+ layout.operator("mesh.select_similar_region", text="Face Regions")
+
+
class VIEW3D_MT_select_edit_mesh(Menu):
bl_label = "Select"
@@ -647,7 +690,7 @@ class VIEW3D_MT_select_edit_mesh(Menu):
layout.separator()
# other ...
- layout.operator_menu_enum("mesh.select_similar", "type", text="Similar")
+ layout.menu("VIEW3D_MT_edit_mesh_select_similar")
layout.operator("mesh.select_ungrouped", text="Ungrouped Verts")
layout.separator()
@@ -687,6 +730,7 @@ class VIEW3D_MT_select_edit_curve(Menu):
layout.operator("curve.select_random")
layout.operator("curve.select_nth")
layout.operator("curve.select_linked", text="Select Linked")
+ layout.operator("curve.select_similar", text="Select Similar")
layout.separator()
@@ -717,6 +761,7 @@ class VIEW3D_MT_select_edit_surface(Menu):
layout.operator("curve.select_random")
layout.operator("curve.select_nth")
layout.operator("curve.select_linked", text="Select Linked")
+ layout.operator("curve.select_similar", text="Select Similar")
layout.separator()
@@ -816,8 +861,13 @@ class VIEW3D_MT_select_edit_armature(Menu):
layout.separator()
- layout.operator("armature.select_hierarchy", text="Parent").direction = 'PARENT'
- layout.operator("armature.select_hierarchy", text="Child").direction = 'CHILD'
+ props = layout.operator("armature.select_hierarchy", text="Parent")
+ props.extend = False
+ props.direction = 'PARENT'
+
+ props = layout.operator("armature.select_hierarchy", text="Child")
+ props.extend = False
+ props.direction = 'CHILD'
layout.separator()
@@ -870,6 +920,41 @@ class VIEW3D_MT_select_paint_mask_vertex(Menu):
layout.operator("paint.vert_select_ungrouped", text="Ungrouped Verts")
+
+class VIEW3D_MT_angle_control(Menu):
+ bl_label = "Angle Control"
+
+ @classmethod
+ def poll(cls, context):
+ settings = UnifiedPaintPanel.paint_settings(context)
+ if not settings:
+ return False
+
+ brush = settings.brush
+ tex_slot = brush.texture_slot
+
+ return tex_slot.has_texture_angle and tex_slot.has_texture_angle_source
+
+ def draw(self, context):
+ layout = self.layout
+
+ settings = UnifiedPaintPanel.paint_settings(context)
+ brush = settings.brush
+
+ sculpt = (context.sculpt_object is not None)
+
+ tex_slot = brush.texture_slot
+
+ layout.prop(tex_slot, "use_rake", text="Rake")
+
+ if brush.brush_capabilities.has_random_texture_angle and tex_slot.has_random_texture_angle:
+ if sculpt:
+ if brush.sculpt_capabilities.has_random_texture_angle:
+ layout.prop(tex_slot, "use_random", text="Random")
+ else:
+ layout.prop(tex_slot, "use_random", text="Random")
+
+
# ********** Add menu **********
# XXX: INFO_MT_ names used to keep backwards compatibility (Addons etc that hook into the menu)
@@ -964,6 +1049,17 @@ class INFO_MT_armature_add(Menu):
layout.operator("object.armature_add", text="Single Bone", icon='BONE_DATA')
+class INFO_MT_lamp_add(Menu):
+ bl_idname = "INFO_MT_lamp_add"
+ bl_label = "Lamp"
+
+ def draw(self, context):
+ layout = self.layout
+
+ layout.operator_context = 'INVOKE_REGION_WIN'
+ layout.operator_enum("object.lamp_add", "type")
+
+
class INFO_MT_add(Menu):
bl_label = "Add"
@@ -996,7 +1092,7 @@ class INFO_MT_add(Menu):
layout.separator()
layout.operator("object.camera_add", text="Camera", icon='OUTLINER_OB_CAMERA')
- layout.operator_menu_enum("object.lamp_add", "type", text="Lamp", icon='OUTLINER_OB_LAMP')
+ layout.menu("INFO_MT_lamp_add", icon='OUTLINER_OB_LAMP')
layout.separator()
layout.operator_menu_enum("object.effector_add", "type", text="Force Field", icon='OUTLINER_OB_EMPTY')
@@ -1039,7 +1135,7 @@ class VIEW3D_MT_object(Menu):
layout.operator("object.duplicate_move")
layout.operator("object.duplicate_move_linked")
- layout.operator("object.delete", text="Delete...")
+ layout.operator("object.delete", text="Delete...").use_global = False
layout.operator("object.proxy_make", text="Make Proxy...")
layout.menu("VIEW3D_MT_make_links", text="Make Links...")
layout.operator("object.make_dupli_face")
@@ -1064,6 +1160,8 @@ class VIEW3D_MT_object(Menu):
layout.separator()
layout.operator("object.join")
+ layout.operator("object.data_transfer")
+ layout.operator("object.datalayout_transfer")
layout.separator()
@@ -1136,12 +1234,16 @@ class VIEW3D_MT_object_specials(Menu):
props.header_text = "Camera Lens Scale: %.3f"
if not obj.data.dof_object:
- #layout.label(text="Test Has DOF obj");
- props = layout.operator("wm.context_modal_mouse", text="DOF Distance")
- props.data_path_iter = "selected_editable_objects"
- props.data_path_item = "data.dof_distance"
- props.input_scale = 0.02
- props.header_text = "DOF Distance: %.3f"
+ view = context.space_data
+ if view and view.camera == obj and view.region_3d.view_perspective == 'CAMERA':
+ props = layout.operator("ui.eyedropper_depth", text="DOF Distance (Pick)")
+ else:
+ props = layout.operator("wm.context_modal_mouse", text="DOF Distance")
+ props.data_path_iter = "selected_editable_objects"
+ props.data_path_item = "data.dof_distance"
+ props.input_scale = 0.02
+ props.header_text = "DOF Distance: %.3f"
+ del view
if obj.type in {'CURVE', 'FONT'}:
layout.operator_context = 'INVOKE_REGION_WIN'
@@ -1569,8 +1671,10 @@ class VIEW3D_MT_paint_weight(Menu):
layout.operator("object.vertex_group_clean", text="Clean")
layout.operator("object.vertex_group_quantize", text="Quantize")
layout.operator("object.vertex_group_levels", text="Levels")
- layout.operator("object.vertex_group_blend", text="Blend")
- layout.operator("object.vertex_group_transfer_weight", text="Transfer Weights")
+ layout.operator("object.vertex_group_smooth", text="Smooth")
+ props = layout.operator("object.data_transfer", text="Transfer Weights")
+ props.use_reverse_transfer = True
+ props.data_type = 'VGROUP_WEIGHTS'
layout.operator("object.vertex_group_limit_total", text="Limit Total")
layout.operator("object.vertex_group_fix", text="Fix Deforms")
@@ -1712,6 +1816,10 @@ class VIEW3D_MT_particle_specials(Menu):
layout.separator()
+ layout.operator("particle.select_random")
+
+ layout.separator()
+
layout.operator("particle.select_more")
layout.operator("particle.select_less")
@@ -1759,7 +1867,7 @@ class VIEW3D_MT_pose(Menu):
layout.separator()
layout.operator("pose.copy")
- layout.operator("pose.paste")
+ layout.operator("pose.paste").flipped = False
layout.operator("pose.paste", text="Paste X-Flipped Pose").flipped = True
layout.separator()
@@ -1842,6 +1950,10 @@ class VIEW3D_MT_pose_propagate(Menu):
layout.separator()
+ layout.operator("pose.propagate", text="On Selected Keyframes").mode = 'SELECTED_KEYS'
+
+ layout.separator()
+
layout.operator("pose.propagate", text="On Selected Markers").mode = 'SELECTED_MARKERS'
@@ -1886,7 +1998,7 @@ class VIEW3D_MT_pose_group(Menu):
layout.separator()
- #layout.operator_context = 'INVOKE_AREA'
+ # layout.operator_context = 'INVOKE_AREA'
layout.operator("pose.group_unassign")
layout.operator("pose.group_remove")
@@ -2165,15 +2277,16 @@ class VIEW3D_MT_edit_mesh_vertices(Menu):
layout.operator("mesh.rip_edge_move")
layout.operator("mesh.split")
layout.operator_menu_enum("mesh.separate", "type")
- layout.operator("mesh.vert_connect", text="Connect")
+ layout.operator("mesh.vert_connect_path", text="Connect Vertex Path")
+ layout.operator("mesh.vert_connect", text="Connect Vertices")
layout.operator("transform.vert_slide", text="Slide")
layout.separator()
- op = layout.operator("mesh.mark_sharp", text="Shade Smooth")
- op.use_verts = True
- op.clear = True
- layout.operator("mesh.mark_sharp", text="Shade Sharp").use_verts = True
+ layout.operator("mesh.mark_sharp", text="Mark Sharp Edges").use_verts = True
+ props = layout.operator("mesh.mark_sharp", text="Clear Sharp Edges")
+ props.use_verts = True
+ props.clear = True
layout.separator()
@@ -2184,7 +2297,7 @@ class VIEW3D_MT_edit_mesh_vertices(Menu):
layout.operator("mesh.blend_from_shape")
- layout.operator("object.vertex_group_blend")
+ layout.operator("object.vertex_group_smooth")
layout.operator("mesh.shape_propagate_to_all")
layout.separator()
@@ -2277,7 +2390,8 @@ class VIEW3D_MT_edit_mesh_faces(Menu):
layout.separator()
layout.operator("mesh.poke")
- layout.operator("mesh.quads_convert_to_tris")
+ props = layout.operator("mesh.quads_convert_to_tris")
+ props.quad_method = props.ngon_method = 'BEAUTY'
layout.operator("mesh.tris_convert_to_quads")
layout.operator("mesh.face_split_by_edges")
@@ -2286,6 +2400,8 @@ class VIEW3D_MT_edit_mesh_faces(Menu):
layout.operator("mesh.faces_shade_smooth")
layout.operator("mesh.faces_shade_flat")
+ layout.operator("mesh.normals_make_consistent", text="Recalculate Normals").inside = False
+
layout.separator()
layout.operator("mesh.edge_rotate", text="Rotate Edge CW").use_ccw = False
@@ -2324,7 +2440,9 @@ class VIEW3D_MT_edit_mesh_clean(Menu):
layout.operator("mesh.dissolve_degenerate")
layout.operator("mesh.dissolve_limited")
+ layout.operator("mesh.face_make_planar")
layout.operator("mesh.vert_connect_nonplanar")
+ layout.operator("mesh.vert_connect_concave")
layout.operator("mesh.fill_holes")
@@ -2355,6 +2473,20 @@ class VIEW3D_MT_edit_mesh_delete(Menu):
class VIEW3D_MT_edit_mesh_showhide(ShowHideMenu, Menu):
_operator_name = "mesh"
+
+class VIEW3D_MT_edit_gpencil_delete(Menu):
+ bl_label = "Delete"
+
+ def draw(self, context):
+ layout = self.layout
+
+ layout.operator_enum("gpencil.delete", "type")
+
+ layout.separator()
+
+ layout.operator("gpencil.dissolve")
+
+
# Edit Curve
# draw_curve is used by VIEW3D_MT_edit_curve and VIEW3D_MT_edit_surface
@@ -2371,6 +2503,7 @@ def draw_curve(self, context):
layout.separator()
layout.operator("curve.extrude_move")
+ layout.operator("curve.spin")
layout.operator("curve.duplicate_move")
layout.operator("curve.split")
layout.operator("curve.separate")
@@ -2410,7 +2543,6 @@ class VIEW3D_MT_edit_curve_ctrlpoints(Menu):
if edit_object.type == 'CURVE':
layout.operator("transform.tilt")
layout.operator("curve.tilt_clear")
- layout.operator("curve.separate")
layout.separator()
@@ -2473,10 +2605,6 @@ class VIEW3D_MT_edit_font(Menu):
layout.operator("font.style_toggle", text="Toggle Underline").style = 'UNDERLINE'
layout.operator("font.style_toggle", text="Toggle Small Caps").style = 'SMALL_CAPS'
- layout.separator()
-
- layout.operator("font.insert_lorem")
-
class VIEW3D_MT_edit_text_chars(Menu):
bl_label = "Special Characters"
@@ -2615,6 +2743,7 @@ class VIEW3D_MT_edit_armature(Menu):
layout.separator()
layout.operator_context = 'EXEC_AREA'
+ layout.operator("armature.symmetrize")
layout.operator("armature.autoside_names", text="AutoName Left/Right").type = 'XAXIS'
layout.operator("armature.autoside_names", text="AutoName Front/Back").type = 'YAXIS'
layout.operator("armature.autoside_names", text="AutoName Top/Bottom").type = 'ZAXIS'
@@ -2653,6 +2782,7 @@ class VIEW3D_MT_armature_specials(Menu):
layout.operator("armature.autoside_names", text="AutoName Front/Back").type = 'YAXIS'
layout.operator("armature.autoside_names", text="AutoName Top/Bottom").type = 'ZAXIS'
layout.operator("armature.flip_names", text="Flip Names")
+ layout.operator("armature.symmetrize")
class VIEW3D_MT_edit_armature_parent(Menu):
@@ -2677,9 +2807,30 @@ class VIEW3D_MT_edit_armature_roll(Menu):
layout.operator("transform.transform", text="Set Roll").mode = 'BONE_ROLL'
+
+class VIEW3D_MT_edit_armature_delete(Menu):
+ bl_label = "Delete"
+
+ def draw(self, context):
+ layout = self.layout
+
+ layout.operator("armature.delete", text="Delete Bones")
+
+ layout.separator()
+
+ layout.operator("armature.dissolve", text="Dissolve")
+
+
# ********** Panel **********
+class VIEW3D_PT_grease_pencil(GreasePencilDataPanel, Panel):
+ bl_space_type = 'VIEW_3D'
+ bl_region_type = 'UI'
+
+ # NOTE: this is just a wrapper around the generic GP Panel
+
+
class VIEW3D_PT_view3d_properties(Panel):
bl_space_type = 'VIEW_3D'
bl_region_type = 'UI'
@@ -2789,6 +2940,7 @@ class VIEW3D_PT_view3d_display(Panel):
col = layout.column()
col.prop(view, "show_only_render")
+ col.prop(view, "show_world")
col = layout.column()
display_all = not view.show_only_render
@@ -2831,16 +2983,50 @@ class VIEW3D_PT_view3d_display(Panel):
row.prop(region, "use_box_clip")
-class VIEW3D_PT_view3d_shading(Panel):
+class VIEW3D_PT_view3d_stereo(Panel):
bl_space_type = 'VIEW_3D'
bl_region_type = 'UI'
- bl_label = "Shading"
+ bl_label = "Stereoscopy"
bl_options = {'DEFAULT_CLOSED'}
@classmethod
def poll(cls, context):
+ scene = context.scene
+
+ multiview = scene.render.use_multiview
+ return context.space_data and multiview
+
+ def draw(self, context):
+ layout = self.layout
view = context.space_data
- return (view)
+
+ basic_stereo = context.scene.render.views_format == 'STEREO_3D'
+
+ col = layout.column()
+ col.row().prop(view, "stereo_3d_camera", expand=True)
+
+ col.label(text="Display:")
+ row = col.row()
+ row.active = basic_stereo
+ row.prop(view, "show_stereo_3d_cameras")
+ row = col.row()
+ row.active = basic_stereo
+ split = row.split()
+ split.prop(view, "show_stereo_3d_convergence_plane")
+ split = row.split()
+ split.prop(view, "stereo_3d_convergence_plane_alpha", text="Alpha")
+ split.active = view.show_stereo_3d_convergence_plane
+ row = col.row()
+ split = row.split()
+ split.prop(view, "show_stereo_3d_volume")
+ split = row.split()
+ split.prop(view, "stereo_3d_volume_alpha", text="Alpha")
+
+
+class VIEW3D_PT_view3d_shading(Panel):
+ bl_space_type = 'VIEW_3D'
+ bl_region_type = 'UI'
+ bl_label = "Shading"
def draw(self, context):
layout = self.layout
@@ -2865,8 +3051,26 @@ class VIEW3D_PT_view3d_shading(Panel):
col.prop(view, "show_textured_shadeless")
col.prop(view, "show_backface_culling")
- if obj and obj.mode == 'EDIT' and view.viewport_shade not in {'BOUNDBOX', 'WIREFRAME'}:
- col.prop(view, "show_occlude_wire")
+
+ if view.viewport_shade not in {'BOUNDBOX', 'WIREFRAME'}:
+ if obj and obj.mode == 'EDIT':
+ col.prop(view, "show_occlude_wire")
+
+ fx_settings = view.fx_settings
+
+ if view.viewport_shade not in {'BOUNDBOX', 'WIREFRAME'}:
+ sub = col.column()
+ sub.active = view.region_3d.view_perspective == 'CAMERA'
+ sub.prop(fx_settings, "use_dof")
+ col.prop(fx_settings, "use_ssao", text="Ambient Occlusion")
+ if fx_settings.use_ssao:
+ ssao_settings = fx_settings.ssao
+ subcol = col.column(align=True)
+ subcol.prop(ssao_settings, "factor")
+ subcol.prop(ssao_settings, "distance_max")
+ subcol.prop(ssao_settings, "attenuation")
+ subcol.prop(ssao_settings, "samples")
+ subcol.prop(ssao_settings, "color")
class VIEW3D_PT_view3d_motion_tracking(Panel):
@@ -3050,6 +3254,7 @@ class VIEW3D_PT_background_image(Panel):
layout = self.layout
view = context.space_data
+ use_multiview = context.scene.render.use_multiview
col = layout.column()
col.operator("view3d.background_image_add", text="Add Image")
@@ -3087,6 +3292,19 @@ class VIEW3D_PT_background_image(Panel):
box.template_image(bg, "image", bg.image_user, compact=True)
has_bg = True
+ if use_multiview and bg.view_axis in {'CAMERA', 'ALL'}:
+ box.prop(bg.image, "use_multiview")
+
+ column = box.column()
+ column.active = bg.image.use_multiview
+
+ column.label(text="Views Format:")
+ column.row().prop(bg.image, "views_format", expand=True)
+
+ sub = column.box()
+ sub.active = bg.image.views_format == 'STEREO_3D'
+ sub.template_image_stereo_3d(bg.image.stereo_3d_format)
+
elif bg.source == 'MOVIE_CLIP':
box.prop(bg, "use_camera_clip")
@@ -3113,12 +3331,19 @@ class VIEW3D_PT_background_image(Panel):
if bg.view_axis in {'CAMERA', 'ALL'}:
col.row().prop(bg, "frame_method", expand=True)
- row = col.row(align=True)
+ box = col.box()
+ row = box.row()
row.prop(bg, "offset_x", text="X")
row.prop(bg, "offset_y", text="Y")
+ row = box.row()
+ row.prop(bg, "use_flip_x")
+ row.prop(bg, "use_flip_y")
+
+ row = box.row()
if bg.view_axis != 'CAMERA':
- col.prop(bg, "size")
+ row.prop(bg, "rotation")
+ row.prop(bg, "size")
class VIEW3D_PT_transform_orientations(Panel):
diff --git a/release/scripts/startup/bl_ui/space_view3d_toolbar.py b/release/scripts/startup/bl_ui/space_view3d_toolbar.py
index 1969572530d..a24dc494c30 100644
--- a/release/scripts/startup/bl_ui/space_view3d_toolbar.py
+++ b/release/scripts/startup/bl_ui/space_view3d_toolbar.py
@@ -19,7 +19,10 @@
# <pep8 compliant>
import bpy
from bpy.types import Menu, Panel, UIList
-from bl_ui.properties_grease_pencil_common import GreasePencilPanel
+from bl_ui.properties_grease_pencil_common import (
+ GreasePencilDrawingToolsPanel,
+ GreasePencilStrokeEditPanel
+ )
from bl_ui.properties_paint_common import (
UnifiedPaintPanel,
brush_texture_settings,
@@ -28,7 +31,7 @@ from bl_ui.properties_paint_common import (
)
-class View3DPanel():
+class View3DPanel:
bl_space_type = 'VIEW_3D'
bl_region_type = 'TOOLS'
@@ -97,6 +100,13 @@ class VIEW3D_PT_tools_object(View3DPanel, Panel):
row.operator("object.shade_smooth", text="Smooth")
row.operator("object.shade_flat", text="Flat")
+ if obj_type == 'MESH':
+ col = layout.column(align=True)
+ col.label(text="Data Transfer:")
+ row = col.row(align=True)
+ row.operator("object.data_transfer", text="Data")
+ row.operator("object.datalayout_transfer", text="Data Layout")
+
class VIEW3D_PT_tools_add_object(View3DPanel, Panel):
bl_category = "Create"
@@ -305,7 +315,7 @@ class VIEW3D_PT_tools_meshedit(View3DPanel, Panel):
row.operator("transform.vert_slide", text="Vertex")
col.operator("mesh.noise")
col.operator("mesh.vertices_smooth")
- col.operator("object.vertex_random")
+ col.operator("transform.vertex_random")
col = layout.column(align=True)
col.label(text="Add:")
@@ -313,8 +323,11 @@ class VIEW3D_PT_tools_meshedit(View3DPanel, Panel):
col.menu("VIEW3D_MT_edit_mesh_extrude")
col.operator("view3d.edit_mesh_extrude_move_normal", text="Extrude Region")
col.operator("view3d.edit_mesh_extrude_individual_move", text="Extrude Individual")
+ col.operator("mesh.inset", text="Inset Faces")
+ col.operator("mesh.edge_face_add")
col.operator("mesh.subdivide")
col.operator("mesh.loopcut_slide")
+ col.operator("mesh.offset_edge_loops_slide")
col.operator("mesh.duplicate_move", text="Duplicate")
row = col.row(align=True)
row.operator("mesh.spin")
@@ -354,7 +367,7 @@ class VIEW3D_PT_tools_meshweight(View3DPanel, Panel):
col.operator("object.vertex_group_clean", text="Clean")
col.operator("object.vertex_group_quantize", text="Quantize")
col.operator("object.vertex_group_levels", text="Levels")
- col.operator("object.vertex_group_blend", text="Blend")
+ col.operator("object.vertex_group_smooth", text="Smooth")
col.operator("object.vertex_group_limit_total", text="Limit Total")
col.operator("object.vertex_group_fix", text="Fix Deforms")
@@ -395,9 +408,9 @@ class VIEW3D_PT_tools_shading(View3DPanel, Panel):
row.operator("mesh.mark_sharp", text="Sharp")
col.label(text="Vertices:")
row = col.row(align=True)
- op = row.operator("mesh.mark_sharp", text="Smooth")
- op.use_verts = True
- op.clear = True
+ props = row.operator("mesh.mark_sharp", text="Smooth")
+ props.use_verts = True
+ props.clear = True
row.operator("mesh.mark_sharp", text="Sharp").use_verts = True
col = layout.column(align=True)
@@ -511,7 +524,7 @@ class VIEW3D_PT_tools_curveedit(View3DPanel, Panel):
col.operator("curve.extrude_move", text="Extrude")
col.operator("curve.subdivide")
col.operator("curve.smooth")
- col.operator("object.vertex_random")
+ col.operator("transform.vertex_random")
class VIEW3D_PT_tools_add_curve_edit(View3DPanel, Panel):
@@ -561,11 +574,12 @@ class VIEW3D_PT_tools_surfaceedit(View3DPanel, Panel):
col = layout.column(align=True)
col.label(text="Modeling:")
col.operator("curve.extrude", text="Extrude")
+ col.operator("curve.spin")
col.operator("curve.subdivide")
col = layout.column(align=True)
col.label(text="Deform:")
- col.operator("object.vertex_random")
+ col.operator("transform.vertex_random")
class VIEW3D_PT_tools_add_surface_edit(View3DPanel, Panel):
@@ -642,7 +656,7 @@ class VIEW3D_PT_tools_armatureedit(View3DPanel, Panel):
col = layout.column(align=True)
col.label(text="Deform:")
- col.operator("object.vertex_random")
+ col.operator("transform.vertex_random")
class VIEW3D_PT_tools_armatureedit_options(View3DPanel, Panel):
@@ -675,7 +689,7 @@ class VIEW3D_PT_tools_mballedit(View3DPanel, Panel):
col = layout.column(align=True)
col.label(text="Deform:")
- col.operator("object.vertex_random")
+ col.operator("transform.vertex_random")
class VIEW3D_PT_tools_add_mball_edit(View3DPanel, Panel):
@@ -713,7 +727,7 @@ class VIEW3D_PT_tools_latticeedit(View3DPanel, Panel):
col = layout.column(align=True)
col.label(text="Deform:")
- col.operator("object.vertex_random")
+ col.operator("transform.vertex_random")
# ********** default tools for pose-mode ****************
@@ -746,6 +760,10 @@ class VIEW3D_PT_tools_posemode(View3DPanel, Panel):
row.operator("pose.copy", text="Copy")
row.operator("pose.paste", text="Paste")
+ row = layout.row(align=True)
+ row.operator("pose.propagate", text="Propagate")
+ row.menu("VIEW3D_MT_pose_propagate", icon='TRIA_RIGHT', text="")
+
col = layout.column(align=True)
col.operator("poselib.pose_add", text="Add To Library")
@@ -776,6 +794,65 @@ class View3DPaintPanel(UnifiedPaintPanel):
bl_region_type = 'TOOLS'
+class VIEW3D_PT_imapaint_tools_missing(Panel, View3DPaintPanel):
+ bl_category = "Tools"
+ bl_label = "Missing Data"
+
+ @classmethod
+ def poll(cls, context):
+ toolsettings = context.tool_settings.image_paint
+ return context.image_paint_object and not toolsettings.detect_data()
+
+ def draw(self, context):
+ layout = self.layout
+ toolsettings = context.tool_settings.image_paint
+
+ col = layout.column()
+ col.label("Missing Data", icon='ERROR')
+ if toolsettings.missing_uvs:
+ col.separator()
+ col.label("Missing UVs", icon='INFO')
+ col.label("Unwrap the mesh in edit mode or generate a simple UV layer")
+ col.operator("paint.add_simple_uvs")
+
+ if toolsettings.mode == 'MATERIAL':
+ if toolsettings.missing_materials:
+ col.separator()
+ col.label("Missing Materials", icon='INFO')
+ col.label("Add a material and paint slot below")
+ col.operator_menu_enum("paint.add_texture_paint_slot", "type", text="Add Paint Slot")
+ elif toolsettings.missing_texture:
+ ob = context.active_object
+ mat = ob.active_material
+
+ col.separator()
+ if mat:
+ col.label("Missing Texture Slots", icon='INFO')
+ col.label("Add a paint slot below")
+ col.operator_menu_enum("paint.add_texture_paint_slot", "type", text="Add Paint Slot")
+ else:
+ col.label("Missing Materials", icon='INFO')
+ col.label("Add a material and paint slot below")
+ col.operator_menu_enum("paint.add_texture_paint_slot", "type", text="Add Paint Slot")
+
+ elif toolsettings.mode == 'IMAGE':
+ if toolsettings.missing_texture:
+ col.separator()
+ col.label("Missing Canvas", icon='INFO')
+ col.label("Add or assign a canvas image below")
+ col.label("Canvas Image")
+ col.template_ID(toolsettings, "canvas")
+ col.operator("image.new", text="New").gen_context = 'PAINT_CANVAS'
+
+ if toolsettings.missing_stencil:
+ col.separator()
+ col.label("Missing Stencil", icon='INFO')
+ col.label("Add or assign a stencil image below")
+ col.label("Stencil Image")
+ col.template_ID(toolsettings, "stencil_image")
+ col.operator("image.new", text="New").gen_context = 'PAINT_STENCIL'
+
+
class VIEW3D_PT_tools_brush(Panel, View3DPaintPanel):
bl_category = "Tools"
bl_label = "Brush"
@@ -811,10 +888,8 @@ class VIEW3D_PT_tools_brush(Panel, View3DPaintPanel):
col.prop(brush, "count")
col = layout.column()
col.prop(settings, "use_default_interpolate")
- sub = col.column(align=True)
- sub.active = settings.use_default_interpolate
- sub.prop(brush, "steps", slider=True)
- sub.prop(settings, "default_key_count", slider=True)
+ col.prop(brush, "steps", slider=True)
+ col.prop(settings, "default_key_count", slider=True)
elif tool == 'LENGTH':
layout.prop(brush, "length_mode", expand=True)
elif tool == 'PUFF':
@@ -844,14 +919,15 @@ class VIEW3D_PT_tools_brush(Panel, View3DPaintPanel):
self.prop_unified_size(row, context, brush, "use_pressure_size")
# strength, use_strength_pressure, and use_strength_attenuation
- if capabilities.has_strength:
- col.separator()
- row = col.row(align=True)
+ col.separator()
+ row = col.row(align=True)
+
+ if capabilities.has_space_attenuation:
+ row.prop(brush, "use_space_attenuation", toggle=True, icon_only=True)
- if capabilities.has_space_attenuation:
- row.prop(brush, "use_space_attenuation", toggle=True, icon_only=True)
+ self.prop_unified_strength(row, context, brush, "strength", text="Strength")
- self.prop_unified_strength(row, context, brush, "strength", text="Strength")
+ if capabilities.has_strength_pressure:
self.prop_unified_strength(row, context, brush, "use_pressure_strength")
# auto_smooth_factor and use_inverse_smooth_pressure
@@ -998,13 +1074,14 @@ class TEXTURE_UL_texpaintslots(UIList):
if self.layout_type in {'DEFAULT', 'COMPACT'}:
layout.prop(item, "name", text="", emboss=False, icon_value=icon)
- if (not mat.use_nodes) and (context.scene.render.engine == 'BLENDER_RENDER'):
+ if (not mat.use_nodes) and context.scene.render.engine in {'BLENDER_RENDER', 'BLENDER_GAME'}:
mtex_index = mat.texture_paint_slots[index].index
layout.prop(mat, "use_textures", text="", index=mtex_index)
- elif self.layout_type in {'GRID'}:
+ elif self.layout_type == 'GRID':
layout.alignment = 'CENTER'
layout.label(text="")
+
class VIEW3D_MT_tools_projectpaint_uvlayer(Menu):
bl_label = "Clone Layer"
@@ -1055,24 +1132,30 @@ class VIEW3D_PT_slots_projectpaint(View3DPanel, Panel):
mat, "texture_paint_images",
mat, "paint_active_slot", rows=2)
- if (not mat.use_nodes) and (context.scene.render.engine == 'BLENDER_RENDER'):
+ if mat.texture_paint_slots:
+ slot = mat.texture_paint_slots[mat.paint_active_slot]
+ else:
+ slot = None
+
+ if (not mat.use_nodes) and context.scene.render.engine in {'BLENDER_RENDER', 'BLENDER_GAME'}:
row = col.row(align=True)
row.operator_menu_enum("paint.add_texture_paint_slot", "type")
row.operator("paint.delete_texture_paint_slot", text="", icon='X')
- if mat.texture_paint_slots:
- slot = mat.texture_paint_slots[mat.paint_active_slot]
-
+ if slot:
col.prop(mat.texture_slots[slot.index], "blend_type")
col.separator()
- col.label("UV Map")
- col.prop_search(slot, "uv_layer", ob.data, "uv_textures", text="")
+
+ if slot and slot.index != -1:
+ col.label("UV Map")
+ col.prop_search(slot, "uv_layer", ob.data, "uv_textures", text="")
elif settings.mode == 'IMAGE':
mesh = ob.data
uv_text = mesh.uv_textures.active.name if mesh.uv_textures.active else ""
- col.label("Image")
+ col.label("Canvas Image")
col.template_ID(settings, "canvas")
+ col.operator("image.new", text="New").gen_context = 'PAINT_CANVAS'
col.label("UV Map")
col.menu("VIEW3D_MT_tools_projectpaint_uvlayer", text=uv_text, translate=False)
@@ -1110,10 +1193,10 @@ class VIEW3D_PT_stencil_projectpaint(View3DPanel, Panel):
col.label("UV Map")
col.menu("VIEW3D_MT_tools_projectpaint_stencil", text=stencil_text, translate=False)
- col.label("Image")
- row = col.row(align=True)
- row.template_ID(ipaint, "stencil_image")
-
+ col.label("Stencil Image")
+ col.template_ID(ipaint, "stencil_image")
+ col.operator("image.new", text="New").gen_context = 'PAINT_STENCIL'
+
col.label("Visualization")
row = col.row(align=True)
row.prop(ipaint, "stencil_color", text="")
@@ -1210,7 +1293,7 @@ class VIEW3D_PT_tools_brush_texture(Panel, View3DPaintPanel):
brush_texture_settings(col, brush, context.sculpt_object)
-class VIEW3D_PT_tools_mask_texture(View3DPanel, Panel):
+class VIEW3D_PT_tools_mask_texture(Panel, View3DPaintPanel):
bl_category = "Tools"
bl_context = "imagepaint"
bl_label = "Texture Mask"
@@ -1218,8 +1301,8 @@ class VIEW3D_PT_tools_mask_texture(View3DPanel, Panel):
@classmethod
def poll(cls, context):
- brush = context.tool_settings.image_paint.brush
- return (context.image_paint_object and brush)
+ settings = cls.paint_settings(context)
+ return (settings and settings.brush and context.image_paint_object)
def draw(self, context):
layout = self.layout
@@ -1390,6 +1473,8 @@ class VIEW3D_PT_sculpt_dyntopo(Panel, View3DPaintPanel):
row = sub.row(align=True)
row.prop(sculpt, "constant_detail")
row.operator("sculpt.sample_detail_size", text="", icon='EYEDROPPER')
+ elif (sculpt.detail_type_method == 'BRUSH'):
+ sub.prop(sculpt, "detail_percent")
else:
sub.prop(sculpt, "detail_size")
sub.prop(sculpt, "detail_refine_method", text="")
@@ -1467,6 +1552,15 @@ class VIEW3D_PT_sculpt_symmetry(Panel, View3DPaintPanel):
row.prop(sculpt, "lock_y", text="Y", toggle=True)
row.prop(sculpt, "lock_z", text="Z", toggle=True)
+ layout.label(text="Tiling:")
+
+ row = layout.row(align=True)
+ row.prop(sculpt, "tile_x", text="X", toggle=True)
+ row.prop(sculpt, "tile_y", text="Y", toggle=True)
+ row.prop(sculpt, "tile_z", text="Z", toggle=True)
+
+ layout.column().prop(sculpt, "tile_offset", text="Tile Offset")
+
class VIEW3D_PT_tools_brush_appearance(Panel, View3DPaintPanel):
bl_category = "Options"
@@ -1474,11 +1568,8 @@ class VIEW3D_PT_tools_brush_appearance(Panel, View3DPaintPanel):
@classmethod
def poll(cls, context):
- toolsettings = context.tool_settings
- return ((context.sculpt_object and toolsettings.sculpt) or
- (context.vertex_paint_object and toolsettings.vertex_paint) or
- (context.weight_paint_object and toolsettings.weight_paint) or
- (context.image_paint_object and toolsettings.image_paint))
+ settings = cls.paint_settings(context)
+ return settings
def draw(self, context):
layout = self.layout
@@ -1527,7 +1618,9 @@ class VIEW3D_PT_tools_weightpaint(View3DPanel, Panel):
col = layout.column()
col.operator("paint.weight_gradient")
- col.operator("object.vertex_group_transfer_weight", text="Transfer Weights")
+ props = col.operator("object.data_transfer", text="Transfer Weights")
+ props.use_reverse_transfer = True
+ props.data_type = 'VGROUP_WEIGHTS'
class VIEW3D_PT_tools_weightpaint_options(Panel, View3DPaintPanel):
@@ -1618,6 +1711,25 @@ class VIEW3D_PT_tools_imagepaint_external(Panel, View3DPaintPanel):
col.operator("paint.project_image", text="Apply Camera Image")
+class VIEW3D_PT_tools_imagepaint_symmetry(Panel, View3DPaintPanel):
+ bl_category = "Tools"
+ bl_context = "imagepaint"
+ bl_label = "Symmetry"
+ bl_options = {'DEFAULT_CLOSED'}
+
+ def draw(self, context):
+ layout = self.layout
+
+ toolsettings = context.tool_settings
+ ipaint = toolsettings.image_paint
+
+ col = layout.column(align=True)
+ row = col.row(align=True)
+ row.prop(ipaint, "use_symmetry_x", text="X", toggle=True)
+ row.prop(ipaint, "use_symmetry_y", text="Y", toggle=True)
+ row.prop(ipaint, "use_symmetry_z", text="Z", toggle=True)
+
+
class VIEW3D_PT_tools_projectpaint(View3DPaintPanel, Panel):
bl_category = "Options"
bl_context = "imagepaint"
@@ -1646,7 +1758,12 @@ class VIEW3D_PT_tools_projectpaint(View3DPaintPanel, Panel):
sub.active = (ipaint.use_normal_falloff)
sub.prop(ipaint, "normal_angle", text="")
+ layout.prop(ipaint, "use_cavity")
+ if ipaint.use_cavity:
+ layout.template_curve_mapping(ipaint, "cavity_curve", brush=True)
+
layout.prop(ipaint, "seam_bleed")
+ layout.prop(ipaint, "dither")
self.unified_paint_settings(layout, context)
@@ -1730,6 +1847,9 @@ class VIEW3D_PT_tools_particlemode(View3DPanel, Panel):
col.prop(pe, "use_auto_velocity", text="Velocity")
col.prop(ob.data, "use_mirror_x")
+ col.prop(pe, "shape_object")
+ col.operator("particle.shape_cut")
+
col = layout.column(align=True)
col.active = pe.is_editable
col.label(text="Draw:")
@@ -1745,11 +1865,14 @@ class VIEW3D_PT_tools_particlemode(View3DPanel, Panel):
sub.prop(pe, "fade_frames", slider=True)
-# Grease Pencil tools
-class VIEW3D_PT_tools_grease_pencil(GreasePencilPanel, Panel):
+# Grease Pencil drawing tools
+class VIEW3D_PT_tools_grease_pencil_draw(GreasePencilDrawingToolsPanel, Panel):
+ bl_space_type = 'VIEW_3D'
+
+
+# Grease Pencil stroke editing tools
+class VIEW3D_PT_tools_grease_pencil_edit(GreasePencilStrokeEditPanel, Panel):
bl_space_type = 'VIEW_3D'
- bl_region_type = 'TOOLS'
- bl_category = "Grease Pencil"
# Note: moved here so that it's always in last position in 'Tools' panels!
@@ -1767,7 +1890,7 @@ class VIEW3D_PT_tools_history(View3DPanel, Panel):
row = col.row(align=True)
row.operator("ed.undo")
row.operator("ed.redo")
- if obj is None or obj.mode not in {'SCULPT'}:
+ if obj is None or obj.mode != 'SCULPT':
# Sculpt mode does not generate an undo menu it seems...
col.operator("ed.undo_history")
diff --git a/release/scripts/startup/nodeitems_builtins.py b/release/scripts/startup/nodeitems_builtins.py
index 5dccda789e0..c3def14787d 100644
--- a/release/scripts/startup/nodeitems_builtins.py
+++ b/release/scripts/startup/nodeitems_builtins.py
@@ -66,6 +66,8 @@ node_tree_group_type = {
# generic node group items generator for shader, compositor and texture node groups
def node_group_items(context):
+ if context is None:
+ return
space = context.space_data
if not space:
return
@@ -112,6 +114,20 @@ def line_style_shader_nodes_poll(context):
snode.shader_type == 'LINESTYLE')
+# only show nodes working in world node trees
+def world_shader_nodes_poll(context):
+ snode = context.space_data
+ return (snode.tree_type == 'ShaderNodeTree' and
+ snode.shader_type == 'WORLD')
+
+
+# only show nodes working in object node trees
+def object_shader_nodes_poll(context):
+ snode = context.space_data
+ return (snode.tree_type == 'ShaderNodeTree' and
+ snode.shader_type == 'OBJECT')
+
+
# All standard node categories currently used in nodes.
shader_node_categories = [
@@ -125,6 +141,7 @@ shader_node_categories = [
NodeItem("ShaderNodeTexture"),
NodeItem("ShaderNodeGeometry"),
NodeItem("ShaderNodeExtendedMaterial"),
+ NodeItem("ShaderNodeParticleInfo"),
NodeItem("NodeGroupInput", poll=group_input_output_item_poll),
]),
ShaderOldNodeCategory("SH_OUTPUT", "Output", items=[
@@ -136,6 +153,7 @@ shader_node_categories = [
NodeItem("ShaderNodeRGBCurve"),
NodeItem("ShaderNodeInvert"),
NodeItem("ShaderNodeHueSaturation"),
+ NodeItem("ShaderNodeGamma"),
]),
ShaderOldNodeCategory("SH_OP_VECTOR", "Vector", items=[
NodeItem("ShaderNodeNormal"),
@@ -180,30 +198,30 @@ shader_node_categories = [
NodeItem("NodeGroupInput", poll=group_input_output_item_poll),
]),
ShaderNewNodeCategory("SH_NEW_OUTPUT", "Output", items=[
- NodeItem("ShaderNodeOutputMaterial"),
- NodeItem("ShaderNodeOutputLamp"),
- NodeItem("ShaderNodeOutputWorld"),
+ NodeItem("ShaderNodeOutputMaterial", poll=object_shader_nodes_poll),
+ NodeItem("ShaderNodeOutputLamp", poll=object_shader_nodes_poll),
+ NodeItem("ShaderNodeOutputWorld", poll=world_shader_nodes_poll),
NodeItem("ShaderNodeOutputLineStyle", poll=line_style_shader_nodes_poll),
NodeItem("NodeGroupOutput", poll=group_input_output_item_poll),
]),
ShaderNewNodeCategory("SH_NEW_SHADER", "Shader", items=[
NodeItem("ShaderNodeMixShader"),
NodeItem("ShaderNodeAddShader"),
- NodeItem("ShaderNodeBsdfDiffuse"),
- NodeItem("ShaderNodeBsdfGlossy"),
- NodeItem("ShaderNodeBsdfTransparent"),
- NodeItem("ShaderNodeBsdfRefraction"),
- NodeItem("ShaderNodeBsdfGlass"),
- NodeItem("ShaderNodeBsdfTranslucent"),
- NodeItem("ShaderNodeBsdfAnisotropic"),
- NodeItem("ShaderNodeBsdfVelvet"),
- NodeItem("ShaderNodeBsdfToon"),
- NodeItem("ShaderNodeSubsurfaceScattering"),
- NodeItem("ShaderNodeEmission"),
- NodeItem("ShaderNodeBsdfHair"),
- NodeItem("ShaderNodeBackground"),
- NodeItem("ShaderNodeAmbientOcclusion"),
- NodeItem("ShaderNodeHoldout"),
+ NodeItem("ShaderNodeBsdfDiffuse", poll=object_shader_nodes_poll),
+ NodeItem("ShaderNodeBsdfGlossy", poll=object_shader_nodes_poll),
+ NodeItem("ShaderNodeBsdfTransparent", poll=object_shader_nodes_poll),
+ NodeItem("ShaderNodeBsdfRefraction", poll=object_shader_nodes_poll),
+ NodeItem("ShaderNodeBsdfGlass", poll=object_shader_nodes_poll),
+ NodeItem("ShaderNodeBsdfTranslucent", poll=object_shader_nodes_poll),
+ NodeItem("ShaderNodeBsdfAnisotropic", poll=object_shader_nodes_poll),
+ NodeItem("ShaderNodeBsdfVelvet", poll=object_shader_nodes_poll),
+ NodeItem("ShaderNodeBsdfToon", poll=object_shader_nodes_poll),
+ NodeItem("ShaderNodeSubsurfaceScattering", poll=object_shader_nodes_poll),
+ NodeItem("ShaderNodeEmission", poll=object_shader_nodes_poll),
+ NodeItem("ShaderNodeBsdfHair", poll=object_shader_nodes_poll),
+ NodeItem("ShaderNodeBackground", poll=world_shader_nodes_poll),
+ NodeItem("ShaderNodeAmbientOcclusion", poll=object_shader_nodes_poll),
+ NodeItem("ShaderNodeHoldout", poll=object_shader_nodes_poll),
NodeItem("ShaderNodeVolumeAbsorption"),
NodeItem("ShaderNodeVolumeScatter"),
]),
@@ -219,6 +237,7 @@ shader_node_categories = [
NodeItem("ShaderNodeTexMagic"),
NodeItem("ShaderNodeTexChecker"),
NodeItem("ShaderNodeTexBrick"),
+ NodeItem("ShaderNodeTexPointDensity"),
]),
ShaderNewNodeCategory("SH_NEW_OP_COLOR", "Color", items=[
NodeItem("ShaderNodeMixRGB"),
@@ -313,6 +332,7 @@ compositor_node_categories = [
NodeItem("CompositorNodeCombYUVA"),
NodeItem("CompositorNodeSepYCCA"),
NodeItem("CompositorNodeCombYCCA"),
+ NodeItem("CompositorNodeSwitchView"),
]),
CompositorNodeCategory("CMP_OP_FILTER", "Filter", items=[
NodeItem("CompositorNodeBlur"),
diff --git a/release/scripts/templates_osl/fresnel_conductive.osl b/release/scripts/templates_osl/fresnel_conductive.osl
index c197656eaee..6de0692bffe 100644
--- a/release/scripts/templates_osl/fresnel_conductive.osl
+++ b/release/scripts/templates_osl/fresnel_conductive.osl
@@ -16,14 +16,14 @@
color fresnel_conductor(float cosi, color eta, color k)
{
- color cosi2 = color(cosi*cosi);
+ color cosi2 = color(cosi * cosi);
color one = color(1, 1, 1);
color tmp_f = eta * eta + k * k;
color tmp = tmp_f * cosi2;
color Rparl2 = (tmp - (2.0 * eta * cosi) + one) /
- (tmp + (2.0 * eta * cosi) + one);
+ (tmp + (2.0 * eta * cosi) + one);
color Rperp2 = (tmp_f - (2.0 * eta * cosi) + cosi2) /
- (tmp_f + (2.0 * eta * cosi) + cosi2);
+ (tmp_f + (2.0 * eta * cosi) + cosi2);
return (Rparl2 + Rperp2) * 0.5;
}
diff --git a/release/scripts/templates_osl/westin_closure.osl b/release/scripts/templates_osl/westin_closure.osl
deleted file mode 100644
index 8d90f3aa306..00000000000
--- a/release/scripts/templates_osl/westin_closure.osl
+++ /dev/null
@@ -1,12 +0,0 @@
-
-shader node_westin_bsdf(
- color Color = 0.8,
- float Roughness = 0.5,
- float Edginess = 0.2,
- normal Normal = N,
- output closure color Sheen = 0,
- output closure color Backscatter = 0)
-{
- Sheen = Color * westin_sheen(Normal, Roughness);
- Backscatter = Color * westin_backscatter(Normal, Edginess);
-} \ No newline at end of file
diff --git a/release/scripts/templates_py/addon_add_object.py b/release/scripts/templates_py/addon_add_object.py
index f0d8bede6d5..8e57d7ef8f8 100644
--- a/release/scripts/templates_py/addon_add_object.py
+++ b/release/scripts/templates_py/addon_add_object.py
@@ -2,12 +2,13 @@ bl_info = {
"name": "New Object",
"author": "Your Name Here",
"version": (1, 0),
- "blender": (2, 65, 0),
+ "blender": (2, 75, 0),
"location": "View3D > Add > Mesh > New Object",
"description": "Adds a new Mesh Object",
"warning": "",
"wiki_url": "",
- "category": "Add Mesh"}
+ "category": "Add Mesh",
+ }
import bpy
diff --git a/release/scripts/templates_py/custom_nodes.py b/release/scripts/templates_py/custom_nodes.py
index 992ef734859..32c61abace7 100644
--- a/release/scripts/templates_py/custom_nodes.py
+++ b/release/scripts/templates_py/custom_nodes.py
@@ -13,9 +13,6 @@ class MyCustomTree(NodeTree):
# Label for nice name display
bl_label = 'Custom Node Tree'
# Icon identifier
- # NOTE: If no icon is defined, the node tree will not show up in the editor header!
- # This can be used to make additional tree types for groups and similar nodes (see below)
- # Only one base tree class is needed in the editor for selecting the general category
bl_icon = 'NODETREE'
diff --git a/release/scripts/templates_py/operator_mesh_add.py b/release/scripts/templates_py/operator_mesh_add.py
index fa248cb9005..5fabaaf3f7f 100644
--- a/release/scripts/templates_py/operator_mesh_add.py
+++ b/release/scripts/templates_py/operator_mesh_add.py
@@ -89,6 +89,7 @@ class AddBox(bpy.types.Operator):
for v_co in verts_loc:
bm.verts.new(v_co)
+ bm.verts.ensure_lookup_table()
for f_idx in faces:
bm.faces.new([bm.verts[i] for i in f_idx])
diff --git a/release/scripts/templates_py/operator_modal_timer.py b/release/scripts/templates_py/operator_modal_timer.py
index 4d36860b9e3..df4d10e656b 100644
--- a/release/scripts/templates_py/operator_modal_timer.py
+++ b/release/scripts/templates_py/operator_modal_timer.py
@@ -10,7 +10,8 @@ class ModalTimerOperator(bpy.types.Operator):
def modal(self, context, event):
if event.type in {'RIGHTMOUSE', 'ESC'}:
- return self.cancel(context)
+ self.cancel(context)
+ return {'CANCELLED'}
if event.type == 'TIMER':
# change theme color, silly!
diff --git a/release/scripts/templates_py/operator_modal_view3d_raycast.py b/release/scripts/templates_py/operator_modal_view3d_raycast.py
index 1aa13c90ca3..b72b2f76750 100644
--- a/release/scripts/templates_py/operator_modal_view3d_raycast.py
+++ b/release/scripts/templates_py/operator_modal_view3d_raycast.py
@@ -14,10 +14,6 @@ def main(context, event, ray_max=1000.0):
view_vector = view3d_utils.region_2d_to_vector_3d(region, rv3d, coord)
ray_origin = view3d_utils.region_2d_to_origin_3d(region, rv3d, coord)
- if rv3d.view_perspective == 'ORTHO':
- # move ortho origin back
- ray_origin = ray_origin - (view_vector * (ray_max / 2.0))
-
ray_target = ray_origin + (view_vector * ray_max)
def visible_objects_and_duplis():
diff --git a/release/scripts/templates_py/ui_previews_custom_icon.py b/release/scripts/templates_py/ui_previews_custom_icon.py
new file mode 100644
index 00000000000..53f84b2982f
--- /dev/null
+++ b/release/scripts/templates_py/ui_previews_custom_icon.py
@@ -0,0 +1,76 @@
+# This sample script demonstrates how to place a custom icon on a button or
+# menu entry.
+#
+# IMPORTANT NOTE: if you run this sample, there will be no icon in the button
+# You need to replace the image path with a real existing one.
+# For distributable scripts, it is recommended to place the icons inside the
+# addon folder and access it relative to the py script file for portability
+#
+#
+# Other use cases for UI-previews:
+# - provide a fixed list of previews to select from
+# - provide a dynamic list of preview (eg. calculated from reading a directory)
+#
+# For the above use cases, see the template 'ui_previews_dynamic_enum.py"
+
+
+import os
+import bpy
+
+
+class PreviewsExamplePanel(bpy.types.Panel):
+ """Creates a Panel in the Object properties window"""
+ bl_label = "Previews Example Panel"
+ bl_idname = "OBJECT_PT_previews"
+ bl_space_type = 'PROPERTIES'
+ bl_region_type = 'WINDOW'
+ bl_context = "object"
+
+ def draw(self, context):
+ layout = self.layout
+ pcoll = preview_collections["main"]
+
+ row = layout.row()
+ my_icon = pcoll["my_icon"]
+ row.operator("render.render", icon_value=my_icon.icon_id)
+
+ # my_icon.icon_id can be used in any UI function that accepts
+ # icon_value # try also setting text=""
+ # to get an icon only operator button
+
+
+# We can store multiple preview collections here,
+# however in this example we only store "main"
+preview_collections = {}
+
+
+def register():
+
+ # Note that preview collections returned by bpy.utils.previews
+ # are regular py objects - you can use them to store custom data.
+ import bpy.utils.previews
+ pcoll = bpy.utils.previews.new()
+
+ # path to the folder where the icon is
+ # the path is calculated relative to this py file inside the addon folder
+ my_icons_dir = os.path.join(os.path.dirname(__file__), "icons")
+
+ # load a preview thumbnail of a file and store in the previews collection
+ pcoll.load("my_icon", os.path.join(my_icons_dir, "icon-image.png"), 'IMAGE')
+
+ preview_collections["main"] = pcoll
+
+ bpy.utils.register_class(PreviewsExamplePanel)
+
+
+def unregister():
+
+ for pcoll in preview_collections.values():
+ bpy.utils.previews.remove(pcoll)
+ preview_collections.clear()
+
+ bpy.utils.unregister_class(PreviewsExamplePanel)
+
+
+if __name__ == "__main__":
+ register()
diff --git a/release/scripts/templates_py/ui_previews_dynamic_enum.py b/release/scripts/templates_py/ui_previews_dynamic_enum.py
new file mode 100644
index 00000000000..0cfa232116d
--- /dev/null
+++ b/release/scripts/templates_py/ui_previews_dynamic_enum.py
@@ -0,0 +1,137 @@
+# This sample script demonstrates a dynamic EnumProperty with custom icons.
+# The EnumProperty is populated dynamically with thumbnails of the contents of
+# a chosen directory in 'enum_previews_from_directory_items'.
+# Then, the same enum is displayed with different interfaces. Note that the
+# generated icon previews do not have Blender IDs, which means that they can
+# not be used with UILayout templates that require IDs,
+# such as template_list and template_ID_preview.
+#
+# Other use cases:
+# - make a fixed list of enum_items instead of calculating them in a function
+# - generate isolated thumbnails to use as custom icons in buttons
+# and menu items
+#
+# For custom icons, see the template "ui_previews_custom_icon.py".
+#
+# For distributable scripts, it is recommended to place the icons inside the
+# script directory and access it relative to the py script file for portability:
+#
+# os.path.join(os.path.dirname(__file__), "images")
+
+
+import os
+import bpy
+
+
+def enum_previews_from_directory_items(self, context):
+ """EnumProperty callback"""
+ enum_items = []
+
+ if context is None:
+ return enum_items
+
+ wm = context.window_manager
+ directory = wm.my_previews_dir
+
+ # Get the preview collection (defined in register func).
+ pcoll = preview_collections["main"]
+
+ if directory == pcoll.my_previews_dir:
+ return pcoll.my_previews
+
+ print("Scanning directory: %s" % directory)
+
+ if directory and os.path.exists(directory):
+ # Scan the directory for png files
+ image_paths = []
+ for fn in os.listdir(directory):
+ if fn.lower().endswith(".png"):
+ image_paths.append(fn)
+
+ for i, name in enumerate(image_paths):
+ # generates a thumbnail preview for a file.
+ filepath = os.path.join(directory, name)
+ thumb = pcoll.load(filepath, filepath, 'IMAGE')
+ enum_items.append((name, name, "", thumb.icon_id, i))
+
+ pcoll.my_previews = enum_items
+ pcoll.my_previews_dir = directory
+ return pcoll.my_previews
+
+
+class PreviewsExamplePanel(bpy.types.Panel):
+ """Creates a Panel in the Object properties window"""
+ bl_label = "Previews Example Panel"
+ bl_idname = "OBJECT_PT_previews"
+ bl_space_type = 'PROPERTIES'
+ bl_region_type = 'WINDOW'
+ bl_context = "object"
+
+ def draw(self, context):
+ layout = self.layout
+ wm = context.window_manager
+
+ row = layout.row()
+ row.prop(wm, "my_previews_dir")
+
+ row = layout.row()
+ row.template_icon_view(wm, "my_previews")
+
+ row = layout.row()
+ row.prop(wm, "my_previews")
+
+
+# We can store multiple preview collections here,
+# however in this example we only store "main"
+preview_collections = {}
+
+
+def register():
+ from bpy.types import WindowManager
+ from bpy.props import (
+ StringProperty,
+ EnumProperty,
+ )
+
+ WindowManager.my_previews_dir = StringProperty(
+ name="Folder Path",
+ subtype='DIR_PATH',
+ default=""
+ )
+
+ WindowManager.my_previews = EnumProperty(
+ items=enum_previews_from_directory_items,
+ )
+
+ # Note that preview collections returned by bpy.utils.previews
+ # are regular Python objects - you can use them to store custom data.
+ #
+ # This is especially useful here, since:
+ # - It avoids us regenerating the whole enum over and over.
+ # - It can store enum_items' strings
+ # (remember you have to keep those strings somewhere in py,
+ # else they get freed and Blender references invalid memory!).
+ import bpy.utils.previews
+ pcoll = bpy.utils.previews.new()
+ pcoll.my_previews_dir = ""
+ pcoll.my_previews = ()
+
+ preview_collections["main"] = pcoll
+
+ bpy.utils.register_class(PreviewsExamplePanel)
+
+
+def unregister():
+ from bpy.types import WindowManager
+
+ del WindowManager.my_previews
+
+ for pcoll in preview_collections.values():
+ bpy.utils.previews.remove(pcoll)
+ preview_collections.clear()
+
+ bpy.utils.unregister_class(PreviewsExamplePanel)
+
+
+if __name__ == "__main__":
+ register()
diff --git a/release/text/readme.html b/release/text/readme.html
index 4d8b0bf24d2..8e08a8ba027 100644
--- a/release/text/readme.html
+++ b/release/text/readme.html
@@ -3,9 +3,7 @@
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta http-equiv="Content-Style-Type" content="text/css">
- <title></title>
- <meta name="Generator" content="Cocoa HTML Writer">
- <meta name="CocoaVersion" content="1265">
+ <title>Blender Readme</title>
<style type="text/css">
p.p1 {margin: 0.0px 156.0px 22.0px 156.0px; text-align: center; font: 22.0px Helvetica}
p.p2 {margin: 0.0px 0.0px 12.0px 0.0px; font: 12.0px Times; min-height: 14.0px}
@@ -20,18 +18,38 @@
</style>
</head>
<body>
-<p class="p1"><b>Blender 2.72</b></p>
+<p class="p1"><b>Blender BLENDER_VERSION</b></p>
<p class="p2"><br></p>
<p class="p3"><b>About</b></p>
-<p class="p4">Welcome to Blender, the free, open source 3D application for modeling, animation, rendering, compositing, video editing and game creation. Blender is available for Linux, Mac OS X and Windows and has a large world-wide community.</p>
-<p class="p4">Blender can be used freely for any purpose, including commercial use and distribution. It's free and open-source software, released under the GNU GPL licence. The entire source code is available on our website.</p>
-<p class="p4">For more information, visit <a href="http://www.blender.org/"><span class="s1">blender.org</span></a>.</p>
+<p class="p4">
+Welcome to Blender, the free, open source 3D application for modeling, animation, rendering,
+compositing, video editing and game creation.
+Blender is available for Linux, Mac OS X and Windows and has a large world-wide community.
+</p>
+<p class="p4">
+Blender can be used freely for any purpose, including commercial use and distribution.
+It's free and open-source software, released under the GNU GPL licence.
+The entire source code is available on our website.
+</p>
+<p class="p4">
+For more information, visit <a href="http://www.blender.org/"><span class="s1">blender.org</span></a>.
+</p>
<p class="p2"><br></p>
-<p class="p3"><b>2.72</b></p>
-<p class="p4">The Blender Foundation and online developer community is proud to present Blender 2.72. This release is the third official stable release of the Blender 2.7 series. <a href="http://wiki.blender.org/index.php/Dev:Ref/Release_Notes/2.72"><span class="s1">More information about this release</span></a>.</p>
+<p class="p3"><b>BLENDER_VERSION</b></p>
+<p class="p4">
+The Blender Foundation and online developer community is proud to present Blender BLENDER_VERSION.
+<a href="http://wiki.blender.org/index.php/Dev:Ref/Release_Notes/BLENDER_VERSION">
+<span class="s1">More information about this release</span></a>.
+</p>
<p class="p2"><br></p>
<p class="p3"><b>Bugs</b></p>
-<p class="p4">Although Blender 2.72 is considered a stable release, you may encounter a bug. If you do, please help us by posting it in the bug tracker or using Help <span class="s2">→</span> Report a Bug from inside Blender. If it wasn’t reported yet, please log in (or register) and fill in detailed information about the error. Please post detailed instructions on how to reproduce it or post a .blend file showcasing the bug.</p>
+<p class="p4">
+Although this is considered a stable release, you may encounter a bug.
+If you do, please help us by posting it in the bug tracker or using Help
+<span class="s2">→</span> Report a Bug from inside Blender.
+If it wasn’t reported yet, please log in (or register) and fill in detailed information about the error.
+Please post detailed instructions on how to reproduce it or post a .blend file showcasing the bug.
+</p>
<p class="p2"><br></p>
<p class="p3"><b>Package Contents</b></p>
<p class="p4">The downloaded Blender package includes:</p>
@@ -40,31 +58,70 @@
<p class="p4">• Readme and copyright files.</p>
<p class="p2"><br></p>
<p class="p3"><b>Installation</b></p>
-<p class="p4"><b>Windows: </b>The download .zip contains a Blender folder. You may put this anywhere on your hard drive. To launch Blender, double-click on Blender.exe.</p>
-<p class="p4"><b>Linux: </b>Unpack the archive, then run the Blender executable.</p>
-<p class="p4"><b>Mac OS X: </b>The downloaded package includes blender.app. Optionally copy this to your Applications folder, and add it to the dock by dragging it from there to the dock.</p>
+<p class="p4">
+<b>Windows: </b>The download .zip contains a Blender folder. You may put this anywhere on your hard drive.
+To launch Blender, double-click on Blender.exe.
+</p>
+<p class="p4">
+<b>Linux: </b>Unpack the archive, then run the Blender executable.
+</p>
+<p class="p4">
+<b>Mac OS X: </b>The downloaded package includes blender.app.
+Optionally copy this to your Applications folder, and add it to the dock by dragging it from there to the dock.
+</p>
<p class="p2"><br></p>
-<p class="p4"><b>Installing Addons (all systems)</b> Addons can be installed from the user preferences addons section, download an addon as a .py or .zip file, then press the "Install Addon" button and select the file to install it.</p>
+<p class="p4">
+<b>Installing Addons (all systems)</b> Addons can be installed from the user preferences addons section,
+download an addon as a .py or .zip file, then press the "Install Addon" button and select the file to install it.
+</p>
<p class="p2"><br></p>
<p class="p3"><b>Getting Started</b></p>
-<p class="p4">When opening Blender, you’ll see large 3D view in the center, a Toolbar on the left, a Properties editor and an Outliner on the right and a Timeline at the bottom.</p>
-<p class="p4">Orbit around in the 3D view by holding the middle mouse button and dragging. Alternatively, hold the alt key and drag the left mouse button. Additionally, hold Shift to pan the view and Ctrl to zoom.</p>
-<p class="p4">Select objects using the right mouse button. With the object selected, perform actions by clicking any of the tool buttons on the left, or make changes to its properties by altering any of the setting on the right.</p>
-<p class="p4">For more information on how to use Blender, <a href="http://www.blender.org/support/"><span class="s1">check out the support page</span></a>.</p>
+<p class="p4">
+When opening Blender, you’ll see large 3D view in the center, a Toolbar on the left,
+a Properties editor and an Outliner on the right and a Timeline at the bottom.
+</p>
+<p class="p4">
+Orbit around in the 3D view by holding the middle mouse button and dragging.
+Alternatively, hold the alt key and drag the left mouse button.
+Additionally, hold Shift to pan the view and Ctrl to zoom.
+</p>
+<p class="p4">
+Select objects using the right mouse button.
+With the object selected, perform actions by clicking any of the tool buttons on the left,
+or make changes to its properties by altering any of the setting on the right.
+</p>
+<p class="p4">
+For more information on how to use Blender,
+<a href="http://www.blender.org/support/"><span class="s1">check out the support page</span></a>.
+</p>
<p class="p2"><br></p>
<p class="p3"><b>Links</b></p>
<p class="p4">Users:</p>
-<p class="p5"><span class="s3">General information <a href="http://www.blender.org/"><span class="s4">www.blender.org</span></a> <br>
-Full release log <a href="http://wiki.blender.org/index.php/Dev:Ref/Release_Notes/2.72"><span class="s4">wiki.blender.org/index.php/Dev:Ref/Release_Notes/2.72</span></a><br>
-Tutorials <a href="http://www.blender.org/support/tutorials/"><span class="s4">www.blender.org/support/tutorials/</span></a> <br>
-Manual <a href="http://wiki.blender.org/index.php/Doc:2.6/Manual"><span class="s4">wiki.blender.org/index.php/Doc:2.6/Manual</span></a><br>
-User Forum <a href="http://www.blenderartists.org/"><span class="s4">www.blenderartists.org</span></a><br>
-IRC <a href="irc://irc.freenode.net/#blenderchat"><span class="s4">#blenderchat</span></a> or <a href="irc://irc.freenode.net/#blender"><span class="s4">#blender</span></a> on irc.freenode.net</span></p>
+<p class="p5">
+<span class="s3">General information <a href="http://www.blender.org/">
+<span class="s4">www.blender.org</span></a> <br>
+Full release log <a href="http://wiki.blender.org/index.php/Dev:Ref/Release_Notes/BLENDER_VERSION">
+<span class="s4">wiki.blender.org/index.php/Dev:Ref/Release_Notes/BLENDER_VERSION</span></a><br>
+Tutorials <a href="http://www.blender.org/support/tutorials/">
+<span class="s4">www.blender.org/support/tutorials/</span></a> <br>
+Manual <a href="http://www.blender.org/manual"><span class="s4">www.blender.org/manual</span></a><br>
+User Forum <a href="http://www.blenderartists.org/">
+<span class="s4">www.blenderartists.org</span></a><br>
+IRC <a href="irc://irc.freenode.net/#blenderchat">
+<span class="s4">#blenderchat</span></a> or <a href="irc://irc.freenode.net/#blender">
+<span class="s4">#blender</span></a> on irc.freenode.net</span>
+</p>
<p class="p4">Developers:</p>
-<p class="p5"><span class="s3">Development <a href="http://www.blender.org/get-involved/developers/"><span class="s4">www.blender.org/get-involved/developers/</span></a><br>
-GIT and Bug Tracker <a href="http://developer.blender.org/"><span class="s4">developer.blender.org/</span></a><br>
-Get Involved <a href="http://www.blender.org/get-involved/"><span class="s4">www.blender.org/get-involved/</span></a><br>
-IRC <a href="irc://irc.freenode.net/#blendercoders"><span class="s4">#blendercoders</span></a> on irc.freenode.net</span></p>
+<p class="p5">
+<span class="s3">Development <a href="http://www.blender.org/get-involved/developers/">
+<span class="s4">www.blender.org/get-involved/developers/</span></a><br>
+GIT and Bug Tracker <a href="http://developer.blender.org/">
+<span class="s4">developer.blender.org/</span></a><br>
+Get Involved <a href="http://www.blender.org/get-involved/">
+<span class="s4">www.blender.org/get-involved/</span></a><br>
+IRC <a href="irc://irc.freenode.net/#blendercoders">
+<span class="s4">#blendercoders</span></a> on irc.freenode.net</span>
+</p>
<p class="p2"><br></p>
<p class="p2"><br></p>
<p class="p6">Blender is open-source and free for all to use.</p>
diff --git a/release/windows/installer/00.sconsblender.nsi b/release/windows/installer/00.sconsblender.nsi
index f6e5b783faa..2d91b9da7f1 100644
--- a/release/windows/installer/00.sconsblender.nsi
+++ b/release/windows/installer/00.sconsblender.nsi
@@ -70,6 +70,13 @@ InstallDir $INSTDIR ; $INSTDIR is set inside .onInit
BrandingText "Blender Foundation | http://www.blender.org"
ComponentText "This will install Blender [VERSION] on your computer."
+VIAddVersionKey "ProductName" "Blender"
+VIAddVersionKey "CompanyName" "http://www.blender.org"
+VIAddVersionKey "FileDescription" "Free open source 3D content creation suite."
+VIAddVersionKey "FileVersion" "[SHORTVERSION].0.0"
+
+VIProductVersion "[SHORTVERSION].0.0"
+
DirText "Use the field below to specify the folder where you want Blender to be copied to. To specify a different folder, type a new name or use the Browse button to select an existing folder."
SilentUnInstall normal
diff --git a/source/blender/CMakeLists.txt b/source/blender/CMakeLists.txt
index 0d309523daf..e36f9e2b43e 100644
--- a/source/blender/CMakeLists.txt
+++ b/source/blender/CMakeLists.txt
@@ -46,6 +46,7 @@ set(SRC_DNA_INC
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_freestyle_types.h
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_genfile.h
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_gpencil_types.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_gpu_types.h
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_group_types.h
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_image_types.h
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_ipo_types.h
@@ -100,8 +101,11 @@ add_subdirectory(blenlib)
add_subdirectory(bmesh)
add_subdirectory(render)
add_subdirectory(blenfont)
+add_subdirectory(blentranslation)
add_subdirectory(blenloader)
+add_subdirectory(depsgraph)
add_subdirectory(ikplugin)
+add_subdirectory(physics)
add_subdirectory(gpu)
add_subdirectory(imbuf)
add_subdirectory(nodes)
diff --git a/source/blender/SConscript b/source/blender/SConscript
index de052f24c33..c6f4994bb4f 100644
--- a/source/blender/SConscript
+++ b/source/blender/SConscript
@@ -33,6 +33,8 @@ SConscript(['avi/SConscript',
'blenkernel/SConscript',
'blenlib/SConscript',
'blenloader/SConscript',
+ 'blentranslation/SConscript',
+ 'depsgraph/SConscript',
'gpu/SConscript',
'editors/SConscript',
'imbuf/SConscript',
@@ -41,6 +43,7 @@ SConscript(['avi/SConscript',
'nodes/SConscript',
'modifiers/SConscript',
'ikplugin/SConscript',
+ 'physics/SConscript',
'windowmanager/SConscript',
'blenfont/SConscript'])
diff --git a/source/blender/avi/AVI_avi.h b/source/blender/avi/AVI_avi.h
index 44ffaad1f48..5e9fe378c38 100644
--- a/source/blender/avi/AVI_avi.h
+++ b/source/blender/avi/AVI_avi.h
@@ -28,18 +28,17 @@
/** \file AVI_avi.h
* \ingroup avi
- * \section aviabout AVI module external interface
*
- * \subsection about About the AVI module
+ * \section avi_about About the AVI module
*
* This is external code. It provides avi file import/export and
* conversions. It has been adapted to make use of Blender memory
* management functions, and because of this it needs module
* blenlib. You need to provide this lib when linking with libavi.a .
*
- * \subsection issues Known issues with AVI
+ * \subsection avi_issues Known issues with AVI
*
- * - avi uses mallocN, freeN from blenlib.
+ * - avi uses #MEM_mallocN, #MEM_freeN from blenlib.
* - Not all functions that are used externally are properly
* prototyped.
*
diff --git a/source/blender/avi/intern/avi.c b/source/blender/avi/intern/avi.c
index a423c874adf..6ea94d3b2f3 100644
--- a/source/blender/avi/intern/avi.c
+++ b/source/blender/avi/intern/avi.c
@@ -676,7 +676,7 @@ AviError AVI_open_movie(const char *name, AviMovie *movie)
* instead of an offset from the movie beginning... this is...
* wacky, but we need to handle it. The wacky offset always
* starts at movi_offset it seems... so we'll check that.
- * Note the the offset needs an extra 4 bytes for some
+ * Note the offset needs an extra 4 bytes for some
* undetermined reason */
if (movie->entries[0].Offset == movie->movi_offset)
diff --git a/source/blender/avi/intern/avi_mjpeg.c b/source/blender/avi/intern/avi_mjpeg.c
index 857501c5796..1fa9da6b3a2 100644
--- a/source/blender/avi/intern/avi_mjpeg.c
+++ b/source/blender/avi/intern/avi_mjpeg.c
@@ -290,17 +290,6 @@ static void deinterlace(int odd, unsigned char *to, unsigned char *from, int wid
}
}
-static int check_and_decode_jpeg(unsigned char *inbuf, unsigned char *outbuf, int width, int height, int bufsize)
-{
- return Decode_JPEG(inbuf, outbuf, width, height, bufsize);
-}
-
-static void check_and_compress_jpeg(int quality, unsigned char *outbuf, const unsigned char *inbuf,
- int width, int height, int bufsize)
-{
- Compress_JPEG(quality, outbuf, inbuf, width, height, bufsize);
-}
-
void *avi_converter_from_mjpeg(AviMovie *movie, int stream, unsigned char *buffer, int *size)
{
int deint;
@@ -310,7 +299,7 @@ void *avi_converter_from_mjpeg(AviMovie *movie, int stream, unsigned char *buffe
buf = MEM_mallocN(movie->header->Height * movie->header->Width * 3, "avi.avi_converter_from_mjpeg 1");
- deint = check_and_decode_jpeg(buffer, buf, movie->header->Width, movie->header->Height, *size);
+ deint = Decode_JPEG(buffer, buf, movie->header->Width, movie->header->Height, *size);
MEM_freeN(buffer);
@@ -335,11 +324,11 @@ void *avi_converter_to_mjpeg(AviMovie *movie, int stream, unsigned char *buffer,
buf = MEM_mallocN(movie->header->Height * movie->header->Width * 3, "avi.avi_converter_to_mjpeg 1");
if (!movie->interlace) {
- check_and_compress_jpeg(movie->streams[stream].sh.Quality / 100,
- buf, buffer,
- movie->header->Width,
- movie->header->Height,
- bufsize);
+ Compress_JPEG(movie->streams[stream].sh.Quality / 100,
+ buf, buffer,
+ movie->header->Width,
+ movie->header->Height,
+ bufsize);
}
else {
deinterlace(movie->odd_fields, buf, buffer, movie->header->Width, movie->header->Height);
@@ -348,18 +337,18 @@ void *avi_converter_to_mjpeg(AviMovie *movie, int stream, unsigned char *buffer,
buffer = buf;
buf = MEM_mallocN(movie->header->Height * movie->header->Width * 3, "avi.avi_converter_to_mjpeg 2");
- check_and_compress_jpeg(movie->streams[stream].sh.Quality / 100,
- buf, buffer,
- movie->header->Width,
- movie->header->Height / 2,
- bufsize / 2);
+ Compress_JPEG(movie->streams[stream].sh.Quality / 100,
+ buf, buffer,
+ movie->header->Width,
+ movie->header->Height / 2,
+ bufsize / 2);
*size += numbytes;
numbytes = 0;
- check_and_compress_jpeg(movie->streams[stream].sh.Quality / 100,
- buf + *size, buffer + (movie->header->Height / 2) * movie->header->Width * 3,
- movie->header->Width,
- movie->header->Height / 2,
- bufsize / 2);
+ Compress_JPEG(movie->streams[stream].sh.Quality / 100,
+ buf + *size, buffer + (movie->header->Height / 2) * movie->header->Width * 3,
+ movie->header->Width,
+ movie->header->Height / 2,
+ bufsize / 2);
}
*size += numbytes;
diff --git a/source/blender/avi/intern/avi_rgb.c b/source/blender/avi/intern/avi_rgb.c
index c6a78eccce2..632ecad61a6 100644
--- a/source/blender/avi/intern/avi_rgb.c
+++ b/source/blender/avi/intern/avi_rgb.c
@@ -123,13 +123,12 @@ void *avi_converter_to_avi_rgb(AviMovie *movie, int stream, unsigned char *buffe
(void)stream; /* unused */
- *size = movie->header->Height * movie->header->Width * 3;
- if (movie->header->Width % 2) *size += movie->header->Height;
-
- buf = MEM_mallocN(*size, "toavirgbbuf");
-
rowstride = movie->header->Width * 3;
- if (movie->header->Width % 2) rowstride++;
+ /* AVI files has uncompressed lines 4-byte aligned */
+ rowstride = (rowstride + 3) & ~3;
+
+ *size = movie->header->Height * rowstride;
+ buf = MEM_mallocN(*size, "toavirgbbuf");
for (y = 0; y < movie->header->Height; y++) {
memcpy(&buf[y * rowstride], &buffer[((movie->header->Height - 1) - y) * movie->header->Width * 3], movie->header->Width * 3);
diff --git a/source/blender/avi/intern/avi_rgb32.c b/source/blender/avi/intern/avi_rgb32.c
index 5c7a4889d97..c9cbcb05bb8 100644
--- a/source/blender/avi/intern/avi_rgb32.c
+++ b/source/blender/avi/intern/avi_rgb32.c
@@ -74,8 +74,8 @@ void *avi_converter_to_rgb32(AviMovie *movie, int stream, unsigned char *buffer,
(void)stream; /* unused */
- buf = MEM_mallocN(movie->header->Height * movie->header->Width * 4, "torgb32buf");
*size = movie->header->Height * movie->header->Width * 4;
+ buf = MEM_mallocN(*size, "torgb32buf");
memset(buf, 255, *size);
diff --git a/source/blender/blenfont/BLF_api.h b/source/blender/blenfont/BLF_api.h
index 206345582b2..9527c4edcf0 100644
--- a/source/blender/blenfont/BLF_api.h
+++ b/source/blender/blenfont/BLF_api.h
@@ -36,6 +36,7 @@
struct rctf;
struct ColorManagedDisplay;
+struct ResultBLF;
int BLF_init(int points, int dpi);
void BLF_exit(void);
@@ -79,9 +80,11 @@ void BLF_draw_default(float x, float y, float z, const char *str, size_t len) AT
void BLF_draw_default_ascii(float x, float y, float z, const char *str, size_t len) ATTR_NONNULL();
/* Draw the string using the current font. */
-void BLF_draw(int fontid, const char *str, size_t len);
-void BLF_draw_ascii(int fontid, const char *str, size_t len);
-int BLF_draw_mono(int fontid, const char *str, size_t len, int cwidth);
+void BLF_draw_ex(int fontid, const char *str, size_t len, struct ResultBLF *r_info) ATTR_NONNULL(2);
+void BLF_draw(int fontid, const char *str, size_t len) ATTR_NONNULL(2);
+void BLF_draw_ascii_ex(int fontid, const char *str, size_t len, struct ResultBLF *r_info) ATTR_NONNULL(2);
+void BLF_draw_ascii(int fontid, const char *str, size_t len) ATTR_NONNULL(2);
+int BLF_draw_mono(int fontid, const char *str, size_t len, int cwidth) ATTR_NONNULL(2);
/* Get the string byte offset that fits within a given width */
size_t BLF_width_to_strlen(int fontid, const char *str, size_t len, float width, float *r_width) ATTR_NONNULL(2);
@@ -91,17 +94,20 @@ size_t BLF_width_to_rstrlen(int fontid, const char *str, size_t len, float width
/* This function return the bounding box of the string
* and are not multiplied by the aspect.
*/
+void BLF_boundbox_ex(int fontid, const char *str, size_t len, struct rctf *box, struct ResultBLF *r_info) ATTR_NONNULL(2);
void BLF_boundbox(int fontid, const char *str, size_t len, struct rctf *box) ATTR_NONNULL();
/* 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_ex(int fontid, const char *str, size_t len, struct ResultBLF *r_info) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(2);
float BLF_width(int fontid, const char *str, size_t len) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+float BLF_height_ex(int fontid, const char *str, size_t len, struct ResultBLF *r_info) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(2);
float BLF_height(int fontid, const char *str, size_t len) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
/* Return dimensions of the font without any sample text. */
-float BLF_height_max(int fontid) ATTR_WARN_UNUSED_RESULT;
+int BLF_height_max(int fontid) ATTR_WARN_UNUSED_RESULT;
float BLF_width_max(int fontid) ATTR_WARN_UNUSED_RESULT;
float BLF_descender(int fontid) ATTR_WARN_UNUSED_RESULT;
float BLF_ascender(int fontid) ATTR_WARN_UNUSED_RESULT;
@@ -137,6 +143,7 @@ void BLF_disable_default(int option);
void BLF_rotation(int fontid, float angle);
void BLF_clipping(int fontid, float xmin, float ymin, float xmax, float ymax);
void BLF_clipping_default(float xmin, float ymin, float xmax, float ymax);
+void BLF_wordwrap(int fontid, int wrap_width);
void BLF_blur(int fontid, int size);
void BLF_enable(int fontid, int option);
@@ -172,7 +179,8 @@ void BLF_buffer_col(int fontid, float r, float g, float b, float a);
/* Draw the string into the buffer, this function draw in both buffer, float and unsigned char _BUT_
* it's not necessary set both buffer, NULL is valid here.
*/
-void BLF_draw_buffer(int fontid, const char *str) ATTR_NONNULL();
+void BLF_draw_buffer_ex(int fontid, const char *str, size_t len, struct ResultBLF *r_info) ATTR_NONNULL(2);
+void BLF_draw_buffer(int fontid, const char *str, size_t len) ATTR_NONNULL(2);
/* Add a path to the font dir paths. */
void BLF_dir_add(const char *path) ATTR_NONNULL();
@@ -186,6 +194,18 @@ char **BLF_dir_get(int *ndir) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
/* Free the data return by BLF_dir_get. */
void BLF_dir_free(char **dirs, int count) ATTR_NONNULL();
+/* blf_thumbs.c */
+void BLF_thumb_preview(
+ const char *filename, const char **draw_str, const unsigned char draw_str_lines,
+ const float font_color[4], const int font_size,
+ unsigned char *buf, int w, int h, int channels) ATTR_NONNULL();
+
+/* blf_font_i18.c */
+unsigned char *BLF_get_unifont(int *unifont_size);
+void BLF_free_unifont(void);
+unsigned char *BLF_get_unifont_mono(int *unifont_size);
+void BLF_free_unifont_mono(void);
+
#ifdef DEBUG
void BLF_state_print(int fontid);
#endif
@@ -198,6 +218,7 @@ void BLF_state_print(int fontid);
#define BLF_MATRIX (1 << 4)
#define BLF_ASPECT (1 << 5)
#define BLF_HINTING (1 << 6)
+#define BLF_WORD_WRAP (1 << 7)
#define BLF_DRAW_STR_DUMMY_MAX 1024
@@ -205,4 +226,18 @@ void BLF_state_print(int fontid);
extern int blf_mono_font;
extern int blf_mono_font_render; /* don't mess drawing with render threads. */
+/**
+ * Result of drawing/evaluating the string
+ */
+struct ResultBLF {
+ /**
+ * Number of lines drawn when #BLF_WORD_WRAP is enabled (both wrapped and `\n` newline).
+ */
+ int lines;
+ /**
+ * The 'cursor' position on completion (ignoring character boundbox).
+ */
+ int width;
+};
+
#endif /* __BLF_API_H__ */
diff --git a/source/blender/blenfont/BLF_translation.h b/source/blender/blenfont/BLF_translation.h
deleted file mode 100644
index c11996799ff..00000000000
--- a/source/blender/blenfont/BLF_translation.h
+++ /dev/null
@@ -1,235 +0,0 @@
-/*
- * ***** BEGIN GPL LICENSE BLOCK *****
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * The Original Code is Copyright (C) 2011 Blender Foundation.
- * All rights reserved.
- *
- *
- * Contributor(s): Blender Foundation,
- * Sergey Sharybin
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-
-/** \file blender/blenfont/BLF_translation.h
- * \ingroup blf
- */
-
-
-#ifndef __BLF_TRANSLATION_H__
-#define __BLF_TRANSLATION_H__
-
-#include "BLI_utildefines.h" /* for bool type */
-
-#define TEXT_DOMAIN_NAME "blender"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* blf_lang.c */
-
-/* Search the path directory to the locale files, this try all
- * the case for Linux, Win and Mac.
- * Also dynamically builds locales and locales' menu from "languages" text file.
- */
-void BLF_lang_init(void);
-
-/* Free languages and locales_menu arrays created by BLF_lang_init. */
-void BLF_lang_free(void);
-
-/* Set the current locale. */
-void BLF_lang_set(const char *);
-/* Get the current locale ([partial] ISO code, e.g. es_ES). */
-const char *BLF_lang_get(void);
-
-/* Get locale's elements (if relevant pointer is not NULL and element actually exists, e.g. if there is no variant,
- * *variant and *language_variant will always be NULL).
- * Non-null elements are always MEM_mallocN'ed, it's the caller's responsibility to free them.
- * NOTE: Always available, even in non-WITH_INTERNATIONAL builds.
- */
-void BLF_locale_explode(const char *locale, char **language, char **country, char **variant,
- char **language_country, char **language_variant);
-
-/* Get EnumPropertyItem's for translations menu. */
-struct EnumPropertyItem *BLF_RNA_lang_enum_properties(void);
-
-/* blf_translation.c */
-
-unsigned char *BLF_get_unifont(int *unifont_size);
-void BLF_free_unifont(void);
-unsigned char *BLF_get_unifont_mono(int *unifont_size);
-void BLF_free_unifont_mono(void);
-
-bool BLF_is_default_context(const char *msgctxt);
-const char *BLF_pgettext(const char *msgctxt, const char *msgid);
-
-/* translation */
-bool BLF_translate_iface(void);
-bool BLF_translate_tooltips(void);
-bool BLF_translate_new_dataname(void);
-const char *BLF_translate_do_iface(const char *msgctxt, const char *msgid);
-const char *BLF_translate_do_tooltip(const char *msgctxt, const char *msgid);
-const char *BLF_translate_do_new_dataname(const char *msgctxt, const char *msgid);
-
-
-/* The "translation-marker" macro. */
-#define N_(msgid) msgid
-#define CTX_N_(context, msgid) msgid
-
-/* Those macros should be used everywhere in UI code. */
-#ifdef WITH_INTERNATIONAL
-/*# define _(msgid) BLF_gettext(msgid) */
-# define IFACE_(msgid) BLF_translate_do_iface(NULL, msgid)
-# define TIP_(msgid) BLF_translate_do_tooltip(NULL, msgid)
-# define DATA_(msgid) BLF_translate_do_new_dataname(NULL, msgid)
-# define CTX_IFACE_(context, msgid) BLF_translate_do_iface(context, msgid)
-# define CTX_TIP_(context, msgid) BLF_translate_do_tooltip(context, msgid)
-# define CTX_DATA_(context, msgid) BLF_translate_do_new_dataname(context, msgid)
-#else
-/*# define _(msgid) msgid */
-# define IFACE_(msgid) msgid
-# define TIP_(msgid) msgid
-# define DATA_(msgid) msgid
-# define CTX_IFACE_(context, msgid) msgid
-# define CTX_TIP_(context, msgid) msgid
-# define CTX_DATA_(context, msgid) msgid
-#endif
-
-/* Helper macro, when we want to define a same msgid for multiple msgctxt...
- * Does nothing in C, but is "parsed" by our i18n py tools.
- * XXX Currently limited to at most 16 contexts at once
- * (but you can call it several times with the same msgid, should you need more contexts!).
- */
-#define BLF_I18N_MSGID_MULTI_CTXT(msgid, ...)
-
-/******************************************************************************
- * All i18n contexts must be defined here.
- * This is a nice way to be sure not to use a context twice for different
- * things, and limit the number of existing contexts!
- * WARNING! Contexts should not be longer than BKE_ST_MAXNAME - 1!
- */
-
-/* Default, void context.
- * WARNING! The "" context is not the same as no (NULL) context at mo/boost::locale level!
- * NOTE: We translate BLF_I18NCONTEXT_DEFAULT as BLF_I18NCONTEXT_DEFAULT_BPY in Python, as we can't use "natural"
- * None value in rna string properties... :/
- * The void string "" is also interpreted as BLF_I18NCONTEXT_DEFAULT.
- * For perf reason, we only use the first char to detect this context, so other contexts should never start
- * with the same char!
- */
-#define BLF_I18NCONTEXT_DEFAULT NULL
-#define BLF_I18NCONTEXT_DEFAULT_BPYRNA "*"
-
-/* Default context for operator names/labels. */
-#define BLF_I18NCONTEXT_OPERATOR_DEFAULT "Operator"
-
-/* Mark the msgid applies to several elements (needed in some cases, as english adjectives have no plural mark. :( */
-#define BLF_I18NCONTEXT_PLURAL "Plural"
-
-/* ID-types contexts. */
-/* WARNING! Keep it in sync with idtypes in blenkernel/intern/idcode.c */
-#define BLF_I18NCONTEXT_ID_ACTION "Action"
-#define BLF_I18NCONTEXT_ID_ARMATURE "Armature"
-#define BLF_I18NCONTEXT_ID_BRUSH "Brush"
-#define BLF_I18NCONTEXT_ID_CAMERA "Camera"
-#define BLF_I18NCONTEXT_ID_CURVE "Curve"
-#define BLF_I18NCONTEXT_ID_FREESTYLELINESTYLE "FreestyleLineStyle"
-#define BLF_I18NCONTEXT_ID_GPENCIL "GPencil"
-#define BLF_I18NCONTEXT_ID_GROUP "Group"
-#define BLF_I18NCONTEXT_ID_ID "ID"
-#define BLF_I18NCONTEXT_ID_IMAGE "Image"
-/*#define BLF_I18NCONTEXT_ID_IPO "Ipo"*/ /* Deprecated */
-#define BLF_I18NCONTEXT_ID_SHAPEKEY "Key"
-#define BLF_I18NCONTEXT_ID_LAMP "Lamp"
-#define BLF_I18NCONTEXT_ID_LIBRARY "Library"
-#define BLF_I18NCONTEXT_ID_LATTICE "Lattice"
-#define BLF_I18NCONTEXT_ID_MATERIAL "Material"
-#define BLF_I18NCONTEXT_ID_METABALL "Metaball"
-#define BLF_I18NCONTEXT_ID_MESH "Mesh"
-#define BLF_I18NCONTEXT_ID_NODETREE "NodeTree"
-#define BLF_I18NCONTEXT_ID_OBJECT "Object"
-#define BLF_I18NCONTEXT_ID_PARTICLESETTINGS "ParticleSettings"
-#define BLF_I18NCONTEXT_ID_SCENE "Scene"
-#define BLF_I18NCONTEXT_ID_SCREEN "Screen"
-#define BLF_I18NCONTEXT_ID_SEQUENCE "Sequence"
-#define BLF_I18NCONTEXT_ID_SPEAKER "Speaker"
-#define BLF_I18NCONTEXT_ID_SOUND "Sound"
-#define BLF_I18NCONTEXT_ID_TEXTURE "Texture"
-#define BLF_I18NCONTEXT_ID_TEXT "Text"
-#define BLF_I18NCONTEXT_ID_VFONT "VFont"
-#define BLF_I18NCONTEXT_ID_WORLD "World"
-#define BLF_I18NCONTEXT_ID_WINDOWMANAGER "WindowManager"
-#define BLF_I18NCONTEXT_ID_MOVIECLIP "MovieClip"
-#define BLF_I18NCONTEXT_ID_MASK "Mask"
-
-/* Helper for bpy.app.i18n object... */
-typedef struct
-{
- const char *c_id;
- const char *py_id;
- const char *value;
-} BLF_i18n_contexts_descriptor;
-
-#define BLF_I18NCONTEXTS_ITEM(ctxt_id, py_id) {#ctxt_id, py_id, ctxt_id}
-
-#define BLF_I18NCONTEXTS_DESC { \
- BLF_I18NCONTEXTS_ITEM(BLF_I18NCONTEXT_DEFAULT, "default_real"), \
- BLF_I18NCONTEXTS_ITEM(BLF_I18NCONTEXT_DEFAULT_BPYRNA, "default"), \
- BLF_I18NCONTEXTS_ITEM(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "operator_default"), \
- BLF_I18NCONTEXTS_ITEM(BLF_I18NCONTEXT_PLURAL, "plural"), \
- BLF_I18NCONTEXTS_ITEM(BLF_I18NCONTEXT_ID_ACTION, "id_action"), \
- BLF_I18NCONTEXTS_ITEM(BLF_I18NCONTEXT_ID_ARMATURE, "id_armature"), \
- BLF_I18NCONTEXTS_ITEM(BLF_I18NCONTEXT_ID_BRUSH, "id_brush"), \
- BLF_I18NCONTEXTS_ITEM(BLF_I18NCONTEXT_ID_CAMERA, "id_camera"), \
- BLF_I18NCONTEXTS_ITEM(BLF_I18NCONTEXT_ID_CURVE, "id_curve"), \
- BLF_I18NCONTEXTS_ITEM(BLF_I18NCONTEXT_ID_FREESTYLELINESTYLE, "id_fs_linestyle"), \
- BLF_I18NCONTEXTS_ITEM(BLF_I18NCONTEXT_ID_GPENCIL, "id_gpencil"), \
- BLF_I18NCONTEXTS_ITEM(BLF_I18NCONTEXT_ID_GROUP, "id_group"), \
- BLF_I18NCONTEXTS_ITEM(BLF_I18NCONTEXT_ID_ID, "id_id"), \
- BLF_I18NCONTEXTS_ITEM(BLF_I18NCONTEXT_ID_IMAGE, "id_image"), \
- /*BLF_I18NCONTEXTS_ITEM(BLF_I18NCONTEXT_ID_IPO, "id_ipo"),*/ \
- BLF_I18NCONTEXTS_ITEM(BLF_I18NCONTEXT_ID_SHAPEKEY, "id_shapekey"), \
- BLF_I18NCONTEXTS_ITEM(BLF_I18NCONTEXT_ID_LAMP, "id_lamp"), \
- BLF_I18NCONTEXTS_ITEM(BLF_I18NCONTEXT_ID_LIBRARY, "id_library"), \
- BLF_I18NCONTEXTS_ITEM(BLF_I18NCONTEXT_ID_LATTICE, "id_lattice"), \
- BLF_I18NCONTEXTS_ITEM(BLF_I18NCONTEXT_ID_MATERIAL, "id_material"), \
- BLF_I18NCONTEXTS_ITEM(BLF_I18NCONTEXT_ID_METABALL, "id_metaball"), \
- BLF_I18NCONTEXTS_ITEM(BLF_I18NCONTEXT_ID_MESH, "id_mesh"), \
- BLF_I18NCONTEXTS_ITEM(BLF_I18NCONTEXT_ID_NODETREE, "id_nodetree"), \
- BLF_I18NCONTEXTS_ITEM(BLF_I18NCONTEXT_ID_OBJECT, "id_object"), \
- BLF_I18NCONTEXTS_ITEM(BLF_I18NCONTEXT_ID_PARTICLESETTINGS, "id_particlesettings"), \
- BLF_I18NCONTEXTS_ITEM(BLF_I18NCONTEXT_ID_SCENE, "id_scene"), \
- BLF_I18NCONTEXTS_ITEM(BLF_I18NCONTEXT_ID_SCREEN, "id_screen"), \
- BLF_I18NCONTEXTS_ITEM(BLF_I18NCONTEXT_ID_SEQUENCE, "id_sequence"), \
- BLF_I18NCONTEXTS_ITEM(BLF_I18NCONTEXT_ID_SPEAKER, "id_speaker"), \
- BLF_I18NCONTEXTS_ITEM(BLF_I18NCONTEXT_ID_SOUND, "id_sound"), \
- BLF_I18NCONTEXTS_ITEM(BLF_I18NCONTEXT_ID_TEXTURE, "id_texture"), \
- BLF_I18NCONTEXTS_ITEM(BLF_I18NCONTEXT_ID_TEXT, "id_text"), \
- BLF_I18NCONTEXTS_ITEM(BLF_I18NCONTEXT_ID_VFONT, "id_vfont"), \
- BLF_I18NCONTEXTS_ITEM(BLF_I18NCONTEXT_ID_WORLD, "id_world"), \
- BLF_I18NCONTEXTS_ITEM(BLF_I18NCONTEXT_ID_WINDOWMANAGER, "id_windowmanager"), \
- BLF_I18NCONTEXTS_ITEM(BLF_I18NCONTEXT_ID_MOVIECLIP, "id_movieclip"), \
- BLF_I18NCONTEXTS_ITEM(BLF_I18NCONTEXT_ID_MASK, "id_mask"), \
- {NULL, NULL, NULL} \
-}
-
-#ifdef __cplusplus
-};
-#endif
-
-#endif /* __BLF_TRANSLATION_H__ */
diff --git a/source/blender/blenfont/CMakeLists.txt b/source/blender/blenfont/CMakeLists.txt
index 2debe516dd7..36ad6fe03cf 100644
--- a/source/blender/blenfont/CMakeLists.txt
+++ b/source/blender/blenfont/CMakeLists.txt
@@ -25,13 +25,14 @@ set(INC
.
../blenkernel
../blenlib
+ ../blentranslation
../editors/include
+ ../gpu
../makesdna
../makesrna
- ../python
../imbuf
../../../intern/guardedalloc
- ../../../intern/locale
+ ../../../intern/glew-mx
)
set(INC_SYS
@@ -43,22 +44,33 @@ set(SRC
intern/blf.c
intern/blf_dir.c
intern/blf_font.c
+ intern/blf_font_i18n.c
intern/blf_glyph.c
- intern/blf_lang.c
- intern/blf_translation.c
+ intern/blf_thumbs.c
intern/blf_util.c
BLF_api.h
- BLF_translation.h
intern/blf_internal.h
intern/blf_internal_types.h
)
+if(WIN32)
+ list(APPEND SRC
+ intern/blf_font_win32_compat.c
+ )
+endif()
+
if(WITH_INTERNATIONAL)
add_definitions(-DWITH_INTERNATIONAL)
endif()
-add_definitions(-DGLEW_STATIC)
+if(WITH_PYTHON)
+ add_definitions(-DWITH_PYTHON)
+ list(APPEND INC
+ ../python
+ )
+endif()
-blender_add_lib(bf_blenfont "${SRC}" "${INC}" "${INC_SYS}")
+add_definitions(${GL_DEFINITIONS})
+blender_add_lib(bf_blenfont "${SRC}" "${INC}" "${INC_SYS}")
diff --git a/source/blender/blenfont/SConscript b/source/blender/blenfont/SConscript
index 1c573fa4a59..6c3b5748011 100644
--- a/source/blender/blenfont/SConscript
+++ b/source/blender/blenfont/SConscript
@@ -34,20 +34,22 @@ incs = [
'.',
'intern',
'#/intern/guardedalloc',
- '#/intern/locale',
- '#/extern/glew/include',
+ env['BF_GLEW_INC'],
+ '#/intern/glew-mx',
'../blenkernel',
'../blenlib',
+ '../blentranslation',
'../editors/include',
+ '../gpu',
'../imbuf',
'../makesdna',
'../makesrna',
- '../python',
]
incs.extend(Split(env['BF_FREETYPE_INC']))
-defs = ['GLEW_STATIC']
+defs = []
+defs += env['BF_GL_DEFINITIONS']
if sys.platform == 'win32' or env['OURPLATFORM'] == 'linuxcross':
defs.append('_WIN32')
@@ -55,6 +57,10 @@ if sys.platform == 'win32' or env['OURPLATFORM'] == 'linuxcross':
if env['WITH_BF_INTERNATIONAL']:
defs.append('WITH_INTERNATIONAL')
+if env['WITH_BF_PYTHON']:
+ defs.append('WITH_PYTHON')
+ incs.append('../python')
+
if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'linuxcross', 'win64-vc', 'win64-mingw'):
incs.append(env['BF_PTHREADS_INC'])
diff --git a/source/blender/blenfont/intern/blf.c b/source/blender/blenfont/intern/blf.c
index cdccbe044bb..a97187657b8 100644
--- a/source/blender/blenfont/intern/blf.c
+++ b/source/blender/blenfont/intern/blf.c
@@ -53,6 +53,8 @@
#include "BIF_gl.h"
#include "BLF_api.h"
+#include "IMB_colormanagement.h"
+
#include "blf_internal_types.h"
#include "blf_internal.h"
@@ -63,6 +65,14 @@
*/
#define BLF_MAX_FONT 16
+/* call BLF_default_set first! */
+#define ASSERT_DEFAULT_SET BLI_assert(global_font_default != -1)
+
+#define BLF_RESULT_CHECK_INIT(r_info) \
+if (r_info) { \
+ memset(r_info, 0, sizeof(*(r_info))); \
+} ((void)0)
+
/* Font array. */
static FontBLF *global_font[BLF_MAX_FONT] = {NULL};
@@ -134,7 +144,7 @@ static int blf_search(const char *name)
for (i = 0; i < BLF_MAX_FONT; i++) {
font = global_font[i];
- if (font && (!strcmp(font->name, name)))
+ if (font && (STREQ(font->name, name)))
return i;
}
@@ -160,21 +170,6 @@ void BLF_default_set(int fontid)
}
}
-static int blf_global_font_init(void)
-{
- if (global_font_default == -1) {
- global_font_default = blf_search("default");
- }
-
- if (global_font_default == -1) {
- printf("Warning: Can't find default font!\n");
- return 0;
- }
- else {
- return 1;
- }
-}
-
int BLF_load(const char *name)
{
FontBLF *font;
@@ -336,7 +331,7 @@ void BLF_unload(const char *name)
for (i = 0; i < BLF_MAX_FONT; i++) {
font = global_font[i];
- if (font && (!strcmp(font->name, name))) {
+ if (font && (STREQ(font->name, name))) {
blf_font_free(font);
global_font[i] = NULL;
}
@@ -477,8 +472,7 @@ void BLF_blur(int fontid, int size)
void BLF_draw_default(float x, float y, float z, const char *str, size_t len)
{
- if (!blf_global_font_init())
- return;
+ ASSERT_DEFAULT_SET;
BLF_size(global_font_default, global_font_points, global_font_dpi);
BLF_position(global_font_default, x, y, z);
@@ -488,8 +482,7 @@ void BLF_draw_default(float x, float y, float z, const char *str, size_t len)
/* same as above but call 'BLF_draw_ascii' */
void BLF_draw_default_ascii(float x, float y, float z, const char *str, size_t len)
{
- if (!blf_global_font_init())
- return;
+ ASSERT_DEFAULT_SET;
BLF_size(global_font_default, global_font_points, global_font_dpi);
BLF_position(global_font_default, x, y, z);
@@ -505,7 +498,7 @@ void BLF_rotation_default(float angle)
}
}
-static void blf_draw__start(FontBLF *font, GLint *mode, GLint *param)
+static void blf_draw_gl__start(FontBLF *font, GLint *mode, GLint *param)
{
/*
* The pixmap alignment hack is handle
@@ -529,7 +522,7 @@ static void blf_draw__start(FontBLF *font, GLint *mode, GLint *param)
if (font->flags & BLF_MATRIX)
glMultMatrixd((GLdouble *)&font->m);
- glTranslatef(font->pos[0], font->pos[1], font->pos[2]);
+ glTranslate3fv(font->pos);
if (font->flags & BLF_ASPECT)
glScalef(font->aspect[0], font->aspect[1], font->aspect[2]);
@@ -549,7 +542,7 @@ static void blf_draw__start(FontBLF *font, GLint *mode, GLint *param)
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
}
-static void blf_draw__end(GLint mode, GLint param)
+static void blf_draw_gl__end(GLint mode, GLint param)
{
/* and restore the original value. */
if (param != GL_MODULATE)
@@ -568,29 +561,56 @@ static void blf_draw__end(GLint mode, GLint param)
glDisable(GL_TEXTURE_2D);
}
-void BLF_draw(int fontid, const char *str, size_t len)
+void BLF_draw_ex(
+ int fontid, const char *str, size_t len,
+ struct ResultBLF *r_info)
{
FontBLF *font = blf_get(fontid);
GLint mode, param;
+ BLF_RESULT_CHECK_INIT(r_info);
+
if (font && font->glyph_cache) {
- blf_draw__start(font, &mode, &param);
- blf_font_draw(font, str, len);
- blf_draw__end(mode, param);
+ blf_draw_gl__start(font, &mode, &param);
+ if (font->flags & BLF_WORD_WRAP) {
+ blf_font_draw__wrap(font, str, len, r_info);
+ }
+ else {
+ blf_font_draw(font, str, len, r_info);
+ }
+ blf_draw_gl__end(mode, param);
}
}
+void BLF_draw(int fontid, const char *str, size_t len)
+{
+ BLF_draw_ex(fontid, str, len, NULL);
+}
-void BLF_draw_ascii(int fontid, const char *str, size_t len)
+void BLF_draw_ascii_ex(
+ int fontid, const char *str, size_t len,
+ struct ResultBLF *r_info)
{
FontBLF *font = blf_get(fontid);
GLint mode, param;
+ BLF_RESULT_CHECK_INIT(r_info);
+
if (font && font->glyph_cache) {
- blf_draw__start(font, &mode, &param);
- blf_font_draw_ascii(font, str, len);
- blf_draw__end(mode, param);
+ blf_draw_gl__start(font, &mode, &param);
+ if (font->flags & BLF_WORD_WRAP) {
+ /* use non-ascii draw function for word-wrap */
+ blf_font_draw__wrap(font, str, len, r_info);
+ }
+ else {
+ blf_font_draw_ascii(font, str, len, r_info);
+ }
+ blf_draw_gl__end(mode, param);
}
}
+void BLF_draw_ascii(int fontid, const char *str, size_t len)
+{
+ BLF_draw_ascii_ex(fontid, str, len, NULL);
+}
int BLF_draw_mono(int fontid, const char *str, size_t len, int cwidth)
{
@@ -599,9 +619,9 @@ int BLF_draw_mono(int fontid, const char *str, size_t len, int cwidth)
int columns = 0;
if (font && font->glyph_cache) {
- blf_draw__start(font, &mode, &param);
+ blf_draw_gl__start(font, &mode, &param);
columns = blf_font_draw_mono(font, str, len, cwidth);
- blf_draw__end(mode, param);
+ blf_draw_gl__end(mode, param);
}
return columns;
@@ -647,21 +667,34 @@ size_t BLF_width_to_rstrlen(int fontid, const char *str, size_t len, float width
return 0;
}
-void BLF_boundbox(int fontid, const char *str, size_t len, rctf *box)
+void BLF_boundbox_ex(
+ int fontid, const char *str, size_t len, rctf *r_box,
+ struct ResultBLF *r_info)
{
FontBLF *font = blf_get(fontid);
+ BLF_RESULT_CHECK_INIT(r_info);
+
if (font) {
- blf_font_boundbox(font, str, len, box);
+ if (font->flags & BLF_WORD_WRAP) {
+ blf_font_boundbox__wrap(font, str, len, r_box, r_info);
+ }
+ else {
+ blf_font_boundbox(font, str, len, r_box, r_info);
+ }
}
}
+void BLF_boundbox(int fontid, const char *str, size_t len, rctf *r_box)
+{
+ BLF_boundbox_ex(fontid, str, len, r_box, NULL);
+}
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, len, r_width, r_height);
+ blf_font_width_and_height(font, str, len, r_width, r_height, NULL);
}
else {
*r_width = *r_height = 0.0f;
@@ -670,25 +703,30 @@ void BLF_width_and_height(int fontid, const char *str, size_t len, float *r_widt
void BLF_width_and_height_default(const char *str, size_t len, float *r_width, float *r_height)
{
- if (!blf_global_font_init()) {
- *r_width = *r_height = 0.0f;
- return;
- }
+ ASSERT_DEFAULT_SET;
BLF_size(global_font_default, global_font_points, global_font_dpi);
BLF_width_and_height(global_font_default, str, len, r_width, r_height);
}
-float BLF_width(int fontid, const char *str, size_t len)
+float BLF_width_ex(
+ int fontid, const char *str, size_t len,
+ struct ResultBLF *r_info)
{
FontBLF *font = blf_get(fontid);
+ BLF_RESULT_CHECK_INIT(r_info);
+
if (font && font->glyph_cache) {
- return blf_font_width(font, str, len);
+ return blf_font_width(font, str, len, r_info);
}
return 0.0f;
}
+float BLF_width(int fontid, const char *str, size_t len)
+{
+ return BLF_width_ex(fontid, str, len, NULL);
+}
float BLF_fixed_width(int fontid)
{
@@ -703,25 +741,32 @@ float BLF_fixed_width(int fontid)
float BLF_width_default(const char *str, size_t len)
{
- if (!blf_global_font_init())
- return 0.0f;
+ ASSERT_DEFAULT_SET;
BLF_size(global_font_default, global_font_points, global_font_dpi);
return BLF_width(global_font_default, str, len);
}
-float BLF_height(int fontid, const char *str, size_t len)
+float BLF_height_ex(
+ int fontid, const char *str, size_t len,
+ struct ResultBLF *r_info)
{
FontBLF *font = blf_get(fontid);
+ BLF_RESULT_CHECK_INIT(r_info);
+
if (font && font->glyph_cache) {
- return blf_font_height(font, str, len);
+ return blf_font_height(font, str, len, r_info);
}
return 0.0f;
}
+float BLF_height(int fontid, const char *str, size_t len)
+{
+ return BLF_height_ex(fontid, str, len, NULL);
+}
-float BLF_height_max(int fontid)
+int BLF_height_max(int fontid)
{
FontBLF *font = blf_get(fontid);
@@ -729,7 +774,7 @@ float BLF_height_max(int fontid)
return font->glyph_cache->max_glyph_height;
}
- return 0.0f;
+ return 0;
}
float BLF_width_max(int fontid)
@@ -767,8 +812,7 @@ float BLF_ascender(int fontid)
float BLF_height_default(const char *str, size_t len)
{
- if (!blf_global_font_init())
- return 0.0f;
+ ASSERT_DEFAULT_SET;
BLF_size(global_font_default, global_font_points, global_font_dpi);
@@ -808,6 +852,15 @@ void BLF_clipping_default(float xmin, float ymin, float xmax, float ymax)
}
}
+void BLF_wordwrap(int fontid, int wrap_width)
+{
+ FontBLF *font = blf_get(fontid);
+
+ if (font) {
+ font->wrap_width = wrap_width;
+ }
+}
+
void BLF_shadow(int fontid, int level, float r, float g, float b, float a)
{
FontBLF *font = blf_get(fontid);
@@ -850,21 +903,52 @@ void BLF_buffer_col(int fontid, float r, float g, float b, float a)
FontBLF *font = blf_get(fontid);
if (font) {
- font->buf_info.col[0] = r;
- font->buf_info.col[1] = g;
- font->buf_info.col[2] = b;
- font->buf_info.col[3] = a;
+ ARRAY_SET_ITEMS(font->buf_info.col_init, r, g, b, a);
}
}
-void BLF_draw_buffer(int fontid, const char *str)
+
+static void blf_draw_buffer__start(FontBLF *font)
+{
+ FontBufInfoBLF *buf_info = &font->buf_info;
+
+ buf_info->col_char[0] = buf_info->col_init[0] * 255;
+ buf_info->col_char[1] = buf_info->col_init[1] * 255;
+ buf_info->col_char[2] = buf_info->col_init[2] * 255;
+ buf_info->col_char[3] = buf_info->col_init[3] * 255;
+
+ if (buf_info->display) {
+ copy_v4_v4(buf_info->col_float, buf_info->col_init);
+ IMB_colormanagement_display_to_scene_linear_v3(buf_info->col_float, buf_info->display);
+ }
+ else {
+ srgb_to_linearrgb_v4(buf_info->col_float, buf_info->col_init);
+ }
+}
+static void blf_draw_buffer__end(void) {}
+
+void BLF_draw_buffer_ex(
+ int fontid, const char *str, size_t len,
+ struct ResultBLF *r_info)
{
FontBLF *font = blf_get(fontid);
if (font && font->glyph_cache && (font->buf_info.fbuf || font->buf_info.cbuf)) {
- blf_font_buffer(font, str);
+ blf_draw_buffer__start(font);
+ if (font->flags & BLF_WORD_WRAP) {
+ blf_font_draw_buffer__wrap(font, str, len, r_info);
+ }
+ else {
+ blf_font_draw_buffer(font, str, len, r_info);
+ }
+ blf_draw_buffer__end();
}
}
+void BLF_draw_buffer(
+ int fontid, const char *str, size_t len)
+{
+ BLF_draw_buffer_ex(fontid, str, len, NULL);
+}
#ifdef DEBUG
void BLF_state_print(int fontid)
diff --git a/source/blender/blenfont/intern/blf_dir.c b/source/blender/blenfont/intern/blf_dir.c
index 4a36ae03bed..f493aa9af74 100644
--- a/source/blender/blenfont/intern/blf_dir.c
+++ b/source/blender/blenfont/intern/blf_dir.c
@@ -103,7 +103,7 @@ char **BLF_dir_get(int *ndir)
char *path;
int i, count;
- count = BLI_countlist(&global_font_dir);
+ count = BLI_listbase_count(&global_font_dir);
if (!count)
return NULL;
diff --git a/source/blender/blenfont/intern/blf_font.c b/source/blender/blenfont/intern/blf_font.c
index 4891c332c87..3f3ca78b6cd 100644
--- a/source/blender/blenfont/intern/blf_font.c
+++ b/source/blender/blenfont/intern/blf_font.c
@@ -58,13 +58,15 @@
#include "BIF_gl.h"
#include "BLF_api.h"
-#include "IMB_colormanagement.h"
-
#include "blf_internal_types.h"
#include "blf_internal.h"
#include "BLI_strict_flags.h"
+#ifdef WIN32
+# define FT_New_Face FT_New_Face__win32_compat
+#endif
+
/* freetype2 handle ONLY for this file!. */
static FT_Library ft_lib;
static SpinLock ft_lib_mutex;
@@ -149,7 +151,7 @@ static void blf_font_ensure_ascii_table(FontBLF *font)
#define BLF_KERNING_VARS(_font, _has_kerning, _kern_mode) \
- const bool _has_kerning = FT_HAS_KERNING((_font)->face); \
+ const bool _has_kerning = FT_HAS_KERNING((_font)->face) != 0; \
const FT_UInt _kern_mode = (_has_kerning == 0) ? 0 : \
(((_font)->flags & BLF_KERNING_DEFAULT) ? \
ft_kerning_default : (FT_UInt)FT_KERNING_UNFITTED) \
@@ -170,12 +172,14 @@ static void blf_font_ensure_ascii_table(FontBLF *font)
} \
} (void)0
-void blf_font_draw(FontBLF *font, const char *str, size_t len)
+static void blf_font_draw_ex(
+ FontBLF *font, const char *str, size_t len, struct ResultBLF *r_info,
+ int pen_y)
{
unsigned int c;
GlyphBLF *g, *g_prev = NULL;
FT_Vector delta;
- int pen_x = 0, pen_y = 0;
+ int pen_x = 0;
size_t i = 0;
GlyphBLF **glyph_ascii_table = font->glyph_cache->glyph_ascii_table;
@@ -199,15 +203,26 @@ void blf_font_draw(FontBLF *font, const char *str, size_t len)
pen_x += g->advance_i;
g_prev = g;
}
+
+ if (r_info) {
+ r_info->lines = 1;
+ r_info->width = pen_x;
+ }
+}
+void blf_font_draw(FontBLF *font, const char *str, size_t len, struct ResultBLF *r_info)
+{
+ blf_font_draw_ex(font, str, len, r_info, 0);
}
/* faster version of blf_font_draw, ascii only for view dimensions */
-void blf_font_draw_ascii(FontBLF *font, const char *str, size_t len)
+static void blf_font_draw_ascii_ex(
+ FontBLF *font, const char *str, size_t len, struct ResultBLF *r_info,
+ int pen_y)
{
unsigned char c;
GlyphBLF *g, *g_prev = NULL;
FT_Vector delta;
- int pen_x = 0, pen_y = 0;
+ int pen_x = 0;
GlyphBLF **glyph_ascii_table = font->glyph_cache->glyph_ascii_table;
BLF_KERNING_VARS(font, has_kerning, kern_mode);
@@ -227,6 +242,15 @@ void blf_font_draw_ascii(FontBLF *font, const char *str, size_t len)
pen_x += g->advance_i;
g_prev = g;
}
+
+ if (r_info) {
+ r_info->lines = 1;
+ r_info->width = pen_x;
+ }
+}
+void blf_font_draw_ascii(FontBLF *font, const char *str, size_t len, struct ResultBLF *r_info)
+{
+ blf_font_draw_ascii_ex(font, str, len, r_info, 0);
}
/* use fixed column width, but an utf8 character may occupy multiple columns */
@@ -264,43 +288,33 @@ int blf_font_draw_mono(FontBLF *font, const char *str, size_t len, int cwidth)
}
/* Sanity checks are done by BLF_draw_buffer() */
-void blf_font_buffer(FontBLF *font, const char *str)
+static void blf_font_draw_buffer_ex(
+ FontBLF *font, const char *str, size_t len, struct ResultBLF *r_info,
+ int pen_y)
{
unsigned int c;
GlyphBLF *g, *g_prev = NULL;
FT_Vector delta;
- int pen_x = (int)font->pos[0], pen_y = 0;
+ int pen_x = (int)font->pos[0];
+ int pen_y_basis = (int)font->pos[1] + pen_y;
size_t i = 0;
GlyphBLF **glyph_ascii_table = font->glyph_cache->glyph_ascii_table;
/* buffer specific vars */
FontBufInfoBLF *buf_info = &font->buf_info;
- float b_col_float[4];
- const unsigned char b_col_char[4] = {
- (unsigned char)(buf_info->col[0] * 255),
- (unsigned char)(buf_info->col[1] * 255),
- (unsigned char)(buf_info->col[2] * 255),
- (unsigned char)(buf_info->col[3] * 255)};
-
- unsigned char *cbuf;
+ const float *b_col_float = buf_info->col_float;
+ const unsigned char *b_col_char = buf_info->col_char;
int chx, chy;
int y, x;
- float a, *fbuf;
+ float a;
BLF_KERNING_VARS(font, has_kerning, kern_mode);
blf_font_ensure_ascii_table(font);
/* another buffer specific call for color conversion */
- if (buf_info->display) {
- copy_v4_v4(b_col_float, buf_info->col);
- IMB_colormanagement_display_to_scene_linear_v3(b_col_float, buf_info->display);
- }
- else {
- srgb_to_linearrgb_v4(b_col_float, buf_info->col);
- }
- while (str[i]) {
+ while ((i < len) && str[i]) {
BLF_UTF8_NEXT_FAST(font, g, str, i, c, glyph_ascii_table);
if (UNLIKELY(c == BLI_UTF8_ERR))
@@ -311,13 +325,13 @@ void blf_font_buffer(FontBLF *font, const char *str)
BLF_KERNING_STEP(font, kern_mode, g_prev, g, delta, pen_x);
chx = pen_x + ((int)g->pos_x);
- chy = (int)font->pos[1] + g->height;
+ chy = pen_y_basis + g->height;
if (g->pitch < 0) {
- pen_y = (int)font->pos[1] + (g->height - (int)g->pos_y);
+ pen_y = pen_y_basis + (g->height - (int)g->pos_y);
}
else {
- pen_y = (int)font->pos[1] - (g->height - (int)g->pos_y);
+ pen_y = pen_y_basis - (g->height - (int)g->pos_y);
}
if ((chx + g->width) >= 0 && chx < buf_info->w && (pen_y + g->height) >= 0 && pen_y < buf_info->h) {
@@ -345,8 +359,12 @@ void blf_font_buffer(FontBLF *font, const char *str)
a = *(g->bitmap + x + (yb * g->pitch)) / 255.0f;
if (a > 0.0f) {
+ const size_t buf_ofs = (
+ ((size_t)(chx + x) + ((size_t)(pen_y + y) * (size_t)buf_info->w)) *
+ (size_t)buf_info->ch);
+ float *fbuf = buf_info->fbuf + buf_ofs;
float alphatest;
- fbuf = buf_info->fbuf + buf_info->ch * ((chx + x) + ((pen_y + y) * buf_info->w));
+
if (a >= 1.0f) {
fbuf[0] = b_col_float[0];
fbuf[1] = b_col_float[1];
@@ -371,13 +389,17 @@ void blf_font_buffer(FontBLF *font, const char *str)
if (buf_info->cbuf) {
int yb = yb_start;
- for (y = 0; y < height_clip; y++) {
- for (x = 0; x < width_clip; x++) {
+ for (y = ((chy >= 0) ? 0 : -chy); y < height_clip; y++) {
+ for (x = ((chx >= 0) ? 0 : -chx); x < width_clip; x++) {
a = *(g->bitmap + x + (yb * g->pitch)) / 255.0f;
if (a > 0.0f) {
+ const size_t buf_ofs = (
+ ((size_t)(chx + x) + ((size_t)(pen_y + y) * (size_t)buf_info->w)) *
+ (size_t)buf_info->ch);
+ unsigned char *cbuf = buf_info->cbuf + buf_ofs;
int alphatest;
- cbuf = buf_info->cbuf + buf_info->ch * ((chx + x) + ((pen_y + y) * buf_info->w));
+
if (a >= 1.0f) {
cbuf[0] = b_col_char[0];
cbuf[1] = b_col_char[1];
@@ -418,6 +440,16 @@ void blf_font_buffer(FontBLF *font, const char *str)
pen_x += g->advance_i;
g_prev = g;
}
+
+ if (r_info) {
+ r_info->lines = 1;
+ r_info->width = pen_x;
+ }
+}
+void blf_font_draw_buffer(
+ FontBLF *font, const char *str, size_t len, struct ResultBLF *r_info)
+{
+ blf_font_draw_buffer_ex(font, str, len, r_info, 0);
}
size_t blf_font_width_to_strlen(FontBLF *font, const char *str, size_t len, float width, float *r_width)
@@ -547,12 +579,14 @@ size_t blf_font_width_to_rstrlen(FontBLF *font, const char *str, size_t len, flo
return i_prev;
}
-void blf_font_boundbox(FontBLF *font, const char *str, size_t len, rctf *box)
+static void blf_font_boundbox_ex(
+ FontBLF *font, const char *str, size_t len, rctf *box, struct ResultBLF *r_info,
+ int pen_y)
{
unsigned int c;
GlyphBLF *g, *g_prev = NULL;
FT_Vector delta;
- int pen_x = 0, pen_y = 0;
+ int pen_x = 0;
size_t i = 0;
GlyphBLF **glyph_ascii_table = font->glyph_cache->glyph_ascii_table;
@@ -598,9 +632,168 @@ void blf_font_boundbox(FontBLF *font, const char *str, size_t len, rctf *box)
box->xmax = 0.0f;
box->ymax = 0.0f;
}
+
+ if (r_info) {
+ r_info->lines = 1;
+ r_info->width = pen_x;
+ }
}
+void blf_font_boundbox(FontBLF *font, const char *str, size_t len, rctf *r_box, struct ResultBLF *r_info)
+{
+ blf_font_boundbox_ex(font, str, len, r_box, r_info, 0);
+}
+
+
+/* -------------------------------------------------------------------- */
+/** \name Word-Wrap Support
+ * \{ */
-void blf_font_width_and_height(FontBLF *font, const char *str, size_t len, float *width, float *height)
+
+/**
+ * Generic function to add word-wrap support for other existing functions.
+ *
+ * Wraps on spaces and respects newlines.
+ * Intentionally ignores non-unix newlines, tabs and more advanced text formatting.
+ *
+ * \note If we want rich text - we better have a higher level API to handle that
+ * (color, bold, switching fonts... etc).
+ */
+static void blf_font_wrap_apply(
+ FontBLF *font, const char *str, size_t len, struct ResultBLF *r_info,
+ void (*callback)(FontBLF *font, const char *str, size_t len, int pen_y, void *userdata),
+ void *userdata)
+{
+ unsigned int c;
+ GlyphBLF *g, *g_prev = NULL;
+ FT_Vector delta;
+ int pen_x = 0, pen_y = 0;
+ size_t i = 0;
+ GlyphBLF **glyph_ascii_table = font->glyph_cache->glyph_ascii_table;
+ int lines = 0;
+ int pen_x_next = 0;
+
+ BLF_KERNING_VARS(font, has_kerning, kern_mode);
+
+ struct WordWrapVars {
+ int wrap_width;
+ size_t start, last[2];
+ } wrap = {font->wrap_width != -1 ? font->wrap_width : INT_MAX, 0, {0, 0}};
+
+ blf_font_ensure_ascii_table(font);
+ // printf("%s wrapping (%d, %d) `%s`:\n", __func__, len, strlen(str), str);
+ while ((i < len) && str[i]) {
+
+ /* wrap vars */
+ size_t i_curr = i;
+ bool do_draw = false;
+
+ BLF_UTF8_NEXT_FAST(font, g, str, i, c, glyph_ascii_table);
+
+ if (UNLIKELY(c == BLI_UTF8_ERR))
+ break;
+ if (UNLIKELY(g == NULL))
+ continue;
+ if (has_kerning)
+ BLF_KERNING_STEP(font, kern_mode, g_prev, g, delta, pen_x);
+
+ /**
+ * Implementation Detail (utf8).
+ *
+ * Take care with single byte offsets here,
+ * since this is utf8 we can't be sure a single byte is a single character.
+ *
+ * This is _only_ done when we know for sure the character is ascii (newline or a space).
+ */
+ pen_x_next = pen_x + g->advance_i;
+ if (UNLIKELY((pen_x_next >= wrap.wrap_width) && (wrap.start != wrap.last[0]))) {
+ do_draw = true;
+ }
+ else if (UNLIKELY(((i < len) && str[i]) == 0)) {
+ /* need check here for trailing newline, else we draw it */
+ wrap.last[0] = i + ((g->c != '\n') ? 1 : 0);
+ wrap.last[1] = i;
+ do_draw = true;
+ }
+ else if (UNLIKELY(g->c == '\n')) {
+ wrap.last[0] = i_curr + 1;
+ wrap.last[1] = i;
+ do_draw = true;
+ }
+ else if (UNLIKELY(g->c != ' ' && (g_prev ? g_prev->c == ' ' : false))) {
+ wrap.last[0] = i_curr;
+ wrap.last[1] = i;
+ }
+
+ if (UNLIKELY(do_draw)) {
+ // printf("(%d..%d) `%.*s`\n", wrap.start, wrap.last[0], (wrap.last[0] - wrap.start) - 1, &str[wrap.start]);
+ callback(font, &str[wrap.start], (wrap.last[0] - wrap.start) - 1, pen_y, userdata);
+ wrap.start = wrap.last[0];
+ i = wrap.last[1];
+ pen_x = 0;
+ pen_y -= font->glyph_cache->max_glyph_height;
+ g_prev = NULL;
+ lines += 1;
+ continue;
+ }
+
+ pen_x = pen_x_next;
+ g_prev = g;
+ }
+
+ // printf("done! %d lines\n", lines);
+
+ if (r_info) {
+ r_info->lines = lines;
+ /* width of last line only (with wrapped lines) */
+ r_info->width = pen_x_next;
+ }
+}
+
+/* blf_font_draw__wrap */
+static void blf_font_draw__wrap_cb(FontBLF *font, const char *str, size_t len, int pen_y, void *UNUSED(userdata))
+{
+ blf_font_draw_ex(font, str, len, NULL, pen_y);
+}
+void blf_font_draw__wrap(FontBLF *font, const char *str, size_t len, struct ResultBLF *r_info)
+{
+ blf_font_wrap_apply(font, str, len, r_info, blf_font_draw__wrap_cb, NULL);
+}
+
+/* blf_font_boundbox__wrap */
+static void blf_font_boundbox_wrap_cb(FontBLF *font, const char *str, size_t len, int pen_y, void *userdata)
+{
+ rctf *box = userdata;
+ rctf box_single;
+
+ blf_font_boundbox_ex(font, str, len, &box_single, NULL, pen_y);
+ BLI_rctf_union(box, &box_single);
+}
+void blf_font_boundbox__wrap(FontBLF *font, const char *str, size_t len, rctf *box, struct ResultBLF *r_info)
+{
+ box->xmin = 32000.0f;
+ box->xmax = -32000.0f;
+ box->ymin = 32000.0f;
+ box->ymax = -32000.0f;
+
+ blf_font_wrap_apply(font, str, len, r_info, blf_font_boundbox_wrap_cb, box);
+}
+
+/* blf_font_draw_buffer__wrap */
+static void blf_font_draw_buffer__wrap_cb(FontBLF *font, const char *str, size_t len, int pen_y, void *UNUSED(userdata))
+{
+ blf_font_draw_buffer_ex(font, str, len, NULL, pen_y);
+}
+void blf_font_draw_buffer__wrap(FontBLF *font, const char *str, size_t len, struct ResultBLF *r_info)
+{
+ blf_font_wrap_apply(font, str, len, r_info, blf_font_draw_buffer__wrap_cb, NULL);
+}
+
+/** \} */
+
+
+void blf_font_width_and_height(
+ FontBLF *font, const char *str, size_t len,
+ float *r_width, float *r_height, struct ResultBLF *r_info)
{
float xa, ya;
rctf box;
@@ -614,12 +807,17 @@ void blf_font_width_and_height(FontBLF *font, const char *str, size_t len, float
ya = 1.0f;
}
- blf_font_boundbox(font, str, len, &box);
- *width = (BLI_rctf_size_x(&box) * xa);
- *height = (BLI_rctf_size_y(&box) * ya);
+ if (font->flags & BLF_WORD_WRAP) {
+ blf_font_boundbox__wrap(font, str, len, &box, r_info);
+ }
+ else {
+ blf_font_boundbox(font, str, len, &box, r_info);
+ }
+ *r_width = (BLI_rctf_size_x(&box) * xa);
+ *r_height = (BLI_rctf_size_y(&box) * ya);
}
-float blf_font_width(FontBLF *font, const char *str, size_t len)
+float blf_font_width(FontBLF *font, const char *str, size_t len, struct ResultBLF *r_info)
{
float xa;
rctf box;
@@ -629,11 +827,16 @@ float blf_font_width(FontBLF *font, const char *str, size_t len)
else
xa = 1.0f;
- blf_font_boundbox(font, str, len, &box);
+ if (font->flags & BLF_WORD_WRAP) {
+ blf_font_boundbox__wrap(font, str, len, &box, r_info);
+ }
+ else {
+ blf_font_boundbox(font, str, len, &box, r_info);
+ }
return BLI_rctf_size_x(&box) * xa;
}
-float blf_font_height(FontBLF *font, const char *str, size_t len)
+float blf_font_height(FontBLF *font, const char *str, size_t len, struct ResultBLF *r_info)
{
float ya;
rctf box;
@@ -643,7 +846,12 @@ float blf_font_height(FontBLF *font, const char *str, size_t len)
else
ya = 1.0f;
- blf_font_boundbox(font, str, len, &box);
+ if (font->flags & BLF_WORD_WRAP) {
+ blf_font_boundbox__wrap(font, str, len, &box, r_info);
+ }
+ else {
+ blf_font_boundbox(font, str, len, &box, r_info);
+ }
return BLI_rctf_size_y(&box) * ya;
}
@@ -663,6 +871,28 @@ float blf_font_fixed_width(FontBLF *font)
return g->advance;
}
+int blf_font_count_missing_chars(FontBLF *font, const char *str, const size_t len, int *r_tot_chars)
+{
+ int missing = 0;
+ size_t i = 0;
+
+ *r_tot_chars = 0;
+ while (i < len) {
+ unsigned int c;
+
+ if ((c = str[i]) < 0x80) {
+ i++;
+ }
+ else if ((c = BLI_str_utf8_as_unicode_step(str, &i)) != BLI_UTF8_ERR) {
+ if (FT_Get_Char_Index((font)->face, c) == 0) {
+ missing++;
+ }
+ }
+ (*r_tot_chars)++;
+ }
+ return missing;
+}
+
void blf_font_free(FontBLF *font)
{
GlyphCacheBLF *gc;
@@ -711,10 +941,10 @@ static void blf_font_fill(FontBLF *font)
font->buf_info.w = 0;
font->buf_info.h = 0;
font->buf_info.ch = 0;
- font->buf_info.col[0] = 0;
- font->buf_info.col[1] = 0;
- font->buf_info.col[2] = 0;
- font->buf_info.col[3] = 0;
+ font->buf_info.col_init[0] = 0;
+ font->buf_info.col_init[1] = 0;
+ font->buf_info.col_init[2] = 0;
+ font->buf_info.col_init[3] = 0;
font->ft_lib = ft_lib;
font->ft_lib_mutex = &ft_lib_mutex;
diff --git a/source/blender/blenfont/intern/blf_font_i18n.c b/source/blender/blenfont/intern/blf_font_i18n.c
new file mode 100644
index 00000000000..b6ff7ed865a
--- /dev/null
+++ b/source/blender/blenfont/intern/blf_font_i18n.c
@@ -0,0 +1,124 @@
+/*
+ * ***** 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) 2011 Blender Foundation.
+ * All rights reserved.
+ *
+ * Contributor(s): Blender Foundation,
+ * Sergey Sharybin
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/blenfont/intern/blf_font_i18n.c
+ * \ingroup blf
+ *
+ * API for accessing font files.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "BLF_api.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_fileops.h"
+#include "BLI_path_util.h"
+#include "BLI_string.h"
+#include "BLI_utildefines.h"
+
+#include "BKE_appdir.h"
+
+#ifdef WITH_INTERNATIONAL
+static const char unifont_filename[] = "droidsans.ttf.gz";
+static unsigned char *unifont_ttf = NULL;
+static int unifont_size = 0;
+static const char unifont_mono_filename[] = "bmonofont-i18n.ttf.gz";
+static unsigned char *unifont_mono_ttf = NULL;
+static int unifont_mono_size = 0;
+#endif /* WITH_INTERNATIONAL */
+
+unsigned char *BLF_get_unifont(int *r_unifont_size)
+{
+#ifdef WITH_INTERNATIONAL
+ if (unifont_ttf == NULL) {
+ const char * const fontpath = BKE_appdir_folder_id(BLENDER_DATAFILES, "fonts");
+ if (fontpath) {
+ char unifont_path[1024];
+
+ BLI_snprintf(unifont_path, sizeof(unifont_path), "%s/%s", fontpath, unifont_filename);
+
+ unifont_ttf = (unsigned char *)BLI_file_ungzip_to_mem(unifont_path, &unifont_size);
+ }
+ else {
+ printf("%s: 'fonts' data path not found for international font, continuing\n", __func__);
+ }
+ }
+
+ *r_unifont_size = unifont_size;
+
+ return unifont_ttf;
+#else
+ (void)r_unifont_size;
+ return NULL;
+#endif
+}
+
+void BLF_free_unifont(void)
+{
+#ifdef WITH_INTERNATIONAL
+ if (unifont_ttf)
+ MEM_freeN(unifont_ttf);
+#else
+#endif
+}
+
+unsigned char *BLF_get_unifont_mono(int *r_unifont_size)
+{
+#ifdef WITH_INTERNATIONAL
+ if (unifont_mono_ttf == NULL) {
+ const char *fontpath = BKE_appdir_folder_id(BLENDER_DATAFILES, "fonts");
+ if (fontpath) {
+ char unifont_path[1024];
+
+ BLI_snprintf(unifont_path, sizeof(unifont_path), "%s/%s", fontpath, unifont_mono_filename);
+
+ unifont_mono_ttf = (unsigned char *)BLI_file_ungzip_to_mem(unifont_path, &unifont_mono_size);
+ }
+ else {
+ printf("%s: 'fonts' data path not found for international monospace font, continuing\n", __func__);
+ }
+ }
+
+ *r_unifont_size = unifont_mono_size;
+
+ return unifont_mono_ttf;
+#else
+ (void)r_unifont_size;
+ return NULL;
+#endif
+}
+
+void BLF_free_unifont_mono(void)
+{
+#ifdef WITH_INTERNATIONAL
+ if (unifont_mono_ttf)
+ MEM_freeN(unifont_mono_ttf);
+#else
+#endif
+}
diff --git a/source/blender/blenfont/intern/blf_font_win32_compat.c b/source/blender/blenfont/intern/blf_font_win32_compat.c
new file mode 100644
index 00000000000..dd4a443e69f
--- /dev/null
+++ b/source/blender/blenfont/intern/blf_font_win32_compat.c
@@ -0,0 +1,145 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/blenfont/intern/blf_font_win32_compat.c
+ * \ingroup blf
+ *
+ * Workaround for win32 which needs to use BLI_fopen to access files.
+ *
+ * defines #FT_New_Face__win32_compat, a drop-in replacement for \a #FT_New_Face.
+ */
+
+#ifdef WIN32
+
+#include <stdio.h>
+
+#include <ft2build.h>
+#include FT_FREETYPE_H
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_utildefines.h"
+#include "BLI_fileops.h"
+
+#include "blf_internal.h"
+
+/* internal freetype defines */
+#define STREAM_FILE(stream) ((FILE *)stream->descriptor.pointer)
+#define FT_THROW(e) -1
+
+static void ft_ansi_stream_close(
+ FT_Stream stream)
+{
+ fclose(STREAM_FILE(stream));
+
+ stream->descriptor.pointer = NULL;
+ stream->size = 0;
+ stream->base = 0;
+
+ /* WARNING: this works but be careful!
+ * Checked freetype sources, there isn't any access after closing. */
+ MEM_freeN(stream);
+}
+
+static unsigned long ft_ansi_stream_io(
+ FT_Stream stream,
+ unsigned long offset,
+ unsigned char *buffer,
+ unsigned long count)
+{
+ FILE *file;
+ if (!count && offset > stream->size)
+ return 1;
+
+ file = STREAM_FILE(stream);
+
+ if (stream->pos != offset)
+ fseek(file, offset, SEEK_SET);
+
+ return fread(buffer, 1, count, file);
+}
+
+static FT_Error FT_Stream_Open__win32_compat(FT_Stream stream, const char *filepathname)
+{
+ FILE *file;
+ BLI_assert(stream);
+
+ stream->descriptor.pointer = NULL;
+ stream->pathname.pointer = (char *)filepathname;
+ stream->base = 0;
+ stream->pos = 0;
+ stream->read = NULL;
+ stream->close = NULL;
+
+ file = BLI_fopen(filepathname, "rb");
+ if (!file) {
+ fprintf(stderr,
+ "FT_Stream_Open: "
+ "could not open `%s'\n", filepathname);
+ return FT_THROW(Cannot_Open_Resource);
+ }
+
+ fseek(file, 0, SEEK_END);
+ stream->size = ftell(file);
+ if (!stream->size) {
+ fprintf(stderr,
+ "FT_Stream_Open: "
+ "opened `%s' but zero-sized\n", filepathname);
+ fclose(file);
+ return FT_THROW(Cannot_Open_Stream);
+ }
+
+ fseek(file, 0, SEEK_SET);
+
+ stream->descriptor.pointer = file;
+ stream->read = ft_ansi_stream_io;
+ stream->close = ft_ansi_stream_close;
+
+ return FT_Err_Ok;
+}
+
+FT_Error FT_New_Face__win32_compat(
+ FT_Library library,
+ const char *pathname,
+ FT_Long face_index,
+ FT_Face *aface)
+{
+ FT_Error err;
+ FT_Open_Args open;
+ FT_Stream stream = NULL;
+ stream = MEM_callocN(sizeof(*stream), __func__);
+
+ open.flags = FT_OPEN_STREAM;
+ open.stream = stream;
+ stream->pathname.pointer = (char *)pathname;
+
+ err = FT_Stream_Open__win32_compat(stream, pathname);
+ if (err) {
+ MEM_freeN(stream);
+ return err;
+ }
+
+ err = FT_Open_Face(library, &open, face_index, aface);
+ /* no need to free 'stream', its handled by FT_Open_Face if an error occurs */
+
+ return err;
+}
+
+#endif /* WIN32 */
diff --git a/source/blender/blenfont/intern/blf_glyph.c b/source/blender/blenfont/intern/blf_glyph.c
index a2462f3e302..215d2484c18 100644
--- a/source/blender/blenfont/intern/blf_glyph.c
+++ b/source/blender/blenfont/intern/blf_glyph.c
@@ -199,7 +199,7 @@ GlyphBLF *blf_glyph_add(FontBLF *font, unsigned int index, unsigned int c)
GlyphBLF *g;
FT_Error err;
FT_Bitmap bitmap, tempbitmap;
- int sharp = (U.text_render & USER_TEXT_DISABLE_AA);
+ const bool is_sharp = (U.text_render & USER_TEXT_DISABLE_AA) != 0;
int flags = FT_LOAD_TARGET_NORMAL | FT_LOAD_NO_HINTING | FT_LOAD_NO_BITMAP;
FT_BBox bbox;
unsigned int key;
@@ -224,7 +224,7 @@ GlyphBLF *blf_glyph_add(FontBLF *font, unsigned int index, unsigned int c)
if (font->flags & BLF_HINTING)
flags &= ~FT_LOAD_NO_HINTING;
- if (sharp)
+ if (is_sharp)
err = FT_Load_Glyph(font->face, (FT_UInt)index, FT_LOAD_TARGET_MONO);
else
err = FT_Load_Glyph(font->face, (FT_UInt)index, flags);
@@ -237,7 +237,7 @@ GlyphBLF *blf_glyph_add(FontBLF *font, unsigned int index, unsigned int c)
/* get the glyph. */
slot = font->face->glyph;
- if (sharp) {
+ if (is_sharp) {
err = FT_Render_Glyph(slot, FT_RENDER_MODE_MONO);
/* Convert result from 1 bit per pixel to 8 bit per pixel */
@@ -262,11 +262,11 @@ GlyphBLF *blf_glyph_add(FontBLF *font, unsigned int index, unsigned int c)
g->xoff = -1;
g->yoff = -1;
bitmap = slot->bitmap;
- g->width = bitmap.width;
- g->height = bitmap.rows;
+ g->width = (int)bitmap.width;
+ g->height = (int)bitmap.rows;
if (g->width && g->height) {
- if (sharp) {
+ if (is_sharp) {
/* Font buffer uses only 0 or 1 values, Blender expects full 0..255 range */
int i;
for (i = 0; i < (g->width * g->height); i++) {
@@ -379,7 +379,7 @@ static void blf_texture3_draw(const float shadow_col[4], float uv[2][2], float x
static void blf_glyph_calc_rect(rctf *rect, GlyphBLF *g, float x, float y)
{
- rect->xmin = (float)floor(x + g->pos_x);
+ rect->xmin = floorf(x + g->pos_x);
rect->xmax = rect->xmin + (float)g->width;
rect->ymin = y + g->pos_y;
rect->ymax = y + g->pos_y - (float)g->height;
diff --git a/source/blender/blenfont/intern/blf_internal.h b/source/blender/blenfont/intern/blf_internal.h
index 8cb2d377449..55bc61e0e43 100644
--- a/source/blender/blenfont/intern/blf_internal.h
+++ b/source/blender/blenfont/intern/blf_internal.h
@@ -31,6 +31,7 @@
#ifndef __BLF_INTERNAL_H__
#define __BLF_INTERNAL_H__
+struct ResultBLF;
struct FontBLF;
struct GlyphBLF;
struct GlyphCacheBLF;
@@ -51,17 +52,23 @@ struct FontBLF *blf_font_new_from_mem(const char *name, const unsigned char *mem
void blf_font_attach_from_mem(struct FontBLF *font, const unsigned char *mem, int mem_size);
void blf_font_size(struct FontBLF *font, unsigned int size, unsigned int dpi);
-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);
+void blf_font_draw(struct FontBLF *font, const char *str, size_t len, struct ResultBLF *r_info);
+void blf_font_draw__wrap(struct FontBLF *font, const char *str, size_t len, struct ResultBLF *r_info);
+void blf_font_draw_ascii(struct FontBLF *font, const char *str, size_t len, struct ResultBLF *r_info);
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_draw_buffer(struct FontBLF *font, const char *str, size_t len, struct ResultBLF *r_info);
+void blf_font_draw_buffer__wrap(struct FontBLF *font, const char *str, size_t len, struct ResultBLF *r_info);
size_t blf_font_width_to_strlen(struct FontBLF *font, const char *str, size_t len, float width, float *r_width);
size_t blf_font_width_to_rstrlen(struct FontBLF *font, const char *str, size_t len, float width, float *r_width);
-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);
+void blf_font_boundbox(struct FontBLF *font, const char *str, size_t len, struct rctf *r_box, struct ResultBLF *r_info);
+void blf_font_boundbox__wrap(struct FontBLF *font, const char *str, size_t len, struct rctf *r_box, struct ResultBLF *r_info);
+void blf_font_width_and_height(struct FontBLF *font, const char *str, size_t len, float *r_width, float *r_height, struct ResultBLF *r_info);
+float blf_font_width(struct FontBLF *font, const char *str, size_t len, struct ResultBLF *r_info);
+float blf_font_height(struct FontBLF *font, const char *str, size_t len, struct ResultBLF *r_info);
float blf_font_fixed_width(struct FontBLF *font);
+
+int blf_font_count_missing_chars(struct FontBLF *font, const char *str, const size_t len, int *r_tot_chars);
+
void blf_font_free(struct FontBLF *font);
struct GlyphCacheBLF *blf_glyph_cache_find(struct FontBLF *font, unsigned int size, unsigned int dpi);
@@ -75,4 +82,11 @@ struct GlyphBLF *blf_glyph_add(struct FontBLF *font, unsigned int index, unsigne
void blf_glyph_free(struct GlyphBLF *g);
void blf_glyph_render(struct FontBLF *font, struct GlyphBLF *g, float x, float y);
+#ifdef WIN32
+/* blf_font_win32_compat.c */
+# ifdef FT_FREETYPE_H
+extern FT_Error FT_New_Face__win32_compat(FT_Library library, const char *pathname, FT_Long face_index, FT_Face *aface);
+# endif
+#endif
+
#endif /* __BLF_INTERNAL_H__ */
diff --git a/source/blender/blenfont/intern/blf_internal_types.h b/source/blender/blenfont/intern/blf_internal_types.h
index da756d65483..f17401a9991 100644
--- a/source/blender/blenfont/intern/blf_internal_types.h
+++ b/source/blender/blenfont/intern/blf_internal_types.h
@@ -48,7 +48,7 @@ typedef struct GlyphCacheBLF {
struct GlyphBLF *glyph_ascii_table[256];
/* texture array, to draw the glyphs. */
- GLuint *textures;
+ unsigned int *textures;
/* size of the array. */
unsigned int ntex;
@@ -103,7 +103,7 @@ typedef struct GlyphBLF {
int advance_i;
/* texture id where this glyph is store. */
- GLuint tex;
+ unsigned int tex;
/* position inside the texture where this glyph is store. */
int xoff;
@@ -152,7 +152,11 @@ typedef struct FontBufInfoBLF {
/* and the color, the alphas is get from the glyph!
* color is srgb space */
- float col[4];
+ float col_init[4];
+ /* cached conversion from 'col_init' */
+ unsigned char col_char[4];
+ float col_float[4];
+
} FontBufInfoBLF;
typedef struct FontBLF {
@@ -195,6 +199,9 @@ typedef struct FontBLF {
/* clipping rectangle. */
rctf clip_rec;
+ /* the width to wrap the text, see BLF_WORD_WRAP */
+ int wrap_width;
+
/* font dpi (default 72). */
unsigned int dpi;
diff --git a/source/blender/blenfont/intern/blf_thumbs.c b/source/blender/blenfont/intern/blf_thumbs.c
new file mode 100644
index 00000000000..76479593b54
--- /dev/null
+++ b/source/blender/blenfont/intern/blf_thumbs.c
@@ -0,0 +1,121 @@
+/*
+ * ***** 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): Thomas Beck
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/blenfont/intern/blf_thumbs.c
+ * \ingroup blf
+ *
+ * Utility function to generate font preview images.
+ *
+ * Isolate since this needs to be called by #ImBuf code (bad level call).
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <ft2build.h>
+
+#include FT_FREETYPE_H
+
+#include "BLI_utildefines.h"
+#include "BLI_listbase.h"
+#include "BLI_rect.h"
+#include "BLI_threads.h"
+
+#include "blf_internal.h"
+#include "blf_internal_types.h"
+
+#include "BLF_api.h"
+#include "BLT_translation.h"
+
+#include "BLI_strict_flags.h"
+
+/**
+ * This function is used for generating thumbnail previews.
+ *
+ * \note called from a thread, so it bypasses the normal BLF_* api (which isn't thread-safe).
+ */
+void BLF_thumb_preview(
+ const char *filename,
+ const char **draw_str, const unsigned char draw_str_lines,
+ const float font_color[4], const int font_size,
+ unsigned char *buf, int w, int h, int channels)
+{
+ const unsigned int dpi = 72;
+ const int font_size_min = 6;
+ int font_size_curr;
+ /* shrink 1/th each line */
+ int font_shrink = 4;
+
+ FontBLF *font;
+ int i;
+
+ /* Create a new blender font obj and fill it with default values */
+ font = blf_font_new("thumb_font", filename);
+ if (!font) {
+ printf("Info: Can't load font '%s', no preview possible\n", filename);
+ return;
+ }
+
+ /* Would be done via the BLF API, but we're not using a fontid here */
+ font->buf_info.cbuf = buf;
+ font->buf_info.ch = channels;
+ font->buf_info.w = w;
+ font->buf_info.h = h;
+
+ /* Always create the image with a white font,
+ * the caller can theme how it likes */
+ memcpy(font->buf_info.col_init, font_color, sizeof(font->buf_info.col_init));
+ font->pos[1] = (float)h;
+
+ font_size_curr = font_size;
+
+ for (i = 0; i < draw_str_lines; i++) {
+ const char *draw_str_i18n = BLT_translate_do(BLT_I18NCONTEXT_DEFAULT, draw_str[i]);
+ const size_t draw_str_i18n_len = strlen(draw_str_i18n);
+ int draw_str_i18n_nbr = 0;
+
+ blf_font_size(font, (unsigned int)MAX2(font_size_min, font_size_curr), dpi);
+
+ /* decrease font size each time */
+ font_size_curr -= (font_size_curr / font_shrink);
+ font_shrink += 1;
+
+ font->pos[1] -= font->glyph_cache->ascender * 1.1f;
+
+ /* We fallback to default english strings in case not enough chars are available in current font for given
+ * translated string (useful in non-latin i18n context, like chinese, since many fonts will then show
+ * nothing but ugly 'missing char' in their preview).
+ * Does not handle all cases, but much better than nothing.
+ */
+ if (blf_font_count_missing_chars(
+ font, draw_str_i18n, draw_str_i18n_len, &draw_str_i18n_nbr) > (draw_str_i18n_nbr / 2))
+ {
+ blf_font_draw_buffer(font, draw_str[i], (size_t)draw_str_i18n_nbr, NULL);
+ }
+ else {
+ blf_font_draw_buffer(font, draw_str_i18n, draw_str_i18n_len, NULL);
+ }
+ }
+
+ blf_font_free(font);
+}
diff --git a/source/blender/blenfont/intern/blf_util.c b/source/blender/blenfont/intern/blf_util.c
index 06309a944e9..cdd81e33b0a 100644
--- a/source/blender/blenfont/intern/blf_util.c
+++ b/source/blender/blenfont/intern/blf_util.c
@@ -38,7 +38,6 @@
#include "blf_internal.h"
#include "BLI_utildefines.h"
-#include "BLI_string_utf8.h"
unsigned int blf_next_p2(unsigned int x)
{
diff --git a/source/blender/blenkernel/BKE_DerivedMesh.h b/source/blender/blenkernel/BKE_DerivedMesh.h
index 229d2fc17cd..2c6e37b9ed8 100644
--- a/source/blender/blenkernel/BKE_DerivedMesh.h
+++ b/source/blender/blenkernel/BKE_DerivedMesh.h
@@ -88,6 +88,7 @@ struct MTFace;
struct Object;
struct Scene;
struct Mesh;
+struct MLoopNorSpaceArray;
struct BMEditMesh;
struct KeyBlock;
struct ModifierData;
@@ -95,8 +96,6 @@ struct MCol;
struct ColorBand;
struct GPUVertexAttribs;
struct GPUDrawObject;
-struct BMEditMesh;
-struct ListBase;
struct PBVH;
/* number of sub-elements each mesh element has (for interpolation) */
@@ -114,11 +113,6 @@ typedef struct DMCoNo {
float no[3];
} DMCoNo;
-typedef struct DMGridAdjacency {
- int index[4];
- int rotation[4];
-} DMGridAdjacency;
-
/* keep in sync with MFace/MPoly types */
typedef struct DMFlagMat {
short mat_nr;
@@ -147,13 +141,17 @@ typedef int (*DMSetMaterial)(int mat_nr, void *attribs);
typedef int (*DMCompareDrawOptions)(void *userData, int cur_index, int next_index);
typedef void (*DMSetDrawInterpOptions)(void *userData, int index, float t);
typedef DMDrawOption (*DMSetDrawOptions)(void *userData, int index);
-typedef DMDrawOption (*DMSetDrawOptionsTex)(struct MTFace *tface, const bool has_vcol, int matnr);
+typedef DMDrawOption (*DMSetDrawOptionsMappedTex)(void *userData, int origindex, int mat_nr);
+typedef DMDrawOption (*DMSetDrawOptionsTex)(struct MTexPoly *mtexpoly, const bool has_vcol, int matnr);
typedef enum DMDrawFlag {
DM_DRAW_USE_COLORS = (1 << 0),
DM_DRAW_ALWAYS_SMOOTH = (1 << 1),
DM_DRAW_USE_ACTIVE_UV = (1 << 2),
DM_DRAW_USE_TEXPAINT_UV = (1 << 3),
+ DM_DRAW_SKIP_HIDDEN = (1 << 4),
+ DM_DRAW_SKIP_SELECT = (1 << 5),
+ DM_DRAW_SELECT_USE_EDITMODE = (1 << 6)
} DMDrawFlag;
typedef enum DMForeachFlag {
@@ -189,6 +187,15 @@ struct DerivedMesh {
int totmat; /* total materials. Will be valid only before object drawing. */
struct Material **mat; /* material array. Will be valid only before object drawing */
+ /**
+ * \warning Typical access is done via #getLoopTriArray, #getNumLoopTri.
+ */
+ struct {
+ struct MLoopTri *array;
+ int num;
+ int num_alloc;
+ } looptris;
+
/* use for converting to BMesh which doesn't store bevel weight and edge crease by default */
char cd_flag;
@@ -196,11 +203,23 @@ struct DerivedMesh {
void (*calcNormals)(DerivedMesh *dm);
/** Calculate loop (split) normals */
- void (*calcLoopNormals)(DerivedMesh *dm, const float split_angle);
+ void (*calcLoopNormals)(DerivedMesh *dm, const bool use_split_normals, const float split_angle);
+
+ /** Calculate loop (split) normals, and returns split loop normal spacearr. */
+ void (*calcLoopNormalsSpaceArray)(DerivedMesh *dm, const bool use_split_normals, const float split_angle,
+ struct MLoopNorSpaceArray *r_lnors_spacearr);
+
+ void (*calcLoopTangents)(DerivedMesh *dm);
/** Recalculates mesh tessellation */
void (*recalcTessellation)(DerivedMesh *dm);
+ /** Loop tessellation cache */
+ void (*recalcLoopTri)(DerivedMesh *dm);
+ /** accessor functions */
+ const struct MLoopTri *(*getLoopTriArray)(DerivedMesh * dm);
+ int (*getNumLoopTri)(DerivedMesh *dm);
+
/* Misc. Queries */
/* Also called in Editmode */
@@ -211,7 +230,7 @@ struct DerivedMesh {
int (*getNumPolys)(DerivedMesh *dm);
/** Copy a single vert/edge/tessellated face from the derived mesh into
- * *{vert/edge/face}_r. note that the current implementation
+ * ``*r_{vert/edge/face}``. note that the current implementation
* of this function can be quite slow, iterating over all
* elements (editmesh)
*/
@@ -284,7 +303,6 @@ struct DerivedMesh {
int (*getNumGrids)(DerivedMesh *dm);
int (*getGridSize)(DerivedMesh *dm);
struct CCGElem **(*getGridData)(DerivedMesh * dm);
- DMGridAdjacency *(*getGridAdjacency)(DerivedMesh * dm);
int *(*getGridOffset)(DerivedMesh * dm);
void (*getGridKey)(DerivedMesh *dm, struct CCGKey *key);
DMFlagMat *(*getGridFlagMats)(DerivedMesh * dm);
@@ -423,7 +441,7 @@ struct DerivedMesh {
* - Drawing options too complicated to enumerate, look at code.
*/
void (*drawMappedFacesTex)(DerivedMesh *dm,
- DMSetDrawOptions setDrawOptions,
+ DMSetDrawOptionsMappedTex setDrawOptions,
DMCompareDrawOptions compareDrawOptions,
void *userData, DMDrawFlag uvflag);
@@ -465,30 +483,31 @@ struct DerivedMesh {
void (*setMaterial)(void *userData, int matnr, void *attribs),
bool (*setFace)(void *userData, int index), void *userData);
+ struct GPUDrawObject *(*gpuObjectNew)(DerivedMesh *dm);
+ void (*copy_gpu_data)(DerivedMesh *dm, int type, void *varray_p,
+ const int *mat_orig_to_new, const void *user_data);
+
/** Release reference to the DerivedMesh. This function decides internally
* if the DerivedMesh will be freed, or cached for later use. */
void (*release)(DerivedMesh *dm);
};
-/** utility function to initialize a DerivedMesh's function pointers to
- * the default implementation (for those functions which have a default)
- */
void DM_init_funcs(DerivedMesh *dm);
-/** utility function to initialize a DerivedMesh for the desired number
- * of vertices, edges and faces (doesn't allocate memory for them, just
- * sets up the custom data layers)
- */
-void DM_init(DerivedMesh *dm, DerivedMeshType type, int numVerts, int numEdges,
- int numFaces, int numLoops, int numPolys);
-
-/** utility function to initialize a DerivedMesh for the desired number
- * of vertices, edges and faces, with a layer setup copied from source
- */
-void DM_from_template(DerivedMesh *dm, DerivedMesh *source,
- DerivedMeshType type,
- int numVerts, int numEdges, int numFaces,
- int numLoops, int numPolys);
+void DM_init(
+ DerivedMesh *dm, DerivedMeshType type, int numVerts, int numEdges,
+ int numFaces, int numLoops, int numPolys);
+
+void DM_from_template_ex(
+ DerivedMesh *dm, DerivedMesh *source, DerivedMeshType type,
+ int numVerts, int numEdges, int numTessFaces,
+ int numLoops, int numPolys,
+ CustomDataMask mask);
+void DM_from_template(
+ DerivedMesh *dm, DerivedMesh *source,
+ DerivedMeshType type,
+ int numVerts, int numEdges, int numFaces,
+ int numLoops, int numPolys);
/** utility function to release a DerivedMesh's layers
* returns 1 if DerivedMesh has to be released by the backend, 0 otherwise
@@ -497,10 +516,11 @@ int DM_release(DerivedMesh *dm);
/** utility function to convert a DerivedMesh to a Mesh
*/
-void DM_to_mesh(DerivedMesh *dm, struct Mesh *me, struct Object *ob, CustomDataMask mask);
+void DM_to_mesh(DerivedMesh *dm, struct Mesh *me, struct Object *ob, CustomDataMask mask, bool take_ownership);
-struct BMEditMesh *DM_to_editbmesh(struct DerivedMesh *dm,
- struct BMEditMesh *existing, const bool do_tessellate);
+struct BMEditMesh *DM_to_editbmesh(
+ struct DerivedMesh *dm,
+ struct BMEditMesh *existing, const bool do_tessellate);
/* conversion to bmesh only */
void DM_to_bmesh_ex(struct DerivedMesh *dm, struct BMesh *bm, const bool calc_face_normal);
@@ -510,10 +530,6 @@ struct BMesh *DM_to_bmesh(struct DerivedMesh *dm, const bool calc_face_normal);
/** Utility function to convert a DerivedMesh to a shape key block */
void DM_to_meshkey(DerivedMesh *dm, struct Mesh *me, struct KeyBlock *kb);
-/** set the CD_FLAG_NOCOPY flag in custom data layers where the mask is
- * zero for the layer type, so only layer types specified by the mask
- * will be copied
- */
void DM_set_only_copy(DerivedMesh *dm, CustomDataMask mask);
/* adds a vertex/edge/face custom data layer to a DerivedMesh, optionally
@@ -521,16 +537,21 @@ void DM_set_only_copy(DerivedMesh *dm, CustomDataMask mask);
* alloctype defines how the layer is allocated or copied, and how it is
* freed, see BKE_customdata.h for the different options
*/
-void DM_add_vert_layer(struct DerivedMesh *dm, int type, int alloctype,
- void *layer);
-void DM_add_edge_layer(struct DerivedMesh *dm, int type, int alloctype,
- void *layer);
-void DM_add_tessface_layer(struct DerivedMesh *dm, int type, int alloctype,
- void *layer);
-void DM_add_loop_layer(DerivedMesh *dm, int type, int alloctype,
- void *layer);
-void DM_add_poly_layer(struct DerivedMesh *dm, int type, int alloctype,
- void *layer);
+void DM_add_vert_layer(
+ struct DerivedMesh *dm, int type, int alloctype,
+ void *layer);
+void DM_add_edge_layer(
+ struct DerivedMesh *dm, int type, int alloctype,
+ void *layer);
+void DM_add_tessface_layer(
+ struct DerivedMesh *dm, int type, int alloctype,
+ void *layer);
+void DM_add_loop_layer(
+ DerivedMesh *dm, int type, int alloctype,
+ void *layer);
+void DM_add_poly_layer(
+ struct DerivedMesh *dm, int type, int alloctype,
+ void *layer);
/* custom data access functions
* return pointer to data from first layer which matches type
@@ -565,16 +586,21 @@ void DM_set_tessface_data(struct DerivedMesh *dm, int index, int type, void *dat
* copy count elements from source_index in source to dest_index in dest
* these copy all layers for which the CD_FLAG_NOCOPY flag is not set
*/
-void DM_copy_vert_data(struct DerivedMesh *source, struct DerivedMesh *dest,
- int source_index, int dest_index, int count);
-void DM_copy_edge_data(struct DerivedMesh *source, struct DerivedMesh *dest,
- int source_index, int dest_index, int count);
-void DM_copy_tessface_data(struct DerivedMesh *source, struct DerivedMesh *dest,
- int source_index, int dest_index, int count);
-void DM_copy_loop_data(struct DerivedMesh *source, struct DerivedMesh *dest,
- int source_index, int dest_index, int count);
-void DM_copy_poly_data(struct DerivedMesh *source, struct DerivedMesh *dest,
- int source_index, int dest_index, int count);
+void DM_copy_vert_data(
+ struct DerivedMesh *source, struct DerivedMesh *dest,
+ int source_index, int dest_index, int count);
+void DM_copy_edge_data(
+ struct DerivedMesh *source, struct DerivedMesh *dest,
+ int source_index, int dest_index, int count);
+void DM_copy_tessface_data(
+ struct DerivedMesh *source, struct DerivedMesh *dest,
+ int source_index, int dest_index, int count);
+void DM_copy_loop_data(
+ struct DerivedMesh *source, struct DerivedMesh *dest,
+ int source_index, int dest_index, int count);
+void DM_copy_poly_data(
+ struct DerivedMesh *source, struct DerivedMesh *dest,
+ int source_index, int dest_index, int count);
/* custom data free functions
* free count elements, starting at index
@@ -592,54 +618,46 @@ void DM_DupPolys(DerivedMesh *source, DerivedMesh *target);
void DM_ensure_normals(DerivedMesh *dm);
void DM_ensure_tessface(DerivedMesh *dm);
+void DM_ensure_looptri_data(DerivedMesh *dm);
+void DM_ensure_looptri(DerivedMesh *dm);
+void DM_verttri_from_looptri(MVertTri *verttri, const MLoop *mloop, const MLoopTri *looptri, int looptri_num);
+
void DM_update_tessface_data(DerivedMesh *dm);
+void DM_generate_tangent_tessface_data(DerivedMesh *dm, bool generate);
void DM_update_materials(DerivedMesh *dm, struct Object *ob);
-struct MTFace *DM_paint_uvlayer_active_get(DerivedMesh *dm, int mat_nr);
+struct MLoopUV *DM_paint_uvlayer_active_get(DerivedMesh *dm, int mat_nr);
+
+void DM_interp_vert_data(
+ struct DerivedMesh *source, struct DerivedMesh *dest,
+ int *src_indices, float *weights,
+ int count, int dest_index);
-/** interpolates vertex data from the vertices indexed by src_indices in the
- * source mesh using the given weights and stores the result in the vertex
- * indexed by dest_index in the dest mesh
- */
-void DM_interp_vert_data(struct DerivedMesh *source, struct DerivedMesh *dest,
- int *src_indices, float *weights,
- int count, int dest_index);
-
-/** interpolates edge data from the edges indexed by src_indices in the
- * source mesh using the given weights and stores the result in the edge indexed
- * by dest_index in the dest mesh.
- * if weights is NULL, all weights default to 1.
- * if vert_weights is non-NULL, any per-vertex edge data is interpolated using
- * vert_weights[i] multiplied by weights[i].
- */
typedef float EdgeVertWeight[SUB_ELEMS_EDGE][SUB_ELEMS_EDGE];
-void DM_interp_edge_data(struct DerivedMesh *source, struct DerivedMesh *dest,
- int *src_indices,
- float *weights, EdgeVertWeight *vert_weights,
- int count, int dest_index);
-
-/** interpolates face data from the faces indexed by src_indices in the
- * source mesh using the given weights and stores the result in the face indexed
- * by dest_index in the dest mesh.
- * if weights is NULL, all weights default to 1.
- * if vert_weights is non-NULL, any per-vertex face data is interpolated using
- * vert_weights[i] multiplied by weights[i].
- */
+void DM_interp_edge_data(
+ struct DerivedMesh *source, struct DerivedMesh *dest,
+ int *src_indices,
+ float *weights, EdgeVertWeight *vert_weights,
+ int count, int dest_index);
+
typedef float FaceVertWeight[SUB_ELEMS_FACE][SUB_ELEMS_FACE];
-void DM_interp_tessface_data(struct DerivedMesh *source, struct DerivedMesh *dest,
- int *src_indices,
- float *weights, FaceVertWeight *vert_weights,
- int count, int dest_index);
+void DM_interp_tessface_data(
+ struct DerivedMesh *source, struct DerivedMesh *dest,
+ int *src_indices,
+ float *weights, FaceVertWeight *vert_weights,
+ int count, int dest_index);
void DM_swap_tessface_data(struct DerivedMesh *dm, int index, const int *corner_indices);
-void DM_interp_loop_data(struct DerivedMesh *source, struct DerivedMesh *dest,
- int *src_indices,
- float *weights, int count, int dest_index);
+void DM_interp_loop_data(
+ struct DerivedMesh *source, struct DerivedMesh *dest,
+ int *src_indices,
+ float *weights, int count, int dest_index);
-void DM_interp_poly_data(struct DerivedMesh *source, struct DerivedMesh *dest,
- int *src_indices,
- float *weights, int count, int dest_index);
+void DM_interp_poly_data(
+ struct DerivedMesh *source, struct DerivedMesh *dest,
+ int *src_indices,
+ float *weights, int count, int dest_index);
/* Temporary? A function to give a colorband to derivedmesh for vertexcolor ranges */
void vDM_ColorBand_store(const struct ColorBand *coba, const char alert_color[4]);
@@ -654,56 +672,67 @@ DMCoNo *mesh_get_mapped_verts_nors(struct Scene *scene, struct Object *ob);
void mesh_get_mapped_verts_coords(DerivedMesh *dm, float (*r_cos)[3], const int totcos);
/* */
-DerivedMesh *mesh_get_derived_final(struct Scene *scene, struct Object *ob,
- CustomDataMask dataMask);
-DerivedMesh *mesh_get_derived_deform(struct Scene *scene, struct Object *ob,
- CustomDataMask dataMask);
+DerivedMesh *mesh_get_derived_final(
+ struct Scene *scene, struct Object *ob,
+ CustomDataMask dataMask);
+DerivedMesh *mesh_get_derived_deform(
+ struct Scene *scene, struct Object *ob,
+ CustomDataMask dataMask);
-DerivedMesh *mesh_create_derived_for_modifier(struct Scene *scene, struct Object *ob,
- struct ModifierData *md, int build_shapekey_layers);
+DerivedMesh *mesh_create_derived_for_modifier(
+ struct Scene *scene, struct Object *ob,
+ struct ModifierData *md, int build_shapekey_layers);
-DerivedMesh *mesh_create_derived_render(struct Scene *scene, struct Object *ob,
- CustomDataMask dataMask);
+DerivedMesh *mesh_create_derived_render(
+ struct Scene *scene, struct Object *ob,
+ CustomDataMask dataMask);
-DerivedMesh *getEditDerivedBMesh(struct BMEditMesh *em, struct Object *ob,
- float (*vertexCos)[3]);
+DerivedMesh *getEditDerivedBMesh(
+ struct BMEditMesh *em, struct Object *ob,
+ float (*vertexCos)[3]);
-DerivedMesh *mesh_create_derived_index_render(struct Scene *scene, struct Object *ob, CustomDataMask dataMask, int index);
+DerivedMesh *mesh_create_derived_index_render(
+ struct Scene *scene, struct Object *ob,
+ CustomDataMask dataMask, int index);
/* same as above but wont use render settings */
DerivedMesh *mesh_create_derived(struct Mesh *me, float (*vertCos)[3]);
-DerivedMesh *mesh_create_derived_view(struct Scene *scene, struct Object *ob,
- CustomDataMask dataMask);
-DerivedMesh *mesh_create_derived_no_deform(struct Scene *scene, struct Object *ob,
- float (*vertCos)[3],
- CustomDataMask dataMask);
-DerivedMesh *mesh_create_derived_no_deform_render(struct Scene *scene, struct Object *ob,
- float (*vertCos)[3],
- CustomDataMask dataMask);
+DerivedMesh *mesh_create_derived_view(
+ struct Scene *scene, struct Object *ob,
+ CustomDataMask dataMask);
+DerivedMesh *mesh_create_derived_no_deform(
+ struct Scene *scene, struct Object *ob,
+ float (*vertCos)[3],
+ CustomDataMask dataMask);
+DerivedMesh *mesh_create_derived_no_deform_render(
+ struct Scene *scene, struct Object *ob,
+ float (*vertCos)[3],
+ CustomDataMask dataMask);
/* for gameengine */
-DerivedMesh *mesh_create_derived_no_virtual(struct Scene *scene, struct Object *ob, float (*vertCos)[3],
- CustomDataMask dataMask);
-DerivedMesh *mesh_create_derived_physics(struct Scene *scene, struct Object *ob, float (*vertCos)[3],
- CustomDataMask dataMask);
-
-DerivedMesh *editbmesh_get_derived_base(struct Object *, struct BMEditMesh *em);
-DerivedMesh *editbmesh_get_derived_cage(struct Scene *scene, struct Object *,
- struct BMEditMesh *em, CustomDataMask dataMask);
-DerivedMesh *editbmesh_get_derived_cage_and_final(struct Scene *scene, struct Object *,
- struct BMEditMesh *em, DerivedMesh **r_final,
- CustomDataMask dataMask);
+DerivedMesh *mesh_create_derived_no_virtual(
+ struct Scene *scene, struct Object *ob, float (*vertCos)[3],
+ CustomDataMask dataMask);
+DerivedMesh *mesh_create_derived_physics(
+ struct Scene *scene, struct Object *ob, float (*vertCos)[3],
+ CustomDataMask dataMask);
+
+DerivedMesh *editbmesh_get_derived_base(
+ struct Object *, struct BMEditMesh *em);
+DerivedMesh *editbmesh_get_derived_cage(
+ struct Scene *scene, struct Object *,
+ struct BMEditMesh *em, CustomDataMask dataMask);
+DerivedMesh *editbmesh_get_derived_cage_and_final(
+ struct Scene *scene, struct Object *,
+ struct BMEditMesh *em, CustomDataMask dataMask,
+ DerivedMesh **r_final);
DerivedMesh *object_get_derived_final(struct Object *ob, const bool for_render);
float (*editbmesh_get_vertex_cos(struct BMEditMesh *em, int *r_numVerts))[3];
bool editbmesh_modifier_is_enabled(struct Scene *scene, struct ModifierData *md, DerivedMesh *dm);
-void makeDerivedMesh(struct Scene *scene, struct Object *ob, struct BMEditMesh *em,
- CustomDataMask dataMask, int build_shapekey_layers);
-
-/** returns an array of deform matrices for crazyspace correction, and the
- * number of modifiers left */
-int editbmesh_get_first_deform_matrices(struct Scene *, struct Object *, struct BMEditMesh *em,
- float (**deformmats)[3][3], float (**deformcos)[3]);
+void makeDerivedMesh(
+ struct Scene *scene, struct Object *ob, struct BMEditMesh *em,
+ CustomDataMask dataMask, const bool build_shapekey_layers);
void weight_to_rgb(float r_rgb[3], const float weight);
/** Update the weight MCOL preview layer.
@@ -713,19 +742,20 @@ void weight_to_rgb(float r_rgb[3], const float weight);
* Else, it must be of num length, as indices, which contains vertices' idx to apply weights to.
* (other vertices are assumed zero weight).
*/
-void DM_update_weight_mcol(struct Object *ob, struct DerivedMesh *dm, int const draw_flag,
- float *weights, int num, const int *indices);
+void DM_update_weight_mcol(
+ struct Object *ob, struct DerivedMesh *dm, int const draw_flag,
+ float *weights, int num, const int *indices);
/** convert layers requested by a GLSL material to actually available layers in
* the DerivedMesh, with both a pointer for arrays and an offset for editmesh */
typedef struct DMVertexAttribs {
struct {
- struct MTFace *array;
+ struct MLoopUV *array;
int em_offset, gl_index, gl_texco;
} tface[MAX_MTFACE];
struct {
- struct MCol *array;
+ struct MLoopCol *array;
int em_offset, gl_index;
} mcol[MAX_MCOL];
@@ -742,10 +772,13 @@ typedef struct DMVertexAttribs {
int tottface, totmcol, tottang, totorco;
} DMVertexAttribs;
-void DM_vertex_attributes_from_gpu(DerivedMesh *dm,
- struct GPUVertexAttribs *gattribs, DMVertexAttribs *attribs);
+void DM_vertex_attributes_from_gpu(
+ DerivedMesh *dm,
+ struct GPUVertexAttribs *gattribs, DMVertexAttribs *attribs);
+
+void DM_draw_attrib_vertex(DMVertexAttribs *attribs, int a, int index, int vert, int loop);
-void DM_add_tangent_layer(DerivedMesh *dm);
+void DM_calc_loop_tangents(DerivedMesh *dm);
void DM_calc_auto_bump_scale(DerivedMesh *dm);
/** Set object's bounding box based on DerivedMesh min/max data */
@@ -762,18 +795,26 @@ void DM_debug_print_cdlayers(CustomData *cdata);
bool DM_is_valid(DerivedMesh *dm);
#endif
-BLI_INLINE int DM_origindex_mface_mpoly(const int *index_mf_to_mpoly, const int *index_mp_to_orig, const int i) ATTR_NONNULL(1);
+BLI_INLINE int DM_origindex_mface_mpoly(
+ const int *index_mf_to_mpoly, const int *index_mp_to_orig, const int i) ATTR_NONNULL(1);
-BLI_INLINE int DM_origindex_mface_mpoly(const int *index_mf_to_mpoly, const int *index_mp_to_orig, const int i)
+BLI_INLINE int DM_origindex_mface_mpoly(
+ const int *index_mf_to_mpoly, const int *index_mp_to_orig, const int i)
{
const int j = index_mf_to_mpoly[i];
return (j != ORIGINDEX_NONE) ? (index_mp_to_orig ? index_mp_to_orig[j] : j) : ORIGINDEX_NONE;
}
-struct MVert *DM_get_vert_array(struct DerivedMesh *dm, bool *allocated);
-struct MEdge *DM_get_edge_array(struct DerivedMesh *dm, bool *allocated);
-struct MLoop *DM_get_loop_array(struct DerivedMesh *dm, bool *allocated);
-struct MPoly *DM_get_poly_array(struct DerivedMesh *dm, bool *allocated);
-struct MFace *DM_get_tessface_array(struct DerivedMesh *dm, bool *allocated);
+struct MVert *DM_get_vert_array(struct DerivedMesh *dm, bool *r_allocated);
+struct MEdge *DM_get_edge_array(struct DerivedMesh *dm, bool *r_allocated);
+struct MLoop *DM_get_loop_array(struct DerivedMesh *dm, bool *r_allocated);
+struct MPoly *DM_get_poly_array(struct DerivedMesh *dm, bool *r_allocated);
+struct MFace *DM_get_tessface_array(struct DerivedMesh *dm, bool *r_allocated);
+const MLoopTri *DM_get_looptri_array(
+ DerivedMesh *dm,
+ const MVert *mvert,
+ const MPoly *mpoly, int mpoly_len,
+ const MLoop *mloop, int mloop_len,
+ bool *r_allocated);
#endif /* __BKE_DERIVEDMESH_H__ */
diff --git a/source/blender/blenkernel/BKE_action.h b/source/blender/blenkernel/BKE_action.h
index 57ba6fd55ca..3fceef5d95d 100644
--- a/source/blender/blenkernel/BKE_action.h
+++ b/source/blender/blenkernel/BKE_action.h
@@ -46,8 +46,6 @@ struct bItasc;
struct bPoseChannel;
struct Main;
struct Object;
-struct Scene;
-struct ID;
/* Kernel prototypes */
#ifdef __cplusplus
@@ -142,6 +140,10 @@ void BKE_pose_channels_free_ex(struct bPose *pose, bool do_id_us
void BKE_pose_channels_hash_make(struct bPose *pose);
void BKE_pose_channels_hash_free(struct bPose *pose);
+void BKE_pose_channels_remove(
+ struct Object *ob,
+ bool (*filter_fn)(const char *bone_name, void *user_data), void *user_data);
+
void BKE_pose_free(struct bPose *pose);
void BKE_pose_free_ex(struct bPose *pose, bool do_id_user);
void BKE_pose_copy_data(struct bPose **dst, struct bPose *src, const bool copy_constraints);
@@ -161,6 +163,9 @@ void extract_pose_from_pose(struct bPose *pose, const struct bPose *src);
/* sets constraint flags */
void BKE_pose_update_constraint_flags(struct bPose *pose);
+/* tag constraint flags for update */
+void BKE_pose_tag_update_constraint_flags(struct bPose *pose);
+
/* return the name of structure pointed by pose->ikparam */
const char *BKE_pose_ikparam_get_name(struct bPose *pose);
@@ -197,6 +202,9 @@ bool BKE_pose_copy_result(struct bPose *to, struct bPose *from);
/* clear all transforms */
void BKE_pose_rest(struct bPose *pose);
+/* Tag pose for recalc. Also tag all related data to be recalc. */
+void BKE_pose_tag_recalc(struct Main *bmain, struct bPose *pose);
+
#ifdef __cplusplus
};
#endif
diff --git a/source/blender/blenkernel/BKE_addon.h b/source/blender/blenkernel/BKE_addon.h
index 9c09fffe0a0..74c1edd1c1b 100644
--- a/source/blender/blenkernel/BKE_addon.h
+++ b/source/blender/blenkernel/BKE_addon.h
@@ -38,7 +38,7 @@ typedef struct bAddonPrefType {
bAddonPrefType *BKE_addon_pref_type_find(const char *idname, bool quiet);
void BKE_addon_pref_type_add(bAddonPrefType *apt);
-void BKE_addon_pref_type_remove(bAddonPrefType *apt);
+void BKE_addon_pref_type_remove(const bAddonPrefType *apt);
void BKE_addon_pref_type_init(void);
void BKE_addon_pref_type_free(void);
diff --git a/source/blender/blenkernel/BKE_anim.h b/source/blender/blenkernel/BKE_anim.h
index 0d5078bc026..584f0da323a 100644
--- a/source/blender/blenkernel/BKE_anim.h
+++ b/source/blender/blenkernel/BKE_anim.h
@@ -35,7 +35,6 @@
struct EvaluationContext;
struct Path;
struct Object;
-struct PartEff;
struct Scene;
struct ListBase;
struct bAnimVizSettings;
@@ -81,7 +80,7 @@ typedef struct DupliApplyData {
DupliExtraData *extra;
} DupliApplyData;
-DupliApplyData *duplilist_apply(struct Object *ob, struct ListBase *duplilist);
+DupliApplyData *duplilist_apply(struct Object *ob, struct Scene *scene, struct ListBase *duplilist);
void duplilist_restore(struct ListBase *duplilist, DupliApplyData *apply_data);
void duplilist_free_apply_data(DupliApplyData *apply_data);
diff --git a/source/blender/blenkernel/BKE_animsys.h b/source/blender/blenkernel/BKE_animsys.h
index 80d2750fe82..dc751747f32 100644
--- a/source/blender/blenkernel/BKE_animsys.h
+++ b/source/blender/blenkernel/BKE_animsys.h
@@ -37,8 +37,10 @@ struct Main;
struct AnimData;
struct KeyingSet;
struct KS_Path;
+struct bContext;
struct PointerRNA;
+struct PropertyRNA;
struct ReportList;
struct bAction;
struct bActionGroup;
@@ -54,28 +56,42 @@ bool id_type_can_have_animdata(struct ID *id);
struct AnimData *BKE_animdata_from_id(struct ID *id);
/* Add AnimData to the given ID-block */
-struct AnimData *BKE_id_add_animdata(struct ID *id);
+struct AnimData *BKE_animdata_add_id(struct ID *id);
/* Set active action used by AnimData from the given ID-block */
bool BKE_animdata_set_action(struct ReportList *reports, struct ID *id, struct bAction *act);
/* Free AnimData */
-void BKE_free_animdata(struct ID *id);
+void BKE_animdata_free(struct ID *id);
/* Copy AnimData */
-struct AnimData *BKE_copy_animdata(struct AnimData *adt, const bool do_action);
+struct AnimData *BKE_animdata_copy(struct AnimData *adt, const bool do_action);
/* Copy AnimData */
-bool BKE_copy_animdata_id(struct ID *id_to, struct ID *id_from, const bool do_action);
+bool BKE_animdata_copy_id(struct ID *id_to, struct ID *id_from, const bool do_action);
/* Copy AnimData Actions */
-void BKE_copy_animdata_id_action(struct ID *id);
+void BKE_animdata_copy_id_action(struct ID *id);
+
+/* Merge copies of data from source AnimData block */
+typedef enum eAnimData_MergeCopy_Modes {
+ /* Keep destination action */
+ ADT_MERGECOPY_KEEP_DST = 0,
+
+ /* Use src action (make a new copy) */
+ ADT_MERGECOPY_SRC_COPY = 1,
+
+ /* Use src action (but just reference the existing version) */
+ ADT_MERGECOPY_SRC_REF = 2
+} eAnimData_MergeCopy_Modes;
+
+void BKE_animdata_merge_copy(struct ID *dst_id, struct ID *src_id, eAnimData_MergeCopy_Modes action_mode, bool fix_drivers);
/* Make Local */
void BKE_animdata_make_local(struct AnimData *adt);
/* Re-Assign ID's */
-void BKE_relink_animdata(struct AnimData *adt);
+void BKE_animdata_relink(struct AnimData *adt);
/* ************************************* */
/* KeyingSets API */
@@ -104,7 +120,11 @@ void BKE_keyingsets_free(struct ListBase *list);
/* ************************************* */
/* Path Fixing API */
-/* Fix all the paths for the the given ID + Action */
+/* Get a "fixed" version of the given path (oldPath) */
+char *BKE_animsys_fix_rna_path_rename(ID *owner_id, char *old_path, const char *prefix, const char *oldName,
+ const char *newName, int oldSubscript, int newSubscript, bool verify_paths);
+
+/* Fix all the paths for the given ID + Action */
void BKE_action_fix_paths_rename(struct ID *owner_id, struct bAction *act, const char *prefix, const char *oldName,
const char *newName, int oldSubscript, int newSubscript, bool verify_paths);
@@ -114,7 +134,7 @@ void BKE_animdata_fix_paths_rename(struct ID *owner_id, struct AnimData *adt, st
bool verify_paths);
/* Fix all the paths for the entire database... */
-void BKE_all_animdata_fix_paths_rename(ID *ref_id, const char *prefix, const char *oldName, const char *newName);
+void BKE_animdata_fix_paths_rename_all(ID *ref_id, const char *prefix, const char *oldName, const char *newName);
/* Fix the path after removing elements that are not ID (e.g., node) */
void BKE_animdata_fix_paths_remove(struct ID *id, const char *path);
@@ -127,6 +147,9 @@ void BKE_animdata_separate_by_basepath(struct ID *srcID, struct ID *dstID, struc
/* Move F-Curves from src to destination if it's path is based on basepath */
void action_move_fcurves_by_basepath(struct bAction *srcAct, struct bAction *dstAct, const char basepath[]);
+char *BKE_animdata_driver_path_hack(struct bContext *C, struct PointerRNA *ptr, struct PropertyRNA *prop,
+ char *base_path);
+
/* ************************************* */
/* Batch AnimData API */
@@ -152,6 +175,9 @@ void BKE_animsys_evaluate_animdata(struct Scene *scene, struct ID *id, struct An
/* Evaluation of all ID-blocks with Animation Data blocks - Animation Data Only */
void BKE_animsys_evaluate_all_animation(struct Main *main, struct Scene *scene, float ctime);
+/* TODO(sergey): This is mainly a temp public function. */
+struct FCurve;
+bool BKE_animsys_execute_fcurve(struct PointerRNA *ptr, struct AnimMapper *remap, struct FCurve *fcu);
/* ------------ Specialized API --------------- */
/* There are a few special tools which require these following functions. They are NOT to be used
@@ -169,4 +195,13 @@ void animsys_evaluate_action_group(struct PointerRNA *ptr, struct bAction *act,
/* ************************************* */
+/* ------------ Evaluation API --------------- */
+
+struct EvaluationContext;
+
+void BKE_animsys_eval_animdata(struct EvaluationContext *eval_ctx, struct ID *id);
+void BKE_animsys_eval_driver(struct EvaluationContext *eval_ctx, struct ID *id, struct FCurve *fcurve);
+
+/* ************************************* */
+
#endif /* __BKE_ANIMSYS_H__*/
diff --git a/source/blender/blenkernel/BKE_appdir.h b/source/blender/blenkernel/BKE_appdir.h
new file mode 100644
index 00000000000..077fe2a629c
--- /dev/null
+++ b/source/blender/blenkernel/BKE_appdir.h
@@ -0,0 +1,85 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+#ifndef __BKE_APPDIR_H__
+#define __BKE_APPDIR_H__
+
+/** \file BKE_appdir.h
+ * \ingroup bli
+ */
+
+/* note on naming: typical _get() suffix is omitted here,
+ * since its the main purpose of the API. */
+const char *BKE_appdir_folder_default(void);
+const char *BKE_appdir_folder_id(const int folder_id, const char *subfolder);
+const char *BKE_appdir_folder_id_create(const int folder_id, const char *subfolder);
+const char *BKE_appdir_folder_id_user_notest(const int folder_id, const char *subfolder);
+const char *BKE_appdir_folder_id_version(const int folder_id, const int ver, const bool do_check);
+
+/* Initialize path to program executable */
+void BKE_appdir_program_path_init(const char *argv0);
+
+const char *BKE_appdir_program_path(void);
+const char *BKE_appdir_program_dir(void);
+
+/* find python executable */
+bool BKE_appdir_program_python_search(
+ char *fullpath, const size_t fullpath_len,
+ const int version_major, const int version_minor);
+
+/* Initialize path to temporary directory. */
+void BKE_tempdir_init(char *userdir);
+void BKE_tempdir_system_init(char *dir);
+
+const char *BKE_tempdir_base(void);
+const char *BKE_tempdir_session(void);
+void BKE_tempdir_session_purge(void);
+
+
+/* folder_id */
+enum {
+ /* general, will find based on user/local/system priority */
+ BLENDER_DATAFILES = 2,
+
+ /* user-specific */
+ BLENDER_USER_CONFIG = 31,
+ BLENDER_USER_DATAFILES = 32,
+ BLENDER_USER_SCRIPTS = 33,
+ BLENDER_USER_AUTOSAVE = 34,
+
+ /* system */
+ BLENDER_SYSTEM_DATAFILES = 52,
+ BLENDER_SYSTEM_SCRIPTS = 53,
+ BLENDER_SYSTEM_PYTHON = 54,
+};
+
+/* for BKE_appdir_folder_id_version only */
+enum {
+ BLENDER_RESOURCE_PATH_USER = 0,
+ BLENDER_RESOURCE_PATH_LOCAL = 1,
+ BLENDER_RESOURCE_PATH_SYSTEM = 2,
+};
+
+#define BLENDER_STARTUP_FILE "startup.blend"
+#define BLENDER_USERPREF_FILE "userpref.blend"
+#define BLENDER_QUIT_FILE "quit.blend"
+#define BLENDER_BOOKMARK_FILE "bookmarks.txt"
+#define BLENDER_HISTORY_FILE "recent-files.txt"
+
+#endif /* __BKE_APPDIR_H__ */
diff --git a/source/blender/blenkernel/BKE_armature.h b/source/blender/blenkernel/BKE_armature.h
index fdf0795fe02..e1885e46b24 100644
--- a/source/blender/blenkernel/BKE_armature.h
+++ b/source/blender/blenkernel/BKE_armature.h
@@ -36,13 +36,10 @@
struct Bone;
struct Main;
struct bArmature;
-struct bPose;
struct bPoseChannel;
struct bConstraint;
struct Scene;
struct Object;
-struct MDeformVert;
-struct Mesh;
struct PoseTree;
struct ListBase;
@@ -83,14 +80,18 @@ struct bArmature *BKE_armature_copy(struct bArmature *arm);
/* Bounding box. */
struct BoundBox *BKE_armature_boundbox_get(struct Object *ob);
+bool BKE_pose_minmax(struct Object *ob, float r_min[3], float r_max[3], bool use_hidden, bool use_select);
+
int bone_autoside_name(char name[64], int strip_number, short axis, float head, float tail);
struct Bone *BKE_armature_find_bone_name(struct bArmature *arm, const char *name);
+bool BKE_armature_bone_flag_test_recursive(const struct Bone *bone, int flag);
+
float distfactor_to_bone(const float vec[3], const float b1[3], const float b2[3], float r1, float r2, float rdist);
void BKE_armature_where_is(struct bArmature *arm);
-void BKE_armature_where_is_bone(struct Bone *bone, struct Bone *prevbone);
+void BKE_armature_where_is_bone(struct Bone *bone, struct Bone *prevbone, const bool use_recursion);
void BKE_pose_rebuild(struct Object *ob, struct bArmature *arm);
void BKE_pose_where_is(struct Scene *scene, struct Object *ob);
void BKE_pose_where_is_bone(struct Scene *scene, struct Object *ob, struct bPoseChannel *pchan, float ctime, bool do_extra);
@@ -143,6 +144,57 @@ void b_bone_spline_setup(struct bPoseChannel *pchan, int rest, Mat4 result_array
#define PBONE_SELECTABLE(arm, bone) \
(PBONE_VISIBLE(arm, bone) && !((bone)->flag & BONE_UNSELECTABLE))
+/* Evaluation helpers */
+struct bKinematicConstraint;
+struct bPose;
+struct bSplineIKConstraint;
+struct EvaluationContext;
+
+struct bPoseChannel *BKE_armature_ik_solver_find_root(
+ struct bPoseChannel *pchan,
+ struct bKinematicConstraint *data);
+struct bPoseChannel *BKE_armature_splineik_solver_find_root(
+ struct bPoseChannel *pchan,
+ struct bSplineIKConstraint *data);
+
+void BKE_pose_splineik_init_tree(struct Scene *scene, struct Object *ob, float ctime);
+void BKE_splineik_execute_tree(struct Scene *scene, struct Object *ob, struct bPoseChannel *pchan_root, float ctime);
+
+void BKE_pose_eval_init(struct EvaluationContext *eval_ctx,
+ struct Scene *scene,
+ struct Object *ob,
+ struct bPose *pose);
+
+void BKE_pose_eval_bone(struct EvaluationContext *eval_ctx,
+ struct Scene *scene,
+ struct Object *ob,
+ struct bPoseChannel *pchan);
+
+void BKE_pose_constraints_evaluate(struct EvaluationContext *eval_ctx,
+ struct Object *ob,
+ struct bPoseChannel *pchan);
+
+void BKE_pose_bone_done(struct EvaluationContext *eval_ctx,
+ struct bPoseChannel *pchan);
+
+void BKE_pose_iktree_evaluate(struct EvaluationContext *eval_ctx,
+ struct Scene *scene,
+ struct Object *ob,
+ struct bPoseChannel *rootchan);
+
+void BKE_pose_splineik_evaluate(struct EvaluationContext *eval_ctx,
+ struct Scene *scene,
+ struct Object *ob,
+ struct bPoseChannel *rootchan);
+
+void BKE_pose_eval_flush(struct EvaluationContext *eval_ctx,
+ struct Scene *scene,
+ struct Object *ob,
+ struct bPose *pose);
+
+void BKE_pose_eval_proxy_copy(struct EvaluationContext *eval_ctx,
+ struct Object *ob);
+
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/blenkernel/BKE_blender.h b/source/blender/blenkernel/BKE_blender.h
index 661fe03912f..327ae898686 100644
--- a/source/blender/blenkernel/BKE_blender.h
+++ b/source/blender/blenkernel/BKE_blender.h
@@ -41,9 +41,9 @@ extern "C" {
/* these lines are grep'd, watch out for our not-so-awesome regex
* and keep comment above the defines.
* Use STRINGIFY() rather than defining with quotes */
-#define BLENDER_VERSION 272
-#define BLENDER_SUBVERSION 0
-/* 262 was the last editmesh release but it has compatibility code for bmesh data */
+#define BLENDER_VERSION 276
+#define BLENDER_SUBVERSION 1
+/* Several breakages with 270, e.g. constraint deg vs rad */
#define BLENDER_MINVERSION 270
#define BLENDER_MINSUBVERSION 5
@@ -55,7 +55,6 @@ extern "C" {
extern char versionstr[]; /* from blender.c */
-struct ListBase;
struct MemFile;
struct bContext;
struct ReportList;
@@ -88,21 +87,21 @@ void BKE_userdef_free(void);
void BKE_userdef_state(void);
/* set this callback when a UI is running */
-void set_blender_test_break_cb(void (*func)(void) );
+void BKE_blender_callback_test_break_set(void (*func)(void));
int blender_test_break(void);
#define BKE_UNDO_STR_MAX 64
/* global undo */
-extern void BKE_write_undo(struct bContext *C, const char *name);
-extern void BKE_undo_step(struct bContext *C, int step);
-extern void BKE_undo_name(struct bContext *C, const char *name);
-extern int BKE_undo_valid(const char *name);
-extern void BKE_reset_undo(void);
-extern void BKE_undo_number(struct bContext *C, int nr);
-extern const char *BKE_undo_get_name(int nr, int *active);
-extern bool BKE_undo_save_file(const char *filename);
-extern struct Main *BKE_undo_get_main(struct Scene **scene);
+extern void BKE_undo_write(struct bContext *C, const char *name);
+extern void BKE_undo_step(struct bContext *C, int step);
+extern void BKE_undo_name(struct bContext *C, const char *name);
+extern bool BKE_undo_is_valid(const char *name);
+extern void BKE_undo_reset(void);
+extern void BKE_undo_number(struct bContext *C, int nr);
+extern const char *BKE_undo_get_name(int nr, bool *r_active);
+extern bool BKE_undo_save_file(const char *filename);
+extern struct Main *BKE_undo_get_main(struct Scene **r_scene);
/* copybuffer */
void BKE_copybuffer_begin(struct Main *bmain);
diff --git a/source/blender/blenkernel/BKE_bpath.h b/source/blender/blenkernel/BKE_bpath.h
index 990b414a4cf..10ee504f244 100644
--- a/source/blender/blenkernel/BKE_bpath.h
+++ b/source/blender/blenkernel/BKE_bpath.h
@@ -48,13 +48,21 @@ void *BKE_bpath_list_backup(struct Main *bmain, const int flag);
void BKE_bpath_list_restore(struct Main *bmain, const int flag, void *ls_handle);
void BKE_bpath_list_free(void *ls_handle);
-#define BKE_BPATH_TRAVERSE_ABS (1 << 0) /* convert paths to absolute */
-#define BKE_BPATH_TRAVERSE_SKIP_LIBRARY (1 << 2) /* skip library paths */
-#define BKE_BPATH_TRAVERSE_SKIP_PACKED (1 << 3) /* skip packed data */
-#define BKE_BPATH_TRAVERSE_SKIP_MULTIFILE (1 << 4) /* skip paths where a single dir is used with an array of files, eg.
- * sequence strip images and pointcache. in this case only use the first
- * file, this is needed for directory manipulation functions which might
- * otherwise modify the same directory multiple times */
+enum {
+ /* convert paths to absolute */
+ BKE_BPATH_TRAVERSE_ABS = (1 << 0),
+ /* skip library paths */
+ BKE_BPATH_TRAVERSE_SKIP_LIBRARY = (1 << 1),
+ /* skip packed data */
+ BKE_BPATH_TRAVERSE_SKIP_PACKED = (1 << 2),
+ /* skip paths where a single dir is used with an array of files, eg.
+ * sequence strip images and pointcache. in this case only use the first
+ * file, this is needed for directory manipulation functions which might
+ * otherwise modify the same directory multiple times */
+ BKE_BPATH_TRAVERSE_SKIP_MULTIFILE = (1 << 3),
+ /* reload data (when the path is edited) */
+ BKE_BPATH_TRAVERSE_RELOAD_EDITED = (1 << 4),
+};
/* high level funcs */
diff --git a/source/blender/blenkernel/BKE_brush.h b/source/blender/blenkernel/BKE_brush.h
index d48753590bb..aff3fb08df6 100644
--- a/source/blender/blenkernel/BKE_brush.h
+++ b/source/blender/blenkernel/BKE_brush.h
@@ -27,14 +27,11 @@
* General operations for brushes.
*/
-struct ID;
struct Brush;
struct ImBuf;
struct ImagePool;
struct Main;
-struct rctf;
struct Scene;
-struct wmOperator;
// enum CurveMappingPreset;
@@ -43,7 +40,8 @@ void BKE_brush_system_init(void);
void BKE_brush_system_exit(void);
/* datablock functions */
-struct Brush *BKE_brush_add(struct Main *bmain, const char *name);
+struct Brush *BKE_brush_add(struct Main *bmain, const char *name, short ob_mode);
+struct Brush *BKE_brush_first_search(struct Main *bmain, short ob_mode);
struct Brush *BKE_brush_copy(struct Brush *brush);
void BKE_brush_make_local(struct Brush *brush);
void BKE_brush_free(struct Brush *brush);
@@ -62,12 +60,12 @@ int BKE_brush_clone_image_delete(struct Brush *brush);
/* jitter */
void BKE_brush_jitter_pos(const struct Scene *scene, struct Brush *brush,
const float pos[2], float jitterpos[2]);
-void BKE_brush_randomize_texture_coordinates(struct UnifiedPaintSettings *ups, bool mask);
+void BKE_brush_randomize_texture_coords(struct UnifiedPaintSettings *ups, bool mask);
/* brush curve */
void BKE_brush_curve_preset(struct Brush *b, int preset);
-float BKE_brush_curve_strength_clamp(struct Brush *br, float p, const float len);
-float BKE_brush_curve_strength(struct Brush *br, float p, const float len); /* used for sculpt */
+float BKE_brush_curve_strength_clamped(struct Brush *br, float p, const float len);
+float BKE_brush_curve_strength(struct Brush *br, float p, const float len);
/* sampling */
float BKE_brush_sample_tex_3D(const Scene *scene, struct Brush *br, const float point[3],
@@ -83,34 +81,36 @@ struct ImBuf *BKE_brush_gen_radial_control_imbuf(struct Brush *br, bool secondar
/* unified strength size and color */
-float *BKE_brush_color_get(const struct Scene *scene, struct Brush *brush);
-float *BKE_brush_secondary_color_get(const struct Scene *scene, struct Brush *brush);
+const float *BKE_brush_color_get(const struct Scene *scene, const struct Brush *brush);
+const float *BKE_brush_secondary_color_get(const struct Scene *scene, const struct Brush *brush);
void BKE_brush_color_set(struct Scene *scene, struct Brush *brush, const float color[3]);
-int BKE_brush_size_get(const struct Scene *scene, struct Brush *brush);
+int BKE_brush_size_get(const struct Scene *scene, const struct Brush *brush);
void BKE_brush_size_set(struct Scene *scene, struct Brush *brush, int value);
-float BKE_brush_unprojected_radius_get(const struct Scene *scene, struct Brush *brush);
+float BKE_brush_unprojected_radius_get(const struct Scene *scene, const struct Brush *brush);
void BKE_brush_unprojected_radius_set(struct Scene *scene, struct Brush *brush, float value);
-float BKE_brush_alpha_get(const struct Scene *scene, struct Brush *brush);
+float BKE_brush_alpha_get(const struct Scene *scene, const struct Brush *brush);
void BKE_brush_alpha_set(Scene *scene, struct Brush *brush, float alpha);
-float BKE_brush_weight_get(const Scene *scene, struct Brush *brush);
+float BKE_brush_weight_get(const Scene *scene, const struct Brush *brush);
void BKE_brush_weight_set(const Scene *scene, struct Brush *brush, float value);
-int BKE_brush_use_locked_size(const struct Scene *scene, struct Brush *brush);
-int BKE_brush_use_alpha_pressure(const struct Scene *scene, struct Brush *brush);
-int BKE_brush_use_size_pressure(const struct Scene *scene, struct Brush *brush);
+int BKE_brush_use_locked_size(const struct Scene *scene, const struct Brush *brush);
+int BKE_brush_use_alpha_pressure(const struct Scene *scene, const struct Brush *brush);
+int BKE_brush_use_size_pressure(const struct Scene *scene, const struct Brush *brush);
/* scale unprojected radius to reflect a change in the brush's 2D size */
-void BKE_brush_scale_unprojected_radius(float *unprojected_radius,
- int new_brush_size,
- int old_brush_size);
+void BKE_brush_scale_unprojected_radius(
+ float *unprojected_radius,
+ int new_brush_size,
+ int old_brush_size);
/* scale brush size to reflect a change in the brush's unprojected radius */
-void BKE_brush_scale_size(int *BKE_brush_size_get,
- float new_unprojected_radius,
- float old_unprojected_radius);
+void BKE_brush_scale_size(
+ int *r_brush_size,
+ float new_unprojected_radius,
+ float old_unprojected_radius);
/* debugging only */
void BKE_brush_debug_print_state(struct Brush *br);
diff --git a/source/blender/blenkernel/BKE_bvhutils.h b/source/blender/blenkernel/BKE_bvhutils.h
index 4bc8fc44bb4..18eda63bcf1 100644
--- a/source/blender/blenkernel/BKE_bvhutils.h
+++ b/source/blender/blenkernel/BKE_bvhutils.h
@@ -31,9 +31,10 @@
* \ingroup bke
*/
+#include "BLI_bitmap.h"
#include "BLI_kdopbvh.h"
-/*
+/**
* This header encapsulates necessary code to buld a BVH
*/
@@ -41,7 +42,7 @@ struct DerivedMesh;
struct MVert;
struct MFace;
-/*
+/**
* struct that kepts basic information about a BVHTree build from a mesh
*/
typedef struct BVHTreeFromMesh {
@@ -52,12 +53,16 @@ typedef struct BVHTreeFromMesh {
BVHTree_RayCastCallback raycast_callback;
/* Vertex array, so that callbacks have instante access to data */
- struct MVert *vert;
- struct MEdge *edge; /* only used for BVHTreeFromMeshEdges */
- struct MFace *face;
+ const struct MVert *vert;
+ const struct MEdge *edge; /* only used for BVHTreeFromMeshEdges */
+ const struct MFace *face;
+ const struct MLoop *loop;
+ const struct MLoopTri *looptri;
bool vert_allocated;
- bool face_allocated;
bool edge_allocated;
+ bool face_allocated;
+ bool loop_allocated;
+ bool looptri_allocated;
/* radius for raycast */
float sphere_radius;
@@ -68,68 +73,87 @@ typedef struct BVHTreeFromMesh {
} BVHTreeFromMesh;
-/*
- * Builds a bvh tree where nodes are the vertexs of the given mesh.
+/**
+ * Builds a bvh tree where nodes are the relevant elements of the given mesh.
* Configures BVHTreeFromMesh.
*
* The tree is build in mesh space coordinates, this means special care must be made on queries
* so that the coordinates and rays are first translated on the mesh local coordinates.
- * Reason for this is that later bvh_from_mesh_* might use a cache system and so it becomes possible to reuse
- * a BVHTree.
+ * Reason for this is that bvh_from_mesh_* can use a cache in some cases and so it becomes possible to reuse a BVHTree.
*
* free_bvhtree_from_mesh should be called when the tree is no longer needed.
*/
-BVHTree *bvhtree_from_mesh_verts(struct BVHTreeFromMesh *data, struct DerivedMesh *mesh, float epsilon, int tree_type, int axis);
-
-/*
- * Builds a bvh tree where nodes are the faces of the given mesh.
- * Configures BVHTreeFromMesh.
- *
- * The tree is build in mesh space coordinates, this means special care must be made on queries
- * so that the coordinates and rays are first translated on the mesh local coordinates.
- * Reason for this is that later bvh_from_mesh_* might use a cache system and so it becomes possible to reuse
- * a BVHTree.
- *
- * The returned value is the same as in data->tree, its only returned to make it easier to test
- * the success
- *
- * free_bvhtree_from_mesh should be called when the tree is no longer needed.
- */
-BVHTree *bvhtree_from_mesh_faces(struct BVHTreeFromMesh *data, struct DerivedMesh *mesh, float epsilon, int tree_type, int axis);
-
-BVHTree *bvhtree_from_mesh_edges(struct BVHTreeFromMesh *data, struct DerivedMesh *mesh, float epsilon, int tree_type, int axis);
-
-/*
+BVHTree *bvhtree_from_mesh_verts(
+ struct BVHTreeFromMesh *data, struct DerivedMesh *mesh, float epsilon, int tree_type, int axis);
+BVHTree *bvhtree_from_mesh_verts_ex(
+ struct BVHTreeFromMesh *data, struct MVert *vert, const int numVerts,
+ const bool vert_allocated, BLI_bitmap *mask, int numVerts_active,
+ float epsilon, int tree_type, int axis);
+
+BVHTree *bvhtree_from_mesh_edges(
+ struct BVHTreeFromMesh *data, struct DerivedMesh *mesh,
+ float epsilon, int tree_type, int axis);
+
+BVHTree *bvhtree_from_mesh_faces(
+ struct BVHTreeFromMesh *data, struct DerivedMesh *mesh, float epsilon,
+ int tree_type, int axis);
+BVHTree *bvhtree_from_mesh_faces_ex(
+ struct BVHTreeFromMesh *data,
+ struct MVert *vert, const bool vert_allocated,
+ struct MFace *face, const int numFaces, const bool face_allocated,
+ BLI_bitmap *mask, int numFaces_active,
+ float epsilon, int tree_type, int axis);
+
+BVHTree *bvhtree_from_mesh_looptri(
+ struct BVHTreeFromMesh *data, struct DerivedMesh *mesh, float epsilon, int tree_type, int axis);
+BVHTree *bvhtree_from_mesh_looptri_ex(
+ struct BVHTreeFromMesh *data,
+ const struct MVert *vert, const bool vert_allocated,
+ const struct MLoop *mloop, const bool loop_allocated,
+ const struct MLoopTri *looptri, const int looptri_num, const bool looptri_allocated,
+ BLI_bitmap *mask, int looptri_num_active,
+ float epsilon, int tree_type, int axis);
+
+/**
* Frees data allocated by a call to bvhtree_from_mesh_*.
*/
void free_bvhtree_from_mesh(struct BVHTreeFromMesh *data);
-/*
+/**
* Math functions used by callbacks
*/
-float bvhtree_ray_tri_intersection(const BVHTreeRay *ray, const float m_dist, const float v0[3], const float v1[3], const float v2[3]);
-float nearest_point_in_tri_surface_squared(const float v0[3], const float v1[3], const float v2[3], const float p[3], int *v, int *e, float nearest[3]);
-
-/*
+float bvhtree_ray_tri_intersection(
+ const BVHTreeRay *ray, const float m_dist,
+ const float v0[3], const float v1[3], const float v2[3]);
+float bvhtree_sphereray_tri_intersection(
+ const BVHTreeRay *ray, float radius, const float m_dist,
+ const float v0[3], const float v1[3], const float v2[3]);
+float nearest_point_in_tri_surface_squared(
+ const float v0[3], const float v1[3], const float v2[3],
+ const float p[3], int *v, int *e, float nearest[3]);
+
+/**
* BVHCache
*/
-//Using local coordinates
-#define BVHTREE_FROM_FACES 0
-#define BVHTREE_FROM_VERTICES 1
-#define BVHTREE_FROM_EDGES 2
-
-#define BVHTREE_FROM_FACES_EDITMESH 3
+/* Using local coordinates */
+enum {
+ BVHTREE_FROM_VERTS = 0,
+ BVHTREE_FROM_EDGES = 1,
+ BVHTREE_FROM_FACES = 2,
+ BVHTREE_FROM_FACES_EDITMESH = 3,
+ BVHTREE_FROM_LOOPTRI = 4,
+};
typedef struct LinkNode *BVHCache;
-/*
+/**
* Queries a bvhcache for the cache bvhtree of the request type
*/
BVHTree *bvhcache_find(BVHCache *cache, int type);
-/*
+/**
* Inserts a BVHTree of the given type under the cache
* After that the caller no longer needs to worry when to free the BVHTree
* as that will be done when the cache is freed.
@@ -138,7 +162,7 @@ BVHTree *bvhcache_find(BVHCache *cache, int type);
*/
void bvhcache_insert(BVHCache *cache, BVHTree *tree, int type);
-/*
+/**
* inits and frees a bvhcache
*/
void bvhcache_init(BVHCache *cache);
diff --git a/source/blender/blenkernel/BKE_camera.h b/source/blender/blenkernel/BKE_camera.h
index 01b401c6bcc..aacb7a4066b 100644
--- a/source/blender/blenkernel/BKE_camera.h
+++ b/source/blender/blenkernel/BKE_camera.h
@@ -46,6 +46,7 @@ struct RenderData;
struct Scene;
struct rctf;
struct View3D;
+struct GPUFXSettings;
/* Camera Datablock */
@@ -103,22 +104,45 @@ typedef struct CameraParams {
float winmat[4][4];
} CameraParams;
+/* values for CameraParams.zoom, need to be taken into account for some operations */
+#define CAMERA_PARAM_ZOOM_INIT_CAMOB 1.0f
+#define CAMERA_PARAM_ZOOM_INIT_PERSP 2.0f
+
void BKE_camera_params_init(CameraParams *params);
-void BKE_camera_params_from_object(CameraParams *params, struct Object *camera);
-void BKE_camera_params_from_view3d(CameraParams *params, struct View3D *v3d, struct RegionView3D *rv3d);
+void BKE_camera_params_from_object(CameraParams *params, const struct Object *camera);
+void BKE_camera_params_from_view3d(CameraParams *params, const struct View3D *v3d, const struct RegionView3D *rv3d);
void BKE_camera_params_compute_viewplane(CameraParams *params, int winx, int winy, float aspx, float aspy);
void BKE_camera_params_compute_matrix(CameraParams *params);
/* Camera View Frame */
-void BKE_camera_view_frame_ex(struct Scene *scene, struct Camera *camera, float drawsize, const bool do_clip, const float scale[3],
- float r_asp[2], float r_shift[2], float *r_drawsize, float r_vec[4][3]);
-
-void BKE_camera_view_frame(struct Scene *scene, struct Camera *camera, float r_vec[4][3]);
-
-bool BKE_camera_view_frame_fit_to_scene(struct Scene *scene, struct View3D *v3d, struct Object *camera_ob,
- float r_co[3]);
+void BKE_camera_view_frame_ex(
+ const struct Scene *scene, const struct Camera *camera,
+ const float drawsize, const bool do_clip, const float scale[3],
+ float r_asp[2], float r_shift[2], float *r_drawsize, float r_vec[4][3]);
+void BKE_camera_view_frame(
+ const struct Scene *scene, const struct Camera *camera,
+ float r_vec[4][3]);
+
+bool BKE_camera_view_frame_fit_to_scene(
+ struct Scene *scene, struct View3D *v3d, struct Object *camera_ob,
+ float r_co[3], float *r_scale);
+bool BKE_camera_view_frame_fit_to_coords(
+ const struct Scene *scene,
+ const float (*cos)[3], int num_cos,
+ const struct Object *camera_ob,
+ float r_co[3], float *r_scale);
+
+void BKE_camera_to_gpu_dof(struct Object *camera, struct GPUFXSettings *r_fx_settings);
+
+/* Camera multi-view API */
+
+struct Object *BKE_camera_multiview_render(struct Scene *scene, struct Object *camera, const char *viewname);
+void BKE_camera_multiview_view_matrix(struct RenderData *rd, struct Object *camera, const bool is_left, float r_viewmat[4][4]);
+void BKE_camera_multiview_model_matrix(struct RenderData *rd, struct Object *camera, const char *viewname, float r_modelmat[4][4]);
+float BKE_camera_multiview_shift_x(struct RenderData *rd, struct Object *camera, const char *viewname);
+void BKE_camera_multiview_params(struct RenderData *rd, struct CameraParams *params, struct Object *camera, const char *viewname);
#ifdef __cplusplus
}
diff --git a/source/blender/blenkernel/BKE_cdderivedmesh.h b/source/blender/blenkernel/BKE_cdderivedmesh.h
index b0ade7bacdf..9948f21ba90 100644
--- a/source/blender/blenkernel/BKE_cdderivedmesh.h
+++ b/source/blender/blenkernel/BKE_cdderivedmesh.h
@@ -40,6 +40,7 @@
struct DerivedMesh;
struct BMEditMesh;
struct Mesh;
+struct MLoopNorSpaceArray;
struct Object;
/* creates a new CDDerivedMesh */
@@ -83,9 +84,15 @@ struct DerivedMesh *CDDM_copy_from_tessface(struct DerivedMesh *dm);
* given DerivedMesh and containing the requested numbers of elements.
* elements are initialized to all zeros
*/
-struct DerivedMesh *CDDM_from_template(struct DerivedMesh *source,
- int numVerts, int numEdges, int numFaces,
- int numLoops, int numPolys);
+struct DerivedMesh *CDDM_from_template_ex(
+ struct DerivedMesh *source,
+ int numVerts, int numEdges, int numFaces,
+ int numLoops, int numPolys,
+ CustomDataMask mask);
+struct DerivedMesh *CDDM_from_template(
+ struct DerivedMesh *source,
+ int numVerts, int numEdges, int numFaces,
+ int numLoops, int numPolys);
/* converts mfaces to mpolys. note things may break if there are not valid
* medges surrounding each mface.
@@ -106,7 +113,9 @@ void CDDM_calc_normals_mapping(struct DerivedMesh *dm);
void CDDM_calc_normals(struct DerivedMesh *dm);
void CDDM_calc_normals_tessface(struct DerivedMesh *dm);
-void CDDM_calc_loop_normals(struct DerivedMesh *dm, const float split_angle);
+void CDDM_calc_loop_normals(struct DerivedMesh *dm, const bool use_split_normals, const float split_angle);
+void CDDM_calc_loop_normals_spacearr(struct DerivedMesh *dm, const bool use_split_normals, const float split_angle,
+ struct MLoopNorSpaceArray *r_lnors_spacearr);
/* calculates edges for a CDDerivedMesh (from face data)
* this completely replaces the current edge data in the DerivedMesh
@@ -122,6 +131,8 @@ void CDDM_calc_edges(struct DerivedMesh *dm);
void CDDM_recalc_tessellation(struct DerivedMesh *dm);
void CDDM_recalc_tessellation_ex(struct DerivedMesh *dm, const bool do_face_nor_cpy);
+void CDDM_recalc_looptri(struct DerivedMesh *dm);
+
/* lowers the number of vertices/edges/faces in a CDDerivedMesh
* the layer data stays the same size
*/
diff --git a/source/blender/blenkernel/BKE_cloth.h b/source/blender/blenkernel/BKE_cloth.h
index 757d63e6ec1..28de270bbd1 100644
--- a/source/blender/blenkernel/BKE_cloth.h
+++ b/source/blender/blenkernel/BKE_cloth.h
@@ -36,12 +36,11 @@
#include "BLI_math_inline.h"
struct Object;
-struct ListBase;
struct Scene;
struct MFace;
struct DerivedMesh;
struct ClothModifierData;
-struct CollisionTree;
+struct CollisionModifierData;
#define DO_INLINE MALWAYS_INLINE
@@ -53,8 +52,26 @@ struct CollisionTree;
#define ALMOST_ZERO FLT_EPSILON
/* Bits to or into the ClothVertex.flags. */
-#define CLOTH_VERT_FLAG_PINNED 1
-#define CLOTH_VERT_FLAG_NOSELFCOLL 2 /* vertex NOT used for self collisions */
+typedef enum eClothVertexFlag {
+ CLOTH_VERT_FLAG_PINNED = 1,
+ CLOTH_VERT_FLAG_NOSELFCOLL = 2, /* vertex NOT used for self collisions */
+} eClothVertexFlag;
+
+typedef struct ClothHairData {
+ float loc[3];
+ float rot[3][3];
+ float rest_target[3]; /* rest target direction for each segment */
+ float radius;
+ float bending_stiffness;
+} ClothHairData;
+
+typedef struct ClothSolverResult {
+ int status;
+
+ int max_iterations, min_iterations;
+ float avg_iterations;
+ float max_error, min_error, avg_error;
+} ClothSolverResult;
/**
* This structure describes a cloth object against which the
@@ -69,17 +86,16 @@ struct CollisionTree;
typedef struct Cloth {
struct ClothVertex *verts; /* The vertices that represent this cloth. */
struct LinkNode *springs; /* The springs connecting the mesh. */
- unsigned int numverts; /* The number of verts == m * n. */
unsigned int numsprings; /* The count of springs. */
- unsigned int numfaces;
+ unsigned int mvert_num; /* The number of verts == m * n. */
+ unsigned int tri_num;
unsigned char old_solver_type; /* unused, only 1 solver here */
unsigned char pad2;
short pad3;
struct BVHTree *bvhtree; /* collision tree for this cloth object */
struct BVHTree *bvhselftree; /* collision tree for this cloth object */
- struct MFace *mfaces;
+ struct MVertTri *tri;
struct Implicit_Data *implicit; /* our implicit solver connects to this pointer */
- struct Implicit_Data *implicitEM; /* our implicit solver connects to this pointer */
struct EdgeSet *edgeset; /* used for selfcollisions */
int last_frame, pad4;
} Cloth;
@@ -116,8 +132,8 @@ ClothVertex;
typedef struct ClothSpring {
int ij; /* Pij from the paper, one end of the spring. */
int kl; /* Pkl from the paper, one end of the spring. */
+ int mn;
float restlen; /* The original length of the spring. */
- int matrix_index; /* needed for implicit solver (fast lookup) */
int type; /* types defined in BKE_cloth.h ("springType") */
int flags; /* defined in BKE_cloth.h, e.g. deactivated due to tearing */
float dfdx[3][3];
@@ -125,6 +141,9 @@ typedef struct ClothSpring {
float f[3];
float stiffness; /* stiffness factor from the vertex groups */
float editrestlen;
+
+ /* angular bending spring target and derivatives */
+ float target[3];
}
ClothSpring;
@@ -150,7 +169,7 @@ typedef enum {
CLOTH_SIMSETTINGS_FLAG_TEARING = ( 1 << 4 ),// true if tearing is enabled
CLOTH_SIMSETTINGS_FLAG_SCALING = ( 1 << 8 ), /* is advanced scaling active? */
CLOTH_SIMSETTINGS_FLAG_CCACHE_EDIT = (1 << 12), /* edit cache in editmode */
- CLOTH_SIMSETTINGS_FLAG_NO_SPRING_COMPRESS = (1 << 13), /* don't allow spring compression */
+ CLOTH_SIMSETTINGS_FLAG_NO_SPRING_COMPRESS = (1 << 13), /* don't allow spring compression */
CLOTH_SIMSETTINGS_FLAG_SEW = (1 << 14), /* pull ends of loose edges together */
} CLOTH_SIMSETTINGS_FLAGS;
@@ -166,7 +185,8 @@ typedef enum {
CLOTH_SPRING_TYPE_SHEAR = (1 << 2),
CLOTH_SPRING_TYPE_BENDING = (1 << 3),
CLOTH_SPRING_TYPE_GOAL = (1 << 4),
- CLOTH_SPRING_TYPE_SEWING = (1 << 5)
+ CLOTH_SPRING_TYPE_SEWING = (1 << 5),
+ CLOTH_SPRING_TYPE_BENDING_ANG = (1 << 6),
} CLOTH_SPRING_TYPES;
/* SPRING FLAGS */
@@ -180,21 +200,25 @@ typedef enum {
// collision.c
////////////////////////////////////////////////
+struct CollPair;
+
+typedef struct ColliderContacts {
+ struct Object *ob;
+ struct CollisionModifierData *collmd;
+
+ struct CollPair *collisions;
+ int totcollisions;
+} ColliderContacts;
+
// needed for implicit.c
int cloth_bvh_objcollision (struct Object *ob, struct ClothModifierData *clmd, float step, float dt );
+int cloth_points_objcollision(struct Object *ob, struct ClothModifierData *clmd, float step, float dt);
-////////////////////////////////////////////////
-
+void cloth_find_point_contacts(struct Object *ob, struct ClothModifierData *clmd, float step, float dt,
+ ColliderContacts **r_collider_contacts, int *r_totcolliders);
+void cloth_free_contacts(ColliderContacts *collider_contacts, int totcolliders);
////////////////////////////////////////////////
-// implicit.c
-////////////////////////////////////////////////
-
-// needed for cloth.c
-int implicit_init (struct Object *ob, struct ClothModifierData *clmd );
-int implicit_free (struct ClothModifierData *clmd );
-int implicit_solver (struct Object *ob, float frame, struct ClothModifierData *clmd, struct ListBase *effectors );
-void implicit_set_positions (struct ClothModifierData *clmd );
/////////////////////////////////////////////////
// cloth.c
@@ -209,8 +233,8 @@ void clothModifier_do (struct ClothModifierData *clmd, struct Scene *scene, stru
int cloth_uses_vgroup(struct ClothModifierData *clmd);
// needed for collision.c
-void bvhtree_update_from_cloth (struct ClothModifierData *clmd, int moving );
-void bvhselftree_update_from_cloth (struct ClothModifierData *clmd, int moving );
+void bvhtree_update_from_cloth(struct ClothModifierData *clmd, bool moving);
+void bvhselftree_update_from_cloth(struct ClothModifierData *clmd, bool moving);
// needed for button_object.c
void cloth_clear_cache (struct Object *ob, struct ClothModifierData *clmd, float framenr );
@@ -218,27 +242,9 @@ void cloth_clear_cache (struct Object *ob, struct ClothModifierData *clmd, float
// needed for cloth.c
int cloth_add_spring (struct ClothModifierData *clmd, unsigned int indexA, unsigned int indexB, float restlength, int spring_type);
-////////////////////////////////////////////////
-
-
-/* This enum provides the IDs for our solvers. */
-// only one available in the moment
-typedef enum {
- CM_IMPLICIT = 0,
-} CM_SOLVER_ID;
-
-
-/* This structure defines how to call the solver.
- */
-typedef struct {
- const char *name;
- CM_SOLVER_ID id;
- int ( *init ) (struct Object *ob, struct ClothModifierData *clmd );
- int ( *solver ) (struct Object *ob, float framenr, struct ClothModifierData *clmd, struct ListBase *effectors );
- int ( *free ) (struct ClothModifierData *clmd );
-}
-CM_SOLVER_DEF;
+void cloth_parallel_transport_hair_frame(float mat[3][3], const float dir_old[3], const float dir_new[3]);
+////////////////////////////////////////////////
#endif
diff --git a/source/blender/blenkernel/BKE_collision.h b/source/blender/blenkernel/BKE_collision.h
index ec257a2f394..d5b4a584ec6 100644
--- a/source/blender/blenkernel/BKE_collision.h
+++ b/source/blender/blenkernel/BKE_collision.h
@@ -43,16 +43,13 @@
#include "BLI_kdopbvh.h"
-struct Cloth;
-struct ClothModifierData;
struct CollisionModifierData;
-struct DerivedMesh;
struct Group;
struct MFace;
struct MVert;
struct Object;
struct Scene;
-struct LinkNode;
+struct MVertTri;
////////////////////////////////////////
// used for collisions in collision.c
@@ -81,6 +78,8 @@ typedef struct CollPair {
float pa[3], pb[3]; // collision point p1 on face1, p2 on face2
int flag;
float time; // collision time, from 0 up to 1
+
+ /* mesh-mesh collision */
#ifdef WITH_ELTOPO /*either ap* or bp* can be set, but not both*/
float bary[3];
int ap1, ap2, ap3, collp, bp1, bp2, bp3;
@@ -126,8 +125,15 @@ FaceCollPair;
// used in modifier.c from collision.c
/////////////////////////////////////////////////
-BVHTree *bvhtree_build_from_mvert(struct MFace *mfaces, unsigned int numfaces, struct MVert *x, unsigned int numverts, float epsilon);
-void bvhtree_update_from_mvert(BVHTree *bvhtree, struct MFace *faces, int numfaces, struct MVert *x, struct MVert *xnew, int numverts, int moving);
+BVHTree *bvhtree_build_from_mvert(
+ const struct MVert *mvert,
+ const struct MVertTri *tri, int tri_num,
+ float epsilon);
+void bvhtree_update_from_mvert(
+ BVHTree *bvhtree,
+ const struct MVert *mvert, const struct MVert *mvert_moving,
+ const struct MVertTri *tri, int tri_num,
+ bool moving);
/////////////////////////////////////////////////
@@ -135,6 +141,8 @@ void bvhtree_update_from_mvert(BVHTree *bvhtree, struct MFace *faces, int numfac
// defined in collisions.c
void collision_move_object(struct CollisionModifierData *collmd, float step, float prevstep);
+void collision_get_collider_velocity(float vel_old[3], float vel_new[3], struct CollisionModifierData *collmd, struct CollPair *collpair);
+
/////////////////////////////////////////////////
// used in effect.c
/////////////////////////////////////////////////
diff --git a/source/blender/blenkernel/BKE_colortools.h b/source/blender/blenkernel/BKE_colortools.h
index 9234625a37c..74a327c3808 100644
--- a/source/blender/blenkernel/BKE_colortools.h
+++ b/source/blender/blenkernel/BKE_colortools.h
@@ -103,5 +103,6 @@ void BKE_color_managed_view_settings_free(struct ColorManagedViewSettings *setti
void BKE_color_managed_colorspace_settings_init(struct ColorManagedColorspaceSettings *colorspace_settings);
void BKE_color_managed_colorspace_settings_copy(struct ColorManagedColorspaceSettings *colorspace_settings,
const struct ColorManagedColorspaceSettings *settings);
-
+bool BKE_color_managed_colorspace_settings_equals(const struct ColorManagedColorspaceSettings *settings1,
+ const struct ColorManagedColorspaceSettings *settings2);
#endif
diff --git a/source/blender/blenkernel/BKE_constraint.h b/source/blender/blenkernel/BKE_constraint.h
index 87da74dc119..f3cfb901154 100644
--- a/source/blender/blenkernel/BKE_constraint.h
+++ b/source/blender/blenkernel/BKE_constraint.h
@@ -108,8 +108,8 @@ typedef struct bConstraintTypeInfo {
} bConstraintTypeInfo;
/* Function Prototypes for bConstraintTypeInfo's */
-bConstraintTypeInfo *BKE_constraint_typeinfo_get(struct bConstraint *con);
-bConstraintTypeInfo *BKE_constraint_typeinfo_from_type(int type);
+const bConstraintTypeInfo *BKE_constraint_typeinfo_get(struct bConstraint *con);
+const bConstraintTypeInfo *BKE_constraint_typeinfo_from_type(int type);
/* ---------------------------------------------------------------------------- */
@@ -118,10 +118,12 @@ bConstraintTypeInfo *BKE_constraint_typeinfo_from_type(int type);
void BKE_constraint_unique_name(struct bConstraint *con, struct ListBase *list);
void BKE_constraints_free(struct ListBase *list);
+void BKE_constraints_free_ex(struct ListBase *list, bool do_id_user);
void BKE_constraints_copy(struct ListBase *dst, const struct ListBase *src, bool do_extern);
void BKE_constraints_relink(struct ListBase *list);
void BKE_constraints_id_loop(struct ListBase *list, ConstraintIDFunc func, void *userdata);
void BKE_constraint_free_data(struct bConstraint *con);
+void BKE_constraint_free_data_ex(struct bConstraint *con, bool do_id_user);
/* Constraint API function prototypes */
struct bConstraint *BKE_constraints_active_get(struct ListBase *list);
@@ -131,6 +133,7 @@ struct bConstraint *BKE_constraints_find_name(struct ListBase *list, const char
struct bConstraint *BKE_constraint_add_for_object(struct Object *ob, const char *name, short type);
struct bConstraint *BKE_constraint_add_for_pose(struct Object *ob, struct bPoseChannel *pchan, const char *name, short type);
+bool BKE_constraint_remove_ex(ListBase *list, struct Object *ob, struct bConstraint *con, bool clear_dep);
bool BKE_constraint_remove(ListBase *list, struct bConstraint *con);
/* Constraints + Proxies function prototypes */
@@ -141,7 +144,8 @@ bool BKE_constraints_proxylocked_owner(struct Object *ob, struct bPoseChannel *p
struct bConstraintOb *BKE_constraints_make_evalob(struct Scene *scene, struct Object *ob, void *subdata, short datatype);
void BKE_constraints_clear_evalob(struct bConstraintOb *cob);
-void BKE_constraint_mat_convertspace(struct Object *ob, struct bPoseChannel *pchan, float mat[4][4], short from, short to);
+void BKE_constraint_mat_convertspace(
+ struct Object *ob, struct bPoseChannel *pchan, float mat[4][4], short from, short to, const bool keep_scale);
void BKE_constraint_target_matrix_get(struct Scene *scene, struct bConstraint *con, int n, short ownertype, void *ownerdata, float mat[4][4], float ctime);
void BKE_constraint_targets_for_solving_get(struct bConstraint *con, struct bConstraintOb *ob, struct ListBase *targets, float ctime);
diff --git a/source/blender/blenkernel/BKE_context.h b/source/blender/blenkernel/BKE_context.h
index 877e376b343..f7af3a7f8ec 100644
--- a/source/blender/blenkernel/BKE_context.h
+++ b/source/blender/blenkernel/BKE_context.h
@@ -53,9 +53,11 @@ struct StructRNA;
struct ToolSettings;
struct Image;
struct Text;
-struct ImBuf;
struct EditBone;
struct bPoseChannel;
+struct bGPdata;
+struct bGPDlayer;
+struct bGPDframe;
struct wmWindow;
struct wmWindowManager;
struct SpaceText;
@@ -275,6 +277,14 @@ struct bPoseChannel *CTX_data_active_pose_bone(const bContext *C);
int CTX_data_selected_pose_bones(const bContext *C, ListBase *list);
int CTX_data_visible_pose_bones(const bContext *C, ListBase *list);
+struct bGPdata *CTX_data_gpencil_data(const bContext *C);
+struct bGPDlayer *CTX_data_active_gpencil_layer(const bContext *C);
+struct bGPDframe *CTX_data_active_gpencil_frame(const bContext *C);
+int CTX_data_visible_gpencil_layers(const bContext *C, ListBase *list);
+int CTX_data_editable_gpencil_layers(const bContext *C, ListBase *list);
+int CTX_data_editable_gpencil_strokes(const bContext *C, ListBase *list);
+
+
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/blenkernel/BKE_crazyspace.h b/source/blender/blenkernel/BKE_crazyspace.h
index 98bcdc5cfaa..ee6c5c57678 100644
--- a/source/blender/blenkernel/BKE_crazyspace.h
+++ b/source/blender/blenkernel/BKE_crazyspace.h
@@ -40,13 +40,22 @@ struct BMEditMesh;
struct Mesh;
/* crazyspace.c */
-float (*BKE_crazyspace_get_mapped_editverts(struct Scene *scene, struct Object *obedit))[3];
+float (*BKE_crazyspace_get_mapped_editverts(
+ struct Scene *scene, struct Object *obedit))[3];
void BKE_crazyspace_set_quats_editmesh(
struct BMEditMesh *em, float (*origcos)[3], float (*mappedcos)[3], float (*quats)[4],
const bool use_select);
-void BKE_crazyspace_set_quats_mesh(struct Mesh *me, float (*origcos)[3], float (*mappedcos)[3], float (*quats)[4]);
-int BKE_sculpt_get_first_deform_matrices(struct Scene *scene, struct Object *ob, float (**deformmats)[3][3], float (**deformcos)[3]);
-void BKE_crazyspace_build_sculpt(struct Scene *scene, struct Object *ob, float (**deformmats)[3][3], float (**deformcos)[3]);
+void BKE_crazyspace_set_quats_mesh(
+ struct Mesh *me, float (*origcos)[3], float (*mappedcos)[3], float (*quats)[4]);
+int BKE_crazyspace_get_first_deform_matrices_editbmesh(
+ struct Scene *, struct Object *, struct BMEditMesh *em,
+ float (**deformmats)[3][3], float (**deformcos)[3]);
+int BKE_sculpt_get_first_deform_matrices(
+ struct Scene *scene, struct Object *ob,
+ float (**deformmats)[3][3], float (**deformcos)[3]);
+void BKE_crazyspace_build_sculpt(
+ struct Scene *scene, struct Object *ob,
+ float (**deformmats)[3][3], float (**deformcos)[3]);
#ifdef __cplusplus
}
diff --git a/source/blender/blenkernel/BKE_curve.h b/source/blender/blenkernel/BKE_curve.h
index 5de7d9936e6..a03dd287146 100644
--- a/source/blender/blenkernel/BKE_curve.h
+++ b/source/blender/blenkernel/BKE_curve.h
@@ -33,7 +33,6 @@
* \author nzc
*/
-struct BevList;
struct BezTriple;
struct Curve;
struct EditNurb;
@@ -49,6 +48,7 @@ struct rctf;
typedef struct CurveCache {
ListBase disp;
ListBase bev;
+ ListBase deformed_nurbs;
struct Path *path;
} CurveCache;
@@ -84,19 +84,21 @@ void BKE_curve_texspace_get(struct Curve *cu, float r_loc[3], float r_rot[3], fl
bool BKE_curve_minmax(struct Curve *cu, bool use_radius, float min[3], float max[3]);
bool BKE_curve_center_median(struct Curve *cu, float cent[3]);
bool BKE_curve_center_bounds(struct Curve *cu, float cent[3]);
-void BKE_curve_transform_ex(struct Curve *cu, float mat[4][4], bool do_keys, const float unit_scale);
-void BKE_curve_transform(struct Curve *cu, float mat[4][4], bool do_keys);
+void BKE_curve_transform_ex(struct Curve *cu, float mat[4][4], const bool do_keys, const float unit_scale);
+void BKE_curve_transform(struct Curve *cu, float mat[4][4], const bool do_keys);
void BKE_curve_translate(struct Curve *cu, float offset[3], const bool do_keys);
void BKE_curve_material_index_remove(struct Curve *cu, int index);
void BKE_curve_material_index_clear(struct Curve *cu);
int BKE_curve_material_index_validate(struct Curve *cu);
+void BKE_curve_material_remap(struct Curve *cu, const unsigned int *remap, unsigned int remap_len);
ListBase *BKE_curve_nurbs_get(struct Curve *cu);
-void BKE_curve_nurb_active_set(struct Curve *cu, struct Nurb *nu);
+int BKE_curve_nurb_vert_index_get(const struct Nurb *nu, const void *vert);
+void BKE_curve_nurb_active_set(struct Curve *cu, const struct Nurb *nu);
struct Nurb *BKE_curve_nurb_active_get(struct Curve *cu);
void *BKE_curve_vert_active_get(struct Curve *cu);
-void BKE_curve_nurb_vert_active_set(struct Curve *cu, struct Nurb *nu, void *vert);
+void BKE_curve_nurb_vert_active_set(struct Curve *cu, const struct Nurb *nu, const void *vert);
bool BKE_curve_nurb_vert_active_get(struct Curve *cu, struct Nurb **r_nu, void **r_vert);
void BKE_curve_nurb_vert_active_validate(struct Curve *cu);
@@ -119,6 +121,7 @@ void BKE_curve_bevel_make(struct Scene *scene, struct Object *ob, struct ListBa
const bool for_render, const bool use_render_resolution);
void BKE_curve_forward_diff_bezier(float q0, float q1, float q2, float q3, float *p, int it, int stride);
+void BKE_curve_forward_diff_tangent_bezier(float q0, float q1, float q2, float q3, float *p, int it, int stride);
void BKE_curve_rect_from_textbox(const struct Curve *cu, const struct TextBox *tb, struct rctf *r_rect);
@@ -164,6 +167,9 @@ bool BKE_nurb_type_convert(struct Nurb *nu, const short type, const bool use_han
void BKE_nurb_points_add(struct Nurb *nu, int number);
void BKE_nurb_bezierPoints_add(struct Nurb *nu, int number);
+int BKE_nurb_index_from_uv(struct Nurb *nu, int u, int v);
+void BKE_nurb_index_to_uv(struct Nurb *nu, int index, int *r_u, int *r_v);
+
struct BezTriple *BKE_nurb_bezt_get_next(struct Nurb *nu, struct BezTriple *bezt);
struct BezTriple *BKE_nurb_bezt_get_prev(struct Nurb *nu, struct BezTriple *bezt);
struct BPoint *BKE_nurb_bpoint_get_next(struct Nurb *nu, struct BPoint *bp);
@@ -172,13 +178,26 @@ struct BPoint *BKE_nurb_bpoint_get_prev(struct Nurb *nu, struct BPoint *bp);
void BKE_nurb_bezt_calc_normal(struct Nurb *nu, struct BezTriple *bezt, float r_normal[3]);
void BKE_nurb_bezt_calc_plane(struct Nurb *nu, struct BezTriple *bezt, float r_plane[3]);
+void BKE_nurb_bpoint_calc_normal(struct Nurb *nu, struct BPoint *bp, float r_normal[3]);
+
void BKE_nurb_handle_calc(struct BezTriple *bezt, struct BezTriple *prev, struct BezTriple *next,
const bool is_fcurve);
void BKE_nurb_handle_calc_simple(struct Nurb *nu, struct BezTriple *bezt);
+void BKE_nurb_handle_calc_simple_auto(struct Nurb *nu, struct BezTriple *bezt);
void BKE_nurb_handles_calc(struct Nurb *nu);
void BKE_nurb_handles_autocalc(struct Nurb *nu, int flag);
void BKE_nurb_bezt_handle_test(struct BezTriple *bezt, const bool use_handle);
void BKE_nurb_handles_test(struct Nurb *nu, const bool use_handles);
+/* **** Depsgraph evaluation **** */
+
+struct EvaluationContext;
+
+void BKE_curve_eval_geometry(struct EvaluationContext *eval_ctx,
+ struct Curve *curve);
+
+void BKE_curve_eval_path(struct EvaluationContext *eval_ctx,
+ struct Curve *curve);
+
#endif /* __BKE_CURVE_H__ */
diff --git a/source/blender/blenkernel/BKE_customdata.h b/source/blender/blenkernel/BKE_customdata.h
index 9a6524cc9ab..3e784752f10 100644
--- a/source/blender/blenkernel/BKE_customdata.h
+++ b/source/blender/blenkernel/BKE_customdata.h
@@ -41,10 +41,11 @@ extern "C" {
#include "BLI_sys_types.h"
#include "BLI_utildefines.h"
+#include "DNA_customdata_types.h"
+
struct BMesh;
struct ID;
struct CustomData;
-struct CustomDataLayer;
typedef uint64_t CustomDataMask;
/*a data type large enough to hold 1 element from any customdata layer type*/
@@ -77,6 +78,9 @@ extern const CustomDataMask CD_MASK_EVERYTHING;
void customData_mask_layers__print(CustomDataMask mask);
+typedef void (*cd_interp)(const void **sources, const float *weights, const float *sub_weights, int count, void *dest);
+typedef void (*cd_copy)(const void *source, void *dest, int count);
+
/**
* Checks if the layer at physical offset \a layer_n (in data->layers) support math
* the below operations.
@@ -91,11 +95,19 @@ bool CustomData_has_math(const struct CustomData *data);
bool CustomData_has_interp(const struct CustomData *data);
bool CustomData_bmesh_has_free(const struct CustomData *data);
+/**
+ * Checks if any of the customdata layers is referenced.
+ */
+bool CustomData_has_referenced(const struct CustomData *data);
+
/* copies the "value" (e.g. mloopuv uv or mloopcol colors) from one block to
* another, while not overwriting anything else (e.g. flags). probably only
* implemented for mloopuv/mloopcol, for now.*/
void CustomData_data_copy_value(int type, const void *source, void *dest);
+/* Same as above, but doing advanced mixing. Only available for a few types of data (like colors...). */
+void CustomData_data_mix_value(int type, const void *source, void *dest, const int mixmode, const float mixfactor);
+
/* compares if data1 is equal to data2. type is a valid CustomData type
* enum (e.g. CD_MLOOPUV). the layer type's equal function is used to compare
* the data, if it exists, otherwise memcmp is used.*/
@@ -119,11 +131,20 @@ void CustomData_update_typemap(struct CustomData *data);
bool CustomData_merge(const struct CustomData *source, struct CustomData *dest,
CustomDataMask mask, int alloctype, int totelem);
+/* Reallocate custom data to a new element count.
+ * Only affects on data layers which are owned by the CustomData itself,
+ * referenced data is kept unchanged,
+ *
+ * NOTE: Take care of referenced layers by yourself!
+ */
+void CustomData_realloc(struct CustomData *data, int totelem);
+
/* bmesh version of CustomData_merge; merges the layouts of source and dest,
* then goes through the mesh and makes sure all the customdata blocks are
* consistent with the new layout.*/
-bool CustomData_bmesh_merge(struct CustomData *source, struct CustomData *dest,
- CustomDataMask mask, int alloctype, struct BMesh *bm, const char htype);
+bool CustomData_bmesh_merge(
+ const struct CustomData *source, struct CustomData *dest,
+ CustomDataMask mask, int alloctype, struct BMesh *bm, const char htype);
/** NULL's all members and resets the typemap. */
void CustomData_reset(struct CustomData *data);
@@ -133,6 +154,9 @@ void CustomData_reset(struct CustomData *data);
*/
void CustomData_free(struct CustomData *data, int totelem);
+/* same as above, but only frees layers which matches the given mask. */
+void CustomData_free_typemask(struct CustomData *data, int totelem, CustomDataMask mask);
+
/* frees all layers with CD_FLAG_TEMPORARY */
void CustomData_free_temporary(struct CustomData *data, int totelem);
@@ -173,6 +197,7 @@ int CustomData_number_of_layers_typemask(const struct CustomData *data, CustomDa
/* duplicate data of a layer with flag NOFREE, and remove that flag.
* returns the layer data */
void *CustomData_duplicate_referenced_layer(struct CustomData *data, const int type, const int totelem);
+void *CustomData_duplicate_referenced_layer_n(struct CustomData *data, const int type, const int n, const int totelem);
void *CustomData_duplicate_referenced_layer_named(struct CustomData *data,
const int type, const char *name, const int totelem);
bool CustomData_is_referenced_layer(struct CustomData *data, int type);
@@ -195,7 +220,7 @@ void CustomData_copy_data(const struct CustomData *source,
void CustomData_copy_data_named(const struct CustomData *source,
struct CustomData *dest, int source_index,
int dest_index, int count);
-void CustomData_copy_elements(int type, void *source, void *dest, int count);
+void CustomData_copy_elements(int type, void *src_data_ofs, void *dst_data_ofs, int count);
void CustomData_bmesh_copy_data(const struct CustomData *source,
struct CustomData *dest, void *src_block,
void **dest_block);
@@ -217,14 +242,17 @@ void CustomData_free_elem(struct CustomData *data, int index, int count);
* count gives the number of source elements to interpolate from
* dest_index gives the dest element to write the interpolated value to
*/
-void CustomData_interp(const struct CustomData *source, struct CustomData *dest,
- int *src_indices, float *weights, float *sub_weights,
- int count, int dest_index);
-void CustomData_bmesh_interp_n(struct CustomData *data, void **src_blocks, const float *weights,
- const float *sub_weights, int count, void *dest_block, int n);
-void CustomData_bmesh_interp(struct CustomData *data, void **src_blocks,
- const float *weights, const float *sub_weights, int count,
- void *dest_block);
+void CustomData_interp(
+ const struct CustomData *source, struct CustomData *dest,
+ int *src_indices, float *weights, float *sub_weights,
+ int count, int dest_index);
+void CustomData_bmesh_interp_n(
+ struct CustomData *data, const void **src_blocks, const float *weights,
+ const float *sub_weights, int count, void *dst_block_ofs, int n);
+void CustomData_bmesh_interp(
+ struct CustomData *data, const void **src_blocks,
+ const float *weights, const float *sub_weights, int count,
+ void *dst_block);
/* swaps the data in the element corners, to new corners with indices as
@@ -245,14 +273,14 @@ void *CustomData_bmesh_get_n(const struct CustomData *data, void *block, int typ
void *CustomData_bmesh_get_layer_n(const struct CustomData *data, void *block, int n);
bool CustomData_set_layer_name(const struct CustomData *data, int type, int n, const char *name);
+const char *CustomData_get_layer_name(const struct CustomData *data, int type, int n);
/* gets a pointer to the active or first layer of type
* returns NULL if there is no layer of type
*/
void *CustomData_get_layer(const struct CustomData *data, int type);
void *CustomData_get_layer_n(const struct CustomData *data, int type, int n);
-void *CustomData_get_layer_named(const struct CustomData *data, int type,
- const char *name);
+void *CustomData_get_layer_named(const struct CustomData *data, int type, const char *name);
int CustomData_get_offset(const struct CustomData *data, int type);
int CustomData_get_n_offset(const struct CustomData *data, int type, int n);
@@ -273,19 +301,23 @@ int CustomData_get_stencil_layer(const struct CustomData *data, int type);
* layer of type
* no effect if there is no layer of type
*/
-void CustomData_set(const struct CustomData *data, int index, int type,
- void *source);
+void CustomData_set(
+ const struct CustomData *data, int index, int type,
+ const void *source);
-void CustomData_bmesh_set(const struct CustomData *data, void *block, int type,
- void *source);
+void CustomData_bmesh_set(
+ const struct CustomData *data, void *block, int type,
+ const void *source);
-void CustomData_bmesh_set_n(struct CustomData *data, void *block, int type, int n,
- void *source);
+void CustomData_bmesh_set_n(
+ struct CustomData *data, void *block, int type, int n,
+ const void *source);
/* sets the data of the block at physical layer n. no real type checking
* is performed.
*/
-void CustomData_bmesh_set_layer_n(struct CustomData *data, void *block, int n,
- void *source);
+void CustomData_bmesh_set_layer_n(
+ struct CustomData *data, void *block, int n,
+ const void *source);
/* set the pointer of to the first layer of type. the old data is not freed.
* returns the value of ptr if the layer is found, NULL otherwise
@@ -319,6 +351,9 @@ void CustomData_to_bmesh_block(const struct CustomData *source,
void CustomData_from_bmesh_block(const struct CustomData *source,
struct CustomData *dest, void *src_block, int dest_index);
+void CustomData_file_write_prepare(
+ struct CustomData *data,
+ struct CustomDataLayer **r_write_layers, struct CustomDataLayer *write_layers_buff, size_t write_layers_size);
/* query info over types */
void CustomData_file_write_info(int type, const char **structname, int *structnum);
@@ -327,6 +362,7 @@ int CustomData_sizeof(int type);
/* get the name of a layer type */
const char *CustomData_layertype_name(int type);
bool CustomData_layertype_is_singleton(int type);
+int CustomData_layertype_layers_max(const int type);
/* make sure the name of layer at index is unique */
void CustomData_set_layer_unique_name(struct CustomData *data, int index);
@@ -345,6 +381,10 @@ void CustomData_bmesh_update_active_layers(struct CustomData *fdata, struct Cust
void CustomData_bmesh_do_versions_update_active_layers(struct CustomData *fdata, struct CustomData *pdata, struct CustomData *ldata);
void CustomData_bmesh_init_pool(struct CustomData *data, int totelem, const char htype);
+#ifndef NDEBUG
+bool CustomData_from_bmeshpoly_test(CustomData *fdata, CustomData *pdata, CustomData *ldata, bool fallback);
+#endif
+
/* External file storage */
void CustomData_external_add(struct CustomData *data,
@@ -360,6 +400,84 @@ void CustomData_external_read(struct CustomData *data,
void CustomData_external_reload(struct CustomData *data,
struct ID *id, CustomDataMask mask, int totelem);
+/* Mesh-to-mesh transfer data. */
+
+struct MeshPairRemap;
+struct CustomDataTransferLayerMap;
+
+typedef void (*cd_datatransfer_interp)(
+ const struct CustomDataTransferLayerMap *laymap, void *dest,
+ const void **sources, const float *weights, const int count, const float mix_factor);
+
+/**
+ * Fake CD_LAYERS (those are actually 'real' data stored directly into elements' structs, or otherwise not (directly)
+ * accessible to usual CDLayer system). */
+enum {
+ CD_FAKE = 1 << 8,
+
+ /* Vertices. */
+ CD_FAKE_MDEFORMVERT = CD_FAKE | CD_MDEFORMVERT, /* *sigh* due to how vgroups are stored :( . */
+ CD_FAKE_SHAPEKEY = CD_FAKE | CD_SHAPEKEY, /* Not available as real CD layer in non-bmesh context. */
+
+ /* Edges. */
+ CD_FAKE_SEAM = CD_FAKE | 100, /* UV seam flag for edges. */
+ CD_FAKE_CREASE = CD_FAKE | CD_CREASE, /* *sigh*. */
+
+ /* Multiple types of mesh elements... */
+ CD_FAKE_BWEIGHT = CD_FAKE | CD_BWEIGHT, /* *sigh*. */
+ CD_FAKE_UV = CD_FAKE | CD_MLOOPUV, /* UV flag, because we handle both loop's UVs and poly's textures. */
+
+ CD_FAKE_LNOR = CD_FAKE | CD_CUSTOMLOOPNORMAL, /* Because we play with clnor and temp lnor layers here. */
+
+ CD_FAKE_SHARP = CD_FAKE | 200, /* Sharp flag for edges, smooth flag for faces. */
+};
+
+enum {
+ ME_VERT = 1 << 0,
+ ME_EDGE = 1 << 1,
+ ME_POLY = 1 << 2,
+ ME_LOOP = 1 << 3,
+};
+
+/**
+ * How to filter out some elements (to leave untouched).
+ * Note those options are highly dependent on type of transferred data! */
+enum {
+ CDT_MIX_NOMIX = -1, /* Special case, only used because we abuse 'copy' CD callback. */
+ CDT_MIX_TRANSFER = 0,
+ CDT_MIX_REPLACE_ABOVE_THRESHOLD = 1,
+ CDT_MIX_REPLACE_BELOW_THRESHOLD = 2,
+ CDT_MIX_MIX = 16,
+ CDT_MIX_ADD = 17,
+ CDT_MIX_SUB = 18,
+ CDT_MIX_MUL = 19,
+ /* etc. etc. */
+};
+
+typedef struct CustomDataTransferLayerMap {
+ struct CustomDataTransferLayerMap *next, *prev;
+
+ int data_type;
+ int mix_mode;
+ float mix_factor;
+ const float *mix_weights; /* If non-NULL, array of weights, one for each dest item, replaces mix_factor. */
+
+ const void *data_src; /* Data source array (can be regular CD data, vertices/edges/etc., keyblocks...). */
+ void *data_dst; /* Data dest array (same type as dat_src). */
+ int data_src_n; /* Index to affect in data_src (used e.g. for vgroups). */
+ int data_dst_n; /* Index to affect in data_dst (used e.g. for vgroups). */
+ size_t elem_size; /* Size of one element of data_src/data_dst. */
+
+ size_t data_size; /* Size of actual data we transfer. */
+ size_t data_offset; /* Offset of actual data we transfer (in element contained in data_src/dst). */
+ uint64_t data_flag; /* For bitflag transfer, flag(s) to affect in transfered data. */
+
+ cd_datatransfer_interp interp;
+} CustomDataTransferLayerMap;
+
+/* Those functions assume src_n and dst_n layers of given type exist in resp. src and dst. */
+void CustomData_data_transfer(const struct MeshPairRemap *me_remap, const CustomDataTransferLayerMap *laymap);
+
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/blenkernel/BKE_customdata_file.h b/source/blender/blenkernel/BKE_customdata_file.h
index 978db8a6c1a..242897f968f 100644
--- a/source/blender/blenkernel/BKE_customdata_file.h
+++ b/source/blender/blenkernel/BKE_customdata_file.h
@@ -40,14 +40,14 @@ void cdf_free(CDataFile *cdf);
/* File read/write/remove */
-int cdf_read_open(CDataFile *cdf, const char *filename);
-int cdf_read_layer(CDataFile *cdf, CDataFileLayer *blay);
-int cdf_read_data(CDataFile *cdf, unsigned int size, void *data);
+bool cdf_read_open(CDataFile *cdf, const char *filename);
+bool cdf_read_layer(CDataFile *cdf, CDataFileLayer *blay);
+bool cdf_read_data(CDataFile *cdf, unsigned int size, void *data);
void cdf_read_close(CDataFile *cdf);
-int cdf_write_open(CDataFile *cdf, const char *filename);
-int cdf_write_layer(CDataFile *cdf, CDataFileLayer *blay);
-int cdf_write_data(CDataFile *cdf, unsigned int size, void *data);
+bool cdf_write_open(CDataFile *cdf, const char *filename);
+bool cdf_write_layer(CDataFile *cdf, CDataFileLayer *blay);
+bool cdf_write_data(CDataFile *cdf, unsigned int size, void *data);
void cdf_write_close(CDataFile *cdf);
void cdf_remove(const char *filename);
diff --git a/source/blender/blenkernel/BKE_data_transfer.h b/source/blender/blenkernel/BKE_data_transfer.h
new file mode 100644
index 00000000000..2ee9d8d2408
--- /dev/null
+++ b/source/blender/blenkernel/BKE_data_transfer.h
@@ -0,0 +1,159 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2014 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Bastien Montagne
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/blenkernel/BKE_data_transfer.h
+ * \ingroup bke
+ */
+
+#ifndef __BKE_DATA_TRANSFER_H__
+#define __BKE_DATA_TRANSFER_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "BKE_customdata.h"
+
+struct Object;
+struct Scene;
+struct SpaceTransform;
+struct ReportList;
+
+/* Warning, those def are stored in files (TransferData modifier), *DO NOT* modify those values. */
+enum {
+ DT_TYPE_MDEFORMVERT = 1 << 0,
+ DT_TYPE_SHAPEKEY = 1 << 1,
+ DT_TYPE_SKIN = 1 << 2,
+ DT_TYPE_BWEIGHT_VERT = 1 << 3,
+
+ DT_TYPE_SHARP_EDGE = 1 << 8,
+ DT_TYPE_SEAM = 1 << 9,
+ DT_TYPE_CREASE = 1 << 10,
+ DT_TYPE_BWEIGHT_EDGE = 1 << 11,
+ DT_TYPE_FREESTYLE_EDGE = 1 << 12,
+
+ DT_TYPE_VCOL = 1 << 16,
+ DT_TYPE_LNOR = 1 << 17,
+
+ DT_TYPE_UV = 1 << 24,
+ DT_TYPE_SHARP_FACE = 1 << 25,
+ DT_TYPE_FREESTYLE_FACE = 1 << 26,
+#define \
+ DT_TYPE_MAX 27
+
+ DT_TYPE_VERT_ALL = DT_TYPE_MDEFORMVERT | DT_TYPE_SHAPEKEY | DT_TYPE_SKIN | DT_TYPE_BWEIGHT_VERT,
+ DT_TYPE_EDGE_ALL = DT_TYPE_SHARP_EDGE | DT_TYPE_SEAM | DT_TYPE_CREASE | DT_TYPE_BWEIGHT_EDGE |
+ DT_TYPE_FREESTYLE_EDGE,
+ DT_TYPE_LOOP_ALL = DT_TYPE_VCOL | DT_TYPE_LNOR | DT_TYPE_UV,
+ DT_TYPE_POLY_ALL = DT_TYPE_UV | DT_TYPE_SHARP_FACE | DT_TYPE_FREESTYLE_FACE,
+};
+
+
+CustomDataMask BKE_object_data_transfer_dttypes_to_cdmask(const int dtdata_types);
+bool BKE_object_data_transfer_get_dttypes_capacity(
+ const int dtdata_types, bool *r_advanced_mixing, bool *r_threshold);
+int BKE_object_data_transfer_get_dttypes_item_types(const int dtdata_types);
+
+int BKE_object_data_transfer_dttype_to_cdtype(const int dtdata_type);
+int BKE_object_data_transfer_dttype_to_srcdst_index(const int dtdata_type);
+
+#define DT_DATATYPE_IS_VERT(_dt) \
+ ELEM(_dt, DT_TYPE_MDEFORMVERT, DT_TYPE_SHAPEKEY, DT_TYPE_SKIN, DT_TYPE_BWEIGHT_VERT)
+#define DT_DATATYPE_IS_EDGE(_dt) \
+ ELEM(_dt, DT_TYPE_CREASE, DT_TYPE_SHARP_EDGE, DT_TYPE_SEAM, DT_TYPE_BWEIGHT_EDGE, DT_TYPE_FREESTYLE_EDGE)
+#define DT_DATATYPE_IS_LOOP(_dt) \
+ ELEM(_dt, DT_TYPE_UV, DT_TYPE_VCOL, DT_TYPE_LNOR)
+#define DT_DATATYPE_IS_POLY(_dt) \
+ ELEM(_dt, DT_TYPE_UV, DT_TYPE_SHARP_FACE, DT_TYPE_FREESTYLE_FACE)
+
+#define DT_DATATYPE_IS_MULTILAYERS(_dt) \
+ ELEM(_dt, DT_TYPE_MDEFORMVERT, DT_TYPE_SHAPEKEY, DT_TYPE_VCOL, DT_TYPE_UV)
+
+
+enum {
+ DT_MULTILAYER_INDEX_INVALID = -1,
+ DT_MULTILAYER_INDEX_MDEFORMVERT = 0,
+ DT_MULTILAYER_INDEX_SHAPEKEY = 1,
+ DT_MULTILAYER_INDEX_VCOL = 2,
+ DT_MULTILAYER_INDEX_UV = 3,
+ DT_MULTILAYER_INDEX_MAX = 4,
+};
+
+/* Below we keep positive values for real layers idx (generated dynamically). */
+
+/* How to select data layers, for types supporting multi-layers.
+ * Here too, some options are highly dependent on type of transferred data! */
+enum {
+ DT_LAYERS_ACTIVE_SRC = -1,
+ DT_LAYERS_ALL_SRC = -2,
+ /* Datatype-specific. */
+ DT_LAYERS_VGROUP_SRC = 1 << 8,
+ DT_LAYERS_VGROUP_SRC_BONE_SELECT = -(DT_LAYERS_VGROUP_SRC | 1),
+ DT_LAYERS_VGROUP_SRC_BONE_DEFORM = -(DT_LAYERS_VGROUP_SRC | 2),
+ /* Other types-related modes... */
+};
+
+/* How to map a source layer to a destination layer, for types supporting multi-layers.
+ * Note: if no matching layer can be found, it will be created. */
+enum {
+ DT_LAYERS_ACTIVE_DST = -1, /* Only for DT_LAYERS_FROMSEL_ACTIVE. */
+ DT_LAYERS_NAME_DST = -2,
+ DT_LAYERS_INDEX_DST = -3,
+#if 0 /* TODO */
+ DT_LAYERS_CREATE_DST = -4, /* Never replace existing data in dst, always create new layers. */
+#endif
+};
+
+void BKE_object_data_transfer_layout(
+ struct Scene *scene, struct Object *ob_src, struct Object *ob_dst, const int data_types, const bool use_delete,
+ const int fromlayers_select[DT_MULTILAYER_INDEX_MAX], const int tolayers_select[DT_MULTILAYER_INDEX_MAX]);
+
+bool BKE_object_data_transfer_mesh(
+ struct Scene *scene,
+ struct Object *ob_src, struct Object *ob_dst, const int data_types, const bool use_create,
+ const int map_vert_mode, const int map_edge_mode, const int map_loop_mode, const int map_poly_mode,
+ struct SpaceTransform *space_transform, const bool auto_transform,
+ const float max_distance, const float ray_radius, const float islands_handling_precision,
+ const int fromlayers_select[DT_MULTILAYER_INDEX_MAX], const int tolayers_select[DT_MULTILAYER_INDEX_MAX],
+ const int mix_mode, const float mix_factor, const char *vgroup_name, const bool invert_vgroup,
+ struct ReportList *reports);
+bool BKE_object_data_transfer_dm(
+ struct Scene *scene,
+ struct Object *ob_src, struct Object *ob_dst, struct DerivedMesh *dm_dst,
+ const int data_types, bool use_create,
+ const int map_vert_mode, const int map_edge_mode, const int map_loop_mode, const int map_poly_mode,
+ struct SpaceTransform *space_transform, const bool auto_transform,
+ const float max_distance, const float ray_radius, const float islands_handling_precision,
+ const int fromlayers_select[DT_MULTILAYER_INDEX_MAX], const int tolayers_select[DT_MULTILAYER_INDEX_MAX],
+ const int mix_mode, const float mix_factor, const char *vgroup_name, const bool invert_vgroup,
+ struct ReportList *reports);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __BKE_DATA_TRANSFER_H__ */
diff --git a/source/blender/blenkernel/BKE_deform.h b/source/blender/blenkernel/BKE_deform.h
index e203549fef5..a45893b00fa 100644
--- a/source/blender/blenkernel/BKE_deform.h
+++ b/source/blender/blenkernel/BKE_deform.h
@@ -39,6 +39,9 @@ struct Object;
struct ListBase;
struct bDeformGroup;
struct MDeformVert;
+struct MEdge;
+struct MLoop;
+struct MPoly;
struct bDeformGroup *BKE_defgroup_new(struct Object *ob, const char *name);
void defgroup_copy_list(struct ListBase *lb1, struct ListBase *lb2);
@@ -85,6 +88,19 @@ void defvert_normalize_lock_map(struct MDeformVert *dvert,
const bool *vgroup_subset, const int vgroup_tot,
const bool *lock_flags, const int defbase_tot);
+/* Utilities to 'extract' a given vgroup into a simple float array, for verts, but also edges/polys/loops. */
+void BKE_defvert_extract_vgroup_to_vertweights(
+ struct MDeformVert *dvert, const int defgroup, const int num_verts, float *r_weights, const bool invert_vgroup);
+void BKE_defvert_extract_vgroup_to_edgeweights(
+ struct MDeformVert *dvert, const int defgroup, const int num_verts, struct MEdge *edges, const int num_edges,
+ float *r_weights, const bool invert_vgroup);
+void BKE_defvert_extract_vgroup_to_loopweights(
+ struct MDeformVert *dvert, const int defgroup, const int num_verts, struct MLoop *loops, const int num_loops,
+ float *r_weights, const bool invert_vgroup);
+void BKE_defvert_extract_vgroup_to_polyweights(
+ struct MDeformVert *dvert, const int defgroup, const int num_verts, struct MLoop *loops, const int num_loops,
+ struct MPoly *polys, const int num_polys, float *r_weights, const bool invert_vgroup);
+
/* utility function, note that MAX_VGROUP_NAME chars is the maximum string length since its only
* used with defgroups currently */
diff --git a/source/blender/blenkernel/BKE_depsgraph.h b/source/blender/blenkernel/BKE_depsgraph.h
index 2ac5e5eb4be..40564aeabe9 100644
--- a/source/blender/blenkernel/BKE_depsgraph.h
+++ b/source/blender/blenkernel/BKE_depsgraph.h
@@ -48,7 +48,6 @@ struct ID;
struct Main;
struct Object;
struct Scene;
-struct ListBase;
/* Dependency graph evaluation context
*
@@ -57,12 +56,13 @@ struct ListBase;
*/
typedef struct EvaluationContext {
int mode; /* evaluation mode */
+ float ctime; /* evaluation time */
} EvaluationContext;
typedef enum eEvaluationMode {
DAG_EVAL_VIEWPORT = 0, /* evaluate for OpenGL viewport */
- DAG_EVAL_PREVIEW = 1, /* evaluate for render with preview settings */
- DAG_EVAL_RENDER = 2, /* evaluate for render purposes */
+ DAG_EVAL_PREVIEW = 1, /* evaluate for render with preview settings */
+ DAG_EVAL_RENDER = 2, /* evaluate for render purposes */
} eEvaluationMode;
/* DagNode->eval_flags */
@@ -72,6 +72,10 @@ enum {
* who're using curve deform, where_on_path and so.
*/
DAG_EVAL_NEED_CURVE_PATH = 1,
+ /* Scene evaluation would need to have object's data on CPU,
+ * meaning no GPU shortcuts is allowed.
+ */
+ DAG_EVAL_NEED_CPU = 2,
};
/* Global initialization/deinitialization */
@@ -92,6 +96,7 @@ void DAG_exit(void);
*/
void DAG_scene_relations_update(struct Main *bmain, struct Scene *sce);
+void DAG_scene_relations_validate(struct Main *bmain, struct Scene *sce);
void DAG_relations_tag_update(struct Main *bmain);
void DAG_scene_relations_rebuild(struct Main *bmain, struct Scene *scene);
void DAG_scene_free(struct Scene *sce);
@@ -142,7 +147,10 @@ void DAG_pose_sort(struct Object *ob);
/* Editors: callbacks to notify editors of datablock changes */
void DAG_editors_update_cb(void (*id_func)(struct Main *bmain, struct ID *id),
- void (*scene_func)(struct Main *bmain, struct Scene *scene, int updated));
+ void (*scene_func)(struct Main *bmain, struct Scene *scene, int updated),
+ void (*scene_pre_func)(struct Main *bmain, struct Scene *scene, bool time));
+
+void DAG_editors_update_pre(struct Main *bmain, struct Scene *scene, bool time);
/* ** Threaded update ** */
diff --git a/source/blender/blenkernel/BKE_displist.h b/source/blender/blenkernel/BKE_displist.h
index 0afc457f2b5..3b096773d96 100644
--- a/source/blender/blenkernel/BKE_displist.h
+++ b/source/blender/blenkernel/BKE_displist.h
@@ -53,14 +53,9 @@
/* prototypes */
-struct Base;
struct Scene;
struct Object;
-struct Curve;
struct ListBase;
-struct Material;
-struct Bone;
-struct Mesh;
struct DerivedMesh;
struct EvaluationContext;
diff --git a/source/blender/blenkernel/BKE_dynamicpaint.h b/source/blender/blenkernel/BKE_dynamicpaint.h
index a8e152fd301..00256176d98 100644
--- a/source/blender/blenkernel/BKE_dynamicpaint.h
+++ b/source/blender/blenkernel/BKE_dynamicpaint.h
@@ -27,8 +27,6 @@
* \ingroup bke
*/
-struct bContext;
-struct wmOperator;
struct Scene;
/* Actual surface point */
@@ -47,12 +45,10 @@ typedef struct PaintPoint {
/* Wet paint is handled at effect layer only
* and mixed to surface when drying */
- float e_color[3];
- float e_alpha;
+ float e_color[4];
float wetness;
short state;
- float color[3];
- float alpha;
+ float color[4];
} PaintPoint;
/* heigh field waves */
@@ -70,8 +66,8 @@ void dynamicPaint_Modifier_copy(struct DynamicPaintModifierData *pmd, struct Dyn
bool dynamicPaint_createType(struct DynamicPaintModifierData *pmd, int type, struct Scene *scene);
struct DynamicPaintSurface *dynamicPaint_createNewSurface(struct DynamicPaintCanvasSettings *canvas, struct Scene *scene);
-void dynamicPaint_clearSurface(struct Scene *scene, struct DynamicPaintSurface *surface);
-bool dynamicPaint_resetSurface(struct Scene *scene, struct DynamicPaintSurface *surface);
+void dynamicPaint_clearSurface(const struct Scene *scene, struct DynamicPaintSurface *surface);
+bool dynamicPaint_resetSurface(const struct Scene *scene, struct DynamicPaintSurface *surface);
void dynamicPaint_freeSurface(struct DynamicPaintSurface *surface);
void dynamicPaint_freeCanvas(struct DynamicPaintModifierData *pmd);
void dynamicPaint_freeBrush(struct DynamicPaintModifierData *pmd);
diff --git a/source/blender/blenkernel/BKE_editmesh.h b/source/blender/blenkernel/BKE_editmesh.h
index 38c8cf12969..55a9db9b1e5 100644
--- a/source/blender/blenkernel/BKE_editmesh.h
+++ b/source/blender/blenkernel/BKE_editmesh.h
@@ -25,6 +25,10 @@
/** \file BKE_editmesh.h
* \ingroup bke
+ *
+ * The \link edmesh EDBM module\endlink is for editmode bmesh stuff.
+ * In contrast, the this module is for code shared with blenkernel thats
+ * only concerned with low level operations on the #BMEditMesh structure.
*/
#include "BKE_customdata.h"
@@ -32,20 +36,15 @@
struct BMesh;
struct BMLoop;
-struct BMFace;
struct Mesh;
struct Scene;
struct DerivedMesh;
struct MeshStatVis;
-/* ok: the EDBM module is for editmode bmesh stuff. in contrast, the
- * BMEdit module is for code shared with blenkernel that concerns
- * the BMEditMesh structure.
- */
-
-/* this structure replaces EditMesh.
+/**
+ * This structure is used for mesh edit-mode.
*
- * through this, you get access to both the edit bmesh,
+ * through this, you get access to both the edit #BMesh,
* it's tessellation, and various stuff that doesn't belong in the BMesh
* struct itself.
*
@@ -93,11 +92,12 @@ void BKE_editmesh_update_linked_customdata(BMEditMesh *em);
void BKE_editmesh_color_free(BMEditMesh *em);
void BKE_editmesh_color_ensure(BMEditMesh *em, const char htype);
+float (*BKE_editmesh_vertexCos_get_orco(BMEditMesh *em, int *r_numVerts))[3];
/* editderivedmesh.c */
/* should really be defined in editmesh.c, but they use 'EditDerivedBMesh' */
void BKE_editmesh_statvis_calc(BMEditMesh *em, struct DerivedMesh *dm,
- struct MeshStatVis *statvis);
+ const struct MeshStatVis *statvis);
float (*BKE_editmesh_vertexCos_get(struct BMEditMesh *em, struct Scene *scene, int *r_numVerts))[3];
diff --git a/source/blender/blenkernel/BKE_editmesh_bvh.h b/source/blender/blenkernel/BKE_editmesh_bvh.h
index 168f700d132..b21c5db2118 100644
--- a/source/blender/blenkernel/BKE_editmesh_bvh.h
+++ b/source/blender/blenkernel/BKE_editmesh_bvh.h
@@ -39,10 +39,11 @@ struct BMVert;
struct BMLoop;
struct BMBVHTree;
struct BVHTree;
-struct Scene;
typedef struct BMBVHTree BMBVHTree;
+typedef bool (*BMBVHTree_FaceFilter)(struct BMFace *f, void *userdata);
+
BMBVHTree *BKE_bmbvh_new_from_editmesh(
struct BMEditMesh *em, int flag,
const float (*cos_cage)[3], const bool cos_cage_free);
@@ -55,14 +56,21 @@ BMBVHTree *BKE_bmbvh_new(
const float (*cos_cage)[3], const bool cos_cage_free);
void BKE_bmbvh_free(BMBVHTree *tree);
struct BVHTree *BKE_bmbvh_tree_get(BMBVHTree *tree);
-struct BMFace *BKE_bmbvh_ray_cast(BMBVHTree *tree, const float co[3], const float dir[3], const float radius,
- float *r_dist, float r_hitout[3], float r_cagehit[3]);
-/* find a face intersecting a segment (but not apart of the segment) */
-struct BMFace *BKE_bmbvh_find_face_segment(BMBVHTree *tree, const float co_a[3], const float co_b[3],
- float *r_fac, float r_hitout[3], float r_cagehit[3]);
+
+struct BMFace *BKE_bmbvh_ray_cast(
+ BMBVHTree *tree, const float co[3], const float dir[3], const float radius,
+ float *r_dist, float r_hitout[3], float r_cagehit[3]);
+
+struct BMFace *BKE_bmbvh_ray_cast_filter(
+ BMBVHTree *tree, const float co[3], const float dir[3], const float radius,
+ float *r_dist, float r_hitout[3], float r_cagehit[3],
+ BMBVHTree_FaceFilter filter, void *filter_cb);
+
/* find a vert closest to co in a sphere of radius dist_max */
struct BMVert *BKE_bmbvh_find_vert_closest(BMBVHTree *tree, const float co[3], const float dist_max);
+struct BVHTreeOverlap *BKE_bmbvh_overlap(const BMBVHTree *bmtree_a, const BMBVHTree *bmtree_b, unsigned int *r_overlap_tot);
+
/* BKE_bmbvh_new flag parameter */
enum {
BMBVH_RETURN_ORIG = (1 << 0), /* use with 'cos_cage', returns hits in relation to original geometry */
diff --git a/source/blender/blenkernel/BKE_effect.h b/source/blender/blenkernel/BKE_effect.h
index d5e54d849cd..f8fee444d91 100644
--- a/source/blender/blenkernel/BKE_effect.h
+++ b/source/blender/blenkernel/BKE_effect.h
@@ -32,15 +32,15 @@
* \since March 2001
* \author nzc
*/
+
#include "DNA_modifier_types.h"
+#include "BLI_utildefines.h"
+
struct Object;
struct Scene;
-struct Effect;
struct ListBase;
-struct Particle;
struct Group;
-struct RNG;
struct ParticleSimulationData;
struct ParticleData;
struct ParticleKey;
@@ -136,6 +136,88 @@ int get_effector_data(struct EffectorCache *eff, struct EffectorData *efd, struc
/* EffectorData->flag */
#define PE_VELOCITY_TO_IMPULSE 1
+/* ======== Simulation Debugging ======== */
+
+#define SIM_DEBUG_HASH_BASE 5381
+
+unsigned int BKE_sim_debug_data_hash(int i);
+unsigned int BKE_sim_debug_data_hash_combine(unsigned int kx, unsigned int ky);
+
+/* _VA_SIM_DEBUG_HASH#(i, ...): combined hash value of multiple integers */
+/* internal helpers*/
+#define _VA_SIM_DEBUG_HASH1(a) \
+ (BKE_sim_debug_data_hash(a))
+#define _VA_SIM_DEBUG_HASH2(a, b) \
+ (BKE_sim_debug_data_hash_combine(BKE_sim_debug_data_hash(a), _VA_SIM_DEBUG_HASH1(b)))
+#define _VA_SIM_DEBUG_HASH3(a, b, c) \
+ (BKE_sim_debug_data_hash_combine(BKE_sim_debug_data_hash(a), _VA_SIM_DEBUG_HASH2(b, c)))
+#define _VA_SIM_DEBUG_HASH4(a, b, c, d) \
+ (BKE_sim_debug_data_hash_combine(BKE_sim_debug_data_hash(a), _VA_SIM_DEBUG_HASH3(b, c, d)))
+#define _VA_SIM_DEBUG_HASH5(a, b, c, d, e) \
+ (BKE_sim_debug_data_hash_combine(BKE_sim_debug_data_hash(a), _VA_SIM_DEBUG_HASH4(b, c, d, e)))
+#define _VA_SIM_DEBUG_HASH6(a, b, c, d, e, f) \
+ (BKE_sim_debug_data_hash_combine(BKE_sim_debug_data_hash(a), _VA_SIM_DEBUG_HASH5(b, c, d, e, f)))
+#define _VA_SIM_DEBUG_HASH7(a, b, c, d, e, f, g) \
+ (BKE_sim_debug_data_hash_combine(BKE_sim_debug_data_hash(a), _VA_SIM_DEBUG_HASH6(b, c, d, e, f, g)))
+#define _VA_SIM_DEBUG_HASH8(a, b, c, d, e, f, g, h) \
+ (BKE_sim_debug_data_hash_combine(BKE_sim_debug_data_hash(a), _VA_SIM_DEBUG_HASH7(b, c, d, e, f, g, h)))
+
+#define SIM_DEBUG_HASH(...) VA_NARGS_CALL_OVERLOAD(_VA_SIM_DEBUG_HASH, __VA_ARGS__)
+
+typedef struct SimDebugElement {
+ unsigned int category_hash;
+ unsigned int hash;
+
+ int type;
+ float color[3];
+
+ float v1[3], v2[3];
+} SimDebugElement;
+
+typedef enum eSimDebugElement_Type {
+ SIM_DEBUG_ELEM_DOT,
+ SIM_DEBUG_ELEM_CIRCLE,
+ SIM_DEBUG_ELEM_LINE,
+ SIM_DEBUG_ELEM_VECTOR,
+} eSimDebugElement_Type;
+
+typedef struct SimDebugData {
+ struct GHash *gh;
+} SimDebugData;
+
+extern SimDebugData *_sim_debug_data;
+
+void BKE_sim_debug_data_set_enabled(bool enable);
+bool BKE_sim_debug_data_get_enabled(void);
+void BKE_sim_debug_data_free(void);
+
+void BKE_sim_debug_data_add_element(int type, const float v1[3], const float v2[3],
+ float r, float g, float b, const char *category, unsigned int hash);
+void BKE_sim_debug_data_remove_element(unsigned int hash);
+
+#define BKE_sim_debug_data_add_dot(p, r, g, b, category, ...) { \
+ const float v2[3] = { 0.0f, 0.0f, 0.0f }; \
+ BKE_sim_debug_data_add_element(SIM_DEBUG_ELEM_DOT, p, v2, r, g, b, category, SIM_DEBUG_HASH(__VA_ARGS__)); \
+}
+
+#define BKE_sim_debug_data_add_circle(p, radius, r, g, b, category, ...) { \
+ const float v2[3] = { radius, 0.0f, 0.0f }; \
+ BKE_sim_debug_data_add_element(SIM_DEBUG_ELEM_CIRCLE, p, v2, r, g, b, category, SIM_DEBUG_HASH(__VA_ARGS__)); \
+}
+
+#define BKE_sim_debug_data_add_line(p1, p2, r, g, b, category, ...) { \
+ BKE_sim_debug_data_add_element(SIM_DEBUG_ELEM_LINE, p1, p2, r, g, b, category, SIM_DEBUG_HASH(__VA_ARGS__)); \
+}
+
+#define BKE_sim_debug_data_add_vector(p, d, r, g, b, category, ...) { \
+ BKE_sim_debug_data_add_element(SIM_DEBUG_ELEM_VECTOR, p, d, r, g, b, category, SIM_DEBUG_HASH(__VA_ARGS__)); \
+}
+
+#define BKE_sim_debug_data_remove(...) \
+ BKE_sim_debug_data_remove_element(SIM_DEBUG_HASH(__VA_ARGS__))
+
+void BKE_sim_debug_data_clear(void);
+void BKE_sim_debug_data_clear_category(const char *category);
#endif
diff --git a/source/blender/blenkernel/BKE_fcurve.h b/source/blender/blenkernel/BKE_fcurve.h
index 0e86be9b97c..443a03a475a 100644
--- a/source/blender/blenkernel/BKE_fcurve.h
+++ b/source/blender/blenkernel/BKE_fcurve.h
@@ -43,6 +43,8 @@ struct DriverVar;
struct DriverTarget;
struct FCM_EnvelopeData;
+struct bContext;
+struct AnimData;
struct bAction;
struct BezTriple;
struct StructRNA;
@@ -170,8 +172,8 @@ typedef enum eFMI_Requirement_Flags {
} eFMI_Requirement_Flags;
/* Function Prototypes for FModifierTypeInfo's */
-FModifierTypeInfo *fmodifier_get_typeinfo(struct FModifier *fcm);
-FModifierTypeInfo *get_fmodifier_typeinfo(int type);
+const FModifierTypeInfo *fmodifier_get_typeinfo(struct FModifier *fcm);
+const FModifierTypeInfo *get_fmodifier_typeinfo(int type);
/* ---------------------- */
@@ -221,8 +223,12 @@ struct FCurve *id_data_find_fcurve(ID *id, void *data, struct StructRNA *type, c
*/
int list_find_data_fcurves(ListBase *dst, ListBase *src, const char *dataPrefix, const char *dataName);
-/* find an f-curve based on an rna property */
-struct FCurve *rna_get_fcurve(struct PointerRNA *ptr, struct PropertyRNA *prop, int rnaindex, struct bAction **action, bool *r_driven);
+/* Find an f-curve based on an rna property. */
+struct FCurve *rna_get_fcurve(struct PointerRNA *ptr, struct PropertyRNA *prop, int rnaindex,
+ struct AnimData **adt, struct bAction **action, bool *r_driven, bool *r_special);
+/* Same as above, but takes a context data, temp hack needed for complex paths like texture ones. */
+struct FCurve *rna_get_fcurve_context_ui(struct bContext *C, struct PointerRNA *ptr, struct PropertyRNA *prop,
+ int rnaindex, struct AnimData **adt, struct bAction **action, bool *r_driven, bool *r_special);
/* Binary search algorithm for finding where to 'insert' BezTriple with given frame number.
* Returns the index to insert at (data already at that index will be offset if replace is 0)
diff --git a/source/blender/blenkernel/BKE_fluidsim.h b/source/blender/blenkernel/BKE_fluidsim.h
index 433c10b82f1..6501c968abc 100644
--- a/source/blender/blenkernel/BKE_fluidsim.h
+++ b/source/blender/blenkernel/BKE_fluidsim.h
@@ -34,9 +34,7 @@
struct Object;
struct Scene;
-struct FluidsimModifierData;
struct FluidsimSettings;
-struct DerivedMesh;
struct MVert;
/* old interface */
diff --git a/source/blender/blenkernel/BKE_font.h b/source/blender/blenkernel/BKE_font.h
index e12ce3df476..137670215cc 100644
--- a/source/blender/blenkernel/BKE_font.h
+++ b/source/blender/blenkernel/BKE_font.h
@@ -40,8 +40,6 @@ extern "C" {
struct VFont;
struct Object;
struct Curve;
-struct objfnt;
-struct TmpFont;
struct CharInfo;
struct Main;
diff --git a/source/blender/blenkernel/BKE_freestyle.h b/source/blender/blenkernel/BKE_freestyle.h
index bb909e4aa9d..e10594634f0 100644
--- a/source/blender/blenkernel/BKE_freestyle.h
+++ b/source/blender/blenkernel/BKE_freestyle.h
@@ -41,6 +41,7 @@ extern "C" {
struct FreestyleConfig;
struct FreestyleLineSet;
struct FreestyleModuleConfig;
+struct Main;
/* RNA aliases */
typedef struct FreestyleSettings FreestyleSettings;
@@ -58,7 +59,7 @@ bool BKE_freestyle_module_move_up(FreestyleConfig *config, FreestyleModuleConfig
bool BKE_freestyle_module_move_down(FreestyleConfig *config, FreestyleModuleConfig *module_conf);
/* FreestyleConfig.linesets */
-FreestyleLineSet *BKE_freestyle_lineset_add(FreestyleConfig *config, const char *name);
+FreestyleLineSet *BKE_freestyle_lineset_add(struct Main *bmain, FreestyleConfig *config, const char *name);
bool BKE_freestyle_lineset_delete(FreestyleConfig *config, FreestyleLineSet *lineset);
FreestyleLineSet *BKE_freestyle_lineset_get_active(FreestyleConfig *config);
short BKE_freestyle_lineset_get_active_index(FreestyleConfig *config);
diff --git a/source/blender/blenkernel/BKE_global.h b/source/blender/blenkernel/BKE_global.h
index a7aa4c6969a..865f621e82d 100644
--- a/source/blender/blenkernel/BKE_global.h
+++ b/source/blender/blenkernel/BKE_global.h
@@ -45,7 +45,6 @@ extern "C" {
/* forwards */
struct Main;
-struct Object;
typedef struct Global {
@@ -70,7 +69,6 @@ typedef struct Global {
bool factory_startup;
short moving;
- short winpos, displaymode; /* used to be in Render */
/* to indicate render is busy, prevent renderwindow events etc */
bool is_rendering;
@@ -90,9 +88,6 @@ typedef struct Global {
/* this variable is written to / read from FileGlobal->fileflags */
int fileflags;
- /* save the allowed windowstate of blender when using -W or -w (GHOST_TWindowState) */
- int windowstate;
-
/* message to use when autoexec fails */
char autoexec_fail[200];
} Global;
@@ -130,10 +125,14 @@ enum {
G_DEBUG_JOBS = (1 << 6), /* jobs time profiling */
G_DEBUG_FREESTYLE = (1 << 7), /* freestyle messages */
G_DEBUG_DEPSGRAPH = (1 << 8), /* depsgraph messages */
+ G_DEBUG_SIMDATA = (1 << 9), /* sim debug data display */
+ G_DEBUG_GPU_MEM = (1 << 10), /* gpu memory in status bar */
+ G_DEBUG_DEPSGRAPH_NO_THREADS = (1 << 11), /* sinle threaded depsgraph */
+ G_DEBUG_GPU = (1 << 12), /* gpu debug */
};
#define G_DEBUG_ALL (G_DEBUG | G_DEBUG_FFMPEG | G_DEBUG_PYTHON | G_DEBUG_EVENTS | G_DEBUG_WM | G_DEBUG_JOBS | \
- G_DEBUG_FREESTYLE | G_DEBUG_DEPSGRAPH)
+ G_DEBUG_FREESTYLE | G_DEBUG_DEPSGRAPH | G_DEBUG_GPU_MEM)
/* G.fileflags */
@@ -141,14 +140,19 @@ enum {
#define G_AUTOPACK (1 << 0)
#define G_FILE_COMPRESS (1 << 1)
#define G_FILE_AUTOPLAY (1 << 2)
+
+#ifdef DNA_DEPRECATED_ALLOW
#define G_FILE_ENABLE_ALL_FRAMES (1 << 3) /* deprecated */
#define G_FILE_SHOW_DEBUG_PROPS (1 << 4) /* deprecated */
#define G_FILE_SHOW_FRAMERATE (1 << 5) /* deprecated */
/* #define G_FILE_SHOW_PROFILE (1 << 6) */ /* deprecated */
-#define G_FILE_LOCK (1 << 7)
-#define G_FILE_SIGN (1 << 8)
+/* #define G_FILE_LOCK (1 << 7) */ /* deprecated */
+/* #define G_FILE_SIGN (1 << 8) */ /* deprecated */
+#endif /* DNA_DEPRECATED_ALLOW */
+
#define G_FILE_USERPREFS (1 << 9)
#define G_FILE_NO_UI (1 << 10)
+#ifdef DNA_DEPRECATED_ALLOW
/* #define G_FILE_GAME_TO_IPO (1 << 11) */ /* deprecated */
#define G_FILE_GAME_MAT (1 << 12) /* deprecated */
/* #define G_FILE_DISPLAY_LISTS (1 << 13) */ /* deprecated */
@@ -161,11 +165,19 @@ enum {
#define G_FILE_GLSL_NO_NODES (1 << 20) /* deprecated */
#define G_FILE_GLSL_NO_EXTRA_TEX (1 << 21) /* deprecated */
#define G_FILE_IGNORE_DEPRECATION_WARNINGS (1 << 22) /* deprecated */
+#endif /* DNA_DEPRECATED_ALLOW */
+
+/* On read, use #FileGlobal.filename instead of the real location on-disk,
+ * needed for recovering temp files so relative paths resolve */
#define G_FILE_RECOVER (1 << 23)
+/* On write, remap relative file paths to the new file location. */
#define G_FILE_RELATIVE_REMAP (1 << 24)
+/* On write, make backup `.blend1`, `.blend2` ... files, when the users preference is enabled */
#define G_FILE_HISTORY (1 << 25)
-#define G_FILE_MESH_COMPAT (1 << 26) /* BMesh option to save as older mesh format */
-#define G_FILE_SAVE_COPY (1 << 27) /* restore paths after editing them */
+/* BMesh option to save as older mesh format */
+#define G_FILE_MESH_COMPAT (1 << 26)
+/* On wrote, restore paths after editing them (G_FILE_RELATIVE_REMAP) */
+#define G_FILE_SAVE_COPY (1 << 27)
#define G_FILE_FLAGS_RUNTIME (G_FILE_NO_UI | G_FILE_RELATIVE_REMAP | G_FILE_MESH_COMPAT | G_FILE_SAVE_COPY)
diff --git a/source/blender/blenkernel/BKE_gpencil.h b/source/blender/blenkernel/BKE_gpencil.h
index 86c111653d1..084c5527f21 100644
--- a/source/blender/blenkernel/BKE_gpencil.h
+++ b/source/blender/blenkernel/BKE_gpencil.h
@@ -35,6 +35,7 @@ struct ListBase;
struct bGPdata;
struct bGPDlayer;
struct bGPDframe;
+struct bGPDstroke;
/* ------------ Grease-Pencil API ------------------ */
@@ -43,17 +44,15 @@ void free_gpencil_frames(struct bGPDlayer *gpl);
void free_gpencil_layers(struct ListBase *list);
void BKE_gpencil_free(struct bGPdata *gpd);
+void gpencil_stroke_sync_selection(struct bGPDstroke *gps);
+
struct bGPDframe *gpencil_frame_addnew(struct bGPDlayer *gpl, int cframe);
struct bGPDlayer *gpencil_layer_addnew(struct bGPdata *gpd, const char *name, int setactive);
struct bGPdata *gpencil_data_addnew(const char name[]);
struct bGPDframe *gpencil_frame_duplicate(struct bGPDframe *src);
struct bGPDlayer *gpencil_layer_duplicate(struct bGPDlayer *src);
-struct bGPdata *gpencil_data_duplicate(struct bGPdata *gpd);
-
-//struct bGPdata *gpencil_data_getactive(struct ScrArea *sa);
-//short gpencil_data_setactive(struct ScrArea *sa, struct bGPdata *gpd);
-//struct ScrArea *gpencil_data_findowner(struct bGPdata *gpd);
+struct bGPdata *gpencil_data_duplicate(struct bGPdata *gpd, bool internal_copy);
void gpencil_frame_delete_laststroke(struct bGPDlayer *gpl, struct bGPDframe *gpf);
diff --git a/source/blender/blenkernel/BKE_group.h b/source/blender/blenkernel/BKE_group.h
index f528fe8c7f9..d856e90a340 100644
--- a/source/blender/blenkernel/BKE_group.h
+++ b/source/blender/blenkernel/BKE_group.h
@@ -36,10 +36,8 @@
struct Base;
struct EvaluationContext;
struct Group;
-struct GroupObject;
struct Main;
struct Object;
-struct bAction;
struct Scene;
void BKE_group_free(struct Group *group);
@@ -50,6 +48,7 @@ bool BKE_group_object_add(struct Group *group, struct Object *ob, struc
bool BKE_group_object_unlink(struct Group *group, struct Object *ob, struct Scene *scene, struct Base *base);
struct Group *BKE_group_object_find(struct Group *group, struct Object *ob);
bool BKE_group_object_exists(struct Group *group, struct Object *ob);
+bool BKE_group_object_cyclic_check(struct Main *bmain, struct Object *object, struct Group *group);
bool BKE_group_is_animated(struct Group *group, struct Object *parent);
void BKE_group_tag_recalc(struct Group *group);
diff --git a/source/blender/blenkernel/BKE_icons.h b/source/blender/blenkernel/BKE_icons.h
index 9af0d96884a..763a3874d4e 100644
--- a/source/blender/blenkernel/BKE_icons.h
+++ b/source/blender/blenkernel/BKE_icons.h
@@ -48,10 +48,14 @@ typedef struct Icon Icon;
struct PreviewImage;
struct ID;
+enum eIconSizes;
+
void BKE_icons_init(int first_dyn_id);
/* return icon id for library object or create new icon if not found */
-int BKE_icon_getid(struct ID *id);
+int BKE_icon_id_ensure(struct ID *id);
+
+int BKE_icon_preview_ensure(struct PreviewImage *preview);
/* retrieve icon for id */
struct Icon *BKE_icon_get(int icon_id);
@@ -60,8 +64,10 @@ struct Icon *BKE_icon_get(int icon_id);
/* used for inserting the internal icons */
void BKE_icon_set(int icon_id, struct Icon *icon);
-/* remove icon and free date if library object becomes invalid */
-void BKE_icon_delete(struct ID *id);
+/* remove icon and free data if library object becomes invalid */
+void BKE_icon_id_delete(struct ID *id);
+
+void BKE_icon_delete(int icon_id);
/* report changes - icon needs to be recalculated */
void BKE_icon_changed(int icon_id);
@@ -75,8 +81,17 @@ void BKE_previewimg_freefunc(void *link);
/* free the preview image */
void BKE_previewimg_free(struct PreviewImage **prv);
+/* clear the preview image or icon, but does not free it */
+void BKE_previewimg_clear(struct PreviewImage *prv);
+
+/* clear the preview image or icon at a specific size */
+void BKE_previewimg_clear_single(struct PreviewImage *prv, enum eIconSizes size);
+
+/* get the preview from any pointer */
+struct PreviewImage **BKE_previewimg_id_get_p(struct ID *id);
+
/* free the preview image belonging to the id */
-void BKE_previewimg_free_id(struct ID *id);
+void BKE_previewimg_id_free(struct ID *id);
/* create a new preview image */
struct PreviewImage *BKE_previewimg_create(void);
@@ -85,6 +100,19 @@ struct PreviewImage *BKE_previewimg_create(void);
struct PreviewImage *BKE_previewimg_copy(struct PreviewImage *prv);
/* retrieve existing or create new preview image */
-struct PreviewImage *BKE_previewimg_get(struct ID *id);
+struct PreviewImage *BKE_previewimg_id_ensure(struct ID *id);
+
+void BKE_previewimg_ensure(struct PreviewImage *prv, const int size);
+
+struct PreviewImage *BKE_previewimg_cached_get(const char *name);
+
+struct PreviewImage *BKE_previewimg_cached_ensure(const char *name);
+
+struct PreviewImage *BKE_previewimg_cached_thumbnail_read(
+ const char *name, const char *path, const int source, bool force_update);
+
+void BKE_previewimg_cached_release(const char *name);
+
+#define ICON_RENDER_DEFAULT_HEIGHT 32
#endif /* __BKE_ICONS_H__ */
diff --git a/source/blender/blenkernel/BKE_idcode.h b/source/blender/blenkernel/BKE_idcode.h
index 10a34838662..ebad0d42232 100644
--- a/source/blender/blenkernel/BKE_idcode.h
+++ b/source/blender/blenkernel/BKE_idcode.h
@@ -34,10 +34,14 @@
const char *BKE_idcode_to_name(int code);
const char *BKE_idcode_to_name_plural(int code);
+const char *BKE_idcode_to_translation_context(int code);
int BKE_idcode_from_name(const char *name);
bool BKE_idcode_is_linkable(int code);
bool BKE_idcode_is_valid(int code);
+int BKE_idcode_to_idfilter(const int idcode);
+int BKE_idcode_from_idfilter(const int idfilter);
+
/**
* Return an ID code and steps the index forward 1.
*
diff --git a/source/blender/blenkernel/BKE_idprop.h b/source/blender/blenkernel/BKE_idprop.h
index 2ab3d84dea5..5b10d7ebc06 100644
--- a/source/blender/blenkernel/BKE_idprop.h
+++ b/source/blender/blenkernel/BKE_idprop.h
@@ -40,18 +40,18 @@ typedef union IDPropertyTemplate {
float f;
double d;
struct {
- char *str;
- short len;
+ const char *str;
+ int len;
char subtype;
} string;
struct ID *id;
struct {
- short type;
- short len;
+ int len;
+ char type;
} array;
struct {
int matvec_size;
- float *example;
+ const float *example;
} matrix_or_vector;
} IDPropertyTemplate;
@@ -91,6 +91,7 @@ void IDP_SyncGroupValues(struct IDProperty *dest, const struct IDProperty *src)
void IDP_SyncGroupTypes(struct IDProperty *dest, const struct IDProperty *src, const bool do_arraylen) ATTR_NONNULL();
void IDP_ReplaceGroupInGroup(struct IDProperty *dest, const struct IDProperty *src) ATTR_NONNULL();
void IDP_ReplaceInGroup(struct IDProperty *group, struct IDProperty *prop) ATTR_NONNULL();
+void IDP_ReplaceInGroup_ex(struct IDProperty *group, struct IDProperty *prop, struct IDProperty *prop_exist);
void IDP_MergeGroup(IDProperty *dest, const IDProperty *src, const bool do_overwrite) ATTR_NONNULL();
bool IDP_AddToGroup(struct IDProperty *group, struct IDProperty *prop) ATTR_NONNULL();
bool IDP_InsertToGroup(struct IDProperty *group, struct IDProperty *previous,
@@ -100,9 +101,6 @@ void IDP_FreeFromGroup(struct IDProperty *group, struct IDProperty *prop) ATTR_N
IDProperty *IDP_GetPropertyFromGroup(struct IDProperty *prop, const char *name) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
IDProperty *IDP_GetPropertyTypeFromGroup(struct IDProperty *prop, const char *name, const char type) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-void *IDP_GetGroupIterator(struct IDProperty *prop) ATTR_WARN_UNUSED_RESULT;
-IDProperty *IDP_GroupIterNext(void *vself) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-void IDP_FreeIterBeforeEnd(void *vself) ATTR_NONNULL();
/*-------- Main Functions --------*/
struct IDProperty *IDP_GetProperties(struct ID *id, const bool create_if_needed) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
@@ -112,7 +110,7 @@ bool IDP_EqualsProperties_ex(IDProperty *prop1, IDProperty *prop2, const bool is
bool IDP_EqualsProperties(struct IDProperty *prop1, struct IDProperty *prop2) ATTR_WARN_UNUSED_RESULT;
-struct IDProperty *IDP_New(const int type, const IDPropertyTemplate *val, const char *name) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+struct IDProperty *IDP_New(const char type, const IDPropertyTemplate *val, const char *name) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
void IDP_FreeProperty(struct IDProperty *prop);
diff --git a/source/blender/blenkernel/BKE_image.h b/source/blender/blenkernel/BKE_image.h
index dc3d9f38b21..94afc8a16ea 100644
--- a/source/blender/blenkernel/BKE_image.h
+++ b/source/blender/blenkernel/BKE_image.h
@@ -39,37 +39,50 @@ extern "C" {
struct Image;
struct ImBuf;
-struct Tex;
+struct ImbFormatOptions;
struct anim;
struct Scene;
struct Object;
struct ImageFormatData;
struct ImagePool;
struct Main;
+struct ReportList;
+struct RenderResult;
+struct StampData;
#define IMA_MAX_SPACE 64
void BKE_images_init(void);
void BKE_images_exit(void);
+void BKE_image_free_packedfiles(struct Image *image);
+void BKE_image_free_views(struct Image *image);
void BKE_image_free_buffers(struct Image *image);
/* call from library */
void BKE_image_free(struct Image *image);
-void BKE_imbuf_stamp_info(struct Scene *scene, struct Object *camera, struct ImBuf *ibuf);
-void BKE_stamp_buf(struct Scene *scene, struct Object *camera, unsigned char *rect, float *rectf, int width, int height, int channels);
+typedef void (StampCallback)(void *data, const char *propname, char *propvalue, int len);
+
+void BKE_render_result_stamp_info(struct Scene *scene, struct Object *camera, struct RenderResult *rr, bool allocate_only);
+void BKE_imbuf_stamp_info(struct RenderResult *rr, struct ImBuf *ibuf);
+void BKE_stamp_info_from_imbuf(struct RenderResult *rr, struct ImBuf *ibuf);
+void BKE_stamp_info_callback(void *data, struct StampData *stamp_data, StampCallback callback, bool noskip);
+void BKE_image_stamp_buf(struct Scene *scene, struct Object *camera, unsigned char *rect, float *rectf, int width, int height, int channels);
bool BKE_imbuf_alpha_test(struct ImBuf *ibuf);
-int BKE_imbuf_write_stamp(struct Scene *scene, struct Object *camera, struct ImBuf *ibuf, const char *name, struct ImageFormatData *imf);
+int BKE_imbuf_write_stamp(struct Scene *scene, struct RenderResult *rr, struct ImBuf *ibuf, const char *name, struct ImageFormatData *imf);
+void BKE_imbuf_write_prepare(struct ImBuf *ibuf, struct ImageFormatData *imf);
int BKE_imbuf_write(struct ImBuf *ibuf, const char *name, struct ImageFormatData *imf);
int BKE_imbuf_write_as(struct ImBuf *ibuf, const char *name, struct ImageFormatData *imf, const bool is_copy);
-void BKE_makepicstring(char *string, const char *base, const char *relbase, int frame,
- const struct ImageFormatData *im_format, const bool use_ext, const bool use_frames);
-void BKE_makepicstring_from_type(char *string, const char *base, const char *relbase, int frame,
- const char imtype, const bool use_ext, const bool use_frames);
-int BKE_add_image_extension(char *string, const struct ImageFormatData *im_format);
-int BKE_add_image_extension_from_type(char *string, const char imtype);
-char BKE_ftype_to_imtype(const int ftype);
-int BKE_imtype_to_ftype(const char imtype);
+void BKE_image_path_from_imformat(
+ char *string, const char *base, const char *relbase, int frame,
+ const struct ImageFormatData *im_format, const bool use_ext, const bool use_frames, const char *suffix);
+void BKE_image_path_from_imtype(
+ char *string, const char *base, const char *relbase, int frame,
+ const char imtype, const bool use_ext, const bool use_frames, const char *suffix);
+int BKE_image_path_ensure_ext_from_imformat(char *string, const struct ImageFormatData *im_format);
+int BKE_image_path_ensure_ext_from_imtype(char *string, const char imtype);
+char BKE_image_ftype_to_imtype(const int ftype, const struct ImbFormatOptions *options);
+int BKE_image_imtype_to_ftype(const char imtype, struct ImbFormatOptions *r_options);
bool BKE_imtype_is_movie(const char imtype);
int BKE_imtype_supports_zbuf(const char imtype);
@@ -85,19 +98,20 @@ void BKE_imformat_defaults(struct ImageFormatData *im_format);
void BKE_imbuf_to_image_format(struct ImageFormatData *im_format, const struct ImBuf *imbuf);
struct anim *openanim(const char *name, int flags, int streamindex, char colorspace[IMA_MAX_SPACE]);
+struct anim *openanim_noload(const char *name, int flags, int streamindex, char colorspace[IMA_MAX_SPACE]);
void BKE_image_de_interlace(struct Image *ima, int odd);
void BKE_image_make_local(struct Image *ima);
void BKE_image_tag_time(struct Image *ima);
-void free_old_images(void);
/* ********************************** NEW IMAGE API *********************** */
/* ImageUser is in Texture, in Nodes, Background Image, Image Window, .... */
/* should be used in conjunction with an ID * to Image. */
struct ImageUser;
+struct RenderData;
struct RenderPass;
struct RenderResult;
@@ -147,7 +161,7 @@ bool BKE_image_has_ibuf(struct Image *ima, struct ImageUser *iuser);
/* same as above, but can be used to retrieve images being rendered in
* a thread safe way, always call both acquire and release */
-struct ImBuf *BKE_image_acquire_ibuf(struct Image *ima, struct ImageUser *iuser, void **lock_r);
+struct ImBuf *BKE_image_acquire_ibuf(struct Image *ima, struct ImageUser *iuser, void **r_lock);
void BKE_image_release_ibuf(struct Image *ima, struct ImBuf *ibuf, void *lock);
struct ImagePool *BKE_image_pool_new(void);
@@ -162,15 +176,17 @@ void BKE_image_alpha_mode_from_extension(struct Image *image);
/* returns a new image or NULL if it can't load */
struct Image *BKE_image_load(struct Main *bmain, const char *filepath);
/* returns existing Image when filename/type is same (frame optional) */
+struct Image *BKE_image_load_exists_ex(const char *filepath, bool *r_exists);
struct Image *BKE_image_load_exists(const char *filepath);
/* adds image, adds ibuf, generates color or pattern */
struct Image *BKE_image_add_generated(
- struct Main *bmain, unsigned int width, unsigned int height, const char *name, int depth, int floatbuf, short gen_type, const float color[4]);
+ struct Main *bmain, unsigned int width, unsigned int height, const char *name, int depth, int floatbuf, short gen_type, const float color[4], const bool stereo3d);
/* adds image from imbuf, owns imbuf */
-struct Image *BKE_image_add_from_imbuf(struct ImBuf *ibuf);
+struct Image *BKE_image_add_from_imbuf(struct ImBuf *ibuf, const char *name);
/* for reload, refresh, pack */
+void BKE_image_init_imageuser(struct Image *ima, struct ImageUser *iuser);
void BKE_image_signal(struct Image *ima, struct ImageUser *iuser, int signal);
void BKE_image_walk_all_users(const struct Main *mainp, void *customdata,
@@ -178,9 +194,8 @@ void BKE_image_walk_all_users(const struct Main *mainp, void *customdata,
/* ensures an Image exists for viewing nodes or render */
struct Image *BKE_image_verify_viewer(int type, const char *name);
-
-/* force an ImBuf to become part of Image */
-void BKE_image_assign_ibuf(struct Image *ima, struct ImBuf *ibuf);
+/* ensures the view node cache is compatible with the scene views */
+void BKE_image_verify_viewer_views(const struct RenderData *rd, struct Image *ima, struct ImageUser *iuser);
/* called on frame change or before render */
void BKE_image_user_frame_calc(struct ImageUser *iuser, int cfra, int fieldnr);
@@ -192,13 +207,23 @@ void BKE_image_update_frame(const struct Main *bmain, int cfra);
/* sets index offset for multilayer files */
struct RenderPass *BKE_image_multilayer_index(struct RenderResult *rr, struct ImageUser *iuser);
+/* sets index offset for multiview files */
+void BKE_image_multiview_index(struct Image *ima, struct ImageUser *iuser);
+
/* for multilayer images as well as for render-viewer */
+bool BKE_image_is_multilayer(struct Image *ima);
struct RenderResult *BKE_image_acquire_renderresult(struct Scene *scene, struct Image *ima);
void BKE_image_release_renderresult(struct Scene *scene, struct Image *ima);
+/* for multilayer images as well as for singlelayer */
+bool BKE_image_is_openexr(struct Image *ima);
+
/* for multiple slot render, call this before render */
void BKE_image_backup_render(struct Scene *scene, struct Image *ima);
-
+
+/* for singlelayer openexr saving */
+bool BKE_image_save_openexr_multiview(struct Image *ima, struct ImBuf *ibuf, const char *filepath, const int flags);
+
/* goes over all textures that use images */
void BKE_image_free_all_textures(void);
@@ -209,6 +234,8 @@ void BKE_image_free_anim_ibufs(struct Image *ima, int except_frame);
void BKE_image_all_free_anim_ibufs(int except_frame);
void BKE_image_memorypack(struct Image *ima);
+void BKE_image_packfiles(struct ReportList *reports, struct Image *ima, const char *basepath);
+void BKE_image_packfiles_from_mem(struct ReportList *reports, struct Image *ima, char *data, const size_t data_len);
/* prints memory statistics for images */
void BKE_image_print_memlist(void);
@@ -240,10 +267,11 @@ float *BKE_image_get_float_pixels_for_frame(struct Image *image, int frame);
/* Guess offset for the first frame in the sequence */
int BKE_image_sequence_guess_offset(struct Image *image);
-
+bool BKE_image_has_anim(struct Image *image);
+bool BKE_image_has_packedfile(struct Image *image);
bool BKE_image_is_animated(struct Image *image);
bool BKE_image_is_dirty(struct Image *image);
-void BKE_image_file_format_set(struct Image *image, int ftype);
+void BKE_image_file_format_set(struct Image *image, int ftype, const struct ImbFormatOptions *options);
bool BKE_image_has_loaded_ibuf(struct Image *image);
struct ImBuf *BKE_image_get_ibuf_with_name(struct Image *image, const char *name);
struct ImBuf *BKE_image_get_first_ibuf(struct Image *image);
diff --git a/source/blender/blenkernel/BKE_key.h b/source/blender/blenkernel/BKE_key.h
index 6183df8666d..abe12282a1b 100644
--- a/source/blender/blenkernel/BKE_key.h
+++ b/source/blender/blenkernel/BKE_key.h
@@ -38,7 +38,6 @@ struct ID;
struct ListBase;
struct Curve;
struct Object;
-struct Scene;
struct Lattice;
struct Mesh;
struct WeightsArrayCache;
@@ -60,10 +59,13 @@ void key_curve_position_weights(float t, float data[4], int type);
void key_curve_tangent_weights(float t, float data[4], int type);
void key_curve_normal_weights(float t, float data[4], int type);
-float *BKE_key_evaluate_object_ex(struct Scene *scene, struct Object *ob, int *r_totelem,
- float *arr, size_t arr_size);
-float *BKE_key_evaluate_object(struct Scene *scene, struct Object *ob, int *r_totelem);
+float *BKE_key_evaluate_object_ex(
+ struct Object *ob, int *r_totelem,
+ float *arr, size_t arr_size);
+float *BKE_key_evaluate_object(
+ struct Object *ob, int *r_totelem);
+struct Key **BKE_key_from_object_p(struct Object *ob);
struct Key *BKE_key_from_object(struct Object *ob);
struct KeyBlock *BKE_keyblock_from_object(struct Object *ob);
struct KeyBlock *BKE_keyblock_from_object_reference(struct Object *ob);
@@ -87,18 +89,29 @@ void BKE_key_evaluate_relative(const int start, int end, const int tot, char *ba
float **per_keyblock_weights, const int mode);
/* conversion functions */
-void BKE_key_convert_to_mesh(struct KeyBlock *kb, struct Mesh *me);
-void BKE_key_convert_from_mesh(struct Mesh *me, struct KeyBlock *kb);
-void BKE_key_convert_to_lattice(struct KeyBlock *kb, struct Lattice *lt);
-void BKE_key_convert_from_lattice(struct Lattice *lt, struct KeyBlock *kb);
-void BKE_key_convert_to_curve(struct KeyBlock *kb, struct Curve *cu, struct ListBase *nurb);
-void BKE_key_convert_from_curve(struct Curve *cu, struct KeyBlock *kb, struct ListBase *nurb);
-float (*BKE_key_convert_to_vertcos(struct Object *ob, struct KeyBlock *kb))[3];
-void BKE_key_convert_from_vertcos(struct Object *ob, struct KeyBlock *kb, float (*vertCos)[3]);
-void BKE_key_convert_from_offset(struct Object *ob, struct KeyBlock *kb, float (*ofs)[3]);
-
-/* key.c */
-extern int slurph_opt;
+/* Note: 'update_from' versions do not (re)allocate mem in kb, while 'convert_from' do. */
+void BKE_keyblock_update_from_lattice(struct Lattice *lt, struct KeyBlock *kb);
+void BKE_keyblock_convert_from_lattice(struct Lattice *lt, struct KeyBlock *kb);
+void BKE_keyblock_convert_to_lattice(struct KeyBlock *kb, struct Lattice *lt);
+
+void BKE_keyblock_update_from_curve(struct Curve *cu, struct KeyBlock *kb, struct ListBase *nurb);
+void BKE_keyblock_convert_from_curve(struct Curve *cu, struct KeyBlock *kb, struct ListBase *nurb);
+void BKE_keyblock_convert_to_curve(struct KeyBlock *kb, struct Curve *cu, struct ListBase *nurb);
+
+void BKE_keyblock_update_from_mesh(struct Mesh *me, struct KeyBlock *kb);
+void BKE_keyblock_convert_from_mesh(struct Mesh *me, struct KeyBlock *kb);
+void BKE_keyblock_convert_to_mesh(struct KeyBlock *kb, struct Mesh *me);
+
+void BKE_keyblock_update_from_vertcos(struct Object *ob, struct KeyBlock *kb, float (*vertCos)[3]);
+void BKE_keyblock_convert_from_vertcos(struct Object *ob, struct KeyBlock *kb, float (*vertCos)[3]);
+float (*BKE_keyblock_convert_to_vertcos(struct Object *ob, struct KeyBlock *kb))[3];
+
+void BKE_keyblock_update_from_offset(struct Object *ob, struct KeyBlock *kb, float (*ofs)[3]);
+
+/* other management */
+bool BKE_keyblock_move(struct Object *ob, int org_index, int new_index);
+
+bool BKE_keyblock_is_basis(struct Key *key, const int index);
#ifdef __cplusplus
};
diff --git a/source/blender/blenkernel/BKE_lattice.h b/source/blender/blenkernel/BKE_lattice.h
index 5fb1053b53f..677d8e34229 100644
--- a/source/blender/blenkernel/BKE_lattice.h
+++ b/source/blender/blenkernel/BKE_lattice.h
@@ -80,6 +80,8 @@ void BKE_lattice_modifiers_calc(struct Scene *scene, struct Object *ob);
struct MDeformVert *BKE_lattice_deform_verts_get(struct Object *lattice);
struct BPoint *BKE_lattice_active_point_get(struct Lattice *lt);
+struct BoundBox *BKE_lattice_boundbox_get(struct Object *ob);
+void BKE_lattice_minmax_dl(struct Object *ob, struct Lattice *lt, float min[3], float max[3]);
void BKE_lattice_minmax(struct Lattice *lt, float min[3], float max[3]);
void BKE_lattice_center_median(struct Lattice *lt, float cent[3]);
void BKE_lattice_center_bounds(struct Lattice *lt, float cent[3]);
@@ -93,4 +95,11 @@ int BKE_lattice_index_flip(struct Lattice *lt, const int index,
void BKE_lattice_bitmap_from_flag(struct Lattice *lt, unsigned int *bitmap, const short flag,
const bool clear, const bool respecthide);
+/* **** Depsgraph evaluation **** */
+
+struct EvaluationContext;
+
+void BKE_lattice_eval_geometry(struct EvaluationContext *eval_ctx,
+ struct Lattice *latt);
+
#endif /* __BKE_LATTICE_H__ */
diff --git a/source/blender/blenkernel/BKE_library.h b/source/blender/blenkernel/BKE_library.h
index 500c2813a75..5b12858fc7d 100644
--- a/source/blender/blenkernel/BKE_library.h
+++ b/source/blender/blenkernel/BKE_library.h
@@ -38,8 +38,10 @@ extern "C" {
#include "BLI_compiler_attrs.h"
+struct BlendThumbnail;
struct ListBase;
struct ID;
+struct ImBuf;
struct Main;
struct Library;
struct wmWindowManager;
@@ -87,6 +89,10 @@ void BKE_main_free(struct Main *mainvar);
void BKE_main_lock(struct Main *bmain);
void BKE_main_unlock(struct Main *bmain);
+struct BlendThumbnail *BKE_main_thumbnail_from_imbuf(struct Main *bmain, struct ImBuf *img);
+struct ImBuf *BKE_main_thumbnail_to_imbuf(struct Main *bmain, struct BlendThumbnail *data);
+void BKE_main_thumbnail_create(struct Main *bmain);
+
void BKE_main_id_tag_idcode(struct Main *mainvar, const short type, const bool tag);
void BKE_main_id_tag_listbase(struct ListBase *lb, const bool tag);
void BKE_main_id_tag_all(struct Main *mainvar, const bool tag);
@@ -107,8 +113,9 @@ void BKE_library_make_local(struct Main *bmain, struct Library *lib, bool untagg
struct ID *BKE_libblock_find_name_ex(struct Main *bmain, const short type, const char *name) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
struct ID *BKE_libblock_find_name(const short type, const char *name) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-void set_free_windowmanager_cb(void (*func)(struct bContext *, struct wmWindowManager *) );
-void set_free_notifier_reference_cb(void (*func)(const void *) );
+void BKE_library_callback_free_window_manager_set(void (*func)(struct bContext *, struct wmWindowManager *));
+void BKE_library_callback_free_notifier_reference_set(void (*func)(const void *));
+void BKE_library_callback_free_editor_id_reference_set(void (*func)(const struct ID *));
/* use when "" is given to new_id() */
#define ID_FALLBACK_NAME N_("Untitled")
diff --git a/source/blender/blenkernel/BKE_linestyle.h b/source/blender/blenkernel/BKE_linestyle.h
index ae10ba4caab..e77b4f5e8fe 100644
--- a/source/blender/blenkernel/BKE_linestyle.h
+++ b/source/blender/blenkernel/BKE_linestyle.h
@@ -49,9 +49,9 @@ struct Object;
struct ColorBand;
struct bContext;
-FreestyleLineStyle *BKE_linestyle_new(const char *name, struct Main *main);
+FreestyleLineStyle *BKE_linestyle_new(struct Main *bmain, const char *name);
void BKE_linestyle_free(FreestyleLineStyle *linestyle);
-FreestyleLineStyle *BKE_linestyle_copy(FreestyleLineStyle *linestyle);
+FreestyleLineStyle *BKE_linestyle_copy(struct Main *bmain, FreestyleLineStyle *linestyle);
FreestyleLineStyle *BKE_linestyle_active_from_scene(struct Scene *scene);
diff --git a/source/blender/blenkernel/BKE_main.h b/source/blender/blenkernel/BKE_main.h
index ec654ea4b71..6a00961fbb3 100644
--- a/source/blender/blenkernel/BKE_main.h
+++ b/source/blender/blenkernel/BKE_main.h
@@ -50,6 +50,13 @@ struct EvaluationContext;
struct Library;
struct MainLock;
+/* Blender thumbnail, as written on file (width, height, and data as char RGBA). */
+/* We pack pixel data after that struct. */
+typedef struct BlendThumbnail {
+ int width, height;
+ char rect[0];
+} BlendThumbnail;
+
typedef struct Main {
struct Main *next, *prev;
char name[1024]; /* 1024 = FILE_MAX */
@@ -58,6 +65,8 @@ typedef struct Main {
uint64_t build_commit_timestamp; /* commit's timestamp from buildinfo */
char build_hash[16]; /* hash from buildinfo */
short recovered; /* indicate the main->name (file) is the recovered one */
+
+ BlendThumbnail *blen_thumb;
struct Library *curlib;
ListBase scene;
@@ -109,7 +118,10 @@ typedef struct Main {
#define MAIN_VERSION_OLDER(main, ver, subver) \
((main)->versionfile < (ver) || (main->versionfile == (ver) && (main)->subversionfile < (subver)))
-
+#define BLEN_THUMB_SIZE 128
+
+#define BLEN_THUMB_MEMSIZE(_x, _y) (sizeof(BlendThumbnail) + (size_t)((_x) * (_y)) * sizeof(int))
+
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/blenkernel/BKE_mask.h b/source/blender/blenkernel/BKE_mask.h
index 3db4d9e7324..2f85db4d5d2 100644
--- a/source/blender/blenkernel/BKE_mask.h
+++ b/source/blender/blenkernel/BKE_mask.h
@@ -79,6 +79,7 @@ struct MaskSpline *BKE_mask_spline_copy(struct MaskSpline *spline);
void BKE_mask_point_free(struct MaskSplinePoint *point);
void BKE_mask_layer_unique_name(struct Mask *mask, struct MaskLayer *masklay);
+void BKE_mask_layer_rename(struct Mask *mask, struct MaskLayer *masklay, char *oldname, char *newname);
struct MaskLayer *BKE_mask_layer_copy(struct MaskLayer *layer);
void BKE_mask_layer_copy_list(struct ListBase *masklayers_new, struct ListBase *masklayers);
diff --git a/source/blender/blenkernel/BKE_material.h b/source/blender/blenkernel/BKE_material.h
index 2f20505bea3..a3c61f44ff2 100644
--- a/source/blender/blenkernel/BKE_material.h
+++ b/source/blender/blenkernel/BKE_material.h
@@ -40,8 +40,6 @@ struct Main;
struct Material;
struct ID;
struct Object;
-struct Mesh;
-struct MTFace;
struct Scene;
/* materials */
@@ -52,6 +50,7 @@ void BKE_material_free_ex(struct Material *ma, bool do_id_user);
void test_object_materials(struct Main *bmain, struct ID *id);
void BKE_material_resize_object(struct Object *ob, const short totcol, bool do_id_user);
void init_material(struct Material *ma);
+void BKE_material_remap_object(struct Object *ob, const unsigned int *remap);
struct Material *BKE_material_add(struct Main *bmain, const char *name);
struct Material *BKE_material_copy(struct Material *ma);
struct Material *localize_material(struct Material *ma);
@@ -70,6 +69,8 @@ struct Material ***give_matarar_id(struct ID *id); /* same but for ID's */
short *give_totcolp_id(struct ID *id);
enum {
+ /* use existing link option */
+ BKE_MAT_ASSIGN_EXISTING,
BKE_MAT_ASSIGN_USERPREF,
BKE_MAT_ASSIGN_OBDATA,
BKE_MAT_ASSIGN_OBJECT
@@ -97,7 +98,7 @@ void BKE_material_clear_id(struct ID *id, bool update_data);
/* rendering */
void init_render_material(struct Material *, int, float *);
-void init_render_materials(struct Main *, int, float *);
+void init_render_materials(struct Main *, int r_mode, float *amd, bool do_default_material);
void end_render_material(struct Material *);
void end_render_materials(struct Main *);
diff --git a/source/blender/blenkernel/BKE_mball.h b/source/blender/blenkernel/BKE_mball.h
index c021960e730..62cd50099fd 100644
--- a/source/blender/blenkernel/BKE_mball.h
+++ b/source/blender/blenkernel/BKE_mball.h
@@ -32,7 +32,6 @@
* \since March 2001
* \author nzc
*/
-struct EvaluationContext;
struct Main;
struct MetaBall;
struct Object;
@@ -46,9 +45,6 @@ struct MetaBall *BKE_mball_copy(struct MetaBall *mb);
void BKE_mball_make_local(struct MetaBall *mb);
-void BKE_mball_cubeTable_free(void);
-
-void BKE_mball_polygonize(struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob, struct ListBase *dispbase);
bool BKE_mball_is_basis_for(struct Object *ob1, struct Object *ob2);
bool BKE_mball_is_basis(struct Object *ob);
struct Object *BKE_mball_basis_find(struct Scene *scene, struct Object *ob);
@@ -72,4 +68,11 @@ void BKE_mball_select_all(struct MetaBall *mb);
void BKE_mball_deselect_all(struct MetaBall *mb);
void BKE_mball_select_swap(struct MetaBall *mb);
+/* **** Depsgraph evaluation **** */
+
+struct EvaluationContext;
+
+void BKE_mball_eval_geometry(struct EvaluationContext *eval_ctx,
+ struct MetaBall *mball);
+
#endif
diff --git a/source/blender/blenkernel/BKE_mball_tessellate.h b/source/blender/blenkernel/BKE_mball_tessellate.h
new file mode 100644
index 00000000000..361f31b704c
--- /dev/null
+++ b/source/blender/blenkernel/BKE_mball_tessellate.h
@@ -0,0 +1,36 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+#ifndef __BKE_MBALL_TESSELLATE_H__
+#define __BKE_MBALL_TESSELLATE_H__
+
+/** \file BKE_mball_tessellate.h
+ * \ingroup bke
+ */
+struct EvaluationContext;
+struct Object;
+struct Scene;
+
+void BKE_mball_polygonize(
+ struct EvaluationContext *eval_ctx, struct Scene *scene,
+ struct Object *ob, struct ListBase *dispbase);
+
+void BKE_mball_cubeTable_free(void);
+
+#endif /* __BKE_MBALL_TESSELLATE_H__ */
diff --git a/source/blender/blenkernel/BKE_mesh.h b/source/blender/blenkernel/BKE_mesh.h
index b2b9e37f500..a27688c1c61 100644
--- a/source/blender/blenkernel/BKE_mesh.h
+++ b/source/blender/blenkernel/BKE_mesh.h
@@ -33,11 +33,13 @@
struct ID;
struct BoundBox;
-struct DispList;
struct EdgeHash;
struct ListBase;
-struct BMEditMesh;
+struct LinkNode;
+struct BLI_Stack;
+struct MemArena;
struct BMesh;
+struct MLoopTri;
struct Main;
struct Mesh;
struct MPoly;
@@ -46,18 +48,11 @@ struct MFace;
struct MEdge;
struct MVert;
struct MDeformVert;
-struct MCol;
struct Object;
-struct MTFace;
-struct VecNor;
struct CustomData;
struct DerivedMesh;
struct Scene;
struct MLoopUV;
-struct UvVertMap;
-struct UvMapVert;
-struct UvElementMap;
-struct UvElement;
struct ReportList;
#ifdef __cplusplus
@@ -75,12 +70,13 @@ extern "C" {
struct BMesh *BKE_mesh_to_bmesh(struct Mesh *me, struct Object *ob);
-int poly_find_loop_from_vert(const struct MPoly *poly,
- const struct MLoop *loopstart,
- unsigned vert);
-
-int poly_get_adj_loops_from_vert(unsigned r_adj[3], const struct MPoly *poly,
- const struct MLoop *mloop, unsigned vert);
+int poly_find_loop_from_vert(
+ const struct MPoly *poly,
+ const struct MLoop *loopstart, unsigned vert);
+int poly_get_adj_loops_from_vert(
+ const struct MPoly *poly,
+ const struct MLoop *mloop, unsigned int vert,
+ unsigned int r_adj[2]);
int BKE_mesh_edge_other_vert(const struct MEdge *e, int v);
@@ -101,18 +97,23 @@ int test_index_face(struct MFace *mface, struct CustomData *mfdata, int mfindex,
struct Mesh *BKE_mesh_from_object(struct Object *ob);
void BKE_mesh_assign_object(struct Object *ob, struct Mesh *me);
void BKE_mesh_from_metaball(struct ListBase *lb, struct Mesh *me);
-int BKE_mesh_nurbs_to_mdata(struct Object *ob, struct MVert **allvert, int *totvert,
- struct MEdge **alledge, int *totedge, struct MLoop **allloop, struct MPoly **allpoly,
- int *totloop, int *totpoly);
-int BKE_mesh_nurbs_displist_to_mdata(struct Object *ob, struct ListBase *dispbase, struct MVert **allvert, int *_totvert,
- struct MEdge **alledge, int *_totedge, struct MLoop **allloop, struct MPoly **allpoly,
- struct MLoopUV **alluv, int *_totloop, int *_totpoly);
+int BKE_mesh_nurbs_to_mdata(
+ struct Object *ob, struct MVert **r_allvert, int *r_totvert,
+ struct MEdge **r_alledge, int *r_totedge, struct MLoop **r_allloop, struct MPoly **r_allpoly,
+ int *r_totloop, int *r_totpoly);
+int BKE_mesh_nurbs_displist_to_mdata(
+ struct Object *ob, const struct ListBase *dispbase,
+ struct MVert **r_allvert, int *r_totvert,
+ struct MEdge **r_alledge, int *r_totedge,
+ struct MLoop **r_allloop, struct MPoly **r_allpoly,
+ struct MLoopUV **r_alluv, int *r_totloop, int *r_totpoly);
void BKE_mesh_from_nurbs_displist(struct Object *ob, struct ListBase *dispbase, const bool use_orco_uv);
void BKE_mesh_from_nurbs(struct Object *ob);
void BKE_mesh_to_curve_nurblist(struct DerivedMesh *dm, struct ListBase *nurblist, const int edge_users_test);
void BKE_mesh_to_curve(struct Scene *scene, struct Object *ob);
void BKE_mesh_material_index_remove(struct Mesh *me, short index);
void BKE_mesh_material_index_clear(struct Mesh *me);
+void BKE_mesh_material_remap(struct Mesh *me, const unsigned int *remap, unsigned int remap_len);
void BKE_mesh_smooth_flag_set(struct Object *meshOb, int enableSmooth);
const char *BKE_mesh_cmp(struct Mesh *me1, struct Mesh *me2, float thresh);
@@ -125,14 +126,17 @@ bool BKE_mesh_uv_cdlayer_rename_index(struct Mesh *me, const int poly_index, con
const char *new_name, const bool do_tessface);
bool BKE_mesh_uv_cdlayer_rename(struct Mesh *me, const char *old_name, const char *new_name, bool do_tessface);
-float (*BKE_mesh_vertexCos_get(struct Mesh *me, int *r_numVerts))[3];
+float (*BKE_mesh_vertexCos_get(const struct Mesh *me, int *r_numVerts))[3];
+
+void BKE_mesh_calc_normals_split(struct Mesh *mesh);
+void BKE_mesh_split_faces(struct Mesh *mesh);
struct Mesh *BKE_mesh_new_from_object(struct Main *bmain, struct Scene *sce, struct Object *ob,
int apply_modifiers, int settings, int calc_tessface, int calc_undeformed);
/* vertex level transformations & checks (no derived mesh) */
-bool BKE_mesh_minmax(struct Mesh *me, float r_min[3], float r_max[3]);
+bool BKE_mesh_minmax(const struct Mesh *me, float r_min[3], float r_max[3]);
void BKE_mesh_transform(struct Mesh *me, float mat[4][4], bool do_keys);
void BKE_mesh_translate(struct Mesh *me, const float offset[3], const bool do_keys);
@@ -157,49 +161,107 @@ void BKE_mesh_mselect_active_set(struct Mesh *me, int index, int type);
void BKE_mesh_calc_normals_mapping(
struct MVert *mverts, int numVerts,
- struct MLoop *mloop, struct MPoly *mpolys, int numLoops, int numPolys, float (*r_polyNors)[3],
- struct MFace *mfaces, int numFaces, const int *origIndexFace, float (*r_faceNors)[3]);
+ const struct MLoop *mloop, const struct MPoly *mpolys, int numLoops, int numPolys, float (*r_polyNors)[3],
+ const struct MFace *mfaces, int numFaces, const int *origIndexFace, float (*r_faceNors)[3]);
void BKE_mesh_calc_normals_mapping_ex(
struct MVert *mverts, int numVerts,
- struct MLoop *mloop, struct MPoly *mpolys, int numLoops, int numPolys, float (*r_polyNors)[3],
- struct MFace *mfaces, int numFaces, const int *origIndexFace, float (*r_faceNors)[3],
+ const struct MLoop *mloop, const struct MPoly *mpolys,
+ int numLoops, int numPolys, float (*r_polyNors)[3],
+ const struct MFace *mfaces, int numFaces, const int *origIndexFace, float (*r_faceNors)[3],
const bool only_face_normals);
void BKE_mesh_calc_normals_poly(
struct MVert *mverts, int numVerts,
- struct MLoop *mloop, struct MPoly *mpolys,
+ const struct MLoop *mloop, const struct MPoly *mpolys,
int numLoops, int numPolys, float (*r_polyNors)[3],
const bool only_face_normals);
void BKE_mesh_calc_normals(struct Mesh *me);
void BKE_mesh_calc_normals_tessface(
struct MVert *mverts, int numVerts,
- struct MFace *mfaces, int numFaces,
+ const struct MFace *mfaces, int numFaces,
float (*r_faceNors)[3]);
-void BKE_mesh_normals_loop_split(
- struct MVert *mverts, const int numVerts, struct MEdge *medges, const int numEdges,
- struct MLoop *mloops, float (*r_loopnors)[3], const int numLoops,
- struct MPoly *mpolys, float (*polynors)[3], const int numPolys, float split_angle);
+void BKE_mesh_calc_normals_looptri(
+ struct MVert *mverts, int numVerts,
+ const struct MLoop *mloop,
+ const struct MLoopTri *looptri, int looptri_num,
+ float (*r_tri_nors)[3]);
void BKE_mesh_loop_tangents_ex(
- struct MVert *mverts, const int numVerts, struct MLoop *mloops, float (*r_looptangent)[4], float (*loopnors)[3],
- struct MLoopUV *loopuv, const int numLoops, struct MPoly *mpolys, const int numPolys,
+ const struct MVert *mverts, const int numVerts, const struct MLoop *mloops,
+ float (*r_looptangent)[4], float (*loopnors)[3], const struct MLoopUV *loopuv,
+ const int numLoops, const struct MPoly *mpolys, const int numPolys,
struct ReportList *reports);
void BKE_mesh_loop_tangents(
struct Mesh *mesh, const char *uvmap, float (*r_looptangents)[4], struct ReportList *reports);
+/**
+ * References a contiguous loop-fan with normal offset vars.
+ */
+typedef struct MLoopNorSpace {
+ float vec_lnor[3]; /* Automatically computed loop normal. */
+ float vec_ref[3]; /* Reference vector, orthogonal to vec_lnor. */
+ float vec_ortho[3]; /* Third vector, orthogonal to vec_lnor and vec_ref. */
+ float ref_alpha; /* Reference angle, around vec_ortho, in ]0, pi] range (0.0 marks that space as invalid). */
+ float ref_beta; /* Reference angle, around vec_lnor, in ]0, 2pi] range (0.0 marks that space as invalid). */
+ struct LinkNode *loops; /* All indices (uint_in_ptr) of loops using this lnor space (i.e. smooth fan of loops). */
+} MLoopNorSpace;
+/**
+ * Collection of #MLoopNorSpace basic storage & pre-allocation.
+ */
+typedef struct MLoopNorSpaceArray {
+ MLoopNorSpace **lspacearr; /* MLoop aligned array */
+ struct LinkNode *loops_pool; /* Allocated once, avoids to call BLI_linklist_prepend_arena() for each loop! */
+ struct MemArena *mem;
+} MLoopNorSpaceArray;
+void BKE_lnor_spacearr_init(MLoopNorSpaceArray *lnors_spacearr, const int numLoops);
+void BKE_lnor_spacearr_clear(MLoopNorSpaceArray *lnors_spacearr);
+void BKE_lnor_spacearr_free(MLoopNorSpaceArray *lnors_spacearr);
+MLoopNorSpace *BKE_lnor_space_create(MLoopNorSpaceArray *lnors_spacearr);
+void BKE_lnor_space_define(
+ MLoopNorSpace *lnor_space, const float lnor[3], float vec_ref[3], float vec_other[3],
+ struct BLI_Stack *edge_vectors);
+void BKE_lnor_space_add_loop(
+ MLoopNorSpaceArray *lnors_spacearr, MLoopNorSpace *lnor_space, const int ml_index, const bool add_to_list);
+void BKE_lnor_space_custom_data_to_normal(MLoopNorSpace *lnor_space, const short clnor_data[2], float r_custom_lnor[3]);
+void BKE_lnor_space_custom_normal_to_data(MLoopNorSpace *lnor_space, const float custom_lnor[3], short r_clnor_data[2]);
+
+bool BKE_mesh_has_custom_loop_normals(struct Mesh *me);
+
+void BKE_mesh_normals_loop_split(
+ const struct MVert *mverts, const int numVerts, struct MEdge *medges, const int numEdges,
+ struct MLoop *mloops, float (*r_loopnors)[3], const int numLoops,
+ struct MPoly *mpolys, const float (*polynors)[3], const int numPolys,
+ const bool use_split_normals, float split_angle,
+ MLoopNorSpaceArray *r_lnors_spacearr, short (*clnors_data)[2], int *r_loop_to_poly);
+
+void BKE_mesh_normals_loop_custom_set(
+ const struct MVert *mverts, const int numVerts, struct MEdge *medges, const int numEdges,
+ struct MLoop *mloops, float (*r_custom_loopnors)[3], const int numLoops,
+ struct MPoly *mpolys, const float (*polynors)[3], const int numPolys,
+ short (*r_clnors_data)[2]);
+void BKE_mesh_normals_loop_custom_from_vertices_set(
+ const struct MVert *mverts, float (*r_custom_vertnors)[3], const int numVerts,
+ struct MEdge *medges, const int numEdges, struct MLoop *mloops, const int numLoops,
+ struct MPoly *mpolys, const float (*polynors)[3], const int numPolys,
+ short (*r_clnors_data)[2]);
+
+void BKE_mesh_normals_loop_to_vertex(
+ const int numVerts, const struct MLoop *mloops, const int numLoops,
+ const float (*clnors)[3], float (*r_vert_clnors)[3]);
+
void BKE_mesh_calc_poly_normal(
- struct MPoly *mpoly, struct MLoop *loopstart,
- struct MVert *mvarray, float no[3]);
+ const struct MPoly *mpoly, const struct MLoop *loopstart,
+ const struct MVert *mvarray, float r_no[3]);
void BKE_mesh_calc_poly_normal_coords(
- struct MPoly *mpoly, struct MLoop *loopstart,
- const float (*vertex_coords)[3], float no[3]);
+ const struct MPoly *mpoly, const struct MLoop *loopstart,
+ const float (*vertex_coords)[3], float r_no[3]);
void BKE_mesh_calc_poly_center(
- struct MPoly *mpoly, struct MLoop *loopstart,
- struct MVert *mvarray, float cent[3]);
+ const struct MPoly *mpoly, const struct MLoop *loopstart,
+ const struct MVert *mvarray, float r_cent[3]);
float BKE_mesh_calc_poly_area(
- struct MPoly *mpoly, struct MLoop *loopstart,
- struct MVert *mvarray);
+ const struct MPoly *mpoly, const struct MLoop *loopstart,
+ const struct MVert *mvarray);
void BKE_mesh_calc_poly_angles(
- struct MPoly *mpoly, struct MLoop *loopstart,
- struct MVert *mvarray, float angles[]);
+ const struct MPoly *mpoly, const struct MLoop *loopstart,
+ const struct MVert *mvarray, float angles[]);
void BKE_mesh_poly_edgehash_insert(
struct EdgeHash *ehash,
@@ -209,13 +271,15 @@ void BKE_mesh_poly_edgebitmap_insert(
const struct MPoly *mp, const struct MLoop *mloop);
-bool BKE_mesh_center_median(struct Mesh *me, float cent[3]);
-bool BKE_mesh_center_bounds(struct Mesh *me, float cent[3]);
-bool BKE_mesh_center_centroid(struct Mesh *me, float cent[3]);
+bool BKE_mesh_center_median(const struct Mesh *me, float r_cent[3]);
+bool BKE_mesh_center_bounds(const struct Mesh *me, float r_cent[3]);
+bool BKE_mesh_center_centroid(const struct Mesh *me, float r_cent[3]);
-void BKE_mesh_calc_volume(struct MVert *mverts, int numVerts,
- struct MFace *mfaces, int numFaces,
- float *r_vol, float *r_com);
+void BKE_mesh_calc_volume(
+ const struct MVert *mverts, const int mverts_num,
+ const struct MLoopTri *mlooptri, const int looptri_num,
+ const struct MLoop *mloop,
+ float *r_volume, float r_center[3]);
/* tessface */
void BKE_mesh_loops_to_mface_corners(
@@ -227,11 +291,18 @@ void BKE_mesh_loops_to_mface_corners(
void BKE_mesh_loops_to_tessdata(
struct CustomData *fdata, struct CustomData *ldata, struct CustomData *pdata, struct MFace *mface,
int *polyindices, unsigned int (*loopindices)[4], const int num_faces);
+void BKE_mesh_tangent_loops_to_tessdata(struct CustomData *fdata, struct CustomData *ldata, struct MFace *mface,
+ int *polyindices, unsigned int (*loopindices)[4], const int num_faces);
int BKE_mesh_recalc_tessellation(
struct CustomData *fdata, struct CustomData *ldata, struct CustomData *pdata,
struct MVert *mvert,
int totface, int totloop, int totpoly,
- const bool do_face_normals);
+ const bool do_face_nor_copy);
+void BKE_mesh_recalc_looptri(
+ const struct MLoop *mloop, const struct MPoly *mpoly,
+ const struct MVert *mvert,
+ int totloop, int totpoly,
+ struct MLoopTri *mlooptri);
int BKE_mesh_mpoly_to_mface(
struct CustomData *fdata, struct CustomData *ldata,
struct CustomData *pdata, int totface, int totloop, int totpoly);
@@ -286,7 +357,7 @@ void BKE_mesh_calc_relative_deform(
/* *** mesh_validate.c *** */
-int BKE_mesh_validate(struct Mesh *me, const int do_verbose);
+int BKE_mesh_validate(struct Mesh *me, const int do_verbose, const int cddata_check_mask);
void BKE_mesh_cd_validate(struct Mesh *me);
int BKE_mesh_validate_material_indices(struct Mesh *me);
@@ -315,6 +386,13 @@ void BKE_mesh_strip_loose_edges(struct Mesh *me);
void BKE_mesh_calc_edges_legacy(struct Mesh *me, const bool use_old);
void BKE_mesh_calc_edges(struct Mesh *mesh, bool update, const bool select);
+/* **** Depsgraph evaluation **** */
+
+struct EvaluationContext;
+
+void BKE_mesh_eval_geometry(struct EvaluationContext *eval_ctx,
+ struct Mesh *mesh);
+
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/blenkernel/BKE_mesh_mapping.h b/source/blender/blenkernel/BKE_mesh_mapping.h
index ed7e506941c..c8a17008f5d 100644
--- a/source/blender/blenkernel/BKE_mesh_mapping.h
+++ b/source/blender/blenkernel/BKE_mesh_mapping.h
@@ -31,10 +31,12 @@
* \ingroup bke
*/
-struct MPoly;
+struct MVert;
struct MEdge;
+struct MPoly;
struct MLoop;
struct MLoopUV;
+struct MLoopTri;
/* map from uv vertex to face (for select linked, stitch, uv suburf) */
@@ -101,7 +103,8 @@ typedef struct MeshElemMap {
/* mapping */
UvVertMap *BKE_mesh_uv_vert_map_create(
struct MPoly *mpoly, struct MLoop *mloop, struct MLoopUV *mloopuv,
- unsigned int totpoly, unsigned int totvert, int selected, float *limit);
+ unsigned int totpoly, unsigned int totvert,
+ const float limit[2], const bool selected, const bool use_winding);
UvMapVert *BKE_mesh_uv_vert_map_get_vert(UvVertMap *vmap, unsigned int v);
void BKE_mesh_uv_vert_map_free(UvVertMap *vmap);
@@ -109,6 +112,10 @@ void BKE_mesh_vert_poly_map_create(
MeshElemMap **r_map, int **r_mem,
const struct MPoly *mface, const struct MLoop *mloop,
int totvert, int totface, int totloop);
+void BKE_mesh_vert_loop_map_create(
+ MeshElemMap **r_map, int **r_mem,
+ const struct MPoly *mface, const struct MLoop *mloop,
+ int totvert, int totface, int totloop);
void BKE_mesh_vert_edge_map_create(
MeshElemMap **r_map, int **r_mem,
const struct MEdge *medge, int totvert, int totedge);
@@ -121,8 +128,65 @@ void BKE_mesh_origindex_map_create(
MeshElemMap **r_map, int **r_mem,
const int totorig,
const int *final_origindex, const int totfinal);
+void BKE_mesh_origindex_map_create_looptri(
+ MeshElemMap **r_map, int **r_mem,
+ const struct MPoly *mpoly, const int mpoly_num,
+ const struct MLoopTri *looptri, const int looptri_num);
+
+/* islands */
+
+/* Loop islands data helpers. */
+enum {
+ MISLAND_TYPE_NONE = 0,
+ MISLAND_TYPE_VERT = 1,
+ MISLAND_TYPE_EDGE = 2,
+ MISLAND_TYPE_POLY = 3,
+ MISLAND_TYPE_LOOP = 4,
+};
+
+typedef struct MeshIslandStore {
+ short item_type; /* MISLAND_TYPE_... */
+ short island_type; /* MISLAND_TYPE_... */
+ short innercut_type; /* MISLAND_TYPE_... */
+
+ int items_to_islands_num;
+ int *items_to_islands; /* map the item to the island index */
+
+ int islands_num;
+ size_t islands_num_alloc;
+ struct MeshElemMap **islands; /* Array of pointers, one item per island. */
+ struct MeshElemMap **innercuts; /* Array of pointers, one item per island. */
+
+ struct MemArena *mem; /* Memory arena, internal use only. */
+} MeshIslandStore;
+
+void BKE_mesh_loop_islands_init(
+ MeshIslandStore *island_store,
+ const short item_type, const int item_num, const short island_type, const short innercut_type);
+void BKE_mesh_loop_islands_clear(MeshIslandStore *island_store);
+void BKE_mesh_loop_islands_free(MeshIslandStore *island_store);
+void BKE_mesh_loop_islands_add(
+ MeshIslandStore *islands, const int item_num, int *item_indices,
+ const int num_island_items, int *island_item_indices,
+ const int num_innercut_items, int *innercut_item_indices);
+
+typedef bool (*MeshRemapIslandsCalc)(
+ struct MVert *verts, const int totvert,
+ struct MEdge *edges, const int totedge,
+ struct MPoly *polys, const int totpoly,
+ struct MLoop *loops, const int totloop,
+ struct MeshIslandStore *r_island_store);
+
+/* Above vert/UV mapping stuff does not do what we need here, but does things we do not need here.
+ * So better keep them separated for now, I think.
+ */
+bool BKE_mesh_calc_islands_loop_poly_uv(
+ struct MVert *verts, const int totvert,
+ struct MEdge *edges, const int totedge,
+ struct MPoly *polys, const int totpoly,
+ struct MLoop *loops, const int totloop,
+ MeshIslandStore *r_island_store);
-/* smoothgroups */
int *BKE_mesh_calc_smoothgroups(
const struct MEdge *medge, const int totedge,
const struct MPoly *mpoly, const int totpoly,
@@ -139,4 +203,14 @@ int *BKE_mesh_calc_smoothgroups(
(_mf->v4 && _mf->v4 == _v) ? 3 : -1) \
)
+/* use on looptri vertex values */
+#define BKE_MESH_TESSTRI_VINDEX_ORDER(_tri, _v) ( \
+ (CHECK_TYPE_ANY(_tri, unsigned int *, int *, int[3], \
+ const unsigned int *, const int *, const int[3]), \
+ CHECK_TYPE_ANY(_v, unsigned int, const unsigned int, int, const int)), \
+ (((_tri)[0] == _v) ? 0 : \
+ ((_tri)[1] == _v) ? 1 : \
+ ((_tri)[2] == _v) ? 2 : -1) \
+ )
+
#endif /* __BKE_MESH_MAPPING_H__ */
diff --git a/source/blender/blenkernel/BKE_mesh_remap.h b/source/blender/blenkernel/BKE_mesh_remap.h
new file mode 100644
index 00000000000..5c77ab8a94e
--- /dev/null
+++ b/source/blender/blenkernel/BKE_mesh_remap.h
@@ -0,0 +1,178 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __BKE_MESH_REMAP_H__
+#define __BKE_MESH_REMAP_H__
+
+/** \file BKE_mesh_remap.h
+ * \ingroup bke
+ */
+
+struct CustomData;
+struct DerivedMesh;
+struct MVert;
+struct MemArena;
+
+/* Generic ways to map some geometry elements from a source mesh to a dest one. */
+
+typedef struct MeshPairRemapItem {
+ int sources_num;
+ int *indices_src; /* NULL if no source found. */
+ float *weights_src; /* NULL if no source found, else, always normalized! */
+ /* UNUSED (at the moment)*/
+ // float hit_dist; /* FLT_MAX if irrelevant or no source found. */
+ int island; /* For loops only. */
+} MeshPairRemapItem;
+
+/* All mapping computing func return this. */
+typedef struct MeshPairRemap {
+ int items_num;
+ MeshPairRemapItem *items; /* array, one item per dest element. */
+
+ struct MemArena *mem; /* memory arena, internal use only. */
+} MeshPairRemap;
+
+/* Helpers! */
+void BKE_mesh_remap_init(MeshPairRemap *map, const int items_num);
+void BKE_mesh_remap_free(MeshPairRemap *map);
+
+void BKE_mesh_remap_item_define_invalid(MeshPairRemap *map, const int index);
+
+/* TODO:
+ * Add other 'from/to' mapping sources, like e.g. using an UVMap, etc.
+ * http://blenderartists.org/forum/showthread.php?346458-Move-Vertices-to-the-location-of-the-Reference-Mesh-based-on-the-UV-Position
+ * We could also use similar topology mappings inside a same mesh
+ * (cf. Campbell's 'select face islands from similar topology' wip work).
+ * Also, users will have to check, whether we can get rid of some modes here, not sure all will be useful!
+ */
+enum {
+ MREMAP_USE_VERT = 1 << 4,
+ MREMAP_USE_EDGE = 1 << 5,
+ MREMAP_USE_LOOP = 1 << 6,
+ MREMAP_USE_POLY = 1 << 7,
+
+ MREMAP_USE_NEAREST = 1 << 8,
+ MREMAP_USE_NORPROJ = 1 << 9,
+ MREMAP_USE_INTERP = 1 << 10,
+ MREMAP_USE_NORMAL = 1 << 11,
+
+ /* ***** Target's vertices ***** */
+ MREMAP_MODE_VERT = 1 << 24,
+ /* Nearest source vert. */
+ MREMAP_MODE_VERT_NEAREST = MREMAP_MODE_VERT | MREMAP_USE_VERT | MREMAP_USE_NEAREST,
+
+ /* Nearest vertex of nearest edge. */
+ MREMAP_MODE_VERT_EDGE_NEAREST = MREMAP_MODE_VERT | MREMAP_USE_EDGE | MREMAP_USE_NEAREST,
+ /* This one uses two verts of selected edge (weighted interpolation). */
+ /* Nearest point on nearest edge. */
+ MREMAP_MODE_VERT_EDGEINTERP_NEAREST = MREMAP_MODE_VERT | MREMAP_USE_EDGE | MREMAP_USE_NEAREST | MREMAP_USE_INTERP,
+
+ /* Nearest vertex of nearest poly. */
+ MREMAP_MODE_VERT_POLY_NEAREST = MREMAP_MODE_VERT | MREMAP_USE_POLY | MREMAP_USE_NEAREST,
+ /* Those two use all verts of selected poly (weighted interpolation). */
+ /* Nearest point on nearest poly. */
+ MREMAP_MODE_VERT_POLYINTERP_NEAREST = MREMAP_MODE_VERT | MREMAP_USE_POLY | MREMAP_USE_NEAREST | MREMAP_USE_INTERP,
+ /* Point on nearest face hit by ray from target vertex's normal. */
+ MREMAP_MODE_VERT_POLYINTERP_VNORPROJ = MREMAP_MODE_VERT | MREMAP_USE_POLY | MREMAP_USE_NORPROJ | MREMAP_USE_INTERP,
+
+ /* ***** Target's edges ***** */
+ MREMAP_MODE_EDGE = 1 << 25,
+
+ /* Source edge which both vertices are nearest of dest ones. */
+ MREMAP_MODE_EDGE_VERT_NEAREST = MREMAP_MODE_EDGE | MREMAP_USE_VERT | MREMAP_USE_NEAREST,
+
+ /* Nearest source edge (using mid-point). */
+ MREMAP_MODE_EDGE_NEAREST = MREMAP_MODE_EDGE | MREMAP_USE_EDGE | MREMAP_USE_NEAREST,
+
+ /* Nearest edge of nearest poly (using mid-point). */
+ MREMAP_MODE_EDGE_POLY_NEAREST = MREMAP_MODE_EDGE | MREMAP_USE_POLY | MREMAP_USE_NEAREST,
+
+ /* Cast a set of rays from along dest edge, interpolating its vertices' normals, and use hit source edges. */
+ MREMAP_MODE_EDGE_EDGEINTERP_VNORPROJ = MREMAP_MODE_EDGE | MREMAP_USE_VERT | MREMAP_USE_NORPROJ | MREMAP_USE_INTERP,
+
+ /* ***** Target's loops ***** */
+ /* Note: when islands are given to loop mapping func, all loops from the same destination face will always be mapped
+ * to loops of source faces within a same island, regardless of mapping mode. */
+ MREMAP_MODE_LOOP = 1 << 26,
+
+ /* Best normal-matching loop from nearest vert. */
+ MREMAP_MODE_LOOP_NEAREST_LOOPNOR = MREMAP_MODE_LOOP | MREMAP_USE_LOOP | MREMAP_USE_VERT | MREMAP_USE_NEAREST | MREMAP_USE_NORMAL,
+ /* Loop from best normal-matching poly from nearest vert. */
+ MREMAP_MODE_LOOP_NEAREST_POLYNOR = MREMAP_MODE_LOOP | MREMAP_USE_POLY | MREMAP_USE_VERT | MREMAP_USE_NEAREST | MREMAP_USE_NORMAL,
+
+ /* Loop from nearest vertex of nearest poly. */
+ MREMAP_MODE_LOOP_POLY_NEAREST = MREMAP_MODE_LOOP | MREMAP_USE_POLY | MREMAP_USE_NEAREST,
+ /* Those two use all verts of selected poly (weighted interpolation). */
+ /* Nearest point on nearest poly. */
+ MREMAP_MODE_LOOP_POLYINTERP_NEAREST = MREMAP_MODE_LOOP | MREMAP_USE_POLY | MREMAP_USE_NEAREST | MREMAP_USE_INTERP,
+ /* Point on nearest face hit by ray from target loop's normal. */
+ MREMAP_MODE_LOOP_POLYINTERP_LNORPROJ = MREMAP_MODE_LOOP | MREMAP_USE_POLY | MREMAP_USE_NORPROJ | MREMAP_USE_INTERP,
+
+ /* ***** Target's polygons ***** */
+ MREMAP_MODE_POLY = 1 << 27,
+
+ /* Nearest source poly. */
+ MREMAP_MODE_POLY_NEAREST = MREMAP_MODE_POLY | MREMAP_USE_POLY | MREMAP_USE_NEAREST,
+ /* Source poly from best normal-matching dest poly. */
+ MREMAP_MODE_POLY_NOR = MREMAP_MODE_POLY | MREMAP_USE_POLY | MREMAP_USE_NORMAL,
+
+ /* Project dest poly onto source mesh using its normal, and use interpolation of all intersecting source polys. */
+ MREMAP_MODE_POLY_POLYINTERP_PNORPROJ = MREMAP_MODE_POLY | MREMAP_USE_POLY | MREMAP_USE_NORPROJ | MREMAP_USE_INTERP,
+
+ /* ***** Same topology, applies to all four elements types. ***** */
+ MREMAP_MODE_TOPOLOGY = MREMAP_MODE_VERT | MREMAP_MODE_EDGE | MREMAP_MODE_LOOP | MREMAP_MODE_POLY,
+};
+
+float BKE_mesh_remap_calc_difference_from_dm(
+ const struct SpaceTransform *space_transform,
+ const struct MVert *verts_dst, const int numverts_dst, struct DerivedMesh *dm_src);
+
+void BKE_mesh_remap_find_best_match_from_dm(
+ const struct MVert *verts_dst, const int numverts_dst, struct DerivedMesh *dm_src,
+ struct SpaceTransform *r_space_transform);
+
+/* TODO add mesh2mesh versions (we'll need mesh versions of bvhtree funcs too, though!). */
+
+void BKE_mesh_remap_calc_verts_from_dm(
+ const int mode, const struct SpaceTransform *space_transform, const float max_dist, const float ray_radius,
+ const struct MVert *verts_dst, const int numverts_dst, const bool dirty_nors_dst,
+ struct DerivedMesh *dm_src, MeshPairRemap *r_map);
+
+void BKE_mesh_remap_calc_edges_from_dm(
+ const int mode, const struct SpaceTransform *space_transform, const float max_dist, const float ray_radius,
+ const struct MVert *verts_dst, const int numverts_dst, const struct MEdge *edges_dst, const int numedges_dst,
+ const bool dirty_nors_dst, struct DerivedMesh *dm_src, MeshPairRemap *r_map);
+
+void BKE_mesh_remap_calc_loops_from_dm(
+ const int mode, const struct SpaceTransform *space_transform, const float max_dist, const float ray_radius,
+ struct MVert *verts_dst, const int numverts_dst, struct MEdge *edges_dst, const int numedges_dst,
+ struct MLoop *loops_dst, const int numloops_dst, struct MPoly *polys_dst, const int numpolys_dst,
+ struct CustomData *ldata_dst, struct CustomData *pdata_dst,
+ const bool use_split_nors_dst, const float split_angle_dst, const bool dirty_nors_dst,
+ struct DerivedMesh *dm_src, const bool use_split_nors_src, const float split_angle_src,
+ MeshRemapIslandsCalc gen_islands_src, const float islands_precision_src, struct MeshPairRemap *r_map);
+
+void BKE_mesh_remap_calc_polys_from_dm(
+ const int mode, const struct SpaceTransform *space_transform, const float max_dist, const float ray_radius,
+ struct MVert *verts_dst, const int numverts_dst, struct MLoop *loops_dst, const int numloops_dst,
+ struct MPoly *polys_dst, const int numpolys_dst, struct CustomData *pdata_dst, const bool dirty_nors_dst,
+ struct DerivedMesh *dm_src, struct MeshPairRemap *r_map);
+
+#endif /* __BKE_MESH_REMAP_H__ */
diff --git a/source/blender/blenkernel/BKE_modifier.h b/source/blender/blenkernel/BKE_modifier.h
index 75616b9df78..ded6e13e003 100644
--- a/source/blender/blenkernel/BKE_modifier.h
+++ b/source/blender/blenkernel/BKE_modifier.h
@@ -39,10 +39,11 @@ struct DagNode;
struct Object;
struct Scene;
struct ListBase;
-struct LinkNode;
struct bArmature;
+struct Main;
struct ModifierData;
struct BMEditMesh;
+struct DepsNodeHandle;
typedef enum {
/* Should not be used, only for None modifier type */
@@ -115,6 +116,12 @@ typedef enum ModifierApplyFlag {
MOD_APPLY_IGNORE_SIMPLIFY = 1 << 3, /* Ignore scene simplification flag and use subdivisions
* level set in multires modifier.
*/
+ MOD_APPLY_ALLOW_GPU = 1 << 4, /* Allow modifier to be applied and stored in the GPU.
+ * Used by the viewport in order to be able to have SS
+ * happening on GPU.
+ * Render pipeline (including viewport render) should
+ * have DM on the CPU.
+ */
} ModifierApplyFlag;
@@ -256,9 +263,21 @@ typedef struct ModifierTypeInfo {
*
* This function is optional.
*/
- void (*updateDepgraph)(struct ModifierData *md, struct DagForest *forest, struct Scene *scene,
+ void (*updateDepgraph)(struct ModifierData *md, struct DagForest *forest,
+ struct Main *bmain, struct Scene *scene,
struct Object *ob, struct DagNode *obNode);
+ /* Add the appropriate relations to the dependency graph.
+ *
+ * This function is optional.
+ */
+ /* TODO(sergey): Remove once we finalyl switched to the new depsgraph. */
+ void (*updateDepsgraph)(struct ModifierData *md,
+ struct Main *bmain,
+ struct Scene *scene,
+ struct Object *ob,
+ struct DepsNodeHandle *node);
+
/* Should return true if the modifier needs to be recalculated on time
* changes.
*
@@ -311,7 +330,7 @@ typedef struct ModifierTypeInfo {
/* Initialize modifier's global data (type info and some common global storages). */
void BKE_modifier_init(void);
-ModifierTypeInfo *modifierType_getInfo(ModifierType type);
+const ModifierTypeInfo *modifierType_getInfo(ModifierType type);
/* Modifier utility calls, do call through type pointer and return
* default values if pointer is optional.
@@ -319,7 +338,7 @@ ModifierTypeInfo *modifierType_getInfo(ModifierType type);
struct ModifierData *modifier_new(int type);
void modifier_free(struct ModifierData *md);
-void modifier_unique_name(struct ListBase *modifiers, struct ModifierData *md);
+bool modifier_unique_name(struct ListBase *modifiers, struct ModifierData *md);
void modifier_copyData_generic(const struct ModifierData *md, struct ModifierData *target);
void modifier_copyData(struct ModifierData *md, struct ModifierData *target);
diff --git a/source/blender/blenkernel/BKE_movieclip.h b/source/blender/blenkernel/BKE_movieclip.h
index 341105cfdf7..7d7675270de 100644
--- a/source/blender/blenkernel/BKE_movieclip.h
+++ b/source/blender/blenkernel/BKE_movieclip.h
@@ -37,7 +37,6 @@ struct Main;
struct MovieClip;
struct MovieClipScopes;
struct MovieClipUser;
-struct MovieTrackingTrack;
struct MovieDistortion;
void BKE_movieclip_free(struct MovieClip *clip);
@@ -46,6 +45,7 @@ void BKE_movieclip_unlink(struct Main *bmain, struct MovieClip *clip);
struct MovieClip *BKE_movieclip_file_add(struct Main *bmain, const char *name);
void BKE_movieclip_reload(struct MovieClip *clip);
void BKE_movieclip_clear_cache(struct MovieClip *clip);
+void BKE_movieclip_clear_proxy_cache(struct MovieClip *clip);
struct ImBuf *BKE_movieclip_get_ibuf(struct MovieClip *clip, struct MovieClipUser *user);
struct ImBuf *BKE_movieclip_get_postprocessed_ibuf(struct MovieClip *clip, struct MovieClipUser *user, int postprocess_flag);
@@ -60,7 +60,7 @@ void BKE_movieclip_user_set_frame(struct MovieClipUser *user, int framenr);
void BKE_movieclip_update_scopes(struct MovieClip *clip, struct MovieClipUser *user, struct MovieClipScopes *scopes);
-void BKE_movieclip_get_cache_segments(struct MovieClip *clip, struct MovieClipUser *user, int *totseg_r, int **points_r);
+void BKE_movieclip_get_cache_segments(struct MovieClip *clip, struct MovieClipUser *user, int *r_totseg, int **r_points);
void BKE_movieclip_build_proxy_frame(struct MovieClip *clip, int clip_flag, struct MovieDistortion *distortion,
int cfra, int *build_sizes, int build_count, bool undistorted);
diff --git a/source/blender/blenkernel/BKE_multires.h b/source/blender/blenkernel/BKE_multires.h
index 11d81a149b1..178751d1640 100644
--- a/source/blender/blenkernel/BKE_multires.h
+++ b/source/blender/blenkernel/BKE_multires.h
@@ -34,9 +34,7 @@
enum MultiresModifiedFlags;
struct DerivedMesh;
-struct GridHidden;
struct MDisps;
-struct MFace;
struct Mesh;
struct ModifierData;
struct Multires;
@@ -44,6 +42,11 @@ struct MultiresModifierData;
struct Object;
struct Scene;
+struct MLoop;
+struct MVert;
+struct MPoly;
+struct MLoopTri;
+
/* Delete mesh mdisps and grid paint masks */
void multires_customdata_delete(struct Mesh *me);
@@ -81,8 +84,9 @@ struct DerivedMesh *get_multires_dm(struct Scene *scene, struct MultiresModifier
struct Object *ob);
void multiresModifier_del_levels(struct MultiresModifierData *, struct Object *, int direction);
void multiresModifier_base_apply(struct MultiresModifierData *mmd, struct Object *ob);
-void multiresModifier_subdivide(struct MultiresModifierData *mmd, struct Object *ob,
- int updateblock, int simple);
+void multiresModifier_subdivide(struct MultiresModifierData *mmd, struct Object *ob, int updateblock, int simple);
+void multiresModifier_sync_levels_ex(
+ struct Object *ob_dst, struct MultiresModifierData *mmd_src, struct MultiresModifierData *mmd_dst);
int multiresModifier_reshape(struct Scene *scene, struct MultiresModifierData *mmd,
struct Object *dst, struct Object *src);
int multiresModifier_reshapeFromDM(struct Scene *scene, struct MultiresModifierData *mmd,
@@ -115,6 +119,6 @@ void multires_topology_changed(struct Mesh *me);
/**** interpolation stuff ****/
void old_mdisps_bilinear(float out[3], float (*disps)[3], const int st, float u, float v);
-int mdisp_rot_face_to_crn(const int corners, const int face_side, const float u, const float v, float *x, float *y);
+int mdisp_rot_face_to_crn(struct MVert *mvert, struct MPoly *mpoly, struct MLoop *mloops, const struct MLoopTri *lt, const int face_side, const float u, const float v, float *x, float *y);
#endif /* __BKE_MULTIRES_H__ */
diff --git a/source/blender/blenkernel/BKE_nla.h b/source/blender/blenkernel/BKE_nla.h
index 0c29179aa1c..3bf8bba47f5 100644
--- a/source/blender/blenkernel/BKE_nla.h
+++ b/source/blender/blenkernel/BKE_nla.h
@@ -76,6 +76,8 @@ void BKE_nlameta_flush_transforms(struct NlaStrip *mstrip);
struct NlaTrack *BKE_nlatrack_find_active(ListBase *tracks);
void BKE_nlatrack_set_active(ListBase *tracks, struct NlaTrack *nlt);
+struct NlaTrack *BKE_nlatrack_find_tweaked(struct AnimData *adt);
+
void BKE_nlatrack_solo_toggle(struct AnimData *adt, struct NlaTrack *nlt);
bool BKE_nlatrack_has_space(struct NlaTrack *nlt, float start, float end);
@@ -105,6 +107,11 @@ void BKE_nla_validate_state(struct AnimData *adt);
/* ............ */
+bool BKE_nla_action_is_stashed(struct AnimData *adt, struct bAction *act);
+bool BKE_nla_action_stash(struct AnimData *adt);
+
+/* ............ */
+
void BKE_nla_action_pushdown(struct AnimData *adt);
bool BKE_nla_tweakmode_enter(struct AnimData *adt);
diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h
index cb96538ad81..b97bf203a7c 100644
--- a/source/blender/blenkernel/BKE_node.h
+++ b/source/blender/blenkernel/BKE_node.h
@@ -62,30 +62,27 @@ struct bNodeTreeExec;
struct bNodeExecContext;
struct bNodeExecData;
struct GPUMaterial;
-struct GPUNode;
struct GPUNodeStack;
struct ID;
struct ImBuf;
struct ImageFormatData;
struct ListBase;
struct Main;
-struct uiBlock;
struct uiLayout;
struct MTex;
struct PointerRNA;
-struct rctf;
struct RenderData;
struct Scene;
struct Tex;
struct SpaceNode;
struct ARegion;
-struct Object;
struct ColorManagedViewSettings;
struct ColorManagedDisplaySettings;
struct bNodeInstanceHash;
-
-/* ************** NODE TYPE DEFINITIONS ***** */
+/* -------------------------------------------------------------------- */
+/** \name Node Type Definitions
+ * \{ */
/** Compact definition of a node socket.
* Can be used to quickly define a list of static sockets for a node,
@@ -314,12 +311,15 @@ typedef struct bNodeTreeType {
ExtensionRNA ext;
} bNodeTreeType;
+/** \} */
-/* ************** GENERIC API, TREES *************** */
+/* -------------------------------------------------------------------- */
+/** \name Generic API, Trees
+ * \{ */
struct bNodeTreeType *ntreeTypeFind(const char *idname);
void ntreeTypeAdd(struct bNodeTreeType *nt);
-void ntreeTypeFreeLink(struct bNodeTreeType *nt);
+void ntreeTypeFreeLink(const struct bNodeTreeType *nt);
bool ntreeIsRegistered(struct bNodeTree *ntree);
struct GHashIterator *ntreeTypeGetIterator(void);
@@ -373,12 +373,17 @@ void ntreeFreeCache(struct bNodeTree *ntree);
int ntreeNodeExists(struct bNodeTree *ntree, struct bNode *testnode);
int ntreeOutputExists(struct bNode *node, struct bNodeSocket *testsock);
+void ntreeNodeFlagSet(const bNodeTree *ntree, const int flag, const bool enable);
struct bNodeTree *ntreeLocalize(struct bNodeTree *ntree);
void ntreeLocalSync(struct bNodeTree *localtree, struct bNodeTree *ntree);
void ntreeLocalMerge(struct bNodeTree *localtree, struct bNodeTree *ntree);
-/* ************** NODE TREE INTERFACE *************** */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Node Tree Interface
+ * \{ */
struct bNodeSocket *ntreeFindSocketInterface(struct bNodeTree *ntree, int in_out, const char *identifier);
struct bNodeSocket *ntreeAddSocketInterface(struct bNodeTree *ntree, int in_out, const char *idname, const char *name);
struct bNodeSocket *ntreeInsertSocketInterface(struct bNodeTree *ntree, int in_out, const char *idname,
@@ -392,7 +397,12 @@ struct StructRNA *ntreeInterfaceTypeGet(struct bNodeTree *ntree, int create);
void ntreeInterfaceTypeFree(struct bNodeTree *ntree);
void ntreeInterfaceTypeUpdate(struct bNodeTree *ntree);
-/* ************** GENERIC API, NODES *************** */
+/** \} */
+
+
+/* -------------------------------------------------------------------- */
+/** \name Generic API, Nodes
+ * \{ */
struct bNodeType *nodeTypeFind(const char *idname);
void nodeRegisterType(struct bNodeType *ntype);
@@ -455,7 +465,7 @@ struct bNode *nodeCopyNode(struct bNodeTree *ntree, struct bNode *node);
struct bNodeLink *nodeAddLink(struct bNodeTree *ntree, struct bNode *fromnode, struct bNodeSocket *fromsock, struct bNode *tonode, struct bNodeSocket *tosock);
void nodeRemLink(struct bNodeTree *ntree, struct bNodeLink *link);
void nodeRemSocketLinks(struct bNodeTree *ntree, struct bNodeSocket *sock);
-int nodeLinkIsHidden(struct bNodeLink *link);
+bool nodeLinkIsHidden(struct bNodeLink *link);
void nodeInternalRelink(struct bNodeTree *ntree, struct bNode *node);
void nodeToView(struct bNode *node, float x, float y, float *rx, float *ry);
@@ -466,6 +476,15 @@ void nodeDetachNode(struct bNode *node);
struct bNode *nodeFindNodebyName(struct bNodeTree *ntree, const char *name);
int nodeFindNode(struct bNodeTree *ntree, struct bNodeSocket *sock, struct bNode **nodep, int *sockindex);
+struct bNode *nodeFindRootParent(bNode *node);
+
+bool nodeIsChildOf(const bNode *parent, const bNode *child);
+
+void nodeChainIter(
+ const bNodeTree *ntree, const bNode *node_start,
+ bool (*callback)(bNode *, bNode *, void *, const bool), void *userdata,
+ const bool reversed);
+void nodeParentsIter(bNode *node, bool (*callback)(bNode *, void *), void *userdata);
struct bNodeLink *nodeFindLink(struct bNodeTree *ntree, struct bNodeSocket *from, struct bNodeSocket *to);
int nodeCountSocketLinks(struct bNodeTree *ntree, struct bNodeSocket *sock);
@@ -485,6 +504,7 @@ void nodeUpdateInternalLinks(struct bNodeTree *ntree, struct bNode *n
void nodeSynchronizeID(struct bNode *node, bool copy_to_id);
int nodeSocketIsHidden(struct bNodeSocket *sock);
+void ntreeTagUsedSockets(struct bNodeTree *ntree);
/* Node Clipboard */
void BKE_node_clipboard_init(struct bNodeTree *ntree);
@@ -497,8 +517,7 @@ const struct ListBase *BKE_node_clipboard_get_links(void);
int BKE_node_clipboard_get_type(void);
/* Node Instance Hash */
-typedef struct bNodeInstanceHash
-{
+typedef struct bNodeInstanceHash {
GHash *ghash; /* XXX should be made a direct member, GHash allocation needs to support it */
} bNodeInstanceHash;
@@ -557,8 +576,12 @@ void BKE_node_preview_merge_tree(struct bNodeTree *to_ntree, struct b
void BKE_node_preview_set_pixel(struct bNodePreview *preview, const float col[4], int x, int y, bool do_manage);
+/** \} */
+
-/* ************** NODE TYPE ACCESS *************** */
+/* -------------------------------------------------------------------- */
+/** \name Node Type Access
+ * \{ */
void nodeLabel(struct bNodeTree *ntree, struct bNode *node, char *label, int maxlen);
@@ -585,7 +608,11 @@ void node_type_gpu(struct bNodeType *ntype, NodeGPUExecFunction gpufu
void node_type_internal_links(struct bNodeType *ntype, void (*update_internal_links)(struct bNodeTree *, struct bNode *));
void node_type_compatibility(struct bNodeType *ntype, short compatibility);
-/* ************** GENERIC NODE FUNCTIONS *************** */
+
+/* -------------------------------------------------------------------- */
+/** \name Node Generic Functions
+ * \{ */
+
bool BKE_node_is_connected_to_output(struct bNodeTree *ntree, struct bNode *node);
/* ************** COMMON NODES *************** */
@@ -602,7 +629,12 @@ bool BKE_node_is_connected_to_output(struct bNodeTree *ntree, struct bNode *node
void BKE_node_tree_unlink_id(ID *id, struct bNodeTree *ntree);
-/* Utility macro for visiting every node tree in the library data, including local bNodeTree blocks in other IDs.
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Node Tree Iterator
+ *
+ * Utility macro for visiting every node tree in the library data, including local bNodeTree blocks in other IDs.
* This avoids the need for callback functions and allows executing code in a single inner code block.
*
* Variables:
@@ -615,6 +647,7 @@ void BKE_node_tree_unlink_id(ID *id, struct bNodeTree *ntree);
*
* Examples:
*
+ * \code{.c}
* FOREACH_NODETREE(bmain, nodetree) {
* if (id == nodetree)
* printf("This is a linkable node tree");
@@ -626,6 +659,9 @@ void BKE_node_tree_unlink_id(ID *id, struct bNodeTree *ntree);
* if (GS(id) == ID_MA)
* printf(" and it's owned by a material");
* } FOREACH_NODETREE_END
+ * \endcode
+ *
+ * \{
*/
/* should be an opaque type, only for internal use by BKE_node_tree_iter_*** */
@@ -657,9 +693,11 @@ bool BKE_node_tree_iter_step(struct NodeTreeIterStore *ntreeiter,
} \
} \
}
+/** \} */
-/* ************** SHADER NODES *************** */
-
+/* -------------------------------------------------------------------- */
+/** \name Shader Nodes
+ */
struct ShadeInput;
struct ShadeResult;
@@ -754,6 +792,7 @@ struct ShadeResult;
#define SH_NODE_COMBXYZ 189
#define SH_NODE_OUTPUT_LINESTYLE 190
#define SH_NODE_UVALONGSTROKE 191
+#define SH_NODE_TEX_POINTDENSITY 192
/* custom defines options for Material node */
#define SH_NODE_MAT_DIFF 1
@@ -782,8 +821,11 @@ void set_node_shader_lamp_loop(void (*lamp_loop_func)(struct ShadeInp
void ntreeGPUMaterialNodes(struct bNodeTree *ntree, struct GPUMaterial *mat, short compatibility);
+/** \} */
-/* ************** COMPOSITE NODES *************** */
+/* -------------------------------------------------------------------- */
+/** \name Composite Nodes
+ */
/* output socket defines */
#define RRES_OUT_IMAGE 0
@@ -817,6 +859,7 @@ void ntreeGPUMaterialNodes(struct bNodeTree *ntree, struct GPUMateria
#define RRES_OUT_SUBSURFACE_DIRECT 28
#define RRES_OUT_SUBSURFACE_INDIRECT 29
#define RRES_OUT_SUBSURFACE_COLOR 30
+#define RRES_OUT_DEBUG 31
/* note: types are needed to restore callbacks, don't change values */
#define CMP_NODE_VIEWER 201
@@ -909,6 +952,7 @@ void ntreeGPUMaterialNodes(struct bNodeTree *ntree, struct GPUMateria
#define CMP_NODE_MAP_RANGE 319
#define CMP_NODE_PLANETRACKDEFORM 320
#define CMP_NODE_CORNERPIN 321
+#define CMP_NODE_SWITCH_VIEW 322
/* channel toggles */
#define CMP_CHAN_RGB 1
@@ -942,9 +986,9 @@ void ntreeGPUMaterialNodes(struct bNodeTree *ntree, struct GPUMateria
#define CMP_TRACKPOS_ABSOLUTE_FRAME 3
/* API */
-struct CompBuf;
void ntreeCompositExecTree(struct Scene *scene, struct bNodeTree *ntree, struct RenderData *rd, int rendering, int do_previews,
- const struct ColorManagedViewSettings *view_settings, const struct ColorManagedDisplaySettings *display_settings);
+ const struct ColorManagedViewSettings *view_settings, const struct ColorManagedDisplaySettings *display_settings,
+ const char *view_name);
void ntreeCompositTagRender(struct Scene *sce);
int ntreeCompositTagAnimated(struct bNodeTree *ntree);
void ntreeCompositTagGenerators(struct bNodeTree *ntree);
@@ -963,7 +1007,11 @@ void ntreeCompositOutputFileUniqueLayer(struct ListBase *list, struct bNodeSocke
void ntreeCompositColorBalanceSyncFromLGG(bNodeTree *ntree, bNode *node);
void ntreeCompositColorBalanceSyncFromCDL(bNodeTree *ntree, bNode *node);
-/* ************** TEXTURE NODES *************** */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Texture Nodes
+ */
struct TexResult;
@@ -1004,11 +1052,9 @@ void ntreeTexEndExecTree(struct bNodeTreeExec *exec);
int ntreeTexExecTree(struct bNodeTree *ntree, struct TexResult *target,
float coord[3], float dxt[3], float dyt[3], int osatex, const short thread,
struct Tex *tex, short which_output, int cfra, int preview, struct ShadeInput *shi, struct MTex *mtex);
-
-
-/*************************************************/
+/** \} */
void init_nodesystem(void);
void free_nodesystem(void);
-#endif
+#endif /* __BKE_NODE_H__ */
diff --git a/source/blender/blenkernel/BKE_object.h b/source/blender/blenkernel/BKE_object.h
index 1bfd26d4f8c..6c5081d1ea9 100644
--- a/source/blender/blenkernel/BKE_object.h
+++ b/source/blender/blenkernel/BKE_object.h
@@ -33,32 +33,31 @@
extern "C" {
#endif
+#include "BLI_compiler_attrs.h"
+
struct Base;
struct EvaluationContext;
struct Scene;
struct Object;
-struct Camera;
struct BoundBox;
struct View3D;
struct SoftBody;
struct BulletSoftBody;
-struct Group;
-struct bAction;
-struct RenderData;
-struct rctf;
struct MovieClip;
struct Main;
struct RigidBodyWorld;
struct HookModifierData;
+struct ModifierData;
void BKE_object_workob_clear(struct Object *workob);
void BKE_object_workob_calc_parent(struct Scene *scene, struct Object *ob, struct Object *workob);
void BKE_object_transform_copy(struct Object *ob_tar, const struct Object *ob_src);
-struct SoftBody *copy_softbody(struct SoftBody *sb, bool copy_caches);
+struct SoftBody *copy_softbody(const struct SoftBody *sb, bool copy_caches);
struct BulletSoftBody *copy_bulletsoftbody(struct BulletSoftBody *sb);
-void BKE_object_copy_particlesystems(struct Object *obn, struct Object *ob);
-void BKE_object_copy_softbody(struct Object *obn, struct Object *ob);
+struct ParticleSystem *BKE_object_copy_particlesystem(struct ParticleSystem *psys);
+void BKE_object_copy_particlesystems(struct Object *ob_dst, const struct Object *ob_src);
+void BKE_object_copy_softbody(struct Object *ob_dst, const struct Object *ob_src);
void BKE_object_free_particlesystems(struct Object *ob);
void BKE_object_free_softbody(struct Object *ob);
void BKE_object_free_bulletsoftbody(struct Object *ob);
@@ -68,12 +67,13 @@ void BKE_object_update_base_layer(struct Scene *scene, struct Object *ob);
void BKE_object_free(struct Object *ob);
void BKE_object_free_ex(struct Object *ob, bool do_id_user);
void BKE_object_free_derived_caches(struct Object *ob);
+void BKE_object_free_caches(struct Object *object);
void BKE_object_modifier_hook_reset(struct Object *ob, struct HookModifierData *hmd);
bool BKE_object_support_modifier_type_check(struct Object *ob, int modifier_type);
-void BKE_object_link_modifiers(struct Object *ob, struct Object *from);
+void BKE_object_link_modifiers(struct Object *ob_dst, const struct Object *ob_src);
void BKE_object_free_modifiers(struct Object *ob);
void BKE_object_make_proxy(struct Object *ob, struct Object *target, struct Object *gob);
@@ -85,9 +85,18 @@ bool BKE_object_is_in_editmode(struct Object *ob);
bool BKE_object_is_in_editmode_vgroup(struct Object *ob);
bool BKE_object_is_in_wpaint_select_vert(struct Object *ob);
-struct Object *BKE_object_add_only_object(struct Main *bmain, int type, const char *name);
-struct Object *BKE_object_add(struct Main *bmain, struct Scene *scene, int type);
-void *BKE_object_obdata_add_from_type(struct Main *bmain, int type);
+struct Object *BKE_object_add_only_object(
+ struct Main *bmain,
+ int type, const char *name)
+ ATTR_NONNULL(1) ATTR_RETURNS_NONNULL;
+struct Object *BKE_object_add(
+ struct Main *bmain, struct Scene *scene,
+ int type, const char *name)
+ ATTR_NONNULL(1, 2) ATTR_RETURNS_NONNULL;
+void *BKE_object_obdata_add_from_type(
+ struct Main *bmain,
+ int type, const char *name)
+ ATTR_NONNULL(1);
void BKE_object_lod_add(struct Object *ob);
void BKE_object_lod_sort(struct Object *ob);
@@ -116,6 +125,7 @@ void BKE_object_matrix_local_get(struct Object *ob, float mat[4][4]);
bool BKE_object_pose_context_check(struct Object *ob);
struct Object *BKE_object_pose_armature_get(struct Object *ob);
+void BKE_object_get_parent_matrix(struct Scene *scene, struct Object *ob, struct Object *par, float parentmat[4][4]);
void BKE_object_where_is_calc(struct Scene *scene, struct Object *ob);
void BKE_object_where_is_calc_ex(struct Scene *scene, struct RigidBodyWorld *rbw, struct Object *ob, float r_originmat[3][3]);
void BKE_object_where_is_calc_time(struct Scene *scene, struct Object *ob, float ctime);
@@ -132,6 +142,9 @@ bool BKE_boundbox_ray_hit_check(
float *r_lambda);
void BKE_boundbox_calc_center_aabb(const struct BoundBox *bb, float r_cent[3]);
void BKE_boundbox_calc_size_aabb(const struct BoundBox *bb, float r_size[3]);
+void BKE_boundbox_minmax(const struct BoundBox *bb, float obmat[4][4], float r_min[3], float r_max[3]);
+struct BoundBox *BKE_boundbox_ensure_minimum_dimensions(
+ struct BoundBox *bb, struct BoundBox *bb_temp, const float epsilon);
struct BoundBox *BKE_object_boundbox_get(struct Object *ob);
void BKE_object_dimensions_get(struct Object *ob, float vec[3]);
@@ -170,6 +183,32 @@ void BKE_object_tfm_protected_restore(struct Object *ob,
const ObjectTfmProtectedChannels *obtfm,
const short protectflag);
+/* Dependency graph evaluation callbacks. */
+void BKE_object_eval_local_transform(struct EvaluationContext *eval_ctx,
+ struct Scene *scene,
+ struct Object *ob);
+void BKE_object_eval_parent(struct EvaluationContext *eval_ctx,
+ struct Scene *scene,
+ struct Object *ob);
+void BKE_object_eval_constraints(struct EvaluationContext *eval_ctx,
+ struct Scene *scene,
+ struct Object *ob);
+void BKE_object_eval_done(struct EvaluationContext *eval_ctx, struct Object *ob);
+
+void BKE_object_eval_modifier(struct EvaluationContext *eval_ctx,
+ struct Scene *scene,
+ struct Object *ob,
+ struct ModifierData *md);
+void BKE_object_eval_uber_transform(struct EvaluationContext *eval_ctx,
+ struct Scene *scene,
+ struct Object *ob);
+void BKE_object_eval_uber_data(struct EvaluationContext *eval_ctx,
+ struct Scene *scene,
+ struct Object *ob);
+
+void BKE_object_handle_data_update(struct EvaluationContext *eval_ctx,
+ struct Scene *scene,
+ struct Object *ob);
void BKE_object_handle_update(struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob);
void BKE_object_handle_update_ex(struct EvaluationContext *eval_ctx,
struct Scene *scene, struct Object *ob,
@@ -181,7 +220,11 @@ int BKE_object_obdata_texspace_get(struct Object *ob, short **r_texflag, float *
int BKE_object_insert_ptcache(struct Object *ob);
void BKE_object_delete_ptcache(struct Object *ob, int index);
-struct KeyBlock *BKE_object_insert_shape_key(struct Scene *scene, struct Object *ob, const char *name, const bool from_mix);
+struct KeyBlock *BKE_object_shapekey_insert(struct Object *ob, const char *name, const bool from_mix);
+bool BKE_object_shapekey_remove(struct Main *bmain, struct Object *ob, struct KeyBlock *kb);
+bool BKE_object_shapekey_free(struct Main *bmain, struct Object *ob);
+
+bool BKE_object_flag_test_recursive(const struct Object *ob, short flag);
bool BKE_object_is_child_recursive(struct Object *ob_parent, struct Object *ob_child);
bool BKE_object_is_animated(struct Scene *scene, struct Object *ob);
@@ -218,6 +261,8 @@ void BKE_object_groups_clear(struct Scene *scene, struct Base *base,
struct KDTree *BKE_object_as_kdtree(struct Object *ob, int *r_tot);
+bool BKE_object_modifier_use_time(struct Object *ob, struct ModifierData *md);
+
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/blenkernel/BKE_object_deform.h b/source/blender/blenkernel/BKE_object_deform.h
index 6de7ff9bc1c..e956815d6f7 100644
--- a/source/blender/blenkernel/BKE_object_deform.h
+++ b/source/blender/blenkernel/BKE_object_deform.h
@@ -29,10 +29,54 @@
* used by painting and tools.
*/
+#ifdef __cplusplus
+extern "C" {
+#endif
+
struct Object;
+struct ID;
+struct MDeformVert;
+struct bDeformGroup;
+
+/* General vgroup operations */
+void BKE_object_defgroup_remap_update_users(struct Object *ob, int *map);
+
+bool BKE_object_defgroup_array_get(struct ID *id, struct MDeformVert **dvert_arr, int *dvert_tot);
+
+struct bDeformGroup *BKE_object_defgroup_add(struct Object *ob);
+struct bDeformGroup *BKE_object_defgroup_add_name(struct Object *ob, const char *name);
+struct MDeformVert *BKE_object_defgroup_data_create(struct ID *id);
+
+bool BKE_object_defgroup_clear(struct Object *ob, struct bDeformGroup *dg, const bool use_selection);
+bool BKE_object_defgroup_clear_all(struct Object *ob, const bool use_selection);
+
+void BKE_object_defgroup_remove(struct Object *ob, struct bDeformGroup *defgroup);
+void BKE_object_defgroup_remove_all(struct Object *ob);
+
+
+/* Select helpers */
+enum eVGroupSelect;
+bool *BKE_object_defgroup_subset_from_select_type(
+ struct Object *ob, enum eVGroupSelect subset_type, int *r_defgroup_tot, int *r_subset_count);
+void BKE_object_defgroup_subset_to_index_array(
+ const bool *defgroup_validmap, const int defgroup_tot, int *r_defgroup_subset_map);
+
+
+/* ********** */
+
+bool *BKE_object_defgroup_lock_flags_get(struct Object *ob, const int defbase_tot);
+bool *BKE_object_defgroup_validmap_get(struct Object *ob, const int defbase_tot);
+bool *BKE_object_defgroup_selected_get(struct Object *ob, int defbase_tot, int *r_dg_flags_sel_tot);
+
+#ifdef __cplusplus
+}
+#endif
+
+/* Select helpers */
+bool *BKE_objdef_vgroup_subset_from_select_type(
+ struct Object *ob, enum eVGroupSelect subset_type, int *r_vgroup_tot, int *r_subset_count);
+void BKE_objdef_vgroup_subset_to_index_array(
+ const bool *vgroup_validmap, const int vgroup_tot, int *r_vgroup_subset_map);
-bool *BKE_objdef_lock_flags_get(struct Object *ob, const int defbase_tot);
-bool *BKE_objdef_validmap_get(struct Object *ob, const int defbase_tot);
-bool *BKE_objdef_selected_get(struct Object *ob, int defbase_tot, int *r_dg_flags_sel_tot);
#endif /* __BKE_OBJECT_DEFORM_H__ */
diff --git a/source/blender/blenkernel/BKE_ocean.h b/source/blender/blenkernel/BKE_ocean.h
index b750d8b283a..9b1b937febf 100644
--- a/source/blender/blenkernel/BKE_ocean.h
+++ b/source/blender/blenkernel/BKE_ocean.h
@@ -74,13 +74,14 @@ typedef struct OceanCache {
#define OCEAN_CACHING 1
#define OCEAN_CACHED 2
-struct Ocean *BKE_add_ocean(void);
-void BKE_free_ocean_data(struct Ocean *oc);
-void BKE_free_ocean(struct Ocean *oc);
+struct Ocean *BKE_ocean_add(void);
+void BKE_ocean_free_data(struct Ocean *oc);
+void BKE_ocean_free(struct Ocean *oc);
-void BKE_init_ocean(struct Ocean *o, int M, int N, float Lx, float Lz, float V, float l, float A, float w, float damp,
- float alignment, float depth, float time, short do_height_field, short do_chop, short do_normals, short do_jacobian, int seed);
-void BKE_simulate_ocean(struct Ocean *o, float t, float scale, float chop_amount);
+void BKE_ocean_init(
+ struct Ocean *o, int M, int N, float Lx, float Lz, float V, float l, float A, float w, float damp,
+ float alignment, float depth, float time, short do_height_field, short do_chop, short do_normals, short do_jacobian, int seed);
+void BKE_ocean_simulate(struct Ocean *o, float t, float scale, float chop_amount);
/* sampling the ocean surface */
float BKE_ocean_jminus_to_foam(float jminus, float coverage);
@@ -92,16 +93,17 @@ void BKE_ocean_eval_ij(struct Ocean *oc, struct OceanResult *ocr, int i, int j)
/* ocean cache handling */
-struct OceanCache *BKE_init_ocean_cache(const char *bakepath, const char *relbase,
- int start, int end, float wave_scale,
- float chop_amount, float foam_coverage, float foam_fade, int resolution);
-void BKE_simulate_ocean_cache(struct OceanCache *och, int frame);
+struct OceanCache *BKE_ocean_init_cache(
+ const char *bakepath, const char *relbase,
+ int start, int end, float wave_scale,
+ float chop_amount, float foam_coverage, float foam_fade, int resolution);
+void BKE_ocean_simulate_cache(struct OceanCache *och, int frame);
-void BKE_bake_ocean(struct Ocean *o, struct OceanCache *och, void (*update_cb)(void *, float progress, int *cancel), void *update_cb_data);
+void BKE_ocean_bake(struct Ocean *o, struct OceanCache *och, void (*update_cb)(void *, float progress, int *cancel), void *update_cb_data);
void BKE_ocean_cache_eval_uv(struct OceanCache *och, struct OceanResult *ocr, int f, float u, float v);
void BKE_ocean_cache_eval_ij(struct OceanCache *och, struct OceanResult *ocr, int f, int i, int j);
-void BKE_free_ocean_cache(struct OceanCache *och);
+void BKE_ocean_free_cache(struct OceanCache *och);
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/blenkernel/BKE_treehash.h b/source/blender/blenkernel/BKE_outliner_treehash.h
index 54deef1ce2f..454edb40c4e 100644
--- a/source/blender/blenkernel/BKE_treehash.h
+++ b/source/blender/blenkernel/BKE_outliner_treehash.h
@@ -19,34 +19,33 @@
*
* ***** END GPL LICENSE BLOCK *****
*/
-#ifndef __BKE_TREEHASH_H__
-#define __BKE_TREEHASH_H__
+#ifndef __BKE_OUTLINER_TREEHASH_H__
+#define __BKE_OUTLINER_TREEHASH_H__
-/** \file BKE_treehash.h
+/** \file BKE_outliner_treehash.h
* \ingroup bke
*/
struct ID;
-struct GHash;
struct BLI_mempool;
struct TreeStoreElem;
/* create and fill hashtable with treestore elements */
-void *BKE_treehash_create_from_treestore(struct BLI_mempool *treestore);
+void *BKE_outliner_treehash_create_from_treestore(struct BLI_mempool *treestore);
/* full rebuild for already allocated hashtable */
-void *BKE_treehash_rebuild_from_treestore(void *treehash, struct BLI_mempool *treestore);
+void *BKE_outliner_treehash_rebuild_from_treestore(void *treehash, struct BLI_mempool *treestore);
/* full rebuild for already allocated hashtable */
-void BKE_treehash_add_element(void *treehash, struct TreeStoreElem *elem);
+void BKE_outliner_treehash_add_element(void *treehash, struct TreeStoreElem *elem);
/* find first unused element with specific type, nr and id */
-struct TreeStoreElem *BKE_treehash_lookup_unused(void *treehash, short type, short nr, struct ID *id);
+struct TreeStoreElem *BKE_outliner_treehash_lookup_unused(void *treehash, short type, short nr, struct ID *id);
/* find user or unused element with specific type, nr and id */
-struct TreeStoreElem *BKE_treehash_lookup_any(void *treehash, short type, short nr, struct ID *id);
+struct TreeStoreElem *BKE_outliner_treehash_lookup_any(void *treehash, short type, short nr, struct ID *id);
/* free treehash structure */
-void BKE_treehash_free(void *treehash);
+void BKE_outliner_treehash_free(void *treehash);
#endif
diff --git a/source/blender/blenkernel/BKE_packedFile.h b/source/blender/blenkernel/BKE_packedFile.h
index 8fab44121de..a2397922061 100644
--- a/source/blender/blenkernel/BKE_packedFile.h
+++ b/source/blender/blenkernel/BKE_packedFile.h
@@ -48,7 +48,7 @@ struct PackedFile *dupPackedFile(const struct PackedFile *pf_src);
struct PackedFile *newPackedFile(struct ReportList *reports, const char *filename, const char *relabase);
struct PackedFile *newPackedFileMemory(void *mem, int memlen);
-void packAll(struct Main *bmain, struct ReportList *reports);
+void packAll(struct Main *bmain, struct ReportList *reports, bool verbose);
void packLibraries(struct Main *bmain, struct ReportList *reports);
/* unpack */
diff --git a/source/blender/blenkernel/BKE_paint.h b/source/blender/blenkernel/BKE_paint.h
index 4eafdae9ebd..bf1cfb263eb 100644
--- a/source/blender/blenkernel/BKE_paint.h
+++ b/source/blender/blenkernel/BKE_paint.h
@@ -37,12 +37,12 @@ struct BMesh;
struct BMFace;
struct Brush;
struct CurveMapping;
-struct MDisps;
struct MeshElemMap;
struct GridPaintMask;
struct Main;
+struct MLoop;
+struct MLoopTri;
struct MFace;
-struct MultireModifierData;
struct MVert;
struct Object;
struct Paint;
@@ -50,13 +50,13 @@ struct PaintCurve;
struct Palette;
struct PaletteColor;
struct PBVH;
+struct ReportList;
struct Scene;
struct Sculpt;
struct StrokeCache;
struct Tex;
struct ImagePool;
struct UnifiedPaintSettings;
-struct wmOperator;
enum OverlayFlags;
@@ -66,13 +66,13 @@ extern const char PAINT_CURSOR_WEIGHT_PAINT[3];
extern const char PAINT_CURSOR_TEXTURE_PAINT[3];
typedef enum PaintMode {
- PAINT_SCULPT = 0,
- PAINT_VERTEX = 1,
- PAINT_WEIGHT = 2,
- PAINT_TEXTURE_PROJECTIVE = 3,
- PAINT_TEXTURE_2D = 4,
- PAINT_SCULPT_UV = 5,
- PAINT_INVALID = 6
+ ePaintSculpt = 0,
+ ePaintVertex = 1,
+ ePaintWeight = 2,
+ ePaintTextureProjective = 3,
+ ePaintTexture2D = 4,
+ ePaintSculptUV = 5,
+ ePaintInvalid = 6
} PaintMode;
/* overlay invalidation */
@@ -102,16 +102,20 @@ struct Palette *BKE_palette_add(struct Main *bmain, const char *name);
struct PaletteColor *BKE_palette_color_add(struct Palette *palette);
bool BKE_palette_is_empty(const struct Palette *palette);
void BKE_palette_color_remove(struct Palette *palette, struct PaletteColor *color);
-void BKE_palette_cleanup(struct Palette *palette);
+void BKE_palette_clear(struct Palette *palette);
/* paint curves */
struct PaintCurve *BKE_paint_curve_add(struct Main *bmain, const char *name);
void BKE_paint_curve_free(struct PaintCurve *pc);
-void BKE_paint_init(struct Paint *p, const char col[3]);
+void BKE_paint_init(struct Scene *sce, PaintMode mode, const char col[3]);
void BKE_paint_free(struct Paint *p);
void BKE_paint_copy(struct Paint *src, struct Paint *tar);
+void BKE_paint_cavity_curve_preset(struct Paint *p, int preset);
+
+short BKE_paint_object_mode_from_paint_mode(PaintMode mode);
+struct Paint *BKE_paint_get_active_from_paintmode(struct Scene *sce, PaintMode mode);
struct Paint *BKE_paint_get_active(struct Scene *sce);
struct Paint *BKE_paint_get_active_from_context(const struct bContext *C);
PaintMode BKE_paintmode_get_active_from_context(const struct bContext *C);
@@ -120,6 +124,10 @@ void BKE_paint_brush_set(struct Paint *paint, struct Brush *br);
struct Palette *BKE_paint_palette(struct Paint *paint);
void BKE_paint_palette_set(struct Paint *p, struct Palette *palette);
void BKE_paint_curve_set(struct Brush *br, struct PaintCurve *pc);
+void BKE_paint_curve_clamp_endpoint_add_index(struct PaintCurve *pc, const int add_index);
+
+void BKE_paint_data_warning(struct ReportList *reports, bool uvs, bool mat, bool tex, bool stencil);
+bool BKE_paint_proj_mesh_data_check(struct Scene *scene, struct Object *ob, bool *uvs, bool *mat, bool *tex, bool *stencil);
/* testing face select mode
* Texture paint could be removed since selected faces are not used
@@ -129,7 +137,7 @@ bool BKE_paint_select_vert_test(struct Object *ob);
bool BKE_paint_select_elem_test(struct Object *ob);
/* partial visibility */
-bool paint_is_face_hidden(const struct MFace *f, const struct MVert *mvert);
+bool paint_is_face_hidden(const struct MLoopTri *lt, const struct MVert *mvert, const struct MLoop *mloop);
bool paint_is_grid_face_hidden(const unsigned int *grid_hidden,
int gridsize, int x, int y);
bool paint_is_bmesh_face_hidden(struct BMFace *f);
@@ -139,7 +147,10 @@ float paint_grid_paint_mask(const struct GridPaintMask *gpm, unsigned level,
unsigned x, unsigned y);
/* stroke related */
-void paint_calculate_rake_rotation(struct UnifiedPaintSettings *ups, const float mouse_pos[2]);
+void paint_calculate_rake_rotation(struct UnifiedPaintSettings *ups, struct Brush *brush, const float mouse_pos[2]);
+void paint_update_brush_rake_rotation(struct UnifiedPaintSettings *ups, struct Brush *brush, float rotation);
+
+void BKE_paint_stroke_get_average(struct Scene *scene, struct Object *ob, float stroke[3]);
/* Session data (mode-specific) */
@@ -150,7 +161,6 @@ typedef struct SculptSession {
struct MPoly *mpoly;
struct MLoop *mloop;
int totvert, totpoly;
- float (*face_normals)[3];
struct KeyBlock *kb;
float *vmask;
@@ -187,17 +197,10 @@ typedef struct SculptSession {
struct SculptStroke *stroke;
struct StrokeCache *cache;
-
- /* last paint/sculpt stroke location */
- bool last_stroke_valid;
- float last_stroke[3];
-
- float average_stroke_accum[3];
- int average_stroke_counter;
} SculptSession;
-void BKE_free_sculptsession(struct Object *ob);
-void BKE_free_sculptsession_deformMats(struct SculptSession *ss);
+void BKE_sculptsession_free(struct Object *ob);
+void BKE_sculptsession_free_deformMats(struct SculptSession *ss);
void BKE_sculptsession_bm_to_me(struct Object *ob, bool reorder);
void BKE_sculptsession_bm_to_me_for_render(struct Object *object);
void BKE_sculpt_update_mesh_elements(struct Scene *scene, struct Sculpt *sd, struct Object *ob,
diff --git a/source/blender/blenkernel/BKE_particle.h b/source/blender/blenkernel/BKE_particle.h
index f84a6378fb3..89cfb3a2aac 100644
--- a/source/blender/blenkernel/BKE_particle.h
+++ b/source/blender/blenkernel/BKE_particle.h
@@ -39,14 +39,14 @@
#include "DNA_particle_types.h"
#include "DNA_object_types.h"
+#include "BKE_customdata.h"
+
struct ParticleSystemModifierData;
struct ParticleSystem;
struct ParticleKey;
struct ParticleSettings;
-struct HairKey;
struct Main;
-struct Group;
struct Object;
struct Scene;
struct DerivedMesh;
@@ -55,12 +55,10 @@ struct MTFace;
struct MCol;
struct MFace;
struct MVert;
-struct IpoCurve;
struct LatticeDeformData;
struct LinkNode;
struct KDTree;
struct RNG;
-struct SurfaceModifierData;
struct BVHTreeRay;
struct BVHTreeRayHit;
struct EdgeHash;
@@ -110,7 +108,7 @@ typedef struct ParticleTexture {
float ivel; /* used in reset */
float time, life, exist, size; /* used in init */
float damp, gravity, field; /* used in physics */
- float length, clump, kink, effector; /* used in path caching */
+ float length, clump, kink_freq, kink_amp, effector; /* used in path caching */
float rough1, rough2, roughe; /* used in path caching */
} ParticleTexture;
@@ -126,7 +124,7 @@ typedef struct ParticleCacheKey {
float rot[4];
float col[3];
float time;
- int steps;
+ int segments;
} ParticleCacheKey;
typedef struct ParticleThreadContext {
@@ -145,12 +143,12 @@ typedef struct ParticleThreadContext {
float maxweight;
int *index, *skip, jitlevel;
- int from, cfrom, distr;
+ int cfrom, distr;
struct ParticleData *tpars;
/* path caching */
- int editupdate, between, steps;
+ int editupdate, between, segments, extra_segments;
int totchild, totparent, parent_pass;
float cfra;
@@ -160,11 +158,11 @@ typedef struct ParticleThreadContext {
float *vg_effector;
} ParticleThreadContext;
-typedef struct ParticleThread {
+typedef struct ParticleTask {
ParticleThreadContext *ctx;
struct RNG *rng, *rng_path;
- int num, tot;
-} ParticleThread;
+ int begin, end;
+} ParticleTask;
typedef struct ParticleBillboardData {
struct Object *ob;
@@ -181,7 +179,7 @@ typedef struct ParticleBillboardData {
typedef struct ParticleCollisionElement {
/* pointers to original data */
- float *x[4], *v[4];
+ float *x[3], *v[3];
/* values interpolated from original data*/
float x0[3], x1[3], x2[3], p[3];
@@ -279,6 +277,9 @@ BLI_INLINE void psys_frand_vec(ParticleSystem *psys, unsigned int seed, float ve
int count_particles(struct ParticleSystem *psys);
int count_particles_mod(struct ParticleSystem *psys, int totgr, int cur);
+int psys_get_child_number(struct Scene *scene, struct ParticleSystem *psys);
+int psys_get_tot_child(struct Scene *scene, struct ParticleSystem *psys);
+
struct ParticleSystem *psys_get_current(struct Object *ob);
/* for rna */
short psys_get_current_num(struct Object *ob);
@@ -288,9 +289,9 @@ void psys_set_current_num(Object *ob, int index);
struct LatticeDeformData *psys_create_lattice_deform_data(struct ParticleSimulationData *sim);
-int psys_in_edit_mode(struct Scene *scene, struct ParticleSystem *psys);
-int psys_check_enabled(struct Object *ob, struct ParticleSystem *psys);
-int psys_check_edited(struct ParticleSystem *psys);
+bool psys_in_edit_mode(struct Scene *scene, struct ParticleSystem *psys);
+bool psys_check_enabled(struct Object *ob, struct ParticleSystem *psys);
+bool psys_check_edited(struct ParticleSystem *psys);
void psys_check_group_weights(struct ParticleSettings *part);
int psys_uses_gravity(struct ParticleSimulationData *sim);
@@ -302,7 +303,6 @@ void psys_free(struct Object *ob, struct ParticleSystem *psys);
void psys_render_set(struct Object *ob, struct ParticleSystem *psys, float viewmat[4][4], float winmat[4][4], int winx, int winy, int timeoffset);
void psys_render_restore(struct Object *ob, struct ParticleSystem *psys);
-int psys_render_simplify_distribution(struct ParticleThreadContext *ctx, int tot);
bool psys_render_simplify_params(struct ParticleSystem *psys, struct ChildParticle *cpa, float *params);
void psys_interpolate_uvs(const struct MTFace *tface, int quad, const float w[4], float uvco[2]);
@@ -310,6 +310,7 @@ void psys_interpolate_mcol(const struct MCol *mcol, int quad, const float w[4],
void copy_particle_key(struct ParticleKey *to, struct ParticleKey *from, int time);
+CustomDataMask psys_emitter_customdata_mask(struct ParticleSystem *psys);
void psys_particle_on_emitter(struct ParticleSystemModifierData *psmd, int distr, int index, int index_dmcache,
float fuv[4], float foffset, float vec[3], float nor[3],
float utan[3], float vtan[3], float orco[3], float ornor[3]);
@@ -328,7 +329,7 @@ void psys_find_parents(struct ParticleSimulationData *sim);
void psys_cache_paths(struct ParticleSimulationData *sim, float cfra);
void psys_cache_edit_paths(struct Scene *scene, struct Object *ob, struct PTCacheEdit *edit, float cfra);
void psys_cache_child_paths(struct ParticleSimulationData *sim, float cfra, int editupdate);
-int do_guides(struct ListBase *effectors, ParticleKey *state, int pa_num, float time);
+int do_guides(struct ParticleSettings *part, struct ListBase *effectors, ParticleKey *state, int pa_num, float time);
void precalc_guides(struct ParticleSimulationData *sim, struct ListBase *effectors);
float psys_get_timestep(struct ParticleSimulationData *sim);
float psys_get_child_time(struct ParticleSystem *psys, struct ChildParticle *cpa, float cfra, float *birthtime, float *dietime);
@@ -336,6 +337,13 @@ float psys_get_child_size(struct ParticleSystem *psys, struct ChildParticle *cpa
void psys_get_particle_on_path(struct ParticleSimulationData *sim, int pa_num, struct ParticleKey *state, const bool vel);
int psys_get_particle_state(struct ParticleSimulationData *sim, int p, struct ParticleKey *state, int always);
+/* child paths */
+void BKE_particlesettings_clump_curve_init(struct ParticleSettings *part);
+void BKE_particlesettings_rough_curve_init(struct ParticleSettings *part);
+void psys_apply_child_modifiers(struct ParticleThreadContext *ctx, struct ListBase *modifiers,
+ struct ChildParticle *cpa, struct ParticleTexture *ptex, const float orco[3], const float ornor[3], float hairmat[4][4],
+ struct ParticleCacheKey *keys, struct ParticleCacheKey *parent_keys, const float parent_orco[3]);
+
void psys_sph_init(struct ParticleSimulationData *sim, struct SPHData *sphdata);
void psys_sph_finalise(struct SPHData *sphdata);
void psys_sph_density(struct BVHTree *tree, struct SPHData *data, float co[3], float vars[2]);
@@ -347,8 +355,10 @@ void psys_get_dupli_texture(struct ParticleSystem *psys, struct ParticleSettings
void psys_get_dupli_path_transform(struct ParticleSimulationData *sim, struct ParticleData *pa, struct ChildParticle *cpa,
struct ParticleCacheKey *cache, float mat[4][4], float *scale);
-ParticleThread *psys_threads_create(struct ParticleSimulationData *sim);
-void psys_threads_free(ParticleThread *threads);
+void psys_thread_context_init(struct ParticleThreadContext *ctx, struct ParticleSimulationData *sim);
+void psys_thread_context_free(struct ParticleThreadContext *ctx);
+void psys_tasks_create(struct ParticleThreadContext *ctx, int startpart, int endpart, struct ParticleTask **r_tasks, int *r_numtasks);
+void psys_tasks_free(struct ParticleTask *tasks, int numtasks);
void psys_make_billboard(ParticleBillboardData *bb, float xvec[3], float yvec[3], float zvec[3], float center[3]);
void psys_apply_hair_lattice(struct Scene *scene, struct Object *ob, struct ParticleSystem *psys);
@@ -364,7 +374,7 @@ void psys_get_pointcache_start_end(struct Scene *scene, ParticleSystem *psys, in
void psys_check_boid_data(struct ParticleSystem *psys);
-void psys_get_birth_coordinates(struct ParticleSimulationData *sim, struct ParticleData *pa, struct ParticleKey *state, float dtime, float cfra);
+void psys_get_birth_coords(struct ParticleSimulationData *sim, struct ParticleData *pa, struct ParticleKey *state, float dtime, float cfra);
void particle_system_update(struct Scene *scene, struct Object *ob, struct ParticleSystem *psys);
@@ -378,7 +388,7 @@ void free_keyed_keys(struct ParticleSystem *psys);
void psys_free_particles(struct ParticleSystem *psys);
void psys_free_children(struct ParticleSystem *psys);
-void psys_interpolate_particle(short type, struct ParticleKey keys[4], float dt, struct ParticleKey *result, int velocity);
+void psys_interpolate_particle(short type, struct ParticleKey keys[4], float dt, struct ParticleKey *result, bool velocity);
void psys_vec_rot_to_face(struct DerivedMesh *dm, struct ParticleData *pa, float vec[3]);
void psys_mat_hair_to_object(struct Object *ob, struct DerivedMesh *dm, short from, struct ParticleData *pa, float hairmat[4][4]);
void psys_mat_hair_to_global(struct Object *ob, struct DerivedMesh *dm, short from, struct ParticleData *pa, float hairmat[4][4]);
@@ -403,6 +413,7 @@ void psys_particle_on_dm(struct DerivedMesh *dm, int from, int index, int index_
float orco[3], float ornor[3]);
/* particle_system.c */
+void distribute_particles(struct ParticleSimulationData *sim, int from);
void initialize_particle(struct ParticleSimulationData *sim, struct ParticleData *pa);
void psys_calc_dmcache(struct Object *ob, struct DerivedMesh *dm, struct ParticleSystem *psys);
int psys_particle_dm_face_lookup(struct Object *ob, struct DerivedMesh *dm, int index, const float fw[4], struct LinkNode *node);
@@ -411,6 +422,33 @@ void reset_particle(struct ParticleSimulationData *sim, struct ParticleData *pa,
float psys_get_current_display_percentage(struct ParticleSystem *psys);
+typedef struct ParticleRenderElem {
+ int curchild, totchild, reduce;
+ float lambda, t, scalemin, scalemax;
+} ParticleRenderElem;
+
+typedef struct ParticleRenderData {
+ ChildParticle *child;
+ ParticleCacheKey **pathcache;
+ ParticleCacheKey **childcache;
+ ListBase pathcachebufs, childcachebufs;
+ int totchild, totcached, totchildcache;
+ struct DerivedMesh *dm;
+ int totdmvert, totdmedge, totdmface;
+
+ float mat[4][4];
+ float viewmat[4][4], winmat[4][4];
+ int winx, winy;
+
+ int do_simplify;
+ int timeoffset;
+ ParticleRenderElem *elems;
+
+ /* ORIGINDEX */
+ const int *index_mf_to_mpoly;
+ const int *index_mp_to_orig;
+} ParticleRenderData;
+
/* psys_reset */
#define PSYS_RESET_ALL 1
#define PSYS_RESET_DEPSGRAPH 2
@@ -421,4 +459,13 @@ float psys_get_current_display_percentage(struct ParticleSystem *psys);
#define DMCACHE_NOTFOUND -1
#define DMCACHE_ISCHILD -2
+/* **** Depsgraph evaluation **** */
+
+struct EvaluationContext;
+
+void BKE_particle_system_eval(struct EvaluationContext *eval_ctx,
+ struct Scene *scene,
+ struct Object *ob,
+ struct ParticleSystem *psys);
+
#endif
diff --git a/source/blender/blenkernel/BKE_pbvh.h b/source/blender/blenkernel/BKE_pbvh.h
index 53e41c1dec8..5dc5ebbbd4c 100644
--- a/source/blender/blenkernel/BKE_pbvh.h
+++ b/source/blender/blenkernel/BKE_pbvh.h
@@ -34,9 +34,9 @@ struct CCGElem;
struct CCGKey;
struct CustomData;
struct DMFlagMat;
-struct DMGridAdjacency;
-struct GHash;
-struct MFace;
+struct MPoly;
+struct MLoop;
+struct MLoopTri;
struct MVert;
struct PBVH;
struct PBVHNode;
@@ -61,10 +61,13 @@ typedef void (*BKE_pbvh_HitOccludedCallback)(PBVHNode *node, void *data, float *
/* Building */
PBVH *BKE_pbvh_new(void);
-void BKE_pbvh_build_mesh(PBVH *bvh, struct MFace *faces, struct MVert *verts,
- int totface, int totvert, struct CustomData *vdata);
+void BKE_pbvh_build_mesh(
+ PBVH *bvh,
+ const struct MPoly *mpoly, const struct MLoop *mloop,
+ struct MVert *verts, int totvert, struct CustomData *vdata,
+ const struct MLoopTri *looptri, int looptri_num);
void BKE_pbvh_build_grids(PBVH *bvh, struct CCGElem **grid_elems,
- struct DMGridAdjacency *gridadj, int totgrid,
+ int totgrid,
struct CCGKey *key, void **gridfaces, struct DMFlagMat *flagmats,
unsigned int **grid_hidden);
void BKE_pbvh_build_bmesh(PBVH *bvh, struct BMesh *bm, bool smooth_shading, struct BMLog *log, const int cd_vert_node_offset, const int cd_face_node_offset);
@@ -89,29 +92,32 @@ void BKE_pbvh_search_gather(PBVH *bvh,
* it's up to the callback to find the primitive within the leaves that is
* hit first */
-void BKE_pbvh_raycast(PBVH *bvh, BKE_pbvh_HitOccludedCallback cb, void *data,
- const float ray_start[3], const float ray_normal[3],
- int original);
+void BKE_pbvh_raycast(
+ PBVH *bvh, BKE_pbvh_HitOccludedCallback cb, void *data,
+ const float ray_start[3], const float ray_normal[3],
+ bool original);
-bool BKE_pbvh_node_raycast(PBVH *bvh, PBVHNode *node, float (*origco)[3], int use_origco,
- const float ray_start[3], const float ray_normal[3],
- float *dist);
+bool BKE_pbvh_node_raycast(
+ PBVH *bvh, PBVHNode *node, float (*origco)[3], int use_origco,
+ const float ray_start[3], const float ray_normal[3],
+ float *dist);
bool BKE_pbvh_bmesh_node_raycast_detail(
PBVHNode *node,
const float ray_start[3], const float ray_normal[3],
- float *detail, float *dist);
+ float *dist, float *r_detail);
/* for orthographic cameras, project the far away ray segment points to the root node so
* we can have better precision. */
-void BKE_pbvh_raycast_project_ray_root(PBVH *bvh, bool original, float ray_start[3],
- float ray_end[3], float ray_normal[3]);
+void BKE_pbvh_raycast_project_ray_root(
+ PBVH *bvh, bool original,
+ float ray_start[3], float ray_end[3], float ray_normal[3]);
/* Drawing */
void BKE_pbvh_node_draw(PBVHNode *node, void *data);
void BKE_pbvh_draw(PBVH *bvh, float (*planes)[4], float (*face_nors)[3],
- int (*setMaterial)(int matnr, void *attribs), bool wireframe);
+ int (*setMaterial)(int matnr, void *attribs), bool wireframe, bool fast);
/* PBVH Access */
typedef enum {
@@ -121,6 +127,7 @@ typedef enum {
} PBVHType;
PBVHType BKE_pbvh_type(const PBVH *bvh);
+bool BKE_pbvh_has_faces(const PBVH *bvh);
/* Get the PBVH root's bounding box */
void BKE_pbvh_bounding_box(const PBVH *bvh, float min[3], float max[3]);
@@ -143,8 +150,10 @@ typedef enum {
PBVH_Subdivide = 1,
PBVH_Collapse = 2,
} PBVHTopologyUpdateMode;
-bool BKE_pbvh_bmesh_update_topology(PBVH *bvh, PBVHTopologyUpdateMode mode,
- const float center[3], float radius);
+bool BKE_pbvh_bmesh_update_topology(
+ PBVH *bvh, PBVHTopologyUpdateMode mode,
+ const float center[3], const float view_normal[3],
+ float radius);
/* Node Access */
@@ -170,13 +179,16 @@ void BKE_pbvh_node_mark_normals_update(PBVHNode *node);
void BKE_pbvh_node_mark_topology_update(PBVHNode *node);
void BKE_pbvh_node_fully_hidden_set(PBVHNode *node, int fully_hidden);
-void BKE_pbvh_node_get_grids(PBVH *bvh, PBVHNode *node,
- int **grid_indices, int *totgrid, int *maxgrid, int *gridsize,
- struct CCGElem ***grid_elems, struct DMGridAdjacency **gridadj);
-void BKE_pbvh_node_num_verts(PBVH *bvh, PBVHNode *node,
- int *uniquevert, int *totvert);
-void BKE_pbvh_node_get_verts(PBVH *bvh, PBVHNode *node,
- int **vert_indices, struct MVert **verts);
+void BKE_pbvh_node_get_grids(
+ PBVH *bvh, PBVHNode *node,
+ int **grid_indices, int *totgrid, int *maxgrid, int *gridsize,
+ struct CCGElem ***grid_elems);
+void BKE_pbvh_node_num_verts(
+ PBVH *bvh, PBVHNode *node,
+ int *r_uniquevert, int *r_totvert);
+void BKE_pbvh_node_get_verts(
+ PBVH *bvh, PBVHNode *node,
+ const int **r_vert_indices, struct MVert **r_verts);
void BKE_pbvh_node_get_BB(PBVHNode *node, float bb_min[3], float bb_max[3]);
void BKE_pbvh_node_get_original_BB(PBVHNode *node, float bb_min[3], float bb_max[3]);
@@ -200,7 +212,7 @@ void BKE_pbvh_update(PBVH *bvh, int flags, float (*face_nors)[3]);
void BKE_pbvh_redraw_BB(PBVH *bvh, float bb_min[3], float bb_max[3]);
void BKE_pbvh_get_grid_updates(PBVH *bvh, int clear, void ***r_gridfaces, int *r_totface);
void BKE_pbvh_grids_update(PBVH *bvh, struct CCGElem **grid_elems,
- struct DMGridAdjacency *gridadj, void **gridfaces,
+ void **gridfaces,
struct DMFlagMat *flagmats, unsigned int **grid_hidden);
/* Layer displacement */
@@ -248,7 +260,7 @@ typedef struct PBVHVertexIter {
/* mesh */
struct MVert *mverts;
int totvert;
- int *vert_indices;
+ const int *vert_indices;
float *vmask;
/* bmesh */
@@ -333,6 +345,9 @@ void BKE_pbvh_node_get_proxies(PBVHNode *node, PBVHProxyNode **proxies, int *pro
void BKE_pbvh_node_free_proxies(PBVHNode *node);
PBVHProxyNode *BKE_pbvh_node_add_proxy(PBVH *bvh, PBVHNode *node);
void BKE_pbvh_gather_proxies(PBVH *pbvh, PBVHNode ***nodes, int *totnode);
+void BKE_pbvh_node_get_bm_orco_data(
+ PBVHNode *node,
+ int (**r_orco_tris)[3], int *r_orco_tris_num, float (**r_orco_coords)[3]);
//void BKE_pbvh_node_BB_reset(PBVHNode *node);
//void BKE_pbvh_node_BB_expand(PBVHNode *node, float co[3]);
diff --git a/source/blender/blenkernel/BKE_pointcache.h b/source/blender/blenkernel/BKE_pointcache.h
index 99579086e25..a3ffad1f66b 100644
--- a/source/blender/blenkernel/BKE_pointcache.h
+++ b/source/blender/blenkernel/BKE_pointcache.h
@@ -241,7 +241,6 @@ typedef struct PTCacheEdit {
/* particles stuff */
struct ParticleSystem *psys;
- struct ParticleData *particles;
struct KDTree *emitter_field;
float *emitter_cosnos; /* localspace face centers and normals (average of its verts), from the derived mesh */
int *mirror_cache;
@@ -304,7 +303,7 @@ struct PointCache *BKE_ptcache_add(struct ListBase *ptcaches);
void BKE_ptcache_free_mem(struct ListBase *mem_cache);
void BKE_ptcache_free(struct PointCache *cache);
void BKE_ptcache_free_list(struct ListBase *ptcaches);
-struct PointCache *BKE_ptcache_copy_list(struct ListBase *ptcaches_new, struct ListBase *ptcaches_old, bool copy_data);
+struct PointCache *BKE_ptcache_copy_list(struct ListBase *ptcaches_new, const struct ListBase *ptcaches_old, bool copy_data);
/********************** Baking *********************/
diff --git a/source/blender/blenkernel/BKE_rigidbody.h b/source/blender/blenkernel/BKE_rigidbody.h
index c946f3ac9e8..a30ce6cda79 100644
--- a/source/blender/blenkernel/BKE_rigidbody.h
+++ b/source/blender/blenkernel/BKE_rigidbody.h
@@ -39,7 +39,6 @@ struct RigidBodyOb;
struct Scene;
struct Object;
-struct Group;
/* -------------- */
/* Memory Management */
@@ -70,7 +69,7 @@ void BKE_rigidbody_world_groups_relink(struct RigidBodyWorld *rbw);
void BKE_rigidbody_validate_sim_world(struct Scene *scene, struct RigidBodyWorld *rbw, bool rebuild);
void BKE_rigidbody_calc_volume(struct Object *ob, float *r_vol);
-void BKE_rigidbody_calc_center_of_mass(struct Object *ob, float r_com[3]);
+void BKE_rigidbody_calc_center_of_mass(struct Object *ob, float r_center[3]);
/* -------------- */
/* Utilities */
@@ -99,4 +98,19 @@ void BKE_rigidbody_cache_reset(struct RigidBodyWorld *rbw);
void BKE_rigidbody_rebuild_world(struct Scene *scene, float ctime);
void BKE_rigidbody_do_simulation(struct Scene *scene, float ctime);
+/* -------------------- */
+/* Depsgraph evaluation */
+
+struct EvaluationContext;
+
+void BKE_rigidbody_rebuild_sim(struct EvaluationContext *eval_ctx,
+ struct Scene *scene);
+
+void BKE_rigidbody_eval_simulation(struct EvaluationContext *eval_ctx,
+ struct Scene *scene);
+
+void BKE_rigidbody_object_sync_transforms(struct EvaluationContext *eval_ctx,
+ struct Scene *scene,
+ struct Object *ob);
+
#endif /* __BKE_RIGIDBODY_H__ */
diff --git a/source/blender/blenkernel/BKE_sca.h b/source/blender/blenkernel/BKE_sca.h
index d598a26fdf9..ebdd159b40c 100644
--- a/source/blender/blenkernel/BKE_sca.h
+++ b/source/blender/blenkernel/BKE_sca.h
@@ -31,7 +31,6 @@
* \ingroup bke
*/
-struct Text;
struct bSensor;
struct Object;
struct bController;
diff --git a/source/blender/blenkernel/BKE_scene.h b/source/blender/blenkernel/BKE_scene.h
index 1bfe0eeea0b..027bdbbbe58 100644
--- a/source/blender/blenkernel/BKE_scene.h
+++ b/source/blender/blenkernel/BKE_scene.h
@@ -40,14 +40,12 @@ extern "C" {
struct AviCodecData;
struct Base;
struct EvaluationContext;
-struct bglMats;
struct Main;
struct Object;
struct QuicktimeCodecData;
struct RenderData;
struct SceneRenderLayer;
struct Scene;
-struct Text;
struct UnitSettings;
struct Main;
@@ -72,6 +70,7 @@ void BKE_scene_free(struct Scene *sce);
struct Scene *BKE_scene_add(struct Main *bmain, const char *name);
/* base functions */
+struct Base *BKE_scene_base_find_by_name(struct Scene *scene, const char *name);
struct Base *BKE_scene_base_find(struct Scene *scene, struct Object *ob);
struct Base *BKE_scene_base_add(struct Scene *sce, struct Object *ob);
void BKE_scene_base_unlink(struct Scene *sce, struct Base *base);
@@ -110,10 +109,10 @@ char *BKE_scene_find_marker_name(struct Scene *scene, int frame);
char *BKE_scene_find_last_marker_name(struct Scene *scene, int frame);
/* checks for cycle, returns 1 if it's all OK */
-int BKE_scene_validate_setscene(struct Main *bmain, struct Scene *sce);
+bool BKE_scene_validate_setscene(struct Main *bmain, struct Scene *sce);
-float BKE_scene_frame_get(struct Scene *scene);
-float BKE_scene_frame_get_from_ctime(struct Scene *scene, const float frame);
+float BKE_scene_frame_get(const struct Scene *scene);
+float BKE_scene_frame_get_from_ctime(const struct Scene *scene, const float frame);
void BKE_scene_frame_set(struct Scene *scene, double cfra);
/* ** Scene evaluation ** */
@@ -124,14 +123,20 @@ void BKE_scene_update_for_newframe_ex(struct EvaluationContext *eval_ctx, struct
struct SceneRenderLayer *BKE_scene_add_render_layer(struct Scene *sce, const char *name);
bool BKE_scene_remove_render_layer(struct Main *main, struct Scene *scene, struct SceneRenderLayer *srl);
+struct SceneRenderView *BKE_scene_add_render_view(struct Scene *sce, const char *name);
+bool BKE_scene_remove_render_view(struct Scene *scene, struct SceneRenderView *srv);
+
/* render profile */
-int get_render_subsurf_level(struct RenderData *r, int level);
-int get_render_child_particle_number(struct RenderData *r, int num);
-int get_render_shadow_samples(struct RenderData *r, int samples);
-float get_render_aosss_error(struct RenderData *r, float error);
+int get_render_subsurf_level(const struct RenderData *r, int level, bool for_render);
+int get_render_child_particle_number(const struct RenderData *r, int num, bool for_render);
+int get_render_shadow_samples(const struct RenderData *r, int samples);
+float get_render_aosss_error(const struct RenderData *r, float error);
+
+bool BKE_scene_use_new_shading_nodes(const struct Scene *scene);
+bool BKE_scene_use_shading_nodes_custom(struct Scene *scene);
-bool BKE_scene_use_new_shading_nodes(struct Scene *scene);
-bool BKE_scene_uses_blender_internal(struct Scene *scene);
+bool BKE_scene_uses_blender_internal(const struct Scene *scene);
+bool BKE_scene_uses_blender_game(const struct Scene *scene);
void BKE_scene_disable_color_management(struct Scene *scene);
bool BKE_scene_check_color_management_enabled(const struct Scene *scene);
@@ -142,6 +147,23 @@ int BKE_render_num_threads(const struct RenderData *r);
double BKE_scene_unit_scale(const struct UnitSettings *unit, const int unit_type, double value);
+/* multiview */
+bool BKE_scene_multiview_is_stereo3d(const struct RenderData *rd);
+bool BKE_scene_multiview_is_render_view_active(const struct RenderData *rd, const struct SceneRenderView *srv);
+bool BKE_scene_multiview_is_render_view_first(const struct RenderData *rd, const char *viewname);
+bool BKE_scene_multiview_is_render_view_last(const struct RenderData *rd, const char *viewname);
+size_t BKE_scene_multiview_num_views_get(const struct RenderData *rd);
+struct SceneRenderView *BKE_scene_multiview_render_view_findindex(const struct RenderData *rd, const int view_id);
+const char *BKE_scene_multiview_render_view_name_get(const struct RenderData *rd, const int view_id);
+size_t BKE_scene_multiview_view_id_get(const struct RenderData *rd, const char *viewname);
+void BKE_scene_multiview_filepath_get(struct SceneRenderView *srv, const char *filepath, char *r_filepath);
+void BKE_scene_multiview_view_filepath_get(const struct RenderData *rd, const char *filepath, const char *view, char *r_filepath);
+const char *BKE_scene_multiview_view_suffix_get(const struct RenderData *rd, const char *viewname);
+const char *BKE_scene_multiview_view_id_suffix_get(const struct RenderData *rd, const size_t view_id);
+void BKE_scene_multiview_view_prefix_get(struct Scene *scene, const char *name, char *rprefix, const char **rext);
+void BKE_scene_multiview_videos_dimensions_get(const struct RenderData *rd, const size_t width, const size_t height, size_t *r_width, size_t *r_height);
+size_t BKE_scene_multiview_num_videos_get(const struct RenderData *rd);
+
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/blenkernel/BKE_screen.h b/source/blender/blenkernel/BKE_screen.h
index 188b8e22815..48616418e67 100644
--- a/source/blender/blenkernel/BKE_screen.h
+++ b/source/blender/blenkernel/BKE_screen.h
@@ -47,11 +47,11 @@ struct bContextDataResult;
struct bScreen;
struct uiLayout;
struct uiList;
-struct uiMenuItem;
struct wmKeyConfig;
struct wmNotifier;
struct wmWindow;
struct wmWindowManager;
+struct GPUFXSettings;
#include "BLI_compiler_attrs.h"
@@ -265,7 +265,7 @@ struct SpaceType *BKE_spacetype_from_id(int spaceid);
struct ARegionType *BKE_regiontype_from_id(struct SpaceType *st, int regionid);
const struct ListBase *BKE_spacetypes_list(void);
void BKE_spacetype_register(struct SpaceType *st);
-int BKE_spacetype_exists(int spaceid);
+bool BKE_spacetype_exists(int spaceid);
void BKE_spacetypes_free(void); /* only for quitting blender */
/* spacedata */
@@ -273,6 +273,9 @@ void BKE_spacedata_freelist(ListBase *lb);
void BKE_spacedata_copylist(ListBase *lb1, ListBase *lb2);
void BKE_spacedata_draw_locks(int set);
+void BKE_spacedata_callback_id_unref_set(void (*func)(struct SpaceLink *sl, const struct ID *));
+void BKE_spacedata_id_unref(struct SpaceLink *sl, const struct ID *id);
+
/* area/regions */
struct ARegion *BKE_area_region_copy(struct SpaceType *st, struct ARegion *ar);
void BKE_area_region_free(struct SpaceType *st, struct ARegion *ar);
@@ -280,18 +283,24 @@ void BKE_screen_area_free(struct ScrArea *sa);
struct ARegion *BKE_area_find_region_type(struct ScrArea *sa, int type);
struct ARegion *BKE_area_find_region_active_win(struct ScrArea *sa);
+struct ARegion *BKE_area_find_region_xy(struct ScrArea *sa, const int regiontype, int x, int y);
+struct ScrArea *BKE_screen_find_area_from_space(struct bScreen *sc, struct SpaceLink *sl) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1, 2);
struct ScrArea *BKE_screen_find_big_area(struct bScreen *sc, const int spacetype, const short min);
+struct ScrArea *BKE_screen_find_area_xy(struct bScreen *sc, const int spacetype, int x, int y);
unsigned int BKE_screen_view3d_layer_active_ex(
const struct View3D *v3d, const struct Scene *scene, bool use_localvd) ATTR_NONNULL(2);
unsigned int BKE_screen_view3d_layer_active(
const struct View3D *v3d, const struct Scene *scene) ATTR_NONNULL(2);
+unsigned int BKE_screen_view3d_layer_all(const struct bScreen *sc) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1);
+
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);
+void BKE_screen_gpu_fx_validate(struct GPUFXSettings *fx_settings);
/* zoom factor conversion */
float BKE_screen_view3d_zoom_to_fac(float camzoom);
diff --git a/source/blender/blenkernel/BKE_sequencer.h b/source/blender/blenkernel/BKE_sequencer.h
index 13cc5d2e84f..f73548373ef 100644
--- a/source/blender/blenkernel/BKE_sequencer.h
+++ b/source/blender/blenkernel/BKE_sequencer.h
@@ -34,14 +34,14 @@ struct bContext;
struct EvaluationContext;
struct StripColorBalance;
struct Editing;
+struct GSet;
struct ImBuf;
struct Main;
struct Mask;
-struct MovieClip;
struct Scene;
struct Sequence;
struct SequenceModifierData;
-struct Strip;
+struct Stereo3dFormat;
struct StripElem;
struct bSound;
@@ -100,10 +100,13 @@ typedef struct SeqRenderData {
float motion_blur_shutter;
bool skip_cache;
bool is_proxy_render;
+ size_t view_id;
} SeqRenderData;
-SeqRenderData BKE_sequencer_new_render_data(struct EvaluationContext *eval_ctx, struct Main *bmain,
- struct Scene *scene, int rectx, int recty, int preview_render_size);
+void BKE_sequencer_new_render_data(
+ struct EvaluationContext *eval_ctx, struct Main *bmain, struct Scene *scene,
+ int rectx, int recty, int preview_render_size,
+ SeqRenderData *r_context);
/* Wipe effect */
enum {
@@ -217,7 +220,12 @@ void BKE_sequence_clipboard_pointers_free(struct Sequence *seq);
void BKE_sequence_clipboard_pointers_store(struct Sequence *seq);
void BKE_sequence_clipboard_pointers_restore(struct Sequence *seq, struct Main *bmain);
+void BKE_sequencer_base_clipboard_pointers_free(struct ListBase *seqbase);
+void BKE_sequencer_base_clipboard_pointers_store(struct ListBase *seqbase);
+void BKE_sequencer_base_clipboard_pointers_restore(struct ListBase *seqbase, struct Main *bmain);
+
void BKE_sequence_free(struct Scene *scene, struct Sequence *seq);
+void BKE_sequence_free_anim(struct Sequence *seq);
const char *BKE_sequence_give_name(struct Sequence *seq);
void BKE_sequence_calc(struct Scene *scene, struct Sequence *seq);
void BKE_sequence_calc_disp(struct Scene *scene, struct Sequence *seq);
@@ -230,10 +238,11 @@ struct StripElem *BKE_sequencer_give_stripelem(struct Sequence *seq, int cfra);
void BKE_sequencer_update_changed_seq_and_deps(struct Scene *scene, struct Sequence *changed_seq, int len_change, int ibuf_change);
bool BKE_sequencer_input_have_to_preprocess(const SeqRenderData *context, struct Sequence *seq, float cfra);
-struct SeqIndexBuildContext *BKE_sequencer_proxy_rebuild_context(struct Main *bmain, struct Scene *scene, struct Sequence *seq);
+void BKE_sequencer_proxy_rebuild_context(struct Main *bmain, struct Scene *scene, struct Sequence *seq, struct GSet *file_list, ListBase *queue);
void BKE_sequencer_proxy_rebuild(struct SeqIndexBuildContext *context, short *stop, short *do_update, float *progress);
void BKE_sequencer_proxy_rebuild_finish(struct SeqIndexBuildContext *context, bool stop);
+void BKE_sequencer_proxy_set(struct Sequence *seq, bool value);
/* **********************************************************************
* seqcache.c
*
@@ -245,25 +254,25 @@ typedef enum {
SEQ_STRIPELEM_IBUF_COMP,
SEQ_STRIPELEM_IBUF_STARTSTILL,
SEQ_STRIPELEM_IBUF_ENDSTILL
-} seq_stripelem_ibuf_t;
+} eSeqStripElemIBuf;
void BKE_sequencer_cache_destruct(void);
void BKE_sequencer_cache_cleanup(void);
/* returned ImBuf is properly refed and has to be freed */
-struct ImBuf *BKE_sequencer_cache_get(const SeqRenderData *context, struct Sequence *seq, float cfra, seq_stripelem_ibuf_t type);
+struct ImBuf *BKE_sequencer_cache_get(const SeqRenderData *context, struct Sequence *seq, float cfra, eSeqStripElemIBuf type);
/* passed ImBuf is properly refed, so ownership is *not*
* transferred to the cache.
* you can pass the same ImBuf multiple times to the cache without problems.
*/
-void BKE_sequencer_cache_put(const SeqRenderData *context, struct Sequence *seq, float cfra, seq_stripelem_ibuf_t type, struct ImBuf *nval);
+void BKE_sequencer_cache_put(const SeqRenderData *context, struct Sequence *seq, float cfra, eSeqStripElemIBuf type, struct ImBuf *nval);
void BKE_sequencer_cache_cleanup_sequence(struct Sequence *seq);
-struct ImBuf *BKE_sequencer_preprocessed_cache_get(const SeqRenderData *context, struct Sequence *seq, float cfra, seq_stripelem_ibuf_t type);
-void BKE_sequencer_preprocessed_cache_put(const SeqRenderData *context, struct Sequence *seq, float cfra, seq_stripelem_ibuf_t type, struct ImBuf *ibuf);
+struct ImBuf *BKE_sequencer_preprocessed_cache_get(const SeqRenderData *context, struct Sequence *seq, float cfra, eSeqStripElemIBuf type);
+void BKE_sequencer_preprocessed_cache_put(const SeqRenderData *context, struct Sequence *seq, float cfra, eSeqStripElemIBuf type, struct ImBuf *ibuf);
void BKE_sequencer_preprocessed_cache_cleanup(void);
void BKE_sequencer_preprocessed_cache_cleanup_sequence(struct Sequence *seq);
@@ -287,7 +296,7 @@ int BKE_sequence_effect_get_supports_mask(int seq_type);
* Sequencer editing functions
* **********************************************************************
*/
-
+
/* for transform but also could use elsewhere */
int BKE_sequence_tx_get_final_left(struct Sequence *seq, bool metaclip);
int BKE_sequence_tx_get_final_right(struct Sequence *seq, bool metaclip);
@@ -306,9 +315,13 @@ struct Sequence *BKE_sequence_metastrip(ListBase *seqbase /* = ed->seqbase */, s
void BKE_sequencer_offset_animdata(struct Scene *scene, struct Sequence *seq, int ofs);
void BKE_sequencer_dupe_animdata(struct Scene *scene, const char *name_src, const char *name_dst);
-bool BKE_sequence_base_shuffle(struct ListBase *seqbasep, struct Sequence *test, struct Scene *evil_scene);
+bool BKE_sequence_base_shuffle_ex(
+ struct ListBase *seqbasep, struct Sequence *test, struct Scene *evil_scene,
+ int channel_delta);
+bool BKE_sequence_base_shuffle(
+ struct ListBase *seqbasep, struct Sequence *test, struct Scene *evil_scene);
bool BKE_sequence_base_shuffle_time(ListBase *seqbasep, struct Scene *evil_scene);
-bool BKE_sequence_base_isolated_sel_check(struct ListBase *seqbase, bool one_only);
+bool BKE_sequence_base_isolated_sel_check(struct ListBase *seqbase);
void BKE_sequencer_free_imbuf(struct Scene *scene, struct ListBase *seqbasep, bool for_render);
struct Sequence *BKE_sequence_dupli_recursive(struct Scene *scene, struct Scene *scene_to, struct Sequence *seq, int dupe_flag);
int BKE_sequence_swap(struct Sequence *seq_a, struct Sequence *seq_b, const char **error_str);
@@ -326,7 +339,9 @@ void BKE_sequencer_update_sound(struct Scene *scene, struct bSound *sound);
void BKE_sequencer_refresh_sound_length(struct Scene *scene);
void BKE_sequence_base_unique_name_recursive(ListBase *seqbasep, struct Sequence *seq);
-void BKE_sequence_base_dupli_recursive(struct Scene *scene, struct Scene *scene_to, ListBase *nseqbase, ListBase *seqbase, int dupe_flag);
+void BKE_sequence_base_dupli_recursive(
+ struct Scene *scene, struct Scene *scene_to, ListBase *nseqbase, ListBase *seqbase,
+ int dupe_flag);
bool BKE_sequence_is_valid_check(struct Sequence *seq);
void BKE_sequencer_clear_scene_in_allseqs(struct Main *bmain, struct Scene *sce);
@@ -343,6 +358,10 @@ typedef struct SeqLoadInfo {
int len; /* only for image strips */
char path[1024]; /* 1024 = FILE_MAX */
+ /* multiview */
+ char views_format;
+ struct Stereo3dFormat *stereo3d_format;
+
/* return values */
char name[64];
struct Sequence *seq_sound; /* for movie's */
@@ -371,12 +390,23 @@ struct Sequence *BKE_sequence_alloc(ListBase *lb, int cfra, int machine);
void BKE_sequence_alpha_mode_from_extension(struct Sequence *seq);
void BKE_sequence_init_colorspace(struct Sequence *seq);
+/* RNA enums, just to be more readable */
+enum {
+ SEQ_SIDE_NONE = 0,
+ SEQ_SIDE_LEFT,
+ SEQ_SIDE_RIGHT,
+ SEQ_SIDE_BOTH
+};
+int BKE_sequencer_find_next_prev_edit(
+ struct Scene *scene, int cfra, const short side,
+ const bool do_skip_mute, const bool do_center, const bool do_unselected);
+
struct Sequence *BKE_sequencer_add_image_strip(struct bContext *C, ListBase *seqbasep, struct SeqLoadInfo *seq_load);
struct Sequence *BKE_sequencer_add_sound_strip(struct bContext *C, ListBase *seqbasep, struct SeqLoadInfo *seq_load);
struct Sequence *BKE_sequencer_add_movie_strip(struct bContext *C, ListBase *seqbasep, struct SeqLoadInfo *seq_load);
/* view3d draw callback, run when not in background view */
-typedef struct ImBuf *(*SequencerDrawView)(struct Scene *, struct Object *, int, int, unsigned int, int, bool, bool, int, char[256]);
+typedef struct ImBuf *(*SequencerDrawView)(struct Scene *, struct Object *, int, int, unsigned int, int, bool, bool, bool, int, const char *, char[256]);
extern SequencerDrawView sequencer_view3d_cb;
/* copy/paste */
@@ -410,7 +440,7 @@ typedef struct SequenceModifierTypeInfo {
void (*apply) (struct SequenceModifierData *smd, struct ImBuf *ibuf, struct ImBuf *mask);
} SequenceModifierTypeInfo;
-struct SequenceModifierTypeInfo *BKE_sequence_modifier_type_info_get(int type);
+const struct SequenceModifierTypeInfo *BKE_sequence_modifier_type_info_get(int type);
struct SequenceModifierData *BKE_sequence_modifier_new(struct Sequence *seq, const char *name, int type);
bool BKE_sequence_modifier_remove(struct Sequence *seq, struct SequenceModifierData *smd);
@@ -424,7 +454,9 @@ void BKE_sequence_modifier_list_copy(struct Sequence *seqn, struct Sequence *seq
int BKE_sequence_supports_modifiers(struct Sequence *seq);
/* internal filters */
-struct ImBuf *BKE_sequencer_render_mask_input(const SeqRenderData *context, int mask_input_type, struct Sequence *mask_sequence, struct Mask *mask_id, int cfra, bool make_float);
+struct ImBuf *BKE_sequencer_render_mask_input(
+ const SeqRenderData *context, int mask_input_type, struct Sequence *mask_sequence, struct Mask *mask_id,
+ int cfra, int fra_offset, bool make_float);
void BKE_sequencer_color_balance_apply(struct StripColorBalance *cb, struct ImBuf *ibuf, float mul, bool make_float, struct ImBuf *mask_input);
#endif /* __BKE_SEQUENCER_H__ */
diff --git a/source/blender/blenkernel/BKE_shrinkwrap.h b/source/blender/blenkernel/BKE_shrinkwrap.h
index 070cd4a9cf0..070f5c762db 100644
--- a/source/blender/blenkernel/BKE_shrinkwrap.h
+++ b/source/blender/blenkernel/BKE_shrinkwrap.h
@@ -47,7 +47,6 @@
*/
struct Object;
-struct Scene;
struct DerivedMesh;
struct MVert;
struct MDeformVert;
diff --git a/source/blender/blenkernel/BKE_sound.h b/source/blender/blenkernel/BKE_sound.h
index 50ca5fcdf7b..e68be701b61 100644
--- a/source/blender/blenkernel/BKE_sound.h
+++ b/source/blender/blenkernel/BKE_sound.h
@@ -35,9 +35,11 @@
#define SOUND_WAVE_SAMPLES_PER_SECOND 250
-struct PackedFile;
+#ifdef WITH_SYSTEM_AUDASPACE
+# include AUD_DEVICE_H
+#endif
+
struct bSound;
-struct ListBase;
struct Main;
struct Sequence;
@@ -46,100 +48,101 @@ typedef struct SoundWaveform {
float *data;
} SoundWaveform;
-void sound_init_once(void);
-void sound_exit_once(void);
+void BKE_sound_init_once(void);
+void BKE_sound_exit_once(void);
+
+void *BKE_sound_get_device(void);
-void sound_init(struct Main *main);
+void BKE_sound_init(struct Main *main);
-void sound_init_main(struct Main *bmain);
+void BKE_sound_init_main(struct Main *bmain);
-void sound_exit(void);
+void BKE_sound_exit(void);
-void sound_force_device(int device);
-int sound_define_from_str(const char *str);
+void BKE_sound_force_device(const char *device);
-struct bSound *sound_new_file(struct Main *main, const char *filename);
+struct bSound *BKE_sound_new_file(struct Main *main, const char *filename);
// XXX unused currently
#if 0
-struct bSound *sound_new_buffer(struct Main *bmain, struct bSound *source);
+struct bSound *BKE_sound_new_buffer(struct Main *bmain, struct bSound *source);
-struct bSound *sound_new_limiter(struct Main *bmain, struct bSound *source, float start, float end);
+struct bSound *BKE_sound_new_limiter(struct Main *bmain, struct bSound *source, float start, float end);
#endif
-void sound_delete(struct Main *bmain, struct bSound *sound);
+void BKE_sound_delete(struct Main *bmain, struct bSound *sound);
-void sound_cache(struct bSound *sound);
+void BKE_sound_cache(struct bSound *sound);
-void sound_cache_notifying(struct Main *main, struct bSound *sound);
+void BKE_sound_delete_cache(struct bSound *sound);
-void sound_delete_cache(struct bSound *sound);
-
-void sound_load(struct Main *main, struct bSound *sound);
+void BKE_sound_load(struct Main *main, struct bSound *sound);
void BKE_sound_free(struct bSound *sound);
-#ifdef __AUD_C_API_H__
-AUD_Device *sound_mixdown(struct Scene *scene, AUD_DeviceSpecs specs, int start, float volume);
+#if defined(__AUD_C_API_H__) || defined(WITH_SYSTEM_AUDASPACE)
+AUD_Device *BKE_sound_mixdown(struct Scene *scene, AUD_DeviceSpecs specs, int start, float volume);
#endif
-void sound_create_scene(struct Scene *scene);
+void BKE_sound_create_scene(struct Scene *scene);
+
+void BKE_sound_destroy_scene(struct Scene *scene);
-void sound_destroy_scene(struct Scene *scene);
+void BKE_sound_mute_scene(struct Scene *scene, int muted);
-void sound_mute_scene(struct Scene *scene, int muted);
+void BKE_sound_update_fps(struct Scene *scene);
-void sound_update_fps(struct Scene *scene);
+void BKE_sound_update_scene_listener(struct Scene *scene);
-void sound_update_scene_listener(struct Scene *scene);
+void *BKE_sound_scene_add_scene_sound(struct Scene *scene, struct Sequence *sequence, int startframe, int endframe, int frameskip);
+void *BKE_sound_scene_add_scene_sound_defaults(struct Scene *scene, struct Sequence *sequence);
-void *sound_scene_add_scene_sound(struct Scene *scene, struct Sequence *sequence, int startframe, int endframe, int frameskip);
-void *sound_scene_add_scene_sound_defaults(struct Scene *scene, struct Sequence *sequence);
+void *BKE_sound_add_scene_sound(struct Scene *scene, struct Sequence *sequence, int startframe, int endframe, int frameskip);
+void *BKE_sound_add_scene_sound_defaults(struct Scene *scene, struct Sequence *sequence);
-void *sound_add_scene_sound(struct Scene *scene, struct Sequence *sequence, int startframe, int endframe, int frameskip);
-void *sound_add_scene_sound_defaults(struct Scene *scene, struct Sequence *sequence);
+void BKE_sound_remove_scene_sound(struct Scene *scene, void *handle);
-void sound_remove_scene_sound(struct Scene *scene, void *handle);
+void BKE_sound_mute_scene_sound(void *handle, char mute);
-void sound_mute_scene_sound(void *handle, char mute);
+void BKE_sound_move_scene_sound(struct Scene *scene, void *handle, int startframe, int endframe, int frameskip);
+void BKE_sound_move_scene_sound_defaults(struct Scene *scene, struct Sequence *sequence);
-void sound_move_scene_sound(struct Scene *scene, void *handle, int startframe, int endframe, int frameskip);
-void sound_move_scene_sound_defaults(struct Scene *scene, struct Sequence *sequence);
+void BKE_sound_update_scene_sound(void *handle, struct bSound *sound);
-void sound_update_scene_sound(void *handle, struct bSound *sound);
+void BKE_sound_set_cfra(int cfra);
-void sound_set_cfra(int cfra);
+void BKE_sound_set_scene_volume(struct Scene *scene, float volume);
-void sound_set_scene_volume(struct Scene *scene, float volume);
+void BKE_sound_set_scene_sound_volume(void *handle, float volume, char animated);
-void sound_set_scene_sound_volume(void *handle, float volume, char animated);
+void BKE_sound_set_scene_sound_pitch(void *handle, float pitch, char animated);
-void sound_set_scene_sound_pitch(void *handle, float pitch, char animated);
+void BKE_sound_set_scene_sound_pan(void *handle, float pan, char animated);
-void sound_set_scene_sound_pan(void *handle, float pan, char animated);
+void BKE_sound_update_sequencer(struct Main *main, struct bSound *sound);
-void sound_update_sequencer(struct Main *main, struct bSound *sound);
+void BKE_sound_play_scene(struct Scene *scene);
-void sound_play_scene(struct Scene *scene);
+void BKE_sound_stop_scene(struct Scene *scene);
-void sound_stop_scene(struct Scene *scene);
+void BKE_sound_seek_scene(struct Main *bmain, struct Scene *scene);
-void sound_seek_scene(struct Main *bmain, struct Scene *scene);
+float BKE_sound_sync_scene(struct Scene *scene);
-float sound_sync_scene(struct Scene *scene);
+int BKE_sound_scene_playing(struct Scene *scene);
-int sound_scene_playing(struct Scene *scene);
+void BKE_sound_free_waveform(struct bSound *sound);
-void sound_free_waveform(struct bSound *sound);
+void BKE_sound_read_waveform(struct bSound *sound, short *stop);
-void sound_read_waveform(struct bSound *sound);
+void BKE_sound_update_scene(struct Main *bmain, struct Scene *scene);
-void sound_update_scene(struct Main *bmain, struct Scene *scene);
+void *BKE_sound_get_factory(void *sound);
-void *sound_get_factory(void *sound);
+float BKE_sound_get_length(struct bSound *sound);
-float sound_get_length(struct bSound *sound);
+char **BKE_sound_get_device_names(void);
-bool sound_is_jack_supported(void);
+bool BKE_sound_is_jack_supported(void);
#endif /* __BKE_SOUND_H__ */
diff --git a/source/blender/blenkernel/BKE_subsurf.h b/source/blender/blenkernel/BKE_subsurf.h
index 3dae4087866..161ab2f2fbd 100644
--- a/source/blender/blenkernel/BKE_subsurf.h
+++ b/source/blender/blenkernel/BKE_subsurf.h
@@ -41,17 +41,14 @@ struct DerivedMesh;
struct MeshElemMap;
struct Mesh;
struct MPoly;
-struct MultiresSubsurf;
struct Object;
struct PBVH;
struct SubsurfModifierData;
struct CCGEdge;
struct CCGFace;
-struct CCGSubsurf;
struct CCGVert;
struct EdgeHash;
struct PBVH;
-struct DMGridAdjacency;
/**************************** External *****************************/
@@ -60,7 +57,8 @@ typedef enum {
SUBSURF_IS_FINAL_CALC = 2,
SUBSURF_FOR_EDIT_MODE = 4,
SUBSURF_IN_EDIT_MODE = 8,
- SUBSURF_ALLOC_PAINT_MASK = 16
+ SUBSURF_ALLOC_PAINT_MASK = 16,
+ SUBSURF_USE_GPU_BACKEND = 32,
} SubsurfFlags;
struct DerivedMesh *subsurf_make_derived_from_derived(
@@ -87,6 +85,9 @@ void subsurf_copy_grid_paint_mask(struct DerivedMesh *dm,
const struct MPoly *mpoly, float *paint_mask,
const struct GridPaintMask *grid_paint_mask);
+bool subsurf_has_edges(struct DerivedMesh *dm);
+bool subsurf_has_faces(struct DerivedMesh *dm);
+
typedef enum MultiresModifiedFlags {
/* indicates the grids have been sculpted on, so MDisps
* have to be updated */
@@ -102,7 +103,7 @@ typedef struct CCGDerivedMesh {
struct CCGSubSurf *ss;
int freeSS;
- int drawInteriorEdges, useSubsurfUv;
+ int drawInteriorEdges, useSubsurfUv, useGpuBackend;
struct {int startVert; struct CCGVert *vert; } *vertMap;
struct {int startVert; int startEdge; struct CCGEdge *edge; } *edgeMap;
@@ -120,7 +121,6 @@ typedef struct CCGDerivedMesh {
int *pmap_mem;
struct CCGElem **gridData;
- struct DMGridAdjacency *gridAdjacency;
int *gridOffset;
struct CCGFace **gridFaces;
struct DMFlagMat *gridFlagMats;
diff --git a/source/blender/blenkernel/BKE_text.h b/source/blender/blenkernel/BKE_text.h
index 1e79eaa8431..a5a59d14c92 100644
--- a/source/blender/blenkernel/BKE_text.h
+++ b/source/blender/blenkernel/BKE_text.h
@@ -40,18 +40,17 @@ extern "C" {
struct Main;
struct Text;
struct TextLine;
-struct SpaceText;
void BKE_text_free (struct Text *text);
void txt_set_undostate (int u);
int txt_get_undostate (void);
struct Text *BKE_text_add (struct Main *bmain, const char *name);
int txt_extended_ascii_as_utf8(char **str);
-int BKE_text_reload (struct Text *text);
+bool BKE_text_reload(struct Text *text);
struct Text *BKE_text_load_ex(struct Main *bmain, const char *file, const char *relpath,
const bool is_internal);
struct Text *BKE_text_load (struct Main *bmain, const char *file, const char *relpath);
-struct Text *BKE_text_copy (struct Text *ta);
+struct Text *BKE_text_copy (struct Main *bmain, struct Text *ta);
void BKE_text_unlink (struct Main *bmain, struct Text *text);
void BKE_text_clear (struct Text *text);
void BKE_text_write (struct Text *text, const char *str);
diff --git a/source/blender/blenkernel/BKE_texture.h b/source/blender/blenkernel/BKE_texture.h
index 4ad84dceb53..95918b9ca0b 100644
--- a/source/blender/blenkernel/BKE_texture.h
+++ b/source/blender/blenkernel/BKE_texture.h
@@ -42,9 +42,7 @@ struct Brush;
struct ColorBand;
struct EnvMap;
struct FreestyleLineStyle;
-struct HaloRen;
struct Lamp;
-struct LampRen;
struct Main;
struct Material;
struct MTex;
@@ -61,8 +59,6 @@ struct World;
#define MAXCOLORBAND 32
-void BKE_texture_free(struct Tex *t);
-
void init_colorband(struct ColorBand *coba, bool rangetype);
struct ColorBand *add_colorband(bool rangetype);
bool do_colorband(const struct ColorBand *coba, float in, float out[4]);
@@ -71,15 +67,17 @@ struct CBData *colorband_element_add(struct ColorBand *coba, float position);
int colorband_element_remove(struct ColorBand *coba, int index);
void colorband_update_sort(struct ColorBand *coba);
-void default_tex(struct Tex *tex);
-struct Tex *add_texture(struct Main *bmain, const char *name);
-void tex_set_type(struct Tex *tex, int type);
-void default_mtex(struct MTex *mtex);
-struct MTex *add_mtex(void);
-struct MTex *add_mtex_id(struct ID *id, int slot);
-struct Tex *BKE_texture_copy(struct Tex *tex);
-struct Tex *localize_texture(struct Tex *tex);
-void BKE_texture_make_local(struct Tex *tex);
+void BKE_texture_free(struct Tex *tex);
+void BKE_texture_default(struct Tex *tex);
+struct Tex *BKE_texture_copy(struct Tex *tex);
+struct Tex *BKE_texture_add(struct Main *bmain, const char *name);
+struct Tex *BKE_texture_localize(struct Tex *tex);
+void BKE_texture_make_local(struct Tex *tex);
+void BKE_texture_type_set(struct Tex *tex, int type);
+
+void BKE_texture_mtex_default(struct MTex *mtex);
+struct MTex *BKE_texture_mtex_add(void);
+struct MTex *BKE_texture_mtex_add_id(struct ID *id, int slot);
/* UNUSED */
// void autotexname(struct Tex *tex);
@@ -105,35 +103,39 @@ void set_current_particle_texture(struct ParticleSettings *part, struct Tex *tex
bool has_current_material_texture(struct Material *ma);
-struct TexMapping *add_tex_mapping(int type);
-void default_tex_mapping(struct TexMapping *texmap, int type);
-void init_tex_mapping(struct TexMapping *texmap);
+struct TexMapping *BKE_texture_mapping_add(int type);
+void BKE_texture_mapping_default(struct TexMapping *texmap, int type);
+void BKE_texture_mapping_init(struct TexMapping *texmap);
+
+struct ColorMapping *BKE_texture_colormapping_add(void);
+void BKE_texture_colormapping_default(struct ColorMapping *colormap);
-struct ColorMapping *add_color_mapping(void);
-void default_color_mapping(struct ColorMapping *colormap);
+void BKE_texture_envmap_free_data(struct EnvMap *env);
+void BKE_texture_envmap_free(struct EnvMap *env);
+struct EnvMap *BKE_texture_envmap_add(void);
+struct EnvMap *BKE_texture_envmap_copy(struct EnvMap *env);
-void BKE_free_envmapdata(struct EnvMap *env);
-void BKE_free_envmap(struct EnvMap *env);
-struct EnvMap *BKE_add_envmap(void);
-struct EnvMap *BKE_copy_envmap(struct EnvMap *env);
+void BKE_texture_pointdensity_init_data(struct PointDensity *pd);
+void BKE_texture_pointdensity_free_data(struct PointDensity *pd);
+void BKE_texture_pointdensity_free(struct PointDensity *pd);
+struct PointDensity *BKE_texture_pointdensity_add(void);
+struct PointDensity *BKE_texture_pointdensity_copy(struct PointDensity *pd);
-void BKE_free_pointdensitydata(struct PointDensity *pd);
-void BKE_free_pointdensity(struct PointDensity *pd);
-struct PointDensity *BKE_add_pointdensity(void);
-struct PointDensity *BKE_copy_pointdensity(struct PointDensity *pd);
+void BKE_texture_voxeldata_free_data(struct VoxelData *vd);
+void BKE_texture_voxeldata_free(struct VoxelData *vd);
+struct VoxelData *BKE_texture_voxeldata_add(void);
+struct VoxelData *BKE_texture_voxeldata_copy(struct VoxelData *vd);
-void BKE_free_voxeldatadata(struct VoxelData *vd);
-void BKE_free_voxeldata(struct VoxelData *vd);
-struct VoxelData *BKE_add_voxeldata(void);
-struct VoxelData *BKE_copy_voxeldata(struct VoxelData *vd);
+void BKE_texture_ocean_free(struct OceanTex *ot);
+struct OceanTex *BKE_texture_ocean_add(void);
+struct OceanTex *BKE_texture_ocean_copy(struct OceanTex *ot);
-void BKE_free_oceantex(struct OceanTex *ot);
-struct OceanTex *BKE_add_oceantex(void);
-struct OceanTex *BKE_copy_oceantex(struct OceanTex *ot);
-
bool BKE_texture_dependsOnTime(const struct Tex *texture);
+bool BKE_texture_is_image_user(const struct Tex *tex);
-void BKE_texture_get_value(struct Scene *scene, struct Tex *texture, float *tex_co, struct TexResult *texres, bool use_color_management);
+void BKE_texture_get_value(
+ const struct Scene *scene, struct Tex *texture,
+ float *tex_co, struct TexResult *texres, bool use_color_management);
#ifdef __cplusplus
}
diff --git a/source/blender/blenkernel/BKE_tracking.h b/source/blender/blenkernel/BKE_tracking.h
index 8bc619c1b27..264bf2bd8fa 100644
--- a/source/blender/blenkernel/BKE_tracking.h
+++ b/source/blender/blenkernel/BKE_tracking.h
@@ -41,7 +41,6 @@ struct MovieTrackingMarker;
struct MovieTrackingPlaneTrack;
struct MovieTrackingPlaneMarker;
struct MovieTracking;
-struct MovieTrackingContext;
struct MovieTrackingObject;
struct MovieClipUser;
struct MovieDistortion;
@@ -91,7 +90,7 @@ struct MovieTrackingTrack *BKE_tracking_track_get_named(struct MovieTracking *tr
struct MovieTrackingObject *object,
const char *name);
struct MovieTrackingTrack *BKE_tracking_track_get_indexed(struct MovieTracking *tracking, int tracknr,
- struct ListBase **tracksbase_r);
+ struct ListBase **r_tracksbase);
struct MovieTrackingTrack *BKE_tracking_track_get_active(struct MovieTracking *tracking);
@@ -137,6 +136,21 @@ struct MovieTrackingPlaneTrack *BKE_tracking_plane_track_get_active(struct Movie
void BKE_tracking_plane_tracks_deselect_all(struct ListBase *plane_tracks_base);
+bool BKE_tracking_plane_track_has_point_track(struct MovieTrackingPlaneTrack *plane_track,
+ struct MovieTrackingTrack *track);
+bool BKE_tracking_plane_track_remove_point_track(struct MovieTrackingPlaneTrack *plane_track,
+ struct MovieTrackingTrack *track);
+
+void BKE_tracking_plane_tracks_remove_point_track(struct MovieTracking *tracking,
+ struct MovieTrackingTrack *track);
+
+void BKE_tracking_plane_track_replace_point_track(struct MovieTrackingPlaneTrack *plane_track,
+ struct MovieTrackingTrack *old_track,
+ struct MovieTrackingTrack *new_track);
+void BKE_tracking_plane_tracks_replace_point_track(struct MovieTracking *tracking,
+ struct MovieTrackingTrack *old_track,
+ struct MovieTrackingTrack *new_track);
+
/* **** Plane Marker **** */
struct MovieTrackingPlaneMarker *BKE_tracking_plane_marker_insert(struct MovieTrackingPlaneTrack *plane_track,
struct MovieTrackingPlaneMarker *plane_marker);
@@ -145,6 +159,9 @@ void BKE_tracking_plane_marker_delete(struct MovieTrackingPlaneTrack *plane_trac
struct MovieTrackingPlaneMarker *BKE_tracking_plane_marker_get(struct MovieTrackingPlaneTrack *plane_track, int framenr);
struct MovieTrackingPlaneMarker *BKE_tracking_plane_marker_get_exact(struct MovieTrackingPlaneTrack *plane_track, int framenr);
struct MovieTrackingPlaneMarker *BKE_tracking_plane_marker_ensure(struct MovieTrackingPlaneTrack *plane_track, int framenr);
+void BKE_tracking_plane_marker_get_subframe_corners(struct MovieTrackingPlaneTrack *plane_track,
+ float framenr,
+ float corners[4][2]);
/* **** Object **** */
struct MovieTrackingObject *BKE_tracking_object_add(struct MovieTracking *tracking, const char *name);
@@ -172,7 +189,7 @@ struct MovieReconstructedCamera *BKE_tracking_camera_get_reconstructed(struct Mo
int framenr);
void BKE_tracking_camera_get_reconstructed_interpolate(struct MovieTracking *tracking,
struct MovieTrackingObject *object,
- int framenr, float mat[4][4]);
+ float framenr, float mat[4][4]);
/* **** Distortion/Undistortion **** */
struct MovieDistortion *BKE_tracking_distortion_new(struct MovieTracking *tracking,
@@ -210,16 +227,18 @@ void BKE_tracking_disable_channels(struct ImBuf *ibuf, bool disable_red, bool di
bool disable_blue, bool grayscale);
/* **** 2D tracking **** */
-struct MovieTrackingContext *BKE_tracking_context_new(struct MovieClip *clip, struct MovieClipUser *user,
- const bool backwards, const bool sequence);
-void BKE_tracking_context_free(struct MovieTrackingContext *context);
-void BKE_tracking_context_sync(struct MovieTrackingContext *context);
-void BKE_tracking_context_sync_user(const struct MovieTrackingContext *context, struct MovieClipUser *user);
-bool BKE_tracking_context_step(struct MovieTrackingContext *context);
-void BKE_tracking_context_finish(struct MovieTrackingContext *context);
-
void BKE_tracking_refine_marker(struct MovieClip *clip, struct MovieTrackingTrack *track, struct MovieTrackingMarker *marker, bool backwards);
+/* *** 2D auto track *** */
+
+struct AutoTrackContext *BKE_autotrack_context_new(struct MovieClip *clip, struct MovieClipUser *user,
+ const bool backwards, const bool sequence);
+bool BKE_autotrack_context_step(struct AutoTrackContext *context);
+void BKE_autotrack_context_sync(struct AutoTrackContext *context);
+void BKE_autotrack_context_sync_user(struct AutoTrackContext *context, struct MovieClipUser *user);
+void BKE_autotrack_context_finish(struct AutoTrackContext *context);
+void BKE_autotrack_context_free(struct AutoTrackContext *context);
+
/* **** Plane tracking **** */
void BKE_tracking_track_plane_from_existing_motion(struct MovieTrackingPlaneTrack *plane_track, int start_frame);
diff --git a/source/blender/blenkernel/BKE_writeavi.h b/source/blender/blenkernel/BKE_writeavi.h
index 78875951ca4..ca295c51f5d 100644
--- a/source/blender/blenkernel/BKE_writeavi.h
+++ b/source/blender/blenkernel/BKE_writeavi.h
@@ -43,16 +43,20 @@ struct ReportList;
struct Scene;
typedef struct bMovieHandle {
- int (*start_movie)(struct Scene *scene, struct RenderData *rd, int rectx, int recty, struct ReportList *reports);
- int (*append_movie)(struct RenderData *rd, int start_frame, int frame, int *pixels,
- int rectx, int recty, struct ReportList *reports);
- void (*end_movie)(void);
- int (*get_next_frame)(struct RenderData *rd, struct ReportList *reports); /* optional */
- void (*get_movie_path)(char *string, struct RenderData *rd); /* optional */
+ int (*start_movie)(void *context_v, struct Scene *scene, struct RenderData *rd, int rectx, int recty,
+ struct ReportList *reports, bool preview, const char *suffix);
+ int (*append_movie)(void *context_v, struct RenderData *rd, int start_frame, int frame, int *pixels,
+ int rectx, int recty, const char *suffix, struct ReportList *reports);
+ void (*end_movie)(void *context_v);
+ int (*get_next_frame)(void *context_v, struct RenderData *rd, struct ReportList *reports); /* optional */
+ void (*get_movie_path)(char *string, struct RenderData *rd, bool preview, const char *suffix); /* optional */
+ void *(*context_create)(void);
+ void (*context_free)(void *context_v);
} bMovieHandle;
bMovieHandle *BKE_movie_handle_get(const char imtype);
-void BKE_movie_filepath_get(char *string, struct RenderData *rd);
+void BKE_movie_filepath_get(char *string, struct RenderData *rd, bool preview, const char *suffix);
+void BKE_context_create(bMovieHandle *mh);
#ifdef __cplusplus
}
diff --git a/source/blender/blenkernel/BKE_writeffmpeg.h b/source/blender/blenkernel/BKE_writeffmpeg.h
index 703e84b3798..a40c31022e3 100644
--- a/source/blender/blenkernel/BKE_writeffmpeg.h
+++ b/source/blender/blenkernel/BKE_writeffmpeg.h
@@ -64,16 +64,15 @@ enum {
FFMPEG_PRESET_XVID = 7,
};
-struct IDProperty;
struct RenderData;
struct ReportList;
struct Scene;
-int BKE_ffmpeg_start(struct Scene *scene, struct RenderData *rd, int rectx, int recty, struct ReportList *reports);
-void BKE_ffmpeg_end(void);
-int BKE_ffmpeg_append(struct RenderData *rd, int start_frame, int frame, int *pixels,
- int rectx, int recty, struct ReportList *reports);
-void BKE_ffmpeg_filepath_get(char *string, struct RenderData *rd);
+int BKE_ffmpeg_start(void *context_v, struct Scene *scene, struct RenderData *rd, int rectx, int recty, struct ReportList *reports, bool preview, const char *suffix);
+void BKE_ffmpeg_end(void *context_v);
+int BKE_ffmpeg_append(void *context_v, struct RenderData *rd, int start_frame, int frame, int *pixels,
+ int rectx, int recty, const char *suffix, struct ReportList *reports);
+void BKE_ffmpeg_filepath_get(char *string, struct RenderData *rd, bool preview, const char *suffix);
void BKE_ffmpeg_preset_set(struct RenderData *rd, int preset);
void BKE_ffmpeg_image_type_verify(struct RenderData *rd, struct ImageFormatData *imf);
@@ -83,6 +82,9 @@ bool BKE_ffmpeg_alpha_channel_is_supported(struct RenderData *rd);
int BKE_ffmpeg_property_add_string(struct RenderData *rd, const char *type, const char *str);
void BKE_ffmpeg_property_del(struct RenderData *rd, void *type, void *prop_);
+void *BKE_ffmpeg_context_create(void);
+void BKE_ffmpeg_context_free(void *context_v);
+
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/blenkernel/BKE_writeframeserver.h b/source/blender/blenkernel/BKE_writeframeserver.h
index bdce9abe8ad..0837e9bce79 100644
--- a/source/blender/blenkernel/BKE_writeframeserver.h
+++ b/source/blender/blenkernel/BKE_writeframeserver.h
@@ -40,11 +40,16 @@ struct RenderData;
struct ReportList;
struct Scene;
-int BKE_frameserver_start(struct Scene *scene, struct RenderData *rd, int rectx, int recty, struct ReportList *reports);
-void BKE_frameserver_end(void);
-int BKE_frameserver_append(struct RenderData *rd, int start_frame, int frame, int *pixels,
- int rectx, int recty, struct ReportList *reports);
-int BKE_frameserver_loop(struct RenderData *rd, struct ReportList *reports);
+int BKE_frameserver_start(
+ void *context_v, struct Scene *scene, struct RenderData *rd, int rectx, int recty,
+ struct ReportList *reports, bool preview, const char *suffix);
+void BKE_frameserver_end(void *context_v);
+int BKE_frameserver_append(
+ void *context_v, struct RenderData *rd, int start_frame, int frame, int *pixels,
+ int rectx, int recty, const char *suffix, struct ReportList *reports);
+int BKE_frameserver_loop(void *context_v, struct RenderData *rd, struct ReportList *reports);
+void *BKE_frameserver_context_create(void);
+void BKE_frameserver_context_free(void *context_v);
#ifdef __cplusplus
}
diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt
index fd201fed9e7..0865efb5ba7 100644
--- a/source/blender/blenkernel/CMakeLists.txt
+++ b/source/blender/blenkernel/CMakeLists.txt
@@ -28,6 +28,8 @@ set(INC
../blenfont
../blenlib
../blenloader
+ ../blentranslation
+ ../depsgraph
../gpu
../ikplugin
../imbuf
@@ -36,15 +38,18 @@ set(INC
../bmesh
../modifiers
../nodes
+ ../physics
../render/extern/include
+ ../../../intern/ghost
../../../intern/guardedalloc
+ ../../../intern/glew-mx
../../../intern/iksolver/extern
../../../intern/memutil
../../../intern/mikktspace
../../../intern/raskter
../../../intern/smoke/extern
- ../../../extern/libmv
../../../intern/atomic
+ ../../../extern/libmv
# XXX - BAD LEVEL CALL WM_api.h
../windowmanager
@@ -57,12 +62,18 @@ set(INC_SYS
set(SRC
intern/CCGSubSurf.c
+ intern/CCGSubSurf_legacy.c
+ intern/CCGSubSurf_opensubdiv.c
+ intern/CCGSubSurf_opensubdiv_converter.c
+ intern/CCGSubSurf_util.c
intern/DerivedMesh.c
intern/action.c
intern/addon.c
intern/anim.c
intern/anim_sys.c
+ intern/appdir.c
intern/armature.c
+ intern/armature_update.c
intern/autoexec.c
intern/blender.c
intern/bmfont.c
@@ -82,6 +93,7 @@ set(SRC
intern/curve.c
intern/customdata.c
intern/customdata_file.c
+ intern/data_transfer.c
intern/deform.c
intern/depsgraph.c
intern/displist.c
@@ -102,7 +114,6 @@ set(SRC
intern/idprop.c
intern/image.c
intern/image_gen.c
- intern/implicit.c
intern/ipo.c
intern/key.c
intern/lamp.c
@@ -115,9 +126,11 @@ set(SRC
intern/mask_rasterize.c
intern/material.c
intern/mball.c
+ intern/mball_tessellate.c
intern/mesh.c
intern/mesh_evaluate.c
intern/mesh_mapping.c
+ intern/mesh_remap.c
intern/mesh_validate.c
intern/modifier.c
intern/modifiers_bmesh.c
@@ -128,10 +141,14 @@ set(SRC
intern/object.c
intern/object_deform.c
intern/object_dupli.c
+ intern/object_update.c
intern/ocean.c
+ intern/outliner_treehash.c
intern/packedFile.c
intern/paint.c
intern/particle.c
+ intern/particle_child.c
+ intern/particle_distribute.c
intern/particle_system.c
intern/pbvh.c
intern/pbvh_bmesh.c
@@ -157,13 +174,13 @@ set(SRC
intern/text.c
intern/texture.c
intern/tracking.c
+ intern/tracking_auto.c
intern/tracking_detect.c
intern/tracking_plane_tracker.c
intern/tracking_region_tracker.c
intern/tracking_solver.c
intern/tracking_stabilize.c
intern/tracking_util.c
- intern/treehash.c
intern/unit.c
intern/world.c
intern/writeavi.c
@@ -174,6 +191,7 @@ set(SRC
BKE_addon.h
BKE_anim.h
BKE_animsys.h
+ BKE_appdir.h
BKE_armature.h
BKE_autoexec.h
BKE_blender.h
@@ -196,10 +214,13 @@ set(SRC
BKE_curve.h
BKE_customdata.h
BKE_customdata_file.h
+ BKE_data_transfer.h
BKE_deform.h
BKE_depsgraph.h
BKE_displist.h
BKE_dynamicpaint.h
+ BKE_editmesh.h
+ BKE_editmesh_bvh.h
BKE_effect.h
BKE_fcurve.h
BKE_fluidsim.h
@@ -223,8 +244,10 @@ set(SRC
BKE_mask.h
BKE_material.h
BKE_mball.h
+ BKE_mball_tessellate.h
BKE_mesh.h
BKE_mesh_mapping.h
+ BKE_mesh_remap.h
BKE_modifier.h
BKE_movieclip.h
BKE_multires.h
@@ -233,6 +256,7 @@ set(SRC
BKE_object.h
BKE_object_deform.h
BKE_ocean.h
+ BKE_outliner_treehash.h
BKE_packedFile.h
BKE_paint.h
BKE_particle.h
@@ -253,12 +277,9 @@ set(SRC
BKE_speaker.h
BKE_subsurf.h
BKE_suggestions.h
- BKE_editmesh.h
- BKE_editmesh_bvh.h
BKE_text.h
BKE_texture.h
BKE_tracking.h
- BKE_treehash.h
BKE_unit.h
BKE_utildefines.h
BKE_world.h
@@ -269,16 +290,33 @@ set(SRC
nla_private.h
tracking_private.h
intern/CCGSubSurf.h
+ intern/CCGSubSurf_inline.h
+ intern/CCGSubSurf_intern.h
intern/pbvh_intern.h
+ intern/data_transfer_intern.h
)
-add_definitions(-DGLEW_STATIC)
+if(WITH_BINRELOC)
+ list(APPEND INC_SYS
+ ${BINRELOC_INCLUDE_DIRS}
+ )
+ add_definitions(-DWITH_BINRELOC)
+endif()
-if(WITH_AUDASPACE)
+add_definitions(${GL_DEFINITIONS})
+
+if(WIN32)
list(APPEND INC
- ../../../intern/audaspace/intern
+ ../../../intern/utfconv
+ )
+endif()
+
+if(WITH_AUDASPACE)
+ add_definitions(${AUDASPACE_DEFINITIONS})
+
+ list(APPEND INC_SYS
+ ${AUDASPACE_C_INCLUDE_DIRS}
)
- add_definitions(-DWITH_AUDASPACE)
endif()
if(WITH_BULLET)
@@ -397,9 +435,16 @@ if(WITH_JACK)
endif()
if(WITH_LZO)
- list(APPEND INC_SYS
- ../../../extern/lzo/minilzo
- )
+ if(WITH_SYSTEM_LZO)
+ list(APPEND INC_SYS
+ ${LZO_INCLUDE_DIR}
+ )
+ add_definitions(-DWITH_SYSTEM_LZO)
+ else()
+ list(APPEND INC_SYS
+ ../../../extern/lzo/minilzo
+ )
+ endif()
add_definitions(-DWITH_LZO)
endif()
@@ -426,6 +471,20 @@ if(WITH_LIBMV)
add_definitions(-DWITH_LIBMV)
endif()
+if(WITH_LIBMV_WERROR)
+ if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_C_COMPILER_ID MATCHES "Clang")
+ set_source_files_properties(intern/tracking.c
+ intern/tracking_auto.c
+ intern/tracking_detect.c
+ intern/tracking_plane_tracker.c
+ intern/tracking_region_tracker.c
+ intern/tracking_solver.c
+ intern/tracking_stabilize.c
+ intern/tracking_util.c
+ PROPERTIES COMPILE_FLAGS -Werror)
+ endif()
+endif()
+
if(WITH_FFTW3)
list(APPEND INC_SYS
${FFTW3_INCLUDE_DIRS}
@@ -441,9 +500,31 @@ if(WITH_FREESTYLE)
add_definitions(-DWITH_FREESTYLE)
endif()
+if(WITH_OPENSUBDIV)
+ add_definitions(-DWITH_OPENSUBDIV)
+ list(APPEND INC_SYS
+ ../../../intern/opensubdiv
+ ${OPENSUBDIV_INCLUDE_DIRS}
+ )
+ if(WITH_SUBSURF_WERROR)
+ if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_C_COMPILER_ID MATCHES "Clang")
+ set_source_files_properties(intern/CCGSubSurf.c
+ intern/CCGSubSurf_legacy.c
+ intern/CCGSubSurf_opensubdiv.c
+ intern/CCGSubSurf_opensubdiv_converter.c
+ intern/CCGSubSurf_util.c
+ PROPERTIES COMPILE_FLAGS -Werror)
+ endif()
+ endif()
+endif()
+
## Warnings as errors, this is too strict!
#if(MSVC)
# set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /WX")
#endif()
+if(WITH_LEGACY_DEPSGRAPH)
+ add_definitions(-DWITH_LEGACY_DEPSGRAPH)
+endif()
+
blender_add_lib(bf_blenkernel "${SRC}" "${INC}" "${INC_SYS}")
diff --git a/source/blender/blenkernel/SConscript b/source/blender/blenkernel/SConscript
index 25f8422afed..edb2852d9ac 100644
--- a/source/blender/blenkernel/SConscript
+++ b/source/blender/blenkernel/SConscript
@@ -45,8 +45,9 @@ incs = [
'#/intern/raskter',
'#/intern/rigidbody',
'#/extern/bullet2/src',
- '#/extern/glew/include',
- '#/intern/audaspace/intern',
+ env['BF_GLEW_INC'],
+ '#/intern/ghost',
+ '#/intern/glew-mx',
'#/intern/elbeem/extern',
'#/intern/iksolver/extern',
'#/intern/smoke/extern',
@@ -55,7 +56,9 @@ incs = [
'../blenfont',
'../blenlib',
'../blenloader',
+ '../blentranslation',
'../bmesh',
+ '../depsgraph',
'../gpu',
'../ikplugin',
'../imbuf',
@@ -63,16 +66,15 @@ incs = [
'../makesrna',
'../modifiers',
'../nodes',
+ '../physics',
'../render/extern/include',
'../windowmanager',
- env['BF_OPENGL_INC'],
env['BF_ZLIB_INC'],
]
incs = ' '.join(incs)
-defs = [
- 'GLEW_STATIC',
- ]
+defs = []
+defs += env['BF_GL_DEFINITIONS']
if env['WITH_BF_SMOKE']:
defs.append('WITH_SMOKE')
@@ -120,6 +122,10 @@ if env['WITH_BF_CINEON']:
if env['WITH_BF_HDR']:
defs.append('WITH_HDR')
+if env['WITH_BF_AUDASPACE']:
+ defs += env['BF_AUDASPACE_DEF']
+ incs += ' ' + env['BF_AUDASPACE_C_INC']
+
if env['WITH_BF_JACK']:
defs.append('WITH_JACK')
@@ -167,9 +173,21 @@ if env['WITH_BF_INTERNATIONAL']:
if env['WITH_BF_FREESTYLE']:
defs.append('WITH_FREESTYLE')
+if env['WITH_BF_OPENSUBDIV']:
+ defs.append('WITH_OPENSUBDIV')
+ incs += ' #intern/opensubdiv'
+ incs += ' ' + env['BF_OPENSUBDIV_INC']
+
if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'linuxcross', 'win64-vc', 'win64-mingw'):
incs += ' ' + env['BF_PTHREADS_INC']
+ incs += ' ../../../intern/utfconv'
+
+if env['WITH_BF_BINRELOC']:
+ incs += ' #extern/binreloc/include'
+ defs.append('WITH_BINRELOC')
+if env['WITH_BF_LEGACY_DEPSGRAPH']:
+ defs.append('WITH_LEGACY_DEPSGRAPH')
if env['OURPLATFORM'] in ('win32-vc', 'win64-vc'):
env.BlenderLib ( libname = 'bf_blenkernel', sources = sources, includes = Split(incs), defines = defs, libtype=['core','player'], priority = [166,25]) #, cc_compileflags = env['CCFLAGS'].append('/WX') )
diff --git a/source/blender/blenkernel/intern/CCGSubSurf.c b/source/blender/blenkernel/intern/CCGSubSurf.c
index 623fb50b62c..95ddb9d5498 100644
--- a/source/blender/blenkernel/intern/CCGSubSurf.c
+++ b/source/blender/blenkernel/intern/CCGSubSurf.c
@@ -30,232 +30,22 @@
#include "BLI_sys_types.h" // for intptr_t support
#include "BLI_utildefines.h" /* for BLI_assert */
+#include "BLI_math.h"
#include "BKE_ccg.h"
#include "CCGSubSurf.h"
+#include "CCGSubSurf_intern.h"
#include "BKE_subsurf.h"
-/* used for normalize_v3 in BLI_math_vector
- * float.h's FLT_EPSILON causes trouble with subsurf normals - campbell */
-#define EPSILON (1.0e-35f)
+#ifdef WITH_OPENSUBDIV
+# include "opensubdiv_capi.h"
+# include "opensubdiv_converter_capi.h"
+#endif
-/* With this limit a single triangle becomes over 3 million faces */
-#define CCGSUBSURF_LEVEL_MAX 11
+#include "GL/glew.h"
/***/
-typedef unsigned char byte;
-
-/***/
-
-static int kHashSizes[] = {
- 1, 3, 5, 11, 17, 37, 67, 131, 257, 521, 1031, 2053, 4099, 8209,
- 16411, 32771, 65537, 131101, 262147, 524309, 1048583, 2097169,
- 4194319, 8388617, 16777259, 33554467, 67108879, 134217757, 268435459
-};
-
-typedef struct _EHEntry EHEntry;
-struct _EHEntry {
- EHEntry *next;
- void *key;
-};
-typedef struct _EHash {
- EHEntry **buckets;
- int numEntries, curSize, curSizeIdx;
-
- CCGAllocatorIFC allocatorIFC;
- CCGAllocatorHDL allocator;
-} EHash;
-
-#define EHASH_alloc(eh, nb) ((eh)->allocatorIFC.alloc((eh)->allocator, nb))
-#define EHASH_free(eh, ptr) ((eh)->allocatorIFC.free((eh)->allocator, ptr))
-
-#define EHASH_hash(eh, item) (((uintptr_t) (item)) % ((unsigned int) (eh)->curSize))
-
-static void ccgSubSurf__sync(CCGSubSurf *ss);
-static int _edge_isBoundary(const CCGEdge *e);
-
-static EHash *_ehash_new(int estimatedNumEntries, CCGAllocatorIFC *allocatorIFC, CCGAllocatorHDL allocator)
-{
- EHash *eh = allocatorIFC->alloc(allocator, sizeof(*eh));
- eh->allocatorIFC = *allocatorIFC;
- eh->allocator = allocator;
- eh->numEntries = 0;
- eh->curSizeIdx = 0;
- while (kHashSizes[eh->curSizeIdx] < estimatedNumEntries)
- eh->curSizeIdx++;
- eh->curSize = kHashSizes[eh->curSizeIdx];
- eh->buckets = EHASH_alloc(eh, eh->curSize * sizeof(*eh->buckets));
- memset(eh->buckets, 0, eh->curSize * sizeof(*eh->buckets));
-
- return eh;
-}
-typedef void (*EHEntryFreeFP)(EHEntry *, void *);
-static void _ehash_free(EHash *eh, EHEntryFreeFP freeEntry, void *userData)
-{
- int numBuckets = eh->curSize;
-
- while (numBuckets--) {
- EHEntry *entry = eh->buckets[numBuckets];
-
- while (entry) {
- EHEntry *next = entry->next;
-
- freeEntry(entry, userData);
-
- entry = next;
- }
- }
-
- EHASH_free(eh, eh->buckets);
- EHASH_free(eh, eh);
-}
-
-static void _ehash_insert(EHash *eh, EHEntry *entry)
-{
- int numBuckets = eh->curSize;
- int hash = EHASH_hash(eh, entry->key);
- entry->next = eh->buckets[hash];
- eh->buckets[hash] = entry;
- eh->numEntries++;
-
- if (UNLIKELY(eh->numEntries > (numBuckets * 3))) {
- EHEntry **oldBuckets = eh->buckets;
- eh->curSize = kHashSizes[++eh->curSizeIdx];
-
- eh->buckets = EHASH_alloc(eh, eh->curSize * sizeof(*eh->buckets));
- memset(eh->buckets, 0, eh->curSize * sizeof(*eh->buckets));
-
- while (numBuckets--) {
- for (entry = oldBuckets[numBuckets]; entry; ) {
- EHEntry *next = entry->next;
-
- hash = EHASH_hash(eh, entry->key);
- entry->next = eh->buckets[hash];
- eh->buckets[hash] = entry;
-
- entry = next;
- }
- }
-
- EHASH_free(eh, oldBuckets);
- }
-}
-
-static void *_ehash_lookupWithPrev(EHash *eh, void *key, void ***prevp_r)
-{
- int hash = EHASH_hash(eh, key);
- void **prevp = (void **) &eh->buckets[hash];
- EHEntry *entry;
-
- for (; (entry = *prevp); prevp = (void **) &entry->next) {
- if (entry->key == key) {
- *prevp_r = (void **) prevp;
- return entry;
- }
- }
-
- return NULL;
-}
-
-static void *_ehash_lookup(EHash *eh, void *key)
-{
- int hash = EHASH_hash(eh, key);
- EHEntry *entry;
-
- for (entry = eh->buckets[hash]; entry; entry = entry->next)
- if (entry->key == key)
- break;
-
- return entry;
-}
-
-/**/
-
-typedef struct _EHashIterator {
- EHash *eh;
- int curBucket;
- EHEntry *curEntry;
-} EHashIterator;
-
-static EHashIterator *_ehashIterator_new(EHash *eh)
-{
- EHashIterator *ehi = EHASH_alloc(eh, sizeof(*ehi));
- ehi->eh = eh;
- ehi->curEntry = NULL;
- ehi->curBucket = -1;
- while (!ehi->curEntry) {
- ehi->curBucket++;
- if (ehi->curBucket == ehi->eh->curSize)
- break;
- ehi->curEntry = ehi->eh->buckets[ehi->curBucket];
- }
- return ehi;
-}
-static void _ehashIterator_free(EHashIterator *ehi)
-{
- EHASH_free(ehi->eh, ehi);
-}
-
-static void *_ehashIterator_getCurrent(EHashIterator *ehi)
-{
- return ehi->curEntry;
-}
-
-static void _ehashIterator_next(EHashIterator *ehi)
-{
- if (ehi->curEntry) {
- ehi->curEntry = ehi->curEntry->next;
- while (!ehi->curEntry) {
- ehi->curBucket++;
- if (ehi->curBucket == ehi->eh->curSize)
- break;
- ehi->curEntry = ehi->eh->buckets[ehi->curBucket];
- }
- }
-}
-static int _ehashIterator_isStopped(EHashIterator *ehi)
-{
- return !ehi->curEntry;
-}
-
-/***/
-
-static void *_stdAllocator_alloc(CCGAllocatorHDL UNUSED(a), int numBytes)
-{
- return malloc(numBytes);
-}
-static void *_stdAllocator_realloc(CCGAllocatorHDL UNUSED(a), void *ptr, int newSize, int UNUSED(oldSize))
-{
- return realloc(ptr, newSize);
-}
-static void _stdAllocator_free(CCGAllocatorHDL UNUSED(a), void *ptr)
-{
- free(ptr);
-}
-
-static CCGAllocatorIFC *_getStandardAllocatorIFC(void)
-{
- static CCGAllocatorIFC ifc;
-
- ifc.alloc = _stdAllocator_alloc;
- ifc.realloc = _stdAllocator_realloc;
- ifc.free = _stdAllocator_free;
- ifc.release = NULL;
-
- return &ifc;
-}
-
-/***/
-
-BLI_INLINE int ccg_gridsize(int level)
-{
- BLI_assert(level > 0);
- BLI_assert(level <= CCGSUBSURF_LEVEL_MAX + 1);
-
- return (1 << (level - 1)) + 1;
-}
-
int BKE_ccg_gridsize(int level)
{
return ccg_gridsize(level);
@@ -269,240 +59,6 @@ int BKE_ccg_factor(int low_level, int high_level)
return 1 << (high_level - low_level);
}
-BLI_INLINE int ccg_edgesize(int level)
-{
- BLI_assert(level > 0);
- BLI_assert(level <= CCGSUBSURF_LEVEL_MAX + 1);
-
- return 1 + (1 << level);
-}
-
-BLI_INLINE int ccg_spacing(int high_level, int low_level)
-{
- BLI_assert(high_level > 0 && low_level > 0);
- BLI_assert(high_level >= low_level);
- BLI_assert((high_level - low_level) <= CCGSUBSURF_LEVEL_MAX);
-
- return 1 << (high_level - low_level);
-}
-
-BLI_INLINE int ccg_edgebase(int level)
-{
- BLI_assert(level > 0);
- BLI_assert(level <= CCGSUBSURF_LEVEL_MAX + 1);
-
- return level + (1 << level) - 1;
-}
-
-/***/
-
-#define NormZero(av) { float *_a = (float *) av; _a[0] = _a[1] = _a[2] = 0.0f; } (void)0
-#define NormCopy(av, bv) { float *_a = (float *) av, *_b = (float *) bv; _a[0] = _b[0]; _a[1] = _b[1]; _a[2] = _b[2]; } (void)0
-#define NormAdd(av, bv) { float *_a = (float *) av, *_b = (float *) bv; _a[0] += _b[0]; _a[1] += _b[1]; _a[2] += _b[2]; } (void)0
-
-BLI_INLINE void Normalize(float no[3])
-{
- const float length = sqrtf(no[0] * no[0] + no[1] * no[1] + no[2] * no[2]);
-
- if (length > EPSILON) {
- const float length_inv = 1.0f / length;
-
- no[0] *= length_inv;
- no[1] *= length_inv;
- no[2] *= length_inv;
- }
- else {
- NormZero(no);
- }
-}
-
-/***/
-
-enum {
- Vert_eEffected = (1 << 0),
- Vert_eChanged = (1 << 1),
- Vert_eSeam = (1 << 2)
-} /*VertFlags*/;
-enum {
- Edge_eEffected = (1 << 0)
-} /*CCGEdgeFlags*/;
-enum {
- Face_eEffected = (1 << 0)
-} /*FaceFlags*/;
-
-struct CCGVert {
- CCGVert *next; /* EHData.next */
- CCGVertHDL vHDL; /* EHData.key */
-
- short numEdges, numFaces, flags, pad;
-
- CCGEdge **edges;
- CCGFace **faces;
-// byte *levelData;
-// byte *userData;
-};
-
-BLI_INLINE byte *VERT_getLevelData(CCGVert *v)
-{
- return (byte *)(&(v)[1]);
-}
-
-struct CCGEdge {
- CCGEdge *next; /* EHData.next */
- CCGEdgeHDL eHDL; /* EHData.key */
-
- short numFaces, flags;
- float crease;
-
- CCGVert *v0, *v1;
- CCGFace **faces;
-
-// byte *levelData;
-// byte *userData;
-};
-
-BLI_INLINE byte *EDGE_getLevelData(CCGEdge *e)
-{
- return (byte *)(&(e)[1]);
-}
-
-struct CCGFace {
- CCGFace *next; /* EHData.next */
- CCGFaceHDL fHDL; /* EHData.key */
-
- short numVerts, flags, pad1, pad2;
-
-// CCGVert **verts;
-// CCGEdge **edges;
-// byte *centerData;
-// byte **gridData;
-// byte *userData;
-};
-
-BLI_INLINE CCGVert **FACE_getVerts(CCGFace *f)
-{
- return (CCGVert **)(&f[1]);
-}
-
-BLI_INLINE CCGEdge **FACE_getEdges(CCGFace *f)
-{
- return (CCGEdge **)(&(FACE_getVerts(f)[f->numVerts]));
-}
-
-BLI_INLINE byte *FACE_getCenterData(CCGFace *f)
-{
- return (byte *)(&(FACE_getEdges(f)[(f)->numVerts]));
-}
-
-typedef enum {
- eSyncState_None = 0,
- eSyncState_Vert,
- eSyncState_Edge,
- eSyncState_Face,
- eSyncState_Partial
-} SyncState;
-
-struct CCGSubSurf {
- EHash *vMap; /* map of CCGVertHDL -> Vert */
- EHash *eMap; /* map of CCGEdgeHDL -> Edge */
- EHash *fMap; /* map of CCGFaceHDL -> Face */
-
- CCGMeshIFC meshIFC;
-
- CCGAllocatorIFC allocatorIFC;
- CCGAllocatorHDL allocator;
-
- int subdivLevels;
- int numGrids;
- int allowEdgeCreation;
- float defaultCreaseValue;
- void *defaultEdgeUserData;
-
- void *q, *r;
-
- /* data for calc vert normals */
- int calcVertNormals;
- int normalDataOffset;
-
- /* data for paint masks */
- int allocMask;
- int maskDataOffset;
-
- /* data for age'ing (to debug sync) */
- int currentAge;
- int useAgeCounts;
- int vertUserAgeOffset;
- int edgeUserAgeOffset;
- int faceUserAgeOffset;
-
- /* data used during syncing */
- SyncState syncState;
-
- EHash *oldVMap, *oldEMap, *oldFMap;
- int lenTempArrays;
- CCGVert **tempVerts;
- CCGEdge **tempEdges;
-};
-
-#define CCGSUBSURF_alloc(ss, nb) ((ss)->allocatorIFC.alloc((ss)->allocator, nb))
-#define CCGSUBSURF_realloc(ss, ptr, nb, ob) ((ss)->allocatorIFC.realloc((ss)->allocator, ptr, nb, ob))
-#define CCGSUBSURF_free(ss, ptr) ((ss)->allocatorIFC.free((ss)->allocator, ptr))
-
-/***/
-
-static int VertDataEqual(const float a[], const float b[], const CCGSubSurf *ss)
-{
- int i;
- for (i = 0; i < ss->meshIFC.numLayers; i++) {
- if (a[i] != b[i])
- return 0;
- }
- return 1;
-}
-
-static void VertDataZero(float v[], const CCGSubSurf *ss)
-{
- memset(v, 0, sizeof(float) * ss->meshIFC.numLayers);
-}
-
-static void VertDataCopy(float dst[], const float src[], const CCGSubSurf *ss)
-{
- int i;
- for (i = 0; i < ss->meshIFC.numLayers; i++)
- dst[i] = src[i];
-}
-
-static void VertDataAdd(float a[], const float b[], const CCGSubSurf *ss)
-{
- int i;
- for (i = 0; i < ss->meshIFC.numLayers; i++)
- a[i] += b[i];
-}
-
-static void VertDataSub(float a[], const float b[], const CCGSubSurf *ss)
-{
- int i;
- for (i = 0; i < ss->meshIFC.numLayers; i++)
- a[i] -= b[i];
-}
-
-static void VertDataMulN(float v[], float f, const CCGSubSurf *ss)
-{
- int i;
- for (i = 0; i < ss->meshIFC.numLayers; i++)
- v[i] *= f;
-}
-
-static void VertDataAvg4(float v[],
- const float a[], const float b[],
- const float c[], const float d[],
- const CCGSubSurf *ss)
-{
- int i;
- for (i = 0; i < ss->meshIFC.numLayers; i++)
- v[i] = (a[i] + b[i] + c[i] + d[i]) * 0.25f;
-}
-
/***/
static CCGVert *_vert_new(CCGVertHDL vHDL, CCGSubSurf *ss)
@@ -569,36 +125,19 @@ static CCGEdge *_vert_findEdgeTo(const CCGVert *v, const CCGVert *vQ)
}
return NULL;
}
-static int _vert_isBoundary(const CCGVert *v)
+static void _vert_free(CCGVert *v, CCGSubSurf *ss)
{
- int i;
- for (i = 0; i < v->numEdges; i++)
- if (_edge_isBoundary(v->edges[i]))
- return 1;
- return 0;
-}
+ if (v->edges) {
+ CCGSUBSURF_free(ss, v->edges);
+ }
-static void *_vert_getCo(CCGVert *v, int lvl, int dataSize)
-{
- return &VERT_getLevelData(v)[lvl * dataSize];
-}
-static float *_vert_getNo(CCGVert *v, int lvl, int dataSize, int normalDataOffset)
-{
- return (float *) &VERT_getLevelData(v)[lvl * dataSize + normalDataOffset];
-}
+ if (v->faces) {
+ CCGSUBSURF_free(ss, v->faces);
+ }
-static void _vert_free(CCGVert *v, CCGSubSurf *ss)
-{
- CCGSUBSURF_free(ss, v->edges);
- CCGSUBSURF_free(ss, v->faces);
CCGSUBSURF_free(ss, v);
}
-static int VERT_seam(const CCGVert *v)
-{
- return ((v->flags & Vert_eSeam) != 0);
-}
-
/***/
static CCGEdge *_edge_new(CCGEdgeHDL eHDL, CCGVert *v0, CCGVert *v1, float crease, CCGSubSurf *ss)
@@ -641,31 +180,6 @@ static void _edge_addFace(CCGEdge *e, CCGFace *f, CCGSubSurf *ss)
e->faces = CCGSUBSURF_realloc(ss, e->faces, (e->numFaces + 1) * sizeof(*e->faces), e->numFaces * sizeof(*e->faces));
e->faces[e->numFaces++] = f;
}
-static int _edge_isBoundary(const CCGEdge *e)
-{
- return e->numFaces < 2;
-}
-
-static CCGVert *_edge_getOtherVert(CCGEdge *e, CCGVert *vQ)
-{
- if (vQ == e->v0) {
- return e->v1;
- }
- else {
- return e->v0;
- }
-}
-
-static void *_edge_getCo(CCGEdge *e, int lvl, int x, int dataSize)
-{
- int levelBase = ccg_edgebase(lvl);
- return &EDGE_getLevelData(e)[dataSize * (levelBase + x)];
-}
-static float *_edge_getNo(CCGEdge *e, int lvl, int x, int dataSize, int normalDataOffset)
-{
- int levelBase = ccg_edgebase(lvl);
- return (float *) &EDGE_getLevelData(e)[dataSize * (levelBase + x) + normalDataOffset];
-}
static void *_edge_getCoVert(CCGEdge *e, CCGVert *v, int lvl, int x, int dataSize)
{
int levelBase = ccg_edgebase(lvl);
@@ -679,7 +193,10 @@ static void *_edge_getCoVert(CCGEdge *e, CCGVert *v, int lvl, int x, int dataSiz
static void _edge_free(CCGEdge *e, CCGSubSurf *ss)
{
- CCGSUBSURF_free(ss, e->faces);
+ if (e->faces) {
+ CCGSUBSURF_free(ss, e->faces);
+ }
+
CCGSUBSURF_free(ss, e);
}
static void _edge_unlinkMarkAndFree(CCGEdge *e, CCGSubSurf *ss)
@@ -691,18 +208,6 @@ static void _edge_unlinkMarkAndFree(CCGEdge *e, CCGSubSurf *ss)
_edge_free(e, ss);
}
-static float EDGE_getSharpness(CCGEdge *e, int lvl)
-{
- if (!lvl)
- return e->crease;
- else if (!e->crease)
- return 0.0f;
- else if (e->crease - lvl < 0.0f)
- return 0.0f;
- else
- return e->crease - lvl;
-}
-
static CCGFace *_face_new(CCGFaceHDL fHDL, CCGVert **verts, CCGEdge **edges, int numVerts, CCGSubSurf *ss)
{
int maxGridSize = ccg_gridsize(ss->subdivLevels);
@@ -734,102 +239,6 @@ static CCGFace *_face_new(CCGFaceHDL fHDL, CCGVert **verts, CCGEdge **edges, int
return f;
}
-
-BLI_INLINE void *_face_getIECo(CCGFace *f, int lvl, int S, int x, int levels, int dataSize)
-{
- int maxGridSize = ccg_gridsize(levels);
- int spacing = ccg_spacing(levels, lvl);
- byte *gridBase = FACE_getCenterData(f) + dataSize * (1 + S * (maxGridSize + maxGridSize * maxGridSize));
- return &gridBase[dataSize * x * spacing];
-}
-BLI_INLINE void *_face_getIENo(CCGFace *f, int lvl, int S, int x, int levels, int dataSize, int normalDataOffset)
-{
- int maxGridSize = ccg_gridsize(levels);
- int spacing = ccg_spacing(levels, lvl);
- byte *gridBase = FACE_getCenterData(f) + dataSize * (1 + S * (maxGridSize + maxGridSize * maxGridSize));
- return &gridBase[dataSize * x * spacing + normalDataOffset];
-}
-BLI_INLINE void *_face_getIFCo(CCGFace *f, int lvl, int S, int x, int y, int levels, int dataSize)
-{
- int maxGridSize = ccg_gridsize(levels);
- int spacing = ccg_spacing(levels, lvl);
- byte *gridBase = FACE_getCenterData(f) + dataSize * (1 + S * (maxGridSize + maxGridSize * maxGridSize));
- return &gridBase[dataSize * (maxGridSize + (y * maxGridSize + x) * spacing)];
-}
-BLI_INLINE float *_face_getIFNo(CCGFace *f, int lvl, int S, int x, int y, int levels, int dataSize, int normalDataOffset)
-{
- int maxGridSize = ccg_gridsize(levels);
- int spacing = ccg_spacing(levels, lvl);
- byte *gridBase = FACE_getCenterData(f) + dataSize * (1 + S * (maxGridSize + maxGridSize * maxGridSize));
- return (float *) &gridBase[dataSize * (maxGridSize + (y * maxGridSize + x) * spacing) + normalDataOffset];
-}
-BLI_INLINE int _face_getVertIndex(CCGFace *f, CCGVert *v)
-{
- int i;
- for (i = 0; i < f->numVerts; i++)
- if (FACE_getVerts(f)[i] == v)
- return i;
- return -1;
-}
-BLI_INLINE int _face_getEdgeIndex(CCGFace *f, CCGEdge *e)
-{
- int i;
- for (i = 0; i < f->numVerts; i++)
- if (FACE_getEdges(f)[i] == e)
- return i;
- return -1;
-}
-BLI_INLINE void *_face_getIFCoEdge(CCGFace *f, CCGEdge *e, int f_ed_idx, int lvl, int eX, int eY, int levels, int dataSize)
-{
- int maxGridSize = ccg_gridsize(levels);
- int spacing = ccg_spacing(levels, lvl);
- int x, y, cx, cy;
-
- BLI_assert(f_ed_idx == _face_getEdgeIndex(f, e));
-
- eX = eX * spacing;
- eY = eY * spacing;
- if (e->v0 != FACE_getVerts(f)[f_ed_idx]) {
- eX = (maxGridSize * 2 - 1) - 1 - eX;
- }
- y = maxGridSize - 1 - eX;
- x = maxGridSize - 1 - eY;
- if (x < 0) {
- f_ed_idx = (f_ed_idx + f->numVerts - 1) % f->numVerts;
- cx = y;
- cy = -x;
- }
- else if (y < 0) {
- f_ed_idx = (f_ed_idx + 1) % f->numVerts;
- cx = -y;
- cy = x;
- }
- else {
- cx = x;
- cy = y;
- }
- return _face_getIFCo(f, levels, f_ed_idx, cx, cy, levels, dataSize);
-}
-static float *_face_getIFNoEdge(CCGFace *f, CCGEdge *e, int f_ed_idx, int lvl, int eX, int eY, int levels, int dataSize, int normalDataOffset)
-{
- return (float *) ((byte *) _face_getIFCoEdge(f, e, f_ed_idx, lvl, eX, eY, levels, dataSize) + normalDataOffset);
-}
-static void _face_calcIFNo(CCGFace *f, int lvl, int S, int x, int y, float no[3], int levels, int dataSize)
-{
- float *a = _face_getIFCo(f, lvl, S, x + 0, y + 0, levels, dataSize);
- float *b = _face_getIFCo(f, lvl, S, x + 1, y + 0, levels, dataSize);
- float *c = _face_getIFCo(f, lvl, S, x + 1, y + 1, levels, dataSize);
- float *d = _face_getIFCo(f, lvl, S, x + 0, y + 1, levels, dataSize);
- float a_cX = c[0] - a[0], a_cY = c[1] - a[1], a_cZ = c[2] - a[2];
- float b_dX = d[0] - b[0], b_dY = d[1] - b[1], b_dZ = d[2] - b[2];
-
- no[0] = b_dY * a_cZ - b_dZ * a_cY;
- no[1] = b_dZ * a_cX - b_dX * a_cZ;
- no[2] = b_dX * a_cY - b_dY * a_cX;
-
- Normalize(no);
-}
-
static void _face_free(CCGFace *f, CCGSubSurf *ss)
{
CCGSUBSURF_free(ss, f);
@@ -850,7 +259,7 @@ static void _face_unlinkMarkAndFree(CCGFace *f, CCGSubSurf *ss)
CCGSubSurf *ccgSubSurf_new(CCGMeshIFC *ifc, int subdivLevels, CCGAllocatorIFC *allocatorIFC, CCGAllocatorHDL allocator)
{
if (!allocatorIFC) {
- allocatorIFC = _getStandardAllocatorIFC();
+ allocatorIFC = ccg_getStandardAllocatorIFC();
allocator = NULL;
}
@@ -863,9 +272,9 @@ CCGSubSurf *ccgSubSurf_new(CCGMeshIFC *ifc, int subdivLevels, CCGAllocatorIFC *a
ss->allocatorIFC = *allocatorIFC;
ss->allocator = allocator;
- ss->vMap = _ehash_new(0, &ss->allocatorIFC, ss->allocator);
- ss->eMap = _ehash_new(0, &ss->allocatorIFC, ss->allocator);
- ss->fMap = _ehash_new(0, &ss->allocatorIFC, ss->allocator);
+ ss->vMap = ccg_ehash_new(0, &ss->allocatorIFC, ss->allocator);
+ ss->eMap = ccg_ehash_new(0, &ss->allocatorIFC, ss->allocator);
+ ss->fMap = ccg_ehash_new(0, &ss->allocatorIFC, ss->allocator);
ss->meshIFC = *ifc;
@@ -895,6 +304,23 @@ CCGSubSurf *ccgSubSurf_new(CCGMeshIFC *ifc, int subdivLevels, CCGAllocatorIFC *a
ss->tempVerts = NULL;
ss->tempEdges = NULL;
+#ifdef WITH_OPENSUBDIV
+ ss->osd_evaluator = NULL;
+ ss->osd_mesh = NULL;
+ ss->osd_topology_refiner = NULL;
+ ss->osd_mesh_invalid = false;
+ ss->osd_coarse_coords_invalid = false;
+ ss->osd_vao = 0;
+ ss->skip_grids = false;
+ ss->osd_compute = 0;
+ ss->osd_uvs_invalid = true;
+ ss->osd_subsurf_uv = 0;
+ ss->osd_uv_index = -1;
+ ss->osd_next_face_ptex_index = 0;
+ ss->osd_coarse_coords = NULL;
+ ss->osd_num_coarse_coords = 0;
+#endif
+
return ss;
}
}
@@ -903,11 +329,29 @@ void ccgSubSurf_free(CCGSubSurf *ss)
{
CCGAllocatorIFC allocatorIFC = ss->allocatorIFC;
CCGAllocatorHDL allocator = ss->allocator;
+#ifdef WITH_OPENSUBDIV
+ if (ss->osd_evaluator != NULL) {
+ openSubdiv_deleteEvaluatorDescr(ss->osd_evaluator);
+ }
+ if (ss->osd_mesh != NULL) {
+ /* TODO(sergey): Make sure free happens form the main thread! */
+ openSubdiv_deleteOsdGLMesh(ss->osd_mesh);
+ }
+ if (ss->osd_vao != 0) {
+ glDeleteVertexArrays(1, &ss->osd_vao);
+ }
+ if (ss->osd_coarse_coords != NULL) {
+ MEM_freeN(ss->osd_coarse_coords);
+ }
+ if (ss->osd_topology_refiner != NULL) {
+ openSubdiv_deleteTopologyRefinerDescr(ss->osd_topology_refiner);
+ }
+#endif
if (ss->syncState) {
- _ehash_free(ss->oldFMap, (EHEntryFreeFP) _face_free, ss);
- _ehash_free(ss->oldEMap, (EHEntryFreeFP) _edge_free, ss);
- _ehash_free(ss->oldVMap, (EHEntryFreeFP) _vert_free, ss);
+ ccg_ehash_free(ss->oldFMap, (EHEntryFreeFP) _face_free, ss);
+ ccg_ehash_free(ss->oldEMap, (EHEntryFreeFP) _edge_free, ss);
+ ccg_ehash_free(ss->oldVMap, (EHEntryFreeFP) _vert_free, ss);
MEM_freeN(ss->tempVerts);
MEM_freeN(ss->tempEdges);
@@ -917,9 +361,9 @@ void ccgSubSurf_free(CCGSubSurf *ss)
CCGSUBSURF_free(ss, ss->q);
if (ss->defaultEdgeUserData) CCGSUBSURF_free(ss, ss->defaultEdgeUserData);
- _ehash_free(ss->fMap, (EHEntryFreeFP) _face_free, ss);
- _ehash_free(ss->eMap, (EHEntryFreeFP) _edge_free, ss);
- _ehash_free(ss->vMap, (EHEntryFreeFP) _vert_free, ss);
+ ccg_ehash_free(ss->fMap, (EHEntryFreeFP) _face_free, ss);
+ ccg_ehash_free(ss->eMap, (EHEntryFreeFP) _edge_free, ss);
+ ccg_ehash_free(ss->vMap, (EHEntryFreeFP) _vert_free, ss);
CCGSUBSURF_free(ss, ss);
@@ -964,12 +408,12 @@ CCGError ccgSubSurf_setSubdivisionLevels(CCGSubSurf *ss, int subdivisionLevels)
else if (subdivisionLevels != ss->subdivLevels) {
ss->numGrids = 0;
ss->subdivLevels = subdivisionLevels;
- _ehash_free(ss->vMap, (EHEntryFreeFP) _vert_free, ss);
- _ehash_free(ss->eMap, (EHEntryFreeFP) _edge_free, ss);
- _ehash_free(ss->fMap, (EHEntryFreeFP) _face_free, ss);
- ss->vMap = _ehash_new(0, &ss->allocatorIFC, ss->allocator);
- ss->eMap = _ehash_new(0, &ss->allocatorIFC, ss->allocator);
- ss->fMap = _ehash_new(0, &ss->allocatorIFC, ss->allocator);
+ ccg_ehash_free(ss->vMap, (EHEntryFreeFP) _vert_free, ss);
+ ccg_ehash_free(ss->eMap, (EHEntryFreeFP) _edge_free, ss);
+ ccg_ehash_free(ss->fMap, (EHEntryFreeFP) _face_free, ss);
+ ss->vMap = ccg_ehash_new(0, &ss->allocatorIFC, ss->allocator);
+ ss->eMap = ccg_ehash_new(0, &ss->allocatorIFC, ss->allocator);
+ ss->fMap = ccg_ehash_new(0, &ss->allocatorIFC, ss->allocator);
}
return eCCGError_None;
@@ -1052,9 +496,9 @@ CCGError ccgSubSurf_initFullSync(CCGSubSurf *ss)
ss->oldEMap = ss->eMap;
ss->oldFMap = ss->fMap;
- ss->vMap = _ehash_new(0, &ss->allocatorIFC, ss->allocator);
- ss->eMap = _ehash_new(0, &ss->allocatorIFC, ss->allocator);
- ss->fMap = _ehash_new(0, &ss->allocatorIFC, ss->allocator);
+ ss->vMap = ccg_ehash_new(0, &ss->allocatorIFC, ss->allocator);
+ ss->eMap = ccg_ehash_new(0, &ss->allocatorIFC, ss->allocator);
+ ss->fMap = ccg_ehash_new(0, &ss->allocatorIFC, ss->allocator);
ss->numGrids = 0;
@@ -1063,6 +507,9 @@ CCGError ccgSubSurf_initFullSync(CCGSubSurf *ss)
ss->tempEdges = MEM_mallocN(sizeof(*ss->tempEdges) * ss->lenTempArrays, "CCGSubsurf tempEdges");
ss->syncState = eSyncState_Vert;
+#ifdef WITH_OPENSUBDIV
+ ss->osd_next_face_ptex_index = 0;
+#endif
return eCCGError_None;
}
@@ -1087,7 +534,7 @@ CCGError ccgSubSurf_syncVertDel(CCGSubSurf *ss, CCGVertHDL vHDL)
}
else {
void **prevp;
- CCGVert *v = _ehash_lookupWithPrev(ss->vMap, vHDL, &prevp);
+ CCGVert *v = ccg_ehash_lookupWithPrev(ss->vMap, vHDL, &prevp);
if (!v || v->numFaces || v->numEdges) {
return eCCGError_InvalidValue;
@@ -1108,7 +555,7 @@ CCGError ccgSubSurf_syncEdgeDel(CCGSubSurf *ss, CCGEdgeHDL eHDL)
}
else {
void **prevp;
- CCGEdge *e = _ehash_lookupWithPrev(ss->eMap, eHDL, &prevp);
+ CCGEdge *e = ccg_ehash_lookupWithPrev(ss->eMap, eHDL, &prevp);
if (!e || e->numFaces) {
return eCCGError_InvalidValue;
@@ -1129,7 +576,7 @@ CCGError ccgSubSurf_syncFaceDel(CCGSubSurf *ss, CCGFaceHDL fHDL)
}
else {
void **prevp;
- CCGFace *f = _ehash_lookupWithPrev(ss->fMap, fHDL, &prevp);
+ CCGFace *f = ccg_ehash_lookupWithPrev(ss->fMap, fHDL, &prevp);
if (!f) {
return eCCGError_InvalidValue;
@@ -1150,19 +597,19 @@ CCGError ccgSubSurf_syncVert(CCGSubSurf *ss, CCGVertHDL vHDL, const void *vertDa
short seamflag = (seam) ? Vert_eSeam : 0;
if (ss->syncState == eSyncState_Partial) {
- v = _ehash_lookupWithPrev(ss->vMap, vHDL, &prevp);
+ v = ccg_ehash_lookupWithPrev(ss->vMap, vHDL, &prevp);
if (!v) {
v = _vert_new(vHDL, ss);
- VertDataCopy(_vert_getCo(v, 0, ss->meshIFC.vertDataSize), vertData, ss);
- _ehash_insert(ss->vMap, (EHEntry *) v);
+ VertDataCopy(ccg_vert_getCo(v, 0, ss->meshIFC.vertDataSize), vertData, ss);
+ ccg_ehash_insert(ss->vMap, (EHEntry *) v);
v->flags = Vert_eEffected | seamflag;
}
- else if (!VertDataEqual(vertData, _vert_getCo(v, 0, ss->meshIFC.vertDataSize), ss) ||
+ else if (!VertDataEqual(vertData, ccg_vert_getCo(v, 0, ss->meshIFC.vertDataSize), ss) ||
((v->flags & Vert_eSeam) != seamflag))
{
int i, j;
- VertDataCopy(_vert_getCo(v, 0, ss->meshIFC.vertDataSize), vertData, ss);
+ VertDataCopy(ccg_vert_getCo(v, 0, ss->meshIFC.vertDataSize), vertData, ss);
v->flags = Vert_eEffected | seamflag;
for (i = 0; i < v->numEdges; i++) {
@@ -1183,26 +630,29 @@ CCGError ccgSubSurf_syncVert(CCGSubSurf *ss, CCGVertHDL vHDL, const void *vertDa
return eCCGError_InvalidSyncState;
}
- v = _ehash_lookupWithPrev(ss->oldVMap, vHDL, &prevp);
+ v = ccg_ehash_lookupWithPrev(ss->oldVMap, vHDL, &prevp);
if (!v) {
v = _vert_new(vHDL, ss);
- VertDataCopy(_vert_getCo(v, 0, ss->meshIFC.vertDataSize), vertData, ss);
- _ehash_insert(ss->vMap, (EHEntry *) v);
+ VertDataCopy(ccg_vert_getCo(v, 0, ss->meshIFC.vertDataSize), vertData, ss);
+ ccg_ehash_insert(ss->vMap, (EHEntry *) v);
v->flags = Vert_eEffected | seamflag;
}
- else if (!VertDataEqual(vertData, _vert_getCo(v, 0, ss->meshIFC.vertDataSize), ss) ||
+ else if (!VertDataEqual(vertData, ccg_vert_getCo(v, 0, ss->meshIFC.vertDataSize), ss) ||
((v->flags & Vert_eSeam) != seamflag))
{
*prevp = v->next;
- _ehash_insert(ss->vMap, (EHEntry *) v);
- VertDataCopy(_vert_getCo(v, 0, ss->meshIFC.vertDataSize), vertData, ss);
+ ccg_ehash_insert(ss->vMap, (EHEntry *) v);
+ VertDataCopy(ccg_vert_getCo(v, 0, ss->meshIFC.vertDataSize), vertData, ss);
v->flags = Vert_eEffected | Vert_eChanged | seamflag;
}
else {
*prevp = v->next;
- _ehash_insert(ss->vMap, (EHEntry *) v);
+ ccg_ehash_insert(ss->vMap, (EHEntry *) v);
v->flags = 0;
}
+#ifdef WITH_OPENSUBDIV
+ v->osd_index = ss->vMap->numEntries - 1;
+#endif
}
if (v_r) *v_r = v;
@@ -1215,10 +665,10 @@ CCGError ccgSubSurf_syncEdge(CCGSubSurf *ss, CCGEdgeHDL eHDL, CCGVertHDL e_vHDL0
CCGEdge *e = NULL, *eNew;
if (ss->syncState == eSyncState_Partial) {
- e = _ehash_lookupWithPrev(ss->eMap, eHDL, &prevp);
+ e = ccg_ehash_lookupWithPrev(ss->eMap, eHDL, &prevp);
if (!e || e->v0->vHDL != e_vHDL0 || e->v1->vHDL != e_vHDL1 || crease != e->crease) {
- CCGVert *v0 = _ehash_lookup(ss->vMap, e_vHDL0);
- CCGVert *v1 = _ehash_lookup(ss->vMap, e_vHDL1);
+ CCGVert *v0 = ccg_ehash_lookup(ss->vMap, e_vHDL0);
+ CCGVert *v1 = ccg_ehash_lookup(ss->vMap, e_vHDL1);
eNew = _edge_new(eHDL, v0, v1, crease, ss);
@@ -1229,7 +679,7 @@ CCGError ccgSubSurf_syncEdge(CCGSubSurf *ss, CCGEdgeHDL eHDL, CCGVertHDL e_vHDL0
_edge_unlinkMarkAndFree(e, ss);
}
else {
- _ehash_insert(ss->eMap, (EHEntry *) eNew);
+ ccg_ehash_insert(ss->eMap, (EHEntry *) eNew);
}
eNew->v0->flags |= Vert_eEffected;
@@ -1244,18 +694,18 @@ CCGError ccgSubSurf_syncEdge(CCGSubSurf *ss, CCGEdgeHDL eHDL, CCGVertHDL e_vHDL0
return eCCGError_InvalidSyncState;
}
- e = _ehash_lookupWithPrev(ss->oldEMap, eHDL, &prevp);
+ e = ccg_ehash_lookupWithPrev(ss->oldEMap, eHDL, &prevp);
if (!e || e->v0->vHDL != e_vHDL0 || e->v1->vHDL != e_vHDL1 || e->crease != crease) {
- CCGVert *v0 = _ehash_lookup(ss->vMap, e_vHDL0);
- CCGVert *v1 = _ehash_lookup(ss->vMap, e_vHDL1);
+ CCGVert *v0 = ccg_ehash_lookup(ss->vMap, e_vHDL0);
+ CCGVert *v1 = ccg_ehash_lookup(ss->vMap, e_vHDL1);
e = _edge_new(eHDL, v0, v1, crease, ss);
- _ehash_insert(ss->eMap, (EHEntry *) e);
+ ccg_ehash_insert(ss->eMap, (EHEntry *) e);
e->v0->flags |= Vert_eEffected;
e->v1->flags |= Vert_eEffected;
}
else {
*prevp = e->next;
- _ehash_insert(ss->eMap, (EHEntry *) e);
+ ccg_ehash_insert(ss->eMap, (EHEntry *) e);
e->flags = 0;
if ((e->v0->flags | e->v1->flags) & Vert_eChanged) {
e->v0->flags |= Vert_eEffected;
@@ -1281,10 +731,10 @@ CCGError ccgSubSurf_syncFace(CCGSubSurf *ss, CCGFaceHDL fHDL, int numVerts, CCGV
}
if (ss->syncState == eSyncState_Partial) {
- f = _ehash_lookupWithPrev(ss->fMap, fHDL, &prevp);
+ f = ccg_ehash_lookupWithPrev(ss->fMap, fHDL, &prevp);
for (k = 0; k < numVerts; k++) {
- ss->tempVerts[k] = _ehash_lookup(ss->vMap, vHDLs[k]);
+ ss->tempVerts[k] = ccg_ehash_lookup(ss->vMap, vHDLs[k]);
}
for (k = 0; k < numVerts; k++) {
ss->tempEdges[k] = _vert_findEdgeTo(ss->tempVerts[k], ss->tempVerts[(k + 1) % numVerts]);
@@ -1312,7 +762,7 @@ CCGError ccgSubSurf_syncFace(CCGSubSurf *ss, CCGFaceHDL fHDL, int numVerts, CCGV
}
else {
ss->numGrids += numVerts;
- _ehash_insert(ss->fMap, (EHEntry *) fNew);
+ ccg_ehash_insert(ss->fMap, (EHEntry *) fNew);
}
for (k = 0; k < numVerts; k++)
@@ -1327,10 +777,10 @@ CCGError ccgSubSurf_syncFace(CCGSubSurf *ss, CCGFaceHDL fHDL, int numVerts, CCGV
return eCCGError_InvalidSyncState;
}
- f = _ehash_lookupWithPrev(ss->oldFMap, fHDL, &prevp);
+ f = ccg_ehash_lookupWithPrev(ss->oldFMap, fHDL, &prevp);
for (k = 0; k < numVerts; k++) {
- ss->tempVerts[k] = _ehash_lookup(ss->vMap, vHDLs[k]);
+ ss->tempVerts[k] = ccg_ehash_lookup(ss->vMap, vHDLs[k]);
if (!ss->tempVerts[k])
return eCCGError_InvalidValue;
@@ -1341,7 +791,7 @@ CCGError ccgSubSurf_syncFace(CCGSubSurf *ss, CCGFaceHDL fHDL, int numVerts, CCGV
if (!ss->tempEdges[k]) {
if (ss->allowEdgeCreation) {
CCGEdge *e = ss->tempEdges[k] = _edge_new((CCGEdgeHDL) - 1, ss->tempVerts[k], ss->tempVerts[(k + 1) % numVerts], ss->defaultCreaseValue, ss);
- _ehash_insert(ss->eMap, (EHEntry *) e);
+ ccg_ehash_insert(ss->eMap, (EHEntry *) e);
e->v0->flags |= Vert_eEffected;
e->v1->flags |= Vert_eEffected;
if (ss->meshIFC.edgeUserSize) {
@@ -1365,7 +815,7 @@ CCGError ccgSubSurf_syncFace(CCGSubSurf *ss, CCGFaceHDL fHDL, int numVerts, CCGV
if (!f || topologyChanged) {
f = _face_new(fHDL, ss->tempVerts, ss->tempEdges, numVerts, ss);
- _ehash_insert(ss->fMap, (EHEntry *) f);
+ ccg_ehash_insert(ss->fMap, (EHEntry *) f);
ss->numGrids += numVerts;
for (k = 0; k < numVerts; k++)
@@ -1373,7 +823,7 @@ CCGError ccgSubSurf_syncFace(CCGSubSurf *ss, CCGFaceHDL fHDL, int numVerts, CCGV
}
else {
*prevp = f->next;
- _ehash_insert(ss->fMap, (EHEntry *) f);
+ ccg_ehash_insert(ss->fMap, (EHEntry *) f);
f->flags = 0;
ss->numGrids += f->numVerts;
@@ -1385,12 +835,34 @@ CCGError ccgSubSurf_syncFace(CCGSubSurf *ss, CCGFaceHDL fHDL, int numVerts, CCGV
}
}
}
+#ifdef WITH_OPENSUBDIV
+ f->osd_index = ss->osd_next_face_ptex_index;
+ if (numVerts == 4) {
+ ss->osd_next_face_ptex_index++;
+ }
+ else {
+ ss->osd_next_face_ptex_index += numVerts;
+ }
+#endif
}
if (f_r) *f_r = f;
return eCCGError_None;
}
+static void ccgSubSurf__sync(CCGSubSurf *ss)
+{
+#ifdef WITH_OPENSUBDIV
+ if (ss->skip_grids) {
+ ccgSubSurf__sync_opensubdiv(ss);
+ }
+ else
+#endif
+ {
+ ccgSubSurf__sync_legacy(ss);
+ }
+}
+
CCGError ccgSubSurf_processSync(CCGSubSurf *ss)
{
if (ss->syncState == eSyncState_Partial) {
@@ -1399,9 +871,9 @@ CCGError ccgSubSurf_processSync(CCGSubSurf *ss)
ccgSubSurf__sync(ss);
}
else if (ss->syncState) {
- _ehash_free(ss->oldFMap, (EHEntryFreeFP) _face_unlinkMarkAndFree, ss);
- _ehash_free(ss->oldEMap, (EHEntryFreeFP) _edge_unlinkMarkAndFree, ss);
- _ehash_free(ss->oldVMap, (EHEntryFreeFP) _vert_free, ss);
+ ccg_ehash_free(ss->oldFMap, (EHEntryFreeFP) _face_unlinkMarkAndFree, ss);
+ ccg_ehash_free(ss->oldEMap, (EHEntryFreeFP) _edge_unlinkMarkAndFree, ss);
+ ccg_ehash_free(ss->oldVMap, (EHEntryFreeFP) _vert_free, ss);
MEM_freeN(ss->tempEdges);
MEM_freeN(ss->tempVerts);
@@ -1422,1009 +894,7 @@ CCGError ccgSubSurf_processSync(CCGSubSurf *ss)
return eCCGError_None;
}
-#define VERT_getCo(v, lvl) _vert_getCo(v, lvl, vertDataSize)
-#define VERT_getNo(e, lvl) _vert_getNo(v, lvl, vertDataSize, normalDataOffset)
-#define EDGE_getCo(e, lvl, x) _edge_getCo(e, lvl, x, vertDataSize)
-#define EDGE_getNo(e, lvl, x) _edge_getNo(e, lvl, x, vertDataSize, normalDataOffset)
-#define FACE_getIFNo(f, lvl, S, x, y) _face_getIFNo(f, lvl, S, x, y, subdivLevels, vertDataSize, normalDataOffset)
-#define FACE_calcIFNo(f, lvl, S, x, y, no) _face_calcIFNo(f, lvl, S, x, y, no, subdivLevels, vertDataSize)
-#define FACE_getIENo(f, lvl, S, x) _face_getIENo(f, lvl, S, x, subdivLevels, vertDataSize, normalDataOffset)
-
-static void ccgSubSurf__calcVertNormals(CCGSubSurf *ss,
- CCGVert **effectedV, CCGEdge **effectedE, CCGFace **effectedF,
- int numEffectedV, int numEffectedE, int numEffectedF)
-{
- int i, ptrIdx;
- int subdivLevels = ss->subdivLevels;
- int lvl = ss->subdivLevels;
- int edgeSize = ccg_edgesize(lvl);
- int gridSize = ccg_gridsize(lvl);
- int normalDataOffset = ss->normalDataOffset;
- int vertDataSize = ss->meshIFC.vertDataSize;
-
-#pragma omp parallel for private(ptrIdx) if (numEffectedF * edgeSize * edgeSize * 4 >= CCG_OMP_LIMIT)
- for (ptrIdx = 0; ptrIdx < numEffectedF; ptrIdx++) {
- CCGFace *f = (CCGFace *) effectedF[ptrIdx];
- int S, x, y;
- float no[3];
-
- for (S = 0; S < f->numVerts; S++) {
- for (y = 0; y < gridSize - 1; y++) {
- for (x = 0; x < gridSize - 1; x++) {
- NormZero(FACE_getIFNo(f, lvl, S, x, y));
- }
- }
-
- if (FACE_getEdges(f)[(S - 1 + f->numVerts) % f->numVerts]->flags & Edge_eEffected) {
- for (x = 0; x < gridSize - 1; x++) {
- NormZero(FACE_getIFNo(f, lvl, S, x, gridSize - 1));
- }
- }
- if (FACE_getEdges(f)[S]->flags & Edge_eEffected) {
- for (y = 0; y < gridSize - 1; y++) {
- NormZero(FACE_getIFNo(f, lvl, S, gridSize - 1, y));
- }
- }
- if (FACE_getVerts(f)[S]->flags & Vert_eEffected) {
- NormZero(FACE_getIFNo(f, lvl, S, gridSize - 1, gridSize - 1));
- }
- }
-
- for (S = 0; S < f->numVerts; S++) {
- int yLimit = !(FACE_getEdges(f)[(S - 1 + f->numVerts) % f->numVerts]->flags & Edge_eEffected);
- int xLimit = !(FACE_getEdges(f)[S]->flags & Edge_eEffected);
- int yLimitNext = xLimit;
- int xLimitPrev = yLimit;
-
- for (y = 0; y < gridSize - 1; y++) {
- for (x = 0; x < gridSize - 1; x++) {
- int xPlusOk = (!xLimit || x < gridSize - 2);
- int yPlusOk = (!yLimit || y < gridSize - 2);
-
- FACE_calcIFNo(f, lvl, S, x, y, no);
-
- NormAdd(FACE_getIFNo(f, lvl, S, x + 0, y + 0), no);
- if (xPlusOk)
- NormAdd(FACE_getIFNo(f, lvl, S, x + 1, y + 0), no);
- if (yPlusOk)
- NormAdd(FACE_getIFNo(f, lvl, S, x + 0, y + 1), no);
- if (xPlusOk && yPlusOk) {
- if (x < gridSize - 2 || y < gridSize - 2 || FACE_getVerts(f)[S]->flags & Vert_eEffected) {
- NormAdd(FACE_getIFNo(f, lvl, S, x + 1, y + 1), no);
- }
- }
-
- if (x == 0 && y == 0) {
- int K;
-
- if (!yLimitNext || 1 < gridSize - 1)
- NormAdd(FACE_getIFNo(f, lvl, (S + 1) % f->numVerts, 0, 1), no);
- if (!xLimitPrev || 1 < gridSize - 1)
- NormAdd(FACE_getIFNo(f, lvl, (S - 1 + f->numVerts) % f->numVerts, 1, 0), no);
-
- for (K = 0; K < f->numVerts; K++) {
- if (K != S) {
- NormAdd(FACE_getIFNo(f, lvl, K, 0, 0), no);
- }
- }
- }
- else if (y == 0) {
- NormAdd(FACE_getIFNo(f, lvl, (S + 1) % f->numVerts, 0, x), no);
- if (!yLimitNext || x < gridSize - 2)
- NormAdd(FACE_getIFNo(f, lvl, (S + 1) % f->numVerts, 0, x + 1), no);
- }
- else if (x == 0) {
- NormAdd(FACE_getIFNo(f, lvl, (S - 1 + f->numVerts) % f->numVerts, y, 0), no);
- if (!xLimitPrev || y < gridSize - 2)
- NormAdd(FACE_getIFNo(f, lvl, (S - 1 + f->numVerts) % f->numVerts, y + 1, 0), no);
- }
- }
- }
- }
- }
- /* XXX can I reduce the number of normalisations here? */
- for (ptrIdx = 0; ptrIdx < numEffectedV; ptrIdx++) {
- CCGVert *v = (CCGVert *) effectedV[ptrIdx];
- float *no = VERT_getNo(v, lvl);
-
- NormZero(no);
-
- for (i = 0; i < v->numFaces; i++) {
- CCGFace *f = v->faces[i];
- NormAdd(no, FACE_getIFNo(f, lvl, _face_getVertIndex(f, v), gridSize - 1, gridSize - 1));
- }
-
- if (UNLIKELY(v->numFaces == 0)) {
- NormCopy(no, VERT_getCo(v, lvl));
- }
-
- Normalize(no);
-
- for (i = 0; i < v->numFaces; i++) {
- CCGFace *f = v->faces[i];
- NormCopy(FACE_getIFNo(f, lvl, _face_getVertIndex(f, v), gridSize - 1, gridSize - 1), no);
- }
- }
- for (ptrIdx = 0; ptrIdx < numEffectedE; ptrIdx++) {
- CCGEdge *e = (CCGEdge *) effectedE[ptrIdx];
-
- if (e->numFaces) {
- CCGFace *fLast = e->faces[e->numFaces - 1];
- int x;
-
- for (i = 0; i < e->numFaces - 1; i++) {
- CCGFace *f = e->faces[i];
- const int f_ed_idx = _face_getEdgeIndex(f, e);
- const int f_ed_idx_last = _face_getEdgeIndex(fLast, e);
-
- for (x = 1; x < edgeSize - 1; x++) {
- NormAdd(_face_getIFNoEdge(fLast, e, f_ed_idx_last, lvl, x, 0, subdivLevels, vertDataSize, normalDataOffset),
- _face_getIFNoEdge(f, e, f_ed_idx, lvl, x, 0, subdivLevels, vertDataSize, normalDataOffset));
- }
- }
-
- for (i = 0; i < e->numFaces - 1; i++) {
- CCGFace *f = e->faces[i];
- const int f_ed_idx = _face_getEdgeIndex(f, e);
- const int f_ed_idx_last = _face_getEdgeIndex(fLast, e);
-
- for (x = 1; x < edgeSize - 1; x++) {
- NormCopy(_face_getIFNoEdge(f, e, f_ed_idx, lvl, x, 0, subdivLevels, vertDataSize, normalDataOffset),
- _face_getIFNoEdge(fLast, e, f_ed_idx_last, lvl, x, 0, subdivLevels, vertDataSize, normalDataOffset));
- }
- }
- }
- }
-
-#pragma omp parallel for private(ptrIdx) if (numEffectedF * edgeSize * edgeSize * 4 >= CCG_OMP_LIMIT)
- for (ptrIdx = 0; ptrIdx < numEffectedF; ptrIdx++) {
- CCGFace *f = (CCGFace *) effectedF[ptrIdx];
- int S, x, y;
-
- for (S = 0; S < f->numVerts; S++) {
- NormCopy(FACE_getIFNo(f, lvl, (S + 1) % f->numVerts, 0, gridSize - 1),
- FACE_getIFNo(f, lvl, S, gridSize - 1, 0));
- }
-
- for (S = 0; S < f->numVerts; S++) {
- for (y = 0; y < gridSize; y++) {
- for (x = 0; x < gridSize; x++) {
- float *no = FACE_getIFNo(f, lvl, S, x, y);
- Normalize(no);
- }
- }
-
- VertDataCopy((float *)((byte *)FACE_getCenterData(f) + normalDataOffset),
- FACE_getIFNo(f, lvl, S, 0, 0), ss);
-
- for (x = 1; x < gridSize - 1; x++)
- NormCopy(FACE_getIENo(f, lvl, S, x),
- FACE_getIFNo(f, lvl, S, x, 0));
- }
- }
-
- for (ptrIdx = 0; ptrIdx < numEffectedE; ptrIdx++) {
- CCGEdge *e = (CCGEdge *) effectedE[ptrIdx];
-
- if (e->numFaces) {
- CCGFace *f = e->faces[0];
- int x;
- const int f_ed_idx = _face_getEdgeIndex(f, e);
-
- for (x = 0; x < edgeSize; x++)
- NormCopy(EDGE_getNo(e, lvl, x),
- _face_getIFNoEdge(f, e, f_ed_idx, lvl, x, 0, subdivLevels, vertDataSize, normalDataOffset));
- }
- else {
- /* set to zero here otherwise the normals are uninitialized memory
- * render: tests/animation/knight.blend with valgrind.
- * we could be more clever and interpolate vertex normals but these are
- * most likely not used so just zero out. */
- int x;
-
- for (x = 0; x < edgeSize; x++) {
- float *no = EDGE_getNo(e, lvl, x);
- NormCopy(no, EDGE_getCo(e, lvl, x));
- Normalize(no);
- }
- }
- }
-}
-#undef FACE_getIFNo
-
-#define FACE_getIECo(f, lvl, S, x) _face_getIECo(f, lvl, S, x, subdivLevels, vertDataSize)
-#define FACE_getIFCo(f, lvl, S, x, y) _face_getIFCo(f, lvl, S, x, y, subdivLevels, vertDataSize)
-
-static void ccgSubSurf__calcSubdivLevel(CCGSubSurf *ss,
- CCGVert **effectedV, CCGEdge **effectedE, CCGFace **effectedF,
- int numEffectedV, int numEffectedE, int numEffectedF, int curLvl)
-{
- int subdivLevels = ss->subdivLevels;
- int edgeSize = ccg_edgesize(curLvl);
- int gridSize = ccg_gridsize(curLvl);
- int nextLvl = curLvl + 1;
- int ptrIdx, cornerIdx, i;
- int vertDataSize = ss->meshIFC.vertDataSize;
- float *q = ss->q, *r = ss->r;
-
-#pragma omp parallel for private(ptrIdx) if (numEffectedF * edgeSize * edgeSize * 4 >= CCG_OMP_LIMIT)
- for (ptrIdx = 0; ptrIdx < numEffectedF; ptrIdx++) {
- CCGFace *f = (CCGFace *) effectedF[ptrIdx];
- int S, x, y;
-
- /* interior face midpoints
- * - old interior face points
- */
- for (S = 0; S < f->numVerts; S++) {
- for (y = 0; y < gridSize - 1; y++) {
- for (x = 0; x < gridSize - 1; x++) {
- int fx = 1 + 2 * x;
- int fy = 1 + 2 * y;
- const float *co0 = FACE_getIFCo(f, curLvl, S, x + 0, y + 0);
- const float *co1 = FACE_getIFCo(f, curLvl, S, x + 1, y + 0);
- const float *co2 = FACE_getIFCo(f, curLvl, S, x + 1, y + 1);
- const float *co3 = FACE_getIFCo(f, curLvl, S, x + 0, y + 1);
- float *co = FACE_getIFCo(f, nextLvl, S, fx, fy);
-
- VertDataAvg4(co, co0, co1, co2, co3, ss);
- }
- }
- }
-
- /* interior edge midpoints
- * - old interior edge points
- * - new interior face midpoints
- */
- for (S = 0; S < f->numVerts; S++) {
- for (x = 0; x < gridSize - 1; x++) {
- int fx = x * 2 + 1;
- const float *co0 = FACE_getIECo(f, curLvl, S, x + 0);
- const float *co1 = FACE_getIECo(f, curLvl, S, x + 1);
- const float *co2 = FACE_getIFCo(f, nextLvl, (S + 1) % f->numVerts, 1, fx);
- const float *co3 = FACE_getIFCo(f, nextLvl, S, fx, 1);
- float *co = FACE_getIECo(f, nextLvl, S, fx);
-
- VertDataAvg4(co, co0, co1, co2, co3, ss);
- }
-
- /* interior face interior edge midpoints
- * - old interior face points
- * - new interior face midpoints
- */
-
- /* vertical */
- for (x = 1; x < gridSize - 1; x++) {
- for (y = 0; y < gridSize - 1; y++) {
- int fx = x * 2;
- int fy = y * 2 + 1;
- const float *co0 = FACE_getIFCo(f, curLvl, S, x, y + 0);
- const float *co1 = FACE_getIFCo(f, curLvl, S, x, y + 1);
- const float *co2 = FACE_getIFCo(f, nextLvl, S, fx - 1, fy);
- const float *co3 = FACE_getIFCo(f, nextLvl, S, fx + 1, fy);
- float *co = FACE_getIFCo(f, nextLvl, S, fx, fy);
-
- VertDataAvg4(co, co0, co1, co2, co3, ss);
- }
- }
-
- /* horizontal */
- for (y = 1; y < gridSize - 1; y++) {
- for (x = 0; x < gridSize - 1; x++) {
- int fx = x * 2 + 1;
- int fy = y * 2;
- const float *co0 = FACE_getIFCo(f, curLvl, S, x + 0, y);
- const float *co1 = FACE_getIFCo(f, curLvl, S, x + 1, y);
- const float *co2 = FACE_getIFCo(f, nextLvl, S, fx, fy - 1);
- const float *co3 = FACE_getIFCo(f, nextLvl, S, fx, fy + 1);
- float *co = FACE_getIFCo(f, nextLvl, S, fx, fy);
-
- VertDataAvg4(co, co0, co1, co2, co3, ss);
- }
- }
- }
- }
-
- /* exterior edge midpoints
- * - old exterior edge points
- * - new interior face midpoints
- */
- for (ptrIdx = 0; ptrIdx < numEffectedE; ptrIdx++) {
- CCGEdge *e = (CCGEdge *) effectedE[ptrIdx];
- float sharpness = EDGE_getSharpness(e, curLvl);
- int x, j;
-
- if (_edge_isBoundary(e) || sharpness > 1.0f) {
- for (x = 0; x < edgeSize - 1; x++) {
- int fx = x * 2 + 1;
- const float *co0 = EDGE_getCo(e, curLvl, x + 0);
- const float *co1 = EDGE_getCo(e, curLvl, x + 1);
- float *co = EDGE_getCo(e, nextLvl, fx);
-
- VertDataCopy(co, co0, ss);
- VertDataAdd(co, co1, ss);
- VertDataMulN(co, 0.5f, ss);
- }
- }
- else {
- for (x = 0; x < edgeSize - 1; x++) {
- int fx = x * 2 + 1;
- const float *co0 = EDGE_getCo(e, curLvl, x + 0);
- const float *co1 = EDGE_getCo(e, curLvl, x + 1);
- float *co = EDGE_getCo(e, nextLvl, fx);
- int numFaces = 0;
-
- VertDataCopy(q, co0, ss);
- VertDataAdd(q, co1, ss);
-
- for (j = 0; j < e->numFaces; j++) {
- CCGFace *f = e->faces[j];
- const int f_ed_idx = _face_getEdgeIndex(f, e);
- VertDataAdd(q, _face_getIFCoEdge(f, e, f_ed_idx, nextLvl, fx, 1, subdivLevels, vertDataSize), ss);
- numFaces++;
- }
-
- VertDataMulN(q, 1.0f / (2.0f + numFaces), ss);
-
- VertDataCopy(r, co0, ss);
- VertDataAdd(r, co1, ss);
- VertDataMulN(r, 0.5f, ss);
-
- VertDataCopy(co, q, ss);
- VertDataSub(r, q, ss);
- VertDataMulN(r, sharpness, ss);
- VertDataAdd(co, r, ss);
- }
- }
- }
-
- /* exterior vertex shift
- * - old vertex points (shifting)
- * - old exterior edge points
- * - new interior face midpoints
- */
- for (ptrIdx = 0; ptrIdx < numEffectedV; ptrIdx++) {
- CCGVert *v = (CCGVert *) effectedV[ptrIdx];
- const float *co = VERT_getCo(v, curLvl);
- float *nCo = VERT_getCo(v, nextLvl);
- int sharpCount = 0, allSharp = 1;
- float avgSharpness = 0.0;
- int j, seam = VERT_seam(v), seamEdges = 0;
-
- for (j = 0; j < v->numEdges; j++) {
- CCGEdge *e = v->edges[j];
- float sharpness = EDGE_getSharpness(e, curLvl);
-
- if (seam && _edge_isBoundary(e))
- seamEdges++;
-
- if (sharpness != 0.0f) {
- sharpCount++;
- avgSharpness += sharpness;
- }
- else {
- allSharp = 0;
- }
- }
-
- if (sharpCount) {
- avgSharpness /= sharpCount;
- if (avgSharpness > 1.0f) {
- avgSharpness = 1.0f;
- }
- }
-
- if (seamEdges < 2 || seamEdges != v->numEdges)
- seam = 0;
-
- if (!v->numEdges || ss->meshIFC.simpleSubdiv) {
- VertDataCopy(nCo, co, ss);
- }
- else if (_vert_isBoundary(v)) {
- int numBoundary = 0;
-
- VertDataZero(r, ss);
- for (j = 0; j < v->numEdges; j++) {
- CCGEdge *e = v->edges[j];
- if (_edge_isBoundary(e)) {
- VertDataAdd(r, _edge_getCoVert(e, v, curLvl, 1, vertDataSize), ss);
- numBoundary++;
- }
- }
-
- VertDataCopy(nCo, co, ss);
- VertDataMulN(nCo, 0.75f, ss);
- VertDataMulN(r, 0.25f / numBoundary, ss);
- VertDataAdd(nCo, r, ss);
- }
- else {
- int cornerIdx = (1 + (1 << (curLvl))) - 2;
- int numEdges = 0, numFaces = 0;
-
- VertDataZero(q, ss);
- for (j = 0; j < v->numFaces; j++) {
- CCGFace *f = v->faces[j];
- VertDataAdd(q, FACE_getIFCo(f, nextLvl, _face_getVertIndex(f, v), cornerIdx, cornerIdx), ss);
- numFaces++;
- }
- VertDataMulN(q, 1.0f / numFaces, ss);
- VertDataZero(r, ss);
- for (j = 0; j < v->numEdges; j++) {
- CCGEdge *e = v->edges[j];
- VertDataAdd(r, _edge_getCoVert(e, v, curLvl, 1, vertDataSize), ss);
- numEdges++;
- }
- VertDataMulN(r, 1.0f / numEdges, ss);
-
- VertDataCopy(nCo, co, ss);
- VertDataMulN(nCo, numEdges - 2.0f, ss);
- VertDataAdd(nCo, q, ss);
- VertDataAdd(nCo, r, ss);
- VertDataMulN(nCo, 1.0f / numEdges, ss);
- }
-
- if ((sharpCount > 1 && v->numFaces) || seam) {
- VertDataZero(q, ss);
-
- if (seam) {
- avgSharpness = 1.0f;
- sharpCount = seamEdges;
- allSharp = 1;
- }
-
- for (j = 0; j < v->numEdges; j++) {
- CCGEdge *e = v->edges[j];
- float sharpness = EDGE_getSharpness(e, curLvl);
-
- if (seam) {
- if (_edge_isBoundary(e))
- VertDataAdd(q, _edge_getCoVert(e, v, curLvl, 1, vertDataSize), ss);
- }
- else if (sharpness != 0.0f) {
- VertDataAdd(q, _edge_getCoVert(e, v, curLvl, 1, vertDataSize), ss);
- }
- }
-
- VertDataMulN(q, (float) 1 / sharpCount, ss);
-
- if (sharpCount != 2 || allSharp) {
- /* q = q + (co - q) * avgSharpness */
- VertDataCopy(r, co, ss);
- VertDataSub(r, q, ss);
- VertDataMulN(r, avgSharpness, ss);
- VertDataAdd(q, r, ss);
- }
-
- /* r = co * 0.75 + q * 0.25 */
- VertDataCopy(r, co, ss);
- VertDataMulN(r, 0.75f, ss);
- VertDataMulN(q, 0.25f, ss);
- VertDataAdd(r, q, ss);
-
- /* nCo = nCo + (r - nCo) * avgSharpness */
- VertDataSub(r, nCo, ss);
- VertDataMulN(r, avgSharpness, ss);
- VertDataAdd(nCo, r, ss);
- }
- }
-
- /* exterior edge interior shift
- * - old exterior edge midpoints (shifting)
- * - old exterior edge midpoints
- * - new interior face midpoints
- */
- for (ptrIdx = 0; ptrIdx < numEffectedE; ptrIdx++) {
- CCGEdge *e = (CCGEdge *) effectedE[ptrIdx];
- float sharpness = EDGE_getSharpness(e, curLvl);
- int sharpCount = 0;
- float avgSharpness = 0.0;
- int x, j;
-
- if (sharpness != 0.0f) {
- sharpCount = 2;
- avgSharpness += sharpness;
-
- if (avgSharpness > 1.0f) {
- avgSharpness = 1.0f;
- }
- }
- else {
- sharpCount = 0;
- avgSharpness = 0;
- }
-
- if (_edge_isBoundary(e)) {
- for (x = 1; x < edgeSize - 1; x++) {
- int fx = x * 2;
- const float *co = EDGE_getCo(e, curLvl, x);
- float *nCo = EDGE_getCo(e, nextLvl, fx);
-
- /* Average previous level's endpoints */
- VertDataCopy(r, EDGE_getCo(e, curLvl, x - 1), ss);
- VertDataAdd(r, EDGE_getCo(e, curLvl, x + 1), ss);
- VertDataMulN(r, 0.5f, ss);
-
- /* nCo = nCo * 0.75 + r * 0.25 */
- VertDataCopy(nCo, co, ss);
- VertDataMulN(nCo, 0.75f, ss);
- VertDataMulN(r, 0.25f, ss);
- VertDataAdd(nCo, r, ss);
- }
- }
- else {
- for (x = 1; x < edgeSize - 1; x++) {
- int fx = x * 2;
- const float *co = EDGE_getCo(e, curLvl, x);
- float *nCo = EDGE_getCo(e, nextLvl, fx);
- int numFaces = 0;
-
- VertDataZero(q, ss);
- VertDataZero(r, ss);
- VertDataAdd(r, EDGE_getCo(e, curLvl, x - 1), ss);
- VertDataAdd(r, EDGE_getCo(e, curLvl, x + 1), ss);
- for (j = 0; j < e->numFaces; j++) {
- CCGFace *f = e->faces[j];
- int f_ed_idx = _face_getEdgeIndex(f, e);
- VertDataAdd(q, _face_getIFCoEdge(f, e, f_ed_idx, nextLvl, fx - 1, 1, subdivLevels, vertDataSize), ss);
- VertDataAdd(q, _face_getIFCoEdge(f, e, f_ed_idx, nextLvl, fx + 1, 1, subdivLevels, vertDataSize), ss);
-
- VertDataAdd(r, _face_getIFCoEdge(f, e, f_ed_idx, curLvl, x, 1, subdivLevels, vertDataSize), ss);
- numFaces++;
- }
- VertDataMulN(q, 1.0f / (numFaces * 2.0f), ss);
- VertDataMulN(r, 1.0f / (2.0f + numFaces), ss);
-
- VertDataCopy(nCo, co, ss);
- VertDataMulN(nCo, (float) numFaces, ss);
- VertDataAdd(nCo, q, ss);
- VertDataAdd(nCo, r, ss);
- VertDataMulN(nCo, 1.0f / (2 + numFaces), ss);
-
- if (sharpCount == 2) {
- VertDataCopy(q, co, ss);
- VertDataMulN(q, 6.0f, ss);
- VertDataAdd(q, EDGE_getCo(e, curLvl, x - 1), ss);
- VertDataAdd(q, EDGE_getCo(e, curLvl, x + 1), ss);
- VertDataMulN(q, 1 / 8.0f, ss);
-
- VertDataSub(q, nCo, ss);
- VertDataMulN(q, avgSharpness, ss);
- VertDataAdd(nCo, q, ss);
- }
- }
- }
- }
-
-#pragma omp parallel private(ptrIdx) if (numEffectedF * edgeSize * edgeSize * 4 >= CCG_OMP_LIMIT)
- {
- float *q, *r;
-
-#pragma omp critical
- {
- q = MEM_mallocN(ss->meshIFC.vertDataSize, "CCGSubsurf q");
- r = MEM_mallocN(ss->meshIFC.vertDataSize, "CCGSubsurf r");
- }
-
-#pragma omp for schedule(static)
- for (ptrIdx = 0; ptrIdx < numEffectedF; ptrIdx++) {
- CCGFace *f = (CCGFace *) effectedF[ptrIdx];
- int S, x, y;
-
- /* interior center point shift
- * - old face center point (shifting)
- * - old interior edge points
- * - new interior face midpoints
- */
- VertDataZero(q, ss);
- for (S = 0; S < f->numVerts; S++) {
- VertDataAdd(q, FACE_getIFCo(f, nextLvl, S, 1, 1), ss);
- }
- VertDataMulN(q, 1.0f / f->numVerts, ss);
- VertDataZero(r, ss);
- for (S = 0; S < f->numVerts; S++) {
- VertDataAdd(r, FACE_getIECo(f, curLvl, S, 1), ss);
- }
- VertDataMulN(r, 1.0f / f->numVerts, ss);
-
- VertDataMulN((float *)FACE_getCenterData(f), f->numVerts - 2.0f, ss);
- VertDataAdd((float *)FACE_getCenterData(f), q, ss);
- VertDataAdd((float *)FACE_getCenterData(f), r, ss);
- VertDataMulN((float *)FACE_getCenterData(f), 1.0f / f->numVerts, ss);
-
- for (S = 0; S < f->numVerts; S++) {
- /* interior face shift
- * - old interior face point (shifting)
- * - new interior edge midpoints
- * - new interior face midpoints
- */
- for (x = 1; x < gridSize - 1; x++) {
- for (y = 1; y < gridSize - 1; y++) {
- int fx = x * 2;
- int fy = y * 2;
- const float *co = FACE_getIFCo(f, curLvl, S, x, y);
- float *nCo = FACE_getIFCo(f, nextLvl, S, fx, fy);
-
- VertDataAvg4(q,
- FACE_getIFCo(f, nextLvl, S, fx - 1, fy - 1),
- FACE_getIFCo(f, nextLvl, S, fx + 1, fy - 1),
- FACE_getIFCo(f, nextLvl, S, fx + 1, fy + 1),
- FACE_getIFCo(f, nextLvl, S, fx - 1, fy + 1),
- ss);
-
- VertDataAvg4(r,
- FACE_getIFCo(f, nextLvl, S, fx - 1, fy + 0),
- FACE_getIFCo(f, nextLvl, S, fx + 1, fy + 0),
- FACE_getIFCo(f, nextLvl, S, fx + 0, fy - 1),
- FACE_getIFCo(f, nextLvl, S, fx + 0, fy + 1),
- ss);
-
- VertDataCopy(nCo, co, ss);
- VertDataSub(nCo, q, ss);
- VertDataMulN(nCo, 0.25f, ss);
- VertDataAdd(nCo, r, ss);
- }
- }
-
- /* interior edge interior shift
- * - old interior edge point (shifting)
- * - new interior edge midpoints
- * - new interior face midpoints
- */
- for (x = 1; x < gridSize - 1; x++) {
- int fx = x * 2;
- const float *co = FACE_getIECo(f, curLvl, S, x);
- float *nCo = FACE_getIECo(f, nextLvl, S, fx);
-
- VertDataAvg4(q,
- FACE_getIFCo(f, nextLvl, (S + 1) % f->numVerts, 1, fx - 1),
- FACE_getIFCo(f, nextLvl, (S + 1) % f->numVerts, 1, fx + 1),
- FACE_getIFCo(f, nextLvl, S, fx + 1, +1),
- FACE_getIFCo(f, nextLvl, S, fx - 1, +1), ss);
-
- VertDataAvg4(r,
- FACE_getIECo(f, nextLvl, S, fx - 1),
- FACE_getIECo(f, nextLvl, S, fx + 1),
- FACE_getIFCo(f, nextLvl, (S + 1) % f->numVerts, 1, fx),
- FACE_getIFCo(f, nextLvl, S, fx, 1),
- ss);
-
- VertDataCopy(nCo, co, ss);
- VertDataSub(nCo, q, ss);
- VertDataMulN(nCo, 0.25f, ss);
- VertDataAdd(nCo, r, ss);
- }
- }
- }
-
-#pragma omp critical
- {
- MEM_freeN(q);
- MEM_freeN(r);
- }
- }
-
- /* copy down */
- edgeSize = ccg_edgesize(nextLvl);
- gridSize = ccg_gridsize(nextLvl);
- cornerIdx = gridSize - 1;
-
-#pragma omp parallel for private(i) if (numEffectedF * edgeSize * edgeSize * 4 >= CCG_OMP_LIMIT)
- for (i = 0; i < numEffectedE; i++) {
- CCGEdge *e = effectedE[i];
- VertDataCopy(EDGE_getCo(e, nextLvl, 0), VERT_getCo(e->v0, nextLvl), ss);
- VertDataCopy(EDGE_getCo(e, nextLvl, edgeSize - 1), VERT_getCo(e->v1, nextLvl), ss);
- }
-
-#pragma omp parallel for private(i) if (numEffectedF * edgeSize * edgeSize * 4 >= CCG_OMP_LIMIT)
- for (i = 0; i < numEffectedF; i++) {
- CCGFace *f = effectedF[i];
- int S, x;
-
- for (S = 0; S < f->numVerts; S++) {
- CCGEdge *e = FACE_getEdges(f)[S];
- CCGEdge *prevE = FACE_getEdges(f)[(S + f->numVerts - 1) % f->numVerts];
-
- VertDataCopy(FACE_getIFCo(f, nextLvl, S, 0, 0), (float *)FACE_getCenterData(f), ss);
- VertDataCopy(FACE_getIECo(f, nextLvl, S, 0), (float *)FACE_getCenterData(f), ss);
- VertDataCopy(FACE_getIFCo(f, nextLvl, S, cornerIdx, cornerIdx), VERT_getCo(FACE_getVerts(f)[S], nextLvl), ss);
- VertDataCopy(FACE_getIECo(f, nextLvl, S, cornerIdx), EDGE_getCo(FACE_getEdges(f)[S], nextLvl, cornerIdx), ss);
- for (x = 1; x < gridSize - 1; x++) {
- float *co = FACE_getIECo(f, nextLvl, S, x);
- VertDataCopy(FACE_getIFCo(f, nextLvl, S, x, 0), co, ss);
- VertDataCopy(FACE_getIFCo(f, nextLvl, (S + 1) % f->numVerts, 0, x), co, ss);
- }
- for (x = 0; x < gridSize - 1; x++) {
- int eI = gridSize - 1 - x;
- VertDataCopy(FACE_getIFCo(f, nextLvl, S, cornerIdx, x), _edge_getCoVert(e, FACE_getVerts(f)[S], nextLvl, eI, vertDataSize), ss);
- VertDataCopy(FACE_getIFCo(f, nextLvl, S, x, cornerIdx), _edge_getCoVert(prevE, FACE_getVerts(f)[S], nextLvl, eI, vertDataSize), ss);
- }
- }
- }
-}
-
-
-static void ccgSubSurf__sync(CCGSubSurf *ss)
-{
- CCGVert **effectedV;
- CCGEdge **effectedE;
- CCGFace **effectedF;
- int numEffectedV, numEffectedE, numEffectedF;
- int subdivLevels = ss->subdivLevels;
- int vertDataSize = ss->meshIFC.vertDataSize;
- int i, j, ptrIdx, S;
- int curLvl, nextLvl;
- void *q = ss->q, *r = ss->r;
-
- effectedV = MEM_mallocN(sizeof(*effectedV) * ss->vMap->numEntries, "CCGSubsurf effectedV");
- effectedE = MEM_mallocN(sizeof(*effectedE) * ss->eMap->numEntries, "CCGSubsurf effectedE");
- effectedF = MEM_mallocN(sizeof(*effectedF) * ss->fMap->numEntries, "CCGSubsurf effectedF");
- numEffectedV = numEffectedE = numEffectedF = 0;
- for (i = 0; i < ss->vMap->curSize; i++) {
- CCGVert *v = (CCGVert *) ss->vMap->buckets[i];
- for (; v; v = v->next) {
- if (v->flags & Vert_eEffected) {
- effectedV[numEffectedV++] = v;
-
- for (j = 0; j < v->numEdges; j++) {
- CCGEdge *e = v->edges[j];
- if (!(e->flags & Edge_eEffected)) {
- effectedE[numEffectedE++] = e;
- e->flags |= Edge_eEffected;
- }
- }
-
- for (j = 0; j < v->numFaces; j++) {
- CCGFace *f = v->faces[j];
- if (!(f->flags & Face_eEffected)) {
- effectedF[numEffectedF++] = f;
- f->flags |= Face_eEffected;
- }
- }
- }
- }
- }
-
- curLvl = 0;
- nextLvl = curLvl + 1;
-
- for (ptrIdx = 0; ptrIdx < numEffectedF; ptrIdx++) {
- CCGFace *f = effectedF[ptrIdx];
- void *co = FACE_getCenterData(f);
- VertDataZero(co, ss);
- for (i = 0; i < f->numVerts; i++) {
- VertDataAdd(co, VERT_getCo(FACE_getVerts(f)[i], curLvl), ss);
- }
- VertDataMulN(co, 1.0f / f->numVerts, ss);
-
- f->flags = 0;
- }
- for (ptrIdx = 0; ptrIdx < numEffectedE; ptrIdx++) {
- CCGEdge *e = effectedE[ptrIdx];
- void *co = EDGE_getCo(e, nextLvl, 1);
- float sharpness = EDGE_getSharpness(e, curLvl);
-
- if (_edge_isBoundary(e) || sharpness >= 1.0f) {
- VertDataCopy(co, VERT_getCo(e->v0, curLvl), ss);
- VertDataAdd(co, VERT_getCo(e->v1, curLvl), ss);
- VertDataMulN(co, 0.5f, ss);
- }
- else {
- int numFaces = 0;
- VertDataCopy(q, VERT_getCo(e->v0, curLvl), ss);
- VertDataAdd(q, VERT_getCo(e->v1, curLvl), ss);
- for (i = 0; i < e->numFaces; i++) {
- CCGFace *f = e->faces[i];
- VertDataAdd(q, (float *)FACE_getCenterData(f), ss);
- numFaces++;
- }
- VertDataMulN(q, 1.0f / (2.0f + numFaces), ss);
-
- VertDataCopy(r, VERT_getCo(e->v0, curLvl), ss);
- VertDataAdd(r, VERT_getCo(e->v1, curLvl), ss);
- VertDataMulN(r, 0.5f, ss);
-
- VertDataCopy(co, q, ss);
- VertDataSub(r, q, ss);
- VertDataMulN(r, sharpness, ss);
- VertDataAdd(co, r, ss);
- }
-
- /* edge flags cleared later */
- }
- for (ptrIdx = 0; ptrIdx < numEffectedV; ptrIdx++) {
- CCGVert *v = effectedV[ptrIdx];
- void *co = VERT_getCo(v, curLvl);
- void *nCo = VERT_getCo(v, nextLvl);
- int sharpCount = 0, allSharp = 1;
- float avgSharpness = 0.0;
- int seam = VERT_seam(v), seamEdges = 0;
-
- for (i = 0; i < v->numEdges; i++) {
- CCGEdge *e = v->edges[i];
- float sharpness = EDGE_getSharpness(e, curLvl);
-
- if (seam && _edge_isBoundary(e))
- seamEdges++;
-
- if (sharpness != 0.0f) {
- sharpCount++;
- avgSharpness += sharpness;
- }
- else {
- allSharp = 0;
- }
- }
-
- if (sharpCount) {
- avgSharpness /= sharpCount;
- if (avgSharpness > 1.0f) {
- avgSharpness = 1.0f;
- }
- }
-
- if (seamEdges < 2 || seamEdges != v->numEdges)
- seam = 0;
-
- if (!v->numEdges || ss->meshIFC.simpleSubdiv) {
- VertDataCopy(nCo, co, ss);
- }
- else if (_vert_isBoundary(v)) {
- int numBoundary = 0;
-
- VertDataZero(r, ss);
- for (i = 0; i < v->numEdges; i++) {
- CCGEdge *e = v->edges[i];
- if (_edge_isBoundary(e)) {
- VertDataAdd(r, VERT_getCo(_edge_getOtherVert(e, v), curLvl), ss);
- numBoundary++;
- }
- }
- VertDataCopy(nCo, co, ss);
- VertDataMulN(nCo, 0.75f, ss);
- VertDataMulN(r, 0.25f / numBoundary, ss);
- VertDataAdd(nCo, r, ss);
- }
- else {
- int numEdges = 0, numFaces = 0;
-
- VertDataZero(q, ss);
- for (i = 0; i < v->numFaces; i++) {
- CCGFace *f = v->faces[i];
- VertDataAdd(q, (float *)FACE_getCenterData(f), ss);
- numFaces++;
- }
- VertDataMulN(q, 1.0f / numFaces, ss);
- VertDataZero(r, ss);
- for (i = 0; i < v->numEdges; i++) {
- CCGEdge *e = v->edges[i];
- VertDataAdd(r, VERT_getCo(_edge_getOtherVert(e, v), curLvl), ss);
- numEdges++;
- }
- VertDataMulN(r, 1.0f / numEdges, ss);
-
- VertDataCopy(nCo, co, ss);
- VertDataMulN(nCo, numEdges - 2.0f, ss);
- VertDataAdd(nCo, q, ss);
- VertDataAdd(nCo, r, ss);
- VertDataMulN(nCo, 1.0f / numEdges, ss);
- }
-
- if (sharpCount > 1 || seam) {
- VertDataZero(q, ss);
-
- if (seam) {
- avgSharpness = 1.0f;
- sharpCount = seamEdges;
- allSharp = 1;
- }
-
- for (i = 0; i < v->numEdges; i++) {
- CCGEdge *e = v->edges[i];
- float sharpness = EDGE_getSharpness(e, curLvl);
-
- if (seam) {
- if (_edge_isBoundary(e)) {
- CCGVert *oV = _edge_getOtherVert(e, v);
- VertDataAdd(q, VERT_getCo(oV, curLvl), ss);
- }
- }
- else if (sharpness != 0.0f) {
- CCGVert *oV = _edge_getOtherVert(e, v);
- VertDataAdd(q, VERT_getCo(oV, curLvl), ss);
- }
- }
-
- VertDataMulN(q, (float) 1 / sharpCount, ss);
-
- if (sharpCount != 2 || allSharp) {
- /* q = q + (co - q) * avgSharpness */
- VertDataCopy(r, co, ss);
- VertDataSub(r, q, ss);
- VertDataMulN(r, avgSharpness, ss);
- VertDataAdd(q, r, ss);
- }
-
- /* r = co * 0.75 + q * 0.25 */
- VertDataCopy(r, co, ss);
- VertDataMulN(r, 0.75f, ss);
- VertDataMulN(q, 0.25f, ss);
- VertDataAdd(r, q, ss);
-
- /* nCo = nCo + (r - nCo) * avgSharpness */
- VertDataSub(r, nCo, ss);
- VertDataMulN(r, avgSharpness, ss);
- VertDataAdd(nCo, r, ss);
- }
-
- /* vert flags cleared later */
- }
-
- if (ss->useAgeCounts) {
- for (i = 0; i < numEffectedV; i++) {
- CCGVert *v = effectedV[i];
- byte *userData = ccgSubSurf_getVertUserData(ss, v);
- *((int *) &userData[ss->vertUserAgeOffset]) = ss->currentAge;
- }
-
- for (i = 0; i < numEffectedE; i++) {
- CCGEdge *e = effectedE[i];
- byte *userData = ccgSubSurf_getEdgeUserData(ss, e);
- *((int *) &userData[ss->edgeUserAgeOffset]) = ss->currentAge;
- }
-
- for (i = 0; i < numEffectedF; i++) {
- CCGFace *f = effectedF[i];
- byte *userData = ccgSubSurf_getFaceUserData(ss, f);
- *((int *) &userData[ss->faceUserAgeOffset]) = ss->currentAge;
- }
- }
-
- for (i = 0; i < numEffectedE; i++) {
- CCGEdge *e = effectedE[i];
- VertDataCopy(EDGE_getCo(e, nextLvl, 0), VERT_getCo(e->v0, nextLvl), ss);
- VertDataCopy(EDGE_getCo(e, nextLvl, 2), VERT_getCo(e->v1, nextLvl), ss);
- }
- for (i = 0; i < numEffectedF; i++) {
- CCGFace *f = effectedF[i];
- for (S = 0; S < f->numVerts; S++) {
- CCGEdge *e = FACE_getEdges(f)[S];
- CCGEdge *prevE = FACE_getEdges(f)[(S + f->numVerts - 1) % f->numVerts];
-
- VertDataCopy(FACE_getIFCo(f, nextLvl, S, 0, 0), (float *)FACE_getCenterData(f), ss);
- VertDataCopy(FACE_getIECo(f, nextLvl, S, 0), (float *)FACE_getCenterData(f), ss);
- VertDataCopy(FACE_getIFCo(f, nextLvl, S, 1, 1), VERT_getCo(FACE_getVerts(f)[S], nextLvl), ss);
- VertDataCopy(FACE_getIECo(f, nextLvl, S, 1), EDGE_getCo(FACE_getEdges(f)[S], nextLvl, 1), ss);
-
- VertDataCopy(FACE_getIFCo(f, nextLvl, S, 1, 0), _edge_getCoVert(e, FACE_getVerts(f)[S], nextLvl, 1, vertDataSize), ss);
- VertDataCopy(FACE_getIFCo(f, nextLvl, S, 0, 1), _edge_getCoVert(prevE, FACE_getVerts(f)[S], nextLvl, 1, vertDataSize), ss);
- }
- }
-
- for (curLvl = 1; curLvl < subdivLevels; curLvl++) {
- ccgSubSurf__calcSubdivLevel(ss,
- effectedV, effectedE, effectedF,
- numEffectedV, numEffectedE, numEffectedF, curLvl);
- }
-
- if (ss->calcVertNormals)
- ccgSubSurf__calcVertNormals(ss,
- effectedV, effectedE, effectedF,
- numEffectedV, numEffectedE, numEffectedF);
-
- for (ptrIdx = 0; ptrIdx < numEffectedV; ptrIdx++) {
- CCGVert *v = effectedV[ptrIdx];
- v->flags = 0;
- }
- for (ptrIdx = 0; ptrIdx < numEffectedE; ptrIdx++) {
- CCGEdge *e = effectedE[ptrIdx];
- e->flags = 0;
- }
-
- MEM_freeN(effectedF);
- MEM_freeN(effectedE);
- MEM_freeN(effectedV);
-}
-
-static void ccgSubSurf__allFaces(CCGSubSurf *ss, CCGFace ***faces, int *numFaces, int *freeFaces)
+void ccgSubSurf__allFaces(CCGSubSurf *ss, CCGFace ***faces, int *numFaces, int *freeFaces)
{
CCGFace **array;
int i, num;
@@ -2448,7 +918,7 @@ static void ccgSubSurf__allFaces(CCGSubSurf *ss, CCGFace ***faces, int *numFaces
}
}
-static void ccgSubSurf__effectedFaceNeighbours(CCGSubSurf *ss, CCGFace **faces, int numFaces, CCGVert ***verts, int *numVerts, CCGEdge ***edges, int *numEdges)
+void ccgSubSurf__effectedFaceNeighbours(CCGSubSurf *ss, CCGFace **faces, int numFaces, CCGVert ***verts, int *numVerts, CCGEdge ***edges, int *numEdges)
{
CCGVert **arrayV;
CCGEdge **arrayE;
@@ -2717,75 +1187,6 @@ CCGError ccgSubSurf_stitchFaces(CCGSubSurf *ss, int lvl, CCGFace **effectedF, in
return eCCGError_None;
}
-/* update normals for specified faces */
-CCGError ccgSubSurf_updateNormals(CCGSubSurf *ss, CCGFace **effectedF, int numEffectedF)
-{
- CCGVert **effectedV;
- CCGEdge **effectedE;
- int i, numEffectedV, numEffectedE, freeF;
-
- ccgSubSurf__allFaces(ss, &effectedF, &numEffectedF, &freeF);
- ccgSubSurf__effectedFaceNeighbours(ss, effectedF, numEffectedF,
- &effectedV, &numEffectedV, &effectedE, &numEffectedE);
-
- if (ss->calcVertNormals)
- ccgSubSurf__calcVertNormals(ss,
- effectedV, effectedE, effectedF,
- numEffectedV, numEffectedE, numEffectedF);
-
- for (i = 0; i < numEffectedV; i++)
- effectedV[i]->flags = 0;
- for (i = 0; i < numEffectedE; i++)
- effectedE[i]->flags = 0;
- for (i = 0; i < numEffectedF; i++)
- effectedF[i]->flags = 0;
-
- MEM_freeN(effectedE);
- MEM_freeN(effectedV);
- if (freeF) MEM_freeN(effectedF);
-
- return eCCGError_None;
-}
-
-/* compute subdivision levels from a given starting point, used by
- * multires subdivide/propagate, by filling in coordinates at a
- * certain level, and then subdividing that up to the highest level */
-CCGError ccgSubSurf_updateLevels(CCGSubSurf *ss, int lvl, CCGFace **effectedF, int numEffectedF)
-{
- CCGVert **effectedV;
- CCGEdge **effectedE;
- int numEffectedV, numEffectedE, freeF, i;
- int curLvl, subdivLevels = ss->subdivLevels;
-
- ccgSubSurf__allFaces(ss, &effectedF, &numEffectedF, &freeF);
- ccgSubSurf__effectedFaceNeighbours(ss, effectedF, numEffectedF,
- &effectedV, &numEffectedV, &effectedE, &numEffectedE);
-
- for (curLvl = lvl; curLvl < subdivLevels; curLvl++) {
- ccgSubSurf__calcSubdivLevel(ss,
- effectedV, effectedE, effectedF,
- numEffectedV, numEffectedE, numEffectedF, curLvl);
- }
-
- for (i = 0; i < numEffectedV; i++)
- effectedV[i]->flags = 0;
- for (i = 0; i < numEffectedE; i++)
- effectedE[i]->flags = 0;
- for (i = 0; i < numEffectedF; i++)
- effectedF[i]->flags = 0;
-
- MEM_freeN(effectedE);
- MEM_freeN(effectedV);
- if (freeF) MEM_freeN(effectedF);
-
- return eCCGError_None;
-}
-
-#undef VERT_getCo
-#undef EDGE_getCo
-#undef FACE_getIECo
-#undef FACE_getIFCo
-
/*** External API accessor functions ***/
int ccgSubSurf_getNumVerts(const CCGSubSurf *ss)
@@ -2803,15 +1204,15 @@ int ccgSubSurf_getNumFaces(const CCGSubSurf *ss)
CCGVert *ccgSubSurf_getVert(CCGSubSurf *ss, CCGVertHDL v)
{
- return (CCGVert *) _ehash_lookup(ss->vMap, v);
+ return (CCGVert *) ccg_ehash_lookup(ss->vMap, v);
}
CCGEdge *ccgSubSurf_getEdge(CCGSubSurf *ss, CCGEdgeHDL e)
{
- return (CCGEdge *) _ehash_lookup(ss->eMap, e);
+ return (CCGEdge *) ccg_ehash_lookup(ss->eMap, e);
}
CCGFace *ccgSubSurf_getFace(CCGSubSurf *ss, CCGFaceHDL f)
{
- return (CCGFace *) _ehash_lookup(ss->fMap, f);
+ return (CCGFace *) ccg_ehash_lookup(ss->fMap, f);
}
int ccgSubSurf_getSubdivisionLevels(const CCGSubSurf *ss)
@@ -2906,7 +1307,7 @@ void *ccgSubSurf_getVertLevelData(CCGSubSurf *ss, CCGVert *v, int level)
return NULL;
}
else {
- return _vert_getCo(v, level, ss->meshIFC.vertDataSize);
+ return ccg_vert_getCo(v, level, ss->meshIFC.vertDataSize);
}
}
@@ -2966,7 +1367,7 @@ void *ccgSubSurf_getEdgeLevelData(CCGSubSurf *ss, CCGEdge *e, int x, int level)
return NULL;
}
else {
- return _edge_getCo(e, level, x, ss->meshIFC.vertDataSize);
+ return ccg_edge_getCo(e, level, x, ss->meshIFC.vertDataSize);
}
}
float ccgSubSurf_getEdgeCrease(CCGEdge *e)
@@ -3038,7 +1439,7 @@ void *ccgSubSurf_getFaceGridEdgeDataArray(CCGSubSurf *ss, CCGFace *f, int gridIn
}
void *ccgSubSurf_getFaceGridEdgeData(CCGSubSurf *ss, CCGFace *f, int gridIndex, int x)
{
- return _face_getIECo(f, ss->subdivLevels, gridIndex, x, ss->subdivLevels, ss->meshIFC.vertDataSize);
+ return ccg_face_getIECo(f, ss->subdivLevels, gridIndex, x, ss->subdivLevels, ss->meshIFC.vertDataSize);
}
void *ccgSubSurf_getFaceGridDataArray(CCGSubSurf *ss, CCGFace *f, int gridIndex)
{
@@ -3046,73 +1447,61 @@ void *ccgSubSurf_getFaceGridDataArray(CCGSubSurf *ss, CCGFace *f, int gridIndex)
}
void *ccgSubSurf_getFaceGridData(CCGSubSurf *ss, CCGFace *f, int gridIndex, int x, int y)
{
- return _face_getIFCo(f, ss->subdivLevels, gridIndex, x, y, ss->subdivLevels, ss->meshIFC.vertDataSize);
+ return ccg_face_getIFCo(f, ss->subdivLevels, gridIndex, x, y, ss->subdivLevels, ss->meshIFC.vertDataSize);
}
/*** External API iterator functions ***/
-CCGVertIterator *ccgSubSurf_getVertIterator(CCGSubSurf *ss)
+void ccgSubSurf_initVertIterator(CCGSubSurf *ss, CCGVertIterator *viter)
{
- return (CCGVertIterator *) _ehashIterator_new(ss->vMap);
+ ccg_ehashIterator_init(ss->vMap, viter);
}
-CCGEdgeIterator *ccgSubSurf_getEdgeIterator(CCGSubSurf *ss)
+void ccgSubSurf_initEdgeIterator(CCGSubSurf *ss, CCGEdgeIterator *eiter)
{
- return (CCGEdgeIterator *) _ehashIterator_new(ss->eMap);
+ ccg_ehashIterator_init(ss->eMap, eiter);
}
-CCGFaceIterator *ccgSubSurf_getFaceIterator(CCGSubSurf *ss)
+void ccgSubSurf_initFaceIterator(CCGSubSurf *ss, CCGFaceIterator *fiter)
{
- return (CCGFaceIterator *) _ehashIterator_new(ss->fMap);
+ ccg_ehashIterator_init(ss->fMap, fiter);
}
CCGVert *ccgVertIterator_getCurrent(CCGVertIterator *vi)
{
- return (CCGVert *) _ehashIterator_getCurrent((EHashIterator *) vi);
+ return (CCGVert *) ccg_ehashIterator_getCurrent((EHashIterator *) vi);
}
int ccgVertIterator_isStopped(CCGVertIterator *vi)
{
- return _ehashIterator_isStopped((EHashIterator *) vi);
+ return ccg_ehashIterator_isStopped((EHashIterator *) vi);
}
void ccgVertIterator_next(CCGVertIterator *vi)
{
- _ehashIterator_next((EHashIterator *) vi);
-}
-void ccgVertIterator_free(CCGVertIterator *vi)
-{
- _ehashIterator_free((EHashIterator *) vi);
+ ccg_ehashIterator_next((EHashIterator *) vi);
}
CCGEdge *ccgEdgeIterator_getCurrent(CCGEdgeIterator *vi)
{
- return (CCGEdge *) _ehashIterator_getCurrent((EHashIterator *) vi);
+ return (CCGEdge *) ccg_ehashIterator_getCurrent((EHashIterator *) vi);
}
int ccgEdgeIterator_isStopped(CCGEdgeIterator *vi)
{
- return _ehashIterator_isStopped((EHashIterator *) vi);
+ return ccg_ehashIterator_isStopped((EHashIterator *) vi);
}
void ccgEdgeIterator_next(CCGEdgeIterator *vi)
{
- _ehashIterator_next((EHashIterator *) vi);
-}
-void ccgEdgeIterator_free(CCGEdgeIterator *vi)
-{
- _ehashIterator_free((EHashIterator *) vi);
+ ccg_ehashIterator_next((EHashIterator *) vi);
}
CCGFace *ccgFaceIterator_getCurrent(CCGFaceIterator *vi)
{
- return (CCGFace *) _ehashIterator_getCurrent((EHashIterator *) vi);
+ return (CCGFace *) ccg_ehashIterator_getCurrent((EHashIterator *) vi);
}
int ccgFaceIterator_isStopped(CCGFaceIterator *vi)
{
- return _ehashIterator_isStopped((EHashIterator *) vi);
+ return ccg_ehashIterator_isStopped((EHashIterator *) vi);
}
void ccgFaceIterator_next(CCGFaceIterator *vi)
{
- _ehashIterator_next((EHashIterator *) vi);
-}
-void ccgFaceIterator_free(CCGFaceIterator *vi)
-{
- _ehashIterator_free((EHashIterator *) vi);
+ ccg_ehashIterator_next((EHashIterator *) vi);
}
/*** Extern API final vert/edge/face interface ***/
@@ -3126,6 +1515,12 @@ int ccgSubSurf_getNumFinalVerts(const CCGSubSurf *ss)
ss->fMap->numEntries +
ss->numGrids * ((gridSize - 2) + ((gridSize - 2) * (gridSize - 2))));
+#ifdef WITH_OPENSUBDIV
+ if (ss->skip_grids) {
+ return 0;
+ }
+#endif
+
return numFinalVerts;
}
int ccgSubSurf_getNumFinalEdges(const CCGSubSurf *ss)
@@ -3134,13 +1529,22 @@ int ccgSubSurf_getNumFinalEdges(const CCGSubSurf *ss)
int gridSize = ccg_gridsize(ss->subdivLevels);
int numFinalEdges = (ss->eMap->numEntries * (edgeSize - 1) +
ss->numGrids * ((gridSize - 1) + 2 * ((gridSize - 2) * (gridSize - 1))));
-
+#ifdef WITH_OPENSUBDIV
+ if (ss->skip_grids) {
+ return 0;
+ }
+#endif
return numFinalEdges;
}
int ccgSubSurf_getNumFinalFaces(const CCGSubSurf *ss)
{
int gridSize = ccg_gridsize(ss->subdivLevels);
int numFinalFaces = ss->numGrids * ((gridSize - 1) * (gridSize - 1));
+#ifdef WITH_OPENSUBDIV
+ if (ss->skip_grids) {
+ return 0;
+ }
+#endif
return numFinalFaces;
}
diff --git a/source/blender/blenkernel/intern/CCGSubSurf.h b/source/blender/blenkernel/intern/CCGSubSurf.h
index fdf6d2df99f..a825cffe7a0 100644
--- a/source/blender/blenkernel/intern/CCGSubSurf.h
+++ b/source/blender/blenkernel/intern/CCGSubSurf.h
@@ -53,6 +53,13 @@ typedef struct CCGAllocatorIFC {
void (*release) (CCGAllocatorHDL a);
} CCGAllocatorIFC;
+/* private, so we can allocate on the stack */
+typedef struct _EHashIterator {
+ struct _EHash *eh;
+ int curBucket;
+ struct _EHEntry *curEntry;
+} EHashIterator;
+
/***/
typedef enum {
@@ -73,6 +80,9 @@ void ccgSubSurf_free (CCGSubSurf *ss);
CCGError ccgSubSurf_initFullSync (CCGSubSurf *ss);
CCGError ccgSubSurf_initPartialSync (CCGSubSurf *ss);
+#ifdef WITH_OPENSUBDIV
+CCGError ccgSubSurf_initOpenSubdivSync (CCGSubSurf *ss);
+#endif
CCGError ccgSubSurf_syncVert (CCGSubSurf *ss, CCGVertHDL vHDL, const void *vertData, int seam, CCGVert **v_r);
CCGError ccgSubSurf_syncEdge (CCGSubSurf *ss, CCGEdgeHDL eHDL, CCGVertHDL e_vHDL0, CCGVertHDL e_vHDL1, float crease, CCGEdge **e_r);
@@ -163,27 +173,77 @@ int ccgSubSurf_getNumFinalFaces (const CCGSubSurf *ss);
/***/
-typedef struct CCGVertIterator CCGVertIterator;
-typedef struct CCGEdgeIterator CCGEdgeIterator;
-typedef struct CCGFaceIterator CCGFaceIterator;
+typedef struct _EHashIterator CCGVertIterator;
+typedef struct _EHashIterator CCGEdgeIterator;
+typedef struct _EHashIterator CCGFaceIterator;
-CCGVertIterator* ccgSubSurf_getVertIterator (CCGSubSurf *ss);
-CCGEdgeIterator* ccgSubSurf_getEdgeIterator (CCGSubSurf *ss);
-CCGFaceIterator* ccgSubSurf_getFaceIterator (CCGSubSurf *ss);
+void ccgSubSurf_initVertIterator(CCGSubSurf *ss, CCGVertIterator *viter);
+void ccgSubSurf_initEdgeIterator(CCGSubSurf *ss, CCGEdgeIterator *eiter);
+void ccgSubSurf_initFaceIterator(CCGSubSurf *ss, CCGFaceIterator *fiter);
CCGVert* ccgVertIterator_getCurrent (CCGVertIterator *vi);
int ccgVertIterator_isStopped (CCGVertIterator *vi);
void ccgVertIterator_next (CCGVertIterator *vi);
-void ccgVertIterator_free (CCGVertIterator *vi);
CCGEdge* ccgEdgeIterator_getCurrent (CCGEdgeIterator *ei);
int ccgEdgeIterator_isStopped (CCGEdgeIterator *ei);
void ccgEdgeIterator_next (CCGEdgeIterator *ei);
-void ccgEdgeIterator_free (CCGEdgeIterator *ei);
CCGFace* ccgFaceIterator_getCurrent (CCGFaceIterator *fi);
int ccgFaceIterator_isStopped (CCGFaceIterator *fi);
void ccgFaceIterator_next (CCGFaceIterator *fi);
-void ccgFaceIterator_free (CCGFaceIterator *fi);
+
+#ifdef WITH_OPENSUBDIV
+struct DerivedMesh;
+
+/* Check if topology changed and evaluators are to be re-created. */
+void ccgSubSurf_checkTopologyChanged(CCGSubSurf *ss, struct DerivedMesh *dm);
+
+/* Create topology refiner from give derived mesh which then later will be
+ * used for GL mesh creation.
+ */
+void ccgSubSurf_prepareTopologyRefiner(CCGSubSurf *ss, struct DerivedMesh *dm);
+
+/* Make sure GL mesh exists, up to date and ready to draw. */
+bool ccgSubSurf_prepareGLMesh(CCGSubSurf *ss, bool use_osd_glsl);
+
+/* Draw given partitions of the GL mesh.
+ *
+ * TODO(sergey): fill_quads is actually an invariant and should be part
+ * of the prepare routine.
+ */
+void ccgSubSurf_drawGLMesh(CCGSubSurf *ss, bool fill_quads,
+ int start_partition, int num_partitions);
+
+/* Get number of base faces in a particular GL mesh. */
+int ccgSubSurf_getNumGLMeshBaseFaces(CCGSubSurf *ss);
+
+/* Get number of vertices in base faces in a particular GL mesh. */
+int ccgSubSurf_getNumGLMeshBaseFaceVerts(CCGSubSurf *ss, int face);
+
+/* Controls whether CCG are needed (Cmeaning CPU evaluation) or fully GPU compute
+ * and draw is allowed.
+ */
+void ccgSubSurf_setSkipGrids(CCGSubSurf *ss, bool skip_grids);
+bool ccgSubSurf_needGrids(CCGSubSurf *ss);
+
+/* Set evaluator's face varying data from UV coordinates.
+ * Used for CPU evaluation.
+ */
+void ccgSubSurf_evaluatorSetFVarUV(CCGSubSurf *ss,
+ struct DerivedMesh *dm,
+ int layer_index);
+
+/* TODO(sergey): Temporary call to test things. */
+void ccgSubSurf_evaluatorFVarUV(CCGSubSurf *ss,
+ int face_index, int S,
+ float grid_u, float grid_v,
+ float uv[2]);
+
+void ccgSubSurf_free_osd_mesh(CCGSubSurf *ss);
+
+void ccgSubSurf_getMinMax(CCGSubSurf *ss, float r_min[3], float r_max[3]);
+
+#endif
#endif /* __CCGSUBSURF_H__ */
diff --git a/source/blender/blenkernel/intern/CCGSubSurf_inline.h b/source/blender/blenkernel/intern/CCGSubSurf_inline.h
new file mode 100644
index 00000000000..183578c26ce
--- /dev/null
+++ b/source/blender/blenkernel/intern/CCGSubSurf_inline.h
@@ -0,0 +1,269 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/blenkernel/intern/CCGSubSurf_inline.h
+ * \ingroup bke
+ */
+
+#ifndef __CCGSUBSURF_INLINE_H__
+#define __CCGSUBSURF_INLINE_H__
+
+BLI_INLINE int ccg_gridsize(int level)
+{
+ BLI_assert(level > 0);
+ BLI_assert(level <= CCGSUBSURF_LEVEL_MAX + 1);
+ return (1 << (level - 1)) + 1;
+}
+
+BLI_INLINE int ccg_edgesize(int level)
+{
+ BLI_assert(level > 0);
+ BLI_assert(level <= CCGSUBSURF_LEVEL_MAX + 1);
+ return 1 + (1 << level);
+}
+
+BLI_INLINE int ccg_spacing(int high_level, int low_level)
+{
+ BLI_assert(high_level > 0 && low_level > 0);
+ BLI_assert(high_level >= low_level);
+ BLI_assert((high_level - low_level) <= CCGSUBSURF_LEVEL_MAX);
+ return 1 << (high_level - low_level);
+}
+
+BLI_INLINE int ccg_edgebase(int level)
+{
+ BLI_assert(level > 0);
+ BLI_assert(level <= CCGSUBSURF_LEVEL_MAX + 1);
+ return level + (1 << level) - 1;
+}
+
+/* **** */
+
+BLI_INLINE byte *VERT_getLevelData(CCGVert *v)
+{
+ return (byte *)(&(v)[1]);
+}
+
+BLI_INLINE byte *EDGE_getLevelData(CCGEdge *e)
+{
+ return (byte *)(&(e)[1]);
+}
+
+BLI_INLINE CCGVert **FACE_getVerts(CCGFace *f)
+{
+ return (CCGVert **)(&f[1]);
+}
+
+BLI_INLINE CCGEdge **FACE_getEdges(CCGFace *f)
+{
+ return (CCGEdge **)(&(FACE_getVerts(f)[f->numVerts]));
+}
+
+BLI_INLINE byte *FACE_getCenterData(CCGFace *f)
+{
+ return (byte *)(&(FACE_getEdges(f)[(f)->numVerts]));
+}
+
+/* **** */
+
+BLI_INLINE void *ccg_vert_getCo(CCGVert *v, int lvl, int dataSize)
+{
+ return &VERT_getLevelData(v)[lvl * dataSize];
+}
+
+BLI_INLINE float *ccg_vert_getNo(CCGVert *v,
+ int lvl,
+ int dataSize,
+ int normalDataOffset)
+{
+ return (float *) &VERT_getLevelData(v)[lvl * dataSize + normalDataOffset];
+}
+
+BLI_INLINE void *ccg_edge_getCo(CCGEdge *e, int lvl, int x, int dataSize)
+{
+ int levelBase = ccg_edgebase(lvl);
+ return &EDGE_getLevelData(e)[dataSize * (levelBase + x)];
+}
+
+BLI_INLINE float *ccg_edge_getNo(CCGEdge *e,
+ int lvl,
+ int x,
+ int dataSize,
+ int normalDataOffset)
+{
+ int levelBase = ccg_edgebase(lvl);
+ return (float *) &EDGE_getLevelData(e)[dataSize * (levelBase + x) + normalDataOffset];
+}
+
+BLI_INLINE void *ccg_face_getIECo(CCGFace *f, int lvl, int S, int x, int levels, int dataSize)
+{
+ int maxGridSize = ccg_gridsize(levels);
+ int spacing = ccg_spacing(levels, lvl);
+ byte *gridBase = FACE_getCenterData(f) + dataSize * (1 + S * (maxGridSize + maxGridSize * maxGridSize));
+ return &gridBase[dataSize * x * spacing];
+}
+
+BLI_INLINE void *ccg_face_getIENo(CCGFace *f, int lvl, int S, int x, int levels, int dataSize, int normalDataOffset)
+{
+ int maxGridSize = ccg_gridsize(levels);
+ int spacing = ccg_spacing(levels, lvl);
+ byte *gridBase = FACE_getCenterData(f) + dataSize * (1 + S * (maxGridSize + maxGridSize * maxGridSize));
+ return &gridBase[dataSize * x * spacing + normalDataOffset];
+}
+
+BLI_INLINE void *ccg_face_getIFCo(CCGFace *f, int lvl, int S, int x, int y, int levels, int dataSize)
+{
+ int maxGridSize = ccg_gridsize(levels);
+ int spacing = ccg_spacing(levels, lvl);
+ byte *gridBase = FACE_getCenterData(f) + dataSize * (1 + S * (maxGridSize + maxGridSize * maxGridSize));
+ return &gridBase[dataSize * (maxGridSize + (y * maxGridSize + x) * spacing)];
+}
+
+BLI_INLINE float *ccg_face_getIFNo(CCGFace *f, int lvl, int S, int x, int y, int levels, int dataSize, int normalDataOffset)
+{
+ int maxGridSize = ccg_gridsize(levels);
+ int spacing = ccg_spacing(levels, lvl);
+ byte *gridBase = FACE_getCenterData(f) + dataSize * (1 + S * (maxGridSize + maxGridSize * maxGridSize));
+ return (float *) &gridBase[dataSize * (maxGridSize + (y * maxGridSize + x) * spacing) + normalDataOffset];
+}
+
+
+BLI_INLINE int ccg_face_getVertIndex(CCGFace *f, CCGVert *v)
+{
+ int i;
+ for (i = 0; i < f->numVerts; i++)
+ if (FACE_getVerts(f)[i] == v)
+ return i;
+ return -1;
+}
+
+BLI_INLINE int ccg_face_getEdgeIndex(CCGFace *f, CCGEdge *e)
+{
+ int i;
+ for (i = 0; i < f->numVerts; i++)
+ if (FACE_getEdges(f)[i] == e)
+ return i;
+ return -1;
+}
+
+BLI_INLINE void *ccg_face_getIFCoEdge(CCGFace *f, CCGEdge *e, int f_ed_idx, int lvl, int eX, int eY, int levels, int dataSize)
+{
+ int maxGridSize = ccg_gridsize(levels);
+ int spacing = ccg_spacing(levels, lvl);
+ int x, y, cx, cy;
+
+ BLI_assert(f_ed_idx == ccg_face_getEdgeIndex(f, e));
+
+ eX = eX * spacing;
+ eY = eY * spacing;
+ if (e->v0 != FACE_getVerts(f)[f_ed_idx]) {
+ eX = (maxGridSize * 2 - 1) - 1 - eX;
+ }
+ y = maxGridSize - 1 - eX;
+ x = maxGridSize - 1 - eY;
+ if (x < 0) {
+ f_ed_idx = (f_ed_idx + f->numVerts - 1) % f->numVerts;
+ cx = y;
+ cy = -x;
+ }
+ else if (y < 0) {
+ f_ed_idx = (f_ed_idx + 1) % f->numVerts;
+ cx = -y;
+ cy = x;
+ }
+ else {
+ cx = x;
+ cy = y;
+ }
+ return ccg_face_getIFCo(f, levels, f_ed_idx, cx, cy, levels, dataSize);
+}
+
+BLI_INLINE void Normalize(float no[3])
+{
+ const float length = sqrtf(no[0] * no[0] + no[1] * no[1] + no[2] * no[2]);
+
+ if (length > EPSILON) {
+ const float length_inv = 1.0f / length;
+
+ no[0] *= length_inv;
+ no[1] *= length_inv;
+ no[2] *= length_inv;
+ }
+ else {
+ NormZero(no);
+ }
+}
+
+/* Data layers mathematics. */
+
+BLI_INLINE int VertDataEqual(const float a[], const float b[], const CCGSubSurf *ss)
+{
+ int i;
+ for (i = 0; i < ss->meshIFC.numLayers; i++) {
+ if (a[i] != b[i])
+ return 0;
+ }
+ return 1;
+}
+
+BLI_INLINE void VertDataZero(float v[], const CCGSubSurf *ss)
+{
+ memset(v, 0, sizeof(float) * ss->meshIFC.numLayers);
+}
+
+BLI_INLINE void VertDataCopy(float dst[], const float src[], const CCGSubSurf *ss)
+{
+ int i;
+ for (i = 0; i < ss->meshIFC.numLayers; i++)
+ dst[i] = src[i];
+}
+
+BLI_INLINE void VertDataAdd(float a[], const float b[], const CCGSubSurf *ss)
+{
+ int i;
+ for (i = 0; i < ss->meshIFC.numLayers; i++)
+ a[i] += b[i];
+}
+
+BLI_INLINE void VertDataSub(float a[], const float b[], const CCGSubSurf *ss)
+{
+ int i;
+ for (i = 0; i < ss->meshIFC.numLayers; i++)
+ a[i] -= b[i];
+}
+
+BLI_INLINE void VertDataMulN(float v[], float f, const CCGSubSurf *ss)
+{
+ int i;
+ for (i = 0; i < ss->meshIFC.numLayers; i++)
+ v[i] *= f;
+}
+
+BLI_INLINE void VertDataAvg4(float v[],
+ const float a[], const float b[],
+ const float c[], const float d[],
+ const CCGSubSurf *ss)
+{
+ int i;
+ for (i = 0; i < ss->meshIFC.numLayers; i++)
+ v[i] = (a[i] + b[i] + c[i] + d[i]) * 0.25f;
+}
+
+#endif /* __CCGSUBSURF_INLINE_H__ */
diff --git a/source/blender/blenkernel/intern/CCGSubSurf_intern.h b/source/blender/blenkernel/intern/CCGSubSurf_intern.h
new file mode 100644
index 00000000000..e2b42065382
--- /dev/null
+++ b/source/blender/blenkernel/intern/CCGSubSurf_intern.h
@@ -0,0 +1,330 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/blenkernel/intern/CCGSubSurf_intern.h
+ * \ingroup bke
+ */
+
+#ifndef __CCGSUBSURF_INTERN_H__
+#define __CCGSUBSURF_INTERN_H__
+
+/**
+ * Definitions which defines internal behavior of CCGSubSurf.
+ */
+
+/* Define this to see dump of the grids after the subsurf applied. */
+#undef DUMP_RESULT_GRIDS
+
+/* used for normalize_v3 in BLI_math_vector
+ * float.h's FLT_EPSILON causes trouble with subsurf normals - campbell */
+#define EPSILON (1.0e-35f)
+
+/* With this limit a single triangle becomes over 3 million faces */
+#define CCGSUBSURF_LEVEL_MAX 11
+
+/**
+ * Common type definitions.
+ */
+
+typedef unsigned char byte;
+
+/**
+ * Hash implementation.
+ */
+
+typedef struct _EHEntry {
+ struct _EHEntry *next;
+ void *key;
+} EHEntry;
+
+typedef struct _EHash {
+ EHEntry **buckets;
+ int numEntries, curSize, curSizeIdx;
+
+ CCGAllocatorIFC allocatorIFC;
+ CCGAllocatorHDL allocator;
+} EHash;
+
+typedef void (*EHEntryFreeFP)(EHEntry *, void *);
+
+#define EHASH_alloc(eh, nb) ((eh)->allocatorIFC.alloc((eh)->allocator, nb))
+#define EHASH_free(eh, ptr) ((eh)->allocatorIFC.free((eh)->allocator, ptr))
+#define EHASH_hash(eh, item) (((uintptr_t) (item)) % ((unsigned int) (eh)->curSize))
+
+/* Generic hash functions. */
+
+EHash *ccg_ehash_new(int estimatedNumEntries,
+ CCGAllocatorIFC *allocatorIFC,
+ CCGAllocatorHDL allocator);
+void ccg_ehash_free(EHash *eh, EHEntryFreeFP freeEntry, void *userData);
+void ccg_ehash_insert(EHash *eh, EHEntry *entry);
+void *ccg_ehash_lookupWithPrev(EHash *eh, void *key, void ***prevp_r);
+void *ccg_ehash_lookup(EHash *eh, void *key);
+
+/* Hash elements iteration. */
+
+void ccg_ehashIterator_init(EHash *eh, EHashIterator *ehi);
+void *ccg_ehashIterator_getCurrent(EHashIterator *ehi);
+void ccg_ehashIterator_next(EHashIterator *ehi);
+int ccg_ehashIterator_isStopped(EHashIterator *ehi);
+
+/**
+ * Standard allocator implementarion.
+ */
+
+CCGAllocatorIFC *ccg_getStandardAllocatorIFC(void);
+
+/**
+ * Catmull-Clark Gridding Subdivision Surface.
+ */
+
+/* TODO(sergey): Get rid of this, it's more or less a bad level call. */
+struct DerivedMesh;
+
+/* ** Data structures, constants. enums ** */
+
+enum {
+ Vert_eEffected = (1 << 0),
+ Vert_eChanged = (1 << 1),
+ Vert_eSeam = (1 << 2)
+} /*VertFlags*/;
+
+enum {
+ Edge_eEffected = (1 << 0)
+} /*CCGEdgeFlags*/;
+
+enum {
+ Face_eEffected = (1 << 0)
+} /*FaceFlags*/;
+
+struct CCGVert {
+ CCGVert *next; /* EHData.next */
+ CCGVertHDL vHDL; /* EHData.key */
+
+ short numEdges, numFaces, flags;
+ int osd_index; /* Index of the vertex in the map, used by OSD. */
+
+ CCGEdge **edges;
+ CCGFace **faces;
+ /* byte *levelData; */
+ /* byte *userData; */
+};
+
+struct CCGEdge {
+ CCGEdge *next; /* EHData.next */
+ CCGEdgeHDL eHDL; /* EHData.key */
+
+ short numFaces, flags;
+ float crease;
+
+ CCGVert *v0, *v1;
+ CCGFace **faces;
+
+ /* byte *levelData; */
+ /* byte *userData; */
+};
+
+struct CCGFace {
+ CCGFace *next; /* EHData.next */
+ CCGFaceHDL fHDL; /* EHData.key */
+
+ short numVerts, flags;
+ int osd_index;
+
+ /* CCGVert **verts; */
+ /* CCGEdge **edges; */
+ /* byte *centerData; */
+ /* byte **gridData; */
+ /* byte *userData; */
+};
+
+typedef enum {
+ eSyncState_None = 0,
+ eSyncState_Vert,
+ eSyncState_Edge,
+ eSyncState_Face,
+ eSyncState_Partial,
+#ifdef WITH_OPENSUBDIV
+ eSyncState_OpenSubdiv,
+#endif
+} SyncState;
+
+struct CCGSubSurf {
+ EHash *vMap; /* map of CCGVertHDL -> Vert */
+ EHash *eMap; /* map of CCGEdgeHDL -> Edge */
+ EHash *fMap; /* map of CCGFaceHDL -> Face */
+
+ CCGMeshIFC meshIFC;
+
+ CCGAllocatorIFC allocatorIFC;
+ CCGAllocatorHDL allocator;
+
+ int subdivLevels;
+ int numGrids;
+ int allowEdgeCreation;
+ float defaultCreaseValue;
+ void *defaultEdgeUserData;
+
+ void *q, *r;
+
+ /* Data for calc vert normals. */
+ int calcVertNormals;
+ int normalDataOffset;
+
+ /* Data for paint masks. */
+ int allocMask;
+ int maskDataOffset;
+
+ /* Data for age'ing (to debug sync). */
+ int currentAge;
+ int useAgeCounts;
+ int vertUserAgeOffset;
+ int edgeUserAgeOffset;
+ int faceUserAgeOffset;
+
+ /* Data used during syncing. */
+ SyncState syncState;
+
+ EHash *oldVMap, *oldEMap, *oldFMap;
+ int lenTempArrays;
+ CCGVert **tempVerts;
+ CCGEdge **tempEdges;
+
+#ifdef WITH_OPENSUBDIV
+ /* Skip grids means no CCG geometry is created and subsurf is possible
+ * to be completely done on GPU.
+ */
+ bool skip_grids;
+
+ /* ** GPU backend. ** */
+
+ /* Compute device used by GL mesh. */
+ short osd_compute;
+ /* Coarse (base mesh) vertex coordinates.
+ *
+ * Filled in from the modifier stack and passed to OpenSubdiv compute
+ * on mesh display.
+ */
+ float (*osd_coarse_coords)[3];
+ int osd_num_coarse_coords;
+ /* Denotes whether coarse positions in the GL mesh are invalid.
+ * Used to avoid updating GL mesh coords on every redraw.
+ */
+ bool osd_coarse_coords_invalid;
+
+ /* GL mesh descriptor, used for refinment and draw. */
+ struct OpenSubdiv_GLMesh *osd_mesh;
+ /* Refiner which is used to create GL mesh.
+ *
+ * Refiner is created from the modifier stack and used later from the main
+ * thread to construct GL mesh to avoid threaded access to GL.
+ */
+ struct OpenSubdiv_TopologyRefinerDescr *osd_topology_refiner; /* Only used at synchronization stage. */
+ /* Denotes whether osd_mesh is invalid now due to topology changes and needs
+ * to be reconstructed.
+ *
+ * Reconstruction happens from main thread due to OpenGL communication.
+ */
+ bool osd_mesh_invalid;
+ /* Vertex array used for osd_mesh draw. */
+ unsigned int osd_vao;
+
+ /* ** CPU backend. ** */
+
+ /* Limit evaluator, used to evaluate CCG. */
+ struct OpenSubdiv_EvaluatorDescr *osd_evaluator;
+ /* Next PTex face index, used while CCG synchronization
+ * to fill in PTex index of CCGFace.
+ */
+ int osd_next_face_ptex_index;
+
+ /* ** Needs review. ** */
+ bool osd_subsurf_uv;
+ int osd_uv_index;
+ bool osd_uvs_invalid;
+#endif
+};
+
+/* ** Utility macros ** */
+
+#define CCGSUBSURF_alloc(ss, nb) ((ss)->allocatorIFC.alloc((ss)->allocator, nb))
+#define CCGSUBSURF_realloc(ss, ptr, nb, ob) ((ss)->allocatorIFC.realloc((ss)->allocator, ptr, nb, ob))
+#define CCGSUBSURF_free(ss, ptr) ((ss)->allocatorIFC.free((ss)->allocator, ptr))
+
+#define VERT_getCo(v, lvl) ccg_vert_getCo(v, lvl, vertDataSize)
+#define VERT_getNo(v, lvl) ccg_vert_getNo(v, lvl, vertDataSize, normalDataOffset)
+#define EDGE_getCo(e, lvl, x) ccg_edge_getCo(e, lvl, x, vertDataSize)
+#define EDGE_getNo(e, lvl, x) ccg_edge_getNo(e, lvl, x, vertDataSize, normalDataOffset)
+#define FACE_getIFNo(f, lvl, S, x, y) ccg_face_getIFNo(f, lvl, S, x, y, subdivLevels, vertDataSize, normalDataOffset)
+//#define FACE_calcIFNo(f, lvl, S, x, y, no) _face_calcIFNo(f, lvl, S, x, y, no, subdivLevels, vertDataSize)
+#define FACE_getIENo(f, lvl, S, x) ccg_face_getIENo(f, lvl, S, x, subdivLevels, vertDataSize, normalDataOffset)
+#define FACE_getIECo(f, lvl, S, x) ccg_face_getIECo(f, lvl, S, x, subdivLevels, vertDataSize)
+#define FACE_getIFCo(f, lvl, S, x, y) ccg_face_getIFCo(f, lvl, S, x, y, subdivLevels, vertDataSize)
+
+#define NormZero(av) { float *_a = (float *) av; _a[0] = _a[1] = _a[2] = 0.0f; } (void)0
+#define NormCopy(av, bv) { float *_a = (float *) av, *_b = (float *) bv; _a[0] = _b[0]; _a[1] = _b[1]; _a[2] = _b[2]; } (void)0
+#define NormAdd(av, bv) { float *_a = (float *) av, *_b = (float *) bv; _a[0] += _b[0]; _a[1] += _b[1]; _a[2] += _b[2]; } (void)0
+
+/* ** General purpose functions ** */
+
+/* * CCGSubSurf.c * */
+
+void ccgSubSurf__allFaces(CCGSubSurf *ss, CCGFace ***faces, int *numFaces, int *freeFaces);
+void ccgSubSurf__effectedFaceNeighbours(CCGSubSurf *ss,
+ CCGFace **faces,
+ int numFaces,
+ CCGVert ***verts,
+ int *numVerts,
+ CCGEdge ***edges,
+ int *numEdges);
+
+/* * CCGSubSurf_legacy.c * */
+
+void ccgSubSurf__sync_legacy(CCGSubSurf *ss);
+
+/* * CCGSubSurf_opensubdiv.c * */
+
+void ccgSubSurf__sync_opensubdiv(CCGSubSurf *ss);
+
+/* * CCGSubSurf_opensubdiv_converter.c * */
+
+struct OpenSubdiv_Converter;
+
+void ccgSubSurf_converter_setup_from_derivedmesh(
+ CCGSubSurf *ss,
+ struct DerivedMesh *dm,
+ struct OpenSubdiv_Converter *converter);
+
+void ccgSubSurf_converter_setup_from_ccg(
+ CCGSubSurf *ss,
+ struct OpenSubdiv_Converter *converter);
+
+void ccgSubSurf_converter_free(
+ struct OpenSubdiv_Converter *converter);
+
+/* * CCGSubSurf_util.c * */
+
+#ifdef DUMP_RESULT_GRIDS
+void ccgSubSurf__dumpCoords(CCGSubSurf *ss);
+#endif
+
+#include "CCGSubSurf_inline.h"
+
+#endif /* __CCGSUBSURF_INTERN_H__ */
diff --git a/source/blender/blenkernel/intern/CCGSubSurf_legacy.c b/source/blender/blenkernel/intern/CCGSubSurf_legacy.c
new file mode 100644
index 00000000000..6adef1ca729
--- /dev/null
+++ b/source/blender/blenkernel/intern/CCGSubSurf_legacy.c
@@ -0,0 +1,1180 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/blenkernel/intern/CCGSubSurf_legacy.c
+ * \ingroup bke
+ */
+
+#include "MEM_guardedalloc.h"
+#include "BLI_sys_types.h" // for intptr_t support
+
+#include "BLI_utildefines.h" /* for BLI_assert */
+#include "BLI_math.h"
+
+#include "CCGSubSurf.h"
+#include "CCGSubSurf_intern.h"
+
+#define FACE_calcIFNo(f, lvl, S, x, y, no) _face_calcIFNo(f, lvl, S, x, y, no, subdivLevels, vertDataSize)
+
+/* TODO(sergey): Deduplicate the following functions/ */
+static void *_edge_getCoVert(CCGEdge *e, CCGVert *v, int lvl, int x, int dataSize)
+{
+ int levelBase = ccg_edgebase(lvl);
+ if (v == e->v0) {
+ return &EDGE_getLevelData(e)[dataSize * (levelBase + x)];
+ }
+ else {
+ return &EDGE_getLevelData(e)[dataSize * (levelBase + (1 << lvl) - x)];
+ }
+}
+/* *************************************************** */
+
+static int _edge_isBoundary(const CCGEdge *e)
+{
+ return e->numFaces < 2;
+}
+
+static int _vert_isBoundary(const CCGVert *v)
+{
+ int i;
+ for (i = 0; i < v->numEdges; i++)
+ if (_edge_isBoundary(v->edges[i]))
+ return 1;
+ return 0;
+}
+
+static CCGVert *_edge_getOtherVert(CCGEdge *e, CCGVert *vQ)
+{
+ if (vQ == e->v0) {
+ return e->v1;
+ }
+ else {
+ return e->v0;
+ }
+}
+
+static float *_face_getIFNoEdge(CCGFace *f,
+ CCGEdge *e,
+ int f_ed_idx,
+ int lvl,
+ int eX, int eY,
+ int levels,
+ int dataSize,
+ int normalDataOffset)
+{
+ return (float *) ((byte *) ccg_face_getIFCoEdge(f, e, f_ed_idx, lvl, eX, eY, levels, dataSize) + normalDataOffset);
+}
+
+static void _face_calcIFNo(CCGFace *f,
+ int lvl,
+ int S,
+ int x, int y,
+ float no[3],
+ int levels,
+ int dataSize)
+{
+ float *a = ccg_face_getIFCo(f, lvl, S, x + 0, y + 0, levels, dataSize);
+ float *b = ccg_face_getIFCo(f, lvl, S, x + 1, y + 0, levels, dataSize);
+ float *c = ccg_face_getIFCo(f, lvl, S, x + 1, y + 1, levels, dataSize);
+ float *d = ccg_face_getIFCo(f, lvl, S, x + 0, y + 1, levels, dataSize);
+ float a_cX = c[0] - a[0], a_cY = c[1] - a[1], a_cZ = c[2] - a[2];
+ float b_dX = d[0] - b[0], b_dY = d[1] - b[1], b_dZ = d[2] - b[2];
+
+ no[0] = b_dY * a_cZ - b_dZ * a_cY;
+ no[1] = b_dZ * a_cX - b_dX * a_cZ;
+ no[2] = b_dX * a_cY - b_dY * a_cX;
+
+ Normalize(no);
+}
+
+static int VERT_seam(const CCGVert *v)
+{
+ return ((v->flags & Vert_eSeam) != 0);
+}
+
+static float EDGE_getSharpness(CCGEdge *e, int lvl)
+{
+ if (!lvl)
+ return e->crease;
+ else if (!e->crease)
+ return 0.0f;
+ else if (e->crease - lvl < 0.0f)
+ return 0.0f;
+ else
+ return e->crease - lvl;
+}
+
+static void ccgSubSurf__calcVertNormals(CCGSubSurf *ss,
+ CCGVert **effectedV, CCGEdge **effectedE, CCGFace **effectedF,
+ int numEffectedV, int numEffectedE, int numEffectedF)
+{
+ int i, ptrIdx;
+ int subdivLevels = ss->subdivLevels;
+ int lvl = ss->subdivLevels;
+ int edgeSize = ccg_edgesize(lvl);
+ int gridSize = ccg_gridsize(lvl);
+ int normalDataOffset = ss->normalDataOffset;
+ int vertDataSize = ss->meshIFC.vertDataSize;
+
+#pragma omp parallel for private(ptrIdx) if (numEffectedF * edgeSize * edgeSize * 4 >= CCG_OMP_LIMIT)
+ for (ptrIdx = 0; ptrIdx < numEffectedF; ptrIdx++) {
+ CCGFace *f = (CCGFace *) effectedF[ptrIdx];
+ int S, x, y;
+ float no[3];
+
+ for (S = 0; S < f->numVerts; S++) {
+ for (y = 0; y < gridSize - 1; y++) {
+ for (x = 0; x < gridSize - 1; x++) {
+ NormZero(FACE_getIFNo(f, lvl, S, x, y));
+ }
+ }
+
+ if (FACE_getEdges(f)[(S - 1 + f->numVerts) % f->numVerts]->flags & Edge_eEffected) {
+ for (x = 0; x < gridSize - 1; x++) {
+ NormZero(FACE_getIFNo(f, lvl, S, x, gridSize - 1));
+ }
+ }
+ if (FACE_getEdges(f)[S]->flags & Edge_eEffected) {
+ for (y = 0; y < gridSize - 1; y++) {
+ NormZero(FACE_getIFNo(f, lvl, S, gridSize - 1, y));
+ }
+ }
+ if (FACE_getVerts(f)[S]->flags & Vert_eEffected) {
+ NormZero(FACE_getIFNo(f, lvl, S, gridSize - 1, gridSize - 1));
+ }
+ }
+
+ for (S = 0; S < f->numVerts; S++) {
+ int yLimit = !(FACE_getEdges(f)[(S - 1 + f->numVerts) % f->numVerts]->flags & Edge_eEffected);
+ int xLimit = !(FACE_getEdges(f)[S]->flags & Edge_eEffected);
+ int yLimitNext = xLimit;
+ int xLimitPrev = yLimit;
+
+ for (y = 0; y < gridSize - 1; y++) {
+ for (x = 0; x < gridSize - 1; x++) {
+ int xPlusOk = (!xLimit || x < gridSize - 2);
+ int yPlusOk = (!yLimit || y < gridSize - 2);
+
+ FACE_calcIFNo(f, lvl, S, x, y, no);
+
+ NormAdd(FACE_getIFNo(f, lvl, S, x + 0, y + 0), no);
+ if (xPlusOk)
+ NormAdd(FACE_getIFNo(f, lvl, S, x + 1, y + 0), no);
+ if (yPlusOk)
+ NormAdd(FACE_getIFNo(f, lvl, S, x + 0, y + 1), no);
+ if (xPlusOk && yPlusOk) {
+ if (x < gridSize - 2 || y < gridSize - 2 || FACE_getVerts(f)[S]->flags & Vert_eEffected) {
+ NormAdd(FACE_getIFNo(f, lvl, S, x + 1, y + 1), no);
+ }
+ }
+
+ if (x == 0 && y == 0) {
+ int K;
+
+ if (!yLimitNext || 1 < gridSize - 1)
+ NormAdd(FACE_getIFNo(f, lvl, (S + 1) % f->numVerts, 0, 1), no);
+ if (!xLimitPrev || 1 < gridSize - 1)
+ NormAdd(FACE_getIFNo(f, lvl, (S - 1 + f->numVerts) % f->numVerts, 1, 0), no);
+
+ for (K = 0; K < f->numVerts; K++) {
+ if (K != S) {
+ NormAdd(FACE_getIFNo(f, lvl, K, 0, 0), no);
+ }
+ }
+ }
+ else if (y == 0) {
+ NormAdd(FACE_getIFNo(f, lvl, (S + 1) % f->numVerts, 0, x), no);
+ if (!yLimitNext || x < gridSize - 2)
+ NormAdd(FACE_getIFNo(f, lvl, (S + 1) % f->numVerts, 0, x + 1), no);
+ }
+ else if (x == 0) {
+ NormAdd(FACE_getIFNo(f, lvl, (S - 1 + f->numVerts) % f->numVerts, y, 0), no);
+ if (!xLimitPrev || y < gridSize - 2)
+ NormAdd(FACE_getIFNo(f, lvl, (S - 1 + f->numVerts) % f->numVerts, y + 1, 0), no);
+ }
+ }
+ }
+ }
+ }
+ /* XXX can I reduce the number of normalisations here? */
+ for (ptrIdx = 0; ptrIdx < numEffectedV; ptrIdx++) {
+ CCGVert *v = (CCGVert *) effectedV[ptrIdx];
+ float *no = VERT_getNo(v, lvl);
+
+ NormZero(no);
+
+ for (i = 0; i < v->numFaces; i++) {
+ CCGFace *f = v->faces[i];
+ NormAdd(no, FACE_getIFNo(f, lvl, ccg_face_getVertIndex(f, v), gridSize - 1, gridSize - 1));
+ }
+
+ if (UNLIKELY(v->numFaces == 0)) {
+ NormCopy(no, VERT_getCo(v, lvl));
+ }
+
+ Normalize(no);
+
+ for (i = 0; i < v->numFaces; i++) {
+ CCGFace *f = v->faces[i];
+ NormCopy(FACE_getIFNo(f, lvl, ccg_face_getVertIndex(f, v), gridSize - 1, gridSize - 1), no);
+ }
+ }
+ for (ptrIdx = 0; ptrIdx < numEffectedE; ptrIdx++) {
+ CCGEdge *e = (CCGEdge *) effectedE[ptrIdx];
+
+ if (e->numFaces) {
+ CCGFace *fLast = e->faces[e->numFaces - 1];
+ int x;
+
+ for (i = 0; i < e->numFaces - 1; i++) {
+ CCGFace *f = e->faces[i];
+ const int f_ed_idx = ccg_face_getEdgeIndex(f, e);
+ const int f_ed_idx_last = ccg_face_getEdgeIndex(fLast, e);
+
+ for (x = 1; x < edgeSize - 1; x++) {
+ NormAdd(_face_getIFNoEdge(fLast, e, f_ed_idx_last, lvl, x, 0, subdivLevels, vertDataSize, normalDataOffset),
+ _face_getIFNoEdge(f, e, f_ed_idx, lvl, x, 0, subdivLevels, vertDataSize, normalDataOffset));
+ }
+ }
+
+ for (i = 0; i < e->numFaces - 1; i++) {
+ CCGFace *f = e->faces[i];
+ const int f_ed_idx = ccg_face_getEdgeIndex(f, e);
+ const int f_ed_idx_last = ccg_face_getEdgeIndex(fLast, e);
+
+ for (x = 1; x < edgeSize - 1; x++) {
+ NormCopy(_face_getIFNoEdge(f, e, f_ed_idx, lvl, x, 0, subdivLevels, vertDataSize, normalDataOffset),
+ _face_getIFNoEdge(fLast, e, f_ed_idx_last, lvl, x, 0, subdivLevels, vertDataSize, normalDataOffset));
+ }
+ }
+ }
+ }
+
+#pragma omp parallel for private(ptrIdx) if (numEffectedF * edgeSize * edgeSize * 4 >= CCG_OMP_LIMIT)
+ for (ptrIdx = 0; ptrIdx < numEffectedF; ptrIdx++) {
+ CCGFace *f = (CCGFace *) effectedF[ptrIdx];
+ int S, x, y;
+
+ for (S = 0; S < f->numVerts; S++) {
+ NormCopy(FACE_getIFNo(f, lvl, (S + 1) % f->numVerts, 0, gridSize - 1),
+ FACE_getIFNo(f, lvl, S, gridSize - 1, 0));
+ }
+
+ for (S = 0; S < f->numVerts; S++) {
+ for (y = 0; y < gridSize; y++) {
+ for (x = 0; x < gridSize; x++) {
+ float *no = FACE_getIFNo(f, lvl, S, x, y);
+ Normalize(no);
+ }
+ }
+
+ VertDataCopy((float *)((byte *)FACE_getCenterData(f) + normalDataOffset),
+ FACE_getIFNo(f, lvl, S, 0, 0), ss);
+
+ for (x = 1; x < gridSize - 1; x++)
+ NormCopy(FACE_getIENo(f, lvl, S, x),
+ FACE_getIFNo(f, lvl, S, x, 0));
+ }
+ }
+
+ for (ptrIdx = 0; ptrIdx < numEffectedE; ptrIdx++) {
+ CCGEdge *e = (CCGEdge *) effectedE[ptrIdx];
+
+ if (e->numFaces) {
+ CCGFace *f = e->faces[0];
+ int x;
+ const int f_ed_idx = ccg_face_getEdgeIndex(f, e);
+
+ for (x = 0; x < edgeSize; x++)
+ NormCopy(EDGE_getNo(e, lvl, x),
+ _face_getIFNoEdge(f, e, f_ed_idx, lvl, x, 0, subdivLevels, vertDataSize, normalDataOffset));
+ }
+ else {
+ /* set to zero here otherwise the normals are uninitialized memory
+ * render: tests/animation/knight.blend with valgrind.
+ * we could be more clever and interpolate vertex normals but these are
+ * most likely not used so just zero out. */
+ int x;
+
+ for (x = 0; x < edgeSize; x++) {
+ float *no = EDGE_getNo(e, lvl, x);
+ NormCopy(no, EDGE_getCo(e, lvl, x));
+ Normalize(no);
+ }
+ }
+ }
+}
+
+static void ccgSubSurf__calcSubdivLevel(CCGSubSurf *ss,
+ CCGVert **effectedV, CCGEdge **effectedE, CCGFace **effectedF,
+ int numEffectedV, int numEffectedE, int numEffectedF, int curLvl)
+{
+ int subdivLevels = ss->subdivLevels;
+ int edgeSize = ccg_edgesize(curLvl);
+ int gridSize = ccg_gridsize(curLvl);
+ int nextLvl = curLvl + 1;
+ int ptrIdx, cornerIdx, i;
+ int vertDataSize = ss->meshIFC.vertDataSize;
+ float *q = ss->q, *r = ss->r;
+
+#pragma omp parallel for private(ptrIdx) if (numEffectedF * edgeSize * edgeSize * 4 >= CCG_OMP_LIMIT)
+ for (ptrIdx = 0; ptrIdx < numEffectedF; ptrIdx++) {
+ CCGFace *f = (CCGFace *) effectedF[ptrIdx];
+ int S, x, y;
+
+ /* interior face midpoints
+ * - old interior face points
+ */
+ for (S = 0; S < f->numVerts; S++) {
+ for (y = 0; y < gridSize - 1; y++) {
+ for (x = 0; x < gridSize - 1; x++) {
+ int fx = 1 + 2 * x;
+ int fy = 1 + 2 * y;
+ const float *co0 = FACE_getIFCo(f, curLvl, S, x + 0, y + 0);
+ const float *co1 = FACE_getIFCo(f, curLvl, S, x + 1, y + 0);
+ const float *co2 = FACE_getIFCo(f, curLvl, S, x + 1, y + 1);
+ const float *co3 = FACE_getIFCo(f, curLvl, S, x + 0, y + 1);
+ float *co = FACE_getIFCo(f, nextLvl, S, fx, fy);
+
+ VertDataAvg4(co, co0, co1, co2, co3, ss);
+ }
+ }
+ }
+
+ /* interior edge midpoints
+ * - old interior edge points
+ * - new interior face midpoints
+ */
+ for (S = 0; S < f->numVerts; S++) {
+ for (x = 0; x < gridSize - 1; x++) {
+ int fx = x * 2 + 1;
+ const float *co0 = FACE_getIECo(f, curLvl, S, x + 0);
+ const float *co1 = FACE_getIECo(f, curLvl, S, x + 1);
+ const float *co2 = FACE_getIFCo(f, nextLvl, (S + 1) % f->numVerts, 1, fx);
+ const float *co3 = FACE_getIFCo(f, nextLvl, S, fx, 1);
+ float *co = FACE_getIECo(f, nextLvl, S, fx);
+
+ VertDataAvg4(co, co0, co1, co2, co3, ss);
+ }
+
+ /* interior face interior edge midpoints
+ * - old interior face points
+ * - new interior face midpoints
+ */
+
+ /* vertical */
+ for (x = 1; x < gridSize - 1; x++) {
+ for (y = 0; y < gridSize - 1; y++) {
+ int fx = x * 2;
+ int fy = y * 2 + 1;
+ const float *co0 = FACE_getIFCo(f, curLvl, S, x, y + 0);
+ const float *co1 = FACE_getIFCo(f, curLvl, S, x, y + 1);
+ const float *co2 = FACE_getIFCo(f, nextLvl, S, fx - 1, fy);
+ const float *co3 = FACE_getIFCo(f, nextLvl, S, fx + 1, fy);
+ float *co = FACE_getIFCo(f, nextLvl, S, fx, fy);
+
+ VertDataAvg4(co, co0, co1, co2, co3, ss);
+ }
+ }
+
+ /* horizontal */
+ for (y = 1; y < gridSize - 1; y++) {
+ for (x = 0; x < gridSize - 1; x++) {
+ int fx = x * 2 + 1;
+ int fy = y * 2;
+ const float *co0 = FACE_getIFCo(f, curLvl, S, x + 0, y);
+ const float *co1 = FACE_getIFCo(f, curLvl, S, x + 1, y);
+ const float *co2 = FACE_getIFCo(f, nextLvl, S, fx, fy - 1);
+ const float *co3 = FACE_getIFCo(f, nextLvl, S, fx, fy + 1);
+ float *co = FACE_getIFCo(f, nextLvl, S, fx, fy);
+
+ VertDataAvg4(co, co0, co1, co2, co3, ss);
+ }
+ }
+ }
+ }
+
+ /* exterior edge midpoints
+ * - old exterior edge points
+ * - new interior face midpoints
+ */
+ for (ptrIdx = 0; ptrIdx < numEffectedE; ptrIdx++) {
+ CCGEdge *e = (CCGEdge *) effectedE[ptrIdx];
+ float sharpness = EDGE_getSharpness(e, curLvl);
+ int x, j;
+
+ if (_edge_isBoundary(e) || sharpness > 1.0f) {
+ for (x = 0; x < edgeSize - 1; x++) {
+ int fx = x * 2 + 1;
+ const float *co0 = EDGE_getCo(e, curLvl, x + 0);
+ const float *co1 = EDGE_getCo(e, curLvl, x + 1);
+ float *co = EDGE_getCo(e, nextLvl, fx);
+
+ VertDataCopy(co, co0, ss);
+ VertDataAdd(co, co1, ss);
+ VertDataMulN(co, 0.5f, ss);
+ }
+ }
+ else {
+ for (x = 0; x < edgeSize - 1; x++) {
+ int fx = x * 2 + 1;
+ const float *co0 = EDGE_getCo(e, curLvl, x + 0);
+ const float *co1 = EDGE_getCo(e, curLvl, x + 1);
+ float *co = EDGE_getCo(e, nextLvl, fx);
+ int numFaces = 0;
+
+ VertDataCopy(q, co0, ss);
+ VertDataAdd(q, co1, ss);
+
+ for (j = 0; j < e->numFaces; j++) {
+ CCGFace *f = e->faces[j];
+ const int f_ed_idx = ccg_face_getEdgeIndex(f, e);
+ VertDataAdd(q, ccg_face_getIFCoEdge(f, e, f_ed_idx, nextLvl, fx, 1, subdivLevels, vertDataSize), ss);
+ numFaces++;
+ }
+
+ VertDataMulN(q, 1.0f / (2.0f + numFaces), ss);
+
+ VertDataCopy(r, co0, ss);
+ VertDataAdd(r, co1, ss);
+ VertDataMulN(r, 0.5f, ss);
+
+ VertDataCopy(co, q, ss);
+ VertDataSub(r, q, ss);
+ VertDataMulN(r, sharpness, ss);
+ VertDataAdd(co, r, ss);
+ }
+ }
+ }
+
+ /* exterior vertex shift
+ * - old vertex points (shifting)
+ * - old exterior edge points
+ * - new interior face midpoints
+ */
+ for (ptrIdx = 0; ptrIdx < numEffectedV; ptrIdx++) {
+ CCGVert *v = (CCGVert *) effectedV[ptrIdx];
+ const float *co = VERT_getCo(v, curLvl);
+ float *nCo = VERT_getCo(v, nextLvl);
+ int sharpCount = 0, allSharp = 1;
+ float avgSharpness = 0.0;
+ int j, seam = VERT_seam(v), seamEdges = 0;
+
+ for (j = 0; j < v->numEdges; j++) {
+ CCGEdge *e = v->edges[j];
+ float sharpness = EDGE_getSharpness(e, curLvl);
+
+ if (seam && _edge_isBoundary(e))
+ seamEdges++;
+
+ if (sharpness != 0.0f) {
+ sharpCount++;
+ avgSharpness += sharpness;
+ }
+ else {
+ allSharp = 0;
+ }
+ }
+
+ if (sharpCount) {
+ avgSharpness /= sharpCount;
+ if (avgSharpness > 1.0f) {
+ avgSharpness = 1.0f;
+ }
+ }
+
+ if (seamEdges < 2 || seamEdges != v->numEdges)
+ seam = 0;
+
+ if (!v->numEdges || ss->meshIFC.simpleSubdiv) {
+ VertDataCopy(nCo, co, ss);
+ }
+ else if (_vert_isBoundary(v)) {
+ int numBoundary = 0;
+
+ VertDataZero(r, ss);
+ for (j = 0; j < v->numEdges; j++) {
+ CCGEdge *e = v->edges[j];
+ if (_edge_isBoundary(e)) {
+ VertDataAdd(r, _edge_getCoVert(e, v, curLvl, 1, vertDataSize), ss);
+ numBoundary++;
+ }
+ }
+
+ VertDataCopy(nCo, co, ss);
+ VertDataMulN(nCo, 0.75f, ss);
+ VertDataMulN(r, 0.25f / numBoundary, ss);
+ VertDataAdd(nCo, r, ss);
+ }
+ else {
+ int cornerIdx = (1 + (1 << (curLvl))) - 2;
+ int numEdges = 0, numFaces = 0;
+
+ VertDataZero(q, ss);
+ for (j = 0; j < v->numFaces; j++) {
+ CCGFace *f = v->faces[j];
+ VertDataAdd(q, FACE_getIFCo(f, nextLvl, ccg_face_getVertIndex(f, v), cornerIdx, cornerIdx), ss);
+ numFaces++;
+ }
+ VertDataMulN(q, 1.0f / numFaces, ss);
+ VertDataZero(r, ss);
+ for (j = 0; j < v->numEdges; j++) {
+ CCGEdge *e = v->edges[j];
+ VertDataAdd(r, _edge_getCoVert(e, v, curLvl, 1, vertDataSize), ss);
+ numEdges++;
+ }
+ VertDataMulN(r, 1.0f / numEdges, ss);
+
+ VertDataCopy(nCo, co, ss);
+ VertDataMulN(nCo, numEdges - 2.0f, ss);
+ VertDataAdd(nCo, q, ss);
+ VertDataAdd(nCo, r, ss);
+ VertDataMulN(nCo, 1.0f / numEdges, ss);
+ }
+
+ if ((sharpCount > 1 && v->numFaces) || seam) {
+ VertDataZero(q, ss);
+
+ if (seam) {
+ avgSharpness = 1.0f;
+ sharpCount = seamEdges;
+ allSharp = 1;
+ }
+
+ for (j = 0; j < v->numEdges; j++) {
+ CCGEdge *e = v->edges[j];
+ float sharpness = EDGE_getSharpness(e, curLvl);
+
+ if (seam) {
+ if (_edge_isBoundary(e))
+ VertDataAdd(q, _edge_getCoVert(e, v, curLvl, 1, vertDataSize), ss);
+ }
+ else if (sharpness != 0.0f) {
+ VertDataAdd(q, _edge_getCoVert(e, v, curLvl, 1, vertDataSize), ss);
+ }
+ }
+
+ VertDataMulN(q, (float) 1 / sharpCount, ss);
+
+ if (sharpCount != 2 || allSharp) {
+ /* q = q + (co - q) * avgSharpness */
+ VertDataCopy(r, co, ss);
+ VertDataSub(r, q, ss);
+ VertDataMulN(r, avgSharpness, ss);
+ VertDataAdd(q, r, ss);
+ }
+
+ /* r = co * 0.75 + q * 0.25 */
+ VertDataCopy(r, co, ss);
+ VertDataMulN(r, 0.75f, ss);
+ VertDataMulN(q, 0.25f, ss);
+ VertDataAdd(r, q, ss);
+
+ /* nCo = nCo + (r - nCo) * avgSharpness */
+ VertDataSub(r, nCo, ss);
+ VertDataMulN(r, avgSharpness, ss);
+ VertDataAdd(nCo, r, ss);
+ }
+ }
+
+ /* exterior edge interior shift
+ * - old exterior edge midpoints (shifting)
+ * - old exterior edge midpoints
+ * - new interior face midpoints
+ */
+ for (ptrIdx = 0; ptrIdx < numEffectedE; ptrIdx++) {
+ CCGEdge *e = (CCGEdge *) effectedE[ptrIdx];
+ float sharpness = EDGE_getSharpness(e, curLvl);
+ int sharpCount = 0;
+ float avgSharpness = 0.0;
+ int x, j;
+
+ if (sharpness != 0.0f) {
+ sharpCount = 2;
+ avgSharpness += sharpness;
+
+ if (avgSharpness > 1.0f) {
+ avgSharpness = 1.0f;
+ }
+ }
+ else {
+ sharpCount = 0;
+ avgSharpness = 0;
+ }
+
+ if (_edge_isBoundary(e)) {
+ for (x = 1; x < edgeSize - 1; x++) {
+ int fx = x * 2;
+ const float *co = EDGE_getCo(e, curLvl, x);
+ float *nCo = EDGE_getCo(e, nextLvl, fx);
+
+ /* Average previous level's endpoints */
+ VertDataCopy(r, EDGE_getCo(e, curLvl, x - 1), ss);
+ VertDataAdd(r, EDGE_getCo(e, curLvl, x + 1), ss);
+ VertDataMulN(r, 0.5f, ss);
+
+ /* nCo = nCo * 0.75 + r * 0.25 */
+ VertDataCopy(nCo, co, ss);
+ VertDataMulN(nCo, 0.75f, ss);
+ VertDataMulN(r, 0.25f, ss);
+ VertDataAdd(nCo, r, ss);
+ }
+ }
+ else {
+ for (x = 1; x < edgeSize - 1; x++) {
+ int fx = x * 2;
+ const float *co = EDGE_getCo(e, curLvl, x);
+ float *nCo = EDGE_getCo(e, nextLvl, fx);
+ int numFaces = 0;
+
+ VertDataZero(q, ss);
+ VertDataZero(r, ss);
+ VertDataAdd(r, EDGE_getCo(e, curLvl, x - 1), ss);
+ VertDataAdd(r, EDGE_getCo(e, curLvl, x + 1), ss);
+ for (j = 0; j < e->numFaces; j++) {
+ CCGFace *f = e->faces[j];
+ int f_ed_idx = ccg_face_getEdgeIndex(f, e);
+ VertDataAdd(q, ccg_face_getIFCoEdge(f, e, f_ed_idx, nextLvl, fx - 1, 1, subdivLevels, vertDataSize), ss);
+ VertDataAdd(q, ccg_face_getIFCoEdge(f, e, f_ed_idx, nextLvl, fx + 1, 1, subdivLevels, vertDataSize), ss);
+
+ VertDataAdd(r, ccg_face_getIFCoEdge(f, e, f_ed_idx, curLvl, x, 1, subdivLevels, vertDataSize), ss);
+ numFaces++;
+ }
+ VertDataMulN(q, 1.0f / (numFaces * 2.0f), ss);
+ VertDataMulN(r, 1.0f / (2.0f + numFaces), ss);
+
+ VertDataCopy(nCo, co, ss);
+ VertDataMulN(nCo, (float) numFaces, ss);
+ VertDataAdd(nCo, q, ss);
+ VertDataAdd(nCo, r, ss);
+ VertDataMulN(nCo, 1.0f / (2 + numFaces), ss);
+
+ if (sharpCount == 2) {
+ VertDataCopy(q, co, ss);
+ VertDataMulN(q, 6.0f, ss);
+ VertDataAdd(q, EDGE_getCo(e, curLvl, x - 1), ss);
+ VertDataAdd(q, EDGE_getCo(e, curLvl, x + 1), ss);
+ VertDataMulN(q, 1 / 8.0f, ss);
+
+ VertDataSub(q, nCo, ss);
+ VertDataMulN(q, avgSharpness, ss);
+ VertDataAdd(nCo, q, ss);
+ }
+ }
+ }
+ }
+
+#pragma omp parallel private(ptrIdx) if (numEffectedF * edgeSize * edgeSize * 4 >= CCG_OMP_LIMIT)
+ {
+ float *q, *r;
+
+#pragma omp critical
+ {
+ q = MEM_mallocN(ss->meshIFC.vertDataSize, "CCGSubsurf q");
+ r = MEM_mallocN(ss->meshIFC.vertDataSize, "CCGSubsurf r");
+ }
+
+#pragma omp for schedule(static)
+ for (ptrIdx = 0; ptrIdx < numEffectedF; ptrIdx++) {
+ CCGFace *f = (CCGFace *) effectedF[ptrIdx];
+ int S, x, y;
+
+ /* interior center point shift
+ * - old face center point (shifting)
+ * - old interior edge points
+ * - new interior face midpoints
+ */
+ VertDataZero(q, ss);
+ for (S = 0; S < f->numVerts; S++) {
+ VertDataAdd(q, FACE_getIFCo(f, nextLvl, S, 1, 1), ss);
+ }
+ VertDataMulN(q, 1.0f / f->numVerts, ss);
+ VertDataZero(r, ss);
+ for (S = 0; S < f->numVerts; S++) {
+ VertDataAdd(r, FACE_getIECo(f, curLvl, S, 1), ss);
+ }
+ VertDataMulN(r, 1.0f / f->numVerts, ss);
+
+ VertDataMulN((float *)FACE_getCenterData(f), f->numVerts - 2.0f, ss);
+ VertDataAdd((float *)FACE_getCenterData(f), q, ss);
+ VertDataAdd((float *)FACE_getCenterData(f), r, ss);
+ VertDataMulN((float *)FACE_getCenterData(f), 1.0f / f->numVerts, ss);
+
+ for (S = 0; S < f->numVerts; S++) {
+ /* interior face shift
+ * - old interior face point (shifting)
+ * - new interior edge midpoints
+ * - new interior face midpoints
+ */
+ for (x = 1; x < gridSize - 1; x++) {
+ for (y = 1; y < gridSize - 1; y++) {
+ int fx = x * 2;
+ int fy = y * 2;
+ const float *co = FACE_getIFCo(f, curLvl, S, x, y);
+ float *nCo = FACE_getIFCo(f, nextLvl, S, fx, fy);
+
+ VertDataAvg4(q,
+ FACE_getIFCo(f, nextLvl, S, fx - 1, fy - 1),
+ FACE_getIFCo(f, nextLvl, S, fx + 1, fy - 1),
+ FACE_getIFCo(f, nextLvl, S, fx + 1, fy + 1),
+ FACE_getIFCo(f, nextLvl, S, fx - 1, fy + 1),
+ ss);
+
+ VertDataAvg4(r,
+ FACE_getIFCo(f, nextLvl, S, fx - 1, fy + 0),
+ FACE_getIFCo(f, nextLvl, S, fx + 1, fy + 0),
+ FACE_getIFCo(f, nextLvl, S, fx + 0, fy - 1),
+ FACE_getIFCo(f, nextLvl, S, fx + 0, fy + 1),
+ ss);
+
+ VertDataCopy(nCo, co, ss);
+ VertDataSub(nCo, q, ss);
+ VertDataMulN(nCo, 0.25f, ss);
+ VertDataAdd(nCo, r, ss);
+ }
+ }
+
+ /* interior edge interior shift
+ * - old interior edge point (shifting)
+ * - new interior edge midpoints
+ * - new interior face midpoints
+ */
+ for (x = 1; x < gridSize - 1; x++) {
+ int fx = x * 2;
+ const float *co = FACE_getIECo(f, curLvl, S, x);
+ float *nCo = FACE_getIECo(f, nextLvl, S, fx);
+
+ VertDataAvg4(q,
+ FACE_getIFCo(f, nextLvl, (S + 1) % f->numVerts, 1, fx - 1),
+ FACE_getIFCo(f, nextLvl, (S + 1) % f->numVerts, 1, fx + 1),
+ FACE_getIFCo(f, nextLvl, S, fx + 1, +1),
+ FACE_getIFCo(f, nextLvl, S, fx - 1, +1), ss);
+
+ VertDataAvg4(r,
+ FACE_getIECo(f, nextLvl, S, fx - 1),
+ FACE_getIECo(f, nextLvl, S, fx + 1),
+ FACE_getIFCo(f, nextLvl, (S + 1) % f->numVerts, 1, fx),
+ FACE_getIFCo(f, nextLvl, S, fx, 1),
+ ss);
+
+ VertDataCopy(nCo, co, ss);
+ VertDataSub(nCo, q, ss);
+ VertDataMulN(nCo, 0.25f, ss);
+ VertDataAdd(nCo, r, ss);
+ }
+ }
+ }
+
+#pragma omp critical
+ {
+ MEM_freeN(q);
+ MEM_freeN(r);
+ }
+ }
+
+ /* copy down */
+ edgeSize = ccg_edgesize(nextLvl);
+ gridSize = ccg_gridsize(nextLvl);
+ cornerIdx = gridSize - 1;
+
+#pragma omp parallel for private(i) if (numEffectedF * edgeSize * edgeSize * 4 >= CCG_OMP_LIMIT)
+ for (i = 0; i < numEffectedE; i++) {
+ CCGEdge *e = effectedE[i];
+ VertDataCopy(EDGE_getCo(e, nextLvl, 0), VERT_getCo(e->v0, nextLvl), ss);
+ VertDataCopy(EDGE_getCo(e, nextLvl, edgeSize - 1), VERT_getCo(e->v1, nextLvl), ss);
+ }
+
+#pragma omp parallel for private(i) if (numEffectedF * edgeSize * edgeSize * 4 >= CCG_OMP_LIMIT)
+ for (i = 0; i < numEffectedF; i++) {
+ CCGFace *f = effectedF[i];
+ int S, x;
+
+ for (S = 0; S < f->numVerts; S++) {
+ CCGEdge *e = FACE_getEdges(f)[S];
+ CCGEdge *prevE = FACE_getEdges(f)[(S + f->numVerts - 1) % f->numVerts];
+
+ VertDataCopy(FACE_getIFCo(f, nextLvl, S, 0, 0), (float *)FACE_getCenterData(f), ss);
+ VertDataCopy(FACE_getIECo(f, nextLvl, S, 0), (float *)FACE_getCenterData(f), ss);
+ VertDataCopy(FACE_getIFCo(f, nextLvl, S, cornerIdx, cornerIdx), VERT_getCo(FACE_getVerts(f)[S], nextLvl), ss);
+ VertDataCopy(FACE_getIECo(f, nextLvl, S, cornerIdx), EDGE_getCo(FACE_getEdges(f)[S], nextLvl, cornerIdx), ss);
+ for (x = 1; x < gridSize - 1; x++) {
+ float *co = FACE_getIECo(f, nextLvl, S, x);
+ VertDataCopy(FACE_getIFCo(f, nextLvl, S, x, 0), co, ss);
+ VertDataCopy(FACE_getIFCo(f, nextLvl, (S + 1) % f->numVerts, 0, x), co, ss);
+ }
+ for (x = 0; x < gridSize - 1; x++) {
+ int eI = gridSize - 1 - x;
+ VertDataCopy(FACE_getIFCo(f, nextLvl, S, cornerIdx, x), _edge_getCoVert(e, FACE_getVerts(f)[S], nextLvl, eI, vertDataSize), ss);
+ VertDataCopy(FACE_getIFCo(f, nextLvl, S, x, cornerIdx), _edge_getCoVert(prevE, FACE_getVerts(f)[S], nextLvl, eI, vertDataSize), ss);
+ }
+ }
+ }
+}
+
+void ccgSubSurf__sync_legacy(CCGSubSurf *ss)
+{
+ CCGVert **effectedV;
+ CCGEdge **effectedE;
+ CCGFace **effectedF;
+ int numEffectedV, numEffectedE, numEffectedF;
+ int subdivLevels = ss->subdivLevels;
+ int vertDataSize = ss->meshIFC.vertDataSize;
+ int i, j, ptrIdx, S;
+ int curLvl, nextLvl;
+ void *q = ss->q, *r = ss->r;
+
+ effectedV = MEM_mallocN(sizeof(*effectedV) * ss->vMap->numEntries, "CCGSubsurf effectedV");
+ effectedE = MEM_mallocN(sizeof(*effectedE) * ss->eMap->numEntries, "CCGSubsurf effectedE");
+ effectedF = MEM_mallocN(sizeof(*effectedF) * ss->fMap->numEntries, "CCGSubsurf effectedF");
+ numEffectedV = numEffectedE = numEffectedF = 0;
+ for (i = 0; i < ss->vMap->curSize; i++) {
+ CCGVert *v = (CCGVert *) ss->vMap->buckets[i];
+ for (; v; v = v->next) {
+ if (v->flags & Vert_eEffected) {
+ effectedV[numEffectedV++] = v;
+
+ for (j = 0; j < v->numEdges; j++) {
+ CCGEdge *e = v->edges[j];
+ if (!(e->flags & Edge_eEffected)) {
+ effectedE[numEffectedE++] = e;
+ e->flags |= Edge_eEffected;
+ }
+ }
+
+ for (j = 0; j < v->numFaces; j++) {
+ CCGFace *f = v->faces[j];
+ if (!(f->flags & Face_eEffected)) {
+ effectedF[numEffectedF++] = f;
+ f->flags |= Face_eEffected;
+ }
+ }
+ }
+ }
+ }
+
+ curLvl = 0;
+ nextLvl = curLvl + 1;
+
+ for (ptrIdx = 0; ptrIdx < numEffectedF; ptrIdx++) {
+ CCGFace *f = effectedF[ptrIdx];
+ void *co = FACE_getCenterData(f);
+ VertDataZero(co, ss);
+ for (i = 0; i < f->numVerts; i++) {
+ VertDataAdd(co, VERT_getCo(FACE_getVerts(f)[i], curLvl), ss);
+ }
+ VertDataMulN(co, 1.0f / f->numVerts, ss);
+
+ f->flags = 0;
+ }
+ for (ptrIdx = 0; ptrIdx < numEffectedE; ptrIdx++) {
+ CCGEdge *e = effectedE[ptrIdx];
+ void *co = EDGE_getCo(e, nextLvl, 1);
+ float sharpness = EDGE_getSharpness(e, curLvl);
+
+ if (_edge_isBoundary(e) || sharpness >= 1.0f) {
+ VertDataCopy(co, VERT_getCo(e->v0, curLvl), ss);
+ VertDataAdd(co, VERT_getCo(e->v1, curLvl), ss);
+ VertDataMulN(co, 0.5f, ss);
+ }
+ else {
+ int numFaces = 0;
+ VertDataCopy(q, VERT_getCo(e->v0, curLvl), ss);
+ VertDataAdd(q, VERT_getCo(e->v1, curLvl), ss);
+ for (i = 0; i < e->numFaces; i++) {
+ CCGFace *f = e->faces[i];
+ VertDataAdd(q, (float *)FACE_getCenterData(f), ss);
+ numFaces++;
+ }
+ VertDataMulN(q, 1.0f / (2.0f + numFaces), ss);
+
+ VertDataCopy(r, VERT_getCo(e->v0, curLvl), ss);
+ VertDataAdd(r, VERT_getCo(e->v1, curLvl), ss);
+ VertDataMulN(r, 0.5f, ss);
+
+ VertDataCopy(co, q, ss);
+ VertDataSub(r, q, ss);
+ VertDataMulN(r, sharpness, ss);
+ VertDataAdd(co, r, ss);
+ }
+
+ /* edge flags cleared later */
+ }
+ for (ptrIdx = 0; ptrIdx < numEffectedV; ptrIdx++) {
+ CCGVert *v = effectedV[ptrIdx];
+ void *co = VERT_getCo(v, curLvl);
+ void *nCo = VERT_getCo(v, nextLvl);
+ int sharpCount = 0, allSharp = 1;
+ float avgSharpness = 0.0;
+ int seam = VERT_seam(v), seamEdges = 0;
+
+ for (i = 0; i < v->numEdges; i++) {
+ CCGEdge *e = v->edges[i];
+ float sharpness = EDGE_getSharpness(e, curLvl);
+
+ if (seam && _edge_isBoundary(e))
+ seamEdges++;
+
+ if (sharpness != 0.0f) {
+ sharpCount++;
+ avgSharpness += sharpness;
+ }
+ else {
+ allSharp = 0;
+ }
+ }
+
+ if (sharpCount) {
+ avgSharpness /= sharpCount;
+ if (avgSharpness > 1.0f) {
+ avgSharpness = 1.0f;
+ }
+ }
+
+ if (seamEdges < 2 || seamEdges != v->numEdges)
+ seam = 0;
+
+ if (!v->numEdges || ss->meshIFC.simpleSubdiv) {
+ VertDataCopy(nCo, co, ss);
+ }
+ else if (_vert_isBoundary(v)) {
+ int numBoundary = 0;
+
+ VertDataZero(r, ss);
+ for (i = 0; i < v->numEdges; i++) {
+ CCGEdge *e = v->edges[i];
+ if (_edge_isBoundary(e)) {
+ VertDataAdd(r, VERT_getCo(_edge_getOtherVert(e, v), curLvl), ss);
+ numBoundary++;
+ }
+ }
+ VertDataCopy(nCo, co, ss);
+ VertDataMulN(nCo, 0.75f, ss);
+ VertDataMulN(r, 0.25f / numBoundary, ss);
+ VertDataAdd(nCo, r, ss);
+ }
+ else {
+ int numEdges = 0, numFaces = 0;
+
+ VertDataZero(q, ss);
+ for (i = 0; i < v->numFaces; i++) {
+ CCGFace *f = v->faces[i];
+ VertDataAdd(q, (float *)FACE_getCenterData(f), ss);
+ numFaces++;
+ }
+ VertDataMulN(q, 1.0f / numFaces, ss);
+ VertDataZero(r, ss);
+ for (i = 0; i < v->numEdges; i++) {
+ CCGEdge *e = v->edges[i];
+ VertDataAdd(r, VERT_getCo(_edge_getOtherVert(e, v), curLvl), ss);
+ numEdges++;
+ }
+ VertDataMulN(r, 1.0f / numEdges, ss);
+
+ VertDataCopy(nCo, co, ss);
+ VertDataMulN(nCo, numEdges - 2.0f, ss);
+ VertDataAdd(nCo, q, ss);
+ VertDataAdd(nCo, r, ss);
+ VertDataMulN(nCo, 1.0f / numEdges, ss);
+ }
+
+ if (sharpCount > 1 || seam) {
+ VertDataZero(q, ss);
+
+ if (seam) {
+ avgSharpness = 1.0f;
+ sharpCount = seamEdges;
+ allSharp = 1;
+ }
+
+ for (i = 0; i < v->numEdges; i++) {
+ CCGEdge *e = v->edges[i];
+ float sharpness = EDGE_getSharpness(e, curLvl);
+
+ if (seam) {
+ if (_edge_isBoundary(e)) {
+ CCGVert *oV = _edge_getOtherVert(e, v);
+ VertDataAdd(q, VERT_getCo(oV, curLvl), ss);
+ }
+ }
+ else if (sharpness != 0.0f) {
+ CCGVert *oV = _edge_getOtherVert(e, v);
+ VertDataAdd(q, VERT_getCo(oV, curLvl), ss);
+ }
+ }
+
+ VertDataMulN(q, (float) 1 / sharpCount, ss);
+
+ if (sharpCount != 2 || allSharp) {
+ /* q = q + (co - q) * avgSharpness */
+ VertDataCopy(r, co, ss);
+ VertDataSub(r, q, ss);
+ VertDataMulN(r, avgSharpness, ss);
+ VertDataAdd(q, r, ss);
+ }
+
+ /* r = co * 0.75 + q * 0.25 */
+ VertDataCopy(r, co, ss);
+ VertDataMulN(r, 0.75f, ss);
+ VertDataMulN(q, 0.25f, ss);
+ VertDataAdd(r, q, ss);
+
+ /* nCo = nCo + (r - nCo) * avgSharpness */
+ VertDataSub(r, nCo, ss);
+ VertDataMulN(r, avgSharpness, ss);
+ VertDataAdd(nCo, r, ss);
+ }
+
+ /* vert flags cleared later */
+ }
+
+ if (ss->useAgeCounts) {
+ for (i = 0; i < numEffectedV; i++) {
+ CCGVert *v = effectedV[i];
+ byte *userData = ccgSubSurf_getVertUserData(ss, v);
+ *((int *) &userData[ss->vertUserAgeOffset]) = ss->currentAge;
+ }
+
+ for (i = 0; i < numEffectedE; i++) {
+ CCGEdge *e = effectedE[i];
+ byte *userData = ccgSubSurf_getEdgeUserData(ss, e);
+ *((int *) &userData[ss->edgeUserAgeOffset]) = ss->currentAge;
+ }
+
+ for (i = 0; i < numEffectedF; i++) {
+ CCGFace *f = effectedF[i];
+ byte *userData = ccgSubSurf_getFaceUserData(ss, f);
+ *((int *) &userData[ss->faceUserAgeOffset]) = ss->currentAge;
+ }
+ }
+
+ for (i = 0; i < numEffectedE; i++) {
+ CCGEdge *e = effectedE[i];
+ VertDataCopy(EDGE_getCo(e, nextLvl, 0), VERT_getCo(e->v0, nextLvl), ss);
+ VertDataCopy(EDGE_getCo(e, nextLvl, 2), VERT_getCo(e->v1, nextLvl), ss);
+ }
+ for (i = 0; i < numEffectedF; i++) {
+ CCGFace *f = effectedF[i];
+ for (S = 0; S < f->numVerts; S++) {
+ CCGEdge *e = FACE_getEdges(f)[S];
+ CCGEdge *prevE = FACE_getEdges(f)[(S + f->numVerts - 1) % f->numVerts];
+
+ VertDataCopy(FACE_getIFCo(f, nextLvl, S, 0, 0), (float *)FACE_getCenterData(f), ss);
+ VertDataCopy(FACE_getIECo(f, nextLvl, S, 0), (float *)FACE_getCenterData(f), ss);
+ VertDataCopy(FACE_getIFCo(f, nextLvl, S, 1, 1), VERT_getCo(FACE_getVerts(f)[S], nextLvl), ss);
+ VertDataCopy(FACE_getIECo(f, nextLvl, S, 1), EDGE_getCo(FACE_getEdges(f)[S], nextLvl, 1), ss);
+
+ VertDataCopy(FACE_getIFCo(f, nextLvl, S, 1, 0), _edge_getCoVert(e, FACE_getVerts(f)[S], nextLvl, 1, vertDataSize), ss);
+ VertDataCopy(FACE_getIFCo(f, nextLvl, S, 0, 1), _edge_getCoVert(prevE, FACE_getVerts(f)[S], nextLvl, 1, vertDataSize), ss);
+ }
+ }
+
+ for (curLvl = 1; curLvl < subdivLevels; curLvl++)
+ ccgSubSurf__calcSubdivLevel(ss,
+ effectedV, effectedE, effectedF,
+ numEffectedV, numEffectedE, numEffectedF, curLvl);
+
+ if (ss->calcVertNormals)
+ ccgSubSurf__calcVertNormals(ss,
+ effectedV, effectedE, effectedF,
+ numEffectedV, numEffectedE, numEffectedF);
+
+ for (ptrIdx = 0; ptrIdx < numEffectedV; ptrIdx++) {
+ CCGVert *v = effectedV[ptrIdx];
+ v->flags = 0;
+ }
+ for (ptrIdx = 0; ptrIdx < numEffectedE; ptrIdx++) {
+ CCGEdge *e = effectedE[ptrIdx];
+ e->flags = 0;
+ }
+
+ MEM_freeN(effectedF);
+ MEM_freeN(effectedE);
+ MEM_freeN(effectedV);
+
+#ifdef DUMP_RESULT_GRIDS
+ ccgSubSurf__dumpCoords(ss);
+#endif
+}
+
+/* ** Public API exposed to other areas which depends on old CCG code. ** */
+
+/* Update normals for specified faces. */
+CCGError ccgSubSurf_updateNormals(CCGSubSurf *ss, CCGFace **effectedF, int numEffectedF)
+{
+ CCGVert **effectedV;
+ CCGEdge **effectedE;
+ int i, numEffectedV, numEffectedE, freeF;
+
+ ccgSubSurf__allFaces(ss, &effectedF, &numEffectedF, &freeF);
+ ccgSubSurf__effectedFaceNeighbours(ss, effectedF, numEffectedF,
+ &effectedV, &numEffectedV, &effectedE, &numEffectedE);
+
+ if (ss->calcVertNormals)
+ ccgSubSurf__calcVertNormals(ss,
+ effectedV, effectedE, effectedF,
+ numEffectedV, numEffectedE, numEffectedF);
+
+ for (i = 0; i < numEffectedV; i++)
+ effectedV[i]->flags = 0;
+ for (i = 0; i < numEffectedE; i++)
+ effectedE[i]->flags = 0;
+ for (i = 0; i < numEffectedF; i++)
+ effectedF[i]->flags = 0;
+
+ MEM_freeN(effectedE);
+ MEM_freeN(effectedV);
+ if (freeF) MEM_freeN(effectedF);
+
+ return eCCGError_None;
+}
+
+/* compute subdivision levels from a given starting point, used by
+ * multires subdivide/propagate, by filling in coordinates at a
+ * certain level, and then subdividing that up to the highest level */
+CCGError ccgSubSurf_updateLevels(CCGSubSurf *ss, int lvl, CCGFace **effectedF, int numEffectedF)
+{
+ CCGVert **effectedV;
+ CCGEdge **effectedE;
+ int numEffectedV, numEffectedE, freeF, i;
+ int curLvl, subdivLevels = ss->subdivLevels;
+
+ ccgSubSurf__allFaces(ss, &effectedF, &numEffectedF, &freeF);
+ ccgSubSurf__effectedFaceNeighbours(ss, effectedF, numEffectedF,
+ &effectedV, &numEffectedV, &effectedE, &numEffectedE);
+
+ for (curLvl = lvl; curLvl < subdivLevels; curLvl++) {
+ ccgSubSurf__calcSubdivLevel(ss,
+ effectedV, effectedE, effectedF,
+ numEffectedV, numEffectedE, numEffectedF, curLvl);
+ }
+
+ for (i = 0; i < numEffectedV; i++)
+ effectedV[i]->flags = 0;
+ for (i = 0; i < numEffectedE; i++)
+ effectedE[i]->flags = 0;
+ for (i = 0; i < numEffectedF; i++)
+ effectedF[i]->flags = 0;
+
+ MEM_freeN(effectedE);
+ MEM_freeN(effectedV);
+ if (freeF) MEM_freeN(effectedF);
+
+ return eCCGError_None;
+}
diff --git a/source/blender/blenkernel/intern/CCGSubSurf_opensubdiv.c b/source/blender/blenkernel/intern/CCGSubSurf_opensubdiv.c
new file mode 100644
index 00000000000..39669fd76d7
--- /dev/null
+++ b/source/blender/blenkernel/intern/CCGSubSurf_opensubdiv.c
@@ -0,0 +1,920 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/blenkernel/intern/CCGSubSurf_opensubdiv.c
+ * \ingroup bke
+ */
+
+#ifdef WITH_OPENSUBDIV
+
+#include "MEM_guardedalloc.h"
+#include "BLI_sys_types.h" // for intptr_t support
+
+#include "BLI_utildefines.h" /* for BLI_assert */
+#include "BLI_math.h"
+
+#include "CCGSubSurf.h"
+#include "CCGSubSurf_intern.h"
+
+#include "BKE_DerivedMesh.h"
+
+#include "DNA_userdef_types.h"
+
+#include "opensubdiv_capi.h"
+#include "opensubdiv_converter_capi.h"
+
+#include "GL/glew.h"
+
+#define OSD_LOG if (false) printf
+
+static bool compare_ccg_derivedmesh_topology(CCGSubSurf *ss, DerivedMesh *dm)
+{
+ const int num_verts = dm->getNumVerts(dm);
+ const int num_edges = dm->getNumEdges(dm);
+ const int num_polys = dm->getNumPolys(dm);
+ const MEdge *medge = dm->getEdgeArray(dm);
+ const MLoop *mloop = dm->getLoopArray(dm);
+ const MPoly *mpoly = dm->getPolyArray(dm);
+
+ /* Quick preliminary tests based on the number of verts and facces. */
+ {
+ if (num_verts != ss->vMap->numEntries ||
+ num_edges != ss->eMap->numEntries ||
+ num_polys != ss->fMap->numEntries)
+ {
+ return false;
+ }
+ }
+
+ /* Rather slow check for faces topology change. */
+ {
+ CCGFaceIterator ccg_face_iter;
+ for (ccgSubSurf_initFaceIterator(ss, &ccg_face_iter);
+ !ccgFaceIterator_isStopped(&ccg_face_iter);
+ ccgFaceIterator_next(&ccg_face_iter))
+ {
+ /*const*/ CCGFace *ccg_face = ccgFaceIterator_getCurrent(&ccg_face_iter);
+ const int poly_index = GET_INT_FROM_POINTER(ccgSubSurf_getFaceFaceHandle(ccg_face));
+ const MPoly *mp = &mpoly[poly_index];
+ int corner;
+ if (ccg_face->numVerts != mp->totloop) {
+ return false;
+ }
+ for (corner = 0; corner < ccg_face->numVerts; corner++) {
+ /*const*/ CCGVert *ccg_vert = FACE_getVerts(ccg_face)[corner];
+ const int vert_index = GET_INT_FROM_POINTER(ccgSubSurf_getVertVertHandle(ccg_vert));
+ if (vert_index != mloop[mp->loopstart + corner].v) {
+ return false;
+ }
+ }
+ }
+ }
+
+ /* Check for edge topology change. */
+ {
+ CCGEdgeIterator ccg_edge_iter;
+ for (ccgSubSurf_initEdgeIterator(ss, &ccg_edge_iter);
+ !ccgEdgeIterator_isStopped(&ccg_edge_iter);
+ ccgEdgeIterator_next(&ccg_edge_iter))
+ {
+ /* const */ CCGEdge *ccg_edge = ccgEdgeIterator_getCurrent(&ccg_edge_iter);
+ /* const */ CCGVert *ccg_vert1 = ccg_edge->v0;
+ /* const */ CCGVert *ccg_vert2 = ccg_edge->v1;
+ const int ccg_vert1_index = GET_INT_FROM_POINTER(ccgSubSurf_getVertVertHandle(ccg_vert1));
+ const int ccg_vert2_index = GET_INT_FROM_POINTER(ccgSubSurf_getVertVertHandle(ccg_vert2));
+ const int edge_index = GET_INT_FROM_POINTER(ccgSubSurf_getEdgeEdgeHandle(ccg_edge));
+ const MEdge *me = &medge[edge_index];
+ if (me->v1 != ccg_vert1_index || me->v2 != ccg_vert2_index) {
+ return false;
+ }
+ }
+ }
+
+ /* TODO(sergey): Crease topology changes detection. */
+ {
+ CCGEdgeIterator ccg_edge_iter;
+ for (ccgSubSurf_initEdgeIterator(ss, &ccg_edge_iter);
+ !ccgEdgeIterator_isStopped(&ccg_edge_iter);
+ ccgEdgeIterator_next(&ccg_edge_iter))
+ {
+ /* const */ CCGEdge *ccg_edge = ccgEdgeIterator_getCurrent(&ccg_edge_iter);
+ const int edge_index = GET_INT_FROM_POINTER(ccgSubSurf_getEdgeEdgeHandle(ccg_edge));
+ if (ccg_edge->crease != medge[edge_index].crease) {
+ return false;
+ }
+ }
+ }
+
+ return true;
+}
+
+static bool compare_osd_derivedmesh_topology(CCGSubSurf *ss, DerivedMesh *dm)
+{
+ const OpenSubdiv_TopologyRefinerDescr *topology_refiner;
+ OpenSubdiv_Converter converter;
+ bool result;
+ if (ss->osd_mesh == NULL && ss->osd_topology_refiner == NULL) {
+ return true;
+ }
+ /* TODO(sergey): De-duplicate with topology counter at the bottom of
+ * the file.
+ */
+ if (ss->osd_topology_refiner != NULL) {
+ topology_refiner = ss->osd_topology_refiner;
+ }
+ else {
+ topology_refiner = openSubdiv_getGLMeshTopologyRefiner(ss->osd_mesh);
+ }
+ ccgSubSurf_converter_setup_from_derivedmesh(ss, dm, &converter);
+ result = openSubdiv_topologyRefnerCompareConverter(topology_refiner,
+ &converter);
+ ccgSubSurf_converter_free(&converter);
+ return result;
+}
+
+static bool opensubdiv_is_topology_changed(CCGSubSurf *ss, DerivedMesh *dm)
+{
+ if (ss->osd_compute != U.opensubdiv_compute_type) {
+ return true;
+ }
+ if (ss->osd_topology_refiner != NULL) {
+ int levels = openSubdiv_topologyRefinerGetSubdivLevel(
+ ss->osd_topology_refiner);
+ BLI_assert(ss->osd_mesh_invalid == true);
+ if (levels != ss->subdivLevels) {
+ return true;
+ }
+ }
+ if (ss->osd_mesh != NULL && ss->osd_mesh_invalid == false) {
+ const OpenSubdiv_TopologyRefinerDescr *topology_refiner =
+ openSubdiv_getGLMeshTopologyRefiner(ss->osd_mesh);
+ int levels = openSubdiv_topologyRefinerGetSubdivLevel(topology_refiner);
+ BLI_assert(ss->osd_topology_refiner == NULL);
+ if (levels != ss->subdivLevels) {
+ return true;
+ }
+ }
+ if (ss->skip_grids == false) {
+ return compare_ccg_derivedmesh_topology(ss, dm) == false;
+ }
+ else {
+ return compare_osd_derivedmesh_topology(ss, dm) == false;
+ }
+ return false;
+}
+
+void ccgSubSurf_checkTopologyChanged(CCGSubSurf *ss, DerivedMesh *dm)
+{
+ if (opensubdiv_is_topology_changed(ss, dm)) {
+ /* ** Make sure both GPU and CPU backends are properly reset. ** */
+
+ ss->osd_coarse_coords_invalid = true;
+ ss->osd_uvs_invalid = true;
+
+ /* Reset GPU part. */
+ ss->osd_mesh_invalid = true;
+ if (ss->osd_topology_refiner != NULL) {
+ openSubdiv_deleteTopologyRefinerDescr(ss->osd_topology_refiner);
+ ss->osd_topology_refiner = NULL;
+ }
+
+ /* Reste CPU side. */
+ if (ss->osd_evaluator != NULL) {
+ openSubdiv_deleteEvaluatorDescr(ss->osd_evaluator);
+ ss->osd_evaluator = NULL;
+ }
+ }
+}
+
+static void ccgSubSurf__updateGLMeshCoords(CCGSubSurf *ss)
+{
+ BLI_assert(ss->meshIFC.numLayers == 3);
+ openSubdiv_osdGLMeshUpdateVertexBuffer(ss->osd_mesh,
+ (float *) ss->osd_coarse_coords,
+ 0,
+ ss->osd_num_coarse_coords);
+}
+
+bool ccgSubSurf_prepareGLMesh(CCGSubSurf *ss, bool use_osd_glsl)
+{
+ int compute_type;
+
+ switch (U.opensubdiv_compute_type) {
+#define CHECK_COMPUTE_TYPE(type) \
+ case USER_OPENSUBDIV_COMPUTE_ ## type: \
+ compute_type = OPENSUBDIV_EVALUATOR_ ## type; \
+ break;
+ CHECK_COMPUTE_TYPE(CPU)
+ CHECK_COMPUTE_TYPE(OPENMP)
+ CHECK_COMPUTE_TYPE(OPENCL)
+ CHECK_COMPUTE_TYPE(CUDA)
+ CHECK_COMPUTE_TYPE(GLSL_TRANSFORM_FEEDBACK)
+ CHECK_COMPUTE_TYPE(GLSL_COMPUTE)
+#undef CHECK_COMPUTE_TYPE
+ }
+
+ if (ss->osd_vao == 0) {
+ glGenVertexArrays(1, &ss->osd_vao);
+ }
+
+ if (ss->osd_mesh_invalid) {
+ if (ss->osd_mesh != NULL) {
+ openSubdiv_deleteOsdGLMesh(ss->osd_mesh);
+ ss->osd_mesh = NULL;
+ }
+ ss->osd_mesh_invalid = false;
+ }
+
+ if (ss->osd_mesh == NULL) {
+ if (ss->osd_topology_refiner == NULL) {
+ /* Happens with empty meshes. */
+ /* TODO(sergey): Add assert that mesh is indeed empty. */
+ return false;
+ }
+
+ ss->osd_mesh = openSubdiv_createOsdGLMeshFromTopologyRefiner(
+ ss->osd_topology_refiner,
+ compute_type,
+ ss->subdivLevels,
+ ss->osd_subsurf_uv);
+ ss->osd_topology_refiner = NULL;
+
+ if (UNLIKELY(ss->osd_mesh == NULL)) {
+ /* Most likely compute device is not available. */
+ return false;
+ }
+
+ ccgSubSurf__updateGLMeshCoords(ss);
+ openSubdiv_osdGLMeshRefine(ss->osd_mesh);
+ openSubdiv_osdGLMeshSynchronize(ss->osd_mesh);
+ ss->osd_coarse_coords_invalid = false;
+
+ glBindVertexArray(ss->osd_vao);
+ glBindBuffer(GL_ARRAY_BUFFER,
+ openSubdiv_getOsdGLMeshVertexBuffer(ss->osd_mesh));
+
+ glEnableVertexAttribArray(0);
+ glEnableVertexAttribArray(1);
+ glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE,
+ sizeof(GLfloat) * 6, 0);
+ glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE,
+ sizeof(GLfloat) * 6, (float *)12);
+
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
+ }
+ else if (ss->osd_coarse_coords_invalid) {
+ ccgSubSurf__updateGLMeshCoords(ss);
+ openSubdiv_osdGLMeshRefine(ss->osd_mesh);
+ openSubdiv_osdGLMeshSynchronize(ss->osd_mesh);
+ ss->osd_coarse_coords_invalid = false;
+ }
+
+ openSubdiv_osdGLMeshDisplayPrepare(use_osd_glsl, ss->osd_uv_index);
+
+ return true;
+}
+
+void ccgSubSurf_drawGLMesh(CCGSubSurf *ss, bool fill_quads,
+ int start_partition, int num_partitions)
+{
+ if (LIKELY(ss->osd_mesh != NULL)) {
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,
+ openSubdiv_getOsdGLMeshPatchIndexBuffer(ss->osd_mesh));
+
+ openSubdiv_osdGLMeshBindVertexBuffer(ss->osd_mesh);
+ glBindVertexArray(ss->osd_vao);
+ openSubdiv_osdGLMeshDisplay(ss->osd_mesh, fill_quads,
+ start_partition, num_partitions);
+ glBindVertexArray(0);
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
+ }
+}
+
+int ccgSubSurf_getNumGLMeshBaseFaces(CCGSubSurf *ss)
+{
+ const OpenSubdiv_TopologyRefinerDescr *topology_refiner;
+ if (ss->osd_topology_refiner != NULL) {
+ topology_refiner = ss->osd_topology_refiner;
+ }
+ else if (ss->osd_mesh != NULL) {
+ topology_refiner = openSubdiv_getGLMeshTopologyRefiner(ss->osd_mesh);
+ }
+ else {
+ return 0;
+ }
+ return openSubdiv_topologyRefinerGetNumFaces(topology_refiner);
+}
+
+/* Get number of vertices in base faces in a particular GL mesh. */
+int ccgSubSurf_getNumGLMeshBaseFaceVerts(CCGSubSurf *ss, int face)
+{
+ const OpenSubdiv_TopologyRefinerDescr *topology_refiner;
+ if (ss->osd_topology_refiner != NULL) {
+ topology_refiner = ss->osd_topology_refiner;
+ }
+ else if (ss->osd_mesh != NULL) {
+ topology_refiner = openSubdiv_getGLMeshTopologyRefiner(ss->osd_mesh);
+ }
+ else {
+ return 0;
+ }
+ return openSubdiv_topologyRefinerGetNumFaceVerts(topology_refiner, face);
+}
+
+void ccgSubSurf_setSkipGrids(CCGSubSurf *ss, bool skip_grids)
+{
+ ss->skip_grids = skip_grids;
+}
+
+bool ccgSubSurf_needGrids(CCGSubSurf *ss)
+{
+ return ss->skip_grids == false;
+}
+
+BLI_INLINE void ccgSubSurf__mapGridToFace(int S, float grid_u, float grid_v,
+ float *face_u, float *face_v)
+{
+ float u, v;
+
+ /* - Each grid covers half of the face along the edges.
+ * - Grid's (0, 0) starts from the middle of the face.
+ */
+ u = 0.5f - 0.5f * grid_u;
+ v = 0.5f - 0.5f * grid_v;
+
+ if (S == 0) {
+ *face_u = v;
+ *face_v = u;
+ }
+ else if (S == 1) {
+ *face_u = 1.0f - u;
+ *face_v = v;
+ }
+ else if (S == 2) {
+ *face_u = 1.0f - v;
+ *face_v = 1.0f - u;
+ }
+ else {
+ *face_u = u;
+ *face_v = 1.0f - v;
+ }
+}
+
+BLI_INLINE void ccgSubSurf__mapEdgeToFace(int S,
+ int edge_segment,
+ bool inverse_edge,
+ int edgeSize,
+ float *face_u, float *face_v)
+{
+ int t = inverse_edge ? edgeSize - edge_segment - 1 : edge_segment;
+ if (S == 0) {
+ *face_u = (float) t / (edgeSize - 1);
+ *face_v = 0.0f;
+ }
+ else if (S == 1) {
+ *face_u = 1.0f;
+ *face_v = (float) t / (edgeSize - 1);
+ }
+ else if (S == 2) {
+ *face_u = 1.0f - (float) t / (edgeSize - 1);
+ *face_v = 1.0f;
+ }
+ else {
+ *face_u = 0.0f;
+ *face_v = 1.0f - (float) t / (edgeSize - 1);
+ }
+}
+
+void ccgSubSurf_evaluatorSetFVarUV(CCGSubSurf *ss,
+ DerivedMesh *dm,
+ int layer_index)
+{
+ MPoly *mpoly = dm->getPolyArray(dm);
+ MLoopUV *mloopuv = CustomData_get_layer_n(&dm->loopData, CD_MLOOPUV, layer_index);
+ int num_polys = dm->getNumPolys(dm);
+ int index, poly;
+ BLI_assert(ss->osd_evaluator != NULL);
+ for (poly = 0, index = 0; poly < num_polys; poly++) {
+ int loop;
+ MPoly *mp = &mpoly[poly];
+ for (loop = 0; loop < mp->totloop; loop++, index++) {
+ MLoopUV *mluv = &mloopuv[loop + mp->loopstart];
+ (void)mluv;
+ /* TODO(sergey): Send mluv->uv to the evaluator's face varying
+ * buffer.
+ */
+ }
+ }
+ (void)ss;
+}
+
+void ccgSubSurf_evaluatorFVarUV(CCGSubSurf *ss,
+ int face_index, int S,
+ float grid_u, float grid_v,
+ float uv[2])
+{
+ float face_u, face_v;
+ ccgSubSurf__mapGridToFace(S,
+ grid_u, grid_v,
+ &face_u, &face_v);
+ (void)ss;
+ (void)face_index;
+ /* TODO(sergey): Evaluate face varying coordinate. */
+ zero_v2(uv);
+}
+
+static bool opensubdiv_createEvaluator(CCGSubSurf *ss)
+{
+ OpenSubdiv_Converter converter;
+ OpenSubdiv_TopologyRefinerDescr *topology_refiner;
+ if (ss->fMap->numEntries == 0) {
+ /* OpenSubdiv doesn't support meshes without faces. */
+ return false;
+ }
+ ccgSubSurf_converter_setup_from_ccg(ss, &converter);
+ topology_refiner = openSubdiv_createTopologyRefinerDescr(&converter);
+ ccgSubSurf_converter_free(&converter);
+ ss->osd_evaluator =
+ openSubdiv_createEvaluatorDescr(topology_refiner,
+ ss->subdivLevels);
+ if (ss->osd_evaluator == NULL) {
+ BLI_assert(!"OpenSubdiv initialization failed, should not happen.");
+ return false;
+ }
+ return true;
+}
+
+static bool opensubdiv_ensureEvaluator(CCGSubSurf *ss)
+{
+ if (ss->osd_evaluator == NULL) {
+ OSD_LOG("Allocating new evaluator, %d verts\n", ss->vMap->numEntries);
+ opensubdiv_createEvaluator(ss);
+ }
+ return ss->osd_evaluator != NULL;
+}
+
+static void opensubdiv_updateEvaluatorCoarsePositions(CCGSubSurf *ss)
+{
+ float (*positions)[3];
+ int vertDataSize = ss->meshIFC.vertDataSize;
+ int num_basis_verts = ss->vMap->numEntries;
+ int i;
+
+ /* TODO(sergey): Avoid allocation on every update. We could either update
+ * coordinates in chunks of 1K vertices (which will only use stack memory)
+ * or do some callback magic for OSD evaluator can invoke it and fill in
+ * buffer directly.
+ */
+ if (ss->meshIFC.numLayers == 3) {
+ /* If all the components are to be initialized, no need to memset the
+ * new memory block.
+ */
+ positions = MEM_mallocN(3 * sizeof(float) * num_basis_verts,
+ "OpenSubdiv coarse points");
+ }
+ else {
+ /* Calloc in order to have z component initialized to 0 for Uvs */
+ positions = MEM_callocN(3 * sizeof(float) * num_basis_verts,
+ "OpenSubdiv coarse points");
+ }
+#pragma omp parallel for
+ for (i = 0; i < ss->vMap->curSize; i++) {
+ CCGVert *v = (CCGVert *) ss->vMap->buckets[i];
+ for (; v; v = v->next) {
+ float *co = VERT_getCo(v, 0);
+ BLI_assert(v->osd_index < ss->vMap->numEntries);
+ VertDataCopy(positions[v->osd_index], co, ss);
+ OSD_LOG("Point %d has value %f %f %f\n",
+ v->osd_index,
+ positions[v->osd_index][0],
+ positions[v->osd_index][1],
+ positions[v->osd_index][2]);
+ }
+ }
+
+ openSubdiv_setEvaluatorCoarsePositions(ss->osd_evaluator,
+ (float *)positions,
+ 0,
+ num_basis_verts);
+
+ MEM_freeN(positions);
+}
+
+static void opensubdiv_evaluateQuadFaceGrids(CCGSubSurf *ss,
+ CCGFace *face,
+ const int osd_face_index)
+{
+ int normalDataOffset = ss->normalDataOffset;
+ int subdivLevels = ss->subdivLevels;
+ int gridSize = ccg_gridsize(subdivLevels);
+ int edgeSize = ccg_edgesize(subdivLevels);
+ int vertDataSize = ss->meshIFC.vertDataSize;
+ int S;
+ bool do_normals = ss->meshIFC.numLayers == 3;
+
+#pragma omp parallel for
+ for (S = 0; S < face->numVerts; S++) {
+ int x, y, k;
+ CCGEdge *edge = NULL;
+ bool inverse_edge;
+
+ for (x = 0; x < gridSize; x++) {
+ for (y = 0; y < gridSize; y++) {
+ float *co = FACE_getIFCo(face, subdivLevels, S, x, y);
+ float *no = FACE_getIFNo(face, subdivLevels, S, x, y);
+ float grid_u = (float) x / (gridSize - 1),
+ grid_v = (float) y / (gridSize - 1);
+ float face_u, face_v;
+ float P[3], dPdu[3], dPdv[3];
+
+ ccgSubSurf__mapGridToFace(S, grid_u, grid_v, &face_u, &face_v);
+
+ /* TODO(sergey): Need proper port. */
+ openSubdiv_evaluateLimit(ss->osd_evaluator, osd_face_index,
+ face_u, face_v,
+ P,
+ do_normals ? dPdu : NULL,
+ do_normals ? dPdv : NULL);
+
+ OSD_LOG("face=%d, corner=%d, grid_u=%f, grid_v=%f, face_u=%f, face_v=%f, P=(%f, %f, %f)\n",
+ osd_face_index, S, grid_u, grid_v, face_u, face_v, P[0], P[1], P[2]);
+
+ VertDataCopy(co, P, ss);
+ if (do_normals) {
+ cross_v3_v3v3(no, dPdu, dPdv);
+ normalize_v3(no);
+ }
+
+ if (x == gridSize - 1 && y == gridSize - 1) {
+ float *vert_co = VERT_getCo(FACE_getVerts(face)[S], subdivLevels);
+ VertDataCopy(vert_co, co, ss);
+ if (do_normals) {
+ float *vert_no = VERT_getNo(FACE_getVerts(face)[S], subdivLevels);
+ VertDataCopy(vert_no, no, ss);
+ }
+ }
+ if (S == 0 && x == 0 && y == 0) {
+ float *center_co = (float *)FACE_getCenterData(face);
+ VertDataCopy(center_co, co, ss);
+ if (do_normals) {
+ float *center_no = (float *)((byte *)FACE_getCenterData(face) + normalDataOffset);
+ VertDataCopy(center_no, no, ss);
+ }
+ }
+ }
+ }
+
+ for (x = 0; x < gridSize; x++) {
+ VertDataCopy(FACE_getIECo(face, subdivLevels, S, x),
+ FACE_getIFCo(face, subdivLevels, S, x, 0), ss);
+ if (do_normals) {
+ VertDataCopy(FACE_getIENo(face, subdivLevels, S, x),
+ FACE_getIFNo(face, subdivLevels, S, x, 0), ss);
+ }
+ }
+
+ for (k = 0; k < face->numVerts; k++) {
+ CCGEdge *current_edge = FACE_getEdges(face)[k];
+ CCGVert **face_verts = FACE_getVerts(face);
+ if (current_edge->v0 == face_verts[S] &&
+ current_edge->v1 == face_verts[(S + 1) % face->numVerts])
+ {
+ edge = current_edge;
+ inverse_edge = false;
+ break;
+ }
+ if (current_edge->v1 == face_verts[S] &&
+ current_edge->v0 == face_verts[(S + 1) % face->numVerts])
+ {
+ edge = current_edge;
+ inverse_edge = true;
+ break;
+ }
+ }
+
+ BLI_assert(edge != NULL);
+
+ for (x = 0; x < edgeSize; x++) {
+ float u = 0, v = 0;
+ float *co = EDGE_getCo(edge, subdivLevels, x);
+ float *no = EDGE_getNo(edge, subdivLevels, x);
+ float P[3], dPdu[3], dPdv[3];
+ ccgSubSurf__mapEdgeToFace(S, x,
+ inverse_edge,
+ edgeSize,
+ &u, &v);
+
+ /* TODO(sergey): Ideally we will re-use grid here, but for now
+ * let's just re-evaluate for simplicity.
+ */
+ /* TODO(sergey): Need proper port. */
+ openSubdiv_evaluateLimit(ss->osd_evaluator, osd_face_index, u, v, P, dPdu, dPdv);
+ VertDataCopy(co, P, ss);
+ if (do_normals) {
+ cross_v3_v3v3(no, dPdu, dPdv);
+ normalize_v3(no);
+ }
+ }
+ }
+}
+
+static void opensubdiv_evaluateNGonFaceGrids(CCGSubSurf *ss,
+ CCGFace *face,
+ const int osd_face_index)
+{
+ CCGVert **all_verts = FACE_getVerts(face);
+ int normalDataOffset = ss->normalDataOffset;
+ int subdivLevels = ss->subdivLevels;
+ int gridSize = ccg_gridsize(subdivLevels);
+ int edgeSize = ccg_edgesize(subdivLevels);
+ int vertDataSize = ss->meshIFC.vertDataSize;
+ int S;
+ bool do_normals = ss->meshIFC.numLayers == 3;
+
+ /* Note about handling non-quad faces.
+ *
+ * In order to deal with non-quad faces we need to split them
+ * into a quads in the following way:
+ *
+ * |
+ * (vert_next)
+ * |
+ * |
+ * |
+ * (face_center) ------------------- (v2)
+ * | (o)--------------------> |
+ * | | v |
+ * | | |
+ * | | |
+ * | | |
+ * | | y ^ |
+ * | | | |
+ * | v u x | |
+ * | <---(o) |
+ * ---- (vert_prev) ---- (v1) -------------------- (vert)
+ *
+ * This is how grids are expected to be stored and it's how
+ * OpenSubdiv deals with non-quad faces using ptex face indices.
+ * We only need to convert ptex (x, y) to grid (u, v) by some
+ * simple flips and evaluate the ptex face.
+ */
+
+ /* Evaluate face grids. */
+#pragma omp parallel for
+ for (S = 0; S < face->numVerts; S++) {
+ int x, y;
+ for (x = 0; x < gridSize; x++) {
+ for (y = 0; y < gridSize; y++) {
+ float *co = FACE_getIFCo(face, subdivLevels, S, x, y);
+ float *no = FACE_getIFNo(face, subdivLevels, S, x, y);
+ float u = 1.0f - (float) y / (gridSize - 1),
+ v = 1.0f - (float) x / (gridSize - 1);
+ float P[3], dPdu[3], dPdv[3];
+
+ /* TODO(sergey): Need proper port. */
+ openSubdiv_evaluateLimit(ss->osd_evaluator, osd_face_index + S, u, v, P, dPdu, dPdv);
+
+ OSD_LOG("face=%d, corner=%d, u=%f, v=%f, P=(%f, %f, %f)\n",
+ osd_face_index + S, S, u, v, P[0], P[1], P[2]);
+
+ VertDataCopy(co, P, ss);
+ if (do_normals) {
+ cross_v3_v3v3(no, dPdu, dPdv);
+ normalize_v3(no);
+ }
+
+ /* TODO(sergey): De-dpuplicate with the quad case. */
+ if (x == gridSize - 1 && y == gridSize - 1) {
+ float *vert_co = VERT_getCo(FACE_getVerts(face)[S], subdivLevels);
+ VertDataCopy(vert_co, co, ss);
+ if (do_normals) {
+ float *vert_no = VERT_getNo(FACE_getVerts(face)[S], subdivLevels);
+ VertDataCopy(vert_no, no, ss);
+ }
+ }
+ if (S == 0 && x == 0 && y == 0) {
+ float *center_co = (float *)FACE_getCenterData(face);
+ VertDataCopy(center_co, co, ss);
+ if (do_normals) {
+ float *center_no = (float *)((byte *)FACE_getCenterData(face) + normalDataOffset);
+ VertDataCopy(center_no, no, ss);
+ }
+ }
+ }
+ }
+ for (x = 0; x < gridSize; x++) {
+ VertDataCopy(FACE_getIECo(face, subdivLevels, S, x),
+ FACE_getIFCo(face, subdivLevels, S, x, 0), ss);
+ if (do_normals) {
+ VertDataCopy(FACE_getIENo(face, subdivLevels, S, x),
+ FACE_getIFNo(face, subdivLevels, S, x, 0), ss);
+ }
+ }
+ }
+
+ /* Evaluate edges. */
+ for (S = 0; S < face->numVerts; S++) {
+ CCGEdge *edge = FACE_getEdges(face)[S];
+ int x, S0, S1;
+ bool flip;
+
+ for (x = 0; x < face->numVerts; ++x) {
+ if (all_verts[x] == edge->v0) {
+ S0 = x;
+ }
+ else if (all_verts[x] == edge->v1) {
+ S1 = x;
+ }
+ }
+ if (S == face->numVerts - 1) {
+ flip = S0 > S1;
+ }
+ else {
+ flip = S0 < S1;
+ }
+
+ for (x = 0; x <= edgeSize / 2; x++) {
+ float *edge_co = EDGE_getCo(edge, subdivLevels, x);
+ float *edge_no = EDGE_getNo(edge, subdivLevels, x);
+ float *face_edge_co;
+ float *face_edge_no;
+ if (flip) {
+ face_edge_co = FACE_getIFCo(face, subdivLevels, S0, gridSize - 1, gridSize - 1 - x);
+ face_edge_no = FACE_getIFNo(face, subdivLevels, S0, gridSize - 1, gridSize - 1 - x);
+ }
+ else {
+ face_edge_co = FACE_getIFCo(face, subdivLevels, S0, gridSize - 1 - x, gridSize - 1);
+ face_edge_no = FACE_getIFNo(face, subdivLevels, S0, gridSize - 1 - x, gridSize - 1);
+ }
+ VertDataCopy(edge_co, face_edge_co, ss);
+ if (do_normals) {
+ VertDataCopy(edge_no, face_edge_no, ss);
+ }
+ }
+ for (x = edgeSize / 2 + 1; x < edgeSize; x++) {
+ float *edge_co = EDGE_getCo(edge, subdivLevels, x);
+ float *edge_no = EDGE_getNo(edge, subdivLevels, x);
+ float *face_edge_co;
+ float *face_edge_no;
+ if (flip) {
+ face_edge_co = FACE_getIFCo(face, subdivLevels, S1, x - edgeSize / 2, gridSize - 1);
+ face_edge_no = FACE_getIFNo(face, subdivLevels, S1, x - edgeSize / 2, gridSize - 1);
+ }
+ else {
+ face_edge_co = FACE_getIFCo(face, subdivLevels, S1, gridSize - 1, x - edgeSize / 2);
+ face_edge_no = FACE_getIFNo(face, subdivLevels, S1, gridSize - 1, x - edgeSize / 2);
+ }
+ VertDataCopy(edge_co, face_edge_co, ss);
+ if (do_normals) {
+ VertDataCopy(edge_no, face_edge_no, ss);
+ }
+ }
+ }
+}
+
+static void opensubdiv_evaluateGrids(CCGSubSurf *ss)
+{
+ int i;
+ for (i = 0; i < ss->fMap->curSize; i++) {
+ CCGFace *face = (CCGFace *) ss->fMap->buckets[i];
+ for (; face; face = face->next) {
+ if (face->numVerts == 4) {
+ /* For quads we do special magic with converting face coords
+ * into corner coords and interpolating grids from it.
+ */
+ opensubdiv_evaluateQuadFaceGrids(ss, face, face->osd_index);
+ }
+ else {
+ /* NGons and tris are split into separate osd faces which
+ * evaluates onto grids directly.
+ */
+ opensubdiv_evaluateNGonFaceGrids(ss, face, face->osd_index);
+ }
+ }
+ }
+}
+
+CCGError ccgSubSurf_initOpenSubdivSync(CCGSubSurf *ss)
+{
+ if (ss->syncState != eSyncState_None) {
+ return eCCGError_InvalidSyncState;
+ }
+ ss->syncState = eSyncState_OpenSubdiv;
+ return eCCGError_None;
+}
+
+void ccgSubSurf_prepareTopologyRefiner(CCGSubSurf *ss, DerivedMesh *dm)
+{
+ if (ss->osd_mesh == NULL || ss->osd_mesh_invalid) {
+ if (dm->getNumPolys(dm) != 0) {
+ OpenSubdiv_Converter converter;
+ ccgSubSurf_converter_setup_from_derivedmesh(ss, dm, &converter);
+ /* TODO(sergey): Remove possibly previously allocated refiner. */
+ ss->osd_topology_refiner = openSubdiv_createTopologyRefinerDescr(&converter);
+ ccgSubSurf_converter_free(&converter);
+ }
+ }
+
+ /* Update number of grids, needed for things like final faces
+ * counter, used by display drawing.
+ */
+ {
+ const int num_polys = dm->getNumPolys(dm);
+ const MPoly *mpoly = dm->getPolyArray(dm);
+ int poly;
+ ss->numGrids = 0;
+ for (poly = 0; poly < num_polys; ++poly) {
+ ss->numGrids += mpoly[poly].totloop;
+ }
+ }
+
+ {
+ const int num_verts = dm->getNumVerts(dm);
+ const MVert *mvert = dm->getVertArray(dm);
+ int vert;
+ if (ss->osd_coarse_coords != NULL &&
+ num_verts != ss->osd_num_coarse_coords)
+ {
+ MEM_freeN(ss->osd_coarse_coords);
+ ss->osd_coarse_coords = NULL;
+ }
+ if (ss->osd_coarse_coords == NULL) {
+ ss->osd_coarse_coords = MEM_mallocN(sizeof(float) * 6 * num_verts, "osd coarse positions");
+ }
+ for (vert = 0; vert < num_verts; vert++) {
+ copy_v3_v3(ss->osd_coarse_coords[vert * 2 + 0], mvert[vert].co);
+ normal_short_to_float_v3(ss->osd_coarse_coords[vert * 2 + 1], mvert[vert].no);
+ }
+ ss->osd_num_coarse_coords = num_verts;
+ ss->osd_coarse_coords_invalid = true;
+ }
+}
+
+void ccgSubSurf__sync_opensubdiv(CCGSubSurf *ss)
+{
+ BLI_assert(ss->meshIFC.numLayers == 2 || ss->meshIFC.numLayers == 3);
+
+ /* Common synchronization steps */
+ ss->osd_compute = U.opensubdiv_compute_type;
+
+ if (ss->skip_grids == false) {
+ /* Make sure OSD evaluator is up-to-date. */
+ if (opensubdiv_ensureEvaluator(ss)) {
+ /* Update coarse points in the OpenSubdiv evaluator. */
+ opensubdiv_updateEvaluatorCoarsePositions(ss);
+
+ /* Evaluate opensubdiv mesh into the CCG grids. */
+ opensubdiv_evaluateGrids(ss);
+ }
+ }
+ else {
+ BLI_assert(ss->meshIFC.numLayers == 3);
+ }
+
+#ifdef DUMP_RESULT_GRIDS
+ ccgSubSurf__dumpCoords(ss);
+#endif
+}
+
+void ccgSubSurf_free_osd_mesh(CCGSubSurf *ss)
+{
+ if (ss->osd_mesh != NULL) {
+ /* TODO(sergey): Make sure free happens form the main thread! */
+ openSubdiv_deleteOsdGLMesh(ss->osd_mesh);
+ ss->osd_mesh = NULL;
+ }
+ if (ss->osd_vao != 0) {
+ glDeleteVertexArrays(1, &ss->osd_vao);
+ ss->osd_vao = 0;
+ }
+}
+
+void ccgSubSurf_getMinMax(CCGSubSurf *ss, float r_min[3], float r_max[3])
+{
+ int i;
+ BLI_assert(ss->skip_grids == true);
+ for (i = 0; i < ss->osd_num_coarse_coords; i++) {
+ /* Coarse coordinates has normals interleaved into the array. */
+ DO_MINMAX(ss->osd_coarse_coords[2 * i], r_min, r_max);
+ }
+}
+
+#endif /* WITH_OPENSUBDIV */
diff --git a/source/blender/blenkernel/intern/CCGSubSurf_opensubdiv_converter.c b/source/blender/blenkernel/intern/CCGSubSurf_opensubdiv_converter.c
new file mode 100644
index 00000000000..c4317f4d740
--- /dev/null
+++ b/source/blender/blenkernel/intern/CCGSubSurf_opensubdiv_converter.c
@@ -0,0 +1,586 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/blenkernel/intern/CCGSubSurf_opensubdiv_converter.c
+ * \ingroup bke
+ */
+
+#ifdef WITH_OPENSUBDIV
+
+#include <stdlib.h>
+
+#include "MEM_guardedalloc.h"
+#include "BLI_sys_types.h" // for intptr_t support
+
+#include "BLI_utildefines.h" /* for BLI_assert */
+#include "BLI_math.h"
+
+#include "CCGSubSurf.h"
+#include "CCGSubSurf_intern.h"
+
+#include "BKE_DerivedMesh.h"
+#include "BKE_mesh_mapping.h"
+
+#include "opensubdiv_capi.h"
+#include "opensubdiv_converter_capi.h"
+
+/* Use mesh element mapping structures during conversion.
+ * Uses more memory but is much faster than naive algorithm.
+ */
+#define USE_MESH_ELEMENT_MAPPING
+
+/**
+ * Converter from DerivedMesh.
+ */
+
+typedef struct ConvDMStorage {
+ CCGSubSurf *ss;
+ DerivedMesh *dm;
+
+#ifdef USE_MESH_ELEMENT_MAPPING
+ MeshElemMap *vert_edge_map,
+ *vert_poly_map,
+ *edge_poly_map;
+ int *vert_edge_mem,
+ *vert_poly_mem,
+ *edge_poly_mem;
+#endif
+} ConvDMStorage;
+
+static OpenSubdiv_SchemeType conv_dm_get_type(
+ const OpenSubdiv_Converter *converter)
+{
+ ConvDMStorage *storage = converter->user_data;
+ if (storage->ss->meshIFC.simpleSubdiv)
+ return OSD_SCHEME_BILINEAR;
+ else
+ return OSD_SCHEME_CATMARK;
+}
+
+static int conv_dm_get_num_faces(const OpenSubdiv_Converter *converter)
+{
+ ConvDMStorage *storage = converter->user_data;
+ DerivedMesh *dm = storage->dm;
+ return dm->getNumPolys(dm);
+}
+
+static int conv_dm_get_num_edges(const OpenSubdiv_Converter *converter)
+{
+ ConvDMStorage *storage = converter->user_data;
+ DerivedMesh *dm = storage->dm;
+ return dm->getNumEdges(dm);
+}
+
+static int conv_dm_get_num_verts(const OpenSubdiv_Converter *converter)
+{
+ ConvDMStorage *storage = converter->user_data;
+ DerivedMesh *dm = storage->dm;
+ return dm->getNumVerts(dm);
+}
+
+static int conv_dm_get_num_face_verts(const OpenSubdiv_Converter *converter,
+ int face)
+{
+ ConvDMStorage *storage = converter->user_data;
+ DerivedMesh *dm = storage->dm;
+ const MPoly *mp = dm->getPolyArray(dm);
+ const MPoly *mpoly = &mp[face];
+ return mpoly->totloop;
+}
+
+static void conv_dm_get_face_verts(const OpenSubdiv_Converter *converter,
+ int face,
+ int *face_verts)
+{
+ ConvDMStorage *storage = converter->user_data;
+ DerivedMesh *dm = storage->dm;
+ const MLoop *ml = dm->getLoopArray(dm);
+ const MPoly *mp = dm->getPolyArray(dm);
+ const MPoly *mpoly = &mp[face];
+ int loop;
+ for (loop = 0; loop < mpoly->totloop; loop++) {
+ face_verts[loop] = ml[mpoly->loopstart + loop].v;
+ }
+}
+
+static void conv_dm_get_face_edges(const OpenSubdiv_Converter *converter,
+ int face,
+ int *face_edges)
+{
+ ConvDMStorage *storage = converter->user_data;
+ DerivedMesh *dm = storage->dm;
+ const MLoop *ml = dm->getLoopArray(dm);
+ const MPoly *mp = dm->getPolyArray(dm);
+ const MPoly *mpoly = &mp[face];
+ int loop;
+ for (loop = 0; loop < mpoly->totloop; loop++) {
+ face_edges[loop] = ml[mpoly->loopstart + loop].e;
+ }
+}
+
+static void conv_dm_get_edge_verts(const OpenSubdiv_Converter *converter,
+ int edge,
+ int *edge_verts)
+{
+ ConvDMStorage *storage = converter->user_data;
+ DerivedMesh *dm = storage->dm;
+ const MEdge *me = dm->getEdgeArray(dm);
+ const MEdge *medge = &me[edge];
+ edge_verts[0] = medge->v1;
+ edge_verts[1] = medge->v2;
+}
+
+static int conv_dm_get_num_edge_faces(const OpenSubdiv_Converter *converter,
+ int edge)
+{
+ ConvDMStorage *storage = converter->user_data;
+#ifndef USE_MESH_ELEMENT_MAPPING
+ DerivedMesh *dm = storage->dm;
+ const MLoop *ml = dm->getLoopArray(dm);
+ const MPoly *mp = dm->getPolyArray(dm);
+ int num = 0, poly;
+ for (poly = 0; poly < dm->getNumPolys(dm); poly++) {
+ const MPoly *mpoly = &mp[poly];
+ int loop;
+ for (loop = 0; loop < mpoly->totloop; loop++) {
+ const MLoop *mloop = &ml[mpoly->loopstart + loop];
+ if (mloop->e == edge) {
+ ++num;
+ break;
+ }
+ }
+ }
+ return num;
+#else
+ return storage->edge_poly_map[edge].count;
+#endif
+}
+
+static void conv_dm_get_edge_faces(const OpenSubdiv_Converter *converter,
+ int edge,
+ int *edge_faces)
+{
+ ConvDMStorage *storage = converter->user_data;
+#ifndef USE_MESH_ELEMENT_MAPPING
+ DerivedMesh *dm = storage->dm;
+ const MLoop *ml = dm->getLoopArray(dm);
+ const MPoly *mp = dm->getPolyArray(dm);
+ int num = 0, poly;
+ for (poly = 0; poly < dm->getNumPolys(dm); poly++) {
+ const MPoly *mpoly = &mp[poly];
+ int loop;
+ for (loop = 0; loop < mpoly->totloop; loop++) {
+ const MLoop *mloop = &ml[mpoly->loopstart + loop];
+ if (mloop->e == edge) {
+ edge_faces[num++] = poly;
+ break;
+ }
+ }
+ }
+#else
+ memcpy(edge_faces,
+ storage->edge_poly_map[edge].indices,
+ sizeof(int) * storage->edge_poly_map[edge].count);
+#endif
+}
+
+static float conv_dm_get_edge_sharpness(const OpenSubdiv_Converter *converter,
+ int edge)
+{
+ ConvDMStorage *storage = converter->user_data;
+ DerivedMesh *dm = storage->dm;
+ CCGSubSurf *ss = storage->ss;
+ const MEdge *medge = dm->getEdgeArray(dm);
+ return (float)medge[edge].crease / 255.0f * ss->subdivLevels;
+}
+
+static int conv_dm_get_num_vert_edges(const OpenSubdiv_Converter *converter,
+ int vert)
+{
+ ConvDMStorage *storage = converter->user_data;
+#ifndef USE_MESH_ELEMENT_MAPPING
+ DerivedMesh *dm = storage->dm;
+ const MEdge *me = dm->getEdgeArray(dm);
+ int num = 0, edge;
+ for (edge = 0; edge < dm->getNumEdges(dm); edge++) {
+ const MEdge *medge = &me[edge];
+ if (medge->v1 == vert || medge->v2 == vert) {
+ ++num;
+ }
+ }
+ return num;
+#else
+ return storage->vert_edge_map[vert].count;
+#endif
+}
+
+static void conv_dm_get_vert_edges(const OpenSubdiv_Converter *converter,
+ int vert,
+ int *vert_edges)
+{
+ ConvDMStorage *storage = converter->user_data;
+#ifndef USE_MESH_ELEMENT_MAPPING
+ DerivedMesh *dm = storage->dm;
+ const MEdge *me = dm->getEdgeArray(dm);
+ int num = 0, edge;
+ for (edge = 0; edge < dm->getNumEdges(dm); edge++) {
+ const MEdge *medge = &me[edge];
+ if (medge->v1 == vert || medge->v2 == vert) {
+ vert_edges[num++] = edge;
+ }
+ }
+#else
+ memcpy(vert_edges,
+ storage->vert_edge_map[vert].indices,
+ sizeof(int) * storage->vert_edge_map[vert].count);
+#endif
+}
+
+static int conv_dm_get_num_vert_faces(const OpenSubdiv_Converter *converter,
+ int vert)
+{
+ ConvDMStorage *storage = converter->user_data;
+#ifndef USE_MESH_ELEMENT_MAPPING
+ DerivedMesh *dm = storage->dm;
+ const MLoop *ml = dm->getLoopArray(dm);
+ const MPoly *mp = dm->getPolyArray(dm);
+ int num = 0, poly;
+ for (poly = 0; poly < dm->getNumPolys(dm); poly++) {
+ const MPoly *mpoly = &mp[poly];
+ int loop;
+ for (loop = 0; loop < mpoly->totloop; loop++) {
+ const MLoop *mloop = &ml[mpoly->loopstart + loop];
+ if (mloop->v == vert) {
+ ++num;
+ break;
+ }
+ }
+ }
+ return num;
+#else
+ return storage->vert_poly_map[vert].count;
+#endif
+}
+
+static void conv_dm_get_vert_faces(const OpenSubdiv_Converter *converter,
+ int vert,
+ int *vert_faces)
+{
+ ConvDMStorage *storage = converter->user_data;
+#ifndef USE_MESH_ELEMENT_MAPPING
+ DerivedMesh *dm = storage->dm;
+ const MLoop *ml = dm->getLoopArray(dm);
+ const MPoly *mp = dm->getPolyArray(dm);
+ int num = 0, poly;
+ for (poly = 0; poly < dm->getNumPolys(dm); poly++) {
+ const MPoly *mpoly = &mp[poly];
+ int loop;
+ for (loop = 0; loop < mpoly->totloop; loop++) {
+ const MLoop *mloop = &ml[mpoly->loopstart + loop];
+ if (mloop->v == vert) {
+ vert_faces[num++] = poly;
+ break;
+ }
+ }
+ }
+#else
+ memcpy(vert_faces,
+ storage->vert_poly_map[vert].indices,
+ sizeof(int) * storage->vert_poly_map[vert].count);
+#endif
+}
+
+static void conv_dm_free_user_data(const OpenSubdiv_Converter *converter)
+{
+ ConvDMStorage *user_data = converter->user_data;
+#ifdef USE_MESH_ELEMENT_MAPPING
+ MEM_freeN(user_data->vert_edge_map);
+ MEM_freeN(user_data->vert_edge_mem);
+ MEM_freeN(user_data->vert_poly_map);
+ MEM_freeN(user_data->vert_poly_mem);
+ MEM_freeN(user_data->edge_poly_map);
+ MEM_freeN(user_data->edge_poly_mem);
+#endif
+ MEM_freeN(user_data);
+}
+
+void ccgSubSurf_converter_setup_from_derivedmesh(
+ CCGSubSurf *ss,
+ DerivedMesh *dm,
+ OpenSubdiv_Converter *converter)
+{
+ ConvDMStorage *user_data;
+
+ converter->get_type = conv_dm_get_type;
+
+ converter->get_num_faces = conv_dm_get_num_faces;
+ converter->get_num_edges = conv_dm_get_num_edges;
+ converter->get_num_verts = conv_dm_get_num_verts;
+
+ converter->get_num_face_verts = conv_dm_get_num_face_verts;
+ converter->get_face_verts = conv_dm_get_face_verts;
+ converter->get_face_edges = conv_dm_get_face_edges;
+
+ converter->get_edge_verts = conv_dm_get_edge_verts;
+ converter->get_num_edge_faces = conv_dm_get_num_edge_faces;
+ converter->get_edge_faces = conv_dm_get_edge_faces;
+ converter->get_edge_sharpness = conv_dm_get_edge_sharpness;
+
+ converter->get_num_vert_edges = conv_dm_get_num_vert_edges;
+ converter->get_vert_edges = conv_dm_get_vert_edges;
+ converter->get_num_vert_faces = conv_dm_get_num_vert_faces;
+ converter->get_vert_faces = conv_dm_get_vert_faces;
+
+ user_data = MEM_mallocN(sizeof(ConvDMStorage), __func__);
+ user_data->ss = ss;
+ user_data->dm = dm;
+ converter->free_user_data = conv_dm_free_user_data;
+ converter->user_data = user_data;
+
+#ifdef USE_MESH_ELEMENT_MAPPING
+ {
+ const MEdge *medge = dm->getEdgeArray(dm);
+ const MLoop *mloop = dm->getLoopArray(dm);
+ const MPoly *mpoly = dm->getPolyArray(dm);
+ const int num_vert = dm->getNumVerts(dm),
+ num_edge = dm->getNumEdges(dm),
+ num_loop = dm->getNumLoops(dm),
+ num_poly = dm->getNumPolys(dm);
+ BKE_mesh_vert_edge_map_create(&user_data->vert_edge_map,
+ &user_data->vert_edge_mem,
+ medge,
+ num_vert,
+ num_edge);
+
+ BKE_mesh_vert_poly_map_create(&user_data->vert_poly_map,
+ &user_data->vert_poly_mem,
+ mpoly,
+ mloop,
+ num_vert,
+ num_poly,
+ num_loop);
+
+ BKE_mesh_edge_poly_map_create(&user_data->edge_poly_map,
+ &user_data->edge_poly_mem,
+ medge,
+ num_edge,
+ mpoly,
+ num_poly,
+ mloop,
+ num_loop);
+ }
+#endif /* USE_MESH_ELEMENT_MAPPING */
+}
+
+/**
+ * Converter from CCGSubSurf
+ */
+
+static OpenSubdiv_SchemeType conv_ccg_get_bilinear_type(
+ const OpenSubdiv_Converter *converter)
+{
+ CCGSubSurf *ss = converter->user_data;
+ if (ss->meshIFC.simpleSubdiv) {
+ return OSD_SCHEME_BILINEAR;
+ }
+ else {
+ return OSD_SCHEME_CATMARK;
+ }
+}
+
+static int conv_ccg_get_num_faces(const OpenSubdiv_Converter *converter)
+{
+ CCGSubSurf *ss = converter->user_data;
+ return ss->fMap->numEntries;
+}
+
+static int conv_ccg_get_num_edges(const OpenSubdiv_Converter *converter)
+{
+ CCGSubSurf *ss = converter->user_data;
+ return ss->eMap->numEntries;
+}
+
+static int conv_ccg_get_num_verts(const OpenSubdiv_Converter *converter)
+{
+ CCGSubSurf *ss = converter->user_data;
+ return ss->vMap->numEntries;
+}
+
+static int conv_ccg_get_num_face_verts(const OpenSubdiv_Converter *converter,
+ int face)
+{
+ CCGSubSurf *ss = converter->user_data;
+ CCGFace *ccg_face = ccgSubSurf_getFace(ss, SET_INT_IN_POINTER(face));
+ return ccgSubSurf_getFaceNumVerts(ccg_face);
+}
+
+static void conv_ccg_get_face_verts(const OpenSubdiv_Converter *converter,
+ int face,
+ int *face_verts)
+{
+ CCGSubSurf *ss = converter->user_data;
+ CCGFace *ccg_face = ccgSubSurf_getFace(ss, SET_INT_IN_POINTER(face));
+ int num_face_verts = ccgSubSurf_getFaceNumVerts(ccg_face);
+ int loop;
+ for (loop = 0; loop < num_face_verts; loop++) {
+ CCGVert *ccg_vert = ccgSubSurf_getFaceVert(ccg_face, loop);
+ face_verts[loop] = GET_INT_FROM_POINTER(ccgSubSurf_getVertVertHandle(ccg_vert));
+ }
+}
+
+static void conv_ccg_get_face_edges(const OpenSubdiv_Converter *converter,
+ int face,
+ int *face_edges)
+{
+ CCGSubSurf *ss = converter->user_data;
+ CCGFace *ccg_face = ccgSubSurf_getFace(ss, SET_INT_IN_POINTER(face));
+ int num_face_verts = ccgSubSurf_getFaceNumVerts(ccg_face);
+ int loop;
+ for (loop = 0; loop < num_face_verts; loop++) {
+ CCGEdge *ccg_edge = ccgSubSurf_getFaceEdge(ccg_face, loop);
+ face_edges[loop] = GET_INT_FROM_POINTER(ccgSubSurf_getEdgeEdgeHandle(ccg_edge));
+ }
+}
+
+static void conv_ccg_get_edge_verts(const OpenSubdiv_Converter *converter,
+ int edge,
+ int *edge_verts)
+{
+ CCGSubSurf *ss = converter->user_data;
+ CCGEdge *ccg_edge = ccgSubSurf_getEdge(ss, SET_INT_IN_POINTER(edge));
+ CCGVert *ccg_vert0 = ccgSubSurf_getEdgeVert0(ccg_edge);
+ CCGVert *ccg_vert1 = ccgSubSurf_getEdgeVert1(ccg_edge);
+ edge_verts[0] = GET_INT_FROM_POINTER(ccgSubSurf_getVertVertHandle(ccg_vert0));
+ edge_verts[1] = GET_INT_FROM_POINTER(ccgSubSurf_getVertVertHandle(ccg_vert1));
+}
+
+static int conv_ccg_get_num_edge_faces(const OpenSubdiv_Converter *converter,
+ int edge)
+{
+ CCGSubSurf *ss = converter->user_data;
+ CCGEdge *ccg_edge = ccgSubSurf_getEdge(ss, SET_INT_IN_POINTER(edge));
+ return ccgSubSurf_getEdgeNumFaces(ccg_edge);
+}
+
+static void conv_ccg_get_edge_faces(const OpenSubdiv_Converter *converter,
+ int edge,
+ int *edge_faces)
+{
+ CCGSubSurf *ss = converter->user_data;
+ CCGEdge *ccg_edge = ccgSubSurf_getEdge(ss, SET_INT_IN_POINTER(edge));
+ int num_edge_faces = ccgSubSurf_getEdgeNumFaces(ccg_edge);
+ int face;
+ for (face = 0; face < num_edge_faces; face++) {
+ CCGFace *ccg_face = ccgSubSurf_getEdgeFace(ccg_edge, face);
+ edge_faces[face] = GET_INT_FROM_POINTER(ccgSubSurf_getFaceFaceHandle(ccg_face));
+ }
+}
+
+static float conv_ccg_get_edge_sharpness(const OpenSubdiv_Converter *converter,
+ int edge)
+{
+ CCGSubSurf *ss = converter->user_data;
+ CCGEdge *ccg_edge = ccgSubSurf_getEdge(ss, SET_INT_IN_POINTER(edge));
+ /* TODO(sergey): Multiply by subdivision level once CPU evaluator
+ * is switched to uniform subdivision type.
+ */
+ return ccg_edge->crease;
+}
+
+static int conv_ccg_get_num_vert_edges(const OpenSubdiv_Converter *converter,
+ int vert)
+{
+ CCGSubSurf *ss = converter->user_data;
+ CCGVert *ccg_vert = ccgSubSurf_getVert(ss, SET_INT_IN_POINTER(vert));
+ return ccgSubSurf_getVertNumEdges(ccg_vert);
+}
+
+static void conv_ccg_get_vert_edges(const OpenSubdiv_Converter *converter,
+ int vert,
+ int *vert_edges)
+{
+ CCGSubSurf *ss = converter->user_data;
+ CCGVert *ccg_vert = ccgSubSurf_getVert(ss, SET_INT_IN_POINTER(vert));
+ int num_vert_edges = ccgSubSurf_getVertNumEdges(ccg_vert);
+ int edge;
+ for (edge = 0; edge < num_vert_edges; edge++) {
+ CCGEdge *ccg_edge = ccgSubSurf_getVertEdge(ccg_vert, edge);
+ vert_edges[edge] = GET_INT_FROM_POINTER(ccgSubSurf_getEdgeEdgeHandle(ccg_edge));
+ }
+}
+
+static int conv_ccg_get_num_vert_faces(const OpenSubdiv_Converter *converter,
+ int vert)
+{
+ CCGSubSurf *ss = converter->user_data;
+ CCGVert *ccg_vert = ccgSubSurf_getVert(ss, SET_INT_IN_POINTER(vert));
+ return ccgSubSurf_getVertNumFaces(ccg_vert);
+}
+
+static void conv_ccg_get_vert_faces(const OpenSubdiv_Converter *converter,
+ int vert,
+ int *vert_faces)
+{
+ CCGSubSurf *ss = converter->user_data;
+ CCGVert *ccg_vert = ccgSubSurf_getVert(ss, SET_INT_IN_POINTER(vert));
+ int num_vert_faces = ccgSubSurf_getVertNumFaces(ccg_vert);
+ int face;
+ for (face = 0; face < num_vert_faces; face++) {
+ CCGFace *ccg_face = ccgSubSurf_getVertFace(ccg_vert, face);
+ vert_faces[face] = GET_INT_FROM_POINTER(ccgSubSurf_getFaceFaceHandle(ccg_face));
+ }
+}
+
+void ccgSubSurf_converter_setup_from_ccg(CCGSubSurf *ss,
+ OpenSubdiv_Converter *converter)
+{
+ converter->get_type = conv_ccg_get_bilinear_type;
+
+ converter->get_num_faces = conv_ccg_get_num_faces;
+ converter->get_num_edges = conv_ccg_get_num_edges;
+ converter->get_num_verts = conv_ccg_get_num_verts;
+
+ converter->get_num_face_verts = conv_ccg_get_num_face_verts;
+ converter->get_face_verts = conv_ccg_get_face_verts;
+ converter->get_face_edges = conv_ccg_get_face_edges;
+
+ converter->get_edge_verts = conv_ccg_get_edge_verts;
+ converter->get_num_edge_faces = conv_ccg_get_num_edge_faces;
+ converter->get_edge_faces = conv_ccg_get_edge_faces;
+ converter->get_edge_sharpness = conv_ccg_get_edge_sharpness;
+
+ converter->get_num_vert_edges = conv_ccg_get_num_vert_edges;
+ converter->get_vert_edges = conv_ccg_get_vert_edges;
+ converter->get_num_vert_faces = conv_ccg_get_num_vert_faces;
+ converter->get_vert_faces = conv_ccg_get_vert_faces;
+
+ converter->free_user_data = NULL;
+ converter->user_data = ss;
+}
+
+void ccgSubSurf_converter_free(
+ struct OpenSubdiv_Converter *converter)
+{
+ if (converter->free_user_data) {
+ converter->free_user_data(converter);
+ }
+}
+
+#endif /* WITH_OPENSUBDIV */
diff --git a/source/blender/blenkernel/intern/CCGSubSurf_util.c b/source/blender/blenkernel/intern/CCGSubSurf_util.c
new file mode 100644
index 00000000000..9af69115559
--- /dev/null
+++ b/source/blender/blenkernel/intern/CCGSubSurf_util.c
@@ -0,0 +1,306 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/blenkernel/intern/CCGSubSurf_util.c
+ * \ingroup bke
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+
+#include "MEM_guardedalloc.h"
+#include "BLI_sys_types.h" // for intptr_t support
+
+#include "BLI_utildefines.h" /* for BLI_assert */
+
+#include "CCGSubSurf.h"
+#include "CCGSubSurf_intern.h"
+
+/**
+ * Hash implementation.
+ */
+
+static int kHashSizes[] = {
+ 1, 3, 5, 11, 17, 37, 67, 131, 257, 521, 1031, 2053, 4099, 8209,
+ 16411, 32771, 65537, 131101, 262147, 524309, 1048583, 2097169,
+ 4194319, 8388617, 16777259, 33554467, 67108879, 134217757, 268435459
+};
+
+/* Generic hash functions. */
+
+EHash *ccg_ehash_new(int estimatedNumEntries,
+ CCGAllocatorIFC *allocatorIFC,
+ CCGAllocatorHDL allocator)
+{
+ EHash *eh = allocatorIFC->alloc(allocator, sizeof(*eh));
+ eh->allocatorIFC = *allocatorIFC;
+ eh->allocator = allocator;
+ eh->numEntries = 0;
+ eh->curSizeIdx = 0;
+ while (kHashSizes[eh->curSizeIdx] < estimatedNumEntries)
+ eh->curSizeIdx++;
+ eh->curSize = kHashSizes[eh->curSizeIdx];
+ eh->buckets = EHASH_alloc(eh, eh->curSize * sizeof(*eh->buckets));
+ memset(eh->buckets, 0, eh->curSize * sizeof(*eh->buckets));
+
+ return eh;
+}
+
+void ccg_ehash_free(EHash *eh, EHEntryFreeFP freeEntry, void *userData)
+{
+ int numBuckets = eh->curSize;
+
+ while (numBuckets--) {
+ EHEntry *entry = eh->buckets[numBuckets];
+
+ while (entry) {
+ EHEntry *next = entry->next;
+
+ freeEntry(entry, userData);
+
+ entry = next;
+ }
+ }
+
+ EHASH_free(eh, eh->buckets);
+ EHASH_free(eh, eh);
+}
+
+void ccg_ehash_insert(EHash *eh, EHEntry *entry)
+{
+ int numBuckets = eh->curSize;
+ int hash = EHASH_hash(eh, entry->key);
+ entry->next = eh->buckets[hash];
+ eh->buckets[hash] = entry;
+ eh->numEntries++;
+
+ if (UNLIKELY(eh->numEntries > (numBuckets * 3))) {
+ EHEntry **oldBuckets = eh->buckets;
+ eh->curSize = kHashSizes[++eh->curSizeIdx];
+
+ eh->buckets = EHASH_alloc(eh, eh->curSize * sizeof(*eh->buckets));
+ memset(eh->buckets, 0, eh->curSize * sizeof(*eh->buckets));
+
+ while (numBuckets--) {
+ for (entry = oldBuckets[numBuckets]; entry; ) {
+ EHEntry *next = entry->next;
+
+ hash = EHASH_hash(eh, entry->key);
+ entry->next = eh->buckets[hash];
+ eh->buckets[hash] = entry;
+
+ entry = next;
+ }
+ }
+
+ EHASH_free(eh, oldBuckets);
+ }
+}
+
+void *ccg_ehash_lookupWithPrev(EHash *eh, void *key, void ***prevp_r)
+{
+ int hash = EHASH_hash(eh, key);
+ void **prevp = (void **) &eh->buckets[hash];
+ EHEntry *entry;
+
+ for (; (entry = *prevp); prevp = (void **) &entry->next) {
+ if (entry->key == key) {
+ *prevp_r = (void **) prevp;
+ return entry;
+ }
+ }
+
+ return NULL;
+}
+
+void *ccg_ehash_lookup(EHash *eh, void *key)
+{
+ int hash = EHASH_hash(eh, key);
+ EHEntry *entry;
+
+ for (entry = eh->buckets[hash]; entry; entry = entry->next) {
+ if (entry->key == key)
+ break;
+ }
+
+ return entry;
+}
+
+/* Hash elements iteration. */
+
+void ccg_ehashIterator_init(EHash *eh, EHashIterator *ehi)
+{
+ /* fill all members */
+ ehi->eh = eh;
+ ehi->curBucket = -1;
+ ehi->curEntry = NULL;
+
+ while (!ehi->curEntry) {
+ ehi->curBucket++;
+ if (ehi->curBucket == ehi->eh->curSize)
+ break;
+ ehi->curEntry = ehi->eh->buckets[ehi->curBucket];
+ }
+}
+
+void *ccg_ehashIterator_getCurrent(EHashIterator *ehi)
+{
+ return ehi->curEntry;
+}
+
+void ccg_ehashIterator_next(EHashIterator *ehi)
+{
+ if (ehi->curEntry) {
+ ehi->curEntry = ehi->curEntry->next;
+ while (!ehi->curEntry) {
+ ehi->curBucket++;
+ if (ehi->curBucket == ehi->eh->curSize)
+ break;
+ ehi->curEntry = ehi->eh->buckets[ehi->curBucket];
+ }
+ }
+}
+int ccg_ehashIterator_isStopped(EHashIterator *ehi)
+{
+ return !ehi->curEntry;
+}
+
+/**
+ * Standard allocator implementarion.
+ */
+
+static void *_stdAllocator_alloc(CCGAllocatorHDL UNUSED(a), int numBytes)
+{
+ return MEM_mallocN(numBytes, "CCG standard alloc");
+}
+
+static void *_stdAllocator_realloc(CCGAllocatorHDL UNUSED(a),
+ void *ptr,
+ int newSize,
+ int UNUSED(oldSize))
+{
+ return MEM_reallocN(ptr, newSize);
+}
+
+static void _stdAllocator_free(CCGAllocatorHDL UNUSED(a), void *ptr)
+{
+ MEM_freeN(ptr);
+}
+
+CCGAllocatorIFC *ccg_getStandardAllocatorIFC(void)
+{
+ static CCGAllocatorIFC ifc;
+
+ ifc.alloc = _stdAllocator_alloc;
+ ifc.realloc = _stdAllocator_realloc;
+ ifc.free = _stdAllocator_free;
+ ifc.release = NULL;
+
+ return &ifc;
+}
+
+/**
+ * Catmull-Clark Gridding Subdivision Surface.
+ */
+
+#ifdef DUMP_RESULT_GRIDS
+void ccgSubSurf__dumpCoords(CCGSubSurf *ss)
+{
+ int vertDataSize = ss->meshIFC.vertDataSize;
+ int subdivLevels = ss->subdivLevels;
+ int gridSize = ccg_gridsize(subdivLevels);
+ int edgeSize = ccg_edgesize(subdivLevels);
+ int i, index, S;
+
+ for (i = 0, index = 0; i < ss->vMap->curSize; i++) {
+ CCGVert *v = (CCGVert *) ss->vMap->buckets[i];
+ for (; v; v = v->next, index++) {
+ float *co = VERT_getCo(v, subdivLevels);
+ printf("vertex index=%d, co=(%f, %f, %f)\n",
+ index, co[0], co[1], co[2]);
+ }
+ }
+
+ for (i = 0, index = 0; i < ss->eMap->curSize; i++) {
+ CCGEdge *e = (CCGEdge *) ss->eMap->buckets[i];
+ for (; e; e = e->next, index++) {
+ int x;
+ float *co = VERT_getCo(e->v0, subdivLevels);
+ printf("edge index=%d, start_co=(%f, %f, %f)\n",
+ index, co[0], co[1], co[2]);
+ for (x = 0; x < edgeSize; x++) {
+ float *co = EDGE_getCo(e, subdivLevels, x);
+ printf("edge index=%d, seg=%d, co=(%f, %f, %f)\n",
+ index, x, co[0], co[1], co[2]);
+ }
+ co = VERT_getCo(e->v1, subdivLevels);
+ printf("edge index=%d, end_co=(%f, %f, %f)\n",
+ index, co[0], co[1], co[2]);
+ }
+ }
+
+ for (i = 0, index = 0; i < ss->fMap->curSize; i++) {
+ CCGFace *f = (CCGFace *) ss->fMap->buckets[i];
+ for (; f; f = f->next, index++) {
+ for (S = 0; S < f->numVerts; S++) {
+ CCGVert *v = FACE_getVerts(f)[S];
+ float *co = VERT_getCo(v, subdivLevels);
+ printf("face index=%d, vertex=%d, coord=(%f, %f, %f)\n",
+ index, S, co[0], co[1], co[2]);
+ }
+ }
+ }
+
+ for (i = 0, index = 0; i < ss->fMap->curSize; i++) {
+ CCGFace *f = (CCGFace *) ss->fMap->buckets[i];
+ for (; f; f = f->next, index++) {
+ for (S = 0; S < f->numVerts; S++) {
+ CCGEdge *e = FACE_getEdges(f)[S];
+ float *co1 = VERT_getCo(e->v0, subdivLevels);
+ float *co2 = VERT_getCo(e->v1, subdivLevels);
+ printf("face index=%d, edge=%d, coord1=(%f, %f, %f), coord2=(%f, %f, %f)\n",
+ index, S, co1[0], co1[1], co1[2], co2[0], co2[1], co2[2]);
+ }
+ }
+ }
+
+ for (i = 0, index = 0; i < ss->fMap->curSize; i++) {
+ CCGFace *f = (CCGFace *) ss->fMap->buckets[i];
+ for (; f; f = f->next, index++) {
+ for (S = 0; S < f->numVerts; S++) {
+ int x, y;
+ for (x = 0; x < gridSize; x++) {
+ for (y = 0; y < gridSize; y++) {
+ float *co = FACE_getIFCo(f, subdivLevels, S, x, y);
+ printf("face index=%d. corner=%d, x=%d, y=%d, coord=(%f, %f, %f)\n",
+ index, S, x, y, co[0], co[1], co[2]);
+ }
+ }
+ for (x = 0; x < gridSize; x++) {
+ float *co = FACE_getIECo(f, subdivLevels, S, x);
+ printf("face index=%d. cornder=%d, ie_index=%d, coord=(%f, %f, %f)\n",
+ index, S, x, co[0], co[1], co[2]);
+ }
+ }
+ }
+ }
+}
+#endif /* DUMP_RESULT_GRIDS */
diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c
index 3aa4e0abbba..20dabbdc323 100644
--- a/source/blender/blenkernel/intern/DerivedMesh.c
+++ b/source/blender/blenkernel/intern/DerivedMesh.c
@@ -72,15 +72,16 @@ static DerivedMesh *navmesh_dm_createNavMeshForVisualization(DerivedMesh *dm);
#include "BLI_sys_types.h" /* for intptr_t support */
-#include "GL/glew.h"
-
#include "GPU_buffers.h"
-#include "GPU_draw.h"
#include "GPU_extensions.h"
-#include "GPU_material.h"
+#include "GPU_glew.h"
+
+#ifdef WITH_OPENSUBDIV
+# include "DNA_userdef_types.h"
+#endif
/* very slow! enable for testing only! */
-// #define USE_MODIFIER_VALIDATE
+//#define USE_MODIFIER_VALIDATE
#ifdef USE_MODIFIER_VALIDATE
# define ASSERT_IS_VALID_DM(dm) (BLI_assert((dm == NULL) || (DM_is_valid(dm) == true)))
@@ -223,6 +224,11 @@ static MPoly *dm_dupPolyArray(DerivedMesh *dm)
return tmp;
}
+static int dm_getNumLoopTri(DerivedMesh *dm)
+{
+ return dm->looptris.num;
+}
+
static CustomData *dm_getVertCData(DerivedMesh *dm)
{
return &dm->vertData;
@@ -248,6 +254,10 @@ static CustomData *dm_getPolyCData(DerivedMesh *dm)
return &dm->polyData;
}
+/**
+ * Utility function to initialize a DerivedMesh's function pointers to
+ * the default implementation (for those functions which have a default)
+ */
void DM_init_funcs(DerivedMesh *dm)
{
/* default function implementations */
@@ -262,6 +272,9 @@ void DM_init_funcs(DerivedMesh *dm)
dm->dupLoopArray = dm_dupLoopArray;
dm->dupPolyArray = dm_dupPolyArray;
+ /* subtypes handle getting actual data */
+ dm->getNumLoopTri = dm_getNumLoopTri;
+
dm->getVertDataLayout = dm_getVertCData;
dm->getEdgeDataLayout = dm_getEdgeCData;
dm->getTessFaceDataLayout = dm_getTessFaceCData;
@@ -281,8 +294,14 @@ void DM_init_funcs(DerivedMesh *dm)
bvhcache_init(&dm->bvhCache);
}
-void DM_init(DerivedMesh *dm, DerivedMeshType type, int numVerts, int numEdges,
- int numTessFaces, int numLoops, int numPolys)
+/**
+ * Utility function to initialize a DerivedMesh for the desired number
+ * of vertices, edges and faces (doesn't allocate memory for them, just
+ * sets up the custom data layers)
+ */
+void DM_init(
+ DerivedMesh *dm, DerivedMeshType type, int numVerts, int numEdges,
+ int numTessFaces, int numLoops, int numPolys)
{
dm->type = type;
dm->numVertData = numVerts;
@@ -298,27 +317,28 @@ void DM_init(DerivedMesh *dm, DerivedMeshType type, int numVerts, int numEdges,
dm->dirty = 0;
/* don't use CustomData_reset(...); because we dont want to touch customdata */
- fill_vn_i(dm->vertData.typemap, CD_NUMTYPES, -1);
- fill_vn_i(dm->edgeData.typemap, CD_NUMTYPES, -1);
- fill_vn_i(dm->faceData.typemap, CD_NUMTYPES, -1);
- fill_vn_i(dm->loopData.typemap, CD_NUMTYPES, -1);
- fill_vn_i(dm->polyData.typemap, CD_NUMTYPES, -1);
-}
-
-void DM_from_template(DerivedMesh *dm, DerivedMesh *source, DerivedMeshType type,
- int numVerts, int numEdges, int numTessFaces,
- int numLoops, int numPolys)
-{
- CustomData_copy(&source->vertData, &dm->vertData, CD_MASK_DERIVEDMESH,
- CD_CALLOC, numVerts);
- CustomData_copy(&source->edgeData, &dm->edgeData, CD_MASK_DERIVEDMESH,
- CD_CALLOC, numEdges);
- CustomData_copy(&source->faceData, &dm->faceData, CD_MASK_DERIVEDMESH,
- CD_CALLOC, numTessFaces);
- CustomData_copy(&source->loopData, &dm->loopData, CD_MASK_DERIVEDMESH,
- CD_CALLOC, numLoops);
- CustomData_copy(&source->polyData, &dm->polyData, CD_MASK_DERIVEDMESH,
- CD_CALLOC, numPolys);
+ copy_vn_i(dm->vertData.typemap, CD_NUMTYPES, -1);
+ copy_vn_i(dm->edgeData.typemap, CD_NUMTYPES, -1);
+ copy_vn_i(dm->faceData.typemap, CD_NUMTYPES, -1);
+ copy_vn_i(dm->loopData.typemap, CD_NUMTYPES, -1);
+ copy_vn_i(dm->polyData.typemap, CD_NUMTYPES, -1);
+}
+
+/**
+ * Utility function to initialize a DerivedMesh for the desired number
+ * of vertices, edges and faces, with a layer setup copied from source
+ */
+void DM_from_template_ex(
+ DerivedMesh *dm, DerivedMesh *source, DerivedMeshType type,
+ int numVerts, int numEdges, int numTessFaces,
+ int numLoops, int numPolys,
+ CustomDataMask mask)
+{
+ CustomData_copy(&source->vertData, &dm->vertData, mask, CD_CALLOC, numVerts);
+ CustomData_copy(&source->edgeData, &dm->edgeData, mask, CD_CALLOC, numEdges);
+ CustomData_copy(&source->faceData, &dm->faceData, mask, CD_CALLOC, numTessFaces);
+ CustomData_copy(&source->loopData, &dm->loopData, mask, CD_CALLOC, numLoops);
+ CustomData_copy(&source->polyData, &dm->polyData, mask, CD_CALLOC, numPolys);
dm->cd_flag = source->cd_flag;
@@ -334,6 +354,17 @@ void DM_from_template(DerivedMesh *dm, DerivedMesh *source, DerivedMeshType type
dm->needsFree = 1;
dm->dirty = 0;
}
+void DM_from_template(
+ DerivedMesh *dm, DerivedMesh *source, DerivedMeshType type,
+ int numVerts, int numEdges, int numTessFaces,
+ int numLoops, int numPolys)
+{
+ DM_from_template_ex(
+ dm, source, type,
+ numVerts, numEdges, numTessFaces,
+ numLoops, numPolys,
+ CD_MASK_DERIVEDMESH);
+}
int DM_release(DerivedMesh *dm)
{
@@ -352,6 +383,10 @@ int DM_release(DerivedMesh *dm)
dm->totmat = 0;
}
+ MEM_SAFE_FREE(dm->looptris.array);
+ dm->looptris.num = 0;
+ dm->looptris.num_alloc = 0;
+
return 1;
}
else {
@@ -395,9 +430,9 @@ void DM_ensure_normals(DerivedMesh *dm)
BLI_assert((dm->dirty & DM_DIRTY_NORMALS) == 0);
}
-static void DM_calc_loop_normals(DerivedMesh *dm, float split_angle)
+static void DM_calc_loop_normals(DerivedMesh *dm, const bool use_split_normals, float split_angle)
{
- dm->calcLoopNormals(dm, split_angle);
+ dm->calcLoopNormals(dm, use_split_normals, split_angle);
dm->dirty |= DM_DIRTY_TESS_CDLAYERS;
}
@@ -415,7 +450,7 @@ void DM_ensure_tessface(DerivedMesh *dm)
/* printf("info %s: polys -> ngons calculated\n", __func__); */
}
else {
- printf("warning %s: could not create tessfaces from %d polygons, dm->type=%d\n",
+ printf("warning %s: could not create tessfaces from %d polygons, dm->type=%u\n",
__func__, numPolys, dm->type);
}
}
@@ -428,6 +463,57 @@ void DM_ensure_tessface(DerivedMesh *dm)
dm->dirty &= ~DM_DIRTY_TESS_CDLAYERS;
}
+/**
+ * Ensure the array is large enough
+ */
+void DM_ensure_looptri_data(DerivedMesh *dm)
+{
+ const unsigned int totpoly = dm->numPolyData;
+ const unsigned int totloop = dm->numLoopData;
+ const int looptris_num = poly_to_tri_count(totpoly, totloop);
+
+ if ((looptris_num > dm->looptris.num_alloc) ||
+ (looptris_num < dm->looptris.num_alloc * 2) ||
+ (totpoly == 0))
+ {
+ MEM_SAFE_FREE(dm->looptris.array);
+ dm->looptris.num_alloc = 0;
+ dm->looptris.num = 0;
+ }
+
+ if (totpoly) {
+ if (dm->looptris.array == NULL) {
+ dm->looptris.array = MEM_mallocN(sizeof(*dm->looptris.array) * looptris_num, __func__);
+ dm->looptris.num_alloc = looptris_num;
+ }
+
+ dm->looptris.num = looptris_num;
+ }
+}
+
+/**
+ * The purpose of this function is that we can call:
+ * `dm->getLoopTriArray(dm)` and get the array returned.
+ */
+void DM_ensure_looptri(DerivedMesh *dm)
+{
+ const int numPolys = dm->getNumPolys(dm);
+
+ if ((dm->looptris.num == 0) && (numPolys != 0)) {
+ dm->recalcLoopTri(dm);
+ }
+}
+
+void DM_verttri_from_looptri(MVertTri *verttri, const MLoop *mloop, const MLoopTri *looptri, int looptri_num)
+{
+ int i;
+ for (i = 0; i < looptri_num; i++) {
+ verttri[i].tri[0] = mloop[looptri[i].tri[0]].v;
+ verttri[i].tri[1] = mloop[looptri[i].tri[1]].v;
+ verttri[i].tri[2] = mloop[looptri[i].tri[2]].v;
+ }
+}
+
/* Update tessface CD data from loop/poly ones. Needed when not retessellating after modstack evaluation. */
/* NOTE: Assumes dm has valid tessellated data! */
void DM_update_tessface_data(DerivedMesh *dm)
@@ -456,7 +542,8 @@ void DM_update_tessface_data(DerivedMesh *dm)
CustomData_has_layer(fdata, CD_MCOL) ||
CustomData_has_layer(fdata, CD_PREVIEW_MCOL) ||
CustomData_has_layer(fdata, CD_ORIGSPACE) ||
- CustomData_has_layer(fdata, CD_TESSLOOPNORMAL))
+ CustomData_has_layer(fdata, CD_TESSLOOPNORMAL) ||
+ CustomData_has_layer(fdata, CD_TANGENT))
{
loopindex = MEM_mallocN(sizeof(*loopindex) * totface, __func__);
@@ -492,6 +579,69 @@ void DM_update_tessface_data(DerivedMesh *dm)
dm->dirty &= ~DM_DIRTY_TESS_CDLAYERS;
}
+void DM_generate_tangent_tessface_data(DerivedMesh *dm, bool generate)
+{
+ int i;
+ MFace *mf, *mface = dm->getTessFaceArray(dm);
+ MPoly *mp = dm->getPolyArray(dm);
+ MLoop *ml = dm->getLoopArray(dm);
+
+ CustomData *fdata = dm->getTessFaceDataLayout(dm);
+ CustomData *pdata = dm->getPolyDataLayout(dm);
+ CustomData *ldata = dm->getLoopDataLayout(dm);
+
+ const int totface = dm->getNumTessFaces(dm);
+ int mf_idx;
+
+ int *polyindex = CustomData_get_layer(fdata, CD_ORIGINDEX);
+ unsigned int (*loopindex)[4];
+
+ /* Should never occure, but better abort than segfault! */
+ if (!polyindex)
+ return;
+
+ if (generate) {
+ for (i = 0; i < ldata->totlayer; i++) {
+ if (ldata->layers[i].type == CD_TANGENT)
+ CustomData_add_layer_named(fdata, CD_TANGENT, CD_CALLOC, NULL, totface, ldata->layers[i].name);
+ }
+ CustomData_bmesh_update_active_layers(fdata, pdata, ldata);
+ }
+
+ BLI_assert(CustomData_from_bmeshpoly_test(fdata, pdata, ldata, true));
+
+ loopindex = MEM_mallocN(sizeof(*loopindex) * totface, __func__);
+
+ for (mf_idx = 0, mf = mface; mf_idx < totface; mf_idx++, mf++) {
+ const int mf_len = mf->v4 ? 4 : 3;
+ unsigned int *ml_idx = loopindex[mf_idx];
+ int i, not_done;
+
+ /* Find out loop indices. */
+ /* NOTE: This assumes tessface are valid and in sync with loop/poly... Else, most likely, segfault! */
+ for (i = mp[polyindex[mf_idx]].loopstart, not_done = mf_len; not_done; i++) {
+ const int tf_v = BKE_MESH_TESSFACE_VINDEX_ORDER(mf, ml[i].v);
+ if (tf_v != -1) {
+ ml_idx[tf_v] = i;
+ not_done--;
+ }
+ }
+ }
+
+ /* NOTE: quad detection issue - forth vertidx vs forth loopidx:
+ * Here, our tfaces' forth vertex index is never 0 for a quad. However, we know our forth loop index may be
+ * 0 for quads (because our quads may have been rotated compared to their org poly, see tessellation code).
+ * So we pass the MFace's, and BKE_mesh_loops_to_tessdata will use MFace->v4 index as quad test.
+ */
+ BKE_mesh_tangent_loops_to_tessdata(fdata, ldata, mface, polyindex, loopindex, totface);
+
+ MEM_freeN(loopindex);
+
+ if (G.debug & G_DEBUG)
+ printf("%s: Updated tessellated tangents of dm %p\n", __func__, dm);
+}
+
+
void DM_update_materials(DerivedMesh *dm, Object *ob)
{
int i, totmat = ob->totcol + 1; /* materials start from 1, default material is 0 */
@@ -511,36 +661,49 @@ void DM_update_materials(DerivedMesh *dm, Object *ob)
}
}
-MTFace *DM_paint_uvlayer_active_get(DerivedMesh *dm, int mat_nr)
+MLoopUV *DM_paint_uvlayer_active_get(DerivedMesh *dm, int mat_nr)
{
- MTFace *tf_base;
+ MLoopUV *uv_base;
BLI_assert(mat_nr < dm->totmat);
if (dm->mat[mat_nr] && dm->mat[mat_nr]->texpaintslot &&
dm->mat[mat_nr]->texpaintslot[dm->mat[mat_nr]->paint_active_slot].uvname)
{
- tf_base = CustomData_get_layer_named(&dm->faceData, CD_MTFACE,
+ uv_base = CustomData_get_layer_named(&dm->loopData, CD_MLOOPUV,
dm->mat[mat_nr]->texpaintslot[dm->mat[mat_nr]->paint_active_slot].uvname);
/* This can fail if we have changed the name in the UV layer list and have assigned the old name in the material
* texture slot.*/
- if (!tf_base)
- tf_base = CustomData_get_layer(&dm->faceData, CD_MTFACE);
+ if (!uv_base)
+ uv_base = CustomData_get_layer(&dm->loopData, CD_MLOOPUV);
}
else {
- tf_base = CustomData_get_layer(&dm->faceData, CD_MTFACE);
+ uv_base = CustomData_get_layer(&dm->loopData, CD_MLOOPUV);
}
- return tf_base;
+ return uv_base;
}
-void DM_to_mesh(DerivedMesh *dm, Mesh *me, Object *ob, CustomDataMask mask)
+void DM_to_mesh(DerivedMesh *dm, Mesh *me, Object *ob, CustomDataMask mask, bool take_ownership)
{
/* dm might depend on me, so we need to do everything with a local copy */
Mesh tmp = *me;
int totvert, totedge /*, totface */ /* UNUSED */, totloop, totpoly;
int did_shapekeys = 0;
-
+ int alloctype = CD_DUPLICATE;
+
+ if (take_ownership && dm->type == DM_TYPE_CDDM && dm->needsFree) {
+ bool has_any_referenced_layers =
+ CustomData_has_referenced(&dm->vertData) ||
+ CustomData_has_referenced(&dm->edgeData) ||
+ CustomData_has_referenced(&dm->loopData) ||
+ CustomData_has_referenced(&dm->faceData) ||
+ CustomData_has_referenced(&dm->polyData);
+ if (!has_any_referenced_layers) {
+ alloctype = CD_ASSIGN;
+ }
+ }
+
CustomData_reset(&tmp.vdata);
CustomData_reset(&tmp.edata);
CustomData_reset(&tmp.fdata);
@@ -555,10 +718,10 @@ void DM_to_mesh(DerivedMesh *dm, Mesh *me, Object *ob, CustomDataMask mask)
totpoly = tmp.totpoly = dm->getNumPolys(dm);
tmp.totface = 0;
- CustomData_copy(&dm->vertData, &tmp.vdata, mask, CD_DUPLICATE, totvert);
- CustomData_copy(&dm->edgeData, &tmp.edata, mask, CD_DUPLICATE, totedge);
- CustomData_copy(&dm->loopData, &tmp.ldata, mask, CD_DUPLICATE, totloop);
- CustomData_copy(&dm->polyData, &tmp.pdata, mask, CD_DUPLICATE, totpoly);
+ CustomData_copy(&dm->vertData, &tmp.vdata, mask, alloctype, totvert);
+ CustomData_copy(&dm->edgeData, &tmp.edata, mask, alloctype, totedge);
+ CustomData_copy(&dm->loopData, &tmp.ldata, mask, alloctype, totloop);
+ CustomData_copy(&dm->polyData, &tmp.pdata, mask, alloctype, totpoly);
tmp.cd_flag = dm->cd_flag;
if (CustomData_has_layer(&dm->vertData, CD_SHAPEKEY)) {
@@ -593,13 +756,19 @@ void DM_to_mesh(DerivedMesh *dm, Mesh *me, Object *ob, CustomDataMask mask)
/* not all DerivedMeshes store their verts/edges/faces in CustomData, so
* we set them here in case they are missing */
- if (!CustomData_has_layer(&tmp.vdata, CD_MVERT))
- CustomData_add_layer(&tmp.vdata, CD_MVERT, CD_ASSIGN, dm->dupVertArray(dm), totvert);
- if (!CustomData_has_layer(&tmp.edata, CD_MEDGE))
- CustomData_add_layer(&tmp.edata, CD_MEDGE, CD_ASSIGN, dm->dupEdgeArray(dm), totedge);
+ if (!CustomData_has_layer(&tmp.vdata, CD_MVERT)) {
+ CustomData_add_layer(&tmp.vdata, CD_MVERT, CD_ASSIGN,
+ (alloctype == CD_ASSIGN) ? dm->getVertArray(dm) : dm->dupVertArray(dm),
+ totvert);
+ }
+ if (!CustomData_has_layer(&tmp.edata, CD_MEDGE)) {
+ CustomData_add_layer(&tmp.edata, CD_MEDGE, CD_ASSIGN,
+ (alloctype == CD_ASSIGN) ? dm->getEdgeArray(dm) : dm->dupEdgeArray(dm),
+ totedge);
+ }
if (!CustomData_has_layer(&tmp.pdata, CD_MPOLY)) {
- tmp.mloop = dm->dupLoopArray(dm);
- tmp.mpoly = dm->dupPolyArray(dm);
+ tmp.mloop = (alloctype == CD_ASSIGN) ? dm->getLoopArray(dm) : dm->dupLoopArray(dm);
+ tmp.mpoly = (alloctype == CD_ASSIGN) ? dm->getPolyArray(dm) : dm->dupPolyArray(dm);
CustomData_add_layer(&tmp.ldata, CD_MLOOP, CD_ASSIGN, tmp.mloop, tmp.totloop);
CustomData_add_layer(&tmp.pdata, CD_MPOLY, CD_ASSIGN, tmp.mpoly, tmp.totpoly);
@@ -610,7 +779,7 @@ void DM_to_mesh(DerivedMesh *dm, Mesh *me, Object *ob, CustomDataMask mask)
if (CustomData_has_layer(&me->ldata, CD_MDISPS)) {
if (totloop == me->totloop) {
MDisps *mdisps = CustomData_get_layer(&me->ldata, CD_MDISPS);
- CustomData_add_layer(&tmp.ldata, CD_MDISPS, CD_DUPLICATE, mdisps, totloop);
+ CustomData_add_layer(&tmp.ldata, CD_MDISPS, alloctype, mdisps, totloop);
}
}
@@ -644,6 +813,16 @@ void DM_to_mesh(DerivedMesh *dm, Mesh *me, Object *ob, CustomDataMask mask)
/* skip the listbase */
MEMCPY_STRUCT_OFS(me, &tmp, id.prev);
+
+ if (take_ownership) {
+ if (alloctype == CD_ASSIGN) {
+ CustomData_free_typemask(&dm->vertData, dm->numVertData, ~mask);
+ CustomData_free_typemask(&dm->edgeData, dm->numEdgeData, ~mask);
+ CustomData_free_typemask(&dm->loopData, dm->numLoopData, ~mask);
+ CustomData_free_typemask(&dm->polyData, dm->numPolyData, ~mask);
+ }
+ dm->release(dm);
+ }
}
void DM_to_meshkey(DerivedMesh *dm, Mesh *me, KeyBlock *kb)
@@ -652,7 +831,9 @@ void DM_to_meshkey(DerivedMesh *dm, Mesh *me, KeyBlock *kb)
float *fp;
MVert *mvert;
- if (totvert == 0 || me->totvert == 0 || me->totvert != totvert) return;
+ if (totvert == 0 || me->totvert == 0 || me->totvert != totvert) {
+ return;
+ }
if (kb->data) MEM_freeN(kb->data);
kb->data = MEM_mallocN(me->key->elemsize * me->totvert, "kb->data");
@@ -666,6 +847,11 @@ void DM_to_meshkey(DerivedMesh *dm, Mesh *me, KeyBlock *kb)
}
}
+/**
+ * set the CD_FLAG_NOCOPY flag in custom data layers where the mask is
+ * zero for the layer type, so only layer types specified by the mask
+ * will be copied
+ */
void DM_set_only_copy(DerivedMesh *dm, CustomDataMask mask)
{
CustomData_set_only_copy(&dm->vertData, mask);
@@ -839,27 +1025,51 @@ void DM_free_poly_data(struct DerivedMesh *dm, int index, int count)
CustomData_free_elem(&dm->polyData, index, count);
}
-void DM_interp_vert_data(DerivedMesh *source, DerivedMesh *dest,
- int *src_indices, float *weights,
- int count, int dest_index)
+/**
+ * interpolates vertex data from the vertices indexed by src_indices in the
+ * source mesh using the given weights and stores the result in the vertex
+ * indexed by dest_index in the dest mesh
+ */
+void DM_interp_vert_data(
+ DerivedMesh *source, DerivedMesh *dest,
+ int *src_indices, float *weights,
+ int count, int dest_index)
{
CustomData_interp(&source->vertData, &dest->vertData, src_indices,
weights, NULL, count, dest_index);
}
-void DM_interp_edge_data(DerivedMesh *source, DerivedMesh *dest,
- int *src_indices,
- float *weights, EdgeVertWeight *vert_weights,
- int count, int dest_index)
+/**
+ * interpolates edge data from the edges indexed by src_indices in the
+ * source mesh using the given weights and stores the result in the edge indexed
+ * by dest_index in the dest mesh.
+ * if weights is NULL, all weights default to 1.
+ * if vert_weights is non-NULL, any per-vertex edge data is interpolated using
+ * vert_weights[i] multiplied by weights[i].
+ */
+void DM_interp_edge_data(
+ DerivedMesh *source, DerivedMesh *dest,
+ int *src_indices,
+ float *weights, EdgeVertWeight *vert_weights,
+ int count, int dest_index)
{
CustomData_interp(&source->edgeData, &dest->edgeData, src_indices,
weights, (float *)vert_weights, count, dest_index);
}
-void DM_interp_tessface_data(DerivedMesh *source, DerivedMesh *dest,
- int *src_indices,
- float *weights, FaceVertWeight *vert_weights,
- int count, int dest_index)
+/**
+ * interpolates face data from the faces indexed by src_indices in the
+ * source mesh using the given weights and stores the result in the face indexed
+ * by dest_index in the dest mesh.
+ * if weights is NULL, all weights default to 1.
+ * if vert_weights is non-NULL, any per-vertex face data is interpolated using
+ * vert_weights[i] multiplied by weights[i].
+ */
+void DM_interp_tessface_data(
+ DerivedMesh *source, DerivedMesh *dest,
+ int *src_indices,
+ float *weights, FaceVertWeight *vert_weights,
+ int count, int dest_index)
{
CustomData_interp(&source->faceData, &dest->faceData, src_indices,
weights, (float *)vert_weights, count, dest_index);
@@ -870,23 +1080,24 @@ void DM_swap_tessface_data(DerivedMesh *dm, int index, const int *corner_indices
CustomData_swap(&dm->faceData, index, corner_indices);
}
-void DM_interp_loop_data(DerivedMesh *source, DerivedMesh *dest,
- int *src_indices,
- float *weights, int count, int dest_index)
+void DM_interp_loop_data(
+ DerivedMesh *source, DerivedMesh *dest,
+ int *src_indices,
+ float *weights, int count, int dest_index)
{
CustomData_interp(&source->loopData, &dest->loopData, src_indices,
weights, NULL, count, dest_index);
}
-void DM_interp_poly_data(DerivedMesh *source, DerivedMesh *dest,
- int *src_indices,
- float *weights, int count, int dest_index)
+void DM_interp_poly_data(
+ DerivedMesh *source, DerivedMesh *dest,
+ int *src_indices,
+ float *weights, int count, int dest_index)
{
CustomData_interp(&source->polyData, &dest->polyData, src_indices,
weights, NULL, count, dest_index);
}
-///
DerivedMesh *mesh_create_derived(Mesh *me, float (*vertCos)[3])
{
DerivedMesh *dm = CDDM_from_mesh(me);
@@ -901,21 +1112,27 @@ DerivedMesh *mesh_create_derived(Mesh *me, float (*vertCos)[3])
return dm;
}
-DerivedMesh *mesh_create_derived_for_modifier(Scene *scene, Object *ob,
- ModifierData *md, int build_shapekey_layers)
+DerivedMesh *mesh_create_derived_for_modifier(
+ Scene *scene, Object *ob,
+ ModifierData *md, int build_shapekey_layers)
{
Mesh *me = ob->data;
- ModifierTypeInfo *mti = modifierType_getInfo(md->type);
+ const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
DerivedMesh *dm;
KeyBlock *kb;
md->scene = scene;
- if (!(md->mode & eModifierMode_Realtime)) return NULL;
- if (mti->isDisabled && mti->isDisabled(md, 0)) return NULL;
+ if (!(md->mode & eModifierMode_Realtime)) {
+ return NULL;
+ }
+
+ if (mti->isDisabled && mti->isDisabled(md, 0)) {
+ return NULL;
+ }
if (build_shapekey_layers && me->key && (kb = BLI_findlink(&me->key->block, ob->shapenr - 1))) {
- BKE_key_convert_to_mesh(kb, me);
+ BKE_keyblock_convert_to_mesh(kb, me);
}
if (mti->type == eModifierTypeType_OnlyDeform) {
@@ -985,8 +1202,9 @@ static float (*get_orco_coords_dm(Object *ob, BMEditMesh *em, int layer, int *fr
ClothModifierData *clmd = (ClothModifierData *)modifiers_findByType(ob, eModifierType_Cloth);
KeyBlock *kb = BKE_keyblock_from_key(BKE_key_from_object(ob), clmd->sim_parms->shapekey_rest);
- if (kb->data)
+ if (kb && kb->data) {
return kb->data;
+ }
}
return NULL;
@@ -1001,8 +1219,12 @@ static DerivedMesh *create_orco_dm(Object *ob, Mesh *me, BMEditMesh *em, int lay
float (*orco)[3];
int free;
- if (em) dm = CDDM_from_editbmesh(em, false, false);
- else dm = CDDM_from_mesh(me);
+ if (em) {
+ dm = CDDM_from_editbmesh(em, false, false);
+ }
+ else {
+ dm = CDDM_from_mesh(me);
+ }
orco = get_orco_coords_dm(ob, em, layer, &free);
@@ -1014,8 +1236,9 @@ static DerivedMesh *create_orco_dm(Object *ob, Mesh *me, BMEditMesh *em, int lay
return dm;
}
-static void add_orco_dm(Object *ob, BMEditMesh *em, DerivedMesh *dm,
- DerivedMesh *orcodm, int layer)
+static void add_orco_dm(
+ Object *ob, BMEditMesh *em, DerivedMesh *dm,
+ DerivedMesh *orcodm, int layer)
{
float (*orco)[3], (*layerorco)[3];
int totvert, free;
@@ -1105,7 +1328,7 @@ typedef struct DMWeightColorInfo {
} DMWeightColorInfo;
-static int dm_drawflag_calc(ToolSettings *ts)
+static int dm_drawflag_calc(const ToolSettings *ts)
{
return ((ts->multipaint ? CALC_WP_MULTIPAINT :
/* CALC_WP_GROUP_USER_ACTIVE or CALC_WP_GROUP_USER_ALL*/
@@ -1206,13 +1429,16 @@ void vDM_ColorBand_store(const ColorBand *coba, const char alert_color[4])
G_dm_wcinfo.alert_color = alert_color;
}
-/* return an array of vertex weight colors, caller must free.
+/**
+ * return an array of vertex weight colors, caller must free.
*
- * note that we could save some memory and allocate RGB only but then we'd need to
+ * \note that we could save some memory and allocate RGB only but then we'd need to
* re-arrange the colors when copying to the face since MCol has odd ordering,
- * so leave this as is - campbell */
-static void calc_weightpaint_vert_array(Object *ob, DerivedMesh *dm, int const draw_flag, DMWeightColorInfo *dm_wcinfo,
- unsigned char (*r_wtcol_v)[4])
+ * so leave this as is - campbell
+ */
+static void calc_weightpaint_vert_array(
+ Object *ob, DerivedMesh *dm, int const draw_flag, DMWeightColorInfo *dm_wcinfo,
+ unsigned char (*r_wtcol_v)[4])
{
MDeformVert *dv = DM_get_vert_data_layer(dm, CD_MDEFORMVERT);
int numVerts = dm->getNumVerts(dm);
@@ -1222,14 +1448,14 @@ static void calc_weightpaint_vert_array(Object *ob, DerivedMesh *dm, int const d
unsigned int i;
/* variables for multipaint */
- const int defbase_tot = BLI_countlist(&ob->defbase);
+ const int defbase_tot = BLI_listbase_count(&ob->defbase);
const int defbase_act = ob->actdef - 1;
int defbase_sel_tot = 0;
bool *defbase_sel = NULL;
if (draw_flag & CALC_WP_MULTIPAINT) {
- defbase_sel = BKE_objdef_selected_get(ob, defbase_tot, &defbase_sel_tot);
+ defbase_sel = BKE_object_defgroup_selected_get(ob, defbase_tot, &defbase_sel_tot);
}
for (i = numVerts; i != 0; i--, wc++, dv++) {
@@ -1249,17 +1475,19 @@ static void calc_weightpaint_vert_array(Object *ob, DerivedMesh *dm, int const d
else {
weightpaint_color(col, dm_wcinfo, 0.0f);
}
- fill_vn_i((int *)r_wtcol_v, numVerts, *((int *)col));
+ copy_vn_i((int *)r_wtcol_v, numVerts, *((int *)col));
}
}
-/* return an array of vertex weight colors from given weights, caller must free.
+/** return an array of vertex weight colors from given weights, caller must free.
*
- * note that we could save some memory and allocate RGB only but then we'd need to
+ * \note that we could save some memory and allocate RGB only but then we'd need to
* re-arrange the colors when copying to the face since MCol has odd ordering,
- * so leave this as is - campbell */
-static void calc_colors_from_weights_array(const int num, const float *weights,
- unsigned char (*r_wtcol_v)[4])
+ * so leave this as is - campbell
+ */
+static void calc_colors_from_weights_array(
+ const int num, const float *weights,
+ unsigned char (*r_wtcol_v)[4])
{
unsigned char (*wc)[4] = r_wtcol_v;
int i;
@@ -1269,8 +1497,9 @@ static void calc_colors_from_weights_array(const int num, const float *weights,
}
}
-void DM_update_weight_mcol(Object *ob, DerivedMesh *dm, int const draw_flag,
- float *weights, int num, const int *indices)
+void DM_update_weight_mcol(
+ Object *ob, DerivedMesh *dm, int const draw_flag,
+ float *weights, int num, const int *indices)
{
BMEditMesh *em = (dm->type == DM_TYPE_EDITBMESH) ? BKE_editmesh_from_object(ob) : NULL;
unsigned char (*wtcol_v)[4];
@@ -1342,7 +1571,7 @@ void DM_update_weight_mcol(Object *ob, DerivedMesh *dm, int const draw_flag,
}
}
-static void DM_update_statvis_color(Scene *scene, Object *ob, DerivedMesh *dm)
+static void DM_update_statvis_color(const Scene *scene, Object *ob, DerivedMesh *dm)
{
BMEditMesh *em = BKE_editmesh_from_object(ob);
@@ -1452,26 +1681,34 @@ static void add_shapekey_layers(DerivedMesh *dm, Mesh *me, Object *UNUSED(ob))
*/
static void dm_ensure_display_normals(DerivedMesh *dm)
{
- /* this is for final output only, up until now this layer should be missing */
- BLI_assert(CustomData_has_layer(&dm->polyData, CD_NORMAL) == false);
+ /* Note: dm *may* have a poly CD_NORMAL layer (generated by a modifier needing poly normals e.g.).
+ * We do not use it here, though. And it should be tagged as temp!
+ */
+ /* BLI_assert((CustomData_has_layer(&dm->polyData, CD_NORMAL) == false)); */
if ((dm->type == DM_TYPE_CDDM) &&
- ((dm->dirty & DM_DIRTY_NORMALS) || CustomData_has_layer(&dm->faceData, CD_NORMAL) == false))
+ ((dm->dirty & DM_DIRTY_NORMALS) || CustomData_has_layer(&dm->polyData, CD_NORMAL) == false))
{
/* if normals are dirty we want to calculate vertex normals too */
CDDM_calc_normals_mapping_ex(dm, (dm->dirty & DM_DIRTY_NORMALS) ? false : true);
}
}
-/* new value for useDeform -1 (hack for the gameengine):
+
+/**
+ * new value for useDeform -1 (hack for the gameengine):
+ *
* - apply only the modifier stack of the object, skipping the virtual modifiers,
* - don't apply the key
* - apply deform modifiers and input vertexco
*/
-static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos)[3],
- DerivedMesh **deform_r, DerivedMesh **final_r,
- int useRenderParams, int useDeform,
- int needMapping, CustomDataMask dataMask,
- int index, int useCache, int build_shapekey_layers)
+static void mesh_calc_modifiers(
+ Scene *scene, Object *ob, float (*inputVertexCos)[3],
+ const bool useRenderParams, int useDeform,
+ const bool need_mapping, CustomDataMask dataMask,
+ const int index, const bool useCache, const bool build_shapekey_layers,
+ const bool allow_gpu,
+ /* return args */
+ DerivedMesh **r_deform, DerivedMesh **r_final)
{
Mesh *me = ob->data;
ModifierData *firstmd, *md, *previewmd = NULL;
@@ -1481,14 +1718,14 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos
float (*deformedVerts)[3] = NULL;
DerivedMesh *dm = NULL, *orcodm, *clothorcodm, *finaldm;
int numVerts = me->totvert;
- int required_mode;
+ const int required_mode = useRenderParams ? eModifierMode_Render : eModifierMode_Realtime;
bool isPrevDeform = false;
const bool skipVirtualArmature = (useDeform < 0);
MultiresModifierData *mmd = get_multires_modifier(scene, ob, 0);
const bool has_multires = (mmd && mmd->sculptlvl != 0);
bool multires_applied = false;
- const bool sculpt_mode = ob->mode & OB_MODE_SCULPT && ob->sculpt;
- const bool sculpt_dyntopo = (sculpt_mode && ob->sculpt->bm);
+ const bool sculpt_mode = ob->mode & OB_MODE_SCULPT && ob->sculpt && !useRenderParams;
+ const bool sculpt_dyntopo = (sculpt_mode && ob->sculpt->bm) && !useRenderParams;
const int draw_flag = dm_drawflag_calc(scene->toolsettings);
/* Generic preview only in object mode! */
@@ -1497,19 +1734,23 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos
const bool do_final_wmcol = (scene->toolsettings->weights_preview == WP_WPREVIEW_FINAL) && do_wmcol;
#endif
const bool do_final_wmcol = false;
- const bool do_init_wmcol = ((dataMask & CD_MASK_PREVIEW_MCOL) && (ob->mode & OB_MODE_WEIGHT_PAINT) && !do_final_wmcol);
+ const bool do_init_wmcol = ((dataMask & CD_MASK_PREVIEW_MLOOPCOL) && (ob->mode & OB_MODE_WEIGHT_PAINT) && !do_final_wmcol);
/* XXX Same as above... For now, only weights preview in WPaint mode. */
const bool do_mod_wmcol = do_init_wmcol;
- const bool do_loop_normals = (me->flag & ME_AUTOSMOOTH);
+ const bool do_loop_normals = (me->flag & ME_AUTOSMOOTH) != 0;
const float loop_normals_split_angle = me->smoothresh;
VirtualModifierData virtualModifierData;
ModifierApplyFlag app_flags = useRenderParams ? MOD_APPLY_RENDER : 0;
ModifierApplyFlag deform_app_flags = app_flags;
+
+
if (useCache)
app_flags |= MOD_APPLY_USECACHE;
+ if (allow_gpu)
+ app_flags |= MOD_APPLY_ALLOW_GPU;
if (useDeform)
deform_app_flags |= MOD_APPLY_USECACHE;
@@ -1527,9 +1768,6 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos
modifiers_clearErrors(ob);
- if (useRenderParams) required_mode = eModifierMode_Render;
- else required_mode = eModifierMode_Realtime;
-
if (do_mod_wmcol || do_mod_mcol) {
/* Find the last active modifier generating a preview, or NULL if none. */
/* XXX Currently, DPaint modifier just ignores this.
@@ -1548,8 +1786,10 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos
datamasks = modifiers_calcDataMasks(scene, ob, md, dataMask, required_mode, previewmd, previewmask);
curr = datamasks;
- if (deform_r) *deform_r = NULL;
- *final_r = NULL;
+ if (r_deform) {
+ *r_deform = NULL;
+ }
+ *r_final = NULL;
if (useDeform) {
if (inputVertexCos)
@@ -1557,12 +1797,17 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos
/* Apply all leading deforming modifiers */
for (; md; md = md->next, curr = curr->next) {
- ModifierTypeInfo *mti = modifierType_getInfo(md->type);
+ const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
md->scene = scene;
- if (!modifier_isEnabled(scene, md, required_mode)) continue;
- if (useDeform < 0 && mti->dependsOnTime && mti->dependsOnTime(md)) continue;
+ if (!modifier_isEnabled(scene, md, required_mode)) {
+ continue;
+ }
+
+ if (useDeform < 0 && mti->dependsOnTime && mti->dependsOnTime(md)) {
+ continue;
+ }
if (mti->type == eModifierTypeType_OnlyDeform && !sculpt_dyntopo) {
if (!deformedVerts)
@@ -1575,7 +1820,7 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos
}
/* grab modifiers until index i */
- if ((index >= 0) && (BLI_findindex(&ob->modifiers, md) >= index))
+ if ((index != -1) && (BLI_findindex(&ob->modifiers, md) >= index))
break;
}
@@ -1583,14 +1828,14 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos
* places that wish to use the original mesh but with deformed
* coordinates (vpaint, etc.)
*/
- if (deform_r) {
- *deform_r = CDDM_from_mesh(me);
+ if (r_deform) {
+ *r_deform = CDDM_from_mesh(me);
if (build_shapekey_layers)
add_shapekey_layers(dm, me, ob);
if (deformedVerts) {
- CDDM_apply_vert_coords(*deform_r, deformedVerts);
+ CDDM_apply_vert_coords(*r_deform, deformedVerts);
}
}
}
@@ -1611,16 +1856,23 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos
clothorcodm = NULL;
for (; md; md = md->next, curr = curr->next) {
- ModifierTypeInfo *mti = modifierType_getInfo(md->type);
+ const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
md->scene = scene;
- if (!modifier_isEnabled(scene, md, required_mode)) continue;
- if (mti->type == eModifierTypeType_OnlyDeform && !useDeform) continue;
+ if (!modifier_isEnabled(scene, md, required_mode)) {
+ continue;
+ }
+
+ if (mti->type == eModifierTypeType_OnlyDeform && !useDeform) {
+ continue;
+ }
+
if ((mti->flags & eModifierTypeFlag_RequiresOriginalData) && dm) {
modifier_setError(md, "Modifier requires original data, bad stack position");
continue;
}
+
if (sculpt_mode &&
(!has_multires || multires_applied || sculpt_dyntopo))
{
@@ -1628,8 +1880,9 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos
if (md->type == eModifierType_Multires && ((MultiresModifierData *)md)->sculptlvl == 0) {
/* If multires is on level 0 skip it silently without warning message. */
- if (!sculpt_dyntopo)
+ if (!sculpt_dyntopo) {
continue;
+ }
}
if (sculpt_dyntopo && !useRenderParams)
@@ -1651,8 +1904,14 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos
modifier_setError(md, "Hide, Mask and optimized display disabled");
}
}
- if (needMapping && !modifier_supportsMapping(md)) continue;
- if (useDeform < 0 && mti->dependsOnTime && mti->dependsOnTime(md)) continue;
+
+ if (need_mapping && !modifier_supportsMapping(md)) {
+ continue;
+ }
+
+ if (useDeform < 0 && mti->dependsOnTime && mti->dependsOnTime(md)) {
+ continue;
+ }
/* add an orco layer if needed by this modifier */
if (mti->requiredDataMask)
@@ -1737,7 +1996,7 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos
* requests it, this way Mirror, Solidify etc will keep ORIGINDEX
* data by using generic DM_copy_vert_data() functions.
*/
- if (needMapping || (nextmask & CD_MASK_ORIGINDEX)) {
+ if (need_mapping || (nextmask & CD_MASK_ORIGINDEX)) {
/* calc */
DM_add_vert_layer(dm, CD_ORIGINDEX, CD_CALLOC, NULL);
DM_add_edge_layer(dm, CD_ORIGINDEX, CD_CALLOC, NULL);
@@ -1761,7 +2020,7 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos
/* needMapping check here fixes bug [#28112], otherwise its
* possible that it wont be copied */
mask |= append_mask;
- DM_set_only_copy(dm, mask | (needMapping ? CD_MASK_ORIGINDEX : 0));
+ DM_set_only_copy(dm, mask | (need_mapping ? CD_MASK_ORIGINDEX : 0));
/* add cloth rest shape key if need */
if (mask & CD_MASK_CLOTH_ORCO)
@@ -1825,7 +2084,9 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos
if (ndm) {
/* if the modifier returned a new dm, release the old one */
- if (clothorcodm && clothorcodm != ndm) clothorcodm->release(clothorcodm);
+ if (clothorcodm && clothorcodm != ndm) {
+ clothorcodm->release(clothorcodm);
+ }
clothorcodm = ndm;
}
}
@@ -1844,7 +2105,7 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos
isPrevDeform = (mti->type == eModifierTypeType_OnlyDeform);
/* grab modifiers until index i */
- if ((index >= 0) && (BLI_findindex(&ob->modifiers, md) >= index))
+ if ((index != -1) && (BLI_findindex(&ob->modifiers, md) >= index))
break;
if (sculpt_mode && md->type == eModifierType_Multires) {
@@ -1901,17 +2162,21 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos
if (dataMask & CD_MASK_ORCO) {
add_orco_dm(ob, NULL, finaldm, orcodm, CD_ORCO);
- if (deform_r && *deform_r)
- add_orco_dm(ob, NULL, *deform_r, NULL, CD_ORCO);
+ if (r_deform && *r_deform)
+ add_orco_dm(ob, NULL, *r_deform, NULL, CD_ORCO);
}
if (do_loop_normals) {
/* Compute loop normals (note: will compute poly and vert normals as well, if needed!) */
- DM_calc_loop_normals(finaldm, loop_normals_split_angle);
+ DM_calc_loop_normals(finaldm, do_loop_normals, loop_normals_split_angle);
}
- {
- DM_ensure_tessface(finaldm);
+ if (sculpt_dyntopo == false) {
+ /* watch this! after 2.75a we move to from tessface to looptri (by default) */
+ if (dataMask & CD_MASK_MFACE) {
+ DM_ensure_tessface(finaldm);
+ }
+ DM_ensure_looptri(finaldm);
/* without this, drawing ngon tri's faces will show ugly tessellated face
* normals and will also have to calculate normals on the fly, try avoid
@@ -1936,10 +2201,12 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos
finaldm->release(finaldm);
finaldm = tdm;
}
+
+ DM_ensure_tessface(finaldm);
}
#endif /* WITH_GAMEENGINE */
- *final_r = finaldm;
+ *r_final = finaldm;
if (orcodm)
orcodm->release(orcodm);
@@ -1972,21 +2239,26 @@ float (*editbmesh_get_vertex_cos(BMEditMesh *em, int *r_numVerts))[3]
bool editbmesh_modifier_is_enabled(Scene *scene, ModifierData *md, DerivedMesh *dm)
{
- ModifierTypeInfo *mti = modifierType_getInfo(md->type);
- int required_mode = eModifierMode_Realtime | eModifierMode_Editmode;
+ const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
+ const int required_mode = eModifierMode_Realtime | eModifierMode_Editmode;
+
+ if (!modifier_isEnabled(scene, md, required_mode)) {
+ return false;
+ }
- if (!modifier_isEnabled(scene, md, required_mode)) return 0;
if ((mti->flags & eModifierTypeFlag_RequiresOriginalData) && dm) {
modifier_setError(md, "Modifier requires original data, bad stack position");
- return 0;
+ return false;
}
- return 1;
+ return true;
}
-static void editbmesh_calc_modifiers(Scene *scene, Object *ob, BMEditMesh *em, DerivedMesh **cage_r,
- DerivedMesh **final_r,
- CustomDataMask dataMask)
+static void editbmesh_calc_modifiers(
+ Scene *scene, Object *ob, BMEditMesh *em,
+ CustomDataMask dataMask,
+ /* return args */
+ DerivedMesh **r_cage, DerivedMesh **r_final)
{
ModifierData *md, *previewmd = NULL;
float (*deformedVerts)[3] = NULL;
@@ -1994,7 +2266,7 @@ static void editbmesh_calc_modifiers(Scene *scene, Object *ob, BMEditMesh *em, D
DerivedMesh *dm = NULL, *orcodm = NULL;
int i, numVerts = 0, cageIndex = modifiers_getCageIndex(scene, ob, NULL, 1);
CDMaskLink *datamasks, *curr;
- int required_mode = eModifierMode_Realtime | eModifierMode_Editmode;
+ const int required_mode = eModifierMode_Realtime | eModifierMode_Editmode;
int draw_flag = dm_drawflag_calc(scene->toolsettings);
// const bool do_mod_mcol = true; // (ob->mode == OB_MODE_OBJECT);
@@ -2003,17 +2275,18 @@ static void editbmesh_calc_modifiers(Scene *scene, Object *ob, BMEditMesh *em, D
#endif
const bool do_final_wmcol = false;
const bool do_init_wmcol = ((((Mesh *)ob->data)->drawflag & ME_DRAWEIGHT) && !do_final_wmcol);
+
const bool do_init_statvis = ((((Mesh *)ob->data)->drawflag & ME_DRAW_STATVIS) && !do_init_wmcol);
const bool do_mod_wmcol = do_init_wmcol;
VirtualModifierData virtualModifierData;
- const bool do_loop_normals = (((Mesh *)(ob->data))->flag & ME_AUTOSMOOTH);
+ const bool do_loop_normals = (((Mesh *)(ob->data))->flag & ME_AUTOSMOOTH) != 0;
const float loop_normals_split_angle = ((Mesh *)(ob->data))->smoothresh;
modifiers_clearErrors(ob);
- if (cage_r && cageIndex == -1) {
- *cage_r = getEditDerivedBMesh(em, ob, NULL);
+ if (r_cage && cageIndex == -1) {
+ *r_cage = getEditDerivedBMesh(em, ob, NULL);
}
md = modifiers_getVirtualModifierList(ob, &virtualModifierData);
@@ -2031,12 +2304,13 @@ static void editbmesh_calc_modifiers(Scene *scene, Object *ob, BMEditMesh *em, D
curr = datamasks;
for (i = 0; md; i++, md = md->next, curr = curr->next) {
- ModifierTypeInfo *mti = modifierType_getInfo(md->type);
+ const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
md->scene = scene;
- if (!editbmesh_modifier_is_enabled(scene, md, dm))
+ if (!editbmesh_modifier_is_enabled(scene, md, dm)) {
continue;
+ }
/* add an orco layer if needed by this modifier */
if (dm && mti->requiredDataMask) {
@@ -2080,14 +2354,15 @@ static void editbmesh_calc_modifiers(Scene *scene, Object *ob, BMEditMesh *em, D
if (dm) {
if (deformedVerts) {
DerivedMesh *tdm = CDDM_copy(dm);
- if (!(cage_r && dm == *cage_r)) dm->release(dm);
+ if (!(r_cage && dm == *r_cage)) {
+ dm->release(dm);
+ }
dm = tdm;
CDDM_apply_vert_coords(dm, deformedVerts);
}
- else if (cage_r && dm == *cage_r) {
- /* dm may be changed by this modifier, so we need to copy it
- */
+ else if (r_cage && dm == *r_cage) {
+ /* dm may be changed by this modifier, so we need to copy it */
dm = CDDM_copy(dm);
}
@@ -2143,9 +2418,9 @@ static void editbmesh_calc_modifiers(Scene *scene, Object *ob, BMEditMesh *em, D
}
if (mti->applyModifierEM)
- ndm = modwrap_applyModifierEM(md, ob, em, dm, MOD_APPLY_USECACHE);
+ ndm = modwrap_applyModifierEM(md, ob, em, dm, MOD_APPLY_USECACHE | MOD_APPLY_ALLOW_GPU);
else
- ndm = modwrap_applyModifier(md, ob, dm, MOD_APPLY_USECACHE);
+ ndm = modwrap_applyModifier(md, ob, dm, MOD_APPLY_USECACHE | MOD_APPLY_ALLOW_GPU);
ASSERT_IS_VALID_DM(ndm);
if (ndm) {
@@ -2167,18 +2442,18 @@ static void editbmesh_calc_modifiers(Scene *scene, Object *ob, BMEditMesh *em, D
append_mask |= CD_MASK_PREVIEW_MLOOPCOL;
}
- if (cage_r && i == cageIndex) {
+ if (r_cage && i == cageIndex) {
if (dm && deformedVerts) {
- *cage_r = CDDM_copy(dm);
- CDDM_apply_vert_coords(*cage_r, deformedVerts);
+ *r_cage = CDDM_copy(dm);
+ CDDM_apply_vert_coords(*r_cage, deformedVerts);
}
else if (dm) {
- *cage_r = dm;
+ *r_cage = dm;
}
else {
- *cage_r =
- getEditDerivedBMesh(em, ob,
- deformedVerts ? MEM_dupallocN(deformedVerts) : NULL);
+ *r_cage = getEditDerivedBMesh(
+ em, ob,
+ deformedVerts ? MEM_dupallocN(deformedVerts) : NULL);
}
}
}
@@ -2190,57 +2465,60 @@ static void editbmesh_calc_modifiers(Scene *scene, Object *ob, BMEditMesh *em, D
* then we need to build one.
*/
if (dm && deformedVerts) {
- *final_r = CDDM_copy(dm);
+ *r_final = CDDM_copy(dm);
- if (!(cage_r && dm == *cage_r)) dm->release(dm);
+ if (!(r_cage && dm == *r_cage)) {
+ dm->release(dm);
+ }
- CDDM_apply_vert_coords(*final_r, deformedVerts);
+ CDDM_apply_vert_coords(*r_final, deformedVerts);
}
else if (dm) {
- *final_r = dm;
+ *r_final = dm;
}
- else if (!deformedVerts && cage_r && *cage_r) {
+ else if (!deformedVerts && r_cage && *r_cage) {
/* cage should already have up to date normals */
- *final_r = *cage_r;
+ *r_final = *r_cage;
/* In this case, we should never have weight-modifying modifiers in stack... */
if (do_init_wmcol)
- DM_update_weight_mcol(ob, *final_r, draw_flag, NULL, 0, NULL);
+ DM_update_weight_mcol(ob, *r_final, draw_flag, NULL, 0, NULL);
if (do_init_statvis)
- DM_update_statvis_color(scene, ob, *final_r);
+ DM_update_statvis_color(scene, ob, *r_final);
}
else {
/* this is just a copy of the editmesh, no need to calc normals */
- *final_r = getEditDerivedBMesh(em, ob, deformedVerts);
+ *r_final = getEditDerivedBMesh(em, ob, deformedVerts);
deformedVerts = NULL;
/* In this case, we should never have weight-modifying modifiers in stack... */
if (do_init_wmcol)
- DM_update_weight_mcol(ob, *final_r, draw_flag, NULL, 0, NULL);
+ DM_update_weight_mcol(ob, *r_final, draw_flag, NULL, 0, NULL);
if (do_init_statvis)
- DM_update_statvis_color(scene, ob, *final_r);
+ DM_update_statvis_color(scene, ob, *r_final);
}
if (do_loop_normals) {
/* Compute loop normals */
- DM_calc_loop_normals(*final_r, loop_normals_split_angle);
- if (cage_r && *cage_r && (*cage_r != *final_r)) {
- DM_calc_loop_normals(*cage_r, loop_normals_split_angle);
+ DM_calc_loop_normals(*r_final, do_loop_normals, loop_normals_split_angle);
+ if (r_cage && *r_cage && (*r_cage != *r_final)) {
+ DM_calc_loop_normals(*r_cage, do_loop_normals, loop_normals_split_angle);
}
}
- /* --- */
/* BMESH_ONLY, ensure tessface's used for drawing,
* but don't recalculate if the last modifier in the stack gives us tessfaces
* check if the derived meshes are DM_TYPE_EDITBMESH before calling, this isn't essential
* but quiets annoying error messages since tessfaces wont be created. */
- if ((*final_r)->type != DM_TYPE_EDITBMESH) {
- DM_ensure_tessface(*final_r);
- }
- if (cage_r && *cage_r) {
- if ((*cage_r)->type != DM_TYPE_EDITBMESH) {
- if (*cage_r != *final_r) {
- DM_ensure_tessface(*cage_r);
+ if (dataMask & CD_MASK_MFACE) {
+ if ((*r_final)->type != DM_TYPE_EDITBMESH) {
+ DM_ensure_tessface(*r_final);
+ }
+ if (r_cage && *r_cage) {
+ if ((*r_cage)->type != DM_TYPE_EDITBMESH) {
+ if (*r_cage != *r_final) {
+ DM_ensure_tessface(*r_cage);
+ }
}
}
}
@@ -2248,12 +2526,12 @@ static void editbmesh_calc_modifiers(Scene *scene, Object *ob, BMEditMesh *em, D
/* same as mesh_calc_modifiers (if using loop normals, poly nors have already been computed). */
if (!do_loop_normals) {
- dm_ensure_display_normals(*final_r);
+ dm_ensure_display_normals(*r_final);
}
/* add an orco layer if needed */
if (dataMask & CD_MASK_ORCO)
- add_orco_dm(ob, em, *final_r, orcodm, CD_ORCO);
+ add_orco_dm(ob, em, *r_final, orcodm, CD_ORCO);
if (orcodm)
orcodm->release(orcodm);
@@ -2262,28 +2540,51 @@ static void editbmesh_calc_modifiers(Scene *scene, Object *ob, BMEditMesh *em, D
MEM_freeN(deformedVerts);
}
-static void mesh_build_data(Scene *scene, Object *ob, CustomDataMask dataMask,
- int build_shapekey_layers)
+#ifdef WITH_OPENSUBDIV
+/* The idea is to skip CPU-side ORCO calculation when
+ * we'll be using GPU backend of OpenSubdiv. This is so
+ * playback performance is kept as high as possible.
+ */
+static bool calc_modifiers_skip_orco(const Object *ob)
{
- Object *obact = scene->basact ? scene->basact->object : NULL;
- bool editing = BKE_paint_select_face_test(ob);
- /* weight paint and face select need original indices because of selection buffer drawing */
- int needMapping = (ob == obact) && (editing || (ob->mode & (OB_MODE_WEIGHT_PAINT | OB_MODE_VERTEX_PAINT | OB_MODE_TEXTURE_PAINT)));
+ const ModifierData *last_md = ob->modifiers.last;
+ if (last_md != NULL &&
+ last_md->type == eModifierType_Subsurf)
+ {
+ SubsurfModifierData *smd = (SubsurfModifierData *)last_md;
+ /* TODO(sergey): Deduplicate this with checks from subsurf_ccg.c. */
+ return smd->use_opensubdiv && U.opensubdiv_compute_type != USER_OPENSUBDIV_COMPUTE_NONE;
+ }
+ return false;
+}
+#endif
+static void mesh_build_data(
+ Scene *scene, Object *ob, CustomDataMask dataMask,
+ const bool build_shapekey_layers, const bool need_mapping)
+{
BLI_assert(ob->type == OB_MESH);
BKE_object_free_derived_caches(ob);
BKE_object_sculpt_modifiers_changed(ob);
- mesh_calc_modifiers(scene, ob, NULL, &ob->derivedDeform,
- &ob->derivedFinal, 0, 1,
- needMapping, dataMask, -1, 1, build_shapekey_layers);
+#ifdef WITH_OPENSUBDIV
+ if (calc_modifiers_skip_orco(ob)) {
+ dataMask &= ~(CD_MASK_ORCO | CD_MASK_PREVIEW_MCOL);
+ }
+#endif
+
+ mesh_calc_modifiers(
+ scene, ob, NULL, false, 1, need_mapping, dataMask, -1, true, build_shapekey_layers,
+ true,
+ &ob->derivedDeform, &ob->derivedFinal);
DM_set_object_boundbox(ob, ob->derivedFinal);
ob->derivedFinal->needsFree = 0;
ob->derivedDeform->needsFree = 0;
ob->lastDataMask = dataMask;
+ ob->lastNeedMapping = need_mapping;
if ((ob->mode & OB_MODE_SCULPT) && ob->sculpt) {
/* create PBVH immediately (would be created on the fly too,
@@ -2302,7 +2603,16 @@ static void editbmesh_build_data(Scene *scene, Object *obedit, BMEditMesh *em, C
BKE_editmesh_free_derivedmesh(em);
- editbmesh_calc_modifiers(scene, obedit, em, &em->derivedCage, &em->derivedFinal, dataMask);
+#ifdef WITH_OPENSUBDIV
+ if (calc_modifiers_skip_orco(obedit)) {
+ dataMask &= ~(CD_MASK_ORCO | CD_MASK_PREVIEW_MCOL);
+ }
+#endif
+
+ editbmesh_calc_modifiers(
+ scene, obedit, em, dataMask,
+ &em->derivedCage, &em->derivedFinal);
+
DM_set_object_boundbox(obedit, em->derivedFinal);
em->lastDataMask = dataMask;
@@ -2312,24 +2622,35 @@ static void editbmesh_build_data(Scene *scene, Object *obedit, BMEditMesh *em, C
BLI_assert(!(em->derivedFinal->dirty & DM_DIRTY_NORMALS));
}
-static CustomDataMask object_get_datamask(Scene *scene, Object *ob)
+static CustomDataMask object_get_datamask(const Scene *scene, Object *ob, bool *r_need_mapping)
{
Object *actob = scene->basact ? scene->basact->object : NULL;
CustomDataMask mask = ob->customdata_mask;
+ bool editing = BKE_paint_select_face_test(ob);
+
+ if (r_need_mapping) {
+ *r_need_mapping = false;
+ }
if (ob == actob) {
+
+ /* weight paint and face select need original indices because of selection buffer drawing */
+ if (r_need_mapping) {
+ *r_need_mapping = (editing || (ob->mode & (OB_MODE_WEIGHT_PAINT | OB_MODE_VERTEX_PAINT)));
+ }
+
/* check if we need tfaces & mcols due to face select or texture paint */
- if (BKE_paint_select_face_test(ob) || (ob->mode & OB_MODE_TEXTURE_PAINT)) {
- mask |= CD_MASK_MTFACE | CD_MASK_MCOL;
+ if ((ob->mode & OB_MODE_TEXTURE_PAINT) || editing) {
+ mask |= CD_MASK_MLOOPUV | CD_MASK_MLOOPCOL;
}
/* check if we need mcols due to vertex paint or weightpaint */
if (ob->mode & OB_MODE_VERTEX_PAINT) {
- mask |= CD_MASK_MCOL;
+ mask |= CD_MASK_MLOOPCOL;
}
if (ob->mode & OB_MODE_WEIGHT_PAINT) {
- mask |= CD_MASK_PREVIEW_MCOL;
+ mask |= CD_MASK_PREVIEW_MLOOPCOL;
}
if (ob->mode & OB_MODE_EDIT)
@@ -2339,16 +2660,18 @@ static CustomDataMask object_get_datamask(Scene *scene, Object *ob)
return mask;
}
-void makeDerivedMesh(Scene *scene, Object *ob, BMEditMesh *em,
- CustomDataMask dataMask, int build_shapekey_layers)
+void makeDerivedMesh(
+ Scene *scene, Object *ob, BMEditMesh *em,
+ CustomDataMask dataMask, const bool build_shapekey_layers)
{
- dataMask |= object_get_datamask(scene, ob);
+ bool need_mapping;
+ dataMask |= object_get_datamask(scene, ob, &need_mapping);
if (em) {
editbmesh_build_data(scene, ob, em, dataMask);
}
else {
- mesh_build_data(scene, ob, dataMask, build_shapekey_layers);
+ mesh_build_data(scene, ob, dataMask, build_shapekey_layers, need_mapping);
}
}
@@ -2359,10 +2682,15 @@ DerivedMesh *mesh_get_derived_final(Scene *scene, Object *ob, CustomDataMask dat
/* if there's no derived mesh or the last data mask used doesn't include
* the data we need, rebuild the derived mesh
*/
- dataMask |= object_get_datamask(scene, ob);
+ bool need_mapping;
+ dataMask |= object_get_datamask(scene, ob, &need_mapping);
- if (!ob->derivedFinal || (dataMask & ob->lastDataMask) != dataMask)
- mesh_build_data(scene, ob, dataMask, 0);
+ if (!ob->derivedFinal ||
+ ((dataMask & ob->lastDataMask) != dataMask) ||
+ (need_mapping != ob->lastNeedMapping))
+ {
+ mesh_build_data(scene, ob, dataMask, false, need_mapping);
+ }
if (ob->derivedFinal) { BLI_assert(!(ob->derivedFinal->dirty & DM_DIRTY_NORMALS)); }
return ob->derivedFinal;
@@ -2373,10 +2701,16 @@ DerivedMesh *mesh_get_derived_deform(Scene *scene, Object *ob, CustomDataMask da
/* if there's no derived mesh or the last data mask used doesn't include
* the data we need, rebuild the derived mesh
*/
- dataMask |= object_get_datamask(scene, ob);
+ bool need_mapping;
- if (!ob->derivedDeform || (dataMask & ob->lastDataMask) != dataMask)
- mesh_build_data(scene, ob, dataMask, 0);
+ dataMask |= object_get_datamask(scene, ob, &need_mapping);
+
+ if (!ob->derivedDeform ||
+ ((dataMask & ob->lastDataMask) != dataMask) ||
+ (need_mapping != ob->lastNeedMapping))
+ {
+ mesh_build_data(scene, ob, dataMask, false, need_mapping);
+ }
return ob->derivedDeform;
}
@@ -2385,7 +2719,9 @@ DerivedMesh *mesh_create_derived_render(Scene *scene, Object *ob, CustomDataMask
{
DerivedMesh *final;
- mesh_calc_modifiers(scene, ob, NULL, NULL, &final, 1, 1, 0, dataMask, -1, 0, 0);
+ mesh_calc_modifiers(
+ scene, ob, NULL, true, 1, false, dataMask, -1, false, false, false,
+ NULL, &final);
return final;
}
@@ -2393,13 +2729,17 @@ DerivedMesh *mesh_create_derived_render(Scene *scene, Object *ob, CustomDataMask
DerivedMesh *mesh_create_derived_index_render(Scene *scene, Object *ob, CustomDataMask dataMask, int index)
{
DerivedMesh *final;
-
- mesh_calc_modifiers(scene, ob, NULL, NULL, &final, 1, 1, 0, dataMask, index, 0, 0);
+
+ mesh_calc_modifiers(
+ scene, ob, NULL, true, 1, false, dataMask, index, false, false, false,
+ NULL, &final);
return final;
}
-DerivedMesh *mesh_create_derived_view(Scene *scene, Object *ob, CustomDataMask dataMask)
+DerivedMesh *mesh_create_derived_view(
+ Scene *scene, Object *ob,
+ CustomDataMask dataMask)
{
DerivedMesh *final;
@@ -2409,63 +2749,80 @@ DerivedMesh *mesh_create_derived_view(Scene *scene, Object *ob, CustomDataMask d
*/
ob->transflag |= OB_NO_PSYS_UPDATE;
- mesh_calc_modifiers(scene, ob, NULL, NULL, &final, 0, 1, 0, dataMask, -1, 0, 0);
+ mesh_calc_modifiers(
+ scene, ob, NULL, false, 1, false, dataMask, -1, false, false, false,
+ NULL, &final);
ob->transflag &= ~OB_NO_PSYS_UPDATE;
return final;
}
-DerivedMesh *mesh_create_derived_no_deform(Scene *scene, Object *ob, float (*vertCos)[3],
- CustomDataMask dataMask)
+DerivedMesh *mesh_create_derived_no_deform(
+ Scene *scene, Object *ob, float (*vertCos)[3],
+ CustomDataMask dataMask)
{
DerivedMesh *final;
- mesh_calc_modifiers(scene, ob, vertCos, NULL, &final, 0, 0, 0, dataMask, -1, 0, 0);
+ mesh_calc_modifiers(
+ scene, ob, vertCos, false, 0, false, dataMask, -1, false, false, false,
+ NULL, &final);
return final;
}
-DerivedMesh *mesh_create_derived_no_virtual(Scene *scene, Object *ob, float (*vertCos)[3],
- CustomDataMask dataMask)
+DerivedMesh *mesh_create_derived_no_virtual(
+ Scene *scene, Object *ob, float (*vertCos)[3],
+ CustomDataMask dataMask)
{
DerivedMesh *final;
- mesh_calc_modifiers(scene, ob, vertCos, NULL, &final, 0, -1, 0, dataMask, -1, 0, 0);
+ mesh_calc_modifiers(
+ scene, ob, vertCos, false, -1, false, dataMask, -1, false, false, false,
+ NULL, &final);
return final;
}
-DerivedMesh *mesh_create_derived_physics(Scene *scene, Object *ob, float (*vertCos)[3],
- CustomDataMask dataMask)
+DerivedMesh *mesh_create_derived_physics(
+ Scene *scene, Object *ob, float (*vertCos)[3],
+ CustomDataMask dataMask)
{
DerivedMesh *final;
- mesh_calc_modifiers(scene, ob, vertCos, NULL, &final, 0, -1, 1, dataMask, -1, 0, 0);
+ mesh_calc_modifiers(
+ scene, ob, vertCos, false, -1, true, dataMask, -1, false, false, false,
+ NULL, &final);
return final;
}
-DerivedMesh *mesh_create_derived_no_deform_render(Scene *scene, Object *ob,
- float (*vertCos)[3],
- CustomDataMask dataMask)
+DerivedMesh *mesh_create_derived_no_deform_render(
+ Scene *scene, Object *ob,
+ float (*vertCos)[3],
+ CustomDataMask dataMask)
{
DerivedMesh *final;
- mesh_calc_modifiers(scene, ob, vertCos, NULL, &final, 1, 0, 0, dataMask, -1, 0, 0);
+ mesh_calc_modifiers(
+ scene, ob, vertCos, true, 0, false, dataMask, -1, false, false, false,
+ NULL, &final);
return final;
}
/***/
-DerivedMesh *editbmesh_get_derived_cage_and_final(Scene *scene, Object *obedit, BMEditMesh *em, DerivedMesh **r_final,
- CustomDataMask dataMask)
+DerivedMesh *editbmesh_get_derived_cage_and_final(
+ Scene *scene, Object *obedit, BMEditMesh *em,
+ CustomDataMask dataMask,
+ /* return args */
+ DerivedMesh **r_final)
{
/* if there's no derived mesh or the last data mask used doesn't include
* the data we need, rebuild the derived mesh
*/
- dataMask |= object_get_datamask(scene, obedit);
+ dataMask |= object_get_datamask(scene, obedit, NULL);
if (!em->derivedCage ||
(em->lastDataMask & dataMask) != dataMask)
@@ -2483,7 +2840,7 @@ DerivedMesh *editbmesh_get_derived_cage(Scene *scene, Object *obedit, BMEditMesh
/* if there's no derived mesh or the last data mask used doesn't include
* the data we need, rebuild the derived mesh
*/
- dataMask |= object_get_datamask(scene, obedit);
+ dataMask |= object_get_datamask(scene, obedit, NULL);
if (!em->derivedCage ||
(em->lastDataMask & dataMask) != dataMask)
@@ -2512,7 +2869,9 @@ DerivedMesh *object_get_derived_final(Object *ob, const bool for_render)
return ob->derivedFinal;
}
- if (em) {
+ /* only return the editmesh if its from this object because
+ * we don't a mesh from another object's modifier stack: T43122 */
+ if (em && (em->ob == ob)) {
DerivedMesh *dm = em->derivedFinal;
return dm;
}
@@ -2587,8 +2946,9 @@ typedef struct {
BLI_bitmap *vertex_visit;
} MappedUserData;
-static void make_vertexcos__mapFunc(void *userData, int index, const float co[3],
- const float UNUSED(no_f[3]), const short UNUSED(no_s[3]))
+static void make_vertexcos__mapFunc(
+ void *userData, int index, const float co[3],
+ const float UNUSED(no_f[3]), const short UNUSED(no_s[3]))
{
MappedUserData *mappedData = (MappedUserData *)userData;
@@ -2623,9 +2983,11 @@ void mesh_get_mapped_verts_coords(DerivedMesh *dm, float (*r_cos)[3], const int
typedef struct {
float (*precomputedFaceNormals)[3];
- short (*precomputedLoopNormals)[4][3];
- MTFace *mtface; /* texture coordinates */
- MFace *mface; /* indices */
+ float (*precomputedLoopNormals)[3];
+ const MLoopTri *looptri;
+ MLoopUV *mloopuv; /* texture coordinates */
+ MPoly *mpoly; /* indices */
+ MLoop *mloop; /* indices */
MVert *mvert; /* vertices & normals */
float (*orco)[3];
float (*tangent)[4]; /* destination */
@@ -2644,15 +3006,17 @@ static int GetNumFaces(const SMikkTSpaceContext *pContext)
static int GetNumVertsOfFace(const SMikkTSpaceContext *pContext, const int face_num)
{
- SGLSLMeshToTangent *pMesh = (SGLSLMeshToTangent *) pContext->m_pUserData;
- return pMesh->mface[face_num].v4 != 0 ? 4 : 3;
+ //SGLSLMeshToTangent *pMesh = (SGLSLMeshToTangent *) pContext->m_pUserData;
+ UNUSED_VARS(pContext, face_num);
+ return 3;
}
static void GetPosition(const SMikkTSpaceContext *pContext, float r_co[3], const int face_num, const int vert_index)
{
//assert(vert_index >= 0 && vert_index < 4);
SGLSLMeshToTangent *pMesh = (SGLSLMeshToTangent *) pContext->m_pUserData;
- const float *co = pMesh->mvert[(&pMesh->mface[face_num].v1)[vert_index]].co;
+ const MLoopTri *lt = &pMesh->looptri[face_num];
+ const float *co = pMesh->mvert[pMesh->mloop[lt->tri[vert_index]].v].co;
copy_v3_v3(r_co, co);
}
@@ -2660,13 +3024,14 @@ static void GetTextureCoordinate(const SMikkTSpaceContext *pContext, float r_uv[
{
//assert(vert_index >= 0 && vert_index < 4);
SGLSLMeshToTangent *pMesh = (SGLSLMeshToTangent *) pContext->m_pUserData;
+ const MLoopTri *lt = &pMesh->looptri[face_num];
- if (pMesh->mtface != NULL) {
- const float *uv = pMesh->mtface[face_num].uv[vert_index];
+ if (pMesh->mloopuv != NULL) {
+ const float *uv = pMesh->mloopuv[lt->tri[vert_index]].uv;
copy_v2_v2(r_uv, uv);
}
else {
- const float *orco = pMesh->orco[(&pMesh->mface[face_num].v1)[vert_index]];
+ const float *orco = pMesh->orco[pMesh->mloop[lt->tri[vert_index]].v];
map_to_sphere(&r_uv[0], &r_uv[1], orco[0], orco[1], orco[2]);
}
}
@@ -2675,82 +3040,81 @@ static void GetNormal(const SMikkTSpaceContext *pContext, float r_no[3], const i
{
//assert(vert_index >= 0 && vert_index < 4);
SGLSLMeshToTangent *pMesh = (SGLSLMeshToTangent *) pContext->m_pUserData;
- const bool smoothnormal = (pMesh->mface[face_num].flag & ME_SMOOTH) != 0;
+ const MLoopTri *lt = &pMesh->looptri[face_num];
+ const bool smoothnormal = (pMesh->mpoly[lt->poly].flag & ME_SMOOTH) != 0;
if (pMesh->precomputedLoopNormals) {
- normal_short_to_float_v3(r_no, pMesh->precomputedLoopNormals[face_num][vert_index]);
+ copy_v3_v3(r_no, pMesh->precomputedLoopNormals[lt->tri[vert_index]]);
}
else if (!smoothnormal) { // flat
if (pMesh->precomputedFaceNormals) {
- copy_v3_v3(r_no, pMesh->precomputedFaceNormals[face_num]);
+ copy_v3_v3(r_no, pMesh->precomputedFaceNormals[lt->poly]);
}
else {
- MFace *mf = &pMesh->mface[face_num];
- const float *p0 = pMesh->mvert[mf->v1].co;
- const float *p1 = pMesh->mvert[mf->v2].co;
- const float *p2 = pMesh->mvert[mf->v3].co;
-
- if (mf->v4) {
- const float *p3 = pMesh->mvert[mf->v4].co;
- normal_quad_v3(r_no, p0, p1, p2, p3);
- }
- else {
- normal_tri_v3(r_no, p0, p1, p2);
- }
+ const float *p0 = pMesh->mvert[pMesh->mloop[lt->tri[0]].v].co;
+ const float *p1 = pMesh->mvert[pMesh->mloop[lt->tri[1]].v].co;
+ const float *p2 = pMesh->mvert[pMesh->mloop[lt->tri[2]].v].co;
+
+ normal_tri_v3(r_no, p0, p1, p2);
}
}
else {
- const short *no = pMesh->mvert[(&pMesh->mface[face_num].v1)[vert_index]].no;
+ const short *no = pMesh->mvert[pMesh->mloop[lt->tri[vert_index]].v].no;
normal_short_to_float_v3(r_no, no);
}
}
-static void SetTSpace(const SMikkTSpaceContext *pContext, const float fvTangent[3], const float fSign, const int face_num, const int iVert)
+static void SetTSpace(const SMikkTSpaceContext *pContext, const float fvTangent[3], const float fSign, const int face_num, const int vert_index)
{
//assert(vert_index >= 0 && vert_index < 4);
SGLSLMeshToTangent *pMesh = (SGLSLMeshToTangent *) pContext->m_pUserData;
- float *pRes = pMesh->tangent[4 * face_num + iVert];
+ const MLoopTri *lt = &pMesh->looptri[face_num];
+ float *pRes = pMesh->tangent[lt->tri[vert_index]];
copy_v3_v3(pRes, fvTangent);
pRes[3] = fSign;
}
-void DM_add_tangent_layer(DerivedMesh *dm)
+void DM_calc_loop_tangents(DerivedMesh *dm)
{
/* mesh vars */
+ const MLoopTri *looptri;
MVert *mvert;
- MTFace *mtface;
- MFace *mface;
+ MLoopUV *mloopuv;
+ MPoly *mpoly;
+ MLoop *mloop;
float (*orco)[3] = NULL, (*tangent)[4];
int /* totvert, */ totface;
float (*fnors)[3];
- short (*tlnors)[4][3];
+ float (*tlnors)[3];
- if (CustomData_get_layer_index(&dm->faceData, CD_TANGENT) != -1)
+ if (CustomData_get_layer_index(&dm->loopData, CD_TANGENT) != -1)
return;
- fnors = dm->getTessFaceDataArray(dm, CD_NORMAL);
+ fnors = dm->getPolyDataArray(dm, CD_NORMAL);
/* Note, we assume we do have tessellated loop normals at this point (in case it is object-enabled),
* have to check this is valid...
*/
- tlnors = dm->getTessFaceDataArray(dm, CD_TESSLOOPNORMAL);
+ tlnors = dm->getLoopDataArray(dm, CD_NORMAL);
/* check we have all the needed layers */
/* totvert = dm->getNumVerts(dm); */ /* UNUSED */
- totface = dm->getNumTessFaces(dm);
+ looptri = dm->getLoopTriArray(dm);
+ totface = dm->getNumLoopTri(dm);
mvert = dm->getVertArray(dm);
- mface = dm->getTessFaceArray(dm);
- mtface = dm->getTessFaceDataArray(dm, CD_MTFACE);
+ mpoly = dm->getPolyArray(dm);
+ mloop = dm->getLoopArray(dm);
+ mloopuv = dm->getLoopDataArray(dm, CD_MLOOPUV);
- if (!mtface) {
+ if (!mloopuv) {
orco = dm->getVertDataArray(dm, CD_ORCO);
if (!orco)
return;
}
/* create tangent layer */
- DM_add_tessface_layer(dm, CD_TANGENT, CD_CALLOC, NULL);
- tangent = DM_get_tessface_data_layer(dm, CD_TANGENT);
+ DM_add_loop_layer(dm, CD_TANGENT, CD_CALLOC, NULL);
+ tangent = DM_get_loop_data_layer(dm, CD_TANGENT);
/* new computation method */
{
@@ -2760,8 +3124,10 @@ void DM_add_tangent_layer(DerivedMesh *dm)
mesh2tangent.precomputedFaceNormals = fnors;
mesh2tangent.precomputedLoopNormals = tlnors;
- mesh2tangent.mtface = mtface;
- mesh2tangent.mface = mface;
+ mesh2tangent.looptri = looptri;
+ mesh2tangent.mloopuv = mloopuv;
+ mesh2tangent.mpoly = mpoly;
+ mesh2tangent.mloop = mloop;
mesh2tangent.mvert = mvert;
mesh2tangent.orco = orco;
mesh2tangent.tangent = tangent;
@@ -2811,16 +3177,24 @@ void DM_calc_auto_bump_scale(DerivedMesh *dm)
/* discard degenerate faces */
is_degenerate = 0;
- if (equals_v3v3(verts[0], verts[1]) || equals_v3v3(verts[0], verts[2]) || equals_v3v3(verts[1], verts[2]) ||
- equals_v2v2(tex_coords[0], tex_coords[1]) || equals_v2v2(tex_coords[0], tex_coords[2]) || equals_v2v2(tex_coords[1], tex_coords[2]))
+ if (equals_v3v3(verts[0], verts[1]) ||
+ equals_v3v3(verts[0], verts[2]) ||
+ equals_v3v3(verts[1], verts[2]) ||
+ equals_v2v2(tex_coords[0], tex_coords[1]) ||
+ equals_v2v2(tex_coords[0], tex_coords[2]) ||
+ equals_v2v2(tex_coords[1], tex_coords[2]))
{
is_degenerate = 1;
}
/* verify last vertex as well if this is a quad */
if (is_degenerate == 0 && nr_verts == 4) {
- if (equals_v3v3(verts[3], verts[0]) || equals_v3v3(verts[3], verts[1]) || equals_v3v3(verts[3], verts[2]) ||
- equals_v2v2(tex_coords[3], tex_coords[0]) || equals_v2v2(tex_coords[3], tex_coords[1]) || equals_v2v2(tex_coords[3], tex_coords[2]))
+ if (equals_v3v3(verts[3], verts[0]) ||
+ equals_v3v3(verts[3], verts[1]) ||
+ equals_v3v3(verts[3], verts[2]) ||
+ equals_v2v2(tex_coords[3], tex_coords[0]) ||
+ equals_v2v2(tex_coords[3], tex_coords[1]) ||
+ equals_v2v2(tex_coords[3], tex_coords[2]))
{
is_degenerate = 1;
}
@@ -2835,7 +3209,7 @@ void DM_calc_auto_bump_scale(DerivedMesh *dm)
while (is_degenerate == 0 && i < 4) {
float cur_edge[2], signed_area;
sub_v2_v2v2(cur_edge, tex_coords[(i + 1) & 0x3], tex_coords[i]);
- signed_area = prev_edge[0] * cur_edge[1] - prev_edge[1] * cur_edge[0];
+ signed_area = cross_v2v2(prev_edge, cur_edge);
if (i == 0) {
is_signed = (signed_area < 0.0f) ? 1 : 0;
@@ -2891,7 +3265,7 @@ void DM_calc_auto_bump_scale(DerivedMesh *dm)
sub_v2_v2v2(edge_t0, tex_coords[indices[t * 3 + 1]], tex_coords[indices[t * 3 + 0]]);
sub_v2_v2v2(edge_t1, tex_coords[indices[t * 3 + 2]], tex_coords[indices[t * 3 + 0]]);
- f2x_area_uv = fabsf(edge_t0[0] * edge_t1[1] - edge_t0[1] * edge_t1[0]);
+ f2x_area_uv = fabsf(cross_v2v2(edge_t0, edge_t1));
if (f2x_area_uv > FLT_EPSILON) {
float norm[3], v0[3], v1[3], f2x_surf_area, fsurf_ratio;
sub_v3_v3v3(v0, p1, p0);
@@ -2924,8 +3298,9 @@ void DM_calc_auto_bump_scale(DerivedMesh *dm)
void DM_vertex_attributes_from_gpu(DerivedMesh *dm, GPUVertexAttribs *gattribs, DMVertexAttribs *attribs)
{
- CustomData *vdata, *fdata, *tfdata = NULL;
+ CustomData *vdata, *ldata;
int a, b, layer;
+ const bool is_editmesh = (dm->type == DM_TYPE_EDITBMESH);
/* From the layers requested by the GLSL shader, figure out which ones are
* actually available for this derivedmesh, and retrieve the pointers */
@@ -2933,124 +3308,73 @@ void DM_vertex_attributes_from_gpu(DerivedMesh *dm, GPUVertexAttribs *gattribs,
memset(attribs, 0, sizeof(DMVertexAttribs));
vdata = &dm->vertData;
- fdata = tfdata = dm->getTessFaceDataLayout(dm);
+ ldata = dm->getLoopDataLayout(dm);
/* calc auto bump scale if necessary */
if (dm->auto_bump_scale <= 0.0f)
DM_calc_auto_bump_scale(dm);
/* add a tangent layer if necessary */
- for (b = 0; b < gattribs->totlayer; b++)
- if (gattribs->layer[b].type == CD_TANGENT)
- if (CustomData_get_layer_index(fdata, CD_TANGENT) == -1)
- DM_add_tangent_layer(dm);
+ for (b = 0; b < gattribs->totlayer; b++) {
+ if (gattribs->layer[b].type == CD_TANGENT) {
+ if (CustomData_get_layer_index(&dm->loopData, CD_TANGENT) == -1) {
+ dm->calcLoopTangents(dm);
+ }
+ break;
+ }
+ }
for (b = 0; b < gattribs->totlayer; b++) {
if (gattribs->layer[b].type == CD_MTFACE) {
/* uv coordinates */
- if (dm->type == DM_TYPE_EDITBMESH) {
- /* exception .. */
- CustomData *ldata = dm->getLoopDataLayout(dm);
-
- if (gattribs->layer[b].name[0])
- layer = CustomData_get_named_layer_index(ldata, CD_MLOOPUV,
- gattribs->layer[b].name);
- else
- layer = CustomData_get_active_layer_index(ldata, CD_MLOOPUV);
-
- a = attribs->tottface++;
+ if (gattribs->layer[b].name[0])
+ layer = CustomData_get_named_layer_index(ldata, CD_MLOOPUV, gattribs->layer[b].name);
+ else
+ layer = CustomData_get_active_layer_index(ldata, CD_MLOOPUV);
- if (layer != -1) {
- attribs->tface[a].array = tfdata->layers[layer].data;
- attribs->tface[a].em_offset = ldata->layers[layer].offset;
- }
- else {
- attribs->tface[a].array = NULL;
- attribs->tface[a].em_offset = -1;
- }
+ a = attribs->tottface++;
- attribs->tface[a].gl_index = gattribs->layer[b].glindex;
- attribs->tface[a].gl_texco = gattribs->layer[b].gltexco;
+ if (layer != -1) {
+ attribs->tface[a].array = is_editmesh ? NULL : ldata->layers[layer].data;
+ attribs->tface[a].em_offset = ldata->layers[layer].offset;
}
else {
- if (gattribs->layer[b].name[0])
- layer = CustomData_get_named_layer_index(tfdata, CD_MTFACE,
- gattribs->layer[b].name);
- else
- layer = CustomData_get_active_layer_index(tfdata, CD_MTFACE);
-
- a = attribs->tottface++;
-
- if (layer != -1) {
- attribs->tface[a].array = tfdata->layers[layer].data;
- attribs->tface[a].em_offset = tfdata->layers[layer].offset;
- }
- else {
- attribs->tface[a].array = NULL;
- attribs->tface[a].em_offset = -1;
- }
-
- attribs->tface[a].gl_index = gattribs->layer[b].glindex;
- attribs->tface[a].gl_texco = gattribs->layer[b].gltexco;
+ attribs->tface[a].array = NULL;
+ attribs->tface[a].em_offset = -1;
}
+
+ attribs->tface[a].gl_index = gattribs->layer[b].glindex;
+ attribs->tface[a].gl_texco = gattribs->layer[b].gltexco;
}
else if (gattribs->layer[b].type == CD_MCOL) {
- if (dm->type == DM_TYPE_EDITBMESH) {
- /* exception .. */
- CustomData *ldata = dm->getLoopDataLayout(dm);
-
- if (gattribs->layer[b].name[0])
- layer = CustomData_get_named_layer_index(ldata, CD_MLOOPCOL,
- gattribs->layer[b].name);
- else
- layer = CustomData_get_active_layer_index(ldata, CD_MLOOPCOL);
+ if (gattribs->layer[b].name[0])
+ layer = CustomData_get_named_layer_index(ldata, CD_MLOOPCOL, gattribs->layer[b].name);
+ else
+ layer = CustomData_get_active_layer_index(ldata, CD_MLOOPCOL);
- a = attribs->totmcol++;
+ a = attribs->totmcol++;
- if (layer != -1) {
- attribs->mcol[a].array = tfdata->layers[layer].data;
- /* odd, store the offset for a different layer type here, but editmode draw code expects it */
- attribs->mcol[a].em_offset = ldata->layers[layer].offset;
- }
- else {
- attribs->mcol[a].array = NULL;
- attribs->mcol[a].em_offset = -1;
- }
-
- attribs->mcol[a].gl_index = gattribs->layer[b].glindex;
+ if (layer != -1) {
+ attribs->mcol[a].array = is_editmesh ? NULL : ldata->layers[layer].data;
+ /* odd, store the offset for a different layer type here, but editmode draw code expects it */
+ attribs->mcol[a].em_offset = ldata->layers[layer].offset;
}
else {
- /* vertex colors */
- if (gattribs->layer[b].name[0])
- layer = CustomData_get_named_layer_index(tfdata, CD_MCOL,
- gattribs->layer[b].name);
- else
- layer = CustomData_get_active_layer_index(tfdata, CD_MCOL);
-
- a = attribs->totmcol++;
-
- if (layer != -1) {
- attribs->mcol[a].array = tfdata->layers[layer].data;
- /* odd, store the offset for a different layer type here, but editmode draw code expects it */
- attribs->mcol[a].em_offset = tfdata->layers[layer].offset;
- }
- else {
- attribs->mcol[a].array = NULL;
- attribs->mcol[a].em_offset = -1;
- }
-
- attribs->mcol[a].gl_index = gattribs->layer[b].glindex;
+ attribs->mcol[a].array = NULL;
+ attribs->mcol[a].em_offset = -1;
}
+
+ attribs->mcol[a].gl_index = gattribs->layer[b].glindex;
}
else if (gattribs->layer[b].type == CD_TANGENT) {
- /* tangents */
- layer = CustomData_get_layer_index(fdata, CD_TANGENT);
+ /* note, even with 'is_editmesh' this uses the derived-meshes loop data */
+ layer = CustomData_get_layer_index(&dm->loopData, CD_TANGENT);
attribs->tottang = 1;
if (layer != -1) {
- attribs->tang.array = fdata->layers[layer].data;
- attribs->tang.em_offset = fdata->layers[layer].offset;
+ attribs->tang.array = dm->loopData.layers[layer].data;
+ attribs->tang.em_offset = dm->loopData.layers[layer].offset;
}
else {
attribs->tang.array = NULL;
@@ -3079,13 +3403,79 @@ void DM_vertex_attributes_from_gpu(DerivedMesh *dm, GPUVertexAttribs *gattribs,
}
}
+/**
+ * Set vertex shader attribute inputs for a particular tessface vert
+ *
+ * \param a: tessface index
+ * \param index: vertex index
+ * \param vert: corner index (0, 1, 2, 3)
+ * \param loop: absolute loop corner index
+ */
+void DM_draw_attrib_vertex(DMVertexAttribs *attribs, int a, int index, int vert, int loop)
+{
+ const float zero[4] = {0.0f, 0.0f, 0.0f, 0.0f};
+ int b;
+
+ UNUSED_VARS(a, vert);
+
+ /* orco texture coordinates */
+ if (attribs->totorco) {
+ /*const*/ float (*array)[3] = attribs->orco.array;
+ const float *orco = (array) ? array[index] : zero;
+
+ if (attribs->orco.gl_texco)
+ glTexCoord3fv(orco);
+ else
+ glVertexAttrib3fvARB(attribs->orco.gl_index, orco);
+ }
+
+ /* uv texture coordinates */
+ for (b = 0; b < attribs->tottface; b++) {
+ const float *uv;
+
+ if (attribs->tface[b].array) {
+ const MLoopUV *mloopuv = &attribs->tface[b].array[loop];
+ uv = mloopuv->uv;
+ }
+ else {
+ uv = zero;
+ }
+
+ if (attribs->tface[b].gl_texco)
+ glTexCoord2fv(uv);
+ else
+ glVertexAttrib2fvARB(attribs->tface[b].gl_index, uv);
+ }
+
+ /* vertex colors */
+ for (b = 0; b < attribs->totmcol; b++) {
+ GLubyte col[4];
+
+ if (attribs->mcol[b].array) {
+ const MLoopCol *cp = &attribs->mcol[b].array[loop];
+ copy_v4_v4_char((char *)col, &cp->r);
+ }
+ else {
+ col[0] = 0; col[1] = 0; col[2] = 0; col[3] = 0;
+ }
+
+ glVertexAttrib4ubvARB(attribs->mcol[b].gl_index, col);
+ }
+
+ /* tangent for normal mapping */
+ if (attribs->tottang) {
+ /*const*/ float (*array)[4] = attribs->tang.array;
+ const float *tang = (array) ? array[loop] : zero;
+ glVertexAttrib4fvARB(attribs->tang.gl_index, tang);
+ }
+}
+
/* Set object's bounding box based on DerivedMesh min/max data */
void DM_set_object_boundbox(Object *ob, DerivedMesh *dm)
{
float min[3], max[3];
INIT_MINMAX(min, max);
-
dm->getMinMax(dm, min, max);
if (!ob->bb)
@@ -3142,7 +3532,8 @@ static void navmesh_drawColored(DerivedMesh *dm)
#endif
glDisable(GL_LIGHTING);
- /* if (GPU_buffer_legacy(dm) ) */ { /* TODO - VBO draw code, not high priority - campbell */
+ /* if (GPU_buffer_legacy(dm) ) */ /* TODO - VBO draw code, not high priority - campbell */
+ {
DEBUG_VBO("Using legacy code. drawNavMeshColored\n");
//glShadeModel(GL_SMOOTH);
glBegin(glmode = GL_QUADS);
@@ -3173,24 +3564,21 @@ static void navmesh_drawColored(DerivedMesh *dm)
glEnable(GL_LIGHTING);
}
-static void navmesh_DM_drawFacesTex(DerivedMesh *dm,
- DMSetDrawOptionsTex setDrawOptions,
- DMCompareDrawOptions compareDrawOptions,
- void *userData, DMDrawFlag UNUSED(flag))
+static void navmesh_DM_drawFacesTex(
+ DerivedMesh *dm,
+ DMSetDrawOptionsTex UNUSED(setDrawOptions),
+ DMCompareDrawOptions UNUSED(compareDrawOptions),
+ void *UNUSED(userData), DMDrawFlag UNUSED(flag))
{
- (void) setDrawOptions;
- (void) compareDrawOptions;
- (void) userData;
-
navmesh_drawColored(dm);
}
-static void navmesh_DM_drawFacesSolid(DerivedMesh *dm,
- float (*partial_redraw_planes)[4],
- bool UNUSED(fast), DMSetMaterial setMaterial)
+static void navmesh_DM_drawFacesSolid(
+ DerivedMesh *dm,
+ float (*partial_redraw_planes)[4],
+ bool UNUSED(fast), DMSetMaterial UNUSED(setMaterial))
{
- (void) partial_redraw_planes;
- (void) setMaterial;
+ UNUSED_VARS(partial_redraw_planes);
//drawFacesSolid_original(dm, partial_redraw_planes, fast, setMaterial);
navmesh_drawColored(dm);
@@ -3309,8 +3697,9 @@ void DM_init_origspace(DerivedMesh *dm)
#ifndef NDEBUG
#include "BLI_dynstr.h"
-static void dm_debug_info_layers(DynStr *dynstr, DerivedMesh *dm, CustomData *cd,
- void *(*getElemDataArray)(DerivedMesh *, int))
+static void dm_debug_info_layers(
+ DynStr *dynstr, DerivedMesh *dm, CustomData *cd,
+ void *(*getElemDataArray)(DerivedMesh *, int))
{
int type;
@@ -3326,7 +3715,7 @@ static void dm_debug_info_layers(DynStr *dynstr, DerivedMesh *dm, CustomData *cd
CustomData_file_write_info(type, &structname, &structnum);
BLI_dynstr_appendf(dynstr,
" dict(name='%s', struct='%s', type=%d, ptr='%p', elem=%d, length=%d),\n",
- name, structname, type, (void *)pt, size, pt_size);
+ name, structname, type, (const void *)pt, size, pt_size);
}
}
}
@@ -3390,7 +3779,7 @@ void DM_debug_print(DerivedMesh *dm)
void DM_debug_print_cdlayers(CustomData *data)
{
int i;
- CustomDataLayer *layer;
+ const CustomDataLayer *layer;
printf("{\n");
@@ -3402,7 +3791,7 @@ void DM_debug_print_cdlayers(CustomData *data)
int structnum;
CustomData_file_write_info(layer->type, &structname, &structnum);
printf(" dict(name='%s', struct='%s', type=%d, ptr='%p', elem=%d, length=%d),\n",
- name, structname, layer->type, (void *)layer->data, size, (int)(MEM_allocN_len(layer->data) / size));
+ name, structname, layer->type, (const void *)layer->data, size, (int)(MEM_allocN_len(layer->data) / size));
}
printf("}\n");
@@ -3421,7 +3810,7 @@ bool DM_is_valid(DerivedMesh *dm)
dm->getEdgeDataLayout(dm),
dm->getLoopDataLayout(dm),
dm->getPolyDataLayout(dm),
- 0, /* setting mask here isn't useful, gives false positives */
+ false, /* setting mask here isn't useful, gives false positives */
do_verbose, do_fixes, &changed);
is_valid &= BKE_mesh_validate_arrays(
@@ -3473,41 +3862,41 @@ MEdge *DM_get_edge_array(DerivedMesh *dm, bool *allocated)
return medge;
}
-MLoop *DM_get_loop_array(DerivedMesh *dm, bool *allocated)
+MLoop *DM_get_loop_array(DerivedMesh *dm, bool *r_allocated)
{
- CustomData *loop_data = dm->getEdgeDataLayout(dm);
+ CustomData *loop_data = dm->getLoopDataLayout(dm);
MLoop *mloop = CustomData_get_layer(loop_data, CD_MLOOP);
- *allocated = false;
+ *r_allocated = false;
if (mloop == NULL) {
mloop = MEM_mallocN(sizeof(MLoop) * dm->getNumLoops(dm), "dm loop data array");
dm->copyLoopArray(dm, mloop);
- *allocated = true;
+ *r_allocated = true;
}
return mloop;
}
-MPoly *DM_get_poly_array(DerivedMesh *dm, bool *allocated)
+MPoly *DM_get_poly_array(DerivedMesh *dm, bool *r_allocated)
{
CustomData *poly_data = dm->getPolyDataLayout(dm);
MPoly *mpoly = CustomData_get_layer(poly_data, CD_MPOLY);
- *allocated = false;
+ *r_allocated = false;
if (mpoly == NULL) {
mpoly = MEM_mallocN(sizeof(MPoly) * dm->getNumPolys(dm), "dm poly data array");
dm->copyPolyArray(dm, mpoly);
- *allocated = true;
+ *r_allocated = true;
}
return mpoly;
}
-MFace *DM_get_tessface_array(DerivedMesh *dm, bool *allocated)
+MFace *DM_get_tessface_array(DerivedMesh *dm, bool *r_allocated)
{
CustomData *tessface_data = dm->getTessFaceDataLayout(dm);
MFace *mface = CustomData_get_layer(tessface_data, CD_MFACE);
- *allocated = false;
+ *r_allocated = false;
if (mface == NULL) {
int numTessFaces = dm->getNumTessFaces(dm);
@@ -3515,9 +3904,41 @@ MFace *DM_get_tessface_array(DerivedMesh *dm, bool *allocated)
if (numTessFaces > 0) {
mface = MEM_mallocN(sizeof(MFace) * numTessFaces, "bvh mface data array");
dm->copyTessFaceArray(dm, mface);
- *allocated = true;
+ *r_allocated = true;
}
}
return mface;
}
+
+const MLoopTri *DM_get_looptri_array(
+ DerivedMesh *dm,
+ const MVert *mvert,
+ const MPoly *mpoly, int mpoly_len,
+ const MLoop *mloop, int mloop_len,
+ bool *r_allocated)
+{
+ const MLoopTri *looptri = dm->getLoopTriArray(dm);
+ *r_allocated = false;
+
+ if (looptri == NULL) {
+ if (mpoly_len > 0) {
+ const int looptris_num = poly_to_tri_count(mpoly_len, mloop_len);
+ MLoopTri *looptri_data;
+
+ looptri_data = MEM_mallocN(sizeof(MLoopTri) * looptris_num, __func__);
+
+ BKE_mesh_recalc_looptri(
+ mloop, mpoly,
+ mvert,
+ mloop_len, mpoly_len,
+ looptri_data);
+
+ looptri = looptri_data;
+
+ *r_allocated = true;
+ }
+ }
+
+ return looptri;
+}
diff --git a/source/blender/blenkernel/intern/action.c b/source/blender/blenkernel/intern/action.c
index c6dcca576fb..b77ae45e94d 100644
--- a/source/blender/blenkernel/intern/action.c
+++ b/source/blender/blenkernel/intern/action.c
@@ -47,13 +47,14 @@
#include "BLI_utildefines.h"
#include "BLI_ghash.h"
-#include "BLF_translation.h"
+#include "BLT_translation.h"
#include "BKE_action.h"
#include "BKE_anim.h"
#include "BKE_animsys.h"
#include "BKE_constraint.h"
#include "BKE_deform.h"
+#include "BKE_depsgraph.h"
#include "BKE_fcurve.h"
#include "BKE_global.h"
#include "BKE_idprop.h"
@@ -215,6 +216,10 @@ bAction *BKE_action_copy(bAction *src)
}
}
+ if (src->id.lib) {
+ BKE_id_lib_local_paths(G.main, src->id.lib, &dst->id);
+ }
+
return dst;
}
@@ -450,9 +455,9 @@ bPoseChannel *BKE_pose_channel_find_name(const bPose *pose, const char *name)
return NULL;
if (pose->chanhash)
- return BLI_ghash_lookup(pose->chanhash, (void *)name);
+ return BLI_ghash_lookup(pose->chanhash, (const void *)name);
- return BLI_findstring(&((bPose *)pose)->chanbase, name, offsetof(bPoseChannel, name));
+ return BLI_findstring(&((const bPose *)pose)->chanbase, name, offsetof(bPoseChannel, name));
}
/**
@@ -480,6 +485,9 @@ bPoseChannel *BKE_pose_channel_verify(bPose *pose, const char *name)
chan = MEM_callocN(sizeof(bPoseChannel), "verifyPoseChannel");
BLI_strncpy(chan->name, name, sizeof(chan->name));
+
+ chan->custom_scale = 1.0f;
+
/* init vars to prevent math errors */
unit_qt(chan->quat);
unit_axis_angle(chan->rotAxis, &chan->rotAngle);
@@ -712,6 +720,57 @@ void BKE_pose_channels_hash_free(bPose *pose)
}
/**
+ * Selectively remove pose channels.
+ */
+void BKE_pose_channels_remove(
+ Object *ob,
+ bool (*filter_fn)(const char *bone_name, void *user_data), void *user_data)
+{
+ /* First erase any associated pose channel */
+ if (ob->pose) {
+ bPoseChannel *pchan, *pchan_next;
+ bConstraint *con;
+
+ for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan_next) {
+ pchan_next = pchan->next;
+
+ if (filter_fn(pchan->name, user_data)) {
+ BKE_pose_channel_free(pchan);
+ if (ob->pose->chanhash) {
+ BLI_ghash_remove(ob->pose->chanhash, pchan->name, NULL, NULL);
+ }
+ BLI_freelinkN(&ob->pose->chanbase, pchan);
+ }
+ else {
+ for (con = pchan->constraints.first; con; con = con->next) {
+ const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
+ ListBase targets = {NULL, NULL};
+ bConstraintTarget *ct;
+
+ if (cti && cti->get_constraint_targets) {
+ cti->get_constraint_targets(con, &targets);
+
+ for (ct = targets.first; ct; ct = ct->next) {
+ if (ct->tar == ob) {
+ if (ct->subtarget[0]) {
+ if (filter_fn(ct->subtarget, user_data)) {
+ con->flag |= CONSTRAINT_DISABLE;
+ ct->subtarget[0] = 0;
+ }
+ }
+ }
+ }
+
+ if (cti->flush_constraint_targets)
+ cti->flush_constraint_targets(con, &targets, 0);
+ }
+ }
+ }
+ }
+ }
+}
+
+/**
* Deallocates a pose channel.
* Does not free the pose channel itself.
*/
@@ -729,7 +788,7 @@ void BKE_pose_channel_free_ex(bPoseChannel *pchan, bool do_id_user)
pchan->mpath = NULL;
}
- BKE_constraints_free(&pchan->constraints);
+ BKE_constraints_free_ex(&pchan->constraints, do_id_user);
if (pchan->prop) {
IDP_FreeProperty(pchan->prop);
@@ -925,6 +984,12 @@ void BKE_pose_update_constraint_flags(bPose *pose)
pchan->constflag |= PCHAN_HAS_CONST;
}
}
+ pose->flag &= ~POSE_CONSTRAINTS_NEED_UPDATE_FLAGS;
+}
+
+void BKE_pose_tag_update_constraint_flags(bPose *pose)
+{
+ pose->flag |= POSE_CONSTRAINTS_NEED_UPDATE_FLAGS;
}
/* Clears all BONE_UNKEYED flags for every pose channel in every pose
@@ -966,7 +1031,7 @@ bActionGroup *BKE_pose_add_group(bPose *pose, const char *name)
BLI_addtail(&pose->agroups, grp);
BLI_uniquename(&pose->agroups, grp, name, '.', offsetof(bActionGroup, name), sizeof(grp->name));
- pose->active_group = BLI_countlist(&pose->agroups);
+ pose->active_group = BLI_listbase_count(&pose->agroups);
return grp;
}
@@ -998,8 +1063,12 @@ void BKE_pose_remove_group(bPose *pose, bActionGroup *grp, const int index)
/* now, remove it from the pose */
BLI_freelinkN(&pose->agroups, grp);
if (pose->active_group >= idx) {
+ const bool has_groups = !BLI_listbase_is_empty(&pose->agroups);
pose->active_group--;
- if (pose->active_group < 0 || BLI_listbase_is_empty(&pose->agroups)) {
+ if (pose->active_group == 0 && has_groups) {
+ pose->active_group = 1;
+ }
+ else if (pose->active_group < 0 || !has_groups) {
pose->active_group = 0;
}
}
@@ -1028,12 +1097,12 @@ bool action_has_motion(const bAction *act)
if (act) {
for (fcu = act->curves.first; fcu; fcu = fcu->next) {
if (fcu->totvert)
- return 1;
+ return true;
}
}
/* nothing found */
- return 0;
+ return false;
}
/* Calculate the extents of given action */
@@ -1303,6 +1372,16 @@ bool BKE_pose_copy_result(bPose *to, bPose *from)
return true;
}
+/* Tag pose for recalc. Also tag all related data to be recalc. */
+void BKE_pose_tag_recalc(Main *bmain, bPose *pose)
+{
+ pose->flag |= POSE_RECALC;
+ /* Depsgraph components depends on actual pose state,
+ * if pose was changed depsgraph is to be updated as well.
+ */
+ DAG_relations_tag_update(bmain);
+}
+
/* For the calculation of the effects of an Action at the given frame on an object
* This is currently only used for the Action Constraint
*/
diff --git a/source/blender/blenkernel/intern/addon.c b/source/blender/blenkernel/intern/addon.c
index 119fa266908..811461b84c1 100644
--- a/source/blender/blenkernel/intern/addon.c
+++ b/source/blender/blenkernel/intern/addon.c
@@ -29,15 +29,9 @@
#include "BLI_utildefines.h"
#include "BLI_ghash.h"
-#include "BLI_string.h"
#include "BKE_addon.h" /* own include */
-#include "RNA_access.h"
-#include "RNA_define.h"
-
-#include "BLF_translation.h"
-
#include "MEM_guardedalloc.h"
static GHash *global_addonpreftype_hash = NULL;
@@ -68,12 +62,12 @@ bAddonPrefType *BKE_addon_pref_type_find(const char *idname, bool quiet)
void BKE_addon_pref_type_add(bAddonPrefType *apt)
{
- BLI_ghash_insert(global_addonpreftype_hash, (void *)apt->idname, apt);
+ BLI_ghash_insert(global_addonpreftype_hash, apt->idname, apt);
}
-void BKE_addon_pref_type_remove(bAddonPrefType *apt)
+void BKE_addon_pref_type_remove(const bAddonPrefType *apt)
{
- BLI_ghash_remove(global_addonpreftype_hash, (void *)apt->idname, NULL, MEM_freeN);
+ BLI_ghash_remove(global_addonpreftype_hash, apt->idname, NULL, MEM_freeN);
}
void BKE_addon_pref_type_init(void)
diff --git a/source/blender/blenkernel/intern/anim.c b/source/blender/blenkernel/intern/anim.c
index aff99d3e1bf..dff696863e9 100644
--- a/source/blender/blenkernel/intern/anim.c
+++ b/source/blender/blenkernel/intern/anim.c
@@ -36,7 +36,7 @@
#include "BLI_listbase.h"
#include "BLI_math.h"
-#include "BLF_translation.h"
+#include "BLT_translation.h"
#include "DNA_anim_types.h"
#include "DNA_armature_types.h"
@@ -627,6 +627,9 @@ int where_on_path(Object *ob, float ctime, float vec[4], float dir[3], float qua
if (!bl->nr) return 0;
if (bl->poly > -1) cycl = 1;
+ /* values below zero for non-cyclic curves give strange results */
+ BLI_assert(cycl || ctime >= 0.0f);
+
ctime *= (path->len - 1);
s1 = (int)floor(ctime);
diff --git a/source/blender/blenkernel/intern/anim_sys.c b/source/blender/blenkernel/intern/anim_sys.c
index 5ee82bb5842..8010d3450cb 100644
--- a/source/blender/blenkernel/intern/anim_sys.c
+++ b/source/blender/blenkernel/intern/anim_sys.c
@@ -44,25 +44,30 @@
#include "BLI_dynstr.h"
#include "BLI_listbase.h"
-#include "BLF_translation.h"
+#include "BLT_translation.h"
#include "DNA_anim_types.h"
#include "DNA_lamp_types.h"
#include "DNA_material_types.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_space_types.h"
#include "DNA_texture_types.h"
#include "DNA_world_types.h"
#include "BKE_animsys.h"
#include "BKE_action.h"
+#include "BKE_context.h"
#include "BKE_depsgraph.h"
#include "BKE_fcurve.h"
#include "BKE_nla.h"
#include "BKE_global.h"
#include "BKE_main.h"
+#include "BKE_material.h"
#include "BKE_library.h"
#include "BKE_report.h"
+#include "BKE_texture.h"
#include "RNA_access.h"
@@ -78,7 +83,7 @@ bool id_type_can_have_animdata(ID *id)
{
/* sanity check */
if (id == NULL)
- return 0;
+ return false;
/* Only some ID-blocks have this info for now */
/* TODO: finish adding this for the other blocktypes */
@@ -95,13 +100,14 @@ bool id_type_can_have_animdata(ID *id)
case ID_SCE:
case ID_MC:
case ID_MSK:
+ case ID_GD:
{
- return 1;
+ return true;
}
/* no AnimData */
default:
- return 0;
+ return false;
}
}
@@ -128,7 +134,7 @@ AnimData *BKE_animdata_from_id(ID *id)
* the AnimData pointer is stored immediately after the given ID-block in the struct,
* as per IdAdtTemplate. Also note that
*/
-AnimData *BKE_id_add_animdata(ID *id)
+AnimData *BKE_animdata_add_id(ID *id)
{
/* Only some ID-blocks have this info for now, so we cast the
* types that do to be of type IdAdtTemplate, and add the AnimData
@@ -188,20 +194,20 @@ bool BKE_animdata_set_action(ReportList *reports, ID *id, bAction *act)
/* can set */
adt->action = act;
id_us_plus((ID *)adt->action);
- ok = 1;
+ ok = true;
}
else {
/* cannot set */
BKE_reportf(reports, RPT_ERROR,
"Could not set action '%s' onto ID '%s', as it does not have suitably rooted paths "
"for this purpose", act->id.name + 2, id->name);
- /* ok = 0; */
+ /* ok = false; */
}
}
else {
/* just clearing the action... */
adt->action = NULL;
- ok = 1;
+ ok = true;
}
return ok;
@@ -210,7 +216,7 @@ bool BKE_animdata_set_action(ReportList *reports, ID *id, bAction *act)
/* Freeing -------------------------------------------- */
/* Free AnimData used by the nominated ID-block, and clear ID-block's AnimData pointer */
-void BKE_free_animdata(ID *id)
+void BKE_animdata_free(ID *id)
{
/* Only some ID-blocks have this info for now, so we cast the
* types that do to be of type IdAdtTemplate
@@ -247,7 +253,7 @@ void BKE_free_animdata(ID *id)
/* Copying -------------------------------------------- */
/* Make a copy of the given AnimData - to be used when copying datablocks */
-AnimData *BKE_copy_animdata(AnimData *adt, const bool do_action)
+AnimData *BKE_animdata_copy(AnimData *adt, const bool do_action)
{
AnimData *dadt;
@@ -279,25 +285,25 @@ AnimData *BKE_copy_animdata(AnimData *adt, const bool do_action)
return dadt;
}
-bool BKE_copy_animdata_id(ID *id_to, ID *id_from, const bool do_action)
+bool BKE_animdata_copy_id(ID *id_to, ID *id_from, const bool do_action)
{
AnimData *adt;
if ((id_to && id_from) && (GS(id_to->name) != GS(id_from->name)))
- return 0;
+ return false;
- BKE_free_animdata(id_to);
+ BKE_animdata_free(id_to);
adt = BKE_animdata_from_id(id_from);
if (adt) {
IdAdtTemplate *iat = (IdAdtTemplate *)id_to;
- iat->adt = BKE_copy_animdata(adt, do_action);
+ iat->adt = BKE_animdata_copy(adt, do_action);
}
- return 1;
+ return true;
}
-void BKE_copy_animdata_id_action(ID *id)
+void BKE_animdata_copy_id_action(ID *id)
{
AnimData *adt = BKE_animdata_from_id(id);
if (adt) {
@@ -312,6 +318,77 @@ void BKE_copy_animdata_id_action(ID *id)
}
}
+/* Merge copies of the data from the src AnimData into the destination AnimData */
+void BKE_animdata_merge_copy(ID *dst_id, ID *src_id, eAnimData_MergeCopy_Modes action_mode, bool fix_drivers)
+{
+ AnimData *src = BKE_animdata_from_id(src_id);
+ AnimData *dst = BKE_animdata_from_id(dst_id);
+
+ /* sanity checks */
+ if (ELEM(NULL, dst, src))
+ return;
+
+ // TODO: we must unset all "tweakmode" flags
+ if ((src->flag & ADT_NLA_EDIT_ON) || (dst->flag & ADT_NLA_EDIT_ON)) {
+ printf("ERROR: Merging AnimData blocks while editing NLA is dangerous as it may cause data corruption\n");
+ return;
+ }
+
+ /* handle actions... */
+ if (action_mode == ADT_MERGECOPY_SRC_COPY) {
+ /* make a copy of the actions */
+ dst->action = BKE_action_copy(src->action);
+ dst->tmpact = BKE_action_copy(src->tmpact);
+ }
+ else if (action_mode == ADT_MERGECOPY_SRC_REF) {
+ /* make a reference to it */
+ dst->action = src->action;
+ id_us_plus((ID *)dst->action);
+
+ dst->tmpact = src->tmpact;
+ id_us_plus((ID *)dst->tmpact);
+ }
+
+ /* duplicate NLA data */
+ if (src->nla_tracks.first) {
+ ListBase tracks = {NULL, NULL};
+
+ copy_nladata(&tracks, &src->nla_tracks);
+ BLI_movelisttolist(&dst->nla_tracks, &tracks);
+ }
+
+ /* duplicate drivers (F-Curves) */
+ if (src->drivers.first) {
+ ListBase drivers = {NULL, NULL};
+
+ copy_fcurves(&drivers, &src->drivers);
+
+ /* Fix up all driver targets using the old target id
+ * - This assumes that the src ID is being merged into the dst ID
+ */
+ if (fix_drivers) {
+ FCurve *fcu;
+
+ for (fcu = drivers.first; fcu; fcu = fcu->next) {
+ ChannelDriver *driver = fcu->driver;
+ DriverVar *dvar;
+
+ for (dvar = driver->variables.first; dvar; dvar = dvar->next) {
+ DRIVER_TARGETS_USED_LOOPER(dvar)
+ {
+ if (dtar->id == src_id) {
+ dtar->id = dst_id;
+ }
+ }
+ DRIVER_TARGETS_LOOPER_END
+ }
+ }
+ }
+
+ BLI_movelisttolist(&dst->drivers, &drivers);
+ }
+}
+
/* Make Local -------------------------------------------- */
static void make_local_strips(ListBase *strips)
@@ -349,7 +426,7 @@ void BKE_animdata_make_local(AnimData *adt)
/* When duplicating data (i.e. objects), drivers referring to the original data will
* get updated to point to the duplicated data (if drivers belong to the new data)
*/
-void BKE_relink_animdata(AnimData *adt)
+void BKE_animdata_relink(AnimData *adt)
{
/* sanity check */
if (adt == NULL)
@@ -494,7 +571,7 @@ void BKE_animdata_separate_by_basepath(ID *srcID, ID *dstID, ListBase *basepaths
/* get animdata from src, and create for destination (if needed) */
srcAdt = BKE_animdata_from_id(srcID);
- dstAdt = BKE_id_add_animdata(dstID);
+ dstAdt = BKE_animdata_add_id(dstID);
if (ELEM(NULL, srcAdt, dstAdt)) {
if (G.debug & G_DEBUG)
@@ -551,6 +628,74 @@ void BKE_animdata_separate_by_basepath(ID *srcID, ID *dstID, ListBase *basepaths
}
}
+/**
+ * Temporary wrapper for driver operators for buttons to make it easier to create
+ * such drivers by rerouting all paths through the active object instead so that
+ * they will get picked up by the dependency system.
+ *
+ * \param C Context pointer - for getting active data
+ * \param[in,out] ptr RNA pointer for property's datablock. May be modified as result of path remapping.
+ * \param prop RNA definition of property to add for
+ * \return MEM_alloc'd string representing the path to the property from the given #PointerRNA
+ */
+char *BKE_animdata_driver_path_hack(bContext *C, PointerRNA *ptr, PropertyRNA *prop, char *base_path)
+{
+ ID *id = (ID *)ptr->id.data;
+ ScrArea *sa = CTX_wm_area(C);
+
+ /* get standard path which may be extended */
+ char *basepath = base_path ? base_path : RNA_path_from_ID_to_property(ptr, prop);
+ char *path = basepath; /* in case no remapping is needed */
+
+ /* Remapping will only be performed in the Properties Editor, as only this
+ * restricts the subspace of options to the 'active' data (a manageable state)
+ */
+ /* TODO: watch out for pinned context? */
+ if ((sa) && (sa->spacetype == SPACE_BUTS)) {
+ Object *ob = CTX_data_active_object(C);
+
+ if (ob && id) {
+ /* only id-types which can be remapped to go through objects should be considered */
+ switch (GS(id->name)) {
+ case ID_TE: /* textures */
+ {
+ Material *ma = give_current_material(ob, ob->actcol);
+ Tex *tex = give_current_material_texture(ma);
+
+ /* assumes: texture will only be shown if it is active material's active texture it's ok */
+ if ((ID *)tex == id) {
+ char name_esc_ma[(sizeof(ma->id.name) - 2) * 2];
+ char name_esc_tex[(sizeof(tex->id.name) - 2) * 2];
+
+ BLI_strescape(name_esc_ma, ma->id.name + 2, sizeof(name_esc_ma));
+ BLI_strescape(name_esc_tex, tex->id.name + 2, sizeof(name_esc_tex));
+
+ /* create new path */
+ // TODO: use RNA path functions to construct step by step instead?
+ // FIXME: maybe this isn't even needed anymore...
+ path = BLI_sprintfN("material_slots[\"%s\"].material.texture_slots[\"%s\"].texture.%s",
+ name_esc_ma, name_esc_tex, basepath);
+
+ /* free old one */
+ if (basepath != base_path)
+ MEM_freeN(basepath);
+ }
+ break;
+ }
+ }
+
+ /* fix RNA pointer, as we've now changed the ID root by changing the paths */
+ if (basepath != path) {
+ /* rebase provided pointer so that it starts from object... */
+ RNA_pointer_create(&ob->id, ptr->type, ptr->data, ptr);
+ }
+ }
+ }
+
+ /* the path should now have been corrected for use */
+ return path;
+}
+
/* Path Validation -------------------------------------------- */
/* Check if a given RNA Path is valid, by tracing it from the given ID, and seeing if we can resolve it */
@@ -646,7 +791,7 @@ static void fcurves_path_rename_fix(ID *owner_id, const char *prefix, const char
if (fcu->rna_path != old_path) {
bActionGroup *agrp = fcu->grp;
- if ((agrp) && strcmp(oldName, agrp->name) == 0) {
+ if ((agrp) && STREQ(oldName, agrp->name)) {
BLI_strncpy(agrp->name, newName, sizeof(agrp->name));
}
}
@@ -683,7 +828,7 @@ static void drivers_path_rename_fix(ID *owner_id, ID *ref_id, const char *prefix
/* also fix the bone-name (if applicable) */
if (strstr(prefix, "bones")) {
if ( ((dtar->id) && (GS(dtar->id->name) == ID_OB) && (!ref_id || ((Object *)(dtar->id))->data == ref_id)) &&
- (dtar->pchan_name[0]) && (strcmp(oldName, dtar->pchan_name) == 0) )
+ (dtar->pchan_name[0]) && STREQ(oldName, dtar->pchan_name) )
{
BLI_strncpy(dtar->pchan_name, newName, sizeof(dtar->pchan_name));
}
@@ -713,6 +858,60 @@ static void nlastrips_path_rename_fix(ID *owner_id, const char *prefix, const ch
}
}
+/* ----------------------- */
+
+
+/* Fix up the given RNA-Path
+ *
+ * This is just an external wrapper for the RNA-Path fixing function,
+ * with input validity checks on top of the basic method.
+ *
+ * NOTE: it is assumed that the structure we're replacing is <prefix><["><name><"]>
+ * i.e. pose.bones["Bone"]
+ */
+char *BKE_animsys_fix_rna_path_rename(ID *owner_id, char *old_path, const char *prefix, const char *oldName,
+ const char *newName, int oldSubscript, int newSubscript, bool verify_paths)
+{
+ char *oldN, *newN;
+ char *result;
+
+ /* if no action, no need to proceed */
+ if (ELEM(NULL, owner_id, old_path)) {
+ printf("early abort\n");
+ return old_path;
+ }
+
+ /* Name sanitation logic - copied from BKE_animdata_fix_paths_rename() */
+ if ((oldName != NULL) && (newName != NULL)) {
+ /* pad the names with [" "] so that only exact matches are made */
+ const size_t name_old_len = strlen(oldName);
+ const size_t name_new_len = strlen(newName);
+ char *name_old_esc = BLI_array_alloca(name_old_esc, (name_old_len * 2) + 1);
+ char *name_new_esc = BLI_array_alloca(name_new_esc, (name_new_len * 2) + 1);
+
+ BLI_strescape(name_old_esc, oldName, (name_old_len * 2) + 1);
+ BLI_strescape(name_new_esc, newName, (name_new_len * 2) + 1);
+ oldN = BLI_sprintfN("[\"%s\"]", name_old_esc);
+ newN = BLI_sprintfN("[\"%s\"]", name_new_esc);
+ }
+ else {
+ oldN = BLI_sprintfN("[%d]", oldSubscript);
+ newN = BLI_sprintfN("[%d]", newSubscript);
+ }
+
+ /* fix given path */
+ printf("%s | %s | oldpath = %p ", oldN, newN, old_path);
+ result = rna_path_rename_fix(owner_id, prefix, oldN, newN, old_path, verify_paths);
+ printf("result = %p\n", result);
+
+ /* free the temp names */
+ MEM_freeN(oldN);
+ MEM_freeN(newN);
+
+ /* return the resulting path - may be the same path again if nothing changed */
+ return result;
+}
+
/* Fix all RNA_Paths in the given Action, relative to the given ID block
*
* This is just an external wrapper for the F-Curve fixing function,
@@ -958,6 +1157,9 @@ void BKE_animdata_main_cb(Main *mainptr, ID_AnimData_Edit_Callback func, void *u
/* line styles */
ANIMDATA_IDS_CB(mainptr->linestyle.first);
+
+ /* grease pencil */
+ ANIMDATA_IDS_CB(mainptr->gpencil.first);
}
/* Fix all RNA-Paths throughout the database (directly access the Global.main version)
@@ -965,7 +1167,7 @@ void BKE_animdata_main_cb(Main *mainptr, ID_AnimData_Edit_Callback func, void *u
* i.e. pose.bones["Bone"]
*/
/* TODO: use BKE_animdata_main_cb for looping over all data */
-void BKE_all_animdata_fix_paths_rename(ID *ref_id, const char *prefix, const char *oldName, const char *newName)
+void BKE_animdata_fix_paths_rename_all(ID *ref_id, const char *prefix, const char *oldName, const char *newName)
{
Main *mainptr = G.main;
ID *id;
@@ -1046,6 +1248,9 @@ void BKE_all_animdata_fix_paths_rename(ID *ref_id, const char *prefix, const cha
/* linestyles */
RENAMEFIX_ANIM_IDS(mainptr->linestyle.first);
+ /* grease pencil */
+ RENAMEFIX_ANIM_IDS(mainptr->gpencil.first);
+
/* scenes */
RENAMEFIX_ANIM_NODETREE_IDS(mainptr->scene.first, Scene);
}
@@ -1076,7 +1281,7 @@ KS_Path *BKE_keyingset_find_path(KeyingSet *ks, ID *id, const char group_name[],
eq_id = 0;
/* path */
- if ((ksp->rna_path == NULL) || strcmp(rna_path, ksp->rna_path))
+ if ((ksp->rna_path == NULL) || !STREQ(rna_path, ksp->rna_path))
eq_path = 0;
/* index - need to compare whole-array setting too... */
@@ -1112,6 +1317,7 @@ KeyingSet *BKE_keyingset_add(ListBase *list, const char idname[], const char nam
ks->flag = flag;
ks->keyingflag = keyingflag;
+ ks->keyingoverride = keyingflag; /* NOTE: assume that if one is set one way, the other should be too, so that it'll work */
/* add KeyingSet to list */
BLI_addtail(list, ks);
@@ -1273,11 +1479,11 @@ static bool animsys_remap_path(AnimMapper *UNUSED(remap), char *path, char **dst
/* nothing suitable found, so just set dst to look at path (i.e. no alloc/free needed) */
*dst = path;
- return 0;
+ return false;
}
-/* less then 1.0 evaluates to false, use epsilon to avoid float error */
+/* less than 1.0 evaluates to false, use epsilon to avoid float error */
#define ANIMSYS_FLOAT_AS_BOOL(value) ((value) > ((1.0f - FLT_EPSILON)))
/* Write the given value to a setting using RNA, and return success */
@@ -1290,8 +1496,11 @@ static bool animsys_write_rna_setting(PointerRNA *ptr, char *path, int array_ind
/* get property to write to */
if (RNA_path_resolve_property(ptr, path, &new_ptr, &prop)) {
- /* set value - only for animatable numerical values */
- if (RNA_property_animateable(&new_ptr, prop)) {
+ /* set value for animatable numerical values only
+ * HACK: some local F-Curves (e.g. those on NLA Strips) are evaluated
+ * without an ID provided, which causes the animateable test to fail!
+ */
+ if (RNA_property_animateable(&new_ptr, prop) || (ptr->id.data == NULL)) {
int array_len = RNA_property_array_length(&new_ptr, prop);
bool written = false;
@@ -1302,7 +1511,7 @@ static bool animsys_write_rna_setting(PointerRNA *ptr, char *path, int array_ind
path, array_index, array_len - 1);
}
- return 0;
+ return false;
}
switch (RNA_property_type(prop)) {
@@ -1356,7 +1565,7 @@ static bool animsys_write_rna_setting(PointerRNA *ptr, char *path, int array_ind
break;
default:
/* nothing can be done here... so it is unsuccessful? */
- return 0;
+ return false;
}
/* RNA property update disabled for now - [#28525] [#28690] [#28774] [#28777] */
@@ -1395,7 +1604,7 @@ static bool animsys_write_rna_setting(PointerRNA *ptr, char *path, int array_ind
}
/* successful */
- return 1;
+ return true;
}
else {
/* failed to get path */
@@ -1406,12 +1615,12 @@ static bool animsys_write_rna_setting(PointerRNA *ptr, char *path, int array_ind
(ptr->id.data) ? (((ID *)ptr->id.data)->name + 2) : "<No ID>",
path, array_index);
}
- return 0;
+ return false;
}
}
/* Simple replacement based data-setting of the FCurve using RNA */
-static bool animsys_execute_fcurve(PointerRNA *ptr, AnimMapper *remap, FCurve *fcu)
+bool BKE_animsys_execute_fcurve(PointerRNA *ptr, AnimMapper *remap, FCurve *fcu)
{
char *path = NULL;
bool free_path = false;
@@ -1446,7 +1655,7 @@ static void animsys_evaluate_fcurves(PointerRNA *ptr, ListBase *list, AnimMapper
/* check if this curve should be skipped */
if ((fcu->flag & (FCURVE_MUTED | FCURVE_DISABLED)) == 0) {
calculate_fcurve(fcu, ctime);
- animsys_execute_fcurve(ptr, remap, fcu);
+ BKE_animsys_execute_fcurve(ptr, remap, fcu);
}
}
}
@@ -1476,7 +1685,7 @@ static void animsys_evaluate_drivers(PointerRNA *ptr, AnimData *adt, float ctime
* NOTE: for 'layering' option later on, we should check if we should remove old value before adding
* new to only be done when drivers only changed */
calculate_fcurve(fcu, ctime);
- ok = animsys_execute_fcurve(ptr, NULL, fcu);
+ ok = BKE_animsys_execute_fcurve(ptr, NULL, fcu);
/* clear recalc flag */
driver->flag &= ~DRIVER_FLAG_RECALC;
@@ -1545,7 +1754,7 @@ void animsys_evaluate_action_group(PointerRNA *ptr, bAction *act, bActionGroup *
/* check if this curve should be skipped */
if ((fcu->flag & (FCURVE_MUTED | FCURVE_DISABLED)) == 0) {
calculate_fcurve(fcu, ctime);
- animsys_execute_fcurve(ptr, remap, fcu);
+ BKE_animsys_execute_fcurve(ptr, remap, fcu);
}
}
}
@@ -1591,12 +1800,6 @@ static float nlastrip_get_influence(NlaStrip *strip, float cframe)
/* evaluate the evaluation time and influence for the strip, storing the results in the strip */
static void nlastrip_evaluate_controls(NlaStrip *strip, float ctime)
{
- /* firstly, analytically generate values for influence and time (if applicable) */
- if ((strip->flag & NLASTRIP_FLAG_USR_TIME) == 0)
- strip->strip_time = nlastrip_get_frame(strip, ctime, NLATIME_CONVERT_EVAL);
- if ((strip->flag & NLASTRIP_FLAG_USR_INFLUENCE) == 0)
- strip->influence = nlastrip_get_influence(strip, ctime);
-
/* now strip's evaluate F-Curves for these settings (if applicable) */
if (strip->fcurves.first) {
PointerRNA strip_ptr;
@@ -1607,6 +1810,15 @@ static void nlastrip_evaluate_controls(NlaStrip *strip, float ctime)
/* execute these settings as per normal */
animsys_evaluate_fcurves(&strip_ptr, &strip->fcurves, NULL, ctime);
}
+
+ /* analytically generate values for influence and time (if applicable)
+ * - we do this after the F-Curves have been evaluated to override the effects of those
+ * in case the override has been turned off.
+ */
+ if ((strip->flag & NLASTRIP_FLAG_USR_TIME) == 0)
+ strip->strip_time = nlastrip_get_frame(strip, ctime, NLATIME_CONVERT_EVAL);
+ if ((strip->flag & NLASTRIP_FLAG_USR_INFLUENCE) == 0)
+ strip->influence = nlastrip_get_influence(strip, ctime);
/* if user can control the evaluation time (using F-Curves), consider the option which allows this time to be clamped
* to lie within extents of the action-clip, so that a steady changing rate of progress through several cycles of the clip
@@ -2259,13 +2471,19 @@ static void animsys_evaluate_nla(ListBase *echannels, PointerRNA *ptr, AnimData
if ((adt->flag & ADT_NLA_EDIT_ON) && (nlt->flag & NLATRACK_DISABLED))
break;
- /* skip if we're only considering a track tagged 'solo' */
- if ((adt->flag & ADT_NLA_SOLO_TRACK) && (nlt->flag & NLATRACK_SOLO) == 0)
- continue;
- /* skip if track is muted */
- if (nlt->flag & NLATRACK_MUTED)
- continue;
-
+ /* solo and muting are mutually exclusive... */
+ if (adt->flag & ADT_NLA_SOLO_TRACK) {
+ /* skip if there is a solo track, but this isn't it */
+ if ((nlt->flag & NLATRACK_SOLO) == 0)
+ continue;
+ /* else - mute doesn't matter */
+ }
+ else {
+ /* no solo tracks - skip track if muted */
+ if (nlt->flag & NLATRACK_MUTED)
+ continue;
+ }
+
/* if this track has strips (but maybe they won't be suitable), set has_strips
* - used for mainly for still allowing normal action evaluation...
*/
@@ -2607,6 +2825,9 @@ void BKE_animsys_evaluate_all_animation(Main *main, Scene *scene, float ctime)
/* linestyles */
EVAL_ANIM_IDS(main->linestyle.first, ADT_RECALC_ANIM);
+ /* grease pencil */
+ EVAL_ANIM_IDS(main->gpencil.first, ADT_RECALC_ANIM);
+
/* objects */
/* ADT_RECALC_ANIM doesn't need to be supplied here, since object AnimData gets
* this tagged by Depsgraph on framechange. This optimization means that objects
@@ -2625,3 +2846,62 @@ void BKE_animsys_evaluate_all_animation(Main *main, Scene *scene, float ctime)
}
/* ***************************************** */
+
+/* ************** */
+/* Evaluation API */
+
+#define DEBUG_PRINT if (G.debug & G_DEBUG_DEPSGRAPH) printf
+
+void BKE_animsys_eval_animdata(EvaluationContext *eval_ctx, ID *id)
+{
+ AnimData *adt = BKE_animdata_from_id(id);
+ Scene *scene = NULL; /* XXX: this is only needed for flushing RNA updates,
+ * which should get handled as part of the graph instead...
+ */
+ DEBUG_PRINT("%s on %s, time=%f\n\n", __func__, id->name, (double)eval_ctx->ctime);
+ BKE_animsys_evaluate_animdata(scene, id, adt, eval_ctx->ctime, ADT_RECALC_ANIM);
+}
+
+void BKE_animsys_eval_driver(EvaluationContext *eval_ctx,
+ ID *id,
+ FCurve *fcu)
+{
+ /* TODO(sergey): De-duplicate with BKE animsys. */
+ ChannelDriver *driver = fcu->driver;
+ PointerRNA id_ptr;
+ bool ok = false;
+
+ DEBUG_PRINT("%s on %s (%s[%d])\n",
+ __func__,
+ id->name,
+ fcu->rna_path,
+ fcu->array_index);
+
+ RNA_id_pointer_create(id, &id_ptr);
+
+ /* check if this driver's curve should be skipped */
+ if ((fcu->flag & (FCURVE_MUTED | FCURVE_DISABLED)) == 0) {
+ /* check if driver itself is tagged for recalculation */
+ /* XXX driver recalc flag is not set yet by depsgraph! */
+ if ((driver) && !(driver->flag & DRIVER_FLAG_INVALID) /*&& (driver->flag & DRIVER_FLAG_RECALC)*/) {
+ /* evaluate this using values set already in other places
+ * NOTE: for 'layering' option later on, we should check if we should remove old value before adding
+ * new to only be done when drivers only changed */
+ //printf("\told val = %f\n", fcu->curval);
+ calculate_fcurve(fcu, eval_ctx->ctime);
+ ok = BKE_animsys_execute_fcurve(&id_ptr, NULL, fcu);
+ //printf("\tnew val = %f\n", fcu->curval);
+
+ /* clear recalc flag */
+ driver->flag &= ~DRIVER_FLAG_RECALC;
+
+ /* set error-flag if evaluation failed */
+ if (ok == 0) {
+ printf("invalid driver - %s[%d]\n", fcu->rna_path, fcu->array_index);
+ driver->flag |= DRIVER_FLAG_INVALID;
+ }
+ }
+ }
+}
+
+#undef DEBUG_PRINT
diff --git a/source/blender/blenkernel/intern/appdir.c b/source/blender/blenkernel/intern/appdir.c
new file mode 100644
index 00000000000..ee6710e1130
--- /dev/null
+++ b/source/blender/blenkernel/intern/appdir.c
@@ -0,0 +1,791 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+/** \file blender/blenkernel/intern/appdir.c
+ * \ingroup bke
+ *
+ * Access to application level directories.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+
+#include "BLI_utildefines.h"
+#include "BLI_string.h"
+#include "BLI_fileops.h"
+#include "BLI_path_util.h"
+
+#include "BKE_blender.h" /* BLENDER_VERSION */
+#include "BKE_appdir.h" /* own include */
+
+#include "GHOST_Path-api.h"
+
+#include "MEM_guardedalloc.h"
+
+#ifdef WIN32
+# include "utf_winfunc.h"
+# include "utfconv.h"
+# include <io.h>
+# ifdef _WIN32_IE
+# undef _WIN32_IE
+# endif
+# define _WIN32_IE 0x0501
+# include <windows.h>
+# include <shlobj.h>
+# include "BLI_winstuff.h"
+#else /* non windows */
+# ifdef WITH_BINRELOC
+# include "binreloc.h"
+# endif
+# include <unistd.h> /* mkdtemp on OSX (and probably all *BSD?), not worth making specific check for this OS. */
+#endif /* WIN32 */
+
+/* local */
+static char bprogname[FILE_MAX]; /* full path to program executable */
+static char bprogdir[FILE_MAX]; /* full path to directory in which executable is located */
+static char btempdir_base[FILE_MAX]; /* persistent temporary directory */
+static char btempdir_session[FILE_MAX] = ""; /* volatile temporary directory */
+
+/* This is now only used to really get the user's default document folder */
+/* On Windows I chose the 'Users/<MyUserName>/Documents' since it's used
+ * as default location to save documents */
+const char *BKE_appdir_folder_default(void)
+{
+#ifndef WIN32
+ const char * const xdg_documents_dir = getenv("XDG_DOCUMENTS_DIR");
+
+ if (xdg_documents_dir)
+ return xdg_documents_dir;
+
+ return getenv("HOME");
+#else /* Windows */
+ static char documentfolder[MAXPATHLEN];
+ HRESULT hResult;
+
+ /* Check for %HOME% env var */
+ if (uput_getenv("HOME", documentfolder, MAXPATHLEN)) {
+ if (BLI_is_dir(documentfolder)) return documentfolder;
+ }
+
+ /* add user profile support for WIN 2K / NT.
+ * This is %APPDATA%, which translates to either
+ * %USERPROFILE%\Application Data or since Vista
+ * to %USERPROFILE%\AppData\Roaming
+ */
+ hResult = SHGetFolderPath(NULL, CSIDL_PERSONAL, NULL, SHGFP_TYPE_CURRENT, documentfolder);
+
+ if (hResult == S_OK) {
+ if (BLI_is_dir(documentfolder)) return documentfolder;
+ }
+
+ return NULL;
+#endif /* WIN32 */
+}
+
+
+// #define PATH_DEBUG
+
+/* returns a formatted representation of the specified version number. Non-reentrant! */
+static char *blender_version_decimal(const int ver)
+{
+ static char version_str[5];
+ sprintf(version_str, "%d.%02d", ver / 100, ver % 100);
+ return version_str;
+}
+
+/**
+ * Concatenates path_base, (optional) path_sep and (optional) folder_name into targetpath,
+ * returning true if result points to a directory.
+ */
+static bool test_path(char *targetpath, const char *path_base, const char *path_sep, const char *folder_name)
+{
+ char tmppath[FILE_MAX];
+
+ if (path_sep) BLI_join_dirfile(tmppath, sizeof(tmppath), path_base, path_sep);
+ else BLI_strncpy(tmppath, path_base, sizeof(tmppath));
+
+ /* rare cases folder_name is omitted (when looking for ~/.blender/2.xx dir only) */
+ if (folder_name)
+ BLI_make_file_string("/", targetpath, tmppath, folder_name);
+ else
+ BLI_strncpy(targetpath, tmppath, sizeof(tmppath));
+ /* FIXME: why is "//" on front of tmppath expanded to "/" (by BLI_join_dirfile)
+ * if folder_name is specified but not otherwise? */
+
+ if (BLI_is_dir(targetpath)) {
+#ifdef PATH_DEBUG
+ printf("\t%s found: %s\n", __func__, targetpath);
+#endif
+ return true;
+ }
+ else {
+#ifdef PATH_DEBUG
+ printf("\t%s missing: %s\n", __func__, targetpath);
+#endif
+ //targetpath[0] = '\0';
+ return false;
+ }
+}
+
+/**
+ * Puts the value of the specified environment variable into *path if it exists
+ * and points at a directory. Returns true if this was done.
+ */
+static bool test_env_path(char *path, const char *envvar)
+{
+ const char *env = envvar ? getenv(envvar) : NULL;
+ if (!env) return false;
+
+ if (BLI_is_dir(env)) {
+ BLI_strncpy(path, env, FILE_MAX);
+#ifdef PATH_DEBUG
+ printf("\t%s env %s found: %s\n", __func__, envvar, env);
+#endif
+ return true;
+ }
+ else {
+ path[0] = '\0';
+#ifdef PATH_DEBUG
+ printf("\t%s env %s missing: %s\n", __func__, envvar, env);
+#endif
+ return false;
+ }
+}
+
+/**
+ * Constructs in \a targetpath the name of a directory relative to a version-specific
+ * subdirectory in the parent directory of the Blender executable.
+ *
+ * \param targetpath String to return path
+ * \param folder_name Optional folder name within version-specific directory
+ * \param subfolder_name Optional subfolder name within folder_name
+ * \param ver To construct name of version-specific directory within bprogdir
+ * \return true if such a directory exists.
+ */
+static bool get_path_local(char *targetpath, const char *folder_name, const char *subfolder_name, const int ver)
+{
+ char relfolder[FILE_MAX];
+
+#ifdef PATH_DEBUG
+ printf("%s...\n", __func__);
+#endif
+
+ if (folder_name) {
+ if (subfolder_name) {
+ BLI_join_dirfile(relfolder, sizeof(relfolder), folder_name, subfolder_name);
+ }
+ else {
+ BLI_strncpy(relfolder, folder_name, sizeof(relfolder));
+ }
+ }
+ else {
+ relfolder[0] = '\0';
+ }
+
+ /* try EXECUTABLE_DIR/2.5x/folder_name - new default directory for local blender installed files */
+#ifdef __APPLE__
+ static char osx_resourses[FILE_MAX]; /* due new codesign situation in OSX > 10.9.5 we must move the blender_version dir with contents to Resources */
+ sprintf(osx_resourses, "%s../Resources", bprogdir);
+ return test_path(targetpath, osx_resourses, blender_version_decimal(ver), relfolder);
+#else
+ return test_path(targetpath, bprogdir, blender_version_decimal(ver), relfolder);
+#endif
+}
+
+/**
+ * Is this an install with user files kept together with the Blender executable and its
+ * installation files.
+ */
+static bool is_portable_install(void)
+{
+ /* detect portable install by the existence of config folder */
+ const int ver = BLENDER_VERSION;
+ char path[FILE_MAX];
+
+ return get_path_local(path, "config", NULL, ver);
+}
+
+/**
+ * Returns the path of a folder within the user-files area.
+ *
+ *
+ * \param targetpath String to return path
+ * \param folder_name default name of folder within user area
+ * \param subfolder_name optional name of subfolder within folder
+ * \param envvar name of environment variable which, if defined, overrides folder_name
+ * \param ver Blender version, used to construct a subdirectory name
+ * \return true if it was able to construct such a path.
+ */
+static bool get_path_user(char *targetpath, const char *folder_name, const char *subfolder_name, const char *envvar, const int ver)
+{
+ char user_path[FILE_MAX];
+ const char *user_base_path;
+
+ /* for portable install, user path is always local */
+ if (is_portable_install())
+ return get_path_local(targetpath, folder_name, subfolder_name, ver);
+
+ user_path[0] = '\0';
+
+ if (test_env_path(user_path, envvar)) {
+ if (subfolder_name) {
+ return test_path(targetpath, user_path, NULL, subfolder_name);
+ }
+ else {
+ BLI_strncpy(targetpath, user_path, FILE_MAX);
+ return true;
+ }
+ }
+
+ user_base_path = (const char *)GHOST_getUserDir(ver, blender_version_decimal(ver));
+ if (user_base_path)
+ BLI_strncpy(user_path, user_base_path, FILE_MAX);
+
+ if (!user_path[0])
+ return false;
+
+#ifdef PATH_DEBUG
+ printf("%s: %s\n", __func__, user_path);
+#endif
+
+ if (subfolder_name) {
+ return test_path(targetpath, user_path, folder_name, subfolder_name);
+ }
+ else {
+ return test_path(targetpath, user_path, NULL, folder_name);
+ }
+}
+
+/**
+ * Returns the path of a folder within the Blender installation directory.
+ *
+ * \param targetpath String to return path
+ * \param folder_name default name of folder within installation area
+ * \param subfolder_name optional name of subfolder within folder
+ * \param envvar name of environment variable which, if defined, overrides folder_name
+ * \param ver Blender version, used to construct a subdirectory name
+ * \return true if it was able to construct such a path.
+ */
+static bool get_path_system(char *targetpath, const char *folder_name, const char *subfolder_name, const char *envvar, const int ver)
+{
+ char system_path[FILE_MAX];
+ const char *system_base_path;
+ char cwd[FILE_MAX];
+ char relfolder[FILE_MAX];
+
+ if (folder_name) {
+ if (subfolder_name) {
+ BLI_join_dirfile(relfolder, sizeof(relfolder), folder_name, subfolder_name);
+ }
+ else {
+ BLI_strncpy(relfolder, folder_name, sizeof(relfolder));
+ }
+ }
+ else {
+ relfolder[0] = '\0';
+ }
+
+ /* first allow developer only overrides to the system path
+ * these are only used when running blender from source */
+
+ /* try CWD/release/folder_name */
+ if (BLI_current_working_dir(cwd, sizeof(cwd))) {
+ if (test_path(targetpath, cwd, "release", relfolder)) {
+ return true;
+ }
+ }
+
+ /* try EXECUTABLE_DIR/release/folder_name */
+ if (test_path(targetpath, bprogdir, "release", relfolder))
+ return true;
+
+ /* end developer overrides */
+
+
+
+ system_path[0] = '\0';
+
+ if (test_env_path(system_path, envvar)) {
+ if (subfolder_name) {
+ return test_path(targetpath, system_path, NULL, subfolder_name);
+ }
+ else {
+ BLI_strncpy(targetpath, system_path, FILE_MAX);
+ return true;
+ }
+ }
+
+ system_base_path = (const char *)GHOST_getSystemDir(ver, blender_version_decimal(ver));
+ if (system_base_path)
+ BLI_strncpy(system_path, system_base_path, FILE_MAX);
+
+ if (!system_path[0])
+ return false;
+
+#ifdef PATH_DEBUG
+ printf("%s: %s\n", __func__, system_path);
+#endif
+
+ if (subfolder_name) {
+ /* try $BLENDERPATH/folder_name/subfolder_name */
+ return test_path(targetpath, system_path, folder_name, subfolder_name);
+ }
+ else {
+ /* try $BLENDERPATH/folder_name */
+ return test_path(targetpath, system_path, NULL, folder_name);
+ }
+}
+
+/* get a folder out of the 'folder_id' presets for paths */
+/* returns the path if found, NULL string if not */
+const char *BKE_appdir_folder_id(const int folder_id, const char *subfolder)
+{
+ const int ver = BLENDER_VERSION;
+ static char path[FILE_MAX] = "";
+
+ switch (folder_id) {
+ case BLENDER_DATAFILES: /* general case */
+ if (get_path_user(path, "datafiles", subfolder, "BLENDER_USER_DATAFILES", ver)) break;
+ if (get_path_local(path, "datafiles", subfolder, ver)) break;
+ if (get_path_system(path, "datafiles", subfolder, "BLENDER_SYSTEM_DATAFILES", ver)) break;
+ return NULL;
+
+ case BLENDER_USER_DATAFILES:
+ if (get_path_user(path, "datafiles", subfolder, "BLENDER_USER_DATAFILES", ver)) break;
+ return NULL;
+
+ case BLENDER_SYSTEM_DATAFILES:
+ if (get_path_local(path, "datafiles", subfolder, ver)) break;
+ if (get_path_system(path, "datafiles", subfolder, "BLENDER_SYSTEM_DATAFILES", ver)) break;
+ return NULL;
+
+ case BLENDER_USER_AUTOSAVE:
+ if (get_path_user(path, "autosave", subfolder, "BLENDER_USER_DATAFILES", ver)) break;
+ return NULL;
+
+ case BLENDER_USER_CONFIG:
+ if (get_path_user(path, "config", subfolder, "BLENDER_USER_CONFIG", ver)) break;
+ return NULL;
+
+ case BLENDER_USER_SCRIPTS:
+ if (get_path_user(path, "scripts", subfolder, "BLENDER_USER_SCRIPTS", ver)) break;
+ return NULL;
+
+ case BLENDER_SYSTEM_SCRIPTS:
+ if (get_path_local(path, "scripts", subfolder, ver)) break;
+ if (get_path_system(path, "scripts", subfolder, "BLENDER_SYSTEM_SCRIPTS", ver)) break;
+ return NULL;
+
+ case BLENDER_SYSTEM_PYTHON:
+ if (get_path_local(path, "python", subfolder, ver)) break;
+ if (get_path_system(path, "python", subfolder, "BLENDER_SYSTEM_PYTHON", ver)) break;
+ return NULL;
+
+ default:
+ BLI_assert(0);
+ break;
+ }
+
+ return path;
+}
+
+/**
+ * Returns the path to a folder in the user area without checking that it actually exists first.
+ */
+const char *BKE_appdir_folder_id_user_notest(const int folder_id, const char *subfolder)
+{
+ const int ver = BLENDER_VERSION;
+ static char path[FILE_MAX] = "";
+
+ switch (folder_id) {
+ case BLENDER_USER_DATAFILES:
+ get_path_user(path, "datafiles", subfolder, "BLENDER_USER_DATAFILES", ver);
+ break;
+ case BLENDER_USER_CONFIG:
+ get_path_user(path, "config", subfolder, "BLENDER_USER_CONFIG", ver);
+ break;
+ case BLENDER_USER_AUTOSAVE:
+ get_path_user(path, "autosave", subfolder, "BLENDER_USER_AUTOSAVE", ver);
+ break;
+ case BLENDER_USER_SCRIPTS:
+ get_path_user(path, "scripts", subfolder, "BLENDER_USER_SCRIPTS", ver);
+ break;
+ default:
+ BLI_assert(0);
+ break;
+ }
+
+ if ('\0' == path[0]) {
+ return NULL;
+ }
+ return path;
+}
+
+/**
+ * Returns the path to a folder in the user area, creating it if it doesn't exist.
+ */
+const char *BKE_appdir_folder_id_create(const int folder_id, const char *subfolder)
+{
+ const char *path;
+
+ /* only for user folders */
+ if (!ELEM(folder_id, BLENDER_USER_DATAFILES, BLENDER_USER_CONFIG, BLENDER_USER_SCRIPTS, BLENDER_USER_AUTOSAVE))
+ return NULL;
+
+ path = BKE_appdir_folder_id(folder_id, subfolder);
+
+ if (!path) {
+ path = BKE_appdir_folder_id_user_notest(folder_id, subfolder);
+ if (path) BLI_dir_create_recursive(path);
+ }
+
+ return path;
+}
+
+/**
+ * Returns the path of the top-level version-specific local, user or system directory.
+ * If do_check, then the result will be NULL if the directory doesn't exist.
+ */
+const char *BKE_appdir_folder_id_version(const int folder_id, const int ver, const bool do_check)
+{
+ static char path[FILE_MAX] = "";
+ bool ok;
+ switch (folder_id) {
+ case BLENDER_RESOURCE_PATH_USER:
+ ok = get_path_user(path, NULL, NULL, NULL, ver);
+ break;
+ case BLENDER_RESOURCE_PATH_LOCAL:
+ ok = get_path_local(path, NULL, NULL, ver);
+ break;
+ case BLENDER_RESOURCE_PATH_SYSTEM:
+ ok = get_path_system(path, NULL, NULL, NULL, ver);
+ break;
+ default:
+ path[0] = '\0'; /* in case do_check is false */
+ ok = false;
+ BLI_assert(!"incorrect ID");
+ break;
+ }
+
+ if (!ok && do_check) {
+ return NULL;
+ }
+
+ return path;
+}
+
+#ifdef PATH_DEBUG
+# undef PATH_DEBUG
+#endif
+
+
+/* -------------------------------------------------------------------- */
+/* Preset paths */
+
+/**
+ * Checks if name is a fully qualified filename to an executable.
+ * If not it searches $PATH for the file. On Windows it also
+ * adds the correct extension (.com .exe etc) from
+ * $PATHEXT if necessary. Also on Windows it translates
+ * the name to its 8.3 version to prevent problems with
+ * spaces and stuff. Final result is returned in fullname.
+ *
+ * \param fullname The full path and full name of the executable
+ * (must be FILE_MAX minimum)
+ * \param name The name of the executable (usually argv[0]) to be checked
+ */
+static void where_am_i(char *fullname, const size_t maxlen, const char *name)
+{
+#ifdef WITH_BINRELOC
+ /* linux uses binreloc since argv[0] is not reliable, call br_init( NULL ) first */
+ {
+ const char *path = NULL;
+ path = br_find_exe(NULL);
+ if (path) {
+ BLI_strncpy(fullname, path, maxlen);
+ free((void *)path);
+ return;
+ }
+ }
+#endif
+
+#ifdef _WIN32
+ {
+ wchar_t *fullname_16 = MEM_mallocN(maxlen * sizeof(wchar_t), "ProgramPath");
+ if (GetModuleFileNameW(0, fullname_16, maxlen)) {
+ conv_utf_16_to_8(fullname_16, fullname, maxlen);
+ if (!BLI_exists(fullname)) {
+ printf("path can't be found: \"%.*s\"\n", (int)maxlen, fullname);
+ MessageBox(NULL, "path contains invalid characters or is too long (see console)", "Error", MB_OK);
+ }
+ MEM_freeN(fullname_16);
+ return;
+ }
+
+ MEM_freeN(fullname_16);
+ }
+#endif
+
+ /* unix and non linux */
+ if (name && name[0]) {
+
+ BLI_strncpy(fullname, name, maxlen);
+ if (name[0] == '.') {
+ char wdir[FILE_MAX] = "";
+ BLI_current_working_dir(wdir, sizeof(wdir)); /* backup cwd to restore after */
+
+ // not needed but avoids annoying /./ in name
+ if (name[1] == SEP)
+ BLI_join_dirfile(fullname, maxlen, wdir, name + 2);
+ else
+ BLI_join_dirfile(fullname, maxlen, wdir, name);
+
+#ifdef _WIN32
+ BLI_path_program_extensions_add_win32(fullname, maxlen);
+#endif
+ }
+ else if (BLI_last_slash(name)) {
+ // full path
+ BLI_strncpy(fullname, name, maxlen);
+#ifdef _WIN32
+ BLI_path_program_extensions_add_win32(fullname, maxlen);
+#endif
+ }
+ else {
+ BLI_path_program_search(fullname, maxlen, name);
+ }
+#if defined(DEBUG)
+ if (!STREQ(name, fullname)) {
+ printf("guessing '%s' == '%s'\n", name, fullname);
+ }
+#endif
+ }
+}
+
+void BKE_appdir_program_path_init(const char *argv0)
+{
+ where_am_i(bprogname, sizeof(bprogname), argv0);
+ BLI_split_dir_part(bprogname, bprogdir, sizeof(bprogdir));
+}
+
+/**
+ * Path to executable
+ */
+const char *BKE_appdir_program_path(void)
+{
+ return bprogname;
+}
+
+/**
+ * Path to directory of executable
+ */
+const char *BKE_appdir_program_dir(void)
+{
+ return bprogdir;
+}
+
+bool BKE_appdir_program_python_search(
+ char *fullpath, const size_t fullpath_len,
+ const int version_major, const int version_minor)
+{
+ const char *basename = "python";
+ char python_ver[16];
+ /* check both possible names */
+ const char *python_names[] = {basename, python_ver};
+ int i;
+
+ bool is_found = false;
+
+ BLI_snprintf(python_ver, sizeof(python_ver), "%s%d.%d", basename, version_major, version_minor);
+
+ {
+ const char *python_bin_dir = BKE_appdir_folder_id(BLENDER_SYSTEM_PYTHON, "bin");
+ if (python_bin_dir) {
+
+ for (i = 0; i < ARRAY_SIZE(python_names); i++) {
+ BLI_join_dirfile(fullpath, fullpath_len, python_bin_dir, python_names[i]);
+
+ if (
+#ifdef _WIN32
+ BLI_path_program_extensions_add_win32(fullpath, fullpath_len)
+#else
+ BLI_exists(fullpath)
+#endif
+ )
+ {
+ is_found = true;
+ break;
+ }
+ }
+ }
+ }
+
+ if (is_found == false) {
+ for (i = 0; i < ARRAY_SIZE(python_names); i++) {
+ if (BLI_path_program_search(fullpath, fullpath_len, python_names[i])) {
+ is_found = true;
+ break;
+ }
+ }
+ }
+
+ if (is_found == false) {
+ *fullpath = '\0';
+ }
+
+ return is_found;
+}
+
+/**
+ * Gets the temp directory when blender first runs.
+ * If the default path is not found, use try $TEMP
+ *
+ * Also make sure the temp dir has a trailing slash
+ *
+ * \param fullname The full path to the temporary temp directory
+ * \param basename The full path to the persistent temp directory (may be NULL)
+ * \param maxlen The size of the fullname buffer
+ * \param userdir Directory specified in user preferences
+ */
+static void where_is_temp(char *fullname, char *basename, const size_t maxlen, char *userdir)
+{
+ /* Clear existing temp dir, if needed. */
+ BKE_tempdir_session_purge();
+
+ fullname[0] = '\0';
+ if (basename) {
+ basename[0] = '\0';
+ }
+
+ if (userdir && BLI_is_dir(userdir)) {
+ BLI_strncpy(fullname, userdir, maxlen);
+ }
+
+
+#ifdef WIN32
+ if (fullname[0] == '\0') {
+ const char *tmp = getenv("TEMP"); /* Windows */
+ if (tmp && BLI_is_dir(tmp)) {
+ BLI_strncpy(fullname, tmp, maxlen);
+ }
+ }
+#else
+ /* Other OS's - Try TMP and TMPDIR */
+ if (fullname[0] == '\0') {
+ const char *tmp = getenv("TMP");
+ if (tmp && BLI_is_dir(tmp)) {
+ BLI_strncpy(fullname, tmp, maxlen);
+ }
+ }
+
+ if (fullname[0] == '\0') {
+ const char *tmp = getenv("TMPDIR");
+ if (tmp && BLI_is_dir(tmp)) {
+ BLI_strncpy(fullname, tmp, maxlen);
+ }
+ }
+#endif
+
+ if (fullname[0] == '\0') {
+ BLI_strncpy(fullname, "/tmp/", maxlen);
+ }
+ else {
+ /* add a trailing slash if needed */
+ BLI_add_slash(fullname);
+#ifdef WIN32
+ if (userdir && userdir != fullname) {
+ BLI_strncpy(userdir, fullname, maxlen); /* also set user pref to show %TEMP%. /tmp/ is just plain confusing for Windows users. */
+ }
+#endif
+ }
+
+ /* Now that we have a valid temp dir, add system-generated unique sub-dir. */
+ if (basename) {
+ /* 'XXXXXX' is kind of tag to be replaced by mktemp-familly by an uuid. */
+ char *tmp_name = BLI_strdupcat(fullname, "blender_XXXXXX");
+ const size_t ln = strlen(tmp_name) + 1;
+ if (ln <= maxlen) {
+#ifdef WIN32
+ if (_mktemp_s(tmp_name, ln) == 0) {
+ BLI_dir_create_recursive(tmp_name);
+ }
+#else
+ mkdtemp(tmp_name);
+#endif
+ }
+ if (BLI_is_dir(tmp_name)) {
+ BLI_strncpy(basename, fullname, maxlen);
+ BLI_strncpy(fullname, tmp_name, maxlen);
+ BLI_add_slash(fullname);
+ }
+ else {
+ printf("Warning! Could not generate a temp file name for '%s', falling back to '%s'\n", tmp_name, fullname);
+ }
+
+ MEM_freeN(tmp_name);
+ }
+}
+
+/**
+ * Sets btempdir_base to userdir if specified and is a valid directory, otherwise
+ * chooses a suitable OS-specific temporary directory.
+ * Sets btempdir_session to a mkdtemp-generated sub-dir of btempdir_base.
+ *
+ * \note On Window userdir will be set to the temporary directory!
+ */
+void BKE_tempdir_init(char *userdir)
+{
+ where_is_temp(btempdir_session, btempdir_base, FILE_MAX, userdir);
+;
+}
+
+/**
+ * Path to temporary directory (with trailing slash)
+ */
+const char *BKE_tempdir_session(void)
+{
+ return btempdir_session[0] ? btempdir_session : BKE_tempdir_base();
+}
+
+/**
+ * Path to persistent temporary directory (with trailing slash)
+ */
+const char *BKE_tempdir_base(void)
+{
+ return btempdir_base;
+}
+
+/**
+ * Path to the system temporary directory (with trailing slash)
+ */
+void BKE_tempdir_system_init(char *dir)
+{
+ where_is_temp(dir, NULL, FILE_MAX, NULL);
+}
+
+/**
+ * Delete content of this instance's temp dir.
+ */
+void BKE_tempdir_session_purge(void)
+{
+ if (btempdir_session[0] && BLI_is_dir(btempdir_session)) {
+ BLI_delete(btempdir_session, true, true);
+ }
+}
diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c
index bb05b5de8a6..6afe7f1abe9 100644
--- a/source/blender/blenkernel/intern/armature.c
+++ b/source/blender/blenkernel/intern/armature.c
@@ -127,7 +127,7 @@ void BKE_armature_free(bArmature *arm)
/* free animation data */
if (arm->adt) {
- BKE_free_animdata(&arm->id);
+ BKE_animdata_free(&arm->id);
arm->adt = NULL;
}
}
@@ -222,6 +222,10 @@ bArmature *BKE_armature_copy(bArmature *arm)
newArm->act_edbone = NULL;
newArm->sketch = NULL;
+ if (arm->id.lib) {
+ BKE_id_lib_local_paths(G.main, arm->id.lib, &newArm->id);
+ }
+
return newArm;
}
@@ -229,7 +233,7 @@ static Bone *get_named_bone_bonechildren(Bone *bone, const char *name)
{
Bone *curBone, *rbone;
- if (!strcmp(bone->name, name))
+ if (STREQ(bone->name, name))
return bone;
for (curBone = bone->childbase.first; curBone; curBone = curBone->next) {
@@ -259,6 +263,19 @@ Bone *BKE_armature_find_bone_name(bArmature *arm, const char *name)
return bone;
}
+bool BKE_armature_bone_flag_test_recursive(const Bone *bone, int flag)
+{
+ if (bone->flag & flag) {
+ return true;
+ }
+ else if (bone->parent) {
+ return BKE_armature_bone_flag_test_recursive(bone->parent, flag);
+ }
+ else {
+ return false;
+ }
+}
+
/* Finds the best possible extension to the name on a particular axis. (For renaming, check for
* unique names afterwards) strip_number: removes number extensions (TODO: not used)
* axis: the axis to name on
@@ -840,7 +857,7 @@ void armature_deform_verts(Object *armOb, Object *target, DerivedMesh *dm, float
/* bone defmats are already in the channels, chan_mat */
/* initialize B_bone matrices and dual quaternions */
- totchan = BLI_countlist(&armOb->pose->chanbase);
+ totchan = BLI_listbase_count(&armOb->pose->chanbase);
if (use_quaternion) {
dualquats = MEM_callocN(sizeof(DualQuat) * totchan, "dualquats");
@@ -866,7 +883,7 @@ void armature_deform_verts(Object *armOb, Object *target, DerivedMesh *dm, float
armature_def_nr = defgroup_name_index(target, defgrp_name);
if (ELEM(target->type, OB_MESH, OB_LATTICE)) {
- defbase_tot = BLI_countlist(&target->defbase);
+ defbase_tot = BLI_listbase_count(&target->defbase);
if (target->type == OB_MESH) {
Mesh *me = target->data;
@@ -1124,8 +1141,7 @@ void BKE_armature_loc_world_to_pose(Object *ob, const float inloc[3], float outl
* Not exported, as it is only used in this file currently... */
static void get_offset_bone_mat(Bone *bone, float offs_bone[4][4])
{
- if (!bone->parent)
- return;
+ BLI_assert(bone->parent != NULL);
/* Bone transform itself. */
copy_m4_m3(offs_bone, bone->bone_mat);
@@ -1489,6 +1505,8 @@ void vec_roll_to_mat3_normalized(const float nor[3], const float roll, float mat
float theta;
float rMatrix[3][3], bMatrix[3][3];
+ BLI_ASSERT_UNIT_V3(nor);
+
theta = 1.0f + nor[1];
/* With old algo, 1.0e-13f caused T23954 and T31333, 1.0e-6f caused T27675 and T30438,
@@ -1549,16 +1567,15 @@ void vec_roll_to_mat3(const float vec[3], const float roll, float mat[3][3])
/* recursive part, calculates restposition of entire tree of children */
/* used by exiting editmode too */
-void BKE_armature_where_is_bone(Bone *bone, Bone *prevbone)
+void BKE_armature_where_is_bone(Bone *bone, Bone *prevbone, const bool use_recursion)
{
float vec[3];
/* Bone Space */
sub_v3_v3v3(vec, bone->tail, bone->head);
+ bone->length = len_v3(vec);
vec_roll_to_mat3(vec, bone->roll, bone->bone_mat);
- bone->length = len_v3v3(bone->head, bone->tail);
-
/* this is called on old file reading too... */
if (bone->xwidth == 0.0f) {
bone->xwidth = 0.1f;
@@ -1580,9 +1597,11 @@ void BKE_armature_where_is_bone(Bone *bone, Bone *prevbone)
}
/* and the kiddies */
- prevbone = bone;
- for (bone = bone->childbase.first; bone; bone = bone->next) {
- BKE_armature_where_is_bone(bone, prevbone);
+ if (use_recursion) {
+ prevbone = bone;
+ for (bone = bone->childbase.first; bone; bone = bone->next) {
+ BKE_armature_where_is_bone(bone, prevbone, use_recursion);
+ }
}
}
@@ -1594,7 +1613,7 @@ void BKE_armature_where_is(bArmature *arm)
/* hierarchical from root to children */
for (bone = arm->bonebase.first; bone; bone = bone->next) {
- BKE_armature_where_is_bone(bone, NULL);
+ BKE_armature_where_is_bone(bone, NULL, true);
}
}
@@ -1654,6 +1673,7 @@ static void pose_proxy_synchronize(Object *ob, Object *from, int layer_protected
pchanw.next = pchan->next;
pchanw.parent = pchan->parent;
pchanw.child = pchan->child;
+ pchanw.custom_tx = pchan->custom_tx;
pchanw.mpath = pchan->mpath;
pchan->mpath = NULL;
@@ -1662,7 +1682,7 @@ static void pose_proxy_synchronize(Object *ob, Object *from, int layer_protected
if (pchanw.prop) {
pchanw.prop = IDP_CopyProperty(pchanw.prop);
- /* use the values from the the existing props */
+ /* use the values from the existing props */
if (pchan->prop) {
IDP_SyncGroupValues(pchanw.prop, pchan->prop);
}
@@ -1682,7 +1702,7 @@ static void pose_proxy_synchronize(Object *ob, Object *from, int layer_protected
/* constraints - set target ob pointer to own object */
for (con = pchanw.constraints.first; con; con = con->next) {
- bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
+ const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
ListBase targets = {NULL, NULL};
bConstraintTarget *ct;
@@ -1807,9 +1827,12 @@ void BKE_pose_rebuild(Object *ob, bArmature *arm)
BKE_pose_update_constraint_flags(ob->pose); /* for IK detection for example */
+#ifdef WITH_LEGACY_DEPSGRAPH
/* the sorting */
+ /* Sorting for new dependnecy graph is done on the scene graph level. */
if (counter > 1)
DAG_pose_sort(ob);
+#endif
ob->pose->flag &= ~POSE_RECALC;
ob->pose->flag |= POSE_WAS_REBUILT;
@@ -1817,443 +1840,6 @@ void BKE_pose_rebuild(Object *ob, bArmature *arm)
BKE_pose_channels_hash_make(ob->pose);
}
-
-/* ********************** SPLINE IK SOLVER ******************* */
-
-/* Temporary evaluation tree data used for Spline IK */
-typedef struct tSplineIK_Tree {
- struct tSplineIK_Tree *next, *prev;
-
- int type; /* type of IK that this serves (CONSTRAINT_TYPE_KINEMATIC or ..._SPLINEIK) */
-
- bool free_points; /* free the point positions array */
- short chainlen; /* number of bones in the chain */
-
- float *points; /* parametric positions for the joints along the curve */
- bPoseChannel **chain; /* chain of bones to affect using Spline IK (ordered from the tip) */
-
- bPoseChannel *root; /* bone that is the root node of the chain */
-
- bConstraint *con; /* constraint for this chain */
- bSplineIKConstraint *ikData; /* constraint settings for this chain */
-} tSplineIK_Tree;
-
-/* ----------- */
-
-/* Tag the bones in the chain formed by the given bone for IK */
-static void splineik_init_tree_from_pchan(Scene *scene, Object *UNUSED(ob), bPoseChannel *pchan_tip)
-{
- bPoseChannel *pchan, *pchanRoot = NULL;
- bPoseChannel *pchanChain[255];
- bConstraint *con = NULL;
- bSplineIKConstraint *ikData = NULL;
- float boneLengths[255], *jointPoints;
- float totLength = 0.0f;
- bool free_joints = 0;
- int segcount = 0;
-
- /* find the SplineIK constraint */
- for (con = pchan_tip->constraints.first; con; con = con->next) {
- if (con->type == CONSTRAINT_TYPE_SPLINEIK) {
- ikData = con->data;
-
- /* target can only be curve */
- if ((ikData->tar == NULL) || (ikData->tar->type != OB_CURVE))
- continue;
- /* skip if disabled */
- if ((con->enforce == 0.0f) || (con->flag & (CONSTRAINT_DISABLE | CONSTRAINT_OFF)))
- continue;
-
- /* otherwise, constraint is ok... */
- break;
- }
- }
- if (con == NULL)
- return;
-
- /* make sure that the constraint targets are ok
- * - this is a workaround for a depsgraph bug...
- */
- if (ikData->tar) {
- /* note: when creating constraints that follow path, the curve gets the CU_PATH set now,
- * currently for paths to work it needs to go through the bevlist/displist system (ton)
- */
-
- /* only happens on reload file, but violates depsgraph still... fix! */
- if (ELEM(NULL, ikData->tar->curve_cache, ikData->tar->curve_cache->path, ikData->tar->curve_cache->path->data)) {
- BKE_displist_make_curveTypes(scene, ikData->tar, 0);
-
- /* path building may fail in EditMode after removing verts [#33268]*/
- if (ELEM(NULL, ikData->tar->curve_cache->path, ikData->tar->curve_cache->path->data)) {
- /* BLI_assert(cu->path != NULL); */
- return;
- }
- }
- }
-
- /* find the root bone and the chain of bones from the root to the tip
- * NOTE: this assumes that the bones are connected, but that may not be true... */
- for (pchan = pchan_tip; pchan && (segcount < ikData->chainlen); pchan = pchan->parent, segcount++) {
- /* store this segment in the chain */
- pchanChain[segcount] = pchan;
-
- /* if performing rebinding, calculate the length of the bone */
- boneLengths[segcount] = pchan->bone->length;
- totLength += boneLengths[segcount];
- }
-
- if (segcount == 0)
- return;
- else
- pchanRoot = pchanChain[segcount - 1];
-
- /* perform binding step if required */
- if ((ikData->flag & CONSTRAINT_SPLINEIK_BOUND) == 0) {
- float segmentLen = (1.0f / (float)segcount);
- int i;
-
- /* setup new empty array for the points list */
- if (ikData->points)
- MEM_freeN(ikData->points);
- ikData->numpoints = ikData->chainlen + 1;
- ikData->points = MEM_callocN(sizeof(float) * ikData->numpoints, "Spline IK Binding");
-
- /* bind 'tip' of chain (i.e. first joint = tip of bone with the Spline IK Constraint) */
- ikData->points[0] = 1.0f;
-
- /* perform binding of the joints to parametric positions along the curve based
- * proportion of the total length that each bone occupies
- */
- for (i = 0; i < segcount; i++) {
- /* 'head' joints, traveling towards the root of the chain
- * - 2 methods; the one chosen depends on whether we've got usable lengths
- */
- if ((ikData->flag & CONSTRAINT_SPLINEIK_EVENSPLITS) || (totLength == 0.0f)) {
- /* 1) equi-spaced joints */
- ikData->points[i + 1] = ikData->points[i] - segmentLen;
- }
- else {
- /* 2) to find this point on the curve, we take a step from the previous joint
- * a distance given by the proportion that this bone takes
- */
- ikData->points[i + 1] = ikData->points[i] - (boneLengths[i] / totLength);
- }
- }
-
- /* spline has now been bound */
- ikData->flag |= CONSTRAINT_SPLINEIK_BOUND;
- }
-
- /* apply corrections for sensitivity to scaling on a copy of the bind points,
- * since it's easier to determine the positions of all the joints beforehand this way
- */
- if ((ikData->flag & CONSTRAINT_SPLINEIK_SCALE_LIMITED) && (totLength != 0.0f)) {
- float splineLen, maxScale;
- int i;
-
- /* make a copy of the points array, that we'll store in the tree
- * - although we could just multiply the points on the fly, this approach means that
- * we can introduce per-segment stretchiness later if it is necessary
- */
- jointPoints = MEM_dupallocN(ikData->points);
- free_joints = 1;
-
- /* get the current length of the curve */
- /* NOTE: this is assumed to be correct even after the curve was resized */
- splineLen = ikData->tar->curve_cache->path->totdist;
-
- /* calculate the scale factor to multiply all the path values by so that the
- * bone chain retains its current length, such that
- * maxScale * splineLen = totLength
- */
- maxScale = totLength / splineLen;
-
- /* apply scaling correction to all of the temporary points */
- /* TODO: this is really not adequate enough on really short chains */
- for (i = 0; i < segcount; i++)
- jointPoints[i] *= maxScale;
- }
- else {
- /* just use the existing points array */
- jointPoints = ikData->points;
- free_joints = 0;
- }
-
- /* make a new Spline-IK chain, and store it in the IK chains */
- /* TODO: we should check if there is already an IK chain on this, since that would take presidence... */
- {
- /* make new tree */
- tSplineIK_Tree *tree = MEM_callocN(sizeof(tSplineIK_Tree), "SplineIK Tree");
- tree->type = CONSTRAINT_TYPE_SPLINEIK;
-
- tree->chainlen = segcount;
-
- /* copy over the array of links to bones in the chain (from tip to root) */
- tree->chain = MEM_callocN(sizeof(bPoseChannel *) * segcount, "SplineIK Chain");
- memcpy(tree->chain, pchanChain, sizeof(bPoseChannel *) * segcount);
-
- /* store reference to joint position array */
- tree->points = jointPoints;
- tree->free_points = free_joints;
-
- /* store references to different parts of the chain */
- tree->root = pchanRoot;
- tree->con = con;
- tree->ikData = ikData;
-
- /* AND! link the tree to the root */
- BLI_addtail(&pchanRoot->siktree, tree);
- }
-
- /* mark root channel having an IK tree */
- pchanRoot->flag |= POSE_IKSPLINE;
-}
-
-/* Tag which bones are members of Spline IK chains */
-static void splineik_init_tree(Scene *scene, Object *ob, float UNUSED(ctime))
-{
- bPoseChannel *pchan;
-
- /* find the tips of Spline IK chains, which are simply the bones which have been tagged as such */
- for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
- if (pchan->constflag & PCHAN_HAS_SPLINEIK)
- splineik_init_tree_from_pchan(scene, ob, pchan);
- }
-}
-
-/* ----------- */
-
-/* Evaluate spline IK for a given bone */
-static void splineik_evaluate_bone(tSplineIK_Tree *tree, Scene *scene, Object *ob, bPoseChannel *pchan,
- int index, float ctime)
-{
- bSplineIKConstraint *ikData = tree->ikData;
- float poseHead[3], poseTail[3], poseMat[4][4];
- float splineVec[3], scaleFac, radius = 1.0f;
-
- /* firstly, calculate the bone matrix the standard way, since this is needed for roll control */
- BKE_pose_where_is_bone(scene, ob, pchan, ctime, 1);
-
- copy_v3_v3(poseHead, pchan->pose_head);
- copy_v3_v3(poseTail, pchan->pose_tail);
-
- /* step 1: determine the positions for the endpoints of the bone */
- {
- float vec[4], dir[3], rad;
- float tailBlendFac = 1.0f;
-
- /* determine if the bone should still be affected by SplineIK */
- if (tree->points[index + 1] >= 1.0f) {
- /* spline doesn't affect the bone anymore, so done... */
- pchan->flag |= POSE_DONE;
- return;
- }
- else if ((tree->points[index] >= 1.0f) && (tree->points[index + 1] < 1.0f)) {
- /* blending factor depends on the amount of the bone still left on the chain */
- tailBlendFac = (1.0f - tree->points[index + 1]) / (tree->points[index] - tree->points[index + 1]);
- }
-
- /* tail endpoint */
- if (where_on_path(ikData->tar, tree->points[index], vec, dir, NULL, &rad, NULL)) {
- /* apply curve's object-mode transforms to the position
- * unless the option to allow curve to be positioned elsewhere is activated (i.e. no root)
- */
- if ((ikData->flag & CONSTRAINT_SPLINEIK_NO_ROOT) == 0)
- mul_m4_v3(ikData->tar->obmat, vec);
-
- /* convert the position to pose-space, then store it */
- mul_m4_v3(ob->imat, vec);
- interp_v3_v3v3(poseTail, pchan->pose_tail, vec, tailBlendFac);
-
- /* set the new radius */
- radius = rad;
- }
-
- /* head endpoint */
- if (where_on_path(ikData->tar, tree->points[index + 1], vec, dir, NULL, &rad, NULL)) {
- /* apply curve's object-mode transforms to the position
- * unless the option to allow curve to be positioned elsewhere is activated (i.e. no root)
- */
- if ((ikData->flag & CONSTRAINT_SPLINEIK_NO_ROOT) == 0)
- mul_m4_v3(ikData->tar->obmat, vec);
-
- /* store the position, and convert it to pose space */
- mul_m4_v3(ob->imat, vec);
- copy_v3_v3(poseHead, vec);
-
- /* set the new radius (it should be the average value) */
- radius = (radius + rad) / 2;
- }
- }
-
- /* step 2: determine the implied transform from these endpoints
- * - splineVec: the vector direction that the spline applies on the bone
- * - scaleFac: the factor that the bone length is scaled by to get the desired amount
- */
- sub_v3_v3v3(splineVec, poseTail, poseHead);
- scaleFac = len_v3(splineVec) / pchan->bone->length;
-
- /* step 3: compute the shortest rotation needed to map from the bone rotation to the current axis
- * - this uses the same method as is used for the Damped Track Constraint (see the code there for details)
- */
- {
- float dmat[3][3], rmat[3][3], tmat[3][3];
- float raxis[3], rangle;
-
- /* compute the raw rotation matrix from the bone's current matrix by extracting only the
- * orientation-relevant axes, and normalizing them
- */
- copy_v3_v3(rmat[0], pchan->pose_mat[0]);
- copy_v3_v3(rmat[1], pchan->pose_mat[1]);
- copy_v3_v3(rmat[2], pchan->pose_mat[2]);
- normalize_m3(rmat);
-
- /* also, normalize the orientation imposed by the bone, now that we've extracted the scale factor */
- normalize_v3(splineVec);
-
- /* calculate smallest axis-angle rotation necessary for getting from the
- * current orientation of the bone, to the spline-imposed direction
- */
- cross_v3_v3v3(raxis, rmat[1], splineVec);
-
- rangle = dot_v3v3(rmat[1], splineVec);
- CLAMP(rangle, -1.0f, 1.0f);
- rangle = acosf(rangle);
-
- /* multiply the magnitude of the angle by the influence of the constraint to
- * control the influence of the SplineIK effect
- */
- rangle *= tree->con->enforce;
-
- /* construct rotation matrix from the axis-angle rotation found above
- * - this call takes care to make sure that the axis provided is a unit vector first
- */
- axis_angle_to_mat3(dmat, raxis, rangle);
-
- /* combine these rotations so that the y-axis of the bone is now aligned as the spline dictates,
- * while still maintaining roll control from the existing bone animation
- */
- mul_m3_m3m3(tmat, dmat, rmat); /* m1, m3, m2 */
- normalize_m3(tmat); /* attempt to reduce shearing, though I doubt this'll really help too much now... */
- copy_m4_m3(poseMat, tmat);
- }
-
- /* step 4: set the scaling factors for the axes */
- {
- /* only multiply the y-axis by the scaling factor to get nice volume-preservation */
- mul_v3_fl(poseMat[1], scaleFac);
-
- /* set the scaling factors of the x and z axes from... */
- switch (ikData->xzScaleMode) {
- case CONSTRAINT_SPLINEIK_XZS_ORIGINAL:
- {
- /* original scales get used */
- float scale;
-
- /* x-axis scale */
- scale = len_v3(pchan->pose_mat[0]);
- mul_v3_fl(poseMat[0], scale);
- /* z-axis scale */
- scale = len_v3(pchan->pose_mat[2]);
- mul_v3_fl(poseMat[2], scale);
- break;
- }
- case CONSTRAINT_SPLINEIK_XZS_VOLUMETRIC:
- {
- /* 'volume preservation' */
- float scale;
-
- /* calculate volume preservation factor which is
- * basically the inverse of the y-scaling factor
- */
- if (fabsf(scaleFac) != 0.0f) {
- scale = 1.0f / fabsf(scaleFac);
-
- /* we need to clamp this within sensible values */
- /* NOTE: these should be fine for now, but should get sanitised in future */
- CLAMP(scale, 0.0001f, 100000.0f);
- }
- else
- scale = 1.0f;
-
- /* apply the scaling */
- mul_v3_fl(poseMat[0], scale);
- mul_v3_fl(poseMat[2], scale);
- break;
- }
- }
-
- /* finally, multiply the x and z scaling by the radius of the curve too,
- * to allow automatic scales to get tweaked still
- */
- if ((ikData->flag & CONSTRAINT_SPLINEIK_NO_CURVERAD) == 0) {
- mul_v3_fl(poseMat[0], radius);
- mul_v3_fl(poseMat[2], radius);
- }
- }
-
- /* step 5: set the location of the bone in the matrix */
- if (ikData->flag & CONSTRAINT_SPLINEIK_NO_ROOT) {
- /* when the 'no-root' option is affected, the chain can retain
- * the shape but be moved elsewhere
- */
- copy_v3_v3(poseHead, pchan->pose_head);
- }
- else if (tree->con->enforce < 1.0f) {
- /* when the influence is too low
- * - blend the positions for the 'root' bone
- * - stick to the parent for any other
- */
- if (pchan->parent) {
- copy_v3_v3(poseHead, pchan->pose_head);
- }
- else {
- /* FIXME: this introduces popping artifacts when we reach 0.0 */
- interp_v3_v3v3(poseHead, pchan->pose_head, poseHead, tree->con->enforce);
- }
- }
- copy_v3_v3(poseMat[3], poseHead);
-
- /* finally, store the new transform */
- copy_m4_m4(pchan->pose_mat, poseMat);
- copy_v3_v3(pchan->pose_head, poseHead);
-
- /* recalculate tail, as it's now outdated after the head gets adjusted above! */
- BKE_pose_where_is_bone_tail(pchan);
-
- /* done! */
- pchan->flag |= POSE_DONE;
-}
-
-/* Evaluate the chain starting from the nominated bone */
-static void splineik_execute_tree(Scene *scene, Object *ob, bPoseChannel *pchan_root, float ctime)
-{
- tSplineIK_Tree *tree;
-
- /* for each pose-tree, execute it if it is spline, otherwise just free it */
- while ((tree = pchan_root->siktree.first) != NULL) {
- int i;
-
- /* walk over each bone in the chain, calculating the effects of spline IK
- * - the chain is traversed in the opposite order to storage order (i.e. parent to children)
- * so that dependencies are correct
- */
- for (i = tree->chainlen - 1; i >= 0; i--) {
- bPoseChannel *pchan = tree->chain[i];
- splineik_evaluate_bone(tree, scene, ob, pchan, i, ctime);
- }
-
- /* free the tree info specific to SplineIK trees now */
- if (tree->chain)
- MEM_freeN(tree->chain);
- if (tree->free_points)
- MEM_freeN(tree->points);
-
- /* free this tree */
- BLI_freelinkN(&pchan_root->siktree, tree);
- }
-}
-
/* ********************** THE POSE SOLVER ******************* */
/* loc/rot/size to given mat4 */
@@ -2361,7 +1947,7 @@ static void do_strip_modifiers(Scene *scene, Object *armob, Bone *bone, bPoseCha
/* validate first */
if (amod->ob && amod->ob->type == OB_CURVE && amod->channel[0]) {
- if (strcmp(pchan->name, amod->channel) == 0) {
+ if (STREQ(pchan->name, amod->channel)) {
float mat4[4][4], mat3[3][3];
curve_deform_vector(scene, amod->ob, armob, bone->arm_mat[3], pchan->pose_mat[3], mat3, amod->no_rot_axis);
@@ -2374,7 +1960,7 @@ static void do_strip_modifiers(Scene *scene, Object *armob, Bone *bone, bPoseCha
break;
case ACTSTRIP_MOD_NOISE:
{
- if (strcmp(pchan->name, amod->channel) == 0) {
+ if (STREQ(pchan->name, amod->channel)) {
float nor[3], loc[3], ofs;
float eul[3], size[3], eulo[3], sizeo[3];
@@ -2554,7 +2140,7 @@ void BKE_pose_where_is(Scene *scene, Object *ob)
* - this is not integrated as an IK plugin, since it should be able
* to function in conjunction with standard IK
*/
- splineik_init_tree(scene, ob, ctime);
+ BKE_pose_splineik_init_tree(scene, ob, ctime);
/* 3. the main loop, channels are already hierarchical sorted from root to children */
for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
@@ -2564,7 +2150,7 @@ void BKE_pose_where_is(Scene *scene, Object *ob)
}
/* 4b. if we find a Spline IK root, we handle it separated too */
else if (pchan->flag & POSE_IKSPLINE) {
- splineik_execute_tree(scene, ob, pchan, ctime);
+ BKE_splineik_execute_tree(scene, ob, pchan, ctime);
}
/* 5. otherwise just call the normal solver */
else if (!(pchan->flag & POSE_DONE)) {
@@ -2598,39 +2184,110 @@ static int minmax_armature(Object *ob, float r_min[3], float r_max[3])
return (BLI_listbase_is_empty(&ob->pose->chanbase) == false);
}
-static void boundbox_armature(Object *ob, float loc[3], float size[3])
+static void boundbox_armature(Object *ob)
{
BoundBox *bb;
float min[3], max[3];
- float mloc[3], msize[3];
if (ob->bb == NULL)
- ob->bb = MEM_callocN(sizeof(BoundBox), "Armature boundbox");
+ ob->bb = MEM_mallocN(sizeof(BoundBox), "Armature boundbox");
bb = ob->bb;
- if (!loc)
- loc = mloc;
- if (!size)
- size = msize;
-
INIT_MINMAX(min, max);
if (!minmax_armature(ob, min, max)) {
min[0] = min[1] = min[2] = -1.0f;
max[0] = max[1] = max[2] = 1.0f;
}
- 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;
-
BKE_boundbox_init_from_minmax(bb, min, max);
}
BoundBox *BKE_armature_boundbox_get(Object *ob)
{
- boundbox_armature(ob, NULL, NULL);
+ boundbox_armature(ob);
return ob->bb;
}
+
+bool BKE_pose_minmax(Object *ob, float r_min[3], float r_max[3], bool use_hidden, bool use_select)
+{
+ bool changed = false;
+
+ if (ob->pose) {
+ bArmature *arm = ob->data;
+ bPoseChannel *pchan;
+
+ for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
+ /* XXX pchan->bone may be NULL for duplicated bones, see duplicateEditBoneObjects() comment
+ * (editarmature.c:2592)... Skip in this case too! */
+ if (pchan->bone &&
+ (!((use_hidden == false) && (PBONE_VISIBLE(arm, pchan->bone) == false)) &&
+ !((use_select == true) && ((pchan->bone->flag & BONE_SELECTED) == 0))))
+ {
+ bPoseChannel *pchan_tx = (pchan->custom && pchan->custom_tx) ? pchan->custom_tx : pchan;
+ BoundBox *bb_custom = ((pchan->custom) && !(arm->flag & ARM_NO_CUSTOM)) ?
+ BKE_object_boundbox_get(pchan->custom) : NULL;
+ if (bb_custom) {
+ float mat[4][4], smat[4][4];
+ scale_m4_fl(smat, PCHAN_CUSTOM_DRAW_SIZE(pchan));
+ mul_m4_series(mat, ob->obmat, pchan_tx->pose_mat, smat);
+ BKE_boundbox_minmax(bb_custom, mat, r_min, r_max);
+ }
+ else {
+ float vec[3];
+ mul_v3_m4v3(vec, ob->obmat, pchan_tx->pose_head);
+ minmax_v3v3_v3(r_min, r_max, vec);
+ mul_v3_m4v3(vec, ob->obmat, pchan_tx->pose_tail);
+ minmax_v3v3_v3(r_min, r_max, vec);
+ }
+
+ changed = true;
+ }
+ }
+ }
+
+ return changed;
+}
+
+/************** Graph evaluation ********************/
+
+bPoseChannel *BKE_armature_ik_solver_find_root(
+ bPoseChannel *pchan,
+ bKinematicConstraint *data)
+{
+ bPoseChannel *rootchan = pchan;
+ if (!(data->flag & CONSTRAINT_IK_TIP)) {
+ /* Exclude tip from chain. */
+ rootchan = rootchan->parent;
+ }
+ if (rootchan != NULL) {
+ int segcount = 0;
+ while (rootchan->parent) {
+ /* Continue up chain, until we reach target number of items. */
+ segcount++;
+ if (segcount == data->rootbone) {
+ break;
+ }
+ rootchan = rootchan->parent;
+ }
+ }
+ return rootchan;
+}
+
+bPoseChannel *BKE_armature_splineik_solver_find_root(
+ bPoseChannel *pchan,
+ bSplineIKConstraint *data)
+{
+ bPoseChannel *rootchan = pchan;
+ int segcount = 0;
+ BLI_assert(rootchan != NULL);
+ while (rootchan->parent) {
+ /* Continue up chain, until we reach target number of items. */
+ segcount++;
+ if (segcount == data->chainlen) {
+ break;
+ }
+ rootchan = rootchan->parent;
+ }
+ return rootchan;
+}
diff --git a/source/blender/blenkernel/intern/armature_update.c b/source/blender/blenkernel/intern/armature_update.c
new file mode 100644
index 00000000000..ceda9f056bb
--- /dev/null
+++ b/source/blender/blenkernel/intern/armature_update.c
@@ -0,0 +1,697 @@
+/*
+ * ***** 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) 2015 Blender Foundation.
+ * All rights reserved.
+ *
+ * Original Author: Joshua Leung
+ * Contributor(s): None Yet
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ *
+ * Defines and code for core node types
+ */
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_utildefines.h"
+#include "BLI_listbase.h"
+#include "BLI_math.h"
+
+#include "DNA_armature_types.h"
+#include "DNA_constraint_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+
+#include "BKE_action.h"
+#include "BKE_anim.h"
+#include "BKE_armature.h"
+#include "BKE_curve.h"
+#include "BKE_depsgraph.h"
+#include "BKE_displist.h"
+#include "BKE_fcurve.h"
+#include "BKE_scene.h"
+
+#include "BIK_api.h"
+
+#include "BKE_global.h"
+#include "BKE_main.h"
+
+#include "DEG_depsgraph.h"
+
+#ifdef WITH_LEGACY_DEPSGRAPH
+# define DEBUG_PRINT if (!DEG_depsgraph_use_legacy() && G.debug & G_DEBUG_DEPSGRAPH) printf
+#else
+# define DEBUG_PRINT if (G.debug & G_DEBUG_DEPSGRAPH) printf
+#endif
+
+/* ********************** SPLINE IK SOLVER ******************* */
+
+/* Temporary evaluation tree data used for Spline IK */
+typedef struct tSplineIK_Tree {
+ struct tSplineIK_Tree *next, *prev;
+
+ int type; /* type of IK that this serves (CONSTRAINT_TYPE_KINEMATIC or ..._SPLINEIK) */
+
+ bool free_points; /* free the point positions array */
+ short chainlen; /* number of bones in the chain */
+
+ float *points; /* parametric positions for the joints along the curve */
+ bPoseChannel **chain; /* chain of bones to affect using Spline IK (ordered from the tip) */
+
+ bPoseChannel *root; /* bone that is the root node of the chain */
+
+ bConstraint *con; /* constraint for this chain */
+ bSplineIKConstraint *ikData; /* constraint settings for this chain */
+} tSplineIK_Tree;
+
+/* ----------- */
+
+/* Tag the bones in the chain formed by the given bone for IK */
+static void splineik_init_tree_from_pchan(Scene *scene, Object *UNUSED(ob), bPoseChannel *pchan_tip)
+{
+ bPoseChannel *pchan, *pchanRoot = NULL;
+ bPoseChannel *pchanChain[255];
+ bConstraint *con = NULL;
+ bSplineIKConstraint *ikData = NULL;
+ float boneLengths[255], *jointPoints;
+ float totLength = 0.0f;
+ bool free_joints = 0;
+ int segcount = 0;
+
+ /* find the SplineIK constraint */
+ for (con = pchan_tip->constraints.first; con; con = con->next) {
+ if (con->type == CONSTRAINT_TYPE_SPLINEIK) {
+ ikData = con->data;
+
+ /* target can only be curve */
+ if ((ikData->tar == NULL) || (ikData->tar->type != OB_CURVE))
+ continue;
+ /* skip if disabled */
+ if ((con->enforce == 0.0f) || (con->flag & (CONSTRAINT_DISABLE | CONSTRAINT_OFF)))
+ continue;
+
+ /* otherwise, constraint is ok... */
+ break;
+ }
+ }
+ if (con == NULL)
+ return;
+
+ /* make sure that the constraint targets are ok
+ * - this is a workaround for a depsgraph bug...
+ */
+ if (ikData->tar) {
+ /* note: when creating constraints that follow path, the curve gets the CU_PATH set now,
+ * currently for paths to work it needs to go through the bevlist/displist system (ton)
+ */
+
+ /* only happens on reload file, but violates depsgraph still... fix! */
+ if (ELEM(NULL, ikData->tar->curve_cache, ikData->tar->curve_cache->path, ikData->tar->curve_cache->path->data)) {
+ BKE_displist_make_curveTypes(scene, ikData->tar, 0);
+
+ /* path building may fail in EditMode after removing verts [#33268]*/
+ if (ELEM(NULL, ikData->tar->curve_cache->path, ikData->tar->curve_cache->path->data)) {
+ /* BLI_assert(cu->path != NULL); */
+ return;
+ }
+ }
+ }
+
+ /* find the root bone and the chain of bones from the root to the tip
+ * NOTE: this assumes that the bones are connected, but that may not be true... */
+ for (pchan = pchan_tip; pchan && (segcount < ikData->chainlen); pchan = pchan->parent, segcount++) {
+ /* store this segment in the chain */
+ pchanChain[segcount] = pchan;
+
+ /* if performing rebinding, calculate the length of the bone */
+ boneLengths[segcount] = pchan->bone->length;
+ totLength += boneLengths[segcount];
+ }
+
+ if (segcount == 0)
+ return;
+ else
+ pchanRoot = pchanChain[segcount - 1];
+
+ /* perform binding step if required */
+ if ((ikData->flag & CONSTRAINT_SPLINEIK_BOUND) == 0) {
+ float segmentLen = (1.0f / (float)segcount);
+ int i;
+
+ /* setup new empty array for the points list */
+ if (ikData->points)
+ MEM_freeN(ikData->points);
+ ikData->numpoints = ikData->chainlen + 1;
+ ikData->points = MEM_mallocN(sizeof(float) * ikData->numpoints, "Spline IK Binding");
+
+ /* bind 'tip' of chain (i.e. first joint = tip of bone with the Spline IK Constraint) */
+ ikData->points[0] = 1.0f;
+
+ /* perform binding of the joints to parametric positions along the curve based
+ * proportion of the total length that each bone occupies
+ */
+ for (i = 0; i < segcount; i++) {
+ /* 'head' joints, traveling towards the root of the chain
+ * - 2 methods; the one chosen depends on whether we've got usable lengths
+ */
+ if ((ikData->flag & CONSTRAINT_SPLINEIK_EVENSPLITS) || (totLength == 0.0f)) {
+ /* 1) equi-spaced joints */
+ ikData->points[i + 1] = ikData->points[i] - segmentLen;
+ }
+ else {
+ /* 2) to find this point on the curve, we take a step from the previous joint
+ * a distance given by the proportion that this bone takes
+ */
+ ikData->points[i + 1] = ikData->points[i] - (boneLengths[i] / totLength);
+ }
+ }
+
+ /* spline has now been bound */
+ ikData->flag |= CONSTRAINT_SPLINEIK_BOUND;
+ }
+
+ /* disallow negative values (happens with float precision) */
+ CLAMP_MIN(ikData->points[segcount], 0.0f);
+
+ /* apply corrections for sensitivity to scaling on a copy of the bind points,
+ * since it's easier to determine the positions of all the joints beforehand this way
+ */
+ if ((ikData->flag & CONSTRAINT_SPLINEIK_SCALE_LIMITED) && (totLength != 0.0f)) {
+ float splineLen, maxScale;
+ int i;
+
+ /* make a copy of the points array, that we'll store in the tree
+ * - although we could just multiply the points on the fly, this approach means that
+ * we can introduce per-segment stretchiness later if it is necessary
+ */
+ jointPoints = MEM_dupallocN(ikData->points);
+ free_joints = 1;
+
+ /* get the current length of the curve */
+ /* NOTE: this is assumed to be correct even after the curve was resized */
+ splineLen = ikData->tar->curve_cache->path->totdist;
+
+ /* calculate the scale factor to multiply all the path values by so that the
+ * bone chain retains its current length, such that
+ * maxScale * splineLen = totLength
+ */
+ maxScale = totLength / splineLen;
+
+ /* apply scaling correction to all of the temporary points */
+ /* TODO: this is really not adequate enough on really short chains */
+ for (i = 0; i < segcount; i++)
+ jointPoints[i] *= maxScale;
+ }
+ else {
+ /* just use the existing points array */
+ jointPoints = ikData->points;
+ free_joints = 0;
+ }
+
+ /* make a new Spline-IK chain, and store it in the IK chains */
+ /* TODO: we should check if there is already an IK chain on this, since that would take presidence... */
+ {
+ /* make new tree */
+ tSplineIK_Tree *tree = MEM_callocN(sizeof(tSplineIK_Tree), "SplineIK Tree");
+ tree->type = CONSTRAINT_TYPE_SPLINEIK;
+
+ tree->chainlen = segcount;
+
+ /* copy over the array of links to bones in the chain (from tip to root) */
+ tree->chain = MEM_mallocN(sizeof(bPoseChannel *) * segcount, "SplineIK Chain");
+ memcpy(tree->chain, pchanChain, sizeof(bPoseChannel *) * segcount);
+
+ /* store reference to joint position array */
+ tree->points = jointPoints;
+ tree->free_points = free_joints;
+
+ /* store references to different parts of the chain */
+ tree->root = pchanRoot;
+ tree->con = con;
+ tree->ikData = ikData;
+
+ /* AND! link the tree to the root */
+ BLI_addtail(&pchanRoot->siktree, tree);
+ }
+
+ /* mark root channel having an IK tree */
+ pchanRoot->flag |= POSE_IKSPLINE;
+}
+
+/* Tag which bones are members of Spline IK chains */
+static void splineik_init_tree(Scene *scene, Object *ob, float UNUSED(ctime))
+{
+ bPoseChannel *pchan;
+
+ /* find the tips of Spline IK chains, which are simply the bones which have been tagged as such */
+ for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
+ if (pchan->constflag & PCHAN_HAS_SPLINEIK)
+ splineik_init_tree_from_pchan(scene, ob, pchan);
+ }
+}
+
+/* ----------- */
+
+/* Evaluate spline IK for a given bone */
+static void splineik_evaluate_bone(tSplineIK_Tree *tree, Scene *scene, Object *ob, bPoseChannel *pchan,
+ int index, float ctime)
+{
+ bSplineIKConstraint *ikData = tree->ikData;
+ float poseHead[3], poseTail[3], poseMat[4][4];
+ float splineVec[3], scaleFac, radius = 1.0f;
+
+ /* firstly, calculate the bone matrix the standard way, since this is needed for roll control */
+ BKE_pose_where_is_bone(scene, ob, pchan, ctime, 1);
+
+ copy_v3_v3(poseHead, pchan->pose_head);
+ copy_v3_v3(poseTail, pchan->pose_tail);
+
+ /* step 1: determine the positions for the endpoints of the bone */
+ {
+ float vec[4], dir[3], rad;
+ float tailBlendFac = 1.0f;
+
+ /* determine if the bone should still be affected by SplineIK */
+ if (tree->points[index + 1] >= 1.0f) {
+ /* spline doesn't affect the bone anymore, so done... */
+ pchan->flag |= POSE_DONE;
+ return;
+ }
+ else if ((tree->points[index] >= 1.0f) && (tree->points[index + 1] < 1.0f)) {
+ /* blending factor depends on the amount of the bone still left on the chain */
+ tailBlendFac = (1.0f - tree->points[index + 1]) / (tree->points[index] - tree->points[index + 1]);
+ }
+
+ /* tail endpoint */
+ if (where_on_path(ikData->tar, tree->points[index], vec, dir, NULL, &rad, NULL)) {
+ /* apply curve's object-mode transforms to the position
+ * unless the option to allow curve to be positioned elsewhere is activated (i.e. no root)
+ */
+ if ((ikData->flag & CONSTRAINT_SPLINEIK_NO_ROOT) == 0)
+ mul_m4_v3(ikData->tar->obmat, vec);
+
+ /* convert the position to pose-space, then store it */
+ mul_m4_v3(ob->imat, vec);
+ interp_v3_v3v3(poseTail, pchan->pose_tail, vec, tailBlendFac);
+
+ /* set the new radius */
+ radius = rad;
+ }
+
+ /* head endpoint */
+ if (where_on_path(ikData->tar, tree->points[index + 1], vec, dir, NULL, &rad, NULL)) {
+ /* apply curve's object-mode transforms to the position
+ * unless the option to allow curve to be positioned elsewhere is activated (i.e. no root)
+ */
+ if ((ikData->flag & CONSTRAINT_SPLINEIK_NO_ROOT) == 0)
+ mul_m4_v3(ikData->tar->obmat, vec);
+
+ /* store the position, and convert it to pose space */
+ mul_m4_v3(ob->imat, vec);
+ copy_v3_v3(poseHead, vec);
+
+ /* set the new radius (it should be the average value) */
+ radius = (radius + rad) / 2;
+ }
+ }
+
+ /* step 2: determine the implied transform from these endpoints
+ * - splineVec: the vector direction that the spline applies on the bone
+ * - scaleFac: the factor that the bone length is scaled by to get the desired amount
+ */
+ sub_v3_v3v3(splineVec, poseTail, poseHead);
+ scaleFac = len_v3(splineVec) / pchan->bone->length;
+
+ /* step 3: compute the shortest rotation needed to map from the bone rotation to the current axis
+ * - this uses the same method as is used for the Damped Track Constraint (see the code there for details)
+ */
+ {
+ float dmat[3][3], rmat[3][3], tmat[3][3];
+ float raxis[3], rangle;
+
+ /* compute the raw rotation matrix from the bone's current matrix by extracting only the
+ * orientation-relevant axes, and normalizing them
+ */
+ copy_v3_v3(rmat[0], pchan->pose_mat[0]);
+ copy_v3_v3(rmat[1], pchan->pose_mat[1]);
+ copy_v3_v3(rmat[2], pchan->pose_mat[2]);
+ normalize_m3(rmat);
+
+ /* also, normalize the orientation imposed by the bone, now that we've extracted the scale factor */
+ normalize_v3(splineVec);
+
+ /* calculate smallest axis-angle rotation necessary for getting from the
+ * current orientation of the bone, to the spline-imposed direction
+ */
+ cross_v3_v3v3(raxis, rmat[1], splineVec);
+
+ rangle = dot_v3v3(rmat[1], splineVec);
+ CLAMP(rangle, -1.0f, 1.0f);
+ rangle = acosf(rangle);
+
+ /* multiply the magnitude of the angle by the influence of the constraint to
+ * control the influence of the SplineIK effect
+ */
+ rangle *= tree->con->enforce;
+
+ /* construct rotation matrix from the axis-angle rotation found above
+ * - this call takes care to make sure that the axis provided is a unit vector first
+ */
+ axis_angle_to_mat3(dmat, raxis, rangle);
+
+ /* combine these rotations so that the y-axis of the bone is now aligned as the spline dictates,
+ * while still maintaining roll control from the existing bone animation
+ */
+ mul_m3_m3m3(tmat, dmat, rmat); /* m1, m3, m2 */
+ normalize_m3(tmat); /* attempt to reduce shearing, though I doubt this'll really help too much now... */
+ copy_m4_m3(poseMat, tmat);
+ }
+
+ /* step 4: set the scaling factors for the axes */
+ {
+ /* only multiply the y-axis by the scaling factor to get nice volume-preservation */
+ mul_v3_fl(poseMat[1], scaleFac);
+
+ /* set the scaling factors of the x and z axes from... */
+ switch (ikData->xzScaleMode) {
+ case CONSTRAINT_SPLINEIK_XZS_ORIGINAL:
+ {
+ /* original scales get used */
+ float scale;
+
+ /* x-axis scale */
+ scale = len_v3(pchan->pose_mat[0]);
+ mul_v3_fl(poseMat[0], scale);
+ /* z-axis scale */
+ scale = len_v3(pchan->pose_mat[2]);
+ mul_v3_fl(poseMat[2], scale);
+ break;
+ }
+ case CONSTRAINT_SPLINEIK_XZS_INVERSE:
+ {
+ /* old 'volume preservation' method using the inverse scale */
+ float scale;
+
+ /* calculate volume preservation factor which is
+ * basically the inverse of the y-scaling factor
+ */
+ if (fabsf(scaleFac) != 0.0f) {
+ scale = 1.0f / fabsf(scaleFac);
+
+ /* we need to clamp this within sensible values */
+ /* NOTE: these should be fine for now, but should get sanitised in future */
+ CLAMP(scale, 0.0001f, 100000.0f);
+ }
+ else
+ scale = 1.0f;
+
+ /* apply the scaling */
+ mul_v3_fl(poseMat[0], scale);
+ mul_v3_fl(poseMat[2], scale);
+ break;
+ }
+ case CONSTRAINT_SPLINEIK_XZS_VOLUMETRIC:
+ {
+ /* improved volume preservation based on the Stretch To constraint */
+ float final_scale;
+
+ /* as the basis for volume preservation, we use the inverse scale factor... */
+ if (fabsf(scaleFac) != 0.0f) {
+ /* NOTE: The method here is taken wholesale from the Stretch To constraint */
+ float bulge = powf(1.0f / fabsf(scaleFac), ikData->bulge);
+
+ if (bulge > 1.0f) {
+ if (ikData->flag & CONSTRAINT_SPLINEIK_USE_BULGE_MAX) {
+ float bulge_max = max_ff(ikData->bulge_max, 1.0f);
+ float hard = min_ff(bulge, bulge_max);
+
+ float range = bulge_max - 1.0f;
+ float scale = (range > 0.0f) ? 1.0f / range : 0.0f;
+ float soft = 1.0f + range * atanf((bulge - 1.0f) * scale) / (float)M_PI_2;
+
+ bulge = interpf(soft, hard, ikData->bulge_smooth);
+ }
+ }
+ if (bulge < 1.0f) {
+ if (ikData->flag & CONSTRAINT_SPLINEIK_USE_BULGE_MIN) {
+ float bulge_min = CLAMPIS(ikData->bulge_min, 0.0f, 1.0f);
+ float hard = max_ff(bulge, bulge_min);
+
+ float range = 1.0f - bulge_min;
+ float scale = (range > 0.0f) ? 1.0f / range : 0.0f;
+ float soft = 1.0f - range * atanf((1.0f - bulge) * scale) / (float)M_PI_2;
+
+ bulge = interpf(soft, hard, ikData->bulge_smooth);
+ }
+ }
+
+ /* compute scale factor for xz axes from this value */
+ final_scale = sqrtf(bulge);
+ }
+ else {
+ /* no scaling, so scale factor is simple */
+ final_scale = 1.0f;
+ }
+
+ /* apply the scaling (assuming normalised scale) */
+ mul_v3_fl(poseMat[0], final_scale);
+ mul_v3_fl(poseMat[2], final_scale);
+ break;
+ }
+ }
+
+ /* finally, multiply the x and z scaling by the radius of the curve too,
+ * to allow automatic scales to get tweaked still
+ */
+ if ((ikData->flag & CONSTRAINT_SPLINEIK_NO_CURVERAD) == 0) {
+ mul_v3_fl(poseMat[0], radius);
+ mul_v3_fl(poseMat[2], radius);
+ }
+ }
+
+ /* step 5: set the location of the bone in the matrix */
+ if (ikData->flag & CONSTRAINT_SPLINEIK_NO_ROOT) {
+ /* when the 'no-root' option is affected, the chain can retain
+ * the shape but be moved elsewhere
+ */
+ copy_v3_v3(poseHead, pchan->pose_head);
+ }
+ else if (tree->con->enforce < 1.0f) {
+ /* when the influence is too low
+ * - blend the positions for the 'root' bone
+ * - stick to the parent for any other
+ */
+ if (pchan->parent) {
+ copy_v3_v3(poseHead, pchan->pose_head);
+ }
+ else {
+ /* FIXME: this introduces popping artifacts when we reach 0.0 */
+ interp_v3_v3v3(poseHead, pchan->pose_head, poseHead, tree->con->enforce);
+ }
+ }
+ copy_v3_v3(poseMat[3], poseHead);
+
+ /* finally, store the new transform */
+ copy_m4_m4(pchan->pose_mat, poseMat);
+ copy_v3_v3(pchan->pose_head, poseHead);
+
+ /* recalculate tail, as it's now outdated after the head gets adjusted above! */
+ BKE_pose_where_is_bone_tail(pchan);
+
+ /* done! */
+ pchan->flag |= POSE_DONE;
+}
+
+/* Evaluate the chain starting from the nominated bone */
+static void splineik_execute_tree(Scene *scene, Object *ob, bPoseChannel *pchan_root, float ctime)
+{
+ tSplineIK_Tree *tree;
+
+ /* for each pose-tree, execute it if it is spline, otherwise just free it */
+ while ((tree = pchan_root->siktree.first) != NULL) {
+ int i;
+
+ /* walk over each bone in the chain, calculating the effects of spline IK
+ * - the chain is traversed in the opposite order to storage order (i.e. parent to children)
+ * so that dependencies are correct
+ */
+ for (i = tree->chainlen - 1; i >= 0; i--) {
+ bPoseChannel *pchan = tree->chain[i];
+ splineik_evaluate_bone(tree, scene, ob, pchan, i, ctime);
+ }
+
+ /* free the tree info specific to SplineIK trees now */
+ if (tree->chain)
+ MEM_freeN(tree->chain);
+ if (tree->free_points)
+ MEM_freeN(tree->points);
+
+ /* free this tree */
+ BLI_freelinkN(&pchan_root->siktree, tree);
+ }
+}
+
+void BKE_pose_splineik_init_tree(Scene *scene, Object *ob, float ctime)
+{
+ splineik_init_tree(scene, ob, ctime);
+}
+
+void BKE_splineik_execute_tree(Scene *scene, Object *ob, bPoseChannel *pchan_root, float ctime)
+{
+ splineik_execute_tree(scene, ob, pchan_root, ctime);
+}
+
+/* *************** Depsgraph evaluation callbacks ************ */
+
+void BKE_pose_eval_init(EvaluationContext *UNUSED(eval_ctx),
+ Scene *scene,
+ Object *ob,
+ bPose *pose)
+{
+ float ctime = BKE_scene_frame_get(scene); /* not accurate... */
+ bPoseChannel *pchan;
+
+ DEBUG_PRINT("%s on %s\n", __func__, ob->id.name);
+
+ BLI_assert(ob->type == OB_ARMATURE);
+
+ /* We demand having proper pose. */
+ BLI_assert(ob->pose != NULL);
+ BLI_assert((ob->pose->flag & POSE_RECALC) == 0);
+
+ /* imat is needed for solvers. */
+ invert_m4_m4(ob->imat, ob->obmat);
+
+ /* 1. clear flags */
+ for (pchan = pose->chanbase.first; pchan != NULL; pchan = pchan->next) {
+ pchan->flag &= ~(POSE_DONE | POSE_CHAIN | POSE_IKTREE | POSE_IKSPLINE);
+ }
+
+ /* 2a. construct the IK tree (standard IK) */
+ BIK_initialize_tree(scene, ob, ctime);
+
+ /* 2b. construct the Spline IK trees
+ * - this is not integrated as an IK plugin, since it should be able
+ * to function in conjunction with standard IK
+ */
+ BKE_pose_splineik_init_tree(scene, ob, ctime);
+}
+
+void BKE_pose_eval_bone(EvaluationContext *UNUSED(eval_ctx),
+ Scene *scene,
+ Object *ob,
+ bPoseChannel *pchan)
+{
+ bArmature *arm = (bArmature *)ob->data;
+ DEBUG_PRINT("%s on %s pchan %s\n", __func__, ob->id.name, pchan->name);
+ BLI_assert(ob->type == OB_ARMATURE);
+ if (arm->edbo || (arm->flag & ARM_RESTPOS)) {
+ Bone *bone = pchan->bone;
+ if (bone) {
+ copy_m4_m4(pchan->pose_mat, bone->arm_mat);
+ copy_v3_v3(pchan->pose_head, bone->arm_head);
+ copy_v3_v3(pchan->pose_tail, bone->arm_tail);
+ }
+ }
+ else {
+ /* TODO(sergey): Currently if there are constraints full transform is being
+ * evaluated in BKE_pose_constraints_evaluate.
+ */
+ if (pchan->constraints.first == NULL) {
+ if (pchan->flag & POSE_IKTREE || pchan->flag & POSE_IKSPLINE) {
+ /* pass */
+ }
+ else {
+ /* TODO(sergey): Use time source node for time. */
+ float ctime = BKE_scene_frame_get(scene); /* not accurate... */
+ BKE_pose_where_is_bone(scene, ob, pchan, ctime, 1);
+ }
+ }
+ }
+}
+
+void BKE_pose_constraints_evaluate(EvaluationContext *UNUSED(eval_ctx),
+ Object *ob,
+ bPoseChannel *pchan)
+{
+ Scene *scene = G.main->scene.first;
+ DEBUG_PRINT("%s on %s pchan %s\n", __func__, ob->id.name, pchan->name);
+ if (pchan->flag & POSE_IKTREE || pchan->flag & POSE_IKSPLINE) {
+ /* IK are being solved separately/ */
+ }
+ else {
+ float ctime = BKE_scene_frame_get(scene); /* not accurate... */
+ BKE_pose_where_is_bone(scene, ob, pchan, ctime, 1);
+ }
+}
+
+void BKE_pose_bone_done(EvaluationContext *UNUSED(eval_ctx),
+ bPoseChannel *pchan)
+{
+ float imat[4][4];
+ DEBUG_PRINT("%s on pchan %s\n", __func__, pchan->name);
+ if (pchan->bone) {
+ invert_m4_m4(imat, pchan->bone->arm_mat);
+ mul_m4_m4m4(pchan->chan_mat, pchan->pose_mat, imat);
+ }
+}
+
+void BKE_pose_iktree_evaluate(EvaluationContext *UNUSED(eval_ctx),
+ Scene *scene,
+ Object *ob,
+ bPoseChannel *rootchan)
+{
+ float ctime = BKE_scene_frame_get(scene); /* not accurate... */
+ DEBUG_PRINT("%s on %s pchan %s\n", __func__, ob->id.name, rootchan->name);
+ BIK_execute_tree(scene, ob, rootchan, ctime);
+}
+
+void BKE_pose_splineik_evaluate(EvaluationContext *UNUSED(eval_ctx),
+ Scene *scene,
+ Object *ob,
+ bPoseChannel *rootchan)
+{
+ float ctime = BKE_scene_frame_get(scene); /* not accurate... */
+ DEBUG_PRINT("%s on %s pchan %s\n", __func__, ob->id.name, rootchan->name);
+ BKE_splineik_execute_tree(scene, ob, rootchan, ctime);
+}
+
+void BKE_pose_eval_flush(EvaluationContext *UNUSED(eval_ctx),
+ Scene *scene,
+ Object *ob,
+ bPose *UNUSED(pose))
+{
+ float ctime = BKE_scene_frame_get(scene); /* not accurate... */
+ DEBUG_PRINT("%s on %s\n", __func__, ob->id.name);
+ BLI_assert(ob->type == OB_ARMATURE);
+
+ /* 6. release the IK tree */
+ BIK_release_tree(scene, ob, ctime);
+
+ ob->recalc &= ~OB_RECALC_ALL;
+}
+
+void BKE_pose_eval_proxy_copy(EvaluationContext *UNUSED(eval_ctx), Object *ob)
+{
+ BLI_assert(ob->id.lib != NULL && ob->proxy_from != NULL);
+ DEBUG_PRINT("%s on %s\n", __func__, ob->id.name);
+ if (BKE_pose_copy_result(ob->pose, ob->proxy_from->pose) == false) {
+ printf("Proxy copy error, lib Object: %s proxy Object: %s\n",
+ ob->id.name + 2, ob->proxy_from->id.name + 2);
+ }
+}
diff --git a/source/blender/blenkernel/intern/autoexec.c b/source/blender/blenkernel/intern/autoexec.c
index 872780bd50a..d9462cd0262 100644
--- a/source/blender/blenkernel/intern/autoexec.c
+++ b/source/blender/blenkernel/intern/autoexec.c
@@ -34,9 +34,12 @@
#include "BLI_utildefines.h"
#include "BLI_fnmatch.h"
-#include "BLI_string.h"
#include "BLI_path_util.h"
+#ifdef WIN32
+# include "BLI_string.h"
+#endif
+
#include "BKE_autoexec.h" /* own include */
/**
diff --git a/source/blender/blenkernel/intern/blender.c b/source/blender/blenkernel/intern/blender.c
index fff8265a158..9aad3cf564b 100644
--- a/source/blender/blenkernel/intern/blender.c
+++ b/source/blender/blenkernel/intern/blender.c
@@ -61,6 +61,7 @@
#include "IMB_imbuf.h"
#include "IMB_moviecache.h"
+#include "BKE_appdir.h"
#include "BKE_blender.h"
#include "BKE_bpath.h"
#include "BKE_brush.h"
@@ -80,6 +81,7 @@
#include "BKE_sound.h"
#include "RE_pipeline.h"
+#include "RE_render_ext.h"
#include "BLF_api.h"
@@ -119,6 +121,7 @@ void free_blender(void)
DAG_exit();
BKE_brush_system_exit();
+ RE_exit_texture_rng();
BLI_callback_global_finalize();
@@ -143,10 +146,6 @@ void initglobals(void)
else
BLI_snprintf(versionstr, sizeof(versionstr), "v%d.%02d", BLENDER_VERSION / 100, BLENDER_VERSION % 100);
-#ifdef _WIN32
- G.windowstate = 0;
-#endif
-
#ifndef WITH_PYTHON_SECURITY /* default */
G.f |= G_SCRIPT_AUTOEXEC;
#else
@@ -186,6 +185,17 @@ static void clean_paths(Main *main)
}
}
+static bool wm_scene_is_visible(wmWindowManager *wm, Scene *scene)
+{
+ wmWindow *win;
+ for (win = wm->windows.first; win; win = win->next) {
+ if (win->screen->scene == scene) {
+ return true;
+ }
+ }
+ return false;
+}
+
/* context matching */
/* handle no-ui case */
@@ -229,6 +239,20 @@ static void setup_app_data(bContext *C, BlendFileData *bfd, const char *filepath
/* no load screens? */
if (mode != LOAD_UI) {
+ /* Logic for 'track_undo_scene' is to keep using the scene which the active screen has,
+ * as long as the scene associated with the undo operation is visible in one of the open windows.
+ *
+ * - 'curscreen->scene' - scene the user is currently looking at.
+ * - 'bfd->curscene' - scene undo-step was created in.
+ *
+ * This means users can have 2+ windows open and undo in both without screens switching.
+ * But if they close one of the screens,
+ * undo will ensure that the scene being operated on will be activated
+ * (otherwise we'd be undoing on an off-screen scene which isn't acceptable).
+ * see: T43424
+ */
+ bool track_undo_scene;
+
/* comes from readfile.c */
SWAP(ListBase, G.main->wm, bfd->main->wm);
SWAP(ListBase, G.main->screen, bfd->main->screen);
@@ -238,15 +262,40 @@ static void setup_app_data(bContext *C, BlendFileData *bfd, const char *filepath
curscreen = CTX_wm_screen(C);
/* but use new Scene pointer */
curscene = bfd->curscene;
+
+ track_undo_scene = (mode == LOAD_UNDO && curscreen && curscene && bfd->main->wm.first);
+
if (curscene == NULL) curscene = bfd->main->scene.first;
/* empty file, we add a scene to make Blender work */
if (curscene == NULL) curscene = BKE_scene_add(bfd->main, "Empty");
-
- /* and we enforce curscene to be in current screen */
- if (curscreen) curscreen->scene = curscene; /* can run in bgmode */
+
+ if (track_undo_scene) {
+ /* keep the old (free'd) scene, let 'blo_lib_link_screen_restore'
+ * replace it with 'curscene' if its needed */
+ }
+ else {
+ /* and we enforce curscene to be in current screen */
+ if (curscreen) {
+ /* can run in bgmode */
+ curscreen->scene = curscene;
+ }
+ }
/* clear_global will free G.main, here we can still restore pointers */
blo_lib_link_screen_restore(bfd->main, curscreen, curscene);
+ /* curscreen might not be set when loading without ui (see T44217) so only re-assign if available */
+ if (curscreen) {
+ curscene = curscreen->scene;
+ }
+
+ if (track_undo_scene) {
+ wmWindowManager *wm = bfd->main->wm.first;
+ if (wm_scene_is_visible(wm, bfd->curscene) == false) {
+ curscene = bfd->curscene;
+ curscreen->scene = curscene;
+ BKE_screen_view3d_scene_sync(curscreen);
+ }
+ }
}
/* free G.main Main database */
@@ -260,14 +309,23 @@ static void setup_app_data(bContext *C, BlendFileData *bfd, const char *filepath
CTX_data_main_set(C, G.main);
- sound_init_main(G.main);
-
if (bfd->user) {
/* only here free userdef themes... */
BKE_userdef_free();
U = *bfd->user;
+
+ /* Security issue: any blend file could include a USER block.
+ *
+ * Currently we load prefs from BLENDER_STARTUP_FILE and later on load BLENDER_USERPREF_FILE,
+ * to load the preferences defined in the users home dir.
+ *
+ * This means we will never accidentally (or maliciously)
+ * enable scripts auto-execution by loading a '.blend' file.
+ */
+ U.flag |= USER_SCRIPT_AUTOEXEC_DISABLE;
+
MEM_freeN(bfd->user);
}
@@ -277,8 +335,6 @@ static void setup_app_data(bContext *C, BlendFileData *bfd, const char *filepath
CTX_data_scene_set(C, curscene);
}
else {
- G.winpos = bfd->winpos;
- G.displaymode = bfd->displaymode;
G.fileflags = bfd->fileflags;
CTX_wm_manager_set(C, G.main->wm.first);
CTX_wm_screen_set(C, bfd->curscreen);
@@ -361,6 +417,7 @@ static void setup_app_data(bContext *C, BlendFileData *bfd, const char *filepath
BKE_scene_set_background(G.main, curscene);
if (mode != LOAD_UNDO) {
+ RE_FreeAllPersistentData();
IMB_colormanagement_check_file_config(G.main);
}
@@ -491,10 +548,11 @@ bool BKE_read_file_from_memory(
BLO_update_defaults_startup_blend(bfd->main);
setup_app_data(C, bfd, "<memory2>");
}
- else
+ else {
BKE_reports_prepend(reports, "Loading failed: ");
+ }
- return (bfd ? 1 : 0);
+ return (bfd != NULL);
}
/* memfile is the undo buffer */
@@ -514,10 +572,11 @@ bool BKE_read_file_from_memfile(
setup_app_data(C, bfd, "<memory1>");
}
- else
+ else {
BKE_reports_prepend(reports, "Loading failed: ");
+ }
- return (bfd ? 1 : 0);
+ return (bfd != NULL);
}
/* only read the userdef from a .blend */
@@ -563,7 +622,7 @@ int BKE_write_file_userdef(const char *filepath, ReportList *reports)
static void (*blender_test_break_cb)(void) = NULL;
-void set_blender_test_break_cb(void (*func)(void) )
+void BKE_blender_callback_test_break_set(void (*func)(void))
{
blender_test_break_cb = func;
}
@@ -627,7 +686,7 @@ static int read_undosave(bContext *C, UndoElem *uel)
}
/* name can be a dynamic string */
-void BKE_write_undo(bContext *C, const char *name)
+void BKE_undo_write(bContext *C, const char *name)
{
uintptr_t maxmem, totmem, memused;
int nr /*, success */ /* UNUSED */;
@@ -645,7 +704,7 @@ void BKE_write_undo(bContext *C, const char *name)
while (undobase.last != curundo) {
uel = undobase.last;
BLI_remlink(&undobase, uel);
- BLO_free_memfile(&uel->memfile);
+ BLO_memfile_free(&uel->memfile);
MEM_freeN(uel);
}
@@ -667,7 +726,7 @@ void BKE_write_undo(bContext *C, const char *name)
UndoElem *first = undobase.first;
BLI_remlink(&undobase, first);
/* the merge is because of compression */
- BLO_merge_memfile(&first->memfile, &first->next->memfile);
+ BLO_memfile_merge(&first->memfile, &first->next->memfile);
MEM_freeN(first);
}
}
@@ -685,7 +744,7 @@ void BKE_write_undo(bContext *C, const char *name)
counter = counter % U.undosteps;
BLI_snprintf(numstr, sizeof(numstr), "%d.blend", counter);
- BLI_make_file_string("/", filepath, BLI_temp_dir_session(), numstr);
+ BLI_make_file_string("/", filepath, BKE_tempdir_session(), numstr);
/* success = */ /* UNUSED */ BLO_write_file(CTX_data_main(C), filepath, fileflags, NULL, NULL);
@@ -722,7 +781,7 @@ void BKE_write_undo(bContext *C, const char *name)
UndoElem *first = undobase.first;
BLI_remlink(&undobase, first);
/* the merge is because of compression */
- BLO_merge_memfile(&first->memfile, &first->next->memfile);
+ BLO_memfile_merge(&first->memfile, &first->next->memfile);
MEM_freeN(first);
}
}
@@ -761,13 +820,13 @@ void BKE_undo_step(bContext *C, int step)
}
}
-void BKE_reset_undo(void)
+void BKE_undo_reset(void)
{
UndoElem *uel;
uel = undobase.first;
while (uel) {
- BLO_free_memfile(&uel->memfile);
+ BLO_memfile_free(&uel->memfile);
uel = uel->next;
}
@@ -794,7 +853,7 @@ void BKE_undo_name(bContext *C, const char *name)
}
/* name optional */
-int BKE_undo_valid(const char *name)
+bool BKE_undo_is_valid(const char *name)
{
if (name) {
UndoElem *uel = BLI_rfindstring(&undobase, name, offsetof(UndoElem, name));
@@ -806,15 +865,16 @@ int BKE_undo_valid(const char *name)
/* get name of undo item, return null if no item with this index */
/* if active pointer, set it to 1 if true */
-const char *BKE_undo_get_name(int nr, int *active)
+const char *BKE_undo_get_name(int nr, bool *r_active)
{
UndoElem *uel = BLI_findlink(&undobase, nr);
- if (active) *active = 0;
+ if (r_active) *r_active = false;
if (uel) {
- if (active && uel == curundo)
- *active = 1;
+ if (r_active && (uel == curundo)) {
+ *r_active = true;
+ }
return uel->name;
}
return NULL;
@@ -832,13 +892,13 @@ bool BKE_undo_save_file(const char *filename)
int file, oflags;
if ((U.uiflag & USER_GLOBALUNDO) == 0) {
- return 0;
+ return false;
}
uel = curundo;
if (uel == NULL) {
fprintf(stderr, "No undo buffer to save recovery file\n");
- return 0;
+ return false;
}
/* note: This is currently used for autosave and 'quit.blend', where _not_ following symlinks is OK,
@@ -860,7 +920,7 @@ bool BKE_undo_save_file(const char *filename)
if (file == -1) {
fprintf(stderr, "Unable to save '%s': %s\n",
filename, errno ? strerror(errno) : "Unknown error opening file");
- return 0;
+ return false;
}
for (chunk = uel->memfile.chunks.first; chunk; chunk = chunk->next) {
@@ -874,21 +934,22 @@ bool BKE_undo_save_file(const char *filename)
if (chunk) {
fprintf(stderr, "Unable to save '%s': %s\n",
filename, errno ? strerror(errno) : "Unknown error writing file");
- return 0;
+ return false;
}
- return 1;
+ return true;
}
/* sets curscene */
-Main *BKE_undo_get_main(Scene **scene)
+Main *BKE_undo_get_main(Scene **r_scene)
{
Main *mainp = NULL;
BlendFileData *bfd = BLO_read_from_memfile(G.main, G.main->name, &curundo->memfile, NULL);
if (bfd) {
mainp = bfd->main;
- if (scene)
- *scene = bfd->curscene;
+ if (r_scene) {
+ *r_scene = bfd->curscene;
+ }
MEM_freeN(bfd);
}
diff --git a/source/blender/blenkernel/intern/boids.c b/source/blender/blenkernel/intern/boids.c
index 5731455fc01..d765dff132f 100644
--- a/source/blender/blenkernel/intern/boids.c
+++ b/source/blender/blenkernel/intern/boids.c
@@ -189,6 +189,7 @@ static int rule_goal_avoid(BoidRule *rule, BoidBrainData *bbd, BoidValues *val,
static int rule_avoid_collision(BoidRule *rule, BoidBrainData *bbd, BoidValues *val, ParticleData *pa)
{
+ const int raycast_flag = BVH_RAYCAST_DEFAULT & ~(BVH_RAYCAST_WATERTIGHT);
BoidRuleAvoidCollision *acbr = (BoidRuleAvoidCollision*) rule;
KDTreeNearest *ptn = NULL;
ParticleTarget *pt;
@@ -214,7 +215,7 @@ static int rule_avoid_collision(BoidRule *rule, BoidBrainData *bbd, BoidValues *
mul_v3_fl(ray_dir, acbr->look_ahead);
col.f = 0.0f;
hit.index = -1;
- hit.dist = col.original_ray_length = len_v3(ray_dir);
+ hit.dist = col.original_ray_length = normalize_v3(ray_dir);
/* find out closest deflector object */
for (coll = bbd->sim->colliders->first; coll; coll=coll->next) {
@@ -225,8 +226,11 @@ static int rule_avoid_collision(BoidRule *rule, BoidBrainData *bbd, BoidValues *
col.current = coll->ob;
col.md = coll->collmd;
- if (col.md && col.md->bvhtree)
- BLI_bvhtree_ray_cast(col.md->bvhtree, col.co1, ray_dir, radius, &hit, BKE_psys_collision_neartest_cb, &col);
+ if (col.md && col.md->bvhtree) {
+ BLI_bvhtree_ray_cast_ex(
+ col.md->bvhtree, col.co1, ray_dir, radius, &hit,
+ BKE_psys_collision_neartest_cb, &col, raycast_flag);
+ }
}
/* then avoid that object */
if (hit.index>=0) {
@@ -759,6 +763,7 @@ static void set_boid_values(BoidValues *val, BoidSettings *boids, ParticleData *
static Object *boid_find_ground(BoidBrainData *bbd, ParticleData *pa, float ground_co[3], float ground_nor[3])
{
+ const int raycast_flag = BVH_RAYCAST_DEFAULT & ~(BVH_RAYCAST_WATERTIGHT);
BoidParticle *bpa = pa->boid;
if (bpa->data.mode == eBoidMode_Climbing) {
@@ -794,7 +799,7 @@ static Object *boid_find_ground(BoidBrainData *bbd, ParticleData *pa, float grou
sub_v3_v3v3(ray_dir, col.co2, col.co1);
col.f = 0.0f;
hit.index = -1;
- hit.dist = col.original_ray_length = len_v3(ray_dir);
+ hit.dist = col.original_ray_length = normalize_v3(ray_dir);
col.pce.inside = 0;
for (coll = bbd->sim->colliders->first; coll; coll = coll->next) {
@@ -802,8 +807,11 @@ static Object *boid_find_ground(BoidBrainData *bbd, ParticleData *pa, float grou
col.md = coll->collmd;
col.fac1 = col.fac2 = 0.f;
- if (col.md && col.md->bvhtree)
- BLI_bvhtree_ray_cast(col.md->bvhtree, col.co1, ray_dir, radius, &hit, BKE_psys_collision_neartest_cb, &col);
+ if (col.md && col.md->bvhtree) {
+ BLI_bvhtree_ray_cast_ex(
+ col.md->bvhtree, col.co1, ray_dir, radius, &hit,
+ BKE_psys_collision_neartest_cb, &col, raycast_flag);
+ }
}
/* then use that object */
if (hit.index>=0) {
@@ -820,14 +828,17 @@ static Object *boid_find_ground(BoidBrainData *bbd, ParticleData *pa, float grou
sub_v3_v3v3(ray_dir, col.co2, col.co1);
col.f = 0.0f;
hit.index = -1;
- hit.dist = col.original_ray_length = len_v3(ray_dir);
+ hit.dist = col.original_ray_length = normalize_v3(ray_dir);
for (coll = bbd->sim->colliders->first; coll; coll = coll->next) {
col.current = coll->ob;
col.md = coll->collmd;
- if (col.md && col.md->bvhtree)
- BLI_bvhtree_ray_cast(col.md->bvhtree, col.co1, ray_dir, radius, &hit, BKE_psys_collision_neartest_cb, &col);
+ if (col.md && col.md->bvhtree) {
+ BLI_bvhtree_ray_cast_ex(
+ col.md->bvhtree, col.co1, ray_dir, radius, &hit,
+ BKE_psys_collision_neartest_cb, &col, raycast_flag);
+ }
}
/* then use that object */
if (hit.index>=0) {
@@ -994,10 +1005,12 @@ void boid_brain(BoidBrainData *bbd, int p, ParticleData *pa)
}
case eBoidRulesetType_Random:
{
- /* use random rule for each particle (allways same for same particle though) */
- rule = BLI_findlink(&state->rules, rand % BLI_countlist(&state->rules));
-
- apply_boid_rule(bbd, rule, &val, pa, -1.0);
+ /* use random rule for each particle (always same for same particle though) */
+ const int n = BLI_listbase_count(&state->rules);
+ if (n) {
+ rule = BLI_findlink(&state->rules, rand % n);
+ apply_boid_rule(bbd, rule, &val, pa, -1.0);
+ }
break;
}
case eBoidRulesetType_Average:
diff --git a/source/blender/blenkernel/intern/bpath.c b/source/blender/blenkernel/intern/bpath.c
index 3cd26dacebd..76544e5ed42 100644
--- a/source/blender/blenkernel/intern/bpath.c
+++ b/source/blender/blenkernel/intern/bpath.c
@@ -80,6 +80,10 @@
#include "BKE_bpath.h" /* own include */
+#ifndef _MSC_VER
+# include "BLI_strict_flags.h"
+#endif
+
static bool checkMissingFiles_visit_cb(void *userdata, char *UNUSED(path_dst), const char *path_src)
{
ReportList *reports = (ReportList *)userdata;
@@ -204,18 +208,19 @@ void BKE_bpath_absolute_convert(Main *bmain, const char *basedir, ReportList *re
* \returns found: 1/0.
*/
#define MAX_RECUR 16
-static int findFileRecursive(char *filename_new,
- const char *dirname,
- const char *filename,
- int *filesize,
- int *recur_depth)
+static bool missing_files_find__recursive(
+ char *filename_new,
+ const char *dirname,
+ const char *filename,
+ off_t *r_filesize,
+ int *r_recur_depth)
{
/* file searching stuff */
DIR *dir;
struct dirent *de;
BLI_stat_t status;
char path[FILE_MAX];
- int size;
+ off_t size;
bool found = false;
dir = opendir(dirname);
@@ -223,35 +228,35 @@ static int findFileRecursive(char *filename_new,
if (dir == NULL)
return found;
- if (*filesize == -1)
- *filesize = 0; /* dir opened fine */
+ if (*r_filesize == -1)
+ *r_filesize = 0; /* dir opened fine */
while ((de = readdir(dir)) != NULL) {
- if (STREQ(".", de->d_name) || STREQ("..", de->d_name))
+ if (FILENAME_IS_CURRPAR(de->d_name))
continue;
BLI_join_dirfile(path, sizeof(path), dirname, de->d_name);
- if (BLI_stat(path, &status) != 0)
+ if (BLI_stat(path, &status) == -1)
continue; /* cant stat, don't bother with this file, could print debug info here */
if (S_ISREG(status.st_mode)) { /* is file */
if (STREQLEN(filename, de->d_name, FILE_MAX)) { /* name matches */
/* open the file to read its size */
size = status.st_size;
- if ((size > 0) && (size > *filesize)) { /* find the biggest file */
- *filesize = size;
+ if ((size > 0) && (size > *r_filesize)) { /* find the biggest file */
+ *r_filesize = size;
BLI_strncpy(filename_new, path, FILE_MAX);
found = true;
}
}
}
else if (S_ISDIR(status.st_mode)) { /* is subdir */
- if (*recur_depth <= MAX_RECUR) {
- (*recur_depth)++;
- found |= findFileRecursive(filename_new, path, filename, filesize, recur_depth);
- (*recur_depth)--;
+ if (*r_recur_depth <= MAX_RECUR) {
+ (*r_recur_depth)++;
+ found |= missing_files_find__recursive(filename_new, path, filename, r_filesize, r_recur_depth);
+ (*r_recur_depth)--;
}
}
}
@@ -266,14 +271,14 @@ typedef struct BPathFind_Data {
bool find_all;
} BPathFind_Data;
-static bool findMissingFiles_visit_cb(void *userdata, char *path_dst, const char *path_src)
+static bool missing_files_find__visit_cb(void *userdata, char *path_dst, const char *path_src)
{
BPathFind_Data *data = (BPathFind_Data *)userdata;
char filename_new[FILE_MAX];
- int filesize = -1;
+ off_t filesize = -1;
int recur_depth = 0;
- int found;
+ bool found;
if (data->find_all == false) {
if (BLI_exists(path_src)) {
@@ -283,9 +288,10 @@ static bool findMissingFiles_visit_cb(void *userdata, char *path_dst, const char
filename_new[0] = '\0';
- found = findFileRecursive(filename_new,
- data->searchdir, BLI_path_basename((char *)path_src),
- &filesize, &recur_depth);
+ found = missing_files_find__recursive(
+ filename_new,
+ data->searchdir, BLI_path_basename(path_src),
+ &filesize, &recur_depth);
if (filesize == -1) { /* could not open dir */
BKE_reportf(data->reports, RPT_WARNING,
@@ -296,7 +302,7 @@ static bool findMissingFiles_visit_cb(void *userdata, char *path_dst, const char
else if (found == false) {
BKE_reportf(data->reports, RPT_WARNING,
"Could not find '%s' in '%s'",
- BLI_path_basename((char *)path_src), data->searchdir);
+ BLI_path_basename(path_src), data->searchdir);
return false;
}
else {
@@ -316,13 +322,14 @@ void BKE_bpath_missing_files_find(Main *bmain, const char *searchpath, ReportLis
const bool find_all)
{
struct BPathFind_Data data = {NULL};
+ const int flag = BKE_BPATH_TRAVERSE_ABS | BKE_BPATH_TRAVERSE_RELOAD_EDITED;
data.basedir = bmain->name;
data.reports = reports;
data.searchdir = searchpath;
data.find_all = find_all;
- BKE_bpath_traverse_main(bmain, findMissingFiles_visit_cb, BKE_BPATH_TRAVERSE_ABS, (void *)&data);
+ BKE_bpath_traverse_main(bmain, missing_files_find__visit_cb, flag, (void *)&data);
}
/* Run a visitor on a string, replacing the contents of the string as needed. */
@@ -364,6 +371,9 @@ static bool rewrite_path_fixed_dirfile(char path_dir[FILE_MAXDIR],
BLI_join_dirfile(path_src, sizeof(path_src), path_dir, path_file);
+ /* so functions can check old value */
+ BLI_strncpy(path_dst, path_src, FILE_MAX);
+
if (absbase) {
BLI_path_abs(path_src, absbase);
}
@@ -393,7 +403,7 @@ static bool rewrite_path_alloc(char **path, BPathVisitor visit_cb, const char *a
}
if (visit_cb(userdata, path_dst, path_src)) {
- MEM_freeN((*path));
+ MEM_freeN(*path);
(*path) = BLI_strdup(path_dst);
return true;
}
@@ -423,12 +433,17 @@ void BKE_bpath_traverse_id(Main *bmain, ID *id, BPathVisitor visit_cb, const int
{
Image *ima;
ima = (Image *)id;
- if (ima->packedfile == NULL || (flag & BKE_BPATH_TRAVERSE_SKIP_PACKED) == 0) {
+ if (BKE_image_has_packedfile(ima) == false || (flag & BKE_BPATH_TRAVERSE_SKIP_PACKED) == 0) {
if (ELEM(ima->source, IMA_SRC_FILE, IMA_SRC_MOVIE, IMA_SRC_SEQUENCE)) {
if (rewrite_path_fixed(ima->name, visit_cb, absbase, bpath_user_data)) {
- if (!ima->packedfile) {
- BKE_image_signal(ima, NULL, IMA_SIGNAL_RELOAD);
- BKE_image_walk_all_users(bmain, ima, bpath_traverse_image_user_cb);
+ if (flag & BKE_BPATH_TRAVERSE_RELOAD_EDITED) {
+ if (!BKE_image_has_packedfile(ima) &&
+ /* image may have been painted onto (and not saved, T44543) */
+ !BKE_image_is_dirty(ima))
+ {
+ BKE_image_signal(ima, NULL, IMA_SIGNAL_RELOAD);
+ BKE_image_walk_all_users(bmain, ima, bpath_traverse_image_user_cb);
+ }
}
}
}
@@ -589,12 +604,12 @@ void BKE_bpath_traverse_id(Main *bmain, ID *id, BPathVisitor visit_cb, const int
}
else if ((seq->type == SEQ_TYPE_IMAGE) && se) {
/* might want an option not to loop over all strips */
- int len = MEM_allocN_len(se) / sizeof(*se);
- int i;
+ unsigned int len = (unsigned int)MEM_allocN_len(se) / (unsigned int)sizeof(*se);
+ unsigned int i;
if (flag & BKE_BPATH_TRAVERSE_SKIP_MULTIFILE) {
/* only operate on one path */
- len = MIN2(1, len);
+ len = MIN2(1u, len);
}
for (i = 0; i < len; i++, se++) {
diff --git a/source/blender/blenkernel/intern/brush.c b/source/blender/blenkernel/intern/brush.c
index 76b0cad337f..e0ffd830804 100644
--- a/source/blender/blenkernel/intern/brush.c
+++ b/source/blender/blenkernel/intern/brush.c
@@ -33,7 +33,6 @@
#include "BLI_math.h"
#include "BLI_blenlib.h"
#include "BLI_rand.h"
-#include "BLI_rect.h"
#include "BKE_brush.h"
#include "BKE_colortools.h"
@@ -49,7 +48,6 @@
#include "IMB_imbuf_types.h"
#include "RE_render_ext.h" /* externtex */
-#include "RE_shader_ext.h"
static RNG *brush_rng;
@@ -105,8 +103,8 @@ static void brush_defaults(Brush *brush)
brush->jitter = 0.0f;
/* BRUSH TEXTURE SETTINGS */
- default_mtex(&brush->mtex);
- default_mtex(&brush->mask_mtex);
+ BKE_texture_mtex_default(&brush->mtex);
+ BKE_texture_mtex_default(&brush->mask_mtex);
brush->texture_sample_bias = 0; /* value to added to texture samples */
brush->texture_overlay_alpha = 33;
@@ -133,7 +131,7 @@ static void brush_defaults(Brush *brush)
/* Datablock add/copy/free/make_local */
-Brush *BKE_brush_add(Main *bmain, const char *name)
+Brush *BKE_brush_add(Main *bmain, const char *name, short ob_mode)
{
Brush *brush;
@@ -145,6 +143,7 @@ Brush *BKE_brush_add(Main *bmain, const char *name)
brush_defaults(brush);
brush->sculpt_tool = SCULPT_TOOL_DRAW; /* sculpting defaults to the draw tool for new brushes */
+ brush->ob_mode = ob_mode;
/* the default alpha falloff curve */
BKE_brush_curve_preset(brush, CURVE_PRESET_SMOOTH);
@@ -152,6 +151,17 @@ Brush *BKE_brush_add(Main *bmain, const char *name)
return brush;
}
+struct Brush *BKE_brush_first_search(struct Main *bmain, short ob_mode)
+{
+ Brush *brush;
+
+ for (brush = bmain->brush.first; brush; brush = brush->id.next) {
+ if (brush->ob_mode & ob_mode)
+ return brush;
+ }
+ return NULL;
+}
+
Brush *BKE_brush_copy(Brush *brush)
{
Brush *brushn;
@@ -180,6 +190,10 @@ Brush *BKE_brush_copy(Brush *brush)
brushn->id.us++;
}
+ if (brush->id.lib) {
+ BKE_id_lib_local_paths(G.main, brush->id.lib, &brushn->id);
+ }
+
return brushn;
}
@@ -295,12 +309,10 @@ void BKE_brush_debug_print_state(Brush *br)
/* br->flag */
BR_TEST_FLAG(BRUSH_AIRBRUSH);
- BR_TEST_FLAG(BRUSH_TORUS);
BR_TEST_FLAG(BRUSH_ALPHA_PRESSURE);
BR_TEST_FLAG(BRUSH_SIZE_PRESSURE);
BR_TEST_FLAG(BRUSH_JITTER_PRESSURE);
BR_TEST_FLAG(BRUSH_SPACING_PRESSURE);
- BR_TEST_FLAG(BRUSH_RAKE);
BR_TEST_FLAG(BRUSH_ANCHORED);
BR_TEST_FLAG(BRUSH_DIR_IN);
BR_TEST_FLAG(BRUSH_SPACE);
@@ -316,7 +328,6 @@ void BKE_brush_debug_print_state(Brush *br)
BR_TEST_FLAG(BRUSH_EDGE_TO_EDGE);
BR_TEST_FLAG(BRUSH_DRAG_DOT);
BR_TEST_FLAG(BRUSH_INVERSE_SMOOTH_PRESSURE);
- BR_TEST_FLAG(BRUSH_RANDOM_ROTATION);
BR_TEST_FLAG(BRUSH_PLANE_TRIM);
BR_TEST_FLAG(BRUSH_FRONTFACE);
BR_TEST_FLAG(BRUSH_CUSTOM_ICON);
@@ -469,7 +480,7 @@ int BKE_brush_texture_set_nr(Brush *brush, int nr)
idtest = (ID *)BLI_findlink(&G.main->tex, nr - 1);
if (idtest == NULL) { /* new tex */
if (id) idtest = (ID *)BKE_texture_copy((Tex *)id);
- else idtest = (ID *)add_texture(G.main, "Tex");
+ else idtest = (ID *)BKE_texture_add(G.main, "Tex");
idtest->us--;
}
if (idtest != id) {
@@ -542,7 +553,7 @@ float BKE_brush_sample_tex_3D(const Scene *scene, Brush *br,
/* Get strength by feeding the vertex
* location directly into a texture */
hasrgb = externtex(mtex, point, &intensity,
- rgba, rgba + 1, rgba + 2, rgba + 3, thread, pool);
+ rgba, rgba + 1, rgba + 2, rgba + 3, thread, pool, false);
}
else if (mtex->brush_map_mode == MTEX_MAP_MODE_STENCIL) {
float rotation = -mtex->rot;
@@ -573,7 +584,7 @@ float BKE_brush_sample_tex_3D(const Scene *scene, Brush *br,
co[2] = 0.0f;
hasrgb = externtex(mtex, co, &intensity,
- rgba, rgba + 1, rgba + 2, rgba + 3, thread, pool);
+ rgba, rgba + 1, rgba + 2, rgba + 3, thread, pool, false);
}
else {
float rotation = -mtex->rot;
@@ -630,7 +641,7 @@ float BKE_brush_sample_tex_3D(const Scene *scene, Brush *br,
co[2] = 0.0f;
hasrgb = externtex(mtex, co, &intensity,
- rgba, rgba + 1, rgba + 2, rgba + 3, thread, pool);
+ rgba, rgba + 1, rgba + 2, rgba + 3, thread, pool, false);
}
intensity += br->texture_sample_bias;
@@ -690,7 +701,7 @@ float BKE_brush_sample_masktex(const Scene *scene, Brush *br,
co[2] = 0.0f;
externtex(mtex, co, &intensity,
- rgba, rgba + 1, rgba + 2, rgba + 3, thread, pool);
+ rgba, rgba + 1, rgba + 2, rgba + 3, thread, pool, false);
}
else {
float rotation = -mtex->rot;
@@ -702,7 +713,7 @@ float BKE_brush_sample_masktex(const Scene *scene, Brush *br,
if (mtex->brush_map_mode == MTEX_MAP_MODE_VIEW) {
/* keep coordinates relative to mouse */
- rotation += ups->brush_rotation;
+ rotation += ups->brush_rotation_sec;
x = point_2d[0] - ups->mask_tex_mouse[0];
y = point_2d[1] - ups->mask_tex_mouse[1];
@@ -720,7 +731,7 @@ float BKE_brush_sample_masktex(const Scene *scene, Brush *br,
y = point_2d[1];
}
else if (mtex->brush_map_mode == MTEX_MAP_MODE_RANDOM) {
- rotation += ups->brush_rotation;
+ rotation += ups->brush_rotation_sec;
/* these contain a random coordinate */
x = point_2d[0] - ups->mask_tex_mouse[0];
y = point_2d[1] - ups->mask_tex_mouse[1];
@@ -747,7 +758,7 @@ float BKE_brush_sample_masktex(const Scene *scene, Brush *br,
co[2] = 0.0f;
externtex(mtex, co, &intensity,
- rgba, rgba + 1, rgba + 2, rgba + 3, thread, pool);
+ rgba, rgba + 1, rgba + 2, rgba + 3, thread, pool, false);
}
CLAMP(intensity, 0.0f, 1.0f);
@@ -782,13 +793,13 @@ float BKE_brush_sample_masktex(const Scene *scene, Brush *br,
* inconsistency. */
-float *BKE_brush_color_get(const struct Scene *scene, struct Brush *brush)
+const float *BKE_brush_color_get(const struct Scene *scene, const struct Brush *brush)
{
UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings;
return (ups->flag & UNIFIED_PAINT_COLOR) ? ups->rgb : brush->rgb;
}
-float *BKE_brush_secondary_color_get(const struct Scene *scene, struct Brush *brush)
+const float *BKE_brush_secondary_color_get(const struct Scene *scene, const struct Brush *brush)
{
UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings;
return (ups->flag & UNIFIED_PAINT_COLOR) ? ups->secondary_rgb : brush->secondary_rgb;
@@ -810,13 +821,16 @@ void BKE_brush_size_set(Scene *scene, Brush *brush, int size)
size = (int)((float)size / U.pixelsize);
+ /* make sure range is sane */
+ CLAMP(size, 1, MAX_BRUSH_PIXEL_RADIUS);
+
if (ups->flag & UNIFIED_PAINT_SIZE)
ups->size = size;
else
brush->size = size;
}
-int BKE_brush_size_get(const Scene *scene, Brush *brush)
+int BKE_brush_size_get(const Scene *scene, const Brush *brush)
{
UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings;
int size = (ups->flag & UNIFIED_PAINT_SIZE) ? ups->size : brush->size;
@@ -824,7 +838,7 @@ int BKE_brush_size_get(const Scene *scene, Brush *brush)
return (int)((float)size * U.pixelsize);
}
-int BKE_brush_use_locked_size(const Scene *scene, Brush *brush)
+int BKE_brush_use_locked_size(const Scene *scene, const Brush *brush)
{
const short us_flag = scene->toolsettings->unified_paint_settings.flag;
@@ -833,7 +847,7 @@ int BKE_brush_use_locked_size(const Scene *scene, Brush *brush)
(brush->flag & BRUSH_LOCK_SIZE);
}
-int BKE_brush_use_size_pressure(const Scene *scene, Brush *brush)
+int BKE_brush_use_size_pressure(const Scene *scene, const Brush *brush)
{
const short us_flag = scene->toolsettings->unified_paint_settings.flag;
@@ -842,7 +856,7 @@ int BKE_brush_use_size_pressure(const Scene *scene, Brush *brush)
(brush->flag & BRUSH_SIZE_PRESSURE);
}
-int BKE_brush_use_alpha_pressure(const Scene *scene, Brush *brush)
+int BKE_brush_use_alpha_pressure(const Scene *scene, const Brush *brush)
{
const short us_flag = scene->toolsettings->unified_paint_settings.flag;
@@ -861,7 +875,7 @@ void BKE_brush_unprojected_radius_set(Scene *scene, Brush *brush, float unprojec
brush->unprojected_radius = unprojected_radius;
}
-float BKE_brush_unprojected_radius_get(const Scene *scene, Brush *brush)
+float BKE_brush_unprojected_radius_get(const Scene *scene, const Brush *brush)
{
UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings;
@@ -880,14 +894,14 @@ void BKE_brush_alpha_set(Scene *scene, Brush *brush, float alpha)
brush->alpha = alpha;
}
-float BKE_brush_alpha_get(const Scene *scene, Brush *brush)
+float BKE_brush_alpha_get(const Scene *scene, const Brush *brush)
{
UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings;
return (ups->flag & UNIFIED_PAINT_ALPHA) ? ups->alpha : brush->alpha;
}
-float BKE_brush_weight_get(const Scene *scene, Brush *brush)
+float BKE_brush_weight_get(const Scene *scene, const Brush *brush)
{
UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings;
@@ -917,9 +931,10 @@ void BKE_brush_scale_unprojected_radius(float *unprojected_radius,
}
/* scale brush size to reflect a change in the brush's unprojected radius */
-void BKE_brush_scale_size(int *r_brush_size,
- float new_unprojected_radius,
- float old_unprojected_radius)
+void BKE_brush_scale_size(
+ int *r_brush_size,
+ float new_unprojected_radius,
+ float old_unprojected_radius)
{
float scale = new_unprojected_radius;
/* avoid division by zero */
@@ -937,7 +952,7 @@ void BKE_brush_jitter_pos(const Scene *scene, Brush *brush, const float pos[2],
do {
rand_pos[0] = BLI_rng_get_float(brush_rng) - 0.5f;
rand_pos[1] = BLI_rng_get_float(brush_rng) - 0.5f;
- } while (len_squared_v2(rand_pos) > (0.5f * 0.5f));
+ } while (len_squared_v2(rand_pos) > SQUARE(0.5f));
if (brush->flag & BRUSH_ABSOLUTE_JITTER) {
@@ -953,7 +968,7 @@ void BKE_brush_jitter_pos(const Scene *scene, Brush *brush, const float pos[2],
jitterpos[1] = pos[1] + 2 * rand_pos[1] * diameter * spread;
}
-void BKE_brush_randomize_texture_coordinates(UnifiedPaintSettings *ups, bool mask)
+void BKE_brush_randomize_texture_coords(UnifiedPaintSettings *ups, bool mask)
{
/* we multiply with brush radius as an optimization for the brush
* texture sampling functions */
@@ -967,8 +982,8 @@ void BKE_brush_randomize_texture_coordinates(UnifiedPaintSettings *ups, bool mas
}
}
-/* Uses the brush curve control to find a strength value between 0 and 1 */
-float BKE_brush_curve_strength_clamp(Brush *br, float p, const float len)
+/* Uses the brush curve control to find a strength value */
+float BKE_brush_curve_strength(Brush *br, float p, const float len)
{
float strength;
@@ -977,20 +992,18 @@ float BKE_brush_curve_strength_clamp(Brush *br, float p, const float len)
strength = curvemapping_evaluateF(br->curve, 0, p);
- CLAMP(strength, 0.0f, 1.0f);
-
return strength;
}
-/* same as above but can return negative values if the curve enables
- * used for sculpt only */
-float BKE_brush_curve_strength(Brush *br, float p, const float len)
+
+
+/* Uses the brush curve control to find a strength value between 0 and 1 */
+float BKE_brush_curve_strength_clamped(Brush *br, float p, const float len)
{
- if (p >= len)
- p = 1.0f;
- else
- p = p / len;
+ float strength = BKE_brush_curve_strength(br, p, len);
- return curvemapping_evaluateF(br->curve, 0, p);
+ CLAMP(strength, 0.0f, 1.0f);
+
+ return strength;
}
/* TODO: should probably be unified with BrushPainter stuff? */
@@ -1018,7 +1031,7 @@ unsigned int *BKE_brush_gen_texture_cache(Brush *br, int half_side, bool use_sec
/* This is copied from displace modifier code */
/* TODO(sergey): brush are always cacheing with CM enabled for now. */
externtex(mtex, co, &intensity,
- rgba, rgba + 1, rgba + 2, rgba + 3, 0, NULL);
+ rgba, rgba + 1, rgba + 2, rgba + 3, 0, NULL, false);
((char *)texcache)[(iy * side + ix) * 4] =
((char *)texcache)[(iy * side + ix) * 4 + 1] =
@@ -1048,8 +1061,8 @@ struct ImBuf *BKE_brush_gen_radial_control_imbuf(Brush *br, bool secondary)
for (i = 0; i < side; ++i) {
for (j = 0; j < side; ++j) {
- float magn = sqrtf(powf(i - half, 2) + powf(j - half, 2));
- im->rect_float[i * side + j] = BKE_brush_curve_strength_clamp(br, magn, half);
+ float magn = sqrtf(pow2f(i - half) + pow2f(j - half));
+ im->rect_float[i * side + j] = BKE_brush_curve_strength_clamped(br, magn, half);
}
}
diff --git a/source/blender/blenkernel/intern/bvhutils.c b/source/blender/blenkernel/intern/bvhutils.c
index 4ad577a7bda..626be0eaf4e 100644
--- a/source/blender/blenkernel/intern/bvhutils.c
+++ b/source/blender/blenkernel/intern/bvhutils.c
@@ -48,26 +48,38 @@
static ThreadRWMutex cache_rwlock = BLI_RWLOCK_INITIALIZER;
+/* -------------------------------------------------------------------- */
+/** \name Local Callbacks
+ * \{ */
+
/* Math stuff for ray casting on mesh faces and for nearest surface */
-float bvhtree_ray_tri_intersection(const BVHTreeRay *ray, const float UNUSED(m_dist), const float v0[3], const float v1[3], const float v2[3])
+float bvhtree_ray_tri_intersection(
+ const BVHTreeRay *ray, const float UNUSED(m_dist),
+ const float v0[3], const float v1[3], const float v2[3])
{
float dist;
+#ifdef USE_KDOPBVH_WATERTIGHT
+ if (isect_ray_tri_watertight_v3(ray->origin, ray->isect_precalc, v0, v1, v2, &dist, NULL))
+#else
if (isect_ray_tri_epsilon_v3(ray->origin, ray->direction, v0, v1, v2, &dist, NULL, FLT_EPSILON))
+#endif
+ {
return dist;
+ }
return FLT_MAX;
}
-static float sphereray_tri_intersection(const BVHTreeRay *ray, float radius, const float m_dist, const float v0[3], const float v1[3], const float v2[3])
+float bvhtree_sphereray_tri_intersection(
+ const BVHTreeRay *ray, float radius, const float m_dist,
+ const float v0[3], const float v1[3], const float v2[3])
{
float idist;
float p1[3];
- float plane_normal[3], hit_point[3];
-
- normal_tri_v3(plane_normal, v0, v1, v2);
+ float hit_point[3];
madd_v3_v3v3fl(p1, ray->origin, ray->direction, m_dist);
if (isect_sweeping_sphere_tri_v3(ray->origin, p1, radius, v0, v1, v2, &idist, hit_point)) {
@@ -81,13 +93,13 @@ static float sphereray_tri_intersection(const BVHTreeRay *ray, float radius, con
* BVH from meshes callbacks
*/
-/* Callback to bvh tree nearest point. The tree must bust have been built using bvhtree_from_mesh_faces.
+/* Callback to bvh tree nearest point. The tree must have been built using bvhtree_from_mesh_faces.
* userdata must be a BVHMeshCallbackUserdata built from the same mesh as the tree. */
static void mesh_faces_nearest_point(void *userdata, int index, const float co[3], BVHTreeNearest *nearest)
{
const BVHTreeFromMesh *data = (BVHTreeFromMesh *) userdata;
- MVert *vert = data->vert;
- MFace *face = data->face + index;
+ const MVert *vert = data->vert;
+ const MFace *face = data->face + index;
const float *t0, *t1, *t2, *t3;
t0 = vert[face->v1].co;
@@ -107,9 +119,6 @@ static void mesh_faces_nearest_point(void *userdata, int index, const float co[3
nearest->dist_sq = dist_sq;
copy_v3_v3(nearest->co, nearest_tmp);
normal_tri_v3(nearest->no, t0, t1, t2);
-
- if (t1 == vert[face->v3].co)
- nearest->flags |= BVH_ONQUAD;
}
t1 = t2;
@@ -118,6 +127,29 @@ static void mesh_faces_nearest_point(void *userdata, int index, const float co[3
} while (t2);
}
+/* copy of function above */
+static void mesh_looptri_nearest_point(void *userdata, int index, const float co[3], BVHTreeNearest *nearest)
+{
+ const BVHTreeFromMesh *data = (BVHTreeFromMesh *) userdata;
+ const MVert *vert = data->vert;
+ const MLoopTri *lt = &data->looptri[index];
+ const float *vtri_co[3] = {
+ vert[data->loop[lt->tri[0]].v].co,
+ vert[data->loop[lt->tri[1]].v].co,
+ vert[data->loop[lt->tri[2]].v].co,
+ };
+ float nearest_tmp[3], dist_sq;
+
+ closest_on_tri_to_point_v3(nearest_tmp, co, UNPACK3(vtri_co));
+ dist_sq = len_squared_v3v3(co, nearest_tmp);
+
+ if (dist_sq < nearest->dist_sq) {
+ nearest->index = index;
+ nearest->dist_sq = dist_sq;
+ copy_v3_v3(nearest->co, nearest_tmp);
+ normal_tri_v3(nearest->no, UNPACK3(vtri_co));
+ }
+}
/* copy of function above (warning, should de-duplicate with editmesh_bvh.c) */
static void editmesh_faces_nearest_point(void *userdata, int index, const float co[3], BVHTreeNearest *nearest)
{
@@ -145,13 +177,13 @@ static void editmesh_faces_nearest_point(void *userdata, int index, const float
}
}
-/* Callback to bvh tree raycast. The tree must bust have been built using bvhtree_from_mesh_faces.
+/* Callback to bvh tree raycast. The tree must have been built using bvhtree_from_mesh_faces.
* userdata must be a BVHMeshCallbackUserdata built from the same mesh as the tree. */
static void mesh_faces_spherecast(void *userdata, int index, const BVHTreeRay *ray, BVHTreeRayHit *hit)
{
const BVHTreeFromMesh *data = (BVHTreeFromMesh *) userdata;
- MVert *vert = data->vert;
- MFace *face = data->face + index;
+ const MVert *vert = data->vert;
+ const MFace *face = &data->face[index];
const float *t0, *t1, *t2, *t3;
t0 = vert[face->v1].co;
@@ -165,7 +197,7 @@ static void mesh_faces_spherecast(void *userdata, int index, const BVHTreeRay *r
if (data->sphere_radius == 0.0f)
dist = bvhtree_ray_tri_intersection(ray, hit->dist, t0, t1, t2);
else
- dist = sphereray_tri_intersection(ray, data->sphere_radius, hit->dist, t0, t1, t2);
+ dist = bvhtree_sphereray_tri_intersection(ray, data->sphere_radius, hit->dist, t0, t1, t2);
if (dist >= 0 && dist < hit->dist) {
hit->index = index;
@@ -173,9 +205,6 @@ static void mesh_faces_spherecast(void *userdata, int index, const BVHTreeRay *r
madd_v3_v3v3fl(hit->co, ray->origin, ray->direction, dist);
normal_tri_v3(hit->no, t0, t1, t2);
-
- if (t1 == vert[face->v3].co)
- hit->flags |= BVH_ONQUAD;
}
t1 = t2;
@@ -184,6 +213,32 @@ static void mesh_faces_spherecast(void *userdata, int index, const BVHTreeRay *r
} while (t2);
}
+/* copy of function above */
+static void mesh_looptri_spherecast(void *userdata, int index, const BVHTreeRay *ray, BVHTreeRayHit *hit)
+{
+ const BVHTreeFromMesh *data = (BVHTreeFromMesh *) userdata;
+ const MVert *vert = data->vert;
+ const MLoopTri *lt = &data->looptri[index];
+ const float *vtri_co[3] = {
+ vert[data->loop[lt->tri[0]].v].co,
+ vert[data->loop[lt->tri[1]].v].co,
+ vert[data->loop[lt->tri[2]].v].co,
+ };
+ float dist;
+
+ if (data->sphere_radius == 0.0f)
+ dist = bvhtree_ray_tri_intersection(ray, hit->dist, UNPACK3(vtri_co));
+ else
+ dist = bvhtree_sphereray_tri_intersection(ray, data->sphere_radius, hit->dist, UNPACK3(vtri_co));
+
+ if (dist >= 0 && dist < hit->dist) {
+ hit->index = index;
+ hit->dist = dist;
+ madd_v3_v3v3fl(hit->co, ray->origin, ray->direction, dist);
+
+ normal_tri_v3(hit->no, UNPACK3(vtri_co));
+ }
+}
/* copy of function above (warning, should de-duplicate with editmesh_bvh.c) */
static void editmesh_faces_spherecast(void *userdata, int index, const BVHTreeRay *ray, BVHTreeRayHit *hit)
{
@@ -202,7 +257,7 @@ static void editmesh_faces_spherecast(void *userdata, int index, const BVHTreeRa
if (data->sphere_radius == 0.0f)
dist = bvhtree_ray_tri_intersection(ray, hit->dist, t0, t1, t2);
else
- dist = sphereray_tri_intersection(ray, data->sphere_radius, hit->dist, t0, t1, t2);
+ dist = bvhtree_sphereray_tri_intersection(ray, data->sphere_radius, hit->dist, t0, t1, t2);
if (dist >= 0 && dist < hit->dist) {
hit->index = index;
@@ -214,13 +269,13 @@ static void editmesh_faces_spherecast(void *userdata, int index, const BVHTreeRa
}
}
-/* Callback to bvh tree nearest point. The tree must bust have been built using bvhtree_from_mesh_edges.
+/* Callback to bvh tree nearest point. The tree must have been built using bvhtree_from_mesh_edges.
* userdata must be a BVHMeshCallbackUserdata built from the same mesh as the tree. */
static void mesh_edges_nearest_point(void *userdata, int index, const float co[3], BVHTreeNearest *nearest)
{
const BVHTreeFromMesh *data = (BVHTreeFromMesh *) userdata;
- MVert *vert = data->vert;
- MEdge *edge = data->edge + index;
+ const MVert *vert = data->vert;
+ const MEdge *edge = data->edge + index;
float nearest_tmp[3], dist_sq;
const float *t0, *t1;
@@ -239,10 +294,159 @@ static void mesh_edges_nearest_point(void *userdata, int index, const float co[3
}
}
+/* Helper, does all the point-spherecast work actually. */
+static void mesh_verts_spherecast_do(
+ const BVHTreeFromMesh *UNUSED(data), int index, const float v[3], const BVHTreeRay *ray, BVHTreeRayHit *hit)
+{
+ float dist;
+ const float *r1;
+ float r2[3], i1[3];
+ r1 = ray->origin;
+ add_v3_v3v3(r2, r1, ray->direction);
+
+ closest_to_line_segment_v3(i1, v, r1, r2);
+
+ /* No hit if closest point is 'behind' the origin of the ray, or too far away from it. */
+ if ((dot_v3v3v3(r1, i1, r2) >= 0.0f) && ((dist = len_v3v3(r1, i1)) < hit->dist)) {
+ hit->index = index;
+ hit->dist = dist;
+ copy_v3_v3(hit->co, i1);
+ }
+}
+
+/* Callback to bvh tree raycast. The tree must have been built using bvhtree_from_mesh_verts.
+ * userdata must be a BVHMeshCallbackUserdata built from the same mesh as the tree. */
+static void mesh_verts_spherecast(void *userdata, int index, const BVHTreeRay *ray, BVHTreeRayHit *hit)
+{
+ const BVHTreeFromMesh *data = (BVHTreeFromMesh *)userdata;
+ const float *v = data->vert[index].co;
+
+ mesh_verts_spherecast_do(data, index, v, ray, hit);
+}
+
+/* Callback to bvh tree raycast. The tree must have been built using bvhtree_from_mesh_edges.
+ * userdata must be a BVHMeshCallbackUserdata built from the same mesh as the tree. */
+static void mesh_edges_spherecast(void *userdata, int index, const BVHTreeRay *ray, BVHTreeRayHit *hit)
+{
+ const BVHTreeFromMesh *data = (BVHTreeFromMesh *)userdata;
+ const MVert *vert = data->vert;
+ const MEdge *edge = &data->edge[index];
+
+ const float radius_sq = SQUARE(data->sphere_radius);
+ float dist;
+ const float *v1, *v2, *r1;
+ float r2[3], i1[3], i2[3];
+ v1 = vert[edge->v1].co;
+ v2 = vert[edge->v2].co;
+
+ /* In case we get a zero-length edge, handle it as a point! */
+ if (equals_v3v3(v1, v2)) {
+ mesh_verts_spherecast_do(data, index, v1, ray, hit);
+ return;
+ }
+
+ r1 = ray->origin;
+ add_v3_v3v3(r2, r1, ray->direction);
+
+ if (isect_line_line_v3(v1, v2, r1, r2, i1, i2)) {
+ /* No hit if intersection point is 'behind' the origin of the ray, or too far away from it. */
+ if ((dot_v3v3v3(r1, i2, r2) >= 0.0f) && ((dist = len_v3v3(r1, i2)) < hit->dist)) {
+ const float e_fac = line_point_factor_v3(i1, v1, v2);
+ if (e_fac < 0.0f) {
+ copy_v3_v3(i1, v1);
+ }
+ else if (e_fac > 1.0f) {
+ copy_v3_v3(i1, v2);
+ }
+ /* Ensure ray is really close enough from edge! */
+ if (len_squared_v3v3(i1, i2) <= radius_sq) {
+ hit->index = index;
+ hit->dist = dist;
+ copy_v3_v3(hit->co, i2);
+ }
+ }
+ }
+}
+
+/** \} */
+
/*
* BVH builders
*/
-/* Builds a bvh tree.. where nodes are the vertexs of the given mesh */
+
+
+/* -------------------------------------------------------------------- */
+
+/** \name Vertex Builder
+ * \{ */
+
+static BVHTree *bvhtree_from_mesh_verts_create_tree(
+ float epsilon, int tree_type, int axis,
+ MVert *vert, const int numVerts,
+ BLI_bitmap *mask, int numVerts_active)
+{
+ BVHTree *tree = NULL;
+ int i;
+
+ if (vert) {
+ if (mask && numVerts_active < 0) {
+ numVerts_active = 0;
+ for (i = 0; i < numVerts; i++) {
+ if (BLI_BITMAP_TEST_BOOL(mask, i)) {
+ numVerts_active++;
+ }
+ }
+ }
+ else if (!mask) {
+ numVerts_active = numVerts;
+ }
+
+ tree = BLI_bvhtree_new(numVerts_active, epsilon, tree_type, axis);
+
+ if (tree) {
+ for (i = 0; i < numVerts; i++) {
+ if (mask && !BLI_BITMAP_TEST_BOOL(mask, i)) {
+ continue;
+ }
+ BLI_bvhtree_insert(tree, i, vert[i].co, 1);
+ }
+
+ BLI_bvhtree_balance(tree);
+ }
+ }
+
+ return tree;
+}
+
+static void bvhtree_from_mesh_verts_setup_data(
+ BVHTreeFromMesh *data, BVHTree *tree, const bool is_cached, float epsilon,
+ MVert *vert, const bool vert_allocated)
+{
+ memset(data, 0, sizeof(*data));
+
+ if (tree) {
+ data->tree = tree;
+ data->cached = is_cached;
+
+ /* a NULL nearest callback works fine
+ * remember the min distance to point is the same as the min distance to BV of point */
+ data->nearest_callback = NULL;
+ data->raycast_callback = mesh_verts_spherecast;
+
+ data->vert = vert;
+ data->vert_allocated = vert_allocated;
+ //data->face = DM_get_tessface_array(dm, &data->face_allocated); /* XXX WHY???? */
+
+ data->sphere_radius = epsilon;
+ }
+ else {
+ if (vert_allocated) {
+ MEM_freeN(vert);
+ }
+ }
+}
+
+/* Builds a bvh tree where nodes are the vertices of the given dm */
BVHTree *bvhtree_from_mesh_verts(BVHTreeFromMesh *data, DerivedMesh *dm, float epsilon, int tree_type, int axis)
{
BVHTree *tree;
@@ -250,7 +454,7 @@ BVHTree *bvhtree_from_mesh_verts(BVHTreeFromMesh *data, DerivedMesh *dm, float e
bool vert_allocated;
BLI_rw_mutex_lock(&cache_rwlock, THREAD_LOCK_READ);
- tree = bvhcache_find(&dm->bvhCache, BVHTREE_FROM_VERTICES);
+ tree = bvhcache_find(&dm->bvhCache, BVHTREE_FROM_VERTS);
BLI_rw_mutex_unlock(&cache_rwlock);
vert = DM_get_vert_array(dm, &vert_allocated);
@@ -258,31 +462,100 @@ BVHTree *bvhtree_from_mesh_verts(BVHTreeFromMesh *data, DerivedMesh *dm, float e
/* Not in cache */
if (tree == NULL) {
BLI_rw_mutex_lock(&cache_rwlock, THREAD_LOCK_WRITE);
- tree = bvhcache_find(&dm->bvhCache, BVHTREE_FROM_VERTICES);
+ tree = bvhcache_find(&dm->bvhCache, BVHTREE_FROM_VERTS);
if (tree == NULL) {
- int i;
- int numVerts = dm->getNumVerts(dm);
+ tree = bvhtree_from_mesh_verts_create_tree(epsilon, tree_type, axis, vert, dm->getNumVerts(dm), NULL, -1);
+ if (tree) {
+ /* Save on cache for later use */
+ /* printf("BVHTree built and saved on cache\n"); */
+ bvhcache_insert(&dm->bvhCache, tree, BVHTREE_FROM_VERTS);
+ }
+ }
+ BLI_rw_mutex_unlock(&cache_rwlock);
+ }
+ else {
+ /* printf("BVHTree is already build, using cached tree\n"); */
+ }
+
+ /* Setup BVHTreeFromMesh */
+ bvhtree_from_mesh_verts_setup_data(data, tree, true, epsilon, vert, vert_allocated);
+
+ return data->tree;
+}
+
+/**
+ * Builds a bvh tree where nodes are the given vertices (note: does not copy given mverts!).
+ * \param vert_allocated if true, vert freeing will be done when freeing data.
+ * \param mask if not null, true elements give which vert to add to BVH tree.
+ * \param numVerts_active if >= 0, number of active verts to add to BVH tree (else will be computed from mask).
+ */
+BVHTree *bvhtree_from_mesh_verts_ex(
+ BVHTreeFromMesh *data, MVert *vert, const int numVerts, const bool vert_allocated,
+ BLI_bitmap *mask, int numVerts_active,
+ float epsilon, int tree_type, int axis)
+{
+ BVHTree *tree = bvhtree_from_mesh_verts_create_tree(epsilon, tree_type, axis, vert, numVerts, mask, numVerts_active);
+
+ /* Setup BVHTreeFromMesh */
+ bvhtree_from_mesh_verts_setup_data(data, tree, false, epsilon, vert, vert_allocated);
+
+ return data->tree;
+}
+
+/** \} */
+
+
+/* -------------------------------------------------------------------- */
+
+/** \name Edge Builder
+ * \{ */
+
+/* Builds a bvh tree where nodes are the edges of the given dm */
+BVHTree *bvhtree_from_mesh_edges(BVHTreeFromMesh *data, DerivedMesh *dm, float epsilon, int tree_type, int axis)
+{
+ BVHTree *tree;
+ MVert *vert;
+ MEdge *edge;
+ bool vert_allocated, edge_allocated;
+
+ BLI_rw_mutex_lock(&cache_rwlock, THREAD_LOCK_READ);
+ tree = bvhcache_find(&dm->bvhCache, BVHTREE_FROM_EDGES);
+ BLI_rw_mutex_unlock(&cache_rwlock);
- if (vert != NULL) {
- tree = BLI_bvhtree_new(numVerts, epsilon, tree_type, axis);
+ vert = DM_get_vert_array(dm, &vert_allocated);
+ edge = DM_get_edge_array(dm, &edge_allocated);
+ /* Not in cache */
+ if (tree == NULL) {
+ BLI_rw_mutex_lock(&cache_rwlock, THREAD_LOCK_WRITE);
+ tree = bvhcache_find(&dm->bvhCache, BVHTREE_FROM_EDGES);
+ if (tree == NULL) {
+ int i;
+ int numEdges = dm->getNumEdges(dm);
+
+ if (vert != NULL && edge != NULL) {
+ /* Create a bvh-tree of the given target */
+ tree = BLI_bvhtree_new(numEdges, epsilon, tree_type, axis);
if (tree != NULL) {
- for (i = 0; i < numVerts; i++) {
- BLI_bvhtree_insert(tree, i, vert[i].co, 1);
- }
+ for (i = 0; i < numEdges; i++) {
+ float co[2][3];
+ copy_v3_v3(co[0], vert[edge[i].v1].co);
+ copy_v3_v3(co[1], vert[edge[i].v2].co);
+ BLI_bvhtree_insert(tree, i, co[0], 2);
+ }
BLI_bvhtree_balance(tree);
/* Save on cache for later use */
-// printf("BVHTree built and saved on cache\n");
- bvhcache_insert(&dm->bvhCache, tree, BVHTREE_FROM_VERTICES);
+ /* printf("BVHTree built and saved on cache\n"); */
+ bvhcache_insert(&dm->bvhCache, tree, BVHTREE_FROM_EDGES);
}
}
}
BLI_rw_mutex_unlock(&cache_rwlock);
}
else {
-// printf("BVHTree is already build, using cached tree\n");
+ /* printf("BVHTree is already build, using cached tree\n"); */
}
@@ -293,14 +566,13 @@ BVHTree *bvhtree_from_mesh_verts(BVHTreeFromMesh *data, DerivedMesh *dm, float e
if (data->tree) {
data->cached = true;
- /* a NULL nearest callback works fine
- * remember the min distance to point is the same as the min distance to BV of point */
- data->nearest_callback = NULL;
- data->raycast_callback = NULL;
+ data->nearest_callback = mesh_edges_nearest_point;
+ data->raycast_callback = mesh_edges_spherecast;
data->vert = vert;
data->vert_allocated = vert_allocated;
- data->face = DM_get_tessface_array(dm, &data->face_allocated);
+ data->edge = edge;
+ data->edge_allocated = edge_allocated;
data->sphere_radius = epsilon;
}
@@ -308,19 +580,176 @@ BVHTree *bvhtree_from_mesh_verts(BVHTreeFromMesh *data, DerivedMesh *dm, float e
if (vert_allocated) {
MEM_freeN(vert);
}
+ if (edge_allocated) {
+ MEM_freeN(edge);
+ }
}
-
return data->tree;
}
-/* Builds a bvh tree.. where nodes are the faces of the given dm. */
+/** \} */
+
+
+/* -------------------------------------------------------------------- */
+
+/** \name Tessellated Face Builder
+ * \{ */
+
+static BVHTree *bvhtree_from_mesh_faces_create_tree(
+ float epsilon, int tree_type, int axis,
+ BMEditMesh *em, MVert *vert, MFace *face, const int numFaces,
+ BLI_bitmap *mask, int numFaces_active)
+{
+ BVHTree *tree = NULL;
+ int i;
+
+ if (numFaces) {
+ if (mask && numFaces_active < 0) {
+ numFaces_active = 0;
+ for (i = 0; i < numFaces; i++) {
+ if (BLI_BITMAP_TEST_BOOL(mask, i)) {
+ numFaces_active++;
+ }
+ }
+ }
+ else if (!mask) {
+ numFaces_active = numFaces;
+ }
+
+ /* Create a bvh-tree of the given target */
+ /* printf("%s: building BVH, total=%d\n", __func__, numFaces); */
+ tree = BLI_bvhtree_new(numFaces_active, epsilon, tree_type, axis);
+ if (tree) {
+ if (em) {
+ const struct BMLoop *(*looptris)[3] = (void *)em->looptris;
+
+ /* avoid double-up on face searches for quads-ngons */
+ bool insert_prev = false;
+ BMFace *f_prev = NULL;
+
+ /* data->em_evil is only set for snapping, and only for the mesh of the object
+ * which is currently open in edit mode. When set, the bvhtree should not contain
+ * faces that will interfere with snapping (e.g. faces that are hidden/selected
+ * or faces that have selected verts). */
+
+ /* Insert BMesh-tessellation triangles into the bvh tree, unless they are hidden
+ * and/or selected. Even if the faces themselves are not selected for the snapped
+ * transform, having a vertex selected means the face (and thus it's tessellated
+ * triangles) will be moving and will not be a good snap targets. */
+ for (i = 0; i < numFaces; i++) {
+ const BMLoop **ltri = looptris[i];
+ BMFace *f = ltri[0]->f;
+ bool insert = mask ? BLI_BITMAP_TEST_BOOL(mask, i) : true;
+
+ /* Start with the assumption the triangle should be included for snapping. */
+ if (f == f_prev) {
+ insert = insert_prev;
+ }
+ else if (insert) {
+ if (BM_elem_flag_test(f, BM_ELEM_SELECT) || BM_elem_flag_test(f, BM_ELEM_HIDDEN)) {
+ /* Don't insert triangles tessellated from faces that are hidden or selected */
+ insert = false;
+ }
+ else {
+ BMLoop *l_iter, *l_first;
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
+ if (BM_elem_flag_test(l_iter->v, BM_ELEM_SELECT)) {
+ /* Don't insert triangles tessellated from faces that have any selected verts */
+ insert = false;
+ break;
+ }
+ } while ((l_iter = l_iter->next) != l_first);
+ }
+
+ /* skip if face doesn't change */
+ f_prev = f;
+ insert_prev = insert;
+ }
+
+ if (insert) {
+ /* No reason found to block hit-testing the triangle for snap, so insert it now.*/
+ float co[3][3];
+ copy_v3_v3(co[0], ltri[0]->v->co);
+ copy_v3_v3(co[1], ltri[1]->v->co);
+ copy_v3_v3(co[2], ltri[2]->v->co);
+
+ BLI_bvhtree_insert(tree, i, co[0], 3);
+ }
+ }
+ }
+ else {
+ if (vert && face) {
+ for (i = 0; i < numFaces; i++) {
+ float co[4][3];
+ if (mask && !BLI_BITMAP_TEST_BOOL(mask, i)) {
+ continue;
+ }
+
+ copy_v3_v3(co[0], vert[face[i].v1].co);
+ copy_v3_v3(co[1], vert[face[i].v2].co);
+ copy_v3_v3(co[2], vert[face[i].v3].co);
+ if (face[i].v4)
+ copy_v3_v3(co[3], vert[face[i].v4].co);
+
+ BLI_bvhtree_insert(tree, i, co[0], face[i].v4 ? 4 : 3);
+ }
+ }
+ }
+ BLI_bvhtree_balance(tree);
+ }
+ }
+
+ return tree;
+}
+
+static void bvhtree_from_mesh_faces_setup_data(
+ BVHTreeFromMesh *data, BVHTree *tree, const bool is_cached,
+ float epsilon, BMEditMesh *em,
+ MVert *vert, const bool vert_allocated,
+ MFace *face, const bool face_allocated)
+{
+ memset(data, 0, sizeof(*data));
+ data->em_evil = em;
+
+ if (tree) {
+ data->tree = tree;
+ data->cached = is_cached;
+
+ if (em) {
+ data->nearest_callback = editmesh_faces_nearest_point;
+ data->raycast_callback = editmesh_faces_spherecast;
+ }
+ else {
+ data->nearest_callback = mesh_faces_nearest_point;
+ data->raycast_callback = mesh_faces_spherecast;
+
+ data->vert = vert;
+ data->vert_allocated = vert_allocated;
+ data->face = face;
+ data->face_allocated = face_allocated;
+ }
+
+ data->sphere_radius = epsilon;
+ }
+ else {
+ if (vert_allocated) {
+ MEM_freeN(vert);
+ }
+ if (face_allocated) {
+ MEM_freeN(face);
+ }
+ }
+}
+
+/* Builds a bvh tree where nodes are the tesselated faces of the given dm */
BVHTree *bvhtree_from_mesh_faces(BVHTreeFromMesh *data, DerivedMesh *dm, float epsilon, int tree_type, int axis)
{
BMEditMesh *em = data->em_evil;
const int bvhcache_type = em ? BVHTREE_FROM_FACES_EDITMESH : BVHTREE_FROM_FACES;
BVHTree *tree;
- MVert *vert;
- MFace *face;
+ MVert *vert = NULL;
+ MFace *face = NULL;
bool vert_allocated = false, face_allocated = false;
BLI_rw_mutex_lock(&cache_rwlock, THREAD_LOCK_READ);
@@ -337,7 +766,6 @@ BVHTree *bvhtree_from_mesh_faces(BVHTreeFromMesh *data, DerivedMesh *dm, float e
BLI_rw_mutex_lock(&cache_rwlock, THREAD_LOCK_WRITE);
tree = bvhcache_find(&dm->bvhCache, bvhcache_type);
if (tree == NULL) {
- int i;
int numFaces;
/* BMESH specific check that we have tessfaces,
@@ -353,232 +781,337 @@ BVHTree *bvhtree_from_mesh_faces(BVHTreeFromMesh *data, DerivedMesh *dm, float e
BLI_assert(!(numFaces == 0 && dm->getNumPolys(dm) != 0));
}
- if (numFaces != 0) {
- /* Create a bvh-tree of the given target */
- // printf("%s: building BVH, total=%d\n", __func__, numFaces);
- tree = BLI_bvhtree_new(numFaces, epsilon, tree_type, axis);
- if (tree != NULL) {
- if (em) {
- const struct BMLoop *(*looptris)[3] = (void *)em->looptris;
-
- /* avoid double-up on face searches for quads-ngons */
- bool insert_prev = false;
- BMFace *f_prev = NULL;
-
- /* data->em_evil is only set for snapping, and only for the mesh of the object
- * which is currently open in edit mode. When set, the bvhtree should not contain
- * faces that will interfere with snapping (e.g. faces that are hidden/selected
- * or faces that have selected verts).*/
-
- /* Insert BMesh-tessellation triangles into the bvh tree, unless they are hidden
- * and/or selected. Even if the faces themselves are not selected for the snapped
- * transform, having a vertex selected means the face (and thus it's tessellated
- * triangles) will be moving and will not be a good snap targets.*/
- for (i = 0; i < em->tottri; i++) {
- const BMLoop **ltri = looptris[i];
- BMFace *f = ltri[0]->f;
- bool insert;
-
- /* Start with the assumption the triangle should be included for snapping. */
- if (f == f_prev) {
- insert = insert_prev;
- }
- else {
- if (BM_elem_flag_test(f, BM_ELEM_SELECT) || BM_elem_flag_test(f, BM_ELEM_HIDDEN)) {
- /* Don't insert triangles tessellated from faces that are hidden
- * or selected*/
+ tree = bvhtree_from_mesh_faces_create_tree(epsilon, tree_type, axis, em, vert, face, numFaces, NULL, -1);
+ if (tree) {
+ /* Save on cache for later use */
+ /* printf("BVHTree built and saved on cache\n"); */
+ bvhcache_insert(&dm->bvhCache, tree, bvhcache_type);
+ }
+ }
+ BLI_rw_mutex_unlock(&cache_rwlock);
+ }
+ else {
+ /* printf("BVHTree is already build, using cached tree\n"); */
+ }
+
+ /* Setup BVHTreeFromMesh */
+ bvhtree_from_mesh_faces_setup_data(data, tree, true, epsilon, em, vert, vert_allocated, face, face_allocated);
+
+ return data->tree;
+}
+
+/**
+ * Builds a bvh tree where nodes are the given tessellated faces (note: does not copy given mfaces!).
+ * \param vert_allocated if true, vert freeing will be done when freeing data.
+ * \param face_allocated if true, face freeing will be done when freeing data.
+ * \param mask if not null, true elements give which faces to add to BVH tree.
+ * \param numFaces_active if >= 0, number of active faces to add to BVH tree (else will be computed from mask).
+ */
+BVHTree *bvhtree_from_mesh_faces_ex(
+ BVHTreeFromMesh *data, MVert *vert, const bool vert_allocated,
+ MFace *face, const int numFaces, const bool face_allocated,
+ BLI_bitmap *mask, int numFaces_active, float epsilon, int tree_type, int axis)
+{
+ BVHTree *tree = bvhtree_from_mesh_faces_create_tree(
+ epsilon, tree_type, axis, NULL, vert, face, numFaces,
+ mask, numFaces_active);
+
+ /* Setup BVHTreeFromMesh */
+ bvhtree_from_mesh_faces_setup_data(data, tree, false, epsilon, NULL, vert, vert_allocated, face, face_allocated);
+
+ return data->tree;
+}
+
+/** \} */
+
+
+/* -------------------------------------------------------------------- */
+
+/** \name LoopTri Face Builder
+ * \{ */
+
+static BVHTree *bvhtree_from_mesh_looptri_create_tree(
+ float epsilon, int tree_type, int axis,
+ BMEditMesh *em, const MVert *vert, const MLoop *mloop, const MLoopTri *looptri, const int looptri_num,
+ BLI_bitmap *mask, int looptri_num_active)
+{
+ BVHTree *tree = NULL;
+ int i;
+
+ if (looptri_num) {
+ if (mask && looptri_num_active < 0) {
+ looptri_num_active = 0;
+ for (i = 0; i < looptri_num; i++) {
+ if (BLI_BITMAP_TEST_BOOL(mask, i)) {
+ looptri_num_active++;
+ }
+ }
+ }
+ else if (!mask) {
+ looptri_num_active = looptri_num;
+ }
+
+ /* Create a bvh-tree of the given target */
+ /* printf("%s: building BVH, total=%d\n", __func__, numFaces); */
+ tree = BLI_bvhtree_new(looptri_num_active, epsilon, tree_type, axis);
+ if (tree) {
+ if (em) {
+ const struct BMLoop *(*looptris)[3] = (void *)em->looptris;
+
+ /* avoid double-up on face searches for quads-ngons */
+ bool insert_prev = false;
+ BMFace *f_prev = NULL;
+
+ /* data->em_evil is only set for snapping, and only for the mesh of the object
+ * which is currently open in edit mode. When set, the bvhtree should not contain
+ * faces that will interfere with snapping (e.g. faces that are hidden/selected
+ * or faces that have selected verts). */
+
+ /* Insert BMesh-tessellation triangles into the bvh tree, unless they are hidden
+ * and/or selected. Even if the faces themselves are not selected for the snapped
+ * transform, having a vertex selected means the face (and thus it's tessellated
+ * triangles) will be moving and will not be a good snap targets. */
+ for (i = 0; i < looptri_num; i++) {
+ const BMLoop **ltri = looptris[i];
+ BMFace *f = ltri[0]->f;
+ bool insert = mask ? BLI_BITMAP_TEST_BOOL(mask, i) : true;
+
+ /* Start with the assumption the triangle should be included for snapping. */
+ if (f == f_prev) {
+ insert = insert_prev;
+ }
+ else if (insert) {
+ if (BM_elem_flag_test(f, BM_ELEM_SELECT) || BM_elem_flag_test(f, BM_ELEM_HIDDEN)) {
+ /* Don't insert triangles tessellated from faces that are hidden or selected */
+ insert = false;
+ }
+ else {
+ BMLoop *l_iter, *l_first;
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
+ if (BM_elem_flag_test(l_iter->v, BM_ELEM_SELECT)) {
+ /* Don't insert triangles tessellated from faces that have any selected verts */
insert = false;
+ break;
}
- else {
- BMLoop *l_iter, *l_first;
- insert = true;
- l_iter = l_first = BM_FACE_FIRST_LOOP(f);
- do {
- if (BM_elem_flag_test(l_iter->v, BM_ELEM_SELECT)) {
- /* Don't insert triangles tessellated from faces that have
- * any selected verts.*/
- insert = false;
- break;
- }
- } while ((l_iter = l_iter->next) != l_first);
- }
-
- /* skip if face doesn't change */
- f_prev = f;
- insert_prev = insert;
- }
-
- if (insert) {
- /* No reason found to block hit-testing the triangle for snap,
- * so insert it now.*/
- float co[3][3];
- copy_v3_v3(co[0], ltri[0]->v->co);
- copy_v3_v3(co[1], ltri[1]->v->co);
- copy_v3_v3(co[2], ltri[2]->v->co);
-
- BLI_bvhtree_insert(tree, i, co[0], 3);
- }
+ } while ((l_iter = l_iter->next) != l_first);
}
+
+ /* skip if face doesn't change */
+ f_prev = f;
+ insert_prev = insert;
}
- else {
- if (vert != NULL && face != NULL) {
- for (i = 0; i < numFaces; i++) {
- float co[4][3];
- copy_v3_v3(co[0], vert[face[i].v1].co);
- copy_v3_v3(co[1], vert[face[i].v2].co);
- copy_v3_v3(co[2], vert[face[i].v3].co);
- if (face[i].v4)
- copy_v3_v3(co[3], vert[face[i].v4].co);
-
- BLI_bvhtree_insert(tree, i, co[0], face[i].v4 ? 4 : 3);
- }
- }
+
+ if (insert) {
+ /* No reason found to block hit-testing the triangle for snap, so insert it now.*/
+ float co[3][3];
+ copy_v3_v3(co[0], ltri[0]->v->co);
+ copy_v3_v3(co[1], ltri[1]->v->co);
+ copy_v3_v3(co[2], ltri[2]->v->co);
+
+ BLI_bvhtree_insert(tree, i, co[0], 3);
}
- BLI_bvhtree_balance(tree);
+ }
+ }
+ else {
+ if (vert && looptri) {
+ for (i = 0; i < looptri_num; i++) {
+ float co[3][3];
+ if (mask && !BLI_BITMAP_TEST_BOOL(mask, i)) {
+ continue;
+ }
- /* Save on cache for later use */
-// printf("BVHTree built and saved on cache\n");
- bvhcache_insert(&dm->bvhCache, tree, bvhcache_type);
+ copy_v3_v3(co[0], vert[mloop[looptri[i].tri[0]].v].co);
+ copy_v3_v3(co[1], vert[mloop[looptri[i].tri[1]].v].co);
+ copy_v3_v3(co[2], vert[mloop[looptri[i].tri[2]].v].co);
+
+ BLI_bvhtree_insert(tree, i, co[0], 3);
+ }
}
}
+ BLI_bvhtree_balance(tree);
}
- BLI_rw_mutex_unlock(&cache_rwlock);
- }
- else {
-// printf("BVHTree is already build, using cached tree\n");
}
+ return tree;
+}
- /* Setup BVHTreeFromMesh */
+static void bvhtree_from_mesh_looptri_setup_data(
+ BVHTreeFromMesh *data, BVHTree *tree, const bool is_cached,
+ float epsilon, BMEditMesh *em,
+ const MVert *vert, const bool vert_allocated,
+ const MLoop *mloop, const bool loop_allocated,
+ const MLoopTri *looptri, const bool looptri_allocated)
+{
memset(data, 0, sizeof(*data));
- data->tree = tree;
data->em_evil = em;
- if (data->tree) {
- data->cached = true;
+ if (tree) {
+ data->tree = tree;
+ data->cached = is_cached;
if (em) {
data->nearest_callback = editmesh_faces_nearest_point;
data->raycast_callback = editmesh_faces_spherecast;
}
else {
- data->nearest_callback = mesh_faces_nearest_point;
- data->raycast_callback = mesh_faces_spherecast;
+ data->nearest_callback = mesh_looptri_nearest_point;
+ data->raycast_callback = mesh_looptri_spherecast;
data->vert = vert;
data->vert_allocated = vert_allocated;
- data->face = face;
- data->face_allocated = face_allocated;
+ data->loop = mloop;
+ data->loop_allocated = loop_allocated;
+ data->looptri = looptri;
+ data->looptri_allocated = looptri_allocated;
}
data->sphere_radius = epsilon;
}
else {
if (vert_allocated) {
- MEM_freeN(vert);
+ MEM_freeN((void *)vert);
}
- if (face_allocated) {
- MEM_freeN(face);
+ if (looptri_allocated) {
+ MEM_freeN((void *)looptri);
}
}
-
- return data->tree;
-
}
-/* Builds a bvh tree.. where nodes are the faces of the given dm. */
-BVHTree *bvhtree_from_mesh_edges(BVHTreeFromMesh *data, DerivedMesh *dm, float epsilon, int tree_type, int axis)
+/**
+ * Builds a bvh tree where nodes are the looptri faces of the given dm
+ *
+ * \note for editmesh this is currently a duplicate of bvhtree_from_mesh_faces
+ */
+BVHTree *bvhtree_from_mesh_looptri(BVHTreeFromMesh *data, DerivedMesh *dm, float epsilon, int tree_type, int axis)
{
+ BMEditMesh *em = data->em_evil;
+ const int bvhcache_type = em ? BVHTREE_FROM_FACES_EDITMESH : BVHTREE_FROM_LOOPTRI;
BVHTree *tree;
- MVert *vert;
- MEdge *edge;
- bool vert_allocated, edge_allocated;
+ MVert *mvert = NULL;
+ MLoop *mloop = NULL;
+ const MLoopTri *looptri = NULL;
+ bool vert_allocated = false;
+ bool loop_allocated = false;
+ bool looptri_allocated = false;
BLI_rw_mutex_lock(&cache_rwlock, THREAD_LOCK_READ);
- tree = bvhcache_find(&dm->bvhCache, BVHTREE_FROM_EDGES);
+ tree = bvhcache_find(&dm->bvhCache, bvhcache_type);
BLI_rw_mutex_unlock(&cache_rwlock);
- vert = DM_get_vert_array(dm, &vert_allocated);
- edge = DM_get_edge_array(dm, &edge_allocated);
+ if (em == NULL) {
+ MPoly *mpoly;
+ bool poly_allocated = false;
+
+ mvert = DM_get_vert_array(dm, &vert_allocated);
+ mpoly = DM_get_poly_array(dm, &poly_allocated);
+
+ mloop = DM_get_loop_array(dm, &loop_allocated);
+ looptri = DM_get_looptri_array(
+ dm,
+ mvert,
+ mpoly, dm->getNumPolys(dm),
+ mloop, dm->getNumLoops(dm),
+ &looptri_allocated);
+
+ if (poly_allocated) {
+ MEM_freeN(mpoly);
+ }
+
+ }
/* Not in cache */
if (tree == NULL) {
BLI_rw_mutex_lock(&cache_rwlock, THREAD_LOCK_WRITE);
- tree = bvhcache_find(&dm->bvhCache, BVHTREE_FROM_EDGES);
+ tree = bvhcache_find(&dm->bvhCache, bvhcache_type);
if (tree == NULL) {
- int i;
- int numEdges = dm->getNumEdges(dm);
+ int looptri_num;
- if (vert != NULL && edge != NULL) {
- /* Create a bvh-tree of the given target */
- tree = BLI_bvhtree_new(numEdges, epsilon, tree_type, axis);
- if (tree != NULL) {
- for (i = 0; i < numEdges; i++) {
- float co[4][3];
- copy_v3_v3(co[0], vert[edge[i].v1].co);
- copy_v3_v3(co[1], vert[edge[i].v2].co);
-
- BLI_bvhtree_insert(tree, i, co[0], 2);
- }
- BLI_bvhtree_balance(tree);
+ /* BMESH specific check that we have tessfaces,
+ * we _could_ tessellate here but rather not - campbell
+ *
+ * this assert checks we have tessfaces,
+ * if not caller should use DM_ensure_tessface() */
+ if (em) {
+ looptri_num = em->tottri;
+ }
+ else {
+ looptri_num = dm->getNumLoopTri(dm);
+ BLI_assert(!(looptri_num == 0 && dm->getNumPolys(dm) != 0));
+ }
- /* Save on cache for later use */
-// printf("BVHTree built and saved on cache\n");
- bvhcache_insert(&dm->bvhCache, tree, BVHTREE_FROM_EDGES);
- }
+ tree = bvhtree_from_mesh_looptri_create_tree(
+ epsilon, tree_type, axis, em,
+ mvert, mloop, looptri, looptri_num, NULL, -1);
+ if (tree) {
+ /* Save on cache for later use */
+ /* printf("BVHTree built and saved on cache\n"); */
+ bvhcache_insert(&dm->bvhCache, tree, bvhcache_type);
}
}
BLI_rw_mutex_unlock(&cache_rwlock);
}
else {
-// printf("BVHTree is already build, using cached tree\n");
+ /* printf("BVHTree is already build, using cached tree\n"); */
}
-
/* Setup BVHTreeFromMesh */
- memset(data, 0, sizeof(*data));
- data->tree = tree;
+ bvhtree_from_mesh_looptri_setup_data(
+ data, tree, true, epsilon, em,
+ mvert, vert_allocated,
+ mloop, loop_allocated,
+ looptri, looptri_allocated);
- if (data->tree) {
- data->cached = true;
+ return data->tree;
+}
- data->nearest_callback = mesh_edges_nearest_point;
- data->raycast_callback = NULL;
+BVHTree *bvhtree_from_mesh_looptri_ex(
+ BVHTreeFromMesh *data,
+ const struct MVert *vert, const bool vert_allocated,
+ const struct MLoop *mloop, const bool loop_allocated,
+ const struct MLoopTri *looptri, const int looptri_num, const bool looptri_allocated,
+ BLI_bitmap *mask, int looptri_num_active,
+ float epsilon, int tree_type, int axis)
+{
+ BVHTree *tree = bvhtree_from_mesh_looptri_create_tree(
+ epsilon, tree_type, axis, NULL, vert, mloop, looptri, looptri_num,
+ mask, looptri_num_active);
- data->vert = vert;
- data->vert_allocated = vert_allocated;
- data->edge = edge;
- data->edge_allocated = edge_allocated;
+ /* Setup BVHTreeFromMesh */
+ bvhtree_from_mesh_looptri_setup_data(
+ data, tree, false, epsilon, NULL,
+ vert, vert_allocated,
+ mloop, loop_allocated,
+ looptri, looptri_allocated);
- data->sphere_radius = epsilon;
- }
- else {
- if (vert_allocated) {
- MEM_freeN(vert);
- }
- if (edge_allocated) {
- MEM_freeN(edge);
- }
- }
return data->tree;
-
}
+/** \} */
+
+
/* Frees data allocated by a call to bvhtree_from_mesh_*. */
void free_bvhtree_from_mesh(struct BVHTreeFromMesh *data)
{
if (data->tree) {
- if (!data->cached)
+ if (!data->cached) {
BLI_bvhtree_free(data->tree);
+ }
if (data->vert_allocated) {
- MEM_freeN(data->vert);
+ MEM_freeN((void *)data->vert);
}
if (data->edge_allocated) {
- MEM_freeN(data->edge);
+ MEM_freeN((void *)data->edge);
}
if (data->face_allocated) {
- MEM_freeN(data->face);
+ MEM_freeN((void *)data->face);
+ }
+ if (data->loop_allocated) {
+ MEM_freeN((void *)data->loop);
+ }
+ if (data->looptri_allocated) {
+ MEM_freeN((void *)data->looptri);
}
memset(data, 0, sizeof(*data));
@@ -586,7 +1119,11 @@ void free_bvhtree_from_mesh(struct BVHTreeFromMesh *data)
}
-/* BVHCache */
+/* -------------------------------------------------------------------- */
+
+/** \name BVHCache
+ * \{ */
+
typedef struct BVHCacheItem {
int type;
BVHTree *tree;
@@ -650,4 +1187,4 @@ void bvhcache_free(BVHCache *cache)
*cache = NULL;
}
-
+/** \} */
diff --git a/source/blender/blenkernel/intern/camera.c b/source/blender/blenkernel/intern/camera.c
index 1402f62291f..7e043df2808 100644
--- a/source/blender/blenkernel/intern/camera.c
+++ b/source/blender/blenkernel/intern/camera.c
@@ -30,14 +30,18 @@
*/
#include <stdlib.h>
+#include <stddef.h>
#include "DNA_camera_types.h"
#include "DNA_lamp_types.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
#include "DNA_view3d_types.h"
+#include "DNA_ID.h"
#include "BLI_math.h"
+#include "BLI_rect.h"
+#include "BLI_string.h"
#include "BLI_utildefines.h"
#include "BKE_animsys.h"
@@ -46,8 +50,11 @@
#include "BKE_global.h"
#include "BKE_library.h"
#include "BKE_main.h"
+#include "BKE_scene.h"
#include "BKE_screen.h"
+#include "GPU_compositing.h"
+
/****************************** Camera Datablock *****************************/
void *BKE_camera_add(Main *bmain, const char *name)
@@ -65,7 +72,13 @@ void *BKE_camera_add(Main *bmain, const char *name)
cam->ortho_scale = 6.0;
cam->flag |= CAM_SHOWPASSEPARTOUT;
cam->passepartalpha = 0.5f;
-
+
+ GPU_fx_compositor_init_dof_settings(&cam->gpu_dof);
+
+ /* stereoscopy 3d */
+ cam->stereo.interocular_distance = 0.065f;
+ cam->stereo.convergence_distance = 30.f * 0.065f;
+
return cam;
}
@@ -77,6 +90,10 @@ Camera *BKE_camera_copy(Camera *cam)
id_lib_extern((ID *)camn->dof_ob);
+ if (cam->id.lib) {
+ BKE_id_lib_local_paths(G.main, cam->id.lib, &camn->id);
+ }
+
return camn;
}
@@ -129,7 +146,7 @@ void BKE_camera_make_local(Camera *cam)
void BKE_camera_free(Camera *ca)
{
- BKE_free_animdata((ID *)ca);
+ BKE_animdata_free((ID *)ca);
}
/******************************** Camera Usage *******************************/
@@ -152,15 +169,15 @@ float BKE_camera_object_dof_distance(Object *ob)
if (ob->type != OB_CAMERA)
return 0.0f;
if (cam->dof_ob) {
- /* too simple, better to return the distance on the view axis only
- * return len_v3v3(ob->obmat[3], cam->dof_ob->obmat[3]); */
- float mat[4][4], imat[4][4], obmat[4][4];
-
- copy_m4_m4(obmat, ob->obmat);
- normalize_m4(obmat);
- invert_m4_m4(imat, obmat);
- mul_m4_m4m4(mat, imat, cam->dof_ob->obmat);
- return fabsf(mat[3][2]);
+#if 0
+ /* too simple, better to return the distance on the view axis only */
+ return len_v3v3(ob->obmat[3], cam->dof_ob->obmat[3]);
+#else
+ float view_dir[3], dof_dir[3];
+ normalize_v3_v3(view_dir, ob->obmat[2]);
+ sub_v3_v3v3(dof_dir, ob->obmat[3], cam->dof_ob->obmat[3]);
+ return fabsf(dot_v3v3(view_dir, dof_dir));
+#endif
}
return cam->YF_dofdist;
}
@@ -204,7 +221,7 @@ void BKE_camera_params_init(CameraParams *params)
params->clipend = 100.0f;
}
-void BKE_camera_params_from_object(CameraParams *params, Object *ob)
+void BKE_camera_params_from_object(CameraParams *params, const Object *ob)
{
if (!ob)
return;
@@ -246,7 +263,7 @@ void BKE_camera_params_from_object(CameraParams *params, Object *ob)
}
}
-void BKE_camera_params_from_view3d(CameraParams *params, View3D *v3d, RegionView3D *rv3d)
+void BKE_camera_params_from_view3d(CameraParams *params, const View3D *v3d, const RegionView3D *rv3d)
{
/* common */
params->lens = v3d->lens;
@@ -257,7 +274,7 @@ void BKE_camera_params_from_view3d(CameraParams *params, View3D *v3d, RegionView
/* camera view */
BKE_camera_params_from_object(params, v3d->camera);
- params->zoom = BKE_screen_view3d_zoom_to_fac((float)rv3d->camzoom);
+ params->zoom = BKE_screen_view3d_zoom_to_fac(rv3d->camzoom);
params->offsetx = 2.0f * rv3d->camdx * params->zoom;
params->offsety = 2.0f * rv3d->camdy * params->zoom;
@@ -265,7 +282,7 @@ void BKE_camera_params_from_view3d(CameraParams *params, View3D *v3d, RegionView
params->shiftx *= params->zoom;
params->shifty *= params->zoom;
- params->zoom = 1.0f / params->zoom;
+ params->zoom = CAMERA_PARAM_ZOOM_INIT_CAMOB / params->zoom;
}
else if (rv3d->persp == RV3D_ORTHO) {
/* orthographic view */
@@ -274,13 +291,13 @@ void BKE_camera_params_from_view3d(CameraParams *params, View3D *v3d, RegionView
params->clipsta = -params->clipend;
params->is_ortho = true;
- /* make sure any changes to this match ED_view3d_radius_to_ortho_dist() */
+ /* make sure any changes to this match ED_view3d_radius_to_dist_ortho() */
params->ortho_scale = rv3d->dist * sensor_size / v3d->lens;
- params->zoom = 2.0f;
+ params->zoom = CAMERA_PARAM_ZOOM_INIT_PERSP;
}
else {
/* perspective view */
- params->zoom = 2.0f;
+ params->zoom = CAMERA_PARAM_ZOOM_INIT_PERSP;
}
}
@@ -375,8 +392,10 @@ void BKE_camera_params_compute_matrix(CameraParams *params)
/***************************** Camera View Frame *****************************/
-void BKE_camera_view_frame_ex(Scene *scene, Camera *camera, float drawsize, const bool do_clip, const float scale[3],
- float r_asp[2], float r_shift[2], float *r_drawsize, float r_vec[4][3])
+void BKE_camera_view_frame_ex(
+ const Scene *scene, const Camera *camera,
+ const float drawsize, const bool do_clip, const float scale[3],
+ float r_asp[2], float r_shift[2], float *r_drawsize, float r_vec[4][3])
{
float facx, facy;
float depth;
@@ -423,8 +442,8 @@ void BKE_camera_view_frame_ex(Scene *scene, Camera *camera, float drawsize, cons
*r_drawsize = 1.0f;
depth = -(camera->clipsta + 0.1f) * scale[2];
fac = depth / (camera->lens / (-half_sensor));
- scale_x = 1.0f;
- scale_y = 1.0f;
+ scale_x = scale[0] / scale[2];
+ scale_y = scale[1] / scale[2];
}
else {
/* fixed size, variable depth (stays a reasonable size in the 3D view) */
@@ -447,24 +466,32 @@ void BKE_camera_view_frame_ex(Scene *scene, Camera *camera, float drawsize, cons
r_vec[3][0] = r_shift[0] - facx; r_vec[3][1] = r_shift[1] + facy; r_vec[3][2] = depth;
}
-void BKE_camera_view_frame(Scene *scene, Camera *camera, float r_vec[4][3])
+void BKE_camera_view_frame(const Scene *scene, const Camera *camera, float r_vec[4][3])
{
float dummy_asp[2];
float dummy_shift[2];
float dummy_drawsize;
const float dummy_scale[3] = {1.0f, 1.0f, 1.0f};
- BKE_camera_view_frame_ex(scene, camera, false, 1.0, dummy_scale,
+ BKE_camera_view_frame_ex(scene, camera, 0.0, true, dummy_scale,
dummy_asp, dummy_shift, &dummy_drawsize, r_vec);
}
+#define CAMERA_VIEWFRAME_NUM_PLANES 4
typedef struct CameraViewFrameData {
- float plane_tx[4][4]; /* 4 planes (not 4x4 matrix)*/
- float frame_tx[4][3];
- float normal_tx[4][3];
- float dist_vals_sq[4]; /* distance squared (signed) */
+ float plane_tx[CAMERA_VIEWFRAME_NUM_PLANES][4]; /* 4 planes */
+ float normal_tx[CAMERA_VIEWFRAME_NUM_PLANES][3];
+ float dist_vals_sq[CAMERA_VIEWFRAME_NUM_PLANES]; /* distance squared (signed) */
unsigned int tot;
+
+ /* Ortho camera only. */
+ bool is_ortho;
+ float camera_no[3];
+ float dist_to_cam;
+
+ /* Not used by callbacks... */
+ float camera_rotmat[3][3];
} CameraViewFrameData;
static void camera_to_frame_view_cb(const float co[3], void *user_data)
@@ -472,67 +499,108 @@ static void camera_to_frame_view_cb(const float co[3], void *user_data)
CameraViewFrameData *data = (CameraViewFrameData *)user_data;
unsigned int i;
- for (i = 0; i < 4; i++) {
- float nd = dist_signed_squared_to_plane_v3(co, data->plane_tx[i]);
- if (nd < data->dist_vals_sq[i]) {
- data->dist_vals_sq[i] = nd;
- }
+ for (i = 0; i < CAMERA_VIEWFRAME_NUM_PLANES; i++) {
+ const float nd = dist_signed_squared_to_plane_v3(co, data->plane_tx[i]);
+ CLAMP_MAX(data->dist_vals_sq[i], nd);
+ }
+
+ if (data->is_ortho) {
+ const float d = dot_v3v3(data->camera_no, co);
+ CLAMP_MAX(data->dist_to_cam, d);
}
data->tot++;
}
-/* don't move the camera, just yield the fit location */
-/* only valid for perspective cameras */
-bool BKE_camera_view_frame_fit_to_scene(Scene *scene, struct View3D *v3d, Object *camera_ob, float r_co[3])
+static void camera_frame_fit_data_init(
+ const Scene *scene, const Object *ob,
+ CameraParams *params, CameraViewFrameData *data)
{
- float shift[2];
- float plane_tx[4][3];
- float rot_obmat[3][3];
- const float zero[3] = {0, 0, 0};
- CameraViewFrameData data_cb;
-
+ float camera_rotmat_transposed_inversed[4][4];
unsigned int i;
- BKE_camera_view_frame(scene, camera_ob->data, data_cb.frame_tx);
+ /* setup parameters */
+ BKE_camera_params_init(params);
+ BKE_camera_params_from_object(params, ob);
- copy_m3_m4(rot_obmat, camera_ob->obmat);
- normalize_m3(rot_obmat);
-
- for (i = 0; i < 4; i++) {
- /* normalize so Z is always 1.0f*/
- mul_v3_fl(data_cb.frame_tx[i], 1.0f / data_cb.frame_tx[i][2]);
+ /* compute matrix, viewplane, .. */
+ if (scene) {
+ BKE_camera_params_compute_viewplane(params, scene->r.xsch, scene->r.ysch, scene->r.xasp, scene->r.yasp);
}
+ else {
+ BKE_camera_params_compute_viewplane(params, 1, 1, 1.0f, 1.0f);
+ }
+ BKE_camera_params_compute_matrix(params);
- /* get the shift back out of the frame */
- shift[0] = (data_cb.frame_tx[0][0] +
- data_cb.frame_tx[1][0] +
- data_cb.frame_tx[2][0] +
- data_cb.frame_tx[3][0]) / 4.0f;
- shift[1] = (data_cb.frame_tx[0][1] +
- data_cb.frame_tx[1][1] +
- data_cb.frame_tx[2][1] +
- data_cb.frame_tx[3][1]) / 4.0f;
-
- for (i = 0; i < 4; i++) {
- mul_m3_v3(rot_obmat, data_cb.frame_tx[i]);
+ /* initialize callback data */
+ copy_m3_m4(data->camera_rotmat, (float (*)[4])ob->obmat);
+ normalize_m3(data->camera_rotmat);
+ /* To transform a plane which is in its homogeneous representation (4d vector),
+ * we need the inverse of the transpose of the transform matrix... */
+ copy_m4_m3(camera_rotmat_transposed_inversed, data->camera_rotmat);
+ transpose_m4(camera_rotmat_transposed_inversed);
+ invert_m4(camera_rotmat_transposed_inversed);
+
+ /* Extract frustum planes from projection matrix. */
+ planes_from_projmat(params->winmat,
+ /* left right top bottom near far */
+ data->plane_tx[2], data->plane_tx[0], data->plane_tx[3], data->plane_tx[1], NULL, NULL);
+
+ /* Rotate planes and get normals from them */
+ for (i = 0; i < CAMERA_VIEWFRAME_NUM_PLANES; i++) {
+ mul_m4_v4(camera_rotmat_transposed_inversed, data->plane_tx[i]);
+ normalize_v3_v3(data->normal_tx[i], data->plane_tx[i]);
}
- for (i = 0; i < 4; i++) {
- normal_tri_v3(data_cb.normal_tx[i], zero, data_cb.frame_tx[i], data_cb.frame_tx[(i + 1) % 4]);
- plane_from_point_normal_v3(data_cb.plane_tx[i], data_cb.frame_tx[i], data_cb.normal_tx[i]);
+ copy_v4_fl(data->dist_vals_sq, FLT_MAX);
+ data->tot = 0;
+ data->is_ortho = params->is_ortho;
+ if (params->is_ortho) {
+ /* we want (0, 0, -1) transformed by camera_rotmat, this is a quicker shortcut. */
+ negate_v3_v3(data->camera_no, data->camera_rotmat[2]);
+ data->dist_to_cam = FLT_MAX;
}
+}
- /* initialize callback data */
- copy_v4_fl(data_cb.dist_vals_sq, FLT_MAX);
- data_cb.tot = 0;
- /* run callback on all visible points */
- BKE_scene_foreach_display_point(scene, v3d, BA_SELECT,
- camera_to_frame_view_cb, &data_cb);
+static bool camera_frame_fit_calc_from_data(
+ CameraParams *params, CameraViewFrameData *data, float r_co[3], float *r_scale)
+{
+ float plane_tx[CAMERA_VIEWFRAME_NUM_PLANES][4];
+ unsigned int i;
- if (data_cb.tot <= 1) {
+ if (data->tot <= 1) {
return false;
}
+
+ if (params->is_ortho) {
+ const float *cam_axis_x = data->camera_rotmat[0];
+ const float *cam_axis_y = data->camera_rotmat[1];
+ const float *cam_axis_z = data->camera_rotmat[2];
+ float dists[CAMERA_VIEWFRAME_NUM_PLANES];
+ float scale_diff;
+
+ /* apply the dist-from-plane's to the transformed plane points */
+ for (i = 0; i < CAMERA_VIEWFRAME_NUM_PLANES; i++) {
+ dists[i] = sqrtf_signed(data->dist_vals_sq[i]);
+ }
+
+ if ((dists[0] + dists[2]) > (dists[1] + dists[3])) {
+ scale_diff = (dists[1] + dists[3]) *
+ (BLI_rctf_size_x(&params->viewplane) / BLI_rctf_size_y(&params->viewplane));
+ }
+ else {
+ scale_diff = (dists[0] + dists[2]) *
+ (BLI_rctf_size_y(&params->viewplane) / BLI_rctf_size_x(&params->viewplane));
+ }
+ *r_scale = params->ortho_scale - scale_diff;
+
+ zero_v3(r_co);
+ madd_v3_v3fl(r_co, cam_axis_x, (dists[2] - dists[0]) * 0.5f + params->shiftx * scale_diff);
+ madd_v3_v3fl(r_co, cam_axis_y, (dists[1] - dists[3]) * 0.5f + params->shifty * scale_diff);
+ madd_v3_v3fl(r_co, cam_axis_z, -(data->dist_to_cam - 1.0f - params->clipsta));
+
+ return true;
+ }
else {
float plane_isect_1[3], plane_isect_1_no[3], plane_isect_1_other[3];
float plane_isect_2[3], plane_isect_2_no[3], plane_isect_2_other[3];
@@ -540,16 +608,14 @@ bool BKE_camera_view_frame_fit_to_scene(Scene *scene, struct View3D *v3d, Object
float plane_isect_pt_1[3], plane_isect_pt_2[3];
/* apply the dist-from-plane's to the transformed plane points */
- for (i = 0; i < 4; i++) {
- mul_v3_v3fl(plane_tx[i], data_cb.normal_tx[i], sqrtf_signed(data_cb.dist_vals_sq[i]));
+ for (i = 0; i < CAMERA_VIEWFRAME_NUM_PLANES; i++) {
+ float co[3];
+ mul_v3_v3fl(co, data->normal_tx[i], sqrtf_signed(data->dist_vals_sq[i]));
+ plane_from_point_normal_v3(plane_tx[i], co, data->normal_tx[i]);
}
- if ((!isect_plane_plane_v3(plane_isect_1, plane_isect_1_no,
- plane_tx[0], data_cb.normal_tx[0],
- plane_tx[2], data_cb.normal_tx[2])) ||
- (!isect_plane_plane_v3(plane_isect_2, plane_isect_2_no,
- plane_tx[1], data_cb.normal_tx[1],
- plane_tx[3], data_cb.normal_tx[3])))
+ if ((!isect_plane_plane_v3(plane_tx[0], plane_tx[2], plane_isect_1, plane_isect_1_no)) ||
+ (!isect_plane_plane_v3(plane_tx[1], plane_tx[3], plane_isect_2, plane_isect_2_no)))
{
return false;
}
@@ -559,16 +625,17 @@ bool BKE_camera_view_frame_fit_to_scene(Scene *scene, struct View3D *v3d, Object
if (isect_line_line_v3(plane_isect_1, plane_isect_1_other,
plane_isect_2, plane_isect_2_other,
- plane_isect_pt_1, plane_isect_pt_2) == 0)
+ plane_isect_pt_1, plane_isect_pt_2) != 0)
{
- return false;
- }
- else {
- float cam_plane_no[3] = {0.0f, 0.0f, -1.0f};
+ float cam_plane_no[3];
float plane_isect_delta[3];
float plane_isect_delta_len;
- mul_m3_v3(rot_obmat, cam_plane_no);
+ float shift_fac = BKE_camera_sensor_size(params->sensor_fit, params->sensor_x, params->sensor_y) /
+ params->lens;
+
+ /* we want (0, 0, -1) transformed by camera_rotmat, this is a quicker shortcut. */
+ negate_v3_v3(cam_plane_no, data->camera_rotmat[2]);
sub_v3_v3v3(plane_isect_delta, plane_isect_pt_2, plane_isect_pt_1);
plane_isect_delta_len = len_v3(plane_isect_delta);
@@ -578,18 +645,319 @@ bool BKE_camera_view_frame_fit_to_scene(Scene *scene, struct View3D *v3d, Object
/* offset shift */
normalize_v3(plane_isect_1_no);
- madd_v3_v3fl(r_co, plane_isect_1_no, shift[1] * -plane_isect_delta_len);
+ madd_v3_v3fl(r_co, plane_isect_1_no, params->shifty * plane_isect_delta_len * shift_fac);
}
else {
copy_v3_v3(r_co, plane_isect_pt_2);
/* offset shift */
normalize_v3(plane_isect_2_no);
- madd_v3_v3fl(r_co, plane_isect_2_no, shift[0] * -plane_isect_delta_len);
+ madd_v3_v3fl(r_co, plane_isect_2_no, params->shiftx * plane_isect_delta_len * shift_fac);
}
-
return true;
}
}
+
+ return false;
+}
+
+/* don't move the camera, just yield the fit location */
+/* r_scale only valid/useful for ortho cameras */
+bool BKE_camera_view_frame_fit_to_scene(
+ Scene *scene, struct View3D *v3d, Object *camera_ob, float r_co[3], float *r_scale)
+{
+ CameraParams params;
+ CameraViewFrameData data_cb;
+
+ /* just in case */
+ *r_scale = 1.0f;
+
+ camera_frame_fit_data_init(scene, camera_ob, &params, &data_cb);
+
+ /* run callback on all visible points */
+ BKE_scene_foreach_display_point(scene, v3d, BA_SELECT, camera_to_frame_view_cb, &data_cb);
+
+ return camera_frame_fit_calc_from_data(&params, &data_cb, r_co, r_scale);
+}
+
+bool BKE_camera_view_frame_fit_to_coords(
+ const Scene *scene, const float (*cos)[3], int num_cos, const Object *camera_ob,
+ float r_co[3], float *r_scale)
+{
+ CameraParams params;
+ CameraViewFrameData data_cb;
+
+ /* just in case */
+ *r_scale = 1.0f;
+
+ camera_frame_fit_data_init(scene, camera_ob, &params, &data_cb);
+
+ /* run callback on all given coordinates */
+ while (num_cos--) {
+ camera_to_frame_view_cb(cos[num_cos], &data_cb);
+ }
+
+ return camera_frame_fit_calc_from_data(&params, &data_cb, r_co, r_scale);
+}
+
+/******************* multiview matrix functions ***********************/
+
+static void camera_model_matrix(Object *camera, float r_modelmat[4][4])
+{
+ copy_m4_m4(r_modelmat, camera->obmat);
+}
+
+static void camera_stereo3d_model_matrix(Object *camera, const bool is_left, float r_modelmat[4][4])
+{
+ Camera *data = (Camera *)camera->data;
+ float interocular_distance, convergence_distance;
+ short convergence_mode, pivot;
+ float sizemat[4][4];
+
+ float fac = 1.0f;
+ float fac_signed;
+
+ interocular_distance = data->stereo.interocular_distance;
+ convergence_distance = data->stereo.convergence_distance;
+ convergence_mode = data->stereo.convergence_mode;
+ pivot = data->stereo.pivot;
+
+ if (((pivot == CAM_S3D_PIVOT_LEFT) && is_left) ||
+ ((pivot == CAM_S3D_PIVOT_RIGHT) && !is_left))
+ {
+ camera_model_matrix(camera, r_modelmat);
+ return;
+ }
+ else {
+ float size[3];
+ mat4_to_size(size, camera->obmat);
+ size_to_mat4(sizemat, size);
+ }
+
+ if (pivot == CAM_S3D_PIVOT_CENTER)
+ fac = 0.5f;
+
+ fac_signed = is_left ? fac : -fac;
+
+ /* rotation */
+ if (convergence_mode == CAM_S3D_TOE) {
+ float angle;
+ float angle_sin, angle_cos;
+ float toeinmat[4][4];
+ float rotmat[4][4];
+
+ unit_m4(rotmat);
+
+ if (pivot == CAM_S3D_PIVOT_CENTER) {
+ fac = -fac;
+ fac_signed = -fac_signed;
+ }
+
+ angle = atanf((interocular_distance * 0.5f) / convergence_distance) / fac;
+
+ angle_cos = cosf(angle * fac_signed);
+ angle_sin = sinf(angle * fac_signed);
+
+ rotmat[0][0] = angle_cos;
+ rotmat[2][0] = -angle_sin;
+ rotmat[0][2] = angle_sin;
+ rotmat[2][2] = angle_cos;
+
+ if (pivot == CAM_S3D_PIVOT_CENTER) {
+ /* set the rotation */
+ copy_m4_m4(toeinmat, rotmat);
+ /* set the translation */
+ toeinmat[3][0] = interocular_distance * fac_signed;
+
+ /* transform */
+ normalize_m4_m4(r_modelmat, camera->obmat);
+ mul_m4_m4m4(r_modelmat, r_modelmat, toeinmat);
+
+ /* scale back to the original size */
+ mul_m4_m4m4(r_modelmat, r_modelmat, sizemat);
+ }
+ else { /* CAM_S3D_PIVOT_LEFT, CAM_S3D_PIVOT_RIGHT */
+ /* rotate perpendicular to the interocular line */
+ normalize_m4_m4(r_modelmat, camera->obmat);
+ mul_m4_m4m4(r_modelmat, r_modelmat, rotmat);
+
+ /* translate along the interocular line */
+ unit_m4(toeinmat);
+ toeinmat[3][0] = -interocular_distance * fac_signed;
+ mul_m4_m4m4(r_modelmat, r_modelmat, toeinmat);
+
+ /* rotate to toe-in angle */
+ mul_m4_m4m4(r_modelmat, r_modelmat, rotmat);
+
+ /* scale back to the original size */
+ mul_m4_m4m4(r_modelmat, r_modelmat, sizemat);
+ }
+ }
+ else {
+ normalize_m4_m4(r_modelmat, camera->obmat);
+
+ /* translate - no rotation in CAM_S3D_OFFAXIS, CAM_S3D_PARALLEL */
+ translate_m4(r_modelmat, -interocular_distance * fac_signed, 0.0f, 0.0f);
+
+ /* scale back to the original size */
+ mul_m4_m4m4(r_modelmat, r_modelmat, sizemat);
+ }
+}
+
+/* the view matrix is used by the viewport drawing, it is basically the inverted model matrix */
+void BKE_camera_multiview_view_matrix(RenderData *rd, Object *camera, const bool is_left, float r_viewmat[4][4])
+{
+ BKE_camera_multiview_model_matrix(rd, camera, is_left ? STEREO_LEFT_NAME : STEREO_RIGHT_NAME, r_viewmat);
+ invert_m4(r_viewmat);
+}
+
+/* left is the default */
+static bool camera_is_left(const char *viewname)
+{
+ if (viewname && viewname[0] != '\0') {
+ return !STREQ(viewname, STEREO_RIGHT_NAME);
+ }
+ return true;
+}
+
+void BKE_camera_multiview_model_matrix(RenderData *rd, Object *camera, const char *viewname, float r_modelmat[4][4])
+{
+ const bool is_multiview = (rd && rd->scemode & R_MULTIVIEW) != 0;
+
+ if (!is_multiview) {
+ camera_model_matrix(camera, r_modelmat);
+ }
+ else if (rd->views_format == SCE_VIEWS_FORMAT_MULTIVIEW) {
+ camera_model_matrix(camera, r_modelmat);
+ }
+ else { /* SCE_VIEWS_SETUP_BASIC */
+ const bool is_left = camera_is_left(viewname);
+ camera_stereo3d_model_matrix(camera, is_left, r_modelmat);
+ }
+ normalize_m4(r_modelmat);
+}
+
+static Object *camera_multiview_advanced(Scene *scene, Object *camera, const char *suffix)
+{
+ SceneRenderView *srv;
+ char name[MAX_NAME];
+ const char *camera_name = camera->id.name + 2;
+ const int len_name = strlen(camera_name);
+ int len_suffix_max = -1;
+
+ name[0] = '\0';
+
+ /* we need to take the better match, thus the len_suffix_max test */
+ for (srv = scene->r.views.first; srv; srv = srv->next) {
+ const int len_suffix = strlen(srv->suffix);
+
+ if ((len_suffix < len_suffix_max) || (len_name < len_suffix))
+ continue;
+
+ if (STREQ(camera_name + (len_name - len_suffix), srv->suffix)) {
+ BLI_snprintf(name, sizeof(name), "%.*s%s", (len_name - len_suffix), camera_name, suffix);
+ len_suffix_max = len_suffix;
+ }
+ }
+
+ if (name[0] != '\0') {
+ Base *base = BKE_scene_base_find_by_name(scene, name);
+ if (base) {
+ return base->object;
+ }
+ }
+
+ return camera;
+}
+
+/* returns the camera to be used for render */
+Object *BKE_camera_multiview_render(Scene *scene, Object *camera, const char *viewname)
+{
+ const bool is_multiview = (scene->r.scemode & R_MULTIVIEW) != 0;
+
+ if (!is_multiview) {
+ return camera;
+ }
+ else if (scene->r.views_format == SCE_VIEWS_FORMAT_STEREO_3D) {
+ return camera;
+ }
+ else { /* SCE_VIEWS_FORMAT_MULTIVIEW */
+ const char *suffix = BKE_scene_multiview_view_suffix_get(&scene->r, viewname);
+ return camera_multiview_advanced(scene, camera, suffix);
+ }
+}
+
+static float camera_stereo3d_shift_x(Object *camera, const char *viewname)
+{
+ Camera *data = camera->data;
+ float shift = data->shiftx;
+ float interocular_distance, convergence_distance;
+ short convergence_mode, pivot;
+ bool is_left = true;
+
+ float fac = 1.0f;
+ float fac_signed;
+
+ if (viewname && viewname[0]) {
+ is_left = STREQ(viewname, STEREO_LEFT_NAME);
+ }
+
+ interocular_distance = data->stereo.interocular_distance;
+ convergence_distance = data->stereo.convergence_distance;
+ convergence_mode = data->stereo.convergence_mode;
+ pivot = data->stereo.pivot;
+
+ if (convergence_mode != CAM_S3D_OFFAXIS)
+ return shift;
+
+ if (((pivot == CAM_S3D_PIVOT_LEFT) && is_left) ||
+ ((pivot == CAM_S3D_PIVOT_RIGHT) && !is_left))
+ {
+ return shift;
+ }
+
+ if (pivot == CAM_S3D_PIVOT_CENTER)
+ fac = 0.5f;
+
+ fac_signed = is_left ? fac : -fac;
+ shift += ((interocular_distance / data->sensor_x) * (data->lens / convergence_distance)) * fac_signed;
+
+ return shift;
+}
+
+float BKE_camera_multiview_shift_x(RenderData *rd, Object *camera, const char *viewname)
+{
+ const bool is_multiview = (rd && rd->scemode & R_MULTIVIEW) != 0;
+ Camera *data = camera->data;
+
+ BLI_assert(camera->type == OB_CAMERA);
+
+ if (!is_multiview) {
+ return data->shiftx;
+ }
+ else if (rd->views_format == SCE_VIEWS_FORMAT_MULTIVIEW) {
+ return data->shiftx;
+ }
+ else { /* SCE_VIEWS_SETUP_BASIC */
+ return camera_stereo3d_shift_x(camera, viewname);
+ }
+}
+
+void BKE_camera_multiview_params(RenderData *rd, CameraParams *params, Object *camera, const char *viewname)
+{
+ if (camera->type == OB_CAMERA) {
+ params->shiftx = BKE_camera_multiview_shift_x(rd, camera, viewname);
+ }
+}
+
+void BKE_camera_to_gpu_dof(struct Object *camera, struct GPUFXSettings *r_fx_settings)
+{
+ if (camera->type == OB_CAMERA) {
+ Camera *cam = camera->data;
+ r_fx_settings->dof = &cam->gpu_dof;
+ r_fx_settings->dof->focal_length = cam->lens;
+ r_fx_settings->dof->sensor = BKE_camera_sensor_size(cam->sensor_fit, cam->sensor_x, cam->sensor_y);
+ r_fx_settings->dof->focus_distance = BKE_camera_object_dof_distance(camera);
+ }
}
diff --git a/source/blender/blenkernel/intern/cdderivedmesh.c b/source/blender/blenkernel/intern/cdderivedmesh.c
index 3aba16ddc38..fa0e6121093 100644
--- a/source/blender/blenkernel/intern/cdderivedmesh.c
+++ b/source/blender/blenkernel/intern/cdderivedmesh.c
@@ -34,10 +34,7 @@
* \ingroup bke
*/
-#include "GL/glew.h"
-
#include "BLI_math.h"
-#include "BLI_blenlib.h"
#include "BLI_edgehash.h"
#include "BLI_utildefines.h"
#include "BLI_stackdefines.h"
@@ -51,7 +48,6 @@
#include "BKE_editmesh.h"
#include "BKE_curve.h"
-#include "DNA_material_types.h"
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
#include "DNA_object_types.h"
@@ -62,7 +58,9 @@
#include "GPU_buffers.h"
#include "GPU_draw.h"
#include "GPU_extensions.h"
-#include "GPU_material.h"
+#include "GPU_glew.h"
+
+#include "WM_api.h"
#include <string.h>
#include <limits.h>
@@ -216,9 +214,10 @@ static const MeshElemMap *cdDM_getPolyMap(Object *ob, DerivedMesh *dm)
if (!cddm->pmap && ob->type == OB_MESH) {
Mesh *me = ob->data;
- BKE_mesh_vert_poly_map_create(&cddm->pmap, &cddm->pmap_mem,
- me->mpoly, me->mloop,
- me->totvert, me->totpoly, me->totloop);
+ BKE_mesh_vert_poly_map_create(
+ &cddm->pmap, &cddm->pmap_mem,
+ me->mpoly, me->mloop,
+ me->totvert, me->totpoly, me->totloop);
}
return cddm->pmap;
@@ -297,15 +296,26 @@ static PBVH *cdDM_getPBVH(Object *ob, DerivedMesh *dm)
* that this is actually for, to support a pbvh on a modified mesh */
if (!cddm->pbvh && ob->type == OB_MESH) {
Mesh *me = ob->data;
+ const int looptris_num = poly_to_tri_count(me->totpoly, me->totloop);
+ MLoopTri *looptri;
bool deformed;
cddm->pbvh = BKE_pbvh_new();
cddm->pbvh_draw = can_pbvh_draw(ob, dm);
- BKE_mesh_tessface_ensure(me);
+ looptri = MEM_mallocN(sizeof(*looptri) * looptris_num, __func__);
+
+ BKE_mesh_recalc_looptri(
+ me->mloop, me->mpoly,
+ me->mvert,
+ me->totloop, me->totpoly,
+ looptri);
- BKE_pbvh_build_mesh(cddm->pbvh, me->mface, me->mvert,
- me->totface, me->totvert, &me->vdata);
+ BKE_pbvh_build_mesh(
+ cddm->pbvh,
+ me->mpoly, me->mloop,
+ me->mvert, me->totvert, &me->vdata,
+ looptri, looptris_num);
pbvh_show_diffuse_color_set(cddm->pbvh, ob->sculpt->show_diffuse_color);
@@ -334,361 +344,159 @@ static void cdDM_update_normals_from_pbvh(DerivedMesh *dm)
CDDerivedMesh *cddm = (CDDerivedMesh *) dm;
float (*face_nors)[3];
- if (!cddm->pbvh || !cddm->pbvh_draw || !dm->numTessFaceData)
+ if (!cddm->pbvh || !cddm->pbvh_draw || !dm->numPolyData)
return;
- face_nors = CustomData_get_layer(&dm->faceData, CD_NORMAL);
+ face_nors = CustomData_get_layer(&dm->polyData, CD_NORMAL);
BKE_pbvh_update(cddm->pbvh, PBVH_UpdateNormals, face_nors);
}
static void cdDM_drawVerts(DerivedMesh *dm)
{
- CDDerivedMesh *cddm = (CDDerivedMesh *) dm;
- MVert *mv = cddm->mvert;
- int i;
-
- if (GPU_buffer_legacy(dm)) {
- glBegin(GL_POINTS);
- for (i = 0; i < dm->numVertData; i++, mv++)
- glVertex3fv(mv->co);
- glEnd();
- }
- else { /* use OpenGL VBOs or Vertex Arrays instead for better, faster rendering */
- GPU_vertex_setup(dm);
- if (!GPU_buffer_legacy(dm)) {
- if (dm->drawObject->tot_triangle_point)
- glDrawArrays(GL_POINTS, 0, dm->drawObject->tot_triangle_point);
- else
- glDrawArrays(GL_POINTS, 0, dm->drawObject->tot_loose_point);
- }
- GPU_buffer_unbind();
- }
+ GPU_vertex_setup(dm);
+ if (dm->drawObject->tot_loop_verts)
+ glDrawArrays(GL_POINTS, 0, dm->drawObject->tot_loop_verts);
+ else
+ glDrawArrays(GL_POINTS, 0, dm->drawObject->tot_loose_point);
+ GPU_buffers_unbind();
}
static void cdDM_drawUVEdges(DerivedMesh *dm)
{
CDDerivedMesh *cddm = (CDDerivedMesh *) dm;
- MFace *mf = cddm->mface;
- MTFace *tf = DM_get_tessface_data_layer(dm, CD_MTFACE);
+ const MPoly *mpoly = cddm->mpoly;
+ int totpoly = dm->getNumPolys(dm);
+ int prevstart = 0;
+ bool prevdraw = true;
+ int curpos = 0;
int i;
- if (mf) {
- if (GPU_buffer_legacy(dm)) {
- glBegin(GL_LINES);
- for (i = 0; i < dm->numTessFaceData; i++, mf++, tf++) {
- if (!(mf->flag & ME_HIDE)) {
- glVertex2fv(tf->uv[0]);
- glVertex2fv(tf->uv[1]);
-
- glVertex2fv(tf->uv[1]);
- glVertex2fv(tf->uv[2]);
+ GPU_uvedge_setup(dm);
+ for (i = 0; i < totpoly; i++, mpoly++) {
+ const bool draw = (mpoly->flag & ME_HIDE) == 0;
- if (!mf->v4) {
- glVertex2fv(tf->uv[2]);
- glVertex2fv(tf->uv[0]);
- }
- else {
- glVertex2fv(tf->uv[2]);
- glVertex2fv(tf->uv[3]);
-
- glVertex2fv(tf->uv[3]);
- glVertex2fv(tf->uv[0]);
- }
- }
- }
- glEnd();
- }
- else {
- int prevstart = 0;
- int prevdraw = 1;
- int draw = 1;
- int curpos = 0;
-
- GPU_uvedge_setup(dm);
- if (!GPU_buffer_legacy(dm)) {
- for (i = 0; i < dm->numTessFaceData; i++, mf++) {
- if (!(mf->flag & ME_HIDE)) {
- draw = 1;
- }
- else {
- draw = 0;
- }
- if (prevdraw != draw) {
- if (prevdraw > 0 && (curpos - prevstart) > 0) {
- glDrawArrays(GL_LINES, prevstart, curpos - prevstart);
- }
- prevstart = curpos;
- }
- if (mf->v4) {
- curpos += 8;
- }
- else {
- curpos += 6;
- }
- prevdraw = draw;
- }
- if (prevdraw > 0 && (curpos - prevstart) > 0) {
- glDrawArrays(GL_LINES, prevstart, curpos - prevstart);
- }
+ if (prevdraw != draw) {
+ if (prevdraw && (curpos != prevstart)) {
+ glDrawArrays(GL_LINES, prevstart, curpos - prevstart);
}
- GPU_buffer_unbind();
+ prevstart = curpos;
}
+
+ curpos += 2 * mpoly->totloop;
+ prevdraw = draw;
}
+ if (prevdraw && (curpos != prevstart)) {
+ glDrawArrays(GL_LINES, prevstart, curpos - prevstart);
+ }
+ GPU_buffers_unbind();
}
static void cdDM_drawEdges(DerivedMesh *dm, bool drawLooseEdges, bool drawAllEdges)
{
CDDerivedMesh *cddm = (CDDerivedMesh *) dm;
- MVert *mvert = cddm->mvert;
- MEdge *medge = cddm->medge;
- int i;
-
+ GPUDrawObject *gdo;
if (cddm->pbvh && cddm->pbvh_draw &&
BKE_pbvh_type(cddm->pbvh) == PBVH_BMESH)
{
- BKE_pbvh_draw(cddm->pbvh, NULL, NULL, NULL, true);
+ BKE_pbvh_draw(cddm->pbvh, NULL, NULL, NULL, true, false);
return;
}
- if (GPU_buffer_legacy(dm)) {
- DEBUG_VBO("Using legacy code. cdDM_drawEdges\n");
- glBegin(GL_LINES);
- for (i = 0; i < dm->numEdgeData; i++, medge++) {
- if ((drawAllEdges || (medge->flag & ME_EDGEDRAW)) &&
- (drawLooseEdges || !(medge->flag & ME_LOOSEEDGE)))
- {
- glVertex3fv(mvert[medge->v1].co);
- glVertex3fv(mvert[medge->v2].co);
- }
+ GPU_edge_setup(dm);
+ gdo = dm->drawObject;
+ if (gdo->edges && gdo->points) {
+ if (drawAllEdges && drawLooseEdges) {
+ GPU_buffer_draw_elements(gdo->edges, GL_LINES, 0, gdo->totedge * 2);
}
- glEnd();
- }
- else { /* use OpenGL VBOs or Vertex Arrays instead for better, faster rendering */
- int prevstart = 0;
- int prevdraw = 1;
- bool draw = true;
-
- GPU_edge_setup(dm);
- if (!GPU_buffer_legacy(dm)) {
- for (i = 0; i < dm->numEdgeData; i++, medge++) {
- if ((drawAllEdges || (medge->flag & ME_EDGEDRAW)) &&
- (drawLooseEdges || !(medge->flag & ME_LOOSEEDGE)))
- {
- draw = true;
- }
- else {
- draw = false;
- }
- if (prevdraw != draw) {
- if (prevdraw > 0 && (i - prevstart) > 0) {
- GPU_buffer_draw_elements(dm->drawObject->edges, GL_LINES, prevstart * 2, (i - prevstart) * 2);
- }
- prevstart = i;
- }
- prevdraw = draw;
- }
- if (prevdraw > 0 && (i - prevstart) > 0) {
- GPU_buffer_draw_elements(dm->drawObject->edges, GL_LINES, prevstart * 2, (i - prevstart) * 2);
- }
+ else if (drawAllEdges) {
+ GPU_buffer_draw_elements(gdo->edges, GL_LINES, 0, gdo->loose_edge_offset * 2);
+ }
+ else {
+ GPU_buffer_draw_elements(gdo->edges, GL_LINES, 0, gdo->tot_edge_drawn * 2);
+ GPU_buffer_draw_elements(gdo->edges, GL_LINES, gdo->loose_edge_offset * 2, dm->drawObject->tot_loose_edge_drawn * 2);
}
- GPU_buffer_unbind();
}
+ GPU_buffers_unbind();
}
static void cdDM_drawLooseEdges(DerivedMesh *dm)
{
- CDDerivedMesh *cddm = (CDDerivedMesh *) dm;
- MVert *mvert = cddm->mvert;
- MEdge *medge = cddm->medge;
- int i;
+ int start;
+ int count;
- if (GPU_buffer_legacy(dm)) {
- DEBUG_VBO("Using legacy code. cdDM_drawLooseEdges\n");
- glBegin(GL_LINES);
- for (i = 0; i < dm->numEdgeData; i++, medge++) {
- if (medge->flag & ME_LOOSEEDGE) {
- glVertex3fv(mvert[medge->v1].co);
- glVertex3fv(mvert[medge->v2].co);
- }
- }
- glEnd();
- }
- else { /* use OpenGL VBOs or Vertex Arrays instead for better, faster rendering */
- int prevstart = 0;
- int prevdraw = 1;
- int draw = 1;
+ GPU_edge_setup(dm);
- GPU_edge_setup(dm);
- if (!GPU_buffer_legacy(dm)) {
- for (i = 0; i < dm->numEdgeData; i++, medge++) {
- if (medge->flag & ME_LOOSEEDGE) {
- draw = 1;
- }
- else {
- draw = 0;
- }
- if (prevdraw != draw) {
- if (prevdraw > 0 && (i - prevstart) > 0) {
- GPU_buffer_draw_elements(dm->drawObject->edges, GL_LINES, prevstart * 2, (i - prevstart) * 2);
- }
- prevstart = i;
- }
- prevdraw = draw;
- }
- if (prevdraw > 0 && (i - prevstart) > 0) {
- GPU_buffer_draw_elements(dm->drawObject->edges, GL_LINES, prevstart * 2, (i - prevstart) * 2);
- }
- }
- GPU_buffer_unbind();
+ start = (dm->drawObject->loose_edge_offset * 2);
+ count = (dm->drawObject->totedge - dm->drawObject->loose_edge_offset) * 2;
+
+ if (count) {
+ GPU_buffer_draw_elements(dm->drawObject->edges, GL_LINES, start, count);
}
+
+ GPU_buffers_unbind();
}
-static void cdDM_drawFacesSolid(DerivedMesh *dm,
- float (*partial_redraw_planes)[4],
- bool UNUSED(fast), DMSetMaterial setMaterial)
+static void cdDM_drawFacesSolid(
+ DerivedMesh *dm,
+ float (*partial_redraw_planes)[4],
+ bool UNUSED(fast), DMSetMaterial setMaterial)
{
CDDerivedMesh *cddm = (CDDerivedMesh *) dm;
- MVert *mvert = cddm->mvert;
- MFace *mface = cddm->mface;
- const float *nors = dm->getTessFaceDataArray(dm, CD_NORMAL);
- const short (*lnors)[4][3] = dm->getTessFaceDataArray(dm, CD_TESSLOOPNORMAL);
- int a, glmode = -1, shademodel = -1, matnr = -1, drawCurrentMat = 1;
+ int a;
if (cddm->pbvh && cddm->pbvh_draw) {
- if (dm->numTessFaceData) {
+ if (BKE_pbvh_has_faces(cddm->pbvh)) {
float (*face_nors)[3] = CustomData_get_layer(&dm->faceData, CD_NORMAL);
+ cdDM_update_normals_from_pbvh(dm);
+
BKE_pbvh_draw(cddm->pbvh, partial_redraw_planes, face_nors,
- setMaterial, false);
+ setMaterial, false, false);
glShadeModel(GL_FLAT);
}
return;
}
-
- if (GPU_buffer_legacy(dm)) {
- DEBUG_VBO("Using legacy code. cdDM_drawFacesSolid\n");
- glBegin(glmode = GL_QUADS);
- for (a = 0; a < dm->numTessFaceData; a++, mface++) {
- int new_glmode, new_matnr, new_shademodel;
-
- new_glmode = mface->v4 ? GL_QUADS : GL_TRIANGLES;
- new_matnr = mface->mat_nr + 1;
- new_shademodel = (lnors || (mface->flag & ME_SMOOTH)) ? GL_SMOOTH : GL_FLAT;
-
-
- if ((new_glmode != glmode) || (new_shademodel != shademodel) ||
- (setMaterial && (new_matnr != matnr)))
- {
- glEnd();
-
- if (setMaterial) {
- drawCurrentMat = setMaterial(matnr = new_matnr, NULL);
- }
-
- glShadeModel(shademodel = new_shademodel);
- glBegin(glmode = new_glmode);
- }
-
- if (drawCurrentMat) {
- if (lnors) {
- glNormal3sv((const GLshort *)lnors[0][0]);
- glVertex3fv(mvert[mface->v1].co);
- glNormal3sv((const GLshort *)lnors[0][1]);
- glVertex3fv(mvert[mface->v2].co);
- glNormal3sv((const GLshort *)lnors[0][2]);
- glVertex3fv(mvert[mface->v3].co);
- if (mface->v4) {
- glNormal3sv((const GLshort *)lnors[0][3]);
- glVertex3fv(mvert[mface->v4].co);
- }
- }
- else if (shademodel == GL_FLAT) {
- if (nors) {
- glNormal3fv(nors);
- }
- else {
- /* TODO make this better (cache facenormals as layer?) */
- float nor[3];
- if (mface->v4) {
- normal_quad_v3(nor, mvert[mface->v1].co, mvert[mface->v2].co, mvert[mface->v3].co, mvert[mface->v4].co);
- }
- else {
- normal_tri_v3(nor, mvert[mface->v1].co, mvert[mface->v2].co, mvert[mface->v3].co);
- }
- glNormal3fv(nor);
- }
- glVertex3fv(mvert[mface->v1].co);
- glVertex3fv(mvert[mface->v2].co);
- glVertex3fv(mvert[mface->v3].co);
- if (mface->v4) {
- glVertex3fv(mvert[mface->v4].co);
- }
- }
- else { /* shademodel == GL_SMOOTH */
- glNormal3sv(mvert[mface->v1].no);
- glVertex3fv(mvert[mface->v1].co);
- glNormal3sv(mvert[mface->v2].no);
- glVertex3fv(mvert[mface->v2].co);
- glNormal3sv(mvert[mface->v3].no);
- glVertex3fv(mvert[mface->v3].co);
- if (mface->v4) {
- glNormal3sv(mvert[mface->v4].no);
- glVertex3fv(mvert[mface->v4].co);
- }
- }
- }
-
- if (nors)
- nors += 3;
- if (lnors)
- lnors++;
- }
- glEnd();
- }
- else { /* use OpenGL VBOs or Vertex Arrays instead for better, faster rendering */
- GPU_vertex_setup(dm);
- GPU_normal_setup(dm);
- if (!GPU_buffer_legacy(dm)) {
- glShadeModel(GL_SMOOTH);
- for (a = 0; a < dm->drawObject->totmaterial; a++) {
- if (!setMaterial || setMaterial(dm->drawObject->materials[a].mat_nr + 1, NULL)) {
- glDrawArrays(GL_TRIANGLES, dm->drawObject->materials[a].start,
- dm->drawObject->materials[a].totpoint);
- }
- }
+
+ GPU_vertex_setup(dm);
+ GPU_normal_setup(dm);
+ GPU_triangle_setup(dm);
+ glShadeModel(GL_SMOOTH);
+ for (a = 0; a < dm->drawObject->totmaterial; a++) {
+ if (!setMaterial || setMaterial(dm->drawObject->materials[a].mat_nr + 1, NULL)) {
+ GPU_buffer_draw_elements(
+ dm->drawObject->triangles, GL_TRIANGLES,
+ dm->drawObject->materials[a].start, dm->drawObject->materials[a].totelements);
}
- GPU_buffer_unbind();
}
+ GPU_buffers_unbind();
glShadeModel(GL_FLAT);
}
-static void cdDM_drawFacesTex_common(DerivedMesh *dm,
- DMSetDrawOptionsTex drawParams,
- DMSetDrawOptions drawParamsMapped,
- DMCompareDrawOptions compareDrawOptions,
- void *userData, DMDrawFlag uvflag)
+static void cdDM_drawFacesTex_common(
+ DerivedMesh *dm,
+ DMSetDrawOptionsTex drawParams,
+ DMSetDrawOptionsMappedTex drawParamsMapped,
+ DMCompareDrawOptions compareDrawOptions,
+ void *userData, DMDrawFlag uvflag)
{
CDDerivedMesh *cddm = (CDDerivedMesh *) dm;
- MVert *mv = cddm->mvert;
- const MFace *mf = DM_get_tessface_data_layer(dm, CD_MFACE);
- const float *nors = dm->getTessFaceDataArray(dm, CD_NORMAL);
- const short (*lnors)[4][3] = dm->getTessFaceDataArray(dm, CD_TESSLOOPNORMAL);
- MTFace *tf = DM_get_tessface_data_layer(dm, CD_MTFACE);
- MCol *mcol;
- int i, orig;
- int colType, startFace = 0;
+ const MPoly *mpoly = cddm->mpoly;
+ MTexPoly *mtexpoly = DM_get_poly_data_layer(dm, CD_MTEXPOLY);
+ const MLoopCol *mloopcol;
+ int i;
+ int colType, start_element, tot_drawn;
bool use_tface = (uvflag & DM_DRAW_USE_ACTIVE_UV) != 0;
+ int totpoly;
+ int next_actualFace;
+ int mat_index;
+ int tot_element;
/* double lookup */
- const int *index_mf_to_mpoly = dm->getTessFaceDataArray(dm, CD_ORIGINDEX);
const int *index_mp_to_orig = dm->getPolyDataArray(dm, CD_ORIGINDEX);
- if (index_mf_to_mpoly == NULL) {
- index_mp_to_orig = NULL;
- }
/* TODO: not entirely correct, but currently dynamic topology will
* destroy UVs anyway, so textured display wouldn't work anyway
@@ -698,61 +506,64 @@ static void cdDM_drawFacesTex_common(DerivedMesh *dm,
* (the same as it'll display without UV maps in textured view)
*/
if (cddm->pbvh && cddm->pbvh_draw && BKE_pbvh_type(cddm->pbvh) == PBVH_BMESH) {
- if (dm->numTessFaceData) {
+ if (BKE_pbvh_has_faces(cddm->pbvh)) {
+ cdDM_update_normals_from_pbvh(dm);
GPU_set_tpage(NULL, false, false);
- BKE_pbvh_draw(cddm->pbvh, NULL, NULL, NULL, false);
+ BKE_pbvh_draw(cddm->pbvh, NULL, NULL, NULL, false, false);
}
return;
}
- colType = CD_TEXTURE_MCOL;
- mcol = dm->getTessFaceDataArray(dm, colType);
- if (!mcol) {
- colType = CD_PREVIEW_MCOL;
- mcol = dm->getTessFaceDataArray(dm, colType);
+ colType = CD_TEXTURE_MLOOPCOL;
+ mloopcol = dm->getLoopDataArray(dm, colType);
+ if (!mloopcol) {
+ colType = CD_PREVIEW_MLOOPCOL;
+ mloopcol = dm->getLoopDataArray(dm, colType);
}
- if (!mcol) {
- colType = CD_MCOL;
- mcol = dm->getTessFaceDataArray(dm, colType);
+ if (!mloopcol) {
+ colType = CD_MLOOPCOL;
+ mloopcol = dm->getLoopDataArray(dm, colType);
}
- cdDM_update_normals_from_pbvh(dm);
-
- if (GPU_buffer_legacy(dm)) {
- int mat_nr_cache = -1;
- MTFace *tf_base = DM_get_tessface_data_layer(dm, CD_MTFACE);
- MTFace *tf_stencil_base = NULL;
- MTFace *tf_stencil = NULL;
-
- if (uvflag & DM_DRAW_USE_TEXPAINT_UV) {
- int stencil = CustomData_get_stencil_layer(&dm->faceData, CD_MTFACE);
- tf_stencil_base = CustomData_get_layer_n(&dm->faceData, CD_MTFACE, stencil);
- }
-
- DEBUG_VBO("Using legacy code. cdDM_drawFacesTex_common\n");
- for (i = 0; i < dm->numTessFaceData; i++, mf++) {
- MVert *mvert;
- DMDrawOption draw_option;
- unsigned char *cp = NULL;
-
- if (uvflag & DM_DRAW_USE_TEXPAINT_UV) {
- if (mf->mat_nr != mat_nr_cache) {
- tf_base = DM_paint_uvlayer_active_get(dm, mf->mat_nr);
-
- mat_nr_cache = mf->mat_nr;
- }
- }
+ GPU_vertex_setup(dm);
+ GPU_normal_setup(dm);
+ GPU_triangle_setup(dm);
+ if (uvflag & DM_DRAW_USE_TEXPAINT_UV)
+ GPU_texpaint_uv_setup(dm);
+ else
+ GPU_uv_setup(dm);
+ if (mloopcol) {
+ GPU_color_setup(dm, colType);
+ }
+
+ glShadeModel(GL_SMOOTH);
+ /* lastFlag = 0; */ /* UNUSED */
+ for (mat_index = 0; mat_index < dm->drawObject->totmaterial; mat_index++) {
+ GPUBufferMaterial *bufmat = dm->drawObject->materials + mat_index;
+ next_actualFace = bufmat->polys[0];
+ totpoly = bufmat->totpolys;
+
+ tot_element = 0;
+ tot_drawn = 0;
+ start_element = 0;
+
+ for (i = 0; i < totpoly; i++) {
+ int actualFace = bufmat->polys[i];
+ DMDrawOption draw_option = DM_DRAW_OPTION_NORMAL;
+ int flush = 0;
+ int tot_tri_verts;
- tf = tf_base ? tf_base + i : NULL;
- tf_stencil = tf_stencil_base ? tf_stencil_base + i : NULL;
+ if (i != totpoly - 1)
+ next_actualFace = bufmat->polys[i + 1];
if (drawParams) {
- draw_option = drawParams(use_tface ? tf : NULL, (mcol != NULL), mf->mat_nr);
+ MTexPoly *tp = use_tface && mtexpoly ? &mtexpoly[actualFace] : NULL;
+ draw_option = drawParams(tp, (mloopcol != NULL), mpoly[actualFace].mat_nr);
}
else {
- if (index_mf_to_mpoly) {
- orig = DM_origindex_mface_mpoly(index_mf_to_mpoly, index_mp_to_orig, i);
+ if (index_mp_to_orig) {
+ const int orig = index_mp_to_orig[actualFace];
if (orig == ORIGINDEX_NONE) {
/* XXX, this is not really correct
* it will draw the previous faces context for this one when we don't know its settings.
@@ -760,464 +571,269 @@ static void cdDM_drawFacesTex_common(DerivedMesh *dm,
draw_option = DM_DRAW_OPTION_NORMAL;
}
else if (drawParamsMapped) {
- draw_option = drawParamsMapped(userData, orig);
- }
- else {
- if (nors) {
- nors += 3;
- }
- continue;
+ draw_option = drawParamsMapped(userData, orig, mpoly[actualFace].mat_nr);
}
}
else if (drawParamsMapped) {
- draw_option = drawParamsMapped(userData, i);
- }
- else {
- if (nors) {
- nors += 3;
- }
- continue;
+ draw_option = drawParamsMapped(userData, actualFace, mpoly[actualFace].mat_nr);
}
}
-
- if (draw_option != DM_DRAW_OPTION_SKIP) {
- if (draw_option != DM_DRAW_OPTION_NO_MCOL && mcol)
- cp = (unsigned char *) &mcol[i * 4];
- if (!(lnors || (mf->flag & ME_SMOOTH))) {
- if (nors) {
- glNormal3fv(nors);
- }
- else {
- float nor[3];
- if (mf->v4) {
- normal_quad_v3(nor, mv[mf->v1].co, mv[mf->v2].co, mv[mf->v3].co, mv[mf->v4].co);
- }
- else {
- normal_tri_v3(nor, mv[mf->v1].co, mv[mf->v2].co, mv[mf->v3].co);
- }
- glNormal3fv(nor);
- }
- }
+ /* flush buffer if current triangle isn't drawable or it's last triangle */
+ flush = (draw_option == DM_DRAW_OPTION_SKIP) || (i == totpoly - 1);
- glBegin(mf->v4 ? GL_QUADS : GL_TRIANGLES);
- if (tf) glTexCoord2fv(tf->uv[0]);
- if (tf_stencil) glMultiTexCoord2fv(GL_TEXTURE2, tf->uv[0]);
- if (cp) glColor3ub(cp[3], cp[2], cp[1]);
- mvert = &mv[mf->v1];
- if (lnors) glNormal3sv((const GLshort *)lnors[0][0]);
- else if (mf->flag & ME_SMOOTH) glNormal3sv(mvert->no);
- glVertex3fv(mvert->co);
-
- if (tf) glTexCoord2fv(tf->uv[1]);
- if (tf_stencil) glMultiTexCoord2fv(GL_TEXTURE2, tf->uv[1]);
- if (cp) glColor3ub(cp[7], cp[6], cp[5]);
- mvert = &mv[mf->v2];
- if (lnors) glNormal3sv((const GLshort *)lnors[0][1]);
- else if (mf->flag & ME_SMOOTH) glNormal3sv(mvert->no);
- glVertex3fv(mvert->co);
-
- if (tf) glTexCoord2fv(tf->uv[2]);
- if (tf_stencil) glMultiTexCoord2fv(GL_TEXTURE2, tf->uv[2]);
- if (cp) glColor3ub(cp[11], cp[10], cp[9]);
- mvert = &mv[mf->v3];
- if (lnors) glNormal3sv((const GLshort *)lnors[0][2]);
- else if (mf->flag & ME_SMOOTH) glNormal3sv(mvert->no);
- glVertex3fv(mvert->co);
-
- if (mf->v4) {
- if (tf) glTexCoord2fv(tf->uv[3]);
- if (tf_stencil) glMultiTexCoord2fv(GL_TEXTURE2, tf->uv[3]);
- if (cp) glColor3ub(cp[15], cp[14], cp[13]);
- mvert = &mv[mf->v4];
- if (lnors) glNormal3sv((const GLshort *)lnors[0][3]);
- else if (mf->flag & ME_SMOOTH) glNormal3sv(mvert->no);
- glVertex3fv(mvert->co);
- }
- glEnd();
+ if (!flush && compareDrawOptions) {
+ /* also compare draw options and flush buffer if they're different
+ * need for face selection highlight in edit mode */
+ flush |= compareDrawOptions(userData, actualFace, next_actualFace) == 0;
}
-
- if (nors)
- nors += 3;
- if (lnors)
- lnors++;
- }
- }
- else { /* use OpenGL VBOs or Vertex Arrays instead for better, faster rendering */
- GPU_vertex_setup(dm);
- GPU_normal_setup(dm);
- if (uvflag & DM_DRAW_USE_TEXPAINT_UV)
- GPU_texpaint_uv_setup(dm);
- else
- GPU_uv_setup(dm);
- if (mcol) {
- GPU_color_setup(dm, colType);
- }
- if (!GPU_buffer_legacy(dm)) {
- int tottri = dm->drawObject->tot_triangle_point / 3;
- int next_actualFace = dm->drawObject->triangle_to_mface[0];
+ tot_tri_verts = ME_POLY_TRI_TOT(&mpoly[actualFace]) * 3;
+ tot_element += tot_tri_verts;
- glShadeModel(GL_SMOOTH);
- /* lastFlag = 0; */ /* UNUSED */
- for (i = 0; i < tottri; i++) {
- int actualFace = next_actualFace;
- DMDrawOption draw_option = DM_DRAW_OPTION_NORMAL;
- int flush = 0;
+ if (flush) {
+ if (draw_option != DM_DRAW_OPTION_SKIP)
+ tot_drawn += tot_tri_verts;
- if (i != tottri - 1)
- next_actualFace = dm->drawObject->triangle_to_mface[i + 1];
+ if (tot_drawn) {
+ if (mloopcol && draw_option != DM_DRAW_OPTION_NO_MCOL)
+ GPU_color_switch(1);
+ else
+ GPU_color_switch(0);
- if (drawParams) {
- draw_option = drawParams(use_tface && tf ? &tf[actualFace] : NULL, (mcol != NULL), mf[actualFace].mat_nr);
- }
- else {
- if (index_mf_to_mpoly) {
- orig = DM_origindex_mface_mpoly(index_mf_to_mpoly, index_mp_to_orig, actualFace);
- if (orig == ORIGINDEX_NONE) {
- /* XXX, this is not really correct
- * it will draw the previous faces context for this one when we don't know its settings.
- * but better then skipping it altogether. - campbell */
- draw_option = DM_DRAW_OPTION_NORMAL;
- }
- else if (drawParamsMapped) {
- draw_option = drawParamsMapped(userData, orig);
- }
- }
- else if (drawParamsMapped) {
- draw_option = drawParamsMapped(userData, actualFace);
- }
- }
-
- /* flush buffer if current triangle isn't drawable or it's last triangle */
- flush = (draw_option == DM_DRAW_OPTION_SKIP) || (i == tottri - 1);
-
- if (!flush && compareDrawOptions) {
- /* also compare draw options and flush buffer if they're different
- * need for face selection highlight in edit mode */
- flush |= compareDrawOptions(userData, actualFace, next_actualFace) == 0;
- }
-
- if (flush) {
- int first = startFace * 3;
- /* Add one to the length if we're drawing at the end of the array */
- int count = (i - startFace + (draw_option != DM_DRAW_OPTION_SKIP ? 1 : 0)) * 3;
-
- if (count) {
- if (mcol && draw_option != DM_DRAW_OPTION_NO_MCOL)
- GPU_color_switch(1);
- else
- GPU_color_switch(0);
-
- glDrawArrays(GL_TRIANGLES, first, count);
- }
-
- startFace = i + 1;
+ GPU_buffer_draw_elements(dm->drawObject->triangles, GL_TRIANGLES, bufmat->start + start_element, tot_drawn);
+ tot_drawn = 0;
}
+ start_element = tot_element;
+ }
+ else {
+ tot_drawn += tot_tri_verts;
}
}
-
- GPU_buffer_unbind();
- glShadeModel(GL_FLAT);
}
+
+ GPU_buffers_unbind();
+ glShadeModel(GL_FLAT);
+
}
-static void cdDM_drawFacesTex(DerivedMesh *dm,
- DMSetDrawOptionsTex setDrawOptions,
- DMCompareDrawOptions compareDrawOptions,
- void *userData, DMDrawFlag uvflag)
+static void cdDM_drawFacesTex(
+ DerivedMesh *dm,
+ DMSetDrawOptionsTex setDrawOptions,
+ DMCompareDrawOptions compareDrawOptions,
+ void *userData, DMDrawFlag uvflag)
{
cdDM_drawFacesTex_common(dm, setDrawOptions, NULL, compareDrawOptions, userData, uvflag);
}
-static void cdDM_drawMappedFaces(DerivedMesh *dm,
- DMSetDrawOptions setDrawOptions,
- DMSetMaterial setMaterial,
- DMCompareDrawOptions compareDrawOptions,
- void *userData, DMDrawFlag flag)
+static void cdDM_drawMappedFaces(
+ DerivedMesh *dm,
+ DMSetDrawOptions setDrawOptions,
+ DMSetMaterial setMaterial,
+ DMCompareDrawOptions compareDrawOptions,
+ void *userData, DMDrawFlag flag)
{
CDDerivedMesh *cddm = (CDDerivedMesh *) dm;
- MVert *mv = cddm->mvert;
- MFace *mf = cddm->mface;
- MCol *mcol;
- const float *nors = DM_get_tessface_data_layer(dm, CD_NORMAL);
- const short (*lnors)[4][3] = dm->getTessFaceDataArray(dm, CD_TESSLOOPNORMAL);
- int colType, useColors = flag & DM_DRAW_USE_COLORS;
- int i, orig;
-
+ const MPoly *mpoly = cddm->mpoly;
+ const MLoopCol *mloopcol = NULL;
+ int colType, useColors = flag & DM_DRAW_USE_COLORS, useHide = flag & DM_DRAW_SKIP_HIDDEN;
+ int i, j;
+ int start_element = 0, tot_element, tot_drawn;
+ int totpoly;
+ int tot_tri_elem;
+ int mat_index;
+ GPUBuffer *findex_buffer = NULL;
- /* double lookup */
- const int *index_mf_to_mpoly = dm->getTessFaceDataArray(dm, CD_ORIGINDEX);
const int *index_mp_to_orig = dm->getPolyDataArray(dm, CD_ORIGINDEX);
- if (index_mf_to_mpoly == NULL) {
- index_mp_to_orig = NULL;
- }
+ /* fist, setup common buffers */
+ GPU_vertex_setup(dm);
+ GPU_triangle_setup(dm);
- colType = CD_ID_MCOL;
- mcol = DM_get_tessface_data_layer(dm, colType);
- if (!mcol) {
- colType = CD_PREVIEW_MCOL;
- mcol = DM_get_tessface_data_layer(dm, colType);
- }
- if (!mcol) {
- colType = CD_MCOL;
- mcol = DM_get_tessface_data_layer(dm, colType);
- }
+ totpoly = dm->getNumPolys(dm);
- cdDM_update_normals_from_pbvh(dm);
+ /* if we do selection, fill the selection buffer color */
+ if (G.f & G_BACKBUFSEL) {
+ if (!(flag & DM_DRAW_SKIP_SELECT)) {
+ Mesh *me = NULL;
+ BMesh *bm = NULL;
+ unsigned int *fi_map;
- /* back-buffer always uses legacy since VBO's would need the
- * color array temporarily overwritten for drawing, then reset. */
- if (GPU_buffer_legacy(dm) || G.f & G_BACKBUFSEL) {
- DEBUG_VBO("Using legacy code. cdDM_drawMappedFaces\n");
- for (i = 0; i < dm->numTessFaceData; i++, mf++) {
- int drawSmooth = ((flag & DM_DRAW_ALWAYS_SMOOTH) || lnors) ? 1 : (mf->flag & ME_SMOOTH);
- DMDrawOption draw_option = DM_DRAW_OPTION_NORMAL;
-
- orig = (index_mf_to_mpoly) ? DM_origindex_mface_mpoly(index_mf_to_mpoly, index_mp_to_orig, i) : i;
-
- if (orig == ORIGINDEX_NONE)
- draw_option = setMaterial(mf->mat_nr + 1, NULL);
- else if (setDrawOptions != NULL)
- draw_option = setDrawOptions(userData, orig);
+ if (flag & DM_DRAW_SELECT_USE_EDITMODE)
+ bm = userData;
+ else
+ me = userData;
- if (draw_option != DM_DRAW_OPTION_SKIP) {
- unsigned char *cp = NULL;
+ findex_buffer = GPU_buffer_alloc(dm->drawObject->tot_loop_verts * sizeof(int), false);
+ fi_map = GPU_buffer_lock(findex_buffer, GPU_BINDING_ARRAY);
- if (draw_option == DM_DRAW_OPTION_STIPPLE) {
- glEnable(GL_POLYGON_STIPPLE);
- glPolygonStipple(stipple_quarttone);
- }
+ if (fi_map) {
+ for (i = 0; i < totpoly; i++, mpoly++) {
+ int selcol = 0xFFFFFFFF;
+ const int orig = (index_mp_to_orig) ? index_mp_to_orig[i] : i;
+ bool is_hidden;
- if (useColors && mcol)
- cp = (unsigned char *)&mcol[i * 4];
-
- /* no need to set shading mode to flat because
- * normals are already used to change shading */
- glShadeModel(GL_SMOOTH);
- glBegin(mf->v4 ? GL_QUADS : GL_TRIANGLES);
-
- if (lnors) {
- if (cp) glColor3ub(cp[3], cp[2], cp[1]);
- glNormal3sv((const GLshort *)lnors[0][0]);
- glVertex3fv(mv[mf->v1].co);
- if (cp) glColor3ub(cp[7], cp[6], cp[5]);
- glNormal3sv((const GLshort *)lnors[0][1]);
- glVertex3fv(mv[mf->v2].co);
- if (cp) glColor3ub(cp[11], cp[10], cp[9]);
- glNormal3sv((const GLshort *)lnors[0][2]);
- glVertex3fv(mv[mf->v3].co);
- if (mf->v4) {
- if (cp) glColor3ub(cp[15], cp[14], cp[13]);
- glNormal3sv((const GLshort *)lnors[0][3]);
- glVertex3fv(mv[mf->v4].co);
- }
- }
- else if (!drawSmooth) {
- if (nors) {
- glNormal3fv(nors);
- }
- else {
- float nor[3];
- if (mf->v4) {
- normal_quad_v3(nor, mv[mf->v1].co, mv[mf->v2].co, mv[mf->v3].co, mv[mf->v4].co);
+ if (useHide) {
+ if (flag & DM_DRAW_SELECT_USE_EDITMODE) {
+ BMFace *efa = BM_face_at_index(bm, orig);
+ is_hidden = BM_elem_flag_test(efa, BM_ELEM_HIDDEN) != 0;
}
else {
- normal_tri_v3(nor, mv[mf->v1].co, mv[mf->v2].co, mv[mf->v3].co);
+ is_hidden = (me->mpoly[orig].flag & ME_HIDE) != 0;
}
- glNormal3fv(nor);
- }
- if (cp) glColor3ub(cp[3], cp[2], cp[1]);
- glVertex3fv(mv[mf->v1].co);
- if (cp) glColor3ub(cp[7], cp[6], cp[5]);
- glVertex3fv(mv[mf->v2].co);
- if (cp) glColor3ub(cp[11], cp[10], cp[9]);
- glVertex3fv(mv[mf->v3].co);
- if (mf->v4) {
- if (cp) glColor3ub(cp[15], cp[14], cp[13]);
- glVertex3fv(mv[mf->v4].co);
- }
- }
- else {
- if (cp) glColor3ub(cp[3], cp[2], cp[1]);
- glNormal3sv(mv[mf->v1].no);
- glVertex3fv(mv[mf->v1].co);
- if (cp) glColor3ub(cp[7], cp[6], cp[5]);
- glNormal3sv(mv[mf->v2].no);
- glVertex3fv(mv[mf->v2].co);
- if (cp) glColor3ub(cp[11], cp[10], cp[9]);
- glNormal3sv(mv[mf->v3].no);
- glVertex3fv(mv[mf->v3].co);
- if (mf->v4) {
- if (cp) glColor3ub(cp[15], cp[14], cp[13]);
- glNormal3sv(mv[mf->v4].no);
- glVertex3fv(mv[mf->v4].co);
+ if ((orig != ORIGINDEX_NONE) && !is_hidden)
+ WM_framebuffer_index_get(orig + 1, &selcol);
}
+ else if (orig != ORIGINDEX_NONE)
+ WM_framebuffer_index_get(orig + 1, &selcol);
+
+ for (j = 0; j < mpoly->totloop; j++)
+ fi_map[start_element++] = selcol;
}
- glEnd();
+ start_element = 0;
+ mpoly = cddm->mpoly;
- if (draw_option == DM_DRAW_OPTION_STIPPLE)
- glDisable(GL_POLYGON_STIPPLE);
+ GPU_buffer_unlock(findex_buffer, GPU_BINDING_ARRAY);
+ GPU_buffer_bind_as_color(findex_buffer);
}
-
- if (nors)
- nors += 3;
- if (lnors)
- lnors++;
}
}
- else { /* use OpenGL VBOs or Vertex Arrays instead for better, faster rendering */
- int prevstart = 0;
- GPU_vertex_setup(dm);
+ else {
GPU_normal_setup(dm);
- if (useColors && mcol) {
- GPU_color_setup(dm, colType);
- }
- if (!GPU_buffer_legacy(dm)) {
- int tottri = dm->drawObject->tot_triangle_point / 3;
- glShadeModel(GL_SMOOTH);
-
- if (tottri == 0) {
- /* avoid buffer problems in following code */
+
+ if (useColors) {
+ colType = CD_TEXTURE_MLOOPCOL;
+ mloopcol = DM_get_loop_data_layer(dm, colType);
+ if (!mloopcol) {
+ colType = CD_PREVIEW_MLOOPCOL;
+ mloopcol = DM_get_loop_data_layer(dm, colType);
}
- if (setDrawOptions == NULL) {
- /* just draw the entire face array */
- glDrawArrays(GL_TRIANGLES, 0, (tottri) * 3);
+ if (!mloopcol) {
+ colType = CD_MLOOPCOL;
+ mloopcol = DM_get_loop_data_layer(dm, colType);
}
- else {
- /* we need to check if the next material changes */
- int next_actualFace = dm->drawObject->triangle_to_mface[0];
-
- for (i = 0; i < tottri; i++) {
- //int actualFace = dm->drawObject->triangle_to_mface[i];
+
+ if (useColors && mloopcol) {
+ GPU_color_setup(dm, colType);
+ }
+ }
+ }
+
+
+ glShadeModel(GL_SMOOTH);
+
+ tot_tri_elem = dm->drawObject->tot_triangle_point;
+
+ if (tot_tri_elem == 0) {
+ /* avoid buffer problems in following code */
+ }
+ else if (setDrawOptions == NULL) {
+ /* just draw the entire face array */
+ GPU_buffer_draw_elements(dm->drawObject->triangles, GL_TRIANGLES, 0, tot_tri_elem);
+ }
+ else {
+ for (mat_index = 0; mat_index < dm->drawObject->totmaterial; mat_index++) {
+ GPUBufferMaterial *bufmat = dm->drawObject->materials + mat_index;
+ DMDrawOption draw_option = DM_DRAW_OPTION_NORMAL;
+ int next_actualFace = bufmat->polys[0];
+ totpoly = useHide ? bufmat->totvisiblepolys : bufmat->totpolys;
+
+ tot_element = 0;
+ start_element = 0;
+ tot_drawn = 0;
+
+ if (setMaterial)
+ draw_option = setMaterial(bufmat->mat_nr + 1, NULL);
+
+ if (draw_option != DM_DRAW_OPTION_SKIP) {
+ for (i = 0; i < totpoly; i++) {
int actualFace = next_actualFace;
- MFace *mface = mf + actualFace;
- /*int drawSmooth = (flag & DM_DRAW_ALWAYS_SMOOTH) ? 1 : (mface->flag & ME_SMOOTH);*/ /* UNUSED */
- DMDrawOption draw_option = DM_DRAW_OPTION_NORMAL;
int flush = 0;
+ int tot_tri_verts;
- if (i != tottri - 1)
- next_actualFace = dm->drawObject->triangle_to_mface[i + 1];
+ draw_option = DM_DRAW_OPTION_NORMAL;
- orig = (index_mf_to_mpoly) ? DM_origindex_mface_mpoly(index_mf_to_mpoly, index_mp_to_orig, actualFace) : actualFace;
+ if (i != totpoly - 1)
+ next_actualFace = bufmat->polys[i + 1];
- if (orig == ORIGINDEX_NONE)
- draw_option = setMaterial(mface->mat_nr + 1, NULL);
- else if (setDrawOptions != NULL)
- draw_option = setDrawOptions(userData, orig);
+ if (setDrawOptions) {
+ const int orig = (index_mp_to_orig) ? index_mp_to_orig[actualFace] : actualFace;
+
+ if (orig != ORIGINDEX_NONE) {
+ draw_option = setDrawOptions(userData, orig);
+ }
+ }
if (draw_option == DM_DRAW_OPTION_STIPPLE) {
glEnable(GL_POLYGON_STIPPLE);
glPolygonStipple(stipple_quarttone);
}
-
+
/* Goal is to draw as long of a contiguous triangle
* array as possible, so draw when we hit either an
* invisible triangle or at the end of the array */
/* flush buffer if current triangle isn't drawable or it's last triangle... */
- flush = (ELEM(draw_option, DM_DRAW_OPTION_SKIP, DM_DRAW_OPTION_STIPPLE)) || (i == tottri - 1);
-
- /* ... or when material setting is dissferent */
- flush |= mf[actualFace].mat_nr != mf[next_actualFace].mat_nr;
+ flush = (ELEM(draw_option, DM_DRAW_OPTION_SKIP, DM_DRAW_OPTION_STIPPLE)) || (i == totpoly - 1);
if (!flush && compareDrawOptions) {
flush |= compareDrawOptions(userData, actualFace, next_actualFace) == 0;
}
+ tot_tri_verts = ME_POLY_TRI_TOT(&mpoly[actualFace]) * 3;
+ tot_element += tot_tri_verts;
+
if (flush) {
- int first = prevstart * 3;
- /* Add one to the length if we're drawing at the end of the array */
- int count = (i - prevstart + (draw_option != DM_DRAW_OPTION_SKIP ? 1 : 0)) * 3;
+ if (!ELEM(draw_option, DM_DRAW_OPTION_SKIP, DM_DRAW_OPTION_STIPPLE))
+ tot_drawn += tot_tri_verts;
- if (count)
- glDrawArrays(GL_TRIANGLES, first, count);
+ if (tot_drawn) {
+ GPU_buffer_draw_elements(dm->drawObject->triangles, GL_TRIANGLES, bufmat->start + start_element, tot_drawn);
+ tot_drawn = 0;
+ }
- prevstart = i + 1;
+ start_element = tot_element;
if (draw_option == DM_DRAW_OPTION_STIPPLE)
glDisable(GL_POLYGON_STIPPLE);
}
+ else {
+ tot_drawn += tot_tri_verts;
+ }
}
}
-
- glShadeModel(GL_FLAT);
}
- GPU_buffer_unbind();
}
+
+ glShadeModel(GL_FLAT);
+
+ GPU_buffers_unbind();
+
+ if (findex_buffer)
+ GPU_buffer_free(findex_buffer);
+
}
-static void cdDM_drawMappedFacesTex(DerivedMesh *dm,
- DMSetDrawOptions setDrawOptions,
- DMCompareDrawOptions compareDrawOptions,
- void *userData, DMDrawFlag flag)
+static void cdDM_drawMappedFacesTex(
+ DerivedMesh *dm,
+ DMSetDrawOptionsMappedTex setDrawOptions,
+ DMCompareDrawOptions compareDrawOptions,
+ void *userData, DMDrawFlag flag)
{
cdDM_drawFacesTex_common(dm, NULL, setDrawOptions, compareDrawOptions, userData, flag);
}
-static void cddm_draw_attrib_vertex(DMVertexAttribs *attribs, const MVert *mvert, int a, int index, int vert,
- const short (*lnor)[3], const bool smoothnormal)
+static void cddm_draw_attrib_vertex(
+ DMVertexAttribs *attribs, const MVert *mvert, int a, int index, int loop, int vert,
+ const float *lnor, const bool smoothnormal)
{
- const float zero[4] = {0.0f, 0.0f, 0.0f, 0.0f};
- int b;
-
- /* orco texture coordinates */
- if (attribs->totorco) {
- /*const*/ float (*array)[3] = attribs->orco.array;
- const float *orco = (array) ? array[index] : zero;
-
- if (attribs->orco.gl_texco)
- glTexCoord3fv(orco);
- else
- glVertexAttrib3fvARB(attribs->orco.gl_index, orco);
- }
-
- /* uv texture coordinates */
- for (b = 0; b < attribs->tottface; b++) {
- const float *uv;
-
- if (attribs->tface[b].array) {
- MTFace *tf = &attribs->tface[b].array[a];
- uv = tf->uv[vert];
- }
- else {
- uv = zero;
- }
-
- if (attribs->tface[b].gl_texco)
- glTexCoord2fv(uv);
- else
- glVertexAttrib2fvARB(attribs->tface[b].gl_index, uv);
- }
-
- /* vertex colors */
- for (b = 0; b < attribs->totmcol; b++) {
- GLubyte col[4];
-
- if (attribs->mcol[b].array) {
- MCol *cp = &attribs->mcol[b].array[a * 4 + vert];
- col[0] = cp->b; col[1] = cp->g; col[2] = cp->r; col[3] = cp->a;
- }
- else {
- col[0] = 0; col[1] = 0; col[2] = 0; col[3] = 0;
- }
-
- glVertexAttrib4ubvARB(attribs->mcol[b].gl_index, col);
- }
-
- /* tangent for normal mapping */
- if (attribs->tottang) {
- /*const*/ float (*array)[4] = attribs->tang.array;
- const float *tang = (array) ? array[a * 4 + vert] : zero;
- glVertexAttrib4fvARB(attribs->tang.gl_index, tang);
- }
+ DM_draw_attrib_vertex(attribs, a, index, vert, loop);
/* vertex normal */
if (lnor) {
- glNormal3sv((const GLshort *)lnor);
+ glNormal3fv(lnor);
}
else if (smoothnormal) {
glNormal3sv(mvert[index].no);
@@ -1227,76 +843,90 @@ static void cddm_draw_attrib_vertex(DMVertexAttribs *attribs, const MVert *mvert
glVertex3fv(mvert[index].co);
}
-static void cdDM_drawMappedFacesGLSL(DerivedMesh *dm,
- DMSetMaterial setMaterial,
- DMSetDrawOptions setDrawOptions,
- void *userData)
+typedef struct {
+ DMVertexAttribs attribs;
+ int numdata;
+
+ GPUAttrib datatypes[GPU_MAX_ATTRIB]; /* TODO, messing up when switching materials many times - [#21056]*/
+} GPUMaterialConv;
+
+static void cdDM_drawMappedFacesGLSL(
+ DerivedMesh *dm,
+ DMSetMaterial setMaterial,
+ DMSetDrawOptions setDrawOptions,
+ void *userData)
{
CDDerivedMesh *cddm = (CDDerivedMesh *) dm;
GPUVertexAttribs gattribs;
- DMVertexAttribs attribs;
const MVert *mvert = cddm->mvert;
- const MFace *mface = cddm->mface;
+ const MPoly *mpoly = cddm->mpoly;
+ const MLoop *mloop = cddm->mloop;
+ const MLoopTri *lt = dm->getLoopTriArray(dm);
+ const int tottri = dm->getNumLoopTri(dm);
/* MTFace *tf = dm->getTessFaceDataArray(dm, CD_MTFACE); */ /* UNUSED */
- const float (*nors)[3] = dm->getTessFaceDataArray(dm, CD_NORMAL);
- const short (*lnors)[4][3] = dm->getTessFaceDataArray(dm, CD_TESSLOOPNORMAL);
+ const float (*nors)[3] = dm->getPolyDataArray(dm, CD_NORMAL);
+ const float (*lnors)[3] = dm->getLoopDataArray(dm, CD_NORMAL);
+ const int totpoly = dm->getNumPolys(dm);
+ const short dm_totmat = dm->totmat;
int a, b, matnr, new_matnr;
bool do_draw;
int orig;
- /* double lookup */
- const int *index_mf_to_mpoly = dm->getTessFaceDataArray(dm, CD_ORIGINDEX);
const int *index_mp_to_orig = dm->getPolyDataArray(dm, CD_ORIGINDEX);
- if (index_mf_to_mpoly == NULL) {
- index_mp_to_orig = NULL;
- }
/* TODO: same as for solid draw, not entirely correct, but works fine for now,
* will skip using textures (dyntopo currently destroys UV anyway) and
* works fine for matcap
*/
if (cddm->pbvh && cddm->pbvh_draw && BKE_pbvh_type(cddm->pbvh) == PBVH_BMESH) {
- if (dm->numTessFaceData) {
+ if (BKE_pbvh_has_faces(cddm->pbvh)) {
+ cdDM_update_normals_from_pbvh(dm);
setMaterial(1, &gattribs);
- BKE_pbvh_draw(cddm->pbvh, NULL, NULL, NULL, false);
+ BKE_pbvh_draw(cddm->pbvh, NULL, NULL, NULL, false, false);
}
return;
}
- cdDM_update_normals_from_pbvh(dm);
-
matnr = -1;
do_draw = false;
glShadeModel(GL_SMOOTH);
- if (GPU_buffer_legacy(dm) || setDrawOptions != NULL) {
+ /* workaround for NVIDIA GPUs on Mac not supporting vertex arrays + interleaved formats, see T43342 */
+ if ((GPU_type_matches(GPU_DEVICE_NVIDIA, GPU_OS_MAC, GPU_DRIVER_ANY) && (U.gameflags & USER_DISABLE_VBO)) ||
+ setDrawOptions != NULL)
+ {
+ DMVertexAttribs attribs;
DEBUG_VBO("Using legacy code. cdDM_drawMappedFacesGLSL\n");
memset(&attribs, 0, sizeof(attribs));
- glBegin(GL_QUADS);
+ glBegin(GL_TRIANGLES);
- for (a = 0; a < dm->numTessFaceData; a++, mface++) {
- const bool smoothnormal = lnors || (mface->flag & ME_SMOOTH);
- const short (*ln1)[3] = NULL, (*ln2)[3] = NULL, (*ln3)[3] = NULL, (*ln4)[3] = NULL;
- new_matnr = mface->mat_nr + 1;
+ for (a = 0; a < tottri; a++, lt++) {
+ const MPoly *mp = &mpoly[lt->poly];
+ const unsigned int vtri[3] = {mloop[lt->tri[0]].v, mloop[lt->tri[1]].v, mloop[lt->tri[2]].v};
+ const unsigned int *ltri = lt->tri;
+ const float *ln1 = NULL, *ln2 = NULL, *ln3 = NULL;
+ const bool smoothnormal = lnors || (mp->flag & ME_SMOOTH);
+ new_matnr = mp->mat_nr;
if (new_matnr != matnr) {
glEnd();
- do_draw = setMaterial(matnr = new_matnr, &gattribs);
+ matnr = new_matnr;
+ do_draw = setMaterial(matnr + 1, &gattribs);
if (do_draw)
DM_vertex_attributes_from_gpu(dm, &gattribs, &attribs);
- glBegin(GL_QUADS);
+ glBegin(GL_TRIANGLES);
}
if (!do_draw) {
continue;
}
else if (setDrawOptions) {
- orig = (index_mf_to_mpoly) ? DM_origindex_mface_mpoly(index_mf_to_mpoly, index_mp_to_orig, a) : a;
+ orig = (index_mp_to_orig) ? index_mp_to_orig[lt->poly] : lt->poly;
if (orig == ORIGINDEX_NONE) {
/* since the material is set by setMaterial(), faces with no
@@ -1310,252 +940,182 @@ static void cdDM_drawMappedFacesGLSL(DerivedMesh *dm,
if (!smoothnormal) {
if (nors) {
- glNormal3fv(nors[a]);
+ glNormal3fv(nors[lt->poly]);
}
else {
/* TODO ideally a normal layer should always be available */
float nor[3];
- if (mface->v4) {
- normal_quad_v3(nor, mvert[mface->v1].co, mvert[mface->v2].co, mvert[mface->v3].co, mvert[mface->v4].co);
- }
- else {
- normal_tri_v3(nor, mvert[mface->v1].co, mvert[mface->v2].co, mvert[mface->v3].co);
- }
+ normal_tri_v3(nor, mvert[vtri[0]].co, mvert[vtri[1]].co, mvert[vtri[2]].co);
glNormal3fv(nor);
}
}
else if (lnors) {
- ln1 = &lnors[a][0];
- ln2 = &lnors[a][1];
- ln3 = &lnors[a][2];
- ln4 = &lnors[a][3];
+ ln1 = lnors[ltri[0]];
+ ln2 = lnors[ltri[1]];
+ ln3 = lnors[ltri[2]];
}
-
- cddm_draw_attrib_vertex(&attribs, mvert, a, mface->v1, 0, ln1, smoothnormal);
- cddm_draw_attrib_vertex(&attribs, mvert, a, mface->v2, 1, ln2, smoothnormal);
- cddm_draw_attrib_vertex(&attribs, mvert, a, mface->v3, 2, ln3, smoothnormal);
-
- if (mface->v4)
- cddm_draw_attrib_vertex(&attribs, mvert, a, mface->v4, 3, ln4, smoothnormal);
- else
- cddm_draw_attrib_vertex(&attribs, mvert, a, mface->v3, 2, ln3, smoothnormal);
+
+ cddm_draw_attrib_vertex(&attribs, mvert, a, vtri[0], ltri[0], 0, ln1, smoothnormal);
+ cddm_draw_attrib_vertex(&attribs, mvert, a, vtri[1], ltri[1], 1, ln2, smoothnormal);
+ cddm_draw_attrib_vertex(&attribs, mvert, a, vtri[2], ltri[2], 2, ln3, smoothnormal);
}
glEnd();
}
else {
+ GPUMaterialConv *matconv;
+ int offset;
+ int *mat_orig_to_new;
+ int tot_active_mat;
GPUBuffer *buffer = NULL;
- const char *varray = NULL;
- int numdata = 0, elementsize = 0, offset;
- int start = 0, numfaces = 0 /* , prevdraw = 0 */ /* UNUSED */, curface = 0;
- int i;
-
- const MFace *mf = mface;
- GPUAttrib datatypes[GPU_MAX_ATTRIB]; /* TODO, messing up when switching materials many times - [#21056]*/
- memset(&attribs, 0, sizeof(attribs));
+ char *varray;
+ size_t max_element_size = 0;
+ int tot_loops = 0;
GPU_vertex_setup(dm);
GPU_normal_setup(dm);
+ GPU_triangle_setup(dm);
- if (!GPU_buffer_legacy(dm)) {
- for (i = 0; i < dm->drawObject->tot_triangle_point / 3; i++) {
-
- a = dm->drawObject->triangle_to_mface[i];
-
- mface = mf + a;
- new_matnr = mface->mat_nr + 1;
-
- if (new_matnr != matnr) {
- numfaces = curface - start;
- if (numfaces > 0) {
+ tot_active_mat = dm->drawObject->totmaterial;
- if (do_draw) {
+ matconv = MEM_callocN(sizeof(*matconv) * tot_active_mat,
+ "cdDM_drawMappedFacesGLSL.matconv");
+ mat_orig_to_new = MEM_mallocN(sizeof(*mat_orig_to_new) * dm->totmat,
+ "cdDM_drawMappedFacesGLSL.mat_orig_to_new");
- if (numdata != 0) {
+ /* part one, check what attributes are needed per material */
+ for (a = 0; a < tot_active_mat; a++) {
+ new_matnr = dm->drawObject->materials[a].mat_nr;
- GPU_buffer_unlock(buffer);
+ /* map from original material index to new
+ * GPUBufferMaterial index */
+ mat_orig_to_new[new_matnr] = a;
+ do_draw = setMaterial(new_matnr + 1, &gattribs);
- GPU_interleaved_attrib_setup(buffer, datatypes, numdata);
- }
-
- glDrawArrays(GL_TRIANGLES, start * 3, numfaces * 3);
-
- if (numdata != 0) {
+ if (do_draw) {
+ int numdata = 0;
+ DM_vertex_attributes_from_gpu(dm, &gattribs, &matconv[a].attribs);
- GPU_buffer_free(buffer);
-
- buffer = NULL;
- }
-
- }
+ if (matconv[a].attribs.totorco && matconv[a].attribs.orco.array) {
+ matconv[a].datatypes[numdata].index = matconv[a].attribs.orco.gl_index;
+ matconv[a].datatypes[numdata].size = 3;
+ matconv[a].datatypes[numdata].type = GL_FLOAT;
+ numdata++;
+ }
+ for (b = 0; b < matconv[a].attribs.tottface; b++) {
+ if (matconv[a].attribs.tface[b].array) {
+ matconv[a].datatypes[numdata].index = matconv[a].attribs.tface[b].gl_index;
+ matconv[a].datatypes[numdata].size = 2;
+ matconv[a].datatypes[numdata].type = GL_FLOAT;
+ numdata++;
}
- numdata = 0;
- start = curface;
- /* prevdraw = do_draw; */ /* UNUSED */
- do_draw = setMaterial(matnr = new_matnr, &gattribs);
- if (do_draw) {
- DM_vertex_attributes_from_gpu(dm, &gattribs, &attribs);
-
- if (attribs.totorco && attribs.orco.array) {
- datatypes[numdata].index = attribs.orco.gl_index;
- datatypes[numdata].size = 3;
- datatypes[numdata].type = GL_FLOAT;
- numdata++;
- }
- for (b = 0; b < attribs.tottface; b++) {
- if (attribs.tface[b].array) {
- datatypes[numdata].index = attribs.tface[b].gl_index;
- datatypes[numdata].size = 2;
- datatypes[numdata].type = GL_FLOAT;
- numdata++;
- }
- }
- for (b = 0; b < attribs.totmcol; b++) {
- if (attribs.mcol[b].array) {
- datatypes[numdata].index = attribs.mcol[b].gl_index;
- datatypes[numdata].size = 4;
- datatypes[numdata].type = GL_UNSIGNED_BYTE;
- numdata++;
- }
- }
- if (attribs.tottang && attribs.tang.array) {
- datatypes[numdata].index = attribs.tang.gl_index;
- datatypes[numdata].size = 4;
- datatypes[numdata].type = GL_FLOAT;
- numdata++;
- }
- if (numdata != 0) {
- elementsize = GPU_attrib_element_size(datatypes, numdata);
- buffer = GPU_buffer_alloc(elementsize * dm->drawObject->tot_triangle_point);
- if (buffer == NULL) {
- GPU_buffer_unbind();
- dm->drawObject->legacy = 1;
- return;
- }
- varray = GPU_buffer_lock_stream(buffer);
- if (varray == NULL) {
- GPU_buffer_unbind();
- GPU_buffer_free(buffer);
- dm->drawObject->legacy = 1;
- return;
- }
- }
- else {
- /* if the buffer was set, don't use it again.
- * prevdraw was assumed true but didnt run so set to false - [#21036] */
- /* prevdraw = 0; */ /* UNUSED */
- buffer = NULL;
- }
+ }
+ for (b = 0; b < matconv[a].attribs.totmcol; b++) {
+ if (matconv[a].attribs.mcol[b].array) {
+ matconv[a].datatypes[numdata].index = matconv[a].attribs.mcol[b].gl_index;
+ matconv[a].datatypes[numdata].size = 4;
+ matconv[a].datatypes[numdata].type = GL_UNSIGNED_BYTE;
+ numdata++;
}
}
+ if (matconv[a].attribs.tottang && matconv[a].attribs.tang.array) {
+ matconv[a].datatypes[numdata].index = matconv[a].attribs.tang.gl_index;
+ matconv[a].datatypes[numdata].size = 4;
+ matconv[a].datatypes[numdata].type = GL_FLOAT;
+ numdata++;
+ }
+ if (numdata != 0) {
+ matconv[a].numdata = numdata;
+ max_element_size = max_ii(GPU_attrib_element_size(matconv[a].datatypes, numdata), max_element_size);
+ }
+ }
+ }
+
+ /* part two, generate and fill the arrays with the data */
+ if (max_element_size > 0) {
+ buffer = GPU_buffer_alloc(max_element_size * dm->drawObject->tot_loop_verts, false);
+
+ if (buffer == NULL) {
+ buffer = GPU_buffer_alloc(max_element_size * dm->drawObject->tot_loop_verts, true);
+ }
+ varray = GPU_buffer_lock_stream(buffer, GPU_BINDING_ARRAY);
+ if (varray == NULL) {
+ GPU_buffers_unbind();
+ GPU_buffer_free(buffer);
+ MEM_freeN(mat_orig_to_new);
+ MEM_freeN(matconv);
+ fprintf(stderr, "Out of memory, can't draw object\n");
+ return;
+ }
- if (do_draw && numdata != 0) {
- offset = 0;
- if (attribs.totorco && attribs.orco.array) {
- copy_v3_v3((float *)&varray[elementsize * curface * 3], (float *)attribs.orco.array[mface->v1]);
- copy_v3_v3((float *)&varray[elementsize * curface * 3 + elementsize], (float *)attribs.orco.array[mface->v2]);
- copy_v3_v3((float *)&varray[elementsize * curface * 3 + elementsize * 2], (float *)attribs.orco.array[mface->v3]);
+ for (a = 0; a < totpoly; a++, mpoly++) {
+ const short mat_nr = ME_MAT_NR_TEST(mpoly->mat_nr, dm_totmat);
+ int j;
+ int i = mat_orig_to_new[mat_nr];
+ offset = tot_loops * max_element_size;
+
+ if (matconv[i].numdata != 0) {
+ if (matconv[i].attribs.totorco && matconv[i].attribs.orco.array) {
+ for (j = 0; j < mpoly->totloop; j++)
+ copy_v3_v3((float *)&varray[offset + j * max_element_size],
+ (float *)matconv[i].attribs.orco.array[mloop[mpoly->loopstart + j].v]);
offset += sizeof(float) * 3;
}
- for (b = 0; b < attribs.tottface; b++) {
- if (attribs.tface[b].array) {
- MTFace *tf = &attribs.tface[b].array[a];
- copy_v2_v2((float *)&varray[elementsize * curface * 3 + offset], tf->uv[0]);
- copy_v2_v2((float *)&varray[elementsize * curface * 3 + offset + elementsize], tf->uv[1]);
-
- copy_v2_v2((float *)&varray[elementsize * curface * 3 + offset + elementsize * 2], tf->uv[2]);
+ for (b = 0; b < matconv[i].attribs.tottface; b++) {
+ if (matconv[i].attribs.tface[b].array) {
+ const MLoopUV *mloopuv = matconv[i].attribs.tface[b].array;
+ for (j = 0; j < mpoly->totloop; j++)
+ copy_v2_v2((float *)&varray[offset + j * max_element_size], mloopuv[mpoly->loopstart + j].uv);
offset += sizeof(float) * 2;
}
}
- for (b = 0; b < attribs.totmcol; b++) {
- if (attribs.mcol[b].array) {
- MCol *cp = &attribs.mcol[b].array[a * 4 + 0];
- GLubyte col[4];
- col[0] = cp->b; col[1] = cp->g; col[2] = cp->r; col[3] = cp->a;
- copy_v4_v4_char((char *)&varray[elementsize * curface * 3 + offset], (char *)col);
- cp = &attribs.mcol[b].array[a * 4 + 1];
- col[0] = cp->b; col[1] = cp->g; col[2] = cp->r; col[3] = cp->a;
- copy_v4_v4_char((char *)&varray[elementsize * curface * 3 + offset + elementsize], (char *)col);
- cp = &attribs.mcol[b].array[a * 4 + 2];
- col[0] = cp->b; col[1] = cp->g; col[2] = cp->r; col[3] = cp->a;
- copy_v4_v4_char((char *)&varray[elementsize * curface * 3 + offset + elementsize * 2], (char *)col);
+ for (b = 0; b < matconv[i].attribs.totmcol; b++) {
+ if (matconv[i].attribs.mcol[b].array) {
+ const MLoopCol *mloopcol = matconv[i].attribs.mcol[b].array;
+ for (j = 0; j < mpoly->totloop; j++)
+ copy_v4_v4_char((char *)&varray[offset + j * max_element_size], &mloopcol[mpoly->loopstart + j].r);
offset += sizeof(unsigned char) * 4;
}
}
- if (attribs.tottang && attribs.tang.array) {
- const float *tang = attribs.tang.array[a * 4 + 0];
- copy_v4_v4((float *)&varray[elementsize * curface * 3 + offset], tang);
- tang = attribs.tang.array[a * 4 + 1];
- copy_v4_v4((float *)&varray[elementsize * curface * 3 + offset + elementsize], tang);
- tang = attribs.tang.array[a * 4 + 2];
- copy_v4_v4((float *)&varray[elementsize * curface * 3 + offset + elementsize * 2], tang);
- offset += sizeof(float) * 4;
- }
- (void)offset;
- }
- curface++;
- if (mface->v4) {
- if (do_draw && numdata != 0) {
- offset = 0;
- if (attribs.totorco && attribs.orco.array) {
- copy_v3_v3((float *)&varray[elementsize * curface * 3], (float *)attribs.orco.array[mface->v3]);
- copy_v3_v3((float *)&varray[elementsize * curface * 3 + elementsize], (float *)attribs.orco.array[mface->v4]);
- copy_v3_v3((float *)&varray[elementsize * curface * 3 + elementsize * 2], (float *)attribs.orco.array[mface->v1]);
- offset += sizeof(float) * 3;
- }
- for (b = 0; b < attribs.tottface; b++) {
- if (attribs.tface[b].array) {
- MTFace *tf = &attribs.tface[b].array[a];
- copy_v2_v2((float *)&varray[elementsize * curface * 3 + offset], tf->uv[2]);
- copy_v2_v2((float *)&varray[elementsize * curface * 3 + offset + elementsize], tf->uv[3]);
- copy_v2_v2((float *)&varray[elementsize * curface * 3 + offset + elementsize * 2], tf->uv[0]);
- offset += sizeof(float) * 2;
- }
- }
- for (b = 0; b < attribs.totmcol; b++) {
- if (attribs.mcol[b].array) {
- MCol *cp = &attribs.mcol[b].array[a * 4 + 2];
- GLubyte col[4];
- col[0] = cp->b; col[1] = cp->g; col[2] = cp->r; col[3] = cp->a;
- copy_v4_v4_char((char *)&varray[elementsize * curface * 3 + offset], (char *)col);
- cp = &attribs.mcol[b].array[a * 4 + 3];
- col[0] = cp->b; col[1] = cp->g; col[2] = cp->r; col[3] = cp->a;
- copy_v4_v4_char((char *)&varray[elementsize * curface * 3 + offset + elementsize], (char *)col);
- cp = &attribs.mcol[b].array[a * 4 + 0];
- col[0] = cp->b; col[1] = cp->g; col[2] = cp->r; col[3] = cp->a;
- copy_v4_v4_char((char *)&varray[elementsize * curface * 3 + offset + elementsize * 2], (char *)col);
- offset += sizeof(unsigned char) * 4;
- }
- }
- if (attribs.tottang && attribs.tang.array) {
- const float *tang = attribs.tang.array[a * 4 + 2];
- copy_v4_v4((float *)&varray[elementsize * curface * 3 + offset], tang);
- tang = attribs.tang.array[a * 4 + 3];
- copy_v4_v4((float *)&varray[elementsize * curface * 3 + offset + elementsize], tang);
- tang = attribs.tang.array[a * 4 + 0];
- copy_v4_v4((float *)&varray[elementsize * curface * 3 + offset + elementsize * 2], tang);
+ if (matconv[i].attribs.tottang && matconv[i].attribs.tang.array) {
+ if (matconv[i].attribs.tface[b].array) {
+ const float (*looptang)[4] = (const float (*)[4])matconv[i].attribs.tang.array;
+ for (j = 0; j < mpoly->totloop; j++)
+ copy_v4_v4((float *)&varray[offset + j * max_element_size], looptang[mpoly->loopstart + j]);
offset += sizeof(float) * 4;
}
- (void)offset;
}
- curface++;
- i++;
}
+
+ tot_loops += mpoly->totloop;
}
- numfaces = curface - start;
- if (numfaces > 0) {
- if (do_draw) {
- if (numdata != 0) {
- GPU_buffer_unlock(buffer);
- GPU_interleaved_attrib_setup(buffer, datatypes, numdata);
- }
- glDrawArrays(GL_TRIANGLES, start * 3, (curface - start) * 3);
+ GPU_buffer_unlock(buffer, GPU_BINDING_ARRAY);
+ }
+
+ for (a = 0; a < tot_active_mat; a++) {
+ new_matnr = dm->drawObject->materials[a].mat_nr;
+
+ do_draw = setMaterial(new_matnr + 1, &gattribs);
+
+ if (do_draw) {
+ if (matconv[a].numdata) {
+ GPU_interleaved_attrib_setup(buffer, matconv[a].datatypes, matconv[a].numdata, max_element_size);
+ }
+ GPU_buffer_draw_elements(dm->drawObject->triangles, GL_TRIANGLES,
+ dm->drawObject->materials[a].start, dm->drawObject->materials[a].totelements);
+ if (matconv[a].numdata) {
+ GPU_interleaved_attrib_unbind();
}
}
- GPU_buffer_unbind();
}
- GPU_buffer_free(buffer);
- }
+ GPU_buffers_unbind();
+ if (buffer)
+ GPU_buffer_free(buffer);
+
+ MEM_freeN(mat_orig_to_new);
+ MEM_freeN(matconv);
+ }
+
glShadeModel(GL_FLAT);
}
@@ -1564,56 +1124,58 @@ static void cdDM_drawFacesGLSL(DerivedMesh *dm, DMSetMaterial setMaterial)
dm->drawMappedFacesGLSL(dm, setMaterial, NULL, NULL);
}
-static void cdDM_drawMappedFacesMat(DerivedMesh *dm,
- void (*setMaterial)(void *userData, int matnr, void *attribs),
- bool (*setFace)(void *userData, int index), void *userData)
+static void cdDM_drawMappedFacesMat(
+ DerivedMesh *dm,
+ void (*setMaterial)(void *userData, int matnr, void *attribs),
+ bool (*setFace)(void *userData, int index), void *userData)
{
CDDerivedMesh *cddm = (CDDerivedMesh *) dm;
GPUVertexAttribs gattribs;
DMVertexAttribs attribs;
MVert *mvert = cddm->mvert;
- MFace *mf = cddm->mface;
- const float (*nors)[3] = dm->getTessFaceDataArray(dm, CD_NORMAL);
- const short (*lnors)[4][3] = dm->getTessFaceDataArray(dm, CD_TESSLOOPNORMAL);
+ const MPoly *mpoly = cddm->mpoly;
+ const MLoop *mloop = cddm->mloop;
+ const MLoopTri *lt = dm->getLoopTriArray(dm);
+ const int tottri = dm->getNumLoopTri(dm);
+ const float (*nors)[3] = dm->getPolyDataArray(dm, CD_NORMAL);
+ const float (*lnors)[3] = dm->getLoopDataArray(dm, CD_NORMAL);
int a, matnr, new_matnr;
int orig;
- /* double lookup */
- const int *index_mf_to_mpoly = dm->getTessFaceDataArray(dm, CD_ORIGINDEX);
const int *index_mp_to_orig = dm->getPolyDataArray(dm, CD_ORIGINDEX);
- if (index_mf_to_mpoly == NULL) {
- index_mp_to_orig = NULL;
- }
/* TODO: same as for solid draw, not entirely correct, but works fine for now,
* will skip using textures (dyntopo currently destroys UV anyway) and
* works fine for matcap
*/
+
if (cddm->pbvh && cddm->pbvh_draw && BKE_pbvh_type(cddm->pbvh) == PBVH_BMESH) {
- if (dm->numTessFaceData) {
+ if (BKE_pbvh_has_faces(cddm->pbvh)) {
+ cdDM_update_normals_from_pbvh(dm);
setMaterial(userData, 1, &gattribs);
- BKE_pbvh_draw(cddm->pbvh, NULL, NULL, NULL, false);
+ BKE_pbvh_draw(cddm->pbvh, NULL, NULL, NULL, false, false);
}
return;
}
- cdDM_update_normals_from_pbvh(dm);
-
matnr = -1;
glShadeModel(GL_SMOOTH);
memset(&attribs, 0, sizeof(attribs));
- glBegin(GL_QUADS);
+ glBegin(GL_TRIANGLES);
- for (a = 0; a < dm->numTessFaceData; a++, mf++) {
- const bool smoothnormal = lnors || (mf->flag & ME_SMOOTH);
- const short (*ln1)[3] = NULL, (*ln2)[3] = NULL, (*ln3)[3] = NULL, (*ln4)[3] = NULL;
+ for (a = 0; a < tottri; a++, lt++) {
+ const MPoly *mp = &mpoly[lt->poly];
+ const unsigned int vtri[3] = {mloop[lt->tri[0]].v, mloop[lt->tri[1]].v, mloop[lt->tri[2]].v};
+ const unsigned int *ltri = lt->tri;
+ const bool smoothnormal = lnors || (mp->flag & ME_SMOOTH);
+ const float *ln1 = NULL, *ln2 = NULL, *ln3 = NULL;
/* material */
- new_matnr = mf->mat_nr + 1;
+ new_matnr = mp->mat_nr + 1;
if (new_matnr != matnr) {
glEnd();
@@ -1621,12 +1183,12 @@ static void cdDM_drawMappedFacesMat(DerivedMesh *dm,
setMaterial(userData, matnr = new_matnr, &gattribs);
DM_vertex_attributes_from_gpu(dm, &gattribs, &attribs);
- glBegin(GL_QUADS);
+ glBegin(GL_TRIANGLES);
}
/* skipping faces */
if (setFace) {
- orig = (index_mf_to_mpoly) ? DM_origindex_mface_mpoly(index_mf_to_mpoly, index_mp_to_orig, a) : a;
+ orig = (index_mp_to_orig) ? index_mp_to_orig[lt->poly] : lt->poly;
if (orig != ORIGINDEX_NONE && !setFace(userData, orig))
continue;
@@ -1635,36 +1197,25 @@ static void cdDM_drawMappedFacesMat(DerivedMesh *dm,
/* smooth normal */
if (!smoothnormal) {
if (nors) {
- glNormal3fv(nors[a]);
+ glNormal3fv(nors[lt->poly]);
}
else {
/* TODO ideally a normal layer should always be available */
float nor[3];
-
- if (mf->v4)
- normal_quad_v3(nor, mvert[mf->v1].co, mvert[mf->v2].co, mvert[mf->v3].co, mvert[mf->v4].co);
- else
- normal_tri_v3(nor, mvert[mf->v1].co, mvert[mf->v2].co, mvert[mf->v3].co);
-
+ normal_tri_v3(nor, mvert[vtri[0]].co, mvert[vtri[1]].co, mvert[vtri[2]].co);
glNormal3fv(nor);
}
}
else if (lnors) {
- ln1 = &lnors[a][0];
- ln2 = &lnors[a][1];
- ln3 = &lnors[a][2];
- ln4 = &lnors[a][3];
+ ln1 = lnors[ltri[0]];
+ ln2 = lnors[ltri[1]];
+ ln3 = lnors[ltri[2]];
}
/* vertices */
- cddm_draw_attrib_vertex(&attribs, mvert, a, mf->v1, 0, ln1, smoothnormal);
- cddm_draw_attrib_vertex(&attribs, mvert, a, mf->v2, 1, ln2, smoothnormal);
- cddm_draw_attrib_vertex(&attribs, mvert, a, mf->v3, 2, ln3, smoothnormal);
-
- if (mf->v4)
- cddm_draw_attrib_vertex(&attribs, mvert, a, mf->v4, 3, ln4, smoothnormal);
- else
- cddm_draw_attrib_vertex(&attribs, mvert, a, mf->v3, 2, ln3, smoothnormal);
+ cddm_draw_attrib_vertex(&attribs, mvert, a, vtri[0], ltri[0], 0, ln1, smoothnormal);
+ cddm_draw_attrib_vertex(&attribs, mvert, a, vtri[1], ltri[1], 1, ln2, smoothnormal);
+ cddm_draw_attrib_vertex(&attribs, mvert, a, vtri[2], ltri[2], 2, ln3, smoothnormal);
}
glEnd();
@@ -1695,6 +1246,499 @@ static void cdDM_drawMappedEdges(DerivedMesh *dm, DMSetDrawOptions setDrawOption
glEnd();
}
+typedef struct FaceCount {
+ unsigned int i_visible;
+ unsigned int i_hidden;
+ unsigned int i_tri_visible;
+ unsigned int i_tri_hidden;
+} FaceCount;
+
+static void cdDM_buffer_copy_triangles(
+ DerivedMesh *dm, unsigned int *varray,
+ const int *mat_orig_to_new)
+{
+ GPUBufferMaterial *gpumat, *gpumaterials = dm->drawObject->materials;
+ int i, j, start;
+
+ const int gpu_totmat = dm->drawObject->totmaterial;
+ const short dm_totmat = dm->totmat;
+ const MPoly *mpoly = dm->getPolyArray(dm);
+ const MLoopTri *lt = dm->getLoopTriArray(dm);
+ const int totpoly = dm->getNumPolys(dm);
+
+ FaceCount *fc = MEM_mallocN(sizeof(*fc) * gpu_totmat, "gpumaterial.facecount");
+
+ for (i = 0; i < gpu_totmat; i++) {
+ fc[i].i_visible = 0;
+ fc[i].i_tri_visible = 0;
+ fc[i].i_hidden = gpumaterials[i].totpolys - 1;
+ fc[i].i_tri_hidden = gpumaterials[i].totelements - 1;
+ }
+
+ for (i = 0; i < totpoly; i++) {
+ const short mat_nr = ME_MAT_NR_TEST(mpoly[i].mat_nr, dm_totmat);
+ int tottri = ME_POLY_TRI_TOT(&mpoly[i]);
+ int mati = mat_orig_to_new[mat_nr];
+ gpumat = gpumaterials + mati;
+
+ if (mpoly[i].flag & ME_HIDE) {
+ for (j = 0; j < tottri; j++, lt++) {
+ start = gpumat->start + fc[mati].i_tri_hidden;
+ /* v1 v2 v3 */
+ varray[start--] = lt->tri[2];
+ varray[start--] = lt->tri[1];
+ varray[start--] = lt->tri[0];
+ fc[mati].i_tri_hidden -= 3;
+ }
+ gpumat->polys[fc[mati].i_hidden--] = i;
+ }
+ else {
+ for (j = 0; j < tottri; j++, lt++) {
+ start = gpumat->start + fc[mati].i_tri_visible;
+ /* v1 v2 v3 */
+ varray[start++] = lt->tri[0];
+ varray[start++] = lt->tri[1];
+ varray[start++] = lt->tri[2];
+ fc[mati].i_tri_visible += 3;
+ }
+ gpumat->polys[fc[mati].i_visible++] = i;
+ }
+ }
+
+ /* set the visible polygons */
+ for (i = 0; i < gpu_totmat; i++) {
+ gpumaterials[i].totvisiblepolys = fc[i].i_visible;
+ }
+
+ MEM_freeN(fc);
+}
+
+static void cdDM_buffer_copy_vertex(
+ DerivedMesh *dm, float *varray)
+{
+ const MVert *mvert;
+ const MPoly *mpoly;
+ const MLoop *mloop;
+
+ int i, j, start, totpoly;
+
+ mvert = dm->getVertArray(dm);
+ mpoly = dm->getPolyArray(dm);
+ mloop = dm->getLoopArray(dm);
+ totpoly = dm->getNumPolys(dm);
+
+ start = 0;
+
+ for (i = 0; i < totpoly; i++, mpoly++) {
+ for (j = 0; j < mpoly->totloop; j++) {
+ copy_v3_v3(&varray[start], mvert[mloop[mpoly->loopstart + j].v].co);
+ start += 3;
+ }
+ }
+
+ /* copy loose points */
+ j = dm->drawObject->tot_loop_verts * 3;
+ for (i = 0; i < dm->drawObject->totvert; i++) {
+ if (dm->drawObject->vert_points[i].point_index >= dm->drawObject->tot_loop_verts) {
+ copy_v3_v3(&varray[j], mvert[i].co);
+ j += 3;
+ }
+ }
+}
+
+static void cdDM_buffer_copy_normal(
+ DerivedMesh *dm, short *varray)
+{
+ int i, j, totpoly;
+ int start;
+
+ const float (*nors)[3] = dm->getPolyDataArray(dm, CD_NORMAL);
+ const float (*lnors)[3] = dm->getLoopDataArray(dm, CD_NORMAL);
+
+ const MVert *mvert;
+ const MPoly *mpoly;
+ const MLoop *mloop;
+
+ mvert = dm->getVertArray(dm);
+ mpoly = dm->getPolyArray(dm);
+ mloop = dm->getLoopArray(dm);
+ totpoly = dm->getNumPolys(dm);
+
+ start = 0;
+ for (i = 0; i < totpoly; i++, mpoly++) {
+ const bool smoothnormal = (mpoly->flag & ME_SMOOTH) != 0;
+
+ if (lnors) {
+ /* Copy loop normals */
+ for (j = 0; j < mpoly->totloop; j++, start += 4) {
+ normal_float_to_short_v3(&varray[start], lnors[mpoly->loopstart + j]);
+ }
+ }
+ else if (smoothnormal) {
+ /* Copy vertex normal */
+ for (j = 0; j < mpoly->totloop; j++, start += 4) {
+ copy_v3_v3_short(&varray[start], mvert[mloop[mpoly->loopstart + j].v].no);
+ }
+ }
+ else {
+ /* Copy cached OR calculated face normal */
+ short f_no_s[3];
+
+ if (nors) {
+ normal_float_to_short_v3(f_no_s, nors[i]);
+ }
+ else {
+ float f_no[3];
+ BKE_mesh_calc_poly_normal(mpoly, &mloop[mpoly->loopstart], mvert, f_no);
+ normal_float_to_short_v3(f_no_s, f_no);
+ }
+
+ for (j = 0; j < mpoly->totloop; j++, start += 4) {
+ copy_v3_v3_short(&varray[start], f_no_s);
+ }
+ }
+ }
+}
+
+static void cdDM_buffer_copy_uv(
+ DerivedMesh *dm, float *varray)
+{
+ int i, j, totpoly;
+ int start;
+
+ const MPoly *mpoly;
+ const MLoopUV *mloopuv;
+
+ if ((mloopuv = DM_get_loop_data_layer(dm, CD_MLOOPUV)) == NULL) {
+ return;
+ }
+
+ mpoly = dm->getPolyArray(dm);
+ totpoly = dm->getNumPolys(dm);
+
+ start = 0;
+ for (i = 0; i < totpoly; i++, mpoly++) {
+ for (j = 0; j < mpoly->totloop; j++) {
+ copy_v2_v2(&varray[start], mloopuv[mpoly->loopstart + j].uv);
+ start += 2;
+ }
+ }
+}
+
+static void cdDM_buffer_copy_uv_texpaint(
+ DerivedMesh *dm, float *varray)
+{
+ int i, j, totpoly;
+ int start;
+
+ const MPoly *mpoly;
+
+ int totmaterial = dm->totmat;
+ const MLoopUV **uv_base;
+ const MLoopUV *uv_stencil_base;
+ int stencil;
+
+ totpoly = dm->getNumPolys(dm);
+
+ /* should have been checked for before, reassert */
+ BLI_assert(DM_get_loop_data_layer(dm, CD_MLOOPUV));
+ uv_base = MEM_mallocN(totmaterial * sizeof(*uv_base), "texslots");
+
+ for (i = 0; i < totmaterial; i++) {
+ uv_base[i] = DM_paint_uvlayer_active_get(dm, i);
+ }
+
+ stencil = CustomData_get_stencil_layer(&dm->loopData, CD_MLOOPUV);
+ uv_stencil_base = CustomData_get_layer_n(&dm->loopData, CD_MLOOPUV, stencil);
+
+ mpoly = dm->getPolyArray(dm);
+ start = 0;
+
+ for (i = 0; i < totpoly; i++, mpoly++) {
+ int mat_i = mpoly->mat_nr;
+
+ for (j = 0; j < mpoly->totloop; j++) {
+ copy_v2_v2(&varray[start], uv_base[mat_i][mpoly->loopstart + j].uv);
+ copy_v2_v2(&varray[start + 2], uv_stencil_base[mpoly->loopstart + j].uv);
+ start += 4;
+ }
+ }
+
+ MEM_freeN(uv_base);
+}
+
+/* treat varray_ as an array of MCol, four MCol's per face */
+static void cdDM_buffer_copy_mcol(
+ DerivedMesh *dm, unsigned char *varray,
+ const void *user_data)
+{
+ int i, j, totpoly;
+ int start;
+
+ const MLoopCol *mloopcol = user_data;
+ const MPoly *mpoly = dm->getPolyArray(dm);
+
+ totpoly = dm->getNumPolys(dm);
+
+ start = 0;
+
+ for (i = 0; i < totpoly; i++, mpoly++) {
+ for (j = 0; j < mpoly->totloop; j++) {
+ copy_v3_v3_char((char *)&varray[start], &mloopcol[mpoly->loopstart + j].r);
+ start += 3;
+ }
+ }
+}
+
+static void cdDM_buffer_copy_edge(
+ DerivedMesh *dm, unsigned int *varray)
+{
+ MEdge *medge, *medge_base;
+ int i, totedge, iloose, inorm, iloosehidden, inormhidden;
+ int tot_loose_hidden = 0, tot_loose = 0;
+ int tot_hidden = 0, tot = 0;
+
+ medge_base = medge = dm->getEdgeArray(dm);
+ totedge = dm->getNumEdges(dm);
+
+ for (i = 0; i < totedge; i++, medge++) {
+ if (medge->flag & ME_EDGEDRAW) {
+ if (medge->flag & ME_LOOSEEDGE) tot_loose++;
+ else tot++;
+ }
+ else {
+ if (medge->flag & ME_LOOSEEDGE) tot_loose_hidden++;
+ else tot_hidden++;
+ }
+ }
+
+ inorm = 0;
+ inormhidden = tot;
+ iloose = tot + tot_hidden;
+ iloosehidden = iloose + tot_loose;
+
+ medge = medge_base;
+ for (i = 0; i < totedge; i++, medge++) {
+ if (medge->flag & ME_EDGEDRAW) {
+ if (medge->flag & ME_LOOSEEDGE) {
+ varray[iloose * 2] = dm->drawObject->vert_points[medge->v1].point_index;
+ varray[iloose * 2 + 1] = dm->drawObject->vert_points[medge->v2].point_index;
+ iloose++;
+ }
+ else {
+ varray[inorm * 2] = dm->drawObject->vert_points[medge->v1].point_index;
+ varray[inorm * 2 + 1] = dm->drawObject->vert_points[medge->v2].point_index;
+ inorm++;
+ }
+ }
+ else {
+ if (medge->flag & ME_LOOSEEDGE) {
+ varray[iloosehidden * 2] = dm->drawObject->vert_points[medge->v1].point_index;
+ varray[iloosehidden * 2 + 1] = dm->drawObject->vert_points[medge->v2].point_index;
+ iloosehidden++;
+ }
+ else {
+ varray[inormhidden * 2] = dm->drawObject->vert_points[medge->v1].point_index;
+ varray[inormhidden * 2 + 1] = dm->drawObject->vert_points[medge->v2].point_index;
+ inormhidden++;
+ }
+ }
+ }
+
+ dm->drawObject->tot_loose_edge_drawn = tot_loose;
+ dm->drawObject->loose_edge_offset = tot + tot_hidden;
+ dm->drawObject->tot_edge_drawn = tot;
+}
+
+static void cdDM_buffer_copy_uvedge(
+ DerivedMesh *dm, float *varray)
+{
+ int i, j, totpoly;
+ int start;
+ const MLoopUV *mloopuv;
+ const MPoly *mpoly = dm->getPolyArray(dm);
+
+ if ((mloopuv = DM_get_loop_data_layer(dm, CD_MLOOPUV)) == NULL) {
+ return;
+ }
+
+ totpoly = dm->getNumPolys(dm);
+ start = 0;
+
+ for (i = 0; i < totpoly; i++, mpoly++) {
+ for (j = 0; j < mpoly->totloop; j++) {
+ copy_v2_v2(&varray[start], mloopuv[mpoly->loopstart + j].uv);
+ copy_v2_v2(&varray[start + 2], mloopuv[mpoly->loopstart + (j + 1) % mpoly->totloop].uv);
+ start += 4;
+ }
+ }
+}
+
+static void cdDM_copy_gpu_data(
+ DerivedMesh *dm, int type, void *varray_p,
+ const int *mat_orig_to_new, const void *user_data)
+{
+ /* 'varray_p' cast is redundant but include for self-documentation */
+ switch (type) {
+ case GPU_BUFFER_VERTEX:
+ cdDM_buffer_copy_vertex(dm, (float *)varray_p);
+ break;
+ case GPU_BUFFER_NORMAL:
+ cdDM_buffer_copy_normal(dm, (short *)varray_p);
+ break;
+ case GPU_BUFFER_COLOR:
+ cdDM_buffer_copy_mcol(dm, (unsigned char *)varray_p, user_data);
+ break;
+ case GPU_BUFFER_UV:
+ cdDM_buffer_copy_uv(dm, (float *)varray_p);
+ break;
+ case GPU_BUFFER_UV_TEXPAINT:
+ cdDM_buffer_copy_uv_texpaint(dm, (float *)varray_p);
+ break;
+ case GPU_BUFFER_EDGE:
+ cdDM_buffer_copy_edge(dm, (unsigned int *)varray_p);
+ break;
+ case GPU_BUFFER_UVEDGE:
+ cdDM_buffer_copy_uvedge(dm, (float *)varray_p);
+ break;
+ case GPU_BUFFER_TRIANGLES:
+ cdDM_buffer_copy_triangles(dm, (unsigned int *)varray_p, mat_orig_to_new);
+ break;
+ default:
+ break;
+ }
+}
+
+/* add a new point to the list of points related to a particular
+ * vertex */
+#ifdef USE_GPU_POINT_LINK
+
+static void cdDM_drawobject_add_vert_point(GPUDrawObject *gdo, int vert_index, int point_index)
+{
+ GPUVertPointLink *lnk;
+
+ lnk = &gdo->vert_points[vert_index];
+
+ /* if first link is in use, add a new link at the end */
+ if (lnk->point_index != -1) {
+ /* get last link */
+ for (; lnk->next; lnk = lnk->next) ;
+
+ /* add a new link from the pool */
+ lnk = lnk->next = &gdo->vert_points_mem[gdo->vert_points_usage];
+ gdo->vert_points_usage++;
+ }
+
+ lnk->point_index = point_index;
+}
+
+#else
+
+static void cdDM_drawobject_add_vert_point(GPUDrawObject *gdo, int vert_index, int point_index)
+{
+ GPUVertPointLink *lnk;
+ lnk = &gdo->vert_points[vert_index];
+ if (lnk->point_index == -1) {
+ lnk->point_index = point_index;
+ }
+}
+
+#endif /* USE_GPU_POINT_LINK */
+
+/* for each vertex, build a list of points related to it; these lists
+ * are stored in an array sized to the number of vertices */
+static void cdDM_drawobject_init_vert_points(
+ GPUDrawObject *gdo,
+ const MPoly *mpoly, const MLoop *mloop,
+ int tot_poly)
+{
+ int i;
+ int tot_loops = 0;
+
+ /* allocate the array and space for links */
+ gdo->vert_points = MEM_mallocN(sizeof(GPUVertPointLink) * gdo->totvert,
+ "GPUDrawObject.vert_points");
+#ifdef USE_GPU_POINT_LINK
+ gdo->vert_points_mem = MEM_callocN(sizeof(GPUVertPointLink) * gdo->totvert,
+ "GPUDrawObject.vert_points_mem");
+ gdo->vert_points_usage = 0;
+#endif
+
+ /* -1 indicates the link is not yet used */
+ for (i = 0; i < gdo->totvert; i++) {
+#ifdef USE_GPU_POINT_LINK
+ gdo->vert_points[i].link = NULL;
+#endif
+ gdo->vert_points[i].point_index = -1;
+ }
+
+ for (i = 0; i < tot_poly; i++) {
+ int j;
+ const MPoly *mp = &mpoly[i];
+
+ /* assign unique indices to vertices of the mesh */
+ for (j = 0; j < mp->totloop; j++) {
+ cdDM_drawobject_add_vert_point(gdo, mloop[mp->loopstart + j].v, tot_loops + j);
+ }
+ tot_loops += mp->totloop;
+ }
+
+ /* map any unused vertices to loose points */
+ for (i = 0; i < gdo->totvert; i++) {
+ if (gdo->vert_points[i].point_index == -1) {
+ gdo->vert_points[i].point_index = gdo->tot_loop_verts + gdo->tot_loose_point;
+ gdo->tot_loose_point++;
+ }
+ }
+}
+
+/* see GPUDrawObject's structure definition for a description of the
+ * data being initialized here */
+static GPUDrawObject *cdDM_GPUobject_new(DerivedMesh *dm)
+{
+ GPUDrawObject *gdo;
+ const MPoly *mpoly;
+ const MLoop *mloop;
+ const short dm_totmat = dm->totmat;
+ GPUBufferMaterial *mat_info;
+ int i, totloops, totpolys;
+
+ /* object contains at least one material (default included) so zero means uninitialized dm */
+ BLI_assert(dm_totmat != 0);
+
+ mpoly = dm->getPolyArray(dm);
+ mloop = dm->getLoopArray(dm);
+
+ totpolys = dm->getNumPolys(dm);
+ totloops = dm->getNumLoops(dm);
+
+ /* get the number of points used by each material, treating
+ * each quad as two triangles */
+ mat_info = MEM_callocN(sizeof(*mat_info) * dm_totmat, "GPU_drawobject_new.mat_orig_to_new");
+
+ for (i = 0; i < totpolys; i++) {
+ const short mat_nr = ME_MAT_NR_TEST(mpoly[i].mat_nr, dm_totmat);
+ mat_info[mat_nr].totpolys++;
+ mat_info[mat_nr].totelements += 3 * ME_POLY_TRI_TOT(&mpoly[i]);
+ mat_info[mat_nr].totloops += mpoly[i].totloop;
+ }
+ /* create the GPUDrawObject */
+ gdo = MEM_callocN(sizeof(GPUDrawObject), "GPUDrawObject");
+ gdo->totvert = dm->getNumVerts(dm);
+ gdo->totedge = dm->getNumEdges(dm);
+
+ GPU_buffer_material_finalize(gdo, mat_info, dm_totmat);
+
+ gdo->tot_loop_verts = totloops;
+
+ /* store total number of points used for triangles */
+ gdo->tot_triangle_point = poly_to_tri_count(totpolys, totloops) * 3;
+
+ cdDM_drawobject_init_vert_points(gdo, mpoly, mloop, totpolys);
+
+ return gdo;
+}
+
static void cdDM_foreachMappedVert(
DerivedMesh *dm,
void (*func)(void *userData, int index, const float co[3], const float no_f[3], const short no_s[3]),
@@ -1816,10 +1860,11 @@ void CDDM_recalc_tessellation_ex(DerivedMesh *dm, const bool do_face_nor_cpy)
{
CDDerivedMesh *cddm = (CDDerivedMesh *)dm;
- dm->numTessFaceData = BKE_mesh_recalc_tessellation(&dm->faceData, &dm->loopData, &dm->polyData,
- cddm->mvert,
- dm->numTessFaceData, dm->numLoopData, dm->numPolyData,
- do_face_nor_cpy);
+ dm->numTessFaceData = BKE_mesh_recalc_tessellation(
+ &dm->faceData, &dm->loopData, &dm->polyData,
+ cddm->mvert,
+ dm->numTessFaceData, dm->numLoopData, dm->numPolyData,
+ do_face_nor_cpy);
cddm->mface = CustomData_get_layer(&dm->faceData, CD_MFACE);
@@ -1833,6 +1878,34 @@ void CDDM_recalc_tessellation(DerivedMesh *dm)
CDDM_recalc_tessellation_ex(dm, true);
}
+void CDDM_recalc_looptri(DerivedMesh *dm)
+{
+ CDDerivedMesh *cddm = (CDDerivedMesh *)dm;
+ const unsigned int totpoly = dm->numPolyData;
+ const unsigned int totloop = dm->numLoopData;
+
+ DM_ensure_looptri_data(dm);
+
+ BKE_mesh_recalc_looptri(
+ cddm->mloop, cddm->mpoly,
+ cddm->mvert,
+ totloop, totpoly,
+ cddm->dm.looptris.array);
+}
+
+static const MLoopTri *cdDM_getLoopTriArray(DerivedMesh *dm)
+{
+ if (dm->looptris.array) {
+ BLI_assert(poly_to_tri_count(dm->numPolyData, dm->numLoopData) == dm->looptris.num);
+ }
+ else {
+ dm->recalcLoopTri(dm);
+
+ /* ccdm is an exception here, that recalcLoopTri will fill in the array too */
+ }
+ return dm->looptris.array;
+}
+
static void cdDM_free_internal(CDDerivedMesh *cddm)
{
if (cddm->pmap) MEM_freeN(cddm->pmap);
@@ -1883,9 +1956,14 @@ static CDDerivedMesh *cdDM_create(const char *desc)
dm->getEdgeDataArray = DM_get_edge_data_layer;
dm->getTessFaceDataArray = DM_get_tessface_data_layer;
+ dm->getLoopTriArray = cdDM_getLoopTriArray;
+
dm->calcNormals = CDDM_calc_normals;
dm->calcLoopNormals = CDDM_calc_loop_normals;
+ dm->calcLoopNormalsSpaceArray = CDDM_calc_loop_normals_spacearr;
+ dm->calcLoopTangents = DM_calc_loop_tangents;
dm->recalcTessellation = CDDM_recalc_tessellation;
+ dm->recalcLoopTri = CDDM_recalc_looptri;
dm->getVertCos = cdDM_getVertCos;
dm->getVertCo = cdDM_getVertCo;
@@ -1909,6 +1987,9 @@ static CDDerivedMesh *cdDM_create(const char *desc)
dm->drawMappedFacesGLSL = cdDM_drawMappedFacesGLSL;
dm->drawMappedFacesMat = cdDM_drawMappedFacesMat;
+ dm->gpuObjectNew = cdDM_GPUobject_new;
+ dm->copy_gpu_data = cdDM_copy_gpu_data;
+
dm->foreachMappedVert = cdDM_foreachMappedVert;
dm->foreachMappedEdge = cdDM_foreachMappedEdge;
dm->foreachMappedLoop = cdDM_foreachMappedLoop;
@@ -1955,7 +2036,7 @@ DerivedMesh *CDDM_from_mesh(Mesh *mesh)
/* this does a referenced copy, with an exception for fluidsim */
- DM_init(dm, DM_TYPE_CDDM, mesh->totvert, mesh->totedge, mesh->totface,
+ DM_init(dm, DM_TYPE_CDDM, mesh->totvert, mesh->totedge, 0 /* mesh->totface */,
mesh->totloop, mesh->totpoly);
dm->deformedOnly = 1;
@@ -1968,7 +2049,7 @@ DerivedMesh *CDDM_from_mesh(Mesh *mesh)
CustomData_merge(&mesh->edata, &dm->edgeData, mask, alloctype,
mesh->totedge);
CustomData_merge(&mesh->fdata, &dm->faceData, mask | CD_MASK_ORIGINDEX, alloctype,
- mesh->totface);
+ 0 /* mesh->totface */);
CustomData_merge(&mesh->ldata, &dm->loopData, mask, alloctype,
mesh->totloop);
CustomData_merge(&mesh->pdata, &dm->polyData, mask, alloctype,
@@ -1978,7 +2059,11 @@ DerivedMesh *CDDM_from_mesh(Mesh *mesh)
cddm->medge = CustomData_get_layer(&dm->edgeData, CD_MEDGE);
cddm->mloop = CustomData_get_layer(&dm->loopData, CD_MLOOP);
cddm->mpoly = CustomData_get_layer(&dm->polyData, CD_MPOLY);
+#if 0
cddm->mface = CustomData_get_layer(&dm->faceData, CD_MFACE);
+#else
+ cddm->mface = NULL;
+#endif
/* commented since even when CD_ORIGINDEX was first added this line fails
* on the default cube, (after editmode toggle too) - campbell */
@@ -2013,9 +2098,10 @@ DerivedMesh *CDDM_from_curve_displist(Object *ob, ListBase *dispbase)
int totvert, totedge, totloop, totpoly;
bool use_orco_uv = (cu->flag & CU_UV_ORCO) != 0;
- if (BKE_mesh_nurbs_displist_to_mdata(ob, dispbase, &allvert, &totvert, &alledge,
- &totedge, &allloop, &allpoly, (use_orco_uv) ? &alluv : NULL,
- &totloop, &totpoly) != 0)
+ if (BKE_mesh_nurbs_displist_to_mdata(
+ ob, dispbase, &allvert, &totvert, &alledge,
+ &totedge, &allloop, &allpoly, (use_orco_uv) ? &alluv : NULL,
+ &totloop, &totpoly) != 0)
{
/* Error initializing mdata. This often happens when curve is empty */
return CDDM_new(0, 0, 0, 0, 0);
@@ -2046,9 +2132,10 @@ DerivedMesh *CDDM_from_curve_displist(Object *ob, ListBase *dispbase)
return dm;
}
-static void loops_to_customdata_corners(BMesh *bm, CustomData *facedata,
- int cdindex, const BMLoop *l3[3],
- int numCol, int numTex)
+static void loops_to_customdata_corners(
+ BMesh *bm, CustomData *facedata,
+ int cdindex, const BMLoop *l3[3],
+ int numCol, int numTex)
{
const BMLoop *l;
BMFace *f = l3[0]->f;
@@ -2094,11 +2181,11 @@ static void loops_to_customdata_corners(BMesh *bm, CustomData *facedata,
}
/* used for both editbmesh and bmesh */
-static DerivedMesh *cddm_from_bmesh_ex(struct BMesh *bm, const bool use_mdisps,
- /* EditBMesh vars for use_tessface */
- const bool use_tessface,
- const int em_tottri, const BMLoop *(*em_looptris)[3]
- )
+static DerivedMesh *cddm_from_bmesh_ex(
+ struct BMesh *bm, const bool use_mdisps,
+ /* EditBMesh vars for use_tessface */
+ const bool use_tessface,
+ const int em_tottri, const BMLoop *(*em_looptris)[3])
{
DerivedMesh *dm = CDDM_new(bm->totvert,
bm->totedge,
@@ -2263,16 +2350,18 @@ static DerivedMesh *cddm_from_bmesh_ex(struct BMesh *bm, const bool use_mdisps,
struct DerivedMesh *CDDM_from_bmesh(struct BMesh *bm, const bool use_mdisps)
{
- return cddm_from_bmesh_ex(bm, use_mdisps, false,
- /* these vars are for editmesh only */
- 0, NULL);
+ return cddm_from_bmesh_ex(
+ bm, use_mdisps, false,
+ /* these vars are for editmesh only */
+ 0, NULL);
}
DerivedMesh *CDDM_from_editbmesh(BMEditMesh *em, const bool use_mdisps, const bool use_tessface)
{
- return cddm_from_bmesh_ex(em->bm, use_mdisps,
- /* editmesh */
- use_tessface, em->tottri, (const BMLoop *(*)[3])em->looptris);
+ return cddm_from_bmesh_ex(
+ em->bm, use_mdisps,
+ /* editmesh */
+ use_tessface, em->tottri, (const BMLoop *(*)[3])em->looptris);
}
static DerivedMesh *cddm_copy_ex(DerivedMesh *source, int faces_from_tessfaces)
@@ -2334,9 +2423,11 @@ DerivedMesh *CDDM_copy_from_tessface(DerivedMesh *source)
/* note, the CD_ORIGINDEX layers are all 0, so if there is a direct
* relationship between mesh data this needs to be set by the caller. */
-DerivedMesh *CDDM_from_template(DerivedMesh *source,
- int numVerts, int numEdges, int numTessFaces,
- int numLoops, int numPolys)
+DerivedMesh *CDDM_from_template_ex(
+ DerivedMesh *source,
+ int numVerts, int numEdges, int numTessFaces,
+ int numLoops, int numPolys,
+ CustomDataMask mask)
{
CDDerivedMesh *cddm = cdDM_create("CDDM_from_template dest");
DerivedMesh *dm = &cddm->dm;
@@ -2348,7 +2439,11 @@ DerivedMesh *CDDM_from_template(DerivedMesh *source,
source->getPolyDataArray(source, CD_ORIGINDEX);
/* this does a copy of all non mvert/medge/mface layers */
- DM_from_template(dm, source, DM_TYPE_CDDM, numVerts, numEdges, numTessFaces, numLoops, numPolys);
+ DM_from_template_ex(
+ dm, source, DM_TYPE_CDDM,
+ numVerts, numEdges, numTessFaces,
+ numLoops, numPolys,
+ mask);
/* now add mvert/medge/mface layers */
CustomData_add_layer(&dm->vertData, CD_MVERT, CD_CALLOC, NULL, numVerts);
@@ -2372,6 +2467,16 @@ DerivedMesh *CDDM_from_template(DerivedMesh *source,
return dm;
}
+DerivedMesh *CDDM_from_template(
+ DerivedMesh *source,
+ int numVerts, int numEdges, int numTessFaces,
+ int numLoops, int numPolys)
+{
+ return CDDM_from_template_ex(
+ source, numVerts, numEdges, numTessFaces,
+ numLoops, numPolys,
+ CD_MASK_DERIVEDMESH);
+}
void CDDM_apply_vert_coords(DerivedMesh *dm, float (*vertCoords)[3])
{
@@ -2424,7 +2529,7 @@ void CDDM_calc_normals_mapping_ex(DerivedMesh *dm, const bool only_face_normals)
cddm->mvert = CustomData_duplicate_referenced_layer(&dm->vertData, CD_MVERT, dm->numVertData);
#endif
-
+#if 0
if (dm->numTessFaceData == 0) {
/* No tessellation on this mesh yet, need to calculate one.
*
@@ -2438,16 +2543,17 @@ void CDDM_calc_normals_mapping_ex(DerivedMesh *dm, const bool only_face_normals)
BLI_assert(CustomData_has_layer(&dm->faceData, CD_ORIGINDEX));
CustomData_free_layers(&dm->faceData, CD_NORMAL, dm->numTessFaceData);
}
+#endif
- face_nors = MEM_mallocN(sizeof(*face_nors) * dm->numTessFaceData, "face_nors");
+ face_nors = MEM_mallocN(sizeof(*face_nors) * dm->numPolyData, "face_nors");
/* calculate face normals */
- BKE_mesh_calc_normals_mapping_ex(cddm->mvert, dm->numVertData, CDDM_get_loops(dm), CDDM_get_polys(dm),
- dm->numLoopData, dm->numPolyData, NULL, cddm->mface, dm->numTessFaceData,
- CustomData_get_layer(&dm->faceData, CD_ORIGINDEX), face_nors,
- only_face_normals);
+ BKE_mesh_calc_normals_poly(
+ cddm->mvert, dm->numVertData, CDDM_get_loops(dm), CDDM_get_polys(dm),
+ dm->numLoopData, dm->numPolyData, face_nors,
+ only_face_normals);
- CustomData_add_layer(&dm->faceData, CD_NORMAL, CD_ASSIGN, face_nors, dm->numTessFaceData);
+ CustomData_add_layer(&dm->polyData, CD_NORMAL, CD_ASSIGN, face_nors, dm->numPolyData);
cddm->dm.dirty &= ~DM_DIRTY_NORMALS;
}
@@ -2501,7 +2607,15 @@ void CDDM_calc_normals(DerivedMesh *dm)
#endif
-void CDDM_calc_loop_normals(DerivedMesh *dm, const float split_angle)
+void CDDM_calc_loop_normals(DerivedMesh *dm, const bool use_split_normals, const float split_angle)
+{
+ CDDM_calc_loop_normals_spacearr(dm, use_split_normals, split_angle, NULL);
+}
+
+/* #define DEBUG_CLNORS */
+
+void CDDM_calc_loop_normals_spacearr(
+ DerivedMesh *dm, const bool use_split_normals, const float split_angle, MLoopNorSpaceArray *r_lnors_spacearr)
{
MVert *mverts = dm->getVertArray(dm);
MEdge *medges = dm->getEdgeArray(dm);
@@ -2511,6 +2625,7 @@ void CDDM_calc_loop_normals(DerivedMesh *dm, const float split_angle)
CustomData *ldata, *pdata;
float (*lnors)[3];
+ short (*clnor_data)[2];
float (*pnors)[3];
const int numVerts = dm->getNumVerts(dm);
@@ -2538,8 +2653,37 @@ void CDDM_calc_loop_normals(DerivedMesh *dm, const float split_angle)
dm->dirty &= ~DM_DIRTY_NORMALS;
+ clnor_data = CustomData_get_layer(ldata, CD_CUSTOMLOOPNORMAL);
+
BKE_mesh_normals_loop_split(mverts, numVerts, medges, numEdges, mloops, lnors, numLoops,
- mpolys, pnors, numPolys, split_angle);
+ mpolys, (const float (*)[3])pnors, numPolys,
+ use_split_normals, split_angle,
+ r_lnors_spacearr, clnor_data, NULL);
+#ifdef DEBUG_CLNORS
+ if (r_lnors_spacearr) {
+ int i;
+ for (i = 0; i < numLoops; i++) {
+ if (r_lnors_spacearr->lspacearr[i]->ref_alpha != 0.0f) {
+ LinkNode *loops = r_lnors_spacearr->lspacearr[i]->loops;
+ printf("Loop %d uses lnor space %p:\n", i, r_lnors_spacearr->lspacearr[i]);
+ print_v3("\tfinal lnor", lnors[i]);
+ print_v3("\tauto lnor", r_lnors_spacearr->lspacearr[i]->vec_lnor);
+ print_v3("\tref_vec", r_lnors_spacearr->lspacearr[i]->vec_ref);
+ printf("\talpha: %f\n\tbeta: %f\n\tloops: %p\n", r_lnors_spacearr->lspacearr[i]->ref_alpha,
+ r_lnors_spacearr->lspacearr[i]->ref_beta, r_lnors_spacearr->lspacearr[i]->loops);
+ printf("\t\t(shared with loops");
+ while (loops) {
+ printf(" %d", GET_INT_FROM_POINTER(loops->link));
+ loops = loops->next;
+ }
+ printf(")\n");
+ }
+ else {
+ printf("Loop %d has no lnor space\n", i);
+ }
+ }
+ }
+#endif
}
@@ -2577,7 +2721,10 @@ void CDDM_calc_normals_tessface(DerivedMesh *dm)
* and may be called again with direct_reverse=-1 for reverse order.
* \return 1 if polys are identical, 0 if polys are different.
*/
-static int cddm_poly_compare(MLoop *mloop_array, MPoly *mpoly_source, MPoly *mpoly_target, const int *vtargetmap, const int direct_reverse)
+static int cddm_poly_compare(
+ MLoop *mloop_array,
+ MPoly *mpoly_source, MPoly *mpoly_target,
+ const int *vtargetmap, const int direct_reverse)
{
int vert_source, first_vert_source, vert_target;
int i_loop_source;
@@ -2726,10 +2873,10 @@ static bool poly_gset_compare_fn(const void *k1, const void *k2)
(pk1->totloops == pk2->totloops))
{
/* Equality - note that this does not mean equality of polys */
- return 0;
+ return false;
}
else {
- return 1;
+ return true;
}
}
@@ -2850,16 +2997,16 @@ DerivedMesh *CDDM_merge_verts(DerivedMesh *dm, const int *vtargetmap, const int
const unsigned int v1 = (vtargetmap[med->v1] != -1) ? vtargetmap[med->v1] : med->v1;
const unsigned int v2 = (vtargetmap[med->v2] != -1) ? vtargetmap[med->v2] : med->v2;
if (LIKELY(v1 != v2)) {
- void **eh_p = BLI_edgehash_lookup_p(ehash, v1, v2);
+ void **val_p;
- if (eh_p) {
- newe[i] = GET_INT_FROM_POINTER(*eh_p);
+ if (BLI_edgehash_ensure_p(ehash, v1, v2, &val_p)) {
+ newe[i] = GET_INT_FROM_POINTER(*val_p);
}
else {
STACK_PUSH(olde, i);
STACK_PUSH(medge, *med);
newe[i] = c;
- BLI_edgehash_insert(ehash, v1, v2, SET_INT_IN_POINTER(c));
+ *val_p = SET_INT_IN_POINTER(c);
c++;
}
}
@@ -3014,10 +3161,17 @@ DerivedMesh *CDDM_merge_verts(DerivedMesh *dm, const int *vtargetmap, const int
if (UNLIKELY(c == 0)) {
continue;
}
+ else if (UNLIKELY(c < 3)) {
+ STACK_DISCARD(oldl, c);
+ STACK_DISCARD(mloop, c);
+ continue;
+ }
+
mp_new = STACK_PUSH_RET_PTR(mpoly);
*mp_new = *mp;
mp_new->totloop = c;
+ BLI_assert(mp_new->totloop >= 3);
mp_new->loopstart = STACK_SIZE(mloop) - c;
STACK_PUSH(oldp, i);
@@ -3032,7 +3186,8 @@ DerivedMesh *CDDM_merge_verts(DerivedMesh *dm, const int *vtargetmap, const int
}
/*create new cddm*/
- cddm2 = (CDDerivedMesh *) CDDM_from_template((DerivedMesh *)cddm, STACK_SIZE(mvert), STACK_SIZE(medge), 0, STACK_SIZE(mloop), STACK_SIZE(mpoly));
+ cddm2 = (CDDerivedMesh *)CDDM_from_template(
+ (DerivedMesh *)cddm, STACK_SIZE(mvert), STACK_SIZE(medge), 0, STACK_SIZE(mloop), STACK_SIZE(mpoly));
/*update edge indices and copy customdata*/
med = medge;
@@ -3088,7 +3243,7 @@ DerivedMesh *CDDM_merge_verts(DerivedMesh *dm, const int *vtargetmap, const int
MEM_freeN(oldv);
MEM_freeN(olde);
MEM_freeN(oldl);
- MEM_freeN(oldp);;
+ MEM_freeN(oldp);
BLI_edgehash_free(ehash, NULL);
@@ -3349,12 +3504,13 @@ void CDDM_tessfaces_to_faces(DerivedMesh *dm)
/* converts mfaces to mpolys/mloops */
CDDerivedMesh *cddm = (CDDerivedMesh *)dm;
- BKE_mesh_convert_mfaces_to_mpolys_ex(NULL, &cddm->dm.faceData, &cddm->dm.loopData, &cddm->dm.polyData,
- cddm->dm.numEdgeData, cddm->dm.numTessFaceData,
- cddm->dm.numLoopData, cddm->dm.numPolyData,
- cddm->medge, cddm->mface,
- &cddm->dm.numLoopData, &cddm->dm.numPolyData,
- &cddm->mloop, &cddm->mpoly);
+ BKE_mesh_convert_mfaces_to_mpolys_ex(
+ NULL, &cddm->dm.faceData, &cddm->dm.loopData, &cddm->dm.polyData,
+ cddm->dm.numEdgeData, cddm->dm.numTessFaceData,
+ cddm->dm.numLoopData, cddm->dm.numPolyData,
+ cddm->medge, cddm->mface,
+ &cddm->dm.numLoopData, &cddm->dm.numPolyData,
+ &cddm->mloop, &cddm->mpoly);
}
void CDDM_set_mvert(DerivedMesh *dm, MVert *mvert)
@@ -3363,7 +3519,7 @@ void CDDM_set_mvert(DerivedMesh *dm, MVert *mvert)
if (!CustomData_has_layer(&dm->vertData, CD_MVERT))
CustomData_add_layer(&dm->vertData, CD_MVERT, CD_ASSIGN, mvert, dm->numVertData);
-
+
cddm->mvert = mvert;
}
diff --git a/source/blender/blenkernel/intern/cloth.c b/source/blender/blenkernel/intern/cloth.c
index aacf02555d4..7a2a4e09b3d 100644
--- a/source/blender/blenkernel/intern/cloth.c
+++ b/source/blender/blenkernel/intern/cloth.c
@@ -47,16 +47,9 @@
#include "BKE_modifier.h"
#include "BKE_pointcache.h"
-// #include "PIL_time.h" /* timing for debug prints */
+#include "BPH_mass_spring.h"
-/* Our available solvers. */
-// 255 is the magic reserved number, so NEVER try to put 255 solvers in here!
-// 254 = MAX!
-static CM_SOLVER_DEF solvers [] =
-{
- { "Implicit", CM_IMPLICIT, implicit_init, implicit_solver, implicit_free },
- // { "Implicit C++", CM_IMPLICITCPP, implicitcpp_init, implicitcpp_solver, implicitcpp_free },
-};
+// #include "PIL_time.h" /* timing for debug prints */
/* ********** cloth engine ******* */
/* Prototypes for internal functions.
@@ -68,7 +61,6 @@ static void cloth_update_springs( ClothModifierData *clmd );
static int cloth_build_springs ( ClothModifierData *clmd, DerivedMesh *dm );
static void cloth_apply_vgroup ( ClothModifierData *clmd, DerivedMesh *dm );
-
/******************************************************************************
*
* External interface called by modifier.c clothModifier functions.
@@ -89,13 +81,13 @@ void cloth_init(ClothModifierData *clmd )
clmd->sim_parms->structural = 15.0;
clmd->sim_parms->shear = 15.0;
clmd->sim_parms->bending = 0.5;
+ clmd->sim_parms->bending_damping = 0.5;
clmd->sim_parms->Cdis = 5.0;
clmd->sim_parms->Cvi = 1.0;
clmd->sim_parms->mass = 0.3f;
clmd->sim_parms->stepsPerFrame = 5;
clmd->sim_parms->flags = 0;
clmd->sim_parms->solver_type = 0;
- clmd->sim_parms->preroll = 0;
clmd->sim_parms->maxspringlen = 10;
clmd->sim_parms->vgroup_mass = 0;
clmd->sim_parms->vgroup_shrink = 0;
@@ -130,6 +122,8 @@ void cloth_init(ClothModifierData *clmd )
clmd->sim_parms->goalfrict = 0.0f;
clmd->sim_parms->velocity_smooth = 0.0f;
+ clmd->sim_parms->voxel_cell_size = 0.1f;
+
if (!clmd->sim_parms->effector_weights)
clmd->sim_parms->effector_weights = BKE_add_effector_weights(NULL);
@@ -143,7 +137,6 @@ static BVHTree *bvhselftree_build_from_cloth (ClothModifierData *clmd, float eps
BVHTree *bvhtree;
Cloth *cloth;
ClothVertex *verts;
- float co[12];
if (!clmd)
return NULL;
@@ -155,21 +148,22 @@ static BVHTree *bvhselftree_build_from_cloth (ClothModifierData *clmd, float eps
verts = cloth->verts;
- // in the moment, return zero if no faces there
- if (!cloth->numverts)
+ /* in the moment, return zero if no faces there */
+ if (!cloth->mvert_num)
return NULL;
- // create quadtree with k=26
- bvhtree = BLI_bvhtree_new(cloth->numverts, epsilon, 4, 6);
+ /* create quadtree with k=26 */
+ bvhtree = BLI_bvhtree_new(cloth->mvert_num, epsilon, 4, 6);
- // fill tree
- for (i = 0; i < cloth->numverts; i++, verts++) {
- copy_v3_v3(&co[0*3], verts->xold);
+ /* fill tree */
+ for (i = 0; i < cloth->mvert_num; i++, verts++) {
+ const float *co;
+ co = verts->xold;
BLI_bvhtree_insert(bvhtree, i, co, 1);
}
- // balance tree
+ /* balance tree */
BLI_bvhtree_balance(bvhtree);
return bvhtree;
@@ -181,8 +175,7 @@ static BVHTree *bvhtree_build_from_cloth (ClothModifierData *clmd, float epsilon
BVHTree *bvhtree;
Cloth *cloth;
ClothVertex *verts;
- MFace *mfaces;
- float co[12];
+ const MVertTri *vt;
if (!clmd)
return NULL;
@@ -193,25 +186,24 @@ static BVHTree *bvhtree_build_from_cloth (ClothModifierData *clmd, float epsilon
return NULL;
verts = cloth->verts;
- mfaces = cloth->mfaces;
+ vt = cloth->tri;
/* in the moment, return zero if no faces there */
- if (!cloth->numfaces)
+ if (!cloth->tri_num)
return NULL;
/* create quadtree with k=26 */
- bvhtree = BLI_bvhtree_new(cloth->numfaces, epsilon, 4, 26);
+ bvhtree = BLI_bvhtree_new(cloth->tri_num, epsilon, 4, 26);
/* fill tree */
- for (i = 0; i < cloth->numfaces; i++, mfaces++) {
- copy_v3_v3(&co[0*3], verts[mfaces->v1].xold);
- copy_v3_v3(&co[1*3], verts[mfaces->v2].xold);
- copy_v3_v3(&co[2*3], verts[mfaces->v3].xold);
+ for (i = 0; i < cloth->tri_num; i++, vt++) {
+ float co[3][3];
- if (mfaces->v4)
- copy_v3_v3(&co[3*3], verts[mfaces->v4].xold);
+ copy_v3_v3(co[0], verts[vt->tri[0]].xold);
+ copy_v3_v3(co[1], verts[vt->tri[1]].xold);
+ copy_v3_v3(co[2], verts[vt->tri[2]].xold);
- BLI_bvhtree_insert(bvhtree, i, co, (mfaces->v4 ? 4 : 3));
+ BLI_bvhtree_insert(bvhtree, i, co[0], 3);
}
/* balance tree */
@@ -220,90 +212,87 @@ static BVHTree *bvhtree_build_from_cloth (ClothModifierData *clmd, float epsilon
return bvhtree;
}
-void bvhtree_update_from_cloth(ClothModifierData *clmd, int moving)
+void bvhtree_update_from_cloth(ClothModifierData *clmd, bool moving)
{
unsigned int i = 0;
Cloth *cloth = clmd->clothObject;
BVHTree *bvhtree = cloth->bvhtree;
ClothVertex *verts = cloth->verts;
- MFace *mfaces;
- float co[12], co_moving[12];
- bool ret = false;
+ const MVertTri *vt;
if (!bvhtree)
return;
- mfaces = cloth->mfaces;
+ vt = cloth->tri;
- // update vertex position in bvh tree
- if (verts && mfaces) {
- for (i = 0; i < cloth->numfaces; i++, mfaces++) {
- copy_v3_v3(&co[0*3], verts[mfaces->v1].txold);
- copy_v3_v3(&co[1*3], verts[mfaces->v2].txold);
- copy_v3_v3(&co[2*3], verts[mfaces->v3].txold);
-
- if (mfaces->v4)
- copy_v3_v3(&co[3*3], verts[mfaces->v4].txold);
-
- // copy new locations into array
+ /* update vertex position in bvh tree */
+ if (verts && vt) {
+ for (i = 0; i < cloth->tri_num; i++, vt++) {
+ float co[3][3], co_moving[3][3];
+ bool ret;
+
+ copy_v3_v3(co[0], verts[vt->tri[0]].txold);
+ copy_v3_v3(co[1], verts[vt->tri[1]].txold);
+ copy_v3_v3(co[2], verts[vt->tri[2]].txold);
+
+ /* copy new locations into array */
if (moving) {
- // update moving positions
- copy_v3_v3(&co_moving[0*3], verts[mfaces->v1].tx);
- copy_v3_v3(&co_moving[1*3], verts[mfaces->v2].tx);
- copy_v3_v3(&co_moving[2*3], verts[mfaces->v3].tx);
-
- if (mfaces->v4)
- copy_v3_v3(&co_moving[3*3], verts[mfaces->v4].tx);
-
- ret = BLI_bvhtree_update_node(bvhtree, i, co, co_moving, (mfaces->v4 ? 4 : 3));
+ /* update moving positions */
+ copy_v3_v3(co_moving[0], verts[vt->tri[0]].tx);
+ copy_v3_v3(co_moving[1], verts[vt->tri[1]].tx);
+ copy_v3_v3(co_moving[2], verts[vt->tri[2]].tx);
+
+ ret = BLI_bvhtree_update_node(bvhtree, i, co[0], co_moving[0], 3);
}
else {
- ret = BLI_bvhtree_update_node(bvhtree, i, co, NULL, (mfaces->v4 ? 4 : 3));
+ ret = BLI_bvhtree_update_node(bvhtree, i, co[0], NULL, 3);
}
- // check if tree is already full
- if (!ret)
+ /* check if tree is already full */
+ if (ret == false) {
break;
+ }
}
BLI_bvhtree_update_tree(bvhtree);
}
}
-void bvhselftree_update_from_cloth(ClothModifierData *clmd, int moving)
+void bvhselftree_update_from_cloth(ClothModifierData *clmd, bool moving)
{
unsigned int i = 0;
Cloth *cloth = clmd->clothObject;
BVHTree *bvhtree = cloth->bvhselftree;
ClothVertex *verts = cloth->verts;
- MFace *mfaces;
- float co[12], co_moving[12];
- int ret = 0;
+ const MVertTri *vt;
if (!bvhtree)
return;
-
- mfaces = cloth->mfaces;
- // update vertex position in bvh tree
- if (verts && mfaces) {
- for (i = 0; i < cloth->numverts; i++, verts++) {
- copy_v3_v3(&co[0*3], verts->txold);
+ vt = cloth->tri;
- // copy new locations into array
- if (moving) {
- // update moving positions
- copy_v3_v3(&co_moving[0*3], verts->tx);
+ /* update vertex position in bvh tree */
+ if (verts && vt) {
+ for (i = 0; i < cloth->mvert_num; i++, verts++) {
+ const float *co, *co_moving;
+ bool ret;
+ co = verts->txold;
+
+ /* copy new locations into array */
+ if (moving) {
+ /* update moving positions */
+ co_moving = verts->tx;
ret = BLI_bvhtree_update_node(bvhtree, i, co, co_moving, 1);
}
else {
ret = BLI_bvhtree_update_node(bvhtree, i, co, NULL, 1);
}
- // check if tree is already full
- if (!ret)
+ /* check if tree is already full */
+ if (ret == false) {
break;
+ }
}
BLI_bvhtree_update_tree(bvhtree);
@@ -343,7 +332,7 @@ static int do_init_cloth(Object *ob, ClothModifierData *clmd, DerivedMesh *resul
return 0;
}
- implicit_set_positions(clmd);
+ BKE_cloth_solver_set_positions(clmd);
clmd->clothObject->last_frame= MINFRAME-1;
}
@@ -366,7 +355,7 @@ static int do_step_cloth(Object *ob, ClothModifierData *clmd, DerivedMesh *resul
mvert = result->getVertArray(result);
/* force any pinned verts to their constrained location. */
- for (i = 0; i < clmd->clothObject->numverts; i++, verts++) {
+ for (i = 0; i < clmd->clothObject->mvert_num; i++, verts++) {
/* save the previous position. */
copy_v3_v3(verts->xold, verts->xconst);
copy_v3_v3(verts->txold, verts->x);
@@ -385,8 +374,7 @@ static int do_step_cloth(Object *ob, ClothModifierData *clmd, DerivedMesh *resul
// TIMEIT_START(cloth_step)
/* call the solver. */
- if (solvers [clmd->sim_parms->solver_type].solver)
- ret = solvers[clmd->sim_parms->solver_type].solver(ob, framenr, clmd, effectors);
+ ret = BPH_cloth_solve(ob, framenr, clmd, effectors);
// TIMEIT_END(cloth_step)
@@ -397,59 +385,6 @@ static int do_step_cloth(Object *ob, ClothModifierData *clmd, DerivedMesh *resul
return ret;
}
-#if 0
-static DerivedMesh *cloth_to_triangles(DerivedMesh *dm)
-{
- DerivedMesh *result = NULL;
- unsigned int i = 0, j = 0;
- unsigned int quads = 0, numfaces = dm->getNumTessFaces(dm);
- MFace *mface = dm->getTessFaceArray(dm);
- MFace *mface2 = NULL;
-
- /* calc faces */
- for (i = 0; i < numfaces; i++) {
- if (mface[i].v4) {
- quads++;
- }
- }
-
- result = CDDM_from_template(dm, dm->getNumVerts(dm), 0, numfaces + quads, 0, 0);
-
- DM_copy_vert_data(dm, result, 0, 0, dm->getNumVerts(dm));
- DM_copy_tessface_data(dm, result, 0, 0, numfaces);
-
- DM_ensure_tessface(result);
- mface2 = result->getTessFaceArray(result);
-
- for (i = 0, j = numfaces; i < numfaces; i++) {
- // DG TODO: is this necessary?
- mface2[i].v1 = mface[i].v1;
- mface2[i].v2 = mface[i].v2;
- mface2[i].v3 = mface[i].v3;
-
- mface2[i].v4 = 0;
- //test_index_face(&mface2[i], &result->faceData, i, 3);
-
- if (mface[i].v4) {
- DM_copy_tessface_data(dm, result, i, j, 1);
-
- mface2[j].v1 = mface[i].v1;
- mface2[j].v2 = mface[i].v3;
- mface2[j].v3 = mface[i].v4;
- mface2[j].v4 = 0;
- //test_index_face(&mface2[j], &result->faceData, j, 3);
-
- j++;
- }
- }
-
- CDDM_calc_edges_tessface(result);
- CDDM_tessfaces_to_faces(result); /* builds ngon faces from tess (mface) faces */
-
- return result;
-}
-#endif
-
/************************************************
* clothModifier_do - main simulation function
************************************************/
@@ -469,10 +404,7 @@ void clothModifier_do(ClothModifierData *clmd, Scene *scene, Object *ob, Derived
BKE_ptcache_id_time(&pid, scene, framenr, &startframe, &endframe, &timescale);
clmd->sim_parms->timescale= timescale;
- if (clmd->sim_parms->reset ||
- (framenr == (startframe - clmd->sim_parms->preroll) && clmd->sim_parms->preroll != 0) ||
- (clmd->clothObject && dm->getNumVerts(dm) != clmd->clothObject->numverts))
- {
+ if (clmd->sim_parms->reset || (clmd->clothObject && dm->getNumVerts(dm) != clmd->clothObject->mvert_num)) {
clmd->sim_parms->reset = 0;
cache->flag |= PTCACHE_OUTDATED;
BKE_ptcache_id_reset(scene, &pid, PTCACHE_RESET_OUTDATED);
@@ -484,22 +416,6 @@ void clothModifier_do(ClothModifierData *clmd, Scene *scene, Object *ob, Derived
// unused in the moment, calculated separately in implicit.c
clmd->sim_parms->dt = clmd->sim_parms->timescale / clmd->sim_parms->stepsPerFrame;
- /* handle continuous simulation with the play button */
- if ((clmd->sim_parms->preroll > 0) && (framenr > startframe - clmd->sim_parms->preroll) && (framenr < startframe)) {
- BKE_ptcache_invalidate(cache);
-
- /* do simulation */
- if (!do_init_cloth(ob, clmd, dm, framenr))
- return;
-
- do_step_cloth(ob, clmd, dm, framenr);
- cloth_to_object(ob, clmd, vertexCos);
-
- clmd->clothObject->last_frame= framenr;
-
- return;
- }
-
/* simulation is only active during a specific period */
if (framenr < startframe) {
BKE_ptcache_invalidate(cache);
@@ -513,7 +429,7 @@ void clothModifier_do(ClothModifierData *clmd, Scene *scene, Object *ob, Derived
if (!do_init_cloth(ob, clmd, dm, framenr))
return;
- if ((framenr == startframe) && (clmd->sim_parms->preroll == 0)) {
+ if (framenr == startframe) {
BKE_ptcache_id_reset(scene, &pid, PTCACHE_RESET_OUTDATED);
do_init_cloth(ob, clmd, dm, framenr);
BKE_ptcache_validate(cache, framenr);
@@ -526,7 +442,7 @@ void clothModifier_do(ClothModifierData *clmd, Scene *scene, Object *ob, Derived
cache_result = BKE_ptcache_read(&pid, (float)framenr+scene->r.subframe);
if (cache_result == PTCACHE_READ_EXACT || cache_result == PTCACHE_READ_INTERPOLATED) {
- implicit_set_positions(clmd);
+ BKE_cloth_solver_set_positions(clmd);
cloth_to_object (ob, clmd, vertexCos);
BKE_ptcache_validate(cache, framenr);
@@ -539,7 +455,7 @@ void clothModifier_do(ClothModifierData *clmd, Scene *scene, Object *ob, Derived
return;
}
else if (cache_result==PTCACHE_READ_OLD) {
- implicit_set_positions(clmd);
+ BKE_cloth_solver_set_positions(clmd);
}
else if ( /*ob->id.lib ||*/ (cache->flag & PTCACHE_BAKED)) { /* 2.4x disabled lib, but this can be used in some cases, testing further - campbell */
/* if baked and nothing in cache, do nothing */
@@ -581,17 +497,14 @@ void cloth_free_modifier(ClothModifierData *clmd )
if ( cloth ) {
- // If our solver provides a free function, call it
- if ( solvers [clmd->sim_parms->solver_type].free ) {
- solvers [clmd->sim_parms->solver_type].free ( clmd );
- }
+ BPH_cloth_solver_free(clmd);
// Free the verts.
if ( cloth->verts != NULL )
MEM_freeN ( cloth->verts );
cloth->verts = NULL;
- cloth->numverts = 0;
+ cloth->mvert_num = 0;
// Free the springs.
if ( cloth->springs != NULL ) {
@@ -618,9 +531,9 @@ void cloth_free_modifier(ClothModifierData *clmd )
BLI_bvhtree_free ( cloth->bvhselftree );
// we save our faces for collision objects
- if ( cloth->mfaces )
- MEM_freeN ( cloth->mfaces );
-
+ if (cloth->tri)
+ MEM_freeN(cloth->tri);
+
if (cloth->edgeset)
BLI_edgeset_free(cloth->edgeset);
@@ -650,17 +563,14 @@ void cloth_free_modifier_extern(ClothModifierData *clmd )
if (G.debug_value > 0)
printf("cloth_free_modifier_extern in\n");
- // If our solver provides a free function, call it
- if ( solvers [clmd->sim_parms->solver_type].free ) {
- solvers [clmd->sim_parms->solver_type].free ( clmd );
- }
+ BPH_cloth_solver_free(clmd);
// Free the verts.
if ( cloth->verts != NULL )
MEM_freeN ( cloth->verts );
cloth->verts = NULL;
- cloth->numverts = 0;
+ cloth->mvert_num = 0;
// Free the springs.
if ( cloth->springs != NULL ) {
@@ -687,8 +597,8 @@ void cloth_free_modifier_extern(ClothModifierData *clmd )
BLI_bvhtree_free ( cloth->bvhselftree );
// we save our faces for collision objects
- if ( cloth->mfaces )
- MEM_freeN ( cloth->mfaces );
+ if (cloth->tri)
+ MEM_freeN(cloth->tri);
if (cloth->edgeset)
BLI_edgeset_free(cloth->edgeset);
@@ -722,7 +632,7 @@ static void cloth_to_object (Object *ob, ClothModifierData *clmd, float (*verte
/* inverse matrix is not uptodate... */
invert_m4_m4(ob->imat, ob->obmat);
- for (i = 0; i < cloth->numverts; i++) {
+ for (i = 0; i < cloth->mvert_num; i++) {
copy_v3_v3 (vertexCos[i], cloth->verts[i].x);
mul_m4_v3(ob->imat, vertexCos[i]); /* cloth is in global coords */
}
@@ -753,7 +663,7 @@ static void cloth_apply_vgroup ( ClothModifierData *clmd, DerivedMesh *dm )
int j = 0;
MDeformVert *dvert = NULL;
Cloth *clothObj = NULL;
- int numverts;
+ int mvert_num;
/* float goalfac = 0; */ /* UNUSED */
ClothVertex *verts = NULL;
@@ -761,12 +671,12 @@ static void cloth_apply_vgroup ( ClothModifierData *clmd, DerivedMesh *dm )
clothObj = clmd->clothObject;
- numverts = dm->getNumVerts (dm);
+ mvert_num = dm->getNumVerts(dm);
verts = clothObj->verts;
if (cloth_uses_vgroup(clmd)) {
- for ( i = 0; i < numverts; i++, verts++ ) {
+ for (i = 0; i < mvert_num; i++, verts++) {
/* Reset Goal values to standard */
if ( clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL )
@@ -789,7 +699,7 @@ static void cloth_apply_vgroup ( ClothModifierData *clmd, DerivedMesh *dm )
// Kicking goal factor to simplify things...who uses that anyway?
// ABS ( clmd->sim_parms->maxgoal - clmd->sim_parms->mingoal );
- verts->goal = powf(verts->goal, 4.0f);
+ verts->goal = pow4f(verts->goal);
if ( verts->goal >= SOFTGOALSNAP )
verts->flags |= CLOTH_VERT_FLAG_PINNED;
}
@@ -812,17 +722,15 @@ static void cloth_apply_vgroup ( ClothModifierData *clmd, DerivedMesh *dm )
}
}
- if (clmd->sim_parms->vgroup_shrink > 0 )
- {
- if ( dvert->dw[j].def_nr == (clmd->sim_parms->vgroup_shrink-1))
- {
- verts->shrink_factor = clmd->sim_parms->shrink_min*(1.0f-dvert->dw[j].weight)+clmd->sim_parms->shrink_max*dvert->dw [j].weight; // linear interpolation between min and max shrink factor based on weight
+ if (clmd->sim_parms->vgroup_shrink > 0) {
+ if (dvert->dw[j].def_nr == (clmd->sim_parms->vgroup_shrink - 1)) {
+ /* linear interpolation between min and max shrink factor based on weight */
+ verts->shrink_factor = clmd->sim_parms->shrink_min * (1.0f - dvert->dw[j].weight) + clmd->sim_parms->shrink_max * dvert->dw [j].weight;
+ }
+ }
+ else {
+ verts->shrink_factor = clmd->sim_parms->shrink_min;
}
- }
- else {
- verts->shrink_factor = clmd->sim_parms->shrink_min;
- }
-
}
}
}
@@ -865,6 +773,7 @@ static int cloth_from_object(Object *ob, ClothModifierData *clmd, DerivedMesh *d
if ( !dm )
return 0;
+ DM_ensure_looptri(dm);
cloth_from_mesh ( clmd, dm );
// create springs
@@ -931,12 +840,10 @@ static int cloth_from_object(Object *ob, ClothModifierData *clmd, DerivedMesh *d
}
// init our solver
- if ( solvers [clmd->sim_parms->solver_type].init ) {
- solvers [clmd->sim_parms->solver_type].init ( ob, clmd );
- }
+ BPH_cloth_solver_init(ob, clmd);
if (!first)
- implicit_set_positions(clmd);
+ BKE_cloth_solver_set_positions(clmd);
clmd->clothObject->bvhtree = bvhtree_build_from_cloth ( clmd, MAX2(clmd->coll_parms->epsilon, clmd->coll_parms->distance_repel) );
@@ -951,32 +858,31 @@ static int cloth_from_object(Object *ob, ClothModifierData *clmd, DerivedMesh *d
static void cloth_from_mesh ( ClothModifierData *clmd, DerivedMesh *dm )
{
- unsigned int numverts = dm->getNumVerts (dm);
- unsigned int numfaces = dm->getNumTessFaces (dm);
- MFace *mface = dm->getTessFaceArray(dm);
- unsigned int i = 0;
+ const MLoop *mloop = dm->getLoopArray(dm);
+ const MLoopTri *looptri = dm->getLoopTriArray(dm);
+ const unsigned int mvert_num = dm->getNumVerts(dm);
+ const unsigned int looptri_num = dm->getNumLoopTri(dm);
/* Allocate our vertices. */
- clmd->clothObject->numverts = numverts;
- clmd->clothObject->verts = MEM_callocN ( sizeof ( ClothVertex ) * clmd->clothObject->numverts, "clothVertex" );
- if ( clmd->clothObject->verts == NULL ) {
- cloth_free_modifier ( clmd );
+ clmd->clothObject->mvert_num = mvert_num;
+ clmd->clothObject->verts = MEM_callocN(sizeof(ClothVertex) * clmd->clothObject->mvert_num, "clothVertex");
+ if (clmd->clothObject->verts == NULL) {
+ cloth_free_modifier(clmd);
modifier_setError(&(clmd->modifier), "Out of memory on allocating clmd->clothObject->verts");
printf("cloth_free_modifier clmd->clothObject->verts\n");
return;
}
- // save face information
- clmd->clothObject->numfaces = numfaces;
- clmd->clothObject->mfaces = MEM_callocN ( sizeof ( MFace ) * clmd->clothObject->numfaces, "clothMFaces" );
- if ( clmd->clothObject->mfaces == NULL ) {
- cloth_free_modifier ( clmd );
- modifier_setError(&(clmd->modifier), "Out of memory on allocating clmd->clothObject->mfaces");
- printf("cloth_free_modifier clmd->clothObject->mfaces\n");
+ /* save face information */
+ clmd->clothObject->tri_num = looptri_num;
+ clmd->clothObject->tri = MEM_mallocN(sizeof(MVertTri) * looptri_num, "clothLoopTris");
+ if (clmd->clothObject->tri == NULL) {
+ cloth_free_modifier(clmd);
+ modifier_setError(&(clmd->modifier), "Out of memory on allocating clmd->clothObject->looptri");
+ printf("cloth_free_modifier clmd->clothObject->looptri\n");
return;
}
- for ( i = 0; i < numfaces; i++ )
- memcpy ( &clmd->clothObject->mfaces[i], &mface[i], sizeof ( MFace ) );
+ DM_verttri_from_looptri(clmd->clothObject->tri, mloop, looptri, looptri_num);
/* Free the springs since they can't be correct if the vertices
* changed.
@@ -1033,19 +939,19 @@ int cloth_add_spring(ClothModifierData *clmd, unsigned int indexA, unsigned int
return 0;
}
-static void cloth_free_edgelist(LinkNode **edgelist, unsigned int numverts)
+static void cloth_free_edgelist(LinkNodePair *edgelist, unsigned int mvert_num)
{
if (edgelist) {
unsigned int i;
- for (i = 0; i < numverts; i++) {
- BLI_linklist_free(edgelist[i], NULL);
+ for (i = 0; i < mvert_num; i++) {
+ BLI_linklist_free(edgelist[i].list, NULL);
}
MEM_freeN(edgelist);
}
}
-static void cloth_free_errorsprings(Cloth *cloth, LinkNode **edgelist)
+static void cloth_free_errorsprings(Cloth *cloth, LinkNodePair *edgelist)
{
if ( cloth->springs != NULL ) {
LinkNode *search = cloth->springs;
@@ -1060,7 +966,7 @@ static void cloth_free_errorsprings(Cloth *cloth, LinkNode **edgelist)
cloth->springs = NULL;
}
- cloth_free_edgelist(edgelist, cloth->numverts);
+ cloth_free_edgelist(edgelist, cloth->mvert_num);
if (cloth->edgeset) {
BLI_edgeset_free(cloth->edgeset);
@@ -1068,6 +974,135 @@ static void cloth_free_errorsprings(Cloth *cloth, LinkNode **edgelist)
}
}
+static void cloth_hair_update_bending_targets(ClothModifierData *clmd)
+{
+ Cloth *cloth = clmd->clothObject;
+ LinkNode *search = NULL;
+ float hair_frame[3][3], dir_old[3], dir_new[3];
+ int prev_mn; /* to find hair chains */
+
+ if (!clmd->hairdata)
+ return;
+
+ /* XXX Note: we need to propagate frames from the root up,
+ * but structural hair springs are stored in reverse order.
+ * The bending springs however are then inserted in the same
+ * order as vertices again ...
+ * This messy situation can be resolved when solver data is
+ * generated directly from a dedicated hair system.
+ */
+
+ prev_mn = -1;
+ for (search = cloth->springs; search; search = search->next) {
+ ClothSpring *spring = search->link;
+ ClothHairData *hair_ij, *hair_kl;
+ bool is_root = spring->kl != prev_mn;
+
+ if (spring->type != CLOTH_SPRING_TYPE_BENDING_ANG) {
+ continue;
+ }
+
+ hair_ij = &clmd->hairdata[spring->ij];
+ hair_kl = &clmd->hairdata[spring->kl];
+ if (is_root) {
+ /* initial hair frame from root orientation */
+ copy_m3_m3(hair_frame, hair_ij->rot);
+ /* surface normal is the initial direction,
+ * parallel transport then keeps it aligned to the hair direction
+ */
+ copy_v3_v3(dir_new, hair_frame[2]);
+ }
+
+ copy_v3_v3(dir_old, dir_new);
+ sub_v3_v3v3(dir_new, cloth->verts[spring->mn].x, cloth->verts[spring->kl].x);
+ normalize_v3(dir_new);
+
+#if 0
+ if (clmd->debug_data && (spring->ij == 0 || spring->ij == 1)) {
+ float a[3], b[3];
+
+ copy_v3_v3(a, cloth->verts[spring->kl].x);
+// BKE_sim_debug_data_add_dot(clmd->debug_data, cloth_vert ? cloth_vert->x : key->co, 1, 1, 0, "frames", 8246, p, k);
+
+ mul_v3_v3fl(b, hair_frame[0], clmd->sim_parms->avg_spring_len);
+ BKE_sim_debug_data_add_vector(clmd->debug_data, a, b, 1, 0, 0, "frames", 8247, spring->kl, spring->mn);
+
+ mul_v3_v3fl(b, hair_frame[1], clmd->sim_parms->avg_spring_len);
+ BKE_sim_debug_data_add_vector(clmd->debug_data, a, b, 0, 1, 0, "frames", 8248, spring->kl, spring->mn);
+
+ mul_v3_v3fl(b, hair_frame[2], clmd->sim_parms->avg_spring_len);
+ BKE_sim_debug_data_add_vector(clmd->debug_data, a, b, 0, 0, 1, "frames", 8249, spring->kl, spring->mn);
+ }
+#endif
+
+ /* get local targets for kl/mn vertices by putting rest targets into the current frame,
+ * then multiply with the rest length to get the actual goals
+ */
+
+ mul_v3_m3v3(spring->target, hair_frame, hair_kl->rest_target);
+ mul_v3_fl(spring->target, spring->restlen);
+
+ /* move frame to next hair segment */
+ cloth_parallel_transport_hair_frame(hair_frame, dir_old, dir_new);
+
+ prev_mn = spring->mn;
+ }
+}
+
+static void cloth_hair_update_bending_rest_targets(ClothModifierData *clmd)
+{
+ Cloth *cloth = clmd->clothObject;
+ LinkNode *search = NULL;
+ float hair_frame[3][3], dir_old[3], dir_new[3];
+ int prev_mn; /* to find hair roots */
+
+ if (!clmd->hairdata)
+ return;
+
+ /* XXX Note: we need to propagate frames from the root up,
+ * but structural hair springs are stored in reverse order.
+ * The bending springs however are then inserted in the same
+ * order as vertices again ...
+ * This messy situation can be resolved when solver data is
+ * generated directly from a dedicated hair system.
+ */
+
+ prev_mn = -1;
+ for (search = cloth->springs; search; search = search->next) {
+ ClothSpring *spring = search->link;
+ ClothHairData *hair_ij, *hair_kl;
+ bool is_root = spring->kl != prev_mn;
+
+ if (spring->type != CLOTH_SPRING_TYPE_BENDING_ANG) {
+ continue;
+ }
+
+ hair_ij = &clmd->hairdata[spring->ij];
+ hair_kl = &clmd->hairdata[spring->kl];
+ if (is_root) {
+ /* initial hair frame from root orientation */
+ copy_m3_m3(hair_frame, hair_ij->rot);
+ /* surface normal is the initial direction,
+ * parallel transport then keeps it aligned to the hair direction
+ */
+ copy_v3_v3(dir_new, hair_frame[2]);
+ }
+
+ copy_v3_v3(dir_old, dir_new);
+ sub_v3_v3v3(dir_new, cloth->verts[spring->mn].xrest, cloth->verts[spring->kl].xrest);
+ normalize_v3(dir_new);
+
+ /* dir expressed in the hair frame defines the rest target direction */
+ copy_v3_v3(hair_kl->rest_target, dir_new);
+ mul_transposed_m3_v3(hair_frame, hair_kl->rest_target);
+
+ /* move frame to next hair segment */
+ cloth_parallel_transport_hair_frame(hair_frame, dir_old, dir_new);
+
+ prev_mn = spring->mn;
+ }
+}
+
/* update stiffness if vertex group values are changing from frame to frame */
static void cloth_update_springs( ClothModifierData *clmd )
{
@@ -1089,6 +1124,16 @@ static void cloth_update_springs( ClothModifierData *clmd )
else if (spring->type == CLOTH_SPRING_TYPE_BENDING) {
spring->stiffness = (cloth->verts[spring->kl].bend_stiff + cloth->verts[spring->ij].bend_stiff) / 2.0f;
}
+ else if (spring->type == CLOTH_SPRING_TYPE_BENDING_ANG) {
+ ClothVertex *v1 = &cloth->verts[spring->ij];
+ ClothVertex *v2 = &cloth->verts[spring->kl];
+ if (clmd->hairdata) {
+ /* copy extra hair data to generic cloth vertices */
+ v1->bend_stiff = clmd->hairdata[spring->ij].bending_stiffness;
+ v2->bend_stiff = clmd->hairdata[spring->kl].bending_stiffness;
+ }
+ spring->stiffness = (v1->bend_stiff + v2->bend_stiff) / 2.0f;
+ }
else if (spring->type == CLOTH_SPRING_TYPE_GOAL) {
/* Warning: Appending NEW goal springs does not work because implicit solver would need reset! */
@@ -1105,8 +1150,43 @@ static void cloth_update_springs( ClothModifierData *clmd )
search = search->next;
}
+
+ cloth_hair_update_bending_targets(clmd);
+}
+BLI_INLINE void cross_identity_v3(float r[3][3], const float v[3])
+{
+ zero_m3(r);
+ r[0][1] = v[2];
+ r[0][2] = -v[1];
+ r[1][0] = -v[2];
+ r[1][2] = v[0];
+ r[2][0] = v[1];
+ r[2][1] = -v[0];
+}
+BLI_INLINE void madd_m3_m3fl(float r[3][3], float m[3][3], float f)
+{
+ r[0][0] += m[0][0] * f;
+ r[0][1] += m[0][1] * f;
+ r[0][2] += m[0][2] * f;
+ r[1][0] += m[1][0] * f;
+ r[1][1] += m[1][1] * f;
+ r[1][2] += m[1][2] * f;
+ r[2][0] += m[2][0] * f;
+ r[2][1] += m[2][1] * f;
+ r[2][2] += m[2][2] * f;
+}
+
+void cloth_parallel_transport_hair_frame(float mat[3][3], const float dir_old[3], const float dir_new[3])
+{
+ float rot[3][3];
+
+ /* rotation between segments */
+ rotation_between_vecs_to_mat3(rot, dir_old, dir_new);
+
+ /* rotate the frame */
+ mul_m3_m3m3(mat, rot, mat);
}
static int cloth_build_springs ( ClothModifierData *clmd, DerivedMesh *dm )
@@ -1115,14 +1195,15 @@ static int cloth_build_springs ( ClothModifierData *clmd, DerivedMesh *dm )
ClothSpring *spring = NULL, *tspring = NULL, *tspring2 = NULL;
unsigned int struct_springs = 0, shear_springs=0, bend_springs = 0;
unsigned int i = 0;
- unsigned int numverts = (unsigned int)dm->getNumVerts (dm);
+ unsigned int mvert_num = (unsigned int)dm->getNumVerts(dm);
unsigned int numedges = (unsigned int)dm->getNumEdges (dm);
- unsigned int numfaces = (unsigned int)dm->getNumTessFaces (dm);
+ unsigned int numpolys = (unsigned int)dm->getNumPolys(dm);
float shrink_factor;
- MEdge *medge = dm->getEdgeArray (dm);
- MFace *mface = dm->getTessFaceArray (dm);
+ const MEdge *medge = dm->getEdgeArray(dm);
+ const MPoly *mpoly = dm->getPolyArray(dm);
+ const MLoop *mloop = dm->getLoopArray(dm);
int index2 = 0; // our second vertex index
- LinkNode **edgelist = NULL;
+ LinkNodePair *edgelist;
EdgeSet *edgeset = NULL;
LinkNode *search = NULL, *search2 = NULL;
@@ -1138,7 +1219,7 @@ static int cloth_build_springs ( ClothModifierData *clmd, DerivedMesh *dm )
cloth->springs = NULL;
cloth->edgeset = NULL;
- edgelist = MEM_callocN ( sizeof (LinkNode *) * numverts, "cloth_edgelist_alloc" );
+ edgelist = MEM_callocN(sizeof(*edgelist) * mvert_num, "cloth_edgelist_alloc" );
if (!edgelist)
return 0;
@@ -1183,67 +1264,51 @@ static int cloth_build_springs ( ClothModifierData *clmd, DerivedMesh *dm )
if (struct_springs > 0)
clmd->sim_parms->avg_spring_len /= struct_springs;
- for (i = 0; i < numverts; i++) {
+ for (i = 0; i < mvert_num; i++) {
cloth->verts[i].avg_spring_len = cloth->verts[i].avg_spring_len * 0.49f / ((float)cloth->verts[i].spring_count);
}
// shear springs
- for ( i = 0; i < numfaces; i++ ) {
- // triangle faces already have shear springs due to structural geometry
- if ( !mface[i].v4 )
- continue;
+ for (i = 0; i < numpolys; i++) {
+ /* triangle faces already have shear springs due to structural geometry */
+ if (mpoly[i].totloop == 4) {
+ int j;
- spring = (ClothSpring *)MEM_callocN(sizeof(ClothSpring), "cloth spring");
-
- if (!spring) {
- cloth_free_errorsprings(cloth, edgelist);
- return 0;
- }
-
- spring_verts_ordered_set(spring, mface[i].v1, mface[i].v3);
- if (clmd->sim_parms->vgroup_shrink > 0)
- shrink_factor = 1.0f - ((cloth->verts[spring->ij].shrink_factor + cloth->verts[spring->kl].shrink_factor) / 2.0f);
- else
- shrink_factor = 1.0f - clmd->sim_parms->shrink_min;
- spring->restlen = len_v3v3(cloth->verts[spring->kl].xrest, cloth->verts[spring->ij].xrest) * shrink_factor;
- spring->type = CLOTH_SPRING_TYPE_SHEAR;
- spring->stiffness = (cloth->verts[spring->kl].shear_stiff + cloth->verts[spring->ij].shear_stiff) / 2.0f;
+ for (j = 0; j != 2; j++) {
+ spring = (ClothSpring *)MEM_callocN(sizeof(ClothSpring), "cloth spring");
- BLI_linklist_append ( &edgelist[spring->ij], spring );
- BLI_linklist_append ( &edgelist[spring->kl], spring );
- shear_springs++;
+ if (!spring) {
+ cloth_free_errorsprings(cloth, edgelist);
+ return 0;
+ }
- BLI_linklist_prepend ( &cloth->springs, spring );
+ spring_verts_ordered_set(
+ spring,
+ mloop[mpoly[i].loopstart + (j + 0)].v,
+ mloop[mpoly[i].loopstart + (j + 2)].v);
-
- // if ( mface[i].v4 ) --> Quad face
- spring = (ClothSpring *)MEM_callocN ( sizeof ( ClothSpring ), "cloth spring" );
-
- if (!spring) {
- cloth_free_errorsprings(cloth, edgelist);
- return 0;
- }
+ if (clmd->sim_parms->vgroup_shrink > 0)
+ shrink_factor = 1.0f - ((cloth->verts[spring->ij].shrink_factor + cloth->verts[spring->kl].shrink_factor) / 2.0f);
+ else
+ shrink_factor = 1.0f - clmd->sim_parms->shrink_min;
+ spring->restlen = len_v3v3(cloth->verts[spring->kl].xrest, cloth->verts[spring->ij].xrest) * shrink_factor;
+ spring->type = CLOTH_SPRING_TYPE_SHEAR;
+ spring->stiffness = (cloth->verts[spring->kl].shear_stiff + cloth->verts[spring->ij].shear_stiff) / 2.0f;
- spring_verts_ordered_set(spring, mface[i].v2, mface[i].v4);
- if (clmd->sim_parms->vgroup_shrink > 0)
- shrink_factor = 1.0f - ((cloth->verts[spring->ij].shrink_factor + cloth->verts[spring->kl].shrink_factor) / 2.0f);
- else
- shrink_factor = 1.0f - clmd->sim_parms->shrink_min;
- spring->restlen = len_v3v3(cloth->verts[spring->kl].xrest, cloth->verts[spring->ij].xrest) * shrink_factor;
- spring->type = CLOTH_SPRING_TYPE_SHEAR;
- spring->stiffness = (cloth->verts[spring->kl].shear_stiff + cloth->verts[spring->ij].shear_stiff) / 2.0f;
+ BLI_linklist_append(&edgelist[spring->ij], spring);
+ BLI_linklist_append(&edgelist[spring->kl], spring);
- BLI_linklist_append ( &edgelist[spring->ij], spring );
- BLI_linklist_append ( &edgelist[spring->kl], spring );
- shear_springs++;
+ shear_springs++;
- BLI_linklist_prepend ( &cloth->springs, spring );
+ BLI_linklist_prepend(&cloth->springs, spring);
+ }
+ }
}
edgeset = BLI_edgeset_new_ex(__func__, numedges);
cloth->edgeset = edgeset;
- if (numfaces) {
+ if (numpolys) {
// bending springs
search2 = cloth->springs;
for ( i = struct_springs; i < struct_springs+shear_springs; i++ ) {
@@ -1251,7 +1316,7 @@ static int cloth_build_springs ( ClothModifierData *clmd, DerivedMesh *dm )
break;
tspring2 = search2->link;
- search = edgelist[tspring2->kl];
+ search = edgelist[tspring2->kl].list;
while ( search ) {
tspring = search->link;
index2 = ( ( tspring->ij==tspring2->kl ) ? ( tspring->kl ) : ( tspring->ij ) );
@@ -1283,40 +1348,74 @@ static int cloth_build_springs ( ClothModifierData *clmd, DerivedMesh *dm )
}
}
else if (struct_springs > 2) {
- /* bending springs for hair strands */
- /* The current algorightm only goes through the edges in order of the mesh edges list */
- /* and makes springs between the outer vert of edges sharing a vertice. This works just */
- /* fine for hair, but not for user generated string meshes. This could/should be later */
- /* extended to work with non-ordered edges so that it can be used for general "rope */
- /* dynamics" without the need for the vertices or edges to be ordered through the length*/
- /* of the strands. -jahka */
- search = cloth->springs;
- search2 = search->next;
- while (search && search2) {
- tspring = search->link;
- tspring2 = search2->link;
-
- if (tspring->ij == tspring2->kl) {
- spring = (ClothSpring *)MEM_callocN ( sizeof ( ClothSpring ), "cloth spring" );
+ if (G.debug_value != 1112) {
+ search = cloth->springs;
+ search2 = search->next;
+ while (search && search2) {
+ tspring = search->link;
+ tspring2 = search2->link;
- if (!spring) {
- cloth_free_errorsprings(cloth, edgelist);
- return 0;
+ if (tspring->ij == tspring2->kl) {
+ spring = (ClothSpring *)MEM_callocN ( sizeof ( ClothSpring ), "cloth spring" );
+
+ if (!spring) {
+ cloth_free_errorsprings(cloth, edgelist);
+ return 0;
+ }
+
+ spring->ij = tspring2->ij;
+ spring->kl = tspring->ij;
+ spring->mn = tspring->kl;
+ spring->restlen = len_v3v3(cloth->verts[spring->kl].xrest, cloth->verts[spring->ij].xrest);
+ spring->type = CLOTH_SPRING_TYPE_BENDING_ANG;
+ spring->stiffness = (cloth->verts[spring->kl].bend_stiff + cloth->verts[spring->ij].bend_stiff) / 2.0f;
+ bend_springs++;
+
+ BLI_linklist_prepend ( &cloth->springs, spring );
}
-
- spring->ij = tspring2->ij;
- spring->kl = tspring->kl;
- spring->restlen = len_v3v3(cloth->verts[spring->kl].xrest, cloth->verts[spring->ij].xrest);
- spring->type = CLOTH_SPRING_TYPE_BENDING;
- spring->stiffness = (cloth->verts[spring->kl].bend_stiff + cloth->verts[spring->ij].bend_stiff) / 2.0f;
- bend_springs++;
-
- BLI_linklist_prepend ( &cloth->springs, spring );
+
+ search = search->next;
+ search2 = search2->next;
}
-
- search = search->next;
- search2 = search2->next;
}
+ else {
+ /* bending springs for hair strands */
+ /* The current algorightm only goes through the edges in order of the mesh edges list */
+ /* and makes springs between the outer vert of edges sharing a vertice. This works just */
+ /* fine for hair, but not for user generated string meshes. This could/should be later */
+ /* extended to work with non-ordered edges so that it can be used for general "rope */
+ /* dynamics" without the need for the vertices or edges to be ordered through the length*/
+ /* of the strands. -jahka */
+ search = cloth->springs;
+ search2 = search->next;
+ while (search && search2) {
+ tspring = search->link;
+ tspring2 = search2->link;
+
+ if (tspring->ij == tspring2->kl) {
+ spring = (ClothSpring *)MEM_callocN ( sizeof ( ClothSpring ), "cloth spring" );
+
+ if (!spring) {
+ cloth_free_errorsprings(cloth, edgelist);
+ return 0;
+ }
+
+ spring->ij = tspring2->ij;
+ spring->kl = tspring->kl;
+ spring->restlen = len_v3v3(cloth->verts[spring->kl].xrest, cloth->verts[spring->ij].xrest);
+ spring->type = CLOTH_SPRING_TYPE_BENDING;
+ spring->stiffness = (cloth->verts[spring->kl].bend_stiff + cloth->verts[spring->ij].bend_stiff) / 2.0f;
+ bend_springs++;
+
+ BLI_linklist_prepend ( &cloth->springs, spring );
+ }
+
+ search = search->next;
+ search2 = search2->next;
+ }
+ }
+
+ cloth_hair_update_bending_rest_targets(clmd);
}
/* note: the edges may already exist so run reinsert */
@@ -1326,18 +1425,17 @@ static int cloth_build_springs ( ClothModifierData *clmd, DerivedMesh *dm )
BLI_edgeset_add(edgeset, medge[i].v1, medge[i].v2);
}
- for (i = 0; i < numfaces; i++) { /* edge springs */
- if (mface[i].v4) {
- BLI_edgeset_add(edgeset, mface[i].v1, mface[i].v3);
-
- BLI_edgeset_add(edgeset, mface[i].v2, mface[i].v4);
+ for (i = 0; i < numpolys; i++) { /* edge springs */
+ if (mpoly[i].totloop == 4) {
+ BLI_edgeset_add(edgeset, mloop[mpoly[i].loopstart + 0].v, mloop[mpoly[i].loopstart + 2].v);
+ BLI_edgeset_add(edgeset, mloop[mpoly[i].loopstart + 1].v, mloop[mpoly[i].loopstart + 3].v);
}
}
cloth->numsprings = struct_springs + shear_springs + bend_springs;
- cloth_free_edgelist(edgelist, numverts);
+ cloth_free_edgelist(edgelist, mvert_num);
#if 0
if (G.debug_value > 0)
diff --git a/source/blender/blenkernel/intern/collision.c b/source/blender/blenkernel/intern/collision.c
index 2f600935b1e..d35762a6f13 100644
--- a/source/blender/blenkernel/intern/collision.c
+++ b/source/blender/blenkernel/intern/collision.c
@@ -33,6 +33,7 @@
#include "MEM_guardedalloc.h"
#include "DNA_cloth_types.h"
+#include "DNA_effect_types.h"
#include "DNA_group_types.h"
#include "DNA_object_types.h"
#include "DNA_object_force.h"
@@ -45,6 +46,7 @@
#include "BLI_edgehash.h"
#include "BKE_cloth.h"
+#include "BKE_effect.h"
#include "BKE_modifier.h"
#include "BKE_scene.h"
@@ -69,82 +71,92 @@ void collision_move_object(CollisionModifierData *collmd, float step, float prev
float tv[3] = {0, 0, 0};
unsigned int i = 0;
- for ( i = 0; i < collmd->numverts; i++ ) {
+ for (i = 0; i < collmd->mvert_num; i++) {
sub_v3_v3v3(tv, collmd->xnew[i].co, collmd->x[i].co);
VECADDS(collmd->current_x[i].co, collmd->x[i].co, tv, prevstep);
VECADDS(collmd->current_xnew[i].co, collmd->x[i].co, tv, step);
sub_v3_v3v3(collmd->current_v[i].co, collmd->current_xnew[i].co, collmd->current_x[i].co);
}
- bvhtree_update_from_mvert ( collmd->bvhtree, collmd->mfaces, collmd->numfaces, collmd->current_x, collmd->current_xnew, collmd->numverts, 1 );
+ bvhtree_update_from_mvert(
+ collmd->bvhtree, collmd->current_x, collmd->current_xnew,
+ collmd->tri, collmd->tri_num, true);
}
-BVHTree *bvhtree_build_from_mvert ( MFace *mfaces, unsigned int numfaces, MVert *x, unsigned int UNUSED(numverts), float epsilon )
+BVHTree *bvhtree_build_from_mvert(
+ const MVert *mvert,
+ const struct MVertTri *tri, int tri_num,
+ float epsilon)
{
BVHTree *tree;
- float co[12];
- unsigned int i;
- MFace *tface = mfaces;
+ const MVertTri *vt;
+ int i;
+
+ tree = BLI_bvhtree_new(tri_num, epsilon, 4, 26);
- tree = BLI_bvhtree_new ( numfaces*2, epsilon, 4, 26 );
+ /* fill tree */
+ for (i = 0, vt = tri; i < tri_num; i++, vt++) {
+ float co[3][3];
- // fill tree
- for ( i = 0; i < numfaces; i++, tface++ ) {
- copy_v3_v3 ( &co[0*3], x[tface->v1].co );
- copy_v3_v3 ( &co[1*3], x[tface->v2].co );
- copy_v3_v3 ( &co[2*3], x[tface->v3].co );
- if ( tface->v4 )
- copy_v3_v3 ( &co[3*3], x[tface->v4].co );
+ copy_v3_v3(co[0], mvert[vt->tri[0]].co);
+ copy_v3_v3(co[1], mvert[vt->tri[1]].co);
+ copy_v3_v3(co[2], mvert[vt->tri[2]].co);
- BLI_bvhtree_insert ( tree, i, co, ( mfaces->v4 ? 4 : 3 ) );
+ BLI_bvhtree_insert(tree, i, co[0], 3);
}
- // balance tree
- BLI_bvhtree_balance ( tree );
+ /* balance tree */
+ BLI_bvhtree_balance(tree);
return tree;
}
-void bvhtree_update_from_mvert(BVHTree *bvhtree, MFace *faces, int numfaces, MVert *x, MVert *xnew, int UNUSED(numverts), int moving )
+void bvhtree_update_from_mvert(
+ BVHTree *bvhtree,
+ const MVert *mvert, const MVert *mvert_moving,
+ const MVertTri *tri, int tri_num,
+ bool moving)
{
+ const MVertTri *vt;
int i;
- MFace *mfaces = faces;
- float co[12], co_moving[12];
- bool ret = false;
- if ( !bvhtree )
+ if ((bvhtree == NULL) || (mvert == NULL)) {
return;
+ }
- if ( x ) {
- for ( i = 0; i < numfaces; i++, mfaces++ ) {
- copy_v3_v3 ( &co[0*3], x[mfaces->v1].co );
- copy_v3_v3 ( &co[1*3], x[mfaces->v2].co );
- copy_v3_v3 ( &co[2*3], x[mfaces->v3].co );
- if ( mfaces->v4 )
- copy_v3_v3 ( &co[3*3], x[mfaces->v4].co );
-
- // copy new locations into array
- if ( moving && xnew ) {
- // update moving positions
- copy_v3_v3 ( &co_moving[0*3], xnew[mfaces->v1].co );
- copy_v3_v3 ( &co_moving[1*3], xnew[mfaces->v2].co );
- copy_v3_v3 ( &co_moving[2*3], xnew[mfaces->v3].co );
- if ( mfaces->v4 )
- copy_v3_v3 ( &co_moving[3*3], xnew[mfaces->v4].co );
-
- ret = BLI_bvhtree_update_node ( bvhtree, i, co, co_moving, ( mfaces->v4 ? 4 : 3 ) );
- }
- else {
- ret = BLI_bvhtree_update_node ( bvhtree, i, co, NULL, ( mfaces->v4 ? 4 : 3 ) );
- }
+ if (mvert_moving == NULL) {
+ moving = false;
+ }
+
+ for (i = 0, vt = tri; i < tri_num; i++, vt++) {
+ float co[3][3];
+ bool ret;
+
+ copy_v3_v3(co[0], mvert[vt->tri[0]].co);
+ copy_v3_v3(co[1], mvert[vt->tri[1]].co);
+ copy_v3_v3(co[2], mvert[vt->tri[2]].co);
- // check if tree is already full
- if ( !ret )
- break;
+ /* copy new locations into array */
+ if (moving) {
+ float co_moving[3][3];
+ /* update moving positions */
+ copy_v3_v3(co_moving[0], mvert_moving[vt->tri[0]].co);
+ copy_v3_v3(co_moving[1], mvert_moving[vt->tri[1]].co);
+ copy_v3_v3(co_moving[2], mvert_moving[vt->tri[2]].co);
+
+ ret = BLI_bvhtree_update_node(bvhtree, i, &co[0][0], &co_moving[0][0], 3);
+ }
+ else {
+ ret = BLI_bvhtree_update_node(bvhtree, i, &co[0][0], NULL, 3);
}
- BLI_bvhtree_update_tree ( bvhtree );
+ /* check if tree is already full */
+ if (ret == false) {
+ break;
+ }
}
+
+ BLI_bvhtree_update_tree(bvhtree);
}
/***********************************
@@ -378,80 +390,29 @@ static CollPair* cloth_collision(ModifierData *md1, ModifierData *md2,
ClothModifierData *clmd = (ClothModifierData *)md1;
CollisionModifierData *collmd = (CollisionModifierData *) md2;
/* Cloth *cloth = clmd->clothObject; */ /* UNUSED */
- MFace *face1=NULL, *face2 = NULL;
+ const MVertTri *tri_a, *tri_b;
#ifdef WITH_BULLET
ClothVertex *verts1 = clmd->clothObject->verts;
#endif
double distance = 0;
float epsilon1 = clmd->coll_parms->epsilon;
float epsilon2 = BLI_bvhtree_getepsilon ( collmd->bvhtree );
- int i;
- face1 = & ( clmd->clothObject->mfaces[overlap->indexA] );
- face2 = & ( collmd->mfaces[overlap->indexB] );
-
- // check all 4 possible collisions
- for ( i = 0; i < 4; i++ ) {
- if ( i == 0 ) {
- // fill faceA
- collpair->ap1 = face1->v1;
- collpair->ap2 = face1->v2;
- collpair->ap3 = face1->v3;
-
- // fill faceB
- collpair->bp1 = face2->v1;
- collpair->bp2 = face2->v2;
- collpair->bp3 = face2->v3;
- }
- else if ( i == 1 ) {
- if ( face1->v4 ) {
- // fill faceA
- collpair->ap1 = face1->v1;
- collpair->ap2 = face1->v3;
- collpair->ap3 = face1->v4;
-
- // fill faceB
- collpair->bp1 = face2->v1;
- collpair->bp2 = face2->v2;
- collpair->bp3 = face2->v3;
- }
- else {
- i++;
- }
- }
- if ( i == 2 ) {
- if ( face2->v4 ) {
- // fill faceA
- collpair->ap1 = face1->v1;
- collpair->ap2 = face1->v2;
- collpair->ap3 = face1->v3;
-
- // fill faceB
- collpair->bp1 = face2->v1;
- collpair->bp2 = face2->v4;
- collpair->bp3 = face2->v3;
- }
- else {
- break;
- }
- }
- else if ( i == 3 ) {
- if ( face1->v4 && face2->v4 ) {
- // fill faceA
- collpair->ap1 = face1->v1;
- collpair->ap2 = face1->v3;
- collpair->ap3 = face1->v4;
-
- // fill faceB
- collpair->bp1 = face2->v1;
- collpair->bp2 = face2->v3;
- collpair->bp3 = face2->v4;
- }
- else {
- break;
- }
- }
-
+ tri_a = &clmd->clothObject->tri[overlap->indexA];
+ tri_b = &collmd->tri[overlap->indexB];
+
+ /* fill face_a */
+ collpair->ap1 = tri_a->tri[0];
+ collpair->ap2 = tri_a->tri[1];
+ collpair->ap3 = tri_a->tri[2];
+
+ /* fill face_b */
+ collpair->bp1 = tri_b->tri[0];
+ collpair->bp2 = tri_b->tri[1];
+ collpair->bp3 = tri_b->tri[2];
+
+ {
+
#ifdef WITH_BULLET
// calc distance + normal
distance = plNearestPoints (
@@ -648,24 +609,24 @@ static void cloth_bvh_objcollisions_nearcheck ( ClothModifierData * clmd, Collis
{
int i;
- *collisions = (CollPair *) MEM_mallocN(sizeof(CollPair) * numresult * 64, "collision array" ); // * 4 since cloth_collision_static can return more than 1 collision
+ *collisions = (CollPair *) MEM_mallocN(sizeof(CollPair) * numresult * 4, "collision array" ); // * 4 since cloth_collision_static can return more than 1 collision
*collisions_index = *collisions;
for ( i = 0; i < numresult; i++ ) {
- *collisions_index = cloth_collision ( (ModifierData *)clmd, (ModifierData *)collmd,
- overlap+i, *collisions_index, dt );
+ *collisions_index = cloth_collision((ModifierData *)clmd, (ModifierData *)collmd,
+ overlap+i, *collisions_index, dt);
}
}
static int cloth_bvh_objcollisions_resolve ( ClothModifierData * clmd, CollisionModifierData *collmd, CollPair *collisions, CollPair *collisions_index)
{
Cloth *cloth = clmd->clothObject;
- int i=0, j = 0, /*numfaces = 0, */ numverts = 0;
+ int i=0, j = 0, /*numfaces = 0, */ mvert_num = 0;
ClothVertex *verts = NULL;
int ret = 0;
int result = 0;
- numverts = clmd->clothObject->numverts;
+ mvert_num = clmd->clothObject->mvert_num;
verts = cloth->verts;
// process all collisions (calculate impulses, TODO: also repulses if distance too short)
@@ -678,7 +639,7 @@ static int cloth_bvh_objcollisions_resolve ( ClothModifierData * clmd, Collision
// apply impulses in parallel
if (result) {
- for (i = 0; i < numverts; i++) {
+ for (i = 0; i < mvert_num; i++) {
// calculate "velocities" (just xnew = xold + v; no dt in v)
if (verts[i].impulse_count) {
// VECADDMUL ( verts[i].tv, verts[i].impulse, 1.0f / verts[i].impulse_count );
@@ -704,7 +665,7 @@ int cloth_bvh_objcollision(Object *ob, ClothModifierData *clmd, float step, floa
{
Cloth *cloth= clmd->clothObject;
BVHTree *cloth_bvh= cloth->bvhtree;
- unsigned int i=0, /* numfaces = 0, */ /* UNUSED */ numverts = 0, k, l, j;
+ unsigned int i=0, /* numfaces = 0, */ /* UNUSED */ mvert_num = 0, k, l, j;
int rounds = 0; // result counts applied collisions; ic is for debug output;
ClothVertex *verts = NULL;
int ret = 0, ret2 = 0;
@@ -716,7 +677,7 @@ int cloth_bvh_objcollision(Object *ob, ClothModifierData *clmd, float step, floa
verts = cloth->verts;
/* numfaces = cloth->numfaces; */ /* UNUSED */
- numverts = cloth->numverts;
+ mvert_num = cloth->mvert_num;
////////////////////////////////////////////////////////////
// static collisions
@@ -762,7 +723,7 @@ int cloth_bvh_objcollision(Object *ob, ClothModifierData *clmd, float step, floa
continue;
/* search for overlapping collision pairs */
- overlap = BLI_bvhtree_overlap ( cloth_bvh, collmd->bvhtree, &result );
+ overlap = BLI_bvhtree_overlap(cloth_bvh, collmd->bvhtree, &result, NULL, NULL);
// go to next object if no overlap is there
if ( result && overlap ) {
@@ -792,8 +753,8 @@ int cloth_bvh_objcollision(Object *ob, ClothModifierData *clmd, float step, floa
// this is needed for bvh_calc_DOP_hull_moving() [kdop.c]
////////////////////////////////////////////////////////////
- // verts come from clmd
- for ( i = 0; i < numverts; i++ ) {
+ /* verts come from clmd */
+ for (i = 0; i < mvert_num; i++) {
if ( clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL ) {
if ( verts [i].flags & CLOTH_VERT_FLAG_PINNED ) {
continue;
@@ -818,13 +779,13 @@ int cloth_bvh_objcollision(Object *ob, ClothModifierData *clmd, float step, floa
verts = cloth->verts; // needed for openMP
/* numfaces = cloth->numfaces; */ /* UNUSED */
- numverts = cloth->numverts;
+ mvert_num = cloth->mvert_num;
verts = cloth->verts;
if ( cloth->bvhselftree ) {
// search for overlapping collision pairs
- overlap = BLI_bvhtree_overlap ( cloth->bvhselftree, cloth->bvhselftree, &result );
+ overlap = BLI_bvhtree_overlap(cloth->bvhselftree, cloth->bvhselftree, &result, NULL, NULL);
// #pragma omp parallel for private(k, i, j) schedule(static)
for ( k = 0; k < result; k++ ) {
@@ -896,8 +857,8 @@ int cloth_bvh_objcollision(Object *ob, ClothModifierData *clmd, float step, floa
////////////////////////////////////////////////////////////
// SELFCOLLISIONS: update velocities
////////////////////////////////////////////////////////////
- if ( ret2 ) {
- for ( i = 0; i < cloth->numverts; i++ ) {
+ if (ret2) {
+ for (i = 0; i < cloth->mvert_num; i++) {
if ( ! ( verts [i].flags & CLOTH_VERT_FLAG_PINNED ) ) {
sub_v3_v3v3(verts[i].tv, verts[i].tx, verts[i].txold);
}
@@ -913,3 +874,562 @@ int cloth_bvh_objcollision(Object *ob, ClothModifierData *clmd, float step, floa
return 1|MIN2 ( ret, 1 );
}
+
+BLI_INLINE void max_v3_v3v3(float r[3], const float a[3], const float b[3])
+{
+ r[0] = max_ff(a[0], b[0]);
+ r[1] = max_ff(a[1], b[1]);
+ r[2] = max_ff(a[2], b[2]);
+}
+
+void collision_get_collider_velocity(float vel_old[3], float vel_new[3], CollisionModifierData *collmd, CollPair *collpair)
+{
+ float u1, u2, u3;
+
+ /* compute barycentric coordinates */
+ collision_compute_barycentric(collpair->pb,
+ collmd->current_x[collpair->bp1].co,
+ collmd->current_x[collpair->bp2].co,
+ collmd->current_x[collpair->bp3].co,
+ &u1, &u2, &u3);
+
+ collision_interpolateOnTriangle(vel_new, collmd->current_v[collpair->bp1].co, collmd->current_v[collpair->bp2].co, collmd->current_v[collpair->bp3].co, u1, u2, u3);
+ /* XXX assume constant velocity of the collider for now */
+ copy_v3_v3(vel_old, vel_new);
+}
+
+static bool cloth_points_collision_response_static(ClothModifierData *clmd, CollisionModifierData *collmd, PartDeflect *pd,
+ CollPair *collpair, CollPair *collision_end, float dt)
+{
+ bool result = false;
+ float restitution = (1.0f - clmd->coll_parms->damping) * (1.0f - pd->pdef_sbdamp);
+ float inv_dt = 1.0f / dt;
+ Cloth *cloth1 = clmd->clothObject;
+
+ // float w1, w2;
+ float u1, u2, u3;
+ float v1[3], v2_old[3], v2_new[3], v_rel_old[3], v_rel_new[3];
+ float epsilon2 = BLI_bvhtree_getepsilon ( collmd->bvhtree );
+
+ for ( ; collpair != collision_end; collpair++ ) {
+ float margin_distance = (float)(collpair->distance - (double)epsilon2);
+ float impulse[3];
+ float mag_v_rel;
+
+ if (margin_distance > 0.0f)
+ continue;
+
+ zero_v3(impulse);
+
+ /* only handle static collisions here */
+ if ( collpair->flag & COLLISION_IN_FUTURE )
+ continue;
+
+ /* compute barycentric coordinates for both collision points */
+ // w1 = 1.0f - collpair->time;
+ // w2 = collpair->time;
+
+ /* was: txold */
+ collision_compute_barycentric ( collpair->pb,
+ collmd->current_x[collpair->bp1].co,
+ collmd->current_x[collpair->bp2].co,
+ collmd->current_x[collpair->bp3].co,
+ &u1, &u2, &u3 );
+
+ /* Calculate relative velocity */
+ copy_v3_v3(v1, cloth1->verts[collpair->ap1].tv);
+
+ collision_interpolateOnTriangle ( v2_new, collmd->current_v[collpair->bp1].co, collmd->current_v[collpair->bp2].co, collmd->current_v[collpair->bp3].co, u1, u2, u3 );
+ /* XXX assume constant velocity of the collider for now */
+ copy_v3_v3(v2_old, v2_new);
+
+ sub_v3_v3v3(v_rel_old, v1, v2_old);
+ sub_v3_v3v3(v_rel_new, v1, v2_new);
+
+ /* normal component of the relative velocity */
+ mag_v_rel = dot_v3v3(v_rel_old, collpair->normal);
+
+ /**** DEBUG ****/
+ BKE_sim_debug_data_add_dot(collpair->pa, 0.9, 0.2, 0.2, "collision", 833, collpair->face1, collpair->face2);
+ BKE_sim_debug_data_add_dot(collpair->pb, 0.2, 0.9, 0.2, "collision", 834, collpair->face1, collpair->face2);
+ BKE_sim_debug_data_add_line(collpair->pa, collpair->pb, 0.8, 0.8, 0.8, "collision", 835, collpair->face1, collpair->face2);
+ /********/
+
+ if (mag_v_rel < -ALMOST_ZERO) {
+ float v_nor_old, v_nor_new;
+ float v_tan_old[3], v_tan_new[3];
+ float bounce, repulse;
+
+ /* Collision response based on
+ * "Simulating Complex Hair with Robust Collision Handling" (Choe, Choi, Ko, ACM SIGGRAPH 2005)
+ * http://graphics.snu.ac.kr/publications/2005-choe-HairSim/Choe_2005_SCA.pdf
+ */
+
+ v_nor_old = mag_v_rel;
+ v_nor_new = dot_v3v3(v_rel_new, collpair->normal);
+
+ madd_v3_v3v3fl(v_tan_old, v_rel_old, collpair->normal, -v_nor_old);
+ madd_v3_v3v3fl(v_tan_new, v_rel_new, collpair->normal, -v_nor_new);
+
+ repulse = -margin_distance * inv_dt + dot_v3v3(v1, collpair->normal);
+
+ if (margin_distance < -epsilon2) {
+ bounce = -v_nor_new + v_nor_old * restitution;
+ mul_v3_v3fl(impulse, collpair->normal, max_ff(repulse, bounce));
+ }
+ else {
+ bounce = 0.0f;
+ mul_v3_v3fl(impulse, collpair->normal, repulse);
+ }
+ cloth1->verts[collpair->ap1].impulse_count++;
+
+ result = true;
+ }
+
+ if (result) {
+ int i = 0;
+
+ for (i = 0; i < 3; i++) {
+ if (cloth1->verts[collpair->ap1].impulse_count > 0 && fabsf(cloth1->verts[collpair->ap1].impulse[i]) < fabsf(impulse[i]))
+ cloth1->verts[collpair->ap1].impulse[i] = impulse[i];
+ }
+ }
+ }
+ return result;
+}
+
+BLI_INLINE bool cloth_point_face_collision_params(const float p1[3], const float p2[3], const float v0[3], const float v1[3], const float v2[3],
+ float r_nor[3], float *r_lambda, float r_w[4])
+{
+ float edge1[3], edge2[3], p2face[3], p1p2[3], v0p2[3];
+ float nor_v0p2, nor_p1p2;
+
+ sub_v3_v3v3(edge1, v1, v0);
+ sub_v3_v3v3(edge2, v2, v0);
+ cross_v3_v3v3(r_nor, edge1, edge2);
+ normalize_v3(r_nor);
+
+ nor_v0p2 = dot_v3v3(v0p2, r_nor);
+ madd_v3_v3v3fl(p2face, p2, r_nor, -nor_v0p2);
+ interp_weights_face_v3(r_w, v0, v1, v2, NULL, p2face);
+
+ sub_v3_v3v3(p1p2, p2, p1);
+ sub_v3_v3v3(v0p2, p2, v0);
+ nor_p1p2 = dot_v3v3(p1p2, r_nor);
+ *r_lambda = (nor_p1p2 != 0.0f ? nor_v0p2 / nor_p1p2 : 0.0f);
+
+ return r_w[1] >= 0.0f && r_w[2] >= 0.0f && r_w[1] + r_w[2] <= 1.0f;
+
+#if 0 /* XXX this method uses the intersection point, but is broken and doesn't work well in general */
+ float p[3], vec1[3], line[3], edge1[3], edge2[3], q[3];
+ float a, f, u, v;
+
+ sub_v3_v3v3(edge1, v1, v0);
+ sub_v3_v3v3(edge2, v2, v0);
+ sub_v3_v3v3(line, p2, p1);
+
+ cross_v3_v3v3(p, line, edge2);
+ a = dot_v3v3(edge1, p);
+ if (a == 0.0f) return 0;
+ f = 1.0f / a;
+
+ sub_v3_v3v3(vec1, p1, v0);
+
+ u = f * dot_v3v3(vec1, p);
+ if ((u < 0.0f) || (u > 1.0f))
+ return false;
+
+ cross_v3_v3v3(q, vec1, edge1);
+
+ v = f * dot_v3v3(line, q);
+ if ((v < 0.0f) || ((u + v) > 1.0f))
+ return false;
+
+ *r_lambda = f * dot_v3v3(edge2, q);
+ /* don't care about 0..1 lambda range here */
+ /*if ((*r_lambda < 0.0f) || (*r_lambda > 1.0f))
+ * return 0;
+ */
+
+ r_w[0] = 1.0f - u - v;
+ r_w[1] = u;
+ r_w[2] = v;
+ r_w[3] = 0.0f;
+
+ cross_v3_v3v3(r_nor, edge1, edge2);
+ normalize_v3(r_nor);
+
+ return true;
+#endif
+}
+
+static CollPair *cloth_point_collpair(
+ float p1[3], float p2[3], const MVert *mverts, int bp1, int bp2, int bp3,
+ int index_cloth, int index_coll, float epsilon, CollPair *collpair)
+{
+ const float *co1 = mverts[bp1].co, *co2 = mverts[bp2].co, *co3 = mverts[bp3].co;
+ float lambda /*, distance1 */, distance2;
+ float facenor[3], v1p1[3], v1p2[3];
+ float w[4];
+
+ if (!cloth_point_face_collision_params(p1, p2, co1, co2, co3, facenor, &lambda, w))
+ return collpair;
+
+ sub_v3_v3v3(v1p1, p1, co1);
+// distance1 = dot_v3v3(v1p1, facenor);
+ sub_v3_v3v3(v1p2, p2, co1);
+ distance2 = dot_v3v3(v1p2, facenor);
+// if (distance2 > epsilon || (distance1 < 0.0f && distance2 < 0.0f))
+ if (distance2 > epsilon)
+ return collpair;
+
+ collpair->face1 = index_cloth; /* XXX actually not a face, but equivalent index for point */
+ collpair->face2 = index_coll;
+ collpair->ap1 = index_cloth;
+ collpair->ap2 = collpair->ap3 = -1; /* unused */
+ collpair->bp1 = bp1;
+ collpair->bp2 = bp2;
+ collpair->bp3 = bp3;
+
+ /* note: using the second point here, which is
+ * the current updated position that needs to be corrected
+ */
+ copy_v3_v3(collpair->pa, p2);
+ collpair->distance = distance2;
+ mul_v3_v3fl(collpair->vector, facenor, -distance2);
+
+ interp_v3_v3v3v3(collpair->pb, co1, co2, co3, w);
+
+ copy_v3_v3(collpair->normal, facenor);
+ collpair->time = lambda;
+ collpair->flag = 0;
+
+ collpair++;
+ return collpair;
+}
+
+//Determines collisions on overlap, collisions are written to collpair[i] and collision+number_collision_found is returned
+static CollPair *cloth_point_collision(
+ ModifierData *md1, ModifierData *md2,
+ BVHTreeOverlap *overlap, float epsilon, CollPair *collpair, float UNUSED(dt))
+{
+ ClothModifierData *clmd = (ClothModifierData *)md1;
+ CollisionModifierData *collmd = (CollisionModifierData *) md2;
+ /* Cloth *cloth = clmd->clothObject; */ /* UNUSED */
+ ClothVertex *vert = NULL;
+ const MVertTri *vt;
+ const MVert *mverts = collmd->current_x;
+
+ vert = &clmd->clothObject->verts[overlap->indexA];
+ vt = &collmd->tri[overlap->indexB];
+
+ collpair = cloth_point_collpair(
+ vert->tx, vert->x, mverts,
+ vt->tri[0], vt->tri[1], vt->tri[2],
+ overlap->indexA, overlap->indexB,
+ epsilon, collpair);
+
+ return collpair;
+}
+
+static void cloth_points_objcollisions_nearcheck(ClothModifierData * clmd, CollisionModifierData *collmd,
+ CollPair **collisions, CollPair **collisions_index,
+ int numresult, BVHTreeOverlap *overlap, float epsilon, double dt)
+{
+ int i;
+
+ /* can return 2 collisions in total */
+ *collisions = (CollPair *) MEM_mallocN(sizeof(CollPair) * numresult * 2, "collision array" );
+ *collisions_index = *collisions;
+
+ for ( i = 0; i < numresult; i++ ) {
+ *collisions_index = cloth_point_collision((ModifierData *)clmd, (ModifierData *)collmd,
+ overlap+i, epsilon, *collisions_index, dt);
+ }
+}
+
+static int cloth_points_objcollisions_resolve(ClothModifierData * clmd, CollisionModifierData *collmd, PartDeflect *pd,
+ CollPair *collisions, CollPair *collisions_index, float dt)
+{
+ Cloth *cloth = clmd->clothObject;
+ int i = 0, mvert_num = clmd->clothObject->mvert_num;
+ ClothVertex *verts = cloth->verts;
+ int ret = 0;
+
+ // process all collisions
+ if ( collmd->bvhtree ) {
+ bool result = cloth_points_collision_response_static(clmd, collmd, pd, collisions, collisions_index, dt);
+
+ // apply impulses in parallel
+ if (result) {
+ for (i = 0; i < mvert_num; i++) {
+ // calculate "velocities" (just xnew = xold + v; no dt in v)
+ if (verts[i].impulse_count) {
+ // VECADDMUL ( verts[i].tv, verts[i].impulse, 1.0f / verts[i].impulse_count );
+ VECADD ( verts[i].tv, verts[i].tv, verts[i].impulse);
+ zero_v3(verts[i].impulse);
+ verts[i].impulse_count = 0;
+
+ ret++;
+ }
+ }
+ }
+ }
+
+ return ret;
+}
+
+// cloth - object collisions
+int cloth_points_objcollision(Object *ob, ClothModifierData *clmd, float step, float dt)
+{
+ Cloth *cloth= clmd->clothObject;
+ BVHTree *cloth_bvh;
+ int rounds = 0; // result counts applied collisions; ic is for debug output;
+ float round_dt = dt / (float)clmd->coll_parms->loop_count;
+ unsigned int i = 0, mvert_num = 0;
+ ClothVertex *verts = NULL;
+ int ret = 0, ret2 = 0;
+ Object **collobjs = NULL;
+ unsigned int numcollobj = 0;
+
+ verts = cloth->verts;
+ mvert_num = cloth->mvert_num;
+
+ ////////////////////////////////////////////////////////////
+ // static collisions
+ ////////////////////////////////////////////////////////////
+
+ // create temporary cloth points bvh
+ cloth_bvh = BLI_bvhtree_new(mvert_num, max_ff(clmd->coll_parms->epsilon, clmd->coll_parms->distance_repel), 4, 6);
+ /* fill tree */
+ for (i = 0; i < mvert_num; i++) {
+ float co[2][3];
+
+ copy_v3_v3(co[0], verts[i].x);
+ copy_v3_v3(co[1], verts[i].tx);
+
+ BLI_bvhtree_insert(cloth_bvh, i, co[0], 2);
+ }
+ /* balance tree */
+ BLI_bvhtree_balance(cloth_bvh);
+
+ collobjs = get_collisionobjects(clmd->scene, ob, clmd->coll_parms->group, &numcollobj, eModifierType_Collision);
+ if (!collobjs)
+ return 0;
+
+ /* move object to position (step) in time */
+ for (i = 0; i < numcollobj; i++) {
+ Object *collob= collobjs[i];
+ CollisionModifierData *collmd = (CollisionModifierData *)modifiers_findByType(collob, eModifierType_Collision);
+ if (!collmd->bvhtree)
+ continue;
+
+ /* move object to position (step) in time */
+ collision_move_object ( collmd, step + dt, step );
+ }
+
+ do {
+ CollPair **collisions, **collisions_index;
+
+ ret2 = 0;
+
+ collisions = MEM_callocN(sizeof(CollPair *) *numcollobj, "CollPair");
+ collisions_index = MEM_callocN(sizeof(CollPair *) *numcollobj, "CollPair");
+
+ // check all collision objects
+ for (i = 0; i < numcollobj; i++) {
+ Object *collob= collobjs[i];
+ CollisionModifierData *collmd = (CollisionModifierData *)modifiers_findByType(collob, eModifierType_Collision);
+ BVHTreeOverlap *overlap = NULL;
+ unsigned int result = 0;
+ float epsilon;
+
+ if (!collmd->bvhtree)
+ continue;
+
+ /* search for overlapping collision pairs */
+ overlap = BLI_bvhtree_overlap(cloth_bvh, collmd->bvhtree, &result, NULL, NULL);
+ epsilon = BLI_bvhtree_getepsilon(collmd->bvhtree);
+
+ // go to next object if no overlap is there
+ if (result && overlap) {
+ /* check if collisions really happen (costly near check) */
+ cloth_points_objcollisions_nearcheck(clmd, collmd, &collisions[i], &collisions_index[i],
+ result, overlap, epsilon, round_dt);
+
+ // resolve nearby collisions
+ ret += cloth_points_objcollisions_resolve(clmd, collmd, collob->pd, collisions[i], collisions_index[i], round_dt);
+ ret2 += ret;
+ }
+
+ if (overlap)
+ MEM_freeN ( overlap );
+ }
+ rounds++;
+
+ for (i = 0; i < numcollobj; i++) {
+ if (collisions[i])
+ MEM_freeN(collisions[i]);
+ }
+
+ MEM_freeN(collisions);
+ MEM_freeN(collisions_index);
+
+ ////////////////////////////////////////////////////////////
+ // update positions
+ // this is needed for bvh_calc_DOP_hull_moving() [kdop.c]
+ ////////////////////////////////////////////////////////////
+
+ // verts come from clmd
+ for (i = 0; i < mvert_num; i++) {
+ if ( clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL ) {
+ if ( verts [i].flags & CLOTH_VERT_FLAG_PINNED ) {
+ continue;
+ }
+ }
+
+ VECADD ( verts[i].tx, verts[i].txold, verts[i].tv );
+ }
+ ////////////////////////////////////////////////////////////
+ }
+ while ( ret2 && ( clmd->coll_parms->loop_count>rounds ) );
+
+ if (collobjs)
+ MEM_freeN(collobjs);
+
+ BLI_bvhtree_free(cloth_bvh);
+
+ return 1|MIN2 ( ret, 1 );
+}
+
+void cloth_find_point_contacts(Object *ob, ClothModifierData *clmd, float step, float dt,
+ ColliderContacts **r_collider_contacts, int *r_totcolliders)
+{
+ Cloth *cloth= clmd->clothObject;
+ BVHTree *cloth_bvh;
+ unsigned int i = 0, mvert_num = 0;
+ ClothVertex *verts = NULL;
+
+ ColliderContacts *collider_contacts;
+
+ Object **collobjs = NULL;
+ unsigned int numcollobj = 0;
+
+ verts = cloth->verts;
+ mvert_num = cloth->mvert_num;
+
+ ////////////////////////////////////////////////////////////
+ // static collisions
+ ////////////////////////////////////////////////////////////
+
+ // create temporary cloth points bvh
+ cloth_bvh = BLI_bvhtree_new(mvert_num, max_ff(clmd->coll_parms->epsilon, clmd->coll_parms->distance_repel), 4, 6);
+ /* fill tree */
+ for (i = 0; i < mvert_num; i++) {
+ float co[6];
+
+ copy_v3_v3(&co[0*3], verts[i].x);
+ copy_v3_v3(&co[1*3], verts[i].tx);
+
+ BLI_bvhtree_insert(cloth_bvh, i, co, 2);
+ }
+ /* balance tree */
+ BLI_bvhtree_balance(cloth_bvh);
+
+ collobjs = get_collisionobjects(clmd->scene, ob, clmd->coll_parms->group, &numcollobj, eModifierType_Collision);
+ if (!collobjs) {
+ *r_collider_contacts = NULL;
+ *r_totcolliders = 0;
+ return;
+ }
+
+ /* move object to position (step) in time */
+ for (i = 0; i < numcollobj; i++) {
+ Object *collob= collobjs[i];
+ CollisionModifierData *collmd = (CollisionModifierData *)modifiers_findByType(collob, eModifierType_Collision);
+ if (!collmd->bvhtree)
+ continue;
+
+ /* move object to position (step) in time */
+ collision_move_object ( collmd, step + dt, step );
+ }
+
+ collider_contacts = MEM_callocN(sizeof(ColliderContacts) * numcollobj, "CollPair");
+
+ // check all collision objects
+ for (i = 0; i < numcollobj; i++) {
+ ColliderContacts *ct = collider_contacts + i;
+ Object *collob= collobjs[i];
+ CollisionModifierData *collmd = (CollisionModifierData *)modifiers_findByType(collob, eModifierType_Collision);
+ BVHTreeOverlap *overlap;
+ unsigned int result = 0;
+ float epsilon;
+
+ ct->ob = collob;
+ ct->collmd = collmd;
+ ct->collisions = NULL;
+ ct->totcollisions = 0;
+
+ if (!collmd->bvhtree)
+ continue;
+
+ /* search for overlapping collision pairs */
+ overlap = BLI_bvhtree_overlap(cloth_bvh, collmd->bvhtree, &result, NULL, NULL);
+ epsilon = BLI_bvhtree_getepsilon(collmd->bvhtree);
+
+ // go to next object if no overlap is there
+ if (result && overlap) {
+ CollPair *collisions_index;
+
+ /* check if collisions really happen (costly near check) */
+ cloth_points_objcollisions_nearcheck(clmd, collmd, &ct->collisions, &collisions_index,
+ result, overlap, epsilon, dt);
+ ct->totcollisions = (int)(collisions_index - ct->collisions);
+
+ // resolve nearby collisions
+// ret += cloth_points_objcollisions_resolve(clmd, collmd, collob->pd, collisions[i], collisions_index[i], dt);
+ }
+
+ if (overlap)
+ MEM_freeN(overlap);
+ }
+
+ if (collobjs)
+ MEM_freeN(collobjs);
+
+ BLI_bvhtree_free(cloth_bvh);
+
+ ////////////////////////////////////////////////////////////
+ // update positions
+ // this is needed for bvh_calc_DOP_hull_moving() [kdop.c]
+ ////////////////////////////////////////////////////////////
+
+ // verts come from clmd
+ for (i = 0; i < mvert_num; i++) {
+ if (clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL) {
+ if (verts [i].flags & CLOTH_VERT_FLAG_PINNED) {
+ continue;
+ }
+ }
+
+ VECADD(verts[i].tx, verts[i].txold, verts[i].tv);
+ }
+ ////////////////////////////////////////////////////////////
+
+ *r_collider_contacts = collider_contacts;
+ *r_totcolliders = numcollobj;
+}
+
+void cloth_free_contacts(ColliderContacts *collider_contacts, int totcolliders)
+{
+ if (collider_contacts) {
+ int i;
+ for (i = 0; i < totcolliders; ++i) {
+ ColliderContacts *ct = collider_contacts + i;
+ if (ct->collisions) {
+ MEM_freeN(ct->collisions);
+ }
+ }
+ MEM_freeN(collider_contacts);
+ }
+}
diff --git a/source/blender/blenkernel/intern/colortools.c b/source/blender/blenkernel/intern/colortools.c
index a63e06c7cb8..7a3cc118eb5 100644
--- a/source/blender/blenkernel/intern/colortools.c
+++ b/source/blender/blenkernel/intern/colortools.c
@@ -43,6 +43,7 @@
#include "BLI_blenlib.h"
#include "BLI_math.h"
#include "BLI_utildefines.h"
+#include "BLI_threads.h"
#include "BKE_colortools.h"
#include "BKE_curve.h"
@@ -50,9 +51,12 @@
#include "IMB_colormanagement.h"
-#include "IMB_imbuf.h"
#include "IMB_imbuf_types.h"
+#ifdef _OPENMP
+# include <omp.h>
+#endif
+
/* ********************************* color curve ********************* */
/* ***************** operations on full struct ************* */
@@ -721,6 +725,16 @@ void curvemapping_changed(CurveMapping *cumap, const bool rem_doubles)
cmp[a].y -= dy;
}
}
+
+ /* ensure zoom-level respects clipping */
+ if (BLI_rctf_size_x(&cumap->curr) > BLI_rctf_size_x(&cumap->clipr)) {
+ cumap->curr.xmin = cumap->clipr.xmin;
+ cumap->curr.xmax = cumap->clipr.xmax;
+ }
+ if (BLI_rctf_size_y(&cumap->curr) > BLI_rctf_size_y(&cumap->clipr)) {
+ cumap->curr.ymin = cumap->clipr.ymin;
+ cumap->curr.ymax = cumap->clipr.ymax;
+ }
}
@@ -791,7 +805,17 @@ float curvemap_evaluateF(const CurveMap *cuma, float value)
float curvemapping_evaluateF(const CurveMapping *cumap, int cur, float value)
{
const CurveMap *cuma = cumap->cm + cur;
- return curvemap_evaluateF(cuma, value);
+ float val = curvemap_evaluateF(cuma, value);
+
+ /* account for clipping */
+ if (cumap->flag & CUMA_DO_CLIP) {
+ if (val < cumap->curr.ymin)
+ val = cumap->curr.ymin;
+ else if (val > cumap->curr.ymax)
+ val = cumap->curr.ymax;
+ }
+
+ return val;
}
/* vector case */
@@ -961,7 +985,6 @@ void BKE_histogram_update_sample_line(Histogram *hist, ImBuf *ibuf, const ColorM
{
int i, x, y;
const float *fp;
- float rgb[3];
unsigned char *cp;
int x1 = 0.5f + hist->co[0][0] * ibuf->x;
@@ -990,20 +1013,40 @@ void BKE_histogram_update_sample_line(Histogram *hist, ImBuf *ibuf, const ColorM
}
else {
if (ibuf->rect_float) {
+ float rgba[4];
fp = (ibuf->rect_float + (ibuf->channels) * (y * ibuf->x + x));
- copy_v3_v3(rgb, fp);
- IMB_colormanagement_processor_apply_v3(cm_processor, rgb);
+ switch (ibuf->channels) {
+ case 4:
+ copy_v4_v4(rgba, fp);
+ IMB_colormanagement_processor_apply_v4(cm_processor, rgba);
+ break;
+ case 3:
+ copy_v3_v3(rgba, fp);
+ IMB_colormanagement_processor_apply_v3(cm_processor, rgba);
+ rgba[3] = 1.0f;
+ break;
+ case 2:
+ copy_v3_fl(rgba, fp[0]);
+ rgba[3] = fp[1];
+ break;
+ case 1:
+ copy_v3_fl(rgba, fp[0]);
+ rgba[3] = 1.0f;
+ break;
+ default:
+ BLI_assert(0);
+ }
- hist->data_luma[i] = rgb_to_luma(rgb);
- hist->data_r[i] = rgb[0];
- hist->data_g[i] = rgb[1];
- hist->data_b[i] = rgb[2];
- hist->data_a[i] = fp[3];
+ hist->data_luma[i] = IMB_colormanagement_get_luminance(rgba);
+ hist->data_r[i] = rgba[0];
+ hist->data_g[i] = rgba[1];
+ hist->data_b[i] = rgba[2];
+ hist->data_a[i] = rgba[3];
}
else if (ibuf->rect) {
cp = (unsigned char *)(ibuf->rect + y * ibuf->x + x);
- hist->data_luma[i] = (float)rgb_to_luma_byte(cp) / 255.0f;
+ hist->data_luma[i] = (float)IMB_colormanagement_get_luminance_byte(cp) / 255.0f;
hist->data_r[i] = (float)cp[0] / 255.0f;
hist->data_g[i] = (float)cp[1] / 255.0f;
hist->data_b[i] = (float)cp[2] / 255.0f;
@@ -1020,18 +1063,28 @@ void BKE_histogram_update_sample_line(Histogram *hist, ImBuf *ibuf, const ColorM
void scopes_update(Scopes *scopes, ImBuf *ibuf, const ColorManagedViewSettings *view_settings,
const ColorManagedDisplaySettings *display_settings)
{
- int x, y, c;
+#ifdef _OPENMP
+ const int num_threads = BLI_system_thread_count();
+#endif
+ int a, y;
unsigned int nl, na, nr, ng, nb;
double divl, diva, divr, divg, divb;
- const float *rf = NULL;
- unsigned char *rc = NULL;
- unsigned int *bin_lum, *bin_r, *bin_g, *bin_b, *bin_a;
- int savedlines, saveline;
- float rgba[4], ycc[3], luma;
+ unsigned char *display_buffer;
+ unsigned int bin_lum[256] = {0},
+ bin_r[256] = {0},
+ bin_g[256] = {0},
+ bin_b[256] = {0},
+ bin_a[256] = {0};
+ unsigned int bin_lum_t[BLENDER_MAX_THREADS][256] = {{0}},
+ bin_r_t[BLENDER_MAX_THREADS][256] = {{0}},
+ bin_g_t[BLENDER_MAX_THREADS][256] = {{0}},
+ bin_b_t[BLENDER_MAX_THREADS][256] = {{0}},
+ bin_a_t[BLENDER_MAX_THREADS][256] = {{0}};
int ycc_mode = -1;
const bool is_float = (ibuf->rect_float != NULL);
void *cache_handle = NULL;
struct ColormanageProcessor *cm_processor = NULL;
+ int rows_per_sample_line;
if (ibuf->rect == NULL && ibuf->rect_float == NULL) return;
@@ -1061,24 +1114,18 @@ void scopes_update(Scopes *scopes, ImBuf *ibuf, const ColorManagedViewSettings *
break;
}
- /* temp table to count pix value for histogram */
- bin_r = MEM_callocN(256 * sizeof(unsigned int), "temp historgram bins");
- bin_g = MEM_callocN(256 * sizeof(unsigned int), "temp historgram bins");
- bin_b = MEM_callocN(256 * sizeof(unsigned int), "temp historgram bins");
- bin_a = MEM_callocN(256 * sizeof(unsigned int), "temp historgram bins");
- bin_lum = MEM_callocN(256 * sizeof(unsigned int), "temp historgram bins");
-
/* convert to number of lines with logarithmic scale */
scopes->sample_lines = (scopes->accuracy * 0.01f) * (scopes->accuracy * 0.01f) * ibuf->y;
+ CLAMP_MIN(scopes->sample_lines, 1);
if (scopes->sample_full)
scopes->sample_lines = ibuf->y;
/* scan the image */
- savedlines = 0;
- for (c = 0; c < 3; c++) {
- scopes->minmax[c][0] = 25500.0f;
- scopes->minmax[c][1] = -25500.0f;
+ rows_per_sample_line = ibuf->y / scopes->sample_lines;
+ for (a = 0; a < 3; a++) {
+ scopes->minmax[a][0] = 25500.0f;
+ scopes->minmax[a][1] = -25500.0f;
}
scopes->waveform_tot = ibuf->x * scopes->sample_lines;
@@ -1097,27 +1144,61 @@ void scopes_update(Scopes *scopes, ImBuf *ibuf, const ColorManagedViewSettings *
scopes->waveform_3 = MEM_callocN(scopes->waveform_tot * 2 * sizeof(float), "waveform point channel 3");
scopes->vecscope = MEM_callocN(scopes->waveform_tot * 2 * sizeof(float), "vectorscope point channel");
- if (is_float)
- rf = ibuf->rect_float;
+ if (ibuf->rect_float) {
+ cm_processor = IMB_colormanagement_display_processor_new(view_settings, display_settings);
+ }
else {
- rc = (unsigned char *)IMB_display_buffer_acquire(ibuf, view_settings, display_settings, &cache_handle);
+ display_buffer = (unsigned char *)IMB_display_buffer_acquire(ibuf,
+ view_settings,
+ display_settings,
+ &cache_handle);
}
-
- if (ibuf->rect_float)
- cm_processor = IMB_colormanagement_display_processor_new(view_settings, display_settings);
+ /* Keep number of threads in sync with the merge parts below. */
+#pragma omp parallel for private(y) schedule(static) num_threads(num_threads) if (ibuf->y > 256)
for (y = 0; y < ibuf->y; y++) {
- if (savedlines < scopes->sample_lines && y >= ((savedlines) * ibuf->y) / (scopes->sample_lines + 1)) {
- saveline = 1;
- }
+#ifdef _OPENMP
+ const int thread_idx = omp_get_thread_num();
+#else
+ const int thread_idx = 0;
+#endif
+ const float *rf = NULL;
+ const unsigned char *rc = NULL;
+ const int savedlines = y / rows_per_sample_line;
+ const bool do_sample_line = (savedlines < scopes->sample_lines) && (y % rows_per_sample_line) == 0;
+ float min[3] = { FLT_MAX, FLT_MAX, FLT_MAX},
+ max[3] = {-FLT_MAX, -FLT_MAX, -FLT_MAX};
+ int x, c;
+ if (is_float)
+ rf = ibuf->rect_float + ((size_t)y) * ibuf->x * ibuf->channels;
else {
- saveline = 0;
+ rc = display_buffer + ((size_t)y) * ibuf->x * ibuf->channels;
}
for (x = 0; x < ibuf->x; x++) {
-
+ float rgba[4], ycc[3], luma;
if (is_float) {
- copy_v4_v4(rgba, rf);
- IMB_colormanagement_processor_apply_v4(cm_processor, rgba);
+
+ switch (ibuf->channels) {
+ case 4:
+ copy_v4_v4(rgba, rf);
+ IMB_colormanagement_processor_apply_v4(cm_processor, rgba);
+ break;
+ case 3:
+ copy_v3_v3(rgba, rf);
+ IMB_colormanagement_processor_apply_v3(cm_processor, rgba);
+ rgba[3] = 1.0f;
+ break;
+ case 2:
+ copy_v3_fl(rgba, rf[0]);
+ rgba[3] = rf[1];
+ break;
+ case 1:
+ copy_v3_fl(rgba, rf[0]);
+ rgba[3] = 1.0f;
+ break;
+ default:
+ BLI_assert(0);
+ }
}
else {
for (c = 0; c < 4; c++)
@@ -1125,32 +1206,32 @@ void scopes_update(Scopes *scopes, ImBuf *ibuf, const ColorManagedViewSettings *
}
/* we still need luma for histogram */
- luma = rgb_to_luma(rgba);
+ luma = IMB_colormanagement_get_luminance(rgba);
/* check for min max */
if (ycc_mode == -1) {
for (c = 0; c < 3; c++) {
- if (rgba[c] < scopes->minmax[c][0]) scopes->minmax[c][0] = rgba[c];
- if (rgba[c] > scopes->minmax[c][1]) scopes->minmax[c][1] = rgba[c];
+ if (rgba[c] < min[c]) min[c] = rgba[c];
+ if (rgba[c] > max[c]) max[c] = rgba[c];
}
}
else {
rgb_to_ycc(rgba[0], rgba[1], rgba[2], &ycc[0], &ycc[1], &ycc[2], ycc_mode);
for (c = 0; c < 3; c++) {
ycc[c] *= INV_255;
- if (ycc[c] < scopes->minmax[c][0]) scopes->minmax[c][0] = ycc[c];
- if (ycc[c] > scopes->minmax[c][1]) scopes->minmax[c][1] = ycc[c];
+ if (ycc[c] < min[c]) min[c] = ycc[c];
+ if (ycc[c] > max[c]) max[c] = ycc[c];
}
}
/* increment count for histo*/
- bin_lum[get_bin_float(luma)] += 1;
- bin_r[get_bin_float(rgba[0])] += 1;
- bin_g[get_bin_float(rgba[1])] += 1;
- bin_b[get_bin_float(rgba[2])] += 1;
- bin_a[get_bin_float(rgba[3])] += 1;
+ bin_lum_t[thread_idx][get_bin_float(luma)] += 1;
+ bin_r_t[thread_idx][get_bin_float(rgba[0])] += 1;
+ bin_g_t[thread_idx][get_bin_float(rgba[1])] += 1;
+ bin_b_t[thread_idx][get_bin_float(rgba[2])] += 1;
+ bin_a_t[thread_idx][get_bin_float(rgba[3])] += 1;
/* save sample if needed */
- if (saveline) {
+ if (do_sample_line) {
const float fx = (float)x / (float)ibuf->x;
const int idx = 2 * (ibuf->x * savedlines + x);
save_sample_line(scopes, idx, fx, rgba, ycc);
@@ -1159,29 +1240,57 @@ void scopes_update(Scopes *scopes, ImBuf *ibuf, const ColorManagedViewSettings *
rf += ibuf->channels;
rc += ibuf->channels;
}
- if (saveline)
- savedlines += 1;
+#pragma omp critical
+ {
+ for (c = 0; c < 3; c++) {
+ if (min[c] < scopes->minmax[c][0]) scopes->minmax[c][0] = min[c];
+ if (max[c] > scopes->minmax[c][1]) scopes->minmax[c][1] = max[c];
+ }
+ }
+ }
+
+#ifdef _OPENMP
+ if (ibuf->y > 256) {
+ for (a = 0; a < num_threads; a++) {
+ int b;
+ for (b = 0; b < 256; b++) {
+ bin_lum[b] += bin_lum_t[a][b];
+ bin_r[b] += bin_r_t[a][b];
+ bin_g[b] += bin_g_t[a][b];
+ bin_b[b] += bin_b_t[a][b];
+ bin_a[b] += bin_a_t[a][b];
+ }
+ }
+ }
+ else
+#endif
+ {
+ memcpy(bin_lum, bin_lum_t[0], sizeof(bin_lum));
+ memcpy(bin_r, bin_r_t[0], sizeof(bin_r));
+ memcpy(bin_g, bin_g_t[0], sizeof(bin_g));
+ memcpy(bin_b, bin_b_t[0], sizeof(bin_b));
+ memcpy(bin_a, bin_a_t[0], sizeof(bin_a));
}
/* test for nicer distribution even - non standard, leave it out for a while */
#if 0
- for (x = 0; x < 256; x++) {
- bin_lum[x] = sqrt (bin_lum[x]);
- bin_r[x] = sqrt(bin_r[x]);
- bin_g[x] = sqrt(bin_g[x]);
- bin_b[x] = sqrt(bin_b[x]);
- bin_a[x] = sqrt(bin_a[x]);
+ for (a = 0; a < 256; a++) {
+ bin_lum[a] = sqrt (bin_lum[a]);
+ bin_r[a] = sqrt(bin_r[a]);
+ bin_g[a] = sqrt(bin_g[a]);
+ bin_b[a] = sqrt(bin_b[a]);
+ bin_a[a] = sqrt(bin_a[a]);
}
#endif
/* convert hist data to float (proportional to max count) */
nl = na = nr = nb = ng = 0;
- for (x = 0; x < 256; x++) {
- if (bin_lum[x] > nl) nl = bin_lum[x];
- if (bin_r[x] > nr) nr = bin_r[x];
- if (bin_g[x] > ng) ng = bin_g[x];
- if (bin_b[x] > nb) nb = bin_b[x];
- if (bin_a[x] > na) na = bin_a[x];
+ for (a = 0; a < 256; a++) {
+ if (bin_lum[a] > nl) nl = bin_lum[a];
+ if (bin_r[a] > nr) nr = bin_r[a];
+ if (bin_g[a] > ng) ng = bin_g[a];
+ if (bin_b[a] > nb) nb = bin_b[a];
+ if (bin_a[a] > na) na = bin_a[a];
}
divl = nl ? 1.0 / (double)nl : 1.0;
diva = na ? 1.0 / (double)na : 1.0;
@@ -1189,18 +1298,13 @@ void scopes_update(Scopes *scopes, ImBuf *ibuf, const ColorManagedViewSettings *
divg = ng ? 1.0 / (double)ng : 1.0;
divb = nb ? 1.0 / (double)nb : 1.0;
- for (x = 0; x < 256; x++) {
- scopes->hist.data_luma[x] = bin_lum[x] * divl;
- scopes->hist.data_r[x] = bin_r[x] * divr;
- scopes->hist.data_g[x] = bin_g[x] * divg;
- scopes->hist.data_b[x] = bin_b[x] * divb;
- scopes->hist.data_a[x] = bin_a[x] * diva;
+ for (a = 0; a < 256; a++) {
+ scopes->hist.data_luma[a] = bin_lum[a] * divl;
+ scopes->hist.data_r[a] = bin_r[a] * divr;
+ scopes->hist.data_g[a] = bin_g[a] * divg;
+ scopes->hist.data_b[a] = bin_b[a] * divb;
+ scopes->hist.data_a[a] = bin_a[a] * diva;
}
- MEM_freeN(bin_lum);
- MEM_freeN(bin_r);
- MEM_freeN(bin_g);
- MEM_freeN(bin_b);
- MEM_freeN(bin_a);
if (cm_processor)
IMB_colormanagement_processor_free(cm_processor);
@@ -1304,3 +1408,9 @@ void BKE_color_managed_colorspace_settings_copy(ColorManagedColorspaceSettings *
{
BLI_strncpy(colorspace_settings->name, settings->name, sizeof(colorspace_settings->name));
}
+
+bool BKE_color_managed_colorspace_settings_equals(const ColorManagedColorspaceSettings *settings1,
+ const ColorManagedColorspaceSettings *settings2)
+{
+ return STREQ(settings1->name, settings2->name);
+}
diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c
index ee7bad773fa..ed2e609ae53 100644
--- a/source/blender/blenkernel/intern/constraint.c
+++ b/source/blender/blenkernel/intern/constraint.c
@@ -43,7 +43,7 @@
#include "BLI_kdopbvh.h"
#include "BLI_utildefines.h"
-#include "BLF_translation.h"
+#include "BLT_translation.h"
#include "DNA_armature_types.h"
#include "DNA_constraint_types.h"
@@ -76,9 +76,12 @@
#include "BKE_idprop.h"
#include "BKE_shrinkwrap.h"
#include "BKE_editmesh.h"
+#include "BKE_scene.h"
#include "BKE_tracking.h"
#include "BKE_movieclip.h"
+#include "BIK_api.h"
+
#ifdef WITH_PYTHON
# include "BPY_extern.h"
#endif
@@ -185,6 +188,10 @@ void BKE_constraints_clear_evalob(bConstraintOb *cob)
/* calculate delta of constraints evaluation */
invert_m4_m4(imat, cob->startmat);
+ /* XXX This would seem to be in wrong order. However, it does not work in 'right' order - would be nice to
+ * understand why premul is needed here instead of usual postmul?
+ * In any case, we **do not get a delta** here (e.g. startmat & matrix having same location, still gives
+ * a 'delta' with non-null translation component :/ ).*/
mul_m4_m4m4(delta, cob->matrix, imat);
/* copy matrices back to source */
@@ -225,7 +232,8 @@ void BKE_constraints_clear_evalob(bConstraintOb *cob)
* of a matrix from one space to another for constraint evaluation.
* For now, this is only implemented for Objects and PoseChannels.
*/
-void BKE_constraint_mat_convertspace(Object *ob, bPoseChannel *pchan, float mat[4][4], short from, short to)
+void BKE_constraint_mat_convertspace(
+ Object *ob, bPoseChannel *pchan, float mat[4][4], short from, short to, const bool keep_scale)
{
float diff_mat[4][4];
float imat[4][4];
@@ -248,7 +256,7 @@ void BKE_constraint_mat_convertspace(Object *ob, bPoseChannel *pchan, float mat[
/* use pose-space as stepping stone for other spaces... */
if (ELEM(to, CONSTRAINT_SPACE_LOCAL, CONSTRAINT_SPACE_PARLOCAL)) {
/* call self with slightly different values */
- BKE_constraint_mat_convertspace(ob, pchan, mat, CONSTRAINT_SPACE_POSE, to);
+ BKE_constraint_mat_convertspace(ob, pchan, mat, CONSTRAINT_SPACE_POSE, to, keep_scale);
}
break;
}
@@ -284,7 +292,7 @@ void BKE_constraint_mat_convertspace(Object *ob, bPoseChannel *pchan, float mat[
/* use pose-space as stepping stone for other spaces */
if (ELEM(to, CONSTRAINT_SPACE_WORLD, CONSTRAINT_SPACE_PARLOCAL)) {
/* call self with slightly different values */
- BKE_constraint_mat_convertspace(ob, pchan, mat, CONSTRAINT_SPACE_POSE, to);
+ BKE_constraint_mat_convertspace(ob, pchan, mat, CONSTRAINT_SPACE_POSE, to, keep_scale);
}
break;
}
@@ -299,7 +307,7 @@ void BKE_constraint_mat_convertspace(Object *ob, bPoseChannel *pchan, float mat[
/* use pose-space as stepping stone for other spaces */
if (ELEM(to, CONSTRAINT_SPACE_WORLD, CONSTRAINT_SPACE_LOCAL)) {
/* call self with slightly different values */
- BKE_constraint_mat_convertspace(ob, pchan, mat, CONSTRAINT_SPACE_POSE, to);
+ BKE_constraint_mat_convertspace(ob, pchan, mat, CONSTRAINT_SPACE_POSE, to, keep_scale);
}
break;
}
@@ -319,8 +327,17 @@ void BKE_constraint_mat_convertspace(Object *ob, bPoseChannel *pchan, float mat[
/* Local space in this case will have to be defined as local to the owner's
* transform-property-rotated axes. So subtract this rotation component.
*/
+ /* XXX This is actually an ugly hack, local space of a parent-less object *is* the same as
+ * global space!
+ * Think what we want actually here is some kind of 'Final Space', i.e. once transformations
+ * are applied - users are often confused about this too, this is not consistent with bones
+ * local space either... Meh :|
+ * --mont29
+ */
BKE_object_to_mat4(ob, diff_mat);
- normalize_m4(diff_mat);
+ if (!keep_scale) {
+ normalize_m4(diff_mat);
+ }
zero_v3(diff_mat[3]);
invert_m4_m4_safe(imat, diff_mat);
@@ -338,8 +355,11 @@ void BKE_constraint_mat_convertspace(Object *ob, bPoseChannel *pchan, float mat[
/* Local space in this case will have to be defined as local to the owner's
* transform-property-rotated axes. So add back this rotation component.
*/
+ /* XXX See comment above for world->local case... */
BKE_object_to_mat4(ob, diff_mat);
- normalize_m4(diff_mat);
+ if (!keep_scale) {
+ normalize_m4(diff_mat);
+ }
zero_v3(diff_mat[3]);
mul_m4_m4m4(mat, diff_mat, mat);
@@ -427,7 +447,7 @@ static void contarget_get_mesh_mat(Object *ob, const char *substring, float mat[
copy_v3_v3(plane, tmat[1]);
cross_v3_v3v3(mat[0], normal, plane);
- if (len_v3(mat[0]) < 1e-3f) {
+ if (len_squared_v3(mat[0]) < SQUARE(1e-3f)) {
copy_v3_v3(plane, tmat[0]);
cross_v3_v3v3(mat[0], normal, plane);
}
@@ -507,7 +527,7 @@ static void constraint_target_to_mat4(Object *ob, const char *substring, float m
/* Case OBJECT */
if (!strlen(substring)) {
copy_m4_m4(mat, ob->obmat);
- BKE_constraint_mat_convertspace(ob, NULL, mat, from, to);
+ BKE_constraint_mat_convertspace(ob, NULL, mat, from, to, false);
}
/* Case VERTEXGROUP */
/* Current method just takes the average location of all the points in the
@@ -520,11 +540,11 @@ static void constraint_target_to_mat4(Object *ob, const char *substring, float m
*/
else if (ob->type == OB_MESH) {
contarget_get_mesh_mat(ob, substring, mat);
- BKE_constraint_mat_convertspace(ob, NULL, mat, from, to);
+ BKE_constraint_mat_convertspace(ob, NULL, mat, from, to, false);
}
else if (ob->type == OB_LATTICE) {
contarget_get_lattice_mat(ob, substring, mat);
- BKE_constraint_mat_convertspace(ob, NULL, mat, from, to);
+ BKE_constraint_mat_convertspace(ob, NULL, mat, from, to, false);
}
/* Case BONE */
else {
@@ -557,7 +577,7 @@ static void constraint_target_to_mat4(Object *ob, const char *substring, float m
copy_m4_m4(mat, ob->obmat);
/* convert matrix space as required */
- BKE_constraint_mat_convertspace(ob, pchan, mat, from, to);
+ BKE_constraint_mat_convertspace(ob, pchan, mat, from, to, false);
}
}
@@ -1967,7 +1987,7 @@ static void pycon_get_tarmat(bConstraint *con, bConstraintOb *cob, bConstraintTa
static void pycon_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *targets)
{
#ifndef WITH_PYTHON
- (void)con; (void)cob; (void)targets; /* unused */
+ UNUSED_VARS(con, cob, targets);
return;
#else
bPythonConstraint *data = con->data;
@@ -2613,6 +2633,8 @@ static void stretchto_new_data(void *cdata)
data->plane = 0;
data->orglength = 0.0;
data->bulge = 1.0;
+ data->bulge_max = 1.0f;
+ data->bulge_min = 1.0f;
}
static void stretchto_id_looper(bConstraint *con, ConstraintIDFunc func, void *userdata)
@@ -2658,7 +2680,7 @@ static void stretchto_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *t
if (VALID_CONS_TARGET(ct)) {
float size[3], scale[3], vec[3], xx[3], zz[3], orth[3];
float totmat[3][3];
- float dist;
+ float dist, bulge;
/* store scaling before destroying obmat */
mat4_to_size(size, cob->matrix);
@@ -2676,7 +2698,7 @@ static void stretchto_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *t
/* vec[2] /= size[2];*/
/* dist = normalize_v3(vec);*/
-
+
dist = len_v3v3(cob->matrix[3], ct->matrix[3]);
/* Only Y constrained object axis scale should be used, to keep same length when scaling it. */
dist /= size[1];
@@ -2684,23 +2706,49 @@ static void stretchto_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *t
/* data->orglength==0 occurs on first run, and after 'R' button is clicked */
if (data->orglength == 0)
data->orglength = dist;
- if (data->bulge == 0)
- data->bulge = 1.0;
-
+
scale[1] = dist / data->orglength;
+
+ bulge = powf(data->orglength / dist, data->bulge);
+
+ if (bulge > 1.0f) {
+ if (data->flag & STRETCHTOCON_USE_BULGE_MAX) {
+ float bulge_max = max_ff(data->bulge_max, 1.0f);
+ float hard = min_ff(bulge, bulge_max);
+
+ float range = bulge_max - 1.0f;
+ float scale = (range > 0.0f) ? 1.0f / range : 0.0f;
+ float soft = 1.0f + range * atanf((bulge - 1.0f) * scale) / (float)M_PI_2;
+
+ bulge = interpf(soft, hard, data->bulge_smooth);
+ }
+ }
+ if (bulge < 1.0f) {
+ if (data->flag & STRETCHTOCON_USE_BULGE_MIN) {
+ float bulge_min = CLAMPIS(data->bulge_min, 0.0f, 1.0f);
+ float hard = max_ff(bulge, bulge_min);
+
+ float range = 1.0f - bulge_min;
+ float scale = (range > 0.0f) ? 1.0f / range : 0.0f;
+ float soft = 1.0f - range * atanf((1.0f - bulge) * scale) / (float)M_PI_2;
+
+ bulge = interpf(soft, hard, data->bulge_smooth);
+ }
+ }
+
switch (data->volmode) {
/* volume preserving scaling */
case VOLUME_XZ:
- scale[0] = 1.0f - sqrtf(data->bulge) + sqrtf(data->bulge * (data->orglength / dist));
+ scale[0] = sqrtf(bulge);
scale[2] = scale[0];
break;
case VOLUME_X:
- scale[0] = 1.0f + data->bulge * (data->orglength / dist - 1);
+ scale[0] = bulge;
scale[2] = 1.0;
break;
case VOLUME_Z:
scale[0] = 1.0;
- scale[2] = 1.0f + data->bulge * (data->orglength / dist - 1);
+ scale[2] = bulge;
break;
/* don't care for volume */
case NO_VOLUME:
@@ -3390,7 +3438,7 @@ static void shrinkwrap_get_tarmat(bConstraint *con, bConstraintOb *cob, bConstra
if (scon->shrinkType == MOD_SHRINKWRAP_NEAREST_VERTEX)
bvhtree_from_mesh_verts(&treeData, target, 0.0, 2, 6);
else
- bvhtree_from_mesh_faces(&treeData, target, 0.0, 2, 6);
+ bvhtree_from_mesh_looptri(&treeData, target, 0.0, 2, 6);
if (treeData.tree == NULL) {
fail = true;
@@ -3429,8 +3477,11 @@ static void shrinkwrap_get_tarmat(bConstraint *con, bConstraintOb *cob, bConstra
}
/* transform normal into requested space */
+ /* Note that in this specific case, we need to keep scaling in non-parented 'local2world' object
+ * case, because SpaceTransform also takes it into account when handling normals. See T42447. */
unit_m4(mat);
- BKE_constraint_mat_convertspace(cob->ob, cob->pchan, mat, CONSTRAINT_SPACE_LOCAL, scon->projAxisSpace);
+ BKE_constraint_mat_convertspace(cob->ob, cob->pchan, mat,
+ CONSTRAINT_SPACE_LOCAL, scon->projAxisSpace, true);
invert_m4(mat);
mul_mat3_m4_v3(mat, no);
@@ -3439,7 +3490,7 @@ static void shrinkwrap_get_tarmat(bConstraint *con, bConstraintOb *cob, bConstra
break;
}
- bvhtree_from_mesh_faces(&treeData, target, scon->dist, 4, 6);
+ bvhtree_from_mesh_looptri(&treeData, target, scon->dist, 4, 6);
if (treeData.tree == NULL) {
fail = true;
break;
@@ -3650,6 +3701,9 @@ static void splineik_new_data(void *cdata)
bSplineIKConstraint *data = (bSplineIKConstraint *)cdata;
data->chainlen = 1;
+ data->bulge = 1.0;
+ data->bulge_max = 1.0f;
+ data->bulge_min = 1.0f;
}
static void splineik_id_looper(bConstraint *con, ConstraintIDFunc func, void *userdata)
@@ -3870,7 +3924,8 @@ static void followtrack_evaluate(bConstraint *con, bConstraintOb *cob, ListBase
MovieTrackingTrack *track;
MovieTrackingObject *tracking_object;
Object *camob = data->camera ? data->camera : scene->camera;
- int framenr;
+ float ctime = BKE_scene_frame_get(scene);
+ float framenr;
if (data->flag & FOLLOWTRACK_ACTIVECLIP)
clip = scene->clip;
@@ -3893,7 +3948,7 @@ static void followtrack_evaluate(bConstraint *con, bConstraintOb *cob, ListBase
if (!track)
return;
- framenr = BKE_movieclip_remap_scene_to_clip_frame(clip, scene->r.cfra);
+ framenr = BKE_movieclip_remap_scene_to_clip_frame(clip, ctime);
if (data->flag & FOLLOWTRACK_USE_3D_POSITION) {
if (track->flag & TRACK_HAS_BUNDLE) {
@@ -3921,7 +3976,6 @@ static void followtrack_evaluate(bConstraint *con, bConstraintOb *cob, ListBase
}
}
else {
- MovieTrackingMarker *marker;
float vec[3], disp[3], axis[3], mat[4][4];
float aspect = (scene->r.xsch * scene->r.xasp) / (scene->r.ysch * scene->r.yasp);
float len, d;
@@ -3947,10 +4001,7 @@ static void followtrack_evaluate(bConstraint *con, bConstraintOb *cob, ListBase
float pos[2], rmat[4][4];
BKE_movieclip_get_size(clip, NULL, &width, &height);
-
- marker = BKE_tracking_marker_get(track, framenr);
-
- add_v2_v2v2(pos, marker->pos, track->offset);
+ BKE_tracking_marker_get_subframe_position(track, framenr, pos);
if (data->flag & FOLLOWTRACK_USE_UNDISTORTION) {
/* Undistortion need to happen in pixel space. */
@@ -4055,8 +4106,9 @@ static void followtrack_evaluate(bConstraint *con, bConstraintOb *cob, ListBase
mul_v3_m4v3(ray_end, imat, cob->matrix[3]);
sub_v3_v3v3(ray_nor, ray_end, ray_start);
+ normalize_v3(ray_nor);
- bvhtree_from_mesh_faces(&treeData, target, 0.0f, 4, 6);
+ bvhtree_from_mesh_looptri(&treeData, target, 0.0f, 4, 6);
hit.dist = FLT_MAX;
hit.index = -1;
@@ -4120,7 +4172,8 @@ static void camerasolver_evaluate(bConstraint *con, bConstraintOb *cob, ListBase
float mat[4][4], obmat[4][4];
MovieTracking *tracking = &clip->tracking;
MovieTrackingObject *object = BKE_tracking_object_get_camera(tracking);
- int framenr = BKE_movieclip_remap_scene_to_clip_frame(clip, scene->r.cfra);
+ float ctime = BKE_scene_frame_get(scene);
+ float framenr = BKE_movieclip_remap_scene_to_clip_frame(clip, ctime);
BKE_tracking_camera_get_reconstructed_interpolate(tracking, object, framenr, mat);
@@ -4185,7 +4238,8 @@ static void objectsolver_evaluate(bConstraint *con, bConstraintOb *cob, ListBase
if (object) {
float mat[4][4], obmat[4][4], imat[4][4], cammat[4][4], camimat[4][4], parmat[4][4];
- int framenr = BKE_movieclip_remap_scene_to_clip_frame(clip, scene->r.cfra);
+ float ctime = BKE_scene_frame_get(scene);
+ float framenr = BKE_movieclip_remap_scene_to_clip_frame(clip, ctime);
BKE_object_where_is_calc_mat4(scene, camob, cammat);
@@ -4265,7 +4319,7 @@ static void constraints_init_typeinfo(void)
/* This function should be used for getting the appropriate type-info when only
* a constraint type is known
*/
-bConstraintTypeInfo *BKE_constraint_typeinfo_from_type(int type)
+const bConstraintTypeInfo *BKE_constraint_typeinfo_from_type(int type)
{
/* initialize the type-info list? */
if (CTI_INIT) {
@@ -4290,7 +4344,7 @@ bConstraintTypeInfo *BKE_constraint_typeinfo_from_type(int type)
/* This function should always be used to get the appropriate type-info, as it
* has checks which prevent segfaults in some weird cases.
*/
-bConstraintTypeInfo *BKE_constraint_typeinfo_get(bConstraint *con)
+const bConstraintTypeInfo *BKE_constraint_typeinfo_get(bConstraint *con)
{
/* only return typeinfo for valid constraints */
if (con)
@@ -4317,10 +4371,10 @@ static void con_unlink_refs_cb(bConstraint *UNUSED(con), ID **idpoin, bool is_re
* be sure to run BIK_clear_data() when freeing an IK constraint,
* unless DAG_relations_tag_update is called.
*/
-void BKE_constraint_free_data(bConstraint *con)
+void BKE_constraint_free_data_ex(bConstraint *con, bool do_id_user)
{
if (con->data) {
- bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
+ const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
if (cti) {
/* perform any special freeing constraint may have */
@@ -4328,7 +4382,7 @@ void BKE_constraint_free_data(bConstraint *con)
cti->free_data(con);
/* unlink the referenced resources it uses */
- if (cti->id_looper)
+ if (do_id_user && cti->id_looper)
cti->id_looper(con, con_unlink_refs_cb, NULL);
}
@@ -4337,19 +4391,28 @@ void BKE_constraint_free_data(bConstraint *con)
}
}
+void BKE_constraint_free_data(bConstraint *con)
+{
+ BKE_constraint_free_data_ex(con, true);
+}
+
/* Free all constraints from a constraint-stack */
-void BKE_constraints_free(ListBase *list)
+void BKE_constraints_free_ex(ListBase *list, bool do_id_user)
{
bConstraint *con;
/* Free constraint data and also any extra data */
for (con = list->first; con; con = con->next)
- BKE_constraint_free_data(con);
+ BKE_constraint_free_data_ex(con, do_id_user);
/* Free the whole list */
BLI_freelistN(list);
}
+void BKE_constraints_free(ListBase *list)
+{
+ BKE_constraints_free_ex(list, true);
+}
/* Remove the specified constraint from the given constraint stack */
bool BKE_constraint_remove(ListBase *list, bConstraint *con)
@@ -4357,10 +4420,26 @@ bool BKE_constraint_remove(ListBase *list, bConstraint *con)
if (con) {
BKE_constraint_free_data(con);
BLI_freelinkN(list, con);
- return 1;
+ return true;
+ }
+ else {
+ return false;
+ }
+}
+
+bool BKE_constraint_remove_ex(ListBase *list, Object *ob, bConstraint *con, bool clear_dep)
+{
+ const short type = con->type;
+ if (BKE_constraint_remove(list, con)) {
+ /* ITASC needs to be rebuilt once a constraint is removed [#26920] */
+ if (clear_dep && ELEM(type, CONSTRAINT_TYPE_KINEMATIC, CONSTRAINT_TYPE_SPLINEIK)) {
+ BIK_clear_data(ob->pose);
+ }
+ return true;
+ }
+ else {
+ return false;
}
- else
- return 0;
}
/* ......... */
@@ -4369,7 +4448,7 @@ bool BKE_constraint_remove(ListBase *list, bConstraint *con)
static bConstraint *add_new_constraint_internal(const char *name, short type)
{
bConstraint *con = MEM_callocN(sizeof(bConstraint), "Constraint");
- bConstraintTypeInfo *cti = BKE_constraint_typeinfo_from_type(type);
+ const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_from_type(type);
const char *newName;
/* Set up a generic constraint datablock */
@@ -4496,7 +4575,7 @@ void BKE_constraints_id_loop(ListBase *conlist, ConstraintIDFunc func, void *use
bConstraint *con;
for (con = conlist->first; con; con = con->next) {
- bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
+ const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
if (cti) {
if (cti->id_looper)
@@ -4531,7 +4610,7 @@ void BKE_constraints_copy(ListBase *dst, const ListBase *src, bool do_extern)
BLI_duplicatelist(dst, src);
for (con = dst->first, srccon = src->first; con && srccon; srccon = srccon->next, con = con->next) {
- bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
+ const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
/* make a new copy of the constraint's data */
con->data = MEM_dupallocN(con->data);
@@ -4624,15 +4703,15 @@ bool BKE_constraints_proxylocked_owner(Object *ob, bPoseChannel *pchan)
/* On bone-level, check if bone is on proxy-protected layer */
if ((pchan->bone) && (pchan->bone->layer & arm->layer_protected))
- return 1;
+ return true;
}
else {
/* FIXME: constraints on object-level are not handled well yet */
- return 1;
+ return true;
}
}
- return 0;
+ return false;
}
/* -------- Target-Matrix Stuff ------- */
@@ -4646,7 +4725,7 @@ bool BKE_constraints_proxylocked_owner(Object *ob, bPoseChannel *pchan)
*/
void BKE_constraint_target_matrix_get(Scene *scene, bConstraint *con, int index, short ownertype, void *ownerdata, float mat[4][4], float ctime)
{
- bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
+ const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
ListBase targets = {NULL, NULL};
bConstraintOb *cob;
bConstraintTarget *ct;
@@ -4713,7 +4792,7 @@ void BKE_constraint_target_matrix_get(Scene *scene, bConstraint *con, int index,
/* Get the list of targets required for solving a constraint */
void BKE_constraint_targets_for_solving_get(bConstraint *con, bConstraintOb *cob, ListBase *targets, float ctime)
{
- bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
+ const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
if (cti && cti->get_constraint_targets) {
bConstraintTarget *ct;
@@ -4758,7 +4837,7 @@ void BKE_constraints_solve(ListBase *conlist, bConstraintOb *cob, float ctime)
/* loop over available constraints, solving and blending them */
for (con = conlist->first; con; con = con->next) {
- bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
+ const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
ListBase targets = {NULL, NULL};
/* these we can skip completely (invalid constraints...) */
@@ -4778,7 +4857,7 @@ void BKE_constraints_solve(ListBase *conlist, bConstraintOb *cob, float ctime)
copy_m4_m4(oldmat, cob->matrix);
/* move owner matrix into right space */
- BKE_constraint_mat_convertspace(cob->ob, cob->pchan, cob->matrix, CONSTRAINT_SPACE_WORLD, con->ownspace);
+ BKE_constraint_mat_convertspace(cob->ob, cob->pchan, cob->matrix, CONSTRAINT_SPACE_WORLD, con->ownspace, false);
/* prepare targets for constraint solving */
BKE_constraint_targets_for_solving_get(con, cob, &targets, ctime);
@@ -4796,7 +4875,7 @@ void BKE_constraints_solve(ListBase *conlist, bConstraintOb *cob, float ctime)
/* move owner back into worldspace for next constraint/other business */
if ((con->flag & CONSTRAINT_SPACEONCE) == 0)
- BKE_constraint_mat_convertspace(cob->ob, cob->pchan, cob->matrix, con->ownspace, CONSTRAINT_SPACE_WORLD);
+ BKE_constraint_mat_convertspace(cob->ob, cob->pchan, cob->matrix, con->ownspace, CONSTRAINT_SPACE_WORLD, false);
/* Interpolate the enforcement, to blend result of constraint into final owner transform
* - all this happens in worldspace to prevent any weirdness creeping in ([#26014] and [#25725]),
diff --git a/source/blender/blenkernel/intern/context.c b/source/blender/blenkernel/intern/context.c
index de285f87444..d223a3aff9e 100644
--- a/source/blender/blenkernel/intern/context.c
+++ b/source/blender/blenkernel/intern/context.c
@@ -37,13 +37,14 @@
#include "DNA_windowmanager_types.h"
#include "DNA_object_types.h"
#include "DNA_linestyle_types.h"
+#include "DNA_gpencil_types.h"
#include "BLI_listbase.h"
#include "BLI_string.h"
#include "BLI_threads.h"
#include "BLI_utildefines.h"
-#include "BLF_translation.h"
+#include "BLT_translation.h"
#include "BKE_context.h"
#include "BKE_main.h"
@@ -257,7 +258,7 @@ static void *ctx_wm_python_context_get(
}
}
#else
- (void)C, (void)member, (void)member_type;
+ UNUSED_VARS(C, member, member_type);
#endif
/* don't allow UI context access from non-main threads */
@@ -453,7 +454,7 @@ static void data_dir_add(ListBase *lb, const char *member, const bool use_all)
{
LinkData *link;
- if ((use_all == false) && strcmp(member, "scene") == 0) /* exception */
+ if ((use_all == false) && STREQ(member, "scene")) /* exception */
return;
if (BLI_findstring(lb, member, offsetof(LinkData, data)))
@@ -545,7 +546,7 @@ ListBase CTX_data_dir_get(const bContext *C)
bool CTX_data_equals(const char *member, const char *str)
{
- return (strcmp(member, str) == 0);
+ return (STREQ(member, str));
}
bool CTX_data_dir(const char *member)
@@ -588,7 +589,7 @@ int ctx_data_list_count(const bContext *C, int (*func)(const bContext *, ListBas
ListBase list;
if (func(C, &list)) {
- int tot = BLI_countlist(&list);
+ int tot = BLI_listbase_count(&list);
BLI_freelistN(&list);
return tot;
}
@@ -1090,3 +1091,34 @@ int CTX_data_visible_pose_bones(const bContext *C, ListBase *list)
{
return ctx_data_collection_get(C, "visible_pose_bones", list);
}
+
+bGPdata *CTX_data_gpencil_data(const bContext *C)
+{
+ return ctx_data_pointer_get(C, "gpencil_data");
+}
+
+bGPDlayer *CTX_data_active_gpencil_layer(const bContext *C)
+{
+ return ctx_data_pointer_get(C, "active_gpencil_layer");
+}
+
+bGPDframe *CTX_data_active_gpencil_frame(const bContext *C)
+{
+ return ctx_data_pointer_get(C, "active_gpencil_frame");
+}
+
+int CTX_data_visible_gpencil_layers(const bContext *C, ListBase *list)
+{
+ return ctx_data_collection_get(C, "visible_gpencil_layers", list);
+}
+
+int CTX_data_editable_gpencil_layers(const bContext *C, ListBase *list)
+{
+ return ctx_data_collection_get(C, "editable_gpencil_layers", list);
+}
+
+int CTX_data_editable_gpencil_strokes(const bContext *C, ListBase *list)
+{
+ return ctx_data_collection_get(C, "editable_gpencil_strokes", list);
+}
+
diff --git a/source/blender/blenkernel/intern/crazyspace.c b/source/blender/blenkernel/intern/crazyspace.c
index 911bb19a594..c8de0786697 100644
--- a/source/blender/blenkernel/intern/crazyspace.c
+++ b/source/blender/blenkernel/intern/crazyspace.c
@@ -108,7 +108,7 @@ float (*BKE_crazyspace_get_mapped_editverts(Scene *scene, Object *obedit))[3]
/* disable subsurf temporal, get mapped cos, and enable it */
if (modifiers_disable_subsurf_temporary(obedit)) {
/* need to make new derivemesh */
- makeDerivedMesh(scene, obedit, me->edit_btmesh, CD_MASK_BAREMESH, 0);
+ makeDerivedMesh(scene, obedit, me->edit_btmesh, CD_MASK_BAREMESH, false);
}
/* now get the cage */
@@ -247,7 +247,9 @@ void BKE_crazyspace_set_quats_mesh(Mesh *me, float (*origcos)[3], float (*mapped
}
}
-int editbmesh_get_first_deform_matrices(Scene *scene, Object *ob, BMEditMesh *em,
+/** returns an array of deform matrices for crazyspace correction, and the
+ * number of modifiers left */
+int BKE_crazyspace_get_first_deform_matrices_editbmesh(Scene *scene, Object *ob, BMEditMesh *em,
float (**deformmats)[3][3], float (**deformcos)[3])
{
ModifierData *md;
@@ -266,7 +268,7 @@ int editbmesh_get_first_deform_matrices(Scene *scene, Object *ob, BMEditMesh *em
* modifiers with on cage editing that are enabled and support computing
* deform matrices */
for (i = 0; md && i <= cageIndex; i++, md = md->next) {
- ModifierTypeInfo *mti = modifierType_getInfo(md->type);
+ const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
if (!editbmesh_modifier_is_enabled(scene, md, dm))
continue;
@@ -322,7 +324,7 @@ int BKE_sculpt_get_first_deform_matrices(Scene *scene, Object *ob, float (**defo
md = modifiers_getVirtualModifierList(ob, &virtualModifierData);
for (; md; md = md->next) {
- ModifierTypeInfo *mti = modifierType_getInfo(md->type);
+ const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
if (!modifier_isEnabled(scene, md, eModifierMode_Realtime)) continue;
@@ -343,7 +345,7 @@ int BKE_sculpt_get_first_deform_matrices(Scene *scene, Object *ob, float (**defo
}
for (; md; md = md->next) {
- ModifierTypeInfo *mti = modifierType_getInfo(md->type);
+ const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
if (!modifier_isEnabled(scene, md, eModifierMode_Realtime)) continue;
@@ -377,7 +379,7 @@ void BKE_crazyspace_build_sculpt(Scene *scene, Object *ob, float (**deformmats)[
Mesh *me = (Mesh *)ob->data;
for (; md; md = md->next) {
- ModifierTypeInfo *mti = modifierType_getInfo(md->type);
+ const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
if (!modifier_isEnabled(scene, md, eModifierMode_Realtime)) continue;
diff --git a/source/blender/blenkernel/intern/curve.c b/source/blender/blenkernel/intern/curve.c
index cee5241cb5c..8d7d62be7e4 100644
--- a/source/blender/blenkernel/intern/curve.c
+++ b/source/blender/blenkernel/intern/curve.c
@@ -147,7 +147,7 @@ void BKE_curve_free(Curve *cu)
BKE_curve_editNurb_free(cu);
BKE_curve_unlink(cu);
- BKE_free_animdata((ID *)cu);
+ BKE_animdata_free((ID *)cu);
if (cu->mat)
MEM_freeN(cu->mat);
@@ -237,6 +237,10 @@ Curve *BKE_curve_copy(Curve *cu)
id_us_plus((ID *)cun->vfonti);
id_us_plus((ID *)cun->vfontbi);
+ if (cu->id.lib) {
+ BKE_id_lib_local_paths(G.main, cu->id.lib, &cun->id);
+ }
+
return cun;
}
@@ -589,6 +593,10 @@ Nurb *BKE_nurb_copy(Nurb *src, int pntsu, int pntsv)
newnu->pntsu = pntsu;
newnu->pntsv = pntsv;
+ /* caller can manually handle these arrays */
+ newnu->knotsu = NULL;
+ newnu->knotsv = NULL;
+
if (src->bezt) {
newnu->bezt = (BezTriple *)MEM_mallocN(pntsu * pntsv * sizeof(BezTriple), "copyNurb2");
}
@@ -729,6 +737,41 @@ void BKE_nurb_bezierPoints_add(Nurb *nu, int number)
}
+int BKE_nurb_index_from_uv(
+ Nurb *nu,
+ int u, int v)
+{
+ const int totu = nu->pntsu;
+ const int totv = nu->pntsv;
+
+ if (nu->flagu & CU_NURB_CYCLIC) {
+ u = mod_i(u, totu);
+ }
+ else if (u < 0 || u >= totu) {
+ return -1;
+ }
+
+ if (nu->flagv & CU_NURB_CYCLIC) {
+ v = mod_i(v, totv);
+ }
+ else if (v < 0 || v >= totv) {
+ return -1;
+ }
+
+ return (v * totu) + u;
+}
+
+void BKE_nurb_index_to_uv(
+ Nurb *nu, int index,
+ int *r_u, int *r_v)
+{
+ const int totu = nu->pntsu;
+ const int totv = nu->pntsv;
+ BLI_assert(index >= 0 && index < (nu->pntsu * nu->pntsv));
+ *r_u = (index % totu);
+ *r_v = (index / totu) % totv;
+}
+
BezTriple *BKE_nurb_bezt_get_next(Nurb *nu, BezTriple *bezt)
{
BezTriple *bezt_next;
@@ -865,6 +908,29 @@ void BKE_nurb_bezt_calc_plane(struct Nurb *nu, struct BezTriple *bezt, float r_p
normalize_v3(r_plane);
}
+void BKE_nurb_bpoint_calc_normal(struct Nurb *nu, struct BPoint *bp, float r_normal[3])
+{
+ BPoint *bp_prev = BKE_nurb_bpoint_get_prev(nu, bp);
+ BPoint *bp_next = BKE_nurb_bpoint_get_next(nu, bp);
+
+ zero_v3(r_normal);
+
+ if (bp_prev) {
+ float dir_prev[3];
+ sub_v3_v3v3(dir_prev, bp_prev->vec, bp->vec);
+ normalize_v3(dir_prev);
+ add_v3_v3(r_normal, dir_prev);
+ }
+ if (bp_next) {
+ float dir_next[3];
+ sub_v3_v3v3(dir_next, bp->vec, bp_next->vec);
+ normalize_v3(dir_next);
+ add_v3_v3(r_normal, dir_next);
+ }
+
+ normalize_v3(r_normal);
+}
+
/* ~~~~~~~~~~~~~~~~~~~~Non Uniform Rational B Spline calculations ~~~~~~~~~~~ */
@@ -1239,6 +1305,7 @@ void BKE_nurb_makeFaces(Nurb *nu, float *coord_array, int rowstride, int resolu,
void BKE_nurb_makeCurve(Nurb *nu, float *coord_array, float *tilt_array, float *radius_array, float *weight_array,
int resolu, int stride)
{
+ const float eps = 1e-6f;
BPoint *bp;
float u, ustart, uend, ustep, sumdiv;
float *basisu, *sum, *fp;
@@ -1297,7 +1364,7 @@ void BKE_nurb_makeCurve(Nurb *nu, float *coord_array, float *tilt_array, float *
*fp = basisu[i] * bp->vec[3];
sumdiv += *fp;
}
- if ((sumdiv != 0.0f) && (sumdiv < 0.999f || sumdiv > 1.001f)) {
+ if ((sumdiv != 0.0f) && (sumdiv < 1.0f - eps || sumdiv > 1.0f + eps)) {
/* is normalizing needed? */
fp = sum;
for (i = istart; i <= iend; i++, fp++) {
@@ -1375,6 +1442,30 @@ void BKE_curve_forward_diff_bezier(float q0, float q1, float q2, float q3, float
}
}
+/* forward differencing method for first derivative of cubic bezier curve */
+void BKE_curve_forward_diff_tangent_bezier(float q0, float q1, float q2, float q3, float *p, int it, int stride)
+{
+ float rt0, rt1, rt2, f;
+ int a;
+
+ f = 1.0f / (float)it;
+
+ rt0 = 3.0f * (q1 - q0);
+ rt1 = f * (3.0f * (q3 - q0) + 9.0f * (q1 - q2));
+ rt2 = 6.0f * (q0 + q2) - 12.0f * q1;
+
+ q0 = rt0;
+ q1 = f * (rt1 + rt2);
+ q2 = 2.0f * f * rt1;
+
+ for (a = 0; a <= it; a++) {
+ *p = q0;
+ p = (float *)(((char *)p) + stride);
+ q0 += q1;
+ q1 += q2;
+ }
+}
+
static void forward_diff_bezier_cotangent(const float p0[3], const float p1[3], const float p2[3], const float p3[3],
float p[3], int it, int stride)
{
@@ -1734,7 +1825,7 @@ void BKE_curve_bevel_make(Scene *scene, Object *ob, ListBase *disp,
/* half a circle */
fp = dl->verts;
- dangle = (0.5 * M_PI / (dnr - 1));
+ dangle = ((float)M_PI_2 / (dnr - 1));
angle = -(nr - 1) * dangle;
for (a = 0; a < nr; a++) {
@@ -1793,7 +1884,7 @@ void BKE_curve_bevel_make(Scene *scene, Object *ob, ListBase *disp,
/* half a circle */
fp = dl->verts;
angle = 0.0;
- dangle = (0.5 * M_PI / (dnr - 1));
+ dangle = ((float)M_PI_2 / (dnr - 1));
for (a = 0; a < nr; a++) {
fp[0] = 0.0;
@@ -1935,7 +2026,7 @@ static void calc_bevel_sin_cos(float x1, float y1, float x2, float y2,
t02 = x1 * x2 + y1 * y2;
if (fabsf(t02) >= 1.0f)
- t02 = 0.5 * M_PI;
+ t02 = M_PI_2;
else
t02 = (saacos(t02)) / 2.0f;
@@ -2468,7 +2559,7 @@ static void make_bevel_list_2D(BevList *bl)
/* first */
bevp = bl->bevpoints;
- angle = atan2f(bevp->dir[0], bevp->dir[1]) - (float)(M_PI / 2.0f);
+ angle = atan2f(bevp->dir[0], bevp->dir[1]) - (float)M_PI_2;
bevp->sina = sinf(angle);
bevp->cosa = cosf(angle);
vec_to_quat(bevp->quat, bevp->dir, 5, 1);
@@ -2476,7 +2567,7 @@ static void make_bevel_list_2D(BevList *bl)
/* last */
bevp = bl->bevpoints;
bevp += (bl->nr - 1);
- angle = atan2f(bevp->dir[0], bevp->dir[1]) - (float)(M_PI / 2.0f);
+ angle = atan2f(bevp->dir[0], bevp->dir[1]) - (float)M_PI_2;
bevp->sina = sinf(angle);
bevp->cosa = cosf(angle);
vec_to_quat(bevp->quat, bevp->dir, 5, 1);
@@ -2513,7 +2604,8 @@ void BKE_curve_bevelList_free(ListBase *bev)
}
MEM_freeN(bl);
}
- bev->first = bev->last = NULL;
+
+ BLI_listbase_clear(bev);
}
void BKE_curve_bevelList_make(Object *ob, ListBase *nurbs, bool for_render)
@@ -2534,7 +2626,7 @@ void BKE_curve_bevelList_make(Object *ob, ListBase *nurbs, bool for_render)
BevPoint *bevp, *bevp2, *bevp1 = NULL, *bevp0;
const float treshold = 0.00001f;
float min, inp;
- float *seglen;
+ float *seglen = NULL;
struct BevelSort *sortdata, *sd, *sd1;
int a, b, nr, poly, resolu = 0, len = 0, segcount;
int *segbevcount;
@@ -2590,7 +2682,7 @@ void BKE_curve_bevelList_make(Object *ob, ListBase *nurbs, bool for_render)
if (nu->type == CU_POLY) {
len = nu->pntsu;
bl = MEM_callocN(sizeof(BevList) + len * sizeof(BevPoint), "makeBevelList2");
- if (need_seglen) {
+ if (need_seglen && (nu->flagu & CU_NURB_CYCLIC) == 0) {
bl->seglen = MEM_mallocN(segcount * sizeof(float), "makeBevelList2_seglen");
bl->segbevcount = MEM_mallocN(segcount * sizeof(int), "makeBevelList2_segbevcount");
}
@@ -2613,7 +2705,7 @@ void BKE_curve_bevelList_make(Object *ob, ListBase *nurbs, bool for_render)
bevp->weight = bp->weight;
bevp->split_tag = true;
bp++;
- if (seglen != NULL) {
+ if (seglen != NULL && len != 0) {
*seglen = len_v3v3(bevp->vec, bp->vec);
bevp++;
bevp->offset = *seglen;
@@ -2629,11 +2721,6 @@ void BKE_curve_bevelList_make(Object *ob, ListBase *nurbs, bool for_render)
if ((nu->flagu & CU_NURB_CYCLIC) == 0) {
bevlist_firstlast_direction_calc_from_bpoint(nu, bl);
- if (seglen != NULL) {
- *seglen = len_v3v3(bevp->vec, nu->bp->vec);
- bl->bevpoints->offset = *seglen;
- *segbevcount = 1;
- }
}
}
else if (nu->type == CU_BEZIER) {
@@ -2641,7 +2728,7 @@ void BKE_curve_bevelList_make(Object *ob, ListBase *nurbs, bool for_render)
len = segcount * resolu + 1;
bl = MEM_callocN(sizeof(BevList) + len * sizeof(BevPoint), "makeBevelBPoints");
- if (need_seglen) {
+ if (need_seglen && (nu->flagu & CU_NURB_CYCLIC) == 0) {
bl->seglen = MEM_mallocN(segcount * sizeof(float), "makeBevelBPoints_seglen");
bl->segbevcount = MEM_mallocN(segcount * sizeof(int), "makeBevelBPoints_segbevcount");
}
@@ -2777,7 +2864,7 @@ void BKE_curve_bevelList_make(Object *ob, ListBase *nurbs, bool for_render)
len = (resolu * segcount);
bl = MEM_callocN(sizeof(BevList) + len * sizeof(BevPoint), "makeBevelList3");
- if (need_seglen) {
+ if (need_seglen && (nu->flagu & CU_NURB_CYCLIC) == 0) {
bl->seglen = MEM_mallocN(segcount * sizeof(float), "makeBevelList3_seglen");
bl->segbevcount = MEM_mallocN(segcount * sizeof(int), "makeBevelList3_segbevcount");
}
@@ -3029,8 +3116,8 @@ static void calchandleNurb_intern(BezTriple *bezt, BezTriple *prev, BezTriple *n
bool is_fcurve, bool skip_align)
{
/* defines to avoid confusion */
-#define p2_h1 (p2 - 3)
-#define p2_h2 (p2 + 3)
+#define p2_h1 ((p2) - 3)
+#define p2_h2 ((p2) + 3)
float *p1, *p2, *p3, pt[3];
float dvec_a[3], dvec_b[3];
@@ -3348,6 +3435,21 @@ void BKE_nurb_handle_calc_simple(Nurb *nu, BezTriple *bezt)
}
}
+void BKE_nurb_handle_calc_simple_auto(Nurb *nu, BezTriple *bezt)
+{
+ if (nu->pntsu > 1) {
+ const char h1_back = bezt->h1, h2_back = bezt->h2;
+
+ bezt->h1 = bezt->h2 = HD_AUTO;
+
+ /* Override handle types to HD_AUTO and recalculate */
+ BKE_nurb_handle_calc_simple(nu, bezt);
+
+ bezt->h1 = h1_back;
+ bezt->h2 = h2_back;
+ }
+}
+
/**
* Use when something has changed handle positions.
*
@@ -3605,24 +3707,12 @@ void BKE_nurbList_handles_recalculate(ListBase *editnurb, const bool calc_length
if (h1_select || h2_select) {
- /* Override handle types to HD_AUTO and recalculate */
-
- char h1_back, h2_back;
float co1_back[3], co2_back[3];
- h1_back = bezt->h1;
- h2_back = bezt->h2;
-
- bezt->h1 = HD_AUTO;
- bezt->h2 = HD_AUTO;
-
copy_v3_v3(co1_back, bezt->vec[0]);
copy_v3_v3(co2_back, bezt->vec[2]);
- BKE_nurb_handle_calc_simple(nu, bezt);
-
- bezt->h1 = h1_back;
- bezt->h2 = h2_back;
+ BKE_nurb_handle_calc_simple_auto(nu, bezt);
if (h1_select) {
if (!calc_length) {
@@ -4149,7 +4239,7 @@ ListBase *BKE_curve_nurbs_get(Curve *cu)
return &cu->nurb;
}
-void BKE_curve_nurb_active_set(Curve *cu, Nurb *nu)
+void BKE_curve_nurb_active_set(Curve *cu, const Nurb *nu)
{
if (nu == NULL) {
cu->actnu = CU_ACT_NONE;
@@ -4176,21 +4266,26 @@ void *BKE_curve_vert_active_get(Curve *cu)
return vert;
}
+int BKE_curve_nurb_vert_index_get(const Nurb *nu, const void *vert)
+{
+ if (nu->type == CU_BEZIER) {
+ BLI_assert(ARRAY_HAS_ITEM((BezTriple *)vert, nu->bezt, nu->pntsu));
+ return (BezTriple *)vert - nu->bezt;
+ }
+ else {
+ BLI_assert(ARRAY_HAS_ITEM((BPoint *)vert, nu->bp, nu->pntsu * nu->pntsv));
+ return (BPoint *)vert - nu->bp;
+ }
+}
+
/* Set active nurb and active vert for curve */
-void BKE_curve_nurb_vert_active_set(Curve *cu, Nurb *nu, void *vert)
+void BKE_curve_nurb_vert_active_set(Curve *cu, const Nurb *nu, const void *vert)
{
if (nu) {
BKE_curve_nurb_active_set(cu, nu);
if (vert) {
- if (nu->type == CU_BEZIER) {
- BLI_assert(ARRAY_HAS_ITEM((BezTriple *)vert, nu->bezt, nu->pntsu));
- cu->actvert = (BezTriple *)vert - nu->bezt;
- }
- else {
- BLI_assert(ARRAY_HAS_ITEM((BPoint *)vert, nu->bp, nu->pntsu * nu->pntsv));
- cu->actvert = (BPoint *)vert - nu->bp;
- }
+ cu->actvert = BKE_curve_nurb_vert_index_get(nu, vert);
}
else {
cu->actvert = CU_ACT_NONE;
@@ -4242,12 +4337,14 @@ void BKE_curve_nurb_vert_active_validate(Curve *cu)
if (BKE_curve_nurb_vert_active_get(cu, &nu, &vert)) {
if (nu->type == CU_BEZIER) {
- if ((((BezTriple *)vert)->f1 & SELECT) == 0) {
+ BezTriple *bezt = vert;
+ if (BEZT_ISSEL_ANY(bezt) == 0) {
cu->actvert = CU_ACT_NONE;
}
}
else {
- if ((((BPoint *)vert)->f1 & SELECT) == 0) {
+ BPoint *bp = vert;
+ if ((bp->f1 & SELECT) == 0) {
cu->actvert = CU_ACT_NONE;
}
}
@@ -4317,7 +4414,7 @@ bool BKE_curve_center_bounds(Curve *cu, float cent[3])
}
-void BKE_curve_transform_ex(Curve *cu, float mat[4][4], bool do_keys, float unit_scale)
+void BKE_curve_transform_ex(Curve *cu, float mat[4][4], const bool do_keys, const float unit_scale)
{
Nurb *nu;
BPoint *bp;
@@ -4337,8 +4434,10 @@ void BKE_curve_transform_ex(Curve *cu, float mat[4][4], bool do_keys, float unit
}
else {
i = nu->pntsu * nu->pntsv;
- for (bp = nu->bp; i--; bp++)
+ for (bp = nu->bp; i--; bp++) {
mul_m4_v3(mat, bp->vec);
+ bp->radius *= unit_scale;
+ }
}
}
@@ -4353,13 +4452,13 @@ void BKE_curve_transform_ex(Curve *cu, float mat[4][4], bool do_keys, float unit
}
}
-void BKE_curve_transform(Curve *cu, float mat[4][4], bool do_keys)
+void BKE_curve_transform(Curve *cu, float mat[4][4], const bool do_keys)
{
float unit_scale = mat4_to_scale(mat);
BKE_curve_transform_ex(cu, mat, do_keys, unit_scale);
}
-void BKE_curve_translate(Curve *cu, float offset[3], bool do_keys)
+void BKE_curve_translate(Curve *cu, float offset[3], const bool do_keys)
{
ListBase *nurb_lb = BKE_curve_nurbs_get(cu);
Nurb *nu;
@@ -4415,9 +4514,6 @@ void BKE_curve_material_index_remove(Curve *cu, int index)
for (nu = cu->nurb.first; nu; nu = nu->next) {
if (nu->mat_nr && nu->mat_nr >= index) {
nu->mat_nr--;
- if (curvetype == OB_CURVE) {
- nu->charidx--;
- }
}
}
}
@@ -4439,9 +4535,6 @@ void BKE_curve_material_index_clear(Curve *cu)
for (nu = cu->nurb.first; nu; nu = nu->next) {
nu->mat_nr = 0;
- if (curvetype == OB_CURVE) {
- nu->charidx = 0;
- }
}
}
}
@@ -4468,9 +4561,6 @@ int BKE_curve_material_index_validate(Curve *cu)
for (nu = cu->nurb.first; nu; nu = nu->next) {
if (nu->mat_nr > max_idx) {
nu->mat_nr = 0;
- if (curvetype == OB_CURVE) {
- nu->charidx = 0;
- }
is_valid = false;
}
}
@@ -4485,6 +4575,54 @@ int BKE_curve_material_index_validate(Curve *cu)
}
}
+void BKE_curve_material_remap(Curve *cu, const unsigned int *remap, unsigned int remap_len)
+{
+ const int curvetype = BKE_curve_type_get(cu);
+ const short remap_len_short = (short)remap_len;
+
+#define MAT_NR_REMAP(n) \
+ if (n < remap_len_short) { \
+ BLI_assert(n >= 0 && remap[n] < remap_len_short); \
+ n = remap[n]; \
+ } ((void)0)
+
+ if (curvetype == OB_FONT) {
+ struct CharInfo *strinfo;
+ int charinfo_len, i;
+
+ if (cu->editfont) {
+ EditFont *ef = cu->editfont;
+ strinfo = ef->textbufinfo;
+ charinfo_len = ef->len;
+ }
+ else {
+ strinfo = cu->strinfo;
+ charinfo_len = cu->len_wchar;
+ }
+
+ for (i = 0; i <= charinfo_len; i++) {
+ if (strinfo[i].mat_nr > 0) {
+ strinfo[i].mat_nr -= 1;
+ MAT_NR_REMAP(strinfo[i].mat_nr);
+ strinfo[i].mat_nr += 1;
+ }
+ }
+ }
+ else {
+ Nurb *nu;
+ ListBase *nurbs = BKE_curve_editNurbs_get(cu);
+
+ if (nurbs) {
+ for (nu = nurbs->first; nu; nu = nu->next) {
+ MAT_NR_REMAP(nu->mat_nr);
+ }
+ }
+ }
+
+#undef MAT_NR_REMAP
+
+}
+
void BKE_curve_rect_from_textbox(const struct Curve *cu, const struct TextBox *tb, struct rctf *r_rect)
{
r_rect->xmin = cu->xof + tb->x;
@@ -4493,3 +4631,27 @@ void BKE_curve_rect_from_textbox(const struct Curve *cu, const struct TextBox *t
r_rect->xmax = r_rect->xmin + tb->w;
r_rect->ymin = r_rect->ymax - tb->h;
}
+
+/* **** Depsgraph evaluation **** */
+
+void BKE_curve_eval_geometry(EvaluationContext *UNUSED(eval_ctx),
+ Curve *curve)
+{
+ if (G.debug & G_DEBUG_DEPSGRAPH) {
+ printf("%s on %s\n", __func__, curve->id.name);
+ }
+ if (curve->bb == NULL || (curve->bb->flag & BOUNDBOX_DIRTY)) {
+ BKE_curve_texspace_calc(curve);
+ }
+}
+
+void BKE_curve_eval_path(EvaluationContext *UNUSED(eval_ctx),
+ Curve *curve)
+{
+ /* TODO(sergey): This will probably need to be a part of
+ * the modifier stack still.
+ */
+ if (G.debug & G_DEBUG_DEPSGRAPH) {
+ printf("%s on %s\n", __func__, curve->id.name);
+ }
+}
diff --git a/source/blender/blenkernel/intern/customdata.c b/source/blender/blenkernel/intern/customdata.c
index 63eb3b397b0..815c18b9e70 100644
--- a/source/blender/blenkernel/intern/customdata.c
+++ b/source/blender/blenkernel/intern/customdata.c
@@ -48,14 +48,17 @@
#include "BLI_string.h"
#include "BLI_path_util.h"
#include "BLI_math.h"
+#include "BLI_math_color_blend.h"
#include "BLI_mempool.h"
-#include "BLF_translation.h"
+#include "BLT_translation.h"
#include "BKE_customdata.h"
#include "BKE_customdata_file.h"
#include "BKE_global.h"
#include "BKE_main.h"
+#include "BKE_mesh_mapping.h"
+#include "BKE_mesh_remap.h"
#include "BKE_multires.h"
#include "bmesh.h"
@@ -92,7 +95,7 @@ typedef struct LayerTypeInfo {
* (deep copy if appropriate)
* if NULL, memcpy is used
*/
- void (*copy)(const void *source, void *dest, int count);
+ cd_copy copy;
/**
* a function to free any dynamically allocated components of this
@@ -117,8 +120,7 @@ typedef struct LayerTypeInfo {
* applying changes while reading from sources.
* See bug [#32395] - Campbell.
*/
- void (*interp)(void **sources, const float *weights, const float *sub_weights,
- int count, void *dest);
+ cd_interp interp;
/** a function to swap the data in corners of the element */
void (*swap)(void *data, const int *corner_indices);
@@ -134,7 +136,7 @@ typedef struct LayerTypeInfo {
void (*initminmax)(void *min, void *max);
void (*add)(void *data1, const void *data2);
void (*dominmax)(const void *data1, void *min, void *max);
- void (*copyvalue)(const void *source, void *dest);
+ void (*copyvalue)(const void *source, void *dest, const int mixmode, const float mixfactor);
/** a function to read data from a cdf file */
int (*read)(CDataFile *cdf, void *data, int count);
@@ -144,6 +146,9 @@ typedef struct LayerTypeInfo {
/** a function to determine file size */
size_t (*filesize)(CDataFile *cdf, const void *data, int count);
+
+ /** a function to determine max allowed number of layers, should be NULL or return -1 if no limit */
+ int (*layers_max)(void);
} LayerTypeInfo;
static void layerCopy_mdeformvert(const void *source, void *dest,
@@ -154,7 +159,7 @@ static void layerCopy_mdeformvert(const void *source, void *dest,
memcpy(dest, source, count * size);
for (i = 0; i < count; ++i) {
- MDeformVert *dvert = (MDeformVert *)((char *)dest + i * size);
+ MDeformVert *dvert = POINTER_OFFSET(dest, i * size);
if (dvert->totweight) {
MDeformWeight *dw = MEM_mallocN(dvert->totweight * sizeof(*dw),
@@ -173,7 +178,7 @@ static void layerFree_mdeformvert(void *data, int count, int size)
int i;
for (i = 0; i < count; ++i) {
- MDeformVert *dvert = (MDeformVert *)((char *)data + i * size);
+ MDeformVert *dvert = POINTER_OFFSET(data, i * size);
if (dvert->dw) {
MEM_freeN(dvert->dw);
@@ -190,7 +195,7 @@ static void layerCopy_bmesh_elem_py_ptr(const void *UNUSED(source), void *dest,
int i, size = sizeof(void *);
for (i = 0; i < count; ++i) {
- void **ptr = (void **)((char *)dest + i * size);
+ void **ptr = POINTER_OFFSET(dest, i * size);
*ptr = NULL;
}
}
@@ -207,15 +212,16 @@ static void layerFree_bmesh_elem_py_ptr(void *data, int count, int size)
int i;
for (i = 0; i < count; ++i) {
- void **ptr = (void *)((char *)data + i * size);
+ void **ptr = POINTER_OFFSET(data, i * size);
if (*ptr) {
bpy_bm_generic_invalidate(*ptr);
}
}
}
-static void layerInterp_mdeformvert(void **sources, const float *weights,
- const float *UNUSED(sub_weights), int count, void *dest)
+static void layerInterp_mdeformvert(
+ const void **sources, const float *weights,
+ const float *UNUSED(sub_weights), int count, void *dest)
{
/* a single linked list of MDeformWeight's
* use this to avoid double allocs (which LinkNode would do) */
@@ -234,7 +240,7 @@ static void layerInterp_mdeformvert(void **sources, const float *weights,
/* build a list of unique def_nrs for dest */
totweight = 0;
for (i = 0; i < count; ++i) {
- MDeformVert *source = sources[i];
+ const MDeformVert *source = sources[i];
float interp_weight = weights ? weights[i] : 1.0f;
for (j = 0; j < source->totweight; ++j) {
@@ -295,6 +301,50 @@ static void layerInterp_mdeformvert(void **sources, const float *weights,
}
}
+static void layerInterp_normal(
+ const void **sources, const float *weights,
+ const float *UNUSED(sub_weights), int count, void *dest)
+{
+ float no[3] = {0.0f};
+
+ while (count--) {
+ madd_v3_v3fl(no, (const float *)sources[count], weights[count]);
+ }
+
+ copy_v3_v3((float *)dest, no);
+}
+
+static void layerCopyValue_normal(const void *source, void *dest, const int mixmode, const float mixfactor)
+{
+ const float *no_src = source;
+ float *no_dst = dest;
+ float no_tmp[3];
+
+ if (ELEM(mixmode, CDT_MIX_NOMIX, CDT_MIX_REPLACE_ABOVE_THRESHOLD, CDT_MIX_REPLACE_BELOW_THRESHOLD)) {
+ /* Above/below threshold modes are not supported here, fallback to nomix (just in case). */
+ copy_v3_v3(no_dst, no_src);
+ }
+ else { /* Modes that support 'real' mix factor. */
+ /* Since we normalize in the end, MIX and ADD are the same op here. */
+ if (ELEM(mixmode, CDT_MIX_MIX, CDT_MIX_ADD)) {
+ add_v3_v3v3(no_tmp, no_dst, no_src);
+ normalize_v3(no_tmp);
+ }
+ else if (mixmode == CDT_MIX_SUB) {
+ sub_v3_v3v3(no_tmp, no_dst, no_src);
+ normalize_v3(no_tmp);
+ }
+ else if (mixmode == CDT_MIX_MUL) {
+ mul_v3_v3v3(no_tmp, no_dst, no_src);
+ normalize_v3(no_tmp);
+ }
+ else {
+ copy_v3_v3(no_tmp, no_src);
+ }
+ interp_v3_v3v3_slerp_safe(no_dst, no_dst, no_tmp, mixfactor);
+ }
+}
+
static void layerCopy_tface(const void *source, void *dest, int count)
{
const MTFace *source_tf = (const MTFace *)source;
@@ -305,8 +355,9 @@ static void layerCopy_tface(const void *source, void *dest, int count)
dest_tf[i] = source_tf[i];
}
-static void layerInterp_tface(void **sources, const float *weights,
- const float *sub_weights, int count, void *dest)
+static void layerInterp_tface(
+ const void **sources, const float *weights,
+ const float *sub_weights, int count, void *dest)
{
MTFace *tf = dest;
int i, j, k;
@@ -318,7 +369,7 @@ static void layerInterp_tface(void **sources, const float *weights,
sub_weight = sub_weights;
for (i = 0; i < count; ++i) {
float weight = weights ? weights[i] : 1;
- MTFace *src = sources[i];
+ const MTFace *src = sources[i];
for (j = 0; j < 4; ++j) {
if (sub_weights) {
@@ -379,6 +430,11 @@ static void layerDefault_tface(void *data, int count)
tf[i] = default_tf;
}
+static int layerMaxNum_tface(void)
+{
+ return MAX_MTFACE;
+}
+
static void layerCopy_propFloat(const void *source, void *dest,
int count)
{
@@ -407,8 +463,9 @@ static void layerCopy_origspace_face(const void *source, void *dest, int count)
dest_tf[i] = source_tf[i];
}
-static void layerInterp_origspace_face(void **sources, const float *weights,
- const float *sub_weights, int count, void *dest)
+static void layerInterp_origspace_face(
+ const void **sources, const float *weights,
+ const float *sub_weights, int count, void *dest)
{
OrigSpaceFace *osf = dest;
int i, j, k;
@@ -420,7 +477,7 @@ static void layerInterp_origspace_face(void **sources, const float *weights,
sub_weight = sub_weights;
for (i = 0; i < count; ++i) {
float weight = weights ? weights[i] : 1;
- OrigSpaceFace *src = sources[i];
+ const OrigSpaceFace *src = sources[i];
for (j = 0; j < 4; ++j) {
if (sub_weights) {
@@ -612,14 +669,53 @@ static void layerFree_grid_paint_mask(void *data, int count, int UNUSED(size))
}
/* --------- */
-static void layerCopyValue_mloopcol(const void *source, void *dest)
+static void layerCopyValue_mloopcol(const void *source, void *dest, const int mixmode, const float mixfactor)
{
const MLoopCol *m1 = source;
MLoopCol *m2 = dest;
-
- m2->r = m1->r;
- m2->g = m1->g;
- m2->b = m1->b;
+ unsigned char tmp_col[4];
+
+ if (ELEM(mixmode, CDT_MIX_NOMIX, CDT_MIX_REPLACE_ABOVE_THRESHOLD, CDT_MIX_REPLACE_BELOW_THRESHOLD)) {
+ /* Modes that do a full copy or nothing. */
+ if (ELEM(mixmode, CDT_MIX_REPLACE_ABOVE_THRESHOLD, CDT_MIX_REPLACE_BELOW_THRESHOLD)) {
+ /* TODO: Check for a real valid way to get 'factor' value of our dest color? */
+ const float f = ((float)m2->r + (float)m2->g + (float)m2->b) / 3.0f;
+ if (mixmode == CDT_MIX_REPLACE_ABOVE_THRESHOLD && f < mixfactor) {
+ return; /* Do Nothing! */
+ }
+ else if (mixmode == CDT_MIX_REPLACE_BELOW_THRESHOLD && f > mixfactor) {
+ return; /* Do Nothing! */
+ }
+ }
+ m2->r = m1->r;
+ m2->g = m1->g;
+ m2->b = m1->b;
+ }
+ else { /* Modes that support 'real' mix factor. */
+ unsigned char src[4] = {m1->r, m1->g, m1->b, m1->a};
+ unsigned char dst[4] = {m2->r, m2->g, m2->b, m2->a};
+
+ if (mixmode == CDT_MIX_MIX) {
+ blend_color_mix_byte(tmp_col, dst, src);
+ }
+ else if (mixmode == CDT_MIX_ADD) {
+ blend_color_add_byte(tmp_col, dst, src);
+ }
+ else if (mixmode == CDT_MIX_SUB) {
+ blend_color_sub_byte(tmp_col, dst, src);
+ }
+ else if (mixmode == CDT_MIX_MUL) {
+ blend_color_mul_byte(tmp_col, dst, src);
+ }
+ else {
+ memcpy(tmp_col, src, sizeof(tmp_col));
+ }
+ blend_color_interpolate_byte(dst, dst, tmp_col, mixfactor);
+
+ m2->r = (char)dst[0];
+ m2->g = (char)dst[1];
+ m2->b = (char)dst[2];
+ }
m2->a = m1->a;
}
@@ -698,8 +794,9 @@ static void layerDefault_mloopcol(void *data, int count)
}
-static void layerInterp_mloopcol(void **sources, const float *weights,
- const float *sub_weights, int count, void *dest)
+static void layerInterp_mloopcol(
+ const void **sources, const float *weights,
+ const float *sub_weights, int count, void *dest)
{
MLoopCol *mc = dest;
int i;
@@ -715,7 +812,7 @@ static void layerInterp_mloopcol(void **sources, const float *weights,
sub_weight = sub_weights;
for (i = 0; i < count; ++i) {
float weight = weights ? weights[i] : 1;
- MLoopCol *src = sources[i];
+ const MLoopCol *src = sources[i];
if (sub_weights) {
col.r += src->r * (*sub_weight) * weight;
col.g += src->g * (*sub_weight) * weight;
@@ -745,12 +842,24 @@ static void layerInterp_mloopcol(void **sources, const float *weights,
mc->a = (int)col.a;
}
-static void layerCopyValue_mloopuv(const void *source, void *dest)
+static int layerMaxNum_mloopcol(void)
+{
+ return MAX_MCOL;
+}
+
+static void layerCopyValue_mloopuv(const void *source, void *dest, const int mixmode, const float mixfactor)
{
const MLoopUV *luv1 = source;
MLoopUV *luv2 = dest;
- copy_v2_v2(luv2->uv, luv1->uv);
+ /* We only support a limited subset of advanced mixing here - namely the mixfactor interpolation. */
+
+ if (mixmode == CDT_MIX_NOMIX) {
+ copy_v2_v2(luv2->uv, luv1->uv);
+ }
+ else {
+ interp_v2_v2v2(luv2->uv, luv2->uv, luv1->uv, mixfactor);
+ }
}
static bool layerEqual_mloopuv(const void *data1, const void *data2)
@@ -790,8 +899,9 @@ static void layerAdd_mloopuv(void *data1, const void *data2)
add_v2_v2(l1->uv, l2->uv);
}
-static void layerInterp_mloopuv(void **sources, const float *weights,
- const float *sub_weights, int count, void *dest)
+static void layerInterp_mloopuv(
+ const void **sources, const float *weights,
+ const float *sub_weights, int count, void *dest)
{
float uv[2];
int i;
@@ -802,7 +912,7 @@ static void layerInterp_mloopuv(void **sources, const float *weights,
const float *sub_weight = sub_weights;
for (i = 0; i < count; i++) {
float weight = weights ? weights[i] : 1.0f;
- MLoopUV *src = sources[i];
+ const MLoopUV *src = sources[i];
madd_v2_v2fl(uv, src->uv, (*sub_weight) * weight);
sub_weight++;
}
@@ -810,7 +920,7 @@ static void layerInterp_mloopuv(void **sources, const float *weights,
else {
for (i = 0; i < count; i++) {
float weight = weights ? weights[i] : 1;
- MLoopUV *src = sources[i];
+ const MLoopUV *src = sources[i];
madd_v2_v2fl(uv, src->uv, weight);
}
}
@@ -820,7 +930,8 @@ static void layerInterp_mloopuv(void **sources, const float *weights,
}
/* origspace is almost exact copy of mloopuv's, keep in sync */
-static void layerCopyValue_mloop_origspace(const void *source, void *dest)
+static void layerCopyValue_mloop_origspace(const void *source, void *dest,
+ const int UNUSED(mixmode), const float UNUSED(mixfactor))
{
const OrigSpaceLoop *luv1 = source;
OrigSpaceLoop *luv2 = dest;
@@ -865,8 +976,9 @@ static void layerAdd_mloop_origspace(void *data1, const void *data2)
add_v2_v2(l1->uv, l2->uv);
}
-static void layerInterp_mloop_origspace(void **sources, const float *weights,
- const float *sub_weights, int count, void *dest)
+static void layerInterp_mloop_origspace(
+ const void **sources, const float *weights,
+ const float *sub_weights, int count, void *dest)
{
float uv[2];
int i;
@@ -877,7 +989,7 @@ static void layerInterp_mloop_origspace(void **sources, const float *weights,
const float *sub_weight = sub_weights;
for (i = 0; i < count; i++) {
float weight = weights ? weights[i] : 1.0f;
- OrigSpaceLoop *src = sources[i];
+ const OrigSpaceLoop *src = sources[i];
madd_v2_v2fl(uv, src->uv, (*sub_weight) * weight);
sub_weight++;
}
@@ -885,7 +997,7 @@ static void layerInterp_mloop_origspace(void **sources, const float *weights,
else {
for (i = 0; i < count; i++) {
float weight = weights ? weights[i] : 1.0f;
- OrigSpaceLoop *src = sources[i];
+ const OrigSpaceLoop *src = sources[i];
madd_v2_v2fl(uv, src->uv, weight);
}
}
@@ -895,8 +1007,9 @@ static void layerInterp_mloop_origspace(void **sources, const float *weights,
}
/* --- end copy */
-static void layerInterp_mcol(void **sources, const float *weights,
- const float *sub_weights, int count, void *dest)
+static void layerInterp_mcol(
+ const void **sources, const float *weights,
+ const float *sub_weights, int count, void *dest)
{
MCol *mc = dest;
int i, j, k;
@@ -917,7 +1030,7 @@ static void layerInterp_mcol(void **sources, const float *weights,
for (j = 0; j < 4; ++j) {
if (sub_weights) {
- MCol *src = sources[i];
+ const MCol *src = sources[i];
for (k = 0; k < 4; ++k, ++sub_weight, ++src) {
const float w = (*sub_weight) * weight;
col[j].a += src->a * w;
@@ -927,7 +1040,7 @@ static void layerInterp_mcol(void **sources, const float *weights,
}
}
else {
- MCol *src = sources[i];
+ const MCol *src = sources[i];
col[j].a += src[j].a * weight;
col[j].r += src[j].r * weight;
col[j].g += src[j].g * weight;
@@ -978,11 +1091,12 @@ static void layerDefault_mcol(void *data, int count)
static void layerDefault_origindex(void *data, int count)
{
- fill_vn_i((int *)data, count, ORIGINDEX_NONE);
+ copy_vn_i((int *)data, count, ORIGINDEX_NONE);
}
-static void layerInterp_bweight(void **sources, const float *weights,
- const float *UNUSED(sub_weights), int count, void *dest)
+static void layerInterp_bweight(
+ const void **sources, const float *weights,
+ const float *UNUSED(sub_weights), int count, void *dest)
{
float f;
float **in = (float **)sources;
@@ -1007,8 +1121,9 @@ static void layerInterp_bweight(void **sources, const float *weights,
*((float *)dest) = f;
}
-static void layerInterp_shapekey(void **sources, const float *weights,
- const float *UNUSED(sub_weights), int count, void *dest)
+static void layerInterp_shapekey(
+ const void **sources, const float *weights,
+ const float *UNUSED(sub_weights), int count, void *dest)
{
float co[3];
float **in = (float **)sources;
@@ -1044,26 +1159,27 @@ static void layerDefault_mvert_skin(void *data, int count)
}
}
-static void layerInterp_mvert_skin(void **sources, const float *weights,
- const float *UNUSED(sub_weights),
- int count, void *dest)
+static void layerInterp_mvert_skin(
+ const void **sources, const float *weights,
+ const float *UNUSED(sub_weights),
+ int count, void *dest)
{
+ MVertSkin *vs_dst = dest;
float radius[3], w;
- MVertSkin *vs;
int i;
zero_v3(radius);
for (i = 0; i < count; i++) {
+ const MVertSkin *vs_src = sources[i];
w = weights ? weights[i] : 1.0f;
- vs = sources[i];
- madd_v3_v3fl(radius, vs->radius, w);
+ madd_v3_v3fl(radius, vs_src->radius, w);
}
/* delay writing to the destination incase dest is in sources */
- vs = dest;
- copy_v3_v3(vs->radius, radius);
- vs->flag &= ~MVERT_SKIN_ROOT;
+ vs_dst = dest;
+ copy_v3_v3(vs_dst->radius, radius);
+ vs_dst->flag &= ~MVERT_SKIN_ROOT;
}
static void layerSwap_flnor(void *data, const int *corner_indices)
@@ -1083,8 +1199,7 @@ static const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = {
/* 0: CD_MVERT */
{sizeof(MVert), "MVert", 1, NULL, NULL, NULL, NULL, NULL, NULL},
/* 1: CD_MSTICKY */ /* DEPRECATED */
- {sizeof(float) * 2, "", 1, NULL, NULL, NULL, NULL, NULL,
- NULL},
+ {sizeof(float) * 2, "", 1, NULL, NULL, NULL, NULL, NULL, NULL},
/* 2: CD_MDEFORMVERT */
{sizeof(MDeformVert), "MDeformVert", 1, NULL, layerCopy_mdeformvert,
layerFree_mdeformvert, layerInterp_mdeformvert, NULL, NULL},
@@ -1093,18 +1208,19 @@ static const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = {
/* 4: CD_MFACE */
{sizeof(MFace), "MFace", 1, NULL, NULL, NULL, NULL, NULL, NULL},
/* 5: CD_MTFACE */
- {sizeof(MTFace), "MTFace", 1, N_("UVMap"), layerCopy_tface, NULL,
- layerInterp_tface, layerSwap_tface, layerDefault_tface},
+ {sizeof(MTFace), "MTFace", 1, N_("UVMap"), layerCopy_tface, NULL, layerInterp_tface, layerSwap_tface,
+ layerDefault_tface, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, layerMaxNum_tface},
/* 6: CD_MCOL */
/* 4 MCol structs per face */
{sizeof(MCol) * 4, "MCol", 4, N_("Col"), NULL, NULL, layerInterp_mcol,
- layerSwap_mcol, layerDefault_mcol},
+ layerSwap_mcol, layerDefault_mcol, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, layerMaxNum_mloopcol},
/* 7: CD_ORIGINDEX */
{sizeof(int), "", 0, NULL, NULL, NULL, NULL, NULL, layerDefault_origindex},
/* 8: CD_NORMAL */
/* 3 floats per normal vector */
- {sizeof(float) * 3, "vec3f", 1, NULL, NULL, NULL, NULL, NULL, NULL},
- /* 9: CD_POLYINDEX (deprecated) */
+ {sizeof(float) * 3, "vec3f", 1, NULL, NULL, NULL, layerInterp_normal, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, layerCopyValue_normal},
+ /* 9: CD_POLYINDEX */ /* DEPRECATED */
{sizeof(int), "", 0, NULL, NULL, NULL, NULL, NULL, NULL},
/* 10: CD_PROP_FLT */
{sizeof(MFloatProperty), "MFloatProperty", 1, N_("Float"), layerCopy_propFloat, NULL, NULL, NULL},
@@ -1119,15 +1235,16 @@ static const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = {
{sizeof(float) * 3, "", 0, NULL, NULL, NULL, NULL, NULL, NULL},
/* 15: CD_MTEXPOLY */
/* note, when we expose the UV Map / TexFace split to the user, change this back to face Texture */
- {sizeof(MTexPoly), "MTexPoly", 1, N_("UVMap") /* "Face Texture" */, NULL, NULL, NULL, NULL, NULL},
+ {sizeof(MTexPoly), "MTexPoly", 1, N_("UVMap") /* "Face Texture" */, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, layerMaxNum_tface},
/* 16: CD_MLOOPUV */
{sizeof(MLoopUV), "MLoopUV", 1, N_("UVMap"), NULL, NULL, layerInterp_mloopuv, NULL, NULL,
layerEqual_mloopuv, layerMultiply_mloopuv, layerInitMinMax_mloopuv,
- layerAdd_mloopuv, layerDoMinMax_mloopuv, layerCopyValue_mloopuv},
+ layerAdd_mloopuv, layerDoMinMax_mloopuv, layerCopyValue_mloopuv, NULL, NULL, NULL, layerMaxNum_tface},
/* 17: CD_MLOOPCOL */
{sizeof(MLoopCol), "MLoopCol", 1, N_("Col"), NULL, NULL, layerInterp_mloopcol, NULL,
layerDefault_mloopcol, layerEqual_mloopcol, layerMultiply_mloopcol, layerInitMinMax_mloopcol,
- layerAdd_mloopcol, layerDoMinMax_mloopcol, layerCopyValue_mloopcol},
+ layerAdd_mloopcol, layerDoMinMax_mloopcol, layerCopyValue_mloopcol, NULL, NULL, NULL, layerMaxNum_mloopcol},
/* 18: CD_TANGENT */
{sizeof(float) * 4 * 4, "", 0, NULL, NULL, NULL, NULL, NULL, NULL},
/* 19: CD_MDISPS */
@@ -1138,9 +1255,8 @@ static const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = {
/* 20: CD_PREVIEW_MCOL */
{sizeof(MCol) * 4, "MCol", 4, N_("PreviewCol"), NULL, NULL, layerInterp_mcol,
layerSwap_mcol, layerDefault_mcol},
- /* 21: CD_ID_MCOL */
- {sizeof(MCol) * 4, "MCol", 4, N_("IDCol"), NULL, NULL, layerInterp_mcol,
- layerSwap_mcol, layerDefault_mcol},
+ /* 21: CD_ID_MCOL */ /* DEPRECATED */
+ {sizeof(MCol) * 4, "", 0, NULL, NULL, NULL, NULL, NULL, NULL},
/* 22: CD_TEXTURE_MCOL */
{sizeof(MCol) * 4, "MCol", 4, N_("TexturedCol"), NULL, NULL, layerInterp_mcol,
layerSwap_mcol, layerDefault_mcol},
@@ -1192,6 +1308,8 @@ static const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = {
{sizeof(float[4]), "", 0, NULL, NULL, NULL, NULL, NULL, NULL},
/* 40: CD_TESSLOOPNORMAL */
{sizeof(short[4][3]), "", 0, NULL, NULL, NULL, NULL, layerSwap_flnor, NULL},
+ /* 41: CD_CUSTOMLOOPNORMAL */
+ {sizeof(short[2]), "vec2s", 1, NULL, NULL, NULL, NULL, NULL, NULL},
};
/* note, numbers are from trunk and need updating for bmesh */
@@ -1207,43 +1325,54 @@ static const char *LAYERTYPENAMES[CD_NUMTYPES] = {
/* 25-29 */ "CDMPoly", "CDMLoop", "CDShapeKeyIndex", "CDShapeKey", "CDBevelWeight",
/* 30-34 */ "CDSubSurfCrease", "CDOrigSpaceLoop", "CDPreviewLoopCol", "CDBMElemPyPtr", "CDPaintMask",
/* 35-36 */ "CDGridPaintMask", "CDMVertSkin",
- /* 37-40 */ "CDFreestyleEdge", "CDFreestyleFace", "CDMLoopTangent", "CDTessLoopNormal",
+ /* 37-38 */ "CDFreestyleEdge", "CDFreestyleFace",
+ /* 39-41 */ "CDMLoopTangent", "CDTessLoopNormal", "CDCustomLoopNormal",
};
const CustomDataMask CD_MASK_BAREMESH =
- CD_MASK_MVERT | CD_MASK_MEDGE | CD_MASK_MFACE | CD_MASK_MLOOP | CD_MASK_MPOLY | CD_MASK_BWEIGHT;
+ CD_MASK_MVERT | CD_MASK_MEDGE | CD_MASK_MLOOP | CD_MASK_MPOLY | CD_MASK_BWEIGHT;
const CustomDataMask CD_MASK_MESH =
- CD_MASK_MVERT | CD_MASK_MEDGE | CD_MASK_MFACE |
- CD_MASK_MSTICKY | CD_MASK_MDEFORMVERT | CD_MASK_MTFACE | CD_MASK_MCOL |
+ CD_MASK_MVERT | CD_MASK_MEDGE |
+ CD_MASK_MDEFORMVERT |
CD_MASK_PROP_FLT | CD_MASK_PROP_INT | CD_MASK_PROP_STR | CD_MASK_MDISPS |
CD_MASK_MLOOPUV | CD_MASK_MLOOPCOL | CD_MASK_MPOLY | CD_MASK_MLOOP |
CD_MASK_MTEXPOLY | CD_MASK_RECAST | CD_MASK_PAINT_MASK |
- CD_MASK_GRID_PAINT_MASK | CD_MASK_MVERT_SKIN | CD_MASK_FREESTYLE_EDGE | CD_MASK_FREESTYLE_FACE;
+ CD_MASK_GRID_PAINT_MASK | CD_MASK_MVERT_SKIN | CD_MASK_FREESTYLE_EDGE | CD_MASK_FREESTYLE_FACE |
+ CD_MASK_CUSTOMLOOPNORMAL;
const CustomDataMask CD_MASK_EDITMESH =
- CD_MASK_MSTICKY | CD_MASK_MDEFORMVERT | CD_MASK_MTFACE | CD_MASK_MLOOPUV |
+ CD_MASK_MDEFORMVERT | CD_MASK_MLOOPUV |
CD_MASK_MLOOPCOL | CD_MASK_MTEXPOLY | CD_MASK_SHAPE_KEYINDEX |
- CD_MASK_MCOL | CD_MASK_PROP_FLT | CD_MASK_PROP_INT | CD_MASK_PROP_STR |
+ CD_MASK_PROP_FLT | CD_MASK_PROP_INT | CD_MASK_PROP_STR |
CD_MASK_MDISPS | CD_MASK_SHAPEKEY | CD_MASK_RECAST | CD_MASK_PAINT_MASK |
- CD_MASK_GRID_PAINT_MASK | CD_MASK_MVERT_SKIN;
+ CD_MASK_GRID_PAINT_MASK | CD_MASK_MVERT_SKIN | CD_MASK_CUSTOMLOOPNORMAL;
const CustomDataMask CD_MASK_DERIVEDMESH =
- CD_MASK_MSTICKY | CD_MASK_MDEFORMVERT | CD_MASK_MTFACE |
- CD_MASK_MCOL | CD_MASK_PROP_FLT | CD_MASK_PROP_INT | CD_MASK_CLOTH_ORCO |
+ CD_MASK_MDEFORMVERT |
+ CD_MASK_PROP_FLT | CD_MASK_PROP_INT | CD_MASK_CLOTH_ORCO |
CD_MASK_MLOOPUV | CD_MASK_MLOOPCOL | CD_MASK_MTEXPOLY | CD_MASK_PREVIEW_MLOOPCOL |
CD_MASK_PROP_STR | CD_MASK_ORIGSPACE | CD_MASK_ORIGSPACE_MLOOP | CD_MASK_ORCO | CD_MASK_TANGENT |
CD_MASK_PREVIEW_MCOL | CD_MASK_SHAPEKEY | CD_MASK_RECAST |
- CD_MASK_ORIGINDEX | CD_MASK_MVERT_SKIN | CD_MASK_FREESTYLE_EDGE | CD_MASK_FREESTYLE_FACE;
+ CD_MASK_ORIGINDEX | CD_MASK_MVERT_SKIN | CD_MASK_FREESTYLE_EDGE | CD_MASK_FREESTYLE_FACE |
+ CD_MASK_CUSTOMLOOPNORMAL;
const CustomDataMask CD_MASK_BMESH =
CD_MASK_MLOOPUV | CD_MASK_MLOOPCOL | CD_MASK_MTEXPOLY |
- CD_MASK_MSTICKY | CD_MASK_MDEFORMVERT | CD_MASK_PROP_FLT | CD_MASK_PROP_INT |
+ CD_MASK_MDEFORMVERT | CD_MASK_PROP_FLT | CD_MASK_PROP_INT |
CD_MASK_PROP_STR | CD_MASK_SHAPEKEY | CD_MASK_SHAPE_KEYINDEX | CD_MASK_MDISPS |
CD_MASK_CREASE | CD_MASK_BWEIGHT | CD_MASK_RECAST | CD_MASK_PAINT_MASK |
- CD_MASK_GRID_PAINT_MASK | CD_MASK_MVERT_SKIN | CD_MASK_FREESTYLE_EDGE | CD_MASK_FREESTYLE_FACE;
-const CustomDataMask CD_MASK_FACECORNERS = /* XXX Not used anywhere! */
- CD_MASK_MTFACE | CD_MASK_MCOL | CD_MASK_MTEXPOLY | CD_MASK_MLOOPUV |
- CD_MASK_MLOOPCOL | CD_MASK_NORMAL | CD_MASK_MLOOPTANGENT;
+ CD_MASK_GRID_PAINT_MASK | CD_MASK_MVERT_SKIN | CD_MASK_FREESTYLE_EDGE | CD_MASK_FREESTYLE_FACE |
+ CD_MASK_CUSTOMLOOPNORMAL;
+/**
+ * cover values copied by #BKE_mesh_loops_to_tessdata
+ */
+const CustomDataMask CD_MASK_FACECORNERS =
+ CD_MASK_MTFACE | CD_MASK_MTEXPOLY | CD_MASK_MLOOPUV |
+ CD_MASK_MCOL | CD_MASK_MLOOPCOL |
+ CD_MASK_PREVIEW_MCOL | CD_MASK_PREVIEW_MLOOPCOL |
+ CD_MASK_ORIGSPACE | CD_MASK_ORIGSPACE_MLOOP |
+ CD_MASK_TESSLOOPNORMAL | CD_MASK_NORMAL |
+ CD_MASK_TANGENT | CD_MASK_MLOOPTANGENT;
const CustomDataMask CD_MASK_EVERYTHING =
- CD_MASK_MVERT | CD_MASK_MSTICKY /* DEPRECATED */ | CD_MASK_MDEFORMVERT | CD_MASK_MEDGE | CD_MASK_MFACE |
+ CD_MASK_MVERT | CD_MASK_MDEFORMVERT | CD_MASK_MEDGE | CD_MASK_MFACE |
CD_MASK_MTFACE | CD_MASK_MCOL | CD_MASK_ORIGINDEX | CD_MASK_NORMAL /* | CD_MASK_POLYINDEX */ | CD_MASK_PROP_FLT |
CD_MASK_PROP_INT | CD_MASK_PROP_STR | CD_MASK_ORIGSPACE | CD_MASK_ORCO | CD_MASK_MTEXPOLY | CD_MASK_MLOOPUV |
CD_MASK_MLOOPCOL | CD_MASK_TANGENT | CD_MASK_MDISPS | CD_MASK_PREVIEW_MCOL | CD_MASK_CLOTH_ORCO | CD_MASK_RECAST |
@@ -1253,7 +1382,7 @@ const CustomDataMask CD_MASK_EVERYTHING =
/* BMESH ONLY END */
CD_MASK_PAINT_MASK | CD_MASK_GRID_PAINT_MASK | CD_MASK_MVERT_SKIN |
CD_MASK_FREESTYLE_EDGE | CD_MASK_FREESTYLE_FACE |
- CD_MASK_MLOOPTANGENT | CD_MASK_TESSLOOPNORMAL;
+ CD_MASK_MLOOPTANGENT | CD_MASK_TESSLOOPNORMAL | CD_MASK_CUSTOMLOOPNORMAL;
static const LayerTypeInfo *layerType_getInfo(int type)
{
@@ -1296,10 +1425,11 @@ void CustomData_update_typemap(CustomData *data)
}
for (i = 0; i < data->totlayer; i++) {
- if (data->layers[i].type != lasttype) {
- data->typemap[data->layers[i].type] = i;
+ const int type = data->layers[i].type;
+ if (type != lasttype) {
+ data->typemap[type] = i;
+ lasttype = type;
}
- lasttype = data->layers[i].type;
}
}
@@ -1319,7 +1449,8 @@ bool CustomData_merge(const struct CustomData *source, struct CustomData *dest,
/*const LayerTypeInfo *typeInfo;*/
CustomDataLayer *layer, *newlayer;
void *data;
- int i, type, number = 0, lasttype = -1, lastactive = 0, lastrender = 0, lastclone = 0, lastmask = 0, lastflag = 0;
+ int i, type, lasttype = -1, lastactive = 0, lastrender = 0, lastclone = 0, lastmask = 0, flag = 0;
+ int number = 0, maxnumber = -1;
bool changed = false;
for (i = 0; i < source->totlayer; ++i) {
@@ -1327,21 +1458,23 @@ bool CustomData_merge(const struct CustomData *source, struct CustomData *dest,
/*typeInfo = layerType_getInfo(layer->type);*/ /*UNUSED*/
type = layer->type;
+ flag = layer->flag;
if (type != lasttype) {
number = 0;
+ maxnumber = CustomData_layertype_layers_max(type);
lastactive = layer->active;
lastrender = layer->active_rnd;
lastclone = layer->active_clone;
lastmask = layer->active_mask;
lasttype = type;
- lastflag = layer->flag;
}
else
number++;
- if (lastflag & CD_FLAG_NOCOPY) continue;
+ if (flag & CD_FLAG_NOCOPY) continue;
else if (!(mask & CD_TYPE_AS_MASK(type))) continue;
+ else if ((maxnumber != -1) && (number >= maxnumber)) continue;
else if (CustomData_get_layer_named(dest, type, layer->name)) continue;
switch (alloctype) {
@@ -1355,12 +1488,12 @@ bool CustomData_merge(const struct CustomData *source, struct CustomData *dest,
break;
}
- if ((alloctype == CD_ASSIGN) && (lastflag & CD_FLAG_NOFREE))
- newlayer = customData_add_layer__internal(dest, type, CD_REFERENCE,
- data, totelem, layer->name);
- else
- newlayer = customData_add_layer__internal(dest, type, alloctype,
- data, totelem, layer->name);
+ if ((alloctype == CD_ASSIGN) && (flag & CD_FLAG_NOFREE)) {
+ newlayer = customData_add_layer__internal(dest, type, CD_REFERENCE, data, totelem, layer->name);
+ }
+ else {
+ newlayer = customData_add_layer__internal(dest, type, alloctype, data, totelem, layer->name);
+ }
if (newlayer) {
newlayer->uid = layer->uid;
@@ -1369,7 +1502,7 @@ bool CustomData_merge(const struct CustomData *source, struct CustomData *dest,
newlayer->active_rnd = lastrender;
newlayer->active_clone = lastclone;
newlayer->active_mask = lastmask;
- newlayer->flag |= lastflag & (CD_FLAG_EXTERNAL | CD_FLAG_IN_MEMORY);
+ newlayer->flag |= flag & (CD_FLAG_EXTERNAL | CD_FLAG_IN_MEMORY);
changed = true;
}
}
@@ -1378,6 +1511,23 @@ bool CustomData_merge(const struct CustomData *source, struct CustomData *dest,
return changed;
}
+/* NOTE: Take care of referenced layers by yourself! */
+void CustomData_realloc(CustomData *data, int totelem)
+{
+ int i;
+ for (i = 0; i < data->totlayer; ++i) {
+ CustomDataLayer *layer = &data->layers[i];
+ const LayerTypeInfo *typeInfo;
+ int size;
+ if (layer->flag & CD_FLAG_NOFREE) {
+ continue;
+ }
+ typeInfo = layerType_getInfo(layer->type);
+ size = totelem * typeInfo->size;
+ layer->data = MEM_reallocN(layer->data, size);
+ }
+}
+
void CustomData_copy(const struct CustomData *source, struct CustomData *dest,
CustomDataMask mask, int alloctype, int totelem)
{
@@ -1415,7 +1565,7 @@ static void CustomData_external_free(CustomData *data)
void CustomData_reset(CustomData *data)
{
memset(data, 0, sizeof(*data));
- fill_vn_i(data->typemap, CD_NUMTYPES, -1);
+ copy_vn_i(data->typemap, CD_NUMTYPES, -1);
}
void CustomData_free(CustomData *data, int totelem)
@@ -1432,6 +1582,25 @@ void CustomData_free(CustomData *data, int totelem)
CustomData_reset(data);
}
+void CustomData_free_typemask(struct CustomData *data, int totelem, CustomDataMask mask)
+{
+ int i;
+
+ for (i = 0; i < data->totlayer; ++i) {
+ CustomDataLayer *layer = &data->layers[i];
+ if (!(mask & CD_TYPE_AS_MASK(layer->type))) {
+ continue;
+ }
+ customData_free_layer__internal(layer, totelem);
+ }
+
+ if (data->layers)
+ MEM_freeN(data->layers);
+
+ CustomData_external_free(data);
+ CustomData_reset(data);
+}
+
static void customData_update_offsets(CustomData *data)
{
const LayerTypeInfo *typeInfo;
@@ -1487,7 +1656,7 @@ int CustomData_get_named_layer_index(const CustomData *data, int type, const cha
for (i = 0; i < data->totlayer; ++i)
if (data->layers[i].type == type)
- if (strcmp(data->layers[i].name, name) == 0)
+ if (STREQ(data->layers[i].name, name))
return i;
return -1;
@@ -1663,7 +1832,8 @@ static CustomDataLayer *customData_add_layer__internal(CustomData *data, int typ
int totelem, const char *name)
{
const LayerTypeInfo *typeInfo = layerType_getInfo(type);
- int size = typeInfo->size * totelem, flag = 0, index = data->totlayer;
+ const int size = totelem * typeInfo->size;
+ int flag = 0, index = data->totlayer;
void *newlayerdata = NULL;
/* Passing a layerdata to copy from with an alloctype that won't copy is
@@ -1682,7 +1852,13 @@ static CustomDataLayer *customData_add_layer__internal(CustomData *data, int typ
newlayerdata = layerdata;
}
else if (size > 0) {
- newlayerdata = MEM_callocN(size, layerType_getName(type));
+ if (alloctype == CD_DUPLICATE && layerdata) {
+ newlayerdata = MEM_mallocN(size, layerType_getName(type));
+ }
+ else {
+ newlayerdata = MEM_callocN(size, layerType_getName(type));
+ }
+
if (!newlayerdata)
return NULL;
}
@@ -1695,7 +1871,7 @@ static CustomDataLayer *customData_add_layer__internal(CustomData *data, int typ
}
else if (alloctype == CD_DEFAULT) {
if (typeInfo->set_default)
- typeInfo->set_default((char *)newlayerdata, totelem);
+ typeInfo->set_default(newlayerdata, totelem);
}
else if (alloctype == CD_REFERENCE)
flag |= CD_FLAG_NOFREE;
@@ -1781,7 +1957,8 @@ bool CustomData_free_layer(CustomData *data, int type, int totelem, int index)
const int n = index - CustomData_get_layer_index(data, type);
int i;
- if (index < 0) return 0;
+ if (index < 0)
+ return false;
customData_free_layer__internal(&data->layers[index], totelem);
@@ -1811,14 +1988,15 @@ bool CustomData_free_layer(CustomData *data, int type, int totelem, int index)
customData_update_offsets(data);
- return 1;
+ return true;
}
bool CustomData_free_layer_active(CustomData *data, int type, int totelem)
{
int index = 0;
index = CustomData_get_active_layer_index(data, type);
- if (index == -1) return 0;
+ if (index == -1)
+ return false;
return CustomData_free_layer(data, type, totelem, index);
}
@@ -1856,14 +2034,13 @@ int CustomData_number_of_layers_typemask(const CustomData *data, CustomDataMask
return number;
}
-void *CustomData_duplicate_referenced_layer(struct CustomData *data, const int type, const int totelem)
+static void *customData_duplicate_referenced_layer_index(CustomData *data, const int layer_index, const int totelem)
{
CustomDataLayer *layer;
- int layer_index;
- /* get the layer index of the first layer of type */
- layer_index = CustomData_get_active_layer_index(data, type);
- if (layer_index == -1) return NULL;
+ if (layer_index == -1) {
+ return NULL;
+ }
layer = &data->layers[layer_index];
@@ -1875,12 +2052,13 @@ void *CustomData_duplicate_referenced_layer(struct CustomData *data, const int t
const LayerTypeInfo *typeInfo = layerType_getInfo(layer->type);
if (typeInfo->copy) {
- char *dest_data = MEM_mallocN(typeInfo->size * totelem, "CD duplicate ref layer");
- typeInfo->copy(layer->data, dest_data, totelem);
- layer->data = dest_data;
+ void *dst_data = MEM_mallocN(totelem * typeInfo->size, "CD duplicate ref layer");
+ typeInfo->copy(layer->data, dst_data, totelem);
+ layer->data = dst_data;
}
- else
+ else {
layer->data = MEM_dupallocN(layer->data);
+ }
layer->flag &= ~CD_FLAG_NOFREE;
}
@@ -1888,37 +2066,34 @@ void *CustomData_duplicate_referenced_layer(struct CustomData *data, const int t
return layer->data;
}
-void *CustomData_duplicate_referenced_layer_named(struct CustomData *data,
- const int type, const char *name, const int totelem)
+void *CustomData_duplicate_referenced_layer(CustomData *data, const int type, const int totelem)
{
- CustomDataLayer *layer;
int layer_index;
- /* get the layer index of the desired layer */
- layer_index = CustomData_get_named_layer_index(data, type, name);
- if (layer_index == -1) return NULL;
+ /* get the layer index of the first layer of type */
+ layer_index = CustomData_get_active_layer_index(data, type);
- layer = &data->layers[layer_index];
+ return customData_duplicate_referenced_layer_index(data, layer_index, totelem);
+}
- if (layer->flag & CD_FLAG_NOFREE) {
- /* MEM_dupallocN won't work in case of complex layers, like e.g.
- * CD_MDEFORMVERT, which has pointers to allocated data...
- * So in case a custom copy function is defined, use it!
- */
- const LayerTypeInfo *typeInfo = layerType_getInfo(layer->type);
+void *CustomData_duplicate_referenced_layer_n(CustomData *data, const int type, const int n, const int totelem)
+{
+ int layer_index;
- if (typeInfo->copy) {
- char *dest_data = MEM_mallocN(typeInfo->size * totelem, "CD duplicate ref layer");
- typeInfo->copy(layer->data, dest_data, totelem);
- layer->data = dest_data;
- }
- else
- layer->data = MEM_dupallocN(layer->data);
+ /* get the layer index of the desired layer */
+ layer_index = CustomData_get_layer_index_n(data, type, n);
- layer->flag &= ~CD_FLAG_NOFREE;
- }
+ return customData_duplicate_referenced_layer_index(data, layer_index, totelem);
+}
- return layer->data;
+void *CustomData_duplicate_referenced_layer_named(CustomData *data, const int type, const char *name, const int totelem)
+{
+ int layer_index;
+
+ /* get the layer index of the desired layer */
+ layer_index = CustomData_get_named_layer_index(data, type, name);
+
+ return customData_duplicate_referenced_layer_index(data, layer_index, totelem);
}
bool CustomData_is_referenced_layer(struct CustomData *data, int type)
@@ -1928,7 +2103,8 @@ bool CustomData_is_referenced_layer(struct CustomData *data, int type)
/* get the layer index of the first layer of type */
layer_index = CustomData_get_active_layer_index(data, type);
- if (layer_index == -1) return 0;
+ if (layer_index == -1)
+ return false;
layer = &data->layers[layer_index];
@@ -1977,47 +2153,49 @@ void CustomData_set_only_copy(const struct CustomData *data,
data->layers[i].flag |= CD_FLAG_NOCOPY;
}
-void CustomData_copy_elements(int type, void *source, void *dest, int count)
+void CustomData_copy_elements(int type, void *src_data_ofs, void *dst_data_ofs, int count)
{
const LayerTypeInfo *typeInfo = layerType_getInfo(type);
if (typeInfo->copy)
- typeInfo->copy(source, dest, count);
+ typeInfo->copy(src_data_ofs, dst_data_ofs, count);
else
- memcpy(dest, source, typeInfo->size * count);
+ memcpy(dst_data_ofs, src_data_ofs, count * typeInfo->size);
}
-static void CustomData_copy_data_layer(const CustomData *source, CustomData *dest,
- int src_i, int dest_i,
- int source_index, int dest_index, int count) {
+static void CustomData_copy_data_layer(
+ const CustomData *source, CustomData *dest,
+ int src_i, int dst_i,
+ int src_index, int dst_index, int count)
+{
const LayerTypeInfo *typeInfo;
int src_offset;
- int dest_offset;
+ int dst_offset;
- const char *src_data = source->layers[src_i].data;
- char *dest_data = dest->layers[dest_i].data;
+ const void *src_data = source->layers[src_i].data;
+ void *dst_data = dest->layers[dst_i].data;
typeInfo = layerType_getInfo(source->layers[src_i].type);
- src_offset = source_index * typeInfo->size;
- dest_offset = dest_index * typeInfo->size;
+ src_offset = src_index * typeInfo->size;
+ dst_offset = dst_index * typeInfo->size;
- if (!src_data || !dest_data) {
- if (!(src_data == NULL && dest_data == NULL)) {
+ if (!count || !src_data || !dst_data) {
+ if (count && !(src_data == NULL && dst_data == NULL)) {
printf("%s: warning null data for %s type (%p --> %p), skipping\n",
__func__, layerType_getName(source->layers[src_i].type),
- (void *)src_data, (void *)dest_data);
+ (void *)src_data, (void *)dst_data);
}
return;
}
if (typeInfo->copy)
- typeInfo->copy(src_data + src_offset,
- dest_data + dest_offset,
+ typeInfo->copy(POINTER_OFFSET(src_data, src_offset),
+ POINTER_OFFSET(dst_data, dst_offset),
count);
else
- memcpy(dest_data + dest_offset,
- src_data + src_offset,
+ memcpy(POINTER_OFFSET(dst_data, dst_offset),
+ POINTER_OFFSET(src_data, src_offset),
count * typeInfo->size);
}
@@ -2080,10 +2258,9 @@ void CustomData_free_elem(CustomData *data, int index, int count)
typeInfo = layerType_getInfo(data->layers[i].type);
if (typeInfo->free) {
- int offset = typeInfo->size * index;
+ int offset = index * typeInfo->size;
- typeInfo->free((char *)data->layers[i].data + offset,
- count, typeInfo->size);
+ typeInfo->free(POINTER_OFFSET(data->layers[i].data, offset), count, typeInfo->size);
}
}
}
@@ -2096,17 +2273,15 @@ void CustomData_interp(const CustomData *source, CustomData *dest,
int count, int dest_index)
{
int src_i, dest_i;
- int dest_offset;
int j;
- void *source_buf[SOURCE_BUF_SIZE];
- void **sources = source_buf;
+ const void *source_buf[SOURCE_BUF_SIZE];
+ const void **sources = source_buf;
/* slow fallback in case we're interpolating a ridiculous number of
* elements
*/
if (count > SOURCE_BUF_SIZE)
- sources = MEM_callocN(sizeof(*sources) * count,
- "CustomData_interp sources");
+ sources = MEM_mallocN(sizeof(*sources) * count, __func__);
/* interpolates a layer at a time */
dest_i = 0;
@@ -2129,13 +2304,11 @@ void CustomData_interp(const CustomData *source, CustomData *dest,
void *src_data = source->layers[src_i].data;
for (j = 0; j < count; ++j) {
- sources[j] = (char *)src_data + typeInfo->size * src_indices[j];
+ sources[j] = POINTER_OFFSET(src_data, src_indices[j] * typeInfo->size);
}
- dest_offset = dest_index * typeInfo->size;
-
typeInfo->interp(sources, weights, sub_weights, count,
- (char *)dest->layers[dest_i].data + dest_offset);
+ POINTER_OFFSET(dest->layers[dest_i].data, dest_index * typeInfo->size));
/* if there are multiple source & dest layers of the same type,
* we don't want to copy all source layers to the same dest, so
@@ -2145,7 +2318,7 @@ void CustomData_interp(const CustomData *source, CustomData *dest,
}
}
- if (count > SOURCE_BUF_SIZE) MEM_freeN(sources);
+ if (count > SOURCE_BUF_SIZE) MEM_freeN((void *)sources);
}
void CustomData_swap(struct CustomData *data, int index, const int *corner_indices)
@@ -2157,9 +2330,9 @@ void CustomData_swap(struct CustomData *data, int index, const int *corner_indic
typeInfo = layerType_getInfo(data->layers[i].type);
if (typeInfo->swap) {
- int offset = typeInfo->size * index;
+ const int offset = index * typeInfo->size;
- typeInfo->swap((char *)data->layers[i].data + offset, corner_indices);
+ typeInfo->swap(POINTER_OFFSET(data->layers[i].data, offset), corner_indices);
}
}
}
@@ -2178,7 +2351,7 @@ void *CustomData_get(const CustomData *data, int index, int type)
/* get the offset of the desired element */
offset = layerType_getInfo(type)->size * index;
- return (char *)data->layers[layer_index].data + offset;
+ return POINTER_OFFSET(data->layers[layer_index].data, offset);
}
void *CustomData_get_n(const CustomData *data, int type, int index, int n)
@@ -2193,7 +2366,7 @@ void *CustomData_get_n(const CustomData *data, int type, int index, int n)
if (layer_index == -1) return NULL;
offset = layerType_getInfo(type)->size * index;
- return (char *)data->layers[layer_index + n].data + offset;
+ return POINTER_OFFSET(data->layers[layer_index + n].data, offset);
}
void *CustomData_get_layer(const CustomData *data, int type)
@@ -2244,16 +2417,23 @@ int CustomData_get_n_offset(const CustomData *data, int type, int n)
bool CustomData_set_layer_name(const CustomData *data, int type, int n, const char *name)
{
/* get the layer index of the first layer of type */
- int layer_index = CustomData_get_layer_index_n(data, type, n);
+ const int layer_index = CustomData_get_layer_index_n(data, type, n);
- if (layer_index == -1) return false;
- if (!name) return false;
+ if ((layer_index == -1) || !name)
+ return false;
BLI_strncpy(data->layers[layer_index].name, name, sizeof(data->layers[layer_index].name));
return true;
}
+const char *CustomData_get_layer_name(const CustomData *data, int type, int n)
+{
+ const int layer_index = CustomData_get_layer_index_n(data, type, n);
+
+ return (layer_index == -1) ? NULL : data->layers[layer_index].name;
+}
+
void *CustomData_set_layer(const CustomData *data, int type, void *ptr)
{
/* get the layer index of the first layer of type */
@@ -2277,7 +2457,7 @@ void *CustomData_set_layer_n(const struct CustomData *data, int type, int n, voi
return ptr;
}
-void CustomData_set(const CustomData *data, int index, int type, void *source)
+void CustomData_set(const CustomData *data, int index, int type, const void *source)
{
void *dest = CustomData_get(data, index, type);
const LayerTypeInfo *typeInfo = layerType_getInfo(type);
@@ -2316,6 +2496,10 @@ void CustomData_to_bmeshpoly(CustomData *fdata, CustomData *pdata, CustomData *l
void CustomData_from_bmeshpoly(CustomData *fdata, CustomData *pdata, CustomData *ldata, int total)
{
int i;
+
+ /* avoid accumulating extra layers */
+ BLI_assert(!CustomData_from_bmeshpoly_test(fdata, pdata, ldata, false));
+
for (i = 0; i < pdata->totlayer; i++) {
if (pdata->layers[i].type == CD_MTEXPOLY) {
CustomData_add_layer_named(fdata, CD_MTFACE, CD_CALLOC, NULL, total, pdata->layers[i].name);
@@ -2334,11 +2518,49 @@ void CustomData_from_bmeshpoly(CustomData *fdata, CustomData *pdata, CustomData
else if (ldata->layers[i].type == CD_NORMAL) {
CustomData_add_layer_named(fdata, CD_TESSLOOPNORMAL, CD_CALLOC, NULL, total, ldata->layers[i].name);
}
+ else if (ldata->layers[i].type == CD_TANGENT) {
+ CustomData_add_layer_named(fdata, CD_TANGENT, CD_CALLOC, NULL, total, ldata->layers[i].name);
+ }
}
CustomData_bmesh_update_active_layers(fdata, pdata, ldata);
}
+#ifndef NDEBUG
+/**
+ * Debug check, used to assert when we expect layers to be in/out of sync.
+ *
+ * \param fallback: Use when there are no layers to handle,
+ * since callers may expect success or failure.
+ */
+bool CustomData_from_bmeshpoly_test(CustomData *fdata, CustomData *pdata, CustomData *ldata, bool fallback)
+{
+ int a_num = 0, b_num = 0;
+#define LAYER_CMP(l_a, t_a, l_b, t_b) \
+ ((a_num += CustomData_number_of_layers(l_a, t_a)) == (b_num += CustomData_number_of_layers(l_b, t_b)))
+
+ if (!LAYER_CMP(pdata, CD_MTEXPOLY, fdata, CD_MTFACE))
+ return false;
+ if (!LAYER_CMP(ldata, CD_MLOOPCOL, fdata, CD_MCOL))
+ return false;
+ if (!LAYER_CMP(ldata, CD_PREVIEW_MLOOPCOL, fdata, CD_PREVIEW_MCOL))
+ return false;
+ if (!LAYER_CMP(ldata, CD_ORIGSPACE_MLOOP, fdata, CD_ORIGSPACE))
+ return false;
+ if (!LAYER_CMP(ldata, CD_NORMAL, fdata, CD_TESSLOOPNORMAL))
+ return false;
+ if (!LAYER_CMP(ldata, CD_TANGENT, fdata, CD_TANGENT))
+ return false;
+
+#undef TEST_RET
+
+ /* if no layers are on either CustomData's,
+ * then there was nothing to do... */
+ return a_num ? true : fallback;
+}
+#endif
+
+
void CustomData_bmesh_update_active_layers(CustomData *fdata, CustomData *pdata, CustomData *ldata)
{
int act;
@@ -2442,8 +2664,9 @@ void CustomData_bmesh_init_pool(CustomData *data, int totelem, const char htype)
}
}
-bool CustomData_bmesh_merge(CustomData *source, CustomData *dest,
- CustomDataMask mask, int alloctype, BMesh *bm, const char htype)
+bool CustomData_bmesh_merge(
+ const CustomData *source, CustomData *dest,
+ CustomDataMask mask, int alloctype, BMesh *bm, const char htype)
{
BMHeader *h;
BMIter iter;
@@ -2540,7 +2763,7 @@ void CustomData_bmesh_free_block(CustomData *data, void **block)
if (typeInfo->free) {
int offset = data->layers[i].offset;
- typeInfo->free((char *)*block + offset, 1, typeInfo->size);
+ typeInfo->free(POINTER_OFFSET(*block, offset), 1, typeInfo->size);
}
}
}
@@ -2568,7 +2791,7 @@ void CustomData_bmesh_free_block_data(CustomData *data, void *block)
if (typeInfo->free) {
int offset = data->layers[i].offset;
- typeInfo->free((char *)block + offset, 1, typeInfo->size);
+ typeInfo->free(POINTER_OFFSET(block, offset), 1, typeInfo->size);
}
}
}
@@ -2617,10 +2840,10 @@ void CustomData_bmesh_copy_data(const CustomData *source, CustomData *dest,
/* if we found a matching layer, copy the data */
if (dest->layers[dest_i].type == source->layers[src_i].type &&
- strcmp(dest->layers[dest_i].name, source->layers[src_i].name) == 0)
+ STREQ(dest->layers[dest_i].name, source->layers[src_i].name))
{
- const char *src_data = (char *)src_block + source->layers[src_i].offset;
- char *dest_data = (char *)*dest_block + dest->layers[dest_i].offset;
+ const void *src_data = POINTER_OFFSET(src_block, source->layers[src_i].offset);
+ void *dest_data = POINTER_OFFSET(*dest_block, dest->layers[dest_i].offset);
typeInfo = layerType_getInfo(source->layers[src_i].type);
@@ -2647,7 +2870,7 @@ void *CustomData_bmesh_get(const CustomData *data, void *block, int type)
layer_index = CustomData_get_active_layer_index(data, type);
if (layer_index == -1) return NULL;
- return (char *)block + data->layers[layer_index].offset;
+ return POINTER_OFFSET(block, data->layers[layer_index].offset);
}
void *CustomData_bmesh_get_n(const CustomData *data, void *block, int type, int n)
@@ -2658,7 +2881,7 @@ void *CustomData_bmesh_get_n(const CustomData *data, void *block, int type, int
layer_index = CustomData_get_layer_index(data, type);
if (layer_index == -1) return NULL;
- return (char *)block + data->layers[layer_index + n].offset;
+ return POINTER_OFFSET(block, data->layers[layer_index + n].offset);
}
/*gets from the layer at physical index n, note: doesn't check type.*/
@@ -2666,7 +2889,7 @@ void *CustomData_bmesh_get_layer_n(const CustomData *data, void *block, int n)
{
if (n < 0 || n >= data->totlayer) return NULL;
- return (char *)block + data->layers[n].offset;
+ return POINTER_OFFSET(block, data->layers[n].offset);
}
bool CustomData_layer_has_math(const struct CustomData *data, int layer_n)
@@ -2738,6 +2961,17 @@ bool CustomData_has_interp(const struct CustomData *data)
return false;
}
+bool CustomData_has_referenced(const struct CustomData *data)
+{
+ int i;
+ for (i = 0; i < data->totlayer; ++i) {
+ if (data->layers[i].flag & CD_FLAG_NOFREE) {
+ return true;
+ }
+ }
+ return false;
+}
+
/* copies the "value" (e.g. mloopuv uv or mloopcol colors) from one block to
* another, while not overwriting anything else (e.g. flags)*/
void CustomData_data_copy_value(int type, const void *source, void *dest)
@@ -2747,11 +2981,28 @@ void CustomData_data_copy_value(int type, const void *source, void *dest)
if (!dest) return;
if (typeInfo->copyvalue)
- typeInfo->copyvalue(source, dest);
+ typeInfo->copyvalue(source, dest, CDT_MIX_NOMIX, 0.0f);
else
memcpy(dest, source, typeInfo->size);
}
+/* Mixes the "value" (e.g. mloopuv uv or mloopcol colors) from one block into
+ * another, while not overwriting anything else (e.g. flags)*/
+void CustomData_data_mix_value(int type, const void *source, void *dest, const int mixmode, const float mixfactor)
+{
+ const LayerTypeInfo *typeInfo = layerType_getInfo(type);
+
+ if (!dest) return;
+
+ if (typeInfo->copyvalue) {
+ typeInfo->copyvalue(source, dest, mixmode, mixfactor);
+ }
+ else {
+ /* Mere copy if no advanced interpolation is supported. */
+ memcpy(dest, source, typeInfo->size);
+ }
+}
+
bool CustomData_data_equals(int type, const void *data1, const void *data2)
{
const LayerTypeInfo *typeInfo = layerType_getInfo(type);
@@ -2796,7 +3047,7 @@ void CustomData_data_add(int type, void *data1, const void *data2)
typeInfo->add(data1, data2);
}
-void CustomData_bmesh_set(const CustomData *data, void *block, int type, void *source)
+void CustomData_bmesh_set(const CustomData *data, void *block, int type, const void *source)
{
void *dest = CustomData_bmesh_get(data, block, type);
const LayerTypeInfo *typeInfo = layerType_getInfo(type);
@@ -2809,7 +3060,7 @@ void CustomData_bmesh_set(const CustomData *data, void *block, int type, void *s
memcpy(dest, source, typeInfo->size);
}
-void CustomData_bmesh_set_n(CustomData *data, void *block, int type, int n, void *source)
+void CustomData_bmesh_set_n(CustomData *data, void *block, int type, int n, const void *source)
{
void *dest = CustomData_bmesh_get_n(data, block, type, n);
const LayerTypeInfo *typeInfo = layerType_getInfo(type);
@@ -2822,7 +3073,7 @@ void CustomData_bmesh_set_n(CustomData *data, void *block, int type, int n, void
memcpy(dest, source, typeInfo->size);
}
-void CustomData_bmesh_set_layer_n(CustomData *data, void *block, int n, void *source)
+void CustomData_bmesh_set_layer_n(CustomData *data, void *block, int n, const void *source)
{
void *dest = CustomData_bmesh_get_layer_n(data, block, n);
const LayerTypeInfo *typeInfo = layerType_getInfo(data->layers[n].type);
@@ -2836,31 +3087,34 @@ void CustomData_bmesh_set_layer_n(CustomData *data, void *block, int n, void *so
}
/**
- * \param src_blocks must be pointers to the data, offset by layer->offset already.
+ * \note src_blocks_ofs & dst_block_ofs
+ * must be pointers to the data, offset by layer->offset already.
*/
-void CustomData_bmesh_interp_n(CustomData *data, void **src_blocks, const float *weights,
- const float *sub_weights, int count, void *dest_block, int n)
+void CustomData_bmesh_interp_n(
+ CustomData *data, const void **src_blocks_ofs,
+ const float *weights, const float *sub_weights,
+ int count, void *dst_block_ofs, int n)
{
CustomDataLayer *layer = &data->layers[n];
const LayerTypeInfo *typeInfo = layerType_getInfo(layer->type);
- typeInfo->interp(src_blocks, weights, sub_weights, count,
- (char *)dest_block + layer->offset);
+ typeInfo->interp(src_blocks_ofs, weights, sub_weights, count, dst_block_ofs);
}
-void CustomData_bmesh_interp(CustomData *data, void **src_blocks, const float *weights,
- const float *sub_weights, int count, void *dest_block)
+void CustomData_bmesh_interp(
+ CustomData *data, const void **src_blocks,
+ const float *weights, const float *sub_weights,
+ int count, void *dst_block)
{
int i, j;
void *source_buf[SOURCE_BUF_SIZE];
- void **sources = source_buf;
+ const void **sources = (const void **)source_buf;
/* slow fallback in case we're interpolating a ridiculous number of
* elements
*/
if (count > SOURCE_BUF_SIZE)
- sources = MEM_callocN(sizeof(*sources) * count,
- "CustomData_interp sources");
+ sources = MEM_mallocN(sizeof(*sources) * count, __func__);
/* interpolates a layer at a time */
for (i = 0; i < data->totlayer; ++i) {
@@ -2868,13 +3122,16 @@ void CustomData_bmesh_interp(CustomData *data, void **src_blocks, const float *w
const LayerTypeInfo *typeInfo = layerType_getInfo(layer->type);
if (typeInfo->interp) {
for (j = 0; j < count; ++j) {
- sources[j] = (char *)src_blocks[j] + layer->offset;
+ sources[j] = POINTER_OFFSET(src_blocks[j], layer->offset);
}
- CustomData_bmesh_interp_n(data, sources, weights, sub_weights, count, dest_block, i);
+ CustomData_bmesh_interp_n(
+ data, sources,
+ weights, sub_weights, count,
+ POINTER_OFFSET(dst_block, layer->offset), i);
}
}
- if (count > SOURCE_BUF_SIZE) MEM_freeN(sources);
+ if (count > SOURCE_BUF_SIZE) MEM_freeN((void *)sources);
}
static void CustomData_bmesh_set_default_n(CustomData *data, void **block, int n)
@@ -2885,10 +3142,10 @@ static void CustomData_bmesh_set_default_n(CustomData *data, void **block, int n
typeInfo = layerType_getInfo(data->layers[n].type);
if (typeInfo->set_default) {
- typeInfo->set_default((char *)*block + offset, 1);
+ typeInfo->set_default(POINTER_OFFSET(*block, offset), 1);
}
else {
- memset((char *)*block + offset, 0, typeInfo->size);
+ memset(POINTER_OFFSET(*block, offset), 0, typeInfo->size);
}
}
@@ -2938,16 +3195,16 @@ void CustomData_to_bmesh_block(const CustomData *source, CustomData *dest,
/* if we found a matching layer, copy the data */
if (dest->layers[dest_i].type == source->layers[src_i].type) {
int offset = dest->layers[dest_i].offset;
- const char *src_data = source->layers[src_i].data;
- char *dest_data = (char *)*dest_block + offset;
+ const void *src_data = source->layers[src_i].data;
+ void *dest_data = POINTER_OFFSET(*dest_block, offset);
typeInfo = layerType_getInfo(dest->layers[dest_i].type);
src_offset = src_index * typeInfo->size;
if (typeInfo->copy)
- typeInfo->copy(src_data + src_offset, dest_data, 1);
+ typeInfo->copy(POINTER_OFFSET(src_data, src_offset), dest_data, 1);
else
- memcpy(dest_data, src_data + src_offset, typeInfo->size);
+ memcpy(dest_data, POINTER_OFFSET(src_data, src_offset), typeInfo->size);
/* if there are multiple source & dest layers of the same type,
* we don't want to copy all source layers to the same dest, so
@@ -2966,10 +3223,9 @@ void CustomData_to_bmesh_block(const CustomData *source, CustomData *dest,
}
void CustomData_from_bmesh_block(const CustomData *source, CustomData *dest,
- void *src_block, int dest_index)
+ void *src_block, int dst_index)
{
- const LayerTypeInfo *typeInfo;
- int dest_i, src_i, dest_offset;
+ int dest_i, src_i;
/* copies a layer at a time */
dest_i = 0;
@@ -2987,17 +3243,15 @@ void CustomData_from_bmesh_block(const CustomData *source, CustomData *dest,
/* if we found a matching layer, copy the data */
if (dest->layers[dest_i].type == source->layers[src_i].type) {
+ const LayerTypeInfo *typeInfo = layerType_getInfo(dest->layers[dest_i].type);
int offset = source->layers[src_i].offset;
- const char *src_data = (char *)src_block + offset;
- char *dest_data = dest->layers[dest_i].data;
-
- typeInfo = layerType_getInfo(dest->layers[dest_i].type);
- dest_offset = dest_index * typeInfo->size;
+ const void *src_data = POINTER_OFFSET(src_block, offset);
+ void *dst_data = POINTER_OFFSET(dest->layers[dest_i].data, dst_index * typeInfo->size);
if (typeInfo->copy)
- typeInfo->copy(src_data, dest_data + dest_offset, 1);
+ typeInfo->copy(src_data, dst_data, 1);
else
- memcpy(dest_data + dest_offset, src_data, typeInfo->size);
+ memcpy(dst_data, src_data, typeInfo->size);
/* if there are multiple source & dest layers of the same type,
* we don't want to copy all source layers to the same dest, so
@@ -3017,6 +3271,57 @@ void CustomData_file_write_info(int type, const char **structname, int *structnu
*structnum = typeInfo->structnum;
}
+/**
+ * Prepare given custom data for file writing.
+ *
+ * \param data the customdata to tweak for .blend file writing (modified in place).
+ * \param r_write_layers contains a reduced set of layers to be written to file, use it with writestruct_at_address()
+ * (caller must free it if != \a write_layers_buff).
+ * \param write_layers_buff an optional buffer for r_write_layers (to avoid allocating it).
+ * \param write_layers_size the size of pre-allocated \a write_layer_buff.
+ *
+ * \warning After this func has ran, given custom data is no more valid from Blender PoV (its totlayer is invalid).
+ * This func shall always be called with localized data (as it is in write_meshes()).
+ * \note data->typemap is not updated here, since it is always rebuilt on file read anyway. This means written
+ * typemap does not match written layers (as returned by \a r_write_layers). Trivial to fix is ever needed.
+ */
+void CustomData_file_write_prepare(
+ CustomData *data,
+ CustomDataLayer **r_write_layers, CustomDataLayer *write_layers_buff, size_t write_layers_size)
+{
+ CustomDataLayer *write_layers = write_layers_buff;
+ const size_t chunk_size = (write_layers_size > 0) ? write_layers_size : CD_TEMP_CHUNK_SIZE;
+
+ const int totlayer = data->totlayer;
+ int i, j;
+
+ for (i = 0, j = 0; i < totlayer; i++) {
+ CustomDataLayer *layer = &data->layers[i];
+ if (layer->flag & CD_FLAG_NOCOPY) { /* Layers with this flag set are not written to file. */
+ data->totlayer--;
+ /* printf("%s: skipping layer %p (%s)\n", __func__, layer, layer->name); */
+ }
+ else {
+ if (UNLIKELY((size_t)j >= write_layers_size)) {
+ if (write_layers == write_layers_buff) {
+ write_layers = MEM_mallocN(sizeof(*write_layers) * (write_layers_size + chunk_size), __func__);
+ if (write_layers_buff) {
+ memcpy(write_layers, write_layers_buff, sizeof(*write_layers) * write_layers_size);
+ }
+ }
+ else {
+ write_layers = MEM_reallocN(write_layers, sizeof(*write_layers) * (write_layers_size + chunk_size));
+ }
+ write_layers_size += chunk_size;
+ }
+ write_layers[j++] = *layer;
+ }
+ }
+ BLI_assert(j == data->totlayer);
+ data->maxlayer = data->totlayer; /* We only write that much of data! */
+ *r_write_layers = write_layers;
+}
+
int CustomData_sizeof(int type)
{
const LayerTypeInfo *typeInfo = layerType_getInfo(type);
@@ -3039,6 +3344,24 @@ bool CustomData_layertype_is_singleton(int type)
return typeInfo->defaultname == NULL;
}
+/**
+ * \return Maximum number of layers of given \a type, -1 means 'no limit'.
+ */
+int CustomData_layertype_layers_max(const int type)
+{
+ const LayerTypeInfo *typeInfo = layerType_getInfo(type);
+
+ /* Same test as for singleton above. */
+ if (typeInfo->defaultname == NULL) {
+ return 1;
+ }
+ else if (typeInfo->layers_max == NULL) {
+ return -1;
+ }
+
+ return typeInfo->layers_max();
+}
+
static bool CustomData_is_property_layer(int type)
{
if ((type == CD_PROP_FLT) || (type == CD_PROP_INT) || (type == CD_PROP_STR))
@@ -3055,12 +3378,12 @@ static bool cd_layer_find_dupe(CustomData *data, const char *name, int type, int
CustomDataLayer *layer = &data->layers[i];
if (CustomData_is_property_layer(type)) {
- if (CustomData_is_property_layer(layer->type) && strcmp(layer->name, name) == 0) {
+ if (CustomData_is_property_layer(layer->type) && STREQ(layer->name, name)) {
return true;
}
}
else {
- if (i != index && layer->type == type && strcmp(layer->name, name) == 0) {
+ if (i != index && layer->type == type && STREQ(layer->name, name)) {
return true;
}
}
@@ -3429,3 +3752,234 @@ void CustomData_external_remove_object(CustomData *data, ID *id)
}
#endif
+/* ********** Mesh-to-mesh data transfer ********** */
+static void copy_bit_flag(void *dst, const void *src, const size_t data_size, const uint64_t flag)
+{
+#define COPY_BIT_FLAG(_type, _dst, _src, _f) \
+{ \
+ const _type _val = *((_type *)(_src)) & ((_type)(_f)); \
+ *((_type *)(_dst)) &= ~((_type)(_f)); \
+ *((_type *)(_dst)) |= _val; \
+} (void) 0
+
+ switch (data_size) {
+ case 1:
+ COPY_BIT_FLAG(uint8_t, dst, src, flag);
+ break;
+ case 2:
+ COPY_BIT_FLAG(uint16_t, dst, src, flag);
+ break;
+ case 4:
+ COPY_BIT_FLAG(uint32_t, dst, src, flag);
+ break;
+ case 8:
+ COPY_BIT_FLAG(uint64_t, dst, src, flag);
+ break;
+ default:
+ //printf("ERROR %s: Unknown flags-container size (%zu)\n", __func__, datasize);
+ break;
+ }
+
+#undef COPY_BIT_FLAG
+}
+
+static bool check_bit_flag(const void *data, const size_t data_size, const uint64_t flag)
+{
+ switch (data_size) {
+ case 1:
+ return ((*((uint8_t *)data) & ((uint8_t)flag)) != 0);
+ case 2:
+ return ((*((uint16_t *)data) & ((uint16_t)flag)) != 0);
+ case 4:
+ return ((*((uint32_t *)data) & ((uint32_t)flag)) != 0);
+ case 8:
+ return ((*((uint64_t *)data) & ((uint64_t)flag)) != 0);
+ default:
+ //printf("ERROR %s: Unknown flags-container size (%zu)\n", __func__, datasize);
+ return false;
+ }
+}
+
+static void customdata_data_transfer_interp_generic(
+ const CustomDataTransferLayerMap *laymap, void *data_dst,
+ const void **sources, const float *weights, const int count,
+ const float mix_factor)
+{
+ /* Fake interpolation, we actually copy highest weighted source to dest.
+ * Note we also handle bitflags here, in which case we rather choose to transfer value of elements totaling
+ * more than 0.5 of weight. */
+
+ int best_src_idx = 0;
+
+ const int data_type = laymap->data_type;
+ const int mix_mode = laymap->mix_mode;
+
+ size_t data_size;
+ const uint64_t data_flag = laymap->data_flag;
+
+ cd_interp interp_cd = NULL;
+ cd_copy copy_cd = NULL;
+
+ void *tmp_dst;
+
+ if (!sources) {
+ /* Not supported here, abort. */
+ return;
+ }
+
+ if (data_type & CD_FAKE) {
+ data_size = laymap->data_size;
+ }
+ else {
+ const LayerTypeInfo *type_info = layerType_getInfo(data_type);
+
+ data_size = (size_t)type_info->size;
+ interp_cd = type_info->interp;
+ copy_cd = type_info->copy;
+ }
+
+ tmp_dst = MEM_mallocN(data_size, __func__);
+
+ if (count > 1 && !interp_cd) {
+ int i;
+
+ if (data_flag) {
+ /* Boolean case, we can 'interpolate' in two groups, and choose value from highest weighted group. */
+ float tot_weight_true = 0.0f;
+ int item_true_idx = -1, item_false_idx = -1;
+
+ for (i = 0; i < count; i++) {
+ if (check_bit_flag(sources[i], data_size, data_flag)) {
+ tot_weight_true += weights[i];
+ item_true_idx = i;
+ }
+ else {
+ item_false_idx = i;
+ }
+ }
+ best_src_idx = (tot_weight_true >= 0.5f) ? item_true_idx : item_false_idx;
+ }
+ else {
+ /* We just choose highest weighted source. */
+ float max_weight = 0.0f;
+
+ for (i = 0; i < count; i++) {
+ if (weights[i] > max_weight) {
+ max_weight = weights[i];
+ best_src_idx = i;
+ }
+ }
+ }
+ }
+
+ BLI_assert(best_src_idx >= 0);
+
+ if (interp_cd) {
+ interp_cd(sources, weights, NULL, count, tmp_dst);
+ }
+ else if (data_flag) {
+ copy_bit_flag(tmp_dst, sources[best_src_idx], data_size, data_flag);
+ }
+ /* No interpolation, just copy highest weight source element's data. */
+ else if (copy_cd) {
+ copy_cd(sources[best_src_idx], tmp_dst, 1);
+ }
+ else {
+ memcpy(tmp_dst, sources[best_src_idx], data_size);
+ }
+
+ if (data_flag) {
+ /* Bool flags, only copy if dest data is set (resp. unset) - only 'advanced' modes we can support here! */
+ if (mix_factor >= 0.5f &&
+ ((mix_mode == CDT_MIX_TRANSFER) ||
+ (mix_mode == CDT_MIX_REPLACE_ABOVE_THRESHOLD && check_bit_flag(data_dst, data_size, data_flag)) ||
+ (mix_mode == CDT_MIX_REPLACE_BELOW_THRESHOLD && !check_bit_flag(data_dst, data_size, data_flag))))
+ {
+ copy_bit_flag(data_dst, tmp_dst, data_size, data_flag);
+ }
+ }
+ else if (!(data_type & CD_FAKE)) {
+ CustomData_data_mix_value(data_type, tmp_dst, data_dst, mix_mode, mix_factor);
+ }
+ /* Else we can do nothing by default, needs custom interp func!
+ * Note this is here only for sake of consistency, not expected to be used much actually? */
+ else {
+ if (mix_factor >= 0.5f) {
+ memcpy(data_dst, tmp_dst, data_size);
+ }
+ }
+
+ MEM_freeN(tmp_dst);
+}
+
+void CustomData_data_transfer(const MeshPairRemap *me_remap, const CustomDataTransferLayerMap *laymap)
+{
+ MeshPairRemapItem *mapit = me_remap->items;
+ const int totelem = me_remap->items_num;
+ int i;
+
+ const int data_type = laymap->data_type;
+ const void *data_src = laymap->data_src;
+ void *data_dst = laymap->data_dst;
+
+ size_t data_step;
+ size_t data_size;
+ size_t data_offset;
+
+ cd_datatransfer_interp interp = NULL;
+
+ size_t tmp_buff_size = 32;
+ const void **tmp_data_src = NULL;
+
+ /* Note: NULL data_src may happen and be valid (see vgroups...). */
+ if (!data_dst) {
+ return;
+ }
+
+ if (data_src) {
+ tmp_data_src = MEM_mallocN(sizeof(*tmp_data_src) * tmp_buff_size, __func__);
+ }
+
+ if (data_type & CD_FAKE) {
+ data_step = laymap->elem_size;
+ data_size = laymap->data_size;
+ data_offset = laymap->data_offset;
+ }
+ else {
+ const LayerTypeInfo *type_info = layerType_getInfo(data_type);
+
+ /* Note: we can use 'fake' CDLayers, like e.g. for crease, bweight, etc. :/ */
+ data_size = (size_t)type_info->size;
+ data_step = laymap->elem_size ? laymap->elem_size : data_size;
+ data_offset = laymap->data_offset;
+ }
+
+ interp = laymap->interp ? laymap->interp : customdata_data_transfer_interp_generic;
+
+ for (i = 0; i < totelem; i++, data_dst = POINTER_OFFSET(data_dst, data_step), mapit++) {
+ const int sources_num = mapit->sources_num;
+ const float mix_factor = laymap->mix_weights ? laymap->mix_weights[i] : laymap->mix_factor;
+ int j;
+
+ if (!sources_num) {
+ /* No sources for this element, skip it. */
+ continue;
+ }
+
+ if (tmp_data_src) {
+ if (UNLIKELY(sources_num > tmp_buff_size)) {
+ tmp_buff_size = (size_t)sources_num;
+ tmp_data_src = MEM_reallocN((void *)tmp_data_src, sizeof(*tmp_data_src) * tmp_buff_size);
+ }
+
+ for (j = 0; j < sources_num; j++) {
+ const size_t src_idx = (size_t)mapit->indices_src[j];
+ tmp_data_src[j] = POINTER_OFFSET(data_src, (data_step * src_idx) + data_offset);
+ }
+ }
+
+ interp(laymap, POINTER_OFFSET(data_dst, data_offset), tmp_data_src, mapit->weights_src, sources_num, mix_factor);
+ }
+
+ MEM_SAFE_FREE(tmp_data_src);
+}
diff --git a/source/blender/blenkernel/intern/customdata_file.c b/source/blender/blenkernel/intern/customdata_file.c
index c72eea50e40..41579aaa568 100644
--- a/source/blender/blenkernel/intern/customdata_file.c
+++ b/source/blender/blenkernel/intern/customdata_file.c
@@ -276,7 +276,7 @@ static int cdf_write_header(CDataFile *cdf)
return 1;
}
-int cdf_read_open(CDataFile *cdf, const char *filename)
+bool cdf_read_open(CDataFile *cdf, const char *filename)
{
FILE *f;
@@ -299,7 +299,7 @@ int cdf_read_open(CDataFile *cdf, const char *filename)
return 1;
}
-int cdf_read_layer(CDataFile *cdf, CDataFileLayer *blay)
+bool cdf_read_layer(CDataFile *cdf, CDataFileLayer *blay)
{
size_t offset;
int a;
@@ -316,7 +316,7 @@ int cdf_read_layer(CDataFile *cdf, CDataFileLayer *blay)
return (fseek(cdf->readf, offset, SEEK_SET) == 0);
}
-int cdf_read_data(CDataFile *cdf, unsigned int size, void *data)
+bool cdf_read_data(CDataFile *cdf, unsigned int size, void *data)
{
/* read data */
if (!fread(data, size, 1, cdf->readf))
@@ -338,7 +338,7 @@ void cdf_read_close(CDataFile *cdf)
}
}
-int cdf_write_open(CDataFile *cdf, const char *filename)
+bool cdf_write_open(CDataFile *cdf, const char *filename)
{
CDataFileHeader *header;
CDataFileImageHeader *image;
@@ -380,12 +380,12 @@ int cdf_write_open(CDataFile *cdf, const char *filename)
return 1;
}
-int cdf_write_layer(CDataFile *UNUSED(cdf), CDataFileLayer *UNUSED(blay))
+bool cdf_write_layer(CDataFile *UNUSED(cdf), CDataFileLayer *UNUSED(blay))
{
return 1;
}
-int cdf_write_data(CDataFile *cdf, unsigned int size, void *data)
+bool cdf_write_data(CDataFile *cdf, unsigned int size, void *data)
{
/* write data */
if (!fwrite(data, size, 1, cdf->writef))
@@ -417,7 +417,7 @@ CDataFileLayer *cdf_layer_find(CDataFile *cdf, int type, const char *name)
for (a = 0; a < cdf->totlayer; a++) {
layer = &cdf->layer[a];
- if (layer->type == type && strcmp(layer->name, name) == 0)
+ if (layer->type == type && STREQ(layer->name, name))
return layer;
}
diff --git a/source/blender/blenkernel/intern/data_transfer.c b/source/blender/blenkernel/intern/data_transfer.c
new file mode 100644
index 00000000000..53b6f4a1019
--- /dev/null
+++ b/source/blender/blenkernel/intern/data_transfer.c
@@ -0,0 +1,1417 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2014 by Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Bastien Montagne.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/blenkernel/intern/data_transfer.c
+ * \ingroup bke
+ */
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_customdata_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+
+#include "BLI_array.h"
+#include "BLI_math.h"
+#include "BLI_blenlib.h"
+#include "BLI_utildefines.h"
+
+#include "BKE_context.h"
+#include "BKE_customdata.h"
+#include "BKE_data_transfer.h"
+#include "BKE_deform.h"
+#include "BKE_DerivedMesh.h"
+#include "BKE_mesh.h"
+#include "BKE_mesh_mapping.h"
+#include "BKE_mesh_remap.h"
+#include "BKE_object.h"
+#include "BKE_object_deform.h"
+#include "BKE_report.h"
+
+#include "data_transfer_intern.h"
+
+
+CustomDataMask BKE_object_data_transfer_dttypes_to_cdmask(const int dtdata_types)
+{
+ CustomDataMask cddata_mask = 0;
+ int i;
+
+ for (i = 0; i < DT_TYPE_MAX; i++) {
+ const int dtdata_type = 1 << i;
+ int cddata_type;
+
+ if (!(dtdata_types & dtdata_type)) {
+ continue;
+ }
+
+ cddata_type = BKE_object_data_transfer_dttype_to_cdtype(dtdata_type);
+ if (!(cddata_type & CD_FAKE)) {
+ cddata_mask |= 1LL << cddata_type;
+ }
+ else if (cddata_type == CD_FAKE_MDEFORMVERT) {
+ cddata_mask |= CD_MASK_MDEFORMVERT; /* Exception for vgroups :/ */
+ }
+ else if (cddata_type == CD_FAKE_UV) {
+ cddata_mask |= CD_MASK_MTEXPOLY | CD_MASK_MLOOPUV;
+ }
+ else if (cddata_type == CD_FAKE_LNOR) {
+ cddata_mask |= CD_MASK_NORMAL | CD_MASK_CUSTOMLOOPNORMAL;
+ }
+ }
+
+ return cddata_mask;
+}
+
+/* Check what can do each layer type (if it is actually handled by transferdata, if it supports advanced mixing... */
+bool BKE_object_data_transfer_get_dttypes_capacity(
+ const int dtdata_types, bool *r_advanced_mixing, bool *r_threshold)
+{
+ int i;
+ bool ret = false;
+
+ *r_advanced_mixing = false;
+ *r_threshold = false;
+
+ for (i = 0; (i < DT_TYPE_MAX) && !(ret && *r_advanced_mixing && *r_threshold); i++) {
+ const int dtdata_type = 1 << i;
+
+ if (!(dtdata_types & dtdata_type)) {
+ continue;
+ }
+
+ switch (dtdata_type) {
+ /* Vertex data */
+ case DT_TYPE_MDEFORMVERT:
+ *r_advanced_mixing = true;
+ *r_threshold = true;
+ ret = true;
+ break;
+ case DT_TYPE_SKIN:
+ *r_threshold = true;
+ ret = true;
+ break;
+ case DT_TYPE_BWEIGHT_VERT:
+ ret = true;
+ break;
+ /* Edge data */
+ case DT_TYPE_SHARP_EDGE:
+ *r_threshold = true;
+ ret = true;
+ break;
+ case DT_TYPE_SEAM:
+ *r_threshold = true;
+ ret = true;
+ break;
+ case DT_TYPE_CREASE:
+ ret = true;
+ break;
+ case DT_TYPE_BWEIGHT_EDGE:
+ ret = true;
+ break;
+ case DT_TYPE_FREESTYLE_EDGE:
+ *r_threshold = true;
+ ret = true;
+ break;
+ /* Loop/Poly data */
+ case DT_TYPE_UV:
+ ret = true;
+ break;
+ case DT_TYPE_VCOL:
+ *r_advanced_mixing = true;
+ *r_threshold = true;
+ ret = true;
+ break;
+ case DT_TYPE_LNOR:
+ *r_advanced_mixing = true;
+ ret = true;
+ break;
+ case DT_TYPE_SHARP_FACE:
+ *r_threshold = true;
+ ret = true;
+ break;
+ case DT_TYPE_FREESTYLE_FACE:
+ *r_threshold = true;
+ ret = true;
+ break;
+ }
+ }
+
+ return ret;
+}
+
+int BKE_object_data_transfer_get_dttypes_item_types(const int dtdata_types)
+{
+ int i, ret = 0;
+
+ for (i = 0; (i < DT_TYPE_MAX) && (ret ^ (ME_VERT | ME_EDGE | ME_LOOP | ME_POLY)); i++) {
+ const int dtdata_type = 1 << i;
+
+ if (!(dtdata_types & dtdata_type)) {
+ continue;
+ }
+
+ if (DT_DATATYPE_IS_VERT(dtdata_type)) {
+ ret |= ME_VERT;
+ }
+ if (DT_DATATYPE_IS_EDGE(dtdata_type)) {
+ ret |= ME_EDGE;
+ }
+ if (DT_DATATYPE_IS_LOOP(dtdata_type)) {
+ ret |= ME_LOOP;
+ }
+ if (DT_DATATYPE_IS_POLY(dtdata_type)) {
+ ret |= ME_POLY;
+ }
+ }
+
+ return ret;
+}
+
+int BKE_object_data_transfer_dttype_to_cdtype(const int dtdata_type)
+{
+ switch (dtdata_type) {
+ case DT_TYPE_MDEFORMVERT:
+ return CD_FAKE_MDEFORMVERT;
+ case DT_TYPE_SHAPEKEY:
+ return CD_FAKE_SHAPEKEY;
+ case DT_TYPE_SKIN:
+ return CD_MVERT_SKIN;
+ case DT_TYPE_BWEIGHT_VERT:
+ return CD_FAKE_BWEIGHT;
+
+ case DT_TYPE_SHARP_EDGE:
+ return CD_FAKE_SHARP;
+ case DT_TYPE_SEAM:
+ return CD_FAKE_SEAM;
+ case DT_TYPE_CREASE:
+ return CD_FAKE_CREASE;
+ case DT_TYPE_BWEIGHT_EDGE:
+ return CD_FAKE_BWEIGHT;
+ case DT_TYPE_FREESTYLE_EDGE:
+ return CD_FREESTYLE_EDGE;
+
+ case DT_TYPE_UV:
+ return CD_FAKE_UV;
+ case DT_TYPE_SHARP_FACE:
+ return CD_FAKE_SHARP;
+ case DT_TYPE_FREESTYLE_FACE:
+ return CD_FREESTYLE_FACE;
+
+ case DT_TYPE_VCOL:
+ return CD_MLOOPCOL;
+ case DT_TYPE_LNOR:
+ return CD_FAKE_LNOR;
+
+ default:
+ BLI_assert(0);
+ }
+ return 0; /* Should never be reached! */
+}
+
+int BKE_object_data_transfer_dttype_to_srcdst_index(const int dtdata_type)
+{
+ switch (dtdata_type) {
+ case DT_TYPE_MDEFORMVERT:
+ return DT_MULTILAYER_INDEX_MDEFORMVERT;
+ case DT_TYPE_SHAPEKEY:
+ return DT_MULTILAYER_INDEX_SHAPEKEY;
+ case DT_TYPE_UV:
+ return DT_MULTILAYER_INDEX_UV;
+ case DT_TYPE_VCOL:
+ return DT_MULTILAYER_INDEX_VCOL;
+ default:
+ return DT_MULTILAYER_INDEX_INVALID;
+ }
+}
+
+/* ********** */
+
+/* Generic pre/post processing, only used by custom loop normals currently. */
+
+static void data_transfer_dtdata_type_preprocess(
+ Object *UNUSED(ob_src), Object *UNUSED(ob_dst), DerivedMesh *dm_src, DerivedMesh *dm_dst, Mesh *me_dst,
+ const int dtdata_type, const bool dirty_nors_dst, const bool use_split_nors_src, const float split_angle_src)
+{
+ if (dtdata_type == DT_TYPE_LNOR) {
+ /* Compute custom normals into regular loop normals, which will be used for the transfer. */
+ MVert *verts_dst = dm_dst ? dm_dst->getVertArray(dm_dst) : me_dst->mvert;
+ const int num_verts_dst = dm_dst ? dm_dst->getNumVerts(dm_dst) : me_dst->totvert;
+ MEdge *edges_dst = dm_dst ? dm_dst->getEdgeArray(dm_dst) : me_dst->medge;
+ const int num_edges_dst = dm_dst ? dm_dst->getNumEdges(dm_dst) : me_dst->totedge;
+ MPoly *polys_dst = dm_dst ? dm_dst->getPolyArray(dm_dst) : me_dst->mpoly;
+ const int num_polys_dst = dm_dst ? dm_dst->getNumPolys(dm_dst) : me_dst->totpoly;
+ MLoop *loops_dst = dm_dst ? dm_dst->getLoopArray(dm_dst) : me_dst->mloop;
+ const int num_loops_dst = dm_dst ? dm_dst->getNumLoops(dm_dst) : me_dst->totloop;
+ CustomData *pdata_dst = dm_dst ? dm_dst->getPolyDataLayout(dm_dst) : &me_dst->pdata;
+ CustomData *ldata_dst = dm_dst ? dm_dst->getLoopDataLayout(dm_dst) : &me_dst->ldata;
+
+ const bool use_split_nors_dst = (me_dst->flag & ME_AUTOSMOOTH) != 0;
+ const float split_angle_dst = me_dst->smoothresh;
+
+ dm_src->calcLoopNormals(dm_src, use_split_nors_src, split_angle_src);
+
+ if (dm_dst) {
+ dm_dst->calcLoopNormals(dm_dst, use_split_nors_dst, split_angle_dst);
+ }
+ else {
+ float (*poly_nors_dst)[3];
+ float (*loop_nors_dst)[3];
+ short (*custom_nors_dst)[2] = CustomData_get_layer(ldata_dst, CD_CUSTOMLOOPNORMAL);
+
+ /* Cache poly nors into a temp CDLayer. */
+ poly_nors_dst = CustomData_get_layer(pdata_dst, CD_NORMAL);
+ if (dirty_nors_dst || !poly_nors_dst) {
+ if (!poly_nors_dst) {
+ poly_nors_dst = CustomData_add_layer(pdata_dst, CD_NORMAL, CD_CALLOC, NULL, num_polys_dst);
+ CustomData_set_layer_flag(pdata_dst, CD_NORMAL, CD_FLAG_TEMPORARY);
+ }
+ BKE_mesh_calc_normals_poly(verts_dst, num_verts_dst, loops_dst, polys_dst,
+ num_loops_dst, num_polys_dst, poly_nors_dst, true);
+ }
+ /* Cache loop nors into a temp CDLayer. */
+ loop_nors_dst = CustomData_get_layer(ldata_dst, CD_NORMAL);
+ if (dirty_nors_dst || loop_nors_dst) {
+ if (!loop_nors_dst) {
+ loop_nors_dst = CustomData_add_layer(ldata_dst, CD_NORMAL, CD_CALLOC, NULL, num_loops_dst);
+ CustomData_set_layer_flag(ldata_dst, CD_NORMAL, CD_FLAG_TEMPORARY);
+ }
+ BKE_mesh_normals_loop_split(verts_dst, num_verts_dst, edges_dst, num_edges_dst,
+ loops_dst, loop_nors_dst, num_loops_dst,
+ polys_dst, (const float (*)[3])poly_nors_dst, num_polys_dst,
+ use_split_nors_dst, split_angle_dst, NULL, custom_nors_dst, NULL);
+ }
+ }
+ }
+}
+
+static void data_transfer_dtdata_type_postprocess(
+ Object *UNUSED(ob_src), Object *UNUSED(ob_dst), DerivedMesh *UNUSED(dm_src), DerivedMesh *dm_dst, Mesh *me_dst,
+ const int dtdata_type, const bool changed)
+{
+ if (dtdata_type == DT_TYPE_LNOR) {
+ /* Bake edited destination loop normals into custom normals again. */
+ MVert *verts_dst = dm_dst ? dm_dst->getVertArray(dm_dst) : me_dst->mvert;
+ const int num_verts_dst = dm_dst ? dm_dst->getNumVerts(dm_dst) : me_dst->totvert;
+ MEdge *edges_dst = dm_dst ? dm_dst->getEdgeArray(dm_dst) : me_dst->medge;
+ const int num_edges_dst = dm_dst ? dm_dst->getNumEdges(dm_dst) : me_dst->totedge;
+ MPoly *polys_dst = dm_dst ? dm_dst->getPolyArray(dm_dst) : me_dst->mpoly;
+ const int num_polys_dst = dm_dst ? dm_dst->getNumPolys(dm_dst) : me_dst->totpoly;
+ MLoop *loops_dst = dm_dst ? dm_dst->getLoopArray(dm_dst) : me_dst->mloop;
+ const int num_loops_dst = dm_dst ? dm_dst->getNumLoops(dm_dst) : me_dst->totloop;
+ CustomData *pdata_dst = dm_dst ? dm_dst->getPolyDataLayout(dm_dst) : &me_dst->pdata;
+ CustomData *ldata_dst = dm_dst ? dm_dst->getLoopDataLayout(dm_dst) : &me_dst->ldata;
+
+ const float (*poly_nors_dst)[3] = CustomData_get_layer(pdata_dst, CD_NORMAL);
+ float (*loop_nors_dst)[3] = CustomData_get_layer(ldata_dst, CD_NORMAL);
+ short (*custom_nors_dst)[2] = CustomData_get_layer(ldata_dst, CD_CUSTOMLOOPNORMAL);
+
+ BLI_assert(poly_nors_dst);
+
+ if (!changed) {
+ return;
+ }
+
+ if (!custom_nors_dst) {
+ custom_nors_dst = CustomData_add_layer(ldata_dst, CD_CUSTOMLOOPNORMAL, CD_CALLOC, NULL, num_loops_dst);
+ }
+
+ /* Note loop_nors_dst contains our custom normals as transferred from source... */
+ BKE_mesh_normals_loop_custom_set(verts_dst, num_verts_dst, edges_dst, num_edges_dst,
+ loops_dst, loop_nors_dst, num_loops_dst,
+ polys_dst, poly_nors_dst, num_polys_dst,
+ custom_nors_dst);
+ }
+}
+
+/* ********** */
+
+static MeshRemapIslandsCalc data_transfer_get_loop_islands_generator(const int cddata_type)
+{
+ switch (cddata_type) {
+ case CD_FAKE_UV:
+ return BKE_mesh_calc_islands_loop_poly_uv;
+ break;
+ default:
+ break;
+ }
+ return NULL;
+}
+
+float data_transfer_interp_float_do(
+ const int mix_mode, const float val_dst, const float val_src, const float mix_factor)
+{
+ float val_ret;
+
+ if (((mix_mode == CDT_MIX_REPLACE_ABOVE_THRESHOLD && (val_dst < mix_factor)) ||
+ (mix_mode == CDT_MIX_REPLACE_BELOW_THRESHOLD && (val_dst > mix_factor))))
+ {
+ return val_dst; /* Do not affect destination. */
+ }
+
+ switch (mix_mode) {
+ case CDT_MIX_REPLACE_ABOVE_THRESHOLD:
+ case CDT_MIX_REPLACE_BELOW_THRESHOLD:
+ return val_src;
+ case CDT_MIX_MIX:
+ val_ret = (val_dst + val_src) * 0.5f;
+ break;
+ case CDT_MIX_ADD:
+ val_ret = val_dst + val_src;
+ break;
+ case CDT_MIX_SUB:
+ val_ret = val_dst - val_src;
+ break;
+ case CDT_MIX_MUL:
+ val_ret = val_dst * val_src;
+ break;
+ case CDT_MIX_TRANSFER:
+ default:
+ val_ret = val_src;
+ break;
+ }
+ return interpf(val_ret, val_dst, mix_factor);
+}
+
+static void data_transfer_interp_char(
+ const CustomDataTransferLayerMap *laymap, void *dest,
+ const void **sources, const float *weights, const int count, const float mix_factor)
+{
+ const char **data_src = (const char **)sources;
+ char *data_dst = (char *)dest;
+
+ const int mix_mode = laymap->mix_mode;
+ float val_src = 0.0f;
+ const float val_dst = (float)(*data_dst) / 255.0f;
+
+ int i;
+
+ for (i = count; i--;) {
+ val_src += ((float)(*data_src[i]) / 255.0f) * weights[i];
+ }
+
+ val_src = data_transfer_interp_float_do(mix_mode, val_dst, val_src, mix_factor);
+
+ CLAMP(val_src, 0.0f, 1.0f);
+
+ *data_dst = (char)(val_src * 255.0f);
+}
+
+/* Helpers to match sources and destinations data layers (also handles 'conversions' in CD_FAKE cases). */
+
+void data_transfer_layersmapping_add_item(
+ ListBase *r_map, const int cddata_type, const int mix_mode, const float mix_factor, const float *mix_weights,
+ const void *data_src, void *data_dst, const int data_src_n, const int data_dst_n,
+ const size_t elem_size, const size_t data_size, const size_t data_offset, const uint64_t data_flag,
+ cd_datatransfer_interp interp)
+{
+ CustomDataTransferLayerMap *item = MEM_mallocN(sizeof(*item), __func__);
+
+ BLI_assert(data_dst != NULL);
+
+ item->data_type = cddata_type;
+ item->mix_mode = mix_mode;
+ item->mix_factor = mix_factor;
+ item->mix_weights = mix_weights;
+
+ item->data_src = data_src;
+ item->data_dst = data_dst;
+ item->data_src_n = data_src_n;
+ item->data_dst_n = data_dst_n;
+ item->elem_size = elem_size;
+
+ item->data_size = data_size;
+ item->data_offset = data_offset;
+ item->data_flag = data_flag;
+
+ item->interp = interp;
+
+ BLI_addtail(r_map, item);
+}
+
+static void data_transfer_layersmapping_add_item_cd(
+ ListBase *r_map, const int cddata_type, const int mix_mode, const float mix_factor, const float *mix_weights,
+ void *data_src, void *data_dst)
+{
+ data_transfer_layersmapping_add_item(
+ r_map, cddata_type, mix_mode, mix_factor, mix_weights, data_src, data_dst,
+ 0, 0, 0, 0, 0, 0, NULL);
+}
+
+/* Note: All those layer mapping handlers return false *only* if they were given invalid parameters.
+ * This means that even if they do nothing, they will return true if all given parameters were OK.
+ * Also, r_map may be NULL, in which case they will 'only' create/delete destination layers according
+ * to given parameters.
+ */
+
+static bool data_transfer_layersmapping_cdlayers_multisrc_to_dst(
+ ListBase *r_map, const int cddata_type, const int mix_mode, const float mix_factor, const float *mix_weights,
+ const int num_elem_dst, const bool use_create, const bool use_delete,
+ CustomData *cd_src, CustomData *cd_dst, const bool use_dupref_dst,
+ const int tolayers, bool *use_layers_src, const int num_layers_src)
+{
+ void *data_src, *data_dst = NULL;
+ int idx_src = num_layers_src;
+ int idx_dst, tot_dst = CustomData_number_of_layers(cd_dst, cddata_type);
+ bool *data_dst_to_delete = NULL;
+
+ if (!use_layers_src) {
+ /* No source at all, we can only delete all dest if requested... */
+ if (use_delete) {
+ idx_dst = tot_dst;
+ while (idx_dst--) {
+ CustomData_free_layer(cd_dst, cddata_type, num_elem_dst, idx_dst);
+ }
+ }
+ return true;
+ }
+
+ switch (tolayers) {
+ case DT_LAYERS_INDEX_DST:
+ idx_dst = tot_dst;
+
+ /* Find last source actually used! */
+ while (idx_src-- && !use_layers_src[idx_src]);
+ idx_src++;
+
+ if (idx_dst < idx_src) {
+ if (!use_create) {
+ return true;
+ }
+ /* Create as much data layers as necessary! */
+ for (; idx_dst < idx_src; idx_dst++) {
+ CustomData_add_layer(cd_dst, cddata_type, CD_CALLOC, NULL, num_elem_dst);
+ }
+ }
+ else if (use_delete && idx_dst > idx_src) {
+ while (idx_dst-- > idx_src) {
+ CustomData_free_layer(cd_dst, cddata_type, num_elem_dst, idx_dst);
+ }
+ }
+ if (r_map) {
+ while (idx_src--) {
+ if (!use_layers_src[idx_src]) {
+ continue;
+ }
+ data_src = CustomData_get_layer_n(cd_src, cddata_type, idx_src);
+ /* If dest is a derivedmesh, we do not want to overwrite cdlayers of org mesh! */
+ if (use_dupref_dst) {
+ data_dst = CustomData_duplicate_referenced_layer_n(cd_dst, cddata_type, idx_src, num_elem_dst);
+ }
+ else {
+ data_dst = CustomData_get_layer_n(cd_dst, cddata_type, idx_src);
+ }
+ data_transfer_layersmapping_add_item_cd(r_map, cddata_type, mix_mode, mix_factor, mix_weights,
+ data_src, data_dst);
+ }
+ }
+ break;
+ case DT_LAYERS_NAME_DST:
+ if (use_delete) {
+ if (tot_dst) {
+ data_dst_to_delete = MEM_mallocN(sizeof(*data_dst_to_delete) * (size_t)tot_dst, __func__);
+ memset(data_dst_to_delete, true, sizeof(*data_dst_to_delete) * (size_t)tot_dst);
+ }
+ }
+
+ while (idx_src--) {
+ const char *name;
+
+ if (!use_layers_src[idx_src]) {
+ continue;
+ }
+
+ name = CustomData_get_layer_name(cd_src, cddata_type, idx_src);
+ data_src = CustomData_get_layer_n(cd_src, cddata_type, idx_src);
+
+ if ((idx_dst = CustomData_get_named_layer(cd_dst, cddata_type, name)) == -1) {
+ if (!use_create) {
+ if (r_map) {
+ BLI_freelistN(r_map);
+ }
+ return true;
+ }
+ CustomData_add_layer_named(cd_dst, cddata_type, CD_CALLOC, NULL, num_elem_dst, name);
+ idx_dst = CustomData_get_named_layer(cd_dst, cddata_type, name);
+ }
+ else if (data_dst_to_delete) {
+ data_dst_to_delete[idx_dst] = false;
+ }
+ if (r_map) {
+ /* If dest is a derivedmesh, we do not want to overwrite cdlayers of org mesh! */
+ if (use_dupref_dst) {
+ data_dst = CustomData_duplicate_referenced_layer_n(cd_dst, cddata_type, idx_dst, num_elem_dst);
+ }
+ else {
+ data_dst = CustomData_get_layer_n(cd_dst, cddata_type, idx_dst);
+ }
+ data_transfer_layersmapping_add_item_cd(r_map, cddata_type, mix_mode, mix_factor, mix_weights,
+ data_src, data_dst);
+ }
+ }
+
+ if (data_dst_to_delete) {
+ /* Note: This won't affect newly created layers, if any, since tot_dst has not been updated!
+ * Also, looping backward ensures us we do not suffer from index shifting when deleting a layer.
+ */
+ for (idx_dst = tot_dst; idx_dst--;) {
+ if (data_dst_to_delete[idx_dst]) {
+ CustomData_free_layer(cd_dst, cddata_type, num_elem_dst, idx_dst);
+ }
+ }
+
+ MEM_freeN(data_dst_to_delete);
+ }
+ break;
+ default:
+ return false;
+ }
+
+ return true;
+}
+
+static bool data_transfer_layersmapping_cdlayers(
+ ListBase *r_map, const int cddata_type, const int mix_mode, const float mix_factor, const float *mix_weights,
+ const int num_elem_dst, const bool use_create, const bool use_delete,
+ CustomData *cd_src, CustomData *cd_dst, const bool use_dupref_dst,
+ const int fromlayers, const int tolayers)
+{
+ int idx_src, idx_dst;
+ void *data_src, *data_dst = NULL;
+
+ if (CustomData_layertype_is_singleton(cddata_type)) {
+ if (!(data_src = CustomData_get_layer(cd_src, cddata_type))) {
+ if (use_delete) {
+ CustomData_free_layer(cd_dst, cddata_type, num_elem_dst, 0);
+ }
+ return true;
+ }
+
+ data_dst = CustomData_get_layer(cd_dst, cddata_type);
+ if (!data_dst) {
+ if (!use_create) {
+ return true;
+ }
+ data_dst = CustomData_add_layer(cd_dst, cddata_type, CD_CALLOC, NULL, num_elem_dst);
+ }
+ else if (use_dupref_dst && r_map) {
+ /* If dest is a derivedmesh, we do not want to overwrite cdlayers of org mesh! */
+ data_dst = CustomData_duplicate_referenced_layer(cd_dst, cddata_type, num_elem_dst);
+ }
+
+ if (r_map) {
+ data_transfer_layersmapping_add_item_cd(r_map, cddata_type, mix_mode, mix_factor, mix_weights,
+ data_src, data_dst);
+ }
+ }
+ else if (fromlayers == DT_LAYERS_ACTIVE_SRC || fromlayers >= 0) {
+ /* Note: use_delete has not much meaning in this case, ignored. */
+
+ if (fromlayers >= 0) { /* Real-layer index */
+ idx_src = fromlayers;
+ }
+ else {
+ if ((idx_src = CustomData_get_active_layer(cd_src, cddata_type)) == -1) {
+ return true;
+ }
+ }
+ data_src = CustomData_get_layer_n(cd_src, cddata_type, idx_src);
+ if (!data_src) {
+ return true;
+ }
+
+ if (tolayers >= 0) { /* Real-layer index */
+ idx_dst = tolayers;
+ /* If dest is a derivedmesh, we do not want to overwrite cdlayers of org mesh! */
+ if (use_dupref_dst && r_map) {
+ data_dst = CustomData_duplicate_referenced_layer_n(cd_dst, cddata_type, idx_dst, num_elem_dst);
+ }
+ else {
+ data_dst = CustomData_get_layer_n(cd_dst, cddata_type, idx_dst);
+ }
+ }
+ else if (tolayers == DT_LAYERS_ACTIVE_DST) {
+ if ((idx_dst = CustomData_get_active_layer(cd_dst, cddata_type)) == -1) {
+ if (!use_create) {
+ return true;
+ }
+ data_dst = CustomData_add_layer(cd_dst, cddata_type, CD_CALLOC, NULL, num_elem_dst);
+ }
+ else {
+ /* If dest is a derivedmesh, we do not want to overwrite cdlayers of org mesh! */
+ if (use_dupref_dst && r_map) {
+ data_dst = CustomData_duplicate_referenced_layer_n(cd_dst, cddata_type, idx_dst, num_elem_dst);
+ }
+ else {
+ data_dst = CustomData_get_layer_n(cd_dst, cddata_type, idx_dst);
+ }
+ }
+ }
+ else if (tolayers == DT_LAYERS_INDEX_DST) {
+ int num = CustomData_number_of_layers(cd_dst, cddata_type);
+ idx_dst = idx_src;
+ if (num <= idx_dst) {
+ if (!use_create) {
+ return true;
+ }
+ /* Create as much data layers as necessary! */
+ for (; num <= idx_dst; num++) {
+ CustomData_add_layer(cd_dst, cddata_type, CD_CALLOC, NULL, num_elem_dst);
+ }
+ }
+ /* If dest is a derivedmesh, we do not want to overwrite cdlayers of org mesh! */
+ if (use_dupref_dst && r_map) {
+ data_dst = CustomData_duplicate_referenced_layer_n(cd_dst, cddata_type, idx_dst, num_elem_dst);
+ }
+ else {
+ data_dst = CustomData_get_layer_n(cd_dst, cddata_type, idx_dst);
+ }
+ }
+ else if (tolayers == DT_LAYERS_NAME_DST) {
+ const char *name = CustomData_get_layer_name(cd_src, cddata_type, idx_src);
+ if ((idx_dst = CustomData_get_named_layer(cd_dst, cddata_type, name)) == -1) {
+ if (!use_create) {
+ return true;
+ }
+ CustomData_add_layer_named(cd_dst, cddata_type, CD_CALLOC, NULL, num_elem_dst, name);
+ idx_dst = CustomData_get_named_layer(cd_dst, cddata_type, name);
+ }
+ /* If dest is a derivedmesh, we do not want to overwrite cdlayers of org mesh! */
+ if (use_dupref_dst && r_map) {
+ data_dst = CustomData_duplicate_referenced_layer_n(cd_dst, cddata_type, idx_dst, num_elem_dst);
+ }
+ else {
+ data_dst = CustomData_get_layer_n(cd_dst, cddata_type, idx_dst);
+ }
+ }
+ else {
+ return false;
+ }
+
+ if (!data_dst) {
+ return false;
+ }
+
+ if (r_map) {
+ data_transfer_layersmapping_add_item_cd(
+ r_map, cddata_type, mix_mode, mix_factor, mix_weights, data_src, data_dst);
+ }
+ }
+ else if (fromlayers == DT_LAYERS_ALL_SRC) {
+ int num_src = CustomData_number_of_layers(cd_src, cddata_type);
+ bool *use_layers_src = num_src ? MEM_mallocN(sizeof(*use_layers_src) * (size_t)num_src, __func__) : NULL;
+ bool ret;
+
+ if (use_layers_src) {
+ memset(use_layers_src, true, sizeof(*use_layers_src) * num_src);
+ }
+
+ ret = data_transfer_layersmapping_cdlayers_multisrc_to_dst(
+ r_map, cddata_type, mix_mode, mix_factor, mix_weights,
+ num_elem_dst, use_create, use_delete, cd_src, cd_dst, use_dupref_dst,
+ tolayers, use_layers_src, num_src);
+
+ if (use_layers_src) {
+ MEM_freeN(use_layers_src);
+ }
+ return ret;
+ }
+ else {
+ return false;
+ }
+
+ return true;
+}
+
+static bool data_transfer_layersmapping_generate(
+ ListBase *r_map, Object *ob_src, Object *ob_dst, DerivedMesh *dm_src, DerivedMesh *dm_dst, Mesh *me_dst,
+ const int elem_type, int cddata_type, int mix_mode, float mix_factor, const float *mix_weights,
+ const int num_elem_dst, const bool use_create, const bool use_delete, const int fromlayers, const int tolayers)
+{
+ CustomData *cd_src, *cd_dst;
+
+ if (elem_type == ME_VERT) {
+ if (!(cddata_type & CD_FAKE)) {
+ cd_src = dm_src->getVertDataLayout(dm_src);
+ cd_dst = dm_dst ? dm_dst->getVertDataLayout(dm_dst) : &me_dst->vdata;
+
+ if (!data_transfer_layersmapping_cdlayers(r_map, cddata_type, mix_mode, mix_factor, mix_weights,
+ num_elem_dst, use_create, use_delete,
+ cd_src, cd_dst, dm_dst != NULL,
+ fromlayers, tolayers))
+ {
+ /* We handle specific source selection cases here. */
+ return false;
+ }
+ return true;
+ }
+ else if (cddata_type == CD_FAKE_BWEIGHT) {
+ const size_t elem_size = sizeof(*((MVert *)NULL));
+ const size_t data_size = sizeof(((MVert *)NULL)->bweight);
+ const size_t data_offset = offsetof(MVert, bweight);
+ const uint64_t data_flag = 0;
+
+ if (!(dm_src->cd_flag & ME_CDFLAG_VERT_BWEIGHT)) {
+ if (use_delete && !dm_dst) {
+ me_dst->cd_flag &= ~ME_CDFLAG_VERT_BWEIGHT;
+ }
+ return true;
+ }
+ if (dm_dst) {
+ dm_dst->cd_flag |= ME_CDFLAG_VERT_BWEIGHT;
+ }
+ else {
+ me_dst->cd_flag |= ME_CDFLAG_VERT_BWEIGHT;
+ }
+ if (r_map) {
+ data_transfer_layersmapping_add_item(r_map, cddata_type, mix_mode, mix_factor, mix_weights,
+ dm_src->getVertArray(dm_src),
+ dm_dst ? dm_dst->getVertArray(dm_dst) : me_dst->mvert,
+ dm_src->getNumVerts(dm_src),
+ dm_dst ? dm_dst->getNumVerts(dm_dst) : me_dst->totvert,
+ elem_size, data_size, data_offset, data_flag,
+ data_transfer_interp_char);
+ }
+ return true;
+ }
+ else if (cddata_type == CD_FAKE_MDEFORMVERT) {
+ bool ret;
+
+ cd_src = dm_src->getVertDataLayout(dm_src);
+ cd_dst = dm_dst ? dm_dst->getVertDataLayout(dm_dst) : &me_dst->vdata;
+
+ ret = data_transfer_layersmapping_vgroups(r_map, mix_mode, mix_factor, mix_weights,
+ num_elem_dst, use_create, use_delete,
+ ob_src, ob_dst, cd_src, cd_dst, dm_dst != NULL,
+ fromlayers, tolayers);
+
+ /* Mesh stores its dvert in a specific pointer too. :( */
+ me_dst->dvert = CustomData_get_layer(&me_dst->vdata, CD_MDEFORMVERT);
+ return ret;
+ }
+ else if (cddata_type == CD_FAKE_SHAPEKEY) {
+ /* TODO: leaving shapekeys asside for now, quite specific case, since we can't access them from MVert :/ */
+ return false;
+ }
+ }
+ else if (elem_type == ME_EDGE) {
+ if (!(cddata_type & CD_FAKE)) { /* Unused for edges, currently... */
+ cd_src = dm_src->getEdgeDataLayout(dm_src);
+ cd_dst = dm_dst ? dm_dst->getEdgeDataLayout(dm_dst) : &me_dst->edata;
+
+ if (!data_transfer_layersmapping_cdlayers(r_map, cddata_type, mix_mode, mix_factor, mix_weights,
+ num_elem_dst, use_create, use_delete,
+ cd_src, cd_dst, dm_dst != NULL,
+ fromlayers, tolayers))
+ {
+ /* We handle specific source selection cases here. */
+ return false;
+ }
+ return true;
+ }
+ else if (cddata_type == CD_FAKE_CREASE) {
+ const size_t elem_size = sizeof(*((MEdge *)NULL));
+ const size_t data_size = sizeof(((MEdge *)NULL)->crease);
+ const size_t data_offset = offsetof(MEdge, crease);
+ const uint64_t data_flag = 0;
+
+ if (!(dm_src->cd_flag & ME_CDFLAG_EDGE_CREASE)) {
+ if (use_delete && !dm_dst) {
+ me_dst->cd_flag &= ~ME_CDFLAG_EDGE_CREASE;
+ }
+ return true;
+ }
+ if (dm_dst) {
+ dm_dst->cd_flag |= ME_CDFLAG_EDGE_CREASE;
+ }
+ else {
+ me_dst->cd_flag |= ME_CDFLAG_EDGE_CREASE;
+ }
+ if (r_map) {
+ data_transfer_layersmapping_add_item(r_map, cddata_type, mix_mode, mix_factor, mix_weights,
+ dm_src->getEdgeArray(dm_src),
+ dm_dst ? dm_dst->getEdgeArray(dm_dst) : me_dst->medge,
+ dm_src->getNumEdges(dm_src),
+ dm_dst ? dm_dst->getNumEdges(dm_dst) : me_dst->totedge,
+ elem_size, data_size, data_offset, data_flag,
+ data_transfer_interp_char);
+ }
+ return true;
+ }
+ else if (cddata_type == CD_FAKE_BWEIGHT) {
+ const size_t elem_size = sizeof(*((MEdge *)NULL));
+ const size_t data_size = sizeof(((MEdge *)NULL)->bweight);
+ const size_t data_offset = offsetof(MEdge, bweight);
+ const uint64_t data_flag = 0;
+
+ if (!(dm_src->cd_flag & ME_CDFLAG_EDGE_BWEIGHT)) {
+ if (use_delete && !dm_dst) {
+ me_dst->cd_flag &= ~ME_CDFLAG_EDGE_BWEIGHT;
+ }
+ return true;
+ }
+ if (dm_dst) {
+ dm_dst->cd_flag |= ME_CDFLAG_EDGE_BWEIGHT;
+ }
+ else {
+ me_dst->cd_flag |= ME_CDFLAG_EDGE_BWEIGHT;
+ }
+ if (r_map) {
+ data_transfer_layersmapping_add_item(r_map, cddata_type, mix_mode, mix_factor, mix_weights,
+ dm_src->getEdgeArray(dm_src),
+ dm_dst ? dm_dst->getEdgeArray(dm_dst) : me_dst->medge,
+ dm_src->getNumEdges(dm_src),
+ dm_dst ? dm_dst->getNumEdges(dm_dst) : me_dst->totedge,
+ elem_size, data_size, data_offset, data_flag,
+ data_transfer_interp_char);
+ }
+ return true;
+ }
+ else if (r_map && ELEM(cddata_type, CD_FAKE_SHARP, CD_FAKE_SEAM)) {
+ const size_t elem_size = sizeof(*((MEdge *)NULL));
+ const size_t data_size = sizeof(((MEdge *)NULL)->flag);
+ const size_t data_offset = offsetof(MEdge, flag);
+ const uint64_t data_flag = (cddata_type == CD_FAKE_SHARP) ? ME_SHARP : ME_SEAM;
+
+ data_transfer_layersmapping_add_item(
+ r_map, cddata_type, mix_mode, mix_factor, mix_weights,
+ dm_src->getEdgeArray(dm_src),
+ dm_dst ? dm_dst->getEdgeArray(dm_dst) : me_dst->medge,
+ dm_src->getNumEdges(dm_src),
+ dm_dst ? dm_dst->getNumEdges(dm_dst) : me_dst->totedge,
+ elem_size, data_size, data_offset, data_flag, NULL);
+ return true;
+ }
+ else {
+ return false;
+ }
+ }
+ else if (elem_type == ME_LOOP) {
+ if (cddata_type == CD_FAKE_UV) {
+ cddata_type = CD_MLOOPUV;
+ }
+ else if (cddata_type == CD_FAKE_LNOR) {
+ /* Preprocess should have generated it, Postprocess will convert it back to CD_CUSTOMLOOPNORMAL. */
+ cddata_type = CD_NORMAL;
+ }
+
+ if (!(cddata_type & CD_FAKE)) {
+ cd_src = dm_src->getLoopDataLayout(dm_src);
+ cd_dst = dm_dst ? dm_dst->getLoopDataLayout(dm_dst) : &me_dst->ldata;
+
+ if (!data_transfer_layersmapping_cdlayers(
+ r_map, cddata_type, mix_mode, mix_factor, mix_weights,
+ num_elem_dst, use_create, use_delete, cd_src, cd_dst, dm_dst != NULL,
+ fromlayers, tolayers))
+ {
+ /* We handle specific source selection cases here. */
+ return false;
+ }
+ return true;
+ }
+ else {
+ return false;
+ }
+ }
+ else if (elem_type == ME_POLY) {
+ if (cddata_type == CD_FAKE_UV) {
+ cddata_type = CD_MTEXPOLY;
+ }
+
+ if (!(cddata_type & CD_FAKE)) {
+ cd_src = dm_src->getPolyDataLayout(dm_src);
+ cd_dst = dm_dst ? dm_dst->getPolyDataLayout(dm_dst) : &me_dst->pdata;
+
+ if (!data_transfer_layersmapping_cdlayers(
+ r_map, cddata_type, mix_mode, mix_factor, mix_weights,
+ num_elem_dst, use_create, use_delete, cd_src, cd_dst, dm_dst != NULL,
+ fromlayers, tolayers))
+ {
+ /* We handle specific source selection cases here. */
+ return false;
+ }
+ return true;
+ }
+ else if (r_map && cddata_type == CD_FAKE_SHARP) {
+ const size_t elem_size = sizeof(*((MPoly *)NULL));
+ const size_t data_size = sizeof(((MPoly *)NULL)->flag);
+ const size_t data_offset = offsetof(MPoly, flag);
+ const uint64_t data_flag = ME_SMOOTH;
+
+ data_transfer_layersmapping_add_item(
+ r_map, cddata_type, mix_mode, mix_factor, mix_weights,
+ dm_src->getPolyArray(dm_src),
+ dm_dst ? dm_dst->getPolyArray(dm_dst) : me_dst->mpoly,
+ dm_src->getNumPolys(dm_src),
+ dm_dst ? dm_dst->getNumPolys(dm_dst) : me_dst->totpoly,
+ elem_size, data_size, data_offset, data_flag, NULL);
+ return true;
+ }
+ else {
+ return false;
+ }
+ }
+
+ return false;
+}
+
+/**
+ * Transfer data *layout* of selected types from source to destination object.
+ * By default, it only creates new data layers if needed on \a ob_dst.
+ * If \a use_delete is true, it will also delete data layers on \a ob_dst that do not match those from \a ob_src,
+ * to get (as much as possible) exact copy of source data layout.
+ */
+void BKE_object_data_transfer_layout(
+ Scene *scene, Object *ob_src, Object *ob_dst, const int data_types, const bool use_delete,
+ const int fromlayers_select[DT_MULTILAYER_INDEX_MAX], const int tolayers_select[DT_MULTILAYER_INDEX_MAX])
+{
+ DerivedMesh *dm_src;
+ Mesh *me_dst;
+ int i;
+
+ const bool use_create = true; /* We always create needed layers here. */
+
+ CustomDataMask dm_src_mask = CD_MASK_BAREMESH;
+
+ BLI_assert((ob_src != ob_dst) && (ob_src->type == OB_MESH) && (ob_dst->type == OB_MESH));
+
+ me_dst = ob_dst->data;
+
+ /* Get source DM.*/
+ dm_src_mask |= BKE_object_data_transfer_dttypes_to_cdmask(data_types);
+ dm_src = mesh_get_derived_final(scene, ob_src, dm_src_mask);
+ if (!dm_src) {
+ return;
+ }
+
+ /* Check all possible data types. */
+ for (i = 0; i < DT_TYPE_MAX; i++) {
+ const int dtdata_type = 1 << i;
+ int cddata_type;
+ int fromlayers, tolayers, fromto_idx;
+
+ if (!(data_types & dtdata_type)) {
+ continue;
+ }
+
+ cddata_type = BKE_object_data_transfer_dttype_to_cdtype(dtdata_type);
+
+ fromto_idx = BKE_object_data_transfer_dttype_to_srcdst_index(dtdata_type);
+ if (fromto_idx != DT_MULTILAYER_INDEX_INVALID) {
+ fromlayers = fromlayers_select[fromto_idx];
+ tolayers = tolayers_select[fromto_idx];
+ }
+ else {
+ fromlayers = tolayers = 0;
+ }
+
+ if (DT_DATATYPE_IS_VERT(dtdata_type)) {
+ const int num_elem_dst = me_dst->totvert;
+
+ data_transfer_layersmapping_generate(
+ NULL, ob_src, ob_dst, dm_src, NULL, me_dst, ME_VERT, cddata_type, 0, 0.0f, NULL,
+ num_elem_dst, use_create, use_delete, fromlayers, tolayers);
+ }
+ if (DT_DATATYPE_IS_EDGE(dtdata_type)) {
+ const int num_elem_dst = me_dst->totedge;
+
+ data_transfer_layersmapping_generate(
+ NULL, ob_src, ob_dst, dm_src, NULL, me_dst, ME_EDGE, cddata_type, 0, 0.0f, NULL,
+ num_elem_dst, use_create, use_delete, fromlayers, tolayers);
+ }
+ if (DT_DATATYPE_IS_LOOP(dtdata_type)) {
+ const int num_elem_dst = me_dst->totloop;
+
+ data_transfer_layersmapping_generate(
+ NULL, ob_src, ob_dst, dm_src, NULL, me_dst, ME_LOOP, cddata_type, 0, 0.0f, NULL,
+ num_elem_dst, use_create, use_delete, fromlayers, tolayers);
+ }
+ if (DT_DATATYPE_IS_POLY(dtdata_type)) {
+ const int num_elem_dst = me_dst->totpoly;
+
+ data_transfer_layersmapping_generate(
+ NULL, ob_src, ob_dst, dm_src, NULL, me_dst, ME_POLY, cddata_type, 0, 0.0f, NULL,
+ num_elem_dst, use_create, use_delete, fromlayers, tolayers);
+ }
+ }
+}
+
+bool BKE_object_data_transfer_dm(
+ Scene *scene, Object *ob_src, Object *ob_dst, DerivedMesh *dm_dst, const int data_types, bool use_create,
+ const int map_vert_mode, const int map_edge_mode, const int map_loop_mode, const int map_poly_mode,
+ SpaceTransform *space_transform, const bool auto_transform,
+ const float max_distance, const float ray_radius, const float islands_handling_precision,
+ const int fromlayers_select[DT_MULTILAYER_INDEX_MAX], const int tolayers_select[DT_MULTILAYER_INDEX_MAX],
+ const int mix_mode, const float mix_factor, const char *vgroup_name, const bool invert_vgroup,
+ ReportList *reports)
+{
+#define VDATA 0
+#define EDATA 1
+#define LDATA 2
+#define PDATA 3
+#define DATAMAX 4
+
+ SpaceTransform auto_space_transform;
+
+ DerivedMesh *dm_src;
+ Mesh *me_dst, *me_src;
+ bool dirty_nors_dst = true; /* Assumed always true if not using a dm as destination. */
+ int i;
+
+ MDeformVert *mdef = NULL;
+ int vg_idx = -1;
+ float *weights[DATAMAX] = {NULL};
+
+ MeshPairRemap geom_map[DATAMAX] = {{0}};
+ bool geom_map_init[DATAMAX] = {0};
+ ListBase lay_map = {NULL};
+ bool changed = false;
+
+ const bool use_delete = false; /* We never delete data layers from destination here. */
+
+ CustomDataMask dm_src_mask = CD_MASK_BAREMESH;
+
+ BLI_assert((ob_src != ob_dst) && (ob_src->type == OB_MESH) && (ob_dst->type == OB_MESH));
+
+ me_dst = ob_dst->data;
+ me_src = ob_src->data;
+ if (dm_dst) {
+ dirty_nors_dst = (dm_dst->dirty & DM_DIRTY_NORMALS) != 0;
+ use_create = false; /* Never create needed custom layers on DM (modifier case). */
+ }
+
+ if (vgroup_name) {
+ if (dm_dst) {
+ mdef = dm_dst->getVertDataArray(dm_dst, CD_MDEFORMVERT);
+ }
+ else {
+ mdef = CustomData_get_layer(&me_dst->vdata, CD_MDEFORMVERT);
+ }
+ if (mdef) {
+ vg_idx = defgroup_name_index(ob_dst, vgroup_name);
+ }
+ }
+
+ /* Get source DM.*/
+ dm_src_mask |= BKE_object_data_transfer_dttypes_to_cdmask(data_types);
+ /* XXX Hack! In case this is being evaluated from dm stack, we cannot compute final dm,
+ * can lead to infinite recursion in case of dependency cycles of DataTransfer modifiers...
+ * Issue is, this means we cannot be sure to have requested cd layers in source.
+ */
+ dm_src = dm_dst ? ob_src->derivedFinal : mesh_get_derived_final(scene, ob_src, dm_src_mask);
+ if (!dm_src) {
+ return changed;
+ }
+
+ if (auto_transform) {
+ MVert *verts_dst = dm_dst ? dm_dst->getVertArray(dm_dst) : me_dst->mvert;
+ const int num_verts_dst = dm_dst ? dm_dst->getNumVerts(dm_dst) : me_dst->totvert;
+
+ if (space_transform == NULL) {
+ space_transform = &auto_space_transform;
+ }
+
+ BKE_mesh_remap_find_best_match_from_dm(verts_dst, num_verts_dst, dm_src, space_transform);
+ }
+
+ /* Check all possible data types.
+ * Note item mappings and dest mix weights are cached. */
+ for (i = 0; i < DT_TYPE_MAX; i++) {
+ const int dtdata_type = 1 << i;
+ int cddata_type;
+ int fromlayers, tolayers, fromto_idx;
+
+ if (!(data_types & dtdata_type)) {
+ continue;
+ }
+
+ data_transfer_dtdata_type_preprocess(ob_src, ob_dst, dm_src, dm_dst, me_dst,
+ dtdata_type, dirty_nors_dst,
+ (me_src->flag & ME_AUTOSMOOTH) != 0, me_src->smoothresh);
+
+ cddata_type = BKE_object_data_transfer_dttype_to_cdtype(dtdata_type);
+
+ fromto_idx = BKE_object_data_transfer_dttype_to_srcdst_index(dtdata_type);
+ if (fromto_idx != DT_MULTILAYER_INDEX_INVALID) {
+ fromlayers = fromlayers_select[fromto_idx];
+ tolayers = tolayers_select[fromto_idx];
+ }
+ else {
+ fromlayers = tolayers = 0;
+ }
+
+ if (DT_DATATYPE_IS_VERT(dtdata_type)) {
+ MVert *verts_dst = dm_dst ? dm_dst->getVertArray(dm_dst) : me_dst->mvert;
+ const int num_verts_dst = dm_dst ? dm_dst->getNumVerts(dm_dst) : me_dst->totvert;
+
+ if (!geom_map_init[VDATA]) {
+ const int num_verts_src = dm_src->getNumVerts(dm_src);
+
+ if ((map_vert_mode == MREMAP_MODE_TOPOLOGY) && (num_verts_dst != num_verts_src)) {
+ BKE_report(reports, RPT_ERROR,
+ "Source and destination meshes do not have the same amount of vertices, "
+ "'Topology' mapping cannot be used in this case");
+ return changed;
+ }
+ if (ELEM(0, num_verts_dst, num_verts_src)) {
+ BKE_report(reports, RPT_ERROR,
+ "Source or destination meshes do not have any vertices, cannot transfer vertex data");
+ return changed;
+ }
+
+ BKE_mesh_remap_calc_verts_from_dm(
+ map_vert_mode, space_transform, max_distance, ray_radius,
+ verts_dst, num_verts_dst, dirty_nors_dst, dm_src, &geom_map[VDATA]);
+ geom_map_init[VDATA] = true;
+ }
+
+ if (mdef && vg_idx != -1 && !weights[VDATA]) {
+ weights[VDATA] = MEM_mallocN(sizeof(*(weights[VDATA])) * (size_t)num_verts_dst, __func__);
+ BKE_defvert_extract_vgroup_to_vertweights(mdef, vg_idx, num_verts_dst, weights[VDATA], invert_vgroup);
+ }
+
+ if (data_transfer_layersmapping_generate(
+ &lay_map, ob_src, ob_dst, dm_src, dm_dst, me_dst, ME_VERT,
+ cddata_type, mix_mode, mix_factor, weights[VDATA],
+ num_verts_dst, use_create, use_delete, fromlayers, tolayers))
+ {
+ CustomDataTransferLayerMap *lay_mapit;
+
+ changed = (lay_map.first != NULL);
+
+ for (lay_mapit = lay_map.first; lay_mapit; lay_mapit = lay_mapit->next) {
+ CustomData_data_transfer(&geom_map[VDATA], lay_mapit);
+ }
+
+ BLI_freelistN(&lay_map);
+ }
+ }
+ if (DT_DATATYPE_IS_EDGE(dtdata_type)) {
+ MVert *verts_dst = dm_dst ? dm_dst->getVertArray(dm_dst) : me_dst->mvert;
+ const int num_verts_dst = dm_dst ? dm_dst->getNumVerts(dm_dst) : me_dst->totvert;
+ MEdge *edges_dst = dm_dst ? dm_dst->getEdgeArray(dm_dst) : me_dst->medge;
+ const int num_edges_dst = dm_dst ? dm_dst->getNumEdges(dm_dst) : me_dst->totedge;
+
+ if (!geom_map_init[EDATA]) {
+ const int num_edges_src = dm_src->getNumEdges(dm_src);
+
+ if ((map_edge_mode == MREMAP_MODE_TOPOLOGY) && (num_edges_dst != num_edges_src)) {
+ BKE_report(reports, RPT_ERROR,
+ "Source and destination meshes do not have the same amount of edges, "
+ "'Topology' mapping cannot be used in this case");
+ return changed;
+ }
+ if (ELEM(0, num_edges_dst, num_edges_src)) {
+ BKE_report(reports, RPT_ERROR,
+ "Source or destination meshes do not have any edges, cannot transfer edge data");
+ return changed;
+ }
+
+ BKE_mesh_remap_calc_edges_from_dm(
+ map_edge_mode, space_transform, max_distance, ray_radius,
+ verts_dst, num_verts_dst, edges_dst, num_edges_dst, dirty_nors_dst,
+ dm_src, &geom_map[EDATA]);
+ geom_map_init[EDATA] = true;
+ }
+
+ if (mdef && vg_idx != -1 && !weights[EDATA]) {
+ weights[EDATA] = MEM_mallocN(sizeof(*weights[EDATA]) * (size_t)num_edges_dst, __func__);
+ BKE_defvert_extract_vgroup_to_edgeweights(
+ mdef, vg_idx, num_verts_dst, edges_dst, num_edges_dst,
+ weights[EDATA], invert_vgroup);
+ }
+
+ if (data_transfer_layersmapping_generate(
+ &lay_map, ob_src, ob_dst, dm_src, dm_dst, me_dst, ME_EDGE,
+ cddata_type, mix_mode, mix_factor, weights[EDATA],
+ num_edges_dst, use_create, use_delete, fromlayers, tolayers))
+ {
+ CustomDataTransferLayerMap *lay_mapit;
+
+ changed = (lay_map.first != NULL);
+
+ for (lay_mapit = lay_map.first; lay_mapit; lay_mapit = lay_mapit->next) {
+ CustomData_data_transfer(&geom_map[EDATA], lay_mapit);
+ }
+
+ BLI_freelistN(&lay_map);
+ }
+ }
+ if (DT_DATATYPE_IS_LOOP(dtdata_type)) {
+ MVert *verts_dst = dm_dst ? dm_dst->getVertArray(dm_dst) : me_dst->mvert;
+ const int num_verts_dst = dm_dst ? dm_dst->getNumVerts(dm_dst) : me_dst->totvert;
+ MEdge *edges_dst = dm_dst ? dm_dst->getEdgeArray(dm_dst) : me_dst->medge;
+ const int num_edges_dst = dm_dst ? dm_dst->getNumEdges(dm_dst) : me_dst->totedge;
+ MPoly *polys_dst = dm_dst ? dm_dst->getPolyArray(dm_dst) : me_dst->mpoly;
+ const int num_polys_dst = dm_dst ? dm_dst->getNumPolys(dm_dst) : me_dst->totpoly;
+ MLoop *loops_dst = dm_dst ? dm_dst->getLoopArray(dm_dst) : me_dst->mloop;
+ const int num_loops_dst = dm_dst ? dm_dst->getNumLoops(dm_dst) : me_dst->totloop;
+ CustomData *pdata_dst = dm_dst ? dm_dst->getPolyDataLayout(dm_dst) : &me_dst->pdata;
+ CustomData *ldata_dst = dm_dst ? dm_dst->getLoopDataLayout(dm_dst) : &me_dst->ldata;
+
+ MeshRemapIslandsCalc island_callback = data_transfer_get_loop_islands_generator(cddata_type);
+
+ if (!geom_map_init[LDATA]) {
+ const int num_loops_src = dm_src->getNumLoops(dm_src);
+
+ if ((map_loop_mode == MREMAP_MODE_TOPOLOGY) && (num_loops_dst != num_loops_src)) {
+ BKE_report(reports, RPT_ERROR,
+ "Source and destination meshes do not have the same amount of face corners, "
+ "'Topology' mapping cannot be used in this case");
+ return changed;
+ }
+ if (ELEM(0, num_loops_dst, num_loops_src)) {
+ BKE_report(reports, RPT_ERROR,
+ "Source or destination meshes do not have any polygons, cannot transfer loop data");
+ return changed;
+ }
+
+ BKE_mesh_remap_calc_loops_from_dm(
+ map_loop_mode, space_transform, max_distance, ray_radius,
+ verts_dst, num_verts_dst, edges_dst, num_edges_dst,
+ loops_dst, num_loops_dst, polys_dst, num_polys_dst,
+ ldata_dst, pdata_dst,
+ (me_dst->flag & ME_AUTOSMOOTH) != 0, me_dst->smoothresh, dirty_nors_dst,
+ dm_src, (me_src->flag & ME_AUTOSMOOTH) != 0, me_src->smoothresh,
+ island_callback, islands_handling_precision, &geom_map[LDATA]);
+ geom_map_init[LDATA] = true;
+ }
+
+ if (mdef && vg_idx != -1 && !weights[LDATA]) {
+ weights[LDATA] = MEM_mallocN(sizeof(*weights[LDATA]) * (size_t)num_loops_dst, __func__);
+ BKE_defvert_extract_vgroup_to_loopweights(
+ mdef, vg_idx, num_verts_dst, loops_dst, num_loops_dst,
+ weights[LDATA], invert_vgroup);
+ }
+
+ if (data_transfer_layersmapping_generate(
+ &lay_map, ob_src, ob_dst, dm_src, dm_dst, me_dst, ME_LOOP,
+ cddata_type, mix_mode, mix_factor, weights[LDATA],
+ num_loops_dst, use_create, use_delete, fromlayers, tolayers))
+ {
+ CustomDataTransferLayerMap *lay_mapit;
+
+ changed = (lay_map.first != NULL);
+
+ for (lay_mapit = lay_map.first; lay_mapit; lay_mapit = lay_mapit->next) {
+ CustomData_data_transfer(&geom_map[LDATA], lay_mapit);
+ }
+
+ BLI_freelistN(&lay_map);
+ }
+ }
+ if (DT_DATATYPE_IS_POLY(dtdata_type)) {
+ MVert *verts_dst = dm_dst ? dm_dst->getVertArray(dm_dst) : me_dst->mvert;
+ const int num_verts_dst = dm_dst ? dm_dst->getNumVerts(dm_dst) : me_dst->totvert;
+ MPoly *polys_dst = dm_dst ? dm_dst->getPolyArray(dm_dst) : me_dst->mpoly;
+ const int num_polys_dst = dm_dst ? dm_dst->getNumPolys(dm_dst) : me_dst->totpoly;
+ MLoop *loops_dst = dm_dst ? dm_dst->getLoopArray(dm_dst) : me_dst->mloop;
+ const int num_loops_dst = dm_dst ? dm_dst->getNumLoops(dm_dst) : me_dst->totloop;
+ CustomData *pdata_dst = dm_dst ? dm_dst->getPolyDataLayout(dm_dst) : &me_dst->pdata;
+
+ if (!geom_map_init[PDATA]) {
+ const int num_polys_src = dm_src->getNumPolys(dm_src);
+
+ if ((map_poly_mode == MREMAP_MODE_TOPOLOGY) && (num_polys_dst != num_polys_src)) {
+ BKE_report(reports, RPT_ERROR,
+ "Source and destination meshes do not have the same amount of faces, "
+ "'Topology' mapping cannot be used in this case");
+ return changed;
+ }
+ if (ELEM(0, num_polys_dst, num_polys_src)) {
+ BKE_report(reports, RPT_ERROR,
+ "Source or destination meshes do not have any polygons, cannot transfer poly data");
+ return changed;
+ }
+
+ BKE_mesh_remap_calc_polys_from_dm(
+ map_poly_mode, space_transform, max_distance, ray_radius,
+ verts_dst, num_verts_dst, loops_dst, num_loops_dst,
+ polys_dst, num_polys_dst, pdata_dst, dirty_nors_dst,
+ dm_src, &geom_map[PDATA]);
+ geom_map_init[PDATA] = true;
+ }
+
+ if (mdef && vg_idx != -1 && !weights[PDATA]) {
+ weights[PDATA] = MEM_mallocN(sizeof(*weights[PDATA]) * (size_t)num_polys_dst, __func__);
+ BKE_defvert_extract_vgroup_to_polyweights(
+ mdef, vg_idx, num_verts_dst, loops_dst, num_loops_dst,
+ polys_dst, num_polys_dst, weights[PDATA], invert_vgroup);
+ }
+
+ if (data_transfer_layersmapping_generate(
+ &lay_map, ob_src, ob_dst, dm_src, dm_dst, me_dst, ME_POLY,
+ cddata_type, mix_mode, mix_factor, weights[PDATA],
+ num_polys_dst, use_create, use_delete, fromlayers, tolayers))
+ {
+ CustomDataTransferLayerMap *lay_mapit;
+
+ changed = (lay_map.first != NULL);
+
+ for (lay_mapit = lay_map.first; lay_mapit; lay_mapit = lay_mapit->next) {
+ CustomData_data_transfer(&geom_map[PDATA], lay_mapit);
+ }
+
+ BLI_freelistN(&lay_map);
+ }
+ }
+
+ data_transfer_dtdata_type_postprocess(ob_src, ob_dst, dm_src, dm_dst, me_dst, dtdata_type, changed);
+ }
+
+ for (i = 0; i < DATAMAX; i++) {
+ BKE_mesh_remap_free(&geom_map[i]);
+ MEM_SAFE_FREE(weights[i]);
+ }
+
+ return changed;
+
+#undef VDATA
+#undef EDATA
+#undef LDATA
+#undef PDATA
+#undef DATAMAX
+}
+
+bool BKE_object_data_transfer_mesh(
+ Scene *scene, Object *ob_src, Object *ob_dst, const int data_types, const bool use_create,
+ const int map_vert_mode, const int map_edge_mode, const int map_loop_mode, const int map_poly_mode,
+ SpaceTransform *space_transform, const bool auto_transform,
+ const float max_distance, const float ray_radius, const float islands_handling_precision,
+ const int fromlayers_select[DT_MULTILAYER_INDEX_MAX], const int tolayers_select[DT_MULTILAYER_INDEX_MAX],
+ const int mix_mode, const float mix_factor, const char *vgroup_name, const bool invert_vgroup,
+ ReportList *reports)
+{
+ return BKE_object_data_transfer_dm(
+ scene, ob_src, ob_dst, NULL, data_types, use_create,
+ map_vert_mode, map_edge_mode, map_loop_mode, map_poly_mode,
+ space_transform, auto_transform,
+ max_distance, ray_radius, islands_handling_precision,
+ fromlayers_select, tolayers_select,
+ mix_mode, mix_factor, vgroup_name, invert_vgroup, reports);
+}
diff --git a/source/blender/blenkernel/intern/data_transfer_intern.h b/source/blender/blenkernel/intern/data_transfer_intern.h
new file mode 100644
index 00000000000..501b749b464
--- /dev/null
+++ b/source/blender/blenkernel/intern/data_transfer_intern.h
@@ -0,0 +1,58 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2014 Blender Foundation.
+ * All rights reserved.
+ *
+ *
+ * Contributor(s): Bastien Montagne
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/blenkernel/intern/data_transfer_intern.h
+ * \ingroup bke
+ */
+
+#ifndef __DATA_TRANSFER_INTERN_H__
+#define __DATA_TRANSFER_INTERN_H__
+
+#include "BKE_customdata.h" /* For cd_datatransfer_interp */
+
+struct CustomDataTransferLayerMap;
+struct CustomData;
+struct ListBase;
+
+float data_transfer_interp_float_do(
+ const int mix_mode, const float val_dst, const float val_src, const float mix_factor);
+
+void data_transfer_layersmapping_add_item(
+ struct ListBase *r_map, const int data_type, const int mix_mode,
+ const float mix_factor, const float *mix_weights,
+ const void *data_src, void *data_dst, const int data_src_n, const int data_dst_n,
+ const size_t elem_size, const size_t data_size, const size_t data_offset, const uint64_t data_flag,
+ cd_datatransfer_interp interp);
+
+/* Type-specific. */
+
+bool data_transfer_layersmapping_vgroups(
+ struct ListBase *r_map, const int mix_mode, const float mix_factor, const float *mix_weights,
+ const int num_elem_dst, const bool use_create, const bool use_delete,
+ struct Object *ob_src, struct Object *ob_dst, struct CustomData *cd_src, struct CustomData *cd_dst,
+ const bool use_dupref_dst, const int fromlayers, const int tolayers);
+
+#endif /* __DATA_TRANSFER_INTERN_H__ */
diff --git a/source/blender/blenkernel/intern/deform.c b/source/blender/blenkernel/intern/deform.c
index 528ff2d7b19..6670c3359d7 100644
--- a/source/blender/blenkernel/intern/deform.c
+++ b/source/blender/blenkernel/intern/deform.c
@@ -39,7 +39,9 @@
#include "MEM_guardedalloc.h"
#include "DNA_meshdata_types.h"
+#include "DNA_mesh_types.h"
#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
#include "BLI_listbase.h"
#include "BLI_math.h"
@@ -47,9 +49,16 @@
#include "BLI_string.h"
#include "BLI_utildefines.h"
-#include "BLF_translation.h"
+#include "BLT_translation.h"
+#include "BKE_customdata.h"
+#include "BKE_data_transfer.h"
#include "BKE_deform.h" /* own include */
+#include "BKE_mesh_mapping.h"
+#include "BKE_object_deform.h"
+
+#include "data_transfer_intern.h"
+
bDeformGroup *BKE_defgroup_new(Object *ob, const char *name)
{
@@ -83,8 +92,10 @@ bDeformGroup *defgroup_duplicate(bDeformGroup *ingroup)
{
bDeformGroup *outgroup;
- if (!ingroup)
+ if (!ingroup) {
+ BLI_assert(0);
return NULL;
+ }
outgroup = MEM_callocN(sizeof(bDeformGroup), "copy deformGroup");
@@ -441,7 +452,7 @@ int defgroup_name_index(Object *ob, const char *name)
/* note, must be freed */
int *defgroup_flip_map(Object *ob, int *flip_map_len, const bool use_default)
{
- int defbase_tot = *flip_map_len = BLI_countlist(&ob->defbase);
+ int defbase_tot = *flip_map_len = BLI_listbase_count(&ob->defbase);
if (defbase_tot == 0) {
return NULL;
@@ -480,7 +491,7 @@ int *defgroup_flip_map(Object *ob, int *flip_map_len, const bool use_default)
/* note, must be freed */
int *defgroup_flip_map_single(Object *ob, int *flip_map_len, const bool use_default, int defgroup)
{
- int defbase_tot = *flip_map_len = BLI_countlist(&ob->defbase);
+ int defbase_tot = *flip_map_len = BLI_listbase_count(&ob->defbase);
if (defbase_tot == 0) {
return NULL;
@@ -533,7 +544,7 @@ static bool defgroup_find_name_dupe(const char *name, bDeformGroup *dg, Object *
for (curdef = ob->defbase.first; curdef; curdef = curdef->next) {
if (dg != curdef) {
- if (!strcmp(curdef->name, name)) {
+ if (STREQ(curdef->name, name)) {
return true;
}
}
@@ -640,7 +651,7 @@ void BKE_deform_flip_side_name(char name[MAX_VGROUP_NAME], const char from_name[
BLI_strncpy(prefix, name, sizeof(prefix));
/* first case; separator . - _ with extensions r R l L */
- if (is_char_sep(name[len - 2])) {
+ if ((len > 1) && is_char_sep(name[len - 2])) {
is_set = true;
switch (name[len - 1]) {
case 'l':
@@ -761,6 +772,9 @@ MDeformWeight *defvert_find_index(const MDeformVert *dvert, const int defgroup)
}
}
}
+ else {
+ BLI_assert(0);
+ }
return NULL;
}
@@ -772,8 +786,10 @@ MDeformWeight *defvert_verify_index(MDeformVert *dvert, const int defgroup)
MDeformWeight *dw_new;
/* do this check always, this function is used to check for it */
- if (!dvert || defgroup < 0)
+ if (!dvert || defgroup < 0) {
+ BLI_assert(0);
return NULL;
+ }
dw_new = defvert_find_index(dvert, defgroup);
if (dw_new)
@@ -804,8 +820,10 @@ void defvert_add_index_notest(MDeformVert *dvert, int defgroup, const float weig
MDeformWeight *dw_new;
/* do this check always, this function is used to check for it */
- if (!dvert || defgroup < 0)
+ if (!dvert || defgroup < 0) {
+ BLI_assert(0);
return;
+ }
dw_new = MEM_callocN(sizeof(MDeformWeight) * (dvert->totweight + 1), "defvert_add_to group, new deformWeight");
if (dvert->dw) {
@@ -825,7 +843,6 @@ void defvert_add_index_notest(MDeformVert *dvert, int defgroup, const float weig
void defvert_remove_group(MDeformVert *dvert, MDeformWeight *dw)
{
if (dvert && dw) {
- MDeformWeight *dw_new;
int i = dw - dvert->dw;
/* Security check! */
@@ -838,20 +855,13 @@ void defvert_remove_group(MDeformVert *dvert, MDeformWeight *dw)
* this deform weight, and reshuffle the others.
*/
if (dvert->totweight) {
- dw_new = MEM_mallocN(sizeof(MDeformWeight) * (dvert->totweight), __func__);
- if (dvert->dw) {
-#if 1 /* since we don't care about order, swap this with the last, save a memcpy */
- if (i != dvert->totweight) {
- dvert->dw[i] = dvert->dw[dvert->totweight];
- }
- memcpy(dw_new, dvert->dw, sizeof(MDeformWeight) * dvert->totweight);
-#else
- memcpy(dw_new, dvert->dw, sizeof(MDeformWeight) * i);
- memcpy(dw_new + i, dvert->dw + i + 1, sizeof(MDeformWeight) * (dvert->totweight - i));
-#endif
- MEM_freeN(dvert->dw);
+ BLI_assert(dvert->dw != NULL);
+
+ if (i != dvert->totweight) {
+ dvert->dw[i] = dvert->dw[dvert->totweight];
}
- dvert->dw = dw_new;
+
+ dvert->dw = MEM_reallocN(dvert->dw, sizeof(MDeformWeight) * dvert->totweight);
}
else {
/* If there are no other deform weights left then just remove this one. */
@@ -960,3 +970,386 @@ void BKE_defvert_array_free(MDeformVert *dvert, int totvert)
MEM_freeN(dvert);
}
+
+void BKE_defvert_extract_vgroup_to_vertweights(
+ MDeformVert *dvert, const int defgroup, const int num_verts, float *r_weights, const bool invert_vgroup)
+{
+ if (dvert && defgroup != -1) {
+ int i = num_verts;
+
+ while (i--) {
+ const float w = defvert_find_weight(&dvert[i], defgroup);
+ r_weights[i] = invert_vgroup ? (1.0f - w) : w;
+ }
+ }
+ else {
+ copy_vn_fl(r_weights, num_verts, invert_vgroup ? 1.0f : 0.0f);
+ }
+}
+
+/* The following three make basic interpolation, using temp vert_weights array to avoid looking up same weight
+ * several times. */
+
+void BKE_defvert_extract_vgroup_to_edgeweights(
+ MDeformVert *dvert, const int defgroup, const int num_verts, MEdge *edges, const int num_edges,
+ float *r_weights, const bool invert_vgroup)
+{
+ if (dvert && defgroup != -1) {
+ int i = num_edges;
+ float *tmp_weights = MEM_mallocN(sizeof(*tmp_weights) * (size_t)num_verts, __func__);
+
+ BKE_defvert_extract_vgroup_to_vertweights(dvert, defgroup, num_verts, tmp_weights, invert_vgroup);
+
+ while (i--) {
+ MEdge *me = &edges[i];
+
+ r_weights[i] = (tmp_weights[me->v1] + tmp_weights[me->v2]) * 0.5f;
+ }
+
+ MEM_freeN(tmp_weights);
+ }
+ else {
+ copy_vn_fl(r_weights, num_edges, 0.0f);
+ }
+}
+
+void BKE_defvert_extract_vgroup_to_loopweights(
+ MDeformVert *dvert, const int defgroup, const int num_verts, MLoop *loops, const int num_loops,
+ float *r_weights, const bool invert_vgroup)
+{
+ if (dvert && defgroup != -1) {
+ int i = num_loops;
+ float *tmp_weights = MEM_mallocN(sizeof(*tmp_weights) * (size_t)num_verts, __func__);
+
+ BKE_defvert_extract_vgroup_to_vertweights(dvert, defgroup, num_verts, tmp_weights, invert_vgroup);
+
+ while (i--) {
+ MLoop *ml = &loops[i];
+
+ r_weights[i] = tmp_weights[ml->v];
+ }
+
+ MEM_freeN(tmp_weights);
+ }
+ else {
+ copy_vn_fl(r_weights, num_loops, 0.0f);
+ }
+}
+
+void BKE_defvert_extract_vgroup_to_polyweights(
+ MDeformVert *dvert, const int defgroup, const int num_verts, MLoop *loops, const int UNUSED(num_loops),
+ MPoly *polys, const int num_polys, float *r_weights, const bool invert_vgroup)
+{
+ if (dvert && defgroup != -1) {
+ int i = num_polys;
+ float *tmp_weights = MEM_mallocN(sizeof(*tmp_weights) * (size_t)num_verts, __func__);
+
+ BKE_defvert_extract_vgroup_to_vertweights(dvert, defgroup, num_verts, tmp_weights, invert_vgroup);
+
+ while (i--) {
+ MPoly *mp = &polys[i];
+ MLoop *ml = &loops[mp->loopstart];
+ int j = mp->totloop;
+ float w = 0.0f;
+
+ for (; j--; ml++) {
+ w += tmp_weights[ml->v];
+ }
+ r_weights[i] = w / (float)mp->totloop;
+ }
+
+ MEM_freeN(tmp_weights);
+ }
+ else {
+ copy_vn_fl(r_weights, num_polys, 0.0f);
+ }
+}
+
+/*********** Data Transfer **********/
+
+static void vgroups_datatransfer_interp(
+ const CustomDataTransferLayerMap *laymap, void *dest,
+ const void **sources, const float *weights, const int count, const float mix_factor)
+{
+ MDeformVert **data_src = (MDeformVert **)sources;
+ MDeformVert *data_dst = (MDeformVert *)dest;
+ const int idx_src = laymap->data_src_n;
+ const int idx_dst = laymap->data_dst_n;
+
+ const int mix_mode = laymap->mix_mode;
+
+ int i, j;
+
+ MDeformWeight *dw_src;
+ MDeformWeight *dw_dst = defvert_find_index(data_dst, idx_dst);
+ float weight_src = 0.0f, weight_dst = 0.0f;
+
+ if (sources) {
+ for (i = count; i--;) {
+ for (j = data_src[i]->totweight; j--;) {
+ if ((dw_src = &data_src[i]->dw[j])->def_nr == idx_src) {
+ weight_src += dw_src->weight * weights[i];
+ break;
+ }
+ }
+ }
+ }
+
+ if (dw_dst) {
+ weight_dst = dw_dst->weight;
+ }
+ else if (mix_mode == CDT_MIX_REPLACE_ABOVE_THRESHOLD) {
+ return; /* Do not affect destination. */
+ }
+
+ weight_src = data_transfer_interp_float_do(mix_mode, weight_dst, weight_src, mix_factor);
+
+ CLAMP(weight_src, 0.0f, 1.0f);
+
+ if (!dw_dst) {
+ defvert_add_index_notest(data_dst, idx_dst, weight_src);
+ }
+ else {
+ dw_dst->weight = weight_src;
+ }
+}
+
+static bool data_transfer_layersmapping_vgroups_multisrc_to_dst(
+ ListBase *r_map, const int mix_mode, const float mix_factor, const float *mix_weights,
+ const int num_elem_dst, const bool use_create, const bool use_delete,
+ Object *ob_src, Object *ob_dst, MDeformVert *data_src, MDeformVert *data_dst,
+ CustomData *UNUSED(cd_src), CustomData *cd_dst, const bool UNUSED(use_dupref_dst),
+ const int tolayers, bool *use_layers_src, const int num_layers_src)
+{
+ int idx_src;
+ int idx_dst;
+ int tot_dst = BLI_listbase_count(&ob_dst->defbase);
+
+ const size_t elem_size = sizeof(*((MDeformVert *)NULL));
+
+ switch (tolayers) {
+ case DT_LAYERS_INDEX_DST:
+ idx_dst = tot_dst;
+
+ /* Find last source actually used! */
+ idx_src = num_layers_src;
+ while (idx_src-- && !use_layers_src[idx_src]);
+ idx_src++;
+
+ if (idx_dst < idx_src) {
+ if (!use_create) {
+ return false;
+ }
+ /* Create as much vgroups as necessary! */
+ for (; idx_dst < idx_src; idx_dst++) {
+ BKE_object_defgroup_add(ob_dst);
+ }
+ }
+ else if (use_delete && idx_dst > idx_src) {
+ while (idx_dst-- > idx_src) {
+ BKE_object_defgroup_remove(ob_dst, ob_dst->defbase.last);
+ }
+ }
+ if (r_map) {
+ /* At this stage, we **need** a valid CD_MDEFORMVERT layer on dest!
+ * Again, use_create is not relevant in this case */
+ if (!data_dst) {
+ data_dst = CustomData_add_layer(cd_dst, CD_MDEFORMVERT, CD_CALLOC, NULL, num_elem_dst);
+ }
+
+ while (idx_src--) {
+ if (!use_layers_src[idx_src]) {
+ continue;
+ }
+ data_transfer_layersmapping_add_item(r_map, CD_FAKE_MDEFORMVERT, mix_mode, mix_factor, mix_weights,
+ data_src, data_dst, idx_src, idx_src,
+ elem_size, 0, 0, 0, vgroups_datatransfer_interp);
+ }
+ }
+ break;
+ case DT_LAYERS_NAME_DST:
+ {
+ bDeformGroup *dg_src, *dg_dst;
+
+ if (use_delete) {
+ /* Remove all unused dst vgroups first, simpler in this case. */
+ for (dg_dst = ob_dst->defbase.first; dg_dst;) {
+ bDeformGroup *dg_dst_next = dg_dst->next;
+
+ if (defgroup_name_index(ob_src, dg_dst->name) == -1) {
+ BKE_object_defgroup_remove(ob_dst, dg_dst);
+ }
+ dg_dst = dg_dst_next;
+ }
+ }
+
+ for (idx_src = 0, dg_src = ob_src->defbase.first;
+ idx_src < num_layers_src;
+ idx_src++, dg_src = dg_src->next)
+ {
+ if (!use_layers_src[idx_src]) {
+ continue;
+ }
+
+ if ((idx_dst = defgroup_name_index(ob_dst, dg_src->name)) == -1) {
+ if (!use_create) {
+ if (r_map) {
+ BLI_freelistN(r_map);
+ }
+ return false;
+ }
+ BKE_object_defgroup_add_name(ob_dst, dg_src->name);
+ idx_dst = ob_dst->actdef - 1;
+ }
+ if (r_map) {
+ /* At this stage, we **need** a valid CD_MDEFORMVERT layer on dest!
+ * use_create is not relevant in this case */
+ if (!data_dst) {
+ data_dst = CustomData_add_layer(cd_dst, CD_MDEFORMVERT, CD_CALLOC, NULL, num_elem_dst);
+ }
+
+ data_transfer_layersmapping_add_item(
+ r_map, CD_FAKE_MDEFORMVERT, mix_mode, mix_factor, mix_weights,
+ data_src, data_dst, idx_src, idx_dst,
+ elem_size, 0, 0, 0, vgroups_datatransfer_interp);
+ }
+ }
+ break;
+ }
+ default:
+ return false;
+ }
+
+ return true;
+}
+
+bool data_transfer_layersmapping_vgroups(
+ ListBase *r_map, const int mix_mode, const float mix_factor, const float *mix_weights,
+ const int num_elem_dst, const bool use_create, const bool use_delete, Object *ob_src, Object *ob_dst,
+ CustomData *cd_src, CustomData *cd_dst, const bool use_dupref_dst, const int fromlayers, const int tolayers)
+{
+ int idx_src, idx_dst;
+ MDeformVert *data_src, *data_dst = NULL;
+
+ const size_t elem_size = sizeof(*((MDeformVert *)NULL));
+
+ /* Note: VGroups are a bit hairy, since their layout is defined on object level (ob->defbase), while their actual
+ * data is a (mesh) CD layer.
+ * This implies we may have to handle data layout itself while having NULL data itself,
+ * and even have to support NULL data_src in transfer data code (we always create a data_dst, though).
+ */
+
+ if (BLI_listbase_is_empty(&ob_src->defbase)) {
+ if (use_delete) {
+ BKE_object_defgroup_remove_all(ob_dst);
+ }
+ return true;
+ }
+
+ data_src = CustomData_get_layer(cd_src, CD_MDEFORMVERT);
+
+ data_dst = CustomData_get_layer(cd_dst, CD_MDEFORMVERT);
+ if (data_dst && use_dupref_dst && r_map) {
+ /* If dest is a derivedmesh, we do not want to overwrite cdlayers of org mesh! */
+ data_dst = CustomData_duplicate_referenced_layer(cd_dst, CD_MDEFORMVERT, num_elem_dst);
+ }
+
+ if (fromlayers == DT_LAYERS_ACTIVE_SRC || fromlayers >= 0) {
+ /* Note: use_delete has not much meaning in this case, ignored. */
+
+ if (fromlayers >= 0) {
+ idx_src = fromlayers;
+ BLI_assert(idx_src < BLI_listbase_count(&ob_src->defbase));
+ }
+ else if ((idx_src = ob_src->actdef - 1) == -1) {
+ return false;
+ }
+
+ if (tolayers >= 0) {
+ /* Note: in this case we assume layer exists! */
+ idx_dst = tolayers;
+ BLI_assert(idx_dst < BLI_listbase_count(&ob_dst->defbase));
+ }
+ else if (tolayers == DT_LAYERS_ACTIVE_DST) {
+ if ((idx_dst = ob_dst->actdef - 1) == -1) {
+ bDeformGroup *dg_src;
+ if (!use_create) {
+ return true;
+ }
+ dg_src = BLI_findlink(&ob_src->defbase, idx_src);
+ BKE_object_defgroup_add_name(ob_dst, dg_src->name);
+ idx_dst = ob_dst->actdef - 1;
+ }
+ }
+ else if (tolayers == DT_LAYERS_INDEX_DST) {
+ int num = BLI_listbase_count(&ob_src->defbase);
+ idx_dst = idx_src;
+ if (num <= idx_dst) {
+ if (!use_create) {
+ return true;
+ }
+ /* Create as much vgroups as necessary! */
+ for (; num <= idx_dst; num++) {
+ BKE_object_defgroup_add(ob_dst);
+ }
+ }
+ }
+ else if (tolayers == DT_LAYERS_NAME_DST) {
+ bDeformGroup *dg_src = BLI_findlink(&ob_src->defbase, idx_src);
+ if ((idx_dst = defgroup_name_index(ob_dst, dg_src->name)) == -1) {
+ if (!use_create) {
+ return true;
+ }
+ BKE_object_defgroup_add_name(ob_dst, dg_src->name);
+ idx_dst = ob_dst->actdef - 1;
+ }
+ }
+ else {
+ return false;
+ }
+
+ if (r_map) {
+ /* At this stage, we **need** a valid CD_MDEFORMVERT layer on dest!
+ * use_create is not relevant in this case */
+ if (!data_dst) {
+ data_dst = CustomData_add_layer(cd_dst, CD_MDEFORMVERT, CD_CALLOC, NULL, num_elem_dst);
+ }
+
+ data_transfer_layersmapping_add_item(r_map, CD_FAKE_MDEFORMVERT, mix_mode, mix_factor, mix_weights,
+ data_src, data_dst, idx_src, idx_dst,
+ elem_size, 0, 0, 0, vgroups_datatransfer_interp);
+ }
+ }
+ else {
+ int num_src, num_sel_unused;
+ bool *use_layers_src = NULL;
+ bool ret = false;
+
+ switch (fromlayers) {
+ case DT_LAYERS_ALL_SRC:
+ use_layers_src = BKE_object_defgroup_subset_from_select_type(ob_src, WT_VGROUP_ALL,
+ &num_src, &num_sel_unused);
+ break;
+ case DT_LAYERS_VGROUP_SRC_BONE_SELECT:
+ use_layers_src = BKE_object_defgroup_subset_from_select_type(ob_src, WT_VGROUP_BONE_SELECT,
+ &num_src, &num_sel_unused);
+ break;
+ case DT_LAYERS_VGROUP_SRC_BONE_DEFORM:
+ use_layers_src = BKE_object_defgroup_subset_from_select_type(ob_src, WT_VGROUP_BONE_DEFORM,
+ &num_src, &num_sel_unused);
+ break;
+ }
+
+ if (use_layers_src) {
+ ret = data_transfer_layersmapping_vgroups_multisrc_to_dst(
+ r_map, mix_mode, mix_factor, mix_weights, num_elem_dst, use_create, use_delete,
+ ob_src, ob_dst, data_src, data_dst, cd_src, cd_dst, use_dupref_dst,
+ tolayers, use_layers_src, num_src);
+ }
+
+ MEM_SAFE_FREE(use_layers_src);
+ return ret;
+ }
+
+ return true;
+}
diff --git a/source/blender/blenkernel/intern/depsgraph.c b/source/blender/blenkernel/intern/depsgraph.c
index 93bb4849718..4373e797dfe 100644
--- a/source/blender/blenkernel/intern/depsgraph.c
+++ b/source/blender/blenkernel/intern/depsgraph.c
@@ -75,6 +75,7 @@
#include "BKE_mball.h"
#include "BKE_modifier.h"
#include "BKE_object.h"
+#include "BKE_paint.h"
#include "BKE_particle.h"
#include "BKE_pointcache.h"
#include "BKE_scene.h"
@@ -87,16 +88,25 @@
#include "depsgraph_private.h"
+#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_build.h"
+#include "DEG_depsgraph_debug.h"
+#include "DEG_depsgraph_query.h"
+
+#ifdef WITH_LEGACY_DEPSGRAPH
+
static SpinLock threaded_update_lock;
void DAG_init(void)
{
BLI_spin_init(&threaded_update_lock);
+ DEG_register_node_types();
}
void DAG_exit(void)
{
BLI_spin_end(&threaded_update_lock);
+ DEG_free_node_types();
}
/* Queue and stack operations for dag traversal
@@ -483,7 +493,7 @@ static void dag_add_collision_field_relation(DagForest *dag, Scene *scene, Objec
}
}
-static void build_dag_object(DagForest *dag, DagNode *scenenode, Scene *scene, Object *ob, int mask)
+static void build_dag_object(DagForest *dag, DagNode *scenenode, Main *bmain, Scene *scene, Object *ob, int mask)
{
bConstraint *con;
DagNode *node;
@@ -511,7 +521,7 @@ static void build_dag_object(DagForest *dag, DagNode *scenenode, Scene *scene, O
for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
for (con = pchan->constraints.first; con; con = con->next) {
- bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
+ const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
ListBase targets = {NULL, NULL};
bConstraintTarget *ct;
@@ -573,9 +583,9 @@ static void build_dag_object(DagForest *dag, DagNode *scenenode, Scene *scene, O
ModifierData *md;
for (md = ob->modifiers.first; md; md = md->next) {
- ModifierTypeInfo *mti = modifierType_getInfo(md->type);
+ const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
- if (mti->updateDepgraph) mti->updateDepgraph(md, dag, scene, ob, node);
+ if (mti->updateDepgraph) mti->updateDepgraph(md, dag, bmain, scene, ob, node);
}
}
if (ob->parent) {
@@ -822,7 +832,7 @@ static void build_dag_object(DagForest *dag, DagNode *scenenode, Scene *scene, O
/* object constraints */
for (con = ob->constraints.first; con; con = con->next) {
- bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
+ const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
ListBase targets = {NULL, NULL};
bConstraintTarget *ct;
@@ -890,7 +900,7 @@ static void build_dag_object(DagForest *dag, DagNode *scenenode, Scene *scene, O
dag_add_relation(dag, scenenode, node, DAG_RL_SCENE, "Scene Relation");
}
-static void build_dag_group(DagForest *dag, DagNode *scenenode, Scene *scene, Group *group, short mask)
+static void build_dag_group(DagForest *dag, DagNode *scenenode, Main *bmain, Scene *scene, Group *group, short mask)
{
GroupObject *go;
@@ -900,9 +910,9 @@ static void build_dag_group(DagForest *dag, DagNode *scenenode, Scene *scene, Gr
group->id.flag |= LIB_DOIT;
for (go = group->gobject.first; go; go = go->next) {
- build_dag_object(dag, scenenode, scene, go->ob, mask);
+ build_dag_object(dag, scenenode, bmain, scene, go->ob, mask);
if (go->ob->dup_group)
- build_dag_group(dag, scenenode, scene, go->ob->dup_group, mask);
+ build_dag_group(dag, scenenode, bmain, scene, go->ob->dup_group, mask);
}
}
@@ -935,11 +945,11 @@ DagForest *build_dag(Main *bmain, Scene *sce, short mask)
for (base = sce->base.first; base; base = base->next) {
ob = base->object;
- build_dag_object(dag, scenenode, sce, ob, mask);
+ build_dag_object(dag, scenenode, bmain, sce, ob, mask);
if (ob->proxy)
- build_dag_object(dag, scenenode, sce, ob->proxy, mask);
+ build_dag_object(dag, scenenode, bmain, sce, ob->proxy, mask);
if (ob->dup_group)
- build_dag_group(dag, scenenode, sce, ob->dup_group, mask);
+ build_dag_group(dag, scenenode, bmain, sce, ob->dup_group, mask);
}
BKE_main_id_tag_idcode(bmain, ID_GR, false);
@@ -959,6 +969,10 @@ DagForest *build_dag(Main *bmain, Scene *sce, short mask)
/* also flush custom data mask */
((Object *)node->ob)->customdata_mask = node->customdata_mask;
+
+ if (node->parent == NULL) {
+ dag_add_relation(dag, scenenode, node, DAG_RL_SCENE, "Scene Relation");
+ }
}
}
/* now set relations equal, so that when only one parent changes, the correct recalcs are found */
@@ -1124,6 +1138,23 @@ void dag_add_relation(DagForest *forest, DagNode *fob1, DagNode *fob2, short rel
/* parent relation is for cycle checking */
dag_add_parent_relation(forest, fob1, fob2, rel, name);
+ /* TODO(sergey): Find a better place for this. */
+#ifdef WITH_OPENSUBDIV
+ if ((rel & DAG_RL_DATA_DATA) != 0) {
+ if (fob1->type == ID_OB) {
+ if ((fob1->eval_flags & DAG_EVAL_NEED_CPU) == 0) {
+ Object *ob2 = fob2->ob;
+ if (ob2->recalc & OB_RECALC_ALL) {
+ /* Make sure object has all the data on CPU. */
+ Object *ob1 = fob1->ob;
+ ob1->recalc |= OB_RECALC_DATA;
+ }
+ fob1->eval_flags |= DAG_EVAL_NEED_CPU;
+ }
+ }
+ }
+#endif
+
while (itA) { /* search if relation exist already */
if (itA->node == fob2) {
itA->type |= rel;
@@ -1321,11 +1352,33 @@ void graph_print_adj_list(DagForest *dag)
* to do their own updates based on changes... */
static void (*EditorsUpdateIDCb)(Main *bmain, ID *id) = NULL;
static void (*EditorsUpdateSceneCb)(Main *bmain, Scene *scene, int updated) = NULL;
+static void (*EditorsUpdateScenePreCb)(Main *bmain, Scene *scene, bool time) = NULL;
-void DAG_editors_update_cb(void (*id_func)(Main *bmain, ID *id), void (*scene_func)(Main *bmain, Scene *scene, int updated))
+void DAG_editors_update_cb(void (*id_func)(Main *bmain, ID *id),
+ void (*scene_func)(Main *bmain, Scene *scene, int updated),
+ void (*scene_pre_func)(Main *bmain, Scene *scene, bool time))
{
- EditorsUpdateIDCb = id_func;
- EditorsUpdateSceneCb = scene_func;
+ if (DEG_depsgraph_use_legacy()) {
+ EditorsUpdateIDCb = id_func;
+ EditorsUpdateSceneCb = scene_func;
+ EditorsUpdateScenePreCb = scene_pre_func;
+ }
+ else {
+ /* New dependency graph. */
+ DEG_editors_set_update_cb(id_func, scene_func, scene_pre_func);
+ }
+}
+
+void DAG_editors_update_pre(Main *bmain, Scene *scene, bool time)
+{
+ if (DEG_depsgraph_use_legacy()) {
+ if (EditorsUpdateScenePreCb != NULL) {
+ EditorsUpdateScenePreCb(bmain, scene, time);
+ }
+ }
+ else {
+ DEG_editors_update_pre(bmain, scene, time);
+ }
}
static void dag_editors_id_update(Main *bmain, ID *id)
@@ -1524,7 +1577,7 @@ static void dag_scene_build(Main *bmain, Scene *sce)
Base *base;
BLI_listbase_clear(&tempbase);
-
+
build_dag(bmain, sce, DAG_RL_ALL_BUT_DATA);
dag_check_cycle(sce->theDag);
@@ -1616,32 +1669,65 @@ static void dag_scene_build(Main *bmain, Scene *sce)
/* clear all dependency graphs */
void DAG_relations_tag_update(Main *bmain)
{
- Scene *sce;
-
- for (sce = bmain->scene.first; sce; sce = sce->id.next)
- dag_scene_free(sce);
+ if (DEG_depsgraph_use_legacy()) {
+ Scene *sce;
+ for (sce = bmain->scene.first; sce; sce = sce->id.next) {
+ dag_scene_free(sce);
+ }
+ }
+ else {
+ /* New dependency graph. */
+ DEG_relations_tag_update(bmain);
+ }
}
/* rebuild dependency graph only for a given scene */
void DAG_scene_relations_rebuild(Main *bmain, Scene *sce)
{
- dag_scene_free(sce);
- DAG_scene_relations_update(bmain, sce);
+ if (DEG_depsgraph_use_legacy()) {
+ dag_scene_free(sce);
+ DAG_scene_relations_update(bmain, sce);
+ }
+ else {
+ /* New dependency graph. */
+ DEG_scene_relations_rebuild(bmain, sce);
+ }
}
/* create dependency graph if it was cleared or didn't exist yet */
void DAG_scene_relations_update(Main *bmain, Scene *sce)
{
- if (!sce->theDag)
- dag_scene_build(bmain, sce);
+ if (DEG_depsgraph_use_legacy()) {
+ if (!sce->theDag)
+ dag_scene_build(bmain, sce);
+ }
+ else {
+ /* New dependency graph. */
+ DEG_scene_relations_update(bmain, sce);
+ }
+}
+
+void DAG_scene_relations_validate(Main *bmain, Scene *sce)
+{
+ if (!DEG_depsgraph_use_legacy()) {
+ DEG_debug_scene_relations_validate(bmain, sce);
+ }
}
void DAG_scene_free(Scene *sce)
{
- if (sce->theDag) {
- free_forest(sce->theDag);
- MEM_freeN(sce->theDag);
- sce->theDag = NULL;
+ if (DEG_depsgraph_use_legacy()) {
+ if (sce->theDag) {
+ free_forest(sce->theDag);
+ MEM_freeN(sce->theDag);
+ sce->theDag = NULL;
+ }
+ }
+ else {
+ if (sce->depsgraph) {
+ DEG_graph_free(sce->depsgraph);
+ sce->depsgraph = NULL;
+ }
}
}
@@ -1884,7 +1970,11 @@ void DAG_scene_flush_update(Main *bmain, Scene *sce, unsigned int lay, const sho
DagAdjList *itA;
Object *ob;
int lasttime;
-
+
+ if (!DEG_depsgraph_use_legacy()) {
+ return;
+ }
+
if (sce->theDag == NULL) {
printf("DAG zero... not allowed to happen!\n");
DAG_scene_relations_update(bmain, sce);
@@ -1929,25 +2019,50 @@ void DAG_scene_flush_update(Main *bmain, Scene *sce, unsigned int lay, const sho
dag_tag_renderlayers(sce, lay);
}
-static int object_modifiers_use_time(Object *ob)
+static bool modifier_nlastrips_use_time(ListBase *strips)
+{
+ NlaStrip *strip;
+
+ if (strips) {
+ for (strip = strips->first; strip; strip = strip->next) {
+ if (modifier_nlastrips_use_time(&strip->strips)) {
+ return true;
+ }
+ else if (strip->act) {
+ FCurve *fcu;
+
+ for (fcu = strip->act->curves.first; fcu; fcu = fcu->next) {
+ if (fcu->rna_path && strstr(fcu->rna_path, "modifiers["))
+ return true;
+ }
+ }
+ }
+ }
+
+ return false;
+}
+
+static bool object_modifiers_use_time(Object *ob)
{
ModifierData *md;
/* check if a modifier in modifier stack needs time input */
- for (md = ob->modifiers.first; md; md = md->next)
+ for (md = ob->modifiers.first; md; md = md->next) {
if (modifier_dependsOnTime(md))
- return 1;
+ return true;
+ }
/* check whether any modifiers are animated */
if (ob->adt) {
AnimData *adt = ob->adt;
+ NlaTrack *nlt;
FCurve *fcu;
/* action - check for F-Curves with paths containing 'modifiers[' */
if (adt->action) {
for (fcu = adt->action->curves.first; fcu; fcu = fcu->next) {
if (fcu->rna_path && strstr(fcu->rna_path, "modifiers["))
- return 1;
+ return true;
}
}
@@ -1959,14 +2074,17 @@ static int object_modifiers_use_time(Object *ob)
*/
for (fcu = adt->drivers.first; fcu; fcu = fcu->next) {
if (fcu->rna_path && strstr(fcu->rna_path, "modifiers["))
- return 1;
+ return true;
}
- /* XXX: also, should check NLA strips, though for now assume that nobody uses
- * that and we can omit that for performance reasons... */
+ /* Also check NLA Strips... [#T45938] */
+ for (nlt = adt->nla_tracks.first; nlt; nlt = nlt->next) {
+ if (modifier_nlastrips_use_time(&nlt->strips))
+ return true;
+ }
}
- return 0;
+ return false;
}
static short animdata_use_time(AnimData *adt)
@@ -2010,7 +2128,7 @@ static void dag_object_time_update_flags(Main *bmain, Scene *scene, Object *ob)
if (ob->constraints.first) {
bConstraint *con;
for (con = ob->constraints.first; con; con = con->next) {
- bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
+ const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
ListBase targets = {NULL, NULL};
bConstraintTarget *ct;
@@ -2295,7 +2413,7 @@ static void dag_current_scene_layers(Main *bmain, ListBase *lb)
}
}
-static void dag_group_on_visible_update(Group *group)
+static void dag_group_on_visible_update(Scene *scene, Group *group)
{
GroupObject *go;
@@ -2317,7 +2435,7 @@ static void dag_group_on_visible_update(Group *group)
}
if (go->ob->dup_group)
- dag_group_on_visible_update(go->ob->dup_group);
+ dag_group_on_visible_update(scene, go->ob->dup_group);
}
}
@@ -2325,7 +2443,13 @@ void DAG_on_visible_update(Main *bmain, const bool do_time)
{
ListBase listbase;
DagSceneLayer *dsl;
-
+
+ if (!DEG_depsgraph_use_legacy()) {
+ /* Inform new dependnecy graphs about visibility changes. */
+ DEG_on_visible_update(bmain, do_time);
+ return;
+ }
+
/* get list of visible scenes and layers */
dag_current_scene_layers(bmain, &listbase);
@@ -2352,16 +2476,26 @@ void DAG_on_visible_update(Main *bmain, const bool do_time)
oblay = (node) ? node->lay : ob->lay;
if ((oblay & lay) & ~scene->lay_updated) {
- if (ELEM(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_MBALL, OB_LATTICE)) {
+ /* TODO(sergey): Why do we need armature here now but didn't need before? */
+ if (ELEM(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_MBALL, OB_LATTICE, OB_ARMATURE)) {
ob->recalc |= OB_RECALC_DATA;
lib_id_recalc_tag(bmain, &ob->id);
}
+ /* This should not be needed here, but in some cases, like after a redo, we can end up with
+ * a wrong final matrix (see T42472).
+ * Quoting Sergey, this comes from BKE_object_handle_update_ex, which is calling
+ * BKE_object_where_is_calc_ex when it shouldn't, but that issue is not easily fixable.
+ */
+ else {
+ ob->recalc |= OB_RECALC_OB;
+ lib_id_recalc_tag(bmain, &ob->id);
+ }
if (ob->proxy && (ob->proxy_group == NULL)) {
ob->proxy->recalc |= OB_RECALC_DATA;
lib_id_recalc_tag(bmain, &ob->id);
}
if (ob->dup_group)
- dag_group_on_visible_update(ob->dup_group);
+ dag_group_on_visible_update(scene, ob->dup_group);
}
}
@@ -2509,6 +2643,7 @@ static void dag_id_flush_update(Main *bmain, Scene *sce, ID *id)
obt = sce->basact ? sce->basact->object : NULL;
if (obt && obt->mode & OB_MODE_TEXTURE_PAINT) {
BKE_texpaint_slots_refresh_object(sce, obt);
+ BKE_paint_proj_mesh_data_check(sce, obt, NULL, NULL, NULL, NULL);
GPU_drawobject_free(obt->derivedFinal);
}
}
@@ -2521,7 +2656,7 @@ static void dag_id_flush_update(Main *bmain, Scene *sce, ID *id)
for (obt = bmain->object.first; obt; obt = obt->id.next) {
bConstraint *con;
for (con = obt->constraints.first; con; con = con->next) {
- bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
+ const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
if (ELEM(cti->type, CONSTRAINT_TYPE_FOLLOWTRACK, CONSTRAINT_TYPE_CAMERASOLVER,
CONSTRAINT_TYPE_OBJECTSOLVER))
{
@@ -2594,7 +2729,12 @@ void DAG_ids_flush_tagged(Main *bmain)
ListBase *lbarray[MAX_LIBARRAY];
int a;
bool do_flush = false;
-
+
+ if (!DEG_depsgraph_use_legacy()) {
+ DEG_ids_flush_tagged(bmain);
+ return;
+ }
+
/* get list of visible scenes and layers */
dag_current_scene_layers(bmain, &listbase);
@@ -2638,6 +2778,11 @@ void DAG_ids_check_recalc(Main *bmain, Scene *scene, bool time)
int a;
bool updated = false;
+ if (!DEG_depsgraph_use_legacy()) {
+ DEG_ids_check_recalc(bmain, scene, time);
+ return;
+ }
+
/* loop over all ID types */
a = set_listbasepointers(bmain, lbarray);
@@ -2754,6 +2899,11 @@ void DAG_ids_clear_recalc(Main *bmain)
void DAG_id_tag_update_ex(Main *bmain, ID *id, short flag)
{
+ if (!DEG_depsgraph_use_legacy()) {
+ DEG_id_tag_update_ex(bmain, id, flag);
+ return;
+ }
+
if (id == NULL) return;
if (G.debug & G_DEBUG_DEPSGRAPH) {
@@ -2905,7 +3055,7 @@ void DAG_pose_sort(Object *ob)
addtoroot = 0;
}
for (con = pchan->constraints.first; con; con = con->next) {
- bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
+ const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
ListBase targets = {NULL, NULL};
bConstraintTarget *ct;
@@ -3145,6 +3295,10 @@ short DAG_get_eval_flags_for_object(Scene *scene, void *object)
{
DagNode *node;
+ if (!DEG_depsgraph_use_legacy()) {
+ return DEG_get_eval_flags_for_id(scene->depsgraph, (ID *)object);
+ }
+
if (scene->theDag == NULL) {
/* Happens when converting objects to mesh from a python script
* after modifying scene graph.
@@ -3183,3 +3337,292 @@ bool DAG_is_acyclic(Scene *scene)
{
return scene->theDag->is_acyclic;
}
+
+#else
+
+/* *********************************************************************
+ * Stubs to avoid linking issues and make sure legacy crap is not used *
+ * *********************************************************************
+ */
+
+DagNodeQueue *queue_create(int UNUSED(slots))
+{
+ BLI_assert(!"Should not be used with new dependnecy graph");
+ return NULL;
+}
+
+void queue_raz(DagNodeQueue *UNUSED(queue))
+{
+ BLI_assert(!"Should not be used with new dependnecy graph");
+}
+
+void queue_delete(DagNodeQueue *UNUSED(queue))
+{
+ BLI_assert(!"Should not be used with new dependnecy graph");
+}
+
+void push_queue(DagNodeQueue *UNUSED(queue), DagNode *UNUSED(node))
+{
+ BLI_assert(!"Should not be used with new dependnecy graph");
+}
+
+void push_stack(DagNodeQueue *UNUSED(queue), DagNode *UNUSED(node))
+{
+ BLI_assert(!"Should not be used with new dependnecy graph");
+}
+
+DagNode *pop_queue(DagNodeQueue *UNUSED(queue))
+{
+ BLI_assert(!"Should not be used with new dependnecy graph");
+ return NULL;
+}
+
+DagNode *get_top_node_queue(DagNodeQueue *UNUSED(queue))
+{
+ BLI_assert(!"Should not be used with new dependnecy graph");
+ return NULL;
+}
+
+DagForest *dag_init(void)
+{
+ BLI_assert(!"Should not be used with new dependnecy graph");
+ return NULL;
+}
+
+DagForest *build_dag(Main *UNUSED(bmain),
+ Scene *UNUSED(sce),
+ short UNUSED(mask))
+{
+ BLI_assert(!"Should not be used with new dependnecy graph");
+ return NULL;
+}
+
+void free_forest(DagForest *UNUSED(Dag))
+{
+ BLI_assert(!"Should not be used with new dependnecy graph");
+}
+
+DagNode *dag_find_node(DagForest *UNUSED(forest), void *UNUSED(fob))
+{
+ BLI_assert(!"Should not be used with new dependnecy graph");
+ return NULL;
+}
+
+DagNode *dag_add_node(DagForest *UNUSED(forest), void *UNUSED(fob))
+{
+ BLI_assert(!"Should not be used with new dependnecy graph");
+ return NULL;
+}
+
+DagNode *dag_get_node(DagForest *UNUSED(forest), void *UNUSED(fob))
+{
+ BLI_assert(!"Should not be used with new dependnecy graph");
+ return NULL;
+}
+
+DagNode *dag_get_sub_node(DagForest *UNUSED(forest), void *UNUSED(fob))
+{
+ BLI_assert(!"Should not be used with new dependnecy graph");
+ return NULL;
+}
+
+void dag_add_relation(DagForest *UNUSED(forest),
+ DagNode *UNUSED(fob1),
+ DagNode *UNUSED(fob2),
+ short UNUSED(rel),
+ const char *UNUSED(name))
+{
+ BLI_assert(!"Should not be used with new dependnecy graph");
+}
+
+/* debug test functions */
+
+void graph_print_queue(DagNodeQueue *UNUSED(nqueue))
+{
+ BLI_assert(!"Should not be used with new dependnecy graph");
+}
+
+void graph_print_queue_dist(DagNodeQueue *UNUSED(nqueue))
+{
+ BLI_assert(!"Should not be used with new dependnecy graph");
+}
+
+void graph_print_adj_list(DagForest *UNUSED(dag))
+{
+ BLI_assert(!"Should not be used with new dependnecy graph");
+}
+
+void DAG_scene_flush_update(Main *UNUSED(bmain),
+ Scene *UNUSED(sce),
+ unsigned int UNUSED(lay),
+ const short UNUSED(time))
+{
+ BLI_assert(!"Should not be used with new dependnecy graph");
+}
+
+void DAG_scene_update_flags(Main *UNUSED(bmain),
+ Scene *UNUSED(scene),
+ unsigned int UNUSED(lay),
+ const bool UNUSED(do_time),
+ const bool UNUSED(do_invisible_flush))
+{
+ BLI_assert(!"Should not be used with new dependnecy graph");
+}
+
+/* ******************* DAG FOR ARMATURE POSE ***************** */
+
+void DAG_pose_sort(Object *UNUSED(ob))
+{
+ BLI_assert(!"Should not be used with new dependnecy graph");
+}
+
+/* ************************ DAG FOR THREADED UPDATE ********************* */
+
+void DAG_threaded_update_begin(Scene *UNUSED(scene),
+ void (*func)(void *node, void *user_data),
+ void *UNUSED(user_data))
+{
+ BLI_assert(!"Should not be used with new dependnecy graph");
+ (void)func;
+}
+
+void DAG_threaded_update_handle_node_updated(void *UNUSED(node_v),
+ void (*func)(void *node, void *user_data),
+ void *UNUSED(user_data))
+{
+ BLI_assert(!"Should not be used with new dependnecy graph");
+ (void)func;
+}
+
+/* ************************ DAG querying ********************* */
+
+Object *DAG_get_node_object(void *UNUSED(node_v))
+{
+ BLI_assert(!"Should not be used with new dependnecy graph");
+ return NULL;
+}
+
+const char *DAG_get_node_name(Scene *UNUSED(scene), void *UNUSED(node_v))
+{
+ BLI_assert(!"Should not be used with new dependnecy graph");
+ return "INVALID";
+}
+
+bool DAG_is_acyclic(Scene *UNUSED(scene))
+{
+ BLI_assert(!"Should not be used with new dependnecy graph");
+ return false;
+}
+
+/* ************************************
+ * This functions are to be supported *
+ * ************************************
+ */
+
+void DAG_init(void)
+{
+ DEG_register_node_types();
+}
+
+void DAG_exit(void)
+{
+ DEG_free_node_types();
+}
+
+/* ************************ API *********************** */
+
+void DAG_editors_update_cb(DEG_EditorUpdateIDCb id_func,
+ DEG_EditorUpdateSceneCb scene_func,
+ DEG_EditorUpdateScenePreCb scene_func_pre)
+{
+ DEG_editors_set_update_cb(id_func, scene_func, scene_func_pre);
+}
+
+void DAG_editors_update_pre(Main *bmain, Scene *scene, bool time)
+{
+ DEG_editors_update_pre(bmain, scene, time);
+}
+
+/* Tag all relations for update. */
+void DAG_relations_tag_update(Main *bmain)
+{
+ DEG_relations_tag_update(bmain);
+}
+
+/* Rebuild dependency graph only for a given scene. */
+void DAG_scene_relations_rebuild(Main *bmain, Scene *scene)
+{
+ DEG_scene_relations_rebuild(bmain, scene);
+}
+
+/* Create dependency graph if it was cleared or didn't exist yet. */
+void DAG_scene_relations_update(Main *bmain, Scene *scene)
+{
+ DEG_scene_relations_update(bmain, scene);
+}
+
+void DAG_scene_relations_validate(Main *bmain, Scene *scene)
+{
+ DEG_debug_scene_relations_validate(bmain, scene);
+}
+
+void DAG_scene_free(Scene *scene)
+{
+ DEG_scene_graph_free(scene);
+}
+
+void DAG_on_visible_update(Main *bmain, const bool do_time)
+{
+ DEG_on_visible_update(bmain, do_time);
+}
+
+void DAG_ids_check_recalc(Main *bmain, Scene *scene, bool time)
+{
+ DEG_ids_check_recalc(bmain, scene, time);
+}
+
+void DAG_id_tag_update(ID *id, short flag)
+{
+ DEG_id_tag_update_ex(G.main, id, flag);
+}
+
+void DAG_id_tag_update_ex(Main *bmain, ID *id, short flag)
+{
+ DEG_id_tag_update_ex(bmain, id, flag);
+}
+
+void DAG_id_type_tag(Main *bmain, short idtype)
+{
+ DEG_id_type_tag(bmain, idtype);
+}
+
+int DAG_id_type_tagged(Main *bmain, short idtype)
+{
+ return DEG_id_type_tagged(bmain, idtype);
+}
+
+void DAG_ids_clear_recalc(Main *bmain)
+{
+ DEG_ids_clear_recalc(bmain);
+}
+
+short DAG_get_eval_flags_for_object(Scene *scene, void *object)
+{
+ return DEG_get_eval_flags_for_id(scene->depsgraph, (ID *)object);
+}
+
+void DAG_ids_flush_tagged(Main *bmain)
+{
+ DEG_ids_flush_tagged(bmain);
+}
+
+/* ************************ DAG DEBUGGING ********************* */
+
+void DAG_print_dependencies(Main *UNUSED(bmain),
+ Scene *scene,
+ Object *UNUSED(ob))
+{
+ DEG_debug_graphviz(scene->depsgraph, stdout, "Depsgraph", false);
+}
+
+#endif
diff --git a/source/blender/blenkernel/intern/displist.c b/source/blender/blenkernel/intern/displist.c
index 98f0025921d..c83050627e9 100644
--- a/source/blender/blenkernel/intern/displist.c
+++ b/source/blender/blenkernel/intern/displist.c
@@ -37,7 +37,6 @@
#include "MEM_guardedalloc.h"
#include "DNA_curve_types.h"
-#include "DNA_meshdata_types.h"
#include "DNA_scene_types.h"
#include "DNA_object_types.h"
#include "DNA_vfont_types.h"
@@ -54,6 +53,7 @@
#include "BKE_cdderivedmesh.h"
#include "BKE_object.h"
#include "BKE_mball.h"
+#include "BKE_mball_tessellate.h"
#include "BKE_curve.h"
#include "BKE_key.h"
#include "BKE_anim.h"
@@ -352,7 +352,8 @@ static void curve_to_displist(Curve *cu, ListBase *nubase, ListBase *dispbase,
data = dl->verts;
- if (nu->flagu & CU_NURB_CYCLIC) {
+ /* check that (len != 2) so we don't immediately loop back on ourselves */
+ if (nu->flagu & CU_NURB_CYCLIC && (dl->nr != 2)) {
dl->type = DL_POLY;
a = nu->pntsu;
}
@@ -422,8 +423,12 @@ static void curve_to_displist(Curve *cu, ListBase *nubase, ListBase *dispbase,
dl->charidx = nu->charidx;
data = dl->verts;
- if (nu->flagu & CU_NURB_CYCLIC) dl->type = DL_POLY;
- else dl->type = DL_SEGM;
+ if ((nu->flagu & CU_NURB_CYCLIC) && (dl->nr != 2)) {
+ dl->type = DL_POLY;
+ }
+ else {
+ dl->type = DL_SEGM;
+ }
a = len;
bp = nu->bp;
@@ -512,7 +517,7 @@ void BKE_displist_fill(ListBase *dispbase, ListBase *to, const float normal_proj
dl = dl->next;
}
- /* XXX (obedit && obedit->actcol) ? (obedit->actcol-1) : 0)) { */
+ /* XXX (obedit && obedit->actcol) ? (obedit->actcol - 1) : 0)) { */
if (totvert && (tot = BLI_scanfill_calc_ex(&sf_ctx,
scanfill_flag,
normal_proj)))
@@ -759,7 +764,7 @@ static ModifierData *curve_get_tessellate_point(Scene *scene, Object *ob,
pretessellatePoint = NULL;
for (; md; md = md->next) {
- ModifierTypeInfo *mti = modifierType_getInfo(md->type);
+ const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
if (!modifier_isEnabled(scene, md, required_mode))
continue;
@@ -814,7 +819,7 @@ static void curve_calc_modifiers_pre(Scene *scene, Object *ob, ListBase *nurb,
required_mode |= eModifierMode_Editmode;
if (cu->editnurb == NULL) {
- keyVerts = BKE_key_evaluate_object(scene, ob, &numVerts);
+ keyVerts = BKE_key_evaluate_object(ob, &numVerts);
if (keyVerts) {
/* split coords from key data, the latter also includes
@@ -828,7 +833,7 @@ static void curve_calc_modifiers_pre(Scene *scene, Object *ob, ListBase *nurb,
if (pretessellatePoint) {
for (; md; md = md->next) {
- ModifierTypeInfo *mti = modifierType_getInfo(md->type);
+ const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
md->scene = scene;
@@ -929,7 +934,7 @@ static void curve_calc_modifiers_post(Scene *scene, Object *ob, ListBase *nurb,
}
for (; md; md = md->next) {
- ModifierTypeInfo *mti = modifierType_getInfo(md->type);
+ const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
ModifierApplyFlag appf = app_flag;
md->scene = scene;
@@ -1160,7 +1165,7 @@ static void curve_calc_orcodm(Scene *scene, Object *ob, DerivedMesh *dm_final,
orcodm = create_orco_dm(scene, ob);
for (; md; md = md->next) {
- ModifierTypeInfo *mti = modifierType_getInfo(md->type);
+ const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
md->scene = scene;
@@ -1271,6 +1276,7 @@ void BKE_displist_make_surf(Scene *scene, Object *ob, ListBase *dispbase,
}
if (!for_orco) {
+ BKE_nurbList_duplicate(&ob->curve_cache->deformed_nurbs, &nubase);
curve_calc_modifiers_post(scene, ob, &nubase, dispbase, r_dm_final,
for_render, use_render_resolution);
}
@@ -1429,9 +1435,8 @@ static void calc_bevfac_mapping(Curve *cu, BevList *bl, Nurb *nu,
return;
}
- if (ELEM(cu->bevfac1_mapping,
- CU_BEVFAC_MAP_SEGMENT,
- CU_BEVFAC_MAP_SPLINE))
+ if (ELEM(cu->bevfac1_mapping, CU_BEVFAC_MAP_SEGMENT, CU_BEVFAC_MAP_SPLINE) ||
+ ELEM(cu->bevfac2_mapping, CU_BEVFAC_MAP_SEGMENT, CU_BEVFAC_MAP_SPLINE))
{
for (i = 0; i < SEGMENTSU(nu); i++) {
total_length += bl->seglen[i];
@@ -1595,7 +1600,7 @@ static void do_makeDispListCurveTypes(Scene *scene, Object *ob, ListBase *dispba
float bottom_no[3] = {0.0f};
float top_no[3] = {0.0f};
float firstblend = 0.0f, lastblend = 0.0f;
- int i, start, steps;
+ int i, start, steps = 0;
if (nu->flagu & CU_NURB_CYCLIC) {
calc_bevfac_mapping_default(bl,
@@ -1621,8 +1626,12 @@ static void do_makeDispListCurveTypes(Scene *scene, Object *ob, ListBase *dispba
dl->type = DL_SURF;
dl->flag = dlb->flag & (DL_FRONT_CURVE | DL_BACK_CURVE);
- if (dlb->type == DL_POLY) dl->flag |= DL_CYCL_U;
- if (bl->poly >= 0) dl->flag |= DL_CYCL_V;
+ if (dlb->type == DL_POLY) {
+ dl->flag |= DL_CYCL_U;
+ }
+ if ((bl->poly >= 0) && (steps != 2)) {
+ dl->flag |= DL_CYCL_V;
+ }
dl->parts = steps;
dl->nr = dlb->nr;
@@ -1729,8 +1738,10 @@ static void do_makeDispListCurveTypes(Scene *scene, Object *ob, ListBase *dispba
}
}
- if (!for_orco)
+ if (!for_orco) {
+ BKE_nurbList_duplicate(&ob->curve_cache->deformed_nurbs, &nubase);
curve_calc_modifiers_post(scene, ob, &nubase, dispbase, r_dm_final, for_render, use_render_resolution);
+ }
if (cu->flag & CU_DEFORM_FILL && !ob->derivedFinal) {
curve_to_filledpoly(cu, &nubase, dispbase);
diff --git a/source/blender/blenkernel/intern/dynamicpaint.c b/source/blender/blenkernel/intern/dynamicpaint.c
index 4719013e2f8..f3ce988ee17 100644
--- a/source/blender/blenkernel/intern/dynamicpaint.c
+++ b/source/blender/blenkernel/intern/dynamicpaint.c
@@ -35,7 +35,7 @@
#include "BLI_threads.h"
#include "BLI_utildefines.h"
-#include "BLF_translation.h"
+#include "BLT_translation.h"
#include "DNA_anim_types.h"
#include "DNA_armature_types.h"
@@ -71,10 +71,6 @@
#include "BKE_scene.h"
#include "BKE_texture.h"
-#include "RNA_access.h"
-#include "RNA_define.h"
-#include "RNA_enum_types.h"
-
/* for image output */
#include "IMB_imbuf_types.h"
#include "IMB_imbuf.h"
@@ -204,12 +200,11 @@ typedef struct PaintBakeData {
/* UV Image sequence format point */
typedef struct PaintUVPoint {
/* Pixel / mesh data */
- unsigned int face_index, pixel_index; /* face index on domain derived mesh */
+ unsigned int tri_index, pixel_index; /* tri index on domain derived mesh */
unsigned int v1, v2, v3; /* vertex indexes */
unsigned int neighbour_pixel; /* If this pixel isn't uv mapped to any face,
* but it's neighboring pixel is */
- short quad;
} PaintUVPoint;
typedef struct ImgSeqFormatData {
@@ -257,20 +252,20 @@ static int dynamicPaint_surfaceNumOfPoints(DynamicPaintSurface *surface)
bool dynamicPaint_surfaceHasColorPreview(DynamicPaintSurface *surface)
{
if (surface->format == MOD_DPAINT_SURFACE_F_IMAGESEQ) {
- return 0;
+ return false;
}
else if (surface->format == MOD_DPAINT_SURFACE_F_VERTEX) {
if (surface->type == MOD_DPAINT_SURFACE_T_DISPLACE ||
surface->type == MOD_DPAINT_SURFACE_T_WAVE)
{
- return 0;
+ return false;
}
else {
- return 1;
+ return true;
}
}
else {
- return 1;
+ return true;
}
}
@@ -325,18 +320,18 @@ bool dynamicPaint_outputLayerExists(struct DynamicPaintSurface *surface, Object
else if (output == 1)
name = surface->output_name2;
else
- return 0;
+ return false;
if (surface->format == MOD_DPAINT_SURFACE_F_VERTEX) {
if (surface->type == MOD_DPAINT_SURFACE_T_PAINT) {
Mesh *me = ob->data;
- return (CustomData_get_named_layer_index(&me->fdata, CD_MCOL, name) != -1);
+ return (CustomData_get_named_layer_index(&me->ldata, CD_MLOOPCOL, name) != -1);
}
else if (surface->type == MOD_DPAINT_SURFACE_T_WEIGHT)
return (defgroup_name_index(ob, surface->output_name) != -1);
}
- return 0;
+ return false;
}
static bool surface_duplicateOutputExists(void *arg, const char *name)
@@ -372,7 +367,7 @@ static bool surface_duplicateNameExists(void *arg, const char *name)
DynamicPaintSurface *surface = t_surface->canvas->surfaces.first;
for (; surface; surface = surface->next) {
- if (surface != t_surface && !strcmp(name, surface->name)) return true;
+ if (surface != t_surface && STREQ(name, surface->name)) return true;
}
return false;
}
@@ -461,7 +456,7 @@ static void blendColors(const float t_color[3], float t_alpha, const float s_col
}
/* Mix two alpha weighed colors by a defined ratio. output is saved at a_color */
-static float mixColors(float a_color[3], float a_weight, float b_color[3], float b_weight, float ratio)
+static float mixColors(float a_color[3], float a_weight, const float b_color[3], float b_weight, float ratio)
{
float weight_ratio, factor;
if (b_weight) {
@@ -531,7 +526,7 @@ static int subframe_updateObject(Scene *scene, Object *ob, int flags, int parent
/* also update constraint targets */
for (con = ob->constraints.first; con; con = con->next) {
- bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
+ const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
ListBase targets = {NULL, NULL};
if (cti && cti->get_constraint_targets) {
@@ -583,7 +578,7 @@ static void scene_setSubframe(Scene *scene, float subframe)
scene->r.subframe = subframe;
}
-static int surface_getBrushFlags(DynamicPaintSurface *surface, Scene *scene)
+static int surface_getBrushFlags(DynamicPaintSurface *surface, const Scene *scene)
{
Base *base = NULL;
GroupObject *go = NULL;
@@ -1082,7 +1077,7 @@ DynamicPaintSurface *dynamicPaint_createNewSurface(DynamicPaintCanvasSettings *c
modifier_path_init(surface->image_output_path, sizeof(surface->image_output_path), "cache_dynamicpaint");
/* Using ID_BRUSH i18n context, as we have no physics/dpaint one for now... */
- dynamicPaintSurface_setUniqueName(surface, CTX_DATA_(BLF_I18NCONTEXT_ID_BRUSH, "Surface"));
+ dynamicPaintSurface_setUniqueName(surface, CTX_DATA_(BLT_I18NCONTEXT_ID_BRUSH, "Surface"));
surface->effector_weights = BKE_add_effector_weights(NULL);
@@ -1106,13 +1101,13 @@ bool dynamicPaint_createType(struct DynamicPaintModifierData *pmd, int type, str
canvas = pmd->canvas = MEM_callocN(sizeof(DynamicPaintCanvasSettings), "DynamicPaint Canvas");
if (!canvas)
- return 0;
+ return false;
canvas->pmd = pmd;
canvas->dm = NULL;
/* Create one surface */
if (!dynamicPaint_createNewSurface(canvas, scene))
- return 0;
+ return false;
}
else if (type == MOD_DYNAMICPAINT_TYPE_BRUSH) {
@@ -1122,7 +1117,7 @@ bool dynamicPaint_createType(struct DynamicPaintModifierData *pmd, int type, str
brush = pmd->brush = MEM_callocN(sizeof(DynamicPaintBrushSettings), "DynamicPaint Paint");
if (!brush)
- return 0;
+ return false;
brush->pmd = pmd;
brush->psys = NULL;
@@ -1157,7 +1152,7 @@ bool dynamicPaint_createType(struct DynamicPaintModifierData *pmd, int type, str
brush->paint_ramp = add_colorband(false);
if (!brush->paint_ramp)
- return 0;
+ return false;
ramp = brush->paint_ramp->data;
/* Add default smooth-falloff ramp. */
ramp[0].r = ramp[0].g = ramp[0].b = ramp[0].a = 1.0f;
@@ -1173,7 +1168,7 @@ bool dynamicPaint_createType(struct DynamicPaintModifierData *pmd, int type, str
brush->vel_ramp = add_colorband(false);
if (!brush->vel_ramp)
- return 0;
+ return false;
ramp = brush->vel_ramp->data;
ramp[0].r = ramp[0].g = ramp[0].b = ramp[0].a = ramp[0].pos = 0.0f;
ramp[1].r = ramp[1].g = ramp[1].b = ramp[1].a = ramp[1].pos = 1.0f;
@@ -1181,10 +1176,11 @@ bool dynamicPaint_createType(struct DynamicPaintModifierData *pmd, int type, str
}
}
}
- else
- return 0;
+ else {
+ return false;
+ }
- return 1;
+ return true;
}
void dynamicPaint_Modifier_copy(struct DynamicPaintModifierData *pmd, struct DynamicPaintModifierData *tpmd)
@@ -1450,7 +1446,7 @@ static void dynamicPaint_initAdjacencyData(DynamicPaintSurface *surface, int for
MEM_freeN(temp_data);
}
-static void dynamicPaint_setInitialColor(Scene *scene, DynamicPaintSurface *surface)
+static void dynamicPaint_setInitialColor(const Scene *scene, DynamicPaintSurface *surface)
{
PaintSurfaceData *sData = surface->data;
PaintPoint *pPoint = (PaintPoint *)sData->type_data;
@@ -1468,24 +1464,26 @@ static void dynamicPaint_setInitialColor(Scene *scene, DynamicPaintSurface *surf
/* apply color to every surface point */
#pragma omp parallel for schedule(static)
for (i = 0; i < sData->total_points; i++) {
- copy_v3_v3(pPoint[i].color, surface->init_color);
- pPoint[i].alpha = surface->init_color[3];
+ copy_v4_v4(pPoint[i].color, surface->init_color);
}
}
/* UV mapped texture */
else if (surface->init_color_type == MOD_DPAINT_INITIAL_TEXTURE) {
Tex *tex = surface->init_texture;
- MTFace *tface;
- MFace *mface = dm->getTessFaceArray(dm);
- int numOfFaces = dm->getNumTessFaces(dm);
+
+ const MLoop *mloop = dm->getLoopArray(dm);
+ const MLoopTri *mlooptri = dm->getLoopTriArray(dm);
+ const int tottri = dm->getNumLoopTri(dm);
+ const MLoopUV *mloopuv = NULL;
+
char uvname[MAX_CUSTOMDATA_LAYER_NAME];
if (!tex) return;
/* get uv map */
- CustomData_validate_layer_name(&dm->faceData, CD_MTFACE, surface->init_layername, uvname);
- tface = CustomData_get_layer_named(&dm->faceData, CD_MTFACE, uvname);
- if (!tface) return;
+ CustomData_validate_layer_name(&dm->loopData, CD_MLOOPUV, surface->init_layername, uvname);
+ mloopuv = CustomData_get_layer_named(&dm->loopData, CD_MLOOPUV, uvname);
+ if (!mloopuv) return;
/* for vertex surface loop through tfaces and find uv color
* that provides highest alpha */
@@ -1493,23 +1491,22 @@ static void dynamicPaint_setInitialColor(Scene *scene, DynamicPaintSurface *surf
struct ImagePool *pool = BKE_image_pool_new();
#pragma omp parallel for schedule(static) shared(pool)
- for (i = 0; i < numOfFaces; i++) {
- int numOfVert = (mface[i].v4) ? 4 : 3;
+ for (i = 0; i < tottri; i++) {
float uv[3] = {0.0f};
int j;
- for (j = 0; j < numOfVert; j++) {
+ for (j = 0; j < 3; j++) {
TexResult texres = {0};
- unsigned int *vert = (&mface[i].v1) + j;
+ unsigned int vert = mloop[mlooptri[i].tri[j]].v;
/* remap to -1.0 to 1.0 */
- uv[0] = tface[i].uv[j][0] * 2.0f - 1.0f;
- uv[1] = tface[i].uv[j][1] * 2.0f - 1.0f;
+ uv[0] = mloopuv[mlooptri[i].tri[j]].uv[0] * 2.0f - 1.0f;
+ uv[1] = mloopuv[mlooptri[i].tri[j]].uv[1] * 2.0f - 1.0f;
- multitex_ext_safe(tex, uv, &texres, pool, scene_color_manage);
+ multitex_ext_safe(tex, uv, &texres, pool, scene_color_manage, false);
- if (texres.tin > pPoint[*vert].alpha) {
- copy_v3_v3(pPoint[*vert].color, &texres.tr);
- pPoint[*vert].alpha = texres.tin;
+ if (texres.tin > pPoint[vert].color[3]) {
+ copy_v3_v3(pPoint[vert].color, &texres.tr);
+ pPoint[vert].color[3] = texres.tin;
}
}
}
@@ -1528,8 +1525,7 @@ static void dynamicPaint_setInitialColor(Scene *scene, DynamicPaintSurface *surf
/* collect all uvs */
for (j = 0; j < 3; j++) {
- int v = (f_data->uv_p[i].quad && j > 0) ? j + 1 : j;
- copy_v2_v2(&uv[j * 3], tface[f_data->uv_p[i].face_index].uv[v]);
+ copy_v2_v2(&uv[j * 3], mloopuv[mlooptri[f_data->uv_p[i].tri_index].tri[j]].uv);
}
/* interpolate final uv pos */
@@ -1539,11 +1535,11 @@ static void dynamicPaint_setInitialColor(Scene *scene, DynamicPaintSurface *surf
uv_final[0] = uv_final[0] * 2.0f - 1.0f;
uv_final[1] = uv_final[1] * 2.0f - 1.0f;
- multitex_ext_safe(tex, uv_final, &texres, NULL, scene_color_manage);
+ multitex_ext_safe(tex, uv_final, &texres, NULL, scene_color_manage, false);
/* apply color */
copy_v3_v3(pPoint[i].color, &texres.tr);
- pPoint[i].alpha = texres.tin;
+ pPoint[i].color[3] = texres.tin;
}
}
}
@@ -1552,53 +1548,46 @@ static void dynamicPaint_setInitialColor(Scene *scene, DynamicPaintSurface *surf
/* for vertex surface, just copy colors from mcol */
if (surface->format == MOD_DPAINT_SURFACE_F_VERTEX) {
- MLoop *mloop = dm->getLoopArray(dm);
- int numOfLoops = dm->getNumLoops(dm);
- MCol *col = CustomData_get_layer_named(&dm->loopData, CD_MLOOPCOL, surface->init_layername);
+ const MLoop *mloop = dm->getLoopArray(dm);
+ const int totloop = dm->getNumLoops(dm);
+ const MLoopCol *col = CustomData_get_layer_named(&dm->loopData, CD_MLOOPCOL, surface->init_layername);
if (!col) return;
#pragma omp parallel for schedule(static)
- for (i = 0; i < numOfLoops; i++) {
- pPoint[mloop[i].v].color[0] = 1.0f / 255.f * (float)col[i].b;
- pPoint[mloop[i].v].color[1] = 1.0f / 255.f * (float)col[i].g;
- pPoint[mloop[i].v].color[2] = 1.0f / 255.f * (float)col[i].r;
- pPoint[mloop[i].v].alpha = 1.0f / 255.f * (float)col[i].a;
+ for (i = 0; i < totloop; i++) {
+ rgba_uchar_to_float(pPoint[mloop[i].v].color, (const unsigned char *)&col[mloop[i].v].r);
}
}
else if (surface->format == MOD_DPAINT_SURFACE_F_IMAGESEQ) {
+ const MLoopTri *mlooptri = dm->getLoopTriArray(dm);
ImgSeqFormatData *f_data = (ImgSeqFormatData *)sData->format_data;
int samples = (surface->flags & MOD_DPAINT_ANTIALIAS) ? 5 : 1;
- MCol *col = CustomData_get_layer_named(&dm->faceData, CD_MCOL, surface->init_layername);
+ MLoopCol *col = CustomData_get_layer_named(&dm->loopData, CD_MLOOPCOL, surface->init_layername);
if (!col) return;
#pragma omp parallel for schedule(static)
for (i = 0; i < sData->total_points; i++) {
- int face_ind = f_data->uv_p[i].face_index;
- float colors[3][4] = {{0.0f, 0.0f, 0.0f, 0.0f}};
+ int tri_ind = f_data->uv_p[i].tri_index;
+ float colors[3][4];
float final_color[4];
int j;
+
/* collect color values */
for (j = 0; j < 3; j++) {
- int v = (f_data->uv_p[i].quad && j > 0) ? j + 1 : j;
- colors[j][0] = 1.0f / 255.f * (float)col[face_ind * 4 + v].b;
- colors[j][1] = 1.0f / 255.f * (float)col[face_ind * 4 + v].g;
- colors[j][2] = 1.0f / 255.f * (float)col[face_ind * 4 + v].r;
- colors[j][3] = 1.0f / 255.f * (float)col[face_ind * 4 + v].a;
+ rgba_uchar_to_float(colors[j], (const unsigned char *)&col[mlooptri[tri_ind].tri[j]].r);
}
-
+
/* interpolate final color */
- interp_v4_v4v4v4(final_color, colors[0], colors[1], colors[2],
- f_data->barycentricWeights[i * samples].v);
+ interp_v4_v4v4v4(final_color, UNPACK3(colors), f_data->barycentricWeights[i * samples].v);
- copy_v3_v3(pPoint[i].color, final_color);
- pPoint[i].alpha = final_color[3];
+ copy_v4_v4(pPoint[i].color, final_color);
}
}
}
}
/* clears surface data back to zero */
-void dynamicPaint_clearSurface(Scene *scene, DynamicPaintSurface *surface)
+void dynamicPaint_clearSurface(const Scene *scene, DynamicPaintSurface *surface)
{
PaintSurfaceData *sData = surface->data;
if (sData && sData->type_data) {
@@ -1623,19 +1612,19 @@ void dynamicPaint_clearSurface(Scene *scene, DynamicPaintSurface *surface)
}
/* completely (re)initializes surface (only for point cache types)*/
-bool dynamicPaint_resetSurface(Scene *scene, DynamicPaintSurface *surface)
+bool dynamicPaint_resetSurface(const Scene *scene, DynamicPaintSurface *surface)
{
int numOfPoints = dynamicPaint_surfaceNumOfPoints(surface);
/* free existing data */
if (surface->data) dynamicPaint_freeSurfaceData(surface);
/* don't reallocate for image sequence types. they get handled only on bake */
- if (surface->format == MOD_DPAINT_SURFACE_F_IMAGESEQ) return 1;
- if (numOfPoints < 1) return 0;
+ if (surface->format == MOD_DPAINT_SURFACE_F_IMAGESEQ) return true;
+ if (numOfPoints < 1) return false;
/* allocate memory */
surface->data = MEM_callocN(sizeof(PaintSurfaceData), "PaintSurfaceData");
- if (!surface->data) return 0;
+ if (!surface->data) return false;
/* allocate data depending on surface type and format */
surface->data->total_points = numOfPoints;
@@ -1646,16 +1635,16 @@ bool dynamicPaint_resetSurface(Scene *scene, DynamicPaintSurface *surface)
if (surface->type == MOD_DPAINT_SURFACE_T_PAINT)
dynamicPaint_setInitialColor(scene, surface);
- return 1;
+ return true;
}
/* make sure allocated surface size matches current requirements */
-static bool dynamicPaint_checkSurfaceData(Scene *scene, DynamicPaintSurface *surface)
+static bool dynamicPaint_checkSurfaceData(const Scene *scene, DynamicPaintSurface *surface)
{
if (!surface->data || ((dynamicPaint_surfaceNumOfPoints(surface) != surface->data->total_points))) {
return dynamicPaint_resetSurface(scene, surface);
}
- return 1;
+ return true;
}
@@ -1727,7 +1716,7 @@ static DerivedMesh *dynamicPaint_Modifier_apply(DynamicPaintModifierData *pmd,
#pragma omp parallel for schedule(static)
for (i = 0; i < sData->total_points; i++) {
/* blend dry and wet layer */
- blendColors(pPoint[i].color, pPoint[i].alpha, pPoint[i].e_color, pPoint[i].e_alpha, &fcolor[i * 4]);
+ blendColors(pPoint[i].color, pPoint[i].color[3], pPoint[i].e_color, pPoint[i].e_color[3], &fcolor[i * 4]);
}
/* viewport preview */
@@ -1784,8 +1773,8 @@ static DerivedMesh *dynamicPaint_Modifier_apply(DynamicPaintModifierData *pmd,
}
else {
col[l_index].r =
- col[l_index].g =
- col[l_index].b = FTOCHAR(pPoint[v_index].wetness);
+ col[l_index].g =
+ col[l_index].b = FTOCHAR(pPoint[v_index].wetness);
col[l_index].a = 255;
}
}
@@ -2007,9 +1996,8 @@ static void dynamicPaint_frameUpdate(DynamicPaintModifierData *pmd, Scene *scene
/* Modifier call. Processes dynamic paint modifier step. */
DerivedMesh *dynamicPaint_Modifier_do(DynamicPaintModifierData *pmd, Scene *scene, Object *ob, DerivedMesh *dm)
{
- /* For now generate tessfaces in every case
- * XXX - move/remove when most of dpaint functions are converted to use bmesh types */
- DM_ensure_tessface(dm);
+ /* For now generate looptris in every case */
+ DM_ensure_looptri(dm);
/* Update canvas data for a new frame */
dynamicPaint_frameUpdate(pmd, scene, ob, dm);
@@ -2054,7 +2042,7 @@ static int dynamicPaint_findNeighbourPixel(PaintUVPoint *tempPoints, DerivedMesh
* Check if shifted point is on same face -> it's a correct neighbor
* (and if it isn't marked as an "edge pixel")
*/
- if ((tPoint->face_index == cPoint->face_index) && (tPoint->neighbour_pixel == -1))
+ if ((tPoint->tri_index == cPoint->tri_index) && (tPoint->neighbour_pixel == -1))
return (x + w * y);
/*
@@ -2065,7 +2053,7 @@ static int dynamicPaint_findNeighbourPixel(PaintUVPoint *tempPoints, DerivedMesh
* This should work fine as long as uv island
* margin is > 1 pixel.
*/
- if ((tPoint->face_index != -1) && (tPoint->neighbour_pixel == -1)) {
+ if ((tPoint->tri_index != -1) && (tPoint->neighbour_pixel == -1)) {
return (x + w * y);
}
@@ -2083,9 +2071,10 @@ static int dynamicPaint_findNeighbourPixel(PaintUVPoint *tempPoints, DerivedMesh
* TODO: Implement something more accurate / optimized?
*/
{
- int numOfFaces = dm->getNumTessFaces(dm);
- MFace *mface = dm->getTessFaceArray(dm);
- MTFace *tface = CustomData_get_layer_named(&dm->faceData, CD_MTFACE, uvname);
+ const MLoop *mloop = dm->getLoopArray(dm);
+ const MLoopTri *mlooptri = dm->getLoopTriArray(dm);
+ const int tottri = dm->getNumLoopTri(dm);
+ const MLoopUV *mloopuv = CustomData_get_layer_named(&dm->loopData, CD_MLOOPUV, uvname);
/* Get closest edge to that subpixel on UV map */
{
@@ -2093,85 +2082,98 @@ static int dynamicPaint_findNeighbourPixel(PaintUVPoint *tempPoints, DerivedMesh
/* distances only used for comparison */
float dist_squared, t_dist_squared;
- int i, uindex[3], edge1_index, edge2_index,
- e1_index, e2_index, target_face;
+ int i, edge1_index, edge2_index,
+ e1_index, e2_index, target_tri;
float closest_point[2], lambda, dir_vec[2];
- int target_uv1, target_uv2, final_pixel[2], final_index;
+ int target_uv1 = 0, target_uv2 = 0, final_pixel[2], final_index;
const float *s_uv1, *s_uv2, *t_uv1, *t_uv2;
pixel[0] = ((float)(px + neighX[n_index]) + 0.5f) / (float)w;
pixel[1] = ((float)(py + neighY[n_index]) + 0.5f) / (float)h;
- /* Get uv indexes for current face part */
- if (cPoint->quad) {
- uindex[0] = 0; uindex[1] = 2; uindex[2] = 3;
- }
- else {
- uindex[0] = 0; uindex[1] = 1; uindex[2] = 2;
- }
-
/*
* Find closest edge to that pixel
*/
+
/* Dist to first edge */
- e1_index = cPoint->v1; e2_index = cPoint->v2; edge1_index = uindex[0]; edge2_index = uindex[1];
- dist_squared = dist_squared_to_line_segment_v2(pixel, tface[cPoint->face_index].uv[edge1_index], tface[cPoint->face_index].uv[edge2_index]);
+ e1_index = cPoint->v1;
+ e2_index = cPoint->v2;
+ edge1_index = 0;
+ edge2_index = 1;
+ dist_squared = dist_squared_to_line_segment_v2(
+ pixel,
+ mloopuv[mlooptri[cPoint->tri_index].tri[0]].uv,
+ mloopuv[mlooptri[cPoint->tri_index].tri[1]].uv);
/* Dist to second edge */
- t_dist_squared = dist_squared_to_line_segment_v2(pixel, tface[cPoint->face_index].uv[uindex[1]], tface[cPoint->face_index].uv[uindex[2]]);
- if (t_dist_squared < dist_squared) { e1_index = cPoint->v2; e2_index = cPoint->v3; edge1_index = uindex[1]; edge2_index = uindex[2]; dist_squared = t_dist_squared; }
+ t_dist_squared = dist_squared_to_line_segment_v2(
+ pixel,
+ mloopuv[mlooptri[cPoint->tri_index].tri[1]].uv,
+ mloopuv[mlooptri[cPoint->tri_index].tri[2]].uv);
+ if (t_dist_squared < dist_squared) {
+ e1_index = cPoint->v2;
+ e2_index = cPoint->v3;
+ edge1_index = 1;
+ edge2_index = 2;
+ dist_squared = t_dist_squared;
+ }
/* Dist to third edge */
- t_dist_squared = dist_squared_to_line_segment_v2(pixel, tface[cPoint->face_index].uv[uindex[2]], tface[cPoint->face_index].uv[uindex[0]]);
- if (t_dist_squared < dist_squared) { e1_index = cPoint->v3; e2_index = cPoint->v1; edge1_index = uindex[2]; edge2_index = uindex[0]; dist_squared = t_dist_squared; }
+ t_dist_squared = dist_squared_to_line_segment_v2(
+ pixel,
+ mloopuv[mlooptri[cPoint->tri_index].tri[2]].uv,
+ mloopuv[mlooptri[cPoint->tri_index].tri[0]].uv);
+ if (t_dist_squared < dist_squared) {
+ e1_index = cPoint->v3;
+ e2_index = cPoint->v1;
+ edge1_index = 2;
+ edge2_index = 0;
+ dist_squared = t_dist_squared;
+ }
/*
* Now find another face that is linked to that edge
*/
- target_face = -1;
+ target_tri = -1;
- for (i = 0; i < numOfFaces; i++) {
+ for (i = 0; i < tottri; i++) {
/*
* Check if both edge vertices share this face
*/
- int v4 = (mface[i].v4) ? mface[i].v4 : -1;
-
- if ((e1_index == mface[i].v1 || e1_index == mface[i].v2 || e1_index == mface[i].v3 || e1_index == v4) &&
- (e2_index == mface[i].v1 || e2_index == mface[i].v2 || e2_index == mface[i].v3 || e2_index == v4))
+ if ((e1_index == mloop[mlooptri[i].tri[0]].v || e1_index == mloop[mlooptri[i].tri[1]].v || e1_index == mloop[mlooptri[i].tri[2]].v) &&
+ (e2_index == mloop[mlooptri[i].tri[0]].v || e2_index == mloop[mlooptri[i].tri[1]].v || e2_index == mloop[mlooptri[i].tri[2]].v))
{
- if (i == cPoint->face_index) continue;
+ if (i == cPoint->tri_index) continue;
- target_face = i;
+ target_tri = i;
/*
* Get edge UV index
*/
- if (e1_index == mface[i].v1) target_uv1 = 0;
- else if (e1_index == mface[i].v2) target_uv1 = 1;
- else if (e1_index == mface[i].v3) target_uv1 = 2;
- else target_uv1 = 3;
+ if (e1_index == mloop[mlooptri[i].tri[0]].v) target_uv1 = 0;
+ else if (e1_index == mloop[mlooptri[i].tri[1]].v) target_uv1 = 1;
+ else if (e1_index == mloop[mlooptri[i].tri[2]].v) target_uv1 = 2;
- if (e2_index == mface[i].v1) target_uv2 = 0;
- else if (e2_index == mface[i].v2) target_uv2 = 1;
- else if (e2_index == mface[i].v3) target_uv2 = 2;
- else target_uv2 = 3;
+ if (e2_index == mloop[mlooptri[i].tri[0]].v) target_uv2 = 0;
+ else if (e2_index == mloop[mlooptri[i].tri[1]].v) target_uv2 = 1;
+ else if (e2_index == mloop[mlooptri[i].tri[2]].v) target_uv2 = 2;
break;
}
}
/* If none found pixel is on mesh edge */
- if (target_face == -1) return ON_MESH_EDGE;
+ if (target_tri == -1) return ON_MESH_EDGE;
/*
* If target face is connected in UV space as well, just use original index
*/
- s_uv1 = (float *)tface[cPoint->face_index].uv[edge1_index];
- s_uv2 = (float *)tface[cPoint->face_index].uv[edge2_index];
- t_uv1 = (float *)tface[target_face].uv[target_uv1];
- t_uv2 = (float *)tface[target_face].uv[target_uv2];
+ s_uv1 = mloopuv[mlooptri[cPoint->tri_index].tri[edge1_index]].uv;
+ s_uv2 = mloopuv[mlooptri[cPoint->tri_index].tri[edge2_index]].uv;
+ t_uv1 = mloopuv[mlooptri[target_tri].tri[target_uv1]].uv;
+ t_uv2 = mloopuv[mlooptri[target_tri].tri[target_uv2]].uv;
//printf("connected UV : %f,%f & %f,%f - %f,%f & %f,%f\n", s_uv1[0], s_uv1[1], s_uv2[0], s_uv2[1], t_uv1[0], t_uv1[1], t_uv2[0], t_uv2[1]);
@@ -2187,15 +2189,21 @@ static int dynamicPaint_findNeighbourPixel(PaintUVPoint *tempPoints, DerivedMesh
* Find a point that is relatively at same edge position
* on this other face UV
*/
- lambda = closest_to_line_v2(closest_point, pixel, tface[cPoint->face_index].uv[edge1_index], tface[cPoint->face_index].uv[edge2_index]);
+ lambda = closest_to_line_v2(
+ closest_point, pixel,
+ mloopuv[mlooptri[cPoint->tri_index].tri[edge1_index]].uv,
+ mloopuv[mlooptri[cPoint->tri_index].tri[edge2_index]].uv);
if (lambda < 0.0f) lambda = 0.0f;
if (lambda > 1.0f) lambda = 1.0f;
- sub_v2_v2v2(dir_vec, tface[target_face].uv[target_uv2], tface[target_face].uv[target_uv1]);
+ sub_v2_v2v2(
+ dir_vec,
+ mloopuv[mlooptri[target_tri].tri[target_uv2]].uv,
+ mloopuv[mlooptri[target_tri].tri[target_uv1]].uv);
mul_v2_fl(dir_vec, lambda);
- copy_v2_v2(pixel, tface[target_face].uv[target_uv1]);
+ copy_v2_v2(pixel, mloopuv[mlooptri[target_tri].tri[target_uv1]].uv);
add_v2_v2(pixel, dir_vec);
pixel[0] = (pixel[0] * (float)w) - 0.5f;
pixel[1] = (pixel[1] * (float)h) - 0.5f;
@@ -2212,7 +2220,9 @@ static int dynamicPaint_findNeighbourPixel(PaintUVPoint *tempPoints, DerivedMesh
/* If we ended up to our origin point ( mesh has smaller than pixel sized faces) */
if (final_index == (px + w * py)) return NOT_FOUND;
/* If found pixel still lies on wrong face ( mesh has smaller than pixel sized faces) */
- if (tempPoints[final_index].face_index != target_face) return NOT_FOUND;
+ if (tempPoints[final_index].tri_index != target_tri) {
+ return NOT_FOUND;
+ }
/*
* If final point is an "edge pixel", use it's "real" neighbor instead
@@ -2239,7 +2249,7 @@ int dynamicPaint_createUVSurface(Scene *scene, DynamicPaintSurface *surface)
};
int ty;
int w, h;
- int numOfFaces;
+ int tottri;
char uvname[MAX_CUSTOMDATA_LAYER_NAME];
int active_points = 0;
int error = 0;
@@ -2250,8 +2260,10 @@ int dynamicPaint_createUVSurface(Scene *scene, DynamicPaintSurface *surface)
PaintUVPoint *tempPoints = NULL;
Vec3f *tempWeights = NULL;
- MFace *mface = NULL;
- MTFace *tface = NULL;
+ const MLoopTri *mlooptri = NULL;
+ const MLoopUV *mloopuv = NULL;
+ const MLoop *mloop = NULL;
+
Bounds2D *faceBB = NULL;
int *final_index;
int aa_samples;
@@ -2261,15 +2273,16 @@ int dynamicPaint_createUVSurface(Scene *scene, DynamicPaintSurface *surface)
if (surface->format != MOD_DPAINT_SURFACE_F_IMAGESEQ)
return setError(canvas, N_("Cannot bake non-'image sequence' formats"));
- numOfFaces = dm->getNumTessFaces(dm);
- mface = dm->getTessFaceArray(dm);
+ mloop = dm->getLoopArray(dm);
+ mlooptri = dm->getLoopTriArray(dm);
+ tottri = dm->getNumLoopTri(dm);
/* get uv map */
- CustomData_validate_layer_name(&dm->faceData, CD_MTFACE, surface->uvlayer_name, uvname);
- tface = CustomData_get_layer_named(&dm->faceData, CD_MTFACE, uvname);
+ CustomData_validate_layer_name(&dm->loopData, CD_MLOOPUV, surface->uvlayer_name, uvname);
+ mloopuv = CustomData_get_layer_named(&dm->loopData, CD_MLOOPUV, uvname);
/* Check for validity */
- if (!tface)
+ if (!mloopuv)
return setError(canvas, N_("No UV data on canvas"));
if (surface->image_resolution < 16 || surface->image_resolution > 8192)
return setError(canvas, N_("Invalid resolution"));
@@ -2279,7 +2292,7 @@ int dynamicPaint_createUVSurface(Scene *scene, DynamicPaintSurface *surface)
/*
* Start generating the surface
*/
- printf("DynamicPaint: Preparing UV surface of %ix%i pixels and %i faces.\n", w, h, numOfFaces);
+ printf("DynamicPaint: Preparing UV surface of %ix%i pixels and %i tris.\n", w, h, tottri);
/* Init data struct */
if (surface->data) dynamicPaint_freeSurfaceData(surface);
@@ -2302,24 +2315,22 @@ int dynamicPaint_createUVSurface(Scene *scene, DynamicPaintSurface *surface)
* the pixel-inside-a-face search.
*/
if (!error) {
- faceBB = (struct Bounds2D *) MEM_mallocN(numOfFaces * sizeof(struct Bounds2D), "MPCanvasFaceBB");
+ faceBB = (struct Bounds2D *) MEM_mallocN(tottri * sizeof(struct Bounds2D), "MPCanvasFaceBB");
if (!faceBB) error = 1;
}
if (!error)
- for (ty = 0; ty < numOfFaces; ty++) {
- int numOfVert = (mface[ty].v4) ? 4 : 3;
+ for (ty = 0; ty < tottri; ty++) {
int i;
- copy_v2_v2(faceBB[ty].min, tface[ty].uv[0]);
- copy_v2_v2(faceBB[ty].max, tface[ty].uv[0]);
-
- for (i = 1; i < numOfVert; i++) {
- if (tface[ty].uv[i][0] < faceBB[ty].min[0]) faceBB[ty].min[0] = tface[ty].uv[i][0];
- if (tface[ty].uv[i][1] < faceBB[ty].min[1]) faceBB[ty].min[1] = tface[ty].uv[i][1];
- if (tface[ty].uv[i][0] > faceBB[ty].max[0]) faceBB[ty].max[0] = tface[ty].uv[i][0];
- if (tface[ty].uv[i][1] > faceBB[ty].max[1]) faceBB[ty].max[1] = tface[ty].uv[i][1];
+ copy_v2_v2(faceBB[ty].min, mloopuv[mlooptri[ty].tri[0]].uv);
+ copy_v2_v2(faceBB[ty].max, mloopuv[mlooptri[ty].tri[0]].uv);
+ for (i = 1; i < 3; i++) {
+ CLAMP_MAX(faceBB[ty].min[0], mloopuv[mlooptri[ty].tri[i]].uv[0]);
+ CLAMP_MAX(faceBB[ty].min[1], mloopuv[mlooptri[ty].tri[i]].uv[1]);
+ CLAMP_MIN(faceBB[ty].max[0], mloopuv[mlooptri[ty].tri[i]].uv[0]);
+ CLAMP_MIN(faceBB[ty].max[1], mloopuv[mlooptri[ty].tri[i]].uv[1]);
}
}
@@ -2336,13 +2347,13 @@ int dynamicPaint_createUVSurface(Scene *scene, DynamicPaintSurface *surface)
int index = tx + w * ty;
PaintUVPoint *tPoint = (&tempPoints[index]);
- short isInside = 0; /* if point is inside a uv face */
+ bool isInside = false; /* if point is inside a uv face */
float d1[2], d2[2], d3[2], point[5][2];
float dot00, dot01, dot02, dot11, dot12, invDenom, u, v;
/* Init per pixel settings */
- tPoint->face_index = -1;
+ tPoint->tri_index = -1;
tPoint->neighbour_pixel = -1;
tPoint->pixel_index = index;
@@ -2369,9 +2380,9 @@ int dynamicPaint_createUVSurface(Scene *scene, DynamicPaintSurface *surface)
/* Loop through samples, starting from middle point */
for (sample = 0; sample < 5; sample++) {
-
+
/* Loop through every face in the mesh */
- for (i = 0; i < numOfFaces; i++) {
+ for (i = 0; i < tottri; i++) {
/* Check uv bb */
if (faceBB[i].min[0] > (point[sample][0])) continue;
@@ -2381,9 +2392,9 @@ int dynamicPaint_createUVSurface(Scene *scene, DynamicPaintSurface *surface)
/* Calculate point inside a triangle check
* for uv0, 1, 2 */
- sub_v2_v2v2(d1, tface[i].uv[2], tface[i].uv[0]); // uv2 - uv0
- sub_v2_v2v2(d2, tface[i].uv[1], tface[i].uv[0]); // uv1 - uv0
- sub_v2_v2v2(d3, point[sample], tface[i].uv[0]); // point - uv0
+ sub_v2_v2v2(d1, mloopuv[mlooptri[i].tri[2]].uv, mloopuv[mlooptri[i].tri[0]].uv); /* uv2 - uv0 */
+ sub_v2_v2v2(d2, mloopuv[mlooptri[i].tri[1]].uv, mloopuv[mlooptri[i].tri[0]].uv); /* uv1 - uv0 */
+ sub_v2_v2v2(d3, point[sample], mloopuv[mlooptri[i].tri[0]].uv); /* point - uv0 */
dot00 = d1[0] * d1[0] + d1[1] * d1[1];
dot01 = d1[0] * d2[0] + d1[1] * d2[1];
@@ -2396,50 +2407,20 @@ int dynamicPaint_createUVSurface(Scene *scene, DynamicPaintSurface *surface)
u = (dot11 * dot02 - dot01 * dot12) * invDenom;
v = (dot00 * dot12 - dot01 * dot02) * invDenom;
- if ((u > 0) && (v > 0) && (u + v < 1)) { isInside = 1; } /* is inside a triangle */
-
- /* If collision wasn't found but the face is a quad
- * do another check for the second half */
- if ((!isInside) && mface[i].v4) {
-
- /* change d2 to test the other half */
- sub_v2_v2v2(d2, tface[i].uv[3], tface[i].uv[0]); // uv3 - uv0
-
- /* test again */
- dot00 = d1[0] * d1[0] + d1[1] * d1[1];
- dot01 = d1[0] * d2[0] + d1[1] * d2[1];
- dot02 = d1[0] * d3[0] + d1[1] * d3[1];
- dot11 = d2[0] * d2[0] + d2[1] * d2[1];
- dot12 = d2[0] * d3[0] + d2[1] * d3[1];
-
- invDenom = (dot00 * dot11 - dot01 * dot01);
- invDenom = invDenom ? 1.0f / invDenom : 1.0f;
- u = (dot11 * dot02 - dot01 * dot12) * invDenom;
- v = (dot00 * dot12 - dot01 * dot02) * invDenom;
-
- if ((u > 0) && (v > 0) && (u + v < 1)) { isInside = 2; } /* is inside the second half of the quad */
-
- }
+ if ((u > 0) && (v > 0) && (u + v < 1)) { isInside = true; } /* is inside a triangle */
/*
* If point was inside the face
*/
- if (isInside != 0) {
+ if (isInside) {
float uv1co[2], uv2co[2], uv3co[2], uv[2];
int j;
/* Get triagnle uvs */
- if (isInside == 1) {
- copy_v2_v2(uv1co, tface[i].uv[0]);
- copy_v2_v2(uv2co, tface[i].uv[1]);
- copy_v2_v2(uv3co, tface[i].uv[2]);
- }
- else {
- copy_v2_v2(uv1co, tface[i].uv[0]);
- copy_v2_v2(uv2co, tface[i].uv[2]);
- copy_v2_v2(uv3co, tface[i].uv[3]);
- }
+ copy_v2_v2(uv1co, mloopuv[mlooptri[i].tri[0]].uv);
+ copy_v2_v2(uv2co, mloopuv[mlooptri[i].tri[1]].uv);
+ copy_v2_v2(uv3co, mloopuv[mlooptri[i].tri[2]].uv);
/* Add b-weights per anti-aliasing sample */
for (j = 0; j < aa_samples; j++) {
@@ -2450,13 +2431,12 @@ int dynamicPaint_createUVSurface(Scene *scene, DynamicPaintSurface *surface)
}
/* Set surface point face values */
- tPoint->face_index = i; /* face index */
- tPoint->quad = (isInside == 2) ? 1 : 0; /* quad or tri part*/
+ tPoint->tri_index = i;
/* save vertex indexes */
- tPoint->v1 = mface[i].v1;
- tPoint->v2 = (isInside == 2) ? mface[i].v3 : mface[i].v2;
- tPoint->v3 = (isInside == 2) ? mface[i].v4 : mface[i].v3;
+ tPoint->v1 = mloop[mlooptri[i].tri[0]].v;
+ tPoint->v2 = mloop[mlooptri[i].tri[1]].v;
+ tPoint->v3 = mloop[mlooptri[i].tri[2]].v;
sample = 5; /* make sure we exit sample loop as well */
break;
@@ -2480,7 +2460,7 @@ int dynamicPaint_createUVSurface(Scene *scene, DynamicPaintSurface *surface)
PaintUVPoint *tPoint = (&tempPoints[index]);
/* If point isn't't on canvas mesh */
- if (tPoint->face_index == -1) {
+ if (tPoint->tri_index == -1) {
int u_min, u_max, v_min, v_max;
int u, v, ind;
float point[2];
@@ -2502,22 +2482,15 @@ int dynamicPaint_createUVSurface(Scene *scene, DynamicPaintSurface *surface)
ind = (tx + u) + w * (ty + v);
/* if neighbor has index */
- if (tempPoints[ind].face_index != -1) {
+ if (tempPoints[ind].tri_index != -1) {
float uv1co[2], uv2co[2], uv3co[2], uv[2];
- int i = tempPoints[ind].face_index, j;
+ int i = tempPoints[ind].tri_index, j;
/* Now calculate pixel data for this pixel as it was on polygon surface */
- if (!tempPoints[ind].quad) {
- copy_v2_v2(uv1co, tface[i].uv[0]);
- copy_v2_v2(uv2co, tface[i].uv[1]);
- copy_v2_v2(uv3co, tface[i].uv[2]);
- }
- else {
- copy_v2_v2(uv1co, tface[i].uv[0]);
- copy_v2_v2(uv2co, tface[i].uv[2]);
- copy_v2_v2(uv3co, tface[i].uv[3]);
- }
+ copy_v2_v2(uv1co, mloopuv[mlooptri[i].tri[0]].uv);
+ copy_v2_v2(uv2co, mloopuv[mlooptri[i].tri[1]].uv);
+ copy_v2_v2(uv3co, mloopuv[mlooptri[i].tri[2]].uv);
/* Add b-weights per anti-aliasing sample */
for (j = 0; j < aa_samples; j++) {
@@ -2528,13 +2501,12 @@ int dynamicPaint_createUVSurface(Scene *scene, DynamicPaintSurface *surface)
}
/* Set values */
- tPoint->neighbour_pixel = ind; // face index
- tPoint->quad = tempPoints[ind].quad; // quad or tri
+ tPoint->neighbour_pixel = ind; /* tri index */
/* save vertex indexes */
- tPoint->v1 = mface[i].v1;
- tPoint->v2 = (tPoint->quad) ? mface[i].v3 : mface[i].v2;
- tPoint->v3 = (tPoint->quad) ? mface[i].v4 : mface[i].v3;
+ tPoint->v1 = mloop[mlooptri[i].tri[0]].v;
+ tPoint->v2 = mloop[mlooptri[i].tri[1]].v;
+ tPoint->v3 = mloop[mlooptri[i].tri[2]].v;
u = u_max + 1; /* make sure we exit outer loop as well */
break;
@@ -2553,10 +2525,12 @@ int dynamicPaint_createUVSurface(Scene *scene, DynamicPaintSurface *surface)
int tx;
for (tx = 0; tx < w; tx++) {
int index = tx + w * ty;
- PaintUVPoint *tPoint = (&tempPoints[index]);
+ PaintUVPoint *tPoint = &tempPoints[index];
- if (tPoint->face_index == -1 && tPoint->neighbour_pixel != -1) tPoint->face_index = tempPoints[tPoint->neighbour_pixel].face_index;
- if (tPoint->face_index != -1) active_points++;
+ if (tPoint->tri_index == -1 && tPoint->neighbour_pixel != -1)
+ tPoint->tri_index = tempPoints[tPoint->neighbour_pixel].tri_index;
+ if (tPoint->tri_index != -1)
+ active_points++;
}
}
@@ -2567,7 +2541,7 @@ int dynamicPaint_createUVSurface(Scene *scene, DynamicPaintSurface *surface)
/* Create a temporary array of final indexes (before unassigned
* pixels have been dropped) */
for (i = 0; i < w * h; i++) {
- if (tempPoints[i].face_index != -1) {
+ if (tempPoints[i].tri_index != -1) {
final_index[i] = cursor;
cursor++;
}
@@ -2584,7 +2558,7 @@ int dynamicPaint_createUVSurface(Scene *scene, DynamicPaintSurface *surface)
for (tx = 0; tx < w; tx++) {
int i, index = tx + w * ty;
- if (tempPoints[index].face_index != -1) {
+ if (tempPoints[index].tri_index != -1) {
ed->n_index[final_index[index]] = n_pos;
ed->n_num[final_index[index]] = 0;
@@ -2638,7 +2612,7 @@ int dynamicPaint_createUVSurface(Scene *scene, DynamicPaintSurface *surface)
sData->format_data = f_data;
for (index = 0; index < (w * h); index++) {
- if (tempPoints[index].face_index != -1) {
+ if (tempPoints[index].tri_index != -1) {
memcpy(&f_data->uv_p[cursor], &tempPoints[index], sizeof(PaintUVPoint));
memcpy(&f_data->barycentricWeights[cursor * aa_samples], &tempWeights[index * aa_samples], sizeof(Vec3f) * aa_samples);
cursor++;
@@ -2674,9 +2648,9 @@ int dynamicPaint_createUVSurface(Scene *scene, DynamicPaintSurface *surface)
/* Every pixel that is assigned as "edge pixel" gets blue color */
if (uvPoint->neighbour_pixel != -1) pPoint->color[2] = 1.0f;
/* and every pixel that finally got an polygon gets red color */
- if (uvPoint->face_index != -1) pPoint->color[0] = 1.0f;
+ if (uvPoint->tri_index != -1) pPoint->color[0] = 1.0f;
/* green color shows pixel face index hash */
- if (uvPoint->face_index != -1) pPoint->color[1] = (float)(uvPoint->face_index % 255) / 256.0f;
+ if (uvPoint->tri_index != -1) pPoint->color[1] = (float)(uvPoint->tri_index % 255) / 256.0f;
}
#endif
@@ -2708,7 +2682,7 @@ void dynamicPaint_outputSurfaceImage(DynamicPaintSurface *surface, char *filenam
if (format == R_IMF_IMTYPE_OPENEXR) format = R_IMF_IMTYPE_PNG;
#endif
BLI_strncpy(output_file, filename, sizeof(output_file));
- BKE_add_image_extension_from_type(output_file, format);
+ BKE_image_path_ensure_ext_from_imtype(output_file, format);
/* Validate output file path */
BLI_path_abs(output_file, G.main->name);
@@ -2744,7 +2718,7 @@ void dynamicPaint_outputSurfaceImage(DynamicPaintSurface *surface, char *filenam
PaintPoint *point = &((PaintPoint *)sData->type_data)[index];
/* blend wet and dry layers */
- blendColors(point->color, point->alpha, point->e_color, point->e_alpha, &ibuf->rect_float[pos]);
+ blendColors(point->color, point->color[3], point->e_color, point->e_color[3], &ibuf->rect_float[pos]);
/* Multiply color by alpha if enabled */
if (surface->flags & MOD_DPAINT_MULALPHA) {
@@ -2788,10 +2762,13 @@ void dynamicPaint_outputSurfaceImage(DynamicPaintSurface *surface, char *filenam
}
/* Set output format, png in case exr isn't supported */
- ibuf->ftype = PNG | 95;
+ ibuf->ftype = IMB_FTYPE_PNG;
+ ibuf->foptions.quality = 15;
+
#ifdef WITH_OPENEXR
if (format == R_IMF_IMTYPE_OPENEXR) { /* OpenEXR 32-bit float */
- ibuf->ftype = OPENEXR | OPENEXR_COMPRESS;
+ ibuf->ftype = IMB_FTYPE_OPENEXR;
+ ibuf->foptions.flag |= OPENEXR_COMPRESS;
}
#endif
@@ -2858,17 +2835,20 @@ static void dynamicPaint_freeBrushMaterials(BrushMaterials *bMats)
/*
* Get material diffuse color and alpha (including linked textures) in given coordinates
*/
-static void dynamicPaint_doMaterialTex(BrushMaterials *bMats, float color[3], float *alpha, Object *brushOb,
- const float volume_co[3], const float surface_co[3],
- int faceIndex, short isQuad, DerivedMesh *orcoDm)
+static void dynamicPaint_doMaterialTex(
+ BrushMaterials *bMats, float color[3], float *alpha, Object *brushOb,
+ const float volume_co[3], const float surface_co[3],
+ int triIndex, DerivedMesh *orcoDm)
{
Material *mat = bMats->mat;
- MFace *mface = orcoDm->getTessFaceArray(orcoDm);
+
+ const MLoopTri *mlooptri = orcoDm->getLoopTriArray(orcoDm);
+ const MPoly *mpoly = orcoDm->getPolyArray(orcoDm);
/* If no material defined, use the one assigned to the mesh face */
if (mat == NULL) {
if (bMats->ob_mats) {
- int mat_nr = mface[faceIndex].mat_nr;
+ int mat_nr = mpoly[mlooptri[triIndex].poly].mat_nr;
if (mat_nr >= (*give_totcolp(brushOb))) return;
mat = bMats->ob_mats[mat_nr];
if (mat == NULL) return; /* No material assigned */
@@ -2877,88 +2857,69 @@ static void dynamicPaint_doMaterialTex(BrushMaterials *bMats, float color[3], fl
return;
}
}
-
- RE_sample_material_color(mat, color, alpha, volume_co, surface_co, faceIndex, isQuad, orcoDm, brushOb);
+ RE_sample_material_color(mat, color, alpha, volume_co, surface_co, triIndex, orcoDm, brushOb);
}
/***************************** Ray / Nearest Point Utils ******************************/
-/* A modified callback to bvh tree raycast. The tree must bust have been built using bvhtree_from_mesh_faces.
+/* A modified callback to bvh tree raycast. The tree must bust have been built using bvhtree_from_mesh_looptri.
* userdata must be a BVHMeshCallbackUserdata built from the same mesh as the tree.
*
* To optimize brush detection speed this doesn't calculate hit coordinates or normal.
- * If ray hit the second half of a quad, no[0] is set to 1.0f.
*/
-static void mesh_faces_spherecast_dp(void *userdata, int index, const BVHTreeRay *ray, BVHTreeRayHit *hit)
+static void mesh_tris_spherecast_dp(void *userdata, int index, const BVHTreeRay *ray, BVHTreeRayHit *hit)
{
const BVHTreeFromMesh *data = (BVHTreeFromMesh *) userdata;
- MVert *vert = data->vert;
- MFace *face = data->face + index;
- short quad = 0;
-
- const float *t0, *t1, *t2, *t3;
- t0 = vert[face->v1].co;
- t1 = vert[face->v2].co;
- t2 = vert[face->v3].co;
- t3 = face->v4 ? vert[face->v4].co : NULL;
-
- do {
- float dist = bvhtree_ray_tri_intersection(ray, hit->dist, t0, t1, t2);
-
- if (dist >= 0 && dist < hit->dist) {
- hit->index = index;
- hit->dist = dist;
- hit->no[0] = (quad) ? 1.0f : 0.0f;
- }
+ const MVert *vert = data->vert;
+ const MLoopTri *mlooptri = data->looptri;
+ const MLoop *mloop = data->loop;
+
+ const float *t0, *t1, *t2;
+ float dist;
+
+ t0 = vert[mloop[mlooptri[index].tri[0]].v].co;
+ t1 = vert[mloop[mlooptri[index].tri[1]].v].co;
+ t2 = vert[mloop[mlooptri[index].tri[2]].v].co;
- t1 = t2;
- t2 = t3;
- t3 = NULL;
- quad = 1;
+ dist = bvhtree_ray_tri_intersection(ray, hit->dist, t0, t1, t2);
+
+ if (dist >= 0 && dist < hit->dist) {
+ hit->index = index;
+ hit->dist = dist;
+ hit->no[0] = 0.0f;
+ }
- } while (t2);
}
-/* A modified callback to bvh tree nearest point. The tree must bust have been built using bvhtree_from_mesh_faces.
+/* A modified callback to bvh tree nearest point. The tree must bust have been built using bvhtree_from_mesh_looptri.
* userdata must be a BVHMeshCallbackUserdata built from the same mesh as the tree.
*
* To optimize brush detection speed this doesn't calculate hit normal.
- * If ray hit the second half of a quad, no[0] is set to 1.0f, else 0.0f
*/
-static void mesh_faces_nearest_point_dp(void *userdata, int index, const float co[3], BVHTreeNearest *nearest)
+static void mesh_tris_nearest_point_dp(void *userdata, int index, const float co[3], BVHTreeNearest *nearest)
{
const BVHTreeFromMesh *data = (BVHTreeFromMesh *) userdata;
- MVert *vert = data->vert;
- MFace *face = data->face + index;
- short quad = 0;
-
- const float *t0, *t1, *t2, *t3;
- t0 = vert[face->v1].co;
- t1 = vert[face->v2].co;
- t2 = vert[face->v3].co;
- t3 = face->v4 ? vert[face->v4].co : NULL;
-
- do {
- float nearest_tmp[3], dist_sq;
-
- closest_on_tri_to_point_v3(nearest_tmp, co, t0, t1, t2);
- dist_sq = len_squared_v3v3(co, nearest_tmp);
-
- if (dist_sq < nearest->dist_sq) {
- nearest->index = index;
- nearest->dist_sq = dist_sq;
- copy_v3_v3(nearest->co, nearest_tmp);
- nearest->no[0] = (quad) ? 1.0f : 0.0f;
- }
-
- t1 = t2;
- t2 = t3;
- t3 = NULL;
- quad = 1;
-
- } while (t2);
+ const MVert *vert = data->vert;
+ const MLoopTri *mlooptri = data->looptri;
+ const MLoop *mloop = data->loop;
+ float nearest_tmp[3], dist_sq;
+
+ const float *t0, *t1, *t2;
+ t0 = vert[mloop[mlooptri[index].tri[0]].v].co;
+ t1 = vert[mloop[mlooptri[index].tri[1]].v].co;
+ t2 = vert[mloop[mlooptri[index].tri[2]].v].co;
+
+ closest_on_tri_to_point_v3(nearest_tmp, co, t0, t1, t2);
+ dist_sq = len_squared_v3v3(co, nearest_tmp);
+
+ if (dist_sq < nearest->dist_sq) {
+ nearest->index = index;
+ nearest->dist_sq = dist_sq;
+ copy_v3_v3(nearest->co, nearest_tmp);
+ nearest->no[0] = 0.0f;
+ }
}
@@ -2967,15 +2928,16 @@ static void mesh_faces_nearest_point_dp(void *userdata, int index, const float c
/**
* Mix color values to canvas point.
*
- * \param surface canvas surface
- * \param index surface point index
- * \param paintFlags paint object flags
- * \param paintColor,Alpha,Wetness to be mixed paint values
- * \param timescale value used to adjust time dependent
+ * \param surface: Canvas surface
+ * \param index: Surface point index
+ * \param paintFlags: paint object flags
+ * \param paintColor,paintAlpha,paintWetness: To be mixed paint values
+ * \param timescale: Value used to adjust time dependent
* operations when using substeps
*/
-static void dynamicPaint_mixPaintColors(DynamicPaintSurface *surface, int index, int paintFlags,
- const float paintColor[3], float *paintAlpha, float *paintWetness, float *timescale)
+static void dynamicPaint_mixPaintColors(
+ DynamicPaintSurface *surface, int index, int paintFlags,
+ const float paintColor[3], float *paintAlpha, float *paintWetness, float *timescale)
{
PaintPoint *pPoint = &((PaintPoint *)surface->data->type_data)[index];
@@ -2985,23 +2947,23 @@ static void dynamicPaint_mixPaintColors(DynamicPaintSurface *surface, int index,
float temp_alpha = (*paintAlpha) * ((paintFlags & MOD_DPAINT_ABS_ALPHA) ? 1.0f : (*timescale));
/* mix brush color with wet layer color */
- blendColors(pPoint->e_color, pPoint->e_alpha, paintColor, temp_alpha, mix);
+ blendColors(pPoint->e_color, pPoint->e_color[3], paintColor, temp_alpha, mix);
copy_v3_v3(pPoint->e_color, mix);
/* mix wetness and alpha depending on selected alpha mode */
if (paintFlags & MOD_DPAINT_ABS_ALPHA) {
/* update values to the brush level unless theyre higher already */
- if (pPoint->e_alpha < (*paintAlpha)) pPoint->e_alpha = (*paintAlpha);
- if (pPoint->wetness < (*paintWetness)) pPoint->wetness = (*paintWetness);
+ CLAMP_MIN(pPoint->e_color[3], *paintAlpha);
+ CLAMP_MIN(pPoint->wetness, *paintWetness);
}
else {
float wetness = (*paintWetness);
CLAMP(wetness, 0.0f, 1.0f);
- pPoint->e_alpha = mix[3];
+ pPoint->e_color[3] = mix[3];
pPoint->wetness = pPoint->wetness * (1.0f - wetness) + wetness;
}
- if (pPoint->wetness < MIN_WETNESS) pPoint->wetness = MIN_WETNESS;
+ CLAMP_MIN(pPoint->wetness, MIN_WETNESS);
pPoint->state = DPAINT_PAINT_NEW;
}
@@ -3016,23 +2978,23 @@ static void dynamicPaint_mixPaintColors(DynamicPaintSurface *surface, int index,
* but maintain alpha ratio
*/
if (paintFlags & MOD_DPAINT_ABS_ALPHA) {
- a_highest = (pPoint->e_alpha > pPoint->alpha) ? pPoint->e_alpha : pPoint->alpha;
+ a_highest = max_ff(pPoint->color[3], pPoint->e_color[3]);
if (a_highest > invFact) {
a_ratio = invFact / a_highest;
- pPoint->e_alpha *= a_ratio;
- pPoint->alpha *= a_ratio;
+ pPoint->e_color[3] *= a_ratio;
+ pPoint->color[3] *= a_ratio;
}
}
else {
- pPoint->e_alpha -= (*paintAlpha) * (*timescale);
- if (pPoint->e_alpha < 0.0f) pPoint->e_alpha = 0.0f;
- pPoint->alpha -= (*paintAlpha) * (*timescale);
- if (pPoint->alpha < 0.0f) pPoint->alpha = 0.0f;
+ pPoint->e_color[3] -= (*paintAlpha) * (*timescale);
+ CLAMP_MIN(pPoint->e_color[3], 0.0f);
+ pPoint->color[3] -= (*paintAlpha) * (*timescale);
+ CLAMP_MIN(pPoint->color[3], 0.0f);
}
- wetness = (1.0f - (*paintWetness)) * pPoint->e_alpha;
- if (pPoint->wetness > wetness) pPoint->wetness = wetness;
+ wetness = (1.0f - (*paintWetness)) * pPoint->e_color[3];
+ CLAMP_MAX(pPoint->wetness, wetness);
}
}
@@ -3285,7 +3247,8 @@ static int dynamicPaint_paintMesh(DynamicPaintSurface *surface,
DerivedMesh *dm = NULL;
Vec3f *brushVelocity = NULL;
MVert *mvert = NULL;
- MFace *mface = NULL;
+ const MLoopTri *mlooptri = NULL;
+ const MLoop *mloop = NULL;
if (brush->flags & MOD_DPAINT_USES_VELOCITY)
dynamicPaint_brushMeshCalculateVelocity(scene, brushOb, brush, &brushVelocity, timescale);
@@ -3302,7 +3265,8 @@ static int dynamicPaint_paintMesh(DynamicPaintSurface *surface,
dm = CDDM_copy(brush->dm);
mvert = dm->getVertArray(dm);
- mface = dm->getTessFaceArray(dm);
+ mlooptri = dm->getLoopTriArray(dm);
+ mloop = dm->getLoopArray(dm);
numOfVerts = dm->getNumVerts(dm);
/* Transform collider vertices to global space
@@ -3326,16 +3290,15 @@ static int dynamicPaint_paintMesh(DynamicPaintSurface *surface,
if (brush->flags & MOD_DPAINT_PROX_PROJECT && brush->collision != MOD_DPAINT_COL_VOLUME) {
mul_v3_fl(avg_brushNor, 1.0f / (float)numOfVerts);
/* instead of null vector use positive z */
- if (!(MIN3(avg_brushNor[0], avg_brushNor[1], avg_brushNor[2])))
+ if (UNLIKELY(normalize_v3(avg_brushNor) == 0.0f)) {
avg_brushNor[2] = 1.0f;
- else
- normalize_v3(avg_brushNor);
+ }
}
/* check bounding box collision */
if (grid && meshBrush_boundsIntersect(&grid->grid_bounds, &mesh_bb, brush, brush_radius)) {
/* Build a bvh tree from transformed vertices */
- if (bvhtree_from_mesh_faces(&treeData, dm, 0.0f, 4, 8)) {
+ if (bvhtree_from_mesh_looptri(&treeData, dm, 0.0f, 4, 8)) {
int c_index;
int total_cells = grid->dim[0] * grid->dim[1] * grid->dim[2];
@@ -3384,8 +3347,7 @@ static int dynamicPaint_paintMesh(DynamicPaintSurface *surface,
/* hit data */
float hitCoord[3];
- int hitFace = -1;
- short hitQuad = 0;
+ int hitTri = -1;
/* Supersampling factor */
if (samples > 1 && surface->format == MOD_DPAINT_SURFACE_F_IMAGESEQ)
@@ -3407,16 +3369,19 @@ static int dynamicPaint_paintMesh(DynamicPaintSurface *surface,
/* Check volume collision */
if (brush->collision == MOD_DPAINT_COL_VOLUME || brush->collision == MOD_DPAINT_COL_VOLDIST)
- if (BLI_bvhtree_ray_cast(treeData.tree, ray_start, ray_dir, 0.0f, &hit, mesh_faces_spherecast_dp, &treeData) != -1) {
+ if (BLI_bvhtree_ray_cast(treeData.tree, ray_start, ray_dir, 0.0f, &hit, mesh_tris_spherecast_dp, &treeData) != -1) {
/* We hit a triangle, now check if collision point normal is facing the point */
/* For optimization sake, hit point normal isn't calculated in ray cast loop */
- int v1 = mface[hit.index].v1, v2 = mface[hit.index].v2, v3 = mface[hit.index].v3, quad = (hit.no[0] == 1.0f);
+ const int vtri[3] = {
+ mloop[mlooptri[hit.index].tri[0]].v,
+ mloop[mlooptri[hit.index].tri[1]].v,
+ mloop[mlooptri[hit.index].tri[2]].v,
+ };
float dot;
- if (quad) { v2 = mface[hit.index].v3; v3 = mface[hit.index].v4; }
- normal_tri_v3(hit.no, mvert[v1].co, mvert[v2].co, mvert[v3].co);
- dot = ray_dir[0] * hit.no[0] + ray_dir[1] * hit.no[1] + ray_dir[2] * hit.no[2];
+ normal_tri_v3(hit.no, mvert[vtri[0]].co, mvert[vtri[1]].co, mvert[vtri[2]].co);
+ dot = dot_v3v3(ray_dir, hit.no);
/* If ray and hit face normal are facing same direction
* hit point is inside a closed mesh. */
@@ -3430,7 +3395,7 @@ static int dynamicPaint_paintMesh(DynamicPaintSurface *surface,
hit.index = -1;
hit.dist = 9999;
- BLI_bvhtree_ray_cast(treeData.tree, ray_start, ray_dir, 0.0f, &hit, mesh_faces_spherecast_dp, &treeData);
+ BLI_bvhtree_ray_cast(treeData.tree, ray_start, ray_dir, 0.0f, &hit, mesh_tris_spherecast_dp, &treeData);
if (hit.index != -1) {
/* Add factor on supersample filter */
@@ -3440,8 +3405,7 @@ static int dynamicPaint_paintMesh(DynamicPaintSurface *surface,
/* Mark hit info */
madd_v3_v3v3fl(hitCoord, ray_start, ray_dir, hit.dist); /* Calculate final hit coordinates */
depth += dist * sample_factor;
- hitFace = f_index;
- hitQuad = quad;
+ hitTri = f_index;
}
}
}
@@ -3452,19 +3416,17 @@ static int dynamicPaint_paintMesh(DynamicPaintSurface *surface,
{
float proxDist = -1.0f;
float hitCo[3] = {0.0f, 0.0f, 0.0f};
- short hQuad;
- int face;
+ int tri = 0;
/* if inverse prox and no hit found, skip this sample */
if (inner_proximity && !hit_found) continue;
/* If pure distance proximity, find the nearest point on the mesh */
if (!(brush->flags & MOD_DPAINT_PROX_PROJECT)) {
- if (BLI_bvhtree_find_nearest(treeData.tree, ray_start, &nearest, mesh_faces_nearest_point_dp, &treeData) != -1) {
+ if (BLI_bvhtree_find_nearest(treeData.tree, ray_start, &nearest, mesh_tris_nearest_point_dp, &treeData) != -1) {
proxDist = sqrtf(nearest.dist_sq);
copy_v3_v3(hitCo, nearest.co);
- hQuad = (nearest.no[0] == 1.0f);
- face = nearest.index;
+ tri = nearest.index;
}
}
else { /* else cast a ray in defined projection direction */
@@ -3484,11 +3446,10 @@ static int dynamicPaint_paintMesh(DynamicPaintSurface *surface,
hit.dist = brush_radius;
/* Do a face normal directional raycast, and use that distance */
- if (BLI_bvhtree_ray_cast(treeData.tree, ray_start, proj_ray, 0.0f, &hit, mesh_faces_spherecast_dp, &treeData) != -1) {
+ if (BLI_bvhtree_ray_cast(treeData.tree, ray_start, proj_ray, 0.0f, &hit, mesh_tris_spherecast_dp, &treeData) != -1) {
proxDist = hit.dist;
madd_v3_v3v3fl(hitCo, ray_start, proj_ray, hit.dist); /* Calculate final hit coordinates */
- hQuad = (hit.no[0] == 1.0f);
- face = hit.index;
+ tri = hit.index;
}
}
@@ -3502,10 +3463,9 @@ static int dynamicPaint_paintMesh(DynamicPaintSurface *surface,
hit_found = HIT_PROXIMITY;
/* if no volume hit, use prox point face info */
- if (hitFace == -1) {
+ if (hitTri == -1) {
copy_v3_v3(hitCoord, hitCo);
- hitQuad = hQuad;
- hitFace = face;
+ hitTri = tri;
}
}
}
@@ -3546,16 +3506,10 @@ static int dynamicPaint_paintMesh(DynamicPaintSurface *surface,
float brushPointVelocity[3];
float velocity[3];
- if (!hitQuad) {
- v1 = mface[hitFace].v1;
- v2 = mface[hitFace].v2;
- v3 = mface[hitFace].v3;
- }
- else {
- v1 = mface[hitFace].v2;
- v2 = mface[hitFace].v3;
- v3 = mface[hitFace].v4;
- }
+ v1 = mloop[mlooptri[hitTri].tri[0]].v;
+ v2 = mloop[mlooptri[hitTri].tri[1]].v;
+ v3 = mloop[mlooptri[hitTri].tri[2]].v;
+
/* calculate barycentric weights for hit point */
interp_weights_face_v3(weights, mvert[v1].co, mvert[v2].co, mvert[v3].co, NULL, hitCoord);
@@ -3600,7 +3554,7 @@ static int dynamicPaint_paintMesh(DynamicPaintSurface *surface,
/* Get material+textures color on hit point if required */
if (brush_usesMaterial(brush, scene))
- dynamicPaint_doMaterialTex(bMats, sampleColor, &alpha_factor, brushOb, bData->realCoord[bData->s_pos[index] + ss].v, hitCoord, hitFace, hitQuad, brush->dm);
+ dynamicPaint_doMaterialTex(bMats, sampleColor, &alpha_factor, brushOb, bData->realCoord[bData->s_pos[index] + ss].v, hitCoord, hitTri, brush->dm);
/* Sample proximity colorband if required */
if ((hit_found == HIT_PROXIMITY) && (brush->proximity_falloff == MOD_DPAINT_PRFALL_RAMP)) {
@@ -3960,7 +3914,7 @@ static int dynamicPaint_paintSinglePoint(DynamicPaintSurface *surface, float *po
copy_v3_v3(hit_coord, mvert[0].co);
mul_m4_v3(brushOb->obmat, hit_coord);
- dynamicPaint_doMaterialTex(bMats, paintColor, &alpha_factor, brushOb, bData->realCoord[bData->s_pos[index]].v, hit_coord, 0, 0, brush->dm);
+ dynamicPaint_doMaterialTex(bMats, paintColor, &alpha_factor, brushOb, bData->realCoord[bData->s_pos[index]].v, hit_coord, 0, brush->dm);
}
/* color ramp */
@@ -4189,15 +4143,15 @@ static void dynamicPaint_doSmudge(DynamicPaintSurface *surface, DynamicPaintBrus
if (dir_dot <= 0.0f) continue;
dir_factor = dir_dot * speed_scale;
- if (dir_factor > brush->smudge_strength) dir_factor = brush->smudge_strength;
+ CLAMP_MAX(dir_factor, brush->smudge_strength);
/* mix new color and alpha */
- mixColors(ePoint->color, ePoint->alpha, pPoint->color, pPoint->alpha, dir_factor);
- ePoint->alpha = ePoint->alpha * (1.0f - dir_factor) + pPoint->alpha * dir_factor;
+ mixColors(ePoint->color, ePoint->color[3], pPoint->color, pPoint->color[3], dir_factor);
+ ePoint->color[3] = ePoint->color[3] * (1.0f - dir_factor) + pPoint->color[3] * dir_factor;
/* smudge "wet layer" */
- mixColors(ePoint->e_color, ePoint->e_alpha, pPoint->e_color, pPoint->e_alpha, dir_factor);
- ePoint->e_alpha = ePoint->e_alpha * (1.0f - dir_factor) + pPoint->e_alpha * dir_factor;
+ mixColors(ePoint->e_color, ePoint->e_color[3], pPoint->e_color, pPoint->e_color[3], dir_factor);
+ ePoint->e_color[3] = ePoint->e_color[3] * (1.0f - dir_factor) + pPoint->e_color[3] * dir_factor;
pPoint->wetness *= (1.0f - dir_factor);
}
}
@@ -4336,7 +4290,7 @@ static void dynamicPaint_doEffectStep(DynamicPaintSurface *surface, float *force
float color_mix = (MIN3(ePoint->wetness, pPoint->wetness, 1.0f)) * 0.25f * surface->color_spread_speed;
/* do color mixing */
- if (color_mix) mixColors(pPoint->e_color, pPoint->e_alpha, ePoint->e_color, ePoint->e_alpha, color_mix);
+ if (color_mix) mixColors(pPoint->e_color, pPoint->e_color[3], ePoint->e_color, ePoint->e_color[3], color_mix);
/* Only continue if surrounding point has higher wetness */
if (ePoint->wetness < pPoint->wetness || ePoint->wetness < MIN_WETNESS) continue;
@@ -4346,7 +4300,7 @@ static void dynamicPaint_doEffectStep(DynamicPaintSurface *surface, float *force
/* mix new wetness and color */
pPoint->wetness = (1.0f - w_factor) * pPoint->wetness + w_factor * ePoint->wetness;
- pPoint->e_alpha = mixColors(pPoint->e_color, pPoint->e_alpha, ePoint->e_color, ePoint->e_alpha, w_factor);
+ pPoint->e_color[3] = mixColors(pPoint->e_color, pPoint->e_color[3], ePoint->e_color, ePoint->e_color[3], w_factor);
}
}
}
@@ -4373,28 +4327,28 @@ static void dynamicPaint_doEffectStep(DynamicPaintSurface *surface, float *force
PaintPoint *ePoint = &prevPoint[sData->adj_data->n_target[n_index]];
float a_factor, ea_factor, w_factor;
- totalAlpha += ePoint->e_alpha;
+ totalAlpha += ePoint->e_color[3];
/* Check if neighboring point has lower alpha,
* if so, decrease this point's alpha as well*/
- if (pPoint->alpha <= 0.0f && pPoint->e_alpha <= 0.0f && pPoint->wetness <= 0.0f) continue;
+ if (pPoint->color[3] <= 0.0f && pPoint->e_color[3] <= 0.0f && pPoint->wetness <= 0.0f) continue;
/* decrease factor for dry paint alpha */
- a_factor = (1.0f - ePoint->alpha) / numOfNeighs * (pPoint->alpha - ePoint->alpha) * speed_scale;
- if (a_factor < 0.0f) a_factor = 0.0f;
+ a_factor = (1.0f - ePoint->color[3]) / numOfNeighs * (pPoint->color[3] - ePoint->color[3]) * speed_scale;
+ CLAMP_MIN(a_factor, 0.0f);
/* decrease factor for wet paint alpha */
- ea_factor = (1.0f - ePoint->e_alpha) / 8 * (pPoint->e_alpha - ePoint->e_alpha) * speed_scale;
- if (ea_factor < 0.0f) ea_factor = 0.0f;
+ ea_factor = (1.0f - ePoint->e_color[3]) / 8 * (pPoint->e_color[3] - ePoint->e_color[3]) * speed_scale;
+ CLAMP_MIN(ea_factor, 0.0f);
/* decrease factor for paint wetness */
w_factor = (1.0f - ePoint->wetness) / 8 * (pPoint->wetness - ePoint->wetness) * speed_scale;
- if (w_factor < 0.0f) w_factor = 0.0f;
+ CLAMP_MIN(w_factor, 0.0f);
- pPoint->alpha -= a_factor;
- if (pPoint->alpha < 0.0f) pPoint->alpha = 0.0f;
- pPoint->e_alpha -= ea_factor;
- if (pPoint->e_alpha < 0.0f) pPoint->e_alpha = 0.0f;
+ pPoint->color[3] -= a_factor;
+ CLAMP_MIN(pPoint->color[3], 0.0f);
+ pPoint->e_color[3] -= ea_factor;
+ CLAMP_MIN(pPoint->e_color[3], 0.0f);
pPoint->wetness -= w_factor;
- if (pPoint->wetness < 0.0f) pPoint->wetness = 0.0f;
+ CLAMP_MIN(pPoint->wetness, 0.0f);
}
}
}
@@ -4436,7 +4390,7 @@ static void dynamicPaint_doEffectStep(DynamicPaintSurface *surface, float *force
if (dir_dot <= 0.0f) continue;
dir_factor = dir_dot * MIN2(speed_scale, 1.0f) * w_factor;
- if (dir_factor > 0.5f) dir_factor = 0.5f;
+ CLAMP_MAX(dir_factor, 0.5f);
/* mix new wetness */
ePoint->wetness += dir_factor;
@@ -4445,12 +4399,11 @@ static void dynamicPaint_doEffectStep(DynamicPaintSurface *surface, float *force
/* mix new color */
a_factor = dir_factor / pPoint_prev->wetness;
CLAMP(a_factor, 0.0f, 1.0f);
- mixColors(ePoint->e_color, ePoint->e_alpha, pPoint_prev->e_color, pPoint_prev->e_alpha, a_factor);
+ mixColors(ePoint->e_color, ePoint->e_color[3], pPoint_prev->e_color, pPoint_prev->e_color[3], a_factor);
/* dripping is supposed to preserve alpha level */
- if (pPoint_prev->e_alpha > ePoint->e_alpha) {
- ePoint->e_alpha += a_factor * pPoint_prev->e_alpha;
- if (ePoint->e_alpha > pPoint_prev->e_alpha)
- ePoint->e_alpha = pPoint_prev->e_alpha;
+ if (pPoint_prev->e_color[3] > ePoint->e_color[3]) {
+ ePoint->e_color[3] += a_factor * pPoint_prev->e_color[3];
+ CLAMP_MAX(ePoint->e_color[3], pPoint_prev->e_color[3]);
}
/* decrease paint wetness on current point */
@@ -4609,21 +4562,21 @@ static void dynamicPaint_surfacePreStep(DynamicPaintSurface *surface, float time
* Slowly "shift" paint from wet layer to dry layer as it drys:
*/
/* make sure alpha values are within proper range */
- CLAMP(pPoint->alpha, 0.0f, 1.0f);
- CLAMP(pPoint->e_alpha, 0.0f, 1.0f);
+ CLAMP(pPoint->color[3], 0.0f, 1.0f);
+ CLAMP(pPoint->e_color[3], 0.0f, 1.0f);
/* get current final blended color of these layers */
- blendColors(pPoint->color, pPoint->alpha, pPoint->e_color, pPoint->e_alpha, f_color);
+ blendColors(pPoint->color, pPoint->color[3], pPoint->e_color, pPoint->e_color[3], f_color);
/* reduce wet layer alpha by dry factor */
- pPoint->e_alpha *= dry_ratio;
+ pPoint->e_color[3] *= dry_ratio;
/* now calculate new alpha for dry layer that keeps final blended color unchanged */
- pPoint->alpha = (f_color[3] - pPoint->e_alpha) / (1.0f - pPoint->e_alpha);
+ pPoint->color[3] = (f_color[3] - pPoint->e_color[3]) / (1.0f - pPoint->e_color[3]);
/* for each rgb component, calculate a new dry layer color that keeps the final blend color
* with these new alpha values. (wet layer color doesnt change)*/
- if (pPoint->alpha) {
+ if (pPoint->color[3]) {
for (i = 0; i < 3; i++) {
- pPoint->color[i] = (f_color[i] * f_color[3] - pPoint->e_color[i] * pPoint->e_alpha) / (pPoint->alpha * (1.0f - pPoint->e_alpha));
+ pPoint->color[i] = (f_color[i] * f_color[3] - pPoint->e_color[i] * pPoint->e_color[3]) / (pPoint->color[3] * (1.0f - pPoint->e_color[3]));
}
}
}
@@ -4633,22 +4586,21 @@ static void dynamicPaint_surfacePreStep(DynamicPaintSurface *surface, float time
/* in case of just dryed paint, just mix it to the dry layer and mark it empty */
else if (pPoint->state > 0) {
float f_color[4];
- blendColors(pPoint->color, pPoint->alpha, pPoint->e_color, pPoint->e_alpha, f_color);
- copy_v3_v3(pPoint->color, f_color);
- pPoint->alpha = f_color[3];
+ blendColors(pPoint->color, pPoint->color[3], pPoint->e_color, pPoint->e_color[3], f_color);
+ copy_v4_v4(pPoint->color, f_color);
/* clear wet layer */
pPoint->wetness = 0.0f;
- pPoint->e_alpha = 0.0f;
+ pPoint->e_color[3] = 0.0f;
pPoint->state = DPAINT_PAINT_DRY;
}
}
if (surface->flags & MOD_DPAINT_DISSOLVE) {
- value_dissolve(&pPoint->alpha, surface->diss_speed, timescale, (surface->flags & MOD_DPAINT_DISSOLVE_LOG));
- if (pPoint->alpha < 0.0f) pPoint->alpha = 0.0f;
+ value_dissolve(&pPoint->color[3], surface->diss_speed, timescale, (surface->flags & MOD_DPAINT_DISSOLVE_LOG));
+ CLAMP_MIN(pPoint->color[3], 0.0f);
- value_dissolve(&pPoint->e_alpha, surface->diss_speed, timescale, (surface->flags & MOD_DPAINT_DISSOLVE_LOG));
- if (pPoint->e_alpha < 0.0f) pPoint->e_alpha = 0.0f;
+ value_dissolve(&pPoint->e_color[3], surface->diss_speed, timescale, (surface->flags & MOD_DPAINT_DISSOLVE_LOG));
+ CLAMP_MIN(pPoint->e_color[3], 0.0f);
}
}
/* dissolve for float types */
@@ -4660,7 +4612,7 @@ static void dynamicPaint_surfacePreStep(DynamicPaintSurface *surface, float time
float *point = &((float *)sData->type_data)[index];
/* log or linear */
value_dissolve(point, surface->diss_speed, timescale, (surface->flags & MOD_DPAINT_DISSOLVE_LOG));
- if (*point < 0.0f) *point = 0.0f;
+ CLAMP_MIN(*point, 0.0f);
}
}
}
@@ -4699,7 +4651,7 @@ static int dynamicPaint_surfaceHasMoved(DynamicPaintSurface *surface, Object *ob
return ret;
}
-static int surface_needsVelocityData(DynamicPaintSurface *surface, Scene *scene)
+static int surface_needsVelocityData(DynamicPaintSurface *surface, const Scene *scene)
{
if (surface->effect & MOD_DPAINT_EFFECT_DO_DRIP)
return 1;
@@ -4719,7 +4671,7 @@ static int surface_needsAccelerationData(DynamicPaintSurface *surface)
}
/* Prepare for surface step by creating PaintBakeNormal data */
-static int dynamicPaint_generateBakeData(DynamicPaintSurface *surface, Scene *scene, Object *ob)
+static int dynamicPaint_generateBakeData(DynamicPaintSurface *surface, const Scene *scene, Object *ob)
{
PaintSurfaceData *sData = surface->data;
PaintAdjData *adj_data = sData->adj_data;
diff --git a/source/blender/blenkernel/intern/editderivedmesh.c b/source/blender/blenkernel/intern/editderivedmesh.c
index 40a4bc22ce9..840935c090b 100644
--- a/source/blender/blenkernel/intern/editderivedmesh.c
+++ b/source/blender/blenkernel/intern/editderivedmesh.c
@@ -41,8 +41,6 @@
* is likely to be a little slow.
*/
-#include "GL/glew.h"
-
#include "BLI_math.h"
#include "BLI_jitter.h"
#include "BLI_bitmap.h"
@@ -58,6 +56,7 @@
#include "MEM_guardedalloc.h"
#include "GPU_extensions.h"
+#include "GPU_glew.h"
extern GLubyte stipple_quarttone[128]; /* glutil.c, bad level data */
@@ -170,12 +169,25 @@ static void emDM_calcNormals(DerivedMesh *dm)
dm->dirty &= ~DM_DIRTY_NORMALS;
}
-static void emDM_calcLoopNormals(DerivedMesh *dm, const float split_angle)
+static void emDM_calcLoopNormalsSpaceArray(
+ DerivedMesh *dm, const bool use_split_normals, const float split_angle, MLoopNorSpaceArray *r_lnors_spacearr);
+
+static void emDM_calcLoopNormals(DerivedMesh *dm, const bool use_split_normals, const float split_angle)
+{
+ emDM_calcLoopNormalsSpaceArray(dm, use_split_normals, split_angle, NULL);
+}
+
+/* #define DEBUG_CLNORS */
+
+static void emDM_calcLoopNormalsSpaceArray(
+ DerivedMesh *dm, const bool use_split_normals, const float split_angle, MLoopNorSpaceArray *r_lnors_spacearr)
{
EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
BMesh *bm = bmdm->em->bm;
const float (*vertexCos)[3], (*vertexNos)[3], (*polyNos)[3];
float (*loopNos)[3];
+ short (*clnors_data)[2];
+ int cd_loop_clnors_offset;
/* calculate loop normals from poly and vertex normals */
emDM_ensureVertNormals(bmdm);
@@ -192,7 +204,215 @@ static void emDM_calcLoopNormals(DerivedMesh *dm, const float split_angle)
loopNos = dm->getLoopDataArray(dm, CD_NORMAL);
}
- BM_loops_calc_normal_vcos(bm, vertexCos, vertexNos, polyNos, split_angle, loopNos);
+ /* We can have both, give priority to dm's data, and fallback to bm's ones. */
+ clnors_data = dm->getLoopDataArray(dm, CD_CUSTOMLOOPNORMAL);
+ cd_loop_clnors_offset = clnors_data ? -1 : CustomData_get_offset(&bm->ldata, CD_CUSTOMLOOPNORMAL);
+
+ BM_loops_calc_normal_vcos(bm, vertexCos, vertexNos, polyNos, use_split_normals, split_angle, loopNos,
+ r_lnors_spacearr, clnors_data, cd_loop_clnors_offset);
+#ifdef DEBUG_CLNORS
+ if (r_lnors_spacearr) {
+ int i;
+ for (i = 0; i < numLoops; i++) {
+ if (r_lnors_spacearr->lspacearr[i]->ref_alpha != 0.0f) {
+ LinkNode *loops = r_lnors_spacearr->lspacearr[i]->loops;
+ printf("Loop %d uses lnor space %p:\n", i, r_lnors_spacearr->lspacearr[i]);
+ print_v3("\tfinal lnor:", loopNos[i]);
+ print_v3("\tauto lnor:", r_lnors_spacearr->lspacearr[i]->vec_lnor);
+ print_v3("\tref_vec:", r_lnors_spacearr->lspacearr[i]->vec_ref);
+ printf("\talpha: %f\n\tbeta: %f\n\tloops: %p\n", r_lnors_spacearr->lspacearr[i]->ref_alpha,
+ r_lnors_spacearr->lspacearr[i]->ref_beta, r_lnors_spacearr->lspacearr[i]->loops);
+ printf("\t\t(shared with loops");
+ while (loops) {
+ printf(" %d", GET_INT_FROM_POINTER(loops->link));
+ loops = loops->next;
+ }
+ printf(")\n");
+ }
+ else {
+ printf("Loop %d has no lnor space\n", i);
+ }
+ }
+ }
+#endif
+}
+
+
+typedef struct {
+ const float (*precomputedFaceNormals)[3];
+ const float (*precomputedLoopNormals)[3];
+ BMLoop *(*looptris)[3];
+ int cd_loop_uv_offset; /* texture coordinates */
+ const float (*orco)[3];
+ float (*tangent)[4]; /* destination */
+ int numTessFaces;
+
+} SGLSLEditMeshToTangent;
+
+/* interface */
+#include "mikktspace.h"
+
+static int emdm_ts_GetNumFaces(const SMikkTSpaceContext *pContext)
+{
+ SGLSLEditMeshToTangent *pMesh = pContext->m_pUserData;
+ return pMesh->numTessFaces;
+}
+
+static int emdm_ts_GetNumVertsOfFace(const SMikkTSpaceContext *pContext, const int face_num)
+{
+ //SGLSLEditMeshToTangent *pMesh = pContext->m_pUserData;
+ UNUSED_VARS(pContext, face_num);
+ return 3;
+}
+
+static void emdm_ts_GetPosition(
+ const SMikkTSpaceContext *pContext, float r_co[3],
+ const int face_num, const int vert_index)
+{
+ //assert(vert_index >= 0 && vert_index < 4);
+ SGLSLEditMeshToTangent *pMesh = pContext->m_pUserData;
+ BMLoop **lt = pMesh->looptris[face_num];
+ const float *co = lt[vert_index]->v->co;
+ copy_v3_v3(r_co, co);
+}
+
+static void emdm_ts_GetTextureCoordinate(
+ const SMikkTSpaceContext *pContext, float r_uv[2],
+ const int face_num, const int vert_index)
+{
+ //assert(vert_index >= 0 && vert_index < 4);
+ SGLSLEditMeshToTangent *pMesh = pContext->m_pUserData;
+ BMLoop **lt = pMesh->looptris[face_num];
+
+ if (pMesh->cd_loop_uv_offset != -1) {
+ const float *uv = BM_ELEM_CD_GET_VOID_P(lt[vert_index], pMesh->cd_loop_uv_offset);
+ copy_v2_v2(r_uv, uv);
+ }
+ else {
+ const float *orco = pMesh->orco[BM_elem_index_get(lt[vert_index]->v)];
+ map_to_sphere(&r_uv[0], &r_uv[1], orco[0], orco[1], orco[2]);
+ }
+}
+
+static void emdm_ts_GetNormal(
+ const SMikkTSpaceContext *pContext, float r_no[3],
+ const int face_num, const int vert_index)
+{
+ //assert(vert_index >= 0 && vert_index < 4);
+ SGLSLEditMeshToTangent *pMesh = pContext->m_pUserData;
+ BMLoop **lt = pMesh->looptris[face_num];
+ const bool smoothnormal = BM_elem_flag_test_bool(lt[0]->f, BM_ELEM_SMOOTH);
+
+ if (pMesh->precomputedLoopNormals) {
+ copy_v3_v3(r_no, pMesh->precomputedLoopNormals[BM_elem_index_get(lt[vert_index])]);
+ }
+ else if (!smoothnormal) {
+ if (pMesh->precomputedFaceNormals) {
+ copy_v3_v3(r_no, pMesh->precomputedFaceNormals[BM_elem_index_get(lt[0]->f)]);
+ }
+ else {
+ copy_v3_v3(r_no, lt[0]->f->no);
+ }
+ }
+ else {
+ copy_v3_v3(r_no, lt[vert_index]->v->no);
+ }
+}
+
+static void emdm_ts_SetTSpace(
+ const SMikkTSpaceContext *pContext, const float fvTangent[3], const float fSign,
+ const int face_num, const int vert_index)
+{
+ //assert(vert_index >= 0 && vert_index < 4);
+ SGLSLEditMeshToTangent *pMesh = pContext->m_pUserData;
+ BMLoop **lt = pMesh->looptris[face_num];
+ float *pRes = pMesh->tangent[BM_elem_index_get(lt[vert_index])];
+ copy_v3_v3(pRes, fvTangent);
+ pRes[3] = fSign;
+}
+
+/**
+ * \see #DM_calc_loop_tangents, same logic but used arrays instead of #BMesh data.
+ *
+ * \note This function is not so normal, its using `bm->ldata` as input, but output's to `dm->loopData`.
+ * This is done because #CD_TANGENT is cache data used only for drawing.
+ */
+static void emDM_calcLoopTangents(DerivedMesh *dm)
+{
+ EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
+ BMEditMesh *em = bmdm->em;
+ BMesh *bm = bmdm->em->bm;
+
+ /* mesh vars */
+ int cd_loop_uv_offset;
+ float (*orco)[3] = NULL, (*tangent)[4];
+ int /* totvert, */ totface;
+ const float (*fnors)[3];
+ const float (*tlnors)[3];
+ char htype_index = BM_LOOP;
+
+ if (CustomData_get_layer_index(&dm->loopData, CD_TANGENT) != -1)
+ return;
+
+ fnors = bmdm->polyNos; /* dm->getPolyDataArray(dm, CD_NORMAL) */
+
+ /* Note, we assume we do have tessellated loop normals at this point (in case it is object-enabled),
+ * have to check this is valid...
+ */
+ tlnors = dm->getLoopDataArray(dm, CD_NORMAL);
+
+ /* check we have all the needed layers */
+ totface = em->tottri;
+
+ cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
+
+ /* needed for indexing loop-tangents */
+ htype_index = BM_LOOP;
+ if (cd_loop_uv_offset == -1) {
+ orco = dm->getVertDataArray(dm, CD_ORCO);
+ if (!orco)
+ return;
+ /* needed for orco lookups */
+ htype_index |= BM_VERT;
+ }
+
+ if (fnors) {
+ /* needed for face normal lookups */
+ htype_index |= BM_FACE;
+ }
+
+ BM_mesh_elem_index_ensure(bm, htype_index);
+
+ /* create tangent layer */
+ DM_add_loop_layer(dm, CD_TANGENT, CD_CALLOC, NULL);
+ tangent = DM_get_loop_data_layer(dm, CD_TANGENT);
+
+ /* new computation method */
+ {
+ SGLSLEditMeshToTangent mesh2tangent = {NULL};
+ SMikkTSpaceContext sContext = {NULL};
+ SMikkTSpaceInterface sInterface = {NULL};
+
+ mesh2tangent.precomputedFaceNormals = fnors;
+ mesh2tangent.precomputedLoopNormals = tlnors;
+ mesh2tangent.looptris = em->looptris;
+ mesh2tangent.cd_loop_uv_offset = cd_loop_uv_offset;
+ mesh2tangent.orco = (const float (*)[3])orco;
+ mesh2tangent.tangent = tangent;
+ mesh2tangent.numTessFaces = totface;
+
+ sContext.m_pUserData = &mesh2tangent;
+ sContext.m_pInterface = &sInterface;
+ sInterface.m_getNumFaces = emdm_ts_GetNumFaces;
+ sInterface.m_getNumVerticesOfFace = emdm_ts_GetNumVertsOfFace;
+ sInterface.m_getPosition = emdm_ts_GetPosition;
+ sInterface.m_getTexCoord = emdm_ts_GetTextureCoordinate;
+ sInterface.m_getNormal = emdm_ts_GetNormal;
+ sInterface.m_setTSpaceBasic = emdm_ts_SetTSpace;
+
+ /* 0 if failed */
+ genTangSpaceDefault(&sContext);
+ }
}
static void emDM_recalcTessellation(DerivedMesh *UNUSED(dm))
@@ -200,6 +420,47 @@ static void emDM_recalcTessellation(DerivedMesh *UNUSED(dm))
/* do nothing */
}
+static void emDM_recalcLoopTri(DerivedMesh *UNUSED(dm))
+{
+ /* Nothing to do: emDM tessellation is known,
+ * allocate and fill in with emDM_getLoopTriArray */
+}
+
+static const MLoopTri *emDM_getLoopTriArray(DerivedMesh *dm)
+{
+ if (dm->looptris.array) {
+ BLI_assert(poly_to_tri_count(dm->numPolyData, dm->numLoopData) == dm->looptris.num);
+ }
+ else {
+ EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
+ BMLoop *(*looptris)[3] = bmdm->em->looptris;
+ MLoopTri *mlooptri;
+ const int tottri = bmdm->em->tottri;
+ int i;
+
+ DM_ensure_looptri_data(dm);
+ mlooptri = dm->looptris.array;
+
+ BLI_assert(poly_to_tri_count(dm->numPolyData, dm->numLoopData) == dm->looptris.num);
+ BLI_assert(tottri == dm->looptris.num);
+
+ BM_mesh_elem_index_ensure(bmdm->em->bm, BM_FACE | BM_LOOP);
+
+ for (i = 0; i < tottri; i++) {
+ BMLoop **ltri = looptris[i];
+ MLoopTri *lt = &mlooptri[i];
+
+ ARRAY_SET_ITEMS(
+ lt->tri,
+ BM_elem_index_get(ltri[0]),
+ BM_elem_index_get(ltri[1]),
+ BM_elem_index_get(ltri[2]));
+ lt->poly = BM_elem_index_get(ltri[0]->f);
+ }
+ }
+ return dm->looptris.array;
+}
+
static void emDM_foreachMappedVert(
DerivedMesh *dm,
void (*func)(void *userData, int index, const float co[3], const float no_f[3], const short no_s[3]),
@@ -236,9 +497,10 @@ static void emDM_foreachMappedVert(
}
}
}
-static void emDM_foreachMappedEdge(DerivedMesh *dm,
- void (*func)(void *userData, int index, const float v0co[3], const float v1co[3]),
- void *userData)
+static void emDM_foreachMappedEdge(
+ DerivedMesh *dm,
+ void (*func)(void *userData, int index, const float v0co[3], const float v1co[3]),
+ void *userData)
{
EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
BMesh *bm = bmdm->em->bm;
@@ -263,9 +525,10 @@ static void emDM_foreachMappedEdge(DerivedMesh *dm,
}
}
-static void emDM_drawMappedEdges(DerivedMesh *dm,
- DMSetDrawOptions setDrawOptions,
- void *userData)
+static void emDM_drawMappedEdges(
+ DerivedMesh *dm,
+ DMSetDrawOptions setDrawOptions,
+ void *userData)
{
EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
BMesh *bm = bmdm->em->bm;
@@ -297,17 +560,19 @@ static void emDM_drawMappedEdges(DerivedMesh *dm,
glEnd();
}
}
-static void emDM_drawEdges(DerivedMesh *dm,
- bool UNUSED(drawLooseEdges),
- bool UNUSED(drawAllEdges))
+static void emDM_drawEdges(
+ DerivedMesh *dm,
+ bool UNUSED(drawLooseEdges),
+ bool UNUSED(drawAllEdges))
{
emDM_drawMappedEdges(dm, NULL, NULL);
}
-static void emDM_drawMappedEdgesInterp(DerivedMesh *dm,
- DMSetDrawOptions setDrawOptions,
- DMSetDrawInterpOptions setDrawInterpOptions,
- void *userData)
+static void emDM_drawMappedEdgesInterp(
+ DerivedMesh *dm,
+ DMSetDrawOptions setDrawOptions,
+ DMSetDrawInterpOptions setDrawInterpOptions,
+ void *userData)
{
EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
BMesh *bm = bmdm->em->bm;
@@ -449,12 +714,14 @@ static void emDM_foreachMappedFaceCenter(
}
}
-static void emDM_drawMappedFaces(DerivedMesh *dm,
- DMSetDrawOptions setDrawOptions,
- DMSetMaterial setMaterial,
- DMCompareDrawOptions compareDrawOptions,
- void *userData,
- DMDrawFlag flag)
+static void emDM_drawMappedFaces(
+ DerivedMesh *dm,
+ DMSetDrawOptions setDrawOptions,
+ DMSetMaterial setMaterial,
+ /* currently unused -- each original face is handled separately */
+ DMCompareDrawOptions UNUSED(compareDrawOptions),
+ void *userData,
+ DMDrawFlag flag)
{
EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
BMEditMesh *em = bmdm->em;
@@ -479,11 +746,6 @@ static void emDM_drawMappedFaces(DerivedMesh *dm,
GLenum poly_prev = GL_ZERO;
GLenum shade_prev = GL_ZERO;
- (void)setMaterial; /* UNUSED */
-
- /* currently unused -- each original face is handled separately */
- (void)compareDrawOptions;
-
/* call again below is ok */
if (has_vcol_preview) {
BM_mesh_elem_index_ensure(bm, BM_VERT);
@@ -497,6 +759,8 @@ static void emDM_drawMappedFaces(DerivedMesh *dm,
}
if (bmdm->vertexCos) {
+ short prev_mat_nr = -1;
+
/* add direct access */
const float (*vertexCos)[3] = bmdm->vertexCos;
const float (*vertexNos)[3];
@@ -527,6 +791,14 @@ static void emDM_drawMappedFaces(DerivedMesh *dm,
setDrawOptions(userData, BM_elem_index_get(efa)));
if (draw_option != DM_DRAW_OPTION_SKIP) {
const GLenum poly_type = GL_TRIANGLES; /* BMESH NOTE, this is odd but keep it for now to match trunk */
+
+ if (efa->mat_nr != prev_mat_nr) {
+ if (setMaterial) {
+ setMaterial(efa->mat_nr + 1, NULL);
+ }
+ prev_mat_nr = efa->mat_nr;
+ }
+
if (draw_option == DM_DRAW_OPTION_STIPPLE) { /* enabled with stipple */
if (poly_prev != GL_ZERO) glEnd();
@@ -601,6 +873,8 @@ static void emDM_drawMappedFaces(DerivedMesh *dm,
}
}
else {
+ short prev_mat_nr = -1;
+
BM_mesh_elem_index_ensure(bm, lnors ? BM_FACE | BM_LOOP : BM_FACE);
for (i = 0; i < tottri; i++) {
@@ -609,12 +883,21 @@ static void emDM_drawMappedFaces(DerivedMesh *dm,
efa = ltri[0]->f;
drawSmooth = lnors || ((flag & DM_DRAW_ALWAYS_SMOOTH) ? 1 : BM_elem_flag_test(efa, BM_ELEM_SMOOTH));
+
+ draw_option = (setDrawOptions ?
+ setDrawOptions(userData, BM_elem_index_get(efa)) :
+ DM_DRAW_OPTION_NORMAL);
- draw_option = (!setDrawOptions ?
- DM_DRAW_OPTION_NORMAL :
- setDrawOptions(userData, BM_elem_index_get(efa)));
if (draw_option != DM_DRAW_OPTION_SKIP) {
const GLenum poly_type = GL_TRIANGLES; /* BMESH NOTE, this is odd but keep it for now to match trunk */
+
+ if (efa->mat_nr != prev_mat_nr) {
+ if (setMaterial) {
+ setMaterial(efa->mat_nr + 1, NULL);
+ }
+ prev_mat_nr = efa->mat_nr;
+ }
+
if (draw_option == DM_DRAW_OPTION_STIPPLE) { /* enabled with stipple */
if (poly_prev != GL_ZERO) glEnd();
@@ -716,11 +999,12 @@ static void bmdm_get_tri_colpreview(BMLoop *ls[3], MLoopCol *lcol[3], unsigned c
lcol[2] = (MLoopCol *)color_vert_array[BM_elem_index_get(ls[2]->v)];
}
-static void emDM_drawFacesTex_common(DerivedMesh *dm,
- DMSetDrawOptionsTex drawParams,
- DMSetDrawOptions drawParamsMapped,
- DMCompareDrawOptions compareDrawOptions,
- void *userData)
+static void emDM_drawFacesTex_common(
+ DerivedMesh *dm,
+ DMSetDrawOptionsTex drawParams,
+ DMSetDrawOptionsMappedTex drawParamsMapped,
+ DMCompareDrawOptions compareDrawOptions,
+ void *userData)
{
EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
BMEditMesh *em = bmdm->em;
@@ -772,21 +1056,17 @@ static void emDM_drawFacesTex_common(DerivedMesh *dm,
for (i = 0; i < em->tottri; i++) {
BMLoop **ltri = looptris[i];
MTexPoly *tp = (cd_poly_tex_offset != -1) ? BM_ELEM_CD_GET_VOID_P(ltri[0]->f, cd_poly_tex_offset) : NULL;
- MTFace mtf = {{{0}}};
/*unsigned char *cp = NULL;*/ /*UNUSED*/
int drawSmooth = lnors || BM_elem_flag_test(ltri[0]->f, BM_ELEM_SMOOTH);
DMDrawOption draw_option;
efa = ltri[0]->f;
- if (cd_poly_tex_offset != -1) {
- ME_MTEXFACE_CPY(&mtf, tp);
+ if (drawParams) {
+ draw_option = drawParams(tp, has_vcol, efa->mat_nr);
}
-
- if (drawParams)
- draw_option = drawParams(&mtf, has_vcol, efa->mat_nr);
else if (drawParamsMapped)
- draw_option = drawParamsMapped(userData, BM_elem_index_get(efa));
+ draw_option = drawParamsMapped(userData, BM_elem_index_get(efa), efa->mat_nr);
else
draw_option = DM_DRAW_OPTION_NORMAL;
@@ -841,21 +1121,16 @@ static void emDM_drawFacesTex_common(DerivedMesh *dm,
for (i = 0; i < em->tottri; i++) {
BMLoop **ltri = looptris[i];
MTexPoly *tp = (cd_poly_tex_offset != -1) ? BM_ELEM_CD_GET_VOID_P(ltri[0]->f, cd_poly_tex_offset) : NULL;
- MTFace mtf = {{{0}}};
/*unsigned char *cp = NULL;*/ /*UNUSED*/
int drawSmooth = lnors || BM_elem_flag_test(ltri[0]->f, BM_ELEM_SMOOTH);
DMDrawOption draw_option;
efa = ltri[0]->f;
- if (cd_poly_tex_offset != -1) {
- ME_MTEXFACE_CPY(&mtf, tp);
- }
-
if (drawParams)
- draw_option = drawParams(&mtf, has_vcol, efa->mat_nr);
+ draw_option = drawParams(tp, has_vcol, efa->mat_nr);
else if (drawParamsMapped)
- draw_option = drawParamsMapped(userData, BM_elem_index_get(efa));
+ draw_option = drawParamsMapped(userData, BM_elem_index_get(efa), efa->mat_nr);
else
draw_option = DM_DRAW_OPTION_NORMAL;
@@ -908,18 +1183,20 @@ static void emDM_drawFacesTex_common(DerivedMesh *dm,
glShadeModel(GL_FLAT);
}
-static void emDM_drawFacesTex(DerivedMesh *dm,
- DMSetDrawOptionsTex setDrawOptions,
- DMCompareDrawOptions compareDrawOptions,
- void *userData, DMDrawFlag UNUSED(flag))
+static void emDM_drawFacesTex(
+ DerivedMesh *dm,
+ DMSetDrawOptionsTex setDrawOptions,
+ DMCompareDrawOptions compareDrawOptions,
+ void *userData, DMDrawFlag UNUSED(flag))
{
emDM_drawFacesTex_common(dm, setDrawOptions, NULL, compareDrawOptions, userData);
}
-static void emDM_drawMappedFacesTex(DerivedMesh *dm,
- DMSetDrawOptions setDrawOptions,
- DMCompareDrawOptions compareDrawOptions,
- void *userData, DMDrawFlag UNUSED(flag))
+static void emDM_drawMappedFacesTex(
+ DerivedMesh *dm,
+ DMSetDrawOptionsMappedTex setDrawOptions,
+ DMCompareDrawOptions compareDrawOptions,
+ void *userData, DMDrawFlag UNUSED(flag))
{
emDM_drawFacesTex_common(dm, NULL, setDrawOptions, compareDrawOptions, userData);
}
@@ -936,7 +1213,7 @@ static void emDM_drawMappedFacesTex(DerivedMesh *dm,
* ... because the material may use layer names to select different UV's
* see: [#34378]
*/
-static void emdm_pass_attrib_vertex_glsl(const DMVertexAttribs *attribs, const BMLoop *loop, const int index_in_face)
+static void emdm_pass_attrib_vertex_glsl(const DMVertexAttribs *attribs, const BMLoop *loop)
{
BMVert *eve = loop->v;
int i;
@@ -971,7 +1248,7 @@ static void emdm_pass_attrib_vertex_glsl(const DMVertexAttribs *attribs, const B
GLubyte col[4];
if (attribs->mcol[i].em_offset != -1) {
const MLoopCol *cp = BM_ELEM_CD_GET_VOID_P(loop, attribs->mcol[i].em_offset);
- col[0] = cp->b; col[1] = cp->g; col[2] = cp->r; col[3] = cp->a;
+ copy_v4_v4_char((char *)col, &cp->r);
}
else {
col[0] = 0; col[1] = 0; col[2] = 0; col[3] = 0;
@@ -979,16 +1256,22 @@ static void emdm_pass_attrib_vertex_glsl(const DMVertexAttribs *attribs, const B
glVertexAttrib4ubvARB(attribs->mcol[i].gl_index, col);
}
if (attribs->tottang) {
- int index = i * 4 + index_in_face;
- const float *tang = (attribs->tang.array) ? attribs->tang.array[index] : zero;
+ const float *tang;
+ if (attribs->tang.em_offset != -1) {
+ tang = attribs->tang.array[BM_elem_index_get(loop)];
+ }
+ else {
+ tang = zero;
+ }
glVertexAttrib4fvARB(attribs->tang.gl_index, tang);
}
}
-static void emDM_drawMappedFacesGLSL(DerivedMesh *dm,
- DMSetMaterial setMaterial,
- DMSetDrawOptions setDrawOptions,
- void *userData)
+static void emDM_drawMappedFacesGLSL(
+ DerivedMesh *dm,
+ DMSetMaterial setMaterial,
+ DMSetDrawOptions setDrawOptions,
+ void *userData)
{
EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
BMEditMesh *em = bmdm->em;
@@ -1019,7 +1302,7 @@ static void emDM_drawMappedFacesGLSL(DerivedMesh *dm,
/* always use smooth shading even for flat faces, else vertex colors wont interpolate */
glShadeModel(GL_SMOOTH);
- BM_mesh_elem_index_ensure(bm, lnors ? BM_VERT | BM_FACE | BM_LOOP : BM_VERT | BM_FACE);
+ BM_mesh_elem_index_ensure(bm, (BM_VERT | BM_FACE) | (lnors ? BM_LOOP : 0));
for (i = 0; i < em->tottri; i++) {
BMLoop **ltri = looptris[i];
@@ -1030,14 +1313,19 @@ static void emDM_drawMappedFacesGLSL(DerivedMesh *dm,
if (setDrawOptions && (setDrawOptions(userData, BM_elem_index_get(efa)) == DM_DRAW_OPTION_SKIP))
continue;
+ /* material */
new_matnr = efa->mat_nr + 1;
if (new_matnr != matnr) {
if (matnr != -1)
glEnd();
do_draw = setMaterial(matnr = new_matnr, &gattribs);
- if (do_draw)
+ if (do_draw) {
DM_vertex_attributes_from_gpu(dm, &gattribs, &attribs);
+ if (UNLIKELY(attribs.tottang && bm->elem_index_dirty & BM_LOOP)) {
+ BM_mesh_elem_index_ensure(bm, BM_LOOP);
+ }
+ }
glBegin(GL_TRIANGLES);
}
@@ -1051,14 +1339,14 @@ static void emDM_drawMappedFacesGLSL(DerivedMesh *dm,
if (vertexCos) {
glNormal3fv(polyNos[BM_elem_index_get(efa)]);
for (fi = 0; fi < 3; fi++) {
- emdm_pass_attrib_vertex_glsl(&attribs, ltri[fi], fi);
+ emdm_pass_attrib_vertex_glsl(&attribs, ltri[fi]);
glVertex3fv(vertexCos[BM_elem_index_get(ltri[fi]->v)]);
}
}
else {
glNormal3fv(efa->no);
for (fi = 0; fi < 3; fi++) {
- emdm_pass_attrib_vertex_glsl(&attribs, ltri[fi], fi);
+ emdm_pass_attrib_vertex_glsl(&attribs, ltri[fi]);
glVertex3fv(ltri[fi]->v->co);
}
}
@@ -1067,7 +1355,7 @@ static void emDM_drawMappedFacesGLSL(DerivedMesh *dm,
if (vertexCos) {
for (fi = 0; fi < 3; fi++) {
const int j = BM_elem_index_get(ltri[fi]->v);
- emdm_pass_attrib_vertex_glsl(&attribs, ltri[fi], fi);
+ emdm_pass_attrib_vertex_glsl(&attribs, ltri[fi]);
if (lnors) glNormal3fv(lnors[BM_elem_index_get(ltri[fi])]);
else glNormal3fv(vertexNos[j]);
glVertex3fv(vertexCos[j]);
@@ -1075,7 +1363,7 @@ static void emDM_drawMappedFacesGLSL(DerivedMesh *dm,
}
else {
for (fi = 0; fi < 3; fi++) {
- emdm_pass_attrib_vertex_glsl(&attribs, ltri[fi], fi);
+ emdm_pass_attrib_vertex_glsl(&attribs, ltri[fi]);
if (lnors) glNormal3fv(lnors[BM_elem_index_get(ltri[fi])]);
else glNormal3fv(ltri[fi]->v->no);
glVertex3fv(ltri[fi]->v->co);
@@ -1090,15 +1378,17 @@ static void emDM_drawMappedFacesGLSL(DerivedMesh *dm,
}
}
-static void emDM_drawFacesGLSL(DerivedMesh *dm,
- int (*setMaterial)(int matnr, void *attribs))
+static void emDM_drawFacesGLSL(
+ DerivedMesh *dm,
+ int (*setMaterial)(int matnr, void *attribs))
{
dm->drawMappedFacesGLSL(dm, setMaterial, NULL, NULL);
}
-static void emDM_drawMappedFacesMat(DerivedMesh *dm,
- void (*setMaterial)(void *userData, int matnr, void *attribs),
- bool (*setFace)(void *userData, int index), void *userData)
+static void emDM_drawMappedFacesMat(
+ DerivedMesh *dm,
+ void (*setMaterial)(void *userData, int matnr, void *attribs),
+ bool (*setFace)(void *userData, int index), void *userData)
{
EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
BMEditMesh *em = bmdm->em;
@@ -1123,8 +1413,7 @@ static void emDM_drawMappedFacesMat(DerivedMesh *dm,
/* always use smooth shading even for flat faces, else vertex colors wont interpolate */
glShadeModel(GL_SMOOTH);
-
- BM_mesh_elem_index_ensure(bm, lnors ? BM_VERT | BM_FACE | BM_LOOP : BM_VERT | BM_FACE);
+ BM_mesh_elem_index_ensure(bm, (BM_VERT | BM_FACE) | (lnors ? BM_LOOP : 0));
for (i = 0; i < em->tottri; i++) {
BMLoop **ltri = looptris[i];
@@ -1144,6 +1433,9 @@ static void emDM_drawMappedFacesMat(DerivedMesh *dm,
setMaterial(userData, matnr = new_matnr, &gattribs);
DM_vertex_attributes_from_gpu(dm, &gattribs, &attribs);
+ if (UNLIKELY(attribs.tottang && bm->elem_index_dirty & BM_LOOP)) {
+ BM_mesh_elem_index_ensure(bm, BM_LOOP);
+ }
glBegin(GL_TRIANGLES);
}
@@ -1155,14 +1447,14 @@ static void emDM_drawMappedFacesMat(DerivedMesh *dm,
if (vertexCos) {
glNormal3fv(polyNos[BM_elem_index_get(efa)]);
for (fi = 0; fi < 3; fi++) {
- emdm_pass_attrib_vertex_glsl(&attribs, ltri[fi], fi);
+ emdm_pass_attrib_vertex_glsl(&attribs, ltri[fi]);
glVertex3fv(vertexCos[BM_elem_index_get(ltri[fi]->v)]);
}
}
else {
glNormal3fv(efa->no);
for (fi = 0; fi < 3; fi++) {
- emdm_pass_attrib_vertex_glsl(&attribs, ltri[fi], fi);
+ emdm_pass_attrib_vertex_glsl(&attribs, ltri[fi]);
glVertex3fv(ltri[fi]->v->co);
}
}
@@ -1171,7 +1463,7 @@ static void emDM_drawMappedFacesMat(DerivedMesh *dm,
if (vertexCos) {
for (fi = 0; fi < 3; fi++) {
const int j = BM_elem_index_get(ltri[fi]->v);
- emdm_pass_attrib_vertex_glsl(&attribs, ltri[fi], fi);
+ emdm_pass_attrib_vertex_glsl(&attribs, ltri[fi]);
if (lnors) glNormal3fv(lnors[BM_elem_index_get(ltri[fi])]);
else glNormal3fv(vertexNos[j]);
glVertex3fv(vertexCos[j]);
@@ -1179,7 +1471,7 @@ static void emDM_drawMappedFacesMat(DerivedMesh *dm,
}
else {
for (fi = 0; fi < 3; fi++) {
- emdm_pass_attrib_vertex_glsl(&attribs, ltri[fi], fi);
+ emdm_pass_attrib_vertex_glsl(&attribs, ltri[fi]);
if (lnors) glNormal3fv(lnors[BM_elem_index_get(ltri[fi])]);
else glNormal3fv(ltri[fi]->v->no);
glVertex3fv(ltri[fi]->v->co);
@@ -1556,7 +1848,8 @@ static void *emDM_getTessFaceDataArray(DerivedMesh *dm, int type)
if (type == CD_MTFACE || type == CD_MCOL) {
const int type_from = (type == CD_MTFACE) ? CD_MTEXPOLY : CD_MLOOPCOL;
int index;
- const char *data, *bmdata;
+ const char *bmdata;
+ char *data;
index = CustomData_get_layer_index(&bm->pdata, type_from);
if (index != -1) {
@@ -1581,11 +1874,11 @@ static void *emDM_getTessFaceDataArray(DerivedMesh *dm, int type)
// bmdata = CustomData_bmesh_get(&bm->pdata, efa->head.data, CD_MTEXPOLY);
bmdata = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset);
- ME_MTEXFACE_CPY(((MTFace *)data), ((MTexPoly *)bmdata));
+ ME_MTEXFACE_CPY(((MTFace *)data), ((const MTexPoly *)bmdata));
for (j = 0; j < 3; j++) {
// bmdata = CustomData_bmesh_get(&bm->ldata, looptris[i][j]->head.data, CD_MLOOPUV);
bmdata = BM_ELEM_CD_GET_VOID_P(looptris[i][j], cd_loop_uv_offset);
- copy_v2_v2(((MTFace *)data)->uv[j], ((MLoopUV *)bmdata)->uv);
+ copy_v2_v2(((MTFace *)data)->uv[j], ((const MLoopUV *)bmdata)->uv);
}
}
}
@@ -1595,7 +1888,7 @@ static void *emDM_getTessFaceDataArray(DerivedMesh *dm, int type)
for (j = 0; j < 3; j++) {
// bmdata = CustomData_bmesh_get(&bm->ldata, looptris[i][j]->head.data, CD_MLOOPCOL);
bmdata = BM_ELEM_CD_GET_VOID_P(looptris[i][j], cd_loop_color_offset);
- MESH_MLOOPCOL_TO_MCOL(((MLoopCol *)bmdata), (((MCol *)data) + j));
+ MESH_MLOOPCOL_TO_MCOL(((const MLoopCol *)bmdata), (((MCol *)data) + j));
}
}
}
@@ -1709,9 +2002,10 @@ static CustomData *bmDm_getPolyDataLayout(DerivedMesh *dm)
}
-DerivedMesh *getEditDerivedBMesh(BMEditMesh *em,
- Object *UNUSED(ob),
- float (*vertexCos)[3])
+DerivedMesh *getEditDerivedBMesh(
+ BMEditMesh *em,
+ Object *UNUSED(ob),
+ float (*vertexCos)[3])
{
EditDerivedBMesh *bmdm = MEM_callocN(sizeof(*bmdm), __func__);
BMesh *bm = em->bm;
@@ -1741,6 +2035,8 @@ DerivedMesh *getEditDerivedBMesh(BMEditMesh *em,
bmdm->dm.getNumLoops = emDM_getNumLoops;
bmdm->dm.getNumPolys = emDM_getNumPolys;
+ bmdm->dm.getLoopTriArray = emDM_getLoopTriArray;
+
bmdm->dm.getVert = emDM_getVert;
bmdm->dm.getVertCo = emDM_getVertCo;
bmdm->dm.getVertNo = emDM_getVertNo;
@@ -1757,7 +2053,10 @@ DerivedMesh *getEditDerivedBMesh(BMEditMesh *em,
bmdm->dm.calcNormals = emDM_calcNormals;
bmdm->dm.calcLoopNormals = emDM_calcLoopNormals;
+ bmdm->dm.calcLoopNormalsSpaceArray = emDM_calcLoopNormalsSpaceArray;
+ bmdm->dm.calcLoopTangents = emDM_calcLoopTangents;
bmdm->dm.recalcTessellation = emDM_recalcTessellation;
+ bmdm->dm.recalcLoopTri = emDM_recalcLoopTri;
bmdm->dm.foreachMappedVert = emDM_foreachMappedVert;
bmdm->dm.foreachMappedLoop = emDM_foreachMappedLoop;
@@ -1917,7 +2216,7 @@ static void statvis_calc_thickness(
BLI_assert(min <= max);
- fill_vn_fl(face_dists, em->bm->totface, max);
+ copy_vn_fl(face_dists, em->bm->totface, max);
if (use_jit) {
int j;
@@ -2017,15 +2316,17 @@ static void statvis_calc_intersect(
/* result */
unsigned char (*r_face_colors)[4])
{
- BMIter iter;
BMesh *bm = em->bm;
- BMEdge *e;
- int index;
+ int i;
/* fallback */
// const char col_fallback[4] = {64, 64, 64, 255};
+ float fcol[3];
+ unsigned char col[3];
struct BMBVHTree *bmtree;
+ BVHTreeOverlap *overlap;
+ unsigned int overlap_len;
memset(r_face_colors, 64, sizeof(int) * em->bm->totface);
@@ -2036,46 +2337,30 @@ static void statvis_calc_intersect(
bmtree = BKE_bmbvh_new_from_editmesh(em, 0, vertexCos, false);
- BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
- BMFace *f_hit;
- float cos[2][3];
- float cos_mid[3];
- float ray_no[3];
+ overlap = BKE_bmbvh_overlap(bmtree, bmtree, &overlap_len);
- if (e->l == NULL)
- continue;
+ /* same for all faces */
+ weight_to_rgb(fcol, 1.0f);
+ rgb_float_to_uchar(col, fcol);
- if (vertexCos) {
- copy_v3_v3(cos[0], vertexCos[BM_elem_index_get(e->v1)]);
- copy_v3_v3(cos[1], vertexCos[BM_elem_index_get(e->v2)]);
- }
- else {
- copy_v3_v3(cos[0], e->v1->co);
- copy_v3_v3(cos[1], e->v2->co);
- }
+ if (overlap) {
+ for (i = 0; i < overlap_len; i++) {
+ BMFace *f_hit_pair[2] = {
+ em->looptris[overlap[i].indexA][0]->f,
+ em->looptris[overlap[i].indexB][0]->f,
+ };
+ int j;
- mid_v3_v3v3(cos_mid, cos[0], cos[1]);
- sub_v3_v3v3(ray_no, cos[1], cos[0]);
+ for (j = 0; j < 2; j++) {
+ BMFace *f_hit = f_hit_pair[j];
+ int index;
- f_hit = BKE_bmbvh_find_face_segment(bmtree, cos[0], cos[1],
- NULL, NULL, NULL);
+ index = BM_elem_index_get(f_hit);
- if (f_hit) {
- BMLoop *l_iter, *l_first;
- float fcol[3];
-
- index = BM_elem_index_get(f_hit);
- weight_to_rgb(fcol, 1.0f);
- rgb_float_to_uchar(r_face_colors[index], fcol);
-
- l_iter = l_first = e->l;
- do {
- index = BM_elem_index_get(l_iter->f);
- weight_to_rgb(fcol, 1.0f);
- rgb_float_to_uchar(r_face_colors[index], fcol);
- } while ((l_iter = l_iter->radial_next) != l_first);
+ copy_v3_v3_char((char *)r_face_colors[index], (const char *)col);
+ }
}
-
+ MEM_freeN(overlap);
}
BKE_bmbvh_free(bmtree);
@@ -2172,7 +2457,7 @@ static void statvis_calc_sharp(
(void)vertexCos; /* TODO */
- fill_vn_fl(vert_angles, em->bm->totvert, -M_PI);
+ copy_vn_fl(vert_angles, em->bm->totvert, -M_PI);
/* first assign float values to verts */
BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
@@ -2201,8 +2486,9 @@ static void statvis_calc_sharp(
}
}
-void BKE_editmesh_statvis_calc(BMEditMesh *em, DerivedMesh *dm,
- MeshStatVis *statvis)
+void BKE_editmesh_statvis_calc(
+ BMEditMesh *em, DerivedMesh *dm,
+ const MeshStatVis *statvis)
{
EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
BLI_assert(dm == NULL || dm->type == DM_TYPE_EDITBMESH);
@@ -2278,8 +2564,9 @@ struct CageUserData {
BLI_bitmap *visit_bitmap;
};
-static void cage_mapped_verts_callback(void *userData, int index, const float co[3],
- const float UNUSED(no_f[3]), const short UNUSED(no_s[3]))
+static void cage_mapped_verts_callback(
+ void *userData, int index, const float co[3],
+ const float UNUSED(no_f[3]), const short UNUSED(no_s[3]))
{
struct CageUserData *data = userData;
@@ -2296,7 +2583,7 @@ float (*BKE_editmesh_vertexCos_get(BMEditMesh *em, Scene *scene, int *r_numVerts
struct CageUserData data;
float (*cos_cage)[3];
- cage = editbmesh_get_derived_cage_and_final(scene, em->ob, em, &final, CD_MASK_BAREMESH);
+ cage = editbmesh_get_derived_cage_and_final(scene, em->ob, em, CD_MASK_BAREMESH, &final);
cos_cage = MEM_callocN(sizeof(*cos_cage) * em->bm->totvert, "bmbvh cos_cage");
/* when initializing cage verts, we only want the first cage coordinate for each vertex,
diff --git a/source/blender/blenkernel/intern/editmesh.c b/source/blender/blenkernel/intern/editmesh.c
index 2247b91df1d..87a5c6f149f 100644
--- a/source/blender/blenkernel/intern/editmesh.c
+++ b/source/blender/blenkernel/intern/editmesh.c
@@ -246,3 +246,21 @@ void BKE_editmesh_color_ensure(BMEditMesh *em, const char htype)
break;
}
}
+
+float (*BKE_editmesh_vertexCos_get_orco(BMEditMesh *em, int *r_numVerts))[3]
+{
+ BMIter iter;
+ BMVert *eve;
+ float (*orco)[3];
+ int i;
+
+ orco = MEM_mallocN(em->bm->totvert * sizeof(*orco), __func__);
+
+ BM_ITER_MESH_INDEX (eve, &iter, em->bm, BM_VERTS_OF_MESH, i) {
+ copy_v3_v3(orco[i], eve->co);
+ }
+
+ *r_numVerts = em->bm->totvert;
+
+ return orco;
+}
diff --git a/source/blender/blenkernel/intern/editmesh_bvh.c b/source/blender/blenkernel/intern/editmesh_bvh.c
index 442ab26ffc8..07706a38deb 100644
--- a/source/blender/blenkernel/intern/editmesh_bvh.c
+++ b/source/blender/blenkernel/intern/editmesh_bvh.c
@@ -239,6 +239,32 @@ struct RayCastUserData {
float uv[2];
};
+
+static BMFace *bmbvh_ray_cast_handle_hit(
+ BMBVHTree *bmtree, struct RayCastUserData *bmcb_data, const BVHTreeRayHit *hit,
+ float *r_dist, float r_hitout[3], float r_cagehit[3])
+{
+ if (r_hitout) {
+ if (bmtree->flag & BMBVH_RETURN_ORIG) {
+ BMLoop **ltri = bmtree->looptris[hit->index];
+ interp_v3_v3v3v3_uv(r_hitout, ltri[0]->v->co, ltri[1]->v->co, ltri[2]->v->co, bmcb_data->uv);
+ }
+ else {
+ copy_v3_v3(r_hitout, hit->co);
+ }
+
+ if (r_cagehit) {
+ copy_v3_v3(r_cagehit, hit->co);
+ }
+ }
+
+ if (r_dist) {
+ *r_dist = hit->dist;
+ }
+
+ return bmtree->looptris[hit->index][0]->f;
+}
+
static void bmbvh_ray_cast_cb(void *userdata, int index, const BVHTreeRay *ray, BVHTreeRayHit *hit)
{
struct RayCastUserData *bmcb_data = userdata;
@@ -252,8 +278,13 @@ static void bmbvh_ray_cast_cb(void *userdata, int index, const BVHTreeRay *ray,
isect = (ray->radius > 0.0f ?
isect_ray_tri_epsilon_v3(ray->origin, ray->direction,
tri_cos[0], tri_cos[1], tri_cos[2], &dist, uv, ray->radius) :
+#ifdef USE_KDOPBVH_WATERTIGHT
+ isect_ray_tri_watertight_v3(ray->origin, ray->isect_precalc,
+ tri_cos[0], tri_cos[1], tri_cos[2], &dist, uv));
+#else
isect_ray_tri_v3(ray->origin, ray->direction,
tri_cos[0], tri_cos[1], tri_cos[2], &dist, uv));
+#endif
if (isect && dist < hit->dist) {
hit->dist = dist;
@@ -284,123 +315,63 @@ BMFace *BKE_bmbvh_ray_cast(BMBVHTree *bmtree, const float co[3], const float dir
bmcb_data.cos_cage = (const float (*)[3])bmtree->cos_cage;
BLI_bvhtree_ray_cast(bmtree->tree, co, dir, radius, &hit, bmbvh_ray_cast_cb, &bmcb_data);
- if (hit.index != -1 && hit.dist != dist) {
- if (r_hitout) {
- if (bmtree->flag & BMBVH_RETURN_ORIG) {
- BMLoop **ltri = bmtree->looptris[hit.index];
- interp_v3_v3v3v3_uv(r_hitout, ltri[0]->v->co, ltri[1]->v->co, ltri[2]->v->co, bmcb_data.uv);
- }
- else {
- copy_v3_v3(r_hitout, hit.co);
- }
-
- if (r_cagehit) {
- copy_v3_v3(r_cagehit, hit.co);
- }
- }
-
- if (r_dist) {
- *r_dist = hit.dist;
- }
- return bmtree->looptris[hit.index][0]->f;
+ if (hit.index != -1 && hit.dist != dist) {
+ return bmbvh_ray_cast_handle_hit(bmtree, &bmcb_data, &hit, r_dist, r_hitout, r_cagehit);
}
return NULL;
}
-
/* -------------------------------------------------------------------- */
-/* BKE_bmbvh_find_face_segment */
+/* bmbvh_ray_cast_cb_filter */
-struct SegmentUserData {
- /* from the bmtree */
- const BMLoop *(*looptris)[3];
- const float (*cos_cage)[3];
+/* Same as BKE_bmbvh_ray_cast but takes a callback to filter out faces.
+ */
- /* from the hit */
- float uv[2];
- const float *co_a, *co_b;
+struct RayCastUserData_Filter {
+ struct RayCastUserData bmcb_data;
+
+ BMBVHTree_FaceFilter filter_cb;
+ void *filter_userdata;
};
-static void bmbvh_find_face_segment_cb(void *userdata, int index, const BVHTreeRay *ray, BVHTreeRayHit *hit)
+static void bmbvh_ray_cast_cb_filter(void *userdata, int index, const BVHTreeRay *ray, BVHTreeRayHit *hit)
{
- struct SegmentUserData *bmcb_data = userdata;
+ struct RayCastUserData_Filter *bmcb_data_filter = userdata;
+ struct RayCastUserData *bmcb_data = &bmcb_data_filter->bmcb_data;
const BMLoop **ltri = bmcb_data->looptris[index];
- float dist, uv[2];
- const float *tri_cos[3];
-
- bmbvh_tri_from_face(tri_cos, ltri, bmcb_data->cos_cage);
-
- if (equals_v3v3(bmcb_data->co_a, tri_cos[0]) ||
- equals_v3v3(bmcb_data->co_a, tri_cos[1]) ||
- equals_v3v3(bmcb_data->co_a, tri_cos[2]) ||
-
- equals_v3v3(bmcb_data->co_b, tri_cos[0]) ||
- equals_v3v3(bmcb_data->co_b, tri_cos[1]) ||
- equals_v3v3(bmcb_data->co_b, tri_cos[2]))
- {
- return;
- }
-
- if (isect_ray_tri_v3(ray->origin, ray->direction, tri_cos[0], tri_cos[1], tri_cos[2], &dist, uv) &&
- (dist < hit->dist))
- {
- hit->dist = dist;
- hit->index = index;
-
- copy_v3_v3(hit->no, ltri[0]->f->no);
-
- madd_v3_v3v3fl(hit->co, ray->origin, ray->direction, dist);
-
- copy_v2_v2(bmcb_data->uv, uv);
+ if (bmcb_data_filter->filter_cb(ltri[0]->f, bmcb_data_filter->filter_userdata)) {
+ bmbvh_ray_cast_cb(bmcb_data, index, ray, hit);
}
}
-BMFace *BKE_bmbvh_find_face_segment(BMBVHTree *bmtree, const float co_a[3], const float co_b[3],
- float *r_fac, float r_hitout[3], float r_cagehit[3])
+BMFace *BKE_bmbvh_ray_cast_filter(
+ BMBVHTree *bmtree, const float co[3], const float dir[3], const float radius,
+ float *r_dist, float r_hitout[3], float r_cagehit[3],
+ BMBVHTree_FaceFilter filter_cb, void *filter_userdata)
{
BVHTreeRayHit hit;
- struct SegmentUserData bmcb_data;
- const float dist = len_v3v3(co_a, co_b);
- float dir[3];
+ struct RayCastUserData_Filter bmcb_data_filter;
+ struct RayCastUserData *bmcb_data = &bmcb_data_filter.bmcb_data;
- if (bmtree->cos_cage) BLI_assert(!(bmtree->bm->elem_index_dirty & BM_VERT));
+ const float dist = r_dist ? *r_dist : FLT_MAX;
+
+ bmcb_data_filter.filter_cb = filter_cb;
+ bmcb_data_filter.filter_userdata = filter_userdata;
- sub_v3_v3v3(dir, co_b, co_a);
+ if (bmtree->cos_cage) BLI_assert(!(bmtree->bm->elem_index_dirty & BM_VERT));
hit.dist = dist;
hit.index = -1;
/* ok to leave 'uv' uninitialized */
- bmcb_data.looptris = (const BMLoop *(*)[3])bmtree->looptris;
- bmcb_data.cos_cage = (const float (*)[3])bmtree->cos_cage;
- bmcb_data.co_a = co_a;
- bmcb_data.co_b = co_b;
+ bmcb_data->looptris = (const BMLoop *(*)[3])bmtree->looptris;
+ bmcb_data->cos_cage = (const float (*)[3])bmtree->cos_cage;
- BLI_bvhtree_ray_cast(bmtree->tree, co_a, dir, 0.0f, &hit, bmbvh_find_face_segment_cb, &bmcb_data);
+ BLI_bvhtree_ray_cast(bmtree->tree, co, dir, radius, &hit, bmbvh_ray_cast_cb_filter, &bmcb_data_filter);
if (hit.index != -1 && hit.dist != dist) {
- /* duplicate of BKE_bmbvh_ray_cast() */
- if (r_hitout) {
- if (bmtree->flag & BMBVH_RETURN_ORIG) {
- BMLoop **ltri = bmtree->looptris[hit.index];
- interp_v3_v3v3v3_uv(r_hitout, ltri[0]->v->co, ltri[1]->v->co, ltri[2]->v->co, bmcb_data.uv);
- }
- else {
- copy_v3_v3(r_hitout, hit.co);
- }
-
- if (r_cagehit) {
- copy_v3_v3(r_cagehit, hit.co);
- }
- }
- /* end duplicate */
-
- if (r_fac) {
- *r_fac = hit.dist / dist;
- }
-
- return bmtree->looptris[hit.index][0]->f;
+ return bmbvh_ray_cast_handle_hit(bmtree, bmcb_data, &hit, r_dist, r_hitout, r_cagehit);
}
return NULL;
@@ -467,3 +438,59 @@ BMVert *BKE_bmbvh_find_vert_closest(BMBVHTree *bmtree, const float co[3], const
return NULL;
}
+
+/* -------------------------------------------------------------------- */
+/* BKE_bmbvh_overlap */
+
+struct BMBVHTree_OverlapData {
+ const BMBVHTree *tree_pair[2];
+ float epsilon;
+};
+
+static bool bmbvh_overlap_cb(void *userdata, int index_a, int index_b, int UNUSED(thread))
+{
+ struct BMBVHTree_OverlapData *data = userdata;
+ const BMBVHTree *bmtree_a = data->tree_pair[0];
+ const BMBVHTree *bmtree_b = data->tree_pair[1];
+
+ BMLoop **tri_a = bmtree_a->looptris[index_a];
+ BMLoop **tri_b = bmtree_b->looptris[index_b];
+ const float *tri_a_co[3] = {tri_a[0]->v->co, tri_a[1]->v->co, tri_a[2]->v->co};
+ const float *tri_b_co[3] = {tri_b[0]->v->co, tri_b[1]->v->co, tri_b[2]->v->co};
+ float ix_pair[2][3];
+ int verts_shared = 0;
+
+ if (bmtree_a->looptris == bmtree_b->looptris) {
+ if (UNLIKELY(tri_a[0]->f == tri_b[0]->f)) {
+ return false;
+ }
+
+ verts_shared = (
+ ELEM(tri_a_co[0], UNPACK3(tri_b_co)) +
+ ELEM(tri_a_co[1], UNPACK3(tri_b_co)) +
+ ELEM(tri_a_co[2], UNPACK3(tri_b_co)));
+
+ /* if 2 points are shared, bail out */
+ if (verts_shared >= 2) {
+ return false;
+ }
+ }
+
+ return (isect_tri_tri_epsilon_v3(UNPACK3(tri_a_co), UNPACK3(tri_b_co), ix_pair[0], ix_pair[1], data->epsilon) &&
+ /* if we share a vertex, check the intersection isn't a 'point' */
+ ((verts_shared == 0) || (len_squared_v3v3(ix_pair[0], ix_pair[1]) > data->epsilon)));
+}
+
+/**
+ * Overlap indices reference the looptri's
+ */
+BVHTreeOverlap *BKE_bmbvh_overlap(const BMBVHTree *bmtree_a, const BMBVHTree *bmtree_b, unsigned int *r_overlap_tot)
+{
+ struct BMBVHTree_OverlapData data;
+
+ data.tree_pair[0] = bmtree_a;
+ data.tree_pair[1] = bmtree_b;
+ data.epsilon = max_ff(BLI_bvhtree_getepsilon(bmtree_a->tree), BLI_bvhtree_getepsilon(bmtree_b->tree));
+
+ return BLI_bvhtree_overlap(bmtree_a->tree, bmtree_b->tree, r_overlap_tot, bmbvh_overlap_cb, &data);
+} \ No newline at end of file
diff --git a/source/blender/blenkernel/intern/effect.c b/source/blender/blenkernel/intern/effect.c
index ced9da8d0b1..bf53acc1d95 100644
--- a/source/blender/blenkernel/intern/effect.c
+++ b/source/blender/blenkernel/intern/effect.c
@@ -30,6 +30,7 @@
*/
#include <stddef.h>
+#include <stdarg.h>
#include <math.h>
#include <stdlib.h>
@@ -51,6 +52,7 @@
#include "BLI_noise.h"
#include "BLI_rand.h"
#include "BLI_utildefines.h"
+#include "BLI_ghash.h"
#include "PIL_time.h"
@@ -61,6 +63,7 @@
#include "BKE_DerivedMesh.h"
#include "BKE_cdderivedmesh.h"
#include "BKE_effect.h"
+#include "BKE_global.h"
#include "BKE_modifier.h"
#include "BKE_object.h"
#include "BKE_particle.h"
@@ -228,7 +231,7 @@ ListBase *pdInitEffectors(Scene *scene, Object *ob_src, ParticleSystem *psys_src
for (base = scene->base.first; base; base= base->next) {
if ( (base->lay & layer) ) {
if ( base->object->pd && base->object->pd->forcefield )
- add_object_to_effectors(&effectors, scene, weights, base->object, ob_src);
+ add_object_to_effectors(&effectors, scene, weights, base->object, ob_src);
if ( base->object->particlesystem.first ) {
ParticleSystem *psys= base->object->particlesystem.first;
@@ -388,6 +391,7 @@ static void eff_tri_ray_hit(void *UNUSED(userData), int UNUSED(index), const BVH
// get visibility of a wind ray
static float eff_calc_visibility(ListBase *colliders, EffectorCache *eff, EffectorData *efd, EffectedPoint *point)
{
+ const int raycast_flag = BVH_RAYCAST_DEFAULT & ~(BVH_RAYCAST_WATERTIGHT);
ListBase *colls = colliders;
ColliderCache *col;
float norm[3], len = 0.0;
@@ -419,7 +423,10 @@ static float eff_calc_visibility(ListBase *colliders, EffectorCache *eff, Effect
hit.dist = len + FLT_EPSILON;
/* check if the way is blocked */
- if (BLI_bvhtree_ray_cast(collmd->bvhtree, point->loc, norm, 0.0f, &hit, eff_tri_ray_hit, NULL)>=0) {
+ if (BLI_bvhtree_ray_cast_ex(
+ collmd->bvhtree, point->loc, norm, 0.0f, &hit,
+ eff_tri_ray_hit, NULL, raycast_flag) != -1)
+ {
absorption= col->ob->pd->absorption;
/* visibility is only between 0 and 1, calculated from 1-absorption */
@@ -503,7 +510,7 @@ float effector_falloff(EffectorCache *eff, EffectorData *efd, EffectedPoint *UNU
if (falloff == 0.0f)
break;
- madd_v3_v3v3fl(temp, efd->vec_to_point, efd->nor, -fac);
+ madd_v3_v3v3fl(temp, efd->vec_to_point2, efd->nor, -fac);
r_fac= len_v3(temp);
falloff*= falloff_func_rad(eff->pd, r_fac);
break;
@@ -539,15 +546,14 @@ int closest_point_on_surface(SurfaceModifierData *surmd, const float co[3], floa
}
if (surface_vel) {
- MFace *mface = CDDM_get_tessface(surmd->dm, nearest.index);
+ const MLoop *mloop = surmd->bvhtree->loop;
+ const MLoopTri *lt = &surmd->bvhtree->looptri[nearest.index];
- copy_v3_v3(surface_vel, surmd->v[mface->v1].co);
- add_v3_v3(surface_vel, surmd->v[mface->v2].co);
- add_v3_v3(surface_vel, surmd->v[mface->v3].co);
- if (mface->v4)
- add_v3_v3(surface_vel, surmd->v[mface->v4].co);
+ copy_v3_v3(surface_vel, surmd->v[mloop[lt->tri[0]].v].co);
+ add_v3_v3(surface_vel, surmd->v[mloop[lt->tri[1]].v].co);
+ add_v3_v3(surface_vel, surmd->v[mloop[lt->tri[2]].v].co);
- mul_v3_fl(surface_vel, mface->v4 ? 0.25f : (1.0f / 3.0f));
+ mul_v3_fl(surface_vel, (1.0f / 3.0f));
}
return 1;
}
@@ -754,7 +760,7 @@ static void do_texture_effector(EffectorCache *eff, EffectorData *efd, EffectedP
scene_color_manage = BKE_scene_check_color_management_enabled(eff->scene);
- hasrgb = multitex_ext(eff->pd->tex, tex_co, NULL, NULL, 0, result, NULL, scene_color_manage);
+ hasrgb = multitex_ext(eff->pd->tex, tex_co, NULL, NULL, 0, result, NULL, scene_color_manage, false);
if (hasrgb && mode==PFIELD_TEX_RGB) {
force[0] = (0.5f - result->tr) * strength;
@@ -765,15 +771,15 @@ static void do_texture_effector(EffectorCache *eff, EffectorData *efd, EffectedP
strength/=nabla;
tex_co[0] += nabla;
- multitex_ext(eff->pd->tex, tex_co, NULL, NULL, 0, result+1, NULL, scene_color_manage);
+ multitex_ext(eff->pd->tex, tex_co, NULL, NULL, 0, result+1, NULL, scene_color_manage, false);
tex_co[0] -= nabla;
tex_co[1] += nabla;
- multitex_ext(eff->pd->tex, tex_co, NULL, NULL, 0, result+2, NULL, scene_color_manage);
+ multitex_ext(eff->pd->tex, tex_co, NULL, NULL, 0, result+2, NULL, scene_color_manage, false);
tex_co[1] -= nabla;
tex_co[2] += nabla;
- multitex_ext(eff->pd->tex, tex_co, NULL, NULL, 0, result+3, NULL, scene_color_manage);
+ multitex_ext(eff->pd->tex, tex_co, NULL, NULL, 0, result+3, NULL, scene_color_manage, false);
if (mode == PFIELD_TEX_GRAD || !hasrgb) { /* if we don't have rgb fall back to grad */
/* generate intensity if texture only has rgb value */
@@ -1024,3 +1030,160 @@ void pdDoEffectors(ListBase *effectors, ListBase *colliders, EffectorWeights *we
}
}
}
+
+/* ======== Simulation Debugging ======== */
+
+SimDebugData *_sim_debug_data = NULL;
+
+unsigned int BKE_sim_debug_data_hash(int i)
+{
+ return BLI_ghashutil_uinthash((unsigned int)i);
+}
+
+unsigned int BKE_sim_debug_data_hash_combine(unsigned int kx, unsigned int ky)
+{
+#define rot(x,k) (((x)<<(k)) | ((x)>>(32-(k))))
+
+ unsigned int a, b, c;
+
+ a = b = c = 0xdeadbeef + (2 << 2) + 13;
+ a += kx;
+ b += ky;
+
+ c ^= b; c -= rot(b,14);
+ a ^= c; a -= rot(c,11);
+ b ^= a; b -= rot(a,25);
+ c ^= b; c -= rot(b,16);
+ a ^= c; a -= rot(c,4);
+ b ^= a; b -= rot(a,14);
+ c ^= b; c -= rot(b,24);
+
+ return c;
+
+#undef rot
+}
+
+static unsigned int debug_element_hash(const void *key)
+{
+ const SimDebugElement *elem = key;
+ return elem->hash;
+}
+
+static bool debug_element_compare(const void *a, const void *b)
+{
+ const SimDebugElement *elem1 = a;
+ const SimDebugElement *elem2 = b;
+
+ if (elem1->hash == elem2->hash) {
+ return 0;
+ }
+ return 1;
+}
+
+static void debug_element_free(void *val)
+{
+ SimDebugElement *elem = val;
+ MEM_freeN(elem);
+}
+
+void BKE_sim_debug_data_set_enabled(bool enable)
+{
+ if (enable) {
+ if (!_sim_debug_data) {
+ _sim_debug_data = MEM_callocN(sizeof(SimDebugData), "sim debug data");
+ _sim_debug_data->gh = BLI_ghash_new(debug_element_hash, debug_element_compare, "sim debug element hash");
+ }
+ }
+ else {
+ BKE_sim_debug_data_free();
+ }
+}
+
+bool BKE_sim_debug_data_get_enabled(void)
+{
+ return _sim_debug_data != NULL;
+}
+
+void BKE_sim_debug_data_free(void)
+{
+ if (_sim_debug_data) {
+ if (_sim_debug_data->gh)
+ BLI_ghash_free(_sim_debug_data->gh, NULL, debug_element_free);
+ MEM_freeN(_sim_debug_data);
+ }
+}
+
+static void debug_data_insert(SimDebugData *debug_data, SimDebugElement *elem)
+{
+ SimDebugElement *old_elem = BLI_ghash_lookup(debug_data->gh, elem);
+ if (old_elem) {
+ *old_elem = *elem;
+ MEM_freeN(elem);
+ }
+ else
+ BLI_ghash_insert(debug_data->gh, elem, elem);
+}
+
+void BKE_sim_debug_data_add_element(int type, const float v1[3], const float v2[3], float r, float g, float b, const char *category, unsigned int hash)
+{
+ unsigned int category_hash = BLI_ghashutil_strhash_p(category);
+ SimDebugElement *elem;
+
+ if (!_sim_debug_data) {
+ if (G.debug & G_DEBUG_SIMDATA)
+ BKE_sim_debug_data_set_enabled(true);
+ else
+ return;
+ }
+
+ elem = MEM_callocN(sizeof(SimDebugElement), "sim debug data element");
+ elem->type = type;
+ elem->category_hash = category_hash;
+ elem->hash = hash;
+ elem->color[0] = r;
+ elem->color[1] = g;
+ elem->color[2] = b;
+ copy_v3_v3(elem->v1, v1);
+ copy_v3_v3(elem->v2, v2);
+
+ debug_data_insert(_sim_debug_data, elem);
+}
+
+void BKE_sim_debug_data_remove_element(unsigned int hash)
+{
+ SimDebugElement dummy;
+ if (!_sim_debug_data)
+ return;
+
+ dummy.hash = hash;
+ BLI_ghash_remove(_sim_debug_data->gh, &dummy, NULL, debug_element_free);
+}
+
+void BKE_sim_debug_data_clear(void)
+{
+ if (!_sim_debug_data)
+ return;
+
+ if (_sim_debug_data->gh)
+ BLI_ghash_clear(_sim_debug_data->gh, NULL, debug_element_free);
+}
+
+void BKE_sim_debug_data_clear_category(const char *category)
+{
+ int category_hash = (int)BLI_ghashutil_strhash_p(category);
+
+ if (!_sim_debug_data)
+ return;
+
+ if (_sim_debug_data->gh) {
+ GHashIterator iter;
+ BLI_ghashIterator_init(&iter, _sim_debug_data->gh);
+ while (!BLI_ghashIterator_done(&iter)) {
+ const SimDebugElement *elem = BLI_ghashIterator_getValue(&iter);
+ BLI_ghashIterator_step(&iter); /* removing invalidates the current iterator, so step before removing */
+
+ if (elem->category_hash == category_hash)
+ BLI_ghash_remove(_sim_debug_data->gh, elem, NULL, debug_element_free);
+ }
+ }
+}
diff --git a/source/blender/blenkernel/intern/fcurve.c b/source/blender/blenkernel/intern/fcurve.c
index 09c1dcf701d..d747fb0cea2 100644
--- a/source/blender/blenkernel/intern/fcurve.c
+++ b/source/blender/blenkernel/intern/fcurve.c
@@ -46,15 +46,17 @@
#include "BLI_blenlib.h"
#include "BLI_math.h"
#include "BLI_easing.h"
+#include "BLI_threads.h"
#include "BLI_utildefines.h"
-#include "BLF_translation.h"
+#include "BLT_translation.h"
#include "BKE_fcurve.h"
#include "BKE_animsys.h"
#include "BKE_action.h"
#include "BKE_armature.h"
#include "BKE_constraint.h"
+#include "BKE_context.h"
#include "BKE_curve.h"
#include "BKE_global.h"
#include "BKE_object.h"
@@ -68,6 +70,10 @@
#define SMALL -1.0e-10
#define SELECT 1
+#ifdef WITH_PYTHON
+static ThreadMutex python_driver_lock = BLI_MUTEX_INITIALIZER;
+#endif
+
/* ************************** Data-Level Functions ************************* */
/* ---------------------- Freeing --------------------------- */
@@ -229,7 +235,7 @@ FCurve *list_find_fcurve(ListBase *list, const char rna_path[], const int array_
/* check paths of curves, then array indices... */
for (fcu = list->first; fcu; fcu = fcu->next) {
/* simple string-compare (this assumes that they have the same root...) */
- if (fcu->rna_path && !strcmp(fcu->rna_path, rna_path)) {
+ if (fcu->rna_path && STREQ(fcu->rna_path, rna_path)) {
/* now check indices */
if (fcu->array_index == array_index)
return fcu;
@@ -252,7 +258,7 @@ FCurve *iter_step_fcurve(FCurve *fcu_iter, const char rna_path[])
/* check paths of curves, then array indices... */
for (fcu = fcu_iter; fcu; fcu = fcu->next) {
/* simple string-compare (this assumes that they have the same root...) */
- if (fcu->rna_path && !strcmp(fcu->rna_path, rna_path)) {
+ if (fcu->rna_path && STREQ(fcu->rna_path, rna_path)) {
return fcu;
}
}
@@ -289,7 +295,7 @@ int list_find_data_fcurves(ListBase *dst, ListBase *src, const char *dataPrefix,
if (quotedName) {
/* check if the quoted name matches the required name */
- if (strcmp(quotedName, dataName) == 0) {
+ if (STREQ(quotedName, dataName)) {
LinkData *ld = MEM_callocN(sizeof(LinkData), __func__);
ld->data = fcu;
@@ -308,42 +314,98 @@ int list_find_data_fcurves(ListBase *dst, ListBase *src, const char *dataPrefix,
return matches;
}
-FCurve *rna_get_fcurve(PointerRNA *ptr, PropertyRNA *prop, int rnaindex, bAction **action, bool *r_driven)
+FCurve *rna_get_fcurve(PointerRNA *ptr, PropertyRNA *prop, int rnaindex, AnimData **adt,
+ bAction **action, bool *r_driven, bool *r_special)
+{
+ return rna_get_fcurve_context_ui(NULL, ptr, prop, rnaindex, adt, action, r_driven, r_special);
+}
+
+FCurve *rna_get_fcurve_context_ui(bContext *C, PointerRNA *ptr, PropertyRNA *prop, int rnaindex, AnimData **animdata,
+ bAction **action, bool *r_driven, bool *r_special)
{
FCurve *fcu = NULL;
+ PointerRNA tptr = *ptr;
+ if (animdata) *animdata = NULL;
*r_driven = false;
+ *r_special = false;
+
+ if (action) *action = NULL;
+
+ /* Special case for NLA Control Curves... */
+ if (ptr->type == &RNA_NlaStrip) {
+ NlaStrip *strip = (NlaStrip *)ptr->data;
+
+ /* Set the special flag, since it cannot be a normal action/driver
+ * if we've been told to start looking here...
+ */
+ *r_special = true;
+
+ /* The F-Curve either exists or it doesn't here... */
+ fcu = list_find_fcurve(&strip->fcurves, RNA_property_identifier(prop), rnaindex);
+ return fcu;
+ }
/* there must be some RNA-pointer + property combon */
- if (prop && ptr->id.data && RNA_property_animateable(ptr, prop)) {
- AnimData *adt = BKE_animdata_from_id(ptr->id.data);
- char *path;
+ if (prop && tptr.id.data && RNA_property_animateable(&tptr, prop)) {
+ AnimData *adt = BKE_animdata_from_id(tptr.id.data);
+ int step = C ? 2 : 1; /* Always 1 in case we have no context (can't check in 'ancestors' of given RNA ptr). */
+ char *path = NULL;
+
+ if (!adt && C) {
+ path = BKE_animdata_driver_path_hack(C, &tptr, prop, NULL);
+ adt = BKE_animdata_from_id(tptr.id.data);
+ step--;
+ }
- if (adt) {
+ /* Standard F-Curve - Animation (Action) or Drivers */
+ while (adt && step--) {
if ((adt->action && adt->action->curves.first) || (adt->drivers.first)) {
/* XXX this function call can become a performance bottleneck */
- path = RNA_path_from_ID_to_property(ptr, prop);
+ if (step) {
+ path = RNA_path_from_ID_to_property(&tptr, prop);
+ }
+ // XXX: the logic here is duplicated with a function up above
if (path) {
/* animation takes priority over drivers */
- if (adt->action && adt->action->curves.first)
+ if (adt->action && adt->action->curves.first) {
fcu = list_find_fcurve(&adt->action->curves, path, rnaindex);
+
+ if (fcu && action)
+ *action = adt->action;
+ }
/* if not animated, check if driven */
if (!fcu && (adt->drivers.first)) {
fcu = list_find_fcurve(&adt->drivers, path, rnaindex);
- if (fcu)
+ if (fcu) {
+ if (animdata) *animdata = adt;
*r_driven = true;
+ }
}
- if (fcu && action)
+ if (fcu && action) {
+ if (animdata) *animdata = adt;
*action = adt->action;
-
- MEM_freeN(path);
+ break;
+ }
+ else if (step) {
+ char *tpath = BKE_animdata_driver_path_hack(C, &tptr, prop, path);
+ if (tpath && tpath != path) {
+ MEM_freeN(path);
+ path = tpath;
+ adt = BKE_animdata_from_id(tptr.id.data);
+ }
+ else {
+ adt = NULL;
+ }
+ }
}
}
}
+ MEM_SAFE_FREE(path);
}
return fcu;
@@ -461,7 +523,7 @@ static short get_fcurve_end_keyframes(FCurve *fcu, BezTriple **first, BezTriple
/* find first selected */
bezt = fcu->bezt;
for (i = 0; i < fcu->totvert; bezt++, i++) {
- if (BEZSELECTED(bezt)) {
+ if (BEZT_ISSEL_ANY(bezt)) {
*first = bezt;
found = true;
break;
@@ -471,7 +533,7 @@ static short get_fcurve_end_keyframes(FCurve *fcu, BezTriple **first, BezTriple
/* find last selected */
bezt = ARRAY_LAST_ITEM(fcu->bezt, BezTriple, fcu->totvert);
for (i = 0; i < fcu->totvert; bezt--, i++) {
- if (BEZSELECTED(bezt)) {
+ if (BEZT_ISSEL_ANY(bezt)) {
*last = bezt;
found = true;
break;
@@ -525,7 +587,7 @@ bool calc_fcurve_bounds(FCurve *fcu, float *xmin, float *xmax, float *ymin, floa
BezTriple *bezt, *prevbezt = NULL;
for (bezt = fcu->bezt, i = 0; i < fcu->totvert; prevbezt = bezt, bezt++, i++) {
- if ((do_sel_only == false) || BEZSELECTED(bezt)) {
+ if ((do_sel_only == false) || BEZT_ISSEL_ANY(bezt)) {
/* keyframe itself */
yminv = min_ff(yminv, bezt->vec[1][1]);
ymaxv = max_ff(ymaxv, bezt->vec[1][1]);
@@ -654,11 +716,11 @@ bool fcurve_are_keyframes_usable(FCurve *fcu)
{
/* F-Curve must exist */
if (fcu == NULL)
- return 0;
+ return false;
/* F-Curve must not have samples - samples are mutually exclusive of keyframes */
if (fcu->fpt)
- return 0;
+ return false;
/* if it has modifiers, none of these should "drastically" alter the curve */
if (fcu->modifiers.first) {
@@ -685,7 +747,7 @@ bool fcurve_are_keyframes_usable(FCurve *fcu)
FMod_Generator *data = (FMod_Generator *)fcm->data;
if ((data->flag & FCM_GENERATOR_ADDITIVE) == 0)
- return 0;
+ return false;
break;
}
case FMODIFIER_TYPE_FN_GENERATOR:
@@ -693,18 +755,18 @@ bool fcurve_are_keyframes_usable(FCurve *fcu)
FMod_FunctionGenerator *data = (FMod_FunctionGenerator *)fcm->data;
if ((data->flag & FCM_GENERATOR_ADDITIVE) == 0)
- return 0;
+ return false;
break;
}
/* always harmful - cannot allow */
default:
- return 0;
+ return false;
}
}
}
/* keyframes are usable */
- return 1;
+ return true;
}
bool BKE_fcurve_is_protected(FCurve *fcu)
@@ -787,7 +849,7 @@ void fcurve_store_samples(FCurve *fcu, void *data, int start, int end, FcuSample
printf("Error: No F-Curve with F-Curve Modifiers to Bake\n");
return;
}
- if (start >= end) {
+ if (start > end) {
printf("Error: Frame range for Sampled F-Curve creation is inappropriate\n");
return;
}
@@ -913,15 +975,12 @@ void sort_time_fcurve(FCurve *fcu)
/* if either one of both of the points exceeds crosses over the keyframe time... */
if ( (bezt->vec[0][0] > bezt->vec[1][0]) && (bezt->vec[2][0] < bezt->vec[1][0]) ) {
/* swap handles if they have switched sides for some reason */
- SWAP(float, bezt->vec[0][0], bezt->vec[2][0]);
- SWAP(float, bezt->vec[0][1], bezt->vec[2][1]);
+ swap_v2_v2(bezt->vec[0], bezt->vec[2]);
}
else {
/* clamp handles */
- if (bezt->vec[0][0] > bezt->vec[1][0])
- bezt->vec[0][0] = bezt->vec[1][0];
- if (bezt->vec[2][0] < bezt->vec[1][0])
- bezt->vec[2][0] = bezt->vec[1][0];
+ CLAMP_MAX(bezt->vec[0][0], bezt->vec[1][0]);
+ CLAMP_MIN(bezt->vec[2][0], bezt->vec[1][0]);
}
}
}
@@ -1250,7 +1309,7 @@ static float dvar_eval_locDiff(ChannelDriver *driver, DriverVar *dvar)
/* extract transform just like how the constraints do it! */
copy_m4_m4(mat, pchan->pose_mat);
- BKE_constraint_mat_convertspace(ob, pchan, mat, CONSTRAINT_SPACE_POSE, CONSTRAINT_SPACE_LOCAL);
+ BKE_constraint_mat_convertspace(ob, pchan, mat, CONSTRAINT_SPACE_POSE, CONSTRAINT_SPACE_LOCAL, false);
/* ... and from that, we get our transform */
copy_v3_v3(tmp_loc, mat[3]);
@@ -1275,7 +1334,7 @@ static float dvar_eval_locDiff(ChannelDriver *driver, DriverVar *dvar)
/* extract transform just like how the constraints do it! */
copy_m4_m4(mat, ob->obmat);
- BKE_constraint_mat_convertspace(ob, NULL, mat, CONSTRAINT_SPACE_WORLD, CONSTRAINT_SPACE_LOCAL);
+ BKE_constraint_mat_convertspace(ob, NULL, mat, CONSTRAINT_SPACE_WORLD, CONSTRAINT_SPACE_LOCAL, false);
/* ... and from that, we get our transform */
copy_v3_v3(tmp_loc, mat[3]);
@@ -1352,7 +1411,7 @@ static float dvar_eval_transChan(ChannelDriver *driver, DriverVar *dvar)
if (dtar->flag & DTAR_FLAG_LOCAL_CONSTS) {
/* just like how the constraints do it! */
copy_m4_m4(mat, pchan->pose_mat);
- BKE_constraint_mat_convertspace(ob, pchan, mat, CONSTRAINT_SPACE_POSE, CONSTRAINT_SPACE_LOCAL);
+ BKE_constraint_mat_convertspace(ob, pchan, mat, CONSTRAINT_SPACE_POSE, CONSTRAINT_SPACE_LOCAL, false);
}
else {
/* specially calculate local matrix, since chan_mat is not valid
@@ -1379,7 +1438,7 @@ static float dvar_eval_transChan(ChannelDriver *driver, DriverVar *dvar)
if (dtar->flag & DTAR_FLAG_LOCAL_CONSTS) {
/* just like how the constraints do it! */
copy_m4_m4(mat, ob->obmat);
- BKE_constraint_mat_convertspace(ob, NULL, mat, CONSTRAINT_SPACE_WORLD, CONSTRAINT_SPACE_LOCAL);
+ BKE_constraint_mat_convertspace(ob, NULL, mat, CONSTRAINT_SPACE_WORLD, CONSTRAINT_SPACE_LOCAL, false);
}
else {
/* transforms to matrix */
@@ -1463,7 +1522,7 @@ static DriverVarTypeInfo dvar_types[MAX_DVAR_TYPES] = {
};
/* Get driver variable typeinfo */
-static DriverVarTypeInfo *get_dvar_typeinfo(int type)
+static const DriverVarTypeInfo *get_dvar_typeinfo(int type)
{
/* check if valid type */
if ((type >= 0) && (type < MAX_DVAR_TYPES))
@@ -1507,7 +1566,7 @@ void driver_free_variable(ChannelDriver *driver, DriverVar *dvar)
/* Change the type of driver variable */
void driver_change_variable_type(DriverVar *dvar, int type)
{
- DriverVarTypeInfo *dvti = get_dvar_typeinfo(type);
+ const DriverVarTypeInfo *dvti = get_dvar_typeinfo(type);
/* sanity check */
if (ELEM(NULL, dvar, dvti))
@@ -1548,8 +1607,8 @@ DriverVar *driver_add_new_variable(ChannelDriver *driver)
BLI_addtail(&driver->variables, dvar);
/* give the variable a 'unique' name */
- strcpy(dvar->name, CTX_DATA_(BLF_I18NCONTEXT_ID_ACTION, "var"));
- BLI_uniquename(&driver->variables, dvar, CTX_DATA_(BLF_I18NCONTEXT_ID_ACTION, "var"), '_',
+ strcpy(dvar->name, CTX_DATA_(BLT_I18NCONTEXT_ID_ACTION, "var"));
+ BLI_uniquename(&driver->variables, dvar, CTX_DATA_(BLT_I18NCONTEXT_ID_ACTION, "var"), '_',
offsetof(DriverVar, name), sizeof(dvar->name));
/* set the default type to 'single prop' */
@@ -1631,7 +1690,7 @@ ChannelDriver *fcurve_copy_driver(ChannelDriver *driver)
/* Evaluate a Driver Variable to get a value that contributes to the final */
float driver_get_variable_value(ChannelDriver *driver, DriverVar *dvar)
{
- DriverVarTypeInfo *dvti;
+ const DriverVarTypeInfo *dvti;
/* sanity check */
if (ELEM(NULL, driver, dvar))
@@ -1739,7 +1798,9 @@ static float evaluate_driver(ChannelDriver *driver, const float evaltime)
/* this evaluates the expression using Python, and returns its result:
* - on errors it reports, then returns 0.0f
*/
+ BLI_mutex_lock(&python_driver_lock);
driver->curval = BPY_driver_exec(driver, evaltime);
+ BLI_mutex_unlock(&python_driver_lock);
}
#else /* WITH_PYTHON*/
(void)evaltime;
@@ -2069,7 +2130,7 @@ static float fcurve_eval_keyframes(FCurve *fcu, BezTriple *bezts, float evaltime
* This lower bound was established in b888a32eee8147b028464336ad2404d8155c64dd
*/
a = binarysearch_bezt_index_ex(bezts, evaltime, fcu->totvert, 0.0001, &exact);
- if (G.debug & G_DEBUG) printf("eval fcurve '%s' - %f => %d/%d, %d\n", fcu->rna_path, evaltime, a, fcu->totvert, exact);
+ if (G.debug & G_DEBUG) printf("eval fcurve '%s' - %f => %u/%u, %d\n", fcu->rna_path, evaltime, a, fcu->totvert, exact);
if (exact) {
/* index returned must be interpreted differently when it sits on top of an existing keyframe
@@ -2124,18 +2185,29 @@ static float fcurve_eval_keyframes(FCurve *fcu, BezTriple *bezts, float evaltime
v4[0] = bezt->vec[1][0];
v4[1] = bezt->vec[1][1];
- /* adjust handles so that they don't overlap (forming a loop) */
- correct_bezpart(v1, v2, v3, v4);
-
- /* try to get a value for this position - if failure, try another set of points */
- b = findzero(evaltime, v1[0], v2[0], v3[0], v4[0], opl);
- if (b) {
- berekeny(v1[1], v2[1], v3[1], v4[1], opl, 1);
- cvalue = opl[0];
- /* break; */
+ if (fabsf(v1[1] - v4[1]) < FLT_EPSILON &&
+ fabsf(v2[1] - v3[1]) < FLT_EPSILON &&
+ fabsf(v3[1] - v4[1]) < FLT_EPSILON)
+ {
+ /* Optimisation: If all the handles are flat/at the same values,
+ * the value is simply the shared value (see T40372 -> F91346)
+ */
+ cvalue = v1[1];
}
else {
- if (G.debug & G_DEBUG) printf(" ERROR: findzero() failed at %f with %f %f %f %f\n", evaltime, v1[0], v2[0], v3[0], v4[0]);
+ /* adjust handles so that they don't overlap (forming a loop) */
+ correct_bezpart(v1, v2, v3, v4);
+
+ /* try to get a value for this position - if failure, try another set of points */
+ b = findzero(evaltime, v1[0], v2[0], v3[0], v4[0], opl);
+ if (b) {
+ berekeny(v1[1], v2[1], v3[1], v4[1], opl, 1);
+ cvalue = opl[0];
+ /* break; */
+ }
+ else {
+ if (G.debug & G_DEBUG) printf(" ERROR: findzero() failed at %f with %f %f %f %f\n", evaltime, v1[0], v2[0], v3[0], v4[0]);
+ }
}
break;
diff --git a/source/blender/blenkernel/intern/fluidsim.c b/source/blender/blenkernel/intern/fluidsim.c
index beb85b31847..8247336d915 100644
--- a/source/blender/blenkernel/intern/fluidsim.c
+++ b/source/blender/blenkernel/intern/fluidsim.c
@@ -70,54 +70,38 @@ void initElbeemMesh(struct Scene *scene, struct Object *ob,
int *numTriangles, int **triangles,
int useGlobalCoords, int modifierIndex)
{
- DerivedMesh *dm = NULL;
- MVert *mvert;
- MFace *mface;
- int countTris = 0, i, totvert, totface;
+ DerivedMesh *dm;
+ const MVert *mvert;
+ const MLoop *mloop;
+ const MLoopTri *looptri, *lt;
+ int i, mvert_num, looptri_num;
float *verts;
int *tris;
dm = mesh_create_derived_index_render(scene, ob, CD_MASK_BAREMESH, modifierIndex);
- DM_ensure_tessface(dm);
+ DM_ensure_looptri(dm);
mvert = dm->getVertArray(dm);
- mface = dm->getTessFaceArray(dm);
- totvert = dm->getNumVerts(dm);
- totface = dm->getNumTessFaces(dm);
-
- *numVertices = totvert;
- verts = MEM_callocN(totvert * 3 * sizeof(float), "elbeemmesh_vertices");
- for (i = 0; i < totvert; i++) {
+ mloop = dm->getLoopArray(dm);
+ looptri = dm->getLoopTriArray(dm);
+ mvert_num = dm->getNumVerts(dm);
+ looptri_num = dm->getNumLoopTri(dm);
+
+ *numVertices = mvert_num;
+ verts = MEM_mallocN(mvert_num * sizeof(float[3]), "elbeemmesh_vertices");
+ for (i = 0; i < mvert_num; i++) {
copy_v3_v3(&verts[i * 3], mvert[i].co);
if (useGlobalCoords) { mul_m4_v3(ob->obmat, &verts[i * 3]); }
}
*vertices = verts;
- for (i = 0; i < totface; i++) {
- countTris++;
- if (mface[i].v4) { countTris++; }
- }
- *numTriangles = countTris;
- tris = MEM_callocN(countTris * 3 * sizeof(int), "elbeemmesh_triangles");
- countTris = 0;
- for (i = 0; i < totface; i++) {
- int face[4];
- face[0] = mface[i].v1;
- face[1] = mface[i].v2;
- face[2] = mface[i].v3;
- face[3] = mface[i].v4;
-
- tris[countTris * 3 + 0] = face[0];
- tris[countTris * 3 + 1] = face[1];
- tris[countTris * 3 + 2] = face[2];
- countTris++;
- if (face[3]) {
- tris[countTris * 3 + 0] = face[0];
- tris[countTris * 3 + 1] = face[2];
- tris[countTris * 3 + 2] = face[3];
- countTris++;
- }
+ *numTriangles = looptri_num;
+ tris = MEM_mallocN(looptri_num * sizeof(int[3]), "elbeemmesh_triangles");
+ for (i = 0, lt = looptri; i < looptri_num; i++, lt++) {
+ tris[(i * 3) + 0] = mloop[lt->tri[0]].v;
+ tris[(i * 3) + 1] = mloop[lt->tri[1]].v;
+ tris[(i * 3) + 2] = mloop[lt->tri[2]].v;
}
*triangles = tris;
diff --git a/source/blender/blenkernel/intern/fmodifier.c b/source/blender/blenkernel/intern/fmodifier.c
index 56b087e7eb6..2305ae89abd 100644
--- a/source/blender/blenkernel/intern/fmodifier.c
+++ b/source/blender/blenkernel/intern/fmodifier.c
@@ -27,8 +27,6 @@
* \ingroup bke
*/
-
-
#include <math.h>
#include <stdio.h>
#include <stddef.h>
@@ -39,7 +37,7 @@
#include "DNA_anim_types.h"
-#include "BLF_translation.h"
+#include "BLT_translation.h"
#include "BLI_blenlib.h"
#include "BLI_ghash.h"
@@ -1042,7 +1040,7 @@ static void fmods_init_typeinfo(void)
/* This function should be used for getting the appropriate type-info when only
* a F-Curve modifier type is known
*/
-FModifierTypeInfo *get_fmodifier_typeinfo(int type)
+const FModifierTypeInfo *get_fmodifier_typeinfo(int type)
{
/* initialize the type-info list? */
if (FMI_INIT) {
@@ -1067,7 +1065,7 @@ FModifierTypeInfo *get_fmodifier_typeinfo(int type)
/* This function should always be used to get the appropriate type-info, as it
* has checks which prevent segfaults in some weird cases.
*/
-FModifierTypeInfo *fmodifier_get_typeinfo(FModifier *fcm)
+const FModifierTypeInfo *fmodifier_get_typeinfo(FModifier *fcm)
{
/* only return typeinfo for valid modifiers */
if (fcm)
@@ -1081,7 +1079,7 @@ FModifierTypeInfo *fmodifier_get_typeinfo(FModifier *fcm)
/* Add a new F-Curve Modifier to the given F-Curve of a certain type */
FModifier *add_fmodifier(ListBase *modifiers, int type)
{
- FModifierTypeInfo *fmi = get_fmodifier_typeinfo(type);
+ const FModifierTypeInfo *fmi = get_fmodifier_typeinfo(type);
FModifier *fcm;
/* sanity checks */
@@ -1121,7 +1119,7 @@ FModifier *add_fmodifier(ListBase *modifiers, int type)
/* Make a copy of the specified F-Modifier */
FModifier *copy_fmodifier(FModifier *src)
{
- FModifierTypeInfo *fmi = fmodifier_get_typeinfo(src);
+ const FModifierTypeInfo *fmi = fmodifier_get_typeinfo(src);
FModifier *dst;
/* sanity check */
@@ -1155,7 +1153,7 @@ void copy_fmodifiers(ListBase *dst, ListBase *src)
BLI_duplicatelist(dst, src);
for (fcm = dst->first, srcfcm = src->first; fcm && srcfcm; srcfcm = srcfcm->next, fcm = fcm->next) {
- FModifierTypeInfo *fmi = fmodifier_get_typeinfo(fcm);
+ const FModifierTypeInfo *fmi = fmodifier_get_typeinfo(fcm);
/* make a new copy of the F-Modifier's data */
fcm->data = MEM_dupallocN(fcm->data);
@@ -1169,11 +1167,11 @@ void copy_fmodifiers(ListBase *dst, ListBase *src)
/* Remove and free the given F-Modifier from the given stack */
bool remove_fmodifier(ListBase *modifiers, FModifier *fcm)
{
- FModifierTypeInfo *fmi = fmodifier_get_typeinfo(fcm);
+ const FModifierTypeInfo *fmi = fmodifier_get_typeinfo(fcm);
/* sanity check */
if (fcm == NULL)
- return 0;
+ return false;
/* free modifier's special data (stored inside fcm->data) */
if (fcm->data) {
@@ -1187,13 +1185,13 @@ bool remove_fmodifier(ListBase *modifiers, FModifier *fcm)
/* remove modifier from stack */
if (modifiers) {
BLI_freelinkN(modifiers, fcm);
- return 1;
+ return true;
}
else {
/* XXX this case can probably be removed some day, as it shouldn't happen... */
printf("remove_fmodifier() - no modifier stack given\n");
MEM_freeN(fcm);
- return 0;
+ return false;
}
}
@@ -1264,11 +1262,11 @@ bool list_has_suitable_fmodifier(ListBase *modifiers, int mtype, short acttype)
/* sanity checks */
if (ELEM(NULL, modifiers, modifiers->first))
- return 0;
+ return false;
/* find the first mdifier fitting these criteria */
for (fcm = modifiers->first; fcm; fcm = fcm->next) {
- FModifierTypeInfo *fmi = fmodifier_get_typeinfo(fcm);
+ const FModifierTypeInfo *fmi = fmodifier_get_typeinfo(fcm);
short mOk = 1, aOk = 1; /* by default 1, so that when only one test, won't fail */
/* check if applicable ones are fullfilled */
@@ -1279,11 +1277,11 @@ bool list_has_suitable_fmodifier(ListBase *modifiers, int mtype, short acttype)
/* if both are ok, we've found a hit */
if (mOk && aOk)
- return 1;
+ return true;
}
/* no matches */
- return 0;
+ return false;
}
/* Evaluation API --------------------------- */
@@ -1298,7 +1296,7 @@ FModifierStackStorage *evaluate_fmodifiers_storage_new(ListBase *modifiers)
}
for (fcm = modifiers->last; fcm; fcm = fcm->prev) {
- FModifierTypeInfo *fmi = fmodifier_get_typeinfo(fcm);
+ const FModifierTypeInfo *fmi = fmodifier_get_typeinfo(fcm);
if (fmi == NULL) {
continue;
@@ -1391,6 +1389,8 @@ static float eval_fmodifier_influence(FModifier *fcm, float evaltime)
* working on the 'global' result of the modified curve, not some localised segment,
* so nevaltime gets set to whatever the last time-modifying modifier likes...
* - we start from the end of the stack, as only the last one matters for now
+ *
+ * Note: *fcu might be NULL
*/
float evaluate_time_fmodifiers(FModifierStackStorage *storage, ListBase *modifiers,
FCurve *fcu, float cvalue, float evaltime)
@@ -1400,7 +1400,10 @@ float evaluate_time_fmodifiers(FModifierStackStorage *storage, ListBase *modifie
/* sanity checks */
if (ELEM(NULL, modifiers, modifiers->last))
return evaltime;
-
+
+ if (fcu && fcu->flag & FCURVE_MOD_OFF)
+ return evaltime;
+
/* Starting from the end of the stack, calculate the time effects of various stacked modifiers
* on the time the F-Curve should be evaluated at.
*
@@ -1412,7 +1415,7 @@ float evaluate_time_fmodifiers(FModifierStackStorage *storage, ListBase *modifie
* (such as multiple 'stepped' modifiers in sequence, causing different stepping rates)
*/
for (fcm = modifiers->last; fcm; fcm = fcm->prev) {
- FModifierTypeInfo *fmi = fmodifier_get_typeinfo(fcm);
+ const FModifierTypeInfo *fmi = fmodifier_get_typeinfo(fcm);
if (fmi == NULL)
continue;
@@ -1457,10 +1460,13 @@ void evaluate_value_fmodifiers(FModifierStackStorage *storage, ListBase *modifie
/* sanity checks */
if (ELEM(NULL, modifiers, modifiers->first))
return;
+
+ if (fcu->flag & FCURVE_MOD_OFF)
+ return;
/* evaluate modifiers */
for (fcm = modifiers->first; fcm; fcm = fcm->next) {
- FModifierTypeInfo *fmi = fmodifier_get_typeinfo(fcm);
+ const FModifierTypeInfo *fmi = fmodifier_get_typeinfo(fcm);
if (fmi == NULL)
continue;
diff --git a/source/blender/blenkernel/intern/font.c b/source/blender/blenkernel/intern/font.c
index 8d4bb7ec058..23261b63486 100644
--- a/source/blender/blenkernel/intern/font.c
+++ b/source/blender/blenkernel/intern/font.c
@@ -245,7 +245,7 @@ VFont *BKE_vfont_load(Main *bmain, const char *name)
}
/* Do not add FO_BUILTIN_NAME to temporary listbase */
- if (strcmp(filename, FO_BUILTIN_NAME)) {
+ if (!STREQ(filename, FO_BUILTIN_NAME)) {
vfont->temp_pf = temp_pf;
}
}
@@ -777,7 +777,7 @@ makebreak:
if ((tb_scale.h != 0.0f) &&
(cu->totbox > (curbox + 1)) &&
- ((-(yof - tb_scale.y)) > (tb_scale.h - (linedist * cu->fsize)) - yof_scale))
+ ((-(yof - tb_scale.y)) > (tb_scale.h - linedist) - yof_scale))
{
maxlen = 0;
curbox++;
diff --git a/source/blender/blenkernel/intern/freestyle.c b/source/blender/blenkernel/intern/freestyle.c
index 4aa1b49ea13..f6c4263cff7 100644
--- a/source/blender/blenkernel/intern/freestyle.c
+++ b/source/blender/blenkernel/intern/freestyle.c
@@ -179,15 +179,15 @@ static FreestyleLineSet *alloc_lineset(void)
return (FreestyleLineSet *)MEM_callocN(sizeof(FreestyleLineSet), "Freestyle line set");
}
-FreestyleLineSet *BKE_freestyle_lineset_add(FreestyleConfig *config, const char *name)
+FreestyleLineSet *BKE_freestyle_lineset_add(struct Main *bmain, FreestyleConfig *config, const char *name)
{
- int lineset_index = BLI_countlist(&config->linesets);
+ int lineset_index = BLI_listbase_count(&config->linesets);
FreestyleLineSet *lineset = alloc_lineset();
BLI_addtail(&config->linesets, (void *)lineset);
BKE_freestyle_lineset_set_active_index(config, lineset_index);
- lineset->linestyle = BKE_linestyle_new("LineStyle", NULL);
+ lineset->linestyle = BKE_linestyle_new(bmain, "LineStyle");
lineset->flags |= FREESTYLE_LINESET_ENABLED;
lineset->selection = FREESTYLE_SEL_VISIBILITY | FREESTYLE_SEL_EDGE_TYPES | FREESTYLE_SEL_IMAGE_BORDER;
lineset->qi = FREESTYLE_QI_VISIBLE;
diff --git a/source/blender/blenkernel/intern/gpencil.c b/source/blender/blenkernel/intern/gpencil.c
index e226e9d9797..ee5c9192371 100644
--- a/source/blender/blenkernel/intern/gpencil.c
+++ b/source/blender/blenkernel/intern/gpencil.c
@@ -40,11 +40,12 @@
#include "BLI_utildefines.h"
#include "BLI_math_vector.h"
-#include "BLF_translation.h"
+#include "BLT_translation.h"
#include "DNA_gpencil_types.h"
#include "DNA_userdef_types.h"
+#include "BKE_animsys.h"
#include "BKE_global.h"
#include "BKE_gpencil.h"
#include "BKE_library.h"
@@ -115,6 +116,12 @@ void BKE_gpencil_free(bGPdata *gpd)
{
/* free layers */
free_gpencil_layers(&gpd->layers);
+
+ /* free animation data */
+ if (gpd->adt) {
+ BKE_animdata_free(&gpd->id);
+ gpd->adt = NULL;
+ }
}
/* -------- Container Creation ---------- */
@@ -122,11 +129,11 @@ void BKE_gpencil_free(bGPdata *gpd)
/* add a new gp-frame to the given layer */
bGPDframe *gpencil_frame_addnew(bGPDlayer *gpl, int cframe)
{
- bGPDframe *gpf, *gf;
+ bGPDframe *gpf = NULL, *gf = NULL;
short state = 0;
/* error checking (neg frame only if they are not allowed in Blender!) */
- if ((gpl == NULL) || ((U.flag & USER_NONEGFRAMES) && (cframe <= 0)))
+ if (gpl == NULL)
return NULL;
/* allocate memory for this frame */
@@ -153,8 +160,14 @@ bGPDframe *gpencil_frame_addnew(bGPDlayer *gpl, int cframe)
/* check whether frame was added successfully */
if (state == -1) {
+ printf("Error: Frame (%d) existed already for this layer. Using existing frame\n", cframe);
+
+ /* free the newly created one, and use the old one instead */
MEM_freeN(gpf);
- printf("Error: frame (%d) existed already for this layer\n", cframe);
+
+ /* return existing frame instead... */
+ BLI_assert(gf != NULL);
+ gpf = gf;
}
else if (state == 0) {
/* add to end then! */
@@ -276,7 +289,7 @@ bGPDlayer *gpencil_layer_duplicate(bGPDlayer *src)
}
/* make a copy of a given gpencil datablock */
-bGPdata *gpencil_data_duplicate(bGPdata *src)
+bGPdata *gpencil_data_duplicate(bGPdata *src, bool internal_copy)
{
bGPDlayer *gpl, *gpld;
bGPdata *dst;
@@ -286,7 +299,14 @@ bGPdata *gpencil_data_duplicate(bGPdata *src)
return NULL;
/* make a copy of the base-data */
- dst = MEM_dupallocN(src);
+ if (internal_copy) {
+ /* make a straight copy for undo buffers used during stroke drawing */
+ dst = MEM_dupallocN(src);
+ }
+ else {
+ /* make a copy when others use this */
+ dst = BKE_libblock_copy(&src->id);
+ }
/* copy layers */
BLI_listbase_clear(&dst->layers);
@@ -300,6 +320,31 @@ bGPdata *gpencil_data_duplicate(bGPdata *src)
return dst;
}
+/* -------- GP-Stroke API --------- */
+
+/* ensure selection status of stroke is in sync with its points */
+void gpencil_stroke_sync_selection(bGPDstroke *gps)
+{
+ bGPDspoint *pt;
+ int i;
+
+ /* error checking */
+ if (gps == NULL)
+ return;
+
+ /* we'll stop when we find the first selected point,
+ * so initially, we must deselect
+ */
+ gps->flag &= ~GP_STROKE_SELECT;
+
+ for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
+ if (pt->flag & GP_SPOINT_SELECT) {
+ gps->flag |= GP_STROKE_SELECT;
+ break;
+ }
+ }
+}
+
/* -------- GP-Frame API ---------- */
/* delete the last stroke of the given frame */
@@ -349,8 +394,6 @@ bGPDframe *gpencil_layer_getframe(bGPDlayer *gpl, int cframe, short addnew)
/* error checking */
if (gpl == NULL) return NULL;
- /* No reason to forbid negative frames when they are allowed in Blender! */
- if ((U.flag & USER_NONEGFRAMES) && cframe <= 0) cframe = 1;
/* check if there is already an active frame */
if (gpl->actframe) {
@@ -359,7 +402,7 @@ bGPDframe *gpencil_layer_getframe(bGPDlayer *gpl, int cframe, short addnew)
/* do not allow any changes to layer's active frame if layer is locked from changes
* or if the layer has been set to stay on the current frame
*/
- if (gpl->flag & (GP_LAYER_LOCKED | GP_LAYER_FRAMELOCK))
+ if (gpl->flag & GP_LAYER_FRAMELOCK)
return gpf;
/* do not allow any changes to actframe if frame has painting tag attached to it */
if (gpf->flag & GP_FRAME_PAINT)
@@ -468,16 +511,23 @@ bGPDframe *gpencil_layer_getframe(bGPDlayer *gpl, int cframe, short addnew)
bool gpencil_layer_delframe(bGPDlayer *gpl, bGPDframe *gpf)
{
bool changed = false;
-
+
/* error checking */
if (ELEM(NULL, gpl, gpf))
return false;
-
+
+ /* if this frame was active, make the previous frame active instead
+ * since it's tricky to set active frame otherwise
+ */
+ if (gpl->actframe == gpf)
+ gpl->actframe = gpf->prev;
+ else
+ gpl->actframe = NULL;
+
/* free the frame and its data */
changed = free_gpencil_strokes(gpf);
BLI_freelinkN(&gpl->frames, gpf);
- gpl->actframe = NULL;
-
+
return changed;
}
diff --git a/source/blender/blenkernel/intern/group.c b/source/blender/blenkernel/intern/group.c
index 6ea6bafaa14..3f68339be11 100644
--- a/source/blender/blenkernel/intern/group.c
+++ b/source/blender/blenkernel/intern/group.c
@@ -49,6 +49,7 @@
#include "BKE_depsgraph.h"
#include "BKE_global.h"
#include "BKE_group.h"
+#include "BKE_icons.h"
#include "BKE_library.h"
#include "BKE_main.h"
#include "BKE_object.h"
@@ -64,7 +65,9 @@ void BKE_group_free(Group *group)
{
/* don't free group itself */
GroupObject *go;
-
+
+ BKE_previewimg_free(&group->preview);
+
while ((go = BLI_pophead(&group->gobject))) {
free_group_object(go);
}
@@ -139,6 +142,9 @@ Group *BKE_group_add(Main *bmain, const char *name)
group = BKE_libblock_alloc(bmain, ID_GR, name);
group->layer = (1 << 20) - 1;
+
+ group->preview = NULL;
+
return group;
}
@@ -149,6 +155,13 @@ Group *BKE_group_copy(Group *group)
groupn = BKE_libblock_copy(&group->id);
BLI_duplicatelist(&groupn->gobject, &group->gobject);
+ /* Do not copy group's preview (same behavior as for objects). */
+ groupn->preview = NULL;
+
+ if (group->id.lib) {
+ BKE_id_lib_local_paths(G.main, group->id.lib, &groupn->id);
+ }
+
return groupn;
}
@@ -215,6 +228,43 @@ static int group_object_unlink_internal(Group *group, Object *ob)
return removed;
}
+static bool group_object_cyclic_check_internal(Object *object, Group *group)
+{
+ if (object->dup_group) {
+ Group *dup_group = object->dup_group;
+ if ((dup_group->id.flag & LIB_DOIT) == 0) {
+ /* Cycle already exists in groups, let's prevent further crappyness */
+ return true;
+ }
+ /* flag the object to identify cyclic dependencies in further dupli groups */
+ dup_group->id.flag &= ~LIB_DOIT;
+
+ if (dup_group == group)
+ return true;
+ else {
+ GroupObject *gob;
+ for (gob = dup_group->gobject.first; gob; gob = gob->next) {
+ if (group_object_cyclic_check_internal(gob->ob, group)) {
+ return true;
+ }
+ }
+ }
+
+ /* un-flag the object, it's allowed to have the same group multiple times in parallel */
+ dup_group->id.flag |= LIB_DOIT;
+ }
+
+ return false;
+}
+
+bool BKE_group_object_cyclic_check(Main *bmain, Object *object, Group *group)
+{
+ /* first flag all groups */
+ BKE_main_id_tag_listbase(&bmain->group, true);
+
+ return group_object_cyclic_check_internal(object, group);
+}
+
bool BKE_group_object_unlink(Group *group, Object *object, Scene *scene, Base *base)
{
if (group_object_unlink_internal(group, object)) {
diff --git a/source/blender/blenkernel/intern/icons.c b/source/blender/blenkernel/intern/icons.c
index 8bda957f187..2171f193bac 100644
--- a/source/blender/blenkernel/intern/icons.c
+++ b/source/blender/blenkernel/intern/icons.c
@@ -37,14 +37,18 @@
#include "MEM_guardedalloc.h"
+#include "DNA_group_types.h"
#include "DNA_lamp_types.h"
#include "DNA_material_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
#include "DNA_texture_types.h"
#include "DNA_world_types.h"
#include "DNA_brush_types.h"
#include "BLI_utildefines.h"
#include "BLI_ghash.h"
+#include "BLI_string.h"
#include "BKE_icons.h"
#include "BKE_global.h" /* only for G.background test */
@@ -53,6 +57,10 @@
#include "GPU_extensions.h"
+#include "IMB_imbuf.h"
+#include "IMB_imbuf_types.h"
+#include "IMB_thumbs.h"
+
/* GLOBALS */
static GHash *gIcons = NULL;
@@ -61,6 +69,7 @@ static int gNextIconId = 1;
static int gFirstIconId = 1;
+static GHash *gCachedPreviews = NULL;
static void icon_free(void *val)
{
@@ -105,30 +114,50 @@ void BKE_icons_init(int first_dyn_id)
gFirstIconId = first_dyn_id;
if (!gIcons)
- gIcons = BLI_ghash_int_new("icons_init gh");
+ gIcons = BLI_ghash_int_new(__func__);
+
+ if (!gCachedPreviews) {
+ gCachedPreviews = BLI_ghash_str_new(__func__);
+ }
}
void BKE_icons_free(void)
{
- if (gIcons)
+ if (gIcons) {
BLI_ghash_free(gIcons, NULL, icon_free);
- gIcons = NULL;
+ gIcons = NULL;
+ }
+
+ if (gCachedPreviews) {
+ BLI_ghash_free(gCachedPreviews, MEM_freeN, BKE_previewimg_freefunc);
+ gCachedPreviews = NULL;
+ }
}
-PreviewImage *BKE_previewimg_create(void)
+static PreviewImage *previewimg_create_ex(size_t deferred_data_size)
{
PreviewImage *prv_img = NULL;
int i;
- prv_img = MEM_callocN(sizeof(PreviewImage), "img_prv");
+ prv_img = MEM_mallocN(sizeof(PreviewImage) + deferred_data_size, "img_prv");
+ memset(prv_img, 0, sizeof(*prv_img)); /* leave deferred data dirty */
+
+ if (deferred_data_size) {
+ prv_img->use_deferred = true;
+ }
for (i = 0; i < NUM_ICON_SIZES; ++i) {
- prv_img->changed[i] = 1;
+ prv_img->flag[i] |= PRV_CHANGED;
prv_img->changed_timestamp[i] = 0;
}
return prv_img;
}
+PreviewImage *BKE_previewimg_create(void)
+{
+ return previewimg_create_ex(0);
+}
+
void BKE_previewimg_freefunc(void *link)
{
PreviewImage *prv = (PreviewImage *)link;
@@ -138,7 +167,6 @@ void BKE_previewimg_freefunc(void *link)
for (i = 0; i < NUM_ICON_SIZES; ++i) {
if (prv->rect[i]) {
MEM_freeN(prv->rect[i]);
- prv->rect[i] = NULL;
}
if (prv->gputexture[i])
GPU_texture_free(prv->gputexture[i]);
@@ -156,6 +184,26 @@ void BKE_previewimg_free(PreviewImage **prv)
}
}
+void BKE_previewimg_clear_single(struct PreviewImage *prv, enum eIconSizes size)
+{
+ MEM_SAFE_FREE(prv->rect[size]);
+ if (prv->gputexture[size]) {
+ GPU_texture_free(prv->gputexture[size]);
+ }
+ prv->h[size] = prv->w[size] = 0;
+ prv->flag[size] |= PRV_CHANGED;
+ prv->flag[size] &= ~PRV_USER_EDITED;
+ prv->changed_timestamp[size] = 0;
+}
+
+void BKE_previewimg_clear(struct PreviewImage *prv)
+{
+ int i;
+ for (i = 0; i < NUM_ICON_SIZES; ++i) {
+ BKE_previewimg_clear_single(prv, i);
+ }
+}
+
PreviewImage *BKE_previewimg_copy(PreviewImage *prv)
{
PreviewImage *prv_img = NULL;
@@ -167,79 +215,189 @@ PreviewImage *BKE_previewimg_copy(PreviewImage *prv)
if (prv->rect[i]) {
prv_img->rect[i] = MEM_dupallocN(prv->rect[i]);
}
- else {
- prv_img->rect[i] = NULL;
- }
prv_img->gputexture[i] = NULL;
}
}
return prv_img;
}
-void BKE_previewimg_free_id(ID *id)
+PreviewImage **BKE_previewimg_id_get_p(ID *id)
{
- if (GS(id->name) == ID_MA) {
- Material *mat = (Material *)id;
- BKE_previewimg_free(&mat->preview);
- }
- else if (GS(id->name) == ID_TE) {
- Tex *tex = (Tex *)id;
- BKE_previewimg_free(&tex->preview);
- }
- else if (GS(id->name) == ID_WO) {
- World *wo = (World *)id;
- BKE_previewimg_free(&wo->preview);
+ switch (GS(id->name)) {
+#define ID_PRV_CASE(id_code, id_struct) case id_code: { return &((id_struct *)id)->preview; } ((void)0)
+ ID_PRV_CASE(ID_MA, Material);
+ ID_PRV_CASE(ID_TE, Tex);
+ ID_PRV_CASE(ID_WO, World);
+ ID_PRV_CASE(ID_LA, Lamp);
+ ID_PRV_CASE(ID_IM, Image);
+ ID_PRV_CASE(ID_BR, Brush);
+ ID_PRV_CASE(ID_OB, Object);
+ ID_PRV_CASE(ID_GR, Group);
+ ID_PRV_CASE(ID_SCE, Scene);
+#undef ID_PRV_CASE
}
- else if (GS(id->name) == ID_LA) {
- Lamp *la = (Lamp *)id;
- BKE_previewimg_free(&la->preview);
- }
- else if (GS(id->name) == ID_IM) {
- Image *img = (Image *)id;
- BKE_previewimg_free(&img->preview);
+
+ return NULL;
+}
+
+void BKE_previewimg_id_free(ID *id)
+{
+ PreviewImage **prv_p = BKE_previewimg_id_get_p(id);
+ if (prv_p) {
+ BKE_previewimg_free(prv_p);
}
- else if (GS(id->name) == ID_BR) {
- Brush *br = (Brush *)id;
- BKE_previewimg_free(&br->preview);
+}
+
+PreviewImage *BKE_previewimg_id_ensure(ID *id)
+{
+ PreviewImage **prv_p = BKE_previewimg_id_get_p(id);
+
+ if (prv_p) {
+ if (*prv_p == NULL) {
+ *prv_p = BKE_previewimg_create();
+ }
+ return *prv_p;
}
+
+ return NULL;
}
-PreviewImage *BKE_previewimg_get(ID *id)
+PreviewImage *BKE_previewimg_cached_get(const char *name)
{
- PreviewImage *prv_img = NULL;
+ return BLI_ghash_lookup(gCachedPreviews, name);
+}
- if (GS(id->name) == ID_MA) {
- Material *mat = (Material *)id;
- if (!mat->preview) mat->preview = BKE_previewimg_create();
- prv_img = mat->preview;
+/**
+ * Generate an empty PreviewImage, if not yet existing.
+ */
+PreviewImage *BKE_previewimg_cached_ensure(const char *name)
+{
+ PreviewImage *prv = NULL;
+ void **prv_p;
+
+ if (!BLI_ghash_ensure_p_ex(gCachedPreviews, name, &prv_p, (GHashKeyCopyFP)BLI_strdup)) {
+ *prv_p = BKE_previewimg_create();
}
- else if (GS(id->name) == ID_TE) {
- Tex *tex = (Tex *)id;
- if (!tex->preview) tex->preview = BKE_previewimg_create();
- prv_img = tex->preview;
+ prv = *prv_p;
+ BLI_assert(prv);
+
+ return prv;
+}
+
+/**
+ * Generate a PreviewImage from given file path, using thumbnails management, if not yet existing.
+ */
+PreviewImage *BKE_previewimg_cached_thumbnail_read(
+ const char *name, const char *path, const int source, bool force_update)
+{
+ PreviewImage *prv = NULL;
+ void **prv_p;
+
+ prv_p = BLI_ghash_lookup_p(gCachedPreviews, name);
+
+ if (prv_p) {
+ prv = *prv_p;
+ BLI_assert(prv);
}
- else if (GS(id->name) == ID_WO) {
- World *wo = (World *)id;
- if (!wo->preview) wo->preview = BKE_previewimg_create();
- prv_img = wo->preview;
+
+ if (prv && force_update) {
+ const char *prv_deferred_data = PRV_DEFERRED_DATA(prv);
+ if (((int)prv_deferred_data[0] == source) && STREQ(&prv_deferred_data[1], path)) {
+ /* If same path, no need to re-allocate preview, just clear it up. */
+ BKE_previewimg_clear(prv);
+ }
+ else {
+ BKE_previewimg_free(&prv);
+ }
}
- else if (GS(id->name) == ID_LA) {
- Lamp *la = (Lamp *)id;
- if (!la->preview) la->preview = BKE_previewimg_create();
- prv_img = la->preview;
+
+ if (!prv) {
+ /* We pack needed data for lazy loading (source type, in a single char, and path). */
+ const size_t deferred_data_size = strlen(path) + 2;
+ char *deferred_data;
+
+ prv = previewimg_create_ex(deferred_data_size);
+ deferred_data = PRV_DEFERRED_DATA(prv);
+ deferred_data[0] = source;
+ memcpy(&deferred_data[1], path, deferred_data_size - 1);
+
+ force_update = true;
}
- else if (GS(id->name) == ID_IM) {
- Image *img = (Image *)id;
- if (!img->preview) img->preview = BKE_previewimg_create();
- prv_img = img->preview;
+
+ if (force_update) {
+ if (prv_p) {
+ *prv_p = prv;
+ }
+ else {
+ BLI_ghash_insert(gCachedPreviews, BLI_strdup(name), prv);
+ }
}
- else if (GS(id->name) == ID_BR) {
- Brush *br = (Brush *)id;
- if (!br->preview) br->preview = BKE_previewimg_create();
- prv_img = br->preview;
+
+ return prv;
+}
+
+void BKE_previewimg_cached_release(const char *name)
+{
+ PreviewImage *prv = BLI_ghash_popkey(gCachedPreviews, name, MEM_freeN);
+
+ if (prv) {
+ if (prv->icon_id) {
+ BKE_icon_delete(prv->icon_id);
+ }
+ BKE_previewimg_freefunc(prv);
}
+}
- return prv_img;
+/** Handle deferred (lazy) loading/generation of preview image, if needed.
+ * For now, only used with file thumbnails. */
+void BKE_previewimg_ensure(PreviewImage *prv, const int size)
+{
+ if (prv->use_deferred) {
+ const bool do_icon = ((size == ICON_SIZE_ICON) && !prv->rect[ICON_SIZE_ICON]);
+ const bool do_preview = ((size == ICON_SIZE_PREVIEW) && !prv->rect[ICON_SIZE_PREVIEW]);
+
+ if (do_icon || do_preview) {
+ ImBuf *thumb;
+ char *prv_deferred_data = PRV_DEFERRED_DATA(prv);
+ int source = prv_deferred_data[0];
+ char *path = &prv_deferred_data[1];
+ int icon_w, icon_h;
+
+ thumb = IMB_thumb_manage(path, THB_LARGE, source);
+
+ if (thumb) {
+ /* PreviewImage assumes premultiplied alhpa... */
+ IMB_premultiply_alpha(thumb);
+
+ if (do_preview) {
+ prv->w[ICON_SIZE_PREVIEW] = thumb->x;
+ prv->h[ICON_SIZE_PREVIEW] = thumb->y;
+ prv->rect[ICON_SIZE_PREVIEW] = MEM_dupallocN(thumb->rect);
+ prv->flag[ICON_SIZE_PREVIEW] &= ~(PRV_CHANGED | PRV_USER_EDITED);
+ }
+ if (do_icon) {
+ if (thumb->x > thumb->y) {
+ icon_w = ICON_RENDER_DEFAULT_HEIGHT;
+ icon_h = (thumb->y * icon_w) / thumb->x + 1;
+ }
+ else if (thumb->x < thumb->y) {
+ icon_h = ICON_RENDER_DEFAULT_HEIGHT;
+ icon_w = (thumb->x * icon_h) / thumb->y + 1;
+ }
+ else {
+ icon_w = icon_h = ICON_RENDER_DEFAULT_HEIGHT;
+ }
+
+ IMB_scaleImBuf(thumb, icon_w, icon_h);
+ prv->w[ICON_SIZE_ICON] = icon_w;
+ prv->h[ICON_SIZE_ICON] = icon_h;
+ prv->rect[ICON_SIZE_ICON] = MEM_dupallocN(thumb->rect);
+ prv->flag[ICON_SIZE_ICON] &= ~(PRV_CHANGED | PRV_USER_EDITED);
+ }
+ IMB_freeImBuf(thumb);
+ }
+ }
+ }
}
void BKE_icon_changed(int id)
@@ -251,20 +409,20 @@ void BKE_icon_changed(int id)
icon = BLI_ghash_lookup(gIcons, SET_INT_IN_POINTER(id));
if (icon) {
- PreviewImage *prv = BKE_previewimg_get((ID *)icon->obj);
+ PreviewImage *prv = BKE_previewimg_id_ensure((ID *)icon->obj);
/* all previews changed */
if (prv) {
int i;
for (i = 0; i < NUM_ICON_SIZES; ++i) {
- prv->changed[i] = 1;
+ prv->flag[i] |= PRV_CHANGED;
prv->changed_timestamp[i]++;
}
}
}
}
-int BKE_icon_getid(struct ID *id)
+int BKE_icon_id_ensure(struct ID *id)
{
Icon *new_icon = NULL;
@@ -277,11 +435,11 @@ int BKE_icon_getid(struct ID *id)
id->icon_id = get_next_free_id();
if (!id->icon_id) {
- printf("BKE_icon_getid: Internal error - not enough IDs\n");
+ printf("%s: Internal error - not enough IDs\n", __func__);
return 0;
}
- new_icon = MEM_callocN(sizeof(Icon), "texicon");
+ new_icon = MEM_mallocN(sizeof(Icon), __func__);
new_icon->obj = id;
new_icon->type = GS(id->name);
@@ -295,6 +453,40 @@ int BKE_icon_getid(struct ID *id)
return id->icon_id;
}
+/**
+ * Return icon id of given preview, or create new icon if not found.
+ */
+int BKE_icon_preview_ensure(PreviewImage *preview)
+{
+ Icon *new_icon = NULL;
+
+ if (!preview || G.background)
+ return 0;
+
+ if (preview->icon_id)
+ return preview->icon_id;
+
+ preview->icon_id = get_next_free_id();
+
+ if (!preview->icon_id) {
+ printf("%s: Internal error - not enough IDs\n", __func__);
+ return 0;
+ }
+
+ new_icon = MEM_mallocN(sizeof(Icon), __func__);
+
+ new_icon->obj = preview;
+ new_icon->type = 0; /* Special, tags as non-ID icon/preview. */
+
+ /* next two lines make sure image gets created */
+ new_icon->drawinfo = NULL;
+ new_icon->drawinfo_free = NULL;
+
+ BLI_ghash_insert(gIcons, SET_INT_IN_POINTER(preview->icon_id), new_icon);
+
+ return preview->icon_id;
+}
+
Icon *BKE_icon_get(int icon_id)
{
Icon *icon = NULL;
@@ -302,7 +494,7 @@ Icon *BKE_icon_get(int icon_id)
icon = BLI_ghash_lookup(gIcons, SET_INT_IN_POINTER(icon_id));
if (!icon) {
- printf("BKE_icon_get: Internal error, no icon for icon ID: %d\n", icon_id);
+ printf("%s: Internal error, no icon for icon ID: %d\n", __func__, icon_id);
return NULL;
}
@@ -311,23 +503,42 @@ Icon *BKE_icon_get(int icon_id)
void BKE_icon_set(int icon_id, struct Icon *icon)
{
- Icon *old_icon = NULL;
+ void **val_p;
- old_icon = BLI_ghash_lookup(gIcons, SET_INT_IN_POINTER(icon_id));
-
- if (old_icon) {
- printf("BKE_icon_set: Internal error, icon already set: %d\n", icon_id);
+ if (BLI_ghash_ensure_p(gIcons, SET_INT_IN_POINTER(icon_id), &val_p)) {
+ printf("%s: Internal error, icon already set: %d\n", __func__, icon_id);
return;
}
- BLI_ghash_insert(gIcons, SET_INT_IN_POINTER(icon_id), icon);
+ *val_p = icon;
}
-void BKE_icon_delete(struct ID *id)
+void BKE_icon_id_delete(struct ID *id)
{
-
if (!id->icon_id) return; /* no icon defined for library object */
BLI_ghash_remove(gIcons, SET_INT_IN_POINTER(id->icon_id), NULL, icon_free);
id->icon_id = 0;
}
+
+/**
+ * Remove icon and free data.
+ */
+void BKE_icon_delete(int icon_id)
+{
+ Icon *icon;
+
+ if (!icon_id) return; /* no icon defined for library object */
+
+ icon = BLI_ghash_popkey(gIcons, SET_INT_IN_POINTER(icon_id), NULL);
+
+ if (icon) {
+ if (icon->type) {
+ ((ID *)(icon->obj))->icon_id = 0;
+ }
+ else {
+ ((PreviewImage *)(icon->obj))->icon_id = 0;
+ }
+ icon_free(icon);
+ }
+}
diff --git a/source/blender/blenkernel/intern/idcode.c b/source/blender/blenkernel/intern/idcode.c
index 1b7a03ec80e..cf1eb8838e9 100644
--- a/source/blender/blenkernel/intern/idcode.c
+++ b/source/blender/blenkernel/intern/idcode.c
@@ -37,54 +37,58 @@
#include "BLI_utildefines.h"
+#include "BLT_translation.h"
+
#include "BKE_idcode.h"
typedef struct {
unsigned short code;
const char *name, *plural;
+
+ const char *i18n_context;
int flags;
#define IDTYPE_FLAGS_ISLINKABLE (1 << 0)
} IDType;
/* plural need to match rna_main.c's MainCollectionDef */
-/* WARNING! Keep it in sync with i18n contexts in BLF_translation.h */
+/* WARNING! Keep it in sync with i18n contexts in BLT_translation.h */
static IDType idtypes[] = {
- { ID_AC, "Action", "actions", IDTYPE_FLAGS_ISLINKABLE },
- { ID_AR, "Armature", "armatures", IDTYPE_FLAGS_ISLINKABLE },
- { ID_BR, "Brush", "brushes", IDTYPE_FLAGS_ISLINKABLE },
- { ID_CA, "Camera", "cameras", IDTYPE_FLAGS_ISLINKABLE },
- { ID_CU, "Curve", "curves", IDTYPE_FLAGS_ISLINKABLE },
- { ID_GD, "GPencil", "grease_pencil", IDTYPE_FLAGS_ISLINKABLE }, /* rename gpencil */
- { ID_GR, "Group", "groups", IDTYPE_FLAGS_ISLINKABLE },
- { ID_ID, "ID", "ids", 0 }, /* plural is fake */
- { ID_IM, "Image", "images", IDTYPE_FLAGS_ISLINKABLE },
- { ID_IP, "Ipo", "ipos", IDTYPE_FLAGS_ISLINKABLE }, /* deprecated */
- { ID_KE, "Key", "shape_keys", 0 },
- { ID_LA, "Lamp", "lamps", IDTYPE_FLAGS_ISLINKABLE },
- { ID_LI, "Library", "libraries", 0 },
- { ID_LS, "FreestyleLineStyle", "linestyles", IDTYPE_FLAGS_ISLINKABLE },
- { ID_LT, "Lattice", "lattices", IDTYPE_FLAGS_ISLINKABLE },
- { ID_MA, "Material", "materials", IDTYPE_FLAGS_ISLINKABLE },
- { ID_MB, "Metaball", "metaballs", IDTYPE_FLAGS_ISLINKABLE },
- { ID_MC, "MovieClip", "movieclips", IDTYPE_FLAGS_ISLINKABLE },
- { ID_ME, "Mesh", "meshes", IDTYPE_FLAGS_ISLINKABLE },
- { ID_MSK, "Mask", "masks", IDTYPE_FLAGS_ISLINKABLE },
- { ID_NT, "NodeTree", "node_groups", IDTYPE_FLAGS_ISLINKABLE },
- { ID_OB, "Object", "objects", IDTYPE_FLAGS_ISLINKABLE },
- { ID_PA, "ParticleSettings", "particles", 0 },
- { ID_PAL, "Palettes", "palettes", IDTYPE_FLAGS_ISLINKABLE },
- { ID_PC, "PaintCurve", "paint_curves", IDTYPE_FLAGS_ISLINKABLE },
- { ID_SCE, "Scene", "scenes", IDTYPE_FLAGS_ISLINKABLE },
- { ID_SCR, "Screen", "screens", 0 },
- { ID_SEQ, "Sequence", "sequences", 0 }, /* not actually ID data */
- { ID_SPK, "Speaker", "speakers", IDTYPE_FLAGS_ISLINKABLE },
- { ID_SO, "Sound", "sounds", IDTYPE_FLAGS_ISLINKABLE },
- { ID_TE, "Texture", "textures", IDTYPE_FLAGS_ISLINKABLE },
- { ID_TXT, "Text", "texts", IDTYPE_FLAGS_ISLINKABLE },
- { ID_VF, "VFont", "fonts", IDTYPE_FLAGS_ISLINKABLE },
- { ID_WO, "World", "worlds", IDTYPE_FLAGS_ISLINKABLE },
- { ID_WM, "WindowManager", "window_managers", 0 },
+ { ID_AC, "Action", "actions", BLT_I18NCONTEXT_ID_ACTION, IDTYPE_FLAGS_ISLINKABLE },
+ { ID_AR, "Armature", "armatures", BLT_I18NCONTEXT_ID_ARMATURE, IDTYPE_FLAGS_ISLINKABLE },
+ { ID_BR, "Brush", "brushes", BLT_I18NCONTEXT_ID_BRUSH, IDTYPE_FLAGS_ISLINKABLE },
+ { ID_CA, "Camera", "cameras", BLT_I18NCONTEXT_ID_CAMERA, IDTYPE_FLAGS_ISLINKABLE },
+ { ID_CU, "Curve", "curves", BLT_I18NCONTEXT_ID_CURVE, IDTYPE_FLAGS_ISLINKABLE },
+ { ID_GD, "GPencil", "grease_pencil", BLT_I18NCONTEXT_ID_GPENCIL, IDTYPE_FLAGS_ISLINKABLE }, /* rename gpencil */
+ { ID_GR, "Group", "groups", BLT_I18NCONTEXT_ID_GROUP, IDTYPE_FLAGS_ISLINKABLE },
+ { ID_ID, "ID", "ids", BLT_I18NCONTEXT_ID_ID, 0 }, /* plural is fake */
+ { ID_IM, "Image", "images", BLT_I18NCONTEXT_ID_IMAGE, IDTYPE_FLAGS_ISLINKABLE },
+ { ID_IP, "Ipo", "ipos", "", IDTYPE_FLAGS_ISLINKABLE }, /* deprecated */
+ { ID_KE, "Key", "shape_keys", BLT_I18NCONTEXT_ID_SHAPEKEY, 0 },
+ { ID_LA, "Lamp", "lamps", BLT_I18NCONTEXT_ID_LAMP, IDTYPE_FLAGS_ISLINKABLE },
+ { ID_LI, "Library", "libraries", BLT_I18NCONTEXT_ID_LIBRARY, 0 },
+ { ID_LS, "FreestyleLineStyle", "linestyles", BLT_I18NCONTEXT_ID_FREESTYLELINESTYLE, IDTYPE_FLAGS_ISLINKABLE },
+ { ID_LT, "Lattice", "lattices", BLT_I18NCONTEXT_ID_LATTICE, IDTYPE_FLAGS_ISLINKABLE },
+ { ID_MA, "Material", "materials", BLT_I18NCONTEXT_ID_MATERIAL, IDTYPE_FLAGS_ISLINKABLE },
+ { ID_MB, "Metaball", "metaballs", BLT_I18NCONTEXT_ID_METABALL, IDTYPE_FLAGS_ISLINKABLE },
+ { ID_MC, "MovieClip", "movieclips", BLT_I18NCONTEXT_ID_MOVIECLIP, IDTYPE_FLAGS_ISLINKABLE },
+ { ID_ME, "Mesh", "meshes", BLT_I18NCONTEXT_ID_MESH, IDTYPE_FLAGS_ISLINKABLE },
+ { ID_MSK, "Mask", "masks", BLT_I18NCONTEXT_ID_MASK, IDTYPE_FLAGS_ISLINKABLE },
+ { ID_NT, "NodeTree", "node_groups", BLT_I18NCONTEXT_ID_NODETREE, IDTYPE_FLAGS_ISLINKABLE },
+ { ID_OB, "Object", "objects", BLT_I18NCONTEXT_ID_OBJECT, IDTYPE_FLAGS_ISLINKABLE },
+ { ID_PA, "ParticleSettings", "particles", BLT_I18NCONTEXT_ID_PARTICLESETTINGS, IDTYPE_FLAGS_ISLINKABLE },
+ { ID_PAL, "Palettes", "palettes", BLT_I18NCONTEXT_ID_PALETTE, IDTYPE_FLAGS_ISLINKABLE },
+ { ID_PC, "PaintCurve", "paint_curves", BLT_I18NCONTEXT_ID_PAINTCURVE, IDTYPE_FLAGS_ISLINKABLE },
+ { ID_SCE, "Scene", "scenes", BLT_I18NCONTEXT_ID_SCENE, IDTYPE_FLAGS_ISLINKABLE },
+ { ID_SCR, "Screen", "screens", BLT_I18NCONTEXT_ID_SCREEN, 0 },
+ { ID_SEQ, "Sequence", "sequences", BLT_I18NCONTEXT_ID_SEQUENCE, 0 }, /* not actually ID data */
+ { ID_SPK, "Speaker", "speakers", BLT_I18NCONTEXT_ID_SPEAKER, IDTYPE_FLAGS_ISLINKABLE },
+ { ID_SO, "Sound", "sounds", BLT_I18NCONTEXT_ID_SOUND, IDTYPE_FLAGS_ISLINKABLE },
+ { ID_TE, "Texture", "textures", BLT_I18NCONTEXT_ID_TEXTURE, IDTYPE_FLAGS_ISLINKABLE },
+ { ID_TXT, "Text", "texts", BLT_I18NCONTEXT_ID_TEXT, IDTYPE_FLAGS_ISLINKABLE },
+ { ID_VF, "VFont", "fonts", BLT_I18NCONTEXT_ID_VFONT, IDTYPE_FLAGS_ISLINKABLE },
+ { ID_WO, "World", "worlds", BLT_I18NCONTEXT_ID_WORLD, IDTYPE_FLAGS_ISLINKABLE },
+ { ID_WM, "WindowManager", "window_managers", BLT_I18NCONTEXT_ID_WINDOWMANAGER, 0 },
};
static IDType *idtype_from_name(const char *str)
@@ -162,6 +166,92 @@ int BKE_idcode_from_name(const char *name)
}
/**
+ * Convert an idcode into an idfilter (e.g. ID_OB -> FILTER_ID_OB).
+ */
+int BKE_idcode_to_idfilter(const int idcode)
+{
+#define CASE_IDFILTER(_id) case ID_##_id: return FILTER_ID_##_id
+
+ switch (idcode) {
+ CASE_IDFILTER(AC);
+ CASE_IDFILTER(AR);
+ CASE_IDFILTER(BR);
+ CASE_IDFILTER(CA);
+ CASE_IDFILTER(CU);
+ CASE_IDFILTER(GD);
+ CASE_IDFILTER(GR);
+ CASE_IDFILTER(IM);
+ CASE_IDFILTER(LA);
+ CASE_IDFILTER(LS);
+ CASE_IDFILTER(LT);
+ CASE_IDFILTER(MA);
+ CASE_IDFILTER(MB);
+ CASE_IDFILTER(MC);
+ CASE_IDFILTER(ME);
+ CASE_IDFILTER(MSK);
+ CASE_IDFILTER(NT);
+ CASE_IDFILTER(OB);
+ CASE_IDFILTER(PA);
+ CASE_IDFILTER(PAL);
+ CASE_IDFILTER(PC);
+ CASE_IDFILTER(SCE);
+ CASE_IDFILTER(SPK);
+ CASE_IDFILTER(SO);
+ CASE_IDFILTER(TE);
+ CASE_IDFILTER(TXT);
+ CASE_IDFILTER(VF);
+ CASE_IDFILTER(WO);
+ default:
+ return 0;
+ }
+
+#undef CASE_IDFILTER
+}
+
+/**
+ * Convert an idfilter into an idcode (e.g. FILTER_ID_OB -> ID_OB).
+ */
+int BKE_idcode_from_idfilter(const int idfilter)
+{
+#define CASE_IDFILTER(_id) case FILTER_ID_##_id: return ID_##_id
+
+ switch (idfilter) {
+ CASE_IDFILTER(AC);
+ CASE_IDFILTER(AR);
+ CASE_IDFILTER(BR);
+ CASE_IDFILTER(CA);
+ CASE_IDFILTER(CU);
+ CASE_IDFILTER(GD);
+ CASE_IDFILTER(GR);
+ CASE_IDFILTER(IM);
+ CASE_IDFILTER(LA);
+ CASE_IDFILTER(LS);
+ CASE_IDFILTER(LT);
+ CASE_IDFILTER(MA);
+ CASE_IDFILTER(MB);
+ CASE_IDFILTER(MC);
+ CASE_IDFILTER(ME);
+ CASE_IDFILTER(MSK);
+ CASE_IDFILTER(NT);
+ CASE_IDFILTER(OB);
+ CASE_IDFILTER(PA);
+ CASE_IDFILTER(PAL);
+ CASE_IDFILTER(PC);
+ CASE_IDFILTER(SCE);
+ CASE_IDFILTER(SPK);
+ CASE_IDFILTER(SO);
+ CASE_IDFILTER(TE);
+ CASE_IDFILTER(TXT);
+ CASE_IDFILTER(VF);
+ CASE_IDFILTER(WO);
+ default:
+ return 0;
+ }
+
+#undef CASE_IDFILTER
+}
+
+/**
* Convert an idcode into a name (plural).
*
* \param code The code to convert.
@@ -176,6 +266,19 @@ const char *BKE_idcode_to_name_plural(int code)
}
/**
+ * Convert an idcode into its translations' context.
+ *
+ * \param code The code to convert.
+ * \return A static string representing the i18n context of the code.
+ */
+const char *BKE_idcode_to_translation_context(int code)
+{
+ IDType *idt = idtype_from_code(code);
+ BLI_assert(idt);
+ return idt ? idt->i18n_context : BLT_I18NCONTEXT_DEFAULT;
+}
+
+/**
* Return an ID code and steps the index forward 1.
*
* \param index start as 0.
diff --git a/source/blender/blenkernel/intern/idprop.c b/source/blender/blenkernel/intern/idprop.c
index 4dbd15a3774..4d83f8cf916 100644
--- a/source/blender/blenkernel/intern/idprop.c
+++ b/source/blender/blenkernel/intern/idprop.c
@@ -42,10 +42,18 @@
#include "MEM_guardedalloc.h"
+#include "BLI_strict_flags.h"
+
/* IDPropertyTemplate is a union in DNA_ID.h */
+/**
+ * if the new is 'IDP_ARRAY_REALLOC_LIMIT' items less,
+ * than #IDProperty.totallen, reallocate anyway.
+ */
+#define IDP_ARRAY_REALLOC_LIMIT 200
+
/*local size table.*/
-static char idp_size_table[] = {
+static size_t idp_size_table[] = {
1, /*strings*/
sizeof(int),
sizeof(float),
@@ -158,9 +166,8 @@ void IDP_ResizeIDPArray(IDProperty *prop, int newlen)
BLI_assert(prop->type == IDP_IDPARRAY);
/* first check if the array buffer size has room */
- /* if newlen is 200 items less then totallen, reallocate anyway */
if (newlen <= prop->totallen) {
- if (newlen < prop->len && prop->totallen - newlen < 200) {
+ if (newlen < prop->len && prop->totallen - newlen < IDP_ARRAY_REALLOC_LIMIT) {
int i;
for (i = newlen; i < prop->len; i++)
@@ -194,7 +201,7 @@ void IDP_ResizeIDPArray(IDProperty *prop, int newlen)
*/
newsize = newlen;
newsize = (newsize >> 3) + (newsize < 9 ? 3 : 6) + newsize;
- prop->data.pointer = MEM_recallocN(prop->data.pointer, sizeof(IDProperty) * newsize);
+ prop->data.pointer = MEM_recallocN(prop->data.pointer, sizeof(IDProperty) * (size_t)newsize);
prop->len = newlen;
prop->totallen = newsize;
}
@@ -235,8 +242,7 @@ void IDP_ResizeArray(IDProperty *prop, int newlen)
const bool is_grow = newlen >= prop->len;
/* first check if the array buffer size has room */
- /* if newlen is 200 chars less then totallen, reallocate anyway */
- if (newlen <= prop->totallen && prop->totallen - newlen < 200) {
+ if (newlen <= prop->totallen && prop->totallen - newlen < IDP_ARRAY_REALLOC_LIMIT) {
idp_resize_group_array(prop, newlen, prop->data.pointer);
prop->len = newlen;
return;
@@ -256,7 +262,8 @@ void IDP_ResizeArray(IDProperty *prop, int newlen)
if (is_grow == false)
idp_resize_group_array(prop, newlen, prop->data.pointer);
- prop->data.pointer = MEM_recallocN(prop->data.pointer, idp_size_table[(int)prop->subtype] * newsize);
+ prop->data.pointer = MEM_recallocN(
+ prop->data.pointer, idp_size_table[(int)prop->subtype] * (size_t)newsize);
if (is_grow == true)
idp_resize_group_array(prop, newlen, prop->data.pointer);
@@ -321,8 +328,8 @@ static IDProperty *IDP_CopyArray(const IDProperty *prop)
*
* \param st The string to assign.
* \param name The property name.
- * \param maxlen The size of the new string (including the \0 terminator)
- * \return
+ * \param maxlen The size of the new string (including the \0 terminator).
+ * \return The new string property.
*/
IDProperty *IDP_NewString(const char *st, const char *name, int maxlen)
{
@@ -336,14 +343,14 @@ IDProperty *IDP_NewString(const char *st, const char *name, int maxlen)
}
else {
/* include null terminator '\0' */
- int stlen = strlen(st) + 1;
+ int stlen = (int)strlen(st) + 1;
if (maxlen > 0 && maxlen < stlen)
stlen = maxlen;
- prop->data.pointer = MEM_mallocN(stlen, "id property string 2");
+ prop->data.pointer = MEM_mallocN((size_t)stlen, "id property string 2");
prop->len = prop->totallen = stlen;
- BLI_strncpy(prop->data.pointer, st, stlen);
+ BLI_strncpy(prop->data.pointer, st, (size_t)stlen);
}
prop->type = IDP_STRING;
@@ -374,18 +381,18 @@ void IDP_AssignString(IDProperty *prop, const char *st, int maxlen)
int stlen;
BLI_assert(prop->type == IDP_STRING);
- stlen = strlen(st);
+ stlen = (int)strlen(st);
if (maxlen > 0 && maxlen < stlen)
stlen = maxlen;
if (prop->subtype == IDP_STRING_SUB_BYTE) {
IDP_ResizeArray(prop, stlen);
- memcpy(prop->data.pointer, st, stlen);
+ memcpy(prop->data.pointer, st, (size_t)stlen);
}
else {
stlen++;
IDP_ResizeArray(prop, stlen);
- BLI_strncpy(prop->data.pointer, st, stlen);
+ BLI_strncpy(prop->data.pointer, st, (size_t)stlen);
}
}
@@ -395,7 +402,7 @@ void IDP_ConcatStringC(IDProperty *prop, const char *st)
BLI_assert(prop->type == IDP_STRING);
- newlen = prop->len + strlen(st);
+ newlen = prop->len + (int)strlen(st);
/* we have to remember that prop->len includes the null byte for strings.
* so there's no need to add +1 to the resize function.*/
IDP_ResizeArray(prop, newlen);
@@ -571,18 +578,18 @@ void IDP_ReplaceGroupInGroup(IDProperty *dest, const IDProperty *src)
* Checks if a property with the same name as prop exists, and if so replaces it.
* Use this to preserve order!
*/
-void IDP_ReplaceInGroup(IDProperty *group, IDProperty *prop)
+void IDP_ReplaceInGroup_ex(IDProperty *group, IDProperty *prop, IDProperty *prop_exist)
{
- IDProperty *loop;
-
BLI_assert(group->type == IDP_GROUP);
- if ((loop = IDP_GetPropertyFromGroup(group, prop->name))) {
- BLI_insertlinkafter(&group->data.group, loop, prop);
+ BLI_assert(prop_exist == IDP_GetPropertyFromGroup(group, prop->name));
+
+ if ((prop_exist = IDP_GetPropertyFromGroup(group, prop->name))) {
+ BLI_insertlinkafter(&group->data.group, prop_exist, prop);
- BLI_remlink(&group->data.group, loop);
- IDP_FreeProperty(loop);
- MEM_freeN(loop);
+ BLI_remlink(&group->data.group, prop_exist);
+ IDP_FreeProperty(prop_exist);
+ MEM_freeN(prop_exist);
}
else {
group->len++;
@@ -590,6 +597,13 @@ void IDP_ReplaceInGroup(IDProperty *group, IDProperty *prop)
}
}
+void IDP_ReplaceInGroup(IDProperty *group, IDProperty *prop)
+{
+ IDProperty *prop_exist = IDP_GetPropertyFromGroup(group, prop->name);
+
+ IDP_ReplaceInGroup_ex(group, prop, prop_exist);
+}
+
/**
* If a property is missing in \a dest, add it.
*/
@@ -623,8 +637,8 @@ void IDP_MergeGroup(IDProperty *dest, const IDProperty *src, const bool do_overw
*
* The sanity check just means the property is not added to the group if another property
* exists with the same name; the client code using ID properties then needs to detect this
- * (the function that adds new properties to groups, IDP_AddToGroup,returns 0 if a property can't
- * be added to the group, and 1 if it can) and free the property.
+ * (the function that adds new properties to groups, IDP_AddToGroup, returns false if a property can't
+ * be added to the group, and true if it can) and free the property.
*
* Currently the code to free ID properties is designed to leave the actual struct
* you pass it un-freed, this is needed for how the system works. This means
@@ -639,10 +653,10 @@ bool IDP_AddToGroup(IDProperty *group, IDProperty *prop)
if (IDP_GetPropertyFromGroup(group, prop->name) == NULL) {
group->len++;
BLI_addtail(&group->data.group, prop);
- return 1;
+ return true;
}
- return 0;
+ return false;
}
/**
@@ -656,10 +670,10 @@ bool IDP_InsertToGroup(IDProperty *group, IDProperty *previous, IDProperty *pnew
if (IDP_GetPropertyFromGroup(group, pnew->name) == NULL) {
group->len++;
BLI_insertlinkafter(&group->data.group, previous, pnew);
- return 1;
+ return true;
}
- return 0;
+ return false;
}
/**
@@ -700,56 +714,6 @@ IDProperty *IDP_GetPropertyTypeFromGroup(IDProperty *prop, const char *name, con
return (idprop && idprop->type == type) ? idprop : NULL;
}
-typedef struct IDPIter {
- void *next;
- IDProperty *parent;
-} IDPIter;
-
-/**
- * Get an iterator to iterate over the members of an id property group.
- * Note that this will automatically free the iterator once iteration is complete;
- * if you stop the iteration before hitting the end, make sure to call
- * IDP_FreeIterBeforeEnd().
- */
-void *IDP_GetGroupIterator(IDProperty *prop)
-{
- IDPIter *iter;
-
- BLI_assert(prop->type == IDP_GROUP);
- iter = MEM_mallocN(sizeof(IDPIter), "IDPIter");
- iter->next = prop->data.group.first;
- iter->parent = prop;
- return (void *) iter;
-}
-
-/**
- * Returns the next item in the iteration. To use, simple for a loop like the following:
- * while (IDP_GroupIterNext(iter) != NULL) {
- * ...
- * }
- */
-IDProperty *IDP_GroupIterNext(void *vself)
-{
- IDPIter *self = (IDPIter *) vself;
- Link *next = (Link *) self->next;
- if (self->next == NULL) {
- MEM_freeN(self);
- return NULL;
- }
-
- self->next = next->next;
- return (void *) next;
-}
-
-/**
- * Frees the iterator pointed to at vself, only use this if iteration is stopped early;
- * when the iterator hits the end of the list it'll automatically free itself.\
- */
-void IDP_FreeIterBeforeEnd(void *vself)
-{
- MEM_freeN(vself);
-}
-
/* Ok, the way things work, Groups free the ID Property structs of their children.
* This is because all ID Property freeing functions free only direct data (not the ID Property
* struct itself), but for Groups the child properties *are* considered
@@ -811,11 +775,11 @@ IDProperty *IDP_GetProperties(ID *id, const bool create_if_needed)
bool IDP_EqualsProperties_ex(IDProperty *prop1, IDProperty *prop2, const bool is_strict)
{
if (prop1 == NULL && prop2 == NULL)
- return 1;
+ return true;
else if (prop1 == NULL || prop2 == NULL)
- return is_strict ? 0 : 1;
+ return is_strict ? false : true;
else if (prop1->type != prop2->type)
- return 0;
+ return false;
switch (prop1->type) {
case IDP_INT:
@@ -838,27 +802,32 @@ bool IDP_EqualsProperties_ex(IDProperty *prop1, IDProperty *prop2, const bool is
case IDP_DOUBLE:
return (IDP_Double(prop1) == IDP_Double(prop2));
case IDP_STRING:
- return ((prop1->len == prop2->len) && strncmp(IDP_String(prop1), IDP_String(prop2), prop1->len) == 0);
+ {
+ return (((prop1->len == prop2->len) &&
+ STREQLEN(IDP_String(prop1), IDP_String(prop2), (size_t)prop1->len)));
+ }
case IDP_ARRAY:
if (prop1->len == prop2->len && prop1->subtype == prop2->subtype) {
- return memcmp(IDP_Array(prop1), IDP_Array(prop2), idp_size_table[(int)prop1->subtype] * prop1->len);
+ return (memcmp(IDP_Array(prop1),
+ IDP_Array(prop2),
+ idp_size_table[(int)prop1->subtype] * (size_t)prop1->len) == 0);
}
- return 0;
+ return false;
case IDP_GROUP:
{
IDProperty *link1, *link2;
if (is_strict && prop1->len != prop2->len)
- return 0;
+ return false;
for (link1 = prop1->data.group.first; link1; link1 = link1->next) {
link2 = IDP_GetPropertyFromGroup(prop2, link1->name);
if (!IDP_EqualsProperties_ex(link1, link2, is_strict))
- return 0;
+ return false;
}
- return 1;
+ return true;
}
case IDP_IDPARRAY:
{
@@ -867,12 +836,12 @@ bool IDP_EqualsProperties_ex(IDProperty *prop1, IDProperty *prop2, const bool is
int i;
if (prop1->len != prop2->len)
- return 0;
+ return false;
for (i = 0; i < prop1->len; i++)
if (!IDP_EqualsProperties(&array1[i], &array2[i]))
- return 0;
- return 1;
+ return false;
+ return true;
}
default:
/* should never get here */
@@ -880,7 +849,7 @@ bool IDP_EqualsProperties_ex(IDProperty *prop1, IDProperty *prop2, const bool is
break;
}
- return 1;
+ return true;
}
bool IDP_EqualsProperties(IDProperty *prop1, IDProperty *prop2)
@@ -913,7 +882,7 @@ bool IDP_EqualsProperties(IDProperty *prop1, IDProperty *prop2)
* IDP_AddToGroup or MEM_freeN the property, doing anything else might result in
* a memory leak.
*/
-IDProperty *IDP_New(const int type, const IDPropertyTemplate *val, const char *name)
+IDProperty *IDP_New(const char type, const IDPropertyTemplate *val, const char *name)
{
IDProperty *prop = NULL;
@@ -940,8 +909,10 @@ IDProperty *IDP_New(const int type, const IDPropertyTemplate *val, const char *n
{
prop = MEM_callocN(sizeof(IDProperty), "IDProperty array");
prop->subtype = val->array.type;
- if (val->array.len)
- prop->data.pointer = MEM_callocN(idp_size_table[val->array.type] * val->array.len, "id property array");
+ if (val->array.len) {
+ prop->data.pointer = MEM_callocN(
+ idp_size_table[val->array.type] * (size_t)val->array.len, "id property array");
+ }
prop->len = prop->totallen = val->array.len;
break;
}
@@ -961,9 +932,9 @@ IDProperty *IDP_New(const int type, const IDPropertyTemplate *val, const char *n
prop->len = 0;
}
else {
- prop->data.pointer = MEM_mallocN(val->string.len, "id property string 2");
+ prop->data.pointer = MEM_mallocN((size_t)val->string.len, "id property string 2");
prop->len = prop->totallen = val->string.len;
- memcpy(prop->data.pointer, st, val->string.len);
+ memcpy(prop->data.pointer, st, (size_t)val->string.len);
}
prop->subtype = IDP_STRING_SUB_BYTE;
}
@@ -975,10 +946,10 @@ IDProperty *IDP_New(const int type, const IDPropertyTemplate *val, const char *n
prop->len = 1; /*NULL string, has len of 1 to account for null byte.*/
}
else {
- int stlen = strlen(st) + 1;
- prop->data.pointer = MEM_mallocN(stlen, "id property string 3");
+ int stlen = (int)strlen(st) + 1;
+ prop->data.pointer = MEM_mallocN((size_t)stlen, "id property string 3");
prop->len = prop->totallen = stlen;
- memcpy(prop->data.pointer, st, stlen);
+ memcpy(prop->data.pointer, st, (size_t)stlen);
}
prop->subtype = IDP_STRING_SUB_UTF8;
}
diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c
index b57d0143b9b..4a76c704130 100644
--- a/source/blender/blenkernel/intern/image.c
+++ b/source/blender/blenkernel/intern/image.c
@@ -56,12 +56,12 @@
#include "DNA_object_types.h"
#include "DNA_camera_types.h"
#include "DNA_sequence_types.h"
-#include "DNA_userdef_types.h"
#include "DNA_brush_types.h"
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
#include "BLI_blenlib.h"
+#include "BLI_math_vector.h"
#include "BLI_threads.h"
#include "BLI_timecode.h" /* for stamp timecode format */
#include "BLI_utildefines.h"
@@ -74,6 +74,7 @@
#include "BKE_library.h"
#include "BKE_main.h"
#include "BKE_packedFile.h"
+#include "BKE_report.h"
#include "BKE_scene.h"
#include "BKE_node.h"
#include "BKE_sequencer.h" /* seq_foreground_frame_get() */
@@ -98,6 +99,12 @@
static SpinLock image_spin;
+/* prototypes */
+static size_t image_num_files(struct Image *ima);
+static ImBuf *image_acquire_ibuf(Image *ima, ImageUser *iuser, void **r_lock);
+static void image_update_views_format(Image *ima, ImageUser *iuser);
+static void image_add_view(Image *ima, const char *viewname, const char *filepath);
+
/* max int, to indicate we don't store sequences in ibuf */
#define IMA_NO_INDEX 0x7FEFEFEF
@@ -116,21 +123,21 @@ typedef struct ImageCacheKey {
static unsigned int imagecache_hashhash(const void *key_v)
{
- const ImageCacheKey *key = (ImageCacheKey *) key_v;
+ const ImageCacheKey *key = key_v;
return key->index;
}
static bool imagecache_hashcmp(const void *a_v, const void *b_v)
{
- const ImageCacheKey *a = (ImageCacheKey *) a_v;
- const ImageCacheKey *b = (ImageCacheKey *) b_v;
+ const ImageCacheKey *a = a_v;
+ const ImageCacheKey *b = b_v;
return (a->index != b->index);
}
static void imagecache_keydata(void *userkey, int *framenr, int *proxy, int *render_flags)
{
- ImageCacheKey *key = (ImageCacheKey *)userkey;
+ ImageCacheKey *key = userkey;
*framenr = IMA_INDEX_FRAME(key->index);
*proxy = IMB_PROXY_NONE;
@@ -248,7 +255,7 @@ void BKE_image_de_interlace(Image *ima, int odd)
/* ***************** ALLOC & FREE, DATA MANAGING *************** */
-static void image_free_cahced_frames(Image *image)
+static void image_free_cached_frames(Image *image)
{
if (image->cache) {
IMB_moviecache_free(image->cache);
@@ -256,23 +263,68 @@ static void image_free_cahced_frames(Image *image)
}
}
+static void image_free_packedfiles(Image *ima)
+{
+ while (ima->packedfiles.last) {
+ ImagePackedFile *imapf = ima->packedfiles.last;
+ if (imapf->packedfile) {
+ freePackedFile(imapf->packedfile);
+ }
+ BLI_remlink(&ima->packedfiles, imapf);
+ MEM_freeN(imapf);
+ }
+}
+
+void BKE_image_free_packedfiles(Image *ima)
+{
+ image_free_packedfiles(ima);
+}
+
+static void image_free_views(Image *ima)
+{
+ BLI_freelistN(&ima->views);
+}
+
+void BKE_image_free_views(Image *image)
+{
+ image_free_views(image);
+}
+
+static void image_free_anims(Image *ima)
+{
+ while (ima->anims.last) {
+ ImageAnim *ia = ima->anims.last;
+ if (ia->anim) {
+ IMB_free_anim(ia->anim);
+ ia->anim = NULL;
+ }
+ BLI_remlink(&ima->anims, ia);
+ MEM_freeN(ia);
+ }
+}
+
/**
* Simply free the image data from memory,
* on display the image can load again (except for render buffers).
*/
void BKE_image_free_buffers(Image *ima)
{
- image_free_cahced_frames(ima);
+ image_free_cached_frames(ima);
- if (ima->anim) IMB_free_anim(ima->anim);
- ima->anim = NULL;
+ image_free_anims(ima);
if (ima->rr) {
RE_FreeRenderResult(ima->rr);
ima->rr = NULL;
}
- GPU_free_image(ima);
+ if (!G.background) {
+ /* Background mode doesn't use opnegl,
+ * so we can avoid freeing GPU images and save some
+ * time by skipping mutex lock.
+ */
+ GPU_free_image(ima);
+ }
ima->ok = IMA_OK;
}
@@ -283,11 +335,10 @@ void BKE_image_free(Image *ima)
int a;
BKE_image_free_buffers(ima);
- if (ima->packedfile) {
- freePackedFile(ima->packedfile);
- ima->packedfile = NULL;
- }
- BKE_icon_delete(&ima->id);
+
+ image_free_packedfiles(ima);
+
+ BKE_icon_id_delete(&ima->id);
ima->id.icon_id = 0;
BKE_previewimg_free(&ima->preview);
@@ -298,6 +349,9 @@ void BKE_image_free(Image *ima)
ima->renders[a] = NULL;
}
}
+
+ image_free_views(ima);
+ MEM_freeN(ima->stereo3d_format);
}
/* only image block itself */
@@ -321,7 +375,9 @@ static Image *image_alloc(Main *bmain, const char *name, short source, short typ
ima->flag |= IMA_VIEW_AS_RENDER;
BKE_color_managed_colorspace_settings_init(&ima->colorspace_settings);
+ ima->stereo3d_format = MEM_callocN(sizeof(Stereo3dFormat), "Image Stereo Format");
}
+
return ima;
}
@@ -352,6 +408,22 @@ static void image_assign_ibuf(Image *ima, ImBuf *ibuf, int index, int frame)
}
}
+static void copy_image_packedfiles(ListBase *lb_dst, const ListBase *lb_src)
+{
+ const ImagePackedFile *imapf_src;
+
+ BLI_listbase_clear(lb_dst);
+ for (imapf_src = lb_src->first; imapf_src; imapf_src = imapf_src->next) {
+ ImagePackedFile *imapf_dst = MEM_mallocN(sizeof(ImagePackedFile), "Image Packed Files (copy)");
+ BLI_strncpy(imapf_dst->filepath, imapf_src->filepath, sizeof(imapf_dst->filepath));
+
+ if (imapf_src->packedfile)
+ imapf_dst->packedfile = dupPackedFile(imapf_src->packedfile);
+
+ BLI_addtail(lb_dst, imapf_dst);
+ }
+}
+
/* empty image block, of similar type and filename */
Image *BKE_image_copy(Main *bmain, Image *ima)
{
@@ -365,6 +437,7 @@ Image *BKE_image_copy(Main *bmain, Image *ima)
nima->gen_x = ima->gen_x;
nima->gen_y = ima->gen_y;
nima->gen_type = ima->gen_type;
+ copy_v4_v4(nima->gen_color, ima->gen_color);
nima->animspeed = ima->animspeed;
@@ -373,8 +446,14 @@ Image *BKE_image_copy(Main *bmain, Image *ima)
BKE_color_managed_colorspace_settings_copy(&nima->colorspace_settings, &ima->colorspace_settings);
- if (ima->packedfile)
- nima->packedfile = dupPackedFile(ima->packedfile);
+ copy_image_packedfiles(&nima->packedfiles, &ima->packedfiles);
+
+ nima->stereo3d_format = MEM_dupallocN(ima->stereo3d_format);
+ BLI_duplicatelist(&nima->views, &ima->views);
+
+ if (ima->id.lib) {
+ BKE_id_lib_local_paths(bmain, ima->id.lib, &nima->id);
+ }
return nima;
}
@@ -659,7 +738,7 @@ Image *BKE_image_load(Main *bmain, const char *filepath)
/* otherwise creates new. */
/* does not load ibuf itself */
/* pass on optional frame for #name images */
-Image *BKE_image_load_exists(const char *filepath)
+Image *BKE_image_load_exists_ex(const char *filepath, bool *r_exists)
{
Image *ima;
char str[FILE_MAX], strtest[FILE_MAX];
@@ -674,21 +753,30 @@ Image *BKE_image_load_exists(const char *filepath)
BLI_path_abs(strtest, ID_BLEND_PATH(G.main, &ima->id));
if (BLI_path_cmp(strtest, str) == 0) {
- if (ima->anim == NULL || ima->id.us == 0) {
- BLI_strncpy(ima->name, filepath, sizeof(ima->name)); /* for stringcode */
- ima->id.us++; /* officially should not, it doesn't link here! */
+ if ((BKE_image_has_anim(ima) == false) ||
+ (ima->id.us == 0))
+ {
+ ima->id.us++; /* officially should not, it doesn't link here! */
if (ima->ok == 0)
ima->ok = IMA_OK;
- /* RETURN! */
+ if (r_exists)
+ *r_exists = true;
return ima;
}
}
}
}
+ if (r_exists)
+ *r_exists = false;
return BKE_image_load(G.main, filepath);
}
+Image *BKE_image_load_exists(const char *filepath)
+{
+ return BKE_image_load_exists_ex(filepath, NULL);
+}
+
static ImBuf *add_ibuf_size(unsigned int width, unsigned int height, const char *name, int depth, int floatbuf, short gen_type,
const float color[4], ColorManagedColorspaceSettings *colorspace_settings)
{
@@ -755,13 +843,14 @@ static ImBuf *add_ibuf_size(unsigned int width, unsigned int height, const char
}
/* adds new image block, creates ImBuf and initializes color */
-Image *BKE_image_add_generated(Main *bmain, unsigned int width, unsigned int height, const char *name, int depth, int floatbuf, short gen_type, const float color[4])
+Image *BKE_image_add_generated(Main *bmain, unsigned int width, unsigned int height, const char *name, int depth, int floatbuf, short gen_type, const float color[4], const bool stereo3d)
{
/* on save, type is changed to FILE in editsima.c */
Image *ima = image_alloc(bmain, name, IMA_SRC_GENERATED, IMA_TYPE_UV_TEST);
if (ima) {
- ImBuf *ibuf;
+ size_t view_id;
+ const char *names[2] = {STEREO_LEFT_NAME, STEREO_RIGHT_NAME};
/* BLI_strncpy(ima->name, name, FILE_MAX); */ /* don't do this, this writes in ain invalid filepath! */
ima->gen_x = width;
@@ -769,26 +858,41 @@ Image *BKE_image_add_generated(Main *bmain, unsigned int width, unsigned int hei
ima->gen_type = gen_type;
ima->gen_flag |= (floatbuf ? IMA_GEN_FLOAT : 0);
ima->gen_depth = depth;
+ copy_v4_v4(ima->gen_color, color);
- ibuf = add_ibuf_size(width, height, ima->name, depth, floatbuf, gen_type, color, &ima->colorspace_settings);
- image_assign_ibuf(ima, ibuf, IMA_NO_INDEX, 0);
+ for (view_id = 0; view_id < 2; view_id++) {
+ ImBuf *ibuf;
+ ibuf = add_ibuf_size(width, height, ima->name, depth, floatbuf, gen_type, color, &ima->colorspace_settings);
+ image_assign_ibuf(ima, ibuf, stereo3d ? view_id : IMA_NO_INDEX, 0);
- /* image_assign_ibuf puts buffer to the cache, which increments user counter. */
- IMB_freeImBuf(ibuf);
+ /* image_assign_ibuf puts buffer to the cache, which increments user counter. */
+ IMB_freeImBuf(ibuf);
+ if (!stereo3d) break;
+
+ image_add_view(ima, names[view_id], "");
+ }
ima->ok = IMA_OK_LOADED;
+ if (stereo3d)
+ ima->flag |= IMA_IS_STEREO | IMA_IS_MULTIVIEW;
}
return ima;
}
-/* creates an image image owns the imbuf passed */
-Image *BKE_image_add_from_imbuf(ImBuf *ibuf)
+/* Create an image image from ibuf. The refcount of ibuf is increased,
+ * caller should take care to drop its reference by calling
+ * IMB_freeImBuf if needed. */
+Image *BKE_image_add_from_imbuf(ImBuf *ibuf, const char *name)
{
/* on save, type is changed to FILE in editsima.c */
Image *ima;
- ima = image_alloc(G.main, BLI_path_basename(ibuf->name), IMA_SRC_FILE, IMA_TYPE_IMAGE);
+ if (name == NULL) {
+ name = BLI_path_basename(ibuf->name);
+ }
+
+ ima = image_alloc(G.main, name, IMA_SRC_FILE, IMA_TYPE_IMAGE);
if (ima) {
BLI_strncpy(ima->name, ibuf->name, FILE_MAX);
@@ -799,19 +903,80 @@ Image *BKE_image_add_from_imbuf(ImBuf *ibuf)
return ima;
}
+/* packs rects from memory as PNG
+ * convert multiview images to R_IMF_VIEWS_INDIVIDUAL
+ */
+static void image_memorypack_multiview(Image *ima)
+{
+ ImageView *iv;
+ size_t i;
+
+ image_free_packedfiles(ima);
+
+ for (i = 0, iv = ima->views.first; iv; iv = iv->next, i++) {
+ ImBuf *ibuf = image_get_cached_ibuf_for_index_frame(ima, i, 0);
+
+ ibuf->ftype = IMB_FTYPE_PNG;
+ ibuf->planes = R_IMF_PLANES_RGBA;
+
+ /* if the image was a R_IMF_VIEWS_STEREO_3D we force _L, _R suffices */
+ if (ima->views_format == R_IMF_VIEWS_STEREO_3D) {
+ const char *suffix[2] = {STEREO_LEFT_SUFFIX, STEREO_RIGHT_SUFFIX};
+ BLI_path_suffix(iv->filepath, FILE_MAX, suffix[i], "");
+ }
+
+ IMB_saveiff(ibuf, iv->filepath, IB_rect | IB_mem);
+
+ if (ibuf->encodedbuffer == NULL) {
+ printf("memory save for pack error\n");
+ IMB_freeImBuf(ibuf);
+ image_free_packedfiles(ima);
+ return;
+ }
+ else {
+ ImagePackedFile *imapf;
+ PackedFile *pf = MEM_callocN(sizeof(*pf), "PackedFile");
+
+ pf->data = ibuf->encodedbuffer;
+ pf->size = ibuf->encodedsize;
+
+ imapf = MEM_mallocN(sizeof(ImagePackedFile), "Image PackedFile");
+ BLI_strncpy(imapf->filepath, iv->filepath, sizeof(imapf->filepath));
+ imapf->packedfile = pf;
+ BLI_addtail(&ima->packedfiles, imapf);
+
+ ibuf->encodedbuffer = NULL;
+ ibuf->encodedsize = 0;
+ ibuf->userflags &= ~IB_BITMAPDIRTY;
+ }
+ IMB_freeImBuf(ibuf);
+ }
+
+ if (ima->source == IMA_SRC_GENERATED) {
+ ima->source = IMA_SRC_FILE;
+ ima->type = IMA_TYPE_IMAGE;
+ }
+ ima->views_format = R_IMF_VIEWS_INDIVIDUAL;
+}
+
/* packs rect from memory as PNG */
void BKE_image_memorypack(Image *ima)
{
- ImBuf *ibuf = image_get_cached_ibuf_for_index_frame(ima, IMA_NO_INDEX, 0);
+ ImBuf *ibuf;
- if (ibuf == NULL)
+ if ((ima->flag & IMA_IS_MULTIVIEW)) {
+ image_memorypack_multiview(ima);
return;
- if (ima->packedfile) {
- freePackedFile(ima->packedfile);
- ima->packedfile = NULL;
}
- ibuf->ftype = PNG;
+ ibuf = image_get_cached_ibuf_for_index_frame(ima, IMA_NO_INDEX, 0);
+
+ if (ibuf == NULL)
+ return;
+
+ image_free_packedfiles(ima);
+
+ ibuf->ftype = IMB_FTYPE_PNG;
ibuf->planes = R_IMF_PLANES_RGBA;
IMB_saveiff(ibuf, ibuf->name, IB_rect | IB_mem);
@@ -819,11 +984,17 @@ void BKE_image_memorypack(Image *ima)
printf("memory save for pack error\n");
}
else {
+ ImagePackedFile *imapf;
PackedFile *pf = MEM_callocN(sizeof(*pf), "PackedFile");
pf->data = ibuf->encodedbuffer;
pf->size = ibuf->encodedsize;
- ima->packedfile = pf;
+
+ imapf = MEM_mallocN(sizeof(ImagePackedFile), "Image PackedFile");
+ BLI_strncpy(imapf->filepath, ima->name, sizeof(imapf->filepath));
+ imapf->packedfile = pf;
+ BLI_addtail(&ima->packedfiles, imapf);
+
ibuf->encodedbuffer = NULL;
ibuf->encodedsize = 0;
ibuf->userflags &= ~IB_BITMAPDIRTY;
@@ -837,16 +1008,63 @@ void BKE_image_memorypack(Image *ima)
IMB_freeImBuf(ibuf);
}
+void BKE_image_packfiles(ReportList *reports, Image *ima, const char *basepath)
+{
+ const size_t totfiles = image_num_files(ima);
+
+ if (totfiles == 1) {
+ ImagePackedFile *imapf = MEM_mallocN(sizeof(ImagePackedFile), "Image packed file");
+ BLI_addtail(&ima->packedfiles, imapf);
+ imapf->packedfile = newPackedFile(reports, ima->name, basepath);
+ if (imapf->packedfile) {
+ BLI_strncpy(imapf->filepath, ima->name, sizeof(imapf->filepath));
+ }
+ else {
+ BLI_freelinkN(&ima->packedfiles, imapf);
+ }
+ }
+ else {
+ ImageView *iv;
+ for (iv = ima->views.first; iv; iv = iv->next) {
+ ImagePackedFile *imapf = MEM_mallocN(sizeof(ImagePackedFile), "Image packed file");
+ BLI_addtail(&ima->packedfiles, imapf);
+
+ imapf->packedfile = newPackedFile(reports, iv->filepath, basepath);
+ if (imapf->packedfile) {
+ BLI_strncpy(imapf->filepath, iv->filepath, sizeof(imapf->filepath));
+ }
+ else {
+ BLI_freelinkN(&ima->packedfiles, imapf);
+ }
+ }
+ }
+}
+
+void BKE_image_packfiles_from_mem(ReportList *reports, Image *ima, char *data, const size_t data_len)
+{
+ const size_t totfiles = image_num_files(ima);
+
+ if (totfiles != 1) {
+ BKE_report(reports, RPT_ERROR, "Cannot pack multiview images from raw data currently...");
+ }
+ else {
+ ImagePackedFile *imapf = MEM_mallocN(sizeof(ImagePackedFile), __func__);
+ BLI_addtail(&ima->packedfiles, imapf);
+ imapf->packedfile = newPackedFileMemory(data, data_len);
+ BLI_strncpy(imapf->filepath, ima->name, sizeof(imapf->filepath));
+ }
+}
+
void BKE_image_tag_time(Image *ima)
{
- ima->lastused = (int)PIL_check_seconds_timer();
+ ima->lastused = PIL_check_seconds_timer_i();
}
#if 0
static void tag_all_images_time()
{
Image *ima;
- int ctime = (int)PIL_check_seconds_timer();
+ int ctime = PIL_check_seconds_timer_i();
ima = G.main->image.first;
while (ima) {
@@ -881,7 +1099,7 @@ static uintptr_t image_mem_size(Image *image)
size += MEM_allocN_len(ibuf->rect_float);
}
- for (level = 0; level < IB_MIPMAP_LEVELS; level++) {
+ for (level = 0; level < IMB_MIPMAP_LEVELS; level++) {
ibufm = ibuf->mipmap[level];
if (ibufm) {
if (ibufm->rect) {
@@ -990,82 +1208,92 @@ void BKE_image_all_free_anim_ibufs(int cfra)
/* *********** READ AND WRITE ************** */
-int BKE_imtype_to_ftype(const char imtype)
+int BKE_image_imtype_to_ftype(const char imtype, ImbFormatOptions *r_options)
{
+ memset(r_options, 0, sizeof(*r_options));
+
if (imtype == R_IMF_IMTYPE_TARGA)
- return TGA;
- else if (imtype == R_IMF_IMTYPE_RAWTGA)
- return RAWTGA;
+ return IMB_FTYPE_TGA;
+ else if (imtype == R_IMF_IMTYPE_RAWTGA) {
+ r_options->flag = RAWTGA;
+ return IMB_FTYPE_TGA;
+ }
else if (imtype == R_IMF_IMTYPE_IRIS)
- return IMAGIC;
+ return IMB_FTYPE_IMAGIC;
#ifdef WITH_HDR
else if (imtype == R_IMF_IMTYPE_RADHDR)
- return RADHDR;
+ return IMB_FTYPE_RADHDR;
#endif
- else if (imtype == R_IMF_IMTYPE_PNG)
- return PNG | 15;
+ else if (imtype == R_IMF_IMTYPE_PNG) {
+ r_options->quality = 15;
+ return IMB_FTYPE_PNG;
+ }
#ifdef WITH_DDS
else if (imtype == R_IMF_IMTYPE_DDS)
- return DDS;
+ return IMB_FTYPE_DDS;
#endif
else if (imtype == R_IMF_IMTYPE_BMP)
- return BMP;
+ return IMB_FTYPE_BMP;
#ifdef WITH_TIFF
else if (imtype == R_IMF_IMTYPE_TIFF)
- return TIF;
+ return IMB_FTYPE_TIF;
#endif
else if (imtype == R_IMF_IMTYPE_OPENEXR || imtype == R_IMF_IMTYPE_MULTILAYER)
- return OPENEXR;
+ return IMB_FTYPE_OPENEXR;
#ifdef WITH_CINEON
else if (imtype == R_IMF_IMTYPE_CINEON)
- return CINEON;
+ return IMB_FTYPE_CINEON;
else if (imtype == R_IMF_IMTYPE_DPX)
- return DPX;
+ return IMB_FTYPE_DPX;
#endif
#ifdef WITH_OPENJPEG
else if (imtype == R_IMF_IMTYPE_JP2)
- return JP2;
+ return IMB_FTYPE_JP2;
#endif
- else
- return JPG | 90;
+ else {
+ r_options->quality = 90;
+ return IMB_FTYPE_JPG;
+ }
}
-char BKE_ftype_to_imtype(const int ftype)
+char BKE_image_ftype_to_imtype(const int ftype, const ImbFormatOptions *options)
{
if (ftype == 0)
return R_IMF_IMTYPE_TARGA;
- else if (ftype == IMAGIC)
+ else if (ftype == IMB_FTYPE_IMAGIC)
return R_IMF_IMTYPE_IRIS;
#ifdef WITH_HDR
- else if (ftype & RADHDR)
+ else if (ftype == IMB_FTYPE_RADHDR)
return R_IMF_IMTYPE_RADHDR;
#endif
- else if (ftype & PNG)
+ else if (ftype == IMB_FTYPE_PNG)
return R_IMF_IMTYPE_PNG;
#ifdef WITH_DDS
- else if (ftype & DDS)
+ else if (ftype == IMB_FTYPE_DDS)
return R_IMF_IMTYPE_DDS;
#endif
- else if (ftype & BMP)
+ else if (ftype == IMB_FTYPE_BMP)
return R_IMF_IMTYPE_BMP;
#ifdef WITH_TIFF
- else if (ftype & TIF)
+ else if (ftype == IMB_FTYPE_TIF)
return R_IMF_IMTYPE_TIFF;
#endif
- else if (ftype & OPENEXR)
+ else if (ftype == IMB_FTYPE_OPENEXR)
return R_IMF_IMTYPE_OPENEXR;
#ifdef WITH_CINEON
- else if (ftype & CINEON)
+ else if (ftype == IMB_FTYPE_CINEON)
return R_IMF_IMTYPE_CINEON;
- else if (ftype & DPX)
+ else if (ftype == IMB_FTYPE_DPX)
return R_IMF_IMTYPE_DPX;
#endif
- else if (ftype & TGA)
- return R_IMF_IMTYPE_TARGA;
- else if (ftype & RAWTGA)
- return R_IMF_IMTYPE_RAWTGA;
+ else if (ftype == IMB_FTYPE_TGA) {
+ if (options && (options->flag & RAWTGA))
+ return R_IMF_IMTYPE_RAWTGA;
+ else
+ return R_IMF_IMTYPE_TARGA;
+ }
#ifdef WITH_OPENJPEG
- else if (ftype & JP2)
+ else if (ftype == IMB_FTYPE_JP2)
return R_IMF_IMTYPE_JP2;
#endif
else
@@ -1181,7 +1409,7 @@ char BKE_imtype_valid_depths(const char imtype)
case R_IMF_IMTYPE_OPENEXR:
return R_IMF_CHAN_DEPTH_16 | R_IMF_CHAN_DEPTH_32;
case R_IMF_IMTYPE_MULTILAYER:
- return R_IMF_CHAN_DEPTH_32;
+ return R_IMF_CHAN_DEPTH_16 | R_IMF_CHAN_DEPTH_32;
/* eeh, cineon does some strange 10bits per channel */
case R_IMF_IMTYPE_DPX:
return R_IMF_CHAN_DEPTH_8 | R_IMF_CHAN_DEPTH_10 | R_IMF_CHAN_DEPTH_12 | R_IMF_CHAN_DEPTH_16;
@@ -1202,37 +1430,37 @@ char BKE_imtype_valid_depths(const char imtype)
* creator.c help info */
char BKE_imtype_from_arg(const char *imtype_arg)
{
- if (!strcmp(imtype_arg, "TGA")) return R_IMF_IMTYPE_TARGA;
- else if (!strcmp(imtype_arg, "IRIS")) return R_IMF_IMTYPE_IRIS;
+ if (STREQ(imtype_arg, "TGA")) return R_IMF_IMTYPE_TARGA;
+ else if (STREQ(imtype_arg, "IRIS")) return R_IMF_IMTYPE_IRIS;
#ifdef WITH_DDS
- else if (!strcmp(imtype_arg, "DDS")) return R_IMF_IMTYPE_DDS;
+ else if (STREQ(imtype_arg, "DDS")) return R_IMF_IMTYPE_DDS;
#endif
- else if (!strcmp(imtype_arg, "JPEG")) return R_IMF_IMTYPE_JPEG90;
- else if (!strcmp(imtype_arg, "IRIZ")) return R_IMF_IMTYPE_IRIZ;
- else if (!strcmp(imtype_arg, "RAWTGA")) return R_IMF_IMTYPE_RAWTGA;
- else if (!strcmp(imtype_arg, "AVIRAW")) return R_IMF_IMTYPE_AVIRAW;
- else if (!strcmp(imtype_arg, "AVIJPEG")) return R_IMF_IMTYPE_AVIJPEG;
- else if (!strcmp(imtype_arg, "PNG")) return R_IMF_IMTYPE_PNG;
- else if (!strcmp(imtype_arg, "QUICKTIME")) return R_IMF_IMTYPE_QUICKTIME;
- else if (!strcmp(imtype_arg, "BMP")) return R_IMF_IMTYPE_BMP;
+ else if (STREQ(imtype_arg, "JPEG")) return R_IMF_IMTYPE_JPEG90;
+ else if (STREQ(imtype_arg, "IRIZ")) return R_IMF_IMTYPE_IRIZ;
+ else if (STREQ(imtype_arg, "RAWTGA")) return R_IMF_IMTYPE_RAWTGA;
+ else if (STREQ(imtype_arg, "AVIRAW")) return R_IMF_IMTYPE_AVIRAW;
+ else if (STREQ(imtype_arg, "AVIJPEG")) return R_IMF_IMTYPE_AVIJPEG;
+ else if (STREQ(imtype_arg, "PNG")) return R_IMF_IMTYPE_PNG;
+ else if (STREQ(imtype_arg, "QUICKTIME")) return R_IMF_IMTYPE_QUICKTIME;
+ else if (STREQ(imtype_arg, "BMP")) return R_IMF_IMTYPE_BMP;
#ifdef WITH_HDR
- else if (!strcmp(imtype_arg, "HDR")) return R_IMF_IMTYPE_RADHDR;
+ else if (STREQ(imtype_arg, "HDR")) return R_IMF_IMTYPE_RADHDR;
#endif
#ifdef WITH_TIFF
- else if (!strcmp(imtype_arg, "TIFF")) return R_IMF_IMTYPE_TIFF;
+ else if (STREQ(imtype_arg, "TIFF")) return R_IMF_IMTYPE_TIFF;
#endif
#ifdef WITH_OPENEXR
- else if (!strcmp(imtype_arg, "EXR")) return R_IMF_IMTYPE_OPENEXR;
- else if (!strcmp(imtype_arg, "MULTILAYER")) return R_IMF_IMTYPE_MULTILAYER;
+ else if (STREQ(imtype_arg, "EXR")) return R_IMF_IMTYPE_OPENEXR;
+ else if (STREQ(imtype_arg, "MULTILAYER")) return R_IMF_IMTYPE_MULTILAYER;
#endif
- else if (!strcmp(imtype_arg, "MPEG")) return R_IMF_IMTYPE_FFMPEG;
- else if (!strcmp(imtype_arg, "FRAMESERVER")) return R_IMF_IMTYPE_FRAMESERVER;
+ else if (STREQ(imtype_arg, "MPEG")) return R_IMF_IMTYPE_FFMPEG;
+ else if (STREQ(imtype_arg, "FRAMESERVER")) return R_IMF_IMTYPE_FRAMESERVER;
#ifdef WITH_CINEON
- else if (!strcmp(imtype_arg, "CINEON")) return R_IMF_IMTYPE_CINEON;
- else if (!strcmp(imtype_arg, "DPX")) return R_IMF_IMTYPE_DPX;
+ else if (STREQ(imtype_arg, "CINEON")) return R_IMF_IMTYPE_CINEON;
+ else if (STREQ(imtype_arg, "DPX")) return R_IMF_IMTYPE_DPX;
#endif
#ifdef WITH_OPENJPEG
- else if (!strcmp(imtype_arg, "JP2")) return R_IMF_IMTYPE_JP2;
+ else if (STREQ(imtype_arg, "JP2")) return R_IMF_IMTYPE_JP2;
#endif
else return R_IMF_IMTYPE_INVALID;
}
@@ -1289,7 +1517,7 @@ static bool do_add_image_extension(char *string, const char imtype, const ImageF
}
#endif
#ifdef WITH_OPENEXR
- else if (ELEM(imtype, R_IMF_IMTYPE_OPENEXR, R_IMF_IMTYPE_MULTILAYER)) {
+ else if (imtype == R_IMF_IMTYPE_OPENEXR || imtype == R_IMF_IMTYPE_MULTILAYER) {
if (!BLI_testextensie(string, extension_test = ".exr"))
extension = extension_test;
}
@@ -1347,12 +1575,12 @@ static bool do_add_image_extension(char *string, const char imtype, const ImageF
}
}
-int BKE_add_image_extension(char *string, const ImageFormatData *im_format)
+int BKE_image_path_ensure_ext_from_imformat(char *string, const ImageFormatData *im_format)
{
return do_add_image_extension(string, im_format->imtype, im_format);
}
-int BKE_add_image_extension_from_type(char *string, const char imtype)
+int BKE_image_path_ensure_ext_from_imtype(char *string, const char imtype)
{
return do_add_image_extension(string, imtype, NULL);
}
@@ -1372,38 +1600,41 @@ void BKE_imformat_defaults(ImageFormatData *im_format)
void BKE_imbuf_to_image_format(struct ImageFormatData *im_format, const ImBuf *imbuf)
{
- int ftype = imbuf->ftype & ~IB_CUSTOM_FLAGS_MASK;
- int custom_flags = imbuf->ftype & IB_CUSTOM_FLAGS_MASK;
+ int ftype = imbuf->ftype;
+ int custom_flags = imbuf->foptions.flag;
+ char quality = imbuf->foptions.quality;
BKE_imformat_defaults(im_format);
/* file type */
- if (ftype == IMAGIC)
+ if (ftype == IMB_FTYPE_IMAGIC)
im_format->imtype = R_IMF_IMTYPE_IRIS;
#ifdef WITH_HDR
- else if (ftype == RADHDR)
+ else if (ftype == IMB_FTYPE_RADHDR)
im_format->imtype = R_IMF_IMTYPE_RADHDR;
#endif
- else if (ftype == PNG) {
+ else if (ftype == IMB_FTYPE_PNG) {
im_format->imtype = R_IMF_IMTYPE_PNG;
if (custom_flags & PNG_16BIT)
im_format->depth = R_IMF_CHAN_DEPTH_16;
+
+ im_format->compress = quality;
}
#ifdef WITH_DDS
- else if (ftype == DDS)
+ else if (ftype == IMB_FTYPE_DDS)
im_format->imtype = R_IMF_IMTYPE_DDS;
#endif
- else if (ftype == BMP)
+ else if (ftype == IMB_FTYPE_BMP)
im_format->imtype = R_IMF_IMTYPE_BMP;
#ifdef WITH_TIFF
- else if (ftype == TIF) {
+ else if (ftype == IMB_FTYPE_TIF) {
im_format->imtype = R_IMF_IMTYPE_TIFF;
if (custom_flags & TIF_16BIT)
im_format->depth = R_IMF_CHAN_DEPTH_16;
@@ -1411,7 +1642,7 @@ void BKE_imbuf_to_image_format(struct ImageFormatData *im_format, const ImBuf *i
#endif
#ifdef WITH_OPENEXR
- else if (ftype == OPENEXR) {
+ else if (ftype == IMB_FTYPE_OPENEXR) {
im_format->imtype = R_IMF_IMTYPE_OPENEXR;
if (custom_flags & OPENEXR_HALF)
im_format->depth = R_IMF_CHAN_DEPTH_16;
@@ -1423,41 +1654,40 @@ void BKE_imbuf_to_image_format(struct ImageFormatData *im_format, const ImBuf *i
#endif
#ifdef WITH_CINEON
- else if (ftype == CINEON)
+ else if (ftype == IMB_FTYPE_CINEON)
im_format->imtype = R_IMF_IMTYPE_CINEON;
- else if (ftype == DPX)
+ else if (ftype == IMB_FTYPE_DPX)
im_format->imtype = R_IMF_IMTYPE_DPX;
#endif
- else if (ftype == TGA) {
- im_format->imtype = R_IMF_IMTYPE_TARGA;
- }
- else if (ftype == RAWTGA) {
- im_format->imtype = R_IMF_IMTYPE_RAWTGA;
+ else if (ftype == IMB_FTYPE_TGA) {
+ if (custom_flags & RAWTGA)
+ im_format->imtype = R_IMF_IMTYPE_RAWTGA;
+ else
+ im_format->imtype = R_IMF_IMTYPE_TARGA;
}
-
#ifdef WITH_OPENJPEG
- else if (ftype & JP2) {
+ else if (ftype == IMB_FTYPE_JP2) {
im_format->imtype = R_IMF_IMTYPE_JP2;
- im_format->quality = custom_flags & ~JPG_MSK;
+ im_format->quality = quality;
- if (ftype & JP2_16BIT)
+ if (custom_flags & JP2_16BIT)
im_format->depth = R_IMF_CHAN_DEPTH_16;
- else if (ftype & JP2_12BIT)
+ else if (custom_flags & JP2_12BIT)
im_format->depth = R_IMF_CHAN_DEPTH_12;
- if (ftype & JP2_YCC)
+ if (custom_flags & JP2_YCC)
im_format->jp2_flag |= R_IMF_JP2_FLAG_YCC;
- if (ftype & JP2_CINE) {
+ if (custom_flags & JP2_CINE) {
im_format->jp2_flag |= R_IMF_JP2_FLAG_CINE_PRESET;
- if (ftype & JP2_CINE_48FPS)
+ if (custom_flags & JP2_CINE_48FPS)
im_format->jp2_flag |= R_IMF_JP2_FLAG_CINE_48;
}
- if (ftype & JP2_JP2)
+ if (custom_flags & JP2_JP2)
im_format->jp2_codec = R_IMF_JP2_CODEC_JP2;
- else if (ftype & JP2_J2K)
+ else if (custom_flags & JP2_J2K)
im_format->jp2_codec = R_IMF_JP2_CODEC_J2K;
else
BLI_assert(!"Unsupported jp2 codec was specified in file type");
@@ -1466,7 +1696,7 @@ void BKE_imbuf_to_image_format(struct ImageFormatData *im_format, const ImBuf *i
else {
im_format->imtype = R_IMF_IMTYPE_JPEG90;
- im_format->quality = custom_flags & ~JPG_MSK;
+ im_format->quality = quality;
}
/* planes */
@@ -1620,7 +1850,7 @@ static void stampdata(Scene *scene, Object *camera, StampData *stamp_data, int d
RenderStats *stats = re ? RE_GetStats(re) : NULL;
if (stats && (scene->r.stamp & R_STAMP_RENDERTIME)) {
- BLI_timestr(stats->lastframetime, text, sizeof(text));
+ BLI_timecode_string_from_time_simple(text, sizeof(text), stats->lastframetime);
BLI_snprintf(stamp_data->rendertime, sizeof(stamp_data->rendertime), do_prefix ? "RenderTime %s" : "%s", text);
}
@@ -1630,7 +1860,9 @@ static void stampdata(Scene *scene, Object *camera, StampData *stamp_data, int d
}
}
-void BKE_stamp_buf(Scene *scene, Object *camera, unsigned char *rect, float *rectf, int width, int height, int channels)
+void BKE_image_stamp_buf(
+ Scene *scene, Object *camera,
+ unsigned char *rect, float *rectf, int width, int height, int channels)
{
struct StampData stamp_data;
float w, h, pad;
@@ -1640,12 +1872,23 @@ void BKE_stamp_buf(Scene *scene, Object *camera, unsigned char *rect, float *rec
struct ColorManagedDisplay *display;
const char *display_device;
+ /* vars for calculating wordwrap */
+ struct {
+ struct ResultBLF info;
+ rctf rect;
+ } wrap;
+
/* 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)))))
+ /* must enable BLF_WORD_WRAP before using */
+#define TEXT_SIZE_CHECK_WORD_WRAP(str, w, h) \
+ ((str[0]) && (BLF_boundbox_ex(mono, str, sizeof(str), &wrap.rect, &wrap.info), \
+ (void)(h = h_fixed * wrap.info.lines), (w = BLI_rctf_size_x(&wrap.rect))))
+
#define BUFF_MARGIN_X 2
#define BUFF_MARGIN_Y 1
@@ -1663,6 +1906,7 @@ void BKE_stamp_buf(Scene *scene, Object *camera, unsigned char *rect, float *rec
/* set before return */
BLF_size(mono, scene->r.stamp_font_id, 72);
+ BLF_wordwrap(mono, width - (BUFF_MARGIN_X * 2));
BLF_buffer(mono, rectf, rect, width, height, channels, display);
BLF_buffer_col(mono, scene->r.fg_stamp[0], scene->r.fg_stamp[1], scene->r.fg_stamp[2], 1.0);
@@ -1685,14 +1929,14 @@ void BKE_stamp_buf(Scene *scene, Object *camera, unsigned char *rect, float *rec
/* and draw the text. */
BLF_position(mono, x, y + y_ofs, 0.0);
- BLF_draw_buffer(mono, stamp_data.file);
+ BLF_draw_buffer(mono, stamp_data.file, BLF_DRAW_STR_DUMMY_MAX);
/* the extra pixel for background. */
y -= BUFF_MARGIN_Y * 2;
}
/* Top left corner, below File */
- if (TEXT_SIZE_CHECK(stamp_data.note, w, h)) {
+ if (TEXT_SIZE_CHECK(stamp_data.date, w, h)) {
y -= h;
/* and space for background. */
@@ -1700,14 +1944,14 @@ void BKE_stamp_buf(Scene *scene, Object *camera, unsigned char *rect, float *rec
0, y - BUFF_MARGIN_Y, w + BUFF_MARGIN_X, y + h + BUFF_MARGIN_Y);
BLF_position(mono, x, y + y_ofs, 0.0);
- BLF_draw_buffer(mono, stamp_data.note);
+ BLF_draw_buffer(mono, stamp_data.date, BLF_DRAW_STR_DUMMY_MAX);
/* the extra pixel for background. */
y -= BUFF_MARGIN_Y * 2;
}
- /* Top left corner, below File (or Note) */
- if (TEXT_SIZE_CHECK(stamp_data.date, w, h)) {
+ /* Top left corner, below File, Date */
+ if (TEXT_SIZE_CHECK(stamp_data.rendertime, w, h)) {
y -= h;
/* and space for background. */
@@ -1715,23 +1959,25 @@ void BKE_stamp_buf(Scene *scene, Object *camera, unsigned char *rect, float *rec
0, y - BUFF_MARGIN_Y, w + BUFF_MARGIN_X, y + h + BUFF_MARGIN_Y);
BLF_position(mono, x, y + y_ofs, 0.0);
- BLF_draw_buffer(mono, stamp_data.date);
+ BLF_draw_buffer(mono, stamp_data.rendertime, BLF_DRAW_STR_DUMMY_MAX);
/* the extra pixel for background. */
y -= BUFF_MARGIN_Y * 2;
}
- /* Top left corner, below File, Date or Note */
- if (TEXT_SIZE_CHECK(stamp_data.rendertime, w, h)) {
+ /* Top left corner, below File, Date, Rendertime */
+ BLF_enable(mono, BLF_WORD_WRAP);
+ if (TEXT_SIZE_CHECK_WORD_WRAP(stamp_data.note, w, h)) {
y -= h;
/* and space for background. */
buf_rectfill_area(rect, rectf, width, height, scene->r.bg_stamp, display,
0, y - BUFF_MARGIN_Y, w + BUFF_MARGIN_X, y + h + BUFF_MARGIN_Y);
- BLF_position(mono, x, y + y_ofs, 0.0);
- BLF_draw_buffer(mono, stamp_data.rendertime);
+ BLF_position(mono, x, y + y_ofs + (h - h_fixed), 0.0);
+ BLF_draw_buffer(mono, stamp_data.note, BLF_DRAW_STR_DUMMY_MAX);
}
+ BLF_disable(mono, BLF_WORD_WRAP);
x = 0;
y = 0;
@@ -1745,7 +1991,7 @@ void BKE_stamp_buf(Scene *scene, Object *camera, unsigned char *rect, float *rec
/* and pad the text. */
BLF_position(mono, x, y + y_ofs, 0.0);
- BLF_draw_buffer(mono, stamp_data.marker);
+ BLF_draw_buffer(mono, stamp_data.marker, BLF_DRAW_STR_DUMMY_MAX);
/* space width. */
x += w + pad;
@@ -1760,7 +2006,7 @@ void BKE_stamp_buf(Scene *scene, Object *camera, unsigned char *rect, float *rec
/* and pad the text. */
BLF_position(mono, x, y + y_ofs, 0.0);
- BLF_draw_buffer(mono, stamp_data.time);
+ BLF_draw_buffer(mono, stamp_data.time, BLF_DRAW_STR_DUMMY_MAX);
/* space width. */
x += w + pad;
@@ -1774,7 +2020,7 @@ void BKE_stamp_buf(Scene *scene, Object *camera, unsigned char *rect, float *rec
/* and pad the text. */
BLF_position(mono, x, y + y_ofs, 0.0);
- BLF_draw_buffer(mono, stamp_data.frame);
+ BLF_draw_buffer(mono, stamp_data.frame, BLF_DRAW_STR_DUMMY_MAX);
/* space width. */
x += w + pad;
@@ -1786,7 +2032,7 @@ void BKE_stamp_buf(Scene *scene, Object *camera, unsigned char *rect, float *rec
buf_rectfill_area(rect, rectf, width, height, scene->r.bg_stamp, display,
x - BUFF_MARGIN_X, y - BUFF_MARGIN_Y, x + w + BUFF_MARGIN_X, y + h + BUFF_MARGIN_Y);
BLF_position(mono, x, y + y_ofs, 0.0);
- BLF_draw_buffer(mono, stamp_data.camera);
+ BLF_draw_buffer(mono, stamp_data.camera, BLF_DRAW_STR_DUMMY_MAX);
/* space width. */
x += w + pad;
@@ -1798,7 +2044,7 @@ void BKE_stamp_buf(Scene *scene, Object *camera, unsigned char *rect, float *rec
buf_rectfill_area(rect, rectf, width, height, scene->r.bg_stamp, display,
x - BUFF_MARGIN_X, y - BUFF_MARGIN_Y, x + w + BUFF_MARGIN_X, y + h + BUFF_MARGIN_Y);
BLF_position(mono, x, y + y_ofs, 0.0);
- BLF_draw_buffer(mono, stamp_data.cameralens);
+ BLF_draw_buffer(mono, stamp_data.cameralens, BLF_DRAW_STR_DUMMY_MAX);
}
if (TEXT_SIZE_CHECK(stamp_data.scene, w, h)) {
@@ -1812,7 +2058,7 @@ void BKE_stamp_buf(Scene *scene, Object *camera, unsigned char *rect, float *rec
/* and pad the text. */
BLF_position(mono, x, y + y_ofs, 0.0);
- BLF_draw_buffer(mono, stamp_data.scene);
+ BLF_draw_buffer(mono, stamp_data.scene, BLF_DRAW_STR_DUMMY_MAX);
}
if (TEXT_SIZE_CHECK(stamp_data.strip, w, h)) {
@@ -1826,37 +2072,90 @@ void BKE_stamp_buf(Scene *scene, Object *camera, unsigned char *rect, float *rec
x - BUFF_MARGIN_X, y - BUFF_MARGIN_Y, x + w + BUFF_MARGIN_X, y + h + BUFF_MARGIN_Y);
BLF_position(mono, x, y + y_ofs, 0.0);
- BLF_draw_buffer(mono, stamp_data.strip);
+ BLF_draw_buffer(mono, stamp_data.strip, BLF_DRAW_STR_DUMMY_MAX);
}
/* cleanup the buffer. */
BLF_buffer(mono, NULL, NULL, 0, 0, 0, NULL);
+ BLF_wordwrap(mono, 0);
#undef TEXT_SIZE_CHECK
+#undef TEXT_SIZE_CHECK_WORD_WRAP
#undef BUFF_MARGIN_X
#undef BUFF_MARGIN_Y
}
-void BKE_imbuf_stamp_info(Scene *scene, Object *camera, struct ImBuf *ibuf)
+void BKE_render_result_stamp_info(Scene *scene, Object *camera, struct RenderResult *rr, bool allocate_only)
{
- struct StampData stamp_data;
+ struct StampData *stamp_data;
- if (!ibuf) return;
+ if (!(scene && (scene->r.stamp & R_STAMP_ALL)) && !allocate_only)
+ return;
- /* fill all the data values, no prefix */
- stampdata(scene, camera, &stamp_data, 0);
+ if (!rr->stamp_data) {
+ stamp_data = MEM_callocN(sizeof(StampData), "RenderResult.stamp_data");
+ }
+ else {
+ stamp_data = rr->stamp_data;
+ }
+
+ if (!allocate_only)
+ stampdata(scene, camera, stamp_data, 0);
+
+ if (!rr->stamp_data) {
+ rr->stamp_data = stamp_data;
+ }
+}
+
+void BKE_stamp_info_callback(void *data, struct StampData *stamp_data, StampCallback callback, bool noskip)
+{
+ if (!callback || !stamp_data) {
+ return;
+ }
- if (stamp_data.file[0]) IMB_metadata_change_field(ibuf, "File", stamp_data.file);
- if (stamp_data.note[0]) IMB_metadata_change_field(ibuf, "Note", stamp_data.note);
- if (stamp_data.date[0]) IMB_metadata_change_field(ibuf, "Date", stamp_data.date);
- if (stamp_data.marker[0]) IMB_metadata_change_field(ibuf, "Marker", stamp_data.marker);
- if (stamp_data.time[0]) IMB_metadata_change_field(ibuf, "Time", stamp_data.time);
- if (stamp_data.frame[0]) IMB_metadata_change_field(ibuf, "Frame", stamp_data.frame);
- if (stamp_data.camera[0]) IMB_metadata_change_field(ibuf, "Camera", stamp_data.camera);
- if (stamp_data.cameralens[0]) IMB_metadata_change_field(ibuf, "Lens", stamp_data.cameralens);
- if (stamp_data.scene[0]) IMB_metadata_change_field(ibuf, "Scene", stamp_data.scene);
- if (stamp_data.strip[0]) IMB_metadata_change_field(ibuf, "Strip", stamp_data.strip);
- if (stamp_data.rendertime[0]) IMB_metadata_change_field(ibuf, "RenderTime", stamp_data.rendertime);
+#define CALL(member, value_str) \
+ if (noskip || stamp_data->member[0]) { \
+ callback(data, value_str, stamp_data->member, sizeof(stamp_data->member)); \
+ } ((void)0)
+
+ CALL(file, "File");
+ CALL(note, "Note");
+ CALL(date, "Date");
+ CALL(marker, "Marker");
+ CALL(time, "Time");
+ CALL(frame, "Frame");
+ CALL(camera, "Camera");
+ CALL(cameralens, "Lens");
+ CALL(scene, "Scene");
+ CALL(strip, "Strip");
+ CALL(rendertime, "RenderTime");
+
+#undef CALL
+}
+
+/* wrap for callback only */
+static void metadata_change_field(void *data, const char *propname, char *propvalue, int UNUSED(len))
+{
+ IMB_metadata_change_field(data, propname, propvalue);
+}
+
+static void metadata_get_field(void *data, const char *propname, char *propvalue, int len)
+{
+ IMB_metadata_get_field(data, propname, propvalue, len);
+}
+
+void BKE_imbuf_stamp_info(RenderResult *rr, struct ImBuf *ibuf)
+{
+ struct StampData *stamp_data = rr->stamp_data;
+
+ BKE_stamp_info_callback(ibuf, stamp_data, metadata_change_field, false);
+}
+
+void BKE_stamp_info_from_imbuf(RenderResult *rr, struct ImBuf *ibuf)
+{
+ struct StampData *stamp_data = rr->stamp_data;
+
+ BKE_stamp_info_callback(ibuf, stamp_data, metadata_get_field, true);
}
bool BKE_imbuf_alpha_test(ImBuf *ibuf)
@@ -1884,55 +2183,53 @@ bool BKE_imbuf_alpha_test(ImBuf *ibuf)
/* note: imf->planes is ignored here, its assumed the image channels
* are already set */
-int BKE_imbuf_write(ImBuf *ibuf, const char *name, ImageFormatData *imf)
+void BKE_imbuf_write_prepare(ImBuf *ibuf, ImageFormatData *imf)
{
char imtype = imf->imtype;
char compress = imf->compress;
char quality = imf->quality;
- int ok;
-
if (imtype == R_IMF_IMTYPE_IRIS) {
- ibuf->ftype = IMAGIC;
+ ibuf->ftype = IMB_FTYPE_IMAGIC;
}
#ifdef WITH_HDR
else if (imtype == R_IMF_IMTYPE_RADHDR) {
- ibuf->ftype = RADHDR;
+ ibuf->ftype = IMB_FTYPE_RADHDR;
}
#endif
else if (ELEM(imtype, R_IMF_IMTYPE_PNG, R_IMF_IMTYPE_FFMPEG, R_IMF_IMTYPE_H264, R_IMF_IMTYPE_THEORA, R_IMF_IMTYPE_XVID)) {
- ibuf->ftype = PNG;
+ ibuf->ftype = IMB_FTYPE_PNG;
if (imtype == R_IMF_IMTYPE_PNG) {
if (imf->depth == R_IMF_CHAN_DEPTH_16)
- ibuf->ftype |= PNG_16BIT;
+ ibuf->foptions.flag |= PNG_16BIT;
- ibuf->ftype |= compress;
+ ibuf->foptions.quality = compress;
}
}
#ifdef WITH_DDS
else if (imtype == R_IMF_IMTYPE_DDS) {
- ibuf->ftype = DDS;
+ ibuf->ftype = IMB_FTYPE_DDS;
}
#endif
else if (imtype == R_IMF_IMTYPE_BMP) {
- ibuf->ftype = BMP;
+ ibuf->ftype = IMB_FTYPE_BMP;
}
#ifdef WITH_TIFF
else if (imtype == R_IMF_IMTYPE_TIFF) {
- ibuf->ftype = TIF;
+ ibuf->ftype = IMB_FTYPE_TIF;
if (imf->depth == R_IMF_CHAN_DEPTH_16)
- ibuf->ftype |= TIF_16BIT;
+ ibuf->foptions.flag |= TIF_16BIT;
}
#endif
#ifdef WITH_OPENEXR
- else if (imtype == R_IMF_IMTYPE_OPENEXR || imtype == R_IMF_IMTYPE_MULTILAYER) {
- ibuf->ftype = OPENEXR;
+ else if (ELEM(imtype, R_IMF_IMTYPE_OPENEXR, R_IMF_IMTYPE_MULTILAYER)) {
+ ibuf->ftype = IMB_FTYPE_OPENEXR;
if (imf->depth == R_IMF_CHAN_DEPTH_16)
- ibuf->ftype |= OPENEXR_HALF;
- ibuf->ftype |= (imf->exr_codec & OPENEXR_COMPRESS);
+ ibuf->foptions.flag |= OPENEXR_HALF;
+ ibuf->foptions.flag |= (imf->exr_codec & OPENEXR_COMPRESS);
if (!(imf->flag & R_IMF_FLAG_ZBUF))
ibuf->zbuf_float = NULL; /* signal for exr saving */
@@ -1941,68 +2238,70 @@ int BKE_imbuf_write(ImBuf *ibuf, const char *name, ImageFormatData *imf)
#endif
#ifdef WITH_CINEON
else if (imtype == R_IMF_IMTYPE_CINEON) {
- ibuf->ftype = CINEON;
+ ibuf->ftype = IMB_FTYPE_CINEON;
if (imf->cineon_flag & R_IMF_CINEON_FLAG_LOG) {
- ibuf->ftype |= CINEON_LOG;
+ ibuf->foptions.flag |= CINEON_LOG;
}
if (imf->depth == R_IMF_CHAN_DEPTH_16) {
- ibuf->ftype |= CINEON_16BIT;
+ ibuf->foptions.flag |= CINEON_16BIT;
}
else if (imf->depth == R_IMF_CHAN_DEPTH_12) {
- ibuf->ftype |= CINEON_12BIT;
+ ibuf->foptions.flag |= CINEON_12BIT;
}
else if (imf->depth == R_IMF_CHAN_DEPTH_10) {
- ibuf->ftype |= CINEON_10BIT;
+ ibuf->foptions.flag |= CINEON_10BIT;
}
}
else if (imtype == R_IMF_IMTYPE_DPX) {
- ibuf->ftype = DPX;
+ ibuf->ftype = IMB_FTYPE_DPX;
if (imf->cineon_flag & R_IMF_CINEON_FLAG_LOG) {
- ibuf->ftype |= CINEON_LOG;
+ ibuf->foptions.flag |= CINEON_LOG;
}
if (imf->depth == R_IMF_CHAN_DEPTH_16) {
- ibuf->ftype |= CINEON_16BIT;
+ ibuf->foptions.flag |= CINEON_16BIT;
}
else if (imf->depth == R_IMF_CHAN_DEPTH_12) {
- ibuf->ftype |= CINEON_12BIT;
+ ibuf->foptions.flag |= CINEON_12BIT;
}
else if (imf->depth == R_IMF_CHAN_DEPTH_10) {
- ibuf->ftype |= CINEON_10BIT;
+ ibuf->foptions.flag |= CINEON_10BIT;
}
}
#endif
else if (imtype == R_IMF_IMTYPE_TARGA) {
- ibuf->ftype = TGA;
+ ibuf->ftype = IMB_FTYPE_TGA;
}
else if (imtype == R_IMF_IMTYPE_RAWTGA) {
- ibuf->ftype = RAWTGA;
+ ibuf->ftype = IMB_FTYPE_TGA;
+ ibuf->foptions.flag = RAWTGA;
}
#ifdef WITH_OPENJPEG
else if (imtype == R_IMF_IMTYPE_JP2) {
if (quality < 10) quality = 90;
- ibuf->ftype = JP2 | quality;
+ ibuf->ftype = IMB_FTYPE_JP2;
+ ibuf->foptions.quality = quality;
if (imf->depth == R_IMF_CHAN_DEPTH_16) {
- ibuf->ftype |= JP2_16BIT;
+ ibuf->foptions.flag |= JP2_16BIT;
}
else if (imf->depth == R_IMF_CHAN_DEPTH_12) {
- ibuf->ftype |= JP2_12BIT;
+ ibuf->foptions.flag |= JP2_12BIT;
}
if (imf->jp2_flag & R_IMF_JP2_FLAG_YCC) {
- ibuf->ftype |= JP2_YCC;
+ ibuf->foptions.flag |= JP2_YCC;
}
if (imf->jp2_flag & R_IMF_JP2_FLAG_CINE_PRESET) {
- ibuf->ftype |= JP2_CINE;
+ ibuf->foptions.flag |= JP2_CINE;
if (imf->jp2_flag & R_IMF_JP2_FLAG_CINE_48)
- ibuf->ftype |= JP2_CINE_48FPS;
+ ibuf->foptions.flag |= JP2_CINE_48FPS;
}
if (imf->jp2_codec == R_IMF_JP2_CODEC_JP2)
- ibuf->ftype |= JP2_JP2;
+ ibuf->foptions.flag |= JP2_JP2;
else if (imf->jp2_codec == R_IMF_JP2_CODEC_J2K)
- ibuf->ftype |= JP2_J2K;
+ ibuf->foptions.flag |= JP2_J2K;
else
BLI_assert(!"Unsupported jp2 codec was specified in im_format->jp2_codec");
}
@@ -2010,8 +2309,16 @@ int BKE_imbuf_write(ImBuf *ibuf, const char *name, ImageFormatData *imf)
else {
/* R_IMF_IMTYPE_JPEG90, etc. default we save jpegs */
if (quality < 10) quality = 90;
- ibuf->ftype = JPG | quality;
+ ibuf->ftype = IMB_FTYPE_JPG;
+ ibuf->foptions.quality = quality;
}
+}
+
+int BKE_imbuf_write(ImBuf *ibuf, const char *name, ImageFormatData *imf)
+{
+ int ok;
+
+ BKE_imbuf_write_prepare(ibuf, imf);
BLI_make_existing_file(name);
@@ -2046,17 +2353,18 @@ int BKE_imbuf_write_as(ImBuf *ibuf, const char *name, ImageFormatData *imf,
return ok;
}
-int BKE_imbuf_write_stamp(Scene *scene, struct Object *camera, ImBuf *ibuf, const char *name, struct ImageFormatData *imf)
+int BKE_imbuf_write_stamp(Scene *scene, struct RenderResult *rr, ImBuf *ibuf, const char *name, struct ImageFormatData *imf)
{
if (scene && scene->r.stamp & R_STAMP_ALL)
- BKE_imbuf_stamp_info(scene, camera, ibuf);
+ BKE_imbuf_stamp_info(rr, ibuf);
return BKE_imbuf_write(ibuf, name, imf);
}
-
-static void do_makepicstring(char *string, const char *base, const char *relbase, int frame, const char imtype,
- const ImageFormatData *im_format, const short use_ext, const short use_frames)
+static void do_makepicstring(
+ char *string, const char *base, const char *relbase, int frame, const char imtype,
+ const ImageFormatData *im_format, const short use_ext, const short use_frames,
+ const char *suffix)
{
if (string == NULL) return;
BLI_strncpy(string, base, FILE_MAX - 10); /* weak assumption */
@@ -2065,20 +2373,33 @@ static void do_makepicstring(char *string, const char *base, const char *relbase
if (use_frames)
BLI_path_frame(string, frame, 4);
+ if (suffix)
+ BLI_path_suffix(string, FILE_MAX, suffix, "");
+
if (use_ext)
do_add_image_extension(string, imtype, im_format);
}
-void BKE_makepicstring(char *string, const char *base, const char *relbase, int frame,
- const ImageFormatData *im_format, const bool use_ext, const bool use_frames)
+void BKE_image_path_from_imformat(
+ char *string, const char *base, const char *relbase, int frame,
+ const ImageFormatData *im_format, const bool use_ext, const bool use_frames, const char *suffix)
{
- do_makepicstring(string, base, relbase, frame, im_format->imtype, im_format, use_ext, use_frames);
+ do_makepicstring(string, base, relbase, frame, im_format->imtype, im_format, use_ext, use_frames, suffix);
}
-void BKE_makepicstring_from_type(char *string, const char *base, const char *relbase, int frame,
- const char imtype, const bool use_ext, const bool use_frames)
+void BKE_image_path_from_imtype(
+ char *string, const char *base, const char *relbase, int frame,
+ const char imtype, const bool use_ext, const bool use_frames, const char *view)
{
- do_makepicstring(string, base, relbase, frame, imtype, NULL, use_ext, use_frames);
+ do_makepicstring(string, base, relbase, frame, imtype, NULL, use_ext, use_frames, view);
+}
+
+struct anim *openanim_noload(const char *name, int flags, int streamindex, char colorspace[IMA_MAX_SPACE])
+{
+ struct anim *anim;
+
+ anim = IMB_open_anim(name, flags, streamindex, colorspace);
+ return anim;
}
/* used by sequencer too */
@@ -2146,9 +2467,69 @@ Image *BKE_image_verify_viewer(int type, const char *name)
return ima;
}
-void BKE_image_assign_ibuf(Image *ima, ImBuf *ibuf)
+static void image_viewer_create_views(const RenderData *rd, Image *ima)
+{
+ if ((rd->scemode & R_MULTIVIEW) == 0) {
+ image_add_view(ima, "", "");
+ }
+ else {
+ SceneRenderView *srv;
+ for (srv = rd->views.first; srv; srv = srv->next) {
+ if (BKE_scene_multiview_is_render_view_active(rd, srv) == false)
+ continue;
+ image_add_view(ima, srv->name, "");
+ }
+ }
+}
+
+/* Reset the image cache and views when the Viewer Nodes views don't match the scene views */
+void BKE_image_verify_viewer_views(const RenderData *rd, Image *ima, ImageUser *iuser)
{
- image_assign_ibuf(ima, ibuf, IMA_NO_INDEX, 0);
+ bool do_reset;
+ const bool is_multiview = (rd->scemode & R_MULTIVIEW) != 0;
+
+ BLI_lock_thread(LOCK_DRAW_IMAGE);
+
+ if (BKE_scene_multiview_is_stereo3d(rd)) {
+ ima->flag |= IMA_IS_STEREO;
+ ima->flag |= IMA_IS_MULTIVIEW;
+ }
+ else {
+ ima->flag &= ~IMA_IS_STEREO;
+ ima->flag &= ~IMA_IS_MULTIVIEW;
+ iuser->flag &= ~IMA_SHOW_STEREO;
+ }
+
+ /* see if all scene render views are in the image view list */
+ do_reset = (BKE_scene_multiview_num_views_get(rd) != BLI_listbase_count(&ima->views));
+
+ /* multiview also needs to be sure all the views are synced */
+ if (is_multiview && !do_reset) {
+ SceneRenderView *srv;
+ ImageView *iv;
+
+ for (iv = ima->views.first; iv; iv = iv->next) {
+ srv = BLI_findstring(&rd->views, iv->name, offsetof(SceneRenderView, name));
+ if ((srv == NULL) || (BKE_scene_multiview_is_render_view_active(rd, srv) == false)) {
+ do_reset = true;
+ break;
+ }
+ }
+ }
+
+ if (do_reset) {
+ BLI_spin_lock(&image_spin);
+
+ image_free_cached_frames(ima);
+ BKE_image_free_views(ima);
+
+ /* add new views */
+ image_viewer_create_views(rd, ima);
+
+ BLI_spin_unlock(&image_spin);
+ }
+
+ BLI_unlock_thread(LOCK_DRAW_IMAGE);
}
void BKE_image_walk_all_users(const Main *mainp, void *customdata,
@@ -2208,6 +2589,22 @@ static void image_tag_frame_recalc(Image *ima, ImageUser *iuser, void *customdat
}
}
+static void image_init_imageuser(Image *ima, ImageUser *iuser)
+{
+ RenderResult *rr = ima->rr;
+
+ iuser->multi_index = 0;
+ iuser->layer = iuser->pass = iuser->view = 0;
+
+ if (rr)
+ BKE_image_multilayer_index(rr, iuser);
+}
+
+void BKE_image_init_imageuser(Image *ima, ImageUser *iuser)
+{
+ image_init_imageuser(ima, iuser);
+}
+
void BKE_image_signal(Image *ima, ImageUser *iuser, int signal)
{
if (ima == NULL)
@@ -2218,8 +2615,13 @@ void BKE_image_signal(Image *ima, ImageUser *iuser, int signal)
switch (signal) {
case IMA_SIGNAL_FREE:
BKE_image_free_buffers(ima);
- if (iuser)
+
+ if (iuser) {
iuser->ok = 1;
+ if (iuser->scene) {
+ image_update_views_format(ima, iuser);
+ }
+ }
break;
case IMA_SIGNAL_SRC_CHANGE:
if (ima->type == IMA_TYPE_UV_TEST)
@@ -2271,23 +2673,41 @@ void BKE_image_signal(Image *ima, ImageUser *iuser, int signal)
case IMA_SIGNAL_RELOAD:
/* try to repack file */
- if (ima->packedfile) {
- PackedFile *pf;
- pf = newPackedFile(NULL, ima->name, ID_BLEND_PATH(G.main, &ima->id));
- if (pf) {
- freePackedFile(ima->packedfile);
- ima->packedfile = pf;
- BKE_image_free_buffers(ima);
+ if (BKE_image_has_packedfile(ima)) {
+ const size_t totfiles = image_num_files(ima);
+
+ if (totfiles != BLI_listbase_count_ex(&ima->packedfiles, totfiles + 1)) {
+ /* in case there are new available files to be loaded */
+ image_free_packedfiles(ima);
+ BKE_image_packfiles(NULL, ima, ID_BLEND_PATH(G.main, &ima->id));
}
else {
- printf("ERROR: Image not available. Keeping packed image\n");
+ ImagePackedFile *imapf;
+ for (imapf = ima->packedfiles.first; imapf; imapf = imapf->next) {
+ PackedFile *pf;
+ pf = newPackedFile(NULL, imapf->filepath, ID_BLEND_PATH(G.main, &ima->id));
+ if (pf) {
+ freePackedFile(imapf->packedfile);
+ imapf->packedfile = pf;
+ }
+ else {
+ printf("ERROR: Image \"%s\" not available. Keeping packed image\n", imapf->filepath);
+ }
+ }
}
+
+ if (BKE_image_has_packedfile(ima))
+ BKE_image_free_buffers(ima);
}
else
BKE_image_free_buffers(ima);
- if (iuser)
+ if (iuser) {
iuser->ok = 1;
+ if (iuser->scene) {
+ image_update_views_format(ima, iuser);
+ }
+ }
break;
case IMA_SIGNAL_USER_NEW_IMAGE:
@@ -2295,8 +2715,7 @@ void BKE_image_signal(Image *ima, ImageUser *iuser, int signal)
iuser->ok = 1;
if (ima->source == IMA_SRC_FILE || ima->source == IMA_SRC_SEQUENCE) {
if (ima->type == IMA_TYPE_MULTILAYER) {
- iuser->multi_index = 0;
- iuser->layer = iuser->pass = 0;
+ image_init_imageuser(ima, iuser);
}
}
}
@@ -2326,6 +2745,52 @@ void BKE_image_signal(Image *ima, ImageUser *iuser, int signal)
}
}
+#define PASSTYPE_UNSET -1
+/* return renderpass for a given pass index and active view */
+/* fallback to available if there are missing passes for active view */
+static RenderPass *image_render_pass_get(RenderLayer *rl, const int pass, const int view, int *r_passindex)
+{
+ RenderPass *rpass_ret = NULL;
+ RenderPass *rpass;
+
+ int rp_index = 0;
+ int rp_passtype = PASSTYPE_UNSET;
+
+ for (rpass = rl->passes.first; rpass; rpass = rpass->next, rp_index++) {
+ if (rp_index == pass) {
+ rpass_ret = rpass;
+ if (view == 0) {
+ /* no multiview or left eye */
+ break;
+ }
+ else {
+ rp_passtype = rpass->passtype;
+ }
+ }
+ /* multiview */
+ else if ((rp_passtype != PASSTYPE_UNSET) &&
+ (rpass->passtype == rp_passtype) &&
+ (rpass->view_id == view))
+ {
+ rpass_ret = rpass;
+ break;
+ }
+ }
+
+ /* fallback to the first pass in the layer */
+ if (rpass_ret == NULL) {
+ rp_index = 0;
+ rpass_ret = rl->passes.first;
+ }
+
+ if (r_passindex) {
+ *r_passindex = (rpass == rpass_ret ? rp_index : pass);
+ }
+
+ return rpass_ret;
+}
+#undef PASSTYPE_UNSET
+
/* if layer or pass changes, we need an index for the imbufs list */
/* note it is called for rendered results, but it doesnt use the index! */
/* and because rendered results use fake layer/passes, don't correct for wrong indices here */
@@ -2338,44 +2803,102 @@ RenderPass *BKE_image_multilayer_index(RenderResult *rr, ImageUser *iuser)
return NULL;
if (iuser) {
- short index = 0, rl_index = 0, rp_index;
+ short index = 0, rv_index, rl_index = 0;
+ bool is_stereo = (iuser->flag & IMA_SHOW_STEREO) && RE_RenderResult_is_stereo(rr);
+
+ rv_index = is_stereo ? iuser->multiview_eye : iuser->view;
+ if (RE_HasFakeLayer(rr)) rl_index += 1;
for (rl = rr->layers.first; rl; rl = rl->next, rl_index++) {
- rp_index = 0;
- for (rpass = rl->passes.first; rpass; rpass = rpass->next, index++, rp_index++)
- if (iuser->layer == rl_index && iuser->pass == rp_index)
- break;
- if (rpass)
+ if (iuser->layer == rl_index) {
+ int rp_index;
+ rpass = image_render_pass_get(rl, iuser->pass, rv_index, &rp_index);
+ iuser->multi_index = index + rp_index;
break;
+ }
+ else {
+ index += BLI_listbase_count(&rl->passes);
+ }
}
+ }
- if (rpass)
- iuser->multi_index = index;
- else
- iuser->multi_index = 0;
+ return rpass;
+}
+
+void BKE_image_multiview_index(Image *ima, ImageUser *iuser)
+{
+ if (iuser) {
+ bool is_stereo = (ima->flag & IMA_IS_STEREO) && (iuser->flag & IMA_SHOW_STEREO);
+ if (is_stereo) {
+ iuser->multi_index = iuser->multiview_eye;
+ }
+ else {
+ if ((iuser->view < 0) || (iuser->view >= BLI_listbase_count_ex(&ima->views, iuser->view + 1))) {
+ iuser->multi_index = iuser->view = 0;
+ }
+ else {
+ iuser->multi_index = iuser->view;
+ }
+ }
}
- if (rpass == NULL) {
- rl = rr->layers.first;
- if (rl)
- rpass = rl->passes.first;
+}
+
+/* if layer or pass changes, we need an index for the imbufs list */
+/* note it is called for rendered results, but it doesnt use the index! */
+/* and because rendered results use fake layer/passes, don't correct for wrong indices here */
+bool BKE_image_is_multilayer(Image *ima)
+{
+ if (ELEM(ima->source, IMA_SRC_FILE, IMA_SRC_SEQUENCE)) {
+ if (ima->type == IMA_TYPE_MULTILAYER) {
+ return true;
+ }
+ }
+ else if (ima->source == IMA_SRC_VIEWER) {
+ if (ima->type == IMA_TYPE_R_RESULT) {
+ return true;
+ }
}
+ return false;
+}
- return rpass;
+static void image_init_multilayer_multiview_flag(Image *ima, RenderResult *rr)
+{
+ if (rr) {
+ if (RE_RenderResult_is_stereo(rr)) {
+ ima->flag |= IMA_IS_STEREO;
+ ima->flag |= IMA_IS_MULTIVIEW;
+ }
+ else {
+ ima->flag &= ~IMA_IS_STEREO;
+ if (BLI_listbase_count_ex(&rr->views, 2) > 1)
+ ima->flag |= IMA_IS_MULTIVIEW;
+ else
+ ima->flag &= ~IMA_IS_MULTIVIEW;
+ }
+ }
+ else {
+ ima->flag &= ~IMA_IS_STEREO;
+ ima->flag &= ~IMA_IS_MULTIVIEW;
+ }
}
RenderResult *BKE_image_acquire_renderresult(Scene *scene, Image *ima)
{
+ RenderResult *rr = NULL;
if (ima->rr) {
- return ima->rr;
+ rr = ima->rr;
}
else if (ima->type == IMA_TYPE_R_RESULT) {
if (ima->render_slot == ima->last_render_slot)
- return RE_AcquireResultRead(RE_GetRender(scene->id.name));
+ rr = RE_AcquireResultRead(RE_GetRender(scene->id.name));
else
- return ima->renders[ima->render_slot];
+ rr = ima->renders[ima->render_slot];
+
+ /* set proper multiview flag */
+ image_init_multilayer_multiview_flag(ima, rr);
}
- else
- return NULL;
+
+ return rr;
}
void BKE_image_release_renderresult(Scene *scene, Image *ima)
@@ -2389,6 +2912,18 @@ void BKE_image_release_renderresult(Scene *scene, Image *ima)
}
}
+bool BKE_image_is_openexr(struct Image *ima)
+{
+#ifdef WITH_OPENEXR
+ if (ELEM(ima->source, IMA_SRC_FILE, IMA_SRC_SEQUENCE)) {
+ return BLI_testextensie(ima->name, ".exr");
+ }
+#else
+ UNUSED_VARS(ima);
+#endif
+ return false;
+}
+
void BKE_image_backup_render(Scene *scene, Image *ima)
{
/* called right before rendering, ima->renders contains render
@@ -2409,8 +2944,155 @@ void BKE_image_backup_render(Scene *scene, Image *ima)
ima->last_render_slot = slot;
}
+/**************************** multiview save openexr *********************************/
+#ifdef WITH_OPENEXR
+static const char *image_get_view_cb(void *base, const size_t view_id)
+{
+ Image *ima = base;
+ ImageView *iv = BLI_findlink(&ima->views, view_id);
+ return iv ? iv->name : "";
+}
+#endif /* WITH_OPENEXR */
+
+#ifdef WITH_OPENEXR
+static ImBuf *image_get_buffer_cb(void *base, const size_t view_id)
+{
+ Image *ima = base;
+ ImageUser iuser = {0};
+
+ iuser.view = view_id;
+ iuser.ok = 1;
+
+ BKE_image_multiview_index(ima, &iuser);
+
+ return image_acquire_ibuf(ima, &iuser, NULL);
+}
+#endif /* WITH_OPENEXR */
+
+bool BKE_image_save_openexr_multiview(Image *ima, ImBuf *ibuf, const char *filepath, const int flags)
+{
+#ifdef WITH_OPENEXR
+ char name[FILE_MAX];
+ bool ok;
+
+ BLI_strncpy(name, filepath, sizeof(name));
+ BLI_path_abs(name, G.main->name);
+
+ ibuf->userdata = ima;
+ ok = IMB_exr_multiview_save(ibuf, name, flags, BLI_listbase_count(&ima->views), image_get_view_cb, image_get_buffer_cb);
+ ibuf->userdata = NULL;
+
+ return ok;
+#else
+ UNUSED_VARS(ima, ibuf, filepath, flags);
+ return false;
+#endif
+}
+
+/**************************** multiview load openexr *********************************/
+
+static void image_add_view(Image *ima, const char *viewname, const char *filepath)
+{
+ ImageView *iv;
+
+ iv = MEM_mallocN(sizeof(ImageView), "Viewer Image View");
+ BLI_strncpy(iv->name, viewname, sizeof(iv->name));
+ BLI_strncpy(iv->filepath, filepath, sizeof(iv->filepath));
+
+ /* For stereo drawing we need to ensure:
+ * STEREO_LEFT_NAME == STEREO_LEFT_ID and
+ * STEREO_RIGHT_NAME == STEREO_RIGHT_ID */
+
+ if (STREQ(viewname, STEREO_LEFT_NAME)) {
+ BLI_addhead(&ima->views, iv);
+ }
+ else if (STREQ(viewname, STEREO_RIGHT_NAME)) {
+ ImageView *left_iv = BLI_findstring(&ima->views, STEREO_LEFT_NAME, offsetof(ImageView, name));
+
+ if (left_iv == NULL) {
+ BLI_addhead(&ima->views, iv);
+ }
+ else {
+ BLI_insertlinkafter(&ima->views, left_iv, iv);
+ }
+ }
+ else {
+ BLI_addtail(&ima->views, iv);
+ }
+}
+
+#ifdef WITH_OPENEXR
+static void image_add_view_cb(void *base, const char *str)
+{
+ Image *ima = base;
+ image_add_view(ima, str, ima->name);
+}
+
+static void image_add_buffer_cb(void *base, const char *str, ImBuf *ibuf, const int frame)
+{
+ Image *ima = base;
+ size_t id;
+ bool predivide = (ima->alpha_mode == IMA_ALPHA_PREMUL);
+ const char *colorspace = ima->colorspace_settings.name;
+ const char *to_colorspace = IMB_colormanagement_role_colorspace_name_get(COLOR_ROLE_SCENE_LINEAR);
+
+ if (ibuf == NULL)
+ return;
+
+ id = BLI_findstringindex(&ima->views, str, offsetof(ImageView, name));
+
+ if (id == -1)
+ return;
+
+ if (ibuf->channels >= 3)
+ IMB_colormanagement_transform(ibuf->rect_float, ibuf->x, ibuf->y, ibuf->channels,
+ colorspace, to_colorspace, predivide);
+
+ image_assign_ibuf(ima, ibuf, id, frame);
+ IMB_freeImBuf(ibuf);
+}
+#endif /* WITH_OPENEXR */
+
+#ifdef WITH_OPENEXR
+static void image_update_multiview_flags(Image *ima)
+{
+ if (BLI_listbase_count_ex(&ima->views, 2) > 1) {
+ ima->flag |= IMA_IS_MULTIVIEW;
+
+ if (BLI_findstring(&ima->views, STEREO_LEFT_NAME, offsetof(ImageView, name)) &&
+ BLI_findstring(&ima->views, STEREO_RIGHT_NAME, offsetof(ImageView, name)))
+ {
+ ima->flag |= IMA_IS_STEREO;
+ }
+ else {
+ ima->flag &= ~IMA_IS_STEREO;
+ }
+ }
+ else {
+ ima->flag &= ~IMA_IS_STEREO;
+ ima->flag &= ~IMA_IS_MULTIVIEW;
+ }
+}
+#endif /* WITH_OPENEXR */
+
+/* after imbuf load, openexr type can return with a exrhandle open */
+/* in that case we have to build a render-result */
+#ifdef WITH_OPENEXR
+static void image_create_multiview(Image *ima, ImBuf *ibuf, const int frame)
+{
+ image_free_views(ima);
+
+ IMB_exr_multiview_convert(ibuf->userdata, ima, image_add_view_cb, image_add_buffer_cb, frame);
+
+ image_update_multiview_flags(ima);
+
+ IMB_exr_close(ibuf->userdata);
+}
+#endif /* WITH_OPENEXR */
+
/* after imbuf load, openexr type can return with a exrhandle open */
/* in that case we have to build a render-result */
+#ifdef WITH_OPENEXR
static void image_create_multilayer(Image *ima, ImBuf *ibuf, int framenr)
{
const char *colorspace = ima->colorspace_settings.name;
@@ -2418,21 +3100,23 @@ static void image_create_multilayer(Image *ima, ImBuf *ibuf, int framenr)
ima->rr = RE_MultilayerConvert(ibuf->userdata, colorspace, predivide, ibuf->x, ibuf->y);
-#ifdef WITH_OPENEXR
IMB_exr_close(ibuf->userdata);
-#endif
ibuf->userdata = NULL;
if (ima->rr)
ima->rr->framenr = framenr;
+
+ /* set proper multiview flag */
+ image_init_multilayer_multiview_flag(ima, ima->rr);
}
+#endif /* WITH_OPENEXR */
/* common stuff to do with images after loading */
static void image_initialize_after_load(Image *ima, ImBuf *ibuf)
{
/* preview is NULL when it has never been used as an icon before */
if (G.background == 0 && ima->preview == NULL)
- BKE_icon_changed(BKE_icon_getid(&ima->id));
+ BKE_icon_changed(BKE_icon_id_ensure(&ima->id));
/* fields */
if (ima->flag & IMA_FIELDS) {
@@ -2458,18 +3142,41 @@ static int imbuf_alpha_flags_for_image(Image *ima)
return flag;
}
-static ImBuf *image_load_sequence_file(Image *ima, ImageUser *iuser, int frame)
+/* the number of files will vary according to the stereo format */
+static size_t image_num_files(Image *ima)
+{
+ const bool is_multiview = (ima->flag & IMA_IS_MULTIVIEW) != 0;
+
+ if (!is_multiview) {
+ return 1;
+ }
+ else if (ima->views_format == R_IMF_VIEWS_STEREO_3D) {
+ return 1;
+ }
+ /* R_IMF_VIEWS_INDIVIDUAL */
+ else {
+ return BLI_listbase_count(&ima->views);
+ }
+}
+
+static ImBuf *load_sequence_single(Image *ima, ImageUser *iuser, int frame, const size_t view_id, bool *r_assign)
{
struct ImBuf *ibuf;
char name[FILE_MAX];
int flag;
+ ImageUser iuser_t;
/* XXX temp stuff? */
if (ima->lastframe != frame)
ima->tpageflag |= IMA_TPAGE_REFRESH;
ima->lastframe = frame;
- BKE_image_user_file_path(iuser, ima, name);
+
+ if (iuser)
+ iuser_t = *iuser;
+
+ iuser_t.view = view_id;
+ BKE_image_user_file_path(&iuser_t, ima, name);
flag = IB_rect | IB_multilayer;
flag |= imbuf_alpha_flags_for_image(ima);
@@ -2489,26 +3196,79 @@ static ImBuf *image_load_sequence_file(Image *ima, ImageUser *iuser, int frame)
if (ibuf) {
#ifdef WITH_OPENEXR
/* handle multilayer case, don't assign ibuf. will be handled in BKE_image_acquire_ibuf */
- if (ibuf->ftype == OPENEXR && ibuf->userdata) {
- image_create_multilayer(ima, ibuf, frame);
- ima->type = IMA_TYPE_MULTILAYER;
- IMB_freeImBuf(ibuf);
- ibuf = NULL;
+ if (ibuf->ftype == IMB_FTYPE_OPENEXR && ibuf->userdata) {
+ /* handle singlelayer multiview case assign ibuf based on available views */
+ if (IMB_exr_has_singlelayer_multiview(ibuf->userdata)) {
+ image_create_multiview(ima, ibuf, frame);
+ IMB_freeImBuf(ibuf);
+ ibuf = NULL;
+ }
+ else if (IMB_exr_has_multilayer(ibuf->userdata)) {
+ /* handle multilayer case, don't assign ibuf. will be handled in BKE_image_acquire_ibuf */
+ image_create_multilayer(ima, ibuf, frame);
+ ima->type = IMA_TYPE_MULTILAYER;
+ IMB_freeImBuf(ibuf);
+ ibuf = NULL;
+ }
}
else {
image_initialize_after_load(ima, ibuf);
- image_assign_ibuf(ima, ibuf, 0, frame);
+ *r_assign = true;
}
#else
image_initialize_after_load(ima, ibuf);
- image_assign_ibuf(ima, ibuf, 0, frame);
+ *r_assign = true;
#endif
}
- else
- ima->ok = 0;
- if (iuser)
- iuser->ok = ima->ok;
+ return ibuf;
+}
+
+static ImBuf *image_load_sequence_file(Image *ima, ImageUser *iuser, int frame)
+{
+ struct ImBuf *ibuf = NULL;
+ const bool is_multiview = (ima->flag & IMA_IS_MULTIVIEW) != 0;
+ const size_t totfiles = image_num_files(ima);
+ bool assign = false;
+
+ if (!is_multiview) {
+ ibuf = load_sequence_single(ima, iuser, frame, 0, &assign);
+ if (assign) {
+ image_assign_ibuf(ima, ibuf, 0, frame);
+ }
+ }
+ else {
+ size_t i;
+ struct ImBuf **ibuf_arr;
+ const size_t totviews = BLI_listbase_count(&ima->views);
+
+ ibuf_arr = MEM_mallocN(sizeof(ImBuf *) * totviews, "Image Views Imbufs");
+
+ for (i = 0; i < totfiles; i++)
+ ibuf_arr[i] = load_sequence_single(ima, iuser, frame, i, &assign);
+
+ if ((ima->flag & IMA_IS_STEREO) && ima->views_format == R_IMF_VIEWS_STEREO_3D)
+ IMB_ImBufFromStereo3d(ima->stereo3d_format, ibuf_arr[0], &ibuf_arr[0], &ibuf_arr[1]);
+
+ /* return the original requested ImBuf */
+ ibuf = ibuf_arr[(iuser ? iuser->multi_index : 0)];
+
+ if (assign) {
+ for (i = 0; i < totviews; i++) {
+ image_assign_ibuf(ima, ibuf_arr[i], i, frame);
+ }
+ }
+
+ /* "remove" the others (decrease their refcount) */
+ for (i = 0; i < totviews; i++) {
+ if (ibuf_arr[i] != ibuf) {
+ IMB_freeImBuf(ibuf_arr[i]);
+ }
+ }
+
+ /* cleanup */
+ MEM_freeN(ibuf_arr);
+ }
return ibuf;
}
@@ -2526,7 +3286,7 @@ static ImBuf *image_load_sequence_multilayer(Image *ima, ImageUser *iuser, int f
* need to ensure there's no image buffers are hanging around
* with dead links after freeing the render result.
*/
- image_free_cahced_frames(ima);
+ image_free_cached_frames(ima);
RE_FreeRenderResult(ima->rr);
ima->rr = NULL;
}
@@ -2565,42 +3325,52 @@ static ImBuf *image_load_sequence_multilayer(Image *ima, ImageUser *iuser, int f
return ibuf;
}
-
-static ImBuf *image_load_movie_file(Image *ima, ImageUser *iuser, int frame)
+static ImBuf *load_movie_single(Image *ima, ImageUser *iuser, int frame, const size_t view_id)
{
struct ImBuf *ibuf = NULL;
+ ImageAnim *ia;
- ima->lastframe = frame;
+ ia = BLI_findlink(&ima->anims, view_id);
- if (ima->anim == NULL) {
+ if (ia->anim == NULL) {
char str[FILE_MAX];
+ int flags = IB_rect;
+ ImageUser iuser_t;
+
+ if (ima->flag & IMA_DEINTERLACE) {
+ flags |= IB_animdeinterlace;
+ }
+
+ if (iuser)
+ iuser_t = *iuser;
+
+ iuser_t.view = view_id;
- BKE_image_user_file_path(iuser, ima, str);
+ BKE_image_user_file_path(&iuser_t, ima, str);
/* FIXME: make several stream accessible in image editor, too*/
- ima->anim = openanim(str, IB_rect, 0, ima->colorspace_settings.name);
+ ia->anim = openanim(str, flags, 0, ima->colorspace_settings.name);
/* let's initialize this user */
- if (ima->anim && iuser && iuser->frames == 0)
- iuser->frames = IMB_anim_get_duration(ima->anim,
+ if (ia->anim && iuser && iuser->frames == 0)
+ iuser->frames = IMB_anim_get_duration(ia->anim,
IMB_TC_RECORD_RUN);
}
- if (ima->anim) {
- int dur = IMB_anim_get_duration(ima->anim,
+ if (ia->anim) {
+ int dur = IMB_anim_get_duration(ia->anim,
IMB_TC_RECORD_RUN);
int fra = frame - 1;
if (fra < 0) fra = 0;
if (fra > (dur - 1)) fra = dur - 1;
ibuf = IMB_makeSingleUser(
- IMB_anim_absolute(ima->anim, fra,
+ IMB_anim_absolute(ia->anim, fra,
IMB_TC_RECORD_RUN,
IMB_PROXY_NONE));
if (ibuf) {
image_initialize_after_load(ima, ibuf);
- image_assign_ibuf(ima, ibuf, 0, frame);
}
else
ima->ok = 0;
@@ -2608,67 +3378,227 @@ static ImBuf *image_load_movie_file(Image *ima, ImageUser *iuser, int frame)
else
ima->ok = 0;
+ return ibuf;
+}
+
+static ImBuf *image_load_movie_file(Image *ima, ImageUser *iuser, int frame)
+{
+ struct ImBuf *ibuf = NULL;
+ const bool is_multiview = (ima->flag & IMA_IS_MULTIVIEW) != 0;
+ const size_t totfiles = image_num_files(ima);
+ size_t i;
+
+ if (totfiles != BLI_listbase_count_ex(&ima->anims, totfiles + 1)) {
+ image_free_anims(ima);
+
+ for (i = 0; i < totfiles; i++) {
+ /* allocate the ImageAnim */
+ ImageAnim *ia = MEM_callocN(sizeof(ImageAnim), "Image Anim");
+ BLI_addtail(&ima->anims, ia);
+ }
+ }
+
+ if (!is_multiview) {
+ ibuf = load_movie_single(ima, iuser, frame, 0);
+ image_assign_ibuf(ima, ibuf, 0, frame);
+ }
+ else {
+ struct ImBuf **ibuf_arr;
+ const size_t totviews = BLI_listbase_count(&ima->views);
+
+ ibuf_arr = MEM_mallocN(sizeof(ImBuf *) * totviews, "Image Views (movie) Imbufs");
+
+ for (i = 0; i < totfiles; i++) {
+ ibuf_arr[i] = load_movie_single(ima, iuser, frame, i);
+ }
+
+ if ((ima->flag & IMA_IS_STEREO) && ima->views_format == R_IMF_VIEWS_STEREO_3D)
+ IMB_ImBufFromStereo3d(ima->stereo3d_format, ibuf_arr[0], &ibuf_arr[0], &ibuf_arr[1]);
+
+ for (i = 0; i < totviews; i++) {
+ if (ibuf_arr[i]) {
+ image_assign_ibuf(ima, ibuf_arr[i], i, frame);
+ }
+ else {
+ ima->ok = 0;
+ }
+ }
+
+ /* return the original requested ImBuf */
+ ibuf = ibuf_arr[(iuser ? iuser->multi_index : 0)];
+
+ /* "remove" the others (decrease their refcount) */
+ for (i = 0; i < totviews; i++) {
+ if (ibuf_arr[i] != ibuf) {
+ IMB_freeImBuf(ibuf_arr[i]);
+ }
+ }
+
+ /* cleanup */
+ MEM_freeN(ibuf_arr);
+ }
+
if (iuser)
iuser->ok = ima->ok;
return ibuf;
}
-/* warning, 'iuser' can be NULL */
-static ImBuf *image_load_image_file(Image *ima, ImageUser *iuser, int cfra)
+static ImBuf *load_image_single(
+ Image *ima, ImageUser *iuser, int cfra,
+ const size_t view_id,
+ const bool has_packed,
+ bool *r_assign)
{
- struct ImBuf *ibuf;
- char str[FILE_MAX];
- int assign = 0, flag;
-
- /* always ensure clean ima */
- BKE_image_free_buffers(ima);
+ char filepath[FILE_MAX];
+ struct ImBuf *ibuf = NULL;
+ int flag;
/* is there a PackedFile with this image ? */
- if (ima->packedfile) {
+ if (has_packed) {
+ ImagePackedFile *imapf;
+
flag = IB_rect | IB_multilayer;
flag |= imbuf_alpha_flags_for_image(ima);
- ibuf = IMB_ibImageFromMemory((unsigned char *)ima->packedfile->data, ima->packedfile->size, flag,
- ima->colorspace_settings.name, "<packed data>");
+ imapf = BLI_findlink(&ima->packedfiles, view_id);
+ if (imapf->packedfile) {
+ ibuf = IMB_ibImageFromMemory(
+ (unsigned char *)imapf->packedfile->data, imapf->packedfile->size, flag,
+ ima->colorspace_settings.name, "<packed data>");
+ }
}
else {
+ ImageUser iuser_t;
+
flag = IB_rect | IB_multilayer | IB_metadata;
flag |= imbuf_alpha_flags_for_image(ima);
- /* get the right string */
+ /* get the correct filepath */
BKE_image_user_frame_calc(iuser, cfra, 0);
- BKE_image_user_file_path(iuser, ima, str);
+
+ if (iuser)
+ iuser_t = *iuser;
+ else
+ iuser_t.framenr = ima->lastframe;
+
+ iuser_t.view = view_id;
+
+ BKE_image_user_file_path(&iuser_t, ima, filepath);
/* read ibuf */
- ibuf = IMB_loadiffname(str, flag, ima->colorspace_settings.name);
+ ibuf = IMB_loadiffname(filepath, flag, ima->colorspace_settings.name);
}
if (ibuf) {
- /* handle multilayer case, don't assign ibuf. will be handled in BKE_image_acquire_ibuf */
- if (ibuf->ftype == OPENEXR && ibuf->userdata) {
- image_create_multilayer(ima, ibuf, cfra);
- ima->type = IMA_TYPE_MULTILAYER;
- IMB_freeImBuf(ibuf);
- ibuf = NULL;
+#ifdef WITH_OPENEXR
+ if (ibuf->ftype == IMB_FTYPE_OPENEXR && ibuf->userdata) {
+ if (IMB_exr_has_singlelayer_multiview(ibuf->userdata)) {
+ /* handle singlelayer multiview case assign ibuf based on available views */
+ image_create_multiview(ima, ibuf, cfra);
+ IMB_freeImBuf(ibuf);
+ ibuf = NULL;
+ }
+ else if (IMB_exr_has_multilayer(ibuf->userdata)) {
+ /* handle multilayer case, don't assign ibuf. will be handled in BKE_image_acquire_ibuf */
+ image_create_multilayer(ima, ibuf, cfra);
+ ima->type = IMA_TYPE_MULTILAYER;
+ IMB_freeImBuf(ibuf);
+ ibuf = NULL;
+ }
}
- else {
+ else
+#endif
+ {
image_initialize_after_load(ima, ibuf);
- assign = 1;
+ *r_assign = true;
/* check if the image is a font image... */
detectBitmapFont(ibuf);
/* make packed file for autopack */
- if ((ima->packedfile == NULL) && (G.fileflags & G_AUTOPACK))
- ima->packedfile = newPackedFile(NULL, str, ID_BLEND_PATH(G.main, &ima->id));
+ if ((has_packed == false) && (G.fileflags & G_AUTOPACK)) {
+ ImagePackedFile *imapf = MEM_mallocN(sizeof(ImagePackedFile), "Image Packefile");
+ BLI_addtail(&ima->packedfiles, imapf);
+
+ BLI_strncpy(imapf->filepath, filepath, sizeof(imapf->filepath));
+ imapf->packedfile = newPackedFile(NULL, filepath, ID_BLEND_PATH(G.main, &ima->id));
+ }
}
}
- else
+ else {
ima->ok = 0;
+ }
- if (assign)
- image_assign_ibuf(ima, ibuf, IMA_NO_INDEX, 0);
+ return ibuf;
+}
+
+/* warning, 'iuser' can be NULL
+ * note: Image->views was already populated (in image_update_views_format)
+ */
+static ImBuf *image_load_image_file(Image *ima, ImageUser *iuser, int cfra)
+{
+ struct ImBuf *ibuf = NULL;
+ bool assign = false;
+ const bool is_multiview = (ima->flag & IMA_IS_MULTIVIEW) != 0;
+ const size_t totfiles = image_num_files(ima);
+ bool has_packed = BKE_image_has_packedfile(ima);
+
+ /* always ensure clean ima */
+ BKE_image_free_buffers(ima);
+
+ /* this should never happen, but just playing safe */
+ if (has_packed) {
+ if (totfiles != BLI_listbase_count_ex(&ima->packedfiles, totfiles + 1)) {
+ image_free_packedfiles(ima);
+ has_packed = false;
+ }
+ }
+
+ if (!is_multiview) {
+ ibuf = load_image_single(ima, iuser, cfra, 0, has_packed, &assign);
+ if (assign) {
+ image_assign_ibuf(ima, ibuf, IMA_NO_INDEX, 0);
+ }
+ }
+ else {
+ size_t i;
+ struct ImBuf **ibuf_arr;
+ const size_t totviews = BLI_listbase_count(&ima->views);
+ BLI_assert(totviews > 0);
+
+ ibuf_arr = MEM_callocN(sizeof(ImBuf *) * totviews, "Image Views Imbufs");
+
+ for (i = 0; i < totfiles; i++)
+ ibuf_arr[i] = load_image_single(ima, iuser, cfra, i, has_packed, &assign);
+
+ /* multi-views/multi-layers OpenEXR files directly populate ima, and return NULL ibuf... */
+ if ((ima->flag & IMA_IS_STEREO) && ima->views_format == R_IMF_VIEWS_STEREO_3D &&
+ ibuf_arr[0] && totfiles == 1 && totviews >= 2)
+ {
+ IMB_ImBufFromStereo3d(ima->stereo3d_format, ibuf_arr[0], &ibuf_arr[0], &ibuf_arr[1]);
+ }
+
+ /* return the original requested ImBuf */
+ i = (iuser && iuser->multi_index < totviews) ? iuser->multi_index : 0;
+ ibuf = ibuf_arr[i];
+
+ if (assign) {
+ for (i = 0; i < totviews; i++) {
+ image_assign_ibuf(ima, ibuf_arr[i], i, 0);
+ }
+ }
+
+ /* "remove" the others (decrease their refcount) */
+ for (i = 0; i < totviews; i++) {
+ if (ibuf_arr[i] != ibuf) {
+ IMB_freeImBuf(ibuf_arr[i]);
+ }
+ }
+
+ /* cleanup */
+ MEM_freeN(ibuf_arr);
+ }
if (iuser)
iuser->ok = ima->ok;
@@ -2715,23 +3645,25 @@ static ImBuf *image_get_ibuf_multilayer(Image *ima, ImageUser *iuser)
/* showing RGBA result itself (from compo/sequence) or
* like exr, using layers etc */
/* always returns a single ibuf, also during render progress */
-static ImBuf *image_get_render_result(Image *ima, ImageUser *iuser, void **lock_r)
+static ImBuf *image_get_render_result(Image *ima, ImageUser *iuser, void **r_lock)
{
Render *re;
RenderResult rres;
+ RenderView *rv;
float *rectf, *rectz;
unsigned int *rect;
float dither;
int channels, layer, pass;
ImBuf *ibuf;
int from_render = (ima->render_slot == ima->last_render_slot);
+ int actview;
bool byte_buffer_in_display_space = false;
if (!(iuser && iuser->scene))
return NULL;
/* if we the caller is not going to release the lock, don't give the image */
- if (!lock_r)
+ if (!r_lock)
return NULL;
re = RE_GetRender(iuser->scene->id.name);
@@ -2739,13 +3671,17 @@ static ImBuf *image_get_render_result(Image *ima, ImageUser *iuser, void **lock_
channels = 4;
layer = iuser->layer;
pass = iuser->pass;
+ actview = iuser->view;
+
+ if ((ima->flag & IMA_IS_STEREO) && (iuser->flag & IMA_SHOW_STEREO))
+ actview = iuser->multiview_eye;
if (from_render) {
- RE_AcquireResultImage(re, &rres);
+ RE_AcquireResultImage(re, &rres, actview);
}
else if (ima->renders[ima->render_slot]) {
rres = *(ima->renders[ima->render_slot]);
- rres.have_combined = rres.rectf != NULL;
+ rres.have_combined = ((RenderView *)rres.views.first)->rectf != NULL;
}
else
memset(&rres, 0, sizeof(RenderResult));
@@ -2756,16 +3692,30 @@ static ImBuf *image_get_render_result(Image *ima, ImageUser *iuser, void **lock_
return NULL;
}
- /* release is done in BKE_image_release_ibuf using lock_r */
+ /* release is done in BKE_image_release_ibuf using r_lock */
if (from_render) {
BLI_lock_thread(LOCK_VIEWER);
- *lock_r = re;
+ *r_lock = re;
+ rv = NULL;
+ }
+ else {
+ rv = BLI_findlink(&rres.views, actview);
+ if (rv == NULL)
+ rv = rres.views.first;
}
/* this gives active layer, composite or sequence result */
- rect = (unsigned int *)rres.rect32;
- rectf = rres.rectf;
- rectz = rres.rectz;
+ if (rv == NULL) {
+ rect = (unsigned int *)rres.rect32;
+ rectf = rres.rectf;
+ rectz = rres.rectz;
+ }
+ else {
+ rect = (unsigned int *)rv->rect32;
+ rectf = rv->rectf;
+ rectz = rv->rectz;
+ }
+
dither = iuser->scene->r.dither_intensity;
/* combined layer gets added as first layer */
@@ -2783,24 +3733,20 @@ static ImBuf *image_get_render_result(Image *ima, ImageUser *iuser, void **lock_
else if (rres.layers.first) {
RenderLayer *rl = BLI_findlink(&rres.layers, layer - (rres.have_combined ? 1 : 0));
if (rl) {
- RenderPass *rpass;
-
- /* there's no combined pass, is in renderlayer itself */
- if (pass == 0) {
- rectf = rl->rectf;
- if (rectf == NULL) {
- /* Happens when Save Buffers is enabled.
- * Use display buffer stored in the render layer.
- */
- rect = (unsigned int *) rl->display_buffer;
- byte_buffer_in_display_space = true;
+ RenderPass *rpass = image_render_pass_get(rl, pass, actview, NULL);
+ if (rpass) {
+ rectf = rpass->rect;
+ if (pass == 0) {
+ if (rectf == NULL) {
+ /* Happens when Save Buffers is enabled.
+ * Use display buffer stored in the render layer.
+ */
+ rect = (unsigned int *) rl->display_buffer;
+ byte_buffer_in_display_space = true;
+ }
}
- }
- else {
- rpass = BLI_findlink(&rl->passes, pass - 1);
- if (rpass) {
+ else {
channels = rpass->channels;
- rectf = rpass->rect;
dither = 0.0f; /* don't dither passes */
}
}
@@ -2891,9 +3837,31 @@ static ImBuf *image_get_render_result(Image *ima, ImageUser *iuser, void **lock_
return ibuf;
}
+static size_t image_get_multiview_index(Image *ima, ImageUser *iuser)
+{
+ const bool is_multilayer = BKE_image_is_multilayer(ima);
+ const bool is_backdrop = (ima->source == IMA_SRC_VIEWER) && (ima->type == IMA_TYPE_COMPOSITE) && (iuser == NULL);
+ int index = BKE_image_is_animated(ima) ? 0 : IMA_NO_INDEX;
+
+ if (is_multilayer) {
+ return iuser ? iuser->multi_index : index;
+ }
+ else if (is_backdrop) {
+ if ((ima->flag & IMA_IS_STEREO)) {
+ /* backdrop hackaround (since there is no iuser */
+ return ima->eye;
+ }
+ }
+ else if ((ima->flag & IMA_IS_MULTIVIEW)) {
+ return iuser ? iuser->multi_index : index;
+ }
+
+ return index;
+}
+
static void image_get_frame_and_index(Image *ima, ImageUser *iuser, int *r_frame, int *r_index)
{
- int frame = 0, index = 0;
+ int frame = 0, index = image_get_multiview_index(ima, iuser);
/* see if we already have an appropriate ibuf, with image source and type */
if (ima->source == IMA_SRC_MOVIE) {
@@ -2905,7 +3873,6 @@ static void image_get_frame_and_index(Image *ima, ImageUser *iuser, int *r_frame
}
else if (ima->type == IMA_TYPE_MULTILAYER) {
frame = iuser ? iuser->framenr : ima->lastframe;
- index = iuser ? iuser->multi_index : IMA_NO_INDEX;
}
}
@@ -2922,12 +3889,12 @@ static void image_get_frame_and_index(Image *ima, ImageUser *iuser, int *r_frame
static ImBuf *image_get_cached_ibuf(Image *ima, ImageUser *iuser, int *r_frame, int *r_index)
{
ImBuf *ibuf = NULL;
- int frame = 0, index = 0;
+ int frame = 0, index = image_get_multiview_index(ima, iuser);
/* see if we already have an appropriate ibuf, with image source and type */
if (ima->source == IMA_SRC_MOVIE) {
frame = iuser ? iuser->framenr : ima->lastframe;
- ibuf = image_get_cached_ibuf_for_index_frame(ima, 0, frame);
+ ibuf = image_get_cached_ibuf_for_index_frame(ima, index, frame);
/* XXX temp stuff? */
if (ima->lastframe != frame)
ima->tpageflag |= IMA_TPAGE_REFRESH;
@@ -2936,28 +3903,37 @@ static ImBuf *image_get_cached_ibuf(Image *ima, ImageUser *iuser, int *r_frame,
else if (ima->source == IMA_SRC_SEQUENCE) {
if (ima->type == IMA_TYPE_IMAGE) {
frame = iuser ? iuser->framenr : ima->lastframe;
- ibuf = image_get_cached_ibuf_for_index_frame(ima, 0, frame);
+ ibuf = image_get_cached_ibuf_for_index_frame(ima, index, frame);
/* XXX temp stuff? */
if (ima->lastframe != frame) {
ima->tpageflag |= IMA_TPAGE_REFRESH;
}
ima->lastframe = frame;
+
+ /* counter the fact that image is set as invalid when loading a frame
+ * that is not in the cache (through image_acquire_ibuf for instance),
+ * yet we have valid frames in the cache loaded */
+ if (ibuf) {
+ ima->ok = IMA_OK_LOADED;
+
+ if (iuser)
+ iuser->ok = ima->ok;
+ }
}
else if (ima->type == IMA_TYPE_MULTILAYER) {
frame = iuser ? iuser->framenr : ima->lastframe;
- index = iuser ? iuser->multi_index : IMA_NO_INDEX;
ibuf = image_get_cached_ibuf_for_index_frame(ima, index, frame);
}
}
else if (ima->source == IMA_SRC_FILE) {
if (ima->type == IMA_TYPE_IMAGE)
- ibuf = image_get_cached_ibuf_for_index_frame(ima, IMA_NO_INDEX, 0);
+ ibuf = image_get_cached_ibuf_for_index_frame(ima, index, 0);
else if (ima->type == IMA_TYPE_MULTILAYER)
- ibuf = image_get_cached_ibuf_for_index_frame(ima, iuser ? iuser->multi_index : IMA_NO_INDEX, 0);
+ ibuf = image_get_cached_ibuf_for_index_frame(ima, index, 0);
}
else if (ima->source == IMA_SRC_GENERATED) {
- ibuf = image_get_cached_ibuf_for_index_frame(ima, IMA_NO_INDEX, 0);
+ ibuf = image_get_cached_ibuf_for_index_frame(ima, index, 0);
}
else if (ima->source == IMA_SRC_VIEWER) {
/* always verify entirely, not that this shouldn't happen
@@ -2993,14 +3969,13 @@ BLI_INLINE bool image_quick_test(Image *ima, ImageUser *iuser)
*
* not thread-safe, so callee should worry about thread locks
*/
-static ImBuf *image_acquire_ibuf(Image *ima, ImageUser *iuser, void **lock_r)
+static ImBuf *image_acquire_ibuf(Image *ima, ImageUser *iuser, void **r_lock)
{
ImBuf *ibuf = NULL;
- float color[] = {0, 0, 0, 1};
int frame = 0, index = 0;
- if (lock_r)
- *lock_r = NULL;
+ if (r_lock)
+ *r_lock = NULL;
/* quick reject tests */
if (!image_quick_test(ima, iuser))
@@ -3041,32 +4016,32 @@ static ImBuf *image_acquire_ibuf(Image *ima, ImageUser *iuser, void **lock_r)
if (ima->gen_y == 0) ima->gen_y = 1024;
if (ima->gen_depth == 0) ima->gen_depth = 24;
ibuf = add_ibuf_size(ima->gen_x, ima->gen_y, ima->name, ima->gen_depth, (ima->gen_flag & IMA_GEN_FLOAT) != 0, ima->gen_type,
- color, &ima->colorspace_settings);
- image_assign_ibuf(ima, ibuf, IMA_NO_INDEX, 0);
+ ima->gen_color, &ima->colorspace_settings);
+ image_assign_ibuf(ima, ibuf, index, 0);
ima->ok = IMA_OK_LOADED;
}
else if (ima->source == IMA_SRC_VIEWER) {
if (ima->type == IMA_TYPE_R_RESULT) {
/* always verify entirely, and potentially
* returns pointer to release later */
- ibuf = image_get_render_result(ima, iuser, lock_r);
+ ibuf = image_get_render_result(ima, iuser, r_lock);
}
else if (ima->type == IMA_TYPE_COMPOSITE) {
/* requires lock/unlock, otherwise don't return image */
- if (lock_r) {
+ if (r_lock) {
/* unlock in BKE_image_release_ibuf */
BLI_lock_thread(LOCK_VIEWER);
- *lock_r = ima;
+ *r_lock = ima;
/* XXX anim play for viewer nodes not yet supported */
frame = 0; // XXX iuser ? iuser->framenr : 0;
- ibuf = image_get_cached_ibuf_for_index_frame(ima, 0, frame);
+ ibuf = image_get_cached_ibuf_for_index_frame(ima, index, frame);
if (!ibuf) {
/* Composite Viewer, all handled in compositor */
/* fake ibuf, will be filled in compositor */
- ibuf = IMB_allocImBuf(256, 256, 32, IB_rect);
- image_assign_ibuf(ima, ibuf, 0, frame);
+ ibuf = IMB_allocImBuf(256, 256, 32, IB_rect | IB_rectfloat);
+ image_assign_ibuf(ima, ibuf, index, frame);
}
}
}
@@ -3090,13 +4065,13 @@ static ImBuf *image_acquire_ibuf(Image *ima, ImageUser *iuser, void **lock_r)
*
* references the result, BKE_image_release_ibuf should be used to de-reference
*/
-ImBuf *BKE_image_acquire_ibuf(Image *ima, ImageUser *iuser, void **lock_r)
+ImBuf *BKE_image_acquire_ibuf(Image *ima, ImageUser *iuser, void **r_lock)
{
ImBuf *ibuf;
BLI_spin_lock(&image_spin);
- ibuf = image_acquire_ibuf(ima, iuser, lock_r);
+ ibuf = image_acquire_ibuf(ima, iuser, r_lock);
BLI_spin_unlock(&image_spin);
@@ -3366,7 +4341,13 @@ void BKE_image_update_frame(const Main *bmain, int cfra)
void BKE_image_user_file_path(ImageUser *iuser, Image *ima, char *filepath)
{
- BLI_strncpy(filepath, ima->name, FILE_MAX);
+ if ((ima->flag & IMA_IS_MULTIVIEW) && (ima->rr == NULL)) {
+ ImageView *iv = BLI_findlink(&ima->views, iuser->view);
+ BLI_strncpy(filepath, iv->filepath, FILE_MAX);
+ }
+ else {
+ BLI_strncpy(filepath, ima->name, FILE_MAX);
+ }
if (ima->source == IMA_SRC_SEQUENCE) {
char head[FILE_MAX], tail[FILE_MAX];
@@ -3391,9 +4372,9 @@ bool BKE_image_has_alpha(struct Image *image)
BKE_image_release_ibuf(image, ibuf, lock);
if (planes == 32)
- return 1;
+ return true;
else
- return 0;
+ return false;
}
void BKE_image_get_size(Image *image, ImageUser *iuser, int *width, int *height)
@@ -3502,6 +4483,16 @@ int BKE_image_sequence_guess_offset(Image *image)
return atoi(num);
}
+bool BKE_image_has_anim(Image *ima)
+{
+ return (BLI_listbase_is_empty(&ima->anims) == false);
+}
+
+bool BKE_image_has_packedfile(Image *ima)
+{
+ return (BLI_listbase_is_empty(&ima->packedfiles) == false);
+}
+
/**
* Checks the image buffer changes (not keyframed values)
*
@@ -3535,12 +4526,13 @@ bool BKE_image_is_dirty(Image *image)
return is_dirty;
}
-void BKE_image_file_format_set(Image *image, int ftype)
+void BKE_image_file_format_set(Image *image, int ftype, const ImbFormatOptions *options)
{
#if 0
ImBuf *ibuf = BKE_image_acquire_ibuf(image, NULL, NULL);
if (ibuf) {
ibuf->ftype = ftype;
+ ibuf->foptions = options;
}
BKE_image_release_ibuf(image, ibuf, NULL);
#endif
@@ -3552,6 +4544,7 @@ void BKE_image_file_format_set(Image *image, int ftype)
while (!IMB_moviecacheIter_done(iter)) {
ImBuf *ibuf = IMB_moviecacheIter_getImBuf(iter);
ibuf->ftype = ftype;
+ ibuf->foptions = *options;
IMB_moviecacheIter_step(iter);
}
IMB_moviecacheIter_free(iter);
@@ -3632,3 +4625,88 @@ ImBuf *BKE_image_get_first_ibuf(Image *image)
return ibuf;
}
+
+static void image_update_views_format(Image *ima, ImageUser *iuser)
+{
+ SceneRenderView *srv;
+ ImageView *iv;
+ Scene *scene = iuser->scene;
+ const bool is_multiview = ((scene->r.scemode & R_MULTIVIEW) != 0) &&
+ ((ima->flag & IMA_USE_VIEWS) != 0);
+
+ /* reset the image views */
+ BKE_image_free_views(ima);
+
+ if (!is_multiview) {
+ goto monoview;
+ }
+ else if (ima->views_format == R_IMF_VIEWS_STEREO_3D) {
+ size_t i;
+ const char *names[2] = {STEREO_LEFT_NAME, STEREO_RIGHT_NAME};
+
+ ima->flag |= IMA_IS_MULTIVIEW;
+ ima->flag |= IMA_IS_STEREO;
+
+ for (i = 0; i < 2; i++) {
+ image_add_view(ima, names[i], ima->name);
+ }
+ return;
+ }
+ else {
+ /* R_IMF_VIEWS_INDIVIDUAL */
+ char prefix[FILE_MAX] = {'\0'};
+ char *name = ima->name;
+ const char *ext = NULL;
+
+ BKE_scene_multiview_view_prefix_get(scene, name, prefix, &ext);
+
+ if (prefix[0] == '\0') {
+ goto monoview;
+ }
+
+ /* create all the image views */
+ for (srv = scene->r.views.first; srv; srv = srv->next) {
+ if (BKE_scene_multiview_is_render_view_active(&scene->r, srv)) {
+ char filepath[FILE_MAX];
+ BLI_snprintf(filepath, sizeof(filepath), "%s%s%s", prefix, srv->suffix, ext);
+ image_add_view(ima, srv->name, filepath);
+ }
+ }
+
+ /* check if the files are all available */
+ iv = ima->views.last;
+ while (iv) {
+ int file;
+ char str[FILE_MAX];
+
+ BLI_strncpy(str, iv->filepath, sizeof(str));
+ BLI_path_abs(str, G.main->name);
+
+ /* exists? */
+ file = BLI_open(str, O_BINARY | O_RDONLY, 0);
+ if (file == -1) {
+ ImageView *iv_del = iv;
+ iv = iv->prev;
+ BLI_remlink(&ima->views, iv_del);
+ MEM_freeN(iv_del);
+ }
+ else {
+ iv = iv->prev;
+ close(file);
+ }
+ }
+
+ /* all good */
+ if (BLI_listbase_count_ex(&ima->views, 2) > 1) {
+ ima->flag |= IMA_IS_MULTIVIEW;
+ if (BKE_scene_multiview_is_stereo3d(&scene->r))
+ ima->flag |= IMA_IS_STEREO;
+ }
+ else {
+monoview:
+ ima->flag &= ~IMA_IS_STEREO;
+ ima->flag &= ~IMA_IS_MULTIVIEW;
+ BKE_image_free_views(ima);
+ }
+ }
+}
diff --git a/source/blender/blenkernel/intern/image_gen.c b/source/blender/blenkernel/intern/image_gen.c
index 4f9ed5f258d..303d0c6adfc 100644
--- a/source/blender/blenkernel/intern/image_gen.c
+++ b/source/blender/blenkernel/intern/image_gen.c
@@ -309,26 +309,26 @@ static void checker_board_text(unsigned char *rect, float *rect_float, int width
BLF_buffer_col(mono, 1.0, 1.0, 1.0, 1.0);
BLF_position(mono, pen_x - outline, pen_y, 0.0);
- BLF_draw_buffer(mono, text);
+ BLF_draw_buffer(mono, text, 2);
BLF_position(mono, pen_x + outline, pen_y, 0.0);
- BLF_draw_buffer(mono, text);
+ BLF_draw_buffer(mono, text, 2);
BLF_position(mono, pen_x, pen_y - outline, 0.0);
- BLF_draw_buffer(mono, text);
+ BLF_draw_buffer(mono, text, 2);
BLF_position(mono, pen_x, pen_y + outline, 0.0);
- BLF_draw_buffer(mono, text);
+ BLF_draw_buffer(mono, text, 2);
BLF_position(mono, pen_x - outline, pen_y - outline, 0.0);
- BLF_draw_buffer(mono, text);
+ BLF_draw_buffer(mono, text, 2);
BLF_position(mono, pen_x + outline, pen_y + outline, 0.0);
- BLF_draw_buffer(mono, text);
+ BLF_draw_buffer(mono, text, 2);
BLF_position(mono, pen_x - outline, pen_y + outline, 0.0);
- BLF_draw_buffer(mono, text);
+ BLF_draw_buffer(mono, text, 2);
BLF_position(mono, pen_x + outline, pen_y - outline, 0.0);
- BLF_draw_buffer(mono, text);
+ BLF_draw_buffer(mono, text, 2);
BLF_buffer_col(mono, 0.0, 0.0, 0.0, 1.0);
BLF_position(mono, pen_x, pen_y, 0.0);
- BLF_draw_buffer(mono, text);
+ BLF_draw_buffer(mono, text, 2);
text[1]++;
}
diff --git a/source/blender/blenkernel/intern/implicit.c b/source/blender/blenkernel/intern/implicit.c
deleted file mode 100644
index 4cf9d52989f..00000000000
--- a/source/blender/blenkernel/intern/implicit.c
+++ /dev/null
@@ -1,1964 +0,0 @@
-/*
- * ***** BEGIN GPL LICENSE BLOCK *****
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * The Original Code is Copyright (C) Blender Foundation
- * All rights reserved.
- *
- * The Original Code is: all of this file.
- *
- * Contributor(s): none yet.
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-
-/** \file blender/blenkernel/intern/implicit.c
- * \ingroup bke
- */
-
-
-#include "MEM_guardedalloc.h"
-
-#include "DNA_scene_types.h"
-#include "DNA_object_types.h"
-#include "DNA_object_force.h"
-#include "DNA_meshdata_types.h"
-
-#include "BLI_math.h"
-#include "BLI_linklist.h"
-#include "BLI_utildefines.h"
-
-#include "BKE_cloth.h"
-#include "BKE_collision.h"
-#include "BKE_effect.h"
-#include "BKE_global.h"
-
-
-#ifdef __GNUC__
-# pragma GCC diagnostic ignored "-Wtype-limits"
-#endif
-
-#ifdef _OPENMP
-# define CLOTH_OPENMP_LIMIT 512
-#endif
-
-#if 0 /* debug timing */
-#ifdef _WIN32
-#include <windows.h>
-static LARGE_INTEGER _itstart, _itend;
-static LARGE_INTEGER ifreq;
-static void itstart(void)
-{
- static int first = 1;
- if (first) {
- QueryPerformanceFrequency(&ifreq);
- first = 0;
- }
- QueryPerformanceCounter(&_itstart);
-}
-static void itend(void)
-{
- QueryPerformanceCounter(&_itend);
-}
-double itval(void)
-{
- return ((double)_itend.QuadPart -
- (double)_itstart.QuadPart)/((double)ifreq.QuadPart);
-}
-#else
-#include <sys/time.h>
-// intrinsics need better compile flag checking
-// #include <xmmintrin.h>
-// #include <pmmintrin.h>
-// #include <pthread.h>
-
-static struct timeval _itstart, _itend;
-static struct timezone itz;
-static void itstart(void)
-{
- gettimeofday(&_itstart, &itz);
-}
-static void itend(void)
-{
- gettimeofday(&_itend, &itz);
-}
-static double itval(void)
-{
- double t1, t2;
- t1 = (double)_itstart.tv_sec + (double)_itstart.tv_usec/(1000*1000);
- t2 = (double)_itend.tv_sec + (double)_itend.tv_usec/(1000*1000);
- return t2-t1;
-}
-#endif
-#endif /* debug timing */
-
-static float I[3][3] = {{1, 0, 0}, {0, 1, 0}, {0, 0, 1}};
-static float ZERO[3][3] = {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}};
-
-/*
-#define C99
-#ifdef C99
-#defineDO_INLINE inline
-#else
-#defineDO_INLINE static
-#endif
-*/
-struct Cloth;
-
-//////////////////////////////////////////
-/* fast vector / matrix library, enhancements are welcome :) -dg */
-/////////////////////////////////////////
-
-/* DEFINITIONS */
-typedef float lfVector[3];
-typedef struct fmatrix3x3 {
- float m[3][3]; /* 3x3 matrix */
- unsigned int c, r; /* column and row number */
- /* int pinned; // is this vertex allowed to move? */
- float n1, n2, n3; /* three normal vectors for collision constrains */
- unsigned int vcount; /* vertex count */
- unsigned int scount; /* spring count */
-} fmatrix3x3;
-
-///////////////////////////
-// float[3] vector
-///////////////////////////
-/* simple vector code */
-/* STATUS: verified */
-DO_INLINE void mul_fvector_S(float to[3], float from[3], float scalar)
-{
- to[0] = from[0] * scalar;
- to[1] = from[1] * scalar;
- to[2] = from[2] * scalar;
-}
-/* simple cross product */
-/* STATUS: verified */
-DO_INLINE void cross_fvector(float to[3], float vectorA[3], float vectorB[3])
-{
- to[0] = vectorA[1] * vectorB[2] - vectorA[2] * vectorB[1];
- to[1] = vectorA[2] * vectorB[0] - vectorA[0] * vectorB[2];
- to[2] = vectorA[0] * vectorB[1] - vectorA[1] * vectorB[0];
-}
-/* simple v^T * v product ("outer product") */
-/* STATUS: HAS TO BE verified (*should* work) */
-DO_INLINE void mul_fvectorT_fvector(float to[3][3], float vectorA[3], float vectorB[3])
-{
- mul_fvector_S(to[0], vectorB, vectorA[0]);
- mul_fvector_S(to[1], vectorB, vectorA[1]);
- mul_fvector_S(to[2], vectorB, vectorA[2]);
-}
-/* simple v^T * v product with scalar ("outer product") */
-/* STATUS: HAS TO BE verified (*should* work) */
-DO_INLINE void mul_fvectorT_fvectorS(float to[3][3], float vectorA[3], float vectorB[3], float aS)
-{
- mul_fvectorT_fvector(to, vectorA, vectorB);
-
- mul_fvector_S(to[0], to[0], aS);
- mul_fvector_S(to[1], to[1], aS);
- mul_fvector_S(to[2], to[2], aS);
-}
-
-#if 0
-/* printf vector[3] on console: for debug output */
-static void print_fvector(float m3[3])
-{
- printf("%f\n%f\n%f\n\n", m3[0], m3[1], m3[2]);
-}
-
-///////////////////////////
-// long float vector float (*)[3]
-///////////////////////////
-/* print long vector on console: for debug output */
-DO_INLINE void print_lfvector(float (*fLongVector)[3], unsigned int verts)
-{
- unsigned int i = 0;
- for (i = 0; i < verts; i++) {
- print_fvector(fLongVector[i]);
- }
-}
-#endif
-
-/* create long vector */
-DO_INLINE lfVector *create_lfvector(unsigned int verts)
-{
- /* TODO: check if memory allocation was successful */
- return (lfVector *)MEM_callocN(verts * sizeof(lfVector), "cloth_implicit_alloc_vector");
- // return (lfVector *)cloth_aligned_malloc(&MEMORY_BASE, verts * sizeof(lfVector));
-}
-/* delete long vector */
-DO_INLINE void del_lfvector(float (*fLongVector)[3])
-{
- if (fLongVector != NULL) {
- MEM_freeN(fLongVector);
- // cloth_aligned_free(&MEMORY_BASE, fLongVector);
- }
-}
-/* copy long vector */
-DO_INLINE void cp_lfvector(float (*to)[3], float (*from)[3], unsigned int verts)
-{
- memcpy(to, from, verts * sizeof(lfVector));
-}
-/* init long vector with float[3] */
-DO_INLINE void init_lfvector(float (*fLongVector)[3], float vector[3], unsigned int verts)
-{
- unsigned int i = 0;
- for (i = 0; i < verts; i++) {
- copy_v3_v3(fLongVector[i], vector);
- }
-}
-/* zero long vector with float[3] */
-DO_INLINE void zero_lfvector(float (*to)[3], unsigned int verts)
-{
- memset(to, 0.0f, verts * sizeof(lfVector));
-}
-/* multiply long vector with scalar*/
-DO_INLINE void mul_lfvectorS(float (*to)[3], float (*fLongVector)[3], float scalar, unsigned int verts)
-{
- unsigned int i = 0;
-
- for (i = 0; i < verts; i++) {
- mul_fvector_S(to[i], fLongVector[i], scalar);
- }
-}
-/* multiply long vector with scalar*/
-/* A -= B * float */
-DO_INLINE void submul_lfvectorS(float (*to)[3], float (*fLongVector)[3], float scalar, unsigned int verts)
-{
- unsigned int i = 0;
- for (i = 0; i < verts; i++) {
- VECSUBMUL(to[i], fLongVector[i], scalar);
- }
-}
-/* dot product for big vector */
-DO_INLINE float dot_lfvector(float (*fLongVectorA)[3], float (*fLongVectorB)[3], unsigned int verts)
-{
- long i = 0;
- float temp = 0.0;
-// XXX brecht, disabled this for now (first schedule line was already disabled),
-// due to non-commutative nature of floating point ops this makes the sim give
-// different results each time you run it!
-// schedule(guided, 2)
-//#pragma omp parallel for reduction(+: temp) if (verts > CLOTH_OPENMP_LIMIT)
- for (i = 0; i < (long)verts; i++) {
- temp += dot_v3v3(fLongVectorA[i], fLongVectorB[i]);
- }
- return temp;
-}
-/* A = B + C --> for big vector */
-DO_INLINE void add_lfvector_lfvector(float (*to)[3], float (*fLongVectorA)[3], float (*fLongVectorB)[3], unsigned int verts)
-{
- unsigned int i = 0;
-
- for (i = 0; i < verts; i++) {
- VECADD(to[i], fLongVectorA[i], fLongVectorB[i]);
- }
-
-}
-/* A = B + C * float --> for big vector */
-DO_INLINE void add_lfvector_lfvectorS(float (*to)[3], float (*fLongVectorA)[3], float (*fLongVectorB)[3], float bS, unsigned int verts)
-{
- unsigned int i = 0;
-
- for (i = 0; i < verts; i++) {
- VECADDS(to[i], fLongVectorA[i], fLongVectorB[i], bS);
-
- }
-}
-/* A = B * float + C * float --> for big vector */
-DO_INLINE void add_lfvectorS_lfvectorS(float (*to)[3], float (*fLongVectorA)[3], float aS, float (*fLongVectorB)[3], float bS, unsigned int verts)
-{
- unsigned int i = 0;
-
- for (i = 0; i < verts; i++) {
- VECADDSS(to[i], fLongVectorA[i], aS, fLongVectorB[i], bS);
- }
-}
-/* A = B - C * float --> for big vector */
-DO_INLINE void sub_lfvector_lfvectorS(float (*to)[3], float (*fLongVectorA)[3], float (*fLongVectorB)[3], float bS, unsigned int verts)
-{
- unsigned int i = 0;
- for (i = 0; i < verts; i++) {
- VECSUBS(to[i], fLongVectorA[i], fLongVectorB[i], bS);
- }
-
-}
-/* A = B - C --> for big vector */
-DO_INLINE void sub_lfvector_lfvector(float (*to)[3], float (*fLongVectorA)[3], float (*fLongVectorB)[3], unsigned int verts)
-{
- unsigned int i = 0;
-
- for (i = 0; i < verts; i++) {
- sub_v3_v3v3(to[i], fLongVectorA[i], fLongVectorB[i]);
- }
-
-}
-///////////////////////////
-// 3x3 matrix
-///////////////////////////
-#if 0
-/* printf 3x3 matrix on console: for debug output */
-static void print_fmatrix(float m3[3][3])
-{
- printf("%f\t%f\t%f\n", m3[0][0], m3[0][1], m3[0][2]);
- printf("%f\t%f\t%f\n", m3[1][0], m3[1][1], m3[1][2]);
- printf("%f\t%f\t%f\n\n", m3[2][0], m3[2][1], m3[2][2]);
-}
-#endif
-
-/* copy 3x3 matrix */
-DO_INLINE void cp_fmatrix(float to[3][3], float from[3][3])
-{
- // memcpy(to, from, sizeof (float) * 9);
- copy_v3_v3(to[0], from[0]);
- copy_v3_v3(to[1], from[1]);
- copy_v3_v3(to[2], from[2]);
-}
-
-/* copy 3x3 matrix */
-DO_INLINE void initdiag_fmatrixS(float to[3][3], float aS)
-{
- cp_fmatrix(to, ZERO);
-
- to[0][0] = aS;
- to[1][1] = aS;
- to[2][2] = aS;
-}
-
-/* calculate determinant of 3x3 matrix */
-DO_INLINE float det_fmatrix(float m[3][3])
-{
- return m[0][0]*m[1][1]*m[2][2] + m[1][0]*m[2][1]*m[0][2] + m[0][1]*m[1][2]*m[2][0]
- -m[0][0]*m[1][2]*m[2][1] - m[0][1]*m[1][0]*m[2][2] - m[2][0]*m[1][1]*m[0][2];
-}
-
-DO_INLINE void inverse_fmatrix(float to[3][3], float from[3][3])
-{
- unsigned int i, j;
- float d;
-
- if ((d=det_fmatrix(from)) == 0) {
- printf("can't build inverse");
- exit(0);
- }
- for (i=0;i<3;i++) {
- for (j=0;j<3;j++) {
- int i1=(i+1)%3;
- int i2=(i+2)%3;
- int j1=(j+1)%3;
- int j2=(j+2)%3;
- // reverse indexs i&j to take transpose
- to[j][i] = (from[i1][j1]*from[i2][j2]-from[i1][j2]*from[i2][j1])/d;
- /*
- if (i==j)
- to[i][j] = 1.0f / from[i][j];
- else
- to[i][j] = 0;
- */
- }
- }
-
-}
-
-/* 3x3 matrix multiplied by a scalar */
-/* STATUS: verified */
-DO_INLINE void mul_fmatrix_S(float matrix[3][3], float scalar)
-{
- mul_fvector_S(matrix[0], matrix[0], scalar);
- mul_fvector_S(matrix[1], matrix[1], scalar);
- mul_fvector_S(matrix[2], matrix[2], scalar);
-}
-
-/* a vector multiplied by a 3x3 matrix */
-/* STATUS: verified */
-DO_INLINE void mul_fvector_fmatrix(float *to, float *from, float matrix[3][3])
-{
- to[0] = matrix[0][0]*from[0] + matrix[1][0]*from[1] + matrix[2][0]*from[2];
- to[1] = matrix[0][1]*from[0] + matrix[1][1]*from[1] + matrix[2][1]*from[2];
- to[2] = matrix[0][2]*from[0] + matrix[1][2]*from[1] + matrix[2][2]*from[2];
-}
-
-/* 3x3 matrix multiplied by a vector */
-/* STATUS: verified */
-DO_INLINE void mul_fmatrix_fvector(float *to, float matrix[3][3], float from[3])
-{
- to[0] = dot_v3v3(matrix[0], from);
- to[1] = dot_v3v3(matrix[1], from);
- to[2] = dot_v3v3(matrix[2], from);
-}
-/* 3x3 matrix multiplied by a 3x3 matrix */
-/* STATUS: verified */
-DO_INLINE void mul_fmatrix_fmatrix(float to[3][3], float matrixA[3][3], float matrixB[3][3])
-{
- mul_fvector_fmatrix(to[0], matrixA[0], matrixB);
- mul_fvector_fmatrix(to[1], matrixA[1], matrixB);
- mul_fvector_fmatrix(to[2], matrixA[2], matrixB);
-}
-/* 3x3 matrix addition with 3x3 matrix */
-DO_INLINE void add_fmatrix_fmatrix(float to[3][3], float matrixA[3][3], float matrixB[3][3])
-{
- VECADD(to[0], matrixA[0], matrixB[0]);
- VECADD(to[1], matrixA[1], matrixB[1]);
- VECADD(to[2], matrixA[2], matrixB[2]);
-}
-/* 3x3 matrix add-addition with 3x3 matrix */
-DO_INLINE void addadd_fmatrix_fmatrix(float to[3][3], float matrixA[3][3], float matrixB[3][3])
-{
- VECADDADD(to[0], matrixA[0], matrixB[0]);
- VECADDADD(to[1], matrixA[1], matrixB[1]);
- VECADDADD(to[2], matrixA[2], matrixB[2]);
-}
-/* 3x3 matrix sub-addition with 3x3 matrix */
-DO_INLINE void addsub_fmatrixS_fmatrixS(float to[3][3], float matrixA[3][3], float aS, float matrixB[3][3], float bS)
-{
- VECADDSUBSS(to[0], matrixA[0], aS, matrixB[0], bS);
- VECADDSUBSS(to[1], matrixA[1], aS, matrixB[1], bS);
- VECADDSUBSS(to[2], matrixA[2], aS, matrixB[2], bS);
-}
-/* A -= B + C (3x3 matrix sub-addition with 3x3 matrix) */
-DO_INLINE void subadd_fmatrix_fmatrix(float to[3][3], float matrixA[3][3], float matrixB[3][3])
-{
- VECSUBADD(to[0], matrixA[0], matrixB[0]);
- VECSUBADD(to[1], matrixA[1], matrixB[1]);
- VECSUBADD(to[2], matrixA[2], matrixB[2]);
-}
-/* A -= B*x + C*y (3x3 matrix sub-addition with 3x3 matrix) */
-DO_INLINE void subadd_fmatrixS_fmatrixS(float to[3][3], float matrixA[3][3], float aS, float matrixB[3][3], float bS)
-{
- VECSUBADDSS(to[0], matrixA[0], aS, matrixB[0], bS);
- VECSUBADDSS(to[1], matrixA[1], aS, matrixB[1], bS);
- VECSUBADDSS(to[2], matrixA[2], aS, matrixB[2], bS);
-}
-/* A = B - C (3x3 matrix subtraction with 3x3 matrix) */
-DO_INLINE void sub_fmatrix_fmatrix(float to[3][3], float matrixA[3][3], float matrixB[3][3])
-{
- sub_v3_v3v3(to[0], matrixA[0], matrixB[0]);
- sub_v3_v3v3(to[1], matrixA[1], matrixB[1]);
- sub_v3_v3v3(to[2], matrixA[2], matrixB[2]);
-}
-/* A += B - C (3x3 matrix add-subtraction with 3x3 matrix) */
-DO_INLINE void addsub_fmatrix_fmatrix(float to[3][3], float matrixA[3][3], float matrixB[3][3])
-{
- VECADDSUB(to[0], matrixA[0], matrixB[0]);
- VECADDSUB(to[1], matrixA[1], matrixB[1]);
- VECADDSUB(to[2], matrixA[2], matrixB[2]);
-}
-/////////////////////////////////////////////////////////////////
-// special functions
-/////////////////////////////////////////////////////////////////
-/* a vector multiplied and added to/by a 3x3 matrix */
-DO_INLINE void muladd_fvector_fmatrix(float to[3], float from[3], float matrix[3][3])
-{
- to[0] += matrix[0][0]*from[0] + matrix[1][0]*from[1] + matrix[2][0]*from[2];
- to[1] += matrix[0][1]*from[0] + matrix[1][1]*from[1] + matrix[2][1]*from[2];
- to[2] += matrix[0][2]*from[0] + matrix[1][2]*from[1] + matrix[2][2]*from[2];
-}
-/* 3x3 matrix multiplied and added to/by a 3x3 matrix and added to another 3x3 matrix */
-DO_INLINE void muladd_fmatrix_fmatrix(float to[3][3], float matrixA[3][3], float matrixB[3][3])
-{
- muladd_fvector_fmatrix(to[0], matrixA[0], matrixB);
- muladd_fvector_fmatrix(to[1], matrixA[1], matrixB);
- muladd_fvector_fmatrix(to[2], matrixA[2], matrixB);
-}
-/* a vector multiplied and sub'd to/by a 3x3 matrix */
-DO_INLINE void mulsub_fvector_fmatrix(float to[3], float from[3], float matrix[3][3])
-{
- to[0] -= matrix[0][0]*from[0] + matrix[1][0]*from[1] + matrix[2][0]*from[2];
- to[1] -= matrix[0][1]*from[0] + matrix[1][1]*from[1] + matrix[2][1]*from[2];
- to[2] -= matrix[0][2]*from[0] + matrix[1][2]*from[1] + matrix[2][2]*from[2];
-}
-/* 3x3 matrix multiplied and sub'd to/by a 3x3 matrix and added to another 3x3 matrix */
-DO_INLINE void mulsub_fmatrix_fmatrix(float to[3][3], float matrixA[3][3], float matrixB[3][3])
-{
- mulsub_fvector_fmatrix(to[0], matrixA[0], matrixB);
- mulsub_fvector_fmatrix(to[1], matrixA[1], matrixB);
- mulsub_fvector_fmatrix(to[2], matrixA[2], matrixB);
-}
-/* 3x3 matrix multiplied+added by a vector */
-/* STATUS: verified */
-DO_INLINE void muladd_fmatrix_fvector(float to[3], float matrix[3][3], float from[3])
-{
- to[0] += dot_v3v3(matrix[0], from);
- to[1] += dot_v3v3(matrix[1], from);
- to[2] += dot_v3v3(matrix[2], from);
-}
-/* 3x3 matrix multiplied+sub'ed by a vector */
-DO_INLINE void mulsub_fmatrix_fvector(float to[3], float matrix[3][3], float from[3])
-{
- to[0] -= dot_v3v3(matrix[0], from);
- to[1] -= dot_v3v3(matrix[1], from);
- to[2] -= dot_v3v3(matrix[2], from);
-}
-/////////////////////////////////////////////////////////////////
-
-///////////////////////////
-// SPARSE SYMMETRIC big matrix with 3x3 matrix entries
-///////////////////////////
-/* printf a big matrix on console: for debug output */
-#if 0
-static void print_bfmatrix(fmatrix3x3 *m3)
-{
- unsigned int i = 0;
-
- for (i = 0; i < m3[0].vcount + m3[0].scount; i++)
- {
- print_fmatrix(m3[i].m);
- }
-}
-#endif
-
-/* create big matrix */
-DO_INLINE fmatrix3x3 *create_bfmatrix(unsigned int verts, unsigned int springs)
-{
- // TODO: check if memory allocation was successful */
- fmatrix3x3 *temp = (fmatrix3x3 *)MEM_callocN(sizeof(fmatrix3x3) * (verts + springs), "cloth_implicit_alloc_matrix");
- temp[0].vcount = verts;
- temp[0].scount = springs;
- return temp;
-}
-/* delete big matrix */
-DO_INLINE void del_bfmatrix(fmatrix3x3 *matrix)
-{
- if (matrix != NULL) {
- MEM_freeN(matrix);
- }
-}
-
-/* copy big matrix */
-DO_INLINE void cp_bfmatrix(fmatrix3x3 *to, fmatrix3x3 *from)
-{
- // TODO bounds checking
- memcpy(to, from, sizeof(fmatrix3x3) * (from[0].vcount+from[0].scount));
-}
-
-/* init big matrix */
-// slow in parallel
-DO_INLINE void init_bfmatrix(fmatrix3x3 *matrix, float m3[3][3])
-{
- unsigned int i;
-
- for (i = 0; i < matrix[0].vcount+matrix[0].scount; i++) {
- cp_fmatrix(matrix[i].m, m3);
- }
-}
-
-/* init the diagonal of big matrix */
-// slow in parallel
-DO_INLINE void initdiag_bfmatrix(fmatrix3x3 *matrix, float m3[3][3])
-{
- unsigned int i, j;
- float tmatrix[3][3] = {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}};
-
- for (i = 0; i < matrix[0].vcount; i++) {
- cp_fmatrix(matrix[i].m, m3);
- }
- for (j = matrix[0].vcount; j < matrix[0].vcount+matrix[0].scount; j++) {
- cp_fmatrix(matrix[j].m, tmatrix);
- }
-}
-
-/* multiply big matrix with scalar*/
-DO_INLINE void mul_bfmatrix_S(fmatrix3x3 *matrix, float scalar)
-{
- unsigned int i = 0;
- for (i = 0; i < matrix[0].vcount+matrix[0].scount; i++) {
- mul_fmatrix_S(matrix[i].m, scalar);
- }
-}
-
-/* SPARSE SYMMETRIC multiply big matrix with long vector*/
-/* STATUS: verified */
-DO_INLINE void mul_bfmatrix_lfvector( float (*to)[3], fmatrix3x3 *from, lfVector *fLongVector)
-{
- unsigned int i = 0;
- unsigned int vcount = from[0].vcount;
- lfVector *temp = create_lfvector(vcount);
-
- zero_lfvector(to, vcount);
-
-#pragma omp parallel sections private(i) if (vcount > CLOTH_OPENMP_LIMIT)
- {
-#pragma omp section
- {
- for (i = from[0].vcount; i < from[0].vcount+from[0].scount; i++) {
- muladd_fmatrix_fvector(to[from[i].c], from[i].m, fLongVector[from[i].r]);
- }
- }
-#pragma omp section
- {
- for (i = 0; i < from[0].vcount+from[0].scount; i++) {
- muladd_fmatrix_fvector(temp[from[i].r], from[i].m, fLongVector[from[i].c]);
- }
- }
- }
- add_lfvector_lfvector(to, to, temp, from[0].vcount);
-
- del_lfvector(temp);
-
-
-}
-
-/* SPARSE SYMMETRIC multiply big matrix with long vector (for diagonal preconditioner) */
-/* STATUS: verified */
-DO_INLINE void mul_prevfmatrix_lfvector( float (*to)[3], fmatrix3x3 *from, lfVector *fLongVector)
-{
- unsigned int i = 0;
-
- for (i = 0; i < from[0].vcount; i++) {
- mul_fmatrix_fvector(to[from[i].r], from[i].m, fLongVector[from[i].c]);
- }
-}
-
-/* SPARSE SYMMETRIC add big matrix with big matrix: A = B + C*/
-DO_INLINE void add_bfmatrix_bfmatrix( fmatrix3x3 *to, fmatrix3x3 *from, fmatrix3x3 *matrix)
-{
- unsigned int i = 0;
-
- /* process diagonal elements */
- for (i = 0; i < matrix[0].vcount+matrix[0].scount; i++) {
- add_fmatrix_fmatrix(to[i].m, from[i].m, matrix[i].m);
- }
-
-}
-/* SPARSE SYMMETRIC add big matrix with big matrix: A += B + C */
-DO_INLINE void addadd_bfmatrix_bfmatrix( fmatrix3x3 *to, fmatrix3x3 *from, fmatrix3x3 *matrix)
-{
- unsigned int i = 0;
-
- /* process diagonal elements */
- for (i = 0; i < matrix[0].vcount+matrix[0].scount; i++) {
- addadd_fmatrix_fmatrix(to[i].m, from[i].m, matrix[i].m);
- }
-
-}
-/* SPARSE SYMMETRIC subadd big matrix with big matrix: A -= B + C */
-DO_INLINE void subadd_bfmatrix_bfmatrix( fmatrix3x3 *to, fmatrix3x3 *from, fmatrix3x3 *matrix)
-{
- unsigned int i = 0;
-
- /* process diagonal elements */
- for (i = 0; i < matrix[0].vcount+matrix[0].scount; i++) {
- subadd_fmatrix_fmatrix(to[i].m, from[i].m, matrix[i].m);
- }
-
-}
-/* A = B - C (SPARSE SYMMETRIC sub big matrix with big matrix) */
-DO_INLINE void sub_bfmatrix_bfmatrix( fmatrix3x3 *to, fmatrix3x3 *from, fmatrix3x3 *matrix)
-{
- unsigned int i = 0;
-
- /* process diagonal elements */
- for (i = 0; i < matrix[0].vcount+matrix[0].scount; i++) {
- sub_fmatrix_fmatrix(to[i].m, from[i].m, matrix[i].m);
- }
-
-}
-/* SPARSE SYMMETRIC sub big matrix with big matrix S (special constraint matrix with limited entries) */
-DO_INLINE void sub_bfmatrix_Smatrix( fmatrix3x3 *to, fmatrix3x3 *from, fmatrix3x3 *matrix)
-{
- unsigned int i = 0;
-
- /* process diagonal elements */
- for (i = 0; i < matrix[0].vcount; i++) {
- sub_fmatrix_fmatrix(to[matrix[i].c].m, from[matrix[i].c].m, matrix[i].m);
- }
-
-}
-/* A += B - C (SPARSE SYMMETRIC addsub big matrix with big matrix) */
-DO_INLINE void addsub_bfmatrix_bfmatrix( fmatrix3x3 *to, fmatrix3x3 *from, fmatrix3x3 *matrix)
-{
- unsigned int i = 0;
-
- /* process diagonal elements */
- for (i = 0; i < matrix[0].vcount+matrix[0].scount; i++) {
- addsub_fmatrix_fmatrix(to[i].m, from[i].m, matrix[i].m);
- }
-
-}
-/* SPARSE SYMMETRIC sub big matrix with big matrix*/
-/* A -= B * float + C * float --> for big matrix */
-/* VERIFIED */
-DO_INLINE void subadd_bfmatrixS_bfmatrixS( fmatrix3x3 *to, fmatrix3x3 *from, float aS, fmatrix3x3 *matrix, float bS)
-{
- unsigned int i = 0;
-
- /* process diagonal elements */
- for (i = 0; i < matrix[0].vcount+matrix[0].scount; i++) {
- subadd_fmatrixS_fmatrixS(to[i].m, from[i].m, aS, matrix[i].m, bS);
- }
-
-}
-
-///////////////////////////////////////////////////////////////////
-// simulator start
-///////////////////////////////////////////////////////////////////
-typedef struct Implicit_Data {
- lfVector *X, *V, *Xnew, *Vnew, *olddV, *F, *B, *dV, *z;
- fmatrix3x3 *A, *dFdV, *dFdX, *S, *P, *Pinv, *bigI, *M;
-} Implicit_Data;
-
-/* Init constraint matrix */
-static void update_matrixS(ClothVertex *verts, int numverts, fmatrix3x3 *S)
-{
- unsigned int pinned = 0;
- int i = 0;
-
- /* Clear matrix from old vertex constraints */
- for (i = 0; i < S[0].vcount; i++)
- S[i].c = S[i].r = 0;
-
- /* Set new vertex constraints */
- for (i = 0; i < numverts; i++) {
- if (verts [i].flags & CLOTH_VERT_FLAG_PINNED) {
- S[pinned].c = S[pinned].r = i;
- pinned++;
- }
- }
-
- // S is special and needs specific vcount and scount
- S[0].vcount = pinned;
- S[0].scount = 0;
-}
-
-int implicit_init(Object *UNUSED(ob), ClothModifierData *clmd)
-{
- unsigned int i = 0;
- Cloth *cloth = NULL;
- ClothVertex *verts = NULL;
- ClothSpring *spring = NULL;
- Implicit_Data *id = NULL;
- LinkNode *search = NULL;
-
- if (G.debug_value > 0)
- printf("implicit_init\n");
-
- // init memory guard
- // BLI_listbase_clear(&MEMORY_BASE);
-
- cloth = (Cloth *)clmd->clothObject;
- verts = cloth->verts;
-
- // create implicit base
- id = (Implicit_Data *)MEM_callocN(sizeof(Implicit_Data), "implicit vecmat");
- cloth->implicit = id;
-
- /* process diagonal elements */
- id->A = create_bfmatrix(cloth->numverts, cloth->numsprings);
- id->dFdV = create_bfmatrix(cloth->numverts, cloth->numsprings);
- id->dFdX = create_bfmatrix(cloth->numverts, cloth->numsprings);
- id->S = create_bfmatrix(cloth->numverts, 0);
- id->Pinv = create_bfmatrix(cloth->numverts, cloth->numsprings);
- id->P = create_bfmatrix(cloth->numverts, cloth->numsprings);
- id->bigI = create_bfmatrix(cloth->numverts, cloth->numsprings); // TODO 0 springs
- id->M = create_bfmatrix(cloth->numverts, cloth->numsprings);
- id->X = create_lfvector(cloth->numverts);
- id->Xnew = create_lfvector(cloth->numverts);
- id->V = create_lfvector(cloth->numverts);
- id->Vnew = create_lfvector(cloth->numverts);
- id->olddV = create_lfvector(cloth->numverts);
- zero_lfvector(id->olddV, cloth->numverts);
- id->F = create_lfvector(cloth->numverts);
- id->B = create_lfvector(cloth->numverts);
- id->dV = create_lfvector(cloth->numverts);
- id->z = create_lfvector(cloth->numverts);
-
- id->S[0].vcount = 0;
- update_matrixS(verts, cloth->numverts, id->S);
-
- for (i = 0; i < cloth->numverts; i++) {
- id->A[i].r = id->A[i].c = id->dFdV[i].r = id->dFdV[i].c = id->dFdX[i].r = id->dFdX[i].c = id->P[i].c = id->P[i].r = id->Pinv[i].c = id->Pinv[i].r = id->bigI[i].c = id->bigI[i].r = id->M[i].r = id->M[i].c = i;
-
- initdiag_fmatrixS(id->M[i].m, verts[i].mass);
- }
-
- // init springs
- search = cloth->springs;
- for (i = 0; i < cloth->numsprings; i++) {
- spring = search->link;
-
- // dFdV_start[i].r = big_I[i].r = big_zero[i].r =
- id->A[i+cloth->numverts].r = id->dFdV[i+cloth->numverts].r = id->dFdX[i+cloth->numverts].r =
- id->P[i+cloth->numverts].r = id->Pinv[i+cloth->numverts].r = id->bigI[i+cloth->numverts].r = id->M[i+cloth->numverts].r = spring->ij;
-
- // dFdV_start[i].c = big_I[i].c = big_zero[i].c =
- id->A[i+cloth->numverts].c = id->dFdV[i+cloth->numverts].c = id->dFdX[i+cloth->numverts].c =
- id->P[i+cloth->numverts].c = id->Pinv[i+cloth->numverts].c = id->bigI[i+cloth->numverts].c = id->M[i+cloth->numverts].c = spring->kl;
-
- spring->matrix_index = i + cloth->numverts;
-
- search = search->next;
- }
-
- initdiag_bfmatrix(id->bigI, I);
-
- for (i = 0; i < cloth->numverts; i++) {
- copy_v3_v3(id->X[i], verts[i].x);
- }
-
- return 1;
-}
-
-int implicit_free(ClothModifierData *clmd)
-{
- Implicit_Data *id;
- Cloth *cloth;
- cloth = (Cloth *)clmd->clothObject;
-
- if (cloth) {
- id = cloth->implicit;
-
- if (id) {
- del_bfmatrix(id->A);
- del_bfmatrix(id->dFdV);
- del_bfmatrix(id->dFdX);
- del_bfmatrix(id->S);
- del_bfmatrix(id->P);
- del_bfmatrix(id->Pinv);
- del_bfmatrix(id->bigI);
- del_bfmatrix(id->M);
-
- del_lfvector(id->X);
- del_lfvector(id->Xnew);
- del_lfvector(id->V);
- del_lfvector(id->Vnew);
- del_lfvector(id->olddV);
- del_lfvector(id->F);
- del_lfvector(id->B);
- del_lfvector(id->dV);
- del_lfvector(id->z);
-
- MEM_freeN(id);
- }
- }
-
- return 1;
-}
-
-DO_INLINE float fb(float length, float L)
-{
- float x = length / L;
- return (-11.541f * powf(x, 4) + 34.193f * powf(x, 3) - 39.083f * powf(x, 2) + 23.116f * x - 9.713f);
-}
-
-DO_INLINE float fbderiv(float length, float L)
-{
- float x = length/L;
-
- return (-46.164f * powf(x, 3) + 102.579f * powf(x, 2) - 78.166f * x + 23.116f);
-}
-
-DO_INLINE float fbstar(float length, float L, float kb, float cb)
-{
- float tempfb_fl = kb * fb(length, L);
- float fbstar_fl = cb * (length - L);
-
- if (tempfb_fl < fbstar_fl)
- return fbstar_fl;
- else
- return tempfb_fl;
-}
-
-// function to calculae bending spring force (taken from Choi & Co)
-DO_INLINE float fbstar_jacobi(float length, float L, float kb, float cb)
-{
- float tempfb_fl = kb * fb(length, L);
- float fbstar_fl = cb * (length - L);
-
- if (tempfb_fl < fbstar_fl) {
- return cb;
- }
- else {
- return kb * fbderiv(length, L);
- }
-}
-
-DO_INLINE void filter(lfVector *V, fmatrix3x3 *S)
-{
- unsigned int i=0;
-
- for (i = 0; i < S[0].vcount; i++) {
- mul_fvector_fmatrix(V[S[i].r], V[S[i].r], S[i].m);
- }
-}
-
-static int cg_filtered(lfVector *ldV, fmatrix3x3 *lA, lfVector *lB, lfVector *z, fmatrix3x3 *S)
-{
- // Solves for unknown X in equation AX=B
- unsigned int conjgrad_loopcount=0, conjgrad_looplimit=100;
- float conjgrad_epsilon=0.0001f /* , conjgrad_lasterror=0 */ /* UNUSED */;
- lfVector *q, *d, *tmp, *r;
- float s, starget, a, s_prev;
- unsigned int numverts = lA[0].vcount;
- q = create_lfvector(numverts);
- d = create_lfvector(numverts);
- tmp = create_lfvector(numverts);
- r = create_lfvector(numverts);
-
- // zero_lfvector(ldV, CLOTHPARTICLES);
- filter(ldV, S);
-
- add_lfvector_lfvector(ldV, ldV, z, numverts);
-
- // r = B - Mul(tmp, A, X); // just use B if X known to be zero
- cp_lfvector(r, lB, numverts);
- mul_bfmatrix_lfvector(tmp, lA, ldV);
- sub_lfvector_lfvector(r, r, tmp, numverts);
-
- filter(r, S);
-
- cp_lfvector(d, r, numverts);
-
- s = dot_lfvector(r, r, numverts);
- starget = s * sqrtf(conjgrad_epsilon);
-
- while (s>starget && conjgrad_loopcount < conjgrad_looplimit) {
- // Mul(q, A, d); // q = A*d;
- mul_bfmatrix_lfvector(q, lA, d);
-
- filter(q, S);
-
- a = s/dot_lfvector(d, q, numverts);
-
- // X = X + d*a;
- add_lfvector_lfvectorS(ldV, ldV, d, a, numverts);
-
- // r = r - q*a;
- sub_lfvector_lfvectorS(r, r, q, a, numverts);
-
- s_prev = s;
- s = dot_lfvector(r, r, numverts);
-
- //d = r+d*(s/s_prev);
- add_lfvector_lfvectorS(d, r, d, (s/s_prev), numverts);
-
- filter(d, S);
-
- conjgrad_loopcount++;
- }
- /* conjgrad_lasterror = s; */ /* UNUSED */
-
- del_lfvector(q);
- del_lfvector(d);
- del_lfvector(tmp);
- del_lfvector(r);
- // printf("W/O conjgrad_loopcount: %d\n", conjgrad_loopcount);
-
- return conjgrad_loopcount<conjgrad_looplimit; // true means we reached desired accuracy in given time - ie stable
-}
-
-// block diagonalizer
-DO_INLINE void BuildPPinv(fmatrix3x3 *lA, fmatrix3x3 *P, fmatrix3x3 *Pinv)
-{
- unsigned int i = 0;
-
- // Take only the diagonal blocks of A
-// #pragma omp parallel for private(i) if (lA[0].vcount > CLOTH_OPENMP_LIMIT)
- for (i = 0; i<lA[0].vcount; i++) {
- // block diagonalizer
- cp_fmatrix(P[i].m, lA[i].m);
- inverse_fmatrix(Pinv[i].m, P[i].m);
-
- }
-}
-#if 0
-/*
-// version 1.3
-static int cg_filtered_pre(lfVector *dv, fmatrix3x3 *lA, lfVector *lB, lfVector *z, fmatrix3x3 *S, fmatrix3x3 *P, fmatrix3x3 *Pinv)
-{
- unsigned int numverts = lA[0].vcount, iterations = 0, conjgrad_looplimit=100;
- float delta0 = 0, deltaNew = 0, deltaOld = 0, alpha = 0;
- float conjgrad_epsilon=0.0001; // 0.2 is dt for steps=5
- lfVector *r = create_lfvector(numverts);
- lfVector *p = create_lfvector(numverts);
- lfVector *s = create_lfvector(numverts);
- lfVector *h = create_lfvector(numverts);
-
- BuildPPinv(lA, P, Pinv);
-
- filter(dv, S);
- add_lfvector_lfvector(dv, dv, z, numverts);
-
- mul_bfmatrix_lfvector(r, lA, dv);
- sub_lfvector_lfvector(r, lB, r, numverts);
- filter(r, S);
-
- mul_prevfmatrix_lfvector(p, Pinv, r);
- filter(p, S);
-
- deltaNew = dot_lfvector(r, p, numverts);
-
- delta0 = deltaNew * sqrt(conjgrad_epsilon);
-
- // itstart();
-
- while ((deltaNew > delta0) && (iterations < conjgrad_looplimit))
- {
- iterations++;
-
- mul_bfmatrix_lfvector(s, lA, p);
- filter(s, S);
-
- alpha = deltaNew / dot_lfvector(p, s, numverts);
-
- add_lfvector_lfvectorS(dv, dv, p, alpha, numverts);
-
- add_lfvector_lfvectorS(r, r, s, -alpha, numverts);
-
- mul_prevfmatrix_lfvector(h, Pinv, r);
- filter(h, S);
-
- deltaOld = deltaNew;
-
- deltaNew = dot_lfvector(r, h, numverts);
-
- add_lfvector_lfvectorS(p, h, p, deltaNew / deltaOld, numverts);
-
- filter(p, S);
-
- }
-
- // itend();
- // printf("cg_filtered_pre time: %f\n", (float)itval());
-
- del_lfvector(h);
- del_lfvector(s);
- del_lfvector(p);
- del_lfvector(r);
-
- printf("iterations: %d\n", iterations);
-
- return iterations<conjgrad_looplimit;
-}
-*/
-// version 1.4
-static int cg_filtered_pre(lfVector *dv, fmatrix3x3 *lA, lfVector *lB, lfVector *z, fmatrix3x3 *S, fmatrix3x3 *P, fmatrix3x3 *Pinv, fmatrix3x3 *bigI)
-{
- unsigned int numverts = lA[0].vcount, iterations = 0, conjgrad_looplimit=100;
- float delta0 = 0, deltaNew = 0, deltaOld = 0, alpha = 0, tol = 0;
- lfVector *r = create_lfvector(numverts);
- lfVector *p = create_lfvector(numverts);
- lfVector *s = create_lfvector(numverts);
- lfVector *h = create_lfvector(numverts);
- lfVector *bhat = create_lfvector(numverts);
- lfVector *btemp = create_lfvector(numverts);
-
- BuildPPinv(lA, P, Pinv);
-
- initdiag_bfmatrix(bigI, I);
- sub_bfmatrix_Smatrix(bigI, bigI, S);
-
- // x = Sx_0+(I-S)z
- filter(dv, S);
- add_lfvector_lfvector(dv, dv, z, numverts);
-
- // b_hat = S(b-A(I-S)z)
- mul_bfmatrix_lfvector(r, lA, z);
- mul_bfmatrix_lfvector(bhat, bigI, r);
- sub_lfvector_lfvector(bhat, lB, bhat, numverts);
-
- // r = S(b-Ax)
- mul_bfmatrix_lfvector(r, lA, dv);
- sub_lfvector_lfvector(r, lB, r, numverts);
- filter(r, S);
-
- // p = SP^-1r
- mul_prevfmatrix_lfvector(p, Pinv, r);
- filter(p, S);
-
- // delta0 = bhat^TP^-1bhat
- mul_prevfmatrix_lfvector(btemp, Pinv, bhat);
- delta0 = dot_lfvector(bhat, btemp, numverts);
-
- // deltaNew = r^TP
- deltaNew = dot_lfvector(r, p, numverts);
-
- /*
- filter(dv, S);
- add_lfvector_lfvector(dv, dv, z, numverts);
-
- mul_bfmatrix_lfvector(r, lA, dv);
- sub_lfvector_lfvector(r, lB, r, numverts);
- filter(r, S);
-
- mul_prevfmatrix_lfvector(p, Pinv, r);
- filter(p, S);
-
- deltaNew = dot_lfvector(r, p, numverts);
-
- delta0 = deltaNew * sqrt(conjgrad_epsilon);
- */
-
- // itstart();
-
- tol = (0.01*0.2);
-
- while ((deltaNew > delta0*tol*tol) && (iterations < conjgrad_looplimit))
- {
- iterations++;
-
- mul_bfmatrix_lfvector(s, lA, p);
- filter(s, S);
-
- alpha = deltaNew / dot_lfvector(p, s, numverts);
-
- add_lfvector_lfvectorS(dv, dv, p, alpha, numverts);
-
- add_lfvector_lfvectorS(r, r, s, -alpha, numverts);
-
- mul_prevfmatrix_lfvector(h, Pinv, r);
- filter(h, S);
-
- deltaOld = deltaNew;
-
- deltaNew = dot_lfvector(r, h, numverts);
-
- add_lfvector_lfvectorS(p, h, p, deltaNew / deltaOld, numverts);
-
- filter(p, S);
-
- }
-
- // itend();
- // printf("cg_filtered_pre time: %f\n", (float)itval());
-
- del_lfvector(btemp);
- del_lfvector(bhat);
- del_lfvector(h);
- del_lfvector(s);
- del_lfvector(p);
- del_lfvector(r);
-
- // printf("iterations: %d\n", iterations);
-
- return iterations<conjgrad_looplimit;
-}
-#endif
-
-// outer product is NOT cross product!!!
-DO_INLINE void dfdx_spring_type1(float to[3][3], float extent[3], float length, float L, float dot, float k)
-{
- // dir is unit length direction, rest is spring's restlength, k is spring constant.
- // return (outerprod(dir, dir)*k + (I - outerprod(dir, dir))*(k - ((k*L)/length)));
- float temp[3][3];
- float temp1 = k * (1.0f - (L / length));
-
- mul_fvectorT_fvectorS(temp, extent, extent, 1.0f / dot);
- sub_fmatrix_fmatrix(to, I, temp);
- mul_fmatrix_S(to, temp1);
-
- mul_fvectorT_fvectorS(temp, extent, extent, k/ dot);
- add_fmatrix_fmatrix(to, to, temp);
-
- /*
- mul_fvectorT_fvector(temp, dir, dir);
- sub_fmatrix_fmatrix(to, I, temp);
- mul_fmatrix_S(to, k* (1.0f-(L/length)));
- mul_fmatrix_S(temp, k);
- add_fmatrix_fmatrix(to, temp, to);
- */
-}
-
-DO_INLINE void dfdx_spring_type2(float to[3][3], float dir[3], float length, float L, float k, float cb)
-{
- // return outerprod(dir, dir)*fbstar_jacobi(length, L, k, cb);
- mul_fvectorT_fvectorS(to, dir, dir, fbstar_jacobi(length, L, k, cb));
-}
-
-DO_INLINE void dfdv_damp(float to[3][3], float dir[3], float damping)
-{
- // derivative of force wrt velocity.
- mul_fvectorT_fvectorS(to, dir, dir, damping);
-
-}
-
-DO_INLINE void dfdx_spring(float to[3][3], float dir[3], float length, float L, float k)
-{
- // dir is unit length direction, rest is spring's restlength, k is spring constant.
- //return ( (I-outerprod(dir, dir))*Min(1.0f, rest/length) - I) * -k;
- mul_fvectorT_fvector(to, dir, dir);
- sub_fmatrix_fmatrix(to, I, to);
-
- mul_fmatrix_S(to, (L/length));
- sub_fmatrix_fmatrix(to, to, I);
- mul_fmatrix_S(to, -k);
-}
-
-// unused atm
-DO_INLINE void dfdx_damp(float to[3][3], float dir[3], float length, const float vel[3], float rest, float damping)
-{
- // inner spring damping vel is the relative velocity of the endpoints.
- // return (I-outerprod(dir, dir)) * (-damping * -(dot(dir, vel)/Max(length, rest)));
- mul_fvectorT_fvector(to, dir, dir);
- sub_fmatrix_fmatrix(to, I, to);
- mul_fmatrix_S(to, (-damping * -(dot_v3v3(dir, vel)/MAX2(length, rest))));
-
-}
-
-DO_INLINE void cloth_calc_spring_force(ClothModifierData *clmd, ClothSpring *s, lfVector *UNUSED(lF), lfVector *X, lfVector *V, fmatrix3x3 *UNUSED(dFdV), fmatrix3x3 *UNUSED(dFdX), float time)
-{
- Cloth *cloth = clmd->clothObject;
- ClothVertex *verts = cloth->verts;
- float extent[3];
- float length = 0, dot = 0;
- float dir[3] = {0, 0, 0};
- float vel[3];
- float k = 0.0f;
- float L = s->restlen;
- float cb; /* = clmd->sim_parms->structural; */ /*UNUSED*/
-
- float nullf[3] = {0, 0, 0};
- float stretch_force[3] = {0, 0, 0};
- float bending_force[3] = {0, 0, 0};
- float damping_force[3] = {0, 0, 0};
- float nulldfdx[3][3] = {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}};
-
- float scaling = 0.0;
-
- int no_compress = clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_NO_SPRING_COMPRESS;
-
- copy_v3_v3(s->f, nullf);
- cp_fmatrix(s->dfdx, nulldfdx);
- cp_fmatrix(s->dfdv, nulldfdx);
-
- // calculate elonglation
- sub_v3_v3v3(extent, X[s->kl], X[s->ij]);
- sub_v3_v3v3(vel, V[s->kl], V[s->ij]);
- dot = dot_v3v3(extent, extent);
- length = sqrtf(dot);
-
- s->flags &= ~CLOTH_SPRING_FLAG_NEEDED;
-
- if (length > ALMOST_ZERO) {
- /*
- if (length>L)
- {
- if ((clmd->sim_parms->flags & CSIMSETT_FLAG_TEARING_ENABLED) &&
- ((((length-L)*100.0f/L) > clmd->sim_parms->maxspringlen))) // cut spring!
- {
- s->flags |= CSPRING_FLAG_DEACTIVATE;
- return;
- }
- }
- */
- mul_fvector_S(dir, extent, 1.0f/length);
- }
- else {
- mul_fvector_S(dir, extent, 0.0f);
- }
-
- // calculate force of structural + shear springs
- if ((s->type & CLOTH_SPRING_TYPE_STRUCTURAL) || (s->type & CLOTH_SPRING_TYPE_SHEAR) || (s->type & CLOTH_SPRING_TYPE_SEWING) ) {
- if (length > L || no_compress) {
- s->flags |= CLOTH_SPRING_FLAG_NEEDED;
-
- k = clmd->sim_parms->structural;
-
- scaling = k + s->stiffness * fabsf(clmd->sim_parms->max_struct - k);
-
- k = scaling / (clmd->sim_parms->avg_spring_len + FLT_EPSILON);
-
- // TODO: verify, half verified (couldn't see error)
- if (s->type & CLOTH_SPRING_TYPE_SEWING) {
- // sewing springs usually have a large distance at first so clamp the force so we don't get tunnelling through colission objects
- float force = k*(length-L);
- if (force > clmd->sim_parms->max_sewing) {
- force = clmd->sim_parms->max_sewing;
- }
- mul_fvector_S(stretch_force, dir, force);
- }
- else {
- mul_fvector_S(stretch_force, dir, k * (length - L));
- }
-
- VECADD(s->f, s->f, stretch_force);
-
- // Ascher & Boxman, p.21: Damping only during elonglation
- // something wrong with it...
- mul_fvector_S(damping_force, dir, clmd->sim_parms->Cdis * dot_v3v3(vel, dir));
- VECADD(s->f, s->f, damping_force);
-
- /* VERIFIED */
- dfdx_spring(s->dfdx, dir, length, L, k);
-
- /* VERIFIED */
- dfdv_damp(s->dfdv, dir, clmd->sim_parms->Cdis);
-
- }
- }
- else if (s->type & CLOTH_SPRING_TYPE_GOAL) {
- float tvect[3];
-
- s->flags |= CLOTH_SPRING_FLAG_NEEDED;
-
- // current_position = xold + t * (newposition - xold)
- sub_v3_v3v3(tvect, verts[s->ij].xconst, verts[s->ij].xold);
- mul_fvector_S(tvect, tvect, time);
- VECADD(tvect, tvect, verts[s->ij].xold);
-
- sub_v3_v3v3(extent, X[s->ij], tvect);
-
- // SEE MSG BELOW (these are UNUSED)
- // dot = dot_v3v3(extent, extent);
- // length = sqrt(dot);
-
- k = clmd->sim_parms->goalspring;
-
- 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);
-
- VECADDS(s->f, s->f, extent, -k);
-
- mul_fvector_S(damping_force, dir, clmd->sim_parms->goalfrict * 0.01f * dot_v3v3(vel, dir));
- VECADD(s->f, s->f, damping_force);
-
- // HERE IS THE PROBLEM!!!!
- // dfdx_spring(s->dfdx, dir, length, 0.0, k);
- // dfdv_damp(s->dfdv, dir, MIN2(1.0, (clmd->sim_parms->goalfrict/100.0)));
- }
- else { /* calculate force of bending springs */
- if (length < L) {
- s->flags |= CLOTH_SPRING_FLAG_NEEDED;
-
- k = clmd->sim_parms->bending;
-
- 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));
- VECADD(s->f, s->f, bending_force);
-
- dfdx_spring_type2(s->dfdx, dir, length, L, k, cb);
- }
- }
-}
-
-DO_INLINE void cloth_apply_spring_force(ClothModifierData *UNUSED(clmd), ClothSpring *s, lfVector *lF, lfVector *UNUSED(X), lfVector *UNUSED(V), fmatrix3x3 *dFdV, fmatrix3x3 *dFdX)
-{
- if (s->flags & CLOTH_SPRING_FLAG_NEEDED) {
- if (!(s->type & CLOTH_SPRING_TYPE_BENDING)) {
- sub_fmatrix_fmatrix(dFdV[s->ij].m, dFdV[s->ij].m, s->dfdv);
- sub_fmatrix_fmatrix(dFdV[s->kl].m, dFdV[s->kl].m, s->dfdv);
- add_fmatrix_fmatrix(dFdV[s->matrix_index].m, dFdV[s->matrix_index].m, s->dfdv);
- }
-
- VECADD(lF[s->ij], lF[s->ij], s->f);
-
- if (!(s->type & CLOTH_SPRING_TYPE_GOAL))
- sub_v3_v3v3(lF[s->kl], lF[s->kl], s->f);
-
- sub_fmatrix_fmatrix(dFdX[s->kl].m, dFdX[s->kl].m, s->dfdx);
- sub_fmatrix_fmatrix(dFdX[s->ij].m, dFdX[s->ij].m, s->dfdx);
- add_fmatrix_fmatrix(dFdX[s->matrix_index].m, dFdX[s->matrix_index].m, s->dfdx);
- }
-}
-
-
-static void CalcFloat( float *v1, float *v2, float *v3, float *n)
-{
- float n1[3], n2[3];
-
- n1[0] = v1[0]-v2[0];
- n2[0] = v2[0]-v3[0];
- n1[1] = v1[1]-v2[1];
- n2[1] = v2[1]-v3[1];
- n1[2] = v1[2]-v2[2];
- n2[2] = v2[2]-v3[2];
- n[0] = n1[1]*n2[2]-n1[2]*n2[1];
- n[1] = n1[2]*n2[0]-n1[0]*n2[2];
- n[2] = n1[0]*n2[1]-n1[1]*n2[0];
-}
-
-static void CalcFloat4( float *v1, float *v2, float *v3, float *v4, float *n)
-{
- /* real cross! */
- float n1[3], n2[3];
-
- n1[0] = v1[0]-v3[0];
- n1[1] = v1[1]-v3[1];
- n1[2] = v1[2]-v3[2];
-
- n2[0] = v2[0]-v4[0];
- n2[1] = v2[1]-v4[1];
- n2[2] = v2[2]-v4[2];
-
- n[0] = n1[1]*n2[2]-n1[2]*n2[1];
- n[1] = n1[2]*n2[0]-n1[0]*n2[2];
- n[2] = n1[0]*n2[1]-n1[1]*n2[0];
-}
-
-static float calculateVertexWindForce(const float wind[3], const float vertexnormal[3])
-{
- return dot_v3v3(wind, vertexnormal);
-}
-
-typedef struct HairGridVert {
- float velocity[3];
- float density;
-} HairGridVert;
-#define HAIR_GRID_INDEX(vec, min, max, axis) (int)((vec[axis] - min[axis]) / (max[axis] - min[axis]) * 9.99f)
-/* Smoothing of hair velocities:
- * adapted from
- * Volumetric Methods for Simulation and Rendering of Hair
- * by Lena Petrovic, Mark Henne and John Anderson
- * Pixar Technical Memo #06-08, Pixar Animation Studios
- */
-static void hair_velocity_smoothing(ClothModifierData *clmd, lfVector *lF, lfVector *lX, lfVector *lV, unsigned int numverts)
-{
- /* TODO: This is an initial implementation and should be made much better in due time.
- * What should at least be implemented is a grid size parameter and a smoothing kernel
- * for bigger grids.
- */
-
- /* 10x10x10 grid gives nice initial results */
- HairGridVert grid[10][10][10];
- HairGridVert colg[10][10][10];
- ListBase *colliders = get_collider_cache(clmd->scene, NULL, NULL);
- ColliderCache *col = NULL;
- float gmin[3], gmax[3], density;
- /* 2.0f is an experimental value that seems to give good results */
- float smoothfac = 2.0f * clmd->sim_parms->velocity_smooth;
- float collfac = 2.0f * clmd->sim_parms->collider_friction;
- unsigned int v = 0;
- int i = 0;
- int j = 0;
- int k = 0;
-
- INIT_MINMAX(gmin, gmax);
-
- for (i = 0; i < numverts; i++)
- DO_MINMAX(lX[i], gmin, gmax);
-
- /* initialize grid */
- for (i = 0; i < 10; i++) {
- for (j = 0; j < 10; j++) {
- for (k = 0; k < 10; k++) {
- grid[i][j][k].velocity[0] = 0.0f;
- grid[i][j][k].velocity[1] = 0.0f;
- grid[i][j][k].velocity[2] = 0.0f;
- grid[i][j][k].density = 0.0f;
-
- colg[i][j][k].velocity[0] = 0.0f;
- colg[i][j][k].velocity[1] = 0.0f;
- colg[i][j][k].velocity[2] = 0.0f;
- colg[i][j][k].density = 0.0f;
- }
- }
- }
-
- /* gather velocities & density */
- if (smoothfac > 0.0f) for (v = 0; v < numverts; v++) {
- i = HAIR_GRID_INDEX(lX[v], gmin, gmax, 0);
- j = HAIR_GRID_INDEX(lX[v], gmin, gmax, 1);
- k = HAIR_GRID_INDEX(lX[v], gmin, gmax, 2);
- if (i < 0 || j < 0 || k < 0 || i >= 10 || j >= 10 || k >= 10)
- continue;
-
- grid[i][j][k].velocity[0] += lV[v][0];
- grid[i][j][k].velocity[1] += lV[v][1];
- grid[i][j][k].velocity[2] += lV[v][2];
- grid[i][j][k].density += 1.0f;
- }
-
- /* gather colliders */
- if (colliders && collfac > 0.0f) for (col = colliders->first; col; col = col->next) {
- MVert *loc0 = col->collmd->x;
- MVert *loc1 = col->collmd->xnew;
- float vel[3];
-
- for (v=0; v<col->collmd->numverts; v++, loc0++, loc1++) {
- i = HAIR_GRID_INDEX(loc1->co, gmin, gmax, 0);
-
- if (i>=0 && i<10) {
- j = HAIR_GRID_INDEX(loc1->co, gmin, gmax, 1);
-
- if (j>=0 && j<10) {
- k = HAIR_GRID_INDEX(loc1->co, gmin, gmax, 2);
-
- if (k>=0 && k<10) {
- sub_v3_v3v3(vel, loc1->co, loc0->co);
-
- colg[i][j][k].velocity[0] += vel[0];
- colg[i][j][k].velocity[1] += vel[1];
- colg[i][j][k].velocity[2] += vel[2];
- colg[i][j][k].density += 1.0f;
- }
- }
- }
- }
- }
-
-
- /* divide velocity with density */
- for (i = 0; i < 10; i++) {
- for (j = 0; j < 10; j++) {
- for (k = 0; k < 10; k++) {
- density = grid[i][j][k].density;
- if (density > 0.0f) {
- grid[i][j][k].velocity[0] /= density;
- grid[i][j][k].velocity[1] /= density;
- grid[i][j][k].velocity[2] /= density;
- }
-
- density = colg[i][j][k].density;
- if (density > 0.0f) {
- colg[i][j][k].velocity[0] /= density;
- colg[i][j][k].velocity[1] /= density;
- colg[i][j][k].velocity[2] /= density;
- }
- }
- }
- }
-
- /* calculate forces */
- for (v = 0; v < numverts; v++) {
- i = HAIR_GRID_INDEX(lX[v], gmin, gmax, 0);
- j = HAIR_GRID_INDEX(lX[v], gmin, gmax, 1);
- k = HAIR_GRID_INDEX(lX[v], gmin, gmax, 2);
- if (i < 0 || j < 0 || k < 0 || i >= 10 || j >= 10 || k >= 10)
- continue;
-
- lF[v][0] += smoothfac * (grid[i][j][k].velocity[0] - lV[v][0]);
- lF[v][1] += smoothfac * (grid[i][j][k].velocity[1] - lV[v][1]);
- lF[v][2] += smoothfac * (grid[i][j][k].velocity[2] - lV[v][2]);
-
- if (colg[i][j][k].density > 0.0f) {
- lF[v][0] += collfac * (colg[i][j][k].velocity[0] - lV[v][0]);
- lF[v][1] += collfac * (colg[i][j][k].velocity[1] - lV[v][1]);
- lF[v][2] += collfac * (colg[i][j][k].velocity[2] - lV[v][2]);
- }
- }
-
- free_collider_cache(&colliders);
-}
-
-static void cloth_calc_force(ClothModifierData *clmd, float UNUSED(frame), lfVector *lF, lfVector *lX, lfVector *lV, fmatrix3x3 *dFdV, fmatrix3x3 *dFdX, ListBase *effectors, float time, fmatrix3x3 *M)
-{
- /* Collect forces and derivatives: F, dFdX, dFdV */
- Cloth *cloth = clmd->clothObject;
- unsigned int i = 0;
- float spring_air = clmd->sim_parms->Cvi * 0.01f; /* viscosity of air scaled in percent */
- float gravity[3] = {0.0f, 0.0f, 0.0f};
- float tm2[3][3] = {{0}};
- MFace *mfaces = cloth->mfaces;
- unsigned int numverts = cloth->numverts;
- LinkNode *search;
- lfVector *winvec;
- EffectedPoint epoint;
-
- tm2[0][0] = tm2[1][1] = tm2[2][2] = -spring_air;
-
- /* global acceleration (gravitation) */
- if (clmd->scene->physics_settings.flag & PHYS_GLOBAL_GRAVITY) {
- copy_v3_v3(gravity, clmd->scene->physics_settings.gravity);
- mul_fvector_S(gravity, gravity, 0.001f * clmd->sim_parms->effector_weights->global_gravity); /* scale gravity force */
- }
-
- /* set dFdX jacobi matrix to zero */
- init_bfmatrix(dFdX, ZERO);
- /* set dFdX jacobi matrix diagonal entries to -spring_air */
- initdiag_bfmatrix(dFdV, tm2);
-
- init_lfvector(lF, gravity, numverts);
-
- if (clmd->sim_parms->velocity_smooth > 0.0f || clmd->sim_parms->collider_friction > 0.0f)
- hair_velocity_smoothing(clmd, lF, lX, lV, numverts);
-
- /* multiply lF with mass matrix
- * force = mass * acceleration (in this case: gravity)
- */
- for (i = 0; i < numverts; i++) {
- float temp[3];
- copy_v3_v3(temp, lF[i]);
- mul_fmatrix_fvector(lF[i], M[i].m, temp);
- }
-
- submul_lfvectorS(lF, lV, spring_air, numverts);
-
- /* handle external forces like wind */
- if (effectors) {
- // 0 = force, 1 = normalized force
- winvec = create_lfvector(cloth->numverts);
-
- if (!winvec)
- printf("winvec: out of memory in implicit.c\n");
-
- // precalculate wind forces
- for (i = 0; i < cloth->numverts; i++) {
- pd_point_from_loc(clmd->scene, (float*)lX[i], (float*)lV[i], i, &epoint);
- pdDoEffectors(effectors, NULL, clmd->sim_parms->effector_weights, &epoint, winvec[i], NULL);
- }
-
- for (i = 0; i < cloth->numfaces; i++) {
- float trinormal[3] = {0, 0, 0}; // normalized triangle normal
- float triunnormal[3] = {0, 0, 0}; // not-normalized-triangle normal
- float tmp[3] = {0, 0, 0};
- float factor = (mfaces[i].v4) ? 0.25 : 1.0 / 3.0;
- factor *= 0.02f;
-
- // calculate face normal
- if (mfaces[i].v4)
- CalcFloat4(lX[mfaces[i].v1], lX[mfaces[i].v2], lX[mfaces[i].v3], lX[mfaces[i].v4], triunnormal);
- else
- CalcFloat(lX[mfaces[i].v1], lX[mfaces[i].v2], lX[mfaces[i].v3], triunnormal);
-
- normalize_v3_v3(trinormal, triunnormal);
-
- // add wind from v1
- copy_v3_v3(tmp, trinormal);
- mul_v3_fl(tmp, calculateVertexWindForce(winvec[mfaces[i].v1], triunnormal));
- VECADDS(lF[mfaces[i].v1], lF[mfaces[i].v1], tmp, factor);
-
- // add wind from v2
- copy_v3_v3(tmp, trinormal);
- mul_v3_fl(tmp, calculateVertexWindForce(winvec[mfaces[i].v2], triunnormal));
- VECADDS(lF[mfaces[i].v2], lF[mfaces[i].v2], tmp, factor);
-
- // add wind from v3
- copy_v3_v3(tmp, trinormal);
- mul_v3_fl(tmp, calculateVertexWindForce(winvec[mfaces[i].v3], triunnormal));
- VECADDS(lF[mfaces[i].v3], lF[mfaces[i].v3], tmp, factor);
-
- // add wind from v4
- if (mfaces[i].v4) {
- copy_v3_v3(tmp, trinormal);
- mul_v3_fl(tmp, calculateVertexWindForce(winvec[mfaces[i].v4], triunnormal));
- VECADDS(lF[mfaces[i].v4], lF[mfaces[i].v4], tmp, factor);
- }
- }
-
- /* Hair has only edges */
- if (cloth->numfaces == 0) {
- ClothSpring *spring;
- float edgevec[3] = {0, 0, 0}; //edge vector
- float edgeunnormal[3] = {0, 0, 0}; // not-normalized-edge normal
- float tmp[3] = {0, 0, 0};
- float factor = 0.01;
-
- search = cloth->springs;
- while (search) {
- spring = search->link;
-
- if (spring->type == CLOTH_SPRING_TYPE_STRUCTURAL) {
- sub_v3_v3v3(edgevec, (float*)lX[spring->ij], (float*)lX[spring->kl]);
-
- project_v3_v3v3(tmp, winvec[spring->ij], edgevec);
- sub_v3_v3v3(edgeunnormal, winvec[spring->ij], tmp);
- /* hair doesn't stretch too much so we can use restlen pretty safely */
- VECADDS(lF[spring->ij], lF[spring->ij], edgeunnormal, spring->restlen * factor);
-
- project_v3_v3v3(tmp, winvec[spring->kl], edgevec);
- sub_v3_v3v3(edgeunnormal, winvec[spring->kl], tmp);
- VECADDS(lF[spring->kl], lF[spring->kl], edgeunnormal, spring->restlen * factor);
- }
-
- search = search->next;
- }
- }
-
- del_lfvector(winvec);
- }
-
- // calculate spring forces
- search = cloth->springs;
- while (search) {
- // only handle active springs
- ClothSpring *spring = search->link;
- if (!(spring->flags & CLOTH_SPRING_FLAG_DEACTIVATE))
- cloth_calc_spring_force(clmd, search->link, lF, lX, lV, dFdV, dFdX, time);
-
- search = search->next;
- }
-
- // apply spring forces
- search = cloth->springs;
- while (search) {
- // only handle active springs
- ClothSpring *spring = search->link;
- if (!(spring->flags & CLOTH_SPRING_FLAG_DEACTIVATE))
- cloth_apply_spring_force(clmd, search->link, lF, lX, lV, dFdV, dFdX);
- search = search->next;
- }
- // printf("\n");
-}
-
-static void simulate_implicit_euler(lfVector *Vnew, lfVector *UNUSED(lX), lfVector *lV, lfVector *lF, fmatrix3x3 *dFdV, fmatrix3x3 *dFdX, float dt, fmatrix3x3 *A, lfVector *B, lfVector *dV, fmatrix3x3 *S, lfVector *z, lfVector *olddV, fmatrix3x3 *UNUSED(P), fmatrix3x3 *UNUSED(Pinv), fmatrix3x3 *M, fmatrix3x3 *UNUSED(bigI))
-{
- unsigned int numverts = dFdV[0].vcount;
-
- lfVector *dFdXmV = create_lfvector(numverts);
- zero_lfvector(dV, numverts);
-
- cp_bfmatrix(A, M);
-
- subadd_bfmatrixS_bfmatrixS(A, dFdV, dt, dFdX, (dt*dt));
-
- mul_bfmatrix_lfvector(dFdXmV, dFdX, lV);
-
- add_lfvectorS_lfvectorS(B, lF, dt, dFdXmV, (dt*dt), numverts);
-
- // itstart();
-
- cg_filtered(dV, A, B, z, S); /* conjugate gradient algorithm to solve Ax=b */
- // cg_filtered_pre(dV, A, B, z, S, P, Pinv, bigI);
-
- // itend();
- // printf("cg_filtered calc time: %f\n", (float)itval());
-
- cp_lfvector(olddV, dV, numverts);
-
- // advance velocities
- add_lfvector_lfvector(Vnew, lV, dV, numverts);
-
-
- del_lfvector(dFdXmV);
-}
-
-/* computes where the cloth would be if it were subject to perfectly stiff edges
- * (edge distance constraints) in a lagrangian solver. then add forces to help
- * guide the implicit solver to that state. this function is called after
- * collisions*/
-static int UNUSED_FUNCTION(cloth_calc_helper_forces)(Object *UNUSED(ob), ClothModifierData *clmd, float (*initial_cos)[3], float UNUSED(step), float dt)
-{
- Cloth *cloth= clmd->clothObject;
- float (*cos)[3] = MEM_callocN(sizeof(float)*3*cloth->numverts, "cos cloth_calc_helper_forces");
- float *masses = MEM_callocN(sizeof(float)*cloth->numverts, "cos cloth_calc_helper_forces");
- LinkNode *node;
- ClothSpring *spring;
- ClothVertex *cv;
- int i, steps;
-
- cv = cloth->verts;
- for (i=0; i<cloth->numverts; i++, cv++) {
- copy_v3_v3(cos[i], cv->tx);
-
- if (cv->goal == 1.0f || len_squared_v3v3(initial_cos[i], cv->tx) != 0.0f) {
- masses[i] = 1e+10;
- }
- else {
- masses[i] = cv->mass;
- }
- }
-
- steps = 55;
- for (i=0; i<steps; i++) {
- for (node=cloth->springs; node; node=node->next) {
- /* ClothVertex *cv1, *cv2; */ /* UNUSED */
- int v1, v2;
- float len, c, l, vec[3];
-
- spring = node->link;
- if (spring->type != CLOTH_SPRING_TYPE_STRUCTURAL && spring->type != CLOTH_SPRING_TYPE_SHEAR)
- continue;
-
- v1 = spring->ij; v2 = spring->kl;
- /* cv1 = cloth->verts + v1; */ /* UNUSED */
- /* cv2 = cloth->verts + v2; */ /* UNUSED */
- len = len_v3v3(cos[v1], cos[v2]);
-
- sub_v3_v3v3(vec, cos[v1], cos[v2]);
- normalize_v3(vec);
-
- c = (len - spring->restlen);
- if (c == 0.0f)
- continue;
-
- l = c / ((1.0f / masses[v1]) + (1.0f / masses[v2]));
-
- mul_v3_fl(vec, -(1.0f / masses[v1]) * l);
- add_v3_v3(cos[v1], vec);
-
- sub_v3_v3v3(vec, cos[v2], cos[v1]);
- normalize_v3(vec);
-
- mul_v3_fl(vec, -(1.0f / masses[v2]) * l);
- add_v3_v3(cos[v2], vec);
- }
- }
-
- cv = cloth->verts;
- for (i=0; i<cloth->numverts; i++, cv++) {
- float vec[3];
-
- /*compute forces*/
- sub_v3_v3v3(vec, cos[i], cv->tx);
- mul_v3_fl(vec, cv->mass*dt*20.0f);
- add_v3_v3(cv->tv, vec);
- //copy_v3_v3(cv->tx, cos[i]);
- }
-
- MEM_freeN(cos);
- MEM_freeN(masses);
-
- return 1;
-}
-
-int implicit_solver(Object *ob, float frame, ClothModifierData *clmd, ListBase *effectors)
-{
- unsigned int i=0;
- float step=0.0f, tf=clmd->sim_parms->timescale;
- Cloth *cloth = clmd->clothObject;
- ClothVertex *verts = cloth->verts, *cv;
- unsigned int numverts = cloth->numverts;
- float dt = clmd->sim_parms->timescale / clmd->sim_parms->stepsPerFrame;
- float spf = (float)clmd->sim_parms->stepsPerFrame / clmd->sim_parms->timescale;
- float (*initial_cos)[3] = MEM_callocN(sizeof(float)*3*cloth->numverts, "initial_cos implicit.c");
- Implicit_Data *id = cloth->implicit;
- int do_extra_solve;
-
- if (clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL) { /* do goal stuff */
-
- /* Update vertex constraints for pinned vertices */
- update_matrixS(verts, cloth->numverts, id->S);
-
- for (i = 0; i < numverts; i++) {
- // update velocities with constrained velocities from pinned verts
- if (verts [i].flags & CLOTH_VERT_FLAG_PINNED) {
- sub_v3_v3v3(id->V[i], verts[i].xconst, verts[i].xold);
- // mul_v3_fl(id->V[i], clmd->sim_parms->stepsPerFrame);
- }
- }
- }
-
- while (step < tf) {
- // damping velocity for artistic reasons
- mul_lfvectorS(id->V, id->V, clmd->sim_parms->vel_damping, numverts);
-
- // calculate forces
- cloth_calc_force(clmd, frame, id->F, id->X, id->V, id->dFdV, id->dFdX, effectors, step, id->M);
-
- // calculate new velocity
- simulate_implicit_euler(id->Vnew, id->X, id->V, id->F, id->dFdV, id->dFdX, dt, id->A, id->B, id->dV, id->S, id->z, id->olddV, id->P, id->Pinv, id->M, id->bigI);
-
- // advance positions
- add_lfvector_lfvectorS(id->Xnew, id->X, id->Vnew, dt, numverts);
-
- /* move pinned verts to correct position */
- for (i = 0; i < numverts; i++) {
- if (clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL) {
- if (verts[i].flags & CLOTH_VERT_FLAG_PINNED) {
- float tvect[3] = {0.0f, 0.0f, 0.0f};
- sub_v3_v3v3(tvect, verts[i].xconst, verts[i].xold);
- mul_fvector_S(tvect, tvect, step+dt);
- VECADD(tvect, tvect, verts[i].xold);
- copy_v3_v3(id->Xnew[i], tvect);
- }
- }
-
- copy_v3_v3(verts[i].txold, id->X[i]);
- }
-
- if (clmd->coll_parms->flags & CLOTH_COLLSETTINGS_FLAG_ENABLED && clmd->clothObject->bvhtree) {
- // collisions
- // itstart();
-
- // update verts to current positions
- for (i = 0; i < numverts; i++) {
- copy_v3_v3(verts[i].tx, id->Xnew[i]);
-
- sub_v3_v3v3(verts[i].tv, verts[i].tx, verts[i].txold);
- copy_v3_v3(verts[i].v, verts[i].tv);
- }
-
- for (i=0, cv=cloth->verts; i<cloth->numverts; i++, cv++) {
- copy_v3_v3(initial_cos[i], cv->tx);
- }
-
- // call collision function
- // TODO: check if "step" or "step+dt" is correct - dg
- do_extra_solve = cloth_bvh_objcollision(ob, clmd, step/clmd->sim_parms->timescale, dt/clmd->sim_parms->timescale);
-
- // copy corrected positions back to simulation
- for (i = 0; i < numverts; i++) {
- // correct velocity again, just to be sure we had to change it due to adaptive collisions
- sub_v3_v3v3(verts[i].tv, verts[i].tx, id->X[i]);
- }
-
- //if (do_extra_solve)
- // cloth_calc_helper_forces(ob, clmd, initial_cos, step/clmd->sim_parms->timescale, dt/clmd->sim_parms->timescale);
-
- if (do_extra_solve) {
- for (i = 0; i < numverts; i++) {
- if ((clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL) && (verts [i].flags & CLOTH_VERT_FLAG_PINNED))
- continue;
-
- copy_v3_v3(id->Xnew[i], verts[i].tx);
- copy_v3_v3(id->Vnew[i], verts[i].tv);
- mul_v3_fl(id->Vnew[i], spf);
- }
- }
-
- // X = Xnew;
- cp_lfvector(id->X, id->Xnew, numverts);
-
- // if there were collisions, advance the velocity from v_n+1/2 to v_n+1
-
- if (do_extra_solve) {
- // V = Vnew;
- cp_lfvector(id->V, id->Vnew, numverts);
-
- // calculate
- cloth_calc_force(clmd, frame, id->F, id->X, id->V, id->dFdV, id->dFdX, effectors, step+dt, id->M);
-
- simulate_implicit_euler(id->Vnew, id->X, id->V, id->F, id->dFdV, id->dFdX, dt / 2.0f, id->A, id->B, id->dV, id->S, id->z, id->olddV, id->P, id->Pinv, id->M, id->bigI);
- }
- }
- else {
- // X = Xnew;
- cp_lfvector(id->X, id->Xnew, numverts);
- }
-
- // itend();
- // printf("collision time: %f\n", (float)itval());
-
- // V = Vnew;
- cp_lfvector(id->V, id->Vnew, numverts);
-
- step += dt;
- }
-
- for (i = 0; i < numverts; i++) {
- if ((clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL) && (verts [i].flags & CLOTH_VERT_FLAG_PINNED)) {
- copy_v3_v3(verts[i].txold, verts[i].xconst); // TODO: test --> should be .x
- copy_v3_v3(verts[i].x, verts[i].xconst);
- copy_v3_v3(verts[i].v, id->V[i]);
- }
- else {
- copy_v3_v3(verts[i].txold, id->X[i]);
- copy_v3_v3(verts[i].x, id->X[i]);
- copy_v3_v3(verts[i].v, id->V[i]);
- }
- }
-
- MEM_freeN(initial_cos);
-
- return 1;
-}
-
-void implicit_set_positions(ClothModifierData *clmd)
-{
- Cloth *cloth = clmd->clothObject;
- ClothVertex *verts = cloth->verts;
- unsigned int numverts = cloth->numverts, i;
- Implicit_Data *id = cloth->implicit;
-
- for (i = 0; i < numverts; i++) {
- copy_v3_v3(id->X[i], verts[i].x);
- copy_v3_v3(id->V[i], verts[i].v);
- }
- if (G.debug_value > 0)
- printf("implicit_set_positions\n");
-}
-
diff --git a/source/blender/blenkernel/intern/ipo.c b/source/blender/blenkernel/intern/ipo.c
index 51cf26063c7..0c3fd48628f 100644
--- a/source/blender/blenkernel/intern/ipo.c
+++ b/source/blender/blenkernel/intern/ipo.c
@@ -64,7 +64,7 @@
#include "BLI_dynstr.h"
#include "BLI_utildefines.h"
-#include "BLF_translation.h"
+#include "BLT_translation.h"
#include "BKE_ipo.h"
#include "BKE_animsys.h"
@@ -161,21 +161,24 @@ static AdrBit2Path ma_mode_bits[] = {
{ \
*tot = sizeof(items) / sizeof(AdrBit2Path); \
return items; \
- }
+ } (void)0
/* This function checks if a Blocktype+Adrcode combo, returning a mapping table */
static AdrBit2Path *adrcode_bitmaps_to_paths(int blocktype, int adrcode, int *tot)
{
/* Object layers */
- if ((blocktype == ID_OB) && (adrcode == OB_LAY))
- RET_ABP(ob_layer_bits)
- else if ((blocktype == ID_MA) && (adrcode == MA_MODE))
- RET_ABP(ma_mode_bits)
+ if ((blocktype == ID_OB) && (adrcode == OB_LAY)) {
+ RET_ABP(ob_layer_bits);
+ }
+ else if ((blocktype == ID_MA) && (adrcode == MA_MODE)) {
+ RET_ABP(ma_mode_bits);
+ }
// XXX TODO: add other types...
/* Normal curve */
return NULL;
}
+#undef RET_ABP
/* *************************************************** */
/* ADRCODE to RNA-Path Conversion Code - Standard */
@@ -919,11 +922,11 @@ static char *get_rna_access(int blocktype, int adrcode, char actname[], char con
BLI_snprintf(buf, sizeof(buf), "pose.bones[\"%s\"].constraints[\"%s\"]", actname, constname);
}
else if (actname && actname[0]) {
- if ((blocktype == ID_OB) && strcmp(actname, "Object") == 0) {
+ if ((blocktype == ID_OB) && STREQ(actname, "Object")) {
/* Actionified "Object" IPO's... no extra path stuff needed */
buf[0] = '\0'; /* empty string */
}
- else if ((blocktype == ID_KE) && strcmp(actname, "Shape") == 0) {
+ else if ((blocktype == ID_KE) && STREQ(actname, "Shape")) {
/* Actionified "Shape" IPO's - these are forced onto object level via the action container there... */
strcpy(buf, "data.shape_keys");
}
@@ -1323,7 +1326,7 @@ static void icu_to_fcurves(ID *id, ListBase *groups, ListBase *list, IpoCurve *i
* - we now need as 'frames'
*/
if ( (id) && (icu->blocktype == GS(id->name)) &&
- (fcu->rna_path && strcmp(fcu->rna_path, "eval_time") == 0) )
+ (fcu->rna_path && STREQ(fcu->rna_path, "eval_time")) )
{
Curve *cu = (Curve *)id;
@@ -1400,9 +1403,9 @@ static void ipo_to_animato(ID *id, Ipo *ipo, char actname[], char constname[], S
* F-Curves for bones). This may be added later... for now let's just dump without them...
*/
if (actname) {
- if ((ipo->blocktype == ID_OB) && (strcmp(actname, "Object") == 0))
+ if ((ipo->blocktype == ID_OB) && STREQ(actname, "Object"))
actname = NULL;
- else if ((ipo->blocktype == ID_OB) && (strcmp(actname, "Shape") == 0))
+ else if ((ipo->blocktype == ID_OB) && STREQ(actname, "Shape"))
actname = NULL;
}
@@ -1523,7 +1526,7 @@ static void ipo_to_animdata(ID *id, Ipo *ipo, char actname[], char constname[],
if (G.debug & G_DEBUG) {
printf("ipo to animdata - ID:%s, IPO:%s, actname:%s constname:%s seqname:%s curves:%d\n",
id->name + 2, ipo->id.name + 2, (actname) ? actname : "<None>", (constname) ? constname : "<None>", (seq) ? (seq->name + 2) : "<None>",
- BLI_countlist(&ipo->curve));
+ BLI_listbase_count(&ipo->curve));
}
/* Convert curves to animato system (separated into separate lists of F-Curves for animation and drivers),
@@ -1648,6 +1651,9 @@ static void nlastrips_to_animdata(ID *id, ListBase *strips)
nlt = add_nlatrack(adt, NULL);
BKE_nlatrack_add_strip(nlt, strip);
}
+
+ /* ensure that strip has a name */
+ BKE_nlastrip_validate_name(adt, strip);
}
/* modifiers */
@@ -1706,7 +1712,7 @@ void do_versions_ipos_to_animato(Main *main)
/* check if object has any animation data */
if (ob->nlastrips.first) {
/* Add AnimData block */
- BKE_id_add_animdata(id);
+ BKE_animdata_add_id(id);
/* IPO first to take into any non-NLA'd Object Animation */
if (ob->ipo) {
@@ -1729,7 +1735,7 @@ void do_versions_ipos_to_animato(Main *main)
}
else if ((ob->ipo) || (ob->action)) {
/* Add AnimData block */
- AnimData *adt = BKE_id_add_animdata(id);
+ AnimData *adt = BKE_animdata_add_id(id);
/* Action first - so that Action name get conserved */
if (ob->action) {
@@ -1770,7 +1776,7 @@ void do_versions_ipos_to_animato(Main *main)
/* check PoseChannels for constraints with local data */
if (ob->pose) {
/* Verify if there's AnimData block */
- BKE_id_add_animdata(id);
+ BKE_animdata_add_id(id);
for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
for (con = pchan->constraints.first; con; con = con->next) {
@@ -1796,7 +1802,7 @@ void do_versions_ipos_to_animato(Main *main)
*/
if (con->ipo) {
/* Verify if there's AnimData block, just in case */
- BKE_id_add_animdata(id);
+ BKE_animdata_add_id(id);
/* although this was the constraint's local IPO, we still need to provide con
* so that drivers can be added properly...
@@ -1813,7 +1819,7 @@ void do_versions_ipos_to_animato(Main *main)
/* check constraint channels - we need to remove them anyway... */
if (ob->constraintChannels.first) {
/* Verify if there's AnimData block */
- BKE_id_add_animdata(id);
+ BKE_animdata_add_id(id);
for (conchan = ob->constraintChannels.first; conchan; conchan = conchann) {
/* get pointer to next Constraint Channel */
@@ -1851,7 +1857,7 @@ void do_versions_ipos_to_animato(Main *main)
*/
if (key->ipo) {
/* Add AnimData block */
- AnimData *adt = BKE_id_add_animdata(id);
+ AnimData *adt = BKE_animdata_add_id(id);
/* Convert Shapekey data... */
ipo_to_animdata(id, key->ipo, NULL, NULL, NULL);
@@ -1873,7 +1879,7 @@ void do_versions_ipos_to_animato(Main *main)
/* we're only interested in the IPO */
if (ma->ipo) {
/* Add AnimData block */
- AnimData *adt = BKE_id_add_animdata(id);
+ AnimData *adt = BKE_animdata_add_id(id);
/* Convert Material data... */
ipo_to_animdata(id, ma->ipo, NULL, NULL, NULL);
@@ -1895,7 +1901,7 @@ void do_versions_ipos_to_animato(Main *main)
/* we're only interested in the IPO */
if (wo->ipo) {
/* Add AnimData block */
- AnimData *adt = BKE_id_add_animdata(id);
+ AnimData *adt = BKE_animdata_add_id(id);
/* Convert World data... */
ipo_to_animdata(id, wo->ipo, NULL, NULL, NULL);
@@ -1915,7 +1921,7 @@ void do_versions_ipos_to_animato(Main *main)
if (ed && ed->seqbasep) {
Sequence *seq;
- AnimData *adt = BKE_id_add_animdata(id);
+ AnimData *adt = BKE_animdata_add_id(id);
SEQ_BEGIN(ed, seq)
{
@@ -1971,7 +1977,7 @@ void do_versions_ipos_to_animato(Main *main)
/* we're only interested in the IPO */
if (te->ipo) {
/* Add AnimData block */
- AnimData *adt = BKE_id_add_animdata(id);
+ AnimData *adt = BKE_animdata_add_id(id);
/* Convert Texture data... */
ipo_to_animdata(id, te->ipo, NULL, NULL, NULL);
@@ -1993,7 +1999,7 @@ void do_versions_ipos_to_animato(Main *main)
/* we're only interested in the IPO */
if (ca->ipo) {
/* Add AnimData block */
- AnimData *adt = BKE_id_add_animdata(id);
+ AnimData *adt = BKE_animdata_add_id(id);
/* Convert Camera data... */
ipo_to_animdata(id, ca->ipo, NULL, NULL, NULL);
@@ -2015,7 +2021,7 @@ void do_versions_ipos_to_animato(Main *main)
/* we're only interested in the IPO */
if (la->ipo) {
/* Add AnimData block */
- AnimData *adt = BKE_id_add_animdata(id);
+ AnimData *adt = BKE_animdata_add_id(id);
/* Convert Lamp data... */
ipo_to_animdata(id, la->ipo, NULL, NULL, NULL);
@@ -2037,7 +2043,7 @@ void do_versions_ipos_to_animato(Main *main)
/* we're only interested in the IPO */
if (cu->ipo) {
/* Add AnimData block */
- AnimData *adt = BKE_id_add_animdata(id);
+ AnimData *adt = BKE_animdata_add_id(id);
/* Convert Curve data... */
ipo_to_animdata(id, cu->ipo, NULL, NULL, NULL);
diff --git a/source/blender/blenkernel/intern/key.c b/source/blender/blenkernel/intern/key.c
index 2dc615c19f9..b591dc19685 100644
--- a/source/blender/blenkernel/intern/key.c
+++ b/source/blender/blenkernel/intern/key.c
@@ -40,7 +40,7 @@
#include "BLI_math_vector.h"
#include "BLI_utildefines.h"
-#include "BLF_translation.h"
+#include "BLT_translation.h"
#include "DNA_anim_types.h"
#include "DNA_key_types.h"
@@ -73,15 +73,11 @@
#define IPO_BEZTRIPLE 100
#define IPO_BPOINT 101
-/* extern, not threadsafe */
-int slurph_opt = 1;
-
-
void BKE_key_free(Key *key)
{
KeyBlock *kb;
- BKE_free_animdata((ID *)key);
+ BKE_animdata_free((ID *)key);
while ((kb = BLI_pophead(&key->block))) {
if (kb->data)
@@ -171,7 +167,11 @@ Key *BKE_key_copy(Key *key)
kbn = kbn->next;
kb = kb->next;
}
-
+
+ if (key->id.lib) {
+ BKE_id_lib_local_paths(G.main, key->id.lib, &keyn->id);
+ }
+
return keyn;
}
@@ -607,7 +607,7 @@ static void cp_key(const int start, int end, const int tot, char *poin, Key *key
k1 = key_block_get_data(key, actkb, kb, &freek1);
kref = key_block_get_data(key, actkb, key->refkey, &freekref);
- /* this exception is needed for slurphing */
+ /* this exception is needed curves with multiple splines */
if (start != 0) {
poin += poinsize * start;
@@ -891,7 +891,7 @@ static void do_key(const int start, int end, const int tot, char *poin, Key *key
}
}
- /* this exception needed for slurphing */
+ /* this exception is needed for curves with multiple splines */
if (start != 0) {
poin += poinsize * start;
@@ -1002,7 +1002,9 @@ static void do_key(const int start, int end, const int tot, char *poin, Key *key
k1 += elemsize;
}
}
- else k1 += elemsize;
+ else {
+ k1 += elemsize;
+ }
}
if (flagdo & 2) {
if (flagflo & 2) {
@@ -1086,7 +1088,7 @@ static float *get_weights_array(Object *ob, char *vgroup, WeightsArrayCache *cac
if (cache) {
if (cache->defgroup_weights == NULL) {
- int num_defgroup = BLI_countlist(&ob->defbase);
+ int num_defgroup = BLI_listbase_count(&ob->defbase);
cache->defgroup_weights =
MEM_callocN(sizeof(*cache->defgroup_weights) * num_defgroup,
"cached defgroup weights");
@@ -1168,53 +1170,29 @@ void BKE_keyblock_free_per_block_weights(Key *key, float **per_keyblock_weights,
MEM_freeN(per_keyblock_weights);
}
-static void do_mesh_key(Scene *scene, Object *ob, Key *key, char *out, const int tot)
+static void do_mesh_key(Object *ob, Key *key, char *out, const int tot)
{
KeyBlock *k[4], *actkb = BKE_keyblock_from_object(ob);
float t[4];
int flag = 0;
- if (key->slurph && key->type != KEY_RELATIVE) {
+ if (key->type == KEY_RELATIVE) {
+ WeightsArrayCache cache = {0, NULL};
+ float **per_keyblock_weights;
+ per_keyblock_weights = BKE_keyblock_get_per_block_weights(ob, key, &cache);
+ BKE_key_evaluate_relative(0, tot, tot, (char *)out, key, actkb, per_keyblock_weights, KEY_MODE_DUMMY);
+ BKE_keyblock_free_per_block_weights(key, per_keyblock_weights, &cache);
+ }
+ else {
const float ctime_scaled = key->ctime / 100.0f;
- float delta = (float)key->slurph / tot;
- float cfra = BKE_scene_frame_get(scene);
- int step, a;
-
- if (tot > 100 && slurph_opt) {
- step = tot / 50;
- delta *= step;
- /* in do_key and cp_key the case a>tot is handled */
- }
- else {
- step = 1;
- }
- for (a = 0; a < tot; a += step, cfra += delta) {
- flag = setkeys(ctime_scaled, &key->block, k, t, 0);
+ flag = setkeys(ctime_scaled, &key->block, k, t, 0);
- if (flag == 0)
- do_key(a, a + step, tot, (char *)out, key, actkb, k, t, KEY_MODE_DUMMY);
- else
- cp_key(a, a + step, tot, (char *)out, key, actkb, k[2], NULL, KEY_MODE_DUMMY);
- }
- }
- else {
- if (key->type == KEY_RELATIVE) {
- WeightsArrayCache cache = {0, NULL};
- float **per_keyblock_weights;
- per_keyblock_weights = BKE_keyblock_get_per_block_weights(ob, key, &cache);
- BKE_key_evaluate_relative(0, tot, tot, (char *)out, key, actkb, per_keyblock_weights, KEY_MODE_DUMMY);
- BKE_keyblock_free_per_block_weights(key, per_keyblock_weights, &cache);
+ if (flag == 0) {
+ do_key(0, tot, tot, (char *)out, key, actkb, k, t, KEY_MODE_DUMMY);
}
else {
- const float ctime_scaled = key->ctime / 100.0f;
-
- flag = setkeys(ctime_scaled, &key->block, k, t, 0);
-
- if (flag == 0)
- do_key(0, tot, tot, (char *)out, key, actkb, k, t, KEY_MODE_DUMMY);
- else
- cp_key(0, tot, tot, (char *)out, key, actkb, k[2], NULL, KEY_MODE_DUMMY);
+ cp_key(0, tot, tot, (char *)out, key, actkb, k[2], NULL, KEY_MODE_DUMMY);
}
}
}
@@ -1259,135 +1237,63 @@ static void do_rel_cu_key(Curve *cu, Key *key, KeyBlock *actkb, char *out, const
}
}
-static void do_curve_key(Scene *scene, Object *ob, Key *key, char *out, const int tot)
+static void do_curve_key(Object *ob, Key *key, char *out, const int tot)
{
Curve *cu = ob->data;
KeyBlock *k[4], *actkb = BKE_keyblock_from_object(ob);
float t[4];
int flag = 0;
- if (key->slurph && key->type != KEY_RELATIVE) {
+ if (key->type == KEY_RELATIVE) {
+ do_rel_cu_key(cu, cu->key, actkb, out, tot);
+ }
+ else {
const float ctime_scaled = key->ctime / 100.0f;
- float delta = (float)key->slurph / tot;
- float cfra = BKE_scene_frame_get(scene);
- Nurb *nu;
- int i = 0, remain = 0;
- int step, a;
-
- if (tot > 100 && slurph_opt) {
- step = tot / 50;
- delta *= step;
- /* in do_key and cp_key the case a>tot has been handled */
- }
- else {
- step = 1;
- }
-
- for (nu = cu->nurb.first; nu; nu = nu->next) {
- int estep, mode;
-
- if (nu->bp) {
- mode = KEY_MODE_BPOINT;
- estep = nu->pntsu * nu->pntsv;
- }
- else if (nu->bezt) {
- mode = KEY_MODE_BEZTRIPLE;
- estep = 3 * nu->pntsu;
- }
- else {
- mode = 0;
- estep = 0;
- }
-
- a = 0;
- while (a < estep) {
- int count;
- if (remain <= 0) {
- cfra += delta;
- flag = setkeys(ctime_scaled, &key->block, k, t, 0);
+ flag = setkeys(ctime_scaled, &key->block, k, t, 0);
- remain = step;
- }
-
- count = min_ii(remain, estep);
- if (mode == KEY_MODE_BEZTRIPLE) {
- count += 3 - count % 3;
- }
-
- if (flag == 0)
- do_key(i, i + count, tot, (char *)out, key, actkb, k, t, mode);
- else
- cp_key(i, i + count, tot, (char *)out, key, actkb, k[2], NULL, mode);
-
- a += count;
- i += count;
- remain -= count;
- }
- }
- }
- else {
- if (key->type == KEY_RELATIVE) {
- do_rel_cu_key(cu, cu->key, actkb, out, tot);
+ if (flag == 0) {
+ do_cu_key(cu, key, actkb, k, t, out, tot);
}
else {
- const float ctime_scaled = key->ctime / 100.0f;
-
- flag = setkeys(ctime_scaled, &key->block, k, t, 0);
-
- if (flag == 0) do_cu_key(cu, key, actkb, k, t, out, tot);
- else cp_cu_key(cu, key, actkb, k[2], 0, tot, out, tot);
+ cp_cu_key(cu, key, actkb, k[2], 0, tot, out, tot);
}
}
}
-static void do_latt_key(Scene *scene, Object *ob, Key *key, char *out, const int tot)
+static void do_latt_key(Object *ob, Key *key, char *out, const int tot)
{
Lattice *lt = ob->data;
KeyBlock *k[4], *actkb = BKE_keyblock_from_object(ob);
float t[4];
int flag;
- if (key->slurph && key->type != KEY_RELATIVE) {
- const float ctime_scaled = key->ctime / 100.0f;
- float delta = (float)key->slurph / tot;
- float cfra = BKE_scene_frame_get(scene);
- int a;
-
- for (a = 0; a < tot; a++, cfra += delta) {
- flag = setkeys(ctime_scaled, &key->block, k, t, 0);
-
- if (flag == 0)
- do_key(a, a + 1, tot, out, key, actkb, k, t, KEY_MODE_DUMMY);
- else
- cp_key(a, a + 1, tot, out, key, actkb, k[2], NULL, KEY_MODE_DUMMY);
- }
+ if (key->type == KEY_RELATIVE) {
+ float **per_keyblock_weights;
+ per_keyblock_weights = BKE_keyblock_get_per_block_weights(ob, key, NULL);
+ BKE_key_evaluate_relative(0, tot, tot, (char *)out, key, actkb, per_keyblock_weights, KEY_MODE_DUMMY);
+ BKE_keyblock_free_per_block_weights(key, per_keyblock_weights, NULL);
}
else {
- if (key->type == KEY_RELATIVE) {
- float **per_keyblock_weights;
- per_keyblock_weights = BKE_keyblock_get_per_block_weights(ob, key, NULL);
- BKE_key_evaluate_relative(0, tot, tot, (char *)out, key, actkb, per_keyblock_weights, KEY_MODE_DUMMY);
- BKE_keyblock_free_per_block_weights(key, per_keyblock_weights, NULL);
+ const float ctime_scaled = key->ctime / 100.0f;
+
+ flag = setkeys(ctime_scaled, &key->block, k, t, 0);
+
+ if (flag == 0) {
+ do_key(0, tot, tot, (char *)out, key, actkb, k, t, KEY_MODE_DUMMY);
}
else {
- const float ctime_scaled = key->ctime / 100.0f;
-
- flag = setkeys(ctime_scaled, &key->block, k, t, 0);
-
- if (flag == 0)
- do_key(0, tot, tot, (char *)out, key, actkb, k, t, KEY_MODE_DUMMY);
- else
- cp_key(0, tot, tot, (char *)out, key, actkb, k[2], NULL, KEY_MODE_DUMMY);
+ cp_key(0, tot, tot, (char *)out, key, actkb, k[2], NULL, KEY_MODE_DUMMY);
}
}
-
+
if (lt->flag & LT_OUTSIDE) outside_lattice(lt);
}
/* returns key coordinates (+ tilt) when key applied, NULL otherwise */
-float *BKE_key_evaluate_object_ex(Scene *scene, Object *ob, int *r_totelem,
- float *arr, size_t arr_size)
+float *BKE_key_evaluate_object_ex(
+ Object *ob, int *r_totelem,
+ float *arr, size_t arr_size)
{
Key *key = BKE_key_from_object(ob);
KeyBlock *actkb = BKE_keyblock_from_object(ob);
@@ -1469,10 +1375,10 @@ float *BKE_key_evaluate_object_ex(Scene *scene, Object *ob, int *r_totelem,
}
else {
- if (ob->type == OB_MESH) do_mesh_key(scene, ob, key, out, tot);
- else if (ob->type == OB_LATTICE) do_latt_key(scene, ob, key, out, tot);
- else if (ob->type == OB_CURVE) do_curve_key(scene, ob, key, out, tot);
- else if (ob->type == OB_SURF) do_curve_key(scene, ob, key, out, tot);
+ if (ob->type == OB_MESH) do_mesh_key(ob, key, out, tot);
+ else if (ob->type == OB_LATTICE) do_latt_key(ob, key, out, tot);
+ else if (ob->type == OB_CURVE) do_curve_key(ob, key, out, tot);
+ else if (ob->type == OB_SURF) do_curve_key(ob, key, out, tot);
}
if (r_totelem) {
@@ -1481,30 +1387,42 @@ float *BKE_key_evaluate_object_ex(Scene *scene, Object *ob, int *r_totelem,
return (float *)out;
}
-float *BKE_key_evaluate_object(Scene *scene, Object *ob, int *r_totelem)
+float *BKE_key_evaluate_object(Object *ob, int *r_totelem)
{
- return BKE_key_evaluate_object_ex(scene, ob, r_totelem, NULL, 0);
+ return BKE_key_evaluate_object_ex(ob, r_totelem, NULL, 0);
}
-Key *BKE_key_from_object(Object *ob)
+Key **BKE_key_from_object_p(Object *ob)
{
- if (ob == NULL) return NULL;
-
+ if (ob == NULL)
+ return NULL;
+
if (ob->type == OB_MESH) {
Mesh *me = ob->data;
- return me->key;
+ return &me->key;
}
else if (ELEM(ob->type, OB_CURVE, OB_SURF)) {
Curve *cu = ob->data;
- return cu->key;
+ return &cu->key;
}
else if (ob->type == OB_LATTICE) {
Lattice *lt = ob->data;
- return lt->key;
+ return &lt->key;
}
return NULL;
}
+Key *BKE_key_from_object(Object *ob)
+{
+ Key **key_p;
+ key_p = BKE_key_from_object_p(ob);
+ if (key_p) {
+ return *key_p;
+ }
+
+ return NULL;
+}
+
KeyBlock *BKE_keyblock_add(Key *key, const char *name)
{
KeyBlock *kb;
@@ -1518,7 +1436,7 @@ KeyBlock *BKE_keyblock_add(Key *key, const char *name)
BLI_addtail(&key->block, kb);
kb->type = KEY_CARDINAL;
- tot = BLI_countlist(&key->block);
+ tot = BLI_listbase_count(&key->block);
if (name) {
BLI_strncpy(kb->name, name, sizeof(kb->name));
}
@@ -1669,31 +1587,43 @@ char *BKE_keyblock_curval_rnapath_get(Key *key, KeyBlock *kb)
/* conversion functions */
/************************* Lattice ************************/
-void BKE_key_convert_from_lattice(Lattice *lt, KeyBlock *kb)
+void BKE_keyblock_update_from_lattice(Lattice *lt, KeyBlock *kb)
{
BPoint *bp;
- float *fp;
+ float (*fp)[3];
int a, tot;
+ BLI_assert(kb->totelem == lt->pntsu * lt->pntsv * lt->pntsw);
+
+ tot = kb->totelem;
+ if (tot == 0) return;
+
+ bp = lt->def;
+ fp = kb->data;
+ for (a = 0; a < kb->totelem; a++, fp++, bp++) {
+ copy_v3_v3(*fp, bp->vec);
+ }
+}
+
+void BKE_keyblock_convert_from_lattice(Lattice *lt, KeyBlock *kb)
+{
+ int tot;
+
tot = lt->pntsu * lt->pntsv * lt->pntsw;
if (tot == 0) return;
- if (kb->data) MEM_freeN(kb->data);
+ MEM_SAFE_FREE(kb->data);
- kb->data = MEM_mallocN(lt->key->elemsize * tot, "kb->data");
+ kb->data = MEM_mallocN(lt->key->elemsize * tot, __func__);
kb->totelem = tot;
- bp = lt->def;
- fp = kb->data;
- for (a = 0; a < kb->totelem; a++, fp += 3, bp++) {
- copy_v3_v3(fp, bp->vec);
- }
+ BKE_keyblock_update_from_lattice(lt, kb);
}
-void BKE_key_convert_to_lattice(KeyBlock *kb, Lattice *lt)
+void BKE_keyblock_convert_to_lattice(KeyBlock *kb, Lattice *lt)
{
BPoint *bp;
- const float *fp;
+ const float (*fp)[3];
int a, tot;
bp = lt->def;
@@ -1702,13 +1632,13 @@ void BKE_key_convert_to_lattice(KeyBlock *kb, Lattice *lt)
tot = lt->pntsu * lt->pntsv * lt->pntsw;
tot = min_ii(kb->totelem, tot);
- for (a = 0; a < tot; a++, fp += 3, bp++) {
- copy_v3_v3(bp->vec, fp);
+ for (a = 0; a < tot; a++, fp++, bp++) {
+ copy_v3_v3(bp->vec, *fp);
}
}
/************************* Curve ************************/
-void BKE_key_convert_from_curve(Curve *cu, KeyBlock *kb, ListBase *nurb)
+void BKE_keyblock_update_from_curve(Curve *UNUSED(cu), KeyBlock *kb, ListBase *nurb)
{
Nurb *nu;
BezTriple *bezt;
@@ -1717,49 +1647,52 @@ void BKE_key_convert_from_curve(Curve *cu, KeyBlock *kb, ListBase *nurb)
int a, tot;
/* count */
- tot = BKE_nurbList_verts_count(nurb);
- if (tot == 0) return;
-
- if (kb->data) MEM_freeN(kb->data);
+ BLI_assert(BKE_nurbList_verts_count(nurb) == kb->totelem);
- kb->data = MEM_mallocN(cu->key->elemsize * tot, "kb->data");
- kb->totelem = tot;
+ tot = kb->totelem;
+ if (tot == 0) return;
- nu = nurb->first;
fp = kb->data;
- while (nu) {
-
+ for (nu = nurb->first; nu; nu = nu->next) {
if (nu->bezt) {
- bezt = nu->bezt;
- a = nu->pntsu;
- while (a--) {
- copy_v3_v3(fp, bezt->vec[0]);
- fp += 3;
- copy_v3_v3(fp, bezt->vec[1]);
- fp += 3;
- copy_v3_v3(fp, bezt->vec[2]);
- fp += 3;
+ for (a = nu->pntsu, bezt = nu->bezt; a; a--, bezt++) {
+ int i;
+
+ for (i = 0; i < 3; i++, fp += 3) {
+ copy_v3_v3(fp, bezt->vec[i]);
+ }
fp[0] = bezt->alfa;
fp += 3; /* alphas */
- bezt++;
}
}
else {
- bp = nu->bp;
- a = nu->pntsu * nu->pntsv;
- while (a--) {
+
+ ;
+ for (a = nu->pntsu * nu->pntsv, bp = nu->bp; a; a--, fp += 4, bp++) {
copy_v3_v3(fp, bp->vec);
fp[3] = bp->alfa;
-
- fp += 4;
- bp++;
}
}
- nu = nu->next;
}
}
-void BKE_key_convert_to_curve(KeyBlock *kb, Curve *UNUSED(cu), ListBase *nurb)
+void BKE_keyblock_convert_from_curve(Curve *cu, KeyBlock *kb, ListBase *nurb)
+{
+ int tot;
+
+ /* count */
+ tot = BKE_nurbList_verts_count(nurb);
+ if (tot == 0) return;
+
+ MEM_SAFE_FREE(kb->data);
+
+ kb->data = MEM_mallocN(cu->key->elemsize * tot, __func__);
+ kb->totelem = tot;
+
+ BKE_keyblock_update_from_curve(cu, kb, nurb);
+}
+
+void BKE_keyblock_convert_to_curve(KeyBlock *kb, Curve *UNUSED(cu), ListBase *nurb)
{
Nurb *nu;
BezTriple *bezt;
@@ -1767,74 +1700,68 @@ void BKE_key_convert_to_curve(KeyBlock *kb, Curve *UNUSED(cu), ListBase *nurb)
const float *fp;
int a, tot;
- nu = nurb->first;
- fp = kb->data;
-
tot = BKE_nurbList_verts_count(nurb);
-
tot = min_ii(kb->totelem, tot);
- while (nu && tot > 0) {
-
+ fp = kb->data;
+ for (nu = nurb->first; nu && tot > 0; nu = nu->next) {
if (nu->bezt) {
- bezt = nu->bezt;
- a = nu->pntsu;
- while (a-- && tot > 0) {
- copy_v3_v3(bezt->vec[0], fp);
- fp += 3;
- copy_v3_v3(bezt->vec[1], fp);
- fp += 3;
- copy_v3_v3(bezt->vec[2], fp);
- fp += 3;
+ for (a = nu->pntsu, bezt = nu->bezt; a && tot > 0; a--, tot -= 3, bezt++) {
+ int i;
+
+ for (i = 0; i < 3; i++, fp += 3) {
+ copy_v3_v3(bezt->vec[i], fp);
+ }
bezt->alfa = fp[0];
fp += 3; /* alphas */
-
- tot -= 3;
- bezt++;
}
}
else {
- bp = nu->bp;
- a = nu->pntsu * nu->pntsv;
- while (a-- && tot > 0) {
+ for (a = nu->pntsu * nu->pntsv, bp = nu->bp; a && tot; a--, tot--, fp += 4, bp++) {
copy_v3_v3(bp->vec, fp);
bp->alfa = fp[3];
-
- fp += 4;
- tot--;
- bp++;
}
}
- nu = nu->next;
}
}
/************************* Mesh ************************/
-void BKE_key_convert_from_mesh(Mesh *me, KeyBlock *kb)
+void BKE_keyblock_update_from_mesh(Mesh *me, KeyBlock *kb)
{
MVert *mvert;
- float *fp;
- int a;
-
- if (me->totvert == 0) return;
+ float (*fp)[3];
+ int a, tot;
- if (kb->data) MEM_freeN(kb->data);
+ BLI_assert(me->totvert == kb->totelem);
- kb->data = MEM_mallocN(me->key->elemsize * me->totvert, "kb->data");
- kb->totelem = me->totvert;
+ tot = me->totvert;
+ if (tot == 0) return;
mvert = me->mvert;
fp = kb->data;
- for (a = 0; a < kb->totelem; a++, fp += 3, mvert++) {
- copy_v3_v3(fp, mvert->co);
-
+ for (a = 0; a < tot; a++, fp++, mvert++) {
+ copy_v3_v3(*fp, mvert->co);
}
}
-void BKE_key_convert_to_mesh(KeyBlock *kb, Mesh *me)
+void BKE_keyblock_convert_from_mesh(Mesh *me, KeyBlock *kb)
+{
+ int tot = me->totvert;
+
+ if (me->totvert == 0) return;
+
+ MEM_SAFE_FREE(kb->data);
+
+ kb->data = MEM_mallocN(me->key->elemsize * tot, __func__);
+ kb->totelem = tot;
+
+ BKE_keyblock_update_from_mesh(me, kb);
+}
+
+void BKE_keyblock_convert_to_mesh(KeyBlock *kb, Mesh *me)
{
MVert *mvert;
- const float *fp;
+ const float (*fp)[3];
int a, tot;
mvert = me->mvert;
@@ -1842,94 +1769,76 @@ void BKE_key_convert_to_mesh(KeyBlock *kb, Mesh *me)
tot = min_ii(kb->totelem, me->totvert);
- for (a = 0; a < tot; a++, fp += 3, mvert++) {
- copy_v3_v3(mvert->co, fp);
+ for (a = 0; a < tot; a++, fp++, mvert++) {
+ copy_v3_v3(mvert->co, *fp);
}
}
-/************************* vert coords ************************/
-float (*BKE_key_convert_to_vertcos(Object *ob, KeyBlock *kb))[3]
+/************************* raw coords ************************/
+void BKE_keyblock_update_from_vertcos(Object *ob, KeyBlock *kb, float (*vertCos)[3])
{
- float (*vertCos)[3], *co;
- const float *fp = kb->data;
- int tot = 0, a;
+ float (*co)[3] = vertCos;
+ float *fp = kb->data;
+ int tot, a;
- /* Count of vertex coords in array */
- if (ob->type == OB_MESH) {
- Mesh *me = (Mesh *)ob->data;
- tot = me->totvert;
- }
- else if (ob->type == OB_LATTICE) {
- Lattice *lt = (Lattice *)ob->data;
- tot = lt->pntsu * lt->pntsv * lt->pntsw;
+#ifndef NDEBUG
+ if (ob->type == OB_LATTICE) {
+ Lattice *lt = ob->data;
+ BLI_assert((lt->pntsu * lt->pntsv * lt->pntsw) == kb->totelem);
}
else if (ELEM(ob->type, OB_CURVE, OB_SURF)) {
- Curve *cu = (Curve *)ob->data;
- tot = BKE_nurbList_verts_count(&cu->nurb);
+ Curve *cu = ob->data;
+ BLI_assert(BKE_nurbList_verts_count(&cu->nurb) == kb->totelem);
}
+ else if (ob->type == OB_MESH) {
+ Mesh *me = ob->data;
+ BLI_assert(me->totvert == kb->totelem);
+ }
+ else {
+ BLI_assert(0 == kb->totelem);
+ }
+#endif
- if (tot == 0) return NULL;
-
- vertCos = MEM_mallocN(tot * sizeof(*vertCos), "BKE_key_convert_to_vertcos vertCos");
-
- /* Copy coords to array */
- co = (float *)vertCos;
+ tot = kb->totelem;
+ if (tot == 0) return;
+ /* Copy coords to keyblock */
if (ELEM(ob->type, OB_MESH, OB_LATTICE)) {
- for (a = 0; a < tot; a++, fp += 3, co += 3) {
- copy_v3_v3(co, fp);
+ for (a = 0; a < tot; a++, fp += 3, co++) {
+ copy_v3_v3(fp, *co);
}
}
else if (ELEM(ob->type, OB_CURVE, OB_SURF)) {
Curve *cu = (Curve *)ob->data;
- Nurb *nu = cu->nurb.first;
+ Nurb *nu;
BezTriple *bezt;
BPoint *bp;
- while (nu) {
+ for (nu = cu->nurb.first; nu; nu = nu->next) {
if (nu->bezt) {
- int i;
- bezt = nu->bezt;
- a = nu->pntsu;
+ for (a = nu->pntsu, bezt = nu->bezt; a; a--, bezt++) {
+ int i;
- while (a--) {
- for (i = 0; i < 3; i++) {
- copy_v3_v3(co, fp);
- fp += 3; co += 3;
+ for (i = 0; i < 3; i++, fp += 3, co++) {
+ copy_v3_v3(fp, *co);
}
-
fp += 3; /* skip alphas */
-
- bezt++;
}
}
else {
- bp = nu->bp;
- a = nu->pntsu * nu->pntsv;
-
- while (a--) {
- copy_v3_v3(co, fp);
-
- fp += 4;
- co += 3;
-
- bp++;
+ for (a = nu->pntsu * nu->pntsv, bp = nu->bp; a; a--, bp++, fp += 4, co++) {
+ copy_v3_v3(fp, *co);
}
}
-
- nu = nu->next;
}
}
-
- return vertCos;
}
-void BKE_key_convert_from_vertcos(Object *ob, KeyBlock *kb, float (*vertCos)[3])
+void BKE_keyblock_convert_from_vertcos(Object *ob, KeyBlock *kb, float (*vertCos)[3])
{
- float *co = (float *)vertCos, *fp;
- int tot = 0, a, elemsize;
+ int tot = 0, elemsize;
- if (kb->data) MEM_freeN(kb->data);
+ MEM_SAFE_FREE(kb->data);
/* Count of vertex coords in array */
if (ob->type == OB_MESH) {
@@ -1948,110 +1857,212 @@ void BKE_key_convert_from_vertcos(Object *ob, KeyBlock *kb, float (*vertCos)[3])
tot = BKE_nurbList_verts_count(&cu->nurb);
}
- if (tot == 0) {
- kb->data = NULL;
- return;
- }
+ if (tot == 0) return;
- fp = kb->data = MEM_mallocN(tot * elemsize, "BKE_key_convert_to_vertcos vertCos");
+ kb->data = MEM_mallocN(tot * elemsize, __func__);
/* Copy coords to keyblock */
+ BKE_keyblock_update_from_vertcos(ob, kb, vertCos);
+}
+
+float (*BKE_keyblock_convert_to_vertcos(Object *ob, KeyBlock *kb))[3]
+{
+ float (*vertCos)[3], (*co)[3];
+ const float *fp = kb->data;
+ int tot = 0, a;
+
+ /* Count of vertex coords in array */
+ if (ob->type == OB_MESH) {
+ Mesh *me = (Mesh *)ob->data;
+ tot = me->totvert;
+ }
+ else if (ob->type == OB_LATTICE) {
+ Lattice *lt = (Lattice *)ob->data;
+ tot = lt->pntsu * lt->pntsv * lt->pntsw;
+ }
+ else if (ELEM(ob->type, OB_CURVE, OB_SURF)) {
+ Curve *cu = (Curve *)ob->data;
+ tot = BKE_nurbList_verts_count(&cu->nurb);
+ }
+
+ if (tot == 0) return NULL;
+
+ co = vertCos = MEM_mallocN(tot * sizeof(*vertCos), __func__);
+ /* Copy coords to array */
if (ELEM(ob->type, OB_MESH, OB_LATTICE)) {
- for (a = 0; a < tot; a++, fp += 3, co += 3) {
- copy_v3_v3(fp, co);
+ for (a = 0; a < tot; a++, fp += 3, co++) {
+ copy_v3_v3(*co, fp);
}
}
else if (ELEM(ob->type, OB_CURVE, OB_SURF)) {
Curve *cu = (Curve *)ob->data;
- Nurb *nu = cu->nurb.first;
+ Nurb *nu;
BezTriple *bezt;
BPoint *bp;
- while (nu) {
+ for (nu = cu->nurb.first; nu; nu = nu->next) {
if (nu->bezt) {
- int i;
- bezt = nu->bezt;
- a = nu->pntsu;
+ for (a = nu->pntsu, bezt = nu->bezt; a; a--, bezt++) {
+ int i;
- while (a--) {
- for (i = 0; i < 3; i++) {
- copy_v3_v3(fp, co);
- fp += 3; co += 3;
+ for (i = 0; i < 3; i++, fp += 3, co++) {
+ copy_v3_v3(*co, fp);
}
-
fp += 3; /* skip alphas */
-
- bezt++;
}
}
else {
- bp = nu->bp;
- a = nu->pntsu * nu->pntsv;
-
- while (a--) {
- copy_v3_v3(fp, co);
-
- fp += 4;
- co += 3;
-
- bp++;
+ for (a = nu->pntsu * nu->pntsv, bp = nu->bp; a; a--, bp++, fp += 4, co++) {
+ copy_v3_v3(*co, fp);
}
}
-
- nu = nu->next;
}
}
+
+ return vertCos;
}
-void BKE_key_convert_from_offset(Object *ob, KeyBlock *kb, float (*ofs)[3])
+/************************* raw coord offsets ************************/
+void BKE_keyblock_update_from_offset(Object *ob, KeyBlock *kb, float (*ofs)[3])
{
int a;
- float *co = (float *)ofs, *fp = kb->data;
+ float *fp = kb->data;
if (ELEM(ob->type, OB_MESH, OB_LATTICE)) {
- for (a = 0; a < kb->totelem; a++, fp += 3, co += 3) {
- add_v3_v3(fp, co);
+ for (a = 0; a < kb->totelem; a++, fp += 3, ofs++) {
+ add_v3_v3(fp, *ofs);
}
}
else if (ELEM(ob->type, OB_CURVE, OB_SURF)) {
Curve *cu = (Curve *)ob->data;
- Nurb *nu = cu->nurb.first;
+ Nurb *nu;
BezTriple *bezt;
BPoint *bp;
- while (nu) {
+ for (nu = cu->nurb.first; nu; nu = nu->next) {
if (nu->bezt) {
- int i;
- bezt = nu->bezt;
- a = nu->pntsu;
+ for (a = nu->pntsu, bezt = nu->bezt; a; a--, bezt++) {
+ int i;
- while (a--) {
- for (i = 0; i < 3; i++) {
- add_v3_v3(fp, co);
- fp += 3; co += 3;
+ for (i = 0; i < 3; i++, fp += 3, ofs++) {
+ add_v3_v3(fp, *ofs);
}
-
fp += 3; /* skip alphas */
-
- bezt++;
}
}
else {
- bp = nu->bp;
- a = nu->pntsu * nu->pntsv;
+ for (a = nu->pntsu * nu->pntsv, bp = nu->bp; a; a--, bp++, fp += 4, ofs++) {
+ add_v3_v3(fp, *ofs);
+ }
+ }
+ }
+ }
+}
+
+/* ==========================================================*/
+
+/** Move shape key from org_index to new_index. Safe, clamps index to valid range, updates reference keys,
+ * the object's active shape index, the 'frame' value in case of absolute keys, etc.
+ * Note indices are expected in real values (not 'fake' shapenr +1 ones).
+ *
+ * \param org_index if < 0, current object's active shape will be used as skey to move.
+ * \return true if something was done, else false.
+ */
+bool BKE_keyblock_move(Object *ob, int org_index, int new_index)
+{
+ Key *key = BKE_key_from_object(ob);
+ KeyBlock *kb;
+ const int act_index = ob->shapenr - 1;
+ const int totkey = key->totkey;
+ int i;
+ bool rev, in_range = false;
- while (a--) {
- add_v3_v3(fp, co);
+ if (org_index < 0) {
+ org_index = act_index;
+ }
- fp += 4;
- co += 3;
+ CLAMP(new_index, 0, key->totkey - 1);
+ CLAMP(org_index, 0, key->totkey - 1);
- bp++;
- }
- }
+ if (new_index == org_index) {
+ return false;
+ }
- nu = nu->next;
+ rev = ((new_index - org_index) < 0) ? true : false;
+
+ /* We swap 'org' element with its previous/next neighbor (depending on direction of the move) repeatedly,
+ * until we reach final position.
+ * This allows us to only loop on the list once! */
+ for (kb = (rev ? key->block.last : key->block.first), i = (rev ? totkey - 1 : 0);
+ kb;
+ kb = (rev ? kb->prev : kb->next), rev ? i-- : i++)
+ {
+ if (i == org_index) {
+ in_range = true; /* Start list items swapping... */
+ }
+ else if (i == new_index) {
+ in_range = false; /* End list items swapping. */
+ }
+
+ if (in_range) {
+ KeyBlock *other_kb = rev ? kb->prev : kb->next;
+
+ /* Swap with previous/next list item. */
+ BLI_listbase_swaplinks(&key->block, kb, other_kb);
+
+ /* Swap absolute positions. */
+ SWAP(float, kb->pos, other_kb->pos);
+
+ kb = other_kb;
+ }
+
+ /* Adjust relative indices, this has to be done on the whole list! */
+ if (kb->relative == org_index) {
+ kb->relative = new_index;
+ }
+ else if (kb->relative < org_index && kb->relative >= new_index) {
+ /* remove after, insert before this index */
+ kb->relative++;
+ }
+ else if (kb->relative > org_index && kb->relative <= new_index) {
+ /* remove before, insert after this index */
+ kb->relative--;
+ }
+ }
+
+ /* Need to update active shape number if it's affected, same principle as for relative indices above. */
+ if (org_index == act_index) {
+ ob->shapenr = new_index + 1;
+ }
+ else if (act_index < org_index && act_index >= new_index) {
+ ob->shapenr++;
+ }
+ else if (act_index > org_index && act_index <= new_index) {
+ ob->shapenr--;
+ }
+
+ /* First key is always refkey, matches interface and BKE_key_sort */
+ key->refkey = key->block.first;
+
+ return true;
+}
+
+/**
+ * Check if given keyblock (as index) is used as basis by others in given key.
+ */
+bool BKE_keyblock_is_basis(Key *key, const int index)
+{
+ KeyBlock *kb;
+ int i;
+
+ if (key->type == KEY_RELATIVE) {
+ for (i = 0, kb = key->block.first; kb; i++, kb = kb->next) {
+ if ((i != index) && (kb->relative == index)) {
+ return true;
+ }
}
}
+
+ return false;
}
diff --git a/source/blender/blenkernel/intern/lamp.c b/source/blender/blenkernel/intern/lamp.c
index 749e915e5ca..44e35c645de 100644
--- a/source/blender/blenkernel/intern/lamp.c
+++ b/source/blender/blenkernel/intern/lamp.c
@@ -41,7 +41,6 @@
#include "DNA_scene_types.h"
#include "DNA_texture_types.h"
-#include "BLI_listbase.h"
#include "BLI_math.h"
#include "BLI_utildefines.h"
@@ -127,6 +126,10 @@ Lamp *BKE_lamp_copy(Lamp *la)
if (la->preview)
lan->preview = BKE_previewimg_copy(la->preview);
+ if (la->id.lib) {
+ BKE_id_lib_local_paths(G.main, la->id.lib, &lan->id);
+ }
+
return lan;
}
@@ -135,8 +138,7 @@ Lamp *localize_lamp(Lamp *la)
Lamp *lan;
int a;
- lan = BKE_libblock_copy(&la->id);
- BLI_remlink(&G.main->lamp, lan);
+ lan = BKE_libblock_copy_nolib(&la->id, false);
for (a = 0; a < MAX_MTEX; a++) {
if (lan->mtex[a]) {
@@ -219,7 +221,7 @@ void BKE_lamp_free(Lamp *la)
if (mtex) MEM_freeN(mtex);
}
- BKE_free_animdata((ID *)la);
+ BKE_animdata_free((ID *)la);
curvemapping_free(la->curfalloff);
@@ -230,7 +232,7 @@ void BKE_lamp_free(Lamp *la)
}
BKE_previewimg_free(&la->preview);
- BKE_icon_delete(&la->id);
+ BKE_icon_id_delete(&la->id);
la->id.icon_id = 0;
}
diff --git a/source/blender/blenkernel/intern/lattice.c b/source/blender/blenkernel/intern/lattice.c
index 3f12e3efcc7..009e1d20328 100644
--- a/source/blender/blenkernel/intern/lattice.c
+++ b/source/blender/blenkernel/intern/lattice.c
@@ -53,6 +53,7 @@
#include "BKE_anim.h"
#include "BKE_cdderivedmesh.h"
#include "BKE_curve.h"
+#include "BKE_depsgraph.h"
#include "BKE_displist.h"
#include "BKE_global.h"
#include "BKE_key.h"
@@ -60,6 +61,7 @@
#include "BKE_library.h"
#include "BKE_main.h"
#include "BKE_modifier.h"
+#include "BKE_object.h"
#include "BKE_deform.h"
@@ -284,6 +286,10 @@ Lattice *BKE_lattice_copy(Lattice *lt)
ltn->editlatt = NULL;
+ if (lt->id.lib) {
+ BKE_id_lib_local_paths(G.main, lt->id.lib, &ltn->id);
+ }
+
return ltn;
}
@@ -303,7 +309,7 @@ void BKE_lattice_free(Lattice *lt)
/* free animation data */
if (lt->adt) {
- BKE_free_animdata(&lt->id);
+ BKE_animdata_free(&lt->id);
lt->adt = NULL;
}
}
@@ -575,7 +581,7 @@ static bool where_on_path_deform(Object *ob, float ctime, float vec[4], float di
/* test for cyclic */
bl = ob->curve_cache->bev.first;
- if (!bl->nr) return 0;
+ if (!bl->nr) return false;
if (bl->poly > -1) cycl = 1;
if (cycl == 0) {
@@ -608,9 +614,9 @@ static bool where_on_path_deform(Object *ob, float ctime, float vec[4], float di
/* weight - not used but could be added */
}
}
- return 1;
+ return true;
}
- return 0;
+ return false;
}
/* for each point, rotate & translate to curve */
@@ -634,9 +640,7 @@ static bool calc_curve_deform(Scene *scene, Object *par, float co[3],
#endif
if (par->curve_cache->path == NULL) {
- return 0; /* happens on append, cyclic dependencies
- * and empty curves
- */
+ return false; /* happens on append, cyclic dependencies and empty curves */
}
/* options */
@@ -718,13 +722,14 @@ static bool calc_curve_deform(Scene *scene, Object *par, float co[3],
if (r_quat)
copy_qt_qt(r_quat, quat);
- return 1;
+ return true;
}
- return 0;
+ return false;
}
-void curve_deform_verts(Scene *scene, Object *cuOb, Object *target, DerivedMesh *dm, float (*vertexCos)[3],
- int numVerts, const char *vgroup, short defaxis)
+void curve_deform_verts(
+ Scene *scene, Object *cuOb, Object *target, DerivedMesh *dm, float (*vertexCos)[3],
+ int numVerts, const char *vgroup, short defaxis)
{
Curve *cu;
int a;
@@ -939,10 +944,10 @@ bool object_deform_mball(Object *ob, ListBase *dispbase)
(float(*)[3])dl->verts, dl->nr, NULL, 1.0f);
}
- return 1;
+ return true;
}
else {
- return 0;
+ return false;
}
}
@@ -1066,7 +1071,7 @@ void BKE_lattice_modifiers_calc(Scene *scene, Object *ob)
}
for (; md; md = md->next) {
- ModifierTypeInfo *mti = modifierType_getInfo(md->type);
+ const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
md->scene = scene;
@@ -1134,6 +1139,48 @@ void BKE_lattice_center_median(Lattice *lt, float cent[3])
mul_v3_fl(cent, 1.0f / (float)numVerts);
}
+static void boundbox_lattice(Object *ob)
+{
+ BoundBox *bb;
+ Lattice *lt;
+ float min[3], max[3];
+
+ if (ob->bb == NULL)
+ ob->bb = MEM_mallocN(sizeof(BoundBox), "Lattice boundbox");
+
+ bb = ob->bb;
+ lt = ob->data;
+
+ INIT_MINMAX(min, max);
+ BKE_lattice_minmax_dl(ob, lt, min, max);
+ BKE_boundbox_init_from_minmax(bb, min, max);
+}
+
+BoundBox *BKE_lattice_boundbox_get(Object *ob)
+{
+ boundbox_lattice(ob);
+
+ return ob->bb;
+}
+
+void BKE_lattice_minmax_dl(Object *ob, Lattice *lt, float min[3], float max[3])
+{
+ DispList *dl = ob->curve_cache ? BKE_displist_find(&ob->curve_cache->disp, DL_VERTS) : NULL;
+
+ if (!dl) {
+ BKE_lattice_minmax(lt, min, max);
+ }
+ else {
+ int i, numVerts;
+
+ if (lt->editlatt) lt = lt->editlatt->latt;
+ numVerts = lt->pntsu * lt->pntsv * lt->pntsw;
+
+ for (i = 0; i < numVerts; i++)
+ minmax_v3v3_v3(min, max, &dl->verts[i * 3]);
+ }
+}
+
void BKE_lattice_minmax(Lattice *lt, float min[3], float max[3])
{
int i, numVerts;
@@ -1203,3 +1250,10 @@ void BKE_lattice_translate(Lattice *lt, float offset[3], bool do_keys)
}
}
+/* **** Depsgraph evaluation **** */
+
+void BKE_lattice_eval_geometry(EvaluationContext *UNUSED(eval_ctx),
+ Lattice *UNUSED(latt))
+{
+}
+
diff --git a/source/blender/blenkernel/intern/library.c b/source/blender/blenkernel/intern/library.c
index b49eee3ea22..9fb0cb42dfc 100644
--- a/source/blender/blenkernel/intern/library.c
+++ b/source/blender/blenkernel/intern/library.c
@@ -72,7 +72,7 @@
#include "BLI_utildefines.h"
#include "BLI_threads.h"
-#include "BLF_translation.h"
+#include "BLT_translation.h"
#include "BKE_action.h"
#include "BKE_animsys.h"
@@ -115,8 +115,13 @@
#include "BKE_texture.h"
#include "BKE_world.h"
+#include "DEG_depsgraph.h"
+
#include "RNA_access.h"
+#include "IMB_imbuf.h"
+#include "IMB_imbuf_types.h"
+
#ifdef WITH_PYTHON
#include "BPY_extern.h"
#endif
@@ -139,7 +144,7 @@ void BKE_id_lib_local_paths(Main *bmain, Library *lib, ID *id)
BKE_bpath_traverse_id(bmain, id,
BKE_bpath_relocate_visitor,
BKE_BPATH_TRAVERSE_SKIP_MULTIFILE,
- bpath_user_data);
+ (void *)bpath_user_data);
}
void id_lib_extern(ID *id)
@@ -291,7 +296,7 @@ bool id_make_local(ID *id, bool test)
/**
* Invokes the appropriate copy method for the block and returns the result in
- * newid, unless test. Returns true iff the block can be copied.
+ * newid, unless test. Returns true if the block can be copied.
*/
bool id_copy(ID *id, ID **newid, bool test)
{
@@ -351,7 +356,7 @@ bool id_copy(ID *id, ID **newid, bool test)
case ID_VF:
return false; /* not implemented */
case ID_TXT:
- if (!test) *newid = (ID *)BKE_text_copy((Text *)id);
+ if (!test) *newid = (ID *)BKE_text_copy(G.main, (Text *)id);
return true;
case ID_SCRIPT:
return false; /* deprecated */
@@ -378,12 +383,13 @@ bool id_copy(ID *id, ID **newid, bool test)
case ID_WM:
return false; /* can't be copied from here */
case ID_GD:
- return false; /* not implemented */
+ if (!test) *newid = (ID *)gpencil_data_duplicate((bGPdata *)id, false);
+ return true;
case ID_MSK:
if (!test) *newid = (ID *)BKE_mask_copy((Mask *)id);
return true;
case ID_LS:
- if (!test) *newid = (ID *)BKE_linestyle_copy((FreestyleLineStyle *)id);
+ if (!test) *newid = (ID *)BKE_linestyle_copy(G.main, (FreestyleLineStyle *)id);
return true;
}
@@ -431,7 +437,7 @@ bool id_single_user(bContext *C, ID *id, PointerRNA *ptr, PropertyRNA *prop)
if (RNA_property_editable(ptr, prop)) {
if (id_copy(id, &newid, false) && newid) {
/* copy animation actions too */
- BKE_copy_animdata_id_action(id);
+ BKE_animdata_copy_id_action(id);
/* us is 1 by convention, but RNA_property_pointer_set
* will also increment it, so set it to zero */
newid->us = 0;
@@ -553,9 +559,11 @@ void BKE_main_lib_objects_recalc_all(Main *bmain)
Object *ob;
/* flag for full recalc */
- for (ob = bmain->object.first; ob; ob = ob->id.next)
- if (ob->id.lib)
- ob->recalc |= OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME;
+ for (ob = bmain->object.first; ob; ob = ob->id.next) {
+ if (ob->id.lib) {
+ DAG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
+ }
+ }
DAG_id_type_tag(bmain, ID_OB);
}
@@ -609,13 +617,13 @@ int set_listbasepointers(Main *main, ListBase **lb)
lb[a++] = &(main->speaker);
lb[a++] = &(main->world);
+ lb[a++] = &(main->movieclip);
lb[a++] = &(main->screen);
lb[a++] = &(main->object);
lb[a++] = &(main->linestyle); /* referenced by scenes */
lb[a++] = &(main->scene);
lb[a++] = &(main->library);
lb[a++] = &(main->wm);
- lb[a++] = &(main->movieclip);
lb[a++] = &(main->mask);
lb[a] = NULL;
@@ -784,7 +792,7 @@ static void id_copy_animdata(ID *id, const bool do_action)
if (adt) {
IdAdtTemplate *iat = (IdAdtTemplate *)id;
- iat->adt = BKE_copy_animdata(iat->adt, do_action); /* could be set to false, need to investigate */
+ iat->adt = BKE_animdata_copy(iat->adt, do_action); /* could be set to false, need to investigate */
}
}
@@ -864,18 +872,24 @@ static void BKE_library_free(Library *lib)
static void (*free_windowmanager_cb)(bContext *, wmWindowManager *) = NULL;
-void set_free_windowmanager_cb(void (*func)(bContext *C, wmWindowManager *) )
+void BKE_library_callback_free_window_manager_set(void (*func)(bContext *C, wmWindowManager *) )
{
free_windowmanager_cb = func;
}
static void (*free_notifier_reference_cb)(const void *) = NULL;
-void set_free_notifier_reference_cb(void (*func)(const void *) )
+void BKE_library_callback_free_notifier_reference_set(void (*func)(const void *) )
{
free_notifier_reference_cb = func;
}
+static void (*free_editor_id_reference_cb)(const ID *) = NULL;
+
+void BKE_library_callback_free_editor_id_reference_set(void (*func)(const ID *))
+{
+ free_editor_id_reference_cb = func;
+}
static void animdata_dtar_clear_cb(ID *UNUSED(id), AnimData *adt, void *userdata)
{
@@ -1033,8 +1047,13 @@ void BKE_libblock_free_ex(Main *bmain, void *idv, bool do_id_user)
/* avoid notifying on removed data */
BKE_main_lock(bmain);
- if (free_notifier_reference_cb)
+ if (free_notifier_reference_cb) {
free_notifier_reference_cb(id);
+ }
+
+ if (free_editor_id_reference_cb) {
+ free_editor_id_reference_cb(id);
+ }
BLI_remlink(lb, id);
@@ -1069,8 +1088,7 @@ void BKE_libblock_free_us(Main *bmain, void *idv) /* test users */
Main *BKE_main_new(void)
{
Main *bmain = MEM_callocN(sizeof(Main), "new main");
- bmain->eval_ctx = MEM_callocN(sizeof(EvaluationContext),
- "EvaluationContext");
+ bmain->eval_ctx = DEG_evaluation_context_new(DAG_EVAL_VIEWPORT);
bmain->lock = MEM_mallocN(sizeof(SpinLock), "main lock");
BLI_spin_init((SpinLock *)bmain->lock);
return bmain;
@@ -1082,6 +1100,8 @@ void BKE_main_free(Main *mainvar)
ListBase *lbarray[MAX_LIBARRAY];
int a;
+ MEM_SAFE_FREE(mainvar->blen_thumb);
+
a = set_listbasepointers(mainvar, lbarray);
while (a--) {
ListBase *lb = lbarray[a];
@@ -1127,6 +1147,7 @@ void BKE_main_free(Main *mainvar)
case 30: BKE_libblock_free_ex(mainvar, id, false); break;
case 31: BKE_libblock_free_ex(mainvar, id, false); break;
case 32: BKE_libblock_free_ex(mainvar, id, false); break;
+ case 33: BKE_libblock_free_ex(mainvar, id, false); break;
default:
BLI_assert(0);
break;
@@ -1137,7 +1158,7 @@ void BKE_main_free(Main *mainvar)
BLI_spin_end((SpinLock *)mainvar->lock);
MEM_freeN(mainvar->lock);
- MEM_freeN(mainvar->eval_ctx);
+ DEG_evaluation_context_free(mainvar->eval_ctx);
MEM_freeN(mainvar);
}
@@ -1151,6 +1172,74 @@ void BKE_main_unlock(struct Main *bmain)
BLI_spin_unlock((SpinLock *) bmain->lock);
}
+/**
+ * Generates a raw .blend file thumbnail data from given image.
+ *
+ * \param bmain If not NULL, also store generated data in this Main.
+ * \param img ImBuf image to generate thumbnail data from.
+ * \return The generated .blend file raw thumbnail data.
+ */
+BlendThumbnail *BKE_main_thumbnail_from_imbuf(Main *bmain, ImBuf *img)
+{
+ BlendThumbnail *data = NULL;
+
+ if (bmain) {
+ MEM_SAFE_FREE(bmain->blen_thumb);
+ }
+
+ if (img) {
+ const size_t sz = BLEN_THUMB_MEMSIZE(img->x, img->y);
+ data = MEM_mallocN(sz, __func__);
+
+ IMB_rect_from_float(img); /* Just in case... */
+ data->width = img->x;
+ data->height = img->y;
+ memcpy(data->rect, img->rect, sz - sizeof(*data));
+ }
+
+ if (bmain) {
+ bmain->blen_thumb = data;
+ }
+ return data;
+}
+
+/**
+ * Generates an image from raw .blend file thumbnail \a data.
+ *
+ * \param bmain Use this bmain->blen_thumb data if given \a data is NULL.
+ * \param data Raw .blend file thumbnail data.
+ * \return An ImBuf from given data, or NULL if invalid.
+ */
+ImBuf *BKE_main_thumbnail_to_imbuf(Main *bmain, BlendThumbnail *data)
+{
+ ImBuf *img = NULL;
+
+ if (!data && bmain) {
+ data = bmain->blen_thumb;
+ }
+
+ if (data) {
+ /* Note: we cannot use IMB_allocFromBuffer(), since it tries to dupalloc passed buffer, which will fail
+ * here (we do not want to pass the first two ints!). */
+ img = IMB_allocImBuf((unsigned int)data->width, (unsigned int)data->height, 32, IB_rect | IB_metadata);
+ memcpy(img->rect, data->rect, BLEN_THUMB_MEMSIZE(data->width, data->height) - sizeof(*data));
+ }
+
+ return img;
+}
+
+/**
+ * Generates an empty (black) thumbnail for given Main.
+ */
+void BKE_main_thumbnail_create(struct Main *bmain)
+{
+ MEM_SAFE_FREE(bmain->blen_thumb);
+
+ bmain->blen_thumb = MEM_callocN(BLEN_THUMB_MEMSIZE(BLEN_THUMB_SIZE, BLEN_THUMB_SIZE), __func__);
+ bmain->blen_thumb->width = BLEN_THUMB_SIZE;
+ bmain->blen_thumb->height = BLEN_THUMB_SIZE;
+}
+
/* ***************** ID ************************ */
ID *BKE_libblock_find_name_ex(struct Main *bmain, const short type, const char *name)
{
@@ -1202,7 +1291,7 @@ static ID *is_dupid(ListBase *lb, ID *id, const char *name)
/* do not test alphabetic! */
/* optimized */
if (idtest->name[2] == name[0]) {
- if (strcmp(name, idtest->name + 2) == 0) break;
+ if (STREQ(name, idtest->name + 2)) break;
}
}
}
@@ -1260,7 +1349,7 @@ static bool check_for_dupid(ListBase *lb, ID *id, char *name)
if ( (id != idtest) &&
(idtest->lib == NULL) &&
(*name == *(idtest->name + 2)) &&
- (strncmp(name, idtest->name + 2, left_len) == 0) &&
+ STREQLEN(name, idtest->name + 2, left_len) &&
(BLI_split_name_num(leftest, &nrtest, idtest->name + 2, '.') == left_len)
)
{
@@ -1403,16 +1492,20 @@ void id_clear_lib_data(Main *bmain, ID *id)
/* internal bNodeTree blocks inside ID types below
* also stores id->lib, make sure this stays in sync.
*/
- switch (GS(id->name)) {
- case ID_SCE: ntree = ((Scene *)id)->nodetree; break;
- case ID_MA: ntree = ((Material *)id)->nodetree; break;
- case ID_LA: ntree = ((Lamp *)id)->nodetree; break;
- case ID_WO: ntree = ((World *)id)->nodetree; break;
- case ID_TE: ntree = ((Tex *)id)->nodetree; break;
- case ID_LS: ntree = ((FreestyleLineStyle *)id)->nodetree; break;
- }
- if (ntree)
+ ntree = ntreeFromID(id);
+
+ if (ntree) {
ntree->id.lib = NULL;
+ }
+
+ if (GS(id->name) == ID_OB) {
+ Object *object = (Object *)id;
+ if (object->proxy_from != NULL) {
+ object->proxy_from->proxy = NULL;
+ object->proxy_from->proxy_group = NULL;
+ }
+ object->proxy = object->proxy_from = object->proxy_group = NULL;
+ }
}
/* next to indirect usage in read/writefile also in editobject.c scene.c */
@@ -1571,7 +1664,7 @@ void test_idbutton(char *name)
ID *idtest;
- lb = which_libbase(G.main, GS(name) );
+ lb = which_libbase(G.main, GS(name));
if (lb == NULL) return;
/* search for id */
@@ -1590,7 +1683,7 @@ void rename_id(ID *id, const char *name)
ListBase *lb;
BLI_strncpy(id->name + 2, name, sizeof(id->name) - 2);
- lb = which_libbase(G.main, GS(id->name) );
+ lb = which_libbase(G.main, GS(id->name));
new_id(lb, id, name);
}
@@ -1602,7 +1695,7 @@ void rename_id(ID *id, const char *name)
void name_uiprefix_id(char *name, const ID *id)
{
name[0] = id->lib ? 'L' : ' ';
- name[1] = id->flag & LIB_FAKEUSER ? 'F' : (id->us == 0) ? '0' : ' ';
+ name[1] = (id->flag & LIB_FAKEUSER) ? 'F' : ((id->us == 0) ? '0' : ' ');
name[2] = ' ';
strcpy(name + 3, id->name + 2);
diff --git a/source/blender/blenkernel/intern/linestyle.c b/source/blender/blenkernel/intern/linestyle.c
index 45695844101..ac2c4e35dce 100644
--- a/source/blender/blenkernel/intern/linestyle.c
+++ b/source/blender/blenkernel/intern/linestyle.c
@@ -53,8 +53,6 @@
#include "BKE_colortools.h"
#include "BKE_animsys.h"
-#include "RNA_access.h"
-
static const char *modifier_name[LS_MODIFIER_NUM] = {
NULL,
"Along Stroke",
@@ -75,6 +73,11 @@ static const char *modifier_name[LS_MODIFIER_NUM] = {
"Blueprint",
"2D Offset",
"2D Transform",
+ "Tangent",
+ "Noise",
+ "Crease Angle",
+ "Simplification",
+ "3D Curvature",
};
static void default_linestyle_settings(FreestyleLineStyle *linestyle)
@@ -93,6 +96,7 @@ static void default_linestyle_settings(FreestyleLineStyle *linestyle)
linestyle->min_length = 0.0f;
linestyle->max_length = 10000.0f;
linestyle->split_length = 100;
+ linestyle->chain_count = 10;
linestyle->sort_key = LS_SORT_KEY_DISTANCE_FROM_CAMERA;
linestyle->integration_type = LS_INTEGRATION_MEAN;
linestyle->texstep = 1.0f;
@@ -108,14 +112,11 @@ static void default_linestyle_settings(FreestyleLineStyle *linestyle)
linestyle->caps = LS_CAPS_BUTT;
}
-FreestyleLineStyle *BKE_linestyle_new(const char *name, struct Main *main)
+FreestyleLineStyle *BKE_linestyle_new(struct Main *bmain, const char *name)
{
FreestyleLineStyle *linestyle;
- if (!main)
- main = G.main;
-
- linestyle = (FreestyleLineStyle *)BKE_libblock_alloc(main, ID_LS, name);
+ linestyle = (FreestyleLineStyle *)BKE_libblock_alloc(bmain, ID_LS, name);
default_linestyle_settings(linestyle);
@@ -139,7 +140,7 @@ void BKE_linestyle_free(FreestyleLineStyle *linestyle)
MEM_freeN(linestyle->nodetree);
}
- BKE_free_animdata(&linestyle->id);
+ BKE_animdata_free(&linestyle->id);
while ((m = (LineStyleModifier *)linestyle->color_modifiers.first))
BKE_linestyle_color_modifier_remove(linestyle, m);
while ((m = (LineStyleModifier *)linestyle->alpha_modifiers.first))
@@ -150,13 +151,13 @@ void BKE_linestyle_free(FreestyleLineStyle *linestyle)
BKE_linestyle_geometry_modifier_remove(linestyle, m);
}
-FreestyleLineStyle *BKE_linestyle_copy(FreestyleLineStyle *linestyle)
+FreestyleLineStyle *BKE_linestyle_copy(struct Main *bmain, FreestyleLineStyle *linestyle)
{
FreestyleLineStyle *new_linestyle;
LineStyleModifier *m;
int a;
- new_linestyle = BKE_linestyle_new(linestyle->id.name + 2, NULL);
+ new_linestyle = BKE_linestyle_new(bmain, linestyle->id.name + 2);
BKE_linestyle_free(new_linestyle);
for (a = 0; a < MAX_MTEX; a++) {
@@ -186,6 +187,7 @@ FreestyleLineStyle *BKE_linestyle_copy(FreestyleLineStyle *linestyle)
new_linestyle->max_angle = linestyle->max_angle;
new_linestyle->min_length = linestyle->min_length;
new_linestyle->max_length = linestyle->max_length;
+ new_linestyle->chain_count = linestyle->chain_count;
new_linestyle->split_dash1 = linestyle->split_dash1;
new_linestyle->split_gap1 = linestyle->split_gap1;
new_linestyle->split_dash2 = linestyle->split_dash2;
@@ -199,8 +201,11 @@ FreestyleLineStyle *BKE_linestyle_copy(FreestyleLineStyle *linestyle)
new_linestyle->dash3 = linestyle->dash3;
new_linestyle->gap3 = linestyle->gap3;
new_linestyle->panel = linestyle->panel;
+ new_linestyle->sort_key = linestyle->sort_key;
+ new_linestyle->integration_type = linestyle->integration_type;
new_linestyle->texstep = linestyle->texstep;
new_linestyle->pr_texture = linestyle->pr_texture;
+ new_linestyle->use_nodes = linestyle->use_nodes;
for (m = (LineStyleModifier *)linestyle->color_modifiers.first; m; m = m->next)
BKE_linestyle_color_modifier_copy(new_linestyle, m);
for (m = (LineStyleModifier *)linestyle->alpha_modifiers.first; m; m = m->next)
@@ -210,6 +215,10 @@ FreestyleLineStyle *BKE_linestyle_copy(FreestyleLineStyle *linestyle)
for (m = (LineStyleModifier *)linestyle->geometry_modifiers.first; m; m = m->next)
BKE_linestyle_geometry_modifier_copy(new_linestyle, m);
+ if (linestyle->id.lib) {
+ BKE_id_lib_local_paths(G.main, linestyle->id.lib, &new_linestyle->id);
+ }
+
return new_linestyle;
}
@@ -264,6 +273,18 @@ static LineStyleModifier *alloc_color_modifier(const char *name, int type)
case LS_MODIFIER_MATERIAL:
size = sizeof(LineStyleColorModifier_Material);
break;
+ case LS_MODIFIER_TANGENT:
+ size = sizeof(LineStyleColorModifier_Tangent);
+ break;
+ case LS_MODIFIER_NOISE:
+ size = sizeof(LineStyleColorModifier_Noise);
+ break;
+ case LS_MODIFIER_CREASE_ANGLE:
+ size = sizeof(LineStyleColorModifier_CreaseAngle);
+ break;
+ case LS_MODIFIER_CURVATURE_3D:
+ size = sizeof(LineStyleColorModifier_Curvature_3D);
+ break;
default:
return NULL; /* unknown modifier type */
}
@@ -276,6 +297,9 @@ LineStyleModifier *BKE_linestyle_color_modifier_add(FreestyleLineStyle *linestyl
LineStyleModifier *m;
m = alloc_color_modifier(name, type);
+ if (UNLIKELY(m == NULL)) {
+ return NULL;
+ }
m->blend = MA_RAMP_BLEND;
switch (type) {
@@ -297,6 +321,25 @@ LineStyleModifier *BKE_linestyle_color_modifier_add(FreestyleLineStyle *linestyl
((LineStyleColorModifier_Material *)m)->color_ramp = add_colorband(1);
((LineStyleColorModifier_Material *)m)->mat_attr = LS_MODIFIER_MATERIAL_LINE;
break;
+ case LS_MODIFIER_TANGENT:
+ ((LineStyleColorModifier_Tangent *)m)->color_ramp = add_colorband(1);
+ break;
+ case LS_MODIFIER_NOISE:
+ ((LineStyleColorModifier_Noise *)m)->color_ramp = add_colorband(1);
+ ((LineStyleColorModifier_Noise *)m)->amplitude = 10.0f;
+ ((LineStyleColorModifier_Noise *)m)->period = 10.0f;
+ ((LineStyleColorModifier_Noise *)m)->seed = 512;
+ break;
+ case LS_MODIFIER_CREASE_ANGLE:
+ ((LineStyleColorModifier_CreaseAngle *)m)->color_ramp = add_colorband(1);
+ ((LineStyleColorModifier_CreaseAngle *)m)->min_angle = 0.0f;
+ ((LineStyleColorModifier_CreaseAngle *)m)->max_angle = DEG2RADF(180.0f);
+ break;
+ case LS_MODIFIER_CURVATURE_3D:
+ ((LineStyleColorModifier_Curvature_3D *)m)->color_ramp = add_colorband(1);
+ ((LineStyleColorModifier_Curvature_3D *)m)->min_curvature = 0.0f;
+ ((LineStyleColorModifier_Curvature_3D *)m)->max_curvature = 0.5f;
+ break;
default:
return NULL; /* unknown modifier type */
}
@@ -310,6 +353,9 @@ LineStyleModifier *BKE_linestyle_color_modifier_copy(FreestyleLineStyle *linesty
LineStyleModifier *new_m;
new_m = alloc_color_modifier(m->name, m->type);
+ if (UNLIKELY(new_m == NULL)) {
+ return NULL;
+ }
new_m->influence = m->influence;
new_m->flags = m->flags;
new_m->blend = m->blend;
@@ -352,6 +398,41 @@ LineStyleModifier *BKE_linestyle_color_modifier_copy(FreestyleLineStyle *linesty
q->mat_attr = p->mat_attr;
break;
}
+ case LS_MODIFIER_TANGENT:
+ {
+ LineStyleColorModifier_Tangent *p = (LineStyleColorModifier_Tangent *)m;
+ LineStyleColorModifier_Tangent *q = (LineStyleColorModifier_Tangent *)new_m;
+ q->color_ramp = MEM_dupallocN(p->color_ramp);
+ break;
+ }
+ case LS_MODIFIER_NOISE:
+ {
+ LineStyleColorModifier_Noise *p = (LineStyleColorModifier_Noise *)m;
+ LineStyleColorModifier_Noise *q = (LineStyleColorModifier_Noise *)new_m;
+ q->color_ramp = MEM_dupallocN(p->color_ramp);
+ q->amplitude = p->amplitude;
+ q->period = p->period;
+ q->seed = p->seed;
+ break;
+ }
+ case LS_MODIFIER_CREASE_ANGLE:
+ {
+ LineStyleColorModifier_CreaseAngle *p = (LineStyleColorModifier_CreaseAngle *)m;
+ LineStyleColorModifier_CreaseAngle *q = (LineStyleColorModifier_CreaseAngle *)new_m;
+ q->color_ramp = MEM_dupallocN(p->color_ramp);
+ q->min_angle = p->min_angle;
+ q->max_angle = p->max_angle;
+ break;
+ }
+ case LS_MODIFIER_CURVATURE_3D:
+ {
+ LineStyleColorModifier_Curvature_3D *p = (LineStyleColorModifier_Curvature_3D *)m;
+ LineStyleColorModifier_Curvature_3D *q = (LineStyleColorModifier_Curvature_3D *)new_m;
+ q->color_ramp = MEM_dupallocN(p->color_ramp);
+ q->min_curvature = p->min_curvature;
+ q->max_curvature = p->max_curvature;
+ break;
+ }
default:
return NULL; /* unknown modifier type */
}
@@ -377,6 +458,18 @@ int BKE_linestyle_color_modifier_remove(FreestyleLineStyle *linestyle, LineStyle
case LS_MODIFIER_MATERIAL:
MEM_freeN(((LineStyleColorModifier_Material *)m)->color_ramp);
break;
+ case LS_MODIFIER_TANGENT:
+ MEM_freeN(((LineStyleColorModifier_Tangent *)m)->color_ramp);
+ break;
+ case LS_MODIFIER_NOISE:
+ MEM_freeN(((LineStyleColorModifier_Noise *)m)->color_ramp);
+ break;
+ case LS_MODIFIER_CREASE_ANGLE:
+ MEM_freeN(((LineStyleColorModifier_CreaseAngle *)m)->color_ramp);
+ break;
+ case LS_MODIFIER_CURVATURE_3D:
+ MEM_freeN(((LineStyleColorModifier_Curvature_3D *)m)->color_ramp);
+ break;
}
BLI_freelinkN(&linestyle->color_modifiers, m);
return 0;
@@ -399,6 +492,18 @@ static LineStyleModifier *alloc_alpha_modifier(const char *name, int type)
case LS_MODIFIER_MATERIAL:
size = sizeof(LineStyleAlphaModifier_Material);
break;
+ case LS_MODIFIER_TANGENT:
+ size = sizeof(LineStyleAlphaModifier_Tangent);
+ break;
+ case LS_MODIFIER_NOISE:
+ size = sizeof(LineStyleAlphaModifier_Noise);
+ break;
+ case LS_MODIFIER_CREASE_ANGLE:
+ size = sizeof(LineStyleAlphaModifier_CreaseAngle);
+ break;
+ case LS_MODIFIER_CURVATURE_3D:
+ size = sizeof(LineStyleAlphaModifier_Curvature_3D);
+ break;
default:
return NULL; /* unknown modifier type */
}
@@ -440,7 +545,38 @@ LineStyleModifier *BKE_linestyle_alpha_modifier_add(FreestyleLineStyle *linestyl
{
LineStyleAlphaModifier_Material *p = (LineStyleAlphaModifier_Material *)m;
p->curve = curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f);
- p->mat_attr = LS_MODIFIER_MATERIAL_ALPHA;
+ p->mat_attr = LS_MODIFIER_MATERIAL_LINE_A;
+ break;
+ }
+ case LS_MODIFIER_TANGENT:
+ {
+ LineStyleAlphaModifier_Tangent *p = (LineStyleAlphaModifier_Tangent *)m;
+ p->curve = curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f);
+ break;
+ }
+ case LS_MODIFIER_NOISE:
+ {
+ LineStyleAlphaModifier_Noise *p = (LineStyleAlphaModifier_Noise *)m;
+ p->curve = curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f);
+ ((LineStyleAlphaModifier_Noise *)m)->amplitude = 10.0f;
+ ((LineStyleAlphaModifier_Noise *)m)->period = 10.0f;
+ ((LineStyleAlphaModifier_Noise *)m)->seed = 512;
+ break;
+ }
+ case LS_MODIFIER_CREASE_ANGLE:
+ {
+ LineStyleAlphaModifier_CreaseAngle *p = (LineStyleAlphaModifier_CreaseAngle *)m;
+ p->curve = curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f);
+ ((LineStyleAlphaModifier_CreaseAngle *)m)->min_angle = 0.0f;
+ ((LineStyleAlphaModifier_CreaseAngle *)m)->max_angle = DEG2RADF(180.0f);
+ break;
+ }
+ case LS_MODIFIER_CURVATURE_3D:
+ {
+ LineStyleAlphaModifier_Curvature_3D *p = (LineStyleAlphaModifier_Curvature_3D *)m;
+ p->curve = curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f);
+ ((LineStyleAlphaModifier_Curvature_3D *)m)->min_curvature = 0.0f;
+ ((LineStyleAlphaModifier_Curvature_3D *)m)->max_curvature = 0.5f;
break;
}
default:
@@ -501,6 +637,45 @@ LineStyleModifier *BKE_linestyle_alpha_modifier_copy(FreestyleLineStyle *linesty
q->mat_attr = p->mat_attr;
break;
}
+ case LS_MODIFIER_TANGENT:
+ {
+ LineStyleAlphaModifier_Tangent *p = (LineStyleAlphaModifier_Tangent *)m;
+ LineStyleAlphaModifier_Tangent *q = (LineStyleAlphaModifier_Tangent *)new_m;
+ q->curve = curvemapping_copy(p->curve);
+ q->flags = p->flags;
+ break;
+ }
+ case LS_MODIFIER_NOISE:
+ {
+ LineStyleAlphaModifier_Noise *p = (LineStyleAlphaModifier_Noise *)m;
+ LineStyleAlphaModifier_Noise *q = (LineStyleAlphaModifier_Noise *)new_m;
+ q->curve = curvemapping_copy(p->curve);
+ q->flags = p->flags;
+ q->amplitude = p->amplitude;
+ q->period = p->period;
+ q->seed = p->seed;
+ break;
+ }
+ case LS_MODIFIER_CREASE_ANGLE:
+ {
+ LineStyleAlphaModifier_CreaseAngle *p = (LineStyleAlphaModifier_CreaseAngle *)m;
+ LineStyleAlphaModifier_CreaseAngle *q = (LineStyleAlphaModifier_CreaseAngle *)new_m;
+ q->curve = curvemapping_copy(p->curve);
+ q->flags = p->flags;
+ q->min_angle = p->min_angle;
+ q->max_angle = p->max_angle;
+ break;
+ }
+ case LS_MODIFIER_CURVATURE_3D:
+ {
+ LineStyleAlphaModifier_Curvature_3D *p = (LineStyleAlphaModifier_Curvature_3D *)m;
+ LineStyleAlphaModifier_Curvature_3D *q = (LineStyleAlphaModifier_Curvature_3D *)new_m;
+ q->curve = curvemapping_copy(p->curve);
+ q->flags = p->flags;
+ q->min_curvature = p->min_curvature;
+ q->max_curvature = p->max_curvature;
+ break;
+ }
default:
return NULL; /* unknown modifier type */
}
@@ -526,6 +701,18 @@ int BKE_linestyle_alpha_modifier_remove(FreestyleLineStyle *linestyle, LineStyle
case LS_MODIFIER_MATERIAL:
curvemapping_free(((LineStyleAlphaModifier_Material *)m)->curve);
break;
+ case LS_MODIFIER_TANGENT:
+ curvemapping_free(((LineStyleAlphaModifier_Tangent *)m)->curve);
+ break;
+ case LS_MODIFIER_NOISE:
+ curvemapping_free(((LineStyleAlphaModifier_Noise *)m)->curve);
+ break;
+ case LS_MODIFIER_CREASE_ANGLE:
+ curvemapping_free(((LineStyleAlphaModifier_CreaseAngle *)m)->curve);
+ break;
+ case LS_MODIFIER_CURVATURE_3D:
+ curvemapping_free(((LineStyleAlphaModifier_Curvature_3D *)m)->curve);
+ break;
}
BLI_freelinkN(&linestyle->alpha_modifiers, m);
return 0;
@@ -551,6 +738,18 @@ static LineStyleModifier *alloc_thickness_modifier(const char *name, int type)
case LS_MODIFIER_CALLIGRAPHY:
size = sizeof(LineStyleThicknessModifier_Calligraphy);
break;
+ case LS_MODIFIER_TANGENT:
+ size = sizeof(LineStyleThicknessModifier_Tangent);
+ break;
+ case LS_MODIFIER_NOISE:
+ size = sizeof(LineStyleThicknessModifier_Noise);
+ break;
+ case LS_MODIFIER_CREASE_ANGLE:
+ size = sizeof(LineStyleThicknessModifier_CreaseAngle);
+ break;
+ case LS_MODIFIER_CURVATURE_3D:
+ size = sizeof(LineStyleThicknessModifier_Curvature_3D);
+ break;
default:
return NULL; /* unknown modifier type */
}
@@ -612,6 +811,43 @@ LineStyleModifier *BKE_linestyle_thickness_modifier_add(FreestyleLineStyle *line
p->orientation = DEG2RADF(60.0f);
break;
}
+ case LS_MODIFIER_TANGENT:
+ {
+ LineStyleThicknessModifier_Tangent *p = (LineStyleThicknessModifier_Tangent *)m;
+ p->curve = curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f);
+ p->min_thickness = 1.0f;
+ p->max_thickness = 10.0f;
+ break;
+ }
+ case LS_MODIFIER_NOISE:
+ {
+ LineStyleThicknessModifier_Noise *p = (LineStyleThicknessModifier_Noise *)m;
+ p->period = 10.0f;
+ p->amplitude = 10.0f;
+ p->seed = 512;
+ p->flags = LS_THICKNESS_ASYMMETRIC;
+ break;
+ }
+ case LS_MODIFIER_CREASE_ANGLE:
+ {
+ LineStyleThicknessModifier_CreaseAngle *p = (LineStyleThicknessModifier_CreaseAngle *)m;
+ p->curve = curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f);
+ p->min_angle = 0.0f;
+ p->max_angle = DEG2RADF(180.0f);
+ p->min_thickness = 1.0f;
+ p->max_thickness = 10.0f;
+ break;
+ }
+ case LS_MODIFIER_CURVATURE_3D:
+ {
+ LineStyleThicknessModifier_Curvature_3D *p = (LineStyleThicknessModifier_Curvature_3D *)m;
+ p->curve = curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f);
+ p->min_curvature = 0.0f;
+ p->max_curvature = 0.5f;
+ p->min_thickness = 1.0f;
+ p->max_thickness = 10.0f;
+ break;
+ }
default:
return NULL; /* unknown modifier type */
}
@@ -689,6 +925,50 @@ LineStyleModifier *BKE_linestyle_thickness_modifier_copy(FreestyleLineStyle *lin
q->orientation = p->orientation;
break;
}
+ case LS_MODIFIER_TANGENT:
+ {
+ LineStyleThicknessModifier_Tangent *p = (LineStyleThicknessModifier_Tangent *)m;
+ LineStyleThicknessModifier_Tangent *q = (LineStyleThicknessModifier_Tangent *)new_m;
+ q->curve = curvemapping_copy(p->curve);
+ q->flags = p->flags;
+ q->min_thickness = p->min_thickness;
+ q->max_thickness = p->max_thickness;
+ break;
+ }
+ case LS_MODIFIER_NOISE:
+ {
+ LineStyleThicknessModifier_Noise *p = (LineStyleThicknessModifier_Noise *)m;
+ LineStyleThicknessModifier_Noise *q = (LineStyleThicknessModifier_Noise *)new_m;
+ q->amplitude = p->amplitude;
+ q->period = p->period;
+ q->seed = p->seed;
+ q->flags = p->flags;
+ break;
+ }
+ case LS_MODIFIER_CURVATURE_3D:
+ {
+ LineStyleThicknessModifier_Curvature_3D *p = (LineStyleThicknessModifier_Curvature_3D *)m;
+ LineStyleThicknessModifier_Curvature_3D *q = (LineStyleThicknessModifier_Curvature_3D *)new_m;
+ q->curve = curvemapping_copy(p->curve);
+ q->flags = p->flags;
+ q->min_curvature = p->min_curvature;
+ q->max_curvature = p->max_curvature;
+ q->min_thickness = p->min_thickness;
+ q->max_thickness = p->max_thickness;
+ break;
+ }
+ case LS_MODIFIER_CREASE_ANGLE:
+ {
+ LineStyleThicknessModifier_CreaseAngle *p = (LineStyleThicknessModifier_CreaseAngle *)m;
+ LineStyleThicknessModifier_CreaseAngle *q = (LineStyleThicknessModifier_CreaseAngle *)new_m;
+ q->curve = curvemapping_copy(p->curve);
+ q->flags = p->flags;
+ q->min_angle = p->min_angle;
+ q->max_angle = p->max_angle;
+ q->min_thickness = p->min_thickness;
+ q->max_thickness = p->max_thickness;
+ break;
+ }
default:
return NULL; /* unknown modifier type */
}
@@ -716,6 +996,15 @@ int BKE_linestyle_thickness_modifier_remove(FreestyleLineStyle *linestyle, LineS
break;
case LS_MODIFIER_CALLIGRAPHY:
break;
+ case LS_MODIFIER_TANGENT:
+ curvemapping_free(((LineStyleThicknessModifier_Tangent *)m)->curve);
+ break;
+ case LS_MODIFIER_NOISE:
+ break;
+ case LS_MODIFIER_CREASE_ANGLE:
+ break;
+ case LS_MODIFIER_CURVATURE_3D:
+ break;
}
BLI_freelinkN(&linestyle->thickness_modifiers, m);
return 0;
@@ -765,6 +1054,9 @@ static LineStyleModifier *alloc_geometry_modifier(const char *name, int type)
case LS_MODIFIER_2D_TRANSFORM:
size = sizeof(LineStyleGeometryModifier_2DTransform);
break;
+ case LS_MODIFIER_SIMPLIFICATION:
+ size = sizeof(LineStyleGeometryModifier_Simplification);
+ break;
default:
return NULL; /* unknown modifier type */
}
@@ -882,6 +1174,12 @@ LineStyleModifier *BKE_linestyle_geometry_modifier_add(FreestyleLineStyle *lines
p->pivot_y = 0.0f;
break;
}
+ case LS_MODIFIER_SIMPLIFICATION:
+ {
+ LineStyleGeometryModifier_Simplification *p = (LineStyleGeometryModifier_Simplification *)m;
+ p->tolerance = 0.1f;
+ break;
+ }
default:
return NULL; /* unknown modifier type */
}
@@ -1016,6 +1314,13 @@ LineStyleModifier *BKE_linestyle_geometry_modifier_copy(FreestyleLineStyle *line
q->pivot_y = p->pivot_y;
break;
}
+ case LS_MODIFIER_SIMPLIFICATION:
+ {
+ LineStyleGeometryModifier_Simplification *p = (LineStyleGeometryModifier_Simplification *)m;
+ LineStyleGeometryModifier_Simplification *q = (LineStyleGeometryModifier_Simplification *)new_m;
+ q->tolerance = p->tolerance;
+ break;
+ }
default:
return NULL; /* unknown modifier type */
}
@@ -1115,6 +1420,22 @@ char *BKE_linestyle_path_to_color_ramp(FreestyleLineStyle *linestyle, ColorBand
if (color_ramp == ((LineStyleColorModifier_Material *)m)->color_ramp)
found = true;
break;
+ case LS_MODIFIER_TANGENT:
+ if (color_ramp == ((LineStyleColorModifier_Tangent *)m)->color_ramp)
+ found = true;
+ break;
+ case LS_MODIFIER_NOISE:
+ if (color_ramp == ((LineStyleColorModifier_Noise *)m)->color_ramp)
+ found = true;
+ break;
+ case LS_MODIFIER_CREASE_ANGLE:
+ if (color_ramp == ((LineStyleColorModifier_CreaseAngle *)m)->color_ramp)
+ found = true;
+ break;
+ case LS_MODIFIER_CURVATURE_3D:
+ if (color_ramp == ((LineStyleColorModifier_Curvature_3D *)m)->color_ramp)
+ found = true;
+ break;
}
if (found) {
diff --git a/source/blender/blenkernel/intern/mask.c b/source/blender/blenkernel/intern/mask.c
index 83ad2f1b2d2..141597e859c 100644
--- a/source/blender/blenkernel/intern/mask.c
+++ b/source/blender/blenkernel/intern/mask.c
@@ -41,7 +41,7 @@
#include "BLI_listbase.h"
#include "BLI_math.h"
-#include "BLF_translation.h"
+#include "BLT_translation.h"
#include "DNA_mask_types.h"
#include "DNA_node_types.h"
@@ -49,7 +49,9 @@
#include "DNA_space_types.h"
#include "DNA_sequence_types.h"
+#include "BKE_animsys.h"
#include "BKE_curve.h"
+#include "BKE_global.h"
#include "BKE_library.h"
#include "BKE_main.h"
#include "BKE_mask.h"
@@ -59,8 +61,6 @@
#include "BKE_movieclip.h"
#include "BKE_image.h"
-#include "NOD_composite.h"
-
static struct {
ListBase splines;
struct GHash *id_hash;
@@ -182,6 +182,16 @@ void BKE_mask_layer_unique_name(Mask *mask, MaskLayer *masklay)
sizeof(masklay->name));
}
+void BKE_mask_layer_rename(Mask *mask, MaskLayer *masklay, char *oldname, char *newname)
+{
+ BLI_strncpy(masklay->name, newname, sizeof(masklay->name));
+
+ BKE_mask_layer_unique_name(mask, masklay);
+
+ /* now fix animation paths */
+ BKE_animdata_fix_paths_rename_all(&mask->id, "layers", oldname, masklay->name);
+}
+
MaskLayer *BKE_mask_layer_copy(MaskLayer *masklay)
{
MaskLayer *masklay_new;
@@ -857,6 +867,10 @@ Mask *BKE_mask_copy(Mask *mask)
mask_new->id.us++;
}
+ if (mask->id.lib) {
+ BKE_id_lib_local_paths(G.main, mask->id.lib, &mask_new->id);
+ }
+
return mask_new;
}
@@ -1187,11 +1201,12 @@ void BKE_mask_point_parent_matrix_get(MaskSplinePoint *point, float ctime, float
MovieTrackingPlaneTrack *plane_track = BKE_tracking_plane_track_get_named(tracking, ob, parent->sub_parent);
if (plane_track) {
- MovieTrackingPlaneMarker *plane_marker = BKE_tracking_plane_marker_get(plane_track, clip_framenr);
+ float corners[4][2];
float aspx, aspy;
float frame_size[2], H[3][3], mask_from_clip_matrix[3][3], mask_to_clip_matrix[3][3];
- BKE_tracking_homography_between_two_quads(parent->parent_corners_orig, plane_marker->corners, H);
+ BKE_tracking_plane_marker_get_subframe_corners(plane_track, ctime, corners);
+ BKE_tracking_homography_between_two_quads(parent->parent_corners_orig, corners, H);
unit_m3(mask_from_clip_matrix);
@@ -1457,7 +1472,7 @@ void BKE_mask_layer_evaluate(MaskLayer *masklay, const float ctime, const bool d
{
if (found == 1) {
#if 0
- printf("%s: exact %d %d (%d)\n", __func__, (int)ctime, BLI_countlist(&masklay->splines_shapes),
+ printf("%s: exact %d %d (%d)\n", __func__, (int)ctime, BLI_listbase_count(&masklay->splines_shapes),
masklay_shape_a->frame);
#endif
@@ -1466,7 +1481,7 @@ void BKE_mask_layer_evaluate(MaskLayer *masklay, const float ctime, const bool d
else if (found == 2) {
float w = masklay_shape_b->frame - masklay_shape_a->frame;
#if 0
- printf("%s: tween %d %d (%d %d)\n", __func__, (int)ctime, BLI_countlist(&masklay->splines_shapes),
+ printf("%s: tween %d %d (%d %d)\n", __func__, (int)ctime, BLI_listbase_count(&masklay->splines_shapes),
masklay_shape_a->frame, masklay_shape_b->frame);
#endif
BKE_mask_layer_shape_to_mask_interp(masklay, masklay_shape_a, masklay_shape_b,
@@ -1833,7 +1848,7 @@ static int mask_layer_shape_sort_cb(const void *masklay_shape_a_ptr, const void
void BKE_mask_layer_shape_sort(MaskLayer *masklay)
{
- BLI_sortlist(&masklay->splines_shapes, mask_layer_shape_sort_cb);
+ BLI_listbase_sort(&masklay->splines_shapes, mask_layer_shape_sort_cb);
}
bool BKE_mask_layer_shape_spline_from_index(MaskLayer *masklay, int index,
diff --git a/source/blender/blenkernel/intern/mask_evaluate.c b/source/blender/blenkernel/intern/mask_evaluate.c
index 3ed6148054c..5517fc36bc1 100644
--- a/source/blender/blenkernel/intern/mask_evaluate.c
+++ b/source/blender/blenkernel/intern/mask_evaluate.c
@@ -40,8 +40,6 @@
#include "BLI_math.h"
#include "DNA_mask_types.h"
-#include "DNA_node_types.h"
-#include "DNA_scene_types.h"
#include "BKE_curve.h"
#include "BKE_mask.h"
diff --git a/source/blender/blenkernel/intern/mask_rasterize.c b/source/blender/blenkernel/intern/mask_rasterize.c
index 4dc8ed21463..13ec970c65c 100644
--- a/source/blender/blenkernel/intern/mask_rasterize.c
+++ b/source/blender/blenkernel/intern/mask_rasterize.c
@@ -572,7 +572,7 @@ void BKE_maskrasterize_handle_init(MaskRasterHandle *mr_handle, struct Mask *mas
unsigned int masklay_index;
MemArena *sf_arena;
- mr_handle->layers_tot = (unsigned int)BLI_countlist(&mask->masklayers);
+ mr_handle->layers_tot = (unsigned int)BLI_listbase_count(&mask->masklayers);
mr_handle->layers = MEM_mallocN(sizeof(MaskRasterLayer) * mr_handle->layers_tot, "MaskRasterLayer");
BLI_rctf_init_minmax(&mr_handle->bounds);
@@ -608,7 +608,7 @@ void BKE_maskrasterize_handle_init(MaskRasterHandle *mr_handle, struct Mask *mas
continue;
}
- tot_splines = (unsigned int)BLI_countlist(&masklay->splines);
+ tot_splines = (unsigned int)BLI_listbase_count(&masklay->splines);
open_spline_ranges = MEM_callocN(sizeof(*open_spline_ranges) * tot_splines, __func__);
BLI_scanfill_begin_arena(&sf_ctx, sf_arena);
@@ -956,7 +956,7 @@ void BKE_maskrasterize_handle_init(MaskRasterHandle *mr_handle, struct Mask *mas
&isect_remvertbase,
&isect_remedgebase)))
{
- unsigned int sf_vert_tot_isect = (unsigned int)BLI_countlist(&sf_ctx.fillvertbase);
+ unsigned int sf_vert_tot_isect = (unsigned int)BLI_listbase_count(&sf_ctx.fillvertbase);
unsigned int i = sf_vert_tot;
face_coords = MEM_reallocN(face_coords, sizeof(float[3]) * (sf_vert_tot + sf_vert_tot_isect));
@@ -1360,6 +1360,9 @@ float BKE_maskrasterize_handle_sample(MaskRasterHandle *mr_handle, const float x
case PROP_SHARP:
value_layer = value_layer * value_layer;
break;
+ case PROP_INVSQUARE:
+ value_layer = value_layer * (2.0f - value_layer);
+ break;
case PROP_LIN:
default:
/* nothing */
diff --git a/source/blender/blenkernel/intern/material.c b/source/blender/blenkernel/intern/material.c
index eeca60f7ef4..3e7e98b4a1d 100644
--- a/source/blender/blenkernel/intern/material.c
+++ b/source/blender/blenkernel/intern/material.c
@@ -53,6 +53,7 @@
#include "BLI_listbase.h"
#include "BLI_utildefines.h"
#include "BLI_string.h"
+#include "BLI_array_utils.h"
#include "BKE_animsys.h"
#include "BKE_displist.h"
@@ -66,6 +67,8 @@
#include "BKE_scene.h"
#include "BKE_node.h"
#include "BKE_curve.h"
+#include "BKE_editmesh.h"
+#include "BKE_font.h"
#include "GPU_material.h"
@@ -99,11 +102,11 @@ void BKE_material_free_ex(Material *ma, bool do_id_user)
if (ma->ramp_col) MEM_freeN(ma->ramp_col);
if (ma->ramp_spec) MEM_freeN(ma->ramp_spec);
- BKE_free_animdata((ID *)ma);
+ BKE_animdata_free((ID *)ma);
if (ma->preview)
BKE_previewimg_free(&ma->preview);
- BKE_icon_delete((struct ID *)ma);
+ BKE_icon_id_delete((struct ID *)ma);
ma->id.icon_id = 0;
/* is no lib link block, but material extension */
@@ -116,7 +119,7 @@ void BKE_material_free_ex(Material *ma, bool do_id_user)
MEM_freeN(ma->texpaintslot);
if (ma->gpumaterial.first)
- GPU_material_free(ma);
+ GPU_material_free(&ma->gpumaterial);
}
void init_material(Material *ma)
@@ -252,6 +255,10 @@ Material *BKE_material_copy(Material *ma)
BLI_listbase_clear(&man->gpumaterial);
+ if (ma->id.lib) {
+ BKE_id_lib_local_paths(G.main, ma->id.lib, &man->id);
+ }
+
return man;
}
@@ -681,16 +688,16 @@ Material *give_current_material(Object *ob, short act)
/* if object cannot have material, (totcolp == NULL) */
totcolp = give_totcolp(ob);
if (totcolp == NULL || ob->totcol == 0) return NULL;
-
- if (act < 0) {
- printf("Negative material index!\n");
- }
-
+
/* return NULL for invalid 'act', can happen for mesh face indices */
if (act > ob->totcol)
return NULL;
- else if (act <= 0)
+ else if (act <= 0) {
+ if (act < 0) {
+ printf("Negative material index!\n");
+ }
return NULL;
+ }
if (ob->matbits && ob->matbits[act - 1]) { /* in object */
ma = ob->mat[act - 1];
@@ -802,9 +809,13 @@ void assign_material_id(ID *id, Material *ma, short act)
if (act > MAXMAT) return;
if (act < 1) act = 1;
+ /* this is needed for Python overrides,
+ * we just have to take care that the UI can't do this */
+#if 0
/* prevent crashing when using accidentally */
BLI_assert(id->lib == NULL);
if (id->lib) return;
+#endif
/* test arraylens */
@@ -868,8 +879,20 @@ void assign_material(Object *ob, Material *ma, short act, int assign_type)
*totcolp = act;
}
+ if (act > ob->totcol) {
+ /* Need more space in the material arrays */
+ ob->mat = MEM_recallocN_id(ob->mat, sizeof(void *) * act, "matarray2");
+ ob->matbits = MEM_recallocN_id(ob->matbits, sizeof(char) * act, "matbits1");
+ ob->totcol = act;
+ }
+
/* Determine the object/mesh linking */
- if (assign_type == BKE_MAT_ASSIGN_USERPREF && ob->totcol && ob->actcol) {
+ if (assign_type == BKE_MAT_ASSIGN_EXISTING) {
+ /* keep existing option (avoid confusion in scripts),
+ * intentionally ignore userpref (default to obdata). */
+ bit = ob->matbits[act - 1];
+ }
+ else if (assign_type == BKE_MAT_ASSIGN_USERPREF && ob->totcol && ob->actcol) {
/* copy from previous material */
bit = ob->matbits[ob->actcol - 1];
}
@@ -887,13 +910,6 @@ void assign_material(Object *ob, Material *ma, short act, int assign_type)
break;
}
}
-
- if (act > ob->totcol) {
- /* Need more space in the material arrays */
- ob->mat = MEM_recallocN_id(ob->mat, sizeof(void *) * act, "matarray2");
- ob->matbits = MEM_recallocN_id(ob->matbits, sizeof(char) * act, "matbits1");
- ob->totcol = act;
- }
/* do it */
@@ -914,6 +930,35 @@ void assign_material(Object *ob, Material *ma, short act, int assign_type)
test_object_materials(G.main, ob->data);
}
+
+void BKE_material_remap_object(Object *ob, const unsigned int *remap)
+{
+ Material ***matar = give_matarar(ob);
+ const short *totcol_p = give_totcolp(ob);
+
+ BLI_array_permute(ob->mat, ob->totcol, remap);
+
+ if (ob->matbits) {
+ BLI_array_permute(ob->matbits, ob->totcol, remap);
+ }
+
+ if (matar) {
+ BLI_array_permute(*matar, *totcol_p, remap);
+ }
+
+ if (ob->type == OB_MESH) {
+ BKE_mesh_material_remap(ob->data, remap, ob->totcol);
+ }
+ else if (ELEM(ob->type, OB_CURVE, OB_SURF, OB_FONT)) {
+ BKE_curve_material_remap(ob->data, remap, ob->totcol);
+ }
+ else {
+ /* add support for this object data! */
+ BLI_assert(matar == NULL);
+ }
+}
+
+
/* XXX - this calls many more update calls per object then are needed, could be optimized */
void assign_matarar(struct Object *ob, struct Material ***matar, short totcol)
{
@@ -1023,7 +1068,7 @@ static void do_init_render_material(Material *ma, int r_mode, float *amb)
Group *group;
for (group = G.main->group.first; group; group = group->id.next) {
- if (!group->id.lib && strcmp(group->id.name, ma->group->id.name) == 0) {
+ if (!group->id.lib && STREQ(group->id.name, ma->group->id.name)) {
ma->group = group;
}
}
@@ -1033,7 +1078,10 @@ static void do_init_render_material(Material *ma, int r_mode, float *amb)
static void init_render_nodetree(bNodeTree *ntree, Material *basemat, int r_mode, float *amb)
{
bNode *node;
-
+
+ /* parses the geom+tex nodes */
+ ntreeShaderGetTexcoMode(ntree, r_mode, &basemat->texco, &basemat->mode_l);
+
for (node = ntree->nodes.first; node; node = node->next) {
if (node->id) {
if (GS(node->id->name) == ID_MA) {
@@ -1070,9 +1118,6 @@ void init_render_material(Material *mat, int r_mode, float *amb)
mat->mode_l = (mat->mode & MA_MODE_PIPELINE) | MA_SHLESS;
mat->mode2_l = mat->mode2 & MA_MODE2_PIPELINE;
- /* parses the geom+tex nodes */
- ntreeShaderGetTexcoMode(mat->nodetree, r_mode, &mat->texco, &mat->mode_l);
-
init_render_nodetree(mat->nodetree, mat, r_mode, amb);
if (!mat->nodetree->execdata)
@@ -1087,7 +1132,7 @@ void init_render_material(Material *mat, int r_mode, float *amb)
}
}
-void init_render_materials(Main *bmain, int r_mode, float *amb)
+void init_render_materials(Main *bmain, int r_mode, float *amb, bool do_default_material)
{
Material *ma;
@@ -1108,8 +1153,10 @@ void init_render_materials(Main *bmain, int r_mode, float *amb)
if (ma->id.us)
init_render_material(ma, r_mode, amb);
}
-
- init_render_material(&defmaterial, r_mode, amb);
+
+ if (do_default_material) {
+ init_render_material(&defmaterial, r_mode, amb);
+ }
}
/* only needed for nodes now */
@@ -1137,28 +1184,28 @@ static bool material_in_nodetree(bNodeTree *ntree, Material *mat)
if (node->id) {
if (GS(node->id->name) == ID_MA) {
if (node->id == (ID *)mat) {
- return 1;
+ return true;
}
}
else if (node->type == NODE_GROUP) {
if (material_in_nodetree((bNodeTree *)node->id, mat)) {
- return 1;
+ return true;
}
}
}
}
- return 0;
+ return false;
}
bool material_in_material(Material *parmat, Material *mat)
{
if (parmat == mat)
- return 1;
+ return true;
else if (parmat->nodetree && parmat->use_nodes)
return material_in_nodetree(parmat->nodetree, mat);
else
- return 0;
+ return false;
}
@@ -1313,6 +1360,26 @@ static bool get_mtex_slot_valid_texpaint(struct MTex *mtex)
mtex->tex->ima);
}
+static bNode *nodetree_uv_node_recursive(bNode *node)
+{
+ bNode *inode;
+ bNodeSocket *sock;
+
+ for (sock = node->inputs.first; sock; sock = sock->next) {
+ if (sock->link) {
+ inode = sock->link->fromnode;
+ if (inode->typeinfo->nclass == NODE_CLASS_INPUT && inode->typeinfo->type == SH_NODE_UVMAP) {
+ return inode;
+ }
+ else {
+ return nodetree_uv_node_recursive(inode);
+ }
+ }
+ }
+
+ return NULL;
+}
+
void BKE_texpaint_slot_refresh_cache(Scene *scene, Material *ma)
{
MTex **mtex;
@@ -1320,7 +1387,7 @@ void BKE_texpaint_slot_refresh_cache(Scene *scene, Material *ma)
short index = 0, i;
bool use_nodes = BKE_scene_use_new_shading_nodes(scene);
- bool is_bi = BKE_scene_uses_blender_internal(scene);
+ bool is_bi = BKE_scene_uses_blender_internal(scene) || BKE_scene_uses_blender_game(scene);
if (!ma)
return;
@@ -1364,7 +1431,27 @@ void BKE_texpaint_slot_refresh_cache(Scene *scene, Material *ma)
if (node->typeinfo->nclass == NODE_CLASS_TEXTURE && node->typeinfo->type == SH_NODE_TEX_IMAGE && node->id) {
if (active_node == node)
ma->paint_active_slot = index;
- ma->texpaintslot[index++].ima = (Image *)node->id;
+ ma->texpaintslot[index].ima = (Image *)node->id;
+
+ /* for new renderer, we need to traverse the treeback in search of a UV node */
+ if (use_nodes) {
+ bNode *uvnode = nodetree_uv_node_recursive(node);
+
+ if (uvnode) {
+ NodeShaderUVMap *storage = (NodeShaderUVMap *)uvnode->storage;
+ ma->texpaintslot[index].uvname = storage->uv_map;
+ /* set a value to index so UI knows that we have a valid pointer for the mesh */
+ ma->texpaintslot[index].index = 0;
+ }
+ else {
+ /* just invalidate the index here so UV map does not get displayed on the UI */
+ ma->texpaintslot[index].index = -1;
+ }
+ }
+ else {
+ ma->texpaintslot[index].index = -1;
+ }
+ index++;
}
}
}
@@ -1724,7 +1811,7 @@ void paste_matcopybuf(Material *ma)
MEM_freeN(ma->nodetree);
}
- GPU_material_free(ma);
+ GPU_material_free(&ma->gpumaterial);
id = (ma->id);
memcpy(ma, &matcopybuf, sizeof(Material));
diff --git a/source/blender/blenkernel/intern/mball.c b/source/blender/blenkernel/intern/mball.c
index 453c6df6e3b..c09cd1aabdc 100644
--- a/source/blender/blenkernel/intern/mball.c
+++ b/source/blender/blenkernel/intern/mball.c
@@ -39,6 +39,7 @@
#include <stdlib.h>
#include <ctype.h>
#include <float.h>
+
#include "MEM_guardedalloc.h"
#include "DNA_material_types.h"
@@ -46,7 +47,6 @@
#include "DNA_meta_types.h"
#include "DNA_scene_types.h"
-
#include "BLI_blenlib.h"
#include "BLI_math.h"
#include "BLI_utildefines.h"
@@ -54,7 +54,6 @@
#include "BKE_global.h"
#include "BKE_main.h"
-/* #include "BKE_object.h" */
#include "BKE_animsys.h"
#include "BKE_curve.h"
#include "BKE_depsgraph.h"
@@ -65,119 +64,6 @@
#include "BKE_object.h"
#include "BKE_material.h"
-/* Data types */
-
-typedef struct vertex { /* surface vertex */
- float co[3]; /* position and surface normal */
- float no[3];
-} VERTEX;
-
-typedef struct vertices { /* list of vertices in polygonization */
- int count, max; /* # vertices, max # allowed */
- VERTEX *ptr; /* dynamically allocated */
-} VERTICES;
-
-typedef struct corner { /* corner of a cube */
- int i, j, k; /* (i, j, k) is index within lattice */
- float co[3], value; /* location and function value */
- struct corner *next;
-} CORNER;
-
-typedef struct cube { /* partitioning cell (cube) */
- int i, j, k; /* lattice location of cube */
- CORNER *corners[8]; /* eight corners */
-} CUBE;
-
-typedef struct cubes { /* linked list of cubes acting as stack */
- CUBE cube; /* a single cube */
- struct cubes *next; /* remaining elements */
-} CUBES;
-
-typedef struct centerlist { /* list of cube locations */
- int i, j, k; /* cube location */
- struct centerlist *next; /* remaining elements */
-} CENTERLIST;
-
-typedef struct edgelist { /* list of edges */
- int i1, j1, k1, i2, j2, k2; /* edge corner ids */
- int vid; /* vertex id */
- struct edgelist *next; /* remaining elements */
-} EDGELIST;
-
-typedef struct intlist { /* list of integers */
- int i; /* an integer */
- struct intlist *next; /* remaining elements */
-} INTLIST;
-
-typedef struct intlists { /* list of list of integers */
- INTLIST *list; /* a list of integers */
- struct intlists *next; /* remaining elements */
-} INTLISTS;
-
-/* dividing scene using octal tree makes polygonisation faster */
-typedef struct ml_pointer {
- struct ml_pointer *next, *prev;
- struct MetaElem *ml;
-} ml_pointer;
-
-typedef struct octal_node {
- struct octal_node *nodes[8];/* children of current node */
- struct octal_node *parent; /* parent of current node */
- struct ListBase elems; /* ListBase of MetaElem pointers (ml_pointer) */
- float x_min, y_min, z_min; /* 1st border point */
- float x_max, y_max, z_max; /* 7th border point */
- float x, y, z; /* center of node */
- int pos, neg; /* number of positive and negative MetaElements in the node */
- int count; /* number of MetaElems, which belongs to the node */
-} octal_node;
-
-typedef struct octal_tree {
- struct octal_node *first; /* first node */
- int pos, neg; /* number of positive and negative MetaElements in the scene */
- short depth; /* number of scene subdivision */
-} octal_tree;
-
-struct pgn_elements {
- struct pgn_elements *next, *prev;
- char *data;
-};
-
-typedef struct process { /* parameters, function, storage */
- /* ** old G_mb contents ** */
- float thresh;
- int totelem;
- MetaElem **mainb;
- octal_tree *metaball_tree;
-
- /* ** old process contents ** */
-
- /* what happens here? floats, I think. */
- /* float (*function)(void); */ /* implicit surface function */
- float (*function)(struct process *, float, float, float);
- float size, delta; /* cube size, normal delta */
- int bounds; /* cube range within lattice */
- CUBES *cubes; /* active cubes */
- VERTICES vertices; /* surface vertices */
- CENTERLIST **centers; /* cube center hash table */
- CORNER **corners; /* corner value hash table */
- EDGELIST **edges; /* edge and vertex id hash table */
-
- /* Runtime things */
- int *indices;
- int totindex, curindex;
-
- int pgn_offset;
- struct pgn_elements *pgn_current;
- ListBase pgn_list;
-} PROCESS;
-
-/* Forward declarations */
-static int vertid(PROCESS *process, const CORNER *c1, const CORNER *c2, MetaBall *mb);
-static int setcenter(PROCESS *process, CENTERLIST *table[], const int i, const int j, const int k);
-static CORNER *setcorner(PROCESS *process, int i, int j, int k);
-static void converge(PROCESS *process, const float p1[3], const float p2[3], float v1, float v2,
- float p[3], MetaBall *mb, int f);
-
/* Functions */
void BKE_mball_unlink(MetaBall *mb)
@@ -197,7 +83,7 @@ void BKE_mball_free(MetaBall *mb)
BKE_mball_unlink(mb);
if (mb->adt) {
- BKE_free_animdata((ID *)mb);
+ BKE_animdata_free((ID *)mb);
mb->adt = NULL;
}
if (mb->mat) MEM_freeN(mb->mat);
@@ -238,6 +124,10 @@ MetaBall *BKE_mball_copy(MetaBall *mb)
mbn->editelems = NULL;
mbn->lastelem = NULL;
+ if (mb->id.lib) {
+ BKE_id_lib_local_paths(G.main, mb->id.lib, &mbn->id);
+ }
+
return mbn;
}
@@ -464,7 +354,7 @@ bool BKE_mball_is_basis_for(Object *ob1, Object *ob2)
BLI_split_name_num(basis1name, &basis1nr, ob1->id.name + 2, '.');
BLI_split_name_num(basis2name, &basis2nr, ob2->id.name + 2, '.');
- if (!strcmp(basis1name, basis2name)) {
+ if (STREQ(basis1name, basis2name)) {
return BKE_mball_is_basis(ob1);
}
else {
@@ -499,7 +389,7 @@ void BKE_mball_properties_copy(Scene *scene, Object *active_object)
/* Object ob has to be in same "group" ... it means, that it has to have
* same base of its name */
- if (strcmp(obname, basisname) == 0) {
+ if (STREQ(obname, basisname)) {
MetaBall *mb = ob->data;
/* Copy properties from selected/edited metaball */
@@ -541,7 +431,7 @@ Object *BKE_mball_basis_find(Scene *scene, Object *basis)
BLI_split_name_num(obname, &obnr, ob->id.name + 2, '.');
/* object ob has to be in same "group" ... it means, that it has to have same base of its name */
- if (strcmp(obname, basisname) == 0) {
+ if (STREQ(obname, basisname)) {
if (obnr < basisnr) {
basis = ob;
basisnr = obnr;
@@ -554,1813 +444,6 @@ Object *BKE_mball_basis_find(Scene *scene, Object *basis)
return basis;
}
-
-/* ******************** ARITH ************************* */
-
-/* BASED AT CODE (but mostly rewritten) :
- * C code from the article
- * "An Implicit Surface Polygonizer"
- * by Jules Bloomenthal, jbloom@beauty.gmu.edu
- * in "Graphics Gems IV", Academic Press, 1994
- *
- * Authored by Jules Bloomenthal, Xerox PARC.
- * Copyright (c) Xerox Corporation, 1991. All rights reserved.
- * Permission is granted to reproduce, use and distribute this code for
- * any and all purposes, provided that this notice appears in all copies. */
-
-#define RES 12 /* # converge iterations */
-
-#define L 0 /* left direction: -x, -i */
-#define R 1 /* right direction: +x, +i */
-#define B 2 /* bottom direction: -y, -j */
-#define T 3 /* top direction: +y, +j */
-#define N 4 /* near direction: -z, -k */
-#define F 5 /* far direction: +z, +k */
-#define LBN 0 /* left bottom near corner */
-#define LBF 1 /* left bottom far corner */
-#define LTN 2 /* left top near corner */
-#define LTF 3 /* left top far corner */
-#define RBN 4 /* right bottom near corner */
-#define RBF 5 /* right bottom far corner */
-#define RTN 6 /* right top near corner */
-#define RTF 7 /* right top far corner */
-
-/* the LBN corner of cube (i, j, k), corresponds with location
- * (i-0.5)*size, (j-0.5)*size, (k-0.5)*size) */
-
-#define HASHBIT (5)
-#define HASHSIZE (size_t)(1 << (3 * HASHBIT)) /*! < hash table size (32768) */
-
-#define HASH(i, j, k) ((((( (i) & 31) << 5) | ( (j) & 31)) << 5) | ( (k) & 31) )
-
-#define MB_BIT(i, bit) (((i) >> (bit)) & 1)
-#define FLIP(i, bit) ((i) ^ 1 << (bit)) /* flip the given bit of i */
-
-
-/* **************** POLYGONIZATION ************************ */
-
-static void calc_mballco(MetaElem *ml, float vec[3])
-{
- if (ml->mat) {
- mul_m4_v3((float (*)[4])ml->mat, vec);
- }
-}
-
-static float densfunc(MetaElem *ball, float x, float y, float z)
-{
- float dist2;
- float dvec[3] = {x, y, z};
-
- mul_m4_v3((float (*)[4])ball->imat, dvec);
-
- switch (ball->type) {
- case MB_BALL:
- /* do nothing */
- break;
- case MB_TUBE:
- if (dvec[0] > ball->expx) dvec[0] -= ball->expx;
- else if (dvec[0] < -ball->expx) dvec[0] += ball->expx;
- else dvec[0] = 0.0;
- break;
- case MB_PLANE:
- if (dvec[0] > ball->expx) dvec[0] -= ball->expx;
- else if (dvec[0] < -ball->expx) dvec[0] += ball->expx;
- else dvec[0] = 0.0;
- if (dvec[1] > ball->expy) dvec[1] -= ball->expy;
- else if (dvec[1] < -ball->expy) dvec[1] += ball->expy;
- else dvec[1] = 0.0;
- break;
- case MB_ELIPSOID:
- dvec[0] /= ball->expx;
- dvec[1] /= ball->expy;
- dvec[2] /= ball->expz;
- break;
- case MB_CUBE:
- if (dvec[0] > ball->expx) dvec[0] -= ball->expx;
- else if (dvec[0] < -ball->expx) dvec[0] += ball->expx;
- else dvec[0] = 0.0;
-
- if (dvec[1] > ball->expy) dvec[1] -= ball->expy;
- else if (dvec[1] < -ball->expy) dvec[1] += ball->expy;
- else dvec[1] = 0.0;
-
- if (dvec[2] > ball->expz) dvec[2] -= ball->expz;
- else if (dvec[2] < -ball->expz) dvec[2] += ball->expz;
- else dvec[2] = 0.0;
- break;
-
- /* *** deprecated, could be removed?, do-versioned at least *** */
- case MB_TUBEX:
- if (dvec[0] > ball->len) dvec[0] -= ball->len;
- else if (dvec[0] < -ball->len) dvec[0] += ball->len;
- else dvec[0] = 0.0;
- break;
- case MB_TUBEY:
- if (dvec[1] > ball->len) dvec[1] -= ball->len;
- else if (dvec[1] < -ball->len) dvec[1] += ball->len;
- else dvec[1] = 0.0;
- break;
- case MB_TUBEZ:
- if (dvec[2] > ball->len) dvec[2] -= ball->len;
- else if (dvec[2] < -ball->len) dvec[2] += ball->len;
- else dvec[2] = 0.0;
- break;
- /* *** end deprecated *** */
- }
-
- dist2 = 1.0f - (len_squared_v3(dvec) / ball->rad2);
-
- if ((ball->flag & MB_NEGATIVE) == 0) {
- return (dist2 < 0.0f) ? -0.5f : (ball->s * dist2 * dist2 * dist2) - 0.5f;
- }
- else {
- return (dist2 < 0.0f) ? 0.5f : 0.5f - (ball->s * dist2 * dist2 * dist2);
- }
-}
-
-static octal_node *find_metaball_octal_node(octal_node *node, float x, float y, float z, short depth)
-{
- if (!depth) return node;
-
- if (z < node->z) {
- if (y < node->y) {
- if (x < node->x) {
- if (node->nodes[0])
- return find_metaball_octal_node(node->nodes[0], x, y, z, depth--);
- else
- return node;
- }
- else {
- if (node->nodes[1])
- return find_metaball_octal_node(node->nodes[1], x, y, z, depth--);
- else
- return node;
- }
- }
- else {
- if (x < node->x) {
- if (node->nodes[3])
- return find_metaball_octal_node(node->nodes[3], x, y, z, depth--);
- else
- return node;
- }
- else {
- if (node->nodes[2])
- return find_metaball_octal_node(node->nodes[2], x, y, z, depth--);
- else
- return node;
- }
- }
- }
- else {
- if (y < node->y) {
- if (x < node->x) {
- if (node->nodes[4])
- return find_metaball_octal_node(node->nodes[4], x, y, z, depth--);
- else
- return node;
- }
- else {
- if (node->nodes[5])
- return find_metaball_octal_node(node->nodes[5], x, y, z, depth--);
- else
- return node;
- }
- }
- else {
- if (x < node->x) {
- if (node->nodes[7])
- return find_metaball_octal_node(node->nodes[7], x, y, z, depth--);
- else
- return node;
- }
- else {
- if (node->nodes[6])
- return find_metaball_octal_node(node->nodes[6], x, y, z, depth--);
- else
- return node;
- }
- }
- }
-
- /* all cases accounted for */
- BLI_assert(0);
-}
-
-static float metaball(PROCESS *process, float x, float y, float z)
-/* float x, y, z; */
-{
- octal_tree *metaball_tree = process->metaball_tree;
- struct octal_node *node;
- struct ml_pointer *ml_p;
- float dens = 0;
- int a;
-
- if (process->totelem > 1) {
- node = find_metaball_octal_node(metaball_tree->first, x, y, z, metaball_tree->depth);
- if (node) {
- for (ml_p = node->elems.first; ml_p; ml_p = ml_p->next) {
- dens += densfunc(ml_p->ml, x, y, z);
- }
-
- dens += -0.5f * (metaball_tree->pos - node->pos);
- dens += 0.5f * (metaball_tree->neg - node->neg);
- }
- else {
- for (a = 0; a < process->totelem; a++) {
- dens += densfunc(process->mainb[a], x, y, z);
- }
- }
- }
- else {
- dens += densfunc(process->mainb[0], x, y, z);
- }
-
- return process->thresh - dens;
-}
-
-/* ******************************************** */
-
-static void accum_mballfaces(PROCESS *process, int i1, int i2, int i3, int i4)
-{
- int *newi, *cur;
- /* static int i = 0; I would like to delete altogether, but I don't dare to, yet */
-
- if (process->totindex == process->curindex) {
- process->totindex += 256;
- newi = MEM_mallocN(4 * sizeof(int) * process->totindex, "vertindex");
-
- if (process->indices) {
- memcpy(newi, process->indices, 4 * sizeof(int) * (process->totindex - 256));
- MEM_freeN(process->indices);
- }
- process->indices = newi;
- }
-
- cur = process->indices + 4 * process->curindex;
-
- /* displists now support array drawing, we treat tri's as fake quad */
-
- cur[0] = i1;
- cur[1] = i2;
- cur[2] = i3;
- if (i4 == 0)
- cur[3] = i3;
- else
- cur[3] = i4;
-
- process->curindex++;
-
-}
-
-/* ******************* MEMORY MANAGEMENT *********************** */
-static void *new_pgn_element(PROCESS *process, int size)
-{
- /* during polygonize 1000s of elements are allocated
- * and never freed in between. Freeing only done at the end.
- */
- int blocksize = 16384;
- void *adr;
-
- if (size > 10000 || size == 0) {
- printf("incorrect use of new_pgn_element\n");
- }
- else if (size == -1) {
- struct pgn_elements *cur = process->pgn_list.first;
- while (cur) {
- MEM_freeN(cur->data);
- cur = cur->next;
- }
- BLI_freelistN(&process->pgn_list);
-
- return NULL;
- }
-
- size = 4 * ( (size + 3) / 4);
-
- if (process->pgn_current) {
- if (size + process->pgn_offset < blocksize) {
- adr = (void *) (process->pgn_current->data + process->pgn_offset);
- process->pgn_offset += size;
- return adr;
- }
- }
-
- process->pgn_current = MEM_callocN(sizeof(struct pgn_elements), "newpgn");
- process->pgn_current->data = MEM_callocN(blocksize, "newpgn");
- BLI_addtail(&process->pgn_list, process->pgn_current);
-
- process->pgn_offset = size;
- return process->pgn_current->data;
-}
-
-static void freepolygonize(PROCESS *process)
-{
- MEM_freeN(process->corners);
- MEM_freeN(process->edges);
- MEM_freeN(process->centers);
-
- new_pgn_element(process, -1);
-
- if (process->vertices.ptr) {
- MEM_freeN(process->vertices.ptr);
- }
-}
-
-/**** Cubical Polygonization (optional) ****/
-
-#define LB 0 /* left bottom edge */
-#define LT 1 /* left top edge */
-#define LN 2 /* left near edge */
-#define LF 3 /* left far edge */
-#define RB 4 /* right bottom edge */
-#define RT 5 /* right top edge */
-#define RN 6 /* right near edge */
-#define RF 7 /* right far edge */
-#define BN 8 /* bottom near edge */
-#define BF 9 /* bottom far edge */
-#define TN 10 /* top near edge */
-#define TF 11 /* top far edge */
-
-static INTLISTS *cubetable[256];
-
-/* edge: LB, LT, LN, LF, RB, RT, RN, RF, BN, BF, TN, TF */
-static int corner1[12] = {
- LBN, LTN, LBN, LBF, RBN, RTN, RBN, RBF, LBN, LBF, LTN, LTF
-};
-static int corner2[12] = {
- LBF, LTF, LTN, LTF, RBF, RTF, RTN, RTF, RBN, RBF, RTN, RTF
-};
-static int leftface[12] = {
- B, L, L, F, R, T, N, R, N, B, T, F
-};
-/* face on left when going corner1 to corner2 */
-static int rightface[12] = {
- L, T, N, L, B, R, R, F, B, F, N, T
-};
-/* face on right when going corner1 to corner2 */
-
-
-/* docube: triangulate the cube directly, without decomposition */
-
-static void docube(PROCESS *process, CUBE *cube, MetaBall *mb)
-{
- INTLISTS *polys;
- CORNER *c1, *c2;
- int i, index = 0, count, indexar[8];
-
- for (i = 0; i < 8; i++) if (cube->corners[i]->value > 0.0f) index += (1 << i);
-
- for (polys = cubetable[index]; polys; polys = polys->next) {
- INTLIST *edges;
-
- count = 0;
-
- for (edges = polys->list; edges; edges = edges->next) {
- c1 = cube->corners[corner1[edges->i]];
- c2 = cube->corners[corner2[edges->i]];
-
- indexar[count] = vertid(process, c1, c2, mb);
- count++;
- }
- if (count > 2) {
- switch (count) {
- case 3:
- accum_mballfaces(process, indexar[2], indexar[1], indexar[0], 0);
- break;
- case 4:
- if (indexar[0] == 0) accum_mballfaces(process, indexar[0], indexar[3], indexar[2], indexar[1]);
- else accum_mballfaces(process, indexar[3], indexar[2], indexar[1], indexar[0]);
- break;
- case 5:
- if (indexar[0] == 0) accum_mballfaces(process, indexar[0], indexar[3], indexar[2], indexar[1]);
- else accum_mballfaces(process, indexar[3], indexar[2], indexar[1], indexar[0]);
-
- accum_mballfaces(process, indexar[4], indexar[3], indexar[0], 0);
- break;
- case 6:
- if (indexar[0] == 0) {
- accum_mballfaces(process, indexar[0], indexar[3], indexar[2], indexar[1]);
- accum_mballfaces(process, indexar[0], indexar[5], indexar[4], indexar[3]);
- }
- else {
- accum_mballfaces(process, indexar[3], indexar[2], indexar[1], indexar[0]);
- accum_mballfaces(process, indexar[5], indexar[4], indexar[3], indexar[0]);
- }
- break;
- case 7:
- if (indexar[0] == 0) {
- accum_mballfaces(process, indexar[0], indexar[3], indexar[2], indexar[1]);
- accum_mballfaces(process, indexar[0], indexar[5], indexar[4], indexar[3]);
- }
- else {
- accum_mballfaces(process, indexar[3], indexar[2], indexar[1], indexar[0]);
- accum_mballfaces(process, indexar[5], indexar[4], indexar[3], indexar[0]);
- }
-
- accum_mballfaces(process, indexar[6], indexar[5], indexar[0], 0);
-
- break;
- }
- }
- }
-}
-
-
-/* testface: given cube at lattice (i, j, k), and four corners of face,
- * if surface crosses face, compute other four corners of adjacent cube
- * and add new cube to cube stack */
-
-static void testface(PROCESS *process, int i, int j, int k, CUBE *old, int bit, int c1, int c2, int c3, int c4)
-{
- CUBE newc;
- CUBES *oldcubes = process->cubes;
- CORNER *corn1, *corn2, *corn3, *corn4;
- int n, pos;
-
- corn1 = old->corners[c1];
- corn2 = old->corners[c2];
- corn3 = old->corners[c3];
- corn4 = old->corners[c4];
-
- pos = corn1->value > 0.0f ? 1 : 0;
-
- /* test if no surface crossing */
- if ( (corn2->value > 0) == pos && (corn3->value > 0) == pos && (corn4->value > 0) == pos) return;
- /* test if cube out of bounds */
- /*if ( abs(i) > p->bounds || abs(j) > p->bounds || abs(k) > p->bounds) return;*/
- /* test if already visited (always as last) */
- if (setcenter(process, process->centers, i, j, k)) {
- return;
- }
-
- /* create new cube and add cube to top of stack: */
- process->cubes = (CUBES *) new_pgn_element(process, sizeof(CUBES));
- process->cubes->next = oldcubes;
-
- newc.i = i;
- newc.j = j;
- newc.k = k;
- for (n = 0; n < 8; n++) newc.corners[n] = NULL;
-
- newc.corners[FLIP(c1, bit)] = corn1;
- newc.corners[FLIP(c2, bit)] = corn2;
- newc.corners[FLIP(c3, bit)] = corn3;
- newc.corners[FLIP(c4, bit)] = corn4;
-
- if (newc.corners[0] == NULL) newc.corners[0] = setcorner(process, i, j, k);
- if (newc.corners[1] == NULL) newc.corners[1] = setcorner(process, i, j, k + 1);
- if (newc.corners[2] == NULL) newc.corners[2] = setcorner(process, i, j + 1, k);
- if (newc.corners[3] == NULL) newc.corners[3] = setcorner(process, i, j + 1, k + 1);
- if (newc.corners[4] == NULL) newc.corners[4] = setcorner(process, i + 1, j, k);
- if (newc.corners[5] == NULL) newc.corners[5] = setcorner(process, i + 1, j, k + 1);
- if (newc.corners[6] == NULL) newc.corners[6] = setcorner(process, i + 1, j + 1, k);
- if (newc.corners[7] == NULL) newc.corners[7] = setcorner(process, i + 1, j + 1, k + 1);
-
- process->cubes->cube = newc;
-}
-
-/* setcorner: return corner with the given lattice location
- * set (and cache) its function value */
-
-static CORNER *setcorner(PROCESS *process, int i, int j, int k)
-{
- /* for speed, do corner value caching here */
- CORNER *c;
- int index;
-
- /* does corner exist? */
- index = HASH(i, j, k);
- c = process->corners[index];
-
- for (; c != NULL; c = c->next) {
- if (c->i == i && c->j == j && c->k == k) {
- return c;
- }
- }
-
- c = (CORNER *) new_pgn_element(process, sizeof(CORNER));
-
- c->i = i;
- c->co[0] = ((float)i - 0.5f) * process->size;
- c->j = j;
- c->co[1] = ((float)j - 0.5f) * process->size;
- c->k = k;
- c->co[2] = ((float)k - 0.5f) * process->size;
- c->value = process->function(process, c->co[0], c->co[1], c->co[2]);
-
- c->next = process->corners[index];
- process->corners[index] = c;
-
- return c;
-}
-
-
-/* nextcwedge: return next clockwise edge from given edge around given face */
-
-static int nextcwedge(int edge, int face)
-{
- switch (edge) {
- case LB:
- return (face == L) ? LF : BN;
- case LT:
- return (face == L) ? LN : TF;
- case LN:
- return (face == L) ? LB : TN;
- case LF:
- return (face == L) ? LT : BF;
- case RB:
- return (face == R) ? RN : BF;
- case RT:
- return (face == R) ? RF : TN;
- case RN:
- return (face == R) ? RT : BN;
- case RF:
- return (face == R) ? RB : TF;
- case BN:
- return (face == B) ? RB : LN;
- case BF:
- return (face == B) ? LB : RF;
- case TN:
- return (face == T) ? LT : RN;
- case TF:
- return (face == T) ? RT : LF;
- }
- return 0;
-}
-
-
-/* otherface: return face adjoining edge that is not the given face */
-
-static int otherface(int edge, int face)
-{
- int other = leftface[edge];
- return face == other ? rightface[edge] : other;
-}
-
-
-/* makecubetable: create the 256 entry table for cubical polygonization */
-
-static void makecubetable(void)
-{
- static bool is_done = false;
- int i, e, c, done[12], pos[8];
-
- if (is_done) return;
- is_done = true;
-
- for (i = 0; i < 256; i++) {
- for (e = 0; e < 12; e++) done[e] = 0;
- for (c = 0; c < 8; c++) pos[c] = MB_BIT(i, c);
- for (e = 0; e < 12; e++)
- if (!done[e] && (pos[corner1[e]] != pos[corner2[e]])) {
- INTLIST *ints = NULL;
- INTLISTS *lists = (INTLISTS *) MEM_callocN(sizeof(INTLISTS), "mball_intlist");
- int start = e, edge = e;
-
- /* get face that is to right of edge from pos to neg corner: */
- int face = pos[corner1[e]] ? rightface[e] : leftface[e];
-
- while (1) {
- edge = nextcwedge(edge, face);
- done[edge] = 1;
- if (pos[corner1[edge]] != pos[corner2[edge]]) {
- INTLIST *tmp = ints;
-
- ints = (INTLIST *) MEM_callocN(sizeof(INTLIST), "mball_intlist");
- ints->i = edge;
- ints->next = tmp; /* add edge to head of list */
-
- if (edge == start) break;
- face = otherface(edge, face);
- }
- }
- lists->list = ints; /* add ints to head of table entry */
- lists->next = cubetable[i];
- cubetable[i] = lists;
- }
- }
-}
-
-void BKE_mball_cubeTable_free(void)
-{
- int i;
- INTLISTS *lists, *nlists;
- INTLIST *ints, *nints;
-
- for (i = 0; i < 256; i++) {
- lists = cubetable[i];
- while (lists) {
- nlists = lists->next;
-
- ints = lists->list;
- while (ints) {
- nints = ints->next;
- MEM_freeN(ints);
- ints = nints;
- }
-
- MEM_freeN(lists);
- lists = nlists;
- }
- cubetable[i] = NULL;
- }
-}
-
-/**** Storage ****/
-
-/* setcenter: set (i, j, k) entry of table[]
- * return 1 if already set; otherwise, set and return 0 */
-
-static int setcenter(PROCESS *process, CENTERLIST *table[], const int i, const int j, const int k)
-{
- int index;
- CENTERLIST *newc, *l, *q;
-
- index = HASH(i, j, k);
- q = table[index];
-
- for (l = q; l != NULL; l = l->next) {
- if (l->i == i && l->j == j && l->k == k) return 1;
- }
-
- newc = (CENTERLIST *) new_pgn_element(process, sizeof(CENTERLIST));
- newc->i = i;
- newc->j = j;
- newc->k = k;
- newc->next = q;
- table[index] = newc;
-
- return 0;
-}
-
-
-/* setedge: set vertex id for edge */
-
-static void setedge(PROCESS *process,
- EDGELIST *table[],
- int i1, int j1,
- int k1, int i2,
- int j2, int k2,
- int vid)
-{
- unsigned int index;
- EDGELIST *newe;
-
- if (i1 > i2 || (i1 == i2 && (j1 > j2 || (j1 == j2 && k1 > k2)))) {
- int t = i1;
- i1 = i2;
- i2 = t;
- t = j1;
- j1 = j2;
- j2 = t;
- t = k1;
- k1 = k2;
- k2 = t;
- }
- index = HASH(i1, j1, k1) + HASH(i2, j2, k2);
- newe = (EDGELIST *) new_pgn_element(process, sizeof(EDGELIST));
- newe->i1 = i1;
- newe->j1 = j1;
- newe->k1 = k1;
- newe->i2 = i2;
- newe->j2 = j2;
- newe->k2 = k2;
- newe->vid = vid;
- newe->next = table[index];
- table[index] = newe;
-}
-
-
-/* getedge: return vertex id for edge; return -1 if not set */
-
-static int getedge(EDGELIST *table[],
- int i1, int j1, int k1,
- int i2, int j2, int k2)
-{
- EDGELIST *q;
-
- if (i1 > i2 || (i1 == i2 && (j1 > j2 || (j1 == j2 && k1 > k2)))) {
- int t = i1;
- i1 = i2;
- i2 = t;
- t = j1;
- j1 = j2;
- j2 = t;
- t = k1;
- k1 = k2;
- k2 = t;
- }
- q = table[HASH(i1, j1, k1) + HASH(i2, j2, k2)];
- for (; q != NULL; q = q->next) {
- if (q->i1 == i1 && q->j1 == j1 && q->k1 == k1 &&
- q->i2 == i2 && q->j2 == j2 && q->k2 == k2)
- {
- return q->vid;
- }
- }
- return -1;
-}
-
-
-/**** Vertices ****/
-
-#undef R
-
-
-
-/* vertid: return index for vertex on edge:
- * c1->value and c2->value are presumed of different sign
- * return saved index if any; else compute vertex and save */
-
-/* addtovertices: add v to sequence of vertices */
-
-static void addtovertices(VERTICES *vertices, VERTEX v)
-{
- if (vertices->count == vertices->max) {
- int i;
- VERTEX *newv;
- vertices->max = vertices->count == 0 ? 10 : 2 * vertices->count;
- newv = (VERTEX *) MEM_callocN(vertices->max * sizeof(VERTEX), "addtovertices");
-
- for (i = 0; i < vertices->count; i++) newv[i] = vertices->ptr[i];
-
- if (vertices->ptr != NULL) MEM_freeN(vertices->ptr);
- vertices->ptr = newv;
- }
- vertices->ptr[vertices->count++] = v;
-}
-
-/* vnormal: compute unit length surface normal at point */
-
-static void vnormal(PROCESS *process, const float point[3], float r_no[3])
-{
- const float delta = 0.2f * process->delta;
- const float f = process->function(process, point[0], point[1], point[2]);
-
- r_no[0] = process->function(process, point[0] + delta, point[1], point[2]) - f;
- r_no[1] = process->function(process, point[0], point[1] + delta, point[2]) - f;
- r_no[2] = process->function(process, point[0], point[1], point[2] + delta) - f;
-
-#if 1
- normalize_v3(r_no);
-#else
- f = normalize_v3(r_no);
-
- if (0) {
- float tvec[3];
-
- delta *= 2.0f;
-
- f = process->function(process, point[0], point[1], point[2]);
-
- tvec[0] = process->function(process, point[0] + delta, point[1], point[2]) - f;
- tvec[1] = process->function(process, point[0], point[1] + delta, point[2]) - f;
- tvec[2] = process->function(process, point[0], point[1], point[2] + delta) - f;
-
- if (normalize_v3(tvec) != 0.0f) {
- add_v3_v3(r_no, tvec);
- normalize_v3(r_no);
- }
- }
-#endif
-}
-
-
-static int vertid(PROCESS *process, const CORNER *c1, const CORNER *c2, MetaBall *mb)
-{
- VERTEX v;
- int vid = getedge(process->edges, c1->i, c1->j, c1->k, c2->i, c2->j, c2->k);
-
- if (vid != -1) {
- return vid; /* previously computed */
- }
-
- converge(process, c1->co, c2->co, c1->value, c2->value, v.co, mb, 1); /* position */
- vnormal(process, v.co, v.no);
-
- addtovertices(&process->vertices, v); /* save vertex */
- vid = process->vertices.count - 1;
- setedge(process, process->edges, c1->i, c1->j, c1->k, c2->i, c2->j, c2->k, vid);
-
- return vid;
-}
-
-
-/* converge: from two points of differing sign, converge to zero crossing */
-/* watch it: p1 and p2 are used to calculate */
-static void converge(PROCESS *process, const float p1[3], const float p2[3], float v1, float v2,
- float p[3], MetaBall *mb, int f)
-{
- int i = 0;
- float pos[3], neg[3];
- float positive = 0.0f, negative = 0.0f;
- float dvec[3];
-
- if (v1 < 0) {
- copy_v3_v3(pos, p2);
- copy_v3_v3(neg, p1);
- positive = v2;
- negative = v1;
- }
- else {
- copy_v3_v3(pos, p1);
- copy_v3_v3(neg, p2);
- positive = v1;
- negative = v2;
- }
-
- sub_v3_v3v3(dvec, pos, neg);
-
-/* Approximation by linear interpolation is faster then binary subdivision,
- * but it results sometimes (mb->thresh < 0.2) into the strange results */
- if ((mb->thresh > 0.2f) && (f == 1)) {
- if ((dvec[1] == 0.0f) && (dvec[2] == 0.0f)) {
- p[0] = neg[0] - negative * dvec[0] / (positive - negative);
- p[1] = neg[1];
- p[2] = neg[2];
- return;
- }
- if ((dvec[0] == 0.0f) && (dvec[2] == 0.0f)) {
- p[0] = neg[0];
- p[1] = neg[1] - negative * dvec[1] / (positive - negative);
- p[2] = neg[2];
- return;
- }
- if ((dvec[0] == 0.0f) && (dvec[1] == 0.0f)) {
- p[0] = neg[0];
- p[1] = neg[1];
- p[2] = neg[2] - negative * dvec[2] / (positive - negative);
- return;
- }
- }
-
- if ((dvec[1] == 0.0f) && (dvec[2] == 0.0f)) {
- p[1] = neg[1];
- p[2] = neg[2];
- while (1) {
- if (i++ == RES) return;
- p[0] = 0.5f * (pos[0] + neg[0]);
- if ((process->function(process, p[0], p[1], p[2])) > 0.0f) pos[0] = p[0];
- else neg[0] = p[0];
- }
- }
-
- if ((dvec[0] == 0.0f) && (dvec[2] == 0.0f)) {
- p[0] = neg[0];
- p[2] = neg[2];
- while (1) {
- if (i++ == RES) return;
- p[1] = 0.5f * (pos[1] + neg[1]);
- if ((process->function(process, p[0], p[1], p[2])) > 0.0f) pos[1] = p[1];
- else neg[1] = p[1];
- }
- }
-
- if ((dvec[0] == 0.0f) && (dvec[1] == 0.0f)) {
- p[0] = neg[0];
- p[1] = neg[1];
- while (1) {
- if (i++ == RES) return;
- p[2] = 0.5f * (pos[2] + neg[2]);
- if ((process->function(process, p[0], p[1], p[2])) > 0.0f) pos[2] = p[2];
- else neg[2] = p[2];
- }
- }
-
- /* This is necessary to find start point */
- while (1) {
- mid_v3_v3v3(&p[0], pos, neg);
-
- if (i++ == RES) {
- return;
- }
-
- if ((process->function(process, p[0], p[1], p[2])) > 0.0f) {
- copy_v3_v3(pos, &p[0]);
- }
- else {
- copy_v3_v3(neg, &p[0]);
- }
- }
-}
-
-/* ************************************** */
-static void add_cube(PROCESS *process, int i, int j, int k, int count)
-{
- CUBES *ncube;
- int n;
- int a, b, c;
-
- /* hmmm, not only one, but eight cube will be added on the stack
- * ... */
- for (a = i - 1; a < i + count; a++)
- for (b = j - 1; b < j + count; b++)
- for (c = k - 1; c < k + count; c++) {
- /* test if cube has been found before */
- if (setcenter(process, process->centers, a, b, c) == 0) {
- /* push cube on stack: */
- ncube = (CUBES *) new_pgn_element(process, sizeof(CUBES));
- ncube->next = process->cubes;
- process->cubes = ncube;
-
- ncube->cube.i = a;
- ncube->cube.j = b;
- ncube->cube.k = c;
-
- /* set corners of initial cube: */
- for (n = 0; n < 8; n++)
- ncube->cube.corners[n] = setcorner(process, a + MB_BIT(n, 2), b + MB_BIT(n, 1), c + MB_BIT(n, 0));
- }
- }
-}
-
-
-static void find_first_points(PROCESS *process, MetaBall *mb, int a)
-{
- MetaElem *ml;
- float f;
-
- ml = process->mainb[a];
- f = 1.0f - (mb->thresh / ml->s);
-
- /* Skip, when Stiffness of MetaElement is too small ... MetaElement can't be
- * visible alone ... but still can influence others MetaElements :-) */
- if (f > 0.0f) {
- float IN[3] = {0.0f}, OUT[3] = {0.0f}, in[3] = {0.0f}, out[3];
- int i, j, k, c_i, c_j, c_k;
- int index[3] = {1, 0, -1};
- float in_v /*, out_v*/;
- float workp[3];
- float dvec[3];
- float tmp_v, workp_v, max_len_sq, nx, ny, nz, max_dim;
-
- calc_mballco(ml, in);
- in_v = process->function(process, in[0], in[1], in[2]);
-
- for (i = 0; i < 3; i++) {
- switch (ml->type) {
- case MB_BALL:
- OUT[0] = out[0] = IN[0] + index[i] * ml->rad;
- break;
- case MB_TUBE:
- case MB_PLANE:
- case MB_ELIPSOID:
- case MB_CUBE:
- OUT[0] = out[0] = IN[0] + index[i] * (ml->expx + ml->rad);
- break;
- }
-
- for (j = 0; j < 3; j++) {
- switch (ml->type) {
- case MB_BALL:
- OUT[1] = out[1] = IN[1] + index[j] * ml->rad;
- break;
- case MB_TUBE:
- case MB_PLANE:
- case MB_ELIPSOID:
- case MB_CUBE:
- OUT[1] = out[1] = IN[1] + index[j] * (ml->expy + ml->rad);
- break;
- }
-
- for (k = 0; k < 3; k++) {
- out[0] = OUT[0];
- out[1] = OUT[1];
- switch (ml->type) {
- case MB_BALL:
- case MB_TUBE:
- case MB_PLANE:
- out[2] = IN[2] + index[k] * ml->rad;
- break;
- case MB_ELIPSOID:
- case MB_CUBE:
- out[2] = IN[2] + index[k] * (ml->expz + ml->rad);
- break;
- }
-
- calc_mballco(ml, out);
-
- /*out_v = process->function(out[0], out[1], out[2]);*/ /*UNUSED*/
-
- /* find "first points" on Implicit Surface of MetaElemnt ml */
- copy_v3_v3(workp, in);
- workp_v = in_v;
- max_len_sq = len_squared_v3v3(out, in);
-
- nx = fabsf((out[0] - in[0]) / process->size);
- ny = fabsf((out[1] - in[1]) / process->size);
- nz = fabsf((out[2] - in[2]) / process->size);
-
- max_dim = max_fff(nx, ny, nz);
- if (max_dim != 0.0f) {
- float len_sq = 0.0f;
-
- dvec[0] = (out[0] - in[0]) / max_dim;
- dvec[1] = (out[1] - in[1]) / max_dim;
- dvec[2] = (out[2] - in[2]) / max_dim;
-
- while (len_sq <= max_len_sq) {
- add_v3_v3(workp, dvec);
-
- /* compute value of implicite function */
- tmp_v = process->function(process, workp[0], workp[1], workp[2]);
- /* add cube to the stack, when value of implicite function crosses zero value */
- if ((tmp_v < 0.0f && workp_v >= 0.0f) || (tmp_v > 0.0f && workp_v <= 0.0f)) {
-
- /* indexes of CUBE, which includes "first point" */
- c_i = (int)floor(workp[0] / process->size);
- c_j = (int)floor(workp[1] / process->size);
- c_k = (int)floor(workp[2] / process->size);
-
- /* add CUBE (with indexes c_i, c_j, c_k) to the stack,
- * this cube includes found point of Implicit Surface */
- if ((ml->flag & MB_NEGATIVE) == 0) {
- add_cube(process, c_i, c_j, c_k, 1);
- }
- else {
- add_cube(process, c_i, c_j, c_k, 2);
- }
- }
- len_sq = len_squared_v3v3(workp, in);
- workp_v = tmp_v;
-
- }
- }
- }
- }
- }
- }
-}
-
-static void polygonize(PROCESS *process, MetaBall *mb)
-{
- CUBE c;
- int a;
-
- process->vertices.count = process->vertices.max = 0;
- process->vertices.ptr = NULL;
-
- /* allocate hash tables and build cube polygon table: */
- process->centers = MEM_callocN(HASHSIZE * sizeof(CENTERLIST *), "mbproc->centers");
- process->corners = MEM_callocN(HASHSIZE * sizeof(CORNER *), "mbproc->corners");
- process->edges = MEM_callocN(2 * HASHSIZE * sizeof(EDGELIST *), "mbproc->edges");
- makecubetable();
-
- for (a = 0; a < process->totelem; a++) {
-
- /* try to find 8 points on the surface for each MetaElem */
- find_first_points(process, mb, a);
- }
-
- /* polygonize all MetaElems of current MetaBall */
- while (process->cubes != NULL) { /* process active cubes till none left */
- c = process->cubes->cube;
-
- /* polygonize the cube directly: */
- docube(process, &c, mb);
-
- /* pop current cube from stack */
- process->cubes = process->cubes->next;
-
- /* test six face directions, maybe add to stack: */
- testface(process, c.i - 1, c.j, c.k, &c, 2, LBN, LBF, LTN, LTF);
- testface(process, c.i + 1, c.j, c.k, &c, 2, RBN, RBF, RTN, RTF);
- testface(process, c.i, c.j - 1, c.k, &c, 1, LBN, LBF, RBN, RBF);
- testface(process, c.i, c.j + 1, c.k, &c, 1, LTN, LTF, RTN, RTF);
- testface(process, c.i, c.j, c.k - 1, &c, 0, LBN, LTN, RBN, RTN);
- testface(process, c.i, c.j, c.k + 1, &c, 0, LBF, LTF, RBF, RTF);
- }
-}
-
-static float init_meta(EvaluationContext *eval_ctx, PROCESS *process, Scene *scene, Object *ob) /* return totsize */
-{
- Scene *sce_iter = scene;
- Base *base;
- Object *bob;
- MetaBall *mb;
- MetaElem *ml;
- float size, totsize, obinv[4][4], obmat[4][4], vec[3];
- //float max = 0.0f;
- int a, obnr, zero_size = 0;
- char obname[MAX_ID_NAME];
- SceneBaseIter iter;
-
- copy_m4_m4(obmat, ob->obmat); /* to cope with duplicators from BKE_scene_base_iter_next */
- invert_m4_m4(obinv, ob->obmat);
- a = 0;
-
- BLI_split_name_num(obname, &obnr, ob->id.name + 2, '.');
-
- /* make main array */
- BKE_scene_base_iter_next(eval_ctx, &iter, &sce_iter, 0, NULL, NULL);
- while (BKE_scene_base_iter_next(eval_ctx, &iter, &sce_iter, 1, &base, &bob)) {
-
- if (bob->type == OB_MBALL) {
- zero_size = 0;
- ml = NULL;
-
- if (bob == ob && (base->flag & OB_FROMDUPLI) == 0) {
- mb = ob->data;
-
- if (mb->editelems) ml = mb->editelems->first;
- else ml = mb->elems.first;
- }
- else {
- char name[MAX_ID_NAME];
- int nr;
-
- BLI_split_name_num(name, &nr, bob->id.name + 2, '.');
- if (strcmp(obname, name) == 0) {
- mb = bob->data;
-
- if (mb->editelems) ml = mb->editelems->first;
- else ml = mb->elems.first;
- }
- }
-
- /* when metaball object has zero scale, then MetaElem to this MetaBall
- * will not be put to mainb array */
- if (has_zero_axis_m4(bob->obmat)) {
- zero_size = 1;
- }
- else if (bob->parent) {
- struct Object *pob = bob->parent;
- while (pob) {
- if (has_zero_axis_m4(pob->obmat)) {
- zero_size = 1;
- break;
- }
- pob = pob->parent;
- }
- }
-
- if (zero_size) {
- unsigned int ml_count = 0;
- while (ml) {
- ml_count++;
- ml = ml->next;
- }
- process->totelem -= ml_count;
- }
- else {
- while (ml) {
- if (!(ml->flag & MB_HIDE)) {
- int i;
- float temp1[4][4], temp2[4][4], temp3[4][4];
- float (*mat)[4] = NULL, (*imat)[4] = NULL;
- float max_x, max_y, max_z, min_x, min_y, min_z;
- float expx, expy, expz;
-
- max_x = max_y = max_z = -3.4e38;
- min_x = min_y = min_z = 3.4e38;
-
- /* too big stiffness seems only ugly due to linear interpolation
- * no need to have possibility for too big stiffness */
- if (ml->s > 10.0f) ml->s = 10.0f;
-
- /* Rotation of MetaElem is stored in quat */
- quat_to_mat4(temp3, ml->quat);
-
- /* Translation of MetaElem */
- unit_m4(temp2);
- temp2[3][0] = ml->x;
- temp2[3][1] = ml->y;
- temp2[3][2] = ml->z;
-
- mul_m4_m4m4(temp1, temp2, temp3);
-
- /* make a copy because of duplicates */
- process->mainb[a] = new_pgn_element(process, sizeof(MetaElem));
- *(process->mainb[a]) = *ml;
- process->mainb[a]->bb = new_pgn_element(process, sizeof(BoundBox));
-
- mat = new_pgn_element(process, 4 * 4 * sizeof(float));
- imat = new_pgn_element(process, 4 * 4 * sizeof(float));
-
- /* mat is the matrix to transform from mball into the basis-mball */
- invert_m4_m4(obinv, obmat);
- mul_m4_m4m4(temp2, obinv, bob->obmat);
- /* MetaBall transformation */
- mul_m4_m4m4(mat, temp2, temp1);
-
- invert_m4_m4(imat, mat);
-
- process->mainb[a]->rad2 = ml->rad * ml->rad;
-
- process->mainb[a]->mat = (float *) mat;
- process->mainb[a]->imat = (float *) imat;
-
- if (!MB_TYPE_SIZE_SQUARED(ml->type)) {
- expx = ml->expx;
- expy = ml->expy;
- expz = ml->expz;
- }
- else {
- expx = ml->expx * ml->expx;
- expy = ml->expy * ml->expy;
- expz = ml->expz * ml->expz;
- }
-
- /* untransformed Bounding Box of MetaElem */
- /* TODO, its possible the elem type has been changed and the exp* values can use a fallback */
- copy_v3_fl3(process->mainb[a]->bb->vec[0], -expx, -expy, -expz); /* 0 */
- copy_v3_fl3(process->mainb[a]->bb->vec[1], +expx, -expy, -expz); /* 1 */
- copy_v3_fl3(process->mainb[a]->bb->vec[2], +expx, +expy, -expz); /* 2 */
- copy_v3_fl3(process->mainb[a]->bb->vec[3], -expx, +expy, -expz); /* 3 */
- copy_v3_fl3(process->mainb[a]->bb->vec[4], -expx, -expy, +expz); /* 4 */
- copy_v3_fl3(process->mainb[a]->bb->vec[5], +expx, -expy, +expz); /* 5 */
- copy_v3_fl3(process->mainb[a]->bb->vec[6], +expx, +expy, +expz); /* 6 */
- copy_v3_fl3(process->mainb[a]->bb->vec[7], -expx, +expy, +expz); /* 7 */
-
- /* transformation of Metalem bb */
- for (i = 0; i < 8; i++)
- mul_m4_v3((float (*)[4])mat, process->mainb[a]->bb->vec[i]);
-
- /* find max and min of transformed bb */
- for (i = 0; i < 8; i++) {
- /* find maximums */
- if (process->mainb[a]->bb->vec[i][0] > max_x) max_x = process->mainb[a]->bb->vec[i][0];
- if (process->mainb[a]->bb->vec[i][1] > max_y) max_y = process->mainb[a]->bb->vec[i][1];
- if (process->mainb[a]->bb->vec[i][2] > max_z) max_z = process->mainb[a]->bb->vec[i][2];
- /* find minimums */
- if (process->mainb[a]->bb->vec[i][0] < min_x) min_x = process->mainb[a]->bb->vec[i][0];
- if (process->mainb[a]->bb->vec[i][1] < min_y) min_y = process->mainb[a]->bb->vec[i][1];
- if (process->mainb[a]->bb->vec[i][2] < min_z) min_z = process->mainb[a]->bb->vec[i][2];
- }
-
- /* create "new" bb, only point 0 and 6, which are
- * necessary for octal tree filling */
- process->mainb[a]->bb->vec[0][0] = min_x - ml->rad;
- process->mainb[a]->bb->vec[0][1] = min_y - ml->rad;
- process->mainb[a]->bb->vec[0][2] = min_z - ml->rad;
-
- process->mainb[a]->bb->vec[6][0] = max_x + ml->rad;
- process->mainb[a]->bb->vec[6][1] = max_y + ml->rad;
- process->mainb[a]->bb->vec[6][2] = max_z + ml->rad;
-
- a++;
- }
- ml = ml->next;
- }
- }
- }
- }
-
-
- /* totsize (= 'manhattan' radius) */
- totsize = 0.0;
- for (a = 0; a < process->totelem; a++) {
-
- vec[0] = process->mainb[a]->x + process->mainb[a]->rad + process->mainb[a]->expx;
- vec[1] = process->mainb[a]->y + process->mainb[a]->rad + process->mainb[a]->expy;
- vec[2] = process->mainb[a]->z + process->mainb[a]->rad + process->mainb[a]->expz;
-
- calc_mballco(process->mainb[a], vec);
-
- size = fabsf(vec[0]);
- if (size > totsize) totsize = size;
- size = fabsf(vec[1]);
- if (size > totsize) totsize = size;
- size = fabsf(vec[2]);
- if (size > totsize) totsize = size;
-
- vec[0] = process->mainb[a]->x - process->mainb[a]->rad;
- vec[1] = process->mainb[a]->y - process->mainb[a]->rad;
- vec[2] = process->mainb[a]->z - process->mainb[a]->rad;
-
- calc_mballco(process->mainb[a], vec);
-
- size = fabsf(vec[0]);
- if (size > totsize) totsize = size;
- size = fabsf(vec[1]);
- if (size > totsize) totsize = size;
- size = fabsf(vec[2]);
- if (size > totsize) totsize = size;
- }
-
- for (a = 0; a < process->totelem; a++) {
- process->thresh += densfunc(process->mainb[a], 2.0f * totsize, 2.0f * totsize, 2.0f * totsize);
- }
-
- return totsize;
-}
-
-/* if MetaElem lies in node, then node includes MetaElem pointer (ml_p)
- * pointing at MetaElem (ml)
- */
-static void fill_metaball_octal_node(octal_node *node, MetaElem *ml, short i)
-{
- ml_pointer *ml_p;
-
- ml_p = MEM_mallocN(sizeof(ml_pointer), "ml_pointer");
- ml_p->ml = ml;
- BLI_addtail(&(node->nodes[i]->elems), ml_p);
- node->count++;
-
- if ((ml->flag & MB_NEGATIVE) == 0) {
- node->nodes[i]->pos++;
- }
- else {
- node->nodes[i]->neg++;
- }
-}
-
-/* Node is subdivided as is illustrated on the following figure:
- *
- * +------+------+
- * / / /|
- * +------+------+ |
- * / / /| +
- * +------+------+ |/|
- * | | | + |
- * | | |/| +
- * +------+------+ |/
- * | | | +
- * | | |/
- * +------+------+
- *
- */
-static void subdivide_metaball_octal_node(octal_node *node, float size_x, float size_y, float size_z, short depth)
-{
- MetaElem *ml;
- ml_pointer *ml_p;
- float x, y, z;
- int a, i;
-
- /* create new nodes */
- for (a = 0; a < 8; a++) {
- node->nodes[a] = MEM_mallocN(sizeof(octal_node), "octal_node");
- for (i = 0; i < 8; i++)
- node->nodes[a]->nodes[i] = NULL;
- node->nodes[a]->parent = node;
- BLI_listbase_clear(&node->nodes[a]->elems);
- node->nodes[a]->count = 0;
- node->nodes[a]->neg = 0;
- node->nodes[a]->pos = 0;
- }
-
- size_x /= 2;
- size_y /= 2;
- size_z /= 2;
-
- /* center of node */
- node->x = x = node->x_min + size_x;
- node->y = y = node->y_min + size_y;
- node->z = z = node->z_min + size_z;
-
- /* setting up of border points of new nodes */
- node->nodes[0]->x_min = node->x_min;
- node->nodes[0]->y_min = node->y_min;
- node->nodes[0]->z_min = node->z_min;
- node->nodes[0]->x = node->nodes[0]->x_min + size_x / 2;
- node->nodes[0]->y = node->nodes[0]->y_min + size_y / 2;
- node->nodes[0]->z = node->nodes[0]->z_min + size_z / 2;
-
- node->nodes[1]->x_min = x;
- node->nodes[1]->y_min = node->y_min;
- node->nodes[1]->z_min = node->z_min;
- node->nodes[1]->x = node->nodes[1]->x_min + size_x / 2;
- node->nodes[1]->y = node->nodes[1]->y_min + size_y / 2;
- node->nodes[1]->z = node->nodes[1]->z_min + size_z / 2;
-
- node->nodes[2]->x_min = x;
- node->nodes[2]->y_min = y;
- node->nodes[2]->z_min = node->z_min;
- node->nodes[2]->x = node->nodes[2]->x_min + size_x / 2;
- node->nodes[2]->y = node->nodes[2]->y_min + size_y / 2;
- node->nodes[2]->z = node->nodes[2]->z_min + size_z / 2;
-
- node->nodes[3]->x_min = node->x_min;
- node->nodes[3]->y_min = y;
- node->nodes[3]->z_min = node->z_min;
- node->nodes[3]->x = node->nodes[3]->x_min + size_x / 2;
- node->nodes[3]->y = node->nodes[3]->y_min + size_y / 2;
- node->nodes[3]->z = node->nodes[3]->z_min + size_z / 2;
-
- node->nodes[4]->x_min = node->x_min;
- node->nodes[4]->y_min = node->y_min;
- node->nodes[4]->z_min = z;
- node->nodes[4]->x = node->nodes[4]->x_min + size_x / 2;
- node->nodes[4]->y = node->nodes[4]->y_min + size_y / 2;
- node->nodes[4]->z = node->nodes[4]->z_min + size_z / 2;
-
- node->nodes[5]->x_min = x;
- node->nodes[5]->y_min = node->y_min;
- node->nodes[5]->z_min = z;
- node->nodes[5]->x = node->nodes[5]->x_min + size_x / 2;
- node->nodes[5]->y = node->nodes[5]->y_min + size_y / 2;
- node->nodes[5]->z = node->nodes[5]->z_min + size_z / 2;
-
- node->nodes[6]->x_min = x;
- node->nodes[6]->y_min = y;
- node->nodes[6]->z_min = z;
- node->nodes[6]->x = node->nodes[6]->x_min + size_x / 2;
- node->nodes[6]->y = node->nodes[6]->y_min + size_y / 2;
- node->nodes[6]->z = node->nodes[6]->z_min + size_z / 2;
-
- node->nodes[7]->x_min = node->x_min;
- node->nodes[7]->y_min = y;
- node->nodes[7]->z_min = z;
- node->nodes[7]->x = node->nodes[7]->x_min + size_x / 2;
- node->nodes[7]->y = node->nodes[7]->y_min + size_y / 2;
- node->nodes[7]->z = node->nodes[7]->z_min + size_z / 2;
-
- ml_p = node->elems.first;
-
- /* setting up references of MetaElems for new nodes */
- while (ml_p) {
- ml = ml_p->ml;
- if (ml->bb->vec[0][2] < z) {
- if (ml->bb->vec[0][1] < y) {
- /* vec[0][0] lies in first octant */
- if (ml->bb->vec[0][0] < x) {
- /* ml belongs to the (0)1st node */
- fill_metaball_octal_node(node, ml, 0);
-
- /* ml belongs to the (3)4th node */
- if (ml->bb->vec[6][1] >= y) {
- fill_metaball_octal_node(node, ml, 3);
-
- /* ml belongs to the (7)8th node */
- if (ml->bb->vec[6][2] >= z) {
- fill_metaball_octal_node(node, ml, 7);
- }
- }
-
- /* ml belongs to the (1)2nd node */
- if (ml->bb->vec[6][0] >= x) {
- fill_metaball_octal_node(node, ml, 1);
-
- /* ml belongs to the (5)6th node */
- if (ml->bb->vec[6][2] >= z) {
- fill_metaball_octal_node(node, ml, 5);
- }
- }
-
- /* ml belongs to the (2)3th node */
- if ((ml->bb->vec[6][0] >= x) && (ml->bb->vec[6][1] >= y)) {
- fill_metaball_octal_node(node, ml, 2);
-
- /* ml belong to the (6)7th node */
- if (ml->bb->vec[6][2] >= z) {
- fill_metaball_octal_node(node, ml, 6);
- }
-
- }
-
- /* ml belongs to the (4)5th node too */
- if (ml->bb->vec[6][2] >= z) {
- fill_metaball_octal_node(node, ml, 4);
- }
-
-
-
- }
- /* vec[0][0] is in the (1)second octant */
- else {
- /* ml belong to the (1)2nd node */
- fill_metaball_octal_node(node, ml, 1);
-
- /* ml belongs to the (2)3th node */
- if (ml->bb->vec[6][1] >= y) {
- fill_metaball_octal_node(node, ml, 2);
-
- /* ml belongs to the (6)7th node */
- if (ml->bb->vec[6][2] >= z) {
- fill_metaball_octal_node(node, ml, 6);
- }
-
- }
-
- /* ml belongs to the (5)6th node */
- if (ml->bb->vec[6][2] >= z) {
- fill_metaball_octal_node(node, ml, 5);
- }
- }
- }
- else {
- /* vec[0][0] is in the (3)4th octant */
- if (ml->bb->vec[0][0] < x) {
- /* ml belongs to the (3)4nd node */
- fill_metaball_octal_node(node, ml, 3);
-
- /* ml belongs to the (7)8th node */
- if (ml->bb->vec[6][2] >= z) {
- fill_metaball_octal_node(node, ml, 7);
- }
-
-
- /* ml belongs to the (2)3th node */
- if (ml->bb->vec[6][0] >= x) {
- fill_metaball_octal_node(node, ml, 2);
-
- /* ml belongs to the (6)7th node */
- if (ml->bb->vec[6][2] >= z) {
- fill_metaball_octal_node(node, ml, 6);
- }
- }
- }
-
- }
-
- /* vec[0][0] is in the (2)3th octant */
- if ((ml->bb->vec[0][0] >= x) && (ml->bb->vec[0][1] >= y)) {
- /* ml belongs to the (2)3th node */
- fill_metaball_octal_node(node, ml, 2);
-
- /* ml belongs to the (6)7th node */
- if (ml->bb->vec[6][2] >= z) {
- fill_metaball_octal_node(node, ml, 6);
- }
- }
- }
- else {
- if (ml->bb->vec[0][1] < y) {
- /* vec[0][0] lies in (4)5th octant */
- if (ml->bb->vec[0][0] < x) {
- /* ml belongs to the (4)5th node */
- fill_metaball_octal_node(node, ml, 4);
-
- if (ml->bb->vec[6][0] >= x) {
- fill_metaball_octal_node(node, ml, 5);
- }
-
- if (ml->bb->vec[6][1] >= y) {
- fill_metaball_octal_node(node, ml, 7);
- }
-
- if ((ml->bb->vec[6][0] >= x) && (ml->bb->vec[6][1] >= y)) {
- fill_metaball_octal_node(node, ml, 6);
- }
- }
- /* vec[0][0] lies in (5)6th octant */
- else {
- fill_metaball_octal_node(node, ml, 5);
-
- if (ml->bb->vec[6][1] >= y) {
- fill_metaball_octal_node(node, ml, 6);
- }
- }
- }
- else {
- /* vec[0][0] lies in (7)8th octant */
- if (ml->bb->vec[0][0] < x) {
- fill_metaball_octal_node(node, ml, 7);
-
- if (ml->bb->vec[6][0] >= x) {
- fill_metaball_octal_node(node, ml, 6);
- }
- }
-
- }
-
- /* vec[0][0] lies in (6)7th octant */
- if ((ml->bb->vec[0][0] >= x) && (ml->bb->vec[0][1] >= y)) {
- fill_metaball_octal_node(node, ml, 6);
- }
- }
- ml_p = ml_p->next;
- }
-
- /* free references of MetaElems for curent node (it is not needed anymore) */
- BLI_freelistN(&node->elems);
-
- depth--;
-
- if (depth > 0) {
- for (a = 0; a < 8; a++) {
- if (node->nodes[a]->count > 0) /* if node is not empty, then it is subdivided */
- subdivide_metaball_octal_node(node->nodes[a], size_x, size_y, size_z, depth);
- }
- }
-}
-
-/* free all octal nodes recursively */
-static void free_metaball_octal_node(octal_node *node)
-{
- int a;
- for (a = 0; a < 8; a++) {
- if (node->nodes[a] != NULL) free_metaball_octal_node(node->nodes[a]);
- }
- BLI_freelistN(&node->elems);
- MEM_freeN(node);
-}
-
-/* If scene include more than one MetaElem, then octree is used */
-static void init_metaball_octal_tree(PROCESS *process, int depth)
-{
- struct octal_node *node;
- ml_pointer *ml_p;
- float size[3];
- int a;
-
- process->metaball_tree = MEM_mallocN(sizeof(octal_tree), "metaball_octal_tree");
- process->metaball_tree->first = node = MEM_mallocN(sizeof(octal_node), "metaball_octal_node");
- /* maximal depth of octree */
- process->metaball_tree->depth = depth;
-
- process->metaball_tree->neg = node->neg = 0;
- process->metaball_tree->pos = node->pos = 0;
-
- BLI_listbase_clear(&node->elems);
- node->count = 0;
-
- for (a = 0; a < 8; a++)
- node->nodes[a] = NULL;
-
- node->x_min = node->y_min = node->z_min = FLT_MAX;
- node->x_max = node->y_max = node->z_max = -FLT_MAX;
-
- /* size of octal tree scene */
- for (a = 0; a < process->totelem; a++) {
- if (process->mainb[a]->bb->vec[0][0] < node->x_min) node->x_min = process->mainb[a]->bb->vec[0][0];
- if (process->mainb[a]->bb->vec[0][1] < node->y_min) node->y_min = process->mainb[a]->bb->vec[0][1];
- if (process->mainb[a]->bb->vec[0][2] < node->z_min) node->z_min = process->mainb[a]->bb->vec[0][2];
-
- if (process->mainb[a]->bb->vec[6][0] > node->x_max) node->x_max = process->mainb[a]->bb->vec[6][0];
- if (process->mainb[a]->bb->vec[6][1] > node->y_max) node->y_max = process->mainb[a]->bb->vec[6][1];
- if (process->mainb[a]->bb->vec[6][2] > node->z_max) node->z_max = process->mainb[a]->bb->vec[6][2];
-
- ml_p = MEM_mallocN(sizeof(ml_pointer), "ml_pointer");
- ml_p->ml = process->mainb[a];
- BLI_addtail(&node->elems, ml_p);
-
- if ((process->mainb[a]->flag & MB_NEGATIVE) == 0) {
- /* number of positive MetaElem in scene */
- process->metaball_tree->pos++;
- }
- else {
- /* number of negative MetaElem in scene */
- process->metaball_tree->neg++;
- }
- }
-
- /* size of first node */
- size[0] = node->x_max - node->x_min;
- size[1] = node->y_max - node->y_min;
- size[2] = node->z_max - node->z_min;
-
- /* first node is subdivided recursively */
- subdivide_metaball_octal_node(node, size[0], size[1], size[2], process->metaball_tree->depth);
-}
-
-static void mball_count(EvaluationContext *eval_ctx, PROCESS *process, Scene *scene, Object *basis)
-{
- Scene *sce_iter = scene;
- Base *base;
- Object *ob, *bob = basis;
- MetaElem *ml = NULL;
- int basisnr, obnr;
- char basisname[MAX_ID_NAME], obname[MAX_ID_NAME];
- SceneBaseIter iter;
-
- BLI_split_name_num(basisname, &basisnr, basis->id.name + 2, '.');
- process->totelem = 0;
-
- BKE_scene_base_iter_next(eval_ctx, &iter, &sce_iter, 0, NULL, NULL);
- while (BKE_scene_base_iter_next(eval_ctx, &iter, &sce_iter, 1, &base, &ob)) {
- if (ob->type == OB_MBALL) {
- if (ob == bob) {
- MetaBall *mb = ob->data;
-
- /* if bob object is in edit mode, then dynamic list of all MetaElems
- * is stored in editelems */
- if (mb->editelems) ml = mb->editelems->first;
- /* if bob object is in object mode */
- else ml = mb->elems.first;
- }
- else {
- BLI_split_name_num(obname, &obnr, ob->id.name + 2, '.');
-
- /* object ob has to be in same "group" ... it means, that it has to have
- * same base of its name */
- if (strcmp(obname, basisname) == 0) {
- MetaBall *mb = ob->data;
-
- /* if object is in edit mode, then dynamic list of all MetaElems
- * is stored in editelems */
- if (mb->editelems) ml = mb->editelems->first;
- /* if bob object is in object mode */
- else ml = mb->elems.first;
- }
- }
-
- for ( ; ml; ml = ml->next) {
- if (!(ml->flag & MB_HIDE)) {
- process->totelem++;
- }
- }
- }
- }
-}
-
-void BKE_mball_polygonize(EvaluationContext *eval_ctx, Scene *scene, Object *ob, ListBase *dispbase)
-{
- MetaBall *mb;
- DispList *dl;
- int a, nr_cubes;
- float *co, *no, totsize, width;
- PROCESS process = {0};
-
- mb = ob->data;
-
- mball_count(eval_ctx, &process, scene, ob);
-
- if (process.totelem == 0) return;
- if ((eval_ctx->mode != DAG_EVAL_RENDER) && (mb->flag == MB_UPDATE_NEVER)) return;
- if ((G.moving & (G_TRANSFORM_OBJ | G_TRANSFORM_EDIT)) && mb->flag == MB_UPDATE_FAST) return;
-
- process.thresh = mb->thresh;
-
- /* total number of MetaElems (totelem) is precomputed in find_basis_mball() function */
- process.mainb = MEM_mallocN(sizeof(void *) * process.totelem, "mainb");
-
- /* initialize all mainb (MetaElems) */
- totsize = init_meta(eval_ctx, &process, scene, ob);
-
- /* if scene includes more than one MetaElem, then octal tree optimization is used */
- if ((process.totelem > 1) && (process.totelem <= 64)) init_metaball_octal_tree(&process, 1);
- if ((process.totelem > 64) && (process.totelem <= 128)) init_metaball_octal_tree(&process, 2);
- if ((process.totelem > 128) && (process.totelem <= 512)) init_metaball_octal_tree(&process, 3);
- if ((process.totelem > 512) && (process.totelem <= 1024)) init_metaball_octal_tree(&process, 4);
- if (process.totelem > 1024) init_metaball_octal_tree(&process, 5);
-
- /* don't polygonize metaballs with too high resolution (base mball to small)
- * note: Eps was 0.0001f but this was giving problems for blood animation for durian, using 0.00001f */
- if (process.metaball_tree) {
- if (ob->size[0] <= 0.00001f * (process.metaball_tree->first->x_max - process.metaball_tree->first->x_min) ||
- ob->size[1] <= 0.00001f * (process.metaball_tree->first->y_max - process.metaball_tree->first->y_min) ||
- ob->size[2] <= 0.00001f * (process.metaball_tree->first->z_max - process.metaball_tree->first->z_min))
- {
- new_pgn_element(&process, -1); /* free values created by init_meta */
-
- MEM_freeN(process.mainb);
-
- /* free tree */
- free_metaball_octal_node(process.metaball_tree->first);
- MEM_freeN(process.metaball_tree);
-
- return;
- }
- }
-
- /* width is size per polygonize cube */
- if (eval_ctx->mode == DAG_EVAL_RENDER) {
- width = mb->rendersize;
- }
- else {
- width = mb->wiresize;
- if ((G.moving & (G_TRANSFORM_OBJ | G_TRANSFORM_EDIT)) && mb->flag == MB_UPDATE_HALFRES) {
- width *= 2;
- }
- }
- /* nr_cubes is just for safety, minimum is totsize */
- nr_cubes = (int)(0.5f + totsize / width);
-
- /* init process */
- process.function = metaball;
- process.size = width;
- process.bounds = nr_cubes;
- process.cubes = NULL;
- process.delta = width / (float)(RES * RES);
-
- polygonize(&process, mb);
-
- MEM_freeN(process.mainb);
-
- /* free octal tree */
- if (process.totelem > 1) {
- free_metaball_octal_node(process.metaball_tree->first);
- MEM_freeN(process.metaball_tree);
- process.metaball_tree = NULL;
- }
-
- if (process.curindex) {
- VERTEX *ptr = process.vertices.ptr;
-
- dl = MEM_callocN(sizeof(DispList), "mbaldisp");
- BLI_addtail(dispbase, dl);
- dl->type = DL_INDEX4;
- dl->nr = process.vertices.count;
- dl->parts = process.curindex;
-
- dl->index = process.indices;
- process.indices = NULL;
-
- a = process.vertices.count;
- dl->verts = co = MEM_mallocN(sizeof(float[3]) * a, "mballverts");
- dl->nors = no = MEM_mallocN(sizeof(float[3]) * a, "mballnors");
-
- for (a = 0; a < process.vertices.count; ptr++, a++, no += 3, co += 3) {
- copy_v3_v3(co, ptr->co);
- copy_v3_v3(no, ptr->no);
- }
- }
-
- freepolygonize(&process);
-}
-
bool BKE_mball_minmax_ex(MetaBall *mb, float min[3], float max[3],
float obmat[4][4], const short flag)
{
@@ -2436,10 +519,10 @@ bool BKE_mball_center_bounds(MetaBall *mb, float r_cent[3])
if (BKE_mball_minmax(mb, min, max)) {
mid_v3_v3v3(r_cent, min, max);
- return 1;
+ return true;
}
- return 0;
+ return false;
}
void BKE_mball_transform(MetaBall *mb, float mat[4][4])
@@ -2503,3 +586,9 @@ void BKE_mball_select_swap(struct MetaBall *mb)
}
}
+/* **** Depsgraph evaluation **** */
+
+void BKE_mball_eval_geometry(EvaluationContext *UNUSED(eval_ctx),
+ MetaBall *UNUSED(mball))
+{
+}
diff --git a/source/blender/blenkernel/intern/mball_tessellate.c b/source/blender/blenkernel/intern/mball_tessellate.c
new file mode 100644
index 00000000000..e8418e876bb
--- /dev/null
+++ b/source/blender/blenkernel/intern/mball_tessellate.c
@@ -0,0 +1,1325 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * Contributor(s): Jiri Hnidek <jiri.hnidek@vslib.cz>.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/blenkernel/intern/mball_tessellate.c
+ * \ingroup bke
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <math.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <float.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_object_types.h"
+#include "DNA_meta_types.h"
+#include "DNA_scene_types.h"
+
+#include "BLI_listbase.h"
+#include "BLI_path_util.h"
+#include "BLI_math.h"
+#include "BLI_utildefines.h"
+#include "BLI_memarena.h"
+
+#include "BKE_global.h"
+
+#include "BKE_depsgraph.h"
+#include "BKE_scene.h"
+#include "BKE_displist.h"
+#include "BKE_mball_tessellate.h" /* own include */
+
+#include "BLI_strict_flags.h"
+
+/* experimental (faster) normal calculation */
+// #define USE_ACCUM_NORMAL
+
+/* Data types */
+
+typedef struct corner { /* corner of a cube */
+ int i, j, k; /* (i, j, k) is index within lattice */
+ float co[3], value; /* location and function value */
+ struct corner *next;
+} CORNER;
+
+typedef struct cube { /* partitioning cell (cube) */
+ int i, j, k; /* lattice location of cube */
+ CORNER *corners[8]; /* eight corners */
+} CUBE;
+
+typedef struct cubes { /* linked list of cubes acting as stack */
+ CUBE cube; /* a single cube */
+ struct cubes *next; /* remaining elements */
+} CUBES;
+
+typedef struct centerlist { /* list of cube locations */
+ int i, j, k; /* cube location */
+ struct centerlist *next; /* remaining elements */
+} CENTERLIST;
+
+typedef struct edgelist { /* list of edges */
+ int i1, j1, k1, i2, j2, k2; /* edge corner ids */
+ int vid; /* vertex id */
+ struct edgelist *next; /* remaining elements */
+} EDGELIST;
+
+typedef struct intlist { /* list of integers */
+ int i; /* an integer */
+ struct intlist *next; /* remaining elements */
+} INTLIST;
+
+typedef struct intlists { /* list of list of integers */
+ INTLIST *list; /* a list of integers */
+ struct intlists *next; /* remaining elements */
+} INTLISTS;
+
+typedef struct Box { /* an AABB with pointer to metalelem */
+ float min[3], max[3];
+ const MetaElem *ml;
+} Box;
+
+typedef struct MetaballBVHNode { /* BVH node */
+ Box bb[2]; /* AABB of children */
+ struct MetaballBVHNode *child[2];
+} MetaballBVHNode;
+
+typedef struct process { /* parameters, storage */
+ float thresh, size; /* mball threshold, single cube size */
+ float delta; /* small delta for calculating normals */
+ unsigned int converge_res; /* converge procedure resolution (more = slower) */
+
+ MetaElem **mainb; /* array of all metaelems */
+ unsigned int totelem, mem; /* number of metaelems */
+
+ MetaballBVHNode metaball_bvh; /* The simplest bvh */
+ Box allbb; /* Bounding box of all metaelems */
+
+ MetaballBVHNode **bvh_queue; /* Queue used during bvh traversal */
+ unsigned int bvh_queue_size;
+
+ CUBES *cubes; /* stack of cubes waiting for polygonization */
+ CENTERLIST **centers; /* cube center hash table */
+ CORNER **corners; /* corner value hash table */
+ EDGELIST **edges; /* edge and vertex id hash table */
+
+ int (*indices)[4]; /* output indices */
+ unsigned int totindex; /* size of memory allocated for indices */
+ unsigned int curindex; /* number of currently added indices */
+
+ float (*co)[3], (*no)[3]; /* surface vertices - positions and normals */
+ unsigned int totvertex; /* memory size */
+ unsigned int curvertex; /* currently added vertices */
+
+ /* memory allocation from common pool */
+ MemArena *pgn_elements;
+} PROCESS;
+
+/* Forward declarations */
+static int vertid(PROCESS *process, const CORNER *c1, const CORNER *c2);
+static void add_cube(PROCESS *process, int i, int j, int k);
+static void make_face(PROCESS *process, int i1, int i2, int i3, int i4);
+static void converge(PROCESS *process, const CORNER *c1, const CORNER *c2, float r_p[3]);
+
+/* ******************* SIMPLE BVH ********************* */
+
+static void make_box_union(const BoundBox *a, const Box *b, Box *r_out)
+{
+ r_out->min[0] = min_ff(a->vec[0][0], b->min[0]);
+ r_out->min[1] = min_ff(a->vec[0][1], b->min[1]);
+ r_out->min[2] = min_ff(a->vec[0][2], b->min[2]);
+
+ r_out->max[0] = max_ff(a->vec[6][0], b->max[0]);
+ r_out->max[1] = max_ff(a->vec[6][1], b->max[1]);
+ r_out->max[2] = max_ff(a->vec[6][2], b->max[2]);
+}
+
+static void make_box_from_metaelem(Box *r, const MetaElem *ml)
+{
+ copy_v3_v3(r->max, ml->bb->vec[6]);
+ copy_v3_v3(r->min, ml->bb->vec[0]);
+ r->ml = ml;
+}
+
+/**
+ * Partitions part of mainb array [start, end) along axis s. Returns i,
+ * where centroids of elements in the [start, i) segment lie "on the right side" of div,
+ * and elements in the [i, end) segment lie "on the left"
+ */
+static unsigned int partition_mainb(MetaElem **mainb, unsigned int start, unsigned int end, unsigned int s, float div)
+{
+ unsigned int i = start, j = end - 1;
+ div *= 2.0f;
+
+ while (1) {
+ while (i < j && div > (mainb[i]->bb->vec[6][s] + mainb[i]->bb->vec[0][s])) i++;
+ while (j > i && div < (mainb[j]->bb->vec[6][s] + mainb[j]->bb->vec[0][s])) j--;
+
+ if (i >= j)
+ break;
+
+ SWAP(MetaElem *, mainb[i], mainb[j]);
+ i++;
+ j--;
+ }
+
+ if (i == start) {
+ i++;
+ }
+
+ return i;
+}
+
+/**
+ * Recursively builds a BVH, dividing elements along the middle of the longest axis of allbox.
+ */
+static void build_bvh_spatial(
+ PROCESS *process, MetaballBVHNode *node,
+ unsigned int start, unsigned int end, const Box *allbox)
+{
+ unsigned int part, j, s;
+ float dim[3], div;
+
+ /* Maximum bvh queue size is number of nodes which are made, equals calls to this function. */
+ process->bvh_queue_size++;
+
+ dim[0] = allbox->max[0] - allbox->min[0];
+ dim[1] = allbox->max[1] - allbox->min[1];
+ dim[2] = allbox->max[2] - allbox->min[2];
+
+ s = 0;
+ if (dim[1] > dim[0] && dim[1] > dim[2]) s = 1;
+ else if (dim[2] > dim[1] && dim[2] > dim[0]) s = 2;
+
+ div = allbox->min[s] + (dim[s] / 2.0f);
+
+ part = partition_mainb(process->mainb, start, end, s, div);
+
+ make_box_from_metaelem(&node->bb[0], process->mainb[start]);
+ node->child[0] = NULL;
+
+ if (part > start + 1) {
+ for (j = start; j < part; j++) {
+ make_box_union(process->mainb[j]->bb, &node->bb[0], &node->bb[0]);
+ }
+
+ node->child[0] = BLI_memarena_alloc(process->pgn_elements, sizeof(MetaballBVHNode));
+ build_bvh_spatial(process, node->child[0], start, part, &node->bb[0]);
+ }
+
+ node->child[1] = NULL;
+ if (part < end) {
+ make_box_from_metaelem(&node->bb[1], process->mainb[part]);
+
+ if (part < end - 1) {
+ for (j = part; j < end; j++) {
+ make_box_union(process->mainb[j]->bb, &node->bb[1], &node->bb[1]);
+ }
+
+ node->child[1] = BLI_memarena_alloc(process->pgn_elements, sizeof(MetaballBVHNode));
+ build_bvh_spatial(process, node->child[1], part, end, &node->bb[1]);
+ }
+ }
+ else {
+ INIT_MINMAX(node->bb[1].min, node->bb[1].max);
+ }
+}
+
+/* ******************** ARITH ************************* */
+
+/**
+ * BASED AT CODE (but mostly rewritten) :
+ * C code from the article
+ * "An Implicit Surface Polygonizer"
+ * by Jules Bloomenthal, jbloom@beauty.gmu.edu
+ * in "Graphics Gems IV", Academic Press, 1994
+ *
+ * Authored by Jules Bloomenthal, Xerox PARC.
+ * Copyright (c) Xerox Corporation, 1991. All rights reserved.
+ * Permission is granted to reproduce, use and distribute this code for
+ * any and all purposes, provided that this notice appears in all copies.
+ */
+
+#define L 0 /* left direction: -x, -i */
+#define R 1 /* right direction: +x, +i */
+#define B 2 /* bottom direction: -y, -j */
+#define T 3 /* top direction: +y, +j */
+#define N 4 /* near direction: -z, -k */
+#define F 5 /* far direction: +z, +k */
+#define LBN 0 /* left bottom near corner */
+#define LBF 1 /* left bottom far corner */
+#define LTN 2 /* left top near corner */
+#define LTF 3 /* left top far corner */
+#define RBN 4 /* right bottom near corner */
+#define RBF 5 /* right bottom far corner */
+#define RTN 6 /* right top near corner */
+#define RTF 7 /* right top far corner */
+
+/**
+ * the LBN corner of cube (i, j, k), corresponds with location
+ * (i-0.5)*size, (j-0.5)*size, (k-0.5)*size)
+ */
+
+#define HASHBIT (5)
+#define HASHSIZE (size_t)(1 << (3 * HASHBIT)) /*! < hash table size (32768) */
+
+#define HASH(i, j, k) ((((( (i) & 31) << 5) | ( (j) & 31)) << 5) | ( (k) & 31) )
+
+#define MB_BIT(i, bit) (((i) >> (bit)) & 1)
+// #define FLIP(i, bit) ((i) ^ 1 << (bit)) /* flip the given bit of i */
+
+/* ******************** DENSITY COPMPUTATION ********************* */
+
+/**
+ * Computes density from given metaball at given position.
+ * Metaball equation is: ``(1 - r^2 / R^2)^3 * s``
+ *
+ * r = distance from center
+ * R = metaball radius
+ * s - metaball stiffness
+ */
+static float densfunc(const MetaElem *ball, float x, float y, float z)
+{
+ float dist2;
+ float dvec[3] = {x, y, z};
+
+ mul_m4_v3((float (*)[4])ball->imat, dvec);
+
+ switch (ball->type) {
+ case MB_BALL:
+ /* do nothing */
+ break;
+ case MB_CUBE:
+ if (dvec[2] > ball->expz) dvec[2] -= ball->expz;
+ else if (dvec[2] < -ball->expz) dvec[2] += ball->expz;
+ else dvec[2] = 0.0;
+ /* fall through */
+ case MB_PLANE:
+ if (dvec[1] > ball->expy) dvec[1] -= ball->expy;
+ else if (dvec[1] < -ball->expy) dvec[1] += ball->expy;
+ else dvec[1] = 0.0;
+ /* fall through */
+ case MB_TUBE:
+ if (dvec[0] > ball->expx) dvec[0] -= ball->expx;
+ else if (dvec[0] < -ball->expx) dvec[0] += ball->expx;
+ else dvec[0] = 0.0;
+ break;
+ case MB_ELIPSOID:
+ dvec[0] /= ball->expx;
+ dvec[1] /= ball->expy;
+ dvec[2] /= ball->expz;
+ break;
+
+ /* *** deprecated, could be removed?, do-versioned at least *** */
+ case MB_TUBEX:
+ if (dvec[0] > ball->len) dvec[0] -= ball->len;
+ else if (dvec[0] < -ball->len) dvec[0] += ball->len;
+ else dvec[0] = 0.0;
+ break;
+ case MB_TUBEY:
+ if (dvec[1] > ball->len) dvec[1] -= ball->len;
+ else if (dvec[1] < -ball->len) dvec[1] += ball->len;
+ else dvec[1] = 0.0;
+ break;
+ case MB_TUBEZ:
+ if (dvec[2] > ball->len) dvec[2] -= ball->len;
+ else if (dvec[2] < -ball->len) dvec[2] += ball->len;
+ else dvec[2] = 0.0;
+ break;
+ /* *** end deprecated *** */
+ }
+
+ /* ball->rad2 is inverse of squared rad */
+ dist2 = 1.0f - (len_squared_v3(dvec) * ball->rad2);
+
+ /* ball->s is negative if metaball is negative */
+ return (dist2 < 0.0f) ? 0.0f : (ball->s * dist2 * dist2 * dist2);
+}
+
+/**
+ * Computes density at given position form all metaballs which contain this point in their box.
+ * Traverses BVH using a queue.
+ */
+static float metaball(PROCESS *process, float x, float y, float z)
+{
+ int i;
+ float dens = 0.0f;
+ unsigned int front = 0, back = 0;
+ MetaballBVHNode *node;
+
+ process->bvh_queue[front++] = &process->metaball_bvh;
+
+ while (front != back) {
+ node = process->bvh_queue[back++];
+
+ for (i = 0; i < 2; i++) {
+ if ((node->bb[i].min[0] <= x) && (node->bb[i].max[0] >= x) &&
+ (node->bb[i].min[1] <= y) && (node->bb[i].max[1] >= y) &&
+ (node->bb[i].min[2] <= z) && (node->bb[i].max[2] >= z))
+ {
+ if (node->child[i]) process->bvh_queue[front++] = node->child[i];
+ else dens += densfunc(node->bb[i].ml, x, y, z);
+ }
+ }
+ }
+
+ return process->thresh - dens;
+}
+
+/**
+ * Adds face to indices, expands memory if needed.
+ */
+static void make_face(PROCESS *process, int i1, int i2, int i3, int i4)
+{
+ int *cur;
+
+#ifdef USE_ACCUM_NORMAL
+ float n[3];
+#endif
+
+ if (UNLIKELY(process->totindex == process->curindex)) {
+ process->totindex += 4096;
+ process->indices = MEM_reallocN(process->indices, sizeof(int[4]) * process->totindex);
+ }
+
+ cur = process->indices[process->curindex++];
+
+ /* displists now support array drawing, we treat tri's as fake quad */
+
+ cur[0] = i1;
+ cur[1] = i2;
+ cur[2] = i3;
+
+ if (i4 == 0) {
+ cur[3] = i3;
+ }
+ else {
+ cur[3] = i4;
+ }
+
+#ifdef USE_ACCUM_NORMAL
+ if (i4 == 0) {
+ normal_tri_v3(n, process->co[i1], process->co[i2], process->co[i3]);
+ accumulate_vertex_normals(
+ process->no[i1], process->no[i2], process->no[i3], NULL, n,
+ process->co[i1], process->co[i2], process->co[i3], NULL);
+ }
+ else {
+ normal_quad_v3(n, process->co[i1], process->co[i2], process->co[i3], process->co[i4]);
+ accumulate_vertex_normals(
+ process->no[i1], process->no[i2], process->no[i3], process->no[i4], n,
+ process->co[i1], process->co[i2], process->co[i3], process->co[i4]);
+ }
+#endif
+
+}
+
+/* Frees allocated memory */
+static void freepolygonize(PROCESS *process)
+{
+ if (process->corners) MEM_freeN(process->corners);
+ if (process->edges) MEM_freeN(process->edges);
+ if (process->centers) MEM_freeN(process->centers);
+ if (process->mainb) MEM_freeN(process->mainb);
+ if (process->bvh_queue) MEM_freeN(process->bvh_queue);
+ if (process->pgn_elements) BLI_memarena_free(process->pgn_elements);
+}
+
+/* **************** POLYGONIZATION ************************ */
+
+/**** Cubical Polygonization (optional) ****/
+
+#define LB 0 /* left bottom edge */
+#define LT 1 /* left top edge */
+#define LN 2 /* left near edge */
+#define LF 3 /* left far edge */
+#define RB 4 /* right bottom edge */
+#define RT 5 /* right top edge */
+#define RN 6 /* right near edge */
+#define RF 7 /* right far edge */
+#define BN 8 /* bottom near edge */
+#define BF 9 /* bottom far edge */
+#define TN 10 /* top near edge */
+#define TF 11 /* top far edge */
+
+static INTLISTS *cubetable[256];
+static char faces[256];
+
+/* edge: LB, LT, LN, LF, RB, RT, RN, RF, BN, BF, TN, TF */
+static int corner1[12] = {
+ LBN, LTN, LBN, LBF, RBN, RTN, RBN, RBF, LBN, LBF, LTN, LTF
+};
+static int corner2[12] = {
+ LBF, LTF, LTN, LTF, RBF, RTF, RTN, RTF, RBN, RBF, RTN, RTF
+};
+static int leftface[12] = {
+ B, L, L, F, R, T, N, R, N, B, T, F
+};
+/* face on left when going corner1 to corner2 */
+static int rightface[12] = {
+ L, T, N, L, B, R, R, F, B, F, N, T
+};
+/* face on right when going corner1 to corner2 */
+
+/**
+ * triangulate the cube directly, without decomposition
+ */
+static void docube(PROCESS *process, CUBE *cube)
+{
+ INTLISTS *polys;
+ CORNER *c1, *c2;
+ int i, index = 0, count, indexar[8];
+
+ /* Determine which case cube falls into. */
+ for (i = 0; i < 8; i++) {
+ if (cube->corners[i]->value > 0.0f) {
+ index += (1 << i);
+ }
+ }
+
+ /* Using faces[] table, adds neighbouring cube if surface intersects face in this direction. */
+ if (MB_BIT(faces[index], 0)) add_cube(process, cube->i - 1, cube->j, cube->k);
+ if (MB_BIT(faces[index], 1)) add_cube(process, cube->i + 1, cube->j, cube->k);
+ if (MB_BIT(faces[index], 2)) add_cube(process, cube->i, cube->j - 1, cube->k);
+ if (MB_BIT(faces[index], 3)) add_cube(process, cube->i, cube->j + 1, cube->k);
+ if (MB_BIT(faces[index], 4)) add_cube(process, cube->i, cube->j, cube->k - 1);
+ if (MB_BIT(faces[index], 5)) add_cube(process, cube->i, cube->j, cube->k + 1);
+
+ /* Using cubetable[], determines polygons for output. */
+ for (polys = cubetable[index]; polys; polys = polys->next) {
+ INTLIST *edges;
+
+ count = 0;
+ /* Sets needed vertex id's lying on the edges. */
+ for (edges = polys->list; edges; edges = edges->next) {
+ c1 = cube->corners[corner1[edges->i]];
+ c2 = cube->corners[corner2[edges->i]];
+
+ indexar[count] = vertid(process, c1, c2);
+ count++;
+ }
+
+ /* Adds faces to output. */
+ if (count > 2) {
+ switch (count) {
+ case 3:
+ make_face(process, indexar[2], indexar[1], indexar[0], 0);
+ break;
+ case 4:
+ if (indexar[0] == 0) make_face(process, indexar[0], indexar[3], indexar[2], indexar[1]);
+ else make_face(process, indexar[3], indexar[2], indexar[1], indexar[0]);
+ break;
+ case 5:
+ if (indexar[0] == 0) make_face(process, indexar[0], indexar[3], indexar[2], indexar[1]);
+ else make_face(process, indexar[3], indexar[2], indexar[1], indexar[0]);
+
+ make_face(process, indexar[4], indexar[3], indexar[0], 0);
+ break;
+ case 6:
+ if (indexar[0] == 0) {
+ make_face(process, indexar[0], indexar[3], indexar[2], indexar[1]);
+ make_face(process, indexar[0], indexar[5], indexar[4], indexar[3]);
+ }
+ else {
+ make_face(process, indexar[3], indexar[2], indexar[1], indexar[0]);
+ make_face(process, indexar[5], indexar[4], indexar[3], indexar[0]);
+ }
+ break;
+ case 7:
+ if (indexar[0] == 0) {
+ make_face(process, indexar[0], indexar[3], indexar[2], indexar[1]);
+ make_face(process, indexar[0], indexar[5], indexar[4], indexar[3]);
+ }
+ else {
+ make_face(process, indexar[3], indexar[2], indexar[1], indexar[0]);
+ make_face(process, indexar[5], indexar[4], indexar[3], indexar[0]);
+ }
+
+ make_face(process, indexar[6], indexar[5], indexar[0], 0);
+
+ break;
+ }
+ }
+ }
+}
+
+/**
+ * return corner with the given lattice location
+ * set (and cache) its function value
+ */
+static CORNER *setcorner(PROCESS *process, int i, int j, int k)
+{
+ /* for speed, do corner value caching here */
+ CORNER *c;
+ int index;
+
+ /* does corner exist? */
+ index = HASH(i, j, k);
+ c = process->corners[index];
+
+ for (; c != NULL; c = c->next) {
+ if (c->i == i && c->j == j && c->k == k) {
+ return c;
+ }
+ }
+
+ c = BLI_memarena_alloc(process->pgn_elements, sizeof(CORNER));
+
+ c->i = i;
+ c->co[0] = ((float)i - 0.5f) * process->size;
+ c->j = j;
+ c->co[1] = ((float)j - 0.5f) * process->size;
+ c->k = k;
+ c->co[2] = ((float)k - 0.5f) * process->size;
+
+ c->value = metaball(process, c->co[0], c->co[1], c->co[2]);
+
+ c->next = process->corners[index];
+ process->corners[index] = c;
+
+ return c;
+}
+
+/**
+ * return next clockwise edge from given edge around given face
+ */
+static int nextcwedge(int edge, int face)
+{
+ switch (edge) {
+ case LB:
+ return (face == L) ? LF : BN;
+ case LT:
+ return (face == L) ? LN : TF;
+ case LN:
+ return (face == L) ? LB : TN;
+ case LF:
+ return (face == L) ? LT : BF;
+ case RB:
+ return (face == R) ? RN : BF;
+ case RT:
+ return (face == R) ? RF : TN;
+ case RN:
+ return (face == R) ? RT : BN;
+ case RF:
+ return (face == R) ? RB : TF;
+ case BN:
+ return (face == B) ? RB : LN;
+ case BF:
+ return (face == B) ? LB : RF;
+ case TN:
+ return (face == T) ? LT : RN;
+ case TF:
+ return (face == T) ? RT : LF;
+ }
+ return 0;
+}
+
+/**
+ * \return the face adjoining edge that is not the given face
+ */
+static int otherface(int edge, int face)
+{
+ int other = leftface[edge];
+ return face == other ? rightface[edge] : other;
+}
+
+/**
+ * create the 256 entry table for cubical polygonization
+ */
+static void makecubetable(void)
+{
+ static bool is_done = false;
+ int i, e, c, done[12], pos[8];
+
+ if (is_done) return;
+ is_done = true;
+
+ for (i = 0; i < 256; i++) {
+ for (e = 0; e < 12; e++) done[e] = 0;
+ for (c = 0; c < 8; c++) pos[c] = MB_BIT(i, c);
+ for (e = 0; e < 12; e++)
+ if (!done[e] && (pos[corner1[e]] != pos[corner2[e]])) {
+ INTLIST *ints = NULL;
+ INTLISTS *lists = MEM_callocN(sizeof(INTLISTS), "mball_intlist");
+ int start = e, edge = e;
+
+ /* get face that is to right of edge from pos to neg corner: */
+ int face = pos[corner1[e]] ? rightface[e] : leftface[e];
+
+ while (1) {
+ edge = nextcwedge(edge, face);
+ done[edge] = 1;
+ if (pos[corner1[edge]] != pos[corner2[edge]]) {
+ INTLIST *tmp = ints;
+
+ ints = MEM_callocN(sizeof(INTLIST), "mball_intlist");
+ ints->i = edge;
+ ints->next = tmp; /* add edge to head of list */
+
+ if (edge == start) break;
+ face = otherface(edge, face);
+ }
+ }
+ lists->list = ints; /* add ints to head of table entry */
+ lists->next = cubetable[i];
+ cubetable[i] = lists;
+ }
+ }
+
+ for (i = 0; i < 256; i++) {
+ INTLISTS *polys;
+ faces[i] = 0;
+ for (polys = cubetable[i]; polys; polys = polys->next) {
+ INTLIST *edges;
+
+ for (edges = polys->list; edges; edges = edges->next) {
+ if (edges->i == LB || edges->i == LT || edges->i == LN || edges->i == LF) faces[i] |= 1 << L;
+ if (edges->i == RB || edges->i == RT || edges->i == RN || edges->i == RF) faces[i] |= 1 << R;
+ if (edges->i == LB || edges->i == RB || edges->i == BN || edges->i == BF) faces[i] |= 1 << B;
+ if (edges->i == LT || edges->i == RT || edges->i == TN || edges->i == TF) faces[i] |= 1 << T;
+ if (edges->i == LN || edges->i == RN || edges->i == BN || edges->i == TN) faces[i] |= 1 << N;
+ if (edges->i == LF || edges->i == RF || edges->i == BF || edges->i == TF) faces[i] |= 1 << F;
+ }
+ }
+ }
+}
+
+void BKE_mball_cubeTable_free(void)
+{
+ int i;
+ INTLISTS *lists, *nlists;
+ INTLIST *ints, *nints;
+
+ for (i = 0; i < 256; i++) {
+ lists = cubetable[i];
+ while (lists) {
+ nlists = lists->next;
+
+ ints = lists->list;
+ while (ints) {
+ nints = ints->next;
+ MEM_freeN(ints);
+ ints = nints;
+ }
+
+ MEM_freeN(lists);
+ lists = nlists;
+ }
+ cubetable[i] = NULL;
+ }
+}
+
+/**** Storage ****/
+
+/**
+ * Inserts cube at lattice i, j, k into hash table, marking it as "done"
+ */
+static int setcenter(PROCESS *process, CENTERLIST *table[], const int i, const int j, const int k)
+{
+ int index;
+ CENTERLIST *newc, *l, *q;
+
+ index = HASH(i, j, k);
+ q = table[index];
+
+ for (l = q; l != NULL; l = l->next) {
+ if (l->i == i && l->j == j && l->k == k) return 1;
+ }
+
+ newc = BLI_memarena_alloc(process->pgn_elements, sizeof(CENTERLIST));
+ newc->i = i;
+ newc->j = j;
+ newc->k = k;
+ newc->next = q;
+ table[index] = newc;
+
+ return 0;
+}
+
+/**
+ * Sets vid of vertex lying on given edge.
+ */
+static void setedge(
+ PROCESS *process,
+ int i1, int j1, int k1,
+ int i2, int j2, int k2,
+ int vid)
+{
+ int index;
+ EDGELIST *newe;
+
+ if (i1 > i2 || (i1 == i2 && (j1 > j2 || (j1 == j2 && k1 > k2)))) {
+ int t = i1;
+ i1 = i2;
+ i2 = t;
+ t = j1;
+ j1 = j2;
+ j2 = t;
+ t = k1;
+ k1 = k2;
+ k2 = t;
+ }
+ index = HASH(i1, j1, k1) + HASH(i2, j2, k2);
+ newe = BLI_memarena_alloc(process->pgn_elements, sizeof(EDGELIST));
+
+ newe->i1 = i1;
+ newe->j1 = j1;
+ newe->k1 = k1;
+ newe->i2 = i2;
+ newe->j2 = j2;
+ newe->k2 = k2;
+ newe->vid = vid;
+ newe->next = process->edges[index];
+ process->edges[index] = newe;
+}
+
+/**
+ * \return vertex id for edge; return -1 if not set
+ */
+static int getedge(EDGELIST *table[],
+ int i1, int j1, int k1,
+ int i2, int j2, int k2)
+{
+ EDGELIST *q;
+
+ if (i1 > i2 || (i1 == i2 && (j1 > j2 || (j1 == j2 && k1 > k2)))) {
+ int t = i1;
+ i1 = i2;
+ i2 = t;
+ t = j1;
+ j1 = j2;
+ j2 = t;
+ t = k1;
+ k1 = k2;
+ k2 = t;
+ }
+ q = table[HASH(i1, j1, k1) + HASH(i2, j2, k2)];
+ for (; q != NULL; q = q->next) {
+ if (q->i1 == i1 && q->j1 == j1 && q->k1 == k1 &&
+ q->i2 == i2 && q->j2 == j2 && q->k2 == k2)
+ {
+ return q->vid;
+ }
+ }
+ return -1;
+}
+
+/**
+ * Adds a vertex, expands memory if needed.
+ */
+static void addtovertices(PROCESS *process, const float v[3], const float no[3])
+{
+ if (process->curvertex == process->totvertex) {
+ process->totvertex += 4096;
+ process->co = MEM_reallocN(process->co, process->totvertex * sizeof(float[3]));
+ process->no = MEM_reallocN(process->no, process->totvertex * sizeof(float[3]));
+ }
+
+ copy_v3_v3(process->co[process->curvertex], v);
+ copy_v3_v3(process->no[process->curvertex], no);
+
+ process->curvertex++;
+}
+
+#ifndef USE_ACCUM_NORMAL
+/**
+ * Computes normal from density field at given point.
+ *
+ * \note Doesn't do normalization!
+ */
+static void vnormal(PROCESS *process, const float point[3], float r_no[3])
+{
+ const float delta = process->delta;
+ const float f = metaball(process, point[0], point[1], point[2]);
+
+ r_no[0] = metaball(process, point[0] + delta, point[1], point[2]) - f;
+ r_no[1] = metaball(process, point[0], point[1] + delta, point[2]) - f;
+ r_no[2] = metaball(process, point[0], point[1], point[2] + delta) - f;
+
+#if 0
+ f = normalize_v3(r_no);
+
+ if (0) {
+ float tvec[3];
+
+ delta *= 2.0f;
+
+ f = process->function(process, point[0], point[1], point[2]);
+
+ tvec[0] = process->function(process, point[0] + delta, point[1], point[2]) - f;
+ tvec[1] = process->function(process, point[0], point[1] + delta, point[2]) - f;
+ tvec[2] = process->function(process, point[0], point[1], point[2] + delta) - f;
+
+ if (normalize_v3(tvec) != 0.0f) {
+ add_v3_v3(r_no, tvec);
+ normalize_v3(r_no);
+ }
+ }
+#endif
+}
+#endif /* USE_ACCUM_NORMAL */
+
+/**
+ * \return the id of vertex between two corners.
+ *
+ * If it wasn't previously computed, does #converge() and adds vertex to process.
+ */
+static int vertid(PROCESS *process, const CORNER *c1, const CORNER *c2)
+{
+ float v[3], no[3];
+ int vid = getedge(process->edges, c1->i, c1->j, c1->k, c2->i, c2->j, c2->k);
+
+ if (vid != -1) return vid; /* previously computed */
+
+ converge(process, c1, c2, v); /* position */
+
+#ifdef USE_ACCUM_NORMAL
+ zero_v3(no);
+#else
+ vnormal(process, v, no);
+#endif
+
+ addtovertices(process, v, no); /* save vertex */
+ vid = (int)process->curvertex - 1;
+ setedge(process, c1->i, c1->j, c1->k, c2->i, c2->j, c2->k, vid);
+
+ return vid;
+}
+
+/**
+ * Given two corners, computes approximation of surface intersection point between them.
+ * In case of small threshold, do bisection.
+ */
+static void converge(PROCESS *process, const CORNER *c1, const CORNER *c2, float r_p[3])
+{
+ float tmp, dens;
+ unsigned int i;
+ float c1_value, c1_co[3];
+ float c2_value, c2_co[3];
+
+ if (c1->value < c2->value) {
+ c1_value = c2->value;
+ copy_v3_v3(c1_co, c2->co);
+ c2_value = c1->value;
+ copy_v3_v3(c2_co, c1->co);
+ }
+ else {
+ c1_value = c1->value;
+ copy_v3_v3(c1_co, c1->co);
+ c2_value = c2->value;
+ copy_v3_v3(c2_co, c2->co);
+ }
+
+
+ for (i = 0; i < process->converge_res; i++) {
+ interp_v3_v3v3(r_p, c1_co, c2_co, 0.5f);
+ dens = metaball(process, r_p[0], r_p[1], r_p[2]);
+
+ if (dens > 0.0f) {
+ c1_value = dens;
+ copy_v3_v3(c1_co, r_p);
+ }
+ else {
+ c2_value = dens;
+ copy_v3_v3(c2_co, r_p);
+ }
+ }
+
+ tmp = -c1_value / (c2_value - c1_value);
+ interp_v3_v3v3(r_p, c1_co, c2_co, tmp);
+}
+
+/**
+ * Adds cube at given lattice position to cube stack of process.
+ */
+static void add_cube(PROCESS *process, int i, int j, int k)
+{
+ CUBES *ncube;
+ int n;
+
+ /* test if cube has been found before */
+ if (setcenter(process, process->centers, i, j, k) == 0) {
+ /* push cube on stack: */
+ ncube = BLI_memarena_alloc(process->pgn_elements, sizeof(CUBES));
+ ncube->next = process->cubes;
+ process->cubes = ncube;
+
+ ncube->cube.i = i;
+ ncube->cube.j = j;
+ ncube->cube.k = k;
+
+ /* set corners of initial cube: */
+ for (n = 0; n < 8; n++)
+ ncube->cube.corners[n] = setcorner(process, i + MB_BIT(n, 2), j + MB_BIT(n, 1), k + MB_BIT(n, 0));
+ }
+}
+
+static void next_lattice(int r[3], const float pos[3], const float size)
+{
+ r[0] = (int)ceil((pos[0] / size) + 0.5f);
+ r[1] = (int)ceil((pos[1] / size) + 0.5f);
+ r[2] = (int)ceil((pos[2] / size) + 0.5f);
+}
+static void prev_lattice(int r[3], const float pos[3], const float size)
+{
+ next_lattice(r, pos, size);
+ r[0]--; r[1]--; r[2]--;
+}
+static void closest_latice(int r[3], const float pos[3], const float size)
+{
+ r[0] = (int)floorf(pos[0] / size + 1.0f);
+ r[1] = (int)floorf(pos[1] / size + 1.0f);
+ r[2] = (int)floorf(pos[2] / size + 1.0f);
+}
+
+/**
+ * Find at most 26 cubes to start polygonization from.
+ */
+static void find_first_points(PROCESS *process, const unsigned int em)
+{
+ const MetaElem *ml;
+ int center[3], lbn[3], rtf[3], it[3], dir[3], add[3];
+ float tmp[3], a, b;
+
+ ml = process->mainb[em];
+
+ mid_v3_v3v3(tmp, ml->bb->vec[0], ml->bb->vec[6]);
+ closest_latice(center, tmp, process->size);
+ prev_lattice(lbn, ml->bb->vec[0], process->size);
+ next_lattice(rtf, ml->bb->vec[6], process->size);
+
+ for (dir[0] = -1; dir[0] <= 1; dir[0]++) {
+ for (dir[1] = -1; dir[1] <= 1; dir[1]++) {
+ for (dir[2] = -1; dir[2] <= 1; dir[2]++) {
+ if (dir[0] == 0 && dir[1] == 0 && dir[2] == 0) {
+ continue;
+ }
+
+ copy_v3_v3_int(it, center);
+
+ b = setcorner(process, it[0], it[1], it[2])->value;
+ do {
+ it[0] += dir[0];
+ it[1] += dir[1];
+ it[2] += dir[2];
+ a = b;
+ b = setcorner(process, it[0], it[1], it[2])->value;
+
+ if (a * b < 0.0f) {
+ add[0] = it[0] - dir[0];
+ add[1] = it[1] - dir[1];
+ add[2] = it[2] - dir[2];
+ DO_MIN(it, add);
+ add_cube(process, add[0], add[1], add[2]);
+ break;
+ }
+ } while ((it[0] > lbn[0]) && (it[1] > lbn[1]) && (it[2] > lbn[2]) &&
+ (it[0] < rtf[0]) && (it[1] < rtf[1]) && (it[2] < rtf[2]));
+ }
+ }
+ }
+}
+
+/**
+ * The main polygonization proc.
+ * Allocates memory, makes cubetable,
+ * finds starting surface points
+ * and processes cubes on the stack until none left.
+ */
+static void polygonize(PROCESS *process)
+{
+ CUBE c;
+ unsigned int i;
+
+ process->centers = MEM_callocN(HASHSIZE * sizeof(CENTERLIST *), "mbproc->centers");
+ process->corners = MEM_callocN(HASHSIZE * sizeof(CORNER *), "mbproc->corners");
+ process->edges = MEM_callocN(2 * HASHSIZE * sizeof(EDGELIST *), "mbproc->edges");
+ process->bvh_queue = MEM_callocN(sizeof(MetaballBVHNode *) * process->bvh_queue_size, "Metaball BVH Queue");
+
+ makecubetable();
+
+ for (i = 0; i < process->totelem; i++) {
+ find_first_points(process, i);
+ }
+
+ while (process->cubes != NULL) {
+ c = process->cubes->cube;
+ process->cubes = process->cubes->next;
+
+ docube(process, &c);
+ }
+}
+
+/**
+ * Iterates over ALL objects in the scene and all of its sets, including
+ * making all duplis(not only metas). Copies metas to mainb array.
+ * Computes bounding boxes for building BVH. */
+static void init_meta(EvaluationContext *eval_ctx, PROCESS *process, Scene *scene, Object *ob)
+{
+ Scene *sce_iter = scene;
+ Base *base;
+ Object *bob;
+ MetaBall *mb;
+ const MetaElem *ml;
+ float obinv[4][4], obmat[4][4];
+ unsigned int i;
+ int obnr, zero_size = 0;
+ char obname[MAX_ID_NAME];
+ SceneBaseIter iter;
+
+ copy_m4_m4(obmat, ob->obmat); /* to cope with duplicators from BKE_scene_base_iter_next */
+ invert_m4_m4(obinv, ob->obmat);
+
+ BLI_split_name_num(obname, &obnr, ob->id.name + 2, '.');
+
+ /* make main array */
+ BKE_scene_base_iter_next(eval_ctx, &iter, &sce_iter, 0, NULL, NULL);
+ while (BKE_scene_base_iter_next(eval_ctx, &iter, &sce_iter, 1, &base, &bob)) {
+ if (bob->type == OB_MBALL) {
+ zero_size = 0;
+ ml = NULL;
+
+ if (bob == ob && (base->flag & OB_FROMDUPLI) == 0) {
+ mb = ob->data;
+
+ if (mb->editelems) ml = mb->editelems->first;
+ else ml = mb->elems.first;
+ }
+ else {
+ char name[MAX_ID_NAME];
+ int nr;
+
+ BLI_split_name_num(name, &nr, bob->id.name + 2, '.');
+ if (STREQ(obname, name)) {
+ mb = bob->data;
+
+ if (mb->editelems) ml = mb->editelems->first;
+ else ml = mb->elems.first;
+ }
+ }
+
+ /* when metaball object has zero scale, then MetaElem to this MetaBall
+ * will not be put to mainb array */
+ if (has_zero_axis_m4(bob->obmat)) {
+ zero_size = 1;
+ }
+ else if (bob->parent) {
+ struct Object *pob = bob->parent;
+ while (pob) {
+ if (has_zero_axis_m4(pob->obmat)) {
+ zero_size = 1;
+ break;
+ }
+ pob = pob->parent;
+ }
+ }
+
+ if (zero_size) {
+ while (ml) {
+ ml = ml->next;
+ }
+ }
+ else {
+ while (ml) {
+ if (!(ml->flag & MB_HIDE)) {
+ float pos[4][4], rot[4][4];
+ float expx, expy, expz;
+ float tempmin[3], tempmax[3];
+
+ MetaElem *new_ml;
+
+ /* make a copy because of duplicates */
+ new_ml = BLI_memarena_alloc(process->pgn_elements, sizeof(MetaElem));
+ *(new_ml) = *ml;
+ new_ml->bb = BLI_memarena_alloc(process->pgn_elements, sizeof(BoundBox));
+ new_ml->mat = BLI_memarena_alloc(process->pgn_elements, 4 * 4 * sizeof(float));
+ new_ml->imat = BLI_memarena_alloc(process->pgn_elements, 4 * 4 * sizeof(float));
+
+ /* too big stiffness seems only ugly due to linear interpolation
+ * no need to have possibility for too big stiffness */
+ if (ml->s > 10.0f) new_ml->s = 10.0f;
+ else new_ml->s = ml->s;
+
+ /* if metaball is negative, set stiffness negative */
+ if (new_ml->flag & MB_NEGATIVE) new_ml->s = -new_ml->s;
+
+ /* Translation of MetaElem */
+ unit_m4(pos);
+ pos[3][0] = ml->x;
+ pos[3][1] = ml->y;
+ pos[3][2] = ml->z;
+
+ /* Rotation of MetaElem is stored in quat */
+ quat_to_mat4(rot, ml->quat);
+
+ /* basis object space -> world -> ml object space -> position -> rotation -> ml local space */
+ mul_m4_series((float(*)[4])new_ml->mat, obinv, bob->obmat, pos, rot);
+ /* ml local space -> basis object space */
+ invert_m4_m4((float(*)[4])new_ml->imat, (float(*)[4])new_ml->mat);
+
+ /* rad2 is inverse of squared radius */
+ new_ml->rad2 = 1 / (ml->rad * ml->rad);
+
+ /* initial dimensions = radius */
+ expx = ml->rad;
+ expy = ml->rad;
+ expz = ml->rad;
+
+ switch (ml->type) {
+ case MB_BALL:
+ break;
+ case MB_CUBE: /* cube is "expanded" by expz, expy and expx */
+ expz += ml->expz;
+ /* fall through */
+ case MB_PLANE: /* plane is "expanded" by expy and expx */
+ expy += ml->expy;
+ /* fall through */
+ case MB_TUBE: /* tube is "expanded" by expx */
+ expx += ml->expx;
+ break;
+ case MB_ELIPSOID: /* ellipsoid is "stretched" by exp* */
+ expx *= ml->expx;
+ expy *= ml->expy;
+ expz *= ml->expz;
+ break;
+ }
+
+ /* untransformed Bounding Box of MetaElem */
+ /* TODO, its possible the elem type has been changed and the exp* values can use a fallback */
+ copy_v3_fl3(new_ml->bb->vec[0], -expx, -expy, -expz); /* 0 */
+ copy_v3_fl3(new_ml->bb->vec[1], +expx, -expy, -expz); /* 1 */
+ copy_v3_fl3(new_ml->bb->vec[2], +expx, +expy, -expz); /* 2 */
+ copy_v3_fl3(new_ml->bb->vec[3], -expx, +expy, -expz); /* 3 */
+ copy_v3_fl3(new_ml->bb->vec[4], -expx, -expy, +expz); /* 4 */
+ copy_v3_fl3(new_ml->bb->vec[5], +expx, -expy, +expz); /* 5 */
+ copy_v3_fl3(new_ml->bb->vec[6], +expx, +expy, +expz); /* 6 */
+ copy_v3_fl3(new_ml->bb->vec[7], -expx, +expy, +expz); /* 7 */
+
+ /* transformation of Metalem bb */
+ for (i = 0; i < 8; i++)
+ mul_m4_v3((float(*)[4])new_ml->mat, new_ml->bb->vec[i]);
+
+ /* find max and min of transformed bb */
+ INIT_MINMAX(tempmin, tempmax);
+ for (i = 0; i < 8; i++) {
+ DO_MINMAX(new_ml->bb->vec[i], tempmin, tempmax);
+ }
+
+ /* set only point 0 and 6 - AABB of Metaelem */
+ copy_v3_v3(new_ml->bb->vec[0], tempmin);
+ copy_v3_v3(new_ml->bb->vec[6], tempmax);
+
+ /* add new_ml to mainb[] */
+ if (UNLIKELY(process->totelem == process->mem)) {
+ process->mem = process->mem * 2 + 10;
+ process->mainb = MEM_reallocN(process->mainb, sizeof(MetaElem *) * process->mem);
+ }
+ process->mainb[process->totelem++] = new_ml;
+ }
+ ml = ml->next;
+ }
+ }
+ }
+ }
+
+ /* compute AABB of all Metaelems */
+ if (process->totelem > 0) {
+ copy_v3_v3(process->allbb.min, process->mainb[0]->bb->vec[0]);
+ copy_v3_v3(process->allbb.max, process->mainb[0]->bb->vec[6]);
+ for (i = 1; i < process->totelem; i++)
+ make_box_union(process->mainb[i]->bb, &process->allbb, &process->allbb);
+ }
+}
+
+void BKE_mball_polygonize(EvaluationContext *eval_ctx, Scene *scene, Object *ob, ListBase *dispbase)
+{
+ MetaBall *mb;
+ DispList *dl;
+ unsigned int a;
+ PROCESS process = {0};
+
+ mb = ob->data;
+
+ process.thresh = mb->thresh;
+
+ if (process.thresh < 0.001f) process.converge_res = 16;
+ else if (process.thresh < 0.01f) process.converge_res = 8;
+ else if (process.thresh < 0.1f) process.converge_res = 4;
+ else process.converge_res = 2;
+
+ if ((eval_ctx->mode != DAG_EVAL_RENDER) && (mb->flag == MB_UPDATE_NEVER)) return;
+ if ((G.moving & (G_TRANSFORM_OBJ | G_TRANSFORM_EDIT)) && mb->flag == MB_UPDATE_FAST) return;
+
+ if (eval_ctx->mode == DAG_EVAL_RENDER) {
+ process.size = mb->rendersize;
+ }
+ else {
+ process.size = mb->wiresize;
+ if ((G.moving & (G_TRANSFORM_OBJ | G_TRANSFORM_EDIT)) && mb->flag == MB_UPDATE_HALFRES) {
+ process.size *= 2.0f;
+ }
+ }
+
+ process.delta = process.size * 0.001f;
+
+ process.pgn_elements = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, "Metaball memarena");
+
+ /* initialize all mainb (MetaElems) */
+ init_meta(eval_ctx, &process, scene, ob);
+
+ if (process.totelem > 0) {
+ build_bvh_spatial(&process, &process.metaball_bvh, 0, process.totelem, &process.allbb);
+
+ /* don't polygonize metaballs with too high resolution (base mball to small)
+ * note: Eps was 0.0001f but this was giving problems for blood animation for durian, using 0.00001f */
+ if (ob->size[0] > 0.00001f * (process.allbb.max[0] - process.allbb.min[0]) ||
+ ob->size[1] > 0.00001f * (process.allbb.max[1] - process.allbb.min[1]) ||
+ ob->size[2] > 0.00001f * (process.allbb.max[2] - process.allbb.min[2]))
+ {
+ polygonize(&process);
+
+ /* add resulting surface to displist */
+ if (process.curindex) {
+ dl = MEM_callocN(sizeof(DispList), "mballdisp");
+ BLI_addtail(dispbase, dl);
+ dl->type = DL_INDEX4;
+ dl->nr = (int)process.curvertex;
+ dl->parts = (int)process.curindex;
+
+ dl->index = (int *)process.indices;
+
+ for (a = 0; a < process.curvertex; a++) {
+ normalize_v3(process.no[a]);
+ }
+
+ dl->verts = (float *)process.co;
+ dl->nors = (float *)process.no;
+ }
+ }
+ }
+
+ freepolygonize(&process);
+}
diff --git a/source/blender/blenkernel/intern/mesh.c b/source/blender/blenkernel/intern/mesh.c
index 2e80379522c..8c89a724975 100644
--- a/source/blender/blenkernel/intern/mesh.c
+++ b/source/blender/blenkernel/intern/mesh.c
@@ -61,6 +61,7 @@
#include "BKE_object.h"
#include "BKE_editmesh.h"
+#include "DEG_depsgraph.h"
enum {
MESHCMP_DVERT_WEIGHTMISMATCH = 1,
@@ -414,6 +415,16 @@ void BKE_mesh_update_customdata_pointers(Mesh *me, const bool do_ensure_tess_cd)
me->mloopuv = CustomData_get_layer(&me->ldata, CD_MLOOPUV);
}
+bool BKE_mesh_has_custom_loop_normals(Mesh *me)
+{
+ if (me->edit_btmesh) {
+ return CustomData_has_layer(&me->edit_btmesh->bm->ldata, CD_CUSTOMLOOPNORMAL);
+ }
+ else {
+ return CustomData_has_layer(&me->ldata, CD_CUSTOMLOOPNORMAL);
+ }
+}
+
/* Note: unlinking is called when me->id.us is 0, question remains how
* much unlinking of Library data in Mesh should be done... probably
* we need a more generic method, like the expand() functions in
@@ -453,7 +464,7 @@ void BKE_mesh_free(Mesh *me, int unlink)
CustomData_free(&me->pdata, me->totpoly);
if (me->adt) {
- BKE_free_animdata(&me->id);
+ BKE_animdata_free(&me->id);
me->adt = NULL;
}
@@ -562,6 +573,10 @@ Mesh *BKE_mesh_copy_ex(Main *bmain, Mesh *me)
men->key = BKE_key_copy(me->key);
if (men->key) men->key->from = (ID *)men;
+ if (me->id.lib) {
+ BKE_id_lib_local_paths(bmain, me->id.lib, &men->id);
+ }
+
return men;
}
@@ -699,7 +714,7 @@ bool BKE_mesh_uv_cdlayer_rename_index(Mesh *me, const int poly_index, const int
}
/* Loop until we do have exactly the same name for all layers! */
- for (i = 1; (strcmp(cdlp->name, cdlu->name) != 0 || (cdlf && strcmp(cdlp->name, cdlf->name) != 0)); i++) {
+ for (i = 1; !STREQ(cdlp->name, cdlu->name) || (cdlf && !STREQ(cdlp->name, cdlf->name)); i++) {
switch (i % step) {
case 0:
BLI_strncpy(cdlp->name, cdlu->name, sizeof(cdlp->name));
@@ -1160,9 +1175,10 @@ static void make_edges_mdata_extend(MEdge **r_alledge, int *r_totedge,
/* Initialize mverts, medges and, faces for converting nurbs to mesh and derived mesh */
/* return non-zero on error */
-int BKE_mesh_nurbs_to_mdata(Object *ob, MVert **allvert, int *totvert,
- MEdge **alledge, int *totedge, MLoop **allloop, MPoly **allpoly,
- int *totloop, int *totpoly)
+int BKE_mesh_nurbs_to_mdata(
+ Object *ob, MVert **r_allvert, int *r_totvert,
+ MEdge **r_alledge, int *r_totedge, MLoop **r_allloop, MPoly **r_allpoly,
+ int *r_totloop, int *r_totpoly)
{
ListBase disp = {NULL, NULL};
@@ -1170,11 +1186,12 @@ int BKE_mesh_nurbs_to_mdata(Object *ob, MVert **allvert, int *totvert,
disp = ob->curve_cache->disp;
}
- return BKE_mesh_nurbs_displist_to_mdata(ob, &disp,
- allvert, totvert,
- alledge, totedge,
- allloop, allpoly, NULL,
- totloop, totpoly);
+ return BKE_mesh_nurbs_displist_to_mdata(
+ ob, &disp,
+ r_allvert, r_totvert,
+ r_alledge, r_totedge,
+ r_allloop, r_allpoly, NULL,
+ r_totloop, r_totpoly);
}
/* BMESH: this doesn't calculate all edges from polygons,
@@ -1182,12 +1199,13 @@ int BKE_mesh_nurbs_to_mdata(Object *ob, MVert **allvert, int *totvert,
/* Initialize mverts, medges and, faces for converting nurbs to mesh and derived mesh */
/* use specified dispbase */
-int BKE_mesh_nurbs_displist_to_mdata(Object *ob, ListBase *dispbase,
- MVert **allvert, int *_totvert,
- MEdge **alledge, int *_totedge,
- MLoop **allloop, MPoly **allpoly,
- MLoopUV **alluv,
- int *_totloop, int *_totpoly)
+int BKE_mesh_nurbs_displist_to_mdata(
+ Object *ob, const ListBase *dispbase,
+ MVert **r_allvert, int *r_totvert,
+ MEdge **r_alledge, int *r_totedge,
+ MLoop **r_allloop, MPoly **r_allpoly,
+ MLoopUV **r_alluv,
+ int *r_totloop, int *r_totpoly)
{
Curve *cu = ob->data;
DispList *dl;
@@ -1238,20 +1256,20 @@ int BKE_mesh_nurbs_displist_to_mdata(Object *ob, ListBase *dispbase,
return -1;
}
- *allvert = mvert = MEM_callocN(sizeof(MVert) * totvert, "nurbs_init mvert");
- *alledge = medge = MEM_callocN(sizeof(MEdge) * totedge, "nurbs_init medge");
- *allloop = mloop = MEM_callocN(sizeof(MLoop) * totvlak * 4, "nurbs_init mloop"); // totloop
- *allpoly = mpoly = MEM_callocN(sizeof(MPoly) * totvlak, "nurbs_init mloop");
+ *r_allvert = mvert = MEM_callocN(sizeof(MVert) * totvert, "nurbs_init mvert");
+ *r_alledge = medge = MEM_callocN(sizeof(MEdge) * totedge, "nurbs_init medge");
+ *r_allloop = mloop = MEM_callocN(sizeof(MLoop) * totvlak * 4, "nurbs_init mloop"); // totloop
+ *r_allpoly = mpoly = MEM_callocN(sizeof(MPoly) * totvlak, "nurbs_init mloop");
- if (alluv)
- *alluv = mloopuv = MEM_callocN(sizeof(MLoopUV) * totvlak * 4, "nurbs_init mloopuv");
+ if (r_alluv)
+ *r_alluv = mloopuv = MEM_callocN(sizeof(MLoopUV) * totvlak * 4, "nurbs_init mloopuv");
/* verts and faces */
vertcount = 0;
dl = dispbase->first;
while (dl) {
- int smooth = dl->rt & CU_SMOOTH ? 1 : 0;
+ const bool is_smooth = (dl->rt & CU_SMOOTH) != 0;
if (dl->type == DL_SEGM) {
startvert = vertcount;
@@ -1317,7 +1335,7 @@ int BKE_mesh_nurbs_displist_to_mdata(Object *ob, ListBase *dispbase,
mloop[0].v = startvert + index[0];
mloop[1].v = startvert + index[2];
mloop[2].v = startvert + index[1];
- mpoly->loopstart = (int)(mloop - (*allloop));
+ mpoly->loopstart = (int)(mloop - (*r_allloop));
mpoly->totloop = 3;
mpoly->mat_nr = dl->col;
@@ -1330,7 +1348,7 @@ int BKE_mesh_nurbs_displist_to_mdata(Object *ob, ListBase *dispbase,
}
}
- if (smooth) mpoly->flag |= ME_SMOOTH;
+ if (is_smooth) mpoly->flag |= ME_SMOOTH;
mpoly++;
mloop += 3;
index += 3;
@@ -1375,7 +1393,7 @@ int BKE_mesh_nurbs_displist_to_mdata(Object *ob, ListBase *dispbase,
mloop[1].v = p3;
mloop[2].v = p4;
mloop[3].v = p2;
- mpoly->loopstart = (int)(mloop - (*allloop));
+ mpoly->loopstart = (int)(mloop - (*r_allloop));
mpoly->totloop = 4;
mpoly->mat_nr = dl->col;
@@ -1409,7 +1427,7 @@ int BKE_mesh_nurbs_displist_to_mdata(Object *ob, ListBase *dispbase,
}
}
- if (smooth) mpoly->flag |= ME_SMOOTH;
+ if (is_smooth) mpoly->flag |= ME_SMOOTH;
mpoly++;
mloop += 4;
@@ -1425,14 +1443,14 @@ int BKE_mesh_nurbs_displist_to_mdata(Object *ob, ListBase *dispbase,
}
if (totvlak) {
- make_edges_mdata_extend(alledge, &totedge,
- *allpoly, *allloop, totvlak);
+ make_edges_mdata_extend(r_alledge, &totedge,
+ *r_allpoly, *r_allloop, totvlak);
}
- *_totpoly = totvlak;
- *_totloop = totloop;
- *_totedge = totedge;
- *_totvert = totvert;
+ *r_totpoly = totvlak;
+ *r_totloop = totloop;
+ *r_totedge = totedge;
+ *r_totvert = totvert;
return 0;
}
@@ -1487,7 +1505,7 @@ void BKE_mesh_from_nurbs_displist(Object *ob, ListBase *dispbase, const bool use
}
else {
me = BKE_mesh_add(G.main, "Mesh");
- DM_to_mesh(dm, me, ob, CD_MASK_MESH);
+ DM_to_mesh(dm, me, ob, CD_MASK_MESH, false);
}
me->totcol = cu->totcol;
@@ -1759,13 +1777,43 @@ void BKE_mesh_material_index_clear(Mesh *me)
}
}
+void BKE_mesh_material_remap(Mesh *me, const unsigned int *remap, unsigned int remap_len)
+{
+ const short remap_len_short = (short)remap_len;
+
+#define MAT_NR_REMAP(n) \
+ if (n < remap_len_short) { \
+ BLI_assert(n >= 0 && remap[n] < remap_len_short); \
+ n = remap[n]; \
+ } ((void)0)
+
+ if (me->edit_btmesh) {
+ BMEditMesh *em = me->edit_btmesh;
+ BMIter iter;
+ BMFace *efa;
+
+ BM_ITER_MESH(efa, &iter, em->bm, BM_FACES_OF_MESH) {
+ MAT_NR_REMAP(efa->mat_nr);
+ }
+ }
+ else {
+ int i;
+ for (i = 0; i < me->totpoly; i++) {
+ MAT_NR_REMAP(me->mpoly[i].mat_nr);
+ }
+ }
+
+#undef MAT_NR_REMAP
+
+}
+
void BKE_mesh_smooth_flag_set(Object *meshOb, int enableSmooth)
{
Mesh *me = meshOb->data;
int i;
for (i = 0; i < me->totpoly; i++) {
- MPoly *mp = &((MPoly *) me->mpoly)[i];
+ MPoly *mp = &me->mpoly[i];
if (enableSmooth) {
mp->flag |= ME_SMOOTH;
@@ -1776,7 +1824,7 @@ void BKE_mesh_smooth_flag_set(Object *meshOb, int enableSmooth)
}
for (i = 0; i < me->totface; i++) {
- MFace *mf = &((MFace *) me->mface)[i];
+ MFace *mf = &me->mface[i];
if (enableSmooth) {
mf->flag |= ME_SMOOTH;
@@ -1791,7 +1839,7 @@ void BKE_mesh_smooth_flag_set(Object *meshOb, int enableSmooth)
* Return a newly MEM_malloc'd array of all the mesh vertex locations
* \note \a r_numVerts may be NULL
*/
-float (*BKE_mesh_vertexCos_get(Mesh *me, int *r_numVerts))[3]
+float (*BKE_mesh_vertexCos_get(const Mesh *me, int *r_numVerts))[3]
{
int i, numVerts = me->totvert;
float (*cos)[3] = MEM_mallocN(sizeof(*cos) * numVerts, "vertexcos1");
@@ -1807,8 +1855,9 @@ float (*BKE_mesh_vertexCos_get(Mesh *me, int *r_numVerts))[3]
* Find the index of the loop in 'poly' which references vertex,
* returns -1 if not found
*/
-int poly_find_loop_from_vert(const MPoly *poly, const MLoop *loopstart,
- unsigned vert)
+int poly_find_loop_from_vert(
+ const MPoly *poly, const MLoop *loopstart,
+ unsigned vert)
{
int j;
for (j = 0; j < poly->totloop; j++, loopstart++) {
@@ -1824,20 +1873,23 @@ int poly_find_loop_from_vert(const MPoly *poly, const MLoop *loopstart,
* vertex. Returns the index of the loop matching vertex, or -1 if the
* vertex is not in \a poly
*/
-int poly_get_adj_loops_from_vert(unsigned r_adj[3], const MPoly *poly,
- const MLoop *mloop, unsigned vert)
+int poly_get_adj_loops_from_vert(
+ const MPoly *poly,
+ const MLoop *mloop, unsigned int vert,
+ unsigned int r_adj[2])
{
int corner = poly_find_loop_from_vert(poly,
&mloop[poly->loopstart],
vert);
if (corner != -1) {
+#if 0 /* unused - this loop */
const MLoop *ml = &mloop[poly->loopstart + corner];
+#endif
/* vertex was found */
r_adj[0] = ME_POLY_LOOP_PREV(mloop, poly, corner)->v;
- r_adj[1] = ml->v;
- r_adj[2] = ME_POLY_LOOP_NEXT(mloop, poly, corner)->v;
+ r_adj[1] = ME_POLY_LOOP_NEXT(mloop, poly, corner)->v;
}
return corner;
@@ -1858,7 +1910,7 @@ int BKE_mesh_edge_other_vert(const MEdge *e, int v)
}
/* basic vertex data functions */
-bool BKE_mesh_minmax(Mesh *me, float r_min[3], float r_max[3])
+bool BKE_mesh_minmax(const Mesh *me, float r_min[3], float r_max[3])
{
int i = me->totvert;
MVert *mvert;
@@ -1873,6 +1925,7 @@ void BKE_mesh_transform(Mesh *me, float mat[4][4], bool do_keys)
{
int i;
MVert *mvert = me->mvert;
+ float (*lnors)[3] = CustomData_get_layer(&me->ldata, CD_NORMAL);
for (i = 0; i < me->totvert; i++, mvert++)
mul_m4_v3(mat, mvert->co);
@@ -1887,7 +1940,17 @@ void BKE_mesh_transform(Mesh *me, float mat[4][4], bool do_keys)
}
}
- /* don't update normals, caller can do this explicitly */
+ /* don't update normals, caller can do this explicitly.
+ * We do update loop normals though, those may not be auto-generated (see e.g. STL import script)! */
+ if (lnors) {
+ float m3[3][3];
+
+ copy_m3_m4(m3, mat);
+ normalize_m3(m3);
+ for (i = 0; i < me->totloop; i++, lnors++) {
+ mul_m3_v3(m3, *lnors);
+ }
+ }
}
void BKE_mesh_translate(Mesh *me, const float offset[3], const bool do_keys)
@@ -2110,6 +2173,147 @@ void BKE_mesh_mselect_active_set(Mesh *me, int index, int type)
(me->mselect[me->totselect - 1].type == type));
}
+void BKE_mesh_calc_normals_split(Mesh *mesh)
+{
+ float (*r_loopnors)[3];
+ float (*polynors)[3];
+ short (*clnors)[2] = NULL;
+ bool free_polynors = false;
+
+ if (CustomData_has_layer(&mesh->ldata, CD_NORMAL)) {
+ r_loopnors = CustomData_get_layer(&mesh->ldata, CD_NORMAL);
+ memset(r_loopnors, 0, sizeof(float[3]) * mesh->totloop);
+ }
+ else {
+ r_loopnors = CustomData_add_layer(&mesh->ldata, CD_NORMAL, CD_CALLOC, NULL, mesh->totloop);
+ CustomData_set_layer_flag(&mesh->ldata, CD_NORMAL, CD_FLAG_TEMPORARY);
+ }
+
+ /* may be NULL */
+ clnors = CustomData_get_layer(&mesh->ldata, CD_CUSTOMLOOPNORMAL);
+
+ if (CustomData_has_layer(&mesh->pdata, CD_NORMAL)) {
+ /* This assume that layer is always up to date, not sure this is the case (esp. in Edit mode?)... */
+ polynors = CustomData_get_layer(&mesh->pdata, CD_NORMAL);
+ free_polynors = false;
+ }
+ else {
+ polynors = MEM_mallocN(sizeof(float[3]) * mesh->totpoly, __func__);
+ BKE_mesh_calc_normals_poly(mesh->mvert, mesh->totvert, mesh->mloop, mesh->mpoly, mesh->totloop, mesh->totpoly,
+ polynors, false);
+ free_polynors = true;
+ }
+
+ BKE_mesh_normals_loop_split(
+ mesh->mvert, mesh->totvert, mesh->medge, mesh->totedge,
+ mesh->mloop, r_loopnors, mesh->totloop, mesh->mpoly, (const float (*)[3])polynors, mesh->totpoly,
+ (mesh->flag & ME_AUTOSMOOTH) != 0, mesh->smoothresh, NULL, clnors, NULL);
+
+ if (free_polynors) {
+ MEM_freeN(polynors);
+ }
+}
+
+/* Spli faces based on the edge angle.
+ * Matches behavior of face splitting in render engines.
+ */
+void BKE_mesh_split_faces(Mesh *mesh)
+{
+ const int num_verts = mesh->totvert;
+ const int num_edges = mesh->totedge;
+ const int num_polys = mesh->totpoly;
+ MVert *mvert = mesh->mvert;
+ MEdge *medge = mesh->medge;
+ MLoop *mloop = mesh->mloop;
+ MPoly *mpoly = mesh->mpoly;
+ float (*lnors)[3];
+ int poly, num_new_verts = 0;
+ if ((mesh->flag & ME_AUTOSMOOTH) == 0) {
+ return;
+ }
+ BKE_mesh_tessface_clear(mesh);
+ /* Compute loop normals if needed. */
+ if (!CustomData_has_layer(&mesh->ldata, CD_NORMAL)) {
+ BKE_mesh_calc_normals_split(mesh);
+ }
+ lnors = CustomData_get_layer(&mesh->ldata, CD_NORMAL);
+ /* Count number of vertices to be split. */
+ for (poly = 0; poly < num_polys; poly++) {
+ MPoly *mp = &mpoly[poly];
+ int loop;
+ for (loop = 0; loop < mp->totloop; loop++) {
+ MLoop *ml = &mloop[mp->loopstart + loop];
+ MVert *mv = &mvert[ml->v];
+ float vn[3];
+ normal_short_to_float_v3(vn, mv->no);
+ if (!equals_v3v3(vn, lnors[mp->loopstart + loop])) {
+ num_new_verts++;
+ }
+ }
+ }
+ if (num_new_verts == 0) {
+ /* No new vertices are to be added, can do early exit. */
+ return;
+ }
+ /* Reallocate all vert and edge related data. */
+ mesh->totvert += num_new_verts;
+ mesh->totedge += 2 * num_new_verts;
+ CustomData_realloc(&mesh->vdata, mesh->totvert);
+ CustomData_realloc(&mesh->edata, mesh->totedge);
+ /* Update pointers to a newly allocated memory. */
+ BKE_mesh_update_customdata_pointers(mesh, false);
+ mvert = mesh->mvert;
+ medge = mesh->medge;
+ /* Perform actual vertex split. */
+ num_new_verts = 0;
+ for (poly = 0; poly < num_polys; poly++) {
+ MPoly *mp = &mpoly[poly];
+ int loop;
+ for (loop = 0; loop < mp->totloop; loop++) {
+ int poly_loop = mp->loopstart + loop;
+ MLoop *ml = &mloop[poly_loop];
+ MVert *mv = &mvert[ml->v];
+ float vn[3];
+ normal_short_to_float_v3(vn, mv->no);
+ if (!equals_v3v3(vn, lnors[mp->loopstart + loop])) {
+ int poly_loop_prev = mp->loopstart + (loop + mp->totloop - 1) % mp->totloop;
+ MLoop *ml_prev = &mloop[poly_loop_prev];
+ int new_edge_prev, new_edge;
+ /* Cretae new vertex. */
+ int new_vert = num_verts + num_new_verts;
+ CustomData_copy_data(&mesh->vdata, &mesh->vdata,
+ ml->v, new_vert, 1);
+ normal_float_to_short_v3(mvert[new_vert].no,
+ lnors[poly_loop]);
+ /* Create new edges. */
+ new_edge_prev = num_edges + 2 * num_new_verts;
+ new_edge = num_edges + 2 * num_new_verts + 1;
+ CustomData_copy_data(&mesh->edata, &mesh->edata,
+ ml_prev->e, new_edge_prev, 1);
+ CustomData_copy_data(&mesh->edata, &mesh->edata,
+ ml->e, new_edge, 1);
+ if (medge[new_edge_prev].v1 == ml->v) {
+ medge[new_edge_prev].v1 = new_vert;
+ }
+ else {
+ medge[new_edge_prev].v2 = new_vert;
+ }
+ if (medge[new_edge].v1 == ml->v) {
+ medge[new_edge].v1 = new_vert;
+ }
+ else {
+ medge[new_edge].v2 = new_vert;
+ }
+
+ ml->v = new_vert;
+ ml_prev->e = new_edge_prev;
+ ml->e = new_edge;
+ num_new_verts++;
+ }
+ }
+ }
+}
+
/* settings: 1 - preview, 2 - render */
Mesh *BKE_mesh_new_from_object(
Main *bmain, Scene *sce, Object *ob,
@@ -2136,6 +2340,19 @@ Mesh *BKE_mesh_new_from_object(
tmpcu = (Curve *)tmpobj->data;
tmpcu->id.us--;
+ /* Copy cached display list, it might be needed by the stack evaluation.
+ * Ideally stack should be able to use render-time display list, but doing
+ * so is quite tricky and not safe so close to the release.
+ *
+ * TODO(sergey): Look into more proper solution.
+ */
+ if (ob->curve_cache != NULL) {
+ if (tmpobj->curve_cache == NULL) {
+ tmpobj->curve_cache = MEM_callocN(sizeof(CurveCache), "CurveCache for curve types");
+ }
+ BKE_displist_copy(&tmpobj->curve_cache->disp, &ob->curve_cache->disp);
+ }
+
/* if getting the original caged mesh, delete object modifiers */
if (cage)
BKE_object_free_modifiers(tmpobj);
@@ -2199,8 +2416,8 @@ Mesh *BKE_mesh_new_from_object(
* only contains for_render flag. As soon as CoW is
* implemented, this is to be rethinked.
*/
- EvaluationContext eval_ctx = {0};
- eval_ctx.mode = DAG_EVAL_RENDER;
+ EvaluationContext eval_ctx;
+ DEG_evaluation_context_init(&eval_ctx, DAG_EVAL_RENDER);
BKE_displist_make_mball_forRender(&eval_ctx, sce, ob, &disp);
BKE_mesh_from_metaball(&disp, tmpmesh);
BKE_displist_free(&disp);
@@ -2242,8 +2459,7 @@ Mesh *BKE_mesh_new_from_object(
dm = mesh_create_derived_view(sce, ob, mask);
tmpmesh = BKE_mesh_add(bmain, "Mesh");
- DM_to_mesh(dm, tmpmesh, ob, mask);
- dm->release(dm);
+ DM_to_mesh(dm, tmpmesh, ob, mask, true);
}
/* BKE_mesh_add/copy gives us a user count we don't need */
@@ -2326,3 +2542,15 @@ Mesh *BKE_mesh_new_from_object(
return tmpmesh;
}
+/* **** Depsgraph evaluation **** */
+
+void BKE_mesh_eval_geometry(EvaluationContext *UNUSED(eval_ctx),
+ Mesh *mesh)
+{
+ if (G.debug & G_DEBUG_DEPSGRAPH) {
+ printf("%s on %s\n", __func__, mesh->id.name);
+ }
+ if (mesh->bb == NULL || (mesh->bb->flag & BOUNDBOX_DIRTY)) {
+ BKE_mesh_texspace_calc(mesh);
+ }
+}
diff --git a/source/blender/blenkernel/intern/mesh_evaluate.c b/source/blender/blenkernel/intern/mesh_evaluate.c
index 4c9e44682c3..2fc535061ac 100644
--- a/source/blender/blenkernel/intern/mesh_evaluate.c
+++ b/source/blender/blenkernel/intern/mesh_evaluate.c
@@ -39,6 +39,7 @@
#include "BLI_utildefines.h"
#include "BLI_memarena.h"
+#include "BLI_mempool.h"
#include "BLI_math.h"
#include "BLI_edgehash.h"
#include "BLI_bitmap.h"
@@ -46,8 +47,11 @@
#include "BLI_linklist.h"
#include "BLI_linklist_stack.h"
#include "BLI_alloca.h"
+#include "BLI_stack.h"
+#include "BLI_task.h"
#include "BKE_customdata.h"
+#include "BKE_global.h"
#include "BKE_mesh.h"
#include "BKE_multires.h"
#include "BKE_report.h"
@@ -58,8 +62,8 @@
// #define DEBUG_TIME
+#include "PIL_time.h"
#ifdef DEBUG_TIME
-# include "PIL_time.h"
# include "PIL_time_utildefines.h"
#endif
@@ -86,26 +90,28 @@ static void mesh_calc_normals_vert_fallback(MVert *mverts, int numVerts)
/* Calculate vertex and face normals, face normals are returned in *r_faceNors if non-NULL
* and vertex normals are stored in actual mverts.
*/
-void BKE_mesh_calc_normals_mapping(MVert *mverts, int numVerts,
- MLoop *mloop, MPoly *mpolys, int numLoops, int numPolys, float (*r_polyNors)[3],
- MFace *mfaces, int numFaces, const int *origIndexFace, float (*r_faceNors)[3])
+void BKE_mesh_calc_normals_mapping(
+ MVert *mverts, int numVerts,
+ const MLoop *mloop, const MPoly *mpolys, int numLoops, int numPolys, float (*r_polyNors)[3],
+ const MFace *mfaces, int numFaces, const int *origIndexFace, float (*r_faceNors)[3])
{
- BKE_mesh_calc_normals_mapping_ex(mverts, numVerts, mloop, mpolys,
- numLoops, numPolys, r_polyNors, mfaces, numFaces,
- origIndexFace, r_faceNors, false);
+ BKE_mesh_calc_normals_mapping_ex(
+ mverts, numVerts, mloop, mpolys,
+ numLoops, numPolys, r_polyNors, mfaces, numFaces,
+ origIndexFace, r_faceNors, false);
}
/* extended version of 'BKE_mesh_calc_normals_poly' with option not to calc vertex normals */
void BKE_mesh_calc_normals_mapping_ex(
MVert *mverts, int numVerts,
- MLoop *mloop, MPoly *mpolys,
+ const MLoop *mloop, const MPoly *mpolys,
int numLoops, int numPolys, float (*r_polyNors)[3],
- MFace *mfaces, int numFaces, const int *origIndexFace, float (*r_faceNors)[3],
+ const MFace *mfaces, int numFaces, const int *origIndexFace, float (*r_faceNors)[3],
const bool only_face_normals)
{
float (*pnors)[3] = r_polyNors, (*fnors)[3] = r_faceNors;
int i;
- MFace *mf;
- MPoly *mp;
+ const MFace *mf;
+ const MPoly *mp;
if (numPolys == 0) {
if (only_face_normals == false) {
@@ -161,8 +167,10 @@ void BKE_mesh_calc_normals_mapping_ex(
}
-static void mesh_calc_normals_poly_accum(MPoly *mp, MLoop *ml,
- MVert *mvert, float polyno[3], float (*tnorms)[3])
+static void mesh_calc_normals_poly_accum(
+ const MPoly *mp, const MLoop *ml,
+ const MVert *mvert,
+ float r_polyno[3], float (*r_tnorms)[3])
{
const int nverts = mp->totloop;
float (*edgevecbuf)[3] = BLI_array_alloca(edgevecbuf, (size_t)nverts);
@@ -175,11 +183,11 @@ static void mesh_calc_normals_poly_accum(MPoly *mp, MLoop *ml,
const float *v_prev = mvert[ml[i_prev].v].co;
const float *v_curr;
- zero_v3(polyno);
+ zero_v3(r_polyno);
/* Newell's Method */
for (i = 0; i < nverts; i++) {
v_curr = mvert[ml[i].v].co;
- add_newell_cross_v3_v3v3(polyno, v_prev, v_curr);
+ add_newell_cross_v3_v3v3(r_polyno, v_prev, v_curr);
/* Unrelated to normalize, calculate edge-vector */
sub_v3_v3v3(edgevecbuf[i_prev], v_prev, v_curr);
@@ -188,8 +196,8 @@ static void mesh_calc_normals_poly_accum(MPoly *mp, MLoop *ml,
v_prev = v_curr;
}
- if (UNLIKELY(normalize_v3(polyno) == 0.0f)) {
- polyno[2] = 1.0f; /* other axis set to 0.0 */
+ if (UNLIKELY(normalize_v3(r_polyno) == 0.0f)) {
+ r_polyno[2] = 1.0f; /* other axis set to 0.0 */
}
}
@@ -206,24 +214,26 @@ static void mesh_calc_normals_poly_accum(MPoly *mp, MLoop *ml,
const float fac = saacos(-dot_v3v3(cur_edge, prev_edge));
/* accumulate */
- madd_v3_v3fl(tnorms[ml[i].v], polyno, fac);
+ madd_v3_v3fl(r_tnorms[ml[i].v], r_polyno, fac);
prev_edge = cur_edge;
}
}
}
-void BKE_mesh_calc_normals_poly(MVert *mverts, int numVerts, MLoop *mloop, MPoly *mpolys,
- int UNUSED(numLoops), int numPolys, float (*r_polynors)[3],
- const bool only_face_normals)
+void BKE_mesh_calc_normals_poly(
+ MVert *mverts, int numVerts,
+ const MLoop *mloop, const MPoly *mpolys,
+ int UNUSED(numLoops), int numPolys, float (*r_polynors)[3],
+ const bool only_face_normals)
{
float (*pnors)[3] = r_polynors;
float (*tnorms)[3];
int i;
- MPoly *mp;
+ const MPoly *mp;
if (only_face_normals) {
- BLI_assert(pnors != NULL);
+ BLI_assert((pnors != NULL) || (numPolys == 0));
#pragma omp parallel for if (numPolys > BKE_MESH_OMP_LIMIT)
for (i = 0; i < numPolys; i++) {
@@ -249,12 +259,12 @@ void BKE_mesh_calc_normals_poly(MVert *mverts, int numVerts, MLoop *mloop, MPoly
}
}
- /* following Mesh convention; we use vertex coordinate itself for normal in this case */
for (i = 0; i < numVerts; i++) {
MVert *mv = &mverts[i];
float *no = tnorms[i];
if (UNLIKELY(normalize_v3(no) == 0.0f)) {
+ /* following Mesh convention; we use vertex coordinate itself for normal in this case */
normalize_v3_v3(no, mv->co);
}
@@ -277,14 +287,17 @@ void BKE_mesh_calc_normals(Mesh *mesh)
#endif
}
-void BKE_mesh_calc_normals_tessface(MVert *mverts, int numVerts, MFace *mfaces, int numFaces, float (*r_faceNors)[3])
+void BKE_mesh_calc_normals_tessface(
+ MVert *mverts, int numVerts,
+ const MFace *mfaces, int numFaces,
+ float (*r_faceNors)[3])
{
float (*tnorms)[3] = MEM_callocN(sizeof(*tnorms) * (size_t)numVerts, "tnorms");
float (*fnors)[3] = (r_faceNors) ? r_faceNors : MEM_callocN(sizeof(*fnors) * (size_t)numFaces, "meshnormals");
int i;
for (i = 0; i < numFaces; i++) {
- MFace *mf = &mfaces[i];
+ const MFace *mf = &mfaces[i];
float *f_no = fnors[i];
float *n4 = (mf->v4) ? tnorms[mf->v4] : NULL;
const float *c4 = (mf->v4) ? mverts[mf->v4].co : NULL;
@@ -316,19 +329,837 @@ void BKE_mesh_calc_normals_tessface(MVert *mverts, int numVerts, MFace *mfaces,
MEM_freeN(fnors);
}
-/**
- * Compute split normals, i.e. vertex normals associated with each poly (hence 'loop normals').
- * Useful to materialize sharp edges (or non-smooth faces) without actually modifying the geometry (splitting edges).
+void BKE_mesh_calc_normals_looptri(
+ MVert *mverts, int numVerts,
+ const MLoop *mloop,
+ const MLoopTri *looptri, int looptri_num,
+ float (*r_tri_nors)[3])
+{
+ float (*tnorms)[3] = MEM_callocN(sizeof(*tnorms) * (size_t)numVerts, "tnorms");
+ float (*fnors)[3] = (r_tri_nors) ? r_tri_nors : MEM_callocN(sizeof(*fnors) * (size_t)looptri_num, "meshnormals");
+ int i;
+
+ for (i = 0; i < looptri_num; i++) {
+ const MLoopTri *lt = &looptri[i];
+ float *f_no = fnors[i];
+ const unsigned int vtri[3] = {
+ mloop[lt->tri[0]].v,
+ mloop[lt->tri[1]].v,
+ mloop[lt->tri[2]].v,
+ };
+
+ normal_tri_v3(
+ f_no,
+ mverts[vtri[0]].co, mverts[vtri[1]].co, mverts[vtri[2]].co);
+
+ accumulate_vertex_normals_tri(
+ tnorms[vtri[0]], tnorms[vtri[1]], tnorms[vtri[2]],
+ f_no, mverts[vtri[0]].co, mverts[vtri[1]].co, mverts[vtri[2]].co);
+ }
+
+ /* following Mesh convention; we use vertex coordinate itself for normal in this case */
+ for (i = 0; i < numVerts; i++) {
+ MVert *mv = &mverts[i];
+ float *no = tnorms[i];
+
+ if (UNLIKELY(normalize_v3(no) == 0.0f)) {
+ normalize_v3_v3(no, mv->co);
+ }
+
+ normal_float_to_short_v3(mv->no, no);
+ }
+
+ MEM_freeN(tnorms);
+
+ if (fnors != r_tri_nors)
+ MEM_freeN(fnors);
+}
+
+void BKE_lnor_spacearr_init(MLoopNorSpaceArray *lnors_spacearr, const int numLoops)
+{
+ if (!(lnors_spacearr->lspacearr && lnors_spacearr->loops_pool)) {
+ MemArena *mem;
+
+ if (!lnors_spacearr->mem) {
+ lnors_spacearr->mem = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__);
+ }
+ mem = lnors_spacearr->mem;
+ lnors_spacearr->lspacearr = BLI_memarena_calloc(mem, sizeof(MLoopNorSpace *) * (size_t)numLoops);
+ lnors_spacearr->loops_pool = BLI_memarena_alloc(mem, sizeof(LinkNode) * (size_t)numLoops);
+ }
+}
+
+void BKE_lnor_spacearr_clear(MLoopNorSpaceArray *lnors_spacearr)
+{
+ BLI_memarena_clear(lnors_spacearr->mem);
+ lnors_spacearr->lspacearr = NULL;
+ lnors_spacearr->loops_pool = NULL;
+}
+
+void BKE_lnor_spacearr_free(MLoopNorSpaceArray *lnors_spacearr)
+{
+ BLI_memarena_free(lnors_spacearr->mem);
+ lnors_spacearr->lspacearr = NULL;
+ lnors_spacearr->loops_pool = NULL;
+ lnors_spacearr->mem = NULL;
+}
+
+MLoopNorSpace *BKE_lnor_space_create(MLoopNorSpaceArray *lnors_spacearr)
+{
+ return BLI_memarena_calloc(lnors_spacearr->mem, sizeof(MLoopNorSpace));
+}
+
+/* This threshold is a bit touchy (usual float precision issue), this value seems OK. */
+#define LNOR_SPACE_TRIGO_THRESHOLD (1.0f - 1e-6f)
+
+/* Should only be called once.
+ * Beware, this modifies ref_vec and other_vec in place!
+ * In case no valid space can be generated, ref_alpha and ref_beta are set to zero (which means 'use auto lnors').
*/
-void BKE_mesh_normals_loop_split(MVert *mverts, const int UNUSED(numVerts), MEdge *medges, const int numEdges,
- MLoop *mloops, float (*r_loopnors)[3], const int numLoops,
- MPoly *mpolys, float (*polynors)[3], const int numPolys, float split_angle)
+void BKE_lnor_space_define(MLoopNorSpace *lnor_space, const float lnor[3],
+ float vec_ref[3], float vec_other[3], BLI_Stack *edge_vectors)
+{
+ const float pi2 = (float)M_PI * 2.0f;
+ float tvec[3], dtp;
+ const float dtp_ref = dot_v3v3(vec_ref, lnor);
+ const float dtp_other = dot_v3v3(vec_other, lnor);
+
+ if (UNLIKELY(fabsf(dtp_ref) >= LNOR_SPACE_TRIGO_THRESHOLD || fabsf(dtp_other) >= LNOR_SPACE_TRIGO_THRESHOLD)) {
+ /* If vec_ref or vec_other are too much aligned with lnor, we can't build lnor space,
+ * tag it as invalid and abort. */
+ lnor_space->ref_alpha = lnor_space->ref_beta = 0.0f;
+
+ if (edge_vectors) {
+ BLI_stack_clear(edge_vectors);
+ }
+ return;
+ }
+
+ copy_v3_v3(lnor_space->vec_lnor, lnor);
+
+ /* Compute ref alpha, average angle of all available edge vectors to lnor. */
+ if (edge_vectors) {
+ float alpha = 0.0f;
+ int nbr = 0;
+ while (!BLI_stack_is_empty(edge_vectors)) {
+ const float *vec = BLI_stack_peek(edge_vectors);
+ alpha += saacosf(dot_v3v3(vec, lnor));
+ BLI_stack_discard(edge_vectors);
+ nbr++;
+ }
+ /* Note: In theory, this could be 'nbr > 2', but there is one case where we only have two edges for
+ * two loops: a smooth vertex with only two edges and two faces (our Monkey's nose has that, e.g.). */
+ BLI_assert(nbr >= 2); /* This piece of code shall only be called for more than one loop... */
+ lnor_space->ref_alpha = alpha / (float)nbr;
+ }
+ else {
+ lnor_space->ref_alpha = (saacosf(dot_v3v3(vec_ref, lnor)) + saacosf(dot_v3v3(vec_other, lnor))) / 2.0f;
+ }
+
+ /* Project vec_ref on lnor's ortho plane. */
+ mul_v3_v3fl(tvec, lnor, dtp_ref);
+ sub_v3_v3(vec_ref, tvec);
+ normalize_v3_v3(lnor_space->vec_ref, vec_ref);
+
+ cross_v3_v3v3(tvec, lnor, lnor_space->vec_ref);
+ normalize_v3_v3(lnor_space->vec_ortho, tvec);
+
+ /* Project vec_other on lnor's ortho plane. */
+ mul_v3_v3fl(tvec, lnor, dtp_other);
+ sub_v3_v3(vec_other, tvec);
+ normalize_v3(vec_other);
+
+ /* Beta is angle between ref_vec and other_vec, around lnor. */
+ dtp = dot_v3v3(lnor_space->vec_ref, vec_other);
+ if (LIKELY(dtp < LNOR_SPACE_TRIGO_THRESHOLD)) {
+ const float beta = saacos(dtp);
+ lnor_space->ref_beta = (dot_v3v3(lnor_space->vec_ortho, vec_other) < 0.0f) ? pi2 - beta : beta;
+ }
+ else {
+ lnor_space->ref_beta = pi2;
+ }
+}
+
+void BKE_lnor_space_add_loop(MLoopNorSpaceArray *lnors_spacearr, MLoopNorSpace *lnor_space, const int ml_index,
+ const bool do_add_loop)
{
+ lnors_spacearr->lspacearr[ml_index] = lnor_space;
+ if (do_add_loop) {
+ BLI_linklist_prepend_nlink(&lnor_space->loops, SET_INT_IN_POINTER(ml_index), &lnors_spacearr->loops_pool[ml_index]);
+ }
+}
+
+MINLINE float unit_short_to_float(const short val)
+{
+ return (float)val / (float)SHRT_MAX;
+}
+
+MINLINE short unit_float_to_short(const float val)
+{
+ /* Rounding... */
+ return (short)floorf(val * (float)SHRT_MAX + 0.5f);
+}
+
+void BKE_lnor_space_custom_data_to_normal(MLoopNorSpace *lnor_space, const short clnor_data[2], float r_custom_lnor[3])
+{
+ /* NOP custom normal data or invalid lnor space, return. */
+ if (clnor_data[0] == 0 || lnor_space->ref_alpha == 0.0f || lnor_space->ref_beta == 0.0f) {
+ copy_v3_v3(r_custom_lnor, lnor_space->vec_lnor);
+ return;
+ }
+
+ {
+ /* TODO Check whether using sincosf() gives any noticeable benefit
+ * (could not even get it working under linux though)! */
+ const float pi2 = (float)(M_PI * 2.0);
+ const float alphafac = unit_short_to_float(clnor_data[0]);
+ const float alpha = (alphafac > 0.0f ? lnor_space->ref_alpha : pi2 - lnor_space->ref_alpha) * alphafac;
+ const float betafac = unit_short_to_float(clnor_data[1]);
+
+ mul_v3_v3fl(r_custom_lnor, lnor_space->vec_lnor, cosf(alpha));
+
+ if (betafac == 0.0f) {
+ madd_v3_v3fl(r_custom_lnor, lnor_space->vec_ref, sinf(alpha));
+ }
+ else {
+ const float sinalpha = sinf(alpha);
+ const float beta = (betafac > 0.0f ? lnor_space->ref_beta : pi2 - lnor_space->ref_beta) * betafac;
+ madd_v3_v3fl(r_custom_lnor, lnor_space->vec_ref, sinalpha * cosf(beta));
+ madd_v3_v3fl(r_custom_lnor, lnor_space->vec_ortho, sinalpha * sinf(beta));
+ }
+ }
+}
+
+void BKE_lnor_space_custom_normal_to_data(MLoopNorSpace *lnor_space, const float custom_lnor[3], short r_clnor_data[2])
+{
+ /* We use null vector as NOP custom normal (can be simpler than giving autocomputed lnor...). */
+ if (is_zero_v3(custom_lnor) || compare_v3v3(lnor_space->vec_lnor, custom_lnor, 1e-4f)) {
+ r_clnor_data[0] = r_clnor_data[1] = 0;
+ return;
+ }
+
+ {
+ const float pi2 = (float)(M_PI * 2.0);
+ const float cos_alpha = dot_v3v3(lnor_space->vec_lnor, custom_lnor);
+ float vec[3], cos_beta;
+ float alpha;
+
+ alpha = saacosf(cos_alpha);
+ if (alpha > lnor_space->ref_alpha) {
+ /* Note we could stick to [0, pi] range here, but makes decoding more complex, not worth it. */
+ r_clnor_data[0] = unit_float_to_short(-(pi2 - alpha) / (pi2 - lnor_space->ref_alpha));
+ }
+ else {
+ r_clnor_data[0] = unit_float_to_short(alpha / lnor_space->ref_alpha);
+ }
+
+ /* Project custom lnor on (vec_ref, vec_ortho) plane. */
+ mul_v3_v3fl(vec, lnor_space->vec_lnor, -cos_alpha);
+ add_v3_v3(vec, custom_lnor);
+ normalize_v3(vec);
+
+ cos_beta = dot_v3v3(lnor_space->vec_ref, vec);
+
+ if (cos_beta < LNOR_SPACE_TRIGO_THRESHOLD) {
+ float beta = saacosf(cos_beta);
+ if (dot_v3v3(lnor_space->vec_ortho, vec) < 0.0f) {
+ beta = pi2 - beta;
+ }
+
+ if (beta > lnor_space->ref_beta) {
+ r_clnor_data[1] = unit_float_to_short(-(pi2 - beta) / (pi2 - lnor_space->ref_beta));
+ }
+ else {
+ r_clnor_data[1] = unit_float_to_short(beta / lnor_space->ref_beta);
+ }
+ }
+ else {
+ r_clnor_data[1] = 0;
+ }
+ }
+}
+
+#define LOOP_SPLIT_TASK_BLOCK_SIZE 1024
+
+typedef struct LoopSplitTaskData {
+ /* Specific to each instance (each task). */
+ MLoopNorSpace *lnor_space; /* We have to create those outside of tasks, since afaik memarena is not threadsafe. */
+ float (*lnor)[3];
+ const MLoop *ml_curr;
+ const MLoop *ml_prev;
+ int ml_curr_index;
+ int ml_prev_index;
+ const int *e2l_prev; /* Also used a flag to switch between single or fan process! */
+ int mp_index;
+
+ /* This one is special, it's owned and managed by worker tasks, avoid to have to create it for each fan! */
+ BLI_Stack *edge_vectors;
+
+ char pad_c;
+} LoopSplitTaskData;
+
+typedef struct LoopSplitTaskDataCommon {
+ /* Read/write.
+ * Note we do not need to protect it, though, since two different tasks will *always* affect different
+ * elements in the arrays. */
+ MLoopNorSpaceArray *lnors_spacearr;
+ BLI_bitmap *sharp_verts;
+ float (*loopnors)[3];
+ short (*clnors_data)[2];
+
+ /* Read-only. */
+ const MVert *mverts;
+ const MEdge *medges;
+ const MLoop *mloops;
+ const MPoly *mpolys;
+ const int (*edge_to_loops)[2];
+ const int *loop_to_poly;
+ const float (*polynors)[3];
+
+ int numPolys;
+
+ /* ***** Workers communication. ***** */
+ ThreadQueue *task_queue;
+
+} LoopSplitTaskDataCommon;
+
#define INDEX_UNSET INT_MIN
#define INDEX_INVALID -1
/* See comment about edge_to_loops below. */
#define IS_EDGE_SHARP(_e2l) (ELEM((_e2l)[1], INDEX_UNSET, INDEX_INVALID))
+static void split_loop_nor_single_do(LoopSplitTaskDataCommon *common_data, LoopSplitTaskData *data)
+{
+ MLoopNorSpaceArray *lnors_spacearr = common_data->lnors_spacearr;
+ short (*clnors_data)[2] = common_data->clnors_data;
+
+ const MVert *mverts = common_data->mverts;
+ const MEdge *medges = common_data->medges;
+ const float (*polynors)[3] = common_data->polynors;
+
+ MLoopNorSpace *lnor_space = data->lnor_space;
+ float (*lnor)[3] = data->lnor;
+ const MLoop *ml_curr = data->ml_curr;
+ const MLoop *ml_prev = data->ml_prev;
+ const int ml_curr_index = data->ml_curr_index;
+#if 0 /* Not needed for 'single' loop. */
+ const int ml_prev_index = data->ml_prev_index;
+ const int *e2l_prev = data->e2l_prev;
+#endif
+ const int mp_index = data->mp_index;
+
+ /* Simple case (both edges around that vertex are sharp in current polygon),
+ * this loop just takes its poly normal.
+ */
+ copy_v3_v3(*lnor, polynors[mp_index]);
+
+ /* printf("BASIC: handling loop %d / edge %d / vert %d\n", ml_curr_index, ml_curr->e, ml_curr->v); */
+
+ /* If needed, generate this (simple!) lnor space. */
+ if (lnors_spacearr) {
+ float vec_curr[3], vec_prev[3];
+
+ const unsigned int mv_pivot_index = ml_curr->v; /* The vertex we are "fanning" around! */
+ const MVert *mv_pivot = &mverts[mv_pivot_index];
+ const MEdge *me_curr = &medges[ml_curr->e];
+ const MVert *mv_2 = (me_curr->v1 == mv_pivot_index) ? &mverts[me_curr->v2] : &mverts[me_curr->v1];
+ const MEdge *me_prev = &medges[ml_prev->e];
+ const MVert *mv_3 = (me_prev->v1 == mv_pivot_index) ? &mverts[me_prev->v2] : &mverts[me_prev->v1];
+
+ sub_v3_v3v3(vec_curr, mv_2->co, mv_pivot->co);
+ normalize_v3(vec_curr);
+ sub_v3_v3v3(vec_prev, mv_3->co, mv_pivot->co);
+ normalize_v3(vec_prev);
+
+ BKE_lnor_space_define(lnor_space, *lnor, vec_curr, vec_prev, NULL);
+ /* We know there is only one loop in this space, no need to create a linklist in this case... */
+ BKE_lnor_space_add_loop(lnors_spacearr, lnor_space, ml_curr_index, false);
+
+ if (clnors_data) {
+ BKE_lnor_space_custom_data_to_normal(lnor_space, clnors_data[ml_curr_index], *lnor);
+ }
+ }
+}
+
+static void split_loop_nor_fan_do(LoopSplitTaskDataCommon *common_data, LoopSplitTaskData *data)
+{
+ MLoopNorSpaceArray *lnors_spacearr = common_data->lnors_spacearr;
+ float (*loopnors)[3] = common_data->loopnors;
+ short (*clnors_data)[2] = common_data->clnors_data;
+
+ const MVert *mverts = common_data->mverts;
+ const MEdge *medges = common_data->medges;
+ const MLoop *mloops = common_data->mloops;
+ const MPoly *mpolys = common_data->mpolys;
+ const int (*edge_to_loops)[2] = common_data->edge_to_loops;
+ const int *loop_to_poly = common_data->loop_to_poly;
+ const float (*polynors)[3] = common_data->polynors;
+
+ MLoopNorSpace *lnor_space = data->lnor_space;
+#if 0 /* Not needed for 'fan' loops. */
+ float (*lnor)[3] = data->lnor;
+#endif
+ const MLoop *ml_curr = data->ml_curr;
+ const MLoop *ml_prev = data->ml_prev;
+ const int ml_curr_index = data->ml_curr_index;
+ const int ml_prev_index = data->ml_prev_index;
+ const int mp_index = data->mp_index;
+ const int *e2l_prev = data->e2l_prev;
+
+ BLI_Stack *edge_vectors = data->edge_vectors;
+
+ /* Gah... We have to fan around current vertex, until we find the other non-smooth edge,
+ * and accumulate face normals into the vertex!
+ * Note in case this vertex has only one sharp edges, this is a waste because the normal is the same as
+ * the vertex normal, but I do not see any easy way to detect that (would need to count number
+ * of sharp edges per vertex, I doubt the additional memory usage would be worth it, especially as
+ * it should not be a common case in real-life meshes anyway).
+ */
+ const unsigned int mv_pivot_index = ml_curr->v; /* The vertex we are "fanning" around! */
+ const MVert *mv_pivot = &mverts[mv_pivot_index];
+ const MEdge *me_org = &medges[ml_curr->e]; /* ml_curr would be mlfan_prev if we needed that one */
+ const int *e2lfan_curr;
+ float vec_curr[3], vec_prev[3], vec_org[3];
+ const MLoop *mlfan_curr, *mlfan_next;
+ const MPoly *mpfan_next;
+ float lnor[3] = {0.0f, 0.0f, 0.0f};
+ /* mlfan_vert_index: the loop of our current edge might not be the loop of our current vertex! */
+ int mlfan_curr_index, mlfan_vert_index, mpfan_curr_index;
+
+ /* We validate clnors data on the fly - cheapest way to do! */
+ int clnors_avg[2] = {0, 0};
+ short (*clnor_ref)[2] = NULL;
+ int clnors_nbr = 0;
+ bool clnors_invalid = false;
+
+ /* Temp loop normal stack. */
+ BLI_SMALLSTACK_DECLARE(normal, float *);
+ /* Temp clnors stack. */
+ BLI_SMALLSTACK_DECLARE(clnors, short *);
+
+ e2lfan_curr = e2l_prev;
+ mlfan_curr = ml_prev;
+ mlfan_curr_index = ml_prev_index;
+ mlfan_vert_index = ml_curr_index;
+ mpfan_curr_index = mp_index;
+
+ BLI_assert(mlfan_curr_index >= 0);
+ BLI_assert(mlfan_vert_index >= 0);
+ BLI_assert(mpfan_curr_index >= 0);
+
+ /* Only need to compute previous edge's vector once, then we can just reuse old current one! */
+ {
+ const MVert *mv_2 = (me_org->v1 == mv_pivot_index) ? &mverts[me_org->v2] : &mverts[me_org->v1];
+
+ sub_v3_v3v3(vec_org, mv_2->co, mv_pivot->co);
+ normalize_v3(vec_org);
+ copy_v3_v3(vec_prev, vec_org);
+
+ if (lnors_spacearr) {
+ BLI_stack_push(edge_vectors, vec_org);
+ }
+ }
+
+ /* printf("FAN: vert %d, start edge %d\n", mv_pivot_index, ml_curr->e); */
+
+ while (true) {
+ const MEdge *me_curr = &medges[mlfan_curr->e];
+ /* Compute edge vectors.
+ * NOTE: We could pre-compute those into an array, in the first iteration, instead of computing them
+ * twice (or more) here. However, time gained is not worth memory and time lost,
+ * given the fact that this code should not be called that much in real-life meshes...
+ */
+ {
+ const MVert *mv_2 = (me_curr->v1 == mv_pivot_index) ? &mverts[me_curr->v2] : &mverts[me_curr->v1];
+
+ sub_v3_v3v3(vec_curr, mv_2->co, mv_pivot->co);
+ normalize_v3(vec_curr);
+ }
+
+ /* printf("\thandling edge %d / loop %d\n", mlfan_curr->e, mlfan_curr_index); */
+
+ {
+ /* Code similar to accumulate_vertex_normals_poly. */
+ /* Calculate angle between the two poly edges incident on this vertex. */
+ const float fac = saacos(dot_v3v3(vec_curr, vec_prev));
+ /* Accumulate */
+ madd_v3_v3fl(lnor, polynors[mpfan_curr_index], fac);
+
+ if (clnors_data) {
+ /* Accumulate all clnors, if they are not all equal we have to fix that! */
+ short (*clnor)[2] = &clnors_data[mlfan_vert_index];
+ if (clnors_nbr) {
+ clnors_invalid |= ((*clnor_ref)[0] != (*clnor)[0] || (*clnor_ref)[1] != (*clnor)[1]);
+ }
+ else {
+ clnor_ref = clnor;
+ }
+ clnors_avg[0] += (*clnor)[0];
+ clnors_avg[1] += (*clnor)[1];
+ clnors_nbr++;
+ /* We store here a pointer to all custom lnors processed. */
+ BLI_SMALLSTACK_PUSH(clnors, (short *)*clnor);
+ }
+ }
+
+ /* We store here a pointer to all loop-normals processed. */
+ BLI_SMALLSTACK_PUSH(normal, (float *)(loopnors[mlfan_vert_index]));
+
+ if (lnors_spacearr) {
+ /* Assign current lnor space to current 'vertex' loop. */
+ BKE_lnor_space_add_loop(lnors_spacearr, lnor_space, mlfan_vert_index, true);
+ if (me_curr != me_org) {
+ /* We store here all edges-normalized vectors processed. */
+ BLI_stack_push(edge_vectors, vec_curr);
+ }
+ }
+
+ if (IS_EDGE_SHARP(e2lfan_curr) || (me_curr == me_org)) {
+ /* Current edge is sharp and we have finished with this fan of faces around this vert,
+ * or this vert is smooth, and we have completed a full turn around it.
+ */
+ /* printf("FAN: Finished!\n"); */
+ break;
+ }
+
+ copy_v3_v3(vec_prev, vec_curr);
+
+ /* Warning! This is rather complex!
+ * We have to find our next edge around the vertex (fan mode).
+ * First we find the next loop, which is either previous or next to mlfan_curr_index, depending
+ * whether both loops using current edge are in the same direction or not, and whether
+ * mlfan_curr_index actually uses the vertex we are fanning around!
+ * mlfan_curr_index is the index of mlfan_next here, and mlfan_next is not the real next one
+ * (i.e. not the future mlfan_curr)...
+ */
+ mlfan_curr_index = (e2lfan_curr[0] == mlfan_curr_index) ? e2lfan_curr[1] : e2lfan_curr[0];
+ mpfan_curr_index = loop_to_poly[mlfan_curr_index];
+
+ BLI_assert(mlfan_curr_index >= 0);
+ BLI_assert(mpfan_curr_index >= 0);
+
+ mlfan_next = &mloops[mlfan_curr_index];
+ mpfan_next = &mpolys[mpfan_curr_index];
+ if ((mlfan_curr->v == mlfan_next->v && mlfan_curr->v == mv_pivot_index) ||
+ (mlfan_curr->v != mlfan_next->v && mlfan_curr->v != mv_pivot_index))
+ {
+ /* We need the previous loop, but current one is our vertex's loop. */
+ mlfan_vert_index = mlfan_curr_index;
+ if (--mlfan_curr_index < mpfan_next->loopstart) {
+ mlfan_curr_index = mpfan_next->loopstart + mpfan_next->totloop - 1;
+ }
+ }
+ else {
+ /* We need the next loop, which is also our vertex's loop. */
+ if (++mlfan_curr_index >= mpfan_next->loopstart + mpfan_next->totloop) {
+ mlfan_curr_index = mpfan_next->loopstart;
+ }
+ mlfan_vert_index = mlfan_curr_index;
+ }
+ mlfan_curr = &mloops[mlfan_curr_index];
+ /* And now we are back in sync, mlfan_curr_index is the index of mlfan_curr! Pff! */
+
+ e2lfan_curr = edge_to_loops[mlfan_curr->e];
+ }
+
+ {
+ float lnor_len = normalize_v3(lnor);
+
+ /* If we are generating lnor spacearr, we can now define the one for this fan,
+ * and optionally compute final lnor from custom data too!
+ */
+ if (lnors_spacearr) {
+ if (UNLIKELY(lnor_len == 0.0f)) {
+ /* Use vertex normal as fallback! */
+ copy_v3_v3(lnor, loopnors[mlfan_vert_index]);
+ lnor_len = 1.0f;
+ }
+
+ BKE_lnor_space_define(lnor_space, lnor, vec_org, vec_curr, edge_vectors);
+
+ if (clnors_data) {
+ if (clnors_invalid) {
+ short *clnor;
+
+ clnors_avg[0] /= clnors_nbr;
+ clnors_avg[1] /= clnors_nbr;
+ /* Fix/update all clnors of this fan with computed average value. */
+ if (G.debug & G_DEBUG) {
+ printf("Invalid clnors in this fan!\n");
+ }
+ while ((clnor = BLI_SMALLSTACK_POP(clnors))) {
+ //print_v2("org clnor", clnor);
+ clnor[0] = (short)clnors_avg[0];
+ clnor[1] = (short)clnors_avg[1];
+ }
+ //print_v2("new clnors", clnors_avg);
+ }
+ /* Extra bonus: since smallstack is local to this func, no more need to empty it at all cost! */
+
+ BKE_lnor_space_custom_data_to_normal(lnor_space, *clnor_ref, lnor);
+ }
+ }
+
+ /* In case we get a zero normal here, just use vertex normal already set! */
+ if (LIKELY(lnor_len != 0.0f)) {
+ /* Copy back the final computed normal into all related loop-normals. */
+ float *nor;
+
+ while ((nor = BLI_SMALLSTACK_POP(normal))) {
+ copy_v3_v3(nor, lnor);
+ }
+ }
+ /* Extra bonus: since smallstack is local to this func, no more need to empty it at all cost! */
+ }
+}
+
+static void loop_split_worker_do(
+ LoopSplitTaskDataCommon *common_data, LoopSplitTaskData *data, BLI_Stack *edge_vectors)
+{
+ BLI_assert(data->ml_curr);
+ if (data->e2l_prev) {
+ BLI_assert((edge_vectors == NULL) || BLI_stack_is_empty(edge_vectors));
+ data->edge_vectors = edge_vectors;
+ split_loop_nor_fan_do(common_data, data);
+ }
+ else {
+ /* No need for edge_vectors for 'single' case! */
+ split_loop_nor_single_do(common_data, data);
+ }
+}
+
+static void loop_split_worker(TaskPool *UNUSED(pool), void *taskdata, int UNUSED(threadid))
+{
+ LoopSplitTaskDataCommon *common_data = taskdata;
+ LoopSplitTaskData *data_buff;
+
+ /* Temp edge vectors stack, only used when computing lnor spacearr. */
+ BLI_Stack *edge_vectors = common_data->lnors_spacearr ? BLI_stack_new(sizeof(float[3]), __func__) : NULL;
+
+#ifdef DEBUG_TIME
+ TIMEIT_START(loop_split_worker);
+#endif
+
+ while ((data_buff = BLI_thread_queue_pop(common_data->task_queue))) {
+ LoopSplitTaskData *data = data_buff;
+ int i;
+
+ for (i = 0; i < LOOP_SPLIT_TASK_BLOCK_SIZE; i++, data++) {
+ /* A NULL ml_curr is used to tag ended data! */
+ if (data->ml_curr == NULL) {
+ break;
+ }
+ loop_split_worker_do(common_data, data, edge_vectors);
+ }
+
+ MEM_freeN(data_buff);
+ }
+
+ if (edge_vectors) {
+ BLI_stack_free(edge_vectors);
+ }
+
+#ifdef DEBUG_TIME
+ TIMEIT_END(loop_split_worker);
+#endif
+}
+
+/* Note we use data_buff to detect whether we are in threaded context or not, in later case it is NULL. */
+static void loop_split_generator_do(LoopSplitTaskDataCommon *common_data, const bool threaded)
+{
+ MLoopNorSpaceArray *lnors_spacearr = common_data->lnors_spacearr;
+ BLI_bitmap *sharp_verts = common_data->sharp_verts;
+ float (*loopnors)[3] = common_data->loopnors;
+
+ const MLoop *mloops = common_data->mloops;
+ const MPoly *mpolys = common_data->mpolys;
+ const int (*edge_to_loops)[2] = common_data->edge_to_loops;
+ const int numPolys = common_data->numPolys;
+
+ const MPoly *mp;
+ int mp_index;
+
+ LoopSplitTaskData *data, *data_buff = NULL, data_mem;
+ int data_idx = 0;
+
+ /* Temp edge vectors stack, only used when computing lnor spacearr (and we are not multi-threading). */
+ BLI_Stack *edge_vectors = (lnors_spacearr && !data_buff) ? BLI_stack_new(sizeof(float[3]), __func__) : NULL;
+
+#ifdef DEBUG_TIME
+ TIMEIT_START(loop_split_generator);
+#endif
+
+ if (!threaded) {
+ memset(&data_mem, 0, sizeof(data_mem));
+ data = &data_mem;
+ }
+
+ /* We now know edges that can be smoothed (with their vector, and their two loops), and edges that will be hard!
+ * Now, time to generate the normals.
+ */
+ for (mp = mpolys, mp_index = 0; mp_index < numPolys; mp++, mp_index++) {
+ const MLoop *ml_curr, *ml_prev;
+ float (*lnors)[3];
+ const int ml_last_index = (mp->loopstart + mp->totloop) - 1;
+ int ml_curr_index = mp->loopstart;
+ int ml_prev_index = ml_last_index;
+
+ ml_curr = &mloops[ml_curr_index];
+ ml_prev = &mloops[ml_prev_index];
+ lnors = &loopnors[ml_curr_index];
+
+ for (; ml_curr_index <= ml_last_index; ml_curr++, ml_curr_index++, lnors++) {
+ const int *e2l_curr = edge_to_loops[ml_curr->e];
+ const int *e2l_prev = edge_to_loops[ml_prev->e];
+
+ if (!IS_EDGE_SHARP(e2l_curr) && (!lnors_spacearr || BLI_BITMAP_TEST_BOOL(sharp_verts, ml_curr->v))) {
+ /* A smooth edge, and we are not generating lnor_spacearr, or the related vertex is sharp.
+ * We skip it because it is either:
+ * - in the middle of a 'smooth fan' already computed (or that will be as soon as we hit
+ * one of its ends, i.e. one of its two sharp edges), or...
+ * - the related vertex is a "full smooth" one, in which case pre-populated normals from vertex
+ * are just fine (or it has already be handled in a previous loop in case of needed lnors spacearr)!
+ */
+ /* printf("Skipping loop %d / edge %d / vert %d(%d)\n", ml_curr_index, ml_curr->e, ml_curr->v, sharp_verts[ml_curr->v]); */
+ }
+ else {
+ if (threaded) {
+ if (data_idx == 0) {
+ data_buff = MEM_callocN(sizeof(*data_buff) * LOOP_SPLIT_TASK_BLOCK_SIZE, __func__);
+ }
+ data = &data_buff[data_idx];
+ }
+
+ if (IS_EDGE_SHARP(e2l_curr) && IS_EDGE_SHARP(e2l_prev)) {
+ data->lnor = lnors;
+ data->ml_curr = ml_curr;
+ data->ml_prev = ml_prev;
+ data->ml_curr_index = ml_curr_index;
+#if 0 /* Not needed for 'single' loop. */
+ data->ml_prev_index = ml_prev_index;
+ data->e2l_prev = NULL; /* Tag as 'single' task. */
+#endif
+ data->mp_index = mp_index;
+ if (lnors_spacearr) {
+ data->lnor_space = BKE_lnor_space_create(lnors_spacearr);
+ }
+ }
+ /* We *do not need* to check/tag loops as already computed!
+ * Due to the fact a loop only links to one of its two edges, a same fan *will never be walked
+ * more than once!*
+ * Since we consider edges having neighbor polys with inverted (flipped) normals as sharp, we are sure
+ * that no fan will be skipped, even only considering the case (sharp curr_edge, smooth prev_edge),
+ * and not the alternative (smooth curr_edge, sharp prev_edge).
+ * All this due/thanks to link between normals and loop ordering (i.e. winding).
+ */
+ else {
+#if 0 /* Not needed for 'fan' loops. */
+ data->lnor = lnors;
+#endif
+ data->ml_curr = ml_curr;
+ data->ml_prev = ml_prev;
+ data->ml_curr_index = ml_curr_index;
+ data->ml_prev_index = ml_prev_index;
+ data->e2l_prev = e2l_prev; /* Also tag as 'fan' task. */
+ data->mp_index = mp_index;
+ if (lnors_spacearr) {
+ data->lnor_space = BKE_lnor_space_create(lnors_spacearr);
+ /* Tag related vertex as sharp, to avoid fanning around it again (in case it was a smooth one).
+ * This *has* to be done outside of workers tasks! */
+ BLI_BITMAP_ENABLE(sharp_verts, ml_curr->v);
+ }
+ }
+
+ if (threaded) {
+ data_idx++;
+ if (data_idx == LOOP_SPLIT_TASK_BLOCK_SIZE) {
+ BLI_thread_queue_push(common_data->task_queue, data_buff);
+ data_idx = 0;
+ }
+ }
+ else {
+ loop_split_worker_do(common_data, data, edge_vectors);
+ memset(data, 0, sizeof(data_mem));
+ }
+ }
+
+ ml_prev = ml_curr;
+ ml_prev_index = ml_curr_index;
+ }
+ }
+
+ if (threaded) {
+ /* Last block of data... Since it is calloc'ed and we use first NULL item as stopper, everything is fine. */
+ if (LIKELY(data_idx)) {
+ BLI_thread_queue_push(common_data->task_queue, data_buff);
+ }
+
+ /* This will signal all other worker threads to wake up and finish! */
+ BLI_thread_queue_nowait(common_data->task_queue);
+ }
+
+ if (edge_vectors) {
+ BLI_stack_free(edge_vectors);
+ }
+
+#ifdef DEBUG_TIME
+ TIMEIT_END(loop_split_generator);
+#endif
+}
+
+static void loop_split_generator(TaskPool *UNUSED(pool), void *taskdata, int UNUSED(threadid))
+{
+ LoopSplitTaskDataCommon *common_data = taskdata;
+
+ loop_split_generator_do(common_data, true);
+}
+
+/**
+ * Compute split normals, i.e. vertex normals associated with each poly (hence 'loop normals').
+ * Useful to materialize sharp edges (or non-smooth faces) without actually modifying the geometry (splitting edges).
+ */
+void BKE_mesh_normals_loop_split(
+ const MVert *mverts, const int numVerts, MEdge *medges, const int numEdges,
+ MLoop *mloops, float (*r_loopnors)[3], const int numLoops,
+ MPoly *mpolys, const float (*polynors)[3], const int numPolys,
+ const bool use_split_normals, float split_angle,
+ MLoopNorSpaceArray *r_lnors_spacearr, short (*clnors_data)[2], int *r_loop_to_poly)
+{
+
+ /* For now this is not supported. If we do not use split normals, we do not generate anything fancy! */
+ BLI_assert(use_split_normals || !(r_lnors_spacearr));
+
+ if (!use_split_normals) {
+ /* In this case, we simply fill lnors with vnors (or fnors for flat faces), quite simple!
+ * Note this is done here to keep some logic and consistency in this quite complex code,
+ * since we may want to use lnors even when mesh's 'autosmooth' is disabled (see e.g. mesh mapping code).
+ * As usual, we could handle that on case-by-case basis, but simpler to keep it well confined here.
+ */
+ int mp_index;
+
+ for (mp_index = 0; mp_index < numPolys; mp_index++) {
+ MPoly *mp = &mpolys[mp_index];
+ int ml_index = mp->loopstart;
+ const int ml_index_end = ml_index + mp->totloop;
+ const bool is_poly_flat = ((mp->flag & ME_SMOOTH) == 0);
+
+ for (; ml_index < ml_index_end; ml_index++) {
+ if (r_loop_to_poly) {
+ r_loop_to_poly[ml_index] = mp_index;
+ }
+ if (is_poly_flat) {
+ copy_v3_v3(r_loopnors[ml_index], polynors[mp_index]);
+ }
+ else {
+ normal_short_to_float_v3(r_loopnors[ml_index], mverts[mloops[ml_index].v].no);
+ }
+ }
+ }
+ return;
+ }
+
+ {
+
/* Mapping edge -> loops.
* If that edge is used by more than two loops (polys), it is always sharp (and tagged as such, see below).
* We also use the second loop index as a kind of flag: smooth edge: > 0,
@@ -341,21 +1172,39 @@ void BKE_mesh_normals_loop_split(MVert *mverts, const int UNUSED(numVerts), MEdg
int (*edge_to_loops)[2] = MEM_callocN(sizeof(int[2]) * (size_t)numEdges, __func__);
/* Simple mapping from a loop to its polygon index. */
- int *loop_to_poly = MEM_mallocN(sizeof(int) * (size_t)numLoops, __func__);
+ int *loop_to_poly = r_loop_to_poly ? r_loop_to_poly : MEM_mallocN(sizeof(int) * (size_t)numLoops, __func__);
MPoly *mp;
- int mp_index;
- const bool check_angle = (split_angle < (float)M_PI);
+ int mp_index, me_index;
+ bool check_angle = (split_angle < (float)M_PI);
+ int i;
- /* Temp normal stack. */
- BLI_SMALLSTACK_DECLARE(normal, float *);
+ BLI_bitmap *sharp_verts = NULL;
+ MLoopNorSpaceArray _lnors_spacearr = {NULL};
+
+ LoopSplitTaskDataCommon common_data = {NULL};
#ifdef DEBUG_TIME
TIMEIT_START(BKE_mesh_normals_loop_split);
#endif
if (check_angle) {
- split_angle = cosf(split_angle);
+ /* When using custom loop normals, disable the angle feature! */
+ if (clnors_data) {
+ check_angle = false;
+ }
+ else {
+ split_angle = cosf(split_angle);
+ }
+ }
+
+ if (!r_lnors_spacearr && clnors_data) {
+ /* We need to compute lnor spacearr if some custom lnor data are given to us! */
+ r_lnors_spacearr = &_lnors_spacearr;
+ }
+ if (r_lnors_spacearr) {
+ BKE_lnor_spacearr_init(r_lnors_spacearr, numLoops);
+ sharp_verts = BLI_BITMAP_NEW((size_t)numVerts, __func__);
}
/* This first loop check which edges are actually smooth, and compute edge vectors. */
@@ -409,187 +1258,344 @@ void BKE_mesh_normals_loop_split(MVert *mverts, const int UNUSED(numVerts), MEdg
}
}
- /* We now know edges that can be smoothed (with their vector, and their two loops), and edges that will be hard!
- * Now, time to generate the normals.
+ if (r_lnors_spacearr) {
+ /* Tag vertices that have at least one sharp edge as 'sharp' (used for the lnor spacearr computation).
+ * XXX This third loop over edges is a bit disappointing, could not find any other way yet.
+ * Not really performance-critical anyway.
+ */
+ for (me_index = 0; me_index < numEdges; me_index++) {
+ const int *e2l = edge_to_loops[me_index];
+ const MEdge *me = &medges[me_index];
+ if (IS_EDGE_SHARP(e2l)) {
+ BLI_BITMAP_ENABLE(sharp_verts, me->v1);
+ BLI_BITMAP_ENABLE(sharp_verts, me->v2);
+ }
+ }
+ }
+
+ /* Init data common to all tasks. */
+ common_data.lnors_spacearr = r_lnors_spacearr;
+ common_data.loopnors = r_loopnors;
+ common_data.clnors_data = clnors_data;
+
+ common_data.mverts = mverts;
+ common_data.medges = medges;
+ common_data.mloops = mloops;
+ common_data.mpolys = mpolys;
+ common_data.sharp_verts = sharp_verts;
+ common_data.edge_to_loops = (const int(*)[2])edge_to_loops;
+ common_data.loop_to_poly = loop_to_poly;
+ common_data.polynors = polynors;
+ common_data.numPolys = numPolys;
+
+ if (numLoops < LOOP_SPLIT_TASK_BLOCK_SIZE * 8) {
+ /* Not enough loops to be worth the whole threading overhead... */
+ loop_split_generator_do(&common_data, false);
+ }
+ else {
+ TaskScheduler *task_scheduler;
+ TaskPool *task_pool;
+ int nbr_workers;
+
+ common_data.task_queue = BLI_thread_queue_init();
+
+ task_scheduler = BLI_task_scheduler_get();
+ task_pool = BLI_task_pool_create(task_scheduler, NULL);
+
+ nbr_workers = max_ii(2, BLI_task_scheduler_num_threads(task_scheduler));
+ for (i = 1; i < nbr_workers; i++) {
+ BLI_task_pool_push(task_pool, loop_split_worker, &common_data, false, TASK_PRIORITY_HIGH);
+ }
+ BLI_task_pool_push(task_pool, loop_split_generator, &common_data, false, TASK_PRIORITY_HIGH);
+ BLI_task_pool_work_and_wait(task_pool);
+
+ BLI_task_pool_free(task_pool);
+
+ BLI_thread_queue_free(common_data.task_queue);
+ }
+
+ MEM_freeN(edge_to_loops);
+ if (!r_loop_to_poly) {
+ MEM_freeN(loop_to_poly);
+ }
+
+ if (r_lnors_spacearr) {
+ MEM_freeN(sharp_verts);
+ if (r_lnors_spacearr == &_lnors_spacearr) {
+ BKE_lnor_spacearr_free(r_lnors_spacearr);
+ }
+ }
+
+#ifdef DEBUG_TIME
+ TIMEIT_END(BKE_mesh_normals_loop_split);
+#endif
+
+ }
+}
+
+#undef INDEX_UNSET
+#undef INDEX_INVALID
+#undef IS_EDGE_SHARP
+
+/**
+ * Compute internal representation of given custom normals (as an array of float[2]).
+ * It also makes sure the mesh matches those custom normals, by setting sharp edges flag as needed to get a
+ * same custom lnor for all loops sharing a same smooth fan.
+ * If use_vertices if true, r_custom_loopnors is assumed to be per-vertex, not per-loop
+ * (this allows to set whole vert's normals at once, useful in some cases).
+ * r_custom_loopnors is expected to have normalized normals, or zero ones, in which case they will be replaced
+ * by default loop/vertex normal.
+ */
+static void mesh_normals_loop_custom_set(
+ const MVert *mverts, const int numVerts, MEdge *medges, const int numEdges,
+ MLoop *mloops, float (*r_custom_loopnors)[3], const int numLoops,
+ MPoly *mpolys, const float (*polynors)[3], const int numPolys,
+ short (*r_clnors_data)[2], const bool use_vertices)
+{
+ /* We *may* make that poor BKE_mesh_normals_loop_split() even more complex by making it handling that
+ * feature too, would probably be more efficient in absolute.
+ * However, this function *is not* performance-critical, since it is mostly expected to be called
+ * by io addons when importing custom normals, and modifier (and perhaps from some editing tools later?).
+ * So better to keep some simplicity here, and just call BKE_mesh_normals_loop_split() twice!
*/
- for (mp = mpolys, mp_index = 0; mp_index < numPolys; mp++, mp_index++) {
- MLoop *ml_curr, *ml_prev;
- float (*lnors)[3];
- const int ml_last_index = (mp->loopstart + mp->totloop) - 1;
- int ml_curr_index = mp->loopstart;
- int ml_prev_index = ml_last_index;
+ MLoopNorSpaceArray lnors_spacearr = {NULL};
+ BLI_bitmap *done_loops = BLI_BITMAP_NEW((size_t)numLoops, __func__);
+ float (*lnors)[3] = MEM_callocN(sizeof(*lnors) * (size_t)numLoops, __func__);
+ int *loop_to_poly = MEM_mallocN(sizeof(int) * (size_t)numLoops, __func__);
+ /* In this case we always consider split nors as ON, and do not want to use angle to define smooth fans! */
+ const bool use_split_normals = true;
+ const float split_angle = (float)M_PI;
+ int i;
- ml_curr = &mloops[ml_curr_index];
- ml_prev = &mloops[ml_prev_index];
- lnors = &r_loopnors[ml_curr_index];
+ BLI_SMALLSTACK_DECLARE(clnors_data, short *);
- for (; ml_curr_index <= ml_last_index; ml_curr++, ml_curr_index++, lnors++) {
- const int *e2l_curr = edge_to_loops[ml_curr->e];
- const int *e2l_prev = edge_to_loops[ml_prev->e];
+ /* Compute current lnor spacearr. */
+ BKE_mesh_normals_loop_split(mverts, numVerts, medges, numEdges, mloops, lnors, numLoops,
+ mpolys, polynors, numPolys, use_split_normals, split_angle,
+ &lnors_spacearr, NULL, loop_to_poly);
- if (!IS_EDGE_SHARP(e2l_curr)) {
- /* A smooth edge.
- * We skip it because it is either:
- * - in the middle of a 'smooth fan' already computed (or that will be as soon as we hit
- * one of its ends, i.e. one of its two sharp edges), or...
- * - the related vertex is a "full smooth" one, in which case pre-populated normals from vertex
- * are just fine!
- */
+ /* Set all given zero vectors to their default value. */
+ if (use_vertices) {
+ for (i = 0; i < numVerts; i++) {
+ if (is_zero_v3(r_custom_loopnors[i])) {
+ normal_short_to_float_v3(r_custom_loopnors[i], mverts[i].no);
}
- else if (IS_EDGE_SHARP(e2l_prev)) {
- /* Simple case (both edges around that vertex are sharp in current polygon),
- * this vertex just takes its poly normal.
- */
- copy_v3_v3(*lnors, polynors[mp_index]);
- /* No need to mark loop as done here, we won't run into it again anyway! */
+ }
+ }
+ else {
+ for (i = 0; i < numLoops; i++) {
+ if (is_zero_v3(r_custom_loopnors[i])) {
+ copy_v3_v3(r_custom_loopnors[i], lnors[i]);
}
- /* We *do not need* to check/tag loops as already computed!
- * Due to the fact a loop only links to one of its two edges, a same fan *will never be walked more than
- * once!*
- * Since we consider edges having neighbor polys with inverted (flipped) normals as sharp, we are sure that
- * no fan will be skipped, even only considering the case (sharp curr_edge, smooth prev_edge), and not the
- * alternative (smooth curr_edge, sharp prev_edge).
- * All this due/thanks to link between normals and loop ordering.
- */
- else {
- /* Gah... We have to fan around current vertex, until we find the other non-smooth edge,
- * and accumulate face normals into the vertex!
- * Note in case this vertex has only one sharp edges, this is a waste because the normal is the same as
- * the vertex normal, but I do not see any easy way to detect that (would need to count number
- * of sharp edges per vertex, I doubt the additional memory usage would be worth it, especially as
- * it should not be a common case in real-life meshes anyway).
- */
- const unsigned int mv_pivot_index = ml_curr->v; /* The vertex we are "fanning" around! */
- const MVert *mv_pivot = &mverts[mv_pivot_index];
- const int *e2lfan_curr;
- float vec_curr[3], vec_prev[3];
- MLoop *mlfan_curr, *mlfan_next;
- MPoly *mpfan_next;
- float lnor[3] = {0.0f, 0.0f, 0.0f};
- /* mlfan_vert_index: the loop of our current edge might not be the loop of our current vertex! */
- int mlfan_curr_index, mlfan_vert_index, mpfan_curr_index;
-
- e2lfan_curr = e2l_prev;
- mlfan_curr = ml_prev;
- mlfan_curr_index = ml_prev_index;
- mlfan_vert_index = ml_curr_index;
- mpfan_curr_index = mp_index;
-
- BLI_assert(mlfan_curr_index >= 0);
- BLI_assert(mlfan_vert_index >= 0);
- BLI_assert(mpfan_curr_index >= 0);
-
- /* Only need to compute previous edge's vector once, then we can just reuse old current one! */
- {
- const MEdge *me_prev = &medges[ml_curr->e]; /* ml_curr would be mlfan_prev if we needed that one */
- const MVert *mv_2 = (me_prev->v1 == mv_pivot_index) ? &mverts[me_prev->v2] : &mverts[me_prev->v1];
+ }
+ }
- sub_v3_v3v3(vec_prev, mv_2->co, mv_pivot->co);
- normalize_v3(vec_prev);
+ /* Now, check each current smooth fan (one lnor space per smooth fan!), and if all its matching custom lnors
+ * are not (enough) equal, add sharp edges as needed.
+ * This way, next time we run BKE_mesh_normals_loop_split(), we'll get lnor spacearr/smooth fans matching
+ * given custom lnors.
+ * Note this code *will never* unsharp edges!
+ * And quite obviously, when we set custom normals per vertices, running this is absolutely useless.
+ */
+ if (!use_vertices) {
+ for (i = 0; i < numLoops; i++) {
+ if (!lnors_spacearr.lspacearr[i]) {
+ /* This should not happen in theory, but in some rare case (probably ugly geometry)
+ * we can get some NULL loopspacearr at this point. :/
+ * Maybe we should set those loops' edges as sharp?
+ */
+ BLI_BITMAP_ENABLE(done_loops, i);
+ if (G.debug & G_DEBUG) {
+ printf("WARNING! Getting invalid NULL loop space for loop %d!\n", i);
}
+ continue;
+ }
- while (true) {
- /* Compute edge vectors.
- * NOTE: We could pre-compute those into an array, in the first iteration, instead of computing them
- * twice (or more) here. However, time gained is not worth memory and time lost,
- * given the fact that this code should not be called that much in real-life meshes...
- */
- {
- const MEdge *me_curr = &medges[mlfan_curr->e];
- const MVert *mv_2 = (me_curr->v1 == mv_pivot_index) ? &mverts[me_curr->v2] :
- &mverts[me_curr->v1];
-
- sub_v3_v3v3(vec_curr, mv_2->co, mv_pivot->co);
- normalize_v3(vec_curr);
+ if (!BLI_BITMAP_TEST(done_loops, i)) {
+ /* Notes:
+ * * In case of mono-loop smooth fan, loops is NULL, so everything is fine (we have nothing to do).
+ * * Loops in this linklist are ordered (in reversed order compared to how they were discovered by
+ * BKE_mesh_normals_loop_split(), but this is not a problem). Which means if we find a
+ * mismatching clnor, we know all remaining loops will have to be in a new, different smooth fan/
+ * lnor space.
+ * * In smooth fan case, we compare each clnor against a ref one, to avoid small differences adding
+ * up into a real big one in the end!
+ */
+ LinkNode *loops = lnors_spacearr.lspacearr[i]->loops;
+ MLoop *prev_ml = NULL;
+ const float *org_nor = NULL;
+
+ while (loops) {
+ const int lidx = GET_INT_FROM_POINTER(loops->link);
+ MLoop *ml = &mloops[lidx];
+ const int nidx = lidx;
+ float *nor = r_custom_loopnors[nidx];
+
+ if (!org_nor) {
+ org_nor = nor;
}
-
- {
- /* Code similar to accumulate_vertex_normals_poly. */
- /* Calculate angle between the two poly edges incident on this vertex. */
- const float fac = saacos(dot_v3v3(vec_curr, vec_prev));
- /* Accumulate */
- madd_v3_v3fl(lnor, polynors[mpfan_curr_index], fac);
+ else if (dot_v3v3(org_nor, nor) < LNOR_SPACE_TRIGO_THRESHOLD) {
+ /* Current normal differs too much from org one, we have to tag the edge between
+ * previous loop's face and current's one as sharp.
+ * We know those two loops do not point to the same edge, since we do not allow reversed winding
+ * in a same smooth fan.
+ */
+ const MPoly *mp = &mpolys[loop_to_poly[lidx]];
+ const MLoop *mlp = &mloops[(lidx == mp->loopstart) ? mp->loopstart + mp->totloop - 1 : lidx - 1];
+ medges[(prev_ml->e == mlp->e) ? prev_ml->e : ml->e].flag |= ME_SHARP;
+
+ org_nor = nor;
}
- /* We store here a pointer to all loop-normals processed. */
- BLI_SMALLSTACK_PUSH(normal, &(r_loopnors[mlfan_vert_index][0]));
+ prev_ml = ml;
+ loops = loops->next;
+ BLI_BITMAP_ENABLE(done_loops, lidx);
+ }
- if (IS_EDGE_SHARP(e2lfan_curr)) {
- /* Current edge is sharp, we have finished with this fan of faces around this vert! */
- break;
+ /* We also have to check between last and first loops, otherwise we may miss some sharp edges here!
+ * This is just a simplified version of above while loop.
+ * See T45984. */
+ loops = lnors_spacearr.lspacearr[i]->loops;
+ if (loops && org_nor) {
+ const int lidx = GET_INT_FROM_POINTER(loops->link);
+ MLoop *ml = &mloops[lidx];
+ const int nidx = lidx;
+ float *nor = r_custom_loopnors[nidx];
+
+ if (dot_v3v3(org_nor, nor) < LNOR_SPACE_TRIGO_THRESHOLD) {
+ const MPoly *mp = &mpolys[loop_to_poly[lidx]];
+ const MLoop *mlp = &mloops[(lidx == mp->loopstart) ? mp->loopstart + mp->totloop - 1 : lidx - 1];
+ medges[(prev_ml->e == mlp->e) ? prev_ml->e : ml->e].flag |= ME_SHARP;
}
+ }
- copy_v3_v3(vec_prev, vec_curr);
-
- /* Warning! This is rather complex!
- * We have to find our next edge around the vertex (fan mode).
- * First we find the next loop, which is either previous or next to mlfan_curr_index, depending
- * whether both loops using current edge are in the same direction or not, and whether
- * mlfan_curr_index actually uses the vertex we are fanning around!
- * mlfan_curr_index is the index of mlfan_next here, and mlfan_next is not the real next one
- * (i.e. not the future mlfan_curr)...
- */
- mlfan_curr_index = (e2lfan_curr[0] == mlfan_curr_index) ? e2lfan_curr[1] : e2lfan_curr[0];
- mpfan_curr_index = loop_to_poly[mlfan_curr_index];
-
- BLI_assert(mlfan_curr_index >= 0);
- BLI_assert(mpfan_curr_index >= 0);
-
- mlfan_next = &mloops[mlfan_curr_index];
- mpfan_next = &mpolys[mpfan_curr_index];
- if ((mlfan_curr->v == mlfan_next->v && mlfan_curr->v == mv_pivot_index) ||
- (mlfan_curr->v != mlfan_next->v && mlfan_curr->v != mv_pivot_index))
- {
- /* We need the previous loop, but current one is our vertex's loop. */
- mlfan_vert_index = mlfan_curr_index;
- if (--mlfan_curr_index < mpfan_next->loopstart) {
- mlfan_curr_index = mpfan_next->loopstart + mpfan_next->totloop - 1;
- }
- }
- else {
- /* We need the next loop, which is also our vertex's loop. */
- if (++mlfan_curr_index >= mpfan_next->loopstart + mpfan_next->totloop) {
- mlfan_curr_index = mpfan_next->loopstart;
- }
- mlfan_vert_index = mlfan_curr_index;
- }
- mlfan_curr = &mloops[mlfan_curr_index];
- /* And now we are back in sync, mlfan_curr_index is the index of mlfan_curr! Pff! */
+ /* For single loops, where lnors_spacearr.lspacearr[i]->loops is NULL. */
+ BLI_BITMAP_ENABLE(done_loops, i);
+ }
+ }
- e2lfan_curr = edge_to_loops[mlfan_curr->e];
- }
+ /* And now, recompute our new auto lnors and lnor spacearr! */
+ BKE_lnor_spacearr_clear(&lnors_spacearr);
+ BKE_mesh_normals_loop_split(mverts, numVerts, medges, numEdges, mloops, lnors, numLoops,
+ mpolys, polynors, numPolys, use_split_normals, split_angle,
+ &lnors_spacearr, NULL, loop_to_poly);
+ }
+ else {
+ BLI_BITMAP_SET_ALL(done_loops, true, (size_t)numLoops);
+ }
- /* In case we get a zero normal here, just use vertex normal already set! */
- if (LIKELY(normalize_v3(lnor) != 0.0f)) {
- /* Copy back the final computed normal into all related loop-normals. */
- float *nor;
- while ((nor = BLI_SMALLSTACK_POP(normal))) {
- copy_v3_v3(nor, lnor);
- }
+ /* And we just have to convert plain object-space custom normals to our lnor space-encoded ones. */
+ for (i = 0; i < numLoops; i++) {
+ if (!lnors_spacearr.lspacearr[i]) {
+ BLI_BITMAP_DISABLE(done_loops, i);
+ if (G.debug & G_DEBUG) {
+ printf("WARNING! Still getting invalid NULL loop space in second loop for loop %d!\n", i);
+ }
+ continue;
+ }
+
+ if (BLI_BITMAP_TEST_BOOL(done_loops, i)) {
+ /* Note we accumulate and average all custom normals in current smooth fan, to avoid getting different
+ * clnors data (tiny differences in plain custom normals can give rather huge differences in
+ * computed 2D factors).
+ */
+ LinkNode *loops = lnors_spacearr.lspacearr[i]->loops;
+ if (loops) {
+ int nbr_nors = 0;
+ float avg_nor[3];
+ short clnor_data_tmp[2], *clnor_data;
+
+ zero_v3(avg_nor);
+ while (loops) {
+ const int lidx = GET_INT_FROM_POINTER(loops->link);
+ const int nidx = use_vertices ? (int)mloops[lidx].v : lidx;
+ float *nor = r_custom_loopnors[nidx];
+
+ nbr_nors++;
+ add_v3_v3(avg_nor, nor);
+ BLI_SMALLSTACK_PUSH(clnors_data, (short *)r_clnors_data[lidx]);
+
+ loops = loops->next;
+ BLI_BITMAP_DISABLE(done_loops, lidx);
}
- else {
- /* We still have to clear the stack! */
- while (BLI_SMALLSTACK_POP(normal));
+
+ mul_v3_fl(avg_nor, 1.0f / (float)nbr_nors);
+ BKE_lnor_space_custom_normal_to_data(lnors_spacearr.lspacearr[i], avg_nor, clnor_data_tmp);
+
+ while ((clnor_data = BLI_SMALLSTACK_POP(clnors_data))) {
+ clnor_data[0] = clnor_data_tmp[0];
+ clnor_data[1] = clnor_data_tmp[1];
}
}
+ else {
+ const int nidx = use_vertices ? (int)mloops[i].v : i;
+ float *nor = r_custom_loopnors[nidx];
- ml_prev = ml_curr;
- ml_prev_index = ml_curr_index;
+ BKE_lnor_space_custom_normal_to_data(lnors_spacearr.lspacearr[i], nor, r_clnors_data[i]);
+ BLI_BITMAP_DISABLE(done_loops, i);
+ }
}
}
- MEM_freeN(edge_to_loops);
+ MEM_freeN(lnors);
MEM_freeN(loop_to_poly);
+ MEM_freeN(done_loops);
+ BKE_lnor_spacearr_free(&lnors_spacearr);
+}
-#ifdef DEBUG_TIME
- TIMEIT_END(BKE_mesh_normals_loop_split);
-#endif
+void BKE_mesh_normals_loop_custom_set(
+ const MVert *mverts, const int numVerts, MEdge *medges, const int numEdges,
+ MLoop *mloops, float (*r_custom_loopnors)[3], const int numLoops,
+ MPoly *mpolys, const float (*polynors)[3], const int numPolys,
+ short (*r_clnors_data)[2])
+{
+ mesh_normals_loop_custom_set(mverts, numVerts, medges, numEdges, mloops, r_custom_loopnors, numLoops,
+ mpolys, polynors, numPolys, r_clnors_data, false);
+}
-#undef INDEX_UNSET
-#undef INDEX_INVALID
-#undef IS_EDGE_SHARP
+void BKE_mesh_normals_loop_custom_from_vertices_set(
+ const MVert *mverts, float (*r_custom_vertnors)[3], const int numVerts,
+ MEdge *medges, const int numEdges, MLoop *mloops, const int numLoops,
+ MPoly *mpolys, const float (*polynors)[3], const int numPolys,
+ short (*r_clnors_data)[2])
+{
+ mesh_normals_loop_custom_set(mverts, numVerts, medges, numEdges, mloops, r_custom_vertnors, numLoops,
+ mpolys, polynors, numPolys, r_clnors_data, true);
}
+/**
+ * Computes average per-vertex normals from given custom loop normals.
+ *
+ * @param clnors The computed custom loop normals.
+ * @param r_vert_clnors The (already allocated) array where to store averaged per-vertex normals.
+ */
+void BKE_mesh_normals_loop_to_vertex(
+ const int numVerts, const MLoop *mloops, const int numLoops,
+ const float (*clnors)[3], float (*r_vert_clnors)[3])
+{
+ const MLoop *ml;
+ int i;
+
+ int *vert_loops_nbr = MEM_callocN(sizeof(*vert_loops_nbr) * (size_t)numVerts, __func__);
+
+ copy_vn_fl((float *)r_vert_clnors, 3 * numVerts, 0.0f);
+
+ for (i = 0, ml = mloops; i < numLoops; i++, ml++) {
+ const unsigned int v = ml->v;
+
+ add_v3_v3(r_vert_clnors[v], clnors[i]);
+ vert_loops_nbr[v]++;
+ }
+
+ for (i = 0; i < numVerts; i++) {
+ mul_v3_fl(r_vert_clnors[i], 1.0f / (float)vert_loops_nbr[i]);
+ }
+
+ MEM_freeN(vert_loops_nbr);
+}
+
+
+#undef LNOR_SPACE_TRIGO_THRESHOLD
/** \} */
@@ -603,10 +1609,10 @@ void BKE_mesh_normals_loop_split(MVert *mverts, const int UNUSED(numVerts), MEdg
/* User data. */
typedef struct {
- MPoly *mpolys; /* faces */
- MLoop *mloops; /* faces's vertices */
- MVert *mverts; /* vertices */
- MLoopUV *luvs; /* texture coordinates */
+ const MPoly *mpolys; /* faces */
+ const MLoop *mloops; /* faces's vertices */
+ const MVert *mverts; /* vertices */
+ const MLoopUV *luvs; /* texture coordinates */
float (*lnors)[3]; /* loops' normals */
float (*tangents)[4]; /* output tangents */
int num_polys; /* number of polygons */
@@ -659,15 +1665,17 @@ static void set_tspace(const SMikkTSpaceContext *pContext, const float fv_tangen
* split normals can be used to recreate the full tangent space.
* Note: * The mesh should be made of only tris and quads!
*/
-void BKE_mesh_loop_tangents_ex(MVert *mverts, const int UNUSED(numVerts), MLoop *mloops,
- float (*r_looptangent)[4], float (*loopnors)[3], MLoopUV *loopuvs,
- const int UNUSED(numLoops), MPoly *mpolys, const int numPolys, ReportList *reports)
+void BKE_mesh_loop_tangents_ex(
+ const MVert *mverts, const int UNUSED(numVerts), const MLoop *mloops,
+ float (*r_looptangent)[4], float (*loopnors)[3], const MLoopUV *loopuvs,
+ const int UNUSED(numLoops), const MPoly *mpolys, const int numPolys,
+ ReportList *reports)
{
BKEMeshToTangent mesh_to_tangent = {NULL};
SMikkTSpaceContext s_context = {NULL};
SMikkTSpaceInterface s_interface = {NULL};
- MPoly *mp;
+ const MPoly *mp;
int mp_index;
/* First check we do have a tris/quads only mesh. */
@@ -704,8 +1712,9 @@ void BKE_mesh_loop_tangents_ex(MVert *mverts, const int UNUSED(numVerts), MLoop
/**
* Wrapper around BKE_mesh_loop_tangents_ex, which takes care of most boiling code.
- * Note: * There must be a valid loop's CD_NORMALS available.
- * * The mesh should be made of only tris and quads!
+ * \note
+ * - There must be a valid loop's CD_NORMALS available.
+ * - The mesh should be made of only tris and quads!
*/
void BKE_mesh_loop_tangents(Mesh *mesh, const char *uvmap, float (*r_looptangents)[4], ReportList *reports)
{
@@ -750,8 +1759,9 @@ void BKE_mesh_loop_tangents(Mesh *mesh, const char *uvmap, float (*r_looptangent
* computing newell normal.
*
*/
-static void mesh_calc_ngon_normal(MPoly *mpoly, MLoop *loopstart,
- MVert *mvert, float normal[3])
+static void mesh_calc_ngon_normal(
+ const MPoly *mpoly, const MLoop *loopstart,
+ const MVert *mvert, float normal[3])
{
const int nverts = mpoly->totloop;
const float *v_prev = mvert[loopstart[nverts - 1].v].co;
@@ -772,21 +1782,22 @@ static void mesh_calc_ngon_normal(MPoly *mpoly, MLoop *loopstart,
}
}
-void BKE_mesh_calc_poly_normal(MPoly *mpoly, MLoop *loopstart,
- MVert *mvarray, float no[3])
+void BKE_mesh_calc_poly_normal(
+ const MPoly *mpoly, const MLoop *loopstart,
+ const MVert *mvarray, float r_no[3])
{
if (mpoly->totloop > 4) {
- mesh_calc_ngon_normal(mpoly, loopstart, mvarray, no);
+ mesh_calc_ngon_normal(mpoly, loopstart, mvarray, r_no);
}
else if (mpoly->totloop == 3) {
- normal_tri_v3(no,
+ normal_tri_v3(r_no,
mvarray[loopstart[0].v].co,
mvarray[loopstart[1].v].co,
mvarray[loopstart[2].v].co
);
}
else if (mpoly->totloop == 4) {
- normal_quad_v3(no,
+ normal_quad_v3(r_no,
mvarray[loopstart[0].v].co,
mvarray[loopstart[1].v].co,
mvarray[loopstart[2].v].co,
@@ -794,49 +1805,51 @@ void BKE_mesh_calc_poly_normal(MPoly *mpoly, MLoop *loopstart,
);
}
else { /* horrible, two sided face! */
- no[0] = 0.0;
- no[1] = 0.0;
- no[2] = 1.0;
+ r_no[0] = 0.0;
+ r_no[1] = 0.0;
+ r_no[2] = 1.0;
}
}
/* duplicate of function above _but_ takes coords rather then mverts */
-static void mesh_calc_ngon_normal_coords(MPoly *mpoly, MLoop *loopstart,
- const float (*vertex_coords)[3], float normal[3])
+static void mesh_calc_ngon_normal_coords(
+ const MPoly *mpoly, const MLoop *loopstart,
+ const float (*vertex_coords)[3], float r_normal[3])
{
const int nverts = mpoly->totloop;
const float *v_prev = vertex_coords[loopstart[nverts - 1].v];
const float *v_curr;
int i;
- zero_v3(normal);
+ zero_v3(r_normal);
/* Newell's Method */
for (i = 0; i < nverts; i++) {
v_curr = vertex_coords[loopstart[i].v];
- add_newell_cross_v3_v3v3(normal, v_prev, v_curr);
+ add_newell_cross_v3_v3v3(r_normal, v_prev, v_curr);
v_prev = v_curr;
}
- if (UNLIKELY(normalize_v3(normal) == 0.0f)) {
- normal[2] = 1.0f; /* other axis set to 0.0 */
+ if (UNLIKELY(normalize_v3(r_normal) == 0.0f)) {
+ r_normal[2] = 1.0f; /* other axis set to 0.0 */
}
}
-void BKE_mesh_calc_poly_normal_coords(MPoly *mpoly, MLoop *loopstart,
- const float (*vertex_coords)[3], float no[3])
+void BKE_mesh_calc_poly_normal_coords(
+ const MPoly *mpoly, const MLoop *loopstart,
+ const float (*vertex_coords)[3], float r_no[3])
{
if (mpoly->totloop > 4) {
- mesh_calc_ngon_normal_coords(mpoly, loopstart, vertex_coords, no);
+ mesh_calc_ngon_normal_coords(mpoly, loopstart, vertex_coords, r_no);
}
else if (mpoly->totloop == 3) {
- normal_tri_v3(no,
+ normal_tri_v3(r_no,
vertex_coords[loopstart[0].v],
vertex_coords[loopstart[1].v],
vertex_coords[loopstart[2].v]
);
}
else if (mpoly->totloop == 4) {
- normal_quad_v3(no,
+ normal_quad_v3(r_no,
vertex_coords[loopstart[0].v],
vertex_coords[loopstart[1].v],
vertex_coords[loopstart[2].v],
@@ -844,14 +1857,15 @@ void BKE_mesh_calc_poly_normal_coords(MPoly *mpoly, MLoop *loopstart,
);
}
else { /* horrible, two sided face! */
- no[0] = 0.0;
- no[1] = 0.0;
- no[2] = 1.0;
+ r_no[0] = 0.0;
+ r_no[1] = 0.0;
+ r_no[2] = 1.0;
}
}
-static void mesh_calc_ngon_center(MPoly *mpoly, MLoop *loopstart,
- MVert *mvert, float cent[3])
+static void mesh_calc_ngon_center(
+ const MPoly *mpoly, const MLoop *loopstart,
+ const MVert *mvert, float cent[3])
{
const float w = 1.0f / (float)mpoly->totloop;
int i;
@@ -863,18 +1877,19 @@ static void mesh_calc_ngon_center(MPoly *mpoly, MLoop *loopstart,
}
}
-void BKE_mesh_calc_poly_center(MPoly *mpoly, MLoop *loopstart,
- MVert *mvarray, float cent[3])
+void BKE_mesh_calc_poly_center(
+ const MPoly *mpoly, const MLoop *loopstart,
+ const MVert *mvarray, float r_cent[3])
{
if (mpoly->totloop == 3) {
- cent_tri_v3(cent,
+ cent_tri_v3(r_cent,
mvarray[loopstart[0].v].co,
mvarray[loopstart[1].v].co,
mvarray[loopstart[2].v].co
);
}
else if (mpoly->totloop == 4) {
- cent_quad_v3(cent,
+ cent_quad_v3(r_cent,
mvarray[loopstart[0].v].co,
mvarray[loopstart[1].v].co,
mvarray[loopstart[2].v].co,
@@ -882,13 +1897,14 @@ void BKE_mesh_calc_poly_center(MPoly *mpoly, MLoop *loopstart,
);
}
else {
- mesh_calc_ngon_center(mpoly, loopstart, mvarray, cent);
+ mesh_calc_ngon_center(mpoly, loopstart, mvarray, r_cent);
}
}
/* note, passing polynormal is only a speedup so we can skip calculating it */
-float BKE_mesh_calc_poly_area(MPoly *mpoly, MLoop *loopstart,
- MVert *mvarray)
+float BKE_mesh_calc_poly_area(
+ const MPoly *mpoly, const MLoop *loopstart,
+ const MVert *mvarray)
{
if (mpoly->totloop == 3) {
return area_tri_v3(mvarray[loopstart[0].v].co,
@@ -896,16 +1912,9 @@ float BKE_mesh_calc_poly_area(MPoly *mpoly, MLoop *loopstart,
mvarray[loopstart[2].v].co
);
}
- else if (mpoly->totloop == 4) {
- return area_quad_v3(mvarray[loopstart[0].v].co,
- mvarray[loopstart[1].v].co,
- mvarray[loopstart[2].v].co,
- mvarray[loopstart[3].v].co
- );
- }
else {
int i;
- MLoop *l_iter = loopstart;
+ const MLoop *l_iter = loopstart;
float area;
float (*vertexcos)[3] = BLI_array_alloca(vertexcos, (size_t)mpoly->totloop);
@@ -922,7 +1931,9 @@ float BKE_mesh_calc_poly_area(MPoly *mpoly, MLoop *loopstart,
}
/* note, results won't be correct if polygon is non-planar */
-static float mesh_calc_poly_planar_area_centroid(MPoly *mpoly, MLoop *loopstart, MVert *mvarray, float cent[3])
+static float mesh_calc_poly_planar_area_centroid(
+ const MPoly *mpoly, const MLoop *loopstart, const MVert *mvarray,
+ float r_cent[3])
{
int i;
float tri_area;
@@ -932,7 +1943,7 @@ static float mesh_calc_poly_planar_area_centroid(MPoly *mpoly, MLoop *loopstart,
BKE_mesh_calc_poly_normal(mpoly, loopstart, mvarray, normal);
copy_v3_v3(v1, mvarray[loopstart[0].v].co);
copy_v3_v3(v2, mvarray[loopstart[1].v].co);
- zero_v3(cent);
+ zero_v3(r_cent);
for (i = 2; i < mpoly->totloop; i++) {
copy_v3_v3(v3, mvarray[loopstart[i].v].co);
@@ -941,12 +1952,12 @@ static float mesh_calc_poly_planar_area_centroid(MPoly *mpoly, MLoop *loopstart,
total_area += tri_area;
cent_tri_v3(tri_cent, v1, v2, v3);
- madd_v3_v3fl(cent, tri_cent, tri_area);
+ madd_v3_v3fl(r_cent, tri_cent, tri_area);
copy_v3_v3(v2, v3);
}
- mul_v3_fl(cent, 1.0f / total_area);
+ mul_v3_fl(r_cent, 1.0f / total_area);
return total_area;
}
@@ -974,8 +1985,9 @@ void BKE_mesh_calc_poly_angles(MPoly *mpoly, MLoop *loopstart,
#else /* equivalent the function above but avoid multiple subtractions + normalize */
-void BKE_mesh_calc_poly_angles(MPoly *mpoly, MLoop *loopstart,
- MVert *mvarray, float angles[])
+void BKE_mesh_calc_poly_angles(
+ const MPoly *mpoly, const MLoop *loopstart,
+ const MVert *mvarray, float angles[])
{
float nor_prev[3];
float nor_next[3];
@@ -1036,35 +2048,35 @@ void BKE_mesh_poly_edgebitmap_insert(unsigned int *edge_bitmap, const MPoly *mp,
/** \name Mesh Center Calculation
* \{ */
-bool BKE_mesh_center_median(Mesh *me, float cent[3])
+bool BKE_mesh_center_median(const Mesh *me, float r_cent[3])
{
int i = me->totvert;
- MVert *mvert;
- zero_v3(cent);
+ const MVert *mvert;
+ zero_v3(r_cent);
for (mvert = me->mvert; i--; mvert++) {
- add_v3_v3(cent, mvert->co);
+ add_v3_v3(r_cent, mvert->co);
}
/* otherwise we get NAN for 0 verts */
if (me->totvert) {
- mul_v3_fl(cent, 1.0f / (float)me->totvert);
+ mul_v3_fl(r_cent, 1.0f / (float)me->totvert);
}
return (me->totvert != 0);
}
-bool BKE_mesh_center_bounds(Mesh *me, float cent[3])
+bool BKE_mesh_center_bounds(const Mesh *me, float r_cent[3])
{
float min[3], max[3];
INIT_MINMAX(min, max);
if (BKE_mesh_minmax(me, min, max)) {
- mid_v3_v3v3(cent, min, max);
+ mid_v3_v3v3(r_cent, min, max);
return true;
}
return false;
}
-bool BKE_mesh_center_centroid(Mesh *me, float cent[3])
+bool BKE_mesh_center_centroid(const Mesh *me, float r_cent[3])
{
int i = me->totpoly;
MPoly *mpoly;
@@ -1072,23 +2084,23 @@ bool BKE_mesh_center_centroid(Mesh *me, float cent[3])
float total_area = 0.0f;
float poly_cent[3];
- zero_v3(cent);
+ zero_v3(r_cent);
/* calculate a weighted average of polygon centroids */
for (mpoly = me->mpoly; i--; mpoly++) {
poly_area = mesh_calc_poly_planar_area_centroid(mpoly, me->mloop + mpoly->loopstart, me->mvert, poly_cent);
- madd_v3_v3fl(cent, poly_cent, poly_area);
+ madd_v3_v3fl(r_cent, poly_cent, poly_area);
total_area += poly_area;
}
/* otherwise we get NAN for 0 polys */
if (me->totpoly) {
- mul_v3_fl(cent, 1.0f / total_area);
+ mul_v3_fl(r_cent, 1.0f / total_area);
}
/* zero area faces cause this, fallback to median */
- if (UNLIKELY(!is_finite_v3(cent))) {
- return BKE_mesh_center_median(me, cent);
+ if (UNLIKELY(!is_finite_v3(r_cent))) {
+ return BKE_mesh_center_median(me, r_cent);
}
return (me->totpoly != 0);
@@ -1101,100 +2113,86 @@ bool BKE_mesh_center_centroid(Mesh *me, float cent[3])
/** \name Mesh Volume Calculation
* \{ */
-static bool mesh_calc_center_centroid_ex(MVert *mverts, int UNUSED(numVerts),
- MFace *mfaces, int numFaces,
- float center[3])
+static bool mesh_calc_center_centroid_ex(
+ const MVert *mverts, int UNUSED(mverts_num),
+ const MLoopTri *looptri, int looptri_num,
+ const MLoop *mloop, float r_center[3])
{
+ const MLoopTri *lt;
float totweight;
- int f;
+ int i;
- zero_v3(center);
+ zero_v3(r_center);
- if (numFaces == 0)
+ if (looptri_num == 0)
return false;
totweight = 0.0f;
- for (f = 0; f < numFaces; ++f) {
- MFace *face = &mfaces[f];
- MVert *v1 = &mverts[face->v1];
- MVert *v2 = &mverts[face->v2];
- MVert *v3 = &mverts[face->v3];
- MVert *v4 = &mverts[face->v4];
+ for (i = 0, lt = looptri; i < looptri_num; i++, lt++) {
+ const MVert *v1 = &mverts[mloop[lt->tri[0]].v];
+ const MVert *v2 = &mverts[mloop[lt->tri[1]].v];
+ const MVert *v3 = &mverts[mloop[lt->tri[2]].v];
float area;
area = area_tri_v3(v1->co, v2->co, v3->co);
- madd_v3_v3fl(center, v1->co, area);
- madd_v3_v3fl(center, v2->co, area);
- madd_v3_v3fl(center, v3->co, area);
+ madd_v3_v3fl(r_center, v1->co, area);
+ madd_v3_v3fl(r_center, v2->co, area);
+ madd_v3_v3fl(r_center, v3->co, area);
totweight += area;
-
- if (face->v4) {
- area = area_tri_v3(v3->co, v4->co, v1->co);
- madd_v3_v3fl(center, v3->co, area);
- madd_v3_v3fl(center, v4->co, area);
- madd_v3_v3fl(center, v1->co, area);
- totweight += area;
- }
}
if (totweight == 0.0f)
return false;
- mul_v3_fl(center, 1.0f / (3.0f * totweight));
+ mul_v3_fl(r_center, 1.0f / (3.0f * totweight));
return true;
}
-void BKE_mesh_calc_volume(MVert *mverts, int numVerts,
- MFace *mfaces, int numFaces,
- float *r_vol, float *r_com)
+/**
+ * Calculate the volume and center.
+ *
+ * \param r_volume: Volume (unsigned).
+ * \param r_center: Center of mass.
+ */
+void BKE_mesh_calc_volume(
+ const MVert *mverts, const int mverts_num,
+ const MLoopTri *looptri, const int looptri_num,
+ const MLoop *mloop,
+ float *r_volume, float r_center[3])
{
+ const MLoopTri *lt;
float center[3];
float totvol;
- int f;
+ int i;
- if (r_vol) *r_vol = 0.0f;
- if (r_com) zero_v3(r_com);
+ if (r_volume)
+ *r_volume = 0.0f;
+ if (r_center)
+ zero_v3(r_center);
- if (numFaces == 0)
+ if (looptri_num == 0)
return;
- if (!mesh_calc_center_centroid_ex(mverts, numVerts, mfaces, numFaces, center))
+ if (!mesh_calc_center_centroid_ex(mverts, mverts_num, looptri, looptri_num, mloop, center))
return;
totvol = 0.0f;
- for (f = 0; f < numFaces; ++f) {
- MFace *face = &mfaces[f];
- MVert *v1 = &mverts[face->v1];
- MVert *v2 = &mverts[face->v2];
- MVert *v3 = &mverts[face->v3];
- MVert *v4 = &mverts[face->v4];
+
+ for (i = 0, lt = looptri; i < looptri_num; i++, lt++) {
+ const MVert *v1 = &mverts[mloop[lt->tri[0]].v];
+ const MVert *v2 = &mverts[mloop[lt->tri[1]].v];
+ const MVert *v3 = &mverts[mloop[lt->tri[2]].v];
float vol;
vol = volume_tetrahedron_signed_v3(center, v1->co, v2->co, v3->co);
- if (r_vol) {
+ if (r_volume) {
totvol += vol;
}
- if (r_com) {
- /* averaging factor 1/4 is applied in the end */
- madd_v3_v3fl(r_com, center, vol); // XXX could extract this
- madd_v3_v3fl(r_com, v1->co, vol);
- madd_v3_v3fl(r_com, v2->co, vol);
- madd_v3_v3fl(r_com, v3->co, vol);
- }
-
- if (face->v4) {
- vol = volume_tetrahedron_signed_v3(center, v3->co, v4->co, v1->co);
-
- if (r_vol) {
- totvol += vol;
- }
- if (r_com) {
- /* averaging factor 1/4 is applied in the end */
- madd_v3_v3fl(r_com, center, vol); // XXX could extract this
- madd_v3_v3fl(r_com, v3->co, vol);
- madd_v3_v3fl(r_com, v4->co, vol);
- madd_v3_v3fl(r_com, v1->co, vol);
- }
+ if (r_center) {
+ /* averaging factor 1/3 is applied in the end */
+ madd_v3_v3fl(r_center, v1->co, vol);
+ madd_v3_v3fl(r_center, v2->co, vol);
+ madd_v3_v3fl(r_center, v3->co, vol);
}
}
@@ -1202,15 +2200,15 @@ void BKE_mesh_calc_volume(MVert *mverts, int numVerts,
* totvol can become negative even for a valid mesh.
* The true value is always the positive value.
*/
- if (r_vol) {
- *r_vol = fabsf(totvol);
+ if (r_volume) {
+ *r_volume = fabsf(totvol);
}
- if (r_com) {
- /* Note: Factor 1/4 is applied once for all vertices here.
+ if (r_center) {
+ /* Note: Factor 1/3 is applied once for all vertices here.
* This also automatically negates the vector if totvol is negative.
*/
if (totvol != 0.0f)
- mul_v3_fl(r_com, 0.25f / totvol);
+ mul_v3_fl(r_center, (1.0f / 3.0f) / totvol);
}
}
@@ -1312,6 +2310,7 @@ void BKE_mesh_loops_to_tessdata(CustomData *fdata, CustomData *ldata, CustomData
const bool hasPCol = CustomData_has_layer(ldata, CD_PREVIEW_MLOOPCOL);
const bool hasOrigSpace = CustomData_has_layer(ldata, CD_ORIGSPACE_MLOOP);
const bool hasLoopNormal = CustomData_has_layer(ldata, CD_NORMAL);
+ const bool hasLoopTangent = CustomData_has_layer(ldata, CD_TANGENT);
int findex, i, j;
const int *pidx;
unsigned int (*lidx)[4];
@@ -1376,17 +2375,65 @@ void BKE_mesh_loops_to_tessdata(CustomData *fdata, CustomData *ldata, CustomData
}
}
}
+
+ if (hasLoopTangent) {
+ /* need to do for all uv maps at some point */
+ float (*ftangents)[4] = CustomData_get_layer(fdata, CD_TANGENT);
+ float (*ltangents)[4] = CustomData_get_layer(ldata, CD_TANGENT);
+
+ for (findex = 0, pidx = polyindices, lidx = loopindices;
+ findex < num_faces;
+ pidx++, lidx++, findex++)
+ {
+ int nverts = (mface ? mface[findex].v4 : (*lidx)[3]) ? 4 : 3;
+ for (j = nverts; j--;) {
+ copy_v4_v4(ftangents[findex * 4 + j], ltangents[(*lidx)[j]]);
+ }
+ }
+ }
+}
+
+void BKE_mesh_tangent_loops_to_tessdata(CustomData *fdata, CustomData *ldata, MFace *mface,
+ int *polyindices, unsigned int (*loopindices)[4], const int num_faces)
+{
+ /* Note: performances are sub-optimal when we get a NULL mface, we could be ~25% quicker with dedicated code...
+ * Issue is, unless having two different functions with nearly the same code, there's not much ways to solve
+ * this. Better imho to live with it for now. :/ --mont29
+ */
+ const bool hasLoopTangent = CustomData_has_layer(ldata, CD_TANGENT);
+ int findex, j;
+ const int *pidx;
+ unsigned int (*lidx)[4];
+
+ if (hasLoopTangent) {
+ /* need to do for all uv maps at some point */
+ float (*ftangents)[4] = CustomData_get_layer(fdata, CD_TANGENT);
+ float (*ltangents)[4] = CustomData_get_layer(ldata, CD_TANGENT);
+
+ for (findex = 0, pidx = polyindices, lidx = loopindices;
+ findex < num_faces;
+ pidx++, lidx++, findex++)
+ {
+ int nverts = (mface ? mface[findex].v4 : (*lidx)[3]) ? 4 : 3;
+ for (j = nverts; j--;) {
+ copy_v4_v4(ftangents[findex * 4 + j], ltangents[(*lidx)[j]]);
+ }
+ }
+ }
}
/**
* Recreate tessellation.
*
- * \param do_face_nor_copy controls whether the normals from the poly are copied to the tessellated faces.
+ * \param do_face_nor_copy: Controls whether the normals from the poly are copied to the tessellated faces.
*
* \return number of tessellation faces.
*/
-int BKE_mesh_recalc_tessellation(CustomData *fdata, CustomData *ldata, CustomData *pdata,
- MVert *mvert, int totface, int totloop, int totpoly, const bool do_face_nor_cpy)
+int BKE_mesh_recalc_tessellation(
+ CustomData *fdata, CustomData *ldata, CustomData *pdata,
+ MVert *mvert,
+ int totface, int totloop, int totpoly,
+ const bool do_face_nor_copy)
{
/* use this to avoid locking pthread for _every_ polygon
* and calling the fill function */
@@ -1397,7 +2444,7 @@ int BKE_mesh_recalc_tessellation(CustomData *fdata, CustomData *ldata, CustomDat
/* We abuse MFace->edcode to tag quad faces. See below for details. */
#define TESSFACE_IS_QUAD 1
- const int looptris_tot = poly_to_tri_count(totpoly, totloop);
+ const int looptri_num = poly_to_tri_count(totpoly, totloop);
MPoly *mp, *mpoly;
MLoop *ml, *mloop;
@@ -1414,9 +2461,9 @@ int BKE_mesh_recalc_tessellation(CustomData *fdata, CustomData *ldata, CustomDat
/* allocate the length of totfaces, avoid many small reallocs,
* if all faces are tri's it will be correct, quads == 2x allocs */
/* take care. we are _not_ calloc'ing so be sure to initialize each field */
- mface_to_poly_map = MEM_mallocN(sizeof(*mface_to_poly_map) * (size_t)looptris_tot, __func__);
- mface = MEM_mallocN(sizeof(*mface) * (size_t)looptris_tot, __func__);
- lindices = MEM_mallocN(sizeof(*lindices) * (size_t)looptris_tot, __func__);
+ mface_to_poly_map = MEM_mallocN(sizeof(*mface_to_poly_map) * (size_t)looptri_num, __func__);
+ mface = MEM_mallocN(sizeof(*mface) * (size_t)looptri_num, __func__);
+ lindices = MEM_mallocN(sizeof(*lindices) * (size_t)looptri_num, __func__);
mface_index = 0;
mp = mpoly;
@@ -1512,7 +2559,7 @@ int BKE_mesh_recalc_tessellation(CustomData *fdata, CustomData *ldata, CustomDat
zero_v3(normal);
- /* calc normal */
+ /* calc normal, flipped: to get a positive 2d cross product */
ml = mloop + mp_loopstart;
co_prev = mvert[ml[mp_totloop - 1].v].co;
for (j = 0; j < mp_totloop; j++, ml++) {
@@ -1525,14 +2572,14 @@ int BKE_mesh_recalc_tessellation(CustomData *fdata, CustomData *ldata, CustomDat
}
/* project verts to 2d */
- axis_dominant_v3_to_m3(axis_mat, normal);
+ axis_dominant_v3_to_m3_negate(axis_mat, normal);
ml = mloop + mp_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, mp_totloop, -1, tris, arena);
+ BLI_polyfill_calc_arena((const float (*)[2])projverts, mp_totloop, 1, tris, arena);
/* apply fill */
for (j = 0; j < totfilltri; j++) {
@@ -1547,11 +2594,6 @@ int BKE_mesh_recalc_tessellation(CustomData *fdata, CustomData *ldata, CustomDat
l2 = mp_loopstart + tri[1];
l3 = mp_loopstart + tri[2];
- /* sort loop indices to ensure winding is correct */
- if (l1 > l2) SWAP(unsigned int, l1, l2);
- if (l2 > l3) SWAP(unsigned int, l2, l3);
- if (l1 > l2) SWAP(unsigned int, l1, l2);
-
mf->v1 = mloop[l1].v;
mf->v2 = mloop[l2].v;
mf->v3 = mloop[l3].v;
@@ -1581,10 +2623,10 @@ int BKE_mesh_recalc_tessellation(CustomData *fdata, CustomData *ldata, CustomDat
CustomData_free(fdata, totface);
totface = mface_index;
- BLI_assert(totface <= looptris_tot);
+ BLI_assert(totface <= looptri_num);
/* not essential but without this we store over-alloc'd memory in the CustomData layers */
- if (LIKELY(looptris_tot != totface)) {
+ if (LIKELY(looptri_num != totface)) {
mface = MEM_reallocN(mface, sizeof(*mface) * (size_t)totface);
mface_to_poly_map = MEM_reallocN(mface_to_poly_map, sizeof(*mface_to_poly_map) * (size_t)totface);
}
@@ -1596,7 +2638,7 @@ int BKE_mesh_recalc_tessellation(CustomData *fdata, CustomData *ldata, CustomDat
CustomData_add_layer(fdata, CD_ORIGINDEX, CD_ASSIGN, mface_to_poly_map, totface);
CustomData_from_bmeshpoly(fdata, pdata, ldata, totface);
- if (do_face_nor_cpy) {
+ if (do_face_nor_copy) {
/* If polys have a normals layer, copying that to faces can help
* avoid the need to recalculate normals later */
if (CustomData_has_layer(pdata, CD_NORMAL)) {
@@ -1643,6 +2685,137 @@ int BKE_mesh_recalc_tessellation(CustomData *fdata, CustomData *ldata, CustomDat
}
+/**
+ * Calculate tessellation into #MLoopTri which exist only for this purpose.
+ */
+void BKE_mesh_recalc_looptri(
+ const MLoop *mloop, const MPoly *mpoly,
+ const MVert *mvert,
+ int totloop, int totpoly,
+ MLoopTri *mlooptri)
+{
+ /* use this to avoid locking pthread for _every_ polygon
+ * and calling the fill function */
+
+#define USE_TESSFACE_SPEEDUP
+
+ const MPoly *mp;
+ const MLoop *ml;
+ MLoopTri *mlt;
+ MemArena *arena = NULL;
+ int poly_index, mlooptri_index;
+ unsigned int j;
+
+ mlooptri_index = 0;
+ mp = mpoly;
+ for (poly_index = 0; poly_index < totpoly; poly_index++, mp++) {
+ const unsigned int mp_loopstart = (unsigned int)mp->loopstart;
+ const unsigned int mp_totloop = (unsigned int)mp->totloop;
+ unsigned int l1, l2, l3;
+ if (mp_totloop < 3) {
+ /* do nothing */
+ }
+
+#ifdef USE_TESSFACE_SPEEDUP
+
+#define ML_TO_MLT(i1, i2, i3) { \
+ mlt = &mlooptri[mlooptri_index]; \
+ l1 = mp_loopstart + i1; \
+ l2 = mp_loopstart + i2; \
+ l3 = mp_loopstart + i3; \
+ ARRAY_SET_ITEMS(mlt->tri, l1, l2, l3); \
+ mlt->poly = (unsigned int)poly_index; \
+ } ((void)0)
+
+ else if (mp_totloop == 3) {
+ ML_TO_MLT(0, 1, 2);
+ mlooptri_index++;
+ }
+ else if (mp_totloop == 4) {
+ ML_TO_MLT(0, 1, 2);
+ mlooptri_index++;
+ ML_TO_MLT(0, 2, 3);
+ mlooptri_index++;
+ }
+#endif /* USE_TESSFACE_SPEEDUP */
+ else {
+ const float *co_curr, *co_prev;
+
+ float normal[3];
+
+ float axis_mat[3][3];
+ float (*projverts)[2];
+ unsigned int (*tris)[3];
+
+ const unsigned int totfilltri = mp_totloop - 2;
+
+ if (UNLIKELY(arena == NULL)) {
+ arena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__);
+ }
+
+ tris = BLI_memarena_alloc(arena, sizeof(*tris) * (size_t)totfilltri);
+ projverts = BLI_memarena_alloc(arena, sizeof(*projverts) * (size_t)mp_totloop);
+
+ zero_v3(normal);
+
+ /* calc normal, flipped: to get a positive 2d cross product */
+ ml = mloop + mp_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;
+ }
+ if (UNLIKELY(normalize_v3(normal) == 0.0f)) {
+ normal[2] = 1.0f;
+ }
+
+ /* project verts to 2d */
+ axis_dominant_v3_to_m3_negate(axis_mat, normal);
+
+ ml = mloop + mp_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, mp_totloop, 1, tris, arena);
+
+ /* apply fill */
+ for (j = 0; j < totfilltri; j++) {
+ unsigned int *tri = tris[j];
+
+ mlt = &mlooptri[mlooptri_index];
+
+ /* set loop indices, transformed to vert indices later */
+ l1 = mp_loopstart + tri[0];
+ l2 = mp_loopstart + tri[1];
+ l3 = mp_loopstart + tri[2];
+
+ ARRAY_SET_ITEMS(mlt->tri, l1, l2, l3);
+ mlt->poly = (unsigned int)poly_index;
+
+ mlooptri_index++;
+ }
+
+ BLI_memarena_clear(arena);
+ }
+ }
+
+ if (arena) {
+ BLI_memarena_free(arena);
+ arena = NULL;
+ }
+
+ BLI_assert(mlooptri_index == poly_to_tri_count(totpoly, totloop));
+ UNUSED_VARS_NDEBUG(totloop);
+
+#undef USE_TESSFACE_SPEEDUP
+#undef ML_TO_MLT
+}
+
+/* -------------------------------------------------------------------- */
+
+
#ifdef USE_BMESH_SAVE_AS_COMPAT
/**
@@ -2074,7 +3247,7 @@ void BKE_mesh_flush_hidden_from_polys_ex(MVert *mvert,
j = mp->totloop;
for (ml = &mloop[mp->loopstart]; j--; ml++) {
mvert[ml->v].flag &= (char)~ME_HIDE;
- medge[ml->e].flag &= (char)~ME_HIDE;
+ medge[ml->e].flag &= (short)~ME_HIDE;
}
}
}
diff --git a/source/blender/blenkernel/intern/mesh_mapping.c b/source/blender/blenkernel/intern/mesh_mapping.c
index 82065750791..cf4c49a9244 100644
--- a/source/blender/blenkernel/intern/mesh_mapping.c
+++ b/source/blender/blenkernel/intern/mesh_mapping.c
@@ -30,12 +30,16 @@
#include "MEM_guardedalloc.h"
#include "DNA_meshdata_types.h"
+#include "DNA_vec_types.h"
+#include "BLI_buffer.h"
#include "BLI_utildefines.h"
+#include "BLI_bitmap.h"
#include "BLI_math.h"
#include "BKE_mesh_mapping.h"
#include "BKE_customdata.h"
+#include "BLI_memarena.h"
#include "BLI_strict_flags.h"
@@ -50,8 +54,10 @@
/* this replaces the non bmesh function (in trunk) which takes MTFace's, if we ever need it back we could
* but for now this replaces it because its unused. */
-UvVertMap *BKE_mesh_uv_vert_map_create(struct MPoly *mpoly, struct MLoop *mloop, struct MLoopUV *mloopuv,
- unsigned int totpoly, unsigned int totvert, int selected, float *limit)
+UvVertMap *BKE_mesh_uv_vert_map_create(
+ struct MPoly *mpoly, struct MLoop *mloop, struct MLoopUV *mloopuv,
+ unsigned int totpoly, unsigned int totvert,
+ const float limit[2], const bool selected, const bool use_winding)
{
UvVertMap *vmap;
UvMapVert *buf;
@@ -59,6 +65,9 @@ UvVertMap *BKE_mesh_uv_vert_map_create(struct MPoly *mpoly, struct MLoop *mloop,
unsigned int a;
int i, totuv, nverts;
+ bool *winding = NULL;
+ BLI_buffer_declare_static(vec2f, tf_uv_buf, BLI_BUFFER_NOP, 32);
+
totuv = 0;
/* generate UvMapVert array */
@@ -71,11 +80,11 @@ UvVertMap *BKE_mesh_uv_vert_map_create(struct MPoly *mpoly, struct MLoop *mloop,
return NULL;
vmap = (UvVertMap *)MEM_callocN(sizeof(*vmap), "UvVertMap");
- if (!vmap)
- return NULL;
-
- vmap->vert = (UvMapVert **)MEM_callocN(sizeof(*vmap->vert) * totvert, "UvMapVert*");
buf = vmap->buf = (UvMapVert *)MEM_callocN(sizeof(*vmap->buf) * (size_t)totuv, "UvMapVert");
+ vmap->vert = (UvMapVert **)MEM_callocN(sizeof(*vmap->vert) * totvert, "UvMapVert*");
+ if (use_winding) {
+ winding = MEM_callocN(sizeof(*winding) * totpoly, "winding");
+ }
if (!vmap->vert || !vmap->buf) {
BKE_mesh_uv_vert_map_free(vmap);
@@ -85,6 +94,12 @@ UvVertMap *BKE_mesh_uv_vert_map_create(struct MPoly *mpoly, struct MLoop *mloop,
mp = mpoly;
for (a = 0; a < totpoly; a++, mp++) {
if (!selected || (!(mp->flag & ME_HIDE) && (mp->flag & ME_FACE_SEL))) {
+ float (*tf_uv)[2] = NULL;
+
+ if (use_winding) {
+ tf_uv = (float (*)[2])BLI_buffer_resize_data(&tf_uv_buf, vec2f, mp->totloop);
+ }
+
nverts = mp->totloop;
for (i = 0; i < nverts; i++) {
@@ -93,8 +108,17 @@ UvVertMap *BKE_mesh_uv_vert_map_create(struct MPoly *mpoly, struct MLoop *mloop,
buf->separate = 0;
buf->next = vmap->vert[mloop[mp->loopstart + i].v];
vmap->vert[mloop[mp->loopstart + i].v] = buf;
+
+ if (use_winding) {
+ copy_v2_v2(tf_uv[i], mloopuv[mpoly[a].loopstart + i].uv);
+ }
+
buf++;
}
+
+ if (use_winding) {
+ winding[a] = cross_poly_v2((const float (*)[2])tf_uv, (unsigned int)nverts) > 0;
+ }
}
}
@@ -121,7 +145,9 @@ UvVertMap *BKE_mesh_uv_vert_map_create(struct MPoly *mpoly, struct MLoop *mloop,
sub_v2_v2v2(uvdiff, uv2, uv);
- if (fabsf(uv[0] - uv2[0]) < limit[0] && fabsf(uv[1] - uv2[1]) < limit[1]) {
+ if (fabsf(uv[0] - uv2[0]) < limit[0] && fabsf(uv[1] - uv2[1]) < limit[1] &&
+ (!use_winding || winding[iterv->f] == winding[v->f]))
+ {
if (lastv) lastv->next = next;
else vlist = next;
iterv->next = newvlist;
@@ -139,6 +165,12 @@ UvVertMap *BKE_mesh_uv_vert_map_create(struct MPoly *mpoly, struct MLoop *mloop,
vmap->vert[a] = newvlist;
}
+ if (use_winding) {
+ MEM_freeN(winding);
+ }
+
+ BLI_buffer_free(&tf_uv_buf);
+
return vmap;
}
@@ -156,18 +188,23 @@ void BKE_mesh_uv_vert_map_free(UvVertMap *vmap)
}
}
-/* Generates a map where the key is the vertex and the value is a list
- * of polys that use that vertex as a corner. The lists are allocated
- * from one memory pool. */
-void BKE_mesh_vert_poly_map_create(MeshElemMap **r_map, int **r_mem,
- const MPoly *mpoly, const MLoop *mloop,
- int totvert, int totpoly, int totloop)
+/**
+ * Generates a map where the key is the vertex and the value is a list
+ * of polys or loops that use that vertex as a corner. The lists are allocated
+ * from one memory pool.
+ *
+ * Wrapped by #BKE_mesh_vert_poly_map_create & BKE_mesh_vert_loop_map_create
+ */
+static void mesh_vert_poly_or_loop_map_create(
+ MeshElemMap **r_map, int **r_mem,
+ const MPoly *mpoly, const MLoop *mloop,
+ int totvert, int totpoly, int totloop, const bool do_loops)
{
- MeshElemMap *map = MEM_callocN(sizeof(MeshElemMap) * (size_t)totvert, "vert poly map");
+ MeshElemMap *map = MEM_callocN(sizeof(MeshElemMap) * (size_t)totvert, __func__);
int *indices, *index_iter;
int i, j;
- indices = index_iter = MEM_mallocN(sizeof(int) * (size_t)totloop, "vert poly map mem");
+ indices = index_iter = MEM_mallocN(sizeof(int) * (size_t)totloop, __func__);
/* Count number of polys for each vertex */
for (i = 0; i < totpoly; i++) {
@@ -193,7 +230,7 @@ void BKE_mesh_vert_poly_map_create(MeshElemMap **r_map, int **r_mem,
for (j = 0; j < p->totloop; j++) {
unsigned int v = mloop[p->loopstart + j].v;
- map[v].indices[map[v].count] = i;
+ map[v].indices[map[v].count] = do_loops ? p->loopstart + j : i;
map[v].count++;
}
}
@@ -202,9 +239,32 @@ void BKE_mesh_vert_poly_map_create(MeshElemMap **r_map, int **r_mem,
*r_mem = indices;
}
-/* Generates a map where the key is the vertex and the value is a list
- * of edges that use that vertex as an endpoint. The lists are allocated
- * from one memory pool. */
+/**
+ * Generates a map where the key is the vertex and the value is a list of polys that use that vertex as a corner.
+ * The lists are allocated from one memory pool.
+ */
+void BKE_mesh_vert_poly_map_create(MeshElemMap **r_map, int **r_mem,
+ const MPoly *mpoly, const MLoop *mloop,
+ int totvert, int totpoly, int totloop)
+{
+ mesh_vert_poly_or_loop_map_create(r_map, r_mem, mpoly, mloop, totvert, totpoly, totloop, false);
+}
+
+/**
+ * Generates a map where the key is the vertex and the value is a list of loops that use that vertex as a corner.
+ * The lists are allocated from one memory pool.
+ */
+void BKE_mesh_vert_loop_map_create(MeshElemMap **r_map, int **r_mem,
+ const MPoly *mpoly, const MLoop *mloop,
+ int totvert, int totpoly, int totloop)
+{
+ mesh_vert_poly_or_loop_map_create(r_map, r_mem, mpoly, mloop, totvert, totpoly, totloop, true);
+}
+
+/**
+ * Generates a map where the key is the vertex and the value is a list of edges that use that vertex as an endpoint.
+ * The lists are allocated from one memory pool.
+ */
void BKE_mesh_vert_edge_map_create(MeshElemMap **r_map, int **r_mem,
const MEdge *medge, int totvert, int totedge)
{
@@ -244,6 +304,10 @@ void BKE_mesh_vert_edge_map_create(MeshElemMap **r_map, int **r_mem,
*r_mem = indices;
}
+/**
+ * Generates a map where the key is the edge and the value is a list of polygons that use that edge.
+ * The lists are allocated from one memory pool.
+ */
void BKE_mesh_edge_poly_map_create(MeshElemMap **r_map, int **r_mem,
const MEdge *UNUSED(medge), const int totedge,
const MPoly *mpoly, const int totpoly,
@@ -342,29 +406,65 @@ void BKE_mesh_origindex_map_create(MeshElemMap **r_map, int **r_mem,
*r_mem = indices;
}
-/** \} */
+/**
+ * A version of #BKE_mesh_origindex_map_create that takes a looptri array.
+ * Making a poly -> looptri map.
+ */
+void BKE_mesh_origindex_map_create_looptri(
+ MeshElemMap **r_map, int **r_mem,
+ const MPoly *mpoly, const int mpoly_num,
+ const MLoopTri *looptri, const int looptri_num)
+{
+ MeshElemMap *map = MEM_callocN(sizeof(MeshElemMap) * (size_t)mpoly_num, "poly-tessface map");
+ int *indices = MEM_mallocN(sizeof(int) * (size_t)looptri_num, "poly-tessface map mem");
+ int *index_step;
+ int i;
+
+ /* create offsets */
+ index_step = indices;
+ for (i = 0; i < mpoly_num; i++) {
+ map[i].indices = index_step;
+ index_step += ME_POLY_TRI_TOT(&mpoly[i]);
+ }
+ /* assign poly-tessface users */
+ for (i = 0; i < looptri_num; i++) {
+ MeshElemMap *map_ele = &map[looptri[i].poly];
+ map_ele->indices[map_ele->count++] = i;
+ }
+
+ *r_map = map;
+ *r_mem = indices;
+}
+
+/** \} */
/* -------------------------------------------------------------------- */
-/** \name Mesh Smooth Groups
+/** \name Mesh loops/poly islands.
+ * Used currently for UVs and 'smooth groups'.
* \{ */
/**
- * Calculate smooth groups from sharp edges.
- *
- * \param r_totgroup The total number of groups, 1 or more.
- * \return Polygon aligned array of group index values (bitflags if use_bitflags is true), starting at 1.
+ * Callback deciding whether the given poly/loop/edge define an island boundary or not.
*/
-int *BKE_mesh_calc_smoothgroups(const MEdge *medge, const int totedge,
- const MPoly *mpoly, const int totpoly,
- const MLoop *mloop, const int totloop,
- int *r_totgroup, const bool use_bitflags)
+typedef bool (*MeshRemap_CheckIslandBoundary)(
+ const struct MPoly *mpoly, const struct MLoop *mloop, const struct MEdge *medge,
+ const int nbr_egde_users);
+
+static void poly_edge_loop_islands_calc(
+ const MEdge *medge, const int totedge, const MPoly *mpoly, const int totpoly,
+ const MLoop *mloop, const int totloop, MeshElemMap *edge_poly_map,
+ const bool use_bitflags, MeshRemap_CheckIslandBoundary edge_boundary_check,
+ int **r_poly_groups, int *r_totgroup, BLI_bitmap **r_edge_borders, int *r_totedgeborder)
{
int *poly_groups;
int *poly_stack;
+ BLI_bitmap *edge_borders = NULL;
+ int num_edgeborders = 0;
+
int poly_prev = 0;
const int temp_poly_group_id = 3; /* Placeholder value. */
const int poly_group_id_overflowed = 5; /* Group we could not find any available bit, will be reset to 0 at end */
@@ -372,18 +472,27 @@ int *BKE_mesh_calc_smoothgroups(const MEdge *medge, const int totedge,
bool group_id_overflow = false;
/* map vars */
- MeshElemMap *edge_poly_map;
- int *edge_poly_mem;
+ int *edge_poly_mem = NULL;
if (totpoly == 0) {
*r_totgroup = 0;
- return NULL;
+ *r_poly_groups = NULL;
+ if (r_edge_borders) {
+ *r_edge_borders = NULL;
+ *r_totedgeborder = 0;
+ }
+ return;
}
- BKE_mesh_edge_poly_map_create(&edge_poly_map, &edge_poly_mem,
- medge, totedge,
- mpoly, totpoly,
- mloop, totloop);
+ if (r_edge_borders) {
+ edge_borders = BLI_BITMAP_NEW(totedge, __func__);
+ *r_totedgeborder = 0;
+ }
+
+ if (!edge_poly_map) {
+ BKE_mesh_edge_poly_map_create(&edge_poly_map, &edge_poly_mem,
+ medge, totedge, mpoly, totpoly, mloop, totloop);
+ }
poly_groups = MEM_callocN(sizeof(int) * (size_t)totpoly, __func__);
poly_stack = MEM_mallocN(sizeof(int) * (size_t)totpoly, __func__);
@@ -424,10 +533,12 @@ int *BKE_mesh_calc_smoothgroups(const MEdge *medge, const int totedge,
mp = &mpoly[poly];
for (ml = &mloop[mp->loopstart], j = mp->totloop; j--; ml++) {
/* loop over poly users */
- const MeshElemMap *map_ele = &edge_poly_map[ml->e];
+ const int me_idx = (int)ml->e;
+ const MEdge *me = &medge[me_idx];
+ const MeshElemMap *map_ele = &edge_poly_map[me_idx];
const int *p = map_ele->indices;
int i = map_ele->count;
- if (!(medge[ml->e].flag & ME_SHARP)) {
+ if (!edge_boundary_check(mp, ml, me, i)) {
for (; i--; p++) {
/* if we meet other non initialized its a bug */
BLI_assert(ELEM(poly_groups[*p], 0, poly_group_id));
@@ -438,14 +549,20 @@ int *BKE_mesh_calc_smoothgroups(const MEdge *medge, const int totedge,
}
}
}
- else if (use_bitflags) {
- /* Find contiguous smooth groups already assigned, these are the values we can't reuse! */
- for (; i--; p++) {
- int bit = poly_groups[*p];
- if (!ELEM(bit, 0, poly_group_id, poly_group_id_overflowed) &&
- !(bit_poly_group_mask & bit))
- {
- bit_poly_group_mask |= bit;
+ else {
+ if (edge_borders && !BLI_BITMAP_TEST(edge_borders, me_idx)) {
+ BLI_BITMAP_ENABLE(edge_borders, me_idx);
+ num_edgeborders++;
+ }
+ if (use_bitflags) {
+ /* Find contiguous smooth groups already assigned, these are the values we can't reuse! */
+ for (; i--; p++) {
+ int bit = poly_groups[*p];
+ if (!ELEM(bit, 0, poly_group_id, poly_group_id_overflowed) &&
+ !(bit_poly_group_mask & bit))
+ {
+ bit_poly_group_mask |= bit;
+ }
}
}
}
@@ -482,6 +599,11 @@ int *BKE_mesh_calc_smoothgroups(const MEdge *medge, const int totedge,
}
}
+ if (use_bitflags) {
+ /* used bits are zero-based. */
+ tot_group++;
+ }
+
if (UNLIKELY(group_id_overflow)) {
int i = totpoly, *gid = poly_groups;
for (; i--; gid++) {
@@ -489,14 +611,278 @@ int *BKE_mesh_calc_smoothgroups(const MEdge *medge, const int totedge,
*gid = 0;
}
}
+ /* Using 0 as group id adds one more group! */
+ tot_group++;
}
- MEM_freeN(edge_poly_map);
- MEM_freeN(edge_poly_mem);
+ if (edge_poly_mem) {
+ MEM_freeN(edge_poly_map);
+ MEM_freeN(edge_poly_mem);
+ }
MEM_freeN(poly_stack);
- *r_totgroup = tot_group + 1;
+ *r_totgroup = tot_group;
+ *r_poly_groups = poly_groups;
+ if (r_edge_borders) {
+ *r_edge_borders = edge_borders;
+ *r_totedgeborder = num_edgeborders;
+ }
+}
+
+static bool poly_is_island_boundary_smooth_cb(
+ const MPoly *mp, const MLoop *UNUSED(ml), const MEdge *me, const int nbr_egde_users)
+{
+ /* Edge is sharp if its poly is sharp, or edge itself is sharp, or edge is not used by exactly two polygons. */
+ return (!(mp->flag & ME_SMOOTH) || (me->flag & ME_SHARP) || (nbr_egde_users != 2));
+}
+
+/**
+ * Calculate smooth groups from sharp edges.
+ *
+ * \param r_totgroup The total number of groups, 1 or more.
+ * \return Polygon aligned array of group index values (bitflags if use_bitflags is true), starting at 1
+ * (0 being used as 'invalid' flag).
+ * Note it's callers's responsibility to MEM_freeN returned array.
+ */
+int *BKE_mesh_calc_smoothgroups(const MEdge *medge, const int totedge,
+ const MPoly *mpoly, const int totpoly,
+ const MLoop *mloop, const int totloop,
+ int *r_totgroup, const bool use_bitflags)
+{
+ int *poly_groups = NULL;
+
+ poly_edge_loop_islands_calc(
+ medge, totedge, mpoly, totpoly, mloop, totloop, NULL, use_bitflags,
+ poly_is_island_boundary_smooth_cb, &poly_groups, r_totgroup, NULL, NULL);
return poly_groups;
}
+
+#define MISLAND_DEFAULT_BUFSIZE 64
+
+void BKE_mesh_loop_islands_init(
+ MeshIslandStore *island_store,
+ const short item_type, const int items_num, const short island_type, const short innercut_type)
+{
+ MemArena *mem = island_store->mem;
+
+ if (mem == NULL) {
+ mem = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__);
+ island_store->mem = mem;
+ }
+ /* else memarena should be cleared */
+
+ BLI_assert(ELEM(item_type, MISLAND_TYPE_VERT, MISLAND_TYPE_EDGE, MISLAND_TYPE_POLY, MISLAND_TYPE_LOOP));
+ BLI_assert(ELEM(island_type, MISLAND_TYPE_VERT, MISLAND_TYPE_EDGE, MISLAND_TYPE_POLY, MISLAND_TYPE_LOOP));
+
+ island_store->item_type = item_type;
+ island_store->items_to_islands_num = items_num;
+ island_store->items_to_islands = BLI_memarena_alloc(mem, sizeof(*island_store->items_to_islands) * (size_t)items_num);
+
+ island_store->island_type = island_type;
+ island_store->islands_num_alloc = MISLAND_DEFAULT_BUFSIZE;
+ island_store->islands = BLI_memarena_alloc(mem, sizeof(*island_store->islands) * island_store->islands_num_alloc);
+
+ island_store->innercut_type = innercut_type;
+ island_store->innercuts = BLI_memarena_alloc(mem, sizeof(*island_store->innercuts) * island_store->islands_num_alloc);
+}
+
+void BKE_mesh_loop_islands_clear(MeshIslandStore *island_store)
+{
+ island_store->item_type = MISLAND_TYPE_NONE;
+ island_store->items_to_islands_num = 0;
+ island_store->items_to_islands = NULL;
+
+ island_store->island_type = MISLAND_TYPE_NONE;
+ island_store->islands_num = 0;
+ island_store->islands = NULL;
+
+ island_store->innercut_type = MISLAND_TYPE_NONE;
+ island_store->innercuts = NULL;
+
+ if (island_store->mem) {
+ BLI_memarena_clear(island_store->mem);
+ }
+
+ island_store->islands_num_alloc = 0;
+}
+
+void BKE_mesh_loop_islands_free(MeshIslandStore *island_store)
+{
+ if (island_store->mem) {
+ BLI_memarena_free(island_store->mem);
+ island_store->mem = NULL;
+ }
+}
+
+void BKE_mesh_loop_islands_add(
+ MeshIslandStore *island_store, const int item_num, int *items_indices,
+ const int num_island_items, int *island_item_indices,
+ const int num_innercut_items, int *innercut_item_indices)
+{
+ MemArena *mem = island_store->mem;
+
+ MeshElemMap *isld, *innrcut;
+ const int curr_island_idx = island_store->islands_num++;
+ const size_t curr_num_islands = (size_t)island_store->islands_num;
+ int i = item_num;
+
+ while (i--) {
+ island_store->items_to_islands[items_indices[i]] = curr_island_idx;
+ }
+
+ if (UNLIKELY(curr_num_islands > island_store->islands_num_alloc)) {
+ MeshElemMap **islds, **innrcuts;
+
+ island_store->islands_num_alloc *= 2;
+ islds = BLI_memarena_alloc(mem, sizeof(*islds) * island_store->islands_num_alloc);
+ memcpy(islds, island_store->islands, sizeof(*islds) * (curr_num_islands - 1));
+ island_store->islands = islds;
+
+ innrcuts = BLI_memarena_alloc(mem, sizeof(*innrcuts) * island_store->islands_num_alloc);
+ memcpy(innrcuts, island_store->innercuts, sizeof(*innrcuts) * (curr_num_islands - 1));
+ island_store->innercuts = innrcuts;
+ }
+
+ island_store->islands[curr_island_idx] = isld = BLI_memarena_alloc(mem, sizeof(*isld));
+ isld->count = num_island_items;
+ isld->indices = BLI_memarena_alloc(mem, sizeof(*isld->indices) * (size_t)num_island_items);
+ memcpy(isld->indices, island_item_indices, sizeof(*isld->indices) * (size_t)num_island_items);
+
+ island_store->innercuts[curr_island_idx] = innrcut = BLI_memarena_alloc(mem, sizeof(*innrcut));
+ innrcut->count = num_innercut_items;
+ innrcut->indices = BLI_memarena_alloc(mem, sizeof(*innrcut->indices) * (size_t)num_innercut_items);
+ memcpy(innrcut->indices, innercut_item_indices, sizeof(*innrcut->indices) * (size_t)num_innercut_items);
+}
+
+/* TODO: I'm not sure edge seam flag is enough to define UV islands? Maybe we should also consider UVmaps values
+ * themselves (i.e. different UV-edges for a same mesh-edge => boundary edge too?).
+ * Would make things much more complex though, and each UVMap would then need its own mesh mapping,
+ * not sure we want that at all!
+ */
+static bool mesh_check_island_boundary_uv(
+ const MPoly *UNUSED(mp), const MLoop *UNUSED(ml), const MEdge *me, const int UNUSED(nbr_egde_users))
+{
+ /* Edge is UV boundary if tagged as seam. */
+ return (me->flag & ME_SEAM) != 0;
+}
+
+/**
+ * Calculate UV islands.
+ *
+ * \note Currently we only consider edges tagges as seams as UV boundaries. This has the advantages of simplicity,
+ * and being valid/common to all UV maps. However, it means actual UV islands whithout matching UV seams
+ * will not be handled correctly...
+ *
+ * \note All this could be optimized...
+ * Not sure it would be worth the more complex code, though, those loops are supposed to be really quick to do...
+ */
+bool BKE_mesh_calc_islands_loop_poly_uv(
+ MVert *UNUSED(verts), const int UNUSED(totvert),
+ MEdge *edges, const int totedge,
+ MPoly *polys, const int totpoly,
+ MLoop *loops, const int totloop,
+ MeshIslandStore *r_island_store)
+{
+ int *poly_groups = NULL;
+ int num_poly_groups;
+
+ /* map vars */
+ MeshElemMap *edge_poly_map;
+ int *edge_poly_mem;
+
+ int *poly_indices;
+ int *loop_indices;
+ int num_pidx, num_lidx;
+
+ /* Those are used to detect 'inner cuts', i.e. edges that are borders, and yet have two or more polys of
+ * a same group using them (typical case: seam used to unwrap properly a cylinder). */
+ BLI_bitmap *edge_borders = NULL;
+ int num_edge_borders = 0;
+ char *edge_border_count = NULL;
+ int *edge_innercut_indices = NULL;
+ int num_einnercuts = 0;
+
+ int grp_idx, p_idx, pl_idx, l_idx;
+
+ BKE_mesh_loop_islands_clear(r_island_store);
+ BKE_mesh_loop_islands_init(r_island_store, MISLAND_TYPE_LOOP, totloop, MISLAND_TYPE_POLY, MISLAND_TYPE_EDGE);
+
+ BKE_mesh_edge_poly_map_create(&edge_poly_map, &edge_poly_mem,
+ edges, totedge, polys, totpoly, loops, totloop);
+
+ poly_edge_loop_islands_calc(
+ edges, totedge, polys, totpoly, loops, totloop, edge_poly_map, false,
+ mesh_check_island_boundary_uv, &poly_groups, &num_poly_groups, &edge_borders, &num_edge_borders);
+
+ if (!num_poly_groups) {
+ /* Should never happen... */
+ MEM_freeN(edge_poly_map);
+ MEM_freeN(edge_poly_mem);
+
+ if (edge_borders) {
+ MEM_freeN(edge_borders);
+ }
+ return false;
+ }
+
+ if (num_edge_borders) {
+ edge_border_count = MEM_mallocN(sizeof(*edge_border_count) * (size_t)totedge, __func__);
+ edge_innercut_indices = MEM_mallocN(sizeof(*edge_innercut_indices) * (size_t)num_edge_borders, __func__);
+ }
+
+ poly_indices = MEM_mallocN(sizeof(*poly_indices) * (size_t)totpoly, __func__);
+ loop_indices = MEM_mallocN(sizeof(*loop_indices) * (size_t)totloop, __func__);
+
+ /* Note: here we ignore '0' invalid group - this should *never* happen in this case anyway? */
+ for (grp_idx = 1; grp_idx <= num_poly_groups; grp_idx++) {
+ num_pidx = num_lidx = 0;
+ if (num_edge_borders) {
+ num_einnercuts = 0;
+ memset(edge_border_count, 0, sizeof(*edge_border_count) * (size_t)totedge);
+ }
+
+ for (p_idx = 0; p_idx < totpoly; p_idx++) {
+ MPoly *mp;
+
+ if (poly_groups[p_idx] != grp_idx) {
+ continue;
+ }
+
+ mp = &polys[p_idx];
+ poly_indices[num_pidx++] = p_idx;
+ for (l_idx = mp->loopstart, pl_idx = 0; pl_idx < mp->totloop; l_idx++, pl_idx++) {
+ MLoop *ml = &loops[l_idx];
+ loop_indices[num_lidx++] = l_idx;
+ if (num_edge_borders && BLI_BITMAP_TEST(edge_borders, ml->e) && (edge_border_count[ml->e] < 2)) {
+ edge_border_count[ml->e]++;
+ if (edge_border_count[ml->e] == 2) {
+ edge_innercut_indices[num_einnercuts++] = (int)ml->e;
+ }
+ }
+ }
+ }
+
+ BKE_mesh_loop_islands_add(r_island_store, num_lidx, loop_indices, num_pidx, poly_indices,
+ num_einnercuts, edge_innercut_indices);
+ }
+
+ MEM_freeN(edge_poly_map);
+ MEM_freeN(edge_poly_mem);
+
+ MEM_freeN(poly_indices);
+ MEM_freeN(loop_indices);
+ MEM_freeN(poly_groups);
+
+ if (edge_borders) {
+ MEM_freeN(edge_borders);
+ }
+
+ if (num_edge_borders) {
+ MEM_freeN(edge_border_count);
+ MEM_freeN(edge_innercut_indices);
+ }
+ return true;
+}
+
/** \} */
diff --git a/source/blender/blenkernel/intern/mesh_remap.c b/source/blender/blenkernel/intern/mesh_remap.c
new file mode 100644
index 00000000000..c3b88b84b8b
--- /dev/null
+++ b/source/blender/blenkernel/intern/mesh_remap.c
@@ -0,0 +1,2275 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/blenkernel/intern/mesh_remap.c
+ * \ingroup bke
+ *
+ * Functions for mapping data between meshes.
+ */
+
+#include <limits.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_meshdata_types.h"
+
+#include "BLI_utildefines.h"
+#include "BLI_alloca.h"
+#include "BLI_astar.h"
+#include "BLI_bitmap.h"
+#include "BLI_math.h"
+#include "BLI_memarena.h"
+#include "BLI_polyfill2d.h"
+#include "BLI_rand.h"
+
+#include "BKE_bvhutils.h"
+#include "BKE_customdata.h"
+#include "BKE_DerivedMesh.h"
+#include "BKE_mesh.h"
+#include "BKE_mesh_mapping.h"
+#include "BKE_mesh_remap.h" /* own include */
+
+#include "BLI_strict_flags.h"
+
+
+/* -------------------------------------------------------------------- */
+
+/** \name Some generic helpers.
+ * \{ */
+
+static bool mesh_remap_bvhtree_query_nearest(
+ BVHTreeFromMesh *treedata, BVHTreeNearest *nearest,
+ const float co[3], const float max_dist_sq, float *r_hit_dist)
+{
+ /* Use local proximity heuristics (to reduce the nearest search). */
+ if (nearest->index != -1) {
+ nearest->dist_sq = min_ff(len_squared_v3v3(co, nearest->co), max_dist_sq);
+ }
+ else {
+ nearest->dist_sq = max_dist_sq;
+ }
+ /* Compute and store result. If invalid (-1 index), keep FLT_MAX dist. */
+ BLI_bvhtree_find_nearest(treedata->tree, co, nearest, treedata->nearest_callback, treedata);
+
+ if ((nearest->index != -1) && (nearest->dist_sq <= max_dist_sq)) {
+ *r_hit_dist = sqrtf(nearest->dist_sq);
+ return true;
+ }
+ else {
+ return false;
+ }
+}
+
+static bool mesh_remap_bvhtree_query_raycast(
+ BVHTreeFromMesh *treedata, BVHTreeRayHit *rayhit,
+ const float co[3], const float no[3], const float radius, const float max_dist, float *r_hit_dist)
+{
+ BVHTreeRayHit rayhit_tmp;
+ float inv_no[3];
+
+ rayhit->index = -1;
+ rayhit->dist = max_dist;
+ BLI_bvhtree_ray_cast(treedata->tree, co, no, radius, rayhit, treedata->raycast_callback, treedata);
+
+ /* Also cast in the other direction! */
+ rayhit_tmp = *rayhit;
+ negate_v3_v3(inv_no, no);
+ BLI_bvhtree_ray_cast(treedata->tree, co, inv_no, radius, &rayhit_tmp, treedata->raycast_callback, treedata);
+ if (rayhit_tmp.dist < rayhit->dist) {
+ *rayhit = rayhit_tmp;
+ }
+
+ if ((rayhit->index != -1) && (rayhit->dist <= max_dist)) {
+ *r_hit_dist = rayhit->dist;
+ return true;
+ }
+ else {
+ return false;
+ }
+}
+
+/** \} */
+
+/**
+ * \name Auto-match.
+ *
+ * Find transform of a mesh to get best match with another.
+ * \{ */
+
+/**
+ * Compute a value of the difference between both given meshes.
+ * The smaller the result, the better the match.
+ *
+ * We return the inverse of the average of the inversed shortest distance from each dst vertex to src ones.
+ * In other words, beyond a certain (relatively small) distance, all differences have more or less the same weight
+ * in final result, which allows to reduce influence of a few high differences, in favor of a global good matching.
+ */
+float BKE_mesh_remap_calc_difference_from_dm(
+ const SpaceTransform *space_transform, const MVert *verts_dst, const int numverts_dst, DerivedMesh *dm_src)
+{
+ BVHTreeFromMesh treedata = {NULL};
+ BVHTreeNearest nearest = {0};
+ float hit_dist;
+
+ float result = 0.0f;
+ int i;
+
+ bvhtree_from_mesh_verts(&treedata, dm_src, 0.0f, 2, 6);
+ nearest.index = -1;
+
+ for (i = 0; i < numverts_dst; i++) {
+ float tmp_co[3];
+
+ copy_v3_v3(tmp_co, verts_dst[i].co);
+
+ /* Convert the vertex to tree coordinates, if needed. */
+ if (space_transform) {
+ BLI_space_transform_apply(space_transform, tmp_co);
+ }
+
+ if (mesh_remap_bvhtree_query_nearest(&treedata, &nearest, tmp_co, FLT_MAX, &hit_dist)) {
+ result += 1.0f / (hit_dist + 1.0f);
+ }
+ else {
+ /* No source for this dest vertex! */
+ result += 1e-18f;
+ }
+ }
+
+ result = ((float)numverts_dst / result) - 1.0f;
+
+// printf("%s: Computed difference between meshes (the lower the better): %f\n", __func__, result);
+
+ return result;
+}
+
+/* This helper computes the eigen values & vectors for covariance matrix of all given vertices coordinates.
+ *
+ * Those vectors define the 'average ellipsoid' of the mesh (i.e. the 'best fitting' ellipsoid
+ * containing 50% of the vertices).
+ *
+ * Note that it will not perform fantastic in case two or more eigen values are equal (e.g. a cylinder or
+ * parallelepiped with a square section give two identical eigenvalues, a sphere or tetrahedron give
+ * three identical ones, etc.), since you cannot really define all axes in those cases. We default to dummy
+ * generated orthogonal vectors in this case, instead of using eigen vectors.
+ */
+static void mesh_calc_eigen_matrix(
+ const MVert *verts, const float (*vcos)[3], const int numverts, float r_mat[4][4])
+{
+ float center[3], covmat[3][3];
+ float eigen_val[3], eigen_vec[3][3];
+ float (*cos)[3] = NULL;
+
+ bool eigen_success;
+ int i;
+
+ if (verts) {
+ const MVert *mv;
+ float (*co)[3];
+
+ cos = MEM_mallocN(sizeof(*cos) * (size_t)numverts, __func__);
+ for (i = 0, co = cos, mv = verts; i < numverts; i++, co++, mv++) {
+ copy_v3_v3(*co, mv->co);
+ }
+ /* TODO(sergey): For until we officially drop all compilers which
+ * doesn't handle casting correct we use workaround to avoid explicit
+ * cast here.
+ */
+ vcos = (void *)cos;
+ }
+ unit_m4(r_mat);
+
+ /* Note: here we apply sample correction to covariance matrix, since we consider the vertices as a sample
+ * of the whole 'surface' population of our mesh... */
+ BLI_covariance_m3_v3n(vcos, numverts, true, covmat, center);
+
+ if (cos) {
+ MEM_freeN(cos);
+ }
+
+ eigen_success = BLI_eigen_solve_selfadjoint_m3((const float (*)[3])covmat, eigen_val, eigen_vec);
+ BLI_assert(eigen_success);
+ UNUSED_VARS_NDEBUG(eigen_success);
+
+ /* Special handling of cases where some eigen values are (nearly) identical. */
+ if (compare_ff_relative(eigen_val[0], eigen_val[1], FLT_EPSILON, 64)) {
+ if (compare_ff_relative(eigen_val[0], eigen_val[2], FLT_EPSILON, 64)) {
+ /* No preferred direction, that set of vertices has a spherical average,
+ * so we simply returned scaled/translated identity matrix (with no rotation). */
+ unit_m3(eigen_vec);
+ }
+ else {
+ /* Ellipsoid defined by eigen values/vectors has a spherical section,
+ * we can only define one axis from eigen_vec[2] (two others computed eigen vecs
+ * are not so nice for us here, they tend to 'randomly' rotate around valid one).
+ * Note that eigen vectors as returned by BLI_eigen_solve_selfadjoint_m3() are normalized. */
+ ortho_basis_v3v3_v3(eigen_vec[0], eigen_vec[1], eigen_vec[2]);
+ }
+ }
+ else if (compare_ff_relative(eigen_val[0], eigen_val[2], FLT_EPSILON, 64)) {
+ /* Same as above, but with eigen_vec[1] as valid axis. */
+ ortho_basis_v3v3_v3(eigen_vec[2], eigen_vec[0], eigen_vec[1]);
+ }
+ else if (compare_ff_relative(eigen_val[1], eigen_val[2], FLT_EPSILON, 64)) {
+ /* Same as above, but with eigen_vec[0] as valid axis. */
+ ortho_basis_v3v3_v3(eigen_vec[1], eigen_vec[2], eigen_vec[0]);
+ }
+
+ for (i = 0; i < 3; i++) {
+ float evi = eigen_val[i];
+
+ /* Protect against 1D/2D degenerated cases! */
+ /* Note: not sure why we need square root of eigen values here (which are equivalent to singular values,
+ * as far as I have understood), but it seems to heavily reduce (if not completely nullify)
+ * the error due to non-uniform scalings... */
+ evi = (evi < 1e-6f && evi > -1e-6f) ? ((evi < 0.0f) ? -1e-3f : 1e-3f) : sqrtf_signed(evi);
+ mul_v3_fl(eigen_vec[i], evi);
+ }
+
+ copy_m4_m3(r_mat, eigen_vec);
+ copy_v3_v3(r_mat[3], center);
+}
+
+/**
+ * Set r_space_transform so that best bbox of dst matches best bbox of src.
+ */
+void BKE_mesh_remap_find_best_match_from_dm(
+ const MVert *verts_dst, const int numverts_dst, DerivedMesh *dm_src, SpaceTransform *r_space_transform)
+{
+ /* Note that those are done so that we successively get actual mirror matrix (by multiplication of columns)... */
+ const float mirrors[][3] = {
+ {-1.0f, 1.0f, 1.0f}, /* -> -1, 1, 1 */
+ { 1.0f, -1.0f, 1.0f}, /* -> -1, -1, 1 */
+ { 1.0f, 1.0f, -1.0f}, /* -> -1, -1, -1 */
+ { 1.0f, -1.0f, 1.0f}, /* -> -1, 1, -1 */
+ {-1.0f, 1.0f, 1.0f}, /* -> 1, 1, -1 */
+ { 1.0f, -1.0f, 1.0f}, /* -> 1, -1, -1 */
+ { 1.0f, 1.0f, -1.0f}, /* -> 1, -1, 1 */
+ {0.0f, 0.0f, 0.0f},
+ };
+ const float (*mirr)[3];
+
+ float mat_src[4][4], mat_dst[4][4], best_mat_dst[4][4];
+ float best_match = FLT_MAX, match;
+
+ const int numverts_src = dm_src->getNumVerts(dm_src);
+ float (*vcos_src)[3] = MEM_mallocN(sizeof(*vcos_src) * (size_t)numverts_src, __func__);
+ dm_src->getVertCos(dm_src, vcos_src);
+
+ mesh_calc_eigen_matrix(NULL, (const float (*)[3])vcos_src, numverts_src, mat_src);
+ mesh_calc_eigen_matrix(verts_dst, NULL, numverts_dst, mat_dst);
+
+ BLI_space_transform_global_from_matrices(r_space_transform, mat_dst, mat_src);
+ match = BKE_mesh_remap_calc_difference_from_dm(r_space_transform, verts_dst, numverts_dst, dm_src);
+ best_match = match;
+ copy_m4_m4(best_mat_dst, mat_dst);
+
+ /* And now, we have to check the otehr sixth possible mirrored versions... */
+ for (mirr = mirrors; (*mirr)[0]; mirr++) {
+ mul_v3_fl(mat_dst[0], (*mirr)[0]);
+ mul_v3_fl(mat_dst[1], (*mirr)[1]);
+ mul_v3_fl(mat_dst[2], (*mirr)[2]);
+
+ BLI_space_transform_global_from_matrices(r_space_transform, mat_dst, mat_src);
+ match = BKE_mesh_remap_calc_difference_from_dm(r_space_transform, verts_dst, numverts_dst, dm_src);
+ if (match < best_match) {
+ best_match = match;
+ copy_m4_m4(best_mat_dst, mat_dst);
+ }
+ }
+
+ BLI_space_transform_global_from_matrices(r_space_transform, best_mat_dst, mat_src);
+}
+
+/** \} */
+
+/** \name Mesh to mesh mapping
+ * \{ */
+
+void BKE_mesh_remap_init(MeshPairRemap *map, const int items_num)
+{
+ MemArena *mem = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__);
+
+ BKE_mesh_remap_free(map);
+
+ map->items = BLI_memarena_alloc(mem, sizeof(*map->items) * (size_t)items_num);
+ map->items_num = items_num;
+
+ map->mem = mem;
+}
+
+void BKE_mesh_remap_free(MeshPairRemap *map)
+{
+ if (map->mem) {
+ BLI_memarena_free((MemArena *)map->mem);
+ }
+
+ map->items_num = 0;
+ map->items = NULL;
+ map->mem = NULL;
+}
+
+static void mesh_remap_item_define(
+ MeshPairRemap *map, const int index, const float UNUSED(hit_dist), const int island,
+ const int sources_num, const int *indices_src, const float *weights_src)
+{
+ MeshPairRemapItem *mapit = &map->items[index];
+ MemArena *mem = map->mem;
+
+ if (sources_num) {
+ mapit->sources_num = sources_num;
+ mapit->indices_src = BLI_memarena_alloc(mem, sizeof(*mapit->indices_src) * (size_t)sources_num);
+ memcpy(mapit->indices_src, indices_src, sizeof(*mapit->indices_src) * (size_t)sources_num);
+ mapit->weights_src = BLI_memarena_alloc(mem, sizeof(*mapit->weights_src) * (size_t)sources_num);
+ memcpy(mapit->weights_src, weights_src, sizeof(*mapit->weights_src) * (size_t)sources_num);
+ }
+ else {
+ mapit->sources_num = 0;
+ mapit->indices_src = NULL;
+ mapit->weights_src = NULL;
+ }
+ /* UNUSED */
+ // mapit->hit_dist = hit_dist;
+ mapit->island = island;
+}
+
+void BKE_mesh_remap_item_define_invalid(MeshPairRemap *map, const int index)
+{
+ mesh_remap_item_define(map, index, FLT_MAX, 0, 0, NULL, NULL);
+}
+
+static int mesh_remap_interp_poly_data_get(
+ const MPoly *mp, MLoop *mloops, const float (*vcos_src)[3], const float point[3],
+ size_t *buff_size, float (**vcos)[3], const bool use_loops, int **indices, float **weights,
+ const bool do_weights, int *r_closest_index)
+{
+ MLoop *ml;
+ float (*vco)[3];
+ float ref_dist_sq = FLT_MAX;
+ int *index;
+ const int sources_num = mp->totloop;
+ int i;
+
+ if ((size_t)sources_num > *buff_size) {
+ *buff_size = (size_t)sources_num;
+ *vcos = MEM_reallocN(*vcos, sizeof(**vcos) * *buff_size);
+ *indices = MEM_reallocN(*indices, sizeof(**indices) * *buff_size);
+ if (do_weights) {
+ *weights = MEM_reallocN(*weights, sizeof(**weights) * *buff_size);
+ }
+ }
+
+ for (i = 0, ml = &mloops[mp->loopstart], vco = *vcos, index = *indices; i < sources_num; i++, ml++, vco++, index++) {
+ *index = use_loops ? (int)mp->loopstart + i : (int)ml->v;
+ copy_v3_v3(*vco, vcos_src[ml->v]);
+ if (r_closest_index) {
+ /* Find closest vert/loop in this case. */
+ const float dist_sq = len_squared_v3v3(point, *vco);
+ if (dist_sq < ref_dist_sq) {
+ ref_dist_sq = dist_sq;
+ *r_closest_index = *index;
+ }
+ }
+ }
+
+ if (do_weights) {
+ interp_weights_poly_v3(*weights, *vcos, sources_num, point);
+ }
+
+ return sources_num;
+}
+
+/* Little helper when dealing with source islands */
+typedef struct IslandResult {
+ float factor; /* A factor, based on which best island for a given set of elements will be selected. */
+ int index_src; /* Index of the source. */
+ float hit_dist; /* The actual hit distance. */
+ float hit_point[3]; /* The hit point, if relevant. */
+} IslandResult;
+
+/* Note about all bvh/raycasting stuff below:
+ * * We must use our ray radius as BVH epsilon too, else rays not hitting anything but 'passing near' an item
+ * would be missed (since BVH handling would not detect them, 'refining' callbacks won't be executed,
+ * even though they would return a valid hit).
+ * * However, in 'islands' case where each hit gets a weight, 'precise' hits should have a better weight than
+ * 'approximate' hits. To address that, we simplify things with:
+ * ** A first raycast with default, given rayradius;
+ * ** If first one fails, we do more raycasting with bigger radius, but if hit is found
+ * it will get smaller weight.
+ * This only concerns loops, currently (because of islands), and 'sampled' edges/polys norproj.
+ */
+
+/* At most n raycasts per 'real' ray. */
+#define MREMAP_RAYCAST_APPROXIMATE_NR 3
+/* Each approximated raycasts will have n times bigger radius than previous one. */
+#define MREMAP_RAYCAST_APPROXIMATE_FAC 5.0f
+/* BVH epsilon value we have to give to bvh 'constructor' when doing approximated raycasting. */
+#define MREMAP_RAYCAST_APPROXIMATE_BVHEPSILON(_ray_radius) \
+ ((float)MREMAP_RAYCAST_APPROXIMATE_NR * MREMAP_RAYCAST_APPROXIMATE_FAC * (_ray_radius))
+
+/* min 16 rays/face, max 400. */
+#define MREMAP_RAYCAST_TRI_SAMPLES_MIN 4
+#define MREMAP_RAYCAST_TRI_SAMPLES_MAX 20
+
+/* Will be enough in 99% of cases. */
+#define MREMAP_DEFAULT_BUFSIZE 32
+
+void BKE_mesh_remap_calc_verts_from_dm(
+ const int mode, const SpaceTransform *space_transform, const float max_dist, const float ray_radius,
+ const MVert *verts_dst, const int numverts_dst, const bool UNUSED(dirty_nors_dst), DerivedMesh *dm_src,
+ MeshPairRemap *r_map)
+{
+ const float full_weight = 1.0f;
+ const float max_dist_sq = max_dist * max_dist;
+ int i;
+
+ BLI_assert(mode & MREMAP_MODE_VERT);
+
+ BKE_mesh_remap_init(r_map, numverts_dst);
+
+ if (mode == MREMAP_MODE_TOPOLOGY) {
+ BLI_assert(numverts_dst == dm_src->getNumVerts(dm_src));
+ for (i = 0; i < numverts_dst; i++) {
+ mesh_remap_item_define(r_map, i, FLT_MAX, 0, 1, &i, &full_weight);
+ }
+ }
+ else {
+ BVHTreeFromMesh treedata = {NULL};
+ BVHTreeNearest nearest = {0};
+ BVHTreeRayHit rayhit = {0};
+ float hit_dist;
+
+ if (mode == MREMAP_MODE_VERT_NEAREST) {
+ bvhtree_from_mesh_verts(&treedata, dm_src, 0.0f, 2, 6);
+ nearest.index = -1;
+
+ for (i = 0; i < numverts_dst; i++) {
+ float tmp_co[3];
+
+ copy_v3_v3(tmp_co, verts_dst[i].co);
+
+ /* Convert the vertex to tree coordinates, if needed. */
+ if (space_transform) {
+ BLI_space_transform_apply(space_transform, tmp_co);
+ }
+
+ if (mesh_remap_bvhtree_query_nearest(&treedata, &nearest, tmp_co, max_dist_sq, &hit_dist)) {
+ mesh_remap_item_define(r_map, i, hit_dist, 0, 1, &nearest.index, &full_weight);
+ }
+ else {
+ /* No source for this dest vertex! */
+ BKE_mesh_remap_item_define_invalid(r_map, i);
+ }
+ }
+ }
+ else if (ELEM(mode, MREMAP_MODE_VERT_EDGE_NEAREST, MREMAP_MODE_VERT_EDGEINTERP_NEAREST)) {
+ MEdge *edges_src = dm_src->getEdgeArray(dm_src);
+ float (*vcos_src)[3] = MEM_mallocN(sizeof(*vcos_src) * (size_t)dm_src->getNumVerts(dm_src), __func__);
+ dm_src->getVertCos(dm_src, vcos_src);
+
+ bvhtree_from_mesh_edges(&treedata, dm_src, 0.0f, 2, 6);
+ nearest.index = -1;
+
+ for (i = 0; i < numverts_dst; i++) {
+ float tmp_co[3];
+
+ copy_v3_v3(tmp_co, verts_dst[i].co);
+
+ /* Convert the vertex to tree coordinates, if needed. */
+ if (space_transform) {
+ BLI_space_transform_apply(space_transform, tmp_co);
+ }
+
+ if (mesh_remap_bvhtree_query_nearest(&treedata, &nearest, tmp_co, max_dist_sq, &hit_dist)) {
+ MEdge *me = &edges_src[nearest.index];
+ const float *v1cos = vcos_src[me->v1];
+ const float *v2cos = vcos_src[me->v2];
+
+ if (mode == MREMAP_MODE_VERT_EDGE_NEAREST) {
+ const float dist_v1 = len_squared_v3v3(tmp_co, v1cos);
+ const float dist_v2 = len_squared_v3v3(tmp_co, v2cos);
+ const int index = (int)((dist_v1 > dist_v2) ? me->v2 : me->v1);
+ mesh_remap_item_define(r_map, i, hit_dist, 0, 1, &index, &full_weight);
+ }
+ else if (mode == MREMAP_MODE_VERT_EDGEINTERP_NEAREST) {
+ int indices[2];
+ float weights[2];
+
+ indices[0] = (int)me->v1;
+ indices[1] = (int)me->v2;
+
+ /* Weight is inverse of point factor here... */
+ weights[0] = line_point_factor_v3(tmp_co, v2cos, v1cos);
+ CLAMP(weights[0], 0.0f, 1.0f);
+ weights[1] = 1.0f - weights[0];
+
+ mesh_remap_item_define(r_map, i, hit_dist, 0, 2, indices, weights);
+ }
+ }
+ else {
+ /* No source for this dest vertex! */
+ BKE_mesh_remap_item_define_invalid(r_map, i);
+ }
+ }
+
+ MEM_freeN(vcos_src);
+ }
+ else if (ELEM(mode, MREMAP_MODE_VERT_POLY_NEAREST, MREMAP_MODE_VERT_POLYINTERP_NEAREST,
+ MREMAP_MODE_VERT_POLYINTERP_VNORPROJ))
+ {
+ MPoly *polys_src = dm_src->getPolyArray(dm_src);
+ MLoop *loops_src = dm_src->getLoopArray(dm_src);
+ float (*vcos_src)[3] = MEM_mallocN(sizeof(*vcos_src) * (size_t)dm_src->getNumVerts(dm_src), __func__);
+
+ size_t tmp_buff_size = MREMAP_DEFAULT_BUFSIZE;
+ float (*vcos)[3] = MEM_mallocN(sizeof(*vcos) * tmp_buff_size, __func__);
+ int *indices = MEM_mallocN(sizeof(*indices) * tmp_buff_size, __func__);
+ float *weights = MEM_mallocN(sizeof(*weights) * tmp_buff_size, __func__);
+
+ dm_src->getVertCos(dm_src, vcos_src);
+ bvhtree_from_mesh_looptri(&treedata, dm_src, (mode & MREMAP_USE_NORPROJ) ? ray_radius : 0.0f, 2, 6);
+
+ if (mode == MREMAP_MODE_VERT_POLYINTERP_VNORPROJ) {
+ for (i = 0; i < numverts_dst; i++) {
+ float tmp_co[3], tmp_no[3];
+
+ copy_v3_v3(tmp_co, verts_dst[i].co);
+ normal_short_to_float_v3(tmp_no, verts_dst[i].no);
+
+ /* Convert the vertex to tree coordinates, if needed. */
+ if (space_transform) {
+ BLI_space_transform_apply(space_transform, tmp_co);
+ BLI_space_transform_apply_normal(space_transform, tmp_no);
+ }
+
+ if (mesh_remap_bvhtree_query_raycast(
+ &treedata, &rayhit, tmp_co, tmp_no, ray_radius, max_dist, &hit_dist))
+ {
+ const MLoopTri *lt = &treedata.looptri[rayhit.index];
+ MPoly *mp_src = &polys_src[lt->poly];
+ const int sources_num = mesh_remap_interp_poly_data_get(
+ mp_src, loops_src, (const float (*)[3])vcos_src, rayhit.co,
+ &tmp_buff_size, &vcos, false, &indices, &weights, true, NULL);
+
+ mesh_remap_item_define(r_map, i, hit_dist, 0, sources_num, indices, weights);
+ }
+ else {
+ /* No source for this dest vertex! */
+ BKE_mesh_remap_item_define_invalid(r_map, i);
+ }
+ }
+ }
+ else {
+ nearest.index = -1;
+
+ for (i = 0; i < numverts_dst; i++) {
+ float tmp_co[3];
+
+ copy_v3_v3(tmp_co, verts_dst[i].co);
+
+ /* Convert the vertex to tree coordinates, if needed. */
+ if (space_transform) {
+ BLI_space_transform_apply(space_transform, tmp_co);
+ }
+
+ if (mesh_remap_bvhtree_query_nearest(&treedata, &nearest, tmp_co, max_dist_sq, &hit_dist)) {
+ const MLoopTri *lt = &treedata.looptri[rayhit.index];
+ MPoly *mp = &polys_src[lt->poly];
+
+ if (mode == MREMAP_MODE_VERT_POLY_NEAREST) {
+ int index;
+ mesh_remap_interp_poly_data_get(
+ mp, loops_src, (const float (*)[3])vcos_src, nearest.co,
+ &tmp_buff_size, &vcos, false, &indices, &weights, false,
+ &index);
+
+ mesh_remap_item_define(r_map, i, hit_dist, 0, 1, &index, &full_weight);
+ }
+ else if (mode == MREMAP_MODE_VERT_POLYINTERP_NEAREST) {
+ const int sources_num = mesh_remap_interp_poly_data_get(
+ mp, loops_src, (const float (*)[3])vcos_src, nearest.co,
+ &tmp_buff_size, &vcos, false, &indices, &weights, true,
+ NULL);
+
+ mesh_remap_item_define(r_map, i, hit_dist, 0, sources_num, indices, weights);
+ }
+ }
+ else {
+ /* No source for this dest vertex! */
+ BKE_mesh_remap_item_define_invalid(r_map, i);
+ }
+ }
+ }
+
+ MEM_freeN(vcos_src);
+ MEM_freeN(vcos);
+ MEM_freeN(indices);
+ MEM_freeN(weights);
+ }
+ else {
+ printf("WARNING! Unsupported mesh-to-mesh vertex mapping mode (%d)!\n", mode);
+ memset(r_map->items, 0, sizeof(*r_map->items) * (size_t)numverts_dst);
+ }
+
+ free_bvhtree_from_mesh(&treedata);
+ }
+}
+
+void BKE_mesh_remap_calc_edges_from_dm(
+ const int mode, const SpaceTransform *space_transform, const float max_dist, const float ray_radius,
+ const MVert *verts_dst, const int numverts_dst, const MEdge *edges_dst, const int numedges_dst,
+ const bool UNUSED(dirty_nors_dst), DerivedMesh *dm_src, MeshPairRemap *r_map)
+{
+ const float full_weight = 1.0f;
+ const float max_dist_sq = max_dist * max_dist;
+ int i;
+
+ BLI_assert(mode & MREMAP_MODE_EDGE);
+
+ BKE_mesh_remap_init(r_map, numedges_dst);
+
+ if (mode == MREMAP_MODE_TOPOLOGY) {
+ BLI_assert(numedges_dst == dm_src->getNumEdges(dm_src));
+ for (i = 0; i < numedges_dst; i++) {
+ mesh_remap_item_define(r_map, i, FLT_MAX, 0, 1, &i, &full_weight);
+ }
+ }
+ else {
+ BVHTreeFromMesh treedata = {NULL};
+ BVHTreeNearest nearest = {0};
+ BVHTreeRayHit rayhit = {0};
+ float hit_dist;
+
+ if (mode == MREMAP_MODE_EDGE_VERT_NEAREST) {
+ const int num_verts_src = dm_src->getNumVerts(dm_src);
+ const int num_edges_src = dm_src->getNumEdges(dm_src);
+ MEdge *edges_src = dm_src->getEdgeArray(dm_src);
+ float (*vcos_src)[3] = MEM_mallocN(sizeof(*vcos_src) * (size_t)dm_src->getNumVerts(dm_src), __func__);
+
+ MeshElemMap *vert_to_edge_src_map;
+ int *vert_to_edge_src_map_mem;
+
+ struct {
+ float hit_dist;
+ int index;
+ } *v_dst_to_src_map = MEM_mallocN(sizeof(*v_dst_to_src_map) * (size_t)numverts_dst, __func__);
+
+ for (i = 0; i < numverts_dst; i++) {
+ v_dst_to_src_map[i].hit_dist = -1.0f;
+ }
+
+ BKE_mesh_vert_edge_map_create(&vert_to_edge_src_map, &vert_to_edge_src_map_mem,
+ edges_src, num_verts_src, num_edges_src);
+
+ dm_src->getVertCos(dm_src, vcos_src);
+
+ bvhtree_from_mesh_verts(&treedata, dm_src, 0.0f, 2, 6);
+ nearest.index = -1;
+
+ for (i = 0; i < numedges_dst; i++) {
+ const MEdge *e_dst = &edges_dst[i];
+ float best_totdist = FLT_MAX;
+ int best_eidx_src = -1;
+ int j = 2;
+
+ while (j--) {
+ const unsigned int vidx_dst = j ? e_dst->v1 : e_dst->v2;
+
+ /* Compute closest verts only once! */
+ if (v_dst_to_src_map[vidx_dst].hit_dist == -1.0f) {
+ float tmp_co[3];
+
+ copy_v3_v3(tmp_co, verts_dst[vidx_dst].co);
+
+ /* Convert the vertex to tree coordinates, if needed. */
+ if (space_transform) {
+ BLI_space_transform_apply(space_transform, tmp_co);
+ }
+
+ if (mesh_remap_bvhtree_query_nearest(&treedata, &nearest, tmp_co, max_dist_sq, &hit_dist)) {
+ v_dst_to_src_map[vidx_dst].hit_dist = hit_dist;
+ v_dst_to_src_map[vidx_dst].index = nearest.index;
+ }
+ else {
+ /* No source for this dest vert! */
+ v_dst_to_src_map[vidx_dst].hit_dist = FLT_MAX;
+ }
+ }
+ }
+
+ /* Now, check all source edges of closest sources vertices, and select the one giving the smallest
+ * total verts-to-verts distance. */
+ for (j = 2; j--;) {
+ const unsigned int vidx_dst = j ? e_dst->v1 : e_dst->v2;
+ const float first_dist = v_dst_to_src_map[vidx_dst].hit_dist;
+ const int vidx_src = v_dst_to_src_map[vidx_dst].index;
+ int *eidx_src, k;
+
+ if (vidx_src < 0) {
+ continue;
+ }
+
+ eidx_src = vert_to_edge_src_map[vidx_src].indices;
+ k = vert_to_edge_src_map[vidx_src].count;
+
+ for (; k--; eidx_src++) {
+ MEdge *e_src = &edges_src[*eidx_src];
+ const float *other_co_src = vcos_src[BKE_mesh_edge_other_vert(e_src, vidx_src)];
+ const float *other_co_dst = verts_dst[BKE_mesh_edge_other_vert(e_dst, (int)vidx_dst)].co;
+ const float totdist = first_dist + len_v3v3(other_co_src, other_co_dst);
+
+ if (totdist < best_totdist) {
+ best_totdist = totdist;
+ best_eidx_src = *eidx_src;
+ }
+ }
+ }
+
+ if (best_eidx_src >= 0) {
+ const float *co1_src = vcos_src[edges_src[best_eidx_src].v1];
+ const float *co2_src = vcos_src[edges_src[best_eidx_src].v2];
+ const float *co1_dst = verts_dst[e_dst->v1].co;
+ const float *co2_dst = verts_dst[e_dst->v2].co;
+ float co_src[3], co_dst[3];
+
+ /* TODO: would need an isect_seg_seg_v3(), actually! */
+ const int isect_type = isect_line_line_v3(co1_src, co2_src, co1_dst, co2_dst, co_src, co_dst);
+ if (isect_type != 0) {
+ const float fac_src = line_point_factor_v3(co_src, co1_src, co2_src);
+ const float fac_dst = line_point_factor_v3(co_dst, co1_dst, co2_dst);
+ if (fac_src < 0.0f) {
+ copy_v3_v3(co_src, co1_src);
+ }
+ else if (fac_src > 1.0f) {
+ copy_v3_v3(co_src, co2_src);
+ }
+ if (fac_dst < 0.0f) {
+ copy_v3_v3(co_dst, co1_dst);
+ }
+ else if (fac_dst > 1.0f) {
+ copy_v3_v3(co_dst, co2_dst);
+ }
+ }
+ hit_dist = len_v3v3(co_dst, co_src);
+ mesh_remap_item_define(r_map, i, hit_dist, 0, 1, &best_eidx_src, &full_weight);
+ }
+ else {
+ /* No source for this dest edge! */
+ BKE_mesh_remap_item_define_invalid(r_map, i);
+ }
+ }
+
+ MEM_freeN(vcos_src);
+ MEM_freeN(v_dst_to_src_map);
+ MEM_freeN(vert_to_edge_src_map);
+ MEM_freeN(vert_to_edge_src_map_mem);
+ }
+ else if (mode == MREMAP_MODE_EDGE_NEAREST) {
+ bvhtree_from_mesh_edges(&treedata, dm_src, 0.0f, 2, 6);
+ nearest.index = -1;
+
+ for (i = 0; i < numedges_dst; i++) {
+ float tmp_co[3];
+
+ interp_v3_v3v3(tmp_co, verts_dst[edges_dst[i].v1].co, verts_dst[edges_dst[i].v2].co, 0.5f);
+
+ /* Convert the vertex to tree coordinates, if needed. */
+ if (space_transform) {
+ BLI_space_transform_apply(space_transform, tmp_co);
+ }
+
+ if (mesh_remap_bvhtree_query_nearest(&treedata, &nearest, tmp_co, max_dist_sq, &hit_dist)) {
+ mesh_remap_item_define(r_map, i, hit_dist, 0, 1, &nearest.index, &full_weight);
+ }
+ else {
+ /* No source for this dest edge! */
+ BKE_mesh_remap_item_define_invalid(r_map, i);
+ }
+ }
+ }
+ else if (mode == MREMAP_MODE_EDGE_POLY_NEAREST) {
+ MEdge *edges_src = dm_src->getEdgeArray(dm_src);
+ MPoly *polys_src = dm_src->getPolyArray(dm_src);
+ MLoop *loops_src = dm_src->getLoopArray(dm_src);
+ float (*vcos_src)[3] = MEM_mallocN(sizeof(*vcos_src) * (size_t)dm_src->getNumVerts(dm_src), __func__);
+
+ dm_src->getVertCos(dm_src, vcos_src);
+ bvhtree_from_mesh_looptri(&treedata, dm_src, 0.0f, 2, 6);
+
+ for (i = 0; i < numedges_dst; i++) {
+ float tmp_co[3];
+
+ interp_v3_v3v3(tmp_co, verts_dst[edges_dst[i].v1].co, verts_dst[edges_dst[i].v2].co, 0.5f);
+
+ /* Convert the vertex to tree coordinates, if needed. */
+ if (space_transform) {
+ BLI_space_transform_apply(space_transform, tmp_co);
+ }
+
+ if (mesh_remap_bvhtree_query_nearest(&treedata, &nearest, tmp_co, max_dist_sq, &hit_dist)) {
+ const MLoopTri *lt = &treedata.looptri[rayhit.index];
+ MPoly *mp_src = &polys_src[lt->poly];
+ MLoop *ml_src = &loops_src[mp_src->loopstart];
+ int nloops = mp_src->totloop;
+ float best_dist_sq = FLT_MAX;
+ int best_eidx_src = -1;
+
+ for (; nloops--; ml_src++) {
+ MEdge *me_src = &edges_src[ml_src->e];
+ float *co1_src = vcos_src[me_src->v1];
+ float *co2_src = vcos_src[me_src->v2];
+ float co_src[3];
+ float dist_sq;
+
+ interp_v3_v3v3(co_src, co1_src, co2_src, 0.5f);
+ dist_sq = len_squared_v3v3(tmp_co, co_src);
+ if (dist_sq < best_dist_sq) {
+ best_dist_sq = dist_sq;
+ best_eidx_src = (int)ml_src->e;
+ }
+ }
+ if (best_eidx_src >= 0) {
+ mesh_remap_item_define(r_map, i, hit_dist, 0, 1, &best_eidx_src, &full_weight);
+ }
+ }
+ else {
+ /* No source for this dest edge! */
+ BKE_mesh_remap_item_define_invalid(r_map, i);
+ }
+ }
+
+ MEM_freeN(vcos_src);
+ }
+ else if (mode == MREMAP_MODE_EDGE_EDGEINTERP_VNORPROJ) {
+ const int num_rays_min = 5, num_rays_max = 100;
+ const int numedges_src = dm_src->getNumEdges(dm_src);
+
+ /* Subtleness - this one we can allocate only max number of cast rays per edges! */
+ int *indices = MEM_mallocN(sizeof(*indices) * (size_t)min_ii(numedges_src, num_rays_max), __func__);
+ /* Here it's simpler to just allocate for all edges :/ */
+ float *weights = MEM_mallocN(sizeof(*weights) * (size_t)numedges_src, __func__);
+
+ bvhtree_from_mesh_edges(&treedata, dm_src, MREMAP_RAYCAST_APPROXIMATE_BVHEPSILON(ray_radius), 2, 6);
+
+ for (i = 0; i < numedges_dst; i++) {
+ /* For each dst edge, we sample some rays from it (interpolated from its vertices)
+ * and use their hits to interpolate from source edges. */
+ const MEdge *me = &edges_dst[i];
+ float tmp_co[3], v1_co[3], v2_co[3];
+ float tmp_no[3], v1_no[3], v2_no[3];
+
+ int grid_size;
+ float edge_dst_len;
+ float grid_step;
+
+ float totweights = 0.0f;
+ float hit_dist_accum = 0.0f;
+ int sources_num = 0;
+ int j;
+
+ copy_v3_v3(v1_co, verts_dst[me->v1].co);
+ copy_v3_v3(v2_co, verts_dst[me->v2].co);
+
+ normal_short_to_float_v3(v1_no, verts_dst[me->v1].no);
+ normal_short_to_float_v3(v2_no, verts_dst[me->v2].no);
+
+ /* We do our transform here, allows to interpolate from normals already in src space. */
+ if (space_transform) {
+ BLI_space_transform_apply(space_transform, v1_co);
+ BLI_space_transform_apply(space_transform, v2_co);
+ BLI_space_transform_apply_normal(space_transform, v1_no);
+ BLI_space_transform_apply_normal(space_transform, v2_no);
+ }
+
+ copy_vn_fl(weights, (int)numedges_src, 0.0f);
+
+ /* We adjust our ray-casting grid to ray_radius (the smaller, the more rays are cast),
+ * with lower/upper bounds. */
+ edge_dst_len = len_v3v3(v1_co, v2_co);
+
+ grid_size = (int)((edge_dst_len / ray_radius) + 0.5f);
+ CLAMP(grid_size, num_rays_min, num_rays_max); /* min 5 rays/edge, max 100. */
+
+ grid_step = 1.0f / (float)grid_size; /* Not actual distance here, rather an interp fac... */
+
+ /* And now we can cast all our rays, and see what we get! */
+ for (j = 0; j < grid_size; j++) {
+ const float fac = grid_step * (float)j;
+
+ int n = (ray_radius > 0.0f) ? MREMAP_RAYCAST_APPROXIMATE_NR : 1;
+ float w = 1.0f;
+
+ interp_v3_v3v3(tmp_co, v1_co, v2_co, fac);
+ interp_v3_v3v3_slerp_safe(tmp_no, v1_no, v2_no, fac);
+
+ while (n--) {
+ if (mesh_remap_bvhtree_query_raycast(
+ &treedata, &rayhit, tmp_co, tmp_no, ray_radius / w, max_dist, &hit_dist))
+ {
+ weights[rayhit.index] += w;
+ totweights += w;
+ hit_dist_accum += hit_dist;
+ break;
+ }
+ /* Next iteration will get bigger radius but smaller weight! */
+ w /= MREMAP_RAYCAST_APPROXIMATE_FAC;
+ }
+ }
+ /* A sampling is valid (as in, its result can be considered as valid sources) only if at least
+ * half of the rays found a source! */
+ if (totweights > ((float)grid_size / 2.0f)) {
+ for (j = 0; j < (int)numedges_src; j++) {
+ if (!weights[j]) {
+ continue;
+ }
+ /* Note: sources_num is always <= j! */
+ weights[sources_num] = weights[j] / totweights;
+ indices[sources_num] = j;
+ sources_num++;
+ }
+ mesh_remap_item_define(r_map, i, hit_dist_accum / totweights, 0,
+ sources_num, indices, weights);
+ }
+ else {
+ /* No source for this dest edge! */
+ BKE_mesh_remap_item_define_invalid(r_map, i);
+ }
+ }
+
+ MEM_freeN(indices);
+ MEM_freeN(weights);
+ }
+ else {
+ printf("WARNING! Unsupported mesh-to-mesh edge mapping mode (%d)!\n", mode);
+ memset(r_map->items, 0, sizeof(*r_map->items) * (size_t)numedges_dst);
+ }
+
+ free_bvhtree_from_mesh(&treedata);
+ }
+}
+
+#define POLY_UNSET 0
+#define POLY_CENTER_INIT 1
+#define POLY_COMPLETE 2
+
+static void mesh_island_to_astar_graph_edge_process(
+ MeshIslandStore *islands, const int island_index, BLI_AStarGraph *as_graph,
+ MVert *verts, MPoly *polys, MLoop *loops,
+ const int edge_idx, BLI_bitmap *done_edges, MeshElemMap *edge_to_poly_map, const bool is_edge_innercut,
+ int *poly_island_index_map, float (*poly_centers)[3], unsigned char *poly_status)
+{
+ int *poly_island_indices = BLI_array_alloca(poly_island_indices, (size_t)edge_to_poly_map[edge_idx].count);
+ int i, j;
+
+ for (i = 0; i < edge_to_poly_map[edge_idx].count; i++) {
+ const int pidx = edge_to_poly_map[edge_idx].indices[i];
+ MPoly *mp = &polys[pidx];
+ const int pidx_isld = islands ? poly_island_index_map[pidx] : pidx;
+ void *custom_data = is_edge_innercut ? SET_INT_IN_POINTER(edge_idx) : SET_INT_IN_POINTER(-1);
+
+ if (UNLIKELY(islands && (islands->items_to_islands[mp->loopstart] != island_index))) {
+ /* poly not in current island, happens with border edges... */
+ poly_island_indices[i] = -1;
+ continue;
+ }
+
+ if (poly_status[pidx_isld] == POLY_COMPLETE) {
+ poly_island_indices[i] = pidx_isld;
+ continue;
+ }
+
+ if (poly_status[pidx_isld] == POLY_UNSET) {
+ BKE_mesh_calc_poly_center(mp, &loops[mp->loopstart], verts, poly_centers[pidx_isld]);
+ BLI_astar_node_init(as_graph, pidx_isld, poly_centers[pidx_isld]);
+ poly_status[pidx_isld] = POLY_CENTER_INIT;
+ }
+
+ for (j = i; j--;) {
+ float dist_cost;
+ const int pidx_isld_other = poly_island_indices[j];
+
+ if (pidx_isld_other == -1 || poly_status[pidx_isld_other] == POLY_COMPLETE) {
+ /* If the other poly is complete, that link has already been added! */
+ continue;
+ }
+ dist_cost = len_v3v3(poly_centers[pidx_isld_other], poly_centers[pidx_isld]);
+ BLI_astar_node_link_add(as_graph, pidx_isld_other, pidx_isld, dist_cost, custom_data);
+ }
+
+ poly_island_indices[i] = pidx_isld;
+ }
+
+ BLI_BITMAP_ENABLE(done_edges, edge_idx);
+}
+
+static void mesh_island_to_astar_graph(
+ MeshIslandStore *islands, const int island_index,
+ MVert *verts, MeshElemMap *edge_to_poly_map, const int numedges, MLoop *loops, MPoly *polys, const int numpolys,
+ BLI_AStarGraph *r_as_graph)
+{
+ MeshElemMap *island_poly_map = islands ? islands->islands[island_index] : NULL;
+ MeshElemMap *island_einnercut_map = islands ? islands->innercuts[island_index] : NULL;
+
+ int *poly_island_index_map = NULL;
+ BLI_bitmap *done_edges = BLI_BITMAP_NEW(numedges, __func__);
+
+ const int node_num = islands ? island_poly_map->count : numpolys;
+ unsigned char *poly_status = MEM_callocN(sizeof(*poly_status) * (size_t)node_num, __func__);
+ float (*poly_centers)[3];
+
+ int pidx_isld;
+ int i;
+
+ BLI_astar_graph_init(r_as_graph, node_num, NULL);
+ /* poly_centers is owned by graph memarena. */
+ poly_centers = BLI_memarena_calloc(r_as_graph->mem, sizeof(*poly_centers) * (size_t)node_num);
+
+ if (islands) {
+ /* poly_island_index_map is owned by graph memarena. */
+ poly_island_index_map = BLI_memarena_calloc(r_as_graph->mem, sizeof(*poly_island_index_map) * (size_t)numpolys);
+ for (i = island_poly_map->count; i--;) {
+ poly_island_index_map[island_poly_map->indices[i]] = i;
+ }
+
+ r_as_graph->custom_data = poly_island_index_map;
+
+ for (i = island_einnercut_map->count; i--;) {
+ mesh_island_to_astar_graph_edge_process(
+ islands, island_index, r_as_graph, verts, polys, loops,
+ island_einnercut_map->indices[i], done_edges, edge_to_poly_map, true,
+ poly_island_index_map, poly_centers, poly_status);
+ }
+ }
+
+ for (pidx_isld = node_num; pidx_isld--;) {
+ const int pidx = islands ? island_poly_map->indices[pidx_isld] : pidx_isld;
+ MPoly *mp = &polys[pidx];
+ int pl_idx, l_idx;
+
+ if (poly_status[pidx_isld] == POLY_COMPLETE) {
+ continue;
+ }
+
+ for (pl_idx = 0, l_idx = mp->loopstart; pl_idx < mp->totloop; pl_idx++, l_idx++) {
+ MLoop *ml = &loops[l_idx];
+
+ if (BLI_BITMAP_TEST(done_edges, ml->e)) {
+ continue;
+ }
+
+ mesh_island_to_astar_graph_edge_process(
+ islands, island_index, r_as_graph, verts, polys, loops,
+ (int)ml->e, done_edges, edge_to_poly_map, false,
+ poly_island_index_map, poly_centers, poly_status);
+ }
+ poly_status[pidx_isld] = POLY_COMPLETE;
+ }
+
+ MEM_freeN(done_edges);
+ MEM_freeN(poly_status);
+}
+
+#undef POLY_UNSET
+#undef POLY_CENTER_INIT
+#undef POLY_COMPLETE
+
+/* Our 'f_cost' callback func, to find shortest poly-path between two remapped-loops.
+ * Note we do not want to make innercuts 'walls' here, just detect when the shortest path goes by those. */
+static float mesh_remap_calc_loops_astar_f_cost(
+ BLI_AStarGraph *as_graph, BLI_AStarSolution *as_solution, BLI_AStarGNLink *link,
+ const int node_idx_curr, const int node_idx_next, const int node_idx_dst)
+{
+ float *co_next, *co_dest;
+
+ if (link && (GET_INT_FROM_POINTER(link->custom_data) != -1)) {
+ /* An innercut edge... We tag our solution as potentially crossing innercuts.
+ * Note it might not be the case in the end (AStar will explore around optimal path), but helps
+ * trimming off some processing later... */
+ if (!GET_INT_FROM_POINTER(as_solution->custom_data)) {
+ as_solution->custom_data = SET_INT_IN_POINTER(true);
+ }
+ }
+
+ /* Our heuristic part of current f_cost is distance from next node to destination one.
+ * It is guaranteed to be less than (or equal to) actual shortest poly-path between next node and destination one.
+ */
+ co_next = (float *)as_graph->nodes[node_idx_next].custom_data;
+ co_dest = (float *)as_graph->nodes[node_idx_dst].custom_data;
+ return (link ? (as_solution->g_costs[node_idx_curr] + link->cost) : 0.0f) + len_v3v3(co_next, co_dest);
+}
+
+#define ASTAR_STEPS_MAX 64
+
+
+void BKE_mesh_remap_calc_loops_from_dm(
+ const int mode, const SpaceTransform *space_transform, const float max_dist, const float ray_radius,
+ MVert *verts_dst, const int numverts_dst, MEdge *edges_dst, const int numedges_dst,
+ MLoop *loops_dst, const int numloops_dst, MPoly *polys_dst, const int numpolys_dst,
+ CustomData *ldata_dst, CustomData *pdata_dst,
+ const bool use_split_nors_dst, const float split_angle_dst, const bool dirty_nors_dst,
+ DerivedMesh *dm_src, const bool use_split_nors_src, const float split_angle_src,
+ MeshRemapIslandsCalc gen_islands_src, const float islands_precision_src, MeshPairRemap *r_map)
+{
+ const float full_weight = 1.0f;
+ const float max_dist_sq = max_dist * max_dist;
+
+ int i;
+
+ BLI_assert(mode & MREMAP_MODE_LOOP);
+ BLI_assert((islands_precision_src >= 0.0f) && (islands_precision_src <= 1.0f));
+
+ BKE_mesh_remap_init(r_map, numloops_dst);
+
+ if (mode == MREMAP_MODE_TOPOLOGY) {
+ /* In topology mapping, we assume meshes are identical, islands included! */
+ BLI_assert(numloops_dst == dm_src->getNumLoops(dm_src));
+ for (i = 0; i < numloops_dst; i++) {
+ mesh_remap_item_define(r_map, i, FLT_MAX, 0, 1, &i, &full_weight);
+ }
+ }
+ else {
+ BVHTreeFromMesh *treedata = NULL;
+ BVHTreeNearest nearest = {0};
+ BVHTreeRayHit rayhit = {0};
+ int num_trees = 0;
+ float hit_dist;
+
+ const bool use_from_vert = (mode & MREMAP_USE_VERT);
+
+ MeshIslandStore island_store = {0};
+ bool use_islands = false;
+
+ BLI_AStarGraph *as_graphdata = NULL;
+ BLI_AStarSolution as_solution = {0};
+ const int isld_steps_src = islands_precision_src ?
+ max_ii((int)(ASTAR_STEPS_MAX * islands_precision_src + 0.499f), 1) : 0;
+
+ float (*poly_nors_src)[3] = NULL;
+ float (*loop_nors_src)[3] = NULL;
+ float (*poly_nors_dst)[3] = NULL;
+ float (*loop_nors_dst)[3] = NULL;
+
+ float (*poly_cents_src)[3] = NULL;
+
+ MeshElemMap *vert_to_loop_map_src = NULL;
+ int *vert_to_loop_map_src_buff = NULL;
+ MeshElemMap *vert_to_poly_map_src = NULL;
+ int *vert_to_poly_map_src_buff = NULL;
+ MeshElemMap *edge_to_poly_map_src = NULL;
+ int *edge_to_poly_map_src_buff = NULL;
+ MeshElemMap *poly_to_looptri_map_src = NULL;
+ int *poly_to_looptri_map_src_buff = NULL;
+
+ /* Unlike above, those are one-to-one mappings, simpler! */
+ int *loop_to_poly_map_src = NULL;
+
+ bool verts_allocated_src;
+ MVert *verts_src = DM_get_vert_array(dm_src, &verts_allocated_src);
+ const int num_verts_src = dm_src->getNumVerts(dm_src);
+ float (*vcos_src)[3] = NULL;
+ bool edges_allocated_src;
+ MEdge *edges_src = DM_get_edge_array(dm_src, &edges_allocated_src);
+ const int num_edges_src = dm_src->getNumEdges(dm_src);
+ bool loops_allocated_src;
+ MLoop *loops_src = DM_get_loop_array(dm_src, &loops_allocated_src);
+ const int num_loops_src = dm_src->getNumLoops(dm_src);
+ bool polys_allocated_src;
+ MPoly *polys_src = DM_get_poly_array(dm_src, &polys_allocated_src);
+ const int num_polys_src = dm_src->getNumPolys(dm_src);
+ bool looptri_allocated_src = false;
+ const MLoopTri *looptri_src = NULL;
+ int num_looptri_src = 0;
+
+ size_t buff_size_interp = MREMAP_DEFAULT_BUFSIZE;
+ float (*vcos_interp)[3] = NULL;
+ int *indices_interp = NULL;
+ float *weights_interp = NULL;
+
+ MLoop *ml_src, *ml_dst;
+ MPoly *mp_src, *mp_dst;
+ int tindex, pidx_dst, lidx_dst, plidx_dst, pidx_src, lidx_src, plidx_src;
+
+ IslandResult **islands_res;
+ size_t islands_res_buff_size = MREMAP_DEFAULT_BUFSIZE;
+
+ const float bvh_epsilon = (mode & MREMAP_USE_NORPROJ) ? MREMAP_RAYCAST_APPROXIMATE_BVHEPSILON(ray_radius) : 0.0f;
+
+ if (!use_from_vert) {
+ vcos_src = MEM_mallocN(sizeof(*vcos_src) * (size_t)num_verts_src, __func__);
+ dm_src->getVertCos(dm_src, vcos_src);
+
+ vcos_interp = MEM_mallocN(sizeof(*vcos_interp) * buff_size_interp, __func__);
+ indices_interp = MEM_mallocN(sizeof(*indices_interp) * buff_size_interp, __func__);
+ weights_interp = MEM_mallocN(sizeof(*weights_interp) * buff_size_interp, __func__);
+ }
+
+ {
+ const bool need_lnors_src = (mode & MREMAP_USE_LOOP) && (mode & MREMAP_USE_NORMAL);
+ const bool need_lnors_dst = need_lnors_src || (mode & MREMAP_USE_NORPROJ);
+ const bool need_pnors_src = need_lnors_src || ((mode & MREMAP_USE_POLY) && (mode & MREMAP_USE_NORMAL));
+ const bool need_pnors_dst = need_lnors_dst || need_pnors_src;
+
+ if (need_pnors_dst) {
+ /* Cache poly nors into a temp CDLayer. */
+ poly_nors_dst = CustomData_get_layer(pdata_dst, CD_NORMAL);
+ if (!poly_nors_dst) {
+ poly_nors_dst = CustomData_add_layer(pdata_dst, CD_NORMAL, CD_CALLOC, NULL, numpolys_dst);
+ CustomData_set_layer_flag(pdata_dst, CD_NORMAL, CD_FLAG_TEMPORARY);
+ }
+ if (dirty_nors_dst) {
+ BKE_mesh_calc_normals_poly(verts_dst, numverts_dst, loops_dst, polys_dst,
+ numloops_dst, numpolys_dst, poly_nors_dst, true);
+ }
+ }
+ if (need_lnors_dst) {
+ short (*custom_nors_dst)[2] = CustomData_get_layer(ldata_dst, CD_CUSTOMLOOPNORMAL);
+
+ /* Cache poly nors into a temp CDLayer. */
+ loop_nors_dst = CustomData_get_layer(ldata_dst, CD_NORMAL);
+ if (dirty_nors_dst || !loop_nors_dst) {
+ if (!loop_nors_dst) {
+ loop_nors_dst = CustomData_add_layer(ldata_dst, CD_NORMAL, CD_CALLOC, NULL, numloops_dst);
+ CustomData_set_layer_flag(ldata_dst, CD_NORMAL, CD_FLAG_TEMPORARY);
+ }
+ BKE_mesh_normals_loop_split(verts_dst, numverts_dst, edges_dst, numedges_dst,
+ loops_dst, loop_nors_dst, numloops_dst,
+ polys_dst, (const float (*)[3])poly_nors_dst, numpolys_dst,
+ use_split_nors_dst, split_angle_dst, NULL, custom_nors_dst, NULL);
+ }
+ }
+ if (need_pnors_src || need_lnors_src) {
+ /* Simpler for now, calcNormals never stores pnors :( */
+ dm_src->calcLoopNormals(dm_src, use_split_nors_src, split_angle_src);
+
+ if (need_pnors_src) {
+ poly_nors_src = dm_src->getPolyDataArray(dm_src, CD_NORMAL);
+ }
+ if (need_lnors_src) {
+ loop_nors_src = dm_src->getLoopDataArray(dm_src, CD_NORMAL);
+ }
+ }
+ }
+
+ if (use_from_vert) {
+ BKE_mesh_vert_loop_map_create(&vert_to_loop_map_src, &vert_to_loop_map_src_buff,
+ polys_src, loops_src, num_verts_src, num_polys_src, num_loops_src);
+ if (mode & MREMAP_USE_POLY) {
+ BKE_mesh_vert_poly_map_create(&vert_to_poly_map_src, &vert_to_poly_map_src_buff,
+ polys_src, loops_src, num_verts_src, num_polys_src, num_loops_src);
+ }
+ }
+
+ /* Needed for islands (or plain mesh) to AStar graph conversion. */
+ BKE_mesh_edge_poly_map_create(&edge_to_poly_map_src, &edge_to_poly_map_src_buff,
+ edges_src, num_edges_src, polys_src, num_polys_src, loops_src, num_loops_src);
+ if (use_from_vert) {
+ loop_to_poly_map_src = MEM_mallocN(sizeof(*loop_to_poly_map_src) * (size_t)num_loops_src, __func__);
+ poly_cents_src = MEM_mallocN(sizeof(*poly_cents_src) * (size_t)num_polys_src, __func__);
+ for (pidx_src = 0, mp_src = polys_src; pidx_src < num_polys_src; pidx_src++, mp_src++) {
+ ml_src = &loops_src[mp_src->loopstart];
+ for (plidx_src = 0, lidx_src = mp_src->loopstart; plidx_src < mp_src->totloop; plidx_src++, lidx_src++) {
+ loop_to_poly_map_src[lidx_src] = pidx_src;
+ }
+ BKE_mesh_calc_poly_center(mp_src, ml_src, verts_src, poly_cents_src[pidx_src]);
+ }
+ }
+
+ /* Island makes things slightly more complex here.
+ * Basically, we:
+ * * Make one treedata for each island's elements.
+ * * Check all loops of a same dest poly against all treedata.
+ * * Choose the island's elements giving the best results.
+ */
+
+ /* First, generate the islands, if possible. */
+ if (gen_islands_src) {
+ use_islands = gen_islands_src(
+ verts_src, num_verts_src,
+ edges_src, num_edges_src,
+ polys_src, num_polys_src,
+ loops_src, num_loops_src,
+ &island_store);
+
+ num_trees = use_islands ? island_store.islands_num : 1;
+ treedata = MEM_callocN(sizeof(*treedata) * (size_t)num_trees, __func__);
+ if (isld_steps_src) {
+ as_graphdata = MEM_callocN(sizeof(*as_graphdata) * (size_t)num_trees, __func__);
+ }
+
+ if (use_islands) {
+ /* We expect our islands to contain poly indices, with edge indices of 'inner cuts',
+ * and a mapping loops -> islands indices.
+ * This implies all loops of a same poly are in the same island. */
+ BLI_assert((island_store.item_type == MISLAND_TYPE_LOOP) &&
+ (island_store.island_type == MISLAND_TYPE_POLY) &&
+ (island_store.innercut_type == MISLAND_TYPE_EDGE));
+ }
+ }
+ else {
+ num_trees = 1;
+ treedata = MEM_callocN(sizeof(*treedata), __func__);
+ if (isld_steps_src) {
+ as_graphdata = MEM_callocN(sizeof(*as_graphdata), __func__);
+ }
+ }
+
+ /* Build our AStar graphs. */
+ if (isld_steps_src) {
+ for (tindex = 0; tindex < num_trees; tindex++) {
+ mesh_island_to_astar_graph(
+ use_islands ? &island_store : NULL, tindex, verts_src, edge_to_poly_map_src, num_edges_src,
+ loops_src, polys_src, num_polys_src, &as_graphdata[tindex]);
+ }
+ }
+
+ /* Build our BVHtrees, either from verts or tessfaces. */
+ if (use_from_vert) {
+ if (use_islands) {
+ BLI_bitmap *verts_active = BLI_BITMAP_NEW((size_t)num_verts_src, __func__);
+
+ for (tindex = 0; tindex < num_trees; tindex++) {
+ MeshElemMap *isld = island_store.islands[tindex];
+ int num_verts_active = 0;
+ BLI_BITMAP_SET_ALL(verts_active, false, (size_t)num_verts_src);
+ for (i = 0; i < isld->count; i++) {
+ mp_src = &polys_src[isld->indices[i]];
+ for (lidx_src = mp_src->loopstart; lidx_src < mp_src->loopstart + mp_src->totloop; lidx_src++) {
+ const unsigned int vidx_src = loops_src[lidx_src].v;
+ if (!BLI_BITMAP_TEST(verts_active, vidx_src)) {
+ BLI_BITMAP_ENABLE(verts_active, loops_src[lidx_src].v);
+ num_verts_active++;
+ }
+ }
+ }
+ /* verts 'ownership' is transfered to treedata here, which will handle its freeing. */
+ bvhtree_from_mesh_verts_ex(&treedata[tindex], verts_src, num_verts_src, verts_allocated_src,
+ verts_active, num_verts_active, bvh_epsilon, 2, 6);
+ if (verts_allocated_src) {
+ verts_allocated_src = false; /* Only 'give' our verts once, to first tree! */
+ }
+ }
+
+ MEM_freeN(verts_active);
+ }
+ else {
+ BLI_assert(num_trees == 1);
+ bvhtree_from_mesh_verts(&treedata[0], dm_src, bvh_epsilon, 2, 6);
+ }
+ }
+ else { /* We use polygons. */
+ if (use_islands) {
+ /* bvhtree here uses looptri faces... */
+ const unsigned int dirty_tess_flag = dm_src->dirty & DM_DIRTY_TESS_CDLAYERS;
+ BLI_bitmap *looptri_active;
+
+ /* We do not care about tessellated data here, only geometry itself is important. */
+ if (dirty_tess_flag) {
+ dm_src->dirty &= ~dirty_tess_flag;
+ }
+ DM_ensure_looptri(dm_src);
+ if (dirty_tess_flag) {
+ dm_src->dirty |= dirty_tess_flag;
+ }
+
+ looptri_src = DM_get_looptri_array(
+ dm_src,
+ verts_src,
+ polys_src, num_polys_src,
+ loops_src, num_loops_src,
+ &looptri_allocated_src);
+ num_looptri_src = dm_src->getNumLoopTri(dm_src);
+ looptri_active = BLI_BITMAP_NEW((size_t)num_looptri_src, __func__);
+
+ for (tindex = 0; tindex < num_trees; tindex++) {
+ int num_looptri_active = 0;
+ BLI_BITMAP_SET_ALL(looptri_active, false, (size_t)num_looptri_src);
+ for (i = 0; i < num_looptri_src; i++) {
+ mp_src = &polys_src[looptri_src[i].poly];
+ if (island_store.items_to_islands[mp_src->loopstart] == tindex) {
+ BLI_BITMAP_ENABLE(looptri_active, i);
+ num_looptri_active++;
+ }
+ }
+ /* verts and faces 'ownership' is transfered to treedata here, which will handle its freeing. */
+ bvhtree_from_mesh_looptri_ex(
+ &treedata[tindex],
+ verts_src, verts_allocated_src,
+ loops_src, loops_allocated_src,
+ looptri_src, num_looptri_src, looptri_allocated_src,
+ looptri_active, num_looptri_active, bvh_epsilon, 2, 6);
+ if (verts_allocated_src) {
+ verts_allocated_src = false; /* Only 'give' our verts once, to first tree! */
+ }
+ if (loops_allocated_src) {
+ loops_allocated_src = false; /* Only 'give' our loops once, to first tree! */
+ }
+ if (looptri_allocated_src) {
+ looptri_allocated_src = false; /* Only 'give' our looptri once, to first tree! */
+ }
+ }
+
+ MEM_freeN(looptri_active);
+ }
+ else {
+ BLI_assert(num_trees == 1);
+ bvhtree_from_mesh_looptri(&treedata[0], dm_src, bvh_epsilon, 2, 6);
+ }
+ }
+
+ /* And check each dest poly! */
+ islands_res = MEM_mallocN(sizeof(*islands_res) * (size_t)num_trees, __func__);
+ for (tindex = 0; tindex < num_trees; tindex++) {
+ islands_res[tindex] = MEM_mallocN(sizeof(**islands_res) * islands_res_buff_size, __func__);
+ }
+
+ for (pidx_dst = 0, mp_dst = polys_dst; pidx_dst < numpolys_dst; pidx_dst++, mp_dst++) {
+ float (*pnor_dst)[3] = &poly_nors_dst[pidx_dst];
+
+ /* Only in use_from_vert case, we may need polys' centers as fallback in case we cannot decide which
+ * corner to use from normals only. */
+ float pcent_dst[3];
+ bool pcent_dst_valid = false;
+
+ if ((size_t)mp_dst->totloop > islands_res_buff_size) {
+ islands_res_buff_size = (size_t)mp_dst->totloop + MREMAP_DEFAULT_BUFSIZE;
+ for (tindex = 0; tindex < num_trees; tindex++) {
+ islands_res[tindex] = MEM_reallocN(islands_res[tindex], sizeof(**islands_res) * islands_res_buff_size);
+ }
+ }
+
+ for (tindex = 0; tindex < num_trees; tindex++) {
+ BVHTreeFromMesh *tdata = &treedata[tindex];
+
+ ml_dst = &loops_dst[mp_dst->loopstart];
+ for (plidx_dst = 0; plidx_dst < mp_dst->totloop; plidx_dst++, ml_dst++) {
+ if (use_from_vert) {
+ float tmp_co[3];
+ MeshElemMap *vert_to_refelem_map_src = NULL;
+
+ copy_v3_v3(tmp_co, verts_dst[ml_dst->v].co);
+ nearest.index = -1;
+
+ /* Convert the vertex to tree coordinates, if needed. */
+ if (space_transform) {
+ BLI_space_transform_apply(space_transform, tmp_co);
+ }
+
+ if (mesh_remap_bvhtree_query_nearest(tdata, &nearest, tmp_co, max_dist_sq, &hit_dist)) {
+ float (*nor_dst)[3];
+ float (*nors_src)[3];
+ float best_nor_dot = -2.0f;
+ float best_sqdist_fallback = FLT_MAX;
+ int best_index_src = -1;
+
+ if (mode == MREMAP_MODE_LOOP_NEAREST_LOOPNOR) {
+ nor_dst = &loop_nors_dst[plidx_dst + mp_dst->loopstart];
+ nors_src = loop_nors_src;
+ vert_to_refelem_map_src = vert_to_loop_map_src;
+ }
+ else { /* if (mode == MREMAP_MODE_LOOP_NEAREST_POLYNOR) { */
+ nor_dst = pnor_dst;
+ nors_src = poly_nors_src;
+ vert_to_refelem_map_src = vert_to_poly_map_src;
+ }
+
+ for (i = vert_to_refelem_map_src[nearest.index].count; i--;) {
+ const int index_src = vert_to_refelem_map_src[nearest.index].indices[i];
+ const float dot = dot_v3v3(nors_src[index_src], *nor_dst);
+
+ pidx_src = (mode == MREMAP_MODE_LOOP_NEAREST_LOOPNOR) ?
+ loop_to_poly_map_src[index_src] : index_src;
+ /* WARNING! This is not the *real* lidx_src in case of POLYNOR, we only use it
+ * to check we stay on current island (all loops from a given poly are
+ * on same island!). */
+ lidx_src = (mode == MREMAP_MODE_LOOP_NEAREST_LOOPNOR) ?
+ index_src : polys_src[pidx_src].loopstart;
+
+ /* A same vert may be at the boundary of several islands! Hence, we have to ensure
+ * poly/loop we are currently considering *belongs* to current island! */
+ if (use_islands && island_store.items_to_islands[lidx_src] != tindex) {
+ continue;
+ }
+
+ if (dot > best_nor_dot - 1e-6f) {
+ /* We need something as fallback decision in case dest normal matches several
+ * source normals (see T44522), using distance between polys' centers here. */
+ float *pcent_src;
+ float sqdist;
+
+ mp_src = &polys_src[pidx_src];
+ ml_src = &loops_src[mp_src->loopstart];
+
+ if (!pcent_dst_valid) {
+ BKE_mesh_calc_poly_center(
+ mp_dst, &loops_dst[mp_dst->loopstart], verts_dst, pcent_dst);
+ pcent_dst_valid = true;
+ }
+ pcent_src = poly_cents_src[pidx_src];
+ sqdist = len_squared_v3v3(pcent_dst, pcent_src);
+
+ if ((dot > best_nor_dot + 1e-6f) || (sqdist < best_sqdist_fallback)) {
+ best_nor_dot = dot;
+ best_sqdist_fallback = sqdist;
+ best_index_src = index_src;
+ }
+ }
+ }
+ if (mode == MREMAP_MODE_LOOP_NEAREST_POLYNOR) {
+ /* Our best_index_src is a poly one for now!
+ * Have to find its loop matching our closest vertex. */
+ mp_src = &polys_src[best_index_src];
+ ml_src = &loops_src[mp_src->loopstart];
+ for (plidx_src = 0; plidx_src < mp_src->totloop; plidx_src++, ml_src++) {
+ if ((int)ml_src->v == nearest.index) {
+ best_index_src = plidx_src + mp_src->loopstart;
+ break;
+ }
+ }
+ }
+ best_nor_dot = (best_nor_dot + 1.0f) * 0.5f;
+ islands_res[tindex][plidx_dst].factor = hit_dist ? (best_nor_dot / hit_dist) : 1e18f;
+ islands_res[tindex][plidx_dst].hit_dist = hit_dist;
+ islands_res[tindex][plidx_dst].index_src = best_index_src;
+ }
+ else {
+ /* No source for this dest loop! */
+ islands_res[tindex][plidx_dst].factor = 0.0f;
+ islands_res[tindex][plidx_dst].hit_dist = FLT_MAX;
+ islands_res[tindex][plidx_dst].index_src = -1;
+ }
+ }
+ else if (mode & MREMAP_USE_NORPROJ) {
+ float tmp_co[3], tmp_no[3];
+
+ int n = (ray_radius > 0.0f) ? MREMAP_RAYCAST_APPROXIMATE_NR : 1;
+ float w = 1.0f;
+
+ copy_v3_v3(tmp_co, verts_dst[ml_dst->v].co);
+ copy_v3_v3(tmp_no, loop_nors_dst[plidx_dst + mp_dst->loopstart]);
+
+ /* We do our transform here, since we may do several raycast/nearest queries. */
+ if (space_transform) {
+ BLI_space_transform_apply(space_transform, tmp_co);
+ BLI_space_transform_apply_normal(space_transform, tmp_no);
+ }
+
+ while (n--) {
+ if (mesh_remap_bvhtree_query_raycast(
+ tdata, &rayhit, tmp_co, tmp_no, ray_radius / w, max_dist, &hit_dist))
+ {
+ islands_res[tindex][plidx_dst].factor = (hit_dist ? (1.0f / hit_dist) : 1e18f) * w;
+ islands_res[tindex][plidx_dst].hit_dist = hit_dist;
+ islands_res[tindex][plidx_dst].index_src = (int)tdata->looptri[rayhit.index].poly;
+ copy_v3_v3(islands_res[tindex][plidx_dst].hit_point, rayhit.co);
+ break;
+ }
+ /* Next iteration will get bigger radius but smaller weight! */
+ w /= MREMAP_RAYCAST_APPROXIMATE_FAC;
+ }
+ if (n == -1) {
+ /* Fallback to 'nearest' hit here, loops usually comes in 'face group', not good to
+ * have only part of one dest face's loops to map to source.
+ * Note that since we give this a null weight, if whole weight for a given face
+ * is null, it means none of its loop mapped to this source island, hence we can skip it
+ * later.
+ */
+ copy_v3_v3(tmp_co, verts_dst[ml_dst->v].co);
+ nearest.index = -1;
+
+ /* Convert the vertex to tree coordinates, if needed. */
+ if (space_transform) {
+ BLI_space_transform_apply(space_transform, tmp_co);
+ }
+
+ /* In any case, this fallback nearest hit should have no weight at all
+ * in 'best island' decision! */
+ islands_res[tindex][plidx_dst].factor = 0.0f;
+
+ if (mesh_remap_bvhtree_query_nearest(tdata, &nearest, tmp_co, max_dist_sq, &hit_dist)) {
+ islands_res[tindex][plidx_dst].hit_dist = hit_dist;
+ islands_res[tindex][plidx_dst].index_src = (int)tdata->looptri[nearest.index].poly;
+ copy_v3_v3(islands_res[tindex][plidx_dst].hit_point, nearest.co);
+ }
+ else {
+ /* No source for this dest loop! */
+ islands_res[tindex][plidx_dst].hit_dist = FLT_MAX;
+ islands_res[tindex][plidx_dst].index_src = -1;
+ }
+ }
+ }
+ else { /* Nearest poly either to use all its loops/verts or just closest one. */
+ float tmp_co[3];
+
+ copy_v3_v3(tmp_co, verts_dst[ml_dst->v].co);
+ nearest.index = -1;
+
+ /* Convert the vertex to tree coordinates, if needed. */
+ if (space_transform) {
+ BLI_space_transform_apply(space_transform, tmp_co);
+ }
+
+ if (mesh_remap_bvhtree_query_nearest(tdata, &nearest, tmp_co, max_dist_sq, &hit_dist)) {
+ islands_res[tindex][plidx_dst].factor = hit_dist ? (1.0f / hit_dist) : 1e18f;
+ islands_res[tindex][plidx_dst].hit_dist = hit_dist;
+ islands_res[tindex][plidx_dst].index_src = (int)tdata->looptri[nearest.index].poly;
+ copy_v3_v3(islands_res[tindex][plidx_dst].hit_point, nearest.co);
+ }
+ else {
+ /* No source for this dest loop! */
+ islands_res[tindex][plidx_dst].factor = 0.0f;
+ islands_res[tindex][plidx_dst].hit_dist = FLT_MAX;
+ islands_res[tindex][plidx_dst].index_src = -1;
+ }
+ }
+ }
+ }
+
+ /* And now, find best island to use! */
+ /* We have to first select the 'best source island' for given dst poly and its loops.
+ * Then, we have to check that poly does not 'spread' across some island's limits
+ * (like inner seams for UVs, etc.).
+ * Note we only still partially support that kind of situation here, i.e. polys spreading over actual cracks
+ * (like a narrow space without faces on src, splitting a 'tube-like' geometry). That kind of situation
+ * should be relatively rare, though.
+ */
+ /* XXX This block in itself is big and complex enough to be a separate function but... it uses a bunch
+ * of locale vars. Not worth sending all that through parameters (for now at least). */
+ {
+ BLI_AStarGraph *as_graph = NULL;
+ int *poly_island_index_map = NULL;
+ int pidx_src_prev = -1;
+
+ MeshElemMap *best_island = NULL;
+ float best_island_fac = 0.0f;
+ int best_island_index = -1;
+
+ for (tindex = 0; tindex < num_trees; tindex++) {
+ float island_fac = 0.0f;
+
+ for (plidx_dst = 0; plidx_dst < mp_dst->totloop; plidx_dst++) {
+ island_fac += islands_res[tindex][plidx_dst].factor;
+ }
+ island_fac /= (float)mp_dst->totloop;
+
+ if (island_fac > best_island_fac) {
+ best_island_fac = island_fac;
+ best_island_index = tindex;
+ }
+ }
+
+ if (best_island_index != -1 && isld_steps_src) {
+ best_island = use_islands ? island_store.islands[best_island_index] : NULL;
+ as_graph = &as_graphdata[best_island_index];
+ poly_island_index_map = (int *)as_graph->custom_data;
+ BLI_astar_solution_init(as_graph, &as_solution, NULL);
+ }
+
+ for (plidx_dst = 0; plidx_dst < mp_dst->totloop; plidx_dst++) {
+ IslandResult *isld_res;
+ lidx_dst = plidx_dst + mp_dst->loopstart;
+
+ if (best_island_index == -1) {
+ /* No source for any loops of our dest poly in any source islands. */
+ BKE_mesh_remap_item_define_invalid(r_map, lidx_dst);
+ continue;
+ }
+
+ as_solution.custom_data = SET_INT_IN_POINTER(false);
+
+ isld_res = &islands_res[best_island_index][plidx_dst];
+ if (use_from_vert) {
+ /* Indices stored in islands_res are those of loops, one per dest loop. */
+ lidx_src = isld_res->index_src;
+ if (lidx_src >= 0) {
+ pidx_src = loop_to_poly_map_src[lidx_src];
+ /* If prev and curr poly are the same, no need to do anything more!!! */
+ if (!ELEM(pidx_src_prev, -1, pidx_src) && isld_steps_src) {
+ int pidx_isld_src, pidx_isld_src_prev;
+ if (poly_island_index_map) {
+ pidx_isld_src = poly_island_index_map[pidx_src];
+ pidx_isld_src_prev = poly_island_index_map[pidx_src_prev];
+ }
+ else {
+ pidx_isld_src = pidx_src;
+ pidx_isld_src_prev = pidx_src_prev;
+ }
+
+ BLI_astar_graph_solve(
+ as_graph, pidx_isld_src_prev, pidx_isld_src,
+ mesh_remap_calc_loops_astar_f_cost, &as_solution, isld_steps_src);
+ if (GET_INT_FROM_POINTER(as_solution.custom_data) && (as_solution.steps > 0)) {
+ /* Find first 'cutting edge' on path, and bring back lidx_src on poly just
+ * before that edge.
+ * Note we could try to be much smarter (like e.g. storing a whole poly's indices,
+ * and making decision (on which side of cutting edge(s!) to be) on the end,
+ * but this is one more level of complexity, better to first see if
+ * simple solution works!
+ */
+ int last_valid_pidx_isld_src = -1;
+ /* Note we go backward here, from dest to src poly. */
+ for (i = as_solution.steps - 1; i--;) {
+ BLI_AStarGNLink *as_link = as_solution.prev_links[pidx_isld_src];
+ const int eidx = GET_INT_FROM_POINTER(as_link->custom_data);
+ pidx_isld_src = as_solution.prev_nodes[pidx_isld_src];
+ BLI_assert(pidx_isld_src != -1);
+ if (eidx != -1) {
+ /* we are 'crossing' a cutting edge. */
+ last_valid_pidx_isld_src = pidx_isld_src;
+ }
+ }
+ if (last_valid_pidx_isld_src != -1) {
+ /* Find a new valid loop in that new poly (nearest one for now).
+ * Note we could be much more subtle here, again that's for later... */
+ int j;
+ float best_dist_sq = FLT_MAX;
+ float tmp_co[3];
+
+ ml_dst = &loops_dst[lidx_dst];
+ copy_v3_v3(tmp_co, verts_dst[ml_dst->v].co);
+
+ /* We do our transform here, since we may do several raycast/nearest queries. */
+ if (space_transform) {
+ BLI_space_transform_apply(space_transform, tmp_co);
+ }
+
+ pidx_src = use_islands ? best_island->indices[last_valid_pidx_isld_src] :
+ last_valid_pidx_isld_src;
+ mp_src = &polys_src[pidx_src];
+ ml_src = &loops_src[mp_src->loopstart];
+ for (j = 0; j < mp_src->totloop; j++, ml_src++) {
+ const float dist_sq = len_squared_v3v3(verts_src[ml_src->v].co, tmp_co);
+ if (dist_sq < best_dist_sq) {
+ best_dist_sq = dist_sq;
+ lidx_src = mp_src->loopstart + j;
+ }
+ }
+ }
+ }
+ }
+ mesh_remap_item_define(
+ r_map, lidx_dst, isld_res->hit_dist,
+ best_island_index, 1, &lidx_src, &full_weight);
+ pidx_src_prev = pidx_src;
+ }
+ else {
+ /* No source for this loop in this island. */
+ /* TODO: would probably be better to get a source at all cost in best island anyway? */
+ mesh_remap_item_define(
+ r_map, lidx_dst, FLT_MAX,
+ best_island_index, 0, NULL, NULL);
+ }
+ }
+ else {
+ /* Else, we use source poly, indices stored in islands_res are those of polygons. */
+ pidx_src = isld_res->index_src;
+ if (pidx_src >= 0) {
+ float *hit_co = isld_res->hit_point;
+ int best_loop_index_src;
+
+ mp_src = &polys_src[pidx_src];
+ /* If prev and curr poly are the same, no need to do anything more!!! */
+ if (!ELEM(pidx_src_prev, -1, pidx_src) && isld_steps_src) {
+ int pidx_isld_src, pidx_isld_src_prev;
+ if (poly_island_index_map) {
+ pidx_isld_src = poly_island_index_map[pidx_src];
+ pidx_isld_src_prev = poly_island_index_map[pidx_src_prev];
+ }
+ else {
+ pidx_isld_src = pidx_src;
+ pidx_isld_src_prev = pidx_src_prev;
+ }
+
+ BLI_astar_graph_solve(
+ as_graph, pidx_isld_src_prev, pidx_isld_src,
+ mesh_remap_calc_loops_astar_f_cost, &as_solution, isld_steps_src);
+ if (GET_INT_FROM_POINTER(as_solution.custom_data) && (as_solution.steps > 0)) {
+ /* Find first 'cutting edge' on path, and bring back lidx_src on poly just
+ * before that edge.
+ * Note we could try to be much smarter (like e.g. storing a whole poly's indices,
+ * and making decision (one which side of cutting edge(s!) to be on the end,
+ * but this is one more level of complexity, better to first see if
+ * simple solution works!
+ */
+ int last_valid_pidx_isld_src = -1;
+ /* Note we go backward here, from dest to src poly. */
+ for (i = as_solution.steps - 1; i--;) {
+ BLI_AStarGNLink *as_link = as_solution.prev_links[pidx_isld_src];
+ int eidx = GET_INT_FROM_POINTER(as_link->custom_data);
+
+ pidx_isld_src = as_solution.prev_nodes[pidx_isld_src];
+ BLI_assert(pidx_isld_src != -1);
+ if (eidx != -1) {
+ /* we are 'crossing' a cutting edge. */
+ last_valid_pidx_isld_src = pidx_isld_src;
+ }
+ }
+ if (last_valid_pidx_isld_src != -1) {
+ /* Find a new valid loop in that new poly (nearest point on poly for now).
+ * Note we could be much more subtle here, again that's for later... */
+ float best_dist_sq = FLT_MAX;
+ float tmp_co[3];
+ int j;
+
+ ml_dst = &loops_dst[lidx_dst];
+ copy_v3_v3(tmp_co, verts_dst[ml_dst->v].co);
+
+ /* We do our transform here, since we may do several raycast/nearest queries. */
+ if (space_transform) {
+ BLI_space_transform_apply(space_transform, tmp_co);
+ }
+
+ pidx_src = use_islands ? best_island->indices[last_valid_pidx_isld_src] :
+ last_valid_pidx_isld_src;
+ mp_src = &polys_src[pidx_src];
+
+ /* Create that one on demand. */
+ if (poly_to_looptri_map_src == NULL) {
+ BKE_mesh_origindex_map_create_looptri(
+ &poly_to_looptri_map_src, &poly_to_looptri_map_src_buff,
+ polys_src, num_polys_src,
+ looptri_src, num_looptri_src);
+ }
+
+ for (j = poly_to_looptri_map_src[pidx_src].count; j--;) {
+ float h[3];
+ const MLoopTri *lt = &looptri_src[poly_to_looptri_map_src[pidx_src].indices[j]];
+ float dist_sq;
+
+ closest_on_tri_to_point_v3(
+ h, tmp_co,
+ vcos_src[loops_src[lt->tri[0]].v],
+ vcos_src[loops_src[lt->tri[1]].v],
+ vcos_src[loops_src[lt->tri[2]].v]);
+ dist_sq = len_squared_v3v3(tmp_co, h);
+ if (dist_sq < best_dist_sq) {
+ copy_v3_v3(hit_co, h);
+ best_dist_sq = dist_sq;
+ }
+ }
+ }
+ }
+ }
+
+ if (mode == MREMAP_MODE_LOOP_POLY_NEAREST) {
+ mesh_remap_interp_poly_data_get(
+ mp_src, loops_src, (const float (*)[3])vcos_src, hit_co,
+ &buff_size_interp, &vcos_interp, true, &indices_interp,
+ &weights_interp, false, &best_loop_index_src);
+
+ mesh_remap_item_define(
+ r_map, lidx_dst, isld_res->hit_dist,
+ best_island_index, 1, &best_loop_index_src, &full_weight);
+ }
+ else {
+ const int sources_num = mesh_remap_interp_poly_data_get(
+ mp_src, loops_src, (const float (*)[3])vcos_src, hit_co,
+ &buff_size_interp, &vcos_interp, true, &indices_interp,
+ &weights_interp, true, NULL);
+
+ mesh_remap_item_define(
+ r_map, lidx_dst,
+ isld_res->hit_dist, best_island_index,
+ sources_num, indices_interp, weights_interp);
+ }
+
+ pidx_src_prev = pidx_src;
+ }
+ else {
+ /* No source for this loop in this island. */
+ /* TODO: would probably be better to get a source at all cost in best island anyway? */
+ mesh_remap_item_define(r_map, lidx_dst, FLT_MAX, best_island_index, 0, NULL, NULL);
+ }
+ }
+ }
+
+ BLI_astar_solution_clear(&as_solution);
+ }
+ }
+
+ for (tindex = 0; tindex < num_trees; tindex++) {
+ MEM_freeN(islands_res[tindex]);
+ free_bvhtree_from_mesh(&treedata[tindex]);
+ if (isld_steps_src) {
+ BLI_astar_graph_free(&as_graphdata[tindex]);
+ }
+ }
+ MEM_freeN(islands_res);
+ BKE_mesh_loop_islands_free(&island_store);
+ MEM_freeN(treedata);
+ if (isld_steps_src) {
+ MEM_freeN(as_graphdata);
+ BLI_astar_solution_free(&as_solution);
+ }
+
+ if (verts_allocated_src) {
+ MEM_freeN(verts_src);
+ }
+ if (vcos_src) {
+ MEM_freeN(vcos_src);
+ }
+ if (edges_allocated_src) {
+ MEM_freeN(edges_src);
+ }
+ if (loops_allocated_src) {
+ MEM_freeN(loops_src);
+ }
+ if (polys_allocated_src) {
+ MEM_freeN(polys_src);
+ }
+ if (looptri_allocated_src) {
+ MEM_freeN((void *)looptri_src);
+ }
+ if (vert_to_loop_map_src) {
+ MEM_freeN(vert_to_loop_map_src);
+ }
+ if (vert_to_loop_map_src_buff) {
+ MEM_freeN(vert_to_loop_map_src_buff);
+ }
+ if (vert_to_poly_map_src) {
+ MEM_freeN(vert_to_poly_map_src);
+ }
+ if (vert_to_poly_map_src_buff) {
+ MEM_freeN(vert_to_poly_map_src_buff);
+ }
+ if (edge_to_poly_map_src) {
+ MEM_freeN(edge_to_poly_map_src);
+ }
+ if (edge_to_poly_map_src_buff) {
+ MEM_freeN(edge_to_poly_map_src_buff);
+ }
+ if (poly_to_looptri_map_src) {
+ MEM_freeN(poly_to_looptri_map_src);
+ }
+ if (poly_to_looptri_map_src_buff) {
+ MEM_freeN(poly_to_looptri_map_src_buff);
+ }
+ if (loop_to_poly_map_src) {
+ MEM_freeN(loop_to_poly_map_src);
+ }
+ if (poly_cents_src) {
+ MEM_freeN(poly_cents_src);
+ }
+ if (vcos_interp) {
+ MEM_freeN(vcos_interp);
+ }
+ if (indices_interp) {
+ MEM_freeN(indices_interp);
+ }
+ if (weights_interp) {
+ MEM_freeN(weights_interp);
+ }
+ }
+}
+
+void BKE_mesh_remap_calc_polys_from_dm(
+ const int mode, const SpaceTransform *space_transform, const float max_dist, const float ray_radius,
+ MVert *verts_dst, const int numverts_dst, MLoop *loops_dst, const int numloops_dst,
+ MPoly *polys_dst, const int numpolys_dst, CustomData *pdata_dst, const bool dirty_nors_dst,
+ DerivedMesh *dm_src, MeshPairRemap *r_map)
+{
+ const float full_weight = 1.0f;
+ const float max_dist_sq = max_dist * max_dist;
+ float (*poly_nors_dst)[3] = NULL;
+ int i;
+
+ BLI_assert(mode & MREMAP_MODE_POLY);
+
+ if (mode & (MREMAP_USE_NORMAL | MREMAP_USE_NORPROJ)) {
+ /* Cache poly nors into a temp CDLayer. */
+ poly_nors_dst = CustomData_get_layer(pdata_dst, CD_NORMAL);
+ if (!poly_nors_dst) {
+ poly_nors_dst = CustomData_add_layer(pdata_dst, CD_NORMAL, CD_CALLOC, NULL, numpolys_dst);
+ CustomData_set_layer_flag(pdata_dst, CD_NORMAL, CD_FLAG_TEMPORARY);
+ }
+ if (dirty_nors_dst) {
+ BKE_mesh_calc_normals_poly(verts_dst, numverts_dst, loops_dst, polys_dst, numloops_dst, numpolys_dst,
+ poly_nors_dst, true);
+ }
+ }
+
+ BKE_mesh_remap_init(r_map, numpolys_dst);
+
+ if (mode == MREMAP_MODE_TOPOLOGY) {
+ BLI_assert(numpolys_dst == dm_src->getNumPolys(dm_src));
+ for (i = 0; i < numpolys_dst; i++) {
+ mesh_remap_item_define(r_map, i, FLT_MAX, 0, 1, &i, &full_weight);
+ }
+ }
+ else {
+ BVHTreeFromMesh treedata = {NULL};
+ BVHTreeNearest nearest = {0};
+ BVHTreeRayHit rayhit = {0};
+ float hit_dist;
+
+ bvhtree_from_mesh_looptri(
+ &treedata, dm_src,
+ (mode & MREMAP_USE_NORPROJ) ? MREMAP_RAYCAST_APPROXIMATE_BVHEPSILON(ray_radius) : 0.0f,
+ 2, 6);
+
+ if (mode == MREMAP_MODE_POLY_NEAREST) {
+ nearest.index = -1;
+
+ for (i = 0; i < numpolys_dst; i++) {
+ MPoly *mp = &polys_dst[i];
+ float tmp_co[3];
+
+ BKE_mesh_calc_poly_center(mp, &loops_dst[mp->loopstart], verts_dst, tmp_co);
+
+ /* Convert the vertex to tree coordinates, if needed. */
+ if (space_transform) {
+ BLI_space_transform_apply(space_transform, tmp_co);
+ }
+
+ if (mesh_remap_bvhtree_query_nearest(&treedata, &nearest, tmp_co, max_dist_sq, &hit_dist)) {
+ const MLoopTri *lt = &treedata.looptri[nearest.index];
+ const int poly_index = (int)lt->poly;
+ mesh_remap_item_define(
+ r_map, i, hit_dist, 0,
+ 1, &poly_index, &full_weight);
+ }
+ else {
+ /* No source for this dest poly! */
+ BKE_mesh_remap_item_define_invalid(r_map, i);
+ }
+ }
+ }
+ else if (mode == MREMAP_MODE_POLY_NOR) {
+ BLI_assert(poly_nors_dst);
+
+ for (i = 0; i < numpolys_dst; i++) {
+ MPoly *mp = &polys_dst[i];
+ float tmp_co[3], tmp_no[3];
+
+ BKE_mesh_calc_poly_center(mp, &loops_dst[mp->loopstart], verts_dst, tmp_co);
+ copy_v3_v3(tmp_no, poly_nors_dst[i]);
+
+ /* Convert the vertex to tree coordinates, if needed. */
+ if (space_transform) {
+ BLI_space_transform_apply(space_transform, tmp_co);
+ BLI_space_transform_apply_normal(space_transform, tmp_no);
+ }
+
+ if (mesh_remap_bvhtree_query_raycast(
+ &treedata, &rayhit, tmp_co, tmp_no, ray_radius, max_dist, &hit_dist))
+ {
+ const MLoopTri *lt = &treedata.looptri[rayhit.index];
+ const int poly_index = (int)lt->poly;
+
+ mesh_remap_item_define(
+ r_map, i, hit_dist, 0,
+ 1, &poly_index, &full_weight);
+ }
+ else {
+ /* No source for this dest poly! */
+ BKE_mesh_remap_item_define_invalid(r_map, i);
+ }
+ }
+ }
+ else if (mode == MREMAP_MODE_POLY_POLYINTERP_PNORPROJ) {
+ /* We cast our rays randomly, with a pseudo-even distribution (since we spread across tessellated tris,
+ * with additional weighting based on each tri's relative area).
+ */
+ RNG *rng = BLI_rng_new(0);
+
+ const size_t numpolys_src = (size_t)dm_src->getNumPolys(dm_src);
+
+ /* Here it's simpler to just allocate for all polys :/ */
+ int *indices = MEM_mallocN(sizeof(*indices) * numpolys_src, __func__);
+ float *weights = MEM_mallocN(sizeof(*weights) * numpolys_src, __func__);
+
+ size_t tmp_poly_size = MREMAP_DEFAULT_BUFSIZE;
+ float (*poly_vcos_2d)[2] = MEM_mallocN(sizeof(*poly_vcos_2d) * tmp_poly_size, __func__);
+ /* Tessellated 2D poly, always (num_loops - 2) triangles. */
+ int (*tri_vidx_2d)[3] = MEM_mallocN(sizeof(*tri_vidx_2d) * (tmp_poly_size - 2), __func__);
+
+ for (i = 0; i < numpolys_dst; i++) {
+ /* For each dst poly, we sample some rays from it (2D grid in pnor space)
+ * and use their hits to interpolate from source polys. */
+ /* Note: dst poly is early-converted into src space! */
+ MPoly *mp = &polys_dst[i];
+ float tmp_co[3], tmp_no[3];
+
+ int tot_rays, done_rays = 0;
+ float poly_area_2d_inv, done_area = 0.0f;
+
+ float pcent_dst[3];
+ float to_pnor_2d_mat[3][3], from_pnor_2d_mat[3][3];
+ float poly_dst_2d_min[2], poly_dst_2d_max[2], poly_dst_2d_z;
+ float poly_dst_2d_size[2];
+
+ float totweights = 0.0f;
+ float hit_dist_accum = 0.0f;
+ int sources_num = 0;
+ const int tris_num = mp->totloop - 2;
+ int j;
+
+ BKE_mesh_calc_poly_center(mp, &loops_dst[mp->loopstart], verts_dst, pcent_dst);
+ copy_v3_v3(tmp_no, poly_nors_dst[i]);
+
+ /* We do our transform here, else it'd be redone by raycast helper for each ray, ugh! */
+ if (space_transform) {
+ BLI_space_transform_apply(space_transform, pcent_dst);
+ BLI_space_transform_apply_normal(space_transform, tmp_no);
+ }
+
+ copy_vn_fl(weights, (int)numpolys_src, 0.0f);
+
+ if (UNLIKELY((size_t)mp->totloop > tmp_poly_size)) {
+ tmp_poly_size = (size_t)mp->totloop;
+ poly_vcos_2d = MEM_reallocN(poly_vcos_2d, sizeof(*poly_vcos_2d) * tmp_poly_size);
+ tri_vidx_2d = MEM_reallocN(tri_vidx_2d, sizeof(*tri_vidx_2d) * (tmp_poly_size - 2));
+ }
+
+ axis_dominant_v3_to_m3(to_pnor_2d_mat, tmp_no);
+ invert_m3_m3(from_pnor_2d_mat, to_pnor_2d_mat);
+
+ mul_m3_v3(to_pnor_2d_mat, pcent_dst);
+ poly_dst_2d_z = pcent_dst[2];
+
+ /* Get (2D) bounding square of our poly. */
+ INIT_MINMAX2(poly_dst_2d_min, poly_dst_2d_max);
+
+ for (j = 0; j < mp->totloop; j++) {
+ MLoop *ml = &loops_dst[j + mp->loopstart];
+ copy_v3_v3(tmp_co, verts_dst[ml->v].co);
+ if (space_transform) {
+ BLI_space_transform_apply(space_transform, tmp_co);
+ }
+ mul_v2_m3v3(poly_vcos_2d[j], to_pnor_2d_mat, tmp_co);
+ minmax_v2v2_v2(poly_dst_2d_min, poly_dst_2d_max, poly_vcos_2d[j]);
+ }
+
+ /* We adjust our ray-casting grid to ray_radius (the smaller, the more rays are cast),
+ * with lower/upper bounds. */
+ sub_v2_v2v2(poly_dst_2d_size, poly_dst_2d_max, poly_dst_2d_min);
+
+ if (ray_radius) {
+ tot_rays = (int)((max_ff(poly_dst_2d_size[0], poly_dst_2d_size[1]) / ray_radius) + 0.5f);
+ CLAMP(tot_rays, MREMAP_RAYCAST_TRI_SAMPLES_MIN, MREMAP_RAYCAST_TRI_SAMPLES_MAX);
+ }
+ else {
+ /* If no radius (pure rays), give max number of rays! */
+ tot_rays = MREMAP_RAYCAST_TRI_SAMPLES_MIN;
+ }
+ tot_rays *= tot_rays;
+
+ poly_area_2d_inv = area_poly_v2((const float(*)[2])poly_vcos_2d, (unsigned int)mp->totloop);
+ /* In case we have a null-area degenerated poly... */
+ poly_area_2d_inv = 1.0f / max_ff(poly_area_2d_inv, 1e-9f);
+
+ /* Tessellate our poly. */
+ if (mp->totloop == 3) {
+ tri_vidx_2d[0][0] = 0;
+ tri_vidx_2d[0][1] = 1;
+ tri_vidx_2d[0][2] = 2;
+ }
+ if (mp->totloop == 4) {
+ tri_vidx_2d[0][0] = 0;
+ tri_vidx_2d[0][1] = 1;
+ tri_vidx_2d[0][2] = 2;
+ tri_vidx_2d[1][0] = 0;
+ tri_vidx_2d[1][1] = 2;
+ tri_vidx_2d[1][2] = 3;
+ }
+ else {
+ BLI_polyfill_calc((const float(*)[2])poly_vcos_2d, (unsigned int)mp->totloop, -1,
+ (unsigned int (*)[3])tri_vidx_2d);
+ }
+
+ for (j = 0; j < tris_num; j++) {
+ float *v1 = poly_vcos_2d[tri_vidx_2d[j][0]];
+ float *v2 = poly_vcos_2d[tri_vidx_2d[j][1]];
+ float *v3 = poly_vcos_2d[tri_vidx_2d[j][2]];
+ int rays_num;
+
+ /* All this allows us to get 'absolute' number of rays for each tri, avoiding accumulating
+ * errors over iterations, and helping better even distribution. */
+ done_area += area_tri_v2(v1, v2, v3);
+ rays_num = max_ii((int)((float)tot_rays * done_area * poly_area_2d_inv + 0.5f) - done_rays, 0);
+ done_rays += rays_num;
+
+ while (rays_num--) {
+ int n = (ray_radius > 0.0f) ? MREMAP_RAYCAST_APPROXIMATE_NR : 1;
+ float w = 1.0f;
+
+ BLI_rng_get_tri_sample_float_v2(rng, v1, v2, v3, tmp_co);
+
+ tmp_co[2] = poly_dst_2d_z;
+ mul_m3_v3(from_pnor_2d_mat, tmp_co);
+
+ /* At this point, tmp_co is a point on our poly surface, in mesh_src space! */
+ while (n--) {
+ if (mesh_remap_bvhtree_query_raycast(
+ &treedata, &rayhit, tmp_co, tmp_no, ray_radius / w, max_dist, &hit_dist))
+ {
+ const MLoopTri *lt = &treedata.looptri[rayhit.index];
+
+ weights[lt->poly] += w;
+ totweights += w;
+ hit_dist_accum += hit_dist;
+ break;
+ }
+ /* Next iteration will get bigger radius but smaller weight! */
+ w /= MREMAP_RAYCAST_APPROXIMATE_FAC;
+ }
+ }
+ }
+
+ if (totweights > 0.0f) {
+ for (j = 0; j < (int)numpolys_src; j++) {
+ if (!weights[j]) {
+ continue;
+ }
+ /* Note: sources_num is always <= j! */
+ weights[sources_num] = weights[j] / totweights;
+ indices[sources_num] = j;
+ sources_num++;
+ }
+ mesh_remap_item_define(r_map, i, hit_dist_accum / totweights, 0, sources_num, indices, weights);
+ }
+ else {
+ /* No source for this dest poly! */
+ BKE_mesh_remap_item_define_invalid(r_map, i);
+ }
+ }
+
+ MEM_freeN(tri_vidx_2d);
+ MEM_freeN(poly_vcos_2d);
+ MEM_freeN(indices);
+ MEM_freeN(weights);
+ BLI_rng_free(rng);
+ }
+ else {
+ printf("WARNING! Unsupported mesh-to-mesh poly mapping mode (%d)!\n", mode);
+ memset(r_map->items, 0, sizeof(*r_map->items) * (size_t)numpolys_dst);
+ }
+
+ free_bvhtree_from_mesh(&treedata);
+ }
+}
+
+#undef MREMAP_RAYCAST_APPROXIMATE_NR
+#undef MREMAP_RAYCAST_APPROXIMATE_FAC
+#undef MREMAP_RAYCAST_APPROXIMATE_BVHEPSILON
+#undef MREMAP_RAYCAST_TRI_SAMPLES_MIN
+#undef MREMAP_RAYCAST_TRI_SAMPLES_MAX
+#undef MREMAP_DEFAULT_BUFSIZE
+
+/** \} */
diff --git a/source/blender/blenkernel/intern/mesh_validate.c b/source/blender/blenkernel/intern/mesh_validate.c
index f3a9e894eb3..e21dde9c726 100644
--- a/source/blender/blenkernel/intern/mesh_validate.c
+++ b/source/blender/blenkernel/intern/mesh_validate.c
@@ -222,11 +222,11 @@ bool BKE_mesh_validate_arrays(Mesh *mesh,
const bool do_verbose, const bool do_fixes,
bool *r_changed)
{
-# define REMOVE_EDGE_TAG(_me) { _me->v2 = _me->v1; do_edge_free = true; } (void)0
+# define REMOVE_EDGE_TAG(_me) { _me->v2 = _me->v1; free_flag.edges = do_fixes; } (void)0
# define IS_REMOVED_EDGE(_me) (_me->v2 == _me->v1)
-# define REMOVE_LOOP_TAG(_ml) { _ml->e = INVALID_LOOP_EDGE_MARKER; do_polyloop_free = true; } (void)0
-# define REMOVE_POLY_TAG(_mp) { _mp->totloop *= -1; do_polyloop_free = true; } (void)0
+# define REMOVE_LOOP_TAG(_ml) { _ml->e = INVALID_LOOP_EDGE_MARKER; free_flag.polyloops = do_fixes; } (void)0
+# define REMOVE_POLY_TAG(_mp) { _mp->totloop *= -1; free_flag.polyloops = do_fixes; } (void)0
MVert *mv = mverts;
MEdge *me;
@@ -237,26 +237,46 @@ bool BKE_mesh_validate_arrays(Mesh *mesh,
bool is_valid = true;
- bool do_edge_free = false;
- bool do_face_free = false;
- bool do_polyloop_free = false; /* This regroups loops and polys! */
-
- bool verts_fixed = false;
- bool vert_weights_fixed = false;
- bool msel_fixed = false;
-
- bool do_edge_recalc = false;
+ union {
+ struct {
+ int verts : 1;
+ int verts_weight : 1;
+ };
+ int as_flag;
+ } fix_flag;
+
+ union {
+ struct {
+ int edges : 1;
+ int faces : 1;
+ /* This regroups loops and polys! */
+ int polyloops : 1;
+ int mselect : 1;
+ };
+ int as_flag;
+ } free_flag;
+
+ union {
+ struct {
+ int edges : 1;
+ };
+ int as_flag;
+ } recalc_flag;
EdgeHash *edge_hash = BLI_edgehash_new_ex(__func__, totedge);
BLI_assert(!(do_fixes && mesh == NULL));
+ fix_flag.as_flag = 0;
+ free_flag.as_flag = 0;
+ recalc_flag.as_flag = 0;
+
PRINT_MSG("%s: verts(%u), edges(%u), loops(%u), polygons(%u)\n",
__func__, totvert, totedge, totloop, totpoly);
if (totedge == 0 && totpoly != 0) {
PRINT_ERR("\tLogical error, %u polygons and 0 edges\n", totpoly);
- do_edge_recalc = do_fixes;
+ recalc_flag.edges = do_fixes;
}
for (i = 0; i < totvert; i++, mv++) {
@@ -269,7 +289,7 @@ bool BKE_mesh_validate_arrays(Mesh *mesh,
if (do_fixes) {
zero_v3(mv->co);
- verts_fixed = true;
+ fix_flag.verts = true;
}
}
@@ -281,13 +301,14 @@ bool BKE_mesh_validate_arrays(Mesh *mesh,
PRINT_ERR("\tVertex %u: has zero normal, assuming Z-up normal\n", i);
if (do_fixes) {
mv->no[2] = SHRT_MAX;
- verts_fixed = true;
+ fix_flag.verts = true;
}
}
}
for (i = 0, me = medges; i < totedge; i++, me++) {
bool remove = false;
+
if (me->v1 == me->v2) {
PRINT_ERR("\tEdge %u: has matching verts, both %u\n", i, me->v1);
remove = do_fixes;
@@ -301,14 +322,16 @@ bool BKE_mesh_validate_arrays(Mesh *mesh,
remove = do_fixes;
}
- if (BLI_edgehash_haskey(edge_hash, me->v1, me->v2)) {
+ if ((me->v1 != me->v2) && BLI_edgehash_haskey(edge_hash, me->v1, me->v2)) {
PRINT_ERR("\tEdge %u: is a duplicate of %d\n", i,
GET_INT_FROM_POINTER(BLI_edgehash_lookup(edge_hash, me->v1, me->v2)));
remove = do_fixes;
}
if (remove == false) {
- BLI_edgehash_insert(edge_hash, me->v1, me->v2, SET_INT_IN_POINTER(i));
+ if (me->v1 != me->v2) {
+ BLI_edgehash_insert(edge_hash, me->v1, me->v2, SET_INT_IN_POINTER(i));
+ }
}
else {
REMOVE_EDGE_TAG(me);
@@ -316,7 +339,7 @@ bool BKE_mesh_validate_arrays(Mesh *mesh,
}
if (mfaces && !mpolys) {
-# define REMOVE_FACE_TAG(_mf) { _mf->v3 = 0; do_face_free = true; } (void)0
+# define REMOVE_FACE_TAG(_mf) { _mf->v3 = 0; free_flag.faces = do_fixes; } (void)0
# define CHECK_FACE_VERT_INDEX(a, b) \
if (mf->a == mf->b) { \
PRINT_ERR(" face %u: verts invalid, " STRINGIFY(a) "/" STRINGIFY(b) " both %u\n", i, mf->a); \
@@ -326,7 +349,7 @@ bool BKE_mesh_validate_arrays(Mesh *mesh,
if (!BLI_edgehash_haskey(edge_hash, mf->a, mf->b)) { \
PRINT_ERR(" face %u: edge " STRINGIFY(a) "/" STRINGIFY(b) \
" (%u,%u) is missing edge data\n", i, mf->a, mf->b); \
- do_edge_recalc = true; \
+ recalc_flag.edges = do_fixes; \
} (void)0
MFace *mf;
@@ -477,13 +500,13 @@ bool BKE_mesh_validate_arrays(Mesh *mesh,
if (mp->loopstart < 0 || mp->totloop < 3) {
/* Invalid loop data. */
- PRINT_ERR("\tPoly %u is invalid (loopstart: %u, totloop: %u)\n",
+ PRINT_ERR("\tPoly %u is invalid (loopstart: %d, totloop: %d)\n",
sp->index, mp->loopstart, mp->totloop);
sp->invalid = true;
}
else if (mp->loopstart + mp->totloop > totloop) {
/* Invalid loop data. */
- PRINT_ERR("\tPoly %u uses loops out of range (loopstart: %u, loopend: %u, max nbr of loops: %u)\n",
+ PRINT_ERR("\tPoly %u uses loops out of range (loopstart: %d, loopend: %d, max nbr of loops: %u)\n",
sp->index, mp->loopstart, mp->loopstart + mp->totloop - 1, totloop - 1);
sp->invalid = true;
}
@@ -529,9 +552,9 @@ bool BKE_mesh_validate_arrays(Mesh *mesh,
v2 = mloops[sp->loopstart + (j + 1) % mp->totloop].v;
if (!BLI_edgehash_haskey(edge_hash, v1, v2)) {
/* Edge not existing. */
- PRINT_ERR("\tPoly %u needs missing edge (%u, %u)\n", sp->index, v1, v2);
+ PRINT_ERR("\tPoly %u needs missing edge (%d, %d)\n", sp->index, v1, v2);
if (do_fixes)
- do_edge_recalc = true;
+ recalc_flag.edges = true;
else
sp->invalid = true;
}
@@ -541,7 +564,7 @@ bool BKE_mesh_validate_arrays(Mesh *mesh,
if (do_fixes) {
int prev_e = ml->e;
ml->e = GET_INT_FROM_POINTER(BLI_edgehash_lookup(edge_hash, v1, v2));
- PRINT_ERR("\tLoop %u has invalid edge reference (%u), fixed using edge %u\n",
+ PRINT_ERR("\tLoop %u has invalid edge reference (%d), fixed using edge %u\n",
sp->loopstart + j, prev_e, ml->e);
}
else {
@@ -557,7 +580,7 @@ bool BKE_mesh_validate_arrays(Mesh *mesh,
if (do_fixes) {
int prev_e = ml->e;
ml->e = GET_INT_FROM_POINTER(BLI_edgehash_lookup(edge_hash, v1, v2));
- PRINT_ERR("\tPoly %u has invalid edge reference (%u), fixed using edge %u\n",
+ PRINT_ERR("\tPoly %u has invalid edge reference (%d), fixed using edge %u\n",
sp->index, prev_e, ml->e);
}
else {
@@ -579,7 +602,7 @@ bool BKE_mesh_validate_arrays(Mesh *mesh,
if (*v != *prev_v) {
int dlt = v - prev_v;
if (dlt > 1) {
- PRINT_ERR("\tPoly %u is invalid, it multi-uses vertex %u (%u times)\n",
+ PRINT_ERR("\tPoly %u is invalid, it multi-uses vertex %d (%d times)\n",
sp->index, *prev_v, dlt);
sp->invalid = true;
}
@@ -587,7 +610,7 @@ bool BKE_mesh_validate_arrays(Mesh *mesh,
}
}
if (v - prev_v > 1) { /* Don't forget final verts! */
- PRINT_ERR("\tPoly %u is invalid, it multi-uses vertex %u (%u times)\n",
+ PRINT_ERR("\tPoly %u is invalid, it multi-uses vertex %d (%d times)\n",
sp->index, *prev_v, (int)(v - prev_v));
sp->invalid = true;
}
@@ -666,10 +689,10 @@ bool BKE_mesh_validate_arrays(Mesh *mesh,
}
if ((p1_nv == p2_nv) && (memcmp(p1_v, p2_v, p1_nv * sizeof(*p1_v)) == 0)) {
if (do_verbose) {
- PRINT_ERR("\tPolys %u and %u use same vertices (%u",
+ PRINT_ERR("\tPolys %u and %u use same vertices (%d",
prev_sp->index, sp->index, *p1_v);
for (j = 1; j < p1_nv; j++)
- PRINT_ERR(", %u", p1_v[j]);
+ PRINT_ERR(", %d", p1_v[j]);
PRINT_ERR("), considering poly %u as invalid.\n", sp->index);
}
else {
@@ -718,7 +741,7 @@ bool BKE_mesh_validate_arrays(Mesh *mesh,
}
/* Multi-used loops. */
else if (prev_end > sp->loopstart) {
- PRINT_ERR("\tPolys %u and %u share loops from %u to %u, considering poly %u as invalid.\n",
+ PRINT_ERR("\tPolys %u and %u share loops from %d to %d, considering poly %u as invalid.\n",
prev_sp->index, sp->index, sp->loopstart, prev_end, sp->index);
if (do_fixes) {
REMOVE_POLY_TAG((&mpolys[sp->index]));
@@ -755,19 +778,19 @@ bool BKE_mesh_validate_arrays(Mesh *mesh,
MDeformWeight *dw;
for (j = 0, dw = dv->dw; j < dv->totweight; j++, dw++) {
- /* note, greater then max defgroups is accounted for in our code, but not < 0 */
+ /* note, greater than max defgroups is accounted for in our code, but not < 0 */
if (!finite(dw->weight)) {
PRINT_ERR("\tVertex deform %u, group %d has weight: %f\n", i, dw->def_nr, dw->weight);
if (do_fixes) {
dw->weight = 0.0f;
- vert_weights_fixed = true;
+ fix_flag.verts_weight = true;
}
}
else if (dw->weight < 0.0f || dw->weight > 1.0f) {
PRINT_ERR("\tVertex deform %u, group %d has weight: %f\n", i, dw->def_nr, dw->weight);
if (do_fixes) {
CLAMP(dw->weight, 0.0f, 1.0f);
- vert_weights_fixed = true;
+ fix_flag.verts_weight = true;
}
}
@@ -775,13 +798,14 @@ bool BKE_mesh_validate_arrays(Mesh *mesh,
PRINT_ERR("\tVertex deform %u, has invalid group %d\n", i, dw->def_nr);
if (do_fixes) {
defvert_remove_group(dv, dw);
+ fix_flag.verts_weight = true;
+
if (dv->dw) {
/* re-allocated, the new values compensate for stepping
* within the for loop and may not be valid */
j--;
dw = dv->dw + j;
- vert_weights_fixed = true;
}
else { /* all freed */
break;
@@ -798,34 +822,33 @@ bool BKE_mesh_validate_arrays(Mesh *mesh,
# undef REMOVE_POLY_TAG
if (mesh) {
- if (do_face_free) {
+ if (free_flag.faces) {
BKE_mesh_strip_loose_faces(mesh);
}
- if (do_polyloop_free) {
+ if (free_flag.polyloops) {
BKE_mesh_strip_loose_polysloops(mesh);
}
- if (do_edge_free) {
+ if (free_flag.edges) {
BKE_mesh_strip_loose_edges(mesh);
}
- if (do_edge_recalc) {
+ if (recalc_flag.edges) {
BKE_mesh_calc_edges(mesh, true, false);
}
}
if (mesh && mesh->mselect) {
MSelect *msel;
- bool free_msel = false;
for (i = 0, msel = mesh->mselect; i < mesh->totselect; i++, msel++) {
int tot_elem = 0;
if (msel->index < 0) {
- PRINT_ERR("\tMesh select element %d type %d index is negative, "
+ PRINT_ERR("\tMesh select element %u type %d index is negative, "
"resetting selection stack.\n", i, msel->type);
- free_msel = true;
+ free_flag.mselect = do_fixes;
break;
}
@@ -842,15 +865,15 @@ bool BKE_mesh_validate_arrays(Mesh *mesh,
}
if (msel->index > tot_elem) {
- PRINT_ERR("\tMesh select element %d type %d index %d is larger than data array size %d, "
+ PRINT_ERR("\tMesh select element %u type %d index %d is larger than data array size %d, "
"resetting selection stack.\n", i, msel->type, msel->index, tot_elem);
- free_msel = true;
+ free_flag.mselect = do_fixes;
break;
}
}
- if (free_msel) {
+ if (free_flag.mselect) {
MEM_freeN(mesh->mselect);
mesh->mselect = NULL;
mesh->totselect = 0;
@@ -859,7 +882,11 @@ bool BKE_mesh_validate_arrays(Mesh *mesh,
PRINT_MSG("%s: finished\n\n", __func__);
- *r_changed = (verts_fixed || vert_weights_fixed || do_polyloop_free || do_edge_free || do_edge_recalc || msel_fixed);
+ *r_changed = (fix_flag.as_flag || free_flag.as_flag || recalc_flag.as_flag);
+
+ if (do_fixes == false) {
+ BLI_assert(*r_changed == false);
+ }
return is_valid;
}
@@ -953,6 +980,24 @@ bool BKE_mesh_validate_all_customdata(CustomData *vdata, CustomData *edata,
MAX_MCOL, tot_vcolloop - MAX_MCOL);
}
+ /* check indices of clone/stencil */
+ if (do_fixes && CustomData_get_clone_layer(pdata, CD_MTEXPOLY) >= tot_texpoly) {
+ CustomData_set_layer_clone(pdata, CD_MTEXPOLY, 0);
+ is_change_p = true;
+ }
+ if (do_fixes && CustomData_get_clone_layer(ldata, CD_MLOOPUV) >= tot_uvloop) {
+ CustomData_set_layer_clone(ldata, CD_MLOOPUV, 0);
+ is_change_l = true;
+ }
+ if (do_fixes && CustomData_get_stencil_layer(pdata, CD_MTEXPOLY) >= tot_texpoly) {
+ CustomData_set_layer_stencil(pdata, CD_MTEXPOLY, 0);
+ is_change_p = true;
+ }
+ if (do_fixes && CustomData_get_stencil_layer(ldata, CD_MLOOPUV) >= tot_uvloop) {
+ CustomData_set_layer_stencil(ldata, CD_MLOOPUV, 0);
+ is_change_l = true;
+ }
+
*r_change = (is_change_v || is_change_e || is_change_l || is_change_p);
return is_valid;
@@ -963,7 +1008,7 @@ bool BKE_mesh_validate_all_customdata(CustomData *vdata, CustomData *edata,
*
* \returns true if a change is made.
*/
-int BKE_mesh_validate(Mesh *me, const int do_verbose)
+int BKE_mesh_validate(Mesh *me, const int do_verbose, const int cddata_check_mask)
{
bool is_valid = true;
bool changed;
@@ -974,7 +1019,7 @@ int BKE_mesh_validate(Mesh *me, const int do_verbose)
is_valid &= BKE_mesh_validate_all_customdata(
&me->vdata, &me->edata, &me->ldata, &me->pdata,
- true,
+ cddata_check_mask,
do_verbose, true,
&changed);
@@ -1445,12 +1490,15 @@ void BKE_mesh_calc_edges(Mesh *mesh, bool update, const bool select)
/* mesh loops (bmesh only) */
for (mp = mesh->mpoly, i = 0; i < totpoly; mp++, i++) {
MLoop *l = &mesh->mloop[mp->loopstart];
- int j, l_prev = (l + (mp->totloop - 1))->v;
+ int j, v_prev = (l + (mp->totloop - 1))->v;
for (j = 0; j < mp->totloop; j++, l++) {
- if (!BLI_edgehash_haskey(eh, l_prev, l->v)) {
- BLI_edgehash_insert(eh, l_prev, l->v, NULL);
+ if (v_prev != l->v) {
+ void **val_p;
+ if (!BLI_edgehash_ensure_p(eh, v_prev, l->v, &val_p)) {
+ *val_p = NULL;
+ }
}
- l_prev = l->v;
+ v_prev = l->v;
}
}
diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c
index a9e853c873e..b2c0c6d6d0a 100644
--- a/source/blender/blenkernel/intern/modifier.c
+++ b/source/blender/blenkernel/intern/modifier.c
@@ -47,7 +47,6 @@
#include "DNA_armature_types.h"
#include "DNA_object_types.h"
-#include "DNA_meshdata_types.h"
#include "BLI_utildefines.h"
#include "BLI_path_util.h"
@@ -55,8 +54,9 @@
#include "BLI_linklist.h"
#include "BLI_string.h"
-#include "BLF_translation.h"
+#include "BLT_translation.h"
+#include "BKE_appdir.h"
#include "BKE_key.h"
#include "BKE_multires.h"
#include "BKE_DerivedMesh.h"
@@ -101,7 +101,7 @@ void BKE_modifier_init(void)
virtualModifierCommonData.smd.modifier.mode |= eModifierMode_Virtual;
}
-ModifierTypeInfo *modifierType_getInfo(ModifierType type)
+const ModifierTypeInfo *modifierType_getInfo(ModifierType type)
{
/* type unsigned, no need to check < 0 */
if (type < NUM_MODIFIER_TYPES && modifier_types[type]->name[0] != '\0') {
@@ -116,7 +116,7 @@ ModifierTypeInfo *modifierType_getInfo(ModifierType type)
ModifierData *modifier_new(int type)
{
- ModifierTypeInfo *mti = modifierType_getInfo(type);
+ const ModifierTypeInfo *mti = modifierType_getInfo(type);
ModifierData *md = MEM_callocN(mti->structSize, mti->structName);
/* note, this name must be made unique later */
@@ -135,7 +135,7 @@ ModifierData *modifier_new(int type)
void modifier_free(ModifierData *md)
{
- ModifierTypeInfo *mti = modifierType_getInfo(md->type);
+ const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
if (mti->freeData) mti->freeData(md);
if (md->error) MEM_freeN(md->error);
@@ -143,25 +143,26 @@ void modifier_free(ModifierData *md)
MEM_freeN(md);
}
-void modifier_unique_name(ListBase *modifiers, ModifierData *md)
+bool modifier_unique_name(ListBase *modifiers, ModifierData *md)
{
if (modifiers && md) {
- ModifierTypeInfo *mti = modifierType_getInfo(md->type);
+ const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
- BLI_uniquename(modifiers, md, DATA_(mti->name), '.', offsetof(ModifierData, name), sizeof(md->name));
+ return BLI_uniquename(modifiers, md, DATA_(mti->name), '.', offsetof(ModifierData, name), sizeof(md->name));
}
+ return false;
}
bool modifier_dependsOnTime(ModifierData *md)
{
- ModifierTypeInfo *mti = modifierType_getInfo(md->type);
+ const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
return mti->dependsOnTime && mti->dependsOnTime(md);
}
bool modifier_supportsMapping(ModifierData *md)
{
- ModifierTypeInfo *mti = modifierType_getInfo(md->type);
+ const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
return (mti->type == eModifierTypeType_OnlyDeform ||
(mti->flags & eModifierTypeFlag_SupportsMapping));
@@ -169,7 +170,7 @@ bool modifier_supportsMapping(ModifierData *md)
bool modifier_isPreview(ModifierData *md)
{
- ModifierTypeInfo *mti = modifierType_getInfo(md->type);
+ const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
/* Constructive modifiers are highly likely to also modify data like vgroups or vcol! */
if (!((mti->flags & eModifierTypeFlag_UsesPreview) || (mti->type == eModifierTypeType_Constructive))) {
@@ -220,7 +221,7 @@ void modifiers_foreachObjectLink(Object *ob, ObjectWalkFunc walk,
ModifierData *md = ob->modifiers.first;
for (; md; md = md->next) {
- ModifierTypeInfo *mti = modifierType_getInfo(md->type);
+ const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
if (mti->foreachObjectLink)
mti->foreachObjectLink(md, ob, walk, userData);
@@ -232,7 +233,7 @@ void modifiers_foreachIDLink(Object *ob, IDWalkFunc walk, void *userData)
ModifierData *md = ob->modifiers.first;
for (; md; md = md->next) {
- ModifierTypeInfo *mti = modifierType_getInfo(md->type);
+ const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
if (mti->foreachIDLink) mti->foreachIDLink(md, ob, walk, userData);
else if (mti->foreachObjectLink) {
@@ -248,7 +249,7 @@ void modifiers_foreachTexLink(Object *ob, TexWalkFunc walk, void *userData)
ModifierData *md = ob->modifiers.first;
for (; md; md = md->next) {
- ModifierTypeInfo *mti = modifierType_getInfo(md->type);
+ const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
if (mti->foreachTexLink)
mti->foreachTexLink(md, ob, walk, userData);
@@ -260,17 +261,17 @@ void modifiers_foreachTexLink(Object *ob, TexWalkFunc walk, void *userData)
*/
void modifier_copyData_generic(const ModifierData *md_src, ModifierData *md_dst)
{
- ModifierTypeInfo *mti = modifierType_getInfo(md_src->type);
+ const ModifierTypeInfo *mti = modifierType_getInfo(md_src->type);
const size_t data_size = sizeof(ModifierData);
- const char *md_src_data = ((char *)md_src) + data_size;
- char *md_dst_data = ((char *)md_dst) + data_size;
+ const char *md_src_data = ((const char *)md_src) + data_size;
+ char *md_dst_data = ((char *)md_dst) + data_size;
BLI_assert(data_size <= (size_t)mti->structSize);
memcpy(md_dst_data, md_src_data, (size_t)mti->structSize - data_size);
}
void modifier_copyData(ModifierData *md, ModifierData *target)
{
- ModifierTypeInfo *mti = modifierType_getInfo(md->type);
+ const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
target->mode = md->mode;
@@ -281,7 +282,7 @@ void modifier_copyData(ModifierData *md, ModifierData *target)
bool modifier_supportsCage(struct Scene *scene, ModifierData *md)
{
- ModifierTypeInfo *mti = modifierType_getInfo(md->type);
+ const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
md->scene = scene;
@@ -292,7 +293,7 @@ bool modifier_supportsCage(struct Scene *scene, ModifierData *md)
bool modifier_couldBeCage(struct Scene *scene, ModifierData *md)
{
- ModifierTypeInfo *mti = modifierType_getInfo(md->type);
+ const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
md->scene = scene;
@@ -304,13 +305,13 @@ bool modifier_couldBeCage(struct Scene *scene, ModifierData *md)
bool modifier_isSameTopology(ModifierData *md)
{
- ModifierTypeInfo *mti = modifierType_getInfo(md->type);
+ const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
return ELEM(mti->type, eModifierTypeType_OnlyDeform, eModifierTypeType_NonGeometrical);
}
bool modifier_isNonGeometrical(ModifierData *md)
{
- ModifierTypeInfo *mti = modifierType_getInfo(md->type);
+ const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
return (mti->type == eModifierTypeType_NonGeometrical);
}
@@ -352,7 +353,7 @@ int modifiers_getCageIndex(struct Scene *scene, Object *ob, int *r_lastPossibleC
/* Find the last modifier acting on the cage. */
for (i = 0; md; i++, md = md->next) {
- ModifierTypeInfo *mti = modifierType_getInfo(md->type);
+ const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
bool supports_mapping;
md->scene = scene;
@@ -410,7 +411,7 @@ bool modifiers_isParticleEnabled(Object *ob)
bool modifier_isEnabled(struct Scene *scene, ModifierData *md, int required_mode)
{
- ModifierTypeInfo *mti = modifierType_getInfo(md->type);
+ const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
md->scene = scene;
@@ -431,7 +432,7 @@ CDMaskLink *modifiers_calcDataMasks(struct Scene *scene, Object *ob, ModifierDat
/* build a list of modifier data requirements in reverse order */
for (; md; md = md->next) {
- ModifierTypeInfo *mti = modifierType_getInfo(md->type);
+ const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
curr = MEM_callocN(sizeof(CDMaskLink), "CDMaskLink");
@@ -625,7 +626,7 @@ bool modifiers_usesArmature(Object *ob, bArmature *arm)
bool modifier_isCorrectableDeformed(ModifierData *md)
{
- ModifierTypeInfo *mti = modifierType_getInfo(md->type);
+ const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
return (mti->deformMatricesEM != NULL);
}
@@ -713,7 +714,7 @@ const char *modifier_path_relbase(Object *ob)
else {
/* last resort, better then using "" which resolves to the current
* working directory */
- return BLI_temp_dir_session();
+ return BKE_tempdir_session();
}
}
@@ -723,7 +724,7 @@ void modifier_path_init(char *path, int path_maxlen, const char *name)
/* elubie: changed this to default to the same dir as the render output
* to prevent saving to C:\ on Windows */
BLI_join_dirfile(path, path_maxlen,
- G.relbase_valid ? "//" : BLI_temp_dir_session(),
+ G.relbase_valid ? "//" : BKE_tempdir_session(),
name);
}
@@ -735,7 +736,7 @@ struct DerivedMesh *modwrap_applyModifier(
struct DerivedMesh *dm,
ModifierApplyFlag flag)
{
- ModifierTypeInfo *mti = modifierType_getInfo(md->type);
+ const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
BLI_assert(CustomData_has_layer(&dm->polyData, CD_NORMAL) == false);
if (mti->dependsOnNormals && mti->dependsOnNormals(md)) {
@@ -750,7 +751,7 @@ struct DerivedMesh *modwrap_applyModifierEM(
DerivedMesh *dm,
ModifierApplyFlag flag)
{
- ModifierTypeInfo *mti = modifierType_getInfo(md->type);
+ const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
BLI_assert(CustomData_has_layer(&dm->polyData, CD_NORMAL) == false);
if (mti->dependsOnNormals && mti->dependsOnNormals(md)) {
@@ -765,7 +766,7 @@ void modwrap_deformVerts(
float (*vertexCos)[3], int numVerts,
ModifierApplyFlag flag)
{
- ModifierTypeInfo *mti = modifierType_getInfo(md->type);
+ const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
BLI_assert(!dm || CustomData_has_layer(&dm->polyData, CD_NORMAL) == false);
if (dm && mti->dependsOnNormals && mti->dependsOnNormals(md)) {
@@ -779,7 +780,7 @@ void modwrap_deformVertsEM(
struct BMEditMesh *em, DerivedMesh *dm,
float (*vertexCos)[3], int numVerts)
{
- ModifierTypeInfo *mti = modifierType_getInfo(md->type);
+ const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
BLI_assert(!dm || CustomData_has_layer(&dm->polyData, CD_NORMAL) == false);
if (dm && mti->dependsOnNormals && mti->dependsOnNormals(md)) {
diff --git a/source/blender/blenkernel/intern/modifiers_bmesh.c b/source/blender/blenkernel/intern/modifiers_bmesh.c
index 645567eea67..18f3db6bd15 100644
--- a/source/blender/blenkernel/intern/modifiers_bmesh.c
+++ b/source/blender/blenkernel/intern/modifiers_bmesh.c
@@ -37,8 +37,9 @@
#include "BKE_editmesh.h"
/* Static function for alloc */
-static BMFace *bm_face_create_from_mpoly(MPoly *mp, MLoop *ml,
- BMesh *bm, BMVert **vtable, BMEdge **etable)
+static BMFace *bm_face_create_from_mpoly(
+ MPoly *mp, MLoop *ml,
+ BMesh *bm, BMVert **vtable, BMEdge **etable)
{
BMVert **verts = BLI_array_alloca(verts, mp->totloop);
BMEdge **edges = BLI_array_alloca(edges, mp->totloop);
diff --git a/source/blender/blenkernel/intern/movieclip.c b/source/blender/blenkernel/intern/movieclip.c
index e28adb7c0e0..7a8c4ad4564 100644
--- a/source/blender/blenkernel/intern/movieclip.c
+++ b/source/blender/blenkernel/intern/movieclip.c
@@ -69,7 +69,6 @@
#include "BKE_image.h" /* openanim */
#include "BKE_tracking.h"
-#include "IMB_colormanagement.h"
#include "IMB_imbuf_types.h"
#include "IMB_imbuf.h"
#include "IMB_moviecache.h"
@@ -78,8 +77,6 @@
# include "intern/openexr/openexr_multi.h"
#endif
-#include "NOD_composite.h"
-
/*********************** movieclip buffer loaders *************************/
static int sequence_guess_offset(const char *full_name, int head_len, unsigned short numlen)
@@ -225,14 +222,14 @@ static ImBuf *movieclip_load_sequence_file(MovieClip *clip, MovieClipUser *user,
colorspace = clip->colorspace_settings.name;
}
- loadflag = IB_rect | IB_multilayer | IB_alphamode_detect;
+ loadflag = IB_rect | IB_multilayer | IB_alphamode_detect | IB_metadata;
/* read ibuf */
ibuf = IMB_loadiffname(name, loadflag, colorspace);
#ifdef WITH_OPENEXR
if (ibuf) {
- if (ibuf->ftype == OPENEXR && ibuf->userdata) {
+ if (ibuf->ftype == IMB_FTYPE_OPENEXR && ibuf->userdata) {
IMB_exr_close(ibuf->userdata);
ibuf->userdata = NULL;
}
@@ -391,7 +388,7 @@ static int user_frame_to_cache_frame(MovieClip *clip, int framenr)
static void moviecache_keydata(void *userkey, int *framenr, int *proxy, int *render_flags)
{
- MovieClipImBufCacheKey *key = (MovieClipImBufCacheKey *)userkey;
+ const MovieClipImBufCacheKey *key = userkey;
*framenr = key->framenr;
*proxy = key->proxy;
@@ -400,7 +397,7 @@ static void moviecache_keydata(void *userkey, int *framenr, int *proxy, int *ren
static unsigned int moviecache_hashhash(const void *keyv)
{
- MovieClipImBufCacheKey *key = (MovieClipImBufCacheKey *)keyv;
+ const MovieClipImBufCacheKey *key = keyv;
int rval = key->framenr;
return rval;
@@ -408,8 +405,8 @@ static unsigned int moviecache_hashhash(const void *keyv)
static bool moviecache_hashcmp(const void *av, const void *bv)
{
- const MovieClipImBufCacheKey *a = (MovieClipImBufCacheKey *)av;
- const MovieClipImBufCacheKey *b = (MovieClipImBufCacheKey *)bv;
+ const MovieClipImBufCacheKey *a = av;
+ const MovieClipImBufCacheKey *b = bv;
return ((a->framenr != b->framenr) ||
(a->proxy != b->proxy) ||
@@ -528,6 +525,15 @@ static bool put_imbuf_cache(MovieClip *clip, MovieClipUser *user, ImBuf *ibuf, i
}
}
+static bool moviecache_check_free_proxy(ImBuf *UNUSED(ibuf),
+ void *userkey,
+ void *UNUSED(userdata))
+{
+ MovieClipImBufCacheKey *key = (MovieClipImBufCacheKey *)userkey;
+
+ return !(key->proxy == IMB_PROXY_NONE && key->render_flag == 0);
+}
+
/*********************** common functions *************************/
/* only image block itself */
@@ -615,7 +621,7 @@ MovieClip *BKE_movieclip_file_add(Main *bmain, const char *name)
BLI_strncpy(strtest, clip->name, sizeof(clip->name));
BLI_path_abs(strtest, G.main->name);
- if (strcmp(strtest, str) == 0) {
+ if (STREQ(strtest, str)) {
BLI_strncpy(clip->name, name, sizeof(clip->name)); /* for stringcode */
clip->id.us++; /* officially should not, it doesn't link here! */
@@ -784,10 +790,10 @@ static ImBuf *postprocess_frame(MovieClip *clip, MovieClipUser *user, ImBuf *ibu
}
if (postprocess_flag) {
- bool disable_red = (postprocess_flag & MOVIECLIP_DISABLE_RED) != 0,
- disable_green = (postprocess_flag & MOVIECLIP_DISABLE_GREEN) != 0,
- disable_blue = (postprocess_flag & MOVIECLIP_DISABLE_BLUE) != 0,
- grayscale = (postprocess_flag & MOVIECLIP_PREVIEW_GRAYSCALE) != 0;
+ bool disable_red = (postprocess_flag & MOVIECLIP_DISABLE_RED) != 0;
+ bool disable_green = (postprocess_flag & MOVIECLIP_DISABLE_GREEN) != 0;
+ bool disable_blue = (postprocess_flag & MOVIECLIP_DISABLE_BLUE) != 0;
+ bool grayscale = (postprocess_flag & MOVIECLIP_PREVIEW_GRAYSCALE) != 0;
if (disable_red || disable_green || disable_blue || grayscale)
BKE_tracking_disable_channels(postproc_ibuf, disable_red, disable_green, disable_blue, 1);
@@ -1123,15 +1129,15 @@ void BKE_movieclip_get_aspect(MovieClip *clip, float *aspx, float *aspy)
}
/* get segments of cached frames. useful for debugging cache policies */
-void BKE_movieclip_get_cache_segments(MovieClip *clip, MovieClipUser *user, int *totseg_r, int **points_r)
+void BKE_movieclip_get_cache_segments(MovieClip *clip, MovieClipUser *user, int *r_totseg, int **r_points)
{
- *totseg_r = 0;
- *points_r = NULL;
+ *r_totseg = 0;
+ *r_points = NULL;
if (clip->cache) {
int proxy = rendersize_to_proxy(user, clip->flag);
- IMB_moviecache_get_cache_segments(clip->cache->moviecache, proxy, user->render_flag, totseg_r, points_r);
+ IMB_moviecache_get_cache_segments(clip->cache->moviecache, proxy, user->render_flag, r_totseg, r_points);
}
}
@@ -1162,7 +1168,7 @@ static void free_buffers(MovieClip *clip)
clip->anim = NULL;
}
- BKE_free_animdata((ID *) clip);
+ BKE_animdata_free((ID *) clip);
}
void BKE_movieclip_clear_cache(MovieClip *clip)
@@ -1170,6 +1176,15 @@ void BKE_movieclip_clear_cache(MovieClip *clip)
free_buffers(clip);
}
+void BKE_movieclip_clear_proxy_cache(MovieClip *clip)
+{
+ if (clip->cache && clip->cache->moviecache) {
+ IMB_moviecache_cleanup(clip->cache->moviecache,
+ moviecache_check_free_proxy,
+ NULL);
+ }
+}
+
void BKE_movieclip_reload(MovieClip *clip)
{
/* clear cache */
@@ -1261,7 +1276,7 @@ void BKE_movieclip_update_scopes(MovieClip *clip, MovieClipUser *user, MovieClip
scopes->frame_width = ibuf->x;
scopes->frame_height = ibuf->y;
- scopes->use_track_mask = track->flag & TRACK_PREVIEW_ALPHA;
+ scopes->use_track_mask = (track->flag & TRACK_PREVIEW_ALPHA) != 0;
}
IMB_freeImBuf(ibuf);
@@ -1307,8 +1322,8 @@ static void movieclip_build_proxy_ibuf(MovieClip *clip, ImBuf *ibuf, int cfra, i
IMB_scaleImBuf(scaleibuf, (short)rectx, (short)recty);
quality = clip->proxy.quality;
- scaleibuf->ftype = JPG | quality;
-
+ scaleibuf->ftype = IMB_FTYPE_JPG;
+ scaleibuf->foptions.quality = quality;
/* unsupported feature only confuses other s/w */
if (scaleibuf->planes == 32)
scaleibuf->planes = 24;
diff --git a/source/blender/blenkernel/intern/multires.c b/source/blender/blenkernel/intern/multires.c
index 246ef8a33f5..fbba6249b73 100644
--- a/source/blender/blenkernel/intern/multires.c
+++ b/source/blender/blenkernel/intern/multires.c
@@ -126,7 +126,7 @@ static BLI_bitmap *multires_mdisps_upsample_hidden(BLI_bitmap *lo_hidden,
if (lo_level == hi_level)
return MEM_dupallocN(lo_hidden);
- subd = BLI_BITMAP_NEW(hi_gridsize * hi_gridsize, "MDisps.hidden upsample");
+ subd = BLI_BITMAP_NEW(SQUARE(hi_gridsize), "MDisps.hidden upsample");
factor = BKE_ccg_factor(lo_level, hi_level);
offset = 1 << (hi_level - lo_level - 1);
@@ -182,9 +182,7 @@ static BLI_bitmap *multires_mdisps_downsample_hidden(BLI_bitmap *old_hidden,
BLI_assert(new_level <= old_level);
factor = BKE_ccg_factor(new_level, old_level);
- new_hidden = BLI_BITMAP_NEW(new_gridsize * new_gridsize,
- "downsample hidden");
-
+ new_hidden = BLI_BITMAP_NEW(SQUARE(new_gridsize), "downsample hidden");
for (y = 0; y < new_gridsize; y++) {
@@ -250,15 +248,15 @@ static MDisps *multires_mdisps_initialize_hidden(Mesh *me, int level)
MDisps *mdisps = CustomData_add_layer(&me->ldata, CD_MDISPS,
CD_CALLOC, NULL, me->totloop);
int gridsize = BKE_ccg_gridsize(level);
- int gridarea = gridsize * gridsize;
- int i, j, k;
+ int gridarea = SQUARE(gridsize);
+ int i, j;
for (i = 0; i < me->totpoly; i++) {
- int hide = 0;
+ bool hide = false;
for (j = 0; j < me->mpoly[i].totloop; j++) {
if (me->mvert[me->mloop[me->mpoly[i].loopstart + j].v].flag & ME_HIDE) {
- hide = 1;
+ hide = true;
break;
}
}
@@ -272,9 +270,7 @@ static MDisps *multires_mdisps_initialize_hidden(Mesh *me, int level)
BLI_assert(!md->hidden);
md->hidden = BLI_BITMAP_NEW(gridarea, "MDisps.hidden initialize");
-
- for (k = 0; k < gridarea; k++)
- BLI_BITMAP_ENABLE(md->hidden, k);
+ BLI_BITMAP_SET_ALL(md->hidden, true, gridarea);
}
}
@@ -284,7 +280,7 @@ static MDisps *multires_mdisps_initialize_hidden(Mesh *me, int level)
DerivedMesh *get_multires_dm(Scene *scene, MultiresModifierData *mmd, Object *ob)
{
ModifierData *md = (ModifierData *)mmd;
- ModifierTypeInfo *mti = modifierType_getInfo(md->type);
+ const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
DerivedMesh *tdm = mesh_get_derived_deform(scene, ob, CD_MASK_BAREMESH);
DerivedMesh *dm;
@@ -344,13 +340,13 @@ static int multires_get_level(Object *ob, MultiresModifierData *mmd,
bool render, bool ignore_simplify)
{
if (render)
- return (mmd->modifier.scene) ? get_render_subsurf_level(&mmd->modifier.scene->r, mmd->renderlvl) : mmd->renderlvl;
+ return (mmd->modifier.scene) ? get_render_subsurf_level(&mmd->modifier.scene->r, mmd->renderlvl, true) : mmd->renderlvl;
else if (ob->mode == OB_MODE_SCULPT)
return mmd->sculptlvl;
else if (ignore_simplify)
return mmd->lvl;
else
- return (mmd->modifier.scene) ? get_render_subsurf_level(&mmd->modifier.scene->r, mmd->lvl) : mmd->lvl;
+ return (mmd->modifier.scene) ? get_render_subsurf_level(&mmd->modifier.scene->r, mmd->lvl, false) : mmd->lvl;
}
void multires_set_tot_level(Object *ob, MultiresModifierData *mmd, int lvl)
@@ -433,7 +429,7 @@ int multiresModifier_reshape(Scene *scene, MultiresModifierData *mmd, Object *ds
int multiresModifier_reshapeFromDeformMod(Scene *scene, MultiresModifierData *mmd,
Object *ob, ModifierData *md)
{
- ModifierTypeInfo *mti = modifierType_getInfo(md->type);
+ const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
DerivedMesh *dm, *ndm;
int numVerts, result;
float (*deformedVerts)[3];
@@ -601,7 +597,7 @@ static void multires_grid_paint_mask_downsample(GridPaintMask *gpm, int level)
{
if (level < gpm->level) {
int gridsize = BKE_ccg_gridsize(level);
- float *data = MEM_callocN(sizeof(float) * gridsize * gridsize,
+ float *data = MEM_callocN(sizeof(float) * SQUARE(gridsize),
"multires_grid_paint_mask_downsample");
int x, y;
@@ -886,18 +882,20 @@ static void multires_subdivide(MultiresModifierData *mmd, Object *ob, int totlvl
{
Mesh *me = ob->data;
MDisps *mdisps;
- int lvl = mmd->totlvl;
+ const int lvl = mmd->totlvl;
if ((totlvl > multires_max_levels) || (me->totpoly == 0))
return;
+ BLI_assert(totlvl > lvl);
+
multires_force_update(ob);
mdisps = CustomData_get_layer(&me->ldata, CD_MDISPS);
if (!mdisps)
mdisps = multires_mdisps_initialize_hidden(me, totlvl);
- if (mdisps->disps && !updateblock && totlvl > 1) {
+ if (mdisps->disps && !updateblock && lvl != 0) {
/* upsample */
DerivedMesh *lowdm, *cddm, *highdm;
CCGElem **highGridData, **lowGridData, **subGridData;
@@ -914,6 +912,7 @@ static void multires_subdivide(MultiresModifierData *mmd, Object *ob, int totlvl
/* create multires DM from original mesh at low level */
lowdm = multires_dm_create_local(ob, cddm, lvl, lvl, simple, has_mask);
+ BLI_assert(lowdm != cddm);
cddm->release(cddm);
/* copy subsurf grids and replace them with low displaced grids */
@@ -1465,10 +1464,10 @@ DerivedMesh *multires_make_derived_from_derived(DerivedMesh *dm,
gridData = result->getGridData(result);
result->getGridKey(result, &key);
- subGridData = MEM_callocN(sizeof(CCGElem *) * numGrids, "subGridData*");
+ subGridData = MEM_mallocN(sizeof(CCGElem *) * numGrids, "subGridData*");
for (i = 0; i < numGrids; i++) {
- subGridData[i] = MEM_callocN(key.elem_size * gridSize * gridSize, "subGridData");
+ subGridData[i] = MEM_mallocN(key.elem_size * gridSize * gridSize, "subGridData");
memcpy(subGridData[i], gridData[i], key.elem_size * gridSize * gridSize);
}
@@ -1604,7 +1603,7 @@ void multires_load_old_250(Mesh *me)
int nvert = mf->v4 ? 4 : 3;
int totdisp = mdisps[i].totdisp / nvert;
- for (j = 0; j < mf->v4 ? 4 : 3; j++, k++) {
+ for (j = 0; j < nvert; j++, k++) {
mdisps2[k].disps = MEM_callocN(sizeof(float) * 3 * totdisp, "multires disp in conversion");
mdisps2[k].totdisp = totdisp;
mdisps2[k].level = mdisps[i].level;
@@ -1645,7 +1644,8 @@ void multires_free(Multires *mr)
lvl = lvl->next;
}
- MEM_freeN(mr->verts);
+ /* mr->verts may be NULL when loading old files, see direct_link_mesh() in readfile.c, and T43560. */
+ MEM_SAFE_FREE(mr->verts);
BLI_freelistN(&mr->levels);
@@ -2140,27 +2140,38 @@ void multires_load_old(Object *ob, Mesh *me)
me->mr = NULL;
}
-/* If 'ob' and 'to_ob' both have multires modifiers, synchronize them
- * such that 'ob' has the same total number of levels as 'to_ob'. */
-static void multires_sync_levels(Scene *scene, Object *ob, Object *to_ob)
+/* If 'ob_src' and 'ob_dst' both have multires modifiers, synchronize them
+ * such that 'ob_dst' has the same total number of levels as 'ob_src'. */
+void multiresModifier_sync_levels_ex(Object *ob_dst, MultiresModifierData *mmd_src, MultiresModifierData *mmd_dst)
{
- MultiresModifierData *mmd = get_multires_modifier(scene, ob, 1);
- MultiresModifierData *to_mmd = get_multires_modifier(scene, to_ob, 1);
+ if (mmd_src->totlvl == mmd_dst->totlvl) {
+ return;
+ }
- if (!mmd) {
+ if (mmd_src->totlvl > mmd_dst->totlvl) {
+ multires_subdivide(mmd_dst, ob_dst, mmd_src->totlvl, false, mmd_dst->simple);
+ }
+ else {
+ multires_del_higher(mmd_dst, ob_dst, mmd_src->totlvl);
+ }
+}
+
+static void multires_sync_levels(Scene *scene, Object *ob_src, Object *ob_dst)
+{
+ MultiresModifierData *mmd_src = get_multires_modifier(scene, ob_src, true);
+ MultiresModifierData *mmd_dst = get_multires_modifier(scene, ob_dst, true);
+
+ if (!mmd_src) {
/* object could have MDISP even when there is no multires modifier
* this could lead to troubles due to i've got no idea how mdisp could be
* upsampled correct without modifier data.
* just remove mdisps if no multires present (nazgul) */
- multires_customdata_delete(ob->data);
+ multires_customdata_delete(ob_src->data);
}
- if (mmd && to_mmd) {
- if (mmd->totlvl > to_mmd->totlvl)
- multires_del_higher(mmd, ob, to_mmd->totlvl);
- else
- multires_subdivide(mmd, ob, to_mmd->totlvl, 0, mmd->simple);
+ if (mmd_src && mmd_dst) {
+ multiresModifier_sync_levels_ex(ob_dst, mmd_src, mmd_dst);
}
}
@@ -2279,7 +2290,7 @@ void multiresModifier_scale_disp(Scene *scene, Object *ob)
void multiresModifier_prepare_join(Scene *scene, Object *ob, Object *to_ob)
{
float smat[3][3], tmat[3][3], mat[3][3];
- multires_sync_levels(scene, ob, to_ob);
+ multires_sync_levels(scene, to_ob, ob);
/* construct scale matrix for displacement */
BKE_object_scale_to_mat3(to_ob, tmat);
@@ -2327,12 +2338,12 @@ void multires_topology_changed(Mesh *me)
/***************** Multires interpolation stuff *****************/
/* Find per-corner coordinate with given per-face UV coord */
-int mdisp_rot_face_to_crn(const int corners, const int face_side, const float u, const float v, float *x, float *y)
+int mdisp_rot_face_to_crn(struct MVert *UNUSED(mvert), struct MPoly *mpoly, struct MLoop *UNUSED(mloop), const struct MLoopTri *UNUSED(lt), const int face_side, const float u, const float v, float *x, float *y)
{
const float offset = face_side * 0.5f - 0.5f;
int S = 0;
- if (corners == 4) {
+ if (mpoly->totloop == 4) {
if (u <= offset && v <= offset) S = 0;
else if (u > offset && v <= offset) S = 1;
else if (u > offset && v > offset) S = 2;
@@ -2355,7 +2366,7 @@ int mdisp_rot_face_to_crn(const int corners, const int face_side, const float u,
*y = v - offset;
}
}
- else {
+ else if (mpoly->totloop == 3) {
int grid_size = offset;
float w = (face_side - 1) - u - v;
float W1, W2;
@@ -2370,6 +2381,30 @@ int mdisp_rot_face_to_crn(const int corners, const int face_side, const float u,
*x = (1 - (2 * W1) / (1 - W2)) * grid_size;
*y = (1 - (2 * W2) / (1 - W1)) * grid_size;
}
+ else {
+ /* the complicated ngon case: find the actual coordinate from
+ * the barycentric coordinates and finally find the closest vertex
+ * should work reliably for convex cases only but better than nothing */
+
+#if 0
+ int minS, i;
+ float mindist = FLT_MAX;
+
+ for (i = 0; i < mpoly->totloop; i++) {
+ float len = len_v3v3(NULL, mvert[mloop[mpoly->loopstart + i].v].co);
+ if (len < mindist) {
+ mindist = len;
+ minS = i;
+ }
+ }
+ S = minS;
+#endif
+ /* temp not implemented yet and also not working properly in current master.
+ * (was worked around by subdividing once) */
+ S = 0;
+ *x = 0;
+ *y = 0;
+ }
return S;
}
diff --git a/source/blender/blenkernel/intern/navmesh_conversion.c b/source/blender/blenkernel/intern/navmesh_conversion.c
index 6c3f4d545d3..35bcca52f63 100644
--- a/source/blender/blenkernel/intern/navmesh_conversion.c
+++ b/source/blender/blenkernel/intern/navmesh_conversion.c
@@ -123,6 +123,11 @@ int buildRawVertIndicesData(DerivedMesh *dm, int *nverts_r, float **verts_r,
printf("Converting navmesh: Error! Too many vertices. Max number of vertices %d\n", 0xffff);
return 0;
}
+ if (nverts == 0) {
+ printf("Converting navmesh: Error! There are no vertices!\n");
+ return 0;
+ }
+
verts = MEM_mallocN(sizeof(float[3]) * nverts, "buildRawVertIndicesData verts");
dm->getVertCos(dm, (float(*)[3])verts);
@@ -132,7 +137,13 @@ int buildRawVertIndicesData(DerivedMesh *dm, int *nverts_r, float **verts_r,
}
/* calculate number of tris */
+ dm->recalcTessellation(dm);
nfaces = dm->getNumTessFaces(dm);
+ if (nfaces == 0) {
+ printf("Converting navmesh: Error! There are %i vertices, but no faces!\n", nverts);
+ return 0;
+ }
+
faces = dm->getTessFaceArray(dm);
ntris = nfaces;
for (fi = 0; fi < nfaces; fi++) {
@@ -387,7 +398,12 @@ int buildNavMeshData(const int nverts, const float *verts,
/* build adjacency info for detailed mesh triangles */
- recast_buildMeshAdjacency(dtris, ndtris, nverts, 3);
+ if (!recast_buildMeshAdjacency(dtris, ndtris, nverts, 3)) {
+ printf("Converting navmesh: Error! Unable to build mesh adjacency information\n");
+ MEM_freeN(trisMapping);
+ MEM_freeN(dtrisToPolysMap);
+ return 0;
+ }
/* create detailed mesh description for each navigation polygon */
npolys = dtrisToPolysMap[ndtris - 1];
@@ -415,7 +431,10 @@ int buildNavMeshData(const int nverts, const float *verts,
polys = MEM_callocN(sizeof(unsigned short) * npolys * vertsPerPoly * 2, "buildNavMeshData polys");
memset(polys, 0xff, sizeof(unsigned short) * vertsPerPoly * 2 * npolys);
- buildPolygonsByDetailedMeshes(vertsPerPoly, npolys, polys, dmeshes, verts, dtris, dtrisToPolysMap);
+ if (!buildPolygonsByDetailedMeshes(vertsPerPoly, npolys, polys, dmeshes, verts, dtris, dtrisToPolysMap)) {
+ printf("Converting navmesh: Error! Unable to build polygons from detailed mesh\n");
+ goto fail;
+ }
*ndtris_r = ndtris;
*npolys_r = npolys;
@@ -449,7 +468,7 @@ int buildNavMeshDataByDerivedMesh(DerivedMesh *dm, int *vertsPerPoly,
res = buildRawVertIndicesData(dm, nverts, verts, &ntris, &tris, trisToFacesMap, &recastData);
if (!res) {
- printf("Converting navmesh: Error! Can't get vertices and indices from mesh\n");
+ printf("Converting navmesh: Error! Can't get raw vertices and indices from mesh\n");
goto exit;
}
@@ -457,7 +476,7 @@ int buildNavMeshDataByDerivedMesh(DerivedMesh *dm, int *vertsPerPoly,
ndtris, dtris, npolys, dmeshes, polys, vertsPerPoly,
dtrisToPolysMap, dtrisToTrisMap);
if (!res) {
- printf("Converting navmesh: Error! Can't get vertices and indices from mesh\n");
+ printf("Converting navmesh: Error! Can't build navmesh data from mesh\n");
goto exit;
}
diff --git a/source/blender/blenkernel/intern/nla.c b/source/blender/blenkernel/intern/nla.c
index 19e45142960..a04eb9bd611 100644
--- a/source/blender/blenkernel/intern/nla.c
+++ b/source/blender/blenkernel/intern/nla.c
@@ -45,7 +45,7 @@
#include "BLI_string.h"
#include "BLI_ghash.h"
-#include "BLF_translation.h"
+#include "BLT_translation.h"
#include "DNA_anim_types.h"
#include "DNA_scene_types.h"
@@ -59,7 +59,7 @@
#include "BKE_library.h"
#ifdef WITH_AUDASPACE
-# include "AUD_C-API.h"
+# include AUD_SPECIAL_H
#endif
#include "RNA_access.h"
@@ -268,7 +268,7 @@ NlaTrack *add_nlatrack(AnimData *adt, NlaTrack *prev)
/* set settings requiring the track to not be part of the stack yet */
nlt->flag = NLATRACK_SELECTED;
- nlt->index = BLI_countlist(&adt->nla_tracks);
+ nlt->index = BLI_listbase_count(&adt->nla_tracks);
/* add track to stack, and make it the active one */
if (prev)
@@ -299,13 +299,12 @@ NlaStrip *add_nlastrip(bAction *act)
/* generic settings
* - selected flag to highlight this to the user
- * - auto-blends to ensure that blend in/out values are automatically
- * determined by overlaps of strips
+ * - (XXX) disabled Auto-Blends, as this was often causing some unwanted effects
* - (XXX) synchronization of strip-length in accordance with changes to action-length
* is not done though, since this should only really happens in editmode for strips now
* though this decision is still subject to further review...
*/
- strip->flag = NLASTRIP_FLAG_SELECT | NLASTRIP_FLAG_AUTO_BLENDS;
+ strip->flag = NLASTRIP_FLAG_SELECT;
/* assign the action reference */
strip->act = act;
@@ -536,9 +535,14 @@ float BKE_nla_tweakedit_remap(AnimData *adt, float cframe, short mode)
/* if the active-strip info has been stored already, access this, otherwise look this up
* and store for (very probable) future usage
*/
+ if (adt->act_track == NULL) {
+ if (adt->actstrip)
+ adt->act_track = BKE_nlatrack_find_tweaked(adt);
+ else
+ adt->act_track = BKE_nlatrack_find_active(&adt->nla_tracks);
+ }
if (adt->actstrip == NULL) {
- NlaTrack *nlt = BKE_nlatrack_find_active(&adt->nla_tracks);
- adt->actstrip = BKE_nlastrip_find_active(nlt);
+ adt->actstrip = BKE_nlastrip_find_active(adt->act_track);
}
strip = adt->actstrip;
@@ -567,7 +571,7 @@ bool BKE_nlastrips_has_space(ListBase *strips, float start, float end)
/* sanity checks */
if ((strips == NULL) || IS_EQF(start, end))
- return 0;
+ return false;
if (start > end) {
puts("BKE_nlastrips_has_space() error... start and end arguments swapped");
SWAP(float, start, end);
@@ -579,17 +583,17 @@ bool BKE_nlastrips_has_space(ListBase *strips, float start, float end)
* we've gone past the window we need to check for, so things are fine
*/
if (strip->start >= end)
- return 1;
+ return true;
/* if the end of the strip is greater than either of the boundaries, the range
* must fall within the extents of the strip
*/
if ((strip->end > start) || (strip->end > end))
- return 0;
+ return false;
}
/* if we are still here, we haven't encountered any overlapping strips */
- return 1;
+ return true;
}
/* Rearrange the strips in the track so that they are always in order
@@ -646,11 +650,11 @@ bool BKE_nlastrips_add_strip(ListBase *strips, NlaStrip *strip)
/* sanity checks */
if (ELEM(NULL, strips, strip))
- return 0;
+ return false;
/* check if any space to add */
if (BKE_nlastrips_has_space(strips, strip->start, strip->end) == 0)
- return 0;
+ return false;
/* find the right place to add the strip to the nominated track */
for (ns = strips->first; ns; ns = ns->next) {
@@ -667,7 +671,7 @@ bool BKE_nlastrips_add_strip(ListBase *strips, NlaStrip *strip)
}
/* added... */
- return 1;
+ return true;
}
@@ -785,11 +789,11 @@ bool BKE_nlameta_add_strip(NlaStrip *mstrip, NlaStrip *strip)
{
/* sanity checks */
if (ELEM(NULL, mstrip, strip))
- return 0;
+ return false;
/* firstly, check if the meta-strip has space for this */
if (BKE_nlastrips_has_space(&mstrip->strips, strip->start, strip->end) == 0)
- return 0;
+ return false;
/* check if this would need to be added to the ends of the meta,
* and subsequently, if the neighboring strips allow us enough room
@@ -803,10 +807,10 @@ bool BKE_nlameta_add_strip(NlaStrip *mstrip, NlaStrip *strip)
BLI_addhead(&mstrip->strips, strip);
mstrip->start = strip->start;
- return 1;
+ return true;
}
else /* failed... no room before */
- return 0;
+ return false;
}
else if (strip->end > mstrip->end) {
/* check if strip to the right (if it exists) starts before the
@@ -817,10 +821,10 @@ bool BKE_nlameta_add_strip(NlaStrip *mstrip, NlaStrip *strip)
BLI_addtail(&mstrip->strips, strip);
mstrip->end = strip->end;
- return 1;
+ return true;
}
else /* failed... no room after */
- return 0;
+ return false;
}
else {
/* just try to add to the meta-strip (no dimension changes needed) */
@@ -927,6 +931,39 @@ NlaTrack *BKE_nlatrack_find_active(ListBase *tracks)
return NULL;
}
+/* Get the NLA Track that the active action/action strip comes from,
+ * since this info is not stored in AnimData. It also isn't as simple
+ * as just using the active track, since multiple tracks may have been
+ * entered at the same time.
+ */
+NlaTrack *BKE_nlatrack_find_tweaked(AnimData *adt)
+{
+ NlaTrack *nlt;
+
+ /* sanity check */
+ if (adt == NULL)
+ return NULL;
+
+ /* Since the track itself gets disabled, we want the first disabled... */
+ for (nlt = adt->nla_tracks.first; nlt; nlt = nlt->next) {
+ if (nlt->flag & (NLATRACK_ACTIVE | NLATRACK_DISABLED)) {
+ /* For good measure, make sure that strip actually exists there */
+ if (BLI_findindex(&nlt->strips, adt->actstrip) != -1) {
+ return nlt;
+ }
+ else if (G.debug & G_DEBUG) {
+ printf("%s: Active strip (%p, %s) not in NLA track found (%p, %s)\n",
+ __func__,
+ adt->actstrip, (adt->actstrip) ? adt->actstrip->name : "<None>",
+ nlt, nlt->name);
+ }
+ }
+ }
+
+ /* Not found! */
+ return NULL;
+}
+
/* Toggle the 'solo' setting for the given NLA-track, making sure that it is the only one
* that has this status in its AnimData block.
*/
@@ -988,7 +1025,7 @@ bool BKE_nlatrack_has_space(NlaTrack *nlt, float start, float end)
* - bounds cannot be equal (0-length is nasty)
*/
if ((nlt == NULL) || (nlt->flag & NLATRACK_PROTECTED) || IS_EQF(start, end))
- return 0;
+ return false;
if (start > end) {
puts("BKE_nlatrack_has_space() error... start and end arguments swapped");
@@ -1019,8 +1056,12 @@ bool BKE_nlatrack_add_strip(NlaTrack *nlt, NlaStrip *strip)
{
/* sanity checks */
if (ELEM(NULL, nlt, strip))
- return 0;
+ return false;
+ /* do not allow adding strips if this track is locked */
+ if (nlt->flag & NLATRACK_PROTECTED)
+ return false;
+
/* try to add the strip to the track using a more generic function */
return BKE_nlastrips_add_strip(&nlt->strips, strip);
}
@@ -1036,11 +1077,11 @@ bool BKE_nlatrack_get_bounds(NlaTrack *nlt, float bounds[2])
if (bounds)
bounds[0] = bounds[1] = 0.0f;
else
- return 0;
+ return false;
/* sanity checks */
if (ELEM(NULL, nlt, nlt->strips.first))
- return 0;
+ return false;
/* lower bound is first strip's start frame */
strip = nlt->strips.first;
@@ -1051,7 +1092,7 @@ bool BKE_nlatrack_get_bounds(NlaTrack *nlt, float bounds[2])
bounds[1] = strip->end;
/* done */
- return 1;
+ return true;
}
/* NLA Strips -------------------------------------- */
@@ -1105,7 +1146,7 @@ bool BKE_nlastrip_within_bounds(NlaStrip *strip, float min, float max)
/* sanity checks */
if ((strip == NULL) || IS_EQF(stripLen, 0.0f) || IS_EQF(boundsLen, 0.0f))
- return 0;
+ return false;
/* only ok if at least part of the strip is within the bounding window
* - first 2 cases cover when the strip length is less than the bounding area
@@ -1115,17 +1156,17 @@ bool BKE_nlastrip_within_bounds(NlaStrip *strip, float min, float max)
!(IN_RANGE(strip->start, min, max) ||
IN_RANGE(strip->end, min, max)))
{
- return 0;
+ return false;
}
if ((stripLen > boundsLen) &&
!(IN_RANGE(min, strip->start, strip->end) ||
IN_RANGE(max, strip->start, strip->end)) )
{
- return 0;
+ return false;
}
/* should be ok! */
- return 1;
+ return true;
}
@@ -1209,11 +1250,11 @@ static bool nlastrip_is_first(AnimData *adt, NlaStrip *strip)
/* sanity checks */
if (ELEM(NULL, adt, strip))
- return 0;
+ return false;
/* check if strip has any strips before it */
if (strip->prev)
- return 0;
+ return false;
/* check other tracks to see if they have a strip that's earlier */
/* TODO: or should we check that the strip's track is also the first? */
@@ -1222,12 +1263,12 @@ static bool nlastrip_is_first(AnimData *adt, NlaStrip *strip)
ns = nlt->strips.first;
if (ns) {
if (ns->start < strip->start)
- return 0;
+ return false;
}
}
/* should be first now */
- return 1;
+ return true;
}
/* Animated Strips ------------------------------------------- */
@@ -1239,16 +1280,16 @@ bool BKE_nlatrack_has_animated_strips(NlaTrack *nlt)
/* sanity checks */
if (ELEM(NULL, nlt, nlt->strips.first))
- return 0;
+ return false;
/* check each strip for F-Curves only (don't care about whether the flags are set) */
for (strip = nlt->strips.first; strip; strip = strip->next) {
if (strip->fcurves.first)
- return 1;
+ return true;
}
/* none found */
- return 0;
+ return false;
}
/* Check if given NLA-Tracks have any strips with own F-Curves */
@@ -1258,16 +1299,16 @@ bool BKE_nlatracks_have_animated_strips(ListBase *tracks)
/* sanity checks */
if (ELEM(NULL, tracks, tracks->first))
- return 0;
+ return false;
/* check each track, stopping on the first hit */
for (nlt = tracks->first; nlt; nlt = nlt->next) {
if (BKE_nlatrack_has_animated_strips(nlt))
- return 1;
+ return true;
}
/* none found */
- return 0;
+ return false;
}
/* Validate the NLA-Strips 'control' F-Curves based on the flags set*/
@@ -1326,7 +1367,7 @@ void BKE_nlastrip_validate_fcurves(NlaStrip *strip)
static bool nla_editbone_name_check(void *arg, const char *name)
{
- return BLI_ghash_haskey((GHash *)arg, (void *)name);
+ return BLI_ghash_haskey((GHash *)arg, (const void *)name);
}
/* Find (and set) a unique name for a strip from the whole AnimData block
@@ -1524,6 +1565,100 @@ void BKE_nla_validate_state(AnimData *adt)
}
}
+/* Action Stashing -------------------------------------- */
+
+/* name of stashed tracks - the translation stuff is included here to save extra work */
+#define STASH_TRACK_NAME DATA_("[Action Stash]")
+
+/* Check if an action is "stashed" in the NLA already
+ *
+ * The criteria for this are:
+ * 1) The action in question lives in a "stash" track
+ * 2) We only check first-level strips. That is, we will not check inside meta strips.
+ */
+bool BKE_nla_action_is_stashed(AnimData *adt, bAction *act)
+{
+ NlaTrack *nlt;
+ NlaStrip *strip;
+
+ for (nlt = adt->nla_tracks.first; nlt; nlt = nlt->next) {
+ if (strstr(nlt->name, STASH_TRACK_NAME)) {
+ for (strip = nlt->strips.first; strip; strip = strip->next) {
+ if (strip->act == act)
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+/* "Stash" an action (i.e. store it as a track/layer in the NLA, but non-contributing)
+ * to retain it in the file for future uses
+ */
+bool BKE_nla_action_stash(AnimData *adt)
+{
+ NlaTrack *prev_track = NULL;
+ NlaTrack *nlt;
+ NlaStrip *strip;
+
+ /* sanity check */
+ if (ELEM(NULL, adt, adt->action)) {
+ printf("%s: Invalid argument - %p %p\n", __func__, adt, adt->action);
+ return false;
+ }
+
+ /* do not add if it is already stashed */
+ if (BKE_nla_action_is_stashed(adt, adt->action))
+ return false;
+
+ /* create a new track, and add this immediately above the previous stashing track */
+ for (prev_track = adt->nla_tracks.last; prev_track; prev_track = prev_track->prev) {
+ if (strstr(prev_track->name, STASH_TRACK_NAME)) {
+ break;
+ }
+ }
+
+ nlt = add_nlatrack(adt, prev_track);
+ BLI_assert(nlt != NULL);
+
+ /* we need to ensure that if there wasn't any previous instance, it must go to tbe bottom of the stack */
+ if (prev_track == NULL) {
+ BLI_remlink(&adt->nla_tracks, nlt);
+ BLI_addhead(&adt->nla_tracks, nlt);
+ }
+
+ BLI_strncpy(nlt->name, STASH_TRACK_NAME, sizeof(nlt->name));
+ BLI_uniquename(&adt->nla_tracks, nlt, STASH_TRACK_NAME, '.', offsetof(NlaTrack, name), sizeof(nlt->name));
+
+ /* add the action as a strip in this new track
+ * NOTE: a new user is created here
+ */
+ strip = add_nlastrip(adt->action);
+ BLI_assert(strip != NULL);
+
+ BKE_nlatrack_add_strip(nlt, strip);
+ BKE_nlastrip_validate_name(adt, strip);
+
+ /* mark the stash track and strip so that they doesn't disturb the stack animation,
+ * and are unlikely to draw attention to itself (or be accidentally bumped around)
+ *
+ * NOTE: this must be done *after* adding the strip to the track, or else
+ * the strip locking will prevent the strip from getting added
+ */
+ nlt->flag = (NLATRACK_MUTED | NLATRACK_PROTECTED);
+ strip->flag &= ~(NLASTRIP_FLAG_SELECT | NLASTRIP_FLAG_ACTIVE);
+
+ /* also mark the strip for auto syncing the length, so that the strips accurately
+ * reflect the length of the action
+ * XXX: we could do with some extra flags here to prevent repeats/scaling options from working!
+ */
+ strip->flag |= NLASTRIP_FLAG_SYNC_LENGTH;
+
+ /* succeeded */
+ return true;
+}
+
/* Core Tools ------------------------------------------- */
/* For the given AnimData block, add the active action to the NLA
@@ -1576,7 +1711,6 @@ void BKE_nla_action_pushdown(AnimData *adt)
}
}
-
/* Find the active strip + track combo, and set them up as the tweaking track,
* and return if successful or not.
*/
@@ -1587,13 +1721,13 @@ bool BKE_nla_tweakmode_enter(AnimData *adt)
/* verify that data is valid */
if (ELEM(NULL, adt, adt->nla_tracks.first))
- return 0;
+ return false;
/* if block is already in tweakmode, just leave, but we should report
* that this block is in tweakmode (as our returncode)
*/
if (adt->flag & ADT_NLA_EDIT_ON)
- return 1;
+ return true;
/* go over the tracks, finding the active one, and its active strip
* - if we cannot find both, then there's nothing to do
@@ -1642,7 +1776,7 @@ bool BKE_nla_tweakmode_enter(AnimData *adt)
printf("NLA tweakmode enter - neither active requirement found\n");
printf("\tactiveTrack = %p, activeStrip = %p\n", (void *)activeTrack, (void *)activeStrip);
}
- return 0;
+ return false;
}
/* go over all the tracks up to the active one, tagging each strip that uses the same
@@ -1672,12 +1806,13 @@ bool BKE_nla_tweakmode_enter(AnimData *adt)
*/
adt->tmpact = adt->action;
adt->action = activeStrip->act;
+ adt->act_track = activeTrack;
adt->actstrip = activeStrip;
id_us_plus(&activeStrip->act->id);
adt->flag |= ADT_NLA_EDIT_ON;
/* done! */
- return 1;
+ return true;
}
/* Exit tweakmode for this AnimData block */
@@ -1731,6 +1866,7 @@ void BKE_nla_tweakmode_exit(AnimData *adt)
if (adt->action) adt->action->id.us--;
adt->action = adt->tmpact;
adt->tmpact = NULL;
+ adt->act_track = NULL;
adt->actstrip = NULL;
adt->flag &= ~ADT_NLA_EDIT_ON;
}
diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c
index 3a7bfb03e07..c656931d18b 100644
--- a/source/blender/blenkernel/intern/node.c
+++ b/source/blender/blenkernel/intern/node.c
@@ -52,7 +52,7 @@
#include "BLI_path_util.h"
#include "BLI_utildefines.h"
-#include "BLF_translation.h"
+#include "BLT_translation.h"
#include "BKE_animsys.h"
#include "BKE_global.h"
@@ -62,6 +62,7 @@
#include "BKE_node.h"
#include "BLI_ghash.h"
+#include "BLI_threads.h"
#include "RNA_access.h"
#include "RNA_define.h"
@@ -287,6 +288,7 @@ void ntreeSetTypes(const struct bContext *C, bNodeTree *ntree)
static GHash *nodetreetypes_hash = NULL;
static GHash *nodetypes_hash = NULL;
static GHash *nodesockettypes_hash = NULL;
+static SpinLock spin;
bNodeTreeType *ntreeTypeFind(const char *idname)
{
@@ -303,7 +305,7 @@ bNodeTreeType *ntreeTypeFind(const char *idname)
void ntreeTypeAdd(bNodeTreeType *nt)
{
- BLI_ghash_insert(nodetreetypes_hash, (void *)nt->idname, nt);
+ BLI_ghash_insert(nodetreetypes_hash, nt->idname, nt);
/* XXX pass Main to register function? */
update_typeinfo(G.main, NULL, nt, NULL, NULL, false);
}
@@ -317,7 +319,7 @@ static void ntree_free_type(void *treetype_v)
MEM_freeN(treetype);
}
-void ntreeTypeFreeLink(bNodeTreeType *nt)
+void ntreeTypeFreeLink(const bNodeTreeType *nt)
{
BLI_ghash_remove(nodetreetypes_hash, nt->idname, NULL, ntree_free_type);
}
@@ -378,7 +380,7 @@ void nodeRegisterType(bNodeType *nt)
BLI_assert(nt->idname[0] != '\0');
BLI_assert(nt->poll != NULL);
- BLI_ghash_insert(nodetypes_hash, (void *)nt->idname, nt);
+ BLI_ghash_insert(nodetypes_hash, nt->idname, nt);
/* XXX pass Main to register function? */
update_typeinfo(G.main, NULL, NULL, nt, NULL, false);
}
@@ -773,6 +775,82 @@ int nodeFindNode(bNodeTree *ntree, bNodeSocket *sock, bNode **nodep, int *sockin
return 0;
}
+/**
+ * \note Recursive
+ */
+bNode *nodeFindRootParent(bNode *node)
+{
+ if (node->parent) {
+ return nodeFindRootParent(node->parent);
+ }
+ else {
+ return node->type == NODE_FRAME ? node : NULL;
+ }
+}
+
+/**
+ * \returns true if \a child has \a parent as a parent/grandparent/...
+ * \note Recursive
+ */
+bool nodeIsChildOf(const bNode *parent, const bNode *child)
+{
+ if (parent == child) {
+ return true;
+ }
+ else if (child->parent) {
+ return nodeIsChildOf(parent, child->parent);
+ }
+ return false;
+}
+
+/**
+ * Iterate over a chain of nodes, starting with \a node_start, executing
+ * \a callback for each node (which can return false to end iterator).
+ *
+ * \param reversed for backwards iteration
+ * \note Recursive
+ */
+void nodeChainIter(
+ const bNodeTree *ntree, const bNode *node_start,
+ bool (*callback)(bNode *, bNode *, void *, const bool), void *userdata,
+ const bool reversed)
+{
+ bNodeLink *link;
+
+ for (link = ntree->links.first; link; link = link->next) {
+ if ((link->flag & NODE_LINK_VALID) == 0) {
+ /* Skip links marked as cyclic. */
+ continue;
+ }
+ if (link->tonode && link->fromnode) {
+ /* is the link part of the chain meaning node_start == fromnode (or tonode for reversed case)? */
+ if ((reversed && (link->tonode == node_start)) ||
+ (!reversed && link->fromnode == node_start))
+ {
+ if (!callback(link->fromnode, link->tonode, userdata, reversed)) {
+ return;
+ }
+ nodeChainIter(ntree, reversed ? link->fromnode : link->tonode, callback, userdata, reversed);
+ }
+ }
+ }
+}
+
+/**
+ * Iterate over all parents of \a node, executing \a callback for each parent (which can return false to end iterator)
+ *
+ * \note Recursive
+ */
+void nodeParentsIter(bNode *node, bool (*callback)(bNode *, void *), void *userdata)
+{
+ if (node->parent) {
+ if (!callback(node->parent, userdata)) {
+ return;
+ }
+ nodeParentsIter(node->parent, callback, userdata);
+ }
+}
+
/* ************** Add stuff ********** */
/* Find the first available, non-duplicate name for a given node */
@@ -955,7 +1033,7 @@ void nodeRemSocketLinks(bNodeTree *ntree, bNodeSocket *sock)
ntree->update |= NTREE_UPDATE_LINKS;
}
-int nodeLinkIsHidden(bNodeLink *link)
+bool nodeLinkIsHidden(bNodeLink *link)
{
return nodeSocketIsHidden(link->fromsock) || nodeSocketIsHidden(link->tosock);
}
@@ -1109,7 +1187,7 @@ bNodeTree *ntreeAddTree(Main *bmain, const char *name, const char *idname)
* copying for internal use (threads for eg), where you wont want it to modify the
* scene data.
*/
-static bNodeTree *ntreeCopyTree_internal(bNodeTree *ntree, Main *bmain, bool do_id_user, bool do_make_extern, bool copy_previews)
+static bNodeTree *ntreeCopyTree_internal(bNodeTree *ntree, Main *bmain, bool skip_database, bool do_id_user, bool do_make_extern, bool copy_previews)
{
bNodeTree *newtree;
bNode *node /*, *nnode */ /* UNUSED */, *last;
@@ -1119,7 +1197,7 @@ static bNodeTree *ntreeCopyTree_internal(bNodeTree *ntree, Main *bmain, bool do_
if (ntree == NULL) return NULL;
/* is ntree part of library? */
- if (bmain && BLI_findindex(&bmain->nodetree, ntree) >= 0) {
+ if (bmain && !skip_database && BLI_findindex(&bmain->nodetree, ntree) >= 0) {
newtree = BKE_libblock_copy(&ntree->id);
}
else {
@@ -1131,6 +1209,8 @@ static bNodeTree *ntreeCopyTree_internal(bNodeTree *ntree, Main *bmain, bool do_
/* in case a running nodetree is copied */
newtree->execdata = NULL;
+
+ newtree->duplilock = NULL;
BLI_listbase_clear(&newtree->nodes);
BLI_listbase_clear(&newtree->links);
@@ -1202,12 +1282,16 @@ static bNodeTree *ntreeCopyTree_internal(bNodeTree *ntree, Main *bmain, bool do_
/* node tree will generate its own interface type */
newtree->interface_type = NULL;
+ if (ntree->id.lib) {
+ BKE_id_lib_local_paths(bmain, ntree->id.lib, &newtree->id);
+ }
+
return newtree;
}
bNodeTree *ntreeCopyTree_ex(bNodeTree *ntree, Main *bmain, const bool do_id_user)
{
- return ntreeCopyTree_internal(ntree, bmain, do_id_user, true, true);
+ return ntreeCopyTree_internal(ntree, bmain, false, do_id_user, true, true);
}
bNodeTree *ntreeCopyTree(bNodeTree *ntree)
{
@@ -1414,7 +1498,7 @@ static void node_preview_sync(bNodePreview *to, bNodePreview *from)
if (to->rect && from->rect) {
int xsize = to->xsize;
int ysize = to->ysize;
- memcpy(to->rect, from->rect, 4 * xsize + xsize * ysize * sizeof(char) * 4);
+ memcpy(to->rect, from->rect, xsize * ysize * sizeof(char) * 4);
}
}
@@ -1729,7 +1813,7 @@ void ntreeFreeTree_ex(bNodeTree *ntree, const bool do_id_user)
/* unregister associated RNA types */
ntreeInterfaceTypeFree(ntree);
- BKE_free_animdata((ID *)ntree);
+ BKE_animdata_free((ID *)ntree);
id_us_min((ID *)ntree->gpd);
@@ -1771,6 +1855,9 @@ void ntreeFreeTree_ex(bNodeTree *ntree, const bool do_id_user)
if (ntree->previews) {
BKE_node_instance_hash_free(ntree->previews, (bNodeInstanceValueFP)BKE_node_preview_free);
}
+
+ if (ntree->duplilock)
+ BLI_mutex_free(ntree->duplilock);
/* if ntree is not part of library, free the libblock data explicitly */
for (tntree = G.main->nodetree.first; tntree; tntree = tntree->id.next)
@@ -1952,62 +2039,87 @@ int ntreeOutputExists(bNode *node, bNodeSocket *testsock)
return 0;
}
+void ntreeNodeFlagSet(const bNodeTree *ntree, const int flag, const bool enable)
+{
+ bNode *node = ntree->nodes.first;
+
+ for (; node; node = node->next) {
+ if (enable) {
+ node->flag |= flag;
+ }
+ else {
+ node->flag &= ~flag;
+ }
+ }
+}
+
/* returns localized tree for execution in threads */
bNodeTree *ntreeLocalize(bNodeTree *ntree)
{
if (ntree) {
bNodeTree *ltree;
bNode *node;
-
+ AnimData *adt;
+
bAction *action_backup = NULL, *tmpact_backup = NULL;
-
+
+ BLI_spin_lock(&spin);
+ if (!ntree->duplilock) {
+ ntree->duplilock = BLI_mutex_alloc();
+ }
+ BLI_spin_unlock(&spin);
+
+ BLI_mutex_lock(ntree->duplilock);
+
/* Workaround for copying an action on each render!
* set action to NULL so animdata actions don't get copied */
- AnimData *adt = BKE_animdata_from_id(&ntree->id);
-
+ adt = BKE_animdata_from_id(&ntree->id);
+
if (adt) {
action_backup = adt->action;
tmpact_backup = adt->tmpact;
-
+
adt->action = NULL;
adt->tmpact = NULL;
}
-
+
/* Make full copy.
* Note: previews are not copied here.
*/
- ltree = ntreeCopyTree_internal(ntree, NULL, false, false, false);
+ ltree = ntreeCopyTree_internal(ntree, G.main, true, false, false, false);
ltree->flag |= NTREE_IS_LOCALIZED;
-
+
for (node = ltree->nodes.first; node; node = node->next) {
if (node->type == NODE_GROUP && node->id) {
node->id = (ID *)ntreeLocalize((bNodeTree *)node->id);
}
}
-
+
if (adt) {
AnimData *ladt = BKE_animdata_from_id(&ltree->id);
-
+
adt->action = ladt->action = action_backup;
adt->tmpact = ladt->tmpact = tmpact_backup;
-
+
if (action_backup) action_backup->id.us++;
if (tmpact_backup) tmpact_backup->id.us++;
-
+
}
/* end animdata uglyness */
-
+
/* ensures only a single output node is enabled */
ntreeSetOutput(ntree);
-
+
for (node = ntree->nodes.first; node; node = node->next) {
/* store new_node pointer to original */
node->new_node->new_node = node;
}
-
+
if (ntree->typeinfo->localize)
ntree->typeinfo->localize(ltree, ntree);
-
+
+ BLI_mutex_unlock(ntree->duplilock);
+
return ltree;
}
else
@@ -2246,7 +2358,7 @@ StructRNA *ntreeInterfaceTypeGet(bNodeTree *ntree, int create)
ntree_interface_identifier_base(ntree, base);
/* RNA identifier may have a number suffix, but should start with the idbase string */
- if (strncmp(RNA_struct_identifier(srna), base, sizeof(base)) != 0) {
+ if (!STREQLEN(RNA_struct_identifier(srna), base, sizeof(base))) {
/* generate new unique RNA identifier from the ID name */
ntree_interface_identifier(ntree, base, identifier, sizeof(identifier), name, description);
@@ -2293,8 +2405,8 @@ bool ntreeHasType(const bNodeTree *ntree, int type)
if (ntree)
for (node = ntree->nodes.first; node; node = node->next)
if (node->type == type)
- return 1;
- return 0;
+ return true;
+ return false;
}
bool ntreeHasTree(const bNodeTree *ntree, const bNodeTree *lookup)
@@ -2559,8 +2671,8 @@ bool BKE_node_clipboard_validate(void)
/* lists must be aligned */
- BLI_assert(BLI_countlist(&node_clipboard.nodes) ==
- BLI_countlist(&node_clipboard.nodes_extra_info));
+ BLI_assert(BLI_listbase_count(&node_clipboard.nodes) ==
+ BLI_listbase_count(&node_clipboard.nodes_extra_info));
for (node = node_clipboard.nodes.first, node_info = node_clipboard.nodes_extra_info.first;
node;
@@ -2877,7 +2989,7 @@ static void ntree_update_node_level(bNodeTree *ntree)
}
}
-static void ntree_update_link_pointers(bNodeTree *ntree)
+void ntreeTagUsedSockets(bNodeTree *ntree)
{
bNode *node;
bNodeSocket *sock;
@@ -2886,22 +2998,43 @@ static void ntree_update_link_pointers(bNodeTree *ntree)
/* first clear data */
for (node = ntree->nodes.first; node; node = node->next) {
for (sock = node->inputs.first; sock; sock = sock->next) {
- sock->link = NULL;
sock->flag &= ~SOCK_IN_USE;
}
for (sock = node->outputs.first; sock; sock = sock->next) {
sock->flag &= ~SOCK_IN_USE;
}
}
-
+
for (link = ntree->links.first; link; link = link->next) {
- link->tosock->link = link;
+ /* link is unused if either side is disabled */
+ if ((link->fromsock->flag & SOCK_UNAVAIL) || (link->tosock->flag & SOCK_UNAVAIL))
+ continue;
link->fromsock->flag |= SOCK_IN_USE;
link->tosock->flag |= SOCK_IN_USE;
}
}
+static void ntree_update_link_pointers(bNodeTree *ntree)
+{
+ bNode *node;
+ bNodeSocket *sock;
+ bNodeLink *link;
+
+ /* first clear data */
+ for (node = ntree->nodes.first; node; node = node->next) {
+ for (sock = node->inputs.first; sock; sock = sock->next) {
+ sock->link = NULL;
+ }
+ }
+
+ for (link = ntree->links.first; link; link = link->next) {
+ link->tosock->link = link;
+ }
+
+ ntreeTagUsedSockets(ntree);
+}
+
static void ntree_validate_links(bNodeTree *ntree)
{
bNodeLink *link;
@@ -3057,10 +3190,14 @@ void nodeSynchronizeID(bNode *node, bool copy_to_id)
bNodeSocket *sock;
Material *ma = (Material *)node->id;
int a;
+ short check_flags = SOCK_UNAVAIL;
+
+ if (!copy_to_id)
+ check_flags |= SOCK_HIDDEN;
/* hrmf, case in loop isn't super fast, but we don't edit 100s of material at same time either! */
for (a = 0, sock = node->inputs.first; sock; sock = sock->next, a++) {
- if (!nodeSocketIsHidden(sock)) {
+ if (!(sock->flag & check_flags)) {
if (copy_to_id) {
switch (a) {
case MAT_IN_COLOR:
@@ -3450,6 +3587,7 @@ static void registerCompositNodes(void)
register_node_type_cmp_bokehimage();
register_node_type_cmp_bokehblur();
register_node_type_cmp_switch();
+ register_node_type_cmp_switch_view();
register_node_type_cmp_pixelate();
register_node_type_cmp_mask();
@@ -3543,6 +3681,7 @@ static void registerShaderNodes(void)
register_node_type_sh_tex_magic();
register_node_type_sh_tex_checker();
register_node_type_sh_tex_brick();
+ register_node_type_sh_tex_pointdensity();
}
static void registerTextureNodes(void)
@@ -3600,6 +3739,7 @@ void init_nodesystem(void)
nodetreetypes_hash = BLI_ghash_str_new("nodetreetypes_hash gh");
nodetypes_hash = BLI_ghash_str_new("nodetypes_hash gh");
nodesockettypes_hash = BLI_ghash_str_new("nodesockettypes_hash gh");
+ BLI_spin_init(&spin);
register_undefined_types();
diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c
index 755ce91a8af..526a71b477d 100644
--- a/source/blender/blenkernel/intern/object.c
+++ b/source/blender/blenkernel/intern/object.c
@@ -67,7 +67,7 @@
#include "BLI_linklist.h"
#include "BLI_kdtree.h"
-#include "BLF_translation.h"
+#include "BLT_translation.h"
#include "BKE_pbvh.h"
#include "BKE_main.h"
@@ -87,6 +87,7 @@
#include "BKE_effect.h"
#include "BKE_fcurve.h"
#include "BKE_group.h"
+#include "BKE_icons.h"
#include "BKE_key.h"
#include "BKE_lamp.h"
#include "BKE_lattice.h"
@@ -96,6 +97,8 @@
#include "BKE_editmesh.h"
#include "BKE_mball.h"
#include "BKE_modifier.h"
+#include "BKE_multires.h"
+#include "BKE_node.h"
#include "BKE_object.h"
#include "BKE_paint.h"
#include "BKE_particle.h"
@@ -107,6 +110,7 @@
#include "BKE_sequencer.h"
#include "BKE_speaker.h"
#include "BKE_softbody.h"
+#include "BKE_subsurf.h"
#include "BKE_material.h"
#include "BKE_camera.h"
#include "BKE_image.h"
@@ -119,6 +123,8 @@
#include "BPY_extern.h"
#endif
+#include "CCGSubSurf.h"
+
#include "GPU_material.h"
/* Vertex parent modifies original BMesh which is not safe for threading.
@@ -185,6 +191,7 @@ void BKE_object_free_curve_cache(Object *ob)
if (ob->curve_cache->path) {
free_path(ob->curve_cache->path);
}
+ BKE_nurbList_free(&ob->curve_cache->deformed_nurbs);
MEM_freeN(ob->curve_cache);
ob->curve_cache = NULL;
}
@@ -229,7 +236,7 @@ void BKE_object_modifier_hook_reset(Object *ob, HookModifierData *hmd)
bool BKE_object_support_modifier_type_check(Object *ob, int modifier_type)
{
- ModifierTypeInfo *mti;
+ const ModifierTypeInfo *mti;
mti = modifierType_getInfo(modifier_type);
@@ -242,7 +249,7 @@ bool BKE_object_support_modifier_type_check(Object *ob, int modifier_type)
return true;
}
-void BKE_object_link_modifiers(struct Object *ob_dst, struct Object *ob_src)
+void BKE_object_link_modifiers(struct Object *ob_dst, const struct Object *ob_src)
{
ModifierData *md;
BKE_object_free_modifiers(ob_dst);
@@ -258,8 +265,6 @@ void BKE_object_link_modifiers(struct Object *ob_dst, struct Object *ob_src)
if (ELEM(md->type,
eModifierType_Hook,
- eModifierType_Softbody,
- eModifierType_ParticleInstance,
eModifierType_Collision))
{
continue;
@@ -267,21 +272,31 @@ void BKE_object_link_modifiers(struct Object *ob_dst, struct Object *ob_src)
if (!BKE_object_support_modifier_type_check(ob_dst, md->type))
continue;
-
- if (md->type == eModifierType_Skin) {
- /* ensure skin-node customdata exists */
- BKE_mesh_ensure_skin_customdata(ob_dst->data);
+
+ switch (md->type) {
+ case eModifierType_Softbody:
+ BKE_object_copy_softbody(ob_dst, ob_src);
+ break;
+ case eModifierType_Skin:
+ /* ensure skin-node customdata exists */
+ BKE_mesh_ensure_skin_customdata(ob_dst->data);
+ break;
}
nmd = modifier_new(md->type);
BLI_strncpy(nmd->name, md->name, sizeof(nmd->name));
+
+ if (md->type == eModifierType_Multires) {
+ /* Has to be done after mod creation, but *before* we actually copy its settings! */
+ multiresModifier_sync_levels_ex(ob_dst, (MultiresModifierData *)md, (MultiresModifierData *)nmd);
+ }
+
modifier_copyData(md, nmd);
BLI_addtail(&ob_dst->modifiers, nmd);
modifier_unique_name(&ob_dst->modifiers, nmd);
}
BKE_object_copy_particlesystems(ob_dst, ob_src);
- BKE_object_copy_softbody(ob_dst, ob_src);
/* TODO: smoke?, cloth? */
}
@@ -321,17 +336,46 @@ void BKE_object_free_derived_caches(Object *ob)
ob->derivedDeform = NULL;
}
- if (ob->curve_cache) {
- BKE_displist_free(&ob->curve_cache->disp);
- BKE_curve_bevelList_free(&ob->curve_cache->bev);
- if (ob->curve_cache->path) {
- free_path(ob->curve_cache->path);
- ob->curve_cache->path = NULL;
+ BKE_object_free_curve_cache(ob);
+}
+
+void BKE_object_free_caches(Object *object)
+{
+ ModifierData *md;
+ short update_flag = 0;
+
+ /* Free particle system caches holding paths. */
+ if (object->particlesystem.first) {
+ ParticleSystem *psys;
+ for (psys = object->particlesystem.first;
+ psys != NULL;
+ psys = psys->next)
+ {
+ psys_free_path_cache(psys, psys->edit);
+ update_flag |= PSYS_RECALC_REDO;
}
+ }
- /* Signal for viewport to run DAG workarounds. */
- MEM_freeN(ob->curve_cache);
- ob->curve_cache = NULL;
+ /* Free memory used by cached derived meshes in the particle system modifiers. */
+ for (md = object->modifiers.first; md != NULL; md = md->next) {
+ if (md->type == eModifierType_ParticleSystem) {
+ ParticleSystemModifierData *psmd = (ParticleSystemModifierData *) md;
+ if (psmd->dm != NULL) {
+ psmd->dm->needsFree = 1;
+ psmd->dm->release(psmd->dm);
+ psmd->dm = NULL;
+ psmd->flag |= eParticleSystemFlag_file_loaded;
+ update_flag |= OB_RECALC_DATA;
+ }
+ }
+ }
+
+ /* Tag object for update, so once memory critical operation is over and
+ * scene update routines are back to it's business the object will be
+ * guaranteed to be in a known state.
+ */
+ if (update_flag != 0) {
+ DAG_id_tag_update(&object->id, update_flag);
}
}
@@ -375,7 +419,7 @@ void BKE_object_free_ex(Object *ob, bool do_id_user)
ob->iuser = NULL;
if (ob->bb) MEM_freeN(ob->bb);
ob->bb = NULL;
- if (ob->adt) BKE_free_animdata((ID *)ob);
+ if (ob->adt) BKE_animdata_free((ID *)ob);
if (ob->poselib) ob->poselib->id.us--;
if (ob->gpd) ((ID *)ob->gpd)->us--;
if (ob->defbase.first)
@@ -391,7 +435,7 @@ void BKE_object_free_ex(Object *ob, bool do_id_user)
free_controllers(&ob->controllers);
free_actuators(&ob->actuators);
- BKE_constraints_free(&ob->constraints);
+ BKE_constraints_free_ex(&ob->constraints, do_id_user);
free_partdeflect(ob->pd);
BKE_rigidbody_free_object(ob);
@@ -401,7 +445,7 @@ void BKE_object_free_ex(Object *ob, bool do_id_user)
if (ob->bsoft) bsbFree(ob->bsoft);
if (ob->gpulamp.first) GPU_lamp_free(ob);
- BKE_free_sculptsession(ob);
+ BKE_sculptsession_free(ob);
if (ob->pc_ids.first) BLI_freelistN(&ob->pc_ids);
@@ -414,6 +458,8 @@ void BKE_object_free_ex(Object *ob, bool do_id_user)
free_path(ob->curve_cache->path);
MEM_freeN(ob->curve_cache);
}
+
+ BKE_previewimg_free(&ob->preview);
}
void BKE_object_free(Object *ob)
@@ -442,6 +488,7 @@ void BKE_object_unlink(Object *ob)
Scene *sce;
SceneRenderLayer *srl;
FreestyleLineSet *lineset;
+ bNodeTree *ntree;
Curve *cu;
Tex *tex;
Group *group;
@@ -497,7 +544,7 @@ void BKE_object_unlink(Object *ob)
bPoseChannel *pchan;
for (pchan = obt->pose->chanbase.first; pchan; pchan = pchan->next) {
for (con = pchan->constraints.first; con; con = con->next) {
- bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
+ const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
ListBase targets = {NULL, NULL};
bConstraintTarget *ct;
@@ -528,7 +575,7 @@ void BKE_object_unlink(Object *ob)
sca_remove_ob_poin(obt, ob);
for (con = obt->constraints.first; con; con = con->next) {
- bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
+ const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
ListBase targets = {NULL, NULL};
bConstraintTarget *ct;
@@ -643,17 +690,22 @@ void BKE_object_unlink(Object *ob)
}
/* materials */
- mat = bmain->mat.first;
- while (mat) {
-
+ for (mat = bmain->mat.first; mat; mat = mat->id.next) {
+ if (mat->nodetree) {
+ ntreeSwitchID(mat->nodetree, &ob->id, NULL);
+ }
for (a = 0; a < MAX_MTEX; a++) {
if (mat->mtex[a] && ob == mat->mtex[a]->object) {
/* actually, test for lib here... to do */
mat->mtex[a]->object = NULL;
}
}
+ }
- mat = mat->id.next;
+ /* node trees */
+ for (ntree = bmain->nodetree.first; ntree; ntree = ntree->id.next) {
+ if (ntree->type == NTREE_SHADER)
+ ntreeSwitchID(ntree, &ob->id, NULL);
}
/* textures */
@@ -683,6 +735,7 @@ void BKE_object_unlink(Object *ob)
if (sce->camera == ob) sce->camera = NULL;
if (sce->toolsettings->skgen_template == ob) sce->toolsettings->skgen_template = NULL;
if (sce->toolsettings->particle.object == ob) sce->toolsettings->particle.object = NULL;
+ if (sce->toolsettings->particle.shape_object == ob) sce->toolsettings->particle.shape_object = NULL;
#ifdef DURIAN_CAMERA_SWITCH
{
@@ -768,34 +821,11 @@ void BKE_object_unlink(Object *ob)
}
}
}
- else if (sl->spacetype == SPACE_OUTLINER) {
- SpaceOops *so = (SpaceOops *)sl;
-
- if (so->treestore) {
- TreeStoreElem *tselem;
- BLI_mempool_iter iter;
- BLI_mempool_iternew(so->treestore, &iter);
- while ((tselem = BLI_mempool_iterstep(&iter))) {
- if (tselem->id == (ID *)ob) tselem->id = NULL;
- }
- }
- }
- else if (sl->spacetype == SPACE_BUTS) {
- SpaceButs *sbuts = (SpaceButs *)sl;
-
- if (sbuts->pinid == (ID *)ob) {
- sbuts->flag &= ~SB_PIN_CONTEXT;
- sbuts->pinid = NULL;
- }
- }
- else if (sl->spacetype == SPACE_NODE) {
- SpaceNode *snode = (SpaceNode *)sl;
-
- if (snode->from == (ID *)ob) {
- snode->flag &= ~SNODE_PIN;
- snode->from = NULL;
- }
+#if 0
+ else if (ELEM(sl->spacetype, SPACE_OUTLINER, SPACE_BUTS, SPACE_NODE)) {
+ /* now handled by WM_main_remove_editor_id_reference */
}
+#endif
}
sa = sa->next;
@@ -898,26 +928,6 @@ bool BKE_object_exists_check(Object *obtest)
/* *************************************************** */
-void *BKE_object_obdata_add_from_type(Main *bmain, int type)
-{
- switch (type) {
- case OB_MESH: return BKE_mesh_add(bmain, "Mesh");
- case OB_CURVE: return BKE_curve_add(bmain, "Curve", OB_CURVE);
- case OB_SURF: return BKE_curve_add(bmain, "Surf", OB_SURF);
- case OB_FONT: return BKE_curve_add(bmain, "Text", OB_FONT);
- case OB_MBALL: return BKE_mball_add(bmain, "Meta");
- case OB_CAMERA: return BKE_camera_add(bmain, "Camera");
- case OB_LAMP: return BKE_lamp_add(bmain, "Lamp");
- case OB_LATTICE: return BKE_lattice_add(bmain, "Lattice");
- case OB_ARMATURE: return BKE_armature_add(bmain, "Armature");
- case OB_SPEAKER: return BKE_speaker_add(bmain, "Speaker");
- case OB_EMPTY: return NULL;
- default:
- printf("BKE_object_obdata_add_from_type: Internal error, bad type: %d\n", type);
- return NULL;
- }
-}
-
static const char *get_obdata_defname(int type)
{
switch (type) {
@@ -938,6 +948,30 @@ static const char *get_obdata_defname(int type)
}
}
+void *BKE_object_obdata_add_from_type(Main *bmain, int type, const char *name)
+{
+ if (name == NULL) {
+ name = get_obdata_defname(type);
+ }
+
+ switch (type) {
+ case OB_MESH: return BKE_mesh_add(bmain, name);
+ case OB_CURVE: return BKE_curve_add(bmain, name, OB_CURVE);
+ case OB_SURF: return BKE_curve_add(bmain, name, OB_SURF);
+ case OB_FONT: return BKE_curve_add(bmain, name, OB_FONT);
+ case OB_MBALL: return BKE_mball_add(bmain, name);
+ case OB_CAMERA: return BKE_camera_add(bmain, name);
+ case OB_LAMP: return BKE_lamp_add(bmain, name);
+ case OB_LATTICE: return BKE_lattice_add(bmain, name);
+ case OB_ARMATURE: return BKE_armature_add(bmain, name);
+ case OB_SPEAKER: return BKE_speaker_add(bmain, name);
+ case OB_EMPTY: return NULL;
+ default:
+ printf("%s: Internal error, bad type: %d\n", __func__, type);
+ return NULL;
+ }
+}
+
/* more general add: creates minimum required data, but without vertices etc. */
Object *BKE_object_add_only_object(Main *bmain, int type, const char *name)
{
@@ -1008,7 +1042,8 @@ Object *BKE_object_add_only_object(Main *bmain, int type, const char *name)
ob->jump_speed = 10.0f;
ob->fall_speed = 55.0f;
ob->col_group = 0x01;
- ob->col_mask = 0xff;
+ ob->col_mask = 0xffff;
+ ob->preview = NULL;
/* NT fluid sim defaults */
ob->fluidsimSettings = NULL;
@@ -1023,16 +1058,16 @@ Object *BKE_object_add_only_object(Main *bmain, int type, const char *name)
/* general add: to scene, with layer from area and default name */
/* creates minimum required data, but without vertices etc. */
-Object *BKE_object_add(Main *bmain, Scene *scene, int type)
+Object *BKE_object_add(
+ Main *bmain, Scene *scene,
+ int type, const char *name)
{
Object *ob;
Base *base;
- char name[MAX_ID_NAME];
- BLI_strncpy(name, get_obdata_defname(type), sizeof(name));
ob = BKE_object_add_only_object(bmain, type, name);
- ob->data = BKE_object_obdata_add_from_type(bmain, type);
+ ob->data = BKE_object_obdata_add_from_type(bmain, type, name);
ob->lay = scene->lay;
@@ -1058,10 +1093,12 @@ void BKE_object_lod_add(Object *ob)
BLI_addtail(&ob->lodlevels, base);
base->flags = OB_LOD_USE_MESH | OB_LOD_USE_MAT;
base->source = ob;
+ base->obhysteresis = 10;
last = ob->currentlod = base;
}
lod->distance = last->distance + 25.0f;
+ lod->obhysteresis = 10;
lod->flags = OB_LOD_USE_MESH | OB_LOD_USE_MAT;
BLI_addtail(&ob->lodlevels, lod);
@@ -1078,14 +1115,14 @@ static int lod_cmp(const void *a, const void *b)
void BKE_object_lod_sort(Object *ob)
{
- BLI_sortlist(&ob->lodlevels, lod_cmp);
+ BLI_listbase_sort(&ob->lodlevels, lod_cmp);
}
bool BKE_object_lod_remove(Object *ob, int level)
{
LodLevel *rem;
- if (level < 1 || level > BLI_countlist(&ob->lodlevels) - 1)
+ if (level < 1 || level > BLI_listbase_count(&ob->lodlevels) - 1)
return false;
rem = BLI_findlink(&ob->lodlevels, level);
@@ -1098,7 +1135,7 @@ bool BKE_object_lod_remove(Object *ob, int level)
MEM_freeN(rem);
/* If there are no user defined lods, remove the base lod as well */
- if (BLI_countlist(&ob->lodlevels) == 1) {
+ if (BLI_listbase_is_single(&ob->lodlevels)) {
LodLevel *base = ob->lodlevels.first;
BLI_remlink(&ob->lodlevels, base);
MEM_freeN(base);
@@ -1126,7 +1163,7 @@ static LodLevel *lod_level_select(Object *ob, const float camera_position[3])
}
else {
/* check for lower LoD */
- while (current->next && dist_sq > (current->next->distance * current->next->distance)) {
+ while (current->next && dist_sq > SQUARE(current->next->distance)) {
current = current->next;
}
}
@@ -1136,7 +1173,7 @@ static LodLevel *lod_level_select(Object *ob, const float camera_position[3])
bool BKE_object_lod_is_usable(Object *ob, Scene *scene)
{
- bool active = (scene) ? ob == OBACT : 0;
+ bool active = (scene) ? ob == OBACT : false;
return (ob->mode == OB_MODE_OBJECT || !active);
}
@@ -1177,7 +1214,7 @@ struct Object *BKE_object_lod_matob_get(Object *ob, Scene *scene)
#endif /* WITH_GAMEENGINE */
-SoftBody *copy_softbody(SoftBody *sb, bool copy_caches)
+SoftBody *copy_softbody(const SoftBody *sb, bool copy_caches)
{
SoftBody *sbn;
@@ -1233,7 +1270,7 @@ BulletSoftBody *copy_bulletsoftbody(BulletSoftBody *bsb)
return bsbn;
}
-static ParticleSystem *copy_particlesystem(ParticleSystem *psys)
+ParticleSystem *BKE_object_copy_particlesystem(ParticleSystem *psys)
{
ParticleSystem *psysn;
ParticleData *pa;
@@ -1301,24 +1338,24 @@ static ParticleSystem *copy_particlesystem(ParticleSystem *psys)
return psysn;
}
-void BKE_object_copy_particlesystems(Object *obn, Object *ob)
+void BKE_object_copy_particlesystems(Object *ob_dst, const Object *ob_src)
{
ParticleSystem *psys, *npsys;
ModifierData *md;
- if (obn->type != OB_MESH) {
+ if (ob_dst->type != OB_MESH) {
/* currently only mesh objects can have soft body */
return;
}
- BLI_listbase_clear(&obn->particlesystem);
- for (psys = ob->particlesystem.first; psys; psys = psys->next) {
- npsys = copy_particlesystem(psys);
+ BLI_listbase_clear(&ob_dst->particlesystem);
+ for (psys = ob_src->particlesystem.first; psys; psys = psys->next) {
+ npsys = BKE_object_copy_particlesystem(psys);
- BLI_addtail(&obn->particlesystem, npsys);
+ BLI_addtail(&ob_dst->particlesystem, npsys);
/* need to update particle modifiers too */
- for (md = obn->modifiers.first; md; md = md->next) {
+ for (md = ob_dst->modifiers.first; md; md = md->next) {
if (md->type == eModifierType_ParticleSystem) {
ParticleSystemModifierData *psmd = (ParticleSystemModifierData *)md;
if (psmd->psys == psys)
@@ -1346,10 +1383,12 @@ void BKE_object_copy_particlesystems(Object *obn, Object *ob)
}
}
-void BKE_object_copy_softbody(Object *obn, Object *ob)
+void BKE_object_copy_softbody(Object *ob_dst, const Object *ob_src)
{
- if (ob->soft)
- obn->soft = copy_softbody(ob->soft, false);
+ if (ob_src->soft) {
+ ob_dst->softflag = ob_src->softflag;
+ ob_dst->soft = copy_softbody(ob_src->soft, false);
+ }
}
static void copy_object_pose(Object *obn, Object *ob)
@@ -1366,7 +1405,7 @@ static void copy_object_pose(Object *obn, Object *ob)
chan->flag &= ~(POSE_LOC | POSE_ROT | POSE_SIZE);
for (con = chan->constraints.first; con; con = con->next) {
- bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
+ const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
ListBase targets = {NULL, NULL};
bConstraintTarget *ct;
@@ -1402,10 +1441,10 @@ bool BKE_object_pose_context_check(Object *ob)
(ob->pose) &&
(ob->mode & OB_MODE_POSE))
{
- return 1;
+ return true;
}
else {
- return 0;
+ return false;
}
}
@@ -1518,6 +1557,13 @@ Object *BKE_object_copy_ex(Main *bmain, Object *ob, bool copy_caches)
/* Copy runtime surve data. */
obn->curve_cache = NULL;
+ if (ob->id.lib) {
+ BKE_id_lib_local_paths(bmain, ob->id.lib, &obn->id);
+ }
+
+ /* Do not copy object's preview (mostly due to the fact renderers create temp copy of objects). */
+ obn->preview = NULL;
+
return obn;
}
@@ -1554,6 +1600,8 @@ static void extern_local_object(Object *ob)
id_lib_extern((ID *)psys->part);
modifiers_foreachIDLink(ob, extern_local_object__modifiersForeachIDLink, NULL);
+
+ ob->preview = NULL;
}
void BKE_object_make_local(Object *ob)
@@ -1570,7 +1618,7 @@ void BKE_object_make_local(Object *ob)
if (ob->id.lib == NULL) return;
- ob->proxy = ob->proxy_from = NULL;
+ ob->proxy = ob->proxy_from = ob->proxy_group = NULL;
if (ob->id.us == 1) {
id_clear_lib_data(bmain, &ob->id);
@@ -1661,7 +1709,7 @@ void BKE_object_copy_proxy_drivers(Object *ob, Object *target)
/* add new animdata block */
if (!ob->adt)
- ob->adt = BKE_id_add_animdata(&ob->id);
+ ob->adt = BKE_animdata_add_id(&ob->id);
/* make a copy of all the drivers (for now), then correct any links that need fixing */
free_fcurves(&ob->adt->drivers);
@@ -1723,8 +1771,7 @@ void BKE_object_make_proxy(Object *ob, Object *target, Object *gob)
mul_m4_m4m4(ob->obmat, gob->obmat, target->obmat);
if (gob->dup_group) { /* should always be true */
float tvec[3];
- copy_v3_v3(tvec, gob->dup_group->dupli_ofs);
- mul_mat3_m4_v3(ob->obmat, tvec);
+ mul_v3_mat3_m4v3(tvec, ob->obmat, gob->dup_group->dupli_ofs);
sub_v3_v3(ob->obmat[3], tvec);
}
BKE_object_apply_mat4(ob, ob->obmat, false, true);
@@ -2022,9 +2069,11 @@ void BKE_object_to_mat4(Object *ob, float mat[4][4])
void BKE_object_matrix_local_get(struct Object *ob, float mat[4][4])
{
if (ob->parent) {
- float invmat[4][4]; /* for inverse of parent's matrix */
- invert_m4_m4(invmat, ob->parent->obmat);
- mul_m4_m4m4(mat, invmat, ob->obmat);
+ float par_imat[4][4];
+
+ BKE_object_get_parent_matrix(NULL, ob, ob->parent, par_imat);
+ invert_m4(par_imat);
+ mul_m4_m4m4(mat, par_imat, ob->obmat);
}
else {
copy_m4_m4(mat, ob->obmat);
@@ -2034,24 +2083,29 @@ void BKE_object_matrix_local_get(struct Object *ob, float mat[4][4])
/* extern */
int enable_cu_speed = 1;
-static void ob_parcurve(Scene *scene, Object *ob, Object *par, float mat[4][4])
+/**
+ * \param scene: Used when curve cache needs to be calculated, or for dupli-frame time.
+ * \return success if \a mat is set.
+ */
+static bool ob_parcurve(Scene *scene, Object *ob, Object *par, float mat[4][4])
{
- Curve *cu;
+ Curve *cu = par->data;
float vec[4], dir[3], quat[4], radius, ctime;
-
- unit_m4(mat);
-
- cu = par->data;
- if (ELEM(NULL, par->curve_cache, par->curve_cache->path, par->curve_cache->path->data)) /* only happens on reload file, but violates depsgraph still... fix! */
+
+ /* only happens on reload file, but violates depsgraph still... fix! */
+ if (par->curve_cache == NULL) {
+ if (scene == NULL) {
+ return false;
+ }
BKE_displist_make_curveTypes(scene, par, 0);
- if (par->curve_cache->path == NULL) return;
-
- /* catch exceptions: feature for nla stride editing */
- if (ob->ipoflag & OB_DISABLE_PATH) {
- ctime = 0.0f;
}
+
+ if (par->curve_cache->path == NULL) {
+ return false;
+ }
+
/* catch exceptions: curve paths used as a duplicator */
- else if (enable_cu_speed) {
+ if (enable_cu_speed) {
/* ctime is now a proper var setting of Curve which gets set by Animato like any other var that's animated,
* but this will only work if it actually is animated...
*
@@ -2068,6 +2122,11 @@ static void ob_parcurve(Scene *scene, Object *ob, Object *par, float mat[4][4])
CLAMP(ctime, 0.0f, 1.0f);
}
else {
+ /* For dupli-frames only */
+ if (scene == NULL) {
+ return false;
+ }
+
ctime = BKE_scene_frame_get(scene);
if (cu->pathlen) {
ctime /= cu->pathlen;
@@ -2076,8 +2135,10 @@ static void ob_parcurve(Scene *scene, Object *ob, Object *par, float mat[4][4])
CLAMP(ctime, 0.0f, 1.0f);
}
+ unit_m4(mat);
+
/* vec: 4 items! */
- if (where_on_path(par, ctime, vec, dir, cu->flag & CU_FOLLOW ? quat : NULL, &radius, NULL)) {
+ if (where_on_path(par, ctime, vec, dir, (cu->flag & CU_FOLLOW) ? quat : NULL, &radius, NULL)) {
if (cu->flag & CU_FOLLOW) {
#if 0
@@ -2109,6 +2170,8 @@ static void ob_parcurve(Scene *scene, Object *ob, Object *par, float mat[4][4])
copy_v3_v3(mat[3], vec);
}
+
+ return true;
}
static void ob_parbone(Object *ob, Object *par, float mat[4][4])
@@ -2161,26 +2224,60 @@ static void give_parvert(Object *par, int nr, float vec[3])
int numVerts = dm->getNumVerts(dm);
if (nr < numVerts) {
- /* avoid dm->getVertDataArray() since it allocates arrays in the dm (not thread safe) */
- int i;
+ bool use_special_ss_case = false;
+
+ if (dm->type == DM_TYPE_CCGDM) {
+ ModifierData *md;
+ VirtualModifierData virtualModifierData;
+ use_special_ss_case = true;
+ for (md = modifiers_getVirtualModifierList(par, &virtualModifierData);
+ md != NULL;
+ md = md->next)
+ {
+ const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
+ /* TODO(sergey): Check for disabled modifiers. */
+ if (mti->type != eModifierTypeType_OnlyDeform && md->next != NULL) {
+ use_special_ss_case = false;
+ break;
+ }
+ }
+ }
- if (em && dm->type == DM_TYPE_EDITBMESH) {
- if (em->bm->elem_table_dirty & BM_VERT) {
-#ifdef VPARENT_THREADING_HACK
- BLI_mutex_lock(&vparent_lock);
+ if (!use_special_ss_case) {
+ /* avoid dm->getVertDataArray() since it allocates arrays in the dm (not thread safe) */
+ if (em && dm->type == DM_TYPE_EDITBMESH) {
if (em->bm->elem_table_dirty & BM_VERT) {
- BM_mesh_elem_table_ensure(em->bm, BM_VERT);
- }
- BLI_mutex_unlock(&vparent_lock);
+#ifdef VPARENT_THREADING_HACK
+ BLI_mutex_lock(&vparent_lock);
+ if (em->bm->elem_table_dirty & BM_VERT) {
+ BM_mesh_elem_table_ensure(em->bm, BM_VERT);
+ }
+ BLI_mutex_unlock(&vparent_lock);
#else
- BLI_assert(!"Not safe for threading");
- BM_mesh_elem_table_ensure(em->bm, BM_VERT);
+ BLI_assert(!"Not safe for threading");
+ BM_mesh_elem_table_ensure(em->bm, BM_VERT);
#endif
+ }
}
}
- /* get the average of all verts with (original index == nr) */
- if (CustomData_has_layer(&dm->vertData, CD_ORIGINDEX)) {
+ if (use_special_ss_case) {
+ /* Special case if the last modifier is SS and no constructive modifier are in front of it. */
+ CCGDerivedMesh *ccgdm = (CCGDerivedMesh *)dm;
+ CCGVert *ccg_vert = ccgSubSurf_getVert(ccgdm->ss, SET_INT_IN_POINTER(nr));
+ /* In case we deleted some verts, nr may refer to inexistent one now, see T42557. */
+ if (ccg_vert) {
+ float *co = ccgSubSurf_getVertData(ccgdm->ss, ccg_vert);
+ add_v3_v3(vec, co);
+ count++;
+ }
+ }
+ else if (CustomData_has_layer(&dm->vertData, CD_ORIGINDEX) &&
+ !(em && dm->type == DM_TYPE_EDITBMESH))
+ {
+ int i;
+
+ /* Get the average of all verts with (original index == nr). */
for (i = 0; i < numVerts; i++) {
const int *index = dm->getVertData(dm, i, CD_ORIGINDEX);
if (*index == nr) {
@@ -2219,8 +2316,18 @@ static void give_parvert(Object *par, int nr, float vec[3])
}
}
else if (ELEM(par->type, OB_CURVE, OB_SURF)) {
- Curve *cu = par->data;
- ListBase *nurb = BKE_curve_nurbs_get(cu);
+ ListBase *nurb;
+
+ /* Unless there's some weird depsgraph failure the cache should exist. */
+ BLI_assert(par->curve_cache != NULL);
+
+ if (par->curve_cache->deformed_nurbs.first != NULL) {
+ nurb = &par->curve_cache->deformed_nurbs;
+ }
+ else {
+ Curve *cu = par->data;
+ nurb = BKE_curve_nurbs_get(cu);
+ }
BKE_nurbList_index_get_co(nurb, nr, vec);
}
@@ -2270,7 +2377,8 @@ static void ob_parvert3(Object *ob, Object *par, float mat[4][4])
}
}
-static void ob_get_parent_matrix(Scene *scene, Object *ob, Object *par, float parentmat[4][4])
+
+void BKE_object_get_parent_matrix(Scene *scene, Object *ob, Object *par, float parentmat[4][4])
{
float tmat[4][4];
float vec[3];
@@ -2280,8 +2388,9 @@ static void ob_get_parent_matrix(Scene *scene, Object *ob, Object *par, float pa
case PAROBJECT:
ok = 0;
if (par->type == OB_CURVE) {
- if (scene && ((Curve *)par->data)->flag & CU_PATH) {
- ob_parcurve(scene, ob, par, tmat);
+ if ((((Curve *)par->data)->flag & CU_PATH) &&
+ (ob_parcurve(scene, ob, par, tmat)))
+ {
ok = 1;
}
}
@@ -2327,7 +2436,7 @@ static void solve_parenting(Scene *scene, Object *ob, Object *par, float obmat[4
if (ob->partype & PARSLOW) copy_m4_m4(slowmat, obmat);
- ob_get_parent_matrix(scene, ob, par, totmat);
+ BKE_object_get_parent_matrix(scene, ob, par, totmat);
/* total */
mul_m4_m4m4(tmat, totmat, ob->parentinv);
@@ -2357,7 +2466,7 @@ static bool where_is_object_parslow(Object *ob, float obmat[4][4], float slowmat
/* include framerate */
fac1 = (1.0f / (1.0f + fabsf(ob->sf)));
- if (fac1 >= 1.0f) return 0;
+ if (fac1 >= 1.0f) return false;
fac2 = 1.0f - fac1;
fp1 = obmat[0];
@@ -2366,7 +2475,7 @@ static bool where_is_object_parslow(Object *ob, float obmat[4][4], float slowmat
fp1[0] = fac1 * fp1[0] + fac2 * fp2[0];
}
- return 1;
+ return true;
}
/* note, scene is the active scene while actual_scene is the scene the object resides in */
@@ -2485,22 +2594,21 @@ void BKE_object_apply_mat4(Object *ob, float mat[4][4], const bool use_compat, c
if (use_parent && ob->parent) {
float rmat[4][4], diff_mat[4][4], imat[4][4], parent_mat[4][4];
- ob_get_parent_matrix(NULL, ob, ob->parent, parent_mat);
+ BKE_object_get_parent_matrix(NULL, ob, ob->parent, parent_mat);
mul_m4_m4m4(diff_mat, parent_mat, ob->parentinv);
invert_m4_m4(imat, diff_mat);
mul_m4_m4m4(rmat, imat, mat); /* get the parent relative matrix */
- BKE_object_apply_mat4(ob, rmat, use_compat, false);
/* same as below, use rmat rather than mat */
mat4_to_loc_rot_size(ob->loc, rot, ob->size, rmat);
- BKE_object_mat3_to_rot(ob, rot, use_compat);
}
else {
mat4_to_loc_rot_size(ob->loc, rot, ob->size, mat);
- BKE_object_mat3_to_rot(ob, rot, use_compat);
}
+ BKE_object_mat3_to_rot(ob, rot, use_compat);
+
sub_v3_v3(ob->loc, ob->dloc);
if (ob->dscale[0] != 0.0f) ob->size[0] /= ob->dscale[0];
@@ -2547,6 +2655,76 @@ void BKE_boundbox_calc_size_aabb(const BoundBox *bb, float r_size[3])
r_size[2] = 0.5f * fabsf(bb->vec[0][2] - bb->vec[1][2]);
}
+void BKE_boundbox_minmax(const BoundBox *bb, float obmat[4][4], float r_min[3], float r_max[3])
+{
+ int i;
+ for (i = 0; i < 8; i++) {
+ float vec[3];
+ mul_v3_m4v3(vec, obmat, bb->vec[i]);
+ minmax_v3v3_v3(r_min, r_max, vec);
+ }
+}
+
+/**
+ * Returns a BBox which each dimensions are at least epsilon.
+ * \note In case a given dimension needs to be enlarged, its final value will be in [epsilon, 3 * epsilon] range.
+ *
+ * \param bb the input bbox to check.
+ * \param bb_temp the temp bbox to modify (\a bb content is never changed).
+ * \param epsilon the minimum dimension to ensure.
+ * \return either bb (if nothing needed to be changed) or bb_temp.
+ */
+BoundBox *BKE_boundbox_ensure_minimum_dimensions(BoundBox *bb, BoundBox *bb_temp, const float epsilon)
+{
+ if (fabsf(bb->vec[0][0] - bb->vec[4][0]) < epsilon) {
+ /* Flat along X axis... */
+ *bb_temp = *bb;
+ bb = bb_temp;
+ bb->vec[0][0] -= epsilon;
+ bb->vec[1][0] -= epsilon;
+ bb->vec[2][0] -= epsilon;
+ bb->vec[3][0] -= epsilon;
+ bb->vec[4][0] += epsilon;
+ bb->vec[5][0] += epsilon;
+ bb->vec[6][0] += epsilon;
+ bb->vec[7][0] += epsilon;
+ }
+
+ if (fabsf(bb->vec[0][1] - bb->vec[3][1]) < epsilon) {
+ /* Flat along Y axis... */
+ if (bb != bb_temp) {
+ *bb_temp = *bb;
+ bb = bb_temp;
+ }
+ bb->vec[0][1] -= epsilon;
+ bb->vec[1][1] -= epsilon;
+ bb->vec[4][1] -= epsilon;
+ bb->vec[5][1] -= epsilon;
+ bb->vec[2][1] += epsilon;
+ bb->vec[3][1] += epsilon;
+ bb->vec[6][1] += epsilon;
+ bb->vec[7][1] += epsilon;
+ }
+
+ if (fabsf(bb->vec[0][2] - bb->vec[1][2]) < epsilon) {
+ /* Flat along Z axis... */
+ if (bb != bb_temp) {
+ *bb_temp = *bb;
+ bb = bb_temp;
+ }
+ bb->vec[0][2] -= epsilon;
+ bb->vec[3][2] -= epsilon;
+ bb->vec[4][2] -= epsilon;
+ bb->vec[7][2] -= epsilon;
+ bb->vec[1][2] += epsilon;
+ bb->vec[2][2] += epsilon;
+ bb->vec[5][2] += epsilon;
+ bb->vec[6][2] += epsilon;
+ }
+
+ return bb;
+}
+
BoundBox *BKE_object_boundbox_get(Object *ob)
{
BoundBox *bb = NULL;
@@ -2560,6 +2738,12 @@ BoundBox *BKE_object_boundbox_get(Object *ob)
else if (ob->type == OB_MBALL) {
bb = ob->bb;
}
+ else if (ob->type == OB_LATTICE) {
+ bb = BKE_lattice_boundbox_get(ob);
+ }
+ else if (ob->type == OB_ARMATURE) {
+ bb = BKE_armature_boundbox_get(ob);
+ }
return bb;
}
@@ -2616,7 +2800,6 @@ 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 changed = false;
switch (ob->type) {
@@ -2625,11 +2808,7 @@ void BKE_object_minmax(Object *ob, float min_r[3], float max_r[3], const bool us
case OB_SURF:
{
bb = *BKE_curve_boundbox_get(ob);
-
- for (a = 0; a < 8; a++) {
- mul_m4_v3(ob->obmat, bb.vec[a]);
- minmax_v3v3_v3(min_r, max_r, bb.vec[a]);
- }
+ BKE_boundbox_minmax(&bb, ob->obmat, min_r, max_r);
changed = true;
break;
}
@@ -2652,23 +2831,7 @@ void BKE_object_minmax(Object *ob, float min_r[3], float max_r[3], const bool us
}
case OB_ARMATURE:
{
- if (ob->pose) {
- bArmature *arm = ob->data;
- bPoseChannel *pchan;
-
- for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
- /* XXX pchan->bone may be NULL for duplicated bones, see duplicateEditBoneObjects() comment
- * (editarmature.c:2592)... Skip in this case too! */
- if (pchan->bone && !((use_hidden == false) && (PBONE_VISIBLE(arm, pchan->bone) == false))) {
- mul_v3_m4v3(vec, ob->obmat, pchan->pose_head);
- minmax_v3v3_v3(min_r, max_r, vec);
- mul_v3_m4v3(vec, ob->obmat, pchan->pose_tail);
- minmax_v3v3_v3(min_r, max_r, vec);
-
- changed = true;
- }
- }
- }
+ changed = BKE_pose_minmax(ob, min_r, max_r, use_hidden, false);
break;
}
case OB_MESH:
@@ -2677,11 +2840,7 @@ void BKE_object_minmax(Object *ob, float min_r[3], float max_r[3], const bool us
if (me) {
bb = *BKE_mesh_boundbox_get(ob);
-
- for (a = 0; a < 8; a++) {
- mul_m4_v3(ob->obmat, bb.vec[a]);
- minmax_v3v3_v3(min_r, max_r, bb.vec[a]);
- }
+ BKE_boundbox_minmax(&bb, ob->obmat, min_r, max_r);
changed = true;
}
break;
@@ -2921,8 +3080,12 @@ void BKE_object_handle_update_ex(EvaluationContext *eval_ctx,
{
if (ob->recalc & OB_RECALC_ALL) {
/* speed optimization for animation lookups */
- if (ob->pose)
+ if (ob->pose) {
BKE_pose_channels_hash_make(ob->pose);
+ if (ob->pose->flag & POSE_CONSTRAINTS_NEED_UPDATE_FLAGS) {
+ BKE_pose_update_constraint_flags(ob->pose);
+ }
+ }
if (ob->recalc & OB_RECALC_DATA) {
if (ob->type == OB_ARMATURE) {
@@ -2948,8 +3111,9 @@ void BKE_object_handle_update_ex(EvaluationContext *eval_ctx,
// printf("ob proxy copy, lib ob %s proxy %s\n", ob->id.name, ob->proxy_from->id.name);
if (ob->proxy_from->proxy_group) { /* transform proxy into group space */
Object *obg = ob->proxy_from->proxy_group;
- invert_m4_m4(obg->imat, obg->obmat);
- mul_m4_m4m4(ob->obmat, obg->imat, ob->proxy_from->obmat);
+ float imat[4][4];
+ invert_m4_m4(imat, obg->obmat);
+ mul_m4_m4m4(ob->obmat, imat, ob->proxy_from->obmat);
if (obg->dup_group) { /* should always be true */
add_v3_v3(ob->obmat[3], obg->dup_group->dupli_ofs);
}
@@ -2962,147 +3126,7 @@ void BKE_object_handle_update_ex(EvaluationContext *eval_ctx,
}
if (ob->recalc & OB_RECALC_DATA) {
- ID *data_id = (ID *)ob->data;
- AnimData *adt = BKE_animdata_from_id(data_id);
- Key *key;
- float ctime = BKE_scene_frame_get(scene);
-
- if (G.debug & G_DEBUG_DEPSGRAPH)
- printf("recalcdata %s\n", ob->id.name + 2);
-
- if (adt) {
- /* evaluate drivers - datalevel */
- /* XXX: for mesh types, should we push this to derivedmesh instead? */
- BKE_animsys_evaluate_animdata(scene, data_id, adt, ctime, ADT_RECALC_DRIVERS);
- }
-
- key = BKE_key_from_object(ob);
- if (key && key->block.first) {
- if (!(ob->shapeflag & OB_SHAPE_LOCK))
- BKE_animsys_evaluate_animdata(scene, &key->id, key->adt, ctime, ADT_RECALC_DRIVERS);
- }
-
- /* includes all keys and modifiers */
- switch (ob->type) {
- case OB_MESH:
- {
- BMEditMesh *em = (ob == scene->obedit) ? BKE_editmesh_from_object(ob) : NULL;
- uint64_t data_mask = scene->customdata_mask | CD_MASK_BAREMESH;
-#ifdef WITH_FREESTYLE
- /* make sure Freestyle edge/face marks appear in DM for render (see T40315) */
- if (eval_ctx->mode != DAG_EVAL_VIEWPORT) {
- data_mask |= CD_MASK_FREESTYLE_EDGE | CD_MASK_FREESTYLE_FACE;
- }
-#endif
- if (em) {
- makeDerivedMesh(scene, ob, em, data_mask, 0); /* was CD_MASK_BAREMESH */
- }
- else {
- makeDerivedMesh(scene, ob, NULL, data_mask, 0);
- }
- break;
- }
- case OB_ARMATURE:
- if (ob->id.lib && ob->proxy_from) {
- if (BKE_pose_copy_result(ob->pose, ob->proxy_from->pose) == false) {
- printf("Proxy copy error, lib Object: %s proxy Object: %s\n",
- ob->id.name + 2, ob->proxy_from->id.name + 2);
- }
- }
- else {
- BKE_pose_where_is(scene, ob);
- }
- break;
-
- case OB_MBALL:
- BKE_displist_make_mball(eval_ctx, scene, ob);
- break;
-
- case OB_CURVE:
- case OB_SURF:
- case OB_FONT:
- BKE_displist_make_curveTypes(scene, ob, 0);
- break;
-
- case OB_LATTICE:
- BKE_lattice_modifiers_calc(scene, ob);
- break;
-
- case OB_EMPTY:
- if (ob->empty_drawtype == OB_EMPTY_IMAGE && ob->data)
- if (BKE_image_is_animated(ob->data))
- BKE_image_user_check_frame_calc(ob->iuser, (int)ctime, 0);
- break;
- }
-
- /* related materials */
- /* XXX: without depsgraph tagging, this will always need to be run, which will be slow!
- * However, not doing anything (or trying to hack around this lack) is not an option
- * anymore, especially due to Cycles [#31834]
- */
- if (ob->totcol) {
- int a;
-
- for (a = 1; a <= ob->totcol; a++) {
- Material *ma = give_current_material(ob, a);
-
- if (ma) {
- /* recursively update drivers for this material */
- material_drivers_update(scene, ma, ctime);
- }
- }
- }
- else if (ob->type == OB_LAMP)
- lamp_drivers_update(scene, ob->data, ctime);
-
- /* particles */
- if (ob != scene->obedit && ob->particlesystem.first) {
- ParticleSystem *tpsys, *psys;
- DerivedMesh *dm;
- ob->transflag &= ~OB_DUPLIPARTS;
-
- psys = ob->particlesystem.first;
- while (psys) {
- /* ensure this update always happens even if psys is disabled */
- if (psys->recalc & PSYS_RECALC_TYPE) {
- psys_changed_type(ob, psys);
- }
-
- if (psys_check_enabled(ob, psys)) {
- /* check use of dupli objects here */
- if (psys->part && (psys->part->draw_as == PART_DRAW_REND || eval_ctx->mode == DAG_EVAL_RENDER) &&
- ((psys->part->ren_as == PART_DRAW_OB && psys->part->dup_ob) ||
- (psys->part->ren_as == PART_DRAW_GR && psys->part->dup_group)))
- {
- ob->transflag |= OB_DUPLIPARTS;
- }
-
- particle_system_update(scene, ob, psys);
- psys = psys->next;
- }
- else if (psys->flag & PSYS_DELETE) {
- tpsys = psys->next;
- BLI_remlink(&ob->particlesystem, psys);
- psys_free(ob, psys);
- psys = tpsys;
- }
- else
- psys = psys->next;
- }
-
- if (eval_ctx->mode == DAG_EVAL_RENDER && ob->transflag & OB_DUPLIPARTS) {
- /* this is to make sure we get render level duplis in groups:
- * the derivedmesh must be created before init_render_mesh,
- * since object_duplilist does dupliparticles before that */
- dm = mesh_create_derived_render(scene, ob, CD_MASK_BAREMESH | CD_MASK_MTFACE | CD_MASK_MCOL);
- dm->release(dm);
-
- for (psys = ob->particlesystem.first; psys; psys = psys->next)
- psys_get_modifier(ob, psys)->flag &= ~eParticleSystemFlag_psys_updated;
- }
- }
-
- /* quick cache removed */
+ BKE_object_handle_data_update(eval_ctx, scene, ob);
}
ob->recalc &= ~OB_RECALC_ALL;
@@ -3147,7 +3171,7 @@ void BKE_object_sculpt_modifiers_changed(Object *ob)
ss->pbvh = NULL;
}
- BKE_free_sculptsession_deformMats(ob->sculpt);
+ BKE_sculptsession_free_deformMats(ob->sculpt);
}
else {
PBVHNode **nodes;
@@ -3255,7 +3279,7 @@ int BKE_object_insert_ptcache(Object *ob)
LinkData *link = NULL;
int i = 0;
- BLI_sortlist(&ob->pc_ids, pc_cmp);
+ BLI_listbase_sort(&ob->pc_ids, pc_cmp);
for (link = ob->pc_ids.first, i = 0; link; link = link->next, i++) {
int index = GET_INT_FROM_POINTER(link->data);
@@ -3300,7 +3324,7 @@ void BKE_object_delete_ptcache(Object *ob, int index)
/* shape key utility function */
/************************* Mesh ************************/
-static KeyBlock *insert_meshkey(Scene *scene, Object *ob, const char *name, const bool from_mix)
+static KeyBlock *insert_meshkey(Object *ob, const char *name, const bool from_mix)
{
Mesh *me = ob->data;
Key *key = me->key;
@@ -3316,12 +3340,12 @@ static KeyBlock *insert_meshkey(Scene *scene, Object *ob, const char *name, cons
if (newkey || from_mix == false) {
/* create from mesh */
kb = BKE_keyblock_add_ctime(key, name, false);
- BKE_key_convert_from_mesh(me, kb);
+ BKE_keyblock_convert_from_mesh(me, kb);
}
else {
/* copy from current values */
int totelem;
- float *data = BKE_key_evaluate_object(scene, ob, &totelem);
+ float *data = BKE_key_evaluate_object(ob, &totelem);
/* create new block with prepared data */
kb = BKE_keyblock_add_ctime(key, name, false);
@@ -3332,7 +3356,7 @@ static KeyBlock *insert_meshkey(Scene *scene, Object *ob, const char *name, cons
return kb;
}
/************************* Lattice ************************/
-static KeyBlock *insert_lattkey(Scene *scene, Object *ob, const char *name, const bool from_mix)
+static KeyBlock *insert_lattkey(Object *ob, const char *name, const bool from_mix)
{
Lattice *lt = ob->data;
Key *key = lt->key;
@@ -3353,13 +3377,13 @@ static KeyBlock *insert_lattkey(Scene *scene, Object *ob, const char *name, cons
kb->totelem = basekb->totelem;
}
else {
- BKE_key_convert_from_lattice(lt, kb);
+ BKE_keyblock_convert_from_lattice(lt, kb);
}
}
else {
/* copy from current values */
int totelem;
- float *data = BKE_key_evaluate_object(scene, ob, &totelem);
+ float *data = BKE_key_evaluate_object(ob, &totelem);
/* create new block with prepared data */
kb = BKE_keyblock_add_ctime(key, name, false);
@@ -3370,7 +3394,7 @@ static KeyBlock *insert_lattkey(Scene *scene, Object *ob, const char *name, cons
return kb;
}
/************************* Curve ************************/
-static KeyBlock *insert_curvekey(Scene *scene, Object *ob, const char *name, const bool from_mix)
+static KeyBlock *insert_curvekey(Object *ob, const char *name, const bool from_mix)
{
Curve *cu = ob->data;
Key *key = cu->key;
@@ -3393,13 +3417,13 @@ static KeyBlock *insert_curvekey(Scene *scene, Object *ob, const char *name, con
kb->totelem = basekb->totelem;
}
else {
- BKE_key_convert_from_curve(cu, kb, lb);
+ BKE_keyblock_convert_from_curve(cu, kb, lb);
}
}
else {
/* copy from current values */
int totelem;
- float *data = BKE_key_evaluate_object(scene, ob, &totelem);
+ float *data = BKE_key_evaluate_object(ob, &totelem);
/* create new block with prepared data */
kb = BKE_keyblock_add_ctime(key, name, false);
@@ -3410,22 +3434,114 @@ static KeyBlock *insert_curvekey(Scene *scene, Object *ob, const char *name, con
return kb;
}
-KeyBlock *BKE_object_insert_shape_key(Scene *scene, Object *ob, const char *name, const bool from_mix)
+KeyBlock *BKE_object_shapekey_insert(Object *ob, const char *name, const bool from_mix)
{
switch (ob->type) {
case OB_MESH:
- return insert_meshkey(scene, ob, name, from_mix);
+ return insert_meshkey(ob, name, from_mix);
case OB_CURVE:
case OB_SURF:
- return insert_curvekey(scene, ob, name, from_mix);
+ return insert_curvekey(ob, name, from_mix);
case OB_LATTICE:
- return insert_lattkey(scene, ob, name, from_mix);
+ return insert_lattkey(ob, name, from_mix);
default:
return NULL;
}
}
+bool BKE_object_shapekey_free(Main *bmain, Object *ob)
+{
+ Key **key_p, *key;
+
+ key_p = BKE_key_from_object_p(ob);
+ if (ELEM(NULL, key_p, *key_p)) {
+ return false;
+ }
+
+ key = *key_p;
+ *key_p = NULL;
+
+ BKE_libblock_free_us(bmain, key);
+
+ return false;
+}
+
+bool BKE_object_shapekey_remove(Main *bmain, Object *ob, KeyBlock *kb)
+{
+ KeyBlock *rkb;
+ Key *key = BKE_key_from_object(ob);
+ short kb_index;
+
+ if (key == NULL) {
+ return false;
+ }
+
+ kb_index = BLI_findindex(&key->block, kb);
+ BLI_assert(kb_index != -1);
+
+ for (rkb = key->block.first; rkb; rkb = rkb->next) {
+ if (rkb->relative == kb_index) {
+ /* remap to the 'Basis' */
+ rkb->relative = 0;
+ }
+ else if (rkb->relative >= kb_index) {
+ /* Fix positional shift of the keys when kb is deleted from the list */
+ rkb->relative -= 1;
+ }
+ }
+
+ BLI_remlink(&key->block, kb);
+ key->totkey--;
+ if (key->refkey == kb) {
+ key->refkey = key->block.first;
+
+ if (key->refkey) {
+ /* apply new basis key on original data */
+ switch (ob->type) {
+ case OB_MESH:
+ BKE_keyblock_convert_to_mesh(key->refkey, ob->data);
+ break;
+ case OB_CURVE:
+ case OB_SURF:
+ BKE_keyblock_convert_to_curve(key->refkey, ob->data, BKE_curve_nurbs_get(ob->data));
+ break;
+ case OB_LATTICE:
+ BKE_keyblock_convert_to_lattice(key->refkey, ob->data);
+ break;
+ }
+ }
+ }
+
+ if (kb->data) {
+ MEM_freeN(kb->data);
+ }
+ MEM_freeN(kb);
+
+ if (ob->shapenr > 1) {
+ ob->shapenr--;
+ }
+
+ if (key->totkey == 0) {
+ BKE_object_shapekey_free(bmain, ob);
+ }
+
+ return true;
+}
+
+bool BKE_object_flag_test_recursive(const Object *ob, short flag)
+{
+ if (ob->flag & flag) {
+ return true;
+ }
+ else if (ob->parent) {
+ return BKE_object_flag_test_recursive(ob->parent, flag);
+ }
+ else {
+ return false;
+ }
+}
+
bool BKE_object_is_child_recursive(Object *ob_parent, Object *ob_child)
{
for (ob_child = ob_child->parent; ob_child; ob_child = ob_child->parent) {
@@ -3464,6 +3580,88 @@ int BKE_object_is_modified(Scene *scene, Object *ob)
return flag;
}
+/* Check of objects moves in time. */
+/* NOTE: This function is currently optimized for usage in combination
+ * with mti->canDeform, so modifiers can quickly check if their target
+ * objects moves (causing deformation motion blur) or not.
+ *
+ * This makes it possible to give some degree of false-positives here,
+ * but it's currently an acceptable tradeoff between complexity and check
+ * speed. In combination with checks of modifier stack and real life usage
+ * percentage of false-positives shouldn't be that hight.
+ */
+static bool object_moves_in_time(Object *object)
+{
+ AnimData *adt = object->adt;
+ if (adt != NULL) {
+ /* If object has any sort of animation data assume it is moving. */
+ if (adt->action != NULL ||
+ !BLI_listbase_is_empty(&adt->nla_tracks) ||
+ !BLI_listbase_is_empty(&adt->drivers) ||
+ !BLI_listbase_is_empty(&adt->overrides))
+ {
+ return true;
+ }
+ }
+ if (!BLI_listbase_is_empty(&object->constraints)) {
+ return true;
+ }
+ if (object->parent != NULL) {
+ /* TODO(sergey): Do recursive check here? */
+ return true;
+ }
+ return false;
+}
+
+static bool constructive_modifier_is_deform_modified(ModifierData *md)
+{
+ /* TODO(sergey): Consider generalizing this a bit so all modifier logic
+ * is concentrated in MOD_{modifier}.c file,
+ */
+ if (md->type == eModifierType_Array) {
+ ArrayModifierData *amd = (ArrayModifierData *)md;
+ /* TODO(sergey): Check if curve is deformed. */
+ return (amd->start_cap != NULL && object_moves_in_time(amd->start_cap)) ||
+ (amd->end_cap != NULL && object_moves_in_time(amd->end_cap)) ||
+ (amd->curve_ob != NULL && object_moves_in_time(amd->curve_ob)) ||
+ (amd->offset_ob != NULL && object_moves_in_time(amd->offset_ob));
+ }
+ else if (md->type == eModifierType_Mirror) {
+ MirrorModifierData *mmd = (MirrorModifierData *)md;
+ return mmd->mirror_ob != NULL && object_moves_in_time(mmd->mirror_ob);
+ }
+ else if (md->type == eModifierType_Screw) {
+ ScrewModifierData *smd = (ScrewModifierData *)md;
+ return smd->ob_axis != NULL && object_moves_in_time(smd->ob_axis);
+ }
+ return false;
+}
+
+static bool modifiers_has_animation_check(Object *ob)
+{
+ /* TODO(sergey): This is a bit code duplication with depsgraph, but
+ * would be nicer to solve this as a part of new dependency graph
+ * work, so we avoid conflicts and so.
+ */
+ if (ob->adt != NULL) {
+ AnimData *adt = ob->adt;
+ FCurve *fcu;
+ if (adt->action != NULL) {
+ for (fcu = adt->action->curves.first; fcu; fcu = fcu->next) {
+ if (fcu->rna_path && strstr(fcu->rna_path, "modifiers[")) {
+ return true;
+ }
+ }
+ }
+ for (fcu = adt->drivers.first; fcu; fcu = fcu->next) {
+ if (fcu->rna_path && strstr(fcu->rna_path, "modifiers[")) {
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
/* test if object is affected by deforming modifiers (for motion blur). again
* most important is to avoid false positives, this is to skip computations
* and we can still if there was actual deformation afterwards */
@@ -3472,6 +3670,7 @@ int BKE_object_is_deform_modified(Scene *scene, Object *ob)
ModifierData *md;
VirtualModifierData virtualModifierData;
int flag = 0;
+ const bool is_modifier_animated = modifiers_has_animation_check(ob);
if (BKE_key_from_object(ob))
flag |= eModifierMode_Realtime | eModifierMode_Render;
@@ -3481,9 +3680,15 @@ int BKE_object_is_deform_modified(Scene *scene, Object *ob)
md && (flag != (eModifierMode_Render | eModifierMode_Realtime));
md = md->next)
{
- ModifierTypeInfo *mti = modifierType_getInfo(md->type);
+ const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
+ bool can_deform = mti->type == eModifierTypeType_OnlyDeform ||
+ is_modifier_animated;
- if (mti->type == eModifierTypeType_OnlyDeform) {
+ if (!can_deform) {
+ can_deform = constructive_modifier_is_deform_modified(md);
+ }
+
+ if (can_deform) {
if (!(flag & eModifierMode_Render) && modifier_isEnabled(scene, md, eModifierMode_Render))
flag |= eModifierMode_Render;
@@ -3532,7 +3737,7 @@ void BKE_object_relink(Object *ob)
modifiers_foreachIDLink(ob, copy_object__forwardModifierLinks, NULL);
if (ob->adt)
- BKE_relink_animdata(ob->adt);
+ BKE_animdata_relink(ob->adt);
if (ob->rigidbody_constraint)
BKE_rigidbody_relink_constraint(ob->rigidbody_constraint);
@@ -3845,3 +4050,50 @@ KDTree *BKE_object_as_kdtree(Object *ob, int *r_tot)
*r_tot = tot;
return tree;
}
+
+bool BKE_object_modifier_use_time(Object *ob, ModifierData *md)
+{
+ if (modifier_dependsOnTime(md)) {
+ return true;
+ }
+
+ /* Check whether modifier is animated. */
+ /* TODO: this should be handled as part of build_animdata() -- Aligorith */
+ if (ob->adt) {
+ AnimData *adt = ob->adt;
+ FCurve *fcu;
+
+ char pattern[MAX_NAME + 16];
+ BLI_snprintf(pattern, sizeof(pattern), "modifiers[\"%s\"]", md->name);
+
+ /* action - check for F-Curves with paths containing 'modifiers[' */
+ if (adt->action) {
+ for (fcu = (FCurve *)adt->action->curves.first;
+ fcu != NULL;
+ fcu = (FCurve *)fcu->next)
+ {
+ if (fcu->rna_path && strstr(fcu->rna_path, pattern))
+ return true;
+ }
+ }
+
+ /* This here allows modifier properties to get driven and still update properly
+ *
+ * Workaround to get [#26764] (e.g. subsurf levels not updating when animated/driven)
+ * working, without the updating problems ([#28525] [#28690] [#28774] [#28777]) caused
+ * by the RNA updates cache introduced in r.38649
+ */
+ for (fcu = (FCurve *)adt->drivers.first;
+ fcu != NULL;
+ fcu = (FCurve *)fcu->next)
+ {
+ if (fcu->rna_path && strstr(fcu->rna_path, pattern))
+ return true;
+ }
+
+ /* XXX: also, should check NLA strips, though for now assume that nobody uses
+ * that and we can omit that for performance reasons... */
+ }
+
+ return false;
+}
diff --git a/source/blender/blenkernel/intern/object_deform.c b/source/blender/blenkernel/intern/object_deform.c
index e53bd26b9a2..e823f87468d 100644
--- a/source/blender/blenkernel/intern/object_deform.c
+++ b/source/blender/blenkernel/intern/object_deform.c
@@ -27,18 +27,455 @@
#include "MEM_guardedalloc.h"
+#include "BLT_translation.h"
+
#include "BLI_utildefines.h"
#include "BLI_ghash.h"
#include "BLI_listbase.h"
+#include "DNA_armature_types.h"
+#include "DNA_cloth_types.h"
+#include "DNA_curve_types.h"
+#include "DNA_lattice_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_modifier_types.h"
+#include "DNA_object_types.h"
+#include "DNA_object_force.h"
+#include "DNA_particle_types.h"
+#include "DNA_scene_types.h"
+
#include "BKE_action.h"
+#include "BKE_deform.h"
+#include "BKE_editmesh.h"
#include "BKE_object_deform.h" /* own include */
#include "BKE_object.h"
#include "BKE_modifier.h"
-#include "DNA_armature_types.h"
-#include "DNA_modifier_types.h"
-#include "DNA_object_types.h"
+/** \name Misc helpers
+ * \{ */
+
+static Lattice *object_defgroup_lattice_get(ID *id)
+{
+ Lattice *lt = (Lattice *)id;
+ BLI_assert(GS(id->name) == ID_LT);
+ return (lt->editlatt) ? lt->editlatt->latt : lt;
+}
+
+/**
+ * Update users of vgroups from this object, according to given map.
+ *
+ * Use it when you remove or reorder vgroups in the object.
+ *
+ * \param map an array mapping old indices to new indices.
+ */
+void BKE_object_defgroup_remap_update_users(Object *ob, int *map)
+{
+ ModifierData *md;
+ ParticleSystem *psys;
+ int a;
+
+ /* these cases don't use names to refer to vertex groups, so when
+ * they get removed the numbers get out of sync, this corrects that */
+
+ if (ob->soft) {
+ ob->soft->vertgroup = map[ob->soft->vertgroup];
+ }
+
+ for (md = ob->modifiers.first; md; md = md->next) {
+ if (md->type == eModifierType_Explode) {
+ ExplodeModifierData *emd = (ExplodeModifierData *)md;
+ emd->vgroup = map[emd->vgroup];
+ }
+ else if (md->type == eModifierType_Cloth) {
+ ClothModifierData *clmd = (ClothModifierData *)md;
+ ClothSimSettings *clsim = clmd->sim_parms;
+
+ if (clsim) {
+ clsim->vgroup_mass = map[clsim->vgroup_mass];
+ clsim->vgroup_bend = map[clsim->vgroup_bend];
+ clsim->vgroup_struct = map[clsim->vgroup_struct];
+ }
+ }
+ }
+
+ for (psys = ob->particlesystem.first; psys; psys = psys->next) {
+ for (a = 0; a < PSYS_TOT_VG; a++) {
+ psys->vgroup[a] = map[psys->vgroup[a]];
+ }
+ }
+}
+/** \} */
+
+
+/** \name Group creation
+ * \{ */
+
+/**
+ * Add a vgroup of given name to object. *Does not* handle MDeformVert data at all!
+ */
+bDeformGroup *BKE_object_defgroup_add_name(Object *ob, const char *name)
+{
+ bDeformGroup *defgroup;
+
+ if (!ob || !OB_TYPE_SUPPORT_VGROUP(ob->type))
+ return NULL;
+
+ defgroup = BKE_defgroup_new(ob, name);
+
+ ob->actdef = BLI_listbase_count(&ob->defbase);
+
+ return defgroup;
+}
+
+/**
+ * Add a vgroup of default name to object. *Does not* handle MDeformVert data at all!
+ */
+bDeformGroup *BKE_object_defgroup_add(Object *ob)
+{
+ return BKE_object_defgroup_add_name(ob, DATA_("Group"));
+}
+
+/**
+ * Create MDeformVert data for given ID. Work in Object mode only.
+ */
+MDeformVert *BKE_object_defgroup_data_create(ID *id)
+{
+ if (GS(id->name) == ID_ME) {
+ Mesh *me = (Mesh *)id;
+ me->dvert = CustomData_add_layer(&me->vdata, CD_MDEFORMVERT, CD_CALLOC, NULL, me->totvert);
+ return me->dvert;
+ }
+ else if (GS(id->name) == ID_LT) {
+ Lattice *lt = (Lattice *)id;
+ lt->dvert = MEM_callocN(sizeof(MDeformVert) * lt->pntsu * lt->pntsv * lt->pntsw, "lattice deformVert");
+ return lt->dvert;
+ }
+
+ return NULL;
+}
+/** \} */
+
+
+/** \name Group clearing
+ * \{ */
+
+/**
+ * Remove all verts (or only selected ones) from given vgroup. Work in Object and Edit modes.
+ *
+ * \param use_selection: Only operate on selection.
+ * \return True if any vertex was removed, false otherwise.
+ */
+bool BKE_object_defgroup_clear(Object *ob, bDeformGroup *dg, const bool use_selection)
+{
+ MDeformVert *dv;
+ const int def_nr = BLI_findindex(&ob->defbase, dg);
+ bool changed = false;
+
+ if (ob->type == OB_MESH) {
+ Mesh *me = ob->data;
+
+ if (me->edit_btmesh) {
+ BMEditMesh *em = me->edit_btmesh;
+ const int cd_dvert_offset = CustomData_get_offset(&em->bm->vdata, CD_MDEFORMVERT);
+
+ if (cd_dvert_offset != -1) {
+ BMVert *eve;
+ BMIter iter;
+
+ BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
+ dv = BM_ELEM_CD_GET_VOID_P(eve, cd_dvert_offset);
+
+ if (dv && dv->dw && (!use_selection || BM_elem_flag_test(eve, BM_ELEM_SELECT))) {
+ MDeformWeight *dw = defvert_find_index(dv, def_nr);
+ defvert_remove_group(dv, dw); /* dw can be NULL */
+ changed = true;
+ }
+ }
+ }
+ }
+ else {
+ if (me->dvert) {
+ MVert *mv;
+ int i;
+
+ mv = me->mvert;
+ dv = me->dvert;
+
+ for (i = 0; i < me->totvert; i++, mv++, dv++) {
+ if (dv->dw && (!use_selection || (mv->flag & SELECT))) {
+ MDeformWeight *dw = defvert_find_index(dv, def_nr);
+ defvert_remove_group(dv, dw); /* dw can be NULL */
+ changed = true;
+ }
+ }
+ }
+ }
+ }
+ else if (ob->type == OB_LATTICE) {
+ Lattice *lt = object_defgroup_lattice_get((ID *)(ob->data));
+
+ if (lt->dvert) {
+ BPoint *bp;
+ int i, tot = lt->pntsu * lt->pntsv * lt->pntsw;
+
+ for (i = 0, bp = lt->def; i < tot; i++, bp++) {
+ if (!use_selection || (bp->f1 & SELECT)) {
+ MDeformWeight *dw;
+
+ dv = &lt->dvert[i];
+
+ dw = defvert_find_index(dv, def_nr);
+ defvert_remove_group(dv, dw); /* dw can be NULL */
+ changed = true;
+ }
+ }
+ }
+ }
+
+ return changed;
+}
+
+/**
+ * Remove all verts (or only selected ones) from all vgroups. Work in Object and Edit modes.
+ *
+ * \param use_selection: Only operate on selection.
+ * \return True if any vertex was removed, false otherwise.
+ */
+bool BKE_object_defgroup_clear_all(Object *ob, const bool use_selection)
+{
+ bDeformGroup *dg;
+ bool changed = false;
+
+ for (dg = ob->defbase.first; dg; dg = dg->next) {
+ if (BKE_object_defgroup_clear(ob, dg, use_selection)) {
+ changed = true;
+ }
+ }
+
+ return changed;
+}
+/** \} */
+
+
+/** \name Group removal
+ * \{ */
+
+static void object_defgroup_remove_update_users(Object *ob, const int idx)
+{
+ int i, defbase_tot = BLI_listbase_count(&ob->defbase) + 1;
+ int *map = MEM_mallocN(sizeof(int) * defbase_tot, "vgroup del");
+
+ map[idx] = map[0] = 0;
+ for (i = 1; i < idx; i++) {
+ map[i] = i;
+ }
+ for (i = idx + 1; i < defbase_tot; i++) {
+ map[i] = i - 1;
+ }
+
+ BKE_object_defgroup_remap_update_users(ob, map);
+ MEM_freeN(map);
+}
+
+static void object_defgroup_remove_common(Object *ob, bDeformGroup *dg, const int def_nr)
+{
+ object_defgroup_remove_update_users(ob, def_nr + 1);
+
+ /* Remove the group */
+ BLI_freelinkN(&ob->defbase, dg);
+
+ /* Update the active deform index if necessary */
+ if (ob->actdef > def_nr)
+ ob->actdef--;
+
+ /* remove all dverts */
+ if (BLI_listbase_is_empty(&ob->defbase)) {
+ if (ob->type == OB_MESH) {
+ Mesh *me = ob->data;
+ CustomData_free_layer_active(&me->vdata, CD_MDEFORMVERT, me->totvert);
+ me->dvert = NULL;
+ }
+ else if (ob->type == OB_LATTICE) {
+ Lattice *lt = object_defgroup_lattice_get((ID *)(ob->data));
+ if (lt->dvert) {
+ MEM_freeN(lt->dvert);
+ lt->dvert = NULL;
+ }
+ }
+ }
+ else if (ob->actdef < 1) { /* Keep a valid active index if we still have some vgroups. */
+ ob->actdef = 1;
+ }
+}
+
+static void object_defgroup_remove_object_mode(Object *ob, bDeformGroup *dg)
+{
+ MDeformVert *dvert_array = NULL;
+ int dvert_tot = 0;
+ const int def_nr = BLI_findindex(&ob->defbase, dg);
+
+ BLI_assert(def_nr != -1);
+
+ BKE_object_defgroup_array_get(ob->data, &dvert_array, &dvert_tot);
+
+ if (dvert_array) {
+ int i, j;
+ MDeformVert *dv;
+ for (i = 0, dv = dvert_array; i < dvert_tot; i++, dv++) {
+ MDeformWeight *dw;
+
+ dw = defvert_find_index(dv, def_nr);
+ defvert_remove_group(dv, dw); /* dw can be NULL */
+
+ /* inline, make into a function if anything else needs to do this */
+ for (j = 0; j < dv->totweight; j++) {
+ if (dv->dw[j].def_nr > def_nr) {
+ dv->dw[j].def_nr--;
+ }
+ }
+ /* done */
+ }
+ }
+
+ object_defgroup_remove_common(ob, dg, def_nr);
+}
+
+static void object_defgroup_remove_edit_mode(Object *ob, bDeformGroup *dg)
+{
+ int i;
+ const int def_nr = BLI_findindex(&ob->defbase, dg);
+
+ BLI_assert(def_nr != -1);
+
+ /* Make sure that no verts are using this group - if none were removed, we can skip next per-vert update. */
+ if (!BKE_object_defgroup_clear(ob, dg, false)) {
+ /* Nothing to do. */
+ }
+ /* Else, make sure that any groups with higher indices are adjusted accordingly */
+ else if (ob->type == OB_MESH) {
+ Mesh *me = ob->data;
+ BMEditMesh *em = me->edit_btmesh;
+ const int cd_dvert_offset = CustomData_get_offset(&em->bm->vdata, CD_MDEFORMVERT);
+
+ BMIter iter;
+ BMVert *eve;
+ MDeformVert *dvert;
+
+ BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
+ dvert = BM_ELEM_CD_GET_VOID_P(eve, cd_dvert_offset);
+
+ if (dvert) {
+ for (i = 0; i < dvert->totweight; i++) {
+ if (dvert->dw[i].def_nr > def_nr) {
+ dvert->dw[i].def_nr--;
+ }
+ }
+ }
+ }
+ }
+ else if (ob->type == OB_LATTICE) {
+ Lattice *lt = ((Lattice *)(ob->data))->editlatt->latt;
+ BPoint *bp;
+ MDeformVert *dvert = lt->dvert;
+ int a, tot;
+
+ if (dvert) {
+ tot = lt->pntsu * lt->pntsv * lt->pntsw;
+ for (a = 0, bp = lt->def; a < tot; a++, bp++, dvert++) {
+ for (i = 0; i < dvert->totweight; i++) {
+ if (dvert->dw[i].def_nr > def_nr) {
+ dvert->dw[i].def_nr--;
+ }
+ }
+ }
+ }
+ }
+
+ object_defgroup_remove_common(ob, dg, def_nr);
+}
+
+/**
+ * Remove given vgroup from object. Work in Object and Edit modes.
+ */
+void BKE_object_defgroup_remove(Object *ob, bDeformGroup *defgroup)
+{
+ if (BKE_object_is_in_editmode_vgroup(ob))
+ object_defgroup_remove_edit_mode(ob, defgroup);
+ else
+ object_defgroup_remove_object_mode(ob, defgroup);
+}
+
+/**
+ * Remove all vgroups from object. Work in Object and Edit modes.
+ */
+void BKE_object_defgroup_remove_all(Object *ob)
+{
+ bDeformGroup *dg = (bDeformGroup *)ob->defbase.first;
+ const bool edit_mode = BKE_object_is_in_editmode_vgroup(ob);
+
+ if (dg) {
+ while (dg) {
+ bDeformGroup *next_dg = dg->next;
+
+ if (edit_mode)
+ object_defgroup_remove_edit_mode(ob, dg);
+ else
+ object_defgroup_remove_object_mode(ob, dg);
+
+ dg = next_dg;
+ }
+ }
+ else { /* ob->defbase is empty... */
+ /* remove all dverts */
+ if (ob->type == OB_MESH) {
+ Mesh *me = ob->data;
+ CustomData_free_layer_active(&me->vdata, CD_MDEFORMVERT, me->totvert);
+ me->dvert = NULL;
+ }
+ else if (ob->type == OB_LATTICE) {
+ Lattice *lt = object_defgroup_lattice_get((ID *)(ob->data));
+ if (lt->dvert) {
+ MEM_freeN(lt->dvert);
+ lt->dvert = NULL;
+ }
+ }
+ /* Fix counters/indices */
+ ob->actdef = 0;
+ }
+}
+
+/**
+ * Get MDeformVert vgroup data from given object. Should only be used in Object mode.
+ *
+ * \return True if the id type supports weights.
+ */
+bool BKE_object_defgroup_array_get(ID *id, MDeformVert **dvert_arr, int *dvert_tot)
+{
+ if (id) {
+ switch (GS(id->name)) {
+ case ID_ME:
+ {
+ Mesh *me = (Mesh *)id;
+ *dvert_arr = me->dvert;
+ *dvert_tot = me->totvert;
+ return true;
+ }
+ case ID_LT:
+ {
+ Lattice *lt = object_defgroup_lattice_get(id);
+ *dvert_arr = lt->dvert;
+ *dvert_tot = lt->pntsu * lt->pntsv * lt->pntsw;
+ return true;
+ }
+ }
+ }
+
+ *dvert_arr = NULL;
+ *dvert_tot = 0;
+ return false;
+}
+/** \} */
/* --- functions for getting vgroup aligned maps --- */
@@ -46,11 +483,11 @@
* gets the status of "flag" for each bDeformGroup
* in ob->defbase and returns an array containing them
*/
-bool *BKE_objdef_lock_flags_get(Object *ob, const int defbase_tot)
+bool *BKE_object_defgroup_lock_flags_get(Object *ob, const int defbase_tot)
{
bool is_locked = false;
int i;
- //int defbase_tot = BLI_countlist(&ob->defbase);
+ //int defbase_tot = BLI_listbase_count(&ob->defbase);
bool *lock_flags = MEM_mallocN(defbase_tot * sizeof(bool), "defflags");
bDeformGroup *defgroup;
@@ -66,21 +503,21 @@ bool *BKE_objdef_lock_flags_get(Object *ob, const int defbase_tot)
return NULL;
}
-bool *BKE_objdef_validmap_get(Object *ob, const int defbase_tot)
+bool *BKE_object_defgroup_validmap_get(Object *ob, const int defbase_tot)
{
bDeformGroup *dg;
ModifierData *md;
- bool *vgroup_validmap;
+ bool *defgroup_validmap;
GHash *gh;
int i, step1 = 1;
- //int defbase_tot = BLI_countlist(&ob->defbase);
+ //int defbase_tot = BLI_listbase_count(&ob->defbase);
VirtualModifierData virtualModifierData;
if (BLI_listbase_is_empty(&ob->defbase)) {
return NULL;
}
- gh = BLI_ghash_str_new_ex("BKE_objdef_validmap_get gh", defbase_tot);
+ gh = BLI_ghash_str_new_ex(__func__, defbase_tot);
/* add all names to a hash table */
for (dg = ob->defbase.first; dg; dg = dg->next) {
@@ -115,23 +552,23 @@ bool *BKE_objdef_validmap_get(Object *ob, const int defbase_tot)
}
}
- vgroup_validmap = MEM_mallocN(sizeof(*vgroup_validmap) * defbase_tot, "wpaint valid map");
+ defgroup_validmap = MEM_mallocN(sizeof(*defgroup_validmap) * defbase_tot, "wpaint valid map");
/* add all names to a hash table */
for (dg = ob->defbase.first, i = 0; dg; dg = dg->next, i++) {
- vgroup_validmap[i] = (BLI_ghash_lookup(gh, dg->name) != NULL);
+ defgroup_validmap[i] = (BLI_ghash_lookup(gh, dg->name) != NULL);
}
BLI_assert(i == BLI_ghash_size(gh));
BLI_ghash_free(gh, NULL, NULL);
- return vgroup_validmap;
+ return defgroup_validmap;
}
/* Returns total selected vgroups,
* wpi.defbase_sel is assumed malloc'd, all values are set */
-bool *BKE_objdef_selected_get(Object *ob, int defbase_tot, int *r_dg_flags_sel_tot)
+bool *BKE_object_defgroup_selected_get(Object *ob, int defbase_tot, int *r_dg_flags_sel_tot)
{
bool *dg_selection = MEM_mallocN(defbase_tot * sizeof(bool), __func__);
bDeformGroup *defgroup;
@@ -158,3 +595,86 @@ bool *BKE_objdef_selected_get(Object *ob, int defbase_tot, int *r_dg_flags_sel_t
return dg_selection;
}
+
+
+/**
+ * Return the subset type of the Vertex Group Selection
+ */
+bool *BKE_object_defgroup_subset_from_select_type(
+ Object *ob, eVGroupSelect subset_type, int *r_defgroup_tot, int *r_subset_count)
+{
+ bool *defgroup_validmap = NULL;
+ *r_defgroup_tot = BLI_listbase_count(&ob->defbase);
+
+ switch (subset_type) {
+ case WT_VGROUP_ACTIVE:
+ {
+ const int def_nr_active = ob->actdef - 1;
+ defgroup_validmap = MEM_mallocN(*r_defgroup_tot * sizeof(*defgroup_validmap), __func__);
+ memset(defgroup_validmap, false, *r_defgroup_tot * sizeof(*defgroup_validmap));
+ if ((def_nr_active >= 0) && (def_nr_active < *r_defgroup_tot)) {
+ *r_subset_count = 1;
+ defgroup_validmap[def_nr_active] = true;
+ }
+ else {
+ *r_subset_count = 0;
+ }
+ break;
+ }
+ case WT_VGROUP_BONE_SELECT:
+ {
+ defgroup_validmap = BKE_object_defgroup_selected_get(ob, *r_defgroup_tot, r_subset_count);
+ break;
+ }
+ case WT_VGROUP_BONE_DEFORM:
+ {
+ int i;
+ defgroup_validmap = BKE_object_defgroup_validmap_get(ob, *r_defgroup_tot);
+ *r_subset_count = 0;
+ for (i = 0; i < *r_defgroup_tot; i++) {
+ if (defgroup_validmap[i] == true) {
+ *r_subset_count += 1;
+ }
+ }
+ break;
+ }
+ case WT_VGROUP_BONE_DEFORM_OFF:
+ {
+ int i;
+ defgroup_validmap = BKE_object_defgroup_validmap_get(ob, *r_defgroup_tot);
+ *r_subset_count = 0;
+ for (i = 0; i < *r_defgroup_tot; i++) {
+ defgroup_validmap[i] = !defgroup_validmap[i];
+ if (defgroup_validmap[i] == true) {
+ *r_subset_count += 1;
+ }
+ }
+ break;
+ }
+ case WT_VGROUP_ALL:
+ default:
+ {
+ defgroup_validmap = MEM_mallocN(*r_defgroup_tot * sizeof(*defgroup_validmap), __func__);
+ memset(defgroup_validmap, true, *r_defgroup_tot * sizeof(*defgroup_validmap));
+ *r_subset_count = *r_defgroup_tot;
+ break;
+ }
+ }
+
+ return defgroup_validmap;
+}
+
+/**
+ * store indices from the defgroup_validmap (faster lookups in some cases)
+ */
+void BKE_object_defgroup_subset_to_index_array(
+ const bool *defgroup_validmap, const int defgroup_tot, int *r_defgroup_subset_map)
+{
+ int i, j = 0;
+ for (i = 0; i < defgroup_tot; i++) {
+ if (defgroup_validmap[i]) {
+ r_defgroup_subset_map[j++] = i;
+ }
+ }
+}
+
diff --git a/source/blender/blenkernel/intern/object_dupli.c b/source/blender/blenkernel/intern/object_dupli.c
index 0d82c6e89a1..8abe4bdbb97 100644
--- a/source/blender/blenkernel/intern/object_dupli.c
+++ b/source/blender/blenkernel/intern/object_dupli.c
@@ -969,9 +969,9 @@ static void make_duplis_particle_system(const DupliContext *ctx, ParticleSystem
}
/* some hair paths might be non-existent so they can't be used for duplication */
- if (hair &&
- ((a < totpart && psys->pathcache[a]->steps < 0) ||
- (a >= totpart && psys->childcache[a - totpart]->steps < 0)))
+ if (hair && psys->pathcache &&
+ ((a < totpart && psys->pathcache[a]->segments < 0) ||
+ (a >= totpart && psys->childcache[a - totpart]->segments < 0)))
{
continue;
}
@@ -1237,10 +1237,10 @@ int count_duplilist(Object *ob)
return 1;
}
-DupliApplyData *duplilist_apply(Object *ob, ListBase *duplilist)
+DupliApplyData *duplilist_apply(Object *ob, Scene *scene, ListBase *duplilist)
{
DupliApplyData *apply_data = NULL;
- int num_objects = BLI_countlist(duplilist);
+ int num_objects = BLI_listbase_count(duplilist);
if (num_objects > 0) {
DupliObject *dob;
@@ -1253,6 +1253,13 @@ DupliApplyData *duplilist_apply(Object *ob, ListBase *duplilist)
for (dob = duplilist->first, i = 0; dob; dob = dob->next, ++i) {
/* copy obmat from duplis */
copy_m4_m4(apply_data->extra[i].obmat, dob->ob->obmat);
+
+ /* make sure derivedmesh is calculated once, before drawing */
+ if (scene && !(dob->ob->transflag & OB_DUPLICALCDERIVED) && dob->ob->type == OB_MESH) {
+ mesh_get_derived_final(scene, dob->ob, scene->customdata_mask);
+ dob->ob->transflag |= OB_DUPLICALCDERIVED;
+ }
+
copy_m4_m4(dob->ob->obmat, dob->mat);
/* copy layers from the main duplicator object */
@@ -1273,6 +1280,7 @@ void duplilist_restore(ListBase *duplilist, DupliApplyData *apply_data)
*/
for (dob = duplilist->last, i = apply_data->num_objects - 1; dob; dob = dob->prev, --i) {
copy_m4_m4(dob->ob->obmat, apply_data->extra[i].obmat);
+ dob->ob->transflag &= ~OB_DUPLICALCDERIVED;
dob->ob->lay = apply_data->extra[i].lay;
}
diff --git a/source/blender/blenkernel/intern/object_update.c b/source/blender/blenkernel/intern/object_update.c
new file mode 100644
index 00000000000..03348adeabc
--- /dev/null
+++ b/source/blender/blenkernel/intern/object_update.c
@@ -0,0 +1,349 @@
+/*
+ * ***** 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) 20014 by Blender Foundation.
+ * All rights reserved.
+ *
+ * Contributor(s): Sergey Sharybin.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/blenkernel/intern/object_update.c
+ * \ingroup bke
+ */
+
+#include "DNA_anim_types.h"
+#include "DNA_constraint_types.h"
+#include "DNA_group_types.h"
+#include "DNA_key_types.h"
+#include "DNA_material_types.h"
+#include "DNA_scene_types.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_utildefines.h"
+#include "BLI_math.h"
+#include "BLI_threads.h"
+
+#include "BKE_global.h"
+#include "BKE_armature.h"
+#include "BKE_action.h"
+#include "BKE_constraint.h"
+#include "BKE_depsgraph.h"
+#include "BKE_DerivedMesh.h"
+#include "BKE_animsys.h"
+#include "BKE_displist.h"
+#include "BKE_effect.h"
+#include "BKE_key.h"
+#include "BKE_lamp.h"
+#include "BKE_lattice.h"
+#include "BKE_editmesh.h"
+#include "BKE_object.h"
+#include "BKE_particle.h"
+#include "BKE_scene.h"
+#include "BKE_material.h"
+#include "BKE_image.h"
+
+#include "DEG_depsgraph.h"
+
+#ifdef WITH_LEGACY_DEPSGRAPH
+# define DEBUG_PRINT if (!DEG_depsgraph_use_legacy() && G.debug & G_DEBUG_DEPSGRAPH) printf
+#else
+# define DEBUG_PRINT if (G.debug & G_DEBUG_DEPSGRAPH) printf
+#endif
+
+static ThreadMutex material_lock = BLI_MUTEX_INITIALIZER;
+
+void BKE_object_eval_local_transform(EvaluationContext *UNUSED(eval_ctx),
+ Scene *UNUSED(scene),
+ Object *ob)
+{
+ DEBUG_PRINT("%s on %s\n", __func__, ob->id.name);
+
+ /* calculate local matrix */
+ BKE_object_to_mat4(ob, ob->obmat);
+}
+
+/* Evaluate parent */
+/* NOTE: based on solve_parenting(), but with the cruft stripped out */
+void BKE_object_eval_parent(EvaluationContext *UNUSED(eval_ctx),
+ Scene *scene,
+ Object *ob)
+{
+ Object *par = ob->parent;
+
+ float totmat[4][4];
+ float tmat[4][4];
+ float locmat[4][4];
+
+ DEBUG_PRINT("%s on %s\n", __func__, ob->id.name);
+
+ /* get local matrix (but don't calculate it, as that was done already!) */
+ // XXX: redundant?
+ copy_m4_m4(locmat, ob->obmat);
+
+ /* get parent effect matrix */
+ BKE_object_get_parent_matrix(scene, ob, par, totmat);
+
+ /* total */
+ mul_m4_m4m4(tmat, totmat, ob->parentinv);
+ mul_m4_m4m4(ob->obmat, tmat, locmat);
+
+ /* origin, for help line */
+ if ((ob->partype & PARTYPE) == PARSKEL) {
+ copy_v3_v3(ob->orig, par->obmat[3]);
+ }
+ else {
+ copy_v3_v3(ob->orig, totmat[3]);
+ }
+}
+
+void BKE_object_eval_constraints(EvaluationContext *UNUSED(eval_ctx),
+ Scene *scene,
+ Object *ob)
+{
+ bConstraintOb *cob;
+ float ctime = BKE_scene_frame_get(scene);
+
+ DEBUG_PRINT("%s on %s\n", __func__, ob->id.name);
+
+ /* evaluate constraints stack */
+ /* TODO: split this into:
+ * - pre (i.e. BKE_constraints_make_evalob, per-constraint (i.e.
+ * - inner body of BKE_constraints_solve),
+ * - post (i.e. BKE_constraints_clear_evalob)
+ *
+ * Not sure why, this is from Joshua - sergey
+ *
+ */
+ cob = BKE_constraints_make_evalob(scene, ob, NULL, CONSTRAINT_OBTYPE_OBJECT);
+ BKE_constraints_solve(&ob->constraints, cob, ctime);
+ BKE_constraints_clear_evalob(cob);
+}
+
+void BKE_object_eval_done(EvaluationContext *UNUSED(eval_ctx), Object *ob)
+{
+ DEBUG_PRINT("%s on %s\n", __func__, ob->id.name);
+
+ /* Set negative scale flag in object. */
+ if (is_negative_m4(ob->obmat)) ob->transflag |= OB_NEG_SCALE;
+ else ob->transflag &= ~OB_NEG_SCALE;
+}
+
+void BKE_object_eval_modifier(struct EvaluationContext *eval_ctx,
+ struct Scene *scene,
+ struct Object *ob,
+ struct ModifierData *md)
+{
+ DEBUG_PRINT("%s on %s\n", __func__, ob->id.name);
+ (void) eval_ctx; /* Ignored. */
+ (void) scene; /* Ignored. */
+ (void) ob; /* Ignored. */
+ (void) md; /* Ignored. */
+}
+
+void BKE_object_handle_data_update(EvaluationContext *eval_ctx,
+ Scene *scene,
+ Object *ob)
+{
+ ID *data_id = (ID *)ob->data;
+ AnimData *adt = BKE_animdata_from_id(data_id);
+ Key *key;
+ float ctime = BKE_scene_frame_get(scene);
+
+ if (G.debug & G_DEBUG_DEPSGRAPH)
+ printf("recalcdata %s\n", ob->id.name + 2);
+
+ /* TODO(sergey): Only used by legacy depsgraph. */
+ if (adt) {
+ /* evaluate drivers - datalevel */
+ /* XXX: for mesh types, should we push this to derivedmesh instead? */
+ BKE_animsys_evaluate_animdata(scene, data_id, adt, ctime, ADT_RECALC_DRIVERS);
+ }
+
+ /* TODO(sergey): Only used by legacy depsgraph. */
+ key = BKE_key_from_object(ob);
+ if (key && key->block.first) {
+ if (!(ob->shapeflag & OB_SHAPE_LOCK))
+ BKE_animsys_evaluate_animdata(scene, &key->id, key->adt, ctime, ADT_RECALC_DRIVERS);
+ }
+
+ /* includes all keys and modifiers */
+ switch (ob->type) {
+ case OB_MESH:
+ {
+ BMEditMesh *em = (ob == scene->obedit) ? BKE_editmesh_from_object(ob) : NULL;
+ uint64_t data_mask = scene->customdata_mask | CD_MASK_BAREMESH;
+#ifdef WITH_FREESTYLE
+ /* make sure Freestyle edge/face marks appear in DM for render (see T40315) */
+ if (eval_ctx->mode != DAG_EVAL_VIEWPORT) {
+ data_mask |= CD_MASK_FREESTYLE_EDGE | CD_MASK_FREESTYLE_FACE;
+ }
+#endif
+ if (em) {
+ makeDerivedMesh(scene, ob, em, data_mask, false); /* was CD_MASK_BAREMESH */
+ }
+ else {
+ makeDerivedMesh(scene, ob, NULL, data_mask, false);
+ }
+ break;
+ }
+ case OB_ARMATURE:
+ if (ob->id.lib && ob->proxy_from) {
+ if (BKE_pose_copy_result(ob->pose, ob->proxy_from->pose) == false) {
+ printf("Proxy copy error, lib Object: %s proxy Object: %s\n",
+ ob->id.name + 2, ob->proxy_from->id.name + 2);
+ }
+ }
+ else {
+ BKE_pose_where_is(scene, ob);
+ }
+ break;
+
+ case OB_MBALL:
+ BKE_displist_make_mball(eval_ctx, scene, ob);
+ break;
+
+ case OB_CURVE:
+ case OB_SURF:
+ case OB_FONT:
+ BKE_displist_make_curveTypes(scene, ob, 0);
+ break;
+
+ case OB_LATTICE:
+ BKE_lattice_modifiers_calc(scene, ob);
+ break;
+
+ case OB_EMPTY:
+ if (ob->empty_drawtype == OB_EMPTY_IMAGE && ob->data)
+ if (BKE_image_is_animated(ob->data))
+ BKE_image_user_check_frame_calc(ob->iuser, (int)ctime, 0);
+ break;
+ }
+
+ /* related materials */
+ /* XXX: without depsgraph tagging, this will always need to be run, which will be slow!
+ * However, not doing anything (or trying to hack around this lack) is not an option
+ * anymore, especially due to Cycles [#31834]
+ */
+ if (ob->totcol) {
+ int a;
+ if (ob->totcol != 0) {
+ BLI_mutex_lock(&material_lock);
+ for (a = 1; a <= ob->totcol; a++) {
+ Material *ma = give_current_material(ob, a);
+ if (ma) {
+ /* recursively update drivers for this material */
+ material_drivers_update(scene, ma, ctime);
+ }
+ }
+ BLI_mutex_unlock(&material_lock);
+ }
+ }
+ else if (ob->type == OB_LAMP)
+ lamp_drivers_update(scene, ob->data, ctime);
+
+ /* particles */
+ if (ob != scene->obedit && ob->particlesystem.first) {
+ ParticleSystem *tpsys, *psys;
+ DerivedMesh *dm;
+ ob->transflag &= ~OB_DUPLIPARTS;
+ psys = ob->particlesystem.first;
+ while (psys) {
+ /* ensure this update always happens even if psys is disabled */
+ if (psys->recalc & PSYS_RECALC_TYPE) {
+ psys_changed_type(ob, psys);
+ }
+
+ if (psys_check_enabled(ob, psys)) {
+ /* check use of dupli objects here */
+ if (psys->part && (psys->part->draw_as == PART_DRAW_REND || eval_ctx->mode == DAG_EVAL_RENDER) &&
+ ((psys->part->ren_as == PART_DRAW_OB && psys->part->dup_ob) ||
+ (psys->part->ren_as == PART_DRAW_GR && psys->part->dup_group)))
+ {
+ ob->transflag |= OB_DUPLIPARTS;
+ }
+
+ particle_system_update(scene, ob, psys);
+ psys = psys->next;
+ }
+ else if (psys->flag & PSYS_DELETE) {
+ tpsys = psys->next;
+ BLI_remlink(&ob->particlesystem, psys);
+ psys_free(ob, psys);
+ psys = tpsys;
+ }
+ else
+ psys = psys->next;
+ }
+
+ if (eval_ctx->mode == DAG_EVAL_RENDER && ob->transflag & OB_DUPLIPARTS) {
+ /* this is to make sure we get render level duplis in groups:
+ * the derivedmesh must be created before init_render_mesh,
+ * since object_duplilist does dupliparticles before that */
+ CustomDataMask data_mask = CD_MASK_BAREMESH | CD_MASK_MFACE | CD_MASK_MTFACE | CD_MASK_MCOL;
+ dm = mesh_create_derived_render(scene, ob, data_mask);
+ dm->release(dm);
+
+ for (psys = ob->particlesystem.first; psys; psys = psys->next)
+ psys_get_modifier(ob, psys)->flag &= ~eParticleSystemFlag_psys_updated;
+ }
+ }
+
+ /* quick cache removed */
+}
+
+void BKE_object_eval_uber_transform(EvaluationContext *UNUSED(eval_ctx),
+ Scene *UNUSED(scene),
+ Object *ob)
+{
+ /* TODO(sergey): Currently it's a duplicate of logic in BKE_object_handle_update_ex(). */
+ // XXX: it's almost redundant now...
+
+ /* Handle proxy copy for target, */
+ if (ob->id.lib && ob->proxy_from) {
+ if (ob->proxy_from->proxy_group) {
+ /* Transform proxy into group space. */
+ Object *obg = ob->proxy_from->proxy_group;
+ float imat[4][4];
+ invert_m4_m4(imat, obg->obmat);
+ mul_m4_m4m4(ob->obmat, imat, ob->proxy_from->obmat);
+ /* Should always be true. */
+ if (obg->dup_group) {
+ add_v3_v3(ob->obmat[3], obg->dup_group->dupli_ofs);
+ }
+ }
+ else
+ copy_m4_m4(ob->obmat, ob->proxy_from->obmat);
+ }
+
+ ob->recalc &= ~(OB_RECALC_OB | OB_RECALC_TIME);
+ if (ob->data == NULL) {
+ ob->recalc &= ~OB_RECALC_DATA;
+ }
+}
+
+void BKE_object_eval_uber_data(EvaluationContext *eval_ctx,
+ Scene *scene,
+ Object *ob)
+{
+ DEBUG_PRINT("%s on %s\n", __func__, ob->id.name);
+ BLI_assert(ob->type != OB_ARMATURE);
+ BKE_object_handle_data_update(eval_ctx, scene, ob);
+
+ ob->recalc &= ~(OB_RECALC_DATA | OB_RECALC_TIME);
+}
diff --git a/source/blender/blenkernel/intern/ocean.c b/source/blender/blenkernel/intern/ocean.c
index 373ad34e7bd..1a178fb2bdf 100644
--- a/source/blender/blenkernel/intern/ocean.c
+++ b/source/blender/blenkernel/intern/ocean.c
@@ -494,7 +494,7 @@ void BKE_ocean_eval_ij(struct Ocean *oc, struct OceanResult *ocr, int i, int j)
BLI_rw_mutex_unlock(&oc->oceanmutex);
}
-void BKE_simulate_ocean(struct Ocean *o, float t, float scale, float chop_amount)
+void BKE_ocean_simulate(struct Ocean *o, float t, float scale, float chop_amount)
{
int i, j;
@@ -732,14 +732,14 @@ static void set_height_normalize_factor(struct Ocean *oc)
oc->normalize_factor = 1.0;
- BKE_simulate_ocean(oc, 0.0, 1.0, 0);
+ BKE_ocean_simulate(oc, 0.0, 1.0, 0);
BLI_rw_mutex_lock(&oc->oceanmutex, THREAD_LOCK_READ);
for (i = 0; i < oc->_M; ++i) {
for (j = 0; j < oc->_N; ++j) {
- if (max_h < fabsf(oc->_disp_y[i * oc->_N + j])) {
- max_h = fabsf(oc->_disp_y[i * oc->_N + j]);
+ if (max_h < fabs(oc->_disp_y[i * oc->_N + j])) {
+ max_h = fabs(oc->_disp_y[i * oc->_N + j]);
}
}
}
@@ -754,7 +754,7 @@ static void set_height_normalize_factor(struct Ocean *oc)
oc->normalize_factor = res;
}
-struct Ocean *BKE_add_ocean(void)
+struct Ocean *BKE_ocean_add(void)
{
Ocean *oc = MEM_callocN(sizeof(Ocean), "ocean sim data");
@@ -763,7 +763,7 @@ struct Ocean *BKE_add_ocean(void)
return oc;
}
-void BKE_init_ocean(struct Ocean *o, int M, int N, float Lx, float Lz, float V, float l, float A, float w, float damp,
+void BKE_ocean_init(struct Ocean *o, int M, int N, float Lx, float Lz, float V, float l, float A, float w, float damp,
float alignment, float depth, float time, short do_height_field, short do_chop, short do_normals,
short do_jacobian, int seed)
{
@@ -900,7 +900,7 @@ void BKE_init_ocean(struct Ocean *o, int M, int N, float Lx, float Lz, float V,
BLI_rng_free(rng);
}
-void BKE_free_ocean_data(struct Ocean *oc)
+void BKE_ocean_free_data(struct Ocean *oc)
{
if (!oc) return;
@@ -962,11 +962,11 @@ void BKE_free_ocean_data(struct Ocean *oc)
BLI_rw_mutex_unlock(&oc->oceanmutex);
}
-void BKE_free_ocean(struct Ocean *oc)
+void BKE_ocean_free(struct Ocean *oc)
{
if (!oc) return;
- BKE_free_ocean_data(oc);
+ BKE_ocean_free_data(oc);
BLI_rw_mutex_end(&oc->oceanmutex);
MEM_freeN(oc);
@@ -1002,7 +1002,7 @@ static void cache_filename(char *string, const char *path, const char *relbase,
BLI_join_dirfile(cachepath, sizeof(cachepath), path, fname);
- BKE_makepicstring_from_type(string, cachepath, relbase, frame, R_IMF_IMTYPE_OPENEXR, true, true);
+ BKE_image_path_from_imtype(string, cachepath, relbase, frame, R_IMF_IMTYPE_OPENEXR, true, true, "");
}
/* silly functions but useful to inline when the args do a lot of indirections */
@@ -1021,7 +1021,7 @@ MINLINE void value_to_rgba_unit_alpha(float r_rgba[4], const float value)
r_rgba[3] = 1.0f;
}
-void BKE_free_ocean_cache(struct OceanCache *och)
+void BKE_ocean_free_cache(struct OceanCache *och)
{
int i, f = 0;
@@ -1111,7 +1111,7 @@ void BKE_ocean_cache_eval_ij(struct OceanCache *och, struct OceanResult *ocr, in
}
}
-struct OceanCache *BKE_init_ocean_cache(const char *bakepath, const char *relbase, int start, int end, float wave_scale,
+struct OceanCache *BKE_ocean_init_cache(const char *bakepath, const char *relbase, int start, int end, float wave_scale,
float chop_amount, float foam_coverage, float foam_fade, int resolution)
{
OceanCache *och = MEM_callocN(sizeof(OceanCache), "ocean cache data");
@@ -1138,7 +1138,7 @@ struct OceanCache *BKE_init_ocean_cache(const char *bakepath, const char *relbas
return och;
}
-void BKE_simulate_ocean_cache(struct OceanCache *och, int frame)
+void BKE_ocean_simulate_cache(struct OceanCache *och, int frame)
{
char string[FILE_MAX];
int f = frame;
@@ -1182,7 +1182,7 @@ void BKE_simulate_ocean_cache(struct OceanCache *och, int frame)
}
-void BKE_bake_ocean(struct Ocean *o, struct OceanCache *och, void (*update_cb)(void *, float progress, int *cancel),
+void BKE_ocean_bake(struct Ocean *o, struct OceanCache *och, void (*update_cb)(void *, float progress, int *cancel),
void *update_cb_data)
{
/* note: some of these values remain uninitialized unless certain options
@@ -1221,7 +1221,7 @@ void BKE_bake_ocean(struct Ocean *o, struct OceanCache *och, void (*update_cb)(v
ibuf_disp = IMB_allocImBuf(res_x, res_y, 32, IB_rectfloat);
ibuf_normal = IMB_allocImBuf(res_x, res_y, 32, IB_rectfloat);
- BKE_simulate_ocean(o, och->time[i], och->wave_scale, och->chop_amount);
+ BKE_ocean_simulate(o, och->time[i], och->wave_scale, och->chop_amount);
/* add new foam */
for (y = 0; y < res_y; y++) {
@@ -1371,29 +1371,29 @@ void BKE_ocean_eval_ij(struct Ocean *UNUSED(oc), struct OceanResult *UNUSED(ocr)
{
}
-void BKE_simulate_ocean(struct Ocean *UNUSED(o), float UNUSED(t), float UNUSED(scale), float UNUSED(chop_amount))
+void BKE_ocean_simulate(struct Ocean *UNUSED(o), float UNUSED(t), float UNUSED(scale), float UNUSED(chop_amount))
{
}
-struct Ocean *BKE_add_ocean(void)
+struct Ocean *BKE_ocean_add(void)
{
Ocean *oc = MEM_callocN(sizeof(Ocean), "ocean sim data");
return oc;
}
-void BKE_init_ocean(struct Ocean *UNUSED(o), int UNUSED(M), int UNUSED(N), float UNUSED(Lx), float UNUSED(Lz),
+void BKE_ocean_init(struct Ocean *UNUSED(o), int UNUSED(M), int UNUSED(N), float UNUSED(Lx), float UNUSED(Lz),
float UNUSED(V), float UNUSED(l), float UNUSED(A), float UNUSED(w), float UNUSED(damp),
float UNUSED(alignment), float UNUSED(depth), float UNUSED(time), short UNUSED(do_height_field),
short UNUSED(do_chop), short UNUSED(do_normals), short UNUSED(do_jacobian), int UNUSED(seed))
{
}
-void BKE_free_ocean_data(struct Ocean *UNUSED(oc))
+void BKE_ocean_free_data(struct Ocean *UNUSED(oc))
{
}
-void BKE_free_ocean(struct Ocean *oc)
+void BKE_ocean_free(struct Ocean *oc)
{
if (!oc) return;
MEM_freeN(oc);
@@ -1403,7 +1403,7 @@ void BKE_free_ocean(struct Ocean *oc)
/* ********* Baking/Caching ********* */
-void BKE_free_ocean_cache(struct OceanCache *och)
+void BKE_ocean_free_cache(struct OceanCache *och)
{
if (!och) return;
@@ -1420,7 +1420,7 @@ void BKE_ocean_cache_eval_ij(struct OceanCache *UNUSED(och), struct OceanResult
{
}
-OceanCache *BKE_init_ocean_cache(const char *UNUSED(bakepath), const char *UNUSED(relbase), int UNUSED(start),
+OceanCache *BKE_ocean_init_cache(const char *UNUSED(bakepath), const char *UNUSED(relbase), int UNUSED(start),
int UNUSED(end), float UNUSED(wave_scale), float UNUSED(chop_amount),
float UNUSED(foam_coverage), float UNUSED(foam_fade), int UNUSED(resolution))
{
@@ -1429,11 +1429,11 @@ OceanCache *BKE_init_ocean_cache(const char *UNUSED(bakepath), const char *UNUSE
return och;
}
-void BKE_simulate_ocean_cache(struct OceanCache *UNUSED(och), int UNUSED(frame))
+void BKE_ocean_simulate_cache(struct OceanCache *UNUSED(och), int UNUSED(frame))
{
}
-void BKE_bake_ocean(struct Ocean *UNUSED(o), struct OceanCache *UNUSED(och),
+void BKE_ocean_bake(struct Ocean *UNUSED(o), struct OceanCache *UNUSED(och),
void (*update_cb)(void *, float progress, int *cancel), void *UNUSED(update_cb_data))
{
/* unused */
diff --git a/source/blender/blenkernel/intern/treehash.c b/source/blender/blenkernel/intern/outliner_treehash.c
index 866502c4ae1..f31ba34a984 100644
--- a/source/blender/blenkernel/intern/treehash.c
+++ b/source/blender/blenkernel/intern/outliner_treehash.c
@@ -20,7 +20,7 @@
* ***** END GPL LICENSE BLOCK *****
*/
-/** \file treehash.c
+/** \file outliner_treehash.c
* \ingroup bke
*
* Tree hash for the outliner space.
@@ -28,7 +28,7 @@
#include <stdlib.h>
-#include "BKE_treehash.h"
+#include "BKE_outliner_treehash.h"
#include "BLI_utildefines.h"
#include "BLI_ghash.h"
@@ -38,8 +38,7 @@
#include "MEM_guardedalloc.h"
-typedef struct TseGroup
-{
+typedef struct TseGroup {
TreeStoreElem **elems;
int size;
int allocated;
@@ -103,12 +102,15 @@ static void fill_treehash(void *treehash, BLI_mempool *treestore)
TreeStoreElem *tselem;
BLI_mempool_iter iter;
BLI_mempool_iternew(treestore, &iter);
+
+ BLI_assert(treehash);
+
while ((tselem = BLI_mempool_iterstep(&iter))) {
- BKE_treehash_add_element(treehash, tselem);
+ BKE_outliner_treehash_add_element(treehash, tselem);
}
}
-void *BKE_treehash_create_from_treestore(BLI_mempool *treestore)
+void *BKE_outliner_treehash_create_from_treestore(BLI_mempool *treestore)
{
GHash *treehash = BLI_ghash_new_ex(tse_hash, tse_cmp, "treehash", BLI_mempool_count(treestore));
fill_treehash(treehash, treestore);
@@ -120,35 +122,46 @@ static void free_treehash_group(void *key)
tse_group_free(key);
}
-void *BKE_treehash_rebuild_from_treestore(void *treehash, BLI_mempool *treestore)
+void *BKE_outliner_treehash_rebuild_from_treestore(void *treehash, BLI_mempool *treestore)
{
+ BLI_assert(treehash);
+
BLI_ghash_clear_ex(treehash, NULL, free_treehash_group, BLI_mempool_count(treestore));
fill_treehash(treehash, treestore);
return treehash;
}
-void BKE_treehash_add_element(void *treehash, TreeStoreElem *elem)
+void BKE_outliner_treehash_add_element(void *treehash, TreeStoreElem *elem)
{
- TseGroup *group = BLI_ghash_lookup(treehash, elem);
- if (!group) {
- group = tse_group_create();
- BLI_ghash_insert(treehash, elem, group);
+ TseGroup *group;
+ void **val_p;
+
+ if (!BLI_ghash_ensure_p(treehash, elem, &val_p)) {
+ *val_p = tse_group_create();
}
+ group = *val_p;
tse_group_add(group, elem);
}
-static TseGroup *BKE_treehash_lookup_group(GHash *th, short type, short nr, struct ID *id)
+static TseGroup *BKE_outliner_treehash_lookup_group(GHash *th, short type, short nr, struct ID *id)
{
TreeStoreElem tse_template;
tse_template.type = type;
tse_template.nr = type ? nr : 0; // we're picky! :)
tse_template.id = id;
+
+ BLI_assert(th);
+
return BLI_ghash_lookup(th, &tse_template);
}
-TreeStoreElem *BKE_treehash_lookup_unused(void *treehash, short type, short nr, struct ID *id)
+TreeStoreElem *BKE_outliner_treehash_lookup_unused(void *treehash, short type, short nr, struct ID *id)
{
- TseGroup *group = BKE_treehash_lookup_group(treehash, type, nr, id);
+ TseGroup *group;
+
+ BLI_assert(treehash);
+
+ group = BKE_outliner_treehash_lookup_group(treehash, type, nr, id);
if (group) {
int i;
for (i = 0; i < group->size; i++) {
@@ -160,13 +173,19 @@ TreeStoreElem *BKE_treehash_lookup_unused(void *treehash, short type, short nr,
return NULL;
}
-TreeStoreElem *BKE_treehash_lookup_any(void *treehash, short type, short nr, struct ID *id)
+TreeStoreElem *BKE_outliner_treehash_lookup_any(void *treehash, short type, short nr, struct ID *id)
{
- TseGroup *group = BKE_treehash_lookup_group(treehash, type, nr, id);
+ TseGroup *group;
+
+ BLI_assert(treehash);
+
+ group = BKE_outliner_treehash_lookup_group(treehash, type, nr, id);
return group ? group->elems[0] : NULL;
}
-void BKE_treehash_free(void *treehash)
+void BKE_outliner_treehash_free(void *treehash)
{
+ BLI_assert(treehash);
+
BLI_ghash_free(treehash, NULL, free_treehash_group);
}
diff --git a/source/blender/blenkernel/intern/packedFile.c b/source/blender/blenkernel/intern/packedFile.c
index d186b4299a5..151889b10a1 100644
--- a/source/blender/blenkernel/intern/packedFile.c
+++ b/source/blender/blenkernel/intern/packedFile.c
@@ -128,8 +128,8 @@ int countPackedFiles(Main *bmain)
/* let's check if there are packed files... */
for (ima = bmain->image.first; ima; ima = ima->id.next)
- if (ima->packedfile)
- count++;
+ if (BKE_image_has_packedfile(ima))
+ count ++;
for (vf = bmain->vfont.first; vf; vf = vf->id.next)
if (vf->packedfile)
@@ -224,7 +224,7 @@ PackedFile *newPackedFile(ReportList *reports, const char *filename, const char
}
/* no libraries for now */
-void packAll(Main *bmain, ReportList *reports)
+void packAll(Main *bmain, ReportList *reports, bool verbose)
{
Image *ima;
VFont *vfont;
@@ -232,12 +232,12 @@ void packAll(Main *bmain, ReportList *reports)
int tot = 0;
for (ima = bmain->image.first; ima; ima = ima->id.next) {
- if (ima->packedfile == NULL && ima->id.lib == NULL) {
+ if (BKE_image_has_packedfile(ima) == false && ima->id.lib == NULL) {
if (ima->source == IMA_SRC_FILE) {
- ima->packedfile = newPackedFile(reports, ima->name, ID_BLEND_PATH(bmain, &ima->id));
+ BKE_image_packfiles(reports, ima, ID_BLEND_PATH(bmain, &ima->id));
tot ++;
}
- else if (BKE_image_is_animated(ima)) {
+ else if (BKE_image_is_animated(ima) && verbose) {
BKE_reportf(reports, RPT_WARNING, "Image '%s' skipped, movies and image sequences not supported",
ima->id.name + 2);
}
@@ -258,10 +258,10 @@ void packAll(Main *bmain, ReportList *reports)
}
}
- if (tot == 0)
- BKE_report(reports, RPT_INFO, "No new files have been packed");
- else
+ if (tot > 0)
BKE_reportf(reports, RPT_INFO, "Packed %d files", tot);
+ else if (verbose)
+ BKE_report(reports, RPT_INFO, "No new files have been packed");
}
@@ -376,7 +376,7 @@ int checkPackedFile(const char *filename, PackedFile *pf)
BLI_strncpy(name, filename, sizeof(name));
BLI_path_abs(name, G.main->name);
- if (BLI_stat(name, &st)) {
+ if (BLI_stat(name, &st) == -1) {
ret_val = PF_NOFILE;
}
else if (st.st_size != pf->size) {
@@ -418,20 +418,19 @@ int checkPackedFile(const char *filename, PackedFile *pf)
return(ret_val);
}
-/* unpackFile() looks at the existing files (abs_name, local_name) and a packed file.
+/**
+ * unpackFile() looks at the existing files (abs_name, local_name) and a packed file.
*
* It returns a char *to the existing file name / new file name or NULL when
* there was an error or when the user decides to cancel the operation.
+ *
+ * \warning 'abs_name' may be relative still! (use a "//" prefix) be sure to run #BLI_path_abs on it first.
*/
-
char *unpackFile(ReportList *reports, const char *abs_name, const char *local_name, PackedFile *pf, int how)
{
char *newname = NULL;
const char *temp = NULL;
- // char newabs[FILE_MAX];
- // char newlocal[FILE_MAX];
-
if (pf != NULL) {
switch (how) {
case -1:
@@ -441,27 +440,41 @@ char *unpackFile(ReportList *reports, const char *abs_name, const char *local_na
temp = abs_name;
break;
case PF_USE_LOCAL:
+ {
+ char temp_abs[FILE_MAX];
+
+ BLI_strncpy(temp_abs, local_name, sizeof(temp_abs));
+ BLI_path_abs(temp_abs, G.main->name);
+
/* if file exists use it */
- if (BLI_exists(local_name)) {
+ if (BLI_exists(temp_abs)) {
temp = local_name;
break;
}
/* else create it */
/* fall-through */
+ }
case PF_WRITE_LOCAL:
if (writePackedFile(reports, local_name, pf, 1) == RET_OK) {
temp = local_name;
}
break;
case PF_USE_ORIGINAL:
+ {
+ char temp_abs[FILE_MAX];
+
+ BLI_strncpy(temp_abs, abs_name, sizeof(temp_abs));
+ BLI_path_abs(temp_abs, G.main->name);
+
/* if file exists use it */
- if (BLI_exists(abs_name)) {
+ if (BLI_exists(temp_abs)) {
BKE_reportf(reports, RPT_INFO, "Use existing file (instead of packed): %s", abs_name);
temp = abs_name;
break;
}
/* else create it */
/* fall-through */
+ }
case PF_WRITE_ORIGINAL:
if (writePackedFile(reports, abs_name, pf, 1) == RET_OK) {
temp = abs_name;
@@ -480,17 +493,54 @@ char *unpackFile(ReportList *reports, const char *abs_name, const char *local_na
return newname;
}
+static void unpack_generate_paths(
+ const char *name, ID *id, char *r_abspath, char *r_relpath, size_t abspathlen, size_t relpathlen)
+{
+ char tempname[FILE_MAX];
+ char tempdir[FILE_MAXDIR];
+
+ BLI_split_dirfile(name, tempdir, tempname, sizeof(tempdir), sizeof(tempname));
+
+ if (tempname[0] == '\0') {
+ /* Note: we do not have any real way to re-create extension out of data... */
+ BLI_strncpy(tempname, id->name + 2, sizeof(tempname));
+ printf("%s\n", tempname);
+ BLI_filename_make_safe(tempname);
+ printf("%s\n", tempname);
+ }
+
+ if (tempdir[0] == '\0') {
+ /* Fallback to relative dir. */
+ BLI_strncpy(tempdir, "//", sizeof(tempdir));
+ }
+
+ switch (GS(id->name)) {
+ case ID_VF:
+ BLI_snprintf(r_relpath, relpathlen, "//fonts/%s", tempname);
+ break;
+ case ID_SO:
+ BLI_snprintf(r_relpath, relpathlen, "//sounds/%s", tempname);
+ break;
+ case ID_IM:
+ BLI_snprintf(r_relpath, relpathlen, "//textures/%s", tempname);
+ break;
+ }
+
+ {
+ size_t len = BLI_strncpy_rlen(r_abspath, tempdir, abspathlen);
+ BLI_strncpy(r_abspath + len, tempname, abspathlen - len);
+ }
+}
int unpackVFont(ReportList *reports, VFont *vfont, int how)
{
- char localname[FILE_MAX], fi[FILE_MAXFILE];
+ char localname[FILE_MAX], absname[FILE_MAX];
char *newname;
int ret_value = RET_ERROR;
if (vfont != NULL) {
- BLI_split_file_part(vfont->name, fi, sizeof(fi));
- BLI_snprintf(localname, sizeof(localname), "//fonts/%s", fi);
- newname = unpackFile(reports, vfont->name, localname, vfont->packedfile, how);
+ unpack_generate_paths(vfont->name, (ID *)vfont, absname, localname, sizeof(absname), sizeof(localname));
+ newname = unpackFile(reports, absname, localname, vfont->packedfile, how);
if (newname != NULL) {
ret_value = RET_OK;
freePackedFile(vfont->packedfile);
@@ -505,14 +555,13 @@ int unpackVFont(ReportList *reports, VFont *vfont, int how)
int unpackSound(Main *bmain, ReportList *reports, bSound *sound, int how)
{
- char localname[FILE_MAXDIR + FILE_MAX], fi[FILE_MAX];
+ char localname[FILE_MAX], absname[FILE_MAX];
char *newname;
int ret_value = RET_ERROR;
if (sound != NULL) {
- BLI_split_file_part(sound->name, fi, sizeof(fi));
- BLI_snprintf(localname, sizeof(localname), "//sounds/%s", fi);
- newname = unpackFile(reports, sound->name, localname, sound->packedfile, how);
+ unpack_generate_paths(sound->name, (ID *)sound, absname, localname, sizeof(absname), sizeof(localname));
+ newname = unpackFile(reports, absname, localname, sound->packedfile, how);
if (newname != NULL) {
BLI_strncpy(sound->name, newname, sizeof(sound->name));
MEM_freeN(newname);
@@ -520,7 +569,7 @@ int unpackSound(Main *bmain, ReportList *reports, bSound *sound, int how)
freePackedFile(sound->packedfile);
sound->packedfile = NULL;
- sound_load(bmain, sound);
+ BKE_sound_load(bmain, sound);
ret_value = RET_OK;
}
@@ -531,24 +580,47 @@ int unpackSound(Main *bmain, ReportList *reports, bSound *sound, int how)
int unpackImage(ReportList *reports, Image *ima, int how)
{
- char localname[FILE_MAXDIR + FILE_MAX], fi[FILE_MAX];
- char *newname;
int ret_value = RET_ERROR;
-
+
if (ima != NULL && ima->name[0]) {
- BLI_split_file_part(ima->name, fi, sizeof(fi));
- BLI_snprintf(localname, sizeof(localname), "//textures/%s", fi);
- newname = unpackFile(reports, ima->name, localname, ima->packedfile, how);
- if (newname != NULL) {
- ret_value = RET_OK;
- freePackedFile(ima->packedfile);
- ima->packedfile = NULL;
- BLI_strncpy(ima->name, newname, sizeof(ima->name));
- MEM_freeN(newname);
- BKE_image_signal(ima, NULL, IMA_SIGNAL_RELOAD);
+ while (ima->packedfiles.last) {
+ char localname[FILE_MAX], absname[FILE_MAX];
+ char *newname;
+ ImagePackedFile *imapf = ima->packedfiles.last;
+
+ unpack_generate_paths(imapf->filepath, (ID *)ima, absname, localname, sizeof(absname), sizeof(localname));
+ newname = unpackFile(reports, absname, localname, imapf->packedfile, how);
+
+ if (newname != NULL) {
+ ImageView *iv;
+
+ ret_value = ret_value == RET_ERROR ? RET_ERROR : RET_OK;
+ freePackedFile(imapf->packedfile);
+ imapf->packedfile = NULL;
+
+ /* update the new corresponding view filepath */
+ iv = BLI_findstring(&ima->views, imapf->filepath, offsetof(ImageView, filepath));
+ if (iv) {
+ BLI_strncpy(iv->filepath, newname, sizeof(imapf->filepath));
+ }
+
+ /* keep the new name in the image for non-pack specific reasons */
+ BLI_strncpy(ima->name, newname, sizeof(imapf->filepath));
+ MEM_freeN(newname);
+ }
+ else {
+ ret_value = RET_ERROR;
+ }
+
+ BLI_remlink(&ima->packedfiles, imapf);
+ MEM_freeN(imapf);
}
}
-
+
+ if (ret_value == RET_OK) {
+ BKE_image_signal(ima, NULL, IMA_SIGNAL_RELOAD);
+ }
+
return(ret_value);
}
@@ -604,7 +676,7 @@ void unpackAll(Main *bmain, ReportList *reports, int how)
bSound *sound;
for (ima = bmain->image.first; ima; ima = ima->id.next)
- if (ima->packedfile)
+ if (BKE_image_has_packedfile(ima))
unpackImage(reports, ima, how);
for (vf = bmain->vfont.first; vf; vf = vf->id.next)
@@ -623,7 +695,7 @@ bool BKE_pack_check(ID *id)
case ID_IM:
{
Image *ima = (Image *)id;
- return ima->packedfile != NULL;
+ return BKE_image_has_packedfile(ima);
}
case ID_VF:
{
@@ -651,7 +723,7 @@ void BKE_unpack_id(Main *bmain, ID *id, ReportList *reports, int how)
case ID_IM:
{
Image *ima = (Image *)id;
- if (ima->packedfile) {
+ if (BKE_image_has_packedfile(ima)) {
unpackImage(reports, ima, how);
}
break;
diff --git a/source/blender/blenkernel/intern/paint.c b/source/blender/blenkernel/intern/paint.c
index d16575d80c8..06844b09a9b 100644
--- a/source/blender/blenkernel/intern/paint.c
+++ b/source/blender/blenkernel/intern/paint.c
@@ -48,6 +48,7 @@
#include "BLI_listbase.h"
#include "BKE_brush.h"
+#include "BKE_colortools.h"
#include "BKE_main.h"
#include "BKE_context.h"
#include "BKE_crazyspace.h"
@@ -127,6 +128,32 @@ void BKE_paint_reset_overlay_invalid(OverlayControlFlags flag)
overlay_flags &= ~(flag);
}
+Paint *BKE_paint_get_active_from_paintmode(Scene *sce, PaintMode mode)
+{
+ if (sce) {
+ ToolSettings *ts = sce->toolsettings;
+
+ switch (mode) {
+ case ePaintSculpt:
+ return &ts->sculpt->paint;
+ case ePaintVertex:
+ return &ts->vpaint->paint;
+ case ePaintWeight:
+ return &ts->wpaint->paint;
+ case ePaintTexture2D:
+ case ePaintTextureProjective:
+ return &ts->imapaint.paint;
+ case ePaintSculptUV:
+ return &ts->uvsculpt->paint;
+ case ePaintInvalid:
+ return NULL;
+ default:
+ return &ts->imapaint.paint;
+ }
+ }
+
+ return NULL;
+}
Paint *BKE_paint_get_active(Scene *sce)
{
@@ -222,39 +249,39 @@ PaintMode BKE_paintmode_get_active_from_context(const bContext *C)
if ((sima = CTX_wm_space_image(C)) != NULL) {
if (obact && obact->mode == OB_MODE_EDIT) {
if (sima->mode == SI_MODE_PAINT)
- return PAINT_TEXTURE_2D;
+ return ePaintTexture2D;
else if (ts->use_uv_sculpt)
- return PAINT_SCULPT_UV;
+ return ePaintSculptUV;
}
else {
- return PAINT_TEXTURE_2D;
+ return ePaintTexture2D;
}
}
else if (obact) {
switch (obact->mode) {
case OB_MODE_SCULPT:
- return PAINT_SCULPT;
+ return ePaintSculpt;
case OB_MODE_VERTEX_PAINT:
- return PAINT_VERTEX;
+ return ePaintVertex;
case OB_MODE_WEIGHT_PAINT:
- return PAINT_WEIGHT;
+ return ePaintWeight;
case OB_MODE_TEXTURE_PAINT:
- return PAINT_TEXTURE_PROJECTIVE;
+ return ePaintTextureProjective;
case OB_MODE_EDIT:
if (ts->use_uv_sculpt)
- return PAINT_SCULPT_UV;
- return PAINT_TEXTURE_2D;
+ return ePaintSculptUV;
+ return ePaintTexture2D;
default:
- return PAINT_TEXTURE_2D;
+ return ePaintTexture2D;
}
}
else {
/* default to image paint */
- return PAINT_TEXTURE_2D;
+ return ePaintTexture2D;
}
}
- return PAINT_INVALID;
+ return ePaintInvalid;
}
Brush *BKE_paint_brush(Paint *p)
@@ -312,25 +339,33 @@ void BKE_paint_curve_set(Brush *br, PaintCurve *pc)
}
}
+void BKE_paint_curve_clamp_endpoint_add_index(PaintCurve *pc, const int add_index)
+{
+ pc->add_index = (add_index || pc->tot_points == 1) ? (add_index + 1) : 0;
+}
+
/* remove colour from palette. Must be certain color is inside the palette! */
void BKE_palette_color_remove(Palette *palette, PaletteColor *color)
{
- if (color) {
- int numcolors = BLI_countlist(&palette->colors);
- if ((numcolors == palette->active_color + 1) && (numcolors != 1))
- palette->active_color--;
-
- BLI_remlink(&palette->colors, color);
- BLI_addhead(&palette->deleted, color);
+ if (BLI_listbase_count_ex(&palette->colors, palette->active_color) == palette->active_color) {
+ palette->active_color--;
}
+
+ BLI_remlink(&palette->colors, color);
+
+ if (palette->active_color < 0 && !BLI_listbase_is_empty(&palette->colors)) {
+ palette->active_color = 0;
+ }
+
+ MEM_freeN(color);
}
-void BKE_palette_cleanup(Palette *palette)
+void BKE_palette_clear(Palette *palette)
{
- BLI_freelistN(&palette->deleted);
+ BLI_freelistN(&palette->colors);
+ palette->active_color = 0;
}
-
Palette *BKE_palette_add(Main *bmain, const char *name)
{
Palette *palette;
@@ -352,7 +387,6 @@ PaletteColor *BKE_palette_color_add(Palette *palette)
{
PaletteColor *color = MEM_callocN(sizeof(*color), "Pallete Color");
BLI_addtail(&palette->colors, color);
- palette->active_color = BLI_countlist(&palette->colors) - 1;
return color;
}
@@ -395,24 +429,73 @@ bool BKE_paint_select_elem_test(Object *ob)
BKE_paint_select_face_test(ob));
}
-void BKE_paint_init(Paint *p, const char col[3])
+void BKE_paint_cavity_curve_preset(Paint *p, int preset)
{
+ CurveMap *cm = NULL;
+
+ if (!p->cavity_curve)
+ p->cavity_curve = curvemapping_add(1, 0, 0, 1, 1);
+
+ cm = p->cavity_curve->cm;
+ cm->flag &= ~CUMA_EXTEND_EXTRAPOLATE;
+
+ p->cavity_curve->preset = preset;
+ curvemap_reset(cm, &p->cavity_curve->clipr, p->cavity_curve->preset, CURVEMAP_SLOPE_POSITIVE);
+ curvemapping_changed(p->cavity_curve, false);
+}
+
+short BKE_paint_object_mode_from_paint_mode(PaintMode mode)
+{
+ switch (mode) {
+ case ePaintSculpt:
+ return OB_MODE_SCULPT;
+ case ePaintVertex:
+ return OB_MODE_VERTEX_PAINT;
+ case ePaintWeight:
+ return OB_MODE_WEIGHT_PAINT;
+ case ePaintTextureProjective:
+ return OB_MODE_TEXTURE_PAINT;
+ case ePaintTexture2D:
+ return OB_MODE_TEXTURE_PAINT;
+ case ePaintSculptUV:
+ return OB_MODE_EDIT;
+ case ePaintInvalid:
+ default:
+ return 0;
+ }
+}
+
+void BKE_paint_init(Scene *sce, PaintMode mode, const char col[3])
+{
+ UnifiedPaintSettings *ups = &sce->toolsettings->unified_paint_settings;
Brush *brush;
+ Paint *paint = BKE_paint_get_active_from_paintmode(sce, mode);
/* If there's no brush, create one */
- brush = BKE_paint_brush(p);
- if (brush == NULL)
- brush = BKE_brush_add(G.main, "Brush");
- BKE_paint_brush_set(p, brush);
+ brush = BKE_paint_brush(paint);
+ if (brush == NULL) {
+ short ob_mode = BKE_paint_object_mode_from_paint_mode(mode);
+ brush = BKE_brush_first_search(G.main, ob_mode);
+
+ if (!brush)
+ brush = BKE_brush_add(G.main, "Brush", ob_mode);
+ BKE_paint_brush_set(paint, brush);
+ }
- memcpy(p->paint_cursor_col, col, 3);
- p->paint_cursor_col[3] = 128;
+ memcpy(paint->paint_cursor_col, col, 3);
+ paint->paint_cursor_col[3] = 128;
+ ups->last_stroke_valid = false;
+ zero_v3(ups->average_stroke_accum);
+ ups->average_stroke_counter = 0;
+ if (!paint->cavity_curve)
+ BKE_paint_cavity_curve_preset(paint, CURVE_PRESET_LINE);
}
void BKE_paint_free(Paint *paint)
{
id_us_min((ID *)paint->brush);
id_us_min((ID *)paint->palette);
+ curvemapping_free(paint->cavity_curve);
}
/* called when copying scene settings, so even if 'src' and 'tar' are the same
@@ -424,16 +507,28 @@ void BKE_paint_copy(Paint *src, Paint *tar)
tar->brush = src->brush;
id_us_plus((ID *)tar->brush);
id_us_plus((ID *)tar->palette);
+ tar->cavity_curve = curvemapping_copy(src->cavity_curve);
+}
+
+void BKE_paint_stroke_get_average(Scene *scene, Object *ob, float stroke[3])
+{
+ UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings;
+ if (ups->last_stroke_valid && ups->average_stroke_counter > 0) {
+ float fac = 1.0f / ups->average_stroke_counter;
+ mul_v3_v3fl(stroke, ups->average_stroke_accum, fac);
+ }
+ else {
+ copy_v3_v3(stroke, ob->obmat[3]);
+ }
}
/* returns non-zero if any of the face's vertices
* are hidden, zero otherwise */
-bool paint_is_face_hidden(const MFace *f, const MVert *mvert)
+bool paint_is_face_hidden(const MLoopTri *lt, const MVert *mvert, const MLoop *mloop)
{
- return ((mvert[f->v1].flag & ME_HIDE) ||
- (mvert[f->v2].flag & ME_HIDE) ||
- (mvert[f->v3].flag & ME_HIDE) ||
- (f->v4 && (mvert[f->v4].flag & ME_HIDE)));
+ return ((mvert[mloop[lt->tri[0]].v].flag & ME_HIDE) ||
+ (mvert[mloop[lt->tri[1]].v].flag & ME_HIDE) ||
+ (mvert[mloop[lt->tri[2]].v].flag & ME_HIDE));
}
/* returns non-zero if any of the corners of the grid
@@ -477,31 +572,53 @@ float paint_grid_paint_mask(const GridPaintMask *gpm, unsigned level,
/* threshold to move before updating the brush rotation */
#define RAKE_THRESHHOLD 20
-void paint_calculate_rake_rotation(UnifiedPaintSettings *ups, const float mouse_pos[2])
+void paint_update_brush_rake_rotation(UnifiedPaintSettings *ups, Brush *brush, float rotation)
{
- const float u = 0.5f;
- const float r = RAKE_THRESHHOLD;
+ if (brush->mtex.brush_angle_mode & MTEX_ANGLE_RAKE)
+ ups->brush_rotation = rotation;
+ else
+ ups->brush_rotation = 0.0f;
- float dpos[2];
- sub_v2_v2v2(dpos, ups->last_rake, mouse_pos);
+ if (brush->mask_mtex.brush_angle_mode & MTEX_ANGLE_RAKE)
+ ups->brush_rotation_sec = rotation;
+ else
+ ups->brush_rotation_sec = 0.0f;
+}
- if (len_squared_v2(dpos) >= r * r) {
- ups->brush_rotation = atan2f(dpos[0], dpos[1]);
+void paint_calculate_rake_rotation(UnifiedPaintSettings *ups, Brush *brush, const float mouse_pos[2])
+{
+ if ((brush->mtex.brush_angle_mode & MTEX_ANGLE_RAKE) || (brush->mask_mtex.brush_angle_mode & MTEX_ANGLE_RAKE)) {
+ const float r = RAKE_THRESHHOLD;
+ float rotation;
+
+ float dpos[2];
+ sub_v2_v2v2(dpos, ups->last_rake, mouse_pos);
+
+ if (len_squared_v2(dpos) >= r * r) {
+ rotation = atan2f(dpos[0], dpos[1]);
- interp_v2_v2v2(ups->last_rake, ups->last_rake,
- mouse_pos, u);
+ copy_v2_v2(ups->last_rake, mouse_pos);
+
+ ups->last_rake_angle = rotation;
+
+ paint_update_brush_rake_rotation(ups, brush, rotation);
+ }
+ /* make sure we reset here to the last rotation to avoid accumulating
+ * values in case a random rotation is also added */
+ else {
+ paint_update_brush_rake_rotation(ups, brush, ups->last_rake_angle);
+ }
+ }
+ else {
+ ups->brush_rotation = ups->brush_rotation_sec = 0.0f;
}
}
-void BKE_free_sculptsession_deformMats(SculptSession *ss)
+void BKE_sculptsession_free_deformMats(SculptSession *ss)
{
- if (ss->orig_cos) MEM_freeN(ss->orig_cos);
- if (ss->deform_cos) MEM_freeN(ss->deform_cos);
- if (ss->deform_imats) MEM_freeN(ss->deform_imats);
-
- ss->orig_cos = NULL;
- ss->deform_cos = NULL;
- ss->deform_imats = NULL;
+ MEM_SAFE_FREE(ss->orig_cos);
+ MEM_SAFE_FREE(ss->deform_cos);
+ MEM_SAFE_FREE(ss->deform_imats);
}
/* Write out the sculpt dynamic-topology BMesh to the Mesh */
@@ -560,7 +677,7 @@ void BKE_sculptsession_bm_to_me_for_render(Object *object)
}
}
-void BKE_free_sculptsession(Object *ob)
+void BKE_sculptsession_free(Object *ob)
{
if (ob && ob->sculpt) {
SculptSession *ss = ob->sculpt;
@@ -644,25 +761,25 @@ static bool sculpt_modifiers_active(Scene *scene, Sculpt *sd, Object *ob)
VirtualModifierData virtualModifierData;
if (mmd || ob->sculpt->bm)
- return 0;
+ return false;
/* non-locked shape keys could be handled in the same way as deformed mesh */
if ((ob->shapeflag & OB_SHAPE_LOCK) == 0 && me->key && ob->shapenr)
- return 1;
+ return true;
md = modifiers_getVirtualModifierList(ob, &virtualModifierData);
/* exception for shape keys because we can edit those */
for (; md; md = md->next) {
- ModifierTypeInfo *mti = modifierType_getInfo(md->type);
+ const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
if (!modifier_isEnabled(scene, md, eModifierMode_Realtime)) continue;
if (ELEM(md->type, eModifierType_ShapeKey, eModifierType_Multires)) continue;
- if (mti->type == eModifierTypeType_OnlyDeform) return 1;
- else if ((sd->flags & SCULPT_ONLY_DEFORM) == 0) return 1;
+ if (mti->type == eModifierTypeType_OnlyDeform) return true;
+ else if ((sd->flags & SCULPT_ONLY_DEFORM) == 0) return true;
}
- return 0;
+ return false;
}
/**
@@ -700,13 +817,11 @@ void BKE_sculpt_update_mesh_elements(Scene *scene, Sculpt *sd, Object *ob,
}
}
- /* BMESH ONLY --- at some point we should move sculpt code to use polygons only - but for now it needs tessfaces */
- BKE_mesh_tessface_ensure(me);
+ /* tessfaces aren't used and will become invalid */
+ BKE_mesh_tessface_clear(me);
- if (!mmd) ss->kb = BKE_keyblock_from_object(ob);
- else ss->kb = NULL;
+ ss->kb = (mmd == NULL) ? BKE_keyblock_from_object(ob) : NULL;
- /* needs to be called after we ensure tessface */
dm = mesh_get_derived_final(scene, ob, CD_MASK_BAREMESH);
if (mmd) {
@@ -716,7 +831,6 @@ void BKE_sculpt_update_mesh_elements(Scene *scene, Sculpt *sd, Object *ob,
ss->mvert = NULL;
ss->mpoly = NULL;
ss->mloop = NULL;
- ss->face_normals = NULL;
}
else {
ss->totvert = me->totvert;
@@ -724,7 +838,6 @@ void BKE_sculpt_update_mesh_elements(Scene *scene, Sculpt *sd, Object *ob,
ss->mvert = me->mvert;
ss->mpoly = me->mpoly;
ss->mloop = me->mloop;
- ss->face_normals = NULL;
ss->multires = NULL;
ss->vmask = CustomData_get_layer(&me->vdata, CD_PAINT_MASK);
}
@@ -738,9 +851,9 @@ void BKE_sculpt_update_mesh_elements(Scene *scene, Sculpt *sd, Object *ob,
if (!ss->orig_cos) {
int a;
- BKE_free_sculptsession_deformMats(ss);
+ BKE_sculptsession_free_deformMats(ss);
- ss->orig_cos = (ss->kb) ? BKE_key_convert_to_vertcos(ob, ss->kb) : BKE_mesh_vertexCos_get(me, NULL);
+ ss->orig_cos = (ss->kb) ? BKE_keyblock_convert_to_vertcos(ob, ss->kb) : BKE_mesh_vertexCos_get(me, NULL);
BKE_crazyspace_build_sculpt(scene, ob, &ss->deform_imats, &ss->deform_cos);
BKE_pbvh_apply_vertCos(ss->pbvh, ss->deform_cos);
@@ -751,18 +864,18 @@ void BKE_sculpt_update_mesh_elements(Scene *scene, Sculpt *sd, Object *ob,
}
}
else {
- BKE_free_sculptsession_deformMats(ss);
+ BKE_sculptsession_free_deformMats(ss);
}
if (ss->kb != NULL && ss->deform_cos == NULL) {
- ss->deform_cos = BKE_key_convert_to_vertcos(ob, ss->kb);
+ ss->deform_cos = BKE_keyblock_convert_to_vertcos(ob, ss->kb);
}
/* if pbvh is deformed, key block is already applied to it */
if (ss->kb) {
bool pbvh_deformd = BKE_pbvh_isDeformed(ss->pbvh);
if (!pbvh_deformd || ss->deform_cos == NULL) {
- float (*vertCos)[3] = BKE_key_convert_to_vertcos(ob, ss->kb);
+ float (*vertCos)[3] = BKE_keyblock_convert_to_vertcos(ob, ss->kb);
if (vertCos) {
if (!pbvh_deformd) {
diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c
index 530573d6e38..9aacba8d02e 100644
--- a/source/blender/blenkernel/intern/particle.c
+++ b/source/blender/blenkernel/intern/particle.c
@@ -53,16 +53,18 @@
#include "BLI_utildefines.h"
#include "BLI_kdtree.h"
#include "BLI_rand.h"
+#include "BLI_task.h"
#include "BLI_threads.h"
#include "BLI_linklist.h"
-#include "BLF_translation.h"
+#include "BLT_translation.h"
#include "BKE_anim.h"
#include "BKE_animsys.h"
#include "BKE_boids.h"
#include "BKE_cloth.h"
+#include "BKE_colortools.h"
#include "BKE_effect.h"
#include "BKE_global.h"
#include "BKE_group.h"
@@ -101,9 +103,11 @@ void psys_init_rng(void)
static void get_child_modifier_parameters(ParticleSettings *part, ParticleThreadContext *ctx,
ChildParticle *cpa, short cpa_from, int cpa_num, float *cpa_fuv, float *orco, ParticleTexture *ptex);
-static void do_child_modifiers(ParticleSimulationData *sim,
- ParticleTexture *ptex, ParticleKey *par, float *par_rot, ChildParticle *cpa,
- float *orco, float mat[4][4], ParticleKey *state, float t);
+static void get_cpa_texture(DerivedMesh *dm, ParticleSystem *psys, ParticleSettings *part, ParticleData *par,
+ int child_index, int face_index, const float fw[4], float *orco, ParticleTexture *ptex, int event, float cfra);
+extern void do_child_modifiers(ParticleSimulationData *sim,
+ ParticleTexture *ptex, const float par_co[3], const float par_vel[3], const float par_rot[4], const float par_orco[3],
+ ChildParticle *cpa, const float orco[3], float mat[4][4], ParticleKey *state, float t);
/* few helpers for countall etc. */
int count_particles(ParticleSystem *psys)
@@ -137,7 +141,7 @@ int count_particles_mod(ParticleSystem *psys, int totgr, int cur)
#define PATH_CACHE_BUF_SIZE 1024
-static ParticleCacheKey **psys_alloc_path_cache_buffers(ListBase *bufs, int tot, int steps)
+static ParticleCacheKey **psys_alloc_path_cache_buffers(ListBase *bufs, int tot, int totkeys)
{
LinkData *buf;
ParticleCacheKey **cache;
@@ -150,10 +154,10 @@ static ParticleCacheKey **psys_alloc_path_cache_buffers(ListBase *bufs, int tot,
while (totkey < tot) {
totbufkey = MIN2(tot - totkey, PATH_CACHE_BUF_SIZE);
buf = MEM_callocN(sizeof(LinkData), "PathCacheLinkData");
- buf->data = MEM_callocN(sizeof(ParticleCacheKey) * totbufkey * steps, "ParticleCacheKey");
+ buf->data = MEM_callocN(sizeof(ParticleCacheKey) * totbufkey * totkeys, "ParticleCacheKey");
for (i = 0; i < totbufkey; i++)
- cache[totkey + i] = ((ParticleCacheKey *)buf->data) + i * steps;
+ cache[totkey + i] = ((ParticleCacheKey *)buf->data) + i * totkeys;
totkey += totbufkey;
BLI_addtail(bufs, buf);
@@ -270,11 +274,11 @@ void psys_enable_all(Object *ob)
for (; psys; psys = psys->next)
psys->flag &= ~PSYS_DISABLED;
}
-int psys_in_edit_mode(Scene *scene, ParticleSystem *psys)
+bool psys_in_edit_mode(Scene *scene, ParticleSystem *psys)
{
return (scene->basact && (scene->basact->object->mode & OB_MODE_PARTICLE_EDIT) && psys == psys_get_current((scene->basact)->object) && (psys->edit || psys->pointcache->edit) && !psys->renderdata);
}
-int psys_check_enabled(Object *ob, ParticleSystem *psys)
+bool psys_check_enabled(Object *ob, ParticleSystem *psys)
{
ParticleSystemModifierData *psmd;
@@ -292,7 +296,7 @@ int psys_check_enabled(Object *ob, ParticleSystem *psys)
return 1;
}
-int psys_check_edited(ParticleSystem *psys)
+bool psys_check_edited(ParticleSystem *psys)
{
if (psys->part && psys->part->type == PART_HAIR)
return (psys->flag & PSYS_EDITED || (psys->edit && psys->edit->edited));
@@ -371,7 +375,13 @@ void BKE_particlesettings_free(ParticleSettings *part)
{
MTex *mtex;
int a;
- BKE_free_animdata(&part->id);
+ BKE_animdata_free(&part->id);
+
+ if (part->clumpcurve)
+ curvemapping_free(part->clumpcurve);
+ if (part->roughcurve)
+ curvemapping_free(part->roughcurve);
+
free_partdeflect(part->pd);
free_partdeflect(part->pd2);
@@ -406,8 +416,7 @@ void free_hair(Object *UNUSED(ob), ParticleSystem *psys, int dynamics)
if (psys->clmd) {
if (dynamics) {
BKE_ptcache_free_list(&psys->ptcaches);
- psys->clmd->point_cache = psys->pointcache = NULL;
- BLI_listbase_clear(&psys->clmd->ptcaches);
+ psys->pointcache = NULL;
modifier_free((ModifierData *)psys->clmd);
@@ -591,89 +600,6 @@ void psys_free(Object *ob, ParticleSystem *psys)
* rendering, to make different render settings possible without
* removing the previous data. this should be solved properly once */
-typedef struct ParticleRenderElem {
- int curchild, totchild, reduce;
- float lambda, t, scalemin, scalemax;
-} ParticleRenderElem;
-
-typedef struct ParticleRenderData {
- ChildParticle *child;
- ParticleCacheKey **pathcache;
- ParticleCacheKey **childcache;
- ListBase pathcachebufs, childcachebufs;
- int totchild, totcached, totchildcache;
- DerivedMesh *dm;
- int totdmvert, totdmedge, totdmface;
-
- float mat[4][4];
- float viewmat[4][4], winmat[4][4];
- int winx, winy;
-
- int do_simplify;
- int timeoffset;
- ParticleRenderElem *elems;
-
- /* ORIGINDEX */
- const int *index_mf_to_mpoly;
- const int *index_mp_to_orig;
-} ParticleRenderData;
-
-static float psys_render_viewport_falloff(double rate, float dist, float width)
-{
- return pow(rate, dist / width);
-}
-
-static float psys_render_projected_area(ParticleSystem *psys, const float center[3], float area, double vprate, float *viewport)
-{
- ParticleRenderData *data = psys->renderdata;
- float co[4], view[3], ortho1[3], ortho2[3], w, dx, dy, radius;
-
- /* transform to view space */
- copy_v3_v3(co, center);
- co[3] = 1.0f;
- mul_m4_v4(data->viewmat, co);
-
- /* compute two vectors orthogonal to view vector */
- normalize_v3_v3(view, co);
- ortho_basis_v3v3_v3(ortho1, ortho2, view);
-
- /* compute on screen minification */
- w = co[2] * data->winmat[2][3] + data->winmat[3][3];
- dx = data->winx * ortho2[0] * data->winmat[0][0];
- dy = data->winy * ortho2[1] * data->winmat[1][1];
- w = sqrtf(dx * dx + dy * dy) / w;
-
- /* w squared because we are working with area */
- area = area * w * w;
-
- /* viewport of the screen test */
-
- /* project point on screen */
- mul_m4_v4(data->winmat, co);
- if (co[3] != 0.0f) {
- co[0] = 0.5f * data->winx * (1.0f + co[0] / co[3]);
- co[1] = 0.5f * data->winy * (1.0f + co[1] / co[3]);
- }
-
- /* screen space radius */
- radius = sqrtf(area / (float)M_PI);
-
- /* make smaller using fallof once over screen edge */
- *viewport = 1.0f;
-
- if (co[0] + radius < 0.0f)
- *viewport *= psys_render_viewport_falloff(vprate, -(co[0] + radius), data->winx);
- else if (co[0] - radius > data->winx)
- *viewport *= psys_render_viewport_falloff(vprate, (co[0] - radius) - data->winx, data->winx);
-
- if (co[1] + radius < 0.0f)
- *viewport *= psys_render_viewport_falloff(vprate, -(co[1] + radius), data->winy);
- else if (co[1] - radius > data->winy)
- *viewport *= psys_render_viewport_falloff(vprate, (co[1] - radius) - data->winy, data->winy);
-
- return area;
-}
-
void psys_render_set(Object *ob, ParticleSystem *psys, float viewmat[4][4], float winmat[4][4], int winx, int winy, int timeoffset)
{
ParticleRenderData *data;
@@ -788,191 +714,6 @@ void psys_render_restore(Object *ob, ParticleSystem *psys)
}
}
-/* BMESH_TODO, for orig face data, we need to use MPoly */
-
-int psys_render_simplify_distribution(ParticleThreadContext *ctx, int tot)
-{
- DerivedMesh *dm = ctx->dm;
- Mesh *me = (Mesh *)(ctx->sim.ob->data);
- MFace *mf, *mface;
- MVert *mvert;
- ParticleRenderData *data;
- ParticleRenderElem *elems, *elem;
- ParticleSettings *part = ctx->sim.psys->part;
- float *facearea, (*facecenter)[3], size[3], fac, powrate, scaleclamp;
- float co1[3], co2[3], co3[3], co4[3], lambda, arearatio, t, area, viewport;
- double vprate;
- int *facetotvert;
- int a, b, totorigface, totface, newtot, skipped;
-
- /* double lookup */
- const int *index_mf_to_mpoly;
- const int *index_mp_to_orig;
-
- if (part->ren_as != PART_DRAW_PATH || !(part->draw & PART_DRAW_REN_STRAND))
- return tot;
- if (!ctx->sim.psys->renderdata)
- return tot;
-
- data = ctx->sim.psys->renderdata;
- if (data->timeoffset)
- return 0;
- if (!(part->simplify_flag & PART_SIMPLIFY_ENABLE))
- return tot;
-
- mvert = dm->getVertArray(dm);
- mface = dm->getTessFaceArray(dm);
- totface = dm->getNumTessFaces(dm);
- totorigface = me->totpoly;
-
- if (totface == 0 || totorigface == 0)
- return tot;
-
- index_mf_to_mpoly = dm->getTessFaceDataArray(dm, CD_ORIGINDEX);
- index_mp_to_orig = dm->getPolyDataArray(dm, CD_ORIGINDEX);
- if (index_mf_to_mpoly == NULL) {
- index_mp_to_orig = NULL;
- }
-
- facearea = MEM_callocN(sizeof(float) * totorigface, "SimplifyFaceArea");
- facecenter = MEM_callocN(sizeof(float[3]) * totorigface, "SimplifyFaceCenter");
- facetotvert = MEM_callocN(sizeof(int) * totorigface, "SimplifyFaceArea");
- elems = MEM_callocN(sizeof(ParticleRenderElem) * totorigface, "SimplifyFaceElem");
-
- if (data->elems)
- MEM_freeN(data->elems);
-
- data->do_simplify = true;
- data->elems = elems;
- data->index_mf_to_mpoly = index_mf_to_mpoly;
- data->index_mp_to_orig = index_mp_to_orig;
-
- /* compute number of children per original face */
- for (a = 0; a < tot; a++) {
- b = (index_mf_to_mpoly) ? DM_origindex_mface_mpoly(index_mf_to_mpoly, index_mp_to_orig, ctx->index[a]) : ctx->index[a];
- if (b != ORIGINDEX_NONE) {
- elems[b].totchild++;
- }
- }
-
- /* compute areas and centers of original faces */
- for (mf = mface, a = 0; a < totface; a++, mf++) {
- b = (index_mf_to_mpoly) ? DM_origindex_mface_mpoly(index_mf_to_mpoly, index_mp_to_orig, a) : a;
-
- if (b != ORIGINDEX_NONE) {
- copy_v3_v3(co1, mvert[mf->v1].co);
- copy_v3_v3(co2, mvert[mf->v2].co);
- copy_v3_v3(co3, mvert[mf->v3].co);
-
- add_v3_v3(facecenter[b], co1);
- add_v3_v3(facecenter[b], co2);
- add_v3_v3(facecenter[b], co3);
-
- if (mf->v4) {
- copy_v3_v3(co4, mvert[mf->v4].co);
- add_v3_v3(facecenter[b], co4);
- facearea[b] += area_quad_v3(co1, co2, co3, co4);
- facetotvert[b] += 4;
- }
- else {
- facearea[b] += area_tri_v3(co1, co2, co3);
- facetotvert[b] += 3;
- }
- }
- }
-
- for (a = 0; a < totorigface; a++)
- if (facetotvert[a] > 0)
- mul_v3_fl(facecenter[a], 1.0f / facetotvert[a]);
-
- /* for conversion from BU area / pixel area to reference screen size */
- BKE_mesh_texspace_get(me, 0, 0, size);
- fac = ((size[0] + size[1] + size[2]) / 3.0f) / part->simplify_refsize;
- fac = fac * fac;
-
- powrate = log(0.5f) / log(part->simplify_rate * 0.5f);
- if (part->simplify_flag & PART_SIMPLIFY_VIEWPORT)
- vprate = pow(1.0f - part->simplify_viewport, 5.0);
- else
- vprate = 1.0;
-
- /* set simplification parameters per original face */
- for (a = 0, elem = elems; a < totorigface; a++, elem++) {
- area = psys_render_projected_area(ctx->sim.psys, facecenter[a], facearea[a], vprate, &viewport);
- arearatio = fac * area / facearea[a];
-
- if ((arearatio < 1.0f || viewport < 1.0f) && elem->totchild) {
- /* lambda is percentage of elements to keep */
- lambda = (arearatio < 1.0f) ? powf(arearatio, powrate) : 1.0f;
- lambda *= viewport;
-
- lambda = MAX2(lambda, 1.0f / elem->totchild);
-
- /* compute transition region */
- t = part->simplify_transition;
- elem->t = (lambda - t < 0.0f) ? lambda : (lambda + t > 1.0f) ? 1.0f - lambda : t;
- elem->reduce = 1;
-
- /* scale at end and beginning of the transition region */
- elem->scalemax = (lambda + t < 1.0f) ? 1.0f / lambda : 1.0f / (1.0f - elem->t * elem->t / t);
- elem->scalemin = (lambda + t < 1.0f) ? 0.0f : elem->scalemax * (1.0f - elem->t / t);
-
- elem->scalemin = sqrtf(elem->scalemin);
- elem->scalemax = sqrtf(elem->scalemax);
-
- /* clamp scaling */
- scaleclamp = (float)min_ii(elem->totchild, 10);
- elem->scalemin = MIN2(scaleclamp, elem->scalemin);
- elem->scalemax = MIN2(scaleclamp, elem->scalemax);
-
- /* extend lambda to include transition */
- lambda = lambda + elem->t;
- if (lambda > 1.0f)
- lambda = 1.0f;
- }
- else {
- lambda = arearatio;
-
- elem->scalemax = 1.0f; //sqrt(lambda);
- elem->scalemin = 1.0f; //sqrt(lambda);
- elem->reduce = 0;
- }
-
- elem->lambda = lambda;
- elem->scalemin = sqrtf(elem->scalemin);
- elem->scalemax = sqrtf(elem->scalemax);
- elem->curchild = 0;
- }
-
- MEM_freeN(facearea);
- MEM_freeN(facecenter);
- MEM_freeN(facetotvert);
-
- /* move indices and set random number skipping */
- ctx->skip = MEM_callocN(sizeof(int) * tot, "SimplificationSkip");
-
- skipped = 0;
- for (a = 0, newtot = 0; a < tot; a++) {
- b = (index_mf_to_mpoly) ? DM_origindex_mface_mpoly(index_mf_to_mpoly, index_mp_to_orig, ctx->index[a]) : ctx->index[a];
-
- if (b != ORIGINDEX_NONE) {
- if (elems[b].curchild++ < ceil(elems[b].lambda * elems[b].totchild)) {
- ctx->index[newtot] = ctx->index[a];
- ctx->skip[newtot] = skipped;
- skipped = 0;
- newtot++;
- }
- else skipped++;
- }
- else skipped++;
- }
-
- for (a = 0, elem = elems; a < totorigface; a++, elem++)
- elem->curchild = 0;
-
- return newtot;
-}
-
bool psys_render_simplify_params(ParticleSystem *psys, ChildParticle *cpa, float *params)
{
ParticleRenderData *data;
@@ -981,14 +722,14 @@ bool psys_render_simplify_params(ParticleSystem *psys, ChildParticle *cpa, float
int b;
if (!(psys->renderdata && (psys->part->simplify_flag & PART_SIMPLIFY_ENABLE)))
- return 0;
+ return false;
data = psys->renderdata;
if (!data->do_simplify)
- return 0;
+ return false;
b = (data->index_mf_to_mpoly) ? DM_origindex_mface_mpoly(data->index_mf_to_mpoly, data->index_mp_to_orig, cpa->num) : cpa->num;
if (b == ORIGINDEX_NONE) {
- return 0;
+ return false;
}
elem = &data->elems[b];
@@ -1043,7 +784,7 @@ static float interpolate_particle_value(float v1, float v2, float v3, float v4,
return value;
}
-void psys_interpolate_particle(short type, ParticleKey keys[4], float dt, ParticleKey *result, int velocity)
+void psys_interpolate_particle(short type, ParticleKey keys[4], float dt, ParticleKey *result, bool velocity)
{
float t[4];
@@ -1073,7 +814,6 @@ void psys_interpolate_particle(short type, ParticleKey keys[4], float dt, Partic
}
-
typedef struct ParticleInterpolationData {
HairKey *hkey[2];
@@ -1400,9 +1140,9 @@ static void interpolate_pathcache(ParticleCacheKey *first, float t, ParticleCach
ParticleCacheKey *cur = first;
/* scale the requested time to fit the entire path even if the path is cut early */
- t *= (first + first->steps)->time;
+ t *= (first + first->segments)->time;
- while (i < first->steps && cur->time < t)
+ while (i < first->segments && cur->time < t)
cur++;
if (cur->time == t)
@@ -1569,12 +1309,13 @@ void psys_interpolate_uvs(const MTFace *tface, int quad, const float w[4], float
void psys_interpolate_mcol(const MCol *mcol, int quad, const float w[4], MCol *mc)
{
- char *cp, *cp1, *cp2, *cp3, *cp4;
+ const char *cp1, *cp2, *cp3, *cp4;
+ char *cp;
cp = (char *)mc;
- cp1 = (char *)&mcol[0];
- cp2 = (char *)&mcol[1];
- cp3 = (char *)&mcol[2];
+ cp1 = (const char *)&mcol[0];
+ cp2 = (const char *)&mcol[1];
+ cp3 = (const char *)&mcol[2];
if (quad) {
cp4 = (char *)&mcol[3];
@@ -1906,6 +1647,42 @@ static void psys_particle_on_shape(int UNUSED(distr), int UNUSED(index),
/************************************************/
/* Particles on emitter */
/************************************************/
+
+CustomDataMask psys_emitter_customdata_mask(ParticleSystem *psys)
+{
+ CustomDataMask dataMask = 0;
+ MTex *mtex;
+ int i;
+
+ if (!psys->part)
+ return 0;
+
+ for (i = 0; i < MAX_MTEX; i++) {
+ mtex = psys->part->mtex[i];
+ if (mtex && mtex->mapto && (mtex->texco & TEXCO_UV))
+ dataMask |= CD_MASK_MTFACE;
+ }
+
+ if (psys->part->tanfac != 0.0f)
+ dataMask |= CD_MASK_MTFACE;
+
+ /* ask for vertexgroups if we need them */
+ for (i = 0; i < PSYS_TOT_VG; i++) {
+ if (psys->vgroup[i]) {
+ dataMask |= CD_MASK_MDEFORMVERT;
+ break;
+ }
+ }
+
+ /* particles only need this if they are after a non deform modifier, and
+ * the modifier stack will only create them in that case. */
+ dataMask |= CD_MASK_ORIGSPACE_MLOOP | CD_MASK_ORIGINDEX;
+
+ dataMask |= CD_MASK_ORCO;
+
+ return dataMask;
+}
+
void psys_particle_on_emitter(ParticleSystemModifierData *psmd, int from, int index, int index_dmcache,
float fuv[4], float foffset, float vec[3], float nor[3], float utan[3], float vtan[3],
float orco[3], float ornor[3])
@@ -1930,202 +1707,11 @@ void psys_particle_on_emitter(ParticleSystemModifierData *psmd, int from, int in
/* Path Cache */
/************************************************/
-static void do_kink(ParticleKey *state, ParticleKey *par, float *par_rot, float time, float freq, float shape, float amplitude, float flat, short type, short axis, float obmat[4][4], int smooth_start)
-{
- float kink[3] = {1.f, 0.f, 0.f}, par_vec[3], q1[4] = {1.f, 0.f, 0.f, 0.f};
- float t, dt = 1.f, result[3];
-
- if (par == NULL || type == PART_KINK_NO)
- return;
-
- CLAMP(time, 0.f, 1.f);
-
- if (shape != 0.0f && type != PART_KINK_BRAID) {
- if (shape < 0.0f)
- time = (float)pow(time, 1.f + shape);
- else
- time = (float)pow(time, 1.f / (1.f - shape));
- }
-
- t = time * freq * (float)M_PI;
-
- if (smooth_start) {
- dt = fabsf(t);
- /* smooth the beginning of kink */
- CLAMP(dt, 0.f, (float)M_PI);
- dt = sinf(dt / 2.f);
- }
-
- if (type != PART_KINK_RADIAL) {
- float temp[3];
-
- kink[axis] = 1.f;
-
- if (obmat)
- mul_mat3_m4_v3(obmat, kink);
-
- if (par_rot)
- mul_qt_v3(par_rot, kink);
-
- /* make sure kink is normal to strand */
- project_v3_v3v3(temp, kink, par->vel);
- sub_v3_v3(kink, temp);
- normalize_v3(kink);
- }
-
- copy_v3_v3(result, state->co);
- sub_v3_v3v3(par_vec, par->co, state->co);
+extern void do_kink(ParticleKey *state, const float par_co[3], const float par_vel[3], const float par_rot[4], float time, float freq, float shape, float amplitude, float flat,
+ short type, short axis, float obmat[4][4], int smooth_start);
+extern float do_clump(ParticleKey *state, const float par_co[3], float time, const float orco_offset[3], float clumpfac, float clumppow, float pa_clump,
+ bool use_clump_noise, float clump_noise_size, CurveMapping *clumpcurve);
- switch (type) {
- case PART_KINK_CURL:
- {
- negate_v3(par_vec);
-
- if (flat > 0.f) {
- float proj[3];
- project_v3_v3v3(proj, par_vec, par->vel);
- madd_v3_v3fl(par_vec, proj, -flat);
-
- project_v3_v3v3(proj, par_vec, kink);
- madd_v3_v3fl(par_vec, proj, -flat);
- }
-
- axis_angle_to_quat(q1, kink, (float)M_PI / 2.f);
-
- mul_qt_v3(q1, par_vec);
-
- madd_v3_v3fl(par_vec, kink, amplitude);
-
- /* rotate kink vector around strand tangent */
- if (t != 0.f) {
- axis_angle_to_quat(q1, par->vel, t);
- mul_qt_v3(q1, par_vec);
- }
-
- add_v3_v3v3(result, par->co, par_vec);
- break;
- }
- case PART_KINK_RADIAL:
- {
- if (flat > 0.f) {
- float proj[3];
- /* flatten along strand */
- project_v3_v3v3(proj, par_vec, par->vel);
- madd_v3_v3fl(result, proj, flat);
- }
-
- madd_v3_v3fl(result, par_vec, -amplitude * sinf(t));
- break;
- }
- case PART_KINK_WAVE:
- {
- madd_v3_v3fl(result, kink, amplitude * sinf(t));
-
- if (flat > 0.f) {
- float proj[3];
- /* flatten along wave */
- project_v3_v3v3(proj, par_vec, kink);
- madd_v3_v3fl(result, proj, flat);
-
- /* flatten along strand */
- project_v3_v3v3(proj, par_vec, par->vel);
- madd_v3_v3fl(result, proj, flat);
- }
- break;
- }
- case PART_KINK_BRAID:
- {
- float y_vec[3] = {0.f, 1.f, 0.f};
- float z_vec[3] = {0.f, 0.f, 1.f};
- float vec_one[3], state_co[3];
- float inp_y, inp_z, length;
-
- if (par_rot) {
- mul_qt_v3(par_rot, y_vec);
- mul_qt_v3(par_rot, z_vec);
- }
-
- negate_v3(par_vec);
- normalize_v3_v3(vec_one, par_vec);
-
- inp_y = dot_v3v3(y_vec, vec_one);
- inp_z = dot_v3v3(z_vec, vec_one);
-
- if (inp_y > 0.5f) {
- copy_v3_v3(state_co, y_vec);
-
- mul_v3_fl(y_vec, amplitude * cosf(t));
- mul_v3_fl(z_vec, amplitude / 2.f * sinf(2.f * t));
- }
- else if (inp_z > 0.0f) {
- mul_v3_v3fl(state_co, z_vec, sinf((float)M_PI / 3.f));
- madd_v3_v3fl(state_co, y_vec, -0.5f);
-
- mul_v3_fl(y_vec, -amplitude * cosf(t + (float)M_PI / 3.f));
- mul_v3_fl(z_vec, amplitude / 2.f * cosf(2.f * t + (float)M_PI / 6.f));
- }
- else {
- mul_v3_v3fl(state_co, z_vec, -sinf((float)M_PI / 3.f));
- madd_v3_v3fl(state_co, y_vec, -0.5f);
-
- mul_v3_fl(y_vec, amplitude * -sinf(t + (float)M_PI / 6.f));
- mul_v3_fl(z_vec, amplitude / 2.f * -sinf(2.f * t + (float)M_PI / 3.f));
- }
-
- mul_v3_fl(state_co, amplitude);
- add_v3_v3(state_co, par->co);
- sub_v3_v3v3(par_vec, state->co, state_co);
-
- length = normalize_v3(par_vec);
- mul_v3_fl(par_vec, MIN2(length, amplitude / 2.f));
-
- add_v3_v3v3(state_co, par->co, y_vec);
- add_v3_v3(state_co, z_vec);
- add_v3_v3(state_co, par_vec);
-
- shape = 2.f * (float)M_PI * (1.f + shape);
-
- if (t < shape) {
- shape = t / shape;
- shape = (float)sqrt((double)shape);
- interp_v3_v3v3(result, result, state_co, shape);
- }
- else {
- copy_v3_v3(result, state_co);
- }
- break;
- }
- }
-
- /* blend the start of the kink */
- if (dt < 1.f)
- interp_v3_v3v3(state->co, state->co, result, dt);
- else
- copy_v3_v3(state->co, result);
-}
-
-static float do_clump(ParticleKey *state, ParticleKey *par, float time, float clumpfac, float clumppow, float pa_clump)
-{
- float clump = 0.f;
-
- if (par && clumpfac != 0.0f) {
- float cpow;
-
- if (clumppow < 0.0f)
- cpow = 1.0f + clumppow;
- else
- cpow = 1.0f + 9.0f * clumppow;
-
- if (clumpfac < 0.0f) /* clump roots instead of tips */
- clump = -clumpfac * pa_clump * (float)pow(1.0 - (double)time, (double)cpow);
- else
- clump = clumpfac * pa_clump * (float)pow((double)time, (double)cpow);
-
- interp_v3_v3v3(state->co, state->co, par->co, clump);
- }
-
- return clump;
-}
void precalc_guides(ParticleSimulationData *sim, ListBase *effectors)
{
EffectedPoint point;
@@ -2166,12 +1752,14 @@ void precalc_guides(ParticleSimulationData *sim, ListBase *effectors)
}
}
}
-int do_guides(ListBase *effectors, ParticleKey *state, int index, float time)
+
+int do_guides(ParticleSettings *part, ListBase *effectors, ParticleKey *state, int index, float time)
{
+ CurveMapping *clumpcurve = (part->child_flag & PART_CHILD_USE_CLUMP_CURVE) ? part->clumpcurve : NULL;
+ CurveMapping *roughcurve = (part->child_flag & PART_CHILD_USE_ROUGH_CURVE) ? part->roughcurve : NULL;
EffectorCache *eff;
PartDeflect *pd;
Curve *cu;
- ParticleKey key, par;
GuideEffectorData *data;
float effect[3] = {0.0f, 0.0f, 0.0f}, veffect[3] = {0.0f, 0.0f, 0.0f};
@@ -2180,78 +1768,92 @@ int do_guides(ListBase *effectors, ParticleKey *state, int index, float time)
float vec_to_point[3];
if (effectors) for (eff = effectors->first; eff; eff = eff->next) {
- pd = eff->pd;
-
- if (pd->forcefield != PFIELD_GUIDE)
- continue;
-
- data = eff->guide_data + index;
-
- if (data->strength <= 0.0f)
- continue;
-
- guidetime = time / (1.0f - pd->free_end);
-
- if (guidetime > 1.0f)
- continue;
-
- cu = (Curve *)eff->ob->data;
-
- if (pd->flag & PFIELD_GUIDE_PATH_ADD) {
- if (where_on_path(eff->ob, data->strength * guidetime, guidevec, guidedir, NULL, &radius, &weight) == 0)
- return 0;
- }
- else {
- if (where_on_path(eff->ob, guidetime, guidevec, guidedir, NULL, &radius, &weight) == 0)
- return 0;
- }
-
- mul_m4_v3(eff->ob->obmat, guidevec);
- mul_mat3_m4_v3(eff->ob->obmat, guidedir);
-
- normalize_v3(guidedir);
-
- copy_v3_v3(vec_to_point, data->vec_to_point);
-
- if (guidetime != 0.0f) {
- /* curve direction */
- cross_v3_v3v3(temp, eff->guide_dir, guidedir);
- angle = dot_v3v3(eff->guide_dir, guidedir) / (len_v3(eff->guide_dir));
- angle = saacos(angle);
- axis_angle_to_quat(rot2, temp, angle);
- mul_qt_v3(rot2, vec_to_point);
-
- /* curve tilt */
- axis_angle_to_quat(rot2, guidedir, guidevec[3] - eff->guide_loc[3]);
- mul_qt_v3(rot2, vec_to_point);
- }
-
- /* curve taper */
- if (cu->taperobj)
- mul_v3_fl(vec_to_point, BKE_displist_calc_taper(eff->scene, cu->taperobj, (int)(data->strength * guidetime * 100.0f), 100));
-
- else { /* curve size*/
- if (cu->flag & CU_PATH_RADIUS) {
- mul_v3_fl(vec_to_point, radius);
- }
+ pd = eff->pd;
+
+ if (pd->forcefield != PFIELD_GUIDE)
+ continue;
+
+ data = eff->guide_data + index;
+
+ if (data->strength <= 0.0f)
+ continue;
+
+ guidetime = time / (1.0f - pd->free_end);
+
+ if (guidetime > 1.0f)
+ continue;
+
+ cu = (Curve *)eff->ob->data;
+
+ if (pd->flag & PFIELD_GUIDE_PATH_ADD) {
+ if (where_on_path(eff->ob, data->strength * guidetime, guidevec, guidedir, NULL, &radius, &weight) == 0)
+ return 0;
+ }
+ else {
+ if (where_on_path(eff->ob, guidetime, guidevec, guidedir, NULL, &radius, &weight) == 0)
+ return 0;
+ }
+
+ mul_m4_v3(eff->ob->obmat, guidevec);
+ mul_mat3_m4_v3(eff->ob->obmat, guidedir);
+
+ normalize_v3(guidedir);
+
+ copy_v3_v3(vec_to_point, data->vec_to_point);
+
+ if (guidetime != 0.0f) {
+ /* curve direction */
+ cross_v3_v3v3(temp, eff->guide_dir, guidedir);
+ angle = dot_v3v3(eff->guide_dir, guidedir) / (len_v3(eff->guide_dir));
+ angle = saacos(angle);
+ axis_angle_to_quat(rot2, temp, angle);
+ mul_qt_v3(rot2, vec_to_point);
+
+ /* curve tilt */
+ axis_angle_to_quat(rot2, guidedir, guidevec[3] - eff->guide_loc[3]);
+ mul_qt_v3(rot2, vec_to_point);
+ }
+
+ /* curve taper */
+ if (cu->taperobj)
+ mul_v3_fl(vec_to_point, BKE_displist_calc_taper(eff->scene, cu->taperobj, (int)(data->strength * guidetime * 100.0f), 100));
+
+ else { /* curve size*/
+ if (cu->flag & CU_PATH_RADIUS) {
+ mul_v3_fl(vec_to_point, radius);
}
- par.co[0] = par.co[1] = par.co[2] = 0.0f;
+ }
+
+ if (clumpcurve)
+ curvemapping_changed_all(clumpcurve);
+ if (roughcurve)
+ curvemapping_changed_all(roughcurve);
+
+ {
+ ParticleKey key;
+ float par_co[3] = {0.0f, 0.0f, 0.0f};
+ float par_vel[3] = {0.0f, 0.0f, 0.0f};
+ float par_rot[4] = {1.0f, 0.0f, 0.0f, 0.0f};
+ float orco_offset[3] = {0.0f, 0.0f, 0.0f};
+
copy_v3_v3(key.co, vec_to_point);
- do_kink(&key, &par, 0, guidetime, pd->kink_freq, pd->kink_shape, pd->kink_amp, 0.f, pd->kink, pd->kink_axis, 0, 0);
- do_clump(&key, &par, guidetime, pd->clump_fac, pd->clump_pow, 1.0f);
+ do_kink(&key, par_co, par_vel, par_rot, guidetime, pd->kink_freq, pd->kink_shape, pd->kink_amp, 0.f, pd->kink, pd->kink_axis, 0, 0);
+ do_clump(&key, par_co, guidetime, orco_offset, pd->clump_fac, pd->clump_pow, 1.0f,
+ part->child_flag & PART_CHILD_USE_CLUMP_NOISE, part->clump_noise_size, clumpcurve);
copy_v3_v3(vec_to_point, key.co);
-
- add_v3_v3(vec_to_point, guidevec);
-
- //sub_v3_v3v3(pa_loc, pa_loc, pa_zero);
- madd_v3_v3fl(effect, vec_to_point, data->strength);
- madd_v3_v3fl(veffect, guidedir, data->strength);
- totstrength += data->strength;
-
- if (pd->flag & PFIELD_GUIDE_PATH_WEIGHT)
- totstrength *= weight;
}
-
+
+ add_v3_v3(vec_to_point, guidevec);
+
+ //sub_v3_v3v3(pa_loc, pa_loc, pa_zero);
+ madd_v3_v3fl(effect, vec_to_point, data->strength);
+ madd_v3_v3fl(veffect, guidedir, data->strength);
+ totstrength += data->strength;
+
+ if (pd->flag & PFIELD_GUIDE_PATH_WEIGHT)
+ totstrength *= weight;
+ }
+
if (totstrength != 0.0f) {
if (totstrength > 1.0f)
mul_v3_fl(effect, 1.0f / totstrength);
@@ -2266,41 +1868,7 @@ int do_guides(ListBase *effectors, ParticleKey *state, int index, float time)
}
return 0;
}
-static void do_rough(float *loc, float mat[4][4], float t, float fac, float size, float thres, ParticleKey *state)
-{
- float rough[3];
- float rco[3];
-
- if (thres != 0.0f) {
- if (fabsf((float)(-1.5f + loc[0] + loc[1] + loc[2])) < 1.5f * thres) {
- return;
- }
- }
-
- copy_v3_v3(rco, loc);
- mul_v3_fl(rco, t);
- rough[0] = -1.0f + 2.0f * BLI_gTurbulence(size, rco[0], rco[1], rco[2], 2, 0, 2);
- rough[1] = -1.0f + 2.0f * BLI_gTurbulence(size, rco[1], rco[2], rco[0], 2, 0, 2);
- rough[2] = -1.0f + 2.0f * BLI_gTurbulence(size, rco[2], rco[0], rco[1], 2, 0, 2);
-
- madd_v3_v3fl(state->co, mat[0], fac * rough[0]);
- madd_v3_v3fl(state->co, mat[1], fac * rough[1]);
- madd_v3_v3fl(state->co, mat[2], fac * rough[2]);
-}
-static void do_rough_end(float *loc, float mat[4][4], float t, float fac, float shape, ParticleKey *state)
-{
- float rough[2];
- float roughfac;
-
- roughfac = fac * (float)pow((double)t, shape);
- copy_v2_v2(rough, loc);
- rough[0] = -1.0f + 2.0f * rough[0];
- rough[1] = -1.0f + 2.0f * rough[1];
- mul_v2_fl(rough, roughfac);
- madd_v3_v3fl(state->co, mat[0], rough[0]);
- madd_v3_v3fl(state->co, mat[1], rough[1]);
-}
static void do_path_effectors(ParticleSimulationData *sim, int i, ParticleCacheKey *ca, int k, int steps, float *UNUSED(rootco), float effector, float UNUSED(dfra), float UNUSED(cfra), float *length, float *vec)
{
float force[3] = {0.0f, 0.0f, 0.0f};
@@ -2332,20 +1900,6 @@ static void do_path_effectors(ParticleSimulationData *sim, int i, ParticleCacheK
if (k < steps)
*length = len_v3(vec);
}
-static int check_path_length(int k, ParticleCacheKey *keys, ParticleCacheKey *state, float max_length, float *cur_length, float length, float *dvec)
-{
- if (*cur_length + length > max_length) {
- mul_v3_fl(dvec, (max_length - *cur_length) / length);
- add_v3_v3v3(state->co, (state - 1)->co, dvec);
- keys->steps = k;
- /* something over the maximum step value */
- return k = 100000;
- }
- else {
- *cur_length += length;
- return k;
- }
-}
static void offset_child(ChildParticle *cpa, ParticleKey *par, float *par_rot, ParticleKey *child, float flat, float radius)
{
copy_v3_v3(child->co, cpa->fuv);
@@ -2391,9 +1945,11 @@ float *psys_cache_vgroup(DerivedMesh *dm, ParticleSystem *psys, int vgroup)
}
void psys_find_parents(ParticleSimulationData *sim)
{
+ ParticleSystem *psys = sim->psys;
ParticleSettings *part = sim->psys->part;
KDTree *tree;
ChildParticle *cpa;
+ ParticleTexture ptex;
int p, totparent, totchild = sim->psys->totchild;
float co[3], orco[3];
int from = PART_FROM_FACE;
@@ -2411,7 +1967,13 @@ void psys_find_parents(ParticleSimulationData *sim)
for (p = 0, cpa = sim->psys->child; p < totparent; p++, cpa++) {
psys_particle_on_emitter(sim->psmd, from, cpa->num, DMCACHE_ISCHILD, cpa->fuv, cpa->foffset, co, 0, 0, 0, orco, 0);
- BLI_kdtree_insert(tree, p, orco);
+
+ /* Check if particle doesn't exist because of texture influence. Insert only existing particles into kdtree. */
+ get_cpa_texture(sim->psmd->dm, psys, part, psys->particles + cpa->pa[0], p, cpa->num, cpa->fuv, orco, &ptex, PAMAP_DENS | PAMAP_CHILD, psys->cfra);
+
+ if (ptex.exist >= psys_frand(psys, p + 24)) {
+ BLI_kdtree_insert(tree, p, orco);
+ }
}
BLI_kdtree_balance(tree);
@@ -2424,58 +1986,24 @@ void psys_find_parents(ParticleSimulationData *sim)
BLI_kdtree_free(tree);
}
-static void get_strand_normal(Material *ma, const float surfnor[3], float surfdist, float nor[3])
+static bool psys_thread_context_init_path(ParticleThreadContext *ctx, ParticleSimulationData *sim, Scene *scene, float cfra, int editupdate)
{
- float cross[3], nstrand[3], vnor[3], blend;
-
- if (!((ma->mode & MA_STR_SURFDIFF) || (ma->strand_surfnor > 0.0f)))
- return;
-
- if (ma->mode & MA_STR_SURFDIFF) {
- cross_v3_v3v3(cross, surfnor, nor);
- cross_v3_v3v3(nstrand, nor, cross);
-
- blend = dot_v3v3(nstrand, surfnor);
- CLAMP(blend, 0.0f, 1.0f);
-
- interp_v3_v3v3(vnor, nstrand, surfnor, blend);
- normalize_v3(vnor);
- }
- else {
- copy_v3_v3(vnor, nor);
- }
-
- if (ma->strand_surfnor > 0.0f) {
- if (ma->strand_surfnor > surfdist) {
- blend = (ma->strand_surfnor - surfdist) / ma->strand_surfnor;
- interp_v3_v3v3(vnor, vnor, surfnor, blend);
- normalize_v3(vnor);
- }
- }
-
- copy_v3_v3(nor, vnor);
-}
-
-static int psys_threads_init_path(ParticleThread *threads, Scene *scene, float cfra, int editupdate)
-{
- ParticleThreadContext *ctx = threads[0].ctx;
-/* Object *ob = ctx->sim.ob; */
- ParticleSystem *psys = ctx->sim.psys;
+ ParticleSystem *psys = sim->psys;
ParticleSettings *part = psys->part;
-/* ParticleEditSettings *pset = &scene->toolsettings->particle; */
int totparent = 0, between = 0;
- int steps = (int)pow(2.0, (double)part->draw_step);
+ int segments = 1 << part->draw_step;
int totchild = psys->totchild;
- int i, seed, totthread = threads[0].tot;
+
+ psys_thread_context_init(ctx, sim);
/*---start figuring out what is actually wanted---*/
if (psys_in_edit_mode(scene, psys)) {
ParticleEditSettings *pset = &scene->toolsettings->particle;
- if (psys->renderdata == 0 && (psys->edit == NULL || pset->flag & PE_DRAW_PART) == 0)
+ if ((psys->renderdata == 0 && G.is_rendering == 0) && (psys->edit == NULL || pset->flag & PE_DRAW_PART) == 0)
totchild = 0;
- steps = (int)pow(2.0, (double)pset->draw_step);
+ segments = 1 << pset->draw_step;
}
if (totchild && part->childtype == PART_CHILD_FACES) {
@@ -2488,29 +2016,23 @@ static int psys_threads_init_path(ParticleThread *threads, Scene *scene, float c
between = 1;
}
- if (psys->renderdata)
- steps = (int)pow(2.0, (double)part->ren_step);
+ if (psys->renderdata || G.is_rendering)
+ segments = 1 << part->ren_step;
else {
totchild = (int)((float)totchild * (float)part->disp / 100.0f);
totparent = MIN2(totparent, totchild);
}
- if (totchild == 0) return 0;
-
- /* init random number generator */
- seed = 31415926 + ctx->sim.psys->seed;
-
- if (ctx->editupdate || totchild < 10000)
- totthread = 1;
-
- for (i = 0; i < totthread; i++) {
- threads[i].rng_path = BLI_rng_new(seed);
- threads[i].tot = totthread;
- }
+ if (totchild == 0)
+ return false;
/* fill context values */
ctx->between = between;
- ctx->steps = steps;
+ ctx->segments = segments;
+ if (ELEM(part->kink, PART_KINK_SPIRAL))
+ ctx->extra_segments = max_ii(part->kink_extra_steps, 1);
+ else
+ ctx->extra_segments = 0;
ctx->totchild = totchild;
ctx->totparent = totparent;
ctx->parent_pass = 0;
@@ -2529,31 +2051,36 @@ static int psys_threads_init_path(ParticleThread *threads, Scene *scene, float c
if (psys->part->flag & PART_CHILD_EFFECT)
ctx->vg_effector = psys_cache_vgroup(ctx->dm, psys, PSYS_VG_EFFECTOR);
- /* set correct ipo timing */
-#if 0 // XXX old animation system
- if (part->flag & PART_ABS_TIME && part->ipo) {
- calc_ipo(part->ipo, cfra);
- execute_ipo((ID *)part, part->ipo);
- }
-#endif // XXX old animation system
+ /* prepare curvemapping tables */
+ if ((part->child_flag & PART_CHILD_USE_CLUMP_CURVE) && part->clumpcurve)
+ curvemapping_changed_all(part->clumpcurve);
+ if ((part->child_flag & PART_CHILD_USE_ROUGH_CURVE) && part->roughcurve)
+ curvemapping_changed_all(part->roughcurve);
- return 1;
+ return true;
+}
+
+static void psys_task_init_path(ParticleTask *task, ParticleSimulationData *sim)
+{
+ /* init random number generator */
+ int seed = 31415926 + sim->psys->seed;
+
+ task->rng_path = BLI_rng_new(seed);
}
/* note: this function must be thread safe, except for branching! */
-static void psys_thread_create_path(ParticleThread *thread, struct ChildParticle *cpa, ParticleCacheKey *child_keys, int i)
+static void psys_thread_create_path(ParticleTask *task, struct ChildParticle *cpa, ParticleCacheKey *child_keys, int i)
{
- ParticleThreadContext *ctx = thread->ctx;
+ ParticleThreadContext *ctx = task->ctx;
Object *ob = ctx->sim.ob;
ParticleSystem *psys = ctx->sim.psys;
ParticleSettings *part = psys->part;
ParticleCacheKey **cache = psys->childcache;
- ParticleCacheKey **pcache = psys_in_edit_mode(ctx->sim.scene, psys) ? psys->edit->pathcache : psys->pathcache;
- ParticleCacheKey *child, *par = NULL, *key[4];
+ ParticleCacheKey **pcache = psys_in_edit_mode(ctx->sim.scene, psys) && psys->edit ? psys->edit->pathcache : psys->pathcache;
+ ParticleCacheKey *child, *key[4];
ParticleTexture ptex;
float *cpa_fuv = 0, *par_rot = 0, rot[4];
- float orco[3], ornor[3], hairmat[4][4], t, dvec[3], off1[4][3], off2[4][3];
- float length, max_length = 1.0f, cur_length = 0.0f;
+ float orco[3], ornor[3], hairmat[4][4], dvec[3], off1[4][3], off2[4][3];
float eff_length, eff_vec[3], weight[4];
int k, cpa_num;
short cpa_from;
@@ -2585,7 +2112,7 @@ static void psys_thread_create_path(ParticleThread *thread, struct ChildParticle
if (!needupdate)
return;
else
- memset(child_keys, 0, sizeof(*child_keys) * (ctx->steps + 1));
+ memset(child_keys, 0, sizeof(*child_keys) * (ctx->segments + 1));
}
/* get parent paths */
@@ -2608,14 +2135,14 @@ static void psys_thread_create_path(ParticleThread *thread, struct ChildParticle
if (part->flag & PART_CHILD_LONG_HAIR) {
/* For long hair use tip distance/root distance as parting factor instead of root to tip angle. */
float d1 = len_v3v3(key[0]->co, key[w]->co);
- float d2 = len_v3v3((key[0] + key[0]->steps - 1)->co, (key[w] + key[w]->steps - 1)->co);
+ float d2 = len_v3v3((key[0] + key[0]->segments - 1)->co, (key[w] + key[w]->segments - 1)->co);
d = d1 > 0.f ? d2 / d1 - 1.f : 10000.f;
}
else {
float v1[3], v2[3];
- sub_v3_v3v3(v1, (key[0] + key[0]->steps - 1)->co, key[0]->co);
- sub_v3_v3v3(v2, (key[w] + key[w]->steps - 1)->co, key[w]->co);
+ sub_v3_v3v3(v1, (key[0] + key[0]->segments - 1)->co, key[0]->co);
+ sub_v3_v3v3(v2, (key[w] + key[w]->segments - 1)->co, key[w]->co);
normalize_v3(v1);
normalize_v3(v2);
@@ -2663,7 +2190,7 @@ static void psys_thread_create_path(ParticleThread *thread, struct ChildParticle
if (!(psys->edit->points[cpa->parent].flag & PEP_EDIT_RECALC))
return;
- memset(child_keys, 0, sizeof(*child_keys) * (ctx->steps + 1));
+ memset(child_keys, 0, sizeof(*child_keys) * (ctx->segments + 1));
}
/* get the parent path */
@@ -2682,18 +2209,18 @@ static void psys_thread_create_path(ParticleThread *thread, struct ChildParticle
psys_mat_hair_to_global(ob, ctx->sim.psmd->dm, psys->part->from, pa, hairmat);
}
- child_keys->steps = ctx->steps;
+ child_keys->segments = ctx->segments;
/* get different child parameters from textures & vgroups */
get_child_modifier_parameters(part, ctx, cpa, cpa_from, cpa_num, cpa_fuv, orco, &ptex);
if (ptex.exist < psys_frand(psys, i + 24)) {
- child_keys->steps = -1;
+ child_keys->segments = -1;
return;
}
/* create the child path */
- for (k = 0, child = child_keys; k <= ctx->steps; k++, child++) {
+ for (k = 0, child = child_keys; k <= ctx->segments; k++, child++) {
if (ctx->between) {
int w = 0;
@@ -2711,7 +2238,7 @@ static void psys_thread_create_path(ParticleThread *thread, struct ChildParticle
/* Fade the effect of rotation for even lengths in the end */
project_v3_v3v3(dvec, off2[w], (key[w] + k)->vel);
- madd_v3_v3fl(off2[w], dvec, -(float)k / (float)ctx->steps);
+ madd_v3_v3fl(off2[w], dvec, -(float)k / (float)ctx->segments);
}
add_v3_v3(off2[w], (key[w] + k)->co);
@@ -2735,14 +2262,14 @@ static void psys_thread_create_path(ParticleThread *thread, struct ChildParticle
offset_child(cpa, (ParticleKey *)(key[0] + k), par_rot, (ParticleKey *)child, part->childflat, part->childrad);
}
- child->time = (float)k / (float)ctx->steps;
+ child->time = (float)k / (float)ctx->segments;
}
/* apply effectors */
if (part->flag & PART_CHILD_EFFECT) {
- for (k = 0, child = child_keys; k <= ctx->steps; k++, child++) {
+ for (k = 0, child = child_keys; k <= ctx->segments; k++, child++) {
if (k) {
- do_path_effectors(&ctx->sim, cpa->pa[0], child, k, ctx->steps, child_keys->co, ptex.effector, 0.0f, ctx->cfra, &eff_length, eff_vec);
+ do_path_effectors(&ctx->sim, cpa->pa[0], child, k, ctx->segments, child_keys->co, ptex.effector, 0.0f, ctx->cfra, &eff_length, eff_vec);
}
else {
sub_v3_v3v3(eff_vec, (child + 1)->co, child->co);
@@ -2751,147 +2278,131 @@ static void psys_thread_create_path(ParticleThread *thread, struct ChildParticle
}
}
- for (k = 0, child = child_keys; k <= ctx->steps; k++, child++) {
- t = (float)k / (float)ctx->steps;
-
- if (ctx->totparent)
- /* this is now threadsafe, virtual parents are calculated before rest of children */
- par = (i >= ctx->totparent) ? cache[cpa->parent] : NULL;
- else if (cpa->parent >= 0)
- par = pcache[cpa->parent];
-
- if (par) {
- if (k) {
- mul_qt_qtqt(rot, (par + k)->rot, par->rot);
- par_rot = rot;
- }
- else {
- par_rot = par->rot;
+ {
+ ParticleData *pa = NULL;
+ ParticleCacheKey *par = NULL;
+ float par_co[3];
+ float par_orco[3];
+
+ if (ctx->totparent) {
+ if (i >= ctx->totparent) {
+ pa = &psys->particles[cpa->parent];
+ /* this is now threadsafe, virtual parents are calculated before rest of children */
+ BLI_assert(cpa->parent < psys->totchildcache);
+ par = cache[cpa->parent];
}
- par += k;
- }
-
- /* apply different deformations to the child path */
- do_child_modifiers(&ctx->sim, &ptex, (ParticleKey *)par, par_rot, cpa, orco, hairmat, (ParticleKey *)child, t);
-
- /* we have to correct velocity because of kink & clump */
- if (k > 1) {
- sub_v3_v3v3((child - 1)->vel, child->co, (child - 2)->co);
- mul_v3_fl((child - 1)->vel, 0.5);
-
- if (ctx->ma && (part->draw_col == PART_DRAW_COL_MAT))
- get_strand_normal(ctx->ma, ornor, cur_length, (child - 1)->vel);
}
+ else if (cpa->parent >= 0) {
+ pa = &psys->particles[cpa->parent];
+ par = pcache[cpa->parent];
- if (k == ctx->steps)
- sub_v3_v3v3(child->vel, child->co, (child - 1)->co);
+ /* If particle is unexisting, try to pick a viable parent from particles used for interpolation. */
+ for (k = 0; k < 4 && pa && (pa->flag & PARS_UNEXIST); k++) {
+ if (cpa->pa[k] >= 0) {
+ pa = &psys->particles[cpa->pa[k]];
+ par = pcache[cpa->pa[k]];
+ }
+ }
- /* check if path needs to be cut before actual end of data points */
- if (k) {
- sub_v3_v3v3(dvec, child->co, (child - 1)->co);
- length = 1.0f / (float)ctx->steps;
- k = check_path_length(k, child_keys, child, max_length, &cur_length, length, dvec);
+ if (pa->flag & PARS_UNEXIST) pa = NULL;
}
- else {
- /* initialize length calculation */
- max_length = ptex.length;
- cur_length = 0.0f;
- }
-
- if (ctx->ma && (part->draw_col == PART_DRAW_COL_MAT)) {
- copy_v3_v3(child->col, &ctx->ma->r);
- get_strand_normal(ctx->ma, ornor, cur_length, child->vel);
+
+ if (pa) {
+ ListBase modifiers;
+ BLI_listbase_clear(&modifiers);
+
+ psys_particle_on_emitter(ctx->sim.psmd, part->from, pa->num, pa->num_dmcache, pa->fuv, pa->foffset,
+ par_co, NULL, NULL, NULL, par_orco, NULL);
+
+ psys_apply_child_modifiers(ctx, &modifiers, cpa, &ptex, orco, ornor, hairmat, child_keys, par, par_orco);
}
+ else
+ zero_v3(par_orco);
}
/* Hide virtual parents */
if (i < ctx->totparent)
- child_keys->steps = -1;
+ child_keys->segments = -1;
}
-static void *exec_child_path_cache(void *data)
+static void exec_child_path_cache(TaskPool *UNUSED(pool), void *taskdata, int UNUSED(threadid))
{
- ParticleThread *thread = (ParticleThread *)data;
- ParticleThreadContext *ctx = thread->ctx;
+ ParticleTask *task = taskdata;
+ ParticleThreadContext *ctx = task->ctx;
ParticleSystem *psys = ctx->sim.psys;
ParticleCacheKey **cache = psys->childcache;
ChildParticle *cpa;
- int i, totchild = ctx->totchild, first = 0;
+ int i;
- if (thread->tot > 1) {
- first = ctx->parent_pass ? 0 : ctx->totparent;
- totchild = ctx->parent_pass ? ctx->totparent : ctx->totchild;
+ cpa = psys->child + task->begin;
+ for (i = task->begin; i < task->end; ++i, ++cpa) {
+ BLI_assert(i < psys->totchildcache);
+ psys_thread_create_path(task, cpa, cache[i], i);
}
-
- cpa = psys->child + first + thread->num;
- for (i = first + thread->num; i < totchild; i += thread->tot, cpa += thread->tot)
- psys_thread_create_path(thread, cpa, cache[i], i);
-
- return 0;
}
void psys_cache_child_paths(ParticleSimulationData *sim, float cfra, int editupdate)
{
- ParticleThread *pthreads;
- ParticleThreadContext *ctx;
- ListBase threads;
- int i, totchild, totparent, totthread;
-
+ TaskScheduler *task_scheduler;
+ TaskPool *task_pool;
+ ParticleThreadContext ctx;
+ ParticleTask *tasks_parent, *tasks_child;
+ int numtasks_parent, numtasks_child;
+ int i, totchild, totparent;
+
if (sim->psys->flag & PSYS_GLOBAL_HAIR)
return;
-
- pthreads = psys_threads_create(sim);
-
- if (!psys_threads_init_path(pthreads, sim->scene, cfra, editupdate)) {
- psys_threads_free(pthreads);
+
+ /* create a task pool for child path tasks */
+ if (!psys_thread_context_init_path(&ctx, sim, sim->scene, cfra, editupdate))
return;
- }
-
- ctx = pthreads[0].ctx;
- totchild = ctx->totchild;
- totparent = ctx->totparent;
-
+
+ task_scheduler = BLI_task_scheduler_get();
+ task_pool = BLI_task_pool_create(task_scheduler, &ctx);
+ totchild = ctx.totchild;
+ totparent = ctx.totparent;
+
if (editupdate && sim->psys->childcache && totchild == sim->psys->totchildcache) {
; /* just overwrite the existing cache */
}
else {
/* clear out old and create new empty path cache */
free_child_path_cache(sim->psys);
- sim->psys->childcache = psys_alloc_path_cache_buffers(&sim->psys->childcachebufs, totchild, ctx->steps + 1);
+
+ sim->psys->childcache = psys_alloc_path_cache_buffers(&sim->psys->childcachebufs, totchild, ctx.segments + ctx.extra_segments + 1);
sim->psys->totchildcache = totchild;
}
-
- totthread = pthreads[0].tot;
-
- if (totthread > 1) {
-
- /* make virtual child parents thread safe by calculating them first */
- if (totparent) {
- BLI_init_threads(&threads, exec_child_path_cache, totthread);
-
- for (i = 0; i < totthread; i++) {
- pthreads[i].ctx->parent_pass = 1;
- BLI_insert_thread(&threads, &pthreads[i]);
- }
-
- BLI_end_threads(&threads);
-
- for (i = 0; i < totthread; i++)
- pthreads[i].ctx->parent_pass = 0;
- }
-
- BLI_init_threads(&threads, exec_child_path_cache, totthread);
-
- for (i = 0; i < totthread; i++)
- BLI_insert_thread(&threads, &pthreads[i]);
-
- BLI_end_threads(&threads);
+
+ /* cache parent paths */
+ ctx.parent_pass = 1;
+ psys_tasks_create(&ctx, 0, totparent, &tasks_parent, &numtasks_parent);
+ for (i = 0; i < numtasks_parent; ++i) {
+ ParticleTask *task = &tasks_parent[i];
+
+ psys_task_init_path(task, sim);
+ BLI_task_pool_push(task_pool, exec_child_path_cache, task, false, TASK_PRIORITY_LOW);
}
- else
- exec_child_path_cache(&pthreads[0]);
+ BLI_task_pool_work_and_wait(task_pool);
+
+ /* cache child paths */
+ ctx.parent_pass = 0;
+ psys_tasks_create(&ctx, totparent, totchild, &tasks_child, &numtasks_child);
+ for (i = 0; i < numtasks_child; ++i) {
+ ParticleTask *task = &tasks_child[i];
+
+ psys_task_init_path(task, sim);
+ BLI_task_pool_push(task_pool, exec_child_path_cache, task, false, TASK_PRIORITY_LOW);
+ }
+ BLI_task_pool_work_and_wait(task_pool);
- psys_threads_free(pthreads);
+ BLI_task_pool_free(task_pool);
+
+ psys_tasks_free(tasks_parent, numtasks_parent);
+ psys_tasks_free(tasks_child, numtasks_child);
+
+ psys_thread_context_free(&ctx);
}
+
/* figure out incremental rotations along path starting from unit quat */
static void cache_key_incremental_rotation(ParticleCacheKey *key0, ParticleCacheKey *key1, ParticleCacheKey *key2, float *prev_tangent, int i)
{
@@ -2959,7 +2470,7 @@ void psys_cache_paths(ParticleSimulationData *sim, float cfra)
float prev_tangent[3] = {0.0f, 0.0f, 0.0f}, hairmat[4][4];
float rotmat[3][3];
int k;
- int steps = (int)pow(2.0, (double)(psys->renderdata ? part->ren_step : part->draw_step));
+ int segments = (int)pow(2.0, (double)((psys->renderdata || G.is_rendering) ? part->ren_step : part->draw_step));
int totpart = psys->totpart;
float length, vec[3];
float *vg_effector = NULL;
@@ -2979,7 +2490,7 @@ void psys_cache_paths(ParticleSimulationData *sim, float cfra)
/* clear out old and create new empty path cache */
psys_free_path_cache(psys, psys->edit);
- cache = psys->pathcache = psys_alloc_path_cache_buffers(&psys->pathcachebufs, totpart, steps + 1);
+ cache = psys->pathcache = psys_alloc_path_cache_buffers(&psys->pathcachebufs, totpart, segments + 1);
psys->lattice_deform_data = psys_create_lattice_deform_data(sim);
ma = give_current_material(sim->ob, psys->part->omat);
@@ -3000,7 +2511,7 @@ void psys_cache_paths(ParticleSimulationData *sim, float cfra)
}
/*---first main loop: create all actual particles' paths---*/
- LOOP_SHOWN_PARTICLES {
+ LOOP_PARTICLES {
if (!psys->totchild) {
psys_get_texture(sim, pa, &ptex, PAMAP_LENGTH, 0.f);
pa_length = ptex.length * (1.0f - part->randlength * psys_frand(psys, psys->seed + p));
@@ -3014,9 +2525,9 @@ void psys_cache_paths(ParticleSimulationData *sim, float cfra)
pind.bspline = (psys->part->flag & PART_HAIR_BSPLINE);
pind.dm = hair_dm;
- memset(cache[p], 0, sizeof(*cache[p]) * (steps + 1));
+ memset(cache[p], 0, sizeof(*cache[p]) * (segments + 1));
- cache[p]->steps = steps;
+ cache[p]->segments = segments;
/*--get the first data points--*/
init_particle_interpolation(sim->ob, sim->psys, pa, &pind);
@@ -3038,15 +2549,15 @@ void psys_cache_paths(ParticleSimulationData *sim, float cfra)
}
if (birthtime >= dietime) {
- cache[p]->steps = -1;
+ cache[p]->segments = -1;
continue;
}
dietime = birthtime + pa_length * (dietime - birthtime);
/*--interpolate actual path from data points--*/
- for (k = 0, ca = cache[p]; k <= steps; k++, ca++) {
- time = (float)k / (float)steps;
+ for (k = 0, ca = cache[p]; k <= segments; k++, ca++) {
+ time = (float)k / (float)segments;
t = birthtime + time * (dietime - birthtime);
result.time = -t;
do_particle_interpolation(psys, p, pa, t, &pind, &result);
@@ -3061,7 +2572,15 @@ void psys_cache_paths(ParticleSimulationData *sim, float cfra)
copy_v3_v3(ca->col, col);
}
-
+
+ if (part->type == PART_HAIR) {
+ HairKey *hkey;
+
+ for (k = 0, hkey = pa->hair; k < pa->totkey; ++k, ++hkey) {
+ mul_v3_m4v3(hkey->world_co, hairmat, hkey->co);
+ }
+ }
+
/*--modify paths and calculate rotation & velocity--*/
if (!(psys->flag & PSYS_GLOBAL_HAIR)) {
@@ -3074,29 +2593,29 @@ void psys_cache_paths(ParticleSimulationData *sim, float cfra)
sub_v3_v3v3(vec, (cache[p] + 1)->co, cache[p]->co);
length = len_v3(vec);
- for (k = 1, ca = cache[p] + 1; k <= steps; k++, ca++)
- do_path_effectors(sim, p, ca, k, steps, cache[p]->co, effector, dfra, cfra, &length, vec);
+ for (k = 1, ca = cache[p] + 1; k <= segments; k++, ca++)
+ do_path_effectors(sim, p, ca, k, segments, cache[p]->co, effector, dfra, cfra, &length, vec);
}
/* apply guide curves to path data */
if (sim->psys->effectors && (psys->part->flag & PART_CHILD_EFFECT) == 0) {
- for (k = 0, ca = cache[p]; k <= steps; k++, ca++)
+ for (k = 0, ca = cache[p]; k <= segments; k++, ca++)
/* ca is safe to cast, since only co and vel are used */
- do_guides(sim->psys->effectors, (ParticleKey *)ca, p, (float)k / (float)steps);
+ do_guides(sim->psys->part, sim->psys->effectors, (ParticleKey *)ca, p, (float)k / (float)segments);
}
/* lattices have to be calculated separately to avoid mixups between effector calculations */
if (psys->lattice_deform_data) {
- for (k = 0, ca = cache[p]; k <= steps; k++, ca++)
+ for (k = 0, ca = cache[p]; k <= segments; k++, ca++)
calc_latt_deform(psys->lattice_deform_data, ca->co, 1.0f);
}
}
/* finally do rotation & velocity */
- for (k = 1, ca = cache[p] + 1; k <= steps; k++, ca++) {
+ for (k = 1, ca = cache[p] + 1; k <= segments; k++, ca++) {
cache_key_incremental_rotation(ca, ca - 1, ca - 2, prev_tangent, k);
- if (k == steps)
+ if (k == segments)
copy_qt_qt(ca->rot, (ca - 1)->rot);
/* set velocity */
@@ -3105,7 +2624,7 @@ void psys_cache_paths(ParticleSimulationData *sim, float cfra)
if (k == 1)
copy_v3_v3((ca - 1)->vel, ca->vel);
- ca->time = (float)k / (float)steps;
+ ca->time = (float)k / (float)segments;
}
/* First rotation is based on emitting face orientation.
* This is way better than having flipping rotations resulting
@@ -3149,17 +2668,17 @@ void psys_cache_edit_paths(Scene *scene, Object *ob, PTCacheEdit *edit, float cf
float t, time = 0.0f, keytime = 0.0f /*, frs_sec */;
float hairmat[4][4], rotmat[3][3], prev_tangent[3] = {0.0f, 0.0f, 0.0f};
int k, i;
- int steps = (int)pow(2.0, (double)pset->draw_step);
+ int segments = 1 << pset->draw_step;
int totpart = edit->totpoint, recalc_set = 0;
float sel_col[3];
float nosel_col[3];
- steps = MAX2(steps, 4);
+ segments = MAX2(segments, 4);
if (!cache || edit->totpoint != edit->totcached) {
/* clear out old and create new empty path cache */
psys_free_path_cache(edit->psys, edit);
- cache = edit->pathcache = psys_alloc_path_cache_buffers(&edit->pathcachebufs, totpart, steps + 1);
+ cache = edit->pathcache = psys_alloc_path_cache_buffers(&edit->pathcachebufs, totpart, segments + 1);
/* set flag for update (child particles check this too) */
for (i = 0, point = edit->points; i < totpart; i++, point++)
@@ -3206,9 +2725,9 @@ void psys_cache_edit_paths(Scene *scene, Object *ob, PTCacheEdit *edit, float cf
}
- memset(cache[i], 0, sizeof(*cache[i]) * (steps + 1));
+ memset(cache[i], 0, sizeof(*cache[i]) * (segments + 1));
- cache[i]->steps = steps;
+ cache[i]->segments = segments;
/*--get the first data points--*/
init_particle_interpolation(ob, psys, pa, &pind);
@@ -3224,13 +2743,13 @@ void psys_cache_edit_paths(Scene *scene, Object *ob, PTCacheEdit *edit, float cf
dietime = pind.dietime;
if (birthtime >= dietime) {
- cache[i]->steps = -1;
+ cache[i]->segments = -1;
continue;
}
/*--interpolate actual path from data points--*/
- for (k = 0, ca = cache[i]; k <= steps; k++, ca++) {
- time = (float)k / (float)steps;
+ for (k = 0, ca = cache[i]; k <= segments; k++, ca++) {
+ time = (float)k / (float)segments;
t = birthtime + time * (dietime - birthtime);
result.time = -t;
do_particle_interpolation(psys, i, pa, t, &pind, &result);
@@ -3243,7 +2762,7 @@ void psys_cache_edit_paths(Scene *scene, Object *ob, PTCacheEdit *edit, float cf
if (k) {
cache_key_incremental_rotation(ca, ca - 1, ca - 2, prev_tangent, k);
- if (k == steps)
+ if (k == segments)
copy_qt_qt(ca->rot, (ca - 1)->rot);
/* set velocity */
@@ -3277,7 +2796,7 @@ void psys_cache_edit_paths(Scene *scene, Object *ob, PTCacheEdit *edit, float cf
/* at the moment this is only used for weight painting.
* will need to move out of this check if its used elsewhere. */
- t2 = birthtime + ((float)k / (float)steps) * (dietime - birthtime);
+ t2 = birthtime + ((float)k / (float)segments) * (dietime - birthtime);
while (pind.hkey[1]->time < t2) pind.hkey[1]++;
pind.hkey[0] = pind.hkey[1] - 1;
@@ -3514,8 +3033,8 @@ ModifierData *object_add_particle_system(Scene *scene, Object *ob, const char *n
psys->part = psys_new_settings(DATA_("ParticleSettings"), NULL);
- if (BLI_countlist(&ob->particlesystem) > 1)
- BLI_snprintf(psys->name, sizeof(psys->name), DATA_("ParticleSystem %i"), BLI_countlist(&ob->particlesystem));
+ if (BLI_listbase_count_ex(&ob->particlesystem, 2) > 1)
+ BLI_snprintf(psys->name, sizeof(psys->name), DATA_("ParticleSystem %i"), BLI_listbase_count(&ob->particlesystem));
else
BLI_strncpy(psys->name, DATA_("ParticleSystem"), sizeof(psys->name));
@@ -3524,7 +3043,7 @@ ModifierData *object_add_particle_system(Scene *scene, Object *ob, const char *n
if (name)
BLI_strncpy_utf8(md->name, name, sizeof(md->name));
else
- BLI_snprintf(md->name, sizeof(md->name), DATA_("ParticleSystem %i"), BLI_countlist(&ob->particlesystem));
+ BLI_snprintf(md->name, sizeof(md->name), DATA_("ParticleSystem %i"), BLI_listbase_count(&ob->particlesystem));
modifier_unique_name(&ob->modifiers, md);
psmd = (ParticleSystemModifierData *) md;
@@ -3581,6 +3100,7 @@ void object_remove_particle_system(Scene *UNUSED(scene), Object *ob)
DAG_relations_tag_update(G.main);
DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
}
+
static void default_particle_settings(ParticleSettings *part)
{
part->type = PART_EMITTER;
@@ -3611,6 +3131,8 @@ static void default_particle_settings(ParticleSettings *part)
part->adapt_pix = 3;
part->kink_axis = 2;
part->kink_amp_clump = 1.f;
+ part->kink_extra_steps = 4;
+ part->clump_noise_size = 1.0f;
part->reactevent = PART_EVENT_DEATH;
part->disp = 100;
part->from = PART_FROM_FACE;
@@ -3678,6 +3200,30 @@ ParticleSettings *psys_new_settings(const char *name, Main *main)
return part;
}
+void BKE_particlesettings_clump_curve_init(ParticleSettings *part)
+{
+ CurveMapping *cumap = curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f);
+
+ cumap->cm[0].curve[0].x = 0.0f;
+ cumap->cm[0].curve[0].y = 1.0f;
+ cumap->cm[0].curve[1].x = 1.0f;
+ cumap->cm[0].curve[1].y = 1.0f;
+
+ part->clumpcurve = cumap;
+}
+
+void BKE_particlesettings_rough_curve_init(ParticleSettings *part)
+{
+ CurveMapping *cumap = curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f);
+
+ cumap->cm[0].curve[0].x = 0.0f;
+ cumap->cm[0].curve[0].y = 1.0f;
+ cumap->cm[0].curve[1].x = 1.0f;
+ cumap->cm[0].curve[1].y = 1.0f;
+
+ part->roughcurve = cumap;
+}
+
ParticleSettings *BKE_particlesettings_copy(ParticleSettings *part)
{
ParticleSettings *partn;
@@ -3689,6 +3235,11 @@ ParticleSettings *BKE_particlesettings_copy(ParticleSettings *part)
partn->effector_weights = MEM_dupallocN(part->effector_weights);
partn->fluid = MEM_dupallocN(part->fluid);
+ if (part->clumpcurve)
+ partn->clumpcurve = curvemapping_copy(part->clumpcurve);
+ if (part->roughcurve)
+ partn->roughcurve = curvemapping_copy(part->roughcurve);
+
partn->boids = boid_copy_settings(part->boids);
for (a = 0; a < MAX_MTEX; a++) {
@@ -3701,6 +3252,10 @@ ParticleSettings *BKE_particlesettings_copy(ParticleSettings *part)
BLI_duplicatelist(&partn->dupliweights, &part->dupliweights);
+ if (part->id.lib) {
+ BKE_id_lib_local_paths(G.main, part->id.lib, &partn->id);
+ }
+
return partn;
}
@@ -3836,7 +3391,7 @@ static void get_cpa_texture(DerivedMesh *dm, ParticleSystem *psys, ParticleSetti
float value, rgba[4], texvec[3];
ptex->ivel = ptex->life = ptex->exist = ptex->size = ptex->damp =
- ptex->gravity = ptex->field = ptex->time = ptex->clump = ptex->kink =
+ ptex->gravity = ptex->field = ptex->time = ptex->clump = ptex->kink_freq = ptex->kink_amp =
ptex->effector = ptex->rough1 = ptex->rough2 = ptex->roughe = 1.0f;
ptex->length = 1.0f - part->randlength * psys_frand(psys, child_index + 26);
@@ -3876,21 +3431,23 @@ static void get_cpa_texture(DerivedMesh *dm, ParticleSystem *psys, ParticleSetti
break;
}
- externtex(mtex, texvec, &value, rgba, rgba + 1, rgba + 2, rgba + 3, 0, NULL);
+ externtex(mtex, texvec, &value, rgba, rgba + 1, rgba + 2, rgba + 3, 0, NULL, false);
if ((event & mtex->mapto) & PAMAP_ROUGH)
ptex->rough1 = ptex->rough2 = ptex->roughe = texture_value_blend(def, ptex->rough1, value, mtex->roughfac, blend);
SET_PARTICLE_TEXTURE(PAMAP_LENGTH, ptex->length, mtex->lengthfac);
SET_PARTICLE_TEXTURE(PAMAP_CLUMP, ptex->clump, mtex->clumpfac);
- SET_PARTICLE_TEXTURE(PAMAP_KINK, ptex->kink, mtex->kinkfac);
+ SET_PARTICLE_TEXTURE(PAMAP_KINK_AMP, ptex->kink_amp, mtex->kinkampfac);
+ SET_PARTICLE_TEXTURE(PAMAP_KINK_FREQ, ptex->kink_freq, mtex->kinkfac);
SET_PARTICLE_TEXTURE(PAMAP_DENS, ptex->exist, mtex->padensfac);
}
}
CLAMP_PARTICLE_TEXTURE_POS(PAMAP_LENGTH, ptex->length);
CLAMP_PARTICLE_TEXTURE_POS(PAMAP_CLUMP, ptex->clump);
- CLAMP_PARTICLE_TEXTURE_POS(PAMAP_KINK, ptex->kink);
+ CLAMP_PARTICLE_TEXTURE_POS(PAMAP_KINK_AMP, ptex->kink_amp);
+ CLAMP_PARTICLE_TEXTURE_POS(PAMAP_KINK_FREQ, ptex->kink_freq);
CLAMP_PARTICLE_TEXTURE_POS(PAMAP_ROUGH, ptex->rough1);
CLAMP_PARTICLE_TEXTURE_POS(PAMAP_DENS, ptex->exist);
}
@@ -3907,7 +3464,7 @@ void psys_get_texture(ParticleSimulationData *sim, ParticleData *pa, ParticleTex
/* initialize ptex */
ptex->ivel = ptex->life = ptex->exist = ptex->size = ptex->damp =
- ptex->gravity = ptex->field = ptex->length = ptex->clump = ptex->kink =
+ ptex->gravity = ptex->field = ptex->length = ptex->clump = ptex->kink_freq = ptex->kink_amp =
ptex->effector = ptex->rough1 = ptex->rough2 = ptex->roughe = 1.0f;
ptex->time = (float)(pa - sim->psys->particles) / (float)sim->psys->totpart;
@@ -3957,7 +3514,7 @@ void psys_get_texture(ParticleSimulationData *sim, ParticleData *pa, ParticleTex
break;
}
- externtex(mtex, texvec, &value, rgba, rgba + 1, rgba + 2, rgba + 3, 0, NULL);
+ externtex(mtex, texvec, &value, rgba, rgba + 1, rgba + 2, rgba + 3, 0, NULL, false);
if ((event & mtex->mapto) & PAMAP_TIME) {
/* the first time has to set the base value for time regardless of blend mode */
@@ -4061,7 +3618,7 @@ static void get_child_modifier_parameters(ParticleSettings *part, ParticleThread
if (ctx->vg_clump)
ptex->clump *= psys_interpolate_value_from_verts(ctx->dm, cpa_from, cpa_num, cpa_fuv, ctx->vg_clump);
if (ctx->vg_kink)
- ptex->kink *= psys_interpolate_value_from_verts(ctx->dm, cpa_from, cpa_num, cpa_fuv, ctx->vg_kink);
+ ptex->kink_freq *= psys_interpolate_value_from_verts(ctx->dm, cpa_from, cpa_num, cpa_fuv, ctx->vg_kink);
if (ctx->vg_rough1)
ptex->rough1 *= psys_interpolate_value_from_verts(ctx->dm, cpa_from, cpa_num, cpa_fuv, ctx->vg_rough1);
if (ctx->vg_rough2)
@@ -4071,55 +3628,6 @@ static void get_child_modifier_parameters(ParticleSettings *part, ParticleThread
if (ctx->vg_effector)
ptex->effector *= psys_interpolate_value_from_verts(ctx->dm, cpa_from, cpa_num, cpa_fuv, ctx->vg_effector);
}
-static void do_child_modifiers(ParticleSimulationData *sim, ParticleTexture *ptex, ParticleKey *par, float *par_rot, ChildParticle *cpa, float *orco, float mat[4][4], ParticleKey *state, float t)
-{
- ParticleSettings *part = sim->psys->part;
- int i = cpa - sim->psys->child;
- int guided = 0;
-
- float kink_freq = part->kink_freq;
- float rough1 = part->rough1;
- float rough2 = part->rough2;
- float rough_end = part->rough_end;
-
- if (ptex) {
- kink_freq *= ptex->kink;
- rough1 *= ptex->rough1;
- rough2 *= ptex->rough2;
- rough_end *= ptex->roughe;
- }
-
- if (part->flag & PART_CHILD_EFFECT)
- /* state is safe to cast, since only co and vel are used */
- guided = do_guides(sim->psys->effectors, (ParticleKey *)state, cpa->parent, t);
-
- if (guided == 0) {
- float clump = do_clump(state, par, t, part->clumpfac, part->clumppow, ptex ? ptex->clump : 1.f);
-
- if (kink_freq != 0.f) {
- float kink_amp = part->kink_amp * (1.f - part->kink_amp_clump * clump);
-
- do_kink(state, par, par_rot, t, kink_freq, part->kink_shape,
- kink_amp, part->kink_flat, part->kink, part->kink_axis,
- sim->ob->obmat, sim->psys->part->childtype == PART_CHILD_FACES);
- }
- }
-
- if (rough1 > 0.f)
- do_rough(orco, mat, t, rough1, part->rough1_size, 0.0, state);
-
- if (rough2 > 0.f) {
- float vec[3];
- psys_frand_vec(sim->psys, i + 27, vec);
- do_rough(vec, mat, t, rough2, part->rough2_size, part->rough2_thres, state);
- }
-
- if (rough_end > 0.f) {
- float vec[3];
- psys_frand_vec(sim->psys, i + 27, vec);
- do_rough_end(vec, mat, t, rough_end, part->rough_end_shape, state);
- }
-}
/* get's hair (or keyed) particles state at the "path time" specified in state->time */
void psys_get_particle_on_path(ParticleSimulationData *sim, int p, ParticleKey *state, const bool vel)
{
@@ -4186,7 +3694,7 @@ void psys_get_particle_on_path(ParticleSimulationData *sim, int p, ParticleKey *
mul_mat3_m4_v3(hairmat, state->vel);
if (sim->psys->effectors && (part->flag & PART_CHILD_GUIDE) == 0) {
- do_guides(sim->psys->effectors, state, p, state->time);
+ do_guides(sim->psys->part, sim->psys->effectors, state, p, state->time);
/* TODO: proper velocity handling */
}
@@ -4208,6 +3716,8 @@ void psys_get_particle_on_path(ParticleSimulationData *sim, int p, ParticleKey *
copy_qt_qt(state->rot, result.rot);
}
else {
+ float par_co[3], par_orco[3];
+
cpa = psys->child + p - totpart;
if (state->time < 0.0f)
@@ -4244,6 +3754,7 @@ void psys_get_particle_on_path(ParticleSimulationData *sim, int p, ParticleKey *
pa = psys->particles + cpa->parent;
+ psys_particle_on_emitter(psmd, part->from, pa->num, pa->num_dmcache, pa->fuv, pa->foffset, par_co, 0, 0, 0, par_orco, 0);
if (part->type == PART_HAIR)
psys_mat_hair_to_global(sim->ob, sim->psmd->dm, psys->part->from, pa, hairmat);
else
@@ -4263,8 +3774,7 @@ void psys_get_particle_on_path(ParticleSimulationData *sim, int p, ParticleKey *
cpa_num = pa->num;
cpa_fuv = pa->fuv;
-
-
+ psys_particle_on_emitter(psmd, part->from, pa->num, pa->num_dmcache, pa->fuv, pa->foffset, par_co, 0, 0, 0, par_orco, 0);
if (part->type == PART_HAIR) {
psys_particle_on_emitter(psmd, cpa_from, cpa_num, DMCACHE_ISCHILD, cpa_fuv, pa->foffset, co, 0, 0, 0, orco, 0);
psys_mat_hair_to_global(sim->ob, sim->psmd->dm, psys->part->from, pa, hairmat);
@@ -4322,7 +3832,7 @@ void psys_get_particle_on_path(ParticleSimulationData *sim, int p, ParticleKey *
copy_particle_key(&tstate, state, 1);
/* apply different deformations to the child path */
- do_child_modifiers(sim, &ptex, par, par->rot, cpa, orco, hairmat, state, t);
+ do_child_modifiers(sim, &ptex, par->co, par->vel, par->rot, par_orco, cpa, orco, hairmat, state, t);
/* try to estimate correct velocity */
if (vel) {
@@ -4417,6 +3927,7 @@ int psys_get_particle_state(ParticleSimulationData *sim, int p, ParticleKey *sta
float mat[4][4];
ParticleKey *key1;
float t = (cfra - pa->time) / pa->lifetime;
+ float par_orco[3] = {0.0f, 0.0f, 0.0f};
key1 = &pa->state;
offset_child(cpa, key1, key1->rot, state, part->childflat, part->childrad);
@@ -4424,7 +3935,7 @@ int psys_get_particle_state(ParticleSimulationData *sim, int p, ParticleKey *sta
CLAMP(t, 0.0f, 1.0f);
unit_m4(mat);
- do_child_modifiers(sim, NULL, key1, key1->rot, cpa, cpa->fuv, mat, state, t);
+ do_child_modifiers(sim, NULL, key1->co, key1->vel, key1->rot, par_orco, cpa, cpa->fuv, mat, state, t);
if (psys->lattice_deform_data)
calc_latt_deform(psys->lattice_deform_data, state->co, 1.0f);
@@ -4552,7 +4063,7 @@ void psys_get_dupli_path_transform(ParticleSimulationData *sim, ParticleData *pa
float loc[3], nor[3], vec[3], side[3], len;
float xvec[3] = {-1.0, 0.0, 0.0}, nmat[3][3];
- sub_v3_v3v3(vec, (cache + cache->steps)->co, cache->co);
+ sub_v3_v3v3(vec, (cache + cache->segments)->co, cache->co);
len = normalize_v3(vec);
if (pa == NULL && psys->part->childflat != PART_CHILD_FACES)
@@ -4564,14 +4075,13 @@ void psys_get_dupli_path_transform(ParticleSimulationData *sim, ParticleData *pa
psys_particle_on_emitter(psmd, PART_FROM_FACE, cpa->num, DMCACHE_ISCHILD, cpa->fuv, cpa->foffset, loc, nor, 0, 0, 0, 0);
if (psys->part->rotmode == PART_ROT_VEL) {
- copy_m3_m4(nmat, ob->imat);
- transpose_m3(nmat);
+ transpose_m3_m4(nmat, ob->imat);
mul_m3_v3(nmat, nor);
normalize_v3(nor);
/* make sure that we get a proper side vector */
- if (fabsf(dot_v3v3(nor, vec)) > 0.999999) {
- if (fabsf(dot_v3v3(nor, xvec)) > 0.999999) {
+ if (fabsf(dot_v3v3(nor, vec)) > 0.999999f) {
+ if (fabsf(dot_v3v3(nor, xvec)) > 0.999999f) {
nor[0] = 0.0f;
nor[1] = 1.0f;
nor[2] = 0.0f;
diff --git a/source/blender/blenkernel/intern/particle_child.c b/source/blender/blenkernel/intern/particle_child.c
new file mode 100644
index 00000000000..7b2e07ea96f
--- /dev/null
+++ b/source/blender/blenkernel/intern/particle_child.c
@@ -0,0 +1,732 @@
+/*
+ * ***** 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) Blender Foundation
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Lukas Toenne
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/blenkernel/intern/particle_child.c
+ * \ingroup bke
+ */
+
+#include "BLI_math.h"
+#include "BLI_noise.h"
+
+#include "DNA_material_types.h"
+
+#include "BKE_colortools.h"
+#include "BKE_particle.h"
+
+struct Material;
+
+void do_kink(ParticleKey *state, const float par_co[3], const float par_vel[3], const float par_rot[4], float time, float freq, float shape, float amplitude, float flat,
+ short type, short axis, float obmat[4][4], int smooth_start);
+float do_clump(ParticleKey *state, const float par_co[3], float time, const float orco_offset[3], float clumpfac, float clumppow, float pa_clump,
+ bool use_clump_noise, float clump_noise_size, CurveMapping *clumpcurve);
+void do_child_modifiers(ParticleSimulationData *sim,
+ ParticleTexture *ptex, const float par_co[3], const float par_vel[3], const float par_rot[4], const float par_orco[3],
+ ChildParticle *cpa, const float orco[3], float mat[4][4], ParticleKey *state, float t);
+
+static void get_strand_normal(Material *ma, const float surfnor[3], float surfdist, float nor[3])
+{
+ float cross[3], nstrand[3], vnor[3], blend;
+
+ if (!((ma->mode & MA_STR_SURFDIFF) || (ma->strand_surfnor > 0.0f)))
+ return;
+
+ if (ma->mode & MA_STR_SURFDIFF) {
+ cross_v3_v3v3(cross, surfnor, nor);
+ cross_v3_v3v3(nstrand, nor, cross);
+
+ blend = dot_v3v3(nstrand, surfnor);
+ CLAMP(blend, 0.0f, 1.0f);
+
+ interp_v3_v3v3(vnor, nstrand, surfnor, blend);
+ normalize_v3(vnor);
+ }
+ else {
+ copy_v3_v3(vnor, nor);
+ }
+
+ if (ma->strand_surfnor > 0.0f) {
+ if (ma->strand_surfnor > surfdist) {
+ blend = (ma->strand_surfnor - surfdist) / ma->strand_surfnor;
+ interp_v3_v3v3(vnor, vnor, surfnor, blend);
+ normalize_v3(vnor);
+ }
+ }
+
+ copy_v3_v3(nor, vnor);
+}
+
+/* ------------------------------------------------------------------------- */
+
+typedef struct ParticlePathIterator {
+ ParticleCacheKey *key;
+ int index;
+ float time;
+
+ ParticleCacheKey *parent_key;
+ float parent_rotation[4];
+} ParticlePathIterator;
+
+static void psys_path_iter_get(ParticlePathIterator *iter, ParticleCacheKey *keys, int totkeys,
+ ParticleCacheKey *parent, int index)
+{
+ BLI_assert(index >= 0 && index < totkeys);
+
+ iter->key = keys + index;
+ iter->index = index;
+ iter->time = (float)index / (float)(totkeys - 1);
+
+ if (parent) {
+ iter->parent_key = parent + index;
+ if (index > 0)
+ mul_qt_qtqt(iter->parent_rotation, iter->parent_key->rot, parent->rot);
+ else
+ copy_qt_qt(iter->parent_rotation, parent->rot);
+ }
+ else {
+ iter->parent_key = NULL;
+ unit_qt(iter->parent_rotation);
+ }
+}
+
+typedef struct ParticlePathModifier {
+ struct ParticlePathModifier *next, *prev;
+
+ void (*apply)(ParticleCacheKey *keys, int totkeys, ParticleCacheKey *parent_keys);
+} ParticlePathModifier;
+
+/* ------------------------------------------------------------------------- */
+
+static void do_kink_spiral_deform(ParticleKey *state, const float dir[3], const float kink[3],
+ float time, float freq, float shape, float amplitude,
+ const float spiral_start[3])
+{
+ float result[3];
+
+ CLAMP(time, 0.f, 1.f);
+
+ copy_v3_v3(result, state->co);
+
+ {
+ /* Creates a logarithmic spiral:
+ * r(theta) = a * exp(b * theta)
+ *
+ * The "density" parameter b is defined by the shape parameter
+ * and goes up to the Golden Spiral for 1.0
+ * http://en.wikipedia.org/wiki/Golden_spiral
+ */
+ const float b = shape * (1.0f + sqrtf(5.0f)) / (float)M_PI * 0.25f;
+ /* angle of the spiral against the curve (rotated opposite to make a smooth transition) */
+ const float start_angle = ((b != 0.0f) ? atanf(1.0f / b) :
+ (float)-M_PI_2) + (b > 0.0f ? -(float)M_PI_2 : (float)M_PI_2);
+
+ float spiral_axis[3], rot[3][3];
+ float vec[3];
+
+ float theta = freq * time * 2.0f * (float)M_PI;
+ float radius = amplitude * expf(b * theta);
+
+ /* a bit more intuitive than using negative frequency for this */
+ if (amplitude < 0.0f)
+ theta = -theta;
+
+ cross_v3_v3v3(spiral_axis, dir, kink);
+ normalize_v3(spiral_axis);
+
+ mul_v3_v3fl(vec, kink, -radius);
+
+ axis_angle_normalized_to_mat3(rot, spiral_axis, theta);
+ mul_m3_v3(rot, vec);
+
+ madd_v3_v3fl(vec, kink, amplitude);
+
+ axis_angle_normalized_to_mat3(rot, spiral_axis, -start_angle);
+ mul_m3_v3(rot, vec);
+
+ add_v3_v3v3(result, spiral_start, vec);
+ }
+
+ copy_v3_v3(state->co, result);
+}
+
+static void do_kink_spiral(ParticleThreadContext *ctx, ParticleTexture *ptex, const float parent_orco[3],
+ ChildParticle *cpa, const float orco[3], float hairmat[4][4],
+ ParticleCacheKey *keys, ParticleCacheKey *parent_keys, int *r_totkeys, float *r_max_length)
+{
+ struct ParticleSettings *part = ctx->sim.psys->part;
+ const int seed = ctx->sim.psys->child_seed + (int)(cpa - ctx->sim.psys->child);
+ const int totkeys = ctx->segments + 1;
+ const int extrakeys = ctx->extra_segments;
+
+ float kink_amp_random = part->kink_amp_random;
+ float kink_amp = part->kink_amp * (1.0f - kink_amp_random * psys_frand(ctx->sim.psys, 93541 + seed));
+ float kink_freq = part->kink_freq;
+ float kink_shape = part->kink_shape;
+ float kink_axis_random = part->kink_axis_random;
+ float rough1 = part->rough1;
+ float rough2 = part->rough2;
+ float rough_end = part->rough_end;
+
+ ParticlePathIterator iter;
+ ParticleCacheKey *key;
+ int k;
+
+ float dir[3];
+ float spiral_start[3] = {0.0f, 0.0f, 0.0f};
+ float spiral_start_time = 0.0f;
+ float spiral_par_co[3] = {0.0f, 0.0f, 0.0f};
+ float spiral_par_vel[3] = {0.0f, 0.0f, 0.0f};
+ float spiral_par_rot[4] = {1.0f, 0.0f, 0.0f, 0.0f};
+ float totlen;
+ float cut_time;
+ int start_index = 0, end_index = 0;
+ float kink_base[3];
+
+ if (ptex) {
+ kink_amp *= ptex->kink_amp;
+ kink_freq *= ptex->kink_freq;
+ rough1 *= ptex->rough1;
+ rough2 *= ptex->rough2;
+ rough_end *= ptex->roughe;
+ }
+
+ cut_time = (totkeys - 1) * ptex->length;
+ zero_v3(spiral_start);
+
+ for (k = 0, key = keys; k < totkeys-1; k++, key++) {
+ if ((float)(k + 1) >= cut_time) {
+ float fac = cut_time - (float)k;
+ ParticleCacheKey *par = parent_keys + k;
+
+ start_index = k + 1;
+ end_index = start_index + extrakeys;
+
+ spiral_start_time = ((float)k + fac) / (float)(totkeys - 1);
+ interp_v3_v3v3(spiral_start, key->co, (key+1)->co, fac);
+
+ interp_v3_v3v3(spiral_par_co, par->co, (par+1)->co, fac);
+ interp_v3_v3v3(spiral_par_vel, par->vel, (par+1)->vel, fac);
+ interp_qt_qtqt(spiral_par_rot, par->rot, (par+1)->rot, fac);
+
+ break;
+ }
+ }
+
+ zero_v3(dir);
+
+ zero_v3(kink_base);
+ kink_base[part->kink_axis] = 1.0f;
+ mul_mat3_m4_v3(ctx->sim.ob->obmat, kink_base);
+
+ for (k = 0, key = keys; k < end_index; k++, key++) {
+ float par_time;
+ float *par_co, *par_vel, *par_rot;
+
+ psys_path_iter_get(&iter, keys, end_index, NULL, k);
+ if (k < start_index) {
+ sub_v3_v3v3(dir, (key+1)->co, key->co);
+ normalize_v3(dir);
+
+ par_time = (float)k / (float)(totkeys - 1);
+ par_co = parent_keys[k].co;
+ par_vel = parent_keys[k].vel;
+ par_rot = parent_keys[k].rot;
+ }
+ else {
+ float spiral_time = (float)(k - start_index) / (float)(extrakeys-1);
+ float kink[3], tmp[3];
+
+ /* use same time value for every point on the spiral */
+ par_time = spiral_start_time;
+ par_co = spiral_par_co;
+ par_vel = spiral_par_vel;
+ par_rot = spiral_par_rot;
+
+ project_v3_v3v3(tmp, kink_base, dir);
+ sub_v3_v3v3(kink, kink_base, tmp);
+ normalize_v3(kink);
+
+ if (kink_axis_random > 0.0f) {
+ float a = kink_axis_random * (psys_frand(ctx->sim.psys, 7112 + seed) * 2.0f - 1.0f) * (float)M_PI;
+ float rot[3][3];
+
+ axis_angle_normalized_to_mat3(rot, dir, a);
+ mul_m3_v3(rot, kink);
+ }
+
+ do_kink_spiral_deform((ParticleKey *)key, dir, kink, spiral_time, kink_freq, kink_shape, kink_amp, spiral_start);
+ }
+
+ /* apply different deformations to the child path */
+ do_child_modifiers(&ctx->sim, ptex, par_co, par_vel, par_rot, parent_orco, cpa, orco, hairmat, (ParticleKey *)key, par_time);
+ }
+
+ totlen = 0.0f;
+ for (k = 0, key = keys; k < end_index-1; k++, key++)
+ totlen += len_v3v3((key+1)->co, key->co);
+
+ *r_totkeys = end_index;
+ *r_max_length = totlen;
+}
+
+/* ------------------------------------------------------------------------- */
+
+static bool check_path_length(int k, ParticleCacheKey *keys, ParticleCacheKey *key, float max_length, float step_length, float *cur_length, float dvec[3])
+{
+ if (*cur_length + step_length > max_length) {
+ sub_v3_v3v3(dvec, key->co, (key-1)->co);
+ mul_v3_fl(dvec, (max_length - *cur_length) / step_length);
+ add_v3_v3v3(key->co, (key-1)->co, dvec);
+ keys->segments = k;
+ /* something over the maximum step value */
+ return false;
+ }
+ else {
+ *cur_length += step_length;
+ return true;
+ }
+}
+
+void psys_apply_child_modifiers(ParticleThreadContext *ctx, struct ListBase *modifiers,
+ ChildParticle *cpa, ParticleTexture *ptex, const float orco[3], const float ornor[3], float hairmat[4][4],
+ ParticleCacheKey *keys, ParticleCacheKey *parent_keys, const float parent_orco[3])
+{
+ struct ParticleSettings *part = ctx->sim.psys->part;
+ struct Material *ma = ctx->ma;
+ const bool draw_col_ma = (part->draw_col == PART_DRAW_COL_MAT);
+ const bool use_length_check = !ELEM(part->kink, PART_KINK_SPIRAL);
+
+ ParticlePathModifier *mod;
+ ParticleCacheKey *key;
+ int totkeys, k;
+ float max_length;
+
+#if 0 /* TODO for the future: use true particle modifiers that work on the whole curve */
+ for (mod = modifiers->first; mod; mod = mod->next) {
+ mod->apply(keys, totkeys, parent_keys);
+ }
+#else
+ (void)modifiers;
+ (void)mod;
+
+ if (part->kink == PART_KINK_SPIRAL) {
+ do_kink_spiral(ctx, ptex, parent_orco, cpa, orco, hairmat, keys, parent_keys, &totkeys, &max_length);
+ keys->segments = totkeys - 1;
+ }
+ else {
+ ParticlePathIterator iter;
+
+ totkeys = ctx->segments + 1;
+ max_length = ptex->length;
+
+ for (k = 0, key = keys; k < totkeys; k++, key++) {
+ ParticleKey *par;
+
+ psys_path_iter_get(&iter, keys, totkeys, parent_keys, k);
+ par = (ParticleKey *)iter.parent_key;
+
+ /* apply different deformations to the child path */
+ do_child_modifiers(&ctx->sim, ptex, par->co, par->vel, iter.parent_rotation, parent_orco, cpa, orco, hairmat, (ParticleKey *)key, iter.time);
+ }
+ }
+
+ {
+ const float step_length = 1.0f / (float)(totkeys - 1);
+
+ float cur_length = 0.0f;
+
+ /* we have to correct velocity because of kink & clump */
+ for (k = 0, key = keys; k < totkeys; ++k, ++key) {
+ if (k >= 2) {
+ sub_v3_v3v3((key-1)->vel, key->co, (key-2)->co);
+ mul_v3_fl((key-1)->vel, 0.5);
+
+ if (ma && draw_col_ma)
+ get_strand_normal(ma, ornor, cur_length, (key-1)->vel);
+ }
+
+ if (use_length_check && k > 1) {
+ float dvec[3];
+ /* check if path needs to be cut before actual end of data points */
+ if (!check_path_length(k, keys, key, max_length, step_length, &cur_length, dvec)) {
+ /* last key */
+ sub_v3_v3v3(key->vel, key->co, (key-1)->co);
+ if (ma && draw_col_ma) {
+ copy_v3_v3(key->col, &ma->r);
+ }
+ break;
+ }
+ }
+ if (k == totkeys-1) {
+ /* last key */
+ sub_v3_v3v3(key->vel, key->co, (key-1)->co);
+ }
+
+ if (ma && draw_col_ma) {
+ copy_v3_v3(key->col, &ma->r);
+ get_strand_normal(ma, ornor, cur_length, key->vel);
+ }
+ }
+ }
+#endif
+}
+
+/* ------------------------------------------------------------------------- */
+
+void do_kink(ParticleKey *state, const float par_co[3], const float par_vel[3], const float par_rot[4], float time, float freq, float shape,
+ float amplitude, float flat, short type, short axis, float obmat[4][4], int smooth_start)
+{
+ float kink[3] = {1.f, 0.f, 0.f}, par_vec[3], q1[4] = {1.f, 0.f, 0.f, 0.f};
+ float t, dt = 1.f, result[3];
+
+ if (ELEM(type, PART_KINK_NO, PART_KINK_SPIRAL))
+ return;
+
+ CLAMP(time, 0.f, 1.f);
+
+ if (shape != 0.0f && !ELEM(type, PART_KINK_BRAID)) {
+ if (shape < 0.0f)
+ time = (float)pow(time, 1.f + shape);
+ else
+ time = (float)pow(time, 1.f / (1.f - shape));
+ }
+
+ t = time * freq * (float)M_PI;
+
+ if (smooth_start) {
+ dt = fabsf(t);
+ /* smooth the beginning of kink */
+ CLAMP(dt, 0.f, (float)M_PI);
+ dt = sinf(dt / 2.f);
+ }
+
+ if (!ELEM(type, PART_KINK_RADIAL)) {
+ float temp[3];
+
+ kink[axis] = 1.f;
+
+ if (obmat)
+ mul_mat3_m4_v3(obmat, kink);
+
+ mul_qt_v3(par_rot, kink);
+
+ /* make sure kink is normal to strand */
+ project_v3_v3v3(temp, kink, par_vel);
+ sub_v3_v3(kink, temp);
+ normalize_v3(kink);
+ }
+
+ copy_v3_v3(result, state->co);
+ sub_v3_v3v3(par_vec, par_co, state->co);
+
+ switch (type) {
+ case PART_KINK_CURL:
+ {
+ float curl_offset[3];
+
+ /* rotate kink vector around strand tangent */
+ mul_v3_v3fl(curl_offset, kink, amplitude);
+ axis_angle_to_quat(q1, par_vel, t);
+ mul_qt_v3(q1, curl_offset);
+
+ interp_v3_v3v3(par_vec, state->co, par_co, flat);
+ add_v3_v3v3(result, par_vec, curl_offset);
+ break;
+ }
+ case PART_KINK_RADIAL:
+ {
+ if (flat > 0.f) {
+ float proj[3];
+ /* flatten along strand */
+ project_v3_v3v3(proj, par_vec, par_vel);
+ madd_v3_v3fl(result, proj, flat);
+ }
+
+ madd_v3_v3fl(result, par_vec, -amplitude * sinf(t));
+ break;
+ }
+ case PART_KINK_WAVE:
+ {
+ madd_v3_v3fl(result, kink, amplitude * sinf(t));
+
+ if (flat > 0.f) {
+ float proj[3];
+ /* flatten along wave */
+ project_v3_v3v3(proj, par_vec, kink);
+ madd_v3_v3fl(result, proj, flat);
+
+ /* flatten along strand */
+ project_v3_v3v3(proj, par_vec, par_vel);
+ madd_v3_v3fl(result, proj, flat);
+ }
+ break;
+ }
+ case PART_KINK_BRAID:
+ {
+ float y_vec[3] = {0.f, 1.f, 0.f};
+ float z_vec[3] = {0.f, 0.f, 1.f};
+ float vec_one[3], state_co[3];
+ float inp_y, inp_z, length;
+
+ if (par_rot) {
+ mul_qt_v3(par_rot, y_vec);
+ mul_qt_v3(par_rot, z_vec);
+ }
+
+ negate_v3(par_vec);
+ normalize_v3_v3(vec_one, par_vec);
+
+ inp_y = dot_v3v3(y_vec, vec_one);
+ inp_z = dot_v3v3(z_vec, vec_one);
+
+ if (inp_y > 0.5f) {
+ copy_v3_v3(state_co, y_vec);
+
+ mul_v3_fl(y_vec, amplitude * cosf(t));
+ mul_v3_fl(z_vec, amplitude / 2.f * sinf(2.f * t));
+ }
+ else if (inp_z > 0.0f) {
+ mul_v3_v3fl(state_co, z_vec, sinf((float)M_PI / 3.f));
+ madd_v3_v3fl(state_co, y_vec, -0.5f);
+
+ mul_v3_fl(y_vec, -amplitude * cosf(t + (float)M_PI / 3.f));
+ mul_v3_fl(z_vec, amplitude / 2.f * cosf(2.f * t + (float)M_PI / 6.f));
+ }
+ else {
+ mul_v3_v3fl(state_co, z_vec, -sinf((float)M_PI / 3.f));
+ madd_v3_v3fl(state_co, y_vec, -0.5f);
+
+ mul_v3_fl(y_vec, amplitude * -sinf(t + (float)M_PI / 6.f));
+ mul_v3_fl(z_vec, amplitude / 2.f * -sinf(2.f * t + (float)M_PI / 3.f));
+ }
+
+ mul_v3_fl(state_co, amplitude);
+ add_v3_v3(state_co, par_co);
+ sub_v3_v3v3(par_vec, state->co, state_co);
+
+ length = normalize_v3(par_vec);
+ mul_v3_fl(par_vec, MIN2(length, amplitude / 2.f));
+
+ add_v3_v3v3(state_co, par_co, y_vec);
+ add_v3_v3(state_co, z_vec);
+ add_v3_v3(state_co, par_vec);
+
+ shape = 2.f * (float)M_PI * (1.f + shape);
+
+ if (t < shape) {
+ shape = t / shape;
+ shape = (float)sqrt((double)shape);
+ interp_v3_v3v3(result, result, state_co, shape);
+ }
+ else {
+ copy_v3_v3(result, state_co);
+ }
+ break;
+ }
+ }
+
+ /* blend the start of the kink */
+ if (dt < 1.f)
+ interp_v3_v3v3(state->co, state->co, result, dt);
+ else
+ copy_v3_v3(state->co, result);
+}
+
+static float do_clump_level(float result[3], const float co[3], const float par_co[3], float time,
+ float clumpfac, float clumppow, float pa_clump, CurveMapping *clumpcurve)
+{
+ float clump = 0.0f;
+
+ if (clumpcurve) {
+ clump = pa_clump * (1.0f - CLAMPIS(curvemapping_evaluateF(clumpcurve, 0, time), 0.0f, 1.0f));
+
+ interp_v3_v3v3(result, co, par_co, clump);
+ }
+ else if (clumpfac != 0.0f) {
+ float cpow;
+
+ if (clumppow < 0.0f)
+ cpow = 1.0f + clumppow;
+ else
+ cpow = 1.0f + 9.0f * clumppow;
+
+ if (clumpfac < 0.0f) /* clump roots instead of tips */
+ clump = -clumpfac * pa_clump * (float)pow(1.0 - (double)time, (double)cpow);
+ else
+ clump = clumpfac * pa_clump * (float)pow((double)time, (double)cpow);
+
+ interp_v3_v3v3(result, co, par_co, clump);
+ }
+
+ return clump;
+}
+
+float do_clump(ParticleKey *state, const float par_co[3], float time, const float orco_offset[3], float clumpfac, float clumppow, float pa_clump,
+ bool use_clump_noise, float clump_noise_size, CurveMapping *clumpcurve)
+{
+ float clump;
+
+ if (use_clump_noise && clump_noise_size != 0.0f) {
+ float center[3], noisevec[3];
+ float da[4], pa[12];
+
+ mul_v3_v3fl(noisevec, orco_offset, 1.0f / clump_noise_size);
+ voronoi(noisevec[0], noisevec[1], noisevec[2], da, pa, 1.0f, 0);
+ mul_v3_fl(&pa[0], clump_noise_size);
+ add_v3_v3v3(center, par_co, &pa[0]);
+
+ do_clump_level(state->co, state->co, center, time, clumpfac, clumppow, pa_clump, clumpcurve);
+ }
+
+ clump = do_clump_level(state->co, state->co, par_co, time, clumpfac, clumppow, pa_clump, clumpcurve);
+
+ return clump;
+}
+
+static void do_rough(const float loc[3], float mat[4][4], float t, float fac, float size, float thres, ParticleKey *state)
+{
+ float rough[3];
+ float rco[3];
+
+ if (thres != 0.0f) {
+ if (fabsf((float)(-1.5f + loc[0] + loc[1] + loc[2])) < 1.5f * thres) {
+ return;
+ }
+ }
+
+ copy_v3_v3(rco, loc);
+ mul_v3_fl(rco, t);
+ rough[0] = -1.0f + 2.0f * BLI_gTurbulence(size, rco[0], rco[1], rco[2], 2, 0, 2);
+ rough[1] = -1.0f + 2.0f * BLI_gTurbulence(size, rco[1], rco[2], rco[0], 2, 0, 2);
+ rough[2] = -1.0f + 2.0f * BLI_gTurbulence(size, rco[2], rco[0], rco[1], 2, 0, 2);
+
+ madd_v3_v3fl(state->co, mat[0], fac * rough[0]);
+ madd_v3_v3fl(state->co, mat[1], fac * rough[1]);
+ madd_v3_v3fl(state->co, mat[2], fac * rough[2]);
+}
+
+static void do_rough_end(const float loc[3], float mat[4][4], float t, float fac, float shape, ParticleKey *state)
+{
+ float rough[2];
+ float roughfac;
+
+ roughfac = fac * (float)pow((double)t, shape);
+ copy_v2_v2(rough, loc);
+ rough[0] = -1.0f + 2.0f * rough[0];
+ rough[1] = -1.0f + 2.0f * rough[1];
+ mul_v2_fl(rough, roughfac);
+
+ madd_v3_v3fl(state->co, mat[0], rough[0]);
+ madd_v3_v3fl(state->co, mat[1], rough[1]);
+}
+
+static void do_rough_curve(const float loc[3], float mat[4][4], float time, float fac, float size, CurveMapping *roughcurve, ParticleKey *state)
+{
+ float rough[3];
+ float rco[3];
+
+ if (!roughcurve)
+ return;
+
+ fac *= CLAMPIS(curvemapping_evaluateF(roughcurve, 0, time), 0.0f, 1.0f);
+
+ copy_v3_v3(rco, loc);
+ mul_v3_fl(rco, time);
+ rough[0] = -1.0f + 2.0f * BLI_gTurbulence(size, rco[0], rco[1], rco[2], 2, 0, 2);
+ rough[1] = -1.0f + 2.0f * BLI_gTurbulence(size, rco[1], rco[2], rco[0], 2, 0, 2);
+ rough[2] = -1.0f + 2.0f * BLI_gTurbulence(size, rco[2], rco[0], rco[1], 2, 0, 2);
+
+ madd_v3_v3fl(state->co, mat[0], fac * rough[0]);
+ madd_v3_v3fl(state->co, mat[1], fac * rough[1]);
+ madd_v3_v3fl(state->co, mat[2], fac * rough[2]);
+}
+
+void do_child_modifiers(ParticleSimulationData *sim, ParticleTexture *ptex, const float par_co[3], const float par_vel[3], const float par_rot[4], const float par_orco[3],
+ ChildParticle *cpa, const float orco[3], float mat[4][4], ParticleKey *state, float t)
+{
+ ParticleSettings *part = sim->psys->part;
+ CurveMapping *clumpcurve = (part->child_flag & PART_CHILD_USE_CLUMP_CURVE) ? part->clumpcurve : NULL;
+ CurveMapping *roughcurve = (part->child_flag & PART_CHILD_USE_ROUGH_CURVE) ? part->roughcurve : NULL;
+ int i = cpa - sim->psys->child;
+ int guided = 0;
+
+ float kink_amp = part->kink_amp;
+ float kink_amp_clump = part->kink_amp_clump;
+ float kink_freq = part->kink_freq;
+ float rough1 = part->rough1;
+ float rough2 = part->rough2;
+ float rough_end = part->rough_end;
+ const bool smooth_start = (sim->psys->part->childtype == PART_CHILD_FACES);
+
+ if (ptex) {
+ kink_amp *= ptex->kink_amp;
+ kink_freq *= ptex->kink_freq;
+ rough1 *= ptex->rough1;
+ rough2 *= ptex->rough2;
+ rough_end *= ptex->roughe;
+ }
+
+ if (part->flag & PART_CHILD_EFFECT)
+ /* state is safe to cast, since only co and vel are used */
+ guided = do_guides(sim->psys->part, sim->psys->effectors, (ParticleKey *)state, cpa->parent, t);
+
+ if (guided == 0) {
+ float orco_offset[3];
+ float clump;
+
+ sub_v3_v3v3(orco_offset, orco, par_orco);
+ clump = do_clump(state, par_co, t, orco_offset, part->clumpfac, part->clumppow, ptex ? ptex->clump : 1.f,
+ part->child_flag & PART_CHILD_USE_CLUMP_NOISE, part->clump_noise_size, clumpcurve);
+
+ if (kink_freq != 0.f) {
+ kink_amp *= (1.f - kink_amp_clump * clump);
+
+ do_kink(state, par_co, par_vel, par_rot, t, kink_freq, part->kink_shape,
+ kink_amp, part->kink_flat, part->kink, part->kink_axis,
+ sim->ob->obmat, smooth_start);
+ }
+ }
+
+ if (roughcurve) {
+ do_rough_curve(orco, mat, t, rough1, part->rough1_size, roughcurve, state);
+ }
+ else {
+ if (rough1 > 0.f)
+ do_rough(orco, mat, t, rough1, part->rough1_size, 0.0, state);
+
+ if (rough2 > 0.f) {
+ float vec[3];
+ psys_frand_vec(sim->psys, i + 27, vec);
+ do_rough(vec, mat, t, rough2, part->rough2_size, part->rough2_thres, state);
+ }
+
+ if (rough_end > 0.f) {
+ float vec[3];
+ psys_frand_vec(sim->psys, i + 27, vec);
+ do_rough_end(vec, mat, t, rough_end, part->rough_end_shape, state);
+ }
+ }
+}
diff --git a/source/blender/blenkernel/intern/particle_distribute.c b/source/blender/blenkernel/intern/particle_distribute.c
new file mode 100644
index 00000000000..87bc355894d
--- /dev/null
+++ b/source/blender/blenkernel/intern/particle_distribute.c
@@ -0,0 +1,1417 @@
+/*
+ * ***** 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) 2007 by Janne Karhu.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Raul Fernandez Hernandez (Farsthary),
+ * Stephen Swhitehorn,
+ * Lukas Toenne
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/blenkernel/intern/particle_distribute.c
+ * \ingroup bke
+ */
+
+#include <string.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_utildefines.h"
+#include "BLI_jitter.h"
+#include "BLI_kdtree.h"
+#include "BLI_math.h"
+#include "BLI_rand.h"
+#include "BLI_sort.h"
+#include "BLI_task.h"
+
+#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_modifier_types.h"
+#include "DNA_particle_types.h"
+#include "DNA_scene_types.h"
+
+#include "BKE_cdderivedmesh.h"
+#include "BKE_DerivedMesh.h"
+#include "BKE_global.h"
+#include "BKE_mesh.h"
+#include "BKE_object.h"
+#include "BKE_particle.h"
+
+static int psys_render_simplify_distribution(ParticleThreadContext *ctx, int tot);
+
+static void alloc_child_particles(ParticleSystem *psys, int tot)
+{
+ if (psys->child) {
+ /* only re-allocate if we have to */
+ if (psys->part->childtype && psys->totchild == tot) {
+ memset(psys->child, 0, tot*sizeof(ChildParticle));
+ return;
+ }
+
+ MEM_freeN(psys->child);
+ psys->child=NULL;
+ psys->totchild=0;
+ }
+
+ if (psys->part->childtype) {
+ psys->totchild= tot;
+ if (psys->totchild)
+ psys->child= MEM_callocN(psys->totchild*sizeof(ChildParticle), "child_particles");
+ }
+}
+
+static void distribute_simple_children(Scene *scene, Object *ob, DerivedMesh *finaldm, ParticleSystem *psys)
+{
+ ChildParticle *cpa = NULL;
+ int i, p;
+ int child_nbr= psys_get_child_number(scene, psys);
+ int totpart= psys_get_tot_child(scene, psys);
+
+ alloc_child_particles(psys, totpart);
+
+ cpa = psys->child;
+ for (i=0; i<child_nbr; i++) {
+ for (p=0; p<psys->totpart; p++,cpa++) {
+ float length=2.0;
+ cpa->parent=p;
+
+ /* create even spherical distribution inside unit sphere */
+ while (length>=1.0f) {
+ cpa->fuv[0]=2.0f*BLI_frand()-1.0f;
+ cpa->fuv[1]=2.0f*BLI_frand()-1.0f;
+ cpa->fuv[2]=2.0f*BLI_frand()-1.0f;
+ length=len_v3(cpa->fuv);
+ }
+
+ cpa->num=-1;
+ }
+ }
+ /* dmcache must be updated for parent particles if children from faces is used */
+ psys_calc_dmcache(ob, finaldm, psys);
+}
+static void distribute_grid(DerivedMesh *dm, ParticleSystem *psys)
+{
+ ParticleData *pa=NULL;
+ float min[3], max[3], delta[3], d;
+ MVert *mv, *mvert = dm->getVertDataArray(dm,0);
+ int totvert=dm->getNumVerts(dm), from=psys->part->from;
+ int i, j, k, p, res=psys->part->grid_res, size[3], axis;
+
+ /* find bounding box of dm */
+ if (totvert > 0) {
+ mv=mvert;
+ copy_v3_v3(min, mv->co);
+ copy_v3_v3(max, mv->co);
+ mv++;
+ for (i = 1; i < totvert; i++, mv++) {
+ minmax_v3v3_v3(min, max, mv->co);
+ }
+ }
+ else {
+ zero_v3(min);
+ zero_v3(max);
+ }
+
+ sub_v3_v3v3(delta, max, min);
+
+ /* determine major axis */
+ axis = axis_dominant_v3_single(delta);
+
+ d = delta[axis]/(float)res;
+
+ size[axis] = res;
+ size[(axis+1)%3] = (int)ceil(delta[(axis+1)%3]/d);
+ size[(axis+2)%3] = (int)ceil(delta[(axis+2)%3]/d);
+
+ /* float errors grrr.. */
+ size[(axis+1)%3] = MIN2(size[(axis+1)%3],res);
+ size[(axis+2)%3] = MIN2(size[(axis+2)%3],res);
+
+ size[0] = MAX2(size[0], 1);
+ size[1] = MAX2(size[1], 1);
+ size[2] = MAX2(size[2], 1);
+
+ /* no full offset for flat/thin objects */
+ min[0]+= d < delta[0] ? d/2.f : delta[0]/2.f;
+ min[1]+= d < delta[1] ? d/2.f : delta[1]/2.f;
+ min[2]+= d < delta[2] ? d/2.f : delta[2]/2.f;
+
+ for (i=0,p=0,pa=psys->particles; i<res; i++) {
+ for (j=0; j<res; j++) {
+ for (k=0; k<res; k++,p++,pa++) {
+ pa->fuv[0] = min[0] + (float)i*d;
+ pa->fuv[1] = min[1] + (float)j*d;
+ pa->fuv[2] = min[2] + (float)k*d;
+ pa->flag |= PARS_UNEXIST;
+ pa->hair_index = 0; /* abused in volume calculation */
+ }
+ }
+ }
+
+ /* enable particles near verts/edges/faces/inside surface */
+ if (from==PART_FROM_VERT) {
+ float vec[3];
+
+ pa=psys->particles;
+
+ min[0] -= d/2.0f;
+ min[1] -= d/2.0f;
+ min[2] -= d/2.0f;
+
+ for (i=0,mv=mvert; i<totvert; i++,mv++) {
+ sub_v3_v3v3(vec,mv->co,min);
+ vec[0]/=delta[0];
+ vec[1]/=delta[1];
+ vec[2]/=delta[2];
+ pa[((int)(vec[0] * (size[0] - 1)) * res +
+ (int)(vec[1] * (size[1] - 1))) * res +
+ (int)(vec[2] * (size[2] - 1))].flag &= ~PARS_UNEXIST;
+ }
+ }
+ else if (ELEM(from,PART_FROM_FACE,PART_FROM_VOLUME)) {
+ float co1[3], co2[3];
+
+ MFace *mface= NULL, *mface_array;
+ float v1[3], v2[3], v3[3], v4[4], lambda;
+ int a, a1, a2, a0mul, a1mul, a2mul, totface;
+ int amax= from==PART_FROM_FACE ? 3 : 1;
+
+ totface=dm->getNumTessFaces(dm);
+ mface=mface_array=dm->getTessFaceDataArray(dm,CD_MFACE);
+
+ for (a=0; a<amax; a++) {
+ if (a==0) { a0mul=res*res; a1mul=res; a2mul=1; }
+ else if (a==1) { a0mul=res; a1mul=1; a2mul=res*res; }
+ else { a0mul=1; a1mul=res*res; a2mul=res; }
+
+ for (a1=0; a1<size[(a+1)%3]; a1++) {
+ for (a2=0; a2<size[(a+2)%3]; a2++) {
+ mface= mface_array;
+
+ pa = psys->particles + a1*a1mul + a2*a2mul;
+ copy_v3_v3(co1, pa->fuv);
+ co1[a] -= d < delta[a] ? d/2.f : delta[a]/2.f;
+ copy_v3_v3(co2, co1);
+ co2[a] += delta[a] + 0.001f*d;
+ co1[a] -= 0.001f*d;
+
+ /* lets intersect the faces */
+ for (i=0; i<totface; i++,mface++) {
+ copy_v3_v3(v1, mvert[mface->v1].co);
+ copy_v3_v3(v2, mvert[mface->v2].co);
+ copy_v3_v3(v3, mvert[mface->v3].co);
+
+ if (isect_axial_line_tri_v3(a, co1, co2, v2, v3, v1, &lambda)) {
+ if (from==PART_FROM_FACE)
+ (pa+(int)(lambda*size[a])*a0mul)->flag &= ~PARS_UNEXIST;
+ else /* store number of intersections */
+ (pa+(int)(lambda*size[a])*a0mul)->hair_index++;
+ }
+ else if (mface->v4) {
+ copy_v3_v3(v4, mvert[mface->v4].co);
+
+ if (isect_axial_line_tri_v3(a, co1, co2, v4, v1, v3, &lambda)) {
+ if (from==PART_FROM_FACE)
+ (pa+(int)(lambda*size[a])*a0mul)->flag &= ~PARS_UNEXIST;
+ else
+ (pa+(int)(lambda*size[a])*a0mul)->hair_index++;
+ }
+ }
+ }
+
+ if (from==PART_FROM_VOLUME) {
+ int in=pa->hair_index%2;
+ if (in) pa->hair_index++;
+ for (i=0; i<size[0]; i++) {
+ if (in || (pa+i*a0mul)->hair_index%2)
+ (pa+i*a0mul)->flag &= ~PARS_UNEXIST;
+ /* odd intersections == in->out / out->in */
+ /* even intersections -> in stays same */
+ in=(in + (pa+i*a0mul)->hair_index) % 2;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (psys->part->flag & PART_GRID_HEXAGONAL) {
+ for (i=0,p=0,pa=psys->particles; i<res; i++) {
+ for (j=0; j<res; j++) {
+ for (k=0; k<res; k++,p++,pa++) {
+ if (j%2)
+ pa->fuv[0] += d/2.f;
+
+ if (k%2) {
+ pa->fuv[0] += d/2.f;
+ pa->fuv[1] += d/2.f;
+ }
+ }
+ }
+ }
+ }
+
+ if (psys->part->flag & PART_GRID_INVERT) {
+ for (i=0; i<size[0]; i++) {
+ for (j=0; j<size[1]; j++) {
+ pa=psys->particles + res*(i*res + j);
+ for (k=0; k<size[2]; k++, pa++) {
+ pa->flag ^= PARS_UNEXIST;
+ }
+ }
+ }
+ }
+
+ if (psys->part->grid_rand > 0.f) {
+ float rfac = d * psys->part->grid_rand;
+ for (p=0,pa=psys->particles; p<psys->totpart; p++,pa++) {
+ if (pa->flag & PARS_UNEXIST)
+ continue;
+
+ pa->fuv[0] += rfac * (psys_frand(psys, p + 31) - 0.5f);
+ pa->fuv[1] += rfac * (psys_frand(psys, p + 32) - 0.5f);
+ pa->fuv[2] += rfac * (psys_frand(psys, p + 33) - 0.5f);
+ }
+ }
+}
+
+/* modified copy from rayshade.c */
+static void hammersley_create(float *out, int n, int seed, float amount)
+{
+ RNG *rng;
+ double p, t, offs[2];
+ int k, kk;
+
+ rng = BLI_rng_new(31415926 + n + seed);
+ offs[0] = BLI_rng_get_double(rng) + (double)amount;
+ offs[1] = BLI_rng_get_double(rng) + (double)amount;
+ BLI_rng_free(rng);
+
+ for (k = 0; k < n; k++) {
+ t = 0;
+ for (p = 0.5, kk = k; kk; p *= 0.5, kk >>= 1)
+ if (kk & 1) /* kk mod 2 = 1 */
+ t += p;
+
+ out[2*k + 0] = fmod((double)k/(double)n + offs[0], 1.0);
+ out[2*k + 1] = fmod(t + offs[1], 1.0);
+ }
+}
+
+/* almost exact copy of BLI_jitter_init */
+static void init_mv_jit(float *jit, int num, int seed2, float amount)
+{
+ RNG *rng;
+ float *jit2, x, rad1, rad2, rad3;
+ int i, num2;
+
+ if (num==0) return;
+
+ rad1= (float)(1.0f/sqrtf((float)num));
+ rad2= (float)(1.0f/((float)num));
+ rad3= (float)sqrtf((float)num)/((float)num);
+
+ rng = BLI_rng_new(31415926 + num + seed2);
+ x= 0;
+ num2 = 2 * num;
+ for (i=0; i<num2; i+=2) {
+
+ jit[i] = x + amount*rad1*(0.5f - BLI_rng_get_float(rng));
+ jit[i+1] = i/(2.0f*num) + amount*rad1*(0.5f - BLI_rng_get_float(rng));
+
+ jit[i]-= (float)floor(jit[i]);
+ jit[i+1]-= (float)floor(jit[i+1]);
+
+ x+= rad3;
+ x -= (float)floor(x);
+ }
+
+ jit2= MEM_mallocN(12 + 2*sizeof(float)*num, "initjit");
+
+ for (i=0 ; i<4 ; i++) {
+ BLI_jitterate1((float (*)[2])jit, (float (*)[2])jit2, num, rad1);
+ BLI_jitterate1((float (*)[2])jit, (float (*)[2])jit2, num, rad1);
+ BLI_jitterate2((float (*)[2])jit, (float (*)[2])jit2, num, rad2);
+ }
+ MEM_freeN(jit2);
+ BLI_rng_free(rng);
+}
+
+static void psys_uv_to_w(float u, float v, int quad, float *w)
+{
+ float vert[4][3], co[3];
+
+ if (!quad) {
+ if (u+v > 1.0f)
+ v= 1.0f-v;
+ else
+ u= 1.0f-u;
+ }
+
+ vert[0][0] = 0.0f; vert[0][1] = 0.0f; vert[0][2] = 0.0f;
+ vert[1][0] = 1.0f; vert[1][1] = 0.0f; vert[1][2] = 0.0f;
+ vert[2][0] = 1.0f; vert[2][1] = 1.0f; vert[2][2] = 0.0f;
+
+ co[0] = u;
+ co[1] = v;
+ co[2] = 0.0f;
+
+ if (quad) {
+ vert[3][0] = 0.0f; vert[3][1] = 1.0f; vert[3][2] = 0.0f;
+ interp_weights_poly_v3( w,vert, 4, co);
+ }
+ else {
+ interp_weights_poly_v3( w,vert, 3, co);
+ w[3] = 0.0f;
+ }
+}
+
+/* Find the index in "sum" array before "value" is crossed. */
+static int distribute_binary_search(float *sum, int n, float value)
+{
+ int mid, low=0, high=n;
+
+ if (value == 0.f)
+ return 0;
+
+ while (low <= high) {
+ mid= (low + high)/2;
+
+ if (sum[mid] < value && value <= sum[mid+1])
+ return mid;
+
+ if (sum[mid] >= value)
+ high= mid - 1;
+ else if (sum[mid] < value)
+ low= mid + 1;
+ else
+ return mid;
+ }
+
+ return low;
+}
+
+/* the max number if calls to rng_* funcs within psys_thread_distribute_particle
+ * be sure to keep up to date if this changes */
+#define PSYS_RND_DIST_SKIP 2
+
+/* note: this function must be thread safe, for from == PART_FROM_CHILD */
+#define ONLY_WORKING_WITH_PA_VERTS 0
+static void distribute_from_verts_exec(ParticleTask *thread, ParticleData *pa, int p)
+{
+ ParticleThreadContext *ctx= thread->ctx;
+ int rng_skip_tot= PSYS_RND_DIST_SKIP; /* count how many rng_* calls wont need skipping */
+
+ /* TODO_PARTICLE - use original index */
+ pa->num= ctx->index[p];
+ pa->fuv[0] = 1.0f;
+ pa->fuv[1] = pa->fuv[2] = pa->fuv[3] = 0.0;
+
+#if ONLY_WORKING_WITH_PA_VERTS
+ if (ctx->tree) {
+ KDTreeNearest ptn[3];
+ int w, maxw;
+
+ psys_particle_on_dm(ctx->dm,from,pa->num,pa->num_dmcache,pa->fuv,pa->foffset,co1,0,0,0,orco1,0);
+ BKE_mesh_orco_verts_transform((Mesh*)ob->data, &orco1, 1, 1);
+ maxw = BLI_kdtree_find_nearest_n(ctx->tree,orco1,ptn,3);
+
+ for (w=0; w<maxw; w++) {
+ pa->verts[w]=ptn->num;
+ }
+ }
+#endif
+
+ if (rng_skip_tot > 0) /* should never be below zero */
+ BLI_rng_skip(thread->rng, rng_skip_tot);
+}
+
+static void distribute_from_faces_exec(ParticleTask *thread, ParticleData *pa, int p) {
+ ParticleThreadContext *ctx= thread->ctx;
+ DerivedMesh *dm= ctx->dm;
+ float randu, randv;
+ int distr= ctx->distr;
+ int i;
+ int rng_skip_tot= PSYS_RND_DIST_SKIP; /* count how many rng_* calls wont need skipping */
+
+ MFace *mface;
+
+ pa->num = i = ctx->index[p];
+ mface = dm->getTessFaceData(dm,i,CD_MFACE);
+
+ switch (distr) {
+ case PART_DISTR_JIT:
+ if (ctx->jitlevel == 1) {
+ if (mface->v4)
+ psys_uv_to_w(0.5f, 0.5f, mface->v4, pa->fuv);
+ else
+ psys_uv_to_w(1.0f / 3.0f, 1.0f / 3.0f, mface->v4, pa->fuv);
+ }
+ else {
+ float offset = fmod(ctx->jitoff[i] + (float)p, (float)ctx->jitlevel);
+ if (!isnan(offset)) {
+ psys_uv_to_w(ctx->jit[2*(int)offset], ctx->jit[2*(int)offset+1], mface->v4, pa->fuv);
+ }
+ }
+ break;
+ case PART_DISTR_RAND:
+ randu= BLI_rng_get_float(thread->rng);
+ randv= BLI_rng_get_float(thread->rng);
+ rng_skip_tot -= 2;
+
+ psys_uv_to_w(randu, randv, mface->v4, pa->fuv);
+ break;
+ }
+ pa->foffset= 0.0f;
+
+ if (rng_skip_tot > 0) /* should never be below zero */
+ BLI_rng_skip(thread->rng, rng_skip_tot);
+}
+
+static void distribute_from_volume_exec(ParticleTask *thread, ParticleData *pa, int p) {
+ ParticleThreadContext *ctx= thread->ctx;
+ DerivedMesh *dm= ctx->dm;
+ float *v1, *v2, *v3, *v4, nor[3], co[3];
+ float cur_d, min_d, randu, randv;
+ int distr= ctx->distr;
+ int i, intersect, tot;
+ int rng_skip_tot= PSYS_RND_DIST_SKIP; /* count how many rng_* calls wont need skipping */
+
+ MFace *mface;
+ MVert *mvert=dm->getVertDataArray(dm,CD_MVERT);
+
+ pa->num = i = ctx->index[p];
+ mface = dm->getTessFaceData(dm,i,CD_MFACE);
+
+ switch (distr) {
+ case PART_DISTR_JIT:
+ if (ctx->jitlevel == 1) {
+ if (mface->v4)
+ psys_uv_to_w(0.5f, 0.5f, mface->v4, pa->fuv);
+ else
+ psys_uv_to_w(1.0f / 3.0f, 1.0f / 3.0f, mface->v4, pa->fuv);
+ }
+ else {
+ float offset = fmod(ctx->jitoff[i] + (float)p, (float)ctx->jitlevel);
+ if (!isnan(offset)) {
+ psys_uv_to_w(ctx->jit[2*(int)offset], ctx->jit[2*(int)offset+1], mface->v4, pa->fuv);
+ }
+ }
+ break;
+ case PART_DISTR_RAND:
+ randu= BLI_rng_get_float(thread->rng);
+ randv= BLI_rng_get_float(thread->rng);
+ rng_skip_tot -= 2;
+
+ psys_uv_to_w(randu, randv, mface->v4, pa->fuv);
+ break;
+ }
+ pa->foffset= 0.0f;
+
+ /* experimental */
+ tot=dm->getNumTessFaces(dm);
+
+ psys_interpolate_face(mvert,mface,0,0,pa->fuv,co,nor,0,0,0,0);
+
+ normalize_v3(nor);
+ negate_v3(nor);
+
+ min_d=FLT_MAX;
+ intersect=0;
+
+ for (i=0,mface=dm->getTessFaceDataArray(dm,CD_MFACE); i<tot; i++,mface++) {
+ if (i==pa->num) continue;
+
+ v1=mvert[mface->v1].co;
+ v2=mvert[mface->v2].co;
+ v3=mvert[mface->v3].co;
+
+ if (isect_ray_tri_v3(co, nor, v2, v3, v1, &cur_d, NULL)) {
+ if (cur_d<min_d) {
+ min_d=cur_d;
+ pa->foffset=cur_d*0.5f; /* to the middle of volume */
+ intersect=1;
+ }
+ }
+ if (mface->v4) {
+ v4=mvert[mface->v4].co;
+
+ if (isect_ray_tri_v3(co, nor, v4, v1, v3, &cur_d, NULL)) {
+ if (cur_d<min_d) {
+ min_d=cur_d;
+ pa->foffset=cur_d*0.5f; /* to the middle of volume */
+ intersect=1;
+ }
+ }
+ }
+ }
+ if (intersect==0)
+ pa->foffset=0.0;
+ else {
+ switch (distr) {
+ case PART_DISTR_JIT:
+ pa->foffset *= ctx->jit[p % (2 * ctx->jitlevel)];
+ break;
+ case PART_DISTR_RAND:
+ pa->foffset *= BLI_frand();
+ break;
+ }
+ }
+
+ if (rng_skip_tot > 0) /* should never be below zero */
+ BLI_rng_skip(thread->rng, rng_skip_tot);
+}
+
+static void distribute_children_exec(ParticleTask *thread, ChildParticle *cpa, int p) {
+ ParticleThreadContext *ctx= thread->ctx;
+ Object *ob= ctx->sim.ob;
+ DerivedMesh *dm= ctx->dm;
+ float orco1[3], co1[3], nor1[3];
+ float randu, randv;
+ int cfrom= ctx->cfrom;
+ int i;
+ int rng_skip_tot= PSYS_RND_DIST_SKIP; /* count how many rng_* calls wont need skipping */
+
+ MFace *mf;
+
+ if (ctx->index[p] < 0) {
+ cpa->num=0;
+ cpa->fuv[0]=cpa->fuv[1]=cpa->fuv[2]=cpa->fuv[3]=0.0f;
+ cpa->pa[0]=cpa->pa[1]=cpa->pa[2]=cpa->pa[3]=0;
+ return;
+ }
+
+ mf= dm->getTessFaceData(dm, ctx->index[p], CD_MFACE);
+
+ randu= BLI_rng_get_float(thread->rng);
+ randv= BLI_rng_get_float(thread->rng);
+ rng_skip_tot -= 2;
+
+ psys_uv_to_w(randu, randv, mf->v4, cpa->fuv);
+
+ cpa->num = ctx->index[p];
+
+ if (ctx->tree) {
+ KDTreeNearest ptn[10];
+ int w,maxw;//, do_seams;
+ float maxd /*, mind,dd */, totw= 0.0f;
+ int parent[10];
+ float pweight[10];
+
+ psys_particle_on_dm(dm,cfrom,cpa->num,DMCACHE_ISCHILD,cpa->fuv,cpa->foffset,co1,nor1,NULL,NULL,orco1,NULL);
+ BKE_mesh_orco_verts_transform((Mesh*)ob->data, &orco1, 1, 1);
+ maxw = BLI_kdtree_find_nearest_n(ctx->tree,orco1,ptn,3);
+
+ maxd=ptn[maxw-1].dist;
+ /* mind=ptn[0].dist; */ /* UNUSED */
+
+ /* the weights here could be done better */
+ for (w=0; w<maxw; w++) {
+ parent[w]=ptn[w].index;
+ pweight[w]=(float)pow(2.0,(double)(-6.0f*ptn[w].dist/maxd));
+ }
+ for (;w<10; w++) {
+ parent[w]=-1;
+ pweight[w]=0.0f;
+ }
+
+ for (w=0,i=0; w<maxw && i<4; w++) {
+ if (parent[w]>=0) {
+ cpa->pa[i]=parent[w];
+ cpa->w[i]=pweight[w];
+ totw+=pweight[w];
+ i++;
+ }
+ }
+ for (;i<4; i++) {
+ cpa->pa[i]=-1;
+ cpa->w[i]=0.0f;
+ }
+
+ if (totw > 0.0f) {
+ for (w = 0; w < 4; w++) {
+ cpa->w[w] /= totw;
+ }
+ }
+
+ cpa->parent=cpa->pa[0];
+ }
+
+ if (rng_skip_tot > 0) /* should never be below zero */
+ BLI_rng_skip(thread->rng, rng_skip_tot);
+}
+
+static void exec_distribute_parent(TaskPool *UNUSED(pool), void *taskdata, int UNUSED(threadid))
+{
+ ParticleTask *task = taskdata;
+ ParticleSystem *psys= task->ctx->sim.psys;
+ ParticleData *pa;
+ int p;
+
+ BLI_rng_skip(task->rng, PSYS_RND_DIST_SKIP * task->begin);
+
+ pa= psys->particles + task->begin;
+ switch (psys->part->from) {
+ case PART_FROM_FACE:
+ for (p = task->begin; p < task->end; ++p, ++pa)
+ distribute_from_faces_exec(task, pa, p);
+ break;
+ case PART_FROM_VOLUME:
+ for (p = task->begin; p < task->end; ++p, ++pa)
+ distribute_from_volume_exec(task, pa, p);
+ break;
+ case PART_FROM_VERT:
+ for (p = task->begin; p < task->end; ++p, ++pa)
+ distribute_from_verts_exec(task, pa, p);
+ break;
+ }
+}
+
+static void exec_distribute_child(TaskPool *UNUSED(pool), void *taskdata, int UNUSED(threadid))
+{
+ ParticleTask *task = taskdata;
+ ParticleSystem *psys = task->ctx->sim.psys;
+ ChildParticle *cpa;
+ int p;
+
+ /* RNG skipping at the beginning */
+ cpa = psys->child;
+ for (p = 0; p < task->begin; ++p, ++cpa) {
+ if (task->ctx->skip) /* simplification skip */
+ BLI_rng_skip(task->rng, PSYS_RND_DIST_SKIP * task->ctx->skip[p]);
+
+ BLI_rng_skip(task->rng, PSYS_RND_DIST_SKIP);
+ }
+
+ for (; p < task->end; ++p, ++cpa) {
+ if (task->ctx->skip) /* simplification skip */
+ BLI_rng_skip(task->rng, PSYS_RND_DIST_SKIP * task->ctx->skip[p]);
+
+ distribute_children_exec(task, cpa, p);
+ }
+}
+
+static int distribute_compare_orig_index(const void *p1, const void *p2, void *user_data)
+{
+ int *orig_index = (int *) user_data;
+ int index1 = orig_index[*(const int *)p1];
+ int index2 = orig_index[*(const int *)p2];
+
+ if (index1 < index2)
+ return -1;
+ else if (index1 == index2) {
+ /* this pointer comparison appears to make qsort stable for glibc,
+ * and apparently on solaris too, makes the renders reproducible */
+ if (p1 < p2)
+ return -1;
+ else if (p1 == p2)
+ return 0;
+ else
+ return 1;
+ }
+ else
+ return 1;
+}
+
+static void distribute_invalid(Scene *scene, ParticleSystem *psys, int from)
+{
+ if (from == PART_FROM_CHILD) {
+ ChildParticle *cpa;
+ int p, totchild = psys_get_tot_child(scene, psys);
+
+ if (psys->child && totchild) {
+ for (p=0,cpa=psys->child; p<totchild; p++,cpa++) {
+ cpa->fuv[0]=cpa->fuv[1]=cpa->fuv[2]=cpa->fuv[3] = 0.0;
+ cpa->foffset= 0.0f;
+ cpa->parent=0;
+ cpa->pa[0]=cpa->pa[1]=cpa->pa[2]=cpa->pa[3]=0;
+ cpa->num= -1;
+ }
+ }
+ }
+ else {
+ PARTICLE_P;
+ LOOP_PARTICLES {
+ pa->fuv[0] = pa->fuv[1] = pa->fuv[2] = pa->fuv[3] = 0.0;
+ pa->foffset= 0.0f;
+ pa->num= -1;
+ }
+ }
+}
+
+/* Creates a distribution of coordinates on a DerivedMesh */
+/* This is to denote functionality that does not yet work with mesh - only derived mesh */
+static int psys_thread_context_init_distribute(ParticleThreadContext *ctx, ParticleSimulationData *sim, int from)
+{
+ Scene *scene = sim->scene;
+ DerivedMesh *finaldm = sim->psmd->dm;
+ Object *ob = sim->ob;
+ ParticleSystem *psys= sim->psys;
+ ParticleData *pa=0, *tpars= 0;
+ ParticleSettings *part;
+ ParticleSeam *seams= 0;
+ KDTree *tree=0;
+ DerivedMesh *dm= NULL;
+ float *jit= NULL;
+ int i, p=0;
+ int cfrom=0;
+ int totelem=0, totpart, *particle_element=0, children=0, totseam=0;
+ int jitlevel= 1, distr;
+ float *element_weight=NULL,*element_sum=NULL,*jitter_offset=NULL, *vweight=NULL;
+ float cur, maxweight=0.0, tweight, totweight, inv_totweight, co[3], nor[3], orco[3];
+
+ if (ELEM(NULL, ob, psys, psys->part))
+ return 0;
+
+ part=psys->part;
+ totpart=psys->totpart;
+ if (totpart==0)
+ return 0;
+
+ if (!finaldm->deformedOnly && !finaldm->getTessFaceDataArray(finaldm, CD_ORIGINDEX)) {
+ printf("Can't create particles with the current modifier stack, disable destructive modifiers\n");
+// XXX error("Can't paint with the current modifier stack, disable destructive modifiers");
+ return 0;
+ }
+
+ psys_thread_context_init(ctx, sim);
+
+ /* First handle special cases */
+ if (from == PART_FROM_CHILD) {
+ /* Simple children */
+ if (part->childtype != PART_CHILD_FACES) {
+ BLI_srandom(31415926 + psys->seed + psys->child_seed);
+ distribute_simple_children(scene, ob, finaldm, psys);
+ return 0;
+ }
+ }
+ else {
+ /* Grid distribution */
+ if (part->distr==PART_DISTR_GRID && from != PART_FROM_VERT) {
+ BLI_srandom(31415926 + psys->seed);
+ dm= CDDM_from_mesh((Mesh*)ob->data);
+ DM_ensure_tessface(dm);
+ distribute_grid(dm,psys);
+ dm->release(dm);
+ return 0;
+ }
+ }
+
+ /* Create trees and original coordinates if needed */
+ if (from == PART_FROM_CHILD) {
+ distr=PART_DISTR_RAND;
+ BLI_srandom(31415926 + psys->seed + psys->child_seed);
+ dm= finaldm;
+
+ /* BMESH ONLY */
+ DM_ensure_tessface(dm);
+
+ children=1;
+
+ tree=BLI_kdtree_new(totpart);
+
+ for (p=0,pa=psys->particles; p<totpart; p++,pa++) {
+ psys_particle_on_dm(dm,part->from,pa->num,pa->num_dmcache,pa->fuv,pa->foffset,co,nor,0,0,orco,NULL);
+ BKE_mesh_orco_verts_transform((Mesh*)ob->data, &orco, 1, 1);
+ BLI_kdtree_insert(tree, p, orco);
+ }
+
+ BLI_kdtree_balance(tree);
+
+ totpart = psys_get_tot_child(scene, psys);
+ cfrom = from = PART_FROM_FACE;
+ }
+ else {
+ distr = part->distr;
+ BLI_srandom(31415926 + psys->seed);
+
+ if (psys->part->use_modifier_stack)
+ dm = finaldm;
+ else
+ dm= CDDM_from_mesh((Mesh*)ob->data);
+
+ /* BMESH ONLY, for verts we don't care about tessfaces */
+ if (from != PART_FROM_VERT) {
+ DM_ensure_tessface(dm);
+ }
+
+ /* we need orco for consistent distributions */
+ if (!CustomData_has_layer(&dm->vertData, CD_ORCO))
+ DM_add_vert_layer(dm, CD_ORCO, CD_ASSIGN, BKE_mesh_orco_verts_get(ob));
+
+ if (from == PART_FROM_VERT) {
+ MVert *mv= dm->getVertDataArray(dm, CD_MVERT);
+ float (*orcodata)[3] = dm->getVertDataArray(dm, CD_ORCO);
+ int totvert = dm->getNumVerts(dm);
+
+ tree=BLI_kdtree_new(totvert);
+
+ for (p=0; p<totvert; p++) {
+ if (orcodata) {
+ copy_v3_v3(co,orcodata[p]);
+ BKE_mesh_orco_verts_transform((Mesh*)ob->data, &co, 1, 1);
+ }
+ else
+ copy_v3_v3(co,mv[p].co);
+ BLI_kdtree_insert(tree, p, co);
+ }
+
+ BLI_kdtree_balance(tree);
+ }
+ }
+
+ /* Get total number of emission elements and allocate needed arrays */
+ totelem = (from == PART_FROM_VERT) ? dm->getNumVerts(dm) : dm->getNumTessFaces(dm);
+
+ if (totelem == 0) {
+ distribute_invalid(scene, psys, children ? PART_FROM_CHILD : 0);
+
+ if (G.debug & G_DEBUG)
+ fprintf(stderr,"Particle distribution error: Nothing to emit from!\n");
+
+ if (dm != finaldm) dm->release(dm);
+
+ BLI_kdtree_free(tree);
+
+ return 0;
+ }
+
+ element_weight = MEM_callocN(sizeof(float)*totelem, "particle_distribution_weights");
+ particle_element= MEM_callocN(sizeof(int)*totpart, "particle_distribution_indexes");
+ element_sum = MEM_callocN(sizeof(float)*(totelem+1), "particle_distribution_sum");
+ jitter_offset = MEM_callocN(sizeof(float)*totelem, "particle_distribution_jitoff");
+
+ /* Calculate weights from face areas */
+ if ((part->flag&PART_EDISTR || children) && from != PART_FROM_VERT) {
+ MVert *v1, *v2, *v3, *v4;
+ float totarea=0.f, co1[3], co2[3], co3[3], co4[3];
+ float (*orcodata)[3];
+
+ orcodata= dm->getVertDataArray(dm, CD_ORCO);
+
+ for (i=0; i<totelem; i++) {
+ MFace *mf=dm->getTessFaceData(dm,i,CD_MFACE);
+
+ if (orcodata) {
+ copy_v3_v3(co1, orcodata[mf->v1]);
+ copy_v3_v3(co2, orcodata[mf->v2]);
+ copy_v3_v3(co3, orcodata[mf->v3]);
+ BKE_mesh_orco_verts_transform((Mesh*)ob->data, &co1, 1, 1);
+ BKE_mesh_orco_verts_transform((Mesh*)ob->data, &co2, 1, 1);
+ BKE_mesh_orco_verts_transform((Mesh*)ob->data, &co3, 1, 1);
+ if (mf->v4) {
+ copy_v3_v3(co4, orcodata[mf->v4]);
+ BKE_mesh_orco_verts_transform((Mesh*)ob->data, &co4, 1, 1);
+ }
+ }
+ else {
+ v1= (MVert*)dm->getVertData(dm,mf->v1,CD_MVERT);
+ v2= (MVert*)dm->getVertData(dm,mf->v2,CD_MVERT);
+ v3= (MVert*)dm->getVertData(dm,mf->v3,CD_MVERT);
+ copy_v3_v3(co1, v1->co);
+ copy_v3_v3(co2, v2->co);
+ copy_v3_v3(co3, v3->co);
+ if (mf->v4) {
+ v4= (MVert*)dm->getVertData(dm,mf->v4,CD_MVERT);
+ copy_v3_v3(co4, v4->co);
+ }
+ }
+
+ cur = mf->v4 ? area_quad_v3(co1, co2, co3, co4) : area_tri_v3(co1, co2, co3);
+
+ if (cur > maxweight)
+ maxweight = cur;
+
+ element_weight[i] = cur;
+ totarea += cur;
+ }
+
+ for (i=0; i<totelem; i++)
+ element_weight[i] /= totarea;
+
+ maxweight /= totarea;
+ }
+ else {
+ float min=1.0f/(float)(MIN2(totelem,totpart));
+ for (i=0; i<totelem; i++)
+ element_weight[i]=min;
+ maxweight=min;
+ }
+
+ /* Calculate weights from vgroup */
+ vweight = psys_cache_vgroup(dm,psys,PSYS_VG_DENSITY);
+
+ if (vweight) {
+ if (from==PART_FROM_VERT) {
+ for (i=0;i<totelem; i++)
+ element_weight[i]*=vweight[i];
+ }
+ else { /* PART_FROM_FACE / PART_FROM_VOLUME */
+ for (i=0;i<totelem; i++) {
+ MFace *mf=dm->getTessFaceData(dm,i,CD_MFACE);
+ tweight = vweight[mf->v1] + vweight[mf->v2] + vweight[mf->v3];
+
+ if (mf->v4) {
+ tweight += vweight[mf->v4];
+ tweight /= 4.0f;
+ }
+ else {
+ tweight /= 3.0f;
+ }
+
+ element_weight[i]*=tweight;
+ }
+ }
+ MEM_freeN(vweight);
+ }
+
+ /* Calculate total weight of all elements */
+ totweight= 0.0f;
+ for (i=0;i<totelem; i++)
+ totweight += element_weight[i];
+
+ inv_totweight = (totweight > 0.f ? 1.f/totweight : 0.f);
+
+ /* Calculate cumulative weights */
+ element_sum[0] = 0.0f;
+ for (i=0; i<totelem; i++)
+ element_sum[i+1] = element_sum[i] + element_weight[i] * inv_totweight;
+
+ /* Finally assign elements to particles */
+ if ((part->flag&PART_TRAND) || (part->simplify_flag&PART_SIMPLIFY_ENABLE)) {
+ float pos;
+
+ for (p=0; p<totpart; p++) {
+ /* In theory element_sum[totelem] should be 1.0, but due to float errors this is not necessarily always true, so scale pos accordingly. */
+ pos= BLI_frand() * element_sum[totelem];
+ particle_element[p] = distribute_binary_search(element_sum, totelem, pos);
+ particle_element[p] = MIN2(totelem-1, particle_element[p]);
+ jitter_offset[particle_element[p]] = pos;
+ }
+ }
+ else {
+ double step, pos;
+
+ step= (totpart < 2) ? 0.5 : 1.0/(double)totpart;
+ pos= 1e-6; /* tiny offset to avoid zero weight face */
+ i= 0;
+
+ for (p=0; p<totpart; p++, pos+=step) {
+ while ((i < totelem) && (pos > (double)element_sum[i + 1]))
+ i++;
+
+ particle_element[p] = MIN2(totelem-1, i);
+
+ /* avoid zero weight face */
+ if (p == totpart-1 && element_weight[particle_element[p]] == 0.0f)
+ particle_element[p] = particle_element[p-1];
+
+ jitter_offset[particle_element[p]] = pos;
+ }
+ }
+
+ MEM_freeN(element_sum);
+
+ /* For hair, sort by origindex (allows optimization's in rendering), */
+ /* however with virtual parents the children need to be in random order. */
+ if (part->type == PART_HAIR && !(part->childtype==PART_CHILD_FACES && part->parents!=0.0f)) {
+ int *orig_index = NULL;
+
+ if (from == PART_FROM_VERT) {
+ if (dm->numVertData)
+ orig_index = dm->getVertDataArray(dm, CD_ORIGINDEX);
+ }
+ else {
+ if (dm->numTessFaceData)
+ orig_index = dm->getTessFaceDataArray(dm, CD_ORIGINDEX);
+ }
+
+ if (orig_index) {
+ BLI_qsort_r(particle_element, totpart, sizeof(int), distribute_compare_orig_index, orig_index);
+ }
+ }
+
+ /* Create jittering if needed */
+ if (distr==PART_DISTR_JIT && ELEM(from,PART_FROM_FACE,PART_FROM_VOLUME)) {
+ jitlevel= part->userjit;
+
+ if (jitlevel == 0) {
+ jitlevel= totpart/totelem;
+ if (part->flag & PART_EDISTR) jitlevel*= 2; /* looks better in general, not very scietific */
+ if (jitlevel<3) jitlevel= 3;
+ }
+
+ jit= MEM_callocN((2+ jitlevel*2)*sizeof(float), "jit");
+
+ /* for small amounts of particles we use regular jitter since it looks
+ * a bit better, for larger amounts we switch to hammersley sequence
+ * because it is much faster */
+ if (jitlevel < 25)
+ init_mv_jit(jit, jitlevel, psys->seed, part->jitfac);
+ else
+ hammersley_create(jit, jitlevel+1, psys->seed, part->jitfac);
+ BLI_array_randomize(jit, 2*sizeof(float), jitlevel, psys->seed); /* for custom jit or even distribution */
+ }
+
+ /* Setup things for threaded distribution */
+ ctx->tree= tree;
+ ctx->seams= seams;
+ ctx->totseam= totseam;
+ ctx->sim.psys= psys;
+ ctx->index= particle_element;
+ ctx->jit= jit;
+ ctx->jitlevel= jitlevel;
+ ctx->jitoff= jitter_offset;
+ ctx->weight= element_weight;
+ ctx->maxweight= maxweight;
+ ctx->cfrom= cfrom;
+ ctx->distr= distr;
+ ctx->dm= dm;
+ ctx->tpars= tpars;
+
+ if (children) {
+ totpart= psys_render_simplify_distribution(ctx, totpart);
+ alloc_child_particles(psys, totpart);
+ }
+
+ return 1;
+}
+
+static void psys_task_init_distribute(ParticleTask *task, ParticleSimulationData *sim)
+{
+ /* init random number generator */
+ int seed = 31415926 + sim->psys->seed;
+
+ task->rng = BLI_rng_new(seed);
+}
+
+static void distribute_particles_on_dm(ParticleSimulationData *sim, int from)
+{
+ TaskScheduler *task_scheduler;
+ TaskPool *task_pool;
+ ParticleThreadContext ctx;
+ ParticleTask *tasks;
+ DerivedMesh *finaldm = sim->psmd->dm;
+ int i, totpart, numtasks;
+
+ /* create a task pool for distribution tasks */
+ if (!psys_thread_context_init_distribute(&ctx, sim, from))
+ return;
+
+ task_scheduler = BLI_task_scheduler_get();
+ task_pool = BLI_task_pool_create(task_scheduler, &ctx);
+
+ totpart = (from == PART_FROM_CHILD ? sim->psys->totchild : sim->psys->totpart);
+ psys_tasks_create(&ctx, 0, totpart, &tasks, &numtasks);
+ for (i = 0; i < numtasks; ++i) {
+ ParticleTask *task = &tasks[i];
+
+ psys_task_init_distribute(task, sim);
+ if (from == PART_FROM_CHILD)
+ BLI_task_pool_push(task_pool, exec_distribute_child, task, false, TASK_PRIORITY_LOW);
+ else
+ BLI_task_pool_push(task_pool, exec_distribute_parent, task, false, TASK_PRIORITY_LOW);
+ }
+ BLI_task_pool_work_and_wait(task_pool);
+
+ BLI_task_pool_free(task_pool);
+
+ psys_calc_dmcache(sim->ob, finaldm, sim->psys);
+
+ if (ctx.dm != finaldm)
+ ctx.dm->release(ctx.dm);
+
+ psys_tasks_free(tasks, numtasks);
+
+ psys_thread_context_free(&ctx);
+}
+
+/* ready for future use, to emit particles without geometry */
+static void distribute_particles_on_shape(ParticleSimulationData *sim, int UNUSED(from))
+{
+ distribute_invalid(sim->scene, sim->psys, 0);
+
+ fprintf(stderr,"Shape emission not yet possible!\n");
+}
+
+void distribute_particles(ParticleSimulationData *sim, int from)
+{
+ PARTICLE_PSMD;
+ int distr_error=0;
+
+ if (psmd) {
+ if (psmd->dm)
+ distribute_particles_on_dm(sim, from);
+ else
+ distr_error=1;
+ }
+ else
+ distribute_particles_on_shape(sim, from);
+
+ if (distr_error) {
+ distribute_invalid(sim->scene, sim->psys, from);
+
+ fprintf(stderr,"Particle distribution error!\n");
+ }
+}
+
+/* ======== Simplify ======== */
+
+static float psys_render_viewport_falloff(double rate, float dist, float width)
+{
+ return pow(rate, dist / width);
+}
+
+static float psys_render_projected_area(ParticleSystem *psys, const float center[3], float area, double vprate, float *viewport)
+{
+ ParticleRenderData *data = psys->renderdata;
+ float co[4], view[3], ortho1[3], ortho2[3], w, dx, dy, radius;
+
+ /* transform to view space */
+ copy_v3_v3(co, center);
+ co[3] = 1.0f;
+ mul_m4_v4(data->viewmat, co);
+
+ /* compute two vectors orthogonal to view vector */
+ normalize_v3_v3(view, co);
+ ortho_basis_v3v3_v3(ortho1, ortho2, view);
+
+ /* compute on screen minification */
+ w = co[2] * data->winmat[2][3] + data->winmat[3][3];
+ dx = data->winx * ortho2[0] * data->winmat[0][0];
+ dy = data->winy * ortho2[1] * data->winmat[1][1];
+ w = sqrtf(dx * dx + dy * dy) / w;
+
+ /* w squared because we are working with area */
+ area = area * w * w;
+
+ /* viewport of the screen test */
+
+ /* project point on screen */
+ mul_m4_v4(data->winmat, co);
+ if (co[3] != 0.0f) {
+ co[0] = 0.5f * data->winx * (1.0f + co[0] / co[3]);
+ co[1] = 0.5f * data->winy * (1.0f + co[1] / co[3]);
+ }
+
+ /* screen space radius */
+ radius = sqrtf(area / (float)M_PI);
+
+ /* make smaller using fallof once over screen edge */
+ *viewport = 1.0f;
+
+ if (co[0] + radius < 0.0f)
+ *viewport *= psys_render_viewport_falloff(vprate, -(co[0] + radius), data->winx);
+ else if (co[0] - radius > data->winx)
+ *viewport *= psys_render_viewport_falloff(vprate, (co[0] - radius) - data->winx, data->winx);
+
+ if (co[1] + radius < 0.0f)
+ *viewport *= psys_render_viewport_falloff(vprate, -(co[1] + radius), data->winy);
+ else if (co[1] - radius > data->winy)
+ *viewport *= psys_render_viewport_falloff(vprate, (co[1] - radius) - data->winy, data->winy);
+
+ return area;
+}
+
+/* BMESH_TODO, for orig face data, we need to use MPoly */
+static int psys_render_simplify_distribution(ParticleThreadContext *ctx, int tot)
+{
+ DerivedMesh *dm = ctx->dm;
+ Mesh *me = (Mesh *)(ctx->sim.ob->data);
+ MFace *mf, *mface;
+ MVert *mvert;
+ ParticleRenderData *data;
+ ParticleRenderElem *elems, *elem;
+ ParticleSettings *part = ctx->sim.psys->part;
+ float *facearea, (*facecenter)[3], size[3], fac, powrate, scaleclamp;
+ float co1[3], co2[3], co3[3], co4[3], lambda, arearatio, t, area, viewport;
+ double vprate;
+ int *facetotvert;
+ int a, b, totorigface, totface, newtot, skipped;
+
+ /* double lookup */
+ const int *index_mf_to_mpoly;
+ const int *index_mp_to_orig;
+
+ if (part->ren_as != PART_DRAW_PATH || !(part->draw & PART_DRAW_REN_STRAND))
+ return tot;
+ if (!ctx->sim.psys->renderdata)
+ return tot;
+
+ data = ctx->sim.psys->renderdata;
+ if (data->timeoffset)
+ return 0;
+ if (!(part->simplify_flag & PART_SIMPLIFY_ENABLE))
+ return tot;
+
+ mvert = dm->getVertArray(dm);
+ mface = dm->getTessFaceArray(dm);
+ totface = dm->getNumTessFaces(dm);
+ totorigface = me->totpoly;
+
+ if (totface == 0 || totorigface == 0)
+ return tot;
+
+ index_mf_to_mpoly = dm->getTessFaceDataArray(dm, CD_ORIGINDEX);
+ index_mp_to_orig = dm->getPolyDataArray(dm, CD_ORIGINDEX);
+ if (index_mf_to_mpoly == NULL) {
+ index_mp_to_orig = NULL;
+ }
+
+ facearea = MEM_callocN(sizeof(float) * totorigface, "SimplifyFaceArea");
+ facecenter = MEM_callocN(sizeof(float[3]) * totorigface, "SimplifyFaceCenter");
+ facetotvert = MEM_callocN(sizeof(int) * totorigface, "SimplifyFaceArea");
+ elems = MEM_callocN(sizeof(ParticleRenderElem) * totorigface, "SimplifyFaceElem");
+
+ if (data->elems)
+ MEM_freeN(data->elems);
+
+ data->do_simplify = true;
+ data->elems = elems;
+ data->index_mf_to_mpoly = index_mf_to_mpoly;
+ data->index_mp_to_orig = index_mp_to_orig;
+
+ /* compute number of children per original face */
+ for (a = 0; a < tot; a++) {
+ b = (index_mf_to_mpoly) ? DM_origindex_mface_mpoly(index_mf_to_mpoly, index_mp_to_orig, ctx->index[a]) : ctx->index[a];
+ if (b != ORIGINDEX_NONE) {
+ elems[b].totchild++;
+ }
+ }
+
+ /* compute areas and centers of original faces */
+ for (mf = mface, a = 0; a < totface; a++, mf++) {
+ b = (index_mf_to_mpoly) ? DM_origindex_mface_mpoly(index_mf_to_mpoly, index_mp_to_orig, a) : a;
+
+ if (b != ORIGINDEX_NONE) {
+ copy_v3_v3(co1, mvert[mf->v1].co);
+ copy_v3_v3(co2, mvert[mf->v2].co);
+ copy_v3_v3(co3, mvert[mf->v3].co);
+
+ add_v3_v3(facecenter[b], co1);
+ add_v3_v3(facecenter[b], co2);
+ add_v3_v3(facecenter[b], co3);
+
+ if (mf->v4) {
+ copy_v3_v3(co4, mvert[mf->v4].co);
+ add_v3_v3(facecenter[b], co4);
+ facearea[b] += area_quad_v3(co1, co2, co3, co4);
+ facetotvert[b] += 4;
+ }
+ else {
+ facearea[b] += area_tri_v3(co1, co2, co3);
+ facetotvert[b] += 3;
+ }
+ }
+ }
+
+ for (a = 0; a < totorigface; a++)
+ if (facetotvert[a] > 0)
+ mul_v3_fl(facecenter[a], 1.0f / facetotvert[a]);
+
+ /* for conversion from BU area / pixel area to reference screen size */
+ BKE_mesh_texspace_get(me, 0, 0, size);
+ fac = ((size[0] + size[1] + size[2]) / 3.0f) / part->simplify_refsize;
+ fac = fac * fac;
+
+ powrate = log(0.5f) / log(part->simplify_rate * 0.5f);
+ if (part->simplify_flag & PART_SIMPLIFY_VIEWPORT)
+ vprate = pow(1.0f - part->simplify_viewport, 5.0);
+ else
+ vprate = 1.0;
+
+ /* set simplification parameters per original face */
+ for (a = 0, elem = elems; a < totorigface; a++, elem++) {
+ area = psys_render_projected_area(ctx->sim.psys, facecenter[a], facearea[a], vprate, &viewport);
+ arearatio = fac * area / facearea[a];
+
+ if ((arearatio < 1.0f || viewport < 1.0f) && elem->totchild) {
+ /* lambda is percentage of elements to keep */
+ lambda = (arearatio < 1.0f) ? powf(arearatio, powrate) : 1.0f;
+ lambda *= viewport;
+
+ lambda = MAX2(lambda, 1.0f / elem->totchild);
+
+ /* compute transition region */
+ t = part->simplify_transition;
+ elem->t = (lambda - t < 0.0f) ? lambda : (lambda + t > 1.0f) ? 1.0f - lambda : t;
+ elem->reduce = 1;
+
+ /* scale at end and beginning of the transition region */
+ elem->scalemax = (lambda + t < 1.0f) ? 1.0f / lambda : 1.0f / (1.0f - elem->t * elem->t / t);
+ elem->scalemin = (lambda + t < 1.0f) ? 0.0f : elem->scalemax * (1.0f - elem->t / t);
+
+ elem->scalemin = sqrtf(elem->scalemin);
+ elem->scalemax = sqrtf(elem->scalemax);
+
+ /* clamp scaling */
+ scaleclamp = (float)min_ii(elem->totchild, 10);
+ elem->scalemin = MIN2(scaleclamp, elem->scalemin);
+ elem->scalemax = MIN2(scaleclamp, elem->scalemax);
+
+ /* extend lambda to include transition */
+ lambda = lambda + elem->t;
+ if (lambda > 1.0f)
+ lambda = 1.0f;
+ }
+ else {
+ lambda = arearatio;
+
+ elem->scalemax = 1.0f; //sqrt(lambda);
+ elem->scalemin = 1.0f; //sqrt(lambda);
+ elem->reduce = 0;
+ }
+
+ elem->lambda = lambda;
+ elem->scalemin = sqrtf(elem->scalemin);
+ elem->scalemax = sqrtf(elem->scalemax);
+ elem->curchild = 0;
+ }
+
+ MEM_freeN(facearea);
+ MEM_freeN(facecenter);
+ MEM_freeN(facetotvert);
+
+ /* move indices and set random number skipping */
+ ctx->skip = MEM_callocN(sizeof(int) * tot, "SimplificationSkip");
+
+ skipped = 0;
+ for (a = 0, newtot = 0; a < tot; a++) {
+ b = (index_mf_to_mpoly) ? DM_origindex_mface_mpoly(index_mf_to_mpoly, index_mp_to_orig, ctx->index[a]) : ctx->index[a];
+
+ if (b != ORIGINDEX_NONE) {
+ if (elems[b].curchild++ < ceil(elems[b].lambda * elems[b].totchild)) {
+ ctx->index[newtot] = ctx->index[a];
+ ctx->skip[newtot] = skipped;
+ skipped = 0;
+ newtot++;
+ }
+ else skipped++;
+ }
+ else skipped++;
+ }
+
+ for (a = 0, elem = elems; a < totorigface; a++, elem++)
+ elem->curchild = 0;
+
+ return newtot;
+}
diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c
index 155299b69c3..9c720126eca 100644
--- a/source/blender/blenkernel/intern/particle_system.c
+++ b/source/blender/blenkernel/intern/particle_system.c
@@ -68,6 +68,7 @@
#include "BLI_kdtree.h"
#include "BLI_kdopbvh.h"
#include "BLI_sort.h"
+#include "BLI_task.h"
#include "BLI_threads.h"
#include "BLI_linklist.h"
@@ -89,6 +90,7 @@
#include "BKE_modifier.h"
#include "BKE_scene.h"
#include "BKE_bvhutils.h"
+#include "BKE_depsgraph.h"
#include "PIL_time.h"
@@ -284,7 +286,7 @@ static void realloc_particles(ParticleSimulationData *sim, int new_totpart)
}
}
-static int get_psys_child_number(struct Scene *scene, ParticleSystem *psys)
+int psys_get_child_number(Scene *scene, ParticleSystem *psys)
{
int nbr;
@@ -296,33 +298,12 @@ static int get_psys_child_number(struct Scene *scene, ParticleSystem *psys)
else
nbr= psys->part->child_nbr;
- return get_render_child_particle_number(&scene->r, nbr);
+ return get_render_child_particle_number(&scene->r, nbr, psys->renderdata != NULL);
}
-static int get_psys_tot_child(struct Scene *scene, ParticleSystem *psys)
+int psys_get_tot_child(Scene *scene, ParticleSystem *psys)
{
- return psys->totpart*get_psys_child_number(scene, psys);
-}
-
-static void alloc_child_particles(ParticleSystem *psys, int tot)
-{
- if (psys->child) {
- /* only re-allocate if we have to */
- if (psys->part->childtype && psys->totchild == tot) {
- memset(psys->child, 0, tot*sizeof(ChildParticle));
- return;
- }
-
- MEM_freeN(psys->child);
- psys->child=NULL;
- psys->totchild=0;
- }
-
- if (psys->part->childtype) {
- psys->totchild= tot;
- if (psys->totchild)
- psys->child= MEM_callocN(psys->totchild*sizeof(ChildParticle), "child_particles");
- }
+ return psys->totpart*psys_get_child_number(scene, psys);
}
/************************************************/
@@ -452,1053 +433,60 @@ void psys_calc_dmcache(Object *ob, DerivedMesh *dm, ParticleSystem *psys)
}
}
-static void distribute_simple_children(Scene *scene, Object *ob, DerivedMesh *finaldm, ParticleSystem *psys)
-{
- ChildParticle *cpa = NULL;
- int i, p;
- int child_nbr= get_psys_child_number(scene, psys);
- int totpart= get_psys_tot_child(scene, psys);
-
- alloc_child_particles(psys, totpart);
-
- cpa = psys->child;
- for (i=0; i<child_nbr; i++) {
- for (p=0; p<psys->totpart; p++,cpa++) {
- float length=2.0;
- cpa->parent=p;
-
- /* create even spherical distribution inside unit sphere */
- while (length>=1.0f) {
- cpa->fuv[0]=2.0f*BLI_frand()-1.0f;
- cpa->fuv[1]=2.0f*BLI_frand()-1.0f;
- cpa->fuv[2]=2.0f*BLI_frand()-1.0f;
- length=len_v3(cpa->fuv);
- }
-
- cpa->num=-1;
- }
- }
- /* dmcache must be updated for parent particles if children from faces is used */
- psys_calc_dmcache(ob, finaldm, psys);
-}
-static void distribute_grid(DerivedMesh *dm, ParticleSystem *psys)
-{
- ParticleData *pa=NULL;
- float min[3], max[3], delta[3], d;
- MVert *mv, *mvert = dm->getVertDataArray(dm,0);
- int totvert=dm->getNumVerts(dm), from=psys->part->from;
- int i, j, k, p, res=psys->part->grid_res, size[3], axis;
-
- /* find bounding box of dm */
- if (totvert > 0) {
- mv=mvert;
- copy_v3_v3(min, mv->co);
- copy_v3_v3(max, mv->co);
- mv++;
- for (i = 1; i < totvert; i++, mv++) {
- minmax_v3v3_v3(min, max, mv->co);
- }
- }
- else {
- zero_v3(min);
- zero_v3(max);
- }
-
- sub_v3_v3v3(delta, max, min);
-
- /* determine major axis */
- axis = axis_dominant_v3_single(delta);
-
- d = delta[axis]/(float)res;
-
- size[axis] = res;
- size[(axis+1)%3] = (int)ceil(delta[(axis+1)%3]/d);
- size[(axis+2)%3] = (int)ceil(delta[(axis+2)%3]/d);
-
- /* float errors grrr.. */
- size[(axis+1)%3] = MIN2(size[(axis+1)%3],res);
- size[(axis+2)%3] = MIN2(size[(axis+2)%3],res);
-
- size[0] = MAX2(size[0], 1);
- size[1] = MAX2(size[1], 1);
- size[2] = MAX2(size[2], 1);
-
- /* no full offset for flat/thin objects */
- min[0]+= d < delta[0] ? d/2.f : delta[0]/2.f;
- min[1]+= d < delta[1] ? d/2.f : delta[1]/2.f;
- min[2]+= d < delta[2] ? d/2.f : delta[2]/2.f;
-
- for (i=0,p=0,pa=psys->particles; i<res; i++) {
- for (j=0; j<res; j++) {
- for (k=0; k<res; k++,p++,pa++) {
- pa->fuv[0] = min[0] + (float)i*d;
- pa->fuv[1] = min[1] + (float)j*d;
- pa->fuv[2] = min[2] + (float)k*d;
- pa->flag |= PARS_UNEXIST;
- pa->hair_index = 0; /* abused in volume calculation */
- }
- }
- }
-
- /* enable particles near verts/edges/faces/inside surface */
- if (from==PART_FROM_VERT) {
- float vec[3];
-
- pa=psys->particles;
-
- min[0] -= d/2.0f;
- min[1] -= d/2.0f;
- min[2] -= d/2.0f;
-
- for (i=0,mv=mvert; i<totvert; i++,mv++) {
- sub_v3_v3v3(vec,mv->co,min);
- vec[0]/=delta[0];
- vec[1]/=delta[1];
- vec[2]/=delta[2];
- pa[((int)(vec[0] * (size[0] - 1)) * res +
- (int)(vec[1] * (size[1] - 1))) * res +
- (int)(vec[2] * (size[2] - 1))].flag &= ~PARS_UNEXIST;
- }
- }
- else if (ELEM(from,PART_FROM_FACE,PART_FROM_VOLUME)) {
- float co1[3], co2[3];
-
- MFace *mface= NULL, *mface_array;
- float v1[3], v2[3], v3[3], v4[4], lambda;
- int a, a1, a2, a0mul, a1mul, a2mul, totface;
- int amax= from==PART_FROM_FACE ? 3 : 1;
-
- totface=dm->getNumTessFaces(dm);
- mface=mface_array=dm->getTessFaceDataArray(dm,CD_MFACE);
-
- for (a=0; a<amax; a++) {
- if (a==0) { a0mul=res*res; a1mul=res; a2mul=1; }
- else if (a==1) { a0mul=res; a1mul=1; a2mul=res*res; }
- else { a0mul=1; a1mul=res*res; a2mul=res; }
-
- for (a1=0; a1<size[(a+1)%3]; a1++) {
- for (a2=0; a2<size[(a+2)%3]; a2++) {
- mface= mface_array;
-
- pa = psys->particles + a1*a1mul + a2*a2mul;
- copy_v3_v3(co1, pa->fuv);
- co1[a] -= d < delta[a] ? d/2.f : delta[a]/2.f;
- copy_v3_v3(co2, co1);
- co2[a] += delta[a] + 0.001f*d;
- co1[a] -= 0.001f*d;
-
- /* lets intersect the faces */
- for (i=0; i<totface; i++,mface++) {
- copy_v3_v3(v1, mvert[mface->v1].co);
- copy_v3_v3(v2, mvert[mface->v2].co);
- copy_v3_v3(v3, mvert[mface->v3].co);
-
- if (isect_axial_line_tri_v3(a, co1, co2, v2, v3, v1, &lambda)) {
- if (from==PART_FROM_FACE)
- (pa+(int)(lambda*size[a])*a0mul)->flag &= ~PARS_UNEXIST;
- else /* store number of intersections */
- (pa+(int)(lambda*size[a])*a0mul)->hair_index++;
- }
- else if (mface->v4) {
- copy_v3_v3(v4, mvert[mface->v4].co);
-
- if (isect_axial_line_tri_v3(a, co1, co2, v4, v1, v3, &lambda)) {
- if (from==PART_FROM_FACE)
- (pa+(int)(lambda*size[a])*a0mul)->flag &= ~PARS_UNEXIST;
- else
- (pa+(int)(lambda*size[a])*a0mul)->hair_index++;
- }
- }
- }
-
- if (from==PART_FROM_VOLUME) {
- int in=pa->hair_index%2;
- if (in) pa->hair_index++;
- for (i=0; i<size[0]; i++) {
- if (in || (pa+i*a0mul)->hair_index%2)
- (pa+i*a0mul)->flag &= ~PARS_UNEXIST;
- /* odd intersections == in->out / out->in */
- /* even intersections -> in stays same */
- in=(in + (pa+i*a0mul)->hair_index) % 2;
- }
- }
- }
- }
- }
- }
-
- if (psys->part->flag & PART_GRID_HEXAGONAL) {
- for (i=0,p=0,pa=psys->particles; i<res; i++) {
- for (j=0; j<res; j++) {
- for (k=0; k<res; k++,p++,pa++) {
- if (j%2)
- pa->fuv[0] += d/2.f;
-
- if (k%2) {
- pa->fuv[0] += d/2.f;
- pa->fuv[1] += d/2.f;
- }
- }
- }
- }
- }
-
- if (psys->part->flag & PART_GRID_INVERT) {
- for (i=0; i<size[0]; i++) {
- for (j=0; j<size[1]; j++) {
- pa=psys->particles + res*(i*res + j);
- for (k=0; k<size[2]; k++, pa++) {
- pa->flag ^= PARS_UNEXIST;
- }
- }
- }
- }
-
- if (psys->part->grid_rand > 0.f) {
- float rfac = d * psys->part->grid_rand;
- for (p=0,pa=psys->particles; p<psys->totpart; p++,pa++) {
- if (pa->flag & PARS_UNEXIST)
- continue;
-
- pa->fuv[0] += rfac * (psys_frand(psys, p + 31) - 0.5f);
- pa->fuv[1] += rfac * (psys_frand(psys, p + 32) - 0.5f);
- pa->fuv[2] += rfac * (psys_frand(psys, p + 33) - 0.5f);
- }
- }
-}
-
-/* modified copy from rayshade.c */
-static void hammersley_create(float *out, int n, int seed, float amount)
-{
- RNG *rng;
- double p, t, offs[2];
- int k, kk;
-
- rng = BLI_rng_new(31415926 + n + seed);
- offs[0] = BLI_rng_get_double(rng) + (double)amount;
- offs[1] = BLI_rng_get_double(rng) + (double)amount;
- BLI_rng_free(rng);
-
- for (k = 0; k < n; k++) {
- t = 0;
- for (p = 0.5, kk = k; kk; p *= 0.5, kk >>= 1)
- if (kk & 1) /* kk mod 2 = 1 */
- t += p;
-
- out[2*k + 0] = fmod((double)k/(double)n + offs[0], 1.0);
- out[2*k + 1] = fmod(t + offs[1], 1.0);
- }
-}
-
-/* almost exact copy of BLI_jitter_init */
-static void init_mv_jit(float *jit, int num, int seed2, float amount)
-{
- RNG *rng;
- float *jit2, x, rad1, rad2, rad3;
- int i, num2;
-
- if (num==0) return;
-
- rad1= (float)(1.0f/sqrtf((float)num));
- rad2= (float)(1.0f/((float)num));
- rad3= (float)sqrtf((float)num)/((float)num);
-
- rng = BLI_rng_new(31415926 + num + seed2);
- x= 0;
- num2 = 2 * num;
- for (i=0; i<num2; i+=2) {
-
- jit[i] = x + amount*rad1*(0.5f - BLI_rng_get_float(rng));
- jit[i+1] = i/(2.0f*num) + amount*rad1*(0.5f - BLI_rng_get_float(rng));
-
- jit[i]-= (float)floor(jit[i]);
- jit[i+1]-= (float)floor(jit[i+1]);
-
- x+= rad3;
- x -= (float)floor(x);
- }
-
- jit2= MEM_mallocN(12 + 2*sizeof(float)*num, "initjit");
-
- for (i=0 ; i<4 ; i++) {
- BLI_jitterate1((float (*)[2])jit, (float (*)[2])jit2, num, rad1);
- BLI_jitterate1((float (*)[2])jit, (float (*)[2])jit2, num, rad1);
- BLI_jitterate2((float (*)[2])jit, (float (*)[2])jit2, num, rad2);
- }
- MEM_freeN(jit2);
- BLI_rng_free(rng);
-}
-
-static void psys_uv_to_w(float u, float v, int quad, float *w)
-{
- float vert[4][3], co[3];
-
- if (!quad) {
- if (u+v > 1.0f)
- v= 1.0f-v;
- else
- u= 1.0f-u;
- }
-
- vert[0][0] = 0.0f; vert[0][1] = 0.0f; vert[0][2] = 0.0f;
- vert[1][0] = 1.0f; vert[1][1] = 0.0f; vert[1][2] = 0.0f;
- vert[2][0] = 1.0f; vert[2][1] = 1.0f; vert[2][2] = 0.0f;
-
- co[0] = u;
- co[1] = v;
- co[2] = 0.0f;
-
- if (quad) {
- vert[3][0] = 0.0f; vert[3][1] = 1.0f; vert[3][2] = 0.0f;
- interp_weights_poly_v3( w,vert, 4, co);
- }
- else {
- interp_weights_poly_v3( w,vert, 3, co);
- w[3] = 0.0f;
- }
-}
-
-/* Find the index in "sum" array before "value" is crossed. */
-static int distribute_binary_search(float *sum, int n, float value)
-{
- int mid, low=0, high=n;
-
- if (value == 0.f)
- return 0;
-
- while (low <= high) {
- mid= (low + high)/2;
-
- if (sum[mid] < value && value <= sum[mid+1])
- return mid;
-
- if (sum[mid] >= value)
- high= mid - 1;
- else if (sum[mid] < value)
- low= mid + 1;
- else
- return mid;
- }
-
- return low;
-}
-
-/* the max number if calls to rng_* funcs within psys_thread_distribute_particle
- * be sure to keep up to date if this changes */
-#define PSYS_RND_DIST_SKIP 2
-
-/* note: this function must be thread safe, for from == PART_FROM_CHILD */
-#define ONLY_WORKING_WITH_PA_VERTS 0
-static void distribute_threads_exec(ParticleThread *thread, ParticleData *pa, ChildParticle *cpa, int p)
-{
- ParticleThreadContext *ctx= thread->ctx;
- Object *ob= ctx->sim.ob;
- DerivedMesh *dm= ctx->dm;
- float *v1, *v2, *v3, *v4, nor[3], orco1[3], co1[3], co2[3], nor1[3];
- float cur_d, min_d, randu, randv;
- int from= ctx->from;
- int cfrom= ctx->cfrom;
- int distr= ctx->distr;
- int i, intersect, tot;
- int rng_skip_tot= PSYS_RND_DIST_SKIP; /* count how many rng_* calls wont need skipping */
-
- if (from == PART_FROM_VERT) {
- /* TODO_PARTICLE - use original index */
- pa->num= ctx->index[p];
- pa->fuv[0] = 1.0f;
- pa->fuv[1] = pa->fuv[2] = pa->fuv[3] = 0.0;
-
-#if ONLY_WORKING_WITH_PA_VERTS
- if (ctx->tree) {
- KDTreeNearest ptn[3];
- int w, maxw;
-
- psys_particle_on_dm(ctx->dm,from,pa->num,pa->num_dmcache,pa->fuv,pa->foffset,co1,0,0,0,orco1,0);
- BKE_mesh_orco_verts_transform((Mesh*)ob->data, &orco1, 1, 1);
- maxw = BLI_kdtree_find_nearest_n(ctx->tree,orco1,ptn,3);
-
- for (w=0; w<maxw; w++) {
- pa->verts[w]=ptn->num;
- }
- }
-#endif
- }
- else if (from == PART_FROM_FACE || from == PART_FROM_VOLUME) {
- MFace *mface;
-
- pa->num = i = ctx->index[p];
- mface = dm->getTessFaceData(dm,i,CD_MFACE);
-
- switch (distr) {
- case PART_DISTR_JIT:
- if (ctx->jitlevel == 1) {
- if (mface->v4)
- psys_uv_to_w(0.5f, 0.5f, mface->v4, pa->fuv);
- else
- psys_uv_to_w(1.0f / 3.0f, 1.0f / 3.0f, mface->v4, pa->fuv);
- }
- else {
- ctx->jitoff[i] = fmod(ctx->jitoff[i],(float)ctx->jitlevel);
- if (!isnan(ctx->jitoff[i])) {
- psys_uv_to_w(ctx->jit[2*(int)ctx->jitoff[i]], ctx->jit[2*(int)ctx->jitoff[i]+1], mface->v4, pa->fuv);
- ctx->jitoff[i]++;
- }
- }
- break;
- case PART_DISTR_RAND:
- randu= BLI_rng_get_float(thread->rng);
- randv= BLI_rng_get_float(thread->rng);
- rng_skip_tot -= 2;
-
- psys_uv_to_w(randu, randv, mface->v4, pa->fuv);
- break;
- }
- pa->foffset= 0.0f;
-
- /* experimental */
- if (from==PART_FROM_VOLUME) {
- MVert *mvert=dm->getVertDataArray(dm,CD_MVERT);
-
- tot=dm->getNumTessFaces(dm);
-
- psys_interpolate_face(mvert,mface,0,0,pa->fuv,co1,nor,0,0,0,0);
-
- normalize_v3(nor);
- mul_v3_fl(nor,-100.0);
-
- add_v3_v3v3(co2,co1,nor);
-
- min_d=2.0;
- intersect=0;
-
- for (i=0,mface=dm->getTessFaceDataArray(dm,CD_MFACE); i<tot; i++,mface++) {
- if (i==pa->num) continue;
-
- v1=mvert[mface->v1].co;
- v2=mvert[mface->v2].co;
- v3=mvert[mface->v3].co;
-
- if (isect_line_tri_v3(co1, co2, v2, v3, v1, &cur_d, 0)) {
- if (cur_d<min_d) {
- min_d=cur_d;
- pa->foffset=cur_d*50.0f; /* to the middle of volume */
- intersect=1;
- }
- }
- if (mface->v4) {
- v4=mvert[mface->v4].co;
-
- if (isect_line_tri_v3(co1, co2, v4, v1, v3, &cur_d, 0)) {
- if (cur_d<min_d) {
- min_d=cur_d;
- pa->foffset=cur_d*50.0f; /* to the middle of volume */
- intersect=1;
- }
- }
- }
- }
- if (intersect==0)
- pa->foffset=0.0;
- else {
- switch (distr) {
- case PART_DISTR_JIT:
- pa->foffset *= ctx->jit[p % (2 * ctx->jitlevel)];
- break;
- case PART_DISTR_RAND:
- pa->foffset *= BLI_frand();
- break;
- }
- }
- }
- }
- else if (from == PART_FROM_CHILD) {
- MFace *mf;
-
- if (ctx->index[p] < 0) {
- cpa->num=0;
- cpa->fuv[0]=cpa->fuv[1]=cpa->fuv[2]=cpa->fuv[3]=0.0f;
- cpa->pa[0]=cpa->pa[1]=cpa->pa[2]=cpa->pa[3]=0;
- return;
- }
-
- mf= dm->getTessFaceData(dm, ctx->index[p], CD_MFACE);
-
- randu= BLI_rng_get_float(thread->rng);
- randv= BLI_rng_get_float(thread->rng);
- rng_skip_tot -= 2;
-
- psys_uv_to_w(randu, randv, mf->v4, cpa->fuv);
-
- cpa->num = ctx->index[p];
-
- if (ctx->tree) {
- KDTreeNearest ptn[10];
- int w,maxw;//, do_seams;
- float maxd /*, mind,dd */, totw= 0.0f;
- int parent[10];
- float pweight[10];
-
- psys_particle_on_dm(dm,cfrom,cpa->num,DMCACHE_ISCHILD,cpa->fuv,cpa->foffset,co1,nor1,NULL,NULL,orco1,NULL);
- BKE_mesh_orco_verts_transform((Mesh*)ob->data, &orco1, 1, 1);
- maxw = BLI_kdtree_find_nearest_n(ctx->tree,orco1,ptn,3);
-
- maxd=ptn[maxw-1].dist;
- /* mind=ptn[0].dist; */ /* UNUSED */
-
- /* the weights here could be done better */
- for (w=0; w<maxw; w++) {
- parent[w]=ptn[w].index;
- pweight[w]=(float)pow(2.0,(double)(-6.0f*ptn[w].dist/maxd));
- }
- for (;w<10; w++) {
- parent[w]=-1;
- pweight[w]=0.0f;
- }
-
- for (w=0,i=0; w<maxw && i<4; w++) {
- if (parent[w]>=0) {
- cpa->pa[i]=parent[w];
- cpa->w[i]=pweight[w];
- totw+=pweight[w];
- i++;
- }
- }
- for (;i<4; i++) {
- cpa->pa[i]=-1;
- cpa->w[i]=0.0f;
- }
-
- if (totw>0.0f) for (w=0; w<4; w++)
- cpa->w[w]/=totw;
-
- cpa->parent=cpa->pa[0];
- }
- }
-
- if (rng_skip_tot > 0) /* should never be below zero */
- BLI_rng_skip(thread->rng, rng_skip_tot);
-}
-
-static void *distribute_threads_exec_cb(void *data)
+/* threaded child particle distribution and path caching */
+void psys_thread_context_init(ParticleThreadContext *ctx, ParticleSimulationData *sim)
{
- ParticleThread *thread= (ParticleThread*)data;
- ParticleSystem *psys= thread->ctx->sim.psys;
- ParticleData *pa;
- ChildParticle *cpa;
- int p, totpart;
-
- if (thread->ctx->from == PART_FROM_CHILD) {
- totpart= psys->totchild;
- cpa= psys->child;
-
- for (p=0; p<totpart; p++, cpa++) {
- if (thread->ctx->skip) /* simplification skip */
- BLI_rng_skip(thread->rng, PSYS_RND_DIST_SKIP * thread->ctx->skip[p]);
-
- if ((p+thread->num) % thread->tot == 0)
- distribute_threads_exec(thread, NULL, cpa, p);
- else /* thread skip */
- BLI_rng_skip(thread->rng, PSYS_RND_DIST_SKIP);
- }
- }
- else {
- totpart= psys->totpart;
- pa= psys->particles + thread->num;
- for (p=thread->num; p<totpart; p+=thread->tot, pa+=thread->tot)
- distribute_threads_exec(thread, pa, NULL, p);
- }
-
- return 0;
+ memset(ctx, 0, sizeof(ParticleThreadContext));
+ ctx->sim = *sim;
+ ctx->dm = ctx->sim.psmd->dm;
+ ctx->ma = give_current_material(sim->ob, sim->psys->part->omat);
}
-static int distribute_compare_orig_index(const void *p1, const void *p2, void *user_data)
-{
- int *orig_index = (int *) user_data;
- int index1 = orig_index[*(const int *)p1];
- int index2 = orig_index[*(const int *)p2];
-
- if (index1 < index2)
- return -1;
- else if (index1 == index2) {
- /* this pointer comparison appears to make qsort stable for glibc,
- * and apparently on solaris too, makes the renders reproducible */
- if (p1 < p2)
- return -1;
- else if (p1 == p2)
- return 0;
- else
- return 1;
- }
- else
- return 1;
-}
+#define MAX_PARTICLES_PER_TASK 256 /* XXX arbitrary - maybe use at least number of points instead for better balancing? */
-static void distribute_invalid(Scene *scene, ParticleSystem *psys, int from)
+BLI_INLINE int ceil_ii(int a, int b)
{
- if (from == PART_FROM_CHILD) {
- ChildParticle *cpa;
- int p, totchild = get_psys_tot_child(scene, psys);
-
- if (psys->child && totchild) {
- for (p=0,cpa=psys->child; p<totchild; p++,cpa++) {
- cpa->fuv[0]=cpa->fuv[1]=cpa->fuv[2]=cpa->fuv[3] = 0.0;
- cpa->foffset= 0.0f;
- cpa->parent=0;
- cpa->pa[0]=cpa->pa[1]=cpa->pa[2]=cpa->pa[3]=0;
- cpa->num= -1;
- }
- }
- }
- else {
- PARTICLE_P;
- LOOP_PARTICLES {
- pa->fuv[0] = pa->fuv[1] = pa->fuv[2] = pa->fuv[3] = 0.0;
- pa->foffset= 0.0f;
- pa->num= -1;
- }
- }
+ return (a + b - 1) / b;
}
-/* Creates a distribution of coordinates on a DerivedMesh */
-/* This is to denote functionality that does not yet work with mesh - only derived mesh */
-static int distribute_threads_init_data(ParticleThread *threads, Scene *scene, DerivedMesh *finaldm, int from)
+void psys_tasks_create(ParticleThreadContext *ctx, int startpart, int endpart, ParticleTask **r_tasks, int *r_numtasks)
{
- ParticleThreadContext *ctx= threads[0].ctx;
- Object *ob= ctx->sim.ob;
- ParticleSystem *psys= ctx->sim.psys;
- ParticleData *pa=0, *tpars= 0;
- ParticleSettings *part;
- ParticleSeam *seams= 0;
- KDTree *tree=0;
- DerivedMesh *dm= NULL;
- float *jit= NULL;
- int i, seed, p=0, totthread= threads[0].tot;
- int cfrom=0;
- int totelem=0, totpart, *particle_element=0, children=0, totseam=0;
- int jitlevel= 1, distr;
- float *element_weight=NULL,*element_sum=NULL,*jitter_offset=NULL, *vweight=NULL;
- float cur, maxweight=0.0, tweight, totweight, inv_totweight, co[3], nor[3], orco[3];
+ ParticleTask *tasks;
+ int numtasks = ceil_ii((endpart - startpart), MAX_PARTICLES_PER_TASK);
+ float particles_per_task = (float)(endpart - startpart) / (float)numtasks, p, pnext;
+ int i;
- if (ELEM(NULL, ob, psys, psys->part))
- return 0;
-
- part=psys->part;
- totpart=psys->totpart;
- if (totpart==0)
- return 0;
-
- if (!finaldm->deformedOnly && !finaldm->getTessFaceDataArray(finaldm, CD_ORIGINDEX)) {
- printf("Can't create particles with the current modifier stack, disable destructive modifiers\n");
-// XXX error("Can't paint with the current modifier stack, disable destructive modifiers");
- return 0;
- }
-
- /* First handle special cases */
- if (from == PART_FROM_CHILD) {
- /* Simple children */
- if (part->childtype != PART_CHILD_FACES) {
- BLI_srandom(31415926 + psys->seed + psys->child_seed);
- distribute_simple_children(scene, ob, finaldm, psys);
- return 0;
- }
- }
- else {
- /* Grid distribution */
- if (part->distr==PART_DISTR_GRID && from != PART_FROM_VERT) {
- BLI_srandom(31415926 + psys->seed);
- dm= CDDM_from_mesh((Mesh*)ob->data);
- DM_ensure_tessface(dm);
- distribute_grid(dm,psys);
- dm->release(dm);
- return 0;
- }
- }
+ tasks = MEM_callocN(sizeof(ParticleTask) * numtasks, "ParticleThread");
+ *r_numtasks = numtasks;
+ *r_tasks = tasks;
- /* Create trees and original coordinates if needed */
- if (from == PART_FROM_CHILD) {
- distr=PART_DISTR_RAND;
- BLI_srandom(31415926 + psys->seed + psys->child_seed);
- dm= finaldm;
-
- /* BMESH ONLY */
- DM_ensure_tessface(dm);
-
- children=1;
-
- tree=BLI_kdtree_new(totpart);
-
- for (p=0,pa=psys->particles; p<totpart; p++,pa++) {
- psys_particle_on_dm(dm,part->from,pa->num,pa->num_dmcache,pa->fuv,pa->foffset,co,nor,0,0,orco,NULL);
- BKE_mesh_orco_verts_transform((Mesh*)ob->data, &orco, 1, 1);
- BLI_kdtree_insert(tree, p, orco);
- }
-
- BLI_kdtree_balance(tree);
-
- totpart = get_psys_tot_child(scene, psys);
- cfrom = from = PART_FROM_FACE;
- }
- else {
- distr = part->distr;
- BLI_srandom(31415926 + psys->seed);
+ p = (float)startpart;
+ for (i = 0; i < numtasks; i++, p = pnext) {
+ pnext = p + particles_per_task;
- if (psys->part->use_modifier_stack)
- dm = finaldm;
- else
- dm= CDDM_from_mesh((Mesh*)ob->data);
-
- /* BMESH ONLY, for verts we don't care about tessfaces */
- if (from != PART_FROM_VERT) {
- DM_ensure_tessface(dm);
- }
-
- /* we need orco for consistent distributions */
- if (!CustomData_has_layer(&dm->vertData, CD_ORCO))
- DM_add_vert_layer(dm, CD_ORCO, CD_ASSIGN, BKE_mesh_orco_verts_get(ob));
-
- if (from == PART_FROM_VERT) {
- MVert *mv= dm->getVertDataArray(dm, CD_MVERT);
- float (*orcodata)[3] = dm->getVertDataArray(dm, CD_ORCO);
- int totvert = dm->getNumVerts(dm);
-
- tree=BLI_kdtree_new(totvert);
-
- for (p=0; p<totvert; p++) {
- if (orcodata) {
- copy_v3_v3(co,orcodata[p]);
- BKE_mesh_orco_verts_transform((Mesh*)ob->data, &co, 1, 1);
- }
- else
- copy_v3_v3(co,mv[p].co);
- BLI_kdtree_insert(tree, p, co);
- }
-
- BLI_kdtree_balance(tree);
- }
- }
-
- /* Get total number of emission elements and allocate needed arrays */
- totelem = (from == PART_FROM_VERT) ? dm->getNumVerts(dm) : dm->getNumTessFaces(dm);
-
- if (totelem == 0) {
- distribute_invalid(scene, psys, children ? PART_FROM_CHILD : 0);
-
- if (G.debug & G_DEBUG)
- fprintf(stderr,"Particle distribution error: Nothing to emit from!\n");
-
- if (dm != finaldm) dm->release(dm);
-
- BLI_kdtree_free(tree);
-
- return 0;
+ tasks[i].ctx = ctx;
+ tasks[i].begin = (int)p;
+ tasks[i].end = min_ii((int)pnext, endpart);
}
-
- element_weight = MEM_callocN(sizeof(float)*totelem, "particle_distribution_weights");
- particle_element= MEM_callocN(sizeof(int)*totpart, "particle_distribution_indexes");
- element_sum = MEM_callocN(sizeof(float)*(totelem+1), "particle_distribution_sum");
- jitter_offset = MEM_callocN(sizeof(float)*totelem, "particle_distribution_jitoff");
-
- /* Calculate weights from face areas */
- if ((part->flag&PART_EDISTR || children) && from != PART_FROM_VERT) {
- MVert *v1, *v2, *v3, *v4;
- float totarea=0.f, co1[3], co2[3], co3[3], co4[3];
- float (*orcodata)[3];
-
- orcodata= dm->getVertDataArray(dm, CD_ORCO);
-
- for (i=0; i<totelem; i++) {
- MFace *mf=dm->getTessFaceData(dm,i,CD_MFACE);
-
- if (orcodata) {
- copy_v3_v3(co1, orcodata[mf->v1]);
- copy_v3_v3(co2, orcodata[mf->v2]);
- copy_v3_v3(co3, orcodata[mf->v3]);
- BKE_mesh_orco_verts_transform((Mesh*)ob->data, &co1, 1, 1);
- BKE_mesh_orco_verts_transform((Mesh*)ob->data, &co2, 1, 1);
- BKE_mesh_orco_verts_transform((Mesh*)ob->data, &co3, 1, 1);
- if (mf->v4) {
- copy_v3_v3(co4, orcodata[mf->v4]);
- BKE_mesh_orco_verts_transform((Mesh*)ob->data, &co4, 1, 1);
- }
- }
- else {
- v1= (MVert*)dm->getVertData(dm,mf->v1,CD_MVERT);
- v2= (MVert*)dm->getVertData(dm,mf->v2,CD_MVERT);
- v3= (MVert*)dm->getVertData(dm,mf->v3,CD_MVERT);
- copy_v3_v3(co1, v1->co);
- copy_v3_v3(co2, v2->co);
- copy_v3_v3(co3, v3->co);
- if (mf->v4) {
- v4= (MVert*)dm->getVertData(dm,mf->v4,CD_MVERT);
- copy_v3_v3(co4, v4->co);
- }
- }
-
- cur = mf->v4 ? area_quad_v3(co1, co2, co3, co4) : area_tri_v3(co1, co2, co3);
-
- if (cur > maxweight)
- maxweight = cur;
-
- element_weight[i] = cur;
- totarea += cur;
- }
-
- for (i=0; i<totelem; i++)
- element_weight[i] /= totarea;
-
- maxweight /= totarea;
- }
- else {
- float min=1.0f/(float)(MIN2(totelem,totpart));
- for (i=0; i<totelem; i++)
- element_weight[i]=min;
- maxweight=min;
- }
-
- /* Calculate weights from vgroup */
- vweight = psys_cache_vgroup(dm,psys,PSYS_VG_DENSITY);
-
- if (vweight) {
- if (from==PART_FROM_VERT) {
- for (i=0;i<totelem; i++)
- element_weight[i]*=vweight[i];
- }
- else { /* PART_FROM_FACE / PART_FROM_VOLUME */
- for (i=0;i<totelem; i++) {
- MFace *mf=dm->getTessFaceData(dm,i,CD_MFACE);
- tweight = vweight[mf->v1] + vweight[mf->v2] + vweight[mf->v3];
-
- if (mf->v4) {
- tweight += vweight[mf->v4];
- tweight /= 4.0f;
- }
- else {
- tweight /= 3.0f;
- }
-
- element_weight[i]*=tweight;
- }
- }
- MEM_freeN(vweight);
- }
-
- /* Calculate total weight of all elements */
- totweight= 0.0f;
- for (i=0;i<totelem; i++)
- totweight += element_weight[i];
-
- inv_totweight = (totweight > 0.f ? 1.f/totweight : 0.f);
-
- /* Calculate cumulative weights */
- element_sum[0] = 0.0f;
- for (i=0; i<totelem; i++)
- element_sum[i+1] = element_sum[i] + element_weight[i] * inv_totweight;
-
- /* Finally assign elements to particles */
- if ((part->flag&PART_TRAND) || (part->simplify_flag&PART_SIMPLIFY_ENABLE)) {
- float pos;
-
- for (p=0; p<totpart; p++) {
- /* In theory element_sum[totelem] should be 1.0, but due to float errors this is not necessarily always true, so scale pos accordingly. */
- pos= BLI_frand() * element_sum[totelem];
- particle_element[p] = distribute_binary_search(element_sum, totelem, pos);
- particle_element[p] = MIN2(totelem-1, particle_element[p]);
- jitter_offset[particle_element[p]] = pos;
- }
- }
- else {
- double step, pos;
-
- step= (totpart < 2) ? 0.5 : 1.0/(double)totpart;
- pos= 1e-6; /* tiny offset to avoid zero weight face */
- i= 0;
-
- for (p=0; p<totpart; p++, pos+=step) {
- while ((i < totelem) && (pos > (double)element_sum[i + 1]))
- i++;
-
- particle_element[p] = MIN2(totelem-1, i);
-
- /* avoid zero weight face */
- if (p == totpart-1 && element_weight[particle_element[p]] == 0.0f)
- particle_element[p] = particle_element[p-1];
-
- jitter_offset[particle_element[p]] = pos;
- }
- }
-
- MEM_freeN(element_sum);
-
- /* For hair, sort by origindex (allows optimization's in rendering), */
- /* however with virtual parents the children need to be in random order. */
- if (part->type == PART_HAIR && !(part->childtype==PART_CHILD_FACES && part->parents!=0.0f)) {
- int *orig_index = NULL;
-
- if (from == PART_FROM_VERT) {
- if (dm->numVertData)
- orig_index = dm->getVertDataArray(dm, CD_ORIGINDEX);
- }
- else {
- if (dm->numTessFaceData)
- orig_index = dm->getTessFaceDataArray(dm, CD_ORIGINDEX);
- }
-
- if (orig_index) {
- BLI_qsort_r(particle_element, totpart, sizeof(int), distribute_compare_orig_index, orig_index);
- }
- }
-
- /* Create jittering if needed */
- if (distr==PART_DISTR_JIT && ELEM(from,PART_FROM_FACE,PART_FROM_VOLUME)) {
- jitlevel= part->userjit;
-
- if (jitlevel == 0) {
- jitlevel= totpart/totelem;
- if (part->flag & PART_EDISTR) jitlevel*= 2; /* looks better in general, not very scietific */
- if (jitlevel<3) jitlevel= 3;
- }
-
- jit= MEM_callocN((2+ jitlevel*2)*sizeof(float), "jit");
-
- /* for small amounts of particles we use regular jitter since it looks
- * a bit better, for larger amounts we switch to hammersley sequence
- * because it is much faster */
- if (jitlevel < 25)
- init_mv_jit(jit, jitlevel, psys->seed, part->jitfac);
- else
- hammersley_create(jit, jitlevel+1, psys->seed, part->jitfac);
- BLI_array_randomize(jit, 2*sizeof(float), jitlevel, psys->seed); /* for custom jit or even distribution */
- }
-
- /* Setup things for threaded distribution */
- ctx->tree= tree;
- ctx->seams= seams;
- ctx->totseam= totseam;
- ctx->sim.psys= psys;
- ctx->index= particle_element;
- ctx->jit= jit;
- ctx->jitlevel= jitlevel;
- ctx->jitoff= jitter_offset;
- ctx->weight= element_weight;
- ctx->maxweight= maxweight;
- ctx->from= (children) ? PART_FROM_CHILD : from;
- ctx->cfrom= cfrom;
- ctx->distr= distr;
- ctx->dm= dm;
- ctx->tpars= tpars;
-
- if (children) {
- totpart= psys_render_simplify_distribution(ctx, totpart);
- alloc_child_particles(psys, totpart);
- }
-
- if (!children || psys->totchild < 10000)
- totthread= 1;
-
- seed= 31415926 + ctx->sim.psys->seed;
- for (i=0; i<totthread; i++) {
- threads[i].rng= BLI_rng_new(seed);
- threads[i].tot= totthread;
- }
-
- return 1;
}
-static void distribute_particles_on_dm(ParticleSimulationData *sim, int from)
+void psys_tasks_free(ParticleTask *tasks, int numtasks)
{
- DerivedMesh *finaldm = sim->psmd->dm;
- ListBase threads;
- ParticleThread *pthreads;
- ParticleThreadContext *ctx;
- int i, totthread;
-
- pthreads= psys_threads_create(sim);
-
- if (!distribute_threads_init_data(pthreads, sim->scene, finaldm, from)) {
- psys_threads_free(pthreads);
- return;
- }
-
- totthread= pthreads[0].tot;
- if (totthread > 1) {
- BLI_init_threads(&threads, distribute_threads_exec_cb, totthread);
-
- for (i=0; i<totthread; i++)
- BLI_insert_thread(&threads, &pthreads[i]);
-
- BLI_end_threads(&threads);
- }
- else
- distribute_threads_exec_cb(&pthreads[0]);
-
- psys_calc_dmcache(sim->ob, finaldm, sim->psys);
-
- ctx= pthreads[0].ctx;
- if (ctx->dm != finaldm)
- ctx->dm->release(ctx->dm);
-
- psys_threads_free(pthreads);
-}
-
-/* ready for future use, to emit particles without geometry */
-static void distribute_particles_on_shape(ParticleSimulationData *sim, int UNUSED(from))
-{
- distribute_invalid(sim->scene, sim->psys, 0);
-
- fprintf(stderr,"Shape emission not yet possible!\n");
-}
-
-static void distribute_particles(ParticleSimulationData *sim, int from)
-{
- PARTICLE_PSMD;
- int distr_error=0;
-
- if (psmd) {
- if (psmd->dm)
- distribute_particles_on_dm(sim, from);
- else
- distr_error=1;
- }
- else
- distribute_particles_on_shape(sim, from);
-
- if (distr_error) {
- distribute_invalid(sim->scene, sim->psys, from);
-
- fprintf(stderr,"Particle distribution error!\n");
- }
-}
-
-/* threaded child particle distribution and path caching */
-ParticleThread *psys_threads_create(ParticleSimulationData *sim)
-{
- ParticleThread *threads;
- ParticleThreadContext *ctx;
- int i, totthread = BKE_scene_num_threads(sim->scene);
+ int i;
- threads= MEM_callocN(sizeof(ParticleThread)*totthread, "ParticleThread");
- ctx= MEM_callocN(sizeof(ParticleThreadContext), "ParticleThreadContext");
-
- ctx->sim = *sim;
- ctx->dm= ctx->sim.psmd->dm;
- ctx->ma= give_current_material(sim->ob, sim->psys->part->omat);
-
- memset(threads, 0, sizeof(ParticleThread)*totthread);
-
- for (i=0; i<totthread; i++) {
- threads[i].ctx= ctx;
- threads[i].num= i;
- threads[i].tot= totthread;
+ /* threads */
+ for (i = 0; i < numtasks; ++i) {
+ if (tasks[i].rng)
+ BLI_rng_free(tasks[i].rng);
+ if (tasks[i].rng_path)
+ BLI_rng_free(tasks[i].rng_path);
}
- return threads;
+ MEM_freeN(tasks);
}
-void psys_threads_free(ParticleThread *threads)
+void psys_thread_context_free(ParticleThreadContext *ctx)
{
- ParticleThreadContext *ctx= threads[0].ctx;
- int i, totthread= threads[0].tot;
-
/* path caching */
if (ctx->vg_length)
MEM_freeN(ctx->vg_length);
@@ -1527,17 +515,6 @@ void psys_threads_free(ParticleThread *threads)
if (ctx->seams) MEM_freeN(ctx->seams);
//if (ctx->vertpart) MEM_freeN(ctx->vertpart);
BLI_kdtree_free(ctx->tree);
-
- /* threads */
- for (i=0; i<totthread; i++) {
- if (threads[i].rng)
- BLI_rng_free(threads[i].rng);
- if (threads[i].rng_path)
- BLI_rng_free(threads[i].rng_path);
- }
-
- MEM_freeN(ctx);
- MEM_freeN(threads);
}
static void initialize_particle_texture(ParticleSimulationData *sim, ParticleData *pa, int p)
@@ -1578,22 +555,44 @@ void initialize_particle(ParticleSimulationData *sim, ParticleData *pa)
/* usage other than straight after distribute has to handle this index by itself - jahka*/
//pa->num_dmcache = DMCACHE_NOTFOUND; /* assume we don't have a derived mesh face */
}
+
static void initialize_all_particles(ParticleSimulationData *sim)
{
ParticleSystem *psys = sim->psys;
+ ParticleSettings *part = psys->part;
+ /* Grid distributionsets UNEXIST flag, need to take care of
+ * it here because later this flag is being reset.
+ *
+ * We can't do it for any distribution, because it'll then
+ * conflict with texture influence, which does not free
+ * unexisting particles and only sets flag.
+ *
+ * It's not so bad, because only grid distribution sets
+ * UNEXIST flag.
+ */
+ const bool emit_from_volume_grid = (part->distr == PART_DISTR_GRID) &&
+ (!ELEM(part->from, PART_FROM_VERT, PART_FROM_CHILD));
+ PARTICLE_P;
+ LOOP_PARTICLES {
+ if (!(emit_from_volume_grid && (pa->flag & PARS_UNEXIST) != 0)) {
+ initialize_particle(sim, pa);
+ }
+ }
+}
+
+static void free_unexisting_particles(ParticleSimulationData *sim)
+{
+ ParticleSystem *psys = sim->psys;
PARTICLE_P;
psys->totunexist = 0;
LOOP_PARTICLES {
- if ((pa->flag & PARS_UNEXIST)==0)
- initialize_particle(sim, pa);
-
- if (pa->flag & PARS_UNEXIST)
+ if (pa->flag & PARS_UNEXIST) {
psys->totunexist++;
+ }
}
- /* Free unexisting particles. */
if (psys->totpart && psys->totunexist == psys->totpart) {
if (psys->particles->boid)
MEM_freeN(psys->particles->boid);
@@ -1625,8 +624,9 @@ static void initialize_all_particles(ParticleSimulationData *sim)
if (psys->particles->boid) {
BoidParticle *newboids = MEM_callocN(psys->totpart * sizeof(BoidParticle), "boid particles");
- LOOP_PARTICLES
+ LOOP_PARTICLES {
pa->boid = newboids++;
+ }
}
}
@@ -1670,7 +670,7 @@ static void get_angular_velocity_vector(short avemode, ParticleKey *state, float
}
}
-void psys_get_birth_coordinates(ParticleSimulationData *sim, ParticleData *pa, ParticleKey *state, float dtime, float cfra)
+void psys_get_birth_coords(ParticleSimulationData *sim, ParticleData *pa, ParticleKey *state, float dtime, float cfra)
{
Object *ob = sim->ob;
ParticleSystem *psys = sim->psys;
@@ -2002,7 +1002,7 @@ void reset_particle(ParticleSimulationData *sim, ParticleData *pa, float dtime,
psys->flag |= PSYS_OB_ANIM_RESTORE;
}
- psys_get_birth_coordinates(sim, pa, &pa->state, dtime, cfra);
+ psys_get_birth_coords(sim, pa, &pa->state, dtime, cfra);
/* Initialize particle settings which depends on texture.
*
@@ -2215,7 +1215,7 @@ void psys_get_pointcache_start_end(Scene *scene, ParticleSystem *psys, int *sfra
ParticleSettings *part = psys->part;
*sfra = MAX2(1, (int)part->sta);
- *efra = MIN2((int)(part->end + part->lifetime + 1.0f), scene->r.efra);
+ *efra = MIN2((int)(part->end + part->lifetime + 1.0f), MAX2(scene->r.pefra, scene->r.efra));
}
/************************************************/
@@ -2764,24 +1764,6 @@ static void sph_force_cb(void *sphdata_v, ParticleKey *state, float *force, floa
sphdata->pass++;
}
-/* powf is really slow for raising to integer powers. */
-MINLINE float pow2(float x)
-{
- return x * x;
-}
-MINLINE float pow3(float x)
-{
- return pow2(x) * x;
-}
-MINLINE float pow4(float x)
-{
- return pow2(pow2(x));
-}
-MINLINE float pow7(float x)
-{
- return pow2(pow3(x)) * x;
-}
-
static void sphclassical_density_accum_cb(void *userdata, int index, float UNUSED(squared_dist))
{
SPHRangeData *pfr = (SPHRangeData *)userdata;
@@ -2803,7 +1785,7 @@ static void sphclassical_density_accum_cb(void *userdata, int index, float UNUSE
/* Smoothing factor. Utilise the Wendland kernel. gnuplot:
* q1(x) = (2.0 - x)**4 * ( 1.0 + 2.0 * x)
* plot [0:2] q1(x) */
- q = qfac / pow3(pfr->h) * pow4(2.0f - rij_h) * ( 1.0f + 2.0f * rij_h);
+ q = qfac / pow3f(pfr->h) * pow4f(2.0f - rij_h) * ( 1.0f + 2.0f * rij_h);
q *= pfr->npsys->part->mass;
if (pfr->use_size)
@@ -2857,7 +1839,7 @@ static void sphclassical_force_cb(void *sphdata_v, ParticleKey *state, float *fo
float rest_density = fluid->rest_density * (fluid->flag & SPH_FAC_DENSITY ? 4.77f : 1.0f);
// Use speed of sound squared
- float stiffness = pow2(fluid->stiffness_k);
+ float stiffness = pow2f(fluid->stiffness_k);
ParticleData *npa;
float vec[3];
@@ -2878,10 +1860,10 @@ static void sphclassical_force_cb(void *sphdata_v, ParticleKey *state, float *fo
pfr.pa = pa;
sph_evaluate_func(NULL, psys, state->co, &pfr, interaction_radius, sphclassical_neighbour_accum_cb);
- pressure = stiffness * (pow7(pa->sphdensity / rest_density) - 1.0f);
+ pressure = stiffness * (pow7f(pa->sphdensity / rest_density) - 1.0f);
/* multiply by mass so that we return a force, not accel */
- qfac2 *= sphdata->mass / pow3(pfr.h);
+ qfac2 *= sphdata->mass / pow3f(pfr.h);
pfn = pfr.neighbors;
for (i = 0; i < pfr.tot_neighbors; i++, pfn++) {
@@ -2902,19 +1884,19 @@ static void sphclassical_force_cb(void *sphdata_v, ParticleKey *state, float *fo
if (rij_h > 2.0f)
continue;
- npressure = stiffness * (pow7(npa->sphdensity / rest_density) - 1.0f);
+ npressure = stiffness * (pow7f(npa->sphdensity / rest_density) - 1.0f);
/* First derivative of smoothing factor. Utilise the Wendland kernel.
* gnuplot:
* q2(x) = 2.0 * (2.0 - x)**4 - 4.0 * (2.0 - x)**3 * (1.0 + 2.0 * x)
* plot [0:2] q2(x)
* Particles > 2h away are excluded above. */
- dq = qfac2 * (2.0f * pow4(2.0f - rij_h) - 4.0f * pow3(2.0f - rij_h) * (1.0f + 2.0f * rij_h) );
+ dq = qfac2 * (2.0f * pow4f(2.0f - rij_h) - 4.0f * pow3f(2.0f - rij_h) * (1.0f + 2.0f * rij_h) );
if (pfn->psys->part->flag & PART_SIZEMASS)
dq *= npa->size;
- pressureTerm = pressure / pow2(pa->sphdensity) + npressure / pow2(npa->sphdensity);
+ pressureTerm = pressure / pow2f(pa->sphdensity) + npressure / pow2f(npa->sphdensity);
/* Note that 'minus' is removed, because vec = vecBA, not vecAB.
* This applies to the viscosity calculation below, too. */
@@ -3128,7 +2110,7 @@ static void basic_integrate(ParticleSimulationData *sim, int p, float dfra, floa
tkey.time=pa->state.time;
if (part->type != PART_HAIR) {
- if (do_guides(sim->psys->effectors, &tkey, p, time)) {
+ if (do_guides(sim->psys->part, sim->psys->effectors, &tkey, p, time)) {
copy_v3_v3(pa->state.co,tkey.co);
/* guides don't produce valid velocity */
sub_v3_v3v3(pa->state.vel, tkey.co, pa->prev_state.co);
@@ -3495,10 +2477,6 @@ static int collision_sphere_to_edges(ParticleCollision *col, float radius, Parti
int i;
for (i=0; i<3; i++) {
- /* in case of a quad, no need to check "edge" that goes through face twice */
- if ((pce->x[3] && i==2))
- continue;
-
cur = edge+i;
cur->x[0] = pce->x[i]; cur->x[1] = pce->x[(i+1)%3];
cur->v[0] = pce->v[i]; cur->v[1] = pce->v[(i+1)%3];
@@ -3542,10 +2520,6 @@ static int collision_sphere_to_verts(ParticleCollision *col, float radius, Parti
int i;
for (i=0; i<3; i++) {
- /* in case of quad, only check one vert the first time */
- if (pce->x[3] && i != 1)
- continue;
-
cur = vert+i;
cur->x[0] = pce->x[i];
cur->v[0] = pce->v[i];
@@ -3573,21 +2547,19 @@ void BKE_psys_collision_neartest_cb(void *userdata, int index, const BVHTreeRay
{
ParticleCollision *col = (ParticleCollision *) userdata;
ParticleCollisionElement pce;
- MFace *face = col->md->mfaces + index;
+ const MVertTri *vt = &col->md->tri[index];
MVert *x = col->md->x;
MVert *v = col->md->current_v;
float t = hit->dist/col->original_ray_length;
int collision = 0;
- pce.x[0] = x[face->v1].co;
- pce.x[1] = x[face->v2].co;
- pce.x[2] = x[face->v3].co;
- pce.x[3] = face->v4 ? x[face->v4].co : NULL;
+ pce.x[0] = x[vt->tri[0]].co;
+ pce.x[1] = x[vt->tri[1]].co;
+ pce.x[2] = x[vt->tri[2]].co;
- pce.v[0] = v[face->v1].co;
- pce.v[1] = v[face->v2].co;
- pce.v[2] = v[face->v3].co;
- pce.v[3] = face->v4 ? v[face->v4].co : NULL;
+ pce.v[0] = v[vt->tri[0]].co;
+ pce.v[1] = v[vt->tri[1]].co;
+ pce.v[2] = v[vt->tri[2]].co;
pce.tot = 3;
pce.inside = 0;
@@ -3597,34 +2569,24 @@ void BKE_psys_collision_neartest_cb(void *userdata, int index, const BVHTreeRay
if (col->hit == col->current && col->pce.index == index && col->pce.tot == 3)
return;
- do {
- collision = collision_sphere_to_tri(col, ray->radius, &pce, &t);
- if (col->pce.inside == 0) {
- collision += collision_sphere_to_edges(col, ray->radius, &pce, &t);
- collision += collision_sphere_to_verts(col, ray->radius, &pce, &t);
- }
-
- if (collision) {
- hit->dist = col->original_ray_length * t;
- hit->index = index;
-
- collision_point_velocity(&col->pce);
-
- col->hit = col->current;
- }
+ collision = collision_sphere_to_tri(col, ray->radius, &pce, &t);
+ if (col->pce.inside == 0) {
+ collision += collision_sphere_to_edges(col, ray->radius, &pce, &t);
+ collision += collision_sphere_to_verts(col, ray->radius, &pce, &t);
+ }
- pce.x[1] = pce.x[2];
- pce.x[2] = pce.x[3];
- pce.x[3] = NULL;
+ if (collision) {
+ hit->dist = col->original_ray_length * t;
+ hit->index = index;
- pce.v[1] = pce.v[2];
- pce.v[2] = pce.v[3];
- pce.v[3] = NULL;
+ collision_point_velocity(&col->pce);
- } while (pce.x[2]);
+ col->hit = col->current;
+ }
}
static int collision_detect(ParticleData *pa, ParticleCollision *col, BVHTreeRayHit *hit, ListBase *colliders)
{
+ const int raycast_flag = BVH_RAYCAST_DEFAULT & ~(BVH_RAYCAST_WATERTIGHT);
ColliderCache *coll;
float ray_dir[3];
@@ -3633,7 +2595,7 @@ static int collision_detect(ParticleData *pa, ParticleCollision *col, BVHTreeRay
sub_v3_v3v3(ray_dir, col->co2, col->co1);
hit->index = -1;
- hit->dist = col->original_ray_length = len_v3(ray_dir);
+ hit->dist = col->original_ray_length = normalize_v3(ray_dir);
col->pce.inside = 0;
/* even if particle is stationary we want to check for moving colliders */
@@ -3655,8 +2617,11 @@ static int collision_detect(ParticleData *pa, ParticleCollision *col, BVHTreeRay
col->fac1 = (col->old_cfra - coll->collmd->time_x) / (coll->collmd->time_xnew - coll->collmd->time_x);
col->fac2 = (col->cfra - coll->collmd->time_x) / (coll->collmd->time_xnew - coll->collmd->time_x);
- if (col->md && col->md->bvhtree)
- BLI_bvhtree_ray_cast(col->md->bvhtree, col->co1, ray_dir, col->radius, hit, BKE_psys_collision_neartest_cb, col);
+ if (col->md && col->md->bvhtree) {
+ BLI_bvhtree_ray_cast_ex(
+ col->md->bvhtree, col->co1, ray_dir, col->radius, hit,
+ BKE_psys_collision_neartest_cb, col, raycast_flag);
+ }
}
return hit->index >= 0;
@@ -3923,7 +2888,7 @@ static void psys_update_path_cache(ParticleSimulationData *sim, float cfra)
Base *base;
int distr=0, alloc=0, skip=0;
- if ((psys->part->childtype && psys->totchild != get_psys_tot_child(sim->scene, psys)) || psys->recalc&PSYS_RECALC_RESET)
+ if ((psys->part->childtype && psys->totchild != psys_get_tot_child(sim->scene, psys)) || psys->recalc&PSYS_RECALC_RESET)
alloc=1;
if (alloc || psys->recalc&PSYS_RECALC_CHILD || (psys->vgroup[PSYS_VG_DENSITY] && (sim->ob && sim->ob->mode & OB_MODE_WEIGHT_PAINT)))
@@ -3933,7 +2898,7 @@ static void psys_update_path_cache(ParticleSimulationData *sim, float cfra)
if (alloc)
realloc_particles(sim, sim->psys->totpart);
- if (get_psys_tot_child(sim->scene, psys)) {
+ if (psys_get_tot_child(sim->scene, psys)) {
/* don't generate children while computing the hair keys */
if (!(psys->part->type == PART_HAIR) || (psys->flag & PSYS_HAIR_DONE)) {
distribute_particles(sim, PART_FROM_CHILD);
@@ -3994,125 +2959,234 @@ static void psys_update_path_cache(ParticleSimulationData *sim, float cfra)
psys_free_path_cache(psys, NULL);
}
-static void do_hair_dynamics(ParticleSimulationData *sim)
+static bool psys_hair_use_simulation(ParticleData *pa, float max_length)
{
- ParticleSystem *psys = sim->psys;
- DerivedMesh *dm = psys->hair_in_dm;
- MVert *mvert = NULL;
- MEdge *medge = NULL;
- MDeformVert *dvert = NULL;
+ /* Minimum segment length relative to average length.
+ * Hairs with segments below this length will be excluded from the simulation,
+ * because otherwise the solver will become unstable.
+ * The hair system should always make sure the hair segments have reasonable length ratios,
+ * but this can happen in old files when e.g. cutting hair.
+ */
+ const float min_length = 0.1f * max_length;
+
HairKey *key;
- PARTICLE_P;
- int totpoint = 0;
- int totedge;
int k;
- float hairmat[4][4];
- float (*deformedVerts)[3];
-
- if (!psys->clmd) {
- psys->clmd = (ClothModifierData*)modifier_new(eModifierType_Cloth);
- psys->clmd->sim_parms->goalspring = 0.0f;
- psys->clmd->sim_parms->vel_damping = 1.0f;
- psys->clmd->sim_parms->flags |= CLOTH_SIMSETTINGS_FLAG_GOAL|CLOTH_SIMSETTINGS_FLAG_NO_SPRING_COMPRESS;
- psys->clmd->coll_parms->flags &= ~CLOTH_COLLSETTINGS_FLAG_SELF;
+
+ if (pa->totkey < 2)
+ return false;
+
+ for (k=1, key=pa->hair+1; k<pa->totkey; k++,key++) {
+ float length = len_v3v3(key->co, (key-1)->co);
+ if (length < min_length)
+ return false;
}
+
+ return true;
+}
- /* create a dm from hair vertices */
- LOOP_PARTICLES
- totpoint += pa->totkey;
-
- totedge = totpoint;
- totpoint += psys->totpart;
-
- if (dm && (totpoint != dm->getNumVerts(dm) || totedge != dm->getNumEdges(dm))) {
- dm->release(dm);
- dm = psys->hair_in_dm = NULL;
+static MDeformVert *hair_set_pinning(MDeformVert *dvert, float weight)
+{
+ if (dvert) {
+ if (!dvert->totweight) {
+ dvert->dw = MEM_callocN(sizeof(MDeformWeight), "deformWeight");
+ dvert->totweight = 1;
+ }
+
+ dvert->dw->weight = weight;
+ dvert++;
}
+ return dvert;
+}
+static void hair_create_input_dm(ParticleSimulationData *sim, int totpoint, int totedge, DerivedMesh **r_dm, ClothHairData **r_hairdata)
+{
+ ParticleSystem *psys = sim->psys;
+ ParticleSettings *part = psys->part;
+ DerivedMesh *dm;
+ ClothHairData *hairdata;
+ MVert *mvert;
+ MEdge *medge;
+ MDeformVert *dvert;
+ HairKey *key;
+ PARTICLE_P;
+ int k, hair_index;
+ float hairmat[4][4];
+ float max_length;
+ float hair_radius;
+
+ dm = *r_dm;
if (!dm) {
- dm = psys->hair_in_dm = CDDM_new(totpoint, totedge, 0, 0, 0);
+ *r_dm = dm = CDDM_new(totpoint, totedge, 0, 0, 0);
DM_add_vert_layer(dm, CD_MDEFORMVERT, CD_CALLOC, NULL);
}
-
mvert = CDDM_get_verts(dm);
medge = CDDM_get_edges(dm);
dvert = DM_get_vert_data_layer(dm, CD_MDEFORMVERT);
-
+
+ hairdata = *r_hairdata;
+ if (!hairdata) {
+ *r_hairdata = hairdata = MEM_mallocN(sizeof(ClothHairData) * totpoint, "hair data");
+ }
+
+ /* calculate maximum segment length */
+ max_length = 0.0f;
+ LOOP_PARTICLES {
+ for (k=1, key=pa->hair+1; k<pa->totkey; k++,key++) {
+ float length = len_v3v3(key->co, (key-1)->co);
+ if (max_length < length)
+ max_length = length;
+ }
+ }
+
psys->clmd->sim_parms->vgroup_mass = 1;
-
+
+ /* XXX placeholder for more flexible future hair settings */
+ hair_radius = part->size;
+
/* make vgroup for pin roots etc.. */
- psys->particles->hair_index = 1;
+ hair_index = 1;
LOOP_PARTICLES {
- if (p)
- pa->hair_index = (pa-1)->hair_index + (pa-1)->totkey + 1;
-
+ float root_mat[4][4];
+ float bending_stiffness;
+ bool use_hair;
+
+ pa->hair_index = hair_index;
+ use_hair = psys_hair_use_simulation(pa, max_length);
+
psys_mat_hair_to_object(sim->ob, sim->psmd->dm, psys->part->from, pa, hairmat);
-
+ mul_m4_m4m4(root_mat, sim->ob->obmat, hairmat);
+ normalize_m4(root_mat);
+
+ bending_stiffness = CLAMPIS(1.0f - part->bending_random * psys_frand(psys, p + 666), 0.0f, 1.0f);
+
for (k=0, key=pa->hair; k<pa->totkey; k++,key++) {
+ ClothHairData *hair;
+ float *co, *co_next;
+
+ co = key->co;
+ co_next = (key+1)->co;
/* create fake root before actual root to resist bending */
if (k==0) {
- float temp[3];
- sub_v3_v3v3(temp, key->co, (key+1)->co);
- copy_v3_v3(mvert->co, key->co);
- add_v3_v3v3(mvert->co, mvert->co, temp);
+ hair = &psys->clmd->hairdata[pa->hair_index - 1];
+ copy_v3_v3(hair->loc, root_mat[3]);
+ copy_m3_m4(hair->rot, root_mat);
+
+ hair->radius = hair_radius;
+ hair->bending_stiffness = bending_stiffness;
+
+ add_v3_v3v3(mvert->co, co, co);
+ sub_v3_v3(mvert->co, co_next);
mul_m4_v3(hairmat, mvert->co);
- mvert++;
-
+
medge->v1 = pa->hair_index - 1;
medge->v2 = pa->hair_index;
+
+ dvert = hair_set_pinning(dvert, 1.0f);
+
+ mvert++;
medge++;
-
- if (dvert) {
- if (!dvert->totweight) {
- dvert->dw = MEM_callocN(sizeof(MDeformWeight), "deformWeight");
- dvert->totweight = 1;
- }
-
- dvert->dw->weight = 1.0f;
- dvert++;
- }
}
-
- copy_v3_v3(mvert->co, key->co);
+
+ /* store root transform in cloth data */
+ hair = &psys->clmd->hairdata[pa->hair_index + k];
+ copy_v3_v3(hair->loc, root_mat[3]);
+ copy_m3_m4(hair->rot, root_mat);
+
+ hair->radius = hair_radius;
+ hair->bending_stiffness = bending_stiffness;
+
+ copy_v3_v3(mvert->co, co);
mul_m4_v3(hairmat, mvert->co);
- mvert++;
if (k) {
medge->v1 = pa->hair_index + k - 1;
medge->v2 = pa->hair_index + k;
- medge++;
- }
-
- if (dvert) {
- if (!dvert->totweight) {
- dvert->dw = MEM_callocN(sizeof(MDeformWeight), "deformWeight");
- dvert->totweight = 1;
- }
- /* roots should be 1.0, the rest can be anything from 0.0 to 1.0 */
- dvert->dw->weight = key->weight;
- dvert++;
}
+
+ /* roots and disabled hairs should be 1.0, the rest can be anything from 0.0 to 1.0 */
+ if (use_hair)
+ dvert = hair_set_pinning(dvert, key->weight);
+ else
+ dvert = hair_set_pinning(dvert, 1.0f);
+
+ mvert++;
+ if (k)
+ medge++;
}
+
+ hair_index += pa->totkey + 1;
}
+}
+static void do_hair_dynamics(ParticleSimulationData *sim)
+{
+ ParticleSystem *psys = sim->psys;
+ PARTICLE_P;
+ EffectorWeights *clmd_effweights;
+ int totpoint;
+ int totedge;
+ float (*deformedVerts)[3];
+ bool realloc_roots;
+
+ if (!psys->clmd) {
+ psys->clmd = (ClothModifierData*)modifier_new(eModifierType_Cloth);
+ psys->clmd->sim_parms->goalspring = 0.0f;
+ psys->clmd->sim_parms->vel_damping = 1.0f;
+ psys->clmd->sim_parms->flags |= CLOTH_SIMSETTINGS_FLAG_GOAL|CLOTH_SIMSETTINGS_FLAG_NO_SPRING_COMPRESS;
+ psys->clmd->coll_parms->flags &= ~CLOTH_COLLSETTINGS_FLAG_SELF;
+ }
+
+ /* count simulated points */
+ totpoint = 0;
+ totedge = 0;
+ LOOP_PARTICLES {
+ /* "out" dm contains all hairs */
+ totedge += pa->totkey;
+ totpoint += pa->totkey + 1; /* +1 for virtual root point */
+ }
+
+ realloc_roots = false; /* whether hair root info array has to be reallocated */
+ if (psys->hair_in_dm) {
+ DerivedMesh *dm = psys->hair_in_dm;
+ if (totpoint != dm->getNumVerts(dm) || totedge != dm->getNumEdges(dm)) {
+ dm->release(dm);
+ psys->hair_in_dm = NULL;
+ realloc_roots = true;
+ }
+ }
+
+ if (!psys->hair_in_dm || !psys->clmd->hairdata || realloc_roots) {
+ if (psys->clmd->hairdata) {
+ MEM_freeN(psys->clmd->hairdata);
+ psys->clmd->hairdata = NULL;
+ }
+ }
+
+ hair_create_input_dm(sim, totpoint, totedge, &psys->hair_in_dm, &psys->clmd->hairdata);
+
if (psys->hair_out_dm)
psys->hair_out_dm->release(psys->hair_out_dm);
-
+
psys->clmd->point_cache = psys->pointcache;
+ /* for hair sim we replace the internal cloth effector weights temporarily
+ * to use the particle settings
+ */
+ clmd_effweights = psys->clmd->sim_parms->effector_weights;
psys->clmd->sim_parms->effector_weights = psys->part->effector_weights;
-
- deformedVerts = MEM_mallocN(sizeof(*deformedVerts) * dm->getNumVerts(dm), "do_hair_dynamics vertexCos");
- psys->hair_out_dm = CDDM_copy(dm);
+
+ deformedVerts = MEM_mallocN(sizeof(*deformedVerts) * psys->hair_in_dm->getNumVerts(psys->hair_in_dm), "do_hair_dynamics vertexCos");
+ psys->hair_out_dm = CDDM_copy(psys->hair_in_dm);
psys->hair_out_dm->getVertCos(psys->hair_out_dm, deformedVerts);
-
- clothModifier_do(psys->clmd, sim->scene, sim->ob, dm, deformedVerts);
-
+
+ clothModifier_do(psys->clmd, sim->scene, sim->ob, psys->hair_in_dm, deformedVerts);
+
CDDM_apply_vert_coords(psys->hair_out_dm, deformedVerts);
-
+
MEM_freeN(deformedVerts);
-
- psys->clmd->sim_parms->effector_weights = NULL;
+
+ /* restore cloth effector weights */
+ psys->clmd->sim_parms->effector_weights = clmd_effweights;
}
static void hair_step(ParticleSimulationData *sim, float cfra)
{
@@ -4503,7 +3577,7 @@ static void update_children(ParticleSimulationData *sim)
/* don't generate children while growing hair - waste of time */
psys_free_children(sim->psys);
else if (sim->psys->part->childtype) {
- if (sim->psys->totchild != get_psys_tot_child(sim->scene, sim->psys))
+ if (sim->psys->totchild != psys_get_tot_child(sim->scene, sim->psys))
distribute_particles(sim, PART_FROM_CHILD);
else {
/* Children are up to date, nothing to do. */
@@ -4723,6 +3797,7 @@ static void system_step(ParticleSimulationData *sim, float cfra)
initialize_all_particles(sim);
/* reset only just created particles (on startframe all particles are recreated) */
reset_all_particles(sim, 0.0, cfra, oldtotpart);
+ free_unexisting_particles(sim);
if (psys->fluid_springs) {
MEM_freeN(psys->fluid_springs);
@@ -5069,6 +4144,7 @@ void particle_system_update(Scene *scene, Object *ob, ParticleSystem *psys)
{
PARTICLE_P;
float disp = psys_get_current_display_percentage(psys);
+ bool free_unexisting = false;
/* Particles without dynamics haven't been reset yet because they don't use pointcache */
if (psys->recalc & PSYS_RECALC_RESET)
@@ -5078,6 +4154,7 @@ void particle_system_update(Scene *scene, Object *ob, ParticleSystem *psys)
free_keyed_keys(psys);
distribute_particles(&sim, part->from);
initialize_all_particles(&sim);
+ free_unexisting = true;
/* flag for possible explode modifiers after this system */
sim.psmd->flag |= eParticleSystemFlag_Pars;
@@ -5096,6 +4173,10 @@ void particle_system_update(Scene *scene, Object *ob, ParticleSystem *psys)
pa->flag &= ~PARS_NO_DISP;
}
+ /* free unexisting after reseting particles */
+ if (free_unexisting)
+ free_unexisting_particles(&sim);
+
if (part->phystype == PART_PHYS_KEYED) {
psys_count_keyed_targets(&sim);
set_keyed_keys(&sim);
@@ -5128,3 +4209,15 @@ void particle_system_update(Scene *scene, Object *ob, ParticleSystem *psys)
invert_m4_m4(psys->imat, ob->obmat);
}
+/* **** Depsgraph evaluation **** */
+
+void BKE_particle_system_eval(EvaluationContext *UNUSED(eval_ctx),
+ Scene *scene,
+ Object *ob,
+ ParticleSystem *psys)
+{
+ if (G.debug & G_DEBUG_DEPSGRAPH) {
+ printf("%s on %s:%s\n", __func__, ob->id.name, psys->name);
+ }
+ BKE_ptcache_object_reset(scene, ob, PTCACHE_RESET_DEPSGRAPH);
+}
diff --git a/source/blender/blenkernel/intern/pbvh.c b/source/blender/blenkernel/intern/pbvh.c
index ccedb6f6b71..311e928c348 100644
--- a/source/blender/blenkernel/intern/pbvh.c
+++ b/source/blender/blenkernel/intern/pbvh.c
@@ -44,6 +44,8 @@
#include "pbvh_intern.h"
+#include <limits.h>
+
#define LEAF_LIMIT 10000
//#define PERFCNTRS
@@ -168,7 +170,7 @@ static void update_node_vb(PBVH *bvh, PBVHNode *node)
// BB_expand(&node->vb, co);
//}
-static int face_materials_match(const MFace *f1, const MFace *f2)
+static int face_materials_match(const MPoly *f1, const MPoly *f2)
{
return ((f1->flag & ME_SMOOTH) == (f2->flag & ME_SMOOTH) &&
(f1->mat_nr == f2->mat_nr));
@@ -201,21 +203,22 @@ static int partition_indices(int *prim_indices, int lo, int hi, int axis,
/* Returns the index of the first element on the right of the partition */
static int partition_indices_material(PBVH *bvh, int lo, int hi)
{
- const MFace *faces = bvh->faces;
+ const MPoly *mpoly = bvh->mpoly;
+ const MLoopTri *looptri = bvh->looptri;
const DMFlagMat *flagmats = bvh->grid_flag_mats;
const int *indices = bvh->prim_indices;
const void *first;
int i = lo, j = hi;
- if (bvh->faces)
- first = &faces[bvh->prim_indices[lo]];
+ if (bvh->looptri)
+ first = &mpoly[looptri[bvh->prim_indices[lo]].poly];
else
first = &flagmats[bvh->prim_indices[lo]];
for (;; ) {
- if (bvh->faces) {
- for (; face_materials_match(first, &faces[indices[i]]); i++) ;
- for (; !face_materials_match(first, &faces[indices[j]]); j--) ;
+ if (bvh->looptri) {
+ for (; face_materials_match(first, &mpoly[looptri[indices[i]].poly]); i++) ;
+ for (; !face_materials_match(first, &mpoly[looptri[indices[j]].poly]); j--) ;
}
else {
for (; grid_materials_match(first, &flagmats[indices[i]]); i++) ;
@@ -232,16 +235,11 @@ static int partition_indices_material(PBVH *bvh, int lo, int hi)
void pbvh_grow_nodes(PBVH *bvh, int totnode)
{
- if (totnode > bvh->node_mem_count) {
- PBVHNode *prev = bvh->nodes;
- bvh->node_mem_count *= 1.33;
+ if (UNLIKELY(totnode > bvh->node_mem_count)) {
+ bvh->node_mem_count = bvh->node_mem_count + (bvh->node_mem_count / 3);
if (bvh->node_mem_count < totnode)
bvh->node_mem_count = totnode;
- bvh->nodes = MEM_mallocN(sizeof(PBVHNode) * bvh->node_mem_count,
- "bvh nodes");
- memcpy(bvh->nodes, prev, bvh->totnode * sizeof(PBVHNode));
- memset(bvh->nodes + bvh->totnode, 0, (bvh->node_mem_count - bvh->totnode) * sizeof(PBVHNode));
- MEM_freeN(prev);
+ bvh->nodes = MEM_recallocN(bvh->nodes, sizeof(PBVHNode) * bvh->node_mem_count);
}
bvh->totnode = totnode;
@@ -281,10 +279,12 @@ static int map_insert_vert(PBVH *bvh, GHash *map,
/* Find vertices used by the faces in this node and update the draw buffers */
static void build_mesh_leaf_node(PBVH *bvh, PBVHNode *node)
{
- GHashIterator *iter;
+ GHashIterator gh_iter;
GHash *map;
int i, j, totface;
bool has_visible = false;
+ int (*face_vert_indices)[4];
+ int *vert_indices;
node->uniq_verts = node->face_verts = 0;
totface = node->totprim;
@@ -292,52 +292,50 @@ static void build_mesh_leaf_node(PBVH *bvh, PBVHNode *node)
/* reserve size is rough guess */
map = BLI_ghash_int_new_ex("build_mesh_leaf_node gh", 2 * totface);
- node->face_vert_indices = MEM_callocN(sizeof(int) * 4 * totface,
- "bvh node face vert indices");
+ face_vert_indices = MEM_callocN(sizeof(int[4]) * totface,
+ "bvh node face vert indices");
+
+ node->face_vert_indices = (const int (*)[4])face_vert_indices;
for (i = 0; i < totface; ++i) {
- MFace *f = bvh->faces + node->prim_indices[i];
- int sides = f->v4 ? 4 : 3;
+ const MLoopTri *lt = &bvh->looptri[node->prim_indices[i]];
+ const int sides = 3;
for (j = 0; j < sides; ++j) {
- node->face_vert_indices[i][j] =
+ face_vert_indices[i][j] =
map_insert_vert(bvh, map, &node->face_verts,
- &node->uniq_verts, (&f->v1)[j]);
+ &node->uniq_verts, bvh->mloop[lt->tri[j]].v);
}
- if (!paint_is_face_hidden(f, bvh->verts))
+ if (!paint_is_face_hidden(lt, bvh->verts, bvh->mloop)) {
has_visible = true;
+ }
}
- node->vert_indices = MEM_callocN(sizeof(int) *
- (node->uniq_verts + node->face_verts),
- "bvh node vert indices");
+ vert_indices = MEM_callocN(sizeof(int) *
+ (node->uniq_verts + node->face_verts),
+ "bvh node vert indices");
+ node->vert_indices = vert_indices;
/* Build the vertex list, unique verts first */
- for (iter = BLI_ghashIterator_new(map), i = 0;
- BLI_ghashIterator_done(iter) == false;
- BLI_ghashIterator_step(iter), ++i)
- {
- void *value = BLI_ghashIterator_getValue(iter);
+ GHASH_ITER (gh_iter, map) {
+ void *value = BLI_ghashIterator_getValue(&gh_iter);
int ndx = GET_INT_FROM_POINTER(value);
if (ndx < 0)
ndx = -ndx + node->uniq_verts - 1;
- node->vert_indices[ndx] =
- GET_INT_FROM_POINTER(BLI_ghashIterator_getKey(iter));
+ vert_indices[ndx] =
+ GET_INT_FROM_POINTER(BLI_ghashIterator_getKey(&gh_iter));
}
- BLI_ghashIterator_free(iter);
-
for (i = 0; i < totface; ++i) {
- MFace *f = bvh->faces + node->prim_indices[i];
- int sides = f->v4 ? 4 : 3;
-
+ const int sides = 3;
+
for (j = 0; j < sides; ++j) {
- if (node->face_vert_indices[i][j] < 0)
- node->face_vert_indices[i][j] =
- -node->face_vert_indices[i][j] +
+ if (face_vert_indices[i][j] < 0)
+ face_vert_indices[i][j] =
+ -face_vert_indices[i][j] +
node->uniq_verts - 1;
}
}
@@ -411,7 +409,7 @@ static void build_leaf(PBVH *bvh, int node_index, BBC *prim_bbc,
/* Still need vb for searches */
update_vb(bvh, &bvh->nodes[node_index], prim_bbc, offset, count);
- if (bvh->faces)
+ if (bvh->looptri)
build_mesh_leaf_node(bvh, bvh->nodes + node_index);
else {
build_grid_leaf_node(bvh, bvh->nodes + node_index);
@@ -422,25 +420,28 @@ static void build_leaf(PBVH *bvh, int node_index, BBC *prim_bbc,
* same material (including flat/smooth shading), non-zero otherwise */
static int leaf_needs_material_split(PBVH *bvh, int offset, int count)
{
- int i, prim;
+ int i;
if (count <= 1)
return 0;
- if (bvh->faces) {
- const MFace *first = &bvh->faces[bvh->prim_indices[offset]];
+ if (bvh->looptri) {
+ const MLoopTri *first = &bvh->looptri[bvh->prim_indices[offset]];
+ const MPoly *mp = &bvh->mpoly[first->poly];
for (i = offset + count - 1; i > offset; --i) {
- prim = bvh->prim_indices[i];
- if (!face_materials_match(first, &bvh->faces[prim]))
+ int prim = bvh->prim_indices[i];
+ const MPoly *mp_other = &bvh->mpoly[bvh->looptri[prim].poly];
+ if (!face_materials_match(mp, mp_other)) {
return 1;
+ }
}
}
else {
const DMFlagMat *first = &bvh->grid_flag_mats[bvh->prim_indices[offset]];
for (i = offset + count - 1; i > offset; --i) {
- prim = bvh->prim_indices[i];
+ int prim = bvh->prim_indices[i];
if (!grid_materials_match(first, &bvh->grid_flag_mats[prim]))
return 1;
}
@@ -538,14 +539,19 @@ static void pbvh_build(PBVH *bvh, BB *cb, BBC *prim_bbc, int totprim)
}
/* Do a full rebuild with on Mesh data structure */
-void BKE_pbvh_build_mesh(PBVH *bvh, MFace *faces, MVert *verts, int totface, int totvert, struct CustomData *vdata)
+void BKE_pbvh_build_mesh(
+ PBVH *bvh, const MPoly *mpoly, const MLoop *mloop, MVert *verts,
+ int totvert, struct CustomData *vdata,
+ const MLoopTri *looptri, int looptri_num)
{
BBC *prim_bbc = NULL;
BB cb;
int i, j;
bvh->type = PBVH_FACES;
- bvh->faces = faces;
+ bvh->mpoly = mpoly;
+ bvh->mloop = mloop;
+ bvh->looptri = looptri;
bvh->verts = verts;
bvh->vert_bitmap = BLI_BITMAP_NEW(totvert, "bvh->vert_bitmap");
bvh->totvert = totvert;
@@ -555,32 +561,32 @@ void BKE_pbvh_build_mesh(PBVH *bvh, MFace *faces, MVert *verts, int totface, int
BB_reset(&cb);
/* For each face, store the AABB and the AABB centroid */
- prim_bbc = MEM_mallocN(sizeof(BBC) * totface, "prim_bbc");
+ prim_bbc = MEM_mallocN(sizeof(BBC) * looptri_num, "prim_bbc");
- for (i = 0; i < totface; ++i) {
- MFace *f = faces + i;
- const int sides = f->v4 ? 4 : 3;
+ for (i = 0; i < looptri_num; ++i) {
+ const MLoopTri *lt = &looptri[i];
+ const int sides = 3;
BBC *bbc = prim_bbc + i;
BB_reset((BB *)bbc);
for (j = 0; j < sides; ++j)
- BB_expand((BB *)bbc, verts[(&f->v1)[j]].co);
+ BB_expand((BB *)bbc, verts[bvh->mloop[lt->tri[j]].v].co);
BBC_update_centroid(bbc);
BB_expand(&cb, bbc->bcentroid);
}
- if (totface)
- pbvh_build(bvh, &cb, prim_bbc, totface);
+ if (looptri_num)
+ pbvh_build(bvh, &cb, prim_bbc, looptri_num);
MEM_freeN(prim_bbc);
MEM_freeN(bvh->vert_bitmap);
}
/* Do a full rebuild with on Grids data structure */
-void BKE_pbvh_build_grids(PBVH *bvh, CCGElem **grids, DMGridAdjacency *gridadj,
+void BKE_pbvh_build_grids(PBVH *bvh, CCGElem **grids,
int totgrid, CCGKey *key, void **gridfaces, DMFlagMat *flagmats, BLI_bitmap **grid_hidden)
{
BBC *prim_bbc = NULL;
@@ -590,7 +596,6 @@ void BKE_pbvh_build_grids(PBVH *bvh, CCGElem **grids, DMGridAdjacency *gridadj,
bvh->type = PBVH_GRIDS;
bvh->grids = grids;
- bvh->gridadj = gridadj;
bvh->gridfaces = gridfaces;
bvh->grid_flag_mats = flagmats;
bvh->totgrid = totgrid;
@@ -642,9 +647,9 @@ void BKE_pbvh_free(PBVH *bvh)
if (node->draw_buffers)
GPU_free_pbvh_buffers(node->draw_buffers);
if (node->vert_indices)
- MEM_freeN(node->vert_indices);
+ MEM_freeN((void *)node->vert_indices);
if (node->face_vert_indices)
- MEM_freeN(node->face_vert_indices);
+ MEM_freeN((void *)node->face_vert_indices);
BKE_pbvh_node_layer_disp_free(node);
if (node->bm_faces)
@@ -660,12 +665,14 @@ void BKE_pbvh_free(PBVH *bvh)
if (bvh->verts) {
/* if pbvh was deformed, new memory was allocated for verts/faces -- free it */
- MEM_freeN(bvh->verts);
- if (bvh->faces)
- MEM_freeN(bvh->faces);
+ MEM_freeN((void *)bvh->verts);
}
}
+ if (bvh->looptri) {
+ MEM_freeN((void *)bvh->looptri);
+ }
+
if (bvh->nodes)
MEM_freeN(bvh->nodes);
@@ -704,16 +711,16 @@ static void pbvh_iter_end(PBVHIter *iter)
static void pbvh_stack_push(PBVHIter *iter, PBVHNode *node, int revisiting)
{
- if (iter->stacksize == iter->stackspace) {
- PBVHStack *newstack;
-
+ if (UNLIKELY(iter->stacksize == iter->stackspace)) {
iter->stackspace *= 2;
- newstack = MEM_callocN(sizeof(PBVHStack) * iter->stackspace, "PBVHStack");
- memcpy(newstack, iter->stack, sizeof(PBVHStack) * iter->stacksize);
- if (iter->stackspace > STACK_FIXED_DEPTH)
- MEM_freeN(iter->stack);
- iter->stack = newstack;
+ if (iter->stackspace != STACK_FIXED_DEPTH) {
+ iter->stack = MEM_reallocN(iter->stack, sizeof(PBVHStack) * iter->stackspace);
+ }
+ else {
+ iter->stack = MEM_mallocN(sizeof(PBVHStack) * iter->stackspace, "PBVHStack");
+ memcpy(iter->stack, iter->stackfixed, sizeof(PBVHStack) * iter->stacksize);
+ }
}
iter->stack[iter->stacksize].node = node;
@@ -805,7 +812,7 @@ void BKE_pbvh_search_gather(PBVH *bvh,
while ((node = pbvh_iter_next(&iter))) {
if (node->flag & PBVH_Leaf) {
- if (tot == space) {
+ if (UNLIKELY(tot == space)) {
/* resize array if needed */
space = (tot == 0) ? 32 : space * 2;
array = MEM_recallocN_id(array, sizeof(PBVHNode *) * space, __func__);
@@ -943,7 +950,7 @@ static bool update_search_cb(PBVHNode *node, void *data_v)
if (node->flag & PBVH_Leaf)
return (node->flag & flag) != 0;
- return 1;
+ return true;
}
static void pbvh_update_normals(PBVH *bvh, PBVHNode **nodes,
@@ -953,6 +960,7 @@ static void pbvh_update_normals(PBVH *bvh, PBVHNode **nodes,
int n;
if (bvh->type == PBVH_BMESH) {
+ BLI_assert(face_nors == NULL);
pbvh_bmesh_normals_update(nodes, totnode);
return;
}
@@ -980,25 +988,34 @@ static void pbvh_update_normals(PBVH *bvh, PBVHNode **nodes,
if ((node->flag & PBVH_UpdateNormals)) {
int i, j, totface, *faces;
+ unsigned int mpoly_prev = UINT_MAX;
+ float fn[3];
faces = node->prim_indices;
totface = node->totprim;
for (i = 0; i < totface; ++i) {
- MFace *f = bvh->faces + faces[i];
- float fn[3];
- unsigned int *fv = &f->v1;
- int sides = (f->v4) ? 4 : 3;
-
- if (f->v4)
- normal_quad_v3(fn, bvh->verts[f->v1].co, bvh->verts[f->v2].co,
- bvh->verts[f->v3].co, bvh->verts[f->v4].co);
- else
- normal_tri_v3(fn, bvh->verts[f->v1].co, bvh->verts[f->v2].co,
- bvh->verts[f->v3].co);
+ const MLoopTri *lt = &bvh->looptri[faces[i]];
+ const unsigned int vtri[3] = {
+ bvh->mloop[lt->tri[0]].v,
+ bvh->mloop[lt->tri[1]].v,
+ bvh->mloop[lt->tri[2]].v,
+ };
+ const int sides = 3;
+
+ /* Face normal and mask */
+ if (lt->poly != mpoly_prev) {
+ const MPoly *mp = &bvh->mpoly[lt->poly];
+ BKE_mesh_calc_poly_normal(mp, &bvh->mloop[mp->loopstart], bvh->verts, fn);
+ mpoly_prev = lt->poly;
+
+ if (face_nors) {
+ copy_v3_v3(face_nors[lt->poly], fn);
+ }
+ }
for (j = 0; j < sides; ++j) {
- int v = fv[j];
+ int v = vtri[j];
if (bvh->verts[v].flag & ME_VERT_PBVH_UPDATE) {
/* this seems like it could be very slow but profile
@@ -1011,9 +1028,6 @@ static void pbvh_update_normals(PBVH *bvh, PBVHNode **nodes,
vnor[v][2] += fn[2];
}
}
-
- if (face_nors)
- copy_v3_v3(face_nors[faces[i]], fn);
}
}
}
@@ -1023,7 +1037,8 @@ static void pbvh_update_normals(PBVH *bvh, PBVHNode **nodes,
PBVHNode *node = nodes[n];
if (node->flag & PBVH_UpdateNormals) {
- int i, *verts, totvert;
+ const int *verts;
+ int i, totvert;
verts = node->vert_indices;
totvert = node->uniq_verts;
@@ -1088,12 +1103,14 @@ static void pbvh_update_draw_buffers(PBVH *bvh, PBVHNode **nodes, int totnode)
GPU_build_grid_pbvh_buffers(node->prim_indices,
node->totprim,
bvh->grid_hidden,
- bvh->gridkey.grid_size);
+ bvh->gridkey.grid_size,
+ &bvh->gridkey);
break;
case PBVH_FACES:
node->draw_buffers =
GPU_build_mesh_pbvh_buffers(node->face_vert_indices,
- bvh->faces, bvh->verts,
+ bvh->mpoly, bvh->mloop, bvh->looptri,
+ bvh->verts,
node->prim_indices,
node->totprim);
break;
@@ -1290,6 +1307,16 @@ PBVHType BKE_pbvh_type(const PBVH *bvh)
return bvh->type;
}
+bool BKE_pbvh_has_faces(const PBVH *bvh)
+{
+ if (bvh->type == PBVH_BMESH) {
+ return (bvh->bm->totface != 0);
+ }
+ else {
+ return (bvh->totprim != 0);
+ }
+}
+
void BKE_pbvh_bounding_box(const PBVH *bvh, float min[3], float max[3])
{
if (bvh->totnode) {
@@ -1354,53 +1381,62 @@ void BKE_pbvh_node_fully_hidden_set(PBVHNode *node, int fully_hidden)
node->flag &= ~PBVH_FullyHidden;
}
-void BKE_pbvh_node_get_verts(PBVH *bvh, PBVHNode *node, int **vert_indices, MVert **verts)
+void BKE_pbvh_node_get_verts(
+ PBVH *bvh, PBVHNode *node,
+ const int **r_vert_indices, MVert **r_verts)
{
- if (vert_indices) *vert_indices = node->vert_indices;
- if (verts) *verts = bvh->verts;
+ if (r_vert_indices) {
+ *r_vert_indices = node->vert_indices;
+ }
+
+ if (r_verts) {
+ *r_verts = bvh->verts;
+ }
}
-void BKE_pbvh_node_num_verts(PBVH *bvh, PBVHNode *node, int *uniquevert, int *totvert)
+void BKE_pbvh_node_num_verts(
+ PBVH *bvh, PBVHNode *node,
+ int *r_uniquevert, int *r_totvert)
{
int tot;
switch (bvh->type) {
case PBVH_GRIDS:
tot = node->totprim * bvh->gridkey.grid_area;
- if (totvert) *totvert = tot;
- if (uniquevert) *uniquevert = tot;
+ if (r_totvert) *r_totvert = tot;
+ if (r_uniquevert) *r_uniquevert = tot;
break;
case PBVH_FACES:
- if (totvert) *totvert = node->uniq_verts + node->face_verts;
- if (uniquevert) *uniquevert = node->uniq_verts;
+ if (r_totvert) *r_totvert = node->uniq_verts + node->face_verts;
+ if (r_uniquevert) *r_uniquevert = node->uniq_verts;
break;
case PBVH_BMESH:
tot = BLI_gset_size(node->bm_unique_verts);
- if (totvert) *totvert = tot + BLI_gset_size(node->bm_other_verts);
- if (uniquevert) *uniquevert = tot;
+ if (r_totvert) *r_totvert = tot + BLI_gset_size(node->bm_other_verts);
+ if (r_uniquevert) *r_uniquevert = tot;
break;
}
}
-void BKE_pbvh_node_get_grids(PBVH *bvh, PBVHNode *node, int **grid_indices, int *totgrid, int *maxgrid, int *gridsize, CCGElem ***griddata, DMGridAdjacency **gridadj)
+void BKE_pbvh_node_get_grids(
+ PBVH *bvh, PBVHNode *node,
+ int **r_grid_indices, int *r_totgrid, int *r_maxgrid, int *r_gridsize, CCGElem ***r_griddata)
{
switch (bvh->type) {
case PBVH_GRIDS:
- if (grid_indices) *grid_indices = node->prim_indices;
- if (totgrid) *totgrid = node->totprim;
- if (maxgrid) *maxgrid = bvh->totgrid;
- if (gridsize) *gridsize = bvh->gridkey.grid_size;
- if (griddata) *griddata = bvh->grids;
- if (gridadj) *gridadj = bvh->gridadj;
+ if (r_grid_indices) *r_grid_indices = node->prim_indices;
+ if (r_totgrid) *r_totgrid = node->totprim;
+ if (r_maxgrid) *r_maxgrid = bvh->totgrid;
+ if (r_gridsize) *r_gridsize = bvh->gridkey.grid_size;
+ if (r_griddata) *r_griddata = bvh->grids;
break;
case PBVH_FACES:
case PBVH_BMESH:
- if (grid_indices) *grid_indices = NULL;
- if (totgrid) *totgrid = 0;
- if (maxgrid) *maxgrid = 0;
- if (gridsize) *gridsize = 0;
- if (griddata) *griddata = NULL;
- if (gridadj) *gridadj = NULL;
+ if (r_grid_indices) *r_grid_indices = NULL;
+ if (r_totgrid) *r_totgrid = 0;
+ if (r_maxgrid) *r_maxgrid = 0;
+ if (r_gridsize) *r_gridsize = 0;
+ if (r_griddata) *r_griddata = NULL;
break;
}
}
@@ -1429,11 +1465,20 @@ void BKE_pbvh_node_get_proxies(PBVHNode *node, PBVHProxyNode **proxies, int *pro
}
}
+void BKE_pbvh_node_get_bm_orco_data(
+ PBVHNode *node,
+ int (**r_orco_tris)[3], int *r_orco_tris_num, float (**r_orco_coords)[3])
+{
+ *r_orco_tris = node->bm_ortri;
+ *r_orco_tris_num = node->bm_tot_ortri;
+ *r_orco_coords = node->bm_orco;
+}
+
/********************************* Raycast ***********************************/
typedef struct {
IsectRayAABBData ray;
- int original;
+ bool original;
} RaycastData;
static bool ray_aabb_intersect(PBVHNode *node, void *data_v)
@@ -1449,9 +1494,10 @@ static bool ray_aabb_intersect(PBVHNode *node, void *data_v)
return isect_ray_aabb(&rcd->ray, bb_min, bb_max, &node->tmin);
}
-void BKE_pbvh_raycast(PBVH *bvh, BKE_pbvh_HitOccludedCallback cb, void *data,
- const float ray_start[3], const float ray_normal[3],
- int original)
+void BKE_pbvh_raycast(
+ PBVH *bvh, BKE_pbvh_HitOccludedCallback cb, void *data,
+ const float ray_start[3], const float ray_normal[3],
+ bool original)
{
RaycastData rcd;
@@ -1461,59 +1507,76 @@ void BKE_pbvh_raycast(PBVH *bvh, BKE_pbvh_HitOccludedCallback cb, void *data,
BKE_pbvh_search_callback_occluded(bvh, ray_aabb_intersect, &rcd, cb, data);
}
-bool ray_face_intersection(const float ray_start[3],
- const float ray_normal[3],
- const float t0[3], const float t1[3],
- const float t2[3], const float t3[3],
- float *fdist)
+bool ray_face_intersection_quad(
+ const float ray_start[3], const float ray_normal[3],
+ const float t0[3], const float t1[3], const float t2[3], const float t3[3],
+ float *dist)
{
- float dist;
+ float dist_test;
- if ((isect_ray_tri_epsilon_v3(ray_start, ray_normal, t0, t1, t2, &dist, NULL, 0.1f) && dist < *fdist) ||
- (t3 && isect_ray_tri_epsilon_v3(ray_start, ray_normal, t0, t2, t3, &dist, NULL, 0.1f) && dist < *fdist))
+ if ((isect_ray_tri_epsilon_v3(ray_start, ray_normal, t0, t1, t2, &dist_test, NULL, 0.1f) && (dist_test < *dist)) ||
+ (isect_ray_tri_epsilon_v3(ray_start, ray_normal, t0, t2, t3, &dist_test, NULL, 0.1f) && (dist_test < *dist)))
{
- *fdist = dist;
- return 1;
+ *dist = dist_test;
+ return true;
}
else {
- return 0;
+ return false;
}
}
-static bool pbvh_faces_node_raycast(PBVH *bvh, const PBVHNode *node,
- float (*origco)[3],
- const float ray_start[3],
- const float ray_normal[3], float *dist)
+bool ray_face_intersection_tri(
+ const float ray_start[3], const float ray_normal[3],
+ const float t0[3], const float t1[3], const float t2[3],
+ float *dist)
+{
+ float dist_test;
+
+ if ((isect_ray_tri_epsilon_v3(ray_start, ray_normal, t0, t1, t2, &dist_test, NULL, 0.1f) && (dist_test < *dist))) {
+ *dist = dist_test;
+ return true;
+ }
+ else {
+ return false;
+ }
+}
+
+static bool pbvh_faces_node_raycast(
+ PBVH *bvh, const PBVHNode *node,
+ float (*origco)[3],
+ const float ray_start[3], const float ray_normal[3],
+ float *dist)
{
const MVert *vert = bvh->verts;
+ const MLoop *mloop = bvh->mloop;
const int *faces = node->prim_indices;
int i, totface = node->totprim;
bool hit = false;
for (i = 0; i < totface; ++i) {
- const MFace *f = bvh->faces + faces[i];
+ const MLoopTri *lt = &bvh->looptri[faces[i]];
const int *face_verts = node->face_vert_indices[i];
- if (paint_is_face_hidden(f, vert))
+ if (paint_is_face_hidden(lt, vert, mloop))
continue;
if (origco) {
/* intersect with backuped original coordinates */
- hit |= ray_face_intersection(ray_start, ray_normal,
- origco[face_verts[0]],
- origco[face_verts[1]],
- origco[face_verts[2]],
- f->v4 ? origco[face_verts[3]] : NULL,
- dist);
+ hit |= ray_face_intersection_tri(
+ ray_start, ray_normal,
+ origco[face_verts[0]],
+ origco[face_verts[1]],
+ origco[face_verts[2]],
+ dist);
}
else {
/* intersect with current coordinates */
- hit |= ray_face_intersection(ray_start, ray_normal,
- vert[f->v1].co,
- vert[f->v2].co,
- vert[f->v3].co,
- f->v4 ? vert[f->v4].co : NULL,
- dist);
+ hit |= ray_face_intersection_tri(
+ ray_start, ray_normal,
+ vert[mloop[lt->tri[0]].v].co,
+ vert[mloop[lt->tri[1]].v].co,
+ vert[mloop[lt->tri[2]].v].co,
+ dist);
}
}
@@ -1549,20 +1612,22 @@ static bool pbvh_grids_node_raycast(
}
if (origco) {
- hit |= ray_face_intersection(ray_start, ray_normal,
- origco[y * gridsize + x],
- origco[y * gridsize + x + 1],
- origco[(y + 1) * gridsize + x + 1],
- origco[(y + 1) * gridsize + x],
- dist);
+ hit |= ray_face_intersection_quad(
+ ray_start, ray_normal,
+ origco[y * gridsize + x],
+ origco[y * gridsize + x + 1],
+ origco[(y + 1) * gridsize + x + 1],
+ origco[(y + 1) * gridsize + x],
+ dist);
}
else {
- hit |= ray_face_intersection(ray_start, ray_normal,
- CCG_grid_elem_co(&bvh->gridkey, grid, x, y),
- CCG_grid_elem_co(&bvh->gridkey, grid, x + 1, y),
- CCG_grid_elem_co(&bvh->gridkey, grid, x + 1, y + 1),
- CCG_grid_elem_co(&bvh->gridkey, grid, x, y + 1),
- dist);
+ hit |= ray_face_intersection_quad(
+ ray_start, ray_normal,
+ CCG_grid_elem_co(&bvh->gridkey, grid, x, y),
+ CCG_grid_elem_co(&bvh->gridkey, grid, x + 1, y),
+ CCG_grid_elem_co(&bvh->gridkey, grid, x + 1, y + 1),
+ CCG_grid_elem_co(&bvh->gridkey, grid, x, y + 1),
+ dist);
}
}
}
@@ -1586,22 +1651,27 @@ bool BKE_pbvh_node_raycast(
switch (bvh->type) {
case PBVH_FACES:
- hit |= pbvh_faces_node_raycast(bvh, node, origco,
- ray_start, ray_normal, dist);
+ hit |= pbvh_faces_node_raycast(
+ bvh, node, origco,
+ ray_start, ray_normal, dist);
break;
case PBVH_GRIDS:
- hit |= pbvh_grids_node_raycast(bvh, node, origco,
- ray_start, ray_normal, dist);
+ hit |= pbvh_grids_node_raycast(
+ bvh, node, origco,
+ ray_start, ray_normal, dist);
break;
case PBVH_BMESH:
- hit = pbvh_bmesh_node_raycast(node, ray_start, ray_normal, dist, use_origco);
+ hit = pbvh_bmesh_node_raycast(
+ node, ray_start, ray_normal, dist, use_origco);
break;
}
return hit;
}
-void BKE_pbvh_raycast_project_ray_root (PBVH *bvh, bool original, float ray_start[3], float ray_end[3], float ray_normal[3])
+void BKE_pbvh_raycast_project_ray_root(
+ PBVH *bvh, bool original,
+ float ray_start[3], float ray_end[3], float ray_normal[3])
{
if (bvh->nodes) {
float rootmin_start, rootmin_end;
@@ -1644,11 +1714,12 @@ void BKE_pbvh_raycast_project_ray_root (PBVH *bvh, bool original, float ray_star
}
-//#include <GL/glew.h>
+//#include "GPU_glew.h"
typedef struct {
DMSetMaterial setMaterial;
bool wireframe;
+ bool fast;
} PBVHNodeDrawData;
void BKE_pbvh_node_draw(PBVHNode *node, void *data_v)
@@ -1675,7 +1746,8 @@ void BKE_pbvh_node_draw(PBVHNode *node, void *data_v)
if (!(node->flag & PBVH_FullyHidden)) {
GPU_draw_pbvh_buffers(node->draw_buffers,
data->setMaterial,
- data->wireframe);
+ data->wireframe,
+ data->fast);
}
}
@@ -1745,9 +1817,9 @@ static void pbvh_node_check_diffuse_changed(PBVH *bvh, PBVHNode *node)
}
void BKE_pbvh_draw(PBVH *bvh, float (*planes)[4], float (*face_nors)[3],
- DMSetMaterial setMaterial, bool wireframe)
+ DMSetMaterial setMaterial, bool wireframe, bool fast)
{
- PBVHNodeDrawData draw_data = {setMaterial, wireframe};
+ PBVHNodeDrawData draw_data = {setMaterial, wireframe, fast};
PBVHNode **nodes;
int a, totnode;
@@ -1774,13 +1846,12 @@ void BKE_pbvh_draw(PBVH *bvh, float (*planes)[4], float (*face_nors)[3],
pbvh_draw_BB(bvh);
}
-void BKE_pbvh_grids_update(PBVH *bvh, CCGElem **grids, DMGridAdjacency *gridadj, void **gridfaces,
+void BKE_pbvh_grids_update(PBVH *bvh, CCGElem **grids, void **gridfaces,
DMFlagMat *flagmats, BLI_bitmap **grid_hidden)
{
int a;
bvh->grids = grids;
- bvh->gridadj = gridadj;
bvh->gridfaces = gridfaces;
if (flagmats != bvh->grid_flag_mats || bvh->grid_hidden != grid_hidden) {
@@ -1842,8 +1913,8 @@ void BKE_pbvh_apply_vertCos(PBVH *pbvh, float (*vertCos)[3])
/* original data and applying new coords to this arrays would lead to */
/* unneeded deformation -- duplicate verts/faces to avoid this */
- pbvh->verts = MEM_dupallocN(pbvh->verts);
- pbvh->faces = MEM_dupallocN(pbvh->faces);
+ pbvh->verts = MEM_dupallocN(pbvh->verts);
+ pbvh->looptri = MEM_dupallocN(pbvh->looptri);
pbvh->deformed = 1;
}
@@ -1858,7 +1929,11 @@ void BKE_pbvh_apply_vertCos(PBVH *pbvh, float (*vertCos)[3])
}
/* coordinates are new -- normals should also be updated */
- BKE_mesh_calc_normals_tessface(pbvh->verts, pbvh->totvert, pbvh->faces, pbvh->totprim, NULL);
+ BKE_mesh_calc_normals_looptri(
+ pbvh->verts, pbvh->totvert,
+ pbvh->mloop,
+ pbvh->looptri, pbvh->totprim,
+ NULL);
for (a = 0; a < pbvh->totnode; ++a)
BKE_pbvh_node_mark_update(&pbvh->nodes[a]);
@@ -1951,7 +2026,8 @@ void pbvh_vertex_iter_init(PBVH *bvh, PBVHNode *node,
{
struct CCGElem **grids;
struct MVert *verts;
- int *grid_indices, *vert_indices;
+ const int *vert_indices;
+ int *grid_indices;
int totgrid, gridsize, uniq_verts, totvert;
vi->grid = NULL;
@@ -1959,7 +2035,7 @@ void pbvh_vertex_iter_init(PBVH *bvh, PBVHNode *node,
vi->fno = NULL;
vi->mvert = NULL;
- BKE_pbvh_node_get_grids(bvh, node, &grid_indices, &totgrid, NULL, &gridsize, &grids, NULL);
+ BKE_pbvh_node_get_grids(bvh, node, &grid_indices, &totgrid, NULL, &gridsize, &grids);
BKE_pbvh_node_num_verts(bvh, node, &uniq_verts, &totvert);
BKE_pbvh_node_get_verts(bvh, node, &vert_indices, &verts);
vi->key = &bvh->gridkey;
diff --git a/source/blender/blenkernel/intern/pbvh_bmesh.c b/source/blender/blenkernel/intern/pbvh_bmesh.c
index 55653f41e75..3e236079a66 100644
--- a/source/blender/blenkernel/intern/pbvh_bmesh.c
+++ b/source/blender/blenkernel/intern/pbvh_bmesh.c
@@ -29,6 +29,7 @@
#include "BLI_ghash.h"
#include "BLI_heap.h"
#include "BLI_math.h"
+#include "BLI_memarena.h"
#include "BKE_ccg.h"
#include "BKE_DerivedMesh.h"
@@ -41,6 +42,34 @@
#include <assert.h>
+/* Avoid skinny faces */
+#define USE_EDGEQUEUE_EVEN_SUBDIV
+#ifdef USE_EDGEQUEUE_EVEN_SUBDIV
+# include "BKE_global.h"
+#endif
+
+/* Support for only operating on front-faces */
+#define USE_EDGEQUEUE_FRONTFACE
+
+/* don't add edges into the queue multiple times */
+#define USE_EDGEQUEUE_TAG
+/**
+ * Ensure we don't have dirty tags for the edge queue, and that they are left cleared.
+ * (slow, even for debug mode, so leave disabled for now).
+ */
+#if defined(USE_EDGEQUEUE_TAG) && 0
+# if !defined(NDEBUG)
+# define USE_EDGEQUEUE_TAG_VERIFY
+# endif
+#endif
+
+// #define USE_VERIFY
+
+#ifdef USE_VERIFY
+static void pbvh_bmesh_verify(PBVH *bvh);
+#endif
+
+
/****************************** Building ******************************/
/* Update node data after splitting */
@@ -100,7 +129,7 @@ static void pbvh_bmesh_node_finalize(PBVH *bvh, int node_index, const int cd_ver
}
/* Recursively split the node if it exceeds the leaf_limit */
-static void pbvh_bmesh_node_split(PBVH *bvh, GHash *prim_bbc, int node_index)
+static void pbvh_bmesh_node_split(PBVH *bvh, const BBC *bbc_array, int node_index)
{
GSet *empty, *other;
GSetIterator gs_iter;
@@ -122,7 +151,7 @@ static void pbvh_bmesh_node_split(PBVH *bvh, GHash *prim_bbc, int node_index)
BB_reset(&cb);
GSET_ITER (gs_iter, n->bm_faces) {
const BMFace *f = BLI_gsetIterator_getKey(&gs_iter);
- const BBC *bbc = BLI_ghash_lookup(prim_bbc, f);
+ const BBC *bbc = &bbc_array[BM_elem_index_get(f)];
BB_expand(&cb, bbc->bcentroid);
}
@@ -150,7 +179,7 @@ static void pbvh_bmesh_node_split(PBVH *bvh, GHash *prim_bbc, int node_index)
/* Partition the parent node's faces between the two children */
GSET_ITER (gs_iter, n->bm_faces) {
BMFace *f = BLI_gsetIterator_getKey(&gs_iter);
- const BBC *bbc = BLI_ghash_lookup(prim_bbc, f);
+ const BBC *bbc = &bbc_array[BM_elem_index_get(f)];
if (bbc->bcentroid[axis] < mid)
BLI_gset_insert(c1->bm_faces, f);
@@ -214,8 +243,8 @@ static void pbvh_bmesh_node_split(PBVH *bvh, GHash *prim_bbc, int node_index)
/* Recurse */
c1 = c2 = NULL;
- pbvh_bmesh_node_split(bvh, prim_bbc, children);
- pbvh_bmesh_node_split(bvh, prim_bbc, children + 1);
+ pbvh_bmesh_node_split(bvh, bbc_array, children);
+ pbvh_bmesh_node_split(bvh, bbc_array, children + 1);
/* Array maybe reallocated, update current node pointer */
n = &bvh->nodes[node_index];
@@ -230,7 +259,6 @@ static void pbvh_bmesh_node_split(PBVH *bvh, GHash *prim_bbc, int node_index)
/* Recursively split the node if it exceeds the leaf_limit */
static bool pbvh_bmesh_node_limit_ensure(PBVH *bvh, int node_index)
{
- GHash *prim_bbc;
GSet *bm_faces;
int bm_faces_size;
GSetIterator gs_iter;
@@ -245,8 +273,7 @@ static bool pbvh_bmesh_node_limit_ensure(PBVH *bvh, int node_index)
}
/* For each BMFace, store the AABB and AABB centroid */
- prim_bbc = BLI_ghash_ptr_new_ex("prim_bbc", bm_faces_size);
- bbc_array = MEM_callocN(sizeof(BBC) * bm_faces_size, "BBC");
+ bbc_array = MEM_mallocN(sizeof(BBC) * bm_faces_size, "BBC");
GSET_ITER_INDEX (gs_iter, bm_faces, i) {
BMFace *f = BLI_gsetIterator_getKey(&gs_iter);
@@ -261,12 +288,14 @@ static bool pbvh_bmesh_node_limit_ensure(PBVH *bvh, int node_index)
} while ((l_iter = l_iter->next) != l_first);
BBC_update_centroid(bbc);
- BLI_ghash_insert(prim_bbc, f, bbc);
+ /* so we can do direct lookups on 'bbc_array' */
+ BM_elem_index_set(f, i); /* set_dirty! */
}
+ /* likely this is already dirty */
+ bvh->bm->elem_index_dirty |= BM_FACE;
- pbvh_bmesh_node_split(bvh, prim_bbc, node_index);
+ pbvh_bmesh_node_split(bvh, bbc_array, node_index);
- BLI_ghash_free(prim_bbc, NULL, NULL);
MEM_freeN(bbc_array);
return true;
@@ -274,30 +303,63 @@ static bool pbvh_bmesh_node_limit_ensure(PBVH *bvh, int node_index)
/**********************************************************************/
-static PBVHNode *pbvh_bmesh_node_lookup(PBVH *bvh, void *key, const int cd_node_offset)
+static int pbvh_bmesh_node_offset_from_elem(PBVH *bvh, BMElem *ele)
{
- int node_index = BM_ELEM_CD_GET_INT((BMElem *)key, cd_node_offset);
+ switch (ele->head.htype) {
+ case BM_VERT:
+ return bvh->cd_vert_node_offset;
+ default:
+ BLI_assert(ele->head.htype == BM_FACE);
+ return bvh->cd_face_node_offset;
+ }
- BLI_assert(node_index != DYNTOPO_NODE_NONE);
+}
+
+static int pbvh_bmesh_node_lookup_index(PBVH *bvh, void *key)
+{
+ const int cd_node_offset = pbvh_bmesh_node_offset_from_elem(bvh, key);
+ const int node_index = BM_ELEM_CD_GET_INT((BMElem *)key, cd_node_offset);
+ BLI_assert(node_index != DYNTOPO_NODE_NONE);
BLI_assert(node_index < bvh->totnode);
+ (void)bvh;
- return &bvh->nodes[node_index];
+ return node_index;
}
-static BMVert *pbvh_bmesh_vert_create(PBVH *bvh, int node_index,
- const float co[3],
- const BMVert *example,
- const int cd_vert_mask_offset,
- const int cd_vert_node_offset)
+static PBVHNode *pbvh_bmesh_node_lookup(PBVH *bvh, void *key)
+{
+ return &bvh->nodes[pbvh_bmesh_node_lookup_index(bvh, key)];
+}
+
+/* typecheck */
+#define pbvh_bmesh_node_lookup_index(bvh, key) ( \
+ CHECK_TYPE_ANY(key, BMFace *, BMVert *), \
+ pbvh_bmesh_node_lookup_index(bvh, key))
+#define pbvh_bmesh_node_lookup(bvh, key) ( \
+ CHECK_TYPE_ANY(key, BMFace *, BMVert *), \
+ pbvh_bmesh_node_lookup(bvh, key))
+
+
+static BMVert *pbvh_bmesh_vert_create(
+ PBVH *bvh, int node_index,
+ const float co[3], const float no[3],
+ const int cd_vert_mask_offset)
{
- BMVert *v = BM_vert_create(bvh->bm, co, example, BM_CREATE_NOP);
PBVHNode *node = &bvh->nodes[node_index];
+ BMVert *v;
BLI_assert((bvh->totnode == 1 || node_index) && node_index <= bvh->totnode);
+ /* avoid initializing customdata because its quite involved */
+ v = BM_vert_create(bvh->bm, co, NULL, BM_CREATE_SKIP_CD);
+ CustomData_bmesh_set_default(&bvh->bm->vdata, &v->head.data);
+
+ /* This value is logged below */
+ copy_v3_v3(v->no, no);
+
BLI_gset_insert(node->bm_unique_verts, v);
- BM_ELEM_CD_SET_INT(v, cd_vert_node_offset, node_index);
+ BM_ELEM_CD_SET_INT(v, bvh->cd_vert_node_offset, node_index);
node->flag |= PBVH_UpdateDrawBuffers | PBVH_UpdateBB;
@@ -307,9 +369,10 @@ static BMVert *pbvh_bmesh_vert_create(PBVH *bvh, int node_index,
return v;
}
-static BMFace *pbvh_bmesh_face_create(PBVH *bvh, int node_index,
- BMVert *v_tri[3], BMEdge *e_tri[3],
- const BMFace *f_example, const int cd_face_node_offset)
+static BMFace *pbvh_bmesh_face_create(
+ PBVH *bvh, int node_index,
+ BMVert *v_tri[3], BMEdge *e_tri[3],
+ const BMFace *f_example)
{
BMFace *f;
PBVHNode *node = &bvh->nodes[node_index];
@@ -317,11 +380,11 @@ static BMFace *pbvh_bmesh_face_create(PBVH *bvh, int node_index,
/* ensure we never add existing face */
BLI_assert(BM_face_exists(v_tri, 3, NULL) == false);
- f = BM_face_create(bvh->bm, v_tri, e_tri, 3, f_example, BM_CREATE_NOP);
+ f = BM_face_create(bvh->bm, v_tri, e_tri, 3, f_example, BM_CREATE_NO_DOUBLE);
f->head.hflag = f_example->head.hflag;
BLI_gset_insert(node->bm_faces, f);
- BM_ELEM_CD_SET_INT(f, cd_face_node_offset, node_index);
+ BM_ELEM_CD_SET_INT(f, bvh->cd_face_node_offset, node_index);
/* mark node for update */
node->flag |= PBVH_UpdateDrawBuffers | PBVH_UpdateNormals;
@@ -334,39 +397,59 @@ static BMFace *pbvh_bmesh_face_create(PBVH *bvh, int node_index,
}
/* Return the number of faces in 'node' that use vertex 'v' */
-static int pbvh_bmesh_node_vert_use_count(PBVH *bvh, PBVHNode *node, BMVert *v, const int cd_face_node_offset)
+#if 0
+static int pbvh_bmesh_node_vert_use_count(PBVH *bvh, PBVHNode *node, BMVert *v)
{
BMIter bm_iter;
BMFace *f;
int count = 0;
BM_ITER_ELEM (f, &bm_iter, v, BM_FACES_OF_VERT) {
- PBVHNode *f_node;
+ PBVHNode *f_node = pbvh_bmesh_node_lookup(bvh, f);
+ if (f_node == node) {
+ count++;
+ }
+ }
- f_node = pbvh_bmesh_node_lookup(bvh, f, cd_face_node_offset);
+ return count;
+}
+#endif
+
+#define pbvh_bmesh_node_vert_use_count_is_equal(bvh, node, v, n) \
+ (pbvh_bmesh_node_vert_use_count_ex(bvh, node, v, (n) + 1) == n)
- if (f_node == node)
+static int pbvh_bmesh_node_vert_use_count_ex(PBVH *bvh, PBVHNode *node, BMVert *v, const int count_max)
+{
+ BMIter bm_iter;
+ BMFace *f;
+ int count = 0;
+
+ BM_ITER_ELEM (f, &bm_iter, v, BM_FACES_OF_VERT) {
+ PBVHNode *f_node = pbvh_bmesh_node_lookup(bvh, f);
+ if (f_node == node) {
count++;
+ if (count == count_max) {
+ break;
+ }
+ }
}
return count;
}
/* Return a node that uses vertex 'v' other than its current owner */
-static PBVHNode *pbvh_bmesh_vert_other_node_find(PBVH *bvh, BMVert *v,
- const int cd_vert_node_offset,
- const int cd_face_node_offset)
+static PBVHNode *pbvh_bmesh_vert_other_node_find(PBVH *bvh, BMVert *v)
{
BMIter bm_iter;
BMFace *f;
PBVHNode *current_node;
- current_node = pbvh_bmesh_node_lookup(bvh, v, cd_vert_node_offset);
+ current_node = pbvh_bmesh_node_lookup(bvh, v);
BM_ITER_ELEM (f, &bm_iter, v, BM_FACES_OF_VERT) {
PBVHNode *f_node;
- f_node = pbvh_bmesh_node_lookup(bvh, f, cd_face_node_offset);
+ f_node = pbvh_bmesh_node_lookup(bvh, f);
if (f_node != current_node)
return f_node;
@@ -375,12 +458,13 @@ static PBVHNode *pbvh_bmesh_vert_other_node_find(PBVH *bvh, BMVert *v,
return NULL;
}
-static void pbvh_bmesh_vert_ownership_transfer(PBVH *bvh, PBVHNode *new_owner,
- BMVert *v, const int cd_vert_node_offset)
+static void pbvh_bmesh_vert_ownership_transfer(
+ PBVH *bvh, PBVHNode *new_owner,
+ BMVert *v)
{
PBVHNode *current_owner;
- current_owner = pbvh_bmesh_node_lookup(bvh, v, cd_vert_node_offset);
+ current_owner = pbvh_bmesh_node_lookup(bvh, v);
/* mark node for update */
current_owner->flag |= PBVH_UpdateDrawBuffers | PBVH_UpdateBB;
@@ -391,7 +475,7 @@ static void pbvh_bmesh_vert_ownership_transfer(PBVH *bvh, PBVHNode *new_owner,
BLI_gset_remove(current_owner->bm_unique_verts, v, NULL);
/* Set new ownership */
- BM_ELEM_CD_SET_INT(v, cd_vert_node_offset, new_owner - bvh->nodes);
+ BM_ELEM_CD_SET_INT(v, bvh->cd_vert_node_offset, new_owner - bvh->nodes);
BLI_gset_insert(new_owner->bm_unique_verts, v);
BLI_gset_remove(new_owner->bm_other_verts, v, NULL);
BLI_assert(!BLI_gset_haskey(new_owner->bm_other_verts, v));
@@ -400,20 +484,31 @@ static void pbvh_bmesh_vert_ownership_transfer(PBVH *bvh, PBVHNode *new_owner,
new_owner->flag |= PBVH_UpdateDrawBuffers | PBVH_UpdateBB;
}
-static void pbvh_bmesh_vert_remove(PBVH *bvh, BMVert *v, const int cd_vert_node_offset, const int cd_face_node_offset)
+static void pbvh_bmesh_vert_remove(PBVH *bvh, BMVert *v)
{
PBVHNode *v_node;
BMIter bm_iter;
BMFace *f;
- v_node = pbvh_bmesh_node_lookup(bvh, v, cd_vert_node_offset);
+ /* never match for first time */
+ int f_node_index_prev = DYNTOPO_NODE_NONE;
+
+ v_node = pbvh_bmesh_node_lookup(bvh, v);
BLI_gset_remove(v_node->bm_unique_verts, v, NULL);
- BM_ELEM_CD_SET_INT(v, cd_vert_node_offset, DYNTOPO_NODE_NONE);
+ BM_ELEM_CD_SET_INT(v, bvh->cd_vert_node_offset, DYNTOPO_NODE_NONE);
/* Have to check each neighboring face's node */
BM_ITER_ELEM (f, &bm_iter, v, BM_FACES_OF_VERT) {
- PBVHNode *f_node = pbvh_bmesh_node_lookup(bvh, f, cd_face_node_offset);
+ const int f_node_index = pbvh_bmesh_node_lookup_index(bvh, f);
+ PBVHNode *f_node;
+ /* faces often share the same node,
+ * quick check to avoid redundant #BLI_gset_remove calls */
+ if (f_node_index_prev == f_node_index)
+ continue;
+ f_node_index_prev = f_node_index;
+
+ f_node = &bvh->nodes[f_node_index];
f_node->flag |= PBVH_UpdateDrawBuffers | PBVH_UpdateBB;
/* Remove current ownership */
@@ -424,7 +519,7 @@ static void pbvh_bmesh_vert_remove(PBVH *bvh, BMVert *v, const int cd_vert_node_
}
}
-static void pbvh_bmesh_face_remove(PBVH *bvh, BMFace *f, const int cd_vert_node_offset, const int cd_face_node_offset)
+static void pbvh_bmesh_face_remove(PBVH *bvh, BMFace *f)
{
PBVHNode *f_node;
BMVert *v;
@@ -432,23 +527,23 @@ static void pbvh_bmesh_face_remove(PBVH *bvh, BMFace *f, const int cd_vert_node_
BMLoop *l_iter;
BMLoop *l_first;
- f_node = pbvh_bmesh_node_lookup(bvh, f, cd_face_node_offset);
+ f_node = pbvh_bmesh_node_lookup(bvh, f);
/* Check if any of this face's vertices need to be removed
* from the node */
l_iter = l_first = BM_FACE_FIRST_LOOP(f);
do {
v = l_iter->v;
- if (pbvh_bmesh_node_vert_use_count(bvh, f_node, v, cd_face_node_offset) == 1) {
+ if (pbvh_bmesh_node_vert_use_count_is_equal(bvh, f_node, v, 1)) {
if (BLI_gset_haskey(f_node->bm_unique_verts, v)) {
/* Find a different node that uses 'v' */
PBVHNode *new_node;
- new_node = pbvh_bmesh_vert_other_node_find(bvh, v, cd_vert_node_offset, cd_face_node_offset);
- BLI_assert(new_node || BM_vert_face_count(v) == 1);
+ new_node = pbvh_bmesh_vert_other_node_find(bvh, v);
+ BLI_assert(new_node || BM_vert_face_count_is_equal(v, 1));
if (new_node) {
- pbvh_bmesh_vert_ownership_transfer(bvh, new_node, v, cd_vert_node_offset);
+ pbvh_bmesh_vert_ownership_transfer(bvh, new_node, v);
}
}
else {
@@ -460,7 +555,7 @@ static void pbvh_bmesh_face_remove(PBVH *bvh, BMFace *f, const int cd_vert_node_
/* Remove face from node and top level */
BLI_gset_remove(f_node->bm_faces, f, NULL);
- BM_ELEM_CD_SET_INT(f, cd_face_node_offset, DYNTOPO_NODE_NONE);
+ BM_ELEM_CD_SET_INT(f, bvh->cd_face_node_offset, DYNTOPO_NODE_NONE);
/* Log removed face */
BM_log_face_removed(bvh->bm_log, f);
@@ -503,6 +598,15 @@ typedef struct {
const float *center;
float radius_squared;
float limit_len_squared;
+#ifdef USE_EDGEQUEUE_EVEN_SUBDIV
+ float limit_len;
+#endif
+
+#ifdef USE_EDGEQUEUE_FRONTFACE
+ const float *view_normal;
+ unsigned int use_view_normal : 1;
+#endif
+
} EdgeQueue;
typedef struct {
@@ -514,6 +618,44 @@ typedef struct {
int cd_face_node_offset;
} EdgeQueueContext;
+/* only tag'd edges are in the queue */
+#ifdef USE_EDGEQUEUE_TAG
+# define EDGE_QUEUE_TEST(e) (BM_elem_flag_test((CHECK_TYPE_INLINE(e, BMEdge *), e), BM_ELEM_TAG))
+# define EDGE_QUEUE_ENABLE(e) BM_elem_flag_enable((CHECK_TYPE_INLINE(e, BMEdge *), e), BM_ELEM_TAG)
+# define EDGE_QUEUE_DISABLE(e) BM_elem_flag_disable((CHECK_TYPE_INLINE(e, BMEdge *), e), BM_ELEM_TAG)
+#endif
+
+#ifdef USE_EDGEQUEUE_TAG_VERIFY
+/* simply check no edges are tagged
+ * (it's a requirement that edges enter and leave a clean tag state) */
+static void pbvh_bmesh_edge_tag_verify(PBVH *bvh)
+{
+ int n;
+
+ for (n = 0; n < bvh->totnode; n++) {
+ PBVHNode *node = &bvh->nodes[n];
+ GSetIterator gs_iter;
+ if (node->bm_faces) {
+ GSET_ITER (gs_iter, node->bm_faces) {
+ BMFace *f = BLI_gsetIterator_getKey(&gs_iter);
+ BMEdge *e_tri[3];
+ BMLoop *l_iter;
+
+ BLI_assert(f->len == 3);
+ l_iter = BM_FACE_FIRST_LOOP(f);
+ e_tri[0] = l_iter->e; l_iter = l_iter->next;
+ e_tri[1] = l_iter->e; l_iter = l_iter->next;
+ e_tri[2] = l_iter->e;
+
+ BLI_assert((EDGE_QUEUE_TEST(e_tri[0]) == false) &&
+ (EDGE_QUEUE_TEST(e_tri[1]) == false) &&
+ (EDGE_QUEUE_TEST(e_tri[2]) == false));
+ }
+ }
+ }
+}
+#endif
+
static bool edge_queue_tri_in_sphere(const EdgeQueue *q, BMFace *f)
{
BMVert *v_tri[3];
@@ -535,8 +677,9 @@ static bool check_mask(EdgeQueueContext *eq_ctx, BMVert *v)
return (BM_ELEM_CD_GET_FLOAT(v, eq_ctx->cd_vert_mask_offset) < 1.0f);
}
-static void edge_queue_insert(EdgeQueueContext *eq_ctx, BMEdge *e,
- float priority)
+static void edge_queue_insert(
+ EdgeQueueContext *eq_ctx, BMEdge *e,
+ float priority)
{
BMVert **pair;
@@ -555,28 +698,120 @@ static void edge_queue_insert(EdgeQueueContext *eq_ctx, BMEdge *e,
pair[0] = e->v1;
pair[1] = e->v2;
BLI_heap_insert(eq_ctx->q->heap, priority, pair);
+#ifdef USE_EDGEQUEUE_TAG
+ BLI_assert(EDGE_QUEUE_TEST(e) == false);
+ EDGE_QUEUE_ENABLE(e);
+#endif
}
}
-static void long_edge_queue_edge_add(EdgeQueueContext *eq_ctx,
- BMEdge *e)
+static void long_edge_queue_edge_add(
+ EdgeQueueContext *eq_ctx,
+ BMEdge *e)
{
- const float len_sq = BM_edge_calc_length_squared(e);
- if (len_sq > eq_ctx->q->limit_len_squared)
- edge_queue_insert(eq_ctx, e, -len_sq);
+#ifdef USE_EDGEQUEUE_TAG
+ if (EDGE_QUEUE_TEST(e) == false)
+#endif
+ {
+ const float len_sq = BM_edge_calc_length_squared(e);
+ if (len_sq > eq_ctx->q->limit_len_squared) {
+ edge_queue_insert(eq_ctx, e, -len_sq);
+ }
+ }
+}
+
+#ifdef USE_EDGEQUEUE_EVEN_SUBDIV
+static void long_edge_queue_edge_add_recursive(
+ EdgeQueueContext *eq_ctx,
+ BMLoop *l_edge, BMLoop *l_end,
+ const float len_sq, float limit_len)
+{
+ BLI_assert(len_sq > SQUARE(limit_len));
+
+#ifdef USE_EDGEQUEUE_FRONTFACE
+ if (eq_ctx->q->use_view_normal) {
+ if (dot_v3v3(l_edge->f->no, eq_ctx->q->view_normal) < 0.0f) {
+ return;
+ }
+ }
+#endif
+
+#ifdef USE_EDGEQUEUE_TAG
+ if (EDGE_QUEUE_TEST(l_edge->e) == false)
+#endif
+ {
+ edge_queue_insert(eq_ctx, l_edge->e, -len_sq);
+ }
+
+ /* temp support previous behavior! */
+ if (UNLIKELY(G.debug_value == 1234)) {
+ return;
+ }
+
+ if ((l_edge->radial_next != l_edge)) {
+ /* how much longer we need to be to consider for subdividing
+ * (avoids subdividing faces which are only *slightly* skinny) */
+#define EVEN_EDGELEN_THRESHOLD 1.2f
+ /* how much the limit increases per recursion
+ * (avoids performing subdvisions too far away) */
+#define EVEN_GENERATION_SCALE 1.6f
+
+ const float len_sq_cmp = len_sq * EVEN_EDGELEN_THRESHOLD;
+ float limit_len_sq;
+ BMLoop *l_iter;
+
+ limit_len *= EVEN_GENERATION_SCALE;
+ limit_len_sq = SQUARE(limit_len);
+
+ l_iter = l_edge;
+ do {
+ float len_sq_other;
+ BMLoop *l_adjacent[2] = {l_iter->next, l_iter->prev};
+ int i;
+ for (i = 0; i < ARRAY_SIZE(l_adjacent); i++) {
+ len_sq_other = BM_edge_calc_length_squared(l_adjacent[i]->e);
+ if (len_sq_other > max_ff(len_sq_cmp, limit_len_sq)) {
+// edge_queue_insert(eq_ctx, l_adjacent[i]->e, -len_sq_other);
+ long_edge_queue_edge_add_recursive(
+ eq_ctx, l_adjacent[i]->radial_next, l_adjacent[i],
+ len_sq_other, limit_len);
+ }
+ }
+ } while ((l_iter = l_iter->radial_next) != l_end);
+
+#undef EVEN_EDGELEN_THRESHOLD
+#undef EVEN_GENERATION_SCALE
+ }
}
+#endif /* USE_EDGEQUEUE_EVEN_SUBDIV */
-static void short_edge_queue_edge_add(EdgeQueueContext *eq_ctx,
- BMEdge *e)
+static void short_edge_queue_edge_add(
+ EdgeQueueContext *eq_ctx,
+ BMEdge *e)
{
- const float len_sq = BM_edge_calc_length_squared(e);
- if (len_sq < eq_ctx->q->limit_len_squared)
- edge_queue_insert(eq_ctx, e, len_sq);
+#ifdef USE_EDGEQUEUE_TAG
+ if (EDGE_QUEUE_TEST(e) == false)
+#endif
+ {
+ const float len_sq = BM_edge_calc_length_squared(e);
+ if (len_sq < eq_ctx->q->limit_len_squared) {
+ edge_queue_insert(eq_ctx, e, len_sq);
+ }
+ }
}
-static void long_edge_queue_face_add(EdgeQueueContext *eq_ctx,
- BMFace *f)
+static void long_edge_queue_face_add(
+ EdgeQueueContext *eq_ctx,
+ BMFace *f)
{
+#ifdef USE_EDGEQUEUE_FRONTFACE
+ if (eq_ctx->q->use_view_normal) {
+ if (dot_v3v3(f->no, eq_ctx->q->view_normal) < 0.0f) {
+ return;
+ }
+ }
+#endif
+
if (edge_queue_tri_in_sphere(eq_ctx->q, f)) {
BMLoop *l_iter;
BMLoop *l_first;
@@ -584,14 +819,34 @@ static void long_edge_queue_face_add(EdgeQueueContext *eq_ctx,
/* Check each edge of the face */
l_iter = l_first = BM_FACE_FIRST_LOOP(f);
do {
- long_edge_queue_edge_add(eq_ctx, l_iter->e);
+ {
+#ifdef USE_EDGEQUEUE_EVEN_SUBDIV
+ const float len_sq = BM_edge_calc_length_squared(l_iter->e);
+ if (len_sq > eq_ctx->q->limit_len_squared) {
+ long_edge_queue_edge_add_recursive(
+ eq_ctx, l_iter->radial_next, l_iter,
+ len_sq, eq_ctx->q->limit_len);
+ }
+#else
+ long_edge_queue_edge_add(eq_ctx, l_iter->e);
+#endif
+ }
} while ((l_iter = l_iter->next) != l_first);
}
}
-static void short_edge_queue_face_add(EdgeQueueContext *eq_ctx,
- BMFace *f)
+static void short_edge_queue_face_add(
+ EdgeQueueContext *eq_ctx,
+ BMFace *f)
{
+#ifdef USE_EDGEQUEUE_FRONTFACE
+ if (eq_ctx->q->use_view_normal) {
+ if (dot_v3v3(f->no, eq_ctx->q->view_normal) < 0.0f) {
+ return;
+ }
+ }
+#endif
+
if (edge_queue_tri_in_sphere(eq_ctx->q, f)) {
BMLoop *l_iter;
BMLoop *l_first;
@@ -613,9 +868,10 @@ static void short_edge_queue_face_add(EdgeQueueContext *eq_ctx,
*
* The highest priority (lowest number) is given to the longest edge.
*/
-static void long_edge_queue_create(EdgeQueueContext *eq_ctx,
- PBVH *bvh, const float center[3],
- float radius)
+static void long_edge_queue_create(
+ EdgeQueueContext *eq_ctx,
+ PBVH *bvh, const float center[3], const float view_normal[3],
+ float radius)
{
int n;
@@ -623,6 +879,21 @@ static void long_edge_queue_create(EdgeQueueContext *eq_ctx,
eq_ctx->q->center = center;
eq_ctx->q->radius_squared = radius * radius;
eq_ctx->q->limit_len_squared = bvh->bm_max_edge_len * bvh->bm_max_edge_len;
+#ifdef USE_EDGEQUEUE_EVEN_SUBDIV
+ eq_ctx->q->limit_len = bvh->bm_max_edge_len;
+#endif
+
+#ifdef USE_EDGEQUEUE_FRONTFACE
+ eq_ctx->q->view_normal = view_normal;
+ eq_ctx->q->use_view_normal = (view_normal != NULL);
+#else
+ UNUSED_VARS(view_normal);
+#endif
+
+#ifdef USE_EDGEQUEUE_TAG_VERIFY
+ pbvh_bmesh_edge_tag_verify(bvh);
+#endif
+
for (n = 0; n < bvh->totnode; n++) {
PBVHNode *node = &bvh->nodes[n];
@@ -653,9 +924,10 @@ static void long_edge_queue_create(EdgeQueueContext *eq_ctx,
*
* The highest priority (lowest number) is given to the shortest edge.
*/
-static void short_edge_queue_create(EdgeQueueContext *eq_ctx,
- PBVH *bvh, const float center[3],
- float radius)
+static void short_edge_queue_create(
+ EdgeQueueContext *eq_ctx,
+ PBVH *bvh, const float center[3], const float view_normal[3],
+ float radius)
{
int n;
@@ -663,6 +935,16 @@ static void short_edge_queue_create(EdgeQueueContext *eq_ctx,
eq_ctx->q->center = center;
eq_ctx->q->radius_squared = radius * radius;
eq_ctx->q->limit_len_squared = bvh->bm_min_edge_len * bvh->bm_min_edge_len;
+#ifdef USE_EDGEQUEUE_EVEN_SUBDIV
+ eq_ctx->q->limit_len = bvh->bm_min_edge_len;
+#endif
+
+#ifdef USE_EDGEQUEUE_FRONTFACE
+ eq_ctx->q->view_normal = view_normal;
+ eq_ctx->q->use_view_normal = (view_normal != NULL);
+#else
+ UNUSED_VARS(view_normal);
+#endif
for (n = 0; n < bvh->totnode; n++) {
PBVHNode *node = &bvh->nodes[n];
@@ -693,21 +975,24 @@ static void bm_edges_from_tri(BMesh *bm, BMVert *v_tri[3], BMEdge *e_tri[3])
e_tri[2] = BM_edge_create(bm, v_tri[2], v_tri[0], NULL, BM_CREATE_NO_DOUBLE);
}
-static void pbvh_bmesh_split_edge(EdgeQueueContext *eq_ctx, PBVH *bvh,
- BMEdge *e, BLI_Buffer *edge_loops)
+static void pbvh_bmesh_split_edge(
+ EdgeQueueContext *eq_ctx, PBVH *bvh,
+ BMEdge *e, BLI_Buffer *edge_loops)
{
BMVert *v_new;
- float mid[3];
+ float co_mid[3], no_mid[3];
int i, node_index;
/* Get all faces adjacent to the edge */
pbvh_bmesh_edge_loops(edge_loops, e);
/* Create a new vertex in current node at the edge's midpoint */
- mid_v3_v3v3(mid, e->v1->co, e->v2->co);
+ mid_v3_v3v3(co_mid, e->v1->co, e->v2->co);
+ mid_v3_v3v3(no_mid, e->v1->no, e->v2->no);
+ normalize_v3(no_mid);
node_index = BM_ELEM_CD_GET_INT(e->v1, eq_ctx->cd_vert_node_offset);
- v_new = pbvh_bmesh_vert_create(bvh, node_index, mid, e->v1, eq_ctx->cd_vert_mask_offset, eq_ctx->cd_vert_node_offset);
+ v_new = pbvh_bmesh_vert_create(bvh, node_index, co_mid, no_mid, eq_ctx->cd_vert_mask_offset);
/* update paint mask */
if (eq_ctx->cd_vert_mask_offset != -1) {
@@ -741,14 +1026,40 @@ static void pbvh_bmesh_split_edge(EdgeQueueContext *eq_ctx, PBVH *bvh,
v2 = l_adj->next->v;
if (ni != node_index && i == 0)
- pbvh_bmesh_vert_ownership_transfer(bvh, &bvh->nodes[ni], v_new, eq_ctx->cd_vert_node_offset);
+ pbvh_bmesh_vert_ownership_transfer(bvh, &bvh->nodes[ni], v_new);
+
+ /**
+ * The 2 new faces created and assigned to ``f_new`` have their
+ * verts & edges shuffled around.
+ *
+ * - faces wind anticlockwise in this example.
+ * - original edge is ``(v1, v2)``
+ * - oroginal face is ``(v1, v2, v3)``
+ *
+ * <pre>
+ * + v3(v_opp)
+ * /|\
+ * / | \
+ * / | \
+ * e4/ | \ e3
+ * / |e5 \
+ * / | \
+ * / e1 | e2 \
+ * +-------+-------+
+ * v1 v4(v_new) v2
+ * (first) (second)
+ * </pre>
+ *
+ * - f_new (first): ``v_tri=(v1, v4, v3), e_tri=(e1, e5, e4)``
+ * - f_new (second): ``v_tri=(v4, v2, v3), e_tri=(e2, e3, e5)``
+ */
/* Create two new faces */
v_tri[0] = v1;
v_tri[1] = v_new;
v_tri[2] = v_opp;
bm_edges_from_tri(bvh->bm, v_tri, e_tri);
- f_new = pbvh_bmesh_face_create(bvh, ni, v_tri, e_tri, f_adj, eq_ctx->cd_face_node_offset);
+ f_new = pbvh_bmesh_face_create(bvh, ni, v_tri, e_tri, f_adj);
long_edge_queue_face_add(eq_ctx, f_new);
v_tri[0] = v_new;
@@ -757,21 +1068,19 @@ static void pbvh_bmesh_split_edge(EdgeQueueContext *eq_ctx, PBVH *bvh,
e_tri[0] = BM_edge_create(bvh->bm, v_tri[0], v_tri[1], NULL, BM_CREATE_NO_DOUBLE);
e_tri[2] = e_tri[1]; /* switched */
e_tri[1] = BM_edge_create(bvh->bm, v_tri[1], v_tri[2], NULL, BM_CREATE_NO_DOUBLE);
- f_new = pbvh_bmesh_face_create(bvh, ni, v_tri, e_tri, f_adj, eq_ctx->cd_face_node_offset);
+ f_new = pbvh_bmesh_face_create(bvh, ni, v_tri, e_tri, f_adj);
long_edge_queue_face_add(eq_ctx, f_new);
/* Delete original */
- pbvh_bmesh_face_remove(bvh, f_adj, eq_ctx->cd_vert_node_offset, eq_ctx->cd_face_node_offset);
+ pbvh_bmesh_face_remove(bvh, f_adj);
BM_face_kill(bvh->bm, f_adj);
/* Ensure new vertex is in the node */
- if (!BLI_gset_haskey(bvh->nodes[ni].bm_unique_verts, v_new) &&
- !BLI_gset_haskey(bvh->nodes[ni].bm_other_verts, v_new))
- {
- BLI_gset_insert(bvh->nodes[ni].bm_other_verts, v_new);
+ if (!BLI_gset_haskey(bvh->nodes[ni].bm_unique_verts, v_new)) {
+ BLI_gset_add(bvh->nodes[ni].bm_other_verts, v_new);
}
- if (BM_vert_edge_count(v_opp) >= 9) {
+ if (BM_vert_edge_count_is_over(v_opp, 8)) {
BMIter bm_iter;
BMEdge *e2;
@@ -784,8 +1093,9 @@ static void pbvh_bmesh_split_edge(EdgeQueueContext *eq_ctx, PBVH *bvh,
BM_edge_kill(bvh->bm, e);
}
-static bool pbvh_bmesh_subdivide_long_edges(EdgeQueueContext *eq_ctx, PBVH *bvh,
- BLI_Buffer *edge_loops)
+static bool pbvh_bmesh_subdivide_long_edges(
+ EdgeQueueContext *eq_ctx, PBVH *bvh,
+ BLI_Buffer *edge_loops)
{
bool any_subdivided = false;
@@ -797,13 +1107,22 @@ static bool pbvh_bmesh_subdivide_long_edges(EdgeQueueContext *eq_ctx, PBVH *bvh,
BLI_mempool_free(eq_ctx->pool, pair);
pair = NULL;
- if (len_squared_v3v3(v1->co, v2->co) <= eq_ctx->q->limit_len_squared)
- continue;
-
/* Check that the edge still exists */
if (!(e = BM_edge_exists(v1, v2))) {
continue;
}
+#ifdef USE_EDGEQUEUE_TAG
+ EDGE_QUEUE_DISABLE(e);
+#endif
+
+ /* At the moment edges never get shorter (subdiv will make new edges)
+ * unlike collapse where edges can become longer. */
+#if 0
+ if (len_squared_v3v3(v1->co, v2->co) <= eq_ctx->q->limit_len_squared)
+ continue;
+#else
+ BLI_assert(len_squared_v3v3(v1->co, v2->co) > eq_ctx->q->limit_len_squared);
+#endif
/* Check that the edge's vertices are still in the PBVH. It's
* possible that an edge collapse has deleted adjacent faces
@@ -820,18 +1139,23 @@ static bool pbvh_bmesh_subdivide_long_edges(EdgeQueueContext *eq_ctx, PBVH *bvh,
pbvh_bmesh_split_edge(eq_ctx, bvh, e, edge_loops);
}
+#ifdef USE_EDGEQUEUE_TAG_VERIFY
+ pbvh_bmesh_edge_tag_verify(bvh);
+#endif
+
return any_subdivided;
}
-static void pbvh_bmesh_collapse_edge(PBVH *bvh, BMEdge *e,
- BMVert *v1, BMVert *v2,
- GSet *deleted_verts,
- BLI_Buffer *edge_loops,
- BLI_Buffer *deleted_faces,
- EdgeQueueContext *eq_ctx)
+static void pbvh_bmesh_collapse_edge(
+ PBVH *bvh, BMEdge *e,
+ BMVert *v1, BMVert *v2,
+ GSet *deleted_verts,
+ BLI_Buffer *deleted_faces,
+ EdgeQueueContext *eq_ctx)
{
BMIter bm_iter;
BMFace *f;
+ BMLoop *l_adj;
BMVert *v_del, *v_conn;
int i;
float mask_v1 = BM_ELEM_CD_GET_FLOAT(v1, eq_ctx->cd_vert_mask_offset);
@@ -846,18 +1170,14 @@ static void pbvh_bmesh_collapse_edge(PBVH *bvh, BMEdge *e,
v_conn = v1;
}
- /* Get all faces adjacent to the edge */
- pbvh_bmesh_edge_loops(edge_loops, e);
-
/* Remove the merge vertex from the PBVH */
- pbvh_bmesh_vert_remove(bvh, v_del, eq_ctx->cd_vert_node_offset, eq_ctx->cd_face_node_offset);
+ pbvh_bmesh_vert_remove(bvh, v_del);
/* Remove all faces adjacent to the edge */
- for (i = 0; i < edge_loops->count; i++) {
- BMLoop *l_adj = BLI_buffer_at(edge_loops, BMLoop *, i);
+ while ((l_adj = e->l)) {
BMFace *f_adj = l_adj->f;
- pbvh_bmesh_face_remove(bvh, f_adj, eq_ctx->cd_vert_node_offset, eq_ctx->cd_face_node_offset);
+ pbvh_bmesh_face_remove(bvh, f_adj);
BM_face_kill(bvh->bm, f_adj);
}
@@ -870,7 +1190,8 @@ static void pbvh_bmesh_collapse_edge(PBVH *bvh, BMEdge *e,
/* Note: this could be done with BM_vert_splice(), but that
* requires handling other issues like duplicate edges, so doesn't
* really buy anything. */
- deleted_faces->count = 0;
+ BLI_buffer_empty(deleted_faces);
+
BM_ITER_ELEM (f, &bm_iter, v_del, BM_FACES_OF_VERT) {
BMVert *v_tri[3];
BMFace *existing_face;
@@ -896,16 +1217,14 @@ static void pbvh_bmesh_collapse_edge(PBVH *bvh, BMEdge *e,
}
else {
BMEdge *e_tri[3];
- n = pbvh_bmesh_node_lookup(bvh, f, eq_ctx->cd_face_node_offset);
+ n = pbvh_bmesh_node_lookup(bvh, f);
ni = n - bvh->nodes;
bm_edges_from_tri(bvh->bm, v_tri, e_tri);
- pbvh_bmesh_face_create(bvh, ni, v_tri, e_tri, f, eq_ctx->cd_face_node_offset);
+ pbvh_bmesh_face_create(bvh, ni, v_tri, e_tri, f);
/* Ensure that v_conn is in the new face's node */
- if (!BLI_gset_haskey(n->bm_unique_verts, v_conn) &&
- !BLI_gset_haskey(n->bm_other_verts, v_conn))
- {
- BLI_gset_insert(n->bm_other_verts, v_conn);
+ if (!BLI_gset_haskey(n->bm_unique_verts, v_conn)) {
+ BLI_gset_add(n->bm_other_verts, v_conn);
}
}
@@ -927,20 +1246,8 @@ static void pbvh_bmesh_collapse_edge(PBVH *bvh, BMEdge *e,
v_tri[1] = l_iter->v; e_tri[1] = l_iter->e; l_iter = l_iter->next;
v_tri[2] = l_iter->v; e_tri[2] = l_iter->e;
- /* Check if any of the face's vertices are now unused, if so
- * remove them from the PBVH */
- for (j = 0; j < 3; j++) {
- if (v_tri[j] != v_del && BM_vert_face_count(v_tri[j]) == 1) {
- BLI_gset_insert(deleted_verts, v_tri[j]);
- pbvh_bmesh_vert_remove(bvh, v_tri[j], eq_ctx->cd_vert_node_offset, eq_ctx->cd_face_node_offset);
- }
- else {
- v_tri[j] = NULL;
- }
- }
-
/* Remove the face */
- pbvh_bmesh_face_remove(bvh, f_del, eq_ctx->cd_vert_node_offset, eq_ctx->cd_face_node_offset);
+ pbvh_bmesh_face_remove(bvh, f_del);
BM_face_kill(bvh->bm, f_del);
/* Check if any of the face's edges are now unused by any
@@ -950,9 +1257,13 @@ static void pbvh_bmesh_collapse_edge(PBVH *bvh, BMEdge *e,
BM_edge_kill(bvh->bm, e_tri[j]);
}
- /* Delete unused vertices */
+ /* Check if any of the face's vertices are now unused, if so
+ * remove them from the PBVH */
for (j = 0; j < 3; j++) {
- if (v_tri[j]) {
+ if ((v_tri[j] != v_del) && (v_tri[j]->e == NULL)) {
+ BLI_gset_insert(deleted_verts, v_tri[j]);
+ pbvh_bmesh_vert_remove(bvh, v_tri[j]);
+
BM_log_vert_removed(bvh->bm_log, v_tri[j], eq_ctx->cd_vert_mask_offset);
BM_vert_kill(bvh->bm, v_tri[j]);
}
@@ -964,19 +1275,21 @@ static void pbvh_bmesh_collapse_edge(PBVH *bvh, BMEdge *e,
if (!BLI_gset_haskey(deleted_verts, v_conn)) {
BM_log_vert_before_modified(bvh->bm_log, v_conn, eq_ctx->cd_vert_mask_offset);
mid_v3_v3v3(v_conn->co, v_conn->co, v_del->co);
+ add_v3_v3(v_conn->no, v_del->no);
+ normalize_v3(v_conn->no);
}
/* Delete v_del */
- BLI_assert(BM_vert_face_count(v_del) == 0);
+ BLI_assert(!BM_vert_face_check(v_del));
BLI_gset_insert(deleted_verts, v_del);
BM_log_vert_removed(bvh->bm_log, v_del, eq_ctx->cd_vert_mask_offset);
BM_vert_kill(bvh->bm, v_del);
}
-static bool pbvh_bmesh_collapse_short_edges(EdgeQueueContext *eq_ctx,
- PBVH *bvh,
- BLI_Buffer *edge_loops,
- BLI_Buffer *deleted_faces)
+static bool pbvh_bmesh_collapse_short_edges(
+ EdgeQueueContext *eq_ctx,
+ PBVH *bvh,
+ BLI_Buffer *deleted_faces)
{
float min_len_squared = bvh->bm_min_edge_len * bvh->bm_min_edge_len;
GSet *deleted_verts;
@@ -999,13 +1312,16 @@ static bool pbvh_bmesh_collapse_short_edges(EdgeQueueContext *eq_ctx,
continue;
}
- if (len_squared_v3v3(v1->co, v2->co) >= min_len_squared)
- continue;
-
/* Check that the edge still exists */
if (!(e = BM_edge_exists(v1, v2))) {
continue;
}
+#ifdef USE_EDGEQUEUE_TAG
+ EDGE_QUEUE_DISABLE(e);
+#endif
+
+ if (len_squared_v3v3(v1->co, v2->co) >= min_len_squared)
+ continue;
/* Check that the edge's vertices are still in the PBVH. It's
* possible that an edge collapse has deleted adjacent faces
@@ -1020,7 +1336,7 @@ static bool pbvh_bmesh_collapse_short_edges(EdgeQueueContext *eq_ctx,
any_collapsed = true;
pbvh_bmesh_collapse_edge(bvh, e, v1, v2,
- deleted_verts, edge_loops,
+ deleted_verts,
deleted_faces, eq_ctx);
}
@@ -1031,9 +1347,10 @@ static bool pbvh_bmesh_collapse_short_edges(EdgeQueueContext *eq_ctx,
/************************* Called from pbvh.c *************************/
-bool pbvh_bmesh_node_raycast(PBVHNode *node, const float ray_start[3],
- const float ray_normal[3], float *dist,
- bool use_original)
+bool pbvh_bmesh_node_raycast(
+ PBVHNode *node, const float ray_start[3],
+ const float ray_normal[3], float *dist,
+ bool use_original)
{
bool hit = false;
@@ -1041,11 +1358,12 @@ bool pbvh_bmesh_node_raycast(PBVHNode *node, const float ray_start[3],
int i;
for (i = 0; i < node->bm_tot_ortri; i++) {
const int *t = node->bm_ortri[i];
- hit |= ray_face_intersection(ray_start, ray_normal,
- node->bm_orco[t[0]],
- node->bm_orco[t[1]],
- node->bm_orco[t[2]],
- NULL, dist);
+ hit |= ray_face_intersection_tri(
+ ray_start, ray_normal,
+ node->bm_orco[t[0]],
+ node->bm_orco[t[1]],
+ node->bm_orco[t[2]],
+ dist);
}
}
else {
@@ -1059,11 +1377,12 @@ bool pbvh_bmesh_node_raycast(PBVHNode *node, const float ray_start[3],
BMVert *v_tri[3];
BM_face_as_array_vert_tri(f, v_tri);
- hit |= ray_face_intersection(ray_start, ray_normal,
- v_tri[0]->co,
- v_tri[1]->co,
- v_tri[2]->co,
- NULL, dist);
+ hit |= ray_face_intersection_tri(
+ ray_start, ray_normal,
+ v_tri[0]->co,
+ v_tri[1]->co,
+ v_tri[2]->co,
+ dist);
}
}
}
@@ -1074,7 +1393,7 @@ bool pbvh_bmesh_node_raycast(PBVHNode *node, const float ray_start[3],
bool BKE_pbvh_bmesh_node_raycast_detail(
PBVHNode *node,
const float ray_start[3], const float ray_normal[3],
- float *detail, float *dist)
+ float *dist, float *r_detail)
{
GSetIterator gs_iter;
bool hit = false;
@@ -1091,12 +1410,12 @@ bool BKE_pbvh_bmesh_node_raycast_detail(
BMVert *v_tri[3];
bool hit_local;
BM_face_as_array_vert_tri(f, v_tri);
- hit_local = ray_face_intersection(
+ hit_local = ray_face_intersection_tri(
ray_start, ray_normal,
v_tri[0]->co,
v_tri[1]->co,
v_tri[2]->co,
- NULL, dist);
+ dist);
if (hit_local) {
f_hit = f;
@@ -1114,7 +1433,7 @@ bool BKE_pbvh_bmesh_node_raycast_detail(
len3 = len_squared_v3v3(v_tri[2]->co, v_tri[0]->co);
/* detail returned will be set to the maximum allowed size, so take max here */
- *detail = sqrtf(max_fff(len1, len2, len3));
+ *r_detail = sqrtf(max_fff(len1, len2, len3));
}
return hit;
@@ -1146,36 +1465,225 @@ void pbvh_bmesh_normals_update(PBVHNode **nodes, int totnode)
}
}
-/***************************** Public API *****************************/
+typedef struct FastNodeBuildInfo {
+ int totface; /* number of faces */
+ int start; /* start of faces in array */
+ struct FastNodeBuildInfo *child1;
+ struct FastNodeBuildInfo *child2;
+} FastNodeBuildInfo;
-static void pbvh_bmesh_node_layers_reset(PBVH *bvh)
+/* Recursively split the node if it exceeds the leaf_limit. This function is multithreadabe since each invocation applies
+ * to a sub part of the arrays */
+static void pbvh_bmesh_node_limit_ensure_fast(PBVH *bvh, BMFace **nodeinfo, BBC *bbc_array, FastNodeBuildInfo *node, MemArena *arena)
{
BMFace *f;
- BMVert *v;
- BMIter iter;
- BMesh *bm = bvh->bm;
- int cd_vert_node_offset = bvh->cd_vert_node_offset;
- int cd_face_node_offset = bvh->cd_face_node_offset;
+ BB cb;
+ BBC *bbc;
+ float mid;
+ int axis, i;
+ int end;
+ FastNodeBuildInfo *child1, *child2;
+ int num_child1, num_child2;
+ BMFace *tmp;
- /* clear the elements of the node information */
- BM_ITER_MESH(v, &iter, bm, BM_VERTS_OF_MESH) {
- BM_ELEM_CD_SET_INT(v, cd_vert_node_offset, DYNTOPO_NODE_NONE);
+ if (node->totface <= bvh->leaf_limit) {
+ return;
}
- BM_ITER_MESH(f, &iter, bm, BM_FACES_OF_MESH) {
- BM_ELEM_CD_SET_INT(f, cd_face_node_offset, DYNTOPO_NODE_NONE);
+ /* Calculate bounding box around primitive centroids */
+ BB_reset(&cb);
+ for (i = 0; i < node->totface; i++) {
+ f = nodeinfo[i + node->start];
+ bbc = &bbc_array[BM_elem_index_get(f)];
+
+ BB_expand(&cb, bbc->bcentroid);
+ }
+
+ /* initialize the children */
+
+ /* Find widest axis and its midpoint */
+ axis = BB_widest_axis(&cb);
+ mid = (cb.bmax[axis] + cb.bmin[axis]) * 0.5f;
+
+ num_child1 = 0, num_child2 = 0;
+
+ /* split vertices along the middle line */
+ end = node->start + node->totface;
+ for (i = node->start; i < end - num_child2; i++) {
+ f = nodeinfo[i];
+ bbc = &bbc_array[BM_elem_index_get(f)];
+
+ if (bbc->bcentroid[axis] > mid) {
+ int i_iter = end - num_child2 - 1;
+ int candidate = -1;
+ /* found a face that should be part of another node, look for a face to substitute with */
+
+ for (;i_iter > i; i_iter--) {
+ BMFace *f_iter = nodeinfo[i_iter];
+ const BBC *bbc_iter = &bbc_array[BM_elem_index_get(f_iter)];
+ if (bbc_iter->bcentroid[axis] <= mid) {
+ candidate = i_iter;
+ break;
+ }
+ else {
+ num_child2++;
+ }
+ }
+
+ if (candidate != -1) {
+ tmp = nodeinfo[i];
+ nodeinfo[i] = nodeinfo[candidate];
+ nodeinfo[candidate] = tmp;
+ /* increase both counts */
+ num_child1++;
+ num_child2++;
+ }
+ else {
+ /* not finding candidate means second half of array part is full of
+ * second node parts, just increase the number of child nodes for it */
+ num_child2++;
+ }
+ }
+ else {
+ num_child1++;
+ }
}
+
+ /* ensure at least one child in each node */
+ if (num_child2 == 0) {
+ num_child2++;
+ num_child1--;
+ }
+ else if (num_child1 == 0) {
+ num_child1++;
+ num_child2--;
+ }
+
+ /* at this point, faces should have been split along the array range sequentially,
+ * each sequential part belonging to one node only */
+ BLI_assert((num_child1 + num_child2) == node->totface);
+
+ node->child1 = child1 = BLI_memarena_alloc(arena, sizeof(FastNodeBuildInfo));
+ node->child2 = child2 = BLI_memarena_alloc(arena, sizeof(FastNodeBuildInfo));
+
+ child1->totface = num_child1;
+ child1->start = node->start;
+ child2->totface = num_child2;
+ child2->start = node->start + num_child1;
+ child1->child1 = child1->child2 = child2->child1 = child2->child2 = NULL;
+
+ pbvh_bmesh_node_limit_ensure_fast(bvh, nodeinfo, bbc_array, child1, arena);
+ pbvh_bmesh_node_limit_ensure_fast(bvh, nodeinfo, bbc_array, child2, arena);
+
+ return;
}
+static void pbvh_bmesh_create_nodes_fast_recursive(PBVH *bvh, BMFace **nodeinfo, BBC *bbc_array, FastNodeBuildInfo *node, int node_index)
+{
+ PBVHNode *n = bvh->nodes + node_index;
+ /* two cases, node does not have children or does have children */
+ if (node->child1) {
+ int children_offset = bvh->totnode;
+
+ n->children_offset = children_offset;
+ pbvh_grow_nodes(bvh, bvh->totnode + 2);
+ pbvh_bmesh_create_nodes_fast_recursive(bvh, nodeinfo, bbc_array, node->child1, children_offset);
+ pbvh_bmesh_create_nodes_fast_recursive(bvh, nodeinfo, bbc_array, node->child2, children_offset + 1);
+
+ n = &bvh->nodes[node_index];
+
+ /* Update bounding box */
+ BB_reset(&n->vb);
+ BB_expand_with_bb(&n->vb, &bvh->nodes[n->children_offset].vb);
+ BB_expand_with_bb(&n->vb, &bvh->nodes[n->children_offset + 1].vb);
+ n->orig_vb = n->vb;
+ }
+ else {
+ /* node does not have children so it's a leaf node, populate with faces and tag accordingly
+ * this is an expensive part but it's not so easily threadable due to vertex node indices */
+ const int cd_vert_node_offset = bvh->cd_vert_node_offset;
+ const int cd_face_node_offset = bvh->cd_face_node_offset;
+
+ bool has_visible = false;
+ int i, end;
+ BMFace *f;
+ BMLoop *l_iter;
+ BMLoop *l_first;
+ BMVert *v;
+ BBC *bbc;
+
+ n->flag = PBVH_Leaf;
+ n->bm_faces = BLI_gset_ptr_new_ex("bm_faces", node->totface);
+
+ /* Create vert hash sets */
+ n->bm_unique_verts = BLI_gset_ptr_new("bm_unique_verts");
+ n->bm_other_verts = BLI_gset_ptr_new("bm_other_verts");
+
+ BB_reset(&n->vb);
+
+ end = node->start + node->totface;
+
+ for (i = node->start; i < end; i++) {
+ f = nodeinfo[i];
+ bbc = &bbc_array[BM_elem_index_get(f)];
+
+ /* Update ownership of faces */
+ BLI_gset_insert(n->bm_faces, f);
+ BM_ELEM_CD_SET_INT(f, cd_face_node_offset, node_index);
+
+ /* Update vertices */
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
+ v = l_iter->v;
+ if (!BLI_gset_haskey(n->bm_unique_verts, v)) {
+ if (BM_ELEM_CD_GET_INT(v, cd_vert_node_offset) != DYNTOPO_NODE_NONE) {
+ BLI_gset_add(n->bm_other_verts, v);
+ }
+ else {
+ BLI_gset_insert(n->bm_unique_verts, v);
+ BM_ELEM_CD_SET_INT(v, cd_vert_node_offset, node_index);
+ }
+ }
+ /* Update node bounding box */
+ } while ((l_iter = l_iter->next) != l_first);
+
+ if (!BM_elem_flag_test(f, BM_ELEM_HIDDEN))
+ has_visible = true;
+
+ BB_expand_with_bb(&n->vb, (BB *)bbc);
+ }
+
+ BLI_assert(n->vb.bmin[0] <= n->vb.bmax[0] &&
+ n->vb.bmin[1] <= n->vb.bmax[1] &&
+ n->vb.bmin[2] <= n->vb.bmax[2]);
+
+ n->orig_vb = n->vb;
+
+ /* Build GPU buffers for new node and update vertex normals */
+ BKE_pbvh_node_mark_rebuild_draw(n);
+
+ BKE_pbvh_node_fully_hidden_set(n, !has_visible);
+ n->flag |= PBVH_UpdateNormals;
+ }
+}
+
+
+/***************************** Public API *****************************/
/* Build a PBVH from a BMesh */
-void BKE_pbvh_build_bmesh(PBVH *bvh, BMesh *bm, bool smooth_shading, BMLog *log,
- const int cd_vert_node_offset, const int cd_face_node_offset)
+void BKE_pbvh_build_bmesh(
+ PBVH *bvh, BMesh *bm, bool smooth_shading, BMLog *log,
+ const int cd_vert_node_offset, const int cd_face_node_offset)
{
BMIter iter;
BMFace *f;
- PBVHNode *n;
- int node_index = 0;
+ BMVert *v;
+ int i;
+ /* bounding box array of all faces, no need to recalculate every time */
+ BBC *bbc_array;
+ BMFace **nodeinfo;
+ FastNodeBuildInfo rootnode = {0};
+ MemArena *arena;
bvh->cd_vert_node_offset = cd_vert_node_offset;
bvh->cd_face_node_offset = cd_face_node_offset;
@@ -1192,29 +1700,64 @@ void BKE_pbvh_build_bmesh(PBVH *bvh, BMesh *bm, bool smooth_shading, BMLog *log,
if (smooth_shading)
bvh->flags |= PBVH_DYNTOPO_SMOOTH_SHADING;
- pbvh_bmesh_node_layers_reset(bvh);
+ /* calculate all bounding boxes once for all faces */
+ bbc_array = MEM_mallocN(sizeof(BBC) * bm->totface, "BBC");
+ nodeinfo = MEM_mallocN(sizeof(*nodeinfo) * bm->totface, "nodeinfo");
+ arena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, "fast PBVH node storage");
+
+ BM_ITER_MESH_INDEX(f, &iter, bm, BM_FACES_OF_MESH, i) {
+ BBC *bbc = &bbc_array[i];
+ BMLoop *l_iter;
+ BMLoop *l_first;
+
+ BB_reset((BB *)bbc);
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
+ BB_expand((BB *)bbc, l_iter->v->co);
+ } while ((l_iter = l_iter->next) != l_first);
+ BBC_update_centroid(bbc);
+
+ /* so we can do direct lookups on 'bbc_array' */
+ BM_elem_index_set(f, i); /* set_dirty! */
+ nodeinfo[i] = f;
+ BM_ELEM_CD_SET_INT(f, cd_face_node_offset, DYNTOPO_NODE_NONE);
+ }
+
+ BM_ITER_MESH(v, &iter, bm, BM_VERTS_OF_MESH) {
+ BM_ELEM_CD_SET_INT(v, cd_vert_node_offset, DYNTOPO_NODE_NONE);
+ }
+
+ /* likely this is already dirty */
+ bm->elem_index_dirty |= BM_FACE;
+
+ /* setup root node */
+ rootnode.totface = bm->totface;
+
+ /* start recursion, assign faces to nodes accordingly */
+ pbvh_bmesh_node_limit_ensure_fast(bvh, nodeinfo, bbc_array, &rootnode, arena);
+
+ /* we now have all faces assigned to a node, next we need to assign those to the gsets of the nodes */
/* Start with all faces in the root node */
- n = bvh->nodes = MEM_callocN(sizeof(PBVHNode), "PBVHNode");
+ bvh->nodes = MEM_callocN(sizeof(PBVHNode), "PBVHNode");
bvh->totnode = 1;
- n->flag = PBVH_Leaf;
- n->bm_faces = BLI_gset_ptr_new_ex("bm_faces", bvh->bm->totface);
- BM_ITER_MESH (f, &iter, bvh->bm, BM_FACES_OF_MESH) {
- BLI_gset_insert(n->bm_faces, f);
- }
- /* Recursively split the node until it is under the limit; if no
- * splitting occurs then finalize the existing leaf node */
- if (!pbvh_bmesh_node_limit_ensure(bvh, node_index))
- pbvh_bmesh_node_finalize(bvh, 0, cd_vert_node_offset, cd_face_node_offset);
+ /* take root node and visit and populate children recursively */
+ pbvh_bmesh_create_nodes_fast_recursive(bvh, nodeinfo, bbc_array, &rootnode, 0);
+
+ BLI_memarena_free(arena);
+ MEM_freeN(bbc_array);
+ MEM_freeN(nodeinfo);
}
/* Collapse short edges, subdivide long edges */
-bool BKE_pbvh_bmesh_update_topology(PBVH *bvh, PBVHTopologyUpdateMode mode,
- const float center[3], float radius)
+bool BKE_pbvh_bmesh_update_topology(
+ PBVH *bvh, PBVHTopologyUpdateMode mode,
+ const float center[3], const float view_normal[3],
+ float radius)
{
/* 2 is enough for edge faces - manifold edge */
- BLI_buffer_declare_static(BMFace *, edge_loops, BLI_BUFFER_NOP, 2);
+ BLI_buffer_declare_static(BMLoop *, edge_loops, BLI_BUFFER_NOP, 2);
BLI_buffer_declare_static(BMFace *, deleted_faces, BLI_BUFFER_NOP, 32);
const int cd_vert_mask_offset = CustomData_get_offset(&bvh->bm->vdata, CD_PAINT_MASK);
const int cd_vert_node_offset = bvh->cd_vert_node_offset;
@@ -1223,14 +1766,18 @@ bool BKE_pbvh_bmesh_update_topology(PBVH *bvh, PBVHTopologyUpdateMode mode,
bool modified = false;
int n;
+ if (view_normal) {
+ BLI_assert(len_squared_v3(view_normal) != 0.0f);
+ }
+
if (mode & PBVH_Collapse) {
EdgeQueue q;
BLI_mempool *queue_pool = BLI_mempool_create(sizeof(BMVert *[2]), 0, 128, BLI_MEMPOOL_NOP);
EdgeQueueContext eq_ctx = {&q, queue_pool, bvh->bm, cd_vert_mask_offset, cd_vert_node_offset, cd_face_node_offset};
- short_edge_queue_create(&eq_ctx, bvh, center, radius);
+ short_edge_queue_create(&eq_ctx, bvh, center, view_normal, radius);
modified |= !BLI_heap_is_empty(q.heap);
- pbvh_bmesh_collapse_short_edges(&eq_ctx, bvh, &edge_loops,
+ pbvh_bmesh_collapse_short_edges(&eq_ctx, bvh,
&deleted_faces);
BLI_heap_free(q.heap, NULL);
BLI_mempool_destroy(queue_pool);
@@ -1241,7 +1788,7 @@ bool BKE_pbvh_bmesh_update_topology(PBVH *bvh, PBVHTopologyUpdateMode mode,
BLI_mempool *queue_pool = BLI_mempool_create(sizeof(BMVert *[2]), 0, 128, BLI_MEMPOOL_NOP);
EdgeQueueContext eq_ctx = {&q, queue_pool, bvh->bm, cd_vert_mask_offset, cd_vert_node_offset, cd_face_node_offset};
- long_edge_queue_create(&eq_ctx, bvh, center, radius);
+ long_edge_queue_create(&eq_ctx, bvh, center, view_normal, radius);
modified |= !BLI_heap_is_empty(q.heap);
pbvh_bmesh_subdivide_long_edges(&eq_ctx, bvh, &edge_loops);
BLI_heap_free(q.heap, NULL);
@@ -1261,6 +1808,10 @@ bool BKE_pbvh_bmesh_update_topology(PBVH *bvh, PBVHTopologyUpdateMode mode,
BLI_buffer_free(&edge_loops);
BLI_buffer_free(&deleted_faces);
+#ifdef USE_VERIFY
+ pbvh_bmesh_verify(bvh);
+#endif
+
return modified;
}
@@ -1382,104 +1933,28 @@ struct GSet *BKE_pbvh_bmesh_node_faces(PBVHNode *node)
#if 0
-void bli_gset_duplicate_key_check(GSet *gs)
+static void pbvh_bmesh_print(PBVH *bvh)
{
- GSetIterator gs_iter1, gs_iter2;
-
- GSET_ITER (gs_iter1, gs) {
- void *key1 = BLI_gsetIterator_getKey(&gs_iter1);
- int dup = -1;
-
- GSET_ITER (gs_iter2, gs) {
- void *key2 = BLI_gsetIterator_getKey(&gs_iter2);
-
- if (key1 == key2) {
- dup++;
- if (dup > 0) {
- BLI_assert(!"duplicate in hash");
- }
- }
- }
- }
-}
-
-void bmesh_print(BMesh *bm)
-{
- BMIter iter, siter;
- BMVert *v;
- BMEdge *e;
- BMFace *f;
- BMLoop *l;
-
- fprintf(stderr, "\nbm=%p, totvert=%d, totedge=%d, "
- "totloop=%d, totface=%d\n",
- bm, bm->totvert, bm->totedge,
- bm->totloop, bm->totface);
-
- fprintf(stderr, "vertices:\n");
- BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
- fprintf(stderr, " %d co=(%.3f %.3f %.3f) oflag=%x\n",
- BM_elem_index_get(v), v->co[0], v->co[1], v->co[2],
- v->oflags[bm->stackdepth - 1].f);
- }
-
- fprintf(stderr, "edges:\n");
- BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
- fprintf(stderr, " %d v1=%d, v2=%d, oflag=%x\n",
- BM_elem_index_get(e),
- BM_elem_index_get(e->v1),
- BM_elem_index_get(e->v2),
- e->oflags[bm->stackdepth - 1].f);
- }
-
- fprintf(stderr, "faces:\n");
- BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
- fprintf(stderr, " %d len=%d, oflag=%x\n",
- BM_elem_index_get(f), f->len,
- f->oflags[bm->stackdepth - 1].f);
-
- fprintf(stderr, " v: ");
- BM_ITER_ELEM(v, &siter, f, BM_VERTS_OF_FACE) {
- fprintf(stderr, "%d ", BM_elem_index_get(v));
- }
- fprintf(stderr, "\n");
-
- fprintf(stderr, " e: ");
- BM_ITER_ELEM(e, &siter, f, BM_EDGES_OF_FACE) {
- fprintf(stderr, "%d ", BM_elem_index_get(e));
- }
- fprintf(stderr, "\n");
-
- fprintf(stderr, " l: ");
- BM_ITER_ELEM(l, &siter, f, BM_LOOPS_OF_FACE) {
- fprintf(stderr, "%d(v=%d, e=%d) ",
- BM_elem_index_get(l),
- BM_elem_index_get(l->v),
- BM_elem_index_get(l->e));
- }
- fprintf(stderr, "\n");
- }
-}
-
-void pbvh_bmesh_print(PBVH *bvh)
-{
- GHashIterator gh_iter;
GSetIterator gs_iter;
int n;
+ BMIter iter;
+ BMFace *f;
+ BMVert *v;
fprintf(stderr, "\npbvh=%p\n", bvh);
fprintf(stderr, "bm_face_to_node:\n");
- GHASH_ITER (gh_iter, bvh->bm_face_to_node) {
+
+ BM_ITER_MESH(f, &iter, bvh->bm, BM_FACES_OF_MESH) {
fprintf(stderr, " %d -> %d\n",
- BM_elem_index_get((BMFace *)BLI_ghashIterator_getKey(&gh_iter)),
- GET_INT_FROM_POINTER(BLI_ghashIterator_getValue(&gh_iter)));
+ BM_elem_index_get(v),
+ pbvh_bmesh_node_lookup_index(bvh, f));
}
fprintf(stderr, "bm_vert_to_node:\n");
- GHASH_ITER (gh_iter, bvh->bm_vert_to_node) {
+ BM_ITER_MESH(v, &iter, bvh->bm, BM_FACES_OF_MESH) {
fprintf(stderr, " %d -> %d\n",
- BM_elem_index_get((BMVert *)BLI_ghashIterator_getKey(&gh_iter)),
- GET_INT_FROM_POINTER(BLI_ghashIterator_getValue(&gh_iter)));
+ BM_elem_index_get(v),
+ pbvh_bmesh_node_lookup_index(bvh, v));
}
for (n = 0; n < bvh->totnode; n++) {
@@ -1488,9 +1963,9 @@ void pbvh_bmesh_print(PBVH *bvh)
continue;
fprintf(stderr, "node %d\n faces:\n", n);
- GHASH_ITER (gh_iter, node->bm_faces)
+ GSET_ITER (gs_iter, node->bm_faces)
fprintf(stderr, " %d\n",
- BM_elem_index_get((BMFace *)BLI_ghashIterator_getKey(&gh_iter)));
+ BM_elem_index_get((BMFace *)BLI_gsetIterator_getKey(&gs_iter)));
fprintf(stderr, " unique verts:\n");
GSET_ITER (gs_iter, node->bm_unique_verts)
fprintf(stderr, " %d\n",
@@ -1502,7 +1977,7 @@ void pbvh_bmesh_print(PBVH *bvh)
}
}
-void print_flag_factors(int flag)
+static void print_flag_factors(int flag)
{
int i;
printf("flag=0x%x:\n", flag);
@@ -1512,24 +1987,53 @@ void print_flag_factors(int flag)
}
}
}
+#endif
+
-void pbvh_bmesh_verify(PBVH *bvh)
+#ifdef USE_VERIFY
+
+static void pbvh_bmesh_verify(PBVH *bvh)
{
- GHashIterator gh_iter;
GSetIterator gs_iter;
- int i, vert_count = 0;
+ int i;
BMIter iter;
- BMVert *vi;
+ BMFace *f;
+ BMVert *v;
+
+ GSet *faces_all;
+ GSet *verts_all;
+
+
+ /* build list of faces & verts to lookup */
+ faces_all = BLI_gset_ptr_new_ex(__func__, bvh->bm->totface);
+ verts_all = BLI_gset_ptr_new_ex(__func__, bvh->bm->totvert);
+
+ BM_ITER_MESH(f, &iter, bvh->bm, BM_FACES_OF_MESH) {
+ BLI_gset_insert(faces_all, f);
+ }
+ BM_ITER_MESH(v, &iter, bvh->bm, BM_VERTS_OF_MESH) {
+ if (BM_ELEM_CD_GET_INT(v, bvh->cd_vert_node_offset) != DYNTOPO_NODE_NONE) {
+ BLI_gset_insert(verts_all, v);
+ }
+ }
- /* Check faces */
- BLI_assert(bvh->bm->totface == BLI_ghash_size(bvh->bm_face_to_node));
- GHASH_ITER (gh_iter, bvh->bm_face_to_node) {
+ /* Check vert/face counts */
+ {
+ int totface = 0, totvert = 0;
+ for (i = 0; i < bvh->totnode; i++) {
+ PBVHNode *n = &bvh->nodes[i];
+ totface += n->bm_faces ? BLI_gset_size(n->bm_faces) : 0;
+ totvert += n->bm_unique_verts ? BLI_gset_size(n->bm_unique_verts) : 0;
+ }
+
+ BLI_assert(totface == BLI_gset_size(faces_all));
+ BLI_assert(totvert == BLI_gset_size(verts_all));
+ }
+
+ BM_ITER_MESH(f, &iter, bvh->bm, BM_FACES_OF_MESH) {
BMIter bm_iter;
BMVert *v;
- BMFace *f = BLI_ghashIterator_getKey(&gh_iter);
- void *nip = BLI_ghashIterator_getValue(&gh_iter);
- int ni = GET_INT_FROM_POINTER(nip);
- PBVHNode *n = &bvh->nodes[ni];
+ PBVHNode *n = pbvh_bmesh_node_lookup(bvh, f);
/* Check that the face's node is a leaf */
BLI_assert(n->flag & PBVH_Leaf);
@@ -1546,7 +2050,7 @@ void pbvh_bmesh_verify(PBVH *bvh)
BLI_gset_haskey(n->bm_other_verts, v));
/* Check that the vertex has a node owner */
- nv = pbvh_bmesh_node_lookup(bvh, bvh->bm_vert_to_node, v);
+ nv = pbvh_bmesh_node_lookup(bvh, v);
/* Check that the vertex's node knows it owns the vert */
BLI_assert(BLI_gset_haskey(nv->bm_unique_verts, v));
@@ -1557,16 +2061,18 @@ void pbvh_bmesh_verify(PBVH *bvh)
}
/* Check verts */
- BLI_assert(bvh->bm->totvert == BLI_ghash_size(bvh->bm_vert_to_node));
- GHASH_ITER (gh_iter, bvh->bm_vert_to_node) {
+ BM_ITER_MESH(v, &iter, bvh->bm, BM_VERTS_OF_MESH) {
BMIter bm_iter;
- BMVert *v = BLI_ghashIterator_getKey(&gh_iter);
- BMFace *f;
- void *nip = BLI_ghashIterator_getValue(&gh_iter);
- int ni = GET_INT_FROM_POINTER(nip);
- PBVHNode *n = &bvh->nodes[ni];
+ PBVHNode *n;
bool found;
+ /* vertex isn't tracked */
+ if (BM_ELEM_CD_GET_INT(v, bvh->cd_vert_node_offset) == DYNTOPO_NODE_NONE) {
+ continue;
+ }
+
+ n = pbvh_bmesh_node_lookup(bvh, v);
+
/* Check that the vert's node is a leaf */
BLI_assert(n->flag & PBVH_Leaf);
@@ -1579,7 +2085,7 @@ void pbvh_bmesh_verify(PBVH *bvh)
/* Check that the vert's node also contains one of the vert's
* adjacent faces */
BM_ITER_ELEM (f, &bm_iter, v, BM_FACES_OF_VERT) {
- if (BLI_ghash_lookup(bvh->bm_face_to_node, f) == nip) {
+ if (pbvh_bmesh_node_lookup(bvh, f) == n) {
found = true;
break;
}
@@ -1590,9 +2096,10 @@ void pbvh_bmesh_verify(PBVH *bvh)
/* total freak stuff, check if node exists somewhere else */
/* Slow */
for (i = 0; i < bvh->totnode; i++) {
- PBVHNode *n = &bvh->nodes[i];
- if (i != ni && n->bm_unique_verts)
- BLI_assert(!BLI_gset_haskey(n->bm_unique_verts, v));
+ PBVHNode *n_other = &bvh->nodes[i];
+ if ((n != n_other) && (n_other->bm_unique_verts)) {
+ BLI_assert(!BLI_gset_haskey(n_other->bm_unique_verts, v));
+ }
}
#endif
@@ -1620,36 +2127,32 @@ void pbvh_bmesh_verify(PBVH *bvh)
for (i = 0; i < bvh->totnode; i++) {
PBVHNode *n = &bvh->nodes[i];
if (n->flag & PBVH_Leaf) {
- /* Check for duplicate entries */
- /* Slow */
-#if 0
- bli_gset_duplicate_key_check(n->bm_faces);
- bli_gset_duplicate_key_check(n->bm_unique_verts);
- bli_gset_duplicate_key_check(n->bm_other_verts);
-#endif
- GHASH_ITER (gh_iter, n->bm_faces) {
- BMFace *f = BLI_ghashIterator_getKey(&gh_iter);
- void *nip = BLI_ghash_lookup(bvh->bm_face_to_node, f);
- BLI_assert(BLI_ghash_haskey(bvh->bm_face_to_node, f));
- BLI_assert(GET_INT_FROM_POINTER(nip) == (n - bvh->nodes));
+ GSET_ITER (gs_iter, n->bm_faces) {
+ BMFace *f = BLI_gsetIterator_getKey(&gs_iter);
+ PBVHNode *n_other = pbvh_bmesh_node_lookup(bvh, f);
+ BLI_assert(n == n_other);
+ BLI_assert(BLI_gset_haskey(faces_all, f));
}
GSET_ITER (gs_iter, n->bm_unique_verts) {
BMVert *v = BLI_gsetIterator_getKey(&gs_iter);
- void *nip = BLI_ghash_lookup(bvh->bm_vert_to_node, v);
- BLI_assert(BLI_ghash_haskey(bvh->bm_vert_to_node, v));
+ PBVHNode *n_other = pbvh_bmesh_node_lookup(bvh, v);
BLI_assert(!BLI_gset_haskey(n->bm_other_verts, v));
- BLI_assert(GET_INT_FROM_POINTER(nip) == (n - bvh->nodes));
+ BLI_assert(n == n_other);
+ BLI_assert(BLI_gset_haskey(verts_all, v));
}
GSET_ITER (gs_iter, n->bm_other_verts) {
BMVert *v = BLI_gsetIterator_getKey(&gs_iter);
- BLI_assert(BLI_ghash_haskey(bvh->bm_vert_to_node, v));
- BLI_assert(BM_vert_face_count(v) > 0);
+ BLI_assert(!BM_vert_face_check(v));
+ BLI_assert(BLI_gset_haskey(verts_all, v));
}
}
}
+
+ BLI_gset_free(faces_all, NULL);
+ BLI_gset_free(verts_all, NULL);
}
#endif
diff --git a/source/blender/blenkernel/intern/pbvh_intern.h b/source/blender/blenkernel/intern/pbvh_intern.h
index 6b3ef8eb5da..bae323dedef 100644
--- a/source/blender/blenkernel/intern/pbvh_intern.h
+++ b/source/blender/blenkernel/intern/pbvh_intern.h
@@ -76,7 +76,7 @@ struct PBVHNode {
*
* Used for leaf nodes in a mesh-based PBVH (not multires.)
*/
- int *vert_indices;
+ const int *vert_indices;
unsigned int uniq_verts, face_verts;
/* An array mapping face corners into the vert_indices
@@ -88,7 +88,7 @@ struct PBVHNode {
*
* Used for leaf nodes in a mesh-based PBVH (not multires.)
*/
- int (*face_vert_indices)[4];
+ const int (*face_vert_indices)[4];
/* Indicates whether this node is a leaf or not; also used for
* marking various updates that need to be applied. */
@@ -133,13 +133,14 @@ struct PBVH {
/* Mesh data */
MVert *verts;
- MFace *faces;
+ const MPoly *mpoly;
+ const MLoop *mloop;
+ const MLoopTri *looptri;
CustomData *vdata;
/* Grid Data */
CCGKey gridkey;
CCGElem **grids;
- DMGridAdjacency *gridadj;
void **gridfaces;
const DMFlagMat *grid_flag_mats;
int totgrid;
@@ -175,9 +176,14 @@ void BB_expand_with_bb(BB *bb, BB *bb2);
void BBC_update_centroid(BBC *bbc);
int BB_widest_axis(const BB *bb);
void pbvh_grow_nodes(PBVH *bvh, int totnode);
-bool ray_face_intersection(const float ray_start[3], const float ray_normal[3],
- const float *t0, const float *t1, const float *t2,
- const float *t3, float *fdist);
+bool ray_face_intersection_quad(
+ const float ray_start[3], const float ray_normal[3],
+ const float *t0, const float *t1, const float *t2, const float *t3,
+ float *r_dist);
+bool ray_face_intersection_tri(
+ const float ray_start[3], const float ray_normal[3],
+ const float *t0, const float *t1, const float *t2,
+ float *r_dist);
void pbvh_update_BB_redraw(PBVH *bvh, PBVHNode **nodes, int totnode, int flag);
/* pbvh_bmesh.c */
diff --git a/source/blender/blenkernel/intern/pointcache.c b/source/blender/blenkernel/intern/pointcache.c
index 063a81e6efb..9054ecc7c3f 100644
--- a/source/blender/blenkernel/intern/pointcache.c
+++ b/source/blender/blenkernel/intern/pointcache.c
@@ -50,14 +50,14 @@
#include "BLI_threads.h"
#include "BLI_math.h"
#include "BLI_utildefines.h"
-#include "BLI_system.h"
-#include "BLF_translation.h"
+#include "BLT_translation.h"
#include "PIL_time.h"
#include "WM_api.h"
+#include "BKE_appdir.h"
#include "BKE_anim.h"
#include "BKE_blender.h"
#include "BKE_cloth.h"
@@ -84,12 +84,17 @@
#endif
#ifdef WITH_LZO
-#include "minilzo.h"
-#else
-/* used for non-lzo cases */
-#define LZO_OUT_LEN(size) ((size) + (size) / 16 + 64 + 3)
+# ifdef WITH_SYSTEM_LZO
+# include <lzo/lzo1x.h>
+# else
+# include "minilzo.h"
+# endif
+# define LZO_HEAP_ALLOC(var,size) \
+ lzo_align_t __LZO_MMODEL var [ ((size) + (sizeof(lzo_align_t) - 1)) / sizeof(lzo_align_t) ]
#endif
+#define LZO_OUT_LEN(size) ((size) + (size) / 16 + 64 + 3)
+
#ifdef WITH_LZMA
#include "LzmaLib.h"
#endif
@@ -538,7 +543,7 @@ static void ptcache_cloth_interpolate(int index, void *cloth_v, void **data, flo
static int ptcache_cloth_totpoint(void *cloth_v, int UNUSED(cfra))
{
ClothModifierData *clmd= cloth_v;
- return clmd->clothObject ? clmd->clothObject->numverts : 0;
+ return clmd->clothObject ? clmd->clothObject->mvert_num : 0;
}
static void ptcache_cloth_error(void *cloth_v, const char *message)
@@ -771,7 +776,7 @@ static int ptcache_smoke_read(PTCacheFile *pf, void *smoke_v)
/* version header */
ptcache_file_read(pf, version, 4, sizeof(char));
- if (strncmp(version, SMOKE_CACHE_VERSION, 4))
+ if (!STREQLEN(version, SMOKE_CACHE_VERSION, 4))
{
/* reset file pointer */
fseek(pf->fp, -4, SEEK_CUR);
@@ -953,7 +958,7 @@ static int ptcache_dynamicpaint_read(PTCacheFile *pf, void *dp_v)
/* version header */
ptcache_file_read(pf, version, 1, sizeof(char) * 4);
- if (strncmp(version, DPAINT_CACHE_VERSION, 4)) {
+ if (!STREQLEN(version, DPAINT_CACHE_VERSION, 4)) {
printf("Dynamic Paint: Invalid cache version: '%c%c%c%c'!\n", UNPACK4(version));
return 0;
}
@@ -1042,8 +1047,6 @@ static void ptcache_rigidbody_interpolate(int index, void *rb_v, void **data, fl
{
RigidBodyWorld *rbw = rb_v;
Object *ob = NULL;
- ParticleKey keys[4];
- float dfra;
if (rbw->objects)
ob = rbw->objects[index];
@@ -1052,6 +1055,11 @@ static void ptcache_rigidbody_interpolate(int index, void *rb_v, void **data, fl
RigidBodyOb *rbo = ob->rigidbody_object;
if (rbo->type == RBO_TYPE_ACTIVE) {
+ ParticleKey keys[4];
+ ParticleKey result;
+ float dfra;
+
+ memset(keys, 0, sizeof(keys));
copy_v3_v3(keys[1].co, rbo->pos);
copy_qt_qt(keys[1].rot, rbo->orn);
@@ -1061,16 +1069,17 @@ static void ptcache_rigidbody_interpolate(int index, void *rb_v, void **data, fl
memcpy(keys[2].rot, data + 3, 4 * sizeof(float));
}
else {
- BKE_ptcache_make_particle_key(keys+2, 0, data, cfra2);
+ BKE_ptcache_make_particle_key(&keys[2], 0, data, cfra2);
}
dfra = cfra2 - cfra1;
- psys_interpolate_particle(-1, keys, (cfra - cfra1) / dfra, keys, 1);
- interp_qt_qtqt(keys->rot, keys[1].rot, keys[2].rot, (cfra - cfra1) / dfra);
+ /* note: keys[0] and keys[3] unused for type < 1 (crappy) */
+ psys_interpolate_particle(-1, keys, (cfra - cfra1) / dfra, &result, true);
+ interp_qt_qtqt(result.rot, keys[1].rot, keys[2].rot, (cfra - cfra1) / dfra);
- copy_v3_v3(rbo->pos, keys->co);
- copy_qt_qt(rbo->orn, keys->rot);
+ copy_v3_v3(rbo->pos, result.co);
+ copy_qt_qt(rbo->orn, result.rot);
}
}
}
@@ -1464,7 +1473,7 @@ static int ptcache_path(PTCacheID *pid, char *filename)
/* use the temp path. this is weak but better then not using point cache at all */
/* temporary directory is assumed to exist and ALWAYS has a trailing slash */
- BLI_snprintf(filename, MAX_PTCACHE_PATH, "%s"PTCACHE_PATH, BLI_temp_dir_session());
+ BLI_snprintf(filename, MAX_PTCACHE_PATH, "%s"PTCACHE_PATH, BKE_tempdir_session());
return BLI_add_slash(filename); /* new strlen() */
}
@@ -1711,7 +1720,7 @@ static int ptcache_file_header_begin_read(PTCacheFile *pf)
if (fread(bphysics, sizeof(char), 8, pf->fp) != 8)
error = 1;
- if (!error && strncmp(bphysics, "BPHYSICS", 8))
+ if (!error && !STREQLEN(bphysics, "BPHYSICS", 8))
error = 1;
if (!error && !fread(&typeflag, sizeof(unsigned int), 1, pf->fp))
@@ -2442,7 +2451,7 @@ static int ptcache_write_needed(PTCacheID *pid, int cfra, int *overwrite)
PointCache *cache = pid->cache;
int ofra = 0, efra = cache->endframe;
- /* allways start from scratch on the first frame */
+ /* always start from scratch on the first frame */
if (cfra && cfra == cache->startframe) {
BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, cfra);
cache->flag &= ~PTCACHE_REDO_NEEDED;
@@ -2566,17 +2575,24 @@ void BKE_ptcache_id_clear(PTCacheID *pid, int mode, unsigned int cfra)
if (pid->cache->flag & PTCACHE_DISK_CACHE) {
ptcache_path(pid, path);
- len = ptcache_filename(pid, filename, cfra, 0, 0); /* no path */
-
dir = opendir(path);
if (dir==NULL)
return;
-
+
+ len = ptcache_filename(pid, filename, cfra, 0, 0); /* no path */
+ /* append underscore terminator to ensure we don't match similar names
+ * from objects whose names start with the same prefix
+ */
+ if (len < sizeof(filename) - 2) {
+ BLI_strncpy(filename + len, "_", sizeof(filename) - 2 - len);
+ len += 1;
+ }
+
BLI_snprintf(ext, sizeof(ext), "_%02u"PTCACHE_EXT, pid->stack_index);
while ((de = readdir(dir)) != NULL) {
if (strstr(de->d_name, ext)) { /* do we have the right extension?*/
- if (strncmp(filename, de->d_name, len ) == 0) { /* do we have the right prefix */
+ if (STREQLEN(filename, de->d_name, len)) { /* do we have the right prefix */
if (mode == PTCACHE_CLEAR_ALL) {
pid->cache->last_exact = MIN2(pid->cache->startframe, 0);
BLI_join_dirfile(path_full, sizeof(path_full), path, de->d_name);
@@ -2782,7 +2798,7 @@ void BKE_ptcache_id_time(PTCacheID *pid, Scene *scene, float cfra, int *startfra
while ((de = readdir(dir)) != NULL) {
if (strstr(de->d_name, ext)) { /* do we have the right extension?*/
- if (strncmp(filename, de->d_name, len ) == 0) { /* do we have the right prefix */
+ if (STREQLEN(filename, de->d_name, len)) { /* do we have the right prefix */
/* read the number of the file */
unsigned int frame, len2 = (int)strlen(de->d_name);
char num[7];
@@ -2963,7 +2979,7 @@ void BKE_ptcache_remove(void)
return;
while ((de = readdir(dir)) != NULL) {
- if ( strcmp(de->d_name, ".")==0 || strcmp(de->d_name, "..")==0) {
+ if (FILENAME_IS_CURRPAR(de->d_name)) {
/* do nothing */
}
else if (strstr(de->d_name, PTCACHE_EXT)) { /* do we have the right extension?*/
@@ -3077,7 +3093,7 @@ static PointCache *ptcache_copy(PointCache *cache, bool copy_data)
}
/* returns first point cache */
-PointCache *BKE_ptcache_copy_list(ListBase *ptcaches_new, ListBase *ptcaches_old, bool copy_data)
+PointCache *BKE_ptcache_copy_list(ListBase *ptcaches_new, const ListBase *ptcaches_old, bool copy_data)
{
PointCache *cache = ptcaches_old->first;
@@ -3338,7 +3354,7 @@ void BKE_ptcache_bake(PTCacheBaker *baker)
}
}
- BLI_end_threads(&threads);
+ BLI_end_threads(&threads);
}
/* clear baking flag */
if (pid) {
@@ -3520,7 +3536,7 @@ void BKE_ptcache_disk_cache_rename(PTCacheID *pid, const char *name_src, const c
while ((de = readdir(dir)) != NULL) {
if (strstr(de->d_name, ext)) { /* do we have the right extension?*/
- if (strncmp(old_filename, de->d_name, len ) == 0) { /* do we have the right prefix */
+ if (STREQLEN(old_filename, de->d_name, len)) { /* do we have the right prefix */
/* read the number of the file */
int frame, len2 = (int)strlen(de->d_name);
char num[7];
@@ -3575,7 +3591,7 @@ void BKE_ptcache_load_external(PTCacheID *pid)
while ((de = readdir(dir)) != NULL) {
if (strstr(de->d_name, ext)) { /* do we have the right extension?*/
- if (strncmp(filename, de->d_name, len ) == 0) { /* do we have the right prefix */
+ if (STREQLEN(filename, de->d_name, len)) { /* do we have the right prefix */
/* read the number of the file */
int frame, len2 = (int)strlen(de->d_name);
char num[7];
diff --git a/source/blender/blenkernel/intern/property.c b/source/blender/blenkernel/intern/property.c
index bb04d548a44..100df5fd121 100644
--- a/source/blender/blenkernel/intern/property.c
+++ b/source/blender/blenkernel/intern/property.c
@@ -131,60 +131,6 @@ bProperty *BKE_bproperty_new(int type)
return prop;
}
-/* used by BKE_bproperty_unique() only */
-static bProperty *bproperty_get(bProperty *first, bProperty *self, const char *name)
-{
- bProperty *p;
- for (p = first; p; p = p->next) {
- if (p != self && (strcmp(p->name, name) == 0))
- return p;
- }
- return NULL;
-}
-void BKE_bproperty_unique(bProperty *first, bProperty *prop, int force)
-{
- bProperty *p;
-
- /* set the first if its not set */
- if (first == NULL) {
- first = prop;
- while (first->prev) {
- first = first->prev;
- }
- }
-
- if (force) {
- /* change other names to make them unique */
- while ((p = bproperty_get(first, prop, prop->name))) {
- BKE_bproperty_unique(first, p, 0);
- }
- }
- else {
- /* change our own name until its unique */
- if (bproperty_get(first, prop, prop->name)) {
- /* there is a collision */
- char new_name[sizeof(prop->name)];
- char base_name[sizeof(prop->name)];
- char num[sizeof(prop->name)];
- int i = 0;
-
- /* strip numbers */
- BLI_strncpy(base_name, prop->name, sizeof(base_name));
- for (i = strlen(base_name) - 1; (i >= 0 && isdigit(base_name[i])); i--) {
- base_name[i] = '\0';
- }
- i = 0;
-
- do { /* ensure we have enough chars for the new number in the name */
- const size_t num_len = BLI_snprintf(num, sizeof(num), "%d", i++);
- BLI_snprintf(new_name, sizeof(prop->name),
- "%.*s%s", (int)(sizeof(prop->name) - num_len), base_name, num);
- } while (bproperty_get(first, prop, new_name));
-
- BLI_strncpy(prop->name, new_name, sizeof(prop->name));
- }
- }
-}
bProperty *BKE_bproperty_object_get(Object *ob, const char *name)
{
diff --git a/source/blender/blenkernel/intern/report.c b/source/blender/blenkernel/intern/report.c
index b2178fe69b3..3b371ce1e2f 100644
--- a/source/blender/blenkernel/intern/report.c
+++ b/source/blender/blenkernel/intern/report.c
@@ -38,7 +38,7 @@
#include "BLI_dynstr.h"
#include "BLI_utildefines.h"
-#include "BLF_translation.h"
+#include "BLT_translation.h"
#include "BKE_report.h"
#include "BKE_global.h" /* G.background only */
diff --git a/source/blender/blenkernel/intern/rigidbody.c b/source/blender/blenkernel/intern/rigidbody.c
index 3d61b0bdefb..476b9a22238 100644
--- a/source/blender/blenkernel/intern/rigidbody.c
+++ b/source/blender/blenkernel/intern/rigidbody.c
@@ -54,6 +54,7 @@
#include "DNA_scene_types.h"
#include "BKE_cdderivedmesh.h"
+#include "BKE_depsgraph.h"
#include "BKE_effect.h"
#include "BKE_global.h"
#include "BKE_library.h"
@@ -61,8 +62,7 @@
#include "BKE_object.h"
#include "BKE_pointcache.h"
#include "BKE_rigidbody.h"
-
-#include "RNA_access.h"
+#include "BKE_scene.h"
#ifdef WITH_BULLET
@@ -274,57 +274,55 @@ static rbCollisionShape *rigidbody_get_shape_trimesh_from_mesh(Object *ob)
if (ob->type == OB_MESH) {
DerivedMesh *dm = NULL;
MVert *mvert;
- MFace *mface;
+ const MLoopTri *looptri;
int totvert;
- int totface;
- int tottris = 0;
- int triangle_index = 0;
-
+ int tottri;
+ const MLoop *mloop;
+
dm = rigidbody_get_mesh(ob);
/* ensure mesh validity, then grab data */
if (dm == NULL)
return NULL;
- DM_ensure_tessface(dm);
+ DM_ensure_looptri(dm);
mvert = dm->getVertArray(dm);
totvert = dm->getNumVerts(dm);
- mface = dm->getTessFaceArray(dm);
- totface = dm->getNumTessFaces(dm);
+ looptri = dm->getLoopTriArray(dm);
+ tottri = dm->getNumLoopTri(dm);
+ mloop = dm->getLoopArray(dm);
/* sanity checking - potential case when no data will be present */
- if ((totvert == 0) || (totface == 0)) {
+ if ((totvert == 0) || (tottri == 0)) {
printf("WARNING: no geometry data converted for Mesh Collision Shape (ob = %s)\n", ob->id.name + 2);
}
else {
rbMeshData *mdata;
int i;
-
- /* count triangles */
- for (i = 0; i < totface; i++) {
- (mface[i].v4) ? (tottris += 2) : (tottris += 1);
- }
/* init mesh data for collision shape */
- mdata = RB_trimesh_data_new(tottris, totvert);
+ mdata = RB_trimesh_data_new(tottri, totvert);
RB_trimesh_add_vertices(mdata, (float *)mvert, totvert, sizeof(MVert));
/* loop over all faces, adding them as triangles to the collision shape
* (so for some faces, more than triangle will get added)
*/
- for (i = 0; (i < totface) && (mface) && (mvert); i++, mface++) {
- /* add first triangle - verts 1,2,3 */
- RB_trimesh_add_triangle_indices(mdata, triangle_index, mface->v1, mface->v2, mface->v3);
- triangle_index++;
-
- /* add second triangle if needed - verts 1,3,4 */
- if (mface->v4) {
- RB_trimesh_add_triangle_indices(mdata, triangle_index, mface->v1, mface->v3, mface->v4);
- triangle_index++;
+ if (mvert && looptri) {
+ for (i = 0; i < tottri; i++) {
+ /* add first triangle - verts 1,2,3 */
+ const MLoopTri *lt = &looptri[i];
+ int vtri[3];
+
+ vtri[0] = mloop[lt->tri[0]].v;
+ vtri[1] = mloop[lt->tri[1]].v;
+ vtri[2] = mloop[lt->tri[2]].v;
+
+ RB_trimesh_add_triangle_indices(mdata, i, UNPACK3(vtri));
}
}
+
RB_trimesh_finish(mdata);
/* construct collision shape
@@ -401,7 +399,7 @@ static void rigidbody_validate_sim_shape(Object *ob, bool rebuild)
height = size[2];
}
else if (rbo->shape == RB_SHAPE_SPHERE) {
- /* take radius to the the largest dimension to try and encompass everything */
+ /* take radius to the largest dimension to try and encompass everything */
radius = MAX3(size[0], size[1], size[2]);
}
@@ -440,6 +438,10 @@ static void rigidbody_validate_sim_shape(Object *ob, bool rebuild)
new_shape = rigidbody_get_shape_trimesh_from_mesh(ob);
break;
}
+ /* use box shape if we can't fall back to old shape */
+ if (new_shape == NULL && rbo->physics_shape == NULL) {
+ new_shape = RB_shape_new_box(size[0], size[1], size[2]);
+ }
/* assign new collision shape if creation was successful */
if (new_shape) {
if (rbo->physics_shape)
@@ -447,11 +449,6 @@ static void rigidbody_validate_sim_shape(Object *ob, bool rebuild)
rbo->physics_shape = new_shape;
RB_shape_set_margin(rbo->physics_shape, RBO_GET_MARGIN(rbo));
}
- /* use box shape if we can't fall back to old shape */
- else if (rbo->physics_shape == NULL) {
- rbo->shape = RB_SHAPE_BOX;
- rigidbody_validate_sim_shape(ob, true);
- }
}
/* --------------------- */
@@ -483,7 +480,7 @@ void BKE_rigidbody_calc_volume(Object *ob, float *r_vol)
height = size[2];
}
else if (rbo->shape == RB_SHAPE_SPHERE) {
- /* take radius to the the largest dimension to try and encompass everything */
+ /* take radius to the largest dimension to try and encompass everything */
radius = max_fff(size[0], size[1], size[2]) * 0.5f;
}
@@ -513,22 +510,24 @@ void BKE_rigidbody_calc_volume(Object *ob, float *r_vol)
if (ob->type == OB_MESH) {
DerivedMesh *dm = rigidbody_get_mesh(ob);
MVert *mvert;
- MFace *mface;
- int totvert, totface;
+ const MLoopTri *lt = NULL;
+ int totvert, tottri = 0;
+ const MLoop *mloop = NULL;
/* ensure mesh validity, then grab data */
if (dm == NULL)
return;
- DM_ensure_tessface(dm);
+ DM_ensure_looptri(dm);
mvert = dm->getVertArray(dm);
totvert = dm->getNumVerts(dm);
- mface = dm->getTessFaceArray(dm);
- totface = dm->getNumTessFaces(dm);
+ lt = dm->getLoopTriArray(dm);
+ tottri = dm->getNumLoopTri(dm);
+ mloop = dm->getLoopArray(dm);
- if (totvert > 0 && totface > 0) {
- BKE_mesh_calc_volume(mvert, totvert, mface, totface, &volume, NULL);
+ if (totvert > 0 && tottri > 0) {
+ BKE_mesh_calc_volume(mvert, totvert, lt, tottri, mloop, &volume, NULL);
}
/* cleanup temp data */
@@ -555,14 +554,14 @@ void BKE_rigidbody_calc_volume(Object *ob, float *r_vol)
if (r_vol) *r_vol = volume;
}
-void BKE_rigidbody_calc_center_of_mass(Object *ob, float r_com[3])
+void BKE_rigidbody_calc_center_of_mass(Object *ob, float r_center[3])
{
RigidBodyOb *rbo = ob->rigidbody_object;
float size[3] = {1.0f, 1.0f, 1.0f};
float height = 1.0f;
- zero_v3(r_com);
+ zero_v3(r_center);
/* if automatically determining dimensions, use the Object's boundbox
* - assume that all quadrics are standing upright on local z-axis
@@ -587,7 +586,7 @@ void BKE_rigidbody_calc_center_of_mass(Object *ob, float r_com[3])
/* cone is geometrically centered on the median,
* center of mass is 1/4 up from the base
*/
- r_com[2] = -0.25f * height;
+ r_center[2] = -0.25f * height;
break;
case RB_SHAPE_CONVEXH:
@@ -596,22 +595,24 @@ void BKE_rigidbody_calc_center_of_mass(Object *ob, float r_com[3])
if (ob->type == OB_MESH) {
DerivedMesh *dm = rigidbody_get_mesh(ob);
MVert *mvert;
- MFace *mface;
- int totvert, totface;
+ const MLoopTri *looptri;
+ int totvert, tottri;
+ const MLoop *mloop;
/* ensure mesh validity, then grab data */
if (dm == NULL)
return;
- DM_ensure_tessface(dm);
+ DM_ensure_looptri(dm);
mvert = dm->getVertArray(dm);
totvert = dm->getNumVerts(dm);
- mface = dm->getTessFaceArray(dm);
- totface = dm->getNumTessFaces(dm);
+ looptri = dm->getLoopTriArray(dm);
+ tottri = dm->getNumLoopTri(dm);
+ mloop = dm->getLoopArray(dm);
- if (totvert > 0 && totface > 0) {
- BKE_mesh_calc_volume(mvert, totvert, mface, totface, NULL, r_com);
+ if (totvert > 0 && tottri > 0) {
+ BKE_mesh_calc_volume(mvert, totvert, looptri, tottri, mloop, NULL, r_center);
}
/* cleanup temp data */
@@ -1158,7 +1159,7 @@ static void rigidbody_update_ob_array(RigidBodyWorld *rbw)
GroupObject *go;
int i, n;
- n = BLI_countlist(&rbw->group->gobject);
+ n = BLI_listbase_count(&rbw->group->gobject);
if (rbw->numbodies != n) {
rbw->numbodies = n;
@@ -1499,7 +1500,7 @@ void BKE_rigidbody_rebuild_world(Scene *scene, float ctime)
cache = rbw->pointcache;
/* flag cache as outdated if we don't have a world or number of objects in the simulation has changed */
- if (rbw->physics_world == NULL || rbw->numbodies != BLI_countlist(&rbw->group->gobject)) {
+ if (rbw->physics_world == NULL || rbw->numbodies != BLI_listbase_count(&rbw->group->gobject)) {
cache->flag |= PTCACHE_OUTDATED;
}
@@ -1592,7 +1593,7 @@ struct RigidBodyCon *BKE_rigidbody_copy_constraint(Object *ob) { return NULL; }
void BKE_rigidbody_relink_constraint(RigidBodyCon *rbc) {}
void BKE_rigidbody_validate_sim_world(Scene *scene, RigidBodyWorld *rbw, bool rebuild) {}
void BKE_rigidbody_calc_volume(Object *ob, float *r_vol) { if (r_vol) *r_vol = 0.0f; }
-void BKE_rigidbody_calc_center_of_mass(Object *ob, float r_com[3]) { zero_v3(r_com); }
+void BKE_rigidbody_calc_center_of_mass(Object *ob, float r_center[3]) { zero_v3(r_center); }
struct RigidBodyWorld *BKE_rigidbody_create_world(Scene *scene) { return NULL; }
struct RigidBodyWorld *BKE_rigidbody_world_copy(RigidBodyWorld *rbw) { return NULL; }
void BKE_rigidbody_world_groups_relink(struct RigidBodyWorld *rbw) {}
@@ -1613,3 +1614,51 @@ void BKE_rigidbody_do_simulation(Scene *scene, float ctime) {}
#endif
#endif /* WITH_BULLET */
+
+/* -------------------- */
+/* Depsgraph evaluation */
+
+void BKE_rigidbody_rebuild_sim(EvaluationContext *UNUSED(eval_ctx),
+ Scene *scene)
+{
+ float ctime = BKE_scene_frame_get(scene);
+
+ if (G.debug & G_DEBUG_DEPSGRAPH) {
+ printf("%s at %f\n", __func__, ctime);
+ }
+
+ /* rebuild sim data (i.e. after resetting to start of timeline) */
+ if (BKE_scene_check_rigidbody_active(scene)) {
+ BKE_rigidbody_rebuild_world(scene, ctime);
+ }
+}
+
+void BKE_rigidbody_eval_simulation(EvaluationContext *UNUSED(eval_ctx),
+ Scene *scene)
+{
+ float ctime = BKE_scene_frame_get(scene);
+
+ if (G.debug & G_DEBUG_DEPSGRAPH) {
+ printf("%s at %f\n", __func__, ctime);
+ }
+
+ /* evaluate rigidbody sim */
+ if (BKE_scene_check_rigidbody_active(scene)) {
+ BKE_rigidbody_do_simulation(scene, ctime);
+ }
+}
+
+void BKE_rigidbody_object_sync_transforms(EvaluationContext *UNUSED(eval_ctx),
+ Scene *scene,
+ Object *ob)
+{
+ RigidBodyWorld *rbw = scene->rigidbody_world;
+ float ctime = BKE_scene_frame_get(scene);
+
+ if (G.debug & G_DEBUG_DEPSGRAPH) {
+ printf("%s on %s\n", __func__, ob->id.name);
+ }
+
+ /* read values pushed into RBO from sim/cache... */
+ BKE_rigidbody_sync_transforms(rbw, ob, ctime);
+}
diff --git a/source/blender/blenkernel/intern/sca.c b/source/blender/blenkernel/intern/sca.c
index 4be75344133..c902659c039 100644
--- a/source/blender/blenkernel/intern/sca.c
+++ b/source/blender/blenkernel/intern/sca.c
@@ -323,15 +323,23 @@ void unlink_actuators(ListBase *lb)
void free_actuator(bActuator *act)
{
- bSoundActuator *sa;
-
if (act->data) {
switch (act->type) {
- case ACT_SOUND:
- sa = (bSoundActuator *) act->data;
- if (sa->sound)
- id_us_min((ID *) sa->sound);
- break;
+ case ACT_ACTION:
+ case ACT_SHAPEACTION:
+ {
+ bActionActuator *aa = (bActionActuator *)act->data;
+ if (aa->act)
+ id_us_min((ID *)aa->act);
+ break;
+ }
+ case ACT_SOUND:
+ {
+ bSoundActuator *sa = (bSoundActuator *) act->data;
+ if (sa->sound)
+ id_us_min((ID *)sa->sound);
+ break;
+ }
}
MEM_freeN(act->data);
@@ -351,7 +359,6 @@ void free_actuators(ListBase *lb)
bActuator *copy_actuator(bActuator *act)
{
bActuator *actn;
- bSoundActuator *sa;
act->mynew=actn= MEM_dupallocN(act);
actn->flag |= ACT_NEW;
@@ -360,11 +367,21 @@ bActuator *copy_actuator(bActuator *act)
}
switch (act->type) {
+ case ACT_ACTION:
+ case ACT_SHAPEACTION:
+ {
+ bActionActuator *aa = (bActionActuator *)act->data;
+ if (aa->act)
+ id_us_plus((ID *)aa->act);
+ break;
+ }
case ACT_SOUND:
- sa= (bSoundActuator *)act->data;
+ {
+ bSoundActuator *sa = (bSoundActuator *)act->data;
if (sa->sound)
- id_us_plus((ID *) sa->sound);
+ id_us_plus((ID *)sa->sound);
break;
+ }
}
return actn;
}
@@ -479,7 +496,7 @@ void init_actuator(bActuator *act)
sta->turnspeed = 120.f;
sta->dist = 1.f;
sta->velocity= 3.f;
- sta->flag = ACT_STEERING_AUTOMATICFACING;
+ sta->flag = ACT_STEERING_AUTOMATICFACING | ACT_STEERING_LOCKZVEL;
sta->facingaxis = 1;
break;
case ACT_MOUSE:
diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c
index b6fc44ec016..1ccc213006a 100644
--- a/source/blender/blenkernel/intern/scene.c
+++ b/source/blender/blenkernel/intern/scene.c
@@ -58,21 +58,25 @@
#include "BLI_threads.h"
#include "BLI_task.h"
-#include "BLF_translation.h"
+#include "BLT_translation.h"
#include "BKE_anim.h"
#include "BKE_animsys.h"
#include "BKE_action.h"
+#include "BKE_armature.h"
#include "BKE_colortools.h"
#include "BKE_depsgraph.h"
#include "BKE_editmesh.h"
#include "BKE_fcurve.h"
#include "BKE_freestyle.h"
#include "BKE_global.h"
+#include "BKE_gpencil.h"
#include "BKE_group.h"
+#include "BKE_icons.h"
#include "BKE_idprop.h"
#include "BKE_image.h"
#include "BKE_library.h"
+#include "BKE_linestyle.h"
#include "BKE_main.h"
#include "BKE_mask.h"
#include "BKE_node.h"
@@ -80,27 +84,37 @@
#include "BKE_paint.h"
#include "BKE_rigidbody.h"
#include "BKE_scene.h"
+#include "BKE_screen.h"
#include "BKE_sequencer.h"
#include "BKE_sound.h"
#include "BKE_unit.h"
#include "BKE_world.h"
+#ifdef WITH_OPENSUBDIV
+# include "BKE_modifier.h"
+# include "CCGSubSurf.h"
+#endif
+
+#include "DEG_depsgraph.h"
+
#include "RE_engine.h"
#include "PIL_time.h"
#include "IMB_colormanagement.h"
+#include "IMB_imbuf.h"
#include "bmesh.h"
-//XXX #include "BIF_previewrender.h"
-//XXX #include "BIF_editseq.h"
-
#ifdef WIN32
#else
# include <sys/time.h>
#endif
+const char *RE_engine_id_BLENDER_RENDER = "BLENDER_RENDER";
+const char *RE_engine_id_BLENDER_GAME = "BLENDER_GAME";
+const char *RE_engine_id_CYCLES = "CYCLES";
+
void free_avicodecdata(AviCodecData *acd)
{
if (acd) {
@@ -150,18 +164,21 @@ Scene *BKE_scene_copy(Scene *sce, int type)
{
Scene *scen;
SceneRenderLayer *srl, *new_srl;
+ FreestyleLineSet *lineset;
ToolSettings *ts;
Base *base, *obase;
if (type == SCE_COPY_EMPTY) {
- ListBase lb;
+ ListBase rl, rv;
/* XXX. main should become an arg */
scen = BKE_scene_add(G.main, sce->id.name + 2);
- lb = scen->r.layers;
+ rl = scen->r.layers;
+ rv = scen->r.views;
scen->r = sce->r;
- scen->r.layers = lb;
+ scen->r.layers = rl;
scen->r.actlay = 0;
+ scen->r.views = rv;
scen->unit = sce->unit;
scen->physics_settings = sce->physics_settings;
scen->gm = sce->gm;
@@ -184,6 +201,7 @@ Scene *BKE_scene_copy(Scene *sce, int type)
scen->ed = NULL;
scen->theDag = NULL;
+ scen->depsgraph = NULL;
scen->obedit = NULL;
scen->stats = NULL;
scen->fps_info = NULL;
@@ -194,6 +212,7 @@ Scene *BKE_scene_copy(Scene *sce, int type)
BLI_duplicatelist(&(scen->markers), &(sce->markers));
BLI_duplicatelist(&(scen->transform_spaces), &(sce->transform_spaces));
BLI_duplicatelist(&(scen->r.layers), &(sce->r.layers));
+ BLI_duplicatelist(&(scen->r.views), &(sce->r.views));
BKE_keyingsets_copy(&(scen->keyingsets), &(sce->keyingsets));
if (sce->nodetree) {
@@ -221,7 +240,7 @@ Scene *BKE_scene_copy(Scene *sce, int type)
sizeof(scen->sequencer_colorspace_settings.name));
/* copy action and remove animation used by sequencer */
- BKE_copy_animdata_id_action(&scen->id);
+ BKE_animdata_copy_id_action(&scen->id);
if (type != SCE_COPY_FULL)
remove_sequencer_fcurves(scen);
@@ -230,6 +249,14 @@ Scene *BKE_scene_copy(Scene *sce, int type)
new_srl = scen->r.layers.first;
for (srl = sce->r.layers.first; srl; srl = srl->next) {
BKE_freestyle_config_copy(&new_srl->freestyleConfig, &srl->freestyleConfig);
+ if (type == SCE_COPY_FULL) {
+ for (lineset = new_srl->freestyleConfig.linesets.first; lineset; lineset = lineset->next) {
+ if (lineset->linestyle) {
+ id_us_plus((ID *)lineset->linestyle);
+ lineset->linestyle = BKE_linestyle_copy(G.main, lineset->linestyle);
+ }
+ }
+ }
new_srl = new_srl->next;
}
}
@@ -290,14 +317,14 @@ Scene *BKE_scene_copy(Scene *sce, int type)
}
/* before scene copy */
- sound_create_scene(scen);
+ BKE_sound_create_scene(scen);
/* world */
if (type == SCE_COPY_FULL) {
if (scen->world) {
id_us_plus((ID *)scen->world);
scen->world = BKE_world_copy(scen->world);
- BKE_copy_animdata_id_action((ID *)scen->world);
+ BKE_animdata_copy_id_action((ID *)scen->world);
}
if (sce->ed) {
@@ -306,6 +333,23 @@ Scene *BKE_scene_copy(Scene *sce, int type)
BKE_sequence_base_dupli_recursive(sce, scen, &scen->ed->seqbase, &sce->ed->seqbase, SEQ_DUPE_ALL);
}
}
+
+ /* grease pencil */
+ if (scen->gpd) {
+ if (type == SCE_COPY_FULL) {
+ scen->gpd = gpencil_data_duplicate(scen->gpd, false);
+ }
+ else if (type == SCE_COPY_EMPTY) {
+ scen->gpd = NULL;
+ }
+ else {
+ id_us_plus((ID *)scen->gpd);
+ }
+ }
+
+ if (sce->preview) {
+ scen->preview = BKE_previewimg_copy(sce->preview);
+ }
return scen;
}
@@ -345,7 +389,7 @@ void BKE_scene_free(Scene *sce)
BLI_freelistN(&sce->base);
BKE_sequencer_editing_free(sce);
- BKE_free_animdata((ID *)sce);
+ BKE_animdata_free((ID *)sce);
BKE_keyingsets_free(&sce->keyingsets);
if (sce->rigidbody_world)
@@ -374,6 +418,7 @@ void BKE_scene_free(Scene *sce)
BLI_freelistN(&sce->markers);
BLI_freelistN(&sce->transform_spaces);
BLI_freelistN(&sce->r.layers);
+ BLI_freelistN(&sce->r.views);
if (sce->toolsettings) {
if (sce->toolsettings->vpaint) {
@@ -399,6 +444,8 @@ void BKE_scene_free(Scene *sce)
}
DAG_scene_free(sce);
+ if (sce->depsgraph)
+ DEG_graph_free(sce->depsgraph);
if (sce->nodetree) {
ntreeFreeTree(sce->nodetree);
@@ -410,9 +457,11 @@ void BKE_scene_free(Scene *sce)
if (sce->fps_info)
MEM_freeN(sce->fps_info);
- sound_destroy_scene(sce);
+ BKE_sound_destroy_scene(sce);
BKE_color_managed_view_settings_free(&sce->view_settings);
+
+ BKE_previewimg_free(&sce->preview);
}
Scene *BKE_scene_add(Main *bmain, const char *name)
@@ -421,6 +470,7 @@ Scene *BKE_scene_add(Main *bmain, const char *name)
ParticleEditSettings *pset;
int a;
const char *colorspace_name;
+ SceneRenderView *srv;
sce = BKE_libblock_alloc(bmain, ID_SCE, name);
sce->lay = sce->layact = 1;
@@ -526,6 +576,7 @@ Scene *BKE_scene_add(Main *bmain, const char *name)
sce->toolsettings = MEM_callocN(sizeof(struct ToolSettings), "Tool Settings Struct");
sce->toolsettings->doublimit = 0.001;
+ sce->toolsettings->vgroup_weight = 1.0f;
sce->toolsettings->uvcalc_margin = 0.001f;
sce->toolsettings->unwrapper = 1;
sce->toolsettings->select_thresh = 0.01f;
@@ -598,7 +649,7 @@ Scene *BKE_scene_add(Main *bmain, const char *name)
sce->r.ffcodecdata.audio_bitrate = 192;
sce->r.ffcodecdata.audio_channels = 2;
- BLI_strncpy(sce->r.engine, "BLENDER_RENDER", sizeof(sce->r.engine));
+ BLI_strncpy(sce->r.engine, RE_engine_id_BLENDER_RENDER, sizeof(sce->r.engine));
sce->audio.distance_model = 2.0f;
sce->audio.doppler_factor = 1.0f;
@@ -612,7 +663,16 @@ Scene *BKE_scene_add(Main *bmain, const char *name)
/* note; in header_info.c the scene copy happens..., if you add more to renderdata it has to be checked there */
BKE_scene_add_render_layer(sce, NULL);
-
+
+ /* multiview - stereo */
+ BKE_scene_add_render_view(sce, STEREO_LEFT_NAME);
+ srv = sce->r.views.first;
+ BLI_strncpy(srv->suffix, STEREO_LEFT_SUFFIX, sizeof(srv->suffix));
+
+ BKE_scene_add_render_view(sce, STEREO_RIGHT_NAME);
+ srv = sce->r.views.last;
+ BLI_strncpy(srv->suffix, STEREO_RIGHT_SUFFIX, sizeof(srv->suffix));
+
/* game data */
sce->gm.stereoflag = STEREO_NOSTEREO;
sce->gm.stereomode = STEREO_ANAGLYPH;
@@ -649,7 +709,7 @@ Scene *BKE_scene_add(Main *bmain, const char *name)
sce->gm.recastData.cellsize = 0.3f;
sce->gm.recastData.cellheight = 0.2f;
- sce->gm.recastData.agentmaxslope = M_PI / 2;
+ sce->gm.recastData.agentmaxslope = M_PI_4;
sce->gm.recastData.agentmaxclimb = 0.9f;
sce->gm.recastData.agentheight = 2.0f;
sce->gm.recastData.agentradius = 0.6f;
@@ -661,9 +721,12 @@ Scene *BKE_scene_add(Main *bmain, const char *name)
sce->gm.recastData.detailsampledist = 6.0f;
sce->gm.recastData.detailsamplemaxerror = 1.0f;
+ sce->gm.lodflag = SCE_LOD_USE_HYST;
+ sce->gm.scehysteresis = 10;
+
sce->gm.exitkey = 218; // Blender key code for ESC
- sound_create_scene(sce);
+ BKE_sound_create_scene(sce);
/* color management */
colorspace_name = IMB_colormanagement_role_colorspace_name_get(COLOR_ROLE_DEFAULT_SEQUENCER);
@@ -673,14 +736,40 @@ Scene *BKE_scene_add(Main *bmain, const char *name)
BLI_strncpy(sce->sequencer_colorspace_settings.name, colorspace_name,
sizeof(sce->sequencer_colorspace_settings.name));
+ /* Safe Areas */
+ copy_v2_fl2(sce->safe_areas.title, 3.5f / 100.0f, 3.5f / 100.0f);
+ copy_v2_fl2(sce->safe_areas.action, 10.0f / 100.0f, 5.0f / 100.0f);
+ copy_v2_fl2(sce->safe_areas.title_center, 17.5f / 100.0f, 5.0f / 100.0f);
+ copy_v2_fl2(sce->safe_areas.action_center, 15.0f / 100.0f, 5.0f / 100.0f);
+
+ sce->preview = NULL;
+
return sce;
}
+Base *BKE_scene_base_find_by_name(struct Scene *scene, const char *name)
+{
+ Base *base;
+
+ for (base = scene->base.first; base; base = base->next) {
+ if (STREQ(base->object->id.name + 2, name)) {
+ break;
+ }
+ }
+
+ return base;
+}
+
Base *BKE_scene_base_find(Scene *scene, Object *ob)
{
return BLI_findptr(&scene->base, ob, offsetof(Base, object));
}
+/**
+ * Sets the active scene, mainly used when running in background mode (``--scene`` command line argument).
+ * This is also called to set the scene directly, bypassing windowing code.
+ * Otherwise #ED_screen_set_scene is used when changing scenes by the user.
+ */
void BKE_scene_set_background(Main *bmain, Scene *scene)
{
Scene *sce;
@@ -745,33 +834,6 @@ Scene *BKE_scene_set_name(Main *bmain, const char *name)
return NULL;
}
-static void scene_unlink_space_node(SpaceNode *snode, Scene *sce)
-{
- if (snode->id == &sce->id) {
- /* nasty DNA logic for SpaceNode:
- * ideally should be handled by editor code, but would be bad level call
- */
- bNodeTreePath *path, *path_next;
- for (path = snode->treepath.first; path; path = path_next) {
- path_next = path->next;
- MEM_freeN(path);
- }
- BLI_listbase_clear(&snode->treepath);
-
- snode->id = NULL;
- snode->from = NULL;
- snode->nodetree = NULL;
- snode->edittree = NULL;
- }
-}
-
-static void scene_unlink_space_buts(SpaceButs *sbuts, Scene *sce)
-{
- if (sbuts->pinid == &sce->id) {
- sbuts->pinid = NULL;
- }
-}
-
void BKE_scene_unlink(Main *bmain, Scene *sce, Scene *newsce)
{
Scene *sce1;
@@ -796,24 +858,11 @@ void BKE_scene_unlink(Main *bmain, Scene *sce, Scene *newsce)
/* all screens */
for (screen = bmain->screen.first; screen; screen = screen->id.next) {
- ScrArea *area;
-
- if (screen->scene == sce)
+ if (screen->scene == sce) {
screen->scene = newsce;
-
- for (area = screen->areabase.first; area; area = area->next) {
- SpaceLink *space_link;
- for (space_link = area->spacedata.first; space_link; space_link = space_link->next) {
- switch (space_link->spacetype) {
- case SPACE_NODE:
- scene_unlink_space_node((SpaceNode *)space_link, sce);
- break;
- case SPACE_BUTS:
- scene_unlink_space_buts((SpaceButs *)space_link, sce);
- break;
- }
- }
}
+
+ /* editors are handled by WM_main_remove_editor_id_reference */
}
BKE_libblock_free(bmain, sce);
@@ -1095,39 +1144,36 @@ void BKE_scene_base_select(Scene *sce, Base *selbase)
}
/* checks for cycle, returns 1 if it's all OK */
-int BKE_scene_validate_setscene(Main *bmain, Scene *sce)
+bool BKE_scene_validate_setscene(Main *bmain, Scene *sce)
{
- Scene *scene;
+ Scene *sce_iter;
int a, totscene;
+
+ if (sce->set == NULL) return true;
+ totscene = BLI_listbase_count(&bmain->scene);
- if (sce->set == NULL) return 1;
-
- totscene = 0;
- for (scene = bmain->scene.first; scene; scene = scene->id.next)
- totscene++;
-
- for (a = 0, scene = sce; scene->set; scene = scene->set, a++) {
+ for (a = 0, sce_iter = sce; sce_iter->set; sce_iter = sce_iter->set, a++) {
/* more iterations than scenes means we have a cycle */
if (a > totscene) {
/* the tested scene gets zero'ed, that's typically current scene */
sce->set = NULL;
- return 0;
+ return false;
}
}
- return 1;
+ return true;
}
/* This function is needed to cope with fractional frames - including two Blender rendering features
* mblur (motion blur that renders 'subframes' and blurs them together), and fields rendering.
*/
-float BKE_scene_frame_get(Scene *scene)
+float BKE_scene_frame_get(const Scene *scene)
{
return BKE_scene_frame_get_from_ctime(scene, scene->r.cfra);
}
/* This function is used to obtain arbitrary fractional frames */
-float BKE_scene_frame_get_from_ctime(Scene *scene, const float frame)
+float BKE_scene_frame_get_from_ctime(const Scene *scene, const float frame)
{
float ctime = frame;
ctime += scene->r.subframe;
@@ -1146,6 +1192,7 @@ void BKE_scene_frame_set(struct Scene *scene, double cfra)
scene->r.cfra = (int)intpart;
}
+#ifdef WITH_LEGACY_DEPSGRAPH
/* drivers support/hacks
* - this method is called from scene_update_tagged_recursive(), so gets included in viewport + render
* - these are always run since the depsgraph can't handle non-object data
@@ -1245,9 +1292,38 @@ static void scene_depsgraph_hack(EvaluationContext *eval_ctx, Scene *scene, Scen
}
}
}
+}
+#endif /* WITH_LEGACY_DEPSGRAPH */
+/* That's like really a bummer, because currently animation data for armatures
+ * might want to use pose, and pose might be missing on the object.
+ * This happens when changing visible layers, which leads to situations when
+ * pose is missing or marked for recalc, animation will change it and then
+ * object update will restore the pose.
+ *
+ * This could be solved by the new dependency graph, but for until then we'll
+ * do an extra pass on the objects to ensure it's all fine.
+ */
+#define POSE_ANIMATION_WORKAROUND
+
+#ifdef POSE_ANIMATION_WORKAROUND
+static void scene_armature_depsgraph_workaround(Main *bmain)
+{
+ Object *ob;
+ if (BLI_listbase_is_empty(&bmain->armature) || !DAG_id_type_tagged(bmain, ID_OB)) {
+ return;
+ }
+ for (ob = bmain->object.first; ob; ob = ob->id.next) {
+ if (ob->type == OB_ARMATURE && ob->adt && ob->adt->recalc & ADT_RECALC_ANIM) {
+ if (ob->pose == NULL || (ob->pose->flag & POSE_RECALC)) {
+ BKE_pose_rebuild(ob, ob->data);
+ }
+ }
+ }
}
+#endif
+#ifdef WITH_LEGACY_DEPSGRAPH
static void scene_rebuild_rbw_recursive(Scene *scene, float ctime)
{
if (scene->set)
@@ -1265,12 +1341,18 @@ static void scene_do_rb_simulation_recursive(Scene *scene, float ctime)
if (BKE_scene_check_rigidbody_active(scene))
BKE_rigidbody_do_simulation(scene, ctime);
}
+#endif
/* Used to visualize CPU threads activity during threaded object update,
* would pollute STDERR with whole bunch of timing information which then
* could be parsed and nicely visualized.
*/
-#undef DETAILED_ANALYSIS_OUTPUT
+#ifdef WITH_LEGACY_DEPSGRAPH
+# undef DETAILED_ANALYSIS_OUTPUT
+#else
+/* ALWAYS KEEY DISABLED! */
+# undef DETAILED_ANALYSIS_OUTPUT
+#endif
/* Mballs evaluation uses BKE_scene_base_iter_next which calls
* duplilist for all objects in the scene. This leads to conflict
@@ -1278,10 +1360,16 @@ static void scene_do_rb_simulation_recursive(Scene *scene, float ctime)
*
* Ideally Mballs shouldn't do such an iteration and use DAG
* queries instead. For the time being we've got new DAG
- * let's keep it simple and update mballs in a ingle thread.
+ * let's keep it simple and update mballs in a single thread.
*/
#define MBALL_SINGLETHREAD_HACK
+/* Need this because CCFDM holds some OpenGL resources. */
+#ifdef WITH_OPENSUBDIV
+# define OPENSUBDIV_GL_WORKAROUND
+#endif
+
+#ifdef WITH_LEGACY_DEPSGRAPH
typedef struct StatisicsEntry {
struct StatisicsEntry *next, *prev;
Object *object;
@@ -1296,13 +1384,13 @@ typedef struct ThreadedObjectUpdateState {
Scene *scene_parent;
double base_time;
- /* Execution statistics */
- ListBase statistics[BLENDER_MAX_THREADS];
- bool has_updated_objects;
-
#ifdef MBALL_SINGLETHREAD_HACK
bool has_mballs;
#endif
+
+ /* Execution statistics */
+ bool has_updated_objects;
+ ListBase *statistics;
} ThreadedObjectUpdateState;
static void scene_update_object_add_task(void *node, void *user_data);
@@ -1371,6 +1459,8 @@ static void scene_update_object_func(TaskPool *pool, void *taskdata, int threadi
if (add_to_stats) {
StatisicsEntry *entry;
+ BLI_assert(threadid < BLI_pool_get_num_threads(pool));
+
entry = MEM_mallocN(sizeof(StatisicsEntry), "update thread statistics");
entry->object = object;
entry->start_time = start_time;
@@ -1400,6 +1490,7 @@ static void scene_update_object_add_task(void *node, void *user_data)
static void print_threads_statistics(ThreadedObjectUpdateState *state)
{
int i, tot_thread;
+ double finish_time;
if ((G.debug & G_DEBUG_DEPSGRAPH) == 0) {
return;
@@ -1425,6 +1516,7 @@ static void print_threads_statistics(ThreadedObjectUpdateState *state)
}
}
#else
+ finish_time = PIL_check_seconds_timer();
tot_thread = BLI_system_thread_count();
for (i = 0; i < tot_thread; i++) {
@@ -1454,6 +1546,9 @@ static void print_threads_statistics(ThreadedObjectUpdateState *state)
BLI_freelistN(&state->statistics[i]);
}
+ if (state->has_updated_objects) {
+ printf("Scene update in %f sec\n", finish_time - state->base_time);
+ }
#endif
}
@@ -1475,6 +1570,47 @@ static bool scene_need_update_objects(Main *bmain)
DAG_id_type_tagged(bmain, ID_AR); /* Armature */
}
+#ifdef OPENSUBDIV_GL_WORKAROUND
+/* CCG DrivedMesh currently hold some OpenGL handles, which could only be
+ * released from the main thread.
+ *
+ * Ideally we need to use gpu_buffer_free, but it's a bit tricky because
+ * some buffers are only accessible from OpenSubdiv side.
+ */
+static void scene_free_unused_opensubdiv_cache(Scene *scene)
+{
+ Base *base;
+ for (base = scene->base.first; base; base = base->next) {
+ Object *object = base->object;
+ if (object->type == OB_MESH && object->recalc & OB_RECALC_DATA) {
+ ModifierData *md = object->modifiers.last;
+ if (md != NULL && md->type == eModifierType_Subsurf) {
+ SubsurfModifierData *smd = (SubsurfModifierData *) md;
+ bool object_in_editmode = object->mode == OB_MODE_EDIT;
+ if (!smd->use_opensubdiv ||
+ DAG_get_eval_flags_for_object(scene, object) & DAG_EVAL_NEED_CPU)
+ {
+ if (smd->mCache != NULL) {
+ ccgSubSurf_free_osd_mesh(smd->mCache);
+ }
+ if (smd->emCache != NULL) {
+ ccgSubSurf_free_osd_mesh(smd->emCache);
+ }
+ }
+ if (object_in_editmode && smd->mCache != NULL) {
+ ccgSubSurf_free(smd->mCache);
+ smd->mCache = NULL;
+ }
+ if (!object_in_editmode && smd->emCache != NULL) {
+ ccgSubSurf_free(smd->emCache);
+ smd->emCache = NULL;
+ }
+ }
+ }
+ }
+}
+#endif
+
static void scene_update_objects(EvaluationContext *eval_ctx, Main *bmain, Scene *scene, Scene *scene_parent)
{
TaskScheduler *task_scheduler = BLI_task_scheduler_get();
@@ -1493,13 +1629,19 @@ static void scene_update_objects(EvaluationContext *eval_ctx, Main *bmain, Scene
return;
}
+#ifdef OPENSUBDIV_GL_WORKAROUND
+ scene_free_unused_opensubdiv_cache(scene);
+#endif
+
state.eval_ctx = eval_ctx;
state.scene = scene;
state.scene_parent = scene_parent;
/* Those are only needed when blender is run with --debug argument. */
if (G.debug & G_DEBUG_DEPSGRAPH) {
- memset(state.statistics, 0, sizeof(state.statistics));
+ const int tot_thread = BLI_task_scheduler_num_threads(task_scheduler);
+ state.statistics = MEM_callocN(tot_thread * sizeof(*state.statistics),
+ "scene update objects stats");
state.has_updated_objects = false;
state.base_time = PIL_check_seconds_timer();
}
@@ -1509,6 +1651,9 @@ static void scene_update_objects(EvaluationContext *eval_ctx, Main *bmain, Scene
#endif
task_pool = BLI_task_pool_create(task_scheduler, &state);
+ if (G.debug & G_DEBUG_DEPSGRAPH_NO_THREADS) {
+ BLI_pool_set_num_threads(task_pool, 1);
+ }
DAG_threaded_update_begin(scene, scene_update_object_add_task, task_pool);
BLI_task_pool_work_and_wait(task_pool);
@@ -1516,6 +1661,7 @@ static void scene_update_objects(EvaluationContext *eval_ctx, Main *bmain, Scene
if (G.debug & G_DEBUG_DEPSGRAPH) {
print_threads_statistics(&state);
+ MEM_freeN(state.statistics);
}
/* We do single thread pass to update all the objects which are in cyclic dependency.
@@ -1561,6 +1707,7 @@ static void scene_update_tagged_recursive(EvaluationContext *eval_ctx, Main *bma
BKE_mask_update_scene(bmain, scene);
}
+#endif /* WITH_LEGACY_DEPSGRAPH */
static bool check_rendered_viewport_visible(Main *bmain)
{
@@ -1596,9 +1743,9 @@ static void prepare_mesh_for_viewport_render(Main *bmain, Scene *scene)
Object *obedit = scene->obedit;
if (obedit) {
Mesh *mesh = obedit->data;
- /* TODO(sergey): Check object recalc flags as well? */
if ((obedit->type == OB_MESH) &&
- (mesh->id.flag & (LIB_ID_RECALC | LIB_ID_RECALC_DATA)))
+ ((obedit->id.flag & LIB_ID_RECALC_ALL) ||
+ (mesh->id.flag & LIB_ID_RECALC_ALL)))
{
if (check_rendered_viewport_visible(bmain)) {
BMesh *bm = mesh->edit_btmesh->bm;
@@ -1612,13 +1759,26 @@ static void prepare_mesh_for_viewport_render(Main *bmain, Scene *scene)
void BKE_scene_update_tagged(EvaluationContext *eval_ctx, Main *bmain, Scene *scene)
{
Scene *sce_iter;
-
+#ifdef WITH_LEGACY_DEPSGRAPH
+ bool use_new_eval = !DEG_depsgraph_use_legacy();
+#endif
+
/* keep this first */
BLI_callback_exec(bmain, &scene->id, BLI_CB_EVT_SCENE_UPDATE_PRE);
/* (re-)build dependency graph if needed */
- for (sce_iter = scene; sce_iter; sce_iter = sce_iter->set)
+ for (sce_iter = scene; sce_iter; sce_iter = sce_iter->set) {
DAG_scene_relations_update(bmain, sce_iter);
+ /* Uncomment this to check if graph was properly tagged for update. */
+#if 0
+#ifdef WITH_LEGACY_DEPSGRAPH
+ if (use_new_eval)
+#endif
+ {
+ DAG_scene_relations_validate(bmain, sce_iter);
+ }
+#endif
+ }
/* flush editing data if needed */
prepare_mesh_for_viewport_render(bmain, scene);
@@ -1639,9 +1799,25 @@ void BKE_scene_update_tagged(EvaluationContext *eval_ctx, Main *bmain, Scene *sc
*
* in the future this should handle updates for all datablocks, not
* only objects and scenes. - brecht */
- scene_update_tagged_recursive(eval_ctx, bmain, scene, scene);
+#ifdef WITH_LEGACY_DEPSGRAPH
+ if (!use_new_eval) {
+ scene_update_tagged_recursive(eval_ctx, bmain, scene, scene);
+ }
+ else
+#endif
+ {
+#ifdef OPENSUBDIV_GL_WORKAROUND
+ if (DEG_needs_eval(scene->depsgraph)) {
+ scene_free_unused_opensubdiv_cache(scene);
+ }
+#endif
+ DEG_evaluate_on_refresh(eval_ctx, scene->depsgraph, scene);
+ /* TODO(sergey): This is to beocme a node in new depsgraph. */
+ BKE_mask_update_scene(bmain, scene);
+ }
+
/* update sound system animation (TODO, move to depsgraph) */
- sound_update_scene(bmain, scene);
+ BKE_sound_update_scene(bmain, scene);
/* extra call here to recalc scene animation (for sequencer) */
{
@@ -1657,7 +1833,8 @@ void BKE_scene_update_tagged(EvaluationContext *eval_ctx, Main *bmain, Scene *sc
* Need to do this so changing material settings from the graph/dopesheet
* will update stuff in the viewport.
*/
- if (DAG_id_type_tagged(bmain, ID_MA)) {
+#ifdef WITH_LEGACY_DEPSGRAPH
+ if (!use_new_eval && DAG_id_type_tagged(bmain, ID_MA)) {
Material *material;
float ctime = BKE_scene_frame_get(scene);
@@ -1672,7 +1849,7 @@ void BKE_scene_update_tagged(EvaluationContext *eval_ctx, Main *bmain, Scene *sc
}
/* Also do the same for node trees. */
- if (DAG_id_type_tagged(bmain, ID_NT)) {
+ if (!use_new_eval && DAG_id_type_tagged(bmain, ID_NT)) {
float ctime = BKE_scene_frame_get(scene);
FOREACH_NODETREE(bmain, ntree, id)
@@ -1683,9 +1860,12 @@ void BKE_scene_update_tagged(EvaluationContext *eval_ctx, Main *bmain, Scene *sc
}
FOREACH_NODETREE_END
}
+#endif
/* notify editors and python about recalc */
BLI_callback_exec(bmain, &scene->id, BLI_CB_EVT_SCENE_UPDATE_POST);
+
+ /* Inform editors about possible changes. */
DAG_ids_check_recalc(bmain, scene, false);
/* clear recalc flags */
@@ -1705,6 +1885,14 @@ void BKE_scene_update_for_newframe_ex(EvaluationContext *eval_ctx, Main *bmain,
#ifdef DETAILED_ANALYSIS_OUTPUT
double start_time = PIL_check_seconds_timer();
#endif
+#ifdef WITH_LEGACY_DEPSGRAPH
+ bool use_new_eval = !DEG_depsgraph_use_legacy();
+#else
+ /* TODO(sergey): Pass to evaluation routines instead of storing layer in the graph? */
+ (void) do_invisible_flush;
+#endif
+
+ DAG_editors_update_pre(bmain, sce, true);
/* keep this first */
BLI_callback_exec(bmain, &sce->id, BLI_CB_EVT_FRAME_CHANGE_PRE);
@@ -1714,13 +1902,17 @@ void BKE_scene_update_for_newframe_ex(EvaluationContext *eval_ctx, Main *bmain,
* call this at the start so modifiers with textures don't lag 1 frame */
BKE_image_update_frame(bmain, sce->r.cfra);
+#ifdef WITH_LEGACY_DEPSGRAPH
/* rebuild rigid body worlds before doing the actual frame update
* this needs to be done on start frame but animation playback usually starts one frame later
* we need to do it here to avoid rebuilding the world on every simulation change, which can be very expensive
*/
- scene_rebuild_rbw_recursive(sce, ctime);
-
- sound_set_cfra(sce->r.cfra);
+ if (!use_new_eval) {
+ scene_rebuild_rbw_recursive(sce, ctime);
+ }
+#endif
+
+ BKE_sound_set_cfra(sce->r.cfra);
/* clear animation overrides */
/* XXX TODO... */
@@ -1728,25 +1920,37 @@ void BKE_scene_update_for_newframe_ex(EvaluationContext *eval_ctx, Main *bmain,
for (sce_iter = sce; sce_iter; sce_iter = sce_iter->set)
DAG_scene_relations_update(bmain, sce_iter);
- /* flush recalc flags to dependencies, if we were only changing a frame
- * this would not be necessary, but if a user or a script has modified
- * some datablock before BKE_scene_update_tagged was called, we need the flush */
- DAG_ids_flush_tagged(bmain);
+#ifdef WITH_LEGACY_DEPSGRAPH
+ if (!use_new_eval) {
+ /* flush recalc flags to dependencies, if we were only changing a frame
+ * this would not be necessary, but if a user or a script has modified
+ * some datablock before BKE_scene_update_tagged was called, we need the flush */
+ DAG_ids_flush_tagged(bmain);
- /* Following 2 functions are recursive
- * so don't call within 'scene_update_tagged_recursive' */
- DAG_scene_update_flags(bmain, sce, lay, true, do_invisible_flush); // only stuff that moves or needs display still
+ /* Following 2 functions are recursive
+ * so don't call within 'scene_update_tagged_recursive' */
+ DAG_scene_update_flags(bmain, sce, lay, true, do_invisible_flush); // only stuff that moves or needs display still
+ }
+#endif
BKE_mask_evaluate_all_masks(bmain, ctime, true);
+#ifdef POSE_ANIMATION_WORKAROUND
+ scene_armature_depsgraph_workaround(bmain);
+#endif
+
/* All 'standard' (i.e. without any dependencies) animation is handled here,
* with an 'local' to 'macro' order of evaluation. This should ensure that
* settings stored nestled within a hierarchy (i.e. settings in a Texture block
* can be overridden by settings from Scene, which owns the Texture through a hierarchy
* such as Scene->World->MTex/Texture) can still get correctly overridden.
*/
- BKE_animsys_evaluate_all_animation(bmain, sce, ctime);
- /*...done with recursive funcs */
+#ifdef WITH_LEGACY_DEPSGRAPH
+ if (!use_new_eval) {
+ BKE_animsys_evaluate_all_animation(bmain, sce, ctime);
+ /*...done with recursive funcs */
+ }
+#endif
/* clear "LIB_DOIT" flag from all materials, to prevent infinite recursion problems later
* when trying to find materials with drivers that need evaluating [#32017]
@@ -1756,19 +1960,38 @@ void BKE_scene_update_for_newframe_ex(EvaluationContext *eval_ctx, Main *bmain,
/* run rigidbody sim */
/* NOTE: current position is so that rigidbody sim affects other objects, might change in the future */
- scene_do_rb_simulation_recursive(sce, ctime);
-
+#ifdef WITH_LEGACY_DEPSGRAPH
+ if (!use_new_eval) {
+ scene_do_rb_simulation_recursive(sce, ctime);
+ }
+#endif
+
/* BKE_object_handle_update() on all objects, groups and sets */
- scene_update_tagged_recursive(eval_ctx, bmain, sce, sce);
+#ifdef WITH_LEGACY_DEPSGRAPH
+ if (use_new_eval) {
+ DEG_evaluate_on_framechange(eval_ctx, bmain, sce->depsgraph, ctime, lay);
+ }
+ else {
+ scene_update_tagged_recursive(eval_ctx, bmain, sce, sce);
+ }
+#else
+ DEG_evaluate_on_framechange(eval_ctx, bmain, sce->depsgraph, ctime, lay);
+#endif
+
/* update sound system animation (TODO, move to depsgraph) */
- sound_update_scene(bmain, sce);
+ BKE_sound_update_scene(bmain, sce);
- scene_depsgraph_hack(eval_ctx, sce, sce);
+#ifdef WITH_LEGACY_DEPSGRAPH
+ if (!use_new_eval) {
+ scene_depsgraph_hack(eval_ctx, sce, sce);
+ }
+#endif
/* notify editors and python about recalc */
BLI_callback_exec(bmain, &sce->id, BLI_CB_EVT_SCENE_UPDATE_POST);
BLI_callback_exec(bmain, &sce->id, BLI_CB_EVT_FRAME_CHANGE_POST);
+ /* Inform editors about possible changes. */
DAG_ids_check_recalc(bmain, sce, true);
/* clear recalc flags */
@@ -1808,13 +2031,13 @@ bool BKE_scene_remove_render_layer(Main *bmain, Scene *scene, SceneRenderLayer *
Scene *sce;
if (act == -1) {
- return 0;
+ return false;
}
else if ( (scene->r.layers.first == scene->r.layers.last) &&
(scene->r.layers.first == srl))
{
/* ensure 1 layer is kept */
- return 0;
+ return false;
}
BLI_remlink(&scene->r.layers, srl);
@@ -1836,28 +2059,74 @@ bool BKE_scene_remove_render_layer(Main *bmain, Scene *scene, SceneRenderLayer *
}
}
- return 1;
+ return true;
+}
+
+/* return default view */
+SceneRenderView *BKE_scene_add_render_view(Scene *sce, const char *name)
+{
+ SceneRenderView *srv;
+
+ if (!name)
+ name = DATA_("RenderView");
+
+ srv = MEM_callocN(sizeof(SceneRenderView), "new render view");
+ BLI_strncpy(srv->name, name, sizeof(srv->name));
+ BLI_uniquename(&sce->r.views, srv, DATA_("RenderView"), '.', offsetof(SceneRenderView, name), sizeof(srv->name));
+ BLI_addtail(&sce->r.views, srv);
+
+ return srv;
+}
+
+bool BKE_scene_remove_render_view(Scene *scene, SceneRenderView *srv)
+{
+ const int act = BLI_findindex(&scene->r.views, srv);
+
+ if (act == -1) {
+ return false;
+ }
+ else if (scene->r.views.first == scene->r.views.last) {
+ /* ensure 1 view is kept */
+ return false;
+ }
+
+ BLI_remlink(&scene->r.views, srv);
+ MEM_freeN(srv);
+
+ scene->r.actview = 0;
+
+ return true;
}
/* render simplification */
-int get_render_subsurf_level(RenderData *r, int lvl)
+int get_render_subsurf_level(const RenderData *r, int lvl, bool for_render)
{
- if (r->mode & R_SIMPLIFY)
- return min_ii(r->simplify_subsurf, lvl);
- else
+ if (r->mode & R_SIMPLIFY) {
+ if (for_render)
+ return min_ii(r->simplify_subsurf_render, lvl);
+ else
+ return min_ii(r->simplify_subsurf, lvl);
+ }
+ else {
return lvl;
+ }
}
-int get_render_child_particle_number(RenderData *r, int num)
+int get_render_child_particle_number(const RenderData *r, int num, bool for_render)
{
- if (r->mode & R_SIMPLIFY)
- return (int)(r->simplify_particles * num);
- else
+ if (r->mode & R_SIMPLIFY) {
+ if (for_render)
+ return (int)(r->simplify_particles_render * num);
+ else
+ return (int)(r->simplify_particles * num);
+ }
+ else {
return num;
+ }
}
-int get_render_shadow_samples(RenderData *r, int samples)
+int get_render_shadow_samples(const RenderData *r, int samples)
{
if ((r->mode & R_SIMPLIFY) && samples > 0)
return min_ii(r->simplify_shadowsamples, samples);
@@ -1865,7 +2134,7 @@ int get_render_shadow_samples(RenderData *r, int samples)
return samples;
}
-float get_render_aosss_error(RenderData *r, float error)
+float get_render_aosss_error(const RenderData *r, float error)
{
if (r->mode & R_SIMPLIFY)
return ((1.0f - r->simplify_aosss) * 10.0f + 1.0f) * error;
@@ -1897,17 +2166,27 @@ Base *_setlooper_base_step(Scene **sce_iter, Base *base)
return NULL;
}
-bool BKE_scene_use_new_shading_nodes(Scene *scene)
+bool BKE_scene_use_new_shading_nodes(const Scene *scene)
{
- RenderEngineType *type = RE_engines_find(scene->r.engine);
+ const RenderEngineType *type = RE_engines_find(scene->r.engine);
return (type && type->flag & RE_USE_SHADING_NODES);
}
-bool BKE_scene_uses_blender_internal(struct Scene *scene)
+bool BKE_scene_use_shading_nodes_custom(Scene *scene)
+{
+ RenderEngineType *type = RE_engines_find(scene->r.engine);
+ return (type && type->flag & RE_USE_SHADING_NODES_CUSTOM);
+}
+
+bool BKE_scene_uses_blender_internal(const Scene *scene)
{
- return strcmp("BLENDER_RENDER", scene->r.engine) == 0;
+ return STREQ(scene->r.engine, RE_engine_id_BLENDER_RENDER);
}
+bool BKE_scene_uses_blender_game(const Scene *scene)
+{
+ return STREQ(scene->r.engine, RE_engine_id_BLENDER_GAME);
+}
void BKE_scene_base_flag_to_objects(struct Scene *scene)
{
@@ -1949,7 +2228,7 @@ void BKE_scene_disable_color_management(Scene *scene)
bool BKE_scene_check_color_management_enabled(const Scene *scene)
{
- return strcmp(scene->display_settings.display_device, "None") != 0;
+ return !STREQ(scene->display_settings.display_device, "None");
}
bool BKE_scene_check_rigidbody_active(const Scene *scene)
@@ -1994,15 +2273,295 @@ double BKE_scene_unit_scale(const UnitSettings *unit, const int unit_type, doubl
switch (unit_type) {
case B_UNIT_LENGTH:
return value * (double)unit->scale_length;
- case B_UNIT_CAMERA:
- return value * (double)unit->scale_length;
case B_UNIT_AREA:
return value * pow(unit->scale_length, 2);
case B_UNIT_VOLUME:
return value * pow(unit->scale_length, 3);
case B_UNIT_MASS:
return value * pow(unit->scale_length, 3);
+ case B_UNIT_CAMERA: /* *Do not* use scene's unit scale for camera focal lens! See T42026. */
default:
return value;
}
}
+
+/******************** multiview *************************/
+
+size_t BKE_scene_multiview_num_views_get(const RenderData *rd)
+{
+ SceneRenderView *srv;
+ size_t totviews = 0;
+
+ if ((rd->scemode & R_MULTIVIEW) == 0)
+ return 1;
+
+ if (rd->views_format == SCE_VIEWS_FORMAT_STEREO_3D) {
+ srv = BLI_findstring(&rd->views, STEREO_LEFT_NAME, offsetof(SceneRenderView, name));
+ if ((srv && srv->viewflag & SCE_VIEW_DISABLE) == 0) {
+ totviews++;
+ }
+
+ srv = BLI_findstring(&rd->views, STEREO_RIGHT_NAME, offsetof(SceneRenderView, name));
+ if ((srv && srv->viewflag & SCE_VIEW_DISABLE) == 0) {
+ totviews++;
+ }
+ }
+ else {
+ for (srv = rd->views.first; srv; srv = srv->next) {
+ if ((srv->viewflag & SCE_VIEW_DISABLE) == 0) {
+ totviews++;
+ }
+ }
+ }
+ return totviews;
+}
+
+bool BKE_scene_multiview_is_stereo3d(const RenderData *rd)
+{
+ SceneRenderView *srv[2];
+
+ if ((rd->scemode & R_MULTIVIEW) == 0)
+ return false;
+
+ srv[0] = (SceneRenderView *)BLI_findstring(&rd->views, STEREO_LEFT_NAME, offsetof(SceneRenderView, name));
+ srv[1] = (SceneRenderView *)BLI_findstring(&rd->views, STEREO_RIGHT_NAME, offsetof(SceneRenderView, name));
+
+ return (srv[0] && ((srv[0]->viewflag & SCE_VIEW_DISABLE) == 0) &&
+ srv[1] && ((srv[1]->viewflag & SCE_VIEW_DISABLE) == 0));
+}
+
+/* return whether to render this SceneRenderView */
+bool BKE_scene_multiview_is_render_view_active(const RenderData *rd, const SceneRenderView *srv)
+{
+ if (srv == NULL)
+ return false;
+
+ if ((rd->scemode & R_MULTIVIEW) == 0)
+ return false;
+
+ if ((srv->viewflag & SCE_VIEW_DISABLE))
+ return false;
+
+ if (rd->views_format == SCE_VIEWS_FORMAT_MULTIVIEW)
+ return true;
+
+ /* SCE_VIEWS_SETUP_BASIC */
+ if (STREQ(srv->name, STEREO_LEFT_NAME) ||
+ STREQ(srv->name, STEREO_RIGHT_NAME))
+ {
+ return true;
+ }
+
+ return false;
+}
+
+/* return true if viewname is the first or if the name is NULL or not found */
+bool BKE_scene_multiview_is_render_view_first(const RenderData *rd, const char *viewname)
+{
+ SceneRenderView *srv;
+
+ if ((rd->scemode & R_MULTIVIEW) == 0)
+ return true;
+
+ if ((!viewname) || (!viewname[0]))
+ return true;
+
+ for (srv = rd->views.first; srv; srv = srv->next) {
+ if (BKE_scene_multiview_is_render_view_active(rd, srv)) {
+ return STREQ(viewname, srv->name);
+ }
+ }
+
+ return true;
+}
+
+/* return true if viewname is the last or if the name is NULL or not found */
+bool BKE_scene_multiview_is_render_view_last(const RenderData *rd, const char *viewname)
+{
+ SceneRenderView *srv;
+
+ if ((rd->scemode & R_MULTIVIEW) == 0)
+ return true;
+
+ if ((!viewname) || (!viewname[0]))
+ return true;
+
+ for (srv = rd->views.last; srv; srv = srv->prev) {
+ if (BKE_scene_multiview_is_render_view_active(rd, srv)) {
+ return STREQ(viewname, srv->name);
+ }
+ }
+
+ return true;
+}
+
+SceneRenderView *BKE_scene_multiview_render_view_findindex(const RenderData *rd, const int view_id)
+{
+ SceneRenderView *srv;
+ size_t nr;
+
+ if ((rd->scemode & R_MULTIVIEW) == 0)
+ return NULL;
+
+ nr = 0;
+ for (srv = rd->views.first, nr = 0; srv; srv = srv->next) {
+ if (BKE_scene_multiview_is_render_view_active(rd, srv)) {
+ if (nr++ == view_id)
+ return srv;
+ }
+ }
+ return srv;
+}
+
+const char *BKE_scene_multiview_render_view_name_get(const RenderData *rd, const int view_id)
+{
+ SceneRenderView *srv = BKE_scene_multiview_render_view_findindex(rd, view_id);
+
+ if (srv)
+ return srv->name;
+ else
+ return "";
+}
+
+size_t BKE_scene_multiview_view_id_get(const RenderData *rd, const char *viewname)
+{
+ SceneRenderView *srv;
+ size_t nr;
+
+ if ((!rd) || ((rd->scemode & R_MULTIVIEW) == 0))
+ return 0;
+
+ if ((!viewname) || (!viewname[0]))
+ return 0;
+
+ nr = 0;
+ for (srv = rd->views.first, nr = 0; srv; srv = srv->next) {
+ if (BKE_scene_multiview_is_render_view_active(rd, srv)) {
+ if (STREQ(viewname, srv->name)) {
+ return nr;
+ }
+ else {
+ nr += 1;
+ }
+ }
+ }
+
+ return 0;
+}
+
+void BKE_scene_multiview_filepath_get(
+ SceneRenderView *srv, const char *filepath,
+ char *r_filepath)
+{
+ BLI_strncpy(r_filepath, filepath, FILE_MAX);
+ BLI_path_suffix(r_filepath, FILE_MAX, srv->suffix, "");
+}
+
+/**
+ * When multiview is not used the filepath is as usual (e.g., ``Image.jpg``).
+ * When multiview is on, even if only one view is enabled the view is incorporated
+ * into the file name (e.g., ``Image_L.jpg``). That allows for the user to re-render
+ * individual views.
+ */
+void BKE_scene_multiview_view_filepath_get(
+ const RenderData *rd, const char *filepath, const char *viewname,
+ char *r_filepath)
+{
+ SceneRenderView *srv;
+ char suffix[FILE_MAX];
+
+ srv = BLI_findstring(&rd->views, viewname, offsetof(SceneRenderView, name));
+ if (srv)
+ BLI_strncpy(suffix, srv->suffix, sizeof(suffix));
+ else
+ BLI_strncpy(suffix, viewname, sizeof(suffix));
+
+ BLI_strncpy(r_filepath, filepath, FILE_MAX);
+ BLI_path_suffix(r_filepath, FILE_MAX, suffix, "");
+}
+
+const char *BKE_scene_multiview_view_suffix_get(const RenderData *rd, const char *viewname)
+{
+ SceneRenderView *srv;
+
+ if ((viewname == NULL) || (viewname[0] == '\0'))
+ return viewname;
+
+ srv = BLI_findstring(&rd->views, viewname, offsetof(SceneRenderView, name));
+ if (srv)
+ return srv->suffix;
+ else
+ return viewname;
+}
+
+const char *BKE_scene_multiview_view_id_suffix_get(const RenderData *rd, const size_t view_id)
+{
+ if ((rd->scemode & R_MULTIVIEW) == 0) {
+ return "";
+ }
+ else {
+ const char *viewname = BKE_scene_multiview_render_view_name_get(rd, view_id);
+ return BKE_scene_multiview_view_suffix_get(rd, viewname);
+ }
+}
+
+void BKE_scene_multiview_view_prefix_get(Scene *scene, const char *name, char *rprefix, const char **rext)
+{
+ SceneRenderView *srv;
+ size_t index_act;
+ const char *suf_act;
+ const char delims[] = {'.', '\0'};
+
+ rprefix[0] = '\0';
+
+ /* begin of extension */
+ index_act = BLI_str_rpartition(name, delims, rext, &suf_act);
+ BLI_assert(index_act > 0);
+ UNUSED_VARS_NDEBUG(index_act);
+
+ for (srv = scene->r.views.first; srv; srv = srv->next) {
+ if (BKE_scene_multiview_is_render_view_active(&scene->r, srv)) {
+ size_t len = strlen(srv->suffix);
+ if (STREQLEN(*rext - len, srv->suffix, len)) {
+ BLI_strncpy(rprefix, name, strlen(name) - strlen(*rext) - len + 1);
+ break;
+ }
+ }
+ }
+}
+
+void BKE_scene_multiview_videos_dimensions_get(
+ const RenderData *rd, const size_t width, const size_t height,
+ size_t *r_width, size_t *r_height)
+{
+ if ((rd->scemode & R_MULTIVIEW) &&
+ rd->im_format.views_format == R_IMF_VIEWS_STEREO_3D)
+ {
+ IMB_stereo3d_write_dimensions(
+ rd->im_format.stereo3d_format.display_mode,
+ (rd->im_format.stereo3d_format.flag & S3D_SQUEEZED_FRAME) != 0,
+ width, height,
+ r_width, r_height);
+ }
+ else {
+ *r_width = width;
+ *r_height = height;
+ }
+}
+
+size_t BKE_scene_multiview_num_videos_get(const RenderData *rd)
+{
+ if (BKE_imtype_is_movie(rd->im_format.imtype) == false)
+ return 0;
+
+ if ((rd->scemode & R_MULTIVIEW) == 0)
+ return 1;
+
+ if (rd->im_format.views_format == R_IMF_VIEWS_STEREO_3D) {
+ return 1;
+ }
+ else {
+ /* R_IMF_VIEWS_INDIVIDUAL */
+ return BKE_scene_multiview_num_views_get(rd);
+ }
+}
diff --git a/source/blender/blenkernel/intern/screen.c b/source/blender/blenkernel/intern/screen.c
index b2296151cf7..7401ef28f62 100644
--- a/source/blender/blenkernel/intern/screen.c
+++ b/source/blender/blenkernel/intern/screen.c
@@ -39,6 +39,8 @@
#include "MEM_guardedalloc.h"
+#include "GPU_compositing.h"
+
#include "DNA_scene_types.h"
#include "DNA_screen_types.h"
#include "DNA_space_types.h"
@@ -46,6 +48,7 @@
#include "BLI_listbase.h"
#include "BLI_utildefines.h"
+#include "BLI_rect.h"
#include "BKE_idprop.h"
#include "BKE_screen.h"
@@ -137,7 +140,7 @@ void BKE_spacetype_register(SpaceType *st)
BLI_addtail(&spacetypes, st);
}
-int BKE_spacetype_exists(int spaceid)
+bool BKE_spacetype_exists(int spaceid)
{
return BKE_spacetype_from_id(spaceid) != NULL;
}
@@ -269,6 +272,19 @@ void BKE_spacedata_draw_locks(int set)
}
}
+static void (*spacedata_id_unref_cb)(struct SpaceLink *sl, const struct ID *id) = NULL;
+
+void BKE_spacedata_callback_id_unref_set(void (*func)(struct SpaceLink *sl, const struct ID *))
+{
+ spacedata_id_unref_cb = func;
+}
+
+void BKE_spacedata_id_unref(struct SpaceLink *sl, const struct ID *id)
+{
+ if (spacedata_id_unref_cb) {
+ spacedata_id_unref_cb(sl, id);
+ }
+}
/* not region itself */
void BKE_area_region_free(SpaceType *st, ARegion *ar)
@@ -292,7 +308,16 @@ void BKE_area_region_free(SpaceType *st, ARegion *ar)
ar->v2d.tab_offset = NULL;
}
- BLI_freelistN(&ar->panels);
+ if (!BLI_listbase_is_empty(&ar->panels)) {
+ Panel *pa, *pa_next;
+ for (pa = ar->panels.first; pa; pa = pa_next) {
+ pa_next = pa->next;
+ if (pa->activedata) {
+ MEM_freeN(pa->activedata);
+ }
+ MEM_freeN(pa);
+ }
+ }
for (uilst = ar->ui_lists.first; uilst; uilst = uilst->next) {
if (uilst->dyn_data) {
@@ -402,16 +427,51 @@ ARegion *BKE_area_find_region_active_win(ScrArea *sa)
return NULL;
}
-/* note, using this function is generally a last resort, you really want to be
+ARegion *BKE_area_find_region_xy(ScrArea *sa, const int regiontype, int x, int y)
+{
+ ARegion *ar_found = NULL;
+ if (sa) {
+ ARegion *ar;
+ for (ar = sa->regionbase.first; ar; ar = ar->next) {
+ if ((regiontype == RGN_TYPE_ANY) || (ar->regiontype == regiontype)) {
+ if (BLI_rcti_isect_pt(&ar->winrct, x, y)) {
+ ar_found = ar;
+ break;
+ }
+ }
+ }
+ }
+ return ar_found;
+}
+
+/**
+ * \note, ideally we can get the area from the context,
+ * there are a few places however where this isn't practical.
+ */
+ScrArea *BKE_screen_find_area_from_space(struct bScreen *sc, SpaceLink *sl)
+{
+ ScrArea *sa;
+
+ for (sa = sc->areabase.first; sa; sa = sa->next) {
+ if (BLI_findindex(&sa->spacedata, sl) != -1) {
+ break;
+ }
+ }
+
+ return sa;
+}
+
+/**
+ * \note Using this function is generally a last resort, you really want to be
* using the context when you can - campbell
- * -1 for any type */
+ */
ScrArea *BKE_screen_find_big_area(bScreen *sc, const int spacetype, const short min)
{
ScrArea *sa, *big = NULL;
int size, maxsize = 0;
for (sa = sc->areabase.first; sa; sa = sa->next) {
- if ((spacetype == -1) || sa->spacetype == spacetype) {
+ if ((spacetype == SPACE_TYPE_ANY) || (sa->spacetype == spacetype)) {
if (min <= sa->winx && min <= sa->winy) {
size = sa->winx * sa->winy;
if (size > maxsize) {
@@ -425,6 +485,22 @@ ScrArea *BKE_screen_find_big_area(bScreen *sc, const int spacetype, const short
return big;
}
+ScrArea *BKE_screen_find_area_xy(bScreen *sc, const int spacetype, int x, int y)
+{
+ ScrArea *sa, *sa_found = NULL;
+
+ for (sa = sc->areabase.first; sa; sa = sa->next) {
+ if (BLI_rcti_isect_pt(&sa->totrct, x, y)) {
+ if ((spacetype == SPACE_TYPE_ANY) || (sa->spacetype == spacetype)) {
+ sa_found = sa;
+ }
+ break;
+ }
+ }
+ return sa_found;
+}
+
+
/**
* Utility function to get the active layer to use when adding new objects.
*/
@@ -451,6 +527,23 @@ unsigned int BKE_screen_view3d_layer_active(const struct View3D *v3d, const stru
return BKE_screen_view3d_layer_active_ex(v3d, scene, true);
}
+/**
+ * Accumulate all visible layers on this screen.
+ */
+unsigned int BKE_screen_view3d_layer_all(const bScreen *sc)
+{
+ const ScrArea *sa;
+ unsigned int lay = 0;
+ for (sa = sc->areabase.first; sa; sa = sa->next) {
+ if (sa->spacetype == SPACE_VIEW3D) {
+ View3D *v3d = sa->spacedata.first;
+ lay |= v3d->lay;
+ }
+ }
+
+ return lay;
+}
+
void BKE_screen_view3d_sync(View3D *v3d, struct Scene *scene)
{
int bit;
@@ -473,8 +566,8 @@ void BKE_screen_view3d_sync(View3D *v3d, struct Scene *scene)
if ((v3d->lay & v3d->layact) == 0) {
for (bit = 0; bit < 32; bit++) {
- if (v3d->lay & (1 << bit)) {
- v3d->layact = 1 << bit;
+ if (v3d->lay & (1u << bit)) {
+ v3d->layact = (1u << bit);
break;
}
}
@@ -563,3 +656,26 @@ float BKE_screen_view3d_zoom_from_fac(float zoomfac)
{
return ((sqrtf(4.0f * zoomfac) - (float)M_SQRT2) * 50.0f);
}
+
+void BKE_screen_gpu_fx_validate(GPUFXSettings *fx_settings)
+{
+ /* currently we use DOF from the camera _only_,
+ * so we never allocate this, only copy from the Camera */
+#if 0
+ if ((fx_settings->dof == NULL) &&
+ (fx_settings->fx_flag & GPU_FX_FLAG_DOF))
+ {
+ GPUDOFSettings *fx_dof;
+ fx_dof = fx_settings->dof = MEM_callocN(sizeof(GPUDOFSettings), __func__);
+ }
+#endif
+
+ if ((fx_settings->ssao == NULL) &&
+ (fx_settings->fx_flag & GPU_FX_FLAG_SSAO))
+ {
+ GPUSSAOSettings *fx_ssao;
+ fx_ssao = fx_settings->ssao = MEM_callocN(sizeof(GPUSSAOSettings), __func__);
+
+ GPU_fx_compositor_init_ssao_settings(fx_ssao);
+ }
+}
diff --git a/source/blender/blenkernel/intern/seqcache.c b/source/blender/blenkernel/intern/seqcache.c
index 4268b33cb14..435d9369faa 100644
--- a/source/blender/blenkernel/intern/seqcache.c
+++ b/source/blender/blenkernel/intern/seqcache.c
@@ -33,6 +33,7 @@
#include "MEM_guardedalloc.h"
#include "DNA_sequence_types.h"
+#include "DNA_scene_types.h"
#include "IMB_moviecache.h"
#include "IMB_imbuf.h"
@@ -41,12 +42,13 @@
#include "BLI_listbase.h"
#include "BKE_sequencer.h"
+#include "BKE_scene.h"
typedef struct SeqCacheKey {
struct Sequence *seq;
SeqRenderData context;
float cfra;
- seq_stripelem_ibuf_t type;
+ eSeqStripElemIBuf type;
} SeqCacheKey;
typedef struct SeqPreprocessCacheElem {
@@ -54,7 +56,7 @@ typedef struct SeqPreprocessCacheElem {
struct Sequence *seq;
SeqRenderData context;
- seq_stripelem_ibuf_t type;
+ eSeqStripElemIBuf type;
ImBuf *ibuf;
} SeqPreprocessCacheElem;
@@ -77,7 +79,9 @@ static bool seq_cmp_render_data(const SeqRenderData *a, const SeqRenderData *b)
(a->bmain != b->bmain) ||
(a->scene != b->scene) ||
(a->motion_blur_shutter != b->motion_blur_shutter) ||
- (a->motion_blur_samples != b->motion_blur_samples));
+ (a->motion_blur_samples != b->motion_blur_samples) ||
+ (a->scene->r.views_format != b->scene->r.views_format) ||
+ (a->view_id != b->view_id));
}
static unsigned int seq_hash_render_data(const SeqRenderData *a)
@@ -88,17 +92,18 @@ static unsigned int seq_hash_render_data(const SeqRenderData *a)
rval ^= ((intptr_t) a->bmain) << 6;
rval ^= ((intptr_t) a->scene) << 6;
rval ^= (int)(a->motion_blur_shutter * 100.0f) << 10;
- rval ^= a->motion_blur_samples << 24;
+ rval ^= a->motion_blur_samples << 16;
+ rval ^= ((a->scene->r.views_format * 2) + a->view_id) << 24;
return rval;
}
static unsigned int seqcache_hashhash(const void *key_)
{
- const SeqCacheKey *key = (SeqCacheKey *) key_;
+ const SeqCacheKey *key = key_;
unsigned int rval = seq_hash_render_data(&key->context);
- rval ^= *(unsigned int *) &key->cfra;
+ rval ^= *(const unsigned int *) &key->cfra;
rval += key->type;
rval ^= ((intptr_t) key->seq) << 6;
@@ -107,8 +112,8 @@ static unsigned int seqcache_hashhash(const void *key_)
static bool seqcache_hashcmp(const void *a_, const void *b_)
{
- const SeqCacheKey *a = (SeqCacheKey *) a_;
- const SeqCacheKey *b = (SeqCacheKey *) b_;
+ const SeqCacheKey *a = a_;
+ const SeqCacheKey *b = b_;
return ((a->seq != b->seq) ||
(a->cfra != b->cfra) ||
@@ -148,7 +153,7 @@ void BKE_sequencer_cache_cleanup_sequence(Sequence *seq)
IMB_moviecache_cleanup(moviecache, seqcache_key_check_seq, seq);
}
-struct ImBuf *BKE_sequencer_cache_get(const SeqRenderData *context, Sequence *seq, float cfra, seq_stripelem_ibuf_t type)
+struct ImBuf *BKE_sequencer_cache_get(const SeqRenderData *context, Sequence *seq, float cfra, eSeqStripElemIBuf type)
{
if (moviecache && seq) {
SeqCacheKey key;
@@ -164,7 +169,7 @@ struct ImBuf *BKE_sequencer_cache_get(const SeqRenderData *context, Sequence *se
return NULL;
}
-void BKE_sequencer_cache_put(const SeqRenderData *context, Sequence *seq, float cfra, seq_stripelem_ibuf_t type, ImBuf *i)
+void BKE_sequencer_cache_put(const SeqRenderData *context, Sequence *seq, float cfra, eSeqStripElemIBuf type, ImBuf *i)
{
SeqCacheKey key;
@@ -210,7 +215,7 @@ static void preprocessed_cache_destruct(void)
preprocess_cache = NULL;
}
-ImBuf *BKE_sequencer_preprocessed_cache_get(const SeqRenderData *context, Sequence *seq, float cfra, seq_stripelem_ibuf_t type)
+ImBuf *BKE_sequencer_preprocessed_cache_get(const SeqRenderData *context, Sequence *seq, float cfra, eSeqStripElemIBuf type)
{
SeqPreprocessCacheElem *elem;
@@ -237,7 +242,7 @@ ImBuf *BKE_sequencer_preprocessed_cache_get(const SeqRenderData *context, Sequen
return NULL;
}
-void BKE_sequencer_preprocessed_cache_put(const SeqRenderData *context, Sequence *seq, float cfra, seq_stripelem_ibuf_t type, ImBuf *ibuf)
+void BKE_sequencer_preprocessed_cache_put(const SeqRenderData *context, Sequence *seq, float cfra, eSeqStripElemIBuf type, ImBuf *ibuf)
{
SeqPreprocessCacheElem *elem;
diff --git a/source/blender/blenkernel/intern/seqeffects.c b/source/blender/blenkernel/intern/seqeffects.c
index 11a6cb7acc3..f375c2b1e4f 100644
--- a/source/blender/blenkernel/intern/seqeffects.c
+++ b/source/blender/blenkernel/intern/seqeffects.c
@@ -38,10 +38,13 @@
#include "BLI_math.h" /* windows needs for M_PI */
#include "BLI_utildefines.h"
+#include "BLI_rect.h"
+#include "BLI_string.h"
#include "DNA_scene_types.h"
#include "DNA_sequence_types.h"
#include "DNA_anim_types.h"
+#include "DNA_space_types.h"
#include "BKE_fcurve.h"
#include "BKE_sequencer.h"
@@ -52,11 +55,10 @@
#include "RNA_access.h"
-/* TODO(sergey): Could be considered a bad level call, but
- * need this for gaussian table.
- */
#include "RE_pipeline.h"
+#include "BLF_api.h"
+
static void slice_get_byte_buffers(const SeqRenderData *context, const ImBuf *ibuf1, const ImBuf *ibuf2,
const ImBuf *ibuf3, const ImBuf *out, int start_line, unsigned char **rect1,
unsigned char **rect2, unsigned char **rect3, unsigned char **rect_out)
@@ -2670,8 +2672,8 @@ static void do_gaussian_blur_effect_byte(Sequence *seq,
{
#define INDEX(_x, _y) (((_y) * (x) + (_x)) * 4)
GaussianBlurVars *data = seq->effectdata;
- const int size_x = (int) (data->size_x + 0.5f),
- size_y = (int) (data->size_y + 0.5f);
+ const int size_x = (int) (data->size_x + 0.5f);
+ const int size_y = (int) (data->size_y + 0.5f);
int i, j;
/* Make gaussian weight tabke. */
@@ -2754,8 +2756,8 @@ static void do_gaussian_blur_effect_float(Sequence *seq,
{
#define INDEX(_x, _y) (((_y) * (x) + (_x)) * 4)
GaussianBlurVars *data = seq->effectdata;
- const int size_x = (int) (data->size_x + 0.5f),
- size_y = (int) (data->size_y + 0.5f);
+ const int size_x = (int) (data->size_x + 0.5f);
+ const int size_y = (int) (data->size_y + 0.5f);
int i, j;
/* Make gaussian weight tabke. */
@@ -2879,6 +2881,134 @@ static void do_gaussian_blur_effect(const SeqRenderData *context,
}
}
+/*********************** text *************************/
+static void init_text_effect(Sequence *seq)
+{
+ TextVars *data;
+
+ if (seq->effectdata)
+ MEM_freeN(seq->effectdata);
+
+ data = seq->effectdata = MEM_callocN(sizeof(TextVars), "textvars");
+ data->text_size = 30;
+ BLI_strncpy(data->text, "Text", sizeof(data->text));
+
+ data->loc[0] = 0.5f;
+ data->align = SEQ_TEXT_ALIGN_X_CENTER;
+ data->align_y = SEQ_TEXT_ALIGN_Y_BOTTOM;
+}
+
+static int num_inputs_text(void)
+{
+ return 0;
+}
+
+static int early_out_text(Sequence *seq, float UNUSED(facf0), float UNUSED(facf1))
+{
+ TextVars *data = seq->effectdata;
+ if (data->text[0] == 0 || data->text_size < 1) {
+ return EARLY_USE_INPUT_1;
+ }
+ return EARLY_NO_INPUT;
+}
+
+static ImBuf *do_text_effect(const SeqRenderData *context, Sequence *seq, float UNUSED(cfra), float UNUSED(facf0), float UNUSED(facf1),
+ ImBuf *ibuf1, ImBuf *ibuf2, ImBuf *ibuf3)
+{
+ ImBuf *out = prepare_effect_imbufs(context, ibuf1, ibuf2, ibuf3);
+ TextVars *data = seq->effectdata;
+ int width = out->x;
+ int height = out->y;
+ struct ColorManagedDisplay *display;
+ const char *display_device;
+ const int mono = blf_mono_font_render; // XXX
+ int line_height;
+ int y_ofs, x, y;
+ float proxy_size_comp;
+
+ display_device = context->scene->display_settings.display_device;
+ display = IMB_colormanagement_display_get_named(display_device);
+
+ /* Compensate text size for preview render size. */
+ if (ELEM(context->preview_render_size, SEQ_PROXY_RENDER_SIZE_SCENE, SEQ_PROXY_RENDER_SIZE_FULL)) {
+ proxy_size_comp = context->scene->r.size / 100.0f;
+ }
+ else if (context->preview_render_size == SEQ_PROXY_RENDER_SIZE_100) {
+ proxy_size_comp = 1.0f;
+ }
+ else {
+ proxy_size_comp = context->preview_render_size / 100.0f;
+ }
+
+ /* set before return */
+ BLF_size(mono, proxy_size_comp * data->text_size, 72);
+
+ BLF_enable(mono, BLF_WORD_WRAP);
+
+ /* use max width to enable newlines only */
+ BLF_wordwrap(mono, (data->wrap_width != 0.0f) ? data->wrap_width * width : -1);
+
+ BLF_buffer(mono, out->rect_float, (unsigned char *)out->rect, width, height, out->channels, display);
+
+ line_height = BLF_height_max(mono);
+
+ y_ofs = -BLF_descender(mono);
+
+ x = (data->loc[0] * width);
+ y = (data->loc[1] * height) + y_ofs;
+
+ if ((data->align == SEQ_TEXT_ALIGN_X_LEFT) &&
+ (data->align_y == SEQ_TEXT_ALIGN_Y_TOP))
+ {
+ y -= line_height;
+ }
+ else {
+ /* vars for calculating wordwrap */
+ struct {
+ struct ResultBLF info;
+ rctf rect;
+ } wrap;
+
+ BLF_boundbox_ex(mono, data->text, sizeof(data->text), &wrap.rect, &wrap.info);
+
+ if (data->align == SEQ_TEXT_ALIGN_X_RIGHT) {
+ x -= BLI_rctf_size_x(&wrap.rect);
+ }
+ else if (data->align == SEQ_TEXT_ALIGN_X_CENTER) {
+ x -= BLI_rctf_size_x(&wrap.rect) / 2;
+ }
+
+ if (data->align_y == SEQ_TEXT_ALIGN_Y_TOP) {
+ y -= line_height;
+ }
+ else if (data->align_y == SEQ_TEXT_ALIGN_Y_BOTTOM) {
+ y += (wrap.info.lines - 1) * line_height;
+ }
+ else if (data->align_y == SEQ_TEXT_ALIGN_Y_CENTER) {
+ y += (((wrap.info.lines - 1) / 2) * line_height) - (line_height / 2);
+ }
+ }
+
+ /* BLF_SHADOW won't work with buffers, instead use cheap shadow trick */
+ if (data->flag & SEQ_TEXT_SHADOW) {
+ int fontx, fonty;
+ fontx = BLF_width_max(mono);
+ fonty = line_height;
+ BLF_position(mono, x + max_ii(fontx / 25, 1), y + max_ii(fonty / 25, 1), 0.0f);
+ BLF_buffer_col(mono, 0.0f, 0.0f, 0.0f, 1.0f);
+ BLF_draw_buffer(mono, data->text, BLF_DRAW_STR_DUMMY_MAX);
+ }
+ BLF_position(mono, x, y, 0.0f);
+ BLF_buffer_col(mono, 1.0f, 1.0f, 1.0f, 1.0f);
+ BLF_draw_buffer(mono, data->text, BLF_DRAW_STR_DUMMY_MAX);
+
+ BLF_buffer(mono, NULL, NULL, 0, 0, 0, NULL);
+
+ BLF_disable(mono, BLF_WORD_WRAP);
+
+ return out;
+}
+
/*********************** sequence effect factory *************************/
static void init_noop(Sequence *UNUSED(seq))
@@ -2901,6 +3031,19 @@ static int num_inputs_default(void)
return 2;
}
+static void copy_effect_default(Sequence *dst, Sequence *src)
+{
+ dst->effectdata = MEM_dupallocN(src->effectdata);
+}
+
+static void free_effect_default(Sequence *seq)
+{
+ if (seq->effectdata)
+ MEM_freeN(seq->effectdata);
+
+ seq->effectdata = NULL;
+}
+
static int early_out_noop(Sequence *UNUSED(seq), float UNUSED(facf0), float UNUSED(facf1))
{
return EARLY_DO_EFFECT;
@@ -3076,6 +3219,14 @@ static struct SeqEffectHandle get_sequence_effect_impl(int seq_type)
rval.early_out = early_out_gaussian_blur;
rval.execute_slice = do_gaussian_blur_effect;
break;
+ case SEQ_TYPE_TEXT:
+ rval.num_inputs = num_inputs_text;
+ rval.init = init_text_effect;
+ rval.free = free_effect_default;
+ rval.copy = copy_effect_default;
+ rval.early_out = early_out_text;
+ rval.execute = do_text_effect;
+ break;
}
return rval;
diff --git a/source/blender/blenkernel/intern/seqmodifier.c b/source/blender/blenkernel/intern/seqmodifier.c
index b78529f51b4..07242aa2f6e 100644
--- a/source/blender/blenkernel/intern/seqmodifier.c
+++ b/source/blender/blenkernel/intern/seqmodifier.c
@@ -39,7 +39,7 @@
#include "BLI_utildefines.h"
#include "BLI_math.h"
-#include "BLF_translation.h"
+#include "BLT_translation.h"
#include "DNA_sequence_types.h"
@@ -77,9 +77,9 @@ typedef struct ModifierThread {
} ModifierThread;
-static ImBuf *modifier_mask_get(SequenceModifierData *smd, const SeqRenderData *context, int cfra, bool make_float)
+static ImBuf *modifier_mask_get(SequenceModifierData *smd, const SeqRenderData *context, int cfra, int fra_offset, bool make_float)
{
- return BKE_sequencer_render_mask_input(context, smd->mask_input_type, smd->mask_sequence, smd->mask_id, cfra, make_float);
+ return BKE_sequencer_render_mask_input(context, smd->mask_input_type, smd->mask_sequence, smd->mask_id, cfra, fra_offset, make_float);
}
static void modifier_init_handle(void *handle_v, int start_line, int tot_line, void *init_data_v)
@@ -164,7 +164,7 @@ static void colorBalance_apply(SequenceModifierData *smd, ImBuf *ibuf, ImBuf *ma
}
static SequenceModifierTypeInfo seqModifier_ColorBalance = {
- CTX_N_(BLF_I18NCONTEXT_ID_SEQUENCE, "Color Balance"), /* name */
+ CTX_N_(BLT_I18NCONTEXT_ID_SEQUENCE, "Color Balance"), /* name */
"ColorBalanceModifierData", /* struct_name */
sizeof(ColorBalanceModifierData), /* struct_size */
colorBalance_init_data, /* init_data */
@@ -273,7 +273,7 @@ static void curves_apply(struct SequenceModifierData *smd, ImBuf *ibuf, ImBuf *m
}
static SequenceModifierTypeInfo seqModifier_Curves = {
- CTX_N_(BLF_I18NCONTEXT_ID_SEQUENCE, "Curves"), /* name */
+ CTX_N_(BLT_I18NCONTEXT_ID_SEQUENCE, "Curves"), /* name */
"CurvesModifierData", /* struct_name */
sizeof(CurvesModifierData), /* struct_size */
curves_init_data, /* init_data */
@@ -381,7 +381,7 @@ static void hue_correct_apply(struct SequenceModifierData *smd, ImBuf *ibuf, ImB
}
static SequenceModifierTypeInfo seqModifier_HueCorrect = {
- CTX_N_(BLF_I18NCONTEXT_ID_SEQUENCE, "Hue Correct"), /* name */
+ CTX_N_(BLT_I18NCONTEXT_ID_SEQUENCE, "Hue Correct"), /* name */
"HueCorrectModifierData", /* struct_name */
sizeof(HueCorrectModifierData), /* struct_size */
hue_correct_init_data, /* init_data */
@@ -478,7 +478,7 @@ static void brightcontrast_apply(struct SequenceModifierData *smd, ImBuf *ibuf,
}
static SequenceModifierTypeInfo seqModifier_BrightContrast = {
- CTX_N_(BLF_I18NCONTEXT_ID_SEQUENCE, "Bright/Contrast"), /* name */
+ CTX_N_(BLT_I18NCONTEXT_ID_SEQUENCE, "Bright/Contrast"), /* name */
"BrightContrastModifierData", /* struct_name */
sizeof(BrightContrastModifierData), /* struct_size */
NULL, /* init_data */
@@ -531,19 +531,15 @@ static void maskmodifier_apply_threaded(int width, int height, unsigned char *re
}
}
-static void maskmodifier_apply(struct SequenceModifierData *smd, ImBuf *ibuf, ImBuf *mask)
+static void maskmodifier_apply(struct SequenceModifierData *UNUSED(smd), ImBuf *ibuf, ImBuf *mask)
{
- BrightContrastModifierData *bcmd = (BrightContrastModifierData *) smd;
- BrightContrastThreadData data;
-
- data.bright = bcmd->bright;
- data.contrast = bcmd->contrast;
+ // SequencerMaskModifierData *bcmd = (SequencerMaskModifierData *)smd;
- modifier_apply_threaded(ibuf, mask, maskmodifier_apply_threaded, &data);
+ modifier_apply_threaded(ibuf, mask, maskmodifier_apply_threaded, NULL);
}
static SequenceModifierTypeInfo seqModifier_Mask = {
- CTX_N_(BLF_I18NCONTEXT_ID_SEQUENCE, "Mask"), /* name */
+ CTX_N_(BLT_I18NCONTEXT_ID_SEQUENCE, "Mask"), /* name */
"SequencerMaskModifierData", /* struct_name */
sizeof(SequencerMaskModifierData), /* struct_size */
NULL, /* init_data */
@@ -567,7 +563,7 @@ static void sequence_modifier_type_info_init(void)
#undef INIT_TYPE
}
-SequenceModifierTypeInfo *BKE_sequence_modifier_type_info_get(int type)
+const SequenceModifierTypeInfo *BKE_sequence_modifier_type_info_get(int type)
{
if (!modifierTypesInit) {
sequence_modifier_type_info_init();
@@ -580,7 +576,7 @@ SequenceModifierTypeInfo *BKE_sequence_modifier_type_info_get(int type)
SequenceModifierData *BKE_sequence_modifier_new(Sequence *seq, const char *name, int type)
{
SequenceModifierData *smd;
- SequenceModifierTypeInfo *smti = BKE_sequence_modifier_type_info_get(type);
+ const SequenceModifierTypeInfo *smti = BKE_sequence_modifier_type_info_get(type);
smd = MEM_callocN(smti->struct_size, "sequence modifier");
@@ -627,7 +623,7 @@ void BKE_sequence_modifier_clear(Sequence *seq)
void BKE_sequence_modifier_free(SequenceModifierData *smd)
{
- SequenceModifierTypeInfo *smti = BKE_sequence_modifier_type_info_get(smd->type);
+ const SequenceModifierTypeInfo *smti = BKE_sequence_modifier_type_info_get(smd->type);
if (smti && smti->free_data) {
smti->free_data(smd);
@@ -638,9 +634,9 @@ void BKE_sequence_modifier_free(SequenceModifierData *smd)
void BKE_sequence_modifier_unique_name(Sequence *seq, SequenceModifierData *smd)
{
- SequenceModifierTypeInfo *smti = BKE_sequence_modifier_type_info_get(smd->type);
+ const SequenceModifierTypeInfo *smti = BKE_sequence_modifier_type_info_get(smd->type);
- BLI_uniquename(&seq->modifiers, smd, CTX_DATA_(BLF_I18NCONTEXT_ID_SEQUENCE, smti->name), '.',
+ BLI_uniquename(&seq->modifiers, smd, CTX_DATA_(BLT_I18NCONTEXT_ID_SEQUENCE, smti->name), '.',
offsetof(SequenceModifierData, name), sizeof(smd->name));
}
@@ -660,7 +656,7 @@ ImBuf *BKE_sequence_modifier_apply_stack(const SeqRenderData *context, Sequence
}
for (smd = seq->modifiers.first; smd; smd = smd->next) {
- SequenceModifierTypeInfo *smti = BKE_sequence_modifier_type_info_get(smd->type);
+ const SequenceModifierTypeInfo *smti = BKE_sequence_modifier_type_info_get(smd->type);
/* could happen if modifier is being removed or not exists in current version of blender */
if (!smti)
@@ -671,7 +667,7 @@ ImBuf *BKE_sequence_modifier_apply_stack(const SeqRenderData *context, Sequence
continue;
if (smti->apply) {
- ImBuf *mask = modifier_mask_get(smd, context, cfra, ibuf->rect_float != NULL);
+ ImBuf *mask = modifier_mask_get(smd, context, cfra, seq->start, ibuf->rect_float != NULL);
if (processed_ibuf == ibuf)
processed_ibuf = IMB_dupImBuf(ibuf);
@@ -696,7 +692,7 @@ void BKE_sequence_modifier_list_copy(Sequence *seqn, Sequence *seq)
for (smd = seq->modifiers.first; smd; smd = smd->next) {
SequenceModifierData *smdn;
- SequenceModifierTypeInfo *smti = BKE_sequence_modifier_type_info_get(smd->type);
+ const SequenceModifierTypeInfo *smti = BKE_sequence_modifier_type_info_get(smd->type);
smdn = MEM_dupallocN(smd);
diff --git a/source/blender/blenkernel/intern/sequencer.c b/source/blender/blenkernel/intern/sequencer.c
index c9647b05ce7..f0e59eda321 100644
--- a/source/blender/blenkernel/intern/sequencer.c
+++ b/source/blender/blenkernel/intern/sequencer.c
@@ -53,7 +53,13 @@
#include "BLI_threads.h"
#include "BLI_utildefines.h"
-#include "BLF_translation.h"
+#ifdef WIN32
+# include "BLI_winstuff.h"
+#else
+# include <unistd.h>
+#endif
+
+#include "BLT_translation.h"
#include "BKE_animsys.h"
#include "BKE_depsgraph.h"
@@ -66,6 +72,7 @@
#include "BKE_scene.h"
#include "BKE_mask.h"
#include "BKE_library.h"
+#include "BKE_idprop.h"
#include "RNA_access.h"
@@ -81,13 +88,15 @@
#include "BKE_sound.h"
#ifdef WITH_AUDASPACE
-# include "AUD_C-API.h"
+# include AUD_SPECIAL_H
#endif
static ImBuf *seq_render_strip_stack(const SeqRenderData *context, ListBase *seqbasep, float cfra, int chanshown);
static ImBuf *seq_render_strip(const SeqRenderData *context, Sequence *seq, float cfra);
static void seq_free_animdata(Scene *scene, Sequence *seq);
static ImBuf *seq_render_mask(const SeqRenderData *context, Mask *mask, float nr, bool make_float);
+static size_t seq_num_files(Scene *scene, char views_format, const bool is_multiview);
+static void seq_anim_add_suffix(Scene *scene, struct anim *anim, const size_t view_id);
/* **** XXX ******** */
#define SELECT 1
@@ -180,10 +189,7 @@ static void BKE_sequence_free_ex(Scene *scene, Sequence *seq, const bool do_cach
if (seq->strip)
seq_free_strip(seq->strip);
- if (seq->anim) {
- IMB_free_anim(seq->anim);
- seq->anim = NULL;
- }
+ BKE_sequence_free_anim(seq);
if (seq->type & SEQ_TYPE_EFFECT) {
struct SeqEffectHandle sh = BKE_sequence_get_effect(seq);
@@ -195,6 +201,10 @@ static void BKE_sequence_free_ex(Scene *scene, Sequence *seq, const bool do_cach
((ID *)seq->sound)->us--;
}
+ if (seq->stereo3d_format) {
+ MEM_freeN(seq->stereo3d_format);
+ }
+
/* clipboard has no scene and will never have a sound handle or be active
* same goes to sequences copy for proxy rebuild job
*/
@@ -205,11 +215,16 @@ static void BKE_sequence_free_ex(Scene *scene, Sequence *seq, const bool do_cach
ed->act_seq = NULL;
if (seq->scene_sound && ELEM(seq->type, SEQ_TYPE_SOUND_RAM, SEQ_TYPE_SCENE))
- sound_remove_scene_sound(scene, seq->scene_sound);
+ BKE_sound_remove_scene_sound(scene, seq->scene_sound);
seq_free_animdata(scene, seq);
}
+ if (seq->prop) {
+ IDP_FreeProperty(seq->prop);
+ MEM_freeN(seq->prop);
+ }
+
/* free modifiers */
BKE_sequence_modifier_clear(seq);
@@ -234,6 +249,22 @@ void BKE_sequence_free(Scene *scene, Sequence *seq)
BKE_sequence_free_ex(scene, seq, true);
}
+/* Function to free imbuf and anim data on changes */
+void BKE_sequence_free_anim(Sequence *seq)
+{
+ while (seq->anims.last) {
+ StripAnim *sanim = seq->anims.last;
+
+ if (sanim->anim) {
+ IMB_free_anim(sanim->anim);
+ sanim->anim = NULL;
+ }
+
+ BLI_freelinkN(&seq->anims, sanim);
+ }
+ BLI_listbase_clear(&seq->anims);
+}
+
/* cache must be freed before calling this function
* since it leaves the seqbase in an invalid state */
static void seq_free_sequence_recurse(Scene *scene, Sequence *seq)
@@ -257,26 +288,15 @@ Editing *BKE_sequencer_editing_get(Scene *scene, bool alloc)
return scene->ed;
}
-static void seq_free_clipboard_recursive(Sequence *seq_parent)
-{
- Sequence *seq, *nseq;
-
- for (seq = seq_parent->seqbase.first; seq; seq = nseq) {
- nseq = seq->next;
- seq_free_clipboard_recursive(seq);
- }
-
- BKE_sequence_clipboard_pointers_free(seq_parent);
- BKE_sequence_free_ex(NULL, seq_parent, false);
-}
-
void BKE_sequencer_free_clipboard(void)
{
Sequence *seq, *nseq;
+ BKE_sequencer_base_clipboard_pointers_free(&seqbase_clipboard);
+
for (seq = seqbase_clipboard.first; seq; seq = nseq) {
nseq = seq->next;
- seq_free_clipboard_recursive(seq);
+ seq_free_sequence_recurse(NULL, seq);
}
BLI_listbase_clear(&seqbase_clipboard);
}
@@ -327,7 +347,7 @@ static void seqclipboard_ptr_restore(Main *bmain, ID **id_pt)
{
id_restore = BLI_findstring(lb, ((bSound *)ID_PT)->name, offsetof(bSound, name));
if (id_restore == NULL) {
- id_restore = sound_new_file(bmain, ((bSound *)ID_PT)->name);
+ id_restore = BKE_sound_new_file(bmain, ((bSound *)ID_PT)->name);
(ID_PT)->newid = id_restore; /* reuse next time */
}
break;
@@ -373,6 +393,33 @@ void BKE_sequence_clipboard_pointers_restore(Sequence *seq, Main *bmain)
seqclipboard_ptr_restore(bmain, (ID **)&seq->mask);
seqclipboard_ptr_restore(bmain, (ID **)&seq->sound);
}
+
+/* recursive versions of funcions above */
+void BKE_sequencer_base_clipboard_pointers_free(ListBase *seqbase)
+{
+ Sequence *seq;
+ for (seq = seqbase->first; seq; seq = seq->next) {
+ BKE_sequence_clipboard_pointers_free(seq);
+ BKE_sequencer_base_clipboard_pointers_free(&seq->seqbase);
+ }
+}
+void BKE_sequencer_base_clipboard_pointers_store(ListBase *seqbase)
+{
+ Sequence *seq;
+ for (seq = seqbase->first; seq; seq = seq->next) {
+ BKE_sequence_clipboard_pointers_store(seq);
+ BKE_sequencer_base_clipboard_pointers_store(&seq->seqbase);
+ }
+}
+void BKE_sequencer_base_clipboard_pointers_restore(ListBase *seqbase, Main *bmain)
+{
+ Sequence *seq;
+ for (seq = seqbase->first; seq; seq = seq->next) {
+ BKE_sequence_clipboard_pointers_restore(seq, bmain);
+ BKE_sequencer_base_clipboard_pointers_restore(&seq->seqbase, bmain);
+ }
+}
+
/* end clipboard pointer mess */
@@ -499,24 +546,23 @@ void BKE_sequencer_pixel_from_sequencer_space_v4(struct Scene *scene, float pixe
/*********************** sequencer pipeline functions *************************/
-SeqRenderData BKE_sequencer_new_render_data(EvaluationContext *eval_ctx,
- Main *bmain, Scene *scene, int rectx, int recty,
- int preview_render_size)
-{
- SeqRenderData rval;
-
- rval.bmain = bmain;
- rval.scene = scene;
- rval.rectx = rectx;
- rval.recty = recty;
- rval.preview_render_size = preview_render_size;
- rval.motion_blur_samples = 0;
- rval.motion_blur_shutter = 0;
- rval.eval_ctx = eval_ctx;
- rval.skip_cache = false;
- rval.is_proxy_render = false;
-
- return rval;
+void BKE_sequencer_new_render_data(
+ EvaluationContext *eval_ctx,
+ Main *bmain, Scene *scene, int rectx, int recty,
+ int preview_render_size,
+ SeqRenderData *r_context)
+{
+ r_context->eval_ctx = eval_ctx;
+ r_context->bmain = bmain;
+ r_context->scene = scene;
+ r_context->rectx = rectx;
+ r_context->recty = recty;
+ r_context->preview_render_size = preview_render_size;
+ r_context->motion_blur_samples = 0;
+ r_context->motion_blur_shutter = 0;
+ r_context->skip_cache = false;
+ r_context->is_proxy_render = false;
+ r_context->view_id = 0;
}
/* ************************* iterator ************************** */
@@ -638,7 +684,7 @@ static void seq_update_sound_bounds_recursive_rec(Scene *scene, Sequence *metase
if (seq->start + seq->len - seq->endofs > end)
endofs = seq->start + seq->len - end;
- sound_move_scene_sound(scene, seq->scene_sound, seq->start + startofs,
+ BKE_sound_move_scene_sound(scene, seq->scene_sound, seq->start + startofs,
seq->start + seq->len - endofs, startofs + seq->anim_startofs);
}
}
@@ -751,10 +797,17 @@ void BKE_sequence_calc(Scene *scene, Sequence *seq)
}
}
+static void seq_multiview_name(Scene *scene, const size_t view_id, const char *prefix,
+ const char *ext, char *r_path, size_t r_size)
+{
+ const char *suffix = BKE_scene_multiview_view_id_suffix_get(&scene->r, view_id);
+ BLI_snprintf(r_path, r_size, "%s%s%s", prefix, suffix, ext);
+}
+
/* note: caller should run BKE_sequence_calc(scene, seq) after */
void BKE_sequence_reload_new_file(Scene *scene, Sequence *seq, const bool lock_range)
{
- char str[FILE_MAX];
+ char path[FILE_MAX];
int prev_startdisp = 0, prev_enddisp = 0;
/* note: don't rename the strip, will break animation curves */
@@ -787,22 +840,67 @@ void BKE_sequence_reload_new_file(Scene *scene, Sequence *seq, const bool lock_r
break;
}
case SEQ_TYPE_MOVIE:
- BLI_join_dirfile(str, sizeof(str), seq->strip->dir,
+ {
+ StripAnim *sanim;
+ bool is_multiview_loaded = false;
+ const bool is_multiview = (seq->flag & SEQ_USE_VIEWS) != 0 &&
+ (scene->r.scemode & R_MULTIVIEW) != 0;
+
+ BLI_join_dirfile(path, sizeof(path), seq->strip->dir,
seq->strip->stripdata->name);
- BLI_path_abs(str, G.main->name);
+ BLI_path_abs(path, G.main->name);
+
+ BKE_sequence_free_anim(seq);
+
+ if (is_multiview && (seq->views_format == R_IMF_VIEWS_INDIVIDUAL)) {
+ char prefix[FILE_MAX];
+ const char *ext = NULL;
+ size_t totfiles = seq_num_files(scene, seq->views_format, true);
+ int i = 0;
+
+ BKE_scene_multiview_view_prefix_get(scene, path, prefix, &ext);
+
+ if (prefix[0] != '\0') {
+ for (i = 0; i < totfiles; i++) {
+ struct anim *anim;
+ char str[FILE_MAX];
- if (seq->anim) IMB_free_anim(seq->anim);
+ seq_multiview_name(scene, i, prefix, ext, str, FILE_MAX);
+ anim = openanim(str, IB_rect | ((seq->flag & SEQ_FILTERY) ? IB_animdeinterlace : 0),
+ seq->streamindex, seq->strip->colorspace_settings.name);
+
+ if (anim) {
+ seq_anim_add_suffix(scene, anim, i);
+ sanim = MEM_mallocN(sizeof(StripAnim), "Strip Anim");
+ BLI_addtail(&seq->anims, sanim);
+ sanim->anim = anim;
+ }
+ }
+ is_multiview_loaded = true;
+ }
+ }
+
+ if (is_multiview_loaded == false) {
+ struct anim *anim;
+ anim = openanim(path, IB_rect | ((seq->flag & SEQ_FILTERY) ? IB_animdeinterlace : 0),
+ seq->streamindex, seq->strip->colorspace_settings.name);
+ if (anim) {
+ sanim = MEM_mallocN(sizeof(StripAnim), "Strip Anim");
+ BLI_addtail(&seq->anims, sanim);
+ sanim->anim = anim;
+ }
+ }
- seq->anim = openanim(str, IB_rect | ((seq->flag & SEQ_FILTERY) ? IB_animdeinterlace : 0),
- seq->streamindex, seq->strip->colorspace_settings.name);
+ /* use the first video as reference for everything */
+ sanim = seq->anims.first;
- if (!seq->anim) {
+ if ((!sanim) || (!sanim->anim)) {
return;
}
- seq->len = IMB_anim_get_duration(seq->anim, seq->strip->proxy ? seq->strip->proxy->tc : IMB_TC_RECORD_RUN);
-
- seq->anim_preseek = IMB_anim_get_preseek(seq->anim);
+ seq->len = IMB_anim_get_duration(sanim->anim, seq->strip->proxy ? seq->strip->proxy->tc : IMB_TC_RECORD_RUN);
+
+ seq->anim_preseek = IMB_anim_get_preseek(sanim->anim);
seq->len -= seq->anim_startofs;
seq->len -= seq->anim_endofs;
@@ -810,6 +908,7 @@ void BKE_sequence_reload_new_file(Scene *scene, Sequence *seq, const bool lock_r
seq->len = 0;
}
break;
+ }
case SEQ_TYPE_MOVIECLIP:
if (seq->clip == NULL)
return;
@@ -876,7 +975,6 @@ void BKE_sequencer_sort(Scene *scene)
Editing *ed = BKE_sequencer_editing_get(scene, false);
Sequence *seq, *seqt;
-
if (ed == NULL)
return;
@@ -1017,6 +1115,7 @@ static const char *give_seqname_by_type(int type)
case SEQ_TYPE_ADJUSTMENT: return "Adjustment";
case SEQ_TYPE_SPEED: return "Speed";
case SEQ_TYPE_GAUSSIAN_BLUR: return "Gaussian Blur";
+ case SEQ_TYPE_TEXT: return "Text";
default:
return NULL;
}
@@ -1027,7 +1126,7 @@ const char *BKE_sequence_give_name(Sequence *seq)
const char *name = give_seqname_by_type(seq->type);
if (!name) {
- if (seq->type < SEQ_TYPE_EFFECT) {
+ if (!(seq->type & SEQ_TYPE_EFFECT)) {
return seq->strip->dir;
}
else {
@@ -1063,30 +1162,25 @@ static void make_black_ibuf(ImBuf *ibuf)
}
}
-static void multibuf(ImBuf *ibuf, float fmul)
+static void multibuf(ImBuf *ibuf, const float fmul)
{
char *rt;
float *rt_float;
- int a, mul, icol;
+ int a;
- mul = (int)(256.0f * fmul);
rt = (char *)ibuf->rect;
rt_float = ibuf->rect_float;
if (rt) {
+ const int imul = (int)(256.0f * fmul);
a = ibuf->x * ibuf->y;
while (a--) {
+ rt[0] = min_ii((imul * rt[0]) >> 8, 255);
+ rt[1] = min_ii((imul * rt[1]) >> 8, 255);
+ rt[2] = min_ii((imul * rt[2]) >> 8, 255);
+ rt[3] = min_ii((imul * rt[3]) >> 8, 255);
- icol = (mul * rt[0]) >> 8;
- if (icol > 254) rt[0] = 255; else rt[0] = icol;
- icol = (mul * rt[1]) >> 8;
- if (icol > 254) rt[1] = 255; else rt[1] = icol;
- icol = (mul * rt[2]) >> 8;
- if (icol > 254) rt[2] = 255; else rt[2] = icol;
- icol = (mul * rt[3]) >> 8;
- if (icol > 254) rt[3] = 255; else rt[3] = icol;
-
rt += 4;
}
}
@@ -1168,7 +1262,7 @@ static int evaluate_seq_frame_gen(Sequence **seq_arr, ListBase *seqbase, int cfr
seq = seqbase->first;
while (seq) {
if (seq->startdisp <= cfra && seq->enddisp > cfra) {
- if ((seq->type & SEQ_TYPE_EFFECT)) {
+ if ((seq->type & SEQ_TYPE_EFFECT) && !(seq->flag & SEQ_MUTE)) {
if (seq->seq1) {
effect_inputs[num_effect_inputs++] = seq->seq1;
}
@@ -1277,6 +1371,8 @@ typedef struct SeqIndexBuildContext {
int tc_flags;
int size_flags;
int quality;
+ bool overwrite;
+ size_t view_id;
Main *bmain;
Scene *scene;
@@ -1316,48 +1412,164 @@ static double seq_rendersize_to_scale_factor(int size)
return 0.25;
}
-static void seq_open_anim_file(Sequence *seq)
+/* the number of files will vary according to the stereo format */
+static size_t seq_num_files(Scene *scene, char views_format, const bool is_multiview)
+{
+ if (!is_multiview) {
+ return 1;
+ }
+ else if (views_format == R_IMF_VIEWS_STEREO_3D) {
+ return 1;
+ }
+ /* R_IMF_VIEWS_INDIVIDUAL */
+ else {
+ return BKE_scene_multiview_num_views_get(&scene->r);
+ }
+}
+
+static void seq_proxy_index_dir_set(struct anim *anim, const char *base_dir)
+{
+ char dir[FILE_MAX];
+ char fname[FILE_MAXFILE];
+
+ IMB_anim_get_fname(anim, fname, FILE_MAXFILE);
+ BLI_strncpy(dir, base_dir, sizeof(dir));
+ BLI_path_append(dir, sizeof(dir), fname);
+ IMB_anim_set_index_dir(anim, dir);
+}
+
+static void seq_open_anim_file(Scene *scene, Sequence *seq, bool openfile)
{
+ char dir[FILE_MAX];
char name[FILE_MAX];
StripProxy *proxy;
+ bool use_proxy;
+ bool is_multiview_loaded = false;
+ Editing *ed = scene->ed;
+ const bool is_multiview = (seq->flag & SEQ_USE_VIEWS) != 0 && (scene->r.scemode & R_MULTIVIEW) != 0;
- if (seq->anim != NULL) {
+ if ((seq->anims.first != NULL) && (((StripAnim *)seq->anims.first)->anim != NULL)) {
return;
}
+ /* reset all the previously created anims */
+ BKE_sequence_free_anim(seq);
+
BLI_join_dirfile(name, sizeof(name),
seq->strip->dir, seq->strip->stripdata->name);
BLI_path_abs(name, G.main->name);
-
- seq->anim = openanim(name, IB_rect | ((seq->flag & SEQ_FILTERY) ? IB_animdeinterlace : 0),
- seq->streamindex, seq->strip->colorspace_settings.name);
- if (seq->anim == NULL) {
- return;
+ proxy = seq->strip->proxy;
+
+ use_proxy = proxy && ((proxy->storage & SEQ_STORAGE_PROXY_CUSTOM_DIR) != 0 ||
+ (ed->proxy_storage == SEQ_EDIT_PROXY_DIR_STORAGE));
+
+ if (use_proxy) {
+ if (ed->proxy_storage == SEQ_EDIT_PROXY_DIR_STORAGE) {
+ if (ed->proxy_dir[0] == 0)
+ BLI_strncpy(dir, "//BL_proxy", sizeof(dir));
+ else
+ BLI_strncpy(dir, ed->proxy_dir, sizeof(dir));
+ }
+ else {
+ BLI_strncpy(dir, seq->strip->proxy->dir, sizeof(dir));
+ }
+ BLI_path_abs(dir, G.main->name);
}
- proxy = seq->strip->proxy;
+ if (is_multiview && seq->views_format == R_IMF_VIEWS_INDIVIDUAL) {
+ size_t totfiles = seq_num_files(scene, seq->views_format, true);
+ char prefix[FILE_MAX];
+ const char *ext = NULL;
+ int i;
- if (proxy == NULL) {
- return;
+ BKE_scene_multiview_view_prefix_get(scene, name, prefix, &ext);
+
+ if (prefix[0] != '\0') {
+ for (i = 0; i < totfiles; i++) {
+ const char *suffix = BKE_scene_multiview_view_id_suffix_get(&scene->r, i);
+ char str[FILE_MAX];
+ StripAnim *sanim = MEM_mallocN(sizeof(StripAnim), "Strip Anim");
+
+ BLI_addtail(&seq->anims, sanim);
+
+ BLI_snprintf(str, sizeof(str), "%s%s%s", prefix, suffix, ext);
+
+ if (openfile) {
+ sanim->anim = openanim(
+ str, IB_rect | ((seq->flag & SEQ_FILTERY) ? IB_animdeinterlace : 0),
+ seq->streamindex, seq->strip->colorspace_settings.name);
+ }
+ else {
+ sanim->anim = openanim_noload(
+ str, IB_rect | ((seq->flag & SEQ_FILTERY) ? IB_animdeinterlace : 0),
+ seq->streamindex, seq->strip->colorspace_settings.name);
+ }
+
+ if (sanim->anim) {
+#if 0
+ seq_anim_add_suffix(scene, sanim->anim, i);
+#else
+ /* we already have the suffix */
+ IMB_suffix_anim(sanim->anim, suffix);
+#endif
+ }
+ else {
+ if (openfile) {
+ sanim->anim = openanim(
+ name, IB_rect | ((seq->flag & SEQ_FILTERY) ? IB_animdeinterlace : 0),
+ seq->streamindex, seq->strip->colorspace_settings.name);
+ }
+ else {
+ sanim->anim = openanim_noload(
+ name, IB_rect | ((seq->flag & SEQ_FILTERY) ? IB_animdeinterlace : 0),
+ seq->streamindex, seq->strip->colorspace_settings.name);
+ }
+
+ /* no individual view files - monoscopic, stereo 3d or exr multiview */
+ totfiles = 1;
+ }
+
+ if (sanim->anim && use_proxy) {
+ seq_proxy_index_dir_set(sanim->anim, dir);
+ }
+ }
+ is_multiview_loaded = true;
+ }
}
- if (seq->flag & SEQ_USE_PROXY_CUSTOM_DIR) {
- char dir[FILE_MAX];
- BLI_strncpy(dir, seq->strip->proxy->dir, sizeof(dir));
- BLI_path_abs(dir, G.main->name);
+ if (is_multiview_loaded == false) {
+ StripAnim *sanim;
+
+ sanim = MEM_mallocN(sizeof(StripAnim), "Strip Anim");
+ BLI_addtail(&seq->anims, sanim);
- IMB_anim_set_index_dir(seq->anim, dir);
+ if (openfile) {
+ sanim->anim = openanim(
+ name, IB_rect | ((seq->flag & SEQ_FILTERY) ? IB_animdeinterlace : 0),
+ seq->streamindex, seq->strip->colorspace_settings.name);
+ }
+ else {
+ sanim->anim = openanim_noload(
+ name, IB_rect | ((seq->flag & SEQ_FILTERY) ? IB_animdeinterlace : 0),
+ seq->streamindex, seq->strip->colorspace_settings.name);
+ }
+
+ if (sanim->anim && use_proxy) {
+ seq_proxy_index_dir_set(sanim->anim, dir);
+ }
}
}
-
-static bool seq_proxy_get_fname(Sequence *seq, int cfra, int render_size, char *name)
+static bool seq_proxy_get_fname(Editing *ed, Sequence *seq, int cfra, int render_size, char *name, const size_t view_id)
{
int frameno;
char dir[PROXY_MAXFILE];
+ StripAnim *sanim;
+ char suffix[24] = {'\0'};
- if (!seq->strip->proxy) {
+ StripProxy *proxy = seq->strip->proxy;
+ if (!proxy) {
return false;
}
@@ -1369,20 +1581,53 @@ static bool seq_proxy_get_fname(Sequence *seq, int cfra, int render_size, char *
* have both, a directory full of jpeg files and proxy avis, so
* sorry folks, please rebuild your proxies... */
- if (seq->flag & (SEQ_USE_PROXY_CUSTOM_DIR | SEQ_USE_PROXY_CUSTOM_FILE)) {
+ sanim = BLI_findlink(&seq->anims, view_id);
+
+ if (ed->proxy_storage == SEQ_EDIT_PROXY_DIR_STORAGE) {
+ char fname[FILE_MAXFILE];
+ if (ed->proxy_dir[0] == 0)
+ BLI_strncpy(dir, "//BL_proxy", sizeof(dir));
+ else
+ BLI_strncpy(dir, ed->proxy_dir, sizeof(dir));
+
+ if (sanim && sanim->anim) {
+ IMB_anim_get_fname(sanim->anim, fname, FILE_MAXFILE);
+ }
+ else if (seq->type == SEQ_TYPE_IMAGE) {
+ fname[0] = 0;
+ }
+ BLI_path_append(dir, sizeof(dir), fname);
+ BLI_path_abs(name, G.main->name);
+ }
+ else if ((proxy->storage & SEQ_STORAGE_PROXY_CUSTOM_DIR) && (proxy->storage & SEQ_STORAGE_PROXY_CUSTOM_FILE)) {
BLI_strncpy(dir, seq->strip->proxy->dir, sizeof(dir));
}
+ else if (sanim && sanim->anim && (proxy->storage & SEQ_STORAGE_PROXY_CUSTOM_DIR)) {
+ char fname[FILE_MAXFILE];
+ BLI_strncpy(dir, seq->strip->proxy->dir, sizeof(dir));
+ IMB_anim_get_fname(sanim->anim, fname, FILE_MAXFILE);
+ BLI_path_append(dir, sizeof(dir), fname);
+ }
else if (seq->type == SEQ_TYPE_IMAGE) {
- BLI_snprintf(dir, PROXY_MAXFILE, "%s/BL_proxy", seq->strip->dir);
+ if (proxy->storage & SEQ_STORAGE_PROXY_CUSTOM_DIR)
+ BLI_strncpy(dir, seq->strip->proxy->dir, sizeof(dir));
+ else
+ BLI_snprintf(dir, PROXY_MAXFILE, "%s/BL_proxy", seq->strip->dir);
}
else {
return false;
}
- if (seq->flag & SEQ_USE_PROXY_CUSTOM_FILE) {
+ if (view_id > 0)
+ BLI_snprintf(suffix, sizeof(suffix), "_%zu", view_id);
+
+ if (proxy->storage & SEQ_STORAGE_PROXY_CUSTOM_FILE && sanim && sanim->anim &&
+ ed->proxy_storage != SEQ_EDIT_PROXY_DIR_STORAGE)
+ {
BLI_join_dirfile(name, PROXY_MAXFILE,
- dir, seq->strip->proxy->file);
+ dir, proxy->file);
BLI_path_abs(name, G.main->name);
+ BLI_snprintf(name, PROXY_MAXFILE, "%s_%s", name, suffix);
return true;
}
@@ -1390,13 +1635,13 @@ static bool seq_proxy_get_fname(Sequence *seq, int cfra, int render_size, char *
/* generate a separate proxy directory for each preview size */
if (seq->type == SEQ_TYPE_IMAGE) {
- BLI_snprintf(name, PROXY_MAXFILE, "%s/images/%d/%s_proxy", dir, render_size,
- BKE_sequencer_give_stripelem(seq, cfra)->name);
+ BLI_snprintf(name, PROXY_MAXFILE, "%s/images/%d/%s_proxy%s", dir, render_size,
+ BKE_sequencer_give_stripelem(seq, cfra)->name, suffix);
frameno = 1;
}
else {
frameno = (int)give_stripelem_index(seq, cfra) + seq->anim_startofs;
- BLI_snprintf(name, PROXY_MAXFILE, "%s/proxy_misc/%d/####", dir, render_size);
+ BLI_snprintf(name, PROXY_MAXFILE, "%s/proxy_misc/%d/####%s", dir, render_size, suffix);
}
BLI_path_abs(name, G.main->name);
@@ -1413,45 +1658,48 @@ static ImBuf *seq_proxy_fetch(const SeqRenderData *context, Sequence *seq, int c
IMB_Proxy_Size psize = seq_rendersize_to_proxysize(context->preview_render_size);
int size_flags;
int render_size = context->preview_render_size;
+ StripProxy *proxy = seq->strip->proxy;
+ Editing *ed = context->scene->ed;
+ StripAnim *sanim;
+
+ if (!(seq->flag & SEQ_USE_PROXY)) {
+ return NULL;
+ }
/* dirty hack to distinguish 100% render size from PROXY_100 */
if (render_size == 99) {
render_size = 100;
}
- if (!(seq->flag & SEQ_USE_PROXY)) {
- return NULL;
- }
-
- size_flags = seq->strip->proxy->build_size_flags;
+ size_flags = proxy->build_size_flags;
/* only use proxies, if they are enabled (even if present!) */
if (psize == IMB_PROXY_NONE || ((size_flags & psize) != psize)) {
return NULL;
}
- if (seq->flag & SEQ_USE_PROXY_CUSTOM_FILE) {
+ if (proxy->storage & SEQ_STORAGE_PROXY_CUSTOM_FILE) {
int frameno = (int)give_stripelem_index(seq, cfra) + seq->anim_startofs;
- if (seq->strip->proxy->anim == NULL) {
- if (seq_proxy_get_fname(seq, cfra, render_size, name) == 0) {
+ if (proxy->anim == NULL) {
+ if (seq_proxy_get_fname(ed, seq, cfra, render_size, name, context->view_id) == 0) {
return NULL;
}
- /* proxies are generated in default color space */
- seq->strip->proxy->anim = openanim(name, IB_rect, 0, NULL);
+ proxy->anim = openanim(name, IB_rect, 0, seq->strip->colorspace_settings.name);
}
- if (seq->strip->proxy->anim == NULL) {
+ if (proxy->anim == NULL) {
return NULL;
}
- seq_open_anim_file(seq);
+ seq_open_anim_file(context->scene, seq, true);
+ sanim = seq->anims.first;
- frameno = IMB_anim_index_get_frame_index(seq->anim, seq->strip->proxy->tc, frameno);
+ frameno = IMB_anim_index_get_frame_index(sanim ? sanim->anim : NULL, seq->strip->proxy->tc, frameno);
- return IMB_anim_absolute(seq->strip->proxy->anim, frameno, IMB_TC_NONE, IMB_PROXY_NONE);
+ return IMB_anim_absolute(proxy->anim, frameno, IMB_TC_NONE, IMB_PROXY_NONE);
}
- if (seq_proxy_get_fname(seq, cfra, render_size, name) == 0) {
+ if (seq_proxy_get_fname(ed, seq, cfra, render_size, name, context->view_id) == 0) {
return NULL;
}
@@ -1468,31 +1716,44 @@ static ImBuf *seq_proxy_fetch(const SeqRenderData *context, Sequence *seq, int c
}
}
-static void seq_proxy_build_frame(const SeqRenderData *context, Sequence *seq, int cfra, int proxy_render_size)
+static void seq_proxy_build_frame(const SeqRenderData *context, Sequence *seq, int cfra,
+ int proxy_render_size, const bool overwrite)
{
char name[PROXY_MAXFILE];
int quality;
int rectx, recty;
int ok;
- ImBuf *ibuf;
+ ImBuf *ibuf_tmp, *ibuf;
+ Editing *ed = context->scene->ed;
- if (!seq_proxy_get_fname(seq, cfra, proxy_render_size, name)) {
+ if (!seq_proxy_get_fname(ed, seq, cfra, proxy_render_size, name, context->view_id)) {
return;
}
- ibuf = seq_render_strip(context, seq, cfra);
+ if (!overwrite && BLI_exists(name)) {
+ return;
+ }
+
+ ibuf_tmp = seq_render_strip(context, seq, cfra);
- rectx = (proxy_render_size * ibuf->x) / 100;
- recty = (proxy_render_size * ibuf->y) / 100;
+ rectx = (proxy_render_size * ibuf_tmp->x) / 100;
+ recty = (proxy_render_size * ibuf_tmp->y) / 100;
- if (ibuf->x != rectx || ibuf->y != recty) {
+ if (ibuf_tmp->x != rectx || ibuf_tmp->y != recty) {
+ ibuf = IMB_dupImBuf(ibuf_tmp);
+ IMB_metadata_copy(ibuf, ibuf_tmp);
+ IMB_freeImBuf(ibuf_tmp);
IMB_scalefastImBuf(ibuf, (short)rectx, (short)recty);
}
+ else {
+ ibuf = ibuf_tmp;
+ }
/* depth = 32 is intentionally left in, otherwise ALPHA channels
* won't work... */
quality = seq->strip->proxy->quality;
- ibuf->ftype = JPG | quality;
+ ibuf->ftype = IMB_FTYPE_JPG;
+ ibuf->foptions.quality = quality;
/* unsupported feature only confuses other s/w */
if (ibuf->planes == 32)
@@ -1508,46 +1769,138 @@ static void seq_proxy_build_frame(const SeqRenderData *context, Sequence *seq, i
IMB_freeImBuf(ibuf);
}
-SeqIndexBuildContext *BKE_sequencer_proxy_rebuild_context(Main *bmain, Scene *scene, Sequence *seq)
+/* returns whether the file this context would read from even exist, if not, don't create the context
+*/
+static bool seq_proxy_multiview_context_invalid(Sequence *seq, Scene *scene, const size_t view_id)
+{
+ if ((scene->r.scemode & R_MULTIVIEW) == 0)
+ return false;
+
+ if ((seq->type == SEQ_TYPE_IMAGE) && (seq->views_format == R_IMF_VIEWS_INDIVIDUAL)) {
+ static char prefix[FILE_MAX];
+ static const char *ext = NULL;
+ char str[FILE_MAX];
+
+ if (view_id == 0) {
+ char path[FILE_MAX];
+ BLI_join_dirfile(path, sizeof(path), seq->strip->dir,
+ seq->strip->stripdata->name);
+ BLI_path_abs(path, G.main->name);
+ BKE_scene_multiview_view_prefix_get(scene, path, prefix, &ext);
+ }
+ else {
+ prefix[0] = '\0';
+ }
+
+ if (prefix[0] == '\0')
+ return view_id != 0;
+
+ seq_multiview_name(scene, view_id, prefix, ext, str, FILE_MAX);
+
+ if (BLI_access(str, R_OK) == 0)
+ return false;
+ else
+ return view_id != 0;
+ }
+ return false;
+}
+
+/** This returns the maximum possible number of required contexts
+*/
+static size_t seq_proxy_context_count(Sequence *seq, Scene *scene)
+{
+ size_t num_views = 1;
+
+ if ((scene->r.scemode & R_MULTIVIEW) == 0)
+ return 1;
+
+ switch (seq->type) {
+ case SEQ_TYPE_MOVIE:
+ {
+ num_views = BLI_listbase_count(&seq->anims);
+ break;
+ }
+ case SEQ_TYPE_IMAGE:
+ {
+ switch (seq->views_format) {
+ case R_IMF_VIEWS_INDIVIDUAL:
+ num_views = BKE_scene_multiview_num_views_get(&scene->r);
+ break;
+ case R_IMF_VIEWS_STEREO_3D:
+ num_views = 2;
+ break;
+ case R_IMF_VIEWS_MULTIVIEW:
+ /* not supported at the moment */
+ /* pass through */
+ default:
+ num_views = 1;
+ }
+ break;
+ }
+ }
+
+ return num_views;
+}
+
+void BKE_sequencer_proxy_rebuild_context(Main *bmain, Scene *scene, Sequence *seq, struct GSet *file_list, ListBase *queue)
{
SeqIndexBuildContext *context;
Sequence *nseq;
+ LinkData *link;
+ size_t i;
+ size_t num_files;
if (!seq->strip || !seq->strip->proxy) {
- return NULL;
+ return;
}
if (!(seq->flag & SEQ_USE_PROXY)) {
- return NULL;
+ return;
}
- context = MEM_callocN(sizeof(SeqIndexBuildContext), "seq proxy rebuild context");
+ num_files = seq_proxy_context_count(seq, scene);
+
+ for (i = 0; i < num_files; i++) {
+ if (seq_proxy_multiview_context_invalid(seq, scene, i))
+ continue;
- nseq = BKE_sequence_dupli_recursive(scene, scene, seq, 0);
+ context = MEM_callocN(sizeof(SeqIndexBuildContext), "seq proxy rebuild context");
- context->tc_flags = nseq->strip->proxy->build_tc_flags;
- context->size_flags = nseq->strip->proxy->build_size_flags;
- context->quality = nseq->strip->proxy->quality;
+ nseq = BKE_sequence_dupli_recursive(scene, scene, seq, 0);
- context->bmain = bmain;
- context->scene = scene;
- context->orig_seq = seq;
- context->seq = nseq;
+ context->tc_flags = nseq->strip->proxy->build_tc_flags;
+ context->size_flags = nseq->strip->proxy->build_size_flags;
+ context->quality = nseq->strip->proxy->quality;
+ context->overwrite = (nseq->strip->proxy->build_flags & SEQ_PROXY_SKIP_EXISTING) == 0;
- if (nseq->type == SEQ_TYPE_MOVIE) {
- seq_open_anim_file(nseq);
+ context->bmain = bmain;
+ context->scene = scene;
+ context->orig_seq = seq;
+ context->seq = nseq;
- if (nseq->anim) {
- context->index_context = IMB_anim_index_rebuild_context(nseq->anim,
- context->tc_flags, context->size_flags, context->quality);
+ context->view_id = i; /* only for images */
+
+ link = BLI_genericNodeN(context);
+ BLI_addtail(queue, link);
+
+ if (nseq->type == SEQ_TYPE_MOVIE) {
+ StripAnim *sanim;
+
+ seq_open_anim_file(scene, nseq, true);
+ sanim = BLI_findlink(&nseq->anims, i);
+
+ if (sanim->anim) {
+ context->index_context = IMB_anim_index_rebuild_context(sanim->anim,
+ context->tc_flags, context->size_flags, context->quality,
+ context->overwrite, file_list);
+ }
}
}
-
- return context;
}
void BKE_sequencer_proxy_rebuild(SeqIndexBuildContext *context, short *stop, short *do_update, float *progress)
{
+ const bool overwrite = context->overwrite;
SeqRenderData render_context;
Sequence *seq = context->seq;
Scene *scene = context->scene;
@@ -1567,30 +1920,34 @@ void BKE_sequencer_proxy_rebuild(SeqIndexBuildContext *context, short *stop, sho
}
/* that's why it is called custom... */
- if (seq->flag & SEQ_USE_PROXY_CUSTOM_FILE) {
+ if (seq->strip->proxy && seq->strip->proxy->storage & SEQ_STORAGE_PROXY_CUSTOM_FILE) {
return;
}
/* fail safe code */
- render_context = BKE_sequencer_new_render_data(bmain->eval_ctx, bmain, context->scene,
- (scene->r.size * (float) scene->r.xsch) / 100.0f + 0.5f,
- (scene->r.size * (float) scene->r.ysch) / 100.0f + 0.5f, 100);
+ BKE_sequencer_new_render_data(
+ bmain->eval_ctx, bmain, context->scene,
+ (scene->r.size * (float) scene->r.xsch) / 100.0f + 0.5f,
+ (scene->r.size * (float) scene->r.ysch) / 100.0f + 0.5f, 100,
+ &render_context);
+
render_context.skip_cache = true;
render_context.is_proxy_render = true;
+ render_context.view_id = context->view_id;
for (cfra = seq->startdisp + seq->startstill; cfra < seq->enddisp - seq->endstill; cfra++) {
if (context->size_flags & IMB_PROXY_25) {
- seq_proxy_build_frame(&render_context, seq, cfra, 25);
+ seq_proxy_build_frame(&render_context, seq, cfra, 25, overwrite);
}
if (context->size_flags & IMB_PROXY_50) {
- seq_proxy_build_frame(&render_context, seq, cfra, 50);
+ seq_proxy_build_frame(&render_context, seq, cfra, 50, overwrite);
}
if (context->size_flags & IMB_PROXY_75) {
- seq_proxy_build_frame(&render_context, seq, cfra, 75);
+ seq_proxy_build_frame(&render_context, seq, cfra, 75, overwrite);
}
if (context->size_flags & IMB_PROXY_100) {
- seq_proxy_build_frame(&render_context, seq, cfra, 100);
+ seq_proxy_build_frame(&render_context, seq, cfra, 100, overwrite);
}
*progress = (float) (cfra - seq->startdisp - seq->startstill) / (seq->enddisp - seq->endstill - seq->startdisp - seq->startstill);
@@ -1604,8 +1961,14 @@ void BKE_sequencer_proxy_rebuild(SeqIndexBuildContext *context, short *stop, sho
void BKE_sequencer_proxy_rebuild_finish(SeqIndexBuildContext *context, bool stop)
{
if (context->index_context) {
- IMB_close_anim_proxies(context->seq->anim);
- IMB_close_anim_proxies(context->orig_seq->anim);
+ StripAnim *sanim;
+
+ for (sanim = context->seq->anims.first; sanim; sanim = sanim->next)
+ IMB_close_anim_proxies(sanim->anim);
+
+ for (sanim = context->orig_seq->anims.first; sanim; sanim = sanim->next)
+ IMB_close_anim_proxies(sanim->anim);
+
IMB_anim_index_rebuild_finish(context->index_context, stop);
}
@@ -1614,6 +1977,22 @@ void BKE_sequencer_proxy_rebuild_finish(SeqIndexBuildContext *context, bool stop
MEM_freeN(context);
}
+void BKE_sequencer_proxy_set(struct Sequence *seq, bool value)
+{
+ if (value) {
+ seq->flag |= SEQ_USE_PROXY;
+ if (seq->strip->proxy == NULL) {
+ seq->strip->proxy = MEM_callocN(sizeof(struct StripProxy), "StripProxy");
+ seq->strip->proxy->quality = 90;
+ seq->strip->proxy->build_tc_flags = SEQ_PROXY_TC_ALL;
+ seq->strip->proxy->build_size_flags = SEQ_PROXY_IMAGE_SIZE_25;
+ }
+ }
+ else {
+ seq->flag ^= SEQ_USE_PROXY;
+ }
+}
+
/*********************** color balance *************************/
static StripColorBalance calc_cb(StripColorBalance *cb_)
@@ -1868,7 +2247,10 @@ static void *color_balance_do_thread(void *thread_data_v)
return NULL;
}
-ImBuf *BKE_sequencer_render_mask_input(const SeqRenderData *context, int mask_input_type, Sequence *mask_sequence, Mask *mask_id, int cfra, bool make_float)
+/* cfra is offset by fra_offset only in case we are using a real mask. */
+ImBuf *BKE_sequencer_render_mask_input(
+ const SeqRenderData *context, int mask_input_type, Sequence *mask_sequence, Mask *mask_id,
+ int cfra, int fra_offset, bool make_float)
{
ImBuf *mask_input = NULL;
@@ -1887,7 +2269,7 @@ ImBuf *BKE_sequencer_render_mask_input(const SeqRenderData *context, int mask_in
}
}
else if (mask_input_type == SEQUENCE_MASK_INPUT_ID) {
- mask_input = seq_render_mask(context, mask_id, cfra, make_float);
+ mask_input = seq_render_mask(context, mask_id, cfra - fra_offset, make_float);
}
return mask_input;
@@ -2047,6 +2429,7 @@ static ImBuf *input_preprocess(const SeqRenderData *context, Sequence *seq, floa
IMB_rectcpy(i, ibuf, t.xofs, t.yofs, c.left, c.bottom, sx, sy);
sequencer_imbuf_assign_spaces(scene, i);
+ IMB_metadata_copy(i, ibuf);
IMB_freeImBuf(ibuf);
ibuf = i;
@@ -2098,6 +2481,7 @@ static ImBuf *input_preprocess(const SeqRenderData *context, Sequence *seq, floa
ImBuf *ibuf_new = BKE_sequence_modifier_apply_stack(context, seq, ibuf, cfra);
if (ibuf_new != ibuf) {
+ IMB_metadata_copy(ibuf_new, ibuf);
IMB_freeImBuf(ibuf);
ibuf = ibuf_new;
}
@@ -2120,6 +2504,7 @@ static ImBuf *copy_from_ibuf_still(const SeqRenderData *context, Sequence *seq,
if (ibuf) {
rval = IMB_dupImBuf(ibuf);
+ IMB_metadata_copy(rval, ibuf);
IMB_freeImBuf(ibuf);
}
@@ -2133,9 +2518,11 @@ static void copy_to_ibuf_still(const SeqRenderData *context, Sequence *seq, floa
/* we have to store a copy, since the passed ibuf
* could be preprocessed afterwards (thereby silently
* changing the cached image... */
- ibuf = IMB_dupImBuf(ibuf);
+ ImBuf *oibuf = ibuf;
+ ibuf = IMB_dupImBuf(oibuf);
if (ibuf) {
+ IMB_metadata_copy(ibuf, oibuf);
sequencer_imbuf_assign_spaces(context->scene, ibuf);
}
@@ -2331,6 +2718,237 @@ static ImBuf *seq_render_effect_strip_impl(const SeqRenderData *context, Sequenc
return out;
}
+static ImBuf *seq_render_image_strip(const SeqRenderData *context, Sequence *seq, float nr, float cfra)
+{
+ ImBuf *ibuf = NULL;
+ char name[FILE_MAX];
+ bool is_multiview = (seq->flag & SEQ_USE_VIEWS) != 0 &&
+ (context->scene->r.scemode & R_MULTIVIEW) != 0;
+ StripElem *s_elem = BKE_sequencer_give_stripelem(seq, cfra);
+ int flag;
+
+ if (s_elem) {
+ BLI_join_dirfile(name, sizeof(name), seq->strip->dir, s_elem->name);
+ BLI_path_abs(name, G.main->name);
+ }
+
+ flag = IB_rect | IB_metadata;
+ if (seq->alpha_mode == SEQ_ALPHA_PREMUL)
+ flag |= IB_alphamode_premul;
+
+ if (!s_elem) {
+ /* don't do anything */
+ }
+ else if (is_multiview) {
+ size_t totfiles = seq_num_files(context->scene, seq->views_format, true);
+ size_t totviews;
+ struct ImBuf **ibufs_arr;
+ char prefix[FILE_MAX];
+ const char *ext = NULL;
+ int i;
+
+ if (totfiles > 1) {
+ BKE_scene_multiview_view_prefix_get(context->scene, name, prefix, &ext);
+ if (prefix[0] == '\0') {
+ goto monoview_image;
+ }
+ }
+ else {
+ prefix[0] = '\0';
+ }
+
+ totviews = BKE_scene_multiview_num_views_get(&context->scene->r);
+ ibufs_arr = MEM_callocN(sizeof(ImBuf *) * totviews, "Sequence Image Views Imbufs");
+
+ for (i = 0; i < totfiles; i++) {
+
+ if (prefix[0] == '\0') {
+ ibufs_arr[i] = IMB_loadiffname(name, flag, seq->strip->colorspace_settings.name);
+ }
+ else {
+ char str[FILE_MAX];
+ seq_multiview_name(context->scene, i, prefix, ext, str, FILE_MAX);
+ ibufs_arr[i] = IMB_loadiffname(str, flag, seq->strip->colorspace_settings.name);
+ }
+
+ if (ibufs_arr[i]) {
+ /* we don't need both (speed reasons)! */
+ if (ibufs_arr[i]->rect_float && ibufs_arr[i]->rect)
+ imb_freerectImBuf(ibufs_arr[i]);
+ }
+ }
+
+ if (seq->views_format == R_IMF_VIEWS_STEREO_3D && ibufs_arr[0])
+ IMB_ImBufFromStereo3d(seq->stereo3d_format, ibufs_arr[0], &ibufs_arr[0], &ibufs_arr[1]);
+
+ for (i = 0; i < totviews; i++) {
+ if (ibufs_arr[i]) {
+ SeqRenderData localcontext = *context;
+ localcontext.view_id = i;
+
+ /* all sequencer color is done in SRGB space, linear gives odd crossfades */
+ BKE_sequencer_imbuf_to_sequencer_space(context->scene, ibufs_arr[i], false);
+
+ if (i != context->view_id) {
+ copy_to_ibuf_still(&localcontext, seq, nr, ibufs_arr[i]);
+ BKE_sequencer_cache_put(&localcontext, seq, cfra, SEQ_STRIPELEM_IBUF, ibufs_arr[i]);
+ }
+ }
+ }
+
+ /* return the original requested ImBuf */
+ ibuf = ibufs_arr[context->view_id];
+ if (ibuf) {
+ s_elem->orig_width = ibufs_arr[0]->x;
+ s_elem->orig_height = ibufs_arr[0]->y;
+ }
+
+ /* "remove" the others (decrease their refcount) */
+ for (i = 0; i < totviews; i++) {
+ if (ibufs_arr[i] != ibuf) {
+ IMB_freeImBuf(ibufs_arr[i]);
+ }
+ }
+
+ MEM_freeN(ibufs_arr);
+ }
+ else {
+monoview_image:
+ if ((ibuf = IMB_loadiffname(name, flag, seq->strip->colorspace_settings.name))) {
+ /* we don't need both (speed reasons)! */
+ if (ibuf->rect_float && ibuf->rect)
+ imb_freerectImBuf(ibuf);
+
+ /* all sequencer color is done in SRGB space, linear gives odd crossfades */
+ BKE_sequencer_imbuf_to_sequencer_space(context->scene, ibuf, false);
+
+ s_elem->orig_width = ibuf->x;
+ s_elem->orig_height = ibuf->y;
+ }
+ }
+
+ return ibuf;
+}
+
+static ImBuf *seq_render_movie_strip(const SeqRenderData *context, Sequence *seq, float nr, float cfra)
+{
+ ImBuf *ibuf = NULL;
+ StripAnim *sanim;
+ bool is_multiview = (seq->flag & SEQ_USE_VIEWS) != 0 &&
+ (context->scene->r.scemode & R_MULTIVIEW) != 0;
+
+ /* load all the videos */
+ seq_open_anim_file(context->scene, seq, false);
+
+ if (is_multiview) {
+ ImBuf **ibuf_arr;
+ size_t totviews;
+ size_t totfiles = seq_num_files(context->scene, seq->views_format, true);
+ int i;
+
+ if (totfiles != BLI_listbase_count_ex(&seq->anims, totfiles + 1))
+ goto monoview_movie;
+
+ totviews = BKE_scene_multiview_num_views_get(&context->scene->r);
+ ibuf_arr = MEM_callocN(sizeof(ImBuf *) * totviews, "Sequence Image Views Imbufs");
+
+ for (i = 0, sanim = seq->anims.first; sanim; sanim = sanim->next, i++) {
+ if (sanim->anim) {
+ IMB_Proxy_Size proxy_size = seq_rendersize_to_proxysize(context->preview_render_size);
+ IMB_anim_set_preseek(sanim->anim, seq->anim_preseek);
+
+ ibuf_arr[i] = IMB_anim_absolute(sanim->anim, nr + seq->anim_startofs,
+ seq->strip->proxy ? seq->strip->proxy->tc : IMB_TC_RECORD_RUN,
+ proxy_size);
+
+ /* fetching for requested proxy size failed, try fetching the original instead */
+ if (!ibuf_arr[i] && proxy_size != IMB_PROXY_NONE) {
+ ibuf_arr[i] = IMB_anim_absolute(sanim->anim, nr + seq->anim_startofs,
+ seq->strip->proxy ? seq->strip->proxy->tc : IMB_TC_RECORD_RUN,
+ IMB_PROXY_NONE);
+ }
+ if (ibuf_arr[i]) {
+ /* we don't need both (speed reasons)! */
+ if (ibuf_arr[i]->rect_float && ibuf_arr[i]->rect)
+ imb_freerectImBuf(ibuf_arr[i]);
+ }
+ }
+ }
+
+ if (seq->views_format == R_IMF_VIEWS_STEREO_3D) {
+ if (ibuf_arr[0]) {
+ IMB_ImBufFromStereo3d(seq->stereo3d_format, ibuf_arr[0], &ibuf_arr[0], &ibuf_arr[1]);
+ }
+ else {
+ /* probably proxy hasn't been created yet */
+ MEM_freeN(ibuf_arr);
+ return NULL;
+ }
+ }
+
+ for (i = 0; i < totviews; i++) {
+ SeqRenderData localcontext = *context;
+ localcontext.view_id = i;
+
+ if (ibuf_arr[i]) {
+ /* all sequencer color is done in SRGB space, linear gives odd crossfades */
+ BKE_sequencer_imbuf_to_sequencer_space(context->scene, ibuf_arr[i], false);
+ }
+ if (i != context->view_id) {
+ copy_to_ibuf_still(&localcontext, seq, nr, ibuf_arr[i]);
+ BKE_sequencer_cache_put(&localcontext, seq, cfra, SEQ_STRIPELEM_IBUF, ibuf_arr[i]);
+ }
+ }
+
+ /* return the original requested ImBuf */
+ ibuf = ibuf_arr[context->view_id];
+ if (ibuf) {
+ seq->strip->stripdata->orig_width = ibuf->x;
+ seq->strip->stripdata->orig_height = ibuf->y;
+ }
+
+ /* "remove" the others (decrease their refcount) */
+ for (i = 0; i < totviews; i++) {
+ if (ibuf_arr[i] != ibuf) {
+ IMB_freeImBuf(ibuf_arr[i]);
+ }
+ }
+
+ MEM_freeN(ibuf_arr);
+ }
+ else {
+monoview_movie:
+ sanim = seq->anims.first;
+ if (sanim && sanim->anim) {
+ IMB_Proxy_Size proxy_size = seq_rendersize_to_proxysize(context->preview_render_size);
+ IMB_anim_set_preseek(sanim->anim, seq->anim_preseek);
+
+ ibuf = IMB_anim_absolute(sanim->anim, nr + seq->anim_startofs,
+ seq->strip->proxy ? seq->strip->proxy->tc : IMB_TC_RECORD_RUN,
+ proxy_size);
+
+ /* fetching for requested proxy size failed, try fetching the original instead */
+ if (!ibuf && proxy_size != IMB_PROXY_NONE) {
+ ibuf = IMB_anim_absolute(sanim->anim, nr + seq->anim_startofs,
+ seq->strip->proxy ? seq->strip->proxy->tc : IMB_TC_RECORD_RUN,
+ IMB_PROXY_NONE);
+ }
+ if (ibuf) {
+ BKE_sequencer_imbuf_to_sequencer_space(context->scene, ibuf, false);
+
+ /* we don't need both (speed reasons)! */
+ if (ibuf->rect_float && ibuf->rect) {
+ imb_freerectImBuf(ibuf);
+ }
+
+ seq->strip->stripdata->orig_width = ibuf->x;
+ seq->strip->stripdata->orig_height = ibuf->y;
+ }
+ }
+ }
+ return ibuf;
+}
+
static ImBuf *seq_render_movieclip_strip(const SeqRenderData *context, Sequence *seq, float nr)
{
ImBuf *ibuf = NULL;
@@ -2462,13 +3080,20 @@ static ImBuf *seq_render_mask_strip(const SeqRenderData *context, Sequence *seq,
return seq_render_mask(context, seq->mask, nr, make_float);
}
-static ImBuf *seq_render_scene_strip(const SeqRenderData *context, Sequence *seq, float nr)
+static ImBuf *seq_render_scene_strip(const SeqRenderData *context, Sequence *seq, float nr, float cfra)
{
ImBuf *ibuf = NULL;
- float frame;
- float oldcfra;
+ double frame;
Object *camera;
- ListBase oldmarkers;
+
+ struct {
+ int scemode;
+ int cfra;
+ float subframe;
+#ifdef DURIAN_CAMERA_SWITCH
+ ListBase markers;
+#endif
+ } orig_data;
/* Old info:
* Hack! This function can be called from do_render_seq(), in that case
@@ -2506,9 +3131,11 @@ static ImBuf *seq_render_scene_strip(const SeqRenderData *context, Sequence *seq
const bool do_seq_gl = is_rendering ?
0 /* (context->scene->r.seq_flag & R_SEQ_GL_REND) */ :
(context->scene->r.seq_flag & R_SEQ_GL_PREV) != 0;
- int do_seq;
// bool have_seq = false; /* UNUSED */
bool have_comp = false;
+ bool use_gpencil = true;
+ /* do we need to re-evaluate the frame after rendering? */
+ bool is_frame_update = false;
Scene *scene;
int is_thread_main = BLI_thread_is_main();
@@ -2518,13 +3145,19 @@ static ImBuf *seq_render_scene_strip(const SeqRenderData *context, Sequence *seq
}
scene = seq->scene;
- frame = scene->r.sfra + nr + seq->anim_startofs;
+ frame = (double)scene->r.sfra + (double)nr + (double)seq->anim_startofs;
// have_seq = (scene->r.scemode & R_DOSEQ) && scene->ed && scene->ed->seqbase.first); /* UNUSED */
have_comp = (scene->r.scemode & R_DOCOMP) && scene->use_nodes && scene->nodetree;
- oldcfra = scene->r.cfra;
- scene->r.cfra = frame;
+ orig_data.scemode = scene->r.scemode;
+ orig_data.cfra = scene->r.cfra;
+ orig_data.subframe = scene->r.subframe;
+#ifdef DURIAN_CAMERA_SWITCH
+ orig_data.markers = scene->markers;
+#endif
+
+ BKE_scene_frame_set(scene, frame);
if (seq->scene_camera) {
camera = seq->scene_camera;
@@ -2533,28 +3166,30 @@ static ImBuf *seq_render_scene_strip(const SeqRenderData *context, Sequence *seq
BKE_scene_camera_switch_update(scene);
camera = scene->camera;
}
-
+
if (have_comp == false && camera == NULL) {
- scene->r.cfra = oldcfra;
- return NULL;
+ goto finally;
+ }
+
+ if (seq->flag & SEQ_SCENE_NO_GPENCIL) {
+ use_gpencil = false;
}
/* prevent eternal loop */
- do_seq = scene->r.scemode & R_DOSEQ;
scene->r.scemode &= ~R_DOSEQ;
#ifdef DURIAN_CAMERA_SWITCH
/* stooping to new low's in hackyness :( */
- oldmarkers = scene->markers;
BLI_listbase_clear(&scene->markers);
-#else
- (void)oldmarkers;
#endif
+ is_frame_update = (orig_data.cfra != scene->r.cfra) || (orig_data.subframe != scene->r.subframe);
+
if ((sequencer_view3d_cb && do_seq_gl && camera) && is_thread_main) {
char err_out[256] = "unknown";
int width = (scene->r.xsch * scene->r.size) / 100;
int height = (scene->r.ysch * scene->r.size) / 100;
+ const char *viewname = BKE_scene_multiview_render_view_name_get(&scene->r, context->view_id);
/* for old scened this can be uninitialized,
* should probably be added to do_versions at some point if the functionality stays */
@@ -2566,14 +3201,18 @@ static ImBuf *seq_render_scene_strip(const SeqRenderData *context, Sequence *seq
ibuf = sequencer_view3d_cb(scene, camera, width, height, IB_rect,
context->scene->r.seq_prev_type,
(context->scene->r.seq_flag & R_SEQ_SOLID_TEX) != 0,
- true, scene->r.alphamode, err_out);
+ use_gpencil, true, scene->r.alphamode, viewname, err_out);
if (ibuf == NULL) {
fprintf(stderr, "seq_render_scene_strip failed to get opengl buffer: %s\n", err_out);
}
}
else {
Render *re = RE_GetRender(scene->id.name);
- RenderResult rres;
+ size_t totviews = BKE_scene_multiview_num_views_get(&scene->r);
+ int i;
+ ImBuf **ibufs_arr;
+
+ ibufs_arr = MEM_callocN(sizeof(ImBuf *) * totviews, "Sequence Image Views Imbufs");
/* XXX: this if can be removed when sequence preview rendering uses the job system
*
@@ -2583,7 +3222,7 @@ static ImBuf *seq_render_scene_strip(const SeqRenderData *context, Sequence *seq
* When rendering from command line renderer is called from main thread, in this
* case it's always safe to render scene here
*/
- if (!is_thread_main || is_rendering == false || is_background) {
+ if (!is_thread_main || is_rendering == false || is_background || context->eval_ctx->mode == DAG_EVAL_RENDER) {
if (re == NULL)
re = RE_NewRender(scene->id.name);
@@ -2593,42 +3232,68 @@ static ImBuf *seq_render_scene_strip(const SeqRenderData *context, Sequence *seq
/* restore previous state after it was toggled on & off by RE_BlenderFrame */
G.is_rendering = is_rendering;
}
-
- RE_AcquireResultImage(re, &rres);
-
- if (rres.rectf) {
- ibuf = IMB_allocImBuf(rres.rectx, rres.recty, 32, IB_rectfloat);
- memcpy(ibuf->rect_float, rres.rectf, 4 * sizeof(float) * rres.rectx * rres.recty);
- if (rres.rectz) {
- addzbuffloatImBuf(ibuf);
- memcpy(ibuf->zbuf_float, rres.rectz, sizeof(float) * rres.rectx * rres.recty);
+
+ for (i = 0; i < totviews; i++) {
+ SeqRenderData localcontext = *context;
+ RenderResult rres;
+
+ localcontext.view_id = i;
+
+ RE_AcquireResultImage(re, &rres, i);
+
+ if (rres.rectf) {
+ ibufs_arr[i] = IMB_allocImBuf(rres.rectx, rres.recty, 32, IB_rectfloat);
+ memcpy(ibufs_arr[i]->rect_float, rres.rectf, 4 * sizeof(float) * rres.rectx * rres.recty);
+
+ if (rres.rectz) {
+ addzbuffloatImBuf(ibufs_arr[i]);
+ memcpy(ibufs_arr[i]->zbuf_float, rres.rectz, sizeof(float) * rres.rectx * rres.recty);
+ }
+
+ /* float buffers in the sequencer are not linear */
+ BKE_sequencer_imbuf_to_sequencer_space(context->scene, ibufs_arr[i], false);
+ }
+ else if (rres.rect32) {
+ ibufs_arr[i] = IMB_allocImBuf(rres.rectx, rres.recty, 32, IB_rect);
+ memcpy(ibufs_arr[i]->rect, rres.rect32, 4 * rres.rectx * rres.recty);
}
- /* float buffers in the sequencer are not linear */
- BKE_sequencer_imbuf_to_sequencer_space(context->scene, ibuf, false);
+ if (i != context->view_id) {
+ copy_to_ibuf_still(&localcontext, seq, nr, ibufs_arr[i]);
+ BKE_sequencer_cache_put(&localcontext, seq, cfra, SEQ_STRIPELEM_IBUF, ibufs_arr[i]);
+ }
+
+ RE_ReleaseResultImage(re);
}
- else if (rres.rect32) {
- ibuf = IMB_allocImBuf(rres.rectx, rres.recty, 32, IB_rect);
- memcpy(ibuf->rect, rres.rect32, 4 * rres.rectx * rres.recty);
+
+ /* return the original requested ImBuf */
+ ibuf = ibufs_arr[context->view_id];
+
+ /* "remove" the others (decrease their refcount) */
+ for (i = 0; i < totviews; i++) {
+ if (ibufs_arr[i] != ibuf) {
+ IMB_freeImBuf(ibufs_arr[i]);
+ }
}
-
- RE_ReleaseResultImage(re);
-
+ MEM_freeN(ibufs_arr);
+
// BIF_end_render_callbacks();
}
-
+
+
+finally:
/* restore */
- scene->r.scemode |= do_seq;
-
- scene->r.cfra = oldcfra;
+ scene->r.scemode = orig_data.scemode;
+ scene->r.cfra = orig_data.cfra;
+ scene->r.subframe = orig_data.subframe;
- if (frame != oldcfra) {
+ if (is_frame_update) {
BKE_scene_update_for_newframe(context->eval_ctx, context->bmain, scene, scene->lay);
}
-
+
#ifdef DURIAN_CAMERA_SWITCH
/* stooping to new low's in hackyness :( */
- scene->markers = oldmarkers;
+ scene->markers = orig_data.markers;
#endif
return ibuf;
@@ -2640,7 +3305,6 @@ static ImBuf *do_render_strip_uncached(const SeqRenderData *context, Sequence *s
float nr = give_stripelem_index(seq, cfra);
int type = (seq->type & SEQ_TYPE_EFFECT && seq->type != SEQ_TYPE_SPEED) ? SEQ_TYPE_EFFECT : seq->type;
bool use_preprocess = BKE_sequencer_input_have_to_preprocess(context, seq, cfra);
- char name[FILE_MAX];
switch (type) {
case SEQ_TYPE_META:
@@ -2699,57 +3363,14 @@ static ImBuf *do_render_strip_uncached(const SeqRenderData *context, Sequence *s
case SEQ_TYPE_IMAGE:
{
- StripElem *s_elem = BKE_sequencer_give_stripelem(seq, cfra);
- int flag;
-
- if (s_elem) {
- BLI_join_dirfile(name, sizeof(name), seq->strip->dir, s_elem->name);
- BLI_path_abs(name, G.main->name);
- }
-
- flag = IB_rect;
- if (seq->alpha_mode == SEQ_ALPHA_PREMUL)
- flag |= IB_alphamode_premul;
-
- if (s_elem && (ibuf = IMB_loadiffname(name, flag, seq->strip->colorspace_settings.name))) {
- /* we don't need both (speed reasons)! */
- if (ibuf->rect_float && ibuf->rect)
- imb_freerectImBuf(ibuf);
-
- /* all sequencer color is done in SRGB space, linear gives odd crossfades */
- BKE_sequencer_imbuf_to_sequencer_space(context->scene, ibuf, false);
-
- copy_to_ibuf_still(context, seq, nr, ibuf);
-
- s_elem->orig_width = ibuf->x;
- s_elem->orig_height = ibuf->y;
- }
+ ibuf = seq_render_image_strip(context, seq, nr, cfra);
+ copy_to_ibuf_still(context, seq, nr, ibuf);
break;
}
case SEQ_TYPE_MOVIE:
{
- seq_open_anim_file(seq);
-
- if (seq->anim) {
- IMB_anim_set_preseek(seq->anim, seq->anim_preseek);
-
- ibuf = IMB_anim_absolute(seq->anim, nr + seq->anim_startofs,
- seq->strip->proxy ? seq->strip->proxy->tc : IMB_TC_RECORD_RUN,
- seq_rendersize_to_proxysize(context->preview_render_size));
-
- if (ibuf) {
- BKE_sequencer_imbuf_to_sequencer_space(context->scene, ibuf, false);
-
- /* we don't need both (speed reasons)! */
- if (ibuf->rect_float && ibuf->rect) {
- imb_freerectImBuf(ibuf);
- }
-
- seq->strip->stripdata->orig_width = ibuf->x;
- seq->strip->stripdata->orig_height = ibuf->y;
- }
- }
+ ibuf = seq_render_movie_strip(context, seq, nr, cfra);
copy_to_ibuf_still(context, seq, nr, ibuf);
break;
}
@@ -2757,7 +3378,7 @@ static ImBuf *do_render_strip_uncached(const SeqRenderData *context, Sequence *s
case SEQ_TYPE_SCENE:
{
/* scene can be NULL after deletions */
- ibuf = seq_render_scene_strip(context, seq, nr);
+ ibuf = seq_render_scene_strip(context, seq, nr, cfra);
/* Scene strips update all animation, so we need to restore original state.*/
BKE_animsys_evaluate_all_animation(context->bmain, context->scene, cfra);
@@ -2986,6 +3607,8 @@ static ImBuf *seq_render_strip_stack(const SeqRenderData *context, ListBase *seq
out = seq_render_strip_stack_apply_effect(context, seq, cfra, ibuf1, ibuf2);
+ IMB_metadata_copy(out, ibuf2);
+
IMB_freeImBuf(ibuf1);
IMB_freeImBuf(ibuf2);
}
@@ -3080,7 +3703,7 @@ ImBuf *BKE_sequencer_give_ibuf(const SeqRenderData *context, float cfra, int cha
if (ed == NULL) return NULL;
if ((chanshown < 0) && !BLI_listbase_is_empty(&ed->metastack)) {
- int count = BLI_countlist(&ed->metastack);
+ int count = BLI_listbase_count(&ed->metastack);
count = max_ii(count + chanshown, 0);
seqbasep = ((MetaStack *)BLI_findlink(&ed->metastack, count))->oldbasep;
}
@@ -3254,16 +3877,6 @@ ImBuf *BKE_sequencer_give_ibuf_threaded(const SeqRenderData *context, float cfra
return e ? e->ibuf : NULL;
}
-/* Functions to free imbuf and anim data on changes */
-
-static void free_anim_seq(Sequence *seq)
-{
- if (seq->anim) {
- IMB_free_anim(seq->anim);
- seq->anim = NULL;
- }
-}
-
/* check whether sequence cur depends on seq */
bool BKE_sequence_check_depend(Sequence *seq, Sequence *cur)
{
@@ -3315,15 +3928,11 @@ static void sequence_invalidate_cache(Scene *scene, Sequence *seq, bool invalida
/* invalidate cache for current sequence */
if (invalidate_self) {
- if (seq->anim) {
- /* Animation structure holds some buffers inside,
- * so for proper cache invalidation we need to
- * re-open the animation.
- */
- IMB_free_anim(seq->anim);
- seq->anim = NULL;
- }
-
+ /* Animation structure holds some buffers inside,
+ * so for proper cache invalidation we need to
+ * re-open the animation.
+ */
+ BKE_sequence_free_anim(seq);
BKE_sequencer_cache_cleanup_sequence(seq);
}
@@ -3370,7 +3979,7 @@ void BKE_sequencer_free_imbuf(Scene *scene, ListBase *seqbase, bool for_render)
if (seq->strip) {
if (seq->type == SEQ_TYPE_MOVIE) {
- free_anim_seq(seq);
+ BKE_sequence_free_anim(seq);
}
if (seq->type == SEQ_TYPE_SPEED) {
BKE_sequence_effect_speed_rebuild_map(scene, seq, true);
@@ -3395,7 +4004,7 @@ static bool update_changed_seq_recurs(Scene *scene, Sequence *seq, Sequence *cha
/* recurs downwards to see if this seq depends on the changed seq */
if (seq == NULL)
- return 0;
+ return false;
if (seq == changed_seq)
free_imbuf = true;
@@ -3417,7 +4026,7 @@ static bool update_changed_seq_recurs(Scene *scene, Sequence *seq, Sequence *cha
if (free_imbuf) {
if (ibuf_change) {
if (seq->type == SEQ_TYPE_MOVIE)
- free_anim_seq(seq);
+ BKE_sequence_free_anim(seq);
if (seq->type == SEQ_TYPE_SPEED) {
BKE_sequence_effect_speed_rebuild_map(scene, seq, true);
}
@@ -3513,28 +4122,16 @@ bool BKE_sequence_single_check(Sequence *seq)
}
/* check if the selected seq's reference unselected seq's */
-bool BKE_sequence_base_isolated_sel_check(ListBase *seqbase, bool one_only)
+bool BKE_sequence_base_isolated_sel_check(ListBase *seqbase)
{
Sequence *seq;
- /* is there a valid selection select */
+ /* is there more than 1 select */
bool ok = false;
- /* is there one selected already? */
- bool first = false;
for (seq = seqbase->first; seq; seq = seq->next) {
if (seq->flag & SELECT) {
- if (one_only) {
- ok = true;
- break;
- }
- else {
- if (first) {
- ok = true;
- break;
- }
- else
- first = true;
- }
+ ok = true;
+ break;
}
}
@@ -3632,7 +4229,7 @@ void BKE_sequence_single_fix(Sequence *seq)
bool BKE_sequence_tx_test(Sequence *seq)
{
- return (seq->type < SEQ_TYPE_EFFECT) || (BKE_sequence_effect_get_num_inputs(seq->type) == 0);
+ return !(seq->type & SEQ_TYPE_EFFECT) || (BKE_sequence_effect_get_num_inputs(seq->type) == 0);
}
static bool seq_overlap(Sequence *seq1, Sequence *seq2)
@@ -3681,10 +4278,10 @@ void BKE_sequence_sound_init(Scene *scene, Sequence *seq)
}
else {
if (seq->sound) {
- seq->scene_sound = sound_add_scene_sound_defaults(scene, seq);
+ seq->scene_sound = BKE_sound_add_scene_sound_defaults(scene, seq);
}
if (seq->scene) {
- seq->scene_sound = sound_scene_add_scene_sound_defaults(scene, seq);
+ seq->scene_sound = BKE_sound_scene_add_scene_sound_defaults(scene, seq);
}
}
}
@@ -3712,21 +4309,23 @@ Sequence *BKE_sequencer_foreground_frame_get(Scene *scene, int frame)
}
/* return 0 if there werent enough space */
-bool BKE_sequence_base_shuffle(ListBase *seqbasep, Sequence *test, Scene *evil_scene)
+bool BKE_sequence_base_shuffle_ex(ListBase *seqbasep, Sequence *test, Scene *evil_scene, int channel_delta)
{
- int orig_machine = test->machine;
- test->machine++;
+ const int orig_machine = test->machine;
+ BLI_assert(ELEM(channel_delta, -1, 1));
+
+ test->machine += channel_delta;
BKE_sequence_calc(evil_scene, test);
- while (BKE_sequence_test_overlap(seqbasep, test) ) {
- if (test->machine >= MAXSEQ) {
+ while (BKE_sequence_test_overlap(seqbasep, test)) {
+ if ((channel_delta > 0) ? (test->machine >= MAXSEQ) : (test->machine <= 1)) {
break;
}
- test->machine++;
+
+ test->machine += channel_delta;
BKE_sequence_calc(evil_scene, test); // XXX - I don't think this is needed since were only moving vertically, Campbell.
}
-
- if (test->machine >= MAXSEQ) {
+ if ((test->machine < 1) || (test->machine > MAXSEQ)) {
/* Blender 2.4x would remove the strip.
* nicer to move it to the end */
@@ -3750,6 +4349,11 @@ bool BKE_sequence_base_shuffle(ListBase *seqbasep, Sequence *test, Scene *evil_s
}
}
+bool BKE_sequence_base_shuffle(ListBase *seqbasep, Sequence *test, Scene *evil_scene)
+{
+ return BKE_sequence_base_shuffle_ex(seqbasep, test, evil_scene, 1);
+}
+
static int shuffle_seq_time_offset_test(ListBase *seqbasep, char dir)
{
int offset = 0;
@@ -3889,11 +4493,11 @@ void BKE_sequencer_update_sound_bounds(Scene *scene, Sequence *seq)
/* We have to take into account start frame of the sequence's scene! */
int startofs = seq->startofs + seq->anim_startofs + seq->scene->r.sfra;
- sound_move_scene_sound(scene, seq->scene_sound, seq->startdisp, seq->enddisp, startofs);
+ BKE_sound_move_scene_sound(scene, seq->scene_sound, seq->startdisp, seq->enddisp, startofs);
}
}
else {
- sound_move_scene_sound_defaults(scene, seq);
+ BKE_sound_move_scene_sound_defaults(scene, seq);
}
/* mute is set in seq_update_muting_recursive */
}
@@ -3918,7 +4522,7 @@ static void seq_update_muting_recursive(ListBase *seqbasep, Sequence *metaseq, i
}
else if (ELEM(seq->type, SEQ_TYPE_SOUND_RAM, SEQ_TYPE_SCENE)) {
if (seq->scene_sound) {
- sound_mute_scene_sound(seq->scene_sound, seqmute);
+ BKE_sound_mute_scene_sound(seq->scene_sound, seqmute);
}
}
}
@@ -3947,7 +4551,7 @@ static void seq_update_sound_recursive(Scene *scene, ListBase *seqbasep, bSound
}
else if (seq->type == SEQ_TYPE_SOUND_RAM) {
if (seq->scene_sound && sound == seq->sound) {
- sound_update_scene_sound(seq->scene_sound, sound);
+ BKE_sound_update_scene_sound(seq->scene_sound, sound);
}
}
}
@@ -4062,7 +4666,7 @@ static size_t sequencer_rna_path_prefix(char str[SEQ_RNAPATH_MAXSTR], const char
char name_esc[SEQ_NAME_MAXSTR * 2];
BLI_strescape(name_esc, name, sizeof(name_esc));
- return BLI_snprintf(str, SEQ_RNAPATH_MAXSTR, "sequence_editor.sequences_all[\"%s\"]", name_esc);
+ return BLI_snprintf_rlen(str, SEQ_RNAPATH_MAXSTR, "sequence_editor.sequences_all[\"%s\"]", name_esc);
}
/* XXX - hackish function needed for transforming strips! TODO - have some better solution */
@@ -4280,7 +4884,7 @@ static void seq_load_apply(Scene *scene, Sequence *seq, SeqLoadInfo *seq_load)
if (seq_load->flag & SEQ_LOAD_SOUND_CACHE) {
if (seq->sound)
- sound_cache(seq->sound);
+ BKE_sound_cache(seq->sound);
}
seq_load->tot_success++;
@@ -4310,6 +4914,8 @@ Sequence *BKE_sequence_alloc(ListBase *lb, int cfra, int machine)
seq->pitch = 1.0f;
seq->scene_sound = NULL;
+ seq->stereo3d_format = MEM_callocN(sizeof(Stereo3dFormat), "Sequence Stereo Format");
+
return seq;
}
@@ -4367,6 +4973,12 @@ Sequence *BKE_sequencer_add_image_strip(bContext *C, ListBase *seqbasep, SeqLoad
strip->stripdata = MEM_callocN(seq->len * sizeof(StripElem), "stripelem");
BLI_strncpy(strip->dir, seq_load->path, sizeof(strip->dir));
+ if (seq_load->stereo3d_format)
+ *seq->stereo3d_format = *seq_load->stereo3d_format;
+
+ seq->views_format = seq_load->views_format;
+ seq->flag |= seq_load->flag & SEQ_USE_VIEWS;
+
seq_load_apply(scene, seq, seq_load);
return seq;
@@ -4386,9 +4998,9 @@ Sequence *BKE_sequencer_add_sound_strip(bContext *C, ListBase *seqbasep, SeqLoad
AUD_SoundInfo info;
- sound = sound_new_file(bmain, seq_load->path); /* handles relative paths */
+ sound = BKE_sound_new_file(bmain, seq_load->path); /* handles relative paths */
- if (sound == NULL || sound->playback_handle == NULL) {
+ if (sound->playback_handle == NULL) {
#if 0
if (op)
BKE_report(op->reports, RPT_ERROR, "Unsupported audio format");
@@ -4400,7 +5012,7 @@ Sequence *BKE_sequencer_add_sound_strip(bContext *C, ListBase *seqbasep, SeqLoad
info = AUD_getInfo(sound->playback_handle);
if (info.specs.channels == AUD_CHANNELS_INVALID) {
- sound_delete(bmain, sound);
+ BKE_sound_delete(bmain, sound);
#if 0
if (op)
BKE_report(op->reports, RPT_ERROR, "Unsupported audio format");
@@ -4425,7 +5037,7 @@ Sequence *BKE_sequencer_add_sound_strip(bContext *C, ListBase *seqbasep, SeqLoad
BLI_split_dirfile(seq_load->path, strip->dir, se->name, sizeof(strip->dir), sizeof(se->name));
- seq->scene_sound = sound_add_scene_sound(scene, seq, seq_load->start_frame, seq_load->start_frame + seq->len, 0);
+ seq->scene_sound = BKE_sound_add_scene_sound(scene, seq, seq_load->start_frame, seq_load->start_frame + seq->len, 0);
BKE_sequence_calc_disp(scene, seq);
@@ -4446,6 +5058,12 @@ Sequence *BKE_sequencer_add_sound_strip(bContext *C, ListBase *seqbasep, SeqLoad
}
#endif // WITH_AUDASPACE
+static void seq_anim_add_suffix(Scene *scene, struct anim *anim, const size_t view_id)
+{
+ const char *suffix = BKE_scene_multiview_view_id_suffix_get(&scene->r, view_id);
+ IMB_suffix_anim(anim, suffix);
+}
+
Sequence *BKE_sequencer_add_movie_strip(bContext *C, ListBase *seqbasep, SeqLoadInfo *seq_load)
{
Scene *scene = CTX_data_scene(C); /* only for sound */
@@ -4455,29 +5073,84 @@ Sequence *BKE_sequencer_add_movie_strip(bContext *C, ListBase *seqbasep, SeqLoad
Strip *strip;
StripElem *se;
char colorspace[64] = "\0"; /* MAX_COLORSPACE_NAME */
-
- struct anim *an;
+ bool is_multiview_loaded = false;
+ const bool is_multiview = (seq_load->flag & SEQ_USE_VIEWS) != 0;
+ size_t totfiles = seq_num_files(scene, seq_load->views_format, is_multiview);
+ struct anim **anim_arr;
+ int i;
BLI_strncpy(path, seq_load->path, sizeof(path));
BLI_path_abs(path, G.main->name);
- an = openanim(path, IB_rect, 0, colorspace);
+ anim_arr = MEM_callocN(sizeof(struct anim *) * totfiles, "Video files");
- if (an == NULL)
- return NULL;
+ if (is_multiview && (seq_load->views_format == R_IMF_VIEWS_INDIVIDUAL)) {
+ char prefix[FILE_MAX];
+ const char *ext = NULL;
+ size_t j = 0;
+
+ BKE_scene_multiview_view_prefix_get(scene, path, prefix, &ext);
+
+ if (prefix[0] != '\0') {
+ for (i = 0; i < totfiles; i++) {
+ char str[FILE_MAX];
+
+ seq_multiview_name(scene, i, prefix, ext, str, FILE_MAX);
+ anim_arr[j] = openanim(str, IB_rect, 0, colorspace);
+
+ if (anim_arr[j]) {
+ seq_anim_add_suffix(scene, anim_arr[j], i);
+ j++;
+ }
+ }
+
+ if (j == 0) {
+ MEM_freeN(anim_arr);
+ return NULL;
+ }
+ is_multiview_loaded = true;
+ }
+ }
+
+ if (is_multiview_loaded == false) {
+ anim_arr[0] = openanim(path, IB_rect, 0, colorspace);
+
+ if (anim_arr[0] == NULL) {
+ MEM_freeN(anim_arr);
+ return NULL;
+ }
+ }
seq = BKE_sequence_alloc(seqbasep, seq_load->start_frame, seq_load->channel);
+
+ /* multiview settings */
+ if (seq_load->stereo3d_format) {
+ *seq->stereo3d_format = *seq_load->stereo3d_format;
+ seq->views_format = seq_load->views_format;
+ }
+ seq->flag |= seq_load->flag & SEQ_USE_VIEWS;
+
seq->type = SEQ_TYPE_MOVIE;
seq->blend_mode = SEQ_TYPE_CROSS; /* so alpha adjustment fade to the strip below */
- seq->anim = an;
- seq->anim_preseek = IMB_anim_get_preseek(an);
+ for (i = 0; i < totfiles; i++) {
+ if (anim_arr[i]) {
+ StripAnim *sanim = MEM_mallocN(sizeof(StripAnim), "Strip Anim");
+ BLI_addtail(&seq->anims, sanim);
+ sanim->anim = anim_arr[i];
+ }
+ else {
+ break;
+ }
+ }
+
+ seq->anim_preseek = IMB_anim_get_preseek(anim_arr[0]);
BLI_strncpy(seq->name + 2, "Movie", SEQ_NAME_MAXSTR - 2);
BKE_sequence_base_unique_name_recursive(&scene->ed->seqbase, seq);
/* basic defaults */
seq->strip = strip = MEM_callocN(sizeof(Strip), "strip");
- seq->len = IMB_anim_get_duration(an, IMB_TC_RECORD_RUN);
+ seq->len = IMB_anim_get_duration(anim_arr[0], IMB_TC_RECORD_RUN);
strip->us = 1;
BLI_strncpy(seq->strip->colorspace_settings.name, colorspace, sizeof(seq->strip->colorspace_settings.name));
@@ -4505,6 +5178,7 @@ Sequence *BKE_sequencer_add_movie_strip(bContext *C, ListBase *seqbasep, SeqLoad
/* can be NULL */
seq_load_apply(scene, seq, seq_load);
+ MEM_freeN(anim_arr);
return seq;
}
@@ -4516,6 +5190,8 @@ static Sequence *seq_dupli(Scene *scene, Scene *scene_to, Sequence *seq, int dup
seq->tmp = seqn;
seqn->strip = MEM_dupallocN(seq->strip);
+ seqn->stereo3d_format = MEM_dupallocN(seq->stereo3d_format);
+
/* XXX: add F-Curve duplication stuff? */
if (seq->strip->crop) {
@@ -4531,6 +5207,10 @@ static Sequence *seq_dupli(Scene *scene, Scene *scene_to, Sequence *seq, int dup
seqn->strip->proxy->anim = NULL;
}
+ if (seq->prop) {
+ seqn->prop = IDP_CopyProperty(seq->prop);
+ }
+
if (seqn->modifiers.first) {
BLI_listbase_clear(&seqn->modifiers);
@@ -4547,7 +5227,7 @@ static Sequence *seq_dupli(Scene *scene, Scene *scene_to, Sequence *seq, int dup
else if (seq->type == SEQ_TYPE_SCENE) {
seqn->strip->stripdata = NULL;
if (seq->scene_sound)
- seqn->scene_sound = sound_scene_add_scene_sound_defaults(sce_audio, seqn);
+ seqn->scene_sound = BKE_sound_scene_add_scene_sound_defaults(sce_audio, seqn);
}
else if (seq->type == SEQ_TYPE_MOVIECLIP) {
/* avoid assert */
@@ -4558,13 +5238,13 @@ static Sequence *seq_dupli(Scene *scene, Scene *scene_to, Sequence *seq, int dup
else if (seq->type == SEQ_TYPE_MOVIE) {
seqn->strip->stripdata =
MEM_dupallocN(seq->strip->stripdata);
- seqn->anim = NULL;
+ BLI_listbase_clear(&seqn->anims);
}
else if (seq->type == SEQ_TYPE_SOUND_RAM) {
seqn->strip->stripdata =
MEM_dupallocN(seq->strip->stripdata);
if (seq->scene_sound)
- seqn->scene_sound = sound_add_scene_sound_defaults(sce_audio, seqn);
+ seqn->scene_sound = BKE_sound_add_scene_sound_defaults(sce_audio, seqn);
id_us_plus((ID *)seqn->sound);
}
@@ -4572,17 +5252,11 @@ static Sequence *seq_dupli(Scene *scene, Scene *scene_to, Sequence *seq, int dup
seqn->strip->stripdata =
MEM_dupallocN(seq->strip->stripdata);
}
- else if (seq->type >= SEQ_TYPE_EFFECT) {
- if (seq->seq1 && seq->seq1->tmp) seqn->seq1 = seq->seq1->tmp;
- if (seq->seq2 && seq->seq2->tmp) seqn->seq2 = seq->seq2->tmp;
- if (seq->seq3 && seq->seq3->tmp) seqn->seq3 = seq->seq3->tmp;
-
- if (seq->type & SEQ_TYPE_EFFECT) {
- struct SeqEffectHandle sh;
- sh = BKE_sequence_get_effect(seq);
- if (sh.copy)
- sh.copy(seq, seqn);
- }
+ else if (seq->type & SEQ_TYPE_EFFECT) {
+ struct SeqEffectHandle sh;
+ sh = BKE_sequence_get_effect(seq);
+ if (sh.copy)
+ sh.copy(seq, seqn);
seqn->strip->stripdata = NULL;
@@ -4601,9 +5275,34 @@ static Sequence *seq_dupli(Scene *scene, Scene *scene_to, Sequence *seq, int dup
return seqn;
}
+static void seq_new_fix_links_recursive(Sequence *seq)
+{
+ SequenceModifierData *smd;
+
+ if (seq->type & SEQ_TYPE_EFFECT) {
+ if (seq->seq1 && seq->seq1->tmp) seq->seq1 = seq->seq1->tmp;
+ if (seq->seq2 && seq->seq2->tmp) seq->seq2 = seq->seq2->tmp;
+ if (seq->seq3 && seq->seq3->tmp) seq->seq3 = seq->seq3->tmp;
+ }
+ else if (seq->type == SEQ_TYPE_META) {
+ Sequence *seqn;
+ for (seqn = seq->seqbase.first; seqn; seqn = seqn->next) {
+ seq_new_fix_links_recursive(seqn);
+ }
+ }
+
+ for (smd = seq->modifiers.first; smd; smd = smd->next) {
+ if (smd->mask_sequence && smd->mask_sequence->tmp)
+ smd->mask_sequence = smd->mask_sequence->tmp;
+ }
+}
+
Sequence *BKE_sequence_dupli_recursive(Scene *scene, Scene *scene_to, Sequence *seq, int dupe_flag)
{
- Sequence *seqn = seq_dupli(scene, scene_to, seq, dupe_flag);
+ Sequence *seqn;
+
+ seq->tmp = NULL;
+ seqn = seq_dupli(scene, scene_to, seq, dupe_flag);
if (seq->type == SEQ_TYPE_META) {
Sequence *s;
for (s = seq->seqbase.first; s; s = s->next) {
@@ -4613,14 +5312,21 @@ Sequence *BKE_sequence_dupli_recursive(Scene *scene, Scene *scene_to, Sequence *
}
}
}
+
+ seq_new_fix_links_recursive(seqn);
+
return seqn;
}
-void BKE_sequence_base_dupli_recursive(Scene *scene, Scene *scene_to, ListBase *nseqbase, ListBase *seqbase, int dupe_flag)
+void BKE_sequence_base_dupli_recursive(
+ Scene *scene, Scene *scene_to, ListBase *nseqbase, ListBase *seqbase,
+ int dupe_flag)
{
Sequence *seq;
Sequence *seqn = NULL;
Sequence *last_seq = BKE_sequencer_active_get(scene);
+ /* always include meta's strips */
+ int dupe_flag_recursive = dupe_flag | SEQ_DUPE_ALL;
for (seq = seqbase->first; seq; seq = seq->next) {
seq->tmp = NULL;
@@ -4633,8 +5339,11 @@ void BKE_sequence_base_dupli_recursive(Scene *scene, Scene *scene_to, ListBase *
}
BLI_addtail(nseqbase, seqn);
- if (seq->type == SEQ_TYPE_META)
- BKE_sequence_base_dupli_recursive(scene, scene_to, &seqn->seqbase, &seq->seqbase, dupe_flag);
+ if (seq->type == SEQ_TYPE_META) {
+ BKE_sequence_base_dupli_recursive(
+ scene, scene_to, &seqn->seqbase, &seq->seqbase,
+ dupe_flag_recursive);
+ }
if (dupe_flag & SEQ_DUPE_CONTEXT) {
if (seq == last_seq) {
@@ -4644,6 +5353,11 @@ void BKE_sequence_base_dupli_recursive(Scene *scene, Scene *scene_to, ListBase *
}
}
}
+
+ /* fix modifier linking */
+ for (seq = nseqbase->first; seq; seq = seq->next) {
+ seq_new_fix_links_recursive(seq);
+ }
}
/* called on draw, needs to be fast,
@@ -4664,3 +5378,70 @@ bool BKE_sequence_is_valid_check(Sequence *seq)
return true;
}
+int BKE_sequencer_find_next_prev_edit(
+ Scene *scene, int cfra, const short side,
+ const bool do_skip_mute, const bool do_center, const bool do_unselected)
+{
+ Editing *ed = BKE_sequencer_editing_get(scene, false);
+ Sequence *seq;
+
+ int dist, best_dist, best_frame = cfra;
+ int seq_frames[2], seq_frames_tot;
+
+ /* in case where both is passed, frame just finds the nearest end while frame_left the nearest start */
+
+ best_dist = MAXFRAME * 2;
+
+ if (ed == NULL) return cfra;
+
+ for (seq = ed->seqbasep->first; seq; seq = seq->next) {
+ int i;
+
+ if (do_skip_mute && (seq->flag & SEQ_MUTE)) {
+ continue;
+ }
+
+ if (do_unselected && (seq->flag & SELECT))
+ continue;
+
+ if (do_center) {
+ seq_frames[0] = (seq->startdisp + seq->enddisp) / 2;
+ seq_frames_tot = 1;
+ }
+ else {
+ seq_frames[0] = seq->startdisp;
+ seq_frames[1] = seq->enddisp;
+
+ seq_frames_tot = 2;
+ }
+
+ for (i = 0; i < seq_frames_tot; i++) {
+ const int seq_frame = seq_frames[i];
+
+ dist = MAXFRAME * 2;
+
+ switch (side) {
+ case SEQ_SIDE_LEFT:
+ if (seq_frame < cfra) {
+ dist = cfra - seq_frame;
+ }
+ break;
+ case SEQ_SIDE_RIGHT:
+ if (seq_frame > cfra) {
+ dist = seq_frame - cfra;
+ }
+ break;
+ case SEQ_SIDE_BOTH:
+ dist = abs(seq_frame - cfra);
+ break;
+ }
+
+ if (dist < best_dist) {
+ best_frame = seq_frame;
+ best_dist = dist;
+ }
+ }
+ }
+
+ return best_frame;
+}
diff --git a/source/blender/blenkernel/intern/shrinkwrap.c b/source/blender/blenkernel/intern/shrinkwrap.c
index d2a4d15a2c6..7d492586b7d 100644
--- a/source/blender/blenkernel/intern/shrinkwrap.c
+++ b/source/blender/blenkernel/intern/shrinkwrap.c
@@ -50,9 +50,9 @@
#include "BKE_lattice.h"
#include "BKE_deform.h"
+#include "BKE_editmesh.h"
#include "BKE_mesh.h" /* for OMP limits. */
#include "BKE_subsurf.h"
-#include "BKE_editmesh.h"
#include "BLI_strict_flags.h"
@@ -90,7 +90,7 @@ static void shrinkwrap_calc_nearest_vertex(ShrinkwrapCalcData *calc)
nearest.index = -1;
nearest.dist_sq = FLT_MAX;
#ifndef __APPLE__
-#pragma omp parallel for default(none) private(i) firstprivate(nearest) shared(treeData, calc) schedule(static) if(calc->numVerts > BKE_MESH_OMP_LIMIT)
+#pragma omp parallel for default(none) private(i) firstprivate(nearest) shared(treeData, calc) schedule(static) if (calc->numVerts > BKE_MESH_OMP_LIMIT)
#endif
for (i = 0; i < calc->numVerts; ++i) {
float *co = calc->vertexCos[i];
@@ -279,9 +279,17 @@ static void shrinkwrap_calc_normal_projection(ShrinkwrapCalcData *calc, bool for
BLI_SPACE_TRANSFORM_SETUP(&local2aux, calc->ob, calc->smd->auxTarget);
}
+ /* use editmesh to avoid array allocation */
+ if (calc->smd->target && calc->target->type == DM_TYPE_EDITBMESH) {
+ treeData.em_evil = BKE_editmesh_from_object(calc->smd->target);
+ }
+ if (calc->smd->auxTarget && auxMesh->type == DM_TYPE_EDITBMESH) {
+ auxData.em_evil = BKE_editmesh_from_object(calc->smd->auxTarget);
+ }
+
/* After sucessufuly build the trees, start projection vertexs */
- if (bvhtree_from_mesh_faces(&treeData, calc->target, 0.0, 4, 6) &&
- (auxMesh == NULL || bvhtree_from_mesh_faces(&auxData, auxMesh, 0.0, 4, 6)))
+ if (bvhtree_from_mesh_looptri(&treeData, calc->target, 0.0, 4, 6) &&
+ (auxMesh == NULL || bvhtree_from_mesh_looptri(&auxData, auxMesh, 0.0, 4, 6)))
{
#ifndef __APPLE__
@@ -382,7 +390,7 @@ static void shrinkwrap_calc_nearest_surface_point(ShrinkwrapCalcData *calc)
BVHTreeNearest nearest = NULL_BVHTreeNearest;
/* Create a bvh-tree of the given target */
- bvhtree_from_mesh_faces(&treeData, calc->target, 0.0, 2, 6);
+ bvhtree_from_mesh_looptri(&treeData, calc->target, 0.0, 2, 6);
if (treeData.tree == NULL) {
OUT_OF_MEMORY();
return;
@@ -395,7 +403,7 @@ static void shrinkwrap_calc_nearest_surface_point(ShrinkwrapCalcData *calc)
/* Find the nearest vertex */
#ifndef __APPLE__
-#pragma omp parallel for default(none) private(i) firstprivate(nearest) shared(calc, treeData) schedule(static) if(calc->numVerts > BKE_MESH_OMP_LIMIT)
+#pragma omp parallel for default(none) private(i) firstprivate(nearest) shared(calc, treeData) schedule(static) if (calc->numVerts > BKE_MESH_OMP_LIMIT)
#endif
for (i = 0; i < calc->numVerts; ++i) {
float *co = calc->vertexCos[i];
diff --git a/source/blender/blenkernel/intern/sketch.c b/source/blender/blenkernel/intern/sketch.c
index da5dd76681d..0d355abb49b 100644
--- a/source/blender/blenkernel/intern/sketch.c
+++ b/source/blender/blenkernel/intern/sketch.c
@@ -81,6 +81,10 @@ void sk_initPoint(SK_Point *pt, SK_DrawData *dd, const float no[3])
}
pt->p2d[0] = dd->mval[0];
pt->p2d[1] = dd->mval[1];
+
+ pt->size = 0.0f;
+ pt->type = PT_CONTINUOUS;
+ pt->mode = PT_SNAP;
/* more init code here */
}
@@ -192,14 +196,14 @@ void sk_appendStrokePoint(SK_Stroke *stk, SK_Point *pt)
void sk_insertStrokePoints(SK_Stroke *stk, SK_Point *pts, int len, int start, int end)
{
- int size = end - start + 1;
+ int size = end - start;
sk_growStrokeBufferN(stk, len - size);
if (len != size) {
- int tail_size = stk->nb_points - end + 1;
+ int tail_size = stk->nb_points - end;
- memmove(stk->points + start + len, stk->points + end + 1, tail_size * sizeof(SK_Point));
+ memmove(stk->points + start + len, stk->points + end, tail_size * sizeof(SK_Point));
}
memcpy(stk->points + start, pts, len * sizeof(SK_Point));
diff --git a/source/blender/blenkernel/intern/smoke.c b/source/blender/blenkernel/intern/smoke.c
index 89245d2300d..4e2f6edfcdd 100644
--- a/source/blender/blenkernel/intern/smoke.c
+++ b/source/blender/blenkernel/intern/smoke.c
@@ -33,8 +33,6 @@
/* Part of the code copied from elbeem fluid library, copyright by Nils Thuerey */
-#include <GL/glew.h>
-
#include "MEM_guardedalloc.h"
#include <float.h>
@@ -62,11 +60,13 @@
#include "DNA_scene_types.h"
#include "DNA_smoke_types.h"
+#include "BKE_appdir.h"
#include "BKE_animsys.h"
#include "BKE_armature.h"
#include "BKE_bvhutils.h"
#include "BKE_cdderivedmesh.h"
#include "BKE_collision.h"
+#include "BKE_colortools.h"
#include "BKE_constraint.h"
#include "BKE_customdata.h"
#include "BKE_deform.h"
@@ -84,6 +84,8 @@
#include "RE_shader_ext.h"
+#include "GPU_glew.h"
+
/* UNUSED so far, may be enabled later */
/* #define USE_SMOKE_COLLISION_DM */
@@ -91,6 +93,8 @@
#ifdef WITH_SMOKE
+static ThreadMutex object_update_lock = BLI_MUTEX_INITIALIZER;
+
#ifdef _WIN32
#include <time.h>
#include <stdio.h>
@@ -205,7 +209,7 @@ void smoke_reallocate_highres_fluid(SmokeDomainSettings *sds, float dx, int res[
/* smoke_turbulence_init uses non-threadsafe functions from fftw3 lib (like fftw_plan & co). */
BLI_lock_thread(LOCK_FFTW);
- sds->wt = smoke_turbulence_init(res, sds->amplify + 1, sds->noise, BLI_temp_dir_session(), use_fire, use_colors);
+ sds->wt = smoke_turbulence_init(res, sds->amplify + 1, sds->noise, BKE_tempdir_session(), use_fire, use_colors);
BLI_unlock_thread(LOCK_FFTW);
@@ -265,7 +269,7 @@ static void smoke_set_domain_from_derivedmesh(SmokeDomainSettings *sds, Object *
}
/* apply object scale */
for (i = 0; i < 3; i++) {
- size[i] = fabs(size[i] * ob->size[i]);
+ size[i] = fabsf(size[i] * ob->size[i]);
}
copy_v3_v3(sds->global_size, size);
copy_v3_v3(sds->dp0, min);
@@ -725,11 +729,13 @@ static void obstacles_from_derivedmesh(Object *coll_ob, SmokeDomainSettings *sds
{
DerivedMesh *dm = NULL;
MVert *mvert = NULL;
- MFace *mface = NULL;
+ const MLoopTri *looptri;
+ const MLoop *mloop;
BVHTreeFromMesh treeData = {NULL};
int numverts, i, z;
- float surface_distance = 0.6;
+ /* slightly rounded-up sqrt(3 * (0.5)^2) == max. distance of cell boundary along the diagonal */
+ const float surface_distance = 0.867f;
float *vert_vel = NULL;
int has_velocity = 0;
@@ -739,7 +745,8 @@ static void obstacles_from_derivedmesh(Object *coll_ob, SmokeDomainSettings *sds
dm = CDDM_copy(scs->dm);
CDDM_calc_normals(dm);
mvert = dm->getVertArray(dm);
- mface = dm->getTessFaceArray(dm);
+ mloop = dm->getLoopArray(dm);
+ looptri = dm->getLoopTriArray(dm);
numverts = dm->getNumVerts(dm);
// DG TODO
@@ -787,7 +794,7 @@ static void obstacles_from_derivedmesh(Object *coll_ob, SmokeDomainSettings *sds
copy_v3_v3(&scs->verts_old[i * 3], co);
}
- if (bvhtree_from_mesh_faces(&treeData, dm, 0.0f, 4, 6)) {
+ if (bvhtree_from_mesh_looptri(&treeData, dm, 0.0f, 4, 6)) {
#pragma omp parallel for schedule(static)
for (z = sds->res_min[2]; z < sds->res_max[2]; z++) {
int x, y;
@@ -802,13 +809,14 @@ static void obstacles_from_derivedmesh(Object *coll_ob, SmokeDomainSettings *sds
/* find the nearest point on the mesh */
if (BLI_bvhtree_find_nearest(treeData.tree, ray_start, &nearest, treeData.nearest_callback, &treeData) != -1) {
+ const MLoopTri *lt = &looptri[nearest.index];
float weights[4];
- int v1, v2, v3, f_index = nearest.index;
+ int v1, v2, v3;
/* calculate barycentric weights for nearest point */
- v1 = mface[f_index].v1;
- v2 = (nearest.flags & BVH_ONQUAD) ? mface[f_index].v3 : mface[f_index].v2;
- v3 = (nearest.flags & BVH_ONQUAD) ? mface[f_index].v4 : mface[f_index].v3;
+ v1 = mloop[lt->tri[0]].v;
+ v2 = mloop[lt->tri[1]].v;
+ v3 = mloop[lt->tri[2]].v;
interp_weights_face_v3(weights, mvert[v1].co, mvert[v2].co, mvert[v3].co, NULL, nearest.co);
// DG TODO
@@ -953,7 +961,7 @@ static bool subframe_updateObject(Scene *scene, Object *ob, int update_mesh, int
/* if other is dynamic paint canvas, don't update */
if (smd && (smd->type & MOD_SMOKE_TYPE_DOMAIN))
- return 1;
+ return true;
/* if object has parents, update them too */
if (parent_recursion) {
@@ -965,11 +973,11 @@ static bool subframe_updateObject(Scene *scene, Object *ob, int update_mesh, int
/* skip subframe if object is parented
* to vertex of a dynamic paint canvas */
if (is_domain && (ob->partype == PARVERT1 || ob->partype == PARVERT3))
- return 0;
+ return false;
/* also update constraint targets */
for (con = ob->constraints.first; con; con = con->next) {
- bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
+ const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
ListBase targets = {NULL, NULL};
if (cti && cti->get_constraint_targets) {
@@ -1011,7 +1019,7 @@ static bool subframe_updateObject(Scene *scene, Object *ob, int update_mesh, int
BKE_pose_where_is(scene, ob);
}
- return 0;
+ return false;
}
/**********************************************************
@@ -1237,6 +1245,12 @@ static void emit_from_particles(Object *flow_ob, SmokeDomainSettings *sds, Smoke
sim.ob = flow_ob;
sim.psys = psys;
+ /* prepare curvemapping tables */
+ if ((psys->part->child_flag & PART_CHILD_USE_CLUMP_CURVE) && psys->part->clumpcurve)
+ curvemapping_changed_all(psys->part->clumpcurve);
+ if ((psys->part->child_flag & PART_CHILD_USE_ROUGH_CURVE) && psys->part->roughcurve)
+ curvemapping_changed_all(psys->part->roughcurve);
+
/* initialize particle cache */
if (psys->part->type == PART_HAIR) {
// TODO: PART_HAIR not supported whatsoever
@@ -1423,10 +1437,12 @@ static void emit_from_particles(Object *flow_ob, SmokeDomainSettings *sds, Smoke
}
static void sample_derivedmesh(
- SmokeFlowSettings *sfs, MVert *mvert, MTFace *tface, MFace *mface,
- float *influence_map, float *velocity_map, int index, int base_res[3], float flow_center[3],
+ SmokeFlowSettings *sfs,
+ const MVert *mvert, const MLoop *mloop, const MLoopTri *mlooptri, const MLoopUV *mloopuv,
+ float *influence_map, float *velocity_map, int index, const int base_res[3], float flow_center[3],
BVHTreeFromMesh *treeData, const float ray_start[3], const float *vert_vel,
- bool has_velocity, int defgrp_index, MDeformVert *dvert, float x, float y, float z)
+ bool has_velocity, int defgrp_index, MDeformVert *dvert,
+ float x, float y, float z)
{
float ray_dir[3] = {1.0f, 0.0f, 0.0f};
BVHTreeRayHit hit = {0};
@@ -1477,9 +1493,9 @@ static void sample_derivedmesh(
sample_str = 0.0f;
/* calculate barycentric weights for nearest point */
- v1 = mface[f_index].v1;
- v2 = (nearest.flags & BVH_ONQUAD) ? mface[f_index].v3 : mface[f_index].v2;
- v3 = (nearest.flags & BVH_ONQUAD) ? mface[f_index].v4 : mface[f_index].v3;
+ v1 = mloop[mlooptri[f_index].tri[0]].v;
+ v2 = mloop[mlooptri[f_index].tri[1]].v;
+ v3 = mloop[mlooptri[f_index].tri[2]].v;
interp_weights_face_v3(weights, mvert[v1].co, mvert[v2].co, mvert[v3].co, NULL, nearest.co);
if (sfs->flags & MOD_SMOKE_FLOW_INITVELOCITY && velocity_map) {
@@ -1527,9 +1543,14 @@ static void sample_derivedmesh(
tex_co[1] = ((y - flow_center[1]) / base_res[1]) / sfs->texture_size;
tex_co[2] = ((z - flow_center[2]) / base_res[2] - sfs->texture_offset) / sfs->texture_size;
}
- else if (tface) {
- interp_v2_v2v2v2(tex_co, tface[f_index].uv[0], tface[f_index].uv[(nearest.flags & BVH_ONQUAD) ? 2 : 1],
- tface[f_index].uv[(nearest.flags & BVH_ONQUAD) ? 3 : 2], weights);
+ else if (mloopuv) {
+ const float *uv[3];
+ uv[0] = mloopuv[mlooptri[f_index].tri[0]].uv;
+ uv[1] = mloopuv[mlooptri[f_index].tri[1]].uv;
+ uv[2] = mloopuv[mlooptri[f_index].tri[2]].uv;
+
+ interp_v2_v2v2v2(tex_co, UNPACK3(uv), weights);
+
/* map between -1.0f and 1.0f */
tex_co[0] = tex_co[0] * 2.0f - 1.0f;
tex_co[1] = tex_co[1] * 2.0f - 1.0f;
@@ -1558,8 +1579,9 @@ static void emit_from_derivedmesh(Object *flow_ob, SmokeDomainSettings *sds, Smo
MDeformVert *dvert = NULL;
MVert *mvert = NULL;
MVert *mvert_orig = NULL;
- MFace *mface = NULL;
- MTFace *tface = NULL;
+ const MLoopTri *mlooptri = NULL;
+ const MLoopUV *mloopuv = NULL;
+ const MLoop *mloop = NULL;
BVHTreeFromMesh treeData = {NULL};
int numOfVerts, i, z;
float flow_center[3] = {0};
@@ -1577,10 +1599,11 @@ static void emit_from_derivedmesh(Object *flow_ob, SmokeDomainSettings *sds, Smo
CDDM_calc_normals(dm);
mvert = dm->getVertArray(dm);
mvert_orig = dm->dupVertArray(dm); /* copy original mvert and restore when done */
- mface = dm->getTessFaceArray(dm);
numOfVerts = dm->getNumVerts(dm);
dvert = dm->getVertDataArray(dm, CD_MDEFORMVERT);
- tface = CustomData_get_layer_named(&dm->faceData, CD_MTFACE, sfs->uvlayer_name);
+ mloopuv = CustomData_get_layer_named(&dm->loopData, CD_MLOOPUV, sfs->uvlayer_name);
+ mloop = dm->getLoopArray(dm);
+ mlooptri = dm->getLoopTriArray(dm);
if (sfs->flags & MOD_SMOKE_FLOW_INITVELOCITY) {
vert_vel = MEM_callocN(sizeof(float) * numOfVerts * 3, "smoke_flow_velocity");
@@ -1641,7 +1664,7 @@ static void emit_from_derivedmesh(Object *flow_ob, SmokeDomainSettings *sds, Smo
res[i] = em->res[i] * hires_multiplier;
}
- if (bvhtree_from_mesh_faces(&treeData, dm, 0.0f, 4, 6)) {
+ if (bvhtree_from_mesh_looptri(&treeData, dm, 0.0f, 4, 6)) {
#pragma omp parallel for schedule(static)
for (z = min[2]; z < max[2]; z++) {
int x, y;
@@ -1657,8 +1680,11 @@ static void emit_from_derivedmesh(Object *flow_ob, SmokeDomainSettings *sds, Smo
int index = smoke_get_index(lx - em->min[0], em->res[0], ly - em->min[1], em->res[1], lz - em->min[2]);
float ray_start[3] = {((float)lx) + 0.5f, ((float)ly) + 0.5f, ((float)lz) + 0.5f};
- sample_derivedmesh(sfs, mvert, tface, mface, em->influence, em->velocity, index, sds->base_res, flow_center, &treeData, ray_start,
- vert_vel, has_velocity, defgrp_index, dvert, (float)lx, (float)ly, (float)lz);
+ sample_derivedmesh(
+ sfs, mvert, mloop, mlooptri, mloopuv,
+ em->influence, em->velocity, index, sds->base_res, flow_center,
+ &treeData, ray_start,vert_vel, has_velocity, defgrp_index, dvert,
+ (float)lx, (float)ly, (float)lz);
}
/* take high res samples if required */
@@ -1672,8 +1698,12 @@ static void emit_from_derivedmesh(Object *flow_ob, SmokeDomainSettings *sds, Smo
int index = smoke_get_index(x - min[0], res[0], y - min[1], res[1], z - min[2]);
float ray_start[3] = {lx + 0.5f*hr, ly + 0.5f*hr, lz + 0.5f*hr};
- sample_derivedmesh(sfs, mvert, tface, mface, em->influence_high, NULL, index, sds->base_res, flow_center, &treeData, ray_start,
- vert_vel, has_velocity, defgrp_index, dvert, lx, ly, lz); /* x,y,z needs to be always lowres */
+ sample_derivedmesh(
+ sfs, mvert, mloop, mlooptri, mloopuv,
+ em->influence_high, NULL, index, sds->base_res, flow_center,
+ &treeData, ray_start, vert_vel, has_velocity, defgrp_index, dvert,
+ /* x,y,z needs to be always lowres */
+ lx, ly, lz);
}
}
@@ -2020,7 +2050,7 @@ BLI_INLINE void apply_inflow_fields(SmokeFlowSettings *sfs, float emission_value
if (fuel && fuel[index] > FLT_EPSILON) {
/* instead of using 1.0 for all new fuel add slight falloff
* to reduce flow blockiness */
- float value = 1.0f - powf(1.0f - emission_value, 2.0f);
+ float value = 1.0f - pow2f(1.0f - emission_value);
if (value > react[index]) {
float f = fuel_flow / fuel[index];
@@ -2130,10 +2160,15 @@ static void update_flowsfluids(Scene *scene, Object *ob, SmokeDomainSettings *sd
if (sfs->source == MOD_SMOKE_FLOW_SOURCE_PARTICLES) {
/* emit_from_particles() updates timestep internally */
emit_from_particles(collob, sds, sfs, &em_temp, scene, sdt);
+ if (!(sfs->flags & MOD_SMOKE_FLOW_USE_PART_SIZE)) {
+ hires_multiplier = 1;
+ }
}
else { /* MOD_SMOKE_FLOW_SOURCE_MESH */
/* update flow object frame */
+ BLI_mutex_lock(&object_update_lock);
subframe_updateObject(scene, collob, 1, 5, BKE_scene_frame_get(scene), for_render);
+ BLI_mutex_unlock(&object_update_lock);
/* apply flow */
emit_from_derivedmesh(collob, sds, sfs, &em_temp, sdt);
@@ -2619,7 +2654,7 @@ static void smokeModifier_process(SmokeModifierData *smd, Scene *scene, Object *
if (smd->flow->dm) smd->flow->dm->release(smd->flow->dm);
smd->flow->dm = CDDM_copy(dm);
- DM_ensure_tessface(smd->flow->dm);
+ DM_ensure_looptri(smd->flow->dm);
if (scene->r.cfra > smd->time)
{
@@ -2642,7 +2677,7 @@ static void smokeModifier_process(SmokeModifierData *smd, Scene *scene, Object *
smd->coll->dm->release(smd->coll->dm);
smd->coll->dm = CDDM_copy(dm);
- DM_ensure_tessface(smd->coll->dm);
+ DM_ensure_looptri(smd->coll->dm);
}
smd->time = scene->r.cfra;
diff --git a/source/blender/blenkernel/intern/softbody.c b/source/blender/blenkernel/intern/softbody.c
index 9c411142566..dac395645c9 100644
--- a/source/blender/blenkernel/intern/softbody.c
+++ b/source/blender/blenkernel/intern/softbody.c
@@ -100,7 +100,7 @@ typedef struct BodySpring {
} BodySpring;
typedef struct BodyFace {
- int v1, v2, v3, v4;
+ int v1, v2, v3;
float ext_force[3]; /* faces colliding */
short flag;
} BodyFace;
@@ -171,8 +171,6 @@ static float SoftHeunTol = 1.0f; /* humm .. this should be calculated from sb pa
/* local prototypes */
static void free_softbody_intern(SoftBody *sb);
-/* aye this belongs to arith.c */
-static void Vec3PlusStVec(float *v, float s, float *v1);
/*+++ frame based timing +++*/
@@ -276,10 +274,10 @@ typedef struct ccdf_minmax {
typedef struct ccd_Mesh {
- int totvert, totface;
- MVert *mvert;
- MVert *mprevvert;
- MFace *mface;
+ int mvert_num, tri_num;
+ const MVert *mvert;
+ const MVert *mprevvert;
+ const MVertTri *tri;
int savety;
ccdf_minmax *mima;
/* Axis Aligned Bounding Box AABB */
@@ -294,26 +292,25 @@ static ccd_Mesh *ccd_mesh_make(Object *ob)
{
CollisionModifierData *cmd;
ccd_Mesh *pccd_M = NULL;
- ccdf_minmax *mima = NULL;
- MFace *mface=NULL;
- float v[3], hull;
+ ccdf_minmax *mima;
+ const MVertTri *vt;
+ float hull;
int i;
cmd =(CollisionModifierData *)modifiers_findByType(ob, eModifierType_Collision);
/* first some paranoia checks */
if (!cmd) return NULL;
- if (!cmd->numverts || !cmd->numfaces) return NULL;
+ if (!cmd->mvert_num || !cmd->tri_num) return NULL;
pccd_M = MEM_mallocN(sizeof(ccd_Mesh), "ccd_Mesh");
- pccd_M->totvert = cmd->numverts;
- pccd_M->totface = cmd->numfaces;
+ pccd_M->mvert_num = cmd->mvert_num;
+ pccd_M->tri_num = cmd->tri_num;
pccd_M->savety = CCD_SAVETY;
pccd_M->bbmin[0]=pccd_M->bbmin[1]=pccd_M->bbmin[2]=1e30f;
pccd_M->bbmax[0]=pccd_M->bbmax[1]=pccd_M->bbmax[2]=-1e30f;
pccd_M->mprevvert=NULL;
-
/* blow it up with forcefield ranges */
hull = max_ff(ob->pd->pdef_sbift, ob->pd->pdef_sboft);
@@ -321,9 +318,11 @@ static ccd_Mesh *ccd_mesh_make(Object *ob)
pccd_M->mvert = MEM_dupallocN(cmd->xnew);
/* note that xnew coords are already in global space, */
/* determine the ortho BB */
- for (i=0; i < pccd_M->totvert; i++) {
+ for (i = 0; i < pccd_M->mvert_num; i++) {
+ const float *v;
+
/* evaluate limits */
- copy_v3_v3(v, pccd_M->mvert[i].co);
+ v = pccd_M->mvert[i].co;
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);
@@ -334,20 +333,20 @@ static ccd_Mesh *ccd_mesh_make(Object *ob)
}
/* alloc and copy faces*/
- pccd_M->mface = MEM_dupallocN(cmd->mfaces);
+ pccd_M->tri = MEM_dupallocN(cmd->tri);
/* OBBs for idea1 */
- pccd_M->mima = MEM_mallocN(sizeof(ccdf_minmax)*pccd_M->totface, "ccd_Mesh_Faces_mima");
- mima = pccd_M->mima;
- mface = pccd_M->mface;
+ pccd_M->mima = MEM_mallocN(sizeof(ccdf_minmax) * pccd_M->tri_num, "ccd_Mesh_Faces_mima");
/* anyhoo we need to walk the list of faces and find OBB they live in */
- for (i=0; i < pccd_M->totface; i++) {
+ for (i = 0, mima = pccd_M->mima, vt = pccd_M->tri; i < pccd_M->tri_num; i++, mima++, vt++) {
+ const float *v;
+
mima->minx=mima->miny=mima->minz=1e30f;
mima->maxx=mima->maxy=mima->maxz=-1e30f;
- copy_v3_v3(v, pccd_M->mvert[mface->v1].co);
+ v = pccd_M->mvert[vt->tri[0]].co;
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);
@@ -355,7 +354,7 @@ static ccd_Mesh *ccd_mesh_make(Object *ob)
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);
+ v = pccd_M->mvert[vt->tri[1]].co;
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);
@@ -363,26 +362,13 @@ static ccd_Mesh *ccd_mesh_make(Object *ob)
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);
+ v = pccd_M->mvert[vt->tri[2]].co;
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 = 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++;
}
return pccd_M;
@@ -390,19 +376,19 @@ static ccd_Mesh *ccd_mesh_make(Object *ob)
static void ccd_mesh_update(Object *ob, ccd_Mesh *pccd_M)
{
CollisionModifierData *cmd;
- ccdf_minmax *mima = NULL;
- MFace *mface=NULL;
- float v[3], hull;
+ ccdf_minmax *mima;
+ const MVertTri *vt;
+ float hull;
int i;
cmd =(CollisionModifierData *)modifiers_findByType(ob, eModifierType_Collision);
/* first some paranoia checks */
if (!cmd) return;
- if (!cmd->numverts || !cmd->numfaces) return;
+ if (!cmd->mvert_num || !cmd->tri_num) return;
- if ((pccd_M->totvert != cmd->numverts) ||
- (pccd_M->totface != cmd->numfaces))
+ if ((pccd_M->mvert_num != cmd->mvert_num) ||
+ (pccd_M->tri_num != cmd->tri_num))
{
return;
}
@@ -415,15 +401,17 @@ static void ccd_mesh_update(Object *ob, ccd_Mesh *pccd_M)
hull = max_ff(ob->pd->pdef_sbift, ob->pd->pdef_sboft);
/* rotate current to previous */
- if (pccd_M->mprevvert) MEM_freeN(pccd_M->mprevvert);
+ if (pccd_M->mprevvert) MEM_freeN((void *)pccd_M->mprevvert);
pccd_M->mprevvert = pccd_M->mvert;
/* alloc and copy verts*/
pccd_M->mvert = MEM_dupallocN(cmd->xnew);
/* note that xnew coords are already in global space, */
/* determine the ortho BB */
- for (i=0; i < pccd_M->totvert; i++) {
+ for (i=0; i < pccd_M->mvert_num; i++) {
+ const float *v;
+
/* evaluate limits */
- copy_v3_v3(v, pccd_M->mvert[i].co);
+ v = pccd_M->mvert[i].co;
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);
@@ -433,7 +421,7 @@ static void ccd_mesh_update(Object *ob, ccd_Mesh *pccd_M)
pccd_M->bbmax[2] = max_ff(pccd_M->bbmax[2], v[2] + hull);
/* evaluate limits */
- copy_v3_v3(v, pccd_M->mprevvert[i].co);
+ v = pccd_M->mprevvert[i].co;
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);
@@ -444,16 +432,15 @@ static void ccd_mesh_update(Object *ob, ccd_Mesh *pccd_M)
}
- mima = pccd_M->mima;
- mface = pccd_M->mface;
-
-
/* anyhoo we need to walk the list of faces and find OBB they live in */
- for (i=0; i < pccd_M->totface; i++) {
+ for (i = 0, mima = pccd_M->mima, vt = pccd_M->tri; i < pccd_M->tri_num; i++, mima++, vt++) {
+ const float *v;
+
mima->minx=mima->miny=mima->minz=1e30f;
mima->maxx=mima->maxy=mima->maxz=-1e30f;
- copy_v3_v3(v, pccd_M->mvert[mface->v1].co);
+ /* mvert */
+ v = pccd_M->mvert[vt->tri[0]].co;
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);
@@ -461,7 +448,7 @@ static void ccd_mesh_update(Object *ob, ccd_Mesh *pccd_M)
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);
+ v = pccd_M->mvert[vt->tri[1]].co;
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);
@@ -469,7 +456,7 @@ static void ccd_mesh_update(Object *ob, ccd_Mesh *pccd_M)
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);
+ v = pccd_M->mvert[vt->tri[2]].co;
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);
@@ -477,18 +464,9 @@ static void ccd_mesh_update(Object *ob, ccd_Mesh *pccd_M)
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 = 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);
+ /* mprevvert */
+ v = pccd_M->mprevvert[vt->tri[0]].co;
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);
@@ -496,7 +474,7 @@ static void ccd_mesh_update(Object *ob, ccd_Mesh *pccd_M)
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);
+ v = pccd_M->mprevvert[vt->tri[1]].co;
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);
@@ -504,28 +482,13 @@ static void ccd_mesh_update(Object *ob, ccd_Mesh *pccd_M)
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);
+ v = pccd_M->mprevvert[vt->tri[2]].co;
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 = 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++;
-
}
return;
}
@@ -533,9 +496,9 @@ static void ccd_mesh_update(Object *ob, ccd_Mesh *pccd_M)
static void ccd_mesh_free(ccd_Mesh *ccdm)
{
if (ccdm && (ccdm->savety == CCD_SAVETY )) { /*make sure we're not nuking objects we don't know*/
- MEM_freeN(ccdm->mface);
- MEM_freeN(ccdm->mvert);
- if (ccdm->mprevvert) MEM_freeN(ccdm->mprevvert);
+ MEM_freeN((void *)ccdm->mvert);
+ MEM_freeN((void *)ccdm->tri);
+ if (ccdm->mprevvert) MEM_freeN((void *)ccdm->mprevvert);
MEM_freeN(ccdm->mima);
MEM_freeN(ccdm);
ccdm = NULL;
@@ -606,11 +569,13 @@ static void ccd_update_deflector_hash(Scene *scene, Object *vertexowner, GHash *
static int count_mesh_quads(Mesh *me)
{
int a, result = 0;
- MFace *mface= me->mface;
+ const MPoly *mp = me->mpoly;
- if (mface) {
- for (a=me->totface; a>0; a--, mface++) {
- if (mface->v4) result++;
+ if (mp) {
+ for (a = me->totpoly; a > 0; a--, mp++) {
+ if (mp->totloop == 4) {
+ result++;
+ }
}
}
return result;
@@ -619,9 +584,7 @@ static int count_mesh_quads(Mesh *me)
static void add_mesh_quad_diag_springs(Object *ob)
{
Mesh *me= ob->data;
- MFace *mface= me->mface;
/*BodyPoint *bp;*/ /*UNUSED*/
- BodySpring *bs, *bs_new;
int a;
if (ob->soft) {
@@ -630,36 +593,32 @@ static void add_mesh_quad_diag_springs(Object *ob)
nofquads = count_mesh_quads(me);
if (nofquads) {
- /* resize spring-array to hold additional quad springs */
- bs_new= MEM_callocN((ob->soft->totspring + nofquads *2 )*sizeof(BodySpring), "bodyspring");
- memcpy(bs_new, ob->soft->bspring, (ob->soft->totspring )*sizeof(BodySpring));
+ const MLoop *mloop = me->mloop;
+ const MPoly *mp = me->mpoly;
+ BodySpring *bs;
- if (ob->soft->bspring)
- MEM_freeN(ob->soft->bspring); /* do this before reassigning the pointer or have a 1st class memory leak */
- ob->soft->bspring = bs_new;
+ /* resize spring-array to hold additional quad springs */
+ ob->soft->bspring = MEM_recallocN(ob->soft->bspring, sizeof(BodySpring) * (ob->soft->totspring + nofquads * 2));
/* fill the tail */
a = 0;
- bs = bs_new+ob->soft->totspring;
+ bs = &ob->soft->bspring[ob->soft->totspring];
/*bp= ob->soft->bpoint; */ /*UNUSED*/
- if (mface ) {
- for (a=me->totface; a>0; a--, mface++) {
- if (mface->v4) {
- bs->v1= mface->v1;
- bs->v2= mface->v3;
- bs->springtype = SB_STIFFQUAD;
- bs++;
- bs->v1= mface->v2;
- bs->v2= mface->v4;
- bs->springtype = SB_STIFFQUAD;
- bs++;
-
- }
+ for (a = me->totpoly; a > 0; a--, mp++) {
+ if (mp->totloop == 4) {
+ bs->v1 = mloop[mp->loopstart + 0].v;
+ bs->v2 = mloop[mp->loopstart + 2].v;
+ bs->springtype = SB_STIFFQUAD;
+ bs++;
+ bs->v1 = mloop[mp->loopstart + 1].v;
+ bs->v2 = mloop[mp->loopstart + 3].v;
+ bs->springtype = SB_STIFFQUAD;
+ bs++;
}
}
/* now we can announce new springs */
- ob->soft->totspring += nofquads *2;
+ ob->soft->totspring += nofquads * 2;
}
}
}
@@ -707,7 +666,7 @@ static void add_2nd_order_roller(Object *ob, float UNUSED(stiffness), int *count
}
}
if ((bs2->v2 !=notthis)&&(bs2->v2 > v0)) {
- (*counter)++;/*hit */
+ (*counter)++; /* hit */
if (addsprings) {
bs3->v1= v0;
bs3->v2= bs2->v2;
@@ -984,14 +943,6 @@ static void free_softbody_intern(SoftBody *sb)
** since that would only valid for 'slow' moving collision targets and dito particles
*/
-/* aye this belongs to arith.c */
-static void Vec3PlusStVec(float *v, float s, float *v1)
-{
- v[0] += s*v1[0];
- v[1] += s*v1[1];
- v[2] += s*v1[2];
-}
-
/* +++ dependency information functions*/
static int are_there_deflectors(Scene *scene, unsigned int layer)
@@ -1037,22 +988,10 @@ static int sb_detect_aabb_collisionCached(float UNUSED(force[3]), unsigned int U
ccd_Mesh *ccdm = BLI_ghashIterator_getValue (ihash);
ob = BLI_ghashIterator_getKey (ihash);
+ {
/* only with deflecting set */
if (ob->pd && ob->pd->deflect) {
-#if 0 /* UNUSED */
- MFace *mface= NULL;
- MVert *mvert= NULL;
- MVert *mprevvert= NULL;
- ccdf_minmax *mima= NULL;
-#endif
if (ccdm) {
-#if 0 /* UNUSED */
- mface= ccdm->mface;
- mvert= ccdm->mvert;
- mprevvert= ccdm->mprevvert;
- mima= ccdm->mima;
- a = ccdm->totface;
-#endif
if ((aabbmax[0] < ccdm->bbmin[0]) ||
(aabbmax[1] < ccdm->bbmin[1]) ||
(aabbmax[2] < ccdm->bbmin[2]) ||
@@ -1078,6 +1017,7 @@ static int sb_detect_aabb_collisionCached(float UNUSED(force[3]), unsigned int U
}
} /* if (ob->pd && ob->pd->deflect) */
BLI_ghashIterator_step(ihash);
+ }
} /* while () */
BLI_ghashIterator_free(ihash);
return deflected;
@@ -1116,13 +1056,14 @@ static int sb_detect_face_pointCached(float face_v1[3], float face_v2[3], float
ccd_Mesh *ccdm = BLI_ghashIterator_getValue (ihash);
ob = BLI_ghashIterator_getKey (ihash);
+ {
/* only with deflecting set */
if (ob->pd && ob->pd->deflect) {
- MVert *mvert= NULL;
- MVert *mprevvert= NULL;
+ const MVert *mvert= NULL;
+ const MVert *mprevvert= NULL;
if (ccdm) {
- mvert= ccdm->mvert;
- a = ccdm->totvert;
+ mvert = ccdm->mvert;
+ a = ccdm->mvert_num;
mprevvert= ccdm->mprevvert;
outerfacethickness = ob->pd->pdef_sboft;
if ((aabbmax[0] < ccdm->bbmin[0]) ||
@@ -1152,7 +1093,7 @@ static int sb_detect_face_pointCached(float face_v1[3], float face_v2[3], float
copy_v3_v3(nv1, mvert[a-1].co);
if (mprevvert) {
mul_v3_fl(nv1, time);
- Vec3PlusStVec(nv1, (1.0f-time), mprevvert[a-1].co);
+ madd_v3_v3fl(nv1, mprevvert[a - 1].co, 1.0f - time);
}
/* origin to face_v2*/
sub_v3_v3(nv1, face_v2);
@@ -1170,7 +1111,7 @@ static int sb_detect_face_pointCached(float face_v1[3], float face_v2[3], float
*damp=df*tune*ob->pd->pdef_sbdamp;
df = 0.01f * expf(-100.0f * df);
- Vec3PlusStVec(force, -df, d_nvect);
+ madd_v3_v3fl(force, d_nvect, -df);
deflected = 3;
}
}
@@ -1179,6 +1120,7 @@ static int sb_detect_face_pointCached(float face_v1[3], float face_v2[3], float
} /* if (mvert) */
} /* if (ob->pd && ob->pd->deflect) */
BLI_ghashIterator_step(ihash);
+ }
} /* while () */
BLI_ghashIterator_free(ihash);
return deflected;
@@ -1191,7 +1133,7 @@ static int sb_detect_face_collisionCached(float face_v1[3], float face_v2[3], fl
Object *ob;
GHash *hash;
GHashIterator *ihash;
- float nv1[3], nv2[3], nv3[3], nv4[3], edge1[3], edge2[3], d_nvect[3], aabbmin[3], aabbmax[3];
+ float nv1[3], nv2[3], nv3[3], edge1[3], edge2[3], d_nvect[3], aabbmin[3], aabbmax[3];
float t, tune = 10.0f;
int a, deflected=0;
@@ -1208,18 +1150,20 @@ static int sb_detect_face_collisionCached(float face_v1[3], float face_v2[3], fl
ccd_Mesh *ccdm = BLI_ghashIterator_getValue (ihash);
ob = BLI_ghashIterator_getKey (ihash);
+ {
/* only with deflecting set */
if (ob->pd && ob->pd->deflect) {
- MFace *mface= NULL;
- MVert *mvert= NULL;
- MVert *mprevvert= NULL;
- ccdf_minmax *mima= NULL;
+ const MVert *mvert = NULL;
+ const MVert *mprevvert = NULL;
+ const MVertTri *vt = NULL;
+ const ccdf_minmax *mima = NULL;
+
if (ccdm) {
- mface= ccdm->mface;
- mvert= ccdm->mvert;
- mprevvert= ccdm->mprevvert;
- mima= ccdm->mima;
- a = ccdm->totface;
+ mvert = ccdm->mvert;
+ vt = ccdm->tri;
+ mprevvert = ccdm->mprevvert;
+ mima = ccdm->mima;
+ a = ccdm->tri_num;
if ((aabbmax[0] < ccdm->bbmin[0]) ||
(aabbmax[1] < ccdm->bbmin[1]) ||
@@ -1244,42 +1188,34 @@ static int sb_detect_face_collisionCached(float face_v1[3], float face_v2[3], fl
/* use mesh*/
while (a--) {
- if (
- (aabbmax[0] < mima->minx) ||
- (aabbmin[0] > mima->maxx) ||
- (aabbmax[1] < mima->miny) ||
- (aabbmin[1] > mima->maxy) ||
- (aabbmax[2] < mima->minz) ||
- (aabbmin[2] > mima->maxz)
- ) {
- mface++;
+ if ((aabbmax[0] < mima->minx) ||
+ (aabbmin[0] > mima->maxx) ||
+ (aabbmax[1] < mima->miny) ||
+ (aabbmin[1] > mima->maxy) ||
+ (aabbmax[2] < mima->minz) ||
+ (aabbmin[2] > mima->maxz))
+ {
mima++;
+ vt++;
continue;
}
if (mvert) {
- copy_v3_v3(nv1, mvert[mface->v1].co);
- copy_v3_v3(nv2, mvert[mface->v2].co);
- copy_v3_v3(nv3, mvert[mface->v3].co);
- if (mface->v4) {
- copy_v3_v3(nv4, mvert[mface->v4].co);
- }
+ copy_v3_v3(nv1, mvert[vt->tri[0]].co);
+ copy_v3_v3(nv2, mvert[vt->tri[1]].co);
+ copy_v3_v3(nv3, mvert[vt->tri[2]].co);
+
if (mprevvert) {
mul_v3_fl(nv1, time);
- Vec3PlusStVec(nv1, (1.0f-time), mprevvert[mface->v1].co);
+ madd_v3_v3fl(nv1, mprevvert[vt->tri[0]].co, 1.0f - time);
mul_v3_fl(nv2, time);
- Vec3PlusStVec(nv2, (1.0f-time), mprevvert[mface->v2].co);
+ madd_v3_v3fl(nv2, mprevvert[vt->tri[1]].co, 1.0f - time);
mul_v3_fl(nv3, time);
- Vec3PlusStVec(nv3, (1.0f-time), mprevvert[mface->v3].co);
-
- if (mface->v4) {
- mul_v3_fl(nv4, time);
- Vec3PlusStVec(nv4, (1.0f-time), mprevvert[mface->v4].co);
- }
+ madd_v3_v3fl(nv3, mprevvert[vt->tri[2]].co, 1.0f - time);
}
}
@@ -1288,35 +1224,20 @@ static int sb_detect_face_collisionCached(float face_v1[3], float face_v2[3], fl
sub_v3_v3v3(edge2, nv3, nv2);
cross_v3_v3v3(d_nvect, edge2, edge1);
normalize_v3(d_nvect);
- if (
- isect_line_tri_v3(nv1, nv2, face_v1, face_v2, face_v3, &t, NULL) ||
- isect_line_tri_v3(nv2, nv3, face_v1, face_v2, face_v3, &t, NULL) ||
- isect_line_tri_v3(nv3, nv1, face_v1, face_v2, face_v3, &t, NULL) ) {
- Vec3PlusStVec(force, -0.5f, d_nvect);
+ if (isect_line_tri_v3(nv1, nv2, face_v1, face_v2, face_v3, &t, NULL) ||
+ isect_line_tri_v3(nv2, nv3, face_v1, face_v2, face_v3, &t, NULL) ||
+ isect_line_tri_v3(nv3, nv1, face_v1, face_v2, face_v3, &t, NULL) )
+ {
+ madd_v3_v3fl(force, d_nvect, -0.5f);
*damp=tune*ob->pd->pdef_sbdamp;
deflected = 2;
}
- if (mface->v4) { /* quad */
- /* switch origin to be nv4 */
- sub_v3_v3v3(edge1, nv3, nv4);
- sub_v3_v3v3(edge2, nv1, nv4);
- cross_v3_v3v3(d_nvect, edge2, edge1);
- normalize_v3(d_nvect);
- if (
- /* isect_line_tri_v3(nv1, nv3, face_v1, face_v2, face_v3, &t, NULL) ||
- * we did that edge already */
- isect_line_tri_v3(nv3, nv4, face_v1, face_v2, face_v3, &t, NULL) ||
- isect_line_tri_v3(nv4, nv1, face_v1, face_v2, face_v3, &t, NULL) ) {
- Vec3PlusStVec(force, -0.5f, d_nvect);
- *damp=tune*ob->pd->pdef_sbdamp;
- deflected = 2;
- }
- }
- mface++;
mima++;
+ vt++;
}/* while a */
} /* if (ob->pd && ob->pd->deflect) */
BLI_ghashIterator_step(ihash);
+ }
} /* while () */
BLI_ghashIterator_free(ihash);
return deflected;
@@ -1341,26 +1262,15 @@ static void scan_for_ext_face_forces(Object *ob, float timenow)
bf->ext_force[0]=bf->ext_force[1]=bf->ext_force[2]=0.0f;
/*+++edges intruding*/
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))
+ zero_v3(feedback);
+ 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))
{
- 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 = 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)))
- {
- 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);
+ madd_v3_v3fl(sb->bpoint[bf->v1].force, feedback, tune);
+ madd_v3_v3fl(sb->bpoint[bf->v2].force, feedback, tune);
+ madd_v3_v3fl(sb->bpoint[bf->v3].force, feedback, tune);
+// madd_v3_v3fl(bf->ext_force, feedback, tune);
bf->flag |= BFF_INTERSECT;
choke = min_ff(max_ff(damp, choke), 1.0f);
}
@@ -1370,26 +1280,15 @@ static void scan_for_ext_face_forces(Object *ob, float timenow)
if (( bf->flag & BFF_INTERSECT)==0) {
bf->flag &= ~BFF_CLOSEVERT;
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 = 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)))
+ zero_v3(feedback);
+ 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->v3].force, tune, feedback);
- Vec3PlusStVec(sb->bpoint[bf->v4].force, tune, feedback);
-// Vec3PlusStVec(bf->ext_force, tune, feedback);
+ madd_v3_v3fl(sb->bpoint[bf->v1].force, feedback, tune);
+ madd_v3_v3fl(sb->bpoint[bf->v2].force, feedback, tune);
+ madd_v3_v3fl(sb->bpoint[bf->v3].force, feedback, tune);
+// madd_v3_v3fl(bf->ext_force, feedback, tune);
bf->flag |= BFF_CLOSEVERT;
choke = min_ff(max_ff(damp, choke), 1.0f);
}
@@ -1402,9 +1301,6 @@ static void scan_for_ext_face_forces(Object *ob, float timenow)
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 = max_ff(sb->bpoint[bf->v2].choke2, choke);
- }
}
}
}
@@ -1421,7 +1317,7 @@ static int sb_detect_edge_collisionCached(float edge_v1[3], float edge_v2[3], fl
Object *ob;
GHash *hash;
GHashIterator *ihash;
- float nv1[3], nv2[3], nv3[3], nv4[3], edge1[3], edge2[3], d_nvect[3], aabbmin[3], aabbmax[3];
+ float nv1[3], nv2[3], nv3[3], edge1[3], edge2[3], d_nvect[3], aabbmin[3], aabbmax[3];
float t, el;
int a, deflected=0;
@@ -1436,18 +1332,20 @@ static int sb_detect_edge_collisionCached(float edge_v1[3], float edge_v2[3], fl
ccd_Mesh *ccdm = BLI_ghashIterator_getValue (ihash);
ob = BLI_ghashIterator_getKey (ihash);
+ {
/* only with deflecting set */
if (ob->pd && ob->pd->deflect) {
- MFace *mface= NULL;
- MVert *mvert= NULL;
- MVert *mprevvert= NULL;
- ccdf_minmax *mima= NULL;
+ const MVert *mvert = NULL;
+ const MVert *mprevvert = NULL;
+ const MVertTri *vt = NULL;
+ const ccdf_minmax *mima = NULL;
+
if (ccdm) {
- mface= ccdm->mface;
- mvert= ccdm->mvert;
- mprevvert= ccdm->mprevvert;
- mima= ccdm->mima;
- a = ccdm->totface;
+ mvert = ccdm->mvert;
+ mprevvert = ccdm->mprevvert;
+ vt = ccdm->tri;
+ mima = ccdm->mima;
+ a = ccdm->tri_num;
if ((aabbmax[0] < ccdm->bbmin[0]) ||
(aabbmax[1] < ccdm->bbmin[1]) ||
@@ -1472,43 +1370,34 @@ static int sb_detect_edge_collisionCached(float edge_v1[3], float edge_v2[3], fl
/* use mesh*/
while (a--) {
- if (
- (aabbmax[0] < mima->minx) ||
- (aabbmin[0] > mima->maxx) ||
- (aabbmax[1] < mima->miny) ||
- (aabbmin[1] > mima->maxy) ||
- (aabbmax[2] < mima->minz) ||
- (aabbmin[2] > mima->maxz)
- )
+ if ((aabbmax[0] < mima->minx) ||
+ (aabbmin[0] > mima->maxx) ||
+ (aabbmax[1] < mima->miny) ||
+ (aabbmin[1] > mima->maxy) ||
+ (aabbmax[2] < mima->minz) ||
+ (aabbmin[2] > mima->maxz))
{
- mface++;
mima++;
+ vt++;
continue;
}
if (mvert) {
- copy_v3_v3(nv1, mvert[mface->v1].co);
- copy_v3_v3(nv2, mvert[mface->v2].co);
- copy_v3_v3(nv3, mvert[mface->v3].co);
- if (mface->v4) {
- copy_v3_v3(nv4, mvert[mface->v4].co);
- }
+ copy_v3_v3(nv1, mvert[vt->tri[0]].co);
+ copy_v3_v3(nv2, mvert[vt->tri[1]].co);
+ copy_v3_v3(nv3, mvert[vt->tri[2]].co);
+
if (mprevvert) {
mul_v3_fl(nv1, time);
- Vec3PlusStVec(nv1, (1.0f-time), mprevvert[mface->v1].co);
+ madd_v3_v3fl(nv1, mprevvert[vt->tri[0]].co, 1.0f - time);
mul_v3_fl(nv2, time);
- Vec3PlusStVec(nv2, (1.0f-time), mprevvert[mface->v2].co);
+ madd_v3_v3fl(nv2, mprevvert[vt->tri[1]].co, 1.0f - time);
mul_v3_fl(nv3, time);
- Vec3PlusStVec(nv3, (1.0f-time), mprevvert[mface->v3].co);
-
- if (mface->v4) {
- mul_v3_fl(nv4, time);
- Vec3PlusStVec(nv4, (1.0f-time), mprevvert[mface->v4].co);
- }
+ madd_v3_v3fl(nv3, mprevvert[vt->tri[2]].co, 1.0f - time);
}
}
@@ -1526,37 +1415,17 @@ static int sb_detect_edge_collisionCached(float edge_v1[3], float edge_v2[3], fl
i1 = dot_v3v3(v1, d_nvect);
i2 = dot_v3v3(v2, d_nvect);
intrusiondepth = -min_ff(i1, i2) / el;
- Vec3PlusStVec(force, intrusiondepth, d_nvect);
+ madd_v3_v3fl(force, d_nvect, intrusiondepth);
*damp=ob->pd->pdef_sbdamp;
deflected = 2;
}
- if (mface->v4) { /* quad */
- /* switch origin to be nv4 */
- sub_v3_v3v3(edge1, nv3, nv4);
- sub_v3_v3v3(edge2, nv1, nv4);
-
- cross_v3_v3v3(d_nvect, edge2, edge1);
- normalize_v3(d_nvect);
- if (isect_line_tri_v3( edge_v1, edge_v2, nv1, nv3, nv4, &t, NULL)) {
- float v1[3], v2[3];
- 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 = -min_ff(i1, i2) / el;
-
-
- Vec3PlusStVec(force, intrusiondepth, d_nvect);
- *damp=ob->pd->pdef_sbdamp;
- deflected = 2;
- }
- }
- mface++;
+
mima++;
+ vt++;
}/* while a */
} /* if (ob->pd && ob->pd->deflect) */
BLI_ghashIterator_step(ihash);
+ }
} /* while () */
BLI_ghashIterator_free(ihash);
return deflected;
@@ -1623,10 +1492,10 @@ 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 - fabsf(dot_v3v3(vel, sp))), vel);
+ madd_v3_v3fl(bs->ext_force, vel, f * (1.0f - fabsf(dot_v3v3(vel, sp))));
}
else {
- Vec3PlusStVec(bs->ext_force, f, vel); // to keep compatible with 2.45 release files
+ madd_v3_v3fl(bs->ext_force, vel, f); // to keep compatible with 2.45 release files
}
}
/* --- springs seeing wind */
@@ -1739,15 +1608,16 @@ static int choose_winner(float*w, float* pos, float*a, float*b, float*c, float*c
-static int sb_detect_vertex_collisionCached(float opco[3], float facenormal[3], float *damp,
- float force[3], unsigned int UNUSED(par_layer), struct Object *vertexowner,
- float time, float vel[3], float *intrusion)
+static int sb_detect_vertex_collisionCached(
+ float opco[3], float facenormal[3], float *damp,
+ float force[3], unsigned int UNUSED(par_layer), struct Object *vertexowner,
+ float time, float vel[3], float *intrusion)
{
Object *ob= NULL;
GHash *hash;
GHashIterator *ihash;
- float nv1[3], nv2[3], nv3[3], nv4[3], edge1[3], edge2[3], d_nvect[3], dv1[3], ve[3], avel[3] = {0.0, 0.0, 0.0},
- vv1[3], vv2[3], vv3[3], vv4[3], coledge[3] = {0.0f, 0.0f, 0.0f}, mindistedge = 1000.0f,
+ float nv1[3], nv2[3], nv3[3], edge1[3], edge2[3], d_nvect[3], dv1[3], ve[3], avel[3] = {0.0, 0.0, 0.0},
+ vv1[3], vv2[3], vv3[3], coledge[3] = {0.0f, 0.0f, 0.0f}, mindistedge = 1000.0f,
outerforceaccu[3], innerforceaccu[3],
facedist, /* n_mag, */ /* UNUSED */ force_mag_norm, minx, miny, minz, maxx, maxy, maxz,
innerfacethickness = -0.5f, outerfacethickness = 0.2f,
@@ -1764,19 +1634,20 @@ static int sb_detect_vertex_collisionCached(float opco[3], float facenormal[3],
ccd_Mesh *ccdm = BLI_ghashIterator_getValue (ihash);
ob = BLI_ghashIterator_getKey (ihash);
+ {
/* only with deflecting set */
if (ob->pd && ob->pd->deflect) {
- MFace *mface= NULL;
- MVert *mvert= NULL;
- MVert *mprevvert= NULL;
- ccdf_minmax *mima= NULL;
+ const MVert *mvert = NULL;
+ const MVert *mprevvert = NULL;
+ const MVertTri *vt = NULL;
+ const ccdf_minmax *mima = NULL;
if (ccdm) {
- mface= ccdm->mface;
- mvert= ccdm->mvert;
- mprevvert= ccdm->mprevvert;
- mima= ccdm->mima;
- a = ccdm->totface;
+ mvert = ccdm->mvert;
+ mprevvert = ccdm->mprevvert;
+ vt = ccdm->tri;
+ mima = ccdm->mima;
+ a = ccdm->tri_num;
minx = ccdm->bbmin[0];
miny = ccdm->bbmin[1];
@@ -1801,7 +1672,7 @@ static int sb_detect_vertex_collisionCached(float opco[3], float facenormal[3],
else {
/*aye that should be cached*/
printf("missing cache error\n");
- BLI_ghashIterator_step(ihash);
+ BLI_ghashIterator_step(ihash);
continue;
}
@@ -1815,27 +1686,23 @@ static int sb_detect_vertex_collisionCached(float opco[3], float facenormal[3],
avel[0]=avel[1]=avel[2]=0.0f;
/* use mesh*/
while (a--) {
- if (
- (opco[0] < mima->minx) ||
- (opco[0] > mima->maxx) ||
- (opco[1] < mima->miny) ||
- (opco[1] > mima->maxy) ||
- (opco[2] < mima->minz) ||
- (opco[2] > mima->maxz)
- ) {
- mface++;
- mima++;
- continue;
+ if ((opco[0] < mima->minx) ||
+ (opco[0] > mima->maxx) ||
+ (opco[1] < mima->miny) ||
+ (opco[1] > mima->maxy) ||
+ (opco[2] < mima->minz) ||
+ (opco[2] > mima->maxz))
+ {
+ mima++;
+ vt++;
+ continue;
}
if (mvert) {
- copy_v3_v3(nv1, mvert[mface->v1].co);
- copy_v3_v3(nv2, mvert[mface->v2].co);
- copy_v3_v3(nv3, mvert[mface->v3].co);
- if (mface->v4) {
- copy_v3_v3(nv4, mvert[mface->v4].co);
- }
+ copy_v3_v3(nv1, mvert[vt->tri[0]].co);
+ copy_v3_v3(nv2, mvert[vt->tri[1]].co);
+ copy_v3_v3(nv3, mvert[vt->tri[2]].co);
if (mprevvert) {
/* grab the average speed of the collider vertices
@@ -1844,26 +1711,18 @@ static int sb_detect_vertex_collisionCached(float opco[3], float facenormal[3],
since the AABB reduced propabitlty to get here drasticallly
it might be a nice tradeof CPU <--> memory
*/
- sub_v3_v3v3(vv1, nv1, mprevvert[mface->v1].co);
- sub_v3_v3v3(vv2, nv2, mprevvert[mface->v2].co);
- sub_v3_v3v3(vv3, nv3, mprevvert[mface->v3].co);
- if (mface->v4) {
- sub_v3_v3v3(vv4, nv4, mprevvert[mface->v4].co);
- }
+ sub_v3_v3v3(vv1, nv1, mprevvert[vt->tri[0]].co);
+ sub_v3_v3v3(vv2, nv2, mprevvert[vt->tri[1]].co);
+ sub_v3_v3v3(vv3, nv3, mprevvert[vt->tri[2]].co);
mul_v3_fl(nv1, time);
- Vec3PlusStVec(nv1, (1.0f-time), mprevvert[mface->v1].co);
+ madd_v3_v3fl(nv1, mprevvert[vt->tri[0]].co, 1.0f - time);
mul_v3_fl(nv2, time);
- Vec3PlusStVec(nv2, (1.0f-time), mprevvert[mface->v2].co);
+ madd_v3_v3fl(nv2, mprevvert[vt->tri[1]].co, 1.0f - time);
mul_v3_fl(nv3, time);
- Vec3PlusStVec(nv3, (1.0f-time), mprevvert[mface->v3].co);
-
- if (mface->v4) {
- mul_v3_fl(nv4, time);
- Vec3PlusStVec(nv4, (1.0f-time), mprevvert[mface->v4].co);
- }
+ madd_v3_v3fl(nv3, mprevvert[vt->tri[2]].co, 1.0f - time);
}
}
@@ -1886,12 +1745,12 @@ static int sb_detect_vertex_collisionCached(float opco[3], float facenormal[3],
*damp=ob->pd->pdef_sbdamp;
if (facedist > 0.0f) {
*damp *= (1.0f - facedist/outerfacethickness);
- Vec3PlusStVec(outerforceaccu, force_mag_norm, d_nvect);
+ madd_v3_v3fl(outerforceaccu, d_nvect, force_mag_norm);
deflected = 3;
}
else {
- Vec3PlusStVec(innerforceaccu, force_mag_norm, d_nvect);
+ madd_v3_v3fl(innerforceaccu, d_nvect, force_mag_norm);
if (deflected < 2) deflected = 2;
}
if ((mprevvert) && (*damp > 0.0f)) {
@@ -1903,109 +1762,20 @@ static int sb_detect_vertex_collisionCached(float opco[3], float facenormal[3],
ci++;
}
}
- if (mface->v4) { /* quad */
- /* switch origin to be nv4 */
- sub_v3_v3v3(edge1, nv3, nv4);
- sub_v3_v3v3(edge2, nv1, nv4);
- sub_v3_v3v3(dv1, opco, nv4); /* abuse dv1 to have vertex in question at *origin* of triangle */
-
- cross_v3_v3v3(d_nvect, edge2, edge1);
- /* n_mag = */ /* UNUSED */ normalize_v3(d_nvect);
- facedist = dot_v3v3(dv1, d_nvect);
-
- if ((facedist > innerfacethickness) && (facedist < outerfacethickness)) {
- if (isect_point_tri_prism_v3(opco, nv1, nv3, nv4) ) {
- force_mag_norm =(float)exp(-ee*facedist);
- if (facedist > outerfacethickness*ff)
- force_mag_norm =(float)force_mag_norm*fa*(facedist - outerfacethickness)*(facedist - outerfacethickness);
- *damp=ob->pd->pdef_sbdamp;
- if (facedist > 0.0f) {
- *damp *= (1.0f - facedist/outerfacethickness);
- Vec3PlusStVec(outerforceaccu, force_mag_norm, d_nvect);
- deflected = 3;
-
- }
- else {
- Vec3PlusStVec(innerforceaccu, force_mag_norm, d_nvect);
- if (deflected < 2) deflected = 2;
- }
-
- if ((mprevvert) && (*damp > 0.0f)) {
- choose_winner(ve, opco, nv1, nv3, nv4, vv1, vv3, vv4);
- add_v3_v3(avel, ve);
- cavel ++;
- }
- *intrusion += facedist;
- ci++;
- }
- }
- if ((deflected < 2)&& (G.debug_value != 444)) { /* we did not hit a face until now */
- /* see if 'outer' hits an edge */
- float dist;
-
- closest_to_line_segment_v3(ve, opco, nv1, nv2);
- sub_v3_v3v3(ve, opco, ve);
- dist = normalize_v3(ve);
- if ((dist < outerfacethickness)&&(dist < mindistedge )) {
- copy_v3_v3(coledge, ve);
- mindistedge = dist,
- deflected=1;
- }
-
- closest_to_line_segment_v3(ve, opco, nv2, nv3);
- sub_v3_v3v3(ve, opco, ve);
- dist = normalize_v3(ve);
- if ((dist < outerfacethickness)&&(dist < mindistedge )) {
- copy_v3_v3(coledge, ve);
- mindistedge = dist,
- deflected=1;
- }
-
- closest_to_line_segment_v3(ve, opco, nv3, nv1);
- sub_v3_v3v3(ve, opco, ve);
- dist = normalize_v3(ve);
- if ((dist < outerfacethickness)&&(dist < mindistedge )) {
- copy_v3_v3(coledge, ve);
- mindistedge = dist,
- deflected=1;
- }
- if (mface->v4) { /* quad */
- closest_to_line_segment_v3(ve, opco, nv3, nv4);
- sub_v3_v3v3(ve, opco, ve);
- dist = normalize_v3(ve);
- if ((dist < outerfacethickness)&&(dist < mindistedge )) {
- copy_v3_v3(coledge, ve);
- mindistedge = dist,
- deflected=1;
- }
-
- closest_to_line_segment_v3(ve, opco, nv1, nv4);
- sub_v3_v3v3(ve, opco, ve);
- dist = normalize_v3(ve);
- if ((dist < outerfacethickness)&&(dist < mindistedge )) {
- copy_v3_v3(coledge, ve);
- mindistedge = dist,
- deflected=1;
- }
-
- }
-
-
- }
- }
- mface++;
mima++;
+ vt++;
}/* while a */
} /* if (ob->pd && ob->pd->deflect) */
BLI_ghashIterator_step(ihash);
+ }
} /* while () */
if (deflected == 1) { // no face but 'outer' edge cylinder sees vert
force_mag_norm =(float)exp(-ee*mindistedge);
if (mindistedge > outerfacethickness*ff)
force_mag_norm =(float)force_mag_norm*fa*(mindistedge - outerfacethickness)*(mindistedge - outerfacethickness);
- Vec3PlusStVec(force, force_mag_norm, coledge);
+ madd_v3_v3fl(force, coledge, force_mag_norm);
*damp=ob->pd->pdef_sbdamp;
if (mindistedge > 0.0f) {
*damp *= (1.0f - mindistedge/outerfacethickness);
@@ -2141,7 +1911,7 @@ static void sb_spring_force(Object *ob, int bpi, BodySpring *bs, float iks, floa
}
- Vec3PlusStVec(bp1->force, (bs->len - distance)*forcefactor, dir);
+ madd_v3_v3fl(bp1->force, dir, (bs->len - distance) * forcefactor);
/* do bp1 <--> bp2 viscous */
sub_v3_v3v3(dvel, bp1->vec, bp2->vec);
@@ -2149,7 +1919,7 @@ static void sb_spring_force(Object *ob, int bpi, BodySpring *bs, float iks, floa
absvel = normalize_v3(dvel);
projvel = dot_v3v3(dir, dvel);
kd *= absvel * projvel;
- Vec3PlusStVec(bp1->force, -kd, dir);
+ madd_v3_v3fl(bp1->force, dir, -kd);
/* do jacobian stuff if needed */
if (nl_flags & NLF_BUILD) {
@@ -2160,7 +1930,7 @@ static void sb_spring_force(Object *ob, int bpi, BodySpring *bs, float iks, floa
// dfdx_spring(ia, ia, op, dir, bs->len, distance, -mpos);
/* depending on my vel */
// dfdv_goal(ia, ia, mvel); // well that ignores geometie
- if (bp2->goal < SOFTGOALSNAP) { /* ommit this bp when it snaps */
+ if (bp2->goal < SOFTGOALSNAP) { /* omit this bp when it snaps */
/* depending on other pos */
// dfdx_spring(ia, ic, op, dir, bs->len, distance, mpos);
/* depending on other vel */
@@ -2223,7 +1993,7 @@ static int _softbody_calc_forces_slice_in_a_thread(Scene *scene, Object *ob, flo
compare = (obp->colball + bp->colball);
sub_v3_v3v3(def, bp->pos, obp->pos);
/* rather check the AABBoxes before ever calulating the real distance */
- /* mathematically it is completly nuts, but performance is pretty much (3) times faster */
+ /* mathematically it is completely nuts, but performance is pretty much (3) times faster */
if ((ABS(def[0]) > compare) || (ABS(def[1]) > compare) || (ABS(def[2]) > compare)) continue;
distance = normalize_v3(def);
if (distance < compare ) {
@@ -2242,22 +2012,22 @@ static int _softbody_calc_forces_slice_in_a_thread(Scene *scene, Object *ob, flo
sub_v3_v3v3(dvel, velcenter, bp->vec);
mul_v3_fl(dvel, _final_mass(ob, bp));
- Vec3PlusStVec(bp->force, f*(1.0f-sb->balldamp), def);
- Vec3PlusStVec(bp->force, sb->balldamp, dvel);
+ madd_v3_v3fl(bp->force, def, f * (1.0f - sb->balldamp));
+ madd_v3_v3fl(bp->force, dvel, sb->balldamp);
/* exploit force(a, b) == -force(b, a) part2/2 */
sub_v3_v3v3(dvel, velcenter, obp->vec);
mul_v3_fl(dvel, _final_mass(ob, bp));
- Vec3PlusStVec(obp->force, sb->balldamp, dvel);
- Vec3PlusStVec(obp->force, -f*(1.0f-sb->balldamp), def);
+ madd_v3_v3fl(obp->force, dvel, sb->balldamp);
+ madd_v3_v3fl(obp->force, def, -f * (1.0f - sb->balldamp));
}
}
}
}
/* naive ball self collision done */
- if (_final_goal(ob, bp) < SOFTGOALSNAP) { /* ommit this bp when it snaps */
+ if (_final_goal(ob, bp) < SOFTGOALSNAP) { /* omit this bp when it snaps */
float auxvect[3];
float velgoal[3];
@@ -2337,16 +2107,16 @@ static int _softbody_calc_forces_slice_in_a_thread(Scene *scene, Object *ob, flo
float kd = 1.0f;
if (sb_deflect_face(ob, bp->pos, facenormal, defforce, &cf, timenow, vel, &intrusion)) {
- if (intrusion < 0.0f) {
- sb->scratch->flag |= SBF_DOFUZZY;
- bp->loc_flag |= SBF_DOFUZZY;
- bp->choke = sb->choke*0.01f;
- }
+ if (intrusion < 0.0f) {
+ sb->scratch->flag |= SBF_DOFUZZY;
+ bp->loc_flag |= SBF_DOFUZZY;
+ bp->choke = sb->choke*0.01f;
+ }
- sub_v3_v3v3(cfforce, bp->vec, vel);
- Vec3PlusStVec(bp->force, -cf*50.0f, cfforce);
+ sub_v3_v3v3(cfforce, bp->vec, vel);
+ madd_v3_v3fl(bp->force, cfforce, -cf * 50.0f);
- Vec3PlusStVec(bp->force, kd, defforce);
+ madd_v3_v3fl(bp->force, defforce, kd);
}
}
@@ -2591,7 +2361,7 @@ static void softbody_calc_forces(Scene *scene, Object *ob, float forcetime, floa
sub_v3_v3v3(def, bp->pos, obp->pos);
/* rather check the AABBoxes before ever calulating the real distance */
- /* mathematically it is completly nuts, but performance is pretty much (3) times faster */
+ /* mathematically it is completely nuts, but performance is pretty much (3) times faster */
if ((ABS(def[0]) > compare) || (ABS(def[1]) > compare) || (ABS(def[2]) > compare)) continue;
distance = normalize_v3(def);
@@ -2611,8 +2381,8 @@ static void softbody_calc_forces(Scene *scene, Object *ob, float forcetime, floa
sub_v3_v3v3(dvel, velcenter, bp->vec);
mul_v3_fl(dvel, _final_mass(ob, bp));
- Vec3PlusStVec(bp->force, f*(1.0f-sb->balldamp), def);
- Vec3PlusStVec(bp->force, sb->balldamp, dvel);
+ madd_v3_v3fl(bp->force, def, f * (1.0f - sb->balldamp));
+ madd_v3_v3fl(bp->force, dvel, sb->balldamp);
if (nl_flags & NLF_BUILD) {
//int ia =3*(sb->totpoint-a);
@@ -2642,17 +2412,15 @@ static void softbody_calc_forces(Scene *scene, Object *ob, float forcetime, floa
sub_v3_v3v3(dvel, velcenter, obp->vec);
mul_v3_fl(dvel, (_final_mass(ob, bp)+_final_mass(ob, obp))/2.0f);
- Vec3PlusStVec(obp->force, sb->balldamp, dvel);
- Vec3PlusStVec(obp->force, -f*(1.0f-sb->balldamp), def);
-
-
+ madd_v3_v3fl(obp->force, dvel, sb->balldamp);
+ madd_v3_v3fl(obp->force, def, -f * (1.0f - sb->balldamp));
}
}
}
}
/* naive ball self collision done */
- if (_final_goal(ob, bp) < SOFTGOALSNAP) { /* ommit this bp when it snaps */
+ if (_final_goal(ob, bp) < SOFTGOALSNAP) { /* omit this bp when it snaps */
float auxvect[3];
float velgoal[3];
@@ -2763,12 +2531,12 @@ static void softbody_calc_forces(Scene *scene, Object *ob, float forcetime, floa
in heun step No1 and leave the heun step No2 adapt to it
so we kind of introduced a implicit solver for this case
*/
- Vec3PlusStVec(bp->pos, -intrusion, facenormal);
+ madd_v3_v3fl(bp->pos, facenormal, -intrusion);
}
else {
sub_v3_v3v3(cfforce, bp->vec, vel);
- Vec3PlusStVec(bp->force, -cf*50.0f, cfforce);
+ madd_v3_v3fl(bp->force, cfforce, -cf * 50.0f);
}
@@ -2778,9 +2546,9 @@ static void softbody_calc_forces(Scene *scene, Object *ob, float forcetime, floa
}
else {
sub_v3_v3v3(cfforce, bp->vec, vel);
- Vec3PlusStVec(bp->force, -cf*50.0f, cfforce);
+ madd_v3_v3fl(bp->force, cfforce, -cf * 50.0f);
}
- Vec3PlusStVec(bp->force, kd, defforce);
+ madd_v3_v3fl(bp->force, defforce, kd);
if (nl_flags & NLF_BUILD) {
// int ia =3*(sb->totpoint-a);
// int op =3*sb->totpoint;
@@ -3183,38 +2951,6 @@ static void interpolate_exciter(Object *ob, int timescale, int time)
- xxxx_to_softbody(Object *ob) : a full (new) copy, creates SB geometry
*/
-static void get_scalar_from_vertexgroup(Object *ob, int vertID, int groupindex, float *target)
-/* result 0 on success, else indicates error number
--- kind of *inverse* result defintion,
--- but this way we can signal error condition to caller
--- and yes this function must not be here but in a *vertex group module*
-*/
-{
- MDeformVert *dv= NULL;
- int i;
-
- /* spot the vert in deform vert list at mesh */
- if (ob->type==OB_MESH) {
- Mesh *me= ob->data;
- if (me->dvert)
- dv = me->dvert + vertID;
- }
- else if (ob->type==OB_LATTICE) { /* not yet supported in softbody btw */
- Lattice *lt= ob->data;
- if (lt->dvert)
- dv = lt->dvert + vertID;
- }
- if (dv) {
- /* Lets see if this vert is in the weight group */
- for (i=0; i<dv->totweight; i++) {
- if (dv->dw[i].def_nr == groupindex) {
- *target= dv->dw[i].weight; /* got it ! */
- break;
- }
- }
- }
-}
-
/* Resetting a Mesh SB object's springs */
/* Spring length are caculted from'raw' mesh vertices that are NOT altered by modifier stack. */
static void springs_from_mesh(Object *ob)
@@ -3263,8 +2999,7 @@ static void mesh_to_softbody(Scene *scene, Object *ob)
BodyPoint *bp;
BodySpring *bs;
int a, totedge;
-
- BKE_mesh_tessface_ensure(me);
+ int defgroup_index, defgroup_index_mass, defgroup_index_spring;
if (ob->softflag & OB_SB_EDGES) totedge= me->totedge;
else totedge= 0;
@@ -3273,9 +3008,13 @@ static void mesh_to_softbody(Scene *scene, Object *ob)
renew_softbody(scene, ob, me->totvert, totedge);
/* we always make body points */
- sb= ob->soft;
+ sb = ob->soft;
bp= sb->bpoint;
+ defgroup_index = me->dvert ? (sb->vertgroup - 1) : -1;
+ defgroup_index_mass = me->dvert ? defgroup_name_index(ob, sb->namedVG_Mass) : -1;
+ defgroup_index_spring = me->dvert ? defgroup_name_index(ob, sb->namedVG_Spring_K) : -1;
+
for (a=0; a<me->totvert; a++, bp++) {
/* get scalar values needed *per vertex* from vertex group functions,
* so we can *paint* them nicly ..
@@ -3283,51 +3022,24 @@ static void mesh_to_softbody(Scene *scene, Object *ob)
* which can be done by caller but still .. i'd like it to go this way
*/
- if ((ob->softflag & OB_SB_GOAL) && sb->vertgroup) { /* even this is a deprecated evil hack */
- /* I'd like to have it .. if (sb->namedVG_Goal[0]) */
-
- get_scalar_from_vertexgroup(ob, a, sb->vertgroup - 1, &bp->goal);
- /* do this always, regardless successful read from vertex group */
- /* this is where '2.5 every thing is animatable' goes wrong in the first place jow_go_for2_5 */
- /* 1st coding action to take : move this to frame level */
- /* reads: leave the bp->goal as it was read from vertex group / or default .. we will need it at per frame call */
- /* should be fixed for meshes */
- // bp->goal= sb->mingoal + bp->goal*goalfac; /* do not do here jow_go_for2_5 */
+ if (ob->softflag & OB_SB_GOAL) {
+ BLI_assert(bp->goal == sb->defgoal);
}
- else {
- /* in consequence if no group was set .. but we want to animate it laters */
- /* logically attach to goal with default first */
- if (ob->softflag & OB_SB_GOAL) {bp->goal = sb->defgoal;}
+ if ((ob->softflag & OB_SB_GOAL) && (defgroup_index != -1)) {
+ bp->goal *= defvert_find_weight(&me->dvert[a], defgroup_index);
}
/* to proof the concept
* this enables per vertex *mass painting*
*/
- if (sb->namedVG_Mass[0]) {
- int defgrp_index = defgroup_name_index(ob, sb->namedVG_Mass);
- /* printf("VGN %s %d\n", sb->namedVG_Mass, defgrp_index); */
- if (defgrp_index != -1) {
- get_scalar_from_vertexgroup(ob, a, defgrp_index, &bp->mass);
- /* 2.5 bp->mass = bp->mass * sb->nodemass; */
- /* printf("bp->mass %f\n", bp->mass); */
-
- }
+ if (defgroup_index_mass != -1) {
+ bp->mass *= defvert_find_weight(&me->dvert[a], defgroup_index_mass);
}
- /* first set the default */
- bp->springweight = 1.0f;
-
- if (sb->namedVG_Spring_K[0]) {
- int defgrp_index = defgroup_name_index(ob, sb->namedVG_Spring_K);
- //printf("VGN %s %d\n", sb->namedVG_Spring_K, defgrp_index);
- if (defgrp_index != -1) {
- get_scalar_from_vertexgroup(ob, a, defgrp_index , &bp->springweight);
- //printf("bp->springweight %f\n", bp->springweight);
- }
+ if (defgroup_index_spring != -1) {
+ bp->springweight *= defvert_find_weight(&me->dvert[a], defgroup_index_spring);
}
-
-
}
/* but we only optionally add body edge springs */
@@ -3349,7 +3061,7 @@ static void mesh_to_softbody(Scene *scene, Object *ob)
build_bps_springlist(ob); /* scan for springs attached to bodypoints ONCE */
/* insert *other second order* springs if desired */
if (sb->secondspring > 0.0000001f) {
- add_2nd_order_springs(ob, sb->secondspring); /* exploits the the first run of build_bps_springlist(ob);*/
+ add_2nd_order_springs(ob, sb->secondspring); /* exploits the first run of build_bps_springlist(ob);*/
build_bps_springlist(ob); /* yes we need to do it again*/
}
springs_from_mesh(ob); /* write the 'rest'-length of the springs */
@@ -3364,24 +3076,32 @@ static void mesh_to_softbody(Scene *scene, Object *ob)
static void mesh_faces_to_scratch(Object *ob)
{
SoftBody *sb= ob->soft;
- Mesh *me= ob->data;
- MFace *mface;
+ const Mesh *me = ob->data;
+ MLoopTri *looptri, *lt;
BodyFace *bodyface;
int a;
/* alloc and copy faces*/
- bodyface = sb->scratch->bodyface = MEM_mallocN(sizeof(BodyFace)*me->totface, "SB_body_Faces");
- //memcpy(sb->scratch->mface, me->mface, sizeof(MFace)*me->totface);
- mface = me->mface;
- for (a=0; a<me->totface; a++, mface++, bodyface++) {
- bodyface->v1 = mface->v1;
- bodyface->v2 = mface->v2;
- bodyface->v3 = mface->v3;
- bodyface->v4 = mface->v4;
+ sb->scratch->totface = poly_to_tri_count(me->totpoly, me->totloop);
+ looptri = lt = MEM_mallocN(sizeof(*looptri) * sb->scratch->totface, __func__);
+ BKE_mesh_recalc_looptri(
+ me->mloop, me->mpoly,
+ me->mvert,
+ me->totloop, me->totpoly,
+ looptri);
+
+ bodyface = sb->scratch->bodyface = MEM_mallocN(sizeof(BodyFace) * sb->scratch->totface, "SB_body_Faces");
+
+ for (a = 0; a < sb->scratch->totface; a++, lt++, bodyface++) {
+ bodyface->v1 = me->mloop[lt->tri[0]].v;
+ bodyface->v2 = me->mloop[lt->tri[1]].v;
+ bodyface->v3 = me->mloop[lt->tri[2]].v;
+ zero_v3(bodyface->ext_force);
bodyface->ext_force[0] = bodyface->ext_force[1] = bodyface->ext_force[2] = 0.0f;
- bodyface->flag =0;
+ bodyface->flag = 0;
}
- sb->scratch->totface = me->totface;
+
+ MEM_freeN(looptri);
}
static void reference_to_scratch(Object *ob)
{
@@ -3486,7 +3206,7 @@ static void makelatticesprings(Lattice *lt, BodySpring *bs, int dostiff, Object
bs->v1 = bpc;
bs->v2 = bpc+dw+dv-1;
bs->springtype=SB_BEND;
- bs->len= globallen((bp+dw+dv-1)->vec, bp->vec, ob);
+ bs->len= globallen((bp+dw+dv-1)->vec, bp->vec, ob);
bs++;
}
}
@@ -3507,6 +3227,7 @@ static void lattice_to_softbody(Scene *scene, Object *ob)
int totvert, totspring = 0, a;
BodyPoint *bp;
BPoint *bpnt = lt->def;
+ int defgroup_index, defgroup_index_mass, defgroup_index_spring;
totvert= lt->pntsu*lt->pntsv*lt->pntsw;
@@ -3525,18 +3246,34 @@ static void lattice_to_softbody(Scene *scene, Object *ob)
sb= ob->soft; /* can be created in renew_softbody() */
bp = sb->bpoint;
+ defgroup_index = lt->dvert ? (sb->vertgroup - 1) : -1;
+ defgroup_index_mass = lt->dvert ? defgroup_name_index(ob, sb->namedVG_Mass) : -1;
+ defgroup_index_spring = lt->dvert ? defgroup_name_index(ob, sb->namedVG_Spring_K) : -1;
+
/* same code used as for mesh vertices */
for (a = 0; a < totvert; a++, bp++, bpnt++) {
- if ((ob->softflag & OB_SB_GOAL) && sb->vertgroup) {
- get_scalar_from_vertexgroup(ob, a, (short) (sb->vertgroup - 1), &bp->goal);
+
+ if (ob->softflag & OB_SB_GOAL) {
+ BLI_assert(bp->goal == sb->defgoal);
+ }
+
+ if ((ob->softflag & OB_SB_GOAL) && (defgroup_index != -1)) {
+ bp->goal *= defvert_find_weight(&lt->dvert[a], defgroup_index);
}
else {
- if (ob->softflag & OB_SB_GOAL) {
- bp->goal = sb->defgoal;
- }
+ bp->goal *= bpnt->weight;
+ }
+
+ if (defgroup_index_mass != -1) {
+ bp->mass *= defvert_find_weight(&lt->dvert[a], defgroup_index_mass);
+ }
+
+ if (defgroup_index_spring != -1) {
+ bp->springweight *= defvert_find_weight(&lt->dvert[a], defgroup_index_spring);
}
}
+
/* create some helper edges to enable SB lattice to be useful at all */
if (ob->softflag & OB_SB_EDGES) {
makelatticesprings(lt, ob->soft->bspring, ob->softflag & OB_SB_QUADS, ob);
@@ -3561,7 +3298,7 @@ static void curve_surf_to_softbody(Scene *scene, Object *ob)
if (ob->softflag & OB_SB_EDGES) {
if (ob->type==OB_CURVE) {
- totspring= totvert - BLI_countlist(&cu->nurb);
+ totspring = totvert - BLI_listbase_count(&cu->nurb);
}
}
@@ -3587,7 +3324,7 @@ static void curve_surf_to_softbody(Scene *scene, Object *ob)
/* not too hard to do, but needs some more code to care for; some one may want look at it JOW 2010/06/12*/
for (bezt=nu->bezt, a=0; a<nu->pntsu; a++, bezt++, bp+=3, curindex+=3) {
if (setgoal) {
- bp->goal= bezt->weight;
+ bp->goal *= bezt->weight;
/* all three triples */
(bp+1)->goal= bp->goal;
@@ -3622,7 +3359,7 @@ static void curve_surf_to_softbody(Scene *scene, Object *ob)
else {
for (bpnt=nu->bp, a=0; a<nu->pntsu*nu->pntsv; a++, bpnt++, bp++, curindex++) {
if (setgoal) {
- bp->goal= bpnt->weight;
+ bp->goal *= bpnt->weight;
}
if (totspring && a>0) {
bs->v1= curindex-1;
diff --git a/source/blender/blenkernel/intern/sound.c b/source/blender/blenkernel/intern/sound.c
index da6ead06d98..0b89931aa75 100644
--- a/source/blender/blenkernel/intern/sound.c
+++ b/source/blender/blenkernel/intern/sound.c
@@ -36,6 +36,7 @@
#include "BLI_blenlib.h"
#include "BLI_math.h"
+#include "BLI_threads.h"
#include "DNA_anim_types.h"
#include "DNA_object_types.h"
@@ -47,7 +48,13 @@
#include "DNA_speaker_types.h"
#ifdef WITH_AUDASPACE
-# include "AUD_C-API.h"
+# include AUD_SOUND_H
+# include AUD_SEQUENCE_H
+# include AUD_HANDLE_H
+# include AUD_SPECIAL_H
+# ifdef WITH_SYSTEM_AUDASPACE
+# include "../../../intern/audaspace/intern/AUD_Set.h"
+# endif
#endif
#include "BKE_global.h"
@@ -59,13 +66,14 @@
#include "BKE_scene.h"
#ifdef WITH_AUDASPACE
-/* evil global ;-) */
+/* evil globals ;-) */
static int sound_cfra;
+static char **audio_device_names = NULL;
#endif
-bSound *sound_new_file(struct Main *bmain, const char *filename)
+bSound *BKE_sound_new_file(struct Main *bmain, const char *filename)
{
- bSound *sound = NULL;
+ bSound *sound;
char str[FILE_MAX];
const char *path;
@@ -86,12 +94,7 @@ bSound *sound_new_file(struct Main *bmain, const char *filename)
BLI_strncpy(sound->name, filename, FILE_MAX);
/* sound->type = SOUND_TYPE_FILE; */ /* XXX unused currently */
- sound_load(bmain, sound);
-
- if (!sound->playback_handle) {
- BKE_libblock_free(bmain, sound);
- sound = NULL;
- }
+ BKE_sound_load(bmain, sound);
return sound;
}
@@ -105,23 +108,30 @@ void BKE_sound_free(bSound *sound)
#ifdef WITH_AUDASPACE
if (sound->handle) {
- AUD_unload(sound->handle);
+ AUD_Sound_free(sound->handle);
sound->handle = NULL;
sound->playback_handle = NULL;
}
if (sound->cache) {
- AUD_unload(sound->cache);
+ AUD_Sound_free(sound->cache);
sound->cache = NULL;
}
- sound_free_waveform(sound);
+ BKE_sound_free_waveform(sound);
+
+ if (sound->spinlock) {
+ BLI_spin_end(sound->spinlock);
+ MEM_freeN(sound->spinlock);
+ sound->spinlock = NULL;
+ }
+
#endif /* WITH_AUDASPACE */
}
#ifdef WITH_AUDASPACE
-static int force_device = -1;
+static const char *force_device = NULL;
#ifdef WITH_JACK
static void sound_sync_callback(void *data, int mode, float time)
@@ -133,46 +143,40 @@ static void sound_sync_callback(void *data, int mode, float time)
while (scene) {
if (scene->audio.flag & AUDIO_SYNC) {
if (mode)
- sound_play_scene(scene);
+ BKE_sound_play_scene(scene);
else
- sound_stop_scene(scene);
- if (scene->sound_scene_handle)
- AUD_seek(scene->sound_scene_handle, time);
+ BKE_sound_stop_scene(scene);
+ if (scene->playback_handle)
+ AUD_Handle_setPosition(scene->playback_handle, time);
}
scene = scene->id.next;
}
}
#endif
-int sound_define_from_str(const char *str)
+void BKE_sound_force_device(const char *device)
{
- if (BLI_strcaseeq(str, "NULL"))
- return AUD_NULL_DEVICE;
- if (BLI_strcaseeq(str, "SDL"))
- return AUD_SDL_DEVICE;
- if (BLI_strcaseeq(str, "OPENAL"))
- return AUD_OPENAL_DEVICE;
- if (BLI_strcaseeq(str, "JACK"))
- return AUD_JACK_DEVICE;
-
- return -1;
+ force_device = device;
}
-void sound_force_device(int device)
+void BKE_sound_init_once(void)
{
- force_device = device;
+ AUD_initOnce();
+ atexit(BKE_sound_exit_once);
}
-void sound_init_once(void)
+static AUD_Device *sound_device;
+
+void *BKE_sound_get_device(void)
{
- AUD_initOnce();
- atexit(sound_exit_once);
+ return sound_device;
}
-void sound_init(struct Main *bmain)
+void BKE_sound_init(struct Main *bmain)
{
AUD_DeviceSpecs specs;
int device, buffersize;
+ const char *device_name;
device = U.audiodevice;
buffersize = U.mixbufsize;
@@ -180,11 +184,23 @@ void sound_init(struct Main *bmain)
specs.format = U.audioformat;
specs.rate = U.audiorate;
- if (force_device >= 0)
- device = force_device;
+ if (force_device == NULL) {
+ int i;
+ char **names = BKE_sound_get_device_names();
+ device_name = names[0];
+
+ /* make sure device is within the bounds of the array */
+ for (i = 0; names[i]; i++) {
+ if (i == device) {
+ device_name = names[i];
+ }
+ }
+ }
+ else
+ device_name = force_device;
if (buffersize < 128)
- buffersize = AUD_DEFAULT_BUFFER_SIZE;
+ buffersize = 1024;
if (specs.rate < AUD_RATE_8000)
specs.rate = AUD_RATE_44100;
@@ -195,35 +211,48 @@ void sound_init(struct Main *bmain)
if (specs.channels <= AUD_CHANNELS_INVALID)
specs.channels = AUD_CHANNELS_STEREO;
- if (!AUD_init(device, specs, buffersize))
- AUD_init(AUD_NULL_DEVICE, specs, buffersize);
+ if (!(sound_device = AUD_init(device_name, specs, buffersize, "Blender")))
+ sound_device = AUD_init("Null", specs, buffersize, "Blender");
- sound_init_main(bmain);
+ BKE_sound_init_main(bmain);
}
-void sound_init_main(struct Main *bmain)
+void BKE_sound_init_main(struct Main *bmain)
{
#ifdef WITH_JACK
- AUD_setSyncCallback(sound_sync_callback, bmain);
+ AUD_setSynchronizerCallback(sound_sync_callback, bmain);
#else
(void)bmain; /* unused */
#endif
}
-void sound_exit(void)
+void BKE_sound_exit(void)
{
- AUD_exit();
+ AUD_exit(sound_device);
+ sound_device = NULL;
}
-void sound_exit_once(void)
+void BKE_sound_exit_once(void)
{
- AUD_exit();
+ AUD_exit(sound_device);
+ sound_device = NULL;
AUD_exitOnce();
+
+#ifdef WITH_SYSTEM_AUDASPACE
+ if (audio_device_names != NULL) {
+ int i;
+ for (i = 0; audio_device_names[i]; i++) {
+ free(audio_device_names[i]);
+ }
+ free(audio_device_names);
+ audio_device_names = NULL;
+ }
+#endif
}
/* XXX unused currently */
#if 0
-bSound *sound_new_buffer(struct Main *bmain, bSound *source)
+bSound *BKE_sound_new_buffer(struct Main *bmain, bSound *source)
{
bSound *sound = NULL;
@@ -238,16 +267,10 @@ bSound *sound_new_buffer(struct Main *bmain, bSound *source)
sound_load(bmain, sound);
- if (!sound->playback_handle)
- {
- BKE_libblock_free(bmain, sound);
- sound = NULL;
- }
-
return sound;
}
-bSound *sound_new_limiter(struct Main *bmain, bSound *source, float start, float end)
+bSound *BKE_sound_new_limiter(struct Main *bmain, bSound *source, float start, float end)
{
bSound *sound = NULL;
@@ -264,17 +287,11 @@ bSound *sound_new_limiter(struct Main *bmain, bSound *source, float start, float
sound_load(bmain, sound);
- if (!sound->playback_handle)
- {
- BKE_libblock_free(bmain, sound);
- sound = NULL;
- }
-
return sound;
}
#endif
-void sound_delete(struct Main *bmain, bSound *sound)
+void BKE_sound_delete(struct Main *bmain, bSound *sound)
{
if (sound) {
BKE_sound_free(sound);
@@ -283,50 +300,44 @@ void sound_delete(struct Main *bmain, bSound *sound)
}
}
-void sound_cache(bSound *sound)
+void BKE_sound_cache(bSound *sound)
{
sound->flags |= SOUND_FLAGS_CACHING;
if (sound->cache)
- AUD_unload(sound->cache);
+ AUD_Sound_free(sound->cache);
- sound->cache = AUD_bufferSound(sound->handle);
+ sound->cache = AUD_Sound_cache(sound->handle);
if (sound->cache)
sound->playback_handle = sound->cache;
else
sound->playback_handle = sound->handle;
}
-void sound_cache_notifying(struct Main *main, bSound *sound)
-{
- sound_cache(sound);
- sound_update_sequencer(main, sound);
-}
-
-void sound_delete_cache(bSound *sound)
+void BKE_sound_delete_cache(bSound *sound)
{
sound->flags &= ~SOUND_FLAGS_CACHING;
if (sound->cache) {
- AUD_unload(sound->cache);
+ AUD_Sound_free(sound->cache);
sound->cache = NULL;
sound->playback_handle = sound->handle;
}
}
-void sound_load(struct Main *bmain, bSound *sound)
+void BKE_sound_load(struct Main *bmain, bSound *sound)
{
if (sound) {
if (sound->cache) {
- AUD_unload(sound->cache);
+ AUD_Sound_free(sound->cache);
sound->cache = NULL;
}
if (sound->handle) {
- AUD_unload(sound->handle);
+ AUD_Sound_free(sound->handle);
sound->handle = NULL;
sound->playback_handle = NULL;
}
- sound_free_waveform(sound);
+ BKE_sound_free_waveform(sound);
/* XXX unused currently */
#if 0
@@ -346,10 +357,10 @@ void sound_load(struct Main *bmain, bSound *sound)
/* but we need a packed file then */
if (pf)
- sound->handle = AUD_loadBuffer((unsigned char *) pf->data, pf->size);
+ sound->handle = AUD_Sound_bufferFile((unsigned char *) pf->data, pf->size);
/* or else load it from disk */
else
- sound->handle = AUD_load(fullpath);
+ sound->handle = AUD_Sound_file(fullpath);
}
/* XXX unused currently */
#if 0
@@ -366,13 +377,13 @@ void sound_load(struct Main *bmain, bSound *sound)
}
#endif
if (sound->flags & SOUND_FLAGS_MONO) {
- void *handle = AUD_monoSound(sound->handle);
- AUD_unload(sound->handle);
+ void *handle = AUD_Sound_rechannel(sound->handle, AUD_CHANNELS_MONO);
+ AUD_Sound_free(sound->handle);
sound->handle = handle;
}
if (sound->flags & SOUND_FLAGS_CACHING) {
- sound->cache = AUD_bufferSound(sound->handle);
+ sound->cache = AUD_Sound_cache(sound->handle);
}
if (sound->cache)
@@ -380,155 +391,157 @@ void sound_load(struct Main *bmain, bSound *sound)
else
sound->playback_handle = sound->handle;
- sound_update_sequencer(bmain, sound);
+ BKE_sound_update_sequencer(bmain, sound);
}
}
-AUD_Device *sound_mixdown(struct Scene *scene, AUD_DeviceSpecs specs, int start, float volume)
+AUD_Device *BKE_sound_mixdown(struct Scene *scene, AUD_DeviceSpecs specs, int start, float volume)
{
return AUD_openMixdownDevice(specs, scene->sound_scene, volume, start / FPS);
}
-void sound_create_scene(struct Scene *scene)
+void BKE_sound_create_scene(struct Scene *scene)
{
/* should be done in version patch, but this gets called before */
if (scene->r.frs_sec_base == 0)
scene->r.frs_sec_base = 1;
- scene->sound_scene = AUD_createSequencer(FPS, scene->audio.flag & AUDIO_MUTE);
- AUD_updateSequencerData(scene->sound_scene, scene->audio.speed_of_sound,
- scene->audio.doppler_factor, scene->audio.distance_model);
- scene->sound_scene_handle = NULL;
+ scene->sound_scene = AUD_Sequence_create(FPS, scene->audio.flag & AUDIO_MUTE);
+ AUD_Sequence_setSpeedOfSound(scene->sound_scene, scene->audio.speed_of_sound);
+ AUD_Sequence_setDopplerFactor(scene->sound_scene, scene->audio.doppler_factor);
+ AUD_Sequence_setDistanceModel(scene->sound_scene, scene->audio.distance_model);
+ scene->playback_handle = NULL;
scene->sound_scrub_handle = NULL;
scene->speaker_handles = NULL;
}
-void sound_destroy_scene(struct Scene *scene)
+void BKE_sound_destroy_scene(struct Scene *scene)
{
- if (scene->sound_scene_handle)
- AUD_stop(scene->sound_scene_handle);
+ if (scene->playback_handle)
+ AUD_Handle_stop(scene->playback_handle);
if (scene->sound_scrub_handle)
- AUD_stop(scene->sound_scrub_handle);
+ AUD_Handle_stop(scene->sound_scrub_handle);
if (scene->sound_scene)
- AUD_destroySequencer(scene->sound_scene);
+ AUD_Sequence_free(scene->sound_scene);
if (scene->speaker_handles)
AUD_destroySet(scene->speaker_handles);
}
-void sound_mute_scene(struct Scene *scene, int muted)
+void BKE_sound_mute_scene(struct Scene *scene, int muted)
{
if (scene->sound_scene)
- AUD_setSequencerMuted(scene->sound_scene, muted);
+ AUD_Sequence_setMuted(scene->sound_scene, muted);
}
-void sound_update_fps(struct Scene *scene)
+void BKE_sound_update_fps(struct Scene *scene)
{
if (scene->sound_scene)
- AUD_setSequencerFPS(scene->sound_scene, FPS);
+ AUD_Sequence_setFPS(scene->sound_scene, FPS);
BKE_sequencer_refresh_sound_length(scene);
}
-void sound_update_scene_listener(struct Scene *scene)
+void BKE_sound_update_scene_listener(struct Scene *scene)
{
- AUD_updateSequencerData(scene->sound_scene, scene->audio.speed_of_sound,
- scene->audio.doppler_factor, scene->audio.distance_model);
+ AUD_Sequence_setSpeedOfSound(scene->sound_scene, scene->audio.speed_of_sound);
+ AUD_Sequence_setDopplerFactor(scene->sound_scene, scene->audio.doppler_factor);
+ AUD_Sequence_setDistanceModel(scene->sound_scene, scene->audio.distance_model);
}
-void *sound_scene_add_scene_sound(struct Scene *scene, struct Sequence *sequence,
+void *BKE_sound_scene_add_scene_sound(struct Scene *scene, struct Sequence *sequence,
int startframe, int endframe, int frameskip)
{
if (scene != sequence->scene) {
const double fps = FPS;
- return AUD_addSequence(scene->sound_scene, sequence->scene->sound_scene,
+ return AUD_Sequence_add(scene->sound_scene, sequence->scene->sound_scene,
startframe / fps, endframe / fps, frameskip / fps);
}
return NULL;
}
-void *sound_scene_add_scene_sound_defaults(struct Scene *scene, struct Sequence *sequence)
+void *BKE_sound_scene_add_scene_sound_defaults(struct Scene *scene, struct Sequence *sequence)
{
- return sound_scene_add_scene_sound(scene, sequence,
+ return BKE_sound_scene_add_scene_sound(scene, sequence,
sequence->startdisp, sequence->enddisp,
sequence->startofs + sequence->anim_startofs);
}
-void *sound_add_scene_sound(struct Scene *scene, struct Sequence *sequence, int startframe, int endframe, int frameskip)
+void *BKE_sound_add_scene_sound(struct Scene *scene, struct Sequence *sequence, int startframe, int endframe, int frameskip)
{
const double fps = FPS;
- void *handle = AUD_addSequence(scene->sound_scene, sequence->sound->playback_handle,
+ void *handle = AUD_Sequence_add(scene->sound_scene, sequence->sound->playback_handle,
startframe / fps, endframe / fps, frameskip / fps);
- AUD_muteSequence(handle, (sequence->flag & SEQ_MUTE) != 0);
- AUD_setSequenceAnimData(handle, AUD_AP_VOLUME, CFRA, &sequence->volume, 0);
- AUD_setSequenceAnimData(handle, AUD_AP_PITCH, CFRA, &sequence->pitch, 0);
- AUD_setSequenceAnimData(handle, AUD_AP_PANNING, CFRA, &sequence->pan, 0);
+ AUD_SequenceEntry_setMuted(handle, (sequence->flag & SEQ_MUTE) != 0);
+ AUD_SequenceEntry_setAnimationData(handle, AUD_AP_VOLUME, CFRA, &sequence->volume, 0);
+ AUD_SequenceEntry_setAnimationData(handle, AUD_AP_PITCH, CFRA, &sequence->pitch, 0);
+ AUD_SequenceEntry_setAnimationData(handle, AUD_AP_PANNING, CFRA, &sequence->pan, 0);
return handle;
}
-void *sound_add_scene_sound_defaults(struct Scene *scene, struct Sequence *sequence)
+void *BKE_sound_add_scene_sound_defaults(struct Scene *scene, struct Sequence *sequence)
{
- return sound_add_scene_sound(scene, sequence,
+ return BKE_sound_add_scene_sound(scene, sequence,
sequence->startdisp, sequence->enddisp,
sequence->startofs + sequence->anim_startofs);
}
-void sound_remove_scene_sound(struct Scene *scene, void *handle)
+void BKE_sound_remove_scene_sound(struct Scene *scene, void *handle)
{
- AUD_removeSequence(scene->sound_scene, handle);
+ AUD_Sequence_remove(scene->sound_scene, handle);
}
-void sound_mute_scene_sound(void *handle, char mute)
+void BKE_sound_mute_scene_sound(void *handle, char mute)
{
- AUD_muteSequence(handle, mute);
+ AUD_SequenceEntry_setMuted(handle, mute);
}
-void sound_move_scene_sound(struct Scene *scene, void *handle, int startframe, int endframe, int frameskip)
+void BKE_sound_move_scene_sound(struct Scene *scene, void *handle, int startframe, int endframe, int frameskip)
{
const double fps = FPS;
- AUD_moveSequence(handle, startframe / fps, endframe / fps, frameskip / fps);
+ AUD_SequenceEntry_move(handle, startframe / fps, endframe / fps, frameskip / fps);
}
-void sound_move_scene_sound_defaults(struct Scene *scene, struct Sequence *sequence)
+void BKE_sound_move_scene_sound_defaults(struct Scene *scene, struct Sequence *sequence)
{
if (sequence->scene_sound) {
- sound_move_scene_sound(scene, sequence->scene_sound,
+ BKE_sound_move_scene_sound(scene, sequence->scene_sound,
sequence->startdisp, sequence->enddisp,
sequence->startofs + sequence->anim_startofs);
}
}
-void sound_update_scene_sound(void *handle, bSound *sound)
+void BKE_sound_update_scene_sound(void *handle, bSound *sound)
{
- AUD_updateSequenceSound(handle, sound->playback_handle);
+ AUD_SequenceEntry_setSound(handle, sound->playback_handle);
}
-void sound_set_cfra(int cfra)
+void BKE_sound_set_cfra(int cfra)
{
sound_cfra = cfra;
}
-void sound_set_scene_volume(struct Scene *scene, float volume)
+void BKE_sound_set_scene_volume(struct Scene *scene, float volume)
{
- AUD_setSequencerAnimData(scene->sound_scene, AUD_AP_VOLUME, CFRA, &volume,
+ AUD_Sequence_setAnimationData(scene->sound_scene, AUD_AP_VOLUME, CFRA, &volume,
(scene->audio.flag & AUDIO_VOLUME_ANIMATED) != 0);
}
-void sound_set_scene_sound_volume(void *handle, float volume, char animated)
+void BKE_sound_set_scene_sound_volume(void *handle, float volume, char animated)
{
- AUD_setSequenceAnimData(handle, AUD_AP_VOLUME, sound_cfra, &volume, animated);
+ AUD_SequenceEntry_setAnimationData(handle, AUD_AP_VOLUME, sound_cfra, &volume, animated);
}
-void sound_set_scene_sound_pitch(void *handle, float pitch, char animated)
+void BKE_sound_set_scene_sound_pitch(void *handle, float pitch, char animated)
{
- AUD_setSequenceAnimData(handle, AUD_AP_PITCH, sound_cfra, &pitch, animated);
+ AUD_SequenceEntry_setAnimationData(handle, AUD_AP_PITCH, sound_cfra, &pitch, animated);
}
-void sound_set_scene_sound_pan(void *handle, float pan, char animated)
+void BKE_sound_set_scene_sound_pan(void *handle, float pan, char animated)
{
- AUD_setSequenceAnimData(handle, AUD_AP_PANNING, sound_cfra, &pan, animated);
+ AUD_SequenceEntry_setAnimationData(handle, AUD_AP_PANNING, sound_cfra, &pan, animated);
}
-void sound_update_sequencer(struct Main *main, bSound *sound)
+void BKE_sound_update_sequencer(struct Main *main, bSound *sound)
{
struct Scene *scene;
@@ -539,55 +552,60 @@ void sound_update_sequencer(struct Main *main, bSound *sound)
static void sound_start_play_scene(struct Scene *scene)
{
- if (scene->sound_scene_handle)
- AUD_stop(scene->sound_scene_handle);
+ AUD_Specs specs;
- AUD_setSequencerDeviceSpecs(scene->sound_scene);
+ if (scene->playback_handle)
+ AUD_Handle_stop(scene->playback_handle);
- if ((scene->sound_scene_handle = AUD_play(scene->sound_scene, 1)))
- AUD_setLoop(scene->sound_scene_handle, -1);
+ specs.channels = AUD_Device_getChannels(sound_device);
+ specs.rate = AUD_Device_getRate(sound_device);
+
+ AUD_Sequence_setSpecs(scene->sound_scene, specs);
+
+ if ((scene->playback_handle = AUD_Device_play(sound_device, scene->sound_scene, 1)))
+ AUD_Handle_setLoopCount(scene->playback_handle, -1);
}
-void sound_play_scene(struct Scene *scene)
+void BKE_sound_play_scene(struct Scene *scene)
{
AUD_Status status;
const float cur_time = (float)((double)CFRA / FPS);
- AUD_lock();
+ AUD_Device_lock(sound_device);
- status = scene->sound_scene_handle ? AUD_getStatus(scene->sound_scene_handle) : AUD_STATUS_INVALID;
+ status = scene->playback_handle ? AUD_Handle_getStatus(scene->playback_handle) : AUD_STATUS_INVALID;
if (status == AUD_STATUS_INVALID) {
sound_start_play_scene(scene);
- if (!scene->sound_scene_handle) {
- AUD_unlock();
+ if (!scene->playback_handle) {
+ AUD_Device_unlock(sound_device);
return;
}
}
if (status != AUD_STATUS_PLAYING) {
- AUD_seek(scene->sound_scene_handle, cur_time);
- AUD_resume(scene->sound_scene_handle);
+ AUD_Handle_setPosition(scene->playback_handle, cur_time);
+ AUD_Handle_resume(scene->playback_handle);
}
if (scene->audio.flag & AUDIO_SYNC)
- AUD_startPlayback();
+ AUD_playSynchronizer();
- AUD_unlock();
+ AUD_Device_unlock(sound_device);
}
-void sound_stop_scene(struct Scene *scene)
+void BKE_sound_stop_scene(struct Scene *scene)
{
- if (scene->sound_scene_handle) {
- AUD_pause(scene->sound_scene_handle);
+ if (scene->playback_handle) {
+ AUD_Handle_pause(scene->playback_handle);
if (scene->audio.flag & AUDIO_SYNC)
- AUD_stopPlayback();
+ AUD_stopSynchronizer();
}
}
-void sound_seek_scene(struct Main *bmain, struct Scene *scene)
+void BKE_sound_seek_scene(struct Main *bmain, struct Scene *scene)
{
AUD_Status status;
bScreen *screen;
@@ -596,109 +614,131 @@ void sound_seek_scene(struct Main *bmain, struct Scene *scene)
const float one_frame = (float)(1.0 / FPS);
const float cur_time = (float)((double)CFRA / FPS);
- AUD_lock();
+ AUD_Device_lock(sound_device);
- status = scene->sound_scene_handle ? AUD_getStatus(scene->sound_scene_handle) : AUD_STATUS_INVALID;
+ status = scene->playback_handle ? AUD_Handle_getStatus(scene->playback_handle) : AUD_STATUS_INVALID;
if (status == AUD_STATUS_INVALID) {
sound_start_play_scene(scene);
- if (!scene->sound_scene_handle) {
- AUD_unlock();
+ if (!scene->playback_handle) {
+ AUD_Device_unlock(sound_device);
return;
}
- AUD_pause(scene->sound_scene_handle);
+ AUD_Handle_pause(scene->playback_handle);
}
animation_playing = 0;
for (screen = bmain->screen.first; screen; screen = screen->id.next) {
if (screen->animtimer) {
animation_playing = 1;
+ break;
}
}
if (scene->audio.flag & AUDIO_SCRUB && !animation_playing) {
+ AUD_Handle_setPosition(scene->playback_handle, cur_time);
if (scene->audio.flag & AUDIO_SYNC) {
- AUD_seek(scene->sound_scene_handle, cur_time);
- AUD_seekSequencer(scene->sound_scene_handle, cur_time);
+ AUD_seekSynchronizer(scene->playback_handle, cur_time);
}
- else {
- AUD_seek(scene->sound_scene_handle, cur_time);
- }
- AUD_resume(scene->sound_scene_handle);
- if (scene->sound_scrub_handle && AUD_getStatus(scene->sound_scrub_handle) != AUD_STATUS_INVALID) {
- AUD_seek(scene->sound_scrub_handle, 0);
+ AUD_Handle_resume(scene->playback_handle);
+ if (scene->sound_scrub_handle && AUD_Handle_getStatus(scene->sound_scrub_handle) != AUD_STATUS_INVALID) {
+ AUD_Handle_setPosition(scene->sound_scrub_handle, 0);
}
else {
if (scene->sound_scrub_handle) {
- AUD_stop(scene->sound_scrub_handle);
+ AUD_Handle_stop(scene->sound_scrub_handle);
}
- scene->sound_scrub_handle = AUD_pauseAfter(scene->sound_scene_handle, one_frame);
+ scene->sound_scrub_handle = AUD_pauseAfter(scene->playback_handle, one_frame);
}
}
else {
if (scene->audio.flag & AUDIO_SYNC) {
- AUD_seekSequencer(scene->sound_scene_handle, cur_time);
+ AUD_seekSynchronizer(scene->playback_handle, cur_time);
}
else {
if (status == AUD_STATUS_PLAYING) {
- AUD_seek(scene->sound_scene_handle, cur_time);
+ AUD_Handle_setPosition(scene->playback_handle, cur_time);
}
}
}
- AUD_unlock();
+ AUD_Device_unlock(sound_device);
}
-float sound_sync_scene(struct Scene *scene)
+float BKE_sound_sync_scene(struct Scene *scene)
{
- if (scene->sound_scene_handle) {
+ if (scene->playback_handle) {
if (scene->audio.flag & AUDIO_SYNC)
- return AUD_getSequencerPosition(scene->sound_scene_handle);
+ return AUD_getSynchronizerPosition(scene->playback_handle);
else
- return AUD_getPosition(scene->sound_scene_handle);
+ return AUD_Handle_getPosition(scene->playback_handle);
}
return NAN_FLT;
}
-int sound_scene_playing(struct Scene *scene)
+int BKE_sound_scene_playing(struct Scene *scene)
{
if (scene->audio.flag & AUDIO_SYNC)
- return AUD_doesPlayback();
+ return AUD_isSynchronizerPlaying();
else
return -1;
}
-void sound_free_waveform(bSound *sound)
+void BKE_sound_free_waveform(bSound *sound)
{
- if (sound->waveform) {
- MEM_freeN(((SoundWaveform *)sound->waveform)->data);
- MEM_freeN(sound->waveform);
+ SoundWaveform *waveform = sound->waveform;
+ if (waveform) {
+ if (waveform->data) {
+ MEM_freeN(waveform->data);
+ }
+ MEM_freeN(waveform);
}
sound->waveform = NULL;
}
-void sound_read_waveform(bSound *sound)
+void BKE_sound_read_waveform(bSound *sound, short *stop)
{
- AUD_SoundInfo info;
-
- info = AUD_getInfo(sound->playback_handle);
+ AUD_SoundInfo info = AUD_getInfo(sound->playback_handle);
+ SoundWaveform *waveform = MEM_mallocN(sizeof(SoundWaveform), "SoundWaveform");
if (info.length > 0) {
- SoundWaveform *waveform = MEM_mallocN(sizeof(SoundWaveform), "SoundWaveform");
int length = info.length * SOUND_WAVE_SAMPLES_PER_SECOND;
-
+
waveform->data = MEM_mallocN(length * sizeof(float) * 3, "SoundWaveform.samples");
- waveform->length = AUD_readSound(sound->playback_handle, waveform->data, length, SOUND_WAVE_SAMPLES_PER_SECOND);
+ waveform->length = AUD_readSound(sound->playback_handle, waveform->data, length, SOUND_WAVE_SAMPLES_PER_SECOND, stop);
+ }
+ else {
+ /* Create an empty waveform here if the sound couldn't be
+ * read. This indicates that reading the waveform is "done",
+ * whereas just setting sound->waveform to NULL causes other
+ * code to think the waveform still needs to be created. */
+ waveform->data = NULL;
+ waveform->length = 0;
+ }
- sound_free_waveform(sound);
- sound->waveform = waveform;
+ if (*stop) {
+ if (waveform->data) {
+ MEM_freeN(waveform->data);
+ }
+ MEM_freeN(waveform);
+ BLI_spin_lock(sound->spinlock);
+ sound->flags &= ~SOUND_FLAGS_WAVEFORM_LOADING;
+ BLI_spin_unlock(sound->spinlock);
+ return;
}
+
+ BKE_sound_free_waveform(sound);
+
+ BLI_spin_lock(sound->spinlock);
+ sound->waveform = waveform;
+ sound->flags &= ~SOUND_FLAGS_WAVEFORM_LOADING;
+ BLI_spin_unlock(sound->spinlock);
}
-void sound_update_scene(Main *bmain, struct Scene *scene)
+void BKE_sound_update_scene(Main *bmain, struct Scene *scene)
{
Object *ob;
Base *base;
@@ -727,38 +767,41 @@ void sound_update_scene(Main *bmain, struct Scene *scene)
if (AUD_removeSet(scene->speaker_handles, strip->speaker_handle)) {
if (speaker->sound) {
- AUD_moveSequence(strip->speaker_handle, (double)strip->start / FPS, FLT_MAX, 0);
+ AUD_SequenceEntry_move(strip->speaker_handle, (double)strip->start / FPS, FLT_MAX, 0);
}
else {
- AUD_removeSequence(scene->sound_scene, strip->speaker_handle);
+ AUD_Sequence_remove(scene->sound_scene, strip->speaker_handle);
strip->speaker_handle = NULL;
}
}
else {
if (speaker->sound) {
- strip->speaker_handle = AUD_addSequence(scene->sound_scene,
+ strip->speaker_handle = AUD_Sequence_add(scene->sound_scene,
speaker->sound->playback_handle,
(double)strip->start / FPS, FLT_MAX, 0);
- AUD_setRelativeSequence(strip->speaker_handle, 0);
+ AUD_SequenceEntry_setRelative(strip->speaker_handle, 0);
}
}
if (strip->speaker_handle) {
const bool mute = ((strip->flag & NLASTRIP_FLAG_MUTED) || (speaker->flag & SPK_MUTED));
AUD_addSet(new_set, strip->speaker_handle);
- AUD_updateSequenceData(strip->speaker_handle, speaker->volume_max,
- speaker->volume_min, speaker->distance_max,
- speaker->distance_reference, speaker->attenuation,
- speaker->cone_angle_outer, speaker->cone_angle_inner,
- speaker->cone_volume_outer);
+ AUD_SequenceEntry_setVolumeMaximum(strip->speaker_handle, speaker->volume_max);
+ AUD_SequenceEntry_setVolumeMinimum(strip->speaker_handle, speaker->volume_min);
+ AUD_SequenceEntry_setDistanceMaximum(strip->speaker_handle, speaker->distance_max);
+ AUD_SequenceEntry_setDistanceReference(strip->speaker_handle, speaker->distance_reference);
+ AUD_SequenceEntry_setAttenuation(strip->speaker_handle, speaker->attenuation);
+ AUD_SequenceEntry_setConeAngleOuter(strip->speaker_handle, speaker->cone_angle_outer);
+ AUD_SequenceEntry_setConeAngleInner(strip->speaker_handle, speaker->cone_angle_inner);
+ AUD_SequenceEntry_setConeVolumeOuter(strip->speaker_handle, speaker->cone_volume_outer);
mat4_to_quat(quat, ob->obmat);
- AUD_setSequenceAnimData(strip->speaker_handle, AUD_AP_LOCATION, CFRA, ob->obmat[3], 1);
- AUD_setSequenceAnimData(strip->speaker_handle, AUD_AP_ORIENTATION, CFRA, quat, 1);
- AUD_setSequenceAnimData(strip->speaker_handle, AUD_AP_VOLUME, CFRA, &speaker->volume, 1);
- AUD_setSequenceAnimData(strip->speaker_handle, AUD_AP_PITCH, CFRA, &speaker->pitch, 1);
- AUD_updateSequenceSound(strip->speaker_handle, speaker->sound->playback_handle);
- AUD_muteSequence(strip->speaker_handle, mute);
+ AUD_SequenceEntry_setAnimationData(strip->speaker_handle, AUD_AP_LOCATION, CFRA, ob->obmat[3], 1);
+ AUD_SequenceEntry_setAnimationData(strip->speaker_handle, AUD_AP_ORIENTATION, CFRA, quat, 1);
+ AUD_SequenceEntry_setAnimationData(strip->speaker_handle, AUD_AP_VOLUME, CFRA, &speaker->volume, 1);
+ AUD_SequenceEntry_setAnimationData(strip->speaker_handle, AUD_AP_PITCH, CFRA, &speaker->pitch, 1);
+ AUD_SequenceEntry_setSound(strip->speaker_handle, speaker->sound->playback_handle);
+ AUD_SequenceEntry_setMuted(strip->speaker_handle, mute);
}
}
}
@@ -766,82 +809,101 @@ void sound_update_scene(Main *bmain, struct Scene *scene)
}
while ((handle = AUD_getSet(scene->speaker_handles))) {
- AUD_removeSequence(scene->sound_scene, handle);
+ AUD_Sequence_remove(scene->sound_scene, handle);
}
if (scene->camera) {
mat4_to_quat(quat, scene->camera->obmat);
- AUD_setSequencerAnimData(scene->sound_scene, AUD_AP_LOCATION, CFRA, scene->camera->obmat[3], 1);
- AUD_setSequencerAnimData(scene->sound_scene, AUD_AP_ORIENTATION, CFRA, quat, 1);
+ AUD_Sequence_setAnimationData(scene->sound_scene, AUD_AP_LOCATION, CFRA, scene->camera->obmat[3], 1);
+ AUD_Sequence_setAnimationData(scene->sound_scene, AUD_AP_ORIENTATION, CFRA, quat, 1);
}
AUD_destroySet(scene->speaker_handles);
scene->speaker_handles = new_set;
}
-void *sound_get_factory(void *sound)
+void *BKE_sound_get_factory(void *sound)
{
return ((bSound *)sound)->playback_handle;
}
/* stupid wrapper because AUD_C-API.h includes Python.h which makesrna doesn't like */
-float sound_get_length(bSound *sound)
+float BKE_sound_get_length(bSound *sound)
{
AUD_SoundInfo info = AUD_getInfo(sound->playback_handle);
return info.length;
}
-bool sound_is_jack_supported(void)
+char **BKE_sound_get_device_names(void)
{
+ if (audio_device_names == NULL) {
+#ifdef WITH_SYSTEM_AUDASPACE
+ audio_device_names = AUD_getDeviceNames();
+#else
+ static const char *names[] = {
+ "Null", "SDL", "OpenAL", "Jack", NULL
+ };
+ audio_device_names = (char **)names;
+#endif
+ }
+
+ return audio_device_names;
+}
+
+bool BKE_sound_is_jack_supported(void)
+{
+#ifdef WITH_SYSTEM_AUDASPACE
+ return 1;
+#else
return (bool)AUD_isJackSupported();
+#endif
}
#else /* WITH_AUDASPACE */
#include "BLI_utildefines.h"
-int sound_define_from_str(const char *UNUSED(str)) { return -1; }
-void sound_force_device(int UNUSED(device)) {}
-void sound_init_once(void) {}
-void sound_init(struct Main *UNUSED(bmain)) {}
-void sound_exit(void) {}
-void sound_exit_once(void) {}
-void sound_cache(struct bSound *UNUSED(sound)) {}
-void sound_delete_cache(struct bSound *UNUSED(sound)) {}
-void sound_load(struct Main *UNUSED(bmain), struct bSound *UNUSED(sound)) {}
-void sound_create_scene(struct Scene *UNUSED(scene)) {}
-void sound_destroy_scene(struct Scene *UNUSED(scene)) {}
-void sound_mute_scene(struct Scene *UNUSED(scene), int UNUSED(muted)) {}
-void *sound_scene_add_scene_sound(struct Scene *UNUSED(scene), struct Sequence *UNUSED(sequence),
- int UNUSED(startframe), int UNUSED(endframe), int UNUSED(frameskip)) { return NULL; }
-void *sound_scene_add_scene_sound_defaults(struct Scene *UNUSED(scene),
- struct Sequence *UNUSED(sequence)) { return NULL; }
-void *sound_add_scene_sound(struct Scene *UNUSED(scene), struct Sequence *UNUSED(sequence), int UNUSED(startframe),
- int UNUSED(endframe), int UNUSED(frameskip)) { return NULL; }
-void *sound_add_scene_sound_defaults(struct Scene *UNUSED(scene), struct Sequence *UNUSED(sequence)) { return NULL; }
-void sound_remove_scene_sound(struct Scene *UNUSED(scene), void *UNUSED(handle)) {}
-void sound_mute_scene_sound(void *UNUSED(handle), char UNUSED(mute)) {}
-void sound_move_scene_sound(struct Scene *UNUSED(scene), void *UNUSED(handle), int UNUSED(startframe),
- int UNUSED(endframe), int UNUSED(frameskip)) {}
-void sound_move_scene_sound_defaults(struct Scene *UNUSED(scene), struct Sequence *UNUSED(sequence)) {}
-void sound_play_scene(struct Scene *UNUSED(scene)) {}
-void sound_stop_scene(struct Scene *UNUSED(scene)) {}
-void sound_seek_scene(struct Main *UNUSED(bmain), struct Scene *UNUSED(scene)) {}
-float sound_sync_scene(struct Scene *UNUSED(scene)) { return NAN_FLT; }
-int sound_scene_playing(struct Scene *UNUSED(scene)) { return -1; }
-void sound_read_waveform(struct bSound *UNUSED(sound)) {}
-void sound_init_main(struct Main *UNUSED(bmain)) {}
-void sound_set_cfra(int UNUSED(cfra)) {}
-void sound_update_sequencer(struct Main *UNUSED(main), struct bSound *UNUSED(sound)) {}
-void sound_update_scene(struct Main *UNUSED(bmain), struct Scene *UNUSED(scene)) {}
-void sound_update_scene_sound(void *UNUSED(handle), struct bSound *UNUSED(sound)) {}
-void sound_update_scene_listener(struct Scene *UNUSED(scene)) {}
-void sound_update_fps(struct Scene *UNUSED(scene)) {}
-void sound_set_scene_sound_volume(void *UNUSED(handle), float UNUSED(volume), char UNUSED(animated)) {}
-void sound_set_scene_sound_pan(void *UNUSED(handle), float UNUSED(pan), char UNUSED(animated)) {}
-void sound_set_scene_volume(struct Scene *UNUSED(scene), float UNUSED(volume)) {}
-void sound_set_scene_sound_pitch(void *UNUSED(handle), float UNUSED(pitch), char UNUSED(animated)) {}
-float sound_get_length(struct bSound *UNUSED(sound)) { return 0; }
-bool sound_is_jack_supported(void) { return false; }
+void BKE_sound_force_device(const char *UNUSED(device)) {}
+void BKE_sound_init_once(void) {}
+void BKE_sound_init(struct Main *UNUSED(bmain)) {}
+void BKE_sound_exit(void) {}
+void BKE_sound_exit_once(void) {}
+void BKE_sound_cache(struct bSound *UNUSED(sound)) {}
+void BKE_sound_delete_cache(struct bSound *UNUSED(sound)) {}
+void BKE_sound_load(struct Main *UNUSED(bmain), struct bSound *UNUSED(sound)) {}
+void BKE_sound_create_scene(struct Scene *UNUSED(scene)) {}
+void BKE_sound_destroy_scene(struct Scene *UNUSED(scene)) {}
+void BKE_sound_mute_scene(struct Scene *UNUSED(scene), int UNUSED(muted)) {}
+void *BKE_sound_scene_add_scene_sound(struct Scene *UNUSED(scene), struct Sequence *UNUSED(sequence),
+ int UNUSED(startframe), int UNUSED(endframe), int UNUSED(frameskip)) { return NULL; }
+void *BKE_sound_scene_add_scene_sound_defaults(struct Scene *UNUSED(scene),
+ struct Sequence *UNUSED(sequence)) { return NULL; }
+void *BKE_sound_add_scene_sound(struct Scene *UNUSED(scene), struct Sequence *UNUSED(sequence), int UNUSED(startframe),
+ int UNUSED(endframe), int UNUSED(frameskip)) { return NULL; }
+void *BKE_sound_add_scene_sound_defaults(struct Scene *UNUSED(scene), struct Sequence *UNUSED(sequence)) { return NULL; }
+void BKE_sound_remove_scene_sound(struct Scene *UNUSED(scene), void *UNUSED(handle)) {}
+void BKE_sound_mute_scene_sound(void *UNUSED(handle), char UNUSED(mute)) {}
+void BKE_sound_move_scene_sound(struct Scene *UNUSED(scene), void *UNUSED(handle), int UNUSED(startframe),
+ int UNUSED(endframe), int UNUSED(frameskip)) {}
+void BKE_sound_move_scene_sound_defaults(struct Scene *UNUSED(scene), struct Sequence *UNUSED(sequence)) {}
+void BKE_sound_play_scene(struct Scene *UNUSED(scene)) {}
+void BKE_sound_stop_scene(struct Scene *UNUSED(scene)) {}
+void BKE_sound_seek_scene(struct Main *UNUSED(bmain), struct Scene *UNUSED(scene)) {}
+float BKE_sound_sync_scene(struct Scene *UNUSED(scene)) { return NAN_FLT; }
+int BKE_sound_scene_playing(struct Scene *UNUSED(scene)) { return -1; }
+void BKE_sound_read_waveform(struct bSound *sound, short *stop) { UNUSED_VARS(sound, stop); }
+void BKE_sound_init_main(struct Main *UNUSED(bmain)) {}
+void BKE_sound_set_cfra(int UNUSED(cfra)) {}
+void BKE_sound_update_sequencer(struct Main *UNUSED(main), struct bSound *UNUSED(sound)) {}
+void BKE_sound_update_scene(struct Main *UNUSED(bmain), struct Scene *UNUSED(scene)) {}
+void BKE_sound_update_scene_sound(void *UNUSED(handle), struct bSound *UNUSED(sound)) {}
+void BKE_sound_update_scene_listener(struct Scene *UNUSED(scene)) {}
+void BKE_sound_update_fps(struct Scene *UNUSED(scene)) {}
+void BKE_sound_set_scene_sound_volume(void *UNUSED(handle), float UNUSED(volume), char UNUSED(animated)) {}
+void BKE_sound_set_scene_sound_pan(void *UNUSED(handle), float UNUSED(pan), char UNUSED(animated)) {}
+void BKE_sound_set_scene_volume(struct Scene *UNUSED(scene), float UNUSED(volume)) {}
+void BKE_sound_set_scene_sound_pitch(void *UNUSED(handle), float UNUSED(pitch), char UNUSED(animated)) {}
+float BKE_sound_get_length(struct bSound *UNUSED(sound)) { return 0; }
+bool BKE_sound_is_jack_supported(void) { return false; }
#endif /* WITH_AUDASPACE */
diff --git a/source/blender/blenkernel/intern/speaker.c b/source/blender/blenkernel/intern/speaker.c
index 08daa09cc85..7a800555144 100644
--- a/source/blender/blenkernel/intern/speaker.c
+++ b/source/blender/blenkernel/intern/speaker.c
@@ -67,6 +67,10 @@ Speaker *BKE_speaker_copy(Speaker *spk)
if (spkn->sound)
spkn->sound->id.us++;
+ if (spk->id.lib) {
+ BKE_id_lib_local_paths(G.main, spk->id.lib, &spkn->id);
+ }
+
return spkn;
}
@@ -126,5 +130,5 @@ void BKE_speaker_free(Speaker *spk)
if (spk->sound)
spk->sound->id.us--;
- BKE_free_animdata((ID *)spk);
+ BKE_animdata_free((ID *)spk);
}
diff --git a/source/blender/blenkernel/intern/subsurf_ccg.c b/source/blender/blenkernel/intern/subsurf_ccg.c
index 2e96eecebcf..509ca9cdd19 100644
--- a/source/blender/blenkernel/intern/subsurf_ccg.c
+++ b/source/blender/blenkernel/intern/subsurf_ccg.c
@@ -41,7 +41,6 @@
#include "MEM_guardedalloc.h"
-#include "DNA_material_types.h"
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
#include "DNA_modifier_types.h"
@@ -60,26 +59,31 @@
#include "BKE_ccg.h"
#include "BKE_cdderivedmesh.h"
#include "BKE_global.h"
+#include "BKE_mesh.h"
#include "BKE_mesh_mapping.h"
#include "BKE_multires.h"
#include "BKE_paint.h"
#include "BKE_scene.h"
#include "BKE_subsurf.h"
-#include "PIL_time.h"
-
#ifndef USE_DYNSIZE
# include "BLI_array.h"
#endif
-#include "GL/glew.h"
-
#include "GPU_draw.h"
#include "GPU_extensions.h"
-#include "GPU_material.h"
+#include "GPU_glew.h"
+#include "GPU_buffers.h"
#include "CCGSubSurf.h"
+#ifdef WITH_OPENSUBDIV
+# include "opensubdiv_capi.h"
+#endif
+
+/* assumes MLoop's are layed out 4 for each poly, in order */
+#define USE_LOOP_LAYOUT_FAST
+
extern GLubyte stipple_quarttone[128]; /* glutil.c, bad level data */
static ThreadRWMutex loops_cache_rwlock = BLI_RWLOCK_INITIALIZER;
@@ -88,7 +92,8 @@ static ThreadRWMutex origindex_cache_rwlock = BLI_RWLOCK_INITIALIZER;
static CCGDerivedMesh *getCCGDerivedMesh(CCGSubSurf *ss,
int drawInteriorEdges,
int useSubsurfUv,
- DerivedMesh *dm);
+ DerivedMesh *dm,
+ bool use_gpu_backend);
static int ccgDM_use_grid_pbvh(CCGDerivedMesh *ccgdm);
///
@@ -305,7 +310,11 @@ static int ss_sync_from_uv(CCGSubSurf *ss, CCGSubSurf *origss, DerivedMesh *dm,
float uv[3] = {0.0f, 0.0f, 0.0f}; /* only first 2 values are written into */
limit[0] = limit[1] = STD_UV_CONNECT_LIMIT;
- vmap = BKE_mesh_uv_vert_map_create(mpoly, mloop, mloopuv, totface, totvert, 0, limit);
+ /* previous behavior here is without accounting for winding, however this causes stretching in
+ * UV map in really simple cases with mirror + subsurf, see second part of T44530. Also, initially
+ * intention is to treat merged vertices from mirror modifier as seams, see code below with ME_VERT_MERGED
+ * This fixes a very old regression (2.49 was correct here) */
+ vmap = BKE_mesh_uv_vert_map_create(mpoly, mloop, mloopuv, totface, totvert, limit, false, true);
if (!vmap)
return 0;
@@ -339,7 +348,7 @@ static int ss_sync_from_uv(CCGSubSurf *ss, CCGSubSurf *origss, DerivedMesh *dm,
eset = BLI_edgeset_new_ex(__func__, BLI_EDGEHASH_SIZE_GUESS_FROM_POLYS(totface));
for (i = 0; i < totface; i++) {
- MPoly *mp = &((MPoly *) mpoly)[i];
+ MPoly *mp = &mpoly[i];
int nverts = mp->totloop;
int j, j_next;
CCGFace *origf = ccgSubSurf_getFace(origss, SET_INT_IN_POINTER(i));
@@ -406,13 +415,96 @@ static int ss_sync_from_uv(CCGSubSurf *ss, CCGSubSurf *origss, DerivedMesh *dm,
return 1;
}
-static void set_subsurf_uv(CCGSubSurf *ss, DerivedMesh *dm, DerivedMesh *result, int n)
+#ifdef WITH_OPENSUBDIV
+static void UNUSED_FUNCTION(set_subsurf_osd_ccg_uv)(CCGSubSurf *ss,
+ DerivedMesh *dm,
+ DerivedMesh *result,
+ int layer_index)
+{
+ CCGFace **faceMap;
+ MTFace *tf;
+ MLoopUV *mluv;
+ CCGFaceIterator fi;
+ int index, gridSize, gridFaces, totface, x, y, S;
+ MLoopUV *dmloopuv = CustomData_get_layer_n(&dm->loopData, CD_MLOOPUV, layer_index);
+ /* need to update both CD_MTFACE & CD_MLOOPUV, hrmf, we could get away with
+ * just tface except applying the modifier then looses subsurf UV */
+ MTFace *tface = CustomData_get_layer_n(&result->faceData, CD_MTFACE, layer_index);
+ MLoopUV *mloopuv = CustomData_get_layer_n(&result->loopData, CD_MLOOPUV, layer_index);
+
+ if (dmloopuv == NULL || (tface == NULL && mloopuv == NULL)) {
+ return;
+ }
+
+ ccgSubSurf_evaluatorSetFVarUV(ss, dm, layer_index);
+
+ /* get some info from CCGSubSurf */
+ totface = ccgSubSurf_getNumFaces(ss);
+ gridSize = ccgSubSurf_getGridSize(ss);
+ gridFaces = gridSize - 1;
+
+ /* make a map from original faces to CCGFaces */
+ faceMap = MEM_mallocN(totface * sizeof(*faceMap), "facemapuv");
+ for (ccgSubSurf_initFaceIterator(ss, &fi); !ccgFaceIterator_isStopped(&fi); ccgFaceIterator_next(&fi)) {
+ CCGFace *f = ccgFaceIterator_getCurrent(&fi);
+ faceMap[GET_INT_FROM_POINTER(ccgSubSurf_getFaceFaceHandle(f))] = f;
+ }
+
+ /* load coordinates from uvss into tface */
+ tf = tface;
+ mluv = mloopuv;
+ for (index = 0; index < totface; index++) {
+ CCGFace *f = faceMap[index];
+ int numVerts = ccgSubSurf_getFaceNumVerts(f);
+ for (S = 0; S < numVerts; S++) {
+ for (y = 0; y < gridFaces; y++) {
+ for (x = 0; x < gridFaces; x++) {
+ const int delta[4][2] = {{0, 0},
+ {0, 1},
+ {1, 1},
+ {1, 0}};
+ float uv[4][2];
+ int i;
+ for (i = 0; i < 4; i++) {
+ const int dx = delta[i][0],
+ dy = delta[i][1];
+ const float grid_u = ((float)(x + dx)) / (gridSize - 1),
+ grid_v = ((float)(y + dy)) / (gridSize - 1);
+ ccgSubSurf_evaluatorFVarUV(ss,
+ index,
+ S,
+ grid_u, grid_v,
+ uv[i]);
+ }
+ if (tf) {
+ copy_v2_v2(tf->uv[0], uv[0]);
+ copy_v2_v2(tf->uv[1], uv[1]);
+ copy_v2_v2(tf->uv[2], uv[2]);
+ copy_v2_v2(tf->uv[3], uv[3]);
+ tf++;
+ }
+ if (mluv) {
+ copy_v2_v2(mluv[0].uv, uv[0]);
+ copy_v2_v2(mluv[1].uv, uv[1]);
+ copy_v2_v2(mluv[2].uv, uv[2]);
+ copy_v2_v2(mluv[3].uv, uv[3]);
+ mluv += 4;
+ }
+ }
+ }
+ }
+ }
+ MEM_freeN(faceMap);
+}
+#endif /* WITH_OPENSUBDIV */
+
+static void set_subsurf_legacy_uv(CCGSubSurf *ss, DerivedMesh *dm, DerivedMesh *result, int n)
{
CCGSubSurf *uvss;
CCGFace **faceMap;
MTFace *tf;
MLoopUV *mluv;
- CCGFaceIterator *fi;
+ CCGFaceIterator fi;
int index, gridSize, gridFaces, /*edgeSize,*/ totface, x, y, S;
MLoopUV *dmloopuv = CustomData_get_layer_n(&dm->loopData, CD_MLOOPUV, n);
/* need to update both CD_MTFACE & CD_MLOOPUV, hrmf, we could get away with
@@ -439,11 +531,10 @@ static void set_subsurf_uv(CCGSubSurf *ss, DerivedMesh *dm, DerivedMesh *result,
/* make a map from original faces to CCGFaces */
faceMap = MEM_mallocN(totface * sizeof(*faceMap), "facemapuv");
- for (fi = ccgSubSurf_getFaceIterator(uvss); !ccgFaceIterator_isStopped(fi); ccgFaceIterator_next(fi)) {
- CCGFace *f = ccgFaceIterator_getCurrent(fi);
+ for (ccgSubSurf_initFaceIterator(uvss, &fi); !ccgFaceIterator_isStopped(&fi); ccgFaceIterator_next(&fi)) {
+ CCGFace *f = ccgFaceIterator_getCurrent(&fi);
faceMap[GET_INT_FROM_POINTER(ccgSubSurf_getFaceFaceHandle(f))] = f;
}
- ccgFaceIterator_free(fi);
/* load coordinates from uvss into tface */
tf = tface;
@@ -488,6 +579,23 @@ static void set_subsurf_uv(CCGSubSurf *ss, DerivedMesh *dm, DerivedMesh *result,
MEM_freeN(faceMap);
}
+static void set_subsurf_uv(CCGSubSurf *ss,
+ DerivedMesh *dm,
+ DerivedMesh *result,
+ int layer_index)
+{
+#ifdef WITH_OPENSUBDIV
+ if (!ccgSubSurf_needGrids(ss)) {
+ /* GPU backend is used, no need to evaluate UVs on CPU. */
+ /* TODO(sergey): Think of how to support edit mode of UVs. */
+ }
+ else
+#endif
+ {
+ set_subsurf_legacy_uv(ss, dm, result, layer_index);
+ }
+}
+
/* face weighting */
typedef struct FaceVertWeightEntry {
FaceVertWeight *weight;
@@ -568,8 +676,10 @@ static void free_ss_weights(WeightTable *wtable)
MEM_freeN(wtable->weight_table);
}
-static void ss_sync_from_derivedmesh(CCGSubSurf *ss, DerivedMesh *dm,
- float (*vertexCos)[3], int useFlatSubdiv)
+static void ss_sync_ccg_from_derivedmesh(CCGSubSurf *ss,
+ DerivedMesh *dm,
+ float (*vertexCos)[3],
+ int useFlatSubdiv)
{
float creaseFactor = (float) ccgSubSurf_getSubdivisionLevels(ss);
#ifndef USE_DYNSIZE
@@ -669,6 +779,37 @@ static void ss_sync_from_derivedmesh(CCGSubSurf *ss, DerivedMesh *dm,
#endif
}
+#ifdef WITH_OPENSUBDIV
+static void ss_sync_osd_from_derivedmesh(CCGSubSurf *ss,
+ DerivedMesh *dm)
+{
+ ccgSubSurf_initFullSync(ss);
+ ccgSubSurf_prepareTopologyRefiner(ss, dm);
+ ccgSubSurf_processSync(ss);
+}
+#endif /* WITH_OPENSUBDIV */
+
+static void ss_sync_from_derivedmesh(CCGSubSurf *ss,
+ DerivedMesh *dm,
+ float (*vertexCos)[3],
+ int use_flat_subdiv)
+{
+#ifdef WITH_OPENSUBDIV
+ /* Reset all related descriptors if actual mesh topology changed or if
+ * other evaluation-related settings changed.
+ */
+ if (!ccgSubSurf_needGrids(ss)) {
+ /* TODO(sergey): Use vertex coordinates and flat subdiv flag. */
+ ccgSubSurf_checkTopologyChanged(ss, dm);
+ ss_sync_osd_from_derivedmesh(ss, dm);
+ }
+ else
+#endif
+ {
+ ss_sync_ccg_from_derivedmesh(ss, dm, vertexCos, use_flat_subdiv);
+ }
+}
+
/***/
static int ccgDM_getVertMapIndex(CCGSubSurf *ss, CCGVert *v)
@@ -700,37 +841,42 @@ static void ccgDM_getMinMax(DerivedMesh *dm, float r_min[3], float r_max[3])
{
CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm;
CCGSubSurf *ss = ccgdm->ss;
- CCGVertIterator *vi;
- CCGEdgeIterator *ei;
- CCGFaceIterator *fi;
+ CCGVertIterator vi;
+ CCGEdgeIterator ei;
+ CCGFaceIterator fi;
CCGKey key;
int i, edgeSize = ccgSubSurf_getEdgeSize(ss);
int gridSize = ccgSubSurf_getGridSize(ss);
+#ifdef WITH_OPENSUBDIV
+ if (ccgdm->useGpuBackend) {
+ ccgSubSurf_getMinMax(ccgdm->ss, r_min, r_max);
+ return;
+ }
+#endif
+
CCG_key_top_level(&key, ss);
if (!ccgSubSurf_getNumVerts(ss))
r_min[0] = r_min[1] = r_min[2] = r_max[0] = r_max[1] = r_max[2] = 0.0;
- for (vi = ccgSubSurf_getVertIterator(ss); !ccgVertIterator_isStopped(vi); ccgVertIterator_next(vi)) {
- CCGVert *v = ccgVertIterator_getCurrent(vi);
+ for (ccgSubSurf_initVertIterator(ss, &vi); !ccgVertIterator_isStopped(&vi); ccgVertIterator_next(&vi)) {
+ CCGVert *v = ccgVertIterator_getCurrent(&vi);
float *co = ccgSubSurf_getVertData(ss, v);
minmax_v3_v3v3(co, r_min, r_max);
}
- ccgVertIterator_free(vi);
- for (ei = ccgSubSurf_getEdgeIterator(ss); !ccgEdgeIterator_isStopped(ei); ccgEdgeIterator_next(ei)) {
- CCGEdge *e = ccgEdgeIterator_getCurrent(ei);
+ for (ccgSubSurf_initEdgeIterator(ss, &ei); !ccgEdgeIterator_isStopped(&ei); ccgEdgeIterator_next(&ei)) {
+ CCGEdge *e = ccgEdgeIterator_getCurrent(&ei);
CCGElem *edgeData = ccgSubSurf_getEdgeDataArray(ss, e);
for (i = 0; i < edgeSize; i++)
minmax_v3_v3v3(CCG_elem_offset_co(&key, edgeData, i), r_min, r_max);
}
- ccgEdgeIterator_free(ei);
- for (fi = ccgSubSurf_getFaceIterator(ss); !ccgFaceIterator_isStopped(fi); ccgFaceIterator_next(fi)) {
- CCGFace *f = ccgFaceIterator_getCurrent(fi);
+ for (ccgSubSurf_initFaceIterator(ss, &fi); !ccgFaceIterator_isStopped(&fi); ccgFaceIterator_next(&fi)) {
+ CCGFace *f = ccgFaceIterator_getCurrent(&fi);
int S, x, y, numVerts = ccgSubSurf_getFaceNumVerts(f);
for (S = 0; S < numVerts; S++) {
@@ -741,7 +887,6 @@ static void ccgDM_getMinMax(DerivedMesh *dm, float r_min[3], float r_max[3])
minmax_v3_v3v3(CCG_grid_elem_co(&key, faceGridData, x, y), r_min, r_max);
}
}
- ccgFaceIterator_free(fi);
}
static int ccgDM_getNumVerts(DerivedMesh *dm)
@@ -758,13 +903,18 @@ static int ccgDM_getNumEdges(DerivedMesh *dm)
return ccgSubSurf_getNumFinalEdges(ccgdm->ss);
}
-static int ccgDM_getNumTessFaces(DerivedMesh *dm)
+static int ccgDM_getNumPolys(DerivedMesh *dm)
{
CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm;
return ccgSubSurf_getNumFinalFaces(ccgdm->ss);
}
+static int ccgDM_getNumTessFaces(DerivedMesh *dm)
+{
+ return dm->numTessFaceData;
+}
+
static int ccgDM_getNumLoops(DerivedMesh *dm)
{
CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm;
@@ -1068,8 +1218,9 @@ void subsurf_copy_grid_hidden(DerivedMesh *dm, const MPoly *mpoly,
const MDisps *md = &mdisps[mpoly[i].loopstart + j];
int hidden_gridsize = BKE_ccg_gridsize(md->level);
int factor = BKE_ccg_factor(level, md->level);
+ BLI_bitmap *hidden = md->hidden;
- if (!md->hidden)
+ if (!hidden)
continue;
for (y = 0; y < gridSize; y++) {
@@ -1078,7 +1229,7 @@ void subsurf_copy_grid_hidden(DerivedMesh *dm, const MPoly *mpoly,
vndx = getFaceIndex(ss, f, j, x, y, edgeSize, gridSize);
offset = (y * factor) * hidden_gridsize + (x * factor);
- if (BLI_BITMAP_TEST(md->hidden, offset))
+ if (BLI_BITMAP_TEST(hidden, offset))
mvert[vndx].flag |= ME_HIDE;
}
}
@@ -1287,7 +1438,7 @@ static void ccgDM_copyFinalFaceArray(DerivedMesh *dm, MFace *mface)
int i = 0;
DMFlagMat *faceFlags = ccgdm->faceFlags;
- totface = ccgSubSurf_getNumFaces(ss);
+ totface = dm->getNumTessFaces(dm);
for (index = 0; index < totface; index++) {
CCGFace *f = ccgdm->faceMap[index].face;
int x, y, S, numVerts = ccgSubSurf_getFaceNumVerts(f);
@@ -1434,9 +1585,9 @@ static void ccgdm_getVertCos(DerivedMesh *dm, float (*cos)[3])
int edgeSize = ccgSubSurf_getEdgeSize(ss);
int gridSize = ccgSubSurf_getGridSize(ss);
int i;
- CCGVertIterator *vi;
- CCGEdgeIterator *ei;
- CCGFaceIterator *fi;
+ CCGVertIterator vi;
+ CCGEdgeIterator ei;
+ CCGFaceIterator fi;
CCGFace **faceMap2;
CCGEdge **edgeMap2;
CCGVert **vertMap2;
@@ -1444,30 +1595,27 @@ static void ccgdm_getVertCos(DerivedMesh *dm, float (*cos)[3])
totvert = ccgSubSurf_getNumVerts(ss);
vertMap2 = MEM_mallocN(totvert * sizeof(*vertMap2), "vertmap");
- for (vi = ccgSubSurf_getVertIterator(ss); !ccgVertIterator_isStopped(vi); ccgVertIterator_next(vi)) {
- CCGVert *v = ccgVertIterator_getCurrent(vi);
+ for (ccgSubSurf_initVertIterator(ss, &vi); !ccgVertIterator_isStopped(&vi); ccgVertIterator_next(&vi)) {
+ CCGVert *v = ccgVertIterator_getCurrent(&vi);
vertMap2[GET_INT_FROM_POINTER(ccgSubSurf_getVertVertHandle(v))] = v;
}
- ccgVertIterator_free(vi);
totedge = ccgSubSurf_getNumEdges(ss);
edgeMap2 = MEM_mallocN(totedge * sizeof(*edgeMap2), "edgemap");
- for (ei = ccgSubSurf_getEdgeIterator(ss), i = 0; !ccgEdgeIterator_isStopped(ei); i++, ccgEdgeIterator_next(ei)) {
- CCGEdge *e = ccgEdgeIterator_getCurrent(ei);
+ for (ccgSubSurf_initEdgeIterator(ss, &ei), i = 0; !ccgEdgeIterator_isStopped(&ei); i++, ccgEdgeIterator_next(&ei)) {
+ CCGEdge *e = ccgEdgeIterator_getCurrent(&ei);
edgeMap2[GET_INT_FROM_POINTER(ccgSubSurf_getEdgeEdgeHandle(e))] = e;
}
- ccgEdgeIterator_free(ei);
totface = ccgSubSurf_getNumFaces(ss);
faceMap2 = MEM_mallocN(totface * sizeof(*faceMap2), "facemap");
- for (fi = ccgSubSurf_getFaceIterator(ss); !ccgFaceIterator_isStopped(fi); ccgFaceIterator_next(fi)) {
- CCGFace *f = ccgFaceIterator_getCurrent(fi);
+ for (ccgSubSurf_initFaceIterator(ss, &fi); !ccgFaceIterator_isStopped(&fi); ccgFaceIterator_next(&fi)) {
+ CCGFace *f = ccgFaceIterator_getCurrent(&fi);
faceMap2[GET_INT_FROM_POINTER(ccgSubSurf_getFaceFaceHandle(f))] = f;
}
- ccgFaceIterator_free(fi);
i = 0;
for (index = 0; index < totface; index++) {
@@ -1517,12 +1665,12 @@ static void ccgDM_foreachMappedVert(
DMForeachFlag flag)
{
CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm;
- CCGVertIterator *vi;
+ CCGVertIterator vi;
CCGKey key;
CCG_key_top_level(&key, ccgdm->ss);
- for (vi = ccgSubSurf_getVertIterator(ccgdm->ss); !ccgVertIterator_isStopped(vi); ccgVertIterator_next(vi)) {
- CCGVert *v = ccgVertIterator_getCurrent(vi);
+ for (ccgSubSurf_initVertIterator(ccgdm->ss, &vi); !ccgVertIterator_isStopped(&vi); ccgVertIterator_next(&vi)) {
+ CCGVert *v = ccgVertIterator_getCurrent(&vi);
const int index = ccgDM_getVertMapIndex(ccgdm->ss, v);
if (index != -1) {
@@ -1531,8 +1679,6 @@ static void ccgDM_foreachMappedVert(
func(userData, index, CCG_elem_co(&key, vd), no, NULL);
}
}
-
- ccgVertIterator_free(vi);
}
static void ccgDM_foreachMappedEdge(
@@ -1542,14 +1688,14 @@ static void ccgDM_foreachMappedEdge(
{
CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm;
CCGSubSurf *ss = ccgdm->ss;
- CCGEdgeIterator *ei;
+ CCGEdgeIterator ei;
CCGKey key;
int i, edgeSize = ccgSubSurf_getEdgeSize(ss);
CCG_key_top_level(&key, ss);
- for (ei = ccgSubSurf_getEdgeIterator(ss); !ccgEdgeIterator_isStopped(ei); ccgEdgeIterator_next(ei)) {
- CCGEdge *e = ccgEdgeIterator_getCurrent(ei);
+ for (ccgSubSurf_initEdgeIterator(ss, &ei); !ccgEdgeIterator_isStopped(&ei); ccgEdgeIterator_next(&ei)) {
+ CCGEdge *e = ccgEdgeIterator_getCurrent(&ei);
const int index = ccgDM_getEdgeMapIndex(ss, e);
if (index != -1) {
@@ -1559,8 +1705,6 @@ static void ccgDM_foreachMappedEdge(
}
}
}
-
- ccgEdgeIterator_free(ei);
}
static void ccgDM_foreachMappedLoop(
@@ -1598,28 +1742,26 @@ static void ccgDM_drawVerts(DerivedMesh *dm)
CCGSubSurf *ss = ccgdm->ss;
int edgeSize = ccgSubSurf_getEdgeSize(ss);
int gridSize = ccgSubSurf_getGridSize(ss);
- CCGVertIterator *vi;
- CCGEdgeIterator *ei;
- CCGFaceIterator *fi;
+ CCGVertIterator vi;
+ CCGEdgeIterator ei;
+ CCGFaceIterator fi;
glBegin(GL_POINTS);
- for (vi = ccgSubSurf_getVertIterator(ss); !ccgVertIterator_isStopped(vi); ccgVertIterator_next(vi)) {
- CCGVert *v = ccgVertIterator_getCurrent(vi);
+ for (ccgSubSurf_initVertIterator(ss, &vi); !ccgVertIterator_isStopped(&vi); ccgVertIterator_next(&vi)) {
+ CCGVert *v = ccgVertIterator_getCurrent(&vi);
glVertex3fv(ccgSubSurf_getVertData(ss, v));
}
- ccgVertIterator_free(vi);
- for (ei = ccgSubSurf_getEdgeIterator(ss); !ccgEdgeIterator_isStopped(ei); ccgEdgeIterator_next(ei)) {
- CCGEdge *e = ccgEdgeIterator_getCurrent(ei);
+ for (ccgSubSurf_initEdgeIterator(ss, &ei); !ccgEdgeIterator_isStopped(&ei); ccgEdgeIterator_next(&ei)) {
+ CCGEdge *e = ccgEdgeIterator_getCurrent(&ei);
int x;
for (x = 1; x < edgeSize - 1; x++)
glVertex3fv(ccgSubSurf_getEdgeData(ss, e, x));
}
- ccgEdgeIterator_free(ei);
- for (fi = ccgSubSurf_getFaceIterator(ss); !ccgFaceIterator_isStopped(fi); ccgFaceIterator_next(fi)) {
- CCGFace *f = ccgFaceIterator_getCurrent(fi);
+ for (ccgSubSurf_initFaceIterator(ss, &fi); !ccgFaceIterator_isStopped(&fi); ccgFaceIterator_next(&fi)) {
+ CCGFace *f = ccgFaceIterator_getCurrent(&fi);
int x, y, S, numVerts = ccgSubSurf_getFaceNumVerts(f);
glVertex3fv(ccgSubSurf_getFaceCenterData(f));
@@ -1631,7 +1773,6 @@ static void ccgDM_drawVerts(DerivedMesh *dm)
for (x = 1; x < gridSize - 1; x++)
glVertex3fv(ccgSubSurf_getFaceGridData(ss, f, S, x, y));
}
- ccgFaceIterator_free(fi);
glEnd();
}
@@ -1652,299 +1793,916 @@ static void ccgdm_pbvh_update(CCGDerivedMesh *ccgdm)
static void ccgDM_drawEdges(DerivedMesh *dm, bool drawLooseEdges, bool drawAllEdges)
{
+ GPUDrawObject *gdo;
+ CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm;
+
+#ifdef WITH_OPENSUBDIV
+ if (ccgdm->useGpuBackend) {
+ /* TODO(sergey): We currently only support all edges drawing. */
+ if (ccgSubSurf_prepareGLMesh(ccgdm->ss, true)) {
+ ccgSubSurf_drawGLMesh(ccgdm->ss, false, -1, -1);
+ }
+ return;
+ }
+#endif
+
+ ccgdm_pbvh_update(ccgdm);
+
+/* old debug feature for edges, unsupported for now */
+#if 0
+ int useAging = 0;
+
+ if (!(G.f & G_BACKBUFSEL)) {
+ CCGSubSurf *ss = ccgdm->ss;
+ ccgSubSurf_getUseAgeCounts(ss, &useAging, NULL, NULL, NULL);
+
+ /* it needs some way to upload this to VBO now */
+ if (useAging) {
+ int ageCol = 255 - ccgSubSurf_getEdgeAge(ss, e) * 4;
+ glColor3ub(0, ageCol > 0 ? ageCol : 0, 0);
+ }
+ }
+#endif
+
+ GPU_edge_setup(dm);
+ gdo = dm->drawObject;
+ if (gdo->edges && gdo->points) {
+ if (drawAllEdges && drawLooseEdges) {
+ GPU_buffer_draw_elements(gdo->edges, GL_LINES, 0, (gdo->totedge - gdo->totinterior) * 2);
+ }
+ else if (drawAllEdges) {
+ GPU_buffer_draw_elements(gdo->edges, GL_LINES, 0, gdo->loose_edge_offset * 2);
+ }
+ else {
+ GPU_buffer_draw_elements(gdo->edges, GL_LINES, 0, gdo->tot_edge_drawn * 2);
+ GPU_buffer_draw_elements(gdo->edges, GL_LINES, gdo->loose_edge_offset * 2, gdo->tot_loose_edge_drawn * 2);
+ }
+ }
+
+ if (gdo->edges && ccgdm->drawInteriorEdges) {
+ GPU_buffer_draw_elements(gdo->edges, GL_LINES, gdo->interior_offset * 2, gdo->totinterior * 2);
+ }
+ GPU_buffers_unbind();
+}
+
+static void ccgDM_drawLooseEdges(DerivedMesh *dm)
+{
+ int start;
+ int count;
+
+#ifdef WITH_OPENSUBDIV
+ CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm;
+ if (ccgdm->useGpuBackend) {
+ /* TODO(sergey): Needs implementation. */
+ return;
+ }
+#endif
+
+ GPU_edge_setup(dm);
+
+ start = (dm->drawObject->loose_edge_offset * 2);
+ count = (dm->drawObject->interior_offset - dm->drawObject->loose_edge_offset) * 2;
+
+ if (count) {
+ GPU_buffer_draw_elements(dm->drawObject->edges, GL_LINES, start, count);
+ }
+
+ GPU_buffers_unbind();
+}
+
+static void ccgDM_NormalFast(float *a, float *b, float *c, float *d, float no[3])
+{
+ float a_cX = c[0] - a[0], a_cY = c[1] - a[1], a_cZ = c[2] - a[2];
+ float b_dX = d[0] - b[0], b_dY = d[1] - b[1], b_dZ = d[2] - b[2];
+
+ no[0] = b_dY * a_cZ - b_dZ * a_cY;
+ no[1] = b_dZ * a_cX - b_dX * a_cZ;
+ no[2] = b_dX * a_cY - b_dY * a_cX;
+
+ normalize_v3(no);
+}
+
+
+static void ccgDM_glNormalFast(float *a, float *b, float *c, float *d)
+{
+ float a_cX = c[0] - a[0], a_cY = c[1] - a[1], a_cZ = c[2] - a[2];
+ float b_dX = d[0] - b[0], b_dY = d[1] - b[1], b_dZ = d[2] - b[2];
+ float no[3];
+
+ no[0] = b_dY * a_cZ - b_dZ * a_cY;
+ no[1] = b_dZ * a_cX - b_dX * a_cZ;
+ no[2] = b_dX * a_cY - b_dY * a_cX;
+
+ /* don't normalize, GL_NORMALIZE is enabled */
+ glNormal3fv(no);
+}
+
+/* Only used by non-editmesh types */
+static void ccgDM_buffer_copy_normal(
+ DerivedMesh *dm, short *varray)
+{
CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm;
CCGSubSurf *ss = ccgdm->ss;
CCGKey key;
- int i, j, edgeSize = ccgSubSurf_getEdgeSize(ss);
- int totedge = ccgSubSurf_getNumEdges(ss);
+ const float (*lnors)[3] = dm->getLoopDataArray(dm, CD_NORMAL);
int gridSize = ccgSubSurf_getGridSize(ss);
- int useAging;
+ int gridFaces = gridSize - 1;
+ DMFlagMat *faceFlags = ccgdm->faceFlags;
+ int i, totface = ccgSubSurf_getNumFaces(ss);
+ int shademodel;
+ int start = 0;
CCG_key_top_level(&key, ss);
- ccgdm_pbvh_update(ccgdm);
- ccgSubSurf_getUseAgeCounts(ss, &useAging, NULL, NULL, NULL);
+ for (i = 0; i < totface; i++) {
+ CCGFace *f = ccgdm->faceMap[i].face;
+ int S, x, y, numVerts = ccgSubSurf_getFaceNumVerts(f);
+ int index = GET_INT_FROM_POINTER(ccgSubSurf_getFaceFaceHandle(f));
+ const float (*ln)[3] = NULL;
- for (j = 0; j < totedge; j++) {
- CCGEdge *e = ccgdm->edgeMap[j].edge;
- CCGElem *edgeData = ccgSubSurf_getEdgeDataArray(ss, e);
+ if (faceFlags) {
+ shademodel = (lnors || (faceFlags[index].flag & ME_SMOOTH)) ? GL_SMOOTH : GL_FLAT;
+ }
+ else {
+ shademodel = GL_SMOOTH;
+ }
- if (!drawLooseEdges && !ccgSubSurf_getEdgeNumFaces(e))
- continue;
+ if (lnors) {
+ ln = lnors;
+ lnors += gridFaces * gridFaces * numVerts * 4;
+ }
- if (!drawAllEdges && ccgdm->edgeFlags && !(ccgdm->edgeFlags[j] & ME_EDGEDRAW))
- continue;
+ for (S = 0; S < numVerts; S++) {
+ CCGElem *faceGridData = ccgSubSurf_getFaceGridDataArray(ss, f, S);
- if (useAging && !(G.f & G_BACKBUFSEL)) {
- int ageCol = 255 - ccgSubSurf_getEdgeAge(ss, e) * 4;
- glColor3ub(0, ageCol > 0 ? ageCol : 0, 0);
- }
+ if (ln) {
+ /* Can't use quad strips here... */
+ for (y = 0; y < gridFaces; y ++) {
+ for (x = 0; x < gridFaces; x ++) {
+ normal_float_to_short_v3(&varray[start + 0], ln[0]);
+ normal_float_to_short_v3(&varray[start + 4], ln[3]);
+ normal_float_to_short_v3(&varray[start + 8], ln[2]);
+ normal_float_to_short_v3(&varray[start + 12], ln[1]);
+
+ start += 16;
+ ln += 4;
+ }
+ }
+ }
+ else if (shademodel == GL_SMOOTH) {
+ for (y = 0; y < gridFaces; y ++) {
+ for (x = 0; x < gridFaces; x ++) {
+ float *a = CCG_grid_elem_no(&key, faceGridData, x, y );
+ float *b = CCG_grid_elem_no(&key, faceGridData, x + 1, y);
+ float *c = CCG_grid_elem_no(&key, faceGridData, x + 1, y + 1);
+ float *d = CCG_grid_elem_no(&key, faceGridData, x, y + 1);
+
+ normal_float_to_short_v3(&varray[start], a);
+ normal_float_to_short_v3(&varray[start + 4], b);
+ normal_float_to_short_v3(&varray[start + 8], c);
+ normal_float_to_short_v3(&varray[start + 12], d);
+
+ start += 16;
+ }
+ }
+ }
+ else {
+ for (y = 0; y < gridFaces; y ++) {
+ for (x = 0; x < gridFaces; x ++) {
+ float f_no[3];
+ short f_no_s[3];
+
+ float *a = CCG_grid_elem_co(&key, faceGridData, x, y );
+ float *b = CCG_grid_elem_co(&key, faceGridData, x + 1, y );
+ float *c = CCG_grid_elem_co(&key, faceGridData, x + 1, y + 1);
+ float *d = CCG_grid_elem_co(&key, faceGridData, x, y + 1);
+
+ ccgDM_NormalFast(a, b, c, d, f_no);
+ normal_float_to_short_v3(f_no_s, f_no);
+
+ copy_v3_v3_short(&varray[start], f_no_s);
+ copy_v3_v3_short(&varray[start + 4], f_no_s);
+ copy_v3_v3_short(&varray[start + 8], f_no_s);
+ copy_v3_v3_short(&varray[start + 12], f_no_s);
- glBegin(GL_LINE_STRIP);
- for (i = 0; i < edgeSize - 1; i++) {
- glVertex3fv(CCG_elem_offset_co(&key, edgeData, i));
- glVertex3fv(CCG_elem_offset_co(&key, edgeData, i + 1));
+ start += 16;
+ }
+ }
+ }
}
- glEnd();
}
+}
- if (useAging && !(G.f & G_BACKBUFSEL)) {
- glColor3ub(0, 0, 0);
+typedef struct FaceCount {
+ unsigned int i_visible;
+ unsigned int i_hidden;
+ unsigned int i_tri_visible;
+ unsigned int i_tri_hidden;
+} FaceCount;
+
+
+/* Only used by non-editmesh types */
+static void ccgDM_buffer_copy_triangles(
+ DerivedMesh *dm, unsigned int *varray,
+ const int *mat_orig_to_new)
+{
+ GPUBufferMaterial *gpumat, *gpumaterials = dm->drawObject->materials;
+ const int gpu_totmat = dm->drawObject->totmaterial;
+ const short dm_totmat = dm->totmat;
+ CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm;
+ CCGSubSurf *ss = ccgdm->ss;
+ CCGKey key;
+ int gridSize = ccgSubSurf_getGridSize(ss);
+ int gridFaces = gridSize - 1;
+ DMFlagMat *faceFlags = ccgdm->faceFlags;
+ int i, totface = ccgSubSurf_getNumFaces(ss);
+ short mat_nr = -1;
+ int start;
+ int totloops = 0;
+ FaceCount *fc = MEM_mallocN(sizeof(*fc) * gpu_totmat, "gpumaterial.facecount");
+
+ CCG_key_top_level(&key, ss);
+
+ for (i = 0; i < gpu_totmat; i++) {
+ fc[i].i_visible = 0;
+ fc[i].i_tri_visible = 0;
+ fc[i].i_hidden = gpumaterials[i].totpolys - 1;
+ fc[i].i_tri_hidden = gpumaterials[i].totelements - 1;
}
- if (ccgdm->drawInteriorEdges) {
- int totface = ccgSubSurf_getNumFaces(ss);
+ for (i = 0; i < totface; i++) {
+ CCGFace *f = ccgdm->faceMap[i].face;
+ int S, x, y, numVerts = ccgSubSurf_getFaceNumVerts(f);
+ int index = GET_INT_FROM_POINTER(ccgSubSurf_getFaceFaceHandle(f));
+ bool is_hidden;
+ int mati;
- for (j = 0; j < totface; j++) {
- CCGFace *f = ccgdm->faceMap[j].face;
- int S, x, y, numVerts = ccgSubSurf_getFaceNumVerts(f);
+ if (faceFlags) {
+ mat_nr = ME_MAT_NR_TEST(faceFlags[index].mat_nr, dm_totmat);
+ is_hidden = (faceFlags[index].flag & ME_HIDE) != 0;
+ }
+ else {
+ mat_nr = 0;
+ is_hidden = false;
+ }
+ mati = mat_orig_to_new[mat_nr];
+ gpumat = dm->drawObject->materials + mati;
+ if (is_hidden) {
for (S = 0; S < numVerts; S++) {
- CCGElem *faceGridData = ccgSubSurf_getFaceGridDataArray(ss, f, S);
+ for (y = 0; y < gridFaces; y++) {
+ for (x = 0; x < gridFaces; x++) {
+ start = gpumat->start + fc[mati].i_tri_hidden;
- glBegin(GL_LINE_STRIP);
- for (x = 0; x < gridSize; x++)
- glVertex3fv(CCG_elem_offset_co(&key, faceGridData, x));
- glEnd();
- for (y = 1; y < gridSize - 1; y++) {
- glBegin(GL_LINE_STRIP);
- for (x = 0; x < gridSize; x++)
- glVertex3fv(CCG_grid_elem_co(&key, faceGridData, x, y));
- glEnd();
+ varray[start--] = totloops + 1;
+ varray[start--] = totloops + 2;
+ varray[start--] = totloops + 3;
+
+ varray[start--] = totloops;
+ varray[start--] = totloops + 1;
+ varray[start--] = totloops + 3;
+
+ fc[mati].i_tri_hidden -= 6;
+
+ totloops += 4;
+ }
}
- for (x = 1; x < gridSize - 1; x++) {
- glBegin(GL_LINE_STRIP);
- for (y = 0; y < gridSize; y++)
- glVertex3fv(CCG_grid_elem_co(&key, faceGridData, x, y));
- glEnd();
+ }
+ gpumat->polys[fc[mati].i_hidden--] = i;
+ }
+ else {
+ for (S = 0; S < numVerts; S++) {
+ for (y = 0; y < gridFaces; y++) {
+ for (x = 0; x < gridFaces; x++) {
+ start = gpumat->start + fc[mati].i_tri_visible;
+
+ varray[start++] = totloops + 3;
+ varray[start++] = totloops + 2;
+ varray[start++] = totloops + 1;
+
+ varray[start++] = totloops + 3;
+ varray[start++] = totloops + 1;
+ varray[start++] = totloops;
+
+ fc[mati].i_tri_visible += 6;
+
+ totloops += 4;
+ }
}
}
+ gpumat->polys[fc[mati].i_visible++] = i;
}
}
+
+ /* set the visible polygons */
+ for (i = 0; i < gpu_totmat; i++) {
+ gpumaterials[i].totvisiblepolys = fc[i].i_visible;
+ }
+
+ MEM_freeN(fc);
}
-static void ccgDM_drawLooseEdges(DerivedMesh *dm)
+
+/* Only used by non-editmesh types */
+static void ccgDM_buffer_copy_vertex(
+ DerivedMesh *dm, void *varray_p)
{
+ float *varray = varray_p;
CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm;
CCGSubSurf *ss = ccgdm->ss;
CCGKey key;
+ int gridSize = ccgSubSurf_getGridSize(ss);
+ int gridFaces = gridSize - 1;
+ int i, totface = ccgSubSurf_getNumFaces(ss);
int totedge = ccgSubSurf_getNumEdges(ss);
- int i, j, edgeSize = ccgSubSurf_getEdgeSize(ss);
+ int start = 0;
+ int edgeSize = ccgSubSurf_getEdgeSize(ss);
CCG_key_top_level(&key, ss);
- for (j = 0; j < totedge; j++) {
- CCGEdge *e = ccgdm->edgeMap[j].edge;
+ for (i = 0; i < totface; i++) {
+ CCGFace *f = ccgdm->faceMap[i].face;
+ int S, x, y, numVerts = ccgSubSurf_getFaceNumVerts(f);
+
+ for (S = 0; S < numVerts; S++) {
+ CCGElem *faceGridData = ccgSubSurf_getFaceGridDataArray(ss, f, S);
+ for (y = 0; y < gridFaces; y++) {
+ for (x = 0; x < gridFaces; x++) {
+ float *a = CCG_grid_elem_co(&key, faceGridData, x, y);
+ float *b = CCG_grid_elem_co(&key, faceGridData, x + 1, y);
+ float *c = CCG_grid_elem_co(&key, faceGridData, x + 1, y + 1);
+ float *d = CCG_grid_elem_co(&key, faceGridData, x, y + 1);
+
+ copy_v3_v3(&varray[start], a);
+ copy_v3_v3(&varray[start + 3], b);
+ copy_v3_v3(&varray[start + 6], c);
+ copy_v3_v3(&varray[start + 9], d);
+
+ start += 12;
+ }
+ }
+ }
+ }
+
+ /* upload loose points */
+ for (i = 0; i < totedge; i++) {
+ CCGEdge *e = ccgdm->edgeMap[i].edge;
CCGElem *edgeData = ccgSubSurf_getEdgeDataArray(ss, e);
if (!ccgSubSurf_getEdgeNumFaces(e)) {
- glBegin(GL_LINE_STRIP);
- for (i = 0; i < edgeSize - 1; i++) {
- glVertex3fv(CCG_elem_offset_co(&key, edgeData, i));
- glVertex3fv(CCG_elem_offset_co(&key, edgeData, i + 1));
+ int j = 0;
+ for (j = 0; j < edgeSize; j++) {
+ copy_v3_v3(&varray[start], CCG_elem_offset_co(&key, edgeData, j));
+ start += 3;
}
- glEnd();
}
}
}
-static void ccgDM_glNormalFast(float *a, float *b, float *c, float *d)
+/* Only used by non-editmesh types */
+static void ccgDM_buffer_copy_color(
+ DerivedMesh *dm, unsigned char *varray,
+ const void *user_data)
{
- float a_cX = c[0] - a[0], a_cY = c[1] - a[1], a_cZ = c[2] - a[2];
- float b_dX = d[0] - b[0], b_dY = d[1] - b[1], b_dZ = d[2] - b[2];
- float no[3];
+ CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm;
+ CCGSubSurf *ss = ccgdm->ss;
+ CCGKey key;
+ const char *mloopcol = user_data;
+ int gridSize = ccgSubSurf_getGridSize(ss);
+ int gridFaces = gridSize - 1;
+ int i, totface = ccgSubSurf_getNumFaces(ss);
+ int start = 0;
+ int iface = 0;
- no[0] = b_dY * a_cZ - b_dZ * a_cY;
- no[1] = b_dZ * a_cX - b_dX * a_cZ;
- no[2] = b_dX * a_cY - b_dY * a_cX;
+ CCG_key_top_level(&key, ss);
- /* don't normalize, GL_NORMALIZE is enabled */
- glNormal3fv(no);
+
+ for (i = 0; i < totface; i++) {
+ CCGFace *f = ccgdm->faceMap[i].face;
+ int S, x, y, numVerts = ccgSubSurf_getFaceNumVerts(f);
+
+ for (S = 0; S < numVerts; S++) {
+ for (y = 0; y < gridFaces; y++) {
+ for (x = 0; x < gridFaces; x++) {
+ copy_v3_v3_char((char *)&varray[start + 0], &mloopcol[iface * 16 + 0]);
+ copy_v3_v3_char((char *)&varray[start + 3], &mloopcol[iface * 16 + 12]);
+ copy_v3_v3_char((char *)&varray[start + 6], &mloopcol[iface * 16 + 8]);
+ copy_v3_v3_char((char *)&varray[start + 9], &mloopcol[iface * 16 + 4]);
+
+ start += 12;
+ iface++;
+ }
+ }
+ }
+ }
}
-/* Only used by non-editmesh types */
-static void ccgDM_drawFacesSolid(DerivedMesh *dm, float (*partial_redraw_planes)[4], bool fast, DMSetMaterial setMaterial)
+static void ccgDM_buffer_copy_uv(
+ DerivedMesh *dm, void *varray_p)
{
+ float *varray = varray_p;
CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm;
CCGSubSurf *ss = ccgdm->ss;
CCGKey key;
- short (*lnors)[4][3] = dm->getTessFaceDataArray(dm, CD_TESSLOOPNORMAL);
+ MLoopUV *mloopuv = DM_get_loop_data_layer(dm, CD_MLOOPUV);
int gridSize = ccgSubSurf_getGridSize(ss);
int gridFaces = gridSize - 1;
- DMFlagMat *faceFlags = ccgdm->faceFlags;
- int step = (fast) ? gridSize - 1 : 1;
int i, totface = ccgSubSurf_getNumFaces(ss);
- int drawcurrent = 0, matnr = -1, shademodel = -1;
+ int start = 0;
CCG_key_top_level(&key, ss);
- ccgdm_pbvh_update(ccgdm);
- if (ccgdm->pbvh && ccgdm->multires.mmd && !fast) {
- if (dm->numTessFaceData) {
- BKE_pbvh_draw(ccgdm->pbvh, partial_redraw_planes, NULL,
- setMaterial, false);
- glShadeModel(GL_FLAT);
+ for (i = 0; i < totface; i++) {
+ CCGFace *f = ccgdm->faceMap[i].face;
+ int S, x, y, numVerts = ccgSubSurf_getFaceNumVerts(f);
+
+ for (S = 0; S < numVerts; S++) {
+ for (y = 0; y < gridFaces; y++) {
+ for (x = 0; x < gridFaces; x++) {
+ copy_v2_v2(&varray[start + 0], mloopuv[0].uv);
+ copy_v2_v2(&varray[start + 2], mloopuv[3].uv);
+ copy_v2_v2(&varray[start + 4], mloopuv[2].uv);
+ copy_v2_v2(&varray[start + 6], mloopuv[1].uv);
+
+ mloopuv += 4;
+ start += 8;
+ }
+ }
}
+ }
+}
- return;
+static void ccgDM_buffer_copy_uv_texpaint(
+ DerivedMesh *dm, float *varray)
+{
+ CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm;
+ CCGSubSurf *ss = ccgdm->ss;
+ CCGKey key;
+ int gridSize = ccgSubSurf_getGridSize(ss);
+ int gridFaces = gridSize - 1;
+ int i, totface = ccgSubSurf_getNumFaces(ss);
+ int start = 0;
+ DMFlagMat *faceFlags = ccgdm->faceFlags;
+ int dm_totmat = dm->totmat;
+ MLoopUV **mloopuv_base;
+ MLoopUV *stencil_base;
+ int stencil;
+
+ CCG_key_top_level(&key, ss);
+
+ /* should have been checked for before, reassert */
+ BLI_assert(DM_get_loop_data_layer(dm, CD_MLOOPUV));
+ mloopuv_base = MEM_mallocN(dm_totmat * sizeof(*mloopuv_base), "texslots");
+
+ for (i = 0; i < dm_totmat; i++) {
+ mloopuv_base[i] = DM_paint_uvlayer_active_get(dm, i);
}
+ stencil = CustomData_get_stencil_layer(&dm->loopData, CD_MLOOPUV);
+ stencil_base = CustomData_get_layer_n(&dm->loopData, CD_MLOOPUV, stencil);
+
+ start = 0;
+
for (i = 0; i < totface; i++) {
CCGFace *f = ccgdm->faceMap[i].face;
int S, x, y, numVerts = ccgSubSurf_getFaceNumVerts(f);
int index = GET_INT_FROM_POINTER(ccgSubSurf_getFaceFaceHandle(f));
- int new_matnr, new_shademodel;
- short (*ln)[4][3] = NULL;
+ int matnr;
if (faceFlags) {
- new_shademodel = (lnors || (faceFlags[index].flag & ME_SMOOTH)) ? GL_SMOOTH : GL_FLAT;
- new_matnr = faceFlags[index].mat_nr;
+ matnr = faceFlags[index].mat_nr;
}
else {
- new_shademodel = GL_SMOOTH;
- new_matnr = 0;
+ matnr = 0;
}
- if (lnors) {
- ln = lnors;
- lnors += gridFaces * gridFaces * numVerts;
+ for (S = 0; S < numVerts; S++) {
+ for (y = 0; y < gridFaces; y++) {
+ for (x = 0; x < gridFaces; x++) {
+ /* divide by 4, gives us current loop-index */
+ unsigned int i_ml = start / 4;
+ copy_v2_v2(&varray[start + 0], mloopuv_base[matnr][i_ml + 0].uv);
+ copy_v2_v2(&varray[start + 2], stencil_base[i_ml + 0].uv);
+ copy_v2_v2(&varray[start + 4], mloopuv_base[matnr][i_ml + 3].uv);
+ copy_v2_v2(&varray[start + 6], stencil_base[i_ml + 3].uv);
+ copy_v2_v2(&varray[start + 8], mloopuv_base[matnr][i_ml + 2].uv);
+ copy_v2_v2(&varray[start + 10], stencil_base[i_ml + 2].uv);
+ copy_v2_v2(&varray[start + 12], mloopuv_base[matnr][i_ml + 1].uv);
+ copy_v2_v2(&varray[start + 14], stencil_base[i_ml + 1].uv);
+ start += 16;
+ }
+ }
}
+ }
- if (shademodel != new_shademodel || matnr != new_matnr) {
- matnr = new_matnr;
- shademodel = new_shademodel;
+ MEM_freeN(mloopuv_base);
+}
- if (setMaterial)
- drawcurrent = setMaterial(matnr + 1, NULL);
- else
- drawcurrent = 1;
+static void ccgDM_buffer_copy_uvedge(
+ DerivedMesh *dm, float *varray)
+{
+ int i, totpoly;
+ int start;
+ const MLoopUV *mloopuv;
+#ifndef USE_LOOP_LAYOUT_FAST
+ const MPoly *mpoly = dm->getPolyArray(dm);
+#endif
- glShadeModel(shademodel);
+ if ((mloopuv = DM_get_loop_data_layer(dm, CD_MLOOPUV)) == NULL) {
+ return;
+ }
+
+ totpoly = dm->getNumPolys(dm);
+ start = 0;
+
+#ifndef USE_LOOP_LAYOUT_FAST
+ for (i = 0; i < totpoly; i++, mpoly++) {
+ for (j = 0; j < mpoly->totloop; j++) {
+ copy_v2_v2(&varray[start], mloopuv[mpoly->loopstart + j].uv);
+ copy_v2_v2(&varray[start + 2], mloopuv[mpoly->loopstart + (j + 1) % mpoly->totloop].uv);
+ start += 4;
}
+ }
+#else
+ for (i = 0; i < totpoly; i++) {
+ copy_v2_v2(&varray[start + 0], mloopuv[(i * 4) + 0].uv);
+ copy_v2_v2(&varray[start + 2], mloopuv[(i * 4) + 1].uv);
- if (!drawcurrent)
- continue;
+ copy_v2_v2(&varray[start + 4], mloopuv[(i * 4) + 1].uv);
+ copy_v2_v2(&varray[start + 6], mloopuv[(i * 4) + 2].uv);
- for (S = 0; S < numVerts; S++) {
- CCGElem *faceGridData = ccgSubSurf_getFaceGridDataArray(ss, f, S);
+ copy_v2_v2(&varray[start + 8], mloopuv[(i * 4) + 2].uv);
+ copy_v2_v2(&varray[start + 10], mloopuv[(i * 4) + 3].uv);
- if (ln) {
- /* Can't use quad strips here... */
- glBegin(GL_QUADS);
- for (y = 0; y < gridFaces; y += step) {
- for (x = 0; x < gridFaces; x += step) {
- float *a = CCG_grid_elem_co(&key, faceGridData, x, y + 0);
- float *b = CCG_grid_elem_co(&key, faceGridData, x + step, y + 0);
- float *c = CCG_grid_elem_co(&key, faceGridData, x + step, y + step);
- float *d = CCG_grid_elem_co(&key, faceGridData, x, y + step);
-
- glNormal3sv(ln[0][1]);
- glVertex3fv(d);
- glNormal3sv(ln[0][2]);
- glVertex3fv(c);
- glNormal3sv(ln[0][3]);
- glVertex3fv(b);
- glNormal3sv(ln[0][0]);
- glVertex3fv(a);
- ln += step;
- }
+ copy_v2_v2(&varray[start + 12], mloopuv[(i * 4) + 3].uv);
+ copy_v2_v2(&varray[start + 14], mloopuv[(i * 4) + 0].uv);
+
+ start += 16;
+ }
+#endif
+}
+
+static void ccgDM_buffer_copy_edge(
+ DerivedMesh *dm, unsigned int *varray)
+{
+ CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm;
+ CCGSubSurf *ss = ccgdm->ss;
+ /* getEdgeSuze returns num of verts, edges is one less */
+ int i, j, edgeSize = ccgSubSurf_getEdgeSize(ss) - 1;
+ int totedge = ccgSubSurf_getNumEdges(ss);
+ int grid_face_side = ccgSubSurf_getGridSize(ss) - 1;
+ int totface = ccgSubSurf_getNumFaces(ss);
+ unsigned int index_start;
+ unsigned int tot_interior = 0;
+ unsigned int grid_tot_face = grid_face_side * grid_face_side;
+
+ unsigned int iloose, inorm, iloosehidden, inormhidden;
+ unsigned int tot_loose_hidden = 0, tot_loose = 0;
+ unsigned int tot_hidden = 0, tot = 0;
+ unsigned int iloosevert;
+ /* int tot_interior = 0; */
+
+ /* first, handle hidden/loose existing edges, then interior edges */
+ for (j = 0; j < totedge; j++) {
+ CCGEdge *e = ccgdm->edgeMap[j].edge;
+
+ if (ccgdm->edgeFlags && !(ccgdm->edgeFlags[j] & ME_EDGEDRAW)) {
+ if (!ccgSubSurf_getEdgeNumFaces(e)) tot_loose_hidden++;
+ else tot_hidden++;
+ }
+ else {
+ if (!ccgSubSurf_getEdgeNumFaces(e)) tot_loose++;
+ else tot++;
+ }
+ }
+
+ inorm = 0;
+ inormhidden = tot * edgeSize;
+ iloose = (tot + tot_hidden) * edgeSize;
+ iloosehidden = (tot + tot_hidden + tot_loose) * edgeSize;
+ iloosevert = dm->drawObject->tot_loop_verts;
+
+ /* part one, handle all normal edges */
+ for (j = 0; j < totedge; j++) {
+ CCGFace *f;
+ int fhandle = 0;
+ int totvert = 0;
+ unsigned int S = 0;
+ CCGEdge *e = ccgdm->edgeMap[j].edge;
+ bool isloose = !ccgSubSurf_getEdgeNumFaces(e);
+
+ if (!isloose) {
+ CCGVert *v1, *v2;
+ CCGVert *ev1 = ccgSubSurf_getEdgeVert0(e);
+ CCGVert *ev2 = ccgSubSurf_getEdgeVert1(e);
+
+ f = ccgSubSurf_getEdgeFace(e, 0);
+ fhandle = GET_INT_FROM_POINTER(ccgSubSurf_getFaceFaceHandle(f));
+ totvert = ccgSubSurf_getFaceNumVerts(f);
+
+ /* find the index of vertices in the face */
+ for (i = 0; i < totvert; i++) {
+ v1 = ccgSubSurf_getFaceVert(f, i);
+ v2 = ccgSubSurf_getFaceVert(f, (i + 1) % totvert);
+
+ if ((ev1 == v1 && ev2 == v2) || (ev1 == v2 && ev2 == v1)) {
+ S = i;
+ break;
}
- glEnd();
}
- else if (shademodel == GL_SMOOTH) {
- for (y = 0; y < gridFaces; y += step) {
- glBegin(GL_QUAD_STRIP);
- for (x = 0; x < gridSize; x += step) {
- CCGElem *a = CCG_grid_elem(&key, faceGridData, x, y + 0);
- CCGElem *b = CCG_grid_elem(&key, faceGridData, x, y + step);
-
- glNormal3fv(CCG_elem_no(&key, a));
- glVertex3fv(CCG_elem_co(&key, a));
- glNormal3fv(CCG_elem_no(&key, b));
- glVertex3fv(CCG_elem_co(&key, b));
- }
- glEnd();
+ }
+
+ if (ccgdm->edgeFlags && !(ccgdm->edgeFlags[j] & ME_EDGEDRAW)) {
+ if (isloose) {
+ for (i = 0; i < edgeSize; i++) {
+ varray[iloosehidden * 2] = iloosevert;
+ varray[iloosehidden * 2 + 1] = iloosevert + 1;
+ iloosehidden++;
+ iloosevert++;
}
+ /* we are through with this loose edge and moving to the next, so increase by one */
+ iloosevert++;
}
else {
- glBegin(GL_QUADS);
- for (y = 0; y < gridFaces; y += step) {
- for (x = 0; x < gridFaces; x += step) {
- float *a = CCG_grid_elem_co(&key, faceGridData, x, y + 0);
- float *b = CCG_grid_elem_co(&key, faceGridData, x + step, y + 0);
- float *c = CCG_grid_elem_co(&key, faceGridData, x + step, y + step);
- float *d = CCG_grid_elem_co(&key, faceGridData, x, y + step);
-
- ccgDM_glNormalFast(a, b, c, d);
-
- glVertex3fv(d);
- glVertex3fv(c);
- glVertex3fv(b);
- glVertex3fv(a);
- }
+ index_start = ccgdm->faceMap[fhandle].startFace;
+
+ for (i = 0; i < grid_face_side; i++) {
+ varray[inormhidden * 2] = (index_start + S * grid_tot_face + i * grid_face_side + grid_face_side - 1) * 4 + 1;
+ varray[inormhidden * 2 + 1] = (index_start + S * grid_tot_face + i * grid_face_side + grid_face_side - 1) * 4 + 2;
+ varray[inormhidden * 2 + 2] = (index_start + ((S + 1) % totvert) * grid_tot_face + grid_face_side * (grid_face_side - 1) + i) * 4 + 2;
+ varray[inormhidden * 2 + 3] = (index_start + ((S + 1) % totvert) * grid_tot_face + grid_face_side * (grid_face_side - 1) + i) * 4 + 3;
+ inormhidden += 2;
+ }
+ }
+ }
+ else {
+ if (isloose) {
+ for (i = 0; i < edgeSize; i++) {
+ varray[iloose * 2] = iloosevert;
+ varray[iloose * 2 + 1] = iloosevert + 1;
+ iloose++;
+ iloosevert++;
+ }
+ /* we are through with this loose edge and moving to the next, so increase by one */
+ iloosevert++;
+ }
+ else {
+ index_start = ccgdm->faceMap[fhandle].startFace;
+
+ for (i = 0; i < grid_face_side; i++) {
+ varray[inorm * 2] = (index_start + S * grid_tot_face + i * grid_face_side + grid_face_side - 1) * 4 + 1;
+ varray[inorm * 2 + 1] = (index_start + S * grid_tot_face + i * grid_face_side + grid_face_side - 1) * 4 + 2;
+ varray[inorm * 2 + 2] = (index_start + ((S + 1) % totvert) * grid_tot_face + grid_face_side * (grid_face_side - 1) + i) * 4 + 2;
+ varray[inorm * 2 + 3] = (index_start + ((S + 1) % totvert) * grid_tot_face + grid_face_side * (grid_face_side - 1) + i) * 4 + 3;
+ inorm += 2;
+ }
+ }
+ }
+ }
+
+ /* part two, handle interior edges */
+ inorm = totedge * grid_face_side * 2;
+
+ index_start = 0;
+ for (i = 0; i < totface; i++) {
+ CCGFace *f = ccgdm->faceMap[i].face;
+ unsigned int S, x, y, numVerts = ccgSubSurf_getFaceNumVerts(f);
+
+ for (S = 0; S < numVerts; S++) {
+ for (x = 1; x < grid_face_side; x++) {
+ for (y = 0; y < grid_face_side; y++) {
+ unsigned int tmp = (index_start + x * grid_face_side + y) * 4;
+ varray[inorm * 2] = tmp;
+ varray[inorm * 2 + 1] = tmp + 1;
+ inorm++;
+ }
+ }
+ for (x = 0; x < grid_face_side; x++) {
+ for (y = 0; y < grid_face_side; y++) {
+ unsigned int tmp = (index_start + x * grid_face_side + y) * 4;
+ varray[inorm * 2] = tmp + 3;
+ varray[inorm * 2 + 1] = tmp;
+ inorm++;
}
- glEnd();
}
+
+ tot_interior += grid_face_side * (2 * grid_face_side - 1);
+ index_start += grid_tot_face;
}
}
+
+ dm->drawObject->tot_loose_edge_drawn = tot_loose * edgeSize;
+ dm->drawObject->loose_edge_offset = (tot + tot_hidden) * edgeSize;
+ dm->drawObject->tot_edge_drawn = tot * edgeSize;
+
+ dm->drawObject->interior_offset = totedge * edgeSize;
+ dm->drawObject->totinterior = tot_interior;
}
-static void ccgdm_draw_attrib_vertex(DMVertexAttribs *attribs, int a, int index, int vert)
+static void ccgDM_copy_gpu_data(
+ DerivedMesh *dm, int type, void *varray_p,
+ const int *mat_orig_to_new, const void *user_data)
{
- const float zero[4] = {0.0f, 0.0f, 0.0f, 0.0f};
- int b;
+ /* 'varray_p' cast is redundant but include for self-documentation */
+ switch (type) {
+ case GPU_BUFFER_VERTEX:
+ ccgDM_buffer_copy_vertex(dm, (float *)varray_p);
+ break;
+ case GPU_BUFFER_NORMAL:
+ ccgDM_buffer_copy_normal(dm, (short *)varray_p);
+ break;
+ case GPU_BUFFER_UV:
+ ccgDM_buffer_copy_uv(dm, (float *)varray_p);
+ break;
+ case GPU_BUFFER_UV_TEXPAINT:
+ ccgDM_buffer_copy_uv_texpaint(dm, (float *)varray_p);
+ break;
+ case GPU_BUFFER_COLOR:
+ ccgDM_buffer_copy_color(dm, (unsigned char *)varray_p, user_data);
+ break;
+ case GPU_BUFFER_UVEDGE:
+ ccgDM_buffer_copy_uvedge(dm, (float *)varray_p);
+ break;
+ case GPU_BUFFER_EDGE:
+ ccgDM_buffer_copy_edge(dm, (unsigned int *)varray_p);
+ break;
+ case GPU_BUFFER_TRIANGLES:
+ ccgDM_buffer_copy_triangles(dm, (unsigned int *)varray_p, mat_orig_to_new);
+ break;
+ default:
+ break;
+ }
+}
- /* orco texture coordinates */
- if (attribs->totorco) {
- /*const*/ float (*array)[3] = attribs->orco.array;
- const float *orco = (array) ? array[index] : zero;
+static GPUDrawObject *ccgDM_GPUObjectNew(DerivedMesh *dm)
+{
+ CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm;
+ CCGSubSurf *ss = ccgdm->ss;
+ GPUDrawObject *gdo;
+ DMFlagMat *faceFlags = ccgdm->faceFlags;
+ int gridFaces = ccgSubSurf_getGridSize(ss) - 1;
+ const short dm_totmat = (faceFlags) ? dm->totmat : 1;
+ GPUBufferMaterial *matinfo;
+ int i;
+ unsigned int tot_internal_edges = 0;
+ int edgeVerts = ccgSubSurf_getEdgeSize(ss);
+ int edgeSize = edgeVerts - 1;
- if (attribs->orco.gl_texco)
- glTexCoord3fv(orco);
- else
- glVertexAttrib3fvARB(attribs->orco.gl_index, orco);
- }
+ int totedge = ccgSubSurf_getNumEdges(ss);
+ int totface = ccgSubSurf_getNumFaces(ss);
- /* uv texture coordinates */
- for (b = 0; b < attribs->tottface; b++) {
- const float *uv;
+ /* object contains at least one material (default included) so zero means uninitialized dm */
+ BLI_assert(dm_totmat != 0);
- if (attribs->tface[b].array) {
- MTFace *tf = &attribs->tface[b].array[a];
- uv = tf->uv[vert];
+ matinfo = MEM_callocN(sizeof(*matinfo) * dm_totmat, "GPU_drawobject_new.mat_orig_to_new");
+
+ if (faceFlags) {
+ for (i = 0; i < totface; i++) {
+ CCGFace *f = ccgdm->faceMap[i].face;
+ int numVerts = ccgSubSurf_getFaceNumVerts(f);
+ int index = GET_INT_FROM_POINTER(ccgSubSurf_getFaceFaceHandle(f));
+ const short new_matnr = ME_MAT_NR_TEST(faceFlags[index].mat_nr, dm_totmat);
+ matinfo[new_matnr].totelements += numVerts * gridFaces * gridFaces * 6;
+ matinfo[new_matnr].totloops += numVerts * gridFaces * gridFaces * 4;
+ matinfo[new_matnr].totpolys++;
+ tot_internal_edges += numVerts * gridFaces * (2 * gridFaces - 1);
}
- else {
- uv = zero;
+ }
+ else {
+ for (i = 0; i < totface; i++) {
+ CCGFace *f = ccgdm->faceMap[i].face;
+ int numVerts = ccgSubSurf_getFaceNumVerts(f);
+ matinfo[0].totelements += numVerts * gridFaces * gridFaces * 6;
+ matinfo[0].totloops += numVerts * gridFaces * gridFaces * 4;
+ matinfo[0].totpolys++;
+ tot_internal_edges += numVerts * gridFaces * (2 * gridFaces - 1);
}
+ }
+
+ /* create the GPUDrawObject */
+ gdo = MEM_callocN(sizeof(GPUDrawObject), "GPUDrawObject");
+ gdo->totvert = 0; /* used to count indices, doesn't really matter for ccgsubsurf */
+ gdo->totedge = (totedge * edgeSize + tot_internal_edges);
- if (attribs->tface[b].gl_texco)
- glTexCoord2fv(uv);
- else
- glVertexAttrib2fvARB(attribs->tface[b].gl_index, uv);
+ GPU_buffer_material_finalize(gdo, matinfo, dm_totmat);
+
+ /* store total number of points used for triangles */
+ gdo->tot_triangle_point = ccgSubSurf_getNumFinalFaces(ss) * 6;
+ gdo->tot_loop_verts = ccgSubSurf_getNumFinalFaces(ss) * 4;
+
+ /* finally, count loose points */
+ for (i = 0; i < totedge; i++) {
+ CCGEdge *e = ccgdm->edgeMap[i].edge;
+
+ if (!ccgSubSurf_getEdgeNumFaces(e))
+ gdo->tot_loose_point += edgeVerts;
}
- /* vertex colors */
- for (b = 0; b < attribs->totmcol; b++) {
- GLubyte col[4];
+ return gdo;
+}
- if (attribs->mcol[b].array) {
- MCol *cp = &attribs->mcol[b].array[a * 4 + vert];
- col[0] = cp->b; col[1] = cp->g; col[2] = cp->r; col[3] = cp->a;
- }
- else {
- col[0] = 0; col[1] = 0; col[2] = 0; col[3] = 0;
+/* Only used by non-editmesh types */
+static void ccgDM_drawFacesSolid(DerivedMesh *dm, float (*partial_redraw_planes)[4], bool fast, DMSetMaterial setMaterial)
+{
+ int a;
+ CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm;
+
+ ccgdm_pbvh_update(ccgdm);
+
+ if (ccgdm->pbvh && ccgdm->multires.mmd) {
+ if (BKE_pbvh_has_faces(ccgdm->pbvh)) {
+ BKE_pbvh_draw(ccgdm->pbvh, partial_redraw_planes, NULL,
+ setMaterial, false, fast);
+ glShadeModel(GL_FLAT);
}
- glVertexAttrib4ubvARB(attribs->mcol[b].gl_index, col);
+ return;
}
- /* tangent for normal mapping */
- if (attribs->tottang) {
- /*const*/ float (*array)[4] = attribs->tang.array;
- const float *tang = (array) ? array[a * 4 + vert] : zero;
+#ifdef WITH_OPENSUBDIV
+ if (ccgdm->useGpuBackend) {
+ CCGSubSurf *ss = ccgdm->ss;
+ const DMFlagMat *faceFlags = ccgdm->faceFlags;
+ const int level = ccgSubSurf_getSubdivisionLevels(ss);
+ const int face_side = 1 << level;
+ const int grid_side = 1 << (level - 1);
+ const int face_patches = face_side * face_side;
+ const int grid_patches = grid_side * grid_side;
+ const int num_base_faces = ccgSubSurf_getNumGLMeshBaseFaces(ss);
+ int i, current_patch = 0;
+ int mat_nr = -1;
+ bool draw_smooth = false;
+ int start_draw_patch = -1, num_draw_patches = 0;
+ if (UNLIKELY(ccgSubSurf_prepareGLMesh(ss, setMaterial != NULL) == false)) {
+ return;
+ }
+ if (setMaterial == NULL) {
+ ccgSubSurf_drawGLMesh(ss,
+ true,
+ -1,
+ -1);
+ return;
+ }
+ for (i = 0; i < num_base_faces; ++i) {
+ const int num_face_verts = ccgSubSurf_getNumGLMeshBaseFaceVerts(ss, i);
+ const int num_patches = (num_face_verts == 4) ? face_patches
+ : num_face_verts * grid_patches;
+ int new_matnr;
+ bool new_draw_smooth;
+ if (faceFlags) {
+ new_draw_smooth = (faceFlags[i].flag & ME_SMOOTH);
+ new_matnr = (faceFlags[i].mat_nr + 1);
+ }
+ else {
+ new_draw_smooth = true;
+ new_matnr = 1;
+ }
+ if (new_draw_smooth != draw_smooth || new_matnr != mat_nr) {
+ if (num_draw_patches != 0) {
+ bool do_draw = setMaterial(mat_nr, NULL);
+ if (do_draw) {
+ glShadeModel(draw_smooth ? GL_SMOOTH : GL_FLAT);
+ ccgSubSurf_drawGLMesh(ss,
+ true,
+ start_draw_patch,
+ num_draw_patches);
+ }
+ }
+ start_draw_patch = current_patch;
+ num_draw_patches = num_patches;
+ mat_nr = new_matnr;
+ draw_smooth = new_draw_smooth;
+ }
+ else {
+ num_draw_patches += num_patches;
+ }
+ current_patch += num_patches;
+ }
+ if (num_draw_patches != 0) {
+ bool do_draw = setMaterial(mat_nr, NULL);
+ if (do_draw) {
+ glShadeModel(draw_smooth ? GL_SMOOTH : GL_FLAT);
+ ccgSubSurf_drawGLMesh(ss,
+ true,
+ start_draw_patch,
+ num_draw_patches);
+ }
+ }
+ return;
+ }
+#endif
- glVertexAttrib4fvARB(attribs->tang.gl_index, tang);
+ GPU_vertex_setup(dm);
+ GPU_normal_setup(dm);
+ GPU_triangle_setup(dm);
+ glShadeModel(GL_SMOOTH);
+ for (a = 0; a < dm->drawObject->totmaterial; a++) {
+ if (!setMaterial || setMaterial(dm->drawObject->materials[a].mat_nr + 1, NULL)) {
+ GPU_buffer_draw_elements(dm->drawObject->triangles, GL_TRIANGLES, dm->drawObject->materials[a].start,
+ dm->drawObject->materials[a].totelements);
+ }
}
+ GPU_buffers_unbind();
}
/* Only used by non-editmesh types */
@@ -1963,9 +2721,76 @@ static void ccgDM_drawMappedFacesGLSL(DerivedMesh *dm,
int gridFaces = gridSize - 1;
int edgeSize = ccgSubSurf_getEdgeSize(ss);
DMFlagMat *faceFlags = ccgdm->faceFlags;
- short (*lnors)[4][3] = dm->getTessFaceDataArray(dm, CD_TESSLOOPNORMAL);
+ const float (*lnors)[3] = dm->getLoopDataArray(dm, CD_NORMAL);
int a, i, do_draw, numVerts, matnr, new_matnr, totface;
+#ifdef WITH_OPENSUBDIV
+ if (ccgdm->useGpuBackend) {
+ CCGSubSurf *ss = ccgdm->ss;
+ const DMFlagMat *faceFlags = ccgdm->faceFlags;
+ const int level = ccgSubSurf_getSubdivisionLevels(ss);
+ const int face_side = 1 << level;
+ const int grid_side = 1 << (level - 1);
+ const int face_patches = face_side * face_side;
+ const int grid_patches = grid_side * grid_side;
+ const int num_base_faces = ccgSubSurf_getNumGLMeshBaseFaces(ss);
+ int i, current_patch = 0;
+ int mat_nr = -1;
+ bool draw_smooth = false;
+ int start_draw_patch = -1, num_draw_patches = 0;
+ GPU_draw_update_fvar_offset(dm);
+ if (UNLIKELY(ccgSubSurf_prepareGLMesh(ss, false) == false)) {
+ return;
+ }
+ for (i = 0; i < num_base_faces; ++i) {
+ const int num_face_verts = ccgSubSurf_getNumGLMeshBaseFaceVerts(ss, i);
+ const int num_patches = (num_face_verts == 4) ? face_patches
+ : num_face_verts * grid_patches;
+ int new_matnr;
+ bool new_draw_smooth;
+ if (faceFlags) {
+ new_draw_smooth = (faceFlags[i].flag & ME_SMOOTH);
+ new_matnr = (faceFlags[i].mat_nr + 1);
+ }
+ else {
+ new_draw_smooth = true;
+ new_matnr = 1;
+ }
+ if (new_draw_smooth != draw_smooth || new_matnr != mat_nr) {
+ if (num_draw_patches != 0) {
+ bool do_draw = setMaterial(mat_nr, &gattribs);
+ if (do_draw) {
+ glShadeModel(draw_smooth ? GL_SMOOTH : GL_FLAT);
+ ccgSubSurf_drawGLMesh(ss,
+ true,
+ start_draw_patch,
+ num_draw_patches);
+ }
+ }
+ start_draw_patch = current_patch;
+ num_draw_patches = num_patches;
+ mat_nr = new_matnr;
+ draw_smooth = new_draw_smooth;
+ }
+ else {
+ num_draw_patches += num_patches;
+ }
+ current_patch += num_patches;
+ }
+ if (num_draw_patches != 0) {
+ bool do_draw = setMaterial(mat_nr, &gattribs);
+ if (do_draw) {
+ glShadeModel(draw_smooth ? GL_SMOOTH : GL_FLAT);
+ ccgSubSurf_drawGLMesh(ss,
+ true,
+ start_draw_patch,
+ num_draw_patches);
+ }
+ }
+ return;
+ }
+#endif
+
CCG_key_top_level(&key, ss);
ccgdm_pbvh_update(ccgdm);
@@ -1977,13 +2802,13 @@ static void ccgDM_drawMappedFacesGLSL(DerivedMesh *dm,
index = getFaceIndex(ss, f, S, x + dx, y + dy, edgeSize, gridSize); \
else \
index = 0; \
- ccgdm_draw_attrib_vertex(&attribs, a, index, vert); \
+ DM_draw_attrib_vertex(&attribs, a, index, vert, ((a) * 4) + vert); \
} (void)0
totface = ccgSubSurf_getNumFaces(ss);
for (a = 0, i = 0; i < totface; i++) {
CCGFace *f = ccgdm->faceMap[i].face;
- short (*ln)[4][3] = NULL;
+ const float (*ln)[3] = NULL;
int S, x, y, drawSmooth;
int index = GET_INT_FROM_POINTER(ccgSubSurf_getFaceFaceHandle(f));
int origIndex = ccgDM_getFaceMapIndex(ss, f);
@@ -2001,7 +2826,7 @@ static void ccgDM_drawMappedFacesGLSL(DerivedMesh *dm,
if (lnors) {
ln = lnors;
- lnors += gridFaces * gridFaces * numVerts;
+ lnors += (gridFaces * gridFaces * numVerts) * 4;
}
if (new_matnr != matnr) {
@@ -2032,19 +2857,19 @@ static void ccgDM_drawMappedFacesGLSL(DerivedMesh *dm,
float *dco = CCG_grid_elem_co(&key, faceGridData, x, y + 1);
PASSATTRIB(0, 1, 1);
- glNormal3sv(ln[0][1]);
+ glNormal3fv(ln[1]);
glVertex3fv(dco);
PASSATTRIB(1, 1, 2);
- glNormal3sv(ln[0][2]);
+ glNormal3fv(ln[2]);
glVertex3fv(cco);
PASSATTRIB(1, 0, 3);
- glNormal3sv(ln[0][3]);
+ glNormal3fv(ln[3]);
glVertex3fv(bco);
PASSATTRIB(0, 0, 0);
- glNormal3sv(ln[0][0]);
+ glNormal3fv(ln[0]);
glVertex3fv(aco);
- ln++;
+ ln += 4;
a++;
}
}
@@ -2135,9 +2960,33 @@ static void ccgDM_drawMappedFacesMat(DerivedMesh *dm,
int gridFaces = gridSize - 1;
int edgeSize = ccgSubSurf_getEdgeSize(ss);
DMFlagMat *faceFlags = ccgdm->faceFlags;
- short (*lnors)[4][3] = dm->getTessFaceDataArray(dm, CD_TESSLOOPNORMAL);
+ const float (*lnors)[3] = dm->getLoopDataArray(dm, CD_NORMAL);
int a, i, numVerts, matnr, new_matnr, totface;
+#ifdef WITH_OPENSUBDIV
+ if (ccgdm->useGpuBackend) {
+ int new_matnr;
+ bool draw_smooth;
+ GPU_draw_update_fvar_offset(dm);
+ if (UNLIKELY(ccgSubSurf_prepareGLMesh(ss, true) == false)) {
+ return;
+ }
+ /* TODO(sergey): Single matierial currently. */
+ if (faceFlags) {
+ draw_smooth = (faceFlags[0].flag & ME_SMOOTH);
+ new_matnr = (faceFlags[0].mat_nr + 1);
+ }
+ else {
+ draw_smooth = true;
+ new_matnr = 1;
+ }
+ glShadeModel(draw_smooth ? GL_SMOOTH : GL_FLAT);
+ setMaterial(userData, new_matnr, &gattribs);
+ ccgSubSurf_drawGLMesh(ss, true, -1, -1);
+ return;
+ }
+#endif
+
CCG_key_top_level(&key, ss);
ccgdm_pbvh_update(ccgdm);
@@ -2148,13 +2997,13 @@ static void ccgDM_drawMappedFacesMat(DerivedMesh *dm,
index = getFaceIndex(ss, f, S, x + dx, y + dy, edgeSize, gridSize); \
else \
index = 0; \
- ccgdm_draw_attrib_vertex(&attribs, a, index, vert); \
+ DM_draw_attrib_vertex(&attribs, a, index, vert, ((a) * 4) + vert); \
} (void)0
totface = ccgSubSurf_getNumFaces(ss);
for (a = 0, i = 0; i < totface; i++) {
CCGFace *f = ccgdm->faceMap[i].face;
- short (*ln)[4][3] = NULL;
+ const float (*ln)[3] = NULL;
int S, x, y, drawSmooth;
int index = GET_INT_FROM_POINTER(ccgSubSurf_getFaceFaceHandle(f));
int origIndex = ccgDM_getFaceMapIndex(ss, f);
@@ -2173,7 +3022,7 @@ static void ccgDM_drawMappedFacesMat(DerivedMesh *dm,
if (lnors) {
ln = lnors;
- lnors += gridFaces * gridFaces * numVerts;
+ lnors += (gridFaces * gridFaces * numVerts) * 4;
}
/* material */
@@ -2204,19 +3053,19 @@ static void ccgDM_drawMappedFacesMat(DerivedMesh *dm,
float *dco = CCG_grid_elem_co(&key, faceGridData, x, y + 1);
PASSATTRIB(0, 1, 1);
- glNormal3sv(ln[0][1]);
+ glNormal3fv(ln[1]);
glVertex3fv(dco);
PASSATTRIB(1, 1, 2);
- glNormal3sv(ln[0][2]);
+ glNormal3fv(ln[2]);
glVertex3fv(cco);
PASSATTRIB(1, 0, 3);
- glNormal3sv(ln[0][3]);
+ glNormal3fv(ln[3]);
glVertex3fv(bco);
PASSATTRIB(0, 0, 0);
- glNormal3sv(ln[0][0]);
+ glNormal3fv(ln[0]);
glVertex3fv(aco);
- ln++;
+ ln += 4;
a++;
}
}
@@ -2290,235 +3139,140 @@ static void ccgDM_drawMappedFacesMat(DerivedMesh *dm,
static void ccgDM_drawFacesTex_common(DerivedMesh *dm,
DMSetDrawOptionsTex drawParams,
- DMSetDrawOptions drawParamsMapped,
+ DMSetDrawOptionsMappedTex drawParamsMapped,
DMCompareDrawOptions compareDrawOptions,
void *userData, DMDrawFlag flag)
{
CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm;
CCGSubSurf *ss = ccgdm->ss;
CCGKey key;
- MCol *mcol = dm->getTessFaceDataArray(dm, CD_PREVIEW_MCOL);
- MTFace *tf = DM_get_tessface_data_layer(dm, CD_MTFACE);
- MTFace *tf_stencil_base = NULL;
- MTFace *tf_stencil = NULL;
- MTFace *tf_base;
- short (*lnors)[4][3] = dm->getTessFaceDataArray(dm, CD_TESSLOOPNORMAL);
+ int colType;
+ const MLoopCol *mloopcol;
+ MTexPoly *mtexpoly = DM_get_poly_data_layer(dm, CD_MTEXPOLY);
DMFlagMat *faceFlags = ccgdm->faceFlags;
DMDrawOption draw_option;
- int i, totface, gridSize = ccgSubSurf_getGridSize(ss);
- int gridFaces = gridSize - 1;
- int gridOffset = 0;
- int mat_nr_cache = -1;
-
- (void) compareDrawOptions;
+ int i, totpoly;
+ bool flush;
+ bool use_tface = (flag & DM_DRAW_USE_ACTIVE_UV) != 0;
+ unsigned int next_actualFace;
+ unsigned int gridFaces = ccgSubSurf_getGridSize(ss) - 1;
+ int mat_index;
+ int tot_element, start_element, tot_drawn;
+
+#ifdef WITH_OPENSUBDIV
+ if (ccgdm->useGpuBackend) {
+ if (ccgSubSurf_prepareGLMesh(ss, true) == false) {
+ return;
+ }
+ ccgSubSurf_drawGLMesh(ss, true, -1, -1);
+ return;
+ }
+#endif
CCG_key_top_level(&key, ss);
ccgdm_pbvh_update(ccgdm);
- if (!mcol)
- mcol = dm->getTessFaceDataArray(dm, CD_MCOL);
-
- if (!mcol)
- mcol = dm->getTessFaceDataArray(dm, CD_TEXTURE_MCOL);
-
- totface = ccgSubSurf_getNumFaces(ss);
+ colType = CD_TEXTURE_MLOOPCOL;
+ mloopcol = dm->getLoopDataArray(dm, colType);
+ if (!mloopcol) {
+ colType = CD_PREVIEW_MLOOPCOL;
+ mloopcol = dm->getLoopDataArray(dm, colType);
+ }
+ if (!mloopcol) {
+ colType = CD_MLOOPCOL;
+ mloopcol = dm->getLoopDataArray(dm, colType);
+ }
- if (flag & DM_DRAW_USE_TEXPAINT_UV) {
- int stencil = CustomData_get_stencil_layer(&dm->faceData, CD_MTFACE);
- tf_stencil_base = CustomData_get_layer_n(&dm->faceData, CD_MTFACE, stencil);
+ GPU_vertex_setup(dm);
+ GPU_normal_setup(dm);
+ GPU_triangle_setup(dm);
+ if (flag & DM_DRAW_USE_TEXPAINT_UV)
+ GPU_texpaint_uv_setup(dm);
+ else
+ GPU_uv_setup(dm);
+ if (mloopcol) {
+ GPU_color_setup(dm, colType);
}
- for (i = 0; i < totface; i++) {
- CCGFace *f = ccgdm->faceMap[i].face;
- int S, x, y, numVerts = ccgSubSurf_getFaceNumVerts(f);
- int drawSmooth, index = ccgDM_getFaceMapIndex(ss, f);
- int origIndex = GET_INT_FROM_POINTER(ccgSubSurf_getFaceFaceHandle(f));
- unsigned char *cp = NULL;
- short (*ln)[4][3] = NULL;
- int mat_nr;
+ next_actualFace = 0;
- if (faceFlags) {
- drawSmooth = (lnors || (faceFlags[origIndex].flag & ME_SMOOTH));
- mat_nr = faceFlags[origIndex].mat_nr;
- }
- else {
- drawSmooth = 1;
- mat_nr = 0;
- }
+ glShadeModel(GL_SMOOTH);
+ /* lastFlag = 0; */ /* UNUSED */
+ for (mat_index = 0; mat_index < dm->drawObject->totmaterial; mat_index++) {
+ GPUBufferMaterial *bufmat = dm->drawObject->materials + mat_index;
+ next_actualFace = bufmat->polys[0];
+ totpoly = bufmat->totpolys;
- /* texture painting, handle the correct uv layer here */
- if (flag & DM_DRAW_USE_TEXPAINT_UV) {
- if (mat_nr != mat_nr_cache) {
- tf_base = DM_paint_uvlayer_active_get(dm, mat_nr);
+ tot_element = 0;
+ tot_drawn = 0;
+ start_element = 0;
- mat_nr_cache = mat_nr;
+ for (i = 0; i < totpoly; i++) {
+ int polyindex = bufmat->polys[i];
+ CCGFace *f = ccgdm->faceMap[polyindex].face;
+ int numVerts = ccgSubSurf_getFaceNumVerts(f);
+ int index = ccgDM_getFaceMapIndex(ss, f);
+ int origIndex = GET_INT_FROM_POINTER(ccgSubSurf_getFaceFaceHandle(f));
+ int mat_nr;
+ int facequads = numVerts * gridFaces * gridFaces;
+ int actualFace = ccgdm->faceMap[polyindex].startFace;
+
+ if (i != totpoly - 1) {
+ polyindex = bufmat->polys[i + 1];
+ next_actualFace = ccgdm->faceMap[polyindex].startFace;
}
- tf = tf_base + gridOffset;
- tf_stencil = tf_stencil_base + gridOffset;
- gridOffset += gridFaces * gridFaces * numVerts;
- }
-
- if (drawParams)
- draw_option = drawParams(tf, (mcol != NULL), mat_nr);
- else if (index != ORIGINDEX_NONE)
- draw_option = (drawParamsMapped) ? drawParamsMapped(userData, index) : DM_DRAW_OPTION_NORMAL;
- else
- draw_option = GPU_enable_material(mat_nr, NULL) ? DM_DRAW_OPTION_NORMAL : DM_DRAW_OPTION_SKIP;
- if (lnors) {
- ln = lnors;
- lnors += gridFaces * gridFaces * numVerts;
- }
-
- if (draw_option == DM_DRAW_OPTION_SKIP) {
- if (tf) tf += gridFaces * gridFaces * numVerts;
- if (mcol) mcol += gridFaces * gridFaces * numVerts * 4;
- continue;
- }
+ if (faceFlags) {
+ mat_nr = faceFlags[origIndex].mat_nr;
+ }
+ else {
+ mat_nr = 0;
+ }
- /* flag 1 == use vertex colors */
- if (mcol) {
- if (draw_option != DM_DRAW_OPTION_NO_MCOL)
- cp = (unsigned char *)mcol;
- mcol += gridFaces * gridFaces * numVerts * 4;
- }
+ if (drawParams) {
+ MTexPoly *tp = (use_tface && mtexpoly) ? &mtexpoly[actualFace] : NULL;
+ draw_option = drawParams(tp, (mloopcol != NULL), mat_nr);
+ }
+ else if (index != ORIGINDEX_NONE)
+ draw_option = (drawParamsMapped) ? drawParamsMapped(userData, index, mat_nr) : DM_DRAW_OPTION_NORMAL;
+ else
+ draw_option = DM_DRAW_OPTION_NORMAL;
- for (S = 0; S < numVerts; S++) {
- CCGElem *faceGridData = ccgSubSurf_getFaceGridDataArray(ss, f, S);
- CCGElem *a, *b;
+ /* flush buffer if current triangle isn't drawable or it's last triangle */
+ flush = (draw_option == DM_DRAW_OPTION_SKIP) || (i == totpoly - 1);
- if (ln) {
- glShadeModel(GL_SMOOTH);
- glBegin(GL_QUADS);
- for (y = 0; y < gridFaces; y++) {
- for (x = 0; x < gridFaces; x++) {
- float *a_co = CCG_grid_elem_co(&key, faceGridData, x, y + 0);
- float *b_co = CCG_grid_elem_co(&key, faceGridData, x + 1, y + 0);
- float *c_co = CCG_grid_elem_co(&key, faceGridData, x + 1, y + 1);
- float *d_co = CCG_grid_elem_co(&key, faceGridData, x, y + 1);
-
- if (tf) glTexCoord2fv(tf->uv[1]);
- if (tf_stencil) glMultiTexCoord2fv(GL_TEXTURE2, tf_stencil->uv[1]);
- if (cp) glColor3ub(cp[7], cp[6], cp[5]);
- glNormal3sv(ln[0][1]);
- glVertex3fv(d_co);
-
- if (tf) glTexCoord2fv(tf->uv[2]);
- if (tf_stencil) glMultiTexCoord2fv(GL_TEXTURE2, tf_stencil->uv[2]);
- if (cp) glColor3ub(cp[11], cp[10], cp[9]);
- glNormal3sv(ln[0][2]);
- glVertex3fv(c_co);
-
- if (tf) glTexCoord2fv(tf->uv[3]);
- if (tf_stencil) glMultiTexCoord2fv(GL_TEXTURE2, tf_stencil->uv[3]);
- if (cp) glColor3ub(cp[15], cp[14], cp[13]);
- glNormal3sv(ln[0][3]);
- glVertex3fv(b_co);
-
- if (tf) glTexCoord2fv(tf->uv[0]);
- if (tf_stencil) glMultiTexCoord2fv(GL_TEXTURE2, tf_stencil->uv[0]);
- if (cp) glColor3ub(cp[3], cp[2], cp[1]);
- glNormal3sv(ln[0][0]);
- glVertex3fv(a_co);
-
- if (tf) tf++;
- if (tf_stencil) tf_stencil++;
- if (cp) cp += 16;
- ln++;
- }
- }
- glEnd();
+ if (!flush && compareDrawOptions) {
+ /* also compare draw options and flush buffer if they're different
+ * need for face selection highlight in edit mode */
+ flush |= compareDrawOptions(userData, actualFace, next_actualFace) == 0;
}
- else if (drawSmooth) {
- glShadeModel(GL_SMOOTH);
- for (y = 0; y < gridFaces; y++) {
- glBegin(GL_QUAD_STRIP);
- for (x = 0; x < gridFaces; x++) {
- a = CCG_grid_elem(&key, faceGridData, x, y + 0);
- b = CCG_grid_elem(&key, faceGridData, x, y + 1);
-
- if (tf) glTexCoord2fv(tf->uv[0]);
- if (tf_stencil) glMultiTexCoord2fv(GL_TEXTURE2, tf_stencil->uv[0]);
- if (cp) glColor3ub(cp[3], cp[2], cp[1]);
- glNormal3fv(CCG_elem_no(&key, a));
- glVertex3fv(CCG_elem_co(&key, a));
-
- if (tf) glTexCoord2fv(tf->uv[1]);
- if (tf_stencil) glMultiTexCoord2fv(GL_TEXTURE2, tf_stencil->uv[1]);
- if (cp) glColor3ub(cp[7], cp[6], cp[5]);
- glNormal3fv(CCG_elem_no(&key, b));
- glVertex3fv(CCG_elem_co(&key, b));
-
- if (x != gridFaces - 1) {
- if (tf) tf++;
- if (tf_stencil) tf_stencil++;
- if (cp) cp += 16;
- }
- }
- a = CCG_grid_elem(&key, faceGridData, x, y + 0);
- b = CCG_grid_elem(&key, faceGridData, x, y + 1);
+ tot_element += facequads * 6;
- if (tf) glTexCoord2fv(tf->uv[3]);
- if (tf_stencil) glMultiTexCoord2fv(GL_TEXTURE2, tf_stencil->uv[3]);
- if (cp) glColor3ub(cp[15], cp[14], cp[13]);
- glNormal3fv(CCG_elem_no(&key, a));
- glVertex3fv(CCG_elem_co(&key, a));
+ if (flush) {
+ if (draw_option != DM_DRAW_OPTION_SKIP)
+ tot_drawn += facequads * 6;
- if (tf) glTexCoord2fv(tf->uv[2]);
- if (tf_stencil) glMultiTexCoord2fv(GL_TEXTURE2, tf_stencil->uv[2]);
- if (cp) glColor3ub(cp[11], cp[10], cp[9]);
- glNormal3fv(CCG_elem_no(&key, b));
- glVertex3fv(CCG_elem_co(&key, b));
+ if (tot_drawn) {
+ if (mloopcol && draw_option != DM_DRAW_OPTION_NO_MCOL)
+ GPU_color_switch(1);
+ else
+ GPU_color_switch(0);
- if (tf) tf++;
- if (tf_stencil) tf_stencil++;
- if (cp) cp += 16;
-
- glEnd();
+ GPU_buffer_draw_elements(dm->drawObject->triangles, GL_TRIANGLES, bufmat->start + start_element, tot_drawn);
+ tot_drawn = 0;
}
+
+ start_element = tot_element;
}
else {
- glShadeModel((cp) ? GL_SMOOTH : GL_FLAT);
- glBegin(GL_QUADS);
- for (y = 0; y < gridFaces; y++) {
- for (x = 0; x < gridFaces; x++) {
- float *a_co = CCG_grid_elem_co(&key, faceGridData, x, y + 0);
- float *b_co = CCG_grid_elem_co(&key, faceGridData, x + 1, y + 0);
- float *c_co = CCG_grid_elem_co(&key, faceGridData, x + 1, y + 1);
- float *d_co = CCG_grid_elem_co(&key, faceGridData, x, y + 1);
-
- ccgDM_glNormalFast(a_co, b_co, c_co, d_co);
-
- if (tf) glTexCoord2fv(tf->uv[1]);
- if (tf_stencil) glMultiTexCoord2fv(GL_TEXTURE2, tf_stencil->uv[1]);
- if (cp) glColor3ub(cp[7], cp[6], cp[5]);
- glVertex3fv(d_co);
-
- if (tf) glTexCoord2fv(tf->uv[2]);
- if (tf_stencil) glMultiTexCoord2fv(GL_TEXTURE2, tf_stencil->uv[2]);
- if (cp) glColor3ub(cp[11], cp[10], cp[9]);
- glVertex3fv(c_co);
-
- if (tf) glTexCoord2fv(tf->uv[3]);
- if (tf_stencil) glMultiTexCoord2fv(GL_TEXTURE2, tf_stencil->uv[3]);
- if (cp) glColor3ub(cp[15], cp[14], cp[13]);
- glVertex3fv(b_co);
-
- if (tf) glTexCoord2fv(tf->uv[0]);
- if (tf_stencil) glMultiTexCoord2fv(GL_TEXTURE2, tf_stencil->uv[0]);
- if (cp) glColor3ub(cp[3], cp[2], cp[1]);
- glVertex3fv(a_co);
-
- if (tf) tf++;
- if (tf_stencil) tf_stencil++;
- if (cp) cp += 16;
- }
- }
- glEnd();
+ tot_drawn += facequads * 6;
}
}
}
+
+
+ GPU_buffers_unbind();
}
static void ccgDM_drawFacesTex(DerivedMesh *dm,
@@ -2530,45 +3284,41 @@ static void ccgDM_drawFacesTex(DerivedMesh *dm,
}
static void ccgDM_drawMappedFacesTex(DerivedMesh *dm,
- DMSetDrawOptions setDrawOptions,
+ DMSetDrawOptionsMappedTex setDrawOptions,
DMCompareDrawOptions compareDrawOptions,
void *userData, DMDrawFlag flag)
{
ccgDM_drawFacesTex_common(dm, NULL, setDrawOptions, compareDrawOptions, userData, flag);
}
+/* same as cdDM_drawUVEdges */
static void ccgDM_drawUVEdges(DerivedMesh *dm)
{
-
- MFace *mf = dm->getTessFaceArray(dm);
- MTFace *tf = DM_get_tessface_data_layer(dm, CD_MTFACE);
+ MPoly *mpoly = dm->getPolyArray(dm);
+ int totpoly = dm->getNumPolys(dm);
+ int prevstart = 0;
+ bool prevdraw = true;
+ int curpos = 0;
int i;
-
- if (tf) {
- glBegin(GL_LINES);
- for (i = 0; i < dm->numTessFaceData; i++, mf++, tf++) {
- if (!(mf->flag & ME_HIDE)) {
- glVertex2fv(tf->uv[0]);
- glVertex2fv(tf->uv[1]);
-
- glVertex2fv(tf->uv[1]);
- glVertex2fv(tf->uv[2]);
-
- if (!mf->v4) {
- glVertex2fv(tf->uv[2]);
- glVertex2fv(tf->uv[0]);
- }
- else {
- glVertex2fv(tf->uv[2]);
- glVertex2fv(tf->uv[3]);
-
- glVertex2fv(tf->uv[3]);
- glVertex2fv(tf->uv[0]);
- }
+
+ GPU_uvedge_setup(dm);
+ for (i = 0; i < totpoly; i++, mpoly++) {
+ const bool draw = (mpoly->flag & ME_HIDE) == 0;
+
+ if (prevdraw != draw) {
+ if (prevdraw && (curpos != prevstart)) {
+ glDrawArrays(GL_LINES, prevstart, curpos - prevstart);
}
+ prevstart = curpos;
}
- glEnd();
+
+ curpos += 2 * mpoly->totloop;
+ prevdraw = draw;
+ }
+ if (prevdraw && (curpos != prevstart)) {
+ glDrawArrays(GL_LINES, prevstart, curpos - prevstart);
}
+ GPU_buffers_unbind();
}
static void ccgDM_drawMappedFaces(DerivedMesh *dm,
@@ -2580,12 +3330,55 @@ static void ccgDM_drawMappedFaces(DerivedMesh *dm,
CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm;
CCGSubSurf *ss = ccgdm->ss;
CCGKey key;
- MCol *mcol = NULL;
- short (*lnors)[4][3] = dm->getTessFaceDataArray(dm, CD_TESSLOOPNORMAL);
+ MLoopCol *mloopcol = NULL;
+ const float (*lnors)[3] = dm->getLoopDataArray(dm, CD_NORMAL);
int i, gridSize = ccgSubSurf_getGridSize(ss);
DMFlagMat *faceFlags = ccgdm->faceFlags;
int useColors = flag & DM_DRAW_USE_COLORS;
int gridFaces = gridSize - 1, totface;
+ int prev_mat_nr = -1;
+
+#ifdef WITH_OPENSUBDIV
+ if (ccgdm->useGpuBackend) {
+ DMFlagMat *faceFlags = ccgdm->faceFlags;
+ int new_matnr;
+ bool draw_smooth, do_draw = true;
+ if (setDrawOptions == NULL) {
+ /* TODO(sergey): This is for cases when vertex colors or weights
+ * are visualising. Currently we don't have CD layers for this data
+ * and here we only make it so there's no garbage displayed.
+ *
+ * In the future we'll either need to have CD for this data or pass
+ * this data as face-varying or vertex-varying data in OSD mesh.
+ */
+ glColor3f(0.8f, 0.8f, 0.8f);
+ }
+ if (UNLIKELY(ccgSubSurf_prepareGLMesh(ss, true) == false)) {
+ return;
+ }
+ if (faceFlags) {
+ draw_smooth = (faceFlags[0].flag & ME_SMOOTH);
+ new_matnr = (faceFlags[0].mat_nr + 1);
+ }
+ else {
+ draw_smooth = true;
+ new_matnr = 1;
+ }
+ if (setMaterial) {
+ setMaterial(new_matnr, NULL);
+ }
+ if (setDrawOptions) {
+ if (setDrawOptions(userData, 0) == DM_DRAW_OPTION_SKIP) {
+ do_draw = false;
+ }
+ }
+ if (do_draw) {
+ glShadeModel(draw_smooth ? GL_SMOOTH : GL_FLAT);
+ ccgSubSurf_drawGLMesh(ss, true, -1, -1);
+ }
+ return;
+ }
+#endif
CCG_key_top_level(&key, ss);
@@ -2593,9 +3386,9 @@ static void ccgDM_drawMappedFaces(DerivedMesh *dm,
(void)compareDrawOptions;
if (useColors) {
- mcol = dm->getTessFaceDataArray(dm, CD_PREVIEW_MCOL);
- if (!mcol)
- mcol = dm->getTessFaceDataArray(dm, CD_MCOL);
+ mloopcol = dm->getLoopDataArray(dm, CD_PREVIEW_MLOOPCOL);
+ if (!mloopcol)
+ mloopcol = dm->getLoopDataArray(dm, CD_MLOOPCOL);
}
totface = ccgSubSurf_getNumFaces(ss);
@@ -2605,7 +3398,7 @@ static void ccgDM_drawMappedFaces(DerivedMesh *dm,
int drawSmooth, index = ccgDM_getFaceMapIndex(ss, f);
int origIndex;
unsigned char *cp = NULL;
- short (*ln)[4][3] = NULL;
+ const float (*ln)[3] = NULL;
origIndex = GET_INT_FROM_POINTER(ccgSubSurf_getFaceFaceHandle(f));
@@ -2613,22 +3406,29 @@ static void ccgDM_drawMappedFaces(DerivedMesh *dm,
else if (faceFlags) drawSmooth = (lnors || (faceFlags[origIndex].flag & ME_SMOOTH));
else drawSmooth = 1;
- if (mcol) {
- cp = (unsigned char *)mcol;
- mcol += gridFaces * gridFaces * numVerts * 4;
+ if (mloopcol) {
+ cp = (unsigned char *)mloopcol;
+ mloopcol += gridFaces * gridFaces * numVerts * 4;
}
if (lnors) {
ln = lnors;
- lnors += gridFaces * gridFaces * numVerts;
+ lnors += (gridFaces * gridFaces * numVerts) * 4;
}
{
DMDrawOption draw_option = DM_DRAW_OPTION_NORMAL;
- if (index == ORIGINDEX_NONE)
- draw_option = setMaterial(faceFlags ? faceFlags[origIndex].mat_nr + 1 : 1, NULL); /* XXX, no faceFlags no material */
- else if (setDrawOptions)
+ if (setMaterial) {
+ int mat_nr = faceFlags ? faceFlags[origIndex].mat_nr + 1 : 1;
+
+ if (mat_nr != prev_mat_nr) {
+ setMaterial(mat_nr, NULL); /* XXX, no faceFlags no material */
+ prev_mat_nr = mat_nr;
+ }
+ }
+
+ if (setDrawOptions && (index != ORIGINDEX_NONE))
draw_option = setDrawOptions(userData, index);
if (draw_option != DM_DRAW_OPTION_SKIP) {
@@ -2652,21 +3452,21 @@ static void ccgDM_drawMappedFaces(DerivedMesh *dm,
float *c = CCG_grid_elem_co(&key, faceGridData, x + 1, y + 1);
float *d = CCG_grid_elem_co(&key, faceGridData, x, y + 1);
- if (cp) glColor3ub(cp[7], cp[6], cp[5]);
- glNormal3sv(ln[0][1]);
+ if (cp) glColor3ubv(&cp[4]);
+ glNormal3fv(ln[1]);
glVertex3fv(d);
- if (cp) glColor3ub(cp[11], cp[10], cp[9]);
- glNormal3sv(ln[0][2]);
+ if (cp) glColor3ubv(&cp[8]);
+ glNormal3fv(ln[2]);
glVertex3fv(c);
- if (cp) glColor3ub(cp[15], cp[14], cp[13]);
- glNormal3sv(ln[0][3]);
+ if (cp) glColor3ubv(&cp[12]);
+ glNormal3fv(ln[3]);
glVertex3fv(b);
- if (cp) glColor3ub(cp[3], cp[2], cp[1]);
- glNormal3sv(ln[0][0]);
+ if (cp) glColor3ubv(&cp[0]);
+ glNormal3fv(ln[0]);
glVertex3fv(a);
if (cp) cp += 16;
- ln++;
+ ln += 4;
}
}
glEnd();
@@ -2679,10 +3479,10 @@ static void ccgDM_drawMappedFaces(DerivedMesh *dm,
a = CCG_grid_elem(&key, faceGridData, x, y + 0);
b = CCG_grid_elem(&key, faceGridData, x, y + 1);
- if (cp) glColor3ub(cp[3], cp[2], cp[1]);
+ if (cp) glColor3ubv(&cp[0]);
glNormal3fv(CCG_elem_no(&key, a));
glVertex3fv(CCG_elem_co(&key, a));
- if (cp) glColor3ub(cp[7], cp[6], cp[5]);
+ if (cp) glColor3ubv(&cp[4]);
glNormal3fv(CCG_elem_no(&key, b));
glVertex3fv(CCG_elem_co(&key, b));
@@ -2694,10 +3494,10 @@ static void ccgDM_drawMappedFaces(DerivedMesh *dm,
a = CCG_grid_elem(&key, faceGridData, x, y + 0);
b = CCG_grid_elem(&key, faceGridData, x, y + 1);
- if (cp) glColor3ub(cp[15], cp[14], cp[13]);
+ if (cp) glColor3ubv(&cp[12]);
glNormal3fv(CCG_elem_no(&key, a));
glVertex3fv(CCG_elem_co(&key, a));
- if (cp) glColor3ub(cp[11], cp[10], cp[9]);
+ if (cp) glColor3ubv(&cp[8]);
glNormal3fv(CCG_elem_no(&key, b));
glVertex3fv(CCG_elem_co(&key, b));
@@ -2717,13 +3517,13 @@ static void ccgDM_drawMappedFaces(DerivedMesh *dm,
ccgDM_glNormalFast(a, b, c, d);
- if (cp) glColor3ub(cp[7], cp[6], cp[5]);
+ if (cp) glColor3ubv(&cp[4]);
glVertex3fv(d);
- if (cp) glColor3ub(cp[11], cp[10], cp[9]);
+ if (cp) glColor3ubv(&cp[8]);
glVertex3fv(c);
- if (cp) glColor3ub(cp[15], cp[14], cp[13]);
+ if (cp) glColor3ubv(&cp[12]);
glVertex3fv(b);
- if (cp) glColor3ub(cp[3], cp[2], cp[1]);
+ if (cp) glColor3ubv(&cp[0]);
glVertex3fv(a);
if (cp) cp += 16;
@@ -2745,15 +3545,27 @@ static void ccgDM_drawMappedEdges(DerivedMesh *dm,
{
CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm;
CCGSubSurf *ss = ccgdm->ss;
- CCGEdgeIterator *ei;
+ CCGEdgeIterator ei;
CCGKey key;
int i, useAging, edgeSize = ccgSubSurf_getEdgeSize(ss);
+#ifdef WITH_OPENSUBDIV
+ if (ccgdm->useGpuBackend) {
+ /* TODO(sergey): Only draw edges from base mesh. */
+ if (ccgSubSurf_prepareGLMesh(ccgdm->ss, true)) {
+ if (!setDrawOptions || (setDrawOptions(userData, 0) != DM_DRAW_OPTION_SKIP)) {
+ ccgSubSurf_drawGLMesh(ccgdm->ss, false, -1, -1);
+ }
+ }
+ return;
+ }
+#endif
+
CCG_key_top_level(&key, ss);
ccgSubSurf_getUseAgeCounts(ss, &useAging, NULL, NULL, NULL);
- for (ei = ccgSubSurf_getEdgeIterator(ss); !ccgEdgeIterator_isStopped(ei); ccgEdgeIterator_next(ei)) {
- CCGEdge *e = ccgEdgeIterator_getCurrent(ei);
+ for (ccgSubSurf_initEdgeIterator(ss, &ei); !ccgEdgeIterator_isStopped(&ei); ccgEdgeIterator_next(&ei)) {
+ CCGEdge *e = ccgEdgeIterator_getCurrent(&ei);
CCGElem *edgeData = ccgSubSurf_getEdgeDataArray(ss, e);
int index = ccgDM_getEdgeMapIndex(ss, e);
@@ -2771,8 +3583,6 @@ static void ccgDM_drawMappedEdges(DerivedMesh *dm,
}
glEnd();
}
-
- ccgEdgeIterator_free(ei);
}
static void ccgDM_drawMappedEdgesInterp(DerivedMesh *dm,
@@ -2783,14 +3593,21 @@ static void ccgDM_drawMappedEdgesInterp(DerivedMesh *dm,
CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm;
CCGSubSurf *ss = ccgdm->ss;
CCGKey key;
- CCGEdgeIterator *ei;
+ CCGEdgeIterator ei;
int i, useAging, edgeSize = ccgSubSurf_getEdgeSize(ss);
+#ifdef WITH_OPENSUBDIV
+ if (ccgdm->useGpuBackend) {
+ BLI_assert(!"Not currently supported");
+ return;
+ }
+#endif
+
CCG_key_top_level(&key, ss);
ccgSubSurf_getUseAgeCounts(ss, &useAging, NULL, NULL, NULL);
- for (ei = ccgSubSurf_getEdgeIterator(ss); !ccgEdgeIterator_isStopped(ei); ccgEdgeIterator_next(ei)) {
- CCGEdge *e = ccgEdgeIterator_getCurrent(ei);
+ for (ccgSubSurf_initEdgeIterator(ss, &ei); !ccgEdgeIterator_isStopped(&ei); ccgEdgeIterator_next(&ei)) {
+ CCGEdge *e = ccgEdgeIterator_getCurrent(&ei);
CCGElem *edgeData = ccgSubSurf_getEdgeDataArray(ss, e);
int index = ccgDM_getEdgeMapIndex(ss, e);
@@ -2809,8 +3626,6 @@ static void ccgDM_drawMappedEdgesInterp(DerivedMesh *dm,
}
glEnd();
}
-
- ccgEdgeIterator_free(ei);
}
static void ccgDM_foreachMappedFaceCenter(
@@ -2822,12 +3637,12 @@ static void ccgDM_foreachMappedFaceCenter(
CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm;
CCGSubSurf *ss = ccgdm->ss;
CCGKey key;
- CCGFaceIterator *fi;
+ CCGFaceIterator fi;
CCG_key_top_level(&key, ss);
- for (fi = ccgSubSurf_getFaceIterator(ss); !ccgFaceIterator_isStopped(fi); ccgFaceIterator_next(fi)) {
- CCGFace *f = ccgFaceIterator_getCurrent(fi);
+ for (ccgSubSurf_initFaceIterator(ss, &fi); !ccgFaceIterator_isStopped(&fi); ccgFaceIterator_next(&fi)) {
+ CCGFace *f = ccgFaceIterator_getCurrent(&fi);
const int index = ccgDM_getFaceMapIndex(ss, f);
if (index != -1) {
@@ -2837,8 +3652,6 @@ static void ccgDM_foreachMappedFaceCenter(
func(userData, index, CCG_elem_co(&key, vd), no);
}
}
-
- ccgFaceIterator_free(fi);
}
static void ccgDM_release(DerivedMesh *dm)
@@ -2869,7 +3682,6 @@ static void ccgDM_release(DerivedMesh *dm)
if (ccgdm->reverseFaceMap) MEM_freeN(ccgdm->reverseFaceMap);
if (ccgdm->gridFaces) MEM_freeN(ccgdm->gridFaces);
if (ccgdm->gridData) MEM_freeN(ccgdm->gridData);
- if (ccgdm->gridAdjacency) MEM_freeN(ccgdm->gridAdjacency);
if (ccgdm->gridOffset) MEM_freeN(ccgdm->gridOffset);
if (ccgdm->gridFlagMats) MEM_freeN(ccgdm->gridFlagMats);
if (ccgdm->gridHidden) {
@@ -2885,62 +3697,12 @@ static void ccgDM_release(DerivedMesh *dm)
if (ccgdm->pmap_mem) MEM_freeN(ccgdm->pmap_mem);
MEM_freeN(ccgdm->edgeFlags);
MEM_freeN(ccgdm->faceFlags);
- MEM_freeN(ccgdm->vertMap);
- MEM_freeN(ccgdm->edgeMap);
- MEM_freeN(ccgdm->faceMap);
- MEM_freeN(ccgdm);
- }
-}
-
-static void ccg_loops_to_corners(CustomData *fdata, CustomData *ldata,
- CustomData *pdata, int loopstart, int findex, int polyindex,
- const int numTex, const int numCol, const int hasPCol, const int hasOrigSpace)
-{
- MTFace *texface;
- MTexPoly *texpoly;
- MCol *mcol;
- MLoopCol *mloopcol;
- MLoopUV *mloopuv;
- int i, j;
-
- for (i = 0; i < numTex; i++) {
- texface = CustomData_get_n(fdata, CD_MTFACE, findex, i);
- texpoly = CustomData_get_n(pdata, CD_MTEXPOLY, polyindex, i);
-
- ME_MTEXFACE_CPY(texface, texpoly);
-
- mloopuv = CustomData_get_n(ldata, CD_MLOOPUV, loopstart, i);
- for (j = 0; j < 4; j++, mloopuv++) {
- copy_v2_v2(texface->uv[j], mloopuv->uv);
- }
- }
-
- for (i = 0; i < numCol; i++) {
- mloopcol = CustomData_get_n(ldata, CD_MLOOPCOL, loopstart, i);
- mcol = CustomData_get_n(fdata, CD_MCOL, findex, i);
-
- for (j = 0; j < 4; j++, mloopcol++) {
- MESH_MLOOPCOL_TO_MCOL(mloopcol, &mcol[j]);
- }
- }
-
- if (hasPCol) {
- mloopcol = CustomData_get(ldata, loopstart, CD_PREVIEW_MLOOPCOL);
- mcol = CustomData_get(fdata, findex, CD_PREVIEW_MCOL);
-
- for (j = 0; j < 4; j++, mloopcol++) {
- MESH_MLOOPCOL_TO_MCOL(mloopcol, &mcol[j]);
- }
- }
-
- if (hasOrigSpace) {
- OrigSpaceFace *of = CustomData_get(fdata, findex, CD_ORIGSPACE);
- OrigSpaceLoop *lof;
-
- lof = CustomData_get(ldata, loopstart, CD_ORIGSPACE_MLOOP);
- for (j = 0; j < 4; j++, lof++) {
- copy_v2_v2(of->uv[j], lof->uv);
+ if (ccgdm->useGpuBackend == false) {
+ MEM_freeN(ccgdm->vertMap);
+ MEM_freeN(ccgdm->edgeMap);
+ MEM_freeN(ccgdm->faceMap);
}
+ MEM_freeN(ccgdm);
}
}
@@ -3180,46 +3942,11 @@ static int ccgDM_getGridSize(DerivedMesh *dm)
return ccgSubSurf_getGridSize(ccgdm->ss);
}
-static int ccgdm_adjacent_grid(int *gridOffset, CCGFace *f, int S, int offset)
-{
- CCGFace *adjf;
- CCGEdge *e;
- int i, j = 0, numFaces, fIndex, numEdges = 0;
-
- e = ccgSubSurf_getFaceEdge(f, S);
- numFaces = ccgSubSurf_getEdgeNumFaces(e);
-
- if (numFaces != 2)
- return -1;
-
- for (i = 0; i < numFaces; i++) {
- adjf = ccgSubSurf_getEdgeFace(e, i);
-
- if (adjf != f) {
- numEdges = ccgSubSurf_getFaceNumVerts(adjf);
- for (j = 0; j < numEdges; j++)
- if (ccgSubSurf_getFaceEdge(adjf, j) == e)
- break;
-
- if (j != numEdges)
- break;
- }
- }
-
- if (numEdges == 0)
- return -1;
-
- fIndex = GET_INT_FROM_POINTER(ccgSubSurf_getFaceFaceHandle(adjf));
-
- return gridOffset[fIndex] + (j + offset) % numEdges;
-}
-
static void ccgdm_create_grids(DerivedMesh *dm)
{
CCGDerivedMesh *ccgdm = (CCGDerivedMesh *)dm;
CCGSubSurf *ss = ccgdm->ss;
CCGElem **gridData;
- DMGridAdjacency *gridAdjacency, *adj;
DMFlagMat *gridFlagMats;
CCGFace **gridFaces;
int *gridOffset;
@@ -3245,7 +3972,6 @@ static void ccgdm_create_grids(DerivedMesh *dm)
/* compute grid data */
gridData = MEM_mallocN(sizeof(CCGElem *) * numGrids, "ccgdm.gridData");
- gridAdjacency = MEM_mallocN(sizeof(DMGridAdjacency) * numGrids, "ccgdm.gridAdjacency");
gridFaces = MEM_mallocN(sizeof(CCGFace *) * numGrids, "ccgdm.gridFaces");
gridFlagMats = MEM_mallocN(sizeof(DMFlagMat) * numGrids, "ccgdm.gridFlagMats");
@@ -3256,29 +3982,14 @@ static void ccgdm_create_grids(DerivedMesh *dm)
int numVerts = ccgSubSurf_getFaceNumVerts(f);
for (S = 0; S < numVerts; S++, gIndex++) {
- int prevS = (S - 1 + numVerts) % numVerts;
- int nextS = (S + 1 + numVerts) % numVerts;
-
gridData[gIndex] = ccgSubSurf_getFaceGridDataArray(ss, f, S);
gridFaces[gIndex] = f;
gridFlagMats[gIndex] = ccgdm->faceFlags[index];
-
- adj = &gridAdjacency[gIndex];
-
- adj->index[0] = gIndex - S + nextS;
- adj->rotation[0] = 3;
- adj->index[1] = ccgdm_adjacent_grid(gridOffset, f, prevS, 0);
- adj->rotation[1] = 1;
- adj->index[2] = ccgdm_adjacent_grid(gridOffset, f, S, 1);
- adj->rotation[2] = 3;
- adj->index[3] = gIndex - S + prevS;
- adj->rotation[3] = 1;
}
}
ccgdm->gridData = gridData;
ccgdm->gridFaces = gridFaces;
- ccgdm->gridAdjacency = gridAdjacency;
ccgdm->gridOffset = gridOffset;
ccgdm->gridFlagMats = gridFlagMats;
}
@@ -3291,14 +4002,6 @@ static CCGElem **ccgDM_getGridData(DerivedMesh *dm)
return ccgdm->gridData;
}
-static DMGridAdjacency *ccgDM_getGridAdjacency(DerivedMesh *dm)
-{
- CCGDerivedMesh *ccgdm = (CCGDerivedMesh *)dm;
-
- ccgdm_create_grids(dm);
- return ccgdm->gridAdjacency;
-}
-
static int *ccgDM_getGridOffset(DerivedMesh *dm)
{
CCGDerivedMesh *ccgdm = (CCGDerivedMesh *)dm;
@@ -3381,7 +4084,7 @@ static struct PBVH *ccgDM_getPBVH(Object *ob, DerivedMesh *dm)
* when the ccgdm gets remade, the assumption is that the topology
* does not change. */
ccgdm_create_grids(dm);
- BKE_pbvh_grids_update(ob->sculpt->pbvh, ccgdm->gridData, ccgdm->gridAdjacency, (void **)ccgdm->gridFaces,
+ BKE_pbvh_grids_update(ob->sculpt->pbvh, ccgdm->gridData, (void **)ccgdm->gridFaces,
ccgdm->gridFlagMats, ccgdm->gridHidden);
}
@@ -3400,15 +4103,26 @@ static struct PBVH *ccgDM_getPBVH(Object *ob, DerivedMesh *dm)
numGrids = ccgDM_getNumGrids(dm);
ob->sculpt->pbvh = ccgdm->pbvh = BKE_pbvh_new();
- BKE_pbvh_build_grids(ccgdm->pbvh, ccgdm->gridData, ccgdm->gridAdjacency,
+ BKE_pbvh_build_grids(ccgdm->pbvh, ccgdm->gridData,
numGrids, &key, (void **) ccgdm->gridFaces, ccgdm->gridFlagMats, ccgdm->gridHidden);
}
else if (ob->type == OB_MESH) {
Mesh *me = ob->data;
+ const int looptris_num = poly_to_tri_count(me->totpoly, me->totloop);
+ MLoopTri *looptri;
+
+ looptri = MEM_mallocN(sizeof(*looptri) * looptris_num, __func__);
+
+ BKE_mesh_recalc_looptri(
+ me->mloop, me->mpoly,
+ me->mvert,
+ me->totloop, me->totpoly,
+ looptri);
+
ob->sculpt->pbvh = ccgdm->pbvh = BKE_pbvh_new();
BLI_assert(!(me->mface == NULL && me->mpoly != NULL)); /* BMESH ONLY complain if mpoly is valid but not mface */
- BKE_pbvh_build_mesh(ccgdm->pbvh, me->mface, me->mvert,
- me->totface, me->totvert, &me->vdata);
+ BKE_pbvh_build_mesh(ccgdm->pbvh, me->mpoly, me->mloop, me->mvert, me->totvert, &me->vdata,
+ looptri, looptris_num);
}
if (ccgdm->pbvh)
@@ -3422,87 +4136,64 @@ static void ccgDM_recalcTessellation(DerivedMesh *UNUSED(dm))
/* Nothing to do: CCG handles creating its own tessfaces */
}
-static void ccgDM_calcNormals(DerivedMesh *dm)
+static void ccgDM_recalcLoopTri(DerivedMesh *UNUSED(dm))
{
- /* Nothing to do: CCG calculates normals during drawing */
- dm->dirty &= ~DM_DIRTY_NORMALS;
+ /* Nothing to do: CCG tessellation is known,
+ * allocate and fill in with ccgDM_getLoopTriArray */
}
-static CCGDerivedMesh *getCCGDerivedMesh(CCGSubSurf *ss,
- int drawInteriorEdges,
- int useSubsurfUv,
- DerivedMesh *dm)
+static const MLoopTri *ccgDM_getLoopTriArray(DerivedMesh *dm)
{
- CCGDerivedMesh *ccgdm = MEM_callocN(sizeof(*ccgdm), "ccgdm");
- CCGVertIterator *vi;
- CCGEdgeIterator *ei;
- CCGFaceIterator *fi;
- int index, totvert, totedge, totface;
- int i;
- int vertNum, edgeNum, faceNum;
- int *vertOrigIndex, *faceOrigIndex, *polyOrigIndex, *base_polyOrigIndex, *edgeOrigIndex;
- short *edgeFlags;
- DMFlagMat *faceFlags;
- int *polyidx = NULL;
-#ifndef USE_DYNSIZE
- int *loopidx = NULL, *vertidx = NULL;
- BLI_array_declare(loopidx);
- BLI_array_declare(vertidx);
-#endif
- int loopindex, loopindex2;
- int edgeSize;
- int gridSize;
- int gridFaces, gridCuts;
- /*int gridSideVerts;*/
- int gridSideEdges;
- int numTex, numCol;
- int hasPCol, hasOrigSpace;
- int gridInternalEdges;
- WeightTable wtable = {NULL};
- /* MCol *mcol; */ /* UNUSED */
- MEdge *medge = NULL;
- /* MFace *mface = NULL; */
- MPoly *mpoly = NULL;
- bool has_edge_cd;
-
- DM_from_template(&ccgdm->dm, dm, DM_TYPE_CCGDM,
- ccgSubSurf_getNumFinalVerts(ss),
- ccgSubSurf_getNumFinalEdges(ss),
- ccgSubSurf_getNumFinalFaces(ss),
- ccgSubSurf_getNumFinalFaces(ss) * 4,
- ccgSubSurf_getNumFinalFaces(ss));
-
- CustomData_free_layer_active(&ccgdm->dm.polyData, CD_NORMAL,
- ccgdm->dm.numPolyData);
-
- numTex = CustomData_number_of_layers(&ccgdm->dm.loopData, CD_MLOOPUV);
- numCol = CustomData_number_of_layers(&ccgdm->dm.loopData, CD_MLOOPCOL);
- hasPCol = CustomData_has_layer(&ccgdm->dm.loopData, CD_PREVIEW_MLOOPCOL);
- hasOrigSpace = CustomData_has_layer(&ccgdm->dm.loopData, CD_ORIGSPACE_MLOOP);
-
- if (
- (numTex && CustomData_number_of_layers(&ccgdm->dm.faceData, CD_MTFACE) != numTex) ||
- (numCol && CustomData_number_of_layers(&ccgdm->dm.faceData, CD_MCOL) != numCol) ||
- (hasPCol && !CustomData_has_layer(&ccgdm->dm.faceData, CD_PREVIEW_MCOL)) ||
- (hasOrigSpace && !CustomData_has_layer(&ccgdm->dm.faceData, CD_ORIGSPACE)) )
- {
- CustomData_from_bmeshpoly(&ccgdm->dm.faceData,
- &ccgdm->dm.polyData,
- &ccgdm->dm.loopData,
- ccgSubSurf_getNumFinalFaces(ss));
+ if (dm->looptris.array) {
+ BLI_assert(poly_to_tri_count(dm->numPolyData, dm->numLoopData) == dm->looptris.num);
+ }
+ else {
+ MLoopTri *mlooptri;
+ const int tottri = dm->numPolyData * 2;
+ int i, poly_index;
+
+ DM_ensure_looptri_data(dm);
+ mlooptri = dm->looptris.array;
+
+ BLI_assert(poly_to_tri_count(dm->numPolyData, dm->numLoopData) == dm->looptris.num);
+ BLI_assert(tottri == dm->looptris.num);
+
+ for (i = 0, poly_index = 0; i < tottri; i += 2, poly_index += 1) {
+ MLoopTri *lt;
+ lt = &mlooptri[i];
+ /* quad is (0, 3, 2, 1) */
+ lt->tri[0] = (poly_index * 4) + 0;
+ lt->tri[1] = (poly_index * 4) + 2;
+ lt->tri[2] = (poly_index * 4) + 3;
+ lt->poly = poly_index;
+
+ lt = &mlooptri[i + 1];
+ lt->tri[0] = (poly_index * 4) + 0;
+ lt->tri[1] = (poly_index * 4) + 1;
+ lt->tri[2] = (poly_index * 4) + 2;
+ lt->poly = poly_index;
+ }
}
+ return dm->looptris.array;
+}
- /* We absolutely need that layer, else it's no valid tessellated data! */
- polyidx = CustomData_add_layer(&ccgdm->dm.faceData, CD_ORIGINDEX, CD_CALLOC,
- NULL, ccgSubSurf_getNumFinalFaces(ss));
+static void ccgDM_calcNormals(DerivedMesh *dm)
+{
+ /* Nothing to do: CCG calculates normals during drawing */
+ dm->dirty &= ~DM_DIRTY_NORMALS;
+}
+static void set_default_ccgdm_callbacks(CCGDerivedMesh *ccgdm)
+{
ccgdm->dm.getMinMax = ccgDM_getMinMax;
ccgdm->dm.getNumVerts = ccgDM_getNumVerts;
ccgdm->dm.getNumEdges = ccgDM_getNumEdges;
- ccgdm->dm.getNumTessFaces = ccgDM_getNumTessFaces;
ccgdm->dm.getNumLoops = ccgDM_getNumLoops;
/* reuse of ccgDM_getNumTessFaces is intentional here: subsurf polys are just created from tessfaces */
- ccgdm->dm.getNumPolys = ccgDM_getNumTessFaces;
+ ccgdm->dm.getNumPolys = ccgDM_getNumPolys;
+ ccgdm->dm.getNumTessFaces = ccgDM_getNumTessFaces;
+
+ ccgdm->dm.getLoopTriArray = ccgDM_getLoopTriArray;
ccgdm->dm.getVert = ccgDM_getFinalVert;
ccgdm->dm.getEdge = ccgDM_getFinalEdge;
@@ -3528,7 +4219,6 @@ static CCGDerivedMesh *getCCGDerivedMesh(CCGSubSurf *ss,
ccgdm->dm.getNumGrids = ccgDM_getNumGrids;
ccgdm->dm.getGridSize = ccgDM_getGridSize;
ccgdm->dm.getGridData = ccgDM_getGridData;
- ccgdm->dm.getGridAdjacency = ccgDM_getGridAdjacency;
ccgdm->dm.getGridOffset = ccgDM_getGridOffset;
ccgdm->dm.getGridKey = ccgDM_getGridKey;
ccgdm->dm.getGridFlagMats = ccgDM_getGridFlagMats;
@@ -3538,14 +4228,17 @@ static CCGDerivedMesh *getCCGDerivedMesh(CCGSubSurf *ss,
ccgdm->dm.calcNormals = ccgDM_calcNormals;
ccgdm->dm.calcLoopNormals = CDDM_calc_loop_normals;
+ ccgdm->dm.calcLoopNormalsSpaceArray = CDDM_calc_loop_normals_spacearr;
+ ccgdm->dm.calcLoopTangents = DM_calc_loop_tangents;
ccgdm->dm.recalcTessellation = ccgDM_recalcTessellation;
+ ccgdm->dm.recalcLoopTri = ccgDM_recalcLoopTri;
ccgdm->dm.getVertCos = ccgdm_getVertCos;
ccgdm->dm.foreachMappedVert = ccgDM_foreachMappedVert;
ccgdm->dm.foreachMappedEdge = ccgDM_foreachMappedEdge;
ccgdm->dm.foreachMappedLoop = ccgDM_foreachMappedLoop;
ccgdm->dm.foreachMappedFaceCenter = ccgDM_foreachMappedFaceCenter;
-
+
ccgdm->dm.drawVerts = ccgDM_drawVerts;
ccgdm->dm.drawEdges = ccgDM_drawEdges;
ccgdm->dm.drawLooseEdges = ccgDM_drawLooseEdges;
@@ -3560,41 +4253,87 @@ static CCGDerivedMesh *getCCGDerivedMesh(CCGSubSurf *ss,
ccgdm->dm.drawMappedEdgesInterp = ccgDM_drawMappedEdgesInterp;
ccgdm->dm.drawMappedEdges = ccgDM_drawMappedEdges;
-
+ ccgdm->dm.gpuObjectNew = ccgDM_GPUObjectNew;
+ ccgdm->dm.copy_gpu_data = ccgDM_copy_gpu_data;
+
ccgdm->dm.release = ccgDM_release;
-
- ccgdm->ss = ss;
- ccgdm->drawInteriorEdges = drawInteriorEdges;
- ccgdm->useSubsurfUv = useSubsurfUv;
+}
+
+static void create_ccgdm_maps(CCGDerivedMesh *ccgdm,
+ CCGSubSurf *ss)
+{
+ CCGVertIterator vi;
+ CCGEdgeIterator ei;
+ CCGFaceIterator fi;
+ int totvert, totedge, totface;
totvert = ccgSubSurf_getNumVerts(ss);
ccgdm->vertMap = MEM_mallocN(totvert * sizeof(*ccgdm->vertMap), "vertMap");
- for (vi = ccgSubSurf_getVertIterator(ss); !ccgVertIterator_isStopped(vi); ccgVertIterator_next(vi)) {
- CCGVert *v = ccgVertIterator_getCurrent(vi);
+ for (ccgSubSurf_initVertIterator(ss, &vi);
+ !ccgVertIterator_isStopped(&vi);
+ ccgVertIterator_next(&vi))
+ {
+ CCGVert *v = ccgVertIterator_getCurrent(&vi);
ccgdm->vertMap[GET_INT_FROM_POINTER(ccgSubSurf_getVertVertHandle(v))].vert = v;
}
- ccgVertIterator_free(vi);
totedge = ccgSubSurf_getNumEdges(ss);
ccgdm->edgeMap = MEM_mallocN(totedge * sizeof(*ccgdm->edgeMap), "edgeMap");
- for (ei = ccgSubSurf_getEdgeIterator(ss); !ccgEdgeIterator_isStopped(ei); ccgEdgeIterator_next(ei)) {
- CCGEdge *e = ccgEdgeIterator_getCurrent(ei);
+ for (ccgSubSurf_initEdgeIterator(ss, &ei);
+ !ccgEdgeIterator_isStopped(&ei);
+ ccgEdgeIterator_next(&ei))
+ {
+ CCGEdge *e = ccgEdgeIterator_getCurrent(&ei);
ccgdm->edgeMap[GET_INT_FROM_POINTER(ccgSubSurf_getEdgeEdgeHandle(e))].edge = e;
}
- ccgEdgeIterator_free(ei);
totface = ccgSubSurf_getNumFaces(ss);
ccgdm->faceMap = MEM_mallocN(totface * sizeof(*ccgdm->faceMap), "faceMap");
- for (fi = ccgSubSurf_getFaceIterator(ss); !ccgFaceIterator_isStopped(fi); ccgFaceIterator_next(fi)) {
- CCGFace *f = ccgFaceIterator_getCurrent(fi);
+ for (ccgSubSurf_initFaceIterator(ss, &fi);
+ !ccgFaceIterator_isStopped(&fi);
+ ccgFaceIterator_next(&fi))
+ {
+ CCGFace *f = ccgFaceIterator_getCurrent(&fi);
ccgdm->faceMap[GET_INT_FROM_POINTER(ccgSubSurf_getFaceFaceHandle(f))].face = f;
}
- ccgFaceIterator_free(fi);
+}
- ccgdm->reverseFaceMap = MEM_callocN(sizeof(int) * ccgSubSurf_getNumFinalFaces(ss), "reverseFaceMap");
+/* Fill in all geometry arrays making it possible to access any
+ * hires data from the CPU.
+ */
+static void set_ccgdm_all_geometry(CCGDerivedMesh *ccgdm,
+ CCGSubSurf *ss,
+ DerivedMesh *dm,
+ bool useSubsurfUv)
+{
+ const int totvert = ccgSubSurf_getNumVerts(ss);
+ const int totedge = ccgSubSurf_getNumEdges(ss);
+ const int totface = ccgSubSurf_getNumFaces(ss);
+ int index;
+ int i;
+ int vertNum = 0, edgeNum = 0, faceNum = 0;
+ int *vertOrigIndex, *faceOrigIndex, *polyOrigIndex, *base_polyOrigIndex, *edgeOrigIndex;
+ short *edgeFlags = ccgdm->edgeFlags;
+ DMFlagMat *faceFlags = ccgdm->faceFlags;
+ int *polyidx = NULL;
+#ifndef USE_DYNSIZE
+ int *loopidx = NULL, *vertidx = NULL;
+ BLI_array_declare(loopidx);
+ BLI_array_declare(vertidx);
+#endif
+ int loopindex, loopindex2;
+ int edgeSize;
+ int gridSize;
+ int gridFaces, gridCuts;
+ int gridSideEdges;
+ int gridInternalEdges;
+ WeightTable wtable = {NULL};
+ MEdge *medge = NULL;
+ MPoly *mpoly = NULL;
+ bool has_edge_cd;
edgeSize = ccgSubSurf_getEdgeSize(ss);
gridSize = ccgSubSurf_getGridSize(ss);
@@ -3602,11 +4341,7 @@ static CCGDerivedMesh *getCCGDerivedMesh(CCGSubSurf *ss,
gridCuts = gridSize - 2;
/*gridInternalVerts = gridSideVerts * gridSideVerts; - as yet, unused */
gridSideEdges = gridSize - 1;
- gridInternalEdges = (gridSideEdges - 1) * gridSideEdges * 2;
-
- vertNum = 0;
- edgeNum = 0;
- faceNum = 0;
+ gridInternalEdges = (gridSideEdges - 1) * gridSideEdges * 2;
/* mvert = dm->getVertArray(dm); */ /* UNUSED */
medge = dm->getEdgeArray(dm);
@@ -3614,10 +4349,6 @@ static CCGDerivedMesh *getCCGDerivedMesh(CCGSubSurf *ss,
mpoly = CustomData_get_layer(&dm->polyData, CD_MPOLY);
base_polyOrigIndex = CustomData_get_layer(&dm->polyData, CD_ORIGINDEX);
-
- /*CDDM hack*/
- edgeFlags = ccgdm->edgeFlags = MEM_callocN(sizeof(short) * totedge, "edgeFlags");
- faceFlags = ccgdm->faceFlags = MEM_callocN(sizeof(DMFlagMat) * totface, "faceFlags");
vertOrigIndex = DM_get_vert_data_layer(&ccgdm->dm, CD_ORIGINDEX);
edgeOrigIndex = DM_get_edge_data_layer(&ccgdm->dm, CD_ORIGINDEX);
@@ -3647,13 +4378,12 @@ static CCGDerivedMesh *getCCGDerivedMesh(CCGSubSurf *ss,
#ifdef USE_DYNSIZE
int loopidx[numVerts], vertidx[numVerts];
#endif
-
w = get_ss_weights(&wtable, gridCuts, numVerts);
ccgdm->faceMap[index].startVert = vertNum;
ccgdm->faceMap[index].startEdge = edgeNum;
ccgdm->faceMap[index].startFace = faceNum;
-
+
faceFlags->flag = mpoly ? mpoly[origIndex].flag : 0;
faceFlags->mat_nr = mpoly ? mpoly[origIndex].mat_nr : 0;
faceFlags++;
@@ -3677,7 +4407,6 @@ static CCGDerivedMesh *getCCGDerivedMesh(CCGSubSurf *ss,
CCGVert *v = ccgSubSurf_getFaceVert(f, s);
vertidx[s] = GET_INT_FROM_POINTER(ccgSubSurf_getVertVertHandle(v));
}
-
/*I think this is for interpolating the center vert?*/
w2 = w; // + numVerts*(g2_wid-1) * (g2_wid-1); //numVerts*((g2_wid-1) * g2_wid+g2_wid-1);
@@ -3748,7 +4477,7 @@ static CCGDerivedMesh *getCCGDerivedMesh(CCGSubSurf *ss,
CustomData_interp(&dm->loopData, &ccgdm->dm.loopData,
loopidx, w2, NULL, numVerts, loopindex2);
loopindex2++;
-
+
w2 = w + s * numVerts * g2_wid * g2_wid + ((y) * g2_wid + (x + 1)) * numVerts;
CustomData_interp(&dm->loopData, &ccgdm->dm.loopData,
loopidx, w2, NULL, numVerts, loopindex2);
@@ -3757,11 +4486,6 @@ static CCGDerivedMesh *getCCGDerivedMesh(CCGSubSurf *ss,
/*copy over poly data, e.g. mtexpoly*/
CustomData_copy_data(&dm->polyData, &ccgdm->dm.polyData, origIndex, faceNum, 1);
- /*generate tessellated face data used for drawing*/
- ccg_loops_to_corners(&ccgdm->dm.faceData, &ccgdm->dm.loopData,
- &ccgdm->dm.polyData, loopindex2 - 4, faceNum, faceNum,
- numTex, numCol, hasPCol, hasOrigSpace);
-
/*set original index data*/
if (faceOrigIndex) {
/* reference the index in 'polyOrigIndex' */
@@ -3776,7 +4500,9 @@ static CCGDerivedMesh *getCCGDerivedMesh(CCGSubSurf *ss,
ccgdm->reverseFaceMap[faceNum] = index;
/* This is a simple one to one mapping, here... */
- polyidx[faceNum] = faceNum;
+ if (polyidx) {
+ polyidx[faceNum] = faceNum;
+ }
faceNum++;
}
@@ -3868,26 +4594,124 @@ static CCGDerivedMesh *getCCGDerivedMesh(CCGSubSurf *ss,
vertNum++;
}
- ccgdm->dm.numVertData = vertNum;
- ccgdm->dm.numEdgeData = edgeNum;
- ccgdm->dm.numTessFaceData = faceNum;
- ccgdm->dm.numLoopData = loopindex2;
- ccgdm->dm.numPolyData = faceNum;
-
- /* All tessellated CD layers were updated! */
- ccgdm->dm.dirty &= ~DM_DIRTY_TESS_CDLAYERS;
-
#ifndef USE_DYNSIZE
BLI_array_free(vertidx);
BLI_array_free(loopidx);
#endif
free_ss_weights(&wtable);
+ BLI_assert(vertNum == ccgSubSurf_getNumFinalVerts(ss));
+ BLI_assert(edgeNum == ccgSubSurf_getNumFinalEdges(ss));
+ BLI_assert(loopindex2 == ccgSubSurf_getNumFinalFaces(ss) * 4);
+ BLI_assert(faceNum == ccgSubSurf_getNumFinalFaces(ss));
+
+}
+
+/* Fill in only geometry arrays needed for the GPU tessellation. */
+static void set_ccgdm_gpu_geometry(CCGDerivedMesh *ccgdm, DerivedMesh *dm)
+{
+ const int totface = dm->getNumPolys(dm);
+ MPoly *mpoly = CustomData_get_layer(&dm->polyData, CD_MPOLY);
+ int index;
+ DMFlagMat *faceFlags = ccgdm->faceFlags;
+
+ for (index = 0; index < totface; index++) {
+ faceFlags->flag = mpoly ? mpoly[index].flag : 0;
+ faceFlags->mat_nr = mpoly ? mpoly[index].mat_nr : 0;
+ faceFlags++;
+ }
+
+ /* TODO(sergey): Fill in edge flags. */
+}
+
+static CCGDerivedMesh *getCCGDerivedMesh(CCGSubSurf *ss,
+ int drawInteriorEdges,
+ int useSubsurfUv,
+ DerivedMesh *dm,
+ bool use_gpu_backend)
+{
+#ifdef WITH_OPENSUBDIV
+ const int totedge = dm->getNumEdges(dm);
+ const int totface = dm->getNumPolys(dm);
+#else
+ const int totedge = ccgSubSurf_getNumEdges(ss);
+ const int totface = ccgSubSurf_getNumFaces(ss);
+#endif
+ CCGDerivedMesh *ccgdm = MEM_callocN(sizeof(*ccgdm), "ccgdm");
+
+ if (use_gpu_backend == false) {
+ BLI_assert(totedge == ccgSubSurf_getNumEdges(ss));
+ BLI_assert(totface == ccgSubSurf_getNumFaces(ss));
+ DM_from_template(&ccgdm->dm, dm, DM_TYPE_CCGDM,
+ ccgSubSurf_getNumFinalVerts(ss),
+ ccgSubSurf_getNumFinalEdges(ss),
+ 0,
+ ccgSubSurf_getNumFinalFaces(ss) * 4,
+ ccgSubSurf_getNumFinalFaces(ss));
+
+ CustomData_free_layer_active(&ccgdm->dm.polyData, CD_NORMAL,
+ ccgdm->dm.numPolyData);
+
+ ccgdm->reverseFaceMap =
+ MEM_callocN(sizeof(int) * ccgSubSurf_getNumFinalFaces(ss),
+ "reverseFaceMap");
+
+ create_ccgdm_maps(ccgdm, ss);
+ }
+ else {
+ DM_from_template(&ccgdm->dm, dm, DM_TYPE_CCGDM,
+ 0, 0, 0, 0, dm->getNumPolys(dm));
+ CustomData_copy_data(&dm->polyData,
+ &ccgdm->dm.polyData,
+ 0, 0, dm->getNumPolys(dm));
+ }
+
+ set_default_ccgdm_callbacks(ccgdm);
+
+ ccgdm->ss = ss;
+ ccgdm->drawInteriorEdges = drawInteriorEdges;
+ ccgdm->useSubsurfUv = useSubsurfUv;
+ ccgdm->useGpuBackend = use_gpu_backend;
+
+ /* CDDM hack. */
+ ccgdm->edgeFlags = MEM_callocN(sizeof(short) * totedge, "edgeFlags");
+ ccgdm->faceFlags = MEM_callocN(sizeof(DMFlagMat) * totface, "faceFlags");
+
+ if (use_gpu_backend == false) {
+ set_ccgdm_all_geometry(ccgdm, ss, dm, useSubsurfUv != 0);
+ }
+ else {
+ set_ccgdm_gpu_geometry(ccgdm, dm);
+ }
+
+ ccgdm->dm.numVertData = ccgSubSurf_getNumFinalVerts(ss);
+ ccgdm->dm.numEdgeData = ccgSubSurf_getNumFinalEdges(ss);
+ ccgdm->dm.numPolyData = ccgSubSurf_getNumFinalFaces(ss);
+ ccgdm->dm.numLoopData = ccgdm->dm.numPolyData * 4;
+ ccgdm->dm.numTessFaceData = 0;
+
return ccgdm;
}
/***/
+static bool subsurf_use_gpu_backend(SubsurfFlags flags)
+{
+#ifdef WITH_OPENSUBDIV
+ /* Use GPU backend if it's a last modifier in the stack
+ * and user choosed to use any of the OSD compute devices,
+ * but also check if GPU has all needed features.
+ */
+ return
+ (flags & SUBSURF_USE_GPU_BACKEND) != 0 &&
+ (U.opensubdiv_compute_type != USER_OPENSUBDIV_COMPUTE_NONE) &&
+ (openSubdiv_supportGPUDisplay());
+#else
+ (void)flags;
+ return false;
+#endif
+}
+
struct DerivedMesh *subsurf_make_derived_from_derived(
struct DerivedMesh *dm,
struct SubsurfModifierData *smd,
@@ -3895,27 +4719,37 @@ struct DerivedMesh *subsurf_make_derived_from_derived(
SubsurfFlags flags)
{
int useSimple = (smd->subdivType == ME_SIMPLE_SUBSURF) ? CCG_SIMPLE_SUBDIV : 0;
- CCGFlags useAging = smd->flags & eSubsurfModifierFlag_DebugIncr ? CCG_USE_AGING : 0;
+ CCGFlags useAging = (smd->flags & eSubsurfModifierFlag_DebugIncr) ? CCG_USE_AGING : 0;
int useSubsurfUv = smd->flags & eSubsurfModifierFlag_SubsurfUv;
int drawInteriorEdges = !(smd->flags & eSubsurfModifierFlag_ControlEdges);
CCGDerivedMesh *result;
+ bool use_gpu_backend = subsurf_use_gpu_backend(flags);
/* note: editmode calculation can only run once per
* modifier stack evaluation (uses freed cache) [#36299] */
if (flags & SUBSURF_FOR_EDIT_MODE) {
- int levels = (smd->modifier.scene) ? get_render_subsurf_level(&smd->modifier.scene->r, smd->levels) : smd->levels;
+ int levels = (smd->modifier.scene) ? get_render_subsurf_level(&smd->modifier.scene->r, smd->levels, false) : smd->levels;
+
+ /* TODO(sergey): Same as emCache below. */
+ if ((flags & SUBSURF_IN_EDIT_MODE) && smd->mCache) {
+ ccgSubSurf_free(smd->mCache);
+ smd->mCache = NULL;
+ }
smd->emCache = _getSubSurf(smd->emCache, levels, 3, useSimple | useAging | CCG_CALC_NORMALS);
- ss_sync_from_derivedmesh(smd->emCache, dm, vertCos, useSimple);
+#ifdef WITH_OPENSUBDIV
+ ccgSubSurf_setSkipGrids(smd->emCache, use_gpu_backend);
+#endif
+ ss_sync_from_derivedmesh(smd->emCache, dm, vertCos, useSimple);
result = getCCGDerivedMesh(smd->emCache,
drawInteriorEdges,
- useSubsurfUv, dm);
+ useSubsurfUv, dm, use_gpu_backend);
}
else if (flags & SUBSURF_USE_RENDER_PARAMS) {
/* Do not use cache in render mode. */
CCGSubSurf *ss;
- int levels = (smd->modifier.scene) ? get_render_subsurf_level(&smd->modifier.scene->r, smd->renderLevels) : smd->renderLevels;
+ int levels = (smd->modifier.scene) ? get_render_subsurf_level(&smd->modifier.scene->r, smd->renderLevels, true) : smd->renderLevels;
if (levels == 0)
return dm;
@@ -3925,13 +4759,13 @@ struct DerivedMesh *subsurf_make_derived_from_derived(
ss_sync_from_derivedmesh(ss, dm, vertCos, useSimple);
result = getCCGDerivedMesh(ss,
- drawInteriorEdges, useSubsurfUv, dm);
+ drawInteriorEdges, useSubsurfUv, dm, false);
result->freeSS = 1;
}
else {
int useIncremental = (smd->flags & eSubsurfModifierFlag_Incremental);
- int levels = (smd->modifier.scene) ? get_render_subsurf_level(&smd->modifier.scene->r, smd->levels) : smd->levels;
+ int levels = (smd->modifier.scene) ? get_render_subsurf_level(&smd->modifier.scene->r, smd->levels, false) : smd->levels;
CCGSubSurf *ss;
/* It is quite possible there is a much better place to do this. It
@@ -3957,23 +4791,45 @@ struct DerivedMesh *subsurf_make_derived_from_derived(
result = getCCGDerivedMesh(smd->mCache,
drawInteriorEdges,
- useSubsurfUv, dm);
+ useSubsurfUv, dm, false);
}
else {
CCGFlags ccg_flags = useSimple | CCG_USE_ARENA | CCG_CALC_NORMALS;
-
+ CCGSubSurf *prevSS = NULL;
+
if (smd->mCache && (flags & SUBSURF_IS_FINAL_CALC)) {
- ccgSubSurf_free(smd->mCache);
- smd->mCache = NULL;
+#ifdef WITH_OPENSUBDIV
+ /* With OpenSubdiv enabled we always tries to re-use previos
+ * subsurf structure in order to save computation time since
+ * re-creation is rather a complicated business.
+ *
+ * TODO(sergey): There was a good eason why final calculation
+ * used to free entirely cached subsurf structure. reason of
+ * this is to be investigated still to be sure we don't have
+ * regressions here.
+ */
+ if (use_gpu_backend) {
+ prevSS = smd->mCache;
+ }
+ else
+#endif
+ {
+ ccgSubSurf_free(smd->mCache);
+ smd->mCache = NULL;
+ }
}
+
if (flags & SUBSURF_ALLOC_PAINT_MASK)
ccg_flags |= CCG_ALLOC_MASK;
- ss = _getSubSurf(NULL, levels, 3, ccg_flags);
+ ss = _getSubSurf(prevSS, levels, 3, ccg_flags);
+#ifdef WITH_OPENSUBDIV
+ ccgSubSurf_setSkipGrids(ss, use_gpu_backend);
+#endif
ss_sync_from_derivedmesh(ss, dm, vertCos, useSimple);
- result = getCCGDerivedMesh(ss, drawInteriorEdges, useSubsurfUv, dm);
+ result = getCCGDerivedMesh(ss, drawInteriorEdges, useSubsurfUv, dm, use_gpu_backend);
if (flags & SUBSURF_IS_FINAL_CALC)
smd->mCache = ss;
@@ -3997,13 +4853,13 @@ void subsurf_calculate_limit_positions(Mesh *me, float (*r_positions)[3])
*/
CCGSubSurf *ss = _getSubSurf(NULL, 1, 3, CCG_USE_ARENA);
float edge_sum[3], face_sum[3];
- CCGVertIterator *vi;
+ CCGVertIterator vi;
DerivedMesh *dm = CDDM_from_mesh(me);
ss_sync_from_derivedmesh(ss, dm, NULL, 0);
- for (vi = ccgSubSurf_getVertIterator(ss); !ccgVertIterator_isStopped(vi); ccgVertIterator_next(vi)) {
- CCGVert *v = ccgVertIterator_getCurrent(vi);
+ for (ccgSubSurf_initVertIterator(ss, &vi); !ccgVertIterator_isStopped(&vi); ccgVertIterator_next(&vi)) {
+ CCGVert *v = ccgVertIterator_getCurrent(&vi);
int idx = GET_INT_FROM_POINTER(ccgSubSurf_getVertVertHandle(v));
int N = ccgSubSurf_getVertNumEdges(v);
int numFaces = ccgSubSurf_getVertNumFaces(v);
@@ -4032,9 +4888,34 @@ void subsurf_calculate_limit_positions(Mesh *me, float (*r_positions)[3])
r_positions[idx][1] = (co[1] * N * N + edge_sum[1] * 4 + face_sum[1]) / (N * (N + 5));
r_positions[idx][2] = (co[2] * N * N + edge_sum[2] * 4 + face_sum[2]) / (N * (N + 5));
}
- ccgVertIterator_free(vi);
ccgSubSurf_free(ss);
dm->release(dm);
}
+
+bool subsurf_has_edges(DerivedMesh *dm)
+{
+ CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm;
+#ifdef WITH_OPENSUBDIV
+ if (ccgdm->useGpuBackend) {
+ return true;
+ }
+#else
+ (void)ccgdm;
+#endif
+ return dm->getNumEdges(dm) != 0;
+}
+
+bool subsurf_has_faces(DerivedMesh *dm)
+{
+ CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm;
+#ifdef WITH_OPENSUBDIV
+ if (ccgdm->useGpuBackend) {
+ return true;
+ }
+#else
+ (void)ccgdm;
+#endif
+ return dm->getNumPolys(dm) != 0;
+}
diff --git a/source/blender/blenkernel/intern/text.c b/source/blender/blenkernel/intern/text.c
index 86371ba3c80..77d6043d6f3 100644
--- a/source/blender/blenkernel/intern/text.c
+++ b/source/blender/blenkernel/intern/text.c
@@ -330,7 +330,7 @@ static void text_from_buf(Text *text, const unsigned char *buffer, const int len
text->curc = text->selc = 0;
}
-int BKE_text_reload(Text *text)
+bool BKE_text_reload(Text *text)
{
FILE *fp;
int len;
@@ -339,13 +339,24 @@ int BKE_text_reload(Text *text)
char str[FILE_MAX];
BLI_stat_t st;
- if (!text || !text->name) return 0;
-
+ if (!text->name) {
+ return false;
+ }
+
BLI_strncpy(str, text->name, FILE_MAX);
BLI_path_abs(str, G.main->name);
fp = BLI_fopen(str, "r");
- if (fp == NULL) return 0;
+ if (fp == NULL) {
+ return false;
+ }
+ fseek(fp, 0L, SEEK_END);
+ len = ftell(fp);
+ fseek(fp, 0L, SEEK_SET);
+ if (UNLIKELY(len == -1)) {
+ fclose(fp);
+ return false;
+ }
/* free memory: */
@@ -363,25 +374,24 @@ int BKE_text_reload(Text *text)
MEM_freeN(text->undo_buf);
init_undo_text(text);
- fseek(fp, 0L, SEEK_END);
- len = ftell(fp);
- fseek(fp, 0L, SEEK_SET);
-
-
buffer = MEM_mallocN(len, "text_buffer");
- // under windows fread can return less then len bytes because
- // of CR stripping
+ /* under windows fread can return less than len bytes because
+ * of CR stripping */
len = fread(buffer, 1, len, fp);
fclose(fp);
- BLI_stat(str, &st);
- text->mtime = st.st_mtime;
+ if (BLI_stat(str, &st) != -1) {
+ text->mtime = st.st_mtime;
+ }
+ else {
+ text->mtime = 0;
+ }
text_from_buf(text, buffer, len);
MEM_freeN(buffer);
- return 1;
+ return true;
}
Text *BKE_text_load_ex(Main *bmain, const char *file, const char *relpath, const bool is_internal)
@@ -398,8 +408,18 @@ Text *BKE_text_load_ex(Main *bmain, const char *file, const char *relpath, const
BLI_path_abs(str, relpath);
fp = BLI_fopen(str, "r");
- if (fp == NULL) return NULL;
-
+ if (fp == NULL) {
+ return NULL;
+ }
+
+ fseek(fp, 0L, SEEK_END);
+ len = ftell(fp);
+ fseek(fp, 0L, SEEK_SET);
+ if (UNLIKELY(len == -1)) {
+ fclose(fp);
+ return NULL;
+ }
+
ta = BKE_libblock_alloc(bmain, ID_TXT, BLI_path_basename(str));
ta->id.us = 1;
@@ -419,20 +439,20 @@ Text *BKE_text_load_ex(Main *bmain, const char *file, const char *relpath, const
/* clear undo buffer */
init_undo_text(ta);
-
- fseek(fp, 0L, SEEK_END);
- len = ftell(fp);
- fseek(fp, 0L, SEEK_SET);
buffer = MEM_mallocN(len, "text_buffer");
- // under windows fread can return less then len bytes because
- // of CR stripping
+ /* under windows fread can return less than len bytes because
+ * of CR stripping */
len = fread(buffer, 1, len, fp);
fclose(fp);
- BLI_stat(str, &st);
- ta->mtime = st.st_mtime;
+ if (BLI_stat(str, &st) != -1) {
+ ta->mtime = st.st_mtime;
+ }
+ else {
+ ta->mtime = 0;
+ }
text_from_buf(ta, buffer, len);
@@ -446,7 +466,7 @@ Text *BKE_text_load(Main *bmain, const char *file, const char *relpath)
return BKE_text_load_ex(bmain, file, relpath, false);
}
-Text *BKE_text_copy(Text *ta)
+Text *BKE_text_copy(Main *bmain, Text *ta)
{
Text *tan;
TextLine *line, *tmp;
@@ -455,8 +475,7 @@ Text *BKE_text_copy(Text *ta)
/* file name can be NULL */
if (ta->name) {
- tan->name = MEM_mallocN(strlen(ta->name) + 1, "text_name");
- strcpy(tan->name, ta->name);
+ tan->name = BLI_strdup(ta->name);
}
else {
tan->name = NULL;
@@ -466,6 +485,7 @@ Text *BKE_text_copy(Text *ta)
BLI_listbase_clear(&tan->lines);
tan->curl = tan->sell = NULL;
+ tan->compiled = NULL;
tan->nlines = ta->nlines;
@@ -490,6 +510,10 @@ Text *BKE_text_copy(Text *ta)
init_undo_text(tan);
+ if (ta->id.lib) {
+ BKE_id_lib_local_paths(bmain, ta->id.lib, &tan->id);
+ }
+
return tan;
}
@@ -505,10 +529,14 @@ void BKE_text_unlink(Main *bmain, Text *text)
bNodeTree *ntree;
bNode *node;
Material *mat;
+ Lamp *la;
+ Tex *te;
+ World *wo;
+ FreestyleLineStyle *linestyle;
Scene *sce;
SceneRenderLayer *srl;
FreestyleModuleConfig *module;
- short update;
+ bool update;
for (ob = bmain->object.first; ob; ob = ob->id.next) {
/* game controllers */
@@ -560,23 +588,97 @@ void BKE_text_unlink(Main *bmain, Text *text)
}
/* nodes */
+ for (la = bmain->lamp.first; la; la = la->id.next) {
+ ntree = la->nodetree;
+ if (!ntree)
+ continue;
+ for (node = ntree->nodes.first; node; node = node->next) {
+ if (node->type == NODE_FRAME) {
+ if ((Text *)node->id == text) {
+ node->id = NULL;
+ }
+ }
+ }
+ }
+
+ for (linestyle = bmain->linestyle.first; linestyle; linestyle = linestyle->id.next) {
+ ntree = linestyle->nodetree;
+ if (!ntree)
+ continue;
+ for (node = ntree->nodes.first; node; node = node->next) {
+ if (node->type == NODE_FRAME) {
+ if ((Text *)node->id == text) {
+ node->id = NULL;
+ }
+ }
+ }
+ }
+
for (mat = bmain->mat.first; mat; mat = mat->id.next) {
ntree = mat->nodetree;
if (!ntree)
continue;
for (node = ntree->nodes.first; node; node = node->next) {
- if (node->type == SH_NODE_SCRIPT) {
+ if (ELEM(node->type, SH_NODE_SCRIPT, NODE_FRAME)) {
+ if ((Text *)node->id == text) {
+ node->id = NULL;
+ }
+ }
+ }
+ }
+
+ for (te = bmain->tex.first; te; te = te->id.next) {
+ ntree = te->nodetree;
+ if (!ntree)
+ continue;
+ for (node = ntree->nodes.first; node; node = node->next) {
+ if (node->type == NODE_FRAME) {
+ if ((Text *)node->id == text) {
+ node->id = NULL;
+ }
+ }
+ }
+ }
+
+ for (wo = bmain->world.first; wo; wo = wo->id.next) {
+ ntree = wo->nodetree;
+ if (!ntree)
+ continue;
+ for (node = ntree->nodes.first; node; node = node->next) {
+ if (node->type == NODE_FRAME) {
+ if ((Text *)node->id == text) {
+ node->id = NULL;
+ }
+ }
+ }
+ }
+
+ for (sce = bmain->scene.first; sce; sce = sce->id.next) {
+ ntree = sce->nodetree;
+ if (!ntree)
+ continue;
+ for (node = ntree->nodes.first; node; node = node->next) {
+ if (node->type == NODE_FRAME) {
Text *ntext = (Text *)node->id;
if (ntext == text) node->id = NULL;
}
}
+
+ /* Freestyle (while looping over the scene) */
+ for (srl = sce->r.layers.first; srl; srl = srl->next) {
+ for (module = srl->freestyleConfig.modules.first; module; module = module->next) {
+ if (module->script == text)
+ module->script = NULL;
+ }
+ }
}
-
+
for (ntree = bmain->nodetree.first; ntree; ntree = ntree->id.next) {
for (node = ntree->nodes.first; node; node = node->next) {
- if (node->type == SH_NODE_SCRIPT) {
- Text *ntext = (Text *)node->id;
- if (ntext == text) node->id = NULL;
+ if (ELEM(node->type, SH_NODE_SCRIPT, NODE_FRAME)) {
+ if ((Text *)node->id == text) {
+ node->id = NULL;
+ }
}
}
}
@@ -597,16 +699,6 @@ void BKE_text_unlink(Main *bmain, Text *text)
}
}
- /* Freestyle */
- for (sce = bmain->scene.first; sce; sce = sce->id.next) {
- for (srl = sce->r.layers.first; srl; srl = srl->next) {
- for (module = srl->freestyleConfig.modules.first; module; module = module->next) {
- if (module->script == text)
- module->script = NULL;
- }
- }
- }
-
text->id.us = 0;
}
@@ -614,7 +706,7 @@ void BKE_text_clear(Text *text) /* called directly from rna */
{
int oldstate;
- oldstate = txt_get_undostate( );
+ oldstate = txt_get_undostate();
txt_set_undostate(1);
txt_sel_all(text);
txt_delete_sel(text);
@@ -647,7 +739,7 @@ int BKE_text_file_modified_check(Text *text)
int result;
char file[FILE_MAX];
- if (!text || !text->name)
+ if (!text->name)
return 0;
BLI_strncpy(file, text->name, FILE_MAX);
@@ -676,7 +768,7 @@ void BKE_text_file_modified_ignore(Text *text)
int result;
char file[FILE_MAX];
- if (!text || !text->name) return;
+ if (!text->name) return;
BLI_strncpy(file, text->name, FILE_MAX);
BLI_path_abs(file, G.main->name);
@@ -742,9 +834,7 @@ static TextLine *txt_new_linen(const char *str, int n)
void txt_clean_text(Text *text)
{
TextLine **top, **bot;
-
- if (!text) return;
-
+
if (!text->lines.first) {
if (text->lines.last) text->lines.first = text->lines.last;
else text->lines.first = text->lines.last = txt_new_line(NULL);
@@ -883,8 +973,7 @@ void txt_move_up(Text *text, const bool sel)
{
TextLine **linep;
int *charp;
-
- if (!text) return;
+
if (sel) txt_curs_sel(text, &linep, &charp);
else { txt_pop_first(text); txt_curs_cur(text, &linep, &charp); }
if (!*linep) return;
@@ -906,8 +995,7 @@ void txt_move_down(Text *text, const bool sel)
{
TextLine **linep;
int *charp;
-
- if (!text) return;
+
if (sel) txt_curs_sel(text, &linep, &charp);
else { txt_pop_last(text); txt_curs_cur(text, &linep, &charp); }
if (!*linep) return;
@@ -929,8 +1017,7 @@ void txt_move_left(Text *text, const bool sel)
TextLine **linep;
int *charp;
int tabsize = 0, i = 0;
-
- if (!text) return;
+
if (sel) txt_curs_sel(text, &linep, &charp);
else { txt_pop_first(text); txt_curs_cur(text, &linep, &charp); }
if (!*linep) return;
@@ -974,8 +1061,7 @@ void txt_move_right(Text *text, const bool sel)
TextLine **linep;
int *charp, i;
bool do_tab = false;
-
- if (!text) return;
+
if (sel) txt_curs_sel(text, &linep, &charp);
else { txt_pop_last(text); txt_curs_cur(text, &linep, &charp); }
if (!*linep) return;
@@ -1016,8 +1102,7 @@ void txt_jump_left(Text *text, const bool sel, const bool use_init_step)
{
TextLine **linep;
int *charp;
-
- if (!text) return;
+
if (sel) txt_curs_sel(text, &linep, &charp);
else { txt_pop_first(text); txt_curs_cur(text, &linep, &charp); }
if (!*linep) return;
@@ -1033,8 +1118,7 @@ void txt_jump_right(Text *text, const bool sel, const bool use_init_step)
{
TextLine **linep;
int *charp;
-
- if (!text) return;
+
if (sel) txt_curs_sel(text, &linep, &charp);
else { txt_pop_last(text); txt_curs_cur(text, &linep, &charp); }
if (!*linep) return;
@@ -1050,8 +1134,7 @@ void txt_move_bol(Text *text, const bool sel)
{
TextLine **linep;
int *charp;
-
- if (!text) return;
+
if (sel) txt_curs_sel(text, &linep, &charp);
else txt_curs_cur(text, &linep, &charp);
if (!*linep) return;
@@ -1065,8 +1148,7 @@ void txt_move_eol(Text *text, const bool sel)
{
TextLine **linep;
int *charp;
-
- if (!text) return;
+
if (sel) txt_curs_sel(text, &linep, &charp);
else txt_curs_cur(text, &linep, &charp);
if (!*linep) return;
@@ -1080,8 +1162,7 @@ void txt_move_bof(Text *text, const bool sel)
{
TextLine **linep;
int *charp;
-
- if (!text) return;
+
if (sel) txt_curs_sel(text, &linep, &charp);
else txt_curs_cur(text, &linep, &charp);
if (!*linep) return;
@@ -1096,8 +1177,7 @@ void txt_move_eof(Text *text, const bool sel)
{
TextLine **linep;
int *charp;
-
- if (!text) return;
+
if (sel) txt_curs_sel(text, &linep, &charp);
else txt_curs_cur(text, &linep, &charp);
if (!*linep) return;
@@ -1119,8 +1199,7 @@ void txt_move_to(Text *text, unsigned int line, unsigned int ch, const bool sel)
TextLine **linep;
int *charp;
unsigned int i;
-
- if (!text) return;
+
if (sel) txt_curs_sel(text, &linep, &charp);
else txt_curs_cur(text, &linep, &charp);
if (!*linep) return;
@@ -1157,7 +1236,6 @@ static void txt_curs_swap(Text *text)
static void txt_pop_first(Text *text)
{
-
if (txt_get_span(text->curl, text->sell) < 0 ||
(text->curl == text->sell && text->curc > text->selc))
{
@@ -1186,7 +1264,6 @@ void txt_pop_sel(Text *text)
void txt_order_cursors(Text *text, const bool reverse)
{
- if (!text) return;
if (!text->curl) return;
if (!text->sell) return;
@@ -1216,8 +1293,7 @@ static void txt_delete_sel(Text *text)
{
TextLine *tmpl;
char *buf;
-
- if (!text) return;
+
if (!text->curl) return;
if (!text->sell) return;
@@ -1253,8 +1329,6 @@ static void txt_delete_sel(Text *text)
void txt_sel_all(Text *text)
{
- if (!text) return;
-
text->curl = text->lines.first;
text->curc = 0;
@@ -1277,7 +1351,6 @@ void txt_sel_clear(Text *text)
void txt_sel_line(Text *text)
{
- if (!text) return;
if (!text->curl) return;
text->curc = 0;
@@ -1295,8 +1368,7 @@ char *txt_to_buf(Text *text)
TextLine *tmp, *linef, *linel;
int charf, charl;
char *buf;
-
- if (!text) return NULL;
+
if (!text->curl) return NULL;
if (!text->sell) return NULL;
if (!text->lines.first) return NULL;
@@ -1358,7 +1430,7 @@ int txt_find_string(Text *text, const char *findstr, int wrap, int match_case)
TextLine *tl, *startl;
const char *s = NULL;
- if (!text || !text->curl || !text->sell) return 0;
+ if (!text->curl || !text->sell) return 0;
txt_order_cursors(text, false);
@@ -1398,8 +1470,7 @@ char *txt_sel_to_buf(Text *text)
int length = 0;
TextLine *tmp, *linef, *linel;
int charf, charl;
-
- if (!text) return NULL;
+
if (!text->curl) return NULL;
if (!text->sell) return NULL;
@@ -1480,7 +1551,6 @@ void txt_insert_buf(Text *text, const char *in_buffer)
TextLine *add;
char *buffer;
- if (!text) return;
if (!in_buffer) return;
txt_delete_sel(text);
@@ -1537,7 +1607,7 @@ static bool max_undo_test(Text *text, int x)
/* XXX error("Undo limit reached, buffer cleared\n"); */
MEM_freeN(text->undo_buf);
init_undo_text(text);
- return 0;
+ return false;
}
else {
void *tmp = text->undo_buf;
@@ -1548,7 +1618,7 @@ static bool max_undo_test(Text *text, int x)
}
}
- return 1;
+ return true;
}
#if 0 /* UNUSED */
@@ -1838,6 +1908,51 @@ static void txt_undo_add_charop(Text *text, int op_start, unsigned int c)
text->undo_buf[text->undo_pos + 1] = 0;
}
+/* extends Link */
+struct LinkInt {
+ struct LinkInt *next, *prev;
+ int value;
+};
+
+/**
+ * UnindentLines points to a #ListBase composed of #LinkInt elements, listing the numbers
+ * of the lines that should not be indented back.
+ */
+static void txt_undo_add_unprefix_op(
+ Text *text, char undo_op,
+ const ListBase *line_index_mask, const int line_index_mask_len)
+{
+ struct LinkInt *idata;
+
+ BLI_assert(BLI_listbase_count(line_index_mask) == line_index_mask_len);
+
+ /* OP byte + UInt32 count + counted UInt32 line numbers + UInt32 count + 12-bytes selection + OP byte */
+ if (!max_undo_test(text, 1 + 4 + (line_index_mask_len * 4) + 4 + 12 + 1)) {
+ return;
+ }
+
+ /* Opening buffer sequence with OP */
+ text->undo_pos++;
+ text->undo_buf[text->undo_pos] = undo_op;
+ text->undo_pos++;
+ /* Adding number of line numbers to read */
+ txt_undo_store_uint32(text->undo_buf, &text->undo_pos, line_index_mask_len);
+
+ /* Adding linenumbers of lines that shall not be indented if undoing */
+ for (idata = line_index_mask->first; idata; idata = idata->next) {
+ txt_undo_store_uint32(text->undo_buf, &text->undo_pos, idata->value);
+ }
+
+ /* Adding number of line numbers to read again */
+ txt_undo_store_uint32(text->undo_buf, &text->undo_pos, line_index_mask_len);
+ /* Adding current selection */
+ txt_undo_store_cursors(text);
+ /* Closing with OP (same as above) */
+ text->undo_buf[text->undo_pos] = undo_op;
+ /* Marking as last undo operation */
+ text->undo_buf[text->undo_pos + 1] = 0;
+}
+
static unsigned short txt_undo_read_uint16(const char *undo_buf, int *undo_pos)
{
unsigned short val;
@@ -2132,9 +2247,7 @@ void txt_do_undo(Text *text)
text->undo_pos--;
break;
case UNDO_INDENT:
- case UNDO_UNINDENT:
case UNDO_COMMENT:
- case UNDO_UNCOMMENT:
case UNDO_DUPLICATE:
case UNDO_MOVE_LINES_UP:
case UNDO_MOVE_LINES_DOWN:
@@ -2146,15 +2259,9 @@ void txt_do_undo(Text *text)
if (op == UNDO_INDENT) {
txt_unindent(text);
}
- else if (op == UNDO_UNINDENT) {
- txt_indent(text);
- }
else if (op == UNDO_COMMENT) {
txt_uncomment(text);
}
- else if (op == UNDO_UNCOMMENT) {
- txt_comment(text);
- }
else if (op == UNDO_DUPLICATE) {
txt_delete_line(text, text->curl->next);
}
@@ -2167,6 +2274,49 @@ void txt_do_undo(Text *text)
text->undo_pos--;
break;
+ case UNDO_UNINDENT:
+ case UNDO_UNCOMMENT:
+ {
+ void (*txt_prefix_fn)(Text *);
+ void (*txt_unprefix_fn)(Text *);
+ int count;
+ int i;
+ /* Get and restore the cursors */
+ txt_undo_read_cursors(text->undo_buf, &text->undo_pos, &curln, &curc, &selln, &selc);
+ txt_move_to(text, curln, curc, 0);
+ txt_move_to(text, selln, selc, 1);
+
+ /* Un-unindent */
+ if (op == UNDO_UNINDENT) {
+ txt_prefix_fn = txt_indent;
+ txt_unprefix_fn = txt_unindent;
+ }
+ else {
+ txt_prefix_fn = txt_comment;
+ txt_unprefix_fn = txt_uncomment;
+ }
+
+ txt_prefix_fn(text);
+
+ /* Get the count */
+ count = txt_undo_read_uint32(text->undo_buf, &text->undo_pos);
+ /* Iterate! */
+ txt_pop_sel(text);
+
+ for (i = 0; i < count; i++) {
+ txt_move_to(text, txt_undo_read_uint32(text->undo_buf, &text->undo_pos), 0, 0);
+ /* Un-un-unindent/comment */
+ txt_unprefix_fn(text);
+ }
+ /* Restore selection */
+ txt_move_to(text, curln, curc, 0);
+ txt_move_to(text, selln, selc, 1);
+ /* Jumo over count */
+ txt_undo_read_uint32(text->undo_buf, &text->undo_pos);
+ /* Jump over closing OP byte */
+ text->undo_pos--;
+ break;
+ }
default:
//XXX error("Undo buffer error - resetting");
text->undo_pos = -1;
@@ -2296,7 +2446,6 @@ void txt_do_redo(Text *text)
break;
case UNDO_INDENT:
- case UNDO_UNINDENT:
case UNDO_COMMENT:
case UNDO_UNCOMMENT:
case UNDO_DUPLICATE:
@@ -2312,9 +2461,6 @@ void txt_do_redo(Text *text)
if (op == UNDO_INDENT) {
txt_indent(text);
}
- else if (op == UNDO_UNINDENT) {
- txt_unindent(text);
- }
else if (op == UNDO_COMMENT) {
txt_comment(text);
}
@@ -2344,6 +2490,26 @@ void txt_do_redo(Text *text)
txt_move_to(text, selln, selc, 1);
break;
+ case UNDO_UNINDENT:
+ {
+ int count;
+ int i;
+
+ text->undo_pos++;
+ /* Scan all the stuff described in txt_undo_add_unindent_op */
+ count = txt_redo_read_uint32(text->undo_buf, &text->undo_pos);
+ for (i = 0; i < count; i++) {
+ txt_redo_read_uint32(text->undo_buf, &text->undo_pos);
+ }
+ /* Count again */
+ txt_redo_read_uint32(text->undo_buf, &text->undo_pos);
+ /* Get the selection and re-unindent */
+ txt_redo_read_cursors(text->undo_buf, &text->undo_pos, &curln, &curc, &selln, &selc);
+ txt_move_to(text, curln, curc, 0);
+ txt_move_to(text, selln, selc, 1);
+ txt_unindent(text);
+ break;
+ }
default:
//XXX error("Undo buffer error - resetting");
text->undo_pos = -1;
@@ -2362,8 +2528,7 @@ void txt_split_curline(Text *text)
{
TextLine *ins;
char *left, *right;
-
- if (!text) return;
+
if (!text->curl) return;
txt_delete_sel(text);
@@ -2405,7 +2570,6 @@ void txt_split_curline(Text *text)
static void txt_delete_line(Text *text, TextLine *line)
{
- if (!text) return;
if (!text->curl) return;
BLI_remlink(&text->lines, line);
@@ -2422,8 +2586,6 @@ static void txt_delete_line(Text *text, TextLine *line)
static void txt_combine_lines(Text *text, TextLine *linea, TextLine *lineb)
{
char *tmp, *s;
-
- if (!text) return;
if (!linea || !lineb) return;
@@ -2447,7 +2609,7 @@ void txt_duplicate_line(Text *text)
{
TextLine *textline;
- if (!text || !text->curl) return;
+ if (!text->curl) return;
if (text->curl == text->sell) {
textline = txt_new_line(text->curl->line);
@@ -2463,8 +2625,7 @@ void txt_duplicate_line(Text *text)
void txt_delete_char(Text *text)
{
unsigned int c = '\n';
-
- if (!text) return;
+
if (!text->curl) return;
if (txt_has_sel(text)) { /* deleting a selection */
@@ -2501,13 +2662,13 @@ void txt_delete_word(Text *text)
{
txt_jump_right(text, true, true);
txt_delete_sel(text);
+ txt_make_dirty(text);
}
void txt_backspace_char(Text *text)
{
unsigned int c = '\n';
- if (!text) return;
if (!text->curl) return;
if (txt_has_sel(text)) { /* deleting a selection */
@@ -2550,6 +2711,7 @@ void txt_backspace_word(Text *text)
{
txt_jump_left(text, true, true);
txt_delete_sel(text);
+ txt_make_dirty(text);
}
/* Max spaces to replace a tab with, currently hardcoded to TXT_TABSIZE = 4.
@@ -2571,19 +2733,18 @@ static bool txt_add_char_intern(Text *text, unsigned int add, bool replace_tabs)
{
char *tmp, ch[BLI_UTF8_MAX];
size_t add_len;
-
- if (!text) return 0;
+
if (!text->curl) return 0;
if (add == '\n') {
txt_split_curline(text);
- return 1;
+ return true;
}
/* insert spaces rather than tabs */
if (add == '\t' && replace_tabs) {
txt_convert_tab_to_spaces(text);
- return 1;
+ return true;
}
txt_delete_sel(text);
@@ -2631,9 +2792,8 @@ bool txt_replace_char(Text *text, unsigned int add)
unsigned int del;
size_t del_size = 0, add_size;
char ch[BLI_UTF8_MAX];
-
- if (!text) return 0;
- if (!text->curl) return 0;
+
+ if (!text->curl) return false;
/* If text is selected or we're at the end of the line just use txt_add_char */
if (text->curc == text->curl->len || txt_has_sel(text) || add == '\n') {
@@ -2672,29 +2832,22 @@ bool txt_replace_char(Text *text, unsigned int add)
text->curc += add_size;
txt_pop_sel(text);
}
- return 1;
+ return true;
}
-void txt_indent(Text *text)
+/**
+ * Generic prefix operation, use for comment & indent.
+ *
+ * \note caller must handle undo.
+ */
+static void txt_select_prefix(Text *text, const char *add)
{
int len, num, curc_old;
char *tmp;
- const char *add = "\t";
- int indentlen = 1;
-
- /* hardcoded: TXT_TABSIZE = 4 spaces: */
- int spaceslen = TXT_TABSIZE;
-
- if (ELEM(NULL, text, text->curl, text->sell)) {
- return;
- }
+ const int indentlen = strlen(add);
- /* insert spaces rather than tabs */
- if (text->flags & TXT_TABSTOSPACES) {
- add = tab_to_spaces;
- indentlen = spaceslen;
- }
+ BLI_assert(!ELEM(NULL, text->curl, text->sell));
curc_old = text->curc;
@@ -2738,40 +2891,55 @@ void txt_indent(Text *text)
num--;
}
- if (!undoing) {
- txt_undo_add_op(text, UNDO_INDENT);
- }
+ /* caller must handle undo */
}
-void txt_unindent(Text *text)
+/**
+ * Generic un-prefix operation, use for comment & indent.
+ *
+ * \param r_line_index_mask: List of lines that are already at indent level 0,
+ * to store them later into the undo buffer.
+ *
+ * \note caller must handle undo.
+ */
+static void txt_select_unprefix(
+ Text *text, const char *remove,
+ ListBase *r_line_index_mask, int *r_line_index_mask_len)
{
int num = 0;
- const char *remove = "\t";
- int indentlen = 1;
+ const int indentlen = strlen(remove);
bool unindented_first = false;
-
- /* hardcoded: TXT_TABSIZE = 4 spaces: */
- int spaceslen = TXT_TABSIZE;
- if (ELEM(NULL, text, text->curl, text->sell)) {
- return;
- }
+ int curl_span_init = 0;
- /* insert spaces rather than tabs */
- if (text->flags & TXT_TABSTOSPACES) {
- remove = tab_to_spaces;
- indentlen = spaceslen;
+ BLI_assert(!ELEM(NULL, text->curl, text->sell));
+
+ BLI_listbase_clear(r_line_index_mask);
+ *r_line_index_mask_len = 0;
+
+ if (!undoing) {
+ curl_span_init = txt_get_span(text->lines.first, text->curl);
}
while (true) {
bool changed = false;
- if (strncmp(text->curl->line, remove, indentlen) == 0) {
+ if (STREQLEN(text->curl->line, remove, indentlen)) {
if (num == 0)
unindented_first = true;
text->curl->len -= indentlen;
memmove(text->curl->line, text->curl->line + indentlen, text->curl->len + 1);
changed = true;
}
+ else {
+ if (!undoing) {
+ /* Create list element for 0 indent line */
+ struct LinkInt *idata = MEM_mallocN(sizeof(struct LinkInt), __func__);
+ idata->value = curl_span_init + num;
+ BLI_assert(idata->value == txt_get_span(text->lines.first, text->curl));
+ BLI_addtail(r_line_index_mask, idata);
+ (*r_line_index_mask_len) += 1;
+ }
+ }
txt_make_dirty(text);
txt_clean_text(text);
@@ -2784,6 +2952,7 @@ void txt_unindent(Text *text)
else {
text->curl = text->curl->next;
num++;
+
}
}
@@ -2795,56 +2964,20 @@ void txt_unindent(Text *text)
text->curl = text->curl->prev;
num--;
}
-
- if (!undoing) {
- txt_undo_add_op(text, UNDO_UNINDENT);
- }
+
+ /* caller must handle undo */
}
void txt_comment(Text *text)
{
- int len, num;
- char *tmp;
- char add = '#';
-
- if (!text) return;
- if (!text->curl) return;
- if (!text->sell) return; // Need to change this need to check if only one line is selected to more than one
-
- num = 0;
- while (true) {
- tmp = MEM_mallocN(text->curl->len + 2, "textline_string");
-
- text->curc = 0;
- if (text->curc) memcpy(tmp, text->curl->line, text->curc);
- tmp[text->curc] = add;
-
- len = text->curl->len - text->curc;
- if (len > 0) memcpy(tmp + text->curc + 1, text->curl->line + text->curc, len);
- tmp[text->curl->len + 1] = 0;
+ const char *prefix = "#";
- make_new_line(text->curl, tmp);
-
- text->curc++;
-
- txt_make_dirty(text);
- txt_clean_text(text);
-
- if (text->curl == text->sell) {
- text->selc = text->sell->len;
- break;
- }
- else {
- text->curl = text->curl->next;
- num++;
- }
- }
- text->curc = 0;
- while (num > 0) {
- text->curl = text->curl->prev;
- num--;
+ if (ELEM(NULL, text->curl, text->sell)) {
+ return;
}
-
+
+ txt_select_prefix(text, prefix);
+
if (!undoing) {
txt_undo_add_op(text, UNDO_COMMENT);
}
@@ -2852,47 +2985,55 @@ void txt_comment(Text *text)
void txt_uncomment(Text *text)
{
- int num = 0;
- char remove = '#';
-
- if (!text) return;
- if (!text->curl) return;
- if (!text->sell) return;
+ const char *prefix = "#";
+ ListBase line_index_mask;
+ int line_index_mask_len;
- while (true) {
- int i = 0;
-
- if (text->curl->line[i] == remove) {
- while (i < text->curl->len) {
- text->curl->line[i] = text->curl->line[i + 1];
- i++;
- }
- text->curl->len--;
- }
-
-
- txt_make_dirty(text);
- txt_clean_text(text);
-
- if (text->curl == text->sell) {
- text->selc = text->sell->len;
- break;
- }
- else {
- text->curl = text->curl->next;
- num++;
- }
-
+ if (ELEM(NULL, text->curl, text->sell)) {
+ return;
}
- text->curc = 0;
- while (num > 0) {
- text->curl = text->curl->prev;
- num--;
+
+ txt_select_unprefix(text, prefix, &line_index_mask, &line_index_mask_len);
+
+ if (!undoing) {
+ txt_undo_add_unprefix_op(text, UNDO_UNCOMMENT, &line_index_mask, line_index_mask_len);
+ }
+
+ BLI_freelistN(&line_index_mask);
+}
+
+void txt_indent(Text *text)
+{
+ const char *prefix = (text->flags & TXT_TABSTOSPACES) ? tab_to_spaces : "\t";
+
+ if (ELEM(NULL, text->curl, text->sell)) {
+ return;
+ }
+
+ txt_select_prefix(text, prefix);
+
+ if (!undoing) {
+ txt_undo_add_op(text, UNDO_INDENT);
}
+}
+
+void txt_unindent(Text *text)
+{
+ const char *prefix = (text->flags & TXT_TABSTOSPACES) ? tab_to_spaces : "\t";
+ ListBase line_index_mask;
+ int line_index_mask_len;
+ if (ELEM(NULL, text->curl, text->sell)) {
+ return;
+ }
+
+ txt_select_unprefix(text, prefix, &line_index_mask, &line_index_mask_len);
+
if (!undoing) {
- txt_undo_add_op(text, UNDO_UNCOMMENT);
+ txt_undo_add_unprefix_op(text, UNDO_UNINDENT, &line_index_mask, line_index_mask_len);
}
+
+ BLI_freelistN(&line_index_mask);
}
void txt_move_lines(struct Text *text, const int direction)
@@ -2901,7 +3042,7 @@ void txt_move_lines(struct Text *text, const int direction)
BLI_assert(ELEM(direction, TXT_MOVE_LINE_UP, TXT_MOVE_LINE_DOWN));
- if (!text || !text->curl || !text->sell) return;
+ if (!text->curl || !text->sell) return;
txt_order_cursors(text, false);
@@ -2934,6 +3075,7 @@ int txt_setcurr_tab_spaces(Text *text, int space)
const char *comm = "#";
const char indent = (text->flags & TXT_TABSTOSPACES) ? ' ' : '\t';
static const char *back_words[] = {"return", "break", "continue", "pass", "yield", NULL};
+
if (!text->curl) return 0;
while (text->curl->line[i] == indent) {
@@ -3008,37 +3150,37 @@ bool text_check_delim(const char ch)
for (a = 0; a < (sizeof(delims) - 1); a++) {
if (ch == delims[a])
- return 1;
+ return true;
}
- return 0;
+ return false;
}
bool text_check_digit(const char ch)
{
- if (ch < '0') return 0;
- if (ch <= '9') return 1;
- return 0;
+ if (ch < '0') return false;
+ if (ch <= '9') return true;
+ return false;
}
bool text_check_identifier(const char ch)
{
- if (ch < '0') return 0;
- if (ch <= '9') return 1;
- if (ch < 'A') return 0;
- if (ch <= 'Z' || ch == '_') return 1;
- if (ch < 'a') return 0;
- if (ch <= 'z') return 1;
- return 0;
+ if (ch < '0') return false;
+ if (ch <= '9') return true;
+ if (ch < 'A') return false;
+ if (ch <= 'Z' || ch == '_') return true;
+ if (ch < 'a') return false;
+ if (ch <= 'z') return true;
+ return false;
}
bool text_check_identifier_nodigit(const char ch)
{
- if (ch <= '9') return 0;
- if (ch < 'A') return 0;
- if (ch <= 'Z' || ch == '_') return 1;
- if (ch < 'a') return 0;
- if (ch <= 'z') return 1;
- return 0;
+ if (ch <= '9') return false;
+ if (ch < 'A') return false;
+ if (ch <= 'Z' || ch == '_') return true;
+ if (ch < 'a') return false;
+ if (ch <= 'z') return true;
+ return false;
}
#ifndef WITH_PYTHON
@@ -3056,8 +3198,8 @@ int text_check_identifier_nodigit_unicode(const unsigned int ch)
bool text_check_whitespace(const char ch)
{
if (ch == ' ' || ch == '\t' || ch == '\r' || ch == '\n')
- return 1;
- return 0;
+ return true;
+ return false;
}
int text_find_identifier_start(const char *str, int i)
diff --git a/source/blender/blenkernel/intern/texture.c b/source/blender/blenkernel/intern/texture.c
index b1981a3a804..88a412d5e95 100644
--- a/source/blender/blenkernel/intern/texture.c
+++ b/source/blender/blenkernel/intern/texture.c
@@ -37,7 +37,6 @@
#include "MEM_guardedalloc.h"
-#include "BLI_blenlib.h"
#include "BLI_math.h"
#include "BLI_kdopbvh.h"
#include "BLI_utildefines.h"
@@ -74,16 +73,16 @@
/* ****************** Mapping ******************* */
-TexMapping *add_tex_mapping(int type)
+TexMapping *BKE_texture_mapping_add(int type)
{
TexMapping *texmap = MEM_callocN(sizeof(TexMapping), "TexMapping");
- default_tex_mapping(texmap, type);
+ BKE_texture_mapping_default(texmap, type);
return texmap;
}
-void default_tex_mapping(TexMapping *texmap, int type)
+void BKE_texture_mapping_default(TexMapping *texmap, int type)
{
memset(texmap, 0, sizeof(TexMapping));
@@ -98,7 +97,7 @@ void default_tex_mapping(TexMapping *texmap, int type)
texmap->type = type;
}
-void init_tex_mapping(TexMapping *texmap)
+void BKE_texture_mapping_init(TexMapping *texmap)
{
float smat[4][4], rmat[4][4], tmat[4][4], proj[4][4], size[3];
@@ -171,16 +170,16 @@ void init_tex_mapping(TexMapping *texmap)
}
}
-ColorMapping *add_color_mapping(void)
+ColorMapping *BKE_texture_colormapping_add(void)
{
ColorMapping *colormap = MEM_callocN(sizeof(ColorMapping), "ColorMapping");
- default_color_mapping(colormap);
+ BKE_texture_colormapping_default(colormap);
return colormap;
}
-void default_color_mapping(ColorMapping *colormap)
+void BKE_texture_colormapping_default(ColorMapping *colormap)
{
memset(colormap, 0, sizeof(ColorMapping));
@@ -328,7 +327,7 @@ bool do_colorband(const ColorBand *coba, float in, float out[4])
int ipotype;
int a;
- if (coba == NULL || coba->tot == 0) return 0;
+ if (coba == NULL || coba->tot == 0) return false;
cbd1 = coba->data;
@@ -350,7 +349,11 @@ bool do_colorband(const ColorBand *coba, float in, float out[4])
CBData left, right;
/* we're looking for first pos > in */
- for (a = 0; a < coba->tot; a++, cbd1++) if (cbd1->pos > in) break;
+ for (a = 0; a < coba->tot; a++, cbd1++) {
+ if (cbd1->pos > in) {
+ break;
+ }
+ }
if (a == coba->tot) {
cbd2 = cbd1 - 1;
@@ -464,7 +467,7 @@ bool do_colorband(const ColorBand *coba, float in, float out[4])
}
}
}
- return 1; /* OK */
+ return true; /* OK */
}
void colorband_table_RGBA(ColorBand *coba, float **array, int *size)
@@ -557,14 +560,14 @@ int colorband_element_remove(struct ColorBand *coba, int index)
void BKE_texture_free(Tex *tex)
{
if (tex->coba) MEM_freeN(tex->coba);
- if (tex->env) BKE_free_envmap(tex->env);
- if (tex->pd) BKE_free_pointdensity(tex->pd);
- if (tex->vd) BKE_free_voxeldata(tex->vd);
- if (tex->ot) BKE_free_oceantex(tex->ot);
- BKE_free_animdata((struct ID *)tex);
+ if (tex->env) BKE_texture_envmap_free(tex->env);
+ if (tex->pd) BKE_texture_pointdensity_free(tex->pd);
+ if (tex->vd) BKE_texture_voxeldata_free(tex->vd);
+ if (tex->ot) BKE_texture_ocean_free(tex->ot);
+ BKE_animdata_free((struct ID *)tex);
BKE_previewimg_free(&tex->preview);
- BKE_icon_delete((struct ID *)tex);
+ BKE_icon_id_delete((struct ID *)tex);
tex->id.icon_id = 0;
if (tex->nodetree) {
@@ -575,7 +578,7 @@ void BKE_texture_free(Tex *tex)
/* ------------------------------------------------------------------------- */
-void default_tex(Tex *tex)
+void BKE_texture_default(Tex *tex)
{
tex->type = TEX_IMAGE;
tex->ima = NULL;
@@ -626,7 +629,7 @@ void default_tex(Tex *tex)
tex->env->stype = ENV_ANIM;
tex->env->clipsta = 0.1;
tex->env->clipend = 100;
- tex->env->cuberes = 600;
+ tex->env->cuberes = 512;
tex->env->depth = 0;
}
@@ -654,25 +657,25 @@ void default_tex(Tex *tex)
tex->preview = NULL;
}
-void tex_set_type(Tex *tex, int type)
+void BKE_texture_type_set(Tex *tex, int type)
{
switch (type) {
case TEX_VOXELDATA:
if (tex->vd == NULL)
- tex->vd = BKE_add_voxeldata();
+ tex->vd = BKE_texture_voxeldata_add();
break;
case TEX_POINTDENSITY:
if (tex->pd == NULL)
- tex->pd = BKE_add_pointdensity();
+ tex->pd = BKE_texture_pointdensity_add();
break;
case TEX_ENVMAP:
if (tex->env == NULL)
- tex->env = BKE_add_envmap();
+ tex->env = BKE_texture_envmap_add();
break;
case TEX_OCEAN:
if (tex->ot == NULL)
- tex->ot = BKE_add_oceantex();
+ tex->ot = BKE_texture_ocean_add();
break;
}
@@ -681,20 +684,20 @@ void tex_set_type(Tex *tex, int type)
/* ------------------------------------------------------------------------- */
-Tex *add_texture(Main *bmain, const char *name)
+Tex *BKE_texture_add(Main *bmain, const char *name)
{
Tex *tex;
tex = BKE_libblock_alloc(bmain, ID_TE, name);
- default_tex(tex);
+ BKE_texture_default(tex);
return tex;
}
/* ------------------------------------------------------------------------- */
-void default_mtex(MTex *mtex)
+void BKE_texture_mtex_default(MTex *mtex)
{
mtex->texco = TEXCO_UV;
mtex->mapto = MAP_COL;
@@ -746,6 +749,7 @@ void default_mtex(MTex *mtex)
mtex->lengthfac = 1.0f;
mtex->clumpfac = 1.0f;
mtex->kinkfac = 1.0f;
+ mtex->kinkampfac = 1.0f;
mtex->roughfac = 1.0f;
mtex->padensfac = 1.0f;
mtex->lifefac = 1.0f;
@@ -756,24 +760,26 @@ void default_mtex(MTex *mtex)
mtex->fieldfac = 1.0f;
mtex->normapspace = MTEX_NSPACE_TANGENT;
mtex->brush_map_mode = MTEX_MAP_MODE_TILED;
+ mtex->random_angle = 2.0f * (float)M_PI;
+ mtex->brush_angle_mode = 0;
}
/* ------------------------------------------------------------------------- */
-MTex *add_mtex(void)
+MTex *BKE_texture_mtex_add(void)
{
MTex *mtex;
- mtex = MEM_callocN(sizeof(MTex), "add_mtex");
+ mtex = MEM_callocN(sizeof(MTex), "BKE_texture_mtex_add");
- default_mtex(mtex);
+ BKE_texture_mtex_default(mtex);
return mtex;
}
/* slot -1 for first free ID */
-MTex *add_mtex_id(ID *id, int slot)
+MTex *BKE_texture_mtex_add_id(ID *id, int slot)
{
MTex **mtex_ar;
short act;
@@ -814,7 +820,7 @@ MTex *add_mtex_id(ID *id, int slot)
((Material *)id)->septex &= ~(1 << slot);
}
- mtex_ar[slot] = add_mtex();
+ mtex_ar[slot] = BKE_texture_mtex_add();
return mtex_ar[slot];
}
@@ -826,14 +832,18 @@ Tex *BKE_texture_copy(Tex *tex)
Tex *texn;
texn = BKE_libblock_copy(&tex->id);
- if (texn->type == TEX_IMAGE) id_us_plus((ID *)texn->ima);
- else texn->ima = NULL;
+ if (BKE_texture_is_image_user(tex)) {
+ id_us_plus((ID *)texn->ima);
+ }
+ else {
+ texn->ima = NULL;
+ }
if (texn->coba) texn->coba = MEM_dupallocN(texn->coba);
- if (texn->env) texn->env = BKE_copy_envmap(texn->env);
- if (texn->pd) texn->pd = BKE_copy_pointdensity(texn->pd);
+ if (texn->env) texn->env = BKE_texture_envmap_copy(texn->env);
+ if (texn->pd) texn->pd = BKE_texture_pointdensity_copy(texn->pd);
if (texn->vd) texn->vd = MEM_dupallocN(texn->vd);
- if (texn->ot) texn->ot = BKE_copy_oceantex(texn->ot);
+ if (texn->ot) texn->ot = BKE_texture_ocean_copy(texn->ot);
if (tex->preview) texn->preview = BKE_previewimg_copy(tex->preview);
if (tex->nodetree) {
@@ -843,11 +853,15 @@ Tex *BKE_texture_copy(Tex *tex)
texn->nodetree = ntreeCopyTree(tex->nodetree);
}
+ if (tex->id.lib) {
+ BKE_id_lib_local_paths(G.main, tex->id.lib, &texn->id);
+ }
+
return texn;
}
/* texture copy without adding to main dbase */
-Tex *localize_texture(Tex *tex)
+Tex *BKE_texture_localize(Tex *tex)
{
Tex *texn;
@@ -857,17 +871,17 @@ Tex *localize_texture(Tex *tex)
if (texn->coba) texn->coba = MEM_dupallocN(texn->coba);
if (texn->env) {
- texn->env = BKE_copy_envmap(texn->env);
+ texn->env = BKE_texture_envmap_copy(texn->env);
id_us_min(&texn->env->ima->id);
}
- if (texn->pd) texn->pd = BKE_copy_pointdensity(texn->pd);
+ if (texn->pd) texn->pd = BKE_texture_pointdensity_copy(texn->pd);
if (texn->vd) {
texn->vd = MEM_dupallocN(texn->vd);
if (texn->vd->dataset)
texn->vd->dataset = MEM_dupallocN(texn->vd->dataset);
}
if (texn->ot) {
- texn->ot = BKE_copy_oceantex(tex->ot);
+ texn->ot = BKE_texture_ocean_copy(tex->ot);
}
texn->preview = NULL;
@@ -1118,7 +1132,7 @@ void set_current_lamp_texture(Lamp *la, Tex *newtex)
if (newtex) {
if (!la->mtex[act]) {
- la->mtex[act] = add_mtex();
+ la->mtex[act] = BKE_texture_mtex_add();
la->mtex[act]->texco = TEXCO_GLOB;
}
@@ -1153,7 +1167,7 @@ void set_current_linestyle_texture(FreestyleLineStyle *linestyle, Tex *newtex)
if (newtex) {
if (!linestyle->mtex[act]) {
- linestyle->mtex[act] = add_mtex();
+ linestyle->mtex[act] = BKE_texture_mtex_add();
linestyle->mtex[act]->texco = TEXCO_STROKE;
}
@@ -1282,7 +1296,7 @@ void set_current_material_texture(Material *ma, Tex *newtex)
if (newtex) {
if (!ma->mtex[act]) {
- ma->mtex[act] = add_mtex();
+ ma->mtex[act] = BKE_texture_mtex_add();
/* Reset this slot's ON/OFF toggle, for materials, when slot was empty. */
ma->septex &= ~(1 << act);
}
@@ -1305,7 +1319,7 @@ bool has_current_material_texture(Material *ma)
node = nodeGetActiveID(ma->nodetree, ID_TE);
if (node)
- return 1;
+ return true;
}
return (ma != NULL);
@@ -1333,7 +1347,7 @@ void set_current_world_texture(World *wo, Tex *newtex)
if (newtex) {
if (!wo->mtex[act]) {
- wo->mtex[act] = add_mtex();
+ wo->mtex[act] = BKE_texture_mtex_add();
wo->mtex[act]->texco = TEXCO_VIEW;
}
@@ -1384,7 +1398,7 @@ void set_current_particle_texture(ParticleSettings *part, Tex *newtex)
if (newtex) {
if (!part->mtex[act]) {
- part->mtex[act] = add_mtex();
+ part->mtex[act] = BKE_texture_mtex_add();
part->mtex[act]->texco = TEXCO_ORCO;
part->mtex[act]->blendtype = MTEX_MUL;
}
@@ -1400,7 +1414,7 @@ void set_current_particle_texture(ParticleSettings *part, Tex *newtex)
/* ------------------------------------------------------------------------- */
-EnvMap *BKE_add_envmap(void)
+EnvMap *BKE_texture_envmap_add(void)
{
EnvMap *env;
@@ -1409,7 +1423,7 @@ EnvMap *BKE_add_envmap(void)
env->stype = ENV_ANIM;
env->clipsta = 0.1;
env->clipend = 100.0;
- env->cuberes = 600;
+ env->cuberes = 512;
env->viewscale = 0.5;
return env;
@@ -1417,7 +1431,7 @@ EnvMap *BKE_add_envmap(void)
/* ------------------------------------------------------------------------- */
-EnvMap *BKE_copy_envmap(EnvMap *env)
+EnvMap *BKE_texture_envmap_copy(EnvMap *env)
{
EnvMap *envn;
int a;
@@ -1432,7 +1446,7 @@ EnvMap *BKE_copy_envmap(EnvMap *env)
/* ------------------------------------------------------------------------- */
-void BKE_free_envmapdata(EnvMap *env)
+void BKE_texture_envmap_free_data(EnvMap *env)
{
unsigned int part;
@@ -1446,21 +1460,18 @@ void BKE_free_envmapdata(EnvMap *env)
/* ------------------------------------------------------------------------- */
-void BKE_free_envmap(EnvMap *env)
+void BKE_texture_envmap_free(EnvMap *env)
{
- BKE_free_envmapdata(env);
+ BKE_texture_envmap_free_data(env);
MEM_freeN(env);
}
/* ------------------------------------------------------------------------- */
-PointDensity *BKE_add_pointdensity(void)
+void BKE_texture_pointdensity_init_data(PointDensity *pd)
{
- PointDensity *pd;
-
- pd = MEM_callocN(sizeof(PointDensity), "pointdensity");
pd->flag = 0;
pd->radius = 0.3f;
pd->falloff_type = TEX_PD_FALLOFF_STD;
@@ -1484,11 +1495,16 @@ PointDensity *BKE_add_pointdensity(void)
pd->falloff_curve->cm->flag &= ~CUMA_EXTEND_EXTRAPOLATE;
curvemap_reset(pd->falloff_curve->cm, &pd->falloff_curve->clipr, pd->falloff_curve->preset, CURVEMAP_SLOPE_POSITIVE);
curvemapping_changed(pd->falloff_curve, false);
+}
+PointDensity *BKE_texture_pointdensity_add(void)
+{
+ PointDensity *pd = MEM_callocN(sizeof(PointDensity), "pointdensity");
+ BKE_texture_pointdensity_init_data(pd);
return pd;
}
-PointDensity *BKE_copy_pointdensity(PointDensity *pd)
+PointDensity *BKE_texture_pointdensity_copy(PointDensity *pd)
{
PointDensity *pdn;
@@ -1500,7 +1516,7 @@ PointDensity *BKE_copy_pointdensity(PointDensity *pd)
return pdn;
}
-void BKE_free_pointdensitydata(PointDensity *pd)
+void BKE_texture_pointdensity_free_data(PointDensity *pd)
{
if (pd->point_tree) {
BLI_bvhtree_free(pd->point_tree);
@@ -1518,15 +1534,15 @@ void BKE_free_pointdensitydata(PointDensity *pd)
curvemapping_free(pd->falloff_curve); /* can be NULL */
}
-void BKE_free_pointdensity(PointDensity *pd)
+void BKE_texture_pointdensity_free(PointDensity *pd)
{
- BKE_free_pointdensitydata(pd);
+ BKE_texture_pointdensity_free_data(pd);
MEM_freeN(pd);
}
/* ------------------------------------------------------------------------- */
-void BKE_free_voxeldatadata(VoxelData *vd)
+void BKE_texture_voxeldata_free_data(VoxelData *vd)
{
if (vd->dataset) {
MEM_freeN(vd->dataset);
@@ -1535,13 +1551,13 @@ void BKE_free_voxeldatadata(VoxelData *vd)
}
-void BKE_free_voxeldata(VoxelData *vd)
+void BKE_texture_voxeldata_free(VoxelData *vd)
{
- BKE_free_voxeldatadata(vd);
+ BKE_texture_voxeldata_free_data(vd);
MEM_freeN(vd);
}
-VoxelData *BKE_add_voxeldata(void)
+VoxelData *BKE_texture_voxeldata_add(void)
{
VoxelData *vd;
@@ -1559,7 +1575,7 @@ VoxelData *BKE_add_voxeldata(void)
return vd;
}
-VoxelData *BKE_copy_voxeldata(VoxelData *vd)
+VoxelData *BKE_texture_voxeldata_copy(VoxelData *vd)
{
VoxelData *vdn;
@@ -1571,7 +1587,7 @@ VoxelData *BKE_copy_voxeldata(VoxelData *vd)
/* ------------------------------------------------------------------------- */
-OceanTex *BKE_add_oceantex(void)
+OceanTex *BKE_texture_ocean_add(void)
{
OceanTex *ot;
@@ -1582,39 +1598,64 @@ OceanTex *BKE_add_oceantex(void)
return ot;
}
-OceanTex *BKE_copy_oceantex(struct OceanTex *ot)
+OceanTex *BKE_texture_ocean_copy(struct OceanTex *ot)
{
OceanTex *otn = MEM_dupallocN(ot);
return otn;
}
-void BKE_free_oceantex(struct OceanTex *ot)
+void BKE_texture_ocean_free(struct OceanTex *ot)
{
MEM_freeN(ot);
}
+/**
+ * \returns true if this texture can use its #Texture.ima (even if its NULL)
+ */
+bool BKE_texture_is_image_user(const struct Tex *tex)
+{
+ switch (tex->type) {
+ case TEX_IMAGE:
+ {
+ return true;
+ }
+ case TEX_ENVMAP:
+ {
+ if (tex->env) {
+ if (tex->env->stype == ENV_LOAD) {
+ return true;
+ }
+ }
+ break;
+ }
+ }
+
+ return false;
+}
/* ------------------------------------------------------------------------- */
bool BKE_texture_dependsOnTime(const struct Tex *texture)
{
if (texture->ima && BKE_image_is_animated(texture->ima)) {
- return 1;
+ return true;
}
else if (texture->adt) {
/* assume anything in adt means the texture is animated */
- return 1;
+ return true;
}
else if (texture->type == TEX_NOISE) {
/* noise always varies with time */
- return 1;
+ return true;
}
- return 0;
+ return false;
}
/* ------------------------------------------------------------------------- */
-void BKE_texture_get_value(Scene *scene, Tex *texture, float *tex_co, TexResult *texres, bool use_color_management)
+void BKE_texture_get_value(
+ const Scene *scene, Tex *texture,
+ float *tex_co, TexResult *texres, bool use_color_management)
{
int result_type;
bool do_color_manage = false;
@@ -1624,7 +1665,7 @@ void BKE_texture_get_value(Scene *scene, Tex *texture, float *tex_co, TexResult
}
/* no node textures for now */
- result_type = multitex_ext_safe(texture, tex_co, texres, NULL, do_color_manage);
+ result_type = multitex_ext_safe(texture, tex_co, texres, NULL, do_color_manage, false);
/* if the texture gave an RGB value, we assume it didn't give a valid
* intensity, since this is in the context of modifiers don't use perceptual color conversion.
diff --git a/source/blender/blenkernel/intern/tracking.c b/source/blender/blenkernel/intern/tracking.c
index 40d9dc0d7e0..9368e58d467 100644
--- a/source/blender/blenkernel/intern/tracking.c
+++ b/source/blender/blenkernel/intern/tracking.c
@@ -51,7 +51,7 @@
#include "BLI_string.h"
#include "BLI_threads.h"
-#include "BLF_translation.h"
+#include "BLT_translation.h"
#include "BKE_fcurve.h"
#include "BKE_tracking.h"
@@ -468,7 +468,7 @@ MovieTrackingTrack *BKE_tracking_track_duplicate(MovieTrackingTrack *track)
*/
void BKE_tracking_track_unique_name(ListBase *tracksbase, MovieTrackingTrack *track)
{
- BLI_uniquename(tracksbase, track, CTX_DATA_(BLF_I18NCONTEXT_ID_MOVIECLIP, "Track"), '.',
+ BLI_uniquename(tracksbase, track, CTX_DATA_(BLT_I18NCONTEXT_ID_MOVIECLIP, "Track"), '.',
offsetof(MovieTrackingTrack, name), sizeof(track->name));
}
@@ -547,7 +547,7 @@ bool BKE_tracking_track_has_enabled_marker_at_frame(MovieTrackingTrack *track, i
* - If action is TRACK_CLEAR_UPTO path from the beginning up to
* ref_frame-1 will be clear.
*
- * - If action is TRACK_CLEAR_ALL only mareker at frame ref_frame will remain.
+ * - If action is TRACK_CLEAR_ALL only marker at frame ref_frame will remain.
*
* NOTE: frame number should be in clip space, not scene space
*/
@@ -721,7 +721,7 @@ MovieTrackingTrack *BKE_tracking_track_get_named(MovieTracking *tracking, MovieT
MovieTrackingTrack *track = tracksbase->first;
while (track) {
- if (!strcmp(track->name, name))
+ if (STREQ(track->name, name))
return track;
track = track->next;
@@ -730,7 +730,7 @@ MovieTrackingTrack *BKE_tracking_track_get_named(MovieTracking *tracking, MovieT
return NULL;
}
-MovieTrackingTrack *BKE_tracking_track_get_indexed(MovieTracking *tracking, int tracknr, ListBase **tracksbase_r)
+MovieTrackingTrack *BKE_tracking_track_get_indexed(MovieTracking *tracking, int tracknr, ListBase **r_tracksbase)
{
MovieTrackingObject *object;
int cur = 1;
@@ -743,7 +743,7 @@ MovieTrackingTrack *BKE_tracking_track_get_indexed(MovieTracking *tracking, int
while (track) {
if (track->flag & TRACK_HAS_BUNDLE) {
if (cur == tracknr) {
- *tracksbase_r = tracksbase;
+ *r_tracksbase = tracksbase;
return track;
}
@@ -756,7 +756,7 @@ MovieTrackingTrack *BKE_tracking_track_get_indexed(MovieTracking *tracking, int
object = object->next;
}
- *tracksbase_r = NULL;
+ *r_tracksbase = NULL;
return NULL;
}
@@ -1238,7 +1238,7 @@ MovieTrackingPlaneTrack *BKE_tracking_plane_track_add(MovieTracking *tracking, L
void BKE_tracking_plane_track_unique_name(ListBase *plane_tracks_base, MovieTrackingPlaneTrack *plane_track)
{
- BLI_uniquename(plane_tracks_base, plane_track, CTX_DATA_(BLF_I18NCONTEXT_ID_MOVIECLIP, "Plane Track"), '.',
+ BLI_uniquename(plane_tracks_base, plane_track, CTX_DATA_(BLT_I18NCONTEXT_ID_MOVIECLIP, "Plane Track"), '.',
offsetof(MovieTrackingPlaneTrack, name), sizeof(plane_track->name));
}
@@ -1267,7 +1267,7 @@ MovieTrackingPlaneTrack *BKE_tracking_plane_track_get_named(MovieTracking *track
plane_track;
plane_track = plane_track->next)
{
- if (!strcmp(plane_track->name, name)) {
+ if (STREQ(plane_track->name, name)) {
return plane_track;
}
}
@@ -1302,6 +1302,95 @@ void BKE_tracking_plane_tracks_deselect_all(ListBase *plane_tracks_base)
}
}
+bool BKE_tracking_plane_track_has_point_track(MovieTrackingPlaneTrack *plane_track,
+ MovieTrackingTrack *track)
+{
+ int i;
+ for (i = 0; i < plane_track->point_tracksnr; i++) {
+ if (plane_track->point_tracks[i] == track) {
+ return true;
+ }
+ }
+ return false;
+}
+
+bool BKE_tracking_plane_track_remove_point_track(MovieTrackingPlaneTrack *plane_track,
+ MovieTrackingTrack *track)
+{
+ int i, track_index;
+ MovieTrackingTrack **new_point_tracks;
+
+ if (plane_track->point_tracksnr <= 4) {
+ return false;
+ }
+
+ new_point_tracks = MEM_mallocN(sizeof(*new_point_tracks) * (plane_track->point_tracksnr - 1),
+ "new point tracks array");
+
+ for (i = 0, track_index = 0; i < plane_track->point_tracksnr; i++) {
+ if (plane_track->point_tracks[i] != track) {
+ new_point_tracks[track_index++] = plane_track->point_tracks[i];
+ }
+ }
+
+ MEM_freeN(plane_track->point_tracks);
+ plane_track->point_tracks = new_point_tracks;
+ plane_track->point_tracksnr--;
+
+ return true;
+}
+
+void BKE_tracking_plane_tracks_remove_point_track(MovieTracking *tracking,
+ MovieTrackingTrack *track)
+{
+ MovieTrackingPlaneTrack *plane_track, *next_plane_track;
+ ListBase *plane_tracks_base = BKE_tracking_get_active_plane_tracks(tracking);
+ for (plane_track = plane_tracks_base->first;
+ plane_track;
+ plane_track = next_plane_track)
+ {
+ next_plane_track = plane_track->next;
+ if (BKE_tracking_plane_track_has_point_track(plane_track, track)) {
+ if (!BKE_tracking_plane_track_remove_point_track(plane_track, track)) {
+ /* Delete planes with less than 3 point tracks in it. */
+ BKE_tracking_plane_track_free(plane_track);
+ BLI_freelinkN(plane_tracks_base, plane_track);
+ }
+ }
+ }
+}
+
+void BKE_tracking_plane_track_replace_point_track(MovieTrackingPlaneTrack *plane_track,
+ MovieTrackingTrack *old_track,
+ MovieTrackingTrack *new_track)
+{
+ int i;
+ for (i = 0; i < plane_track->point_tracksnr; i++) {
+ if (plane_track->point_tracks[i] == old_track) {
+ plane_track->point_tracks[i] = new_track;
+ break;
+ }
+ }
+}
+
+void BKE_tracking_plane_tracks_replace_point_track(MovieTracking *tracking,
+ MovieTrackingTrack *old_track,
+ MovieTrackingTrack *new_track)
+{
+ MovieTrackingPlaneTrack *plane_track;
+ ListBase *plane_tracks_base = BKE_tracking_get_active_plane_tracks(tracking);
+ for (plane_track = plane_tracks_base->first;
+ plane_track;
+ plane_track = plane_track->next)
+ {
+ if (BKE_tracking_plane_track_has_point_track(plane_track, old_track)) {
+ BKE_tracking_plane_track_replace_point_track(plane_track,
+ old_track,
+ new_track);
+ }
+ }
+}
+
/*********************** Plane Marker *************************/
MovieTrackingPlaneMarker *BKE_tracking_plane_marker_insert(MovieTrackingPlaneTrack *plane_track,
@@ -1456,6 +1545,35 @@ MovieTrackingPlaneMarker *BKE_tracking_plane_marker_ensure(MovieTrackingPlaneTra
return plane_marker;
}
+void BKE_tracking_plane_marker_get_subframe_corners(MovieTrackingPlaneTrack *plane_track,
+ float framenr,
+ float corners[4][2])
+{
+ MovieTrackingPlaneMarker *marker = BKE_tracking_plane_marker_get(plane_track, (int)framenr);
+ MovieTrackingPlaneMarker *marker_last = plane_track->markers + (plane_track->markersnr - 1);
+ int i;
+ if (marker != marker_last) {
+ MovieTrackingPlaneMarker *marker_next = marker + 1;
+ if (marker_next->framenr == marker->framenr + 1) {
+ float fac = (framenr - (int) framenr) / (marker_next->framenr - marker->framenr);
+ for (i = 0; i < 4; ++i) {
+ interp_v2_v2v2(corners[i], marker->corners[i],
+ marker_next->corners[i], fac);
+ }
+ }
+ else {
+ for (i = 0; i < 4; ++i) {
+ copy_v2_v2(corners[i], marker->corners[i]);
+ }
+ }
+ }
+ else {
+ for (i = 0; i < 4; ++i) {
+ copy_v2_v2(corners[i], marker->corners[i]);
+ }
+ }
+}
+
/*********************** Object *************************/
MovieTrackingObject *BKE_tracking_object_add(MovieTracking *tracking, const char *name)
@@ -1475,7 +1593,7 @@ MovieTrackingObject *BKE_tracking_object_add(MovieTracking *tracking, const char
BLI_addtail(&tracking->objects, object);
tracking->tot_object++;
- tracking->objectnr = BLI_countlist(&tracking->objects) - 1;
+ tracking->objectnr = BLI_listbase_count(&tracking->objects) - 1;
object->scale = 1.0f;
object->keyframe1 = 1;
@@ -1534,7 +1652,7 @@ MovieTrackingObject *BKE_tracking_object_get_named(MovieTracking *tracking, cons
MovieTrackingObject *object = tracking->objects.first;
while (object) {
- if (!strcmp(object->name, name))
+ if (STREQ(object->name, name))
return object;
object = object->next;
@@ -1704,7 +1822,7 @@ MovieReconstructedCamera *BKE_tracking_camera_get_reconstructed(MovieTracking *t
}
void BKE_tracking_camera_get_reconstructed_interpolate(MovieTracking *tracking, MovieTrackingObject *object,
- int framenr, float mat[4][4])
+ float framenr, float mat[4][4])
{
MovieTrackingReconstruction *reconstruction;
MovieReconstructedCamera *cameras;
@@ -1712,17 +1830,15 @@ void BKE_tracking_camera_get_reconstructed_interpolate(MovieTracking *tracking,
reconstruction = BKE_tracking_object_get_reconstruction(tracking, object);
cameras = reconstruction->cameras;
- a = reconstructed_camera_index_get(reconstruction, framenr, true);
+ a = reconstructed_camera_index_get(reconstruction, (int)framenr, true);
if (a == -1) {
unit_m4(mat);
-
return;
}
- if (cameras[a].framenr != framenr && a > 0 && a < reconstruction->camnr - 1) {
+ if (cameras[a].framenr != framenr && a < reconstruction->camnr - 1) {
float t = ((float)framenr - cameras[a].framenr) / (cameras[a + 1].framenr - cameras[a].framenr);
-
blend_m4_m4m4(mat, cameras[a].mat, cameras[a + 1].mat, t);
}
else {
@@ -2410,30 +2526,30 @@ static void tracking_dopesheet_channels_sort(MovieTracking *tracking, int sort_m
if (inverse) {
if (sort_method == TRACKING_DOPE_SORT_NAME) {
- BLI_sortlist(&dopesheet->channels, channels_alpha_inverse_sort);
+ BLI_listbase_sort(&dopesheet->channels, channels_alpha_inverse_sort);
}
else if (sort_method == TRACKING_DOPE_SORT_LONGEST) {
- BLI_sortlist(&dopesheet->channels, channels_longest_segment_inverse_sort);
+ BLI_listbase_sort(&dopesheet->channels, channels_longest_segment_inverse_sort);
}
else if (sort_method == TRACKING_DOPE_SORT_TOTAL) {
- BLI_sortlist(&dopesheet->channels, channels_total_track_inverse_sort);
+ BLI_listbase_sort(&dopesheet->channels, channels_total_track_inverse_sort);
}
else if (sort_method == TRACKING_DOPE_SORT_AVERAGE_ERROR) {
- BLI_sortlist(&dopesheet->channels, channels_average_error_inverse_sort);
+ BLI_listbase_sort(&dopesheet->channels, channels_average_error_inverse_sort);
}
}
else {
if (sort_method == TRACKING_DOPE_SORT_NAME) {
- BLI_sortlist(&dopesheet->channels, channels_alpha_sort);
+ BLI_listbase_sort(&dopesheet->channels, channels_alpha_sort);
}
else if (sort_method == TRACKING_DOPE_SORT_LONGEST) {
- BLI_sortlist(&dopesheet->channels, channels_longest_segment_sort);
+ BLI_listbase_sort(&dopesheet->channels, channels_longest_segment_sort);
}
else if (sort_method == TRACKING_DOPE_SORT_TOTAL) {
- BLI_sortlist(&dopesheet->channels, channels_total_track_sort);
+ BLI_listbase_sort(&dopesheet->channels, channels_total_track_sort);
}
else if (sort_method == TRACKING_DOPE_SORT_AVERAGE_ERROR) {
- BLI_sortlist(&dopesheet->channels, channels_average_error_sort);
+ BLI_listbase_sort(&dopesheet->channels, channels_average_error_sort);
}
}
}
diff --git a/source/blender/blenkernel/intern/tracking_auto.c b/source/blender/blenkernel/intern/tracking_auto.c
new file mode 100644
index 00000000000..76261bddfbc
--- /dev/null
+++ b/source/blender/blenkernel/intern/tracking_auto.c
@@ -0,0 +1,558 @@
+/*
+ * ***** 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) 2011 Blender Foundation.
+ * All rights reserved.
+ *
+ * Contributor(s): Blender Foundation,
+ * Sergey Sharybin
+ * Keir Mierle
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/blenkernel/intern/tracking_auto.c
+ * \ingroup bke
+ */
+
+#include <stdlib.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_movieclip_types.h"
+#include "DNA_object_types.h" /* SELECT */
+
+#include "BLI_threads.h"
+#include "BLI_utildefines.h"
+#include "BLI_math.h"
+
+#include "BKE_movieclip.h"
+#include "BKE_tracking.h"
+
+#include "libmv-capi.h"
+#include "tracking_private.h"
+
+typedef struct AutoTrackOptions {
+ int clip_index; /** Index of the clip this track belogs to. */
+ int track_index; /* Index of the track in AutoTrack tracks structure. */
+ MovieTrackingTrack *track; /* Pointer to an original track/ */
+ libmv_TrackRegionOptions track_region_options; /* Options for the region
+ tracker. */
+ bool use_keyframe_match; /* Keyframe pattern matching. */
+
+ /* TODO(sergey): A bit awkward to keep it in here, only used to
+ * place a disabled marker once the tracking fails,
+ * Wither find a more clear way to do it or call it track context
+ * or state, not options.
+ */
+ bool is_failed;
+ int failed_frame;
+} AutoTrackOptions;
+
+typedef struct AutoTrackContext {
+ MovieClip *clips[MAX_ACCESSOR_CLIP];
+ int num_clips;
+
+ MovieClipUser user;
+ int frame_width, frame_height;
+
+ struct libmv_AutoTrack *autotrack;
+ TrackingImageAccessor *image_accessor;
+
+ int num_tracks; /* Number of tracks being tracked. */
+ AutoTrackOptions *options; /* Per-tracking track options. */
+
+ bool backwards;
+ bool sequence;
+ int first_frame;
+ int sync_frame;
+ bool first_sync;
+ SpinLock spin_lock;
+} AutoTrackContext;
+
+static void normalized_to_libmv_frame(const float normalized[2],
+ const int frame_dimensions[2],
+ float result[2])
+{
+ result[0] = normalized[0] * frame_dimensions[0] - 0.5f;
+ result[1] = normalized[1] * frame_dimensions[1] - 0.5f;
+}
+
+static void normalized_relative_to_libmv_frame(const float normalized[2],
+ const float origin[2],
+ const int frame_dimensions[2],
+ float result[2])
+{
+ result[0] = (normalized[0] + origin[0]) * frame_dimensions[0] - 0.5f;
+ result[1] = (normalized[1] + origin[1]) * frame_dimensions[1] - 0.5f;
+}
+
+static void libmv_frame_to_normalized(const float frame_coord[2],
+ const int frame_dimensions[2],
+ float result[2])
+{
+ result[0] = (frame_coord[0] + 0.5f) / frame_dimensions[0];
+ result[1] = (frame_coord[1] + 0.5f) / frame_dimensions[1];
+}
+
+static void libmv_frame_to_normalized_relative(const float frame_coord[2],
+ const float origin[2],
+ const int frame_dimensions[2],
+ float result[2])
+{
+ result[0] = (frame_coord[0] - origin[0]) / frame_dimensions[0];
+ result[1] = (frame_coord[1] - origin[1]) / frame_dimensions[1];
+}
+
+static void dna_marker_to_libmv_marker(/*const*/ MovieTrackingTrack *track,
+ /*const*/ MovieTrackingMarker *marker,
+ int clip,
+ int track_index,
+ int frame_width,
+ int frame_height,
+ bool backwards,
+ libmv_Marker *libmv_marker)
+{
+ const int frame_dimensions[2] = {frame_width, frame_height};
+ int i;
+ libmv_marker->clip = clip;
+ libmv_marker->frame = marker->framenr;
+ libmv_marker->track = track_index;
+
+ normalized_to_libmv_frame(marker->pos,
+ frame_dimensions,
+ libmv_marker->center);
+ for (i = 0; i < 4; ++i) {
+ normalized_relative_to_libmv_frame(marker->pattern_corners[i],
+ marker->pos,
+ frame_dimensions,
+ libmv_marker->patch[i]);
+ }
+
+ normalized_relative_to_libmv_frame(marker->search_min,
+ marker->pos,
+ frame_dimensions,
+ libmv_marker->search_region_min);
+
+ normalized_relative_to_libmv_frame(marker->search_max,
+ marker->pos,
+ frame_dimensions,
+ libmv_marker->search_region_max);
+
+ /* TODO(sergey): All the markers does have 1.0 weight. */
+ libmv_marker->weight = 1.0f;
+
+ if (marker->flag & MARKER_TRACKED) {
+ libmv_marker->source = LIBMV_MARKER_SOURCE_TRACKED;
+ }
+ else {
+ libmv_marker->source = LIBMV_MARKER_SOURCE_MANUAL;
+ }
+ libmv_marker->status = LIBMV_MARKER_STATUS_UNKNOWN;
+ libmv_marker->model_type = LIBMV_MARKER_MODEL_TYPE_POINT;
+ libmv_marker->model_id = 0;
+
+ /* TODO(sergey): We currently don't support reference marker from
+ * different clip.
+ */
+ libmv_marker->reference_clip = clip;
+
+ if (track->pattern_match == TRACK_MATCH_KEYFRAME) {
+ MovieTrackingMarker *keyframe_marker =
+ tracking_get_keyframed_marker(track,
+ marker->framenr,
+ backwards);
+ libmv_marker->reference_frame = keyframe_marker->framenr;
+ }
+ else {
+ libmv_marker->reference_frame = backwards ?
+ marker->framenr - 1 :
+ marker->framenr;
+ }
+
+ libmv_marker->disabled_channels =
+ ((track->flag & TRACK_DISABLE_RED) ? LIBMV_MARKER_CHANNEL_R : 0) |
+ ((track->flag & TRACK_DISABLE_GREEN) ? LIBMV_MARKER_CHANNEL_G : 0) |
+ ((track->flag & TRACK_DISABLE_BLUE) ? LIBMV_MARKER_CHANNEL_B : 0);
+}
+
+static void libmv_marker_to_dna_marker(libmv_Marker *libmv_marker,
+ int frame_width,
+ int frame_height,
+ MovieTrackingMarker *marker)
+{
+ const int frame_dimensions[2] = {frame_width, frame_height};
+ int i;
+ marker->framenr = libmv_marker->frame;
+
+ libmv_frame_to_normalized(libmv_marker->center,
+ frame_dimensions,
+ marker->pos);
+ for (i = 0; i < 4; ++i) {
+ libmv_frame_to_normalized_relative(libmv_marker->patch[i],
+ libmv_marker->center,
+ frame_dimensions,
+ marker->pattern_corners[i]);
+ }
+
+ libmv_frame_to_normalized_relative(libmv_marker->search_region_min,
+ libmv_marker->center,
+ frame_dimensions,
+ marker->search_min);
+
+ libmv_frame_to_normalized_relative(libmv_marker->search_region_max,
+ libmv_marker->center,
+ frame_dimensions,
+ marker->search_max);
+
+ marker->flag = 0;
+ if (libmv_marker->source == LIBMV_MARKER_SOURCE_TRACKED) {
+ marker->flag |= MARKER_TRACKED;
+ }
+ else {
+ marker->flag &= ~MARKER_TRACKED;
+ }
+}
+
+static bool check_track_trackable(MovieClip *clip,
+ MovieTrackingTrack *track,
+ MovieClipUser *user)
+{
+ if (TRACK_SELECTED(track) &&
+ (track->flag & (TRACK_LOCKED | TRACK_HIDDEN)) == 0)
+ {
+ MovieTrackingMarker *marker;
+ int frame;
+ frame = BKE_movieclip_remap_scene_to_clip_frame(clip, user->framenr);
+ marker = BKE_tracking_marker_get(track, frame);
+ return (marker->flag & MARKER_DISABLED) == 0;
+ }
+ return false;
+}
+
+/* Returns false if marker crossed margin area from frame bounds. */
+static bool tracking_check_marker_margin(libmv_Marker *libmv_marker,
+ int margin,
+ int frame_width,
+ int frame_height)
+{
+ float patch_min[2], patch_max[2];
+ float margin_left, margin_top, margin_right, margin_bottom;
+
+ INIT_MINMAX2(patch_min, patch_max);
+ minmax_v2v2_v2(patch_min, patch_max, libmv_marker->patch[0]);
+ minmax_v2v2_v2(patch_min, patch_max, libmv_marker->patch[1]);
+ minmax_v2v2_v2(patch_min, patch_max, libmv_marker->patch[2]);
+ minmax_v2v2_v2(patch_min, patch_max, libmv_marker->patch[3]);
+
+ margin_left = max_ff(libmv_marker->center[0] - patch_min[0], margin);
+ margin_top = max_ff(patch_max[1] - libmv_marker->center[1], margin);
+ margin_right = max_ff(patch_max[0] - libmv_marker->center[0], margin);
+ margin_bottom = max_ff(libmv_marker->center[1] - patch_min[1], margin);
+
+ if (libmv_marker->center[0] < margin_left ||
+ libmv_marker->center[0] > frame_width - margin_right ||
+ libmv_marker->center[1] < margin_bottom ||
+ libmv_marker->center[1] > frame_height - margin_top)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+AutoTrackContext *BKE_autotrack_context_new(MovieClip *clip,
+ MovieClipUser *user,
+ const bool backwards,
+ const bool sequence)
+{
+ AutoTrackContext *context = MEM_callocN(sizeof(AutoTrackContext),
+ "autotrack context");
+ MovieTracking *tracking = &clip->tracking;
+ MovieTrackingTrack *track;
+ ListBase *tracksbase = BKE_tracking_get_active_tracks(tracking);
+ int i, track_index, frame_width, frame_height;
+
+ BKE_movieclip_get_size(clip, user, &frame_width, &frame_height);
+
+ /* TODO(sergey): Currently using only a single clip. */
+ context->clips[0] = clip;
+ context->num_clips = 1;
+
+ context->user = *user;
+ context->user.render_size = MCLIP_PROXY_RENDER_SIZE_FULL;
+ context->user.render_flag = 0;
+ context->frame_width = frame_width;
+ context->frame_height = frame_height;
+ context->backwards = backwards;
+ context->sequence = sequence;
+ context->first_frame = user->framenr;
+ context->sync_frame = user->framenr;
+ context->first_sync = true;
+
+ BLI_spin_init(&context->spin_lock);
+
+ context->image_accessor =
+ tracking_image_accessor_new(context->clips, 1, user->framenr);
+ context->autotrack =
+ libmv_autoTrackNew(context->image_accessor->libmv_accessor);
+
+ /* Fill in Autotrack with all markers we know. */
+ track_index = 0;
+ for (track = tracksbase->first;
+ track;
+ track = track->next)
+ {
+ if (check_track_trackable(clip, track, user)) {
+ context->num_tracks++;
+ }
+
+ for (i = 0; i < track->markersnr; ++i) {
+ MovieTrackingMarker *marker = track->markers + i;
+ if ((marker->flag & MARKER_DISABLED) == 0) {
+ libmv_Marker libmv_marker;
+ dna_marker_to_libmv_marker(track,
+ marker,
+ 0,
+ track_index,
+ frame_width,
+ frame_height,
+ backwards,
+ &libmv_marker);
+ libmv_autoTrackAddMarker(context->autotrack,
+ &libmv_marker);
+ }
+ }
+ track_index++;
+ }
+
+ /* Create per-track tracking options. */
+ context->options =
+ MEM_callocN(sizeof(AutoTrackOptions) * context->num_tracks,
+ "auto track options");
+ i = track_index = 0;
+ for (track = tracksbase->first;
+ track;
+ track = track->next)
+ {
+ if (check_track_trackable(clip, track, user)) {
+ AutoTrackOptions *options = &context->options[i++];
+ /* TODO(sergey): Single clip only for now. */
+ options->clip_index = 0;
+ options->track_index = track_index;
+ options->track = track;
+ tracking_configure_tracker(track,
+ NULL,
+ &options->track_region_options);
+ options->use_keyframe_match =
+ track->pattern_match == TRACK_MATCH_KEYFRAME;
+ }
+ ++track_index;
+ }
+
+ return context;
+}
+
+bool BKE_autotrack_context_step(AutoTrackContext *context)
+{
+ int frame_delta = context->backwards ? -1 : 1;
+ bool ok = false;
+ int track;
+
+#pragma omp parallel for if (context->num_tracks > 1)
+ for (track = 0; track < context->num_tracks; ++track) {
+ AutoTrackOptions *options = &context->options[track];
+ libmv_Marker libmv_current_marker,
+ libmv_reference_marker,
+ libmv_tracked_marker;
+ libmv_TrackRegionResult libmv_result;
+ int frame = BKE_movieclip_remap_scene_to_clip_frame(
+ context->clips[options->clip_index],
+ context->user.framenr);
+ bool has_marker;
+
+ BLI_spin_lock(&context->spin_lock);
+ has_marker = libmv_autoTrackGetMarker(context->autotrack,
+ options->clip_index,
+ frame,
+ options->track_index,
+ &libmv_current_marker);
+ BLI_spin_unlock(&context->spin_lock);
+
+ if (has_marker) {
+ if (!tracking_check_marker_margin(&libmv_current_marker,
+ options->track->margin,
+ context->frame_width,
+ context->frame_height))
+ {
+ continue;
+ }
+
+ libmv_tracked_marker = libmv_current_marker;
+ libmv_tracked_marker.frame = frame + frame_delta;
+
+ if (options->use_keyframe_match) {
+ libmv_tracked_marker.reference_frame =
+ libmv_current_marker.reference_frame;
+ libmv_autoTrackGetMarker(context->autotrack,
+ options->clip_index,
+ libmv_tracked_marker.reference_frame,
+ options->track_index,
+ &libmv_reference_marker);
+ }
+ else {
+ libmv_tracked_marker.reference_frame = frame;
+ libmv_reference_marker = libmv_current_marker;
+ }
+
+ if (libmv_autoTrackMarker(context->autotrack,
+ &options->track_region_options,
+ &libmv_tracked_marker,
+ &libmv_result))
+ {
+ BLI_spin_lock(&context->spin_lock);
+ libmv_autoTrackAddMarker(context->autotrack,
+ &libmv_tracked_marker);
+ BLI_spin_unlock(&context->spin_lock);
+ }
+ else {
+ options->is_failed = true;
+ options->failed_frame = frame + frame_delta;
+ }
+ ok = true;
+ }
+ }
+
+ BLI_spin_lock(&context->spin_lock);
+ context->user.framenr += frame_delta;
+ BLI_spin_unlock(&context->spin_lock);
+
+ return ok;
+}
+
+void BKE_autotrack_context_sync(AutoTrackContext *context)
+{
+ int newframe, frame_delta = context->backwards ? -1 : 1;
+ int clip, frame;
+
+ BLI_spin_lock(&context->spin_lock);
+ newframe = context->user.framenr;
+ for (frame = context->sync_frame;
+ frame != (context->backwards ? newframe - 1 : newframe + 1);
+ frame += frame_delta)
+ {
+ MovieTrackingMarker marker;
+ libmv_Marker libmv_marker;
+ int clip = 0;
+ int track;
+ for (track = 0; track < context->num_tracks; ++track) {
+ AutoTrackOptions *options = &context->options[track];
+ int track_frame = BKE_movieclip_remap_scene_to_clip_frame(
+ context->clips[options->clip_index], frame);
+ if (options->is_failed && options->failed_frame == track_frame) {
+ MovieTrackingMarker *prev_marker =
+ BKE_tracking_marker_get_exact(options->track, frame);
+ if (prev_marker) {
+ marker = *prev_marker;
+ marker.framenr = context->backwards ?
+ track_frame - 1 :
+ track_frame + 1;
+ marker.flag |= MARKER_DISABLED;
+ BKE_tracking_marker_insert(options->track, &marker);
+ continue;
+ }
+ }
+ if (libmv_autoTrackGetMarker(context->autotrack,
+ clip,
+ track_frame,
+ options->track_index,
+ &libmv_marker))
+ {
+ libmv_marker_to_dna_marker(&libmv_marker,
+ context->frame_width,
+ context->frame_height,
+ &marker);
+ if (context->first_sync && frame == context->sync_frame) {
+ tracking_marker_insert_disabled(options->track,
+ &marker,
+ !context->backwards,
+ false);
+ }
+ BKE_tracking_marker_insert(options->track, &marker);
+ tracking_marker_insert_disabled(options->track,
+ &marker,
+ context->backwards,
+ false);
+ }
+ }
+ }
+ BLI_spin_unlock(&context->spin_lock);
+
+ for (clip = 0; clip < context->num_clips; ++clip) {
+ MovieTracking *tracking = &context->clips[clip]->tracking;
+ BKE_tracking_dopesheet_tag_update(tracking);
+ }
+
+ context->sync_frame = newframe;
+ context->first_sync = false;
+}
+
+void BKE_autotrack_context_sync_user(AutoTrackContext *context,
+ MovieClipUser *user)
+{
+ user->framenr = context->sync_frame;
+}
+
+void BKE_autotrack_context_finish(AutoTrackContext *context)
+{
+ int clip_index;
+
+ for (clip_index = 0; clip_index < context->num_clips; ++clip_index) {
+ MovieClip *clip = context->clips[clip_index];
+ ListBase *plane_tracks_base =
+ BKE_tracking_get_active_plane_tracks(&clip->tracking);
+ MovieTrackingPlaneTrack *plane_track;
+
+ for (plane_track = plane_tracks_base->first;
+ plane_track;
+ plane_track = plane_track->next)
+ {
+ if ((plane_track->flag & PLANE_TRACK_AUTOKEY) == 0) {
+ int track;
+ for (track = 0; track < context->num_tracks; ++track) {
+ if (BKE_tracking_plane_track_has_point_track(plane_track,
+ context->options[track].track))
+ {
+ BKE_tracking_track_plane_from_existing_motion(
+ plane_track,
+ context->first_frame);
+ break;
+ }
+ }
+ }
+ }
+ }
+}
+
+void BKE_autotrack_context_free(AutoTrackContext *context)
+{
+ libmv_autoTrackDestroy(context->autotrack);
+ tracking_image_accessor_destroy(context->image_accessor);
+ MEM_freeN(context->options);
+ BLI_spin_end(&context->spin_lock);
+ MEM_freeN(context);
+}
diff --git a/source/blender/blenkernel/intern/tracking_detect.c b/source/blender/blenkernel/intern/tracking_detect.c
index 62039b761e8..6df51b5441a 100644
--- a/source/blender/blenkernel/intern/tracking_detect.c
+++ b/source/blender/blenkernel/intern/tracking_detect.c
@@ -40,7 +40,6 @@
#include "BKE_tracking.h"
#include "IMB_imbuf_types.h"
-#include "IMB_imbuf.h"
#include "libmv-capi.h"
diff --git a/source/blender/blenkernel/intern/tracking_region_tracker.c b/source/blender/blenkernel/intern/tracking_region_tracker.c
index c41106f37cb..dd7def16ca8 100644
--- a/source/blender/blenkernel/intern/tracking_region_tracker.c
+++ b/source/blender/blenkernel/intern/tracking_region_tracker.c
@@ -35,11 +35,8 @@
#include "MEM_guardedalloc.h"
#include "DNA_movieclip_types.h"
-#include "DNA_object_types.h" /* SELECT */
#include "BLI_utildefines.h"
-#include "BLI_math.h"
-#include "BLI_ghash.h"
#include "BLI_threads.h"
#include "BKE_tracking.h"
@@ -51,170 +48,6 @@
#include "libmv-capi.h"
#include "tracking_private.h"
-typedef struct TrackContext {
- /* the reference marker and cutout search area */
- MovieTrackingMarker reference_marker;
-
- /* keyframed patch. This is the search area */
- float *search_area;
- int search_area_height;
- int search_area_width;
- int framenr;
-
- float *mask;
-} TrackContext;
-
-typedef struct MovieTrackingContext {
- MovieClipUser user;
- MovieClip *clip;
- int clip_flag;
-
- int frames, first_frame;
- bool first_time;
-
- MovieTrackingSettings settings;
- TracksMap *tracks_map;
-
- bool backwards, sequence;
- int sync_frame;
-} MovieTrackingContext;
-
-static void track_context_free(void *customdata)
-{
- TrackContext *track_context = (TrackContext *)customdata;
-
- if (track_context->search_area)
- MEM_freeN(track_context->search_area);
-
- if (track_context->mask)
- MEM_freeN(track_context->mask);
-}
-
-/* Create context for motion 2D tracking, copies all data needed
- * for thread-safe tracking, allowing clip modifications during
- * tracking.
- */
-MovieTrackingContext *BKE_tracking_context_new(MovieClip *clip, MovieClipUser *user,
- const bool backwards, const bool sequence)
-{
- MovieTrackingContext *context = MEM_callocN(sizeof(MovieTrackingContext), "trackingContext");
- MovieTracking *tracking = &clip->tracking;
- MovieTrackingSettings *settings = &tracking->settings;
- ListBase *tracksbase = BKE_tracking_get_active_tracks(tracking);
- MovieTrackingTrack *track;
- MovieTrackingObject *object = BKE_tracking_object_get_active(tracking);
- int num_tracks = 0;
-
- context->clip = clip;
- context->settings = *settings;
- context->backwards = backwards;
- context->sync_frame = user->framenr;
- context->first_time = true;
- context->first_frame = user->framenr;
- context->sequence = sequence;
-
- /* count */
- track = tracksbase->first;
- while (track) {
- if (TRACK_SELECTED(track) && (track->flag & (TRACK_LOCKED | TRACK_HIDDEN)) == 0) {
- int framenr = BKE_movieclip_remap_scene_to_clip_frame(clip, user->framenr);
- MovieTrackingMarker *marker = BKE_tracking_marker_get(track, framenr);
-
- if ((marker->flag & MARKER_DISABLED) == 0)
- num_tracks++;
- }
-
- track = track->next;
- }
-
- /* create tracking contextx for all tracks which would be tracked */
- if (num_tracks) {
- int width, height;
-
- context->tracks_map = tracks_map_new(object->name, object->flag & TRACKING_OBJECT_CAMERA,
- num_tracks, sizeof(TrackContext));
-
- BKE_movieclip_get_size(clip, user, &width, &height);
-
- /* create tracking data */
- track = tracksbase->first;
- while (track) {
- if (TRACK_SELECTED(track) && (track->flag & (TRACK_HIDDEN | TRACK_LOCKED)) == 0) {
- int framenr = BKE_movieclip_remap_scene_to_clip_frame(clip, user->framenr);
- MovieTrackingMarker *marker = BKE_tracking_marker_get(track, framenr);
-
- if ((marker->flag & MARKER_DISABLED) == 0) {
- TrackContext track_context;
- memset(&track_context, 0, sizeof(TrackContext));
- tracks_map_insert(context->tracks_map, track, &track_context);
- }
- }
-
- track = track->next;
- }
- }
-
- /* store needed clip flags passing to get_buffer functions
- * - MCLIP_USE_PROXY is needed to because timecode affects on movie clip
- * only in case Proxy/Timecode flag is set, so store this flag to use
- * timecodes properly but reset render size to SIZE_FULL so correct resolution
- * would be used for images
- * - MCLIP_USE_PROXY_CUSTOM_DIR is needed because proxy/timecode files might
- * be stored in a different location
- * ignore all the rest possible flags for now
- */
- context->clip_flag = clip->flag & MCLIP_TIMECODE_FLAGS;
-
- context->user = *user;
- context->user.render_size = MCLIP_PROXY_RENDER_SIZE_FULL;
- context->user.render_flag = 0;
-
- if (!sequence)
- BLI_begin_threaded_malloc();
-
- return context;
-}
-
-/* Free context used for tracking. */
-void BKE_tracking_context_free(MovieTrackingContext *context)
-{
- if (!context->sequence)
- BLI_end_threaded_malloc();
-
- tracks_map_free(context->tracks_map, track_context_free);
-
- MEM_freeN(context);
-}
-
-/* Synchronize tracks between clip editor and tracking context,
- * by merging them together so all new created tracks and tracked
- * ones presents in the movie clip.
- */
-void BKE_tracking_context_sync(MovieTrackingContext *context)
-{
- MovieTracking *tracking = &context->clip->tracking;
- int newframe;
-
- tracks_map_merge(context->tracks_map, tracking);
-
- if (context->backwards)
- newframe = context->user.framenr + 1;
- else
- newframe = context->user.framenr - 1;
-
- context->sync_frame = newframe;
-
- BKE_tracking_dopesheet_tag_update(tracking);
-}
-
-/* Synchronize clip user's frame number with a frame number from tracking context,
- * used to update current frame displayed in the clip editor while tracking.
- */
-void BKE_tracking_context_sync_user(const MovieTrackingContext *context, MovieClipUser *user)
-{
- user->framenr = context->sync_frame;
-}
-
/* **** utility functions for tracking **** */
/* convert from float and byte RGBA to grayscale. Supports different coefficients for RGB. */
@@ -280,7 +113,7 @@ static float *track_get_search_floatbuf(ImBuf *ibuf, MovieTrackingTrack *track,
return gray_pixels;
}
-/* Get image boffer for a given frame
+/* Get image buffer for a given frame
*
* Frame is in clip space.
*/
@@ -296,51 +129,6 @@ static ImBuf *tracking_context_get_frame_ibuf(MovieClip *clip, MovieClipUser *us
return ibuf;
}
-/* Get previous keyframed marker. */
-static MovieTrackingMarker *tracking_context_get_keyframed_marker(MovieTrackingTrack *track,
- int curfra, bool backwards)
-{
- MovieTrackingMarker *marker_keyed = NULL;
- MovieTrackingMarker *marker_keyed_fallback = NULL;
- int a = BKE_tracking_marker_get(track, curfra) - track->markers;
-
- while (a >= 0 && a < track->markersnr) {
- int next = backwards ? a + 1 : a - 1;
- bool is_keyframed = false;
- MovieTrackingMarker *cur_marker = &track->markers[a];
- MovieTrackingMarker *next_marker = NULL;
-
- if (next >= 0 && next < track->markersnr)
- next_marker = &track->markers[next];
-
- if ((cur_marker->flag & MARKER_DISABLED) == 0) {
- /* If it'll happen so we didn't find a real keyframe marker,
- * fallback to the first marker in current tracked segment
- * as a keyframe.
- */
- if (next_marker && next_marker->flag & MARKER_DISABLED) {
- if (marker_keyed_fallback == NULL)
- marker_keyed_fallback = cur_marker;
- }
-
- is_keyframed |= (cur_marker->flag & MARKER_TRACKED) == 0;
- }
-
- if (is_keyframed) {
- marker_keyed = cur_marker;
-
- break;
- }
-
- a = next;
- }
-
- if (marker_keyed == NULL)
- marker_keyed = marker_keyed_fallback;
-
- return marker_keyed;
-}
-
/* Get image buffer for previous marker's keyframe. */
static ImBuf *tracking_context_get_keyframed_ibuf(MovieClip *clip, MovieClipUser *user, int clip_flag,
MovieTrackingTrack *track, int curfra, bool backwards,
@@ -349,7 +137,7 @@ static ImBuf *tracking_context_get_keyframed_ibuf(MovieClip *clip, MovieClipUser
MovieTrackingMarker *marker_keyed;
int keyed_framenr;
- marker_keyed = tracking_context_get_keyframed_marker(track, curfra, backwards);
+ marker_keyed = tracking_get_keyframed_marker(track, curfra, backwards);
if (marker_keyed == NULL) {
return NULL;
}
@@ -381,50 +169,9 @@ static ImBuf *tracking_context_get_reference_ibuf(MovieClip *clip, MovieClipUser
return ibuf;
}
-/* Update track's reference patch (patch from which track is tracking from)
- *
- * Returns false if reference image buffer failed to load.
- */
-static bool track_context_update_reference(MovieTrackingContext *context, TrackContext *track_context,
- MovieTrackingTrack *track, MovieTrackingMarker *marker, int curfra,
- int frame_width, int frame_height)
-{
- MovieTrackingMarker *reference_marker = NULL;
- ImBuf *reference_ibuf = NULL;
- int width, height;
-
- /* calculate patch for keyframed position */
- reference_ibuf = tracking_context_get_reference_ibuf(context->clip, &context->user, context->clip_flag,
- track, curfra, context->backwards, &reference_marker);
-
- if (!reference_ibuf)
- return false;
-
- track_context->reference_marker = *reference_marker;
-
- if (track_context->search_area) {
- MEM_freeN(track_context->search_area);
- }
-
- track_context->search_area = track_get_search_floatbuf(reference_ibuf, track, reference_marker, &width, &height);
- track_context->search_area_height = height;
- track_context->search_area_width = width;
-
- if ((track->algorithm_flag & TRACK_ALGORITHM_FLAG_USE_MASK) != 0) {
- if (track_context->mask)
- MEM_freeN(track_context->mask);
-
- track_context->mask = BKE_tracking_track_get_mask(frame_width, frame_height, track, marker);
- }
-
- IMB_freeImBuf(reference_ibuf);
-
- return true;
-}
-
/* Fill in libmv tracker options structure with settings need to be used to perform track. */
-static void tracking_configure_tracker(const MovieTrackingTrack *track, float *mask,
- libmv_TrackRegionOptions *options)
+void tracking_configure_tracker(const MovieTrackingTrack *track, float *mask,
+ libmv_TrackRegionOptions *options)
{
options->motion_model = track->motion_model;
@@ -442,102 +189,6 @@ static void tracking_configure_tracker(const MovieTrackingTrack *track, float *m
options->image1_mask = NULL;
}
-/* returns false if marker crossed margin area from frame bounds */
-static bool tracking_check_marker_margin(MovieTrackingTrack *track, MovieTrackingMarker *marker,
- int frame_width, int frame_height)
-{
- float pat_min[2], pat_max[2];
- float margin_left, margin_top, margin_right, margin_bottom;
- float normalized_track_margin[2];
-
- /* margin from frame boundaries */
- BKE_tracking_marker_pattern_minmax(marker, pat_min, pat_max);
-
- normalized_track_margin[0] = (float)track->margin / frame_width;
- normalized_track_margin[1] = (float)track->margin / frame_height;
-
- margin_left = max_ff(-pat_min[0], normalized_track_margin[0]);
- margin_top = max_ff( pat_max[1], normalized_track_margin[1]);
- margin_right = max_ff( pat_max[0], normalized_track_margin[0]);
- margin_bottom = max_ff(-pat_min[1], normalized_track_margin[1]);
-
- /* do not track markers which are too close to boundary */
- if (marker->pos[0] < margin_left || marker->pos[0] > 1.0f - margin_right ||
- marker->pos[1] < margin_bottom || marker->pos[1] > 1.0f - margin_top)
- {
- return false;
- }
-
- return true;
-}
-
-/* Scale search area of marker based on scale changes of pattern area,
- *
- * TODO(sergey): currently based on pattern bounding box scale change,
- * smarter approach here is welcome.
- */
-static void tracking_scale_marker_search(const MovieTrackingMarker *old_marker, MovieTrackingMarker *new_marker)
-{
- float old_pat_min[2], old_pat_max[2];
- float new_pat_min[2], new_pat_max[2];
- float scale_x, scale_y;
-
- BKE_tracking_marker_pattern_minmax(old_marker, old_pat_min, old_pat_max);
- BKE_tracking_marker_pattern_minmax(new_marker, new_pat_min, new_pat_max);
-
- scale_x = (new_pat_max[0] - new_pat_min[0]) / (old_pat_max[0] - old_pat_min[0]);
- scale_y = (new_pat_max[1] - new_pat_min[1]) / (old_pat_max[1] - old_pat_min[1]);
-
- new_marker->search_min[0] *= scale_x;
- new_marker->search_min[1] *= scale_y;
-
- new_marker->search_max[0] *= scale_x;
- new_marker->search_max[1] *= scale_y;
-}
-
-/* Insert new marker which was tracked from old_marker to a new image,
- * will also ensure tracked segment is surrounded by disabled markers.
- */
-static void tracking_insert_new_marker(MovieTrackingContext *context, MovieTrackingTrack *track,
- const MovieTrackingMarker *old_marker, int curfra, bool tracked,
- int frame_width, int frame_height,
- const double dst_pixel_x[5], const double dst_pixel_y[5])
-{
- MovieTrackingMarker new_marker;
- int frame_delta = context->backwards ? -1 : 1;
- int nextfra = curfra + frame_delta;
-
- new_marker = *old_marker;
-
- if (tracked) {
- tracking_set_marker_coords_from_tracking(frame_width, frame_height, &new_marker, dst_pixel_x, dst_pixel_y);
- new_marker.flag |= MARKER_TRACKED;
- new_marker.framenr = nextfra;
-
- tracking_scale_marker_search(old_marker, &new_marker);
-
- if (context->first_time) {
- /* check if there's no keyframe/tracked markers before tracking marker.
- * if so -- create disabled marker before currently tracking "segment"
- */
-
- tracking_marker_insert_disabled(track, old_marker, !context->backwards, false);
- }
-
- /* insert currently tracked marker */
- BKE_tracking_marker_insert(track, &new_marker);
-
- /* make currently tracked segment be finished with disabled marker */
- tracking_marker_insert_disabled(track, &new_marker, context->backwards, false);
- }
- else {
- new_marker.framenr = nextfra;
- new_marker.flag |= MARKER_DISABLED;
-
- BKE_tracking_marker_insert(track, &new_marker);
- }
-}
-
/* Peform tracking from a reference_marker to destination_ibuf.
* Uses marker as an initial position guess.
*
@@ -601,130 +252,6 @@ static bool configure_and_run_tracker(ImBuf *destination_ibuf, MovieTrackingTrac
return tracked;
}
-/* Track all the tracks from context one more frame,
- * returns FALSe if nothing was tracked.
- */
-bool BKE_tracking_context_step(MovieTrackingContext *context)
-{
- ImBuf *destination_ibuf;
- int frame_delta = context->backwards ? -1 : 1;
- int curfra = BKE_movieclip_remap_scene_to_clip_frame(context->clip, context->user.framenr);
- int a, map_size;
- bool ok = false;
-
- int frame_width, frame_height;
-
- map_size = tracks_map_get_size(context->tracks_map);
-
- /* Nothing to track, avoid unneeded frames reading to save time and memory. */
- if (!map_size)
- return false;
-
- /* Get an image buffer for frame we're tracking to. */
- context->user.framenr += frame_delta;
-
- destination_ibuf = BKE_movieclip_get_ibuf_flag(context->clip, &context->user,
- context->clip_flag, MOVIECLIP_CACHE_SKIP);
- if (!destination_ibuf)
- return false;
-
- frame_width = destination_ibuf->x;
- frame_height = destination_ibuf->y;
-
-#pragma omp parallel for private(a) shared(destination_ibuf, ok) if (map_size > 1)
- for (a = 0; a < map_size; a++) {
- TrackContext *track_context = NULL;
- MovieTrackingTrack *track;
- MovieTrackingMarker *marker;
-
- tracks_map_get_indexed_element(context->tracks_map, a, &track, (void **)&track_context);
-
- marker = BKE_tracking_marker_get_exact(track, curfra);
-
- if (marker && (marker->flag & MARKER_DISABLED) == 0) {
- bool tracked = false, need_readjust;
- double dst_pixel_x[5], dst_pixel_y[5];
-
- if (track->pattern_match == TRACK_MATCH_KEYFRAME)
- need_readjust = context->first_time;
- else
- need_readjust = true;
-
- /* do not track markers which are too close to boundary */
- if (tracking_check_marker_margin(track, marker, frame_width, frame_height)) {
- if (need_readjust) {
- if (track_context_update_reference(context, track_context, track, marker,
- curfra, frame_width, frame_height) == false)
- {
- /* happens when reference frame fails to be loaded */
- continue;
- }
- }
-
- tracked = configure_and_run_tracker(destination_ibuf, track,
- &track_context->reference_marker, marker,
- track_context->search_area,
- track_context->search_area_width,
- track_context->search_area_height,
- track_context->mask,
- dst_pixel_x, dst_pixel_y);
- }
-
- BLI_spin_lock(&context->tracks_map->spin_lock);
- tracking_insert_new_marker(context, track, marker, curfra, tracked,
- frame_width, frame_height, dst_pixel_x, dst_pixel_y);
- BLI_spin_unlock(&context->tracks_map->spin_lock);
-
- ok = true;
- }
- }
-
- IMB_freeImBuf(destination_ibuf);
-
- context->first_time = false;
- context->frames++;
-
- return ok;
-}
-
-void BKE_tracking_context_finish(MovieTrackingContext *context)
-{
- MovieClip *clip = context->clip;
- ListBase *plane_tracks_base = BKE_tracking_get_active_plane_tracks(&clip->tracking);
- MovieTrackingPlaneTrack *plane_track;
- int map_size = tracks_map_get_size(context->tracks_map);
-
- for (plane_track = plane_tracks_base->first;
- plane_track;
- plane_track = plane_track->next)
- {
- if ((plane_track->flag & PLANE_TRACK_AUTOKEY) == 0) {
- int i;
- for (i = 0; i < map_size; i++) {
- TrackContext *track_context = NULL;
- MovieTrackingTrack *track, *old_track;
- bool do_update = false;
- int j;
-
- tracks_map_get_indexed_element(context->tracks_map, i, &track, (void **)&track_context);
-
- old_track = BLI_ghash_lookup(context->tracks_map->hash, track);
- for (j = 0; j < plane_track->point_tracksnr; j++) {
- if (plane_track->point_tracks[j] == old_track) {
- do_update = true;
- break;
- }
- }
-
- if (do_update) {
- BKE_tracking_track_plane_from_existing_motion(plane_track, context->first_frame);
- break;
- }
- }
- }
- }
-}
-
static bool refine_marker_reference_frame_get(MovieTrackingTrack *track,
MovieTrackingMarker *marker,
bool backwards,
diff --git a/source/blender/blenkernel/intern/tracking_solver.c b/source/blender/blenkernel/intern/tracking_solver.c
index 056220e27d8..c21883c6eb8 100644
--- a/source/blender/blenkernel/intern/tracking_solver.c
+++ b/source/blender/blenkernel/intern/tracking_solver.c
@@ -43,7 +43,7 @@
#include "BLI_listbase.h"
#include "BLI_string.h"
-#include "BLF_translation.h"
+#include "BLT_translation.h"
#include "BKE_fcurve.h"
#include "BKE_tracking.h"
@@ -356,7 +356,7 @@ MovieReconstructContext *BKE_tracking_reconstruction_context_new(MovieClip *clip
MovieReconstructContext *context = MEM_callocN(sizeof(MovieReconstructContext), "MovieReconstructContext data");
ListBase *tracksbase = BKE_tracking_object_get_tracks(tracking, object);
float aspy = 1.0f / tracking->camera.pixel_aspect;
- int num_tracks = BLI_countlist(tracksbase);
+ int num_tracks = BLI_listbase_count(tracksbase);
int sfra = INT_MAX, efra = INT_MIN;
MovieTrackingTrack *track;
@@ -368,8 +368,8 @@ MovieReconstructContext *BKE_tracking_reconstruction_context_new(MovieClip *clip
(tracking->settings.reconstruction_flag & TRACKING_USE_KEYFRAME_SELECTION) != 0;
tracking_cameraIntrinscisOptionsFromTracking(tracking,
- width, height,
- &context->camera_intrinsics_options);
+ width, height,
+ &context->camera_intrinsics_options);
context->tracks_map = tracks_map_new(context->object_name, context->is_camera, num_tracks, 0);
@@ -391,7 +391,7 @@ MovieReconstructContext *BKE_tracking_reconstruction_context_new(MovieClip *clip
last_marker--;
}
- if (first < track->markersnr - 1)
+ if (first <= track->markersnr - 1)
sfra = min_ii(sfra, first_marker->framenr);
if (last >= 0)
@@ -509,6 +509,11 @@ bool BKE_tracking_reconstruction_finish(MovieReconstructContext *context, MovieT
MovieTrackingReconstruction *reconstruction;
MovieTrackingObject *object;
+ if (!libmv_reconstructionIsValid(context->reconstruction)) {
+ printf("Failed solve the motion: most likely there are no good keyframes\n");
+ return false;
+ }
+
tracks_map_merge(context->tracks_map, tracking);
BKE_tracking_dopesheet_tag_update(tracking);
diff --git a/source/blender/blenkernel/intern/tracking_util.c b/source/blender/blenkernel/intern/tracking_util.c
index 0a8293630c7..1cbfc5eb834 100644
--- a/source/blender/blenkernel/intern/tracking_util.c
+++ b/source/blender/blenkernel/intern/tracking_util.c
@@ -45,10 +45,15 @@
#include "BLI_path_util.h"
#include "BLI_string.h"
-#include "BLF_translation.h"
+#include "BLT_translation.h"
+#include "BKE_movieclip.h"
#include "BKE_tracking.h"
+#include "IMB_imbuf_types.h"
+#include "IMB_imbuf.h"
+#include "IMB_moviecache.h"
+
#include "tracking_private.h"
#include "libmv-capi.h"
@@ -167,8 +172,7 @@ void tracks_map_merge(TracksMap *map, MovieTracking *tracking)
MovieTrackingTrack *new_track = BKE_tracking_track_duplicate(track);
/* Update old-new track mapping */
- BLI_ghash_remove(map->hash, track, NULL, NULL);
- BLI_ghash_insert(map->hash, track, new_track);
+ BLI_ghash_reinsert(map->hash, track, new_track, NULL, NULL);
BLI_addtail(&tracks, new_track);
}
@@ -192,7 +196,7 @@ void tracks_map_merge(TracksMap *map, MovieTracking *tracking)
track->next = track->prev = NULL;
BLI_addtail(&new_tracks, track);
- BLI_uniquename(&new_tracks, track, CTX_DATA_(BLF_I18NCONTEXT_ID_MOVIECLIP, "Track"), '.',
+ BLI_uniquename(&new_tracks, track, CTX_DATA_(BLT_I18NCONTEXT_ID_MOVIECLIP, "Track"), '.',
offsetof(MovieTrackingTrack, name), sizeof(track->name));
track = next;
@@ -390,8 +394,7 @@ void tracking_marker_insert_disabled(MovieTrackingTrack *track, const MovieTrack
}
-/* Fill in Libmv C-API camera intrinsics options from tracking structure.
- */
+/* Fill in Libmv C-API camera intrinsics options from tracking structure. */
void tracking_cameraIntrinscisOptionsFromTracking(MovieTracking *tracking,
int calibration_width, int calibration_height,
libmv_CameraIntrinsicsOptions *camera_intrinsics_options)
@@ -420,6 +423,7 @@ void tracking_cameraIntrinscisOptionsFromTracking(MovieTracking *tracking,
break;
default:
BLI_assert(!"Unknown distortion model");
+ break;
}
camera_intrinsics_options->image_width = calibration_width;
@@ -451,5 +455,444 @@ void tracking_trackingCameraFromIntrinscisOptions(MovieTracking *tracking,
break;
default:
BLI_assert(!"Unknown distortion model");
+ break;
+ }
+}
+
+/* Get previous keyframed marker. */
+MovieTrackingMarker *tracking_get_keyframed_marker(MovieTrackingTrack *track,
+ int current_frame,
+ bool backwards)
+{
+ MovieTrackingMarker *marker_keyed = NULL;
+ MovieTrackingMarker *marker_keyed_fallback = NULL;
+ int a = BKE_tracking_marker_get(track, current_frame) - track->markers;
+
+ while (a >= 0 && a < track->markersnr) {
+ int next = backwards ? a + 1 : a - 1;
+ bool is_keyframed = false;
+ MovieTrackingMarker *cur_marker = &track->markers[a];
+ MovieTrackingMarker *next_marker = NULL;
+
+ if (next >= 0 && next < track->markersnr)
+ next_marker = &track->markers[next];
+
+ if ((cur_marker->flag & MARKER_DISABLED) == 0) {
+ /* If it'll happen so we didn't find a real keyframe marker,
+ * fallback to the first marker in current tracked segment
+ * as a keyframe.
+ */
+ if (next_marker && next_marker->flag & MARKER_DISABLED) {
+ if (marker_keyed_fallback == NULL)
+ marker_keyed_fallback = cur_marker;
+ }
+
+ is_keyframed |= (cur_marker->flag & MARKER_TRACKED) == 0;
+ }
+
+ if (is_keyframed) {
+ marker_keyed = cur_marker;
+
+ break;
+ }
+
+ a = next;
+ }
+
+ if (marker_keyed == NULL)
+ marker_keyed = marker_keyed_fallback;
+
+ return marker_keyed;
+}
+
+/*********************** Frame accessr *************************/
+
+typedef struct AccessCacheKey {
+ int clip_index;
+ int frame;
+ int downscale;
+ libmv_InputMode input_mode;
+ int64_t transform_key;
+} AccessCacheKey;
+
+static unsigned int accesscache_hashhash(const void *key_v)
+{
+ const AccessCacheKey *key = (const AccessCacheKey *) key_v;
+ /* TODP(sergey): Need better hasing here for faster frame access. */
+ return key->clip_index << 16 | key->frame;
+}
+
+static bool accesscache_hashcmp(const void *a_v, const void *b_v)
+{
+ const AccessCacheKey *a = (const AccessCacheKey *) a_v;
+ const AccessCacheKey *b = (const AccessCacheKey *) b_v;
+
+#define COMPARE_FIELD(field)
+ { \
+ if (a->clip_index != b->clip_index) { \
+ return false; \
+ } \
+ } (void) 0
+
+ COMPARE_FIELD(clip_index);
+ COMPARE_FIELD(frame);
+ COMPARE_FIELD(downscale);
+ COMPARE_FIELD(input_mode);
+ COMPARE_FIELD(transform_key);
+
+#undef COMPARE_FIELD
+
+ return true;
+}
+
+static void accesscache_put(TrackingImageAccessor *accessor,
+ int clip_index,
+ int frame,
+ libmv_InputMode input_mode,
+ int downscale,
+ int64_t transform_key,
+ ImBuf *ibuf)
+{
+ AccessCacheKey key;
+ key.clip_index = clip_index;
+ key.frame = frame;
+ key.input_mode = input_mode;
+ key.downscale = downscale;
+ key.transform_key = transform_key;
+ IMB_moviecache_put(accessor->cache, &key, ibuf);
+}
+
+static ImBuf *accesscache_get(TrackingImageAccessor *accessor,
+ int clip_index,
+ int frame,
+ libmv_InputMode input_mode,
+ int downscale,
+ int64_t transform_key)
+{
+ AccessCacheKey key;
+ key.clip_index = clip_index;
+ key.frame = frame;
+ key.input_mode = input_mode;
+ key.downscale = downscale;
+ key.transform_key = transform_key;
+ return IMB_moviecache_get(accessor->cache, &key);
+}
+
+static ImBuf *accessor_get_preprocessed_ibuf(TrackingImageAccessor *accessor,
+ int clip_index,
+ int frame)
+{
+ MovieClip *clip;
+ MovieClipUser user;
+ ImBuf *ibuf;
+ int scene_frame;
+
+ BLI_assert(clip_index < accessor->num_clips);
+
+ clip = accessor->clips[clip_index];
+ scene_frame = BKE_movieclip_remap_clip_to_scene_frame(clip, frame);
+ BKE_movieclip_user_set_frame(&user, scene_frame);
+ user.render_size = MCLIP_PROXY_RENDER_SIZE_FULL;
+ user.render_flag = 0;
+ ibuf = BKE_movieclip_get_ibuf(clip, &user);
+
+ return ibuf;
+}
+
+static ImBuf *make_grayscale_ibuf_copy(ImBuf *ibuf)
+{
+ ImBuf *grayscale = IMB_allocImBuf(ibuf->x, ibuf->y, 32, 0);
+ size_t size;
+ int i;
+
+ BLI_assert(ibuf->channels == 3 || ibuf->channels == 4);
+
+ /* TODO(sergey): Bummer, currently IMB API only allows to create 4 channels
+ * float buffer, so we do it manually here.
+ *
+ * Will generalize it later.
+ */
+ size = (size_t)grayscale->x * (size_t)grayscale->y * sizeof(float);
+ grayscale->channels = 1;
+ if ((grayscale->rect_float = MEM_mapallocN(size, "tracking grayscale image"))) {
+ grayscale->mall |= IB_rectfloat;
+ grayscale->flags |= IB_rectfloat;
+ }
+
+ for (i = 0; i < grayscale->x * grayscale->y; ++i) {
+ const float *pixel = ibuf->rect_float + ibuf->channels * i;
+
+ grayscale->rect_float[i] = 0.2126f * pixel[0] +
+ 0.7152f * pixel[1] +
+ 0.0722f * pixel[2];
+ }
+
+ return grayscale;
+}
+
+static void ibuf_to_float_image(const ImBuf *ibuf, libmv_FloatImage *float_image)
+{
+ BLI_assert(ibuf->rect_float != NULL);
+ float_image->buffer = ibuf->rect_float;
+ float_image->width = ibuf->x;
+ float_image->height = ibuf->y;
+ float_image->channels = ibuf->channels;
+}
+
+static ImBuf *float_image_to_ibuf(libmv_FloatImage *float_image)
+{
+ ImBuf *ibuf = IMB_allocImBuf(float_image->width, float_image->height, 32, 0);
+ size_t size = (size_t)ibuf->x * (size_t)ibuf->y *
+ float_image->channels * sizeof(float);
+ ibuf->channels = float_image->channels;
+ if ((ibuf->rect_float = MEM_mapallocN(size, "tracking grayscale image"))) {
+ ibuf->mall |= IB_rectfloat;
+ ibuf->flags |= IB_rectfloat;
+ }
+ memcpy(ibuf->rect_float, float_image->buffer, size);
+ return ibuf;
+}
+
+static ImBuf *accessor_get_ibuf(TrackingImageAccessor *accessor,
+ int clip_index,
+ int frame,
+ libmv_InputMode input_mode,
+ int downscale,
+ const libmv_Region *region,
+ const libmv_FrameTransform *transform)
+{
+ ImBuf *ibuf, *orig_ibuf, *final_ibuf;
+ int64_t transform_key = 0;
+
+ if (transform != NULL) {
+ transform_key = libmv_frameAccessorgetTransformKey(transform);
+ }
+
+ /* First try to get fully processed image from the cache. */
+ ibuf = accesscache_get(accessor,
+ clip_index,
+ frame,
+ input_mode,
+ downscale,
+ transform_key);
+ if (ibuf != NULL) {
+ return ibuf;
+ }
+
+ /* And now we do postprocessing of the original frame. */
+ orig_ibuf = accessor_get_preprocessed_ibuf(accessor, clip_index, frame);
+
+ if (orig_ibuf == NULL) {
+ return NULL;
+ }
+
+ if (region != NULL) {
+ int width = region->max[0] - region->min[0],
+ height = region->max[1] - region->min[1];
+
+ /* If the requested region goes outside of the actual frame we still
+ * return the requested region size, but only fill it's partially with
+ * the data we can.
+ */
+ int clamped_origin_x = max_ii((int)region->min[0], 0),
+ clamped_origin_y = max_ii((int)region->min[1], 0);
+ int dst_offset_x = clamped_origin_x - (int)region->min[0],
+ dst_offset_y = clamped_origin_y - (int)region->min[1];
+ int clamped_width = width - dst_offset_x,
+ clamped_height = height - dst_offset_y;
+ clamped_width = min_ii(clamped_width, orig_ibuf->x - clamped_origin_x);
+ clamped_height = min_ii(clamped_height, orig_ibuf->y - clamped_origin_y);
+
+ final_ibuf = IMB_allocImBuf(width, height, 32, IB_rectfloat);
+
+ if (orig_ibuf->rect_float != NULL) {
+ IMB_rectcpy(final_ibuf, orig_ibuf,
+ dst_offset_x, dst_offset_y,
+ clamped_origin_x, clamped_origin_y,
+ clamped_width, clamped_height);
+ }
+ else {
+ int y;
+ /* TODO(sergey): We don't do any color space or alpha conversion
+ * here. Probably Libmv is better to work in the linear space,
+ * but keep sRGB space here for compatibility for now.
+ */
+ for (y = 0; y < clamped_height; ++y) {
+ int x;
+ for (x = 0; x < clamped_width; ++x) {
+ int src_x = x + clamped_origin_x,
+ src_y = y + clamped_origin_y;
+ int dst_x = x + dst_offset_x,
+ dst_y = y + dst_offset_y;
+ int dst_index = (dst_y * width + dst_x) * 4,
+ src_index = (src_y * orig_ibuf->x + src_x) * 4;
+ rgba_uchar_to_float(final_ibuf->rect_float + dst_index,
+ (unsigned char *)orig_ibuf->rect +
+ src_index);
+ }
+ }
+ }
+ }
+ else {
+ /* Libmv only works with float images,
+ *
+ * This would likely make it so loads of float buffers are being stored
+ * in the cache which is nice on the one hand (faster re-use of the
+ * frames) but on the other hand it bumps the memory usage up.
+ */
+ BLI_lock_thread(LOCK_MOVIECLIP);
+ IMB_float_from_rect(orig_ibuf);
+ BLI_unlock_thread(LOCK_MOVIECLIP);
+ final_ibuf = orig_ibuf;
+ }
+
+ if (downscale > 0) {
+ if (final_ibuf == orig_ibuf) {
+ final_ibuf = IMB_dupImBuf(orig_ibuf);
+ }
+ IMB_scaleImBuf(final_ibuf,
+ ibuf->x / (1 << downscale),
+ ibuf->y / (1 << downscale));
+ }
+
+ if (transform != NULL) {
+ libmv_FloatImage input_image, output_image;
+ ibuf_to_float_image(final_ibuf, &input_image);
+ libmv_frameAccessorgetTransformRun(transform,
+ &input_image,
+ &output_image);
+ if (final_ibuf != orig_ibuf) {
+ IMB_freeImBuf(final_ibuf);
+ }
+ final_ibuf = float_image_to_ibuf(&output_image);
+ libmv_floatImageDestroy(&output_image);
+ }
+
+ if (input_mode == LIBMV_IMAGE_MODE_RGBA) {
+ BLI_assert(ibuf->channels == 3 || ibuf->channels == 4);
+ /* pass */
+ }
+ else /* if (input_mode == LIBMV_IMAGE_MODE_MONO) */ {
+ if (final_ibuf->channels != 1) {
+ ImBuf *grayscale_ibuf = make_grayscale_ibuf_copy(final_ibuf);
+ if (final_ibuf != orig_ibuf) {
+ /* We dereference original frame later. */
+ IMB_freeImBuf(final_ibuf);
+ }
+ final_ibuf = grayscale_ibuf;
+ }
+ }
+
+ /* it's possible processing still didn't happen at this point,
+ * but we really need a copy of the buffer to be transformed
+ * and to be put to the cache.
+ */
+ if (final_ibuf == orig_ibuf) {
+ final_ibuf = IMB_dupImBuf(orig_ibuf);
+ }
+
+ IMB_freeImBuf(orig_ibuf);
+
+ /* We put postprocessed frame to the cache always for now,
+ * not the smartest thing in the world, but who cares at this point.
+ */
+
+ /* TODO(sergey): Disable cache for now, because we don't store region
+ * in the cache key and can't check whether cached version is usable for
+ * us or not.
+ *
+ * Need to think better about what to cache and when.
+ */
+ if (false) {
+ accesscache_put(accessor,
+ clip_index,
+ frame,
+ input_mode,
+ downscale,
+ transform_key,
+ final_ibuf);
+ }
+
+ return final_ibuf;
+}
+
+static libmv_CacheKey accessor_get_image_callback(
+ struct libmv_FrameAccessorUserData *user_data,
+ int clip_index,
+ int frame,
+ libmv_InputMode input_mode,
+ int downscale,
+ const libmv_Region *region,
+ const libmv_FrameTransform *transform,
+ float **destination,
+ int *width,
+ int *height,
+ int *channels)
+{
+ TrackingImageAccessor *accessor = (TrackingImageAccessor *) user_data;
+ ImBuf *ibuf;
+
+ BLI_assert(clip_index >= 0 && clip_index < accessor->num_clips);
+
+ ibuf = accessor_get_ibuf(accessor,
+ clip_index,
+ frame,
+ input_mode,
+ downscale,
+ region,
+ transform);
+
+ if (ibuf) {
+ *destination = ibuf->rect_float;
+ *width = ibuf->x;
+ *height = ibuf->y;
+ *channels = ibuf->channels;
+ }
+ else {
+ *destination = NULL;
+ *width = 0;
+ *height = 0;
+ *channels = 0;
}
+
+ return ibuf;
+}
+
+static void accessor_release_image_callback(libmv_CacheKey cache_key)
+{
+ ImBuf *ibuf = (ImBuf *) cache_key;
+ IMB_freeImBuf(ibuf);
+}
+
+TrackingImageAccessor *tracking_image_accessor_new(MovieClip *clips[MAX_ACCESSOR_CLIP],
+ int num_clips,
+ int start_frame)
+{
+ TrackingImageAccessor *accessor =
+ MEM_callocN(sizeof(TrackingImageAccessor), "tracking image accessor");
+
+ BLI_assert(num_clips <= MAX_ACCESSOR_CLIP);
+
+ accessor->cache = IMB_moviecache_create("frame access cache",
+ sizeof(AccessCacheKey),
+ accesscache_hashhash,
+ accesscache_hashcmp);
+
+ memcpy(accessor->clips, clips, num_clips * sizeof(MovieClip *));
+ accessor->num_clips = num_clips;
+ accessor->start_frame = start_frame;
+
+ accessor->libmv_accessor =
+ libmv_FrameAccessorNew((libmv_FrameAccessorUserData *) accessor,
+ accessor_get_image_callback,
+ accessor_release_image_callback);
+
+ return accessor;
+}
+
+void tracking_image_accessor_destroy(TrackingImageAccessor *accessor)
+{
+ IMB_moviecache_free(accessor->cache);
+ libmv_FrameAccessorDestroy(accessor->libmv_accessor);
+ MEM_freeN(accessor);
}
diff --git a/source/blender/blenkernel/intern/unit.c b/source/blender/blenkernel/intern/unit.c
index 5a2c77b5619..64d561491e2 100644
--- a/source/blender/blenkernel/intern/unit.c
+++ b/source/blender/blenkernel/intern/unit.c
@@ -48,7 +48,7 @@
#define SEP_CHR '#'
#define SEP_STR "#"
-#define EPS 0.00001
+#define EPS 0.001
#define UN_SC_KM 1000.0f
#define UN_SC_HM 100.0f
@@ -370,12 +370,7 @@ static size_t unit_as_string(char *str, int len_max, double value, int prec, bUn
value_conv = value / unit->scalar;
/* Convert to a string */
- {
- len = BLI_snprintf(str, len_max, "%.*f", prec, value_conv);
-
- if (len >= len_max)
- len = len_max;
- }
+ len = BLI_snprintf_rlen(str, len_max, "%.*f", prec, value_conv);
/* Add unit prefix and strip zeros */
@@ -650,7 +645,7 @@ bool bUnit_ReplaceString(char *str, int len_max, const char *str_prev, double sc
}
/* make lowercase */
- BLI_ascii_strtolower(str, len_max);
+ BLI_str_tolower_ascii(str, len_max);
/* Try to find a default unit from current or previous string. */
default_unit = unit_detect_from_str(usys, str, str_prev);
diff --git a/source/blender/blenkernel/intern/world.c b/source/blender/blenkernel/intern/world.c
index 8e3c92314e6..e4736b1f54c 100644
--- a/source/blender/blenkernel/intern/world.c
+++ b/source/blender/blenkernel/intern/world.c
@@ -38,8 +38,8 @@
#include "DNA_scene_types.h"
#include "DNA_texture_types.h"
-#include "BLI_listbase.h"
#include "BLI_utildefines.h"
+#include "BLI_listbase.h"
#include "BKE_animsys.h"
#include "BKE_global.h"
@@ -49,6 +49,8 @@
#include "BKE_node.h"
#include "BKE_world.h"
+#include "GPU_material.h"
+
void BKE_world_free_ex(World *wrld, bool do_id_user)
{
MTex *mtex;
@@ -61,7 +63,7 @@ void BKE_world_free_ex(World *wrld, bool do_id_user)
}
BKE_previewimg_free(&wrld->preview);
- BKE_free_animdata((ID *)wrld);
+ BKE_animdata_free((ID *)wrld);
/* is no lib link block, but world extension */
if (wrld->nodetree) {
@@ -69,7 +71,10 @@ void BKE_world_free_ex(World *wrld, bool do_id_user)
MEM_freeN(wrld->nodetree);
}
- BKE_icon_delete((struct ID *)wrld);
+ if (wrld->gpumaterial.first)
+ GPU_material_free(&wrld->gpumaterial);
+
+ BKE_icon_id_delete((struct ID *)wrld);
wrld->id.icon_id = 0;
}
@@ -134,6 +139,12 @@ World *BKE_world_copy(World *wrld)
if (wrld->preview)
wrldn->preview = BKE_previewimg_copy(wrld->preview);
+ BLI_listbase_clear(&wrldn->gpumaterial);
+
+ if (wrld->id.lib) {
+ BKE_id_lib_local_paths(G.main, wrld->id.lib, &wrldn->id);
+ }
+
return wrldn;
}
@@ -158,6 +169,8 @@ World *localize_world(World *wrld)
wrldn->preview = NULL;
+ BLI_listbase_clear(&wrldn->gpumaterial);
+
return wrldn;
}
diff --git a/source/blender/blenkernel/intern/writeavi.c b/source/blender/blenkernel/intern/writeavi.c
index aef44993912..82e4405225a 100644
--- a/source/blender/blenkernel/intern/writeavi.c
+++ b/source/blender/blenkernel/intern/writeavi.c
@@ -50,26 +50,34 @@
/* ********************** general blender movie support ***************************** */
-static int start_stub(Scene *UNUSED(scene), RenderData *UNUSED(rd), int UNUSED(rectx), int UNUSED(recty),
- ReportList *UNUSED(reports))
+static int start_stub(void *UNUSED(context_v), Scene *UNUSED(scene), RenderData *UNUSED(rd), int UNUSED(rectx), int UNUSED(recty),
+ ReportList *UNUSED(reports), bool UNUSED(preview), const char *UNUSED(suffix))
{ return 0; }
-static void end_stub(void)
+static void end_stub(void *UNUSED(context_v))
{}
-static int append_stub(RenderData *UNUSED(rd), int UNUSED(start_frame), int UNUSED(frame), int *UNUSED(pixels),
- int UNUSED(rectx), int UNUSED(recty), ReportList *UNUSED(reports))
+static int append_stub(void *UNUSED(context_v), RenderData *UNUSED(rd), int UNUSED(start_frame), int UNUSED(frame), int *UNUSED(pixels),
+ int UNUSED(rectx), int UNUSED(recty), const char *UNUSED(suffix), ReportList *UNUSED(reports))
{ return 0; }
+static void *context_create_stub(void)
+{ return NULL; }
+
+static void context_free_stub(void *UNUSED(context_v))
+{}
+
#ifdef WITH_AVI
# include "AVI_avi.h"
/* callbacks */
-static int start_avi(Scene *scene, RenderData *rd, int rectx, int recty, ReportList *reports);
-static void end_avi(void);
-static int append_avi(RenderData *rd, int start_frame, int frame, int *pixels,
- int rectx, int recty, ReportList *reports);
-static void filepath_avi(char *string, RenderData *rd);
+static int start_avi(void *context_v, Scene *scene, RenderData *rd, int rectx, int recty, ReportList *reports, bool preview, const char *suffix);
+static void end_avi(void *context_v);
+static int append_avi(void *context_v, RenderData *rd, int start_frame, int frame, int *pixels,
+ int rectx, int recty, const char *suffix, ReportList *reports);
+static void filepath_avi(char *string, RenderData *rd, bool preview, const char *suffix);
+static void *context_create_avi(void);
+static void context_free_avi(void *context_v);
#endif /* WITH_AVI */
#ifdef WITH_QUICKTIME
@@ -80,7 +88,9 @@ static void filepath_avi(char *string, RenderData *rd);
# include "BKE_writeffmpeg.h"
#endif
-#include "BKE_writeframeserver.h"
+#ifdef WITH_FRAMESERVER
+# include "BKE_writeframeserver.h"
+#endif
bMovieHandle *BKE_movie_handle_get(const char imtype)
{
@@ -91,13 +101,17 @@ bMovieHandle *BKE_movie_handle_get(const char imtype)
mh.end_movie = end_stub;
mh.get_next_frame = NULL;
mh.get_movie_path = NULL;
-
+ mh.context_create = context_create_stub;
+ mh.context_free = context_free_stub;
+
/* set the default handle, as builtin */
#ifdef WITH_AVI
mh.start_movie = start_avi;
mh.append_movie = append_avi;
mh.end_movie = end_avi;
mh.get_movie_path = filepath_avi;
+ mh.context_create = context_create_avi;
+ mh.context_free = context_free_avi;
#endif
/* do the platform specific handles */
@@ -107,6 +121,8 @@ bMovieHandle *BKE_movie_handle_get(const char imtype)
mh.append_movie = append_qt;
mh.end_movie = end_qt;
mh.get_movie_path = filepath_qt;
+ mh.context_create = context_create_qt;
+ mh.context_free = context_free_qt;
}
#endif
#ifdef WITH_FFMPEG
@@ -115,6 +131,8 @@ bMovieHandle *BKE_movie_handle_get(const char imtype)
mh.append_movie = BKE_ffmpeg_append;
mh.end_movie = BKE_ffmpeg_end;
mh.get_movie_path = BKE_ffmpeg_filepath_get;
+ mh.context_create = BKE_ffmpeg_context_create;
+ mh.context_free = BKE_ffmpeg_context_free;
}
#endif
#ifdef WITH_FRAMESERVER
@@ -123,13 +141,15 @@ bMovieHandle *BKE_movie_handle_get(const char imtype)
mh.append_movie = BKE_frameserver_append;
mh.end_movie = BKE_frameserver_end;
mh.get_next_frame = BKE_frameserver_loop;
+ mh.context_create = BKE_frameserver_context_create;
+ mh.context_free = BKE_frameserver_context_free;
}
#endif
/* in case all above are disabled */
(void)imtype;
- return &mh;
+ return (mh.append_movie != append_stub) ? &mh : NULL;
}
/* ****************************************************************** */
@@ -137,12 +157,21 @@ bMovieHandle *BKE_movie_handle_get(const char imtype)
#ifdef WITH_AVI
-static AviMovie *avi = NULL;
-
-static void filepath_avi(char *string, RenderData *rd)
+static void filepath_avi(char *string, RenderData *rd, bool preview, const char *suffix)
{
+ int sfra, efra;
+
if (string == NULL) return;
+ if (preview) {
+ sfra = rd->psfra;
+ efra = rd->pefra;
+ }
+ else {
+ sfra = rd->sfra;
+ efra = rd->efra;
+ }
+
strcpy(string, rd->pic);
BLI_path_abs(string, G.main->name);
@@ -150,36 +179,36 @@ static void filepath_avi(char *string, RenderData *rd)
if (rd->scemode & R_EXTENSION) {
if (!BLI_testextensie(string, ".avi")) {
- BLI_path_frame_range(string, rd->sfra, rd->efra, 4);
+ BLI_path_frame_range(string, sfra, efra, 4);
strcat(string, ".avi");
}
}
else {
if (BLI_path_frame_check_chars(string)) {
- BLI_path_frame_range(string, rd->sfra, rd->efra, 4);
+ BLI_path_frame_range(string, sfra, efra, 4);
}
}
+
+ BLI_path_suffix(string, FILE_MAX, suffix, "");
}
-static int start_avi(Scene *scene, RenderData *rd, int rectx, int recty, ReportList *reports)
+static int start_avi(void *context_v, Scene *UNUSED(scene), RenderData *rd, int rectx, int recty,
+ ReportList *reports, bool preview, const char *suffix)
{
int x, y;
char name[256];
AviFormat format;
int quality;
double framerate;
-
- (void)scene; /* unused */
-
- filepath_avi(name, rd);
+ AviMovie *avi = context_v;
+
+ filepath_avi(name, rd, preview, suffix);
x = rectx;
y = recty;
quality = rd->im_format.quality;
framerate = (double) rd->frs_sec / (double) rd->frs_sec_base;
-
- avi = MEM_mallocN(sizeof(AviMovie), "avimovie");
if (rd->im_format.imtype != R_IMF_IMTYPE_AVIJPEG) format = AVI_FORMAT_AVI_RGB;
else format = AVI_FORMAT_MJPEG;
@@ -205,12 +234,13 @@ static int start_avi(Scene *scene, RenderData *rd, int rectx, int recty, ReportL
return 1;
}
-static int append_avi(RenderData *UNUSED(rd), int start_frame, int frame, int *pixels,
- int rectx, int recty, ReportList *UNUSED(reports))
+static int append_avi(void *context_v, RenderData *UNUSED(rd), int start_frame, int frame, int *pixels,
+ int rectx, int recty, const char *UNUSED(suffix), ReportList *UNUSED(reports))
{
unsigned int *rt1, *rt2, *rectot;
int x, y;
char *cp, rt;
+ AviMovie *avi = context_v;
if (avi == NULL)
return 0;
@@ -241,22 +271,39 @@ static int append_avi(RenderData *UNUSED(rd), int start_frame, int frame, int *p
return 1;
}
-static void end_avi(void)
+static void end_avi(void *context_v)
{
+ AviMovie *avi = context_v;
+
if (avi == NULL) return;
AVI_close_compress(avi);
- MEM_freeN(avi);
- avi = NULL;
}
+
+static void *context_create_avi(void)
+{
+ AviMovie *avi = MEM_mallocN(sizeof(AviMovie), "avimovie");
+ return avi;
+}
+
+static void context_free_avi(void *context_v)
+{
+ AviMovie *avi = context_v;
+ if (avi) {
+ MEM_freeN(avi);
+ }
+}
+
#endif /* WITH_AVI */
-/* similar to BKE_makepicstring() */
-void BKE_movie_filepath_get(char *string, RenderData *rd)
+/* similar to BKE_image_path_from_imformat() */
+void BKE_movie_filepath_get(char *string, RenderData *rd, bool preview, const char *suffix)
{
bMovieHandle *mh = BKE_movie_handle_get(rd->im_format.imtype);
- if (mh->get_movie_path)
- mh->get_movie_path(string, rd);
- else
+ if (mh && mh->get_movie_path) {
+ mh->get_movie_path(string, rd, preview, suffix);
+ }
+ else {
string[0] = '\0';
+ }
}
diff --git a/source/blender/blenkernel/intern/writeffmpeg.c b/source/blender/blenkernel/intern/writeffmpeg.c
index ca21180000d..bc734a9a551 100644
--- a/source/blender/blenkernel/intern/writeffmpeg.c
+++ b/source/blender/blenkernel/intern/writeffmpeg.c
@@ -45,7 +45,8 @@
#include "BLI_blenlib.h"
#ifdef WITH_AUDASPACE
-# include "AUD_C-API.h"
+# include AUD_DEVICE_H
+# include AUD_SPECIAL_H
#endif
#include "BLI_utildefines.h"
@@ -57,40 +58,42 @@
#include "BKE_sound.h"
#include "BKE_writeffmpeg.h"
-#include "IMB_imbuf_types.h"
#include "IMB_imbuf.h"
#include "ffmpeg_compat.h"
-static int ffmpeg_type = 0;
-static int ffmpeg_codec = AV_CODEC_ID_MPEG4;
-static int ffmpeg_audio_codec = AV_CODEC_ID_NONE;
-static int ffmpeg_video_bitrate = 1150;
-static int ffmpeg_audio_bitrate = 128;
-static int ffmpeg_gop_size = 12;
-static int ffmpeg_autosplit = 0;
-static int ffmpeg_autosplit_count = 0;
-
-static AVFormatContext *outfile = 0;
-static AVStream *video_stream = 0;
-static AVStream *audio_stream = 0;
-static AVFrame *current_frame = 0;
-static struct SwsContext *img_convert_ctx = 0;
-
-static uint8_t *audio_input_buffer = 0;
-static uint8_t *audio_deinterleave_buffer = 0;
-static int audio_input_samples = 0;
+typedef struct FFMpegContext {
+ int ffmpeg_type;
+ int ffmpeg_codec;
+ int ffmpeg_audio_codec;
+ int ffmpeg_video_bitrate;
+ int ffmpeg_audio_bitrate;
+ int ffmpeg_gop_size;
+ int ffmpeg_autosplit;
+ int ffmpeg_autosplit_count;
+ bool ffmpeg_preview;
+
+ AVFormatContext *outfile;
+ AVStream *video_stream;
+ AVStream *audio_stream;
+ AVFrame *current_frame;
+ struct SwsContext *img_convert_ctx;
+
+ uint8_t *audio_input_buffer;
+ uint8_t *audio_deinterleave_buffer;
+ int audio_input_samples;
#ifndef FFMPEG_HAVE_ENCODE_AUDIO2
-static uint8_t *audio_output_buffer = 0;
-static int audio_outbuf_size = 0;
+ uint8_t *audio_output_buffer;
+ int audio_outbuf_size;
#endif
-static double audio_time = 0.0f;
-static bool audio_deinterleave = false;
-static int audio_sample_size = 0;
+ double audio_time;
+ bool audio_deinterleave;
+ int audio_sample_size;
#ifdef WITH_AUDASPACE
-static AUD_Device *audio_mixdown_device = 0;
+ AUD_Device *audio_mixdown_device;
#endif
+} FFMpegContext;
#define FFMPEG_AUTOSPLIT_SIZE 2000000000
@@ -99,6 +102,7 @@ static AUD_Device *audio_mixdown_device = 0;
static void ffmpeg_dict_set_int(AVDictionary **dict, const char *key, int value);
static void ffmpeg_dict_set_float(AVDictionary **dict, const char *key, float value);
static void ffmpeg_set_expert_options(RenderData *rd);
+static void ffmpeg_filepath_get(FFMpegContext *context, char *string, struct RenderData *rd, bool preview, const char *suffix);
/* Delete a picture buffer */
@@ -117,50 +121,50 @@ static int request_float_audio_buffer(int codec_id)
}
#ifdef WITH_AUDASPACE
-static int write_audio_frame(void)
+static int write_audio_frame(FFMpegContext *context)
{
AVCodecContext *c = NULL;
AVPacket pkt;
AVFrame *frame = NULL;
int got_output = 0;
- c = audio_stream->codec;
+ c = context->audio_stream->codec;
av_init_packet(&pkt);
pkt.size = 0;
pkt.data = NULL;
- AUD_readDevice(audio_mixdown_device, audio_input_buffer, audio_input_samples);
- audio_time += (double) audio_input_samples / (double) c->sample_rate;
+ AUD_Device_read(context->audio_mixdown_device, context->audio_input_buffer, context->audio_input_samples);
+ context->audio_time += (double) context->audio_input_samples / (double) c->sample_rate;
#ifdef FFMPEG_HAVE_ENCODE_AUDIO2
frame = avcodec_alloc_frame();
avcodec_get_frame_defaults(frame);
- frame->pts = audio_time / av_q2d(c->time_base);
- frame->nb_samples = audio_input_samples;
+ frame->pts = context->audio_time / av_q2d(c->time_base);
+ frame->nb_samples = context->audio_input_samples;
frame->format = c->sample_fmt;
#ifdef FFMPEG_HAVE_FRAME_CHANNEL_LAYOUT
frame->channel_layout = c->channel_layout;
#endif
- if (audio_deinterleave) {
+ if (context->audio_deinterleave) {
int channel, i;
uint8_t *temp;
for (channel = 0; channel < c->channels; channel++) {
for (i = 0; i < frame->nb_samples; i++) {
- memcpy(audio_deinterleave_buffer + (i + channel * frame->nb_samples) * audio_sample_size,
- audio_input_buffer + (c->channels * i + channel) * audio_sample_size, audio_sample_size);
+ memcpy(context->audio_deinterleave_buffer + (i + channel * frame->nb_samples) * context->audio_sample_size,
+ context->audio_input_buffer + (c->channels * i + channel) * context->audio_sample_size, context->audio_sample_size);
}
}
- temp = audio_deinterleave_buffer;
- audio_deinterleave_buffer = audio_input_buffer;
- audio_input_buffer = temp;
+ temp = context->audio_deinterleave_buffer;
+ context->audio_deinterleave_buffer = context->audio_input_buffer;
+ context->audio_input_buffer = temp;
}
- avcodec_fill_audio_frame(frame, c->channels, c->sample_fmt, audio_input_buffer,
- audio_input_samples * c->channels * audio_sample_size, 1);
+ avcodec_fill_audio_frame(frame, c->channels, c->sample_fmt, context->audio_input_buffer,
+ context->audio_input_samples * c->channels * context->audio_sample_size, 1);
if (avcodec_encode_audio2(c, &pkt, frame, &got_output) < 0) {
// XXX error("Error writing audio packet");
@@ -172,30 +176,30 @@ static int write_audio_frame(void)
return 0;
}
#else
- pkt.size = avcodec_encode_audio(c, audio_output_buffer, audio_outbuf_size, (short *) audio_input_buffer);
+ pkt.size = avcodec_encode_audio(c, context->audio_output_buffer, context->audio_outbuf_size, (short *) context->audio_input_buffer);
if (pkt.size < 0) {
// XXX error("Error writing audio packet");
return -1;
}
- pkt.data = audio_output_buffer;
+ pkt.data = context->audio_output_buffer;
got_output = 1;
#endif
if (got_output) {
if (pkt.pts != AV_NOPTS_VALUE)
- pkt.pts = av_rescale_q(pkt.pts, c->time_base, audio_stream->time_base);
+ pkt.pts = av_rescale_q(pkt.pts, c->time_base, context->audio_stream->time_base);
if (pkt.dts != AV_NOPTS_VALUE)
- pkt.dts = av_rescale_q(pkt.dts, c->time_base, audio_stream->time_base);
+ pkt.dts = av_rescale_q(pkt.dts, c->time_base, context->audio_stream->time_base);
if (pkt.duration > 0)
- pkt.duration = av_rescale_q(pkt.duration, c->time_base, audio_stream->time_base);
+ pkt.duration = av_rescale_q(pkt.duration, c->time_base, context->audio_stream->time_base);
- pkt.stream_index = audio_stream->index;
+ pkt.stream_index = context->audio_stream->index;
pkt.flags |= AV_PKT_FLAG_KEY;
- if (av_interleaved_write_frame(outfile, &pkt) != 0) {
+ if (av_interleaved_write_frame(context->outfile, &pkt) != 0) {
fprintf(stderr, "Error writing audio packet!\n");
if (frame)
avcodec_free_frame(&frame);
@@ -302,11 +306,11 @@ static const char **get_file_extensions(int format)
}
/* Write a frame to the output file */
-static int write_video_frame(RenderData *rd, int cfra, AVFrame *frame, ReportList *reports)
+static int write_video_frame(FFMpegContext *context, RenderData *rd, int cfra, AVFrame *frame, ReportList *reports)
{
int got_output;
int ret, success = 1;
- AVCodecContext *c = video_stream->codec;
+ AVCodecContext *c = context->video_stream->codec;
AVPacket packet = { 0 };
av_init_packet(&packet);
@@ -321,22 +325,22 @@ static int write_video_frame(RenderData *rd, int cfra, AVFrame *frame, ReportLis
if (ret >= 0 && got_output) {
if (packet.pts != AV_NOPTS_VALUE) {
- packet.pts = av_rescale_q(packet.pts, c->time_base, video_stream->time_base);
+ packet.pts = av_rescale_q(packet.pts, c->time_base, context->video_stream->time_base);
PRINT("Video Frame PTS: %d\n", (int)packet.pts);
}
else {
PRINT("Video Frame PTS: not set\n");
}
if (packet.dts != AV_NOPTS_VALUE) {
- packet.dts = av_rescale_q(packet.dts, c->time_base, video_stream->time_base);
+ packet.dts = av_rescale_q(packet.dts, c->time_base, context->video_stream->time_base);
PRINT("Video Frame DTS: %d\n", (int)packet.dts);
}
else {
PRINT("Video Frame DTS: not set\n");
}
- packet.stream_index = video_stream->index;
- ret = av_interleaved_write_frame(outfile, &packet);
+ packet.stream_index = context->video_stream->index;
+ ret = av_interleaved_write_frame(context->outfile, &packet);
success = (ret == 0);
}
else if (ret < 0) {
@@ -350,11 +354,11 @@ static int write_video_frame(RenderData *rd, int cfra, AVFrame *frame, ReportLis
}
/* read and encode a frame of audio from the buffer */
-static AVFrame *generate_video_frame(uint8_t *pixels, ReportList *reports)
+static AVFrame *generate_video_frame(FFMpegContext *context, uint8_t *pixels, ReportList *reports)
{
uint8_t *rendered_frame;
- AVCodecContext *c = video_stream->codec;
+ AVCodecContext *c = context->video_stream->codec;
int width = c->width;
int height = c->height;
AVFrame *rgb_frame;
@@ -367,7 +371,7 @@ static AVFrame *generate_video_frame(uint8_t *pixels, ReportList *reports)
}
}
else {
- rgb_frame = current_frame;
+ rgb_frame = context->current_frame;
}
rendered_frame = pixels;
@@ -411,17 +415,17 @@ static AVFrame *generate_video_frame(uint8_t *pixels, ReportList *reports)
}
if (c->pix_fmt != PIX_FMT_BGR32) {
- sws_scale(img_convert_ctx, (const uint8_t *const *) rgb_frame->data,
+ sws_scale(context->img_convert_ctx, (const uint8_t *const *) rgb_frame->data,
rgb_frame->linesize, 0, c->height,
- current_frame->data, current_frame->linesize);
+ context->current_frame->data, context->current_frame->linesize);
delete_picture(rgb_frame);
}
- current_frame->format = PIX_FMT_BGR32;
- current_frame->width = width;
- current_frame->height = height;
+ context->current_frame->format = PIX_FMT_BGR32;
+ context->current_frame->width = width;
+ context->current_frame->height = height;
- return current_frame;
+ return context->current_frame;
}
static void set_ffmpeg_property_option(AVCodecContext *c, IDProperty *prop, AVDictionary **dictionary)
@@ -470,8 +474,8 @@ static int ffmpeg_proprty_valid(AVCodecContext *c, const char *prop_name, IDProp
{
int valid = 1;
- if (strcmp(prop_name, "video") == 0) {
- if (strcmp(curr->name, "bf") == 0) {
+ if (STREQ(prop_name, "video")) {
+ if (STREQ(curr->name, "bf")) {
/* flash codec doesn't support b frames */
valid &= c->codec_id != AV_CODEC_ID_FLV1;
}
@@ -484,7 +488,6 @@ static void set_ffmpeg_properties(RenderData *rd, AVCodecContext *c, const char
AVDictionary **dictionary)
{
IDProperty *prop;
- void *iter;
IDProperty *curr;
/* TODO(sergey): This is actually rather stupid, because changing
@@ -495,7 +498,7 @@ static void set_ffmpeg_properties(RenderData *rd, AVCodecContext *c, const char
*
* For as long we don't allow editing properties in the interface
* it's all good. bug if we allow editing them, we'll need to
- * repace it with some smarter code which would port settings
+ * replace it with some smarter code which would port settings
* from deprecated to new one.
*/
ffmpeg_set_expert_options(rd);
@@ -509,9 +512,7 @@ static void set_ffmpeg_properties(RenderData *rd, AVCodecContext *c, const char
return;
}
- iter = IDP_GetGroupIterator(prop);
-
- while ((curr = IDP_GroupIterNext(iter)) != NULL) {
+ for (curr = prop->data.group.first; curr; curr = curr->next) {
if (ffmpeg_proprty_valid(c, prop_name, curr))
set_ffmpeg_property_option(c, curr, dictionary);
}
@@ -519,7 +520,7 @@ static void set_ffmpeg_properties(RenderData *rd, AVCodecContext *c, const char
/* prepare a video stream for the output file */
-static AVStream *alloc_video_stream(RenderData *rd, int codec_id, AVFormatContext *of,
+static AVStream *alloc_video_stream(FFMpegContext *context, RenderData *rd, int codec_id, AVFormatContext *of,
int rectx, int recty, char *error, int error_size)
{
AVStream *st;
@@ -545,7 +546,7 @@ static AVStream *alloc_video_stream(RenderData *rd, int codec_id, AVFormatContex
c->height = recty;
/* FIXME: Really bad hack (tm) for NTSC support */
- if (ffmpeg_type == FFMPEG_DV && rd->frs_sec != 25) {
+ if (context->ffmpeg_type == FFMPEG_DV && rd->frs_sec != 25) {
c->time_base.den = 2997;
c->time_base.num = 100;
}
@@ -558,8 +559,8 @@ static AVStream *alloc_video_stream(RenderData *rd, int codec_id, AVFormatContex
c->time_base.num = ((double) rd->frs_sec_base) * 100000;
}
- c->gop_size = ffmpeg_gop_size;
- c->bit_rate = ffmpeg_video_bitrate * 1000;
+ c->gop_size = context->ffmpeg_gop_size;
+ c->bit_rate = context->ffmpeg_video_bitrate * 1000;
c->rc_max_rate = rd->ffcodecdata.rc_max_rate * 1000;
c->rc_min_rate = rd->ffcodecdata.rc_min_rate * 1000;
c->rc_buffer_size = rd->ffcodecdata.rc_buffer_size * 1024;
@@ -588,7 +589,7 @@ static AVStream *alloc_video_stream(RenderData *rd, int codec_id, AVFormatContex
c->pix_fmt = PIX_FMT_YUV422P;
}
- if (ffmpeg_type == FFMPEG_XVID) {
+ if (context->ffmpeg_type == FFMPEG_XVID) {
/* arghhhh ... */
c->pix_fmt = PIX_FMT_YUV420P;
c->codec_tag = (('D' << 24) + ('I' << 16) + ('V' << 8) + 'X');
@@ -602,8 +603,12 @@ static AVStream *alloc_video_stream(RenderData *rd, int codec_id, AVFormatContex
/* Keep lossless encodes in the RGB domain. */
if (codec_id == AV_CODEC_ID_HUFFYUV) {
- /* HUFFYUV was PIX_FMT_YUV422P before */
- c->pix_fmt = PIX_FMT_RGB32;
+ if (rd->im_format.planes == R_IMF_PLANES_RGBA) {
+ c->pix_fmt = PIX_FMT_BGRA;
+ }
+ else {
+ c->pix_fmt = PIX_FMT_RGB32;
+ }
}
if (codec_id == AV_CODEC_ID_FFV1) {
@@ -624,9 +629,9 @@ static AVStream *alloc_video_stream(RenderData *rd, int codec_id, AVFormatContex
if ((of->oformat->flags & AVFMT_GLOBALHEADER)
#if 0
- || !strcmp(of->oformat->name, "mp4")
- || !strcmp(of->oformat->name, "mov")
- || !strcmp(of->oformat->name, "3gp")
+ || STREQ(of->oformat->name, "mp4")
+ || STREQ(of->oformat->name, "mov")
+ || STREQ(of->oformat->name, "3gp")
#endif
)
{
@@ -654,14 +659,14 @@ static AVStream *alloc_video_stream(RenderData *rd, int codec_id, AVFormatContex
}
av_dict_free(&opts);
- current_frame = alloc_picture(c->pix_fmt, c->width, c->height);
+ context->current_frame = alloc_picture(c->pix_fmt, c->width, c->height);
- img_convert_ctx = sws_getContext(c->width, c->height, PIX_FMT_BGR32, c->width, c->height, c->pix_fmt, SWS_BICUBIC,
+ context->img_convert_ctx = sws_getContext(c->width, c->height, PIX_FMT_BGR32, c->width, c->height, c->pix_fmt, SWS_BICUBIC,
NULL, NULL, NULL);
return st;
}
-static AVStream *alloc_audio_stream(RenderData *rd, int codec_id, AVFormatContext *of, char *error, int error_size)
+static AVStream *alloc_audio_stream(FFMpegContext *context, RenderData *rd, int codec_id, AVFormatContext *of, char *error, int error_size)
{
AVStream *st;
AVCodecContext *c;
@@ -679,7 +684,7 @@ static AVStream *alloc_audio_stream(RenderData *rd, int codec_id, AVFormatContex
c->codec_type = AVMEDIA_TYPE_AUDIO;
c->sample_rate = rd->ffcodecdata.audio_mixrate;
- c->bit_rate = ffmpeg_audio_bitrate * 1000;
+ c->bit_rate = context->ffmpeg_audio_bitrate * 1000;
c->sample_fmt = AV_SAMPLE_FMT_S16;
c->channels = rd->ffcodecdata.audio_channels;
@@ -696,7 +701,7 @@ static AVStream *alloc_audio_stream(RenderData *rd, int codec_id, AVFormatContex
}
if (codec->sample_fmts) {
- /* check if the prefered sample format for this codec is supported.
+ /* check if the preferred sample format for this codec is supported.
* this is because, depending on the version of libav, and with the whole ffmpeg/libav fork situation,
* you have various implementations around. float samples in particular are not always supported.
*/
@@ -741,40 +746,40 @@ static AVStream *alloc_audio_stream(RenderData *rd, int codec_id, AVFormatContex
av_dict_free(&opts);
/* need to prevent floating point exception when using vorbis audio codec,
- * initialize this value in the same way as it's done in FFmpeg iteslf (sergey) */
+ * initialize this value in the same way as it's done in FFmpeg itself (sergey) */
st->codec->time_base.num = 1;
st->codec->time_base.den = st->codec->sample_rate;
#ifndef FFMPEG_HAVE_ENCODE_AUDIO2
- audio_outbuf_size = FF_MIN_BUFFER_SIZE;
+ context->audio_outbuf_size = FF_MIN_BUFFER_SIZE;
#endif
if (c->frame_size == 0)
// used to be if ((c->codec_id >= CODEC_ID_PCM_S16LE) && (c->codec_id <= CODEC_ID_PCM_DVD))
// not sure if that is needed anymore, so let's try out if there are any
// complaints regarding some ffmpeg versions users might have
- audio_input_samples = FF_MIN_BUFFER_SIZE * 8 / c->bits_per_coded_sample / c->channels;
+ context->audio_input_samples = FF_MIN_BUFFER_SIZE * 8 / c->bits_per_coded_sample / c->channels;
else {
- audio_input_samples = c->frame_size;
+ context->audio_input_samples = c->frame_size;
#ifndef FFMPEG_HAVE_ENCODE_AUDIO2
- if (c->frame_size * c->channels * sizeof(int16_t) * 4 > audio_outbuf_size)
- audio_outbuf_size = c->frame_size * c->channels * sizeof(int16_t) * 4;
+ if (c->frame_size * c->channels * sizeof(int16_t) * 4 > context->audio_outbuf_size)
+ context->audio_outbuf_size = c->frame_size * c->channels * sizeof(int16_t) * 4;
#endif
}
- audio_deinterleave = av_sample_fmt_is_planar(c->sample_fmt);
+ context->audio_deinterleave = av_sample_fmt_is_planar(c->sample_fmt);
- audio_sample_size = av_get_bytes_per_sample(c->sample_fmt);
+ context->audio_sample_size = av_get_bytes_per_sample(c->sample_fmt);
- audio_input_buffer = (uint8_t *) av_malloc(audio_input_samples * c->channels * audio_sample_size);
+ context->audio_input_buffer = (uint8_t *) av_malloc(context->audio_input_samples * c->channels * context->audio_sample_size);
#ifndef FFMPEG_HAVE_ENCODE_AUDIO2
- audio_output_buffer = (uint8_t *) av_malloc(audio_outbuf_size);
+ context->audio_output_buffer = (uint8_t *) av_malloc(context->audio_outbuf_size);
#endif
- if (audio_deinterleave)
- audio_deinterleave_buffer = (uint8_t *) av_malloc(audio_input_samples * c->channels * audio_sample_size);
+ if (context->audio_deinterleave)
+ context->audio_deinterleave_buffer = (uint8_t *) av_malloc(context->audio_input_samples * c->channels * context->audio_sample_size);
- audio_time = 0.0f;
+ context->audio_time = 0.0f;
return st;
}
@@ -798,7 +803,7 @@ static void ffmpeg_dict_set_float(AVDictionary **dict, const char *key, float va
av_dict_set(dict, key, buffer, 0);
}
-static int start_ffmpeg_impl(struct RenderData *rd, int rectx, int recty, ReportList *reports)
+static int start_ffmpeg_impl(FFMpegContext *context, struct RenderData *rd, int rectx, int recty, const char *suffix, ReportList *reports)
{
/* Handle to the output file */
AVFormatContext *of;
@@ -807,26 +812,26 @@ static int start_ffmpeg_impl(struct RenderData *rd, int rectx, int recty, Report
char name[256], error[1024];
const char **exts;
- ffmpeg_type = rd->ffcodecdata.type;
- ffmpeg_codec = rd->ffcodecdata.codec;
- ffmpeg_audio_codec = rd->ffcodecdata.audio_codec;
- ffmpeg_video_bitrate = rd->ffcodecdata.video_bitrate;
- ffmpeg_audio_bitrate = rd->ffcodecdata.audio_bitrate;
- ffmpeg_gop_size = rd->ffcodecdata.gop_size;
- ffmpeg_autosplit = rd->ffcodecdata.flags & FFMPEG_AUTOSPLIT_OUTPUT;
-
+ context->ffmpeg_type = rd->ffcodecdata.type;
+ context->ffmpeg_codec = rd->ffcodecdata.codec;
+ context->ffmpeg_audio_codec = rd->ffcodecdata.audio_codec;
+ context->ffmpeg_video_bitrate = rd->ffcodecdata.video_bitrate;
+ context->ffmpeg_audio_bitrate = rd->ffcodecdata.audio_bitrate;
+ context->ffmpeg_gop_size = rd->ffcodecdata.gop_size;
+ context->ffmpeg_autosplit = rd->ffcodecdata.flags & FFMPEG_AUTOSPLIT_OUTPUT;
+
/* Determine the correct filename */
- BKE_ffmpeg_filepath_get(name, rd);
+ ffmpeg_filepath_get(context, name, rd, context->ffmpeg_preview, suffix);
PRINT("Starting output to %s(ffmpeg)...\n"
" Using type=%d, codec=%d, audio_codec=%d,\n"
" video_bitrate=%d, audio_bitrate=%d,\n"
" gop_size=%d, autosplit=%d\n"
" render width=%d, render height=%d\n",
- name, ffmpeg_type, ffmpeg_codec, ffmpeg_audio_codec,
- ffmpeg_video_bitrate, ffmpeg_audio_bitrate,
- ffmpeg_gop_size, ffmpeg_autosplit, rectx, recty);
+ name, context->ffmpeg_type, context->ffmpeg_codec, context->ffmpeg_audio_codec,
+ context->ffmpeg_video_bitrate, context->ffmpeg_audio_bitrate,
+ context->ffmpeg_gop_size, context->ffmpeg_autosplit, rectx, recty);
- exts = get_file_extensions(ffmpeg_type);
+ exts = get_file_extensions(context->ffmpeg_type);
if (!exts) {
BKE_report(reports, RPT_ERROR, "No valid formats found");
return 0;
@@ -845,7 +850,7 @@ static int start_ffmpeg_impl(struct RenderData *rd, int rectx, int recty, Report
of->oformat = fmt;
of->packet_size = rd->ffcodecdata.mux_packet_size;
- if (ffmpeg_audio_codec != AV_CODEC_ID_NONE) {
+ if (context->ffmpeg_audio_codec != AV_CODEC_ID_NONE) {
ffmpeg_dict_set_int(&opts, "muxrate", rd->ffcodecdata.mux_rate);
}
else {
@@ -856,15 +861,15 @@ static int start_ffmpeg_impl(struct RenderData *rd, int rectx, int recty, Report
of->max_delay = (int)(0.7 * AV_TIME_BASE);
- fmt->audio_codec = ffmpeg_audio_codec;
+ fmt->audio_codec = context->ffmpeg_audio_codec;
BLI_strncpy(of->filename, name, sizeof(of->filename));
/* set the codec to the user's selection */
- switch (ffmpeg_type) {
+ switch (context->ffmpeg_type) {
case FFMPEG_AVI:
case FFMPEG_MOV:
case FFMPEG_MKV:
- fmt->video_codec = ffmpeg_codec;
+ fmt->video_codec = context->ffmpeg_codec;
break;
case FFMPEG_OGG:
fmt->video_codec = AV_CODEC_ID_THEORA;
@@ -889,7 +894,7 @@ static int start_ffmpeg_impl(struct RenderData *rd, int rectx, int recty, Report
break;
case FFMPEG_MPEG4:
default:
- fmt->video_codec = AV_CODEC_ID_MPEG4;
+ fmt->video_codec = context->ffmpeg_codec;
break;
}
if (fmt->video_codec == AV_CODEC_ID_DVVIDEO) {
@@ -907,9 +912,9 @@ static int start_ffmpeg_impl(struct RenderData *rd, int rectx, int recty, Report
}
}
- if (ffmpeg_type == FFMPEG_DV) {
+ if (context->ffmpeg_type == FFMPEG_DV) {
fmt->audio_codec = AV_CODEC_ID_PCM_S16LE;
- if (ffmpeg_audio_codec != AV_CODEC_ID_NONE && rd->ffcodecdata.audio_mixrate != 48000 && rd->ffcodecdata.audio_channels != 2) {
+ if (context->ffmpeg_audio_codec != AV_CODEC_ID_NONE && rd->ffcodecdata.audio_mixrate != 48000 && rd->ffcodecdata.audio_channels != 2) {
BKE_report(reports, RPT_ERROR, "FFMPEG only supports 48khz / stereo audio for DV!");
av_dict_free(&opts);
return 0;
@@ -917,9 +922,9 @@ static int start_ffmpeg_impl(struct RenderData *rd, int rectx, int recty, Report
}
if (fmt->video_codec != AV_CODEC_ID_NONE) {
- video_stream = alloc_video_stream(rd, fmt->video_codec, of, rectx, recty, error, sizeof(error));
- PRINT("alloc video stream %p\n", video_stream);
- if (!video_stream) {
+ context->video_stream = alloc_video_stream(context, rd, fmt->video_codec, of, rectx, recty, error, sizeof(error));
+ PRINT("alloc video stream %p\n", context->video_stream);
+ if (!context->video_stream) {
if (error[0])
BKE_report(reports, RPT_ERROR, error);
else
@@ -930,9 +935,9 @@ static int start_ffmpeg_impl(struct RenderData *rd, int rectx, int recty, Report
}
}
- if (ffmpeg_audio_codec != AV_CODEC_ID_NONE) {
- audio_stream = alloc_audio_stream(rd, fmt->audio_codec, of, error, sizeof(error));
- if (!audio_stream) {
+ if (context->ffmpeg_audio_codec != AV_CODEC_ID_NONE) {
+ context->audio_stream = alloc_audio_stream(context, rd, fmt->audio_codec, of, error, sizeof(error));
+ if (!context->audio_stream) {
if (error[0])
BKE_report(reports, RPT_ERROR, error);
else
@@ -955,7 +960,7 @@ static int start_ffmpeg_impl(struct RenderData *rd, int rectx, int recty, Report
return 0;
}
- outfile = of;
+ context->outfile = of;
av_dump_format(of, 0, name, 1);
av_dict_free(&opts);
@@ -979,11 +984,11 @@ static int start_ffmpeg_impl(struct RenderData *rd, int rectx, int recty, Report
* parameter.
* </p>
*/
-static void flush_ffmpeg(void)
+static void flush_ffmpeg(FFMpegContext *context)
{
int ret = 0;
- AVCodecContext *c = video_stream->codec;
+ AVCodecContext *c = context->video_stream->codec;
/* get the delayed frames */
while (1) {
int got_output;
@@ -999,28 +1004,28 @@ static void flush_ffmpeg(void)
break;
}
if (packet.pts != AV_NOPTS_VALUE) {
- packet.pts = av_rescale_q(packet.pts, c->time_base, video_stream->time_base);
+ packet.pts = av_rescale_q(packet.pts, c->time_base, context->video_stream->time_base);
PRINT("Video Frame PTS: %d\n", (int) packet.pts);
}
else {
PRINT("Video Frame PTS: not set\n");
}
if (packet.dts != AV_NOPTS_VALUE) {
- packet.dts = av_rescale_q(packet.dts, c->time_base, video_stream->time_base);
+ packet.dts = av_rescale_q(packet.dts, c->time_base, context->video_stream->time_base);
PRINT("Video Frame DTS: %d\n", (int) packet.dts);
}
else {
PRINT("Video Frame DTS: not set\n");
}
- packet.stream_index = video_stream->index;
- ret = av_interleaved_write_frame(outfile, &packet);
+ packet.stream_index = context->video_stream->index;
+ ret = av_interleaved_write_frame(context->outfile, &packet);
if (ret != 0) {
fprintf(stderr, "Error writing delayed frame %d\n", ret);
break;
}
}
- avcodec_flush_buffers(video_stream->codec);
+ avcodec_flush_buffers(context->video_stream->codec);
}
/* **********************************************************************
@@ -1028,15 +1033,25 @@ static void flush_ffmpeg(void)
* ********************************************************************** */
/* Get the output filename-- similar to the other output formats */
-void BKE_ffmpeg_filepath_get(char *string, RenderData *rd)
+static void ffmpeg_filepath_get(FFMpegContext *context, char *string, RenderData *rd, bool preview, const char *suffix)
{
char autosplit[20];
const char **exts = get_file_extensions(rd->ffcodecdata.type);
const char **fe = exts;
+ int sfra, efra;
if (!string || !exts) return;
+ if (preview) {
+ sfra = rd->psfra;
+ efra = rd->pefra;
+ }
+ else {
+ sfra = rd->sfra;
+ efra = rd->efra;
+ }
+
strcpy(string, rd->pic);
BLI_path_abs(string, G.main->name);
@@ -1045,7 +1060,9 @@ void BKE_ffmpeg_filepath_get(char *string, RenderData *rd)
autosplit[0] = 0;
if ((rd->ffcodecdata.flags & FFMPEG_AUTOSPLIT_OUTPUT) != 0) {
- sprintf(autosplit, "_%03d", ffmpeg_autosplit_count);
+ if (context) {
+ sprintf(autosplit, "_%03d", context->ffmpeg_autosplit_count);
+ }
}
if (rd->scemode & R_EXTENSION) {
@@ -1059,7 +1076,7 @@ void BKE_ffmpeg_filepath_get(char *string, RenderData *rd)
if (*fe == NULL) {
strcat(string, autosplit);
- BLI_path_frame_range(string, rd->sfra, rd->efra, 4);
+ BLI_path_frame_range(string, sfra, efra, 4);
strcat(string, *exts);
}
else {
@@ -1070,23 +1087,33 @@ void BKE_ffmpeg_filepath_get(char *string, RenderData *rd)
}
else {
if (BLI_path_frame_check_chars(string)) {
- BLI_path_frame_range(string, rd->sfra, rd->efra, 4);
+ BLI_path_frame_range(string, sfra, efra, 4);
}
strcat(string, autosplit);
}
+
+ BLI_path_suffix(string, FILE_MAX, suffix, "");
}
-int BKE_ffmpeg_start(struct Scene *scene, RenderData *rd, int rectx, int recty, ReportList *reports)
+void BKE_ffmpeg_filepath_get(char *string, RenderData *rd, bool preview, const char *suffix)
+{
+ ffmpeg_filepath_get(NULL, string, rd, preview, suffix);
+}
+
+int BKE_ffmpeg_start(void *context_v, struct Scene *scene, RenderData *rd, int rectx, int recty,
+ ReportList *reports, bool preview, const char *suffix)
{
int success;
+ FFMpegContext *context = context_v;
- ffmpeg_autosplit_count = 0;
+ context->ffmpeg_autosplit_count = 0;
+ context->ffmpeg_preview = preview;
- success = start_ffmpeg_impl(rd, rectx, recty, reports);
+ success = start_ffmpeg_impl(context, rd, rectx, recty, suffix, reports);
#ifdef WITH_AUDASPACE
- if (audio_stream) {
- AVCodecContext *c = audio_stream->codec;
+ if (context->audio_stream) {
+ AVCodecContext *c = context->audio_stream->codec;
AUD_DeviceSpecs specs;
specs.channels = c->channels;
@@ -1111,7 +1138,7 @@ int BKE_ffmpeg_start(struct Scene *scene, RenderData *rd, int rectx, int recty,
}
specs.rate = rd->ffcodecdata.audio_mixrate;
- audio_mixdown_device = sound_mixdown(scene, specs, rd->sfra, rd->ffcodecdata.audio_volume);
+ context->audio_mixdown_device = BKE_sound_mixdown(scene, specs, preview ? rd->psfra : rd->sfra, rd->ffcodecdata.audio_volume);
#ifdef FFMPEG_CODEC_TIME_BASE
c->time_base.den = specs.rate;
c->time_base.num = 1;
@@ -1121,16 +1148,16 @@ int BKE_ffmpeg_start(struct Scene *scene, RenderData *rd, int rectx, int recty,
return success;
}
-static void end_ffmpeg_impl(int is_autosplit);
+static void end_ffmpeg_impl(FFMpegContext *context, int is_autosplit);
#ifdef WITH_AUDASPACE
-static void write_audio_frames(double to_pts)
+static void write_audio_frames(FFMpegContext *context, double to_pts)
{
int finished = 0;
- while (audio_stream && !finished) {
- if ((audio_time >= to_pts) ||
- (write_audio_frame()))
+ while (context->audio_stream && !finished) {
+ if ((context->audio_time >= to_pts) ||
+ (write_audio_frame(context)))
{
finished = 1;
}
@@ -1138,8 +1165,10 @@ static void write_audio_frames(double to_pts)
}
#endif
-int BKE_ffmpeg_append(RenderData *rd, int start_frame, int frame, int *pixels, int rectx, int recty, ReportList *reports)
+int BKE_ffmpeg_append(void *context_v, RenderData *rd, int start_frame, int frame, int *pixels,
+ int rectx, int recty, const char *suffix, ReportList *reports)
{
+ FFMpegContext *context = context_v;
AVFrame *avframe;
int success = 1;
@@ -1148,111 +1177,103 @@ int BKE_ffmpeg_append(RenderData *rd, int start_frame, int frame, int *pixels, i
/* why is this done before writing the video frame and again at end_ffmpeg? */
// write_audio_frames(frame / (((double)rd->frs_sec) / rd->frs_sec_base));
- if (video_stream) {
- avframe = generate_video_frame((unsigned char *) pixels, reports);
- success = (avframe && write_video_frame(rd, frame - start_frame, avframe, reports));
+ if (context->video_stream) {
+ avframe = generate_video_frame(context, (unsigned char *) pixels, reports);
+ success = (avframe && write_video_frame(context, rd, frame - start_frame, avframe, reports));
- if (ffmpeg_autosplit) {
- if (avio_tell(outfile->pb) > FFMPEG_AUTOSPLIT_SIZE) {
- end_ffmpeg_impl(true);
- ffmpeg_autosplit_count++;
- success &= start_ffmpeg_impl(rd, rectx, recty, reports);
+ if (context->ffmpeg_autosplit) {
+ if (avio_tell(context->outfile->pb) > FFMPEG_AUTOSPLIT_SIZE) {
+ end_ffmpeg_impl(context, true);
+ context->ffmpeg_autosplit_count++;
+ success &= start_ffmpeg_impl(context, rd, rectx, recty, suffix, reports);
}
}
}
#ifdef WITH_AUDASPACE
- write_audio_frames((frame - rd->sfra) / (((double)rd->frs_sec) / (double)rd->frs_sec_base));
+ write_audio_frames(context, (frame - start_frame) / (((double)rd->frs_sec) / (double)rd->frs_sec_base));
#endif
return success;
}
-static void end_ffmpeg_impl(int is_autosplit)
+static void end_ffmpeg_impl(FFMpegContext *context, int is_autosplit)
{
unsigned int i;
PRINT("Closing ffmpeg...\n");
#if 0
- if (audio_stream) { /* SEE UPPER */
- write_audio_frames();
+ if (context->audio_stream) { /* SEE UPPER */
+ write_audio_frames(context);
}
#endif
#ifdef WITH_AUDASPACE
if (is_autosplit == false) {
- if (audio_mixdown_device) {
- AUD_closeReadDevice(audio_mixdown_device);
- audio_mixdown_device = 0;
+ if (context->audio_mixdown_device) {
+ AUD_Device_free(context->audio_mixdown_device);
+ context->audio_mixdown_device = 0;
}
}
#endif
- if (video_stream && video_stream->codec) {
+ if (context->video_stream && context->video_stream->codec) {
PRINT("Flushing delayed frames...\n");
- flush_ffmpeg();
+ flush_ffmpeg(context);
}
- if (outfile) {
- av_write_trailer(outfile);
+ if (context->outfile) {
+ av_write_trailer(context->outfile);
}
/* Close the video codec */
- if (video_stream && video_stream->codec) {
- avcodec_close(video_stream->codec);
- PRINT("zero video stream %p\n", video_stream);
- video_stream = 0;
+ if (context->video_stream && context->video_stream->codec) {
+ avcodec_close(context->video_stream->codec);
+ PRINT("zero video stream %p\n", context->video_stream);
+ context->video_stream = 0;
}
-
- /* Close the output file */
- if (outfile) {
- for (i = 0; i < outfile->nb_streams; i++) {
- if (&outfile->streams[i]) {
- av_freep(&outfile->streams[i]);
- }
- }
- }
/* free the temp buffer */
- if (current_frame) {
- delete_picture(current_frame);
- current_frame = 0;
+ if (context->current_frame) {
+ delete_picture(context->current_frame);
+ context->current_frame = 0;
}
- if (outfile && outfile->oformat) {
- if (!(outfile->oformat->flags & AVFMT_NOFILE)) {
- avio_close(outfile->pb);
+ if (context->outfile && context->outfile->oformat) {
+ if (!(context->outfile->oformat->flags & AVFMT_NOFILE)) {
+ avio_close(context->outfile->pb);
}
}
- if (outfile) {
- av_free(outfile);
- outfile = 0;
+ if (context->outfile) {
+ avformat_free_context(context->outfile);
+ context->outfile = 0;
}
- if (audio_input_buffer) {
- av_free(audio_input_buffer);
- audio_input_buffer = 0;
+ if (context->audio_input_buffer) {
+ av_free(context->audio_input_buffer);
+ context->audio_input_buffer = 0;
}
#ifndef FFMPEG_HAVE_ENCODE_AUDIO2
- if (audio_output_buffer) {
- av_free(audio_output_buffer);
- audio_output_buffer = 0;
+ if (context->audio_output_buffer) {
+ av_free(context->audio_output_buffer);
+ context->audio_output_buffer = 0;
}
#endif
- if (audio_deinterleave_buffer) {
- av_free(audio_deinterleave_buffer);
- audio_deinterleave_buffer = 0;
+ if (context->audio_deinterleave_buffer) {
+ av_free(context->audio_deinterleave_buffer);
+ context->audio_deinterleave_buffer = 0;
}
- if (img_convert_ctx) {
- sws_freeContext(img_convert_ctx);
- img_convert_ctx = 0;
+ if (context->img_convert_ctx) {
+ sws_freeContext(context->img_convert_ctx);
+ context->img_convert_ctx = 0;
}
}
-void BKE_ffmpeg_end(void)
+void BKE_ffmpeg_end(void *context_v)
{
- end_ffmpeg_impl(false);
+ FFMpegContext *context = context_v;
+ end_ffmpeg_impl(context, false);
}
/* properties */
@@ -1632,6 +1653,12 @@ bool BKE_ffmpeg_alpha_channel_is_supported(RenderData *rd)
if (codec == AV_CODEC_ID_PNG)
return true;
+ if (codec == AV_CODEC_ID_PNG)
+ return true;
+
+ if (codec == AV_CODEC_ID_HUFFYUV)
+ return true;
+
#ifdef FFMPEG_FFV1_ALPHA_SUPPORTED
if (codec == AV_CODEC_ID_FFV1)
return true;
@@ -1640,4 +1667,31 @@ bool BKE_ffmpeg_alpha_channel_is_supported(RenderData *rd)
return false;
}
-#endif
+void *BKE_ffmpeg_context_create(void)
+{
+ FFMpegContext *context;
+
+ /* new ffmpeg data struct */
+ context = MEM_callocN(sizeof(FFMpegContext), "new ffmpeg context");
+
+ context->ffmpeg_codec = AV_CODEC_ID_MPEG4;
+ context->ffmpeg_audio_codec = AV_CODEC_ID_NONE;
+ context->ffmpeg_video_bitrate = 1150;
+ context->ffmpeg_audio_bitrate = 128;
+ context->ffmpeg_gop_size = 12;
+ context->ffmpeg_autosplit = 0;
+ context->ffmpeg_autosplit_count = 0;
+ context->ffmpeg_preview = false;
+
+ return context;
+}
+
+void BKE_ffmpeg_context_free(void *context_v)
+{
+ FFMpegContext *context = context_v;
+ if (context) {
+ MEM_freeN(context);
+ }
+}
+
+#endif /* WITH_FFMPEG */
diff --git a/source/blender/blenkernel/intern/writeframeserver.c b/source/blender/blenkernel/intern/writeframeserver.c
index 746b99ffb52..212af76a7e8 100644
--- a/source/blender/blenkernel/intern/writeframeserver.c
+++ b/source/blender/blenkernel/intern/writeframeserver.c
@@ -66,12 +66,15 @@
#include "BKE_report.h"
#include "DNA_scene_types.h"
+#include "MEM_guardedalloc.h"
-static int sock;
-static int connsock;
-static int write_ppm;
-static int render_width;
-static int render_height;
+typedef struct FrameserverContext {
+ int sock;
+ int connsock;
+ int write_ppm;
+ int render_width;
+ int render_height;
+} FrameserverContext;
#if defined(_WIN32)
@@ -110,10 +113,11 @@ static int closesocket(int fd)
}
#endif
-int BKE_frameserver_start(struct Scene *scene, RenderData *UNUSED(rd), int rectx, int recty, ReportList *reports)
+int BKE_frameserver_start(void *context_v, struct Scene *scene, RenderData *UNUSED(rd), int rectx, int recty, ReportList *reports, bool UNUSED(preview), const char *UNUSED(suffix))
{
struct sockaddr_in addr;
int arg = 1;
+ FrameserverContext *context = context_v;
(void)scene; /* unused */
@@ -122,33 +126,33 @@ int BKE_frameserver_start(struct Scene *scene, RenderData *UNUSED(rd), int rectx
return 0;
}
- if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
+ if ((context->sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
shutdown_socket_system();
BKE_report(reports, RPT_ERROR, "Cannot open socket");
return 0;
}
- setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *) &arg, sizeof(arg));
+ setsockopt(context->sock, SOL_SOCKET, SO_REUSEADDR, (char *) &arg, sizeof(arg));
addr.sin_family = AF_INET;
addr.sin_port = htons(U.frameserverport);
addr.sin_addr.s_addr = INADDR_ANY;
- if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
+ if (bind(context->sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
shutdown_socket_system();
BKE_report(reports, RPT_ERROR, "Cannot bind to socket");
return 0;
}
- if (listen(sock, SOMAXCONN) < 0) {
+ if (listen(context->sock, SOMAXCONN) < 0) {
shutdown_socket_system();
BKE_report(reports, RPT_ERROR, "Cannot establish listen backlog");
return 0;
}
- connsock = -1;
+ context->connsock = -1;
- render_width = rectx;
- render_height = recty;
+ context->render_width = rectx;
+ context->render_height = recty;
return 1;
}
@@ -177,7 +181,7 @@ static char good_bye[] =
"<body><pre>\n"
"Render stopped. Goodbye</pre></body></html>";
-static int safe_write(char *s, int tosend)
+static int safe_write(const int connsock, char *s, int tosend)
{
int total = tosend;
do {
@@ -192,12 +196,12 @@ static int safe_write(char *s, int tosend)
return total;
}
-static int safe_puts(char *s)
+static int safe_puts(const int connsock, char *s)
{
- return safe_write(s, strlen(s));
+ return safe_write(connsock, s, strlen(s));
}
-static int handle_request(RenderData *rd, char *req)
+static int handle_request(FrameserverContext *context, RenderData *rd, char *req)
{
char *p;
char *path;
@@ -214,19 +218,19 @@ static int handle_request(RenderData *rd, char *req)
*p = 0;
- if (strcmp(path, "/index.html") == 0 || strcmp(path, "/") == 0) {
- safe_puts(index_page);
+ if (STREQ(path, "/index.html") || STREQ(path, "/")) {
+ safe_puts(context->connsock, index_page);
return -1;
}
- write_ppm = 0;
+ context->write_ppm = 0;
pathlen = strlen(path);
if (pathlen > 12 && memcmp(path, "/images/ppm/", 12) == 0) {
- write_ppm = 1;
+ context->write_ppm = 1;
return atoi(path + 12);
}
- if (strcmp(path, "/info.txt") == 0) {
+ if (STREQ(path, "/info.txt")) {
char buf[4096];
sprintf(buf,
@@ -241,24 +245,24 @@ static int handle_request(RenderData *rd, char *req)
"ratescale %d\n",
rd->sfra,
rd->efra,
- render_width,
- render_height,
+ context->render_width,
+ context->render_height,
rd->frs_sec,
1
);
- safe_puts(buf);
+ safe_puts(context->connsock, buf);
return -1;
}
- if (strcmp(path, "/close.txt") == 0) {
- safe_puts(good_bye);
+ if (STREQ(path, "/close.txt")) {
+ safe_puts(context->connsock, good_bye);
G.is_break = true; /* Abort render */
return -1;
}
return -1;
}
-int BKE_frameserver_loop(RenderData *rd, ReportList *UNUSED(reports))
+int BKE_frameserver_loop(void *context_v, RenderData *rd, ReportList *UNUSED(reports))
{
fd_set readfds;
struct timeval tv;
@@ -271,18 +275,20 @@ int BKE_frameserver_loop(RenderData *rd, ReportList *UNUSED(reports))
#endif
char buf[4096];
- if (connsock != -1) {
- closesocket(connsock);
- connsock = -1;
+ FrameserverContext *context = context_v;
+
+ if (context->connsock != -1) {
+ closesocket(context->connsock);
+ context->connsock = -1;
}
tv.tv_sec = 1;
tv.tv_usec = 0;
FD_ZERO(&readfds);
- FD_SET(sock, &readfds);
+ FD_SET(context->sock, &readfds);
- rval = select(sock + 1, &readfds, NULL, NULL, &tv);
+ rval = select(context->sock + 1, &readfds, NULL, NULL, &tv);
if (rval < 0) {
return -1;
}
@@ -293,19 +299,19 @@ int BKE_frameserver_loop(RenderData *rd, ReportList *UNUSED(reports))
socklen = sizeof(addr);
- if ((connsock = accept(sock, (struct sockaddr *)&addr, &socklen)) < 0) {
+ if ((context->connsock = accept(context->sock, (struct sockaddr *)&addr, &socklen)) < 0) {
return -1;
}
FD_ZERO(&readfds);
- FD_SET(connsock, &readfds);
+ FD_SET(context->connsock, &readfds);
for (;;) {
/* give 10 seconds for telnet testing... */
tv.tv_sec = 10;
tv.tv_usec = 0;
- rval = select(connsock + 1, &readfds, NULL, NULL, &tv);
+ rval = select(context->connsock + 1, &readfds, NULL, NULL, &tv);
if (rval > 0) {
break;
}
@@ -319,7 +325,7 @@ int BKE_frameserver_loop(RenderData *rd, ReportList *UNUSED(reports))
}
}
- len = recv(connsock, buf, sizeof(buf) - 1, 0);
+ len = recv(context->connsock, buf, sizeof(buf) - 1, 0);
if (len < 0) {
return -1;
@@ -327,13 +333,13 @@ int BKE_frameserver_loop(RenderData *rd, ReportList *UNUSED(reports))
buf[len] = 0;
- return handle_request(rd, buf);
+ return handle_request(context, rd, buf);
}
-static void serve_ppm(int *pixels, int rectx, int recty)
+static void serve_ppm(FrameserverContext *context, int *pixels, int rectx, int recty)
{
unsigned char *rendered_frame;
- unsigned char *row = (unsigned char *) malloc(render_width * 3);
+ unsigned char *row = (unsigned char *) malloc(context->render_width * 3);
int y;
char header[1024];
@@ -348,7 +354,7 @@ static void serve_ppm(int *pixels, int rectx, int recty)
"255\n",
rectx, recty);
- safe_puts(header);
+ safe_puts(context->connsock, header);
rendered_frame = (unsigned char *)pixels;
@@ -364,36 +370,54 @@ static void serve_ppm(int *pixels, int rectx, int recty)
target += 3;
src += 4;
}
- safe_write((char *)row, 3 * rectx);
+ safe_write(context->connsock, (char *)row, 3 * rectx);
}
free(row);
- closesocket(connsock);
- connsock = -1;
+ closesocket(context->connsock);
+ context->connsock = -1;
}
-int BKE_frameserver_append(RenderData *UNUSED(rd), int UNUSED(start_frame), int frame, int *pixels,
- int rectx, int recty, ReportList *UNUSED(reports))
+int BKE_frameserver_append(void *context_v, RenderData *UNUSED(rd), int UNUSED(start_frame), int frame, int *pixels,
+ int rectx, int recty, const char *UNUSED(suffix), ReportList *UNUSED(reports))
{
+ FrameserverContext *context = context_v;
+
fprintf(stderr, "Serving frame: %d\n", frame);
- if (write_ppm) {
- serve_ppm(pixels, rectx, recty);
+ if (context->write_ppm) {
+ serve_ppm(context, pixels, rectx, recty);
}
- if (connsock != -1) {
- closesocket(connsock);
- connsock = -1;
+ if (context->connsock != -1) {
+ closesocket(context->connsock);
+ context->connsock = -1;
}
return 1;
}
-void BKE_frameserver_end(void)
+void BKE_frameserver_end(void *context_v)
{
- if (connsock != -1) {
- closesocket(connsock);
- connsock = -1;
+ FrameserverContext *context = context_v;
+
+ if (context->connsock != -1) {
+ closesocket(context->connsock);
+ context->connsock = -1;
}
- closesocket(sock);
+ closesocket(context->sock);
shutdown_socket_system();
}
+void *BKE_frameserver_context_create(void)
+{
+ FrameserverContext *context = MEM_mallocN(sizeof(FrameserverContext), "Frameserver Context");
+ return context;
+}
+
+void BKE_frameserver_context_free(void *context_v)
+{
+ FrameserverContext *context = context_v;
+ if (context) {
+ MEM_freeN(context);
+ }
+}
+
#endif /* WITH_FRAMESERVER */
diff --git a/source/blender/blenkernel/tracking_private.h b/source/blender/blenkernel/tracking_private.h
index 6efa1533e3e..591ee4d0d01 100644
--- a/source/blender/blenkernel/tracking_private.h
+++ b/source/blender/blenkernel/tracking_private.h
@@ -95,4 +95,32 @@ void tracking_cameraIntrinscisOptionsFromTracking(struct MovieTracking *tracking
void tracking_trackingCameraFromIntrinscisOptions(struct MovieTracking *tracking,
const struct libmv_CameraIntrinsicsOptions *camera_intrinsics_options);
+struct libmv_TrackRegionOptions;
+
+void tracking_configure_tracker(const MovieTrackingTrack *track, float *mask,
+ struct libmv_TrackRegionOptions *options);
+
+struct MovieTrackingMarker *tracking_get_keyframed_marker(
+ struct MovieTrackingTrack *track,
+ int current_frame,
+ bool backwards);
+
+/*********************** Frame accessr *************************/
+
+struct libmv_FrameAccessor;
+
+#define MAX_ACCESSOR_CLIP 64
+typedef struct TrackingImageAccessor {
+ struct MovieCache *cache;
+ struct MovieClip *clips[MAX_ACCESSOR_CLIP];
+ int num_clips;
+ int start_frame;
+ struct libmv_FrameAccessor *libmv_accessor;
+} TrackingImageAccessor;
+
+TrackingImageAccessor *tracking_image_accessor_new(MovieClip *clips[MAX_ACCESSOR_CLIP],
+ int num_clips,
+ int start_frame);
+void tracking_image_accessor_destroy(TrackingImageAccessor *accessor);
+
#endif /* __TRACKING_PRIVATE_H__ */
diff --git a/source/blender/blenlib/BLI_array.h b/source/blender/blenlib/BLI_array.h
index 3a9d013f796..c645ff06c00 100644
--- a/source/blender/blenlib/BLI_array.h
+++ b/source/blender/blenlib/BLI_array.h
@@ -34,9 +34,10 @@
*/
/* -------------------------------------------------------------------- */
-/* internal defines */
+/** \name Internal defines
+ * \{ */
-/* this returns the entire size of the array, including any buffering. */
+/** this returns the entire size of the array, including any buffering. */
#define _bli_array_totalsize_dynamic(arr) ( \
((arr) == NULL) ? \
0 : \
@@ -53,7 +54,10 @@
_bli_array_totalsize_dynamic(arr)) \
)
-/* BLI_array.c
+/** \} */
+
+
+/** BLI_array.c
*
* Doing the realloc in a macro isn't so simple,
* so use a function the macros can use.
@@ -64,55 +68,62 @@ void _bli_array_grow_func(void **arr_p, const void *arr_static,
/* -------------------------------------------------------------------- */
-/* public defines */
-/* use sizeof(*(arr)) to ensure the array exists and is an array */
+/** \name Public defines
+ * \{ */
+
+/** use ``sizeof(*(arr))`` to ensure the array exists and is an array */
#define BLI_array_declare(arr) \
int _##arr##_count = ((void)(sizeof(*(arr))), 0); \
void *_##arr##_static = NULL
-/* this will use stack space, up to maxstatic array elements, before
+/**
+ * this will use stack space, up to maxstatic array elements, before
* switching to dynamic heap allocation */
#define BLI_array_staticdeclare(arr, maxstatic) \
int _##arr##_count = 0; \
char _##arr##_static[maxstatic * sizeof(*(arr))]
-/* this returns the logical size of the array, not including buffering. */
+/** returns the logical size of the array, not including buffering. */
#define BLI_array_count(arr) ((void)0, _##arr##_count)
-/* Grow the array by a fixed number of items.
+/**
+ * Grow the array by a fixed number of items.
*
* Allow for a large 'num' value when the new size is more than double
* to allocate the exact sized array. */
-#define BLI_array_grow_items(arr, num) (( \
+#define BLI_array_reserve(arr, num) (void)( \
(((void *)(arr) == NULL) && \
((void *)(_##arr##_static) != NULL) && \
/* don't add _##arr##_count below because it must be zero */ \
- (_bli_array_totalsize_static(arr) >= _##arr##_count + num)) ? \
+ (_bli_array_totalsize_static(arr) >= _##arr##_count + (num))) ? \
/* we have an empty array and a static var big enough */ \
(void)(arr = (void *)_##arr##_static) \
: \
/* use existing static array or allocate */ \
- (LIKELY(_bli_array_totalsize(arr) >= _##arr##_count + num) ? \
+ (LIKELY(_bli_array_totalsize(arr) >= _##arr##_count + (num)) ? \
(void)0 /* do nothing */ : \
_bli_array_grow_func((void **)&(arr), _##arr##_static, \
sizeof(*(arr)), _##arr##_count, num, \
"BLI_array." #arr)) \
- ), \
- /* increment the array count, all conditions above are accounted for. */ \
- (_##arr##_count += num))
+ )
-/* returns length of array */
-#define BLI_array_grow_one(arr) BLI_array_grow_items(arr, 1)
+/** returns length of array */
+#define BLI_array_grow_items(arr, num) \
+ (BLI_array_reserve(arr, num), (_##arr##_count += num))
-/* appends an item to the array. */
+#define BLI_array_grow_one(arr) \
+ BLI_array_grow_items(arr, 1)
+
+/** appends an item to the array. */
#define BLI_array_append(arr, item) ( \
(void) BLI_array_grow_one(arr), \
(void) (arr[_##arr##_count - 1] = item) \
)
-/* appends an item to the array and returns a pointer to the item in the array.
+/**
+ * appends an item to the array and returns a pointer to the item in the array.
* item is not a pointer, but actual data value.*/
#define BLI_array_append_r(arr, item) ( \
(void) BLI_array_grow_one(arr), \
@@ -120,9 +131,9 @@ void _bli_array_grow_func(void **arr_p, const void *arr_static,
(&arr[_##arr##_count - 1]) \
)
-#define BLI_array_reserve(arr, num) \
- BLI_array_grow_items(arr, num), (void)(_##arr##_count -= (num))
-
+/** appends (grows) & returns a pointer to the uninitialized memory */
+#define BLI_array_append_ret(arr) \
+ (BLI_array_reserve(arr, 1), &arr[(_##arr##_count++)])
#define BLI_array_free(arr) \
if (arr && (char *)arr != _##arr##_static) { \
@@ -136,28 +147,37 @@ void _bli_array_grow_func(void **arr_p, const void *arr_static,
NULL \
)
-/* resets the logical size of an array to zero, but doesn't
+/**
+ * resets the logical size of an array to zero, but doesn't
* free the memory. */
#define BLI_array_empty(arr) \
{ _##arr##_count = 0; } (void)0
-/* set the count of the array, doesn't actually increase the allocated array
+/**
+ * set the count of the array, doesn't actually increase the allocated array
* size. don't use this unless you know what you're doing. */
#define BLI_array_count_set(arr, count) \
{ _##arr##_count = (count); }(void)0
-/* only to prevent unused warnings */
+/** only to prevent unused warnings */
#define BLI_array_fake_user(arr) \
((void)_##arr##_count, \
(void)_##arr##_static)
+/** \} */
+
/* -------------------------------------------------------------------- */
-/* other useful defines
- * (unrelated to the main array macros) */
-/* not part of the 'API' but handy funcs,
- * same purpose as BLI_array_staticdeclare()
+/** \name Generic Array Utils
+ * other useful defines
+ * (unrelated to the main array macros)
+ *
+ * \{ */
+
+/**
+ * not part of the 'API' but handy funcs,
+ * same purpose as #BLI_array_staticdeclare()
* but use when the max size is known ahead of time */
#define BLI_array_fixedstack_declare(arr, maxstatic, realsize, allocstr) \
char _##arr##_static[maxstatic * sizeof(*(arr))]; \
@@ -172,17 +192,6 @@ void _bli_array_grow_func(void **arr_p, const void *arr_static,
MEM_freeN(arr); \
} (void)0
-
-void _bli_array_reverse(void *arr, unsigned int arr_len, size_t arr_stride);
-#define BLI_array_reverse(arr, arr_len) \
- _bli_array_reverse(arr, arr_len, sizeof(*(arr)))
-
-void _bli_array_wrap(void *arr, unsigned int arr_len, size_t arr_stride, int dir);
-#define BLI_array_wrap(arr, arr_len, dir) \
- _bli_array_wrap(arr, arr_len, sizeof(*(arr)), dir)
-
-int _bli_array_findindex(const void *arr, unsigned int arr_len, size_t arr_stride, const void *p);
-#define BLI_array_findindex(arr, arr_len, p) \
- _bli_array_findindex(arr, arr_len, sizeof(*(arr)), p)
+/** \} */
#endif /* __BLI_ARRAY_H__ */
diff --git a/source/blender/blenlib/BLI_array_utils.h b/source/blender/blenlib/BLI_array_utils.h
new file mode 100644
index 00000000000..ff7976dc701
--- /dev/null
+++ b/source/blender/blenlib/BLI_array_utils.h
@@ -0,0 +1,49 @@
+/*
+ * ***** 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_ARRAY_UTILS_H__
+#define __BLI_ARRAY_UTILS_H__
+
+/** \file BLI_array_utils.h
+ * \ingroup bli
+ * \brief Generic array manipulation API.
+ */
+
+void _bli_array_reverse(void *arr, unsigned int arr_len, size_t arr_stride);
+#define BLI_array_reverse(arr, arr_len) \
+ _bli_array_reverse(arr, arr_len, sizeof(*(arr)))
+
+void _bli_array_wrap(void *arr, unsigned int arr_len, size_t arr_stride, int dir);
+#define BLI_array_wrap(arr, arr_len, dir) \
+ _bli_array_wrap(arr, arr_len, sizeof(*(arr)), dir)
+
+void _bli_array_permute(
+ void *arr, const unsigned int arr_len, const size_t arr_stride,
+ const unsigned int *index, void *arr_temp);
+#define BLI_array_permute(arr, arr_len, order) \
+ _bli_array_permute(arr, arr_len, sizeof(*(arr)), order, NULL)
+#define BLI_array_permute_ex(arr, arr_len, index, arr_temp) \
+ _bli_array_permute(arr, arr_len, sizeof(*(arr)), order, arr_temp)
+
+int _bli_array_findindex(const void *arr, unsigned int arr_len, size_t arr_stride, const void *p);
+#define BLI_array_findindex(arr, arr_len, p) \
+ _bli_array_findindex(arr, arr_len, sizeof(*(arr)), p)
+
+#endif /* __BLI_ARRAY_UTILS_H__ */
diff --git a/source/blender/blenlib/BLI_astar.h b/source/blender/blenlib/BLI_astar.h
new file mode 100644
index 00000000000..5e9434a1d56
--- /dev/null
+++ b/source/blender/blenlib/BLI_astar.h
@@ -0,0 +1,107 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2014 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Bastien Montagne.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __BLI_ASTAR_H__
+#define __BLI_ASTAR_H__
+
+/** \file BLI_astar.h
+ * \ingroup bli
+ * \brief An implementation of the A* (AStar) algorithm to solve shortest path problem.
+ */
+
+#include "BLI_utildefines.h"
+
+#include "BLI_bitmap.h"
+
+/* -------------------------------------------------------------------- */
+
+typedef struct BLI_AStarGNLink {
+ int nodes[2];
+ float cost;
+
+ void *custom_data;
+} BLI_AStarGNLink;
+
+typedef struct BLI_AStarGNode {
+ struct ListBase neighbor_links;
+
+ void *custom_data;
+} BLI_AStarGNode;
+
+typedef struct BLI_AStarSolution {
+ /* Final 'most useful' data. */
+ int steps; /* Number of steps (i.e. walked links) in path (nodes num, including start and end, is steps + 1). */
+ int *prev_nodes; /* Store the path, in reversed order (from destination to source node), as indices. */
+ BLI_AStarGNLink **prev_links; /* Indices are nodes' ones, as prev_nodes, but they map to relevant link. */
+
+ void *custom_data;
+
+ /* Mostly runtime data. */
+ BLI_bitmap *done_nodes;
+ float *g_costs;
+ int *g_steps;
+
+ struct MemArena *mem; /* Memory arena. */
+} BLI_AStarSolution;
+
+typedef struct BLI_AStarGraph {
+ int node_num;
+ BLI_AStarGNode *nodes;
+
+ void *custom_data;
+
+ struct MemArena *mem; /* Memory arena. */
+} BLI_AStarGraph;
+
+void BLI_astar_node_init(BLI_AStarGraph *as_graph, const int node_index, void *custom_data);
+void BLI_astar_node_link_add(
+ BLI_AStarGraph *as_graph, const int node1_index, const int node2_index, const float cost, void *custom_data);
+int BLI_astar_node_link_other_node(BLI_AStarGNLink *lnk, const int idx);
+
+void BLI_astar_solution_init(BLI_AStarGraph *as_graph, BLI_AStarSolution *as_solution, void *custom_data);
+void BLI_astar_solution_clear(BLI_AStarSolution *as_solution);
+void BLI_astar_solution_free(BLI_AStarSolution *as_solution);
+
+/**
+ * Callback computing the current cost (distance) to next node, and the estimated overall cost to destination node
+ * (A* expects this estimation to always be less or equal than actual shortest path from next node to destination one).
+ *
+ * \param link the graph link between current node and next one.
+ * \param node_idx_curr current node index.
+ * \param node_idx_next next node index.
+ * \param node_idx_dst destination node index.
+ */
+typedef float (*astar_f_cost)(BLI_AStarGraph *as_graph, BLI_AStarSolution *as_solution, BLI_AStarGNLink *link,
+ const int node_idx_curr, const int node_idx_next, const int node_idx_dst);
+
+void BLI_astar_graph_init(BLI_AStarGraph *as_graph, const int node_num, void *custom_data);
+void BLI_astar_graph_free(BLI_AStarGraph *as_graph);
+bool BLI_astar_graph_solve(
+ BLI_AStarGraph *as_graph, const int node_index_src, const int node_index_dst, astar_f_cost f_cost_cb,
+ BLI_AStarSolution *r_solution, const int max_steps);
+
+#endif /* __BLI_ASTAR_H__ */
diff --git a/source/blender/blenlib/BLI_bitmap.h b/source/blender/blenlib/BLI_bitmap.h
index 5431785aa84..60fc143a447 100644
--- a/source/blender/blenlib/BLI_bitmap.h
+++ b/source/blender/blenlib/BLI_bitmap.h
@@ -47,7 +47,7 @@ typedef unsigned int BLI_bitmap;
/* size (in bytes) used to hold '_tot' bits */
#define BLI_BITMAP_SIZE(_tot) \
- (_BITMAP_NUM_BLOCKS(_tot) * sizeof(BLI_bitmap))
+ ((size_t)(_BITMAP_NUM_BLOCKS(_tot)) * sizeof(BLI_bitmap))
/* allocate memory for a bitmap with '_tot' bits; free
* with MEM_freeN() */
@@ -59,25 +59,30 @@ typedef unsigned int BLI_bitmap;
#define BLI_BITMAP_NEW_ALLOCA(_tot) \
((BLI_bitmap *)memset(alloca(BLI_BITMAP_SIZE(_tot)), 0, BLI_BITMAP_SIZE(_tot)))
+/* Allocate using given MemArena */
+#define BLI_BITMAP_NEW_MEMARENA(_mem, _tot) \
+ (CHECK_TYPE_INLINE(_mem, MemArena *), \
+ ((BLI_bitmap *)BLI_memarena_calloc(_mem, BLI_BITMAP_SIZE(_tot))))
+
/* get the value of a single bit at '_index' */
#define BLI_BITMAP_TEST(_bitmap, _index) \
- (CHECK_TYPE_INLINE(_bitmap, BLI_bitmap *), \
+ (CHECK_TYPE_ANY(_bitmap, BLI_bitmap *, const BLI_bitmap *), \
((_bitmap)[(_index) >> _BITMAP_POWER] & \
(1u << ((_index) & _BITMAP_MASK))))
#define BLI_BITMAP_TEST_BOOL(_bitmap, _index) \
- (CHECK_TYPE_INLINE(_bitmap, BLI_bitmap *), \
+ (CHECK_TYPE_ANY(_bitmap, BLI_bitmap *, const BLI_bitmap *), \
(BLI_BITMAP_TEST(_bitmap, _index) != 0))
/* set the value of a single bit at '_index' */
#define BLI_BITMAP_ENABLE(_bitmap, _index) \
- (CHECK_TYPE_INLINE(_bitmap, BLI_bitmap *), \
+ (CHECK_TYPE_ANY(_bitmap, BLI_bitmap *, const BLI_bitmap *), \
((_bitmap)[(_index) >> _BITMAP_POWER] |= \
(1u << ((_index) & _BITMAP_MASK))))
/* clear the value of a single bit at '_index' */
#define BLI_BITMAP_DISABLE(_bitmap, _index) \
- (CHECK_TYPE_INLINE(_bitmap, BLI_bitmap *), \
+ (CHECK_TYPE_ANY(_bitmap, BLI_bitmap *, const BLI_bitmap *), \
((_bitmap)[(_index) >> _BITMAP_POWER] &= \
~(1u << ((_index) & _BITMAP_MASK))))
@@ -91,6 +96,16 @@ typedef unsigned int BLI_bitmap;
BLI_BITMAP_DISABLE(_bitmap, _index); \
} (void)0
+/* set or clear the value of the whole bitmap (needs size info) */
+#define BLI_BITMAP_SET_ALL(_bitmap, _set, _tot) \
+ { \
+ CHECK_TYPE(_bitmap, BLI_bitmap *); \
+ if (_set) \
+ memset(_bitmap, UCHAR_MAX, BLI_BITMAP_SIZE(_tot)); \
+ else \
+ memset(_bitmap, 0, BLI_BITMAP_SIZE(_tot)); \
+ } (void)0
+
/* resize bitmap to have space for '_tot' bits */
#define BLI_BITMAP_RESIZE(_bitmap, _tot) \
{ \
diff --git a/source/blender/blenlib/BLI_blenlib.h b/source/blender/blenlib/BLI_blenlib.h
index 03b75975af4..06bbf29a223 100644
--- a/source/blender/blenlib/BLI_blenlib.h
+++ b/source/blender/blenlib/BLI_blenlib.h
@@ -58,7 +58,6 @@
#ifndef __BLI_BLENLIB_H__
#define __BLI_BLENLIB_H__
-struct ListBase;
#include <stdlib.h>
diff --git a/source/blender/blenlib/BLI_buffer.h b/source/blender/blenlib/BLI_buffer.h
index 9c4b4b00b24..4e5b61da532 100644
--- a/source/blender/blenlib/BLI_buffer.h
+++ b/source/blender/blenlib/BLI_buffer.h
@@ -29,7 +29,7 @@
* declared in since.
*
* Usage examples:
- * \code
+ * \code{.c}
* BLI_buffer_declare_static(int, my_int_array, BLI_BUFFER_NOP, 32);
*
* BLI_buffer_append(my_int_array, int, 42);
@@ -88,13 +88,15 @@ enum {
#define BLI_buffer_resize_data(buffer_, type_, new_count_) ( \
(BLI_buffer_resize(buffer_, new_count_), new_count_ ? BLI_buffer_array(buffer_, type_) : NULL))
-
-
#define BLI_buffer_append(buffer_, type_, val_) ( \
BLI_buffer_resize(buffer_, (buffer_)->count + 1), \
(BLI_buffer_at(buffer_, type_, (buffer_)->count - 1) = val_) \
)
+#define BLI_buffer_empty(buffer_) { \
+ (buffer_)->count = 0; \
+} (void)0
+
/* Never decreases the amount of memory allocated */
void BLI_buffer_resize(BLI_Buffer *buffer, int new_count);
diff --git a/source/blender/blenlib/BLI_callbacks.h b/source/blender/blenlib/BLI_callbacks.h
index 2f963cfac51..fdffbeb4c8d 100644
--- a/source/blender/blenlib/BLI_callbacks.h
+++ b/source/blender/blenlib/BLI_callbacks.h
@@ -25,7 +25,6 @@
#ifndef __BLI_CALLBACKS_H__
#define __BLI_CALLBACKS_H__
-struct bContext;
struct Main;
struct ID;
@@ -41,6 +40,7 @@ typedef enum {
BLI_CB_EVT_FRAME_CHANGE_POST,
BLI_CB_EVT_RENDER_PRE,
BLI_CB_EVT_RENDER_POST,
+ BLI_CB_EVT_RENDER_WRITE,
BLI_CB_EVT_RENDER_STATS,
BLI_CB_EVT_RENDER_INIT,
BLI_CB_EVT_RENDER_COMPLETE,
diff --git a/source/blender/blenlib/BLI_compiler_compat.h b/source/blender/blenlib/BLI_compiler_compat.h
index 10c0752c9a7..92928889c52 100644
--- a/source/blender/blenlib/BLI_compiler_compat.h
+++ b/source/blender/blenlib/BLI_compiler_compat.h
@@ -37,4 +37,16 @@
# include <malloc.h>
#endif
+#if defined(__cplusplus) && ((__cplusplus >= 201103L) || defined(_MSC_VER))
+# define HAS_CPP11_FEATURES
+#endif
+
+#if (defined(__GNUC__) || defined(__clang__)) && defined(HAS_CPP11_FEATURES)
+extern "C++" {
+ /* Some magic to be sure we don't have reference in the type. */
+ template<typename T> static inline T decltype_helper(T x) { return x; }
+# define typeof(x) decltype(decltype_helper(x))
+}
+#endif
+
#endif /* __BLI_COMPILER_COMPAT_H__ */
diff --git a/source/blender/blenlib/BLI_compiler_typecheck.h b/source/blender/blenlib/BLI_compiler_typecheck.h
index 551569b066d..b9fb3ebf47a 100644
--- a/source/blender/blenlib/BLI_compiler_typecheck.h
+++ b/source/blender/blenlib/BLI_compiler_typecheck.h
@@ -51,9 +51,9 @@
}))
#else
-# define CHECK_TYPE(var, type)
-# define CHECK_TYPE_PAIR(var_a, var_b)
-# define CHECK_TYPE_PAIR_INLINE(var_a, var_b) (void)0
+# define CHECK_TYPE(var, type) { EXPR_NOP(var); }(void)0
+# define CHECK_TYPE_PAIR(var_a, var_b) { (EXPR_NOP(var_a), EXPR_NOP(var_b)); }(void)0
+# define CHECK_TYPE_PAIR_INLINE(var_a, var_b) (EXPR_NOP(var_a), EXPR_NOP(var_b))
#endif
/* can be used in simple macros */
@@ -66,22 +66,27 @@
((void)(((type)0) != (0 ? (val) : ((type)0))))
#endif
-#define CHECK_TYPE_NONCONST(var) { \
- void *non_const = 0 ? (var) : NULL; \
- (void)non_const; \
-} (void)0
+#if defined(__GNUC__) || defined(__clang__)
+# define CHECK_TYPE_NONCONST(var) __extension__ ({ \
+ void *non_const = 0 ? (var) : NULL; \
+ (void)non_const; \
+})
+#else
+# define CHECK_TYPE_NONCONST(var) EXPR_NOP(var)
+#endif
+
/**
* CHECK_TYPE_ANY: handy macro, eg:
* ``CHECK_TYPE_ANY(var, Foo *, Bar *, Baz *)``
*
* excuse ridiculously long generated args.
- * <pre>
+ * \code{.py}
* for i in range(63):
* args = [(chr(ord('a') + (c % 26)) + (chr(ord('0') + (c // 26)))) for c in range(i + 1)]
* print("#define _VA_CHECK_TYPE_ANY%d(v, %s) \\" % (i + 2, ", ".join(args)))
* print(" ((void)_Generic((v), %s))" % (": 0, ".join(args) + ": 0"))
- * </pre>
+ * \endcode
*/
#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)
@@ -376,4 +381,303 @@
# define CHECK_TYPE_ANY(...) (void)0
#endif
+
+/**
+ * GENERIC_TYPE_ANY: handy macro to reuse a single expression for multiple types, eg:
+ *
+ * \code{.c}
+ * _Generic(value,
+ * GENERIC_TYPE_ANY(result_a, Foo *, Bar *, Baz *),
+ * GENERIC_TYPE_ANY(result_b, Spam *, Spaz *, Spot *),
+ * )
+ * \endcode
+ *
+ * excuse ridiculously long generated args.
+ * \code{.py}
+ * for i in range(63):
+ * args = [(chr(ord('a') + (c % 26)) + (chr(ord('0') + (c // 26)))) for c in range(i + 1)]
+ * print("#define _VA_GENERIC_TYPE_ANY%d(r, %s) \\" % (i + 2, ", ".join(args)))
+ * print(" %s: r " % (": r, ".join(args)))
+ * \endcode
+ */
+#define _VA_GENERIC_TYPE_ANY2(r, a0) \
+ a0: r
+#define _VA_GENERIC_TYPE_ANY3(r, a0, b0) \
+ a0: r, b0: r
+#define _VA_GENERIC_TYPE_ANY4(r, a0, b0, c0) \
+ a0: r, b0: r, c0: r
+#define _VA_GENERIC_TYPE_ANY5(r, a0, b0, c0, d0) \
+ a0: r, b0: r, c0: r, d0: r
+#define _VA_GENERIC_TYPE_ANY6(r, a0, b0, c0, d0, e0) \
+ a0: r, b0: r, c0: r, d0: r, e0: r
+#define _VA_GENERIC_TYPE_ANY7(r, a0, b0, c0, d0, e0, f0) \
+ a0: r, b0: r, c0: r, d0: r, e0: r, f0: r
+#define _VA_GENERIC_TYPE_ANY8(r, a0, b0, c0, d0, e0, f0, g0) \
+ a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r
+#define _VA_GENERIC_TYPE_ANY9(r, a0, b0, c0, d0, e0, f0, g0, h0) \
+ a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r
+#define _VA_GENERIC_TYPE_ANY10(r, a0, b0, c0, d0, e0, f0, g0, h0, i0) \
+ a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r
+#define _VA_GENERIC_TYPE_ANY11(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0) \
+ a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r
+#define _VA_GENERIC_TYPE_ANY12(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0) \
+ a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r
+#define _VA_GENERIC_TYPE_ANY13(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0) \
+ a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r
+#define _VA_GENERIC_TYPE_ANY14(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0) \
+ a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r
+#define _VA_GENERIC_TYPE_ANY15(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0) \
+ a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r
+#define _VA_GENERIC_TYPE_ANY16(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0) \
+ a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r
+#define _VA_GENERIC_TYPE_ANY17(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0) \
+ a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r
+#define _VA_GENERIC_TYPE_ANY18(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0) \
+ a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \
+ q0: r
+#define _VA_GENERIC_TYPE_ANY19(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0) \
+ a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \
+ q0: r, r0: r
+#define _VA_GENERIC_TYPE_ANY20(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0) \
+ a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \
+ q0: r, r0: r, s0: r
+#define _VA_GENERIC_TYPE_ANY21(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0) \
+ a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \
+ q0: r, r0: r, s0: r, t0: r
+#define _VA_GENERIC_TYPE_ANY22(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, \
+ u0) \
+ a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \
+ q0: r, r0: r, s0: r, t0: r, u0: r
+#define _VA_GENERIC_TYPE_ANY23(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, \
+ u0, v0) \
+ a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \
+ q0: r, r0: r, s0: r, t0: r, u0: r, v0: r
+#define _VA_GENERIC_TYPE_ANY24(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, \
+ u0, v0, w0) \
+ a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \
+ q0: r, r0: r, s0: r, t0: r, u0: r, v0: r, w0: r
+#define _VA_GENERIC_TYPE_ANY25(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, \
+ u0, v0, w0, x0) \
+ a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \
+ q0: r, r0: r, s0: r, t0: r, u0: r, v0: r, w0: r, x0: r
+#define _VA_GENERIC_TYPE_ANY26(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, \
+ u0, v0, w0, x0, y0) \
+ a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \
+ q0: r, r0: r, s0: r, t0: r, u0: r, v0: r, w0: r, x0: r, y0: r
+#define _VA_GENERIC_TYPE_ANY27(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, \
+ u0, v0, w0, x0, y0, z0) \
+ a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \
+ q0: r, r0: r, s0: r, t0: r, u0: r, v0: r, w0: r, x0: r, y0: r, z0: r
+#define _VA_GENERIC_TYPE_ANY28(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, \
+ u0, v0, w0, x0, y0, z0, a1) \
+ a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \
+ q0: r, r0: r, s0: r, t0: r, u0: r, v0: r, w0: r, x0: r, y0: r, z0: r, a1: r
+#define _VA_GENERIC_TYPE_ANY29(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, \
+ u0, v0, w0, x0, y0, z0, a1, b1) \
+ a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \
+ q0: r, r0: r, s0: r, t0: r, u0: r, v0: r, w0: r, x0: r, y0: r, z0: r, a1: r, b1: r
+#define _VA_GENERIC_TYPE_ANY30(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, \
+ u0, v0, w0, x0, y0, z0, a1, b1, c1) \
+ a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \
+ q0: r, r0: r, s0: r, t0: r, u0: r, v0: r, w0: r, x0: r, y0: r, z0: r, a1: r, b1: r, c1: r
+#define _VA_GENERIC_TYPE_ANY31(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, \
+ u0, v0, w0, x0, y0, z0, a1, b1, c1, d1) \
+ a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \
+ q0: r, r0: r, s0: r, t0: r, u0: r, v0: r, w0: r, x0: r, y0: r, z0: r, a1: r, b1: r, c1: r, d1: r
+#define _VA_GENERIC_TYPE_ANY32(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, \
+ u0, v0, w0, x0, y0, z0, a1, b1, c1, d1, e1) \
+ a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \
+ q0: r, r0: r, s0: r, t0: r, u0: r, v0: r, w0: r, x0: r, y0: r, z0: r, a1: r, b1: r, c1: r, d1: r, e1: r
+#define _VA_GENERIC_TYPE_ANY33(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, \
+ u0, v0, w0, x0, y0, z0, a1, b1, c1, d1, e1, f1) \
+ a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \
+ q0: r, r0: r, s0: r, t0: r, u0: r, v0: r, w0: r, x0: r, y0: r, z0: r, a1: r, b1: r, c1: r, d1: r, e1: r, f1: r
+#define _VA_GENERIC_TYPE_ANY34(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, \
+ u0, v0, w0, x0, y0, z0, a1, b1, c1, d1, e1, f1, g1) \
+ a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \
+ q0: r, r0: r, s0: r, t0: r, u0: r, v0: r, w0: r, x0: r, y0: r, z0: r, a1: r, b1: r, c1: r, d1: r, e1: r, f1: r, \
+ g1: r
+#define _VA_GENERIC_TYPE_ANY35(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, \
+ u0, v0, w0, x0, y0, z0, a1, b1, c1, d1, e1, f1, g1, h1) \
+ a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \
+ q0: r, r0: r, s0: r, t0: r, u0: r, v0: r, w0: r, x0: r, y0: r, z0: r, a1: r, b1: r, c1: r, d1: r, e1: r, f1: r, \
+ g1: r, h1: r
+#define _VA_GENERIC_TYPE_ANY36(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, \
+ u0, v0, w0, x0, y0, z0, a1, b1, c1, d1, e1, f1, g1, h1, i1) \
+ a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \
+ q0: r, r0: r, s0: r, t0: r, u0: r, v0: r, w0: r, x0: r, y0: r, z0: r, a1: r, b1: r, c1: r, d1: r, e1: r, f1: r, \
+ g1: r, h1: r, i1: r
+#define _VA_GENERIC_TYPE_ANY37(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, \
+ u0, v0, w0, x0, y0, z0, a1, b1, c1, d1, e1, f1, g1, h1, i1, j1) \
+ a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \
+ q0: r, r0: r, s0: r, t0: r, u0: r, v0: r, w0: r, x0: r, y0: r, z0: r, a1: r, b1: r, c1: r, d1: r, e1: r, f1: r, \
+ g1: r, h1: r, i1: r, j1: r
+#define _VA_GENERIC_TYPE_ANY38(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, \
+ u0, v0, w0, x0, y0, z0, a1, b1, c1, d1, e1, f1, g1, h1, i1, j1, k1) \
+ a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \
+ q0: r, r0: r, s0: r, t0: r, u0: r, v0: r, w0: r, x0: r, y0: r, z0: r, a1: r, b1: r, c1: r, d1: r, e1: r, f1: r, \
+ g1: r, h1: r, i1: r, j1: r, k1: r
+#define _VA_GENERIC_TYPE_ANY39(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, \
+ u0, v0, w0, x0, y0, z0, a1, b1, c1, d1, e1, f1, g1, h1, i1, j1, k1, l1) \
+ a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \
+ q0: r, r0: r, s0: r, t0: r, u0: r, v0: r, w0: r, x0: r, y0: r, z0: r, a1: r, b1: r, c1: r, d1: r, e1: r, f1: r, \
+ g1: r, h1: r, i1: r, j1: r, k1: r, l1: r
+#define _VA_GENERIC_TYPE_ANY40(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, \
+ u0, v0, w0, x0, y0, z0, a1, b1, c1, d1, e1, f1, g1, h1, i1, j1, k1, l1, m1) \
+ a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \
+ q0: r, r0: r, s0: r, t0: r, u0: r, v0: r, w0: r, x0: r, y0: r, z0: r, a1: r, b1: r, c1: r, d1: r, e1: r, f1: r, \
+ g1: r, h1: r, i1: r, j1: r, k1: r, l1: r, m1: r
+#define _VA_GENERIC_TYPE_ANY41(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, \
+ u0, v0, w0, x0, y0, z0, a1, b1, c1, d1, e1, f1, g1, h1, i1, j1, k1, l1, m1, n1) \
+ a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \
+ q0: r, r0: r, s0: r, t0: r, u0: r, v0: r, w0: r, x0: r, y0: r, z0: r, a1: r, b1: r, c1: r, d1: r, e1: r, f1: r, \
+ g1: r, h1: r, i1: r, j1: r, k1: r, l1: r, m1: r, n1: r
+#define _VA_GENERIC_TYPE_ANY42(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, \
+ u0, v0, w0, x0, y0, z0, a1, b1, c1, d1, e1, f1, g1, h1, i1, j1, k1, l1, m1, n1, o1) \
+ a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \
+ q0: r, r0: r, s0: r, t0: r, u0: r, v0: r, w0: r, x0: r, y0: r, z0: r, a1: r, b1: r, c1: r, d1: r, e1: r, f1: r, \
+ g1: r, h1: r, i1: r, j1: r, k1: r, l1: r, m1: r, n1: r, o1: r
+#define _VA_GENERIC_TYPE_ANY43(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, \
+ u0, v0, w0, x0, y0, z0, a1, b1, c1, d1, e1, f1, g1, h1, i1, j1, k1, l1, m1, n1, o1, p1) \
+ a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \
+ q0: r, r0: r, s0: r, t0: r, u0: r, v0: r, w0: r, x0: r, y0: r, z0: r, a1: r, b1: r, c1: r, d1: r, e1: r, f1: r, \
+ g1: r, h1: r, i1: r, j1: r, k1: r, l1: r, m1: r, n1: r, o1: r, p1: r
+#define _VA_GENERIC_TYPE_ANY44(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, \
+ u0, v0, w0, x0, y0, z0, a1, b1, c1, d1, e1, f1, g1, h1, i1, j1, k1, l1, m1, n1, o1, p1, q1) \
+ a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \
+ q0: r, r0: r, s0: r, t0: r, u0: r, v0: r, w0: r, x0: r, y0: r, z0: r, a1: r, b1: r, c1: r, d1: r, e1: r, f1: r, \
+ g1: r, h1: r, i1: r, j1: r, k1: r, l1: r, m1: r, n1: r, o1: r, p1: r, q1: r
+#define _VA_GENERIC_TYPE_ANY45(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, \
+ u0, v0, w0, x0, y0, z0, a1, b1, c1, d1, e1, f1, g1, h1, i1, j1, k1, l1, m1, n1, o1, p1, q1, r1) \
+ a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \
+ q0: r, r0: r, s0: r, t0: r, u0: r, v0: r, w0: r, x0: r, y0: r, z0: r, a1: r, b1: r, c1: r, d1: r, e1: r, f1: r, \
+ g1: r, h1: r, i1: r, j1: r, k1: r, l1: r, m1: r, n1: r, o1: r, p1: r, q1: r, r1: r
+#define _VA_GENERIC_TYPE_ANY46(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, \
+ u0, v0, w0, x0, y0, z0, a1, b1, c1, d1, e1, f1, g1, h1, i1, j1, k1, l1, m1, n1, o1, p1, q1, r1, s1) \
+ a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \
+ q0: r, r0: r, s0: r, t0: r, u0: r, v0: r, w0: r, x0: r, y0: r, z0: r, a1: r, b1: r, c1: r, d1: r, e1: r, f1: r, \
+ g1: r, h1: r, i1: r, j1: r, k1: r, l1: r, m1: r, n1: r, o1: r, p1: r, q1: r, r1: r, s1: r
+#define _VA_GENERIC_TYPE_ANY47(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, \
+ u0, v0, w0, x0, y0, z0, a1, b1, c1, d1, e1, f1, g1, h1, i1, j1, k1, l1, m1, n1, o1, p1, q1, r1, s1, t1) \
+ a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \
+ q0: r, r0: r, s0: r, t0: r, u0: r, v0: r, w0: r, x0: r, y0: r, z0: r, a1: r, b1: r, c1: r, d1: r, e1: r, f1: r, \
+ g1: r, h1: r, i1: r, j1: r, k1: r, l1: r, m1: r, n1: r, o1: r, p1: r, q1: r, r1: r, s1: r, t1: r
+#define _VA_GENERIC_TYPE_ANY48(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, \
+ u0, v0, w0, x0, y0, z0, a1, b1, c1, d1, e1, f1, g1, h1, i1, j1, k1, l1, m1, n1, o1, p1, q1, r1, s1, t1, u1) \
+ a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \
+ q0: r, r0: r, s0: r, t0: r, u0: r, v0: r, w0: r, x0: r, y0: r, z0: r, a1: r, b1: r, c1: r, d1: r, e1: r, f1: r, \
+ g1: r, h1: r, i1: r, j1: r, k1: r, l1: r, m1: r, n1: r, o1: r, p1: r, q1: r, r1: r, s1: r, t1: r, u1: r
+#define _VA_GENERIC_TYPE_ANY49(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, \
+ u0, v0, w0, x0, y0, z0, a1, b1, c1, d1, e1, f1, g1, h1, i1, j1, k1, l1, m1, n1, o1, p1, q1, r1, s1, t1, u1, v1) \
+ a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \
+ q0: r, r0: r, s0: r, t0: r, u0: r, v0: r, w0: r, x0: r, y0: r, z0: r, a1: r, b1: r, c1: r, d1: r, e1: r, f1: r, \
+ g1: r, h1: r, i1: r, j1: r, k1: r, l1: r, m1: r, n1: r, o1: r, p1: r, q1: r, r1: r, s1: r, t1: r, u1: r, v1: r
+#define _VA_GENERIC_TYPE_ANY50(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, \
+ u0, v0, w0, x0, y0, z0, a1, b1, c1, d1, e1, f1, g1, h1, i1, j1, k1, l1, m1, n1, o1, p1, q1, r1, s1, t1, u1, v1, \
+ w1) \
+ a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \
+ q0: r, r0: r, s0: r, t0: r, u0: r, v0: r, w0: r, x0: r, y0: r, z0: r, a1: r, b1: r, c1: r, d1: r, e1: r, f1: r, \
+ g1: r, h1: r, i1: r, j1: r, k1: r, l1: r, m1: r, n1: r, o1: r, p1: r, q1: r, r1: r, s1: r, t1: r, u1: r, v1: r, \
+ w1: r
+#define _VA_GENERIC_TYPE_ANY51(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, \
+ u0, v0, w0, x0, y0, z0, a1, b1, c1, d1, e1, f1, g1, h1, i1, j1, k1, l1, m1, n1, o1, p1, q1, r1, s1, t1, u1, v1, \
+ w1, x1) \
+ a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \
+ q0: r, r0: r, s0: r, t0: r, u0: r, v0: r, w0: r, x0: r, y0: r, z0: r, a1: r, b1: r, c1: r, d1: r, e1: r, f1: r, \
+ g1: r, h1: r, i1: r, j1: r, k1: r, l1: r, m1: r, n1: r, o1: r, p1: r, q1: r, r1: r, s1: r, t1: r, u1: r, v1: r, \
+ w1: r, x1: r
+#define _VA_GENERIC_TYPE_ANY52(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, \
+ u0, v0, w0, x0, y0, z0, a1, b1, c1, d1, e1, f1, g1, h1, i1, j1, k1, l1, m1, n1, o1, p1, q1, r1, s1, t1, u1, v1, \
+ w1, x1, y1) \
+ a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \
+ q0: r, r0: r, s0: r, t0: r, u0: r, v0: r, w0: r, x0: r, y0: r, z0: r, a1: r, b1: r, c1: r, d1: r, e1: r, f1: r, \
+ g1: r, h1: r, i1: r, j1: r, k1: r, l1: r, m1: r, n1: r, o1: r, p1: r, q1: r, r1: r, s1: r, t1: r, u1: r, v1: r, \
+ w1: r, x1: r, y1: r
+#define _VA_GENERIC_TYPE_ANY53(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, \
+ u0, v0, w0, x0, y0, z0, a1, b1, c1, d1, e1, f1, g1, h1, i1, j1, k1, l1, m1, n1, o1, p1, q1, r1, s1, t1, u1, v1, \
+ w1, x1, y1, z1) \
+ a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \
+ q0: r, r0: r, s0: r, t0: r, u0: r, v0: r, w0: r, x0: r, y0: r, z0: r, a1: r, b1: r, c1: r, d1: r, e1: r, f1: r, \
+ g1: r, h1: r, i1: r, j1: r, k1: r, l1: r, m1: r, n1: r, o1: r, p1: r, q1: r, r1: r, s1: r, t1: r, u1: r, v1: r, \
+ w1: r, x1: r, y1: r, z1: r
+#define _VA_GENERIC_TYPE_ANY54(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, \
+ u0, v0, w0, x0, y0, z0, a1, b1, c1, d1, e1, f1, g1, h1, i1, j1, k1, l1, m1, n1, o1, p1, q1, r1, s1, t1, u1, v1, \
+ w1, x1, y1, z1, a2) \
+ a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \
+ q0: r, r0: r, s0: r, t0: r, u0: r, v0: r, w0: r, x0: r, y0: r, z0: r, a1: r, b1: r, c1: r, d1: r, e1: r, f1: r, \
+ g1: r, h1: r, i1: r, j1: r, k1: r, l1: r, m1: r, n1: r, o1: r, p1: r, q1: r, r1: r, s1: r, t1: r, u1: r, v1: r, \
+ w1: r, x1: r, y1: r, z1: r, a2: r
+#define _VA_GENERIC_TYPE_ANY55(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, \
+ u0, v0, w0, x0, y0, z0, a1, b1, c1, d1, e1, f1, g1, h1, i1, j1, k1, l1, m1, n1, o1, p1, q1, r1, s1, t1, u1, v1, \
+ w1, x1, y1, z1, a2, b2) \
+ a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \
+ q0: r, r0: r, s0: r, t0: r, u0: r, v0: r, w0: r, x0: r, y0: r, z0: r, a1: r, b1: r, c1: r, d1: r, e1: r, f1: r, \
+ g1: r, h1: r, i1: r, j1: r, k1: r, l1: r, m1: r, n1: r, o1: r, p1: r, q1: r, r1: r, s1: r, t1: r, u1: r, v1: r, \
+ w1: r, x1: r, y1: r, z1: r, a2: r, b2: r
+#define _VA_GENERIC_TYPE_ANY56(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, \
+ u0, v0, w0, x0, y0, z0, a1, b1, c1, d1, e1, f1, g1, h1, i1, j1, k1, l1, m1, n1, o1, p1, q1, r1, s1, t1, u1, v1, \
+ w1, x1, y1, z1, a2, b2, c2) \
+ a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \
+ q0: r, r0: r, s0: r, t0: r, u0: r, v0: r, w0: r, x0: r, y0: r, z0: r, a1: r, b1: r, c1: r, d1: r, e1: r, f1: r, \
+ g1: r, h1: r, i1: r, j1: r, k1: r, l1: r, m1: r, n1: r, o1: r, p1: r, q1: r, r1: r, s1: r, t1: r, u1: r, v1: r, \
+ w1: r, x1: r, y1: r, z1: r, a2: r, b2: r, c2: r
+#define _VA_GENERIC_TYPE_ANY57(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, \
+ u0, v0, w0, x0, y0, z0, a1, b1, c1, d1, e1, f1, g1, h1, i1, j1, k1, l1, m1, n1, o1, p1, q1, r1, s1, t1, u1, v1, \
+ w1, x1, y1, z1, a2, b2, c2, d2) \
+ a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \
+ q0: r, r0: r, s0: r, t0: r, u0: r, v0: r, w0: r, x0: r, y0: r, z0: r, a1: r, b1: r, c1: r, d1: r, e1: r, f1: r, \
+ g1: r, h1: r, i1: r, j1: r, k1: r, l1: r, m1: r, n1: r, o1: r, p1: r, q1: r, r1: r, s1: r, t1: r, u1: r, v1: r, \
+ w1: r, x1: r, y1: r, z1: r, a2: r, b2: r, c2: r, d2: r
+#define _VA_GENERIC_TYPE_ANY58(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, \
+ u0, v0, w0, x0, y0, z0, a1, b1, c1, d1, e1, f1, g1, h1, i1, j1, k1, l1, m1, n1, o1, p1, q1, r1, s1, t1, u1, v1, \
+ w1, x1, y1, z1, a2, b2, c2, d2, e2) \
+ a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \
+ q0: r, r0: r, s0: r, t0: r, u0: r, v0: r, w0: r, x0: r, y0: r, z0: r, a1: r, b1: r, c1: r, d1: r, e1: r, f1: r, \
+ g1: r, h1: r, i1: r, j1: r, k1: r, l1: r, m1: r, n1: r, o1: r, p1: r, q1: r, r1: r, s1: r, t1: r, u1: r, v1: r, \
+ w1: r, x1: r, y1: r, z1: r, a2: r, b2: r, c2: r, d2: r, e2: r
+#define _VA_GENERIC_TYPE_ANY59(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, \
+ u0, v0, w0, x0, y0, z0, a1, b1, c1, d1, e1, f1, g1, h1, i1, j1, k1, l1, m1, n1, o1, p1, q1, r1, s1, t1, u1, v1, \
+ w1, x1, y1, z1, a2, b2, c2, d2, e2, f2) \
+ a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \
+ q0: r, r0: r, s0: r, t0: r, u0: r, v0: r, w0: r, x0: r, y0: r, z0: r, a1: r, b1: r, c1: r, d1: r, e1: r, f1: r, \
+ g1: r, h1: r, i1: r, j1: r, k1: r, l1: r, m1: r, n1: r, o1: r, p1: r, q1: r, r1: r, s1: r, t1: r, u1: r, v1: r, \
+ w1: r, x1: r, y1: r, z1: r, a2: r, b2: r, c2: r, d2: r, e2: r, f2: r
+#define _VA_GENERIC_TYPE_ANY60(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, \
+ u0, v0, w0, x0, y0, z0, a1, b1, c1, d1, e1, f1, g1, h1, i1, j1, k1, l1, m1, n1, o1, p1, q1, r1, s1, t1, u1, v1, \
+ w1, x1, y1, z1, a2, b2, c2, d2, e2, f2, g2) \
+ a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \
+ q0: r, r0: r, s0: r, t0: r, u0: r, v0: r, w0: r, x0: r, y0: r, z0: r, a1: r, b1: r, c1: r, d1: r, e1: r, f1: r, \
+ g1: r, h1: r, i1: r, j1: r, k1: r, l1: r, m1: r, n1: r, o1: r, p1: r, q1: r, r1: r, s1: r, t1: r, u1: r, v1: r, \
+ w1: r, x1: r, y1: r, z1: r, a2: r, b2: r, c2: r, d2: r, e2: r, f2: r, g2: r
+#define _VA_GENERIC_TYPE_ANY61(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, \
+ u0, v0, w0, x0, y0, z0, a1, b1, c1, d1, e1, f1, g1, h1, i1, j1, k1, l1, m1, n1, o1, p1, q1, r1, s1, t1, u1, v1, \
+ w1, x1, y1, z1, a2, b2, c2, d2, e2, f2, g2, h2) \
+ a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \
+ q0: r, r0: r, s0: r, t0: r, u0: r, v0: r, w0: r, x0: r, y0: r, z0: r, a1: r, b1: r, c1: r, d1: r, e1: r, f1: r, \
+ g1: r, h1: r, i1: r, j1: r, k1: r, l1: r, m1: r, n1: r, o1: r, p1: r, q1: r, r1: r, s1: r, t1: r, u1: r, v1: r, \
+ w1: r, x1: r, y1: r, z1: r, a2: r, b2: r, c2: r, d2: r, e2: r, f2: r, g2: r, h2: r
+#define _VA_GENERIC_TYPE_ANY62(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, \
+ u0, v0, w0, x0, y0, z0, a1, b1, c1, d1, e1, f1, g1, h1, i1, j1, k1, l1, m1, n1, o1, p1, q1, r1, s1, t1, u1, v1, \
+ w1, x1, y1, z1, a2, b2, c2, d2, e2, f2, g2, h2, i2) \
+ a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \
+ q0: r, r0: r, s0: r, t0: r, u0: r, v0: r, w0: r, x0: r, y0: r, z0: r, a1: r, b1: r, c1: r, d1: r, e1: r, f1: r, \
+ g1: r, h1: r, i1: r, j1: r, k1: r, l1: r, m1: r, n1: r, o1: r, p1: r, q1: r, r1: r, s1: r, t1: r, u1: r, v1: r, \
+ w1: r, x1: r, y1: r, z1: r, a2: r, b2: r, c2: r, d2: r, e2: r, f2: r, g2: r, h2: r, i2: r
+#define _VA_GENERIC_TYPE_ANY63(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, \
+ u0, v0, w0, x0, y0, z0, a1, b1, c1, d1, e1, f1, g1, h1, i1, j1, k1, l1, m1, n1, o1, p1, q1, r1, s1, t1, u1, v1, \
+ w1, x1, y1, z1, a2, b2, c2, d2, e2, f2, g2, h2, i2, j2) \
+ a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \
+ q0: r, r0: r, s0: r, t0: r, u0: r, v0: r, w0: r, x0: r, y0: r, z0: r, a1: r, b1: r, c1: r, d1: r, e1: r, f1: r, \
+ g1: r, h1: r, i1: r, j1: r, k1: r, l1: r, m1: r, n1: r, o1: r, p1: r, q1: r, r1: r, s1: r, t1: r, u1: r, v1: r, \
+ w1: r, x1: r, y1: r, z1: r, a2: r, b2: r, c2: r, d2: r, e2: r, f2: r, g2: r, h2: r, i2: r, j2: r
+#define _VA_GENERIC_TYPE_ANY64(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, \
+ u0, v0, w0, x0, y0, z0, a1, b1, c1, d1, e1, f1, g1, h1, i1, j1, k1, l1, m1, n1, o1, p1, q1, r1, s1, t1, u1, v1, \
+ w1, x1, y1, z1, a2, b2, c2, d2, e2, f2, g2, h2, i2, j2, k2) \
+ a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \
+ q0: r, r0: r, s0: r, t0: r, u0: r, v0: r, w0: r, x0: r, y0: r, z0: r, a1: r, b1: r, c1: r, d1: r, e1: r, f1: r, \
+ g1: r, h1: r, i1: r, j1: r, k1: r, l1: r, m1: r, n1: r, o1: r, p1: r, q1: r, r1: r, s1: r, t1: r, u1: r, v1: r, \
+ w1: r, x1: r, y1: r, z1: r, a2: r, b2: r, c2: r, d2: r, e2: r, f2: r, g2: r, h2: r, i2: r, j2: r, k2: r
+
+# define GENERIC_TYPE_ANY(...) VA_NARGS_CALL_OVERLOAD(_VA_GENERIC_TYPE_ANY, __VA_ARGS__)
+
#endif /* __BLI_COMPILER_TYPECHECK_H__ */
diff --git a/source/blender/blenlib/BLI_dial.h b/source/blender/blenlib/BLI_dial.h
index c8b57e803d2..ad7680fe03e 100644
--- a/source/blender/blenlib/BLI_dial.h
+++ b/source/blender/blenlib/BLI_dial.h
@@ -34,7 +34,8 @@
* current and previous directions of the digit, and returned to the user.
*
* Usage examples:
- * \code
+ *
+ * \code{.c}
* float start_position[2] = {0.0f, 0.0f};
* float current_position[2];
* float threshold = 0.5f;
@@ -46,7 +47,6 @@
* angle = BLI_dial_angle(dial, curent_position);
*
* MEM_freeN(dial);
- *
* \endcode
*/
diff --git a/source/blender/blenlib/BLI_edgehash.h b/source/blender/blenlib/BLI_edgehash.h
index a0455489d24..20272dd97cd 100644
--- a/source/blender/blenlib/BLI_edgehash.h
+++ b/source/blender/blenlib/BLI_edgehash.h
@@ -26,7 +26,6 @@
/** \file BLI_edgehash.h
* \ingroup bli
* \author Daniel Dunbar
- * \brief A general unordered 2-int pair hash table ADT.
*/
#include "BLI_compiler_attrs.h"
@@ -55,6 +54,10 @@ bool BLI_edgehash_reinsert(EdgeHash *eh, unsigned int v0, unsigned in
void *BLI_edgehash_lookup(EdgeHash *eh, unsigned int v0, unsigned int v1) ATTR_WARN_UNUSED_RESULT;
void *BLI_edgehash_lookup_default(EdgeHash *eh, unsigned int v0, unsigned int v1, void *val_default) ATTR_WARN_UNUSED_RESULT;
void **BLI_edgehash_lookup_p(EdgeHash *eh, unsigned int v0, unsigned int v1) ATTR_WARN_UNUSED_RESULT;
+bool BLI_edgehash_ensure_p(EdgeHash *eh, unsigned int v0, unsigned int v1, void ***r_val) ATTR_WARN_UNUSED_RESULT;
+bool BLI_edgehash_remove(EdgeHash *eh, unsigned int v0, unsigned int v1, EdgeHashFreeFP valfreefp);
+
+void *BLI_edgehash_popkey(EdgeHash *eh, unsigned int v0, unsigned int v1) ATTR_WARN_UNUSED_RESULT;
bool BLI_edgehash_haskey(EdgeHash *eh, unsigned int v0, unsigned int v1) ATTR_WARN_UNUSED_RESULT;
int BLI_edgehash_size(EdgeHash *eh) ATTR_WARN_UNUSED_RESULT;
void BLI_edgehash_clear_ex(EdgeHash *eh, EdgeHashFreeFP valfreefp,
diff --git a/source/blender/blenlib/BLI_endian_switch_inline.h b/source/blender/blenlib/BLI_endian_switch_inline.h
index 358206f1177..280503e9b93 100644
--- a/source/blender/blenlib/BLI_endian_switch_inline.h
+++ b/source/blender/blenlib/BLI_endian_switch_inline.h
@@ -42,9 +42,13 @@ BLI_INLINE void BLI_endian_switch_int16(short *val)
}
BLI_INLINE void BLI_endian_switch_uint16(unsigned short *val)
{
+#if (defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) >= 408)) /* gcc4.8+ only */
+ *val = __builtin_bswap16(*val);
+#else
unsigned short tval = *val;
*val = (tval >> 8) |
(tval << 8);
+#endif
}
@@ -55,11 +59,15 @@ BLI_INLINE void BLI_endian_switch_int32(int *val)
}
BLI_INLINE void BLI_endian_switch_uint32(unsigned int *val)
{
+#ifdef __GNUC__
+ *val = __builtin_bswap32(*val);
+#else
unsigned int tval = *val;
*val = ((tval >> 24)) |
((tval << 8) & 0x00ff0000) |
((tval >> 8) & 0x0000ff00) |
((tval << 24));
+#endif
}
BLI_INLINE void BLI_endian_switch_float(float *val)
{
@@ -74,6 +82,9 @@ BLI_INLINE void BLI_endian_switch_int64(int64_t *val)
}
BLI_INLINE void BLI_endian_switch_uint64(uint64_t *val)
{
+#ifdef __GNUC__
+ *val = __builtin_bswap64(*val);
+#else
uint64_t tval = *val;
*val = ((tval >> 56)) |
((tval << 40) & 0x00ff000000000000ll) |
@@ -83,6 +94,7 @@ BLI_INLINE void BLI_endian_switch_uint64(uint64_t *val)
((tval >> 24) & 0x0000000000ff0000ll) |
((tval >> 40) & 0x000000000000ff00ll) |
((tval << 56));
+#endif
}
BLI_INLINE void BLI_endian_switch_double(double *val)
{
diff --git a/source/blender/blenlib/BLI_fileops.h b/source/blender/blenlib/BLI_fileops.h
index 4f451a6c741..33dae45ac26 100644
--- a/source/blender/blenlib/BLI_fileops.h
+++ b/source/blender/blenlib/BLI_fileops.h
@@ -45,20 +45,23 @@ extern "C" {
#include <limits.h> /* for PATH_MAX */
+#include "BLI_compiler_attrs.h"
+
#ifndef PATH_MAX
# define PATH_MAX 4096
#endif
-struct gzFile;
/* Common */
-int BLI_exists(const char *path);
-int BLI_copy(const char *path, const char *to);
-int BLI_rename(const char *from, const char *to);
-int BLI_delete(const char *path, bool dir, bool recursive);
-int BLI_move(const char *path, const char *to);
-int BLI_create_symlink(const char *path, const char *to);
+int BLI_exists(const char *path) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+int BLI_copy(const char *path, const char *to) ATTR_NONNULL();
+int BLI_rename(const char *from, const char *to) ATTR_NONNULL();
+int BLI_delete(const char *path, bool dir, bool recursive) ATTR_NONNULL();
+#if 0 /* Unused */
+int BLI_move(const char *path, const char *to) ATTR_NONNULL();
+int BLI_create_symlink(const char *path, const char *to) ATTR_NONNULL();
+#endif
/* keep in sync with the definition of struct direntry in BLI_fileops_types.h */
#ifdef WIN32
@@ -73,7 +76,7 @@ typedef struct _stat BLI_stat_t;
typedef struct stat BLI_stat_t;
#endif
-int BLI_stat(const char *path, BLI_stat_t *buffer);
+int BLI_stat(const char *path, BLI_stat_t *buffer) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
#ifdef WIN32
int BLI_wstat(const wchar_t *path, BLI_stat_t *buffer);
#endif
@@ -82,38 +85,51 @@ int BLI_wstat(const wchar_t *path, BLI_stat_t *buffer);
struct direntry;
-bool BLI_is_dir(const char *path);
-bool BLI_is_file(const char *path);
-void BLI_dir_create_recursive(const char *dir);
-double BLI_dir_free_space(const char *dir);
-char *BLI_current_working_dir(char *dir, const size_t maxlen);
+bool BLI_is_dir(const char *path) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+bool BLI_is_file(const char *path) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+bool BLI_dir_create_recursive(const char *dir) ATTR_NONNULL();
+double BLI_dir_free_space(const char *dir) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+char *BLI_current_working_dir(char *dir, const size_t maxlen) ATTR_NONNULL();
+
+/* Filelist */
+
+unsigned int BLI_filelist_dir_contents(const char *dir, struct direntry **r_filelist);
+void BLI_filelist_entry_duplicate(struct direntry *dst, const struct direntry *src);
+void BLI_filelist_duplicate(
+ struct direntry **dest_filelist, struct direntry * const src_filelist, const unsigned int nrentries);
+void BLI_filelist_entry_free(struct direntry *entry);
+void BLI_filelist_free(struct direntry *filelist, const unsigned int nrentries);
-unsigned int BLI_dir_contents(const char *dir, struct direntry **filelist);
-void BLI_free_filelist(struct direntry *filelist, unsigned int nrentries);
+void BLI_filelist_entry_size_to_string(const struct stat *st, const uint64_t sz, const bool compact, char r_size[]);
+void BLI_filelist_entry_mode_to_string(
+ const struct stat *st, const bool compact, char r_mode1[], char r_mode2[], char r_mode3[]);
+void BLI_filelist_entry_owner_to_string(const struct stat *st, const bool compact, char r_owner[]);
+void BLI_filelist_entry_datetime_to_string(
+ const struct stat *st, const int64_t ts, const bool compact, char r_time[], char r_date[]);
/* Files */
-FILE *BLI_fopen(const char *filename, const char *mode);
-void *BLI_gzopen(const char *filename, const char *mode);
-int BLI_open(const char *filename, int oflag, int pmode);
-int BLI_access(const char *filename, int mode);
+FILE *BLI_fopen(const char *filename, const char *mode) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+void *BLI_gzopen(const char *filename, const char *mode) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+int BLI_open(const char *filename, int oflag, int pmode) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+int BLI_access(const char *filename, int mode) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-bool BLI_file_is_writable(const char *file);
-bool BLI_file_touch(const char *file);
+bool BLI_file_is_writable(const char *file) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+bool BLI_file_touch(const char *file) ATTR_NONNULL();
#if 0 /* UNUSED */
-int BLI_file_gzip(const char *from, const char *to);
+int BLI_file_gzip(const char *from, const char *to) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
#endif
-char *BLI_file_ungzip_to_mem(const char *from_file, int *r_size);
+char *BLI_file_ungzip_to_mem(const char *from_file, int *r_size) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-size_t BLI_file_descriptor_size(int file);
-size_t BLI_file_size(const char *file);
+size_t BLI_file_descriptor_size(int file) ATTR_WARN_UNUSED_RESULT;
+size_t BLI_file_size(const char *file) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
/* compare if one was last modified before the other */
-bool BLI_file_older(const char *file1, const char *file2);
+bool BLI_file_older(const char *file1, const char *file2) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
/* read ascii file as lines, empty list if reading fails */
-struct LinkNode *BLI_file_read_as_lines(const char *file);
+struct LinkNode *BLI_file_read_as_lines(const char *file) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
void BLI_file_free_lines(struct LinkNode *lines);
/* this weirdo pops up in two places ... */
diff --git a/source/blender/blenlib/BLI_fileops_types.h b/source/blender/blenlib/BLI_fileops_types.h
index 0e6eab687ad..0cf8c8ddb4a 100644
--- a/source/blender/blenlib/BLI_fileops_types.h
+++ b/source/blender/blenlib/BLI_fileops_types.h
@@ -39,12 +39,16 @@
typedef unsigned int mode_t;
#endif
-struct ImBuf;
+#define FILELIST_DIRENTRY_SIZE_LEN 16
+#define FILELIST_DIRENTRY_MODE_LEN 4
+#define FILELIST_DIRENTRY_OWNER_LEN 16
+#define FILELIST_DIRENTRY_TIME_LEN 8
+#define FILELIST_DIRENTRY_DATE_LEN 16
struct direntry {
mode_t type;
- char *relname;
- char *path;
+ const char *relname;
+ const char *path;
#ifdef WIN32 /* keep in sync with the definition of BLI_stat_t in BLI_fileops.h */
# if defined(_MSC_VER) || defined(__MINGW64__)
struct _stat64 s;
@@ -56,19 +60,6 @@ struct direntry {
#else
struct stat s;
#endif
- unsigned int flags;
- char size[16];
- char mode1[4];
- char mode2[4];
- char mode3[4];
- char owner[16];
- char time[8];
- char date[16];
- char extra[16];
- void *poin;
- int nr;
- struct ImBuf *image;
- unsigned int selflag; /* selection flag */
};
struct dirlink {
diff --git a/source/blender/blenlib/BLI_ghash.h b/source/blender/blenlib/BLI_ghash.h
index af2605894e3..a81fee2cdb7 100644
--- a/source/blender/blenlib/BLI_ghash.h
+++ b/source/blender/blenlib/BLI_ghash.h
@@ -30,7 +30,6 @@
/** \file BLI_ghash.h
* \ingroup bli
- * \brief A general (pointer -> pointer) hash table ADT
*/
#include "BLI_sys_types.h" /* for bool */
@@ -41,9 +40,12 @@ extern "C" {
#endif
typedef unsigned int (*GHashHashFP) (const void *key);
+/** returns false when equal */
typedef bool (*GHashCmpFP) (const void *a, const void *b);
typedef void (*GHashKeyFreeFP) (void *key);
typedef void (*GHashValFreeFP) (void *val);
+typedef void *(*GHashKeyCopyFP) (const void *key);
+typedef void *(*GHashValCopyFP) (const void *val);
typedef struct GHash GHash;
@@ -54,7 +56,13 @@ typedef struct GHashIterator {
} GHashIterator;
enum {
- GHASH_FLAG_ALLOW_DUPES = (1 << 0), /* only checked for in debug mode */
+ GHASH_FLAG_ALLOW_DUPES = (1 << 0), /* Only checked for in debug mode */
+ GHASH_FLAG_ALLOW_SHRINK = (1 << 1), /* Allow to shrink buckets' size. */
+
+#ifdef GHASH_INTERNAL_API
+ /* Internal usage only */
+ GHASH_FLAG_IS_GSET = (1 << 16), /* Whether the GHash is actually used as GSet (no value storage). */
+#endif
};
/* *** */
@@ -62,19 +70,24 @@ enum {
GHash *BLI_ghash_new_ex(GHashHashFP hashfp, GHashCmpFP cmpfp, const char *info,
const unsigned int nentries_reserve) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT;
GHash *BLI_ghash_new(GHashHashFP hashfp, GHashCmpFP cmpfp, const char *info) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT;
+GHash *BLI_ghash_copy(GHash *gh, GHashKeyCopyFP keycopyfp,
+ GHashValCopyFP valcopyfp) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT;
void BLI_ghash_free(GHash *gh, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp);
+void BLI_ghash_reserve(GHash *gh, const unsigned int nentries_reserve);
void BLI_ghash_insert(GHash *gh, void *key, void *val);
bool BLI_ghash_reinsert(GHash *gh, void *key, void *val, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp);
void *BLI_ghash_lookup(GHash *gh, const void *key) ATTR_WARN_UNUSED_RESULT;
void *BLI_ghash_lookup_default(GHash *gh, const void *key, void *val_default) ATTR_WARN_UNUSED_RESULT;
void **BLI_ghash_lookup_p(GHash *gh, const void *key) ATTR_WARN_UNUSED_RESULT;
-bool BLI_ghash_remove(GHash *gh, void *key, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp);
+bool BLI_ghash_ensure_p(GHash *gh, void *key, void ***r_val) ATTR_WARN_UNUSED_RESULT;
+bool BLI_ghash_ensure_p_ex(GHash *gh, const void *key, void ***r_val, GHashKeyCopyFP keycopyfp) ATTR_WARN_UNUSED_RESULT;
+bool BLI_ghash_remove(GHash *gh, const void *key, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp);
void BLI_ghash_clear(GHash *gh, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp);
void BLI_ghash_clear_ex(GHash *gh, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp,
const unsigned int nentries_reserve);
-void *BLI_ghash_popkey(GHash *gh, void *key, GHashKeyFreeFP keyfreefp) ATTR_WARN_UNUSED_RESULT;
+void *BLI_ghash_popkey(GHash *gh, const void *key, GHashKeyFreeFP keyfreefp) ATTR_WARN_UNUSED_RESULT;
bool BLI_ghash_haskey(GHash *gh, const void *key) ATTR_WARN_UNUSED_RESULT;
-int BLI_ghash_size(GHash *gh) ATTR_WARN_UNUSED_RESULT;
+unsigned int BLI_ghash_size(GHash *gh) ATTR_WARN_UNUSED_RESULT;
void BLI_ghash_flag_set(GHash *gh, unsigned int flag);
void BLI_ghash_flag_clear(GHash *gh, unsigned int flag);
@@ -124,26 +137,41 @@ bool BLI_ghashutil_ptrcmp(const void *a, const void *b);
unsigned int BLI_ghashutil_strhash_n(const char *key, size_t n);
#define BLI_ghashutil_strhash(key) ( \
- CHECK_TYPE_INLINE(key, char *), \
+ CHECK_TYPE_ANY(key, char *, const char *, const char * const), \
BLI_ghashutil_strhash_p(key))
unsigned int BLI_ghashutil_strhash_p(const void *key);
+unsigned int BLI_ghashutil_strhash_p_murmur(const void *key);
bool BLI_ghashutil_strcmp(const void *a, const void *b);
#define BLI_ghashutil_inthash(key) ( \
- CHECK_TYPE_INLINE(&(key), int *), \
+ CHECK_TYPE_ANY(&(key), int *, const int *), \
BLI_ghashutil_uinthash((unsigned int)key))
unsigned int BLI_ghashutil_uinthash(unsigned int key);
+unsigned int BLI_ghashutil_inthash_p(const void *ptr);
+unsigned int BLI_ghashutil_inthash_p_murmur(const void *ptr);
+unsigned int BLI_ghashutil_inthash_p_simple(const void *ptr);
+bool BLI_ghashutil_intcmp(const void *a, const void *b);
+
+
+unsigned int BLI_ghashutil_uinthash_v4(const unsigned int key[4]);
#define BLI_ghashutil_inthash_v4(key) ( \
- CHECK_TYPE_INLINE(key, int *), \
+ CHECK_TYPE_ANY(key, int *, const int *), \
BLI_ghashutil_uinthash_v4((const unsigned int *)key))
-unsigned int BLI_ghashutil_uinthash_v4(const unsigned int key[4]);
#define BLI_ghashutil_inthash_v4_p \
((GSetHashFP)BLI_ghashutil_uinthash_v4)
+#define BLI_ghashutil_uinthash_v4_p \
+ ((GSetHashFP)BLI_ghashutil_uinthash_v4)
+unsigned int BLI_ghashutil_uinthash_v4_murmur(const unsigned int key[4]);
+#define BLI_ghashutil_inthash_v4_murmur(key) ( \
+ CHECK_TYPE_ANY(key, int *, const int *), \
+ BLI_ghashutil_uinthash_v4_murmur((const unsigned int *)key))
+#define BLI_ghashutil_inthash_v4_p_murmur \
+ ((GSetHashFP)BLI_ghashutil_uinthash_v4_murmur)
+#define BLI_ghashutil_uinthash_v4_p_murmur \
+ ((GSetHashFP)BLI_ghashutil_uinthash_v4_murmur)
bool BLI_ghashutil_uinthash_v4_cmp(const void *a, const void *b);
#define BLI_ghashutil_inthash_v4_cmp \
BLI_ghashutil_uinthash_v4_cmp
-unsigned int BLI_ghashutil_inthash_p(const void *ptr);
-bool BLI_ghashutil_intcmp(const void *a, const void *b);
/** \} */
@@ -178,6 +206,7 @@ typedef struct GSet GSet;
typedef GHashHashFP GSetHashFP;
typedef GHashCmpFP GSetCmpFP;
typedef GHashKeyFreeFP GSetKeyFreeFP;
+typedef GHashKeyCopyFP GSetKeyCopyFP;
/* so we can cast but compiler sees as different */
typedef struct GSetIterator {
@@ -191,7 +220,8 @@ typedef struct GSetIterator {
GSet *BLI_gset_new_ex(GSetHashFP hashfp, GSetCmpFP cmpfp, const char *info,
const unsigned int nentries_reserve) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT;
GSet *BLI_gset_new(GSetHashFP hashfp, GSetCmpFP cmpfp, const char *info) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT;
-int BLI_gset_size(GSet *gs) ATTR_WARN_UNUSED_RESULT;
+GSet *BLI_gset_copy(GSet *gs, GSetKeyCopyFP keycopyfp) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT;
+unsigned int BLI_gset_size(GSet *gs) ATTR_WARN_UNUSED_RESULT;
void BLI_gset_flag_set(GSet *gs, unsigned int flag);
void BLI_gset_flag_clear(GSet *gs, unsigned int flag);
void BLI_gset_free(GSet *gs, GSetKeyFreeFP keyfreefp);
@@ -199,16 +229,16 @@ void BLI_gset_insert(GSet *gh, void *key);
bool BLI_gset_add(GSet *gs, void *key);
bool BLI_gset_reinsert(GSet *gh, void *key, GSetKeyFreeFP keyfreefp);
bool BLI_gset_haskey(GSet *gs, const void *key) ATTR_WARN_UNUSED_RESULT;
-bool BLI_gset_remove(GSet *gs, void *key, GSetKeyFreeFP keyfreefp);
+bool BLI_gset_remove(GSet *gs, const void *key, GSetKeyFreeFP keyfreefp);
void BLI_gset_clear_ex(GSet *gs, GSetKeyFreeFP keyfreefp,
const unsigned int nentries_reserve);
-void BLI_gset_clear(GSet *gs, GSetKeyFreeFP keyfreefp);
+void BLI_gset_clear(GSet *gs, GSetKeyFreeFP keyfreefp);
-GSet *BLI_gset_ptr_new_ex(const char *info,
- const unsigned int nentries_reserve) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT;
+GSet *BLI_gset_ptr_new_ex(const char *info, const unsigned int nentries_reserve) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT;
GSet *BLI_gset_ptr_new(const char *info);
-GSet *BLI_gset_pair_new_ex(const char *info,
- const unsigned int nentries_reserve) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT;
+GSet *BLI_gset_str_new_ex(const char *info, const unsigned int nentries_reserve) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT;
+GSet *BLI_gset_str_new(const char *info);
+GSet *BLI_gset_pair_new_ex(const char *info, const unsigned int nentries_reserve) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT;
GSet *BLI_gset_pair_new(const char *info) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT;
/* rely on inline api for now */
@@ -229,10 +259,22 @@ BLI_INLINE bool BLI_gsetIterator_done(GSetIterator *gsi) { return BLI_ghashItera
BLI_gsetIterator_done(&gs_iter_) == false; \
BLI_gsetIterator_step(&gs_iter_), i_++)
-#ifdef DEBUG
+
+/* For testing, debugging only */
+#ifdef GHASH_INTERNAL_API
+int BLI_ghash_buckets_size(GHash *gh);
+int BLI_gset_buckets_size(GSet *gs);
+
+double BLI_ghash_calc_quality_ex(
+ GHash *gh, double *r_load, double *r_variance,
+ double *r_prop_empty_buckets, double *r_prop_overloaded_buckets, int *r_biggest_bucket);
+double BLI_gset_calc_quality_ex(
+ GSet *gs, double *r_load, double *r_variance,
+ double *r_prop_empty_buckets, double *r_prop_overloaded_buckets, int *r_biggest_bucket);
double BLI_ghash_calc_quality(GHash *gh);
double BLI_gset_calc_quality(GSet *gs);
-#endif
+#endif /* GHASH_INTERNAL_API */
+
#ifdef __cplusplus
}
diff --git a/source/blender/blenlib/BLI_md5.h b/source/blender/blenlib/BLI_hash_md5.h
index 6a760f53e45..544ae753793 100644
--- a/source/blender/blenlib/BLI_md5.h
+++ b/source/blender/blenlib/BLI_hash_md5.h
@@ -18,30 +18,26 @@
* ***** END GPL LICENSE BLOCK *****
*/
-#ifndef __BLI_MD5_H__
-#define __BLI_MD5_H__
+#ifndef __BLI_HASH_MD5_H__
+#define __BLI_HASH_MD5_H__
-/** \file BLI_md5.h
+/** \file BLI_hash_md5.h
* \ingroup bli
*/
-#include <stdio.h>
-#include <stdlib.h>
-
/* Compute MD5 message digest for LEN bytes beginning at BUFFER. The
* result is always in little endian byte order, so that a byte-wise
* output yields to the wanted ASCII representation of the message
* digest. */
-void *md5_buffer(const char *buffer, size_t len, void *resblock);
+void *BLI_hash_md5_buffer(const char *buffer, size_t len, void *resblock);
/* Compute MD5 message digest for bytes read from STREAM. The
* resulting message digest number will be written into the 16 bytes
* beginning at RESBLOCK. */
-int md5_stream(FILE *stream, void *resblock);
-
-char *md5_to_hexdigest(void *resblock, char r_hex_digest[33]);
+int BLI_hash_md5_stream(FILE *stream, void *resblock);
-#endif
+char *BLI_hash_md5_to_hexdigest(void *resblock, char r_hex_digest[33]);
+#endif /* __BLI_HASH_MD5_H__ */
diff --git a/source/blender/blenlib/BLI_hash_mm2a.h b/source/blender/blenlib/BLI_hash_mm2a.h
new file mode 100644
index 00000000000..6beaf50ae8f
--- /dev/null
+++ b/source/blender/blenlib/BLI_hash_mm2a.h
@@ -0,0 +1,47 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __BLI_HASH_MM2A_H__
+#define __BLI_HASH_MM2A_H__
+
+/** \file BLI_hash_mm2a.h
+ * \ingroup bli
+ */
+
+#include "BLI_sys_types.h"
+
+typedef struct BLI_HashMurmur2A {
+ uint32_t hash;
+ uint32_t tail;
+ uint32_t count;
+ uint32_t size;
+} BLI_HashMurmur2A;
+
+void BLI_hash_mm2a_init(BLI_HashMurmur2A *mm2, uint32_t seed);
+
+void BLI_hash_mm2a_add(BLI_HashMurmur2A *mm2, const unsigned char *data, size_t len);
+
+void BLI_hash_mm2a_add_int(BLI_HashMurmur2A *mm2, int data);
+
+uint32_t BLI_hash_mm2a_end(BLI_HashMurmur2A *mm2);
+
+uint32_t BLI_hash_mm2(const unsigned char *data, size_t len, uint32_t seed);
+
+#endif /* __BLI_HASH_MM2A_H__ */
diff --git a/source/blender/blenlib/BLI_heap.h b/source/blender/blenlib/BLI_heap.h
index ac9edfd46a2..ea361097b7b 100644
--- a/source/blender/blenlib/BLI_heap.h
+++ b/source/blender/blenlib/BLI_heap.h
@@ -37,6 +37,7 @@ typedef void (*HeapFreeFP)(void *ptr);
* are recycled, so memory usage will not shrink. */
Heap *BLI_heap_new_ex(unsigned int tot_reserve) ATTR_WARN_UNUSED_RESULT;
Heap *BLI_heap_new(void) ATTR_WARN_UNUSED_RESULT;
+void BLI_heap_clear(Heap *heap, HeapFreeFP ptrfreefp) ATTR_NONNULL(1);
void BLI_heap_free(Heap *heap, HeapFreeFP ptrfreefp) ATTR_NONNULL(1);
/* Insert heap node with a value (often a 'cost') and pointer into the heap,
diff --git a/source/blender/blenlib/BLI_kdopbvh.h b/source/blender/blenlib/BLI_kdopbvh.h
index 49d072ddfdc..0c359c7f090 100644
--- a/source/blender/blenlib/BLI_kdopbvh.h
+++ b/source/blender/blenlib/BLI_kdopbvh.h
@@ -41,15 +41,13 @@ extern "C" {
struct BVHTree;
typedef struct BVHTree BVHTree;
+#define USE_KDOPBVH_WATERTIGHT
typedef struct BVHTreeOverlap {
int indexA;
int indexB;
} BVHTreeOverlap;
-/* flags */
-#define BVH_ONQUAD (1 << 0)
-
typedef struct BVHTreeNearest {
int index; /* the index of the nearest found (untouched if none is found within a dist radius from the given coordinates) */
float co[3]; /* nearest coordinates (untouched it none is found within a dist radius from the given coordinates) */
@@ -62,6 +60,9 @@ typedef struct BVHTreeRay {
float origin[3]; /* ray origin */
float direction[3]; /* ray direction */
float radius; /* radius around ray */
+#ifdef USE_KDOPBVH_WATERTIGHT
+ struct IsectRayPrecalc *isect_precalc;
+#endif
} BVHTreeRay;
typedef struct BVHTreeRayHit {
@@ -69,15 +70,23 @@ typedef struct BVHTreeRayHit {
float co[3]; /* coordinates of the hit point */
float no[3]; /* normal on hit point */
float dist; /* distance to the hit point */
- int flags;
} BVHTreeRayHit;
+enum {
+ /* calculate IsectRayPrecalc data */
+ BVH_RAYCAST_WATERTIGHT = (1 << 0),
+};
+#define BVH_RAYCAST_DEFAULT (BVH_RAYCAST_WATERTIGHT)
+
/* callback must update nearest in case it finds a nearest result */
typedef void (*BVHTree_NearestPointCallback)(void *userdata, int index, const float co[3], BVHTreeNearest *nearest);
/* callback must update hit in case it finds a nearest successful hit */
typedef void (*BVHTree_RayCastCallback)(void *userdata, int index, const BVHTreeRay *ray, BVHTreeRayHit *hit);
+/* callback to check if 2 nodes overlap (use thread if intersection results need to be stored) */
+typedef bool (*BVHTree_OverlapCallback)(void *userdata, int index_a, int index_b, int thread);
+
/* callback to range search query */
typedef void (*BVHTree_RangeQuery)(void *userdata, int index, float dist_sq);
@@ -92,8 +101,12 @@ void BLI_bvhtree_balance(BVHTree *tree);
bool BLI_bvhtree_update_node(BVHTree *tree, int index, const float co[3], const float co_moving[3], int numpoints);
void BLI_bvhtree_update_tree(BVHTree *tree);
+int BLI_bvhtree_overlap_thread_num(const BVHTree *tree);
+
/* collision/overlap: check two trees if they overlap, alloc's *overlap with length of the int return value */
-BVHTreeOverlap *BLI_bvhtree_overlap(BVHTree *tree1, BVHTree *tree2, unsigned int *r_overlap_tot);
+BVHTreeOverlap *BLI_bvhtree_overlap(
+ const BVHTree *tree1, const BVHTree *tree2, unsigned int *r_overlap_tot,
+ BVHTree_OverlapCallback callback, void *userdata);
float BLI_bvhtree_getepsilon(const BVHTree *tree);
@@ -102,8 +115,21 @@ float BLI_bvhtree_getepsilon(const BVHTree *tree);
int BLI_bvhtree_find_nearest(BVHTree *tree, const float co[3], BVHTreeNearest *nearest,
BVHTree_NearestPointCallback callback, void *userdata);
-int BLI_bvhtree_ray_cast(BVHTree *tree, const float co[3], const float dir[3], float radius, BVHTreeRayHit *hit,
- BVHTree_RayCastCallback callback, void *userdata);
+int BLI_bvhtree_ray_cast_ex(
+ BVHTree *tree, const float co[3], const float dir[3], float radius, BVHTreeRayHit *hit,
+ BVHTree_RayCastCallback callback, void *userdata,
+ int flag);
+int BLI_bvhtree_ray_cast(
+ BVHTree *tree, const float co[3], const float dir[3], float radius, BVHTreeRayHit *hit,
+ BVHTree_RayCastCallback callback, void *userdata);
+
+int BLI_bvhtree_ray_cast_all_ex(
+ BVHTree *tree, const float co[3], const float dir[3], float radius,
+ BVHTree_RayCastCallback callback, void *userdata,
+ int flag);
+int BLI_bvhtree_ray_cast_all(
+ BVHTree *tree, const float co[3], const float dir[3], float radius,
+ BVHTree_RayCastCallback callback, void *userdata);
float BLI_bvhtree_bb_raycast(const float bv[6], const float light_start[3], const float light_end[3], float pos[3]);
diff --git a/source/blender/blenlib/BLI_linklist.h b/source/blender/blenlib/BLI_linklist.h
index 2ca363ee780..67cb30e8d17 100644
--- a/source/blender/blenlib/BLI_linklist.h
+++ b/source/blender/blenlib/BLI_linklist.h
@@ -35,43 +35,59 @@
*
*/
+#include "BLI_compiler_attrs.h"
+
struct MemArena;
struct BLI_mempool;
typedef void (*LinkNodeFreeFP)(void *link);
typedef void (*LinkNodeApplyFP)(void *link, void *userdata);
-struct LinkNode;
typedef struct LinkNode {
struct LinkNode *next;
void *link;
} LinkNode;
-int BLI_linklist_length(struct LinkNode *list);
-int BLI_linklist_index(struct LinkNode *list, void *ptr);
+/**
+ * Use for append (single linked list, storing the last element).
+ *
+ * \note list manipulation functions don't operate on this struct.
+ * This is only to be used while appending.
+ */
+typedef struct LinkNodePair {
+ LinkNode *list, *last_node;
+} LinkNodePair;
+
+int BLI_linklist_count(LinkNode *list) ATTR_WARN_UNUSED_RESULT;
+int BLI_linklist_index(LinkNode *list, void *ptr) ATTR_WARN_UNUSED_RESULT;
+
+LinkNode *BLI_linklist_find(LinkNode *list, int index) ATTR_WARN_UNUSED_RESULT;
-struct LinkNode *BLI_linklist_find(struct LinkNode *list, int index);
+void BLI_linklist_reverse(LinkNode **listp) ATTR_NONNULL(1);
-void BLI_linklist_reverse(struct LinkNode **listp);
+void BLI_linklist_move_item(LinkNode **listp, int curr_index, int new_index) ATTR_NONNULL(1);
-void BLI_linklist_prepend_nlink(struct LinkNode **listp, void *ptr, struct LinkNode *nlink);
-void BLI_linklist_prepend(struct LinkNode **listp, void *ptr);
-void BLI_linklist_prepend_arena(struct LinkNode **listp, void *ptr, struct MemArena *ma);
-void BLI_linklist_prepend_pool(struct LinkNode **listp, void *ptr, struct BLI_mempool *mempool);
+void BLI_linklist_prepend_nlink(LinkNode **listp, void *ptr, LinkNode *nlink) ATTR_NONNULL(1, 3);
+void BLI_linklist_prepend(LinkNode **listp, void *ptr) ATTR_NONNULL(1);
+void BLI_linklist_prepend_arena(LinkNode **listp, void *ptr, struct MemArena *ma) ATTR_NONNULL(1, 3);
+void BLI_linklist_prepend_pool(LinkNode **listp, void *ptr, struct BLI_mempool *mempool) ATTR_NONNULL(1, 3);
-void BLI_linklist_append_nlink(LinkNode **listp, void *ptr, LinkNode *nlink);
-void BLI_linklist_append(struct LinkNode **listp, void *ptr);
-void BLI_linklist_append_arena(LinkNode **listp, void *ptr, struct MemArena *ma);
-void BLI_linklist_append_pool(LinkNode **listp, void *ptr, struct BLI_mempool *mempool);
+/* use LinkNodePair to avoid full search */
+void BLI_linklist_append_nlink(LinkNodePair *list_pair, void *ptr, LinkNode *nlink) ATTR_NONNULL(1, 3);
+void BLI_linklist_append(LinkNodePair *list_pair, void *ptr) ATTR_NONNULL(1);
+void BLI_linklist_append_arena(LinkNodePair *list_pair, void *ptr, struct MemArena *ma) ATTR_NONNULL(1, 3);
+void BLI_linklist_append_pool(LinkNodePair *list_pair, void *ptr, struct BLI_mempool *mempool) ATTR_NONNULL(1, 3);
-void *BLI_linklist_pop(struct LinkNode **listp);
-void *BLI_linklist_pop_pool(struct LinkNode **listp, struct BLI_mempool *mempool);
-void BLI_linklist_insert_after(struct LinkNode **listp, void *ptr);
+void *BLI_linklist_pop(LinkNode **listp) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1);
+void *BLI_linklist_pop_pool(LinkNode **listp, struct BLI_mempool *mempool) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1, 2);
+void BLI_linklist_insert_after(LinkNode **listp, void *ptr) ATTR_NONNULL(1);
-void BLI_linklist_free(struct LinkNode *list, LinkNodeFreeFP freefunc);
-void BLI_linklist_freeN(struct LinkNode *list);
-void BLI_linklist_free_pool(LinkNode *list, LinkNodeFreeFP freefunc, struct BLI_mempool *mempool);
-void BLI_linklist_apply(struct LinkNode *list, LinkNodeApplyFP applyfunc, void *userdata);
+void BLI_linklist_free(LinkNode *list, LinkNodeFreeFP freefunc);
+void BLI_linklist_freeN(LinkNode *list);
+void BLI_linklist_free_pool(LinkNode *list, LinkNodeFreeFP freefunc, struct BLI_mempool *mempool);
+void BLI_linklist_apply(LinkNode *list, LinkNodeApplyFP applyfunc, void *userdata);
+LinkNode *BLI_linklist_sort(LinkNode *list, int (*cmp)(const void *, const void *)) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(2);
+LinkNode *BLI_linklist_sort_r(LinkNode *list, int (*cmp)(void *, const void *, const void *), void *thunk) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(2);
#define BLI_linklist_prepend_alloca(listp, ptr) \
BLI_linklist_prepend_nlink(listp, ptr, alloca(sizeof(LinkNode)))
diff --git a/source/blender/blenlib/BLI_linklist_stack.h b/source/blender/blenlib/BLI_linklist_stack.h
index 17d40e068b3..c5f9be927d3 100644
--- a/source/blender/blenlib/BLI_linklist_stack.h
+++ b/source/blender/blenlib/BLI_linklist_stack.h
@@ -37,7 +37,7 @@
* \note These macros follow STACK_* macros defined in 'BLI_utildefines.h'
* and should be kept (mostly) interchangeable.
*
- * \note _##var##_type is a dummy var only used for typechecks.
+ * \note ``_##var##_type`` is a dummy variable only used for typechecks.
*/
/* -------------------------------------------------------------------- */
@@ -51,46 +51,46 @@
#define BLI_LINKSTACK_DECLARE(var, type) \
LinkNode *var; \
- BLI_mempool *_##var##_pool; \
- type _##var##_type
+ BLI_mempool *var##_pool_; \
+ type var##_type_
#define BLI_LINKSTACK_INIT(var) { \
var = NULL; \
- _##var##_pool = BLI_mempool_create(sizeof(LinkNode), 0, 64, BLI_MEMPOOL_NOP); \
+ var##_pool_ = BLI_mempool_create(sizeof(LinkNode), 0, 64, BLI_MEMPOOL_NOP); \
} (void)0
#define BLI_LINKSTACK_SIZE(var) \
- BLI_mempool_count(_##var##_pool)
+ BLI_mempool_count(var##_pool_)
/* check for typeof() */
#ifdef __GNUC__
#define BLI_LINKSTACK_PUSH(var, ptr) ( \
- CHECK_TYPE_INLINE(ptr, typeof(_##var##_type)), \
- BLI_linklist_prepend_pool(&(var), ptr, _##var##_pool))
+ CHECK_TYPE_INLINE(ptr, typeof(var##_type_)), \
+ BLI_linklist_prepend_pool(&(var), ptr, var##_pool_))
#define BLI_LINKSTACK_POP(var) \
- (var ? (typeof(_##var##_type))BLI_linklist_pop_pool(&(var), _##var##_pool) : NULL)
+ (var ? (typeof(var##_type_))BLI_linklist_pop_pool(&(var), var##_pool_) : NULL)
#define BLI_LINKSTACK_POP_DEFAULT(var, r) \
- (var ? (typeof(_##var##_type))BLI_linklist_pop_pool(&(var), _##var##_pool) : r)
+ (var ? (typeof(var##_type_))BLI_linklist_pop_pool(&(var), var##_pool_) : r)
#else /* non gcc */
#define BLI_LINKSTACK_PUSH(var, ptr) ( \
- BLI_linklist_prepend_pool(&(var), ptr, _##var##_pool))
+ BLI_linklist_prepend_pool(&(var), ptr, var##_pool_))
#define BLI_LINKSTACK_POP(var) \
- (var ? BLI_linklist_pop_pool(&(var), _##var##_pool) : NULL)
+ (var ? BLI_linklist_pop_pool(&(var), var##_pool_) : NULL)
#define BLI_LINKSTACK_POP_DEFAULT(var, r) \
- (var ? BLI_linklist_pop_pool(&(var), _##var##_pool) : r)
+ (var ? BLI_linklist_pop_pool(&(var), var##_pool_) : r)
#endif /* gcc check */
#define BLI_LINKSTACK_SWAP(var_a, var_b) { \
- CHECK_TYPE_PAIR(_##var_a##_type, _##var_b##_type); \
+ CHECK_TYPE_PAIR(var_a##_type_, var_b##_type_); \
SWAP(LinkNode *, var_a, var_b); \
- SWAP(BLI_mempool *, _##var_a##_pool, _##var_b##_pool); \
+ SWAP(BLI_mempool *, var_a##_pool_, var_b##_pool_); \
} (void)0
#define BLI_LINKSTACK_FREE(var) { \
- BLI_mempool_destroy(_##var##_pool); \
- _##var##_pool = NULL; (void)_##var##_pool; \
+ BLI_mempool_destroy(var##_pool_); \
+ var##_pool_ = NULL; (void)var##_pool_; \
var = NULL; (void)var; \
- (void)&(_##var##_type); \
+ (void)&(var##_type_); \
} (void)0
#include "BLI_linklist.h"
@@ -168,6 +168,16 @@
#define BLI_SMALLSTACK_IS_EMPTY(var) \
((_BLI_SMALLSTACK_CAST(var) _##var##_stack) == NULL)
+/* fill in a lookup table */
+#define BLI_SMALLSTACK_AS_TABLE(var, data) \
+{ \
+ LinkNode *_##var##_iter; \
+ unsigned int i; \
+ for (_##var##_iter = _##var##_stack, i = 0; _##var##_iter; _##var##_iter = _##var##_iter->next, i++) { \
+ (data)[i] = _BLI_SMALLSTACK_CAST(var) (_##var##_iter->link); \
+ } \
+} ((void)0)
+
/* loop over stack members last-added-first */
#define BLI_SMALLSTACK_ITER_BEGIN(var, item) \
{ \
diff --git a/source/blender/blenlib/BLI_listbase.h b/source/blender/blenlib/BLI_listbase.h
index fb388977ddf..9dfa80006de 100644
--- a/source/blender/blenlib/BLI_listbase.h
+++ b/source/blender/blenlib/BLI_listbase.h
@@ -67,12 +67,15 @@ void *BLI_poptail(ListBase *listbase) ATTR_NONNULL(1);
void BLI_addhead(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1);
void BLI_insertlinkbefore(struct ListBase *listbase, void *vnextlink, void *vnewlink) ATTR_NONNULL(1);
void BLI_insertlinkafter(struct ListBase *listbase, void *vprevlink, void *vnewlink) ATTR_NONNULL(1);
-void BLI_sortlist(struct ListBase *listbase, int (*cmp)(const void *, const void *)) ATTR_NONNULL(1, 2);
-void BLI_sortlist_r(ListBase *listbase, void *thunk, int (*cmp)(void *, const void *, const void *)) ATTR_NONNULL(1, 3);
+void BLI_listbase_sort(struct ListBase *listbase, int (*cmp)(const void *, const void *)) ATTR_NONNULL(1, 2);
+void BLI_listbase_sort_r(ListBase *listbase, int (*cmp)(void *, const void *, const void *), void *thunk) ATTR_NONNULL(1, 2);
void BLI_freelist(struct ListBase *listbase) ATTR_NONNULL(1);
-int BLI_countlist(const struct ListBase *listbase) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1);
+int BLI_listbase_count_ex(const struct ListBase *listbase, const int count_max) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1);
+int BLI_listbase_count(const struct ListBase *listbase) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1);
void BLI_freelinkN(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1);
+void BLI_listbase_swaplinks(struct ListBase *listbase, void *vlinka, void *vlinkb) ATTR_NONNULL(1, 2);
+
void BLI_movelisttolist(struct ListBase *dst, struct ListBase *src) ATTR_NONNULL(1, 2);
void BLI_duplicatelist(struct ListBase *dst, const struct ListBase *src) ATTR_NONNULL(1, 2);
void BLI_listbase_reverse(struct ListBase *lb) ATTR_NONNULL(1);
diff --git a/source/blender/blenlib/BLI_math.h b/source/blender/blenlib/BLI_math.h
index db2fed433da..ec3fbdc9bfc 100644
--- a/source/blender/blenlib/BLI_math.h
+++ b/source/blender/blenlib/BLI_math.h
@@ -30,18 +30,32 @@
* \ingroup bli
* \section mathabbrev Abbreviations
*
- * - fl = float
- * - db = double
- * - v2 = vec2 = vector 2
- * - v3 = vec3 = vector 3
- * - v4 = vec4 = vector 4
- * - qt = quat = quaternion
- * - dq = dquat = dual quaternion
- * - m2 = mat2 = matrix 2x2
- * - m3 = mat3 = matrix 3x3
- * - m4 = mat4 = matrix 4x4
- * - eul = euler rotation
- * - eulO = euler with order
+ * - ``fl`` = float
+ * - ``db`` = double
+ * - ``v2`` = vec2 = vector 2
+ * - ``v3`` = vec3 = vector 3
+ * - ``v4`` = vec4 = vector 4
+ * - ``vn`` = vec4 = vector N dimensions, *passed as an arg, after the vector*.
+ * - ``qt`` = quat = quaternion
+ * - ``dq`` = dquat = dual quaternion
+ * - ``m2`` = mat2 = matrix 2x2
+ * - ``m3`` = mat3 = matrix 3x3
+ * - ``m4`` = mat4 = matrix 4x4
+ * - ``eul`` = euler rotation
+ * - ``eulO`` = euler with order
+ * - ``plane`` = plane 4, (vec3, distance)
+ * - ``plane3`` = plane 3 (same as a ``plane`` with a zero 4th component)
+ *
+ * \subsection mathabbrev_all Function Type Abbreviations
+ *
+ * For non float versions of functions (which typically operate on floats),
+ * use single suffix abbreviations.
+ *
+ * - ``_d`` = double
+ * - ``_i`` = int
+ * - ``_u`` = unsigned int
+ * - ``_char`` = char
+ * - ``_uchar`` = unsigned char
*
* \section mathvarnames Variable Names
*
@@ -59,6 +73,7 @@
#include "BLI_math_vector.h"
#include "BLI_math_geom.h"
#include "BLI_math_interp.h"
+#include "BLI_math_solvers.h"
+#include "BLI_math_statistics.h"
#endif /* __BLI_MATH_H__ */
-
diff --git a/source/blender/blenlib/BLI_math_base.h b/source/blender/blenlib/BLI_math_base.h
index 5f94f04e0a8..20b76354f58 100644
--- a/source/blender/blenlib/BLI_math_base.h
+++ b/source/blender/blenlib/BLI_math_base.h
@@ -42,37 +42,43 @@
#endif
#ifndef M_PI
-#define M_PI 3.14159265358979323846
+#define M_PI 3.14159265358979323846 /* pi */
#endif
#ifndef M_PI_2
-#define M_PI_2 1.57079632679489661923
+#define M_PI_2 1.57079632679489661923 /* pi/2 */
+#endif
+#ifndef M_PI_4
+#define M_PI_4 0.78539816339744830962 /* pi/4 */
#endif
#ifndef M_SQRT2
-#define M_SQRT2 1.41421356237309504880
+#define M_SQRT2 1.41421356237309504880 /* sqrt(2) */
#endif
#ifndef M_SQRT1_2
-#define M_SQRT1_2 0.70710678118654752440
+#define M_SQRT1_2 0.70710678118654752440 /* 1/sqrt(2) */
#endif
#ifndef M_SQRT3
-#define M_SQRT3 1.7320508075688772
+#define M_SQRT3 1.73205080756887729352 /* sqrt(3) */
+#endif
+#ifndef M_SQRT1_3
+#define M_SQRT1_3 0.57735026918962576450 /* 1/sqrt(3) */
#endif
#ifndef M_1_PI
-#define M_1_PI 0.318309886183790671538
+#define M_1_PI 0.318309886183790671538 /* 1/pi */
#endif
#ifndef M_E
-#define M_E 2.7182818284590452354
+#define M_E 2.7182818284590452354 /* e */
#endif
#ifndef M_LOG2E
-#define M_LOG2E 1.4426950408889634074
+#define M_LOG2E 1.4426950408889634074 /* log_2 e */
#endif
#ifndef M_LOG10E
-#define M_LOG10E 0.43429448190325182765
+#define M_LOG10E 0.43429448190325182765 /* log_10 e */
#endif
#ifndef M_LN2
-#define M_LN2 0.69314718055994530942
+#define M_LN2 0.69314718055994530942 /* log_e 2 */
#endif
#ifndef M_LN10
-#define M_LN10 2.30258509299404568402
+#define M_LN10 2.30258509299404568402 /* log_e 10 */
#endif
#if defined(__GNUC__)
@@ -83,8 +89,8 @@ static const int NAN_INT = 0x7FC00000;
# define NAN_FLT (*((float *)(&NAN_INT)))
#endif
-/* do not redefine functions from C99 or POSIX.1-2001 */
-#if !(defined(_ISOC99_SOURCE) || (defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 200112L))
+/* do not redefine functions from C99, POSIX.1-2001 or MSVC12 (partial C99) */
+#if !(defined(_ISOC99_SOURCE) || (defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 200112L) || defined(_MSC_VER))
#ifndef sqrtf
#define sqrtf(a) ((float)sqrt(a))
@@ -138,7 +144,7 @@ static const int NAN_INT = 0x7FC00000;
#define copysignf(a, b) ((float)copysign(a, b))
#endif
-#endif /* C99 or POSIX.1-2001 */
+#endif /* C99, POSIX.1-2001 or MSVC12 (partial C99) */
#ifdef WIN32
# if defined(_MSC_VER)
@@ -146,32 +152,6 @@ static const int NAN_INT = 0x7FC00000;
# endif
#endif
-/* Causes warning:
- * incompatible types when assigning to type 'Foo' from type 'Bar'
- * ... the compiler optimizes away the temp var */
-#ifndef CHECK_TYPE
-#ifdef __GNUC__
-#define CHECK_TYPE(var, type) { \
- typeof(var) *__tmp; \
- __tmp = (type *)NULL; \
- (void)__tmp; \
-} (void)0
-#else
-#define CHECK_TYPE(var, type)
-#endif
-#endif
-
-#ifndef SWAP
-# define SWAP(type, a, b) { \
- type sw_ap; \
- CHECK_TYPE(a, type); \
- CHECK_TYPE(b, type); \
- sw_ap = (a); \
- (a) = (b); \
- (b) = sw_ap; \
-} (void)0
-#endif
-
#if BLI_MATH_DO_INLINE
#include "intern/math_base_inline.c"
#endif
@@ -183,6 +163,11 @@ static const int NAN_INT = 0x7FC00000;
/******************************* Float ******************************/
+MINLINE float pow2f(float x);
+MINLINE float pow3f(float x);
+MINLINE float pow4f(float x);
+MINLINE float pow7f(float x);
+
MINLINE float sqrt3f(float f);
MINLINE double sqrt3d(double d);
@@ -211,7 +196,12 @@ 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 int compare_ff(float a, float b, const float max_diff);
+MINLINE int compare_ff_relative(float a, float b, const float max_diff, const int max_ulps);
+
MINLINE float signf(float f);
+MINLINE int signum_i_ex(float a, float eps);
+MINLINE int signum_i(float a);
MINLINE float power_of_2(float f);
@@ -227,9 +217,7 @@ MINLINE int iroundf(float a);
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);
-
+int pow_i(int base, int exp);
double double_round(double x, int ndigits);
#ifdef BLI_MATH_GCC_WARN_PRAGMA
diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_streamShader.h b/source/blender/blenlib/BLI_math_bits.h
index 047ff4b58b5..1ac98a682d1 100644
--- a/source/blender/freestyle/intern/python/StrokeShader/BPy_streamShader.h
+++ b/source/blender/blenlib/BLI_math_bits.h
@@ -16,38 +16,42 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* ***** END GPL LICENSE BLOCK *****
- */
-
-/** \file source/blender/freestyle/intern/python/StrokeShader/BPy_streamShader.h
- * \ingroup freestyle
- */
+ * */
-#ifndef __FREESTYLE_PYTHON_STREAMSHADER_H__
-#define __FREESTYLE_PYTHON_STREAMSHADER_H__
+#ifndef __BLI_MATH_BITS_H__
+#define __BLI_MATH_BITS_H__
-#include "../BPy_StrokeShader.h"
+/** \file BLI_math_bits.h
+ * \ingroup bli
+ */
#ifdef __cplusplus
extern "C" {
#endif
-///////////////////////////////////////////////////////////////////////////////////////////
+#include "BLI_math_inline.h"
-extern PyTypeObject streamShader_Type;
+MINLINE unsigned int highest_order_bit_i(unsigned int n);
+MINLINE unsigned short highest_order_bit_s(unsigned short n);
-#define BPy_streamShader_Check(v) (PyObject_IsInstance((PyObject *)v, (PyObject *)&streamShader_Type))
-
-/*---------------------------Python BPy_streamShader structure definition----------*/
-typedef struct {
- BPy_StrokeShader py_ss;
-} BPy_streamShader;
+#ifdef __GNUC__
+# define count_bits_i(i) __builtin_popcount(i)
+#else
+MINLINE int count_bits_i(unsigned int n);
+#endif
+MINLINE int float_as_int(float f);
+MINLINE unsigned int float_as_uint(float f);
+MINLINE float int_as_float(int i);
+MINLINE float uint_as_float(unsigned int i);
+MINLINE float xor_fl(float x, int y);
-///////////////////////////////////////////////////////////////////////////////////////////
+#if BLI_MATH_DO_INLINE
+#include "intern/math_bits_inline.c"
+#endif
#ifdef __cplusplus
}
#endif
-
-#endif /* __FREESTYLE_PYTHON_STREAMSHADER_H__ */
+#endif /* __BLI_MATH_BITS_H__ */
diff --git a/source/blender/blenlib/BLI_math_color.h b/source/blender/blenlib/BLI_math_color.h
index 5c14ac55492..d70dfcd9e58 100644
--- a/source/blender/blenlib/BLI_math_color.h
+++ b/source/blender/blenlib/BLI_math_color.h
@@ -80,18 +80,8 @@ 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);
-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 *****************/
-void gamma_correct(float *c, float gamma);
-float rec709_to_linearrgb(float c);
-float linearrgb_to_rec709(float c);
float srgb_to_linearrgb(float c);
float linearrgb_to_srgb(float c);
@@ -139,8 +129,15 @@ void rgba_float_to_uchar(unsigned char r_col[4], const float col_f[4]);
void xyz_to_lab(float x, float y, float z, float *l, float *a, float *b);
+MINLINE float rgb_to_grayscale(const float rgb[3]);
+MINLINE unsigned char rgb_to_grayscale_byte(const unsigned char rgb[3]);
+
MINLINE int compare_rgb_uchar(const unsigned char a[3], const unsigned char b[3], const int limit);
+MINLINE float dither_random_value(float s, float t);
+MINLINE void float_to_byte_dither_v3(unsigned char b[3], const float f[3], float dither, float s, float t);
+
+
#define rgba_char_args_set_fl(col, r, g, b, a) \
rgba_char_args_set(col, (r) * 255, (g) * 255, (b) * 255, (a) * 255)
diff --git a/source/blender/blenlib/BLI_math_color_blend.h b/source/blender/blenlib/BLI_math_color_blend.h
index 2535a31ccc4..d966676e19e 100644
--- a/source/blender/blenlib/BLI_math_color_blend.h
+++ b/source/blender/blenlib/BLI_math_color_blend.h
@@ -78,22 +78,22 @@ MINLINE void blend_color_darken_float(float dst[4], const float src1[4], const f
MINLINE void blend_color_erase_alpha_float(float dst[4], const float src1[4], const float src2[4]);
MINLINE void blend_color_add_alpha_float(float dst[4], const float src1[4], const float src2[4]);
-MINLINE void blend_color_overlay_float(float dst[4], const float src1[4], const float src2[2]);
-MINLINE void blend_color_hardlight_float(float dst[4], const float src1[4], const float src2[2]);
-MINLINE void blend_color_burn_float(float dst[4], const float src1[4], const float src2[2]);
-MINLINE void blend_color_linearburn_float(float dst[4], const float src1[4], const float src2[2]);
-MINLINE void blend_color_dodge_float(float dst[4], const float src1[4], const float src2[2]);
-MINLINE void blend_color_screen_float(float dst[4], const float src1[4], const float src2[2]);
-MINLINE void blend_color_softlight_float(float dst[4], const float src1[4], const float src2[2]);
-MINLINE void blend_color_pinlight_float(float dst[4], const float src1[4], const float src2[2]);
-MINLINE void blend_color_linearlight_float(float dst[4], const float src1[4], const float src2[2]);
-MINLINE void blend_color_vividlight_float(float dst[4], const float src1[4], const float src2[2]);
-MINLINE void blend_color_difference_float(float dst[4], const float src1[4], const float src2[2]);
-MINLINE void blend_color_exclusion_float(float dst[4], const float src1[4], const float src2[2]);
-MINLINE void blend_color_color_float(float dst[4], const float src1[4], const float src2[2]);
-MINLINE void blend_color_hue_float(float dst[4], const float src1[4], const float src2[2]);
-MINLINE void blend_color_saturation_float(float dst[4], const float src1[4], const float src2[2]);
-MINLINE void blend_color_luminosity_float(float dst[4], const float src1[4], const float src2[2]);
+MINLINE void blend_color_overlay_float(float dst[4], const float src1[4], const float src2[4]);
+MINLINE void blend_color_hardlight_float(float dst[4], const float src1[4], const float src2[4]);
+MINLINE void blend_color_burn_float(float dst[4], const float src1[4], const float src2[4]);
+MINLINE void blend_color_linearburn_float(float dst[4], const float src1[4], const float src2[4]);
+MINLINE void blend_color_dodge_float(float dst[4], const float src1[4], const float src2[4]);
+MINLINE void blend_color_screen_float(float dst[4], const float src1[4], const float src2[4]);
+MINLINE void blend_color_softlight_float(float dst[4], const float src1[4], const float src2[4]);
+MINLINE void blend_color_pinlight_float(float dst[4], const float src1[4], const float src2[4]);
+MINLINE void blend_color_linearlight_float(float dst[4], const float src1[4], const float src2[4]);
+MINLINE void blend_color_vividlight_float(float dst[4], const float src1[4], const float src2[4]);
+MINLINE void blend_color_difference_float(float dst[4], const float src1[4], const float src2[4]);
+MINLINE void blend_color_exclusion_float(float dst[4], const float src1[4], const float src2[4]);
+MINLINE void blend_color_color_float(float dst[4], const float src1[4], const float src2[4]);
+MINLINE void blend_color_hue_float(float dst[4], const float src1[4], const float src2[4]);
+MINLINE void blend_color_saturation_float(float dst[4], const float src1[4], const float src2[4]);
+MINLINE void blend_color_luminosity_float(float dst[4], const float src1[4], const float src2[4]);
MINLINE void blend_color_interpolate_float(float dst[4], const float src1[4], const float src2[4], float t);
diff --git a/source/blender/blenlib/BLI_math_geom.h b/source/blender/blenlib/BLI_math_geom.h
index 81ca2908619..b3526b6fc60 100644
--- a/source/blender/blenlib/BLI_math_geom.h
+++ b/source/blender/blenlib/BLI_math_geom.h
@@ -52,21 +52,31 @@ float normal_quad_v3(float r[3], const float a[3], const float b[3], const float
float normal_poly_v3(float r[3], const float verts[][3], unsigned int nr);
MINLINE float area_tri_v2(const float a[2], const float b[2], const float c[2]);
+MINLINE float area_squared_tri_v2(const float a[2], const float b[2], const float c[2]);
MINLINE float area_tri_signed_v2(const float v1[2], const float v2[2], const float v3[2]);
float area_tri_v3(const float a[3], const float b[3], const float c[3]);
+float area_squared_tri_v3(const float a[3], const float b[3], const float c[3]);
float area_tri_signed_v3(const float v1[3], const float v2[3], const float v3[3], const float normal[3]);
float area_quad_v3(const float a[3], const float b[3], const float c[3], const float d[3]);
+float area_squared_quad_v3(const float a[3], const float b[3], const float c[3], const float d[3]);
float area_poly_v3(const float verts[][3], unsigned int nr);
float area_poly_v2(const float verts[][2], unsigned int nr);
+float area_squared_poly_v3(const float verts[][3], unsigned int nr);
+float area_squared_poly_v2(const float verts[][2], unsigned int nr);
+float area_poly_signed_v2(const float verts[][2], unsigned int nr);
float cotangent_tri_weight_v3(const float v1[3], const float v2[3], const float v3[3]);
+void cross_tri_v3(float n[3], const float v1[3], const float v2[3], const float v3[3]);
MINLINE float cross_tri_v2(const float v1[2], const float v2[2], const float v3[2]);
+void cross_poly_v3(float n[3], const float verts[][3], unsigned int nr);
float cross_poly_v2(const float verts[][2], unsigned int nr);
/********************************* Planes **********************************/
void plane_from_point_normal_v3(float r_plane[4], const float plane_co[3], const float plane_no[3]);
-void plane_to_point_normal_v3(const float plane[4], float r_plane_co[3], float r_plane_no[3]);
+void plane_to_point_vector_v3(const float plane[4], float r_plane_co[3], float r_plane_no[3]);
+void plane_to_point_vector_v3_normalized(const float plane[4], float r_plane_co[3], float r_plane_no[3]);
+
MINLINE float plane_point_side_v3(const float plane[4], const float co[3]);
/********************************* Volume **********************************/
@@ -77,6 +87,7 @@ float volume_tetrahedron_signed_v3(const float v1[3], const float v2[3], const f
bool is_quad_convex_v3(const float v1[3], const float v2[3], const float v3[3], const float v4[3]);
bool is_quad_convex_v2(const float v1[2], const float v2[2], const float v3[2], const float v4[2]);
bool is_poly_convex_v2(const float verts[][2], unsigned int nr);
+int is_quad_flip_v3(const float v1[3], const float v2[3], const float v3[3], const float v4[3]);
/********************************* Distance **********************************/
@@ -91,21 +102,42 @@ float dist_squared_to_plane_v3(const float p[3], const float plane[4]);
float dist_signed_to_plane_v3(const float p[3], const float plane[4]);
float dist_to_plane_v3(const float p[3], const float plane[4]);
+/* plane3 versions */
+float dist_signed_squared_to_plane3_v3(const float p[3], const float plane[4]);
+float dist_squared_to_plane3_v3(const float p[3], const float plane[4]);
+float dist_signed_to_plane3_v3(const float p[3], const float plane[4]);
+float dist_to_plane3_v3(const float p[3], const float plane[4]);
+
float dist_squared_to_line_segment_v3(const float p[3], const float l1[3], const float l2[3]);
float dist_to_line_segment_v3(const float p[3], const float l1[3], const float l2[3]);
float dist_squared_to_line_v3(const float p[3], const float l1[3], const float l2[3]);
float dist_to_line_v3(const float p[3], const float l1[3], const float l2[3]);
+float dist_signed_squared_to_corner_v3v3v3(
+ const float p[3],
+ const float v1[3], const float v2[3], const float v3[3],
+ const float axis_ref[3]);
float closest_to_line_v3(float r[3], const float p[3], const float l1[3], const float l2[3]);
float closest_to_line_v2(float r[2], const float p[2], const float l1[2], const float l2[2]);
void closest_to_line_segment_v3(float r_close[3], const float p[3], const float l1[3], const float l2[3]);
+void closest_to_plane_normalized_v3(float r_close[3], const float plane[4], const float pt[3]);
void closest_to_plane_v3(float r_close[3], const float plane[4], const float pt[3]);
+void closest_to_plane3_normalized_v3(float r_close[3], const float plane[3], const float pt[3]);
+void closest_to_plane3_v3(float r_close[3], const float plane[3], const float pt[3]);
/* Set 'r' to the point in triangle (t1, t2, t3) closest to point 'p' */
void closest_on_tri_to_point_v3(float r[3], const float p[3], const float t1[3], const float t2[3], const float t3[3]);
+float line_point_factor_v3_ex(
+ const float p[3], const float l1[3], const float l2[3],
+ const float epsilon, const float fallback);
+float line_point_factor_v3(
+ const float p[3], const float l1[3], const float l2[3]);
-float line_point_factor_v3(const float p[3], const float l1[3], const float l2[3]);
-float line_point_factor_v2(const float p[2], const float l1[2], const float l2[2]);
+float line_point_factor_v2_ex(
+ const float p[2], const float l1[2], const float l2[2],
+ const float epsilon, const float fallback);
+float line_point_factor_v2(
+ const float p[2], const float l1[2], const float l2[2]);
float line_plane_factor_v3(const float plane_co[3], const float plane_no[3],
const float l1[3], const float l2[3]);
@@ -122,12 +154,12 @@ void limit_dist_v3(float v1[3], float v2[3], const float dist);
#define ISECT_LINE_LINE_EXACT 1
#define ISECT_LINE_LINE_CROSS 2
-int isect_line_line_v2_point(const float v1[2], const float v2[2], const float v3[2], const float v4[2], float vi[2]);
+int isect_line_line_v2_point(const float v0[2], const float v1[2], const float v2[2], const float v3[2], float r_vi[2]);
int isect_line_line_v2(const float a1[2], const float a2[2], const float b1[2], const float b2[2]);
int isect_line_line_v2_int(const int a1[2], const int a2[2], const int b1[2], const int b2[2]);
int isect_line_sphere_v3(const float l1[3], const float l2[3], const float sp[3], const float r, float r_p1[3], float r_p2[3]);
int isect_line_sphere_v2(const float l1[2], const float l2[2], const float sp[2], const float r, float r_p1[2], float r_p2[2]);
-int isect_seg_seg_v2_point(const float v1[2], const float v2[2], const float v3[2], const float v4[2], float vi[2]);
+int isect_seg_seg_v2_point(const float v0[2], const float v1[2], const float v2[2], const float v3[2], float vi[2]);
bool isect_seg_seg_v2(const float v1[2], const float v2[2], const float v3[2], const float v4[2]);
int isect_line_line_epsilon_v3(
@@ -142,30 +174,69 @@ bool isect_line_line_strict_v3(const float v1[3], const float v2[3],
const float v3[3], const float v4[3],
float vi[3], float *r_lambda);
-bool isect_ray_plane_v3(const float p1[3], const float d[3],
- const float v0[3], const float v1[3], const float v2[3],
- float *r_lambda, const int clip);
+bool isect_ray_plane_v3(
+ const float p1[3], const float d[3],
+ const float v0[3], const float v1[3], const float v2[3],
+ float *r_lambda, const bool clip);
bool isect_point_planes_v3(float (*planes)[4], int totplane, const float p[3]);
bool isect_line_plane_v3(float out[3], const float l1[3], const float l2[3],
const float plane_co[3], const float plane_no[3]) ATTR_WARN_UNUSED_RESULT;
-bool isect_plane_plane_v3(float r_isect_co[3], float r_isect_no[3],
- const float plane_a_co[3], const float plane_a_no[3],
- const float plane_b_co[3], const float plane_b_no[3]) ATTR_WARN_UNUSED_RESULT;
+bool isect_plane_plane_plane_v3(
+ const float plane_a[4], const float plane_b[4], const float plane_c[4],
+ float r_isect_co[3]) ATTR_WARN_UNUSED_RESULT;
+bool isect_plane_plane_v3(
+ const float plane_a[4], const float plane_b[4],
+ float r_isect_co[3], float r_isect_no[3]) ATTR_WARN_UNUSED_RESULT;
/* line/ray triangle */
-bool isect_line_tri_v3(const float p1[3], const float p2[3],
- const float v0[3], const float v1[3], const float v2[3], float *r_lambda, float r_uv[2]);
-bool isect_line_tri_epsilon_v3(const float p1[3], const float p2[3],
- const float v0[3], const float v1[3], const float v2[3],
- float *r_lambda, float r_uv[2], const float epsilon);
-bool isect_ray_tri_v3(const float p1[3], const float d[3],
- const float v0[3], const float v1[3], const float v2[3], float *r_lambda, float r_uv[2]);
-bool isect_ray_tri_threshold_v3(const float p1[3], const float d[3],
- const float v0[3], const float v1[3], const float v2[3], float *r_lambda, float r_uv[2], const float threshold);
-bool isect_ray_tri_epsilon_v3(const float p1[3], const float d[3],
- const float v0[3], const float v1[3], const float v2[3], float *r_lambda, float r_uv[2], const float epsilon);
+bool isect_line_tri_v3(
+ const float p1[3], const float p2[3],
+ const float v0[3], const float v1[3], const float v2[3],
+ float *r_lambda, float r_uv[2]);
+bool isect_line_tri_epsilon_v3(
+ const float p1[3], const float p2[3],
+ const float v0[3], const float v1[3], const float v2[3],
+ float *r_lambda, float r_uv[2], const float epsilon);
+bool isect_ray_tri_v3(
+ const float p1[3], const float d[3],
+ const float v0[3], const float v1[3], const float v2[3],
+ float *r_lambda, float r_uv[2]);
+bool isect_ray_tri_threshold_v3(
+ const float p1[3], const float d[3],
+ const float v0[3], const float v1[3], const float v2[3],
+ float *r_lambda, float r_uv[2], const float threshold);
+bool isect_ray_tri_epsilon_v3(
+ const float p1[3], const float d[3],
+ const float v0[3], const float v1[3], const float v2[3],
+ float *r_lambda, float r_uv[2], const float epsilon);
+bool isect_tri_tri_epsilon_v3(
+ const float t_a0[3], const float t_a1[3], const float t_a2[3],
+ const float t_b0[3], const float t_b1[3], const float t_b2[3],
+ float r_i1[3], float r_i2[3],
+ const float epsilon);
+
+/* water-tight raycast (requires pre-calculation) */
+struct IsectRayPrecalc {
+ /* Maximal dimension kz, and orthogonal dimensions. */
+ int kx, ky, kz;
+
+ /* Shear constants. */
+ float sx, sy, sz;
+};
+
+void isect_ray_tri_watertight_v3_precalc(
+ struct IsectRayPrecalc *isect_precalc, const float dir[3]);
+bool isect_ray_tri_watertight_v3(
+ const float P[3], const struct IsectRayPrecalc *isect_precalc,
+ const float v0[3], const float v1[3], const float v2[3],
+ float *r_dist, float r_uv[2]);
+/* slower version which calculates IsectRayPrecalc each time */
+bool isect_ray_tri_watertight_v3_simple(
+ const float P[3], const float dir[3],
+ const float v0[3], const float v1[3], const float v2[3],
+ float *r_lambda, float r_uv[2]);
/* point in polygon */
bool isect_point_poly_v2(const float pt[2], const float verts[][2], const unsigned int nr, const bool use_holes);
@@ -244,6 +315,7 @@ void resolve_tri_uv_v3(float r_uv[2], const float st[3], const float st0[3], con
void resolve_quad_uv_v2(float r_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_v2_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]);
+float resolve_quad_u_v2(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]);
@@ -263,6 +335,9 @@ void orthographic_m4(float mat[4][4], const float left, const float right,
void window_translate_m4(float winmat[4][4], float perspmat[4][4],
const float x, const float y);
+void planes_from_projmat(float mat[4][4], float left[4], float right[4], float top[4], float bottom[4],
+ float front[4], float back[4]);
+
int box_clip_bounds_m4(float boundbox[2][3],
const float bounds[4], float winmat[4][4]);
void box_minmax_bounds_m4(float min[3], float max[3],
@@ -275,17 +350,27 @@ void map_to_sphere(float *r_u, float *r_v, const float x, const float y, const f
/********************************** Normals **********************************/
-void accumulate_vertex_normals(float n1[3], float n2[3], float n3[3],
- float n4[3], const float f_no[3], const float co1[3], const float co2[3],
- const float co3[3], const float co4[3]);
+void accumulate_vertex_normals_tri(
+ float n1[3], float n2[3], float n3[3],
+ const float f_no[3],
+ const float co1[3], const float co2[3], const float co3[3]);
+
+void accumulate_vertex_normals(
+ float n1[3], float n2[3], float n3[3], float n4[3],
+ const float f_no[3],
+ const float co1[3], const float co2[3], const float co3[3], const float co4[3]);
-void accumulate_vertex_normals_poly(float **vertnos, const float polyno[3],
- const float **vertcos, float vdiffs[][3], const int nverts);
+void accumulate_vertex_normals_poly(
+ float **vertnos, const float polyno[3],
+ const float **vertcos, float vdiffs[][3], const int nverts);
/********************************* Tangents **********************************/
-void tangent_from_uv(float uv1[2], float uv2[2], float uv3[2],
- float co1[3], float co2[3], float co3[3], float n[3], float tang[3]);
+void tangent_from_uv(
+ const float uv1[2], const float uv2[2], const float uv3[2],
+ const float co1[3], const float co2[3], const float co3[3],
+ const float n[3],
+ float r_tang[3]);
/******************************** Vector Clouds ******************************/
@@ -321,6 +406,7 @@ bool form_factor_visible_quad(const float p[3], const float n[3],
float form_factor_hemi_poly(float p[3], float n[3],
float v1[3], float v2[3], float v3[3], float v4[3]);
+void axis_dominant_v3_to_m3_negate(float r_mat[3][3], const float normal[3]);
void axis_dominant_v3_to_m3(float r_mat[3][3], const float normal[3]);
MINLINE void axis_dominant_v3(int *r_axis_a, int *r_axis_b, const float axis[3]);
diff --git a/source/blender/blenlib/BLI_math_matrix.h b/source/blender/blenlib/BLI_math_matrix.h
index 732f4b66f38..d7a309e0835 100644
--- a/source/blender/blenlib/BLI_math_matrix.h
+++ b/source/blender/blenlib/BLI_math_matrix.h
@@ -106,6 +106,7 @@ void mul_v2_m4v3(float r[2], float M[4][4], const float v[3]);
void mul_v2_m2v2(float r[2], float M[2][2], const float v[2]);
void mul_m2v2(float M[2][2], float v[2]);
void mul_mat3_m4_v3(float M[4][4], float r[3]);
+void mul_v3_mat3_m4v3(float r[3], float M[4][4], const float v[3]);
void mul_m4_v4(float M[4][4], float r[4]);
void mul_v4_m4v4(float r[4], float M[4][4], const float v[4]);
void mul_project_m4_v3(float M[4][4], float vec[3]);
@@ -125,7 +126,8 @@ void mul_m3_fl(float R[3][3], float f);
void mul_m4_fl(float R[4][4], float f);
void mul_mat3_m4_fl(float R[4][4], float f);
-void negate_m3(float R[4][4]);
+void negate_m3(float R[3][3]);
+void negate_mat3_m4(float R[4][4]);
void negate_m4(float R[4][4]);
bool invert_m3_ex(float m[3][3], const float epsilon);
@@ -144,7 +146,10 @@ void mul_v4d_m4v4d(double r[4], float M[4][4], double v[4]);
/****************************** Linear Algebra *******************************/
void transpose_m3(float R[3][3]);
+void transpose_m3_m3(float R[3][3], float A[3][3]);
+void transpose_m3_m4(float R[3][3], float A[4][4]);
void transpose_m4(float R[4][4]);
+void transpose_m4_m4(float R[4][4], float A[4][4]);
int compare_m4m4(float mat1[4][4], float mat2[4][4], float limit);
@@ -236,6 +241,7 @@ typedef struct SpaceTransform {
} SpaceTransform;
void BLI_space_transform_from_matrices(struct SpaceTransform *data, float local[4][4], float target[4][4]);
+void BLI_space_transform_global_from_matrices(struct SpaceTransform *data, float local[4][4], float target[4][4]);
void BLI_space_transform_apply(const struct SpaceTransform *data, float co[3]);
void BLI_space_transform_invert(const struct SpaceTransform *data, float co[3]);
void BLI_space_transform_apply_normal(const struct SpaceTransform *data, float no[3]);
diff --git a/source/blender/blenlib/BLI_math_rotation.h b/source/blender/blenlib/BLI_math_rotation.h
index 905889a33d7..fbd026f7617 100644
--- a/source/blender/blenlib/BLI_math_rotation.h
+++ b/source/blender/blenlib/BLI_math_rotation.h
@@ -119,6 +119,11 @@ void mat4_to_axis_angle(float axis[3], float *angle, float M[4][4]);
void axis_angle_to_mat3_single(float R[3][3], const char axis, const float angle);
void angle_to_mat2(float R[2][2], const float angle);
+/****************************** Exponential Map ******************************/
+void quat_to_expmap(float expmap[3], const float q[4]);
+void quat_normalized_to_expmap(float expmap[3], const float q[4]);
+void expmap_to_quat(float r[4], const float expmap[3]);
+
/******************************** XYZ Eulers *********************************/
void eul_to_quat(float quat[4], const float eul[3]);
diff --git a/source/blender/blenlib/BLI_math_solvers.h b/source/blender/blenlib/BLI_math_solvers.h
new file mode 100644
index 00000000000..ec9ba5538e2
--- /dev/null
+++ b/source/blender/blenlib/BLI_math_solvers.h
@@ -0,0 +1,66 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2015 by Blender Foundation
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ * */
+
+#ifndef __BLI_MATH_SOLVERS_H__
+#define __BLI_MATH_SOLVERS_H__
+
+/** \file BLI_math_solvers.h
+ * \ingroup bli
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "BLI_compiler_attrs.h"
+#include "BLI_math_inline.h"
+
+#ifdef BLI_MATH_GCC_WARN_PRAGMA
+# pragma GCC diagnostic push
+# pragma GCC diagnostic ignored "-Wredundant-decls"
+#endif
+
+/********************************** Eigen Solvers *********************************/
+
+bool BLI_eigen_solve_selfadjoint_m3(const float m3[3][3], float r_eigen_values[3], float r_eigen_vectors[3][3]);
+
+
+/**************************** Inline Definitions ******************************/
+#if 0 /* None so far. */
+# if BLI_MATH_DO_INLINE
+# include "intern/math_geom_inline.c"
+# endif
+#endif
+
+#ifdef BLI_MATH_GCC_WARN_PRAGMA
+# pragma GCC diagnostic pop
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __BLI_MATH_SOLVERS_H__ */
+
diff --git a/source/blender/blenlib/BLI_math_statistics.h b/source/blender/blenlib/BLI_math_statistics.h
new file mode 100644
index 00000000000..484cc30cc46
--- /dev/null
+++ b/source/blender/blenlib/BLI_math_statistics.h
@@ -0,0 +1,70 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2015 by Blender Foundation
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ * */
+
+#ifndef __BLI_MATH_STATISTICS_H__
+#define __BLI_MATH_STATISTICS_H__
+
+/** \file BLI_math_statistics.h
+ * \ingroup bli
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "BLI_compiler_attrs.h"
+#include "BLI_math_inline.h"
+
+#ifdef BLI_MATH_GCC_WARN_PRAGMA
+# pragma GCC diagnostic push
+# pragma GCC diagnostic ignored "-Wredundant-decls"
+#endif
+
+/********************************** Covariance Matrices *********************************/
+
+void BLI_covariance_m_vn_ex(
+ const int n, const float *cos_vn, const int nbr_cos_v3, const float *center, const bool use_sample_correction,
+ float *r_covmat);
+void BLI_covariance_m3_v3n(
+ const float (*cos_v3)[3], const int nbr_cos_v3, const bool use_sample_correction,
+ float r_covmat[3][3], float r_center[3]);
+
+/**************************** Inline Definitions ******************************/
+#if 0 /* None so far. */
+# if BLI_MATH_DO_INLINE
+# include "intern/math_geom_inline.c"
+# endif
+#endif
+
+#ifdef BLI_MATH_GCC_WARN_PRAGMA
+# pragma GCC diagnostic pop
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __BLI_MATH_STATISTICS_H__ */
+
diff --git a/source/blender/blenlib/BLI_math_vector.h b/source/blender/blenlib/BLI_math_vector.h
index 6885a5aa351..fc0dd76b003 100644
--- a/source/blender/blenlib/BLI_math_vector.h
+++ b/source/blender/blenlib/BLI_math_vector.h
@@ -146,10 +146,20 @@ MINLINE void negate_v4_v4(float r[4], const float a[3]);
MINLINE void negate_v3_short(short r[3]);
+MINLINE void abs_v2(float r[2]);
+MINLINE void abs_v2_v2(float r[2], const float a[2]);
+MINLINE void abs_v3(float r[3]);
+MINLINE void abs_v3_v3(float r[3], const float a[3]);
+MINLINE void abs_v4(float r[4]);
+MINLINE void abs_v4_v4(float r[4], const float a[4]);
+
MINLINE float dot_v2v2(const float a[2], const float b[2]) ATTR_WARN_UNUSED_RESULT;
MINLINE float dot_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT;
+MINLINE float dot_v3v3v3(const float p[3], const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT;
MINLINE float dot_v4v4(const float a[4], const float b[4]) ATTR_WARN_UNUSED_RESULT;
+MINLINE double dot_v3db_v3fl(const double a[3], const float b[3]) 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]);
@@ -207,6 +217,7 @@ void interp_v4_v4v4_uchar(unsigned char target[4], const unsigned char a[4], con
void mid_v3_v3v3(float r[3], const float a[3], const float b[3]);
void mid_v2_v2v2(float r[2], const float a[2], const float b[2]);
void mid_v3_v3v3v3(float v[3], const float v1[3], const float v2[3], const float v3[3]);
+void mid_v3_v3v3v3v3(float v[3], const float v1[3], const float v2[3], const float v3[3], const float v4[3]);
void mid_v3_v3v3_angle_weighted(float r[3], const float a[3], const float b[3]);
void mid_v3_angle_weighted(float r[3]);
@@ -229,14 +240,19 @@ MINLINE bool is_one_v3(const float a[3]) ATTR_WARN_UNUSED_RESULT;
MINLINE bool equals_v2v2(const float v1[2], const float v2[2]) ATTR_WARN_UNUSED_RESULT;
MINLINE bool equals_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT;
+MINLINE bool equals_v4v4(const float a[4], const float b[4]) ATTR_WARN_UNUSED_RESULT;
+
MINLINE bool compare_v2v2(const float a[2], const float b[2], const float limit) ATTR_WARN_UNUSED_RESULT;
MINLINE bool compare_v3v3(const float a[3], const float b[3], const float limit) ATTR_WARN_UNUSED_RESULT;
+MINLINE bool compare_v4v4(const float a[4], const float b[4], const float limit) ATTR_WARN_UNUSED_RESULT;
+
+MINLINE bool compare_v2v2_relative(const float a[2], const float b[2], const float limit, const int max_ulps) ATTR_WARN_UNUSED_RESULT;
+MINLINE bool compare_v3v3_relative(const float a[3], const float b[3], const float limit, const int max_ulps) ATTR_WARN_UNUSED_RESULT;
+MINLINE bool compare_v4v4_relative(const float a[4], const float b[4], const float limit, const int max_ulps) ATTR_WARN_UNUSED_RESULT;
+
MINLINE bool compare_len_v3v3(const float a[3], const float b[3], const float limit) ATTR_WARN_UNUSED_RESULT;
MINLINE bool compare_len_squared_v3v3(const float a[3], const float b[3], const float limit) ATTR_WARN_UNUSED_RESULT;
-MINLINE bool compare_v4v4(const float a[4], const float b[4], const float limit) ATTR_WARN_UNUSED_RESULT;
-MINLINE bool equals_v4v4(const float a[4], const float b[4]) ATTR_WARN_UNUSED_RESULT;
-
MINLINE float line_point_side_v2(const float l1[2], const float l2[2], const float pt[2]) ATTR_WARN_UNUSED_RESULT;
/********************************** Angles ***********************************/
@@ -262,6 +278,8 @@ void angle_poly_v3(float *angles, const float *verts[3], int len);
void project_v2_v2v2(float c[2], const float v1[2], const float v2[2]);
void project_v3_v3v3(float r[3], const float p[3], const float n[3]);
+void project_plane_v3_v3v3(float c[3], const float v[3], const float v_plane[3]);
+void project_plane_v2_v2v2(float c[2], const float v[2], const float v_plane[2]);
void project_v3_plane(float v[3], const float n[3], const float p[3]);
void reflect_v3_v3v3(float r[3], const float v[3], const float n[3]);
void ortho_basis_v3v3_v3(float r_n1[3], float r_n2[3], const float n[3]);
@@ -289,18 +307,21 @@ MINLINE void normal_float_to_short_v3(short r[3], const float n[3]);
void minmax_v3v3_v3(float min[3], float max[3], const float vec[3]);
void minmax_v2v2_v2(float min[2], float max[2], const float vec[2]);
+void minmax_v3v3_v3_array(float r_min[3], float r_max[3], const float (*vec_arr)[3], int nbr);
+
void dist_ensure_v3_v3fl(float v1[3], const float v2[3], const float dist);
void dist_ensure_v2_v2fl(float v1[2], const float v2[2], const float dist);
void axis_sort_v3(const float axis_values[3], int r_axis_order[3]);
/***************************** Array Functions *******************************/
-/* attempted to follow fixed length vertex functions. names could be improved*/
+/* follow fixed length vector function conventions. */
double dot_vn_vn(const float *array_src_a, const float *array_src_b, const int size) ATTR_WARN_UNUSED_RESULT;
double len_squared_vn(const float *array, const int size) ATTR_WARN_UNUSED_RESULT;
float normalize_vn_vn(float *array_tar, const float *array_src, const int size);
float normalize_vn(float *array_tar, const int size);
void range_vn_i(int *array_tar, const int size, const int start);
+void range_vn_u(unsigned int *array_tar, const int size, const unsigned int start);
void range_vn_fl(float *array_tar, const int size, const float start, const float step);
void negate_vn(float *array_tar, const int size);
void negate_vn_vn(float *array_tar, const float *array_src, const int size);
@@ -315,10 +336,15 @@ void sub_vn_vnvn(float *array_tar, const float *array_src_a, const float *array_
void msub_vn_vn(float *array_tar, const float *array_src, const float f, const int size);
void msub_vn_vnvn(float *array_tar, const float *array_src_a, const float *array_src_b, const float f, const int size);
void interp_vn_vn(float *array_tar, const float *array_src, const float t, const int size);
-void fill_vn_i(int *array_tar, const int size, const int val);
-void fill_vn_short(short *array_tar, const int size, const short val);
-void fill_vn_ushort(unsigned short *array_tar, const int size, const unsigned short val);
-void fill_vn_fl(float *array_tar, const int size, const float val);
+void copy_vn_i(int *array_tar, const int size, const int val);
+void copy_vn_short(short *array_tar, const int size, const short val);
+void copy_vn_ushort(unsigned short *array_tar, const int size, const unsigned short val);
+void copy_vn_uchar(unsigned char *array_tar, const int size, const unsigned char val);
+void copy_vn_fl(float *array_tar, const int size, const float val);
+
+void add_vn_vn_d(double *array_tar, const double *array_src, const int size);
+void add_vn_vnvn_d(double *array_tar, const double *array_src_a, const double *array_src_b, const int size);
+void mul_vn_db(double *array_tar, const int size, const double f);
/**************************** Inline Definitions ******************************/
diff --git a/source/blender/blenlib/BLI_memarena.h b/source/blender/blenlib/BLI_memarena.h
index 8d5a7654425..6b1d32b48f2 100644
--- a/source/blender/blenlib/BLI_memarena.h
+++ b/source/blender/blenlib/BLI_memarena.h
@@ -27,11 +27,6 @@
/** \file BLI_memarena.h
* \ingroup bli
- * \brief Memory arena ADT.
- * \section aboutmemarena Memory Arena
- * Memory arena's are commonly used when the program
- * needs to quickly allocate lots of little bits of
- * data, which are all freed at the same moment.
*/
#ifndef __BLI_MEMARENA_H__
diff --git a/source/blender/blenlib/BLI_mempool.h b/source/blender/blenlib/BLI_mempool.h
index 25694f4445b..0c754f551e0 100644
--- a/source/blender/blenlib/BLI_mempool.h
+++ b/source/blender/blenlib/BLI_mempool.h
@@ -30,8 +30,6 @@
/** \file BLI_mempool.h
* \ingroup bli
- * \author Geoffrey Bantle
- * \brief Simple fast memory allocator for fixed size chunks.
*/
#ifdef __cplusplus
@@ -46,10 +44,6 @@ struct BLI_mempool_chunk;
typedef struct BLI_mempool BLI_mempool;
-/* allow_iter allows iteration on this mempool. note: this requires that the
- * first four bytes of the elements never contain the character string
- * 'free'. use with care.*/
-
BLI_mempool *BLI_mempool_create(unsigned int esize, unsigned int totelem,
unsigned int pchunk, unsigned int flag) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT;
void *BLI_mempool_alloc(BLI_mempool *pool) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1);
@@ -67,7 +61,7 @@ void **BLI_mempool_as_tableN(BLI_mempool *pool, const char *allocstr) ATTR_
void BLI_mempool_as_array(BLI_mempool *pool, void *data) ATTR_NONNULL(1, 2);
void *BLI_mempool_as_arrayN(BLI_mempool *pool, const char *allocstr) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1, 2);
-#ifdef DEBUG
+#ifndef NDEBUG
void BLI_mempool_set_memory_debug(void);
#endif
@@ -82,6 +76,11 @@ typedef struct BLI_mempool_iter {
/* flag */
enum {
BLI_MEMPOOL_NOP = 0,
+ /** allow iterating on this mempool.
+ *
+ * \note this requires that the first four bytes of the elements never begin with 'free' (FREEWORD).
+ * \note order of iteration is only assured to be the order of allocation when no chunks have been freed.
+ */
BLI_MEMPOOL_ALLOW_ITER = (1 << 0),
};
diff --git a/source/blender/blenlib/BLI_path_util.h b/source/blender/blenlib/BLI_path_util.h
index 3d82480d050..a344c9d2bc1 100644
--- a/source/blender/blenlib/BLI_path_util.h
+++ b/source/blender/blenlib/BLI_path_util.h
@@ -38,41 +38,6 @@ extern "C" {
#include "BLI_compiler_attrs.h"
struct ListBase;
-struct direntry;
-
-const char *BLI_getDefaultDocumentFolder(void);
-
-const char *BLI_get_folder(int folder_id, const char *subfolder);
-const char *BLI_get_folder_create(int folder_id, const char *subfolder);
-const char *BLI_get_user_folder_notest(int folder_id, const char *subfolder);
-const char *BLI_get_folder_version(const int id, const int ver, const bool do_check);
-
-/* folder_id */
-
-/* general, will find based on user/local/system priority */
-#define BLENDER_DATAFILES 2
-
-/* user-specific */
-#define BLENDER_USER_CONFIG 31
-#define BLENDER_USER_DATAFILES 32
-#define BLENDER_USER_SCRIPTS 33
-#define BLENDER_USER_AUTOSAVE 34
-
-/* system */
-#define BLENDER_SYSTEM_DATAFILES 52
-#define BLENDER_SYSTEM_SCRIPTS 53
-#define BLENDER_SYSTEM_PYTHON 54
-
-/* for BLI_get_folder_version only */
-#define BLENDER_RESOURCE_PATH_USER 0
-#define BLENDER_RESOURCE_PATH_LOCAL 1
-#define BLENDER_RESOURCE_PATH_SYSTEM 2
-
-#define BLENDER_STARTUP_FILE "startup.blend"
-#define BLENDER_USERPREF_FILE "userpref.blend"
-#define BLENDER_QUIT_FILE "quit.blend"
-#define BLENDER_BOOKMARK_FILE "bookmarks.txt"
-#define BLENDER_HISTORY_FILE "recent-files.txt"
#ifdef WIN32
#define SEP '\\'
@@ -113,6 +78,11 @@ void BLI_del_slash(char *string) ATTR_NONNULL();
const char *BLI_first_slash(const char *string) ATTR_NONNULL() ATTR_WARN_UNUSED_RESULT;
void BLI_path_native_slash(char *path) ATTR_NONNULL();
+#ifdef _WIN32
+bool BLI_path_program_extensions_add_win32(char *name, const size_t maxlen);
+#endif
+bool BLI_path_program_search(char *fullname, const size_t maxlen, const char *name);
+
void BLI_getlastdir(const char *dir, char *last, const size_t maxlen);
bool BLI_testextensie(const char *str, const char *ext) ATTR_NONNULL() ATTR_WARN_UNUSED_RESULT;
bool BLI_testextensie_n(const char *str, ...) ATTR_NONNULL(1) ATTR_SENTINEL(0);
@@ -121,7 +91,7 @@ bool BLI_testextensie_glob(const char *str, const char *ext_fnmatch) ATTR_NONNUL
bool BLI_replace_extension(char *path, size_t maxlen, const char *ext) ATTR_NONNULL();
bool BLI_ensure_extension(char *path, size_t maxlen, const char *ext) ATTR_NONNULL();
bool BLI_ensure_filename(char *filepath, size_t maxlen, const char *filename) ATTR_NONNULL();
-void BLI_uniquename(struct ListBase *list, void *vlink, const char *defname, char delim, int name_offs, int len);
+bool 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, int name_len);
void BLI_newname(char *name, int add);
@@ -142,6 +112,9 @@ void BLI_cleanup_dir(const char *relabase, char *dir) ATTR_NONNULL(2);
/* doesn't touch trailing slash */
void BLI_cleanup_path(const char *relabase, char *path) ATTR_NONNULL(2);
+bool BLI_filename_make_safe(char *fname) ATTR_NONNULL(1);
+bool BLI_path_make_safe(char *path) ATTR_NONNULL(1);
+
/* go back one directory */
bool BLI_parent_dir(char *path) ATTR_NONNULL();
@@ -160,6 +133,8 @@ bool BLI_parent_dir(char *path) ATTR_NONNULL();
bool BLI_path_abs(char *path, const char *basepath) ATTR_NONNULL();
bool BLI_path_frame(char *path, int frame, int digits) ATTR_NONNULL();
bool BLI_path_frame_range(char *path, int sta, int end, int digits) ATTR_NONNULL();
+bool BLI_path_frame_get(char *path, int *r_frame, int *numdigits) ATTR_NONNULL();
+void BLI_path_frame_strip(char *path, bool setsharp, char *ext) ATTR_NONNULL();
bool BLI_path_frame_check_chars(const char *path) ATTR_NONNULL();
bool BLI_path_cwd(char *path) ATTR_NONNULL();
void BLI_path_rel(char *file, const char *relfile) ATTR_NONNULL();
@@ -183,21 +158,6 @@ bool BLI_path_suffix(char *string, size_t maxlen, const char *suffix, const char
# define BLI_path_ncmp strncmp
#endif
-void BLI_char_switch(char *string, char from, char to) ATTR_NONNULL();
-
-/* Initialize path to program executable */
-void BLI_init_program_path(const char *argv0);
-/* Initialize path to temporary directory.
- * NOTE: On Window userdir will be set to the temporary directory! */
-void BLI_temp_dir_init(char *userdir);
-
-const char *BLI_program_path(void);
-const char *BLI_program_dir(void);
-const char *BLI_temp_dir_session(void);
-const char *BLI_temp_dir_base(void);
-void BLI_system_temporary_dir(char *dir);
-void BLI_temp_dir_session_purge(void);
-
#ifdef WITH_ICONV
void BLI_string_to_utf8(char *original, char *utf_8, const char *code);
#endif
@@ -210,6 +170,15 @@ void BLI_string_to_utf8(char *original, char *utf_8, const char *code);
# define FILE_MAX 1024
#endif
+/* Parent and current dir helpers. */
+#define FILENAME_PARENT ".."
+#define FILENAME_CURRENT "."
+
+/* Avoid calling strcmp on one or two chars! */
+#define FILENAME_IS_PARENT(_n) (((_n)[0] == '.') && ((_n)[1] == '.') && ((_n)[2] == '\0'))
+#define FILENAME_IS_CURRENT(_n) (((_n)[0] == '.') && ((_n)[1] == '\0'))
+#define FILENAME_IS_CURRPAR(_n) (((_n)[0] == '.') && (((_n)[1] == '\0') || (((_n)[1] == '.') && ((_n)[2] == '\0'))))
+
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/blenlib/BLI_polyfill2d.h b/source/blender/blenlib/BLI_polyfill2d.h
index 5c5cea8f67d..798055f9240 100644
--- a/source/blender/blenlib/BLI_polyfill2d.h
+++ b/source/blender/blenlib/BLI_polyfill2d.h
@@ -37,4 +37,7 @@ void BLI_polyfill_calc(
const int coords_sign,
unsigned int (*r_tris)[3]);
+/* default size of polyfill arena */
+#define BLI_POLYFILL_ARENA_SIZE MEM_SIZE_OPTIMAL(1 << 14)
+
#endif /* __BLI_POLYFILL2D_H__ */
diff --git a/source/blender/blenlib/BLI_polyfill2d_beautify.h b/source/blender/blenlib/BLI_polyfill2d_beautify.h
new file mode 100644
index 00000000000..20e53b080fe
--- /dev/null
+++ b/source/blender/blenlib/BLI_polyfill2d_beautify.h
@@ -0,0 +1,42 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __BLI_POLYFILL2D_BEAUTIFY_H__
+#define __BLI_POLYFILL2D_BEAUTIFY_H__
+
+struct EdgeHash;
+struct Heap;
+struct MemArena;
+
+void BLI_polyfill_beautify(
+ const float (*coords)[2],
+ const unsigned int coords_tot,
+ unsigned int (*tris)[3],
+
+ /* structs for reuse */
+ struct MemArena *arena, struct Heap *eheap, struct EdgeHash *eh);
+
+float BLI_polyfill_beautify_quad_rotate_calc(
+ const float v1[2], const float v2[2], const float v3[2], const float v4[2]);
+
+/* avoid realloc's when creating new structures for polyfill ngons */
+#define BLI_POLYFILL_ALLOC_NGON_RESERVE 64
+
+#endif /* __BLI_POLYFILL2D_BEAUTIFY_H__ */
diff --git a/source/blender/blenlib/BLI_quadric.h b/source/blender/blenlib/BLI_quadric.h
index 82c39463dd2..eaf9c7a0738 100644
--- a/source/blender/blenlib/BLI_quadric.h
+++ b/source/blender/blenlib/BLI_quadric.h
@@ -31,14 +31,14 @@
*/
typedef struct Quadric {
- float a2, ab, ac, ad,
- b2, bc, bd,
- c2, cd,
- d2;
+ double a2, ab, ac, ad,
+ b2, bc, bd,
+ c2, cd,
+ d2;
} Quadric;
/* conversion */
-void BLI_quadric_from_v3_dist(Quadric *q, const float v[3], const float offset);
+void BLI_quadric_from_plane(Quadric *q, const double v[4]);
void BLI_quadric_to_tensor_m3(const Quadric *q, float m[3][3]);
void BLI_quadric_to_vector_v3(const Quadric *q, float v[3]);
@@ -47,10 +47,10 @@ void BLI_quadric_clear(Quadric *q);
/* math */
void BLI_quadric_add_qu_qu(Quadric *a, const Quadric *b);
void BLI_quadric_add_qu_ququ(Quadric *r, const Quadric *a, const Quadric *b);
-void BLI_quadric_mul(Quadric *a, const float scalar);
+void BLI_quadric_mul(Quadric *a, const double scalar);
/* solve */
-float BLI_quadric_evaluate(const Quadric *q, const float v[3]);
+double BLI_quadric_evaluate(const Quadric *q, const float v_fl[3]);
bool BLI_quadric_optimize(const Quadric *q, float v[3], const float epsilon);
#endif /* __BLI_QUADRIC_H__ */
diff --git a/source/blender/blenlib/BLI_rand.h b/source/blender/blenlib/BLI_rand.h
index c86b3aea503..7b84dddcb68 100644
--- a/source/blender/blenlib/BLI_rand.h
+++ b/source/blender/blenlib/BLI_rand.h
@@ -40,6 +40,9 @@
struct RNG;
typedef struct RNG RNG;
+struct RNG_THREAD_ARRAY;
+typedef struct RNG_THREAD_ARRAY RNG_THREAD_ARRAY;
+
struct RNG *BLI_rng_new(unsigned int seed);
struct RNG *BLI_rng_new_srandom(unsigned int seed);
void BLI_rng_free(struct RNG *rng) ATTR_NONNULL(1);
@@ -52,6 +55,9 @@ double BLI_rng_get_double(struct RNG *rng) ATTR_WARN_UNUSED_RESULT ATTR_NON
float BLI_rng_get_float(struct RNG *rng) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1);
void BLI_rng_get_float_unit_v2(struct RNG *rng, float v[2]) ATTR_NONNULL(1, 2);
void BLI_rng_get_float_unit_v3(struct RNG *rng, float v[3]) ATTR_NONNULL(1, 2);
+void BLI_rng_get_tri_sample_float_v2(
+ struct RNG *rng, const float v1[2], const float v2[2], const float v3[2],
+ float r_pt[2]) ATTR_NONNULL();
void BLI_rng_shuffle_array(struct RNG *rng, void *data, unsigned int elem_size_i, unsigned int elem_tot) ATTR_NONNULL(1, 2);
/** Note that skipping is as slow as generating n numbers! */
@@ -89,4 +95,9 @@ int BLI_thread_rand(int thread) ATTR_WARN_UNUSED_RESULT;
/** Allows up to BLENDER_MAX_THREADS threads to address */
float BLI_thread_frand(int thread) ATTR_WARN_UNUSED_RESULT;
+/** array versions for thread safe random generation */
+RNG_THREAD_ARRAY *BLI_rng_threaded_new(void);
+void BLI_rng_threaded_free(struct RNG_THREAD_ARRAY *rngarr) ATTR_NONNULL(1);
+int BLI_rng_thread_rand(RNG_THREAD_ARRAY *rngarr, int thread) ATTR_WARN_UNUSED_RESULT;
+
#endif /* __BLI_RAND_H__ */
diff --git a/source/blender/blenlib/BLI_rect.h b/source/blender/blenlib/BLI_rect.h
index a132ac40206..a98931d2ae8 100644
--- a/source/blender/blenlib/BLI_rect.h
+++ b/source/blender/blenlib/BLI_rect.h
@@ -78,6 +78,10 @@ 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]);
+int BLI_rcti_length_x(const rcti *rect, const int x);
+int BLI_rcti_length_y(const rcti *rect, const int y);
+float BLI_rctf_length_x(const rctf *rect, const float x);
+float BLI_rctf_length_y(const rctf *rect, const float y);
bool BLI_rcti_isect_segment(const struct rcti *rect, const int s1[2], const int s2[2]);
bool BLI_rctf_isect_segment(const struct rctf *rect, const float s1[2], const float s2[2]);
bool BLI_rcti_isect_circle(const struct rcti *rect, const float xy[2], const float radius);
@@ -88,6 +92,9 @@ void BLI_rcti_union(struct rcti *rcti1, const struct rcti *rcti2);
void BLI_rctf_union(struct rctf *rctf1, const struct rctf *rctf2);
void BLI_rcti_rctf_copy(struct rcti *dst, const struct rctf *src);
void BLI_rctf_rcti_copy(struct rctf *dst, const struct rcti *src);
+void BLI_rcti_rctf_copy_floor(struct rcti *dst, const struct rctf *src);
+
+void BLI_rctf_rotate_expand(rctf *dst, const rctf *src, const float angle);
void print_rctf(const char *str, const struct rctf *rect);
void print_rcti(const char *str, const struct rcti *rect);
diff --git a/source/blender/blenlib/BLI_smallhash.h b/source/blender/blenlib/BLI_smallhash.h
index b80044bccff..e096354e5b1 100644
--- a/source/blender/blenlib/BLI_smallhash.h
+++ b/source/blender/blenlib/BLI_smallhash.h
@@ -52,7 +52,7 @@ typedef struct SmallHash {
} SmallHash;
typedef struct {
- SmallHash *sh;
+ const SmallHash *sh;
unsigned int i;
} SmallHashIter;
@@ -61,13 +61,16 @@ void BLI_smallhash_init_ex(SmallHash *sh,
void BLI_smallhash_init(SmallHash *sh) ATTR_NONNULL(1);
void BLI_smallhash_release(SmallHash *sh) ATTR_NONNULL(1);
void BLI_smallhash_insert(SmallHash *sh, uintptr_t key, void *item) ATTR_NONNULL(1);
+bool BLI_smallhash_reinsert(SmallHash *sh, uintptr_t key, void *item) ATTR_NONNULL(1);
bool BLI_smallhash_remove(SmallHash *sh, uintptr_t key) ATTR_NONNULL(1);
-void *BLI_smallhash_lookup(SmallHash *sh, uintptr_t key) ATTR_NONNULL(1) ATTR_WARN_UNUSED_RESULT;
-void **BLI_smallhash_lookup_p(SmallHash *sh, uintptr_t key) ATTR_NONNULL(1) ATTR_WARN_UNUSED_RESULT;
-bool BLI_smallhash_haskey(SmallHash *sh, uintptr_t key) ATTR_NONNULL(1);
-int BLI_smallhash_count(SmallHash *sh) ATTR_NONNULL(1);
+void *BLI_smallhash_lookup(const SmallHash *sh, uintptr_t key) ATTR_NONNULL(1) ATTR_WARN_UNUSED_RESULT;
+void **BLI_smallhash_lookup_p(const SmallHash *sh, uintptr_t key) ATTR_NONNULL(1) ATTR_WARN_UNUSED_RESULT;
+bool BLI_smallhash_haskey(const SmallHash *sh, uintptr_t key) ATTR_NONNULL(1);
+int BLI_smallhash_count(const SmallHash *sh) ATTR_NONNULL(1);
void *BLI_smallhash_iternext(SmallHashIter *iter, uintptr_t *key) ATTR_NONNULL(1) ATTR_WARN_UNUSED_RESULT;
-void *BLI_smallhash_iternew(SmallHash *sh, SmallHashIter *iter, uintptr_t *key) ATTR_NONNULL(1) ATTR_WARN_UNUSED_RESULT;
+void **BLI_smallhash_iternext_p(SmallHashIter *iter, uintptr_t *key) ATTR_NONNULL(1) ATTR_WARN_UNUSED_RESULT;
+void *BLI_smallhash_iternew(const SmallHash *sh, SmallHashIter *iter, uintptr_t *key) ATTR_NONNULL(1) ATTR_WARN_UNUSED_RESULT;
+void **BLI_smallhash_iternew_p(const SmallHash *sh, SmallHashIter *iter, uintptr_t *key) ATTR_NONNULL(1) ATTR_WARN_UNUSED_RESULT;
/* void BLI_smallhash_print(SmallHash *sh); */ /* UNUSED */
#ifdef DEBUG
diff --git a/source/blender/blenlib/BLI_sort.h b/source/blender/blenlib/BLI_sort.h
index 516f917a351..cb6b87bda38 100644
--- a/source/blender/blenlib/BLI_sort.h
+++ b/source/blender/blenlib/BLI_sort.h
@@ -35,7 +35,8 @@
#include <stdlib.h>
-#ifdef __GLIBC__
+/* glibc 2.8+ */
+#if defined(__GLIBC__) && (__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 8))
# define BLI_qsort_r qsort_r
#endif
diff --git a/source/blender/blenlib/BLI_stack.h b/source/blender/blenlib/BLI_stack.h
index 1e0b29bc7e8..222005ee92e 100644
--- a/source/blender/blenlib/BLI_stack.h
+++ b/source/blender/blenlib/BLI_stack.h
@@ -44,8 +44,13 @@ void *BLI_stack_push_r(BLI_Stack *stack) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
void BLI_stack_push(BLI_Stack *stack, const void *src) ATTR_NONNULL();
void BLI_stack_pop_n(BLI_Stack *stack, void *dst, unsigned int n) ATTR_NONNULL();
+void BLI_stack_pop_n_reverse(BLI_Stack *stack, void *dst, unsigned int n) ATTR_NONNULL();
void BLI_stack_pop(BLI_Stack *stack, void *dst) ATTR_NONNULL();
+void *BLI_stack_peek(BLI_Stack *stack) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+void BLI_stack_discard(BLI_Stack *stack) ATTR_NONNULL();
+void BLI_stack_clear(BLI_Stack *stack) ATTR_NONNULL();
+
size_t BLI_stack_count(const BLI_Stack *stack) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
bool BLI_stack_is_empty(const BLI_Stack *stack) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
diff --git a/source/blender/blenlib/BLI_stackdefines.h b/source/blender/blenlib/BLI_stackdefines.h
index da9bf5ea04c..2d8d6e4482d 100644
--- a/source/blender/blenlib/BLI_stackdefines.h
+++ b/source/blender/blenlib/BLI_stackdefines.h
@@ -40,7 +40,7 @@
# define _STACK_SIZETEST(stack, off) (void)(stack), (void)(off)
# define _STACK_SWAP_TOTALLOC(stack_a, stack_b) (void)(stack_a), (void)(stack_b)
#endif
-#define _STACK_BOUNDSTEST(stack, index) ((void)stack, BLI_assert(index >= 0 && index < _##stack##_index))
+#define _STACK_BOUNDSTEST(stack, index) ((void)stack, BLI_assert((unsigned int)index < _##stack##_index))
#define STACK_SIZE(stack) ((void)stack, (_##stack##_index))
@@ -64,6 +64,13 @@
stack[_i] = stack[_##stack##_index]; \
} \
} (void)0
+#define STACK_DISCARD(stack, n) \
+ { \
+ const unsigned int _n = n; \
+ BLI_assert(_##stack##_index >= _n); \
+ (void)stack; \
+ _##stack##_index -= _n; \
+ } (void)0
#ifdef __GNUC__
#define STACK_SWAP(stack_a, stack_b) { \
SWAP(typeof(stack_a), stack_a, stack_b); \
diff --git a/source/blender/blenlib/BLI_strict_flags.h b/source/blender/blenlib/BLI_strict_flags.h
index 1d595ff3bf3..964ee06469d 100644
--- a/source/blender/blenlib/BLI_strict_flags.h
+++ b/source/blender/blenlib/BLI_strict_flags.h
@@ -28,13 +28,15 @@
*/
#ifdef __GNUC__
-# pragma GCC diagnostic error "-Wsign-conversion"
# if (__GNUC__ * 100 + __GNUC_MINOR__) >= 406 /* gcc4.6+ only */
# pragma GCC diagnostic error "-Wsign-compare"
# pragma GCC diagnostic error "-Wconversion"
# endif
-# if (__GNUC__ * 100 + __GNUC_MINOR__) >= 408 /* gcc4.8+ only (behavior changed to ignore globals)*/
+# if (__GNUC__ * 100 + __GNUC_MINOR__) >= 408
+ /* gcc4.8+ only (behavior changed to ignore globals)*/
# pragma GCC diagnostic error "-Wshadow"
+ /* older gcc changed behavior with ternary */
+# pragma GCC diagnostic error "-Wsign-conversion"
# endif
/* pedantic gives too many issues, developers can define this for own use */
# ifdef WARN_PEDANTIC
diff --git a/source/blender/blenlib/BLI_string.h b/source/blender/blenlib/BLI_string.h
index b249bc720c6..82780394ce7 100644
--- a/source/blender/blenlib/BLI_string.h
+++ b/source/blender/blenlib/BLI_string.h
@@ -48,17 +48,23 @@ char *BLI_strdupcat(const char *__restrict str1, const char *__restrict str2) AT
char *BLI_strncpy(char *__restrict dst, const char *__restrict src, const size_t maxncpy) ATTR_NONNULL();
+char *BLI_strncpy_ensure_pad(char *__restrict dst, const char *__restrict src, const char pad, size_t maxncpy) ATTR_NONNULL();
+
size_t BLI_strncpy_rlen(char *__restrict dst, const char *__restrict src, const size_t maxncpy) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
size_t BLI_strcpy_rlen(char *__restrict dst, const char *__restrict src) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
char *BLI_str_quoted_substrN(const char *__restrict str, const char *__restrict prefix) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL() ATTR_MALLOC;
-char *BLI_replacestrN(const char *__restrict str, const char *__restrict substr_old, const char *__restrict substr_new) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL() ATTR_MALLOC;
+char *BLI_str_replaceN(const char *__restrict str, const char *__restrict substr_old, const char *__restrict substr_new) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL() ATTR_MALLOC;
+
+void BLI_str_replace_char(char *string, char src, char dst) ATTR_NONNULL();
size_t BLI_snprintf(char *__restrict dst, size_t maxncpy, const char *__restrict format, ...) ATTR_NONNULL(1, 3) ATTR_PRINTF_FORMAT(3, 4);
+size_t BLI_snprintf_rlen(char *__restrict dst, size_t maxncpy, const char *__restrict format, ...) ATTR_NONNULL(1, 3) ATTR_PRINTF_FORMAT(3, 4);
size_t BLI_vsnprintf(char *__restrict dst, size_t maxncpy, const char *__restrict format, va_list arg) ATTR_PRINTF_FORMAT(3, 0);
+size_t BLI_vsnprintf_rlen(char *__restrict buffer, size_t maxncpy, const char *__restrict format, va_list arg) ATTR_PRINTF_FORMAT(3, 0);
char *BLI_sprintfN(const char *__restrict format, ...) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) ATTR_MALLOC ATTR_PRINTF_FORMAT(1, 2);
@@ -71,19 +77,25 @@ char *BLI_strcasestr(const char *s, const char *find) ATTR_WARN_UNUSED_RESULT AT
int BLI_strcasecmp(const char *s1, const char *s2) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
int BLI_strncasecmp(const char *s1, const char *s2, size_t len) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
int BLI_natstrcmp(const char *s1, const char *s2) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+int BLI_strcmp_ignore_pad(const char *str1, const char *str2, const char pad) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+
size_t BLI_strnlen(const char *str, const size_t maxlen) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-void BLI_timestr(double _time, char *str, size_t maxlen) ATTR_NONNULL();
-void BLI_ascii_strtolower(char *str, const size_t len) ATTR_NONNULL();
-void BLI_ascii_strtoupper(char *str, const size_t len) ATTR_NONNULL();
+void BLI_str_tolower_ascii(char *str, const size_t len) ATTR_NONNULL();
+void BLI_str_toupper_ascii(char *str, const size_t len) ATTR_NONNULL();
int BLI_str_rstrip_float_zero(char *str, const char pad) ATTR_NONNULL();
int BLI_str_index_in_array_n(const char *__restrict str, const char **__restrict str_array, const int str_array_len) ATTR_NONNULL();
int BLI_str_index_in_array(const char *__restrict str, const char **__restrict str_array) ATTR_NONNULL();
-size_t BLI_str_partition(const char *str, const char delim[], char **sep, char **suf) ATTR_NONNULL();
-size_t BLI_str_rpartition(const char *str, const char delim[], char **sep, char **suf) ATTR_NONNULL();
-size_t BLI_str_partition_ex(const char *str, const char delim[], char **sep, char **suf, const bool from_right) ATTR_NONNULL();
+bool BLI_str_endswith(const char *__restrict str, const char *__restrict end) ATTR_NONNULL();
+bool BLI_strn_endswith(const char *__restrict str, const char *__restrict end, size_t length) ATTR_NONNULL();
+
+size_t BLI_str_partition(const char *str, const char delim[], const char **sep, const char **suf) ATTR_NONNULL();
+size_t BLI_str_rpartition(const char *str, const char delim[], const char **sep, const char **suf) ATTR_NONNULL();
+size_t BLI_str_partition_ex(
+ const char *str, const char *end, const char delim[], const char **sep, const char **suf, const bool from_right)
+ ATTR_NONNULL(1, 3, 4, 5);
#ifdef __cplusplus
}
diff --git a/source/blender/blenlib/BLI_string_utf8.h b/source/blender/blenlib/BLI_string_utf8.h
index 89754be25ba..0740b574c1a 100644
--- a/source/blender/blenlib/BLI_string_utf8.h
+++ b/source/blender/blenlib/BLI_string_utf8.h
@@ -34,6 +34,7 @@ extern "C" {
#include "BLI_compiler_attrs.h"
char *BLI_strncpy_utf8(char *__restrict dst, const char *__restrict src, size_t maxncpy) ATTR_NONNULL();
+size_t BLI_strncpy_utf8_rlen(char *__restrict dst, const char *__restrict src, size_t maxncpy) ATTR_NONNULL();
char *BLI_strncat_utf8(char *__restrict dst, const char *__restrict src, size_t maxncpy) ATTR_NONNULL();
int BLI_utf8_invalid_byte(const char *str, int length) ATTR_NONNULL();
int BLI_utf8_invalid_strip(char *str, int length) ATTR_NONNULL();
@@ -66,9 +67,11 @@ int BLI_wcswidth(const wchar_t *pwcs, size_t n) ATTR_NONNULL();
int BLI_str_utf8_char_width(const char *p) ATTR_NONNULL(); /* warning, can return -1 on bad chars */
int BLI_str_utf8_char_width_safe(const char *p) ATTR_NONNULL();
-size_t BLI_str_partition_utf8(const char *str, const unsigned int delim[], char **sep, char **suf) ATTR_NONNULL();
-size_t BLI_str_rpartition_utf8(const char *str, const unsigned int delim[], char **sep, char **suf) ATTR_NONNULL();
-size_t BLI_str_partition_ex_utf8(const char *str, const unsigned int delim[], char **sep, char **suf, const bool from_right) ATTR_NONNULL();
+size_t BLI_str_partition_utf8(const char *str, const unsigned int delim[], const char **sep, const char **suf) ATTR_NONNULL();
+size_t BLI_str_rpartition_utf8(const char *str, const unsigned int delim[], const char **sep, const char **suf) ATTR_NONNULL();
+size_t BLI_str_partition_ex_utf8(
+ const char *str, const char *end, const unsigned int delim[], const char **sep, const char **suf, const bool from_right)
+ ATTR_NONNULL(1, 3, 4, 5);
#define BLI_UTF8_MAX 6 /* mem */
#define BLI_UTF8_WIDTH_MAX 2 /* columns */
diff --git a/source/blender/blenlib/BLI_system.h b/source/blender/blenlib/BLI_system.h
index 8cdc9e4e6c5..cb8cb6f5a0d 100644
--- a/source/blender/blenlib/BLI_system.h
+++ b/source/blender/blenlib/BLI_system.h
@@ -27,6 +27,10 @@
int BLI_cpu_support_sse2(void);
+#if defined(NDEBUG) || !defined(__BLI_UTILDEFINES_H__)
+void BLI_system_backtrace(FILE *fp);
+#endif
+
/* getpid */
#ifdef WIN32
# define BLI_SYSTEM_PID_H <process.h>
@@ -35,4 +39,3 @@ int BLI_cpu_support_sse2(void);
#endif
#endif /* __BLI_SYSTEM_H__ */
-
diff --git a/source/blender/blenlib/BLI_task.h b/source/blender/blenlib/BLI_task.h
index c9cbaf997fb..780b0bfbbd6 100644
--- a/source/blender/blenlib/BLI_task.h
+++ b/source/blender/blenlib/BLI_task.h
@@ -73,7 +73,7 @@ typedef enum TaskPriority {
} TaskPriority;
typedef struct TaskPool TaskPool;
-typedef void (*TaskRunFunction)(TaskPool *pool, void *taskdata, int threadid);
+typedef void (*TaskRunFunction)(TaskPool *__restrict pool, void *taskdata, int threadid);
TaskPool *BLI_task_pool_create(TaskScheduler *scheduler, void *userdata);
void BLI_task_pool_free(TaskPool *pool);
@@ -88,6 +88,12 @@ void BLI_task_pool_cancel(TaskPool *pool);
/* stop all worker threads */
void BLI_task_pool_stop(TaskPool *pool);
+/* get number of threads allowed to be used by this pool */
+int BLI_pool_get_num_threads(TaskPool *pool);
+
+/* set number of threads allowed to be used by this pool */
+void BLI_pool_set_num_threads(TaskPool *pool, int num_threads);
+
/* for worker threads, test if canceled */
bool BLI_task_pool_canceled(TaskPool *pool);
@@ -100,6 +106,19 @@ ThreadMutex *BLI_task_pool_user_mutex(TaskPool *pool);
/* number of tasks done, for stats, don't use this to make decisions */
size_t BLI_task_pool_tasks_done(TaskPool *pool);
+/* Parallel for routines */
+typedef void (*TaskParallelRangeFunc)(void *userdata, int iter);
+void BLI_task_parallel_range_ex(
+ int start, int stop,
+ void *userdata,
+ TaskParallelRangeFunc func,
+ const int range_threshold,
+ const bool use_dynamic_scheduling);
+void BLI_task_parallel_range(
+ int start, int stop,
+ void *userdata,
+ TaskParallelRangeFunc func);
+
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/blenlib/BLI_threads.h b/source/blender/blenlib/BLI_threads.h
index 74291ca305e..6ae833d5ed7 100644
--- a/source/blender/blenlib/BLI_threads.h
+++ b/source/blender/blenlib/BLI_threads.h
@@ -89,6 +89,7 @@ int BLI_system_num_threads_override_get(void);
#define LOCK_MOVIECLIP 7
#define LOCK_COLORMANAGE 8
#define LOCK_FFTW 9
+#define LOCK_VIEW3D 10
void BLI_lock_thread(int type);
void BLI_unlock_thread(int type);
@@ -157,6 +158,7 @@ typedef pthread_cond_t ThreadCondition;
void BLI_condition_init(ThreadCondition *cond);
void BLI_condition_wait(ThreadCondition *cond, ThreadMutex *mutex);
+void BLI_condition_wait_global_mutex(ThreadCondition *cond, const int type);
void BLI_condition_notify_one(ThreadCondition *cond);
void BLI_condition_notify_all(ThreadCondition *cond);
void BLI_condition_end(ThreadCondition *cond);
@@ -174,6 +176,7 @@ void BLI_thread_queue_push(ThreadQueue *queue, void *work);
void *BLI_thread_queue_pop(ThreadQueue *queue);
void *BLI_thread_queue_pop_timeout(ThreadQueue *queue, int ms);
int BLI_thread_queue_size(ThreadQueue *queue);
+bool BLI_thread_queue_is_empty(ThreadQueue *queue);
void BLI_thread_queue_wait_finish(ThreadQueue *queue);
void BLI_thread_queue_nowait(ThreadQueue *queue);
diff --git a/source/blender/blenlib/BLI_timecode.h b/source/blender/blenlib/BLI_timecode.h
index b6cd0117bf5..235d928b460 100644
--- a/source/blender/blenlib/BLI_timecode.h
+++ b/source/blender/blenlib/BLI_timecode.h
@@ -31,11 +31,19 @@
* \ingroup BLI
*/
+#include "BLI_compiler_attrs.h"
+
size_t BLI_timecode_string_from_time(
char *str, const size_t len, const int power, const float time_seconds,
- const double scene_fps, const short timecode_style);
+ const double scene_fps, const short timecode_style)
+ ATTR_NONNULL();
size_t BLI_timecode_string_from_time_simple(
- char *str, const size_t len, const int power, const float time_seconds);
+ char *str, size_t maxlen, const double time_seconds)
+ ATTR_NONNULL();
+
+size_t BLI_timecode_string_from_time_seconds(
+ char *str, const size_t len, const int power, const float time_seconds)
+ ATTR_NONNULL();
#endif /* __BLI_TIMECODE_H__ */
diff --git a/source/blender/blenlib/BLI_utildefines.h b/source/blender/blenlib/BLI_utildefines.h
index a829cc60106..65e8dcdba4a 100644
--- a/source/blender/blenlib/BLI_utildefines.h
+++ b/source/blender/blenlib/BLI_utildefines.h
@@ -32,6 +32,10 @@
* \ingroup bli
*/
+#ifdef __cplusplus
+extern "C" {
+#endif
+
/* avoid many includes for now */
#include "BLI_sys_types.h"
#include "BLI_compiler_compat.h"
@@ -51,7 +55,8 @@
_49_, _50_, _51_, _52_, _53_, _54_, _55_, _56_, _57_, _58_, _59_, _60_, _61_, _62_, _63_, _64_, \
count, ...) count
#define _VA_NARGS_EXPAND(args) _VA_NARGS_RETURN_COUNT args
-#define _VA_NARGS_COUNT_MAX32(...) _VA_NARGS_EXPAND((__VA_ARGS__, \
+/* 64 args max */
+#define _VA_NARGS_COUNT(...) _VA_NARGS_EXPAND((__VA_ARGS__, \
64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, \
48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, \
32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, \
@@ -61,7 +66,7 @@
#define _VA_NARGS_OVERLOAD_MACRO(name, count) _VA_NARGS_OVERLOAD_MACRO1(name, count)
/* --- expose for re-use --- */
#define VA_NARGS_CALL_OVERLOAD(name, ...) \
- _VA_NARGS_GLUE(_VA_NARGS_OVERLOAD_MACRO(name, _VA_NARGS_COUNT_MAX32(__VA_ARGS__)), (__VA_ARGS__))
+ _VA_NARGS_GLUE(_VA_NARGS_OVERLOAD_MACRO(name, _VA_NARGS_COUNT(__VA_ARGS__)), (__VA_ARGS__))
/* useful for finding bad use of min/max */
#if 0
@@ -179,8 +184,10 @@
/* ELEM#(v, ...): is the first arg equal any others? */
/* internal helpers*/
+#define _VA_ELEM2(v, a) \
+ ((v) == (a))
#define _VA_ELEM3(v, a, b) \
- (((v) == (a)) || ((v) == (b)))
+ (_VA_ELEM2(v, a) || ((v) == (b)))
#define _VA_ELEM4(v, a, b, c) \
(_VA_ELEM3(v, a, b) || ((v) == (c)))
#define _VA_ELEM5(v, a, b, c, d) \
@@ -213,6 +220,8 @@
/* reusable ELEM macro */
#define ELEM(...) VA_NARGS_CALL_OVERLOAD(_VA_ELEM, __VA_ARGS__)
+/* no-op for expressions we don't want to instansiate, but must remian valid */
+#define EXPR_NOP(expr) (void)(0 ? ((void)(expr), 1) : 0)
/* shift around elements */
#define SHIFT3(type, a, b, c) { \
@@ -243,7 +252,7 @@
#define FTOCHAR(val) ((CHECK_TYPE_INLINE(val, float)), \
(char)(((val) <= 0.0f) ? 0 : (((val) > (1.0f - 0.5f / 255.0f)) ? 255 : ((255.0f * (val)) + 0.5f))))
#define FTOUSHORT(val) ((CHECK_TYPE_INLINE(val, float)), \
- ((val >= 1.0f - 0.5f / 65535) ? 65535 : (val <= 0.0f) ? 0 : (unsigned short)(val * 65535.0f + 0.5f)))
+ (unsigned short)((val >= 1.0f - 0.5f / 65535) ? 65535 : (val <= 0.0f) ? 0 : (val * 65535.0f + 0.5f)))
#define USHORTTOUCHAR(val) ((unsigned char)(((val) >= 65535 - 128) ? 255 : ((val) + 128) >> 8))
#define F3TOCHAR3(v2, v1) { \
(v1)[0] = FTOCHAR((v2[0])); \
@@ -309,10 +318,14 @@
#define ABS(a) ({ \
typeof(a) a_ = (a); \
((a_) < 0 ? (-(a_)) : (a_)); })
+#define SQUARE(a) ({ \
+ typeof(a) a_ = (a); \
+ ((a_) * (a_)); })
#else
#define ABS(a) ((a) < 0 ? (-(a)) : (a))
+#define SQUARE(a) ((a) * (a))
#endif
@@ -331,6 +344,60 @@
if ((a) < (b)) (a) = (b); \
} (void)0
+#define CLAMP2(vec, b, c) { \
+ CLAMP((vec)[0], b, c); \
+ CLAMP((vec)[1], b, c); \
+} (void)0
+
+#define CLAMP2_MIN(vec, b) { \
+ CLAMP_MIN((vec)[0], b); \
+ CLAMP_MIN((vec)[1], b); \
+} (void)0
+
+#define CLAMP2_MAX(vec, b) { \
+ CLAMP_MAX((vec)[0], b); \
+ CLAMP_MAX((vec)[1], b); \
+} (void)0
+
+#define CLAMP3(vec, b, c) { \
+ CLAMP((vec)[0], b, c); \
+ CLAMP((vec)[1], b, c); \
+ CLAMP((vec)[2], b, c); \
+} (void)0
+
+#define CLAMP3_MIN(vec, b) { \
+ CLAMP_MIN((vec)[0], b); \
+ CLAMP_MIN((vec)[1], b); \
+ CLAMP_MIN((vec)[2], b); \
+} (void)0
+
+#define CLAMP3_MAX(vec, b) { \
+ CLAMP_MAX((vec)[0], b); \
+ CLAMP_MAX((vec)[1], b); \
+ CLAMP_MAX((vec)[2], b); \
+} (void)0
+
+#define CLAMP4(vec, b, c) { \
+ CLAMP((vec)[0], b, c); \
+ CLAMP((vec)[1], b, c); \
+ CLAMP((vec)[2], b, c); \
+ CLAMP((vec)[3], b, c); \
+} (void)0
+
+#define CLAMP4_MIN(vec, b) { \
+ CLAMP_MIN((vec)[0], b); \
+ CLAMP_MIN((vec)[1], b); \
+ CLAMP_MIN((vec)[2], b); \
+ CLAMP_MIN((vec)[3], b); \
+} (void)0
+
+#define CLAMP4_MAX(vec, b) { \
+ CLAMP_MAX((vec)[0], b); \
+ CLAMP_MAX((vec)[1], b); \
+ CLAMP_MAX((vec)[2], b); \
+ CLAMP_MAX((vec)[3], b); \
+} (void)0
+
#define IS_EQ(a, b) ( \
CHECK_TYPE_INLINE(a, double), CHECK_TYPE_INLINE(b, double), \
((fabs((double)((a) - (b))) >= (double) FLT_EPSILON) ? false : true))
@@ -339,7 +406,7 @@
CHECK_TYPE_INLINE(a, float), CHECK_TYPE_INLINE(b, float), \
((fabsf((float)((a) - (b))) >= (float) FLT_EPSILON) ? false : true))
-#define IS_EQT(a, b, c) ((a > b) ? (((a - b) <= c) ? 1 : 0) : ((((b - a) <= c) ? 1 : 0)))
+#define IS_EQT(a, b, c) ((a > b) ? ((((a) - (b)) <= c) ? 1 : 0) : (((((b) - (a)) <= c) ? 1 : 0)))
#define IN_RANGE(a, b, c) ((b < c) ? ((b < a && a < c) ? 1 : 0) : ((c < a && a < b) ? 1 : 0))
#define IN_RANGE_INCL(a, b, c) ((b < c) ? ((b <= a && a <= c) ? 1 : 0) : ((c <= a && a <= b) ? 1 : 0))
@@ -354,7 +421,7 @@
/* array helpers */
#define ARRAY_LAST_ITEM(arr_start, arr_dtype, tot) \
- (arr_dtype *)((char *)arr_start + (sizeof(*((arr_dtype *)NULL)) * (size_t)(tot - 1)))
+ (arr_dtype *)((char *)(arr_start) + (sizeof(*((arr_dtype *)NULL)) * (size_t)(tot - 1)))
#define ARRAY_HAS_ITEM(arr_item, arr_start, tot) ( \
CHECK_TYPE_PAIR_INLINE(arr_start, arr_item), \
@@ -368,20 +435,69 @@
} (void)0
/* assuming a static array */
-#if defined(__GNUC__) && !defined(__cplusplus)
-# define ARRAY_SIZE(arr) \
- ((sizeof(struct {int isnt_array : ((void *)&(arr) == &(arr)[0]);}) * 0) + \
+#if defined(__GNUC__) && !defined(__cplusplus) && !defined(__clang__)
+# define ARRAY_SIZE(arr) \
+ ((sizeof(struct {int isnt_array : ((const void *)&(arr) == &(arr)[0]);}) * 0) + \
(sizeof(arr) / sizeof(*(arr))))
#else
# define ARRAY_SIZE(arr) (sizeof(arr) / sizeof(*(arr)))
#endif
+/* ARRAY_SET_ITEMS#(v, ...): set indices of array 'v' */
+/* internal helpers */
+#define _VA_ARRAY_SET_ITEMS2(v, a) \
+ ((v)[0] = (a))
+#define _VA_ARRAY_SET_ITEMS3(v, a, b) \
+ _VA_ARRAY_SET_ITEMS2(v, a); ((v)[1] = (b))
+#define _VA_ARRAY_SET_ITEMS4(v, a, b, c) \
+ _VA_ARRAY_SET_ITEMS3(v, a, b); ((v)[2] = (c))
+#define _VA_ARRAY_SET_ITEMS5(v, a, b, c, d) \
+ _VA_ARRAY_SET_ITEMS4(v, a, b, c); ((v)[3] = (d))
+#define _VA_ARRAY_SET_ITEMS6(v, a, b, c, d, e) \
+ _VA_ARRAY_SET_ITEMS5(v, a, b, c, d); ((v)[4] = (e))
+#define _VA_ARRAY_SET_ITEMS7(v, a, b, c, d, e, f) \
+ _VA_ARRAY_SET_ITEMS6(v, a, b, c, d, e); ((v)[5] = (f))
+#define _VA_ARRAY_SET_ITEMS8(v, a, b, c, d, e, f, g) \
+ _VA_ARRAY_SET_ITEMS7(v, a, b, c, d, e, f); ((v)[6] = (g))
+#define _VA_ARRAY_SET_ITEMS9(v, a, b, c, d, e, f, g, h) \
+ _VA_ARRAY_SET_ITEMS8(v, a, b, c, d, e, f, g); ((v)[7] = (h))
+#define _VA_ARRAY_SET_ITEMS10(v, a, b, c, d, e, f, g, h, i) \
+ _VA_ARRAY_SET_ITEMS9(v, a, b, c, d, e, f, g, h); ((v)[8] = (i))
+#define _VA_ARRAY_SET_ITEMS11(v, a, b, c, d, e, f, g, h, i, j) \
+ _VA_ARRAY_SET_ITEMS10(v, a, b, c, d, e, f, g, h, i); ((v)[9] = (j))
+#define _VA_ARRAY_SET_ITEMS12(v, a, b, c, d, e, f, g, h, i, j, k) \
+ _VA_ARRAY_SET_ITEMS11(v, a, b, c, d, e, f, g, h, i, j); ((v)[10] = (k))
+#define _VA_ARRAY_SET_ITEMS13(v, a, b, c, d, e, f, g, h, i, j, k, l) \
+ _VA_ARRAY_SET_ITEMS12(v, a, b, c, d, e, f, g, h, i, j, k); ((v)[11] = (l))
+#define _VA_ARRAY_SET_ITEMS14(v, a, b, c, d, e, f, g, h, i, j, k, l, m) \
+ _VA_ARRAY_SET_ITEMS13(v, a, b, c, d, e, f, g, h, i, j, k, l); ((v)[12] = (m))
+#define _VA_ARRAY_SET_ITEMS15(v, a, b, c, d, e, f, g, h, i, j, k, l, m, n) \
+ _VA_ARRAY_SET_ITEMS14(v, a, b, c, d, e, f, g, h, i, j, k, l, m); ((v)[13] = (n))
+#define _VA_ARRAY_SET_ITEMS16(v, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o) \
+ _VA_ARRAY_SET_ITEMS15(v, a, b, c, d, e, f, g, h, i, j, k, l, m, n); ((v)[14] = (o))
+#define _VA_ARRAY_SET_ITEMS17(v, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p) \
+ _VA_ARRAY_SET_ITEMS16(v, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o); ((v)[15] = (p))
+
+/* reusable ARRAY_SET_ITEMS macro */
+#define ARRAY_SET_ITEMS(...) { VA_NARGS_CALL_OVERLOAD(_VA_ARRAY_SET_ITEMS, __VA_ARGS__); } (void)0
+
+#if defined(__GNUC__) || defined(__clang__)
+#define POINTER_OFFSET(v, ofs) \
+ ((typeof(v))((char *)(v) + (ofs)))
+#else
+#define POINTER_OFFSET(v, ofs) \
+ ((void *)((char *)(v) + (ofs)))
+#endif
+
/* Like offsetof(typeof(), member), for non-gcc compilers */
#define OFFSETOF_STRUCT(_struct, _member) \
((((char *)&((_struct)->_member)) - ((char *)(_struct))) + sizeof((_struct)->_member))
-/* memcpy, skipping the first part of a struct,
- * ensures 'struct_dst' isn't const and that the offset can be computed at compile time */
+/**
+ * memcpy helper, skipping the first part of a struct,
+ * ensures 'struct_dst' isn't const and the offset can be computed at compile time.
+ * This isn't inclusive, the value of \a member isn't copied.
+ */
#define MEMCPY_STRUCT_OFS(struct_dst, struct_src, member) { \
CHECK_TYPE_NONCONST(struct_dst); \
((void)(struct_dst == struct_src), \
@@ -390,6 +506,13 @@
sizeof(*(struct_dst)) - OFFSETOF_STRUCT(struct_dst, member))); \
} (void)0
+#define MEMSET_STRUCT_OFS(struct_var, value, member) { \
+ CHECK_TYPE_NONCONST(struct_var); \
+ memset((char *)(struct_var) + OFFSETOF_STRUCT(struct_var, member), \
+ value, \
+ sizeof(*(struct_var)) - OFFSETOF_STRUCT(struct_var, member)); \
+} (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)! */
#define SET_INT_IN_POINTER(i) ((void *)(intptr_t)(i))
@@ -410,6 +533,11 @@
/* generic strcmp macros */
+#if defined(_MSC_VER)
+# define strcasecmp _stricmp
+# define strncasecmp _strnicmp
+#endif
+
#define STREQ(a, b) (strcmp(a, b) == 0)
#define STRCASEEQ(a, b) (strcasecmp(a, b) == 0)
#define STREQLEN(a, b, n) (strncmp(a, b, n) == 0)
@@ -433,6 +561,62 @@
# define UNUSED_FUNCTION(x) UNUSED_ ## x
#endif
+/**
+ * UNUSED_VARS#(a, ...): quiet unused warnings
+ *
+ * \code{.py}
+ * for i in range(16):
+ * args = [(chr(ord('a') + (c % 26)) + (chr(ord('0') + (c // 26)))) for c in range(i + 1)]
+ * print("#define _VA_UNUSED_VARS_%d(%s) \\" % (i + 1, ", ".join(args)))
+ * print("\t((void)(%s)%s)" %
+ * (args[0], ((", _VA_UNUSED_VARS_" + str(i) + "(%s)") if i else "%s") % ", ".join((args[1:]))))
+ * \endcode
+ */
+
+#define _VA_UNUSED_VARS_1(a0) \
+ ((void)(a0))
+#define _VA_UNUSED_VARS_2(a0, b0) \
+ ((void)(a0), _VA_UNUSED_VARS_1(b0))
+#define _VA_UNUSED_VARS_3(a0, b0, c0) \
+ ((void)(a0), _VA_UNUSED_VARS_2(b0, c0))
+#define _VA_UNUSED_VARS_4(a0, b0, c0, d0) \
+ ((void)(a0), _VA_UNUSED_VARS_3(b0, c0, d0))
+#define _VA_UNUSED_VARS_5(a0, b0, c0, d0, e0) \
+ ((void)(a0), _VA_UNUSED_VARS_4(b0, c0, d0, e0))
+#define _VA_UNUSED_VARS_6(a0, b0, c0, d0, e0, f0) \
+ ((void)(a0), _VA_UNUSED_VARS_5(b0, c0, d0, e0, f0))
+#define _VA_UNUSED_VARS_7(a0, b0, c0, d0, e0, f0, g0) \
+ ((void)(a0), _VA_UNUSED_VARS_6(b0, c0, d0, e0, f0, g0))
+#define _VA_UNUSED_VARS_8(a0, b0, c0, d0, e0, f0, g0, h0) \
+ ((void)(a0), _VA_UNUSED_VARS_7(b0, c0, d0, e0, f0, g0, h0))
+#define _VA_UNUSED_VARS_9(a0, b0, c0, d0, e0, f0, g0, h0, i0) \
+ ((void)(a0), _VA_UNUSED_VARS_8(b0, c0, d0, e0, f0, g0, h0, i0))
+#define _VA_UNUSED_VARS_10(a0, b0, c0, d0, e0, f0, g0, h0, i0, j0) \
+ ((void)(a0), _VA_UNUSED_VARS_9(b0, c0, d0, e0, f0, g0, h0, i0, j0))
+#define _VA_UNUSED_VARS_11(a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0) \
+ ((void)(a0), _VA_UNUSED_VARS_10(b0, c0, d0, e0, f0, g0, h0, i0, j0, k0))
+#define _VA_UNUSED_VARS_12(a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0) \
+ ((void)(a0), _VA_UNUSED_VARS_11(b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0))
+#define _VA_UNUSED_VARS_13(a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0) \
+ ((void)(a0), _VA_UNUSED_VARS_12(b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0))
+#define _VA_UNUSED_VARS_14(a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0) \
+ ((void)(a0), _VA_UNUSED_VARS_13(b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0))
+#define _VA_UNUSED_VARS_15(a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0) \
+ ((void)(a0), _VA_UNUSED_VARS_14(b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0))
+#define _VA_UNUSED_VARS_16(a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0) \
+ ((void)(a0), _VA_UNUSED_VARS_15(b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0))
+
+
+/* reusable ELEM macro */
+#define UNUSED_VARS(...) VA_NARGS_CALL_OVERLOAD(_VA_UNUSED_VARS_, __VA_ARGS__)
+
+/* for debug-only variables */
+#ifndef NDEBUG
+# define UNUSED_VARS_NDEBUG(...)
+#else
+# define UNUSED_VARS_NDEBUG UNUSED_VARS
+#endif
+
/*little macro so inline keyword works*/
#if defined(_MSC_VER)
# define BLI_INLINE static __forceinline
@@ -450,6 +634,7 @@
* for aborting need to define WITH_ASSERT_ABORT
*/
#ifndef NDEBUG
+extern void BLI_system_backtrace(FILE *fp);
# ifdef WITH_ASSERT_ABORT
# define _BLI_DUMMY_ABORT abort
# else
@@ -459,6 +644,7 @@
# define BLI_assert(a) \
(void)((!(a)) ? ( \
( \
+ BLI_system_backtrace(stderr), \
fprintf(stderr, \
"BLI_assert failed: %s:%d, %s(), at \'%s\'\n", \
__FILE__, __LINE__, __func__, STRINGIFY(a)), \
@@ -498,4 +684,8 @@
# define UNLIKELY(x) (x)
#endif
+#ifdef __cplusplus
+}
+#endif
+
#endif /* __BLI_UTILDEFINES_H__ */
diff --git a/source/blender/blenlib/BLI_winstuff.h b/source/blender/blenlib/BLI_winstuff.h
index f40359ec3dc..8cf6f188e19 100644
--- a/source/blender/blenlib/BLI_winstuff.h
+++ b/source/blender/blenlib/BLI_winstuff.h
@@ -132,17 +132,8 @@ struct dirent {
char *d_name;
};
-typedef struct _DIR {
- HANDLE handle;
- WIN32_FIND_DATAW data;
- char path[MAX_PATH];
- long dd_loc;
- long dd_size;
- char dd_buf[4096];
- void *dd_direct;
-
- struct dirent direntry;
-} DIR;
+/* intentionally opaque to users */
+typedef struct __dirstream DIR;
DIR *opendir(const char *path);
struct dirent *readdir(DIR *dp);
diff --git a/source/blender/blenlib/CMakeLists.txt b/source/blender/blenlib/CMakeLists.txt
index 9efa20da13e..dcf7c3b5d39 100644
--- a/source/blender/blenlib/CMakeLists.txt
+++ b/source/blender/blenlib/CMakeLists.txt
@@ -23,15 +23,14 @@
#
# ***** END GPL LICENSE BLOCK *****
-# XXX allowing blenkernel and RNA includes in blenlib is a hack,
-# but needed in a few places atm (bpath.c for instance)
set(INC
.
# ../blenkernel # dont add this back!
../makesdna
- ../../../intern/ghost
../../../intern/guardedalloc
+ ../../../intern/atomic
../../../extern/wcwidth
+ ../../../extern/Eigen3
)
set(INC_SYS
@@ -44,6 +43,7 @@ set(SRC
intern/BLI_array.c
intern/BLI_dial.c
intern/BLI_dynstr.c
+ intern/BLI_filelist.c
intern/BLI_ghash.c
intern/BLI_heap.c
intern/BLI_kdopbvh.c
@@ -52,6 +52,8 @@ set(SRC
intern/BLI_memarena.c
intern/BLI_mempool.c
intern/DLRB_tree.c
+ intern/array_utils.c
+ intern/astar.c
intern/boxpack2d.c
intern/buffer.c
intern/callbacks.c
@@ -65,11 +67,15 @@ set(SRC
intern/freetypefont.c
intern/graph.c
intern/gsqueue.c
+ intern/hash_md5.c
+ intern/hash_mm2a.c
intern/jitter.c
intern/lasso.c
+ intern/list_sort_impl.h
intern/listbase.c
intern/math_base.c
intern/math_base_inline.c
+ intern/math_bits_inline.c
intern/math_color.c
intern/math_color_blend_inline.c
intern/math_color_inline.c
@@ -78,12 +84,14 @@ set(SRC
intern/math_interp.c
intern/math_matrix.c
intern/math_rotation.c
+ intern/math_solvers.c
+ intern/math_statistics.c
intern/math_vector.c
intern/math_vector_inline.c
- intern/md5.c
intern/noise.c
intern/path_util.c
intern/polyfill2d.c
+ intern/polyfill2d_beautify.c
intern/quadric.c
intern/rand.c
intern/rct.c
@@ -111,6 +119,8 @@ set(SRC
BLI_alloca.h
BLI_args.h
BLI_array.h
+ BLI_array_utils.h
+ BLI_astar.h
BLI_bitmap.h
BLI_blenlib.h
BLI_boxpack2d.h
@@ -134,6 +144,8 @@ set(SRC
BLI_ghash.h
BLI_graph.h
BLI_gsqueue.h
+ BLI_hash_md5.h
+ BLI_hash_mm2a.h
BLI_heap.h
BLI_jitter.h
BLI_kdopbvh.h
@@ -145,6 +157,7 @@ set(SRC
BLI_listbase.h
BLI_math.h
BLI_math_base.h
+ BLI_math_bits.h
BLI_math_color.h
BLI_math_color_blend.h
BLI_math_geom.h
@@ -152,13 +165,15 @@ set(SRC
BLI_math_interp.h
BLI_math_matrix.h
BLI_math_rotation.h
+ BLI_math_solvers.h
+ BLI_math_statistics.h
BLI_math_vector.h
- BLI_md5.h
BLI_memarena.h
BLI_mempool.h
BLI_noise.h
BLI_path_util.h
BLI_polyfill2d.h
+ BLI_polyfill2d_beautify.h
BLI_quadric.h
BLI_rand.h
BLI_rect.h
@@ -187,13 +202,6 @@ set(SRC
PIL_time_utildefines.h
)
-if(WITH_BINRELOC)
- list(APPEND INC_SYS
- ${BINRELOC_INCLUDE_DIRS}
- )
- add_definitions(-DWITH_BINRELOC)
-endif()
-
if(WITH_MEM_VALGRIND)
add_definitions(-DWITH_MEM_VALGRIND)
endif()
@@ -204,10 +212,15 @@ if(WIN32)
)
endif()
-blender_add_lib(bf_blenlib "${SRC}" "${INC}" "${INC_SYS}")
+# no need to compile object files for inline headers.
+set_source_files_properties(
+ intern/math_base_inline.c
+ intern/math_bits_inline.c
+ intern/math_color_blend_inline.c
+ intern/math_color_inline.c
+ intern/math_geom_inline.c
+ intern/math_vector_inline.c
+ PROPERTIES HEADER_FILE_ONLY TRUE
+)
-if(MSVC)
- # Quiet warning about inline math library files that do not export symbols.
- # (normally you'd exclude from project, but we still want to see the files in MSVC)
- set_target_properties(bf_blenlib PROPERTIES STATIC_LIBRARY_FLAGS /ignore:4221)
-endif()
+blender_add_lib(bf_blenlib "${SRC}" "${INC}" "${INC_SYS}")
diff --git a/source/blender/blenlib/PIL_time.h b/source/blender/blenlib/PIL_time.h
index 158559fa3d9..6e347339980 100644
--- a/source/blender/blenlib/PIL_time.h
+++ b/source/blender/blenlib/PIL_time.h
@@ -37,7 +37,7 @@
extern "C" {
#endif
-extern
+extern
/** Return an indication of time, expressed as
* seconds since some fixed point. Successive calls
* are guaranteed to generate values greater than or
@@ -45,6 +45,12 @@ extern
*/
double PIL_check_seconds_timer(void);
+extern
+/**
+ * int version of #PIL_check_seconds_timer
+ */
+long int PIL_check_seconds_timer_i(void);
+
/**
* Platform-independent sleep function.
* \param ms Number of milliseconds to sleep
diff --git a/source/blender/blenlib/SConscript b/source/blender/blenlib/SConscript
index b712d2032bf..0e4b9bf4efd 100644
--- a/source/blender/blenlib/SConscript
+++ b/source/blender/blenlib/SConscript
@@ -34,8 +34,9 @@ cflags=''
incs = [
'.',
'#/extern/wcwidth',
- '#/intern/ghost',
+ '#/extern/Eigen3',
'#/intern/guardedalloc',
+ '#/intern/atomic',
'../makesdna',
env['BF_FREETYPE_INC'],
env['BF_ZLIB_INC'],
@@ -44,10 +45,6 @@ incs = ' '.join(incs)
defs = []
-if env['WITH_BF_BINRELOC']:
- incs += ' ../../../extern/binreloc/include'
- defs.append('WITH_BINRELOC')
-
if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'linuxcross', 'win64-vc', 'win64-mingw'):
incs += ' ' + env['BF_PTHREADS_INC']
incs += ' ../../../intern/utfconv'
diff --git a/source/blender/blenlib/intern/BLI_args.c b/source/blender/blenlib/intern/BLI_args.c
index 49a3c466727..9faf6c93447 100644
--- a/source/blender/blenlib/intern/BLI_args.c
+++ b/source/blender/blenlib/intern/BLI_args.c
@@ -100,7 +100,7 @@ static bool keycmp(const void *a, const void *b)
return (BLI_strcasecmp(ka->arg, kb->arg) != 0);
}
else {
- return (strcmp(ka->arg, kb->arg) != 0);
+ return (!STREQ(ka->arg, kb->arg));
}
}
else {
diff --git a/source/blender/blenlib/intern/BLI_array.c b/source/blender/blenlib/intern/BLI_array.c
index da2eef8ab6a..f681d222e69 100644
--- a/source/blender/blenlib/intern/BLI_array.c
+++ b/source/blender/blenlib/intern/BLI_array.c
@@ -30,19 +30,14 @@
* \ingroup bli
* \brief A (mainly) macro array library.
*
- * This library needs to be changed to not use macros quite so heavily,
- * and to be more of a complete array API. The way arrays are
- * exposed to client code as normal C arrays is very useful though, imho.
- * it does require some use of macros, however.
+ * This is an array library, used to manage array (re)allocation.
*
- * anyway, it's used a bit too heavily to simply rewrite as a
- * more "correct" solution without macros entirely. I originally wrote this
- * to be very easy to use, without the normal pain of most array libraries.
- * This was especially helpful when it came to the massive refactors necessary
- * for bmesh, and really helped to speed the process up. - joeedh
+ * \note This is primarily accessed via macros,
+ * functions are used to implement some of the internals.
*
- * little array macro library. example of usage:
+ * Example usage:
*
+ * \code{.c}
* int *arr = NULL;
* BLI_array_declare(arr);
* int i;
@@ -52,20 +47,19 @@
* arr[i] = something;
* }
* BLI_array_free(arr);
+ * \endcode
*
- * arrays are buffered, using double-buffering (so on each reallocation,
- * the array size is doubled). supposedly this should give good Big Oh
- * behavior, though it may not be the best in practice.
+ * Arrays are over allocated, so each reallocation the array size is doubled.
+ * In situations where contiguous array access isn't needed,
+ * other solutions for allocation are available.
+ * Consider using on of: BLI_memarena.c, BLI_mempool.c, BLi_stack.c
*/
#include <string.h>
-#include <stdlib.h>
#include "BLI_array.h"
#include "BLI_sys_types.h"
-#include "BLI_utildefines.h"
-#include "BLI_alloca.h"
#include "MEM_guardedalloc.h"
@@ -100,55 +94,3 @@ void _bli_array_grow_func(void **arr_p, const void *arr_static,
arr_count += num;
#endif
}
-
-void _bli_array_reverse(void *arr_v, unsigned int arr_len, size_t arr_stride)
-{
- const unsigned int arr_half_stride = (arr_len / 2) * arr_stride;
- unsigned int i, i_end;
- char *arr = arr_v;
- char *buf = BLI_array_alloca(buf, arr_stride);
-
- for (i = 0, i_end = (arr_len - 1) * arr_stride;
- i < arr_half_stride;
- i += arr_stride, i_end -= arr_stride)
- {
- memcpy(buf, &arr[i], arr_stride);
- memcpy(&arr[i], &arr[i_end], arr_stride);
- memcpy(&arr[i_end], buf, arr_stride);
- }
-}
-
-void _bli_array_wrap(void *arr_v, unsigned int arr_len, size_t arr_stride, int dir)
-{
- char *arr = arr_v;
- char *buf = BLI_array_alloca(buf, arr_stride);
-
- if (dir == -1) {
- memcpy(buf, arr, arr_stride);
- memmove(arr, arr + arr_stride, arr_stride * (arr_len - 1));
- memcpy(arr + (arr_stride * (arr_len - 1)), buf, arr_stride);
- }
- else if (dir == 1) {
- memcpy(buf, arr + (arr_stride * (arr_len - 1)), arr_stride);
- memmove(arr + arr_stride, arr, arr_stride * (arr_len - 1));
- memcpy(arr, buf, arr_stride);
- }
- else {
- BLI_assert(0);
- }
-}
-
-/**
- * \note Not efficient, use for error checks/asserts.
- */
-int _bli_array_findindex(const void *arr, unsigned int arr_len, size_t arr_stride, const void *p)
-{
- const char *arr_step = (const char *)arr;
- unsigned int i;
- for (i = 0; i < arr_len; i++, arr_step += arr_stride) {
- if (memcmp(arr_step, p, arr_stride) == 0) {
- return (int)i;
- }
- }
- return -1;
-}
diff --git a/source/blender/blenlib/intern/BLI_dynstr.c b/source/blender/blenlib/intern/BLI_dynstr.c
index 8617132e988..ecd4a6e6b09 100644
--- a/source/blender/blenlib/intern/BLI_dynstr.c
+++ b/source/blender/blenlib/intern/BLI_dynstr.c
@@ -258,11 +258,11 @@ int BLI_dynstr_get_len(DynStr *ds)
/**
* Get a DynStr's contents as a c-string.
- * <i> The str argument must be allocated to be at
- * least the size of BLI_dynstr_get_len(ds) + 1. </i>
+ * The \a rets argument must be allocated to be at
+ * least the size of ``BLI_dynstr_get_len(ds) + 1``.
*
- * \param ds The DynStr of interest.
- * \param str The string to fill.
+ * \param ds: The DynStr of interest.
+ * \param rets: The string to fill.
*/
void BLI_dynstr_get_cstring_ex(DynStr *__restrict ds, char *__restrict rets)
{
diff --git a/source/blender/blenlib/intern/BLI_filelist.c b/source/blender/blenlib/intern/BLI_filelist.c
new file mode 100644
index 00000000000..62690ff4f3c
--- /dev/null
+++ b/source/blender/blenlib/intern/BLI_filelist.c
@@ -0,0 +1,412 @@
+/*
+ * ***** 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/BLI_filelist.c
+ * \ingroup bli
+ */
+
+#include <sys/types.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#ifndef WIN32
+# include <dirent.h>
+#endif
+
+#include <time.h>
+#include <sys/stat.h>
+#include <string.h> /* strcpy etc.. */
+
+#ifdef WIN32
+# include <io.h>
+# include <direct.h>
+# include "BLI_winstuff.h"
+# include "utfconv.h"
+#else
+# include <sys/ioctl.h>
+# include <unistd.h>
+# include <pwd.h>
+#endif
+
+/* lib includes */
+#include "MEM_guardedalloc.h"
+
+#include "DNA_listBase.h"
+
+#include "BLI_listbase.h"
+#include "BLI_string.h"
+#include "BLI_fileops.h"
+#include "BLI_fileops_types.h"
+#include "BLI_path_util.h"
+
+#include "../imbuf/IMB_imbuf.h"
+
+
+/*
+ * Ordering function for sorting lists of files/directories. Returns -1 if
+ * entry1 belongs before entry2, 0 if they are equal, 1 if they should be swapped.
+ */
+static int bli_compare(struct direntry *entry1, struct direntry *entry2)
+{
+ /* type is equal to stat.st_mode */
+
+ /* directories come before non-directories */
+ if (S_ISDIR(entry1->type)) {
+ if (S_ISDIR(entry2->type) == 0) return (-1);
+ }
+ else {
+ if (S_ISDIR(entry2->type)) return (1);
+ }
+ /* non-regular files come after regular files */
+ if (S_ISREG(entry1->type)) {
+ if (S_ISREG(entry2->type) == 0) return (-1);
+ }
+ else {
+ if (S_ISREG(entry2->type)) return (1);
+ }
+ /* arbitrary, but consistent, ordering of different types of non-regular files */
+ if ((entry1->type & S_IFMT) < (entry2->type & S_IFMT)) return (-1);
+ if ((entry1->type & S_IFMT) > (entry2->type & S_IFMT)) return (1);
+
+ /* OK, now we know their S_IFMT fields are the same, go on to a name comparison */
+ /* make sure "." and ".." are always first */
+ if (FILENAME_IS_CURRENT(entry1->relname)) return (-1);
+ if (FILENAME_IS_CURRENT(entry2->relname)) return (1);
+ if (FILENAME_IS_PARENT(entry1->relname)) return (-1);
+ if (FILENAME_IS_PARENT(entry2->relname)) return (1);
+
+ return (BLI_natstrcmp(entry1->relname, entry2->relname));
+}
+
+
+struct BuildDirCtx {
+ struct direntry *files; /* array[nrfiles] */
+ int nrfiles;
+};
+
+/**
+ * Scans the directory named *dirname and appends entries for its contents to files.
+ */
+static void bli_builddir(struct BuildDirCtx *dir_ctx, const char *dirname)
+{
+ struct ListBase dirbase = {NULL, NULL};
+ int newnum = 0;
+ DIR *dir;
+
+ if ((dir = opendir(dirname)) != NULL) {
+ const struct dirent *fname;
+ bool has_current = false, has_parent = false;
+
+ while ((fname = readdir(dir)) != NULL) {
+ struct dirlink * const dlink = (struct dirlink *)malloc(sizeof(struct dirlink));
+ if (dlink != NULL) {
+ dlink->name = BLI_strdup(fname->d_name);
+ if (FILENAME_IS_PARENT(dlink->name)) {
+ has_parent = true;
+ }
+ else if (FILENAME_IS_CURRENT(dlink->name)) {
+ has_current = true;
+ }
+ BLI_addhead(&dirbase, dlink);
+ newnum++;
+ }
+ }
+
+ if (!has_parent) {
+ char pardir[FILE_MAXDIR];
+
+ BLI_strncpy(pardir, dirname, sizeof(pardir));
+ if (BLI_parent_dir(pardir) && (BLI_access(pardir, R_OK) == 0)) {
+ struct dirlink * const dlink = (struct dirlink *)malloc(sizeof(struct dirlink));
+ if (dlink != NULL) {
+ dlink->name = BLI_strdup(FILENAME_PARENT);
+ BLI_addhead(&dirbase, dlink);
+ newnum++;
+ }
+ }
+ }
+ if (!has_current) {
+ struct dirlink * const dlink = (struct dirlink *)malloc(sizeof(struct dirlink));
+ if (dlink != NULL) {
+ dlink->name = BLI_strdup(FILENAME_CURRENT);
+ BLI_addhead(&dirbase, dlink);
+ newnum++;
+ }
+ }
+
+ if (newnum) {
+ if (dir_ctx->files) {
+ void * const tmp = MEM_reallocN(dir_ctx->files, (dir_ctx->nrfiles + newnum) * sizeof(struct direntry));
+ if (tmp) {
+ dir_ctx->files = (struct direntry *)tmp;
+ }
+ else { /* realloc fail */
+ MEM_freeN(dir_ctx->files);
+ dir_ctx->files = NULL;
+ }
+ }
+
+ if (dir_ctx->files == NULL)
+ dir_ctx->files = (struct direntry *)MEM_mallocN(newnum * sizeof(struct direntry), __func__);
+
+ if (dir_ctx->files) {
+ struct dirlink * dlink = (struct dirlink *) dirbase.first;
+ struct direntry *file = &dir_ctx->files[dir_ctx->nrfiles];
+ while (dlink) {
+ char fullname[PATH_MAX];
+ memset(file, 0, sizeof(struct direntry));
+ file->relname = dlink->name;
+ file->path = BLI_strdupcat(dirname, dlink->name);
+ BLI_join_dirfile(fullname, sizeof(fullname), dirname, dlink->name);
+ if (BLI_stat(fullname, &file->s) != -1) {
+ file->type = file->s.st_mode;
+ }
+ else if (FILENAME_IS_CURRPAR(file->relname)) {
+ /* Hack around for UNC paths on windows - does not support stat on '\\SERVER\foo\..', sigh... */
+ file->type |= S_IFDIR;
+ }
+ dir_ctx->nrfiles++;
+ file++;
+ dlink = dlink->next;
+ }
+ }
+ else {
+ printf("Couldn't get memory for dir\n");
+ exit(1);
+ }
+
+ BLI_freelist(&dirbase);
+ if (dir_ctx->files) {
+ qsort(dir_ctx->files, dir_ctx->nrfiles, sizeof(struct direntry), (int (*)(const void *, const void *))bli_compare);
+ }
+ }
+ else {
+ printf("%s empty directory\n", dirname);
+ }
+
+ closedir(dir);
+ }
+ else {
+ printf("%s non-existent directory\n", dirname);
+ }
+}
+
+/**
+ * Scans the contents of the directory named *dirname, and allocates and fills in an
+ * array of entries describing them in *filelist.
+ *
+ * \return The length of filelist array.
+ */
+unsigned int BLI_filelist_dir_contents(const char *dirname, struct direntry **r_filelist)
+{
+ struct BuildDirCtx dir_ctx;
+
+ dir_ctx.nrfiles = 0;
+ dir_ctx.files = NULL;
+
+ bli_builddir(&dir_ctx, dirname);
+
+ if (dir_ctx.files) {
+ *r_filelist = dir_ctx.files;
+ }
+ else {
+ // keep blender happy. Blender stores this in a variable
+ // where 0 has special meaning.....
+ *r_filelist = MEM_mallocN(sizeof(**r_filelist), __func__);
+ }
+
+ return dir_ctx.nrfiles;
+}
+
+/**
+ * Convert given entry's size into human-readable strings.
+ *
+ */
+void BLI_filelist_entry_size_to_string(
+ const struct stat *st, const uint64_t sz, const bool compact, char r_size[FILELIST_DIRENTRY_SIZE_LEN])
+{
+ double size;
+ const char *fmt;
+ const char *units[] = {"KiB", "MiB", "GiB", "TiB", NULL};
+ const char *units_compact[] = {"K", "M", "G", "T", NULL};
+ const char *unit = "B";
+
+ /*
+ * Seems st_size is signed 32-bit value in *nix and Windows. This
+ * will buy us some time until files get bigger than 4GB or until
+ * everyone starts using __USE_FILE_OFFSET64 or equivalent.
+ */
+ size = (double)(st ? st->st_size : sz);
+
+ if (size > 1024.0) {
+ const char **u;
+ for (u = compact ? units_compact : units, size /= 1024.0; size > 1024.0 && *(u + 1); u++, size /= 1024.0);
+ fmt = size > 100.0 ? "%.0f %s" : (size > 10.0 ? "%.1f %s" : "%.2f %s");
+ unit = *u;
+ }
+ else {
+ fmt = "%.0f %s";
+ }
+
+ BLI_snprintf(r_size, sizeof(*r_size) * FILELIST_DIRENTRY_SIZE_LEN, fmt, size, unit);
+}
+
+/**
+ * Convert given entry's modes into human-readable strings.
+ *
+ */
+void BLI_filelist_entry_mode_to_string(
+ const struct stat *st, const bool UNUSED(compact), char r_mode1[FILELIST_DIRENTRY_MODE_LEN],
+ char r_mode2[FILELIST_DIRENTRY_MODE_LEN], char r_mode3[FILELIST_DIRENTRY_MODE_LEN])
+{
+ const char *types[8] = {"---", "--x", "-w-", "-wx", "r--", "r-x", "rw-", "rwx"};
+
+#ifdef WIN32
+ BLI_strncpy(r_mode1, types[0], sizeof(*r_mode1) * FILELIST_DIRENTRY_MODE_LEN);
+ BLI_strncpy(r_mode2, types[0], sizeof(*r_mode2) * FILELIST_DIRENTRY_MODE_LEN);
+ BLI_strncpy(r_mode3, types[0], sizeof(*r_mode3) * FILELIST_DIRENTRY_MODE_LEN);
+#else
+ const int mode = st->st_mode;
+
+ BLI_strncpy(r_mode1, types[(mode & 0700) >> 6], sizeof(*r_mode1) * FILELIST_DIRENTRY_MODE_LEN);
+ BLI_strncpy(r_mode2, types[(mode & 0070) >> 3], sizeof(*r_mode2) * FILELIST_DIRENTRY_MODE_LEN);
+ BLI_strncpy(r_mode3, types[(mode & 0007)], sizeof(*r_mode3) * FILELIST_DIRENTRY_MODE_LEN);
+
+ if (((mode & S_ISGID) == S_ISGID) && (r_mode2[2] == '-')) r_mode2[2] = 'l';
+
+ if (mode & (S_ISUID | S_ISGID)) {
+ if (r_mode1[2] == 'x') r_mode1[2] = 's';
+ else r_mode1[2] = 'S';
+
+ if (r_mode2[2] == 'x') r_mode2[2] = 's';
+ }
+
+ if (mode & S_ISVTX) {
+ if (r_mode3[2] == 'x') r_mode3[2] = 't';
+ else r_mode3[2] = 'T';
+ }
+#endif
+}
+
+/**
+ * Convert given entry's owner into human-readable strings.
+ *
+ */
+void BLI_filelist_entry_owner_to_string(
+ const struct stat *st, const bool UNUSED(compact), char r_owner[FILELIST_DIRENTRY_OWNER_LEN])
+{
+#ifdef WIN32
+ strcpy(r_owner, "unknown");
+#else
+ struct passwd *pwuser = getpwuid(st->st_uid);
+
+ if (pwuser) {
+ BLI_strncpy(r_owner, pwuser->pw_name, sizeof(*r_owner) * FILELIST_DIRENTRY_OWNER_LEN);
+ }
+ else {
+ BLI_snprintf(r_owner, sizeof(*r_owner) * FILELIST_DIRENTRY_OWNER_LEN, "%u", st->st_uid);
+ }
+#endif
+}
+
+/**
+ * Convert given entry's time into human-readable strings.
+ */
+void BLI_filelist_entry_datetime_to_string(
+ const struct stat *st, const int64_t ts, const bool compact,
+ char r_time[FILELIST_DIRENTRY_TIME_LEN], char r_date[FILELIST_DIRENTRY_DATE_LEN])
+{
+ const struct tm *tm = localtime(st ? &st->st_mtime : &ts);
+ const time_t zero = 0;
+
+ /* Prevent impossible dates in windows. */
+ if (tm == NULL) {
+ tm = localtime(&zero);
+ }
+
+ if (r_time) {
+ strftime(r_time, sizeof(*r_time) * FILELIST_DIRENTRY_TIME_LEN, "%H:%M", tm);
+ }
+ if (r_date) {
+ strftime(r_date, sizeof(*r_date) * FILELIST_DIRENTRY_DATE_LEN, compact ? "%d/%m/%y" : "%d-%b-%y", tm);
+ }
+}
+
+/**
+ * Deep-duplicate of a single direntry.
+ *
+ * \param dup_poin If given, called for each non-NULL direntry->poin. Otherwise, pointer is always simply copied over.
+ */
+void BLI_filelist_entry_duplicate(struct direntry *dst, const struct direntry *src)
+{
+ *dst = *src;
+ if (dst->relname) {
+ dst->relname = MEM_dupallocN(src->relname);
+ }
+ if (dst->path) {
+ dst->path = MEM_dupallocN(src->path);
+ }
+}
+
+/**
+ * Deep-duplicate of an array of direntries, including the array itself.
+ *
+ * \param dup_poin If given, called for each non-NULL direntry->poin. Otherwise, pointer is always simply copied over.
+ */
+void BLI_filelist_duplicate(
+ struct direntry **dest_filelist, struct direntry * const src_filelist, const unsigned int nrentries)
+{
+ unsigned int i;
+
+ *dest_filelist = MEM_mallocN(sizeof(**dest_filelist) * (size_t)(nrentries), __func__);
+ for (i = 0; i < nrentries; ++i) {
+ struct direntry * const src = &src_filelist[i];
+ struct direntry *dst = &(*dest_filelist)[i];
+ BLI_filelist_entry_duplicate(dst, src);
+ }
+}
+
+/**
+ * frees storage for a single direntry, not the direntry itself.
+ */
+void BLI_filelist_entry_free(struct direntry *entry)
+{
+ if (entry->relname) {
+ MEM_freeN((void *)entry->relname);
+ }
+ if (entry->path) {
+ MEM_freeN((void *)entry->path);
+ }
+}
+
+/**
+ * frees storage for an array of direntries, including the array itself.
+ */
+void BLI_filelist_free(struct direntry *filelist, const unsigned int nrentries)
+{
+ unsigned int i;
+ for (i = 0; i < nrentries; ++i) {
+ BLI_filelist_entry_free(&filelist[i]);
+ }
+
+ if (filelist != NULL) {
+ MEM_freeN(filelist);
+ }
+}
diff --git a/source/blender/blenlib/intern/BLI_ghash.c b/source/blender/blenlib/intern/BLI_ghash.c
index 6747e5c4e7e..7e6dabdffef 100644
--- a/source/blender/blenlib/intern/BLI_ghash.c
+++ b/source/blender/blenlib/intern/BLI_ghash.c
@@ -28,24 +28,31 @@
/** \file blender/blenlib/intern/BLI_ghash.c
* \ingroup bli
*
- * A general (pointer -> pointer) hash table ADT
+ * A general (pointer -> pointer) chaining hash table
+ * for 'Abstract Data Types' (known as an ADT Hash Table).
*
* \note edgehash.c is based on this, make sure they stay in sync.
*/
#include <string.h>
#include <stdlib.h>
+#include <stdarg.h>
#include <limits.h>
#include "MEM_guardedalloc.h"
#include "BLI_sys_types.h" /* for intptr_t support */
#include "BLI_utildefines.h"
+#include "BLI_hash_mm2a.h"
#include "BLI_mempool.h"
+
+#define GHASH_INTERNAL_API
#include "BLI_ghash.h"
#include "BLI_strict_flags.h"
+#define GHASH_USE_MODULO_BUCKETS
+/* Also used by smallhash! */
const unsigned int hashsizes[] = {
5, 11, 17, 37, 67, 131, 257, 521, 1031, 2053, 4099, 8209,
16411, 32771, 65537, 131101, 262147, 524309, 1048583, 2097169,
@@ -53,24 +60,43 @@ const unsigned int hashsizes[] = {
268435459
};
-/* internal flag to ensure sets values aren't used */
-#ifndef NDEBUG
-# define GHASH_FLAG_IS_SET (1 << 8)
-# define IS_GHASH_ASSERT(gh) BLI_assert((gh->flag & GHASH_FLAG_IS_SET) == 0)
-// # define IS_GSET_ASSERT(gs) BLI_assert((gs->flag & GHASH_FLAG_IS_SET) != 0)
+#ifdef GHASH_USE_MODULO_BUCKETS
+# define GHASH_MAX_SIZE 27
#else
-# define IS_GHASH_ASSERT(gh)
-// # define IS_GSET_ASSERT(eh)
+# define GHASH_BUCKET_BIT_MIN 2
+# define GHASH_BUCKET_BIT_MAX 28 /* About 268M of buckets... */
#endif
+/**
+ * \note Max load #GHASH_LIMIT_GROW used to be 3. (pre 2.74).
+ * Python uses 0.6666, tommyhaslib even goes down to 0.5.
+ * Reducing our from 3 to 0.75 gives huge speedup (about twice quicker pure GHash insertions/lookup,
+ * about 25% - 30% quicker 'dynamic-topology' stroke drawing e.g.).
+ * Min load #GHASH_LIMIT_SHRINK is a quarter of max load, to avoid resizing to quickly.
+ */
+#define GHASH_LIMIT_GROW(_nbkt) (((_nbkt) * 3) / 4)
+#define GHASH_LIMIT_SHRINK(_nbkt) (((_nbkt) * 3) / 16)
+
/***/
+/* WARNING! Keep in sync with ugly _gh_Entry in header!!! */
typedef struct Entry {
struct Entry *next;
- void *key, *val;
+ void *key;
} Entry;
+typedef struct GHashEntry {
+ Entry e;
+
+ void *val;
+} GHashEntry;
+
+typedef Entry GSetEntry;
+
+#define GHASH_ENTRY_SIZE(_is_gset) \
+ ((_is_gset) ? sizeof(GSetEntry) : sizeof(GHashEntry))
+
struct GHash {
GHashHashFP hashfp;
GHashCmpFP cmpfp;
@@ -78,11 +104,34 @@ struct GHash {
Entry **buckets;
struct BLI_mempool *entrypool;
unsigned int nbuckets;
+ unsigned int limit_grow, limit_shrink;
+#ifdef GHASH_USE_MODULO_BUCKETS
+ unsigned int cursize, size_min;
+#else
+ unsigned int bucket_mask, bucket_bit, bucket_bit_min;
+#endif
+
unsigned int nentries;
- unsigned int cursize, flag;
+ unsigned int flag;
};
+BLI_INLINE void ghash_entry_copy(
+ GHash *gh_dst, Entry *dst, GHash *gh_src, Entry *src,
+ GHashKeyCopyFP keycopyfp, GHashValCopyFP valcopyfp)
+{
+ dst->key = (keycopyfp) ? keycopyfp(src->key) : src->key;
+
+ if ((gh_dst->flag & GHASH_FLAG_IS_GSET) == 0) {
+ if ((gh_src->flag & GHASH_FLAG_IS_GSET) == 0) {
+ ((GHashEntry *)dst)->val = (valcopyfp) ? valcopyfp(((GHashEntry *)src)->val) : ((GHashEntry *)src)->val;
+ }
+ else {
+ ((GHashEntry *)dst)->val = NULL;
+ }
+ }
+}
+
/* -------------------------------------------------------------------- */
/* GHash API */
@@ -90,25 +139,37 @@ struct GHash {
* \{ */
/**
- * Get the hash for a key.
+ * Get the full hash for a key.
*/
BLI_INLINE unsigned int ghash_keyhash(GHash *gh, const void *key)
{
- return gh->hashfp(key) % gh->nbuckets;
+ return gh->hashfp(key);
}
/**
- * Check if the number of items in the GHash is large enough to require more buckets.
+ * Get the full hash for an entry.
*/
-BLI_INLINE bool ghash_test_expand_buckets(const unsigned int nentries, const unsigned int nbuckets)
+BLI_INLINE unsigned int ghash_entryhash(GHash *gh, const Entry *e)
{
- return (nentries > nbuckets * 3);
+ return gh->hashfp(e->key);
}
/**
- * Expand buckets to the next size up.
+ * Get the bucket-hash for an already-computed full hash.
*/
-BLI_INLINE void ghash_resize_buckets(GHash *gh, const unsigned int nbuckets)
+BLI_INLINE unsigned int ghash_bucket_index(GHash *gh, const unsigned int hash)
+{
+#ifdef GHASH_USE_MODULO_BUCKETS
+ return hash % gh->nbuckets;
+#else
+ return hash & gh->bucket_mask;
+#endif
+}
+
+/**
+ * Expand buckets to the next size up or down.
+ */
+static void ghash_buckets_resize(GHash *gh, const unsigned int nbuckets)
{
Entry **buckets_old = gh->buckets;
Entry **buckets_new;
@@ -116,49 +177,223 @@ BLI_INLINE void ghash_resize_buckets(GHash *gh, const unsigned int nbuckets)
unsigned int i;
Entry *e;
- BLI_assert(gh->nbuckets != nbuckets);
+ BLI_assert((gh->nbuckets != nbuckets) || !gh->buckets);
+// printf("%s: %d -> %d\n", __func__, nbuckets_old, nbuckets);
gh->nbuckets = nbuckets;
- buckets_new = (Entry **)MEM_callocN(gh->nbuckets * sizeof(*gh->buckets), "buckets");
-
- for (i = 0; i < nbuckets_old; i++) {
- Entry *e_next;
- for (e = buckets_old[i]; e; e = e_next) {
- const unsigned hash = ghash_keyhash(gh, e->key);
- e_next = e->next;
- e->next = buckets_new[hash];
- buckets_new[hash] = e;
+#ifdef GHASH_USE_MODULO_BUCKETS
+#else
+ gh->bucket_mask = nbuckets - 1;
+#endif
+
+ buckets_new = (Entry **)MEM_callocN(sizeof(*gh->buckets) * gh->nbuckets, __func__);
+
+ if (buckets_old) {
+ if (nbuckets > nbuckets_old) {
+ for (i = 0; i < nbuckets_old; i++) {
+ Entry *e_next;
+ for (e = buckets_old[i]; e; e = e_next) {
+ const unsigned hash = ghash_entryhash(gh, e);
+ const unsigned bucket_index = ghash_bucket_index(gh, hash);
+ e_next = e->next;
+ e->next = buckets_new[bucket_index];
+ buckets_new[bucket_index] = e;
+ }
+ }
+ }
+ else {
+ for (i = 0; i < nbuckets_old; i++) {
+#ifdef GHASH_USE_MODULO_BUCKETS
+ Entry *e_next;
+ for (e = buckets_old[i]; e; e = e_next) {
+ const unsigned hash = ghash_entryhash(gh, e);
+ const unsigned bucket_index = ghash_bucket_index(gh, hash);
+ e_next = e->next;
+ e->next = buckets_new[bucket_index];
+ buckets_new[bucket_index] = e;
+ }
+#else
+ /* No need to recompute hashes in this case, since our mask is just smaller, all items in old bucket i
+ * will go in same new bucket (i & new_mask)! */
+ const unsigned bucket_index = ghash_bucket_index(gh, i);
+ BLI_assert(!buckets_old[i] || (bucket_index == ghash_bucket_index(gh, ghash_entryhash(gh, buckets_old[i]))));
+ for (e = buckets_old[i]; e && e->next; e = e->next);
+ if (e) {
+ e->next = buckets_new[bucket_index];
+ buckets_new[bucket_index] = buckets_old[i];
+ }
+#endif
+ }
}
}
gh->buckets = buckets_new;
- MEM_freeN(buckets_old);
+ if (buckets_old) {
+ MEM_freeN(buckets_old);
+ }
}
/**
- * Increase initial bucket size to match a reserved amount.
+ * Check if the number of items in the GHash is large enough to require more buckets,
+ * or small enough to require less buckets, and resize \a gh accordingly.
*/
-BLI_INLINE void ghash_buckets_reserve(GHash *gh, const unsigned int nentries_reserve)
+static void ghash_buckets_expand(
+ GHash *gh, const unsigned int nentries, const bool user_defined)
{
- while (ghash_test_expand_buckets(nentries_reserve, gh->nbuckets)) {
- gh->nbuckets = hashsizes[++gh->cursize];
+ unsigned int new_nbuckets;
+
+ if (LIKELY(gh->buckets && (nentries < gh->limit_grow))) {
+ return;
}
+
+ new_nbuckets = gh->nbuckets;
+
+#ifdef GHASH_USE_MODULO_BUCKETS
+ while ((nentries > gh->limit_grow) &&
+ (gh->cursize < GHASH_MAX_SIZE - 1))
+ {
+ new_nbuckets = hashsizes[++gh->cursize];
+ gh->limit_grow = GHASH_LIMIT_GROW(new_nbuckets);
+ }
+#else
+ while ((nentries > gh->limit_grow) &&
+ (gh->bucket_bit < GHASH_BUCKET_BIT_MAX))
+ {
+ new_nbuckets = 1u << ++gh->bucket_bit;
+ gh->limit_grow = GHASH_LIMIT_GROW(new_nbuckets);
+ }
+#endif
+
+ if (user_defined) {
+#ifdef GHASH_USE_MODULO_BUCKETS
+ gh->size_min = gh->cursize;
+#else
+ gh->bucket_bit_min = gh->bucket_bit;
+#endif
+ }
+
+ if ((new_nbuckets == gh->nbuckets) && gh->buckets) {
+ return;
+ }
+
+ gh->limit_grow = GHASH_LIMIT_GROW(new_nbuckets);
+ gh->limit_shrink = GHASH_LIMIT_SHRINK(new_nbuckets);
+ ghash_buckets_resize(gh, new_nbuckets);
+}
+
+static void ghash_buckets_contract(
+ GHash *gh, const unsigned int nentries, const bool user_defined, const bool force_shrink)
+{
+ unsigned int new_nbuckets;
+
+ if (!(force_shrink || (gh->flag & GHASH_FLAG_ALLOW_SHRINK))) {
+ return;
+ }
+
+ if (LIKELY(gh->buckets && (nentries > gh->limit_shrink))) {
+ return;
+ }
+
+ new_nbuckets = gh->nbuckets;
+
+#ifdef GHASH_USE_MODULO_BUCKETS
+ while ((nentries < gh->limit_shrink) &&
+ (gh->cursize > gh->size_min))
+ {
+ new_nbuckets = hashsizes[--gh->cursize];
+ gh->limit_shrink = GHASH_LIMIT_SHRINK(new_nbuckets);
+ }
+#else
+ while ((nentries < gh->limit_shrink) &&
+ (gh->bucket_bit > gh->bucket_bit_min))
+ {
+ new_nbuckets = 1u << --gh->bucket_bit;
+ gh->limit_shrink = GHASH_LIMIT_SHRINK(new_nbuckets);
+ }
+#endif
+
+ if (user_defined) {
+#ifdef GHASH_USE_MODULO_BUCKETS
+ gh->size_min = gh->cursize;
+#else
+ gh->bucket_bit_min = gh->bucket_bit;
+#endif
+ }
+
+ if ((new_nbuckets == gh->nbuckets) && gh->buckets) {
+ return;
+ }
+
+ gh->limit_grow = GHASH_LIMIT_GROW(new_nbuckets);
+ gh->limit_shrink = GHASH_LIMIT_SHRINK(new_nbuckets);
+ ghash_buckets_resize(gh, new_nbuckets);
+}
+
+/**
+ * Clear and reset \a gh buckets, reserve again buckets for given number of entries.
+ */
+BLI_INLINE void ghash_buckets_reset(GHash *gh, const unsigned int nentries)
+{
+ MEM_SAFE_FREE(gh->buckets);
+
+#ifdef GHASH_USE_MODULO_BUCKETS
+ gh->cursize = 0;
+ gh->size_min = 0;
+ gh->nbuckets = hashsizes[gh->cursize];
+#else
+ gh->bucket_bit = GHASH_BUCKET_BIT_MIN;
+ gh->bucket_bit_min = GHASH_BUCKET_BIT_MIN;
+ gh->nbuckets = 1u << gh->bucket_bit;
+ gh->bucket_mask = gh->nbuckets - 1;
+#endif
+
+ gh->limit_grow = GHASH_LIMIT_GROW(gh->nbuckets);
+ gh->limit_shrink = GHASH_LIMIT_SHRINK(gh->nbuckets);
+
+ gh->nentries = 0;
+
+ ghash_buckets_expand(gh, nentries, (nentries != 0));
}
/**
* Internal lookup function.
- * Takes a hash argument to avoid calling #ghash_keyhash multiple times.
+ * Takes hash and bucket_index arguments to avoid calling #ghash_keyhash and #ghash_bucket_index multiple times.
*/
-BLI_INLINE Entry *ghash_lookup_entry_ex(GHash *gh, const void *key,
- const unsigned int hash)
+BLI_INLINE Entry *ghash_lookup_entry_ex(
+ GHash *gh, const void *key, const unsigned int bucket_index)
{
Entry *e;
+ /* If we do not store GHash, not worth computing it for each entry here!
+ * Typically, comparison function will be quicker, and since it's needed in the end anyway... */
+ for (e = gh->buckets[bucket_index]; e; e = e->next) {
+ if (UNLIKELY(gh->cmpfp(key, e->key) == false)) {
+ return e;
+ }
+ }
- for (e = gh->buckets[hash]; e; e = e->next) {
+ return NULL;
+}
+
+/**
+ * Internal lookup function, returns previous entry of target one too.
+ * Takes hash and bucket_index arguments to avoid calling #ghash_keyhash and #ghash_bucket_index multiple times.
+ * Useful when modifying buckets somehow (like removing an entry...).
+ */
+BLI_INLINE Entry *ghash_lookup_entry_prev_ex(
+ GHash *gh, const void *key, Entry **r_e_prev, const unsigned int bucket_index)
+{
+ Entry *e, *e_prev = NULL;
+
+ /* If we do not store GHash, not worth computing it for each entry here!
+ * Typically, comparison function will be quicker, and since it's needed in the end anyway... */
+ for (e = gh->buckets[bucket_index]; e; e_prev = e, e = e->next) {
if (UNLIKELY(gh->cmpfp(key, e->key) == false)) {
+ *r_e_prev = e_prev;
return e;
}
}
+
+ *r_e_prev = NULL;
return NULL;
}
@@ -168,105 +403,157 @@ BLI_INLINE Entry *ghash_lookup_entry_ex(GHash *gh, const void *key,
BLI_INLINE Entry *ghash_lookup_entry(GHash *gh, const void *key)
{
const unsigned int hash = ghash_keyhash(gh, key);
- return ghash_lookup_entry_ex(gh, key, hash);
+ const unsigned int bucket_index = ghash_bucket_index(gh, hash);
+ return ghash_lookup_entry_ex(gh, key, bucket_index);
}
static GHash *ghash_new(GHashHashFP hashfp, GHashCmpFP cmpfp, const char *info,
- const unsigned int nentries_reserve,
- const unsigned int entry_size)
+ const unsigned int nentries_reserve, const unsigned int flag)
{
GHash *gh = MEM_mallocN(sizeof(*gh), info);
gh->hashfp = hashfp;
gh->cmpfp = cmpfp;
- gh->nbuckets = hashsizes[0]; /* gh->cursize */
- gh->nentries = 0;
- gh->cursize = 0;
- gh->flag = 0;
+ gh->buckets = NULL;
+ gh->flag = flag;
- /* if we have reserved the number of elements that this hash will contain */
- if (nentries_reserve) {
- ghash_buckets_reserve(gh, nentries_reserve);
- }
-
- gh->buckets = MEM_callocN(gh->nbuckets * sizeof(*gh->buckets), "buckets");
- gh->entrypool = BLI_mempool_create(entry_size, 64, 64, BLI_MEMPOOL_NOP);
+ ghash_buckets_reset(gh, nentries_reserve);
+ gh->entrypool = BLI_mempool_create(GHASH_ENTRY_SIZE(flag & GHASH_FLAG_IS_GSET), 64, 64, BLI_MEMPOOL_NOP);
return gh;
}
/**
* Internal insert function.
- * Takes a hash argument to avoid calling #ghash_keyhash multiple times.
+ * Takes hash and bucket_index arguments to avoid calling #ghash_keyhash and #ghash_bucket_index multiple times.
*/
-BLI_INLINE void ghash_insert_ex(GHash *gh, void *key, void *val,
- unsigned int hash)
+BLI_INLINE void ghash_insert_ex(
+ GHash *gh, void *key, void *val, const unsigned int bucket_index)
{
- Entry *e = (Entry *)BLI_mempool_alloc(gh->entrypool);
+ GHashEntry *e = BLI_mempool_alloc(gh->entrypool);
+
BLI_assert((gh->flag & GHASH_FLAG_ALLOW_DUPES) || (BLI_ghash_haskey(gh, key) == 0));
- IS_GHASH_ASSERT(gh);
+ BLI_assert(!(gh->flag & GHASH_FLAG_IS_GSET));
- e->next = gh->buckets[hash];
- e->key = key;
+ e->e.next = gh->buckets[bucket_index];
+ e->e.key = key;
e->val = val;
- gh->buckets[hash] = e;
+ gh->buckets[bucket_index] = (Entry *)e;
- if (UNLIKELY(ghash_test_expand_buckets(++gh->nentries, gh->nbuckets))) {
- ghash_resize_buckets(gh, hashsizes[++gh->cursize]);
- }
+ ghash_buckets_expand(gh, ++gh->nentries, false);
+}
+
+/**
+ * Insert function that takes a pre-allocated entry.
+ */
+BLI_INLINE void ghash_insert_ex_keyonly_entry(
+ GHash *gh, void *key, const unsigned int bucket_index,
+ Entry *e)
+{
+ BLI_assert((gh->flag & GHASH_FLAG_ALLOW_DUPES) || (BLI_ghash_haskey(gh, key) == 0));
+
+ e->next = gh->buckets[bucket_index];
+ e->key = key;
+ gh->buckets[bucket_index] = e;
+
+ ghash_buckets_expand(gh, ++gh->nentries, false);
}
/**
* Insert function that doesn't set the value (use for GSet)
*/
-BLI_INLINE void ghash_insert_ex_keyonly(GHash *gh, void *key,
- unsigned int hash)
+BLI_INLINE void ghash_insert_ex_keyonly(
+ GHash *gh, void *key, const unsigned int bucket_index)
{
- Entry *e = (Entry *)BLI_mempool_alloc(gh->entrypool);
+ Entry *e = BLI_mempool_alloc(gh->entrypool);
+
BLI_assert((gh->flag & GHASH_FLAG_ALLOW_DUPES) || (BLI_ghash_haskey(gh, key) == 0));
- e->next = gh->buckets[hash];
+ BLI_assert((gh->flag & GHASH_FLAG_IS_GSET) != 0);
+
+ e->next = gh->buckets[bucket_index];
e->key = key;
- /* intentionally leave value unset */
- gh->buckets[hash] = e;
+ gh->buckets[bucket_index] = e;
- if (UNLIKELY(ghash_test_expand_buckets(++gh->nentries, gh->nbuckets))) {
- ghash_resize_buckets(gh, hashsizes[++gh->cursize]);
- }
+ ghash_buckets_expand(gh, ++gh->nentries, false);
}
BLI_INLINE void ghash_insert(GHash *gh, void *key, void *val)
{
const unsigned int hash = ghash_keyhash(gh, key);
- ghash_insert_ex(gh, key, val, hash);
+ const unsigned int bucket_index = ghash_bucket_index(gh, hash);
+
+ ghash_insert_ex(gh, key, val, bucket_index);
+}
+
+BLI_INLINE bool ghash_insert_safe(
+ GHash *gh, void *key, void *val, const bool override, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp)
+{
+ const unsigned int hash = ghash_keyhash(gh, key);
+ const unsigned int bucket_index = ghash_bucket_index(gh, hash);
+ GHashEntry *e = (GHashEntry *)ghash_lookup_entry_ex(gh, key, bucket_index);
+
+ BLI_assert(!(gh->flag & GHASH_FLAG_IS_GSET));
+
+ if (e) {
+ if (override) {
+ if (keyfreefp) keyfreefp(e->e.key);
+ if (valfreefp) valfreefp(e->val);
+ e->e.key = key;
+ e->val = val;
+ }
+ return false;
+ }
+ else {
+ ghash_insert_ex(gh, key, val, bucket_index);
+ return true;
+ }
+}
+
+BLI_INLINE bool ghash_insert_safe_keyonly(GHash *gh, void *key, const bool override, GHashKeyFreeFP keyfreefp)
+{
+ const unsigned int hash = ghash_keyhash(gh, key);
+ const unsigned int bucket_index = ghash_bucket_index(gh, hash);
+ Entry *e = ghash_lookup_entry_ex(gh, key, bucket_index);
+
+ BLI_assert((gh->flag & GHASH_FLAG_IS_GSET) != 0);
+
+ if (e) {
+ if (override) {
+ if (keyfreefp) keyfreefp(e->key);
+ e->key = key;
+ }
+ return false;
+ }
+ else {
+ ghash_insert_ex_keyonly(gh, key, bucket_index);
+ return true;
+ }
}
/**
* Remove the entry and return it, caller must free from gh->entrypool.
*/
-static Entry *ghash_remove_ex(GHash *gh, void *key, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp,
- unsigned int hash)
+static Entry *ghash_remove_ex(
+ GHash *gh, const void *key, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp,
+ const unsigned int bucket_index)
{
- Entry *e;
- Entry *e_prev = NULL;
+ Entry *e_prev;
+ Entry *e = ghash_lookup_entry_prev_ex(gh, key, &e_prev, bucket_index);
- for (e = gh->buckets[hash]; e; e = e->next) {
- if (UNLIKELY(gh->cmpfp(key, e->key) == false)) {
- Entry *e_next = e->next;
+ BLI_assert(!valfreefp || !(gh->flag & GHASH_FLAG_IS_GSET));
- if (keyfreefp) keyfreefp(e->key);
- if (valfreefp) valfreefp(e->val);
+ if (e) {
+ if (keyfreefp) keyfreefp(e->key);
+ if (valfreefp) valfreefp(((GHashEntry *)e)->val);
- if (e_prev) e_prev->next = e_next;
- else gh->buckets[hash] = e_next;
+ if (e_prev) e_prev->next = e->next;
+ else gh->buckets[bucket_index] = e->next;
- gh->nentries--;
- return e;
- }
- e_prev = e;
+ ghash_buckets_contract(gh, --gh->nentries, false, false);
}
- return NULL;
+ return e;
}
/**
@@ -276,21 +563,57 @@ static void ghash_free_cb(GHash *gh, GHashKeyFreeFP keyfreefp, GHashValFreeFP va
{
unsigned int i;
- BLI_assert(keyfreefp || valfreefp);
+ BLI_assert(keyfreefp || valfreefp);
+ BLI_assert(!valfreefp || !(gh->flag & GHASH_FLAG_IS_GSET));
for (i = 0; i < gh->nbuckets; i++) {
Entry *e;
- for (e = gh->buckets[i]; e; ) {
- Entry *e_next = e->next;
-
+ for (e = gh->buckets[i]; e; e = e->next) {
if (keyfreefp) keyfreefp(e->key);
- if (valfreefp) valfreefp(e->val);
+ if (valfreefp) valfreefp(((GHashEntry *)e)->val);
+ }
+ }
+}
+
+/**
+ * Copy the GHash.
+ */
+static GHash *ghash_copy(GHash *gh, GHashKeyCopyFP keycopyfp, GHashValCopyFP valcopyfp)
+{
+ GHash *gh_new;
+ unsigned int i;
+ /* This allows us to be sure to get the same number of buckets in gh_new as in ghash. */
+ const unsigned int reserve_nentries_new = MAX2(GHASH_LIMIT_GROW(gh->nbuckets) - 1, gh->nentries);
+
+ BLI_assert(!valcopyfp || !(gh->flag & GHASH_FLAG_IS_GSET));
+
+ gh_new = ghash_new(gh->hashfp, gh->cmpfp, __func__, 0, gh->flag);
+ ghash_buckets_expand(gh_new, reserve_nentries_new, false);
+
+ BLI_assert(gh_new->nbuckets == gh->nbuckets);
+
+ for (i = 0; i < gh->nbuckets; i++) {
+ Entry *e;
+
+ for (e = gh->buckets[i]; e; e = e->next) {
+ Entry *e_new = BLI_mempool_alloc(gh_new->entrypool);
+ ghash_entry_copy(gh_new, e_new, gh, e, keycopyfp, valcopyfp);
+
+ /* Warning!
+ * This means entries in buckets in new copy will be in reversed order!
+ * This shall not be an issue though, since order should never be assumed in ghash. */
- e = e_next;
+ /* Note: We can use 'i' here, since we are sure that 'gh' and 'gh_new' have the same number of buckets! */
+ e_new->next = gh_new->buckets[i];
+ gh_new->buckets[i] = e_new;
}
}
+ gh_new->nentries = gh->nentries;
+
+ return gh_new;
}
+
/** \} */
@@ -310,9 +633,7 @@ static void ghash_free_cb(GHash *gh, GHashKeyFreeFP keyfreefp, GHashValFreeFP va
GHash *BLI_ghash_new_ex(GHashHashFP hashfp, GHashCmpFP cmpfp, const char *info,
const unsigned int nentries_reserve)
{
- return ghash_new(hashfp, cmpfp, info,
- nentries_reserve,
- (unsigned int)sizeof(Entry));
+ return ghash_new(hashfp, cmpfp, info, nentries_reserve, 0);
}
/**
@@ -324,11 +645,28 @@ GHash *BLI_ghash_new(GHashHashFP hashfp, GHashCmpFP cmpfp, const char *info)
}
/**
+ * Copy given GHash. Keys and values are also copied if relevant callback is provided, else pointers remain the same.
+ */
+GHash *BLI_ghash_copy(GHash *gh, GHashKeyCopyFP keycopyfp, GHashValCopyFP valcopyfp)
+{
+ return ghash_copy(gh, keycopyfp, valcopyfp);
+}
+
+/**
+ * Reserve given amount of entries (resize \a gh accordingly if needed).
+ */
+void BLI_ghash_reserve(GHash *gh, const unsigned int nentries_reserve)
+{
+ ghash_buckets_expand(gh, nentries_reserve, true);
+ ghash_buckets_contract(gh, nentries_reserve, true, false);
+}
+
+/**
* \return size of the GHash.
*/
-int BLI_ghash_size(GHash *gh)
+unsigned int BLI_ghash_size(GHash *gh)
{
- return (int)gh->nentries;
+ return gh->nentries;
}
/**
@@ -352,19 +690,7 @@ void BLI_ghash_insert(GHash *gh, void *key, void *val)
*/
bool BLI_ghash_reinsert(GHash *gh, void *key, void *val, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp)
{
- const unsigned int hash = ghash_keyhash(gh, key);
- Entry *e = ghash_lookup_entry_ex(gh, key, hash);
- if (e) {
- if (keyfreefp) keyfreefp(e->key);
- if (valfreefp) valfreefp(e->val);
- e->key = key;
- e->val = val;
- return false;
- }
- else {
- ghash_insert_ex(gh, key, val, hash);
- return true;
- }
+ return ghash_insert_safe(gh, key, val, true, keyfreefp, valfreefp);
}
/**
@@ -378,8 +704,8 @@ bool BLI_ghash_reinsert(GHash *gh, void *key, void *val, GHashKeyFreeFP keyfreef
*/
void *BLI_ghash_lookup(GHash *gh, const void *key)
{
- Entry *e = ghash_lookup_entry(gh, key);
- IS_GHASH_ASSERT(gh);
+ GHashEntry *e = (GHashEntry *)ghash_lookup_entry(gh, key);
+ BLI_assert(!(gh->flag & GHASH_FLAG_IS_GSET));
return e ? e->val : NULL;
}
@@ -388,8 +714,8 @@ void *BLI_ghash_lookup(GHash *gh, const void *key)
*/
void *BLI_ghash_lookup_default(GHash *gh, const void *key, void *val_default)
{
- Entry *e = ghash_lookup_entry(gh, key);
- IS_GHASH_ASSERT(gh);
+ GHashEntry *e = (GHashEntry *)ghash_lookup_entry(gh, key);
+ BLI_assert(!(gh->flag & GHASH_FLAG_IS_GSET));
return e ? e->val : val_default;
}
@@ -405,12 +731,64 @@ void *BLI_ghash_lookup_default(GHash *gh, const void *key, void *val_default)
*/
void **BLI_ghash_lookup_p(GHash *gh, const void *key)
{
- Entry *e = ghash_lookup_entry(gh, key);
- IS_GHASH_ASSERT(gh);
+ GHashEntry *e = (GHashEntry *)ghash_lookup_entry(gh, key);
+ BLI_assert(!(gh->flag & GHASH_FLAG_IS_GSET));
return e ? &e->val : NULL;
}
/**
+ * Ensure \a key is exists in \a gh.
+ *
+ * This handles the common situation where the caller needs ensure a key is added to \a gh,
+ * constructing a new value in the case the key isn't found.
+ * Otherwise use the existing value.
+ *
+ * Such situations typically incur multiple lookups, however this function
+ * avoids them by ensuring the key is added,
+ * returning a pointer to the value so it can be used or initialized by the caller.
+ *
+ * \returns true when the value didn't need to be added.
+ * (when false, the caller _must_ initialize the value).
+ */
+bool BLI_ghash_ensure_p(GHash *gh, void *key, void ***r_val)
+{
+ const unsigned int hash = ghash_keyhash(gh, key);
+ const unsigned int bucket_index = ghash_bucket_index(gh, hash);
+ GHashEntry *e = (GHashEntry *)ghash_lookup_entry_ex(gh, key, bucket_index);
+ const bool haskey = (e != NULL);
+
+ if (!haskey) {
+ e = BLI_mempool_alloc(gh->entrypool);
+ ghash_insert_ex_keyonly_entry(gh, key, bucket_index, (Entry *)e);
+ }
+
+ *r_val = &e->val;
+ return haskey;
+}
+
+/**
+ * A version of #BLI_ghash_ensure_p copies the key on insertion.
+ */
+bool BLI_ghash_ensure_p_ex(
+ GHash *gh, const void *key, void ***r_val,
+ GHashKeyCopyFP keycopyfp)
+{
+ const unsigned int hash = ghash_keyhash(gh, key);
+ const unsigned int bucket_index = ghash_bucket_index(gh, hash);
+ GHashEntry *e = (GHashEntry *)ghash_lookup_entry_ex(gh, key, bucket_index);
+ const bool haskey = (e != NULL);
+
+ if (!haskey) {
+ /* keycopyfp(key) is the only difference to BLI_ghash_ensure_p */
+ e = BLI_mempool_alloc(gh->entrypool);
+ ghash_insert_ex_keyonly_entry(gh, keycopyfp(key), bucket_index, (Entry *)e);
+ }
+
+ *r_val = &e->val;
+ return haskey;
+}
+
+/**
* Remove \a key from \a gh, or return false if the key wasn't found.
*
* \param key The key to remove.
@@ -418,10 +796,11 @@ void **BLI_ghash_lookup_p(GHash *gh, const void *key)
* \param valfreefp Optional callback to free the value.
* \return true if \a key was removed from \a gh.
*/
-bool BLI_ghash_remove(GHash *gh, void *key, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp)
+bool BLI_ghash_remove(GHash *gh, const void *key, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp)
{
const unsigned int hash = ghash_keyhash(gh, key);
- Entry *e = ghash_remove_ex(gh, key, keyfreefp, valfreefp, hash);
+ const unsigned int bucket_index = ghash_bucket_index(gh, hash);
+ Entry *e = ghash_remove_ex(gh, key, keyfreefp, valfreefp, bucket_index);
if (e) {
BLI_mempool_free(gh->entrypool, e);
return true;
@@ -440,11 +819,12 @@ bool BLI_ghash_remove(GHash *gh, void *key, GHashKeyFreeFP keyfreefp, GHashValFr
* \param keyfreefp Optional callback to free the key.
* \return the value of \a key int \a gh or NULL.
*/
-void *BLI_ghash_popkey(GHash *gh, void *key, GHashKeyFreeFP keyfreefp)
+void *BLI_ghash_popkey(GHash *gh, const void *key, GHashKeyFreeFP keyfreefp)
{
const unsigned int hash = ghash_keyhash(gh, key);
- Entry *e = ghash_remove_ex(gh, key, keyfreefp, NULL, hash);
- IS_GHASH_ASSERT(gh);
+ const unsigned int bucket_index = ghash_bucket_index(gh, hash);
+ GHashEntry *e = (GHashEntry *)ghash_remove_ex(gh, key, keyfreefp, NULL, bucket_index);
+ BLI_assert(!(gh->flag & GHASH_FLAG_IS_GSET));
if (e) {
void *val = e->val;
BLI_mempool_free(gh->entrypool, e);
@@ -476,17 +856,7 @@ void BLI_ghash_clear_ex(GHash *gh, GHashKeyFreeFP keyfreefp, GHashValFreeFP valf
if (keyfreefp || valfreefp)
ghash_free_cb(gh, keyfreefp, valfreefp);
- gh->nbuckets = hashsizes[0]; /* gh->cursize */
- gh->nentries = 0;
- gh->cursize = 0;
-
- if (nentries_reserve) {
- ghash_buckets_reserve(gh, nentries_reserve);
- }
-
- MEM_freeN(gh->buckets);
- gh->buckets = MEM_callocN(gh->nbuckets * sizeof(*gh->buckets), "buckets");
-
+ ghash_buckets_reset(gh, nentries_reserve);
BLI_mempool_clear_ex(gh->entrypool, nentries_reserve ? (int)nentries_reserve : -1);
}
@@ -700,6 +1070,10 @@ unsigned int BLI_ghashutil_uinthash_v4(const unsigned int key[4])
hash += key[3];
return hash;
}
+unsigned int BLI_ghashutil_uinthash_v4_murmur(const unsigned int key[4])
+{
+ return BLI_hash_mm2((const unsigned char *)key, sizeof(int) * 4 /* sizeof(key) */, 0);
+}
bool BLI_ghashutil_uinthash_v4_cmp(const void *a, const void *b)
{
@@ -732,6 +1106,18 @@ unsigned int BLI_ghashutil_inthash_p(const void *ptr)
return (unsigned int)(key & 0xffffffff);
}
+unsigned int BLI_ghashutil_inthash_p_murmur(const void *ptr)
+{
+ uintptr_t key = (uintptr_t)ptr;
+
+ return BLI_hash_mm2((const unsigned char *)&key, sizeof(key), 0);
+}
+
+unsigned int BLI_ghashutil_inthash_p_simple(const void *ptr)
+{
+ return GET_UINT_FROM_POINTER(ptr);
+}
+
bool BLI_ghashutil_intcmp(const void *a, const void *b)
{
return (a != b);
@@ -768,9 +1154,15 @@ unsigned int BLI_ghashutil_strhash_p(const void *ptr)
return h;
}
+unsigned int BLI_ghashutil_strhash_p_murmur(const void *ptr)
+{
+ const unsigned char *key = ptr;
+
+ return BLI_hash_mm2(key, strlen((const char *)key) + 1, 0);
+}
bool BLI_ghashutil_strcmp(const void *a, const void *b)
{
- return (strcmp(a, b) != 0);
+ return (a == b) ? false : !STREQ(a, b);
}
GHashPair *BLI_ghashutil_pairalloc(const void *first, const void *second)
@@ -808,44 +1200,36 @@ void BLI_ghashutil_pairfree(void *ptr)
/** \name Convenience GHash Creation Functions
* \{ */
-GHash *BLI_ghash_ptr_new_ex(const char *info,
- const unsigned int nentries_reserve)
+GHash *BLI_ghash_ptr_new_ex(const char *info, const unsigned int nentries_reserve)
{
- return BLI_ghash_new_ex(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, info,
- nentries_reserve);
+ return BLI_ghash_new_ex(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, info, nentries_reserve);
}
GHash *BLI_ghash_ptr_new(const char *info)
{
return BLI_ghash_ptr_new_ex(info, 0);
}
-GHash *BLI_ghash_str_new_ex(const char *info,
- const unsigned int nentries_reserve)
+GHash *BLI_ghash_str_new_ex(const char *info, const unsigned int nentries_reserve)
{
- return BLI_ghash_new_ex(BLI_ghashutil_strhash_p, BLI_ghashutil_strcmp, info,
- nentries_reserve);
+ return BLI_ghash_new_ex(BLI_ghashutil_strhash_p, BLI_ghashutil_strcmp, info, nentries_reserve);
}
GHash *BLI_ghash_str_new(const char *info)
{
return BLI_ghash_str_new_ex(info, 0);
}
-GHash *BLI_ghash_int_new_ex(const char *info,
- const unsigned int nentries_reserve)
+GHash *BLI_ghash_int_new_ex(const char *info, const unsigned int nentries_reserve)
{
- return BLI_ghash_new_ex(BLI_ghashutil_inthash_p, BLI_ghashutil_intcmp, info,
- nentries_reserve);
+ return BLI_ghash_new_ex(BLI_ghashutil_inthash_p, BLI_ghashutil_intcmp, info, nentries_reserve);
}
GHash *BLI_ghash_int_new(const char *info)
{
return BLI_ghash_int_new_ex(info, 0);
}
-GHash *BLI_ghash_pair_new_ex(const char *info,
- const unsigned int nentries_reserve)
+GHash *BLI_ghash_pair_new_ex(const char *info, const unsigned int nentries_reserve)
{
- return BLI_ghash_new_ex(BLI_ghashutil_pairhash, BLI_ghashutil_paircmp, info,
- nentries_reserve);
+ return BLI_ghash_new_ex(BLI_ghashutil_pairhash, BLI_ghashutil_paircmp, info, nentries_reserve);
}
GHash *BLI_ghash_pair_new(const char *info)
{
@@ -860,21 +1244,12 @@ GHash *BLI_ghash_pair_new(const char *info)
/* Use ghash API to give 'set' functionality */
-/* TODO: typical set functions
- * isdisjoint/issubset/issuperset/union/intersection/difference etc */
-
/** \name GSet Functions
* \{ */
GSet *BLI_gset_new_ex(GSetHashFP hashfp, GSetCmpFP cmpfp, const char *info,
const unsigned int nentries_reserve)
{
- GSet *gs = (GSet *)ghash_new(hashfp, cmpfp, info,
- nentries_reserve,
- sizeof(Entry) - sizeof(void *));
-#ifndef NDEBUG
- ((GHash *)gs)->flag |= GHASH_FLAG_IS_SET;
-#endif
- return gs;
+ return (GSet *)ghash_new(hashfp, cmpfp, info, nentries_reserve, GHASH_FLAG_IS_GSET);
}
GSet *BLI_gset_new(GSetHashFP hashfp, GSetCmpFP cmpfp, const char *info)
@@ -882,9 +1257,17 @@ GSet *BLI_gset_new(GSetHashFP hashfp, GSetCmpFP cmpfp, const char *info)
return BLI_gset_new_ex(hashfp, cmpfp, info, 0);
}
-int BLI_gset_size(GSet *gs)
+/**
+ * Copy given GSet. Keys are also copied if callback is provided, else pointers remain the same.
+ */
+GSet *BLI_gset_copy(GSet *gs, GHashKeyCopyFP keycopyfp)
+{
+ return (GSet *)ghash_copy((GHash *)gs, keycopyfp, NULL);
+}
+
+unsigned int BLI_gset_size(GSet *gs)
{
- return (int)((GHash *)gs)->nentries;
+ return ((GHash *)gs)->nentries;
}
/**
@@ -894,7 +1277,8 @@ int BLI_gset_size(GSet *gs)
void BLI_gset_insert(GSet *gs, void *key)
{
const unsigned int hash = ghash_keyhash((GHash *)gs, key);
- ghash_insert_ex_keyonly((GHash *)gs, key, hash);
+ const unsigned int bucket_index = ghash_bucket_index((GHash *)gs, hash);
+ ghash_insert_ex_keyonly((GHash *)gs, key, bucket_index);
}
/**
@@ -905,15 +1289,7 @@ void BLI_gset_insert(GSet *gs, void *key)
*/
bool BLI_gset_add(GSet *gs, void *key)
{
- const unsigned int hash = ghash_keyhash((GHash *)gs, key);
- Entry *e = ghash_lookup_entry_ex((GHash *)gs, key, hash);
- if (e) {
- return false;
- }
- else {
- ghash_insert_ex_keyonly((GHash *)gs, key, hash);
- return true;
- }
+ return ghash_insert_safe_keyonly((GHash *)gs, key, false, NULL);
}
/**
@@ -924,20 +1300,10 @@ bool BLI_gset_add(GSet *gs, void *key)
*/
bool BLI_gset_reinsert(GSet *gs, void *key, GSetKeyFreeFP keyfreefp)
{
- const unsigned int hash = ghash_keyhash((GHash *)gs, key);
- Entry *e = ghash_lookup_entry_ex((GHash *)gs, key, hash);
- if (e) {
- if (keyfreefp) keyfreefp(e->key);
- e->key = key;
- return false;
- }
- else {
- ghash_insert_ex_keyonly((GHash *)gs, key, hash);
- return true;
- }
+ return ghash_insert_safe_keyonly((GHash *)gs, key, true, keyfreefp);
}
-bool BLI_gset_remove(GSet *gs, void *key, GSetKeyFreeFP keyfreefp)
+bool BLI_gset_remove(GSet *gs, const void *key, GSetKeyFreeFP keyfreefp)
{
return BLI_ghash_remove((GHash *)gs, key, keyfreefp, NULL);
}
@@ -981,22 +1347,27 @@ void BLI_gset_flag_clear(GSet *gs, unsigned int flag)
/** \name Convenience GSet Creation Functions
* \{ */
-GSet *BLI_gset_ptr_new_ex(const char *info,
- const unsigned int nentries_reserve)
+GSet *BLI_gset_ptr_new_ex(const char *info, const unsigned int nentries_reserve)
{
- return BLI_gset_new_ex(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, info,
- nentries_reserve);
+ return BLI_gset_new_ex(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, info, nentries_reserve);
}
GSet *BLI_gset_ptr_new(const char *info)
{
return BLI_gset_ptr_new_ex(info, 0);
}
-GSet *BLI_gset_pair_new_ex(const char *info,
- const unsigned int nentries_reserve)
+GSet *BLI_gset_str_new_ex(const char *info, const unsigned int nentries_reserve)
+{
+ return BLI_gset_new_ex(BLI_ghashutil_strhash_p, BLI_ghashutil_strcmp, info, nentries_reserve);
+}
+GSet *BLI_gset_str_new(const char *info)
+{
+ return BLI_gset_str_new_ex(info, 0);
+}
+
+GSet *BLI_gset_pair_new_ex(const char *info, const unsigned int nentries_reserve)
{
- return BLI_gset_new_ex(BLI_ghashutil_pairhash, BLI_ghashutil_paircmp, info,
- nentries_reserve);
+ return BLI_gset_new_ex(BLI_ghashutil_pairhash, BLI_ghashutil_paircmp, info, nentries_reserve);
}
GSet *BLI_gset_pair_new(const char *info)
{
@@ -1008,37 +1379,126 @@ GSet *BLI_gset_pair_new(const char *info)
/** \name Debugging & Introspection
* \{ */
-#ifdef DEBUG
+
+#include "BLI_math.h"
+
+/**
+ * \return number of buckets in the GHash.
+ */
+int BLI_ghash_buckets_size(GHash *gh)
+{
+ return (int)gh->nbuckets;
+}
+int BLI_gset_buckets_size(GSet *gs)
+{
+ return BLI_ghash_buckets_size((GHash *)gs);
+}
/**
- * Measure how well the hash function performs
- * (1.0 is approx as good as random distribution).
+ * Measure how well the hash function performs (1.0 is approx as good as random distribution),
+ * and return a few other stats like load, variance of the distribution of the entries in the buckets, etc.
*
* Smaller is better!
*/
-double BLI_ghash_calc_quality(GHash *gh)
+double BLI_ghash_calc_quality_ex(
+ GHash *gh, double *r_load, double *r_variance,
+ double *r_prop_empty_buckets, double *r_prop_overloaded_buckets, int *r_biggest_bucket)
{
- uint64_t sum = 0;
+ double mean;
unsigned int i;
- if (gh->nentries == 0)
- return -1.0;
+ if (gh->nentries == 0) {
+ if (r_load) {
+ *r_load = 0.0;
+ }
+ if (r_variance) {
+ *r_variance = 0.0;
+ }
+ if (r_prop_empty_buckets) {
+ *r_prop_empty_buckets = 1.0;
+ }
+ if (r_prop_overloaded_buckets) {
+ *r_prop_overloaded_buckets = 0.0;
+ }
+ if (r_biggest_bucket) {
+ *r_biggest_bucket = 0;
+ }
- for (i = 0; i < gh->nbuckets; i++) {
- uint64_t count = 0;
- Entry *e;
- for (e = gh->buckets[i]; e; e = e->next) {
- count += 1;
+ return 0.0;
+ }
+
+ mean = (double)gh->nentries / (double)gh->nbuckets;
+ if (r_load) {
+ *r_load = mean;
+ }
+ if (r_biggest_bucket) {
+ *r_biggest_bucket = 0;
+ }
+
+ if (r_variance) {
+ /* We already know our mean (i.e. load factor), easy to compute variance.
+ * See http://en.wikipedia.org/wiki/Algorithms_for_calculating_variance#Two-pass_algorithm
+ */
+ double sum = 0.0;
+ for (i = 0; i < gh->nbuckets; i++) {
+ int count = 0;
+ Entry *e;
+ for (e = gh->buckets[i]; e; e = e->next) {
+ count++;
+ }
+ sum += ((double)count - mean) * ((double)count - mean);
+ }
+ *r_variance = sum / (double)(gh->nbuckets - 1);
+ }
+
+ {
+ uint64_t sum = 0;
+ uint64_t overloaded_buckets_threshold = (uint64_t)max_ii(GHASH_LIMIT_GROW(1), 1);
+ uint64_t sum_overloaded = 0;
+ uint64_t sum_empty = 0;
+
+ for (i = 0; i < gh->nbuckets; i++) {
+ uint64_t count = 0;
+ Entry *e;
+ for (e = gh->buckets[i]; e; e = e->next) {
+ count++;
+ }
+ if (r_biggest_bucket) {
+ *r_biggest_bucket = max_ii(*r_biggest_bucket, (int)count);
+ }
+ if (r_prop_overloaded_buckets && (count > overloaded_buckets_threshold)) {
+ sum_overloaded++;
+ }
+ if (r_prop_empty_buckets && !count) {
+ sum_empty++;
+ }
+ sum += count * (count + 1);
}
- sum += count * (count + 1);
+ if (r_prop_overloaded_buckets) {
+ *r_prop_overloaded_buckets = (double)sum_overloaded / (double)gh->nbuckets;
+ }
+ if (r_prop_empty_buckets) {
+ *r_prop_empty_buckets = (double)sum_empty / (double)gh->nbuckets;
+ }
+ return ((double)sum * (double)gh->nbuckets /
+ ((double)gh->nentries * (gh->nentries + 2 * gh->nbuckets - 1)));
}
- return ((double)sum * (double)gh->nbuckets /
- ((double)gh->nentries * (gh->nentries + 2 * gh->nbuckets - 1)));
+}
+double BLI_gset_calc_quality_ex(
+ GSet *gs, double *r_load, double *r_variance,
+ double *r_prop_empty_buckets, double *r_prop_overloaded_buckets, int *r_biggest_bucket)
+{
+ return BLI_ghash_calc_quality_ex((GHash *)gs, r_load, r_variance,
+ r_prop_empty_buckets, r_prop_overloaded_buckets, r_biggest_bucket);
+}
+
+double BLI_ghash_calc_quality(GHash *gh)
+{
+ return BLI_ghash_calc_quality_ex(gh, NULL, NULL, NULL, NULL, NULL);
}
double BLI_gset_calc_quality(GSet *gs)
{
- return BLI_ghash_calc_quality((GHash *)gs);
+ return BLI_ghash_calc_quality_ex((GHash *)gs, NULL, NULL, NULL, NULL, NULL);
}
-#endif
/** \} */
diff --git a/source/blender/blenlib/intern/BLI_heap.c b/source/blender/blenlib/intern/BLI_heap.c
index 55dee4e8677..4bd404e5d73 100644
--- a/source/blender/blenlib/intern/BLI_heap.c
+++ b/source/blender/blenlib/intern/BLI_heap.c
@@ -49,19 +49,18 @@ struct Heap {
unsigned int bufsize;
MemArena *arena;
HeapNode *freenodes;
- HeapNode *nodes;
HeapNode **tree;
};
/* internal functions */
-#define HEAP_PARENT(i) ((i - 1) >> 1)
-#define HEAP_LEFT(i) ((i << 1) + 1)
-#define HEAP_RIGHT(i) ((i << 1) + 2)
-#define HEAP_COMPARE(a, b) (a->value < b->value)
+#define HEAP_PARENT(i) (((i) - 1) >> 1)
+#define HEAP_LEFT(i) (((i) << 1) + 1)
+#define HEAP_RIGHT(i) (((i) << 1) + 2)
+#define HEAP_COMPARE(a, b) ((a)->value < (b)->value)
#if 0 /* UNUSED */
-#define HEAP_EQUALS(a, b) (a->value == b->value)
+#define HEAP_EQUALS(a, b) ((a)->value == (b)->value)
#endif
BLI_INLINE void heap_swap(Heap *heap, const unsigned int i, const unsigned int j)
@@ -139,9 +138,9 @@ Heap *BLI_heap_new(void)
void BLI_heap_free(Heap *heap, HeapFreeFP ptrfreefp)
{
- unsigned int i;
-
if (ptrfreefp) {
+ unsigned int i;
+
for (i = 0; i < heap->size; i++) {
ptrfreefp(heap->tree[i]->ptr);
}
@@ -152,6 +151,21 @@ void BLI_heap_free(Heap *heap, HeapFreeFP ptrfreefp)
MEM_freeN(heap);
}
+void BLI_heap_clear(Heap *heap, HeapFreeFP ptrfreefp)
+{
+ if (ptrfreefp) {
+ unsigned int i;
+
+ for (i = 0; i < heap->size; i++) {
+ ptrfreefp(heap->tree[i]->ptr);
+ }
+ }
+
+ heap->size = 0;
+ BLI_memarena_clear(heap->arena);
+ heap->freenodes = NULL;
+}
+
HeapNode *BLI_heap_insert(Heap *heap, float value, void *ptr)
{
HeapNode *node;
@@ -163,14 +177,14 @@ HeapNode *BLI_heap_insert(Heap *heap, float value, void *ptr)
if (heap->freenodes) {
node = heap->freenodes;
- heap->freenodes = (HeapNode *)(((HeapNode *)heap->freenodes)->ptr);
+ heap->freenodes = heap->freenodes->ptr;
}
else {
node = (HeapNode *)BLI_memarena_alloc(heap->arena, sizeof(*node));
}
- node->value = value;
node->ptr = ptr;
+ node->value = value;
node->index = heap->size;
heap->tree[node->index] = node;
@@ -206,13 +220,8 @@ void *BLI_heap_popmin(Heap *heap)
heap->tree[0]->ptr = heap->freenodes;
heap->freenodes = heap->tree[0];
- if (UNLIKELY(heap->size == 1)) {
- heap->size--;
- }
- else {
- heap_swap(heap, 0, heap->size - 1);
- heap->size--;
-
+ if (--heap->size) {
+ heap_swap(heap, 0, heap->size);
heap_down(heap, 0);
}
diff --git a/source/blender/blenlib/intern/BLI_kdopbvh.c b/source/blender/blenlib/intern/BLI_kdopbvh.c
index d28215ee8ed..ddb61e415ac 100644
--- a/source/blender/blenlib/intern/BLI_kdopbvh.c
+++ b/source/blender/blenlib/intern/BLI_kdopbvh.c
@@ -27,6 +27,16 @@
/** \file blender/blenlib/intern/BLI_kdopbvh.c
* \ingroup bli
+ * \brief BVH-tree implementation.
+ *
+ * KD-Overlap-BVH, implements a bvh-tree structure with support for:
+ *
+ * - Ray-cast:
+ * #BLI_bvhtree_ray_cast, #BVHRayCastData
+ * - Nearest point on surface:
+ * #BLI_bvhtree_find_nearest, #BVHNearestData
+ * - Overlapping 2 trees:
+ * #BLI_bvhtree_overlap, #BVHOverlapData_Shared, #BVHOverlapData_Thread
*/
#include <assert.h>
@@ -34,6 +44,7 @@
#include "MEM_guardedalloc.h"
#include "BLI_utildefines.h"
+#include "BLI_alloca.h"
#include "BLI_stack.h"
#include "BLI_kdopbvh.h"
#include "BLI_math.h"
@@ -92,11 +103,22 @@ BLI_STATIC_ASSERT((sizeof(void *) == 8 && sizeof(BVHTree) <= 48) ||
(sizeof(void *) == 4 && sizeof(BVHTree) <= 32),
"over sized")
-typedef struct BVHOverlapData {
- BVHTree *tree1, *tree2;
- struct BLI_Stack *overlap; /* store BVHTreeOverlap */
+/* avoid duplicating vars in BVHOverlapData_Thread */
+typedef struct BVHOverlapData_Shared {
+ const BVHTree *tree1, *tree2;
axis_t start_axis, stop_axis;
-} BVHOverlapData;
+
+ /* use for callbacks */
+ BVHTree_OverlapCallback callback;
+ void *userdata;
+} BVHOverlapData_Shared;
+
+typedef struct BVHOverlapData_Thread {
+ BVHOverlapData_Shared *shared;
+ struct BLI_Stack *overlap; /* store BVHTreeOverlap */
+ /* use for callbacks */
+ int thread;
+} BVHOverlapData_Thread;
typedef struct BVHNearestData {
BVHTree *tree;
@@ -116,6 +138,12 @@ typedef struct BVHRayCastData {
BVHTreeRay ray;
+
+#ifdef USE_KDOPBVH_WATERTIGHT
+ struct IsectRayPrecalc isect_precalc;
+#endif
+
+ /* initialized by bvhtree_ray_cast_data_precalc */
float ray_dot_axis[13];
float idot_axis[13];
int index[6];
@@ -986,7 +1014,7 @@ bool BLI_bvhtree_update_node(BVHTree *tree, int index, const float co[3], const
/* check if index exists */
if (index > tree->totleaf)
- return 0;
+ return false;
node = tree->nodearray + index;
@@ -1001,7 +1029,7 @@ bool BLI_bvhtree_update_node(BVHTree *tree, int index, const float co[3], const
node->bv[(2 * axis_iter) + 1] += tree->epsilon; /* maximum */
}
- return 1;
+ return true;
}
/* call BLI_bvhtree_update_node() first for every node/point/triangle */
@@ -1030,30 +1058,30 @@ float BLI_bvhtree_getepsilon(const BVHTree *tree)
/**
* overlap - is it possible for 2 bv's to collide ?
*/
-static int tree_overlap(BVHNode *node1, BVHNode *node2, axis_t start_axis, axis_t stop_axis)
+static bool tree_overlap_test(const BVHNode *node1, const BVHNode *node2, axis_t start_axis, axis_t stop_axis)
{
- const float *bv1 = node1->bv;
- const float *bv2 = node2->bv;
-
- const float *bv1_end = bv1 + (stop_axis << 1);
-
- bv1 += start_axis << 1;
- bv2 += start_axis << 1;
+ const float *bv1 = node1->bv + (start_axis << 1);
+ const float *bv2 = node2->bv + (start_axis << 1);
+ const float *bv1_end = node1->bv + (stop_axis << 1);
/* test all axis if min + max overlap */
for (; bv1 != bv1_end; bv1 += 2, bv2 += 2) {
- if ((*(bv1) > *(bv2 + 1)) || (*(bv2) > *(bv1 + 1)))
+ if ((bv1[0] > bv2[1]) || (bv2[0] > bv1[1])) {
return 0;
+ }
}
return 1;
}
-static void traverse(BVHOverlapData *data, BVHNode *node1, BVHNode *node2)
+static void tree_overlap_traverse(
+ BVHOverlapData_Thread *data_thread,
+ const BVHNode *node1, const BVHNode *node2)
{
+ BVHOverlapData_Shared *data = data_thread->shared;
int j;
- if (tree_overlap(node1, node2, data->start_axis, data->stop_axis)) {
+ if (tree_overlap_test(node1, node2, data->start_axis, data->stop_axis)) {
/* check if node1 is a leaf */
if (!node1->totnode) {
/* check if node2 is a leaf */
@@ -1065,33 +1093,97 @@ static void traverse(BVHOverlapData *data, BVHNode *node1, BVHNode *node2)
}
/* both leafs, insert overlap! */
- overlap = BLI_stack_push_r(data->overlap);
+ overlap = BLI_stack_push_r(data_thread->overlap);
overlap->indexA = node1->index;
overlap->indexB = node2->index;
}
else {
for (j = 0; j < data->tree2->tree_type; j++) {
- if (node2->children[j])
- traverse(data, node1, node2->children[j]);
+ if (node2->children[j]) {
+ tree_overlap_traverse(data_thread, node1, node2->children[j]);
+ }
+ }
+ }
+ }
+ else {
+ for (j = 0; j < data->tree2->tree_type; j++) {
+ if (node1->children[j]) {
+ tree_overlap_traverse(data_thread, node1->children[j], node2);
+ }
+ }
+ }
+ }
+}
+
+/**
+ * a version of #tree_overlap_traverse that runs a callback to check if the nodes really intersect.
+ */
+static void tree_overlap_traverse_cb(
+ BVHOverlapData_Thread *data_thread,
+ const BVHNode *node1, const BVHNode *node2)
+{
+ BVHOverlapData_Shared *data = data_thread->shared;
+ int j;
+
+ if (tree_overlap_test(node1, node2, data->start_axis, data->stop_axis)) {
+ /* check if node1 is a leaf */
+ if (!node1->totnode) {
+ /* check if node2 is a leaf */
+ if (!node2->totnode) {
+ BVHTreeOverlap *overlap;
+
+ if (UNLIKELY(node1 == node2)) {
+ return;
+ }
+
+ /* only difference to tree_overlap_traverse! */
+ if (data->callback(data->userdata, node1->index, node2->index, data_thread->thread)) {
+ /* both leafs, insert overlap! */
+ overlap = BLI_stack_push_r(data_thread->overlap);
+ overlap->indexA = node1->index;
+ overlap->indexB = node2->index;
+ }
+ }
+ else {
+ for (j = 0; j < data->tree2->tree_type; j++) {
+ if (node2->children[j]) {
+ tree_overlap_traverse_cb(data_thread, node1, node2->children[j]);
+ }
}
}
}
else {
for (j = 0; j < data->tree2->tree_type; j++) {
- if (node1->children[j])
- traverse(data, node1->children[j], node2);
+ if (node1->children[j]) {
+ tree_overlap_traverse_cb(data_thread, node1->children[j], node2);
+ }
}
}
}
- return;
}
-BVHTreeOverlap *BLI_bvhtree_overlap(BVHTree *tree1, BVHTree *tree2, unsigned int *r_overlap_tot)
+/**
+ * Use to check the total number of threads #BLI_bvhtree_overlap will use.
+ *
+ * \warning Must be the first tree passed to #BLI_bvhtree_overlap!
+ */
+int BLI_bvhtree_overlap_thread_num(const BVHTree *tree)
{
+ return (int)MIN2(tree->tree_type, tree->nodes[tree->totleaf]->totnode);
+}
+
+BVHTreeOverlap *BLI_bvhtree_overlap(
+ const BVHTree *tree1, const BVHTree *tree2, unsigned int *r_overlap_tot,
+ /* optional callback to test the overlap before adding (must be thread-safe!) */
+ BVHTree_OverlapCallback callback, void *userdata)
+{
+ const int thread_num = BLI_bvhtree_overlap_thread_num(tree1);
int j;
size_t total = 0;
BVHTreeOverlap *overlap = NULL, *to = NULL;
- BVHOverlapData **data;
+ BVHOverlapData_Shared data_shared;
+ BVHOverlapData_Thread *data = BLI_array_alloca(data, (size_t)thread_num);
+ axis_t start_axis, stop_axis;
/* check for compatibility of both trees (can't compare 14-DOP with 18-DOP) */
if (UNLIKELY((tree1->axis != tree2->axis) &&
@@ -1101,50 +1193,55 @@ BVHTreeOverlap *BLI_bvhtree_overlap(BVHTree *tree1, BVHTree *tree2, unsigned int
BLI_assert(0);
return NULL;
}
+
+ start_axis = min_axis(tree1->start_axis, tree2->start_axis);
+ stop_axis = min_axis(tree1->stop_axis, tree2->stop_axis);
/* fast check root nodes for collision before doing big splitting + traversal */
- if (!tree_overlap(tree1->nodes[tree1->totleaf], tree2->nodes[tree2->totleaf],
- min_axis(tree1->start_axis, tree2->start_axis),
- min_axis(tree1->stop_axis, tree2->stop_axis)))
- {
+ if (!tree_overlap_test(tree1->nodes[tree1->totleaf], tree2->nodes[tree2->totleaf], start_axis, stop_axis)) {
return NULL;
}
- data = MEM_mallocN(sizeof(BVHOverlapData *) * tree1->tree_type, "BVHOverlapData_star");
-
- for (j = 0; j < tree1->tree_type; j++) {
- data[j] = MEM_mallocN(sizeof(BVHOverlapData), "BVHOverlapData");
-
- /* init BVHOverlapData */
- data[j]->overlap = BLI_stack_new(sizeof(BVHTreeOverlap), __func__);
- data[j]->tree1 = tree1;
- data[j]->tree2 = tree2;
- data[j]->start_axis = min_axis(tree1->start_axis, tree2->start_axis);
- data[j]->stop_axis = min_axis(tree1->stop_axis, tree2->stop_axis);
+ data_shared.tree1 = tree1;
+ data_shared.tree2 = tree2;
+ data_shared.start_axis = start_axis;
+ data_shared.stop_axis = stop_axis;
+
+ /* can be NULL */
+ data_shared.callback = callback;
+ data_shared.userdata = userdata;
+
+ for (j = 0; j < thread_num; j++) {
+ /* init BVHOverlapData_Thread */
+ data[j].shared = &data_shared;
+ data[j].overlap = BLI_stack_new(sizeof(BVHTreeOverlap), __func__);
+
+ /* for callback */
+ data[j].thread = j;
}
#pragma omp parallel for private(j) schedule(static) if (tree1->totleaf > KDOPBVH_OMP_LIMIT)
- for (j = 0; j < MIN2(tree1->tree_type, tree1->nodes[tree1->totleaf]->totnode); j++) {
- traverse(data[j], tree1->nodes[tree1->totleaf]->children[j], tree2->nodes[tree2->totleaf]);
+ for (j = 0; j < thread_num; j++) {
+ if (callback) {
+ tree_overlap_traverse_cb(&data[j], tree1->nodes[tree1->totleaf]->children[j], tree2->nodes[tree2->totleaf]);
+ }
+ else {
+ tree_overlap_traverse(&data[j], tree1->nodes[tree1->totleaf]->children[j], tree2->nodes[tree2->totleaf]);
+ }
}
- for (j = 0; j < tree1->tree_type; j++)
- total += BLI_stack_count(data[j]->overlap);
+ for (j = 0; j < thread_num; j++)
+ total += BLI_stack_count(data[j].overlap);
to = overlap = MEM_mallocN(sizeof(BVHTreeOverlap) * total, "BVHTreeOverlap");
- for (j = 0; j < tree1->tree_type; j++) {
- unsigned int count = (unsigned int)BLI_stack_count(data[j]->overlap);
- BLI_stack_pop_n(data[j]->overlap, to, count);
- BLI_stack_free(data[j]->overlap);
+ for (j = 0; j < thread_num; j++) {
+ unsigned int count = (unsigned int)BLI_stack_count(data[j].overlap);
+ BLI_stack_pop_n(data[j].overlap, to, count);
+ BLI_stack_free(data[j].overlap);
to += count;
}
-
- for (j = 0; j < tree1->tree_type; j++) {
- MEM_freeN(data[j]);
- }
- MEM_freeN(data);
-
+
*r_overlap_tot = (unsigned int)total;
return overlap;
}
@@ -1468,6 +1565,42 @@ static void dfs_raycast(BVHRayCastData *data, BVHNode *node)
}
}
+static void dfs_raycast_all(BVHRayCastData *data, BVHNode *node)
+{
+ int i;
+
+ /* ray-bv is really fast.. and simple tests revealed its worth to test it
+ * before calling the ray-primitive functions */
+ /* XXX: temporary solution for particles until fast_ray_nearest_hit supports ray.radius */
+ float dist = (data->ray.radius == 0.0f) ? fast_ray_nearest_hit(data, node) : ray_nearest_hit(data, node->bv);
+
+ if (node->totnode == 0) {
+ if (data->callback) {
+ data->hit.index = -1;
+ data->hit.dist = FLT_MAX;
+ data->callback(data->userdata, node->index, &data->ray, &data->hit);
+ }
+ else {
+ data->hit.index = node->index;
+ data->hit.dist = dist;
+ madd_v3_v3v3fl(data->hit.co, data->ray.origin, data->ray.direction, dist);
+ }
+ }
+ else {
+ /* pick loop direction to dive into the tree (based on ray direction and split axis) */
+ if (data->ray_dot_axis[node->main_axis] > 0.0f) {
+ for (i = 0; i != node->totnode; i++) {
+ dfs_raycast_all(data, node->children[i]);
+ }
+ }
+ else {
+ for (i = node->totnode - 1; i >= 0; i--) {
+ dfs_raycast_all(data, node->children[i]);
+ }
+ }
+ }
+}
+
#if 0
static void iterative_raycast(BVHRayCastData *data, BVHNode *node)
{
@@ -1497,13 +1630,46 @@ static void iterative_raycast(BVHRayCastData *data, BVHNode *node)
}
#endif
-int BLI_bvhtree_ray_cast(BVHTree *tree, const float co[3], const float dir[3], float radius, BVHTreeRayHit *hit,
- BVHTree_RayCastCallback callback, void *userdata)
+static void bvhtree_ray_cast_data_precalc(BVHRayCastData *data, int flag)
{
int i;
+
+ for (i = 0; i < 3; i++) {
+ data->ray_dot_axis[i] = dot_v3v3(data->ray.direction, KDOP_AXES[i]);
+ data->idot_axis[i] = 1.0f / data->ray_dot_axis[i];
+
+ if (fabsf(data->ray_dot_axis[i]) < FLT_EPSILON) {
+ data->ray_dot_axis[i] = 0.0;
+ }
+ data->index[2 * i] = data->idot_axis[i] < 0.0f ? 1 : 0;
+ data->index[2 * i + 1] = 1 - data->index[2 * i];
+ data->index[2 * i] += 2 * i;
+ data->index[2 * i + 1] += 2 * i;
+ }
+
+#ifdef USE_KDOPBVH_WATERTIGHT
+ if (flag & BVH_RAYCAST_WATERTIGHT) {
+ isect_ray_tri_watertight_v3_precalc(&data->isect_precalc, data->ray.direction);
+ data->ray.isect_precalc = &data->isect_precalc;
+ }
+ else {
+ data->ray.isect_precalc = NULL;
+ }
+#else
+ UNUSED_VARS(flag);
+#endif
+}
+
+int BLI_bvhtree_ray_cast_ex(
+ BVHTree *tree, const float co[3], const float dir[3], float radius, BVHTreeRayHit *hit,
+ BVHTree_RayCastCallback callback, void *userdata,
+ int flag)
+{
BVHRayCastData data;
BVHNode *root = tree->nodes[tree->totleaf];
+ BLI_ASSERT_UNIT_V3(dir);
+
data.tree = tree;
data.callback = callback;
@@ -1513,24 +1679,11 @@ int BLI_bvhtree_ray_cast(BVHTree *tree, const float co[3], const float dir[3], f
copy_v3_v3(data.ray.direction, dir);
data.ray.radius = radius;
- normalize_v3(data.ray.direction);
-
- for (i = 0; i < 3; i++) {
- data.ray_dot_axis[i] = dot_v3v3(data.ray.direction, KDOP_AXES[i]);
- data.idot_axis[i] = 1.0f / data.ray_dot_axis[i];
-
- if (fabsf(data.ray_dot_axis[i]) < FLT_EPSILON) {
- data.ray_dot_axis[i] = 0.0;
- }
- data.index[2 * i] = data.idot_axis[i] < 0.0f ? 1 : 0;
- data.index[2 * i + 1] = 1 - data.index[2 * i];
- data.index[2 * i] += 2 * i;
- data.index[2 * i + 1] += 2 * i;
- }
-
+ bvhtree_ray_cast_data_precalc(&data, flag);
- if (hit)
+ if (hit) {
memcpy(&data.hit, hit, sizeof(*hit));
+ }
else {
data.hit.index = -1;
data.hit.dist = FLT_MAX;
@@ -1548,6 +1701,13 @@ int BLI_bvhtree_ray_cast(BVHTree *tree, const float co[3], const float dir[3], f
return data.hit.index;
}
+int BLI_bvhtree_ray_cast(
+ BVHTree *tree, const float co[3], const float dir[3], float radius, BVHTreeRayHit *hit,
+ BVHTree_RayCastCallback callback, void *userdata)
+{
+ return BLI_bvhtree_ray_cast_ex(tree, co, dir, radius, hit, callback, userdata, BVH_RAYCAST_DEFAULT);
+}
+
float BLI_bvhtree_bb_raycast(const float bv[6], const float light_start[3], const float light_end[3], float pos[3])
{
BVHRayCastData data;
@@ -1574,6 +1734,47 @@ float BLI_bvhtree_bb_raycast(const float bv[6], const float light_start[3], cons
}
/**
+ * Calls the callback for every ray intersection
+ */
+int BLI_bvhtree_ray_cast_all_ex(
+ BVHTree *tree, const float co[3], const float dir[3], float radius,
+ BVHTree_RayCastCallback callback, void *userdata,
+ int flag)
+{
+ BVHRayCastData data;
+ BVHNode *root = tree->nodes[tree->totleaf];
+
+ BLI_ASSERT_UNIT_V3(dir);
+
+ data.tree = tree;
+
+ data.callback = callback;
+ data.userdata = userdata;
+
+ copy_v3_v3(data.ray.origin, co);
+ copy_v3_v3(data.ray.direction, dir);
+ data.ray.radius = radius;
+
+ bvhtree_ray_cast_data_precalc(&data, flag);
+
+ data.hit.index = -1;
+ data.hit.dist = FLT_MAX;
+
+ if (root) {
+ dfs_raycast_all(&data, root);
+ }
+
+ return data.hit.index;
+}
+
+int BLI_bvhtree_ray_cast_all(
+ BVHTree *tree, const float co[3], const float dir[3], float radius,
+ BVHTree_RayCastCallback callback, void *userdata)
+{
+ return BLI_bvhtree_ray_cast_all_ex(tree, co, dir, radius, callback, userdata, BVH_RAYCAST_DEFAULT);
+}
+
+/**
* Range Query - as request by broken :P
*
* Allocs and fills an array with the indexs of node that are on the given spherical range (center, radius)
diff --git a/source/blender/blenlib/intern/BLI_linklist.c b/source/blender/blenlib/intern/BLI_linklist.c
index a0b61e7945c..1da39967945 100644
--- a/source/blender/blenlib/intern/BLI_linklist.c
+++ b/source/blender/blenlib/intern/BLI_linklist.c
@@ -30,13 +30,18 @@
* \ingroup bli
*/
+#include <stdlib.h>
#include "MEM_guardedalloc.h"
+
+#include "BLI_utildefines.h"
#include "BLI_linklist.h"
#include "BLI_memarena.h"
#include "BLI_mempool.h"
-int BLI_linklist_length(LinkNode *list)
+#include "BLI_strict_flags.h"
+
+int BLI_linklist_count(LinkNode *list)
{
int len;
@@ -85,6 +90,77 @@ void BLI_linklist_reverse(LinkNode **listp)
}
/**
+ * Move an item from its current position to a new one inside a single-linked list.
+ * Note *listp may be modified.
+ */
+void BLI_linklist_move_item(LinkNode **listp, int curr_index, int new_index)
+{
+ LinkNode *lnk, *lnk_psrc = NULL, *lnk_pdst = NULL;
+ int i;
+
+ if (new_index == curr_index) {
+ return;
+ }
+
+ if (new_index < curr_index) {
+ for (lnk = *listp, i = 0; lnk; lnk = lnk->next, i++) {
+ if (i == new_index - 1) {
+ lnk_pdst = lnk;
+ }
+ else if (i == curr_index - 1) {
+ lnk_psrc = lnk;
+ break;
+ }
+ }
+
+ if (!(lnk_psrc && lnk_psrc->next && (!lnk_pdst || lnk_pdst->next))) {
+ /* Invalid indices, abort. */
+ return;
+ }
+
+ lnk = lnk_psrc->next;
+ lnk_psrc->next = lnk->next;
+ if (lnk_pdst) {
+ lnk->next = lnk_pdst->next;
+ lnk_pdst->next = lnk;
+ }
+ else {
+ /* destination is first element of the list... */
+ lnk->next = *listp;
+ *listp = lnk;
+ }
+ }
+ else {
+ for (lnk = *listp, i = 0; lnk; lnk = lnk->next, i++) {
+ if (i == new_index) {
+ lnk_pdst = lnk;
+ break;
+ }
+ else if (i == curr_index - 1) {
+ lnk_psrc = lnk;
+ }
+ }
+
+ if (!(lnk_pdst && (!lnk_psrc || lnk_psrc->next))) {
+ /* Invalid indices, abort. */
+ return;
+ }
+
+ if (lnk_psrc) {
+ lnk = lnk_psrc->next;
+ lnk_psrc->next = lnk->next;
+ }
+ else {
+ /* source is first element of the list... */
+ lnk = *listp;
+ *listp = lnk->next;
+ }
+ lnk->next = lnk_pdst->next;
+ lnk_pdst->next = lnk;
+ }
+}
+
+/**
* A version of prepend that takes the allocated link.
*/
void BLI_linklist_prepend_nlink(LinkNode **listp, void *ptr, LinkNode *nlink)
@@ -96,7 +172,7 @@ void BLI_linklist_prepend_nlink(LinkNode **listp, void *ptr, LinkNode *nlink)
void BLI_linklist_prepend(LinkNode **listp, void *ptr)
{
- LinkNode *nlink = MEM_mallocN(sizeof(*nlink), "nlink");
+ LinkNode *nlink = MEM_mallocN(sizeof(*nlink), __func__);
BLI_linklist_prepend_nlink(listp, ptr, nlink);
}
@@ -115,40 +191,39 @@ void BLI_linklist_prepend_pool(LinkNode **listp, void *ptr, BLI_mempool *mempool
/**
* A version of append that takes the allocated link.
*/
-void BLI_linklist_append_nlink(LinkNode **listp, void *ptr, LinkNode *nlink)
+void BLI_linklist_append_nlink(LinkNodePair *list_pair, void *ptr, LinkNode *nlink)
{
- LinkNode *node = *listp;
-
nlink->link = ptr;
nlink->next = NULL;
- if (node == NULL) {
- *listp = nlink;
+ if (list_pair->list) {
+ BLI_assert((list_pair->last_node != NULL) && (list_pair->last_node->next == NULL));
+ list_pair->last_node->next = nlink;
}
else {
- while (node->next != NULL) {
- node = node->next;
- }
- node->next = nlink;
+ BLI_assert(list_pair->last_node == NULL);
+ list_pair->list = nlink;
}
+
+ list_pair->last_node = nlink;
}
-void BLI_linklist_append(LinkNode **listp, void *ptr)
+void BLI_linklist_append(LinkNodePair *list_pair, void *ptr)
{
- LinkNode *nlink = MEM_mallocN(sizeof(*nlink), "nlink");
- BLI_linklist_append_nlink(listp, ptr, nlink);
+ LinkNode *nlink = MEM_mallocN(sizeof(*nlink), __func__);
+ BLI_linklist_append_nlink(list_pair, ptr, nlink);
}
-void BLI_linklist_append_arena(LinkNode **listp, void *ptr, MemArena *ma)
+void BLI_linklist_append_arena(LinkNodePair *list_pair, void *ptr, MemArena *ma)
{
LinkNode *nlink = BLI_memarena_alloc(ma, sizeof(*nlink));
- BLI_linklist_append_nlink(listp, ptr, nlink);
+ BLI_linklist_append_nlink(list_pair, ptr, nlink);
}
-void BLI_linklist_append_pool(LinkNode **listp, void *ptr, BLI_mempool *mempool)
+void BLI_linklist_append_pool(LinkNodePair *list_pair, void *ptr, BLI_mempool *mempool)
{
LinkNode *nlink = BLI_mempool_alloc(mempool);
- BLI_linklist_append_nlink(listp, ptr, nlink);
+ BLI_linklist_append_nlink(list_pair, ptr, nlink);
}
void *BLI_linklist_pop(struct LinkNode **listp)
@@ -157,7 +232,7 @@ void *BLI_linklist_pop(struct LinkNode **listp)
void *link = (*listp)->link;
void *next = (*listp)->next;
- MEM_freeN((*listp));
+ MEM_freeN(*listp);
*listp = next;
return link;
@@ -177,7 +252,7 @@ void *BLI_linklist_pop_pool(struct LinkNode **listp, struct BLI_mempool *mempool
void BLI_linklist_insert_after(LinkNode **listp, void *ptr)
{
- LinkNode *nlink = MEM_mallocN(sizeof(*nlink), "nlink");
+ LinkNode *nlink = MEM_mallocN(sizeof(*nlink), __func__);
LinkNode *node = *listp;
nlink->link = ptr;
@@ -235,3 +310,40 @@ void BLI_linklist_apply(LinkNode *list, LinkNodeApplyFP applyfunc, void *userdat
for (; list; list = list->next)
applyfunc(list->link, userdata);
}
+
+/* -------------------------------------------------------------------- */
+/* Sort */
+#define SORT_IMPL_LINKTYPE LinkNode
+#define SORT_IMPL_LINKTYPE_DATA link
+
+/* regular call */
+#define SORT_IMPL_FUNC linklist_sort_fn
+#include "list_sort_impl.h"
+#undef SORT_IMPL_FUNC
+
+/* reentrant call */
+#define SORT_IMPL_USE_THUNK
+#define SORT_IMPL_FUNC linklist_sort_fn_r
+#include "list_sort_impl.h"
+#undef SORT_IMPL_FUNC
+#undef SORT_IMPL_USE_THUNK
+
+#undef SORT_IMPL_LINKTYPE
+#undef SORT_IMPL_LINKTYPE_DATA
+
+
+LinkNode *BLI_linklist_sort(LinkNode *list, int (*cmp)(const void *, const void *))
+{
+ if (list && list->next) {
+ list = linklist_sort_fn(list, cmp);
+ }
+ return list;
+}
+
+LinkNode *BLI_linklist_sort_r(LinkNode *list, int (*cmp)(void *, const void *, const void *), void *thunk)
+{
+ if (list && list->next) {
+ list = linklist_sort_fn_r(list, cmp, thunk);
+ }
+ return list;
+}
diff --git a/source/blender/blenlib/intern/BLI_memarena.c b/source/blender/blenlib/intern/BLI_memarena.c
index dd0997c8e1c..2604dbafdc0 100644
--- a/source/blender/blenlib/intern/BLI_memarena.c
+++ b/source/blender/blenlib/intern/BLI_memarena.c
@@ -28,6 +28,14 @@
/** \file blender/blenlib/intern/BLI_memarena.c
* \ingroup bli
+ * \brief Memory arena ADT.
+ * \section aboutmemarena Memory Arena
+ *
+ * Memory arena's are commonly used when the program
+ * needs to quickly allocate lots of little bits of data,
+ * which are all freed at the same moment.
+ *
+ * \note Memory can't be freed during the arenas lifetime.
*/
#include <stdlib.h>
diff --git a/source/blender/blenlib/intern/BLI_mempool.c b/source/blender/blenlib/intern/BLI_mempool.c
index 8fc5f97221d..7338804c685 100644
--- a/source/blender/blenlib/intern/BLI_mempool.c
+++ b/source/blender/blenlib/intern/BLI_mempool.c
@@ -27,8 +27,15 @@
/** \file blender/blenlib/intern/BLI_mempool.c
* \ingroup bli
+ * \author Geoffrey Bantle
*
* Simple, fast memory allocator for allocating many elements of the same size.
+ *
+ * Supports:
+ *
+ * - Freeing chunks.
+ * - Iterating over allocated chunks
+ * (optionally when using the #BLI_MEMPOOL_ALLOW_ITER flag).
*/
#include <string.h>
diff --git a/source/blender/blenlib/intern/array_utils.c b/source/blender/blenlib/intern/array_utils.c
new file mode 100644
index 00000000000..cef912e42a3
--- /dev/null
+++ b/source/blender/blenlib/intern/array_utils.c
@@ -0,0 +1,144 @@
+/*
+ * ***** 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/array_utils.c
+ * \ingroup bli
+ * \brief Generic array manipulation API.
+ *
+ * \warning Some array operations here are inherently inefficient,
+ * and only included for the cases where the performance is acceptable.
+ * Use with care.
+ */
+#include <string.h>
+#include <stdlib.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_array_utils.h"
+
+#include "BLI_sys_types.h"
+#include "BLI_utildefines.h"
+#include "BLI_alloca.h"
+
+#include "BLI_strict_flags.h"
+
+/**
+ *In-place array reverse.
+ *
+ * Access via #BLI_array_reverse
+ */
+void _bli_array_reverse(void *arr_v, unsigned int arr_len, size_t arr_stride)
+{
+ const unsigned int arr_stride_uint = (unsigned int)arr_stride;
+ const unsigned int arr_half_stride = (arr_len / 2) * arr_stride_uint;
+ unsigned int i, i_end;
+ char *arr = arr_v;
+ char *buf = BLI_array_alloca(buf, arr_stride);
+
+ for (i = 0, i_end = (arr_len - 1) * arr_stride_uint;
+ i < arr_half_stride;
+ i += arr_stride_uint, i_end -= arr_stride_uint)
+ {
+ memcpy(buf, &arr[i], arr_stride);
+ memcpy(&arr[i], &arr[i_end], arr_stride);
+ memcpy(&arr[i_end], buf, arr_stride);
+ }
+}
+
+/**
+ * In-place array wrap.
+ * (rotate the array one step forward or backwards).
+ *
+ * Access via #BLI_array_wrap
+ */
+void _bli_array_wrap(void *arr_v, unsigned int arr_len, size_t arr_stride, int dir)
+{
+ char *arr = arr_v;
+ char *buf = BLI_array_alloca(buf, arr_stride);
+
+ if (dir == -1) {
+ memcpy(buf, arr, arr_stride);
+ memmove(arr, arr + arr_stride, arr_stride * (arr_len - 1));
+ memcpy(arr + (arr_stride * (arr_len - 1)), buf, arr_stride);
+ }
+ else if (dir == 1) {
+ memcpy(buf, arr + (arr_stride * (arr_len - 1)), arr_stride);
+ memmove(arr + arr_stride, arr, arr_stride * (arr_len - 1));
+ memcpy(arr, buf, arr_stride);
+ }
+ else {
+ BLI_assert(0);
+ }
+}
+
+/**
+ *In-place array permute.
+ * (re-arrange elements based on an array of indices).
+ *
+ * Access via #BLI_array_wrap
+ */
+void _bli_array_permute(
+ void *arr_v, const unsigned int arr_len, const size_t arr_stride,
+ const unsigned int *order, void *arr_temp)
+{
+ const size_t len = arr_len * arr_stride;
+ const unsigned int arr_stride_uint = (unsigned int)arr_stride;
+ void *arr_orig;
+ unsigned int i;
+
+ if (arr_temp == NULL) {
+ arr_orig = MEM_mallocN(len, __func__);
+ }
+ else {
+ arr_orig = arr_temp;
+ }
+
+ memcpy(arr_orig, arr_v, len);
+
+ for (i = 0; i < arr_len; i++) {
+ BLI_assert(order[i] < arr_len);
+ memcpy(POINTER_OFFSET(arr_v, arr_stride_uint * i),
+ POINTER_OFFSET(arr_orig, arr_stride_uint * order[i]),
+ arr_stride);
+ }
+
+ if (arr_temp == NULL) {
+ MEM_freeN(arr_orig);
+ }
+}
+
+/**
+ * Find the first index of an item in an array.
+ *
+ * Access via #BLI_array_findindex
+ *
+ * \note Not efficient, use for error checks/asserts.
+ */
+int _bli_array_findindex(const void *arr, unsigned int arr_len, size_t arr_stride, const void *p)
+{
+ const char *arr_step = (const char *)arr;
+ unsigned int i;
+ for (i = 0; i < arr_len; i++, arr_step += arr_stride) {
+ if (memcmp(arr_step, p, arr_stride) == 0) {
+ return (int)i;
+ }
+ }
+ return -1;
+}
diff --git a/source/blender/blenlib/intern/astar.c b/source/blender/blenlib/intern/astar.c
new file mode 100644
index 00000000000..21d974de1c4
--- /dev/null
+++ b/source/blender/blenlib/intern/astar.c
@@ -0,0 +1,282 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2014 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Bastien Montagne
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/blenlib/intern/astar.c
+ * \ingroup bli
+ * \brief An implementation of the A* (AStar) algorithm to solve shortest path problem.
+ *
+ * This library implements the simple A* (AStar) algorithm, an optimized version of
+ * classical dijkstra shortest path solver. The difference is that each future possible
+ * path is weighted from its 'shortest' (smallest) possible distance to destination,
+ * in addition to distance already walked. This heuristic allows more efficiency
+ * in finding optimal path.
+ *
+ * Implementation based on Wikipedia A* page [http://en.wikipedia.org/wiki/A*_search_algorithm].
+ *
+ * Note that most memory handling here is done through two different MemArena's. Those should also be used to allocate
+ * custom data needed to a specific use of A*.
+ * The first one, owned by BLI_AStarGraph, is for 'static' data that will live as long as the graph.
+ * The second one, owned by BLI_AStarSolution, is for data used during a single path solve. It will be cleared
+ * much more often than graph's one.
+ */
+
+#include <limits.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_sys_types.h"
+#include "BLI_compiler_attrs.h"
+
+#include "BLI_alloca.h"
+#include "BLI_heap.h"
+#include "BLI_listbase.h"
+#include "BLI_math.h"
+#include "BLI_memarena.h"
+
+#include "BLI_astar.h"
+
+/**
+ * Init a node in A* graph.
+ *
+ * \param custom_data an opaque pointer attached to this link, available e.g. to cost callback function.
+ */
+void BLI_astar_node_init(BLI_AStarGraph *as_graph, const int node_index, void *custom_data)
+{
+ as_graph->nodes[node_index].custom_data = custom_data;
+}
+
+/**
+ * Add a link between two nodes of our A* graph.
+ *
+ * \param cost the 'length' of the link (actual distance between two vertices or face centers e.g.).
+ * \param custom_data an opaque pointer attached to this link, available e.g. to cost callback function.
+ */
+void BLI_astar_node_link_add(
+ BLI_AStarGraph *as_graph, const int node1_index, const int node2_index, const float cost, void *custom_data)
+{
+ MemArena *mem = as_graph->mem;
+ BLI_AStarGNLink *link = BLI_memarena_alloc(mem, sizeof(*link));
+ LinkData *ld = BLI_memarena_alloc(mem, sizeof(*ld) * 2);
+
+ link->nodes[0] = node1_index;
+ link->nodes[1] = node2_index;
+ link->cost = cost;
+ link->custom_data = custom_data;
+
+ ld[0].data = ld[1].data = link;
+
+ BLI_addtail(&(as_graph->nodes[node1_index].neighbor_links), &ld[0]);
+ BLI_addtail(&(as_graph->nodes[node2_index].neighbor_links), &ld[1]);
+}
+
+/**
+ * \return The index of the other node of given link.
+ */
+int BLI_astar_node_link_other_node(BLI_AStarGNLink *lnk, const int idx)
+{
+ return (lnk->nodes[0] == idx) ? lnk->nodes[1] : lnk->nodes[0];
+}
+
+/**
+ * Initialize a solution data for given A* graph. Does not compute anything!
+ *
+ * \param custom_data an opaque pointer attached to this link, available e.g. to cost callback function.
+ *
+ * \note BLI_AStarSolution stores nearly all data needed during solution compute.
+ */
+void BLI_astar_solution_init(BLI_AStarGraph *as_graph, BLI_AStarSolution *as_solution, void *custom_data)
+{
+ MemArena *mem = as_solution->mem;
+ size_t node_num = (size_t)as_graph->node_num;
+
+ if (mem == NULL) {
+ mem = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__);
+ as_solution->mem = mem;
+ }
+ /* else memarena should be cleared */
+
+ as_solution->steps = 0;
+ as_solution->prev_nodes = BLI_memarena_alloc(mem, sizeof(*as_solution->prev_nodes) * node_num);
+ as_solution->prev_links = BLI_memarena_alloc(mem, sizeof(*as_solution->prev_links) * node_num);
+
+ as_solution->custom_data = custom_data;
+
+ as_solution->done_nodes = BLI_BITMAP_NEW_MEMARENA(mem, node_num);
+ as_solution->g_costs = BLI_memarena_alloc(mem, sizeof(*as_solution->g_costs) * node_num);
+ as_solution->g_steps = BLI_memarena_alloc(mem, sizeof(*as_solution->g_steps) * node_num);
+}
+
+/**
+ * Clear given solution's data, but does not release its memory. Avoids having to recreate/allocate
+ * a memarena in loops, e.g.
+ *
+ * \note This *has to be called* between each path solving.
+ */
+void BLI_astar_solution_clear(BLI_AStarSolution *as_solution)
+{
+ if (as_solution->mem) {
+ BLI_memarena_clear(as_solution->mem);
+ }
+
+ as_solution->steps = 0;
+ as_solution->prev_nodes = NULL;
+ as_solution->prev_links = NULL;
+
+ as_solution->custom_data = NULL;
+
+ as_solution->done_nodes = NULL;
+ as_solution->g_costs = NULL;
+ as_solution->g_steps = NULL;
+}
+
+/**
+ * Release the memory allocated for this solution.
+ */
+void BLI_astar_solution_free(BLI_AStarSolution *as_solution)
+{
+ if (as_solution->mem) {
+ BLI_memarena_free(as_solution->mem);
+ as_solution->mem = NULL;
+ }
+}
+
+/**
+ * Init an A* graph. Total number of nodes must be known.
+ *
+ * Nodes might be e.g. vertices, faces, ...
+ *
+ * \param custom_data an opaque pointer attached to this link, available e.g. to cost callback function.
+ */
+void BLI_astar_graph_init(BLI_AStarGraph *as_graph, const int node_num, void *custom_data)
+{
+ MemArena *mem = as_graph->mem;
+
+ if (mem == NULL) {
+ mem = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__);
+ as_graph->mem = mem;
+ }
+ /* else memarena should be cleared */
+
+ as_graph->node_num = node_num;
+ as_graph->nodes = BLI_memarena_calloc(mem, sizeof(*as_graph->nodes) * (size_t)node_num);
+
+ as_graph->custom_data = custom_data;
+}
+
+void BLI_astar_graph_free(BLI_AStarGraph *as_graph)
+{
+ if (as_graph->mem) {
+ BLI_memarena_free(as_graph->mem);
+ as_graph->mem = NULL;
+ }
+}
+
+/**
+ * Solve a path in given graph, using given 'cost' callback function.
+ *
+ * \param max_steps maximum number of nodes the found path may have. Useful in performance-critical usages.
+ * If no path is found within given steps, returns false too.
+ * \return true if a path was found, false otherwise.
+ */
+bool BLI_astar_graph_solve(
+ BLI_AStarGraph *as_graph, const int node_index_src, const int node_index_dst, astar_f_cost f_cost_cb,
+ BLI_AStarSolution *r_solution, const int max_steps)
+{
+ Heap *todo_nodes;
+
+ BLI_bitmap *done_nodes = r_solution->done_nodes;
+ int *prev_nodes = r_solution->prev_nodes;
+ BLI_AStarGNLink **prev_links = r_solution->prev_links;
+ float *g_costs = r_solution->g_costs;
+ int *g_steps = r_solution->g_steps;
+
+ r_solution->steps = 0;
+ prev_nodes[node_index_src] = -1;
+ BLI_BITMAP_SET_ALL(done_nodes, false, as_graph->node_num);
+ copy_vn_fl(g_costs, as_graph->node_num, FLT_MAX);
+ g_costs[node_index_src] = 0.0f;
+ g_steps[node_index_src] = 0;
+
+ if (node_index_src == node_index_dst) {
+ return true;
+ }
+
+ todo_nodes = BLI_heap_new();
+ BLI_heap_insert(todo_nodes,
+ f_cost_cb(as_graph, r_solution, NULL, -1, node_index_src, node_index_dst),
+ SET_INT_IN_POINTER(node_index_src));
+
+ while (!BLI_heap_is_empty(todo_nodes)) {
+ const int node_curr_idx = GET_INT_FROM_POINTER(BLI_heap_popmin(todo_nodes));
+ BLI_AStarGNode *node_curr = &as_graph->nodes[node_curr_idx];
+ LinkData *ld;
+
+ if (BLI_BITMAP_TEST(done_nodes, node_curr_idx)) {
+ /* Might happen, because we always add nodes to heap when evaluating them, without ever removing them. */
+ continue;
+ }
+
+ /* If we are limited in amount of steps to find a path, skip if we reached limit. */
+ if (max_steps && g_steps[node_curr_idx] > max_steps) {
+ continue;
+ }
+
+ if (node_curr_idx == node_index_dst) {
+ /* Success! Path found... */
+ r_solution->steps = g_steps[node_curr_idx] + 1;
+
+ BLI_heap_free(todo_nodes, NULL);
+ return true;
+ }
+
+ BLI_BITMAP_ENABLE(done_nodes, node_curr_idx);
+
+ for (ld = node_curr->neighbor_links.first; ld; ld = ld->next) {
+ BLI_AStarGNLink *link = ld->data;
+ const int node_next_idx = BLI_astar_node_link_other_node(link, node_curr_idx);
+
+ if (!BLI_BITMAP_TEST(done_nodes, node_next_idx)) {
+ float g_cst = g_costs[node_curr_idx] + link->cost;
+
+ if (g_cst < g_costs[node_next_idx]) {
+ prev_nodes[node_next_idx] = node_curr_idx;
+ prev_links[node_next_idx] = link;
+ g_costs[node_next_idx] = g_cst;
+ g_steps[node_next_idx] = g_steps[node_curr_idx] + 1;
+ /* We might have this node already in heap, but since this 'instance' will be evaluated first,
+ * no problem. */
+ BLI_heap_insert(todo_nodes,
+ f_cost_cb(as_graph, r_solution, link, node_curr_idx, node_next_idx, node_index_dst),
+ SET_INT_IN_POINTER(node_next_idx));
+ }
+ }
+ }
+ }
+
+ BLI_heap_free(todo_nodes, NULL);
+ return false;
+}
diff --git a/source/blender/blenlib/intern/boxpack2d.c b/source/blender/blenlib/intern/boxpack2d.c
index 91495ce3c9c..2db52cbda60 100644
--- a/source/blender/blenlib/intern/boxpack2d.c
+++ b/source/blender/blenlib/intern/boxpack2d.c
@@ -32,6 +32,9 @@
#include "BLI_utildefines.h"
#include "BLI_boxpack2d.h" /* own include */
+#include "BLI_sort.h" /* qsort_r */
+#define qsort_r BLI_qsort_r
+
#include "BLI_strict_flags.h"
#ifdef __GNUC__
@@ -226,18 +229,20 @@ static int box_areasort(const void *p1, const void *p2)
* sorts from lower left to top right It uses the current box's width and height
* as offsets when sorting, this has the result of not placing boxes outside
* the bounds of the existing backed area where possible
- * */
-static float box_width;
-static float box_height;
-static BoxVert *vertarray;
+ */
+struct VertSortContext {
+ BoxVert *vertarray;
+ float box_width, box_height;
+};
-static int vertex_sort(const void *p1, const void *p2)
+static int vertex_sort(const void *p1, const void *p2, void *vs_ctx_p)
{
- BoxVert *v1, *v2;
+ const struct VertSortContext *vs_ctx = vs_ctx_p;
+ const BoxVert *v1, *v2;
float a1, a2;
- v1 = vertarray + ((int *)p1)[0];
- v2 = vertarray + ((int *)p2)[0];
+ v1 = &vs_ctx->vertarray[*((const unsigned int *)p1)];
+ v2 = &vs_ctx->vertarray[*((const unsigned int *)p2)];
#ifdef USE_FREE_STRIP
/* push free verts to the end so we can strip */
@@ -246,8 +251,8 @@ static int vertex_sort(const void *p1, const void *p2)
else if (UNLIKELY(v2->free == 0)) return -1;
#endif
- a1 = max_ff(v1->x + box_width, v1->y + box_height);
- a2 = max_ff(v2->x + box_width, v2->y + box_height);
+ a1 = max_ff(v1->x + vs_ctx->box_width, v1->y + vs_ctx->box_height);
+ a2 = max_ff(v2->x + vs_ctx->box_width, v2->y + vs_ctx->box_height);
#ifdef USE_PACK_BIAS
a1 += v1->bias;
@@ -285,6 +290,8 @@ void BLI_box_pack_2d(BoxPack *boxarray, const unsigned int len, float *r_tot_x,
BoxPack *box, *box_test; /*current box and another for intersection tests*/
BoxVert *vert; /* the current vert */
+ struct VertSortContext vs_ctx;
+
if (!len) {
*r_tot_x = tot_x;
*r_tot_y = tot_y;
@@ -295,9 +302,11 @@ void BLI_box_pack_2d(BoxPack *boxarray, const unsigned int len, float *r_tot_x,
qsort(boxarray, (size_t)len, sizeof(BoxPack), box_areasort);
/* add verts to the boxes, these are only used internally */
- vert = vertarray = MEM_mallocN((size_t)len * 4 * sizeof(BoxVert), "BoxPack Verts");
+ vert = MEM_mallocN((size_t)len * 4 * sizeof(BoxVert), "BoxPack Verts");
vertex_pack_indices = MEM_mallocN((size_t)len * 3 * sizeof(int), "BoxPack Indices");
+ vs_ctx.vertarray = vert;
+
for (box = boxarray, box_index = 0, i = 0; box_index < len; box_index++, box++) {
vert->blb = vert->brb = vert->tlb =
@@ -371,16 +380,16 @@ void BLI_box_pack_2d(BoxPack *boxarray, const unsigned int len, float *r_tot_x,
/* Main boxpacking loop */
for (box_index = 1; box_index < len; box_index++, box++) {
- /* These static floatds are used for sorting */
- box_width = box->w;
- box_height = box->h;
+ /* These floats are used for sorting re-sorting */
+ vs_ctx.box_width = box->w;
+ vs_ctx.box_height = box->h;
- qsort(vertex_pack_indices, (size_t)verts_pack_len, sizeof(int), vertex_sort);
+ qsort_r(vertex_pack_indices, (size_t)verts_pack_len, sizeof(int), vertex_sort, &vs_ctx);
#ifdef USE_FREE_STRIP
/* strip free vertices */
i = verts_pack_len - 1;
- while ((i != 0) && vertarray[vertex_pack_indices[i]].free == 0) {
+ while ((i != 0) && vs_ctx.vertarray[vertex_pack_indices[i]].free == 0) {
i--;
}
verts_pack_len = i + 1;
@@ -391,7 +400,7 @@ void BLI_box_pack_2d(BoxPack *boxarray, const unsigned int len, float *r_tot_x,
isect = true;
for (i = 0; i < verts_pack_len && isect; i++) {
- vert = vertarray + vertex_pack_indices[i];
+ vert = &vs_ctx.vertarray[vertex_pack_indices[i]];
/* printf("\ttesting vert %i %i %i %f %f\n", i,
* vert->free, verts_pack_len, vert->x, vert->y); */
@@ -661,5 +670,5 @@ void BLI_box_pack_2d(BoxPack *boxarray, const unsigned int len, float *r_tot_x,
box->v[0] = box->v[1] = box->v[2] = box->v[3] = NULL;
}
MEM_freeN(vertex_pack_indices);
- MEM_freeN(vertarray);
+ MEM_freeN(vs_ctx.vertarray);
}
diff --git a/source/blender/blenlib/intern/buffer.c b/source/blender/blenlib/intern/buffer.c
index 4e570823319..9e96205a5e8 100644
--- a/source/blender/blenlib/intern/buffer.c
+++ b/source/blender/blenlib/intern/buffer.c
@@ -38,17 +38,14 @@ static void *buffer_alloc(BLI_Buffer *buffer, int len)
static void *buffer_realloc(BLI_Buffer *buffer, int len)
{
- if (buffer->flag & BLI_BUFFER_USE_CALLOC) {
- return MEM_recallocN(buffer->data, buffer->elem_size * len);
- }
- else {
- return MEM_reallocN(buffer->data, buffer->elem_size * len);
- }
+ return ((buffer->flag & BLI_BUFFER_USE_CALLOC) ?
+ MEM_recallocN_id : MEM_reallocN_id)
+ (buffer->data, buffer->elem_size * len, "BLI_Buffer.data");
}
void BLI_buffer_resize(BLI_Buffer *buffer, int new_count)
{
- if (new_count > buffer->alloc_count) {
+ if (UNLIKELY(new_count > buffer->alloc_count)) {
if (buffer->flag & BLI_BUFFER_USE_STATIC) {
void *orig = buffer->data;
@@ -65,12 +62,7 @@ void BLI_buffer_resize(BLI_Buffer *buffer, int new_count)
buffer->alloc_count = new_count;
}
- if (buffer->data) {
- buffer->data = buffer_realloc(buffer, buffer->alloc_count);
- }
- else {
- buffer->data = buffer_alloc(buffer, buffer->alloc_count);
- }
+ buffer->data = buffer_realloc(buffer, buffer->alloc_count);
}
}
diff --git a/source/blender/blenlib/intern/convexhull2d.c b/source/blender/blenlib/intern/convexhull2d.c
index 361e4b4eadb..740f3cce4a4 100644
--- a/source/blender/blenlib/intern/convexhull2d.c
+++ b/source/blender/blenlib/intern/convexhull2d.c
@@ -187,8 +187,8 @@ static int pointref_cmp_yx(const void *a_, const void *b_)
* \param points An array of 2D points.
* \param n The number of points in points.
* \param r_points An array of the convex hull vertex indices (max is n).
- * _must_ be allocated as ``n * 2`` because of how its used internally,
- * even though the final result will be no more then \a n in size.
+ * _must_ be allocated as ``n * 2`` because of how its used internally,
+ * even though the final result will be no more than \a n in size.
* \returns the number of points in r_points.
*/
int BLI_convexhull_2d(const float (*points)[2], const int n, int r_points[])
@@ -239,7 +239,7 @@ int BLI_convexhull_2d(const float (*points)[2], const int n, int r_points[])
*
* Intended to be used with #BLI_convexhull_2d
*
- * \param points Orded hull points
+ * \param points_hull Ordered hull points
* (result of #BLI_convexhull_2d mapped to a contiguous array).
*
* \note we could return the index of the best edge too if its needed.
diff --git a/source/blender/blenlib/intern/dynlib.c b/source/blender/blenlib/intern/dynlib.c
index b66eda4f141..e916b01e859 100644
--- a/source/blender/blenlib/intern/dynlib.c
+++ b/source/blender/blenlib/intern/dynlib.c
@@ -43,6 +43,8 @@ struct DynamicLibrary {
#ifdef WIN32
+#define _WIN32_WINNT 0x501 /* Windows XP or newer */
+#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include "utf_winfunc.h"
#include "utfconv.h"
diff --git a/source/blender/blenlib/intern/easing.c b/source/blender/blenlib/intern/easing.c
index 80f02d54eaa..90c8528338e 100644
--- a/source/blender/blenlib/intern/easing.c
+++ b/source/blender/blenlib/intern/easing.c
@@ -139,7 +139,7 @@ float BLI_easing_cubic_ease_in_out(float time, float begin, float change, float
#ifdef USE_ELASTIC_BLEND
/**
- * When the amplitude is less then the change, we need to blend
+ * When the amplitude is less than the change, we need to blend
* \a f when we're close to the crossing point (int time), else we get an ugly sharp falloff.
*/
static float elastic_blend(float time, float change, float duration, float amplitude, float s, float f)
diff --git a/source/blender/blenlib/intern/edgehash.c b/source/blender/blenlib/intern/edgehash.c
index 4ed82f8a473..cde4a8bf59d 100644
--- a/source/blender/blenlib/intern/edgehash.c
+++ b/source/blender/blenlib/intern/edgehash.c
@@ -23,12 +23,13 @@
/** \file blender/blenlib/intern/edgehash.c
* \ingroup bli
*
- * A general (pointer -> pointer) hash table ADT
+ * An (edge -> pointer) chaining hash table.
+ * Using unordered int-pairs as keys.
*
- * \note Based on 'BLI_ghash.c', make sure these stay in sync.
+ * \note Based on 'BLI_ghash.c', which is a more generalized hash-table
+ * make sure these stay in sync.
*/
-
#include <stdlib.h>
#include <string.h>
#include <limits.h>
@@ -146,7 +147,7 @@ BLI_INLINE void edgehash_buckets_reserve(EdgeHash *eh, const unsigned int nentri
/**
* Internal lookup function.
- * Takes a hash argument to avoid calling #ghash_keyhash multiple times.
+ * Takes a hash argument to avoid calling #edgehash_keyhash multiple times.
*/
BLI_INLINE EdgeEntry *edgehash_lookup_entry_ex(EdgeHash *eh, unsigned int v0, unsigned int v1,
const unsigned int hash)
@@ -239,6 +240,30 @@ BLI_INLINE void edgehash_insert_ex_keyonly(EdgeHash *eh, unsigned int v0, unsign
e->next = eh->buckets[hash];
e->v0 = v0;
e->v1 = v1;
+ eh->buckets[hash] = e;
+
+ if (UNLIKELY(edgehash_test_expand_buckets(++eh->nentries, eh->nbuckets))) {
+ edgehash_resize_buckets(eh, _ehash_hashsizes[++eh->cursize]);
+ }
+}
+
+/**
+ * Insert function that doesn't set the value (use for EdgeSet)
+ */
+BLI_INLINE void edgehash_insert_ex_keyonly_entry(
+ EdgeHash *eh, unsigned int v0, unsigned int v1,
+ unsigned int hash,
+ EdgeEntry *e)
+{
+ BLI_assert((eh->flag & EDGEHASH_FLAG_ALLOW_DUPES) || (BLI_edgehash_haskey(eh, v0, v1) == 0));
+
+ /* this helps to track down errors with bad edge data */
+ BLI_assert(v0 < v1);
+ BLI_assert(v0 != v1);
+
+ e->next = eh->buckets[hash];
+ e->v0 = v0;
+ e->v1 = v1;
/* intentionally leave value unset */
eh->buckets[hash] = e;
@@ -256,6 +281,35 @@ BLI_INLINE void edgehash_insert(EdgeHash *eh, unsigned int v0, unsigned int v1,
}
/**
+ * Remove the entry and return it, caller must free from eh->epool.
+ */
+static EdgeEntry *edgehash_remove_ex(EdgeHash *eh, unsigned int v0, unsigned int v1, EdgeHashFreeFP valfreefp,
+ unsigned int hash)
+{
+ EdgeEntry *e;
+ EdgeEntry *e_prev = NULL;
+
+ BLI_assert(v0 < v1);
+
+ for (e = eh->buckets[hash]; e; e = e->next) {
+ if (UNLIKELY(v0 == e->v0 && v1 == e->v1)) {
+ EdgeEntry *e_next = e->next;
+
+ if (valfreefp) valfreefp(e->val);
+
+ if (e_prev) e_prev->next = e_next;
+ else eh->buckets[hash] = e_next;
+
+ eh->nentries--;
+ return e;
+ }
+ e_prev = e;
+ }
+
+ return NULL;
+}
+
+/**
* Run free callbacks for freeing entries.
*/
static void edgehash_free_cb(EdgeHash *eh, EdgeHashFreeFP valfreefp)
@@ -343,6 +397,40 @@ void **BLI_edgehash_lookup_p(EdgeHash *eh, unsigned int v0, unsigned int v1)
}
/**
+ * Ensure \a (v0, v1) is exists in \a eh.
+ *
+ * This handles the common situation where the caller needs ensure a key is added to \a eh,
+ * constructing a new value in the case the key isn't found.
+ * Otherwise use the existing value.
+ *
+ * Such situations typically incur multiple lookups, however this function
+ * avoids them by ensuring the key is added,
+ * returning a pointer to the value so it can be used or initialized by the caller.
+ *
+ * \returns true when the value didn't need to be added.
+ * (when false, the caller _must_ initialize the value).
+ */
+bool BLI_edgehash_ensure_p(EdgeHash *eh, unsigned int v0, unsigned int v1, void ***r_val)
+{
+ unsigned int hash;
+ EdgeEntry *e;
+ bool haskey;
+
+ EDGE_ORD(v0, v1); /* ensure v0 is smaller */
+ hash = edgehash_keyhash(eh, v0, v1);
+ e = edgehash_lookup_entry_ex(eh, v0, v1, hash);
+ haskey = (e != NULL);
+
+ if (!haskey) {
+ e = BLI_mempool_alloc(eh->epool);
+ edgehash_insert_ex_keyonly_entry(eh, v0, v1, hash, e);
+ }
+
+ *r_val = &e->val;
+ return haskey;
+}
+
+/**
* Return value for given edge (\a v0, \a v1), or NULL if
* if key does not exist in hash. (If need exists
* to differentiate between key-value being NULL and
@@ -366,6 +454,57 @@ void *BLI_edgehash_lookup_default(EdgeHash *eh, unsigned int v0, unsigned int v1
}
/**
+ * Remove \a key (v0, v1) from \a eh, or return false if the key wasn't found.
+ *
+ * \param v0, v1: The key to remove.
+ * \param valfreefp Optional callback to free the value.
+ * \return true if \a key was removed from \a eh.
+ */
+bool BLI_edgehash_remove(EdgeHash *eh, unsigned int v0, unsigned int v1, EdgeHashFreeFP valfreefp)
+{
+ unsigned int hash;
+ EdgeEntry *e;
+
+ EDGE_ORD(v0, v1); /* ensure v0 is smaller */
+ hash = edgehash_keyhash(eh, v0, v1);
+ e = edgehash_remove_ex(eh, v0, v1, valfreefp, hash);
+ if (e) {
+ BLI_mempool_free(eh->epool, e);
+ return true;
+ }
+ else {
+ return false;
+ }
+}
+
+/* same as above but return the value,
+ * no free value argument since it will be returned */
+/**
+ * Remove \a key (v0, v1) from \a eh, returning the value or NULL if the key wasn't found.
+ *
+ * \param v0, v1: The key to remove.
+ * \return the value of \a key int \a eh or NULL.
+ */
+void *BLI_edgehash_popkey(EdgeHash *eh, unsigned int v0, unsigned int v1)
+{
+ unsigned int hash;
+ EdgeEntry *e;
+
+ EDGE_ORD(v0, v1); /* ensure v0 is smaller */
+ hash = edgehash_keyhash(eh, v0, v1);
+ e = edgehash_remove_ex(eh, v0, v1, NULL, hash);
+ IS_EDGEHASH_ASSERT(eh);
+ if (e) {
+ void *val = e->val;
+ BLI_mempool_free(eh->epool, e);
+ return val;
+ }
+ else {
+ return NULL;
+ }
+}
+
+/**
* Return boolean true/false if edge (v0,v1) in hash.
*/
bool BLI_edgehash_haskey(EdgeHash *eh, unsigned int v0, unsigned int v1)
@@ -404,6 +543,14 @@ void BLI_edgehash_clear_ex(EdgeHash *eh, EdgeHashFreeFP valfreefp,
BLI_mempool_clear_ex(eh->epool, nentries_reserve ? (int)nentries_reserve : -1);
}
+/**
+ * Wraps #BLI_edgehash_clear_ex with zero entries reserved.
+ */
+void BLI_edgehash_clear(EdgeHash *eh, EdgeHashFreeFP valfreefp)
+{
+ BLI_edgehash_clear_ex(eh, valfreefp, 0);
+}
+
void BLI_edgehash_free(EdgeHash *eh, EdgeHashFreeFP valfreefp)
{
BLI_assert((int)eh->nentries == BLI_mempool_count(eh->epool));
@@ -440,7 +587,7 @@ void BLI_edgehash_flag_clear(EdgeHash *eh, unsigned int flag)
/**
* Create a new EdgeHashIterator. The hash table must not be mutated
* while the iterator is in use, and the iterator will step exactly
- * BLI_edgehash_size(gh) times before becoming done.
+ * BLI_edgehash_size(eh) times before becoming done.
*/
EdgeHashIterator *BLI_edgehashIterator_new(EdgeHash *eh)
{
diff --git a/source/blender/blenlib/intern/endian_switch.c b/source/blender/blenlib/intern/endian_switch.c
index 892d7396011..b1dcdffba01 100644
--- a/source/blender/blenlib/intern/endian_switch.c
+++ b/source/blender/blenlib/intern/endian_switch.c
@@ -32,9 +32,8 @@ void BLI_endian_switch_int16_array(short *val, const int size)
{
if (size > 0) {
int i = size;
- val = val + (size - 1);
while (i--) {
- BLI_endian_switch_int16(val--);
+ BLI_endian_switch_int16(val++);
}
}
}
@@ -43,9 +42,8 @@ void BLI_endian_switch_uint16_array(unsigned short *val, const int size)
{
if (size > 0) {
int i = size;
- val = val + (size - 1);
while (i--) {
- BLI_endian_switch_uint16(val--);
+ BLI_endian_switch_uint16(val++);
}
}
}
@@ -54,9 +52,8 @@ void BLI_endian_switch_int32_array(int *val, const int size)
{
if (size > 0) {
int i = size;
- val = val + (size - 1);
while (i--) {
- BLI_endian_switch_int32(val--);
+ BLI_endian_switch_int32(val++);
}
}
}
@@ -65,9 +62,8 @@ void BLI_endian_switch_uint32_array(unsigned int *val, const int size)
{
if (size > 0) {
int i = size;
- val = val + (size - 1);
while (i--) {
- BLI_endian_switch_uint32(val--);
+ BLI_endian_switch_uint32(val++);
}
}
}
@@ -76,9 +72,8 @@ void BLI_endian_switch_float_array(float *val, const int size)
{
if (size > 0) {
int i = size;
- val = val + (size - 1);
while (i--) {
- BLI_endian_switch_float(val--);
+ BLI_endian_switch_float(val++);
}
}
}
@@ -87,9 +82,8 @@ void BLI_endian_switch_int64_array(int64_t *val, const int size)
{
if (size > 0) {
int i = size;
- val = val + (size - 1);
while (i--) {
- BLI_endian_switch_int64(val--);
+ BLI_endian_switch_int64(val++);
}
}
}
@@ -98,9 +92,8 @@ void BLI_endian_switch_uint64_array(uint64_t *val, const int size)
{
if (size > 0) {
int i = size;
- val = val + (size - 1);
while (i--) {
- BLI_endian_switch_uint64(val--);
+ BLI_endian_switch_uint64(val++);
}
}
}
@@ -110,9 +103,8 @@ void BLI_endian_switch_double_array(double *val, const int size)
{
if (size > 0) {
int i = size;
- val = val + (size - 1);
while (i--) {
- BLI_endian_switch_double(val--);
+ BLI_endian_switch_double(val++);
}
}
}
diff --git a/source/blender/blenlib/intern/fileops.c b/source/blender/blenlib/intern/fileops.c
index f6bbd3273f9..ef9a7c0603f 100644
--- a/source/blender/blenlib/intern/fileops.c
+++ b/source/blender/blenlib/intern/fileops.c
@@ -193,15 +193,25 @@ bool BLI_file_is_writable(const char *filename)
/**
* Creates the file with nothing in it, or updates its last-modified date if it already exists.
- * Returns true if successful. (like the unix touch command)
+ * Returns true if successful (like the unix touch command).
*/
bool BLI_file_touch(const char *file)
{
FILE *f = BLI_fopen(file, "r+b");
+
if (f != NULL) {
int c = getc(f);
- rewind(f);
- putc(c, f);
+
+ if (c == EOF) {
+ /* Empty file, reopen in truncate write mode... */
+ fclose(f);
+ f = BLI_fopen(file, "w+b");
+ }
+ else {
+ /* Otherwise, rewrite first byte. */
+ rewind(f);
+ putc(c, f);
+ }
}
else {
f = BLI_fopen(file, "wb");
@@ -220,10 +230,10 @@ static void callLocalErrorCallBack(const char *err)
printf("%s\n", err);
}
-static char str[MAXPATHLEN + 12];
-
FILE *BLI_fopen(const char *filename, const char *mode)
{
+ BLI_assert(!BLI_path_is_rel(filename));
+
return ufopen(filename, mode);
}
@@ -247,41 +257,42 @@ void *BLI_gzopen(const char *filename, const char *mode)
{
gzFile gzfile;
- if (!filename || !mode) {
- return 0;
- }
- else {
- /* xxx Creates file before transcribing the path */
- if (mode[0] == 'w')
- fclose(ufopen(filename, "a"));
+ BLI_assert(!BLI_path_is_rel(filename));
+
+ /* xxx Creates file before transcribing the path */
+ if (mode[0] == 'w')
+ fclose(ufopen(filename, "a"));
- /* temporary #if until we update all libraries to 1.2.7
- * for correct wide char path handling */
+ /* temporary #if until we update all libraries to 1.2.7
+ * for correct wide char path handling */
#if ZLIB_VERNUM >= 0x1270 && !defined(FREE_WINDOWS)
- UTF16_ENCODE(filename);
+ UTF16_ENCODE(filename);
- gzfile = gzopen_w(filename_16, mode);
+ gzfile = gzopen_w(filename_16, mode);
- UTF16_UN_ENCODE(filename);
+ UTF16_UN_ENCODE(filename);
#else
- {
- char short_name[256];
- BLI_get_short_name(short_name, filename);
- gzfile = gzopen(short_name, mode);
- }
-#endif
+ {
+ char short_name[256];
+ BLI_get_short_name(short_name, filename);
+ gzfile = gzopen(short_name, mode);
}
+#endif
return gzfile;
}
int BLI_open(const char *filename, int oflag, int pmode)
{
+ BLI_assert(!BLI_path_is_rel(filename));
+
return uopen(filename, oflag, pmode);
}
int BLI_access(const char *filename, int mode)
{
+ BLI_assert(!BLI_path_is_rel(filename));
+
return uaccess(filename, mode);
}
@@ -311,16 +322,22 @@ static bool delete_recursive(const char *dir)
bool err = false;
unsigned int nbr, i;
- i = nbr = BLI_dir_contents(dir, &filelist);
+ i = nbr = BLI_filelist_dir_contents(dir, &filelist);
fl = filelist;
while (i--) {
- char file[8];
- BLI_split_file_part(fl->path, file, sizeof(file));
- if (STREQ(file, ".") || STREQ(file, "..")) {
+ const char *file = BLI_path_basename(fl->path);
+
+ if (FILENAME_IS_CURRPAR(file)) {
/* Skip! */
}
else if (S_ISDIR(fl->type)) {
- if (delete_recursive(fl->path)) {
+ char path[FILE_MAXDIR];
+
+ /* dir listing produces dir path without trailing slash... */
+ BLI_strncpy(path, fl->path, sizeof(path));
+ BLI_add_slash(path);
+
+ if (delete_recursive(path)) {
err = true;
}
}
@@ -336,7 +353,7 @@ static bool delete_recursive(const char *dir)
err = true;
}
- BLI_free_filelist(filelist, nbr);
+ BLI_filelist_free(filelist, nbr);
return err;
}
@@ -345,6 +362,8 @@ int BLI_delete(const char *file, bool dir, bool recursive)
{
int err;
+ BLI_assert(!BLI_path_is_rel(file));
+
if (recursive) {
err = delete_recursive(file);
}
@@ -359,6 +378,7 @@ int BLI_delete(const char *file, bool dir, bool recursive)
#if 0
int BLI_move(const char *file, const char *to)
{
+ char str[MAXPATHLEN + 12];
int err;
/* windows doesn't support moving to a directory
@@ -390,6 +410,7 @@ int BLI_move(const char *file, const char *to)
int BLI_copy(const char *file, const char *to)
{
+ char str[MAXPATHLEN + 12];
int err;
/* windows doesn't support copying to a directory
@@ -418,18 +439,23 @@ int BLI_copy(const char *file, const char *to)
return err;
}
+#if 0
int BLI_create_symlink(const char *file, const char *to)
{
+ /* See patch from T30870, should this ever become needed. */
callLocalErrorCallBack("Linking files is unsupported on Windows");
(void)file;
(void)to;
return 1;
}
+#endif
-void BLI_dir_create_recursive(const char *dirname)
+/** \return true on success (i.e. given path now exists on FS), false otherwise. */
+bool BLI_dir_create_recursive(const char *dirname)
{
char *lslash;
char tmp[MAXPATHLEN];
+ bool ret = true;
/* First remove possible slash at the end of the dirname.
* This routine otherwise tries to create
@@ -437,30 +463,37 @@ void BLI_dir_create_recursive(const char *dirname)
* blah1/blah2 (without slash) */
BLI_strncpy(tmp, dirname, sizeof(tmp));
- lslash = (char *)BLI_last_slash(tmp);
-
- if (lslash && (*(lslash + 1) == '\0')) {
- *lslash = '\0';
- }
+ BLI_del_slash(tmp);
/* check special case "c:\foo", don't try create "c:", harmless but prints an error below */
- if (isalpha(tmp[0]) && (tmp[1] == ':') && tmp[2] == '\0') return;
+ if (isalpha(tmp[0]) && (tmp[1] == ':') && tmp[2] == '\0') {
+ return true;
+ }
- if (BLI_exists(tmp)) return;
+ if (BLI_is_dir(tmp)) {
+ return true;
+ }
+ else if (BLI_exists(tmp)) {
+ return false;
+ }
lslash = (char *)BLI_last_slash(tmp);
if (lslash) {
/* Split about the last slash and recurse */
*lslash = 0;
- BLI_dir_create_recursive(tmp);
+ if (!BLI_dir_create_recursive(tmp)) {
+ ret = false;
+ }
}
- if (dirname[0]) { /* patch, this recursive loop tries to create a nameless directory */
+ if (ret && dirname[0]) { /* patch, this recursive loop tries to create a nameless directory */
if (umkdir(dirname) == -1) {
printf("Unable to create directory %s\n", dirname);
+ ret = false;
}
}
+ return ret;
}
int BLI_rename(const char *from, const char *to)
@@ -537,7 +570,7 @@ static int recursive_operation(const char *startfrom, const char *startto,
char *from_path = NULL, *to_path = NULL;
struct dirent **dirlist = NULL;
size_t from_alloc_len = -1, to_alloc_len = -1;
- int i, n, ret = 0;
+ int i, n = 0, ret = 0;
do { /* once */
/* ensure there's no trailing slash in file path */
@@ -584,7 +617,7 @@ static int recursive_operation(const char *startfrom, const char *startto,
for (i = 0; i < n; i++) {
const struct dirent * const dirent = dirlist[i];
- if (!strcmp(dirent->d_name, ".") || !strcmp(dirent->d_name, ".."))
+ if (FILENAME_IS_CURRPAR(dirent->d_name))
continue;
join_dirfile_alloc(&from_path, &from_alloc_len, from, dirent->d_name);
@@ -657,21 +690,29 @@ static int delete_single_file(const char *from, const char *UNUSED(to))
FILE *BLI_fopen(const char *filename, const char *mode)
{
+ BLI_assert(!BLI_path_is_rel(filename));
+
return fopen(filename, mode);
}
void *BLI_gzopen(const char *filename, const char *mode)
{
+ BLI_assert(!BLI_path_is_rel(filename));
+
return gzopen(filename, mode);
}
int BLI_open(const char *filename, int oflag, int pmode)
{
+ BLI_assert(!BLI_path_is_rel(filename));
+
return open(filename, oflag, pmode);
}
int BLI_access(const char *filename, int mode)
{
+ BLI_assert(!BLI_path_is_rel(filename));
+
return access(filename, mode);
}
@@ -682,6 +723,8 @@ int BLI_access(const char *filename, int mode)
*/
int BLI_delete(const char *file, bool dir, bool recursive)
{
+ BLI_assert(!BLI_path_is_rel(file));
+
if (recursive) {
return recursive_operation(file, NULL, NULL, delete_single_file, delete_callback_post);
}
@@ -896,7 +939,7 @@ int BLI_move(const char *file, const char *to)
}
#endif
-static char *check_destination(const char *file, const char *to)
+static const char *check_destination(const char *file, const char *to)
{
struct stat st;
@@ -927,28 +970,31 @@ static char *check_destination(const char *file, const char *to)
}
}
- return (char *)to;
+ return to;
}
int BLI_copy(const char *file, const char *to)
{
- char *actual_to = check_destination(file, to);
+ const char *actual_to = check_destination(file, to);
int ret;
ret = recursive_operation(file, actual_to, copy_callback_pre, copy_single_file, NULL);
if (actual_to != to)
- MEM_freeN(actual_to);
+ MEM_freeN((void *)actual_to);
return ret;
}
+#if 0
int BLI_create_symlink(const char *file, const char *to)
{
return symlink(to, file);
}
+#endif
-void BLI_dir_create_recursive(const char *dirname)
+/** \return true on success (i.e. given path now exists on FS), false otherwise. */
+bool BLI_dir_create_recursive(const char *dirname)
{
char *lslash;
size_t size;
@@ -956,8 +1002,14 @@ void BLI_dir_create_recursive(const char *dirname)
char static_buf[MAXPATHLEN];
#endif
char *tmp;
+ bool ret = true;
- if (BLI_exists(dirname)) return;
+ if (BLI_is_dir(dirname)) {
+ return true;
+ }
+ else if (BLI_exists(dirname)) {
+ return false;
+ }
#ifdef MAXPATHLEN
size = MAXPATHLEN;
@@ -969,18 +1021,26 @@ void BLI_dir_create_recursive(const char *dirname)
BLI_strncpy(tmp, dirname, size);
+ /* Avoids one useless recursion in case of '/foo/bar/' path... */
+ BLI_del_slash(tmp);
+
lslash = (char *)BLI_last_slash(tmp);
if (lslash) {
/* Split about the last slash and recurse */
*lslash = 0;
- BLI_dir_create_recursive(tmp);
+ if (!BLI_dir_create_recursive(tmp)) {
+ ret = false;
+ }
}
#ifndef MAXPATHLEN
MEM_freeN(tmp);
#endif
- mkdir(dirname, 0777);
+ if (ret) {
+ ret = (mkdir(dirname, 0777) == 0);
+ }
+ return ret;
}
int BLI_rename(const char *from, const char *to)
diff --git a/source/blender/blenlib/intern/freetypefont.c b/source/blender/blenlib/intern/freetypefont.c
index b3392e28223..8719c92a2a6 100644
--- a/source/blender/blenlib/intern/freetypefont.c
+++ b/source/blender/blenlib/intern/freetypefont.c
@@ -507,8 +507,7 @@ VChar *BLI_vfontchar_from_freetypefont(VFont *vfont, unsigned long character)
/* Freetype2 Outline struct */
-typedef struct FT_Outline_
-{
+typedef struct FT_Outline_ {
short n_contours; /* number of contours in glyph */
short n_points; /* number of points in the glyph */
diff --git a/source/blender/blenlib/intern/graph.c b/source/blender/blenlib/intern/graph.c
index d4d87dfdbf6..81cc9fde01f 100644
--- a/source/blender/blenlib/intern/graph.c
+++ b/source/blender/blenlib/intern/graph.c
@@ -170,11 +170,11 @@ bool BLI_hasAdjacencyList(BGraph *graph)
for (node = graph->nodes.first; node; node = node->next) {
if (node->arcs == NULL) {
- return 0;
+ return false;
}
}
- return 1;
+ return true;
}
void BLI_replaceNodeInArc(BGraph *graph, BArc *arc, BNode *node_src, BNode *node_replaced)
@@ -337,7 +337,7 @@ static bool detectCycle(BNode *node, BArc *src_arc)
}
}
else {
- value = 1;
+ value = true;
}
return value;
@@ -354,7 +354,7 @@ bool BLI_isGraphCyclic(BGraph *graph)
BLI_flagNodes(graph, 0);
/* detectCycles in subgraphs */
- for (node = graph->nodes.first; node && value == 0; node = node->next) {
+ for (node = graph->nodes.first; node && value == false; node = node->next) {
/* only for nodes in subgraphs that haven't been visited yet */
if (node->flag == 0) {
value = value || detectCycle(node, NULL);
diff --git a/source/blender/blenlib/intern/gsqueue.c b/source/blender/blenlib/intern/gsqueue.c
index 94d18ce3c77..25da7701924 100644
--- a/source/blender/blenlib/intern/gsqueue.c
+++ b/source/blender/blenlib/intern/gsqueue.c
@@ -32,7 +32,7 @@
* (a queue for fixed length generally small) structures.
*
* \note Only use this if you need (first-in-first-out),
- * otherwise #BLI_stack is more efficient (first-in-last-out).
+ * otherwise #BLI_Stack is more efficient (first-in-last-out).
*/
#include <string.h>
@@ -96,8 +96,8 @@ int BLI_gsqueue_size(GSQueue *gq)
* Access the item at the head of the queue
* without removing it.
*
- * \param item_r A pointer to an appropriately
- * sized structure (the size passed to BLI_gsqueue_new)
+ * \param r_item: A pointer to an appropriately
+ * sized structure (the size passed to #BLI_gsqueue_new)
*/
void BLI_gsqueue_peek(GSQueue *gq, void *r_item)
{
@@ -108,8 +108,8 @@ void BLI_gsqueue_peek(GSQueue *gq, void *r_item)
* Access the item at the head of the queue
* and remove it.
*
- * \param item_r A pointer to an appropriately
- * sized structure (the size passed to BLI_gsqueue_new).
+ * \param r_item: A pointer to an appropriately
+ * sized structure (the size passed to #BLI_gsqueue_new).
* Can be NULL if desired.
*/
void BLI_gsqueue_pop(GSQueue *gq, void *r_item)
diff --git a/source/blender/blenlib/intern/md5.c b/source/blender/blenlib/intern/hash_md5.c
index 3d1a9cdb7a4..d98b915983c 100644
--- a/source/blender/blenlib/intern/md5.c
+++ b/source/blender/blenlib/intern/hash_md5.c
@@ -22,20 +22,20 @@
* Written by Ulrich Drepper <drepper@gnu.ai.mit.edu>.
*/
-/** \file blender/blenlib/intern/md5.c
+/** \file blender/blenlib/intern/hash_md5.c
* \ingroup bli
*
* Functions to compute MD5 message digest of files or memory blocks
* according to the definition of MD5 in RFC 1321 from April 1992.
*/
-#include "BLI_md5.h" /* own include */
-
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <sys/types.h>
+#include "BLI_hash_md5.h" /* own include */
+
#if defined HAVE_LIMITS_H || defined _LIBC
# include <limits.h>
#endif
@@ -77,11 +77,11 @@
#endif
-/* Following code is low level, upon which are built up the functions 'md5_stream' and 'md5_buffer'. */
+/* Following code is low level, upon which are built up the functions
+ * 'BLI_hash_md5_stream' and 'BLI_hash_md5_buffer'. */
/* Structure to save state of computation between the single steps. */
-struct md5_ctx
-{
+struct md5_ctx {
md5_uint32 A;
md5_uint32 B;
md5_uint32 C;
@@ -284,7 +284,7 @@ static void *md5_read_ctx(const struct md5_ctx *ctx, void *resbuf)
* The resulting message digest number will be written into the 16 bytes beginning at 'resblock'.
* \return Non-zero if an error occurred.
*/
-int md5_stream(FILE *stream, void *resblock)
+int BLI_hash_md5_stream(FILE *stream, void *resblock)
{
#define BLOCKSIZE 4096 /* Important: must be a multiple of 64. */
struct md5_ctx ctx;
@@ -356,7 +356,7 @@ int md5_stream(FILE *stream, void *resblock)
* The result is always in little endian byte order, so that a byte-wise output yields to the wanted
* ASCII representation of the message digest.
*/
-void *md5_buffer(const char *buffer, size_t len, void *resblock)
+void *BLI_hash_md5_buffer(const char *buffer, size_t len, void *resblock)
{
struct md5_ctx ctx;
char restbuf[64 + 72];
@@ -390,7 +390,7 @@ void *md5_buffer(const char *buffer, size_t len, void *resblock)
return md5_read_ctx(&ctx, resblock);
}
-char *md5_to_hexdigest(void *resblock, char r_hex_digest[33])
+char *BLI_hash_md5_to_hexdigest(void *resblock, char r_hex_digest[33])
{
static const char hex_map[17] = "0123456789abcdef";
const unsigned char *p;
diff --git a/source/blender/blenlib/intern/hash_mm2a.c b/source/blender/blenlib/intern/hash_mm2a.c
new file mode 100644
index 00000000000..af6ef4f355f
--- /dev/null
+++ b/source/blender/blenlib/intern/hash_mm2a.c
@@ -0,0 +1,145 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ *
+ * Copyright (C) 2014 Blender Foundation.
+ *
+ */
+
+/** \file blender/blenlib/intern/hash_mm2a.c
+ * \ingroup bli
+ *
+ * Functions to compute Murmur2A hash key.
+ *
+ * A very fast hash generating int32 result, with few collisions and good repartition.
+ *
+ * See also:
+ * reference implementation: https://smhasher.googlecode.com/svn-history/r130/trunk/MurmurHash2.cpp
+ * and http://programmers.stackexchange.com/questions/49550/which-hashing-algorithm-is-best-for-uniqueness-and-speed
+ *
+ * \warning Do not store that hash in files or such, it is not endian-agnostic, so you should only use it
+ * for temporary data.
+ */
+
+#include "BLI_hash_mm2a.h" /* own include */
+
+/* Helpers. */
+#define MM2A_M 0x5bd1e995
+
+#define MM2A_MIX(h, k) \
+{ \
+ (k) *= MM2A_M; \
+ (k) ^= (k) >> 24; \
+ (k) *= MM2A_M; \
+ (h) = ((h) * MM2A_M) ^ (k); \
+} (void)0
+
+#define MM2A_MIX_FINALIZE(h) \
+{ \
+ (h) ^= (h) >> 13; \
+ (h) *= MM2A_M; \
+ (h) ^= (h) >> 15; \
+} (void)0
+
+static void mm2a_mix_tail(BLI_HashMurmur2A *mm2, const unsigned char **data, size_t *len)
+{
+ while (*len && ((*len < 4) || mm2->count)) {
+ mm2->tail |= (uint32_t)(**data) << (mm2->count * 8);
+
+ mm2->count++;
+ (*len)--;
+ (*data)++;
+
+ if (mm2->count == 4) {
+ MM2A_MIX(mm2->hash, mm2->tail);
+ mm2->tail = 0;
+ mm2->count = 0;
+ }
+ }
+}
+
+void BLI_hash_mm2a_init(BLI_HashMurmur2A *mm2, uint32_t seed)
+{
+ mm2->hash = seed;
+ mm2->tail = 0;
+ mm2->count = 0;
+ mm2->size = 0;
+}
+
+void BLI_hash_mm2a_add(BLI_HashMurmur2A *mm2, const unsigned char *data, size_t len)
+{
+ mm2->size += (uint32_t)len;
+
+ mm2a_mix_tail(mm2, &data, &len);
+
+ for (; len >= 4; data += 4, len -= 4) {
+ uint32_t k = *(const uint32_t *)data;
+
+ MM2A_MIX(mm2->hash, k);
+ }
+
+ mm2a_mix_tail(mm2, &data, &len);
+}
+
+void BLI_hash_mm2a_add_int(BLI_HashMurmur2A *mm2, int data)
+{
+ BLI_hash_mm2a_add(mm2, (const unsigned char *)&data, sizeof(data));
+}
+
+uint32_t BLI_hash_mm2a_end(BLI_HashMurmur2A *mm2)
+{
+ MM2A_MIX(mm2->hash, mm2->tail);
+ MM2A_MIX(mm2->hash, mm2->size);
+
+ MM2A_MIX_FINALIZE(mm2->hash);
+
+ return mm2->hash;
+}
+
+/* Non-incremental version, quicker for small keys. */
+uint32_t BLI_hash_mm2(const unsigned char *data, size_t len, uint32_t seed)
+{
+ /* Initialize the hash to a 'random' value */
+ uint32_t h = seed ^ len;
+
+ /* Mix 4 bytes at a time into the hash */
+ for (; len >= 4; data += 4, len -= 4) {
+ uint32_t k = *(uint32_t *)data;
+
+ MM2A_MIX(h, k);
+ }
+
+ /* Handle the last few bytes of the input array */
+ switch (len) {
+ case 3:
+ h ^= data[2] << 16;
+ /* fall through */
+ case 2:
+ h ^= data[1] << 8;
+ /* fall through */
+ case 1:
+ h ^= data[0];
+ h *= MM2A_M;
+ }
+
+ /* Do a few final mixes of the hash to ensure the last few bytes are well-incorporated. */
+ MM2A_MIX_FINALIZE(h);
+
+ return h;
+}
+
diff --git a/source/blender/blenlib/intern/lasso.c b/source/blender/blenlib/intern/lasso.c
index e89f7fd795b..23704538413 100644
--- a/source/blender/blenlib/intern/lasso.c
+++ b/source/blender/blenlib/intern/lasso.c
@@ -33,7 +33,6 @@
#include "DNA_vec_types.h"
#include "BLI_math.h"
-#include "BLI_rect.h"
#include "BLI_strict_flags.h"
#include "BLI_lasso.h" /* own include */
diff --git a/source/blender/blenlib/intern/list_sort_impl.h b/source/blender/blenlib/intern/list_sort_impl.h
new file mode 100644
index 00000000000..249ed470d6e
--- /dev/null
+++ b/source/blender/blenlib/intern/list_sort_impl.h
@@ -0,0 +1,341 @@
+/*
+ * ***** 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/list_sort_impl.h
+ * \ingroup bli
+ *
+ * Common implementation of linked-list a non-recursive mergesort.
+ *
+ * Originally from Mono's eglib, adapted for portable inclusion.
+ * This file is to be directly included in C-source,
+ * with defines to control its use.
+ *
+ * This code requires a typedef named `SORT_IMPL_LINKTYPE` for the list node.
+ * It is assumed that the list type is the type of a pointer to a list
+ * node, and that the node has a field named 'next' that implements to
+ * the linked list. No additional invariant is maintained
+ * (e.g. the `prev` pointer of a doubly-linked list node is _not_ updated).
+ * Any invariant would require a post-processing pass to update `prev`.
+ *
+ * Source file including this must define:
+ * - `SORT_IMPL_LINKTYPE`:
+ * Struct type for sorting.
+ * - `SORT_IMPL_LINKTYPE_DATA`:
+ * Data pointer or leave undefined to pass the link its self.
+ * - `SORT_IMPL_FUNC`:
+ * Function name of the sort function.
+ *
+ * Optionally:
+ * - `SORT_IMPL_USE_THUNK`:
+ * Takes an argument for the sort function (like `qsort_r`).
+ */
+
+/* -------------------------------------------------------------------- */
+/* Handle External Defines */
+
+/* check we're not building directly */
+#if !defined(SORT_IMPL_LINKTYPE) || !defined(SORT_IMPL_FUNC)
+# error "This file can't be compiled directly, include in another source file"
+#endif
+
+#define list_node SORT_IMPL_LINKTYPE
+#define list_sort_do SORT_IMPL_FUNC
+
+#ifdef SORT_IMPL_LINKTYPE_DATA
+# define SORT_ARG(n) ((n)->SORT_IMPL_LINKTYPE_DATA)
+#else
+# define SORT_ARG(n) (n)
+#endif
+
+#ifdef SORT_IMPL_USE_THUNK
+# define THUNK_APPEND1(a, thunk) a, thunk
+# define THUNK_PREPEND2(thunk, a, b) thunk, a, b
+#else
+# define THUNK_APPEND1(a, thunk) a
+# define THUNK_PREPEND2(thunk, a, b) a, b
+#endif
+
+#define _CONCAT_AUX(MACRO_ARG1, MACRO_ARG2) MACRO_ARG1 ## MACRO_ARG2
+#define _CONCAT(MACRO_ARG1, MACRO_ARG2) _CONCAT_AUX(MACRO_ARG1, MACRO_ARG2)
+#define _SORT_PREFIX(id) _CONCAT(SORT_IMPL_FUNC, _##id)
+
+/* local identifiers */
+#define SortInfo _SORT_PREFIX(SortInfo)
+#define CompareFn _SORT_PREFIX(CompareFn)
+#define init_sort_info _SORT_PREFIX(init_sort_info)
+#define merge_lists _SORT_PREFIX(merge_lists)
+#define sweep_up _SORT_PREFIX(sweep_up)
+#define insert_list _SORT_PREFIX(insert_list)
+
+typedef int (* CompareFn)(
+#ifdef SORT_IMPL_USE_THUNK
+ void *thunk,
+#endif
+ const void *,
+ const void *);
+
+
+/* -------------------------------------------------------------------- */
+/* MIT license from original source */
+
+/*
+ * 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.
+ *
+ * Author:
+ * Raja R Harinath (rharinath@novell.com)
+ */
+
+/**
+ * The maximum possible depth of the merge tree
+ * - `ceiling(log2(maximum number of list nodes))`
+ * - `ceiling(log2(maximum possible memory size/size of each list node))`
+ * - number of bits in `'size_t' - floor(log2(sizeof(list_node *)))`
+ *
+ * Also, each list in #SortInfo is at least 2 nodes long:
+ * we can reduce the depth by 1.
+ */
+#define FLOOR_LOG2(x) \
+ (((x) >= 2) + ((x) >= 4) + ((x) >= 8) + ((x) >= 16) + ((x) >= 32) + ((x) >= 64) + ((x) >= 128))
+#define MAX_RANKS \
+ ((sizeof(size_t) * 8) - FLOOR_LOG2(sizeof(list_node)) - 1)
+
+struct SortInfo {
+ unsigned int min_rank, n_ranks;
+ CompareFn func;
+
+#ifdef SORT_IMPL_USE_THUNK
+ void *thunk;
+#endif
+
+ /**
+ * Invariant: `ranks[i] == NULL || length(ranks[i]) >= 2**(i+1)`.
+ *
+ * ~ 128 bytes on 32bit, ~ 512 bytes on 64bit */
+ list_node *ranks[MAX_RANKS];
+};
+
+BLI_INLINE void init_sort_info(
+ struct SortInfo *si,
+ CompareFn func
+#ifdef SORT_IMPL_USE_THUNK
+ ,
+ void *thunk
+#endif
+ )
+{
+ si->min_rank = si->n_ranks = 0;
+ si->func = func;
+ /* we don't need to initialize si->ranks,
+ * since we never lookup past si->n_ranks. */
+
+#ifdef SORT_IMPL_USE_THUNK
+ si->thunk = thunk;
+#endif
+}
+
+BLI_INLINE list_node *merge_lists(
+ list_node *first, list_node *second,
+ CompareFn func
+#ifdef SORT_IMPL_USE_THUNK
+ ,
+ void *thunk
+#endif
+ )
+{
+ /* merge the two lists */
+ list_node *list = NULL;
+ list_node **pos = &list;
+ while (first && second) {
+ if (func(THUNK_PREPEND2(thunk, SORT_ARG(first), SORT_ARG(second))) > 0) {
+ *pos = second;
+ second = second->next;
+ }
+ else {
+ *pos = first;
+ first = first->next;
+ }
+ pos = &((*pos)->next);
+ }
+ *pos = first ? first : second;
+ return list;
+}
+
+/**
+ * Pre-condition:
+ * `upto <= si->n_ranks, list == NULL || length(list) == 1`
+ */
+BLI_INLINE list_node *sweep_up(struct SortInfo *si, list_node *list, unsigned int upto)
+{
+ unsigned int i;
+ for (i = si->min_rank; i < upto; i++) {
+ list = merge_lists(si->ranks[i], list, THUNK_APPEND1(si->func, si->thunk));
+ si->ranks[i] = NULL;
+ }
+ return list;
+}
+
+/**
+ * The 'ranks' array essentially captures the recursion stack of a mergesort.
+ * The merge tree is built in a bottom-up manner. The control loop for
+ * updating the 'ranks' array is analogous to incrementing a binary integer,
+ * and the `O(n)` time for counting upto n translates to `O(n)` merges when
+ * inserting `rank-0` lists.
+ * When we plug in the sizes of the lists involved in those merges,
+ * we get the `O(n log n)` time for the sort.
+ *
+ * Inserting higher-ranked lists reduce the height of the merge tree,
+ * and also eliminate a lot of redundant comparisons when merging two lists
+ * that would've been part of the same run.
+ * Adding a `rank-i` list is analogous to incrementing a binary integer by
+ * `2**i` in one operation, thus sharing a similar speedup.
+ *
+ * When inserting higher-ranked lists, we choose to clear out the lower ranks
+ * in the interests of keeping the sort stable, but this makes analysis harder.
+ * Note that clearing the lower-ranked lists is `O(length(list))--` thus it
+ * shouldn't affect the `O(n log n)` behaviour.
+ * In other words, inserting one `rank-i` list is equivalent to inserting
+ * `2**i` `rank-0` lists, thus even if we do `i` additional merges
+ * in the clearing-out (taking at most `2**i` time) we are still fine.
+ */
+
+/**
+ * Pre-condition:
+ * `2**(rank+1) <= length(list) < 2**(rank+2)`
+ * (therefore: `length(list) >= 2`)
+ */
+BLI_INLINE void insert_list(
+ struct SortInfo *si,
+ list_node *list,
+ unsigned int rank)
+{
+ unsigned int i;
+
+ if (rank > si->n_ranks) {
+ if (UNLIKELY(rank > MAX_RANKS)) {
+ // printf("Rank '%d' should not exceed " STRINGIFY(MAX_RANKS), rank);
+ rank = MAX_RANKS;
+ }
+ list = merge_lists(sweep_up(si, NULL, si->n_ranks), list, THUNK_APPEND1(si->func, si->thunk));
+ for (i = si->n_ranks; i < rank; ++i) {
+ si->ranks[i] = NULL;
+ }
+ }
+ else {
+ if (rank) {
+ list = merge_lists(sweep_up(si, NULL, rank), list, THUNK_APPEND1(si->func, si->thunk));
+ }
+ for (i = rank; i < si->n_ranks && si->ranks[i]; ++i) {
+ list = merge_lists(si->ranks[i], list, THUNK_APPEND1(si->func, si->thunk));
+ si->ranks[i] = NULL;
+ }
+ }
+
+ /* Will _never_ happen: so we can just devolve into quadratic ;-) */
+ if (UNLIKELY(i == MAX_RANKS)) {
+ i--;
+ }
+
+ if (i >= si->n_ranks) {
+ si->n_ranks = i + 1;
+ }
+
+ si->min_rank = i;
+ si->ranks[i] = list;
+}
+
+#undef MAX_RANKS
+#undef FLOOR_LOG2
+
+/**
+ * Main sort function.
+ */
+BLI_INLINE list_node *list_sort_do(
+ list_node *list,
+ CompareFn func
+#ifdef SORT_IMPL_USE_THUNK
+ ,
+ void *thunk
+#endif
+ )
+{
+ struct SortInfo si;
+
+ init_sort_info(
+ &si,
+ func
+#ifdef SORT_IMPL_USE_THUNK
+ ,
+ thunk
+#endif
+ );
+
+ while (list && list->next) {
+ list_node *next = list->next;
+ list_node *tail = next->next;
+
+ if (func(THUNK_PREPEND2(thunk, SORT_ARG(list), SORT_ARG(next))) > 0) {
+ next->next = list;
+ next = list;
+ list = list->next;
+ }
+ next->next = NULL;
+
+ insert_list(&si, list, 0);
+
+ list = tail;
+ }
+
+ return sweep_up(&si, list, si.n_ranks);
+}
+
+#undef _CONCAT_AUX
+#undef _CONCAT
+#undef _SORT_PREFIX
+
+#undef SortInfo
+#undef CompareFn
+#undef init_sort_info
+#undef merge_lists
+#undef sweep_up
+#undef insert_list
+
+#undef list_node
+#undef list_sort_do
+
+#undef THUNK_APPEND1
+#undef THUNK_PREPEND2
+#undef SORT_ARG
diff --git a/source/blender/blenlib/intern/listbase.c b/source/blender/blenlib/intern/listbase.c
index d9cf8971246..ebee2c7941c 100644
--- a/source/blender/blenlib/intern/listbase.c
+++ b/source/blender/blenlib/intern/listbase.c
@@ -42,6 +42,8 @@
#include "BLI_listbase.h"
+#include "BLI_strict_flags.h"
+
/* implementation */
/**
@@ -130,6 +132,44 @@ bool BLI_remlink_safe(ListBase *listbase, void *vlink)
}
/**
+ * Swaps \a vlinka and \a vlinkb in the list. Assumes they are both already in the list!
+ */
+void BLI_listbase_swaplinks(ListBase *listbase, void *vlinka, void *vlinkb)
+{
+ Link *linka = vlinka;
+ Link *linkb = vlinkb;
+
+ if (!linka || !linkb)
+ return;
+
+ if (linkb->next == linka) {
+ SWAP(Link *, linka, linkb);
+ }
+
+ if (linka->next == linkb) {
+ linka->next = linkb->next;
+ linkb->prev = linka->prev;
+ linka->prev = linkb;
+ linkb->next = linka;
+ }
+ else { /* Non-contiguous items, we can safely swap. */
+ SWAP(Link *, linka->prev, linkb->prev);
+ SWAP(Link *, linka->next, linkb->next);
+ }
+
+ /* Update neighbors of linka and linkb. */
+ if (linka->prev) linka->prev->next = linka;
+ if (linka->next) linka->next->prev = linka;
+ if (linkb->prev) linkb->prev->next = linkb;
+ if (linkb->next) linkb->next->prev = linkb;
+
+ if (listbase->last == linka) listbase->last = linkb;
+ else if (listbase->last == linkb) listbase->last = linka;
+ if (listbase->first == linka) listbase->first = linkb;
+ else if (listbase->first == linkb) listbase->first = linka;
+}
+
+/**
* Removes the head from \a listbase and returns it.
*/
void *BLI_pophead(ListBase *listbase)
@@ -167,53 +207,56 @@ void BLI_freelinkN(ListBase *listbase, void *vlink)
MEM_freeN(link);
}
+/**
+ * Assigns all #Link.prev pointers from #Link.next
+ */
+static void listbase_double_from_single(Link *iter, ListBase *listbase)
+{
+ Link *prev = NULL;
+ listbase->first = iter;
+ do {
+ iter->prev = prev;
+ prev = iter;
+ } while ((iter = iter->next));
+ listbase->last = prev;
+}
+
+#define SORT_IMPL_LINKTYPE Link
+
+/* regular call */
+#define SORT_IMPL_FUNC listbase_sort_fn
+#include "list_sort_impl.h"
+#undef SORT_IMPL_FUNC
+
+/* reentrant call */
+#define SORT_IMPL_USE_THUNK
+#define SORT_IMPL_FUNC listbase_sort_fn_r
+#include "list_sort_impl.h"
+#undef SORT_IMPL_FUNC
+#undef SORT_IMPL_USE_THUNK
+
+#undef SORT_IMPL_LINKTYPE
/**
* Sorts the elements of listbase into the order defined by cmp
- * (which should return 1 iff its first arg should come after its second arg).
+ * (which should return 1 if its first arg should come after its second arg).
* This uses insertion sort, so NOT ok for large list.
*/
-void BLI_sortlist(ListBase *listbase, int (*cmp)(const void *, const void *))
+void BLI_listbase_sort(ListBase *listbase, int (*cmp)(const void *, const void *))
{
- Link *current = NULL;
- Link *previous = NULL;
- Link *next = NULL;
-
if (listbase->first != listbase->last) {
- for (previous = listbase->first, current = previous->next; current; current = next) {
- next = current->next;
- previous = current->prev;
-
- BLI_remlink(listbase, current);
-
- while (previous && cmp(previous, current) == 1) {
- previous = previous->prev;
- }
-
- BLI_insertlinkafter(listbase, previous, current);
- }
+ Link *head = listbase->first;
+ head = listbase_sort_fn(head, cmp);
+ listbase_double_from_single(head, listbase);
}
}
-void BLI_sortlist_r(ListBase *listbase, void *thunk, int (*cmp)(void *, const void *, const void *))
+void BLI_listbase_sort_r(ListBase *listbase, int (*cmp)(void *, const void *, const void *), void *thunk)
{
- Link *current = NULL;
- Link *previous = NULL;
- Link *next = NULL;
-
if (listbase->first != listbase->last) {
- for (previous = listbase->first, current = previous->next; current; current = next) {
- next = current->next;
- previous = current->prev;
-
- BLI_remlink(listbase, current);
-
- while (previous && cmp(thunk, previous, current) == 1) {
- previous = previous->prev;
- }
-
- BLI_insertlinkafter(listbase, previous, current);
- }
+ Link *head = listbase->first;
+ head = listbase_sort_fn_r(head, cmp, thunk);
+ listbase_double_from_single(head, listbase);
}
}
@@ -334,22 +377,35 @@ void BLI_freelistN(ListBase *listbase)
BLI_listbase_clear(listbase);
}
+/**
+ * Returns the number of elements in \a listbase, up until (and including count_max)
+ *
+ * \note Use to avoid redundant looping.
+ */
+int BLI_listbase_count_ex(const ListBase *listbase, const int count_max)
+{
+ Link *link;
+ int count = 0;
+
+ for (link = listbase->first; link && count != count_max; link = link->next) {
+ count++;
+ }
+
+ return count;
+}
/**
* Returns the number of elements in \a listbase.
*/
-int BLI_countlist(const ListBase *listbase)
+int BLI_listbase_count(const ListBase *listbase)
{
Link *link;
int count = 0;
-
- if (listbase) {
- link = listbase->first;
- while (link) {
- count++;
- link = link->next;
- }
+
+ for (link = listbase->first; link; link = link->next) {
+ count++;
}
+
return count;
}
@@ -423,7 +479,7 @@ void *BLI_findstring(const ListBase *listbase, const char *id, const int offset)
for (link = listbase->first; link; link = link->next) {
id_iter = ((const char *)link) + offset;
- if (id[0] == id_iter[0] && strcmp(id, id_iter) == 0) {
+ if (id[0] == id_iter[0] && STREQ(id, id_iter)) {
return link;
}
}
@@ -443,7 +499,7 @@ void *BLI_rfindstring(const ListBase *listbase, const char *id, const int offset
for (link = listbase->last; link; link = link->prev) {
id_iter = ((const char *)link) + offset;
- if (id[0] == id_iter[0] && strcmp(id, id_iter) == 0) {
+ if (id[0] == id_iter[0] && STREQ(id, id_iter)) {
return link;
}
}
@@ -464,7 +520,7 @@ void *BLI_findstring_ptr(const ListBase *listbase, const char *id, const int off
/* exact copy of BLI_findstring(), except for this line */
id_iter = *((const char **)(((const char *)link) + offset));
- if (id[0] == id_iter[0] && strcmp(id, id_iter) == 0) {
+ if (id[0] == id_iter[0] && STREQ(id, id_iter)) {
return link;
}
}
@@ -485,7 +541,7 @@ void *BLI_rfindstring_ptr(const ListBase *listbase, const char *id, const int of
/* exact copy of BLI_rfindstring(), except for this line */
id_iter = *((const char **)(((const char *)link) + offset));
- if (id[0] == id_iter[0] && strcmp(id, id_iter) == 0) {
+ if (id[0] == id_iter[0] && STREQ(id, id_iter)) {
return link;
}
}
@@ -549,7 +605,7 @@ int BLI_findstringindex(const ListBase *listbase, const char *id, const int offs
while (link) {
id_iter = ((const char *)link) + offset;
- if (id[0] == id_iter[0] && strcmp(id, id_iter) == 0)
+ if (id[0] == id_iter[0] && STREQ(id, id_iter))
return i;
i++;
link = link->next;
diff --git a/source/blender/blenlib/intern/math_base.c b/source/blender/blenlib/intern/math_base.c
index 3ff1af3513e..0a1e9e8a8a1 100644
--- a/source/blender/blenlib/intern/math_base.c
+++ b/source/blender/blenlib/intern/math_base.c
@@ -31,41 +31,20 @@
#include "BLI_strict_flags.h"
-/* WARNING: MSVC compiling hack for double_round() */
-#if (defined(WIN32) || defined(WIN64)) && !(defined(FREE_WINDOWS))
-
-/* from python 3.1 pymath.c */
-double copysign(double x, double y)
+int pow_i(int base, int exp)
{
- /* use atan2 to distinguish -0.0 from 0.0 */
- if (y > 0.0 || (y == 0.0 && atan2(y, -1.0) > 0.0)) {
- return fabs(x);
- }
- else {
- return -fabs(x);
+ int result = 1;
+ BLI_assert(exp >= 0);
+ while (exp) {
+ if (exp & 1) {
+ result *= base;
+ }
+ exp >>= 1;
+ base *= base;
}
-}
-/* from python 3.1 pymath.c */
-double round(double x)
-{
- double absx, y;
- absx = fabs(x);
- y = floor(absx);
- if (absx - y >= 0.5)
- y += 1.0;
- return copysign(y, x);
+ return result;
}
-#else /* OpenSuse 11.1 seems to need this. */
-# ifdef __GNUC__
-# pragma GCC diagnostic push
-# pragma GCC diagnostic ignored "-Wredundant-decls"
-# endif
-double round(double x);
-# ifdef __GNUC__
-# pragma GCC diagnostic pop
-# endif
-#endif
/* from python 3.1 floatobject.c
* ndigits must be between 0 and 21 */
diff --git a/source/blender/blenlib/intern/math_base_inline.c b/source/blender/blenlib/intern/math_base_inline.c
index e6217329145..f70c12bd26e 100644
--- a/source/blender/blenlib/intern/math_base_inline.c
+++ b/source/blender/blenlib/intern/math_base_inline.c
@@ -44,6 +44,24 @@
# define UNLIKELY(x) (x)
#endif
+/* powf is really slow for raising to integer powers. */
+MINLINE float pow2f(float x)
+{
+ return x * x;
+}
+MINLINE float pow3f(float x)
+{
+ return pow2f(x) * x;
+}
+MINLINE float pow4f(float x)
+{
+ return pow2f(pow2f(x));
+}
+MINLINE float pow7f(float x)
+{
+ return pow2f(pow3f(x)) * x;
+}
+
MINLINE float sqrt3f(float f)
{
if (UNLIKELY(f == 0.0f)) return 0.0f;
@@ -180,25 +198,6 @@ MINLINE int mod_i(int i, int n)
return (i % n + n) % n;
}
-MINLINE unsigned int highest_order_bit_i(unsigned int n)
-{
- n |= (n >> 1);
- n |= (n >> 2);
- n |= (n >> 4);
- n |= (n >> 8);
- n |= (n >> 16);
- return n - (n >> 1);
-}
-
-MINLINE unsigned short highest_order_bit_s(unsigned short n)
-{
- n |= (n >> 1);
- n |= (n >> 2);
- n |= (n >> 4);
- n |= (n >> 8);
- return (unsigned short)(n - (n >> 1));
-}
-
MINLINE float min_ff(float a, float b)
{
return (a < b) ? a : b;
@@ -253,10 +252,63 @@ MINLINE int max_iiii(int a, int b, int c, int d)
return max_ii(max_iii(a, b, c), d);
}
+/**
+ * Almost-equal for IEEE floats, using absolute difference method.
+ *
+ * \param max_diff the maximum absolute difference.
+ */
+MINLINE int compare_ff(float a, float b, const float max_diff)
+{
+ return fabsf(a - b) <= max_diff;
+}
+
+/**
+ * Almost-equal for IEEE floats, using their integer representation (mixing ULP and absolute difference methods).
+ *
+ * \param max_diff is the maximum absolute difference (allows to take care of the near-zero area,
+ * where relative difference methods cannot really work).
+ * \param max_ulps is the 'maximum number of floats + 1' allowed between \a a and \a b to consider them equal.
+ *
+ * \see https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/
+ */
+MINLINE int compare_ff_relative(float a, float b, const float max_diff, const int max_ulps)
+{
+ union {float f; int i;} ua, ub;
+
+#if 0 /* No BLI_assert in INLINE :/ */
+ BLI_assert(sizeof(float) == sizeof(int));
+ BLI_assert(max_ulps < (1 << 22));
+#endif
+
+ if (fabsf(a - b) <= max_diff) {
+ return 1;
+ }
+
+ ua.f = a;
+ ub.f = b;
+
+ /* Important to compare sign from integers, since (-0.0f < 0) is false
+ * (though this shall not be an issue in common cases)... */
+ return ((ua.i < 0) != (ub.i < 0)) ? 0 : (abs(ua.i - ub.i) <= max_ulps) ? 1 : 0;
+}
+
MINLINE float signf(float f)
{
return (f < 0.f) ? -1.f : 1.f;
}
+MINLINE int signum_i_ex(float a, float eps)
+{
+ if (a > eps) return 1;
+ if (a < -eps) return -1;
+ else return 0;
+}
+
+MINLINE int signum_i(float a)
+{
+ if (a > 0.0f) return 1;
+ if (a < 0.0f) return -1;
+ else return 0;
+}
#endif /* __MATH_BASE_INLINE_C__ */
diff --git a/source/blender/blenlib/intern/math_bits_inline.c b/source/blender/blenlib/intern/math_bits_inline.c
new file mode 100644
index 00000000000..82d7e2114c2
--- /dev/null
+++ b/source/blender/blenlib/intern/math_bits_inline.c
@@ -0,0 +1,92 @@
+/*
+ * ***** 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/math_bits_inline.c
+ * \ingroup bli
+ */
+
+#ifndef __MATH_BITS_INLINE_C__
+#define __MATH_BITS_INLINE_C__
+
+#include "BLI_math_bits.h"
+
+MINLINE unsigned int highest_order_bit_i(unsigned int n)
+{
+ n |= (n >> 1);
+ n |= (n >> 2);
+ n |= (n >> 4);
+ n |= (n >> 8);
+ n |= (n >> 16);
+ return n - (n >> 1);
+}
+
+MINLINE unsigned short highest_order_bit_s(unsigned short n)
+{
+ n |= (n >> 1);
+ n |= (n >> 2);
+ n |= (n >> 4);
+ n |= (n >> 8);
+ return (unsigned short)(n - (n >> 1));
+}
+
+#ifndef __GNUC__
+MINLINE int count_bits_i(unsigned int i)
+{
+ /* variable-precision SWAR algorithm. */
+ i = i - ((i >> 1) & 0x55555555);
+ i = (i & 0x33333333) + ((i >> 2) & 0x33333333);
+ return (((i + (i >> 4)) & 0x0F0F0F0F) * 0x01010101) >> 24;
+}
+#endif
+
+MINLINE int float_as_int(float f)
+{
+ union { int i; float f; } u;
+ u.f = f;
+ return u.i;
+}
+
+MINLINE unsigned int float_as_uint(float f)
+{
+ union { unsigned int i; float f; } u;
+ u.f = f;
+ return u.i;
+}
+
+MINLINE float int_as_float(int i)
+{
+ union { int i; float f; } u;
+ u.i = i;
+ return u.f;
+}
+
+MINLINE float uint_as_float(unsigned int i)
+{
+ union { unsigned int i; float f; } u;
+ u.i = i;
+ return u.f;
+}
+
+MINLINE float xor_fl(float x, int y)
+{
+ return int_as_float(float_as_int(x) ^ y);
+}
+
+#endif /* __MATH_BITS_INLINE_C__ */
diff --git a/source/blender/blenlib/intern/math_color.c b/source/blender/blenlib/intern/math_color.c
index 3ed7230b1d2..e149fdb2d26 100644
--- a/source/blender/blenlib/intern/math_color.c
+++ b/source/blender/blenlib/intern/math_color.c
@@ -429,27 +429,6 @@ void rgba_float_to_uchar(unsigned char r_col[4], const float col_f[4])
/* ********************************* color transforms ********************************* */
-void gamma_correct(float *c, float gamma)
-{
- *c = powf((*c), gamma);
-}
-
-float rec709_to_linearrgb(float c)
-{
- if (c < 0.081f)
- return (c < 0.0f) ? 0.0f : c * (1.0f / 4.5f);
- else
- return powf((c + 0.099f) * (1.0f / 1.099f), (1.0f / 0.45f));
-}
-
-float linearrgb_to_rec709(float c)
-{
- if (c < 0.018f)
- return (c < 0.0f) ? 0.0f : c * 4.5f;
- else
- return 1.099f * powf(c, 0.45f) - 0.099f;
-}
-
float srgb_to_linearrgb(float c)
{
if (c < 0.04045f)
diff --git a/source/blender/blenlib/intern/math_color_blend_inline.c b/source/blender/blenlib/intern/math_color_blend_inline.c
index 2522fe5f6c9..88be86aa1c2 100644
--- a/source/blender/blenlib/intern/math_color_blend_inline.c
+++ b/source/blender/blenlib/intern/math_color_blend_inline.c
@@ -36,7 +36,7 @@
#ifndef __MATH_COLOR_BLEND_INLINE_C__
#define __MATH_COLOR_BLEND_INLINE_C__
-/* don't add any saturation to a completly black and white image */
+/* don't add any saturation to a completely black and white image */
#define EPS_SATURATION 0.0005f
#define EPS_ALPHA 0.0005f
@@ -781,7 +781,7 @@ MINLINE void blend_color_add_alpha_float(float dst[4], const float src1[4], cons
}
}
-MINLINE void blend_color_overlay_float(float dst[3], const float src1[3], const float src2[3])
+MINLINE void blend_color_overlay_float(float dst[4], const float src1[4], const float src2[4])
{
const float fac = src2[3];
if (fac != 0.0f && fac < 1.0f) {
@@ -807,7 +807,7 @@ MINLINE void blend_color_overlay_float(float dst[3], const float src1[3], const
}
-MINLINE void blend_color_hardlight_float(float dst[4], const float src1[4], const float src2[2])
+MINLINE void blend_color_hardlight_float(float dst[4], const float src1[4], const float src2[4])
{
const float fac = src2[3];
if (fac != 0.0f && fac < 1.0f) {
@@ -832,7 +832,7 @@ MINLINE void blend_color_hardlight_float(float dst[4], const float src1[4], cons
}
}
-MINLINE void blend_color_burn_float(float dst[3], const float src1[3], const float src2[3])
+MINLINE void blend_color_burn_float(float dst[4], const float src1[4], const float src2[4])
{
const float fac = src2[3];
if (fac != 0.0f && fac < 1.0f) {
@@ -850,7 +850,7 @@ MINLINE void blend_color_burn_float(float dst[3], const float src1[3], const flo
}
}
-MINLINE void blend_color_linearburn_float(float dst[3], const float src1[3], const float src2[3])
+MINLINE void blend_color_linearburn_float(float dst[4], const float src1[4], const float src2[4])
{
const float fac = src2[3];
if (fac != 0.0f && fac < 1.0f) {
@@ -869,7 +869,7 @@ MINLINE void blend_color_linearburn_float(float dst[3], const float src1[3], con
}
-MINLINE void blend_color_dodge_float(float dst[3], const float src1[3], const float src2[3])
+MINLINE void blend_color_dodge_float(float dst[4], const float src1[4], const float src2[4])
{
const float fac = src2[3];
if (fac != 0.0f && fac < 1.0f) {
@@ -887,7 +887,7 @@ MINLINE void blend_color_dodge_float(float dst[3], const float src1[3], const fl
}
}
-MINLINE void blend_color_screen_float(float dst[3], const float src1[3], const float src2[3])
+MINLINE void blend_color_screen_float(float dst[4], const float src1[4], const float src2[4])
{
const float fac = src2[3];
if (fac != 0.0f && fac < 1.0f) {
@@ -905,7 +905,7 @@ MINLINE void blend_color_screen_float(float dst[3], const float src1[3], const f
}
}
-MINLINE void blend_color_softlight_float(float dst[3], const float src1[3], const float src2[3])
+MINLINE void blend_color_softlight_float(float dst[4], const float src1[4], const float src2[4])
{
const float fac = src2[3];
if (fac != 0.0f && fac < 1.0f) {
@@ -930,7 +930,7 @@ MINLINE void blend_color_softlight_float(float dst[3], const float src1[3], cons
}
}
-MINLINE void blend_color_pinlight_float(float dst[3], const float src1[3], const float src2[3])
+MINLINE void blend_color_pinlight_float(float dst[4], const float src1[4], const float src2[4])
{
const float fac = src2[3];
if (fac != 0.0f && fac < 1.0f) {
@@ -956,7 +956,7 @@ MINLINE void blend_color_pinlight_float(float dst[3], const float src1[3], const
}
-MINLINE void blend_color_linearlight_float(float dst[3], const float src1[3], const float src2[3])
+MINLINE void blend_color_linearlight_float(float dst[4], const float src1[4], const float src2[4])
{
const float fac = src2[3];
if (fac != 0.0f && fac < 1.0f) {
@@ -982,7 +982,7 @@ MINLINE void blend_color_linearlight_float(float dst[3], const float src1[3], co
}
-MINLINE void blend_color_vividlight_float(float dst[3], const float src1[3], const float src2[3])
+MINLINE void blend_color_vividlight_float(float dst[4], const float src1[4], const float src2[4])
{
const float fac = src2[3];
if (fac != 0.0f && fac < 1.0f) {
@@ -1013,7 +1013,7 @@ MINLINE void blend_color_vividlight_float(float dst[3], const float src1[3], con
}
}
-MINLINE void blend_color_difference_float(float dst[3], const float src1[3], const float src2[3])
+MINLINE void blend_color_difference_float(float dst[4], const float src1[4], const float src2[4])
{
const float fac = src2[3];
if (fac != 0.0f && fac < 1.0f) {
@@ -1031,7 +1031,7 @@ MINLINE void blend_color_difference_float(float dst[3], const float src1[3], con
}
-MINLINE void blend_color_exclusion_float(float dst[3], const float src1[3], const float src2[3])
+MINLINE void blend_color_exclusion_float(float dst[4], const float src1[4], const float src2[4])
{
const float fac = src2[3];
if (fac != 0.0f && fac < 1.0f) {
@@ -1050,7 +1050,7 @@ MINLINE void blend_color_exclusion_float(float dst[3], const float src1[3], cons
}
-MINLINE void blend_color_color_float(float dst[3], const float src1[3], const float src2[3])
+MINLINE void blend_color_color_float(float dst[4], const float src1[4], const float src2[4])
{
const float fac = src2[3];
if (fac != 0.0f && fac < 1.0f) {
@@ -1078,7 +1078,7 @@ MINLINE void blend_color_color_float(float dst[3], const float src1[3], const fl
}
-MINLINE void blend_color_hue_float(float dst[3], const float src1[3], const float src2[3])
+MINLINE void blend_color_hue_float(float dst[4], const float src1[4], const float src2[4])
{
const float fac = src2[3];
if (fac != 0.0f && fac < 1.0f) {
@@ -1104,7 +1104,7 @@ MINLINE void blend_color_hue_float(float dst[3], const float src1[3], const floa
}
}
-MINLINE void blend_color_saturation_float(float dst[3], const float src1[3], const float src2[3])
+MINLINE void blend_color_saturation_float(float dst[4], const float src1[4], const float src2[4])
{
const float fac = src2[3];
if (fac != 0.0f && fac < 1.0f) {
@@ -1131,7 +1131,7 @@ MINLINE void blend_color_saturation_float(float dst[3], const float src1[3], con
}
}
-MINLINE void blend_color_luminosity_float(float dst[3], const float src1[3], const float src2[3])
+MINLINE void blend_color_luminosity_float(float dst[4], const float src1[4], const float src2[4])
{
const float fac = src2[3];
if (fac != 0.0f && fac < 1.0f) {
diff --git a/source/blender/blenlib/intern/math_color_inline.c b/source/blender/blenlib/intern/math_color_inline.c
index 9233749d5df..45466226e72 100644
--- a/source/blender/blenlib/intern/math_color_inline.c
+++ b/source/blender/blenlib/intern/math_color_inline.c
@@ -31,6 +31,8 @@
#include "BLI_math_color.h"
#include "BLI_utildefines.h"
+#include "math.h"
+
#ifndef __MATH_COLOR_INLINE_C__
#define __MATH_COLOR_INLINE_C__
@@ -198,60 +200,46 @@ MINLINE void cpack_cpy_3ub(unsigned char r_col[3], const unsigned int pack)
r_col[2] = ((pack) >> 16) & 0xFF;
}
-/* TODO:
+
+/** \name RGB/Grayscale Functions
*
- * regarding #rgb_to_bw vs #rgb_to_grayscale,
- * it seems nobody knows why we have both functions which convert color to grays
- * but with different influences, this is quite stupid, and should be resolved
- * by someone who knows this stuff: see this thread
- * http://lists.blender.org/pipermail/bf-committers/2012-June/037180.html
+ * \warning
+ * These are only an approximation,
+ * in almost _all_ cases, #IMB_colormanagement_get_luminance should be used instead.
+ * however for screen-only colors which don't depend on the currently loaded profile - this is preferred.
+ * Checking theme colors for contrast, etc. Basically anything outside the render pipeline.
*
- * Only conclusion is that rgb_to_grayscale is used more for compositing.
- */
-MINLINE float rgb_to_bw(const float rgb[3])
-{
- return 0.35f * rgb[0] + 0.45f * rgb[1] + 0.2f * rgb[2];
-}
+ * \{ */
-/* non-linear luma from ITU-R BT.601-2
- * see: http://www.poynton.com/notes/colour_and_gamma/ColorFAQ.html#RTFToC11
- * note: the values used for are not exact matches to those documented above,
- * but they are from the same */
+/**
+ * ITU-R BT.709 primaries
+ * http://en.wikipedia.org/wiki/Relative_luminance
+ *
+ * Real values are:
+ * ``Y = 0.2126390059(R) + 0.7151686788(G) + 0.0721923154(B)``
+ * according to: "Derivation of Basic Television Color Equations", RP 177-1993
+ *
+ * As this sums slightly above 1.0, the document recommends to use:
+ * ``0.2126(R) + 0.7152(G) + 0.0722(B)``, as used here.
+ *
+ * The high precision values are used to calculate the rounded byte weights so they add up to 255:
+ * ``54(R) + 182(G) + 19(B)``
+ */
MINLINE float rgb_to_grayscale(const float rgb[3])
{
- return 0.3f * rgb[0] + 0.58f * rgb[1] + 0.12f * rgb[2];
+ return (0.2126f * rgb[0]) + (0.7152f * rgb[1]) + (0.0722f * rgb[2]);
}
MINLINE unsigned char rgb_to_grayscale_byte(const unsigned char rgb[3])
{
- return (unsigned char)(((76 * (unsigned short)rgb[0]) +
- (148 * (unsigned short)rgb[1]) +
- (31 * (unsigned short)rgb[2])) / 255);
+ return (unsigned char)(((54 * (unsigned short)rgb[0]) +
+ (182 * (unsigned short)rgb[1]) +
+ (19 * (unsigned short)rgb[2])) / 255);
}
-/* luma from defined by 'YCC_JFIF', see #rgb_to_ycc */
-MINLINE float rgb_to_luma(const float rgb[3])
-{
- return 0.299f * rgb[0] + 0.587f * rgb[1] + 0.114f * rgb[2];
-}
+/** \} */
-MINLINE unsigned char rgb_to_luma_byte(const unsigned char rgb[3])
-{
- return (unsigned char)(((76 * (unsigned short)rgb[0]) +
- (150 * (unsigned short)rgb[1]) +
- (29 * (unsigned short)rgb[2])) / 255);
-}
-/* gamma-corrected RGB --> CIE XYZ
- * for this function we only get the Y component
- * see: http://software.intel.com/sites/products/documentation/hpc/ipp/ippi/ippi_ch6/ch6_color_models.html
- *
- * also known as:
- * luminance rec. 709 */
-MINLINE float rgb_to_luma_y(const float rgb[3])
-{
- return 0.212671f * rgb[0] + 0.71516f * rgb[1] + 0.072169f * rgb[2];
-}
MINLINE int compare_rgb_uchar(const unsigned char col_a[3], const unsigned char col_b[3], const int limit)
{
@@ -269,6 +257,24 @@ MINLINE int compare_rgb_uchar(const unsigned char col_a[3], const unsigned char
return 0;
}
+MINLINE float dither_random_value(float s, float t)
+{
+ static float vec[2] = {12.9898f, 78.233f};
+ float value;
+
+ value = sinf(s * vec[0] + t * vec[1]) * 43758.5453f;
+ return value - floorf(value);
+}
+
+MINLINE void float_to_byte_dither_v3(unsigned char b[3], const float f[3], float dither, float s, float t)
+{
+ float dither_value = dither_random_value(s, t) * 0.005f * dither;
+
+ b[0] = FTOCHAR(dither_value + f[0]);
+ b[1] = FTOCHAR(dither_value + f[1]);
+ b[2] = FTOCHAR(dither_value + f[2]);
+}
+
/**************** Alpha Transformations *****************/
MINLINE void premul_to_straight_v4_v4(float straight[4], const float premul[4])
diff --git a/source/blender/blenlib/intern/math_geom.c b/source/blender/blenlib/intern/math_geom.c
index 4db9015d9e2..c3ae557d3d3 100644
--- a/source/blender/blenlib/intern/math_geom.c
+++ b/source/blender/blenlib/intern/math_geom.c
@@ -30,6 +30,7 @@
#include "MEM_guardedalloc.h"
#include "BLI_math.h"
+#include "BLI_math_bits.h"
#include "BLI_utildefines.h"
#include "BLI_strict_flags.h"
@@ -50,6 +51,21 @@ void cent_quad_v3(float cent[3], const float v1[3], const float v2[3], const flo
cent[2] = 0.25f * (v1[2] + v2[2] + v3[2] + v4[2]);
}
+void cross_tri_v3(float n[3], const float v1[3], const float v2[3], const float v3[3])
+{
+ float n1[3], n2[3];
+
+ n1[0] = v1[0] - v2[0];
+ n2[0] = v2[0] - v3[0];
+ n1[1] = v1[1] - v2[1];
+ n2[1] = v2[1] - v3[1];
+ n1[2] = v1[2] - v2[2];
+ n2[2] = v2[2] - v3[2];
+ n[0] = n1[1] * n2[2] - n1[2] * n2[1];
+ n[1] = n1[2] * n2[0] - n1[0] * n2[2];
+ n[2] = n1[0] * n2[1] - n1[1] * n2[0];
+}
+
float normal_tri_v3(float n[3], const float v1[3], const float v2[3], const float v3[3])
{
float n1[3], n2[3];
@@ -94,58 +110,44 @@ float normal_quad_v3(float n[3], const float v1[3], const float v2[3], const flo
*/
float normal_poly_v3(float n[3], const float verts[][3], unsigned int nr)
{
- const float *v_prev = verts[nr - 1];
- const float *v_curr = verts[0];
- unsigned int i;
-
- zero_v3(n);
-
- /* Newell's Method */
- for (i = 0; i < nr; v_prev = v_curr, v_curr = verts[++i]) {
- add_newell_cross_v3_v3v3(n, v_prev, v_curr);
- }
-
+ cross_poly_v3(n, verts, nr);
return normalize_v3(n);
}
-/* only convex Quadrilaterals */
float area_quad_v3(const float v1[3], const float v2[3], const float v3[3], const float v4[3])
{
- float len, vec1[3], vec2[3], n[3];
-
- sub_v3_v3v3(vec1, v2, v1);
- sub_v3_v3v3(vec2, v4, v1);
- cross_v3_v3v3(n, vec1, vec2);
- len = len_v3(n);
-
- sub_v3_v3v3(vec1, v4, v3);
- sub_v3_v3v3(vec2, v2, v3);
- cross_v3_v3v3(n, vec1, vec2);
- len += len_v3(n);
+ const float verts[4][3] = {{UNPACK3(v1)}, {UNPACK3(v2)}, {UNPACK3(v3)}, {UNPACK3(v4)}};
+ return area_poly_v3(verts, 4);
+}
- return (len / 2.0f);
+float area_squared_quad_v3(const float v1[3], const float v2[3], const float v3[3], const float v4[3])
+{
+ const float verts[4][3] = {{UNPACK3(v1)}, {UNPACK3(v2)}, {UNPACK3(v3)}, {UNPACK3(v4)}};
+ return area_squared_poly_v3(verts, 4);
}
/* Triangles */
float area_tri_v3(const float v1[3], const float v2[3], const float v3[3])
{
- float vec1[3], vec2[3], n[3];
-
- sub_v3_v3v3(vec1, v3, v2);
- sub_v3_v3v3(vec2, v1, v2);
- cross_v3_v3v3(n, vec1, vec2);
+ float n[3];
+ cross_tri_v3(n, v1, v2, v3);
+ return len_v3(n) * 0.5f;
+}
- return len_v3(n) / 2.0f;
+float area_squared_tri_v3(const float v1[3], const float v2[3], const float v3[3])
+{
+ float n[3];
+ cross_tri_v3(n, v1, v2, v3);
+ mul_v3_fl(n, 0.5f);
+ return len_squared_v3(n);
}
float area_tri_signed_v3(const float v1[3], const float v2[3], const float v3[3], const float normal[3])
{
- float area, vec1[3], vec2[3], n[3];
+ float area, n[3];
- sub_v3_v3v3(vec1, v3, v2);
- sub_v3_v3v3(vec2, v1, v2);
- cross_v3_v3v3(n, vec1, vec2);
- area = len_v3(n) / 2.0f;
+ cross_tri_v3(n, v1, v2, v3);
+ area = len_v3(n) * 0.5f;
/* negate area for flipped triangles */
if (dot_v3v3(n, normal) < 0.0f)
@@ -157,9 +159,25 @@ float area_tri_signed_v3(const float v1[3], const float v2[3], const float v3[3]
float area_poly_v3(const float verts[][3], unsigned int nr)
{
float n[3];
- return normal_poly_v3(n, verts, nr) * 0.5f;
+ cross_poly_v3(n, verts, nr);
+ return len_v3(n) * 0.5f;
}
+float area_squared_poly_v3(const float verts[][3], unsigned int nr)
+{
+ float n[3];
+
+ cross_poly_v3(n, verts, nr);
+ mul_v3_fl(n, 0.5f);
+ return len_squared_v3(n);
+}
+
+/**
+ * Scalar cross product of a 2d polygon.
+ *
+ * - equivalent to ``area * 2``
+ * - useful for checking polygon winding (a positive value is clockwise).
+ */
float cross_poly_v2(const float verts[][2], unsigned int nr)
{
unsigned int a;
@@ -179,11 +197,36 @@ float cross_poly_v2(const float verts[][2], unsigned int nr)
return cross;
}
+void cross_poly_v3(float n[3], const float verts[][3], unsigned int nr)
+{
+ const float *v_prev = verts[nr - 1];
+ const float *v_curr = verts[0];
+ unsigned int i;
+
+ zero_v3(n);
+
+ /* Newell's Method */
+ for (i = 0; i < nr; v_prev = v_curr, v_curr = verts[++i]) {
+ add_newell_cross_v3_v3v3(n, v_prev, v_curr);
+ }
+}
+
float area_poly_v2(const float verts[][2], unsigned int nr)
{
return fabsf(0.5f * cross_poly_v2(verts, nr));
}
+float area_poly_signed_v2(const float verts[][2], unsigned int nr)
+{
+ return (0.5f * cross_poly_v2(verts, nr));
+}
+
+float area_squared_poly_v2(const float verts[][2], unsigned int nr)
+{
+ float area = area_poly_signed_v2(verts, nr);
+ return area * area;
+}
+
float cotangent_tri_weight_v3(const float v1[3], const float v2[3], const float v3[3])
{
float a[3], b[3], c[3], c_len;
@@ -215,14 +258,22 @@ void plane_from_point_normal_v3(float r_plane[4], const float plane_co[3], const
}
/**
- * Get a point and a normal from a plane.
+ * Get a point and a direction from a plane.
*/
-void plane_to_point_normal_v3(const float plane[4], float r_plane_co[3], float r_plane_no[3])
+void plane_to_point_vector_v3(const float plane[4], float r_plane_co[3], float r_plane_no[3])
{
- const float length = normalize_v3_v3(r_plane_no, plane);
- madd_v3_v3v3fl(r_plane_co, r_plane_no, r_plane_no, (-plane[3] / length) - 1.0f);
+ mul_v3_v3fl(r_plane_co, plane, (-plane[3] / len_squared_v3(plane)));
+ copy_v3_v3(r_plane_no, plane);
}
+/**
+ * version of #plane_to_point_vector_v3 that gets a unit length vector.
+ */
+void plane_to_point_vector_v3_normalized(const float plane[4], float r_plane_co[3], float r_plane_no[3])
+{
+ const float length = normalize_v3_v3(r_plane_no, plane);
+ mul_v3_v3fl(r_plane_co, r_plane_no, (-plane[3] / length));
+}
/********************************* Volume **********************************/
@@ -257,72 +308,25 @@ float volume_tetrahedron_signed_v3(const float v1[3], const float v2[3], const f
* using Hesse formula, NO LINE PIECE! */
float dist_squared_to_line_v2(const float p[2], const float l1[2], const float l2[2])
{
- float a[2], deler;
-
- a[0] = l1[1] - l2[1];
- a[1] = l2[0] - l1[0];
+ float closest[2];
- deler = len_squared_v2(a);
+ closest_to_line_v2(closest, p, l1, l2);
- if (deler != 0.0f) {
- float f = ((p[0] - l1[0]) * a[0] +
- (p[1] - l1[1]) * a[1]);
- return (f * f) / deler;
- }
- else {
- return 0.0f;
- }
+ return len_squared_v2v2(closest, p);
}
float dist_to_line_v2(const float p[2], const float l1[2], const float l2[2])
{
- float a[2], deler;
-
- a[0] = l1[1] - l2[1];
- a[1] = l2[0] - l1[0];
-
- deler = len_squared_v2(a);
-
- if (deler != 0.0f) {
- float f = ((p[0] - l1[0]) * a[0] +
- (p[1] - l1[1]) * a[1]);
- return fabsf(f) / sqrtf(deler);
- }
- else {
- return 0.0f;
- }
+ return sqrtf(dist_squared_to_line_v2(p, l1, l2));
}
/* distance p to line-piece v1-v2 */
float dist_squared_to_line_segment_v2(const float p[2], const float l1[2], const float l2[2])
{
- float lambda, rc[2], pt[2], len;
-
- rc[0] = l2[0] - l1[0];
- rc[1] = l2[1] - l1[1];
- len = rc[0] * rc[0] + rc[1] * rc[1];
- if (len == 0.0f) {
- rc[0] = p[0] - l1[0];
- rc[1] = p[1] - l1[1];
- return (rc[0] * rc[0] + rc[1] * rc[1]);
- }
+ float closest[2];
- lambda = (rc[0] * (p[0] - l1[0]) + rc[1] * (p[1] - l1[1])) / len;
- if (lambda <= 0.0f) {
- pt[0] = l1[0];
- pt[1] = l1[1];
- }
- else if (lambda >= 1.0f) {
- pt[0] = l2[0];
- pt[1] = l2[1];
- }
- else {
- pt[0] = lambda * rc[0] + l1[0];
- pt[1] = lambda * rc[1] + l1[1];
- }
+ closest_to_line_segment_v2(closest, p, l1, l2);
- rc[0] = pt[0] - p[0];
- rc[1] = pt[1] - p[1];
- return (rc[0] * rc[0] + rc[1] * rc[1]);
+ return len_squared_v2v2(closest, p);
}
float dist_to_line_segment_v2(const float p[2], const float l1[2], const float l2[2])
@@ -376,6 +380,27 @@ void closest_to_plane_v3(float r_close[3], const float plane[4], const float pt[
madd_v3_v3v3fl(r_close, pt, plane, -side / len_sq);
}
+void closest_to_plane_normalized_v3(float r_close[3], const float plane[4], const float pt[3])
+{
+ const float side = plane_point_side_v3(plane, pt);
+ BLI_ASSERT_UNIT_V3(plane);
+ madd_v3_v3v3fl(r_close, pt, plane, -side);
+}
+
+void closest_to_plane3_v3(float r_close[3], const float plane[3], const float pt[3])
+{
+ const float len_sq = len_squared_v3(plane);
+ const float side = dot_v3v3(plane, pt);
+ madd_v3_v3v3fl(r_close, pt, plane, -side / len_sq);
+}
+
+void closest_to_plane3_normalized_v3(float r_close[3], const float plane[3], const float pt[3])
+{
+ const float side = dot_v3v3(plane, pt);
+ BLI_ASSERT_UNIT_V3(plane);
+ madd_v3_v3v3fl(r_close, pt, plane, -side);
+}
+
float dist_signed_squared_to_plane_v3(const float pt[3], const float plane[4])
{
const float len_sq = len_squared_v3(plane);
@@ -392,6 +417,22 @@ float dist_squared_to_plane_v3(const float pt[3], const float plane[4])
return len_sq * (fac * fac);
}
+float dist_signed_squared_to_plane3_v3(const float pt[3], const float plane[3])
+{
+ const float len_sq = len_squared_v3(plane);
+ const float side = dot_v3v3(plane, pt); /* only difference with 'plane[4]' version */
+ const float fac = side / len_sq;
+ return copysignf(len_sq * (fac * fac), side);
+}
+float dist_squared_to_plane3_v3(const float pt[3], const float plane[3])
+{
+ const float len_sq = len_squared_v3(plane);
+ const float side = dot_v3v3(plane, pt); /* only difference with 'plane[4]' version */
+ const float fac = side / len_sq;
+ /* only difference to code above - no 'copysignf' */
+ return len_sq * (fac * fac);
+}
+
/**
* Return the signed distance from the point to the plane.
*/
@@ -407,6 +448,18 @@ float dist_to_plane_v3(const float pt[3], const float plane[4])
return fabsf(dist_signed_to_plane_v3(pt, plane));
}
+float dist_signed_to_plane3_v3(const float pt[3], const float plane[3])
+{
+ const float len_sq = len_squared_v3(plane);
+ const float side = dot_v3v3(plane, pt); /* only difference with 'plane[4]' version */
+ const float fac = side / len_sq;
+ return sqrtf(len_sq) * fac;
+}
+float dist_to_plane3_v3(const float pt[3], const float plane[3])
+{
+ return fabsf(dist_signed_to_plane3_v3(pt, plane));
+}
+
/* distance v1 to line-piece l1-l2 in 3D */
float dist_squared_to_line_segment_v3(const float p[3], const float l1[3], const float l2[3])
{
@@ -422,17 +475,93 @@ float dist_to_line_segment_v3(const float p[3], const float l1[3], const float l
return sqrtf(dist_squared_to_line_segment_v3(p, l1, l2));
}
-float dist_squared_to_line_v3(const float v1[3], const float l1[3], const float l2[3])
+float dist_squared_to_line_v3(const float p[3], const float l1[3], const float l2[3])
{
float closest[3];
- closest_to_line_v3(closest, v1, l1, l2);
+ closest_to_line_v3(closest, p, l1, l2);
- return len_squared_v3v3(closest, v1);
+ return len_squared_v3v3(closest, p);
}
-float dist_to_line_v3(const float v1[3], const float l1[3], const float l2[3])
+float dist_to_line_v3(const float p[3], const float l1[3], const float l2[3])
{
- return sqrtf(dist_squared_to_line_v3(v1, l1, l2));
+ return sqrtf(dist_squared_to_line_v3(p, l1, l2));
+}
+
+/**
+ * Check if \a p is inside the 2x planes defined by ``(v1, v2, v3)``
+ * where the 3x points define 2x planes.
+ *
+ * \param axis_ref used when v1,v2,v3 form a line and to check if the corner is concave/convex.
+ *
+ * \note the distance from \a v1 & \a v3 to \a v2 doesnt matter
+ * (it just defines the planes).
+ *
+ * \return the lowest squared distance to eithe of the planes.
+ * where ``(return < 0.0)`` is outside.
+ *
+ * <pre>
+ * v1
+ * +
+ * /
+ * x - out / x - inside
+ * /
+ * +----+
+ * v2 v3
+ * x - also outside
+ * </pre>
+ */
+float dist_signed_squared_to_corner_v3v3v3(
+ const float p[3],
+ const float v1[3], const float v2[3], const float v3[3],
+ const float axis_ref[3])
+{
+ float dir_a[3], dir_b[3];
+ float plane_a[3], plane_b[3];
+ float dist_a, dist_b;
+ float axis[3];
+ float s_p_v2[3];
+ bool flip = false;
+
+ sub_v3_v3v3(dir_a, v1, v2);
+ sub_v3_v3v3(dir_b, v3, v2);
+
+ cross_v3_v3v3(axis, dir_a, dir_b);
+
+ if ((len_squared_v3(axis) < FLT_EPSILON)) {
+ copy_v3_v3(axis, axis_ref);
+ }
+ else if (dot_v3v3(axis, axis_ref) < 0.0f) {
+ /* concave */
+ flip = true;
+ negate_v3(axis);
+ }
+
+ cross_v3_v3v3(plane_a, dir_a, axis);
+ cross_v3_v3v3(plane_b, axis, dir_b);
+
+#if 0
+ plane_from_point_normal_v3(plane_a, v2, plane_a);
+ plane_from_point_normal_v3(plane_b, v2, plane_b);
+
+ dist_a = dist_signed_squared_to_plane_v3(p, plane_a);
+ dist_b = dist_signed_squared_to_plane_v3(p, plane_b);
+#else
+ /* calculate without the planes 4th component to avoid float precision issues */
+ sub_v3_v3v3(s_p_v2, p, v2);
+
+ dist_a = dist_signed_squared_to_plane3_v3(s_p_v2, plane_a);
+ dist_b = dist_signed_squared_to_plane3_v3(s_p_v2, plane_b);
+#endif
+
+
+
+ if (flip) {
+ return min_ff(dist_a, dist_b);
+ }
+ else {
+ return max_ff(dist_a, dist_b);
+ }
}
/* Adapted from "Real-Time Collision Detection" by Christer Ericson,
@@ -539,19 +668,28 @@ int isect_line_line_v2_int(const int v1[2], const int v2[2], const int v3[2], co
}
/* intersect Line-Line, floats - gives intersection point */
-int isect_line_line_v2_point(const float v1[2], const float v2[2], const float v3[2], const float v4[2], float vi[2])
+int isect_line_line_v2_point(const float v0[2], const float v1[2], const float v2[2], const float v3[2], float r_vi[2])
{
+ float s10[2], s32[2];
float div;
- div = (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;
+ sub_v2_v2v2(s10, v1, v0);
+ sub_v2_v2v2(s32, v3, v2);
- vi[0] = ((v3[0] - v4[0]) * (v1[0] * v2[1] - v1[1] * v2[0]) - (v1[0] - v2[0]) * (v3[0] * v4[1] - v3[1] * v4[0])) / div;
- vi[1] = ((v3[1] - v4[1]) * (v1[0] * v2[1] - v1[1] * v2[0]) - (v1[1] - v2[1]) * (v3[0] * v4[1] - v3[1] * v4[0])) / div;
+ div = cross_v2v2(s10, s32);
+ if (div != 0.0f) {
+ const float u = cross_v2v2(v1, v0);
+ const float v = cross_v2v2(v3, v2);
- return ISECT_LINE_LINE_CROSS;
-}
+ r_vi[0] = ((s32[0] * u) - (s10[0] * v)) / div;
+ r_vi[1] = ((s32[1] * u) - (s10[1] * v)) / div;
+ return ISECT_LINE_LINE_CROSS;
+ }
+ else {
+ return ISECT_LINE_LINE_COLINEAR;
+ }
+}
/* intersect Line-Line, floats */
int isect_line_line_v2(const float v1[2], const float v2[2], const float v3[2], const float v4[2])
@@ -576,37 +714,73 @@ int isect_line_line_v2(const float v1[2], const float v2[2], const float v3[2],
* -1: collinear
* 1: intersection
*/
-int isect_seg_seg_v2_point(const float v1[2], const float v2[2], const float v3[2], const float v4[2], float vi[2])
+int isect_seg_seg_v2_point(const float v0[2], const float v1[2], const float v2[2], const float v3[2], float r_vi[2])
{
- float a1, a2, b1, b2, c1, c2, d;
- float u, v;
+ float s10[2], s32[2], s30[2], d;
const float eps = 1e-6f;
const float eps_sq = eps * eps;
- a1 = v2[0] - v1[0];
- b1 = v4[0] - v3[0];
- c1 = v1[0] - v4[0];
+ sub_v2_v2v2(s10, v1, v0);
+ sub_v2_v2v2(s32, v3, v2);
+ sub_v2_v2v2(s30, v3, v0);
- a2 = v2[1] - v1[1];
- b2 = v4[1] - v3[1];
- c2 = v1[1] - v4[1];
+ d = cross_v2v2(s10, s32);
- d = a1 * b2 - a2 * b1;
+ if (d != 0) {
+ float u, v;
- if (d == 0) {
- if (a1 * c2 - a2 * c1 == 0.0f && b1 * c2 - b2 * c1 == 0.0f) { /* equal lines */
- float a[2], b[2], c[2];
- float u2;
+ u = cross_v2v2(s30, s32) / d;
+ v = cross_v2v2(s10, s30) / d;
- if (equals_v2v2(v1, v2)) {
- if (len_squared_v2v2(v3, v4) > eps_sq) {
+ if ((u >= -eps && u <= 1.0f + eps) &&
+ (v >= -eps && v <= 1.0f + eps))
+ {
+ /* intersection */
+ float vi_test[2];
+ float s_vi_v2[2];
+
+ madd_v2_v2v2fl(vi_test, v0, s10, u);
+
+ /* When 'd' approaches zero, float precision lets non-overlapping co-linear segments
+ * detect as an intersection. So re-calculate 'v' to ensure the point overlaps both.
+ * see T45123 */
+
+ /* inline since we have most vars already */
+#if 0
+ v = line_point_factor_v2(ix_test, v2, v3);
+#else
+ sub_v2_v2v2(s_vi_v2, vi_test, v2);
+ v = (dot_v2v2(s32, s_vi_v2) / dot_v2v2(s32, s32));
+#endif
+ if (v >= -eps && v <= 1.0f + eps) {
+ copy_v2_v2(r_vi, vi_test);
+ return 1;
+ }
+ }
+
+ /* out of segment intersection */
+ return -1;
+ }
+ else {
+ if ((cross_v2v2(s10, s30) == 0.0f) &&
+ (cross_v2v2(s32, s30) == 0.0f))
+ {
+ /* equal lines */
+ float s20[2];
+ float u_a, u_b;
+
+ if (equals_v2v2(v0, v1)) {
+ if (len_squared_v2v2(v2, v3) > eps_sq) {
/* use non-point segment as basis */
+ SWAP(const float *, v0, v2);
SWAP(const float *, v1, v3);
- SWAP(const float *, v2, v4);
+
+ sub_v2_v2v2(s10, v1, v0);
+ sub_v2_v2v2(s30, v3, v0);
}
else { /* both of segments are points */
- if (equals_v2v2(v1, v3)) { /* points are equal */
- copy_v2_v2(vi, v1);
+ if (equals_v2v2(v0, v2)) { /* points are equal */
+ copy_v2_v2(r_vi, v0);
return 1;
}
@@ -615,19 +789,21 @@ int isect_seg_seg_v2_point(const float v1[2], const float v2[2], const float v3[
}
}
- sub_v2_v2v2(a, v3, v1);
- sub_v2_v2v2(b, v2, v1);
- sub_v2_v2v2(c, v2, v1);
- u = dot_v2v2(a, b) / dot_v2v2(c, c);
+ sub_v2_v2v2(s20, v2, v0);
- sub_v2_v2v2(a, v4, v1);
- u2 = dot_v2v2(a, b) / dot_v2v2(c, c);
+ u_a = dot_v2v2(s20, s10) / dot_v2v2(s10, s10);
+ u_b = dot_v2v2(s30, s10) / dot_v2v2(s10, s10);
- if (u > u2) SWAP(float, u, u2);
+ if (u_a > u_b)
+ SWAP(float, u_a, u_b);
- if (u > 1.0f + eps || u2 < -eps) return -1; /* non-ovlerlapping segments */
- else if (max_ff(0.0f, u) == min_ff(1.0f, u2)) { /* one common point: can return result */
- interp_v2_v2v2(vi, v1, v2, max_ff(0, u));
+ if (u_a > 1.0f + eps || u_b < -eps) {
+ /* non-overlapping segments */
+ return -1;
+ }
+ else if (max_ff(0.0f, u_a) == min_ff(1.0f, u_b)) {
+ /* one common point: can return result */
+ madd_v2_v2v2fl(r_vi, v0, s10, max_ff(0, u_a));
return 1;
}
}
@@ -635,22 +811,13 @@ int isect_seg_seg_v2_point(const float v1[2], const float v2[2], const float v3[
/* lines are collinear */
return -1;
}
-
- u = (c2 * b1 - b2 * c1) / d;
- v = (c1 * a2 - a1 * c2) / d;
-
- if (u >= -eps && u <= 1.0f + eps && v >= -eps && v <= 1.0f + eps) { /* intersection */
- interp_v2_v2v2(vi, v1, v2, u);
- return 1;
- }
-
- /* out of segment intersection */
- return -1;
}
bool isect_seg_seg_v2(const float v1[2], const float v2[2], const float v3[2], const float v4[2])
{
-#define CCW(A, B, C) ((C[1] - A[1]) * (B[0] - A[0]) > (B[1]-A[1]) * (C[0]-A[0]))
+#define CCW(A, B, C) \
+ ((C[1] - A[1]) * (B[0] - A[0]) > \
+ (B[1] - A[1]) * (C[0] - A[0]))
return CCW(v1, v3, v4) != CCW(v2, v3, v4) && CCW(v1, v2, v3) != CCW(v1, v2, v4);
@@ -906,12 +1073,12 @@ bool isect_point_tri_v2_cw(const float pt[2], const float v1[2], const float v2[
if (line_point_side_v2(v1, v2, pt) >= 0.0f) {
if (line_point_side_v2(v2, v3, pt) >= 0.0f) {
if (line_point_side_v2(v3, v1, pt) >= 0.0f) {
- return 1;
+ return true;
}
}
}
- return 0;
+ return false;
}
int isect_point_tri_v2(const float pt[2], const float v1[2], const float v2[2], const float v3[2])
@@ -963,9 +1130,10 @@ int isect_point_quad_v2(const float pt[2], const float v1[2], const float v2[2],
* test if the line starting at p1 ending at p2 intersects the triangle v0..v2
* return non zero if it does
*/
-bool isect_line_tri_v3(const float p1[3], const float p2[3],
- const float v0[3], const float v1[3], const float v2[3],
- float *r_lambda, float r_uv[2])
+bool isect_line_tri_v3(
+ const float p1[3], const float p2[3],
+ const float v0[3], const float v1[3], const float v2[3],
+ float *r_lambda, float r_uv[2])
{
float p[3], s[3], d[3], e1[3], e2[3], q[3];
@@ -977,34 +1145,35 @@ bool isect_line_tri_v3(const float p1[3], const float p2[3],
cross_v3_v3v3(p, d, e2);
a = dot_v3v3(e1, p);
- if (a == 0.0f) return 0;
+ if (a == 0.0f) return false;
f = 1.0f / a;
sub_v3_v3v3(s, p1, v0);
u = f * dot_v3v3(s, p);
- if ((u < 0.0f) || (u > 1.0f)) return 0;
+ if ((u < 0.0f) || (u > 1.0f)) return false;
cross_v3_v3v3(q, s, e1);
v = f * dot_v3v3(d, q);
- if ((v < 0.0f) || ((u + v) > 1.0f)) return 0;
+ if ((v < 0.0f) || ((u + v) > 1.0f)) return false;
*r_lambda = f * dot_v3v3(e2, q);
- if ((*r_lambda < 0.0f) || (*r_lambda > 1.0f)) return 0;
+ if ((*r_lambda < 0.0f) || (*r_lambda > 1.0f)) return false;
if (r_uv) {
r_uv[0] = u;
r_uv[1] = v;
}
- return 1;
+ return true;
}
/* like isect_line_tri_v3, but allows epsilon tolerance around triangle */
-bool isect_line_tri_epsilon_v3(const float p1[3], const float p2[3],
- const float v0[3], const float v1[3], const float v2[3],
- float *r_lambda, float r_uv[2], const float epsilon)
+bool isect_line_tri_epsilon_v3(
+ const float p1[3], const float p2[3],
+ const float v0[3], const float v1[3], const float v2[3],
+ float *r_lambda, float r_uv[2], const float epsilon)
{
float p[3], s[3], d[3], e1[3], e2[3], q[3];
@@ -1016,38 +1185,42 @@ bool isect_line_tri_epsilon_v3(const float p1[3], const float p2[3],
cross_v3_v3v3(p, d, e2);
a = dot_v3v3(e1, p);
- if (a == 0.0f) return 0;
+ if (a == 0.0f) return false;
f = 1.0f / a;
sub_v3_v3v3(s, p1, v0);
u = f * dot_v3v3(s, p);
- if ((u < -epsilon) || (u > 1.0f + epsilon)) return 0;
+ if ((u < -epsilon) || (u > 1.0f + epsilon)) return false;
cross_v3_v3v3(q, s, e1);
v = f * dot_v3v3(d, q);
- if ((v < -epsilon) || ((u + v) > 1.0f + epsilon)) return 0;
+ if ((v < -epsilon) || ((u + v) > 1.0f + epsilon)) return false;
*r_lambda = f * dot_v3v3(e2, q);
- if ((*r_lambda < 0.0f) || (*r_lambda > 1.0f)) return 0;
+ if ((*r_lambda < 0.0f) || (*r_lambda > 1.0f)) return false;
if (r_uv) {
r_uv[0] = u;
r_uv[1] = v;
}
- return 1;
+ return true;
}
/* moved from effect.c
* test if the ray starting at p1 going in d direction intersects the triangle v0..v2
* return non zero if it does
*/
-bool isect_ray_tri_v3(const float p1[3], const float d[3],
- const float v0[3], const float v1[3], const float v2[3],
- float *r_lambda, float r_uv[2])
+bool isect_ray_tri_v3(
+ const float p1[3], const float d[3],
+ const float v0[3], const float v1[3], const float v2[3],
+ float *r_lambda, float r_uv[2])
{
+ /* note: these values were 0.000001 in 2.4x but for projection snapping on
+ * a human head (1BU == 1m), subsurf level 2, this gave many errors - campbell */
+ const float epsilon = 0.00000001f;
float p[3], s[3], e1[3], e2[3], q[3];
float a, f, u, v;
@@ -1056,40 +1229,40 @@ bool isect_ray_tri_v3(const float p1[3], const float d[3],
cross_v3_v3v3(p, d, e2);
a = dot_v3v3(e1, p);
- /* note: these values were 0.000001 in 2.4x but for projection snapping on
- * a human head (1BU == 1m), subsurf level 2, this gave many errors - campbell */
- if ((a > -0.00000001f) && (a < 0.00000001f)) return 0;
+ if ((a > -epsilon) && (a < epsilon)) return false;
f = 1.0f / a;
sub_v3_v3v3(s, p1, v0);
u = f * dot_v3v3(s, p);
- if ((u < 0.0f) || (u > 1.0f)) return 0;
+ if ((u < 0.0f) || (u > 1.0f)) return false;
cross_v3_v3v3(q, s, e1);
v = f * dot_v3v3(d, q);
- if ((v < 0.0f) || ((u + v) > 1.0f)) return 0;
+ if ((v < 0.0f) || ((u + v) > 1.0f)) return false;
*r_lambda = f * dot_v3v3(e2, q);
- if ((*r_lambda < 0.0f)) return 0;
+ if ((*r_lambda < 0.0f)) return false;
if (r_uv) {
r_uv[0] = u;
r_uv[1] = v;
}
- return 1;
+ return true;
}
/**
* if clip is nonzero, will only return true if lambda is >= 0.0
* (i.e. intersection point is along positive d)
*/
-bool isect_ray_plane_v3(const float p1[3], const float d[3],
- const float v0[3], const float v1[3], const float v2[3],
- float *r_lambda, const int clip)
+bool isect_ray_plane_v3(
+ const float p1[3], const float d[3],
+ const float v0[3], const float v1[3], const float v2[3],
+ float *r_lambda, const bool clip)
{
+ const float epsilon = 0.00000001f;
float p[3], s[3], e1[3], e2[3], q[3];
float a, f;
/* float u, v; */ /*UNUSED*/
@@ -1101,7 +1274,7 @@ bool isect_ray_plane_v3(const float p1[3], const float d[3],
a = dot_v3v3(e1, p);
/* note: these values were 0.000001 in 2.4x but for projection snapping on
* a human head (1BU == 1m), subsurf level 2, this gave many errors - campbell */
- if ((a > -0.00000001f) && (a < 0.00000001f)) return 0;
+ if ((a > -epsilon) && (a < epsilon)) return false;
f = 1.0f / a;
sub_v3_v3v3(s, p1, v0);
@@ -1113,14 +1286,15 @@ bool isect_ray_plane_v3(const float p1[3], const float d[3],
/* v = f * dot_v3v3(d, q); */ /*UNUSED*/
*r_lambda = f * dot_v3v3(e2, q);
- if (clip && (*r_lambda < 0.0f)) return 0;
+ if (clip && (*r_lambda < 0.0f)) return false;
- return 1;
+ return true;
}
-bool isect_ray_tri_epsilon_v3(const float p1[3], const float d[3],
- const float v0[3], const float v1[3], const float v2[3],
- float *r_lambda, float uv[2], const float epsilon)
+bool isect_ray_tri_epsilon_v3(
+ const float p1[3], const float d[3],
+ const float v0[3], const float v1[3], const float v2[3],
+ float *r_lambda, float uv[2], const float epsilon)
{
float p[3], s[3], e1[3], e2[3], q[3];
float a, f, u, v;
@@ -1130,34 +1304,156 @@ bool isect_ray_tri_epsilon_v3(const float p1[3], const float d[3],
cross_v3_v3v3(p, d, e2);
a = dot_v3v3(e1, p);
- if (a == 0.0f) return 0;
+ if (a == 0.0f) return false;
f = 1.0f / a;
sub_v3_v3v3(s, p1, v0);
u = f * dot_v3v3(s, p);
- if ((u < -epsilon) || (u > 1.0f + epsilon)) return 0;
+ if ((u < -epsilon) || (u > 1.0f + epsilon)) return false;
cross_v3_v3v3(q, s, e1);
v = f * dot_v3v3(d, q);
- if ((v < -epsilon) || ((u + v) > 1.0f + epsilon)) return 0;
+ if ((v < -epsilon) || ((u + v) > 1.0f + epsilon)) return false;
*r_lambda = f * dot_v3v3(e2, q);
- if ((*r_lambda < 0.0f)) return 0;
+ if ((*r_lambda < 0.0f)) return false;
if (uv) {
uv[0] = u;
uv[1] = v;
}
- return 1;
+ return true;
+}
+
+void isect_ray_tri_watertight_v3_precalc(struct IsectRayPrecalc *isect_precalc, const float dir[3])
+{
+ float inv_dir_z;
+
+ /* Calculate dimension where the ray direction is maximal. */
+ int kz = axis_dominant_v3_single(dir);
+ int kx = (kz != 2) ? (kz + 1) : 0;
+ int ky = (kx != 2) ? (kx + 1) : 0;
+
+ /* Swap kx and ky dimensions to preserve winding direction of triangles. */
+ if (dir[kz] < 0.0f) {
+ SWAP(int, kx, ky);
+ }
+
+ /* Calculate the shear constants. */
+ inv_dir_z = 1.0f / dir[kz];
+ isect_precalc->sx = dir[kx] * inv_dir_z;
+ isect_precalc->sy = dir[ky] * inv_dir_z;
+ isect_precalc->sz = inv_dir_z;
+
+ /* Store the dimensions. */
+ isect_precalc->kx = kx;
+ isect_precalc->ky = ky;
+ isect_precalc->kz = kz;
+}
+
+bool isect_ray_tri_watertight_v3(
+ const float p[3], const struct IsectRayPrecalc *isect_precalc,
+ const float v0[3], const float v1[3], const float v2[3],
+ float *r_lambda, float r_uv[2])
+{
+ const int kx = isect_precalc->kx;
+ const int ky = isect_precalc->ky;
+ const int kz = isect_precalc->kz;
+ const float sx = isect_precalc->sx;
+ const float sy = isect_precalc->sy;
+ const float sz = isect_precalc->sz;
+
+ /* Calculate vertices relative to ray origin. */
+ const float a[3] = {v0[0] - p[0], v0[1] - p[1], v0[2] - p[2]};
+ const float b[3] = {v1[0] - p[0], v1[1] - p[1], v1[2] - p[2]};
+ const float c[3] = {v2[0] - p[0], v2[1] - p[1], v2[2] - p[2]};
+
+ const float a_kx = a[kx], a_ky = a[ky], a_kz = a[kz];
+ const float b_kx = b[kx], b_ky = b[ky], b_kz = b[kz];
+ const float c_kx = c[kx], c_ky = c[ky], c_kz = c[kz];
+
+ /* Perform shear and scale of vertices. */
+ const float ax = a_kx - sx * a_kz;
+ const float ay = a_ky - sy * a_kz;
+ const float bx = b_kx - sx * b_kz;
+ const float by = b_ky - sy * b_kz;
+ const float cx = c_kx - sx * c_kz;
+ const float cy = c_ky - sy * c_kz;
+
+ /* Calculate scaled barycentric coordinates. */
+ float u = cx * by - cy * bx;
+ int sign_mask = (float_as_int(u) & (int)0x80000000);
+ float v = ax * cy - ay * cx;
+ float w, det;
+
+ if (sign_mask != (float_as_int(v) & (int)0x80000000)) {
+ return false;
+ }
+ w = bx * ay - by * ax;
+ if (sign_mask != (float_as_int(w) & (int)0x80000000)) {
+ return false;
+ }
+
+ /* Calculate determinant. */
+ det = u + v + w;
+ if (UNLIKELY(det == 0.0f)) {
+ return false;
+ }
+ else {
+ /* Calculate scaled z-coordinates of vertices and use them to calculate
+ * the hit distance.
+ */
+ const float t = (u * a_kz + v * b_kz + w * c_kz) * sz;
+ const float sign_t = xor_fl(t, sign_mask);
+ if ((sign_t < 0.0f)
+ /* differ from Cycles, don't read r_lambda's original value
+ * otherwise we won't match any of the other intersect functions here...
+ * which would be confusing */
+#if 0
+ ||
+ (sign_T > *r_lambda * xor_signmask(det, sign_mask))
+#endif
+ )
+ {
+ return false;
+ }
+ else {
+ /* Normalize u, v and t. */
+ const float inv_det = 1.0f / det;
+ if (r_uv) {
+ r_uv[0] = u * inv_det;
+ r_uv[1] = v * inv_det;
+ }
+ *r_lambda = t * inv_det;
+ return true;
+ }
+ }
}
-bool isect_ray_tri_threshold_v3(const float p1[3], const float d[3],
- const float v0[3], const float v1[3], const float v2[3],
- float *r_lambda, float r_uv[2], const float threshold)
+bool isect_ray_tri_watertight_v3_simple(
+ const float P[3], const float dir[3],
+ const float v0[3], const float v1[3], const float v2[3],
+ float *r_lambda, float r_uv[2])
{
+ struct IsectRayPrecalc isect_precalc;
+ isect_ray_tri_watertight_v3_precalc(&isect_precalc, dir);
+ return isect_ray_tri_watertight_v3(P, &isect_precalc, v0, v1, v2, r_lambda, r_uv);
+}
+
+#if 0 /* UNUSED */
+/**
+ * A version of #isect_ray_tri_v3 which takes a threshold argument
+ * so rays slightly outside the triangle to be considered as intersecting.
+ */
+bool isect_ray_tri_threshold_v3(
+ const float p1[3], const float d[3],
+ const float v0[3], const float v1[3], const float v2[3],
+ float *r_lambda, float r_uv[2], const float threshold)
+{
+ const float epsilon = 0.00000001f;
float p[3], s[3], e1[3], e2[3], q[3];
float a, f, u, v;
float du, dv;
@@ -1167,14 +1463,14 @@ bool isect_ray_tri_threshold_v3(const float p1[3], const float d[3],
cross_v3_v3v3(p, d, e2);
a = dot_v3v3(e1, p);
- if ((a > -0.000001f) && (a < 0.000001f)) return 0;
+ if ((a > -epsilon) && (a < epsilon)) return false;
f = 1.0f / a;
sub_v3_v3v3(s, p1, v0);
cross_v3_v3v3(q, s, e1);
*r_lambda = f * dot_v3v3(e2, q);
- if ((*r_lambda < 0.0f)) return 0;
+ if ((*r_lambda < 0.0f)) return false;
u = f * dot_v3v3(s, p);
v = f * dot_v3v3(d, q);
@@ -1198,7 +1494,7 @@ bool isect_ray_tri_threshold_v3(const float p1[3], const float d[3],
mul_v3_fl(e2, dv);
if (len_squared_v3(e1) + len_squared_v3(e2) > threshold * threshold) {
- return 0;
+ return false;
}
if (r_uv) {
@@ -1206,8 +1502,9 @@ bool isect_ray_tri_threshold_v3(const float p1[3], const float d[3],
r_uv[1] = v;
}
- return 1;
+ return true;
}
+#endif
/**
* Check if a point is behind all planes.
@@ -1259,30 +1556,191 @@ bool isect_line_plane_v3(float out[3],
}
/**
+ * Intersect three planes, return the point where all 3 meet.
+ * See Graphics Gems 1 pg 305
+ *
+ * \param plane_a, plane_b, plane_c: Planes.
+ * \param r_isect_co: The resulting intersection point.
+ */
+bool isect_plane_plane_plane_v3(
+ const float plane_a[4], const float plane_b[4], const float plane_c[4],
+ float r_isect_co[3])
+{
+ float det;
+
+ det = determinant_m3(UNPACK3(plane_a), UNPACK3(plane_b), UNPACK3(plane_c));
+
+ if (det != 0.0f) {
+ float tmp[3];
+
+ /* (plane_b.xyz.cross(plane_c.xyz) * -plane_a[3] +
+ * plane_c.xyz.cross(plane_a.xyz) * -plane_b[3] +
+ * plane_a.xyz.cross(plane_b.xyz) * -plane_c[3]) / det; */
+
+ cross_v3_v3v3(tmp, plane_c, plane_b);
+ mul_v3_v3fl(r_isect_co, tmp, plane_a[3]);
+
+ cross_v3_v3v3(tmp, plane_a, plane_c);
+ madd_v3_v3fl(r_isect_co, tmp, plane_b[3]);
+
+ cross_v3_v3v3(tmp, plane_b, plane_a);
+ madd_v3_v3fl(r_isect_co, tmp, plane_c[3]);
+
+ mul_v3_fl(r_isect_co, 1.0f / det);
+
+ return true;
+ }
+ else {
+ return false;
+ }
+}
+
+/**
* Intersect two planes, return a point on the intersection and a vector
* that runs on the direction of the intersection.
- * Return error code is the same as 'isect_line_line_v3'.
*
- * \param r_isect_co The resulting intersection point.
- * \param r_isect_no The resulting vector of the intersection.
- * \param plane_a_co The point on the first plane.
- * \param plane_a_no The normal of the first plane.
- * \param plane_b_co The point on the second plane.
- * \param plane_b_no The normal of the second plane.
*
- * \note return normal isn't unit length
+ * \note this is a slightly reduced version of #isect_plane_plane_plane_v3
+ *
+ * \param plane_a, plane_b: Planes.
+ * \param r_isect_co: The resulting intersection point.
+ * \param r_isect_no: The resulting vector of the intersection.
+ *
+ * \note \a r_isect_no isn't unit length.
*/
-bool isect_plane_plane_v3(float r_isect_co[3], float r_isect_no[3],
- const float plane_a_co[3], const float plane_a_no[3],
- const float plane_b_co[3], const float plane_b_no[3])
+bool isect_plane_plane_v3(
+ const float plane_a[4], const float plane_b[4],
+ float r_isect_co[3], float r_isect_no[3])
{
- float plane_a_co_other[3];
- cross_v3_v3v3(r_isect_no, plane_a_no, plane_b_no); /* direction is simply the cross product */
- cross_v3_v3v3(plane_a_co_other, plane_a_no, r_isect_no);
- add_v3_v3(plane_a_co_other, plane_a_co);
- return isect_line_plane_v3(r_isect_co, plane_a_co, plane_a_co_other, plane_b_co, plane_b_no);
+ float det, plane_c[3];
+
+ /* direction is simply the cross product */
+ cross_v3_v3v3(plane_c, plane_a, plane_b);
+
+ /* in this case we don't need to use 'determinant_m3' */
+ det = len_squared_v3(plane_c);
+
+ if (det != 0.0f) {
+ float tmp[3];
+
+ /* (plane_b.xyz.cross(plane_c.xyz) * -plane_a[3] +
+ * plane_c.xyz.cross(plane_a.xyz) * -plane_b[3]) / det; */
+ cross_v3_v3v3(tmp, plane_c, plane_b);
+ mul_v3_v3fl(r_isect_co, tmp, plane_a[3]);
+
+ cross_v3_v3v3(tmp, plane_a, plane_c);
+ madd_v3_v3fl(r_isect_co, tmp, plane_b[3]);
+
+ mul_v3_fl(r_isect_co, 1.0f / det);
+
+ copy_v3_v3(r_isect_no, plane_c);
+
+ return true;
+ }
+ else {
+ return false;
+ }
}
+/**
+ * Intersect two triangles.
+ *
+ * \param r_i1, r_i2: Optional arguments to retrieve the overlapping edge between the 2 triangles.
+ * \return true when the triangles intersect.
+ *
+ * \note intersections between coplanar triangles are currently undetected.
+ */
+bool isect_tri_tri_epsilon_v3(
+ const float t_a0[3], const float t_a1[3], const float t_a2[3],
+ const float t_b0[3], const float t_b1[3], const float t_b2[3],
+ float r_i1[3], float r_i2[3],
+ const float epsilon)
+{
+ const float *tri_pair[2][3] = {{t_a0, t_a1, t_a2}, {t_b0, t_b1, t_b2}};
+ float plane_a[4], plane_b[4];
+ float plane_co[3], plane_no[3];
+
+ BLI_assert((r_i1 != NULL) == (r_i2 != NULL));
+
+ /* normalizing is needed for small triangles T46007 */
+ normal_tri_v3(plane_a, UNPACK3(tri_pair[0]));
+ normal_tri_v3(plane_b, UNPACK3(tri_pair[1]));
+
+ plane_a[3] = -dot_v3v3(plane_a, t_a0);
+ plane_b[3] = -dot_v3v3(plane_b, t_b0);
+
+ if (isect_plane_plane_v3(plane_a, plane_b, plane_co, plane_no) &&
+ (normalize_v3(plane_no) > epsilon))
+ {
+ /**
+ * Implementation note: its simpler to project the triangles onto the intersection plane
+ * before intersecting their edges with the ray, defined by 'isect_plane_plane_v3'.
+ * This way we can use 'line_point_factor_v3_ex' to see if an edge crosses 'co_proj',
+ * then use the factor to calculate the world-space point.
+ */
+ struct {
+ float min, max;
+ } range[2] = {{FLT_MAX, -FLT_MAX}, {FLT_MAX, -FLT_MAX}};
+ int t;
+ float co_proj[3];
+
+ closest_to_plane3_normalized_v3(co_proj, plane_no, plane_co);
+
+ /* For both triangles, find the overlap with the line defined by the ray [co_proj, plane_no].
+ * When the ranges overlap we know the triangles do too. */
+ for (t = 0; t < 2; t++) {
+ int j, j_prev;
+ float tri_proj[3][3];
+
+ closest_to_plane3_normalized_v3(tri_proj[0], plane_no, tri_pair[t][0]);
+ closest_to_plane3_normalized_v3(tri_proj[1], plane_no, tri_pair[t][1]);
+ closest_to_plane3_normalized_v3(tri_proj[2], plane_no, tri_pair[t][2]);
+
+ for (j = 0, j_prev = 2; j < 3; j_prev = j++) {
+ /* note that its important to have a very small nonzero epsilon here
+ * otherwise this fails for very small faces.
+ * However if its too small, large adjacent faces will count as intersecting */
+ const float edge_fac = line_point_factor_v3_ex(co_proj, tri_proj[j_prev], tri_proj[j], 1e-10f, -1.0f);
+ /* ignore collinear lines, they are either an edge shared between 2 tri's
+ * (which runs along [co_proj, plane_no], but can be safely ignored).
+ *
+ * or a collinear edge placed away from the ray - which we don't intersect with & can ignore. */
+ if (UNLIKELY(edge_fac == -1.0f)) {
+ /* pass */
+ }
+ else if (edge_fac > 0.0f && edge_fac < 1.0f) {
+ float ix_tri[3];
+ float span_fac;
+
+ interp_v3_v3v3(ix_tri, tri_pair[t][j_prev], tri_pair[t][j], edge_fac);
+ /* the actual distance, since 'plane_no' is normalized */
+ span_fac = dot_v3v3(plane_no, ix_tri);
+
+ range[t].min = min_ff(range[t].min, span_fac);
+ range[t].max = max_ff(range[t].max, span_fac);
+ }
+ }
+
+ if (range[t].min == FLT_MAX) {
+ return false;
+ }
+ }
+
+ if (((range[0].min > range[1].max) ||
+ (range[0].max < range[1].min)) == 0)
+ {
+ if (r_i1 && r_i2) {
+ project_plane_v3_v3v3(plane_co, plane_co, plane_no);
+ madd_v3_v3v3fl(r_i1, plane_co, plane_no, max_ff(range[0].min, range[1].min));
+ madd_v3_v3v3fl(r_i2, plane_co, plane_no, min_ff(range[0].max, range[1].max));
+ }
+
+ return true;
+ }
+ }
+
+ return false;
+}
/* Adapted from the paper by Kasper Fauerby */
@@ -1357,7 +1815,7 @@ bool isect_sweeping_sphere_tri_v3(const float p1[3], const float p2[3], const fl
if (t0 > t1)
SWAP(float, t0, t1);
- if (t0 > 1.0f || t1 < 0.0f) return 0;
+ if (t0 > 1.0f || t1 < 0.0f) return false;
/* clamp to [0, 1] */
CLAMP(t0, 0.0f, 1.0f);
@@ -1512,6 +1970,7 @@ bool isect_sweeping_sphere_tri_v3(const float p1[3], const float p2[3], const fl
bool isect_axial_line_tri_v3(const int axis, const float p1[3], const float p2[3],
const float v0[3], const float v1[3], const float v2[3], float *r_lambda)
{
+ const float epsilon = 0.000001f;
float p[3], e1[3], e2[3];
float u, v, f;
int a0 = axis, a1 = (axis + 1) % 3, a2 = (axis + 2) % 3;
@@ -1533,21 +1992,21 @@ bool isect_axial_line_tri_v3(const int axis, const float p1[3], const float p2[3
sub_v3_v3v3(p, v0, p1);
f = (e2[a1] * e1[a2] - e2[a2] * e1[a1]);
- if ((f > -0.000001f) && (f < 0.000001f)) return false;
+ if ((f > -epsilon) && (f < epsilon)) return false;
v = (p[a2] * e1[a1] - p[a1] * e1[a2]) / f;
- if ((v < 0.0f) || (v > 1.0f)) return 0;
+ if ((v < 0.0f) || (v > 1.0f)) return false;
f = e1[a1];
- if ((f > -0.000001f) && (f < 0.000001f)) {
+ if ((f > -epsilon) && (f < epsilon)) {
f = e1[a2];
- if ((f > -0.000001f) && (f < 0.000001f)) return false;
+ if ((f > -epsilon) && (f < epsilon)) return false;
u = (-p[a2] - v * e2[a2]) / f;
}
else
u = (-p[a1] - v * e2[a1]) / f;
- if ((u < 0.0f) || ((u + v) > 1.0f)) return 0;
+ if ((u < 0.0f) || ((u + v) > 1.0f)) return false;
*r_lambda = (p[a0] + u * e1[a0] + v * e2[a0]) / (p2[a0] - p1[a0]);
@@ -1558,7 +2017,7 @@ bool isect_axial_line_tri_v3(const int axis, const float p1[3], const float p2[3
/**
* \return The number of point of interests
- * 0 - lines are colinear
+ * 0 - lines are collinear
* 1 - lines are coplanar, i1 is set to intersection
* 2 - i1 and i2 are the nearest points on line 1 (v1, v2) and line 2 (v3, v4) respectively
*/
@@ -1567,25 +2026,18 @@ int isect_line_line_epsilon_v3(
const float v3[3], const float v4[3], float i1[3], float i2[3],
const float epsilon)
{
- float a[3], b[3], c[3], ab[3], cb[3], dir1[3], dir2[3];
+ float a[3], b[3], c[3], ab[3], cb[3];
float d, div;
sub_v3_v3v3(c, v3, v1);
sub_v3_v3v3(a, v2, v1);
sub_v3_v3v3(b, v4, v3);
- normalize_v3_v3(dir1, a);
- normalize_v3_v3(dir2, b);
- d = dot_v3v3(dir1, dir2);
- if (d == 1.0f || d == -1.0f) {
- /* colinear */
- return 0;
- }
-
cross_v3_v3v3(ab, a, b);
d = dot_v3v3(c, ab);
div = dot_v3v3(ab, ab);
+ /* important not to use an epsilon here, see: T45919 */
/* test zero length line */
if (UNLIKELY(div == 0.0f)) {
return 0;
@@ -1646,31 +2098,28 @@ bool isect_line_line_strict_v3(const float v1[3], const float v2[3],
const float v3[3], const float v4[3],
float vi[3], float *r_lambda)
{
- float a[3], b[3], c[3], ab[3], cb[3], ca[3], dir1[3], dir2[3];
+ const float epsilon = 0.000001f;
+ float a[3], b[3], c[3], ab[3], cb[3], ca[3];
float d, div;
sub_v3_v3v3(c, v3, v1);
sub_v3_v3v3(a, v2, v1);
sub_v3_v3v3(b, v4, v3);
- normalize_v3_v3(dir1, a);
- normalize_v3_v3(dir2, b);
- d = dot_v3v3(dir1, dir2);
- if (d == 1.0f || d == -1.0f || d == 0) {
- /* colinear or one vector is zero-length*/
- return false;
- }
-
cross_v3_v3v3(ab, a, b);
d = dot_v3v3(c, ab);
div = dot_v3v3(ab, ab);
+ /* important not to use an epsilon here, see: T45919 */
/* test zero length line */
if (UNLIKELY(div == 0.0f)) {
return false;
}
/* test if the two lines are coplanar */
- else if (d > -0.000001f && d < 0.000001f) {
+ else if (UNLIKELY(fabsf(d) < epsilon)) {
+ return false;
+ }
+ else {
float f1, f2;
cross_v3_v3v3(cb, c, b);
cross_v3_v3v3(ca, c, a);
@@ -1692,9 +2141,6 @@ bool isect_line_line_strict_v3(const float v1[3], const float v2[3],
return false;
}
}
- else {
- return false;
- }
}
bool isect_aabb_aabb_v3(const float min1[3], const float max1[3], const float min2[3], const float max2[3])
@@ -1750,8 +2196,8 @@ bool isect_ray_aabb(const IsectRayAABBData *data, const float bb_min[3],
if (tzmin > tmin)
tmin = tzmin;
- /* XXX jwilkins: tmax does not need to be updated since we don't use it
- * keeping this here for future reference */
+ /* Note: tmax does not need to be updated since we don't use it
+ * keeping this here for future reference - jwilkins */
//if (tzmax < tmax) tmax = tzmax;
if (tmin_out)
@@ -1786,8 +2232,16 @@ float closest_to_line_v2(float cp[2], const float p[2], const float l1[2], const
return lambda;
}
-/* little sister we only need to know lambda */
-float line_point_factor_v3(const float p[3], const float l1[3], const float l2[3])
+/**
+ * A simplified version of #closest_to_line_v3
+ * we only need to return the ``lambda``
+ *
+ * \param epsilon: avoid approaching divide-by-zero.
+ * Passing a zero will just check for nonzero division.
+ */
+float line_point_factor_v3_ex(
+ const float p[3], const float l1[3], const float l2[3],
+ const float epsilon, const float fallback)
{
float h[3], u[3];
float dot;
@@ -1798,11 +2252,18 @@ float line_point_factor_v3(const float p[3], const float l1[3], const float l2[3
#else
/* better check for zero */
dot = dot_v3v3(u, u);
- return (dot != 0.0f) ? (dot_v3v3(u, h) / dot) : 0.0f;
+ return (fabsf(dot) > epsilon) ? (dot_v3v3(u, h) / dot) : fallback;
#endif
}
+float line_point_factor_v3(
+ const float p[3], const float l1[3], const float l2[3])
+{
+ return line_point_factor_v3_ex(p, l1, l2, 0.0f, 0.0f);
+}
-float line_point_factor_v2(const float p[2], const float l1[2], const float l2[2])
+float line_point_factor_v2_ex(
+ const float p[2], const float l1[2], const float l2[2],
+ const float epsilon, const float fallback)
{
float h[2], u[2];
float dot;
@@ -1813,10 +2274,15 @@ float line_point_factor_v2(const float p[2], const float l1[2], const float l2[2
#else
/* better check for zero */
dot = dot_v2v2(u, u);
- return (dot != 0.0f) ? (dot_v2v2(u, h) / dot) : 0.0f;
+ return (fabsf(dot) > epsilon) ? (dot_v2v2(u, h) / dot) : fallback;
#endif
}
+float line_point_factor_v2(const float p[2], const float l1[2], const float l2[2])
+{
+ return line_point_factor_v2_ex(p, l1, l2, 0.0f, 0.0f);
+}
+
/**
* \note #isect_line_plane_v3() shares logic
*/
@@ -1831,7 +2297,7 @@ float line_plane_factor_v3(const float plane_co[3], const float plane_no[3],
return (dot != 0.0f) ? -dot_v3v3(plane_no, h) / dot : 0.0f;
}
-/** Ensure the distance between these points is no greater then 'dist'.
+/** Ensure the distance between these points is no greater than 'dist'.
* If it is, scale then both into the center.
*/
void limit_dist_v3(float v1[3], float v2[3], const float dist)
@@ -2213,7 +2679,26 @@ void axis_dominant_v3_to_m3(float r_mat[3][3], const float normal[3])
transpose_m3(r_mat);
BLI_assert(!is_negative_m3(r_mat));
- BLI_assert(fabsf(dot_m3_v3_row_z(r_mat, normal) - 1.0f) < BLI_ASSERT_UNIT_EPSILON);
+ BLI_assert((fabsf(dot_m3_v3_row_z(r_mat, normal) - 1.0f) < BLI_ASSERT_UNIT_EPSILON) || is_zero_v3(normal));
+}
+
+/**
+ * Same as axis_dominant_v3_to_m3, but flips the normal
+ */
+void axis_dominant_v3_to_m3_negate(float r_mat[3][3], const float normal[3])
+{
+ BLI_ASSERT_UNIT_V3(normal);
+
+ negate_v3_v3(r_mat[2], normal);
+ ortho_basis_v3v3_v3(r_mat[0], r_mat[1], r_mat[2]);
+
+ BLI_ASSERT_UNIT_V3(r_mat[0]);
+ BLI_ASSERT_UNIT_V3(r_mat[1]);
+
+ transpose_m3(r_mat);
+
+ BLI_assert(!is_negative_m3(r_mat));
+ BLI_assert((dot_m3_v3_row_z(r_mat, normal) < BLI_ASSERT_UNIT_EPSILON) || is_zero_v3(normal));
}
/****************************** Interpolation ********************************/
@@ -2341,15 +2826,15 @@ bool barycentric_coords_v2(const float v1[2], const float v2[2], const float v3[
}
/**
- * \note: using #area_tri_signed_v2 means locations outside the triangle are correctly weighted
+ * \note: using #cross_tri_v2 means locations outside the triangle are correctly weighted
*/
void barycentric_weights_v2(const float v1[2], const float v2[2], const float v3[2], const float co[2], float w[3])
{
float wtot;
- w[0] = area_tri_signed_v2(v2, v3, co);
- w[1] = area_tri_signed_v2(v3, v1, co);
- w[2] = area_tri_signed_v2(v1, v2, co);
+ w[0] = cross_tri_v2(v2, v3, co);
+ w[1] = cross_tri_v2(v3, v1, co);
+ w[2] = cross_tri_v2(v1, v2, co);
wtot = w[0] + w[1] + w[2];
if (wtot != 0.0f) {
@@ -2368,9 +2853,9 @@ void barycentric_weights_v2_persp(const float v1[4], const float v2[4], const fl
{
float wtot;
- w[0] = area_tri_signed_v2(v2, v3, co) / v1[3];
- w[1] = area_tri_signed_v2(v3, v1, co) / v2[3];
- w[2] = area_tri_signed_v2(v1, v2, co) / v3[3];
+ w[0] = cross_tri_v2(v2, v3, co) / v1[3];
+ w[1] = cross_tri_v2(v3, v1, co) / v2[3];
+ w[2] = cross_tri_v2(v1, v2, co) / v3[3];
wtot = w[0] + w[1] + w[2];
if (wtot != 0.0f) {
@@ -2593,38 +3078,55 @@ int interp_sparse_array(float *array, const int list_size, const float skipval)
return 1;
}
+/** \name interp_weights_poly_v2, v3
+ * \{ */
+
+#define IS_POINT_IX (1 << 0)
+#define IS_SEGMENT_IX (1 << 1)
+
+#define DIR_V3_SET(d_len, va, vb) { \
+ sub_v3_v3v3((d_len)->dir, va, vb); \
+ (d_len)->len = len_v3((d_len)->dir); \
+} (void)0
+
+#define DIR_V2_SET(d_len, va, vb) { \
+ sub_v2_v2v2((d_len)->dir, va, vb); \
+ (d_len)->len = len_v2((d_len)->dir); \
+} (void)0
+
+struct Float3_Len {
+ float dir[3], len;
+};
+
+struct Float2_Len {
+ float dir[2], len;
+};
+
/* Mean value weights - smooth interpolation weights for polygons with
* more than 3 vertices */
-static float mean_value_half_tan_v3(const float v1[3], const float v2[3], const float v3[3])
+static float mean_value_half_tan_v3(const struct Float3_Len *d_curr, const struct Float3_Len *d_next)
{
- float d2[3], d3[3], cross[3], area;
-
- sub_v3_v3v3(d2, v2, v1);
- sub_v3_v3v3(d3, v3, v1);
- cross_v3_v3v3(cross, d2, d3);
-
+ float cross[3], area;
+ cross_v3_v3v3(cross, d_curr->dir, d_next->dir);
area = len_v3(cross);
- if (LIKELY(area != 0.0f)) {
- const float dot = dot_v3v3(d2, d3);
- const float len = len_v3(d2) * len_v3(d3);
+ if (LIKELY(fabsf(area) > FLT_EPSILON)) {
+ const float dot = dot_v3v3(d_curr->dir, d_next->dir);
+ const float len = d_curr->len * d_next->len;
return (len - dot) / area;
}
else {
return 0.0f;
}
}
-static float mean_value_half_tan_v2(const float v1[2], const float v2[2], const float v3[2])
-{
- float d2[2], d3[2], area;
-
- sub_v2_v2v2(d2, v2, v1);
- sub_v2_v2v2(d3, v3, v1);
+static float mean_value_half_tan_v2(const struct Float2_Len *d_curr, const struct Float2_Len *d_next)
+{
+ float area;
/* different from the 3d version but still correct */
- area = cross_v2v2(d2, d3);
- if (LIKELY(area != 0.0f)) {
- const float dot = dot_v2v2(d2, d3);
- const float len = len_v2(d2) * len_v2(d3);
+ area = cross_v2v2(d_curr->dir, d_next->dir);
+ if (LIKELY(fabsf(area) > FLT_EPSILON)) {
+ const float dot = dot_v2v2(d_curr->dir, d_next->dir);
+ const float len = d_curr->len * d_next->len;
return (len - dot) / area;
}
else {
@@ -2639,62 +3141,66 @@ void interp_weights_poly_v3(float *w, float v[][3], const int n, const float co[
const float *v_curr, *v_next;
float ht_prev, ht; /* half tangents */
float totweight = 0.0f;
- int i = 0;
- bool vert_interp = false;
- bool edge_interp = false;
+ int i_curr, i_next;
+ char ix_flag = 0;
+ struct Float3_Len d_curr, d_next;
- v_curr = v[0];
- v_next = v[1];
+ /* loop over 'i_next' */
+ i_curr = n - 1;
+ i_next = 0;
- ht_prev = mean_value_half_tan_v3(co, v[n - 1], v_curr);
+ v_curr = v[i_curr];
+ v_next = v[i_next];
- while (i < n) {
- const float len_sq = len_squared_v3v3(co, v_curr);
+ DIR_V3_SET(&d_curr, v_curr - 3 /* v[n - 2] */, co);
+ DIR_V3_SET(&d_next, v_curr /* v[n - 1] */, co);
+ ht_prev = mean_value_half_tan_v3(&d_curr, &d_next);
+ while (i_next < n) {
/* Mark Mayer et al algorithm that is used here does not operate well if vertex is close
* to borders of face. In that case, do simple linear interpolation between the two edge vertices */
- if (len_sq < eps_sq) {
- vert_interp = true;
+
+ /* 'd_next.len' is infact 'd_curr.len', just avoid copy to begin with */
+ if (UNLIKELY(d_next.len < eps)) {
+ ix_flag = IS_POINT_IX;
break;
}
- else if (dist_squared_to_line_segment_v3(co, v_curr, v_next) < eps_sq) {
- edge_interp = true;
+ else if (UNLIKELY(dist_squared_to_line_segment_v3(co, v_curr, v_next) < eps_sq)) {
+ ix_flag = IS_SEGMENT_IX;
break;
}
- ht = mean_value_half_tan_v3(co, v_curr, v_next);
- w[i] = (ht_prev + ht) / sqrtf(len_sq);
- totweight += w[i];
+ d_curr = d_next;
+ DIR_V3_SET(&d_next, v_next, co);
+ ht = mean_value_half_tan_v3(&d_curr, &d_next);
+ w[i_curr] = (ht_prev + ht) / d_curr.len;
+ totweight += w[i_curr];
/* step */
- i++;
+ i_curr = i_next++;
v_curr = v_next;
- v_next = v[(i + 1) % n];
+ v_next = v[i_next];
ht_prev = ht;
}
- if (vert_interp) {
- const int i_curr = i;
- for (i = 0; i < n; i++)
- w[i] = 0.0;
- w[i_curr] = 1.0f;
- }
- else if (edge_interp) {
- const int i_curr = i;
- float len_curr = len_v3v3(co, v_curr);
- float len_next = len_v3v3(co, v_next);
- float edge_len = len_curr + len_next;
- for (i = 0; i < n; i++)
- w[i] = 0.0;
+ if (ix_flag) {
+ memset(w, 0, sizeof(*w) * (size_t)n);
- w[i_curr] = len_next / edge_len;
- w[(i_curr + 1) % n] = len_curr / edge_len;
+ if (ix_flag & IS_POINT_IX) {
+ w[i_curr] = 1.0f;
+ }
+ else {
+ float fac = line_point_factor_v3(co, v_curr, v_next);
+ CLAMP(fac, 0.0f, 1.0f);
+ w[i_curr] = 1.0f - fac;
+ w[i_next] = fac;
+ }
}
else {
if (totweight != 0.0f) {
- for (i = 0; i < n; i++) {
- w[i] /= totweight;
+ for (i_curr = 0; i_curr < n; i_curr++) {
+ w[i_curr] /= totweight;
}
}
}
@@ -2708,67 +3214,80 @@ void interp_weights_poly_v2(float *w, float v[][2], const int n, const float co[
const float *v_curr, *v_next;
float ht_prev, ht; /* half tangents */
float totweight = 0.0f;
- int i = 0;
- bool vert_interp = false;
- bool edge_interp = false;
+ int i_curr, i_next;
+ char ix_flag = 0;
+ struct Float2_Len d_curr, d_next;
- v_curr = v[0];
- v_next = v[1];
+ /* loop over 'i_next' */
+ i_curr = n - 1;
+ i_next = 0;
- ht_prev = mean_value_half_tan_v2(co, v[n - 1], v_curr);
+ v_curr = v[i_curr];
+ v_next = v[i_next];
- while (i < n) {
- const float len_sq = len_squared_v2v2(co, v_curr);
+ DIR_V2_SET(&d_curr, v_curr - 2 /* v[n - 2] */, co);
+ DIR_V2_SET(&d_next, v_curr /* v[n - 1] */, co);
+ ht_prev = mean_value_half_tan_v2(&d_curr, &d_next);
+ while (i_next < n) {
/* Mark Mayer et al algorithm that is used here does not operate well if vertex is close
* to borders of face. In that case, do simple linear interpolation between the two edge vertices */
- if (len_sq < eps_sq) {
- vert_interp = true;
+
+ /* 'd_next.len' is infact 'd_curr.len', just avoid copy to begin with */
+ if (UNLIKELY(d_next.len < eps)) {
+ ix_flag = IS_POINT_IX;
break;
}
- else if (dist_squared_to_line_segment_v2(co, v_curr, v_next) < eps_sq) {
- edge_interp = true;
+ else if (UNLIKELY(dist_squared_to_line_segment_v2(co, v_curr, v_next) < eps_sq)) {
+ ix_flag = IS_SEGMENT_IX;
break;
}
- ht = mean_value_half_tan_v2(co, v_curr, v_next);
- w[i] = (ht_prev + ht) / sqrtf(len_sq);
- totweight += w[i];
+ d_curr = d_next;
+ DIR_V2_SET(&d_next, v_next, co);
+ ht = mean_value_half_tan_v2(&d_curr, &d_next);
+ w[i_curr] = (ht_prev + ht) / d_curr.len;
+ totweight += w[i_curr];
/* step */
- i++;
+ i_curr = i_next++;
v_curr = v_next;
- v_next = v[(i + 1) % n];
+ v_next = v[i_next];
ht_prev = ht;
}
- if (vert_interp) {
- const int i_curr = i;
- for (i = 0; i < n; i++)
- w[i] = 0.0;
- w[i_curr] = 1.0f;
- }
- else if (edge_interp) {
- const int i_curr = i;
- float len_curr = len_v2v2(co, v_curr);
- float len_next = len_v2v2(co, v_next);
- float edge_len = len_curr + len_next;
- for (i = 0; i < n; i++)
- w[i] = 0.0;
+ if (ix_flag) {
+ memset(w, 0, sizeof(*w) * (size_t)n);
- w[i_curr] = len_next / edge_len;
- w[(i_curr + 1) % n] = len_curr / edge_len;
+ if (ix_flag & IS_POINT_IX) {
+ w[i_curr] = 1.0f;
+ }
+ else {
+ float fac = line_point_factor_v2(co, v_curr, v_next);
+ CLAMP(fac, 0.0f, 1.0f);
+ w[i_curr] = 1.0f - fac;
+ w[i_next] = fac;
+ }
}
else {
if (totweight != 0.0f) {
- for (i = 0; i < n; i++) {
- w[i] /= totweight;
+ for (i_curr = 0; i_curr < n; i_curr++) {
+ w[i_curr] /= totweight;
}
}
}
}
+#undef IS_POINT_IX
+#undef IS_SEGMENT_IX
+
+#undef DIR_V3_SET
+#undef DIR_V2_SET
+
+/** \} */
+
+
/* (x1, v1)(t1=0)------(x2, v2)(t2=1), 0<t<1 --> (x, v)(t) */
void interp_cubic_v3(float x[3], float v[3], const float x1[3], const float v1[3], const float x2[3], const float v2[3], const float t)
{
@@ -2945,6 +3464,43 @@ void resolve_quad_uv_v2_deriv(float r_uv[2], float r_deriv[2][2],
}
}
+/* a version of resolve_quad_uv_v2 that only calculates the 'u' */
+float resolve_quad_u_v2(
+ 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]);
+
+ /* X is 2D cross product (determinant)
+ * A = (p0 - p) X (p0 - p3)*/
+ const double a = (st0[0] - st[0]) * (st0[1] - st3[1]) - (st0[1] - st[1]) * (st0[0] - st3[0]);
+
+ /* B = ( (p0 - p) X (p1 - p2) + (p1 - p) X (p0 - p3) ) / 2 */
+ const double b = 0.5 * (double)(((st0[0] - st[0]) * (st1[1] - st2[1]) - (st0[1] - st[1]) * (st1[0] - st2[0])) +
+ ((st1[0] - st[0]) * (st0[1] - st3[1]) - (st1[1] - st[1]) * (st0[0] - st3[0])));
+
+ /* 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]);
+ double denom = a - 2 * b + fC;
+
+ if (IS_ZERO(denom) != 0) {
+ const double fDen = a - fC;
+ if (IS_ZERO(fDen) == 0)
+ return (float)(a / fDen);
+ else
+ return 0.0f;
+ }
+ else {
+ const double desc_sq = b * b - a * fC;
+ const double desc = sqrt(desc_sq < 0.0 ? 0.0 : desc_sq);
+ const double s = signed_area > 0 ? (-1.0) : 1.0;
+
+ return (float)(((a - b) + s * desc) / denom);
+ }
+}
+
+
#undef IS_ZERO
/* reverse of the functions above */
@@ -3014,8 +3570,8 @@ void perspective_m4(float mat[4][4], const float left, const float right, const
mat[2][3] = -1.0f;
mat[3][2] = (-2.0f * nearClip * farClip) / Zdelta;
mat[0][1] = mat[0][2] = mat[0][3] =
- mat[1][0] = mat[1][2] = mat[1][3] =
- mat[3][0] = mat[3][1] = mat[3][3] = 0.0f;
+ mat[1][0] = mat[1][2] = mat[1][3] =
+ mat[3][0] = mat[3][1] = mat[3][3] = 0.0f;
}
@@ -3048,6 +3604,59 @@ void window_translate_m4(float winmat[4][4], float perspmat[4][4], const float x
}
}
+/**
+ * Frustum planes extraction from a projection matrix (homogeneous 4d vector representations of planes).
+ *
+ * plane parameters can be NULL if you do not need them.
+ */
+void planes_from_projmat(float mat[4][4], float left[4], float right[4], float top[4], float bottom[4],
+ float near[4], float far[4])
+{
+ /* References:
+ *
+ * https://fgiesen.wordpress.com/2012/08/31/frustum-planes-from-the-projection-matrix/
+ * http://www8.cs.umu.se/kurser/5DV051/HT12/lab/plane_extraction.pdf
+ */
+
+ int i;
+
+ if (left) {
+ for (i = 4; i--; ) {
+ left[i] = mat[i][3] + mat[i][0];
+ }
+ }
+
+ if (right) {
+ for (i = 4; i--; ) {
+ right[i] = mat[i][3] - mat[i][0];
+ }
+ }
+
+ if (bottom) {
+ for (i = 4; i--; ) {
+ bottom[i] = mat[i][3] + mat[i][1];
+ }
+ }
+
+ if (top) {
+ for (i = 4; i--; ) {
+ top[i] = mat[i][3] - mat[i][1];
+ }
+ }
+
+ if (near) {
+ for (i = 4; i--; ) {
+ near[i] = mat[i][3] + mat[i][2];
+ }
+ }
+
+ if (far) {
+ for (i = 4; i--; ) {
+ far[i] = mat[i][3] - mat[i][2];
+ }
+ }
+}
+
static void i_multmatrix(float icand[4][4], float Vm[4][4])
{
int row, col;
@@ -3222,9 +3831,44 @@ void map_to_sphere(float *r_u, float *r_v, const float x, const float y, const f
/********************************* Normals **********************************/
-void accumulate_vertex_normals(float n1[3], float n2[3], float n3[3],
- float n4[3], const float f_no[3], const float co1[3], const float co2[3],
- const float co3[3], const float co4[3])
+void accumulate_vertex_normals_tri(
+ float n1[3], float n2[3], float n3[3],
+ const float f_no[3],
+ const float co1[3], const float co2[3], const float co3[3])
+{
+ float vdiffs[3][3];
+ const int nverts = 3;
+
+ /* compute normalized edge vectors */
+ sub_v3_v3v3(vdiffs[0], co2, co1);
+ sub_v3_v3v3(vdiffs[1], co3, co2);
+ sub_v3_v3v3(vdiffs[2], co1, co3);
+
+ normalize_v3(vdiffs[0]);
+ normalize_v3(vdiffs[1]);
+ normalize_v3(vdiffs[2]);
+
+ /* accumulate angle weighted face normal */
+ {
+ float *vn[] = {n1, n2, n3};
+ const float *prev_edge = vdiffs[nverts - 1];
+ int i;
+
+ for (i = 0; i < nverts; i++) {
+ const float *cur_edge = vdiffs[i];
+ const float fac = saacos(-dot_v3v3(cur_edge, prev_edge));
+
+ /* accumulate */
+ madd_v3_v3fl(vn[i], f_no, fac);
+ prev_edge = cur_edge;
+ }
+ }
+}
+
+void accumulate_vertex_normals(
+ float n1[3], float n2[3], float n3[3], float n4[3],
+ const float f_no[3],
+ const float co1[3], const float co2[3], const float co3[3], const float co4[3])
{
float vdiffs[4][3];
const int nverts = (n4 != NULL && co4 != NULL) ? 4 : 3;
@@ -3296,7 +3940,11 @@ void accumulate_vertex_normals_poly(float **vertnos, const float polyno[3],
/********************************* Tangents **********************************/
-void tangent_from_uv(float uv1[2], float uv2[2], float uv3[3], float co1[3], float co2[3], float co3[3], float n[3], float tang[3])
+void tangent_from_uv(
+ const float uv1[2], const float uv2[2], const float uv3[3],
+ const float co1[3], const float co2[3], const float co3[3],
+ const float n[3],
+ float r_tang[3])
{
const float s1 = uv2[0] - uv1[0];
const float s2 = uv3[0] - uv1[0];
@@ -3304,7 +3952,8 @@ void tangent_from_uv(float uv1[2], float uv2[2], float uv3[3], float co1[3], flo
const float t2 = uv3[1] - uv1[1];
float det = (s1 * t2 - s2 * t1);
- if (det != 0.0f) { /* otherwise 'tang' becomes nan */
+ /* otherwise 'r_tang' becomes nan */
+ if (det != 0.0f) {
float tangv[3], ct[3], e1[3], e2[3];
det = 1.0f / det;
@@ -3312,21 +3961,21 @@ void tangent_from_uv(float uv1[2], float uv2[2], float uv3[3], float co1[3], flo
/* normals in render are inversed... */
sub_v3_v3v3(e1, co1, co2);
sub_v3_v3v3(e2, co1, co3);
- tang[0] = (t2 * e1[0] - t1 * e2[0]) * det;
- tang[1] = (t2 * e1[1] - t1 * e2[1]) * det;
- tang[2] = (t2 * e1[2] - t1 * e2[2]) * det;
+ r_tang[0] = (t2 * e1[0] - t1 * e2[0]) * det;
+ r_tang[1] = (t2 * e1[1] - t1 * e2[1]) * det;
+ r_tang[2] = (t2 * e1[2] - t1 * e2[2]) * det;
tangv[0] = (s1 * e2[0] - s2 * e1[0]) * det;
tangv[1] = (s1 * e2[1] - s2 * e1[1]) * det;
tangv[2] = (s1 * e2[2] - s2 * e1[2]) * det;
- cross_v3_v3v3(ct, tang, tangv);
+ cross_v3_v3v3(ct, r_tang, tangv);
/* check flip */
if (dot_v3v3(ct, n) < 0.0f) {
- negate_v3(tang);
+ negate_v3(r_tang);
}
}
else {
- tang[0] = tang[1] = tang[2] = 0.0f;
+ zero_v3(r_tang);
}
}
@@ -4001,3 +4650,31 @@ bool is_poly_convex_v2(const float verts[][2], unsigned int nr)
return true;
}
+
+/**
+ * Check if either of the diagonals along this quad create flipped triangles
+ * (normals pointing away from eachother).
+ * - (1 << 0): (v1-v3) is flipped.
+ * - (1 << 1): (v2-v4) is flipped.
+ */
+int is_quad_flip_v3(const float v1[3], const float v2[3], const float v3[3], const float v4[3])
+{
+ float d_12[3], d_23[3], d_34[3], d_41[3];
+ float cross_a[3], cross_b[3];
+ int ret = 0;
+
+ sub_v3_v3v3(d_12, v1, v2);
+ sub_v3_v3v3(d_23, v2, v3);
+ sub_v3_v3v3(d_34, v3, v4);
+ sub_v3_v3v3(d_41, v4, v1);
+
+ cross_v3_v3v3(cross_a, d_12, d_23);
+ cross_v3_v3v3(cross_b, d_34, d_41);
+ ret |= ((dot_v3v3(cross_a, cross_b) < 0.0f) << 0);
+
+ cross_v3_v3v3(cross_a, d_23, d_34);
+ cross_v3_v3v3(cross_b, d_41, d_12);
+ ret |= ((dot_v3v3(cross_a, cross_b) < 0.0f) << 1);
+
+ return ret;
+}
diff --git a/source/blender/blenlib/intern/math_geom_inline.c b/source/blender/blenlib/intern/math_geom_inline.c
index 5a64ed63ecf..44b17681540 100644
--- a/source/blender/blenlib/intern/math_geom_inline.c
+++ b/source/blender/blenlib/intern/math_geom_inline.c
@@ -54,6 +54,12 @@ MINLINE float area_tri_v2(const float v1[2], const float v2[2], const float v3[2
return fabsf(area_tri_signed_v2(v1, v2, v3));
}
+MINLINE float area_squared_tri_v2(const float v1[2], const float v2[2], const float v3[2])
+{
+ float area = area_tri_signed_v2(v1, v2, v3);
+ return area * area;
+}
+
/****************************** Spherical Harmonics **************************/
MINLINE void zero_sh(float r[9])
diff --git a/source/blender/blenlib/intern/math_interp.c b/source/blender/blenlib/intern/math_interp.c
index 4feb954a31a..b45d8b4c13b 100644
--- a/source/blender/blenlib/intern/math_interp.c
+++ b/source/blender/blenlib/intern/math_interp.c
@@ -111,10 +111,12 @@ 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;
+ if (float_output) {
+ copy_vn_fl(float_output, components, 0.0f);
+ }
+ if (byte_output) {
+ copy_vn_uchar(byte_output, components, 0);
+ }
return;
}
@@ -279,7 +281,7 @@ BLI_INLINE void bilinear_interpolation(const unsigned char *byte_buffer, const f
/* 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;
+ copy_vn_fl(float_output, components, 0.0f);
return;
}
@@ -321,7 +323,7 @@ BLI_INLINE void bilinear_interpolation(const unsigned char *byte_buffer, const f
/* 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;
+ copy_vn_uchar(byte_output, components, 0);
return;
}
@@ -467,7 +469,7 @@ void BLI_ewa_filter(const int width, const int height,
/* scaling dxt/dyt by full resolution can cause overflow because of huge A/B/C and esp. F values,
* scaling by aspect ratio alone does the opposite, so try something in between instead... */
const float ff2 = (float)width, ff = sqrtf(ff2), q = (float)height / ff;
- const float Ux = du[0] * ff, Vx = dv[0] * q, Uy = du[1] * ff, Vy = dv[1] * q;
+ const float Ux = du[0] * ff, Vx = du[1] * q, Uy = dv[0] * ff, Vy = dv[1] * q;
float A = Vx * Vx + Vy * Vy;
float B = -2.0f * (Ux * Vx + Uy * Vy);
float C = Ux * Ux + Uy * Uy;
diff --git a/source/blender/blenlib/intern/math_matrix.c b/source/blender/blenlib/intern/math_matrix.c
index af42af88582..33d0fb87aca 100644
--- a/source/blender/blenlib/intern/math_matrix.c
+++ b/source/blender/blenlib/intern/math_matrix.c
@@ -504,6 +504,16 @@ void mul_mat3_m4_v3(float mat[4][4], float vec[3])
vec[2] = x * mat[0][2] + y * mat[1][2] + mat[2][2] * vec[2];
}
+void mul_v3_mat3_m4v3(float r[3], float mat[4][4], const float vec[3])
+{
+ const float x = vec[0];
+ const float y = vec[1];
+
+ r[0] = x * mat[0][0] + y * mat[1][0] + mat[2][0] * vec[2];
+ r[1] = x * mat[0][1] + y * mat[1][1] + mat[2][1] * vec[2];
+ r[2] = x * mat[0][2] + y * mat[1][2] + mat[2][2] * vec[2];
+}
+
void mul_project_m4_v3(float mat[4][4], float vec[3])
{
const float w = mul_project_m4_v3_zfac(mat, vec);
@@ -639,7 +649,16 @@ void mul_mat3_m4_fl(float m[4][4], float f)
m[i][j] *= f;
}
-void negate_m3(float m[4][4])
+void negate_m3(float m[3][3])
+{
+ int i, j;
+
+ for (i = 0; i < 3; i++)
+ for (j = 0; j < 3; j++)
+ m[i][j] *= -1.0f;
+}
+
+void negate_mat3_m4(float m[4][4])
{
int i, j;
@@ -839,9 +858,10 @@ bool invert_m4_m4(float inverse[4][4], float mat[4][4])
}
}
- temp = tempmat[i][i];
- if (temp == 0)
- return 0; /* No non-zero pivot */
+ if (UNLIKELY(tempmat[i][i] == 0.0f)) {
+ return false; /* No non-zero pivot */
+ }
+ temp = (double)tempmat[i][i];
for (k = 0; k < 4; k++) {
tempmat[i][k] = (float)((double)tempmat[i][k] / temp);
inverse[i][k] = (float)((double)inverse[i][k] / temp);
@@ -856,7 +876,7 @@ bool invert_m4_m4(float inverse[4][4], float mat[4][4])
}
}
}
- return 1;
+ return true;
}
/****************************** Linear Algebra *******************************/
@@ -876,6 +896,37 @@ void transpose_m3(float mat[3][3])
mat[2][1] = t;
}
+void transpose_m3_m3(float rmat[3][3], float mat[3][3])
+{
+ BLI_assert(rmat != mat);
+
+ rmat[0][0] = mat[0][0];
+ rmat[0][1] = mat[1][0];
+ rmat[0][2] = mat[2][0];
+ rmat[1][0] = mat[0][1];
+ rmat[1][1] = mat[1][1];
+ rmat[1][2] = mat[2][1];
+ rmat[2][0] = mat[0][2];
+ rmat[2][1] = mat[1][2];
+ rmat[2][2] = mat[2][2];
+}
+
+/* seems obscure but in-fact a common operation */
+void transpose_m3_m4(float rmat[3][3], float mat[4][4])
+{
+ BLI_assert(&rmat[0][0] != &mat[0][0]);
+
+ rmat[0][0] = mat[0][0];
+ rmat[0][1] = mat[1][0];
+ rmat[0][2] = mat[2][0];
+ rmat[1][0] = mat[0][1];
+ rmat[1][1] = mat[1][1];
+ rmat[1][2] = mat[2][1];
+ rmat[2][0] = mat[0][2];
+ rmat[2][1] = mat[1][2];
+ rmat[2][2] = mat[2][2];
+}
+
void transpose_m4(float mat[4][4])
{
float t;
@@ -902,6 +953,28 @@ void transpose_m4(float mat[4][4])
mat[3][2] = t;
}
+void transpose_m4_m4(float rmat[4][4], float mat[4][4])
+{
+ BLI_assert(rmat != mat);
+
+ rmat[0][0] = mat[0][0];
+ rmat[0][1] = mat[1][0];
+ rmat[0][2] = mat[2][0];
+ rmat[0][3] = mat[3][0];
+ rmat[1][0] = mat[0][1];
+ rmat[1][1] = mat[1][1];
+ rmat[1][2] = mat[2][1];
+ rmat[1][3] = mat[3][1];
+ rmat[2][0] = mat[0][2];
+ rmat[2][1] = mat[1][2];
+ rmat[2][2] = mat[2][2];
+ rmat[2][3] = mat[3][2];
+ rmat[3][0] = mat[0][3];
+ rmat[3][1] = mat[1][3];
+ rmat[3][2] = mat[2][3];
+ rmat[3][3] = mat[3][3];
+}
+
int compare_m4m4(float mat1[4][4], float mat2[4][4], float limit)
{
if (compare_v4v4(mat1[0], mat2[0], limit))
@@ -1086,12 +1159,12 @@ bool is_orthogonal_m3(float m[3][3])
for (i = 0; i < 3; i++) {
for (j = 0; j < i; j++) {
- if (fabsf(dot_v3v3(m[i], m[j])) > 1.5f * FLT_EPSILON)
- return 0;
+ if (fabsf(dot_v3v3(m[i], m[j])) > 1e-5f)
+ return false;
}
}
- return 1;
+ return true;
}
bool is_orthogonal_m4(float m[4][4])
@@ -1100,13 +1173,13 @@ bool is_orthogonal_m4(float m[4][4])
for (i = 0; i < 4; i++) {
for (j = 0; j < i; j++) {
- if (fabsf(dot_v4v4(m[i], m[j])) > 1.5f * FLT_EPSILON)
- return 0;
+ if (fabsf(dot_v4v4(m[i], m[j])) > 1e-5f)
+ return false;
}
}
- return 1;
+ return true;
}
bool is_orthonormal_m3(float m[3][3])
@@ -1115,13 +1188,13 @@ bool is_orthonormal_m3(float m[3][3])
int i;
for (i = 0; i < 3; i++)
- if (fabsf(dot_v3v3(m[i], m[i]) - 1) > 1.5f * FLT_EPSILON)
- return 0;
+ if (fabsf(dot_v3v3(m[i], m[i]) - 1) > 1e-5f)
+ return false;
- return 1;
+ return true;
}
- return 0;
+ return false;
}
bool is_orthonormal_m4(float m[4][4])
@@ -1130,13 +1203,13 @@ bool is_orthonormal_m4(float m[4][4])
int i;
for (i = 0; i < 4; i++)
- if (fabsf(dot_v4v4(m[i], m[i]) - 1) > 1.5f * FLT_EPSILON)
- return 0;
+ if (fabsf(dot_v4v4(m[i], m[i]) - 1) > 1e-5f)
+ return false;
- return 1;
+ return true;
}
- return 0;
+ return false;
}
bool is_uniform_scaled_m3(float m[3][3])
@@ -1145,8 +1218,7 @@ bool is_uniform_scaled_m3(float m[3][3])
float t[3][3];
float l1, l2, l3, l4, l5, l6;
- copy_m3_m3(t, m);
- transpose_m3(t);
+ transpose_m3_m3(t, m);
l1 = len_squared_v3(m[0]);
l2 = len_squared_v3(m[1]);
@@ -1387,7 +1459,7 @@ float mat3_to_scale(float mat[3][3])
{
/* unit length vector */
float unit_vec[3];
- copy_v3_fl(unit_vec, (float)(1.0 / M_SQRT3));
+ copy_v3_fl(unit_vec, (float)M_SQRT1_3);
mul_m3_v3(mat, unit_vec);
return len_v3(unit_vec);
}
@@ -1396,40 +1468,21 @@ float mat4_to_scale(float mat[4][4])
{
/* unit length vector */
float unit_vec[3];
- copy_v3_fl(unit_vec, (float)(1.0 / M_SQRT3));
+ copy_v3_fl(unit_vec, (float)M_SQRT1_3);
mul_mat3_m4_v3(mat, unit_vec);
return len_v3(unit_vec);
}
void mat3_to_rot_size(float rot[3][3], float size[3], float mat3[3][3])
{
- float mat3_n[3][3]; /* mat3 -> normalized, 3x3 */
- float imat3_n[3][3]; /* mat3 -> normalized & inverted, 3x3 */
-
- /* rotation & scale are linked, we need to create the mat's
- * for these together since they are related. */
-
- /* so scale doesn't interfere with rotation [#24291] */
- /* note: this is a workaround for negative matrix not working for rotation conversion, FIXME */
- normalize_m3_m3(mat3_n, mat3);
- if (is_negative_m3(mat3)) {
- negate_v3(mat3_n[0]);
- negate_v3(mat3_n[1]);
- negate_v3(mat3_n[2]);
- }
-
- /* rotation */
/* keep rot as a 3x3 matrix, the caller can convert into a quat or euler */
- copy_m3_m3(rot, mat3_n);
-
- /* scale */
- /* note: mat4_to_size(ob->size, mat) fails for negative scale */
- invert_m3_m3(imat3_n, mat3_n);
- mul_m3_m3m3(mat3, imat3_n, mat3);
-
- size[0] = mat3[0][0];
- size[1] = mat3[1][1];
- size[2] = mat3[2][2];
+ size[0] = normalize_v3_v3(rot[0], mat3[0]);
+ size[1] = normalize_v3_v3(rot[1], mat3[1]);
+ size[2] = normalize_v3_v3(rot[2], mat3[2]);
+ if (UNLIKELY(is_negative_m3(rot))) {
+ negate_m3(rot);
+ negate_v3(size);
+ }
}
void mat4_to_loc_rot_size(float loc[3], float rot[3][3], float size[3], float wmat[4][4])
@@ -1454,9 +1507,7 @@ void mat4_to_loc_quat(float loc[3], float quat[4], float wmat[4][4])
/* so scale doesn't interfere with rotation [#24291] */
/* note: this is a workaround for negative matrix not working for rotation conversion, FIXME */
if (is_negative_m3(mat3)) {
- negate_v3(mat3_n[0]);
- negate_v3(mat3_n[1]);
- negate_v3(mat3_n[2]);
+ negate_m3(mat3_n);
}
mat3_to_quat(quat, mat3_n);
@@ -2183,14 +2234,14 @@ void svd_m4(float U[4][4], float s[4], float V[4][4], float A_[4][4])
}
}
-void pseudoinverse_m4_m4(float Ainv[4][4], float A[4][4], float epsilon)
+void pseudoinverse_m4_m4(float Ainv[4][4], float A_[4][4], float epsilon)
{
- /* compute moon-penrose pseudo inverse of matrix, singular values
+ /* compute Moore-Penrose pseudo inverse of matrix, singular values
* below epsilon are ignored for stability (truncated SVD) */
- float V[4][4], W[4], Wm[4][4], U[4][4];
+ float A[4][4], V[4][4], W[4], Wm[4][4], U[4][4];
int i;
- transpose_m4(A);
+ transpose_m4_m4(A, A_);
svd_m4(V, W, U, A);
transpose_m4(U);
transpose_m4(V);
@@ -2261,6 +2312,16 @@ void invert_m4_m4_safe(float Ainv[4][4], float A[4][4])
*
*/
+/**
+ * Global-invariant transform.
+ *
+ * This defines a matrix transforming a point in local space to a point in target space such that its global
+ * coordinates remain unchanged.
+ *
+ * In other words, if we have a global point P with local coordinates (x, y, z) and global coordinates (X, Y, Z),
+ * this defines a transform matrix TM such that (x', y', z') = TM * (x, y, z)
+ * where (x', y', z') are the coordinates of P' in target space such that it keeps (X, Y, Z) coordinates in global space.
+ */
void BLI_space_transform_from_matrices(SpaceTransform *data, float local[4][4], float target[4][4])
{
float itarget[4][4];
@@ -2269,6 +2330,24 @@ void BLI_space_transform_from_matrices(SpaceTransform *data, float local[4][4],
invert_m4_m4(data->target2local, data->local2target);
}
+/**
+ * Local-invariant transform.
+ *
+ * This defines a matrix transforming a point in global space such that its local coordinates
+ * (from local space to target space) remain unchanged.
+ *
+ * In other words, if we have a local point p with local coordinates (x, y, z) and global coordinates (X, Y, Z),
+ * this defines a transform matrix TM such that (X', Y', Z') = TM * (X, Y, Z)
+ * where (X', Y', Z') are the coordinates of p' in global space such that it keeps (x, y, z) coordinates in target space.
+ */
+void BLI_space_transform_global_from_matrices(SpaceTransform *data, float local[4][4], float target[4][4])
+{
+ float ilocal[4][4];
+ invert_m4_m4(ilocal, local);
+ mul_m4_m4m4(data->local2target, target, ilocal);
+ invert_m4_m4(data->target2local, data->local2target);
+}
+
void BLI_space_transform_apply(const SpaceTransform *data, float co[3])
{
mul_v3_m4v3(co, ((SpaceTransform *)data)->local2target, co);
diff --git a/source/blender/blenlib/intern/math_rotation.c b/source/blender/blenlib/intern/math_rotation.c
index 9a6515daf68..575710e8d75 100644
--- a/source/blender/blenlib/intern/math_rotation.c
+++ b/source/blender/blenlib/intern/math_rotation.c
@@ -1016,6 +1016,41 @@ void angle_to_mat2(float mat[2][2], const float angle)
mat[1][1] = angle_cos;
}
+/****************************** Exponential Map ******************************/
+
+void quat_normalized_to_expmap(float expmap[3], const float q[4])
+{
+ float angle;
+ BLI_ASSERT_UNIT_QUAT(q);
+
+ /* Obtain axis/angle representation. */
+ quat_to_axis_angle(expmap, &angle, q);
+
+ /* Convert to exponential map. */
+ mul_v3_fl(expmap, angle);
+}
+
+void quat_to_expmap(float expmap[3], const float q[4])
+{
+ float q_no[4];
+ normalize_qt_qt(q_no, q);
+ quat_normalized_to_expmap(expmap, q_no);
+}
+
+void expmap_to_quat(float r[4], const float expmap[3])
+{
+ float axis[3];
+ float angle;
+
+ /* Obtain axis/angle representation. */
+ if (LIKELY((angle = normalize_v3_v3(axis, expmap)) != 0.0f)) {
+ axis_angle_normalized_to_quat(r, axis, angle_wrap_rad(angle));
+ }
+ else {
+ unit_qt(r);
+ }
+}
+
/******************************** XYZ Eulers *********************************/
/* XYZ order */
@@ -1288,12 +1323,21 @@ static const RotOrderInfo rotOrders[] = {
* NOTE: since we start at 1 for the values, but arrays index from 0,
* there is -1 factor involved in this process...
*/
-#define GET_ROTATIONORDER_INFO(order) (assert(order >= 0 && order <= 6), (order < 1) ? &rotOrders[0] : &rotOrders[(order) - 1])
+static const RotOrderInfo *get_rotation_order_info(const short order)
+{
+ assert(order >= 0 && order <= 6);
+ if (order < 1)
+ return &rotOrders[0];
+ else if (order < 6)
+ return &rotOrders[order - 1];
+ else
+ return &rotOrders[5];
+}
/* Construct quaternion from Euler angles (in radians). */
void eulO_to_quat(float q[4], const float e[3], const short order)
{
- const RotOrderInfo *R = GET_ROTATIONORDER_INFO(order);
+ const RotOrderInfo *R = get_rotation_order_info(order);
short i = R->axis[0], j = R->axis[1], k = R->axis[2];
double ti, tj, th, ci, cj, ch, si, sj, sh, cc, cs, sc, ss;
double a[3];
@@ -1338,7 +1382,7 @@ void quat_to_eulO(float e[3], short const order, const float q[4])
/* Construct 3x3 matrix from Euler angles (in radians). */
void eulO_to_mat3(float M[3][3], const float e[3], const short order)
{
- const RotOrderInfo *R = GET_ROTATIONORDER_INFO(order);
+ const RotOrderInfo *R = get_rotation_order_info(order);
short i = R->axis[0], j = R->axis[1], k = R->axis[2];
double ti, tj, th, ci, cj, ch, si, sj, sh, cc, cs, sc, ss;
@@ -1379,7 +1423,7 @@ void eulO_to_mat3(float M[3][3], const float e[3], const short order)
/* returns two euler calculation methods, so we can pick the best */
static void mat3_to_eulo2(float M[3][3], float eul1[3], float eul2[3], const short order)
{
- const RotOrderInfo *R = GET_ROTATIONORDER_INFO(order);
+ const RotOrderInfo *R = get_rotation_order_info(order);
short i = R->axis[0], j = R->axis[1], k = R->axis[2];
float mat[3][3];
float cy;
@@ -1515,7 +1559,7 @@ void rotate_eulO(float beul[3], const short order, char axis, float ang)
/* the matrix is written to as 3 axis vectors */
void eulO_to_gimbal_axis(float gmat[3][3], const float eul[3], const short order)
{
- const RotOrderInfo *R = GET_ROTATIONORDER_INFO(order);
+ const RotOrderInfo *R = get_rotation_order_info(order);
float mat[3][3];
float teul[3];
@@ -1572,7 +1616,7 @@ void eulO_to_gimbal_axis(float gmat[3][3], const float eul[3], const short order
void mat4_to_dquat(DualQuat *dq, float basemat[4][4], float mat[4][4])
{
- float *t, *q, dscale[3], scale[3], basequat[4];
+ float *t, *q, dscale[3], scale[3], basequat[4], mat3[3][3];
float baseRS[4][4], baseinv[4][4], baseR[4][4], baseRinv[4][4];
float R[4][4], S[4][4];
@@ -1585,7 +1629,9 @@ void mat4_to_dquat(DualQuat *dq, float basemat[4][4], float mat[4][4])
dscale[1] = scale[1] - 1.0f;
dscale[2] = scale[2] - 1.0f;
- if ((determinant_m4(mat) < 0.0f) || len_v3(dscale) > 1e-4f) {
+ copy_m3_m4(mat3, mat);
+
+ if (!is_orthonormal_m3(mat3) || (determinant_m4(mat) < 0.0f) || len_squared_v3(dscale) > SQUARE(1e-4f)) {
/* extract R and S */
float tmp[4][4];
@@ -1867,7 +1913,7 @@ float angle_wrap_deg(float angle)
/* returns an angle compatible with angle_compat */
float angle_compat_rad(float angle, float angle_compat)
{
- return angle + (floorf(((angle_compat - angle) / (float)M_PI) + 0.5f)) * (float)M_PI;
+ return angle_compat + angle_wrap_rad(angle - angle_compat);
}
/* axis conversion */
diff --git a/source/blender/blenlib/intern/math_solvers.c b/source/blender/blenlib/intern/math_solvers.c
new file mode 100644
index 00000000000..2f962714c8c
--- /dev/null
+++ b/source/blender/blenlib/intern/math_solvers.c
@@ -0,0 +1,61 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2015 by Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ * */
+
+/** \file blender/blenlib/intern/math_solvers.c
+ * \ingroup bli
+ */
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_math.h"
+#include "BLI_utildefines.h"
+
+#include "BLI_strict_flags.h"
+
+#include "eigen3_capi.h"
+
+/********************************** Eigen Solvers *********************************/
+
+/**
+ * \brief Compute the eigen values and/or vectors of given 3D symmetric (aka adjoint) matrix.
+ *
+ * \param m3 the 3D symmetric matrix.
+ * \return r_eigen_values the computed eigen values (NULL if not needed).
+ * \return r_eigen_vectors the computed eigen vectors (NULL if not needed).
+ */
+bool BLI_eigen_solve_selfadjoint_m3(const float m3[3][3], float r_eigen_values[3], float r_eigen_vectors[3][3])
+{
+#ifndef NDEBUG
+ /* We must assert given matrix is self-adjoint (i.e. symmetric) */
+ if ((m3[0][1] != m3[1][0]) ||
+ (m3[0][2] != m3[2][0]) ||
+ (m3[1][2] != m3[2][1]))
+ {
+ BLI_assert(0);
+ }
+#endif
+
+ return EG3_self_adjoint_eigen_solve(3, (const float *)m3, r_eigen_values, (float *)r_eigen_vectors);
+}
diff --git a/source/blender/blenlib/intern/math_statistics.c b/source/blender/blenlib/intern/math_statistics.c
new file mode 100644
index 00000000000..a8cb8e2c40d
--- /dev/null
+++ b/source/blender/blenlib/intern/math_statistics.c
@@ -0,0 +1,116 @@
+/*
+ * ***** 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) 2015 by Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ * */
+
+/** \file blender/blenlib/intern/math_statistics.c
+ * \ingroup bli
+ */
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_math.h"
+#include "BLI_utildefines.h"
+
+#include "BLI_strict_flags.h"
+
+/********************************** Covariance Matrices *********************************/
+
+/**
+ * \brief Compute the covariance matrix of given set of nD coordinates.
+ *
+ * \param n the dimension of the vectors (and hence, of the covariance matrix to compute).
+ * \param cos_vn the nD points to compute covariance from.
+ * \param nbr_cos_vn the number of nD coordinates in cos_vn.
+ * \param center the center (or mean point) of cos_vn. If NULL, it is assumed cos_vn is already centered.
+ * \param use_sample_correction whether to apply sample correction
+ * (i.e. get 'sample varince' instead of 'population variance').
+ * \return r_covmat the computed covariance matrix.
+ */
+void BLI_covariance_m_vn_ex(
+ const int n, const float *cos_vn, const int nbr_cos_vn, const float *center, const bool use_sample_correction,
+ float *r_covmat)
+{
+ int i, j, k;
+
+ /* Note about that division: see https://en.wikipedia.org/wiki/Bessel%27s_correction.
+ * In a nutshell, it must be 1 / (n - 1) for 'sample data', and 1 / n for 'population data'...
+ */
+ const float covfac = 1.0f / (float)(use_sample_correction ? nbr_cos_vn - 1 : nbr_cos_vn);
+
+ memset(r_covmat, 0, sizeof(*r_covmat) * (size_t)(n * n));
+
+#pragma omp parallel for default(shared) private(i, j, k) schedule(static) if ((nbr_cos_vn * n) >= 10000)
+ for (i = 0; i < n; i++) {
+ for (j = i; j < n; j++) {
+ r_covmat[i * n + j] = 0.0f;
+ if (center) {
+ for (k = 0; k < nbr_cos_vn; k++) {
+ r_covmat[i * n + j] += (cos_vn[k * n + i] - center[i]) * (cos_vn[k * n + j] - center[j]);
+ }
+ }
+ else {
+ for (k = 0; k < nbr_cos_vn; k++) {
+ r_covmat[i * n + j] += cos_vn[k * n + i] * cos_vn[k * n + j];
+ }
+ }
+ r_covmat[i * n + j] *= covfac;
+ }
+ }
+ /* Covariance matrices are always symetrical, so we can compute only one half of it (as done above),
+ * and copy it to the other half! */
+ for (i = 1; i < n; i++) {
+ for (j = 0; j < i; j++) {
+ r_covmat[i * n + j] = r_covmat[j * n + i];
+ }
+ }
+}
+
+/**
+ * \brief Compute the covariance matrix of given set of 3D coordinates.
+ *
+ * \param cos_v3 the 3D points to compute covariance from.
+ * \param nbr_cos_v3 the number of 3D coordinates in cos_v3.
+ * \return r_covmat the computed covariance matrix.
+ * \return r_center the computed center (mean) of 3D points (may be NULL).
+ */
+void BLI_covariance_m3_v3n(
+ const float (*cos_v3)[3], const int nbr_cos_v3, const bool use_sample_correction,
+ float r_covmat[3][3], float r_center[3])
+{
+ float center[3];
+ const float mean_fac = 1.0f / (float)nbr_cos_v3;
+ int i;
+
+ zero_v3(center);
+ for (i = 0; i < nbr_cos_v3; i++) {
+ /* Applying mean_fac here rather than once at the end reduce compute errors... */
+ madd_v3_v3fl(center, cos_v3[i], mean_fac);
+ }
+
+ if (r_center) {
+ copy_v3_v3(r_center, center);
+ }
+
+ BLI_covariance_m_vn_ex(3, (const float *)cos_v3, nbr_cos_v3, center, use_sample_correction, (float *)r_covmat);
+}
diff --git a/source/blender/blenlib/intern/math_vector.c b/source/blender/blenlib/intern/math_vector.c
index 887ec7d4d2c..8d33e04241a 100644
--- a/source/blender/blenlib/intern/math_vector.c
+++ b/source/blender/blenlib/intern/math_vector.c
@@ -252,6 +252,13 @@ void mid_v3_v3v3v3(float v[3], const float v1[3], const float v2[3], const float
v[2] = (v1[2] + v2[2] + v3[2]) / 3.0f;
}
+void mid_v3_v3v3v3v3(float v[3], const float v1[3], const float v2[3], const float v3[3], const float v4[3])
+{
+ v[0] = (v1[0] + v2[0] + v3[0] + v4[0]) / 4.0f;
+ v[1] = (v1[1] + v2[1] + v3[1] + v4[1]) / 4.0f;
+ v[2] = (v1[2] + v2[2] + v3[2] + v4[2]) / 4.0f;
+}
+
/**
* Specialized function for calculating normals.
* fastpath for:
@@ -565,6 +572,27 @@ void project_v3_v3v3(float c[3], const float v1[3], const float v2[3])
c[2] = mul * v2[2];
}
+/**
+ * In this case plane is a 3D vector only (no 4th component).
+ *
+ * Projecting will make \a c a copy of \a v orthogonal to \a v_plane.
+ *
+ * \note If \a v is exactly perpendicular to \a v_plane, \a c will just be a copy of \a v.
+ */
+void project_plane_v3_v3v3(float c[3], const float v[3], const float v_plane[3])
+{
+ float delta[3];
+ project_v3_v3v3(delta, v, v_plane);
+ sub_v3_v3v3(c, v, delta);
+}
+
+void project_plane_v2_v2v2(float c[2], const float v[2], const float v_plane[2])
+{
+ float delta[2];
+ project_v2_v2v2(delta, v, v_plane);
+ sub_v2_v2v2(c, v, delta);
+}
+
/* project a vector on a plane defined by normal and a plane point p */
void project_v3_plane(float v[3], const float n[3], const float p[3])
{
@@ -757,6 +785,13 @@ void minmax_v2v2_v2(float min[2], float max[2], const float vec[2])
if (max[1] < vec[1]) max[1] = vec[1];
}
+void minmax_v3v3_v3_array(float r_min[3], float r_max[3], const float (*vec_arr)[3], int nbr)
+{
+ while (nbr--) {
+ minmax_v3v3_v3(r_min, r_max, *vec_arr++);
+ }
+}
+
/** ensure \a v1 is \a dist from \a v2 */
void dist_ensure_v3_v3fl(float v1[3], const float v2[3], const float dist)
{
@@ -841,7 +876,7 @@ float normalize_vn_vn(float *array_tar, const float *array_src, const int size)
mul_vn_vn_fl(array_tar, array_src, size, 1.0f / d_sqrt);
}
else {
- fill_vn_fl(array_tar, size, 0.0f);
+ copy_vn_fl(array_tar, size, 0.0f);
d_sqrt = 0.0f;
}
return d_sqrt;
@@ -862,6 +897,16 @@ void range_vn_i(int *array_tar, const int size, const int start)
}
}
+void range_vn_u(unsigned int *array_tar, const int size, const unsigned int start)
+{
+ unsigned int *array_pt = array_tar + (size - 1);
+ unsigned int j = start + (unsigned int)(size - 1);
+ int i = size;
+ while (i--) {
+ *(array_pt--) = j--;
+ }
+}
+
void range_vn_fl(float *array_tar, const int size, const float start, const float step)
{
float *array_pt = array_tar + (size - 1);
@@ -1006,7 +1051,7 @@ void interp_vn_vn(float *array_tar, const float *array_src, const float t, const
}
}
-void fill_vn_i(int *array_tar, const int size, const int val)
+void copy_vn_i(int *array_tar, const int size, const int val)
{
int *tar = array_tar + (size - 1);
int i = size;
@@ -1015,7 +1060,7 @@ void fill_vn_i(int *array_tar, const int size, const int val)
}
}
-void fill_vn_short(short *array_tar, const int size, const short val)
+void copy_vn_short(short *array_tar, const int size, const short val)
{
short *tar = array_tar + (size - 1);
int i = size;
@@ -1024,7 +1069,7 @@ void fill_vn_short(short *array_tar, const int size, const short val)
}
}
-void fill_vn_ushort(unsigned short *array_tar, const int size, const unsigned short val)
+void copy_vn_ushort(unsigned short *array_tar, const int size, const unsigned short val)
{
unsigned short *tar = array_tar + (size - 1);
int i = size;
@@ -1033,7 +1078,16 @@ void fill_vn_ushort(unsigned short *array_tar, const int size, const unsigned sh
}
}
-void fill_vn_fl(float *array_tar, const int size, const float val)
+void copy_vn_uchar(unsigned char *array_tar, const int size, const unsigned char val)
+{
+ unsigned char *tar = array_tar + (size - 1);
+ int i = size;
+ while (i--) {
+ *(tar--) = val;
+ }
+}
+
+void copy_vn_fl(float *array_tar, const int size, const float val)
{
float *tar = array_tar + (size - 1);
int i = size;
@@ -1041,3 +1095,38 @@ void fill_vn_fl(float *array_tar, const int size, const float val)
*(tar--) = val;
}
}
+
+/** \name Double precision versions 'db'.
+ * \{ */
+
+void add_vn_vn_d(double *array_tar, const double *array_src, const int size)
+{
+ double *tar = array_tar + (size - 1);
+ const double *src = array_src + (size - 1);
+ int i = size;
+ while (i--) {
+ *(tar--) += *(src--);
+ }
+}
+
+void add_vn_vnvn_d(double *array_tar, const double *array_src_a, const double *array_src_b, const int size)
+{
+ double *tar = array_tar + (size - 1);
+ const double *src_a = array_src_a + (size - 1);
+ const double *src_b = array_src_b + (size - 1);
+ int i = size;
+ while (i--) {
+ *(tar--) = *(src_a--) + *(src_b--);
+ }
+}
+
+void mul_vn_db(double *array_tar, const int size, const double f)
+{
+ double *array_pt = array_tar + (size - 1);
+ int i = size;
+ while (i--) {
+ *(array_pt--) *= f;
+ }
+}
+
+/** \} */
diff --git a/source/blender/blenlib/intern/math_vector_inline.c b/source/blender/blenlib/intern/math_vector_inline.c
index 5529433f6c9..c21b09748c9 100644
--- a/source/blender/blenlib/intern/math_vector_inline.c
+++ b/source/blender/blenlib/intern/math_vector_inline.c
@@ -611,6 +611,48 @@ MINLINE void negate_v3_short(short r[3])
r[2] = (short)-r[2];
}
+MINLINE void abs_v2(float r[2])
+{
+ r[0] = fabsf(r[0]);
+ r[1] = fabsf(r[1]);
+}
+
+MINLINE void abs_v2_v2(float r[2], const float a[2])
+{
+ r[0] = fabsf(a[0]);
+ r[1] = fabsf(a[1]);
+}
+
+MINLINE void abs_v3(float r[3])
+{
+ r[0] = fabsf(r[0]);
+ r[1] = fabsf(r[1]);
+ r[2] = fabsf(r[2]);
+}
+
+MINLINE void abs_v3_v3(float r[3], const float a[3])
+{
+ r[0] = fabsf(a[0]);
+ r[1] = fabsf(a[1]);
+ r[2] = fabsf(a[2]);
+}
+
+MINLINE void abs_v4(float r[4])
+{
+ r[0] = fabsf(r[0]);
+ r[1] = fabsf(r[1]);
+ r[2] = fabsf(r[2]);
+ r[3] = fabsf(r[3]);
+}
+
+MINLINE void abs_v4_v4(float r[4], const float a[4])
+{
+ r[0] = fabsf(a[0]);
+ r[1] = fabsf(a[1]);
+ r[2] = fabsf(a[2]);
+ r[3] = fabsf(a[3]);
+}
+
MINLINE float dot_v2v2(const float a[2], const float b[2])
{
return a[0] * b[0] + a[1] * b[1];
@@ -621,11 +663,28 @@ MINLINE float dot_v3v3(const float a[3], const float b[3])
return a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
}
+MINLINE float dot_v3v3v3(const float p[3], const float a[3], const float b[3])
+{
+ float vec1[3], vec2[3];
+
+ sub_v3_v3v3(vec1, a, p);
+ sub_v3_v3v3(vec2, b, p);
+ if (is_zero_v3(vec1) || is_zero_v3(vec2)) {
+ return 0.0f;
+ }
+ return dot_v3v3(vec1, vec2);
+}
+
MINLINE float dot_v4v4(const float a[4], const float b[4])
{
return a[0] * b[0] + a[1] * b[1] + a[2] * b[2] + a[3] * b[3];
}
+MINLINE double dot_v3db_v3fl(const double a[3], const float b[3])
+{
+ return a[0] * (double)b[0] + a[1] * (double)b[1] + a[2] * (double)b[2];
+}
+
MINLINE float cross_v2v2(const float a[2], const float b[2])
{
return a[0] * b[1] - a[1] * b[0];
@@ -907,23 +966,47 @@ MINLINE bool equals_v4v4(const float v1[4], const float v2[4])
MINLINE bool compare_v2v2(const float v1[2], const float v2[2], const float limit)
{
- if (fabsf(v1[0] - v2[0]) <= limit)
- if (fabsf(v1[1] - v2[1]) <= limit)
- return true;
-
- return false;
+ return (compare_ff(v1[0], v2[0], limit) &&
+ compare_ff(v1[1], v2[1], limit));
}
MINLINE bool compare_v3v3(const float v1[3], const float v2[3], const float limit)
{
- if (fabsf(v1[0] - v2[0]) <= limit)
- if (fabsf(v1[1] - v2[1]) <= limit)
- if (fabsf(v1[2] - v2[2]) <= limit)
- return true;
+ return (compare_ff(v1[0], v2[0], limit) &&
+ compare_ff(v1[1], v2[1], limit) &&
+ compare_ff(v1[2], v2[2], limit));
+}
+
+MINLINE bool compare_v4v4(const float v1[4], const float v2[4], const float limit)
+{
+ return (compare_ff(v1[0], v2[0], limit) &&
+ compare_ff(v1[1], v2[1], limit) &&
+ compare_ff(v1[2], v2[2], limit) &&
+ compare_ff(v1[3], v2[3], limit));
+}
+
+MINLINE bool compare_v2v2_relative(const float v1[2], const float v2[2], const float limit, const int max_ulps)
+{
+ return (compare_ff_relative(v1[0], v2[0], limit, max_ulps) &&
+ compare_ff_relative(v1[1], v2[1], limit, max_ulps));
+}
+
+MINLINE bool compare_v3v3_relative(const float v1[3], const float v2[3], const float limit, const int max_ulps)
+{
+ return (compare_ff_relative(v1[0], v2[0], limit, max_ulps) &&
+ compare_ff_relative(v1[1], v2[1], limit, max_ulps) &&
+ compare_ff_relative(v1[2], v2[2], limit, max_ulps));
+}
- return false;
+MINLINE bool compare_v4v4_relative(const float v1[4], const float v2[4], const float limit, const int max_ulps)
+{
+ return (compare_ff_relative(v1[0], v2[0], limit, max_ulps) &&
+ compare_ff_relative(v1[1], v2[1], limit, max_ulps) &&
+ compare_ff_relative(v1[2], v2[2], limit, max_ulps) &&
+ compare_ff_relative(v1[3], v2[3], limit, max_ulps));
}
+
MINLINE bool compare_len_v3v3(const float v1[3], const float v2[3], const float limit)
{
float x, y, z;
@@ -946,17 +1029,18 @@ MINLINE bool compare_len_squared_v3v3(const float v1[3], const float v2[3], cons
return ((x * x + y * y + z * z) <= limit_sq);
}
-MINLINE bool compare_v4v4(const float v1[4], const float v2[4], const float limit)
-{
- if (fabsf(v1[0] - v2[0]) <= limit)
- if (fabsf(v1[1] - v2[1]) <= limit)
- if (fabsf(v1[2] - v2[2]) <= limit)
- if (fabsf(v1[3] - v2[3]) <= limit)
- return true;
-
- return false;
-}
-
+/**
+ * <pre>
+ * + l1
+ * |
+ * neg <- | -> pos
+ * |
+ * + l2
+ * </pre>
+ *
+ * \return Positive value when 'pt' is left-of-line
+ * (looking from 'l1' -> 'l2').
+ */
MINLINE float line_point_side_v2(const float l1[2], const float l2[2], const float pt[2])
{
return (((l1[0] - pt[0]) * (l2[1] - pt[1])) -
diff --git a/source/blender/blenlib/intern/noise.c b/source/blender/blenlib/intern/noise.c
index f002ea54b32..4b2ad834d75 100644
--- a/source/blender/blenlib/intern/noise.c
+++ b/source/blender/blenlib/intern/noise.c
@@ -278,8 +278,8 @@ static float npfade(float t)
static float grad(int hash_val, float x, float y, float z)
{
int h = hash_val & 15; /* CONVERT LO 4 BITS OF HASH CODE */
- float u = h < 8 ? x : y, /* INTO 12 GRADIENT DIRECTIONS. */
- v = h < 4 ? y : h == 12 || h == 14 ? x : z;
+ float u = h < 8 ? x : y; /* INTO 12 GRADIENT DIRECTIONS. */
+ float v = h < 4 ? y : h == 12 || h == 14 ? x : z;
return ((h & 1) == 0 ? u : -u) + ((h & 2) == 0 ? v : -v);
}
@@ -1546,7 +1546,7 @@ float BLI_gTurbulence(float noisesize, float x, float y, float z, int oct, int h
/*
* The following code is based on Ken Musgrave's explanations and sample
- * source code in the book "Texturing and Modelling: A procedural approach"
+ * source code in the book "Texturing and Modeling: A procedural approach"
*/
/*
diff --git a/source/blender/blenlib/intern/path_util.c b/source/blender/blenlib/intern/path_util.c
index d5af980e373..4692af0ffa7 100644
--- a/source/blender/blenlib/intern/path_util.c
+++ b/source/blender/blenlib/intern/path_util.c
@@ -45,12 +45,6 @@
#include "BLI_string_utf8.h"
#include "BLI_fnmatch.h"
-#include "../blenkernel/BKE_blender.h" /* BLENDER_VERSION, bad level include (no function call) */
-
-#include "GHOST_Path-api.h"
-
-#include "MEM_guardedalloc.h"
-
#ifdef WIN32
# include "utf_winfunc.h"
# include "utfconv.h"
@@ -62,20 +56,24 @@
# include <windows.h>
# include <shlobj.h>
# include "BLI_winstuff.h"
-#else /* non windows */
-# ifdef WITH_BINRELOC
-# include "binreloc.h"
-# endif
-# include <unistd.h> /* mkdtemp on OSX (and probably all *BSD?), not worth making specific check for this OS. */
+# include "BLI_alloca.h"
+#else
+# include "unistd.h"
#endif /* WIN32 */
+#include "MEM_guardedalloc.h"
+
/* local */
#define UNIQUE_NAME_MAX 128
-static char bprogname[FILE_MAX]; /* full path to program executable */
-static char bprogdir[FILE_MAX]; /* full path to directory in which executable is located */
-static char btempdir_base[FILE_MAX]; /* persistent temporary directory */
-static char btempdir_session[FILE_MAX] = ""; /* volatile temporary directory */
+/* Declarations */
+
+#ifdef WIN32
+
+/* return true if the path is absolute ie starts with a drive specifier (eg A:\) or is a UNC path */
+static bool BLI_path_is_abs(const char *name);
+
+#endif /* WIN32 */
/* implementation */
@@ -243,7 +241,8 @@ bool BLI_uniquename_cb(bool (*unique_check)(void *arg, const char *name),
int number;
int len = BLI_split_name_num(left, &number, name, delim);
do {
- const int numlen = BLI_snprintf(numstr, sizeof(numstr), "%c%03d", delim, ++number);
+ /* add 1 to account for \0 */
+ const int numlen = BLI_snprintf(numstr, sizeof(numstr), "%c%03d", delim, ++number) + 1;
/* highly unlikely the string only has enough room for the number
* but support anyway */
@@ -253,9 +252,8 @@ bool BLI_uniquename_cb(bool (*unique_check)(void *arg, const char *name),
}
else {
char *tempname_buf;
- tempname[0] = '\0';
- tempname_buf = BLI_strncat_utf8(tempname, left, name_len - numlen);
- memcpy(tempname_buf, numstr, numlen + 1);
+ tempname_buf = tempname + BLI_strncpy_utf8_rlen(tempname, left, name_len - numlen);
+ memcpy(tempname_buf, numstr, numlen);
}
} while (unique_check(arg, tempname));
@@ -305,7 +303,7 @@ static bool uniquename_unique_check(void *arg, const char *name)
/**
* Ensures that the specified block has a unique name within the containing list,
- * incrementing its numeric suffix as necessary.
+ * incrementing its numeric suffix as necessary. Returns true if name had to be adjusted.
*
* \param list List containing the block
* \param vlink The block to check the name for
@@ -314,7 +312,7 @@ 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, int name_offs, int name_len)
+bool BLI_uniquename(ListBase *list, void *vlink, const char *defname, char delim, int name_offs, int name_len)
{
struct {ListBase *lb; void *vlink; int name_offs; } data;
data.lb = list;
@@ -325,9 +323,9 @@ void BLI_uniquename(ListBase *list, void *vlink, const char *defname, char delim
/* See if we are given an empty string */
if (ELEM(NULL, vlink, defname))
- return;
+ return false;
- BLI_uniquename_cb(uniquename_unique_check, &data, defname, delim, GIVE_STRADDR(vlink, name_offs), name_len);
+ return BLI_uniquename_cb(uniquename_unique_check, &data, defname, delim, GIVE_STRADDR(vlink, name_offs), name_len);
}
static int BLI_path_unc_prefix_len(const char *path); /* defined below in same file */
@@ -361,7 +359,7 @@ void BLI_cleanup_path(const char *relabase, char *path)
/* Note
* memmove(start, eind, strlen(eind) + 1);
* is the same as
- * strcpy( start, eind );
+ * strcpy(start, eind);
* except strcpy should not be used because there is overlap,
* so use memmove's slightly more obscure syntax - Campbell
*/
@@ -443,6 +441,127 @@ void BLI_cleanup_file(const char *relabase, char *path)
BLI_del_slash(path);
}
+
+/**
+ * Make given name safe to be used in paths.
+ *
+ * \return true if \a fname was changed, false otherwise.
+ *
+ * For now, simply replaces reserved chars (as listed in
+ * http://en.wikipedia.org/wiki/Filename#Reserved_characters_and_words )
+ * by underscores ('_').
+ *
+ * \note Space case ' ' is a bit of an edge case here - in theory it is allowed, but again can be an issue
+ * in some cases, so we simply replace it by an underscore too (good practice anyway).
+ *
+ * \note On Windows, it also ensures there is no '.' (dot char) at the end of the file, this can lead to issues...
+ *
+ * \note On Windows, it also checks for forbidden names
+ * (see https://msdn.microsoft.com/en-us/library/windows/desktop/aa365247%28v=vs.85%29.aspx ).
+ */
+bool BLI_filename_make_safe(char *fname)
+{
+ const char *invalid = "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
+ "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f"
+ "/\\?%*:|\"<> ";
+ char *fn;
+ bool changed = false;
+
+ if (*fname == '\0') {
+ return changed;
+ }
+
+ for (fn = fname; *fn && (fn = strpbrk(fn, invalid)); fn++) {
+ *fn = '_';
+ changed = true;
+ }
+
+ /* Forbid only dots. */
+ for (fn = fname; *fn == '.'; fn++);
+ if (*fn == '\0') {
+ *fname = '_';
+ changed = true;
+ }
+
+#ifdef WIN32
+ {
+ const size_t len = strlen(fname);
+ const char *invalid_names[] = {
+ "con", "prn", "aux", "null",
+ "com1", "com2", "com3", "com4", "com5", "com6", "com7", "com8", "com9",
+ "lpt1", "lpt2", "lpt3", "lpt4", "lpt5", "lpt6", "lpt7", "lpt8", "lpt9",
+ NULL
+ };
+ char *lower_fname = BLI_strdup(fname);
+ const char **iname;
+
+ /* Forbid trailing dot (trailing space has already been replaced above). */
+ if (fname[len - 1] == '.') {
+ fname[len - 1] = '_';
+ changed = true;
+ }
+
+ /* Check for forbidden names - not we have to check all combination of upper and lower cases, hence the usage
+ * of lower_fname (more efficient than using BLI_strcasestr repeatedly). */
+ BLI_str_tolower_ascii(lower_fname, len);
+ for (iname = invalid_names; *iname; iname++) {
+ if (strstr(lower_fname, *iname) == lower_fname) {
+ const size_t iname_len = strlen(*iname);
+ /* Only invalid if the whole name is made of the invalid chunk, or it has an (assumed extension) dot
+ * just after. This means it will also catch 'valid' names like 'aux.foo.bar', but should be
+ * good enough for us! */
+ if ((iname_len == len) || (lower_fname[iname_len] == '.')) {
+ *fname = '_';
+ changed = true;
+ break;
+ }
+ }
+ }
+
+ MEM_freeN(lower_fname);
+ }
+#endif
+
+ return changed;
+}
+
+/**
+ * Make given path OS-safe.
+ *
+ * \return true if \a path was changed, false otherwise.
+ */
+bool BLI_path_make_safe(char *path)
+{
+ /* Simply apply BLI_filename_make_safe() over each component of the path.
+ * Luckily enough, same 'sfae' rules applies to filenames and dirnames. */
+ char *curr_slash, *curr_path = path;
+ bool changed = false;
+ bool skip_first = false;
+
+#ifdef WIN32
+ if (BLI_path_is_abs(path)) {
+ /* Do not make safe 'C:' in 'C:\foo\bar'... */
+ skip_first = true;
+ }
+#endif
+
+ for (curr_slash = (char *)BLI_first_slash(curr_path); curr_slash; curr_slash = (char *)BLI_first_slash(curr_path)) {
+ const char backup = *curr_slash;
+ *curr_slash = '\0';
+ if (!skip_first && (*curr_path != '\0') && BLI_filename_make_safe(curr_path)) {
+ changed = true;
+ }
+ skip_first = false;
+ curr_path = curr_slash + 1;
+ *curr_slash = backup;
+ }
+ if (BLI_filename_make_safe(curr_path)) {
+ changed = true;
+ }
+
+ return changed;
+}
+
/**
* Does path begin with the special "//" prefix that Blender uses to indicate
* a path relative to the .blend file.
@@ -618,8 +737,8 @@ void BLI_path_rel(char *file, const char *relfile)
BLI_strncpy(temp, relfile, FILE_MAX);
#endif
- BLI_char_switch(temp + BLI_path_unc_prefix_len(temp), '\\', '/');
- BLI_char_switch(file + BLI_path_unc_prefix_len(file), '\\', '/');
+ BLI_str_replace_char(temp + BLI_path_unc_prefix_len(temp), '\\', '/');
+ BLI_str_replace_char(file + BLI_path_unc_prefix_len(file), '\\', '/');
/* remove /./ which confuse the following slash counting... */
BLI_cleanup_path(NULL, file);
@@ -680,7 +799,7 @@ void BLI_path_rel(char *file, const char *relfile)
r += BLI_strcpy_rlen(r, q + 1);
#ifdef WIN32
- BLI_char_switch(res + 2, '/', '\\');
+ BLI_str_replace_char(res + 2, '/', '\\');
#endif
strcpy(file, res);
}
@@ -741,7 +860,7 @@ bool BLI_parent_dir(char *path)
BLI_cleanup_dir(NULL, tmp); /* does all the work of normalizing the path for us */
if (!BLI_testextensie(tmp, parent_dir)) {
- BLI_strncpy(path, tmp, sizeof(tmp));
+ strcpy(path, tmp); /* We assume pardir is always shorter... */
return true;
}
else {
@@ -854,6 +973,111 @@ bool BLI_path_frame_range(char *path, int sta, int end, int digits)
}
/**
+ * Get the frame from a filename formatted by blender's frame scheme
+ */
+bool BLI_path_frame_get(char *path, int *r_frame, int *r_numdigits)
+{
+ if (path && *path) {
+ char *file = (char *)BLI_last_slash(path);
+ char *c;
+ int len, numdigits;
+
+ numdigits = *r_numdigits = 0;
+
+ if (file == NULL)
+ file = path;
+
+ /* first get the extension part */
+ len = strlen(file);
+
+ c = file + len;
+
+ /* isolate extension */
+ while (--c != file) {
+ if (*c == '.') {
+ c--;
+ break;
+ }
+ }
+
+ /* find start of number */
+ while (c != (file - 1) && isdigit(*c)) {
+ c--;
+ numdigits++;
+ }
+
+ if (numdigits) {
+ char prevchar;
+
+ c++;
+ prevchar = c[numdigits];
+ c[numdigits] = 0;
+
+ /* was the number really an extension? */
+ *r_frame = atoi(c);
+ c[numdigits] = prevchar;
+
+ *r_numdigits = numdigits;
+
+ return true;
+ }
+ }
+
+ return false;
+}
+
+void BLI_path_frame_strip(char *path, bool setsharp, char *ext)
+{
+ if (path && *path) {
+ char *file = (char *)BLI_last_slash(path);
+ char *c, *suffix;
+ int len;
+ int numdigits = 0;
+
+ if (file == NULL)
+ file = path;
+
+ /* first get the extension part */
+ len = strlen(file);
+
+ c = file + len;
+
+ /* isolate extension */
+ while (--c != file) {
+ if (*c == '.') {
+ c--;
+ break;
+ }
+ }
+
+ suffix = c + 1;
+
+ /* find start of number */
+ while (c != (file - 1) && isdigit(*c)) {
+ c--;
+ numdigits++;
+ }
+
+ c++;
+
+ if (numdigits) {
+ /* replace the number with the suffix and terminate the string */
+ while (numdigits--) {
+ if (ext) *ext++ = *suffix;
+
+ if (setsharp) *c++ = '#';
+ else *c++ = *suffix;
+
+ suffix++;
+ }
+ *c = 0;
+ if (ext) *ext = 0;
+ }
+ }
+}
+
+
+/**
* Check if we have '#' chars, usable for #BLI_path_frame, #BLI_path_frame_range
*/
bool BLI_path_frame_check_chars(const char *path)
@@ -922,7 +1146,7 @@ bool BLI_path_abs(char *path, const char *basepath)
* For UNC paths the first characters containing the UNC prefix
* shouldn't be switched as we need to distinguish them from
* paths relative to the .blend file -elubie */
- BLI_char_switch(tmp + BLI_path_unc_prefix_len(tmp), '\\', '/');
+ BLI_str_replace_char(tmp + BLI_path_unc_prefix_len(tmp), '\\', '/');
/* Paths starting with // will get the blend file as their base,
* this isn't standard in any os but is used in blender all over the place */
@@ -933,7 +1157,7 @@ bool BLI_path_abs(char *path, const char *basepath)
/* file component is ignored, so don't bother with the trailing slash */
BLI_cleanup_path(NULL, base);
lslash = BLI_last_slash(base);
- BLI_char_switch(base + BLI_path_unc_prefix_len(base), '\\', '/');
+ BLI_str_replace_char(base + BLI_path_unc_prefix_len(base), '\\', '/');
if (lslash) {
const int baselen = (int) (lslash - base) + 1; /* length up to and including last "/" */
@@ -954,8 +1178,6 @@ bool BLI_path_abs(char *path, const char *basepath)
BLI_strncpy(path, tmp, FILE_MAX);
}
- BLI_cleanup_path(NULL, path);
-
#ifdef WIN32
/* skip first two chars, which in case of
* absolute path will be drive:/blabla and
@@ -963,9 +1185,12 @@ bool BLI_path_abs(char *path, const char *basepath)
* // will be retained, rest will be nice and
* shiny win32 backward slashes :) -jesterKing
*/
- BLI_char_switch(path + 2, '/', '\\');
+ BLI_str_replace_char(path + 2, '/', '\\');
#endif
-
+
+ /* ensure this is after correcting for path switch */
+ BLI_cleanup_path(NULL, path);
+
return wasrelative;
}
@@ -1015,469 +1240,137 @@ bool BLI_path_cwd(char *path)
return wasrelative;
}
+#ifdef _WIN32
/**
- * Copies into *last the part of *dir following the second-last slash.
- */
-void BLI_getlastdir(const char *dir, char *last, const size_t maxlen)
-{
- const char *s = dir;
- const char *lslash = NULL;
- const char *prevslash = NULL;
- while (*s) {
- if ((*s == '\\') || (*s == '/')) {
- prevslash = lslash;
- lslash = s;
- }
- s++;
- }
- if (prevslash) {
- BLI_strncpy(last, prevslash + 1, maxlen);
- }
- else {
- BLI_strncpy(last, dir, maxlen);
- }
-}
-
-/* This is now only used to really get the user's default document folder */
-/* On Windows I chose the 'Users/<MyUserName>/Documents' since it's used
- * as default location to save documents */
-const char *BLI_getDefaultDocumentFolder(void)
-{
-#ifndef WIN32
- const char * const xdg_documents_dir = getenv("XDG_DOCUMENTS_DIR");
-
- if (xdg_documents_dir)
- return xdg_documents_dir;
-
- return getenv("HOME");
-#else /* Windows */
- static char documentfolder[MAXPATHLEN];
- HRESULT hResult;
-
- /* Check for %HOME% env var */
- if (uput_getenv("HOME", documentfolder, MAXPATHLEN)) {
- if (BLI_is_dir(documentfolder)) return documentfolder;
- }
-
- /* add user profile support for WIN 2K / NT.
- * This is %APPDATA%, which translates to either
- * %USERPROFILE%\Application Data or since Vista
- * to %USERPROFILE%\AppData\Roaming
- */
- hResult = SHGetFolderPath(NULL, CSIDL_PERSONAL, NULL, SHGFP_TYPE_CURRENT, documentfolder);
-
- if (hResult == S_OK) {
- if (BLI_is_dir(documentfolder)) return documentfolder;
- }
-
- return NULL;
-#endif /* WIN32 */
-}
-
-/* NEW stuff, to be cleaned up when fully migrated */
-/* ************************************************************* */
-/* ************************************************************* */
-
-// #define PATH_DEBUG
-
-/* returns a formatted representation of the specified version number. Non-reentrant! */
-static char *blender_version_decimal(const int ver)
-{
- static char version_str[5];
- sprintf(version_str, "%d.%02d", ver / 100, ver % 100);
- return version_str;
-}
-
-/**
- * Concatenates path_base, (optional) path_sep and (optional) folder_name into targetpath,
- * returning true if result points to a directory.
- */
-static bool test_path(char *targetpath, const char *path_base, const char *path_sep, const char *folder_name)
-{
- char tmppath[FILE_MAX];
-
- if (path_sep) BLI_join_dirfile(tmppath, sizeof(tmppath), path_base, path_sep);
- else BLI_strncpy(tmppath, path_base, sizeof(tmppath));
-
- /* rare cases folder_name is omitted (when looking for ~/.blender/2.xx dir only) */
- if (folder_name)
- BLI_make_file_string("/", targetpath, tmppath, folder_name);
- else
- BLI_strncpy(targetpath, tmppath, sizeof(tmppath));
- /* FIXME: why is "//" on front of tmppath expanded to "/" (by BLI_join_dirfile)
- * if folder_name is specified but not otherwise? */
-
- if (BLI_is_dir(targetpath)) {
-#ifdef PATH_DEBUG
- printf("\t%s found: %s\n", __func__, targetpath);
-#endif
- return true;
- }
- else {
-#ifdef PATH_DEBUG
- printf("\t%s missing: %s\n", __func__, targetpath);
-#endif
- //targetpath[0] = '\0';
- return false;
- }
-}
-
-/**
- * Puts the value of the specified environment variable into *path if it exists
- * and points at a directory. Returns true if this was done.
+ * Tries appending each of the semicolon-separated extensions in the PATHEXT
+ * environment variable (Windows-only) onto *name in turn until such a file is found.
+ * Returns success/failure.
*/
-static bool test_env_path(char *path, const char *envvar)
+bool BLI_path_program_extensions_add_win32(char *name, const size_t maxlen)
{
- const char *env = envvar ? getenv(envvar) : NULL;
- if (!env) return false;
-
- if (BLI_is_dir(env)) {
- BLI_strncpy(path, env, FILE_MAX);
-#ifdef PATH_DEBUG
- printf("\t%s env %s found: %s\n", __func__, envvar, env);
-#endif
- return true;
- }
- else {
- path[0] = '\0';
-#ifdef PATH_DEBUG
- printf("\t%s env %s missing: %s\n", __func__, envvar, env);
-#endif
- return false;
- }
-}
+ bool retval = false;
+ int type;
-/**
- * Constructs in \a targetpath the name of a directory relative to a version-specific
- * subdirectory in the parent directory of the Blender executable.
- *
- * \param targetpath String to return path
- * \param folder_name Optional folder name within version-specific directory
- * \param subfolder_name Optional subfolder name within folder_name
- * \param ver To construct name of version-specific directory within bprogdir
- * \return true if such a directory exists.
- */
-static bool get_path_local(char *targetpath, const char *folder_name, const char *subfolder_name, const int ver)
-{
- char relfolder[FILE_MAX];
-
-#ifdef PATH_DEBUG
- printf("%s...\n", __func__);
-#endif
+ type = BLI_exists(name);
+ if ((type == 0) || S_ISDIR(type)) {
+ /* typically 3-5, ".EXE", ".BAT"... etc */
+ const int ext_max = 12;
+ const char *ext = getenv("PATHEXT");
+ if (ext) {
+ const int name_len = strlen(name);
+ char *filename = alloca(name_len + ext_max);
+ char *filename_ext;
+ const char *ext_next;
+
+ /* null terminated in the loop */
+ memcpy(filename, name, name_len);
+ filename_ext = filename + name_len;
- if (folder_name) {
- if (subfolder_name) {
- BLI_join_dirfile(relfolder, sizeof(relfolder), folder_name, subfolder_name);
- }
- else {
- BLI_strncpy(relfolder, folder_name, sizeof(relfolder));
+ do {
+ int ext_len;
+ ext_next = strchr(ext, ';');
+ ext_len = ext_next ? ((ext_next++) - ext) : strlen(ext);
+
+ if (LIKELY(ext_len < ext_max)) {
+ memcpy(filename_ext, ext, ext_len);
+ filename_ext[ext_len] = '\0';
+
+ type = BLI_exists(filename);
+ if (type && (!S_ISDIR(type))) {
+ retval = true;
+ BLI_strncpy(name, filename, maxlen);
+ break;
+ }
+ }
+ } while ((ext = ext_next));
}
}
else {
- relfolder[0] = '\0';
+ retval = true;
}
- /* try EXECUTABLE_DIR/2.5x/folder_name - new default directory for local blender installed files */
-#ifdef __APPLE__
- static char osx_resourses[FILE_MAX]; /* due new codesign situation in OSX > 10.9.5 we must move the blender_version dir with contents to Resources */
- sprintf(osx_resourses, "%s../Resources", bprogdir);
- return test_path(targetpath, osx_resourses, blender_version_decimal(ver), relfolder);
-#else
- return test_path(targetpath, bprogdir, blender_version_decimal(ver), relfolder);
-#endif
-}
-
-/**
- * Is this an install with user files kept together with the Blender executable and its
- * installation files.
- */
-static bool is_portable_install(void)
-{
- /* detect portable install by the existence of config folder */
- const int ver = BLENDER_VERSION;
- char path[FILE_MAX];
-
- return get_path_local(path, "config", NULL, ver);
+ return retval;
}
+#endif /* WIN32 */
/**
- * Returns the path of a folder within the user-files area.
- *
- *
- * \param targetpath String to return path
- * \param folder_name default name of folder within user area
- * \param subfolder_name optional name of subfolder within folder
- * \param envvar name of environment variable which, if defined, overrides folder_name
- * \param ver Blender version, used to construct a subdirectory name
- * \return true if it was able to construct such a path.
+ * Search for a binary (executable)
*/
-static bool get_path_user(char *targetpath, const char *folder_name, const char *subfolder_name, const char *envvar, const int ver)
+bool BLI_path_program_search(
+ char *fullname, const size_t maxlen,
+ const char *name)
{
- char user_path[FILE_MAX];
- const char *user_base_path;
-
- /* for portable install, user path is always local */
- if (is_portable_install())
- return get_path_local(targetpath, folder_name, subfolder_name, ver);
-
- user_path[0] = '\0';
-
- if (test_env_path(user_path, envvar)) {
- if (subfolder_name) {
- return test_path(targetpath, user_path, NULL, subfolder_name);
- }
- else {
- BLI_strncpy(targetpath, user_path, FILE_MAX);
- return true;
- }
- }
-
- user_base_path = (const char *)GHOST_getUserDir(ver, blender_version_decimal(ver));
- if (user_base_path)
- BLI_strncpy(user_path, user_base_path, FILE_MAX);
+ const char *path;
+ bool retval = false;
- if (!user_path[0])
- return false;
-
-#ifdef PATH_DEBUG
- printf("%s: %s\n", __func__, user_path);
+#ifdef _WIN32
+ const char separator = ';';
+#else
+ const char separator = ':';
#endif
-
- if (subfolder_name) {
- return test_path(targetpath, user_path, folder_name, subfolder_name);
- }
- else {
- return test_path(targetpath, user_path, NULL, folder_name);
- }
-}
-
-/**
- * Returns the path of a folder within the Blender installation directory.
- *
- * \param targetpath String to return path
- * \param folder_name default name of folder within installation area
- * \param subfolder_name optional name of subfolder within folder
- * \param envvar name of environment variable which, if defined, overrides folder_name
- * \param ver Blender version, used to construct a subdirectory name
- * \return true if it was able to construct such a path.
- */
-static bool get_path_system(char *targetpath, const char *folder_name, const char *subfolder_name, const char *envvar, const int ver)
-{
- char system_path[FILE_MAX];
- const char *system_base_path;
- char cwd[FILE_MAX];
- char relfolder[FILE_MAX];
-
- if (folder_name) {
- if (subfolder_name) {
- BLI_join_dirfile(relfolder, sizeof(relfolder), folder_name, subfolder_name);
- }
- else {
- BLI_strncpy(relfolder, folder_name, sizeof(relfolder));
- }
- }
- else {
- relfolder[0] = '\0';
- }
-
- /* first allow developer only overrides to the system path
- * these are only used when running blender from source */
-
- /* try CWD/release/folder_name */
- if (BLI_current_working_dir(cwd, sizeof(cwd))) {
- if (test_path(targetpath, cwd, "release", relfolder)) {
- return true;
- }
- }
-
- /* try EXECUTABLE_DIR/release/folder_name */
- if (test_path(targetpath, bprogdir, "release", relfolder))
- return true;
-
- /* end developer overrides */
-
-
- system_path[0] = '\0';
+ path = getenv("PATH");
+ if (path) {
+ char filename[FILE_MAX];
+ const char *temp;
- if (test_env_path(system_path, envvar)) {
- if (subfolder_name) {
- return test_path(targetpath, system_path, NULL, subfolder_name);
- }
- else {
- BLI_strncpy(targetpath, system_path, FILE_MAX);
- return true;
- }
- }
+ do {
+ temp = strchr(path, separator);
+ if (temp) {
+ strncpy(filename, path, temp - path);
+ filename[temp - path] = 0;
+ path = temp + 1;
+ }
+ else {
+ strncpy(filename, path, sizeof(filename));
+ }
- system_base_path = (const char *)GHOST_getSystemDir(ver, blender_version_decimal(ver));
- if (system_base_path)
- BLI_strncpy(system_path, system_base_path, FILE_MAX);
-
- if (!system_path[0])
- return false;
-
-#ifdef PATH_DEBUG
- printf("%s: %s\n", __func__, system_path);
+ BLI_path_append(filename, maxlen, name);
+ if (
+#ifdef _WIN32
+ BLI_path_program_extensions_add_win32(filename, maxlen)
+#else
+ BLI_exists(filename)
#endif
-
- if (subfolder_name) {
- /* try $BLENDERPATH/folder_name/subfolder_name */
- return test_path(targetpath, system_path, folder_name, subfolder_name);
- }
- else {
- /* try $BLENDERPATH/folder_name */
- return test_path(targetpath, system_path, NULL, folder_name);
- }
-}
-
-/* get a folder out of the 'folder_id' presets for paths */
-/* returns the path if found, NULL string if not */
-const char *BLI_get_folder(int folder_id, const char *subfolder)
-{
- const int ver = BLENDER_VERSION;
- static char path[FILE_MAX] = "";
-
- switch (folder_id) {
- case BLENDER_DATAFILES: /* general case */
- if (get_path_user(path, "datafiles", subfolder, "BLENDER_USER_DATAFILES", ver)) break;
- if (get_path_local(path, "datafiles", subfolder, ver)) break;
- if (get_path_system(path, "datafiles", subfolder, "BLENDER_SYSTEM_DATAFILES", ver)) break;
- return NULL;
-
- case BLENDER_USER_DATAFILES:
- if (get_path_user(path, "datafiles", subfolder, "BLENDER_USER_DATAFILES", ver)) break;
- return NULL;
-
- case BLENDER_SYSTEM_DATAFILES:
- if (get_path_local(path, "datafiles", subfolder, ver)) break;
- if (get_path_system(path, "datafiles", subfolder, "BLENDER_SYSTEM_DATAFILES", ver)) break;
- return NULL;
-
- case BLENDER_USER_AUTOSAVE:
- if (get_path_user(path, "autosave", subfolder, "BLENDER_USER_DATAFILES", ver)) break;
- return NULL;
-
- case BLENDER_USER_CONFIG:
- if (get_path_user(path, "config", subfolder, "BLENDER_USER_CONFIG", ver)) break;
- return NULL;
-
- case BLENDER_USER_SCRIPTS:
- if (get_path_user(path, "scripts", subfolder, "BLENDER_USER_SCRIPTS", ver)) break;
- return NULL;
-
- case BLENDER_SYSTEM_SCRIPTS:
- if (get_path_local(path, "scripts", subfolder, ver)) break;
- if (get_path_system(path, "scripts", subfolder, "BLENDER_SYSTEM_SCRIPTS", ver)) break;
- return NULL;
-
- case BLENDER_SYSTEM_PYTHON:
- if (get_path_local(path, "python", subfolder, ver)) break;
- if (get_path_system(path, "python", subfolder, "BLENDER_SYSTEM_PYTHON", ver)) break;
- return NULL;
-
- default:
- BLI_assert(0);
- break;
+ )
+ {
+ BLI_strncpy(fullname, filename, maxlen);
+ retval = true;
+ break;
+ }
+ } while (temp);
}
-
- return path;
-}
-/**
- * Returns the path to a folder in the user area without checking that it actually exists first.
- */
-const char *BLI_get_user_folder_notest(int folder_id, const char *subfolder)
-{
- const int ver = BLENDER_VERSION;
- static char path[FILE_MAX] = "";
-
- switch (folder_id) {
- case BLENDER_USER_DATAFILES:
- get_path_user(path, "datafiles", subfolder, "BLENDER_USER_DATAFILES", ver);
- break;
- case BLENDER_USER_CONFIG:
- get_path_user(path, "config", subfolder, "BLENDER_USER_CONFIG", ver);
- break;
- case BLENDER_USER_AUTOSAVE:
- get_path_user(path, "autosave", subfolder, "BLENDER_USER_AUTOSAVE", ver);
- break;
- case BLENDER_USER_SCRIPTS:
- get_path_user(path, "scripts", subfolder, "BLENDER_USER_SCRIPTS", ver);
- break;
- default:
- BLI_assert(0);
- break;
+ if (retval == false) {
+ *fullname = '\0';
}
- if ('\0' == path[0]) {
- return NULL;
- }
- return path;
+ return retval;
}
/**
- * Returns the path to a folder in the user area, creating it if it doesn't exist.
+ * Copies into *last the part of *dir following the second-last slash.
*/
-const char *BLI_get_folder_create(int folder_id, const char *subfolder)
+void BLI_getlastdir(const char *dir, char *last, const size_t maxlen)
{
- const char *path;
-
- /* only for user folders */
- if (!ELEM(folder_id, BLENDER_USER_DATAFILES, BLENDER_USER_CONFIG, BLENDER_USER_SCRIPTS, BLENDER_USER_AUTOSAVE))
- return NULL;
-
- path = BLI_get_folder(folder_id, subfolder);
-
- if (!path) {
- path = BLI_get_user_folder_notest(folder_id, subfolder);
- if (path) BLI_dir_create_recursive(path);
+ const char *s = dir;
+ const char *lslash = NULL;
+ const char *prevslash = NULL;
+ while (*s) {
+ if ((*s == '\\') || (*s == '/')) {
+ prevslash = lslash;
+ lslash = s;
+ }
+ s++;
}
-
- return path;
-}
-
-/**
- * Returns the path of the top-level version-specific local, user or system directory.
- * If do_check, then the result will be NULL if the directory doesn't exist.
- */
-const char *BLI_get_folder_version(const int id, const int ver, const bool do_check)
-{
- static char path[FILE_MAX] = "";
- bool ok;
- switch (id) {
- case BLENDER_RESOURCE_PATH_USER:
- ok = get_path_user(path, NULL, NULL, NULL, ver);
- break;
- case BLENDER_RESOURCE_PATH_LOCAL:
- ok = get_path_local(path, NULL, NULL, ver);
- break;
- case BLENDER_RESOURCE_PATH_SYSTEM:
- ok = get_path_system(path, NULL, NULL, NULL, ver);
- break;
- default:
- path[0] = '\0'; /* in case do_check is false */
- ok = false;
- BLI_assert(!"incorrect ID");
- break;
+ if (prevslash) {
+ BLI_strncpy(last, prevslash + 1, maxlen);
}
-
- if (!ok && do_check) {
- return NULL;
+ else {
+ BLI_strncpy(last, dir, maxlen);
}
-
- return path;
}
-/* End new stuff */
-/* ************************************************************* */
-/* ************************************************************* */
-
-
-
-#ifdef PATH_DEBUG
-# undef PATH_DEBUG
-#endif
/**
* Sets the specified environment variable to the specified value,
@@ -1525,50 +1418,23 @@ void BLI_setenv_if_new(const char *env, const char *val)
}
/**
- * Change every \a from in \a string into \a to. The
- * result will be in \a string
- *
- * \param string The string to work on
- * \param from The character to replace
- * \param to The character to replace with
- */
-void BLI_char_switch(char *string, char from, char to)
-{
- while (*string != 0) {
- if (*string == from) *string = to;
- string++;
- }
-}
-
-/**
- * Strips off nonexistent subdirectories from the end of *dir, leaving the path of
- * the lowest-level directory that does exist.
+ * Strips off nonexistent (or non-accessible) subdirectories from the end of *dir, leaving the path of
+ * the lowest-level directory that does exist and we can read.
*/
void BLI_make_exist(char *dir)
{
- int a;
-
- BLI_char_switch(dir, ALTSEP, SEP);
+ bool valid_path = true;
- a = strlen(dir);
+ /* Loop as long as cur path is not a dir, and we can get a parent path. */
+ while ((BLI_access(dir, R_OK) != 0) && (valid_path = BLI_parent_dir(dir)));
- while (!BLI_is_dir(dir)) {
- a--;
- while (dir[a] != SEP) {
- a--;
- if (a <= 0) break;
- }
- if (a >= 0) {
- dir[a + 1] = '\0';
- }
- else {
+ /* If we could not find an existing dir, use default root... */
+ if (!valid_path || !dir[0]) {
#ifdef WIN32
- get_default_root(dir);
+ get_default_root(dir);
#else
- strcpy(dir, "/");
+ strcpy(dir, "/");
#endif
- break;
- }
}
}
@@ -1580,7 +1446,7 @@ void BLI_make_existing_file(const char *name)
char di[FILE_MAX];
BLI_split_dir_part(name, di, sizeof(di));
- /* make if if the dir doesn't exist */
+ /* make if the dir doesn't exist */
BLI_dir_create_recursive(di);
}
@@ -1614,9 +1480,9 @@ void BLI_make_file_string(const char *relabase, char *string, const char *dir, c
* any mess with slashes later on. -jesterKing */
/* constant strings can be passed for those parameters - don't change them - elubie */
#if 0
- BLI_char_switch(relabase, '\\', '/');
- BLI_char_switch(dir, '\\', '/');
- BLI_char_switch(file, '\\', '/');
+ BLI_str_replace_char(relabase, '\\', '/');
+ BLI_str_replace_char(dir, '\\', '/');
+ BLI_str_replace_char(file, '\\', '/');
#endif
/* Resolve relative references */
@@ -1707,11 +1573,10 @@ bool BLI_testextensie_n(const char *str, ...)
while ((ext = (const char *) va_arg(args, void *))) {
if (testextensie_ex(str, str_len, ext, strlen(ext))) {
ret = true;
- goto finally;
+ break;
}
}
-finally:
va_end(args);
return ret;
@@ -1745,17 +1610,16 @@ bool BLI_testextensie_glob(const char *str, const char *ext_fnmatch)
while (ext_step[0]) {
const char *ext_next;
- int len_ext;
+ size_t len_ext;
if ((ext_next = strchr(ext_step, ';'))) {
- len_ext = (int)(ext_next - ext_step) + 1;
+ len_ext = ext_next - ext_step + 1;
+ BLI_strncpy(pattern, ext_step, (len_ext > sizeof(pattern)) ? sizeof(pattern) : len_ext);
}
else {
- len_ext = sizeof(pattern);
+ len_ext = BLI_strncpy_rlen(pattern, ext_step, sizeof(pattern));
}
- BLI_strncpy(pattern, ext_step, len_ext);
-
if (fnmatch(pattern, str, FNM_CASEFOLD) == 0) {
return true;
}
@@ -1803,9 +1667,7 @@ bool BLI_ensure_extension(char *path, size_t maxlen, const char *ext)
ssize_t a;
/* first check the extension is already there */
- if ( (ext_len <= path_len) &&
- (strcmp(path + (path_len - ext_len), ext) == 0))
- {
+ if ((ext_len <= path_len) && (STREQ(path + (path_len - ext_len), ext))) {
return true;
}
@@ -2146,317 +2008,13 @@ void BLI_path_native_slash(char *path)
{
#ifdef WIN32
if (path && BLI_strnlen(path, 3) > 2) {
- BLI_char_switch(path + 2, '/', '\\');
- }
-#else
- BLI_char_switch(path + BLI_path_unc_prefix_len(path), '\\', '/');
-#endif
-}
-
-/**
- * Tries appending each of the semicolon-separated extensions in the PATHEXT
- * environment variable (Windows-only) onto *name in turn until such a file is found.
- * Returns success/failure.
- */
-static int add_win32_extension(char *name)
-{
- int retval = 0;
- int type;
-
- type = BLI_exists(name);
- if ((type == 0) || S_ISDIR(type)) {
-#ifdef _WIN32
- char filename[FILE_MAX];
- char ext[FILE_MAX];
- const char *extensions = getenv("PATHEXT");
- if (extensions) {
- char *temp;
- do {
- strcpy(filename, name);
- temp = strstr(extensions, ";");
- if (temp) {
- strncpy(ext, extensions, temp - extensions);
- ext[temp - extensions] = 0;
- extensions = temp + 1;
- strcat(filename, ext);
- }
- else {
- strcat(filename, extensions);
- }
-
- type = BLI_exists(filename);
- if (type && (!S_ISDIR(type))) {
- retval = 1;
- strcpy(name, filename);
- break;
- }
- } while (temp);
- }
-#endif
- }
- else {
- retval = 1;
+ BLI_str_replace_char(path + 2, '/', '\\');
}
-
- return (retval);
-}
-
-/**
- * Checks if name is a fully qualified filename to an executable.
- * If not it searches $PATH for the file. On Windows it also
- * adds the correct extension (.com .exe etc) from
- * $PATHEXT if necessary. Also on Windows it translates
- * the name to its 8.3 version to prevent problems with
- * spaces and stuff. Final result is returned in fullname.
- *
- * \param fullname The full path and full name of the executable
- * (must be FILE_MAX minimum)
- * \param name The name of the executable (usually argv[0]) to be checked
- */
-static void bli_where_am_i(char *fullname, const size_t maxlen, const char *name)
-{
- char filename[FILE_MAX];
- const char *path = NULL, *temp;
-
-#ifdef _WIN32
- const char *separator = ";";
#else
- const char *separator = ":";
+ BLI_str_replace_char(path + BLI_path_unc_prefix_len(path), '\\', '/');
#endif
-
-
-#ifdef WITH_BINRELOC
- /* linux uses binreloc since argv[0] is not reliable, call br_init( NULL ) first */
- path = br_find_exe(NULL);
- if (path) {
- BLI_strncpy(fullname, path, maxlen);
- free((void *)path);
- return;
- }
-#endif
-
-#ifdef _WIN32
- wchar_t *fullname_16 = MEM_mallocN(maxlen * sizeof(wchar_t), "ProgramPath");
- if (GetModuleFileNameW(0, fullname_16, maxlen)) {
- conv_utf_16_to_8(fullname_16, fullname, maxlen);
- if (!BLI_exists(fullname)) {
- printf("path can't be found: \"%.*s\"\n", (int)maxlen, fullname);
- MessageBox(NULL, "path contains invalid characters or is too long (see console)", "Error", MB_OK);
- }
- MEM_freeN(fullname_16);
- return;
- }
-
- MEM_freeN(fullname_16);
-#endif
-
- /* unix and non linux */
- if (name && name[0]) {
-
- BLI_strncpy(fullname, name, maxlen);
- if (name[0] == '.') {
- char wdir[FILE_MAX] = "";
- BLI_current_working_dir(wdir, sizeof(wdir)); /* backup cwd to restore after */
-
- // not needed but avoids annoying /./ in name
- if (name[1] == SEP)
- BLI_join_dirfile(fullname, maxlen, wdir, name + 2);
- else
- BLI_join_dirfile(fullname, maxlen, wdir, name);
-
- add_win32_extension(fullname); /* XXX, doesnt respect length */
- }
- else if (BLI_last_slash(name)) {
- // full path
- BLI_strncpy(fullname, name, maxlen);
- add_win32_extension(fullname);
- }
- else {
- // search for binary in $PATH
- path = getenv("PATH");
- if (path) {
- do {
- temp = strstr(path, separator);
- if (temp) {
- strncpy(filename, path, temp - path);
- filename[temp - path] = 0;
- path = temp + 1;
- }
- else {
- strncpy(filename, path, sizeof(filename));
- }
- BLI_path_append(fullname, maxlen, name);
- if (add_win32_extension(filename)) {
- BLI_strncpy(fullname, filename, maxlen);
- break;
- }
- } while (temp);
- }
- }
-#if defined(DEBUG)
- if (strcmp(name, fullname)) {
- printf("guessing '%s' == '%s'\n", name, fullname);
- }
-#endif
- }
-}
-
-void BLI_init_program_path(const char *argv0)
-{
- bli_where_am_i(bprogname, sizeof(bprogname), argv0);
- BLI_split_dir_part(bprogname, bprogdir, sizeof(bprogdir));
-}
-
-/**
- * Path to executable
- */
-const char *BLI_program_path(void)
-{
- return bprogname;
}
-/**
- * Path to directory of executable
- */
-const char *BLI_program_dir(void)
-{
- return bprogdir;
-}
-
-/**
- * Gets the temp directory when blender first runs.
- * If the default path is not found, use try $TEMP
- *
- * Also make sure the temp dir has a trailing slash
- *
- * \param fullname The full path to the temporary temp directory
- * \param basename The full path to the persistent temp directory (may be NULL)
- * \param maxlen The size of the fullname buffer
- * \param userdir Directory specified in user preferences
- */
-static void BLI_where_is_temp(char *fullname, char *basename, const size_t maxlen, char *userdir)
-{
- /* Clear existing temp dir, if needed. */
- BLI_temp_dir_session_purge();
-
- fullname[0] = '\0';
- if (basename) {
- basename[0] = '\0';
- }
-
- if (userdir && BLI_is_dir(userdir)) {
- BLI_strncpy(fullname, userdir, maxlen);
- }
-
-
-#ifdef WIN32
- if (fullname[0] == '\0') {
- const char *tmp = getenv("TEMP"); /* Windows */
- if (tmp && BLI_is_dir(tmp)) {
- BLI_strncpy(fullname, tmp, maxlen);
- }
- }
-#else
- /* Other OS's - Try TMP and TMPDIR */
- if (fullname[0] == '\0') {
- const char *tmp = getenv("TMP");
- if (tmp && BLI_is_dir(tmp)) {
- BLI_strncpy(fullname, tmp, maxlen);
- }
- }
-
- if (fullname[0] == '\0') {
- const char *tmp = getenv("TMPDIR");
- if (tmp && BLI_is_dir(tmp)) {
- BLI_strncpy(fullname, tmp, maxlen);
- }
- }
-#endif
-
- if (fullname[0] == '\0') {
- BLI_strncpy(fullname, "/tmp/", maxlen);
- }
- else {
- /* add a trailing slash if needed */
- BLI_add_slash(fullname);
-#ifdef WIN32
- if (userdir && userdir != fullname) {
- BLI_strncpy(userdir, fullname, maxlen); /* also set user pref to show %TEMP%. /tmp/ is just plain confusing for Windows users. */
- }
-#endif
- }
-
- /* Now that we have a valid temp dir, add system-generated unique sub-dir. */
- if (basename) {
- /* 'XXXXXX' is kind of tag to be replaced by mktemp-familly by an uuid. */
- char *tmp_name = BLI_strdupcat(fullname, "blender_XXXXXX");
- const size_t ln = strlen(tmp_name) + 1;
- if (ln <= maxlen) {
-#ifdef WIN32
- if (_mktemp_s(tmp_name, ln) == 0) {
- BLI_dir_create_recursive(tmp_name);
- }
-#else
- mkdtemp(tmp_name);
-#endif
- }
- if (BLI_is_dir(tmp_name)) {
- BLI_strncpy(basename, fullname, maxlen);
- BLI_strncpy(fullname, tmp_name, maxlen);
- BLI_add_slash(fullname);
- }
- else {
- printf("Warning! Could not generate a temp file name for '%s', falling back to '%s'\n", tmp_name, fullname);
- }
-
- MEM_freeN(tmp_name);
- }
-}
-
-/**
- * Sets btempdir_base to userdir if specified and is a valid directory, otherwise
- * chooses a suitable OS-specific temporary directory.
- * Sets btempdir_session to a mkdtemp-generated sub-dir of btempdir_base.
- */
-void BLI_temp_dir_init(char *userdir)
-{
- BLI_where_is_temp(btempdir_session, btempdir_base, FILE_MAX, userdir);
-;
-}
-
-/**
- * Path to temporary directory (with trailing slash)
- */
-const char *BLI_temp_dir_session(void)
-{
- return btempdir_session[0] ? btempdir_session : BLI_temp_dir_base();
-}
-
-/**
- * Path to persistent temporary directory (with trailing slash)
- */
-const char *BLI_temp_dir_base(void)
-{
- return btempdir_base;
-}
-
-/**
- * Path to the system temporary directory (with trailing slash)
- */
-void BLI_system_temporary_dir(char *dir)
-{
- BLI_where_is_temp(dir, NULL, FILE_MAX, NULL);
-}
-
-/**
- * Delete content of this instance's temp dir.
- */
-void BLI_temp_dir_session_purge(void)
-{
- if (btempdir_session[0] && BLI_is_dir(btempdir_session)) {
- BLI_delete(btempdir_session, true, true);
- }
-}
#ifdef WITH_ICONV
diff --git a/source/blender/blenlib/intern/polyfill2d.c b/source/blender/blenlib/intern/polyfill2d.c
index a00d95a075f..df6caa4b65a 100644
--- a/source/blender/blenlib/intern/polyfill2d.c
+++ b/source/blender/blenlib/intern/polyfill2d.c
@@ -61,6 +61,9 @@
# define USE_KDTREE
#endif
+/* disable in production, it can fail on near zero area ngons */
+// #define USE_STRICT_ASSERT
+
// #define DEBUG_TIME
#ifdef DEBUG_TIME
# include "PIL_time_utildefines.h"
@@ -165,7 +168,7 @@ static bool pf_ear_tip_check(PolyFill *pf, PolyIndex *pi_ear_tip);
static void pf_ear_tip_cut(PolyFill *pf, PolyIndex *pi_ear_tip);
-BLI_INLINE eSign signum_i(float a)
+BLI_INLINE eSign signum_enum(float a)
{
if (UNLIKELY(a == 0.0f))
return 0;
@@ -179,7 +182,7 @@ BLI_INLINE eSign signum_i(float a)
* alternative version of #area_tri_signed_v2
* needed because of float precision issues
*
- * \note removes / 2 since its not needed since we only need ths sign.
+ * \note removes / 2 since its not needed since we only need the sign.
*/
BLI_INLINE float area_tri_signed_v2_alt_2x(const float v1[2], const float v2[2], const float v3[2])
{
@@ -191,7 +194,7 @@ BLI_INLINE float area_tri_signed_v2_alt_2x(const float v1[2], const float v2[2],
static eSign span_tri_v2_sign(const float v1[2], const float v2[2], const float v3[2])
{
- return signum_i(area_tri_signed_v2_alt_2x(v3, v2, v1));
+ return signum_enum(area_tri_signed_v2_alt_2x(v3, v2, v1));
}
@@ -567,7 +570,7 @@ static void pf_triangulate(PolyFill *pf)
#ifdef USE_CLIP_EVEN
#ifdef USE_CLIP_SWEEP
- pi_ear_init = reverse ? pi_next->next : pi_prev->prev;
+ pi_ear_init = reverse ? pi_prev->prev : pi_next->next;
#else
pi_ear_init = pi_next->next;
#endif
@@ -797,6 +800,7 @@ static void polyfill_prepare(
}
else {
/* chech we're passing in correcty args */
+#ifdef USE_STRICT_ASSERT
#ifndef NDEBUG
if (coords_sign == 1) {
BLI_assert(cross_poly_v2(coords, coords_tot) >= 0.0f);
@@ -805,6 +809,7 @@ static void polyfill_prepare(
BLI_assert(cross_poly_v2(coords, coords_tot) <= 0.0f);
}
#endif
+#endif
}
if (coords_sign == 1) {
diff --git a/source/blender/blenlib/intern/polyfill2d_beautify.c b/source/blender/blenlib/intern/polyfill2d_beautify.c
new file mode 100644
index 00000000000..46f9251bea7
--- /dev/null
+++ b/source/blender/blenlib/intern/polyfill2d_beautify.c
@@ -0,0 +1,495 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/blenlib/intern/polyfill2d_beautify.c
+ * \ingroup bli
+ *
+ * This function is to improve the tessellation resulting from polyfill2d,
+ * creating optimal topology.
+ *
+ * The functionality here matches #BM_mesh_beautify_fill,
+ * but its far simpler to perform this operation in 2d,
+ * on a simple polygon representation where we _know_:
+ *
+ * - The polygon is primitive with no holes with a continuous boundary.
+ * - Tris have consistent winding.
+ * - 2d (saves some hassles projecting face pairs on an axis for every edge-rotation)
+ * also saves us having to store all previous edge-states (see #EdRotState in bmesh_beautify.c)
+ *
+ * \note
+ *
+ * No globals - keep threadsafe.
+ */
+
+#include "BLI_utildefines.h"
+#include "BLI_math.h"
+
+#include "BLI_memarena.h"
+#include "BLI_edgehash.h"
+#include "BLI_heap.h"
+
+#include "BLI_polyfill2d_beautify.h" /* own include */
+
+#include "BLI_strict_flags.h"
+
+struct PolyEdge {
+ /** ordered vert indices (smaller first) */
+ unsigned int verts[2];
+ /** ordered face indices (depends on winding compared to the edge verts)
+ * - (verts[0], verts[1]) == faces[0]
+ * - (verts[1], verts[0]) == faces[1]
+ */
+ unsigned int faces[2];
+ /**
+ * The face-index which isn't used by either of the edges verts [0 - 2].
+ * could be calculated each time, but cleaner to store for reuse.
+ */
+ unsigned int faces_other_v[2];
+};
+
+
+#ifndef NDEBUG
+/**
+ * Only to check for error-cases.
+ */
+static void polyfill_validate_tri(unsigned int (*tris)[3], unsigned int tri_index, EdgeHash *ehash)
+{
+ const unsigned int *tri = tris[tri_index];
+ int j_curr;
+
+ BLI_assert(!ELEM(tri[0], tri[1], tri[2]) &&
+ !ELEM(tri[1], tri[0], tri[2]) &&
+ !ELEM(tri[2], tri[0], tri[1]));
+
+ for (j_curr = 0; j_curr < 3; j_curr++) {
+ struct PolyEdge *e;
+ unsigned int e_v1 = tri[(j_curr ) ];
+ unsigned int e_v2 = tri[(j_curr + 1) % 3];
+ e = BLI_edgehash_lookup(ehash, e_v1, e_v2);
+ if (e) {
+ if (e->faces[0] == tri_index) {
+ BLI_assert(e->verts[0] == e_v1);
+ BLI_assert(e->verts[1] == e_v2);
+ }
+ else if (e->faces[1] == tri_index) {
+ BLI_assert(e->verts[0] == e_v2);
+ BLI_assert(e->verts[1] == e_v1);
+ }
+ else {
+ BLI_assert(0);
+ }
+
+ BLI_assert(e->faces[0] != e->faces[1]);
+ BLI_assert(ELEM(e_v1, UNPACK3(tri)));
+ BLI_assert(ELEM(e_v2, UNPACK3(tri)));
+ BLI_assert(ELEM(e_v1, UNPACK2(e->verts)));
+ BLI_assert(ELEM(e_v2, UNPACK2(e->verts)));
+ BLI_assert(e_v1 != tris[e->faces[0]][e->faces_other_v[0]]);
+ BLI_assert(e_v1 != tris[e->faces[1]][e->faces_other_v[1]]);
+ BLI_assert(e_v2 != tris[e->faces[0]][e->faces_other_v[0]]);
+ BLI_assert(e_v2 != tris[e->faces[1]][e->faces_other_v[1]]);
+
+ BLI_assert(ELEM(tri_index, UNPACK2(e->faces)));
+ }
+ }
+}
+#endif
+
+BLI_INLINE bool is_boundary_edge(unsigned int i_a, unsigned int i_b, const unsigned int coord_last)
+{
+ BLI_assert(i_a < i_b);
+ return ((i_a + 1 == i_b) || UNLIKELY((i_a == 0) && (i_b == coord_last)));
+}
+/**
+ * Assuming we have 2 triangles sharing an edge (2 - 4),
+ * check if the edge running from (1 - 3) gives better results.
+ *
+ * \return (negative number means the edge can be rotated, lager == better).
+ */
+float BLI_polyfill_beautify_quad_rotate_calc(
+ const float v1[2], const float v2[2], const float v3[2], const float v4[2])
+{
+ /* not a loop (only to be able to break out) */
+ do {
+ bool is_zero_a, is_zero_b;
+
+ const float area_2x_234 = cross_tri_v2(v2, v3, v4);
+ const float area_2x_241 = cross_tri_v2(v2, v4, v1);
+
+ const float area_2x_123 = cross_tri_v2(v1, v2, v3);
+ const float area_2x_134 = cross_tri_v2(v1, v3, v4);
+
+ {
+ BLI_assert((ELEM(v1, v2, v3, v4) == false) &&
+ (ELEM(v2, v1, v3, v4) == false) &&
+ (ELEM(v3, v1, v2, v4) == false) &&
+ (ELEM(v4, v1, v2, v3) == false));
+
+ is_zero_a = (fabsf(area_2x_234) <= FLT_EPSILON);
+ is_zero_b = (fabsf(area_2x_241) <= FLT_EPSILON);
+
+ if (is_zero_a && is_zero_b) {
+ break;
+ }
+ }
+
+ /* one of the tri's was degenerate, check we're not rotating
+ * into a different degenerate shape or flipping the face */
+ if ((fabsf(area_2x_123) <= FLT_EPSILON) || (fabsf(area_2x_134) <= FLT_EPSILON)) {
+ /* one of the new rotations is degenerate */
+ break;
+ }
+
+ if ((area_2x_123 >= 0.0f) != (area_2x_134 >= 0.0f)) {
+ /* rotation would cause flipping */
+ break;
+ }
+
+ {
+ /* testing rule: the area divided by the perimeter,
+ * check if (1-3) beats the existing (2-4) edge rotation */
+ float area_a, area_b;
+ float prim_a, prim_b;
+ float fac_24, fac_13;
+
+ float len_12, len_23, len_34, len_41, len_24, len_13;
+
+ /* edges around the quad */
+ len_12 = len_v2v2(v1, v2);
+ len_23 = len_v2v2(v2, v3);
+ len_34 = len_v2v2(v3, v4);
+ len_41 = len_v2v2(v4, v1);
+ /* edges crossing the quad interior */
+ len_13 = len_v2v2(v1, v3);
+ len_24 = len_v2v2(v2, v4);
+
+ /* note, area is in fact (area * 2),
+ * but in this case its OK, since we're comparing ratios */
+
+ /* edge (2-4), current state */
+ area_a = fabsf(area_2x_234);
+ area_b = fabsf(area_2x_241);
+ prim_a = len_23 + len_34 + len_24;
+ prim_b = len_41 + len_12 + len_24;
+ fac_24 = (area_a / prim_a) + (area_b / prim_b);
+
+ /* edge (1-3), new state */
+ area_a = fabsf(area_2x_123);
+ area_b = fabsf(area_2x_134);
+ prim_a = len_12 + len_23 + len_13;
+ prim_b = len_34 + len_41 + len_13;
+ fac_13 = (area_a / prim_a) + (area_b / prim_b);
+
+ /* negative number if (1-3) is an improved state */
+ return fac_24 - fac_13;
+ }
+ } while (false);
+
+ return FLT_MAX;
+}
+
+static float polyedge_rotate_beauty_calc(
+ const float (*coords)[2],
+ const unsigned int (*tris)[3],
+ const struct PolyEdge *e)
+{
+ const float *v1, *v2, *v3, *v4;
+
+ v1 = coords[tris[e->faces[0]][e->faces_other_v[0]]];
+ v3 = coords[tris[e->faces[1]][e->faces_other_v[1]]];
+ v2 = coords[e->verts[0]];
+ v4 = coords[e->verts[1]];
+
+ return BLI_polyfill_beautify_quad_rotate_calc(v1, v2, v3, v4);
+}
+
+static void polyedge_beauty_cost_update_single(
+ const float (*coords)[2],
+ const unsigned int (*tris)[3],
+ const struct PolyEdge *edges,
+ struct PolyEdge *e,
+ Heap *eheap, HeapNode **eheap_table)
+{
+ const unsigned int i = (unsigned int)(e - edges);
+
+ if (eheap_table[i]) {
+ BLI_heap_remove(eheap, eheap_table[i]);
+ eheap_table[i] = NULL;
+ }
+
+ {
+ /* recalculate edge */
+ const float cost = polyedge_rotate_beauty_calc(coords, tris, e);
+ /* We can get cases where both choices generate very small negative costs, which leads to infinite loop.
+ * Anyway, costs above that are not worth recomputing, maybe we could even optimize it to a smaller limit?
+ * See T43578. */
+ if (cost < -FLT_EPSILON) {
+ eheap_table[i] = BLI_heap_insert(eheap, cost, e);
+ }
+ else {
+ eheap_table[i] = NULL;
+ }
+ }
+}
+
+static void polyedge_beauty_cost_update(
+ const float (*coords)[2],
+ const unsigned int (*tris)[3],
+ const struct PolyEdge *edges,
+ struct PolyEdge *e,
+ Heap *eheap, HeapNode **eheap_table,
+ EdgeHash *ehash)
+{
+ const unsigned int *tri_0 = tris[e->faces[0]];
+ const unsigned int *tri_1 = tris[e->faces[1]];
+ unsigned int i;
+
+ struct PolyEdge *e_arr[4] = {
+ BLI_edgehash_lookup(ehash,
+ tri_0[(e->faces_other_v[0] ) % 3],
+ tri_0[(e->faces_other_v[0] + 1) % 3]),
+ BLI_edgehash_lookup(ehash,
+ tri_0[(e->faces_other_v[0] + 2) % 3],
+ tri_0[(e->faces_other_v[0] ) % 3]),
+ BLI_edgehash_lookup(ehash,
+ tri_1[(e->faces_other_v[1] ) % 3],
+ tri_1[(e->faces_other_v[1] + 1) % 3]),
+ BLI_edgehash_lookup(ehash,
+ tri_1[(e->faces_other_v[1] + 2) % 3],
+ tri_1[(e->faces_other_v[1] ) % 3]),
+ };
+
+
+ for (i = 0; i < 4; i++) {
+ if (e_arr[i]) {
+ BLI_assert(!(ELEM(e_arr[i]->faces[0], UNPACK2(e->faces)) &&
+ ELEM(e_arr[i]->faces[1], UNPACK2(e->faces))));
+
+ polyedge_beauty_cost_update_single(
+ coords, tris, edges,
+ e_arr[i],
+ eheap, eheap_table);
+ }
+ }
+}
+
+static void polyedge_rotate(
+ unsigned int (*tris)[3],
+ struct PolyEdge *e,
+ EdgeHash *ehash)
+{
+ unsigned int e_v1_new = tris[e->faces[0]][e->faces_other_v[0]];
+ unsigned int e_v2_new = tris[e->faces[1]][e->faces_other_v[1]];
+
+#ifndef NDEBUG
+ polyfill_validate_tri(tris, e->faces[0], ehash);
+ polyfill_validate_tri(tris, e->faces[1], ehash);
+#endif
+
+ BLI_assert(e_v1_new != e_v2_new);
+ BLI_assert(!ELEM(e_v2_new, UNPACK3(tris[e->faces[0]])));
+ BLI_assert(!ELEM(e_v1_new, UNPACK3(tris[e->faces[1]])));
+
+ tris[e->faces[0]][(e->faces_other_v[0] + 1) % 3] = e_v2_new;
+ tris[e->faces[1]][(e->faces_other_v[1] + 1) % 3] = e_v1_new;
+
+ e->faces_other_v[0] = (e->faces_other_v[0] + 2) % 3;
+ e->faces_other_v[1] = (e->faces_other_v[1] + 2) % 3;
+
+ BLI_assert((tris[e->faces[0]][e->faces_other_v[0]] != e_v1_new) &&
+ (tris[e->faces[0]][e->faces_other_v[0]] != e_v2_new));
+ BLI_assert((tris[e->faces[1]][e->faces_other_v[1]] != e_v1_new) &&
+ (tris[e->faces[1]][e->faces_other_v[1]] != e_v2_new));
+
+ BLI_edgehash_remove(ehash, e->verts[0], e->verts[1], NULL);
+ BLI_edgehash_insert(ehash, e_v1_new, e_v2_new, e);
+
+ if (e_v1_new < e_v2_new) {
+ e->verts[0] = e_v1_new;
+ e->verts[1] = e_v2_new;
+ }
+ else {
+ /* maintain winding info */
+ e->verts[0] = e_v2_new;
+ e->verts[1] = e_v1_new;
+
+ SWAP(unsigned int, e->faces[0], e->faces[1]);
+ SWAP(unsigned int, e->faces_other_v[0], e->faces_other_v[1]);
+ }
+
+ /* update adjacent data */
+ {
+ unsigned int e_side = 0;
+
+ for (e_side = 0; e_side < 2; e_side++) {
+ /* 't_other' which we need to swap out is always the same edge-order */
+ const unsigned int t_other = (((e->faces_other_v[e_side]) + 2)) % 3;
+ unsigned int t_index = e->faces[e_side];
+ unsigned int t_index_other = e->faces[!e_side];
+ unsigned int *tri = tris[t_index];
+
+ struct PolyEdge *e_other;
+ unsigned int e_v1 = tri[(t_other ) ];
+ unsigned int e_v2 = tri[(t_other + 1) % 3];
+
+ e_other = BLI_edgehash_lookup(ehash, e_v1, e_v2);
+ if (e_other) {
+ BLI_assert(t_index != e_other->faces[0] && t_index != e_other->faces[1]);
+ if (t_index_other == e_other->faces[0]) {
+ e_other->faces[0] = t_index;
+ e_other->faces_other_v[0] = (t_other + 2) % 3;
+ BLI_assert(!ELEM(tri[e_other->faces_other_v[0]], e_v1, e_v2));
+ }
+ else if (t_index_other == e_other->faces[1]) {
+ e_other->faces[1] = t_index;
+ e_other->faces_other_v[1] = (t_other + 2) % 3;
+ BLI_assert(!ELEM(tri[e_other->faces_other_v[1]], e_v1, e_v2));
+ }
+ else {
+ BLI_assert(0);
+ }
+ }
+ }
+ }
+
+#ifndef NDEBUG
+ polyfill_validate_tri(tris, e->faces[0], ehash);
+ polyfill_validate_tri(tris, e->faces[1], ehash);
+#endif
+
+ BLI_assert(!ELEM(tris[e->faces[0]][e->faces_other_v[0]], UNPACK2(e->verts)));
+ BLI_assert(!ELEM(tris[e->faces[1]][e->faces_other_v[1]], UNPACK2(e->verts)));
+}
+
+/**
+ * The intention is that this calculates the output of #BLI_polyfill_calc
+ *
+ *
+ * \note assumes the \a coords form a boundary,
+ * so any edges running along contiguous (wrapped) indices,
+ * are ignored since the edges wont share 2 faces.
+ */
+void BLI_polyfill_beautify(
+ const float (*coords)[2],
+ const unsigned int coords_tot,
+ unsigned int (*tris)[3],
+
+ /* structs for reuse */
+ MemArena *arena, Heap *eheap, EdgeHash *ehash)
+{
+ const unsigned int coord_last = coords_tot - 1;
+ const unsigned int tris_tot = coords_tot - 2;
+ /* internal edges only (between 2 tris) */
+ const unsigned int edges_tot = tris_tot - 1;
+ unsigned int edges_tot_used = 0;
+ unsigned int i;
+
+ HeapNode **eheap_table;
+
+ struct PolyEdge *edges = BLI_memarena_alloc(arena, edges_tot * sizeof(*edges));
+
+ BLI_assert(BLI_heap_size(eheap) == 0);
+ BLI_assert(BLI_edgehash_size(ehash) == 0);
+
+ /* first build edges */
+ for (i = 0; i < tris_tot; i++) {
+ unsigned int j_prev, j_curr, j_next;
+ j_prev = 2;
+ j_next = 1;
+ for (j_curr = 0; j_curr < 3; j_next = j_prev, j_prev = j_curr++) {
+ int e_index;
+
+ unsigned int e_pair[2] = {
+ tris[i][j_prev],
+ tris[i][j_curr],
+ };
+
+ if (e_pair[0] > e_pair[1]) {
+ SWAP(unsigned int, e_pair[0], e_pair[1]);
+ e_index = 1;
+ }
+ else {
+ e_index = 0;
+ }
+
+ if (!is_boundary_edge(e_pair[0], e_pair[1], coord_last)) {
+ struct PolyEdge *e;
+ void **val_p;
+
+ if (!BLI_edgehash_ensure_p(ehash, e_pair[0], e_pair[1], &val_p)) {
+ e = &edges[edges_tot_used++];
+ *val_p = e;
+ memcpy(e->verts, e_pair, sizeof(e->verts));
+#ifndef NDEBUG
+ e->faces[!e_index] = (unsigned int)-1;
+#endif
+ }
+ else {
+ e = *val_p;
+ /* ensure each edge only ever has 2x users */
+#ifndef NDEBUG
+ BLI_assert(e->faces[e_index] == (unsigned int)-1);
+ BLI_assert((e->verts[0] == e_pair[0]) &&
+ (e->verts[1] == e_pair[1]));
+#endif
+ }
+
+ e->faces[e_index] = i;
+ e->faces_other_v[e_index] = j_next;
+ }
+ }
+ }
+
+ /* now perform iterative rotations */
+ eheap_table = BLI_memarena_alloc(arena, sizeof(HeapNode *) * (size_t)edges_tot);
+
+ // for (i = 0; i < tris_tot; i++) { polyfill_validate_tri(tris, i, eh); }
+
+ /* build heap */
+ for (i = 0; i < edges_tot; i++) {
+ struct PolyEdge *e = &edges[i];
+ const float cost = polyedge_rotate_beauty_calc(coords, (const unsigned int (*)[3])tris, e);
+ if (cost < 0.0f) {
+ eheap_table[i] = BLI_heap_insert(eheap, cost, e);
+ }
+ else {
+ eheap_table[i] = NULL;
+ }
+ }
+
+ while (BLI_heap_is_empty(eheap) == false) {
+ struct PolyEdge *e = BLI_heap_popmin(eheap);
+ i = (unsigned int)(e - edges);
+ eheap_table[i] = NULL;
+
+ polyedge_rotate(tris, e, ehash);
+
+ /* recalculate faces connected on the heap */
+ polyedge_beauty_cost_update(
+ coords, (const unsigned int (*)[3])tris, edges,
+ e,
+ eheap, eheap_table, ehash);
+ }
+
+ BLI_heap_clear(eheap, NULL);
+ BLI_edgehash_clear_ex(ehash, NULL, BLI_POLYFILL_ALLOC_NGON_RESERVE);
+
+ /* MEM_freeN(eheap_table); */ /* arena */
+}
diff --git a/source/blender/blenlib/intern/quadric.c b/source/blender/blenlib/intern/quadric.c
index 814d05ca80e..588cd9c2cb5 100644
--- a/source/blender/blenlib/intern/quadric.c
+++ b/source/blender/blenlib/intern/quadric.c
@@ -29,20 +29,24 @@
* \note This isn't fully complete,
* possible there are other useful functions to add here.
*
- * \note try to follow BLI_math naming convention here.
+ * \note follow BLI_math naming convention here.
+ *
+ * \note this uses doubles for internal calculations,
+ * even though input/output are floats in some cases.
+ *
+ * This is done because the cases quadrics are useful
+ * often need high precision, see T44780.
*/
-//#include <string.h>
-
#include "BLI_math.h"
#include "BLI_strict_flags.h"
#include "BLI_quadric.h" /* own include */
-#define QUADRIC_FLT_TOT (sizeof(Quadric) / sizeof(float))
+#define QUADRIC_FLT_TOT (sizeof(Quadric) / sizeof(double))
-void BLI_quadric_from_v3_dist(Quadric *q, const float v[3], const float offset)
+void BLI_quadric_from_plane(Quadric *q, const double v[4])
{
q->a2 = v[0] * v[0];
q->b2 = v[1] * v[1];
@@ -52,33 +56,33 @@ void BLI_quadric_from_v3_dist(Quadric *q, const float v[3], const float offset)
q->ac = v[0] * v[2];
q->bc = v[1] * v[2];
- q->ad = v[0] * offset;
- q->bd = v[1] * offset;
- q->cd = v[2] * offset;
+ q->ad = v[0] * v[3];
+ q->bd = v[1] * v[3];
+ q->cd = v[2] * v[3];
- q->d2 = offset * offset;
+ q->d2 = v[3] * v[3];
}
void BLI_quadric_to_tensor_m3(const Quadric *q, float m[3][3])
{
- m[0][0] = q->a2;
- m[0][1] = q->ab;
- m[0][2] = q->ac;
+ m[0][0] = (float)q->a2;
+ m[0][1] = (float)q->ab;
+ m[0][2] = (float)q->ac;
- m[1][0] = q->ab;
- m[1][1] = q->b2;
- m[1][2] = q->bc;
+ m[1][0] = (float)q->ab;
+ m[1][1] = (float)q->b2;
+ m[1][2] = (float)q->bc;
- m[2][0] = q->ac;
- m[2][1] = q->bc;
- m[2][2] = q->c2;
+ m[2][0] = (float)q->ac;
+ m[2][1] = (float)q->bc;
+ m[2][2] = (float)q->c2;
}
void BLI_quadric_to_vector_v3(const Quadric *q, float v[3])
{
- v[0] = q->ad;
- v[1] = q->bd;
- v[2] = q->cd;
+ v[0] = (float)q->ad;
+ v[1] = (float)q->bd;
+ v[2] = (float)q->cd;
}
void BLI_quadric_clear(Quadric *q)
@@ -88,25 +92,26 @@ void BLI_quadric_clear(Quadric *q)
void BLI_quadric_add_qu_qu(Quadric *a, const Quadric *b)
{
- add_vn_vn((float *)a, (float *)b, QUADRIC_FLT_TOT);
+ add_vn_vn_d((double *)a, (double *)b, QUADRIC_FLT_TOT);
}
void BLI_quadric_add_qu_ququ(Quadric *r, const Quadric *a, const Quadric *b)
{
- add_vn_vnvn((float *)r, (const float *)a, (const float *)b, QUADRIC_FLT_TOT);
+ add_vn_vnvn_d((double *)r, (const double *)a, (const double *)b, QUADRIC_FLT_TOT);
}
-void BLI_quadric_mul(Quadric *a, const float scalar)
+void BLI_quadric_mul(Quadric *a, const double scalar)
{
- mul_vn_fl((float *)a, QUADRIC_FLT_TOT, scalar);
+ mul_vn_db((double *)a, QUADRIC_FLT_TOT, scalar);
}
-float BLI_quadric_evaluate(const Quadric *q, const float v[3])
+double BLI_quadric_evaluate(const Quadric *q, const float v_fl[3])
{
- return (v[0] * v[0] * q->a2 + 2.0f * v[0] * v[1] * q->ab + 2.0f * v[0] * v[2] * q->ac + 2.0f * v[0] * q->ad +
- v[1] * v[1] * q->b2 + 2.0f * v[1] * v[2] * q->bc + 2.0f * v[1] * q->bd +
- v[2] * v[2] * q->c2 + 2.0f * v[2] * q->cd +
- q->d2);
+ const double v[3] = {UNPACK3(v_fl)};
+ return ((q->a2 * v[0] * v[0]) + (q->ab * 2 * v[0] * v[1]) + (q->ac * 2 * v[0] * v[2]) + (q->ad * 2 * v[0]) +
+ (q->b2 * v[1] * v[1]) + (q->bc * 2 * v[1] * v[2]) + (q->bd * 2 * v[1]) +
+ (q->c2 * v[2] * v[2]) + (q->cd * 2 * v[2]) +
+ (q->d2));
}
bool BLI_quadric_optimize(const Quadric *q, float v[3], const float epsilon)
diff --git a/source/blender/blenlib/intern/rand.c b/source/blender/blenlib/intern/rand.c
index 3dff0b31091..66c568a7ff3 100644
--- a/source/blender/blenlib/intern/rand.c
+++ b/source/blender/blenlib/intern/rand.c
@@ -33,6 +33,7 @@
#include <stdlib.h>
#include <string.h>
#include <math.h>
+#include <time.h>
#include "MEM_guardedalloc.h"
@@ -67,6 +68,9 @@ RNG *BLI_rng_new(unsigned int seed)
return rng;
}
+/**
+ * A version of #BLI_rng_new that hashes the seed.
+ */
RNG *BLI_rng_new_srandom(unsigned int seed)
{
RNG *rng = MEM_mallocN(sizeof(*rng), "rng");
@@ -86,6 +90,9 @@ void BLI_rng_seed(RNG *rng, unsigned int seed)
rng->X = (((uint64_t) seed) << 16) | LOWSEED;
}
+/**
+ * Use a hash table to create better seed.
+ */
void BLI_rng_srandom(RNG *rng, unsigned int seed)
{
BLI_rng_seed(rng, seed + hash[seed & 255]);
@@ -112,11 +119,17 @@ unsigned int BLI_rng_get_uint(RNG *rng)
return (unsigned int) (rng->X >> 17);
}
+/**
+ * \return Random value (0..1), but never 1.0.
+ */
double BLI_rng_get_double(RNG *rng)
{
return (double) BLI_rng_get_int(rng) / 0x80000000;
}
+/**
+ * \return Random value (0..1), but never 1.0.
+ */
float BLI_rng_get_float(RNG *rng)
{
return (float) BLI_rng_get_int(rng) / 0x80000000;
@@ -144,9 +157,34 @@ void BLI_rng_get_float_unit_v3(RNG *rng, float v[3])
}
}
+/**
+ * Generate a random point inside given tri.
+ */
+void BLI_rng_get_tri_sample_float_v2(
+ RNG *rng, const float v1[2], const float v2[2], const float v3[2],
+ float r_pt[2])
+{
+ float u = BLI_rng_get_float(rng);
+ float v = BLI_rng_get_float(rng);
+
+ float side_u[2], side_v[2];
+
+ if ((u + v) > 1.0f) {
+ u = 1.0f - u;
+ v = 1.0f - v;
+ }
+
+ sub_v2_v2v2(side_u, v2, v1);
+ sub_v2_v2v2(side_v, v3, v1);
+
+ copy_v2_v2(r_pt, v1);
+ madd_v2_v2fl(r_pt, side_u, u);
+ madd_v2_v2fl(r_pt, side_v, v);
+}
+
void BLI_rng_shuffle_array(RNG *rng, void *data, unsigned int elem_size_i, unsigned int elem_tot)
{
- const size_t elem_size = (unsigned int)elem_size_i;
+ const size_t elem_size = (size_t)elem_size_i;
unsigned int i = elem_tot;
void *temp;
@@ -170,6 +208,11 @@ void BLI_rng_shuffle_array(RNG *rng, void *data, unsigned int elem_size_i, unsig
free(temp);
}
+/**
+ * Simulate getting \a n random values.
+ *
+ * \note Useful when threaded code needs consistent values, independent of task division.
+ */
void BLI_rng_skip(RNG *rng, int n)
{
while (n--) {
@@ -182,7 +225,6 @@ void BLI_rng_skip(RNG *rng, int n)
/* initialize with some non-zero seed */
static RNG theBLI_rng = {611330372042337130};
-/* using hash table to create better seed */
void BLI_srandom(unsigned int seed)
{
BLI_rng_srandom(&theBLI_rng, seed);
@@ -245,3 +287,29 @@ float BLI_thread_frand(int thread)
return BLI_rng_get_float(&rng_tab[thread]);
}
+struct RNG_THREAD_ARRAY {
+ RNG rng_tab[BLENDER_MAX_THREADS];
+};
+
+RNG_THREAD_ARRAY *BLI_rng_threaded_new(void)
+{
+ unsigned int i;
+ RNG_THREAD_ARRAY *rngarr = MEM_mallocN(sizeof(RNG_THREAD_ARRAY), "random_array");
+
+ for (i = 0; i < BLENDER_MAX_THREADS; i++) {
+ BLI_rng_srandom(&rngarr->rng_tab[i], (unsigned int)clock());
+ }
+
+ return rngarr;
+}
+
+void BLI_rng_threaded_free(struct RNG_THREAD_ARRAY *rngarr)
+{
+ MEM_freeN(rngarr);
+}
+
+int BLI_rng_thread_rand(RNG_THREAD_ARRAY *rngarr, int thread)
+{
+ return BLI_rng_get_int(&rngarr->rng_tab[thread]);
+}
+
diff --git a/source/blender/blenlib/intern/rct.c b/source/blender/blenlib/intern/rct.c
index 61e5783cd3e..646613d9a29 100644
--- a/source/blender/blenlib/intern/rct.c
+++ b/source/blender/blenlib/intern/rct.c
@@ -123,6 +123,38 @@ bool BLI_rctf_isect_pt_v(const rctf *rect, const float xy[2])
}
/**
+ * \returns shortest distance from \a rect to x/y (0 if inside)
+*/
+
+int BLI_rcti_length_x(const rcti *rect, const int x)
+{
+ if (x < rect->xmin) return rect->xmin - x;
+ if (x > rect->xmax) return x - rect->xmax;
+ return 0;
+}
+
+int BLI_rcti_length_y(const rcti *rect, const int y)
+{
+ if (y < rect->ymin) return rect->ymin - y;
+ if (y > rect->ymax) return y - rect->ymax;
+ return 0;
+}
+
+float BLI_rctf_length_x(const rctf *rect, const float x)
+{
+ if (x < rect->xmin) return rect->xmin - x;
+ if (x > rect->xmax) return x - rect->xmax;
+ return 0.0f;
+}
+
+float BLI_rctf_length_y(const rctf *rect, const float y)
+{
+ if (y < rect->ymin) return rect->ymin - y;
+ if (y > rect->ymax) return y - rect->ymax;
+ return 0.0f;
+}
+
+/**
* is \a rct_b inside \a rct_a
*/
bool BLI_rctf_inside_rctf(rctf *rct_a, const rctf *rct_b)
@@ -552,6 +584,14 @@ void BLI_rcti_rctf_copy(rcti *dst, const rctf *src)
dst->ymax = dst->ymin + floorf(BLI_rctf_size_y(src) + 0.5f);
}
+void BLI_rcti_rctf_copy_floor(rcti *dst, const rctf *src)
+{
+ dst->xmin = floorf(src->xmin);
+ dst->xmax = floorf(src->xmax);
+ dst->ymin = floorf(src->ymin);
+ dst->ymax = floorf(src->ymax);
+}
+
void BLI_rctf_rcti_copy(rctf *dst, const rcti *src)
{
dst->xmin = src->xmin;
@@ -571,3 +611,46 @@ void print_rcti(const char *str, const rcti *rect)
printf("%s: xmin %d, xmax %d, ymin %d, ymax %d (%dx%d)\n", str,
rect->xmin, rect->xmax, rect->ymin, rect->ymax, BLI_rcti_size_x(rect), BLI_rcti_size_y(rect));
}
+
+
+/* -------------------------------------------------------------------- */
+/* Comprehensive math (float only) */
+
+/** \name Rect math functions
+ * \{ */
+
+#define ROTATE_SINCOS(r_vec, mat2, vec) { \
+ (r_vec)[0] = (mat2)[1] * (vec)[0] + (+(mat2)[0]) * (vec)[1]; \
+ (r_vec)[1] = (mat2)[0] * (vec)[0] + (-(mat2)[1]) * (vec)[1]; \
+} ((void)0)
+
+/**
+ * Expand the rectangle to fit a rotated \a src.
+ */
+void BLI_rctf_rotate_expand(rctf *dst, const rctf *src, const float angle)
+{
+ const float mat2[2] = {sinf(angle), cosf(angle)};
+ const float cent[2] = {BLI_rctf_cent_x(src), BLI_rctf_cent_y(src)};
+ float corner[2], corner_rot[2], corder_max[2];
+
+ /* x is same for both corners */
+ corner[0] = src->xmax - cent[0];
+ corner[1] = src->ymax - cent[1];
+ ROTATE_SINCOS(corner_rot, mat2, corner);
+ corder_max[0] = fabsf(corner_rot[0]);
+ corder_max[1] = fabsf(corner_rot[1]);
+
+ corner[1] *= -1;
+ ROTATE_SINCOS(corner_rot, mat2, corner);
+ corder_max[0] = MAX2(corder_max[0], fabsf(corner_rot[0]));
+ corder_max[1] = MAX2(corder_max[1], fabsf(corner_rot[1]));
+
+ dst->xmin = cent[0] - corder_max[0];
+ dst->xmax = cent[0] + corder_max[0];
+ dst->ymin = cent[1] - corder_max[1];
+ dst->ymax = cent[1] + corder_max[1];
+}
+
+#undef ROTATE_SINCOS
+
+/** \} */
diff --git a/source/blender/blenlib/intern/scanfill.c b/source/blender/blenlib/intern/scanfill.c
index cf0d8cff870..8a96daeeb91 100644
--- a/source/blender/blenlib/intern/scanfill.c
+++ b/source/blender/blenlib/intern/scanfill.c
@@ -173,13 +173,13 @@ static bool boundisect(PolyFill *pf2, PolyFill *pf1)
/* has pf2 been touched (intersected) by pf1 ? with bounding box */
/* test first if polys exist */
- if (pf1->edges == 0 || pf2->edges == 0) return 0;
+ if (pf1->edges == 0 || pf2->edges == 0) return false;
- if (pf2->max_xy[0] < pf1->min_xy[0]) return 0;
- if (pf2->max_xy[1] < pf1->min_xy[1]) return 0;
+ if (pf2->max_xy[0] < pf1->min_xy[0]) return false;
+ if (pf2->max_xy[1] < pf1->min_xy[1]) return false;
- if (pf2->min_xy[0] > pf1->max_xy[0]) return 0;
- if (pf2->min_xy[1] > pf1->max_xy[1]) return 0;
+ if (pf2->min_xy[0] > pf1->max_xy[0]) return false;
+ if (pf2->min_xy[1] > pf1->max_xy[1]) return false;
/* join */
if (pf2->max_xy[0] < pf1->max_xy[0]) pf2->max_xy[0] = pf1->max_xy[0];
@@ -188,7 +188,7 @@ static bool boundisect(PolyFill *pf2, PolyFill *pf1)
if (pf2->min_xy[0] > pf1->min_xy[0]) pf2->min_xy[0] = pf1->min_xy[0];
if (pf2->min_xy[1] > pf1->min_xy[1]) pf2->min_xy[1] = pf1->min_xy[1];
- return 1;
+ return true;
}
@@ -225,13 +225,13 @@ static bool testedgeside(const float v1[2], const float v2[2], const float v3[2]
(v1[1] - v2[1]) * (v1[0] - v3[0]);
if (inp < 0.0f) {
- return 0;
+ return false;
}
else if (inp == 0.0f) {
- if (v1[0] == v3[0] && v1[1] == v3[1]) return 0;
- if (v2[0] == v3[0] && v2[1] == v3[1]) return 0;
+ if (v1[0] == v3[0] && v1[1] == v3[1]) return false;
+ if (v2[0] == v3[0] && v2[1] == v3[1]) return false;
}
- return 1;
+ return true;
}
static bool addedgetoscanvert(ScanFillVertLink *sc, ScanFillEdge *eed)
@@ -261,7 +261,7 @@ static bool addedgetoscanvert(ScanFillVertLink *sc, ScanFillEdge *eed)
for (ed = sc->edge_first; ed; ed = ed->next) {
if (ed->v2 == eed->v2) {
- return 0;
+ return false;
}
fac = ed->v2->xy[1] - y;
@@ -279,7 +279,7 @@ static bool addedgetoscanvert(ScanFillVertLink *sc, ScanFillEdge *eed)
if (ed) BLI_insertlinkbefore((ListBase *)&(sc->edge_first), ed, eed);
else BLI_addtail((ListBase *)&(sc->edge_first), eed);
- return 1;
+ return true;
}
@@ -341,10 +341,10 @@ static bool boundinsideEV(ScanFillEdge *eed, ScanFillVert *eve)
maxy = eed->v1->xy[1];
}
if (eve->xy[1] >= miny && eve->xy[1] <= maxy) {
- return 1;
+ return true;
}
}
- return 0;
+ return false;
}
@@ -807,7 +807,7 @@ unsigned int BLI_scanfill_calc_ex(ScanFillContext *sf_ctx, const int flag, const
#if 0
if (flag & BLI_SCANFILL_CALC_QUADTRI_FASTPATH) {
- const int totverts = BLI_countlist(&sf_ctx->fillvertbase);
+ const int totverts = BLI_listbase_count(&sf_ctx->fillvertbase);
if (totverts == 3) {
eve = sf_ctx->fillvertbase.first;
diff --git a/source/blender/blenlib/intern/scanfill_utils.c b/source/blender/blenlib/intern/scanfill_utils.c
index 9fc1db1f1e4..059d5cb05a4 100644
--- a/source/blender/blenlib/intern/scanfill_utils.c
+++ b/source/blender/blenlib/intern/scanfill_utils.c
@@ -76,7 +76,7 @@ typedef struct ScanFillIsect {
#if 0
-void BKE_scanfill_obj_dump(ScanFillContext *sf_ctx)
+void BLI_scanfill_obj_dump(ScanFillContext *sf_ctx)
{
FILE *f = fopen("test.obj", "w");
unsigned int i = 1;
@@ -96,7 +96,7 @@ void BKE_scanfill_obj_dump(ScanFillContext *sf_ctx)
#endif
#if 0
-void BKE_scanfill_view3d_dump(ScanFillContext *sf_ctx)
+void BLI_scanfill_view3d_dump(ScanFillContext *sf_ctx)
{
ScanFillEdge *eed;
@@ -112,11 +112,13 @@ void BKE_scanfill_view3d_dump(ScanFillContext *sf_ctx)
static ListBase *edge_isect_ls_ensure(GHash *isect_hash, ScanFillEdge *eed)
{
ListBase *e_ls;
- e_ls = BLI_ghash_lookup(isect_hash, eed);
- if (e_ls == NULL) {
- e_ls = MEM_callocN(sizeof(ListBase), __func__);
- BLI_ghash_insert(isect_hash, eed, e_ls);
+ void **val_p;
+
+ if (!BLI_ghash_ensure_p(isect_hash, eed, &val_p)) {
+ *val_p = MEM_callocN(sizeof(ListBase), __func__);
}
+ e_ls = *val_p;
+
return e_ls;
}
@@ -136,8 +138,8 @@ static int edge_isect_ls_sort_cb(void *thunk, const void *def_a_ptr, const void
{
const float *co = thunk;
- const ScanFillIsect *i_a = ((LinkData *)def_a_ptr)->data;
- const ScanFillIsect *i_b = ((LinkData *)def_b_ptr)->data;
+ const ScanFillIsect *i_a = ((const LinkData *)def_a_ptr)->data;
+ const ScanFillIsect *i_b = ((const LinkData *)def_b_ptr)->data;
const float a = len_squared_v2v2(co, i_a->co);
const float b = len_squared_v2v2(co, i_b->co);
@@ -265,7 +267,7 @@ static bool scanfill_preprocess_self_isect(
}
if (BLI_listbase_is_single(e_ls) == false) {
- BLI_sortlist_r(e_ls, eed->v2->co, edge_isect_ls_sort_cb);
+ BLI_listbase_sort_r(e_ls, edge_isect_ls_sort_cb, eed->v2->co);
}
/* move original edge to filledgebase and add replacement
@@ -508,8 +510,8 @@ bool BLI_scanfill_calc_self_isect(
sf_ctx->poly_nr = SF_POLY_UNSET;
#if 0
- BKE_scanfill_view3d_dump(sf_ctx);
- BKE_scanfill_obj_dump(sf_ctx);
+ BLI_scanfill_view3d_dump(sf_ctx);
+ BLI_scanfill_obj_dump(sf_ctx);
#endif
return changed;
diff --git a/source/blender/blenlib/intern/smallhash.c b/source/blender/blenlib/intern/smallhash.c
index 0cf9f69b9ae..ba336ab6c4b 100644
--- a/source/blender/blenlib/intern/smallhash.c
+++ b/source/blender/blenlib/intern/smallhash.c
@@ -118,7 +118,7 @@ BLI_INLINE void smallhash_buckets_reserve(SmallHash *sh, const unsigned int nent
}
}
-BLI_INLINE SmallHashEntry *smallhash_lookup(SmallHash *sh, const uintptr_t key)
+BLI_INLINE SmallHashEntry *smallhash_lookup(const SmallHash *sh, const uintptr_t key)
{
SmallHashEntry *e;
unsigned int h = smallhash_key(key);
@@ -246,6 +246,26 @@ void BLI_smallhash_insert(SmallHash *sh, uintptr_t key, void *val)
e->val = val;
}
+/**
+ * Inserts a new value to a key that may already be in ghash.
+ *
+ * Avoids #BLI_smallhash_remove, #BLI_smallhash_insert calls (double lookups)
+ *
+ * \returns true if a new key has been added.
+ */
+bool BLI_smallhash_reinsert(SmallHash *sh, uintptr_t key, void *item)
+{
+ SmallHashEntry *e = smallhash_lookup(sh, key);
+ if (e) {
+ e->val = item;
+ return false;
+ }
+ else {
+ BLI_smallhash_insert(sh, key, item);
+ return true;
+ }
+}
+
#ifdef USE_REMOVE
bool BLI_smallhash_remove(SmallHash *sh, uintptr_t key)
{
@@ -264,33 +284,33 @@ bool BLI_smallhash_remove(SmallHash *sh, uintptr_t key)
}
#endif
-void *BLI_smallhash_lookup(SmallHash *sh, uintptr_t key)
+void *BLI_smallhash_lookup(const SmallHash *sh, uintptr_t key)
{
SmallHashEntry *e = smallhash_lookup(sh, key);
return e ? e->val : NULL;
}
-void **BLI_smallhash_lookup_p(SmallHash *sh, uintptr_t key)
+void **BLI_smallhash_lookup_p(const SmallHash *sh, uintptr_t key)
{
SmallHashEntry *e = smallhash_lookup(sh, key);
return e ? &e->val : NULL;
}
-bool BLI_smallhash_haskey(SmallHash *sh, uintptr_t key)
+bool BLI_smallhash_haskey(const SmallHash *sh, uintptr_t key)
{
SmallHashEntry *e = smallhash_lookup(sh, key);
return (e != NULL);
}
-int BLI_smallhash_count(SmallHash *sh)
+int BLI_smallhash_count(const SmallHash *sh)
{
return (int)sh->nentries;
}
-void *BLI_smallhash_iternext(SmallHashIter *iter, uintptr_t *key)
+BLI_INLINE SmallHashEntry *smallhash_iternext(SmallHashIter *iter, uintptr_t *key)
{
while (iter->i < iter->sh->nbuckets) {
if (smallhash_val_is_used(iter->sh->buckets[iter->i].val)) {
@@ -298,7 +318,7 @@ void *BLI_smallhash_iternext(SmallHashIter *iter, uintptr_t *key)
*key = iter->sh->buckets[iter->i].key;
}
- return iter->sh->buckets[iter->i++].val;
+ return &iter->sh->buckets[iter->i++];
}
iter->i++;
@@ -307,7 +327,21 @@ void *BLI_smallhash_iternext(SmallHashIter *iter, uintptr_t *key)
return NULL;
}
-void *BLI_smallhash_iternew(SmallHash *sh, SmallHashIter *iter, uintptr_t *key)
+void *BLI_smallhash_iternext(SmallHashIter *iter, uintptr_t *key)
+{
+ SmallHashEntry *e = smallhash_iternext(iter, key);
+
+ return e ? e->val : NULL;
+}
+
+void **BLI_smallhash_iternext_p(SmallHashIter *iter, uintptr_t *key)
+{
+ SmallHashEntry *e = smallhash_iternext(iter, key);
+
+ return e ? &e->val : NULL;
+}
+
+void *BLI_smallhash_iternew(const SmallHash *sh, SmallHashIter *iter, uintptr_t *key)
{
iter->sh = sh;
iter->i = 0;
@@ -315,6 +349,15 @@ void *BLI_smallhash_iternew(SmallHash *sh, SmallHashIter *iter, uintptr_t *key)
return BLI_smallhash_iternext(iter, key);
}
+void **BLI_smallhash_iternew_p(const SmallHash *sh, SmallHashIter *iter, uintptr_t *key)
+{
+ iter->sh = sh;
+ iter->i = 0;
+
+ return BLI_smallhash_iternext_p(iter, key);
+}
+
+
/** \name Debugging & Introspection
* \{ */
diff --git a/source/blender/blenlib/intern/sort.c b/source/blender/blenlib/intern/sort.c
index 9fad7505f79..c5922feb0ed 100644
--- a/source/blender/blenlib/intern/sort.c
+++ b/source/blender/blenlib/intern/sort.c
@@ -32,7 +32,9 @@
#include <stdlib.h>
-#ifndef __GLIBC__
+#if defined(__GLIBC__) && (__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 8))
+/* do nothing! */
+#else
#include "BLI_utildefines.h"
diff --git a/source/blender/blenlib/intern/stack.c b/source/blender/blenlib/intern/stack.c
index 58029120de9..084d692fcf0 100644
--- a/source/blender/blenlib/intern/stack.c
+++ b/source/blender/blenlib/intern/stack.c
@@ -48,8 +48,6 @@
((void)0, (((char *)(_stack)->chunk_curr->data) + \
((_stack)->elem_size * (_stack)->chunk_index)))
-#define IS_POW2(a) (((a) & ((a) - 1)) == 0)
-
struct StackChunk {
struct StackChunk *next;
char data[0];
@@ -96,11 +94,6 @@ BLI_Stack *BLI_stack_new_ex(const size_t elem_size, const char *description,
/* force init */
stack->chunk_index = stack->chunk_elem_max - 1;
- /* ensure we have a correctly rounded size */
- BLI_assert((IS_POW2(stack->elem_size) == 0) ||
- (IS_POW2((stack->chunk_elem_max * stack->elem_size) +
- (sizeof(struct StackChunk) + MEM_SIZE_OVERHEAD))));
-
return stack;
}
@@ -132,8 +125,10 @@ void BLI_stack_free(BLI_Stack *stack)
}
/**
- * Copies the source value onto the stack (note that it copies
- * elem_size bytes from 'src', the pointer itself is not stored)
+ * Push a new item onto the stack.
+ *
+ * \return a pointer #BLI_Stack.elem_size
+ * bytes of uninitialized memory (caller must fill in).
*/
void *BLI_stack_push_r(BLI_Stack *stack)
{
@@ -165,6 +160,14 @@ void *BLI_stack_push_r(BLI_Stack *stack)
return CHUNK_LAST_ELEM(stack);
}
+/**
+ * Copies the source value onto the stack
+ *
+ * \note This copies #BLI_Stack.elem_size bytes from \a src,
+ * (the pointer itself is not stored).
+ *
+ * \param src: source data to be copied to the stack.
+ */
void BLI_stack_push(BLI_Stack *stack, const void *src)
{
void *dst = BLI_stack_push_r(stack);
@@ -182,6 +185,60 @@ void BLI_stack_pop(BLI_Stack *stack, void *dst)
BLI_assert(BLI_stack_is_empty(stack) == false);
memcpy(dst, CHUNK_LAST_ELEM(stack), stack->elem_size);
+
+ BLI_stack_discard(stack);
+}
+
+/**
+ * A version of #BLI_stack_pop which which fills in an array.
+ *
+ * \param dst: The destination array,
+ * must be at least (#BLI_Stack.elem_size * \a n) bytes long.
+ * \param n: The number of items to pop.
+ *
+ * \note The first item in the array will be last item added to the stack.
+ */
+void BLI_stack_pop_n(BLI_Stack *stack, void *dst, unsigned int n)
+{
+ BLI_assert(n <= BLI_stack_count(stack));
+
+ while (n--) {
+ BLI_stack_pop(stack, dst);
+ dst = (void *)((char *)dst + stack->elem_size);
+ }
+}
+
+/**
+ * A version of #BLI_stack_pop_n which which fills in an array (in the reverse order).
+ *
+ * \note The first item in the array will be first item added to the stack.
+ */
+void BLI_stack_pop_n_reverse(BLI_Stack *stack, void *dst, unsigned int n)
+{
+ BLI_assert(n <= BLI_stack_count(stack));
+
+ dst = (void *)((char *)dst + (stack->elem_size * n));
+
+ while (n--) {
+ dst = (void *)((char *)dst - stack->elem_size);
+ BLI_stack_pop(stack, dst);
+ }
+}
+
+void *BLI_stack_peek(BLI_Stack *stack)
+{
+ BLI_assert(BLI_stack_is_empty(stack) == false);
+
+ return CHUNK_LAST_ELEM(stack);
+}
+
+/**
+ * Removes the top element from the stack.
+ */
+void BLI_stack_discard(BLI_Stack *stack)
+{
+ BLI_assert(BLI_stack_is_empty(stack) == false);
+
#ifdef USE_TOTELEM
stack->totelem--;
#endif
@@ -198,13 +255,38 @@ void BLI_stack_pop(BLI_Stack *stack, void *dst)
}
}
-void BLI_stack_pop_n(BLI_Stack *stack, void *dst, unsigned int n)
+/**
+ * Discards all elements without freeing.
+ */
+void BLI_stack_clear(BLI_Stack *stack)
{
- BLI_assert(n <= BLI_stack_count(stack));
+#ifdef USE_TOTELEM
+ if (UNLIKELY(stack->totelem == 0)) {
+ return;
+ }
+ stack->totelem = 0;
+#else
+ if (UNLIKELY(stack->chunk_curr == NULL)) {
+ return;
+ }
+#endif
- while (n--) {
- BLI_stack_pop(stack, dst);
- dst = (void *)((char *)dst + stack->elem_size);
+ stack->chunk_index = stack->chunk_elem_max - 1;
+
+ if (stack->chunk_free) {
+ if (stack->chunk_curr) {
+ /* move all used chunks into tail of free list */
+ struct StackChunk *chunk_free_last = stack->chunk_free;
+ while (chunk_free_last->next) {
+ chunk_free_last = chunk_free_last->next;
+ }
+ chunk_free_last->next = stack->chunk_curr;
+ stack->chunk_curr = NULL;
+ }
+ }
+ else {
+ stack->chunk_free = stack->chunk_curr;
+ stack->chunk_curr = NULL;
}
}
diff --git a/source/blender/blenlib/intern/storage.c b/source/blender/blenlib/intern/storage.c
index f3ecc799e1e..7fdf6ec8101 100644
--- a/source/blender/blenlib/intern/storage.c
+++ b/source/blender/blenlib/intern/storage.c
@@ -35,11 +35,6 @@
#include <stdio.h>
#include <stdlib.h>
-#ifndef WIN32
-# include <dirent.h>
-#endif
-
-#include <time.h>
#include <sys/stat.h>
#if defined(__NetBSD__) || defined(__DragonFly__) || defined(__sun__) || defined(__sun)
@@ -79,17 +74,13 @@
/* lib includes */
#include "MEM_guardedalloc.h"
-#include "DNA_listBase.h"
-
-#include "BLI_listbase.h"
+#include "BLI_utildefines.h"
#include "BLI_linklist.h"
#include "BLI_string.h"
#include "BLI_fileops.h"
#include "BLI_fileops_types.h"
#include "BLI_path_util.h"
-#include "../imbuf/IMB_imbuf.h"
-
/**
* Copies the current working directory into *dir (max size maxncpy), and
* returns a pointer to same.
@@ -107,42 +98,6 @@ char *BLI_current_working_dir(char *dir, const size_t maxncpy)
return getcwd(dir, maxncpy);
}
-/*
- * Ordering function for sorting lists of files/directories. Returns -1 if
- * entry1 belongs before entry2, 0 if they are equal, 1 if they should be swapped.
- */
-static int bli_compare(struct direntry *entry1, struct direntry *entry2)
-{
- /* type is equal to stat.st_mode */
-
- /* directories come before non-directories */
- if (S_ISDIR(entry1->type)) {
- if (S_ISDIR(entry2->type) == 0) return (-1);
- }
- else {
- if (S_ISDIR(entry2->type)) return (1);
- }
- /* non-regular files come after regular files */
- if (S_ISREG(entry1->type)) {
- if (S_ISREG(entry2->type) == 0) return (-1);
- }
- else {
- if (S_ISREG(entry2->type)) return (1);
- }
- /* arbitrary, but consistent, ordering of different types of non-regular files */
- if ((entry1->type & S_IFMT) < (entry2->type & S_IFMT)) return (-1);
- if ((entry1->type & S_IFMT) > (entry2->type & S_IFMT)) return (1);
-
- /* OK, now we know their S_IFMT fields are the same, go on to a name comparison */
- /* make sure "." and ".." are always first */
- if (strcmp(entry1->relname, ".") == 0) return (-1);
- if (strcmp(entry2->relname, ".") == 0) return (1);
- if (strcmp(entry1->relname, "..") == 0) return (-1);
- if (strcmp(entry2->relname, "..") == 0) return (1);
-
- return (BLI_natstrcmp(entry1->relname, entry2->relname));
-}
-
/**
* Returns the number of free bytes on the volume containing the specified pathname. */
/* Not actually used anywhere.
@@ -204,230 +159,6 @@ double BLI_dir_free_space(const char *dir)
#endif
}
-struct BuildDirCtx {
- struct direntry *files; /* array[nrfiles] */
- int nrfiles;
-};
-
-/**
- * Scans the directory named *dirname and appends entries for its contents to files.
- */
-static void bli_builddir(struct BuildDirCtx *dir_ctx, const char *dirname)
-{
- struct ListBase dirbase = {NULL, NULL};
- int newnum = 0;
- DIR *dir;
-
- if ((dir = opendir(dirname)) != NULL) {
-
- const struct dirent *fname;
- while ((fname = readdir(dir)) != NULL) {
- struct dirlink * const dlink = (struct dirlink *)malloc(sizeof(struct dirlink));
- if (dlink != NULL) {
- dlink->name = BLI_strdup(fname->d_name);
- BLI_addhead(&dirbase, dlink);
- newnum++;
- }
- }
-
- if (newnum) {
-
- if (dir_ctx->files) {
- void * const tmp = realloc(dir_ctx->files, (dir_ctx->nrfiles + newnum) * sizeof(struct direntry));
- if (tmp) {
- dir_ctx->files = (struct direntry *)tmp;
- }
- else { /* realloc fail */
- free(dir_ctx->files);
- dir_ctx->files = NULL;
- }
- }
-
- if (dir_ctx->files == NULL)
- dir_ctx->files = (struct direntry *)malloc(newnum * sizeof(struct direntry));
-
- if (dir_ctx->files) {
- struct dirlink * dlink = (struct dirlink *) dirbase.first;
- struct direntry *file = &dir_ctx->files[dir_ctx->nrfiles];
- while (dlink) {
- char fullname[PATH_MAX];
- memset(file, 0, sizeof(struct direntry));
- file->relname = dlink->name;
- file->path = BLI_strdupcat(dirname, dlink->name);
- BLI_join_dirfile(fullname, sizeof(fullname), dirname, dlink->name);
- BLI_stat(fullname, &file->s);
- file->type = file->s.st_mode;
- file->flags = 0;
- dir_ctx->nrfiles++;
- file++;
- dlink = dlink->next;
- }
- }
- else {
- printf("Couldn't get memory for dir\n");
- exit(1);
- }
-
- BLI_freelist(&dirbase);
- if (dir_ctx->files) {
- qsort(dir_ctx->files, dir_ctx->nrfiles, sizeof(struct direntry), (int (*)(const void *, const void *))bli_compare);
- }
- }
- else {
- printf("%s empty directory\n", dirname);
- }
-
- closedir(dir);
- }
- else {
- printf("%s non-existant directory\n", dirname);
- }
-}
-
-/**
- * Fills in the "mode[123]", "size" and "string" fields in the elements of the files
- * array with descriptive details about each item. "string" will have a format similar to "ls -l".
- */
-static void bli_adddirstrings(struct BuildDirCtx *dir_ctx)
-{
- const char *types[8] = {"---", "--x", "-w-", "-wx", "r--", "r-x", "rw-", "rwx"};
- /* symbolic display, indexed by mode field value */
- int num;
-#ifdef WIN32
- __int64 st_size;
-#else
- off_t st_size;
- int mode;
-#endif
-
- struct direntry *file;
- struct tm *tm;
- time_t zero = 0;
-
- for (num = 0, file = dir_ctx->files; num < dir_ctx->nrfiles; num++, file++) {
-
-
- /* Mode */
-#ifdef WIN32
- BLI_strncpy(file->mode1, types[0], sizeof(file->mode1));
- BLI_strncpy(file->mode2, types[0], sizeof(file->mode2));
- BLI_strncpy(file->mode3, types[0], sizeof(file->mode3));
-#else
- mode = file->s.st_mode;
-
- BLI_strncpy(file->mode1, types[(mode & 0700) >> 6], sizeof(file->mode1));
- BLI_strncpy(file->mode2, types[(mode & 0070) >> 3], sizeof(file->mode2));
- BLI_strncpy(file->mode3, types[(mode & 0007)], sizeof(file->mode3));
-
- if (((mode & S_ISGID) == S_ISGID) && (file->mode2[2] == '-')) file->mode2[2] = 'l';
-
- if (mode & (S_ISUID | S_ISGID)) {
- if (file->mode1[2] == 'x') file->mode1[2] = 's';
- else file->mode1[2] = 'S';
-
- if (file->mode2[2] == 'x') file->mode2[2] = 's';
- }
-
- if (mode & S_ISVTX) {
- if (file->mode3[2] == 'x') file->mode3[2] = 't';
- else file->mode3[2] = 'T';
- }
-#endif
-
-
- /* User */
-#ifdef WIN32
- strcpy(file->owner, "user");
-#else
- {
- struct passwd *pwuser;
- pwuser = getpwuid(file->s.st_uid);
- if (pwuser) {
- BLI_strncpy(file->owner, pwuser->pw_name, sizeof(file->owner));
- }
- else {
- BLI_snprintf(file->owner, sizeof(file->owner), "%u", file->s.st_uid);
- }
- }
-#endif
-
-
- /* Time */
- tm = localtime(&file->s.st_mtime);
- // prevent impossible dates in windows
- if (tm == NULL) tm = localtime(&zero);
- strftime(file->time, sizeof(file->time), "%H:%M", tm);
- strftime(file->date, sizeof(file->date), "%d-%b-%y", tm);
-
-
- /* Size */
- /*
- * Seems st_size is signed 32-bit value in *nix and Windows. This
- * will buy us some time until files get bigger than 4GB or until
- * everyone starts using __USE_FILE_OFFSET64 or equivalent.
- */
- st_size = file->s.st_size;
-
- if (st_size > 1024 * 1024 * 1024) {
- BLI_snprintf(file->size, sizeof(file->size), "%.2f GiB", ((double)st_size) / (1024 * 1024 * 1024));
- }
- else if (st_size > 1024 * 1024) {
- BLI_snprintf(file->size, sizeof(file->size), "%.1f MiB", ((double)st_size) / (1024 * 1024));
- }
- else if (st_size > 1024) {
- BLI_snprintf(file->size, sizeof(file->size), "%d KiB", (int)(st_size / 1024));
- }
- else {
- BLI_snprintf(file->size, sizeof(file->size), "%d B", (int)st_size);
- }
- }
-}
-
-/**
- * Scans the contents of the directory named *dirname, and allocates and fills in an
- * array of entries describing them in *filelist. The length of the array is the function result.
- */
-unsigned int BLI_dir_contents(const char *dirname, struct direntry **filelist)
-{
- struct BuildDirCtx dir_ctx;
-
- dir_ctx.nrfiles = 0;
- dir_ctx.files = NULL;
-
- bli_builddir(&dir_ctx, dirname);
- bli_adddirstrings(&dir_ctx);
-
- if (dir_ctx.files) {
- *filelist = dir_ctx.files;
- }
- else {
- // keep blender happy. Blender stores this in a variable
- // where 0 has special meaning.....
- *filelist = malloc(sizeof(struct direntry));
- }
-
- return dir_ctx.nrfiles;
-}
-
-/* frees storage for an array of direntries, including the array itself. */
-void BLI_free_filelist(struct direntry *filelist, unsigned int nrentries)
-{
- unsigned int i;
- for (i = 0; i < nrentries; ++i) {
- struct direntry * const entry = filelist + i;
- if (entry->image) {
- IMB_freeImBuf(entry->image);
- }
- if (entry->relname)
- MEM_freeN(entry->relname);
- if (entry->path)
- MEM_freeN(entry->path);
- /* entry->poin assumed not to point to anything needing freeing here */
- }
-
- free(filelist);
-}
-
/**
* Returns the file size of an opened file descriptor.
@@ -495,6 +226,8 @@ int BLI_exists(const char *name)
if (res == -1) return(0);
#else
struct stat st;
+ BLI_assert(name);
+ BLI_assert(!BLI_path_is_rel(name));
if (stat(name, &st)) return(0);
#endif
return(st.st_mode);
@@ -554,7 +287,7 @@ bool BLI_is_file(const char *path)
LinkNode *BLI_file_read_as_lines(const char *name)
{
FILE *fp = BLI_fopen(name, "r");
- LinkNode *lines = NULL;
+ LinkNodePair lines = {NULL, NULL};
char *buf;
size_t size;
@@ -564,6 +297,11 @@ LinkNode *BLI_file_read_as_lines(const char *name)
size = (size_t)ftell(fp);
fseek(fp, 0, SEEK_SET);
+ if (UNLIKELY(size == (size_t)-1)) {
+ fclose(fp);
+ return NULL;
+ }
+
buf = MEM_mallocN(size, "file_as_lines");
if (buf) {
size_t i, last = 0;
@@ -578,7 +316,7 @@ LinkNode *BLI_file_read_as_lines(const char *name)
if (i == size || buf[i] == '\n') {
char *line = BLI_strdupn(&buf[last], i - last);
- BLI_linklist_prepend(&lines, line);
+ BLI_linklist_append(&lines, line);
/* faster to build singly-linked list in reverse order */
/* alternatively, could process buffer in reverse order so
* list ends up right way round to start with */
@@ -591,9 +329,7 @@ LinkNode *BLI_file_read_as_lines(const char *name)
fclose(fp);
- /* get them the right way round */
- BLI_linklist_reverse(&lines);
- return lines;
+ return lines.list;
}
/*
@@ -636,4 +372,3 @@ bool BLI_file_older(const char *file1, const char *file2)
#endif
return (st1.st_mtime < st2.st_mtime);
}
-
diff --git a/source/blender/blenlib/intern/string.c b/source/blender/blenlib/intern/string.c
index eeafc1a9e8f..e93d2b7507a 100644
--- a/source/blender/blenlib/intern/string.c
+++ b/source/blender/blenlib/intern/string.c
@@ -126,6 +126,54 @@ char *BLI_strncpy(char *__restrict dst, const char *__restrict src, const size_t
}
/**
+ * Like BLI_strncpy but ensures dst is always padded by given char, on both sides (unless src is empty).
+ *
+ * \param dst Destination for copy
+ * \param src Source string to copy
+ * \param pad the char to use for padding
+ * \param maxncpy Maximum number of characters to copy (generally the size of dst)
+ * \retval Returns dst
+ */
+char *BLI_strncpy_ensure_pad(char *__restrict dst, const char *__restrict src, const char pad, size_t maxncpy)
+{
+ BLI_assert(maxncpy != 0);
+
+#ifdef DEBUG_STRSIZE
+ memset(dst, 0xff, sizeof(*dst) * maxncpy);
+#endif
+
+ if (src[0] == '\0') {
+ dst[0] = '\0';
+ }
+ else {
+ /* Add heading/trailing wildcards if needed. */
+ size_t idx = 0;
+ size_t srclen;
+
+ if (src[idx] != pad) {
+ dst[idx++] = pad;
+ maxncpy--;
+ }
+ maxncpy--; /* trailing '\0' */
+
+ srclen = BLI_strnlen(src, maxncpy);
+ if ((src[srclen - 1] != pad) && (srclen == maxncpy)) {
+ srclen--;
+ }
+
+ memcpy(&dst[idx], src, srclen);
+ idx += srclen;
+
+ if (dst[idx - 1] != pad) {
+ dst[idx++] = pad;
+ }
+ dst[idx] = '\0';
+ }
+
+ return dst;
+}
+
+/**
* Like strncpy but ensures dst is always
* '\0' terminated.
*
@@ -183,6 +231,30 @@ size_t BLI_vsnprintf(char *__restrict buffer, size_t maxncpy, const char *__rest
}
/**
+ * A version of #BLI_vsnprintf that returns ``strlen(buffer)``
+ */
+size_t BLI_vsnprintf_rlen(char *__restrict buffer, size_t maxncpy, const char *__restrict format, va_list arg)
+{
+ size_t n;
+
+ BLI_assert(buffer != NULL);
+ BLI_assert(maxncpy > 0);
+ BLI_assert(format != NULL);
+
+ n = (size_t)vsnprintf(buffer, maxncpy, format, arg);
+
+ if (n != -1 && n < maxncpy) {
+ /* pass */
+ }
+ else {
+ n = maxncpy - 1;
+ }
+ buffer[n] = '\0';
+
+ return n;
+}
+
+/**
* Portable replacement for #snprintf
*/
size_t BLI_snprintf(char *__restrict dst, size_t maxncpy, const char *__restrict format, ...)
@@ -202,6 +274,25 @@ size_t BLI_snprintf(char *__restrict dst, size_t maxncpy, const char *__restrict
}
/**
+ * A version of #BLI_snprintf that returns ``strlen(dst)``
+ */
+size_t BLI_snprintf_rlen(char *__restrict dst, size_t maxncpy, const char *__restrict format, ...)
+{
+ size_t n;
+ va_list arg;
+
+#ifdef DEBUG_STRSIZE
+ memset(dst, 0xff, sizeof(*dst) * maxncpy);
+#endif
+
+ va_start(arg, format);
+ n = BLI_vsnprintf_rlen(dst, maxncpy, format, arg);
+ va_end(arg);
+
+ return n;
+}
+
+/**
* Print formatted string into a newly #MEM_mallocN'd string
* and return it.
*/
@@ -288,12 +379,13 @@ escape_finish:
*/
char *BLI_str_quoted_substrN(const char *__restrict str, const char *__restrict prefix)
{
- size_t prefixLen = strlen(prefix);
const char *startMatch, *endMatch;
-
+
/* get the starting point (i.e. where prefix starts, and add prefixLen+1 to it to get be after the first " */
- startMatch = strstr(str, prefix) + prefixLen + 1;
+ startMatch = strstr(str, prefix);
if (startMatch) {
+ const size_t prefixLen = strlen(prefix);
+ startMatch += prefixLen + 1;
/* get the end point (i.e. where the next occurance of " is after the starting point) */
endMatch = startMatch;
@@ -327,7 +419,7 @@ char *BLI_str_quoted_substrN(const char *__restrict str, const char *__restrict
* \param substr_new The text in the string to find and replace
* \retval Returns the duplicated string
*/
-char *BLI_replacestrN(const char *__restrict str, const char *__restrict substr_old, const char *__restrict substr_new)
+char *BLI_str_replaceN(const char *__restrict str, const char *__restrict substr_old, const char *__restrict substr_new)
{
DynStr *ds = NULL;
size_t len_old = strlen(substr_old);
@@ -386,6 +478,23 @@ char *BLI_replacestrN(const char *__restrict str, const char *__restrict substr_
}
/**
+ * In-place replace every \a src to \a dst in \a str.
+ *
+ * \param str: The string to operate on.
+ * \param src: The character to replace.
+ * \param dst: The character to replace with.
+ */
+void BLI_str_replace_char(char *str, char src, char dst)
+{
+ while (*str) {
+ if (*str == src) {
+ *str = dst;
+ }
+ str++;
+ }
+}
+
+/**
* Compare two strings without regard to case.
*
* \retval True if the strings are equal, false otherwise.
@@ -566,19 +675,47 @@ int BLI_natstrcmp(const char *s1, const char *s2)
return strcmp(s1, s2);
}
-void BLI_timestr(double _time, char *str, size_t maxlen)
+/**
+ * Like strcmp, but will ignore any heading/trailing pad char for comparison.
+ * So e.g. if pad is '*', '*world' and 'world*' will compare equal.
+ */
+int BLI_strcmp_ignore_pad(const char *str1, const char *str2, const char pad)
{
- /* format 00:00:00.00 (hr:min:sec) string has to be 12 long */
- int hr = ( (int) _time) / (60 * 60);
- int min = (((int) _time) / 60 ) % 60;
- int sec = ( (int) _time) % 60;
- int hun = ( (int) (_time * 100.0)) % 100;
+ size_t str1_len, str2_len;
+
+ while (*str1 == pad) {
+ str1++;
+ }
+ while (*str2 == pad) {
+ str2++;
+ }
+
+ str1_len = strlen(str1);
+ str2_len = strlen(str2);
+
+ while (str1_len && (str1[str1_len - 1] == pad)) {
+ str1_len--;
+ }
+ while (str2_len && (str2[str2_len - 1] == pad)) {
+ str2_len--;
+ }
- if (hr) {
- BLI_snprintf(str, maxlen, "%.2d:%.2d:%.2d.%.2d", hr, min, sec, hun);
+ if (str1_len == str2_len) {
+ return strncmp(str1, str2, str2_len);
+ }
+ else if (str1_len > str2_len) {
+ int ret = strncmp(str1, str2, str2_len);
+ if (ret == 0) {
+ ret = 1;
+ }
+ return ret;
}
else {
- BLI_snprintf(str, maxlen, "%.2d:%.2d.%.2d", min, sec, hun);
+ int ret = strncmp(str1, str2, str1_len);
+ if (ret == 0) {
+ ret = -1;
+ }
+ return ret;
}
}
@@ -594,7 +731,7 @@ size_t BLI_strnlen(const char *s, const size_t maxlen)
return len;
}
-void BLI_ascii_strtolower(char *str, const size_t len)
+void BLI_str_tolower_ascii(char *str, const size_t len)
{
size_t i;
@@ -603,7 +740,7 @@ void BLI_ascii_strtolower(char *str, const size_t len)
str[i] += 'a' - 'A';
}
-void BLI_ascii_strtoupper(char *str, const size_t len)
+void BLI_str_toupper_ascii(char *str, const size_t len)
{
size_t i;
@@ -619,7 +756,7 @@ void BLI_ascii_strtoupper(char *str, const size_t len)
*
* \param str
* \param pad
- * \return The number of zeto's stripped.
+ * \return The number of zeros stripped.
*/
int BLI_str_rstrip_float_zero(char *str, const char pad)
{
@@ -681,6 +818,35 @@ int BLI_str_index_in_array(const char *__restrict str, const char **__restrict s
return -1;
}
+bool BLI_strn_endswith(const char *__restrict str, const char *__restrict end, size_t slength)
+{
+ size_t elength = strlen(end);
+
+ if (elength < slength) {
+ const char *iter = &str[slength - elength];
+ while (*iter) {
+ if (*iter++ != *end++) {
+ return false;
+ }
+ }
+ return true;
+ }
+ return false;
+}
+
+/**
+ * Find if a string ends with another string.
+ *
+ * \param str The string to search within.
+ * \param end The string we look for at the end.
+ * \return If str ends with end.
+ */
+bool BLI_str_endswith(const char *__restrict str, const char *end)
+{
+ const size_t slength = strlen(str);
+ return BLI_strn_endswith(str, end, slength);
+}
+
/**
* Find the first char matching one of the chars in \a delim, from left.
*
@@ -690,9 +856,9 @@ int BLI_str_index_in_array(const char *__restrict str, const char **__restrict s
* \param suf Return value, set to next char after the first delimiter found (or NULL if none found).
* \return The length of the prefix (i.e. *sep - str).
*/
-size_t BLI_str_partition(const char *str, const char delim[], char **sep, char **suf)
+size_t BLI_str_partition(const char *str, const char delim[], const char **sep, const char **suf)
{
- return BLI_str_partition_ex(str, delim, sep, suf, false);
+ return BLI_str_partition_ex(str, NULL, delim, sep, suf, false);
}
/**
@@ -704,30 +870,52 @@ size_t BLI_str_partition(const char *str, const char delim[], char **sep, char *
* \param suf Return value, set to next char after the first delimiter found (or NULL if none found).
* \return The length of the prefix (i.e. *sep - str).
*/
-size_t BLI_str_rpartition(const char *str, const char delim[], char **sep, char **suf)
+size_t BLI_str_rpartition(const char *str, const char delim[], const char **sep, const char **suf)
{
- return BLI_str_partition_ex(str, delim, sep, suf, true);
+ return BLI_str_partition_ex(str, NULL, delim, sep, suf, true);
}
/**
* Find the first char matching one of the chars in \a delim, either from left or right.
*
* \param str The string to search within.
+ * \param end If non-NULL, the right delimiter of the string.
* \param delim The set of delimiters to search for, as unicode values.
* \param sep Return value, set to the first delimiter found (or NULL if none found).
* \param suf Return value, set to next char after the first delimiter found (or NULL if none found).
* \param from_right If %true, search from the right of \a str, else, search from its left.
* \return The length of the prefix (i.e. *sep - str).
*/
-size_t BLI_str_partition_ex(const char *str, const char delim[], char **sep, char **suf, const bool from_right)
+size_t BLI_str_partition_ex(
+ const char *str, const char *end, const char delim[], const char **sep, const char **suf, const bool from_right)
{
const char *d;
char *(*func)(const char *str, int c) = from_right ? strrchr : strchr;
+ BLI_assert(end == NULL || end > str);
+
*sep = *suf = NULL;
for (d = delim; *d != '\0'; ++d) {
- char *tmp = func(str, *d);
+ const char *tmp;
+
+ if (end) {
+ if (from_right) {
+ for (tmp = end - 1; (tmp >= str) && (*tmp != *d); tmp--);
+ if (tmp < str) {
+ tmp = NULL;
+ }
+ }
+ else {
+ tmp = func(str, *d);
+ if (tmp >= end) {
+ tmp = NULL;
+ }
+ }
+ }
+ else {
+ tmp = func(str, *d);
+ }
if (tmp && (from_right ? (*sep < tmp) : (!*sep || *sep > tmp))) {
*sep = tmp;
@@ -739,7 +927,7 @@ size_t BLI_str_partition_ex(const char *str, const char delim[], char **sep, cha
return (size_t)(*sep - str);
}
- return strlen(str);
+ return end ? (size_t)(end - str) : strlen(str);
}
/**
diff --git a/source/blender/blenlib/intern/string_utf8.c b/source/blender/blenlib/intern/string_utf8.c
index 9697fcf09e9..96033615cf5 100644
--- a/source/blender/blenlib/intern/string_utf8.c
+++ b/source/blender/blenlib/intern/string_utf8.c
@@ -69,11 +69,11 @@ static const char trailingBytesForUTF8[256] = {
int BLI_utf8_invalid_byte(const char *str, int length)
{
- const unsigned char *p, *pend = (unsigned char *)str + length;
+ const unsigned char *p, *pend = (const unsigned char *)str + length;
unsigned char c;
int ab;
- for (p = (unsigned char *)str; p < pend; p++) {
+ for (p = (const unsigned char *)str; p < pend; p++) {
c = *p;
if (c < 128)
continue;
@@ -130,7 +130,7 @@ int BLI_utf8_invalid_byte(const char *str, int length)
utf8_error:
- return (int)((char *)p - (char *)str) - 1;
+ return (int)((const char *)p - (const char *)str) - 1;
}
int BLI_utf8_invalid_strip(char *str, int length)
@@ -209,6 +209,22 @@ char *BLI_strncpy_utf8(char *__restrict dst, const char *__restrict src, size_t
return r_dst;
}
+size_t BLI_strncpy_utf8_rlen(char *__restrict dst, const char *__restrict src, size_t maxncpy)
+{
+ char *r_dst = dst;
+
+ BLI_assert(maxncpy != 0);
+
+#ifdef DEBUG_STRSIZE
+ memset(dst, 0xff, sizeof(*dst) * maxncpy);
+#endif
+
+ /* note: currently we don't attempt to deal with invalid utf8 chars */
+ BLI_STR_UTF8_CPY(dst, src, maxncpy);
+
+ return (size_t)(dst - r_dst);
+}
+
char *BLI_strncat_utf8(char *__restrict dst, const char *__restrict src, size_t maxncpy)
{
while (*dst && maxncpy > 0) {
@@ -233,6 +249,7 @@ char *BLI_strncat_utf8(char *__restrict dst, const char *__restrict src, size_t
size_t BLI_strncpy_wchar_as_utf8(char *__restrict dst, const wchar_t *__restrict src, const size_t maxncpy)
{
const size_t maxlen = maxncpy - 1;
+ const int64_t maxlen_secured = (int64_t)maxlen - 6; /* 6 is max utf8 length of an unicode char. */
size_t len = 0;
BLI_assert(maxncpy != 0);
@@ -241,10 +258,23 @@ size_t BLI_strncpy_wchar_as_utf8(char *__restrict dst, const wchar_t *__restrict
memset(dst, 0xff, sizeof(*dst) * maxncpy);
#endif
- while (*src && len < maxlen) { /* XXX can still run over the buffer because utf8 size isn't known :| */
+ while (*src && len <= maxlen_secured) {
len += BLI_str_utf8_from_unicode((unsigned int)*src++, dst + len);
}
+ /* We have to be more careful for the last six bytes, to avoid buffer overflow in case utf8-encoded char
+ * would be too long for our dst buffer. */
+ while (*src) {
+ char t[6];
+ size_t l = BLI_str_utf8_from_unicode((unsigned int)*src++, t);
+ BLI_assert(l <= 6);
+ if (len + l > maxlen) {
+ break;
+ }
+ memcpy(dst + len, t, l);
+ len += l;
+ }
+
dst[len] = '\0';
return len;
@@ -299,8 +329,8 @@ size_t BLI_strnlen_utf8_ex(const char *strc, const size_t maxlen, size_t *r_len_
}
/**
- * \param start the string to measure the length.
- * \param maxlen the string length (in bytes)
+ * \param strc: the string to measure the length.
+ * \param maxlen: the string length (in bytes)
* \return the unicode length (not in bytes!)
*/
size_t BLI_strnlen_utf8(const char *strc, const size_t maxlen)
@@ -569,14 +599,14 @@ unsigned int BLI_str_utf8_as_unicode_step(const char *__restrict p, size_t *__re
/* was g_unichar_to_utf8 */
/**
* BLI_str_utf8_from_unicode:
- * @c a Unicode character code
- * \param outbuf output buffer, must have at least 6 bytes of space.
+ * \param c: a Unicode character code
+ * \param outbuf: output buffer, must have at least 6 bytes of space.
* If %NULL, the length will be computed and returned
* and nothing will be written to outbuf.
*
* Converts a single character to UTF-8.
*
- * Return value: number of bytes written
+ * \return number of bytes written
**/
size_t BLI_str_utf8_from_unicode(unsigned int c, char *outbuf)
{
@@ -704,28 +734,31 @@ char *BLI_str_prev_char_utf8(const char *p)
}
/* end glib copy */
-size_t BLI_str_partition_utf8(const char *str, const unsigned int delim[], char **sep, char **suf)
+size_t BLI_str_partition_utf8(const char *str, const unsigned int delim[], const char **sep, const char **suf)
{
- return BLI_str_partition_ex_utf8(str, delim, sep, suf, false);
+ return BLI_str_partition_ex_utf8(str, NULL, delim, sep, suf, false);
}
-size_t BLI_str_rpartition_utf8(const char *str, const unsigned int delim[], char **sep, char **suf)
+size_t BLI_str_rpartition_utf8(const char *str, const unsigned int delim[], const char **sep, const char **suf)
{
- return BLI_str_partition_ex_utf8(str, delim, sep, suf, true);
+ return BLI_str_partition_ex_utf8(str, NULL, delim, sep, suf, true);
}
-size_t BLI_str_partition_ex_utf8(const char *str, const unsigned int delim[], char **sep, char **suf,
- const bool from_right)
+size_t BLI_str_partition_ex_utf8(
+ const char *str, const char *end, const unsigned int delim[], const char **sep, const char **suf, const bool from_right)
{
const unsigned int *d;
- const size_t str_len = strlen(str);
+ const size_t str_len = end ? (size_t)(end - str) : strlen(str);
size_t index;
+ /* Note that here, we assume end points to a valid utf8 char! */
+ BLI_assert(end == NULL || (end >= str && (BLI_str_utf8_as_unicode(end) != BLI_UTF8_ERR)));
+
*suf = (char *)(str + str_len);
for (*sep = (char *)(from_right ? BLI_str_find_prev_char_utf8(str, str + str_len) : str), index = 0;
- *sep != NULL && **sep != '\0';
- *sep = (char *)(from_right ? (char *)BLI_str_find_prev_char_utf8(str, *sep) : str + index))
+ *sep >= str && (!end || *sep < end) && **sep != '\0';
+ *sep = (char *)(from_right ? BLI_str_find_prev_char_utf8(str, *sep) : str + index))
{
const unsigned int c = BLI_str_utf8_as_unicode_and_size(*sep, &index);
diff --git a/source/blender/blenlib/intern/system.c b/source/blender/blenlib/intern/system.c
index e6389bc68f3..5d1bdd6d978 100644
--- a/source/blender/blenlib/intern/system.c
+++ b/source/blender/blenlib/intern/system.c
@@ -22,9 +22,21 @@
* \ingroup bli
*/
+#include <stdio.h>
+#include <stdlib.h>
#include "BLI_system.h"
+#include "MEM_guardedalloc.h"
+
+/* for backtrace */
+#if defined(__linux__) || defined(__APPLE__)
+# include <execinfo.h>
+#elif defined(WIN32)
+# include <windows.h>
+# include <DbgHelp.h>
+#endif
+
int BLI_cpu_support_sse2(void)
{
#if defined(__x86_64__) || defined(_M_X64)
@@ -57,3 +69,71 @@ int BLI_cpu_support_sse2(void)
#endif
}
+/**
+ * Write a backtrace into a file for systems which support it.
+ */
+void BLI_system_backtrace(FILE *fp)
+{
+ /* ------------- */
+ /* Linux / Apple */
+#if defined(__linux__) || defined(__APPLE__)
+
+#define SIZE 100
+ void *buffer[SIZE];
+ int nptrs;
+ char **strings;
+ int i;
+
+ /* include a backtrace for good measure */
+ nptrs = backtrace(buffer, SIZE);
+ strings = backtrace_symbols(buffer, nptrs);
+ for (i = 0; i < nptrs; i++) {
+ fputs(strings[i], fp);
+ fputc('\n', fp);
+ }
+
+ free(strings);
+#undef SIZE
+
+ /* -------- */
+ /* Windows */
+#elif defined(_MSC_VER)
+
+#ifndef NDEBUG
+#define MAXSYMBOL 256
+#define SIZE 100
+ unsigned short i;
+ void *stack[SIZE];
+ unsigned short nframes;
+ SYMBOL_INFO *symbolinfo;
+ HANDLE process;
+
+ process = GetCurrentProcess();
+
+ SymInitialize(process, NULL, TRUE);
+
+ nframes = CaptureStackBackTrace(0, SIZE, stack, NULL);
+ symbolinfo = MEM_callocN(sizeof(SYMBOL_INFO) + MAXSYMBOL * sizeof(char), "crash Symbol table");
+ symbolinfo->MaxNameLen = MAXSYMBOL - 1;
+ symbolinfo->SizeOfStruct = sizeof(SYMBOL_INFO);
+
+ for (i = 0; i < nframes; i++) {
+ SymFromAddr(process, (DWORD64)(stack[i]), 0, symbolinfo);
+
+ fprintf(fp, "%u: %s - 0x%0X\n", nframes - i - 1, symbolinfo->Name, symbolinfo->Address);
+ }
+
+ MEM_freeN(symbolinfo);
+#undef MAXSYMBOL
+#undef SIZE
+#else
+ fprintf(fp, "Crash backtrace not supported on release builds\n");
+#endif /* NDEBUG */
+#else /* _MSC_VER */
+ /* ------------------ */
+ /* non msvc/osx/linux */
+ (void)fp;
+#endif
+
+}
+/* end BLI_system_backtrace */
diff --git a/source/blender/blenlib/intern/task.c b/source/blender/blenlib/intern/task.c
index 8d867b9f295..08d40a158ca 100644
--- a/source/blender/blenlib/intern/task.c
+++ b/source/blender/blenlib/intern/task.c
@@ -29,9 +29,12 @@
#include "MEM_guardedalloc.h"
#include "BLI_listbase.h"
+#include "BLI_math.h"
#include "BLI_task.h"
#include "BLI_threads.h"
+#include "atomic_ops.h"
+
/* Types */
typedef struct Task {
@@ -48,6 +51,8 @@ struct TaskPool {
volatile size_t num;
volatile size_t done;
+ size_t num_threads;
+ size_t currently_running_tasks;
ThreadMutex num_mutex;
ThreadCondition num_cond;
@@ -83,6 +88,7 @@ static void task_pool_num_decrease(TaskPool *pool, size_t done)
BLI_assert(pool->num >= done);
pool->num -= done;
+ atomic_sub_z(&pool->currently_running_tasks, done);
pool->done += done;
if (pool->num == 0)
@@ -103,19 +109,37 @@ static void task_pool_num_increase(TaskPool *pool)
static bool task_scheduler_thread_wait_pop(TaskScheduler *scheduler, Task **task)
{
+ bool found_task = false;
BLI_mutex_lock(&scheduler->queue_mutex);
while (!scheduler->queue.first && !scheduler->do_exit)
BLI_condition_wait(&scheduler->queue_cond, &scheduler->queue_mutex);
- if (!scheduler->queue.first) {
- BLI_mutex_unlock(&scheduler->queue_mutex);
- BLI_assert(scheduler->do_exit);
- return false;
- }
-
- *task = scheduler->queue.first;
- BLI_remlink(&scheduler->queue, *task);
+ do {
+ Task *current_task;
+ if (!scheduler->queue.first) {
+ BLI_mutex_unlock(&scheduler->queue_mutex);
+ BLI_assert(scheduler->do_exit);
+ return false;
+ }
+ for (current_task = scheduler->queue.first;
+ current_task != NULL;
+ current_task = current_task->next)
+ {
+ TaskPool *pool = current_task->pool;
+ if (pool->num_threads == 0 ||
+ pool->currently_running_tasks < pool->num_threads)
+ {
+ *task = current_task;
+ found_task = true;
+ atomic_add_z(&pool->currently_running_tasks, 1);
+ BLI_remlink(&scheduler->queue, *task);
+ break;
+ }
+ }
+ if (!found_task)
+ BLI_condition_wait(&scheduler->queue_cond, &scheduler->queue_mutex);
+ } while (!found_task);
BLI_mutex_unlock(&scheduler->queue_mutex);
@@ -287,6 +311,8 @@ TaskPool *BLI_task_pool_create(TaskScheduler *scheduler, void *userdata)
pool->scheduler = scheduler;
pool->num = 0;
+ pool->num_threads = 0;
+ pool->currently_running_tasks = 0;
pool->do_cancel = false;
BLI_mutex_init(&pool->num_mutex);
@@ -350,12 +376,16 @@ void BLI_task_pool_work_and_wait(TaskPool *pool)
/* find task from this pool. if we get a task from another pool,
* we can get into deadlock */
- for (task = scheduler->queue.first; task; task = task->next) {
- if (task->pool == pool) {
- work_task = task;
- found_task = true;
- BLI_remlink(&scheduler->queue, task);
- break;
+ if (pool->num_threads == 0 ||
+ pool->currently_running_tasks < pool->num_threads)
+ {
+ for (task = scheduler->queue.first; task; task = task->next) {
+ if (task->pool == pool) {
+ work_task = task;
+ found_task = true;
+ BLI_remlink(&scheduler->queue, task);
+ break;
+ }
}
}
@@ -364,6 +394,7 @@ void BLI_task_pool_work_and_wait(TaskPool *pool)
/* if found task, do it, otherwise wait until other tasks are done */
if (found_task) {
/* run task */
+ atomic_add_z(&pool->currently_running_tasks, 1);
work_task->run(pool, work_task->taskdata, 0);
/* delete task */
@@ -386,6 +417,22 @@ void BLI_task_pool_work_and_wait(TaskPool *pool)
BLI_mutex_unlock(&pool->num_mutex);
}
+int BLI_pool_get_num_threads(TaskPool *pool)
+{
+ if (pool->num_threads != 0) {
+ return pool->num_threads;
+ }
+ else {
+ return BLI_task_scheduler_num_threads(pool->scheduler);
+ }
+}
+
+void BLI_pool_set_num_threads(TaskPool *pool, int num_threads)
+{
+ /* NOTE: Don't try to modify threads while tasks are running! */
+ pool->num_threads = num_threads;
+}
+
void BLI_task_pool_cancel(TaskPool *pool)
{
pool->do_cancel = true;
@@ -428,3 +475,129 @@ size_t BLI_task_pool_tasks_done(TaskPool *pool)
return pool->done;
}
+/* Parallel range routines */
+
+/**
+ *
+ * Main functions:
+ * - #BLI_task_parallel_range
+ *
+ * TODO:
+ * - #BLI_task_parallel_foreach_listbase (#ListBase - double linked list)
+ * - #BLI_task_parallel_foreach_link (#Link - single linked list)
+ * - #BLI_task_parallel_foreach_ghash/gset (#GHash/#GSet - hash & set)
+ * - #BLI_task_parallel_foreach_mempool (#BLI_mempool - iterate over mempools)
+ *
+ * Possible improvements:
+ *
+ * - Chunk iterations to reduce number of spin locks.
+ */
+
+typedef struct ParallelRangeState {
+ int start, stop;
+ void *userdata;
+ TaskParallelRangeFunc func;
+
+ int iter;
+ int chunk_size;
+ SpinLock lock;
+} ParallelRangeState;
+
+BLI_INLINE bool parallel_range_next_iter_get(
+ ParallelRangeState * __restrict state,
+ int * __restrict iter, int * __restrict count)
+{
+ bool result = false;
+ BLI_spin_lock(&state->lock);
+ if (state->iter < state->stop) {
+ *count = min_ii(state->chunk_size, state->stop - state->iter);
+ *iter = state->iter;
+ state->iter += *count;
+ result = true;
+ }
+ BLI_spin_unlock(&state->lock);
+ return result;
+}
+
+static void parallel_range_func(
+ TaskPool * __restrict pool,
+ void *UNUSED(taskdata),
+ int UNUSED(threadid))
+{
+ ParallelRangeState * __restrict state = BLI_task_pool_userdata(pool);
+ int iter, count;
+ while (parallel_range_next_iter_get(state, &iter, &count)) {
+ int i;
+ for (i = 0; i < count; ++i) {
+ state->func(state->userdata, iter + i);
+ }
+ }
+}
+
+void BLI_task_parallel_range_ex(
+ int start, int stop,
+ void *userdata,
+ TaskParallelRangeFunc func,
+ const int range_threshold,
+ const bool use_dynamic_scheduling)
+{
+ TaskScheduler *task_scheduler;
+ TaskPool *task_pool;
+ ParallelRangeState state;
+ int i, num_threads, num_tasks;
+
+ BLI_assert(start < stop);
+
+ /* If it's not enough data to be crunched, don't bother with tasks at all,
+ * do everything from the main thread.
+ */
+ if (stop - start < range_threshold) {
+ for (i = start; i < stop; ++i) {
+ func(userdata, i);
+ }
+ return;
+ }
+
+ task_scheduler = BLI_task_scheduler_get();
+ task_pool = BLI_task_pool_create(task_scheduler, &state);
+ num_threads = BLI_task_scheduler_num_threads(task_scheduler);
+
+ /* The idea here is to prevent creating task for each of the loop iterations
+ * and instead have tasks which are evenly distributed across CPU cores and
+ * pull next iter to be crunched using the queue.
+ */
+ num_tasks = num_threads * 2;
+
+ BLI_spin_init(&state.lock);
+ state.start = start;
+ state.stop = stop;
+ state.userdata = userdata;
+ state.func = func;
+ state.iter = start;
+ if (use_dynamic_scheduling) {
+ state.chunk_size = 32;
+ }
+ else {
+ state.chunk_size = (stop - start) / (num_tasks);
+ }
+
+ for (i = 0; i < num_tasks; i++) {
+ BLI_task_pool_push(task_pool,
+ parallel_range_func,
+ NULL, false,
+ TASK_PRIORITY_HIGH);
+ }
+
+ BLI_task_pool_work_and_wait(task_pool);
+ BLI_task_pool_free(task_pool);
+
+ BLI_spin_end(&state.lock);
+}
+
+void BLI_task_parallel_range(
+ int start, int stop,
+ void *userdata,
+ TaskParallelRangeFunc func)
+{
+ BLI_task_parallel_range_ex(start, stop, userdata, func, 64, false);
+}
diff --git a/source/blender/blenlib/intern/threads.c b/source/blender/blenlib/intern/threads.c
index ded2fd7e06d..b60981802aa 100644
--- a/source/blender/blenlib/intern/threads.c
+++ b/source/blender/blenlib/intern/threads.c
@@ -122,6 +122,7 @@ static pthread_mutex_t _nodes_lock = PTHREAD_MUTEX_INITIALIZER;
static pthread_mutex_t _movieclip_lock = PTHREAD_MUTEX_INITIALIZER;
static pthread_mutex_t _colormanage_lock = PTHREAD_MUTEX_INITIALIZER;
static pthread_mutex_t _fftw_lock = PTHREAD_MUTEX_INITIALIZER;
+static pthread_mutex_t _view3d_lock = PTHREAD_MUTEX_INITIALIZER;
static pthread_t mainid;
static int thread_levels = 0; /* threads can be invoked inside threads */
static int num_threads_override = 0;
@@ -198,6 +199,7 @@ void BLI_init_threads(ListBase *threadbase, void *(*do_thread)(void *), int tot)
}
}
+ BLI_spin_lock(&_malloc_lock);
if (thread_levels == 0) {
MEM_set_lock_callback(BLI_lock_malloc_thread, BLI_unlock_malloc_thread);
@@ -210,6 +212,7 @@ void BLI_init_threads(ListBase *threadbase, void *(*do_thread)(void *), int tot)
}
thread_levels++;
+ BLI_spin_unlock(&_malloc_lock);
}
/* amount of available threads */
@@ -328,9 +331,11 @@ void BLI_end_threads(ListBase *threadbase)
BLI_freelistN(threadbase);
}
+ BLI_spin_lock(&_malloc_lock);
thread_levels--;
if (thread_levels == 0)
MEM_set_lock_callback(NULL, NULL);
+ BLI_spin_unlock(&_malloc_lock);
}
/* System Information */
@@ -338,33 +343,37 @@ void BLI_end_threads(ListBase *threadbase)
/* how many threads are native on this system? */
int BLI_system_thread_count(void)
{
- int t;
+ static int t = -1;
+
+ if (num_threads_override != 0) {
+ return num_threads_override;
+ }
+ else if (LIKELY(t != -1)) {
+ return t;
+ }
+
+ {
#ifdef WIN32
- SYSTEM_INFO info;
- GetSystemInfo(&info);
- t = (int) info.dwNumberOfProcessors;
+ SYSTEM_INFO info;
+ GetSystemInfo(&info);
+ t = (int) info.dwNumberOfProcessors;
#else
# ifdef __APPLE__
- int mib[2];
- size_t len;
-
- mib[0] = CTL_HW;
- mib[1] = HW_NCPU;
- len = sizeof(t);
- sysctl(mib, 2, &t, &len, NULL, 0);
+ int mib[2];
+ size_t len;
+
+ mib[0] = CTL_HW;
+ mib[1] = HW_NCPU;
+ len = sizeof(t);
+ sysctl(mib, 2, &t, &len, NULL, 0);
# else
- t = (int)sysconf(_SC_NPROCESSORS_ONLN);
+ t = (int)sysconf(_SC_NPROCESSORS_ONLN);
# endif
#endif
+ }
+
+ CLAMP(t, 1, RE_MAX_THREAD);
- if (num_threads_override > 0)
- return num_threads_override;
-
- if (t > RE_MAX_THREAD)
- return RE_MAX_THREAD;
- if (t < 1)
- return 1;
-
return t;
}
@@ -380,52 +389,45 @@ int BLI_system_num_threads_override_get(void)
/* Global Mutex Locks */
+static ThreadMutex *global_mutex_from_type(const int type)
+{
+ switch (type) {
+ case LOCK_IMAGE:
+ return &_image_lock;
+ case LOCK_DRAW_IMAGE:
+ return &_image_draw_lock;
+ case LOCK_VIEWER:
+ return &_viewer_lock;
+ case LOCK_CUSTOM1:
+ return &_custom1_lock;
+ case LOCK_RCACHE:
+ return &_rcache_lock;
+ case LOCK_OPENGL:
+ return &_opengl_lock;
+ case LOCK_NODES:
+ return &_nodes_lock;
+ case LOCK_MOVIECLIP:
+ return &_movieclip_lock;
+ case LOCK_COLORMANAGE:
+ return &_colormanage_lock;
+ case LOCK_FFTW:
+ return &_fftw_lock;
+ case LOCK_VIEW3D:
+ return &_view3d_lock;
+ default:
+ BLI_assert(0);
+ return NULL;
+ }
+}
+
void BLI_lock_thread(int type)
{
- if (type == LOCK_IMAGE)
- pthread_mutex_lock(&_image_lock);
- else if (type == LOCK_DRAW_IMAGE)
- pthread_mutex_lock(&_image_draw_lock);
- else if (type == LOCK_VIEWER)
- pthread_mutex_lock(&_viewer_lock);
- else if (type == LOCK_CUSTOM1)
- pthread_mutex_lock(&_custom1_lock);
- else if (type == LOCK_RCACHE)
- pthread_mutex_lock(&_rcache_lock);
- else if (type == LOCK_OPENGL)
- pthread_mutex_lock(&_opengl_lock);
- else if (type == LOCK_NODES)
- pthread_mutex_lock(&_nodes_lock);
- else if (type == LOCK_MOVIECLIP)
- pthread_mutex_lock(&_movieclip_lock);
- else if (type == LOCK_COLORMANAGE)
- pthread_mutex_lock(&_colormanage_lock);
- else if (type == LOCK_FFTW)
- pthread_mutex_lock(&_fftw_lock);
+ pthread_mutex_lock(global_mutex_from_type(type));
}
void BLI_unlock_thread(int type)
{
- if (type == LOCK_IMAGE)
- pthread_mutex_unlock(&_image_lock);
- else if (type == LOCK_DRAW_IMAGE)
- pthread_mutex_unlock(&_image_draw_lock);
- else if (type == LOCK_VIEWER)
- pthread_mutex_unlock(&_viewer_lock);
- else if (type == LOCK_CUSTOM1)
- pthread_mutex_unlock(&_custom1_lock);
- else if (type == LOCK_RCACHE)
- pthread_mutex_unlock(&_rcache_lock);
- else if (type == LOCK_OPENGL)
- pthread_mutex_unlock(&_opengl_lock);
- else if (type == LOCK_NODES)
- pthread_mutex_unlock(&_nodes_lock);
- else if (type == LOCK_MOVIECLIP)
- pthread_mutex_unlock(&_movieclip_lock);
- else if (type == LOCK_COLORMANAGE)
- pthread_mutex_unlock(&_colormanage_lock);
- else if (type == LOCK_FFTW)
- pthread_mutex_unlock(&_fftw_lock);
+ pthread_mutex_unlock(global_mutex_from_type(type));
}
/* Mutex Locks */
@@ -606,6 +608,11 @@ void BLI_condition_wait(ThreadCondition *cond, ThreadMutex *mutex)
pthread_cond_wait(cond, mutex);
}
+void BLI_condition_wait_global_mutex(ThreadCondition *cond, const int type)
+{
+ pthread_cond_wait(cond, global_mutex_from_type(type));
+}
+
void BLI_condition_notify_one(ThreadCondition *cond)
{
pthread_cond_signal(cond);
@@ -768,6 +775,17 @@ int BLI_thread_queue_size(ThreadQueue *queue)
return size;
}
+bool BLI_thread_queue_is_empty(ThreadQueue *queue)
+{
+ bool is_empty;
+
+ pthread_mutex_lock(&queue->mutex);
+ is_empty = BLI_gsqueue_is_empty(queue->queue);
+ pthread_mutex_unlock(&queue->mutex);
+
+ return is_empty;
+}
+
void BLI_thread_queue_nowait(ThreadQueue *queue)
{
pthread_mutex_lock(&queue->mutex);
@@ -797,10 +815,12 @@ void BLI_begin_threaded_malloc(void)
/* Used for debug only */
/* BLI_assert(thread_levels >= 0); */
+ BLI_spin_lock(&_malloc_lock);
if (thread_levels == 0) {
MEM_set_lock_callback(BLI_lock_malloc_thread, BLI_unlock_malloc_thread);
}
thread_levels++;
+ BLI_spin_unlock(&_malloc_lock);
}
void BLI_end_threaded_malloc(void)
@@ -808,8 +828,10 @@ void BLI_end_threaded_malloc(void)
/* Used for debug only */
/* BLI_assert(thread_levels >= 0); */
+ BLI_spin_lock(&_malloc_lock);
thread_levels--;
if (thread_levels == 0)
MEM_set_lock_callback(NULL, NULL);
+ BLI_spin_unlock(&_malloc_lock);
}
diff --git a/source/blender/blenlib/intern/time.c b/source/blender/blenlib/intern/time.c
index 078fc2c295b..a0fb78cd193 100644
--- a/source/blender/blenlib/intern/time.c
+++ b/source/blender/blenlib/intern/time.c
@@ -33,6 +33,9 @@
#include "PIL_time.h"
#ifdef WIN32
+
+#define _WIN32_WINNT 0x501 /* Windows XP or newer */
+#define WIN32_LEAN_AND_MEAN
#include <windows.h>
double PIL_check_seconds_timer(void)
@@ -70,6 +73,11 @@ double PIL_check_seconds_timer(void)
}
}
+long int PIL_check_seconds_timer_i(void)
+{
+ return (long int)PIL_check_seconds_timer();
+}
+
void PIL_sleep_ms(int ms)
{
Sleep(ms);
@@ -90,6 +98,16 @@ double PIL_check_seconds_timer(void)
return ((double) tv.tv_sec + tv.tv_usec / 1000000.0);
}
+long int PIL_check_seconds_timer_i(void)
+{
+ struct timeval tv;
+ struct timezone tz;
+
+ gettimeofday(&tv, &tz);
+
+ return tv.tv_sec;
+}
+
void PIL_sleep_ms(int ms)
{
if (ms >= 1000) {
diff --git a/source/blender/blenlib/intern/timecode.c b/source/blender/blenlib/intern/timecode.c
index 0c8834008b6..4ae9249ec0d 100644
--- a/source/blender/blenlib/intern/timecode.c
+++ b/source/blender/blenlib/intern/timecode.c
@@ -113,22 +113,22 @@ size_t BLI_timecode_string_from_time(
if (power <= 0) {
/* include "frames" in display */
if (hours) {
- rlen = BLI_snprintf(str, maxncpy, "%s%02d:%02d:%02d+%02d", neg, hours, minutes, seconds, frames);
+ rlen = BLI_snprintf_rlen(str, maxncpy, "%s%02d:%02d:%02d+%02d", neg, hours, minutes, seconds, frames);
}
else if (minutes) {
- rlen = BLI_snprintf(str, maxncpy, "%s%02d:%02d+%02d", neg, minutes, seconds, frames);
+ rlen = BLI_snprintf_rlen(str, maxncpy, "%s%02d:%02d+%02d", neg, minutes, seconds, frames);
}
else {
- rlen = BLI_snprintf(str, maxncpy, "%s%d+%02d", neg, seconds, frames);
+ rlen = BLI_snprintf_rlen(str, maxncpy, "%s%d+%02d", neg, seconds, frames);
}
}
else {
/* don't include 'frames' in display */
if (hours) {
- rlen = BLI_snprintf(str, maxncpy, "%s%02d:%02d:%02d", neg, hours, minutes, seconds);
+ rlen = BLI_snprintf_rlen(str, maxncpy, "%s%02d:%02d:%02d", neg, hours, minutes, seconds);
}
else {
- rlen = BLI_snprintf(str, maxncpy, "%s%02d:%02d", neg, minutes, seconds);
+ rlen = BLI_snprintf_rlen(str, maxncpy, "%s%02d:%02d", neg, minutes, seconds);
}
}
break;
@@ -137,10 +137,10 @@ size_t BLI_timecode_string_from_time(
{
/* reduced SMPTE format that always shows minutes, seconds, frames. Hours only shown as needed. */
if (hours) {
- rlen = BLI_snprintf(str, maxncpy, "%s%02d:%02d:%02d:%02d", neg, hours, minutes, seconds, frames);
+ rlen = BLI_snprintf_rlen(str, maxncpy, "%s%02d:%02d:%02d:%02d", neg, hours, minutes, seconds, frames);
}
else {
- rlen = BLI_snprintf(str, maxncpy, "%s%02d:%02d:%02d", neg, minutes, seconds, frames);
+ rlen = BLI_snprintf_rlen(str, maxncpy, "%s%02d:%02d:%02d", neg, minutes, seconds, frames);
}
break;
}
@@ -156,10 +156,10 @@ size_t BLI_timecode_string_from_time(
const int s_pad = ms_dp + 3;
if (hours) {
- rlen = BLI_snprintf(str, maxncpy, "%s%02d:%02d:%0*.*f", neg, hours, minutes, s_pad, ms_dp, time);
+ rlen = BLI_snprintf_rlen(str, maxncpy, "%s%02d:%02d:%0*.*f", neg, hours, minutes, s_pad, ms_dp, time);
}
else {
- rlen = BLI_snprintf(str, maxncpy, "%s%02d:%0*.*f", neg, minutes, s_pad, ms_dp, time);
+ rlen = BLI_snprintf_rlen(str, maxncpy, "%s%02d:%0*.*f", neg, minutes, s_pad, ms_dp, time);
}
break;
}
@@ -168,10 +168,10 @@ size_t BLI_timecode_string_from_time(
/* only show the original seconds display */
/* round to whole numbers if power is >= 1 (i.e. scale is coarse) */
if (power <= 0) {
- rlen = BLI_snprintf(str, maxncpy, "%.*f", 1 - power, time_seconds);
+ rlen = BLI_snprintf_rlen(str, maxncpy, "%.*f", 1 - power, time_seconds);
}
else {
- rlen = BLI_snprintf(str, maxncpy, "%d", iroundf(time_seconds));
+ rlen = BLI_snprintf_rlen(str, maxncpy, "%d", iroundf(time_seconds));
}
break;
}
@@ -179,7 +179,7 @@ size_t BLI_timecode_string_from_time(
default:
{
/* full SMPTE format */
- rlen = BLI_snprintf(str, maxncpy, "%s%02d:%02d:%02d:%02d", neg, hours, minutes, seconds, frames);
+ rlen = BLI_snprintf_rlen(str, maxncpy, "%s%02d:%02d:%02d:%02d", neg, hours, minutes, seconds, frames);
break;
}
}
@@ -187,6 +187,34 @@ size_t BLI_timecode_string_from_time(
return rlen;
}
+/**
+ * Generate time string and store in \a str
+ *
+ * \param str: destination string
+ * \param maxncpy: maximum number of characters to copy ``sizeof(str)``
+ * \param time_seconds: time total time in seconds
+ * \return length of \a str
+ */
+size_t BLI_timecode_string_from_time_simple(
+ char *str, const size_t maxncpy, const double time_seconds)
+{
+ size_t rlen;
+
+ /* format 00:00:00.00 (hr:min:sec) string has to be 12 long */
+ const int hr = ( (int) time_seconds) / (60 * 60);
+ const int min = (((int) time_seconds) / 60 ) % 60;
+ const int sec = ( (int) time_seconds) % 60;
+ const int hun = ( (int) (time_seconds * 100.0)) % 100;
+
+ if (hr) {
+ rlen = BLI_snprintf(str, maxncpy, "%.2d:%.2d:%.2d.%.2d", hr, min, sec, hun);
+ }
+ else {
+ rlen = BLI_snprintf(str, maxncpy, "%.2d:%.2d.%.2d", min, sec, hun);
+ }
+
+ return rlen;
+}
/**
* Generate time string and store in \a str
@@ -196,22 +224,21 @@ size_t BLI_timecode_string_from_time(
* \param power special setting for #View2D grid drawing,
* used to specify how detailed we need to be
* \param time_seconds time total time in seconds
- * \param seconds time in seconds.
* \return length of \a str
*
* \note in some cases this is used to print non-seconds values.
*/
-size_t BLI_timecode_string_from_time_simple(
+size_t BLI_timecode_string_from_time_seconds(
char *str, const size_t maxncpy, const int power, const float time_seconds)
{
size_t rlen;
/* round to whole numbers if power is >= 1 (i.e. scale is coarse) */
if (power <= 0) {
- rlen = BLI_snprintf(str, maxncpy, "%.*f", 1 - power, time_seconds);
+ rlen = BLI_snprintf_rlen(str, maxncpy, "%.*f", 1 - power, time_seconds);
}
else {
- rlen = BLI_snprintf(str, maxncpy, "%d", iroundf(time_seconds));
+ rlen = BLI_snprintf_rlen(str, maxncpy, "%d", iroundf(time_seconds));
}
return rlen;
diff --git a/source/blender/blenlib/intern/winstuff.c b/source/blender/blenlib/intern/winstuff.c
index a67e116969e..32ab16b4b5a 100644
--- a/source/blender/blenlib/intern/winstuff.c
+++ b/source/blender/blenlib/intern/winstuff.c
@@ -93,7 +93,7 @@ void RegisterBlendExtension(void)
char RegCmd[MAX_PATH * 2];
char MBox[256];
char *blender_app;
-#ifndef WIN64
+#ifndef _WIN64
BOOL IsWOW64;
#endif
@@ -158,7 +158,7 @@ void RegisterBlendExtension(void)
BLI_getInstallationDir(InstallDir);
GetSystemDirectory(SysDir, FILE_MAXDIR);
-#ifdef WIN64
+#ifdef _WIN64
ThumbHandlerDLL = "BlendThumb64.dll";
#elif defined(__MINGW32__)
ThumbHandlerDLL = "BlendThumb.dll";
diff --git a/source/blender/blenlib/intern/winstuff_dir.c b/source/blender/blenlib/intern/winstuff_dir.c
index 3d669a869f9..bde0734a740 100644
--- a/source/blender/blenlib/intern/winstuff_dir.c
+++ b/source/blender/blenlib/intern/winstuff_dir.c
@@ -44,35 +44,51 @@
#include "BLI_utildefines.h"
#include "utfconv.h"
+#define PATH_SUFFIX "\\*"
+#define PATH_SUFFIX_LEN 2
+
+/* keep local to this file */
+struct __dirstream {
+ HANDLE handle;
+ WIN32_FIND_DATAW data;
+ char path[MAX_PATH + PATH_SUFFIX_LEN];
+ long dd_loc;
+ long dd_size;
+ char dd_buf[4096];
+ void *dd_direct;
+
+ struct dirent direntry;
+};
+
/* Note: MinGW (FREE_WINDOWS) has opendir() and _wopendir(), and only the
-* latter accepts a path name of wchar_t type. Rather than messing up with
-* extra #ifdef's here and there, Blender's own implementations of opendir()
-* and related functions are used to properly support paths with non-ASCII
-* characters. (kjym3)
-*/
+ * latter accepts a path name of wchar_t type. Rather than messing up with
+ * extra #ifdef's here and there, Blender's own implementations of opendir()
+ * and related functions are used to properly support paths with non-ASCII
+ * characters. (kjym3)
+ */
DIR *opendir(const char *path)
{
wchar_t *path_16 = alloc_utf16_from_8(path, 0);
+ int path_len;
+ DIR *newd = NULL;
- if (GetFileAttributesW(path_16) & FILE_ATTRIBUTE_DIRECTORY) {
- DIR *newd = MEM_mallocN(sizeof(DIR), "opendir");
-
+ if ((GetFileAttributesW(path_16) & FILE_ATTRIBUTE_DIRECTORY) &&
+ ((path_len = strlen(path)) < (sizeof(newd->path) - PATH_SUFFIX_LEN)))
+ {
+ newd = MEM_mallocN(sizeof(DIR), "opendir");
newd->handle = INVALID_HANDLE_VALUE;
- sprintf(newd->path, "%s\\*", path);
-
+ memcpy(newd->path, path, path_len);
+ memcpy(newd->path + path_len, PATH_SUFFIX, PATH_SUFFIX_LEN + 1);
+
newd->direntry.d_ino = 0;
newd->direntry.d_off = 0;
newd->direntry.d_reclen = 0;
newd->direntry.d_name = NULL;
-
- free(path_16);
- return newd;
- }
- else {
- free(path_16);
- return NULL;
}
+
+ free(path_16);
+ return newd;
}
static char *BLI_alloc_utf_8_from_16(wchar_t *in16, size_t add)
diff --git a/source/blender/blenloader/BLO_blend_defs.h b/source/blender/blenloader/BLO_blend_defs.h
index 8005be158ce..a6b06a080cc 100644
--- a/source/blender/blenloader/BLO_blend_defs.h
+++ b/source/blender/blenloader/BLO_blend_defs.h
@@ -34,14 +34,47 @@
# define BLEND_MAKE_ID(a, b, c, d) ( (int)(d) << 24 | (int)(c) << 16 | (b) << 8 | (a) )
#endif
-#define DATA BLEND_MAKE_ID('D', 'A', 'T', 'A')
-#define GLOB BLEND_MAKE_ID('G', 'L', 'O', 'B')
-
-#define DNA1 BLEND_MAKE_ID('D', 'N', 'A', '1')
-#define TEST BLEND_MAKE_ID('T', 'E', 'S', 'T') /* used as preview between 'REND' and 'GLOB' */
-#define REND BLEND_MAKE_ID('R', 'E', 'N', 'D')
-#define USER BLEND_MAKE_ID('U', 'S', 'E', 'R')
+/**
+ * Codes used for #BHead.code.
+ *
+ * These coexist with ID codes such as #ID_OB, #ID_SCE ... etc.
+ */
+enum {
+ /**
+ * Arbitrary allocated memory
+ * (typically owned by #ID's, will be freed when there are no users).
+ */
+ DATA = BLEND_MAKE_ID('D', 'A', 'T', 'A'),
+ /**
+ * Used for #Global struct.
+ */
+ GLOB = BLEND_MAKE_ID('G', 'L', 'O', 'B'),
+ /**
+ * Used for storing the encoded SDNA string
+ * (decoded into an #SDNA on load).
+ */
+ DNA1 = BLEND_MAKE_ID('D', 'N', 'A', '1'),
+ /**
+ * Used to store thumbnail previews, written between #REND and #GLOB blocks,
+ * (ignored for regular file reading).
+ */
+ TEST = BLEND_MAKE_ID('T', 'E', 'S', 'T'),
+ /**
+ * Used for #RenderInfo, basic Scene and frame range info,
+ * can be easily read by other applications without writing a full blend file parser.
+ */
+ REND = BLEND_MAKE_ID('R', 'E', 'N', 'D'),
+ /**
+ * Used for #UserDef, (user-preferences data).
+ * (written to #BLENDER_STARTUP_FILE & #BLENDER_USERPREF_FILE).
+ */
+ USER = BLEND_MAKE_ID('U', 'S', 'E', 'R'),
+ /**
+ * Terminate reading (no data).
+ */
+ ENDB = BLEND_MAKE_ID('E', 'N', 'D', 'B'),
+};
-#define ENDB BLEND_MAKE_ID('E', 'N', 'D', 'B')
+#define BLEN_THUMB_MEMSIZE_FILE(_x, _y) (sizeof(int) * (size_t)(2 + (_x) * (_y)))
#endif /* __BLO_BLEND_DEFS_H__ */
diff --git a/source/blender/blenloader/BLO_readfile.h b/source/blender/blenloader/BLO_readfile.h
index 4b7b9cecb17..77bdb99b54b 100644
--- a/source/blender/blenloader/BLO_readfile.h
+++ b/source/blender/blenloader/BLO_readfile.h
@@ -36,14 +36,13 @@
extern "C" {
#endif
+struct BlendThumbnail;
struct bScreen;
-struct direntry;
struct LinkNode;
struct Main;
struct MemFile;
struct ReportList;
struct Scene;
-struct SpaceFile;
struct UserDef;
struct bContext;
struct BHead;
@@ -61,9 +60,7 @@ typedef struct BlendFileData {
struct Main *main;
struct UserDef *user;
- int winpos;
int fileflags;
- int displaymode;
int globalf;
char filename[1024]; /* 1024 = FILE_MAX */
@@ -123,8 +120,8 @@ BLO_blendfiledata_free(BlendFileData *bfd);
/**
* Open a blendhandle from a file path.
*
- * \param file The file path to open.
- * \param reports Report errors in opening the file (can be NULL).
+ * \param filepath: The file path to open.
+ * \param reports: Report errors in opening the file (can be NULL).
* \return A handle on success, or NULL on failure.
*/
BlendHandle *BLO_blendhandle_from_file(
@@ -199,10 +196,13 @@ BLO_blendhandle_close(BlendHandle *bh);
bool BLO_has_bfile_extension(const char *str);
/**
- * return ok when a blenderfile, in dir is the filename,
- * in group the type of libdata
+ * \param path the full path to explode.
+ * \param r_dir the string that'll contain path up to blend file itself ('library' path).
+ * \param r_group the string that'll contain 'group' part of the path, if any. May be NULL.
+ * \param r_name the string that'll contain data's name part of the path, if any. May be NULL.
+ * \return true if path contains a blend file.
*/
-bool BLO_is_a_library(const char *path, char *dir, char *group);
+bool BLO_library_path_explode(const char *path, char *r_dir, char **r_group, char **r_name);
/**
@@ -279,6 +279,15 @@ void BLO_expand_main(void *fdhandle, struct Main *mainvar);
void BLO_update_defaults_userpref_blend(void);
void BLO_update_defaults_startup_blend(struct Main *mainvar);
+/**
+ * Does a very light reading of given .blend file to extract its stored thumbnail.
+ *
+ * \param filepath The path of the file to extract thumbnail from.
+ * \return The raw thumbnail
+ * (MEM-allocated, as stored in file, use BKE_main_thumbnail_to_imbuf() to convert it to ImBuf image).
+ */
+struct BlendThumbnail *BLO_thumbnail_from_file(const char *filepath);
+
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/blenloader/BLO_undofile.h b/source/blender/blenloader/BLO_undofile.h
index f716b47ea2e..fb96ec75e62 100644
--- a/source/blender/blenloader/BLO_undofile.h
+++ b/source/blender/blenloader/BLO_undofile.h
@@ -47,11 +47,11 @@ typedef struct MemFile {
} MemFile;
/* actually only used writefile.c */
-extern void add_memfilechunk(MemFile *compare, MemFile *current, const char *buf, unsigned int size);
+extern void memfile_chunk_add(MemFile *compare, MemFile *current, const char *buf, unsigned int size);
/* exports */
-extern void BLO_free_memfile(MemFile *memfile);
-extern void BLO_merge_memfile(MemFile *first, MemFile *second);
+extern void BLO_memfile_free(MemFile *memfile);
+extern void BLO_memfile_merge(MemFile *first, MemFile *second);
#endif
diff --git a/source/blender/blenloader/BLO_writefile.h b/source/blender/blenloader/BLO_writefile.h
index 7a8429afec0..0d66eb743aa 100644
--- a/source/blender/blenloader/BLO_writefile.h
+++ b/source/blender/blenloader/BLO_writefile.h
@@ -33,14 +33,14 @@
* \brief external writefile function prototypes.
*/
+struct BlendThumbnail;
struct MemFile;
struct Main;
struct ReportList;
-extern int BLO_write_file(struct Main *mainvar, const char *filepath, int write_flags, struct ReportList *reports, const int *thumb);
+extern int BLO_write_file(struct Main *mainvar, const char *filepath, int write_flags,
+ struct ReportList *reports, const struct BlendThumbnail *thumb);
extern int BLO_write_file_mem(struct Main *mainvar, struct MemFile *compare, struct MemFile *current, int write_flags);
-#define BLEN_THUMB_SIZE 128
-
#endif
diff --git a/source/blender/blenloader/CMakeLists.txt b/source/blender/blenloader/CMakeLists.txt
index 7f557d3de22..8364df38208 100644
--- a/source/blender/blenloader/CMakeLists.txt
+++ b/source/blender/blenloader/CMakeLists.txt
@@ -28,6 +28,7 @@ set(INC
../blenfont
../blenkernel
../blenlib
+ ../blentranslation
../imbuf
../makesdna
../makesrna
diff --git a/source/blender/blenloader/SConscript b/source/blender/blenloader/SConscript
index bd002e59fa4..7f2a1e0723c 100644
--- a/source/blender/blenloader/SConscript
+++ b/source/blender/blenloader/SConscript
@@ -35,6 +35,7 @@ incs = [
'../blenfont',
'../blenkernel',
'../blenlib',
+ '../blentranslation',
'../imbuf',
'../makesdna',
'../makesrna',
@@ -43,11 +44,14 @@ incs = [
env['BF_ZLIB_INC'],
]
+defs = []
+
+if env['BF_BUILDINFO']:
+ defs.append('WITH_BUILDINFO')
+
if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'linuxcross', 'win64-vc', 'win64-mingw'):
incs.append(env['BF_PTHREADS_INC'])
-defs = []
-
if env['WITH_BF_INTERNATIONAL']:
defs.append('WITH_INTERNATIONAL')
diff --git a/source/blender/blenloader/intern/readblenentry.c b/source/blender/blenloader/intern/readblenentry.c
index d9bcfc2e8f9..e8d7a46687f 100644
--- a/source/blender/blenloader/intern/readblenentry.c
+++ b/source/blender/blenloader/intern/readblenentry.c
@@ -161,6 +161,9 @@ LinkNode *BLO_blendhandle_get_previews(BlendHandle *bh, int ofblocktype, int *to
case ID_IM: /* fall through */
case ID_WO: /* fall through */
case ID_LA: /* fall through */
+ case ID_OB: /* fall through */
+ case ID_GR: /* fall through */
+ case ID_SCE: /* fall through */
new_prv = MEM_callocN(sizeof(PreviewImage), "newpreview");
BLI_linklist_prepend(&previews, new_prv);
tot++;
@@ -176,26 +179,38 @@ LinkNode *BLO_blendhandle_get_previews(BlendHandle *bh, int ofblocktype, int *to
prv = BLO_library_read_struct(fd, bhead, "PreviewImage");
if (prv) {
memcpy(new_prv, prv, sizeof(PreviewImage));
- if (prv->rect[0]) {
+ if (prv->rect[0] && prv->w[0] && prv->h[0]) {
unsigned int *rect = NULL;
- new_prv->rect[0] = MEM_callocN(new_prv->w[0] * new_prv->h[0] * sizeof(unsigned int), "prvrect");
+ size_t len = new_prv->w[0] * new_prv->h[0] * sizeof(unsigned int);
+ new_prv->rect[0] = MEM_callocN(len, __func__);
bhead = blo_nextbhead(fd, bhead);
rect = (unsigned int *)(bhead + 1);
- memcpy(new_prv->rect[0], rect, bhead->len);
+ BLI_assert(len == bhead->len);
+ memcpy(new_prv->rect[0], rect, len);
}
else {
+ /* This should not be needed, but can happen in 'broken' .blend files,
+ * better handle this gracefully than crashing. */
+ BLI_assert(prv->rect[0] == NULL && prv->w[0] == 0 && prv->h[0] == 0);
new_prv->rect[0] = NULL;
+ new_prv->w[0] = new_prv->h[0] = 0;
}
- if (prv->rect[1]) {
+ if (prv->rect[1] && prv->w[1] && prv->h[1]) {
unsigned int *rect = NULL;
- new_prv->rect[1] = MEM_callocN(new_prv->w[1] * new_prv->h[1] * sizeof(unsigned int), "prvrect");
+ size_t len = new_prv->w[1] * new_prv->h[1] * sizeof(unsigned int);
+ new_prv->rect[1] = MEM_callocN(len, __func__);
bhead = blo_nextbhead(fd, bhead);
rect = (unsigned int *)(bhead + 1);
- memcpy(new_prv->rect[1], rect, bhead->len);
+ BLI_assert(len == bhead->len);
+ memcpy(new_prv->rect[1], rect, len);
}
else {
+ /* This should not be needed, but can happen in 'broken' .blend files,
+ * better handle this gracefully than crashing. */
+ BLI_assert(prv->rect[1] == NULL && prv->w[1] == 0 && prv->h[1] == 0);
new_prv->rect[1] = NULL;
+ new_prv->w[1] = new_prv->h[1] = 0;
}
MEM_freeN(prv);
}
@@ -308,6 +323,9 @@ BlendFileData *BLO_read_from_memfile(Main *oldmain, const char *filename, MemFil
/* makes lookup of existing video clips in old main */
blo_make_movieclip_pointer_map(fd, oldmain);
+
+ /* make lookups of existing sound data in old main */
+ blo_make_sound_pointer_map(fd, oldmain);
/* removed packed data from this trick - it's internal data that needs saves */
@@ -318,7 +336,10 @@ BlendFileData *BLO_read_from_memfile(Main *oldmain, const char *filename, MemFil
/* ensures relinked movie clips are not freed */
blo_end_movieclip_pointer_map(fd, oldmain);
-
+
+ /* ensures relinked sounds are not freed */
+ blo_end_sound_pointer_map(fd, oldmain);
+
/* move libraries from old main to new main */
if (bfd && mainlist.first != mainlist.last) {
diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c
index 4739718fa54..aeb3168c1bc 100644
--- a/source/blender/blenloader/intern/readfile.c
+++ b/source/blender/blenloader/intern/readfile.c
@@ -109,10 +109,12 @@
#include "BLI_threads.h"
#include "BLI_mempool.h"
-#include "BLF_translation.h"
+#include "BLT_translation.h"
+#include "BKE_action.h"
#include "BKE_armature.h"
#include "BKE_brush.h"
+#include "BKE_cloth.h"
#include "BKE_constraint.h"
#include "BKE_context.h"
#include "BKE_curve.h"
@@ -138,16 +140,12 @@
#include "BKE_scene.h"
#include "BKE_screen.h"
#include "BKE_sequencer.h"
-#include "BKE_treehash.h"
+#include "BKE_outliner_treehash.h"
#include "BKE_sound.h"
-#include "IMB_imbuf.h" // for proxy / timecode versioning stuff
#include "NOD_common.h"
#include "NOD_socket.h"
-#include "NOD_composite.h"
-#include "NOD_shader.h"
-#include "NOD_texture.h"
#include "BLO_readfile.h"
#include "BLO_undofile.h"
@@ -157,7 +155,6 @@
#include "readfile.h"
-#include "PIL_time.h"
#include <errno.h>
@@ -210,6 +207,9 @@
* - initialize FileGlobal and copy pointers to Global
*/
+/* use GHash for BHead name-based lookups (speeds up linking) */
+#define USE_GHASH_BHEAD
+
/***/
typedef struct OldNew {
@@ -229,6 +229,8 @@ typedef struct OldNewMap {
static void *read_struct(FileData *fd, BHead *bh, const char *blockname);
static void direct_link_modifiers(FileData *fd, ListBase *lb);
static void convert_tface_mt(FileData *fd, Main *main);
+static BHead *find_bhead_from_code_name(FileData *fd, const short idcode, const char *name);
+static BHead *find_bhead_from_idname(FileData *fd, const char *idname);
/* this function ensures that reports are printed,
* in the case of libraray linking errors this is important!
@@ -256,6 +258,12 @@ void blo_reportf_wrap(ReportList *reports, ReportType type, const char *format,
}
}
+/* for reporting linking messages */
+static const char *library_parent_filepath(Library *lib)
+{
+ return lib->parent ? lib->parent->filepath : "<direct>";
+}
+
static OldNewMap *oldnewmap_new(void)
{
OldNewMap *onm= MEM_callocN(sizeof(*onm), "OldNewMap");
@@ -289,15 +297,9 @@ static void oldnewmap_insert(OldNewMap *onm, void *oldaddr, void *newaddr, int n
if (oldaddr==NULL || newaddr==NULL) return;
- if (onm->nentries == onm->entriessize) {
- int osize = onm->entriessize;
- OldNew *oentries = onm->entries;
-
+ if (UNLIKELY(onm->nentries == onm->entriessize)) {
onm->entriessize *= 2;
- onm->entries = MEM_mallocN(sizeof(*onm->entries)*onm->entriessize, "OldNewMap.entries");
-
- memcpy(onm->entries, oentries, sizeof(*oentries)*osize);
- MEM_freeN(oentries);
+ onm->entries = MEM_reallocN(onm->entries, sizeof(*onm->entries) * onm->entriessize);
}
entry = &onm->entries[onm->nentries++];
@@ -311,6 +313,56 @@ void blo_do_versions_oldnewmap_insert(OldNewMap *onm, void *oldaddr, void *newad
oldnewmap_insert(onm, oldaddr, newaddr, nr);
}
+/**
+ * Do a full search (no state).
+ *
+ * \param lasthit: Use as a reference position to avoid a full search
+ * from either end of the array, giving more efficient lookups.
+ *
+ * \note This would seem an ideal case for hash or btree lookups.
+ * However the data is written in-order, using the \a lasthit will normally avoid calling this function.
+ * Creating a btree/hash structure adds overhead for the common-case to optimize the corner-case
+ * (since most entries will never be retrieved).
+ * So just keep full lookups as a fall-back.
+ */
+static int oldnewmap_lookup_entry_full(const OldNewMap *onm, const void *addr, int lasthit)
+{
+ const int nentries = onm->nentries;
+ const OldNew *entries = onm->entries;
+ int i;
+
+ /* search relative to lasthit where possible */
+ if (lasthit >= 0 && lasthit < nentries) {
+
+ /* search forwards */
+ i = lasthit;
+ while (++i != nentries) {
+ if (entries[i].old == addr) {
+ return i;
+ }
+ }
+
+ /* search backwards */
+ i = lasthit + 1;
+ while (i--) {
+ if (entries[i].old == addr) {
+ return i;
+ }
+ }
+ }
+ else {
+ /* search backwards (full) */
+ i = nentries;
+ while (i--) {
+ if (entries[i].old == addr) {
+ return i;
+ }
+ }
+ }
+
+ return -1;
+}
+
static void *oldnewmap_lookup_and_inc(OldNewMap *onm, void *addr, bool increase_users)
{
int i;
@@ -327,16 +379,14 @@ static void *oldnewmap_lookup_and_inc(OldNewMap *onm, void *addr, bool increase_
}
}
- for (i = 0; i < onm->nentries; i++) {
+ i = oldnewmap_lookup_entry_full(onm, addr, onm->lasthit);
+ if (i != -1) {
OldNew *entry = &onm->entries[i];
-
- if (entry->old == addr) {
- onm->lasthit = i;
-
- if (increase_users)
- entry->nr++;
- return entry->newp;
- }
+ BLI_assert(entry->old == addr);
+ onm->lasthit = i;
+ if (increase_users)
+ entry->nr++;
+ return entry->newp;
}
return NULL;
@@ -366,16 +416,13 @@ static void *oldnewmap_liblookup(OldNewMap *onm, void *addr, void *lib)
}
else {
/* note, this can be a bottle neck when loading some files */
- unsigned int nentries = (unsigned int)onm->nentries;
- unsigned int i;
- OldNew *entry;
-
- for (i = 0, entry = onm->entries; i < nentries; i++, entry++) {
- if (entry->old == addr) {
- ID *id = entry->newp;
- if (id && (!lib || id->lib)) {
- return id;
- }
+ const int i = oldnewmap_lookup_entry_full(onm, addr, -1);
+ if (i != -1) {
+ OldNew *entry = &onm->entries[i];
+ ID *id = entry->newp;
+ BLI_assert(entry->old == addr);
+ if (id && (!lib || id->lib)) {
+ return id;
}
}
}
@@ -506,6 +553,44 @@ static void read_file_version(FileData *fd, Main *main)
}
}
+#ifdef USE_GHASH_BHEAD
+static void read_file_bhead_idname_map_create(FileData *fd)
+{
+ BHead *bhead;
+
+ /* dummy values */
+ bool is_link = false;
+ int code_prev = ENDB;
+ unsigned int reserve = 0;
+
+ for (bhead = blo_firstbhead(fd); bhead; bhead = blo_nextbhead(fd, bhead)) {
+ if (code_prev != bhead->code) {
+ code_prev = bhead->code;
+ is_link = BKE_idcode_is_valid(code_prev) ? BKE_idcode_is_linkable(code_prev) : false;
+ }
+
+ if (is_link) {
+ reserve += 1;
+ }
+ }
+
+ BLI_assert(fd->bhead_idname_hash == NULL);
+
+ fd->bhead_idname_hash = BLI_ghash_str_new_ex(__func__, reserve);
+
+ for (bhead = blo_firstbhead(fd); bhead; bhead = blo_nextbhead(fd, bhead)) {
+ if (code_prev != bhead->code) {
+ code_prev = bhead->code;
+ is_link = BKE_idcode_is_valid(code_prev) ? BKE_idcode_is_linkable(code_prev) : false;
+ }
+
+ if (is_link) {
+ BLI_ghash_insert(fd->bhead_idname_hash, (void *)bhead_id_name(fd, bhead), bhead);
+ }
+ }
+}
+#endif
+
static Main *blo_find_main(FileData *fd, const char *filepath, const char *relabase)
{
@@ -533,7 +618,9 @@ static Main *blo_find_main(FileData *fd, const char *filepath, const char *relab
m = BKE_main_new();
BLI_addtail(mainlist, m);
- lib = BKE_libblock_alloc(m, ID_LI, "lib");
+ /* Add library datablock itself to 'main' Main, since libraries are **never** linked data.
+ * Fixes bug where you could end with all ID_LI datablocks having the same name... */
+ lib = BKE_libblock_alloc(mainlist->first, ID_LI, "Lib");
BLI_strncpy(lib->name, filepath, sizeof(lib->name));
BLI_strncpy(lib->filepath, name1, sizeof(lib->filepath));
@@ -734,7 +821,7 @@ BHead *blo_firstbhead(FileData *fd)
BHead *blo_prevbhead(FileData *UNUSED(fd), BHead *thisblock)
{
- BHeadN *bheadn = (BHeadN *) (((char *) thisblock) - offsetof(BHeadN, bhead));
+ BHeadN *bheadn = (BHeadN *)POINTER_OFFSET(thisblock, -offsetof(BHeadN, bhead));
BHeadN *prev = bheadn->prev;
return (prev) ? &prev->bhead : NULL;
@@ -748,7 +835,7 @@ BHead *blo_nextbhead(FileData *fd, BHead *thisblock)
if (thisblock) {
/* bhead is actually a sub part of BHeadN
* We calculate the BHeadN pointer from the BHead pointer below */
- new_bhead = (BHeadN *) (((char *) thisblock) - offsetof(BHeadN, bhead));
+ new_bhead = (BHeadN *)POINTER_OFFSET(thisblock, -offsetof(BHeadN, bhead));
/* get the next BHeadN. If it doesn't exist we read in the next one */
new_bhead = new_bhead->next;
@@ -775,7 +862,7 @@ static void decode_blender_header(FileData *fd)
readsize = fd->read(fd, header, sizeof(header));
if (readsize == sizeof(header)) {
- if (strncmp(header, "BLENDER", 7) == 0) {
+ if (STREQLEN(header, "BLENDER", 7)) {
int remove_this_endian_test = 1;
fd->flags |= FD_FLAGS_FILE_OK;
@@ -832,6 +919,41 @@ static int read_file_dna(FileData *fd)
return 0;
}
+static int *read_file_thumbnail(FileData *fd)
+{
+ BHead *bhead;
+ int *blend_thumb = NULL;
+
+ for (bhead = blo_firstbhead(fd); bhead; bhead = blo_nextbhead(fd, bhead)) {
+ if (bhead->code == TEST) {
+ const bool do_endian_swap = (fd->flags & FD_FLAGS_SWITCH_ENDIAN) != 0;
+ int *data = (int *)(bhead + 1);
+
+ if (bhead->len < (2 * sizeof(int))) {
+ break;
+ }
+
+ if (do_endian_swap) {
+ BLI_endian_switch_int32(&data[0]);
+ BLI_endian_switch_int32(&data[1]);
+ }
+
+ if (bhead->len < BLEN_THUMB_MEMSIZE_FILE(data[0], data[1])) {
+ break;
+ }
+
+ blend_thumb = data;
+ break;
+ }
+ else if (bhead->code != REND) {
+ /* Thumbnail is stored in TEST immediately after first REND... */
+ break;
+ }
+ }
+
+ return blend_thumb;
+}
+
static int fd_read_from_file(FileData *filedata, void *buffer, unsigned int size)
{
int readsize = read(filedata->filedes, buffer, size);
@@ -918,7 +1040,7 @@ static int fd_read_from_memfile(FileData *filedata, void *buffer, unsigned int s
if (chunkoffset+readsize > chunk->size)
readsize= chunk->size-chunkoffset;
- memcpy((char *)buffer + totread, chunk->buf + chunkoffset, readsize);
+ memcpy(POINTER_OFFSET(buffer, totread), chunk->buf + chunkoffset, readsize);
totread += readsize;
filedata->seek += readsize;
seek += readsize;
@@ -995,6 +1117,33 @@ FileData *blo_openblenderfile(const char *filepath, ReportList *reports)
}
}
+/**
+ * Same as blo_openblenderfile(), but does not reads DNA data, only header. Use it for light access
+ * (e.g. thumbnail reading).
+ */
+static FileData *blo_openblenderfile_minimal(const char *filepath)
+{
+ gzFile gzfile;
+ errno = 0;
+ gzfile = BLI_gzopen(filepath, "rb");
+
+ if (gzfile != (gzFile)Z_NULL) {
+ FileData *fd = filedata_new();
+ fd->gzfiledes = gzfile;
+ fd->read = fd_read_gzip_from_file;
+
+ decode_blender_header(fd);
+
+ if (fd->flags & FD_FLAGS_FILE_OK) {
+ return fd;
+ }
+
+ blo_freefiledata(fd);
+ }
+
+ return NULL;
+}
+
static int fd_read_gzip_from_memory(FileData *filedata, void *buffer, unsigned int size)
{
int err;
@@ -1122,6 +1271,8 @@ void blo_freefiledata(FileData *fd)
oldnewmap_free(fd->imamap);
if (fd->movieclipmap)
oldnewmap_free(fd->movieclipmap);
+ if (fd->soundmap)
+ oldnewmap_free(fd->soundmap);
if (fd->packedmap)
oldnewmap_free(fd->packedmap);
if (fd->libmap && !(fd->flags & FD_FLAGS_NOT_MY_LIBMAP))
@@ -1129,6 +1280,12 @@ void blo_freefiledata(FileData *fd)
if (fd->bheadmap)
MEM_freeN(fd->bheadmap);
+#ifdef USE_GHASH_BHEAD
+ if (fd->bhead_idname_hash) {
+ BLI_ghash_free(fd->bhead_idname_hash, NULL, NULL);
+ }
+#endif
+
MEM_freeN(fd);
}
}
@@ -1141,44 +1298,87 @@ bool BLO_has_bfile_extension(const char *str)
return BLI_testextensie_array(str, ext_test);
}
-bool BLO_is_a_library(const char *path, char *dir, char *group)
+bool BLO_library_path_explode(const char *path, char *r_dir, char **r_group, char **r_name)
{
- /* return ok when a blenderfile, in dir is the filename,
- * in group the type of libdata
- */
- int len;
- char *fd;
-
- strcpy(dir, path);
- len = strlen(dir);
- if (len < 7) return 0;
- if ((dir[len - 1] != '/') && (dir[len - 1] != '\\')) return 0;
-
- group[0] = '\0';
- dir[len - 1] = '\0';
+ /* We might get some data names with slashes, so we have to go up in path until we find blend file itself,
+ * then we now next path item is group, and everything else is data name. */
+ char *slash = NULL, *prev_slash = NULL, c = '\0';
+
+ r_dir[0] = '\0';
+ if (r_group) {
+ *r_group = NULL;
+ }
+ if (r_name) {
+ *r_name = NULL;
+ }
+
+ /* if path leads to an existing directory, we can be sure we're not (in) a library */
+ if (BLI_is_dir(path)) {
+ return false;
+ }
+
+ strcpy(r_dir, path);
+
+ while ((slash = (char *)BLI_last_slash(r_dir))) {
+ char tc = *slash;
+ *slash = '\0';
+ if (BLO_has_bfile_extension(r_dir)) {
+ break;
+ }
+
+ if (prev_slash) {
+ *prev_slash = c;
+ }
+ prev_slash = slash;
+ c = tc;
+ }
+
+ if (!slash) {
+ return false;
+ }
+
+ if (slash[1] != '\0') {
+ BLI_assert(strlen(slash + 1) < BLO_GROUP_MAX);
+ if (r_group) {
+ *r_group = slash + 1;
+ }
+ }
+
+ if (prev_slash && (prev_slash[1] != '\0')) {
+ BLI_assert(strlen(prev_slash + 1) < MAX_ID_NAME - 2);
+ if (r_name) {
+ *r_name = prev_slash + 1;
+ }
+ }
+
+ return true;
+}
+
+BlendThumbnail *BLO_thumbnail_from_file(const char *filepath)
+{
+ FileData *fd;
+ BlendThumbnail *data;
+ int *fd_data;
+
+ fd = blo_openblenderfile_minimal(filepath);
+ fd_data = fd ? read_file_thumbnail(fd) : NULL;
- /* Find the last slash */
- fd = (char *)BLI_last_slash(dir);
+ if (fd_data) {
+ const size_t sz = BLEN_THUMB_MEMSIZE(fd_data[0], fd_data[1]);
+ data = MEM_mallocN(sz, __func__);
- if (fd == NULL) return 0;
- *fd = 0;
- if (BLO_has_bfile_extension(fd+1)) {
- /* the last part of the dir is a .blend file, no group follows */
- *fd = '/'; /* put back the removed slash separating the dir and the .blend file name */
+ BLI_assert((sz - sizeof(*data)) == (BLEN_THUMB_MEMSIZE_FILE(fd_data[0], fd_data[1]) - (sizeof(*fd_data) * 2)));
+ data->width = fd_data[0];
+ data->height = fd_data[1];
+ memcpy(data->rect, &fd_data[2], sz - sizeof(*data));
}
else {
- const char * const gp = fd + 1; // in case we have a .blend file, gp points to the group
-
- /* Find the last slash */
- fd = (char *)BLI_last_slash(dir);
- if (!fd || !BLO_has_bfile_extension(fd+1)) return 0;
-
- /* now we know that we are in a blend file and it is safe to
- * assume that gp actually points to a group */
- if (strcmp("Screen", gp) != 0)
- BLI_strncpy(group, gp, BLO_GROUP_MAX);
+ data = NULL;
}
- return 1;
+
+ blo_freefiledata(fd);
+
+ return data;
}
/* ************** OLD POINTERS ******************* */
@@ -1188,6 +1388,31 @@ static void *newdataadr(FileData *fd, void *adr) /* only direct databocks */
return oldnewmap_lookup_and_inc(fd->datamap, adr, true);
}
+/* This is a special version of newdataadr() which allows us to keep lasthit of
+ * map unchanged. In certain cases this makes file loading time significantly
+ * faster.
+ *
+ * Use this function in cases like restoring pointer from one list element to
+ * another list element, but keep lasthit value so we can continue restoring
+ * pointers efficiently.
+ *
+ * Example of this could be found in direct_link_fcurves() which restores the
+ * fcurve group pointer and keeps lasthit optimal for linking all further
+ * fcurves.
+ */
+static void *newdataadr_ex(FileData *fd, void *adr, bool increase_lasthit) /* only direct databocks */
+{
+ if (increase_lasthit) {
+ return newdataadr(fd, adr);
+ }
+ else {
+ int lasthit = fd->datamap->lasthit;
+ void *newadr = newdataadr(fd, adr);
+ fd->datamap->lasthit = lasthit;
+ return newadr;
+ }
+}
+
static void *newdataadr_no_us(FileData *fd, void *adr) /* only direct databocks */
{
return oldnewmap_lookup_and_inc(fd->datamap, adr, false);
@@ -1212,6 +1437,13 @@ static void *newmclipadr(FileData *fd, void *adr) /* used to restore movie
return NULL;
}
+static void *newsoundadr(FileData *fd, void *adr) /* used to restore sound data after undo */
+{
+ if (fd->soundmap && adr)
+ return oldnewmap_lookup_and_inc(fd->soundmap, adr, true);
+ return NULL;
+}
+
static void *newpackedadr(FileData *fd, void *adr) /* used to restore packed data after undo */
{
if (fd->packedmap && adr)
@@ -1428,6 +1660,37 @@ void blo_end_movieclip_pointer_map(FileData *fd, Main *oldmain)
}
}
+void blo_make_sound_pointer_map(FileData *fd, Main *oldmain)
+{
+ bSound *sound = oldmain->sound.first;
+
+ fd->soundmap = oldnewmap_new();
+
+ for (; sound; sound = sound->id.next) {
+ if (sound->waveform)
+ oldnewmap_insert(fd->soundmap, sound->waveform, sound->waveform, 0);
+ }
+}
+
+/* set old main sound caches to zero if it has been restored */
+/* this works because freeing old main only happens after this call */
+void blo_end_sound_pointer_map(FileData *fd, Main *oldmain)
+{
+ OldNew *entry = fd->soundmap->entries;
+ bSound *sound = oldmain->sound.first;
+ int i;
+
+ /* used entries were restored, so we put them to zero */
+ for (i = 0; i < fd->soundmap->nentries; i++, entry++) {
+ if (entry->nr > 0)
+ entry->newp = NULL;
+ }
+
+ for (; sound; sound = sound->id.next) {
+ sound->waveform = newsoundadr(fd, sound->waveform);
+ }
+}
+
/* XXX disabled this feature - packed files also belong in temp saves and quit.blend, to make restore work */
static void insert_packedmap(FileData *fd, PackedFile *pf)
@@ -1445,9 +1708,16 @@ void blo_make_packed_pointer_map(FileData *fd, Main *oldmain)
fd->packedmap = oldnewmap_new();
- for (ima = oldmain->image.first; ima; ima = ima->id.next)
+ for (ima = oldmain->image.first; ima; ima = ima->id.next) {
+ ImagePackedFile *imapf;
+
if (ima->packedfile)
insert_packedmap(fd, ima->packedfile);
+
+ for (imapf = ima->packedfiles.first; imapf; imapf = imapf->next)
+ if (imapf->packedfile)
+ insert_packedmap(fd, imapf->packedfile);
+ }
for (vfont = oldmain->vfont.first; vfont; vfont = vfont->id.next)
if (vfont->packedfile)
@@ -1480,8 +1750,14 @@ void blo_end_packed_pointer_map(FileData *fd, Main *oldmain)
entry->newp = NULL;
}
- for (ima = oldmain->image.first; ima; ima = ima->id.next)
+ for (ima = oldmain->image.first; ima; ima = ima->id.next) {
+ ImagePackedFile *imapf;
+
ima->packedfile = newpackedadr(fd, ima->packedfile);
+
+ for (imapf = ima->packedfiles.first; imapf; imapf = imapf->next)
+ imapf->packedfile = newpackedadr(fd, imapf->packedfile);
+ }
for (vfont = oldmain->vfont.first; vfont; vfont = vfont->id.next)
vfont->packedfile = newpackedadr(fd, vfont->packedfile);
@@ -1553,17 +1829,25 @@ static void *read_struct(FileData *fd, BHead *bh, const char *blockname)
return temp;
}
-static void link_list(FileData *fd, ListBase *lb) /* only direct data */
+typedef void (*link_list_cb)(FileData *fd, void *data);
+
+static void link_list_ex(FileData *fd, ListBase *lb, link_list_cb callback) /* only direct data */
{
Link *ln, *prev;
if (BLI_listbase_is_empty(lb)) return;
lb->first = newdataadr(fd, lb->first);
+ if (callback != NULL) {
+ callback(fd, lb->first);
+ }
ln = lb->first;
prev = NULL;
while (ln) {
ln->next = newdataadr(fd, ln->next);
+ if (ln->next != NULL && callback != NULL) {
+ callback(fd, ln->next);
+ }
ln->prev = prev;
prev = ln;
ln = ln->next;
@@ -1571,6 +1855,11 @@ static void link_list(FileData *fd, ListBase *lb) /* only direct data */
lb->last = prev;
}
+static void link_list(FileData *fd, ListBase *lb) /* only direct data */
+{
+ link_list_ex(fd, lb, NULL);
+}
+
static void link_glob_list(FileData *fd, ListBase *lb) /* for glob data */
{
Link *ln, *prev;
@@ -1780,6 +2069,25 @@ static void IDP_LibLinkProperty(IDProperty *UNUSED(prop), int UNUSED(switch_endi
{
}
+/* ************ READ IMAGE PREVIEW *************** */
+
+static PreviewImage *direct_link_preview_image(FileData *fd, PreviewImage *old_prv)
+{
+ PreviewImage *prv = newdataadr(fd, old_prv);
+
+ if (prv) {
+ int i;
+ for (i = 0; i < NUM_ICON_SIZES; ++i) {
+ if (prv->rect[i]) {
+ prv->rect[i] = newdataadr(fd, prv->rect[i]);
+ }
+ prv->gputexture[i] = NULL;
+ }
+ }
+
+ return prv;
+}
+
/* ************ READ ID *************** */
static void direct_link_id(FileData *fd, ID *id)
@@ -1862,7 +2170,6 @@ static void direct_link_palette(FileData *fd, Palette *palette)
{
/* palette itself has been read */
link_list(fd, &palette->colors);
- BLI_listbase_clear(&palette->deleted);
}
static void lib_link_paint_curve(FileData *UNUSED(fd), Main *main)
@@ -1895,7 +2202,7 @@ static void direct_link_script(FileData *UNUSED(fd), Script *script)
static PackedFile *direct_link_packedfile(FileData *fd, PackedFile *oldpf)
{
PackedFile *pf = newpackedadr(fd, oldpf);
-
+
if (pf) {
pf->data = newpackedadr(fd, pf->data);
}
@@ -1903,25 +2210,6 @@ static PackedFile *direct_link_packedfile(FileData *fd, PackedFile *oldpf)
return pf;
}
-/* ************ READ IMAGE PREVIEW *************** */
-
-static PreviewImage *direct_link_preview_image(FileData *fd, PreviewImage *old_prv)
-{
- PreviewImage *prv = newdataadr(fd, old_prv);
-
- if (prv) {
- int i;
- for (i = 0; i < NUM_ICON_SIZES; ++i) {
- if (prv->rect[i]) {
- prv->rect[i] = newdataadr(fd, prv->rect[i]);
- }
- prv->gputexture[i] = NULL;
- }
- }
-
- return prv;
-}
-
/* ************ READ ANIMATION STUFF ***************** */
/* Legacy Data Support (for Version Patching) ----------------------------- */
@@ -2006,8 +2294,9 @@ static void lib_link_fmodifiers(FileData *fd, ID *id, ListBase *list)
{
FMod_Python *data = (FMod_Python *)fcm->data;
data->script = newlibadr(fd, id->lib, data->script);
- }
+
break;
+ }
}
}
}
@@ -2065,23 +2354,26 @@ static void direct_link_fmodifiers(FileData *fd, ListBase *list)
if (fd->flags & FD_FLAGS_SWITCH_ENDIAN) {
BLI_endian_switch_float_array(data->coefficients, data->arraysize);
}
- }
+
break;
+ }
case FMODIFIER_TYPE_ENVELOPE:
{
FMod_Envelope *data= (FMod_Envelope *)fcm->data;
data->data= newdataadr(fd, data->data);
- }
+
break;
+ }
case FMODIFIER_TYPE_PYTHON:
{
FMod_Python *data = (FMod_Python *)fcm->data;
data->prop = newdataadr(fd, data->prop);
IDP_DirectLinkGroup_OrFree(&data->prop, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd);
- }
+
break;
+ }
}
}
}
@@ -2101,7 +2393,7 @@ static void direct_link_fcurves(FileData *fd, ListBase *list)
fcu->rna_path = newdataadr(fd, fcu->rna_path);
/* group */
- fcu->grp = newdataadr(fd, fcu->grp);
+ fcu->grp = newdataadr_ex(fd, fcu->grp, false);
/* clear disabled flag - allows disabled drivers to be tried again ([#32155]),
* but also means that another method for "reviving disabled F-Curves" exists
@@ -2333,12 +2625,13 @@ static void direct_link_animdata(FileData *fd, AnimData *adt)
link_list(fd, &adt->nla_tracks);
direct_link_nladata(fd, &adt->nla_tracks);
- /* relink active strip - even though strictly speaking this should only be used
+ /* relink active track/strip - even though strictly speaking this should only be used
* if we're in 'tweaking mode', we need to be able to have this loaded back for
* undo, but also since users may not exit tweakmode before saving (#24535)
*/
// TODO: it's not really nice that anyone should be able to save the file in this
// state, but it's going to be too hard to enforce this single case...
+ adt->act_track = newdataadr(fd, adt->act_track);
adt->actstrip = newdataadr(fd, adt->actstrip);
}
@@ -2540,7 +2833,7 @@ static void lib_verify_nodetree(Main *main, int UNUSED(open))
* New file versions already have input/output nodes with duplicate links,
* in that case just remove the invalid links.
*/
- int create_io_nodes = (ntree->flag & NTREE_DO_VERSIONS_CUSTOMNODES_GROUP_CREATE_INTERFACE);
+ const bool create_io_nodes = (ntree->flag & NTREE_DO_VERSIONS_CUSTOMNODES_GROUP_CREATE_INTERFACE) != 0;
float input_locx = 1000000.0f, input_locy = 0.0f;
float output_locx = -1000000.0f, output_locy = 0.0f;
@@ -2661,7 +2954,8 @@ static void direct_link_nodetree(FileData *fd, bNodeTree *ntree)
ntree->progress = NULL;
ntree->execdata = NULL;
-
+ ntree->duplilock = NULL;
+
ntree->adt = newdataadr(fd, ntree->adt);
direct_link_animdata(fd, ntree->adt);
@@ -2910,7 +3204,7 @@ static void lib_link_pose(FileData *fd, Main *bmain, Object *ob, bPose *pose)
if (rebuild) {
DAG_id_tag_update_ex(bmain, &ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
- pose->flag |= POSE_RECALC;
+ BKE_pose_tag_recalc(bmain, pose);
}
}
@@ -3079,14 +3373,14 @@ static void lib_link_key(FileData *fd, Main *main)
static void switch_endian_keyblock(Key *key, KeyBlock *kb)
{
int elemsize, a, b;
- const char *data, *poin, *cp;
+ char *data;
elemsize = key->elemsize;
data = kb->data;
for (a = 0; a < kb->totelem; a++) {
- cp = key->elemstr;
- poin = data;
+ const char *cp = key->elemstr;
+ char *poin = data;
while (cp[0]) { /* cp[0] == amount */
switch (cp[1]) { /* cp[1] = type */
@@ -3211,6 +3505,7 @@ static void direct_link_world(FileData *fd, World *wrld)
}
wrld->preview = direct_link_preview_image(fd, wrld->preview);
+ BLI_listbase_clear(&wrld->gpumaterial);
}
@@ -3303,9 +3598,11 @@ static void lib_link_image(FileData *fd, Main *main)
static void direct_link_image(FileData *fd, Image *ima)
{
+ ImagePackedFile *imapf;
+
/* for undo system, pointers could be restored */
if (fd->imamap)
- ima->cache = newmclipadr(fd, ima->cache);
+ ima->cache = newimaadr(fd, ima->cache);
else
ima->cache = NULL;
@@ -3316,8 +3613,7 @@ static void direct_link_image(FileData *fd, Image *ima)
ima->gputexture = NULL;
ima->rr = NULL;
}
-
- ima->anim = NULL;
+
ima->repbind = NULL;
/* undo system, try to restore render buffers */
@@ -3331,9 +3627,23 @@ static void direct_link_image(FileData *fd, Image *ima)
memset(ima->renders, 0, sizeof(ima->renders));
ima->last_render_slot = ima->render_slot;
}
-
- ima->packedfile = direct_link_packedfile(fd, ima->packedfile);
+
+ link_list(fd, &(ima->views));
+ link_list(fd, &(ima->packedfiles));
+
+ if (ima->packedfiles.first) {
+ for (imapf = ima->packedfiles.first; imapf; imapf = imapf->next) {
+ imapf->packedfile = direct_link_packedfile(fd, imapf->packedfile);
+ }
+ ima->packedfile = NULL;
+ }
+ else {
+ ima->packedfile = direct_link_packedfile(fd, ima->packedfile);
+ }
+
+ BLI_listbase_clear(&ima->anims);
ima->preview = direct_link_preview_image(fd, ima->preview);
+ ima->stereo3d_format = newdataadr(fd, ima->stereo3d_format);
ima->ok = 1;
}
@@ -3422,7 +3732,7 @@ static void direct_link_curve(FileData *fd, Curve *cu)
nu->bp = newdataadr(fd, nu->bp);
nu->knotsu = newdataadr(fd, nu->knotsu);
nu->knotsv = newdataadr(fd, nu->knotsv);
- if (cu->vfont == NULL) nu->charidx= nu->mat_nr;
+ if (cu->vfont == NULL) nu->charidx = 0;
if (fd->flags & FD_FLAGS_SWITCH_ENDIAN) {
switch_endian_knots(nu);
@@ -3583,35 +3893,34 @@ static const char *ptcache_data_struct[] = {
"", // BPHYS_DATA_TIMES:
"BoidData" // case BPHYS_DATA_BOIDS:
};
+
+static void direct_link_pointcache_cb(FileData *fd, void *data)
+{
+ PTCacheMem *pm = data;
+ PTCacheExtra *extra;
+ int i;
+ for (i = 0; i < BPHYS_TOT_DATA; i++) {
+ pm->data[i] = newdataadr(fd, pm->data[i]);
+
+ /* the cache saves non-struct data without DNA */
+ if (pm->data[i] && ptcache_data_struct[i][0]=='\0' && (fd->flags & FD_FLAGS_SWITCH_ENDIAN)) {
+ int tot = (BKE_ptcache_data_size (i) * pm->totpoint) / sizeof(int); /* data_size returns bytes */
+ int *poin = pm->data[i];
+
+ BLI_endian_switch_int32_array(poin, tot);
+ }
+ }
+
+ link_list(fd, &pm->extradata);
+
+ for (extra=pm->extradata.first; extra; extra=extra->next)
+ extra->data = newdataadr(fd, extra->data);
+}
+
static void direct_link_pointcache(FileData *fd, PointCache *cache)
{
if ((cache->flag & PTCACHE_DISK_CACHE)==0) {
- PTCacheMem *pm;
- PTCacheExtra *extra;
- int i;
-
- link_list(fd, &cache->mem_cache);
-
- pm = cache->mem_cache.first;
-
- for (; pm; pm=pm->next) {
- for (i=0; i<BPHYS_TOT_DATA; i++) {
- pm->data[i] = newdataadr(fd, pm->data[i]);
-
- /* the cache saves non-struct data without DNA */
- if (pm->data[i] && ptcache_data_struct[i][0]=='\0' && (fd->flags & FD_FLAGS_SWITCH_ENDIAN)) {
- int tot = (BKE_ptcache_data_size (i) * pm->totpoint) / sizeof(int); /* data_size returns bytes */
- int *poin = pm->data[i];
-
- BLI_endian_switch_int32_array(poin, tot);
- }
- }
-
- link_list(fd, &pm->extradata);
-
- for (extra=pm->extradata.first; extra; extra=extra->next)
- extra->data = newdataadr(fd, extra->data);
- }
+ link_list_ex(fd, &cache->mem_cache, direct_link_pointcache_cb);
}
else
BLI_listbase_clear(&cache->mem_cache);
@@ -3721,25 +4030,26 @@ static void lib_link_particlesettings(FileData *fd, Main *main)
BoidRule *rule;
for (; state; state=state->next) {
rule = state->rules.first;
- for (; rule; rule=rule->next)
- switch (rule->type) {
- case eBoidRuleType_Goal:
- case eBoidRuleType_Avoid:
- {
- BoidRuleGoalAvoid *brga = (BoidRuleGoalAvoid*)rule;
- brga->ob = newlibadr(fd, part->id.lib, brga->ob);
- break;
- }
- case eBoidRuleType_FollowLeader:
- {
- BoidRuleFollowLeader *brfl = (BoidRuleFollowLeader*)rule;
- brfl->ob = newlibadr(fd, part->id.lib, brfl->ob);
- break;
+ for (; rule; rule=rule->next) {
+ switch (rule->type) {
+ case eBoidRuleType_Goal:
+ case eBoidRuleType_Avoid:
+ {
+ BoidRuleGoalAvoid *brga = (BoidRuleGoalAvoid*)rule;
+ brga->ob = newlibadr(fd, part->id.lib, brga->ob);
+ break;
+ }
+ case eBoidRuleType_FollowLeader:
+ {
+ BoidRuleFollowLeader *brfl = (BoidRuleFollowLeader*)rule;
+ brfl->ob = newlibadr(fd, part->id.lib, brfl->ob);
+ break;
+ }
}
}
}
}
-
+
for (a = 0; a < MAX_MTEX; a++) {
mtex= part->mtex[a];
if (mtex) {
@@ -3770,6 +4080,13 @@ static void direct_link_particlesettings(FileData *fd, ParticleSettings *part)
direct_link_partdeflect(part->pd);
direct_link_partdeflect(part->pd2);
+ part->clumpcurve = newdataadr(fd, part->clumpcurve);
+ if (part->clumpcurve)
+ direct_link_curvemapping(fd, part->clumpcurve);
+ part->roughcurve = newdataadr(fd, part->roughcurve);
+ if (part->roughcurve)
+ direct_link_curvemapping(fd, part->roughcurve);
+
part->effector_weights = newdataadr(fd, part->effector_weights);
if (!part->effector_weights)
part->effector_weights = BKE_add_effector_weights(part->eff_group);
@@ -3813,7 +4130,7 @@ static void lib_link_particlesystems(FileData *fd, Object *ob, ID *id, ListBase
if (psys->clmd) {
/* XXX - from reading existing code this seems correct but intended usage of
- * pointcache should /w cloth should be added in 'ParticleSystem' - campbell */
+ * pointcache /w cloth should be added in 'ParticleSystem' - campbell */
psys->clmd->point_cache = psys->pointcache;
psys->clmd->ptcaches.first = psys->clmd->ptcaches.last= NULL;
psys->clmd->coll_parms->group = newlibadr(fd, id->lib, psys->clmd->coll_parms->group);
@@ -3881,11 +4198,10 @@ static void direct_link_particlesystems(FileData *fd, ListBase *particles)
psys->pdd = NULL;
psys->renderdata = NULL;
- direct_link_pointcache_list(fd, &psys->ptcaches, &psys->pointcache, 0);
-
if (psys->clmd) {
psys->clmd = newdataadr(fd, psys->clmd);
psys->clmd->clothObject = NULL;
+ psys->clmd->hairdata = NULL;
psys->clmd->sim_parms= newdataadr(fd, psys->clmd->sim_parms);
psys->clmd->coll_parms= newdataadr(fd, psys->clmd->coll_parms);
@@ -3897,10 +4213,14 @@ static void direct_link_particlesystems(FileData *fd, ListBase *particles)
}
psys->hair_in_dm = psys->hair_out_dm = NULL;
-
+ psys->clmd->solver_result = NULL;
+ }
+
+ direct_link_pointcache_list(fd, &psys->ptcaches, &psys->pointcache, 0);
+ if (psys->clmd) {
psys->clmd->point_cache = psys->pointcache;
}
-
+
psys->tree = NULL;
psys->bvhtree = NULL;
}
@@ -4425,7 +4745,7 @@ static void lib_link_object(FileData *fd, Main *main)
bCameraActuator *ca = act->data;
ca->ob= newlibadr(fd, ob->id.lib, ca->ob);
}
- /* leave this one, it's obsolete but necessary to read for conversion */
+ /* leave this one, it's obsolete but necessary to read for conversion */
else if (act->type == ACT_ADD_OBJECT) {
bAddObjectActuator *eoa = act->data;
if (eoa) eoa->ob= newlibadr(fd, ob->id.lib, eoa->ob);
@@ -4456,11 +4776,11 @@ static void lib_link_object(FileData *fd, Main *main)
}
else if (act->type == ACT_ACTION) {
bActionActuator *aa = act->data;
- aa->act= newlibadr(fd, ob->id.lib, aa->act);
+ aa->act= newlibadr_us(fd, ob->id.lib, aa->act);
}
else if (act->type == ACT_SHAPEACTION) {
bActionActuator *aa = act->data;
- aa->act= newlibadr(fd, ob->id.lib, aa->act);
+ aa->act= newlibadr_us(fd, ob->id.lib, aa->act);
}
else if (act->type == ACT_PROPERTY) {
bPropertyActuator *pa = act->data;
@@ -4491,7 +4811,7 @@ static void lib_link_object(FileData *fd, Main *main)
steeringa->target = newlibadr(fd, ob->id.lib, steeringa->target);
steeringa->navmesh = newlibadr(fd, ob->id.lib, steeringa->navmesh);
}
- else if(act->type == ACT_MOUSE) {
+ else if (act->type == ACT_MOUSE) {
/* bMouseActuator *moa= act->data; */
}
}
@@ -4611,6 +4931,7 @@ static void direct_link_modifiers(FileData *fd, ListBase *lb)
ClothModifierData *clmd = (ClothModifierData *)md;
clmd->clothObject = NULL;
+ clmd->hairdata = NULL;
clmd->sim_parms= newdataadr(fd, clmd->sim_parms);
clmd->coll_parms= newdataadr(fd, clmd->coll_parms);
@@ -4629,6 +4950,8 @@ static void direct_link_modifiers(FileData *fd, ListBase *lb)
clmd->sim_parms->effector_weights = BKE_add_effector_weights(NULL);
}
}
+
+ clmd->solver_result = NULL;
}
else if (md->type == eModifierType_Fluidsim) {
FluidsimModifierData *fluidmd = (FluidsimModifierData *)md;
@@ -4758,9 +5081,10 @@ static void direct_link_modifiers(FileData *fd, ListBase *lb)
collmd->current_xnew = NULL;
collmd->current_v = NULL;
collmd->time_x = collmd->time_xnew = -1000;
- collmd->numverts = 0;
+ collmd->mvert_num = 0;
+ collmd->tri_num = 0;
collmd->bvhtree = NULL;
- collmd->mfaces = NULL;
+ collmd->tri = NULL;
}
else if (md->type == eModifierType_Surface) {
@@ -4779,6 +5103,11 @@ static void direct_link_modifiers(FileData *fd, ListBase *lb)
if (fd->flags & FD_FLAGS_SWITCH_ENDIAN) {
BLI_endian_switch_int32_array(hmd->indexar, hmd->totindex);
}
+
+ hmd->curfalloff = newdataadr(fd, hmd->curfalloff);
+ if (hmd->curfalloff) {
+ direct_link_curvemapping(fd, hmd->curfalloff);
+ }
}
else if (md->type == eModifierType_ParticleSystem) {
ParticleSystemModifierData *psmd = (ParticleSystemModifierData *)md;
@@ -4843,6 +5172,20 @@ static void direct_link_modifiers(FileData *fd, ListBase *lb)
}
lmd->cache_system = NULL;
}
+ else if (md->type == eModifierType_CorrectiveSmooth) {
+ CorrectiveSmoothModifierData *csmd = (CorrectiveSmoothModifierData*)md;
+
+ if (csmd->bind_coords) {
+ csmd->bind_coords = newdataadr(fd, csmd->bind_coords);
+ if (fd->flags & FD_FLAGS_SWITCH_ENDIAN) {
+ BLI_endian_switch_float_array((float *)csmd->bind_coords, csmd->bind_coords_num * 3);
+ }
+ }
+
+ /* runtime only */
+ csmd->delta_cache = NULL;
+ csmd->delta_cache_num = 0;
+ }
}
}
@@ -4865,9 +5208,14 @@ static void direct_link_object(FileData *fd, Object *ob)
/* loading saved files with editmode enabled works, but for undo we like
* to stay in object mode during undo presses so keep editmode disabled.
*
- * Also when linking in a file don't allow editmode: [#34776] */
+ * Also when linking in a file don't allow edit and pose modes.
+ * See [#34776, #42780] for more information.
+ */
if (fd->memfile || (ob->id.flag & (LIB_EXTERN | LIB_INDIRECT))) {
ob->mode &= ~(OB_MODE_EDIT | OB_MODE_PARTICLE_EDIT);
+ if (!fd->memfile) {
+ ob->mode &= ~OB_MODE_POSE;
+ }
}
ob->adt = newdataadr(fd, ob->adt);
@@ -5081,6 +5429,8 @@ static void direct_link_object(FileData *fd, Object *ob)
link_list(fd, &ob->lodlevels);
ob->currentlod = ob->lodlevels.first;
+
+ ob->preview = direct_link_preview_image(fd, ob->preview);
}
/* ************ READ SCENE ***************** */
@@ -5115,6 +5465,36 @@ static void lib_link_sequence_modifiers(FileData *fd, Scene *scene, ListBase *lb
}
}
+/* check for cyclic set-scene,
+ * libs can cause this case which is normally prevented, see (T#####) */
+#define USE_SETSCENE_CHECK
+
+#ifdef USE_SETSCENE_CHECK
+/**
+ * A version of #BKE_scene_validate_setscene with special checks for linked libs.
+ */
+static bool scene_validate_setscene__liblink(Scene *sce, const int totscene)
+{
+ Scene *sce_iter;
+ int a;
+
+ if (sce->set == NULL) return 1;
+
+ for (a = 0, sce_iter = sce; sce_iter->set; sce_iter = sce_iter->set, a++) {
+ if (sce_iter->id.flag & LIB_NEED_LINK) {
+ return 1;
+ }
+
+ if (a > totscene) {
+ sce->set = NULL;
+ return 0;
+ }
+ }
+
+ return 1;
+}
+#endif
+
static void lib_link_scene(FileData *fd, Main *main)
{
Scene *sce;
@@ -5124,6 +5504,11 @@ static void lib_link_scene(FileData *fd, Main *main)
TimeMarker *marker;
FreestyleModuleConfig *fmc;
FreestyleLineSet *fls;
+
+#ifdef USE_SETSCENE_CHECK
+ bool need_check_set = false;
+ int totscene = 0;
+#endif
for (sce = main->scene.first; sce; sce = sce->id.next) {
if (sce->id.flag & LIB_NEED_LINK) {
@@ -5163,6 +5548,8 @@ static void lib_link_scene(FileData *fd, Main *main)
sce->toolsettings->skgen_template = newlibadr(fd, sce->id.lib, sce->toolsettings->skgen_template);
+ sce->toolsettings->particle.shape_object = newlibadr(fd, sce->id.lib, sce->toolsettings->particle.shape_object);
+
for (base = sce->base.first; base; base = next) {
next = base->next;
@@ -5185,7 +5572,7 @@ static void lib_link_scene(FileData *fd, Main *main)
if (seq->scene) {
seq->scene = newlibadr(fd, sce->id.lib, seq->scene);
if (seq->scene) {
- seq->scene_sound = sound_scene_add_scene_sound_defaults(sce, seq);
+ seq->scene_sound = BKE_sound_scene_add_scene_sound_defaults(sce, seq);
}
}
if (seq->clip) {
@@ -5213,10 +5600,10 @@ static void lib_link_scene(FileData *fd, Main *main)
}
if (seq->sound) {
seq->sound->id.us++;
- seq->scene_sound = sound_add_scene_sound_defaults(sce, seq);
+ seq->scene_sound = BKE_sound_add_scene_sound_defaults(sce, seq);
}
}
- seq->anim = NULL;
+ BLI_listbase_clear(&seq->anims);
lib_link_sequence_modifiers(fd, sce, &seq->modifiers);
}
@@ -5269,12 +5656,45 @@ static void lib_link_scene(FileData *fd, Main *main)
/* Motion Tracking */
sce->clip = newlibadr_us(fd, sce->id.lib, sce->clip);
-
- sce->id.flag -= LIB_NEED_LINK;
+
+#ifdef USE_SETSCENE_CHECK
+ if (sce->set != NULL) {
+ /* link flag for scenes with set would be reset later,
+ * so this way we only check cyclic for newly linked scenes.
+ */
+ need_check_set = true;
+ }
+ else {
+ /* postpone un-setting the flag until we've checked the set-scene */
+ sce->id.flag &= ~LIB_NEED_LINK;
+ }
+#else
+ sce->id.flag &= ~LIB_NEED_LINK;
+#endif
}
+
+#ifdef USE_SETSCENE_CHECK
+ totscene++;
+#endif
}
+
+#ifdef USE_SETSCENE_CHECK
+ if (need_check_set) {
+ for (sce = main->scene.first; sce; sce = sce->id.next) {
+ if (sce->id.flag & LIB_NEED_LINK) {
+ sce->id.flag &= ~LIB_NEED_LINK;
+ if (!scene_validate_setscene__liblink(sce, totscene)) {
+ printf("Found cyclic background scene when linking %s\n", sce->id.name + 2);
+ }
+ }
+ }
+ }
+#endif
}
+#undef USE_SETSCENE_CHECK
+
+
static void link_recurs_seq(FileData *fd, ListBase *lb)
{
Sequence *seq;
@@ -5287,12 +5707,26 @@ static void link_recurs_seq(FileData *fd, ListBase *lb)
}
}
-static void direct_link_paint(FileData *fd, Paint **paint)
+static void direct_link_paint(FileData *fd, Paint *p)
+{
+ if (p->num_input_samples < 1)
+ p->num_input_samples = 1;
+
+ p->cavity_curve = newdataadr(fd, p->cavity_curve);
+ if (p->cavity_curve)
+ direct_link_curvemapping(fd, p->cavity_curve);
+ else
+ BKE_paint_cavity_curve_preset(p, CURVE_PRESET_LINE);
+}
+
+static void direct_link_paint_helper(FileData *fd, Paint **paint)
{
/* TODO. is this needed */
(*paint) = newdataadr(fd, (*paint));
- if (*paint && (*paint)->num_input_samples < 1)
- (*paint)->num_input_samples = 1;
+
+ if (*paint) {
+ direct_link_paint(fd, *paint);
+ }
}
static void direct_link_sequence_modifiers(FileData *fd, ListBase *lb)
@@ -5335,13 +5769,14 @@ static void direct_link_scene(FileData *fd, Scene *sce)
SceneRenderLayer *srl;
sce->theDag = NULL;
+ sce->depsgraph = NULL;
sce->obedit = NULL;
sce->stats = NULL;
sce->fps_info = NULL;
sce->customdata_mask_modal = 0;
sce->lay_updated = 0;
- sound_create_scene(sce);
+ BKE_sound_create_scene(sce);
/* set users to one by default, not in lib-link, this will increase it for compo nodes */
sce->id.us = 1;
@@ -5358,11 +5793,13 @@ static void direct_link_scene(FileData *fd, Scene *sce)
sce->toolsettings= newdataadr(fd, sce->toolsettings);
if (sce->toolsettings) {
- direct_link_paint(fd, (Paint**)&sce->toolsettings->sculpt);
- direct_link_paint(fd, (Paint**)&sce->toolsettings->vpaint);
- direct_link_paint(fd, (Paint**)&sce->toolsettings->wpaint);
- direct_link_paint(fd, (Paint**)&sce->toolsettings->uvsculpt);
+ direct_link_paint_helper(fd, (Paint**)&sce->toolsettings->sculpt);
+ direct_link_paint_helper(fd, (Paint**)&sce->toolsettings->vpaint);
+ direct_link_paint_helper(fd, (Paint**)&sce->toolsettings->wpaint);
+ direct_link_paint_helper(fd, (Paint**)&sce->toolsettings->uvsculpt);
+ direct_link_paint(fd, &sce->toolsettings->imapaint.paint);
+
sce->toolsettings->imapaint.paintcursor = NULL;
sce->toolsettings->particle.paintcursor = NULL;
sce->toolsettings->particle.scene = NULL;
@@ -5380,7 +5817,7 @@ static void direct_link_scene(FileData *fd, Scene *sce)
}
if (sce->ed) {
- ListBase *old_seqbasep = &((Editing *)sce->ed)->seqbase;
+ ListBase *old_seqbasep = &sce->ed->seqbase;
ed = sce->ed = newdataadr(fd, sce->ed);
@@ -5394,10 +5831,12 @@ static void direct_link_scene(FileData *fd, Scene *sce)
seq->seq1= newdataadr(fd, seq->seq1);
seq->seq2= newdataadr(fd, seq->seq2);
seq->seq3= newdataadr(fd, seq->seq3);
+
/* a patch: after introduction of effects with 3 input strips */
if (seq->seq3 == NULL) seq->seq3 = seq->seq2;
seq->effectdata = newdataadr(fd, seq->effectdata);
+ seq->stereo3d_format = newdataadr(fd, seq->stereo3d_format);
if (seq->type & SEQ_TYPE_EFFECT)
seq->flag |= SEQ_EFFECT_NOT_LOADED;
@@ -5406,7 +5845,10 @@ static void direct_link_scene(FileData *fd, Scene *sce)
SpeedControlVars *s = seq->effectdata;
s->frameMap = NULL;
}
-
+
+ seq->prop = newdataadr(fd, seq->prop);
+ IDP_DirectLinkGroup_OrFree(&seq->prop, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd);
+
seq->strip = newdataadr(fd, seq->strip);
if (seq->strip && seq->strip->done==0) {
seq->strip->done = true;
@@ -5451,7 +5893,7 @@ static void direct_link_scene(FileData *fd, Scene *sce)
/* link metastack, slight abuse of structs here, have to restore pointer to internal part in struct */
{
Sequence temp;
- char *poin;
+ void *poin;
intptr_t offset;
offset = ((intptr_t)&(temp.seqbase)) - ((intptr_t)&temp);
@@ -5461,12 +5903,11 @@ static void direct_link_scene(FileData *fd, Scene *sce)
ed->seqbasep = &ed->seqbase;
}
else {
- poin = (char *)ed->seqbasep;
- poin -= offset;
+ poin = POINTER_OFFSET(ed->seqbasep, -offset);
poin = newdataadr(fd, poin);
if (poin)
- ed->seqbasep = (ListBase *)(poin+offset);
+ ed->seqbasep = (ListBase *)POINTER_OFFSET(poin, offset);
else
ed->seqbasep = &ed->seqbase;
}
@@ -5479,11 +5920,10 @@ static void direct_link_scene(FileData *fd, Scene *sce)
if (ms->oldbasep == old_seqbasep)
ms->oldbasep= &ed->seqbase;
else {
- poin = (char *)ms->oldbasep;
- poin -= offset;
+ poin = POINTER_OFFSET(ms->oldbasep, -offset);
poin = newdataadr(fd, poin);
if (poin)
- ms->oldbasep = (ListBase *)(poin+offset);
+ ms->oldbasep = (ListBase *)POINTER_OFFSET(poin, offset);
else
ms->oldbasep = &ed->seqbase;
}
@@ -5509,6 +5949,7 @@ static void direct_link_scene(FileData *fd, Scene *sce)
link_list(fd, &(sce->markers));
link_list(fd, &(sce->transform_spaces));
link_list(fd, &(sce->r.layers));
+ link_list(fd, &(sce->r.views));
for (srl = sce->r.layers.first; srl; srl = srl->next) {
link_list(fd, &(srl->freestyleConfig.modules));
@@ -5547,6 +5988,8 @@ static void direct_link_scene(FileData *fd, Scene *sce)
rbw->ltime = (float)rbw->pointcache->startframe;
}
}
+
+ sce->preview = direct_link_preview_image(fd, sce->preview);
}
/* ************ READ WM ***************** */
@@ -5563,14 +6006,17 @@ static void direct_link_windowmanager(FileData *fd, wmWindowManager *wm)
win->eventstate = NULL;
win->curswin = NULL;
win->tweak = NULL;
+#ifdef WIN32
+ win->ime_data = NULL;
+#endif
BLI_listbase_clear(&win->queue);
BLI_listbase_clear(&win->handlers);
BLI_listbase_clear(&win->modalhandlers);
BLI_listbase_clear(&win->subwindows);
BLI_listbase_clear(&win->gesture);
+ BLI_listbase_clear(&win->drawdata);
- win->drawdata = NULL;
win->drawmethod = -1;
win->drawfail = 0;
win->active = 0;
@@ -5578,6 +6024,13 @@ static void direct_link_windowmanager(FileData *fd, wmWindowManager *wm)
win->cursor = 0;
win->lastcursor = 0;
win->modalcursor = 0;
+ win->stereo3d_format = newdataadr(fd, win->stereo3d_format);
+
+ /* multiview always fallback to anaglyph at file opening
+ * otherwise quadbuffer saved files can break Blender */
+ if (win->stereo3d_format) {
+ win->stereo3d_format->display_mode = S3D_DISPLAY_ANAGLYPH;
+ }
}
BLI_listbase_clear(&wm->timers);
@@ -5618,6 +6071,21 @@ static void lib_link_windowmanager(FileData *fd, Main *main)
/* ****************** READ GREASE PENCIL ***************** */
+/* relink's grease pencil data's refs */
+static void lib_link_gpencil(FileData *fd, Main *main)
+{
+ bGPdata *gpd;
+
+ for (gpd = main->gpencil.first; gpd; gpd = gpd->id.next) {
+ if (gpd->id.flag & LIB_NEED_LINK) {
+ gpd->id.flag -= LIB_NEED_LINK;
+
+ if (gpd->adt)
+ lib_link_animdata(fd, &gpd->id, gpd->adt);
+ }
+ }
+}
+
/* relinks grease-pencil data - used for direct_link and old file linkage */
static void direct_link_gpencil(FileData *fd, bGPdata *gpd)
{
@@ -5629,6 +6097,10 @@ static void direct_link_gpencil(FileData *fd, bGPdata *gpd)
if (gpd == NULL)
return;
+ /* relink animdata */
+ gpd->adt = newdataadr(fd, gpd->adt);
+ direct_link_animdata(fd, gpd->adt);
+
/* relink layers */
link_list(fd, &gpd->layers);
@@ -5661,7 +6133,14 @@ static void lib_link_screen(FileData *fd, Main *main)
if (sc->id.flag & LIB_NEED_LINK) {
sc->id.us = 1;
sc->scene = newlibadr(fd, sc->id.lib, sc->scene);
+
+ /* this should not happen, but apparently it does somehow. Until we figure out the cause,
+ * just assign first available scene */
+ if (!sc->scene)
+ sc->scene = main->scene.first;
+
sc->animtimer = NULL; /* saved in rare cases */
+ sc->scrubbing = false;
for (sa = sc->areabase.first; sa; sa = sa->next) {
SpaceLink *sl;
@@ -5703,6 +6182,9 @@ static void lib_link_screen(FileData *fd, Main *main)
else if (sl->spacetype == SPACE_BUTS) {
SpaceButs *sbuts = (SpaceButs *)sl;
sbuts->pinid = newlibadr(fd, sc->id.lib, sbuts->pinid);
+ if (sbuts->pinid == NULL) {
+ sbuts->flag &= ~SB_PIN_CONTEXT;
+ }
}
else if (sl->spacetype == SPACE_FILE) {
;
@@ -5776,7 +6258,7 @@ static void lib_link_screen(FileData *fd, Main *main)
}
if (so->treehash) {
/* rebuild hash table, because it depends on ids too */
- BKE_treehash_rebuild_from_treestore(so->treehash, so->treestore);
+ so->storeflag |= SO_TREESTORE_REBUILD;
}
}
}
@@ -5852,7 +6334,7 @@ typedef enum ePointerUserMode {
static bool restore_pointer(ID *id, ID *newid, ePointerUserMode user)
{
- if (strcmp(newid->name + 2, id->name + 2) == 0) {
+ if (STREQ(newid->name + 2, id->name + 2)) {
if (newid->lib == id->lib) {
if (user == USER_ONE) {
if (newid->us == 0) {
@@ -6032,6 +6514,9 @@ void blo_lib_link_screen_restore(Main *newmain, bScreen *curscreen, Scene *cursc
else if (sl->spacetype == SPACE_BUTS) {
SpaceButs *sbuts = (SpaceButs *)sl;
sbuts->pinid = restore_pointer_by_name(newmain, sbuts->pinid, USER_IGNORE);
+ if (sbuts->pinid == NULL) {
+ sbuts->flag &= ~SB_PIN_CONTEXT;
+ }
/* TODO: restore path pointers: T40046
* (complicated because this contains data pointers too, not just ID)*/
@@ -6040,6 +6525,7 @@ void blo_lib_link_screen_restore(Main *newmain, bScreen *curscreen, Scene *cursc
else if (sl->spacetype == SPACE_FILE) {
SpaceFile *sfile = (SpaceFile *)sl;
sfile->op = NULL;
+ sfile->previews_timer = NULL;
}
else if (sl->spacetype == SPACE_ACTION) {
SpaceAction *saction = (SpaceAction *)sl;
@@ -6123,11 +6609,17 @@ void blo_lib_link_screen_restore(Main *newmain, bScreen *curscreen, Scene *cursc
BLI_mempool_iternew(so->treestore, &iter);
while ((tselem = BLI_mempool_iterstep(&iter))) {
- tselem->id = restore_pointer_by_name(newmain, tselem->id, USER_IGNORE);
+ /* Do not try to restore pointers to drivers/sequence/etc., can crash in undo case! */
+ if (TSE_IS_REAL_ID(tselem)) {
+ tselem->id = restore_pointer_by_name(newmain, tselem->id, USER_IGNORE);
+ }
+ else {
+ tselem->id = NULL;
+ }
}
if (so->treehash) {
/* rebuild hash table, because it depends on ids too */
- BKE_treehash_rebuild_from_treestore(so->treehash, so->treestore);
+ so->storeflag |= SO_TREESTORE_REBUILD;
}
}
}
@@ -6238,10 +6730,10 @@ static void direct_link_region(FileData *fd, ARegion *ar, int spacetype)
rv3d->depths = NULL;
rv3d->gpuoffscreen = NULL;
- rv3d->ri = NULL;
rv3d->render_engine = NULL;
rv3d->sms = NULL;
rv3d->smooth_timer = NULL;
+ rv3d->compositor = NULL;
}
}
}
@@ -6284,6 +6776,8 @@ void blo_do_versions_view3d_split_250(View3D *v3d, ListBase *regions)
/* this was not initialized correct always */
if (v3d->twtype == 0)
v3d->twtype = V3D_MANIP_TRANSLATE;
+ if (v3d->gridsubdiv == 0)
+ v3d->gridsubdiv = 10;
}
static bool direct_link_screen(FileData *fd, bScreen *sc)
@@ -6349,7 +6843,7 @@ static bool direct_link_screen(FileData *fd, bScreen *sc)
/* add local view3d too */
else if (sa->spacetype == SPACE_VIEW3D)
blo_do_versions_view3d_split_250(sa->spacedata.first, &sa->regionbase);
-
+
/* incase we set above */
sa->butspacetype = sa->spacetype;
@@ -6396,6 +6890,11 @@ static bool direct_link_screen(FileData *fd, bScreen *sc)
/* render can be quite heavy, set to solid on load */
if (v3d->drawtype == OB_RENDER)
v3d->drawtype = OB_SOLID;
+
+ if (v3d->fx_settings.dof)
+ v3d->fx_settings.dof = newdataadr(fd, v3d->fx_settings.dof);
+ if (v3d->fx_settings.ssao)
+ v3d->fx_settings.ssao = newdataadr(fd, v3d->fx_settings.ssao);
blo_do_versions_view3d_split_250(v3d, &sl->regionbase);
}
@@ -6471,6 +6970,7 @@ static bool direct_link_screen(FileData *fd, bScreen *sc)
link_list(fd, &snode->treepath);
snode->edittree = NULL;
+ snode->iofsd = NULL;
BLI_listbase_clear(&snode->linkdrag);
}
else if (sl->spacetype == SPACE_TEXT) {
@@ -6561,6 +7061,7 @@ static bool direct_link_screen(FileData *fd, bScreen *sc)
sfile->files = NULL;
sfile->layout = NULL;
sfile->op = NULL;
+ sfile->previews_timer = NULL;
sfile->params = newdataadr(fd, sfile->params);
}
else if (sl->spacetype == SPACE_CLIP) {
@@ -6700,14 +7201,27 @@ static void direct_link_sound(FileData *fd, bSound *sound)
{
sound->handle = NULL;
sound->playback_handle = NULL;
- sound->waveform = NULL;
- // versioning stuff, if there was a cache, then we enable caching:
+ /* versioning stuff, if there was a cache, then we enable caching: */
if (sound->cache) {
sound->flags |= SOUND_FLAGS_CACHING;
sound->cache = NULL;
}
+ if (fd->soundmap) {
+ sound->waveform = newsoundadr(fd, sound->waveform);
+ }
+ else {
+ sound->waveform = NULL;
+ }
+
+ if (sound->spinlock) {
+ sound->spinlock = MEM_mallocN(sizeof(SpinLock), "sound_spinlock");
+ BLI_spin_init(sound->spinlock);
+ }
+ /* clear waveform loading flag */
+ sound->flags &= ~SOUND_FLAGS_WAVEFORM_LOADING;
+
sound->packedfile = direct_link_packedfile(fd, sound->packedfile);
sound->newpackedfile = direct_link_packedfile(fd, sound->newpackedfile);
}
@@ -6721,7 +7235,7 @@ static void lib_link_sound(FileData *fd, Main *main)
sound->id.flag -= LIB_NEED_LINK;
sound->ipo = newlibadr_us(fd, sound->id.lib, sound->ipo); // XXX deprecated - old animation system
- sound_load(main, sound);
+ BKE_sound_load(main, sound);
}
}
}
@@ -6730,6 +7244,8 @@ static void lib_link_sound(FileData *fd, Main *main)
static void direct_link_group(FileData *fd, Group *group)
{
link_list(fd, &group->gobject);
+
+ group->preview = direct_link_preview_image(fd, group->preview);
}
static void lib_link_group(FileData *fd, Main *main)
@@ -6791,7 +7307,7 @@ static void direct_link_moviePlaneTracks(FileData *fd, ListBase *plane_tracks_ba
int i;
plane_track->point_tracks = newdataadr(fd, plane_track->point_tracks);
-
+ test_pointer_array(fd, (void**)&plane_track->point_tracks);
for (i = 0; i < plane_track->point_tracksnr; i++) {
plane_track->point_tracks[i] = newdataadr(fd, plane_track->point_tracks[i]);
}
@@ -7065,6 +7581,30 @@ static void direct_link_linestyle_color_modifier(FileData *fd, LineStyleModifier
m->color_ramp = newdataadr(fd, m->color_ramp);
}
break;
+ case LS_MODIFIER_TANGENT:
+ {
+ LineStyleColorModifier_Tangent *m = (LineStyleColorModifier_Tangent *)modifier;
+ m->color_ramp = newdataadr(fd, m->color_ramp);
+ }
+ break;
+ case LS_MODIFIER_NOISE:
+ {
+ LineStyleColorModifier_Noise *m = (LineStyleColorModifier_Noise *)modifier;
+ m->color_ramp = newdataadr(fd, m->color_ramp);
+ }
+ break;
+ case LS_MODIFIER_CREASE_ANGLE:
+ {
+ LineStyleColorModifier_CreaseAngle *m = (LineStyleColorModifier_CreaseAngle *)modifier;
+ m->color_ramp = newdataadr(fd, m->color_ramp);
+ }
+ break;
+ case LS_MODIFIER_CURVATURE_3D:
+ {
+ LineStyleColorModifier_Curvature_3D *m = (LineStyleColorModifier_Curvature_3D *)modifier;
+ m->color_ramp = newdataadr(fd, m->color_ramp);
+ }
+ break;
}
}
@@ -7099,6 +7639,34 @@ static void direct_link_linestyle_alpha_modifier(FileData *fd, LineStyleModifier
direct_link_curvemapping(fd, m->curve);
}
break;
+ case LS_MODIFIER_TANGENT:
+ {
+ LineStyleAlphaModifier_Tangent *m = (LineStyleAlphaModifier_Tangent *)modifier;
+ m->curve = newdataadr(fd, m->curve);
+ direct_link_curvemapping(fd, m->curve);
+ }
+ break;
+ case LS_MODIFIER_NOISE:
+ {
+ LineStyleAlphaModifier_Noise *m = (LineStyleAlphaModifier_Noise *)modifier;
+ m->curve = newdataadr(fd, m->curve);
+ direct_link_curvemapping(fd, m->curve);
+ }
+ break;
+ case LS_MODIFIER_CREASE_ANGLE:
+ {
+ LineStyleAlphaModifier_CreaseAngle *m = (LineStyleAlphaModifier_CreaseAngle *)modifier;
+ m->curve = newdataadr(fd, m->curve);
+ direct_link_curvemapping(fd, m->curve);
+ }
+ break;
+ case LS_MODIFIER_CURVATURE_3D:
+ {
+ LineStyleAlphaModifier_Curvature_3D *m = (LineStyleAlphaModifier_Curvature_3D *)modifier;
+ m->curve = newdataadr(fd, m->curve);
+ direct_link_curvemapping(fd, m->curve);
+ }
+ break;
}
}
@@ -7133,6 +7701,27 @@ static void direct_link_linestyle_thickness_modifier(FileData *fd, LineStyleModi
direct_link_curvemapping(fd, m->curve);
}
break;
+ case LS_MODIFIER_TANGENT:
+ {
+ LineStyleThicknessModifier_Tangent *m = (LineStyleThicknessModifier_Tangent *)modifier;
+ m->curve = newdataadr(fd, m->curve);
+ direct_link_curvemapping(fd, m->curve);
+ }
+ break;
+ case LS_MODIFIER_CREASE_ANGLE:
+ {
+ LineStyleThicknessModifier_CreaseAngle *m = (LineStyleThicknessModifier_CreaseAngle *)modifier;
+ m->curve = newdataadr(fd, m->curve);
+ direct_link_curvemapping(fd, m->curve);
+ }
+ break;
+ case LS_MODIFIER_CURVATURE_3D:
+ {
+ LineStyleThicknessModifier_Curvature_3D *m = (LineStyleThicknessModifier_Curvature_3D *)modifier;
+ m->curve = newdataadr(fd, m->curve);
+ direct_link_curvemapping(fd, m->curve);
+ }
+ break;
}
}
@@ -7419,9 +8008,7 @@ static BHead *read_global(BlendFileData *bfd, FileData *fd, BHead *bhead)
bfd->main->build_commit_timestamp = fg->build_commit_timestamp;
BLI_strncpy(bfd->main->build_hash, fg->build_hash, sizeof(bfd->main->build_hash));
- bfd->winpos = fg->winpos;
bfd->fileflags = fg->fileflags;
- bfd->displaymode = fg->displaymode;
bfd->globalf = fg->globalf;
BLI_strncpy(bfd->filename, fg->filename, sizeof(bfd->filename));
@@ -7508,7 +8095,6 @@ static void do_versions_userdef(FileData *fd, BlendFileData *bfd)
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)
@@ -7518,12 +8104,12 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
if (G.debug & G_DEBUG) {
char build_commit_datetime[32];
time_t temp_time = main->build_commit_timestamp;
- struct tm *tm = gmtime(&temp_time);
+ struct tm *tm = (temp_time) ? gmtime(&temp_time) : NULL;
if (LIKELY(tm)) {
strftime(build_commit_datetime, sizeof(build_commit_datetime), "%Y-%m-%d %H:%M", tm);
}
else {
- BLI_strncpy(build_commit_datetime, "date-unknown", sizeof(build_commit_datetime));
+ BLI_strncpy(build_commit_datetime, "unknown", sizeof(build_commit_datetime));
}
printf("read file %s\n Version %d sub %d date %s hash %s\n",
@@ -7589,6 +8175,7 @@ static void lib_link_all(FileData *fd, Main *main)
lib_link_movieclip(fd, main);
lib_link_mask(fd, main);
lib_link_linestyle(fd, main);
+ lib_link_gpencil(fd, main);
lib_link_mesh(fd, main); /* as last: tpage images with users at zero */
@@ -7630,7 +8217,7 @@ static BHead *read_userdef(BlendFileData *bfd, FileData *fd, BHead *bhead)
link_list(fd, &user->user_keymaps);
link_list(fd, &user->addons);
link_list(fd, &user->autoexec_paths);
-
+
for (keymap=user->user_keymaps.first; keymap; keymap=keymap->next) {
keymap->modal_items= NULL;
keymap->poll = NULL;
@@ -7686,6 +8273,24 @@ BlendFileData *blo_read_file_internal(FileData *fd, const char *filepath)
bfd->type = BLENFILETYPE_BLEND;
BLI_strncpy(bfd->main->name, filepath, sizeof(bfd->main->name));
+ if (G.background) {
+ /* We only read & store .blend thumbnail in background mode
+ * (because we cannot re-generate it, no OpenGL available).
+ */
+ const int *data = read_file_thumbnail(fd);
+
+ if (data) {
+ const size_t sz = BLEN_THUMB_MEMSIZE(data[0], data[1]);
+ bfd->main->blen_thumb = MEM_mallocN(sz, __func__);
+
+ BLI_assert((sz - sizeof(*bfd->main->blen_thumb)) ==
+ (BLEN_THUMB_MEMSIZE_FILE(data[0], data[1]) - (sizeof(*data) * 2)));
+ bfd->main->blen_thumb->width = data[0];
+ bfd->main->blen_thumb->height = data[1];
+ memcpy(bfd->main->blen_thumb->rect, &data[2], sz - sizeof(*bfd->main->blen_thumb));
+ }
+ }
+
while (bhead) {
switch (bhead->code) {
case DATA:
@@ -7736,10 +8341,10 @@ BlendFileData *blo_read_file_internal(FileData *fd, const char *filepath)
}
/* do before read_libraries, but skip undo case */
- if (fd->memfile==NULL)
+ if (fd->memfile == NULL) {
do_versions(fd, NULL, bfd->main);
-
- do_versions_userdef(fd, bfd);
+ do_versions_userdef(fd, bfd);
+ }
read_libraries(fd, &mainlist);
@@ -7752,6 +8357,8 @@ BlendFileData *blo_read_file_internal(FileData *fd, const char *filepath)
link_global(fd, bfd); /* as last */
+ fd->mainlist = NULL; /* Safety, this is local variable, shall not be used afterward. */
+
return bfd;
}
@@ -7836,9 +8443,48 @@ static BHead *find_bhead(FileData *fd, void *old)
return NULL;
}
-char *bhead_id_name(FileData *fd, BHead *bhead)
+static BHead *find_bhead_from_code_name(FileData *fd, const short idcode, const char *name)
+{
+#ifdef USE_GHASH_BHEAD
+
+ char idname_full[MAX_ID_NAME];
+
+ *((short *)idname_full) = idcode;
+ BLI_strncpy(idname_full + 2, name, sizeof(idname_full) - 2);
+
+ return BLI_ghash_lookup(fd->bhead_idname_hash, idname_full);
+
+#else
+ BHead *bhead;
+
+ for (bhead = blo_firstbhead(fd); bhead; bhead = blo_nextbhead(fd, bhead)) {
+ if (bhead->code == idcode) {
+ const char *idname_test = bhead_id_name(fd, bhead);
+ if (STREQ(idname_test + 2, name)) {
+ return bhead;
+ }
+ }
+ else if (bhead->code == ENDB) {
+ break;
+ }
+ }
+
+ return NULL;
+#endif
+}
+
+static BHead *find_bhead_from_idname(FileData *fd, const char *idname)
{
- return ((char *)(bhead+1)) + fd->id_name_offs;
+#ifdef USE_GHASH_BHEAD
+ return BLI_ghash_lookup(fd->bhead_idname_hash, idname);
+#else
+ return find_bhead_from_code_name(fd, GS(idname), idname + 2);
+#endif
+}
+
+const char *bhead_id_name(const FileData *fd, const BHead *bhead)
+{
+ return (const char *)POINTER_OFFSET(bhead, sizeof(*bhead) + fd->id_name_offs);
}
static ID *is_yet_read(FileData *fd, Main *mainvar, BHead *bhead)
@@ -7959,8 +8605,9 @@ static void expand_fmodifiers(FileData *fd, Main *mainvar, ListBase *list)
FMod_Python *data = (FMod_Python *)fcm->data;
expand_doit(fd, mainvar, data->script);
- }
+
break;
+ }
}
}
}
@@ -8694,6 +9341,12 @@ static void expand_linestyle(FileData *fd, Main *mainvar, FreestyleLineStyle *li
}
}
+static void expand_gpencil(FileData *fd, Main *mainvar, bGPdata *gpd)
+{
+ if (gpd->adt)
+ expand_animdata(fd, mainvar, gpd->adt);
+}
+
void BLO_main_expander(void (*expand_doit_func)(void *, Main *, void *))
{
expand_doit = expand_doit_func;
@@ -8788,6 +9441,9 @@ void BLO_expand_main(void *fdhandle, Main *mainvar)
case ID_LS:
expand_linestyle(fd, mainvar, (FreestyleLineStyle *)id);
break;
+ case ID_GD:
+ expand_gpencil(fd, mainvar, (bGPdata *)id);
+ break;
}
do_it = true;
@@ -8836,7 +9492,7 @@ static void give_base_to_objects(Main *mainvar, Scene *sce, Library *lib, const
do_it = true;
}
else if (idcode==ID_GR) {
- if (ob->id.us == 1 && is_link == false && ob->id.lib == lib) {
+ if ((is_link == false) && (ob->id.lib == lib)) {
if ((ob->flag & OB_FROMGROUP) && object_in_any_scene(mainvar, ob)==0) {
do_it = true;
}
@@ -8845,7 +9501,7 @@ static void give_base_to_objects(Main *mainvar, Scene *sce, Library *lib, const
else {
/* when appending, make sure any indirectly loaded objects
* get a base else they cant be accessed at all [#27437] */
- if (ob->id.us==1 && is_link == false && ob->id.lib == lib) {
+ if ((is_link == false) && (ob->id.lib == lib)) {
/* we may be appending from a scene where we already
* have a linked object which is not in any scene [#27616] */
if ((ob->id.flag & LIB_PRE_EXISTING)==0) {
@@ -8865,7 +9521,9 @@ static void give_base_to_objects(Main *mainvar, Scene *sce, Library *lib, const
base->lay = ob->lay;
base->object = ob;
base->flag = ob->flag;
- ob->id.us = 1;
+
+ CLAMP_MIN(ob->id.us, 0);
+ ob->id.us += 1;
ob->id.flag -= LIB_INDIRECT;
ob->id.flag |= LIB_EXTERN;
@@ -8903,7 +9561,6 @@ static void give_base_to_groups(Main *mainvar, Scene *scene)
/* assign the group */
ob->dup_group = group;
ob->transflag |= OB_DUPLIGROUP;
- rename_id(&ob->id, group->id.name + 2);
copy_v3_v3(ob->loc, scene->cursor);
}
}
@@ -8913,50 +9570,40 @@ static void give_base_to_groups(Main *mainvar, Scene *scene)
* but it may already have already been appended/linked */
static ID *append_named_part(Main *mainl, FileData *fd, const char *idname, const short idcode)
{
- BHead *bhead;
- ID *id = NULL;
- int found = 0;
+ BHead *bhead = find_bhead_from_code_name(fd, idcode, idname);
+ ID *id;
- for (bhead = blo_firstbhead(fd); bhead; bhead = blo_nextbhead(fd, bhead)) {
- if (bhead->code == idcode) {
- const char *idname_test= bhead_id_name(fd, bhead);
-
- if (strcmp(idname_test + 2, idname) == 0) {
- found = 1;
- id = is_yet_read(fd, mainl, bhead);
- if (id == NULL) {
- /* not read yet */
- read_libblock(fd, mainl, bhead, LIB_TESTEXT, &id);
-
- if (id) {
- /* sort by name in list */
- ListBase *lb = which_libbase(mainl, idcode);
- id_sort_by_name(lb, id);
- }
- }
- else {
- /* already linked */
- if (G.debug)
- printf("append: already linked\n");
- oldnewmap_insert(fd->libmap, bhead->old, id, bhead->code);
- if (id->flag & LIB_INDIRECT) {
- id->flag -= LIB_INDIRECT;
- id->flag |= LIB_EXTERN;
- }
- }
-
- break;
+ if (bhead) {
+ id = is_yet_read(fd, mainl, bhead);
+ if (id == NULL) {
+ /* not read yet */
+ read_libblock(fd, mainl, bhead, LIB_TESTEXT, &id);
+
+ if (id) {
+ /* sort by name in list */
+ ListBase *lb = which_libbase(mainl, idcode);
+ id_sort_by_name(lb, id);
}
}
- else if (bhead->code == ENDB) {
- break;
+ else {
+ /* already linked */
+ if (G.debug)
+ printf("append: already linked\n");
+ oldnewmap_insert(fd->libmap, bhead->old, id, bhead->code);
+ if (id->flag & LIB_INDIRECT) {
+ id->flag -= LIB_INDIRECT;
+ id->flag |= LIB_EXTERN;
+ }
}
}
+ else {
+ id = NULL;
+ }
/* if we found the id but the id is NULL, this is really bad */
- BLI_assert((found != 0) == (id != NULL));
+ BLI_assert((bhead != NULL) == (id != NULL));
- return (found) ? id : NULL;
+ return id;
}
/* simple reader for copy/paste buffers */
@@ -8996,10 +9643,10 @@ static ID *append_named_part_ex(const bContext *C, Main *mainl, FileData *fd, co
ob = (Object *)id;
- /* link at active layer (view3d->lay if in context, else scene->lay */
+ /* link at active layer (view3d if available in context, else scene one */
if ((flag & FILE_ACTIVELAY)) {
View3D *v3d = CTX_wm_view3d(C);
- ob->lay = v3d ? v3d->layact : scene->lay;
+ ob->lay = BKE_screen_view3d_layer_active(v3d, scene);
}
ob->mode = OB_MODE_OBJECT;
@@ -9037,22 +9684,13 @@ ID *BLO_library_append_named_part_ex(const bContext *C, Main *mainl, BlendHandle
static void append_id_part(FileData *fd, Main *mainvar, ID *id, ID **r_id)
{
- BHead *bhead;
-
- for (bhead = blo_firstbhead(fd); bhead; bhead = blo_nextbhead(fd, bhead)) {
- if (bhead->code == GS(id->name)) {
-
- if (strcmp(id->name, bhead_id_name(fd, bhead))==0) {
- id->flag &= ~LIB_READ;
- id->flag |= LIB_NEED_EXPAND;
-// printf("read lib block %s\n", id->name);
- read_libblock(fd, mainvar, bhead, id->flag, r_id);
-
- break;
- }
- }
- else if (bhead->code==ENDB)
- break;
+ BHead *bhead = find_bhead_from_idname(fd, id->name);
+
+ if (bhead) {
+ id->flag &= ~LIB_READ;
+ id->flag |= LIB_NEED_EXPAND;
+ // printf("read lib block %s\n", id->name);
+ read_libblock(fd, mainvar, bhead, id->flag, r_id);
}
}
@@ -9076,6 +9714,9 @@ static Main *library_append_begin(Main *mainvar, FileData **fd, const char *file
/* needed for do_version */
mainl->versionfile = (*fd)->fileversion;
read_file_version(*fd, mainl);
+#ifdef USE_GHASH_BHEAD
+ read_file_bhead_idname_map_create(*fd);
+#endif
return mainl;
}
@@ -9220,8 +9861,10 @@ static void read_libraries(FileData *basefd, ListBase *mainlist)
if (mainptr->curlib->packedfile) {
PackedFile *pf = mainptr->curlib->packedfile;
- blo_reportf_wrap(basefd->reports, RPT_INFO, TIP_("Read packed library: '%s'"),
- mainptr->curlib->name);
+ blo_reportf_wrap(
+ basefd->reports, RPT_INFO, TIP_("Read packed library: '%s', parent '%s'"),
+ mainptr->curlib->name,
+ library_parent_filepath(mainptr->curlib));
fd = blo_openblendermemory(pf->data, pf->size, basefd->reports);
@@ -9229,8 +9872,11 @@ static void read_libraries(FileData *basefd, ListBase *mainlist)
BLI_strncpy(fd->relabase, mainptr->curlib->filepath, sizeof(fd->relabase));
}
else {
- blo_reportf_wrap(basefd->reports, RPT_INFO, TIP_("Read library: '%s', '%s'"),
- mainptr->curlib->filepath, mainptr->curlib->name);
+ blo_reportf_wrap(
+ basefd->reports, RPT_INFO, TIP_("Read library: '%s', '%s', parent '%s'"),
+ mainptr->curlib->filepath,
+ mainptr->curlib->name,
+ library_parent_filepath(mainptr->curlib));
fd = blo_openblenderfile(mainptr->curlib->filepath, basefd->reports);
}
/* allow typing in a new lib path */
@@ -9277,6 +9923,10 @@ static void read_libraries(FileData *basefd, ListBase *mainlist)
/* subversion */
read_file_version(fd, mainptr);
+#ifdef USE_GHASH_BHEAD
+ read_file_bhead_idname_map_create(fd);
+#endif
+
}
else {
mainptr->curlib->filedata = NULL;
@@ -9301,10 +9951,13 @@ static void read_libraries(FileData *basefd, ListBase *mainlist)
append_id_part(fd, mainptr, id, &realid);
if (!realid) {
- 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);
+ blo_reportf_wrap(
+ fd->reports, RPT_WARNING,
+ TIP_("LIB ERROR: %s: '%s' missing from '%s', parent '%s'"),
+ BKE_idcode_to_name(GS(id->name)),
+ id->name + 2,
+ mainptr->curlib->filepath,
+ library_parent_filepath(mainptr->curlib));
}
change_idid_adr(mainlist, basefd, id, realid);
@@ -9333,9 +9986,13 @@ static void read_libraries(FileData *basefd, ListBase *mainlist)
idn = id->next;
if (id->flag & LIB_READ) {
BLI_remlink(lbarray[a], id);
- 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);
+ blo_reportf_wrap(
+ basefd->reports, RPT_WARNING,
+ TIP_("LIB ERROR: %s: '%s' unread lib block missing from '%s', parent '%s'"),
+ BKE_idcode_to_name(GS(id->name)),
+ id->name + 2,
+ mainptr->curlib->filepath,
+ library_parent_filepath(mainptr->curlib));
change_idid_adr(mainlist, basefd, id, NULL);
MEM_freeN(id);
diff --git a/source/blender/blenloader/intern/readfile.h b/source/blender/blenloader/intern/readfile.h
index d56f58d1b37..ed22daef9ec 100644
--- a/source/blender/blenloader/intern/readfile.h
+++ b/source/blender/blenloader/intern/readfile.h
@@ -38,12 +38,10 @@
struct OldNewMap;
struct MemFile;
-struct bheadsort;
struct ReportList;
struct Object;
struct PartEff;
struct View3D;
-struct bNodeTree;
struct Key;
typedef struct FileData {
@@ -88,10 +86,14 @@ typedef struct FileData {
struct OldNewMap *libmap;
struct OldNewMap *imamap;
struct OldNewMap *movieclipmap;
+ struct OldNewMap *soundmap;
struct OldNewMap *packedmap;
struct BHeadSort *bheadmap;
int tot_bheadmap;
+
+ /* see: USE_GHASH_BHEAD */
+ struct GHash *bhead_idname_hash;
ListBase *mainlist;
@@ -133,6 +135,8 @@ void blo_make_image_pointer_map(FileData *fd, Main *oldmain);
void blo_end_image_pointer_map(FileData *fd, Main *oldmain);
void blo_make_movieclip_pointer_map(FileData *fd, Main *oldmain);
void blo_end_movieclip_pointer_map(FileData *fd, Main *oldmain);
+void blo_make_sound_pointer_map(FileData *fd, Main *oldmain);
+void blo_end_sound_pointer_map(FileData *fd, Main *oldmain);
void blo_make_packed_pointer_map(FileData *fd, Main *oldmain);
void blo_end_packed_pointer_map(FileData *fd, Main *oldmain);
void blo_add_library_pointer_map(ListBase *mainlist, FileData *fd);
@@ -143,7 +147,7 @@ BHead *blo_firstbhead(FileData *fd);
BHead *blo_nextbhead(FileData *fd, BHead *thisblock);
BHead *blo_prevbhead(FileData *fd, BHead *thisblock);
-char *bhead_id_name(FileData *fd, BHead *bhead);
+const char *bhead_id_name(const FileData *fd, const BHead *bhead);
/* do versions stuff */
diff --git a/source/blender/blenloader/intern/runtime.c b/source/blender/blenloader/intern/runtime.c
index d6fd2f92443..ec496e1c866 100644
--- a/source/blender/blenloader/intern/runtime.c
+++ b/source/blender/blenloader/intern/runtime.c
@@ -51,7 +51,6 @@
#include "BLO_readfile.h"
#include "BLO_runtime.h"
-#include "BKE_blender.h"
#include "BKE_report.h"
/* Runtime reading */
diff --git a/source/blender/blenloader/intern/undofile.c b/source/blender/blenloader/intern/undofile.c
index 12f4a295a34..d0dc9a88cc0 100644
--- a/source/blender/blenloader/intern/undofile.c
+++ b/source/blender/blenloader/intern/undofile.c
@@ -40,14 +40,13 @@
#include "DNA_listBase.h"
#include "BLI_blenlib.h"
-#include "BLI_linklist.h"
#include "BLO_undofile.h"
/* **************** support for memory-write, for undo buffers *************** */
/* not memfile itself */
-void BLO_free_memfile(MemFile *memfile)
+void BLO_memfile_free(MemFile *memfile)
{
MemFileChunk *chunk;
@@ -61,7 +60,7 @@ void BLO_free_memfile(MemFile *memfile)
/* to keep list of memfiles consistent, 'first' is always first in list */
/* result is that 'first' is being freed */
-void BLO_merge_memfile(MemFile *first, MemFile *second)
+void BLO_memfile_merge(MemFile *first, MemFile *second)
{
MemFileChunk *fc, *sc;
@@ -78,7 +77,7 @@ void BLO_merge_memfile(MemFile *first, MemFile *second)
if (sc) sc = sc->next;
}
- BLO_free_memfile(first);
+ BLO_memfile_free(first);
}
static int my_memcmp(const int *mem1, const int *mem2, const int len)
@@ -95,7 +94,7 @@ static int my_memcmp(const int *mem1, const int *mem2, const int len)
return 0;
}
-void add_memfilechunk(MemFile *compare, MemFile *current, const char *buf, unsigned int size)
+void memfile_chunk_add(MemFile *compare, MemFile *current, const char *buf, unsigned int size)
{
static MemFileChunk *compchunk = NULL;
MemFileChunk *curchunk;
diff --git a/source/blender/blenloader/intern/versioning_250.c b/source/blender/blenloader/intern/versioning_250.c
index 06d871c8db0..43ebab7856c 100644
--- a/source/blender/blenloader/intern/versioning_250.c
+++ b/source/blender/blenloader/intern/versioning_250.c
@@ -25,11 +25,10 @@
* \ingroup blenloader
*/
-#include "zlib.h"
-
#ifndef WIN32
# include <unistd.h> /* for read close */
#else
+# include <zlib.h> /* odd include order-issue */
# include <io.h> // for open close read
# include "winsock2.h"
# include "BLI_winstuff.h"
@@ -89,18 +88,10 @@
#include "NOD_socket.h"
-//XXX #include "BIF_butspace.h" // badlevel, for do_versions, patching event codes
-//XXX #include "BIF_filelist.h" // badlevel too, where to move this? - elubie
-//XXX #include "BIF_previewrender.h" // bedlelvel, for struct RenderInfo
#include "BLO_readfile.h"
-#include "BLO_undofile.h"
-
-#include "RE_engine.h"
#include "readfile.h"
-#include "PIL_time.h"
-
#include <errno.h>
/* 2.50 patch */
@@ -332,7 +323,7 @@ static void area_add_window_regions(ScrArea *sa, SpaceLink *sl, ListBase *lb)
SpaceNla *snla = (SpaceNla *)sl;
memcpy(&ar->v2d, &snla->v2d, sizeof(View2D));
- ar->v2d.tot.ymin = (float)(-sa->winy)/3.0f;
+ ar->v2d.tot.ymin = (float)(-sa->winy) / 3.0f;
ar->v2d.tot.ymax = 0.0f;
ar->v2d.scroll |= (V2D_SCROLL_BOTTOM|V2D_SCROLL_SCALE_HORIZONTAL);
@@ -347,8 +338,8 @@ static void area_add_window_regions(ScrArea *sa, SpaceLink *sl, ListBase *lb)
/* we totally reinit the view for the Action Editor, as some old instances had some weird cruft set */
ar->v2d.tot.xmin = -20.0f;
- ar->v2d.tot.ymin = (float)(-sa->winy)/3.0f;
- ar->v2d.tot.xmax = (float)((sa->winx > 120)? (sa->winx) : 120);
+ ar->v2d.tot.ymin = (float)(-sa->winy) / 3.0f;
+ ar->v2d.tot.xmax = (float)((sa->winx > 120) ? (sa->winx) : 120);
ar->v2d.tot.ymax = 0.0f;
ar->v2d.cur = ar->v2d.tot;
@@ -775,7 +766,7 @@ void blo_do_versions_250(FileData *fd, Library *lib, Main *main)
bSoundActuator *sAct = (bSoundActuator*) act->data;
if (sAct->sound) {
sound = blo_do_versions_newlibadr(fd, lib, sAct->sound);
- sAct->flag = sound->flags & SOUND_FLAGS_3D ? ACT_SND_3D_SOUND : 0;
+ sAct->flag = (sound->flags & SOUND_FLAGS_3D) ? ACT_SND_3D_SOUND : 0;
sAct->pitch = sound->pitch;
sAct->volume = sound->volume;
sAct->sound3D.reference_distance = sound->distance;
@@ -804,14 +795,18 @@ void blo_do_versions_250(FileData *fd, Library *lib, Main *main)
char str[FILE_MAX];
BLI_join_dirfile(str, sizeof(str), seq->strip->dir, seq->strip->stripdata->name);
BLI_path_abs(str, main->name);
- seq->sound = sound_new_file(main, str);
+ seq->sound = BKE_sound_new_file(main, str);
}
+#define SEQ_USE_PROXY_CUSTOM_DIR (1 << 19)
+#define SEQ_USE_PROXY_CUSTOM_FILE (1 << 21)
/* don't know, if anybody used that this way, but just in case, upgrade to new way... */
if ((seq->flag & SEQ_USE_PROXY_CUSTOM_FILE) &&
!(seq->flag & SEQ_USE_PROXY_CUSTOM_DIR))
{
BLI_snprintf(seq->strip->proxy->dir, FILE_MAXDIR, "%s/BL_proxy", seq->strip->dir);
}
+#undef SEQ_USE_PROXY_CUSTOM_DIR
+#undef SEQ_USE_PROXY_CUSTOM_FILE
}
SEQ_END
}
@@ -1594,7 +1589,7 @@ void blo_do_versions_250(FileData *fd, Library *lib, Main *main)
bAnimVizSettings *avs = &ob->pose->avs;
/* ghosting settings ---------------- */
- /* ranges */
+ /* ranges */
avs->ghost_bc = avs->ghost_ac = arm->ghostep;
avs->ghost_sf = arm->ghostsf;
@@ -1604,19 +1599,19 @@ void blo_do_versions_250(FileData *fd, Library *lib, Main *main)
avs->ghost_ef = 100;
}
- /* type */
+ /* type */
if (arm->ghostep == 0)
avs->ghost_type = GHOST_TYPE_NONE;
else
avs->ghost_type = arm->ghosttype + 1;
- /* stepsize */
+ /* stepsize */
avs->ghost_step = arm->ghostsize;
if (avs->ghost_step == 0)
avs->ghost_step = 1;
/* path settings --------------------- */
- /* ranges */
+ /* ranges */
avs->path_bc = arm->pathbc;
avs->path_ac = arm->pathac;
if ((avs->path_bc == avs->path_ac) && (avs->path_bc == 0))
@@ -1629,7 +1624,7 @@ void blo_do_versions_250(FileData *fd, Library *lib, Main *main)
avs->path_ef = 250;
}
- /* flags */
+ /* flags */
if (arm->pathflag & ARM_PATH_FNUMS)
avs->path_viewflag |= MOTIONPATH_VIEW_FNUMS;
if (arm->pathflag & ARM_PATH_KFRAS)
@@ -1637,15 +1632,15 @@ void blo_do_versions_250(FileData *fd, Library *lib, Main *main)
if (arm->pathflag & ARM_PATH_KFNOS)
avs->path_viewflag |= MOTIONPATH_VIEW_KFNOS;
- /* bake flags */
+ /* bake flags */
if (arm->pathflag & ARM_PATH_HEADS)
avs->path_bakeflag |= MOTIONPATH_BAKE_HEADS;
- /* type */
+ /* type */
if (arm->pathflag & ARM_PATH_ACFRA)
avs->path_type = MOTIONPATH_TYPE_ACFRA;
- /* stepsize */
+ /* stepsize */
avs->path_step = arm->pathsize;
if (avs->path_step == 0)
avs->path_step = 1;
@@ -1657,8 +1652,8 @@ void blo_do_versions_250(FileData *fd, Library *lib, Main *main)
/* brush texture changes */
for (brush = main->brush.first; brush; brush = brush->id.next) {
- default_mtex(&brush->mtex);
- default_mtex(&brush->mask_mtex);
+ BKE_texture_mtex_default(&brush->mtex);
+ BKE_texture_mtex_default(&brush->mask_mtex);
}
for (ma = main->mat.first; ma; ma = ma->id.next) {
diff --git a/source/blender/blenloader/intern/versioning_260.c b/source/blender/blenloader/intern/versioning_260.c
index 7c6b6ec7249..25074effaab 100644
--- a/source/blender/blenloader/intern/versioning_260.c
+++ b/source/blender/blenloader/intern/versioning_260.c
@@ -25,8 +25,6 @@
* \ingroup blenloader
*/
-#include "zlib.h"
-
#include "BLI_utildefines.h"
/* allow readfile to use deprecated functionality */
@@ -59,7 +57,7 @@
#include "BLI_blenlib.h"
#include "BLI_math.h"
-#include "BLF_translation.h"
+#include "BLT_translation.h"
#include "BKE_anim.h"
#include "BKE_image.h"
@@ -277,7 +275,7 @@ static void do_versions_nodetree_multi_file_output_format_2_62_1(Scene *sce, bNo
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 */
+ /* XXX later do_versions copies path from socket name, need to set this explicitly */
BLI_strncpy(sock->name, sockpath, sizeof(sock->name));
if (old_image->link) {
old_image->link->tosock = sock;
@@ -286,7 +284,7 @@ static void do_versions_nodetree_multi_file_output_format_2_62_1(Scene *sce, bNo
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 */
+ /* XXX later do_versions copies path from socket name, need to set this explicitly */
BLI_strncpy(sock->name, sockpath, sizeof(sock->name));
if (old_z->link) {
old_z->link->tosock = sock;
@@ -295,7 +293,7 @@ static void do_versions_nodetree_multi_file_output_format_2_62_1(Scene *sce, bNo
}
else {
sock = ntreeCompositOutputFileAddSocket(ntree, node, filename, &nimf->format);
- /* XXX later do_versions copies path from socket name, need to set this explicitely */
+ /* XXX later do_versions copies path from socket name, need to set this explicitly */
BLI_strncpy(sock->name, filename, sizeof(sock->name));
if (old_image->link) {
old_image->link->tosock = sock;
@@ -847,7 +845,7 @@ void blo_do_versions_260(FileData *fd, Library *UNUSED(lib), Main *main)
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);
+ copy_vn_fl(ob->dscale, 3, 1.0f);
}
}
}
@@ -1885,7 +1883,7 @@ void blo_do_versions_260(FileData *fd, Library *UNUSED(lib), Main *main)
SEQ_END
if (scene->r.bake_samples == 0)
- scene->r.bake_samples = 256;
+ scene->r.bake_samples = 256;
if (scene->world) {
World *world = blo_do_versions_newlibadr(fd, scene->id.lib, scene->world);
@@ -2098,7 +2096,7 @@ void blo_do_versions_260(FileData *fd, Library *UNUSED(lib), Main *main)
if (!MAIN_VERSION_ATLEAST(main, 266, 4)) {
Brush *brush;
for (brush = main->brush.first; brush; brush = brush->id.next) {
- default_mtex(&brush->mask_mtex);
+ BKE_texture_mtex_default(&brush->mask_mtex);
if (brush->ob_mode & OB_MODE_TEXTURE_PAINT) {
brush->spacing /= 2;
diff --git a/source/blender/blenloader/intern/versioning_270.c b/source/blender/blenloader/intern/versioning_270.c
index 67d51ab0493..1f4aa3c9f3c 100644
--- a/source/blender/blenloader/intern/versioning_270.c
+++ b/source/blender/blenloader/intern/versioning_270.c
@@ -35,33 +35,40 @@
#define DNA_DEPRECATED_ALLOW
#include "DNA_brush_types.h"
+#include "DNA_camera_types.h"
#include "DNA_cloth_types.h"
#include "DNA_constraint_types.h"
#include "DNA_sdna_types.h"
+#include "DNA_sequence_types.h"
#include "DNA_space_types.h"
#include "DNA_screen_types.h"
+#include "DNA_object_force.h"
#include "DNA_object_types.h"
#include "DNA_mesh_types.h"
#include "DNA_modifier_types.h"
#include "DNA_particle_types.h"
#include "DNA_linestyle_types.h"
#include "DNA_actuator_types.h"
+#include "DNA_view3d_types.h"
#include "DNA_genfile.h"
-#include "BLI_blenlib.h"
-#include "BLI_math.h"
-
#include "BKE_main.h"
+#include "BKE_modifier.h"
#include "BKE_node.h"
+#include "BKE_scene.h"
+#include "BKE_sequencer.h"
+#include "BKE_screen.h"
#include "BLI_math.h"
+#include "BLI_listbase.h"
#include "BLI_string.h"
#include "BLO_readfile.h"
#include "readfile.h"
+#include "MEM_guardedalloc.h"
static void do_version_constraints_radians_degrees_270_1(ListBase *lb)
{
@@ -114,6 +121,19 @@ static void do_version_constraints_radians_degrees_270_5(ListBase *lb)
}
}
+static void do_version_constraints_stretch_to_limits(ListBase *lb)
+{
+ bConstraint *con;
+
+ for (con = lb->first; con; con = con->next) {
+ if (con->type == CONSTRAINT_TYPE_STRETCHTO) {
+ bStretchToConstraint *data = (bStretchToConstraint *)con->data;
+ data->bulge_min = 1.0f;
+ data->bulge_max = 1.0f;
+ }
+ }
+}
+
void blo_do_versions_270(FileData *fd, Library *UNUSED(lib), Main *main)
{
if (!MAIN_VERSION_ATLEAST(main, 270, 0)) {
@@ -297,7 +317,7 @@ void blo_do_versions_270(FileData *fd, Library *UNUSED(lib), Main *main)
{
Scene *scene;
for (scene = main->scene.first; scene; scene = scene->id.next) {
- int num_layers = BLI_countlist(&scene->r.layers);
+ int num_layers = BLI_listbase_count(&scene->r.layers);
scene->r.actlay = min_ff(scene->r.actlay, num_layers - 1);
}
}
@@ -350,6 +370,20 @@ void blo_do_versions_270(FileData *fd, Library *UNUSED(lib), Main *main)
for (br = main->brush.first; br; br = br->id.next) {
br->fill_threshold = 0.2f;
}
+
+ if (!DNA_struct_elem_find(fd->filesdna, "BevelModifierData", "int", "mat")) {
+ 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_Bevel) {
+ BevelModifierData *bmd = (BevelModifierData *)md;
+ bmd->mat = -1;
+ }
+ }
+ }
+ }
}
if (!MAIN_VERSION_ATLEAST(main, 271, 6)) {
@@ -376,4 +410,462 @@ void blo_do_versions_270(FileData *fd, Library *UNUSED(lib), Main *main)
}
}
}
+
+ if (!MAIN_VERSION_ATLEAST(main, 272, 1)) {
+ Brush *br;
+ for (br = main->brush.first; br; br = br->id.next) {
+ if ((br->ob_mode & OB_MODE_SCULPT) && ELEM(br->sculpt_tool, SCULPT_TOOL_GRAB, SCULPT_TOOL_SNAKE_HOOK))
+ br->alpha = 1.0f;
+ }
+ }
+
+ if (!MAIN_VERSION_ATLEAST(main, 272, 2)) {
+ if (!DNA_struct_elem_find(fd->filesdna, "Image", "float", "gen_color")) {
+ Image *image;
+ for (image = main->image.first; image != NULL; image = image->id.next) {
+ image->gen_color[3] = 1.0f;
+ }
+ }
+
+ if (!DNA_struct_elem_find(fd->filesdna, "bStretchToConstraint", "float", "bulge_min")) {
+ Object *ob;
+
+ /* Update Transform constraint (again :|). */
+ for (ob = main->object.first; ob; ob = ob->id.next) {
+ do_version_constraints_stretch_to_limits(&ob->constraints);
+
+ if (ob->pose) {
+ /* Bones constraints! */
+ bPoseChannel *pchan;
+ for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
+ do_version_constraints_stretch_to_limits(&pchan->constraints);
+ }
+ }
+ }
+ }
+ }
+
+ if (!MAIN_VERSION_ATLEAST(main, 273, 1)) {
+#define BRUSH_RAKE (1 << 7)
+#define BRUSH_RANDOM_ROTATION (1 << 25)
+
+ Brush *br;
+
+ for (br = main->brush.first; br; br = br->id.next) {
+ if (br->flag & BRUSH_RAKE) {
+ br->mtex.brush_angle_mode |= MTEX_ANGLE_RAKE;
+ br->mask_mtex.brush_angle_mode |= MTEX_ANGLE_RAKE;
+ }
+ else if (br->flag & BRUSH_RANDOM_ROTATION) {
+ br->mtex.brush_angle_mode |= MTEX_ANGLE_RANDOM;
+ br->mask_mtex.brush_angle_mode |= MTEX_ANGLE_RANDOM;
+ }
+ br->mtex.random_angle = 2.0 * M_PI;
+ br->mask_mtex.random_angle = 2.0 * M_PI;
+ }
+ }
+
+#undef BRUSH_RAKE
+#undef BRUSH_RANDOM_ROTATION
+
+ /* Customizable Safe Areas */
+ if (!MAIN_VERSION_ATLEAST(main, 273, 2)) {
+ if (!DNA_struct_elem_find(fd->filesdna, "Scene", "DisplaySafeAreas", "safe_areas")) {
+ Scene *scene;
+
+ for (scene = main->scene.first; scene; scene = scene->id.next) {
+ copy_v2_fl2(scene->safe_areas.title, 3.5f / 100.0f, 3.5f / 100.0f);
+ copy_v2_fl2(scene->safe_areas.action, 10.0f / 100.0f, 5.0f / 100.0f);
+ copy_v2_fl2(scene->safe_areas.title_center, 17.5f / 100.0f, 5.0f / 100.0f);
+ copy_v2_fl2(scene->safe_areas.action_center, 15.0f / 100.0f, 5.0f / 100.0f);
+ }
+ }
+ }
+
+ if (!MAIN_VERSION_ATLEAST(main, 273, 3)) {
+ ParticleSettings *part;
+ for (part = main->particle.first; part; part = part->id.next) {
+ if (part->clumpcurve)
+ part->child_flag |= PART_CHILD_USE_CLUMP_CURVE;
+ if (part->roughcurve)
+ part->child_flag |= PART_CHILD_USE_ROUGH_CURVE;
+ }
+ }
+
+ if (!MAIN_VERSION_ATLEAST(main, 273, 6)) {
+ if (!DNA_struct_elem_find(fd->filesdna, "ClothSimSettings", "float", "bending_damping")) {
+ 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_Cloth) {
+ ClothModifierData *clmd = (ClothModifierData *)md;
+ clmd->sim_parms->bending_damping = 0.5f;
+ }
+ else if (md->type == eModifierType_ParticleSystem) {
+ ParticleSystemModifierData *pmd = (ParticleSystemModifierData *)md;
+ if (pmd->psys->clmd) {
+ pmd->psys->clmd->sim_parms->bending_damping = 0.5f;
+ }
+ }
+ }
+ }
+ }
+
+ if (!DNA_struct_elem_find(fd->filesdna, "ParticleSettings", "float", "clump_noise_size")) {
+ ParticleSettings *part;
+ for (part = main->particle.first; part; part = part->id.next) {
+ part->clump_noise_size = 1.0f;
+ }
+ }
+
+ if (!DNA_struct_elem_find(fd->filesdna, "ParticleSettings", "int", "kink_extra_steps")) {
+ ParticleSettings *part;
+ for (part = main->particle.first; part; part = part->id.next) {
+ part->kink_extra_steps = 4;
+ }
+ }
+
+ if (!DNA_struct_elem_find(fd->filesdna, "MTex", "float", "kinkampfac")) {
+ ParticleSettings *part;
+ for (part = main->particle.first; part; part = part->id.next) {
+ int a;
+ for (a = 0; a < MAX_MTEX; a++) {
+ MTex *mtex = part->mtex[a];
+ if (mtex) {
+ mtex->kinkampfac = 1.0f;
+ }
+ }
+ }
+ }
+
+ if (!DNA_struct_elem_find(fd->filesdna, "HookModifierData", "char", "flag")) {
+ 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_Hook) {
+ HookModifierData *hmd = (HookModifierData *)md;
+ hmd->falloff_type = eHook_Falloff_InvSquare;
+ }
+ }
+ }
+ }
+
+ if (!DNA_struct_elem_find(fd->filesdna, "NodePlaneTrackDeformData", "char", "flag")) {
+ FOREACH_NODETREE(main, ntree, id) {
+ if (ntree->type == NTREE_COMPOSIT) {
+ bNode *node;
+ for (node = ntree->nodes.first; node; node = node->next) {
+ if (ELEM(node->type, CMP_NODE_PLANETRACKDEFORM)) {
+ NodePlaneTrackDeformData *data = node->storage;
+ data->flag = 0;
+ data->motion_blur_samples = 16;
+ data->motion_blur_shutter = 0.5f;
+ }
+ }
+ }
+ }
+ FOREACH_NODETREE_END
+ }
+
+ if (!DNA_struct_elem_find(fd->filesdna, "Camera", "GPUDOFSettings", "gpu_dof")) {
+ Camera *ca;
+ for (ca = main->camera.first; ca; ca = ca->id.next) {
+ ca->gpu_dof.fstop = 128.0f;
+ ca->gpu_dof.focal_length = 1.0f;
+ ca->gpu_dof.focus_distance = 1.0f;
+ ca->gpu_dof.sensor = 1.0f;
+ }
+ }
+ }
+
+ if (!MAIN_VERSION_ATLEAST(main, 273, 7)) {
+ bScreen *scr;
+ ScrArea *sa;
+ SpaceLink *sl;
+ ARegion *ar;
+
+ for (scr = main->screen.first; scr; scr = scr->id.next) {
+ /* Remove old deprecated region from filebrowsers */
+ for (sa = scr->areabase.first; sa; sa = sa->next) {
+ for (sl = sa->spacedata.first; sl; sl = sl->next) {
+ if (sl->spacetype == SPACE_FILE) {
+ for (ar = sl->regionbase.first; ar; ar = ar->next) {
+ if (ar->regiontype == RGN_TYPE_CHANNELS) {
+ break;
+ }
+ }
+
+ if (ar) {
+ /* Free old deprecated 'channel' region... */
+ BKE_area_region_free(NULL, ar);
+ BLI_freelinkN(&sl->regionbase, ar);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (!MAIN_VERSION_ATLEAST(main, 273, 8)) {
+ Object *ob;
+ for (ob = main->object.first; ob != NULL; ob = ob->id.next) {
+ ModifierData *md;
+ for (md = ob->modifiers.last; md != NULL; md = md->prev) {
+ if (modifier_unique_name(&ob->modifiers, md)) {
+ printf("Warning: Object '%s' had several modifiers with the "
+ "same name, renamed one of them to '%s'.\n",
+ ob->id.name + 2, md->name);
+ }
+ }
+ }
+ }
+
+ if (!MAIN_VERSION_ATLEAST(main, 273, 9)) {
+ bScreen *scr;
+ ScrArea *sa;
+ SpaceLink *sl;
+ ARegion *ar;
+
+ /* Make sure sequencer preview area limits zoom */
+ for (scr = main->screen.first; scr; scr = scr->id.next) {
+ for (sa = scr->areabase.first; sa; sa = sa->next) {
+ for (sl = sa->spacedata.first; sl; sl = sl->next) {
+ if (sl->spacetype == SPACE_SEQ) {
+ for (ar = sl->regionbase.first; ar; ar = ar->next) {
+ if (ar->regiontype == RGN_TYPE_PREVIEW) {
+ ar->v2d.keepzoom |= V2D_LIMITZOOM;
+ ar->v2d.minzoom = 0.001f;
+ ar->v2d.maxzoom = 1000.0f;
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (!MAIN_VERSION_ATLEAST(main, 274, 1)) {
+ /* particle systems need to be forced to redistribute for jitter mode fix */
+ {
+ Object *ob;
+ ParticleSystem *psys;
+ for (ob = main->object.first; ob; ob = ob->id.next) {
+ for (psys = ob->particlesystem.first; psys; psys = psys->next) {
+ if ((psys->pointcache->flag & PTCACHE_BAKED) == 0) {
+ psys->recalc |= PSYS_RECALC_RESET;
+ }
+ }
+ }
+ }
+
+ /* hysteresis setted to 10% but not actived */
+ if (!DNA_struct_elem_find(fd->filesdna, "LodLevel", "int", "obhysteresis")) {
+ Object *ob;
+ for (ob = main->object.first; ob; ob = ob->id.next) {
+ LodLevel *level;
+ for (level = ob->lodlevels.first; level; level = level->next) {
+ level->obhysteresis = 10;
+ }
+ }
+ }
+
+ if (!DNA_struct_elem_find(fd->filesdna, "GameData", "int", "scehysteresis")) {
+ Scene *scene;
+ for (scene = main->scene.first; scene; scene = scene->id.next) {
+ scene->gm.scehysteresis = 10;
+ }
+ }
+ }
+
+ if (!MAIN_VERSION_ATLEAST(main, 274, 2)) {
+ FOREACH_NODETREE(main, ntree, id) {
+ bNode *node;
+ bNodeSocket *sock;
+
+ for (node = ntree->nodes.first; node; node = node->next) {
+ if (node->type == SH_NODE_MATERIAL) {
+ for (sock = node->inputs.first; sock; sock = sock->next) {
+ if (STREQ(sock->name, "Refl")) {
+ BLI_strncpy(sock->name, "DiffuseIntensity", sizeof(sock->name));
+ }
+ }
+ }
+ else if (node->type == SH_NODE_MATERIAL_EXT) {
+ for (sock = node->outputs.first; sock; sock = sock->next) {
+ if (STREQ(sock->name, "Refl")) {
+ BLI_strncpy(sock->name, "DiffuseIntensity", sizeof(sock->name));
+ }
+ else if (STREQ(sock->name, "Ray Mirror")) {
+ BLI_strncpy(sock->name, "Reflectivity", sizeof(sock->name));
+ }
+ }
+ }
+ }
+ } FOREACH_NODETREE_END
+ }
+
+ if (!MAIN_VERSION_ATLEAST(main, 274, 4)) {
+ SceneRenderView *srv;
+ wmWindowManager *wm;
+ bScreen *screen;
+ wmWindow *win;
+ Scene *scene;
+ Camera *cam;
+ Image *ima;
+
+ for (scene = main->scene.first; scene; scene = scene->id.next) {
+ Sequence *seq;
+
+ BKE_scene_add_render_view(scene, STEREO_LEFT_NAME);
+ srv = scene->r.views.first;
+ BLI_strncpy(srv->suffix, STEREO_LEFT_SUFFIX, sizeof(srv->suffix));
+
+ BKE_scene_add_render_view(scene, STEREO_RIGHT_NAME);
+ srv = scene->r.views.last;
+ BLI_strncpy(srv->suffix, STEREO_RIGHT_SUFFIX, sizeof(srv->suffix));
+
+ SEQ_BEGIN (scene->ed, seq)
+ {
+ seq->stereo3d_format = MEM_callocN(sizeof(Stereo3dFormat), "Stereo Display 3d Format");
+
+#define SEQ_USE_PROXY_CUSTOM_DIR (1 << 19)
+#define SEQ_USE_PROXY_CUSTOM_FILE (1 << 21)
+ if (seq->strip && seq->strip->proxy && !seq->strip->proxy->storage) {
+ if (seq->flag & SEQ_USE_PROXY_CUSTOM_DIR)
+ seq->strip->proxy->storage = SEQ_STORAGE_PROXY_CUSTOM_DIR;
+ if (seq->flag & SEQ_USE_PROXY_CUSTOM_FILE)
+ seq->strip->proxy->storage = SEQ_STORAGE_PROXY_CUSTOM_FILE;
+ }
+#undef SEQ_USE_PROXY_CUSTOM_DIR
+#undef SEQ_USE_PROXY_CUSTOM_FILE
+
+ }
+ SEQ_END
+ }
+
+ 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) {
+ switch (sl->spacetype) {
+ case SPACE_VIEW3D:
+ {
+ View3D *v3d = (View3D *)sl;
+ v3d->stereo3d_camera = STEREO_3D_ID;
+ v3d->stereo3d_flag |= V3D_S3D_DISPPLANE;
+ v3d->stereo3d_convergence_alpha = 0.15f;
+ v3d->stereo3d_volume_alpha = 0.05f;
+ break;
+ }
+ case SPACE_IMAGE:
+ {
+ SpaceImage *sima = (SpaceImage *) sl;
+ sima->iuser.flag |= IMA_SHOW_STEREO;
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ for (cam = main->camera.first; cam; cam = cam->id.next) {
+ cam->stereo.interocular_distance = 0.065f;
+ cam->stereo.convergence_distance = 30.0f * 0.065f;
+ }
+
+ for (ima = main->image.first; ima; ima = ima->id.next) {
+ ima->stereo3d_format = MEM_callocN(sizeof(Stereo3dFormat), "Image Stereo 3d Format");
+
+ if (ima->packedfile) {
+ ImagePackedFile *imapf = MEM_mallocN(sizeof(ImagePackedFile), "Image Packed File");
+ BLI_addtail(&ima->packedfiles, imapf);
+
+ imapf->packedfile = ima->packedfile;
+ BLI_strncpy(imapf->filepath, ima->name, FILE_MAX);
+ ima->packedfile = NULL;
+ }
+ }
+
+ for (wm = main->wm.first; wm; wm = wm->id.next) {
+ for (win = wm->windows.first; win; win = win->next) {
+ win->stereo3d_format = MEM_callocN(sizeof(Stereo3dFormat), "Stereo Display 3d Format");
+ }
+ }
+ }
+
+ if (!MAIN_VERSION_ATLEAST(main, 274, 6)) {
+ bScreen *screen;
+
+ if (!DNA_struct_elem_find(fd->filesdna, "FileSelectParams", "int", "thumbnail_size")) {
+ 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_FILE) {
+ SpaceFile *sfile = (SpaceFile *)sl;
+
+ if (sfile->params) {
+ sfile->params->thumbnail_size = 128;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (!DNA_struct_elem_find(fd->filesdna, "RenderData", "short", "simplify_subsurf_render")) {
+ Scene *scene;
+ for (scene = main->scene.first; scene != NULL; scene = scene->id.next) {
+ scene->r.simplify_subsurf_render = scene->r.simplify_subsurf;
+ scene->r.simplify_particles_render = scene->r.simplify_particles;
+ }
+ }
+
+ if (!DNA_struct_elem_find(fd->filesdna, "DecimateModifierData", "float", "defgrp_factor")) {
+ 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_Decimate) {
+ DecimateModifierData *dmd = (DecimateModifierData *)md;
+ dmd->defgrp_factor = 1.0f;
+ }
+ }
+ }
+ }
+ }
+
+ if (!MAIN_VERSION_ATLEAST(main, 275, 3)) {
+ Brush *br;
+#define BRUSH_TORUS (1 << 1)
+ for (br = main->brush.first; br; br = br->id.next) {
+ br->flag &= ~BRUSH_TORUS;
+ }
+#undef BRUSH_TORUS
+ }
+
+ if (!MAIN_VERSION_ATLEAST(main, 276, 2)) {
+ if (!DNA_struct_elem_find(fd->filesdna, "bPoseChannel", "float", "custom_scale")) {
+ Object *ob;
+
+ for (ob = main->object.first; ob; ob = ob->id.next) {
+ if (ob->pose) {
+ bPoseChannel *pchan;
+ for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
+ pchan->custom_scale = 1.0f;
+ }
+ }
+ }
+ }
+ }
}
diff --git a/source/blender/blenloader/intern/versioning_defaults.c b/source/blender/blenloader/intern/versioning_defaults.c
index 217d1f0821f..01af11e78d1 100644
--- a/source/blender/blenloader/intern/versioning_defaults.c
+++ b/source/blender/blenloader/intern/versioning_defaults.c
@@ -92,6 +92,9 @@ void BLO_update_defaults_startup_blend(Main *bmain)
sculpt->detail_size = 12;
}
}
+
+ scene->gm.lodflag |= SCE_LOD_USE_HYST;
+ scene->gm.scehysteresis = 10;
}
for (linestyle = bmain->linestyle.first; linestyle; linestyle = linestyle->id.next) {
@@ -99,6 +102,7 @@ void BLO_update_defaults_startup_blend(Main *bmain)
linestyle->sort_key = LS_SORT_KEY_DISTANCE_FROM_CAMERA;
linestyle->integration_type = LS_INTEGRATION_MEAN;
linestyle->texstep = 1.0;
+ linestyle->chain_count = 10;
}
{
@@ -117,9 +121,16 @@ void BLO_update_defaults_startup_blend(Main *bmain)
}
}
- /* Remove all stored panels, we want to use defaults (order, open/closed) as defined by UI code here! */
for (ar = area->regionbase.first; ar; ar = ar->next) {
+ /* Remove all stored panels, we want to use defaults (order, open/closed) as defined by UI code here! */
BLI_freelistN(&ar->panels);
+
+ /* simple fix for 3d view properties scrollbar being not set to top */
+ if (ar->regiontype == RGN_TYPE_UI) {
+ float offset = ar->v2d.tot.ymax - ar->v2d.cur.ymax;
+ ar->v2d.cur.ymax += offset;
+ ar->v2d.cur.ymin += offset;
+ }
}
}
}
@@ -137,15 +148,37 @@ void BLO_update_defaults_startup_blend(Main *bmain)
{
Brush *br;
- br = BKE_brush_add(bmain, "Fill");
- br->imagepaint_tool = PAINT_TOOL_FILL;
- br->ob_mode = OB_MODE_TEXTURE_PAINT;
+
+ br = (Brush *)BKE_libblock_find_name_ex(bmain, ID_BR, "Fill");
+ if (!br) {
+ br = BKE_brush_add(bmain, "Fill", OB_MODE_TEXTURE_PAINT);
+ br->imagepaint_tool = PAINT_TOOL_FILL;
+ br->ob_mode = OB_MODE_TEXTURE_PAINT;
+ }
br = (Brush *)BKE_libblock_find_name_ex(bmain, ID_BR, "Mask");
if (br) {
br->imagepaint_tool = PAINT_TOOL_MASK;
br->ob_mode |= OB_MODE_TEXTURE_PAINT;
}
+
+ /* remove polish brush (flatten/contrast does the same) */
+ br = (Brush *)BKE_libblock_find_name_ex(bmain, ID_BR, "Polish");
+ if (br) {
+ BKE_libblock_free(bmain, br);
+ }
+
+ /* remove brush brush (huh?) from some modes (draw brushes do the same) */
+ br = (Brush *)BKE_libblock_find_name_ex(bmain, ID_BR, "Brush");
+ if (br) {
+ BKE_libblock_free(bmain, br);
+ }
+
+ /* remove draw brush from texpaint (draw brushes do the same) */
+ br = (Brush *)BKE_libblock_find_name_ex(bmain, ID_BR, "Draw");
+ if (br) {
+ br->ob_mode &= ~OB_MODE_TEXTURE_PAINT;
+ }
}
}
diff --git a/source/blender/blenloader/intern/versioning_legacy.c b/source/blender/blenloader/intern/versioning_legacy.c
index 557cc147f19..12069fd80dd 100644
--- a/source/blender/blenloader/intern/versioning_legacy.c
+++ b/source/blender/blenloader/intern/versioning_legacy.c
@@ -30,13 +30,12 @@
*/
-#include "zlib.h"
-
#include <limits.h>
#ifndef WIN32
# include <unistd.h> // for read close
#else
+# include <zlib.h> /* odd include order-issue */
# include <io.h> // for open close read
# include "winsock2.h"
# include "BLI_winstuff.h"
@@ -78,6 +77,7 @@
#include "BLI_blenlib.h"
#include "BLI_math.h"
+#include "BKE_action.h"
#include "BKE_armature.h"
#include "BKE_colortools.h"
#include "BKE_constraint.h"
@@ -94,14 +94,9 @@
#include "BKE_scene.h"
#include "BKE_sequencer.h"
-#include "IMB_imbuf.h" // for proxy / timecode versioning stuff
-
#include "NOD_socket.h"
#include "BLO_readfile.h"
-#include "BLO_undofile.h"
-
-#include "RE_engine.h"
#include "readfile.h"
@@ -521,6 +516,40 @@ static void do_version_free_effects_245(ListBase *lb)
}
}
+static void do_version_constraints_245(ListBase *lb)
+{
+ bConstraint *con;
+ bConstraintTarget *ct;
+
+ for (con = lb->first; con; con = con->next) {
+ if (con->type == CONSTRAINT_TYPE_PYTHON) {
+ bPythonConstraint *data = (bPythonConstraint *)con->data;
+ if (data->tar) {
+ /* version patching needs to be done */
+ ct = MEM_callocN(sizeof(bConstraintTarget), "PyConTarget");
+
+ ct->tar = data->tar;
+ BLI_strncpy(ct->subtarget, data->subtarget, sizeof(ct->subtarget));
+ ct->space = con->tarspace;
+
+ BLI_addtail(&data->targets, ct);
+ data->tarnum++;
+
+ /* clear old targets to avoid problems */
+ data->tar = NULL;
+ data->subtarget[0] = '\0';
+ }
+ }
+ else if (con->type == CONSTRAINT_TYPE_LOCLIKE) {
+ bLocateLikeConstraint *data = (bLocateLikeConstraint *)con->data;
+
+ /* new headtail functionality makes Bone-Tip function obsolete */
+ if (data->flag & LOCLIKE_TIP)
+ con->headtail = 1.0f;
+ }
+ }
+}
+
PartEff *blo_do_version_give_parteff_245(Object *ob)
{
PartEff *paf;
@@ -619,7 +648,6 @@ void blo_do_versions_pre250(FileData *fd, Library *lib, Main *main)
while (ob) {
if (ob->transflag & 1) {
ob->transflag -= 1;
- //ob->ipoflag |= OB_OFFS_OB;
}
ob = ob->id.next;
}
@@ -656,7 +684,6 @@ void blo_do_versions_pre250(FileData *fd, Library *lib, Main *main)
}
ob = main->object.first;
while (ob) {
- //ob->ipoflag |= OB_OFFS_PARENT;
if (ob->dt == 0)
ob->dt = OB_SOLID;
ob = ob->id.next;
@@ -767,22 +794,14 @@ void blo_do_versions_pre250(FileData *fd, Library *lib, Main *main)
nr = me->totface;
tface = me->tface;
while (nr--) {
- cp = (char *)&tface->col[0];
- if (cp[1] > 126) cp[1] = 255; else cp[1] *= 2;
- if (cp[2] > 126) cp[2] = 255; else cp[2] *= 2;
- if (cp[3] > 126) cp[3] = 255; else cp[3] *= 2;
- cp = (char *)&tface->col[1];
- if (cp[1] > 126) cp[1] = 255; else cp[1] *= 2;
- if (cp[2] > 126) cp[2] = 255; else cp[2] *= 2;
- if (cp[3] > 126) cp[3] = 255; else cp[3] *= 2;
- cp = (char *)&tface->col[2];
- if (cp[1] > 126) cp[1] = 255; else cp[1] *= 2;
- if (cp[2] > 126) cp[2] = 255; else cp[2] *= 2;
- if (cp[3] > 126) cp[3] = 255; else cp[3] *= 2;
- cp = (char *)&tface->col[3];
- if (cp[1] > 126) cp[1] = 255; else cp[1] *= 2;
- if (cp[2] > 126) cp[2] = 255; else cp[2] *= 2;
- if (cp[3] > 126) cp[3] = 255; else cp[3] *= 2;
+ int j;
+ for (j = 0; j < 4; j++) {
+ int k;
+ cp = ((char *)&tface->col[j]) + 1;
+ for (k = 0; k < 3; k++) {
+ cp[k] = (cp[k] > 126) ? 255 : cp[k] * 2;
+ }
+ }
tface++;
}
@@ -1271,7 +1290,7 @@ void blo_do_versions_pre250(FileData *fd, Library *lib, Main *main)
Object *ob;
for (vf = main->vfont.first; vf; vf = vf->id.next) {
- if (strcmp(vf->name + strlen(vf->name)-6, ".Bfont") == 0) {
+ if (STREQ(vf->name + strlen(vf->name) - 6, ".Bfont")) {
strcpy(vf->name, FO_BUILTIN_NAME);
}
}
@@ -1930,7 +1949,7 @@ void blo_do_versions_pre250(FileData *fd, Library *lib, Main *main)
/* btw. armature_rebuild_pose is further only called on leave editmode */
if (ob->type == OB_ARMATURE) {
if (ob->pose)
- ob->pose->flag |= POSE_RECALC;
+ BKE_pose_tag_recalc(main, ob->pose);
/* cannot call stuff now (pointers!), done in setup_app_data */
ob->recalc |= OB_RECALC_OB|OB_RECALC_DATA|OB_RECALC_TIME;
@@ -2054,7 +2073,7 @@ void blo_do_versions_pre250(FileData *fd, Library *lib, Main *main)
data->rootbone = -1;
/* update_pose_etc handles rootbone == -1 */
- ob->pose->flag |= POSE_RECALC;
+ BKE_pose_tag_recalc(main, ob->pose);
}
}
}
@@ -2155,8 +2174,8 @@ void blo_do_versions_pre250(FileData *fd, Library *lib, Main *main)
cam->flag |= CAM_SHOWPASSEPARTOUT;
/* make sure old cameras have title safe on */
- if (!(cam->flag & CAM_SHOWTITLESAFE))
- cam->flag |= CAM_SHOWTITLESAFE;
+ if (!(cam->flag & CAM_SHOW_SAFE_MARGINS))
+ cam->flag |= CAM_SHOW_SAFE_MARGINS;
/* set an appropriate camera passepartout alpha */
if (!(cam->passepartalpha))
@@ -2286,7 +2305,7 @@ void blo_do_versions_pre250(FileData *fd, Library *lib, Main *main)
if (main->versionfile == 241) {
Image *ima;
for (ima = main->image.first; ima; ima = ima->id.next)
- if (strcmp(ima->name, "Compositor") == 0) {
+ if (STREQ(ima->name, "Compositor")) {
strcpy(ima->id.name + 2, "Viewer Node");
strcpy(ima->name, "Viewer Node");
}
@@ -2380,8 +2399,9 @@ void blo_do_versions_pre250(FileData *fd, Library *lib, Main *main)
data->flag |= MINMAX_STICKY;
else
data->flag &= ~MINMAX_STICKY;
- }
+
break;
+ }
case CONSTRAINT_TYPE_ROTLIKE:
{
bRotateLikeConstraint *data = curcon->data;
@@ -2389,8 +2409,9 @@ void blo_do_versions_pre250(FileData *fd, Library *lib, Main *main)
/* version patch from buttons_object.c */
if (data->flag == 0)
data->flag = ROTLIKE_X|ROTLIKE_Y|ROTLIKE_Z;
- }
+
break;
+ }
}
}
}
@@ -2459,7 +2480,7 @@ void blo_do_versions_pre250(FileData *fd, Library *lib, Main *main)
for (group = main->group.first; group; group = group->id.next)
if (group->layer == 0)
- group->layer = (1<<20)-1;
+ group->layer = (1 << 20) - 1;
/* now, subversion control! */
if (main->subversionfile < 3) {
@@ -2474,11 +2495,11 @@ void blo_do_versions_pre250(FileData *fd, Library *lib, Main *main)
ima->gen_x = 256; ima->gen_y = 256;
ima->gen_type = 1;
- if (0 == strncmp(ima->id.name + 2, "Viewer Node", sizeof(ima->id.name) - 2)) {
+ if (STREQLEN(ima->id.name + 2, "Viewer Node", sizeof(ima->id.name) - 2)) {
ima->source = IMA_SRC_VIEWER;
ima->type = IMA_TYPE_COMPOSITE;
}
- if (0 == strncmp(ima->id.name + 2, "Render Result", sizeof(ima->id.name) - 2)) {
+ if (STREQLEN(ima->id.name + 2, "Render Result", sizeof(ima->id.name) - 2)) {
ima->source = IMA_SRC_VIEWER;
ima->type = IMA_TYPE_R_RESULT;
}
@@ -2957,69 +2978,14 @@ void blo_do_versions_pre250(FileData *fd, Library *lib, Main *main)
if ((main->versionfile < 245) || (main->versionfile == 245 && main->subversionfile < 7)) {
Object *ob;
bPoseChannel *pchan;
- bConstraint *con;
- bConstraintTarget *ct;
for (ob = main->object.first; ob; ob = ob->id.next) {
if (ob->pose) {
for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
- for (con = pchan->constraints.first; con; con = con->next) {
- if (con->type == CONSTRAINT_TYPE_PYTHON) {
- bPythonConstraint *data = (bPythonConstraint *)con->data;
- if (data->tar) {
- /* version patching needs to be done */
- ct = MEM_callocN(sizeof(bConstraintTarget), "PyConTarget");
-
- ct->tar = data->tar;
- BLI_strncpy(ct->subtarget, data->subtarget, sizeof(ct->subtarget));
- ct->space = con->tarspace;
-
- BLI_addtail(&data->targets, ct);
- data->tarnum++;
-
- /* clear old targets to avoid problems */
- data->tar = NULL;
- data->subtarget[0] = '\0';
- }
- }
- else if (con->type == CONSTRAINT_TYPE_LOCLIKE) {
- bLocateLikeConstraint *data = (bLocateLikeConstraint *)con->data;
-
- /* new headtail functionality makes Bone-Tip function obsolete */
- if (data->flag & LOCLIKE_TIP)
- con->headtail = 1.0f;
- }
- }
- }
- }
-
- for (con = ob->constraints.first; con; con = con->next) {
- if (con->type == CONSTRAINT_TYPE_PYTHON) {
- bPythonConstraint *data = (bPythonConstraint *)con->data;
- if (data->tar) {
- /* version patching needs to be done */
- ct = MEM_callocN(sizeof(bConstraintTarget), "PyConTarget");
-
- ct->tar = data->tar;
- BLI_strncpy(ct->subtarget, data->subtarget, sizeof(ct->subtarget));
- ct->space = con->tarspace;
-
- BLI_addtail(&data->targets, ct);
- data->tarnum++;
-
- /* clear old targets to avoid problems */
- data->tar = NULL;
- data->subtarget[0] = '\0';
- }
- }
- else if (con->type == CONSTRAINT_TYPE_LOCLIKE) {
- bLocateLikeConstraint *data = (bLocateLikeConstraint *)con->data;
-
- /* new headtail functionality makes Bone-Tip function obsolete */
- if (data->flag & LOCLIKE_TIP)
- con->headtail = 1.0f;
+ do_version_constraints_245(&pchan->constraints);
}
}
+ do_version_constraints_245(&ob->constraints);
if (ob->soft && ob->soft->keys) {
SoftBody *sb = ob->soft;
@@ -3085,7 +3051,7 @@ void blo_do_versions_pre250(FileData *fd, Library *lib, Main *main)
BLI_addtail(&ob->particlesystem, psys);
md = modifier_new(eModifierType_ParticleSystem);
- BLI_snprintf(md->name, sizeof(md->name), "ParticleSystem %i", BLI_countlist(&ob->particlesystem));
+ BLI_snprintf(md->name, sizeof(md->name), "ParticleSystem %i", BLI_listbase_count(&ob->particlesystem));
psmd = (ParticleSystemModifierData*) md;
psmd->psys = psys;
BLI_addtail(&ob->modifiers, md);
diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c
index 59f12657703..d320274ef96 100644
--- a/source/blender/blenloader/intern/writefile.c
+++ b/source/blender/blenloader/intern/writefile.c
@@ -79,9 +79,8 @@
#include <string.h>
#include <stdlib.h>
-#include "zlib.h"
-
#ifdef WIN32
+# include <zlib.h> /* odd include order-issue */
# include "winsock2.h"
# include <io.h>
# include "BLI_winstuff.h"
@@ -163,11 +162,9 @@
#include "BKE_mesh.h"
#ifdef USE_NODE_COMPAT_CUSTOMNODES
-#include "NOD_common.h"
#include "NOD_socket.h" /* for sock->default_value data */
#endif
-#include "RNA_access.h"
#include "BLO_writefile.h"
#include "BLO_readfile.h"
@@ -294,11 +291,10 @@ static void ww_handle_init(eWriteWrapType ww_type, WriteWrap *r_ww)
typedef struct {
struct SDNA *sdna;
- int file;
unsigned char *buf;
MemFile *compare, *current;
- int tot, count, error, memsize;
+ int tot, count, error;
/* Wrap writing, so we can use zlib or
* other compression types later, see: G_FILE_COMPRESS
@@ -336,7 +332,7 @@ static void writedata_do_write(WriteData *wd, const void *mem, int memlen)
/* memory based save */
if (wd->current) {
- add_memfilechunk(NULL, wd->current, mem, memlen);
+ memfile_chunk_add(NULL, wd->current, mem, memlen);
}
else {
if (wd->ww->write(wd->ww, mem, memlen) != memlen) {
@@ -410,7 +406,7 @@ static void mywrite(WriteData *wd, const void *adr, int len)
/**
* BeGiN initializer for mywrite
- * \param file File descriptor
+ * \param ww: File write wrapper.
* \param compare Previous memory file (can be NULL).
* \param current The current memory file (can be NULL).
* \warning Talks to other functions with global parameters
@@ -424,7 +420,7 @@ static WriteData *bgnwrite(WriteWrap *ww, MemFile *compare, MemFile *current)
wd->compare= compare;
wd->current= current;
/* this inits comparing */
- add_memfilechunk(compare, NULL, NULL, 0);
+ memfile_chunk_add(compare, NULL, NULL, 0);
return wd;
}
@@ -591,6 +587,33 @@ void IDP_WriteProperty(IDProperty *prop, void *wd)
IDP_WriteProperty_OnlyData(prop, wd);
}
+static void write_previews(WriteData *wd, PreviewImage *prv)
+{
+ /* Never write previews when doing memsave (i.e. undo/redo)! */
+ if (prv && !wd->current) {
+ short w = prv->w[1];
+ short h = prv->h[1];
+ unsigned int *rect = prv->rect[1];
+
+ /* don't write out large previews if not requested */
+ if (!(U.flag & USER_SAVE_PREVIEWS)) {
+ prv->w[1] = 0;
+ prv->h[1] = 0;
+ prv->rect[1] = NULL;
+ }
+ writestruct(wd, DATA, "PreviewImage", 1, prv);
+ if (prv->rect[0]) writedata(wd, DATA, prv->w[0] * prv->h[0] * sizeof(unsigned int), prv->rect[0]);
+ if (prv->rect[1]) writedata(wd, DATA, prv->w[1] * prv->h[1] * sizeof(unsigned int), prv->rect[1]);
+
+ /* restore preview, we still want to keep it in memory even if not saved to file */
+ if (!(U.flag & USER_SAVE_PREVIEWS) ) {
+ prv->w[1] = w;
+ prv->h[1] = h;
+ prv->rect[1] = rect;
+ }
+ }
+}
+
static void write_fmodifiers(WriteData *wd, ListBase *fmodifiers)
{
FModifier *fcm;
@@ -600,7 +623,7 @@ static void write_fmodifiers(WriteData *wd, ListBase *fmodifiers)
/* Modifiers */
for (fcm= fmodifiers->first; fcm; fcm= fcm->next) {
- FModifierTypeInfo *fmi= fmodifier_get_typeinfo(fcm);
+ const FModifierTypeInfo *fmi= fmodifier_get_typeinfo(fcm);
/* Write the specific data */
if (fmi && fcm->data) {
@@ -616,8 +639,9 @@ static void write_fmodifiers(WriteData *wd, ListBase *fmodifiers)
/* write coefficients array */
if (data->coefficients)
writedata(wd, DATA, sizeof(float)*(data->arraysize), data->coefficients);
- }
+
break;
+ }
case FMODIFIER_TYPE_ENVELOPE:
{
FMod_Envelope *data= (FMod_Envelope *)fcm->data;
@@ -625,8 +649,9 @@ static void write_fmodifiers(WriteData *wd, ListBase *fmodifiers)
/* write envelope data */
if (data->data)
writestruct(wd, DATA, "FCM_EnvelopeData", data->totvert, data->data);
- }
+
break;
+ }
case FMODIFIER_TYPE_PYTHON:
{
FMod_Python *data = (FMod_Python *)fcm->data;
@@ -634,8 +659,9 @@ static void write_fmodifiers(WriteData *wd, ListBase *fmodifiers)
/* Write ID Properties -- and copy this comment EXACTLY for easy finding
* of library blocks that implement this.*/
IDP_WriteProperty(data->prop, wd);
- }
+
break;
+ }
}
}
}
@@ -912,16 +938,39 @@ static void write_nodetree(WriteData *wd, bNodeTree *ntree)
write_node_socket_interface(wd, ntree, sock);
}
-static void current_screen_compat(Main *mainvar, bScreen **screen)
+/**
+ * Take care using 'use_active_win', since we wont want the currently active window
+ * to change which scene renders (currently only used for undo).
+ */
+static void current_screen_compat(Main *mainvar, bScreen **r_screen, bool use_active_win)
{
wmWindowManager *wm;
- wmWindow *window;
+ wmWindow *window = NULL;
/* find a global current screen in the first open window, to have
* a reasonable default for reading in older versions */
wm = mainvar->wm.first;
- window = (wm) ? wm->windows.first : NULL;
- *screen = (window) ? window->screen : NULL;
+
+ if (wm) {
+ if (use_active_win) {
+ /* write the active window into the file, needed for multi-window undo T43424 */
+ for (window = wm->windows.first; window; window = window->next) {
+ if (window->active) {
+ break;
+ }
+ }
+
+ /* fallback */
+ if (window == NULL) {
+ window = wm->windows.first;
+ }
+ }
+ else {
+ window = wm->windows.first;
+ }
+ }
+
+ *r_screen = (window) ? window->screen : NULL;
}
typedef struct RenderInfo {
@@ -940,7 +989,7 @@ static void write_renderinfo(WriteData *wd, Main *mainvar)
RenderInfo data;
/* XXX in future, handle multiple windows with multiple screens? */
- current_screen_compat(mainvar, &curscreen);
+ current_screen_compat(mainvar, &curscreen, false);
if (curscreen) curscene = curscreen->scene;
for (sce= mainvar->scene.first; sce; sce= sce->id.next) {
@@ -1076,7 +1125,7 @@ static void write_pointcaches(WriteData *wd, ListBase *ptcaches)
for (i=0; i<BPHYS_TOT_DATA; i++) {
if (pm->data[i] && pm->data_types & (1<<i)) {
- if (ptcache_data_struct[i][0]=='\0')
+ if (ptcache_data_struct[i][0] == '\0')
writedata(wd, DATA, MEM_allocN_len(pm->data[i]), pm->data[i]);
else
writestruct(wd, DATA, ptcache_data_struct[i], pm->totpoint, pm->data[i]);
@@ -1084,7 +1133,7 @@ static void write_pointcaches(WriteData *wd, ListBase *ptcaches)
}
for (; extra; extra=extra->next) {
- if (ptcache_extra_struct[extra->type][0]=='\0')
+ if (ptcache_extra_struct[extra->type][0] == '\0')
continue;
writestruct(wd, DATA, "PTCacheExtra", 1, extra);
writestruct(wd, DATA, ptcache_extra_struct[extra->type], extra->totdata, extra->data);
@@ -1111,6 +1160,11 @@ static void write_particlesettings(WriteData *wd, ListBase *idbase)
writestruct(wd, DATA, "PartDeflect", 1, part->pd2);
writestruct(wd, DATA, "EffectorWeights", 1, part->effector_weights);
+ if (part->clumpcurve)
+ write_curvemapping(wd, part->clumpcurve);
+ if (part->roughcurve)
+ write_curvemapping(wd, part->roughcurve);
+
dw = part->dupliweights.first;
for (; dw; dw=dw->next) {
/* update indices */
@@ -1379,7 +1433,7 @@ static void write_constraints(WriteData *wd, ListBase *conlist)
bConstraint *con;
for (con=conlist->first; con; con=con->next) {
- bConstraintTypeInfo *cti= BKE_constraint_typeinfo_get(con);
+ const bConstraintTypeInfo *cti= BKE_constraint_typeinfo_get(con);
/* Write the specific data */
if (cti && con->data) {
@@ -1400,16 +1454,18 @@ static void write_constraints(WriteData *wd, ListBase *conlist)
/* Write ID Properties -- and copy this comment EXACTLY for easy finding
* of library blocks that implement this.*/
IDP_WriteProperty(data->prop, wd);
- }
+
break;
+ }
case CONSTRAINT_TYPE_SPLINEIK:
{
bSplineIKConstraint *data = (bSplineIKConstraint *)con->data;
/* write points array */
writedata(wd, DATA, sizeof(float)*(data->numpoints), data->points);
- }
+
break;
+ }
}
}
@@ -1451,7 +1507,7 @@ static void write_pose(WriteData *wd, bPose *pose)
/* write IK param */
if (pose->ikparam) {
- const char *structname = (char *)BKE_pose_ikparam_get_name(pose);
+ const char *structname = BKE_pose_ikparam_get_name(pose);
if (structname)
writestruct(wd, DATA, structname, 1, pose->ikparam);
}
@@ -1475,7 +1531,7 @@ static void write_modifiers(WriteData *wd, ListBase *modbase)
if (modbase == NULL) return;
for (md=modbase->first; md; md= md->next) {
- ModifierTypeInfo *mti = modifierType_getInfo(md->type);
+ const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
if (mti == NULL) return;
writestruct(wd, DATA, mti->structName, 1, md);
@@ -1483,6 +1539,10 @@ static void write_modifiers(WriteData *wd, ListBase *modbase)
if (md->type==eModifierType_Hook) {
HookModifierData *hmd = (HookModifierData*) md;
+ if (hmd->curfalloff) {
+ write_curvemapping(wd, hmd->curfalloff);
+ }
+
writedata(wd, DATA, sizeof(int)*hmd->totindex, hmd->indexar);
}
else if (md->type==eModifierType_Cloth) {
@@ -1591,6 +1651,13 @@ static void write_modifiers(WriteData *wd, ListBase *modbase)
writedata(wd, DATA, sizeof(float)*lmd->total_verts * 3, lmd->vertexco);
}
+ else if (md->type == eModifierType_CorrectiveSmooth) {
+ CorrectiveSmoothModifierData *csmd = (CorrectiveSmoothModifierData *)md;
+
+ if (csmd->bind_coords) {
+ writedata(wd, DATA, sizeof(float[3]) * csmd->bind_coords_num, csmd->bind_coords);
+ }
+ }
}
}
@@ -1657,6 +1724,9 @@ static void write_objects(WriteData *wd, ListBase *idbase)
writelist(wd, DATA, "LinkData", &ob->pc_ids);
writelist(wd, DATA, "LodLevel", &ob->lodlevels);
}
+
+ write_previews(wd, ob->preview);
+
ob= ob->id.next;
}
@@ -1865,28 +1935,20 @@ static void write_grid_paint_mask(WriteData *wd, int count, GridPaintMask *grid_
}
}
-static void write_customdata(WriteData *wd, ID *id, int count, CustomData *data, int partial_type, int partial_count)
+static void write_customdata(
+ WriteData *wd, ID *id, int count, CustomData *data, CustomDataLayer *layers,
+ int partial_type, int partial_count)
{
- CustomData data_tmp;
int i;
- /* This copy will automatically ignore/remove layers set as NO_COPY (and TEMPORARY). */
- CustomData_copy(data, &data_tmp, CD_MASK_EVERYTHING, CD_REFERENCE, count);
-
/* write external customdata (not for undo) */
- if (data_tmp.external && !wd->current)
- CustomData_external_write(&data_tmp, id, CD_MASK_MESH, count, 0);
-
- for (i = 0; i < data_tmp.totlayer; i++)
- data_tmp.layers[i].flag &= ~CD_FLAG_NOFREE;
+ if (data->external && !wd->current)
+ CustomData_external_write(data, id, CD_MASK_MESH, count, 0);
- writestruct_at_address(wd, DATA, "CustomDataLayer", data_tmp.maxlayer, data->layers, data_tmp.layers);
+ writestruct_at_address(wd, DATA, "CustomDataLayer", data->totlayer, data->layers, layers);
- for (i = 0; i < data_tmp.totlayer; i++)
- data_tmp.layers[i].flag |= CD_FLAG_NOFREE;
-
- for (i = 0; i < data_tmp.totlayer; i++) {
- CustomDataLayer *layer= &data_tmp.layers[i];
+ for (i = 0; i < data->totlayer; i++) {
+ CustomDataLayer *layer = &layers[i];
const char *structname;
int structnum, datasize;
@@ -1922,10 +1984,8 @@ static void write_customdata(WriteData *wd, ID *id, int count, CustomData *data,
}
}
- if (data_tmp.external)
- writestruct_at_address(wd, DATA, "CustomDataExternal", 1, data->external, data_tmp.external);
-
- CustomData_free(&data_tmp, count);
+ if (data->external)
+ writestruct(wd, DATA, "CustomDataExternal", 1, data->external);
}
static void write_meshes(WriteData *wd, ListBase *idbase)
@@ -1939,26 +1999,46 @@ static void write_meshes(WriteData *wd, ListBase *idbase)
mesh= idbase->first;
while (mesh) {
+ CustomDataLayer *vlayers = NULL, vlayers_buff[CD_TEMP_CHUNK_SIZE];
+ CustomDataLayer *elayers = NULL, elayers_buff[CD_TEMP_CHUNK_SIZE];
+ CustomDataLayer *flayers = NULL, flayers_buff[CD_TEMP_CHUNK_SIZE];
+ CustomDataLayer *llayers = NULL, llayers_buff[CD_TEMP_CHUNK_SIZE];
+ CustomDataLayer *players = NULL, players_buff[CD_TEMP_CHUNK_SIZE];
+
if (mesh->id.us>0 || wd->current) {
/* write LibData */
if (!save_for_old_blender) {
-
-#ifdef USE_BMESH_SAVE_WITHOUT_MFACE
/* write a copy of the mesh, don't modify in place because it is
* not thread safe for threaded renders that are reading this */
Mesh *old_mesh = mesh;
Mesh copy_mesh = *mesh;
mesh = &copy_mesh;
+#ifdef USE_BMESH_SAVE_WITHOUT_MFACE
/* cache only - don't write */
mesh->mface = NULL;
mesh->totface = 0;
memset(&mesh->fdata, 0, sizeof(mesh->fdata));
+#endif /* USE_BMESH_SAVE_WITHOUT_MFACE */
- writestruct_at_address(wd, ID_ME, "Mesh", 1, old_mesh, mesh);
+ /**
+ * Those calls:
+ * - Reduce mesh->xdata.totlayer to number of layers to write.
+ * - Fill xlayers with those layers to be written.
+ * Note that mesh->xdata is from now on invalid for Blender, but this is why the whole mesh is
+ * a temp local copy!
+ */
+ CustomData_file_write_prepare(&mesh->vdata, &vlayers, vlayers_buff, ARRAY_SIZE(vlayers_buff));
+ CustomData_file_write_prepare(&mesh->edata, &elayers, elayers_buff, ARRAY_SIZE(elayers_buff));
+#ifndef USE_BMESH_SAVE_WITHOUT_MFACE /* Do not copy org fdata in this case!!! */
+ CustomData_file_write_prepare(&mesh->fdata, &flayers, flayers_buff, ARRAY_SIZE(flayers_buff));
#else
- writestruct(wd, ID_ME, "Mesh", 1, mesh);
-#endif /* USE_BMESH_SAVE_WITHOUT_MFACE */
+ flayers = flayers_buff;
+#endif
+ CustomData_file_write_prepare(&mesh->ldata, &llayers, llayers_buff, ARRAY_SIZE(llayers_buff));
+ CustomData_file_write_prepare(&mesh->pdata, &players, players_buff, ARRAY_SIZE(players_buff));
+
+ writestruct_at_address(wd, ID_ME, "Mesh", 1, old_mesh, mesh);
/* direct data */
if (mesh->id.properties) IDP_WriteProperty(mesh->id.properties, wd);
@@ -1967,18 +2047,15 @@ static void write_meshes(WriteData *wd, ListBase *idbase)
writedata(wd, DATA, sizeof(void *)*mesh->totcol, mesh->mat);
writedata(wd, DATA, sizeof(MSelect) * mesh->totselect, mesh->mselect);
- write_customdata(wd, &mesh->id, mesh->totvert, &mesh->vdata, -1, 0);
- write_customdata(wd, &mesh->id, mesh->totedge, &mesh->edata, -1, 0);
+ write_customdata(wd, &mesh->id, mesh->totvert, &mesh->vdata, vlayers, -1, 0);
+ write_customdata(wd, &mesh->id, mesh->totedge, &mesh->edata, elayers, -1, 0);
/* fdata is really a dummy - written so slots align */
- write_customdata(wd, &mesh->id, mesh->totface, &mesh->fdata, -1, 0);
- write_customdata(wd, &mesh->id, mesh->totloop, &mesh->ldata, -1, 0);
- write_customdata(wd, &mesh->id, mesh->totpoly, &mesh->pdata, -1, 0);
+ write_customdata(wd, &mesh->id, mesh->totface, &mesh->fdata, flayers, -1, 0);
+ write_customdata(wd, &mesh->id, mesh->totloop, &mesh->ldata, llayers, -1, 0);
+ write_customdata(wd, &mesh->id, mesh->totpoly, &mesh->pdata, players, -1, 0);
-#ifdef USE_BMESH_SAVE_WITHOUT_MFACE
/* restore pointer */
mesh = old_mesh;
-#endif /* USE_BMESH_SAVE_WITHOUT_MFACE */
-
}
else {
@@ -2000,11 +2077,25 @@ static void write_meshes(WriteData *wd, ListBase *idbase)
mesh->edit_btmesh = NULL;
/* now fill in polys to mfaces */
+ /* XXX This breaks writing desing, by using temp allocated memory, which will likely generate
+ * duplicates in stored 'old' addresses.
+ * This is very bad, but do not see easy way to avoid this, aside from generating those data
+ * outside of save process itself.
+ * Maybe we can live with this, though?
+ */
mesh->totface = BKE_mesh_mpoly_to_mface(&mesh->fdata, &old_mesh->ldata, &old_mesh->pdata,
mesh->totface, old_mesh->totloop, old_mesh->totpoly);
BKE_mesh_update_customdata_pointers(mesh, false);
+ CustomData_file_write_prepare(&mesh->vdata, &vlayers, vlayers_buff, ARRAY_SIZE(vlayers_buff));
+ CustomData_file_write_prepare(&mesh->edata, &elayers, elayers_buff, ARRAY_SIZE(elayers_buff));
+ CustomData_file_write_prepare(&mesh->fdata, &flayers, flayers_buff, ARRAY_SIZE(flayers_buff));
+#if 0
+ CustomData_file_write_prepare(&mesh->ldata, &llayers, llayers_buff, ARRAY_SIZE(llayers_buff));
+ CustomData_file_write_prepare(&mesh->pdata, &players, players_buff, ARRAY_SIZE(players_buff));
+#endif
+
writestruct_at_address(wd, ID_ME, "Mesh", 1, old_mesh, mesh);
/* direct data */
@@ -2014,22 +2105,40 @@ static void write_meshes(WriteData *wd, ListBase *idbase)
writedata(wd, DATA, sizeof(void *)*mesh->totcol, mesh->mat);
/* writedata(wd, DATA, sizeof(MSelect) * mesh->totselect, mesh->mselect); */ /* pre-bmesh NULL's */
- write_customdata(wd, &mesh->id, mesh->totvert, &mesh->vdata, -1, 0);
- write_customdata(wd, &mesh->id, mesh->totedge, &mesh->edata, -1, 0);
- write_customdata(wd, &mesh->id, mesh->totface, &mesh->fdata, -1, 0);
+ write_customdata(wd, &mesh->id, mesh->totvert, &mesh->vdata, vlayers, -1, 0);
+ write_customdata(wd, &mesh->id, mesh->totedge, &mesh->edata, elayers, -1, 0);
+ write_customdata(wd, &mesh->id, mesh->totface, &mesh->fdata, flayers, -1, 0);
/* harmless for older blender versioins but _not_ writing these keeps file size down */
#if 0
- write_customdata(wd, &mesh->id, mesh->totloop, &mesh->ldata, -1, 0);
- write_customdata(wd, &mesh->id, mesh->totpoly, &mesh->pdata, -1, 0);
+ write_customdata(wd, &mesh->id, mesh->totloop, &mesh->ldata, llayers, -1, 0);
+ write_customdata(wd, &mesh->id, mesh->totpoly, &mesh->pdata, players, -1, 0);
#endif
CustomData_free(&mesh->fdata, mesh->totface);
+ flayers = NULL;
/* restore pointer */
mesh = old_mesh;
#endif /* USE_BMESH_SAVE_AS_COMPAT */
}
}
+
+ if (vlayers && vlayers != vlayers_buff) {
+ MEM_freeN(vlayers);
+ }
+ if (elayers && elayers != elayers_buff) {
+ MEM_freeN(elayers);
+ }
+ if (flayers && flayers != flayers_buff) {
+ MEM_freeN(flayers);
+ }
+ if (llayers && llayers != llayers_buff) {
+ MEM_freeN(llayers);
+ }
+ if (players && players != players_buff) {
+ MEM_freeN(players);
+ }
+
mesh= mesh->id.next;
}
}
@@ -2058,51 +2167,43 @@ static void write_lattices(WriteData *wd, ListBase *idbase)
}
}
-static void write_previews(WriteData *wd, PreviewImage *prv)
-{
- if (prv) {
- short w = prv->w[1];
- short h = prv->h[1];
- unsigned int *rect = prv->rect[1];
- /* don't write out large previews if not requested */
- if (!(U.flag & USER_SAVE_PREVIEWS)) {
- prv->w[1] = 0;
- prv->h[1] = 0;
- prv->rect[1] = NULL;
- }
- writestruct(wd, DATA, "PreviewImage", 1, prv);
- if (prv->rect[0]) writedata(wd, DATA, prv->w[0]*prv->h[0]*sizeof(unsigned int), prv->rect[0]);
- if (prv->rect[1]) writedata(wd, DATA, prv->w[1]*prv->h[1]*sizeof(unsigned int), prv->rect[1]);
-
- /* restore preview, we still want to keep it in memory even if not saved to file */
- if (!(U.flag & USER_SAVE_PREVIEWS) ) {
- prv->w[1] = w;
- prv->h[1] = h;
- prv->rect[1] = rect;
- }
- }
-}
-
static void write_images(WriteData *wd, ListBase *idbase)
{
Image *ima;
PackedFile * pf;
-
+ ImageView *iv;
+ ImagePackedFile *imapf;
ima= idbase->first;
while (ima) {
if (ima->id.us>0 || wd->current) {
+ /* Some trickery to keep forward compatibility of packed images. */
+ BLI_assert(ima->packedfile == NULL);
+ if (ima->packedfiles.first != NULL) {
+ imapf = ima->packedfiles.first;
+ ima->packedfile = imapf->packedfile;
+ }
+
/* write LibData */
writestruct(wd, ID_IM, "Image", 1, ima);
if (ima->id.properties) IDP_WriteProperty(ima->id.properties, wd);
- if (ima->packedfile) {
- pf = ima->packedfile;
- writestruct(wd, DATA, "PackedFile", 1, pf);
- writedata(wd, DATA, pf->size, pf->data);
+ for (imapf = ima->packedfiles.first; imapf; imapf = imapf->next) {
+ writestruct(wd, DATA, "ImagePackedFile", 1, imapf);
+ if (imapf->packedfile) {
+ pf = imapf->packedfile;
+ writestruct(wd, DATA, "PackedFile", 1, pf);
+ writedata(wd, DATA, pf->size, pf->data);
+ }
}
write_previews(wd, ima->preview);
+
+ for (iv = ima->views.first; iv; iv = iv->next)
+ writestruct(wd, DATA, "ImageView", 1, iv);
+ writestruct(wd, DATA, "Stereo3dFormat", 1, ima->stereo3d_format);
+
+ ima->packedfile = NULL;
}
ima= ima->id.next;
}
@@ -2257,7 +2358,7 @@ static void write_sequence_modifiers(WriteData *wd, ListBase *modbase)
SequenceModifierData *smd;
for (smd = modbase->first; smd; smd = smd->next) {
- SequenceModifierTypeInfo *smti = BKE_sequence_modifier_type_info_get(smd->type);
+ const SequenceModifierTypeInfo *smti = BKE_sequence_modifier_type_info_get(smd->type);
if (smti) {
writestruct(wd, DATA, smti->struct_name, 1, smd);
@@ -2286,6 +2387,12 @@ static void write_view_settings(WriteData *wd, ColorManagedViewSettings *view_se
}
}
+static void write_paint(WriteData *wd, Paint *p)
+{
+ if (p->cavity_curve)
+ write_curvemapping(wd, p->cavity_curve);
+}
+
static void write_scenes(WriteData *wd, ListBase *scebase)
{
Scene *sce;
@@ -2297,6 +2404,7 @@ static void write_scenes(WriteData *wd, ListBase *scebase)
TimeMarker *marker;
TransformOrientation *ts;
SceneRenderLayer *srl;
+ SceneRenderView *srv;
ToolSettings *tos;
FreestyleModuleConfig *fmc;
FreestyleLineSet *fls;
@@ -2321,18 +2429,22 @@ static void write_scenes(WriteData *wd, ListBase *scebase)
writestruct(wd, DATA, "ToolSettings", 1, tos);
if (tos->vpaint) {
writestruct(wd, DATA, "VPaint", 1, tos->vpaint);
+ write_paint (wd, &tos->vpaint->paint);
}
if (tos->wpaint) {
writestruct(wd, DATA, "VPaint", 1, tos->wpaint);
+ write_paint (wd, &tos->wpaint->paint);
}
if (tos->sculpt) {
writestruct(wd, DATA, "Sculpt", 1, tos->sculpt);
+ write_paint (wd, &tos->sculpt->paint);
}
if (tos->uvsculpt) {
writestruct(wd, DATA, "UvSculpt", 1, tos->uvsculpt);
+ write_paint (wd, &tos->uvsculpt->paint);
}
- // write_paint(wd, &tos->imapaint.paint);
+ write_paint(wd, &tos->imapaint.paint);
ed= sce->ed;
if (ed) {
@@ -2372,9 +2484,14 @@ static void write_scenes(WriteData *wd, ListBase *scebase)
case SEQ_TYPE_GAUSSIAN_BLUR:
writestruct(wd, DATA, "GaussianBlurVars", 1, seq->effectdata);
break;
+ case SEQ_TYPE_TEXT:
+ writestruct(wd, DATA, "TextVars", 1, seq->effectdata);
+ break;
}
}
-
+
+ writestruct(wd, DATA, "Stereo3dFormat", 1, seq->stereo3d_format);
+
strip= seq->strip;
writestruct(wd, DATA, "Strip", 1, strip);
if (seq->flag & SEQ_USE_CROP && strip->crop) {
@@ -2394,6 +2511,10 @@ static void write_scenes(WriteData *wd, ListBase *scebase)
strip->done = true;
}
+ if (seq->prop) {
+ IDP_WriteProperty(seq->prop, wd);
+ }
+
write_sequence_modifiers(wd, &seq->modifiers);
}
SEQ_END
@@ -2435,6 +2556,10 @@ static void write_scenes(WriteData *wd, ListBase *scebase)
writestruct(wd, DATA, "FreestyleLineSet", 1, fls);
}
}
+
+ /* writing MultiView to the blend file */
+ for (srv = sce->r.views.first; srv; srv = srv->next)
+ writestruct(wd, DATA, "SceneRenderView", 1, srv);
if (sce->nodetree) {
writestruct(wd, DATA, "bNodeTree", 1, sce->nodetree);
@@ -2450,6 +2575,8 @@ static void write_scenes(WriteData *wd, ListBase *scebase)
write_pointcaches(wd, &(sce->rigidbody_world->ptcaches));
}
+ write_previews(wd, sce->preview);
+
sce= sce->id.next;
}
/* flush helps the compression for undo-save */
@@ -2468,6 +2595,8 @@ static void write_gpencils(WriteData *wd, ListBase *lb)
/* write gpd data block to file */
writestruct(wd, ID_GD, "bGPdata", 1, gpd);
+ if (gpd->adt) write_animdata(wd, gpd->adt);
+
/* write grease-pencil layers to file */
writelist(wd, DATA, "bGPDlayer", &gpd->layers);
for (gpl= gpd->layers.first; gpl; gpl= gpl->next) {
@@ -2495,8 +2624,10 @@ static void write_windowmanagers(WriteData *wd, ListBase *lb)
for (wm= lb->first; wm; wm= wm->id.next) {
writestruct(wd, ID_WM, "wmWindowManager", 1, wm);
- for (win= wm->windows.first; win; win= win->next)
+ for (win= wm->windows.first; win; win= win->next) {
writestruct(wd, DATA, "wmWindow", 1, win);
+ writestruct(wd, DATA, "Stereo3dFormat", 1, win->stereo3d_format);
+ }
}
}
@@ -2640,6 +2771,11 @@ static void write_screens(WriteData *wd, ListBase *scrbase)
for (bgpic= v3d->bgpicbase.first; bgpic; bgpic= bgpic->next)
writestruct(wd, DATA, "BGpic", 1, bgpic);
if (v3d->localvd) writestruct(wd, DATA, "View3D", 1, v3d->localvd);
+
+ if (v3d->fx_settings.ssao)
+ writestruct(wd, DATA, "GPUSSAOSettings", 1, v3d->fx_settings.ssao);
+ if (v3d->fx_settings.dof)
+ writestruct(wd, DATA, "GPUDOFSettings", 1, v3d->fx_settings.dof);
}
else if (sl->spacetype==SPACE_IPO) {
SpaceIpo *sipo= (SpaceIpo *)sl;
@@ -2727,6 +2863,9 @@ static void write_screens(WriteData *wd, ListBase *scrbase)
else if (sl->spacetype==SPACE_CLIP) {
writestruct(wd, DATA, "SpaceClip", 1, sl);
}
+ else if (sl->spacetype == SPACE_INFO) {
+ writestruct(wd, DATA, "SpaceInfo", 1, sl);
+ }
sl= sl->next;
}
@@ -2934,6 +3073,8 @@ static void write_groups(WriteData *wd, ListBase *idbase)
writestruct(wd, ID_GR, "Group", 1, group);
if (group->id.properties) IDP_WriteProperty(group->id.properties, wd);
+ write_previews(wd, group->preview);
+
go= group->gobject.first;
while (go) {
writestruct(wd, DATA, "GroupObject", 1, go);
@@ -3037,7 +3178,7 @@ static void write_brushes(WriteData *wd, ListBase *idbase)
if (brush->curve)
write_curvemapping(wd, brush->curve);
- if (brush->curve)
+ if (brush->gradient)
writestruct(wd, DATA, "ColorBand", 1, brush->gradient);
}
}
@@ -3233,6 +3374,18 @@ static void write_linestyle_color_modifiers(WriteData *wd, ListBase *modifiers)
case LS_MODIFIER_MATERIAL:
struct_name = "LineStyleColorModifier_Material";
break;
+ case LS_MODIFIER_TANGENT:
+ struct_name = "LineStyleColorModifier_Tangent";
+ break;
+ case LS_MODIFIER_NOISE:
+ struct_name = "LineStyleColorModifier_Noise";
+ break;
+ case LS_MODIFIER_CREASE_ANGLE:
+ struct_name = "LineStyleColorModifier_CreaseAngle";
+ break;
+ case LS_MODIFIER_CURVATURE_3D:
+ struct_name = "LineStyleColorModifier_Curvature_3D";
+ break;
default:
struct_name = "LineStyleColorModifier"; /* this should not happen */
}
@@ -3252,6 +3405,18 @@ static void write_linestyle_color_modifiers(WriteData *wd, ListBase *modifiers)
case LS_MODIFIER_MATERIAL:
writestruct(wd, DATA, "ColorBand", 1, ((LineStyleColorModifier_Material *)m)->color_ramp);
break;
+ case LS_MODIFIER_TANGENT:
+ writestruct(wd, DATA, "ColorBand", 1, ((LineStyleColorModifier_Tangent *)m)->color_ramp);
+ break;
+ case LS_MODIFIER_NOISE:
+ writestruct(wd, DATA, "ColorBand", 1, ((LineStyleColorModifier_Noise *)m)->color_ramp);
+ break;
+ case LS_MODIFIER_CREASE_ANGLE:
+ writestruct(wd, DATA, "ColorBand", 1, ((LineStyleColorModifier_CreaseAngle *)m)->color_ramp);
+ break;
+ case LS_MODIFIER_CURVATURE_3D:
+ writestruct(wd, DATA, "ColorBand", 1, ((LineStyleColorModifier_Curvature_3D *)m)->color_ramp);
+ break;
}
}
}
@@ -3275,6 +3440,18 @@ static void write_linestyle_alpha_modifiers(WriteData *wd, ListBase *modifiers)
case LS_MODIFIER_MATERIAL:
struct_name = "LineStyleAlphaModifier_Material";
break;
+ case LS_MODIFIER_TANGENT:
+ struct_name = "LineStyleAlphaModifier_Tangent";
+ break;
+ case LS_MODIFIER_NOISE:
+ struct_name = "LineStyleAlphaModifier_Noise";
+ break;
+ case LS_MODIFIER_CREASE_ANGLE:
+ struct_name = "LineStyleAlphaModifier_CreaseAngle";
+ break;
+ case LS_MODIFIER_CURVATURE_3D:
+ struct_name = "LineStyleAlphaModifier_Curvature_3D";
+ break;
default:
struct_name = "LineStyleAlphaModifier"; /* this should not happen */
}
@@ -3294,6 +3471,18 @@ static void write_linestyle_alpha_modifiers(WriteData *wd, ListBase *modifiers)
case LS_MODIFIER_MATERIAL:
write_curvemapping(wd, ((LineStyleAlphaModifier_Material *)m)->curve);
break;
+ case LS_MODIFIER_TANGENT:
+ write_curvemapping(wd, ((LineStyleAlphaModifier_Tangent *)m)->curve);
+ break;
+ case LS_MODIFIER_NOISE:
+ write_curvemapping(wd, ((LineStyleAlphaModifier_Noise *)m)->curve);
+ break;
+ case LS_MODIFIER_CREASE_ANGLE:
+ write_curvemapping(wd, ((LineStyleAlphaModifier_CreaseAngle *)m)->curve);
+ break;
+ case LS_MODIFIER_CURVATURE_3D:
+ write_curvemapping(wd, ((LineStyleAlphaModifier_Curvature_3D *)m)->curve);
+ break;
}
}
}
@@ -3320,6 +3509,18 @@ static void write_linestyle_thickness_modifiers(WriteData *wd, ListBase *modifie
case LS_MODIFIER_CALLIGRAPHY:
struct_name = "LineStyleThicknessModifier_Calligraphy";
break;
+ case LS_MODIFIER_TANGENT:
+ struct_name = "LineStyleThicknessModifier_Tangent";
+ break;
+ case LS_MODIFIER_NOISE:
+ struct_name = "LineStyleThicknessModifier_Noise";
+ break;
+ case LS_MODIFIER_CREASE_ANGLE:
+ struct_name = "LineStyleThicknessModifier_CreaseAngle";
+ break;
+ case LS_MODIFIER_CURVATURE_3D:
+ struct_name = "LineStyleThicknessModifier_Curvature_3D";
+ break;
default:
struct_name = "LineStyleThicknessModifier"; /* this should not happen */
}
@@ -3339,6 +3540,15 @@ static void write_linestyle_thickness_modifiers(WriteData *wd, ListBase *modifie
case LS_MODIFIER_MATERIAL:
write_curvemapping(wd, ((LineStyleThicknessModifier_Material *)m)->curve);
break;
+ case LS_MODIFIER_TANGENT:
+ write_curvemapping(wd, ((LineStyleThicknessModifier_Tangent *)m)->curve);
+ break;
+ case LS_MODIFIER_CREASE_ANGLE:
+ write_curvemapping(wd, ((LineStyleThicknessModifier_CreaseAngle *)m)->curve);
+ break;
+ case LS_MODIFIER_CURVATURE_3D:
+ write_curvemapping(wd, ((LineStyleThicknessModifier_Curvature_3D *)m)->curve);
+ break;
}
}
}
@@ -3389,6 +3599,9 @@ static void write_linestyle_geometry_modifiers(WriteData *wd, ListBase *modifier
case LS_MODIFIER_2D_TRANSFORM:
struct_name = "LineStyleGeometryModifier_2DTransform";
break;
+ case LS_MODIFIER_SIMPLIFICATION:
+ struct_name = "LineStyleGeometryModifier_Simplification";
+ break;
default:
struct_name = "LineStyleGeometryModifier"; /* this should not happen */
}
@@ -3428,22 +3641,21 @@ static void write_linestyles(WriteData *wd, ListBase *idbase)
* - for undofile, curscene needs to be saved */
static void write_global(WriteData *wd, int fileflags, Main *mainvar)
{
+ const bool is_undo = (wd->current != NULL);
FileGlobal fg;
bScreen *screen;
char subvstr[8];
/* prevent mem checkers from complaining */
- fg.pads= 0;
+ memset(fg.pad, 0, sizeof(fg.pad));
memset(fg.filename, 0, sizeof(fg.filename));
memset(fg.build_hash, 0, sizeof(fg.build_hash));
- current_screen_compat(mainvar, &screen);
+ current_screen_compat(mainvar, &screen, is_undo);
/* XXX still remap G */
fg.curscreen= screen;
fg.curscene= screen ? screen->scene : NULL;
- fg.displaymode= G.displaymode;
- fg.winpos= G.winpos;
/* prevent to save this, is not good convention, and feature with concerns... */
fg.fileflags= (fileflags & ~G_FILE_FLAGS_RUNTIME);
@@ -3475,10 +3687,11 @@ static void write_global(WriteData *wd, int fileflags, Main *mainvar)
* second are an RGBA image (unsigned char)
* note, this uses 'TEST' since new types will segfault on file load for older blender versions.
*/
-static void write_thumb(WriteData *wd, const int *img)
+static void write_thumb(WriteData *wd, const BlendThumbnail *thumb)
{
- if (img)
- writedata(wd, TEST, (2 + img[0] * img[1]) * sizeof(int), img);
+ if (thumb) {
+ writedata(wd, TEST, BLEN_THUMB_MEMSIZE_FILE(thumb->width, thumb->height), thumb);
+ }
}
/* if MemFile * there's filesave to memory */
@@ -3486,7 +3699,7 @@ static int write_file_handle(
Main *mainvar,
WriteWrap *ww,
MemFile *compare, MemFile *current,
- int write_user_block, int write_flags, const int *thumb)
+ int write_user_block, int write_flags, const BlendThumbnail *thumb)
{
BHead bhead;
ListBase mainlist;
@@ -3618,7 +3831,8 @@ static bool do_history(const char *name, ReportList *reports)
}
/* return: success (1) */
-int BLO_write_file(Main *mainvar, const char *filepath, int write_flags, ReportList *reports, const int *thumb)
+int BLO_write_file(
+ Main *mainvar, const char *filepath, int write_flags, ReportList *reports, const BlendThumbnail *thumb)
{
char tempname[FILE_MAX+1];
int err, write_user_block;
diff --git a/source/blender/blentranslation/BLT_lang.h b/source/blender/blentranslation/BLT_lang.h
new file mode 100644
index 00000000000..fddb18d382f
--- /dev/null
+++ b/source/blender/blentranslation/BLT_lang.h
@@ -0,0 +1,69 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2011 Blender Foundation.
+ * All rights reserved.
+ *
+ *
+ * Contributor(s): Blender Foundation,
+ * Sergey Sharybin
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/blentranslation/BLT_lang.h
+ * \ingroup blt
+ */
+
+#ifndef __BLT_LANG_H__
+#define __BLT_LANG_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Search the path directory to the locale files, this try all
+ * the case for Linux, Win and Mac.
+ * Also dynamically builds locales and locales' menu from "languages" text file.
+ */
+void BLT_lang_init(void);
+
+/* Free languages and locales_menu arrays created by BLT_lang_init. */
+void BLT_lang_free(void);
+
+/* Set the current locale. */
+void BLT_lang_set(const char *);
+/* Get the current locale ([partial] ISO code, e.g. es_ES). */
+const char *BLT_lang_get(void);
+
+/* Get locale's elements (if relevant pointer is not NULL and element actually exists, e.g. if there is no variant,
+ * *variant and *language_variant will always be NULL).
+ * Non-null elements are always MEM_mallocN'ed, it's the caller's responsibility to free them.
+ * NOTE: Always available, even in non-WITH_INTERNATIONAL builds.
+ */
+void BLT_lang_locale_explode(
+ const char *locale, char **language, char **country, char **variant,
+ char **language_country, char **language_variant);
+
+/* Get EnumPropertyItem's for translations menu. */
+struct EnumPropertyItem *BLT_lang_RNA_enum_properties(void);
+
+#ifdef __cplusplus
+};
+#endif
+
+#endif /* __BLT_LANG_H__ */
diff --git a/source/blender/blentranslation/BLT_translation.h b/source/blender/blentranslation/BLT_translation.h
new file mode 100644
index 00000000000..6f24f00acfc
--- /dev/null
+++ b/source/blender/blentranslation/BLT_translation.h
@@ -0,0 +1,206 @@
+/*
+ * ***** 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) 2011 Blender Foundation.
+ * All rights reserved.
+ *
+ *
+ * Contributor(s): Blender Foundation,
+ * Sergey Sharybin
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/blentranslation/BLT_translation.h
+ * \ingroup blt
+ */
+
+
+#ifndef __BLT_TRANSLATION_H__
+#define __BLT_TRANSLATION_H__
+
+#include "BLI_utildefines.h" /* for bool type */
+
+#define TEXT_DOMAIN_NAME "blender"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+bool BLT_is_default_context(const char *msgctxt);
+const char *BLT_pgettext(const char *msgctxt, const char *msgid);
+
+/* translation */
+bool BLT_translate(void);
+bool BLT_translate_iface(void);
+bool BLT_translate_tooltips(void);
+bool BLT_translate_new_dataname(void);
+const char *BLT_translate_do(const char *msgctxt, const char *msgid);
+const char *BLT_translate_do_iface(const char *msgctxt, const char *msgid);
+const char *BLT_translate_do_tooltip(const char *msgctxt, const char *msgid);
+const char *BLT_translate_do_new_dataname(const char *msgctxt, const char *msgid);
+
+
+/* The "translation-marker" macro. */
+#define N_(msgid) msgid
+#define CTX_N_(context, msgid) msgid
+
+/* Those macros should be used everywhere in UI code. */
+#ifdef WITH_INTERNATIONAL
+/*# define _(msgid) BLT_gettext(msgid) */
+# define IFACE_(msgid) BLT_translate_do_iface(NULL, msgid)
+# define TIP_(msgid) BLT_translate_do_tooltip(NULL, msgid)
+# define DATA_(msgid) BLT_translate_do_new_dataname(NULL, msgid)
+# define CTX_IFACE_(context, msgid) BLT_translate_do_iface(context, msgid)
+# define CTX_TIP_(context, msgid) BLT_translate_do_tooltip(context, msgid)
+# define CTX_DATA_(context, msgid) BLT_translate_do_new_dataname(context, msgid)
+#else
+/*# define _(msgid) msgid */
+# define IFACE_(msgid) msgid
+# define TIP_(msgid) msgid
+# define DATA_(msgid) msgid
+# define CTX_IFACE_(context, msgid) msgid
+# define CTX_TIP_(context, msgid) msgid
+# define CTX_DATA_(context, msgid) msgid
+#endif
+
+/* Helper macro, when we want to define a same msgid for multiple msgctxt...
+ * Does nothing in C, but is "parsed" by our i18n py tools.
+ * XXX Currently limited to at most 16 contexts at once
+ * (but you can call it several times with the same msgid, should you need more contexts!).
+ */
+#define BLT_I18N_MSGID_MULTI_CTXT(msgid, ...)
+
+/******************************************************************************
+ * All i18n contexts must be defined here.
+ * This is a nice way to be sure not to use a context twice for different
+ * things, and limit the number of existing contexts!
+ * WARNING! Contexts should not be longer than BKE_ST_MAXNAME - 1!
+ */
+
+/* Default, void context.
+ * WARNING! The "" context is not the same as no (NULL) context at mo/boost::locale level!
+ * NOTE: We translate BLT_I18NCONTEXT_DEFAULT as BLT_I18NCONTEXT_DEFAULT_BPY in Python, as we can't use "natural"
+ * None value in rna string properties... :/
+ * The void string "" is also interpreted as BLT_I18NCONTEXT_DEFAULT.
+ * For perf reason, we only use the first char to detect this context, so other contexts should never start
+ * with the same char!
+ */
+#define BLT_I18NCONTEXT_DEFAULT NULL
+#define BLT_I18NCONTEXT_DEFAULT_BPYRNA "*"
+
+/* Default context for operator names/labels. */
+#define BLT_I18NCONTEXT_OPERATOR_DEFAULT "Operator"
+
+/* Mark the msgid applies to several elements (needed in some cases, as english adjectives have no plural mark. :( */
+#define BLT_I18NCONTEXT_PLURAL "Plural"
+
+/* ID-types contexts. */
+/* WARNING! Keep it in sync with idtypes in blenkernel/intern/idcode.c */
+#define BLT_I18NCONTEXT_ID_ACTION "Action"
+#define BLT_I18NCONTEXT_ID_ARMATURE "Armature"
+#define BLT_I18NCONTEXT_ID_BRUSH "Brush"
+#define BLT_I18NCONTEXT_ID_CAMERA "Camera"
+#define BLT_I18NCONTEXT_ID_CURVE "Curve"
+#define BLT_I18NCONTEXT_ID_FREESTYLELINESTYLE "FreestyleLineStyle"
+#define BLT_I18NCONTEXT_ID_GPENCIL "GPencil"
+#define BLT_I18NCONTEXT_ID_GROUP "Group"
+#define BLT_I18NCONTEXT_ID_ID "ID"
+#define BLT_I18NCONTEXT_ID_IMAGE "Image"
+/*#define BLT_I18NCONTEXT_ID_IPO "Ipo"*/ /* Deprecated */
+#define BLT_I18NCONTEXT_ID_SHAPEKEY "Key"
+#define BLT_I18NCONTEXT_ID_LAMP "Lamp"
+#define BLT_I18NCONTEXT_ID_LIBRARY "Library"
+#define BLT_I18NCONTEXT_ID_LATTICE "Lattice"
+#define BLT_I18NCONTEXT_ID_MATERIAL "Material"
+#define BLT_I18NCONTEXT_ID_METABALL "Metaball"
+#define BLT_I18NCONTEXT_ID_MESH "Mesh"
+#define BLT_I18NCONTEXT_ID_NODETREE "NodeTree"
+#define BLT_I18NCONTEXT_ID_OBJECT "Object"
+#define BLT_I18NCONTEXT_ID_PAINTCURVE "PaintCurve"
+#define BLT_I18NCONTEXT_ID_PALETTE "Palette"
+#define BLT_I18NCONTEXT_ID_PARTICLESETTINGS "ParticleSettings"
+#define BLT_I18NCONTEXT_ID_SCENE "Scene"
+#define BLT_I18NCONTEXT_ID_SCREEN "Screen"
+#define BLT_I18NCONTEXT_ID_SEQUENCE "Sequence"
+#define BLT_I18NCONTEXT_ID_SPEAKER "Speaker"
+#define BLT_I18NCONTEXT_ID_SOUND "Sound"
+#define BLT_I18NCONTEXT_ID_TEXTURE "Texture"
+#define BLT_I18NCONTEXT_ID_TEXT "Text"
+#define BLT_I18NCONTEXT_ID_VFONT "VFont"
+#define BLT_I18NCONTEXT_ID_WORLD "World"
+#define BLT_I18NCONTEXT_ID_WINDOWMANAGER "WindowManager"
+#define BLT_I18NCONTEXT_ID_MOVIECLIP "MovieClip"
+#define BLT_I18NCONTEXT_ID_MASK "Mask"
+
+/* Helper for bpy.app.i18n object... */
+typedef struct {
+ const char *c_id;
+ const char *py_id;
+ const char *value;
+} BLT_i18n_contexts_descriptor;
+
+#define BLT_I18NCONTEXTS_ITEM(ctxt_id, py_id) {#ctxt_id, py_id, ctxt_id}
+
+#define BLT_I18NCONTEXTS_DESC { \
+ BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_DEFAULT, "default_real"), \
+ BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_DEFAULT_BPYRNA, "default"), \
+ BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "operator_default"), \
+ BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_PLURAL, "plural"), \
+ BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_ID_ACTION, "id_action"), \
+ BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_ID_ARMATURE, "id_armature"), \
+ BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_ID_BRUSH, "id_brush"), \
+ BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_ID_CAMERA, "id_camera"), \
+ BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_ID_CURVE, "id_curve"), \
+ BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_ID_FREESTYLELINESTYLE, "id_fs_linestyle"), \
+ BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_ID_GPENCIL, "id_gpencil"), \
+ BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_ID_GROUP, "id_group"), \
+ BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_ID_ID, "id_id"), \
+ BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_ID_IMAGE, "id_image"), \
+ /*BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_ID_IPO, "id_ipo"),*/ \
+ BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_ID_SHAPEKEY, "id_shapekey"), \
+ BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_ID_LAMP, "id_lamp"), \
+ BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_ID_LIBRARY, "id_library"), \
+ BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_ID_LATTICE, "id_lattice"), \
+ BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_ID_MASK, "id_mask"), \
+ BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_ID_MATERIAL, "id_material"), \
+ BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_ID_METABALL, "id_metaball"), \
+ BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_ID_MESH, "id_mesh"), \
+ BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_ID_MOVIECLIP, "id_movieclip"), \
+ BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_ID_NODETREE, "id_nodetree"), \
+ BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_ID_OBJECT, "id_object"), \
+ BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_ID_PAINTCURVE, "id_paintcurve"), \
+ BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_ID_PALETTE, "id_palette"), \
+ BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_ID_PARTICLESETTINGS, "id_particlesettings"), \
+ BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_ID_SCENE, "id_scene"), \
+ BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_ID_SCREEN, "id_screen"), \
+ BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_ID_SEQUENCE, "id_sequence"), \
+ BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_ID_SPEAKER, "id_speaker"), \
+ BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_ID_SOUND, "id_sound"), \
+ BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_ID_TEXTURE, "id_texture"), \
+ BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_ID_TEXT, "id_text"), \
+ BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_ID_VFONT, "id_vfont"), \
+ BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_ID_WORLD, "id_world"), \
+ BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_ID_WINDOWMANAGER, "id_windowmanager"), \
+ {NULL, NULL, NULL} \
+}
+
+#ifdef __cplusplus
+};
+#endif
+
+#endif /* __BLT_TRANSLATION_H__ */
diff --git a/source/blender/blentranslation/CMakeLists.txt b/source/blender/blentranslation/CMakeLists.txt
new file mode 100644
index 00000000000..59bd7f0adfa
--- /dev/null
+++ b/source/blender/blentranslation/CMakeLists.txt
@@ -0,0 +1,56 @@
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# The Original Code is Copyright (C) 2008, Blender Foundation
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# ***** END GPL LICENSE BLOCK *****
+
+set(INC
+ .
+ ../blenkernel
+ ../blenlib
+ ../makesdna
+ ../makesrna
+ ../../../intern/guardedalloc
+ ../../../intern/locale
+)
+
+set(INC_SYS
+)
+
+set(SRC
+ intern/blt_lang.c
+ intern/blt_translation.c
+
+ BLT_lang.h
+ BLT_translation.h
+)
+
+if(WITH_INTERNATIONAL)
+ add_definitions(-DWITH_INTERNATIONAL)
+endif()
+
+if(WITH_PYTHON)
+ add_definitions(-DWITH_PYTHON)
+ list(APPEND INC
+ ../python
+ )
+endif()
+
+blender_add_lib(bf_blentranslation "${SRC}" "${INC}" "${INC_SYS}")
diff --git a/source/blender/blentranslation/SConscript b/source/blender/blentranslation/SConscript
new file mode 100644
index 00000000000..c7e9853618c
--- /dev/null
+++ b/source/blender/blentranslation/SConscript
@@ -0,0 +1,46 @@
+#!/usr/bin/env python
+#
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# ***** END GPL LICENSE BLOCK *****
+
+import sys
+Import ('env')
+
+sources = env.Glob('intern/*.c')
+
+incs = [
+ '.',
+ '#/intern/guardedalloc',
+ '#/intern/locale',
+ '../blenkernel',
+ '../blenlib',
+ '../blentranslation',
+ '../makesdna',
+ '../makesrna',
+ ]
+
+defs = []
+
+if env['WITH_BF_INTERNATIONAL']:
+ defs.append('WITH_INTERNATIONAL')
+
+if env['WITH_BF_PYTHON']:
+ defs.append('WITH_PYTHON')
+ incs.append('../python')
+
+env.BlenderLib('bf_blentranslation', sources, incs, defines=defs, libtype=['core', 'player'], priority=[211, 211])
diff --git a/source/blender/blenfont/intern/blf_lang.c b/source/blender/blentranslation/intern/blt_lang.c
index 12d71827136..1ad62fa5869 100644
--- a/source/blender/blenfont/intern/blf_lang.c
+++ b/source/blender/blentranslation/intern/blt_lang.c
@@ -23,8 +23,8 @@
* ***** END GPL LICENSE BLOCK *****
*/
-/** \file blender/blenfont/intern/blf_lang.c
- * \ingroup blf
+/** \file blender/blentranslation/intern/blt_lang.c
+ * \ingroup blt
*
* Main internationalization functions to set the locale and query available languages.
*/
@@ -33,15 +33,22 @@
#include <stdlib.h>
#include <string.h>
+#ifndef _WIN32
+# include <locale.h>
+#endif
+
#include "RNA_types.h"
-#include "BLF_translation.h" /* own include */
+#include "BLT_translation.h"
+#include "BLT_lang.h" /* own include */
#include "BLI_fileops.h"
#include "BLI_linklist.h"
#include "BLI_path_util.h"
#include "BLI_string.h"
+#include "BLI_utildefines.h"
+#include "BKE_appdir.h"
#include "DNA_userdef_types.h"
@@ -79,7 +86,7 @@ static void free_locales(void)
static void fill_locales(void)
{
- const char * const languages_path = BLI_get_folder(BLENDER_DATAFILES, "locale");
+ const char * const languages_path = BKE_appdir_folder_id(BLENDER_DATAFILES, "locale");
char languages[FILE_MAX];
LinkNode *lines = NULL, *line;
char *str;
@@ -90,7 +97,7 @@ static void fill_locales(void)
BLI_join_dirfile(languages, FILE_MAX, languages_path, "languages");
line = lines = BLI_file_read_as_lines(languages);
- /* This whole "parsing" code is a bit weak, in that it expects strictly formated input file...
+ /* This whole "parsing" code is a bit weak, in that it expects strictly formatted input file...
* Should not be a problem, though, as this file is script-generated! */
/* First loop to find highest locale ID */
@@ -175,7 +182,7 @@ static void fill_locales(void)
}
#endif /* WITH_INTERNATIONAL */
-EnumPropertyItem *BLF_RNA_lang_enum_properties(void)
+EnumPropertyItem *BLT_lang_RNA_enum_properties(void)
{
#ifdef WITH_INTERNATIONAL
return locales_menu;
@@ -184,11 +191,40 @@ EnumPropertyItem *BLF_RNA_lang_enum_properties(void)
#endif
}
-void BLF_lang_init(void)
+void BLT_lang_init(void)
{
#ifdef WITH_INTERNATIONAL
- const char * const messagepath = BLI_get_folder(BLENDER_DATAFILES, "locale");
+ const char * const messagepath = BKE_appdir_folder_id(BLENDER_DATAFILES, "locale");
+#endif
+ /* Make sure LANG is correct and wouldn't cause std::rumtime_error. */
+#ifndef _WIN32
+ /* TODO(sergey): This code only ensures LANG is set properly, so later when
+ * Cycles will try to use file system API from boost there'll be no runtime
+ * exception generated by std::locale() which _requires_ having proper LANG
+ * set in the environment.
+ *
+ * Ideally we also need to ensure LC_ALL, LC_MESSAGES and others are also
+ * set to a proper value, but currently it's not a huge deal and doesn't
+ * cause any headache.
+ *
+ * Would also be good to find nicer way to check if LANG is correct.
+ */
+ const char *lang = getenv("LANG");
+ if (lang != NULL) {
+ char *old_locale = setlocale(LC_ALL, NULL);
+ /* Make a copy so subsequenct setlocale() doesn't interfere. */
+ old_locale = BLI_strdup(old_locale);
+ if (setlocale(LC_ALL, lang) == NULL) {
+ setenv("LANG", "C", 1);
+ printf("Warning: Falling back to the standard locale (\"C\")\n");
+ }
+ setlocale(LC_ALL, old_locale);
+ MEM_freeN(old_locale);
+ }
+#endif
+
+#ifdef WITH_INTERNATIONAL
if (messagepath) {
bl_locale_init(messagepath, TEXT_DOMAIN_NAME);
fill_locales();
@@ -200,7 +236,7 @@ void BLF_lang_init(void)
#endif
}
-void BLF_lang_free(void)
+void BLT_lang_free(void)
{
#ifdef WITH_INTERNATIONAL
free_locales();
@@ -213,7 +249,7 @@ void BLF_lang_free(void)
# define LOCALE(_id) (locales ? locales[(_id)] : "")
#endif
-void BLF_lang_set(const char *str)
+void BLT_lang_set(const char *str)
{
#ifdef WITH_INTERNATIONAL
int ulang = ULANGUAGE;
@@ -247,15 +283,18 @@ void BLF_lang_set(const char *str)
}
/* Get the current locale (short code, e.g. es_ES). */
-const char *BLF_lang_get(void)
+const char *BLT_lang_get(void)
{
#ifdef WITH_INTERNATIONAL
- const char *locale = LOCALE(ULANGUAGE);
- if (locale[0] == '\0') {
- /* Default locale, we have to find which one we are actually using! */
- locale = bl_locale_get();
+ if (BLT_translate()) {
+ const char *locale = LOCALE(ULANGUAGE);
+ if (locale[0] == '\0') {
+ /* Default locale, we have to find which one we are actually using! */
+ locale = bl_locale_get();
+ }
+ return locale;
}
- return locale;
+ return "en_US"; /* Kind of default locale in Blender when no translation enabled. */
#else
return "";
#endif
@@ -269,8 +308,9 @@ const char *BLF_lang_get(void)
* Non-null elements are always MEM_mallocN'ed, it's the caller's responsibility to free them.
* NOTE: Keep that one always available, you never know, may become useful even in no-WITH_INTERNATIONAL context...
*/
-void BLF_locale_explode(const char *locale, char **language, char **country, char **variant,
- char **language_country, char **language_variant)
+void BLT_lang_locale_explode(
+ const char *locale, char **language, char **country, char **variant,
+ char **language_country, char **language_variant)
{
char *m1, *m2, *_t = NULL;
diff --git a/source/blender/blenfont/intern/blf_translation.c b/source/blender/blentranslation/intern/blt_translation.c
index 150ff1b2107..c552bac25b0 100644
--- a/source/blender/blenfont/intern/blf_translation.c
+++ b/source/blender/blentranslation/intern/blt_translation.c
@@ -24,8 +24,8 @@
* ***** END GPL LICENSE BLOCK *****
*/
-/** \file blender/blenfont/intern/blf_translation.c
- * \ingroup blf
+/** \file blender/blentranslation/intern/blt_translation.c
+ * \ingroup blt
*
* Manages translation files and provides translation functions.
* (which are optional and can be disabled as a preference).
@@ -34,7 +34,7 @@
#include <stdlib.h>
#include <string.h>
-#include "BLF_translation.h"
+#include "BLT_translation.h"
#include "MEM_guardedalloc.h"
@@ -44,115 +44,41 @@
#include "DNA_userdef_types.h" /* For user settings. */
+#ifdef WITH_PYTHON
#include "BPY_extern.h"
+#endif
#ifdef WITH_INTERNATIONAL
-
#include "boost_locale_wrapper.h"
-
-static const char unifont_filename[] = "droidsans.ttf.gz";
-static unsigned char *unifont_ttf = NULL;
-static int unifont_size = 0;
-static const char unifont_mono_filename[] = "bmonofont-i18n.ttf.gz";
-static unsigned char *unifont_mono_ttf = NULL;
-static int unifont_mono_size = 0;
#endif /* WITH_INTERNATIONAL */
-unsigned char *BLF_get_unifont(int *r_unifont_size)
-{
-#ifdef WITH_INTERNATIONAL
- if (unifont_ttf == NULL) {
- const char * const fontpath = BLI_get_folder(BLENDER_DATAFILES, "fonts");
- if (fontpath) {
- char unifont_path[1024];
-
- BLI_snprintf(unifont_path, sizeof(unifont_path), "%s/%s", fontpath, unifont_filename);
-
- unifont_ttf = (unsigned char *)BLI_file_ungzip_to_mem(unifont_path, &unifont_size);
- }
- else {
- printf("%s: 'fonts' data path not found for international font, continuing\n", __func__);
- }
- }
-
- *r_unifont_size = unifont_size;
-
- return unifont_ttf;
-#else
- (void)r_unifont_size;
- return NULL;
-#endif
-}
-
-void BLF_free_unifont(void)
-{
-#ifdef WITH_INTERNATIONAL
- if (unifont_ttf)
- MEM_freeN(unifont_ttf);
-#else
-#endif
-}
-
-unsigned char *BLF_get_unifont_mono(int *r_unifont_size)
-{
-#ifdef WITH_INTERNATIONAL
- if (unifont_mono_ttf == NULL) {
- const char *fontpath = BLI_get_folder(BLENDER_DATAFILES, "fonts");
- if (fontpath) {
- char unifont_path[1024];
-
- BLI_snprintf(unifont_path, sizeof(unifont_path), "%s/%s", fontpath, unifont_mono_filename);
-
- unifont_mono_ttf = (unsigned char *)BLI_file_ungzip_to_mem(unifont_path, &unifont_mono_size);
- }
- else {
- printf("%s: 'fonts' data path not found for international monospace font, continuing\n", __func__);
- }
- }
-
- *r_unifont_size = unifont_mono_size;
-
- return unifont_mono_ttf;
-#else
- (void)r_unifont_size;
- return NULL;
-#endif
-}
-
-void BLF_free_unifont_mono(void)
-{
-#ifdef WITH_INTERNATIONAL
- if (unifont_mono_ttf)
- MEM_freeN(unifont_mono_ttf);
-#else
-#endif
-}
-
-bool BLF_is_default_context(const char *msgctxt)
+bool BLT_is_default_context(const char *msgctxt)
{
/* We use the "short" test, a more complete one could be:
- * return (!msgctxt || !msgctxt[0] || !strcmp(msgctxt == BLF_I18NCONTEXT_DEFAULT_BPYRNA))
+ * return (!msgctxt || !msgctxt[0] || STREQ(msgctxt, BLT_I18NCONTEXT_DEFAULT_BPYRNA))
*/
/* Note: trying without the void string check for now, it *should* not be necessary... */
- return (!msgctxt || msgctxt[0] == BLF_I18NCONTEXT_DEFAULT_BPYRNA[0]);
+ return (!msgctxt || msgctxt[0] == BLT_I18NCONTEXT_DEFAULT_BPYRNA[0]);
}
-const char *BLF_pgettext(const char *msgctxt, const char *msgid)
+const char *BLT_pgettext(const char *msgctxt, const char *msgid)
{
#ifdef WITH_INTERNATIONAL
const char *ret = msgid;
if (msgid && msgid[0]) {
- if (BLF_is_default_context(msgctxt)) {
- msgctxt = BLF_I18NCONTEXT_DEFAULT;
+ if (BLT_is_default_context(msgctxt)) {
+ msgctxt = BLT_I18NCONTEXT_DEFAULT;
}
ret = bl_locale_pgettext(msgctxt, msgid);
/* We assume if the returned string is the same (memory level) as the msgid, no translation was found,
* and we can try py scripts' ones!
*/
+#ifdef WITH_PYTHON
if (ret == msgid) {
ret = BPY_app_translations_py_pgettext(msgctxt, msgid);
}
+#endif
}
return ret;
@@ -162,7 +88,16 @@ const char *BLF_pgettext(const char *msgctxt, const char *msgid)
#endif
}
-bool BLF_translate_iface(void)
+bool BLT_translate(void)
+{
+#ifdef WITH_INTERNATIONAL
+ return (U.transopts & USER_DOTRANSLATE) != 0;
+#else
+ return false;
+#endif
+}
+
+bool BLT_translate_iface(void)
{
#ifdef WITH_INTERNATIONAL
return (U.transopts & USER_DOTRANSLATE) && (U.transopts & USER_TR_IFACE);
@@ -171,7 +106,7 @@ bool BLF_translate_iface(void)
#endif
}
-bool BLF_translate_tooltips(void)
+bool BLT_translate_tooltips(void)
{
#ifdef WITH_INTERNATIONAL
return (U.transopts & USER_DOTRANSLATE) && (U.transopts & USER_TR_TOOLTIPS);
@@ -180,7 +115,7 @@ bool BLF_translate_tooltips(void)
#endif
}
-bool BLF_translate_new_dataname(void)
+bool BLT_translate_new_dataname(void)
{
#ifdef WITH_INTERNATIONAL
return (U.transopts & USER_DOTRANSLATE) && (U.transopts & USER_TR_NEWDATANAME);
@@ -189,11 +124,26 @@ bool BLF_translate_new_dataname(void)
#endif
}
-const char *BLF_translate_do_iface(const char *msgctxt, const char *msgid)
+const char *BLT_translate_do(const char *msgctxt, const char *msgid)
+{
+#ifdef WITH_INTERNATIONAL
+ if (BLT_translate()) {
+ return BLT_pgettext(msgctxt, msgid);
+ }
+ else {
+ return msgid;
+ }
+#else
+ (void)msgctxt;
+ return msgid;
+#endif
+}
+
+const char *BLT_translate_do_iface(const char *msgctxt, const char *msgid)
{
#ifdef WITH_INTERNATIONAL
- if (BLF_translate_iface()) {
- return BLF_pgettext(msgctxt, msgid);
+ if (BLT_translate_iface()) {
+ return BLT_pgettext(msgctxt, msgid);
}
else {
return msgid;
@@ -204,11 +154,11 @@ const char *BLF_translate_do_iface(const char *msgctxt, const char *msgid)
#endif
}
-const char *BLF_translate_do_tooltip(const char *msgctxt, const char *msgid)
+const char *BLT_translate_do_tooltip(const char *msgctxt, const char *msgid)
{
#ifdef WITH_INTERNATIONAL
- if (BLF_translate_tooltips()) {
- return BLF_pgettext(msgctxt, msgid);
+ if (BLT_translate_tooltips()) {
+ return BLT_pgettext(msgctxt, msgid);
}
else {
return msgid;
@@ -219,11 +169,11 @@ const char *BLF_translate_do_tooltip(const char *msgctxt, const char *msgid)
#endif
}
-const char *BLF_translate_do_new_dataname(const char *msgctxt, const char *msgid)
+const char *BLT_translate_do_new_dataname(const char *msgctxt, const char *msgid)
{
#ifdef WITH_INTERNATIONAL
- if (BLF_translate_new_dataname()) {
- return BLF_pgettext(msgctxt, msgid);
+ if (BLT_translate_new_dataname()) {
+ return BLT_pgettext(msgctxt, msgid);
}
else {
return msgid;
diff --git a/source/blender/bmesh/CMakeLists.txt b/source/blender/bmesh/CMakeLists.txt
index a43e835f022..257768b0ac8 100644
--- a/source/blender/bmesh/CMakeLists.txt
+++ b/source/blender/bmesh/CMakeLists.txt
@@ -25,9 +25,9 @@
set(INC
.
- ../blenfont
../blenkernel
../blenlib
+ ../blentranslation
../makesdna
../../../intern/guardedalloc
../../../extern/rangetree
@@ -43,6 +43,7 @@ set(SRC
operators/bmo_bisect_plane.c
operators/bmo_bridge.c
operators/bmo_connect.c
+ operators/bmo_connect_concave.c
operators/bmo_connect_nonplanar.c
operators/bmo_connect_pair.c
operators/bmo_create.c
@@ -60,6 +61,8 @@ set(SRC
operators/bmo_mesh_conv.c
operators/bmo_mirror.c
operators/bmo_normals.c
+ operators/bmo_offset_edgeloops.c
+ operators/bmo_planar_faces.c
operators/bmo_poke.c
operators/bmo_primitive.c
operators/bmo_removedoubles.c
@@ -74,6 +77,8 @@ set(SRC
operators/bmo_utils.c
operators/bmo_wireframe.c
+ intern/bmesh_callback_generic.c
+ intern/bmesh_callback_generic.h
intern/bmesh_construct.c
intern/bmesh_construct.h
intern/bmesh_core.c
@@ -140,6 +145,8 @@ set(SRC
tools/bmesh_intersect.h
tools/bmesh_path.c
tools/bmesh_path.h
+ tools/bmesh_region_match.c
+ tools/bmesh_region_match.h
tools/bmesh_triangulate.c
tools/bmesh_triangulate.h
tools/bmesh_wireframe.c
diff --git a/source/blender/bmesh/SConscript b/source/blender/bmesh/SConscript
index de839f7f6a6..c53974be1a7 100644
--- a/source/blender/bmesh/SConscript
+++ b/source/blender/bmesh/SConscript
@@ -35,8 +35,8 @@ sources += env.Glob('tools/*.c')
incs = [
'./',
- '../blenfont',
'../blenlib',
+ '../blentranslation',
'../makesdna',
'../blenkernel',
'#/intern/guardedalloc',
diff --git a/source/blender/bmesh/bmesh.h b/source/blender/bmesh/bmesh.h
index 8b5250b7c1e..78c814af86e 100644
--- a/source/blender/bmesh/bmesh.h
+++ b/source/blender/bmesh/bmesh.h
@@ -28,8 +28,7 @@
*
* \addtogroup bmesh BMesh
*
- * \brief BMesh is a non-manifold boundary representation designed to replace the current, limited EditMesh structure,
- * solving many of the design limitations and maintenance issues of EditMesh.
+ * \brief BMesh is a non-manifold boundary representation designed to support advanced editing operations.
*
*
* \section bm_structure The Structure
@@ -58,10 +57,14 @@
*
* \subsection bm_loop The Loop
*
- * Loops define the boundary loop of a face. Each loop logically corresponds to an edge,
- * which is defined by the loop and next loop's vertices.
+ * Loops can be thought of as a *face-corner*, since faces don't reference verts or edges directly.
+ * Each loop connects the face to one of its corner vertices,
+ * and also references an edge which connects this loop's vertex to the next loop's vertex.
*
- * Loops store several handy pointers:
+ * Loops allow faces to access their verts and edges,
+ * while edges and faces store their loops, allowing access in the opposite direction too.
+ *
+ * Loop pointers:
*
* - BMLoop#v - pointer to the vertex associated with this loop.
* - BMLoop#e - pointer to the edge associated with this loop,
@@ -78,11 +81,11 @@
*
* \subsection bm_edges_and_verts Edges and Vertices
*
- * Edges and Vertices in BMesh are much like their counterparts in EditMesh,
- * except for some members private to the BMesh api.
+ * Edges and Vertices in BMesh are primitive structures.
*
- * \note There can be more than one edge between two vertices in bmesh,
- * though the rest of blender (e.g. DerivedMesh, CDDM, CCGSubSurf, etc) does not support this.
+ * \note There can be more than one edge between two vertices in BMesh,
+ * though the rest of Blender (e.g. DerivedMesh, CDDM, CCGSubSurf, etc) does not support this.
+ * So it should only occur temporarily during editing operations.
*
*
* \subsection bm_queries Queries
@@ -107,7 +110,8 @@
* \subsection bm_iter_api Iterator API
*
* Most topological queries in BMesh go through an iterator API (see Queries above).
- * These are defined in bmesh_iterators.h. If you can, please use the #BM_ITER macro in bmesh_iterators.h
+ * These are defined in bmesh_iterators.h.
+ * If you can, please use the #BM_ITER_MESH, #BM_ITER_ELEM macros in bmesh_iterators.h
*
*
* \subsection bm_walker_api Walker API
@@ -161,7 +165,7 @@
* - integer - #BMO_OP_SLOT_INT
* - boolean - #BMO_OP_SLOT_BOOL
* - float - #BMO_OP_SLOT_FLT
- * - pointer - #BMO_OP_SLOT_PNT
+ * - pointer - #BMO_OP_SLOT_PTR
* - matrix - #BMO_OP_SLOT_MAT
* - vector - #BMO_OP_SLOT_VEC
* - buffer - #BMO_OP_SLOT_ELEMENT_BUF - a list of verts/edges/faces.
@@ -199,18 +203,6 @@
*
* There may be a better place for this section, but adding here for now.
*
- * \subsection bm_todo_tools Tools
- *
- * Probably most of these will be bmesh operators.
- *
- * - make ngons flat.
- * - solidify (precise mode), keeps even wall thickness, re-creates outlines of offset faces with plane-plane
- * intersections.
- * - split vert (we already have in our API, just no tool).
- * - flip selected region (invert all faces about the plane defined by the selected region outline)
- * - interactive dissolve (like the knife tool but draw over edges to dissolve)
- *
- *
* \subsection bm_todo_optimize Optimizations
*
* - skip normal calc when its not needed (when calling chain of operators & for modifiers, flag as dirty)
@@ -218,11 +210,6 @@
* - ability to call BMO's with option not to create return data (will save some time)
* - binary diff UNDO, currently this uses huge amount of ram when all shapes are stored for each undo step for eg.
* - use two different iterator types for BMO map/buffer types.
- *
- *
- * \subsection bm_todo_tools_enhance Tool Enhancements
- *
- * - vert slide UV correction (like we have for edge slide)
*/
#ifdef __cplusplus
@@ -243,6 +230,7 @@ extern "C" {
#include "intern/bmesh_error.h"
#include "intern/bmesh_core.h"
+#include "intern/bmesh_callback_generic.h"
#include "intern/bmesh_construct.h"
#include "intern/bmesh_delete.h"
#include "intern/bmesh_edgeloop.h"
diff --git a/source/blender/bmesh/bmesh_class.h b/source/blender/bmesh/bmesh_class.h
index 39359b97a4e..57107ed4e37 100644
--- a/source/blender/bmesh/bmesh_class.h
+++ b/source/blender/bmesh/bmesh_class.h
@@ -256,27 +256,54 @@ enum {
#define BM_ALL (BM_VERT | BM_EDGE | BM_LOOP | BM_FACE)
#define BM_ALL_NOLOOP (BM_VERT | BM_EDGE | BM_FACE)
+/* args for _Generic */
+#define _BM_GENERIC_TYPE_ELEM_NONCONST \
+ void *, BMVert *, BMEdge *, BMLoop *, BMFace *, \
+ BMElem *, BMElemF *, BMHeader *
+
+#define _BM_GENERIC_TYPE_ELEM_CONST \
+ const void *, const BMVert *, const BMEdge *, const BMLoop *, const BMFace *, \
+ const BMElem *, const BMElemF *, const BMHeader *, \
+ void * const, BMVert * const, BMEdge * const, BMLoop * const, BMFace * const, \
+ BMElem * const, BMElemF * const, BMHeader * const
+
+#define BM_CHECK_TYPE_ELEM_CONST(ele) \
+ CHECK_TYPE_ANY(ele, _BM_GENERIC_TYPES_CONST)
+
+#define BM_CHECK_TYPE_ELEM_NONCONST(ele) \
+ CHECK_TYPE_ANY(ele, _BM_GENERIC_TYPE_ELEM_NONCONST)
+
+#define BM_CHECK_TYPE_ELEM(ele) \
+ CHECK_TYPE_ANY(ele, _BM_GENERIC_TYPE_ELEM_NONCONST, _BM_GENERIC_TYPE_ELEM_CONST)
+
+#define BM_CHECK_TYPE_ELEM_ASSIGN(ele) \
+ (BM_CHECK_TYPE_ELEM(ele)), ele
+
/* BMHeader->hflag (char) */
enum {
BM_ELEM_SELECT = (1 << 0),
BM_ELEM_HIDDEN = (1 << 1),
BM_ELEM_SEAM = (1 << 2),
- BM_ELEM_SMOOTH = (1 << 3), /* used for faces and edges, note from the user POV,
- * this is a sharp edge when disabled */
-
- BM_ELEM_TAG = (1 << 4), /* internal flag, used for ensuring correct normals
- * during multires interpolation, and any other time
- * when temp tagging is handy.
- * always assume dirty & clear before use. */
+ /**
+ * used for faces and edges, note from the user POV,
+ * this is a sharp edge when disabled */
+ BM_ELEM_SMOOTH = (1 << 3),
+ /**
+ * internal flag, used for ensuring correct normals
+ * during multires interpolation, and any other time
+ * when temp tagging is handy.
+ * always assume dirty & clear before use. */
+ BM_ELEM_TAG = (1 << 4),
BM_ELEM_DRAW = (1 << 5), /* edge display */
/* spare tag, assumed dirty, use define in each function to name based on use */
// _BM_ELEM_TAG_ALT = (1 << 6), // UNUSED
-
- BM_ELEM_INTERNAL_TAG = (1 << 7) /* for low level internal API tagging,
- * since tools may want to tag verts and
- * not have functions clobber them */
+ /**
+ * for low level internal API tagging,
+ * since tools may want to tag verts and
+ * not have functions clobber them */
+ BM_ELEM_INTERNAL_TAG = (1 << 7),
};
struct BPy_BMGeneric;
@@ -291,8 +318,17 @@ typedef bool (*BMElemFilterFunc)(BMElem *, void *user_data);
#define BM_ELEM_CD_GET_INT(ele, offset) \
(assert(offset != -1), *((int *)((char *)(ele)->head.data + (offset))))
+#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)
+#define BM_ELEM_CD_GET_VOID_P(ele, offset) \
+ (assert(offset != -1), \
+ _Generic(ele, \
+ GENERIC_TYPE_ANY( POINTER_OFFSET((ele)->head.data, offset), _BM_GENERIC_TYPE_ELEM_NONCONST), \
+ GENERIC_TYPE_ANY((const void *)POINTER_OFFSET((ele)->head.data, offset), _BM_GENERIC_TYPE_ELEM_CONST)) \
+ )
+#else
#define BM_ELEM_CD_GET_VOID_P(ele, offset) \
(assert(offset != -1), (void *)((char *)(ele)->head.data + (offset)))
+#endif
#define BM_ELEM_CD_SET_FLOAT(ele, offset, f) { CHECK_TYPE_NONCONST(ele); \
assert(offset != -1); *((float *)((char *)(ele)->head.data + (offset))) = (f); } (void)0
diff --git a/source/blender/bmesh/bmesh_tools.h b/source/blender/bmesh/bmesh_tools.h
index baffeb774b6..f7f767f91bf 100644
--- a/source/blender/bmesh/bmesh_tools.h
+++ b/source/blender/bmesh/bmesh_tools.h
@@ -41,6 +41,7 @@ extern "C" {
#include "tools/bmesh_edgenet.h"
#include "tools/bmesh_edgesplit.h"
#include "tools/bmesh_path.h"
+#include "tools/bmesh_region_match.h"
#include "tools/bmesh_triangulate.h"
#ifdef __cplusplus
diff --git a/source/blender/bmesh/intern/bmesh_callback_generic.c b/source/blender/bmesh/intern/bmesh_callback_generic.c
new file mode 100644
index 00000000000..913255bfb33
--- /dev/null
+++ b/source/blender/bmesh/intern/bmesh_callback_generic.c
@@ -0,0 +1,60 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/bmesh/intern/bmesh_callback_generic.c
+ * \ingroup bmesh
+ *
+ * BM element callback functions.
+ */
+
+#include "BLI_utildefines.h"
+
+#include "bmesh.h"
+
+#include "intern/bmesh_callback_generic.h"
+
+bool BM_elem_cb_check_hflag_ex(BMElem *ele, void *user_data)
+{
+ const unsigned int hflag_pair = GET_INT_FROM_POINTER(user_data);
+ const char hflag_p = (hflag_pair & 0xff);
+ const char hflag_n = (hflag_pair >> 8);
+
+ return ((BM_elem_flag_test(ele, hflag_p) != 0) &&
+ (BM_elem_flag_test(ele, hflag_n) == 0));
+}
+
+bool BM_elem_cb_check_hflag_enabled(BMElem *ele, void *user_data)
+{
+ const char hflag = GET_INT_FROM_POINTER(user_data);
+
+ return (BM_elem_flag_test(ele, hflag) != 0);
+}
+
+bool BM_elem_cb_check_hflag_disabled(BMElem *ele, void *user_data)
+{
+ const char hflag = GET_INT_FROM_POINTER(user_data);
+
+ return (BM_elem_flag_test(ele, hflag) == 0);
+}
+
+bool BM_elem_cb_check_elem_not_equal(BMElem *ele, void *user_data)
+{
+ return (ele != user_data);
+}
diff --git a/source/blender/bmesh/intern/bmesh_callback_generic.h b/source/blender/bmesh/intern/bmesh_callback_generic.h
new file mode 100644
index 00000000000..3cae01d417f
--- /dev/null
+++ b/source/blender/bmesh/intern/bmesh_callback_generic.h
@@ -0,0 +1,45 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __BMESH_CALLBACK_GENERIC_H__
+#define __BMESH_CALLBACK_GENERIC_H__
+
+/** \file blender/bmesh/intern/bmesh_callback_generic.h
+ * \ingroup bmesh
+ */
+
+bool BM_elem_cb_check_hflag_enabled(BMElem *, void *user_data);
+bool BM_elem_cb_check_hflag_disabled(BMElem *, void *user_data);
+bool BM_elem_cb_check_hflag_ex(BMElem *, void *user_data);
+bool BM_elem_cb_check_elem_not_equal(BMElem *ele, void *user_data);
+
+#define BM_elem_cb_check_hflag_ex_simple(type, hflag_p, hflag_n) \
+ (bool (*)(type, void *))BM_elem_cb_check_hflag_ex, \
+ SET_UINT_IN_POINTER(((hflag_p) | (hflag_n << 8)))
+
+#define BM_elem_cb_check_hflag_enabled_simple(type, hflag_p) \
+ (bool (*)(type, void *))BM_elem_cb_check_hflag_enabled, \
+ SET_UINT_IN_POINTER((hflag_p))
+
+#define BM_elem_cb_check_hflag_disabled_simple(type, hflag_n) \
+ (bool (*)(type, void *))BM_elem_cb_check_hflag_disabled, \
+ SET_UINT_IN_POINTER(hflag_n)
+
+#endif /* __BMESH_CALLBACK_GENERIC_H__ */
diff --git a/source/blender/bmesh/intern/bmesh_construct.c b/source/blender/bmesh/intern/bmesh_construct.c
index e0348fea636..7664108f348 100644
--- a/source/blender/bmesh/intern/bmesh_construct.c
+++ b/source/blender/bmesh/intern/bmesh_construct.c
@@ -46,9 +46,41 @@
#define SELECT 1
+/**
+ * Fill in an edge array from a vertex array (connected polygon loop).
+ *
+ * \returns false if any edges aren't found .
+ */
+bool BM_edges_from_verts(BMEdge **edge_arr, BMVert **vert_arr, const int len)
+{
+ int i, i_prev = len - 1;
+ for (i = 0; i < len; i++) {
+ edge_arr[i_prev] = BM_edge_exists(vert_arr[i_prev], vert_arr[i]);
+ if (edge_arr[i_prev] == NULL) {
+ return false;
+ }
+ i_prev = i;
+ }
+ return true;
+}
+
+/**
+ * Fill in an edge array from a vertex array (connected polygon loop).
+ * Creating edges as-needed.
+ */
+void BM_edges_from_verts_ensure(BMesh *bm, BMEdge **edge_arr, BMVert **vert_arr, const int len)
+{
+ int i, i_prev = len - 1;
+ for (i = 0; i < len; i++) {
+ edge_arr[i_prev] = BM_edge_create(bm, vert_arr[i_prev], vert_arr[i], NULL, BM_CREATE_NO_DOUBLE);
+ i_prev = i;
+ }
+}
+
/* prototypes */
-static void bm_loop_attrs_copy(BMesh *source_mesh, BMesh *target_mesh,
- const BMLoop *source_loop, BMLoop *target_loop);
+static void bm_loop_attrs_copy(
+ BMesh *source_mesh, BMesh *target_mesh,
+ const BMLoop *source_loop, BMLoop *target_loop);
/**
* \brief Make Quad/Triangle
@@ -64,9 +96,10 @@ static void bm_loop_attrs_copy(BMesh *source_mesh, BMesh *target_mesh,
* of the vertices in the vertex array.
*/
-BMFace *BM_face_create_quad_tri(BMesh *bm,
- BMVert *v1, BMVert *v2, BMVert *v3, BMVert *v4,
- const BMFace *f_example, const eBMCreateFlag create_flag)
+BMFace *BM_face_create_quad_tri(
+ BMesh *bm,
+ BMVert *v1, BMVert *v2, BMVert *v3, BMVert *v4,
+ const BMFace *f_example, const eBMCreateFlag create_flag)
{
BMVert *vtar[4] = {v1, v2, v3, v4};
return BM_face_create_verts(bm, vtar, v4 ? 4 : 3, f_example, create_flag, true);
@@ -81,8 +114,9 @@ BMFace *BM_face_create_quad_tri(BMesh *bm,
* this is done since the face may not be completely surrounded by faces,
* this way: a quad with 2 connected quads on either side will still get all 4 loops updated
*/
-void BM_face_copy_shared(BMesh *bm, BMFace *f,
- BMElemFilterFunc filter_fn, void *user_data)
+void BM_face_copy_shared(
+ BMesh *bm, BMFace *f,
+ BMElemFilterFunc filter_fn, void *user_data)
{
BMLoop *l_first;
BMLoop *l_iter;
@@ -132,155 +166,113 @@ void BM_face_copy_shared(BMesh *bm, BMFace *f,
}
/**
- * \brief Make NGon
+ * Given an array of edges,
+ * order them using the winding defined by \a v1 & \a v2
+ * into \a edges_sort & \a verts_sort.
*
- * Makes an ngon from an unordered list of edges. \a v1 and \a v2
- * must be the verts defining edges[0],
- * and define the winding of the new face.
- *
- * \a edges are not required to be ordered, simply to to form
- * a single closed loop as a whole.
- *
- * \note While this function will work fine when the edges
- * are already sorted, if the edges are always going to be sorted,
- * #BM_face_create should be considered over this function as it
- * avoids some unnecessary work.
+ * All arrays must be \a len long.
*/
-BMFace *BM_face_create_ngon(BMesh *bm, BMVert *v1, BMVert *v2, BMEdge **edges, const int len,
- const BMFace *f_example, const eBMCreateFlag create_flag)
+static bool bm_edges_sort_winding(
+ BMVert *v1, BMVert *v2,
+ BMEdge **edges, const int len,
+ BMEdge **edges_sort, BMVert **verts_sort)
{
- BMEdge **edges_sort = BLI_array_alloca(edges_sort, len);
- BMVert **verts_sort = BLI_array_alloca(verts_sort, len + 1);
- int esort_index = 0;
- int vsort_index = 0;
-
- BMFace *f = NULL;
- BMEdge *e;
- BMVert *v, *ev1, *ev2;
+ BMEdge *e_iter, *e_first;
+ BMVert *v_iter;
int i;
- bool is_v1_found, is_reverse;
-
- /* this code is hideous, yeek. I'll have to think about ways of
- * cleaning it up. basically, it now combines the old BM_face_create_ngon
- * _and_ the old bmesh_mf functions, so its kindof smashed together
- * - joeedh */
-
- BLI_assert(len && v1 && v2 && edges && bm);
-
- /* put edges in correct order */
+ /* all flags _must_ be cleared on exit! */
for (i = 0; i < len; i++) {
BM_ELEM_API_FLAG_ENABLE(edges[i], _FLAG_MF);
+ BM_ELEM_API_FLAG_ENABLE(edges[i]->v1, _FLAG_MV);
+ BM_ELEM_API_FLAG_ENABLE(edges[i]->v2, _FLAG_MV);
}
- ev1 = edges[0]->v1;
- ev2 = edges[0]->v2;
-
- BLI_assert(ELEM(v1, ev1, ev2) && ELEM(v2, ev1, ev2));
-
- if (v1 == ev2) {
- /* Swapping here improves performance and consistency of face
- * structure in the special case that the edges are already in
- * the correct order and winding */
- SWAP(BMVert *, ev1, ev2);
- }
-
- verts_sort[vsort_index++] = ev1;
- v = ev2;
- e = edges[0];
+ /* find first edge */
+ i = 0;
+ v_iter = v1;
+ e_iter = e_first = v1->e;
do {
- BMEdge *e2 = e;
-
- /* vertex array is (len + 1) */
- if (UNLIKELY(vsort_index > len)) {
- goto err; /* vertex in loop twice */
+ if (BM_ELEM_API_FLAG_TEST(e_iter, _FLAG_MF) &&
+ (BM_edge_other_vert(e_iter, v_iter) == v2))
+ {
+ i = 1;
+ break;
}
+ } while ((e_iter = bmesh_disk_edge_next(e_iter, v_iter)) != e_first);
+ if (i == 0) {
+ goto error;
+ }
- verts_sort[vsort_index++] = v;
- edges_sort[esort_index++] = e;
-
- /* we only flag the verts to check if they are in the face more than once */
- BM_ELEM_API_FLAG_ENABLE(v, _FLAG_MV);
-
- do {
- e2 = bmesh_disk_edge_next(e2, v);
- if (e2 != e && BM_ELEM_API_FLAG_TEST(e2, _FLAG_MF)) {
- v = BM_edge_other_vert(e2, v);
- break;
+ i = 0;
+ do {
+ /* entering loop will always succeed */
+ if (BM_ELEM_API_FLAG_TEST(e_iter, _FLAG_MF)) {
+ if (UNLIKELY(BM_ELEM_API_FLAG_TEST(v_iter, _FLAG_MV) == false)) {
+ /* vert is in loop multiple times */
+ goto error;
}
- } while (e2 != e);
- if (UNLIKELY(e2 == e)) {
- goto err; /* the edges do not form a closed loop */
- }
+ BM_ELEM_API_FLAG_DISABLE(e_iter, _FLAG_MF);
+ edges_sort[i] = e_iter;
- e = e2;
- } while (e != edges[0]);
+ BM_ELEM_API_FLAG_DISABLE(v_iter, _FLAG_MV);
+ verts_sort[i] = v_iter;
- if (UNLIKELY(esort_index != len)) {
- goto err; /* we didn't use all edges in forming the boundary loop */
- }
+ i += 1;
- /* ok, edges are in correct order, now ensure they are going
- * in the correct direction */
- is_v1_found = is_reverse = false;
- for (i = 0; i < len; i++) {
- if (BM_vert_in_edge(edges_sort[i], v1)) {
- /* see if v1 and v2 are in the same edge */
- if (BM_vert_in_edge(edges_sort[i], v2)) {
- /* if v1 is shared by the *next* edge, then the winding
- * is incorrect */
- if (BM_vert_in_edge(edges_sort[(i + 1) % len], v1)) {
- is_reverse = true;
- break;
+ /* walk onto the next vertex */
+ v_iter = BM_edge_other_vert(e_iter, v_iter);
+ if (i == len) {
+ if (UNLIKELY(v_iter != verts_sort[0])) {
+ goto error;
}
+ break;
}
- is_v1_found = true;
- }
-
- if ((is_v1_found == false) && BM_vert_in_edge(edges_sort[i], v2)) {
- is_reverse = true;
- break;
+ e_first = e_iter;
}
- }
+ } while ((e_iter = bmesh_disk_edge_next(e_iter, v_iter)) != e_first);
- if (is_reverse) {
- for (i = 0; i < len / 2; i++) {
- v = verts_sort[i];
- verts_sort[i] = verts_sort[len - i - 1];
- verts_sort[len - i - 1] = v;
- }
+ if (i == len) {
+ return true;
}
+error:
for (i = 0; i < len; i++) {
- edges_sort[i] = BM_edge_exists(verts_sort[i], verts_sort[(i + 1) % len]);
- if (UNLIKELY(edges_sort[i] == NULL)) {
- goto err;
- }
-
- /* check if vert is in face more than once. if the flag is disabled. we've already visited */
- if (UNLIKELY(!BM_ELEM_API_FLAG_TEST(verts_sort[i], _FLAG_MV))) {
- goto err;
- }
- BM_ELEM_API_FLAG_DISABLE(verts_sort[i], _FLAG_MV);
+ BM_ELEM_API_FLAG_DISABLE(edges[i], _FLAG_MF);
+ BM_ELEM_API_FLAG_DISABLE(edges[i]->v1, _FLAG_MV);
+ BM_ELEM_API_FLAG_DISABLE(edges[i]->v2, _FLAG_MV);
}
- f = BM_face_create(bm, verts_sort, edges_sort, len, f_example, create_flag);
+ return false;
+}
- /* clean up flags */
- for (i = 0; i < len; i++) {
- BM_ELEM_API_FLAG_DISABLE(edges_sort[i], _FLAG_MF);
- }
+/**
+ * \brief Make NGon
+ *
+ * Makes an ngon from an unordered list of edges.
+ * Verts \a v1 and \a v2 define the winding of the new face.
+ *
+ * \a edges are not required to be ordered, simply to to form
+ * a single closed loop as a whole.
+ *
+ * \note While this function will work fine when the edges
+ * are already sorted, if the edges are always going to be sorted,
+ * #BM_face_create should be considered over this function as it
+ * avoids some unnecessary work.
+ */
+BMFace *BM_face_create_ngon(
+ BMesh *bm, BMVert *v1, BMVert *v2, BMEdge **edges, const int len,
+ const BMFace *f_example, const eBMCreateFlag create_flag)
+{
+ BMEdge **edges_sort = BLI_array_alloca(edges_sort, len);
+ BMVert **verts_sort = BLI_array_alloca(verts_sort, len);
- return f;
+ BLI_assert(len && v1 && v2 && edges && bm);
-err:
- for (i = 0; i < len; i++) {
- BM_ELEM_API_FLAG_DISABLE(edges[i], _FLAG_MF);
- }
- for (i = 0; i < vsort_index; i++) {
- BM_ELEM_API_FLAG_DISABLE(verts_sort[i], _FLAG_MV);
+ if (bm_edges_sort_winding(v1, v2, edges, len, edges_sort, verts_sort)) {
+ return BM_face_create(bm, verts_sort, edges_sort, len, f_example, create_flag);
}
return NULL;
@@ -294,9 +286,10 @@ err:
* - Optionally create edges between vertices.
* - Uses verts so no need to find edges (handy when you only have verts)
*/
-BMFace *BM_face_create_ngon_verts(BMesh *bm, BMVert **vert_arr, const int len,
- const BMFace *f_example, const eBMCreateFlag create_flag,
- const bool calc_winding, const bool create_edges)
+BMFace *BM_face_create_ngon_verts(
+ BMesh *bm, BMVert **vert_arr, const int len,
+ const BMFace *f_example, const eBMCreateFlag create_flag,
+ const bool calc_winding, const bool create_edges)
{
BMEdge **edge_arr = BLI_array_alloca(edge_arr, len);
unsigned int winding[2] = {0, 0};
@@ -375,8 +368,9 @@ BMFace *BM_face_create_ngon_verts(BMesh *bm, BMVert **vert_arr, const int len,
*
* \note Since this is a vcloud there is no direction.
*/
-BMFace *BM_face_create_ngon_vcloud(BMesh *bm, BMVert **vert_arr, int len,
- const BMFace *f_example, const eBMCreateFlag create_flag)
+BMFace *BM_face_create_ngon_vcloud(
+ BMesh *bm, BMVert **vert_arr, int len,
+ const BMFace *f_example, const eBMCreateFlag create_flag)
{
struct SortIntByFloat *vang = BLI_array_alloca(vang, len);
BMVert **vert_arr_map = BLI_array_alloca(vert_arr_map, len);
@@ -497,8 +491,9 @@ BMFace *BM_face_create_ngon_vcloud(BMesh *bm, BMVert **vert_arr, int len,
/*************************************************************/
-static void bm_vert_attrs_copy(BMesh *source_mesh, BMesh *target_mesh,
- const BMVert *source_vertex, BMVert *target_vertex)
+static void bm_vert_attrs_copy(
+ BMesh *source_mesh, BMesh *target_mesh,
+ const BMVert *source_vertex, BMVert *target_vertex)
{
if ((source_mesh == target_mesh) && (source_vertex == target_vertex)) {
BLI_assert(!"BMVert: source and targer match");
@@ -510,8 +505,9 @@ static void bm_vert_attrs_copy(BMesh *source_mesh, BMesh *target_mesh,
source_vertex->head.data, &target_vertex->head.data);
}
-static void bm_edge_attrs_copy(BMesh *source_mesh, BMesh *target_mesh,
- const BMEdge *source_edge, BMEdge *target_edge)
+static void bm_edge_attrs_copy(
+ BMesh *source_mesh, BMesh *target_mesh,
+ const BMEdge *source_edge, BMEdge *target_edge)
{
if ((source_mesh == target_mesh) && (source_edge == target_edge)) {
BLI_assert(!"BMEdge: source and targer match");
@@ -522,8 +518,9 @@ static void bm_edge_attrs_copy(BMesh *source_mesh, BMesh *target_mesh,
source_edge->head.data, &target_edge->head.data);
}
-static void bm_loop_attrs_copy(BMesh *source_mesh, BMesh *target_mesh,
- const BMLoop *source_loop, BMLoop *target_loop)
+static void bm_loop_attrs_copy(
+ BMesh *source_mesh, BMesh *target_mesh,
+ const BMLoop *source_loop, BMLoop *target_loop)
{
if ((source_mesh == target_mesh) && (source_loop == target_loop)) {
BLI_assert(!"BMLoop: source and targer match");
@@ -534,8 +531,9 @@ static void bm_loop_attrs_copy(BMesh *source_mesh, BMesh *target_mesh,
source_loop->head.data, &target_loop->head.data);
}
-static void bm_face_attrs_copy(BMesh *source_mesh, BMesh *target_mesh,
- const BMFace *source_face, BMFace *target_face)
+static void bm_face_attrs_copy(
+ BMesh *source_mesh, BMesh *target_mesh,
+ const BMFace *source_face, BMFace *target_face)
{
if ((source_mesh == target_mesh) && (source_face == target_face)) {
BLI_assert(!"BMFace: source and targer match");
@@ -555,8 +553,9 @@ static void bm_face_attrs_copy(BMesh *source_mesh, BMesh *target_mesh,
* Copies attributes, e.g. customdata, header flags, etc, from one element
* to another of the same type.
*/
-void BM_elem_attrs_copy_ex(BMesh *bm_src, BMesh *bm_dst, const void *ele_src_v, void *ele_dst_v,
- const char hflag_mask)
+void BM_elem_attrs_copy_ex(
+ BMesh *bm_src, BMesh *bm_dst, const void *ele_src_v, void *ele_dst_v,
+ const char hflag_mask)
{
const BMHeader *ele_src = ele_src_v;
BMHeader *ele_dst = ele_dst_v;
@@ -621,9 +620,10 @@ void BM_elem_select_copy(BMesh *bm_dst, BMesh *UNUSED(bm_src), void *ele_dst_v,
}
/* helper function for 'BM_mesh_copy' */
-static BMFace *bm_mesh_copy_new_face(BMesh *bm_new, BMesh *bm_old,
- BMVert **vtable, BMEdge **etable,
- BMFace *f)
+static BMFace *bm_mesh_copy_new_face(
+ BMesh *bm_new, BMesh *bm_old,
+ BMVert **vtable, BMEdge **etable,
+ BMFace *f)
{
BMLoop **loops = BLI_array_alloca(loops, f->len);
BMVert **verts = BLI_array_alloca(verts, f->len);
diff --git a/source/blender/bmesh/intern/bmesh_construct.h b/source/blender/bmesh/intern/bmesh_construct.h
index 12d3a4bd474..29503679547 100644
--- a/source/blender/bmesh/intern/bmesh_construct.h
+++ b/source/blender/bmesh/intern/bmesh_construct.h
@@ -29,23 +29,32 @@
struct BMAllocTemplate;
-BMFace *BM_face_create_quad_tri(BMesh *bm, BMVert *v1, BMVert *v2, BMVert *v3, BMVert *v4,
- const BMFace *f_example, const eBMCreateFlag create_flag);
+bool BM_edges_from_verts(BMEdge **edge_arr, BMVert **vert_arr, const int len);
+void BM_edges_from_verts_ensure(BMesh *bm, BMEdge **edge_arr, BMVert **vert_arr, const int len);
-void BM_face_copy_shared(BMesh *bm, BMFace *f,
- BMElemFilterFunc filter_fn, void *user_data);
+BMFace *BM_face_create_quad_tri(
+ BMesh *bm, BMVert *v1, BMVert *v2, BMVert *v3, BMVert *v4,
+ const BMFace *f_example, const eBMCreateFlag create_flag);
-BMFace *BM_face_create_ngon(BMesh *bm, BMVert *v1, BMVert *v2, BMEdge **edges, const int len,
- const BMFace *f_example, const eBMCreateFlag create_flag);
-BMFace *BM_face_create_ngon_verts(BMesh *bm, BMVert **vert_arr, const int len,
- const BMFace *f_example, const eBMCreateFlag create_flag,
- const bool calc_winding, const bool create_edges);
+void BM_face_copy_shared(
+ BMesh *bm, BMFace *f,
+ BMElemFilterFunc filter_fn, void *user_data);
-BMFace *BM_face_create_ngon_vcloud(BMesh *bm, BMVert **vert_arr, int len,
- const BMFace *f_example, const eBMCreateFlag create_flag);
+BMFace *BM_face_create_ngon(
+ BMesh *bm, BMVert *v1, BMVert *v2, BMEdge **edges, const int len,
+ const BMFace *f_example, const eBMCreateFlag create_flag);
+BMFace *BM_face_create_ngon_verts(
+ BMesh *bm, BMVert **vert_arr, const int len,
+ const BMFace *f_example, const eBMCreateFlag create_flag,
+ const bool calc_winding, const bool create_edges);
-void BM_elem_attrs_copy_ex(BMesh *bm_src, BMesh *bm_dst, const void *ele_src_v, void *ele_dst_v,
- const char hflag_mask);
+BMFace *BM_face_create_ngon_vcloud(
+ BMesh *bm, BMVert **vert_arr, int len,
+ const BMFace *f_example, const eBMCreateFlag create_flag);
+
+void BM_elem_attrs_copy_ex(
+ BMesh *bm_src, BMesh *bm_dst, const void *ele_src_v, void *ele_dst_v,
+ const char hflag_mask);
void BM_elem_attrs_copy(BMesh *bm_src, BMesh *bm_dst, const void *ele_src_v, void *ele_dst_v);
void BM_elem_select_copy(BMesh *bm_dst, BMesh *bm_src, void *ele_dst_v, const void *ele_src_v);
diff --git a/source/blender/bmesh/intern/bmesh_core.c b/source/blender/bmesh/intern/bmesh_core.c
index eb7b9f78ef4..e67aa1da340 100644
--- a/source/blender/bmesh/intern/bmesh_core.c
+++ b/source/blender/bmesh/intern/bmesh_core.c
@@ -31,10 +31,10 @@
#include "BLI_math_vector.h"
#include "BLI_array.h"
#include "BLI_alloca.h"
-#include "BLI_smallhash.h"
+#include "BLI_linklist_stack.h"
#include "BLI_stackdefines.h"
-#include "BLF_translation.h"
+#include "BLT_translation.h"
#include "BKE_DerivedMesh.h"
@@ -57,8 +57,9 @@
/**
* \brief Main function for creating a new vertex.
*/
-BMVert *BM_vert_create(BMesh *bm, const float co[3],
- const BMVert *v_example, const eBMCreateFlag create_flag)
+BMVert *BM_vert_create(
+ BMesh *bm, const float co[3],
+ const BMVert *v_example, const eBMCreateFlag create_flag)
{
BMVert *v = BLI_mempool_alloc(bm->vpool);
@@ -88,7 +89,7 @@ BMVert *BM_vert_create(BMesh *bm, const float co[3],
else {
zero_v3(v->co);
}
- zero_v3(v->no);
+ /* 'v->no' set below */
v->e = NULL;
/* --- done --- */
@@ -107,6 +108,7 @@ BMVert *BM_vert_create(BMesh *bm, const float co[3],
if (v_example) {
int *keyi;
+ /* handles 'v->no' too */
BM_elem_attrs_copy(bm, bm, v_example, v);
/* exception: don't copy the original shapekey index */
@@ -117,6 +119,15 @@ BMVert *BM_vert_create(BMesh *bm, const float co[3],
}
else {
CustomData_bmesh_set_default(&bm->vdata, &v->head.data);
+ zero_v3(v->no);
+ }
+ }
+ else {
+ if (v_example) {
+ copy_v3_v3(v->no, v_example->no);
+ }
+ else {
+ zero_v3(v->no);
}
}
@@ -131,8 +142,9 @@ BMVert *BM_vert_create(BMesh *bm, const float co[3],
* \note Duplicate edges are supported by the API however users should _never_ see them.
* so unless you need a unique edge or know the edge won't exist, you should call with \a no_double = true
*/
-BMEdge *BM_edge_create(BMesh *bm, BMVert *v1, BMVert *v2,
- const BMEdge *e_example, const eBMCreateFlag create_flag)
+BMEdge *BM_edge_create(
+ BMesh *bm, BMVert *v1, BMVert *v2,
+ const BMEdge *e_example, const eBMCreateFlag create_flag)
{
BMEdge *e;
@@ -194,8 +206,9 @@ BMEdge *BM_edge_create(BMesh *bm, BMVert *v1, BMVert *v2,
return e;
}
-static BMLoop *bm_loop_create(BMesh *bm, BMVert *v, BMEdge *e, BMFace *f,
- const BMLoop *l_example, const eBMCreateFlag create_flag)
+static BMLoop *bm_loop_create(
+ BMesh *bm, BMVert *v, BMEdge *e, BMFace *f,
+ const BMLoop *l_example, const eBMCreateFlag create_flag)
{
BMLoop *l = NULL;
@@ -213,8 +226,8 @@ static BMLoop *bm_loop_create(BMesh *bm, BMVert *v, BMEdge *e, BMFace *f,
BM_elem_index_set(l, -1); /* set_ok_invalid */
#endif
- l->head.hflag = 0;
l->head.htype = BM_LOOP;
+ l->head.hflag = 0;
l->head.api_flag = 0;
l->v = v;
@@ -244,8 +257,9 @@ static BMLoop *bm_loop_create(BMesh *bm, BMVert *v, BMEdge *e, BMFace *f,
return l;
}
-static BMLoop *bm_face_boundary_add(BMesh *bm, BMFace *f, BMVert *startv, BMEdge *starte,
- const eBMCreateFlag create_flag)
+static BMLoop *bm_face_boundary_add(
+ BMesh *bm, BMFace *f, BMVert *startv, BMEdge *starte,
+ const eBMCreateFlag create_flag)
{
#ifdef USE_BMESH_HOLES
BMLoopList *lst = BLI_mempool_calloc(bm->looplistpool);
@@ -266,8 +280,9 @@ static BMLoop *bm_face_boundary_add(BMesh *bm, BMFace *f, BMVert *startv, BMEdge
return l;
}
-BMFace *BM_face_copy(BMesh *bm_dst, BMesh *bm_src, BMFace *f,
- const bool copy_verts, const bool copy_edges)
+BMFace *BM_face_copy(
+ BMesh *bm_dst, BMesh *bm_src, BMFace *f,
+ const bool copy_verts, const bool copy_edges)
{
BMVert **verts = BLI_array_alloca(verts, f->len);
BMEdge **edges = BLI_array_alloca(edges, f->len);
@@ -362,7 +377,8 @@ BLI_INLINE BMFace *bm_face_create__internal(BMesh *bm)
f->l_first = NULL;
#endif
f->len = 0;
- zero_v3(f->no);
+ /* caller must initialize */
+ // zero_v3(f->no);
f->mat_nr = 0;
/* --- done --- */
@@ -389,8 +405,9 @@ BLI_INLINE BMFace *bm_face_create__internal(BMesh *bm)
* \param len Length of the face
* \param create_flag Options for creating the face
*/
-BMFace *BM_face_create(BMesh *bm, BMVert **verts, BMEdge **edges, const int len,
- const BMFace *f_example, const eBMCreateFlag create_flag)
+BMFace *BM_face_create(
+ BMesh *bm, BMVert **verts, BMEdge **edges, const int len,
+ const BMFace *f_example, const eBMCreateFlag create_flag)
{
BMFace *f = NULL;
BMLoop *l, *startl, *lastl;
@@ -443,6 +460,15 @@ BMFace *BM_face_create(BMesh *bm, BMVert **verts, BMEdge **edges, const int len,
}
else {
CustomData_bmesh_set_default(&bm->pdata, &f->head.data);
+ zero_v3(f->no);
+ }
+ }
+ else {
+ if (f_example) {
+ copy_v3_v3(f->no, f_example->no);
+ }
+ else {
+ zero_v3(f->no);
}
}
@@ -454,25 +480,18 @@ BMFace *BM_face_create(BMesh *bm, BMVert **verts, BMEdge **edges, const int len,
/**
* Wrapper for #BM_face_create when you don't have an edge array
*/
-BMFace *BM_face_create_verts(BMesh *bm, BMVert **vert_arr, const int len,
- const BMFace *f_example, const eBMCreateFlag create_flag, const bool create_edges)
+BMFace *BM_face_create_verts(
+ BMesh *bm, BMVert **vert_arr, const int len,
+ const BMFace *f_example, const eBMCreateFlag create_flag, const bool create_edges)
{
BMEdge **edge_arr = BLI_array_alloca(edge_arr, len);
- int i, i_prev = len - 1;
if (create_edges) {
- for (i = 0; i < len; i++) {
- edge_arr[i_prev] = BM_edge_create(bm, vert_arr[i_prev], vert_arr[i], NULL, BM_CREATE_NO_DOUBLE);
- i_prev = i;
- }
+ BM_edges_from_verts_ensure(bm, edge_arr, vert_arr, len);
}
else {
- for (i = 0; i < len; i++) {
- edge_arr[i_prev] = BM_edge_exists(vert_arr[i_prev], vert_arr[i]);
- if (edge_arr[i_prev] == NULL) {
- return NULL;
- }
- i_prev = i;
+ if (BM_edges_from_verts(edge_arr, vert_arr, len) == false) {
+ return NULL;
}
}
@@ -493,17 +512,17 @@ int bmesh_elem_check(void *element, const char htype)
int err = 0;
if (!element)
- return 1;
+ return (1 << 0);
if (head->htype != htype)
- return 2;
+ return (1 << 1);
switch (htype) {
case BM_VERT:
{
BMVert *v = element;
if (v->e && v->e->head.htype != BM_EDGE) {
- err |= 4;
+ err |= (1 << 2);
}
break;
}
@@ -511,20 +530,20 @@ int bmesh_elem_check(void *element, const char htype)
{
BMEdge *e = element;
if (e->l && e->l->head.htype != BM_LOOP)
- err |= 8;
+ err |= (1 << 3);
if (e->l && e->l->f->head.htype != BM_FACE)
- err |= 16;
+ err |= (1 << 4);
if (e->v1_disk_link.prev == NULL ||
e->v2_disk_link.prev == NULL ||
e->v1_disk_link.next == NULL ||
e->v2_disk_link.next == NULL)
{
- err |= 32;
+ err |= (1 << 5);
}
if (e->l && (e->l->radial_next == NULL || e->l->radial_prev == NULL))
- err |= 64;
+ err |= (1 << 6);
if (e->l && e->l->f->len <= 0)
- err |= 128;
+ err |= (1 << 7);
break;
}
case BM_LOOP:
@@ -533,14 +552,14 @@ int bmesh_elem_check(void *element, const char htype)
int i;
if (l->f->head.htype != BM_FACE)
- err |= 256;
+ err |= (1 << 8);
if (l->e->head.htype != BM_EDGE)
- err |= 512;
+ err |= (1 << 9);
if (l->v->head.htype != BM_VERT)
- err |= 1024;
+ err |= (1 << 10);
if (!BM_vert_in_edge(l->e, l->v)) {
fprintf(stderr, "%s: fatal bmesh error (vert not in edge)! (bmesh internal error)\n", __func__);
- err |= 2048;
+ err |= (1 << 11);
}
if (l->radial_next == NULL || l->radial_prev == NULL)
@@ -1026,8 +1045,9 @@ static bool disk_is_flagged(BMVert *v, const char api_flag)
return false;
}
- if (bmesh_radial_length(l) == 1)
+ if (BM_edge_is_boundary(l->e)) {
return false;
+ }
do {
if (!BM_ELEM_API_FLAG_TEST(l->f, api_flag))
@@ -1111,7 +1131,7 @@ BMFace *BM_faces_join(BMesh *bm, BMFace **faces, int totface, const bool do_del)
if (!d1 && !d2 && !BM_ELEM_API_FLAG_TEST(l_iter->e, _FLAG_JF)) {
/* don't remove an edge it makes up the side of another face
* else this will remove the face as well - campbell */
- if (BM_edge_face_count(l_iter->e) <= 2) {
+ if (!BM_edge_face_count_is_over(l_iter->e, 3)) {
if (do_del) {
BLI_array_append(deledges, l_iter->e);
}
@@ -1307,14 +1327,14 @@ static BMFace *bm_face_create__sfme(BMesh *bm, BMFace *f_example)
*
* \return A BMFace pointer
*/
-BMFace *bmesh_sfme(BMesh *bm, BMFace *f, BMLoop *l_v1, BMLoop *l_v2,
- BMLoop **r_l,
+BMFace *bmesh_sfme(
+ BMesh *bm, BMFace *f, BMLoop *l_v1, BMLoop *l_v2,
+ BMLoop **r_l,
#ifdef USE_BMESH_HOLES
- ListBase *holes,
+ ListBase *holes,
#endif
- BMEdge *e_example,
- const bool no_double
- )
+ BMEdge *e_example,
+ const bool no_double)
{
#ifdef USE_BMESH_HOLES
BMLoopList *lst, *lst2;
@@ -1481,14 +1501,7 @@ BMVert *bmesh_semv(BMesh *bm, BMVert *tv, BMEdge *e, BMEdge **r_e)
bmesh_disk_edge_remove(e_new, tv);
bmesh_disk_edge_remove(e_new, v_new);
- /* remove e from tv's disk cycle */
- bmesh_disk_edge_remove(e, tv);
-
- /* swap out tv for v_new in e */
- bmesh_edge_swapverts(e, tv, v_new);
-
- /* add e to v_new's disk cycle */
- bmesh_disk_edge_append(e, v_new);
+ bmesh_disk_vert_replace(e, v_new, tv);
/* add e_new to v_new's disk cycle */
bmesh_disk_edge_append(e_new, v_new);
@@ -1653,13 +1666,14 @@ BMVert *bmesh_semv(BMesh *bm, BMVert *tv, BMEdge *e, BMEdge **r_e)
* faces with just 2 edges. It is up to the caller to decide what to do with
* these faces.
*/
-BMEdge *bmesh_jekv(BMesh *bm, BMEdge *e_kill, BMVert *v_kill,
- const bool do_del, const bool check_edge_double)
+BMEdge *bmesh_jekv(
+ BMesh *bm, BMEdge *e_kill, BMVert *v_kill,
+ const bool do_del, const bool check_edge_double)
{
BMEdge *e_old;
BMVert *v_old, *tv;
BMLoop *l_kill;
- int len, radlen = 0, i;
+ int radlen = 0, i;
bool halt = false;
#ifndef NDEBUG
bool edok;
@@ -1670,10 +1684,8 @@ BMEdge *bmesh_jekv(BMesh *bm, BMEdge *e_kill, BMVert *v_kill,
if (BM_vert_in_edge(e_kill, v_kill) == 0) {
return NULL;
}
-
- len = bmesh_disk_count(v_kill);
- if (len == 2) {
+ if (bmesh_disk_count_ex(v_kill, 3) == 2) {
#ifndef NDEBUG
int valence1, valence2;
BMLoop *l;
@@ -1700,12 +1712,8 @@ BMEdge *bmesh_jekv(BMesh *bm, BMEdge *e_kill, BMVert *v_kill,
e_splice = BM_edge_exists(tv, v_old);
}
- /* remove e_old from v_kill's disk cycle */
- bmesh_disk_edge_remove(e_old, v_kill);
- /* relink e_old->v_kill to be e_old->tv */
- bmesh_edge_swapverts(e_old, v_kill, tv);
- /* append e_old to tv's disk cycle */
- bmesh_disk_edge_append(e_old, tv);
+ bmesh_disk_vert_replace(e_old, tv, v_kill);
+
/* remove e_kill from tv's disk cycle */
bmesh_disk_edge_remove(e_kill, tv);
@@ -1789,7 +1797,7 @@ BMEdge *bmesh_jekv(BMesh *bm, BMEdge *e_kill, BMVert *v_kill,
if (check_edge_double) {
if (e_splice) {
/* removes e_splice */
- BM_edge_splice(bm, e_splice, e_old);
+ BM_edge_splice(bm, e_old, e_splice);
}
}
@@ -1963,27 +1971,38 @@ bool BM_vert_splice_check_double(BMVert *v_a, BMVert *v_b)
BLI_assert(BM_edge_exists(v_a, v_b) == false);
if (v_a->e && v_b->e) {
- SmallHash visit;
BMEdge *e, *e_first;
- BLI_smallhash_init(&visit);
+#define VERT_VISIT _FLAG_WALK
+ /* tag 'v_a' */
e = e_first = v_a->e;
do {
BMVert *v_other = BM_edge_other_vert(e, v_a);
- BLI_smallhash_insert(&visit, (uintptr_t)v_other, NULL);
+ BLI_assert(!BM_ELEM_API_FLAG_TEST(v_other, VERT_VISIT));
+ BM_ELEM_API_FLAG_ENABLE(v_other, VERT_VISIT);
} while ((e = BM_DISK_EDGE_NEXT(e, v_a)) != e_first);
+ /* check 'v_b' connects to 'v_a' edges */
e = e_first = v_b->e;
do {
BMVert *v_other = BM_edge_other_vert(e, v_b);
- if (BLI_smallhash_haskey(&visit, (uintptr_t)v_other)) {
+ if (BM_ELEM_API_FLAG_TEST(v_other, VERT_VISIT)) {
is_double = true;
break;
}
} while ((e = BM_DISK_EDGE_NEXT(e, v_b)) != e_first);
- BLI_smallhash_release(&visit);
+ /* cleanup */
+ e = e_first = v_a->e;
+ do {
+ BMVert *v_other = BM_edge_other_vert(e, v_a);
+ BLI_assert(BM_ELEM_API_FLAG_TEST(v_other, VERT_VISIT));
+ BM_ELEM_API_FLAG_DISABLE(v_other, VERT_VISIT);
+ } while ((e = BM_DISK_EDGE_NEXT(e, v_a)) != e_first);
+
+#undef VERT_VISIT
+
}
return is_double;
@@ -1992,57 +2011,51 @@ bool BM_vert_splice_check_double(BMVert *v_a, BMVert *v_b)
/**
* \brief Splice Vert
*
- * Merges two verts into one (\a v into \a vtarget).
+ * Merges two verts into one
+ * (\a v_src into \a v_dst, removing \a v_src).
*
* \return Success
*
- * \warning This does't work for collapsing edges,
+ * \warning This doesn't work for collapsing edges,
* where \a v and \a vtarget are connected by an edge
* (assert checks for this case).
*/
-bool BM_vert_splice(BMesh *bm, BMVert *v, BMVert *v_target)
+bool BM_vert_splice(BMesh *bm, BMVert *v_dst, BMVert *v_src)
{
BMEdge *e;
/* verts already spliced */
- if (v == v_target) {
+ if (v_src == v_dst) {
return false;
}
- BLI_assert(BM_vert_pair_share_face_check(v, v_target) == false);
-
- /* move all the edges from v's disk to vtarget's disk */
- while ((e = v->e)) {
-
- /* loop */
- BMLoop *l_first;
- if ((l_first = e->l)) {
- BMLoop *l_iter = l_first;
- do {
- if (l_iter->v == v) {
- l_iter->v = v_target;
- }
- /* else if (l_iter->prev->v == v) {...}
- * (this case will be handled by a different edge) */
- } while ((l_iter = l_iter->radial_next) != l_first);
- }
+ BLI_assert(BM_vert_pair_share_face_check(v_src, v_dst) == false);
- /* disk */
- bmesh_disk_edge_remove(e, v);
- bmesh_edge_swapverts(e, v, v_target);
- bmesh_disk_edge_append(e, v_target);
+ /* move all the edges from 'v_src' disk to 'v_dst' */
+ while ((e = v_src->e)) {
+ bmesh_edge_vert_swap(e, v_dst, v_src);
BLI_assert(e->v1 != e->v2);
}
- BM_CHECK_ELEMENT(v);
- BM_CHECK_ELEMENT(v_target);
+ BM_CHECK_ELEMENT(v_src);
+ BM_CHECK_ELEMENT(v_dst);
- /* v is unused now, and can be killed */
- BM_vert_kill(bm, v);
+ /* 'v_src' is unused now, and can be killed */
+ BM_vert_kill(bm, v_src);
return true;
}
+
+/** \name BM_vert_separate, bmesh_vert_separate and friends
+ * \{ */
+
+/* BM_edge_face_count(e) >= 1 */
+BLI_INLINE bool bm_edge_supports_separate(const BMEdge *e)
+{
+ return (e->l && e->l->radial_next != e->l);
+}
+
/**
* \brief Separate Vert
*
@@ -2054,167 +2067,252 @@ bool BM_vert_splice(BMesh *bm, BMVert *v, BMVert *v_target)
*
* \return Success
*/
-void bmesh_vert_separate(BMesh *bm, BMVert *v, BMVert ***r_vout, int *r_vout_len,
- const bool copy_select)
+void bmesh_vert_separate(
+ BMesh *bm, BMVert *v, BMVert ***r_vout, int *r_vout_len,
+ const bool copy_select)
{
- const int v_edgetot = BM_vert_face_count(v);
- BMEdge **stack = BLI_array_alloca(stack, v_edgetot);
- STACK_DECLARE(stack);
+ int v_edges_num = 0;
- SmallHash visithash;
- BMVert **verts = NULL;
- BMIter eiter, liter;
- BMLoop *l;
- BMEdge *e;
- int i, maxindex;
- BMLoop *l_new;
+ /* Detailed notes on array use since this is stack memory, we have to be careful */
- BLI_smallhash_init_ex(&visithash, v_edgetot);
+ /* newly created vertices, only use when 'r_vout' is set
+ * (total size will be number of fans) */
+ BLI_SMALLSTACK_DECLARE(verts_new, BMVert *);
+ /* fill with edges from the face-fan, clearing on completion
+ * (total size will be max fan edge count) */
+ BLI_SMALLSTACK_DECLARE(edges, BMEdge *);
+ /* temp store edges to walk over when filling 'edges',
+ * (total size will be max radial edges of any edge) */
+ BLI_SMALLSTACK_DECLARE(edges_search, BMEdge *);
- STACK_INIT(stack, v_edgetot);
+ /* number of resulting verts, include self */
+ int verts_num = 1;
+ /* track the total number of edges handled, so we know when we've found the last fan */
+ int edges_found = 0;
- maxindex = 0;
- BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) {
- if (BLI_smallhash_haskey(&visithash, (uintptr_t)e)) {
- continue;
- }
+#define EDGE_VISIT _FLAG_WALK
+ /* count and flag at once */
+ if (v->e) {
+ BMEdge *e_first, *e_iter;
+ e_iter = e_first = v->e;
+ do {
+ v_edges_num += 1;
+
+ BLI_assert(!BM_ELEM_API_FLAG_TEST(e_iter, EDGE_VISIT));
+ BM_ELEM_API_FLAG_ENABLE(e_iter, EDGE_VISIT);
+ } while ((e_iter = bmesh_disk_edge_next(e_iter, v)) != e_first);
+ }
+
+ while (true) {
/* Considering only edges and faces incident on vertex v, walk
- * the edges & faces and assign an index to each connected set */
- BLI_smallhash_insert(&visithash, (uintptr_t)e, SET_INT_IN_POINTER(maxindex));
+ * the edges & collect in the 'edges' list for splitting */
+
+ BMEdge *e = v->e;
+ BM_ELEM_API_FLAG_DISABLE(e, EDGE_VISIT);
+
do {
+ BLI_assert(!BM_ELEM_API_FLAG_TEST(e, EDGE_VISIT));
+ BLI_SMALLSTACK_PUSH(edges, e);
+ edges_found += 1;
+
if (e->l) {
BMLoop *l_iter, *l_first;
l_iter = l_first = e->l;
do {
- l_new = (l_iter->v == v) ? l_iter->prev : l_iter->next;
- BLI_assert(BM_vert_in_edge(l_new->e, v));
- if (!BLI_smallhash_haskey(&visithash, (uintptr_t)l_new->e)) {
- BLI_smallhash_insert(&visithash, (uintptr_t)l_new->e, SET_INT_IN_POINTER(maxindex));
- STACK_PUSH(stack, l_new->e);
+ BMLoop *l_adjacent = (l_iter->v == v) ? l_iter->prev : l_iter->next;
+ BLI_assert(BM_vert_in_edge(l_adjacent->e, v));
+ if (BM_ELEM_API_FLAG_TEST(l_adjacent->e, EDGE_VISIT)) {
+ BM_ELEM_API_FLAG_DISABLE(l_adjacent->e, EDGE_VISIT);
+ BLI_SMALLSTACK_PUSH(edges_search, l_adjacent->e);
}
} while ((l_iter = l_iter->radial_next) != l_first);
}
- } while ((e = STACK_POP(stack)));
-
- maxindex++;
- }
+ } while ((e = BLI_SMALLSTACK_POP(edges_search)));
- /* Make enough verts to split v for each group */
- if (r_vout != NULL) {
- verts = MEM_callocN(sizeof(BMVert *) * maxindex, __func__);
- }
- else {
- verts = BLI_array_alloca(verts, maxindex);
- }
+ /* now we have all edges connected to 'v->e' */
- verts[0] = v;
- for (i = 1; i < maxindex; i++) {
- verts[i] = BM_vert_create(bm, v->co, v, BM_CREATE_NOP);
- if (copy_select) {
- BM_elem_select_copy(bm, bm, verts[i], v);
- }
- }
+ BLI_assert(edges_found <= v_edges_num);
- /* Replace v with the new verts in each group */
-#if 0
- BM_ITER_ELEM (l, &liter, v, BM_LOOPS_OF_VERT) {
- /* call first since its faster then a hash lookup */
- if (l->v != v) {
- continue;
- }
- i = GET_INT_FROM_POINTER(BLI_ghash_lookup(visithash, l->e));
- if (i == 0) {
- continue;
+ if (edges_found == v_edges_num) {
+ /* We're done! The remaining edges in 'edges' form the last fan,
+ * which can be left as is.
+ * if 'edges' were alloc'd it'd be freed here. */
+ break;
}
+ else {
+ BMVert *v_new;
- /* Loops here should always refer to an edge that has v as an
- * endpoint. For each appearance of this vert in a face, there
- * will actually be two iterations: one for the loop heading
- * towards vertex v, and another for the loop heading out from
- * vertex v. Only need to swap the vertex on one of those times,
- * on the outgoing loop. */
+ v_new = BM_vert_create(bm, v->co, v, BM_CREATE_NOP);
+ if (copy_select) {
+ BM_elem_select_copy(bm, bm, v_new, v);
+ }
- /* XXX - because this clobbers the iterator, this *whole* block is commented, see below */
- l->v = verts[i];
- }
-#else
- /* note: this is the same as the commented code above *except* that it doesn't break iterator
- * by modifying data it loops over [#30632], this re-uses the 'stack' variable which is a bit
- * bad practice but save alloc'ing a new array - note, the comment above is useful, keep it
- * if you are tidying up code - campbell */
- STACK_INIT(stack, v_edgetot);
- BM_ITER_ELEM (l, &liter, v, BM_LOOPS_OF_VERT) {
- if (l->v == v) {
- STACK_PUSH(stack, (BMEdge *)l);
- }
- }
- while ((l = (BMLoop *)(STACK_POP(stack)))) {
- if ((i = GET_INT_FROM_POINTER(BLI_smallhash_lookup(&visithash, (uintptr_t)l->e)))) {
- l->v = verts[i];
- }
- }
-#endif
+ while ((e = BLI_SMALLSTACK_POP(edges))) {
+ bmesh_edge_vert_swap(e, v_new, v);
+ }
- BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) {
- i = GET_INT_FROM_POINTER(BLI_smallhash_lookup(&visithash, (uintptr_t)e));
- if (i == 0) {
- continue;
+ if (r_vout) {
+ BLI_SMALLSTACK_PUSH(verts_new, v_new);
+ }
+ verts_num += 1;
}
-
- BLI_assert(e->v1 == v || e->v2 == v);
- bmesh_disk_edge_remove(e, v);
- bmesh_edge_swapverts(e, v, verts[i]);
- bmesh_disk_edge_append(e, verts[i]);
}
- BLI_smallhash_release(&visithash);
+#undef EDGE_VISIT
- for (i = 0; i < maxindex; i++) {
- BM_CHECK_ELEMENT(verts[i]);
- }
+ /* flags are clean now, handle return values */
if (r_vout_len != NULL) {
- *r_vout_len = maxindex;
+ *r_vout_len = verts_num;
}
if (r_vout != NULL) {
+ BMVert **verts;
+
+ verts = MEM_mallocN(sizeof(BMVert *) * verts_num, __func__);
*r_vout = verts;
+
+ verts[0] = v;
+ BLI_SMALLSTACK_AS_TABLE(verts_new, &verts[1]);
}
}
/**
+ * Utility function for #BM_vert_separate
+ *
+ * Takes a list of edges, which have been split from their original.
+ *
+ * Any edges which failed to split off in #bmesh_vert_separate will be merged back into the original edge.
+ *
+ * \param edges_separate
+ * A list-of-lists, each list is from a single original edge (the first edge is the original),
+ * Check for duplicates (not just with the first) but between all.
+ * This is O(n2) but radial edges are very rarely >2 and almost never >~10.
+ *
+ * \note typically its best to avoid creating the data in the first place,
+ * but inspecting all loops connectivity is quite involved.
+ *
+ * \note this function looks like it could become slow,
+ * but in common cases its only going to iterate a few times.
+ */
+static void bmesh_vert_separate__cleanup(BMesh *bm, LinkNode *edges_separate)
+{
+ do {
+ LinkNode *n_orig = edges_separate->link;
+ do {
+ BMEdge *e_orig = n_orig->link;
+ LinkNode *n_step = n_orig->next;
+ LinkNode *n_prev = n_orig;
+ do {
+ BMEdge *e = n_step->link;
+ BLI_assert(e != e_orig);
+ if ((e->v1 == e_orig->v1) && (e->v2 == e_orig->v2)) {
+ BM_edge_splice(bm, e_orig, e);
+ n_prev->next = n_step->next;
+ n_step = n_prev;
+ }
+ } while ((n_prev = n_step),
+ (n_step = n_step->next));
+
+ } while ((n_orig = n_orig->next) && n_orig->next);
+ } while ((edges_separate = edges_separate->next));
+}
+
+/**
* High level function which wraps both #bmesh_vert_separate and #bmesh_edge_separate
*/
-void BM_vert_separate(BMesh *bm, BMVert *v, BMVert ***r_vout, int *r_vout_len,
- BMEdge **e_in, int e_in_len)
+void BM_vert_separate(
+ BMesh *bm, BMVert *v,
+ BMEdge **e_in, int e_in_len,
+ const bool copy_select,
+ BMVert ***r_vout, int *r_vout_len)
{
+ LinkNode *edges_separate = NULL;
int i;
for (i = 0; i < e_in_len; i++) {
BMEdge *e = e_in[i];
- if (e->l && BM_vert_in_edge(e, v)) {
- bmesh_edge_separate(bm, e, e->l, false);
+ if (bm_edge_supports_separate(e)) {
+ LinkNode *edges_orig = NULL;
+ do {
+ BMLoop *l_sep = e->l;
+ bmesh_edge_separate(bm, e, l_sep, copy_select);
+ BLI_linklist_prepend_alloca(&edges_orig, l_sep->e);
+ BLI_assert(e != l_sep->e);
+ } while (bm_edge_supports_separate(e));
+ BLI_linklist_prepend_alloca(&edges_orig, e);
+ BLI_linklist_prepend_alloca(&edges_separate, edges_orig);
}
}
- bmesh_vert_separate(bm, v, r_vout, r_vout_len, false);
+ bmesh_vert_separate(bm, v, r_vout, r_vout_len, copy_select);
+
+ if (edges_separate) {
+ bmesh_vert_separate__cleanup(bm, edges_separate);
+ }
}
+
+/**
+ * A version of #BM_vert_separate which takes a flag.
+ */
+void BM_vert_separate_hflag(
+ BMesh *bm, BMVert *v,
+ const char hflag,
+ const bool copy_select,
+ BMVert ***r_vout, int *r_vout_len)
+{
+ LinkNode *edges_separate = NULL;
+ BMEdge *e_iter, *e_first;
+
+ e_iter = e_first = v->e;
+ do {
+ if (BM_elem_flag_test(e_iter, hflag)) {
+ BMEdge *e = e_iter;
+ if (bm_edge_supports_separate(e)) {
+ LinkNode *edges_orig = NULL;
+ do {
+ BMLoop *l_sep = e->l;
+ bmesh_edge_separate(bm, e, l_sep, copy_select);
+ /* trick to avoid looping over seperated edges */
+ if (edges_separate == NULL && edges_orig == NULL) {
+ e_first = l_sep->e;
+ }
+ BLI_linklist_prepend_alloca(&edges_orig, l_sep->e);
+ BLI_assert(e != l_sep->e);
+ } while (bm_edge_supports_separate(e));
+ BLI_linklist_prepend_alloca(&edges_orig, e);
+ BLI_linklist_prepend_alloca(&edges_separate, edges_orig);
+ }
+ }
+ } while ((e_iter = BM_DISK_EDGE_NEXT(e_iter, v)) != e_first);
+
+ bmesh_vert_separate(bm, v, r_vout, r_vout_len, copy_select);
+
+ if (edges_separate) {
+ bmesh_vert_separate__cleanup(bm, edges_separate);
+ }
+}
+
+/** \} */
+
+
/**
* \brief Splice Edge
*
* Splice two unique edges which share the same two vertices into one edge.
+ * (\a e_src into \a e_dst, removing e_src).
*
* \return Success
*
* \note Edges must already have the same vertices.
*/
-bool BM_edge_splice(BMesh *bm, BMEdge *e, BMEdge *e_target)
+bool BM_edge_splice(BMesh *bm, BMEdge *e_dst, BMEdge *e_src)
{
BMLoop *l;
- if (!BM_vert_in_edge(e, e_target->v1) || !BM_vert_in_edge(e, e_target->v2)) {
+ if (!BM_vert_in_edge(e_src, e_dst->v1) || !BM_vert_in_edge(e_src, e_dst->v2)) {
/* not the same vertices can't splice */
/* the caller should really make sure this doesn't happen ever
@@ -2224,21 +2322,21 @@ bool BM_edge_splice(BMesh *bm, BMEdge *e, BMEdge *e_target)
return false;
}
- while (e->l) {
- l = e->l;
- BLI_assert(BM_vert_in_edge(e_target, l->v));
- BLI_assert(BM_vert_in_edge(e_target, l->next->v));
- bmesh_radial_loop_remove(l, e);
- bmesh_radial_append(e_target, l);
+ while (e_src->l) {
+ l = e_src->l;
+ BLI_assert(BM_vert_in_edge(e_dst, l->v));
+ BLI_assert(BM_vert_in_edge(e_dst, l->next->v));
+ bmesh_radial_loop_remove(l, e_src);
+ bmesh_radial_append(e_dst, l);
}
- BLI_assert(bmesh_radial_length(e->l) == 0);
+ BLI_assert(bmesh_radial_length(e_src->l) == 0);
- BM_CHECK_ELEMENT(e);
- BM_CHECK_ELEMENT(e_target);
+ BM_CHECK_ELEMENT(e_src);
+ BM_CHECK_ELEMENT(e_dst);
/* removes from disks too */
- BM_edge_kill(bm, e);
+ BM_edge_kill(bm, e_src);
return true;
}
@@ -2254,8 +2352,9 @@ bool BM_edge_splice(BMesh *bm, BMEdge *e, BMEdge *e_target)
* \note Does nothing if \a l_sep is already the only loop in the
* edge radial.
*/
-void bmesh_edge_separate(BMesh *bm, BMEdge *e, BMLoop *l_sep,
- const bool copy_select)
+void bmesh_edge_separate(
+ BMesh *bm, BMEdge *e, BMLoop *l_sep,
+ const bool copy_select)
{
BMEdge *e_new;
#ifndef NDEBUG
@@ -2266,7 +2365,7 @@ void bmesh_edge_separate(BMesh *bm, BMEdge *e, BMLoop *l_sep,
BLI_assert(e->l);
if (BM_edge_is_boundary(e)) {
- /* no cut required */
+ BLI_assert(0); /* no cut required */
return;
}
@@ -2296,75 +2395,252 @@ void bmesh_edge_separate(BMesh *bm, BMEdge *e, BMLoop *l_sep,
* Disconnects a face from its vertex fan at loop \a l_sep
*
* \return The newly created BMVert
+ *
+ * \note Will be a no-op and return original vertex if only two edges at that vertex.
*/
BMVert *bmesh_urmv_loop(BMesh *bm, BMLoop *l_sep)
{
- BMVert **vtar;
- int len, i;
BMVert *v_new = NULL;
BMVert *v_sep = l_sep->v;
+ BMEdge *e_iter;
+ BMEdge *edges[2];
+ int i;
/* peel the face from the edge radials on both sides of the
* loop vert, disconnecting the face from its fan */
- bmesh_edge_separate(bm, l_sep->e, l_sep, false);
- bmesh_edge_separate(bm, l_sep->prev->e, l_sep->prev, false);
+ if (!BM_edge_is_boundary(l_sep->e))
+ bmesh_edge_separate(bm, l_sep->e, l_sep, false);
+ if (!BM_edge_is_boundary(l_sep->prev->e))
+ bmesh_edge_separate(bm, l_sep->prev->e, l_sep->prev, false);
- if (bmesh_disk_count(v_sep) == 2) {
- /* If there are still only two edges out of v_sep, then
- * this whole URMV was just a no-op, so exit now. */
+ /* do inline, below */
+#if 0
+ if (BM_vert_edge_count_is_equal(v_sep, 2)) {
return v_sep;
}
+#endif
- /* Update the disk start, so that v->e points to an edge
- * not touching the split loop. This is so that BM_vert_split
- * will leave the original v_sep on some *other* fan (not the
- * one-face fan that holds the unglue face). */
- while (v_sep->e == l_sep->e || v_sep->e == l_sep->prev->e) {
- v_sep->e = bmesh_disk_edge_next(v_sep->e, v_sep);
+ /* Search for an edge unattached to this loop */
+ e_iter = v_sep->e;
+ while (!ELEM(e_iter, l_sep->e, l_sep->prev->e)) {
+ e_iter = bmesh_disk_edge_next(e_iter, v_sep);
+
+ /* We've come back around to the initial edge, all touch this loop.
+ * If there are still only two edges out of v_sep,
+ * then this whole URMV was just a no-op, so exit now. */
+ if (e_iter == v_sep->e) {
+ BLI_assert(BM_vert_edge_count_is_equal(v_sep, 2));
+ return v_sep;
+ }
}
- /* Split all fans connected to the vert, duplicating it for
- * each fans. */
- bmesh_vert_separate(bm, v_sep, &vtar, &len, false);
+ v_sep->e = l_sep->e;
- /* There should have been at least two fans cut apart here,
- * otherwise the early exit would have kicked in. */
- BLI_assert(len >= 2);
+ v_new = BM_vert_create(bm, v_sep->co, v_sep, BM_CREATE_NOP);
- v_new = l_sep->v;
+ edges[0] = l_sep->e;
+ edges[1] = l_sep->prev->e;
- /* Desired result here is that a new vert should always be
- * created for the unglue face. This is so we can glue any
- * extras back into the original vert. */
- BLI_assert(v_new != v_sep);
- BLI_assert(v_sep == vtar[0]);
+ for (i = 0; i < ARRAY_SIZE(edges); i++) {
+ BMEdge *e = edges[i];
+ bmesh_edge_vert_swap(e, v_new, v_sep);
+ }
- /* If there are more than two verts as a result, glue together
- * all the verts except the one this URMV intended to create */
- if (len > 2) {
- for (i = 0; i < len; i++) {
- if (vtar[i] == v_new) {
- break;
+ BLI_assert(v_sep != l_sep->v);
+ BLI_assert(v_sep->e != l_sep->v->e);
+
+ BM_CHECK_ELEMENT(l_sep);
+ BM_CHECK_ELEMENT(v_sep);
+ BM_CHECK_ELEMENT(edges[0]);
+ BM_CHECK_ELEMENT(edges[1]);
+ BM_CHECK_ELEMENT(v_new);
+
+ return v_new;
+}
+
+/**
+ * A version of #bmesh_urmv_loop that disconnects multiple loops at once.
+ *
+ * Handles the task of finding fans boundaries.
+ */
+BMVert *bmesh_urmv_loop_multi(
+ BMesh *bm, BMLoop **larr, int larr_len)
+{
+ BMVert *v_sep = larr[0]->v;
+ BMVert *v_new;
+ int i;
+ bool is_mixed_any = false;
+
+ BLI_SMALLSTACK_DECLARE(edges, BMEdge *);
+
+#define LOOP_VISIT _FLAG_WALK
+#define EDGE_VISIT _FLAG_WALK
+
+ for (i = 0; i < larr_len; i++) {
+ BMLoop *l_sep = larr[i];
+
+ /* all must be from the same vert! */
+ BLI_assert(v_sep == l_sep->v);
+
+ BLI_assert(!BM_ELEM_API_FLAG_TEST(l_sep, LOOP_VISIT));
+ BM_ELEM_API_FLAG_ENABLE(l_sep, LOOP_VISIT);
+
+ /* weak! but it makes it simpler to check for edges to split
+ * while doing a radial loop (where loops may be adjacent) */
+ BM_ELEM_API_FLAG_ENABLE(l_sep->next, LOOP_VISIT);
+ BM_ELEM_API_FLAG_ENABLE(l_sep->prev, LOOP_VISIT);
+ }
+
+ for (i = 0; i < larr_len; i++) {
+ BMLoop *l_sep = larr[i];
+
+ BMLoop *loop_pair[2] = {l_sep, l_sep->prev};
+ int j;
+ for (j = 0; j < ARRAY_SIZE(loop_pair); j++) {
+ BMEdge *e = loop_pair[j]->e;
+ if (!BM_ELEM_API_FLAG_TEST(e, EDGE_VISIT)) {
+ BMLoop *l_iter, *l_first;
+ bool is_mixed = false;
+
+ BM_ELEM_API_FLAG_ENABLE(e, EDGE_VISIT);
+
+ l_iter = l_first = e->l;
+ do {
+ if (!BM_ELEM_API_FLAG_TEST(l_iter, LOOP_VISIT)) {
+ is_mixed = true;
+ is_mixed_any = true;
+ break;
+ }
+ } while ((l_iter = l_iter->radial_next) != l_first);
+
+ if (is_mixed) {
+ /* ensure the first loop is one we don't own so we can do a quick check below
+ * on the edge's loop-flag to see if the edge is mixed or not. */
+ e->l = l_iter;
+ }
+ BLI_SMALLSTACK_PUSH(edges, e);
}
}
+ }
+
+ if (is_mixed_any == false) {
+ /* all loops in 'larr' are the soul owners of their edges.
+ * nothing to split away from, this is a no-op */
+ v_new = v_sep;
+ }
+ else {
+ BMEdge *e;
+
+ BLI_assert(!BLI_SMALLSTACK_IS_EMPTY(edges));
+
+ v_new = BM_vert_create(bm, v_sep->co, v_sep, BM_CREATE_NOP);
+ while ((e = BLI_SMALLSTACK_POP(edges))) {
+ BMLoop *l_iter, *l_first, *l_next;
+ BMEdge *e_new;
+
+ /* disable so copied edge isn't left dirty (loop edges are cleared last too) */
+ BM_ELEM_API_FLAG_DISABLE(e, EDGE_VISIT);
+
+ if (!BM_ELEM_API_FLAG_TEST(e->l, LOOP_VISIT)) {
+ /* edge has some loops owned by us, some owned by other loops */
+ BMVert *e_new_v_pair[2];
- if (i != len) {
- /* Swap the single vert that was needed for the
- * unglue into the last array slot */
- SWAP(BMVert *, vtar[i], vtar[len - 1]);
+ if (e->v1 == v_sep) {
+ e_new_v_pair[0] = v_new;
+ e_new_v_pair[1] = e->v2;
+ }
+ else {
+ BLI_assert(v_sep == e->v2);
+ e_new_v_pair[0] = e->v1;
+ e_new_v_pair[1] = v_new;
+ }
- /* And then glue the rest back together */
- for (i = 1; i < len - 1; i++) {
- BM_vert_splice(bm, vtar[i], vtar[0]);
+ e_new = BM_edge_create(bm, UNPACK2(e_new_v_pair), e, BM_CREATE_NOP);
+
+ /* now moved all loops from 'larr' to this newly created edge */
+ l_iter = l_first = e->l;
+ do {
+ l_next = l_iter->radial_next;
+ if (BM_ELEM_API_FLAG_TEST(l_iter, LOOP_VISIT)) {
+ bmesh_radial_loop_remove(l_iter, e);
+ bmesh_radial_append(e_new, l_iter);
+ l_iter->e = e_new;
+ }
+ } while ((l_iter = l_next) != l_first);
+ }
+ else {
+ /* we own the edge entirely, replace the vert */
+ bmesh_disk_vert_replace(e, v_new, v_sep);
}
+
+ /* loop vert is handled last! */
}
}
- MEM_freeN(vtar);
+ for (i = 0; i < larr_len; i++) {
+ BMLoop *l_sep = larr[i];
+
+ l_sep->v = v_new;
+
+ BLI_assert(BM_ELEM_API_FLAG_TEST(l_sep, LOOP_VISIT));
+ BLI_assert(BM_ELEM_API_FLAG_TEST(l_sep->prev, LOOP_VISIT));
+ BLI_assert(BM_ELEM_API_FLAG_TEST(l_sep->next, LOOP_VISIT));
+ BM_ELEM_API_FLAG_DISABLE(l_sep, LOOP_VISIT);
+ BM_ELEM_API_FLAG_DISABLE(l_sep->prev, LOOP_VISIT);
+ BM_ELEM_API_FLAG_DISABLE(l_sep->next, LOOP_VISIT);
+
+
+ BM_ELEM_API_FLAG_DISABLE(l_sep->prev->e, EDGE_VISIT);
+ BM_ELEM_API_FLAG_DISABLE(l_sep->e, EDGE_VISIT);
+ }
+
+#undef LOOP_VISIT
+#undef EDGE_VISIT
+
+ return v_new;
+}
+
+static void bmesh_edge_vert_swap__recursive(BMEdge *e, BMVert *v_dst, BMVert *v_src)
+{
+ BMLoop *l_iter, *l_first;
+
+ BLI_assert(ELEM(v_src, e->v1, e->v2));
+ bmesh_disk_vert_replace(e, v_dst, v_src);
+
+ l_iter = l_first = e->l;
+ do {
+ if (l_iter->v == v_src) {
+ l_iter->v = v_dst;
+ if (BM_vert_in_edge(l_iter->prev->e, v_src)) {
+ bmesh_edge_vert_swap__recursive(l_iter->prev->e, v_dst, v_src);
+ }
+ }
+ else if (l_iter->next->v == v_src) {
+ l_iter->next->v = v_dst;
+ if (BM_vert_in_edge(l_iter->next->e, v_src)) {
+ bmesh_edge_vert_swap__recursive(l_iter->next->e, v_dst, v_src);
+ }
+ }
+ else {
+ BLI_assert(l_iter->prev->v != v_src);
+ }
+ } while ((l_iter = l_iter->radial_next) != l_first);
+}
+/**
+ * This function assumes l_sep is apart of a larger fan which has already been
+ * isolated by calling bmesh_edge_separate to segregate it radially.
+ */
+BMVert *bmesh_urmv_loop_region(BMesh *bm, BMLoop *l_sep)
+{
+ BMVert *v_new = BM_vert_create(bm, l_sep->v->co, l_sep->v, BM_CREATE_NOP);
+ /* passing either 'l_sep->e', 'l_sep->prev->e' will work */
+ bmesh_edge_vert_swap__recursive(l_sep->e, v_new, l_sep->v);
+ BLI_assert(l_sep->v == v_new);
return v_new;
}
+
/**
* \brief Unglue Region Make Vert (URMV)
*
diff --git a/source/blender/bmesh/intern/bmesh_core.h b/source/blender/bmesh/intern/bmesh_core.h
index ab847fc82eb..2b100eb7b8d 100644
--- a/source/blender/bmesh/intern/bmesh_core.h
+++ b/source/blender/bmesh/intern/bmesh_core.h
@@ -27,8 +27,9 @@
* \ingroup bmesh
*/
-BMFace *BM_face_copy(BMesh *bm_dst, BMesh *bm_src, BMFace *f,
- const bool copy_verts, const bool copy_edges);
+BMFace *BM_face_copy(
+ BMesh *bm_dst, BMesh *bm_src, BMFace *f,
+ const bool copy_verts, const bool copy_edges);
typedef enum eBMCreateFlag {
BM_CREATE_NOP = 0,
@@ -40,15 +41,19 @@ typedef enum eBMCreateFlag {
BM_CREATE_SKIP_CD = (1 << 2),
} eBMCreateFlag;
-BMVert *BM_vert_create(BMesh *bm, const float co[3],
- const BMVert *v_example, const eBMCreateFlag create_flag);
-BMEdge *BM_edge_create(BMesh *bm, BMVert *v1, BMVert *v2,
- const BMEdge *e_example, const eBMCreateFlag create_flag);
-BMFace *BM_face_create(BMesh *bm, BMVert **verts, BMEdge **edges, const int len,
- const BMFace *f_example, const eBMCreateFlag create_flag);
-BMFace *BM_face_create_verts(BMesh *bm, BMVert **verts, const int len,
- const BMFace *f_example, const eBMCreateFlag create_flag,
- const bool create_edges);
+BMVert *BM_vert_create(
+ BMesh *bm, const float co[3],
+ const BMVert *v_example, const eBMCreateFlag create_flag);
+BMEdge *BM_edge_create(
+ BMesh *bm, BMVert *v1, BMVert *v2,
+ const BMEdge *e_example, const eBMCreateFlag create_flag);
+BMFace *BM_face_create(
+ BMesh *bm, BMVert **verts, BMEdge **edges, const int len,
+ const BMFace *f_example, const eBMCreateFlag create_flag);
+BMFace *BM_face_create_verts(
+ BMesh *bm, BMVert **verts, const int len,
+ const BMFace *f_example, const eBMCreateFlag create_flag,
+ const bool create_edges);
void BM_face_edges_kill(BMesh *bm, BMFace *f);
void BM_face_verts_kill(BMesh *bm, BMFace *f);
@@ -57,25 +62,32 @@ void BM_face_kill(BMesh *bm, BMFace *f);
void BM_edge_kill(BMesh *bm, BMEdge *e);
void BM_vert_kill(BMesh *bm, BMVert *v);
-void bmesh_edge_separate(BMesh *bm, BMEdge *e, BMLoop *l_sep,
- const bool copy_select);
-bool BM_edge_splice(BMesh *bm, BMEdge *e, BMEdge *e_target);
-bool BM_vert_splice(BMesh *bm, BMVert *v, BMVert *v_target);
+void bmesh_edge_separate(
+ BMesh *bm, BMEdge *e, BMLoop *l_sep,
+ const bool copy_select);
+bool BM_edge_splice(BMesh *bm, BMEdge *e_dst, BMEdge *e_src);
+bool BM_vert_splice(BMesh *bm, BMVert *v_dst, BMVert *v_src);
bool BM_vert_splice_check_double(BMVert *v_a, BMVert *v_b);
-void bmesh_vert_separate(BMesh *bm, BMVert *v, BMVert ***r_vout, int *r_vout_len,
- const bool copy_select);
+void bmesh_vert_separate(
+ BMesh *bm, BMVert *v, BMVert ***r_vout, int *r_vout_len,
+ const bool copy_select);
bool bmesh_loop_reverse(BMesh *bm, BMFace *f);
BMFace *BM_faces_join(BMesh *bm, BMFace **faces, int totface, const bool do_del);
-void BM_vert_separate(BMesh *bm, BMVert *v, BMVert ***r_vout, int *r_vout_len,
- BMEdge **e_in, int e_in_len);
+void BM_vert_separate(
+ BMesh *bm, BMVert *v, BMEdge **e_in, int e_in_len, const bool copy_select,
+ BMVert ***r_vout, int *r_vout_len);
+void BM_vert_separate_hflag(
+ BMesh *bm, BMVert *v, const char hflag, const bool copy_select,
+ BMVert ***r_vout, int *r_vout_len);
/* EULER API - For modifying structure */
-BMFace *bmesh_sfme(BMesh *bm, BMFace *f,
- BMLoop *l1, BMLoop *l2,
- BMLoop **r_l,
+BMFace *bmesh_sfme(
+ BMesh *bm, BMFace *f,
+ BMLoop *l1, BMLoop *l2,
+ BMLoop **r_l,
#ifdef USE_BMESH_HOLES
ListBase *holes,
#endif
@@ -84,11 +96,15 @@ BMFace *bmesh_sfme(BMesh *bm, BMFace *f,
);
BMVert *bmesh_semv(BMesh *bm, BMVert *tv, BMEdge *e, BMEdge **r_e);
-BMEdge *bmesh_jekv(BMesh *bm, BMEdge *e_kill, BMVert *v_kill,
- const bool do_del, const bool check_edge_splice);
+BMEdge *bmesh_jekv(
+ BMesh *bm, BMEdge *e_kill, BMVert *v_kill,
+ const bool do_del, const bool check_edge_splice);
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);
+BMVert *bmesh_urmv_loop_multi(
+ BMesh *bm, BMLoop **larr, int larr_len);
+BMVert *bmesh_urmv_loop_region(BMesh *bm, BMLoop *l_sep);
void bmesh_face_swap_data(BMFace *f_a, BMFace *f_b);
diff --git a/source/blender/bmesh/intern/bmesh_edgeloop.c b/source/blender/bmesh/intern/bmesh_edgeloop.c
index e83a1d5b00a..eaa070151a6 100644
--- a/source/blender/bmesh/intern/bmesh_edgeloop.c
+++ b/source/blender/bmesh/intern/bmesh_edgeloop.c
@@ -52,8 +52,9 @@ typedef struct BMEdgeLoopStore {
/* -------------------------------------------------------------------- */
/* BM_mesh_edgeloops_find & Util Functions */
-static int bm_vert_other_tag(BMVert *v, BMVert *v_prev,
- BMEdge **r_e)
+static int bm_vert_other_tag(
+ BMVert *v, BMVert *v_prev,
+ BMEdge **r_e)
{
BMIter iter;
BMEdge *e, *e_next = NULL;
@@ -125,8 +126,9 @@ static bool bm_loop_build(BMEdgeLoopStore *el_store, BMVert *v_prev, BMVert *v,
/**
* \return listbase of listbases, each linking to a vertex.
*/
-int BM_mesh_edgeloops_find(BMesh *bm, ListBase *r_eloops,
- bool (*test_fn)(BMEdge *, void *user_data), void *user_data)
+int BM_mesh_edgeloops_find(
+ BMesh *bm, ListBase *r_eloops,
+ bool (*test_fn)(BMEdge *, void *user_data), void *user_data)
{
BMIter iter;
BMEdge *e;
@@ -183,8 +185,9 @@ struct VertStep {
BMVert *v;
};
-static void vs_add(BLI_mempool *vs_pool, ListBase *lb,
- BMVert *v, BMEdge *e_prev, const int iter_tot)
+static void vs_add(
+ BLI_mempool *vs_pool, ListBase *lb,
+ BMVert *v, BMEdge *e_prev, const int iter_tot)
{
struct VertStep *vs_new = BLI_mempool_alloc(vs_pool);
vs_new->v = v;
@@ -256,9 +259,10 @@ static bool bm_loop_path_build_step(BLI_mempool *vs_pool, ListBase *lb, const in
return (BLI_listbase_is_empty(lb) == false);
}
-bool BM_mesh_edgeloops_find_path(BMesh *bm, ListBase *r_eloops,
- bool (*test_fn)(BMEdge *, void *user_data), void *user_data,
- BMVert *v_src, BMVert *v_dst)
+bool BM_mesh_edgeloops_find_path(
+ BMesh *bm, ListBase *r_eloops,
+ bool (*test_fn)(BMEdge *, void *user_data), void *user_data,
+ BMVert *v_src, BMVert *v_dst)
{
BMIter iter;
BMEdge *e;
@@ -662,7 +666,7 @@ void BM_edgeloop_flip(BMesh *UNUSED(bm), BMEdgeLoopStore *el_store)
void BM_edgeloop_expand(BMesh *UNUSED(bm), BMEdgeLoopStore *el_store, int el_store_len)
{
- /* first double until we are more then half as big */
+ /* first double until we are more than half as big */
while ((el_store->len * 2) < el_store_len) {
LinkData *node_curr = el_store->verts.first;
while (node_curr) {
diff --git a/source/blender/bmesh/intern/bmesh_edgeloop.h b/source/blender/bmesh/intern/bmesh_edgeloop.h
index 527dba120e1..5df4ee5848e 100644
--- a/source/blender/bmesh/intern/bmesh_edgeloop.h
+++ b/source/blender/bmesh/intern/bmesh_edgeloop.h
@@ -32,17 +32,20 @@ struct ListBase;
struct BMEdgeLoopStore;
/* multiple edgeloops (ListBase) */
-int BM_mesh_edgeloops_find(BMesh *bm, struct ListBase *r_lb,
- bool (*test_fn)(BMEdge *, void *user_data), void *user_data);
-bool BM_mesh_edgeloops_find_path(BMesh *bm, ListBase *r_eloops,
- bool (*test_fn)(BMEdge *, void *user_data), void *user_data,
- BMVert *v_src, BMVert *v_dst);
+int BM_mesh_edgeloops_find(
+ BMesh *bm, struct ListBase *r_lb,
+ bool (*test_fn)(BMEdge *, void *user_data), void *user_data);
+bool BM_mesh_edgeloops_find_path(
+ BMesh *bm, ListBase *r_eloops,
+ bool (*test_fn)(BMEdge *, void *user_data), void *user_data,
+ BMVert *v_src, BMVert *v_dst);
void BM_mesh_edgeloops_free(struct ListBase *eloops);
void BM_mesh_edgeloops_calc_center(BMesh *bm, struct ListBase *eloops);
void BM_mesh_edgeloops_calc_normal(BMesh *bm, struct ListBase *eloops);
-void BM_mesh_edgeloops_calc_normal_aligned(BMesh *bm, struct ListBase *eloops,
- const float no_align[3]);
+void BM_mesh_edgeloops_calc_normal_aligned(
+ BMesh *bm, struct ListBase *eloops,
+ const float no_align[3]);
void BM_mesh_edgeloops_calc_order(BMesh *UNUSED(bm), ListBase *eloops, const bool use_normals);
@@ -59,8 +62,9 @@ const float *BM_edgeloop_center_get(struct BMEdgeLoopStore *el_store);
void BM_edgeloop_edges_get(struct BMEdgeLoopStore *el_store, BMEdge **e_arr);
void BM_edgeloop_calc_center(BMesh *bm, struct BMEdgeLoopStore *el_store);
bool BM_edgeloop_calc_normal(BMesh *bm, struct BMEdgeLoopStore *el_store);
-bool BM_edgeloop_calc_normal_aligned(BMesh *bm, struct BMEdgeLoopStore *el_store,
- const float no_align[3]);
+bool BM_edgeloop_calc_normal_aligned(
+ BMesh *bm, struct BMEdgeLoopStore *el_store,
+ const float no_align[3]);
void BM_edgeloop_flip(BMesh *bm, struct BMEdgeLoopStore *el_store);
void BM_edgeloop_expand(BMesh *bm, struct BMEdgeLoopStore *el_store, int el_store_len);
diff --git a/source/blender/bmesh/intern/bmesh_inline.h b/source/blender/bmesh/intern/bmesh_inline.h
index 96b2cd396a2..4b55060875b 100644
--- a/source/blender/bmesh/intern/bmesh_inline.h
+++ b/source/blender/bmesh/intern/bmesh_inline.h
@@ -39,11 +39,13 @@
#define BM_elem_flag_merge( ele_a, ele_b) _bm_elem_flag_merge (&(ele_a)->head, &(ele_b)->head)
#define BM_elem_flag_merge_into(ele, ele_a, ele_b)_bm_elem_flag_merge_into (&(ele)->head, &(ele_a)->head, &(ele_b)->head)
+ATTR_WARN_UNUSED_RESULT
BLI_INLINE char _bm_elem_flag_test(const BMHeader *head, const char hflag)
{
return head->hflag & hflag;
}
+ATTR_WARN_UNUSED_RESULT
BLI_INLINE bool _bm_elem_flag_test_bool(const BMHeader *head, const char hflag)
{
return (head->hflag & hflag) != 0;
@@ -116,6 +118,7 @@ BLI_INLINE void _bm_elem_index_set(BMHeader *head, const int index)
head->index = index;
}
+ATTR_WARN_UNUSED_RESULT
BLI_INLINE int _bm_elem_index_get(const BMHeader *head)
{
return head->index;
diff --git a/source/blender/bmesh/intern/bmesh_interp.c b/source/blender/bmesh/intern/bmesh_interp.c
index a32f28169f6..6e468bf44f2 100644
--- a/source/blender/bmesh/intern/bmesh_interp.c
+++ b/source/blender/bmesh/intern/bmesh_interp.c
@@ -40,39 +40,43 @@
#include "BKE_customdata.h"
#include "BKE_multires.h"
+#include "BLI_memarena.h"
+#include "BLI_linklist.h"
#include "bmesh.h"
#include "intern/bmesh_private.h"
/* edge and vertex share, currently theres no need to have different logic */
-static void bm_data_interp_from_elem(CustomData *data_layer, BMElem *ele1, BMElem *ele2, BMElem *ele_dst, const float fac)
+static void bm_data_interp_from_elem(
+ CustomData *data_layer, const BMElem *ele_src_1, const BMElem *ele_src_2,
+ BMElem *ele_dst, const float fac)
{
- if (ele1->head.data && ele2->head.data) {
+ if (ele_src_1->head.data && ele_src_2->head.data) {
/* first see if we can avoid interpolation */
if (fac <= 0.0f) {
- if (ele1 == ele_dst) {
+ if (ele_src_1 == ele_dst) {
/* do nothing */
}
else {
CustomData_bmesh_free_block_data(data_layer, ele_dst->head.data);
- CustomData_bmesh_copy_data(data_layer, data_layer, ele1->head.data, &ele_dst->head.data);
+ CustomData_bmesh_copy_data(data_layer, data_layer, ele_src_1->head.data, &ele_dst->head.data);
}
}
else if (fac >= 1.0f) {
- if (ele2 == ele_dst) {
+ if (ele_src_2 == ele_dst) {
/* do nothing */
}
else {
CustomData_bmesh_free_block_data(data_layer, ele_dst->head.data);
- CustomData_bmesh_copy_data(data_layer, data_layer, ele2->head.data, &ele_dst->head.data);
+ CustomData_bmesh_copy_data(data_layer, data_layer, ele_src_2->head.data, &ele_dst->head.data);
}
}
else {
- void *src[2];
+ const void *src[2];
float w[2];
- src[0] = ele1->head.data;
- src[1] = ele2->head.data;
+ src[0] = ele_src_1->head.data;
+ src[1] = ele_src_2->head.data;
w[0] = 1.0f - fac;
w[1] = fac;
CustomData_bmesh_interp(data_layer, src, w, NULL, 2, ele_dst->head.data);
@@ -83,25 +87,25 @@ static void bm_data_interp_from_elem(CustomData *data_layer, BMElem *ele1, BMEle
/**
* \brief Data, Interp From Verts
*
- * Interpolates per-vertex data from two sources to a target.
+ * Interpolates per-vertex data from two sources to \a v_dst
*
* \note This is an exact match to #BM_data_interp_from_edges
*/
-void BM_data_interp_from_verts(BMesh *bm, BMVert *v1, BMVert *v2, BMVert *v, const float fac)
+void BM_data_interp_from_verts(BMesh *bm, const BMVert *v_src_1, const BMVert *v_src_2, BMVert *v_dst, const float fac)
{
- bm_data_interp_from_elem(&bm->vdata, (BMElem *)v1, (BMElem *)v2, (BMElem *)v, fac);
+ bm_data_interp_from_elem(&bm->vdata, (const BMElem *)v_src_1, (const BMElem *)v_src_2, (BMElem *)v_dst, fac);
}
/**
* \brief Data, Interp From Edges
*
- * Interpolates per-edge data from two sources to a target.
+ * Interpolates per-edge data from two sources to \a e_dst.
*
* \note This is an exact match to #BM_data_interp_from_verts
*/
-void BM_data_interp_from_edges(BMesh *bm, BMEdge *e1, BMEdge *e2, BMEdge *e, const float fac)
+void BM_data_interp_from_edges(BMesh *bm, const BMEdge *e_src_1, const BMEdge *e_src_2, BMEdge *e_dst, const float fac)
{
- bm_data_interp_from_elem(&bm->edata, (BMElem *)e1, (BMElem *)e2, (BMElem *)e, fac);
+ bm_data_interp_from_elem(&bm->edata, (const BMElem *)e_src_1, (const BMElem *)e_src_2, (BMElem *)e_dst, fac);
}
/**
@@ -118,26 +122,26 @@ static void UNUSED_FUNCTION(BM_Data_Vert_Average)(BMesh *UNUSED(bm), BMFace *UNU
/**
* \brief Data Face-Vert Edge Interp
*
- * Walks around the faces of an edge and interpolates the per-face-edge
- * data between two sources to a target.
+ * Walks around the faces of \a e and interpolates
+ * the loop data between two sources.
*/
-void BM_data_interp_face_vert_edge(BMesh *bm, BMVert *v1, BMVert *UNUSED(v2), BMVert *v, BMEdge *e1, const float fac)
+void BM_data_interp_face_vert_edge(
+ BMesh *bm, const BMVert *v_src_1, const BMVert *UNUSED(v_src_2), BMVert *v, BMEdge *e, const float fac)
{
- void *src[2];
float w[2];
BMLoop *l_v1 = NULL, *l_v = NULL, *l_v2 = NULL;
BMLoop *l_iter = NULL;
- if (!e1->l) {
+ if (!e->l) {
return;
}
w[1] = 1.0f - fac;
w[0] = fac;
- l_iter = e1->l;
+ l_iter = e->l;
do {
- if (l_iter->v == v1) {
+ if (l_iter->v == v_src_1) {
l_v1 = l_iter;
l_v = l_v1->next;
l_v2 = l_v->next;
@@ -148,14 +152,17 @@ void BM_data_interp_face_vert_edge(BMesh *bm, BMVert *v1, BMVert *UNUSED(v2), BM
l_v2 = l_iter->prev;
}
- if (!l_v1 || !l_v2)
+ if (!l_v1 || !l_v2) {
return;
-
- src[0] = l_v1->head.data;
- src[1] = l_v2->head.data;
+ }
+ else {
+ const void *src[2];
+ src[0] = l_v1->head.data;
+ src[1] = l_v2->head.data;
- CustomData_bmesh_interp(&bm->ldata, src, w, NULL, 2, l_v->head.data);
- } while ((l_iter = l_iter->radial_next) != e1->l);
+ CustomData_bmesh_interp(&bm->ldata, src, w, NULL, 2, l_v->head.data);
+ }
+ } while ((l_iter = l_iter->radial_next) != e->l);
}
/**
@@ -166,56 +173,57 @@ void BM_data_interp_face_vert_edge(BMesh *bm, BMVert *v1, BMVert *UNUSED(v2), BM
*
* \note Only handles loop customdata. multires is handled.
*/
-void BM_face_interp_from_face_ex(BMesh *bm, BMFace *target, BMFace *source, const bool do_vertex,
- void **blocks_l, void **blocks_v, float (*cos_2d)[2], float axis_mat[3][3])
+void BM_face_interp_from_face_ex(
+ BMesh *bm, BMFace *f_dst, const BMFace *f_src, const bool do_vertex,
+ const void **blocks_l, const void **blocks_v, float (*cos_2d)[2], float axis_mat[3][3])
{
BMLoop *l_iter;
BMLoop *l_first;
- float *w = BLI_array_alloca(w, source->len);
+ float *w = BLI_array_alloca(w, f_src->len);
float co[2];
int i;
- if (source != target)
- BM_elem_attrs_copy(bm, bm, source, target);
+ if (f_src != f_dst)
+ BM_elem_attrs_copy(bm, bm, f_src, f_dst);
/* interpolate */
i = 0;
- l_iter = l_first = BM_FACE_FIRST_LOOP(target);
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f_dst);
do {
mul_v2_m3v3(co, axis_mat, l_iter->v->co);
- interp_weights_poly_v2(w, cos_2d, source->len, co);
- CustomData_bmesh_interp(&bm->ldata, blocks_l, w, NULL, source->len, l_iter->head.data);
+ interp_weights_poly_v2(w, cos_2d, f_src->len, co);
+ CustomData_bmesh_interp(&bm->ldata, blocks_l, w, NULL, f_src->len, l_iter->head.data);
if (do_vertex) {
- CustomData_bmesh_interp(&bm->vdata, blocks_v, w, NULL, source->len, l_iter->v->head.data);
+ CustomData_bmesh_interp(&bm->vdata, blocks_v, w, NULL, f_src->len, l_iter->v->head.data);
}
} while (i++, (l_iter = l_iter->next) != l_first);
}
-void BM_face_interp_from_face(BMesh *bm, BMFace *target, BMFace *source, const bool do_vertex)
+void BM_face_interp_from_face(BMesh *bm, BMFace *f_dst, const BMFace *f_src, const bool do_vertex)
{
BMLoop *l_iter;
BMLoop *l_first;
- void **blocks_l = BLI_array_alloca(blocks_l, source->len);
- void **blocks_v = do_vertex ? BLI_array_alloca(blocks_v, source->len) : NULL;
- float (*cos_2d)[2] = BLI_array_alloca(cos_2d, source->len);
+ const void **blocks_l = BLI_array_alloca(blocks_l, f_src->len);
+ const void **blocks_v = do_vertex ? BLI_array_alloca(blocks_v, f_src->len) : NULL;
+ float (*cos_2d)[2] = BLI_array_alloca(cos_2d, f_src->len);
float axis_mat[3][3]; /* use normal to transform into 2d xy coords */
int i;
/* convert the 3d coords into 2d for projection */
- BLI_assert(BM_face_is_normal_valid(source));
- axis_dominant_v3_to_m3(axis_mat, source->no);
+ BLI_assert(BM_face_is_normal_valid(f_src));
+ axis_dominant_v3_to_m3(axis_mat, f_src->no);
i = 0;
- l_iter = l_first = BM_FACE_FIRST_LOOP(source);
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f_src);
do {
mul_v2_m3v3(cos_2d[i], axis_mat, l_iter->v->co);
blocks_l[i] = l_iter->head.data;
if (do_vertex) blocks_v[i] = l_iter->v->head.data;
} while (i++, (l_iter = l_iter->next) != l_first);
- BM_face_interp_from_face_ex(bm, target, source, do_vertex,
+ BM_face_interp_from_face_ex(bm, f_dst, f_src, do_vertex,
blocks_l, blocks_v, cos_2d, axis_mat);
}
@@ -233,8 +241,9 @@ void BM_face_interp_from_face(BMesh *bm, BMFace *target, BMFace *source, const b
* y
* </pre>
*/
-static int compute_mdisp_quad(BMLoop *l, float v1[3], float v2[3], float v3[3], float v4[3],
- float e1[3], float e2[3])
+static int compute_mdisp_quad(
+ BMLoop *l, float v1[3], float v2[3], float v3[3], float v4[3],
+ float e1[3], float e2[3])
{
float cent[3], n[3], p[3];
@@ -294,9 +303,10 @@ static float quad_coord(const float aa[3], const float bb[3], const float cc[3],
return f1;
}
-static int quad_co(float *x, float *y,
- const float v1[3], const float v2[3], const float v3[3], const float v4[3],
- const float p[3], const float n[3])
+static int quad_co(
+ float *r_x, float *r_y,
+ const float v1[3], const float v2[3], const float v3[3], const float v4[3],
+ const float p[3], const float n[3])
{
float projverts[5][3], n2[3];
float dprojverts[4][3], origin[3] = {0.0f, 0.0f, 0.0f};
@@ -332,14 +342,15 @@ static int quad_co(float *x, float *y,
return 0;
}
- *y = quad_coord(dprojverts[1], dprojverts[0], dprojverts[2], dprojverts[3], 0, 1);
- *x = quad_coord(dprojverts[2], dprojverts[1], dprojverts[3], dprojverts[0], 0, 1);
+ *r_y = quad_coord(dprojverts[1], dprojverts[0], dprojverts[2], dprojverts[3], 0, 1);
+ *r_x = quad_coord(dprojverts[2], dprojverts[1], dprojverts[3], dprojverts[0], 0, 1);
return 1;
}
-static void mdisp_axis_from_quad(float v1[3], float v2[3], float UNUSED(v3[3]), float v4[3],
- float axis_x[3], float axis_y[3])
+static void mdisp_axis_from_quad(
+ float v1[3], float v2[3], float UNUSED(v3[3]), float v4[3],
+ float axis_x[3], float axis_y[3])
{
sub_v3_v3v3(axis_x, v4, v1);
sub_v3_v3v3(axis_y, v2, v1);
@@ -350,8 +361,9 @@ static void mdisp_axis_from_quad(float v1[3], float v2[3], float UNUSED(v3[3]),
/* tl is loop to project onto, l is loop whose internal displacement, co, is being
* projected. x and y are location in loop's mdisps grid of point co. */
-static bool mdisp_in_mdispquad(BMLoop *l, BMLoop *tl, float p[3], float *x, float *y,
- int res, float axis_x[3], float axis_y[3])
+static bool mdisp_in_mdispquad(
+ BMLoop *l, BMLoop *tl, float p[3], float *x, float *y,
+ int res, float axis_x[3], float axis_y[3])
{
float v1[3], v2[3], c[3], v3[3], v4[3], e1[3], e2[3];
float eps = FLT_EPSILON * 4000;
@@ -384,8 +396,9 @@ static bool mdisp_in_mdispquad(BMLoop *l, BMLoop *tl, float p[3], float *x, floa
return 1;
}
-static float bm_loop_flip_equotion(float mat[2][2], float b[2], const float target_axis_x[3], const float target_axis_y[3],
- const float coord[3], int i, int j)
+static float bm_loop_flip_equotion(
+ float mat[2][2], float b[2], const float target_axis_x[3], const float target_axis_y[3],
+ const float coord[3], int i, int j)
{
mat[0][0] = target_axis_x[i];
mat[0][1] = target_axis_y[i];
@@ -394,11 +407,12 @@ static float bm_loop_flip_equotion(float mat[2][2], float b[2], const float targ
b[0] = coord[i];
b[1] = coord[j];
- return mat[0][0] * mat[1][1] - mat[0][1] * mat[1][0];
+ return cross_v2v2(mat[0], mat[1]);
}
-static void bm_loop_flip_disp(const float source_axis_x[3], const float source_axis_y[3],
- const float target_axis_x[3], const float target_axis_y[3], float disp[3])
+static void bm_loop_flip_disp(
+ const float source_axis_x[3], const float source_axis_y[3],
+ const float target_axis_x[3], const float target_axis_y[3], float disp[3])
{
float vx[3], vy[3], coord[3];
float n[3], vec[3];
@@ -425,7 +439,7 @@ static void bm_loop_flip_disp(const float source_axis_x[3], const float source_a
disp[1] = (mat[0][0] * b[1] - b[0] * mat[1][0]) / d;
}
-static void bm_loop_interp_mdisps(BMesh *bm, BMLoop *l_dst, BMFace *f_src)
+static void bm_loop_interp_mdisps(BMesh *bm, BMLoop *l_dst, const BMFace *f_src)
{
const int cd_loop_mdisp_offset = CustomData_get_offset(&bm->ldata, CD_MDISPS);
MDisps *md_dst;
@@ -445,8 +459,8 @@ static void bm_loop_interp_mdisps(BMesh *bm, BMLoop *l_dst, BMFace *f_src)
/* if no disps data allocate a new grid, the size of the first grid in f_src. */
if (!md_dst->totdisp) {
- MDisps *md_src = BM_ELEM_CD_GET_VOID_P(BM_FACE_FIRST_LOOP(f_src), cd_loop_mdisp_offset);
-
+ const MDisps *md_src = BM_ELEM_CD_GET_VOID_P(BM_FACE_FIRST_LOOP(f_src), cd_loop_mdisp_offset);
+
md_dst->totdisp = md_src->totdisp;
md_dst->level = md_src->level;
if (md_dst->totdisp) {
@@ -609,36 +623,37 @@ void BM_face_multires_bounds_smooth(BMesh *bm, BMFace *f)
}
/**
- * project the multires grid in target onto source's set of multires grids
+ * project the multires grid in target onto f_src's set of multires grids
*/
-void BM_loop_interp_multires(BMesh *bm, BMLoop *target, BMFace *source)
+void BM_loop_interp_multires(BMesh *bm, BMLoop *l_dst, const BMFace *f_src)
{
- bm_loop_interp_mdisps(bm, target, source);
+ bm_loop_interp_mdisps(bm, l_dst, f_src);
}
/**
- * projects a single loop, target, onto source for customdata interpolation. multires is handled.
+ * projects a single loop, target, onto f_src for customdata interpolation. multires is handled.
* if do_vertex is true, target's vert data will also get interpolated.
*/
-void BM_loop_interp_from_face(BMesh *bm, BMLoop *target, BMFace *source,
- const bool do_vertex, const bool do_multires)
+void BM_loop_interp_from_face(
+ BMesh *bm, BMLoop *l_dst, const BMFace *f_src,
+ const bool do_vertex, const bool do_multires)
{
BMLoop *l_iter;
BMLoop *l_first;
- void **vblocks = do_vertex ? BLI_array_alloca(vblocks, source->len) : NULL;
- void **blocks = BLI_array_alloca(blocks, source->len);
- float (*cos_2d)[2] = BLI_array_alloca(cos_2d, source->len);
- float *w = BLI_array_alloca(w, source->len);
+ const void **vblocks = do_vertex ? BLI_array_alloca(vblocks, f_src->len) : NULL;
+ const void **blocks = BLI_array_alloca(blocks, f_src->len);
+ float (*cos_2d)[2] = BLI_array_alloca(cos_2d, f_src->len);
+ float *w = BLI_array_alloca(w, f_src->len);
float axis_mat[3][3]; /* use normal to transform into 2d xy coords */
float co[2];
int i;
/* convert the 3d coords into 2d for projection */
- BLI_assert(BM_face_is_normal_valid(source));
- axis_dominant_v3_to_m3(axis_mat, source->no);
+ BLI_assert(BM_face_is_normal_valid(f_src));
+ axis_dominant_v3_to_m3(axis_mat, f_src->no);
i = 0;
- l_iter = l_first = BM_FACE_FIRST_LOOP(source);
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f_src);
do {
mul_v2_m3v3(cos_2d[i], axis_mat, l_iter->v->co);
blocks[i] = l_iter->head.data;
@@ -648,48 +663,48 @@ void BM_loop_interp_from_face(BMesh *bm, BMLoop *target, BMFace *source,
}
} while (i++, (l_iter = l_iter->next) != l_first);
- mul_v2_m3v3(co, axis_mat, target->v->co);
+ mul_v2_m3v3(co, axis_mat, l_dst->v->co);
/* interpolate */
- interp_weights_poly_v2(w, cos_2d, source->len, co);
- CustomData_bmesh_interp(&bm->ldata, blocks, w, NULL, source->len, target->head.data);
+ interp_weights_poly_v2(w, cos_2d, f_src->len, co);
+ CustomData_bmesh_interp(&bm->ldata, blocks, w, NULL, f_src->len, l_dst->head.data);
if (do_vertex) {
- CustomData_bmesh_interp(&bm->vdata, vblocks, w, NULL, source->len, target->v->head.data);
+ CustomData_bmesh_interp(&bm->vdata, vblocks, w, NULL, f_src->len, l_dst->v->head.data);
}
if (do_multires) {
- bm_loop_interp_mdisps(bm, target, source);
+ bm_loop_interp_mdisps(bm, l_dst, f_src);
}
}
-void BM_vert_interp_from_face(BMesh *bm, BMVert *v, BMFace *source)
+void BM_vert_interp_from_face(BMesh *bm, BMVert *v_dst, const BMFace *f_src)
{
BMLoop *l_iter;
BMLoop *l_first;
- void **blocks = BLI_array_alloca(blocks, source->len);
- float (*cos_2d)[2] = BLI_array_alloca(cos_2d, source->len);
- float *w = BLI_array_alloca(w, source->len);
+ const void **blocks = BLI_array_alloca(blocks, f_src->len);
+ float (*cos_2d)[2] = BLI_array_alloca(cos_2d, f_src->len);
+ float *w = BLI_array_alloca(w, f_src->len);
float axis_mat[3][3]; /* use normal to transform into 2d xy coords */
float co[2];
int i;
/* convert the 3d coords into 2d for projection */
- BLI_assert(BM_face_is_normal_valid(source));
- axis_dominant_v3_to_m3(axis_mat, source->no);
+ BLI_assert(BM_face_is_normal_valid(f_src));
+ axis_dominant_v3_to_m3(axis_mat, f_src->no);
i = 0;
- l_iter = l_first = BM_FACE_FIRST_LOOP(source);
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f_src);
do {
mul_v2_m3v3(cos_2d[i], axis_mat, l_iter->v->co);
blocks[i] = l_iter->v->head.data;
} while (i++, (l_iter = l_iter->next) != l_first);
- mul_v2_m3v3(co, axis_mat, v->co);
+ mul_v2_m3v3(co, axis_mat, v_dst->co);
/* interpolate */
- interp_weights_poly_v2(w, cos_2d, source->len, co);
- CustomData_bmesh_interp(&bm->vdata, blocks, w, NULL, source->len, v->head.data);
+ interp_weights_poly_v2(w, cos_2d, f_src->len, co);
+ CustomData_bmesh_interp(&bm->vdata, blocks, w, NULL, f_src->len, v_dst->head.data);
}
static void update_data_blocks(BMesh *bm, CustomData *olddata, CustomData *data)
@@ -812,6 +827,7 @@ void BM_data_layer_free(BMesh *bm, CustomData *data, int type)
has_layer = CustomData_free_layer_active(data, type, 0);
/* assert because its expensive to realloc - better not do if layer isnt present */
BLI_assert(has_layer != false);
+ UNUSED_VARS_NDEBUG(has_layer);
update_data_blocks(bm, &olddata, data);
if (olddata.layers) MEM_freeN(olddata.layers);
@@ -831,7 +847,8 @@ void BM_data_layer_free_n(BMesh *bm, CustomData *data, int type, int n)
has_layer = CustomData_free_layer(data, type, 0, CustomData_get_layer_index_n(data, type, n));
/* assert because its expensive to realloc - better not do if layer isnt present */
BLI_assert(has_layer != false);
-
+ UNUSED_VARS_NDEBUG(has_layer);
+
update_data_blocks(bm, &olddata, data);
if (olddata.layers) MEM_freeN(olddata.layers);
}
@@ -893,3 +910,249 @@ void BM_elem_float_data_set(CustomData *cd, void *element, int type, const float
float *f = CustomData_bmesh_get(cd, ((BMHeader *)element)->data, type);
if (f) *f = val;
}
+
+/** \name Loop interpolation functions: BM_vert_loop_groups_data_layer_***
+ *
+ * Handling loop custom-data such as UV's, while keeping contiguous fans is rather tedious.
+ * Especially when a verts loops can have multiple CustomData layers,
+ * and each layer can have multiple (different) contiguous fans.
+ * Said differently, a single vertices loops may span multiple UV islands.
+ *
+ * These functions snapshot vertices loops, storing each contiguous fan in its own group.
+ * The caller can manipulate the loops, then re-combine the CustomData values.
+ *
+ * While these functions don't explicitly handle multiple layers at once,
+ * the caller can simply store its own list.
+ *
+ * \note Currently they are averaged back together (weighted by loop angle)
+ * but we could copy add other methods to re-combine CustomData-Loop-Fans.
+ *
+ * \{ */
+
+struct LoopWalkCtx {
+ /* same for all groups */
+ int type;
+ int cd_layer_offset;
+ const float *loop_weights;
+ MemArena *arena;
+
+ /* --- Per loop fan vars --- */
+
+ /* reference for this contiguous fan */
+ const void *data_ref;
+ int data_len;
+
+ /* accumulate 'LoopGroupCD.weight' to make unit length */
+ float weight_accum;
+
+ /* both arrays the size of the 'BM_vert_face_count(v)'
+ * each contiguous fan gets a slide of these arrays */
+ void **data_array;
+ int *data_index_array;
+ float *weight_array;
+};
+
+/* Store vars to pass into 'CustomData_bmesh_interp' */
+struct LoopGroupCD {
+ /* direct customdata pointer array */
+ void **data;
+ /* weights (aligned with 'data') */
+ float *data_weights;
+ /* index-in-face */
+ int *data_index;
+ /* number of loops in the fan */
+ int data_len;
+};
+
+static void bm_loop_walk_add(struct LoopWalkCtx *lwc, BMLoop *l)
+{
+ const int i = BM_elem_index_get(l);
+ const float w = lwc->loop_weights[i];
+ BM_elem_flag_enable(l, BM_ELEM_INTERNAL_TAG);
+ lwc->data_array[lwc->data_len] = BM_ELEM_CD_GET_VOID_P(l, lwc->cd_layer_offset);
+ lwc->data_index_array[lwc->data_len] = i;
+ lwc->weight_array[lwc->data_len] = w;
+ lwc->weight_accum += w;
+
+ lwc->data_len += 1;
+}
+
+/**
+ * called recursively, keep stack-usage minimal.
+ *
+ * \note called for fan matching so we're pretty much safe not to break the stack
+ */
+static void bm_loop_walk_data(struct LoopWalkCtx *lwc, BMLoop *l_walk)
+{
+ int i;
+
+ BLI_assert(CustomData_data_equals(lwc->type, lwc->data_ref, BM_ELEM_CD_GET_VOID_P(l_walk, lwc->cd_layer_offset)));
+ BLI_assert(BM_elem_flag_test(l_walk, BM_ELEM_INTERNAL_TAG) == false);
+
+ bm_loop_walk_add(lwc, l_walk);
+
+ /* recurse around this loop-fan (in both directions) */
+ for (i = 0; i < 2; i++) {
+ BMLoop *l_other = ((i == 0) ? l_walk : l_walk->prev)->radial_next;
+ if (l_other->radial_next != l_other) {
+ if (l_other->v != l_walk->v) {
+ l_other = l_other->next;
+ }
+ BLI_assert(l_other->v == l_walk->v);
+ if (!BM_elem_flag_test(l_other, BM_ELEM_INTERNAL_TAG)) {
+ if (CustomData_data_equals(lwc->type, lwc->data_ref, BM_ELEM_CD_GET_VOID_P(l_other, lwc->cd_layer_offset))) {
+ bm_loop_walk_data(lwc, l_other);
+ }
+ }
+ }
+ }
+}
+
+LinkNode *BM_vert_loop_groups_data_layer_create(
+ BMesh *bm, BMVert *v, const int layer_n, const float *loop_weights, MemArena *arena)
+{
+ struct LoopWalkCtx lwc;
+ LinkNode *groups = NULL;
+ BMLoop *l;
+ BMIter liter;
+ int loop_num;
+
+
+ lwc.type = bm->ldata.layers[layer_n].type;
+ lwc.cd_layer_offset = bm->ldata.layers[layer_n].offset;
+ lwc.loop_weights = loop_weights;
+ lwc.arena = arena;
+
+ loop_num = 0;
+ BM_ITER_ELEM (l, &liter, v, BM_LOOPS_OF_VERT) {
+ BM_elem_flag_disable(l, BM_ELEM_INTERNAL_TAG);
+ BM_elem_index_set(l, loop_num); /* set_dirty! */
+ loop_num++;
+ }
+ bm->elem_index_dirty |= BM_LOOP;
+
+ lwc.data_len = 0;
+ lwc.data_array = BLI_memarena_alloc(lwc.arena, sizeof(void *) * loop_num);
+ lwc.data_index_array = BLI_memarena_alloc(lwc.arena, sizeof(int) * loop_num);
+ lwc.weight_array = BLI_memarena_alloc(lwc.arena, sizeof(float) * loop_num);
+
+ BM_ITER_ELEM (l, &liter, v, BM_LOOPS_OF_VERT) {
+ if (!BM_elem_flag_test(l, BM_ELEM_INTERNAL_TAG)) {
+ struct LoopGroupCD *lf = BLI_memarena_alloc(lwc.arena, sizeof(*lf));
+ int len_prev = lwc.data_len;
+
+ lwc.data_ref = BM_ELEM_CD_GET_VOID_P(l, lwc.cd_layer_offset);
+
+ /* assign len-last */
+ lf->data = &lwc.data_array[lwc.data_len];
+ lf->data_index = &lwc.data_index_array[lwc.data_len];
+ lf->data_weights = &lwc.weight_array[lwc.data_len];
+ lwc.weight_accum = 0.0f;
+
+ /* new group */
+ bm_loop_walk_data(&lwc, l);
+ lf->data_len = lwc.data_len - len_prev;
+
+ if (LIKELY(lwc.weight_accum != 0.0f)) {
+ mul_vn_fl(lf->data_weights, lf->data_len, 1.0f / lwc.weight_accum);
+ }
+ else {
+ copy_vn_fl(lf->data_weights, lf->data_len, 1.0f / (float)lf->data_len);
+ }
+
+ BLI_linklist_prepend_arena(&groups, lf, lwc.arena);
+ }
+ }
+
+ BLI_assert(lwc.data_len == loop_num);
+
+ return groups;
+}
+
+static void bm_vert_loop_groups_data_layer_merge__single(
+ BMesh *bm, void *lf_p, int layer_n,
+ void *data_tmp)
+{
+ struct LoopGroupCD *lf = lf_p;
+ const int type = bm->ldata.layers[layer_n].type;
+ int i;
+ const float *data_weights;
+
+ data_weights = lf->data_weights;
+
+ CustomData_bmesh_interp_n(
+ &bm->ldata, (const void **)lf->data,
+ data_weights, NULL, lf->data_len, data_tmp, layer_n);
+
+ for (i = 0; i < lf->data_len; i++) {
+ CustomData_copy_elements(type, data_tmp, lf->data[i], 1);
+ }
+}
+
+static void bm_vert_loop_groups_data_layer_merge_weights__single(
+ BMesh *bm, void *lf_p, const int layer_n, void *data_tmp,
+ const float *loop_weights)
+{
+ struct LoopGroupCD *lf = lf_p;
+ const int type = bm->ldata.layers[layer_n].type;
+ int i;
+ const float *data_weights;
+
+ /* re-weight */
+ float *temp_weights = BLI_array_alloca(temp_weights, lf->data_len);
+ float weight_accum = 0.0f;
+
+ for (i = 0; i < lf->data_len; i++) {
+ float w = loop_weights[lf->data_index[i]] * lf->data_weights[i];
+ temp_weights[i] = w;
+ weight_accum += w;
+ }
+
+ if (LIKELY(weight_accum != 0.0f)) {
+ mul_vn_fl(temp_weights, lf->data_len, 1.0f / weight_accum);
+ data_weights = temp_weights;
+ }
+ else {
+ data_weights = lf->data_weights;
+ }
+
+ CustomData_bmesh_interp_n(
+ &bm->ldata, (const void **)lf->data,
+ data_weights, NULL, lf->data_len, data_tmp, layer_n);
+
+ for (i = 0; i < lf->data_len; i++) {
+ CustomData_copy_elements(type, data_tmp, lf->data[i], 1);
+ }
+}
+
+/**
+ * Take existing custom data and merge each fan's data.
+ */
+void BM_vert_loop_groups_data_layer_merge(BMesh *bm, LinkNode *groups, const int layer_n)
+{
+ const int type = bm->ldata.layers[layer_n].type;
+ const int size = CustomData_sizeof(type);
+ void *data_tmp = alloca(size);
+
+ do {
+ bm_vert_loop_groups_data_layer_merge__single(bm, groups->link, layer_n, data_tmp);
+ } while ((groups = groups->next));
+}
+
+/**
+ * A version of #BM_vert_loop_groups_data_layer_merge
+ * that takes an array of loop-weights (aligned with #BM_LOOPS_OF_VERT iterator)
+ */
+void BM_vert_loop_groups_data_layer_merge_weights(
+ BMesh *bm, LinkNode *groups, const int layer_n, const float *loop_weights)
+{
+ const int type = bm->ldata.layers[layer_n].type;
+ const int size = CustomData_sizeof(type);
+ void *data_tmp = alloca(size);
+
+ do {
+ bm_vert_loop_groups_data_layer_merge_weights__single(bm, groups->link, layer_n, data_tmp, loop_weights);
+ } while ((groups = groups->next));
+}
+
+/** \} */
diff --git a/source/blender/bmesh/intern/bmesh_interp.h b/source/blender/bmesh/intern/bmesh_interp.h
index c605ad31ae7..969e92f37db 100644
--- a/source/blender/bmesh/intern/bmesh_interp.h
+++ b/source/blender/bmesh/intern/bmesh_interp.h
@@ -27,12 +27,15 @@
* \ingroup bmesh
*/
-void BM_loop_interp_multires(BMesh *bm, BMLoop *target, BMFace *source);
-void BM_vert_interp_from_face(BMesh *bm, BMVert *v, BMFace *source);
+struct LinkNode;
+struct MemArena;
-void BM_data_interp_from_verts(BMesh *bm, BMVert *v1, BMVert *v2, BMVert *v, const float fac);
-void BM_data_interp_from_edges(BMesh *bm, BMEdge *e1, BMEdge *e2, BMEdge *e, const float fac);
-void BM_data_interp_face_vert_edge(BMesh *bm, BMVert *v1, BMVert *v2, BMVert *v, BMEdge *e1, const float fac);
+void BM_loop_interp_multires(BMesh *bm, BMLoop *l_dst, const BMFace *f_src);
+void BM_vert_interp_from_face(BMesh *bm, BMVert *v_dst, const BMFace *f_src);
+
+void BM_data_interp_from_verts(BMesh *bm, const BMVert *v_src_1, const BMVert *v_src_2, BMVert *v_dst, const float fac);
+void BM_data_interp_from_edges(BMesh *bm, const BMEdge *e_src_1, const BMEdge *e_src_2, BMEdge *e_dst, const float fac);
+void BM_data_interp_face_vert_edge(BMesh *bm, const BMVert *v_src_1, const BMVert *v_src_2, BMVert *v, BMEdge *e, const float fac);
void BM_data_layer_add(BMesh *bm, CustomData *data, int type);
void BM_data_layer_add_named(BMesh *bm, CustomData *data, int type, const char *name);
void BM_data_layer_free(BMesh *bm, CustomData *data, int type);
@@ -42,12 +45,26 @@ void BM_data_layer_copy(BMesh *bm, CustomData *data, int type, int src_n, int d
float BM_elem_float_data_get(CustomData *cd, void *element, int type);
void BM_elem_float_data_set(CustomData *cd, void *element, int type, const float val);
-void BM_face_interp_from_face_ex(BMesh *bm, BMFace *target, BMFace *source, const bool do_vertex,
- void **blocks, void **blocks_v, float (*cos_2d)[2], float axis_mat[3][3]);
-void BM_face_interp_from_face(BMesh *bm, BMFace *target, BMFace *source, const bool do_vertex);
-void BM_loop_interp_from_face(BMesh *bm, BMLoop *target, BMFace *source,
- const bool do_vertex, const bool do_multires);
+void BM_face_interp_from_face_ex(
+ BMesh *bm, BMFace *f_dst, const BMFace *f_src, const bool do_vertex,
+ const void **blocks, const void **blocks_v,
+ float (*cos_2d)[2], float axis_mat[3][3]);
+void BM_face_interp_from_face(
+ BMesh *bm, BMFace *f_dst, const BMFace *f_src,
+ const bool do_vertex);
+void BM_loop_interp_from_face(
+ BMesh *bm, BMLoop *l_dst, const BMFace *f_src,
+ const bool do_vertex, const bool do_multires);
void BM_face_multires_bounds_smooth(BMesh *bm, BMFace *f);
+struct LinkNode *BM_vert_loop_groups_data_layer_create(
+ BMesh *bm, BMVert *v, const int layer_n,
+ const float *loop_weights, struct MemArena *arena);
+void BM_vert_loop_groups_data_layer_merge(
+ BMesh *bm, struct LinkNode *groups, const int layer_n);
+void BM_vert_loop_groups_data_layer_merge_weights(
+ BMesh *bm, struct LinkNode *groups, const int layer_n,
+ const float *loop_weights);
+
#endif /* __BMESH_INTERP_H__ */
diff --git a/source/blender/bmesh/intern/bmesh_iterators.c b/source/blender/bmesh/intern/bmesh_iterators.c
index 476878ad38c..0abf41709a0 100644
--- a/source/blender/bmesh/intern/bmesh_iterators.c
+++ b/source/blender/bmesh/intern/bmesh_iterators.c
@@ -56,7 +56,7 @@ const char bm_iter_itype_htype_map[BM_ITYPE_MAX] = {
/**
* Utility function.
*/
-int BM_iter_mesh_count(BMesh *bm, const char itype)
+int BM_iter_mesh_count(const char itype, BMesh *bm)
{
int count;
@@ -136,8 +136,9 @@ int BM_iter_as_array(BMesh *bm, const char itype, void *data, void **array, cons
*
* Sometimes its convenient to get the iterator as an array.
*/
-int BMO_iter_as_array(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const char restrictmask,
- void **array, const int len)
+int BMO_iter_as_array(
+ BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const char restrictmask,
+ void **array, const int len)
{
int i = 0;
@@ -169,9 +170,10 @@ int BMO_iter_as_array(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_nam
*
* Caller needs to free the array.
*/
-void *BM_iter_as_arrayN(BMesh *bm, const char itype, void *data, int *r_len,
- /* optional args to avoid an alloc (normally stack array) */
- void **stack_array, int stack_array_size)
+void *BM_iter_as_arrayN(
+ BMesh *bm, const char itype, void *data, int *r_len,
+ /* optional args to avoid an alloc (normally stack array) */
+ void **stack_array, int stack_array_size)
{
BMIter iter;
@@ -212,10 +214,11 @@ void *BM_iter_as_arrayN(BMesh *bm, const char itype, void *data, int *r_len,
}
}
-void *BMO_iter_as_arrayN(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const char restrictmask,
- int *r_len,
- /* optional args to avoid an alloc (normally stack array) */
- void **stack_array, int stack_array_size)
+void *BMO_iter_as_arrayN(
+ BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const char restrictmask,
+ int *r_len,
+ /* optional args to avoid an alloc (normally stack array) */
+ void **stack_array, int stack_array_size)
{
BMOIter iter;
BMElem *ele;
@@ -273,8 +276,9 @@ int BM_iter_elem_count_flag(const char itype, void *data, const char hflag, cons
*
* Counts how many flagged / unflagged items are found in this element.
*/
-int BMO_iter_elem_count_flag(BMesh *bm, const char itype, void *data,
- const short oflag, const bool value)
+int BMO_iter_elem_count_flag(
+ BMesh *bm, const char itype, void *data,
+ const short oflag, const bool value)
{
BMIter iter;
BMElemF *ele;
diff --git a/source/blender/bmesh/intern/bmesh_iterators.h b/source/blender/bmesh/intern/bmesh_iterators.h
index 44be7072e71..c4b184ef8b8 100644
--- a/source/blender/bmesh/intern/bmesh_iterators.h
+++ b/source/blender/bmesh/intern/bmesh_iterators.h
@@ -84,30 +84,40 @@ typedef enum BMIterType {
extern const char bm_iter_itype_htype_map[BM_ITYPE_MAX];
#define BM_ITER_MESH(ele, iter, bm, itype) \
- for (ele = BM_iter_new(iter, bm, itype, NULL); ele; ele = BM_iter_step(iter))
+ for (BM_CHECK_TYPE_ELEM_ASSIGN(ele) = BM_iter_new(iter, bm, itype, NULL); \
+ ele; \
+ BM_CHECK_TYPE_ELEM_ASSIGN(ele) = BM_iter_step(iter))
#define BM_ITER_MESH_INDEX(ele, iter, bm, itype, indexvar) \
- for (ele = BM_iter_new(iter, bm, itype, NULL), indexvar = 0; ele; ele = BM_iter_step(iter), (indexvar)++)
+ for (BM_CHECK_TYPE_ELEM_ASSIGN(ele) = BM_iter_new(iter, bm, itype, NULL), indexvar = 0; \
+ ele; \
+ BM_CHECK_TYPE_ELEM_ASSIGN(ele) = BM_iter_step(iter), (indexvar)++)
/* a version of BM_ITER_MESH which keeps the next item in storage
* so we can delete the current item, see bug [#36923] */
#ifdef DEBUG
# define BM_ITER_MESH_MUTABLE(ele, ele_next, iter, bm, itype) \
- for (ele = BM_iter_new(iter, bm, itype, NULL); \
- ele ? ((void)((iter)->count = BM_iter_mesh_count(bm, itype)), \
- (void)(ele_next = BM_iter_step(iter)), 1) : 0; \
- ele = ele_next)
+ for (BM_CHECK_TYPE_ELEM_ASSIGN(ele) = BM_iter_new(iter, bm, itype, NULL); \
+ ele ? ((void)((iter)->count = BM_iter_mesh_count(itype, bm)), \
+ (void)(ele_next = BM_iter_step(iter)), 1) : 0; \
+ BM_CHECK_TYPE_ELEM_ASSIGN(ele) = ele_next)
#else
# define BM_ITER_MESH_MUTABLE(ele, ele_next, iter, bm, itype) \
- for (ele = BM_iter_new(iter, bm, itype, NULL); ele ? ((ele_next = BM_iter_step(iter)), 1) : 0; ele = ele_next)
+ for (BM_CHECK_TYPE_ELEM_ASSIGN(ele) = BM_iter_new(iter, bm, itype, NULL); \
+ ele ? ((BM_CHECK_TYPE_ELEM_ASSIGN(ele_next) = BM_iter_step(iter)), 1) : 0; \
+ ele = ele_next)
#endif
#define BM_ITER_ELEM(ele, iter, data, itype) \
- for (ele = BM_iter_new(iter, NULL, itype, data); ele; ele = BM_iter_step(iter))
+ for (BM_CHECK_TYPE_ELEM_ASSIGN(ele) = BM_iter_new(iter, NULL, itype, data); \
+ ele; \
+ BM_CHECK_TYPE_ELEM_ASSIGN(ele) = BM_iter_step(iter))
#define BM_ITER_ELEM_INDEX(ele, iter, data, itype, indexvar) \
- for (ele = BM_iter_new(iter, NULL, itype, data), indexvar = 0; ele; ele = BM_iter_step(iter), (indexvar)++)
+ for (BM_CHECK_TYPE_ELEM_ASSIGN(ele) = BM_iter_new(iter, NULL, itype, data), indexvar = 0; \
+ ele; \
+ BM_CHECK_TYPE_ELEM_ASSIGN(ele) = BM_iter_step(iter), (indexvar)++)
/* iterator type structs */
struct BMIter__elem_of_mesh {
@@ -185,20 +195,22 @@ typedef struct BMIter {
char itype;
} BMIter;
-int BM_iter_mesh_count(BMesh *bm, const char itype);
void *BM_iter_at_index(BMesh *bm, const char itype, void *data, int index) ATTR_WARN_UNUSED_RESULT;
int BM_iter_as_array(BMesh *bm, const char itype, void *data, void **array, const int len);
-void *BM_iter_as_arrayN(BMesh *bm, const char itype, void *data, int *r_len,
- void **stack_array, int stack_array_size) ATTR_WARN_UNUSED_RESULT;
-int BMO_iter_as_array(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const char restrictmask,
- void **array, const int len);
-void *BMO_iter_as_arrayN(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const char restrictmask,
- int *r_len,
- /* optional args to avoid an alloc (normally stack array) */
- void **stack_array, int stack_array_size);
-
+void *BM_iter_as_arrayN(
+ BMesh *bm, const char itype, void *data, int *r_len,
+ void **stack_array, int stack_array_size) ATTR_WARN_UNUSED_RESULT;
+int BMO_iter_as_array(
+ BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const char restrictmask,
+ void **array, const int len);
+void *BMO_iter_as_arrayN(
+ BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const char restrictmask,
+ int *r_len,
+ /* optional args to avoid an alloc (normally stack array) */
+ void **stack_array, int stack_array_size);
int BM_iter_elem_count_flag(const char itype, void *data, const char hflag, const bool value);
int BMO_iter_elem_count_flag(BMesh *bm, const char itype, void *data, const short oflag, const bool value);
+int BM_iter_mesh_count(const char itype, BMesh *bm);
int BM_iter_mesh_count_flag(const char itype, BMesh *bm, const char hflag, const bool value);
/* private for bmesh_iterators_inline.c */
diff --git a/source/blender/bmesh/intern/bmesh_iterators_inline.h b/source/blender/bmesh/intern/bmesh_iterators_inline.h
index d3e18b97acb..e68440021e6 100644
--- a/source/blender/bmesh/intern/bmesh_iterators_inline.h
+++ b/source/blender/bmesh/intern/bmesh_iterators_inline.h
@@ -37,6 +37,7 @@
*
* Calls an iterators step function to return the next element.
*/
+ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
BLI_INLINE void *BM_iter_step(BMIter *iter)
{
return iter->step(iter);
@@ -50,6 +51,7 @@ BLI_INLINE void *BM_iter_step(BMIter *iter)
* it with the appropriate function pointers based
* upon its type.
*/
+ATTR_NONNULL(1)
BLI_INLINE bool BM_iter_init(BMIter *iter, BMesh *bm, const char itype, void *data)
{
/* int argtype; */
@@ -169,6 +171,7 @@ BLI_INLINE bool BM_iter_init(BMIter *iter, BMesh *bm, const char itype, void *da
* to return the first element of the iterator.
*
*/
+ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
BLI_INLINE void *BM_iter_new(BMIter *iter, BMesh *bm, const char itype, void *data)
{
if (LIKELY(BM_iter_init(iter, bm, itype, data))) {
diff --git a/source/blender/bmesh/intern/bmesh_log.c b/source/blender/bmesh/intern/bmesh_log.c
index 0bb1a892ffe..1f64f7b74cc 100644
--- a/source/blender/bmesh/intern/bmesh_log.c
+++ b/source/blender/bmesh/intern/bmesh_log.c
@@ -115,8 +115,8 @@ struct BMLog {
typedef struct {
float co[3];
short no[3];
- float mask;
char hflag;
+ float mask;
} BMLogVert;
typedef struct {
@@ -126,6 +126,10 @@ typedef struct {
/************************* Get/set element IDs ************************/
+/* bypass actual hashing, the keys don't overlap */
+#define logkey_hash BLI_ghashutil_inthash_p_simple
+#define logkey_cmp BLI_ghashutil_intcmp
+
/* Get the vertex's unique ID from the log */
static unsigned int bm_log_vert_id_get(BMLog *log, BMVert *v)
{
@@ -386,12 +390,12 @@ static BMLogEntry *bm_log_entry_create(void)
{
BMLogEntry *entry = MEM_callocN(sizeof(BMLogEntry), __func__);
- entry->deleted_verts = BLI_ghash_ptr_new(__func__);
- entry->deleted_faces = BLI_ghash_ptr_new(__func__);
- entry->added_verts = BLI_ghash_ptr_new(__func__);
- entry->added_faces = BLI_ghash_ptr_new(__func__);
- entry->modified_verts = BLI_ghash_ptr_new(__func__);
- entry->modified_faces = BLI_ghash_ptr_new(__func__);
+ entry->deleted_verts = BLI_ghash_new(logkey_hash, logkey_cmp, __func__);
+ entry->deleted_faces = BLI_ghash_new(logkey_hash, logkey_cmp, __func__);
+ entry->added_verts = BLI_ghash_new(logkey_hash, logkey_cmp, __func__);
+ entry->added_faces = BLI_ghash_new(logkey_hash, logkey_cmp, __func__);
+ entry->modified_verts = BLI_ghash_new(logkey_hash, logkey_cmp, __func__);
+ entry->modified_faces = BLI_ghash_new(logkey_hash, logkey_cmp, __func__);
entry->pool_verts = BLI_mempool_create(sizeof(BMLogVert), 0, 64, BLI_MEMPOOL_NOP);
entry->pool_faces = BLI_mempool_create(sizeof(BMLogFace), 0, 64, BLI_MEMPOOL_NOP);
@@ -423,9 +427,7 @@ static void bm_log_id_ghash_retake(RangeTreeUInt *unused_ids, GHash *id_ghash)
void *key = BLI_ghashIterator_getKey(&gh_iter);
unsigned int id = GET_UINT_FROM_POINTER(key);
- if (range_tree_uint_has(unused_ids, id)) {
- range_tree_uint_take(unused_ids, id);
- }
+ range_tree_uint_retake(unused_ids, id);
}
}
@@ -478,10 +480,11 @@ static void bm_log_id_ghash_release(BMLog *log, GHash *id_ghash)
BMLog *BM_log_create(BMesh *bm)
{
BMLog *log = MEM_callocN(sizeof(*log), __func__);
+ const unsigned int reserve_num = (unsigned int)(bm->totvert + bm->totface);
log->unused_ids = range_tree_uint_alloc(0, (unsigned)-1);
- log->id_to_elem = BLI_ghash_ptr_new_ex(__func__, (unsigned int)(bm->totvert + bm->totface));
- log->elem_to_id = BLI_ghash_ptr_new_ex(__func__, (unsigned int)(bm->totvert + bm->totface));
+ log->id_to_elem = BLI_ghash_new_ex(logkey_hash, logkey_cmp, __func__, reserve_num);
+ log->elem_to_id = BLI_ghash_ptr_new_ex(__func__, reserve_num);
/* Assign IDs to all existing vertices and faces */
bm_log_assign_ids(bm, log);
@@ -584,14 +587,14 @@ void BM_log_free(BMLog *log)
/* Get the number of log entries */
int BM_log_length(const BMLog *log)
{
- return BLI_countlist(&log->entries);
+ return BLI_listbase_count(&log->entries);
}
/* Apply a consistent ordering to BMesh vertices */
void BM_log_mesh_elems_reorder(BMesh *bm, BMLog *log)
{
- void *varr;
- void *farr;
+ unsigned int *varr;
+ unsigned int *farr;
GHash *id_to_idx;
@@ -599,41 +602,37 @@ void BM_log_mesh_elems_reorder(BMesh *bm, BMLog *log)
BMVert *v;
BMFace *f;
- int i;
+ unsigned int i;
/* Put all vertex IDs into an array */
- i = 0;
varr = MEM_mallocN(sizeof(int) * (size_t)bm->totvert, __func__);
- BM_ITER_MESH (v, &bm_iter, bm, BM_VERTS_OF_MESH) {
- ((unsigned int *)varr)[i++] = bm_log_vert_id_get(log, v);
+ BM_ITER_MESH_INDEX (v, &bm_iter, bm, BM_VERTS_OF_MESH, i) {
+ varr[i] = bm_log_vert_id_get(log, v);
}
/* Put all face IDs into an array */
- i = 0;
farr = MEM_mallocN(sizeof(int) * (size_t)bm->totface, __func__);
- BM_ITER_MESH (f, &bm_iter, bm, BM_FACES_OF_MESH) {
- ((unsigned int *)farr)[i++] = bm_log_face_id_get(log, f);
+ BM_ITER_MESH_INDEX (f, &bm_iter, bm, BM_FACES_OF_MESH, i) {
+ farr[i] = bm_log_face_id_get(log, f);
}
/* Create BMVert index remap array */
id_to_idx = bm_log_compress_ids_to_indices(varr, (unsigned int)bm->totvert);
- i = 0;
- BM_ITER_MESH (v, &bm_iter, bm, BM_VERTS_OF_MESH) {
+ BM_ITER_MESH_INDEX (v, &bm_iter, bm, BM_VERTS_OF_MESH, i) {
const unsigned id = bm_log_vert_id_get(log, v);
const void *key = SET_UINT_IN_POINTER(id);
const void *val = BLI_ghash_lookup(id_to_idx, key);
- ((unsigned int *)varr)[i++] = GET_UINT_FROM_POINTER(val);
+ varr[i] = GET_UINT_FROM_POINTER(val);
}
BLI_ghash_free(id_to_idx, NULL, NULL);
/* Create BMFace index remap array */
id_to_idx = bm_log_compress_ids_to_indices(farr, (unsigned int)bm->totface);
- i = 0;
- BM_ITER_MESH (f, &bm_iter, bm, BM_FACES_OF_MESH) {
+ BM_ITER_MESH_INDEX (f, &bm_iter, bm, BM_FACES_OF_MESH, i) {
const unsigned id = bm_log_face_id_get(log, f);
const void *key = SET_UINT_IN_POINTER(id);
const void *val = BLI_ghash_lookup(id_to_idx, key);
- ((unsigned int *)farr)[i++] = GET_UINT_FROM_POINTER(val);
+ farr[i] = GET_UINT_FROM_POINTER(val);
}
BLI_ghash_free(id_to_idx, NULL, NULL);
@@ -838,14 +837,15 @@ void BM_log_vert_before_modified(BMLog *log, BMVert *v, const int cd_vert_mask_o
BMLogVert *lv;
unsigned int v_id = bm_log_vert_id_get(log, v);
void *key = SET_UINT_IN_POINTER(v_id);
+ void **val_p;
/* Find or create the BMLogVert entry */
if ((lv = BLI_ghash_lookup(entry->added_verts, key))) {
bm_log_vert_bmvert_copy(lv, v, cd_vert_mask_offset);
}
- else if (!BLI_ghash_haskey(entry->modified_verts, key)) {
+ else if (!BLI_ghash_ensure_p(entry->modified_verts, key, &val_p)) {
lv = bm_log_vert_alloc(log, v, cd_vert_mask_offset);
- BLI_ghash_insert(entry->modified_verts, key, lv);
+ *val_p = lv;
}
}
@@ -989,6 +989,15 @@ void BM_log_all_added(BMesh *bm, BMLog *log)
BMVert *v;
BMFace *f;
+ /* avoid unnecessary resizing on initialization */
+ if (BLI_ghash_size(log->current_entry->added_verts) == 0) {
+ BLI_ghash_reserve(log->current_entry->added_verts, (unsigned int)bm->totvert);
+ }
+
+ if (BLI_ghash_size(log->current_entry->added_faces) == 0) {
+ BLI_ghash_reserve(log->current_entry->added_faces, (unsigned int)bm->totface);
+ }
+
/* Log all vertices as newly created */
BM_ITER_MESH (v, &bm_iter, bm, BM_VERTS_OF_MESH) {
BM_log_vert_added(log, v, cd_vert_mask_offset);
@@ -1073,6 +1082,24 @@ float BM_log_original_mask(BMLog *log, BMVert *v)
return lv->mask;
}
+void BM_log_original_vert_data(
+ BMLog *log, BMVert *v,
+ const float **r_co, const short **r_no)
+{
+ BMLogEntry *entry = log->current_entry;
+ const BMLogVert *lv;
+ unsigned v_id = bm_log_vert_id_get(log, v);
+ void *key = SET_UINT_IN_POINTER(v_id);
+
+ BLI_assert(entry);
+
+ BLI_assert(BLI_ghash_haskey(entry->modified_verts, key));
+
+ lv = BLI_ghash_lookup(entry->modified_verts, key);
+ *r_co = lv->co;
+ *r_no = lv->no;
+}
+
/************************ Debugging and Testing ***********************/
/* For internal use only (unit testing) */
diff --git a/source/blender/bmesh/intern/bmesh_log.h b/source/blender/bmesh/intern/bmesh_log.h
index 2147b5c64b4..dd1772af068 100644
--- a/source/blender/bmesh/intern/bmesh_log.h
+++ b/source/blender/bmesh/intern/bmesh_log.h
@@ -96,6 +96,11 @@ const short *BM_log_original_vert_no(BMLog *log, BMVert *v);
/* Get the logged mask of a vertex */
float BM_log_original_mask(BMLog *log, BMVert *v);
+/* Get the logged data of a vertex (avoid multiple lookups) */
+void BM_log_original_vert_data(
+ BMLog *log, BMVert *v,
+ const float **r_co, const short **r_no);
+
/* For internal use only (unit testing) */
BMLogEntry *BM_log_current_entry(BMLog *log);
struct RangeTreeUInt *BM_log_unused_ids(BMLog *log);
diff --git a/source/blender/bmesh/intern/bmesh_marking.c b/source/blender/bmesh/intern/bmesh_marking.c
index ee35d8cd1d2..17b6d1d99e7 100644
--- a/source/blender/bmesh/intern/bmesh_marking.c
+++ b/source/blender/bmesh/intern/bmesh_marking.c
@@ -41,6 +41,7 @@
#include "BLI_listbase.h"
#include "bmesh.h"
+#include "bmesh_structure.h"
static void recount_totsels(BMesh *bm)
{
@@ -69,6 +70,69 @@ static void recount_totsels(BMesh *bm)
}
}
+/** \name BMesh helper functions for selection flushing.
+ * \{ */
+
+static bool bm_vert_is_edge_select_any_other(const BMVert *v, const BMEdge *e_first)
+{
+ const BMEdge *e_iter = e_first;
+
+ /* start by stepping over the current edge */
+ while ((e_iter = bmesh_disk_edge_next(e_iter, v)) != e_first) {
+ if (BM_elem_flag_test(e_iter, BM_ELEM_SELECT)) {
+ return true;
+ }
+ }
+ return false;
+}
+
+#if 0
+static bool bm_vert_is_edge_select_any(const BMVert *v)
+{
+ if (v->e) {
+ const BMEdge *e_iter, *e_first;
+ e_iter = e_first = v->e;
+ do {
+ if (BM_elem_flag_test(e_iter, BM_ELEM_SELECT)) {
+ return true;
+ }
+ } while ((e_iter = bmesh_disk_edge_next(e_iter, v)) != e_first);
+ }
+ return false;
+}
+#endif
+
+static bool bm_edge_is_face_select_any_other(BMLoop *l_first)
+{
+ const BMLoop *l_iter = l_first;
+
+ /* start by stepping over the current face */
+ while ((l_iter = l_iter->radial_next) != l_first) {
+ if (BM_elem_flag_test(l_iter->f, BM_ELEM_SELECT)) {
+ return true;
+ }
+ }
+ return false;
+}
+
+#if 0
+static bool bm_edge_is_face_select_any(const BMEdge *e)
+{
+ if (e->l) {
+ const BMLoop *l_iter, *l_first;
+ l_iter = l_first = e->l;
+ do {
+ if (BM_elem_flag_test(l_iter->f, BM_ELEM_SELECT)) {
+ return true;
+ }
+ } while ((l_iter = l_iter->radial_next) != l_first);
+ }
+ return false;
+}
+#endif
+
+/** \} */
+
/**
* \brief Select Mode Clean
*
@@ -341,8 +405,8 @@ void BM_vert_select_set(BMesh *bm, BMVert *v, const bool select)
if (select) {
if (!BM_elem_flag_test(v, BM_ELEM_SELECT)) {
- bm->totvertsel += 1;
BM_elem_flag_enable(v, BM_ELEM_SELECT);
+ bm->totvertsel += 1;
}
}
else {
@@ -367,39 +431,27 @@ void BM_edge_select_set(BMesh *bm, BMEdge *e, const bool select)
}
if (select) {
- if (!BM_elem_flag_test(e, BM_ELEM_SELECT)) bm->totedgesel += 1;
-
- BM_elem_flag_enable(e, BM_ELEM_SELECT);
+ if (!BM_elem_flag_test(e, BM_ELEM_SELECT)) {
+ BM_elem_flag_enable(e, BM_ELEM_SELECT);
+ bm->totedgesel += 1;
+ }
BM_vert_select_set(bm, e->v1, true);
BM_vert_select_set(bm, e->v2, true);
}
else {
- if (BM_elem_flag_test(e, BM_ELEM_SELECT)) bm->totedgesel -= 1;
- BM_elem_flag_disable(e, BM_ELEM_SELECT);
+ if (BM_elem_flag_test(e, BM_ELEM_SELECT)) {
+ BM_elem_flag_disable(e, BM_ELEM_SELECT);
+ bm->totedgesel -= 1;
+ }
if ((bm->selectmode & SCE_SELECT_VERTEX) == 0) {
- BMIter iter;
- BMVert *verts[2] = {e->v1, e->v2};
- BMEdge *e2;
int i;
/* check if the vert is used by a selected edge */
for (i = 0; i < 2; i++) {
- bool deselect = true;
-
- for (e2 = BM_iter_new(&iter, bm, BM_EDGES_OF_VERT, verts[i]); e2; e2 = BM_iter_step(&iter)) {
- if (e2 == e) {
- continue;
- }
-
- if (BM_elem_flag_test(e2, BM_ELEM_SELECT)) {
- deselect = false;
- break;
- }
- }
-
- if (deselect) {
- BM_vert_select_set(bm, verts[i], false);
+ BMVert *v = *((&e->v1) + i);
+ if (bm_vert_is_edge_select_any_other(v, e) == false) {
+ BM_vert_select_set(bm, v, false);
}
}
}
@@ -430,10 +482,10 @@ void BM_face_select_set(BMesh *bm, BMFace *f, const bool select)
if (select) {
if (!BM_elem_flag_test(f, BM_ELEM_SELECT)) {
- bm->totfacesel++;
+ BM_elem_flag_enable(f, BM_ELEM_SELECT);
+ bm->totfacesel += 1;
}
- BM_elem_flag_enable(f, BM_ELEM_SELECT);
l_iter = l_first = BM_FACE_FIRST_LOOP(f);
do {
BM_vert_select_set(bm, l_iter->v, true);
@@ -441,42 +493,80 @@ void BM_face_select_set(BMesh *bm, BMFace *f, const bool select)
} while ((l_iter = l_iter->next) != l_first);
}
else {
- BMIter liter;
- BMLoop *l;
- if (BM_elem_flag_test(f, BM_ELEM_SELECT)) bm->totfacesel -= 1;
- BM_elem_flag_disable(f, BM_ELEM_SELECT);
+ if (BM_elem_flag_test(f, BM_ELEM_SELECT)) {
+ BM_elem_flag_disable(f, BM_ELEM_SELECT);
+ bm->totfacesel -= 1;
+ }
/* flush down to edges */
- BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) {
- BMIter fiter;
- BMFace *f2;
- BM_ITER_ELEM (f2, &fiter, l->e, BM_FACES_OF_EDGE) {
- if (BM_elem_flag_test(f2, BM_ELEM_SELECT))
- break;
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
+ /* vertex flushing is handled below */
+ if (bm_edge_is_face_select_any_other(l_iter) == false) {
+ BM_edge_select_set_noflush(bm, l_iter->e, false);
}
+ } while ((l_iter = l_iter->next) != l_first);
- if (!f2) {
- BM_edge_select_set(bm, l->e, false);
+ /* flush down to verts */
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
+ if (bm_vert_is_edge_select_any_other(l_iter->v, l_iter->e) == false) {
+ BM_vert_select_set(bm, l_iter->v, false);
}
+ } while ((l_iter = l_iter->next) != l_first);
+ }
+}
+
+/** \name Non flushing versions element selection.
+ * \{ */
+
+void BM_edge_select_set_noflush(BMesh *bm, BMEdge *e, const bool select)
+{
+ BLI_assert(e->head.htype == BM_EDGE);
+
+ if (BM_elem_flag_test(e, BM_ELEM_HIDDEN)) {
+ return;
+ }
+
+ if (select) {
+ if (!BM_elem_flag_test(e, BM_ELEM_SELECT)) {
+ BM_elem_flag_enable(e, BM_ELEM_SELECT);
+ bm->totedgesel += 1;
+ }
+ }
+ else {
+ if (BM_elem_flag_test(e, BM_ELEM_SELECT)) {
+ BM_elem_flag_disable(e, BM_ELEM_SELECT);
+ bm->totedgesel -= 1;
}
+ }
+}
- /* flush down to verts */
- BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) {
- BMIter eiter;
- BMEdge *e;
- BM_ITER_ELEM (e, &eiter, l->v, BM_EDGES_OF_VERT) {
- if (BM_elem_flag_test(e, BM_ELEM_SELECT))
- break;
- }
+void BM_face_select_set_noflush(BMesh *bm, BMFace *f, const bool select)
+{
+ BLI_assert(f->head.htype == BM_FACE);
- if (!e) {
- BM_vert_select_set(bm, l->v, false);
- }
+ if (BM_elem_flag_test(f, BM_ELEM_HIDDEN)) {
+ return;
+ }
+
+ if (select) {
+ if (!BM_elem_flag_test(f, BM_ELEM_SELECT)) {
+ BM_elem_flag_enable(f, BM_ELEM_SELECT);
+ bm->totfacesel += 1;
+ }
+ }
+ else {
+ if (BM_elem_flag_test(f, BM_ELEM_SELECT)) {
+ BM_elem_flag_disable(f, BM_ELEM_SELECT);
+ bm->totfacesel -= 1;
}
}
}
+/** \} */
+
/**
* Select Mode Set
*
@@ -536,8 +626,9 @@ void BM_mesh_select_mode_set(BMesh *bm, int selectmode)
/**
* counts number of elements with flag enabled/disabled
*/
-static int bm_mesh_flag_count(BMesh *bm, const char htype, const char hflag,
- const bool respecthide, const bool test_for_enabled)
+static int bm_mesh_flag_count(
+ BMesh *bm, const char htype, const char hflag,
+ const bool respecthide, const bool test_for_enabled)
{
BMElem *ele;
BMIter iter;
@@ -823,6 +914,12 @@ void _bm_select_history_store_notest(BMesh *bm, BMHeader *ele)
BLI_addtail(&(bm->selected), ese);
}
+void _bm_select_history_store_head_notest(BMesh *bm, BMHeader *ele)
+{
+ BMEditSelection *ese = bm_select_history_create(ele);
+ BLI_addhead(&(bm->selected), ese);
+}
+
void _bm_select_history_store(BMesh *bm, BMHeader *ele)
{
if (!BM_select_history_check(bm, (BMElem *)ele)) {
@@ -830,6 +927,12 @@ void _bm_select_history_store(BMesh *bm, BMHeader *ele)
}
}
+void _bm_select_history_store_head(BMesh *bm, BMHeader *ele)
+{
+ if (!BM_select_history_check(bm, (BMElem *)ele)) {
+ BM_select_history_store_head_notest(bm, (BMElem *)ele);
+ }
+}
void _bm_select_history_store_after_notest(BMesh *bm, BMEditSelection *ese_ref, BMHeader *ele)
{
@@ -923,8 +1026,9 @@ GHash *BM_select_history_map_create(BMesh *bm)
return map;
}
-void BM_mesh_elem_hflag_disable_test(BMesh *bm, const char htype, const char hflag,
- const bool respecthide, const bool overwrite, const char hflag_test)
+void BM_mesh_elem_hflag_disable_test(
+ BMesh *bm, const char htype, const char hflag,
+ const bool respecthide, const bool overwrite, const char hflag_test)
{
const char iter_types[3] = {BM_VERTS_OF_MESH,
BM_EDGES_OF_MESH,
@@ -994,8 +1098,9 @@ void BM_mesh_elem_hflag_disable_test(BMesh *bm, const char htype, const char hfl
}
}
-void BM_mesh_elem_hflag_enable_test(BMesh *bm, const char htype, const char hflag,
- const bool respecthide, const bool overwrite, const char hflag_test)
+void BM_mesh_elem_hflag_enable_test(
+ BMesh *bm, const char htype, const char hflag,
+ const bool respecthide, const bool overwrite, const char hflag_test)
{
const char iter_types[3] = {BM_VERTS_OF_MESH,
BM_EDGES_OF_MESH,
@@ -1049,15 +1154,17 @@ void BM_mesh_elem_hflag_enable_test(BMesh *bm, const char htype, const char hfla
}
}
-void BM_mesh_elem_hflag_disable_all(BMesh *bm, const char htype, const char hflag,
- const bool respecthide)
+void BM_mesh_elem_hflag_disable_all(
+ BMesh *bm, const char htype, const char hflag,
+ const bool respecthide)
{
/* call with 0 hflag_test */
BM_mesh_elem_hflag_disable_test(bm, htype, hflag, respecthide, false, 0);
}
-void BM_mesh_elem_hflag_enable_all(BMesh *bm, const char htype, const char hflag,
- const bool respecthide)
+void BM_mesh_elem_hflag_enable_all(
+ BMesh *bm, const char htype, const char hflag,
+ const bool respecthide)
{
/* call with 0 hflag_test */
BM_mesh_elem_hflag_enable_test(bm, htype, hflag, respecthide, false, 0);
diff --git a/source/blender/bmesh/intern/bmesh_marking.h b/source/blender/bmesh/intern/bmesh_marking.h
index 9e0c0923164..4730af66a74 100644
--- a/source/blender/bmesh/intern/bmesh_marking.h
+++ b/source/blender/bmesh/intern/bmesh_marking.h
@@ -43,15 +43,19 @@ void BM_face_hide_set(BMFace *f, const bool hide);
/* Selection code */
void BM_elem_select_set(BMesh *bm, BMElem *ele, const bool select);
-void BM_mesh_elem_hflag_enable_test(BMesh *bm, const char htype, const char hflag,
- const bool respecthide, const bool overwrite, const char hflag_test);
-void BM_mesh_elem_hflag_disable_test(BMesh *bm, const char htype, const char hflag,
- const bool respecthide, const bool overwrite, const char hflag_test);
-
-void BM_mesh_elem_hflag_enable_all(BMesh *bm, const char htype, const char hflag,
- const bool respecthide);
-void BM_mesh_elem_hflag_disable_all(BMesh *bm, const char htype, const char hflag,
- const bool respecthide);
+void BM_mesh_elem_hflag_enable_test(
+ BMesh *bm, const char htype, const char hflag,
+ const bool respecthide, const bool overwrite, const char hflag_test);
+void BM_mesh_elem_hflag_disable_test(
+ BMesh *bm, const char htype, const char hflag,
+ const bool respecthide, const bool overwrite, const char hflag_test);
+
+void BM_mesh_elem_hflag_enable_all(
+ BMesh *bm, const char htype, const char hflag,
+ const bool respecthide);
+void BM_mesh_elem_hflag_disable_all(
+ BMesh *bm, const char htype, const char hflag,
+ const bool respecthide);
/* individual element select functions, BM_elem_select_set is a shortcut for these
* that automatically detects which one to use*/
@@ -59,6 +63,10 @@ void BM_vert_select_set(BMesh *bm, BMVert *v, const bool select);
void BM_edge_select_set(BMesh *bm, BMEdge *e, const bool select);
void BM_face_select_set(BMesh *bm, BMFace *f, const bool select);
+/* lower level functions which don't do flushing */
+void BM_edge_select_set_noflush(BMesh *bm, BMEdge *e, const bool select);
+void BM_face_select_set_noflush(BMesh *bm, BMFace *e, const bool select);
+
void BM_mesh_select_mode_clean_ex(BMesh *bm, const short selectmode);
void BM_mesh_select_mode_clean(BMesh *bm);
@@ -87,6 +95,8 @@ void BM_editselection_plane(BMEditSelection *ese, float r_plane[3]);
#define BM_select_history_remove(bm, ele) _bm_select_history_remove(bm, &(ele)->head)
#define BM_select_history_store_notest(bm, ele) _bm_select_history_store_notest(bm, &(ele)->head)
#define BM_select_history_store(bm, ele) _bm_select_history_store(bm, &(ele)->head)
+#define BM_select_history_store_head_notest(bm, ele) _bm_select_history_store_head_notest(bm, &(ele)->head)
+#define BM_select_history_store_head(bm, ele) _bm_select_history_store_head(bm, &(ele)->head)
#define BM_select_history_store_after_notest(bm, ese_ref, ele) _bm_select_history_store_after_notest(bm, ese_ref, &(ele)->head)
#define BM_select_history_store_after(bm, ese, ese_ref) _bm_select_history_store_after(bm, ese_ref, &(ele)->head)
@@ -94,6 +104,8 @@ bool _bm_select_history_check(BMesh *bm, const BMHeader *ele);
bool _bm_select_history_remove(BMesh *bm, BMHeader *ele);
void _bm_select_history_store_notest(BMesh *bm, BMHeader *ele);
void _bm_select_history_store(BMesh *bm, BMHeader *ele);
+void _bm_select_history_store_head_notest(BMesh *bm, BMHeader *ele);
+void _bm_select_history_store_head(BMesh *bm, BMHeader *ele);
void _bm_select_history_store_after(BMesh *bm, BMEditSelection *ese_ref, BMHeader *ele);
void _bm_select_history_store_after_notest(BMesh *bm, BMEditSelection *ese_ref, BMHeader *ele);
diff --git a/source/blender/bmesh/intern/bmesh_mesh.c b/source/blender/bmesh/intern/bmesh_mesh.c
index b16ea42304a..115330cb25a 100644
--- a/source/blender/bmesh/intern/bmesh_mesh.c
+++ b/source/blender/bmesh/intern/bmesh_mesh.c
@@ -34,10 +34,12 @@
#include "BLI_linklist_stack.h"
#include "BLI_listbase.h"
#include "BLI_math.h"
+#include "BLI_stack.h"
#include "BLI_utildefines.h"
#include "BKE_cdderivedmesh.h"
#include "BKE_editmesh.h"
+#include "BKE_mesh.h"
#include "BKE_multires.h"
#include "intern/bmesh_private.h"
@@ -301,8 +303,9 @@ static void bm_mesh_edges_calc_vectors(BMesh *bm, float (*edgevec)[3], const flo
bm->elem_index_dirty &= ~BM_EDGE;
}
-static void bm_mesh_verts_calc_normals(BMesh *bm, const float (*edgevec)[3], const float (*fnos)[3],
- const float (*vcos)[3], float (*vnos)[3])
+static void bm_mesh_verts_calc_normals(
+ BMesh *bm, const float (*edgevec)[3], const float (*fnos)[3],
+ const float (*vcos)[3], float (*vnos)[3])
{
BM_mesh_elem_index_ensure(bm, (vnos) ? (BM_EDGE | BM_VERT) : BM_EDGE);
@@ -435,10 +438,12 @@ void BM_verts_calc_normal_vcos(BMesh *bm, const float (*fnos)[3], const float (*
/**
* Helpers for #BM_mesh_loop_normals_update and #BM_loops_calc_normals_vnos
*/
-static void bm_mesh_edges_sharp_tag(BMesh *bm, const float (*vnos)[3], const float (*fnos)[3], float split_angle,
- float (*r_lnos)[3])
+static void bm_mesh_edges_sharp_tag(
+ BMesh *bm, const float (*vnos)[3], const float (*fnos)[3], float split_angle,
+ float (*r_lnos)[3])
{
- BMIter eiter;
+ BMIter eiter, viter;
+ BMVert *v;
BMEdge *e;
int i;
@@ -450,15 +455,18 @@ static void bm_mesh_edges_sharp_tag(BMesh *bm, const float (*vnos)[3], const flo
{
char htype = BM_LOOP;
- if (vnos) {
- htype |= BM_VERT;
- }
if (fnos) {
htype |= BM_FACE;
}
BM_mesh_elem_index_ensure(bm, htype);
}
+ /* Clear all vertices' tags (means they are all smooth for now). */
+ BM_ITER_MESH_INDEX (v, &viter, bm, BM_VERTS_OF_MESH, i) {
+ BM_elem_index_set(v, i); /* set_inline */
+ BM_elem_flag_disable(v, BM_ELEM_TAG);
+ }
+
/* This first loop checks which edges are actually smooth, and pre-populate lnos with vnos (as if they were
* all smooth).
*/
@@ -481,13 +489,13 @@ static void bm_mesh_edges_sharp_tag(BMesh *bm, const float (*vnos)[3], const flo
* If the angle between both its polys' normals is below split_angle value,
* and it is tagged as such,
* and both its faces are smooth,
- * and both its faces have compatible (non-flipped) normals, i.e. both loops on the same edge do not share
- * the same vertex.
+ * and both its faces have compatible (non-flipped) normals,
+ * i.e. both loops on the same edge do not share the same vertex.
*/
if (is_angle_smooth &&
- BM_elem_flag_test_bool(e, BM_ELEM_SMOOTH) &&
- BM_elem_flag_test_bool(l_a->f, BM_ELEM_SMOOTH) &&
- BM_elem_flag_test_bool(l_b->f, BM_ELEM_SMOOTH) &&
+ BM_elem_flag_test(e, BM_ELEM_SMOOTH) &&
+ BM_elem_flag_test(l_a->f, BM_ELEM_SMOOTH) &&
+ BM_elem_flag_test(l_b->f, BM_ELEM_SMOOTH) &&
l_a->v != l_b->v)
{
const float *no;
@@ -499,20 +507,40 @@ static void bm_mesh_edges_sharp_tag(BMesh *bm, const float (*vnos)[3], const flo
no = vnos ? vnos[BM_elem_index_get(l_b->v)] : l_b->v->no;
copy_v3_v3(r_lnos[BM_elem_index_get(l_b)], no);
}
+ else {
+ /* Sharp edge, tag its verts as such. */
+ BM_elem_flag_enable(e->v1, BM_ELEM_TAG);
+ BM_elem_flag_enable(e->v2, BM_ELEM_TAG);
+ }
+ }
+ else {
+ /* Sharp edge, tag its verts as such. */
+ BM_elem_flag_enable(e->v1, BM_ELEM_TAG);
+ BM_elem_flag_enable(e->v2, BM_ELEM_TAG);
}
}
- bm->elem_index_dirty &= ~BM_EDGE;
+ bm->elem_index_dirty &= ~(BM_EDGE | BM_VERT);
}
-/* BMesh version of BKE_mesh_normals_loop_split() in mesh_evaluate.c */
-static void bm_mesh_loops_calc_normals(BMesh *bm, const float (*vcos)[3], const float (*fnos)[3], float (*r_lnos)[3])
+/* BMesh version of BKE_mesh_normals_loop_split() in mesh_evaluate.c
+ * Will use first clnors_data array, and fallback to cd_loop_clnors_offset (use NULL and -1 to not use clnors). */
+static void bm_mesh_loops_calc_normals(
+ BMesh *bm, const float (*vcos)[3], const float (*fnos)[3], float (*r_lnos)[3],
+ MLoopNorSpaceArray *r_lnors_spacearr, short (*clnors_data)[2], const int cd_loop_clnors_offset)
{
BMIter fiter;
BMFace *f_curr;
+ const bool has_clnors = clnors_data || (cd_loop_clnors_offset != -1);
+
+ MLoopNorSpaceArray _lnors_spacearr = {NULL};
/* Temp normal stack. */
BLI_SMALLSTACK_DECLARE(normal, float *);
+ /* Temp clnors stack. */
+ BLI_SMALLSTACK_DECLARE(clnors, short *);
+ /* Temp edge vectors stack, only used when computing lnor spacearr. */
+ BLI_Stack *edge_vectors = NULL;
{
char htype = BM_LOOP;
@@ -525,6 +553,15 @@ static void bm_mesh_loops_calc_normals(BMesh *bm, const float (*vcos)[3], const
BM_mesh_elem_index_ensure(bm, htype);
}
+ if (!r_lnors_spacearr && has_clnors) {
+ /* We need to compute lnor spacearr if some custom lnor data are given to us! */
+ r_lnors_spacearr = &_lnors_spacearr;
+ }
+ if (r_lnors_spacearr) {
+ BKE_lnor_spacearr_init(r_lnors_spacearr, bm->totloop);
+ edge_vectors = BLI_stack_new(sizeof(float[3]), __func__);
+ }
+
/* We now know edges that can be smoothed (they are tagged), and edges that will be hard (they aren't).
* Now, time to generate the normals.
*/
@@ -533,8 +570,10 @@ static void bm_mesh_loops_calc_normals(BMesh *bm, const float (*vcos)[3], const
l_curr = l_first = BM_FACE_FIRST_LOOP(f_curr);
do {
- if (BM_elem_flag_test_bool(l_curr->e, BM_ELEM_TAG)) {
- /* A smooth edge.
+ if (BM_elem_flag_test(l_curr->e, BM_ELEM_TAG) &&
+ (!r_lnors_spacearr || BM_elem_flag_test(l_curr->v, BM_ELEM_TAG)))
+ {
+ /* A smooth edge, and we are not generating lnors_spacearr, or the related vertex is sharp.
* We skip it because it is either:
* - in the middle of a 'smooth fan' already computed (or that will be as soon as we hit
* one of its ends, i.e. one of its two sharp edges), or...
@@ -542,12 +581,45 @@ static void bm_mesh_loops_calc_normals(BMesh *bm, const float (*vcos)[3], const
* are just fine!
*/
}
- else if (!BM_elem_flag_test_bool(l_curr->prev->e, BM_ELEM_TAG)) {
+ else if (!BM_elem_flag_test(l_curr->e, BM_ELEM_TAG) &&
+ !BM_elem_flag_test(l_curr->prev->e, BM_ELEM_TAG))
+ {
/* Simple case (both edges around that vertex are sharp in related polygon),
* this vertex just takes its poly normal.
*/
+ const int l_curr_index = BM_elem_index_get(l_curr);
const float *no = fnos ? fnos[BM_elem_index_get(f_curr)] : f_curr->no;
- copy_v3_v3(r_lnos[BM_elem_index_get(l_curr)], no);
+ copy_v3_v3(r_lnos[l_curr_index], no);
+
+ /* If needed, generate this (simple!) lnor space. */
+ if (r_lnors_spacearr) {
+ float vec_curr[3], vec_prev[3];
+ MLoopNorSpace *lnor_space = BKE_lnor_space_create(r_lnors_spacearr);
+
+ {
+ const BMVert *v_pivot = l_curr->v;
+ const float *co_pivot = vcos ? vcos[BM_elem_index_get(v_pivot)] : v_pivot->co;
+ const BMVert *v_1 = BM_edge_other_vert(l_curr->e, v_pivot);
+ const float *co_1 = vcos ? vcos[BM_elem_index_get(v_1)] : v_1->co;
+ const BMVert *v_2 = BM_edge_other_vert(l_curr->prev->e, v_pivot);
+ const float *co_2 = vcos ? vcos[BM_elem_index_get(v_2)] : v_2->co;
+
+ sub_v3_v3v3(vec_curr, co_1, co_pivot);
+ normalize_v3(vec_curr);
+ sub_v3_v3v3(vec_prev, co_2, co_pivot);
+ normalize_v3(vec_prev);
+ }
+
+ BKE_lnor_space_define(lnor_space, r_lnos[l_curr_index], vec_curr, vec_prev, NULL);
+ /* We know there is only one loop in this space, no need to create a linklist in this case... */
+ BKE_lnor_space_add_loop(r_lnors_spacearr, lnor_space, l_curr_index, false);
+
+ if (has_clnors) {
+ short (*clnor)[2] = clnors_data ? &clnors_data[l_curr_index] :
+ BM_ELEM_CD_GET_VOID_P(l_curr, cd_loop_clnors_offset);
+ BKE_lnor_space_custom_data_to_normal(lnor_space, *clnor, r_lnos[l_curr_index]);
+ }
+ }
}
/* We *do not need* to check/tag loops as already computed!
* Due to the fact a loop only links to one of its two edges, a same fan *will never be walked more than
@@ -567,13 +639,26 @@ static void bm_mesh_loops_calc_normals(BMesh *bm, const float (*vcos)[3], const
*/
BMVert *v_pivot = l_curr->v;
BMEdge *e_next;
+ const BMEdge *e_org = l_curr->e;
BMLoop *lfan_pivot, *lfan_pivot_next;
+ int lfan_pivot_index;
float lnor[3] = {0.0f, 0.0f, 0.0f};
- float vec_curr[3], vec_next[3];
+ float vec_curr[3], vec_next[3], vec_org[3];
+
+ /* We validate clnors data on the fly - cheapest way to do! */
+ int clnors_avg[2] = {0, 0};
+ short (*clnor_ref)[2] = NULL;
+ int clnors_nbr = 0;
+ bool clnors_invalid = false;
const float *co_pivot = vcos ? vcos[BM_elem_index_get(v_pivot)] : v_pivot->co;
+ MLoopNorSpace *lnor_space = r_lnors_spacearr ? BKE_lnor_space_create(r_lnors_spacearr) : NULL;
+
+ BLI_assert((edge_vectors == NULL) || BLI_stack_is_empty(edge_vectors));
+
lfan_pivot = l_curr;
+ lfan_pivot_index = BM_elem_index_get(lfan_pivot);
e_next = lfan_pivot->e; /* Current edge here, actually! */
/* Only need to compute previous edge's vector once, then we can just reuse old current one! */
@@ -581,8 +666,13 @@ static void bm_mesh_loops_calc_normals(BMesh *bm, const float (*vcos)[3], const
const BMVert *v_2 = BM_edge_other_vert(e_next, v_pivot);
const float *co_2 = vcos ? vcos[BM_elem_index_get(v_2)] : v_2->co;
- sub_v3_v3v3(vec_curr, co_2, co_pivot);
- normalize_v3(vec_curr);
+ sub_v3_v3v3(vec_org, co_2, co_pivot);
+ normalize_v3(vec_org);
+ copy_v3_v3(vec_curr, vec_org);
+
+ if (r_lnors_spacearr) {
+ BLI_stack_push(edge_vectors, vec_org);
+ }
}
while (true) {
@@ -617,12 +707,38 @@ static void bm_mesh_loops_calc_normals(BMesh *bm, const float (*vcos)[3], const
const float *no = fnos ? fnos[BM_elem_index_get(f)] : f->no;
/* Accumulate */
madd_v3_v3fl(lnor, no, fac);
+
+ if (has_clnors) {
+ /* Accumulate all clnors, if they are not all equal we have to fix that! */
+ short (*clnor)[2] = clnors_data ? &clnors_data[lfan_pivot_index] :
+ BM_ELEM_CD_GET_VOID_P(lfan_pivot, cd_loop_clnors_offset);
+ if (clnors_nbr) {
+ clnors_invalid |= ((*clnor_ref)[0] != (*clnor)[0] || (*clnor_ref)[1] != (*clnor)[1]);
+ }
+ else {
+ clnor_ref = clnor;
+ }
+ clnors_avg[0] += (*clnor)[0];
+ clnors_avg[1] += (*clnor)[1];
+ clnors_nbr++;
+ /* We store here a pointer to all custom lnors processed. */
+ BLI_SMALLSTACK_PUSH(clnors, (short *)*clnor);
+ }
}
/* We store here a pointer to all loop-normals processed. */
- BLI_SMALLSTACK_PUSH(normal, (float *)r_lnos[BM_elem_index_get(lfan_pivot)]);
+ BLI_SMALLSTACK_PUSH(normal, (float *)r_lnos[lfan_pivot_index]);
+
+ if (r_lnors_spacearr) {
+ /* Assign current lnor space to current 'vertex' loop. */
+ BKE_lnor_space_add_loop(r_lnors_spacearr, lnor_space, lfan_pivot_index, true);
+ if (e_next != e_org) {
+ /* We store here all edges-normalized vectors processed. */
+ BLI_stack_push(edge_vectors, vec_next);
+ }
+ }
- if (!BM_elem_flag_test_bool(e_next, BM_ELEM_TAG)) {
+ if (!BM_elem_flag_test(e_next, BM_ELEM_TAG) || (e_next == e_org)) {
/* Next edge is sharp, we have finished with this fan of faces around this vert! */
break;
}
@@ -631,23 +747,105 @@ static void bm_mesh_loops_calc_normals(BMesh *bm, const float (*vcos)[3], const
copy_v3_v3(vec_curr, vec_next);
/* Next pivot loop to current one. */
lfan_pivot = lfan_pivot_next;
+ lfan_pivot_index = BM_elem_index_get(lfan_pivot);
}
- /* In case we get a zero normal here, just use vertex normal already set! */
- if (LIKELY(normalize_v3(lnor) != 0.0f)) {
- /* Copy back the final computed normal into all related loop-normals. */
- float *nor;
- while ((nor = BLI_SMALLSTACK_POP(normal))) {
- copy_v3_v3(nor, lnor);
+ {
+ float lnor_len = normalize_v3(lnor);
+
+ /* If we are generating lnor spacearr, we can now define the one for this fan. */
+ if (r_lnors_spacearr) {
+ if (UNLIKELY(lnor_len == 0.0f)) {
+ /* Use vertex normal as fallback! */
+ copy_v3_v3(lnor, r_lnos[lfan_pivot_index]);
+ lnor_len = 1.0f;
+ }
+
+ BKE_lnor_space_define(lnor_space, lnor, vec_org, vec_next, edge_vectors);
+
+ if (has_clnors) {
+ if (clnors_invalid) {
+ short *clnor;
+
+ clnors_avg[0] /= clnors_nbr;
+ clnors_avg[1] /= clnors_nbr;
+ /* Fix/update all clnors of this fan with computed average value. */
+ printf("Invalid clnors in this fan!\n");
+ while ((clnor = BLI_SMALLSTACK_POP(clnors))) {
+ //print_v2("org clnor", clnor);
+ clnor[0] = (short)clnors_avg[0];
+ clnor[1] = (short)clnors_avg[1];
+ }
+ //print_v2("new clnors", clnors_avg);
+ }
+ else {
+ /* We still have to consume the stack! */
+ while (BLI_SMALLSTACK_POP(clnors));
+ }
+ BKE_lnor_space_custom_data_to_normal(lnor_space, *clnor_ref, lnor);
+ }
+ }
+
+ /* In case we get a zero normal here, just use vertex normal already set! */
+ if (LIKELY(lnor_len != 0.0f)) {
+ /* Copy back the final computed normal into all related loop-normals. */
+ float *nor;
+
+ while ((nor = BLI_SMALLSTACK_POP(normal))) {
+ copy_v3_v3(nor, lnor);
+ }
+ }
+ else {
+ /* We still have to consume the stack! */
+ while (BLI_SMALLSTACK_POP(normal));
}
}
- else {
- /* We still have to clear the stack! */
- while (BLI_SMALLSTACK_POP(normal));
+
+ /* Tag related vertex as sharp, to avoid fanning around it again (in case it was a smooth one). */
+ if (r_lnors_spacearr) {
+ BM_elem_flag_enable(l_curr->v, BM_ELEM_TAG);
}
}
} while ((l_curr = l_curr->next) != l_first);
}
+
+ if (r_lnors_spacearr) {
+ BLI_stack_free(edge_vectors);
+ if (r_lnors_spacearr == &_lnors_spacearr) {
+ BKE_lnor_spacearr_free(r_lnors_spacearr);
+ }
+ }
+}
+
+static void bm_mesh_loops_calc_normals_no_autosmooth(
+ BMesh *bm, const float (*vnos)[3], const float (*fnos)[3], float (*r_lnos)[3])
+{
+ BMIter fiter;
+ BMFace *f_curr;
+
+ {
+ char htype = BM_LOOP;
+ if (vnos) {
+ htype |= BM_VERT;
+ }
+ if (fnos) {
+ htype |= BM_FACE;
+ }
+ BM_mesh_elem_index_ensure(bm, htype);
+ }
+
+ BM_ITER_MESH (f_curr, &fiter, bm, BM_FACES_OF_MESH) {
+ BMLoop *l_curr, *l_first;
+ const bool is_face_flat = !BM_elem_flag_test(f_curr, BM_ELEM_SMOOTH);
+
+ l_curr = l_first = BM_FACE_FIRST_LOOP(f_curr);
+ do {
+ const float *no = is_face_flat ? (fnos ? fnos[BM_elem_index_get(f_curr)] : f_curr->no) :
+ (vnos ? vnos[BM_elem_index_get(l_curr->v)] : l_curr->v->no);
+ copy_v3_v3(r_lnos[BM_elem_index_get(l_curr)], no);
+
+ } while ((l_curr = l_curr->next) != l_first);
+ }
}
#if 0 /* Unused currently */
@@ -657,13 +855,24 @@ static void bm_mesh_loops_calc_normals(BMesh *bm, const float (*vcos)[3], const
* Updates the loop normals of a mesh. Assumes vertex and face normals are valid (else call BM_mesh_normals_update()
* first)!
*/
-void BM_mesh_loop_normals_update(BMesh *bm, const float split_angle, float (*r_lnos)[3])
+void BM_mesh_loop_normals_update(
+ BMesh *bm, const bool use_split_normals, const float split_angle, float (*r_lnos)[3],
+ MLoopNorSpaceArray *r_lnors_spacearr, short (*clnors_data)[2], const int cd_loop_clnors_offset)
{
- /* Tag smooth edges and set lnos from vnos when they might be completely smooth... */
- bm_mesh_edges_sharp_tag(bm, NULL, NULL, split_angle, r_lnos);
+ const bool has_clnors = clnors_data || (cd_loop_clnors_offset != -1);
- /* Finish computing lnos by accumulating face normals in each fan of faces defined by sharp edges. */
- bm_mesh_loops_calc_normals(bm, NULL, NULL, r_lnos);
+ if (use_split_normals) {
+ /* Tag smooth edges and set lnos from vnos when they might be completely smooth...
+ * When using custom loop normals, disable the angle feature! */
+ bm_mesh_edges_sharp_tag(bm, NULL, NULL, has_clnors ? (float)M_PI : split_angle, r_lnos);
+
+ /* Finish computing lnos by accumulating face normals in each fan of faces defined by sharp edges. */
+ bm_mesh_loops_calc_normals(bm, NULL, NULL, r_lnos, r_lnors_spacearr, clnors_data, cd_loop_clnors_offset);
+ }
+ else {
+ BLI_assert(!r_lnors_spacearr);
+ bm_mesh_loops_calc_normals_no_autosmooth(bm, NULL, NULL, r_lnos);
+ }
}
#endif
@@ -673,14 +882,25 @@ void BM_mesh_loop_normals_update(BMesh *bm, const float split_angle, float (*r_l
* Compute split normals, i.e. vertex normals associated with each poly (hence 'loop normals').
* Useful to materialize sharp edges (or non-smooth faces) without actually modifying the geometry (splitting edges).
*/
-void BM_loops_calc_normal_vcos(BMesh *bm, const float (*vcos)[3], const float (*vnos)[3], const float (*fnos)[3],
- const float split_angle, float (*r_lnos)[3])
+void BM_loops_calc_normal_vcos(
+ BMesh *bm, const float (*vcos)[3], const float (*vnos)[3], const float (*fnos)[3],
+ const bool use_split_normals, const float split_angle, float (*r_lnos)[3],
+ MLoopNorSpaceArray *r_lnors_spacearr, short (*clnors_data)[2], const int cd_loop_clnors_offset)
{
- /* Tag smooth edges and set lnos from vnos when they might be completely smooth... */
- bm_mesh_edges_sharp_tag(bm, vnos, fnos, split_angle, r_lnos);
+ const bool has_clnors = clnors_data || (cd_loop_clnors_offset != -1);
+
+ if (use_split_normals) {
+ /* Tag smooth edges and set lnos from vnos when they might be completely smooth...
+ * When using custom loop normals, disable the angle feature! */
+ bm_mesh_edges_sharp_tag(bm, vnos, fnos, has_clnors ? (float)M_PI : split_angle, r_lnos);
- /* Finish computing lnos by accumulating face normals in each fan of faces defined by sharp edges. */
- bm_mesh_loops_calc_normals(bm, vcos, fnos, r_lnos);
+ /* Finish computing lnos by accumulating face normals in each fan of faces defined by sharp edges. */
+ bm_mesh_loops_calc_normals(bm, vcos, fnos, r_lnos, r_lnors_spacearr, clnors_data, cd_loop_clnors_offset);
+ }
+ else {
+ BLI_assert(!r_lnors_spacearr);
+ bm_mesh_loops_calc_normals_no_autosmooth(bm, vnos, fnos, r_lnos);
+ }
}
static void UNUSED_FUNCTION(bm_mdisps_space_set)(Object *ob, BMesh *bm, int from, int to)
@@ -913,8 +1133,9 @@ finally:
* These functions ensure its correct and are called more often in debug mode.
*/
-void BM_mesh_elem_index_validate(BMesh *bm, const char *location, const char *func,
- const char *msg_a, const char *msg_b)
+void BM_mesh_elem_index_validate(
+ BMesh *bm, const char *location, const char *func,
+ const char *msg_a, const char *msg_b)
{
const char iter_types[3] = {BM_VERTS_OF_MESH,
BM_EDGES_OF_MESH,
@@ -1161,6 +1382,41 @@ BMFace *BM_face_at_index_find(BMesh *bm, const int index)
return BLI_mempool_findelem(bm->fpool, index);
}
+/**
+ * Use lookup table when available, else use slower find functions.
+ *
+ * \note Try to use #BM_mesh_elem_table_ensure instead.
+ */
+BMVert *BM_vert_at_index_find_or_table(BMesh *bm, const int index)
+{
+ if ((bm->elem_table_dirty & BM_VERT) == 0) {
+ return (index < bm->totvert) ? bm->vtable[index] : NULL;
+ }
+ else {
+ return BM_vert_at_index_find(bm, index);
+ }
+}
+
+BMEdge *BM_edge_at_index_find_or_table(BMesh *bm, const int index)
+{
+ if ((bm->elem_table_dirty & BM_EDGE) == 0) {
+ return (index < bm->totedge) ? bm->etable[index] : NULL;
+ }
+ else {
+ return BM_edge_at_index_find(bm, index);
+ }
+}
+
+BMFace *BM_face_at_index_find_or_table(BMesh *bm, const int index)
+{
+ if ((bm->elem_table_dirty & BM_FACE) == 0) {
+ return (index < bm->totface) ? bm->ftable[index] : NULL;
+ }
+ else {
+ return BM_face_at_index_find(bm, index);
+ }
+}
+
/**
* Return the amount of element of type 'type' in a given bmesh.
@@ -1182,6 +1438,24 @@ int BM_mesh_elem_count(BMesh *bm, const char htype)
}
/**
+ * Special case: Python uses custom-data layers to hold PyObject references.
+ * These have to be kept in-place, else the PyObject's we point to, wont point back to us.
+ *
+ * \note ``ele_src`` Is a duplicate, so we don't need to worry about getting in a feedback loop.
+ *
+ * \note If there are other customdata layers which need this functionality, it should be generalized.
+ * However #BM_mesh_remap is currently the only place where this is done.
+ */
+static void bm_mesh_remap_cd_update(
+ BMHeader *ele_dst, BMHeader *ele_src,
+ const int cd_elem_pyptr)
+{
+ void **pyptr_dst_p = BM_ELEM_CD_GET_VOID_P(((BMElem *)ele_dst), cd_elem_pyptr);
+ void **pyptr_src_p = BM_ELEM_CD_GET_VOID_P(((BMElem *)ele_src), cd_elem_pyptr);
+ *pyptr_dst_p = *pyptr_src_p;
+}
+
+/**
* Remaps the vertices, edges and/or faces of the bmesh as indicated by vert/edge/face_idx arrays
* (xxx_idx[org_index] = new_index).
*
@@ -1221,6 +1495,7 @@ void BM_mesh_remap(
BMVert **verts_pool, *verts_copy, **vep;
int i, totvert = bm->totvert;
const unsigned int *new_idx;
+ const int cd_vert_pyptr = CustomData_get_offset(&bm->vdata, CD_BM_ELEM_PYPTR);
/* Init the old-to-new vert pointers mapping */
vptr_map = BLI_ghash_ptr_new_ex("BM_mesh_remap vert pointers mapping", bm->totvert);
@@ -1241,7 +1516,10 @@ void BM_mesh_remap(
BMVert *new_vep = verts_pool[*new_idx];
*new_vep = *ve;
/* printf("mapping vert from %d to %d (%p/%p to %p)\n", i, *new_idx, *vep, verts_pool[i], new_vep);*/
- BLI_ghash_insert(vptr_map, (void *)*vep, (void *)new_vep);
+ BLI_ghash_insert(vptr_map, *vep, new_vep);
+ if (cd_vert_pyptr != -1) {
+ bm_mesh_remap_cd_update(&(*vep)->head, &new_vep->head, cd_vert_pyptr);
+ }
}
bm->elem_index_dirty |= BM_VERT;
bm->elem_table_dirty |= BM_VERT;
@@ -1254,6 +1532,7 @@ void BM_mesh_remap(
BMEdge **edges_pool, *edges_copy, **edp;
int i, totedge = bm->totedge;
const unsigned int *new_idx;
+ const int cd_edge_pyptr = CustomData_get_offset(&bm->edata, CD_BM_ELEM_PYPTR);
/* Init the old-to-new vert pointers mapping */
eptr_map = BLI_ghash_ptr_new_ex("BM_mesh_remap edge pointers mapping", bm->totedge);
@@ -1272,8 +1551,11 @@ void BM_mesh_remap(
for (i = totedge; i--; new_idx--, ed--, edp--) {
BMEdge *new_edp = edges_pool[*new_idx];
*new_edp = *ed;
- BLI_ghash_insert(eptr_map, (void *)*edp, (void *)new_edp);
+ BLI_ghash_insert(eptr_map, *edp, new_edp);
/* printf("mapping edge from %d to %d (%p/%p to %p)\n", i, *new_idx, *edp, edges_pool[i], new_edp);*/
+ if (cd_edge_pyptr != -1) {
+ bm_mesh_remap_cd_update(&(*edp)->head, &new_edp->head, cd_edge_pyptr);
+ }
}
bm->elem_index_dirty |= BM_EDGE;
bm->elem_table_dirty |= BM_EDGE;
@@ -1286,6 +1568,7 @@ void BM_mesh_remap(
BMFace **faces_pool, *faces_copy, **fap;
int i, totface = bm->totface;
const unsigned int *new_idx;
+ const int cd_poly_pyptr = CustomData_get_offset(&bm->pdata, CD_BM_ELEM_PYPTR);
/* Init the old-to-new vert pointers mapping */
fptr_map = BLI_ghash_ptr_new_ex("BM_mesh_remap face pointers mapping", bm->totface);
@@ -1304,7 +1587,10 @@ void BM_mesh_remap(
for (i = totface; i--; new_idx--, fa--, fap--) {
BMFace *new_fap = faces_pool[*new_idx];
*new_fap = *fa;
- BLI_ghash_insert(fptr_map, (void *)*fap, (void *)new_fap);
+ BLI_ghash_insert(fptr_map, *fap, new_fap);
+ if (cd_poly_pyptr != -1) {
+ bm_mesh_remap_cd_update(&(*fap)->head, &new_fap->head, cd_poly_pyptr);
+ }
}
bm->elem_index_dirty |= BM_FACE | BM_LOOP;
@@ -1317,8 +1603,11 @@ void BM_mesh_remap(
/* Verts' pointers, only edge pointers... */
if (eptr_map) {
BM_ITER_MESH (ve, &iter, bm, BM_VERTS_OF_MESH) {
-/* printf("Vert e: %p -> %p\n", ve->e, BLI_ghash_lookup(eptr_map, (const void *)ve->e));*/
- ve->e = BLI_ghash_lookup(eptr_map, (const void *)ve->e);
+/* printf("Vert e: %p -> %p\n", ve->e, BLI_ghash_lookup(eptr_map, ve->e));*/
+ if (ve->e) {
+ ve->e = BLI_ghash_lookup(eptr_map, ve->e);
+ BLI_assert(ve->e);
+ }
}
}
@@ -1327,24 +1616,30 @@ void BM_mesh_remap(
if (vptr_map || eptr_map) {
BM_ITER_MESH (ed, &iter, bm, BM_EDGES_OF_MESH) {
if (vptr_map) {
-/* printf("Edge v1: %p -> %p\n", ed->v1, BLI_ghash_lookup(vptr_map, (const void *)ed->v1));*/
-/* printf("Edge v2: %p -> %p\n", ed->v2, BLI_ghash_lookup(vptr_map, (const void *)ed->v2));*/
- ed->v1 = BLI_ghash_lookup(vptr_map, (const void *)ed->v1);
- ed->v2 = BLI_ghash_lookup(vptr_map, (const void *)ed->v2);
+/* printf("Edge v1: %p -> %p\n", ed->v1, BLI_ghash_lookup(vptr_map, ed->v1));*/
+/* printf("Edge v2: %p -> %p\n", ed->v2, BLI_ghash_lookup(vptr_map, ed->v2));*/
+ ed->v1 = BLI_ghash_lookup(vptr_map, ed->v1);
+ ed->v2 = BLI_ghash_lookup(vptr_map, ed->v2);
+ BLI_assert(ed->v1);
+ BLI_assert(ed->v2);
}
if (eptr_map) {
/* printf("Edge v1_disk_link prev: %p -> %p\n", ed->v1_disk_link.prev,*/
-/* BLI_ghash_lookup(eptr_map, (const void *)ed->v1_disk_link.prev));*/
+/* BLI_ghash_lookup(eptr_map, ed->v1_disk_link.prev));*/
/* printf("Edge v1_disk_link next: %p -> %p\n", ed->v1_disk_link.next,*/
-/* BLI_ghash_lookup(eptr_map, (const void *)ed->v1_disk_link.next));*/
+/* BLI_ghash_lookup(eptr_map, ed->v1_disk_link.next));*/
/* printf("Edge v2_disk_link prev: %p -> %p\n", ed->v2_disk_link.prev,*/
-/* BLI_ghash_lookup(eptr_map, (const void *)ed->v2_disk_link.prev));*/
+/* BLI_ghash_lookup(eptr_map, ed->v2_disk_link.prev));*/
/* printf("Edge v2_disk_link next: %p -> %p\n", ed->v2_disk_link.next,*/
-/* BLI_ghash_lookup(eptr_map, (const void *)ed->v2_disk_link.next));*/
- ed->v1_disk_link.prev = BLI_ghash_lookup(eptr_map, (const void *)ed->v1_disk_link.prev);
- ed->v1_disk_link.next = BLI_ghash_lookup(eptr_map, (const void *)ed->v1_disk_link.next);
- ed->v2_disk_link.prev = BLI_ghash_lookup(eptr_map, (const void *)ed->v2_disk_link.prev);
- ed->v2_disk_link.next = BLI_ghash_lookup(eptr_map, (const void *)ed->v2_disk_link.next);
+/* BLI_ghash_lookup(eptr_map, ed->v2_disk_link.next));*/
+ ed->v1_disk_link.prev = BLI_ghash_lookup(eptr_map, ed->v1_disk_link.prev);
+ ed->v1_disk_link.next = BLI_ghash_lookup(eptr_map, ed->v1_disk_link.next);
+ ed->v2_disk_link.prev = BLI_ghash_lookup(eptr_map, ed->v2_disk_link.prev);
+ ed->v2_disk_link.next = BLI_ghash_lookup(eptr_map, ed->v2_disk_link.next);
+ BLI_assert(ed->v1_disk_link.prev);
+ BLI_assert(ed->v1_disk_link.next);
+ BLI_assert(ed->v2_disk_link.prev);
+ BLI_assert(ed->v2_disk_link.next);
}
}
}
@@ -1353,16 +1648,19 @@ void BM_mesh_remap(
BM_ITER_MESH (fa, &iter, bm, BM_FACES_OF_MESH) {
BM_ITER_ELEM (lo, &iterl, fa, BM_LOOPS_OF_FACE) {
if (vptr_map) {
-/* printf("Loop v: %p -> %p\n", lo->v, BLI_ghash_lookup(vptr_map, (const void *)lo->v));*/
- lo->v = BLI_ghash_lookup(vptr_map, (const void *)lo->v);
+/* printf("Loop v: %p -> %p\n", lo->v, BLI_ghash_lookup(vptr_map, lo->v));*/
+ lo->v = BLI_ghash_lookup(vptr_map, lo->v);
+ BLI_assert(lo->v);
}
if (eptr_map) {
-/* printf("Loop e: %p -> %p\n", lo->e, BLI_ghash_lookup(eptr_map, (const void *)lo->e));*/
- lo->e = BLI_ghash_lookup(eptr_map, (const void *)lo->e);
+/* printf("Loop e: %p -> %p\n", lo->e, BLI_ghash_lookup(eptr_map, lo->e));*/
+ lo->e = BLI_ghash_lookup(eptr_map, lo->e);
+ BLI_assert(lo->e);
}
if (fptr_map) {
-/* printf("Loop f: %p -> %p\n", lo->f, BLI_ghash_lookup(fptr_map, (const void *)lo->f));*/
- lo->f = BLI_ghash_lookup(fptr_map, (const void *)lo->f);
+/* printf("Loop f: %p -> %p\n", lo->f, BLI_ghash_lookup(fptr_map, lo->f));*/
+ lo->f = BLI_ghash_lookup(fptr_map, lo->f);
+ BLI_assert(lo->f);
}
}
}
diff --git a/source/blender/bmesh/intern/bmesh_mesh.h b/source/blender/bmesh/intern/bmesh_mesh.h
index 22e50502aee..b157237c7d0 100644
--- a/source/blender/bmesh/intern/bmesh_mesh.h
+++ b/source/blender/bmesh/intern/bmesh_mesh.h
@@ -28,6 +28,7 @@
*/
struct BMAllocTemplate;
+struct MLoopNorSpaceArray;
void BM_mesh_elem_toolflags_ensure(BMesh *bm);
void BM_mesh_elem_toolflags_clear(BMesh *bm);
@@ -39,15 +40,18 @@ void BM_mesh_clear(BMesh *bm);
void BM_mesh_normals_update(BMesh *bm);
void BM_verts_calc_normal_vcos(BMesh *bm, const float (*fnos)[3], const float (*vcos)[3], float (*vnos)[3]);
-void BM_loops_calc_normal_vcos(BMesh *bm, const float (*vcos)[3], const float (*vnos)[3], const float (*pnos)[3],
- const float split_angle, float (*r_lnos)[3]);
+void BM_loops_calc_normal_vcos(
+ BMesh *bm, const float (*vcos)[3], const float (*vnos)[3], const float (*pnos)[3],
+ const bool use_split_normals, const float split_angle, float (*r_lnos)[3],
+ struct MLoopNorSpaceArray *r_lnors_spacearr, short (*clnors_data)[2], const int cd_loop_clnors_offset);
void bmesh_edit_begin(BMesh *bm, const BMOpTypeFlag type_flag);
void bmesh_edit_end(BMesh *bm, const BMOpTypeFlag type_flag);
void BM_mesh_elem_index_ensure(BMesh *bm, const char hflag);
-void BM_mesh_elem_index_validate(BMesh *bm, const char *location, const char *func,
- const char *msg_a, const char *msg_b);
+void BM_mesh_elem_index_validate(
+ BMesh *bm, const char *location, const char *func,
+ const char *msg_a, const char *msg_b);
#ifndef NDEBUG
bool BM_mesh_elem_table_check(BMesh *bm);
@@ -65,6 +69,10 @@ BMVert *BM_vert_at_index_find(BMesh *bm, const int index);
BMEdge *BM_edge_at_index_find(BMesh *bm, const int index);
BMFace *BM_face_at_index_find(BMesh *bm, const int index);
+BMVert *BM_vert_at_index_find_or_table(BMesh *bm, const int index);
+BMEdge *BM_edge_at_index_find_or_table(BMesh *bm, const int index);
+BMFace *BM_face_at_index_find_or_table(BMesh *bm, const int index);
+
// XXX
int BM_mesh_elem_count(BMesh *bm, const char htype);
diff --git a/source/blender/bmesh/intern/bmesh_mesh_conv.c b/source/blender/bmesh/intern/bmesh_mesh_conv.c
index 05f3ff5b60b..24d70cefb2e 100644
--- a/source/blender/bmesh/intern/bmesh_mesh_conv.c
+++ b/source/blender/bmesh/intern/bmesh_mesh_conv.c
@@ -200,8 +200,9 @@ char BM_mesh_cd_flag_from_bmesh(BMesh *bm)
}
/* Static function for alloc (duplicate in modifiers_bmesh.c) */
-static BMFace *bm_face_create_from_mpoly(MPoly *mp, MLoop *ml,
- BMesh *bm, BMVert **vtable, BMEdge **etable)
+static BMFace *bm_face_create_from_mpoly(
+ MPoly *mp, MLoop *ml,
+ BMesh *bm, BMVert **vtable, BMEdge **etable)
{
BMVert **verts = BLI_array_alloca(verts, mp->totloop);
BMEdge **edges = BLI_array_alloca(edges, mp->totloop);
@@ -221,8 +222,9 @@ static BMFace *bm_face_create_from_mpoly(MPoly *mp, MLoop *ml,
*
* \warning This function doesn't calculate face normals.
*/
-void BM_mesh_bm_from_me(BMesh *bm, Mesh *me,
- const bool calc_face_normal, const bool set_key, int act_key_nr)
+void BM_mesh_bm_from_me(
+ BMesh *bm, Mesh *me,
+ const bool calc_face_normal, const bool set_key, int act_key_nr)
{
MVert *mvert;
MEdge *medge;
@@ -788,7 +790,7 @@ void BM_mesh_bm_to_me(BMesh *bm, Mesh *me, bool do_tessface)
{
BMEditSelection *selected;
- me->totselect = BLI_countlist(&(bm->selected));
+ me->totselect = BLI_listbase_count(&(bm->selected));
if (me->mselect) MEM_freeN(me->mselect);
@@ -850,15 +852,7 @@ void BM_mesh_bm_to_me(BMesh *bm, Mesh *me, bool do_tessface)
* bmesh and the mesh are out of sync */
(oldverts != NULL)) /* not used here, but 'oldverts' is used later for applying 'ofs' */
{
- bool act_is_basis = false;
-
- /* find if this key is a basis for any others */
- for (currkey = me->key->block.first; currkey; currkey = currkey->next) {
- if (bm->shapenr - 1 == currkey->relative) {
- act_is_basis = true;
- break;
- }
- }
+ const bool act_is_basis = BKE_keyblock_is_basis(me->key, bm->shapenr - 1);
/* active key is a base */
if (act_is_basis && (cd_shape_keyindex_offset != -1)) {
diff --git a/source/blender/bmesh/intern/bmesh_mesh_conv.h b/source/blender/bmesh/intern/bmesh_mesh_conv.h
index ab9d7a0ccf3..ce286f6c662 100644
--- a/source/blender/bmesh/intern/bmesh_mesh_conv.h
+++ b/source/blender/bmesh/intern/bmesh_mesh_conv.h
@@ -39,8 +39,9 @@ void BM_mesh_cd_flag_ensure(BMesh *bm, struct Mesh *mesh, const char cd_flag);
void BM_mesh_cd_flag_apply(BMesh *bm, const char cd_flag);
char BM_mesh_cd_flag_from_bmesh(BMesh *bm);
-void BM_mesh_bm_from_me(BMesh *bm, struct Mesh *me,
- const bool calc_face_normal, const bool set_key, int act_key_nr);
+void BM_mesh_bm_from_me(
+ BMesh *bm, struct Mesh *me,
+ const bool calc_face_normal, const bool set_key, int act_key_nr);
void BM_mesh_bm_to_me(BMesh *bm, struct Mesh *me, bool do_tessface);
#endif /* __BMESH_MESH_CONV_H__ */
diff --git a/source/blender/bmesh/intern/bmesh_mesh_validate.c b/source/blender/bmesh/intern/bmesh_mesh_validate.c
index 3a7a4f85e99..478194735f3 100644
--- a/source/blender/bmesh/intern/bmesh_mesh_validate.c
+++ b/source/blender/bmesh/intern/bmesh_mesh_validate.c
@@ -86,20 +86,19 @@ bool BM_mesh_validate(BMesh *bm)
/* check edges */
BM_ITER_MESH_INDEX (e, &iter, bm, BM_EDGES_OF_MESH, i) {
- BMEdge *e_other;
+ void **val_p;
if (e->v1 == e->v2) {
ERRMSG("edge %d: duplicate index: %d", i, BM_elem_index_get(e->v1));
}
-
/* build edgehash at the same time */
- e_other = BLI_edgehash_lookup(edge_hash, BM_elem_index_get(e->v1), BM_elem_index_get(e->v2));
- if (e_other) {
+ if (BLI_edgehash_ensure_p(edge_hash, BM_elem_index_get(e->v1), BM_elem_index_get(e->v2), &val_p)) {
+ BMEdge *e_other = *val_p;
ERRMSG("edge %d, %d: are duplicates", i, BM_elem_index_get(e_other));
}
else {
- BLI_edgehash_insert(edge_hash, BM_elem_index_get(e->v1), BM_elem_index_get(e->v2), e);
+ *val_p = e;
}
}
@@ -196,7 +195,7 @@ bool BM_mesh_validate(BMesh *bm)
ERRMSG("Finished - errors %d", errtot);
- return true;
+ return (errtot == 0);
}
diff --git a/source/blender/bmesh/intern/bmesh_mods.c b/source/blender/bmesh/intern/bmesh_mods.c
index 6e8591da0f3..13c43fabdb0 100644
--- a/source/blender/bmesh/intern/bmesh_mods.c
+++ b/source/blender/bmesh/intern/bmesh_mods.c
@@ -72,7 +72,8 @@
*/
bool BM_vert_dissolve(BMesh *bm, BMVert *v)
{
- const int len = BM_vert_edge_count(v);
+ /* logic for 3 or more is identical */
+ const int len = BM_vert_edge_count_ex(v, 3);
if (len == 1) {
BM_vert_kill(bm, v); /* will kill edges too */
@@ -97,7 +98,7 @@ bool BM_vert_dissolve(BMesh *bm, BMVert *v)
return false;
}
}
- else if (len == 2 && BM_vert_face_count(v) == 1) {
+ else if (len == 2 && BM_vert_face_count_is_equal(v, 1)) {
/* boundary vertex on a face */
return (BM_vert_collapse_edge(bm, v->e, v, true, true) != NULL);
}
@@ -265,19 +266,21 @@ BMFace *BM_faces_join_pair(BMesh *bm, BMFace *f_a, BMFace *f_b, BMEdge *e, const
*
* \param bm The bmesh
* \param f the original face
- * \param v1, v2 vertices which define the split edge, must be different
+ * \param l_a, l_b Loops of this face, their vertices define
+ * the split edge to be created (must be differ and not can't be adjacent in the face).
* \param r_l pointer which will receive the BMLoop for the split edge in the new face
* \param example Edge used for attributes of splitting edge, if non-NULL
- * \param nodouble Use an existing edge if found
+ * \param no_double: Use an existing edge if found
*
* \return Pointer to the newly created face representing one side of the split
* if the split is successful (and the original original face will be the
* other side). NULL if the split fails.
*/
-BMFace *BM_face_split(BMesh *bm, BMFace *f,
- BMLoop *l_a, BMLoop *l_b,
- BMLoop **r_l, BMEdge *example,
- const bool no_double)
+BMFace *BM_face_split(
+ BMesh *bm, BMFace *f,
+ BMLoop *l_a, BMLoop *l_b,
+ BMLoop **r_l, BMEdge *example,
+ const bool no_double)
{
const bool has_mdisp = CustomData_has_layer(&bm->ldata, CD_MDISPS);
BMFace *f_new, *f_tmp;
@@ -348,17 +351,18 @@ BMFace *BM_face_split(BMesh *bm, BMFace *f,
* \param l_a, l_b vertices which define the split edge, must be different
* \param cos Array of coordinates for intermediate points
* \param n Length of \a cos (must be > 0)
- * \param r_l pointer which will receive the BMLoop for the first split edge (from \a v1) in the new face
+ * \param r_l pointer which will receive the BMLoop for the first split edge (from \a l_a) in the new face
* \param example Edge used for attributes of splitting edge, if non-NULL
*
* \return Pointer to the newly created face representing one side of the split
* if the split is successful (and the original original face will be the
* other side). NULL if the split fails.
*/
-BMFace *BM_face_split_n(BMesh *bm, BMFace *f,
- BMLoop *l_a, BMLoop *l_b,
- float cos[][3], int n,
- BMLoop **r_l, BMEdge *example)
+BMFace *BM_face_split_n(
+ BMesh *bm, BMFace *f,
+ BMLoop *l_a, BMLoop *l_b,
+ float cos[][3], int n,
+ BMLoop **r_l, BMEdge *example)
{
BMFace *f_new, *f_tmp;
BMLoop *l_dummy;
@@ -901,7 +905,9 @@ bool BM_face_split_edgenet(
if (l_first == NULL) {
mul_v2_m3v3(co, axis_mat, v->co);
interp_weights_poly_v2(w, cos_2d, f->len, co);
- CustomData_bmesh_interp(&bm->ldata, blocks, w, NULL, f->len, l_iter->head.data);
+ CustomData_bmesh_interp(
+ &bm->ldata, (const void **)blocks,
+ w, NULL, f->len, l_iter->head.data);
l_first = l_iter;
}
else {
@@ -987,8 +993,9 @@ bool BM_face_split_edgenet(
*
* \returns The New Edge
*/
-BMEdge *BM_vert_collapse_faces(BMesh *bm, BMEdge *e_kill, BMVert *v_kill, float fac,
- const bool do_del, const bool join_faces, const bool kill_degenerate_faces)
+BMEdge *BM_vert_collapse_faces(
+ BMesh *bm, BMEdge *e_kill, BMVert *v_kill, float fac,
+ const bool do_del, const bool join_faces, const bool kill_degenerate_faces)
{
BMEdge *e_new = NULL;
BMVert *tv = BM_edge_other_vert(e_kill, v_kill);
@@ -1009,7 +1016,7 @@ BMEdge *BM_vert_collapse_faces(BMesh *bm, BMEdge *e_kill, BMVert *v_kill, float
l_iter = e_kill->l;
do {
if (l_iter->v == tv && l_iter->next->v == v_kill) {
- void *src[2];
+ const void *src[2];
BMLoop *tvloop = l_iter;
BMLoop *kvloop = l_iter->next;
@@ -1100,8 +1107,9 @@ BMEdge *BM_vert_collapse_faces(BMesh *bm, BMEdge *e_kill, BMVert *v_kill, float
*
* \return The New Edge
*/
-BMEdge *BM_vert_collapse_edge(BMesh *bm, BMEdge *e_kill, BMVert *v_kill,
- const bool do_del, const bool kill_degenerate_faces)
+BMEdge *BM_vert_collapse_edge(
+ BMesh *bm, BMEdge *e_kill, BMVert *v_kill,
+ const bool do_del, const bool kill_degenerate_faces)
{
/* nice example implementation but we want loops to have their customdata
* accounted for */
@@ -1148,7 +1156,7 @@ BMEdge *BM_vert_collapse_edge(BMesh *bm, BMEdge *e_kill, BMVert *v_kill,
* </pre>
*
* \param e The edge to split.
- * \param v One of the vertices in \a e and defines the the "from" end of the splitting operation,
+ * \param v One of the vertices in \a e and defines the "from" end of the splitting operation,
* the new vertex will be \a fac of the way from \a v to the other end.
* \param r_e The newly created edge.
* \return The new vertex.
@@ -1350,8 +1358,9 @@ bool BM_face_validate(BMFace *face, FILE *err)
*
* \note #BM_edge_rotate_check must have already run.
*/
-void BM_edge_calc_rotate(BMEdge *e, const bool ccw,
- BMLoop **r_l1, BMLoop **r_l2)
+void BM_edge_calc_rotate(
+ BMEdge *e, const bool ccw,
+ BMLoop **r_l1, BMLoop **r_l2)
{
BMVert *v1, *v2;
BMFace *fa, *fb;
@@ -1513,8 +1522,9 @@ bool BM_edge_rotate_check_degenerate(BMEdge *e, BMLoop *l1, BMLoop *l2)
return true;
}
-bool BM_edge_rotate_check_beauty(BMEdge *e,
- BMLoop *l1, BMLoop *l2)
+bool BM_edge_rotate_check_beauty(
+ BMEdge *e,
+ BMLoop *l1, BMLoop *l2)
{
/* Stupid check for now:
* Could compare angles of surrounding edges
@@ -1640,3 +1650,9 @@ BMVert *BM_face_loop_separate(BMesh *bm, BMLoop *sl)
{
return bmesh_urmv_loop(bm, sl);
}
+
+BMVert *BM_face_loop_separate_multi(
+ BMesh *bm, BMLoop **larr, int larr_len)
+{
+ return bmesh_urmv_loop_multi(bm, larr, larr_len);
+}
diff --git a/source/blender/bmesh/intern/bmesh_mods.h b/source/blender/bmesh/intern/bmesh_mods.h
index 59aee323bba..1b826b1e0b2 100644
--- a/source/blender/bmesh/intern/bmesh_mods.h
+++ b/source/blender/bmesh/intern/bmesh_mods.h
@@ -35,24 +35,29 @@ bool BM_disk_dissolve(BMesh *bm, BMVert *v);
BMFace *BM_faces_join_pair(BMesh *bm, BMFace *f1, BMFace *f2, BMEdge *e, const bool do_del);
-BMFace *BM_face_split(BMesh *bm, BMFace *f,
- BMLoop *l_a, BMLoop *l_b,
- BMLoop **r_l,
- BMEdge *example, const bool no_double);
-
-BMFace *BM_face_split_n(BMesh *bm, BMFace *f,
- BMLoop *l_a, BMLoop *l_b,
- float cos[][3], int n,
- BMLoop **r_l, BMEdge *example);
-
-bool BM_face_split_edgenet(BMesh *bm, BMFace *f,
- BMEdge **edge_net, const int edge_net_len,
- BMFace ***r_face_arr, int *r_face_arr_len);
-
-BMEdge *BM_vert_collapse_faces(BMesh *bm, BMEdge *e_kill, BMVert *v_kill, float fac,
- const bool do_del, const bool join_faces, const bool kill_degenerate_faces);
-BMEdge *BM_vert_collapse_edge(BMesh *bm, BMEdge *e_kill, BMVert *v_kill,
- const bool do_del, const bool kill_degenerate_faces);
+BMFace *BM_face_split(
+ BMesh *bm, BMFace *f,
+ BMLoop *l_a, BMLoop *l_b,
+ BMLoop **r_l,
+ BMEdge *example, const bool no_double);
+
+BMFace *BM_face_split_n(
+ BMesh *bm, BMFace *f,
+ BMLoop *l_a, BMLoop *l_b,
+ float cos[][3], int n,
+BMLoop **r_l, BMEdge *example);
+
+bool BM_face_split_edgenet(
+ BMesh *bm, BMFace *f,
+ BMEdge **edge_net, const int edge_net_len,
+ BMFace ***r_face_arr, int *r_face_arr_len);
+
+BMEdge *BM_vert_collapse_faces(
+ BMesh *bm, BMEdge *e_kill, BMVert *v_kill, float fac,
+ const bool do_del, const bool join_faces, const bool kill_degenerate_faces);
+BMEdge *BM_vert_collapse_edge(
+ BMesh *bm, BMEdge *e_kill, BMVert *v_kill,
+ const bool do_del, const bool kill_degenerate_faces);
BMVert *BM_edge_split(BMesh *bm, BMEdge *e, BMVert *v, BMEdge **r_e, float percent);
@@ -61,13 +66,16 @@ BMVert *BM_edge_split_n(BMesh *bm, BMEdge *e, int numcuts, BMVert **r_varr);
bool BM_face_validate(BMFace *face, FILE *err);
-void BM_edge_calc_rotate(BMEdge *e, const bool ccw,
- BMLoop **r_l1, BMLoop **r_l2);
+void BM_edge_calc_rotate(
+ BMEdge *e, const bool ccw,
+ BMLoop **r_l1, BMLoop **r_l2);
bool BM_edge_rotate_check(BMEdge *e);
-bool BM_edge_rotate_check_degenerate(BMEdge *e,
- BMLoop *l1, BMLoop *l2);
-bool BM_edge_rotate_check_beauty(BMEdge *e,
- BMLoop *l1, BMLoop *l2);
+bool BM_edge_rotate_check_degenerate(
+ BMEdge *e,
+ BMLoop *l1, BMLoop *l2);
+bool BM_edge_rotate_check_beauty(
+ BMEdge *e,
+ BMLoop *l1, BMLoop *l2);
BMEdge *BM_edge_rotate(BMesh *bm, BMEdge *e, const bool ccw, const short check_flag);
/* flags for BM_edge_rotate */
@@ -81,5 +89,7 @@ enum {
BMVert *BM_face_vert_separate(BMesh *bm, BMFace *sf, BMVert *sv);
BMVert *BM_face_loop_separate(BMesh *bm, BMLoop *sl);
+BMVert *BM_face_loop_separate_multi(
+ BMesh *bm, BMLoop **larr, int larr_len);
#endif /* __BMESH_MODS_H__ */
diff --git a/source/blender/bmesh/intern/bmesh_opdefines.c b/source/blender/bmesh/intern/bmesh_opdefines.c
index d8be55ce7c2..3e814948ade 100644
--- a/source/blender/bmesh/intern/bmesh_opdefines.c
+++ b/source/blender/bmesh/intern/bmesh_opdefines.c
@@ -104,6 +104,7 @@ static BMOpDefine bmo_smooth_vert_def = {
"smooth_vert",
/* slots_in */
{{"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* input vertices */
+ {"factor", BMO_OP_SLOT_FLT}, /* smoothing factor */
{"mirror_clip_x", BMO_OP_SLOT_BOOL}, /* set vertices close to the x axis before the operation to 0 */
{"mirror_clip_y", BMO_OP_SLOT_BOOL}, /* set vertices close to the y axis before the operation to 0 */
{"mirror_clip_z", BMO_OP_SLOT_BOOL}, /* set vertices close to the z axis before the operation to 0 */
@@ -159,6 +160,28 @@ static BMOpDefine bmo_recalc_face_normals_def = {
};
/*
+ * Planar Faces.
+ *
+ * Iteratively flatten faces.
+ */
+static BMOpDefine bmo_planar_faces_def = {
+ "planar_faces",
+ /* slots_in */
+ {{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* input geometry. */
+ {"iterations", BMO_OP_SLOT_INT},
+ {"factor", BMO_OP_SLOT_FLT}, /* planar factor */
+ {{'\0'}},
+ },
+ /* slots_out */
+ {{"geom.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, /* output slot, computed boundary geometry. */
+ {{'\0'}},
+ },
+ bmo_planar_faces_exec,
+ (BMO_OPTYPE_FLAG_SELECT_FLUSH |
+ BMO_OPTYPE_FLAG_SELECT_VALIDATE),
+};
+
+/*
* Region Extend.
*
* used to implement the select more/less tools.
@@ -172,8 +195,9 @@ static BMOpDefine bmo_region_extend_def = {
"region_extend",
/* slots_in */
{{"geom", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, /* input geometry */
- {"use_constrict", BMO_OP_SLOT_BOOL}, /* find boundary inside the regions, not outside. */
+ {"use_contract", BMO_OP_SLOT_BOOL}, /* find boundary inside the regions, not outside. */
{"use_faces", BMO_OP_SLOT_BOOL}, /* extend from faces instead of edges */
+ {"use_face_step", BMO_OP_SLOT_BOOL}, /* step over connected faces */
{{'\0'}},
},
/* slots_out */
@@ -357,6 +381,7 @@ static BMOpDefine bmo_collapse_def = {
"collapse",
/* slots_in */
{{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* input edges */
+ {"uvs", BMO_OP_SLOT_BOOL}, /* also collapse UVs and such */
{{'\0'}},
},
{{{'\0'}}}, /* no output */
@@ -484,17 +509,19 @@ static BMOpDefine bmo_create_vert_def = {
* Join Triangles.
*
* Tries to intelligently join triangles according
- * to various settings and stuff.
+ * to angle threshold and delimiters.
*/
static BMOpDefine bmo_join_triangles_def = {
"join_triangles",
/* slots_in */
{{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* input geometry. */
+ {"cmp_seam", BMO_OP_SLOT_BOOL},
{"cmp_sharp", BMO_OP_SLOT_BOOL},
{"cmp_uvs", BMO_OP_SLOT_BOOL},
{"cmp_vcols", BMO_OP_SLOT_BOOL},
{"cmp_materials", BMO_OP_SLOT_BOOL},
- {"limit", BMO_OP_SLOT_FLT},
+ {"angle_face_threshold", BMO_OP_SLOT_FLT},
+ {"angle_shape_threshold", BMO_OP_SLOT_FLT},
{{'\0'}},
},
/* slots_out */
@@ -931,6 +958,28 @@ static BMOpDefine bmo_connect_verts_def = {
};
/*
+ * Connect Verts to form Convex Faces.
+ *
+ * Ensures all faces are convex **faces**.
+ */
+static BMOpDefine bmo_connect_verts_concave_def = {
+ "connect_verts_concave",
+ /* slots_in */
+ {{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}},
+ {{'\0'}},
+ },
+ /* slots_out */
+ {{"edges.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}},
+ {"faces.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}},
+ {{'\0'}},
+ },
+ bmo_connect_verts_concave_exec,
+ (BMO_OPTYPE_FLAG_UNTAN_MULTIRES |
+ BMO_OPTYPE_FLAG_NORMALS_CALC |
+ BMO_OPTYPE_FLAG_SELECT_FLUSH),
+};
+
+/*
* Connect Verts Across non Planer Faces.
*
* Split faces by connecting edges along non planer **faces**.
@@ -1675,8 +1724,10 @@ static BMOpDefine bmo_bevel_def = {
{"offset_type", BMO_OP_SLOT_INT}, /* how to measure offset (enum) */
{"segments", BMO_OP_SLOT_INT}, /* number of segments in bevel */
{"profile", BMO_OP_SLOT_FLT}, /* profile shape, 0->1 (.5=>round) */
- {"vertex_only", BMO_OP_SLOT_BOOL}, /* only bevel vertices, not edges */
+ {"vertex_only", BMO_OP_SLOT_BOOL}, /* only bevel vertices, not edges */
+ {"clamp_overlap", BMO_OP_SLOT_BOOL}, /* do not allow beveled edges/vertices to overlap each other */
{"material", BMO_OP_SLOT_INT}, /* material for bevel faces, -1 means get from adjacent faces */
+ {"loop_slide", BMO_OP_SLOT_BOOL}, /* prefer to slide along edges to having even widths */
{{'\0'}},
},
/* slots_out */
@@ -1816,6 +1867,27 @@ static BMOpDefine bmo_inset_region_def = {
};
/*
+ * Edgeloop Offset.
+ *
+ * Creates edge loops based on simple edge-outset method.
+ */
+static BMOpDefine bmo_offset_edgeloops_def = {
+ "offset_edgeloops",
+ /* slots_in */
+ {{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* input faces */
+ {"use_cap_endpoint", BMO_OP_SLOT_BOOL},
+ {{'\0'}},
+ },
+ /* slots_out */
+ {{"edges.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* output faces */
+ {{'\0'}},
+ },
+ bmo_offset_edgeloops_exec,
+ (BMO_OPTYPE_FLAG_NORMALS_CALC |
+ BMO_OPTYPE_FLAG_SELECT_FLUSH),
+};
+
+/*
* Wire Frame.
*
* Makes a wire-frame copy of faces.
@@ -1947,6 +2019,7 @@ const BMOpDefine *bmo_opdefines[] = {
&bmo_collapse_def,
&bmo_collapse_uvs_def,
&bmo_connect_verts_def,
+ &bmo_connect_verts_concave_def,
&bmo_connect_verts_nonplanar_def,
&bmo_connect_vert_pair_def,
&bmo_contextual_create_def,
@@ -1970,6 +2043,7 @@ const BMOpDefine *bmo_opdefines[] = {
&bmo_duplicate_def,
&bmo_holes_fill_def,
&bmo_face_attribute_fill_def,
+ &bmo_offset_edgeloops_def,
&bmo_edgeloop_fill_def,
&bmo_edgenet_fill_def,
&bmo_edgenet_prepare_def,
@@ -1989,6 +2063,7 @@ const BMOpDefine *bmo_opdefines[] = {
&bmo_pointmerge_facedata_def,
&bmo_poke_def,
&bmo_recalc_face_normals_def,
+ &bmo_planar_faces_def,
&bmo_region_extend_def,
&bmo_remove_doubles_def,
&bmo_reverse_colors_def,
diff --git a/source/blender/bmesh/intern/bmesh_operator_api.h b/source/blender/bmesh/intern/bmesh_operator_api.h
index 287aafc8f9f..14e9bf81be7 100644
--- a/source/blender/bmesh/intern/bmesh_operator_api.h
+++ b/source/blender/bmesh/intern/bmesh_operator_api.h
@@ -273,9 +273,10 @@ BMOpSlot *BMO_slot_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *identif
(op_dst)->slots_dst, slot_name_dst, \
(op_dst)->arena)
-void _bmo_slot_copy(BMOpSlot slot_args_src[BMO_OP_MAX_SLOTS], const char *slot_name_src,
- BMOpSlot slot_args_dst[BMO_OP_MAX_SLOTS], const char *slot_name_dst,
- struct MemArena *arena_dst);
+void _bmo_slot_copy(
+ BMOpSlot slot_args_src[BMO_OP_MAX_SLOTS], const char *slot_name_src,
+ BMOpSlot slot_args_dst[BMO_OP_MAX_SLOTS], const char *slot_name_dst,
+ struct MemArena *arena_dst);
/* del "context" slot values, used for operator too */
enum {
@@ -301,6 +302,8 @@ typedef enum {
BMO_DELIM_NORMAL = 1 << 0,
BMO_DELIM_MATERIAL = 1 << 1,
BMO_DELIM_SEAM = 1 << 2,
+ BMO_DELIM_SHARP = 1 << 3,
+ BMO_DELIM_UV = 1 << 4,
} BMO_Delimit;
void BMO_op_flag_enable(BMesh *bm, BMOperator *op, const int op_flag);
@@ -335,11 +338,12 @@ void BMO_slot_mat3_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_na
void BMO_mesh_flag_disable_all(BMesh *bm, BMOperator *op, const char htype, const short oflag);
-void BMO_mesh_selected_remap(BMesh *bm,
- BMOpSlot *slot_vert_map,
- BMOpSlot *slot_edge_map,
- BMOpSlot *slot_face_map,
- const bool check_select);
+void BMO_mesh_selected_remap(
+ BMesh *bm,
+ BMOpSlot *slot_vert_map,
+ BMOpSlot *slot_edge_map,
+ BMOpSlot *slot_face_map,
+ const bool check_select);
/* copies the values from another slot to the end of the output slot */
#define BMO_slot_buffer_append(op_src, slots_src, slot_name_src, \
@@ -347,53 +351,64 @@ void BMO_mesh_selected_remap(BMesh *bm,
_bmo_slot_buffer_append((op_src)->slots_src, slot_name_src, \
(op_dst)->slots_dst, slot_name_dst, \
(op_dst)->arena)
-void _bmo_slot_buffer_append(BMOpSlot slot_args_dst[BMO_OP_MAX_SLOTS], const char *slot_name_dst,
- BMOpSlot slot_args_src[BMO_OP_MAX_SLOTS], const char *slot_name_src,
- struct MemArena *arena_dst);
+void _bmo_slot_buffer_append(
+ BMOpSlot slot_args_dst[BMO_OP_MAX_SLOTS], const char *slot_name_dst,
+ BMOpSlot slot_args_src[BMO_OP_MAX_SLOTS], const char *slot_name_src,
+ struct MemArena *arena_dst);
/* puts every element of type 'type' (which is a bitmask) with tool
* flag 'flag', into a slot. */
-void BMO_slot_buffer_from_enabled_flag(BMesh *bm, BMOperator *op,
- BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name,
- const char htype, const short oflag);
+void BMO_slot_buffer_from_enabled_flag(
+ BMesh *bm, BMOperator *op,
+ BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name,
+ const char htype, const short oflag);
/* puts every element of type 'type' (which is a bitmask) without tool
* flag 'flag', into a slot. */
-void BMO_slot_buffer_from_disabled_flag(BMesh *bm, BMOperator *op,
- BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name,
- const char htype, const short oflag);
+void BMO_slot_buffer_from_disabled_flag(
+ BMesh *bm, BMOperator *op,
+ BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name,
+ const char htype, const short oflag);
/* tool-flags all elements inside an element slot array with flag flag. */
-void BMO_slot_buffer_flag_enable(BMesh *bm,
- BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name,
- const char htype, const short oflag);
+void BMO_slot_buffer_flag_enable(
+ BMesh *bm,
+ BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name,
+ const char htype, const short oflag);
/* clears tool-flag flag from all elements inside a slot array. */
-void BMO_slot_buffer_flag_disable(BMesh *bm,
- BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name,
- const char htype, const short oflag);
+void BMO_slot_buffer_flag_disable(
+ BMesh *bm,
+ BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name,
+ const char htype, const short oflag);
/* tool-flags all elements inside an element slot array with flag flag. */
-void BMO_slot_buffer_hflag_enable(BMesh *bm,
- BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name,
- const char htype, const char hflag, const bool do_flush);
+void BMO_slot_buffer_hflag_enable(
+ BMesh *bm,
+ BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name,
+ const char htype, const char hflag, const bool do_flush);
/* clears tool-flag flag from all elements inside a slot array. */
-void BMO_slot_buffer_hflag_disable(BMesh *bm,
- BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name,
- const char htype, const char hflag, const bool do_flush);
+void BMO_slot_buffer_hflag_disable(
+ BMesh *bm,
+ BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name,
+ const char htype, const char hflag, const bool do_flush);
/* puts every element of type 'type' (which is a bitmask) with header
* flag 'flag', into a slot. note: ignores hidden elements
* (e.g. elements with header flag BM_ELEM_HIDDEN set).*/
-void BMO_slot_buffer_from_enabled_hflag(BMesh *bm, BMOperator *op,
- BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name,
- const char htype, const char hflag);
+void BMO_slot_buffer_from_enabled_hflag(
+ BMesh *bm, BMOperator *op,
+ BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name,
+ const char htype, const char hflag);
/* puts every element of type 'type' (which is a bitmask) without
* header flag 'flag', into a slot. note: ignores hidden elements
* (e.g. elements with header flag BM_ELEM_HIDDEN set).*/
-void BMO_slot_buffer_from_disabled_hflag(BMesh *bm, BMOperator *op,
- BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name,
- const char htype, const char hflag);
+void BMO_slot_buffer_from_disabled_hflag(
+ BMesh *bm, BMOperator *op,
+ BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name,
+ const char htype, const char hflag);
+
+void BMO_slot_buffer_from_array(BMOperator *op, BMOpSlot *slot, BMHeader **ele_buffer, int ele_buffer_len);
void BMO_slot_buffer_from_single(BMOperator *op, BMOpSlot *slot, BMHeader *ele);
void *BMO_slot_buffer_get_single(BMOpSlot *slot);
@@ -403,19 +418,23 @@ void *BMO_slot_buffer_get_single(BMOpSlot *slot);
int BMO_slot_buffer_count(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name);
int BMO_slot_map_count(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name);
-void BMO_slot_map_insert(BMOperator *op, BMOpSlot *slot,
- const void *element, const void *data);
+void BMO_slot_map_insert(
+ BMOperator *op, BMOpSlot *slot,
+ const void *element, const void *data);
/* flags all elements in a mapping. note that the mapping must only have
* bmesh elements in it.*/
-void BMO_slot_map_to_flag(BMesh *bm, BMOpSlot slot_args[BMO_OP_MAX_SLOTS],
- const char *slot_name, const char hflag, const short oflag);
+void BMO_slot_map_to_flag(
+ BMesh *bm, BMOpSlot slot_args[BMO_OP_MAX_SLOTS],
+ const char *slot_name, const char hflag, const short oflag);
-void *BMO_slot_buffer_alloc(BMOperator *op, BMOpSlot slot_args[BMO_OP_MAX_SLOTS],
- const char *slot_name, const int len);
+void *BMO_slot_buffer_alloc(
+ BMOperator *op, BMOpSlot slot_args[BMO_OP_MAX_SLOTS],
+ const char *slot_name, const int len);
-void BMO_slot_buffer_from_all(BMesh *bm, BMOperator *op, BMOpSlot slot_args[BMO_OP_MAX_SLOTS],
- const char *slot_name, const char htype);
+void BMO_slot_buffer_from_all(
+ BMesh *bm, BMOperator *op, BMOpSlot slot_args[BMO_OP_MAX_SLOTS],
+ const char *slot_name, const char htype);
/**
* This part of the API is used to iterate over element buffer or
@@ -464,9 +483,10 @@ typedef struct BMOIter {
void *BMO_slot_buffer_get_first(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name);
-void *BMO_iter_new(BMOIter *iter,
- BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name,
- const char restrictmask);
+void *BMO_iter_new(
+ BMOIter *iter,
+ BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name,
+ const char restrictmask);
void *BMO_iter_step(BMOIter *iter);
void **BMO_iter_map_value_p(BMOIter *iter);
@@ -477,10 +497,14 @@ int BMO_iter_map_value_int(BMOIter *iter);
bool BMO_iter_map_value_bool(BMOIter *iter);
#define BMO_ITER(ele, iter, slot_args, slot_name, restrict_flag) \
- for (ele = BMO_iter_new(iter, slot_args, slot_name, restrict_flag); ele; ele = BMO_iter_step(iter))
-
-/******************* Inlined Functions********************/
-typedef void (*opexec)(BMesh *bm, BMOperator *op);
+ for (BM_CHECK_TYPE_ELEM_ASSIGN(ele) = BMO_iter_new(iter, slot_args, slot_name, restrict_flag); \
+ ele; \
+ BM_CHECK_TYPE_ELEM_ASSIGN(ele) = BMO_iter_step(iter))
+
+#define BMO_ITER_INDEX(ele, iter, slot_args, slot_name, restrict_flag, i_) \
+ for (BM_CHECK_TYPE_ELEM_ASSIGN(ele) = BMO_iter_new(iter, slot_args, slot_name, restrict_flag), i_ = 0; \
+ ele; \
+ BM_CHECK_TYPE_ELEM_ASSIGN(ele) = BMO_iter_step(iter), i_++)
extern const int BMO_OPSLOT_TYPEINFO[BMO_OP_SLOT_TOTAL_TYPES];
diff --git a/source/blender/bmesh/intern/bmesh_operator_api_inline.h b/source/blender/bmesh/intern/bmesh_operator_api_inline.h
index 2b78b775723..4f995e08b9c 100644
--- a/source/blender/bmesh/intern/bmesh_operator_api_inline.h
+++ b/source/blender/bmesh/intern/bmesh_operator_api_inline.h
@@ -38,55 +38,67 @@
* ghash or a mapping slot to do it. */
/* flags 15 and 16 (1 << 14 and 1 << 15) are reserved for bmesh api use */
+ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1, 2)
BLI_INLINE short _bmo_elem_flag_test(BMesh *bm, BMFlagLayer *oflags, const short oflag)
{
return oflags[bm->stackdepth - 1].f & oflag;
}
+ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1, 2)
BLI_INLINE bool _bmo_elem_flag_test_bool(BMesh *bm, BMFlagLayer *oflags, const short oflag)
{
return (oflags[bm->stackdepth - 1].f & oflag) != 0;
}
+ATTR_NONNULL(1, 2)
BLI_INLINE void _bmo_elem_flag_enable(BMesh *bm, BMFlagLayer *oflags, const short oflag)
{
oflags[bm->stackdepth - 1].f |= oflag;
}
+ATTR_NONNULL(1, 2)
BLI_INLINE void _bmo_elem_flag_disable(BMesh *bm, BMFlagLayer *oflags, const short oflag)
{
oflags[bm->stackdepth - 1].f &= (short)~oflag;
}
+ATTR_NONNULL(1, 2)
BLI_INLINE void _bmo_elem_flag_set(BMesh *bm, BMFlagLayer *oflags, const short oflag, int val)
{
if (val) oflags[bm->stackdepth - 1].f |= oflag;
else oflags[bm->stackdepth - 1].f &= (short)~oflag;
}
+ATTR_NONNULL(1, 2)
BLI_INLINE void _bmo_elem_flag_toggle(BMesh *bm, BMFlagLayer *oflags, const short oflag)
{
oflags[bm->stackdepth - 1].f ^= oflag;
}
-BLI_INLINE void BMO_slot_map_int_insert(BMOperator *op, BMOpSlot *slot,
- void *element, const int val)
+ATTR_NONNULL(1, 2)
+BLI_INLINE void BMO_slot_map_int_insert(
+ BMOperator *op, BMOpSlot *slot,
+ void *element, const int val)
{
union { void *ptr; int val; } t = {NULL};
BLI_assert(slot->slot_subtype.map == BMO_OP_SLOT_SUBTYPE_MAP_INT);
BMO_slot_map_insert(op, slot, element, ((t.val = val), t.ptr));
}
-BLI_INLINE void BMO_slot_map_bool_insert(BMOperator *op, BMOpSlot *slot,
- void *element, const bool val)
+ATTR_NONNULL(1, 2)
+BLI_INLINE void BMO_slot_map_bool_insert(
+ BMOperator *op, BMOpSlot *slot,
+ void *element, const bool val)
{
union { void *ptr; bool val; } t = {NULL};
BLI_assert(slot->slot_subtype.map == BMO_OP_SLOT_SUBTYPE_MAP_BOOL);
BMO_slot_map_insert(op, slot, element, ((t.val = val), t.ptr));
}
-BLI_INLINE void BMO_slot_map_float_insert(BMOperator *op, BMOpSlot *slot,
- void *element, const float val)
+ATTR_NONNULL(1, 2)
+BLI_INLINE void BMO_slot_map_float_insert(
+ BMOperator *op, BMOpSlot *slot,
+ void *element, const float val)
{
union { void *ptr; float val; } t = {NULL};
BLI_assert(slot->slot_subtype.map == BMO_OP_SLOT_SUBTYPE_MAP_FLT);
@@ -99,15 +111,19 @@ BLI_INLINE void BMO_slot_map_float_insert(BMOperator *op, BMOpSlot *slot,
* do NOT use these for non-operator-api-allocated memory! instead
* use BMO_slot_map_data_get and BMO_slot_map_insert, which copies the data. */
-BLI_INLINE void BMO_slot_map_ptr_insert(BMOperator *op, BMOpSlot *slot,
- const void *element, void *val)
+ATTR_NONNULL(1, 2)
+BLI_INLINE void BMO_slot_map_ptr_insert(
+ BMOperator *op, BMOpSlot *slot,
+ const void *element, void *val)
{
BLI_assert(slot->slot_subtype.map == BMO_OP_SLOT_SUBTYPE_MAP_INTERNAL);
BMO_slot_map_insert(op, slot, element, val);
}
-BLI_INLINE void BMO_slot_map_elem_insert(BMOperator *op, BMOpSlot *slot,
- const void *element, void *val)
+ATTR_NONNULL(1, 2)
+BLI_INLINE void BMO_slot_map_elem_insert(
+ BMOperator *op, BMOpSlot *slot,
+ const void *element, void *val)
{
BLI_assert(slot->slot_subtype.map == BMO_OP_SLOT_SUBTYPE_MAP_ELEM);
BMO_slot_map_insert(op, slot, element, val);
@@ -115,25 +131,30 @@ BLI_INLINE void BMO_slot_map_elem_insert(BMOperator *op, BMOpSlot *slot,
/* no values */
-BLI_INLINE void BMO_slot_map_empty_insert(BMOperator *op, BMOpSlot *slot,
- const void *element)
+ATTR_NONNULL(1, 2)
+BLI_INLINE void BMO_slot_map_empty_insert(
+ BMOperator *op, BMOpSlot *slot,
+ const void *element)
{
BLI_assert(slot->slot_subtype.map == BMO_OP_SLOT_SUBTYPE_MAP_EMPTY);
BMO_slot_map_insert(op, slot, element, NULL);
}
+ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
BLI_INLINE bool BMO_slot_map_contains(BMOpSlot *slot, const void *element)
{
BLI_assert(slot->slot_type == BMO_OP_SLOT_MAPPING);
return BLI_ghash_haskey(slot->data.ghash, element);
}
+ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
BLI_INLINE void **BMO_slot_map_data_get(BMOpSlot *slot, const void *element)
{
return BLI_ghash_lookup_p(slot->data.ghash, element);
}
+ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
BLI_INLINE float BMO_slot_map_float_get(BMOpSlot *slot, const void *element)
{
void **data;
@@ -148,6 +169,7 @@ BLI_INLINE float BMO_slot_map_float_get(BMOpSlot *slot, const void *element)
}
}
+ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
BLI_INLINE int BMO_slot_map_int_get(BMOpSlot *slot, const void *element)
{
void **data;
@@ -162,6 +184,7 @@ BLI_INLINE int BMO_slot_map_int_get(BMOpSlot *slot, const void *element)
}
}
+ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
BLI_INLINE bool BMO_slot_map_bool_get(BMOpSlot *slot, const void *element)
{
void **data;
@@ -176,6 +199,7 @@ BLI_INLINE bool BMO_slot_map_bool_get(BMOpSlot *slot, const void *element)
}
}
+ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
BLI_INLINE void *BMO_slot_map_ptr_get(BMOpSlot *slot, const void *element)
{
void **val = BMO_slot_map_data_get(slot, element);
@@ -185,6 +209,7 @@ BLI_INLINE void *BMO_slot_map_ptr_get(BMOpSlot *slot, const void *element)
return NULL;
}
+ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
BLI_INLINE void *BMO_slot_map_elem_get(BMOpSlot *slot, const void *element)
{
void **val = (void **) BMO_slot_map_data_get(slot, element);
diff --git a/source/blender/bmesh/intern/bmesh_operators.c b/source/blender/bmesh/intern/bmesh_operators.c
index b041c010c22..e65f3e38900 100644
--- a/source/blender/bmesh/intern/bmesh_operators.c
+++ b/source/blender/bmesh/intern/bmesh_operators.c
@@ -35,7 +35,7 @@
#include "BLI_mempool.h"
#include "BLI_listbase.h"
-#include "BLF_translation.h"
+#include "BLT_translation.h"
#include "bmesh.h"
#include "intern/bmesh_private.h"
@@ -281,9 +281,10 @@ BMOpSlot *BMO_slot_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *identif
* define used.
* Copies data from one slot to another.
*/
-void _bmo_slot_copy(BMOpSlot slot_args_src[BMO_OP_MAX_SLOTS], const char *slot_name_src,
- BMOpSlot slot_args_dst[BMO_OP_MAX_SLOTS], const char *slot_name_dst,
- struct MemArena *arena_dst)
+void _bmo_slot_copy(
+ BMOpSlot slot_args_src[BMO_OP_MAX_SLOTS], const char *slot_name_src,
+ BMOpSlot slot_args_dst[BMO_OP_MAX_SLOTS], const char *slot_name_dst,
+ struct MemArena *arena_dst)
{
BMOpSlot *slot_src = BMO_slot_get(slot_args_src, slot_name_src);
BMOpSlot *slot_dst = BMO_slot_get(slot_args_dst, slot_name_dst);
@@ -543,8 +544,9 @@ void BMO_slot_vec_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_nam
*
*/
-static int bmo_mesh_flag_count(BMesh *bm, const char htype, const short oflag,
- const bool test_for_enabled)
+static int bmo_mesh_flag_count(
+ BMesh *bm, const char htype, const short oflag,
+ const bool test_for_enabled)
{
const char iter_types[3] = {BM_VERTS_OF_MESH,
BM_EDGES_OF_MESH,
@@ -602,11 +604,12 @@ void BMO_mesh_flag_disable_all(BMesh *bm, BMOperator *UNUSED(op), const char hty
}
}
-void BMO_mesh_selected_remap(BMesh *bm,
- BMOpSlot *slot_vert_map,
- BMOpSlot *slot_edge_map,
- BMOpSlot *slot_face_map,
- const bool check_select)
+void BMO_mesh_selected_remap(
+ BMesh *bm,
+ BMOpSlot *slot_vert_map,
+ BMOpSlot *slot_edge_map,
+ BMOpSlot *slot_face_map,
+ const bool check_select)
{
if (bm->selected.first) {
BMEditSelection *ese, *ese_next;
@@ -663,8 +666,9 @@ int BMO_slot_map_count(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_na
/* inserts a key/value mapping into a mapping slot. note that it copies the
* value, it doesn't store a reference to it. */
-void BMO_slot_map_insert(BMOperator *op, BMOpSlot *slot,
- const void *element, const void *data)
+void BMO_slot_map_insert(
+ BMOperator *op, BMOpSlot *slot,
+ const void *element, const void *data)
{
(void) op; /* Ignored in release builds. */
@@ -717,8 +721,9 @@ void *bmo_slot_buffer_grow(BMesh *bm, BMOperator *op, int slot_code, int totadd)
}
#endif
-void BMO_slot_map_to_flag(BMesh *bm, BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name,
- const char htype, const short oflag)
+void BMO_slot_map_to_flag(
+ BMesh *bm, BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name,
+ const char htype, const short oflag)
{
GHashIterator gh_iter;
BMOpSlot *slot = BMO_slot_get(slot_args, slot_name);
@@ -759,8 +764,9 @@ void *BMO_slot_buffer_alloc(BMOperator *op, BMOpSlot slot_args[BMO_OP_MAX_SLOTS]
*
* Copies all elements of a certain type into an operator slot.
*/
-void BMO_slot_buffer_from_all(BMesh *bm, BMOperator *op, BMOpSlot slot_args[BMO_OP_MAX_SLOTS],
- const char *slot_name, const char htype)
+void BMO_slot_buffer_from_all(
+ BMesh *bm, BMOperator *op, BMOpSlot slot_args[BMO_OP_MAX_SLOTS],
+ const char *slot_name, const char htype)
{
BMOpSlot *output = BMO_slot_get(slot_args, slot_name);
int totelement = 0, i = 0;
@@ -809,9 +815,10 @@ void BMO_slot_buffer_from_all(BMesh *bm, BMOperator *op, BMOpSlot slot_args[BMO_
* Copies elements of a certain type, which have a certain header flag
* enabled/disabled into a slot for an operator.
*/
-static void bmo_slot_buffer_from_hflag(BMesh *bm, BMOperator *op, BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name,
- const char htype, const char hflag,
- const bool test_for_enabled)
+static void bmo_slot_buffer_from_hflag(
+ BMesh *bm, BMOperator *op, BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name,
+ const char htype, const char hflag,
+ const bool test_for_enabled)
{
BMOpSlot *output = BMO_slot_get(slot_args, slot_name);
int totelement = 0, i = 0;
@@ -872,16 +879,18 @@ static void bmo_slot_buffer_from_hflag(BMesh *bm, BMOperator *op, BMOpSlot slot_
}
}
-void BMO_slot_buffer_from_enabled_hflag(BMesh *bm, BMOperator *op,
- BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name,
- const char htype, const char hflag)
+void BMO_slot_buffer_from_enabled_hflag(
+ BMesh *bm, BMOperator *op,
+ BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name,
+ const char htype, const char hflag)
{
bmo_slot_buffer_from_hflag(bm, op, slot_args, slot_name, htype, hflag, true);
}
-void BMO_slot_buffer_from_disabled_hflag(BMesh *bm, BMOperator *op,
- BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name,
- const char htype, const char hflag)
+void BMO_slot_buffer_from_disabled_hflag(
+ BMesh *bm, BMOperator *op,
+ BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name,
+ const char htype, const char hflag)
{
bmo_slot_buffer_from_hflag(bm, op, slot_args, slot_name, htype, hflag, false);
}
@@ -900,6 +909,21 @@ void BMO_slot_buffer_from_single(BMOperator *op, BMOpSlot *slot, BMHeader *ele)
*slot->data.buf = ele;
}
+void BMO_slot_buffer_from_array(BMOperator *op, BMOpSlot *slot, BMHeader **ele_buffer, int ele_buffer_len)
+{
+ BMO_ASSERT_SLOT_IN_OP(slot, op);
+ BLI_assert(slot->slot_type == BMO_OP_SLOT_ELEMENT_BUF);
+ BLI_assert(slot->len == 0 || slot->len == ele_buffer_len);
+
+ if (slot->data.buf == NULL) {
+ slot->data.buf = BLI_memarena_alloc(op->arena, sizeof(*slot->data.buf) * ele_buffer_len);
+ }
+
+ slot->len = ele_buffer_len;
+ memcpy(slot->data.buf, ele_buffer, ele_buffer_len * sizeof(*slot->data.buf));
+}
+
+
void *BMO_slot_buffer_get_single(BMOpSlot *slot)
{
BLI_assert(slot->slot_type == BMO_OP_SLOT_ELEMENT_BUF);
@@ -912,9 +936,10 @@ void *BMO_slot_buffer_get_single(BMOpSlot *slot)
/**
* Copies the values from another slot to the end of the output slot.
*/
-void _bmo_slot_buffer_append(BMOpSlot slot_args_dst[BMO_OP_MAX_SLOTS], const char *slot_name_dst,
- BMOpSlot slot_args_src[BMO_OP_MAX_SLOTS], const char *slot_name_src,
- struct MemArena *arena_dst)
+void _bmo_slot_buffer_append(
+ BMOpSlot slot_args_dst[BMO_OP_MAX_SLOTS], const char *slot_name_dst,
+ BMOpSlot slot_args_src[BMO_OP_MAX_SLOTS], const char *slot_name_src,
+ struct MemArena *arena_dst)
{
BMOpSlot *slot_dst = BMO_slot_get(slot_args_dst, slot_name_dst);
BMOpSlot *slot_src = BMO_slot_get(slot_args_src, slot_name_src);
@@ -949,10 +974,11 @@ void _bmo_slot_buffer_append(BMOpSlot slot_args_dst[BMO_OP_MAX_SLOTS], const cha
* Copies elements of a certain type, which have a certain flag set
* into an output slot for an operator.
*/
-static void bmo_slot_buffer_from_flag(BMesh *bm, BMOperator *op,
- BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name,
- const char htype, const short oflag,
- const bool test_for_enabled)
+static void bmo_slot_buffer_from_flag(
+ BMesh *bm, BMOperator *op,
+ BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name,
+ const char htype, const short oflag,
+ const bool test_for_enabled)
{
BMOpSlot *slot = BMO_slot_get(slot_args, slot_name);
int totelement, i = 0;
@@ -1011,16 +1037,18 @@ static void bmo_slot_buffer_from_flag(BMesh *bm, BMOperator *op,
}
}
-void BMO_slot_buffer_from_enabled_flag(BMesh *bm, BMOperator *op,
- BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name,
- const char htype, const short oflag)
+void BMO_slot_buffer_from_enabled_flag(
+ BMesh *bm, BMOperator *op,
+ BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name,
+ const char htype, const short oflag)
{
bmo_slot_buffer_from_flag(bm, op, slot_args, slot_name, htype, oflag, true);
}
-void BMO_slot_buffer_from_disabled_flag(BMesh *bm, BMOperator *op,
- BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name,
- const char htype, const short oflag)
+void BMO_slot_buffer_from_disabled_flag(
+ BMesh *bm, BMOperator *op,
+ BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name,
+ const char htype, const short oflag)
{
bmo_slot_buffer_from_flag(bm, op, slot_args, slot_name, htype, oflag, false);
}
@@ -1031,9 +1059,10 @@ void BMO_slot_buffer_from_disabled_flag(BMesh *bm, BMOperator *op,
* Header Flags elements in a slots buffer, automatically
* using the selection API where appropriate.
*/
-void BMO_slot_buffer_hflag_enable(BMesh *bm,
- BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name,
- const char htype, const char hflag, const bool do_flush)
+void BMO_slot_buffer_hflag_enable(
+ BMesh *bm,
+ BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name,
+ const char htype, const char hflag, const bool do_flush)
{
BMOpSlot *slot = BMO_slot_get(slot_args, slot_name);
BMElem **data = (BMElem **)slot->data.buf;
@@ -1067,9 +1096,10 @@ void BMO_slot_buffer_hflag_enable(BMesh *bm,
* Removes flags from elements in a slots buffer, automatically
* using the selection API where appropriate.
*/
-void BMO_slot_buffer_hflag_disable(BMesh *bm,
- BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name,
- const char htype, const char hflag, const bool do_flush)
+void BMO_slot_buffer_hflag_disable(
+ BMesh *bm,
+ BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name,
+ const char htype, const char hflag, const bool do_flush)
{
BMOpSlot *slot = BMO_slot_get(slot_args, slot_name);
BMElem **data = (BMElem **)slot->data.buf;
@@ -1101,9 +1131,10 @@ void BMO_slot_buffer_hflag_disable(BMesh *bm,
*
* Flags elements in a slots buffer
*/
-void BMO_slot_buffer_flag_enable(BMesh *bm,
- BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name,
- const char htype, const short oflag)
+void BMO_slot_buffer_flag_enable(
+ BMesh *bm,
+ BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name,
+ const char htype, const short oflag)
{
BMOpSlot *slot = BMO_slot_get(slot_args, slot_name);
BMHeader **data = slot->data.p;
@@ -1125,9 +1156,10 @@ void BMO_slot_buffer_flag_enable(BMesh *bm,
*
* Removes flags from elements in a slots buffer
*/
-void BMO_slot_buffer_flag_disable(BMesh *bm,
- BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name,
- const char htype, const short oflag)
+void BMO_slot_buffer_flag_disable(
+ BMesh *bm,
+ BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name,
+ const char htype, const short oflag)
{
BMOpSlot *slot = BMO_slot_get(slot_args, slot_name);
BMHeader **data = (BMHeader **)slot->data.buf;
@@ -1379,9 +1411,10 @@ void *BMO_slot_buffer_get_first(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char
* \param restrictmask restricts the iteration to certain element types
* (e.g. combination of BM_VERT, BM_EDGE, BM_FACE), if iterating
* over an element buffer (not a mapping). */
-void *BMO_iter_new(BMOIter *iter,
- BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name,
- const char restrictmask)
+void *BMO_iter_new(
+ BMOIter *iter,
+ BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name,
+ const char restrictmask)
{
BMOpSlot *slot = BMO_slot_get(slot_args, slot_name);
@@ -1636,6 +1669,7 @@ static int BMO_opcode_from_opname_check(const char *opname)
*
* **Element Buffer** (#BMO_OP_SLOT_ELEMENT_BUF)
* - `e` - single element vert/edge/face (use with #BMO_OP_SLOT_SUBTYPE_ELEM_IS_SINGLE).
+ * - `eb` - elem buffer, take an array and a length.
* - `av` - all verts
* - `ae` - all edges
* - `af` - all faces
@@ -1756,12 +1790,23 @@ bool BMO_op_vinitf(BMesh *bm, BMOperator *op, const int flag, const char *_fmt,
state = true;
break;
}
- case 'e': /* single vert/edge/face */
+ case 'e':
{
- BMHeader *ele = va_arg(vlist, void *);
BMOpSlot *slot = BMO_slot_get(op->slots_in, slot_name);
- BMO_slot_buffer_from_single(op, slot, ele);
+ if (NEXT_CHAR(fmt) == 'b') {
+ BMHeader **ele_buffer = va_arg(vlist, void *);
+ int ele_buffer_len = va_arg(vlist, int);
+
+ BMO_slot_buffer_from_array(op, slot, ele_buffer, ele_buffer_len);
+ fmt++;
+ }
+ else {
+ /* single vert/edge/face */
+ BMHeader *ele = va_arg(vlist, void *);
+
+ BMO_slot_buffer_from_single(op, slot, ele);
+ }
state = true;
break;
diff --git a/source/blender/bmesh/intern/bmesh_operators.h b/source/blender/bmesh/intern/bmesh_operators.h
index b3d97947cab..d9961e589da 100644
--- a/source/blender/bmesh/intern/bmesh_operators.h
+++ b/source/blender/bmesh/intern/bmesh_operators.h
@@ -33,10 +33,10 @@
/*quad innervert values*/
enum {
- SUBD_INNERVERT,
- SUBD_PATH,
- SUBD_FAN,
- SUBD_STRAIGHT_CUT
+ SUBD_CORNER_INNERVERT,
+ SUBD_CORNER_PATH,
+ SUBD_CORNER_FAN,
+ SUBD_CORNER_STRAIGHT_CUT
};
/* aligned with PROP_SMOOTH and friends */
@@ -46,6 +46,7 @@ enum {
SUBD_FALLOFF_ROOT,
SUBD_FALLOFF_SHARP,
SUBD_FALLOFF_LIN,
+ SUBD_FALLOFF_INVSQUARE = 7, /* matching PROP_INVSQUARE */
};
enum {
@@ -82,6 +83,7 @@ enum {
SIMFACE_PERIMETER,
SIMFACE_NORMAL,
SIMFACE_COPLANAR,
+ SIMFACE_SMOOTH,
#ifdef WITH_FREESTYLE
SIMFACE_FREESTYLE
#endif
@@ -129,14 +131,15 @@ extern const BMOpDefine *bmo_opdefines[];
extern const int bmo_opdefines_total;
/*------specific operator helper functions-------*/
-void BM_mesh_esubdivide(BMesh *bm, const char edge_hflag,
- const float smooth, const short smooth_falloff, const bool use_smooth_even,
- const float fractal, const float along_normal,
- const int numcuts,
- const int seltype, const int cornertype,
- const short use_single_edge, const short use_grid_fill,
- const short use_only_quads,
- const int seed);
+void BM_mesh_esubdivide(
+ BMesh *bm, const char edge_hflag,
+ const float smooth, const short smooth_falloff, const bool use_smooth_even,
+ const float fractal, const float along_normal,
+ const int numcuts,
+ const int seltype, const int cornertype,
+ const short use_single_edge, const short use_grid_fill,
+ const short use_only_quads,
+ const int seed);
#include "intern/bmesh_operator_api_inline.h"
diff --git a/source/blender/bmesh/intern/bmesh_operators_private.h b/source/blender/bmesh/intern/bmesh_operators_private.h
index 9c1b7085835..5548ee7c361 100644
--- a/source/blender/bmesh/intern/bmesh_operators_private.h
+++ b/source/blender/bmesh/intern/bmesh_operators_private.h
@@ -41,6 +41,7 @@ void bmo_bridge_loops_exec(BMesh *bm, BMOperator *op);
void bmo_collapse_exec(BMesh *bm, BMOperator *op);
void bmo_collapse_uvs_exec(BMesh *bm, BMOperator *op);
void bmo_connect_verts_exec(BMesh *bm, BMOperator *op);
+void bmo_connect_verts_concave_exec(BMesh *bm, BMOperator *op);
void bmo_connect_verts_nonplanar_exec(BMesh *bm, BMOperator *op);
void bmo_connect_vert_pair_exec(BMesh *bm, BMOperator *op);
void bmo_contextual_create_exec(BMesh *bm, BMOperator *op);
@@ -81,6 +82,8 @@ void bmo_pointmerge_exec(BMesh *bm, BMOperator *op);
void bmo_pointmerge_facedata_exec(BMesh *bm, BMOperator *op);
void bmo_recalc_face_normals_exec(BMesh *bm, BMOperator *op);
void bmo_poke_exec(BMesh *bm, BMOperator *op);
+void bmo_offset_edgeloops_exec(BMesh *bm, BMOperator *op);
+void bmo_planar_faces_exec(BMesh *bm, BMOperator *op);
void bmo_region_extend_exec(BMesh *bm, BMOperator *op);
void bmo_remove_doubles_exec(BMesh *bm, BMOperator *op);
void bmo_reverse_colors_exec(BMesh *bm, BMOperator *op);
diff --git a/source/blender/bmesh/intern/bmesh_polygon.c b/source/blender/bmesh/intern/bmesh_polygon.c
index 9a1914b5596..b0eddf73960 100644
--- a/source/blender/bmesh/intern/bmesh_polygon.c
+++ b/source/blender/bmesh/intern/bmesh_polygon.c
@@ -37,6 +37,7 @@
#include "BLI_math.h"
#include "BLI_memarena.h"
#include "BLI_polyfill2d.h"
+#include "BLI_polyfill2d_beautify.h"
#include "bmesh.h"
#include "bmesh_tools.h"
@@ -98,11 +99,12 @@ static float bm_face_calc_poly_normal(const BMFace *f, float n[3])
/**
* \brief COMPUTE POLY NORMAL (BMFace)
*
- * Same as #calc_poly_normal and #bm_face_calc_poly_normal
+ * Same as #bm_face_calc_poly_normal
* but takes an array of vertex locations.
*/
-static float bm_face_calc_poly_normal_vertex_cos(BMFace *f, float r_no[3],
- float const (*vertexCos)[3])
+static float bm_face_calc_poly_normal_vertex_cos(
+ BMFace *f, float r_no[3],
+ float const (*vertexCos)[3])
{
BMLoop *l_first = BM_FACE_FIRST_LOOP(f);
BMLoop *l_iter = l_first;
@@ -126,8 +128,9 @@ static float bm_face_calc_poly_normal_vertex_cos(BMFace *f, float r_no[3],
/**
* \brief COMPUTE POLY CENTER (BMFace)
*/
-static void bm_face_calc_poly_center_mean_vertex_cos(BMFace *f, float r_cent[3],
- float const (*vertexCos)[3])
+static void bm_face_calc_poly_center_mean_vertex_cos(
+ BMFace *f, float r_cent[3],
+ float const (*vertexCos)[3])
{
BMLoop *l_first = BM_FACE_FIRST_LOOP(f);
BMLoop *l_iter = l_first;
@@ -213,9 +216,6 @@ float BM_face_calc_area(BMFace *f)
if (f->len == 3) {
area = area_tri_v3(verts[0], verts[1], verts[2]);
}
- else if (f->len == 4) {
- area = area_quad_v3(verts[0], verts[1], verts[2], verts[3]);
- }
else {
area = area_poly_v3((const float (*)[3])verts, f->len);
}
@@ -422,6 +422,43 @@ void BM_edge_normals_update(BMEdge *e)
BM_vert_normal_update(e->v2);
}
+bool BM_vert_normal_update_ex(BMVert *v, const char hflag, float r_no[3])
+{
+ /* TODO, we can normalize each edge only once, then compare with previous edge */
+
+ BMIter liter;
+ BMLoop *l;
+ int len = 0;
+
+ zero_v3(r_no);
+
+ BM_ITER_ELEM (l, &liter, v, BM_LOOPS_OF_VERT) {
+ if (BM_elem_flag_test(l->f, hflag)) {
+ float vec1[3], vec2[3], fac;
+
+ /* Same calculation used in BM_mesh_normals_update */
+ sub_v3_v3v3(vec1, l->v->co, l->prev->v->co);
+ sub_v3_v3v3(vec2, l->next->v->co, l->v->co);
+ normalize_v3(vec1);
+ normalize_v3(vec2);
+
+ fac = saacos(-dot_v3v3(vec1, vec2));
+
+ madd_v3_v3fl(r_no, l->f->no, fac);
+
+ len++;
+ }
+ }
+
+ if (len) {
+ normalize_v3(r_no);
+ return true;
+ }
+ else {
+ return false;
+ }
+}
+
/**
* update a vert normal (but not the faces incident on it)
*/
@@ -431,12 +468,13 @@ void BM_vert_normal_update(BMVert *v)
BMIter liter;
BMLoop *l;
- float vec1[3], vec2[3], fac;
int len = 0;
zero_v3(v->no);
BM_ITER_ELEM (l, &liter, v, BM_LOOPS_OF_VERT) {
+ float vec1[3], vec2[3], fac;
+
/* Same calculation used in BM_mesh_normals_update */
sub_v3_v3v3(vec1, l->v->co, l->prev->v->co);
sub_v3_v3v3(vec2, l->next->v->co, l->v->co);
@@ -512,8 +550,9 @@ void BM_face_normal_update(BMFace *f)
}
/* exact same as 'BM_face_calc_normal' but accepts vertex coords */
-float BM_face_calc_normal_vcos(BMesh *bm, BMFace *f, float r_no[3],
- float const (*vertexCos)[3])
+float BM_face_calc_normal_vcos(
+ BMesh *bm, BMFace *f, float r_no[3],
+ float const (*vertexCos)[3])
{
BMLoop *l;
@@ -571,8 +610,9 @@ float BM_face_calc_normal_subset(BMLoop *l_first, BMLoop *l_last, float r_no[3])
}
/* exact same as 'BM_face_calc_normal' but accepts vertex coords */
-void BM_face_calc_center_mean_vcos(BMesh *bm, BMFace *f, float r_cent[3],
- float const (*vertexCos)[3])
+void BM_face_calc_center_mean_vcos(
+ BMesh *bm, BMFace *f, float r_cent[3],
+ float const (*vertexCos)[3])
{
/* must have valid index data */
BLI_assert((bm->elem_index_dirty & BM_VERT) == 0);
@@ -666,49 +706,25 @@ static bool line_crosses_v2f(const float v1[2], const float v2[2], const float v
*/
bool BM_face_point_inside_test(BMFace *f, const float co[3])
{
- int ax, ay;
- float co2[2], cent[2] = {0.0f, 0.0f}, out[2] = {FLT_MAX * 0.5f, FLT_MAX * 0.5f};
+ float axis_mat[3][3];
+ float (*projverts)[2] = BLI_array_alloca(projverts, f->len);
+
+ float co_2d[2];
BMLoop *l_iter;
- BMLoop *l_first;
- int crosses = 0;
- float onepluseps = 1.0f + (float)FLT_EPSILON * 150.0f;
+ int i;
if (is_zero_v3(f->no))
BM_face_normal_update(f);
-
- /* find best projection of face XY, XZ or YZ: barycentric weights of
- * the 2d projected coords are the same and faster to compute
- *
- * this probably isn't all that accurate, but it has the advantage of
- * being fast (especially compared to projecting into the face orientation)
- */
- axis_dominant_v3(&ax, &ay, f->no);
-
- co2[0] = co[ax];
- co2[1] = co[ay];
-
- l_iter = l_first = BM_FACE_FIRST_LOOP(f);
- do {
- cent[0] += l_iter->v->co[ax];
- cent[1] += l_iter->v->co[ay];
- } while ((l_iter = l_iter->next) != l_first);
-
- mul_v2_fl(cent, 1.0f / (float)f->len);
-
- l_iter = l_first = BM_FACE_FIRST_LOOP(f);
- do {
- float v1[2], v2[2];
-
- v1[0] = (l_iter->prev->v->co[ax] - cent[0]) * onepluseps + cent[0];
- v1[1] = (l_iter->prev->v->co[ay] - cent[1]) * onepluseps + cent[1];
-
- v2[0] = (l_iter->v->co[ax] - cent[0]) * onepluseps + cent[0];
- v2[1] = (l_iter->v->co[ay] - cent[1]) * onepluseps + cent[1];
-
- crosses += line_crosses_v2f(v1, v2, co2, out) != 0;
- } while ((l_iter = l_iter->next) != l_first);
-
- return crosses % 2 != 0;
+
+ axis_dominant_v3_to_m3(axis_mat, f->no);
+
+ mul_v2_m3v3(co_2d, axis_mat, co);
+
+ for (i = 0, l_iter = BM_FACE_FIRST_LOOP(f); i < f->len; i++, l_iter = l_iter->next) {
+ mul_v2_m3v3(projverts[i], axis_mat, l_iter->v->co);
+ }
+
+ return isect_point_poly_v2(co_2d, (const float (*)[2])projverts, f->len, false);
}
/**
@@ -728,20 +744,24 @@ bool BM_face_point_inside_test(BMFace *f, const float co[3])
*
* \note use_tag tags new flags and edges.
*/
-void BM_face_triangulate(BMesh *bm, BMFace *f,
- BMFace **r_faces_new,
- int *r_faces_new_tot,
- MemArena *sf_arena,
- const int quad_method,
- const int ngon_method,
- const bool use_tag)
+void BM_face_triangulate(
+ BMesh *bm, BMFace *f,
+ BMFace **r_faces_new,
+ int *r_faces_new_tot,
+ BMEdge **r_edges_new,
+ int *r_edges_new_tot,
+ const int quad_method,
+ const int ngon_method,
+ const bool use_tag,
+ MemArena *pf_arena,
+
+ /* use for MOD_TRIANGULATE_NGON_BEAUTY only! */
+ struct Heap *pf_heap, struct EdgeHash *pf_ehash)
{
BMLoop *l_iter, *l_first, *l_new;
BMFace *f_new;
- int orig_f_len = f->len;
int nf_i = 0;
- BMEdge **edge_array;
- int edge_array_len;
+ int ne_i = 0;
bool use_beauty = (ngon_method == MOD_TRIANGULATE_NGON_BEAUTY);
BLI_assert(BM_face_is_normal_valid(f));
@@ -767,38 +787,39 @@ void BM_face_triangulate(BMesh *bm, BMFace *f,
break;
}
case MOD_TRIANGULATE_QUAD_SHORTEDGE:
- {
- BMLoop *l_v3, *l_v4;
- float d1, d2;
-
- l_v1 = l_first;
- l_v2 = l_first->next->next;
- l_v3 = l_first->next;
- l_v4 = l_first->prev;
-
- d1 = len_squared_v3v3(l_v1->v->co, l_v2->v->co);
- d2 = len_squared_v3v3(l_v3->v->co, l_v4->v->co);
-
- if (d2 < d1) {
- l_v1 = l_v3;
- l_v2 = l_v4;
- }
- break;
- }
case MOD_TRIANGULATE_QUAD_BEAUTY:
default:
{
BMLoop *l_v3, *l_v4;
- float cost;
+ bool split_24;
l_v1 = l_first->next;
l_v2 = l_first->next->next;
l_v3 = l_first->prev;
l_v4 = l_first;
- cost = BM_verts_calc_rotate_beauty(l_v1->v, l_v2->v, l_v3->v, l_v4->v, 0, 0);
+ if (quad_method == MOD_TRIANGULATE_QUAD_SHORTEDGE) {
+ float d1, d2;
+ d1 = len_squared_v3v3(l_v4->v->co, l_v2->v->co);
+ d2 = len_squared_v3v3(l_v1->v->co, l_v3->v->co);
+ split_24 = ((d2 - d1) > 0.0f);
+ }
+ else {
+ /* first check if the quad is concave on either diagonal */
+ const int flip_flag = is_quad_flip_v3(l_v1->v->co, l_v2->v->co, l_v3->v->co, l_v4->v->co);
+ if (UNLIKELY(flip_flag & (1 << 0))) {
+ split_24 = true;
+ }
+ else if (UNLIKELY(flip_flag & (1 << 1))) {
+ split_24 = false;
+ }
+ else {
+ split_24 = (BM_verts_calc_rotate_beauty(l_v1->v, l_v2->v, l_v3->v, l_v4->v, 0, 0) > 0.0f);
+ }
+ }
- if (cost < 0.0f) {
+ /* named confusingly, l_v1 is in fact the second vertex */
+ if (split_24) {
l_v1 = l_v4;
//l_v2 = l_v2;
}
@@ -821,6 +842,9 @@ void BM_face_triangulate(BMesh *bm, BMFace *f,
if (r_faces_new) {
r_faces_new[nf_i++] = f_new;
}
+ if (r_edges_new) {
+ r_edges_new[ne_i++] = l_new->e;
+ }
}
else if (f->len > 4) {
@@ -832,28 +856,31 @@ void BM_face_triangulate(BMesh *bm, BMFace *f,
const int last_tri = f->len - 3;
int i;
- axis_dominant_v3_to_m3(axis_mat, f->no);
+ axis_dominant_v3_to_m3_negate(axis_mat, f->no);
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);
}
- BLI_polyfill_calc_arena((const float (*)[2])projverts, f->len, -1, tris,
- sf_arena);
+ BLI_polyfill_calc_arena((const float (*)[2])projverts, f->len, 1, tris,
+ pf_arena);
if (use_beauty) {
- edge_array = BLI_array_alloca(edge_array, orig_f_len - 3);
- edge_array_len = 0;
+ BLI_polyfill_beautify(
+ (const float (*)[2])projverts, f->len, tris,
+ pf_arena, pf_heap, pf_ehash);
}
+ BLI_memarena_clear(pf_arena);
+
/* loop over calculated triangles and create new geometry */
for (i = 0; i < totfilltri; i++) {
/* the order is reverse, otherwise the normal is flipped */
BMLoop *l_tri[3] = {
- loops[tris[i][2]],
+ loops[tris[i][0]],
loops[tris[i][1]],
- loops[tris[i][0]]};
+ loops[tris[i][2]]};
BMVert *v_tri[3] = {
l_tri[0]->v,
@@ -880,8 +907,7 @@ void BM_face_triangulate(BMesh *bm, BMFace *f,
}
}
- /* we know any edge that we create and _isnt_ */
- if (use_beauty || use_tag) {
+ if (use_tag || r_edges_new) {
/* new faces loops */
l_iter = l_first = l_new;
do {
@@ -891,14 +917,11 @@ void BM_face_triangulate(BMesh *bm, BMFace *f,
bool is_new_edge = (l_iter == l_iter->radial_next);
if (is_new_edge) {
- if (use_beauty) {
- edge_array[edge_array_len] = e;
- edge_array_len++;
- }
-
if (use_tag) {
BM_elem_flag_enable(e, BM_ELEM_TAG);
-
+ }
+ if (r_edges_new) {
+ r_edges_new[ne_i++] = e;
}
}
/* note, never disable tag's */
@@ -906,83 +929,22 @@ void BM_face_triangulate(BMesh *bm, BMFace *f,
}
}
- if ((!use_beauty) || (!r_faces_new)) {
+ {
/* we can't delete the real face, because some of the callers expect it to remain valid.
* so swap data and delete the last created tri */
bmesh_face_swap_data(f, f_new);
BM_face_kill(bm, f_new);
}
-
- if (use_beauty) {
- BLI_assert(edge_array_len <= orig_f_len - 3);
-
- BM_mesh_beautify_fill(bm, edge_array, edge_array_len, 0, 0, 0, 0);
-
- if (r_faces_new) {
- /* beautify deletes and creates new faces
- * we need to re-populate the r_faces_new array
- * with the new faces
- */
- int i;
-
-
-#define FACE_USED_TEST(f) (BM_elem_index_get(f) == -2)
-#define FACE_USED_SET(f) BM_elem_index_set(f, -2)
-
- nf_i = 0;
- for (i = 0; i < edge_array_len; i++) {
- BMFace *f_a, *f_b;
- BMEdge *e = edge_array[i];
-#ifndef NDEBUG
- const bool ok = BM_edge_face_pair(e, &f_a, &f_b);
- BLI_assert(ok);
-#else
- BM_edge_face_pair(e, &f_a, &f_b);
-#endif
-
- if (FACE_USED_TEST(f_a) == false) {
- FACE_USED_SET(f_a); /* set_dirty */
-
- if (nf_i < edge_array_len) {
- r_faces_new[nf_i++] = f_a;
- }
- else {
- f_new = f_a;
- break;
- }
- }
-
- if (FACE_USED_TEST(f_b) == false) {
- FACE_USED_SET(f_b); /* set_dirty */
-
- if (nf_i < edge_array_len) {
- r_faces_new[nf_i++] = f_b;
- }
- else {
- f_new = f_b;
- break;
- }
- }
- }
-
-#undef FACE_USED_TEST
-#undef FACE_USED_SET
-
- /* nf_i doesn't include the last face */
- BLI_assert(nf_i <= orig_f_len - 3);
-
- /* we can't delete the real face, because some of the callers expect it to remain valid.
- * so swap data and delete the last created tri */
- bmesh_face_swap_data(f, f_new);
- BM_face_kill(bm, f_new);
- }
- }
}
bm->elem_index_dirty |= BM_FACE;
if (r_faces_new_tot) {
*r_faces_new_tot = nf_i;
}
+
+ if (r_edges_new_tot) {
+ *r_edges_new_tot = ne_i;
+ }
}
/**
@@ -1299,7 +1261,7 @@ void BM_bmesh_calc_tessellation(BMesh *bm, BMLoop *(*looptris)[3], int *r_looptr
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);
+ axis_dominant_v3_to_m3_negate(axis_mat, efa->no);
j = 0;
l_iter = l_first = BM_FACE_FIRST_LOOP(efa);
@@ -1309,15 +1271,15 @@ void BM_bmesh_calc_tessellation(BMesh *bm, BMLoop *(*looptris)[3], int *r_looptr
j++;
} while ((l_iter = l_iter->next) != l_first);
- BLI_polyfill_calc_arena((const float (*)[2])projverts, efa->len, -1, tris, arena);
+ BLI_polyfill_calc_arena((const float (*)[2])projverts, efa->len, 1, tris, arena);
for (j = 0; j < totfilltri; j++) {
BMLoop **l_ptr = looptris[i++];
unsigned int *tri = tris[j];
- l_ptr[0] = l_arr[tri[2]];
+ l_ptr[0] = l_arr[tri[0]];
l_ptr[1] = l_arr[tri[1]];
- l_ptr[2] = l_arr[tri[0]];
+ l_ptr[2] = l_arr[tri[2]];
}
BLI_memarena_clear(arena);
diff --git a/source/blender/bmesh/intern/bmesh_polygon.h b/source/blender/bmesh/intern/bmesh_polygon.h
index 91e649edb16..582b4248c7d 100644
--- a/source/blender/bmesh/intern/bmesh_polygon.h
+++ b/source/blender/bmesh/intern/bmesh_polygon.h
@@ -27,40 +27,51 @@
* \ingroup bmesh
*/
+struct EdgeHash;
+struct Heap;
+
#include "BLI_compiler_attrs.h"
void BM_bmesh_calc_tessellation(BMesh *bm, BMLoop *(*looptris)[3], int *r_looptris_tot);
void BM_face_calc_tessellation(const BMFace *f, BMLoop **r_loops, unsigned int (*r_index)[3]);
float BM_face_calc_normal(const BMFace *f, float r_no[3]) ATTR_NONNULL();
-float BM_face_calc_normal_vcos(BMesh *bm, BMFace *f, float r_no[3],
- float const (*vertexCos)[3]) ATTR_NONNULL();
+float BM_face_calc_normal_vcos(
+ BMesh *bm, BMFace *f, float r_no[3],
+ float const (*vertexCos)[3]) ATTR_NONNULL();
float BM_face_calc_normal_subset(BMLoop *l_first, BMLoop *l_last, float r_no[3]) ATTR_NONNULL();
float BM_face_calc_area(BMFace *f) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
float BM_face_calc_perimeter(BMFace *f) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
void BM_face_calc_plane(BMFace *f, float r_plane[3]) ATTR_NONNULL();
void BM_face_calc_center_bounds(BMFace *f, float center[3]) ATTR_NONNULL();
void BM_face_calc_center_mean(BMFace *f, float center[3]) ATTR_NONNULL();
-void BM_face_calc_center_mean_vcos(BMesh *bm, BMFace *f, float r_cent[3],
- float const (*vertexCos)[3]) ATTR_NONNULL();
+void BM_face_calc_center_mean_vcos(
+ BMesh *bm, BMFace *f, float r_cent[3],
+ float const (*vertexCos)[3]) ATTR_NONNULL();
void BM_face_calc_center_mean_weighted(BMFace *f, float center[3]) ATTR_NONNULL();
void BM_face_normal_update(BMFace *f) ATTR_NONNULL();
void BM_edge_normals_update(BMEdge *e) ATTR_NONNULL();
+bool BM_vert_normal_update_ex(BMVert *v, const char hflag, float r_no[3]);
void BM_vert_normal_update(BMVert *v) ATTR_NONNULL();
void BM_vert_normal_update_all(BMVert *v) ATTR_NONNULL();
void BM_face_normal_flip(BMesh *bm, BMFace *f) ATTR_NONNULL();
bool BM_face_point_inside_test(BMFace *f, const float co[3]) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-void BM_face_triangulate(BMesh *bm, BMFace *f,
- BMFace **r_faces_new,
- int *r_faces_new_tot,
- struct MemArena *sf_arena,
- const int quad_method, const int ngon_method,
- const bool use_tag) ATTR_NONNULL(1, 2);
+void BM_face_triangulate(
+ BMesh *bm, BMFace *f,
+ BMFace **r_faces_new,
+ int *r_faces_new_tot,
+ BMEdge **r_edges_new,
+ int *r_edges_new_tot,
+ const int quad_method, const int ngon_method,
+ const bool use_tag,
+ struct MemArena *pf_arena,
+ struct Heap *pf_heap, struct EdgeHash *pf_ehash
+ ) ATTR_NONNULL(1, 2);
void BM_face_splits_check_legal(BMesh *bm, BMFace *f, BMLoop *(*loops)[2], int len) ATTR_NONNULL();
void BM_face_splits_check_optimal(BMFace *f, BMLoop *(*loops)[2], int len) ATTR_NONNULL();
diff --git a/source/blender/bmesh/intern/bmesh_private.h b/source/blender/bmesh/intern/bmesh_private.h
index 102a677943b..814015a2a74 100644
--- a/source/blender/bmesh/intern/bmesh_private.h
+++ b/source/blender/bmesh/intern/bmesh_private.h
@@ -54,6 +54,7 @@ int bmesh_elem_check(void *element, const char htype);
#endif
int bmesh_radial_length(const BMLoop *l);
+int bmesh_disk_count_ex(const BMVert *v, const int count_max);
int bmesh_disk_count(const BMVert *v);
/**
diff --git a/source/blender/bmesh/intern/bmesh_queries.c b/source/blender/bmesh/intern/bmesh_queries.c
index 685e5443583..1a8ea1e3a0d 100644
--- a/source/blender/bmesh/intern/bmesh_queries.c
+++ b/source/blender/bmesh/intern/bmesh_queries.c
@@ -38,6 +38,8 @@
#include "BLI_linklist.h"
#include "BLI_stackdefines.h"
+#include "BKE_customdata.h"
+
#include "bmesh.h"
#include "intern/bmesh_private.h"
@@ -193,7 +195,7 @@ bool BM_vert_pair_share_face_check(
BMFace *f;
BM_ITER_ELEM (f, &iter, v_a, BM_FACES_OF_VERT) {
- if (BM_vert_in_face(f, v_b)) {
+ if (BM_vert_in_face(v_b, f)) {
return true;
}
}
@@ -202,6 +204,26 @@ bool BM_vert_pair_share_face_check(
return false;
}
+bool BM_vert_pair_share_face_check_cb(
+ BMVert *v_a, BMVert *v_b,
+ bool (*test_fn)(BMFace *, void *user_data), void *user_data)
+{
+ if (v_a->e && v_b->e) {
+ BMIter iter;
+ BMFace *f;
+
+ BM_ITER_ELEM (f, &iter, v_a, BM_FACES_OF_VERT) {
+ if (test_fn(f, user_data)) {
+ if (BM_vert_in_face(v_b, f)) {
+ return true;
+ }
+ }
+ }
+ }
+
+ return false;
+}
+
/**
* Given 2 verts, find the smallest face they share and give back both loops.
*/
@@ -235,6 +257,36 @@ BMFace *BM_vert_pair_share_face_by_len(
return f_cur;
}
+BMFace *BM_edge_pair_share_face_by_len(
+ BMEdge *e_a, BMEdge *e_b,
+ BMLoop **r_l_a, BMLoop **r_l_b,
+ const bool allow_adjacent)
+{
+ BMLoop *l_cur_a = NULL, *l_cur_b = NULL;
+ BMFace *f_cur = NULL;
+
+ if (e_a->l && e_b->l) {
+ BMIter iter;
+ BMLoop *l_a, *l_b;
+
+ BM_ITER_ELEM (l_a, &iter, e_a, BM_LOOPS_OF_EDGE) {
+ if ((f_cur == NULL) || (l_a->f->len < f_cur->len)) {
+ l_b = BM_face_edge_share_loop(l_a->f, e_b);
+ if (l_b && (allow_adjacent || !BM_loop_is_adjacent(l_a, l_b))) {
+ f_cur = l_a->f;
+ l_cur_a = l_a;
+ l_cur_b = l_b;
+ }
+ }
+ }
+ }
+
+ *r_l_a = l_cur_a;
+ *r_l_b = l_cur_b;
+
+ return f_cur;
+}
+
static float bm_face_calc_split_dot(BMLoop *l_a, BMLoop *l_b)
{
float no[2][3];
@@ -250,6 +302,37 @@ static float bm_face_calc_split_dot(BMLoop *l_a, BMLoop *l_b)
}
/**
+ * Check if a point is inside the corner defined by a loop
+ * (within the 2 planes defined by the loops corner & face normal).
+ *
+ * \return signed, squared distance to the loops planes, less than 0.0 when outside.
+ */
+float BM_loop_point_side_of_loop_test(const BMLoop *l, const float co[3])
+{
+ const float *axis = l->f->no;
+ return dist_signed_squared_to_corner_v3v3v3(co, l->prev->v->co, l->v->co, l->next->v->co, axis);
+}
+
+/**
+ * Check if a point is inside the edge defined by a loop
+ * (within the plane defined by the loops edge & face normal).
+ *
+ * \return signed, squared distance to the edge plane, less than 0.0 when outside.
+ */
+float BM_loop_point_side_of_edge_test(const BMLoop *l, const float co[3])
+{
+ const float *axis = l->f->no;
+ float dir[3];
+ float plane[4];
+
+ sub_v3_v3v3(dir, l->next->v->co, l->v->co);
+ cross_v3_v3v3(plane, axis, dir);
+
+ plane[3] = -dot_v3v3(plane, l->v->co);
+ return dist_signed_squared_to_plane_v3(co, plane);
+}
+
+/**
* Given 2 verts, find a face they share that has the lowest angle across these verts and give back both loops.
*
* This can be better then #BM_vert_pair_share_face_by_len because concave splits are ranked lowest.
@@ -311,7 +394,7 @@ BMLoop *BM_vert_find_first_loop(BMVert *v)
{
BMEdge *e;
- if (!v || !v->e)
+ if (!v->e)
return NULL;
e = bmesh_disk_faceedge_find_first(v->e, v);
@@ -325,7 +408,7 @@ BMLoop *BM_vert_find_first_loop(BMVert *v)
/**
* Returns true if the vertex is used in a given face.
*/
-bool BM_vert_in_face(BMFace *f, BMVert *v)
+bool BM_vert_in_face(BMVert *v, BMFace *f)
{
BMLoop *l_iter, *l_first;
@@ -353,7 +436,7 @@ bool BM_vert_in_face(BMFace *f, BMVert *v)
* Compares the number of vertices in an array
* that appear in a given face
*/
-int BM_verts_in_face_count(BMFace *f, BMVert **varr, int len)
+int BM_verts_in_face_count(BMVert **varr, int len, BMFace *f)
{
BMLoop *l_iter, *l_first;
@@ -397,7 +480,7 @@ int BM_verts_in_face_count(BMFace *f, BMVert **varr, int len)
/**
* Return true if all verts are in the face.
*/
-bool BM_verts_in_face(BMFace *f, BMVert **varr, int len)
+bool BM_verts_in_face(BMVert **varr, int len, BMFace *f)
{
BMLoop *l_iter, *l_first;
@@ -448,12 +531,12 @@ bool BM_verts_in_face(BMFace *f, BMVert **varr, int len)
}
/**
- * Returns whether or not a given edge is is part of a given face.
+ * Returns whether or not a given edge is part of a given face.
*/
-bool BM_edge_in_face(BMEdge *e, BMFace *f)
+bool BM_edge_in_face(const BMEdge *e, const BMFace *f)
{
if (e->l) {
- BMLoop *l_iter, *l_first;
+ const BMLoop *l_iter, *l_first;
l_iter = l_first = e->l;
do {
@@ -613,7 +696,7 @@ BMEdge *BM_vert_other_disk_edge(BMVert *v, BMEdge *e_first)
/**
* Returns edge length
*/
-float BM_edge_calc_length(BMEdge *e)
+float BM_edge_calc_length(const BMEdge *e)
{
return len_v3v3(e->v1->co, e->v2->co);
}
@@ -621,7 +704,7 @@ float BM_edge_calc_length(BMEdge *e)
/**
* Returns edge length squared (for comparisons)
*/
-float BM_edge_calc_length_squared(BMEdge *e)
+float BM_edge_calc_length_squared(const BMEdge *e)
{
return len_squared_v3v3(e->v1->co, e->v2->co);
}
@@ -681,9 +764,9 @@ bool BM_edge_loop_pair(BMEdge *e, BMLoop **r_la, BMLoop **r_lb)
/**
* Fast alternative to ``(BM_vert_edge_count(v) == 2)``
*/
-bool BM_vert_is_edge_pair(BMVert *v)
+bool BM_vert_is_edge_pair(const BMVert *v)
{
- BMEdge *e = v->e;
+ const BMEdge *e = v->e;
if (e) {
const BMDiskLink *dl = bmesh_disk_edge_link_from_vert(e, v);
return (dl->next == dl->prev);
@@ -694,17 +777,22 @@ bool BM_vert_is_edge_pair(BMVert *v)
/**
* Returns the number of edges around this vertex.
*/
-int BM_vert_edge_count(BMVert *v)
+int BM_vert_edge_count(const BMVert *v)
{
return bmesh_disk_count(v);
}
-int BM_vert_edge_count_nonwire(BMVert *v)
+int BM_vert_edge_count_ex(const BMVert *v, const int count_max)
+{
+ return bmesh_disk_count_ex(v, count_max);
+}
+
+int BM_vert_edge_count_nonwire(const BMVert *v)
{
int count = 0;
BMIter eiter;
BMEdge *edge;
- BM_ITER_ELEM (edge, &eiter, v, BM_EDGES_OF_VERT) {
+ BM_ITER_ELEM (edge, &eiter, (BMVert *)v, BM_EDGES_OF_VERT) {
if (edge->l) {
count++;
}
@@ -714,18 +802,35 @@ int BM_vert_edge_count_nonwire(BMVert *v)
/**
* Returns the number of faces around this edge
*/
-int BM_edge_face_count(BMEdge *e)
+int BM_edge_face_count(const BMEdge *e)
{
int count = 0;
if (e->l) {
- BMLoop *l_iter;
- BMLoop *l_first;
+ BMLoop *l_iter, *l_first;
l_iter = l_first = e->l;
+ do {
+ count++;
+ } while ((l_iter = l_iter->radial_next) != l_first);
+ }
+
+ return count;
+}
+
+int BM_edge_face_count_ex(const BMEdge *e, const int count_max)
+{
+ int count = 0;
+
+ if (e->l) {
+ BMLoop *l_iter, *l_first;
+ l_iter = l_first = e->l;
do {
count++;
+ if (count == count_max) {
+ break;
+ }
} while ((l_iter = l_iter->radial_next) != l_first);
}
@@ -736,11 +841,26 @@ int BM_edge_face_count(BMEdge *e)
* Returns the number of faces around this vert
* length matches #BM_LOOPS_OF_VERT iterator
*/
-int BM_vert_face_count(BMVert *v)
+int BM_vert_face_count(const BMVert *v)
{
return bmesh_disk_facevert_count(v);
}
+int BM_vert_face_count_ex(const BMVert *v, int count_max)
+{
+ return bmesh_disk_facevert_count_ex(v, count_max);
+}
+
+/**
+ * Return true if the vertex is connected to _any_ faces.
+ *
+ * same as ``BM_vert_face_count(v) != 0`` or ``BM_vert_find_first_loop(v) == NULL``
+ */
+bool BM_vert_face_check(BMVert *v)
+{
+ return v->e && (bmesh_disk_faceedge_find_first(v->e, v) != NULL);
+}
+
/**
* Tests whether or not the vertex is part of a wire edge.
* (ie: has no faces attached to it)
@@ -773,9 +893,9 @@ bool BM_vert_is_wire(const BMVert *v)
*/
bool BM_vert_is_manifold(const BMVert *v)
{
- BMEdge *e, *e_old;
- BMLoop *l;
- int len, count, flag;
+ BMEdge *e_iter, *e_first, *e_prev;
+ BMLoop *l_iter, *l_first;
+ int loop_num = 0, loop_num_region = 0, boundary_num = 0;
if (v->e == NULL) {
/* loose vert */
@@ -783,50 +903,150 @@ bool BM_vert_is_manifold(const BMVert *v)
}
/* count edges while looking for non-manifold edges */
- len = 0;
- e_old = e = v->e;
+ e_first = e_iter = v->e;
+ l_first = e_iter->l ? e_iter->l : NULL;
do {
/* loose edge or edge shared by more than two faces,
* edges with 1 face user are OK, otherwise we could
* use BM_edge_is_manifold() here */
- if (e->l == NULL || bmesh_radial_length(e->l) > 2) {
+ if (e_iter->l == NULL || (e_iter->l != e_iter->l->radial_next->radial_next)) {
return false;
}
- len++;
- } while ((e = bmesh_disk_edge_next(e, v)) != e_old);
-
- count = 1;
- flag = 1;
- e = NULL;
- e_old = v->e;
- l = e_old->l;
- while (e != e_old) {
- l = (l->v == v) ? l->prev : l->next;
- e = l->e;
- count++; /* count the edges */
-
- if (flag && l->radial_next == l) {
- /* we've hit the edge of an open mesh, reset once */
- flag = 0;
- count = 1;
- e_old = e;
- e = NULL;
- l = e_old->l;
- }
- else if (l->radial_next == l) {
- /* break the loop */
- e = e_old;
+
+ /* count radial loops */
+ if (e_iter->l->v == v) {
+ loop_num += 1;
+ }
+
+ if (!BM_edge_is_boundary(e_iter)) {
+ /* non boundary check opposite loop */
+ if (e_iter->l->radial_next->v == v) {
+ loop_num += 1;
+ }
+ }
+ else {
+ /* start at the boundary */
+ l_first = e_iter->l;
+ boundary_num += 1;
+ /* >2 boundaries cant be manifold */
+ if (boundary_num == 3) {
+ return false;
+ }
+ }
+ } while ((e_iter = bmesh_disk_edge_next(e_iter, v)) != e_first);
+
+ e_first = l_first->e;
+ l_first = (l_first->v == v) ? l_first : l_first->next;
+ BLI_assert(l_first->v == v);
+
+ l_iter = l_first;
+ e_prev = e_first;
+
+ do {
+ loop_num_region += 1;
+ } while (((l_iter = BM_vert_step_fan_loop(l_iter, &e_prev)) != l_first) && (l_iter != NULL));
+
+ return (loop_num == loop_num_region);
+}
+
+#define LOOP_VISIT _FLAG_WALK
+#define EDGE_VISIT _FLAG_WALK
+
+static int bm_loop_region_count__recursive(BMEdge *e, BMVert *v)
+{
+ BMLoop *l_iter, *l_first;
+ int count = 0;
+
+ BLI_assert(!BM_ELEM_API_FLAG_TEST(e, EDGE_VISIT));
+ BM_ELEM_API_FLAG_ENABLE(e, EDGE_VISIT);
+
+ l_iter = l_first = e->l;
+ do {
+ if (l_iter->v == v) {
+ BMEdge *e_other = l_iter->prev->e;
+ if (!BM_ELEM_API_FLAG_TEST(l_iter, LOOP_VISIT)) {
+ BM_ELEM_API_FLAG_ENABLE(l_iter, LOOP_VISIT);
+ count += 1;
+ }
+ if (!BM_ELEM_API_FLAG_TEST(e_other, EDGE_VISIT)) {
+ count += bm_loop_region_count__recursive(e_other, v);
+ }
+ }
+ else if (l_iter->next->v == v) {
+ BMEdge *e_other = l_iter->next->e;
+ if (!BM_ELEM_API_FLAG_TEST(l_iter->next, LOOP_VISIT)) {
+ BM_ELEM_API_FLAG_ENABLE(l_iter->next, LOOP_VISIT);
+ count += 1;
+ }
+ if (!BM_ELEM_API_FLAG_TEST(e_other, EDGE_VISIT)) {
+ count += bm_loop_region_count__recursive(e_other, v);
+ }
}
else {
- l = l->radial_next;
+ BLI_assert(0);
}
- }
+ } while ((l_iter = l_iter->radial_next) != l_first);
- if (count < len) {
- /* vert shared by multiple regions */
- return false;
+ return count;
+}
+
+static int bm_loop_region_count__clear(BMLoop *l)
+{
+ int count = 0;
+ BMEdge *e_iter, *e_first;
+
+ /* clear flags */
+ e_iter = e_first = l->e;
+ do {
+ BM_ELEM_API_FLAG_DISABLE(e_iter, EDGE_VISIT);
+ if (e_iter->l) {
+ BMLoop *l_iter, *l_first;
+ l_iter = l_first = e_iter->l;
+ do {
+ if (l_iter->v == l->v) {
+ BM_ELEM_API_FLAG_DISABLE(l_iter, LOOP_VISIT);
+ count += 1;
+ }
+ } while ((l_iter = l_iter->radial_next) != l_first);
+ }
+ } while ((e_iter = BM_DISK_EDGE_NEXT(e_iter, l->v)) != e_first);
+
+ return count;
+}
+
+/**
+ * The number of loops connected to this loop (not including disconnected regions).
+ */
+int BM_loop_region_loops_count_ex(BMLoop *l, int *r_loop_total)
+{
+ const int count = bm_loop_region_count__recursive(l->e, l->v);
+ const int count_total = bm_loop_region_count__clear(l);
+ if (r_loop_total) {
+ *r_loop_total = count_total;
}
+ return count;
+}
+
+#undef LOOP_VISIT
+#undef EDGE_VISIT
+int BM_loop_region_loops_count(BMLoop *l)
+{
+ return BM_loop_region_loops_count_ex(l, NULL);
+}
+
+/**
+ * A version of #BM_vert_is_manifold
+ * which only checks if we're connected to multiple isolated regions.
+ */
+bool BM_vert_is_manifold_region(const BMVert *v)
+{
+ BMLoop *l_first = BM_vert_find_first_loop((BMVert *)v);
+ if (l_first) {
+ int count, count_total;
+ count = BM_loop_region_loops_count_ex(l_first, &count_total);
+ return (count == count_total);
+ }
return true;
}
@@ -851,6 +1071,53 @@ bool BM_edge_is_convex(const BMEdge *e)
return true;
}
+/**
+ * \return true when loop customdata is contiguous.
+ */
+bool BM_edge_is_contiguous_loop_cd(
+ const BMEdge *e,
+ const int cd_loop_type, const int cd_loop_offset)
+{
+ BLI_assert(cd_loop_offset != -1);
+
+ if (e->l && e->l->radial_next != e->l) {
+ const BMLoop *l_base_v1 = e->l;
+ const BMLoop *l_base_v2 = e->l->next;
+ const void *l_base_cd_v1 = BM_ELEM_CD_GET_VOID_P(l_base_v1, cd_loop_offset);
+ const void *l_base_cd_v2 = BM_ELEM_CD_GET_VOID_P(l_base_v2, cd_loop_offset);
+ const BMLoop *l_iter = e->l->radial_next;
+ do {
+ const BMLoop *l_iter_v1;
+ const BMLoop *l_iter_v2;
+ const void *l_iter_cd_v1;
+ const void *l_iter_cd_v2;
+
+ if (l_iter->v == l_base_v1->v) {
+ l_iter_v1 = l_iter;
+ l_iter_v2 = l_iter->next;
+ }
+ else {
+ l_iter_v1 = l_iter->next;
+ l_iter_v2 = l_iter;
+ }
+ BLI_assert((l_iter_v1->v == l_base_v1->v) &&
+ (l_iter_v2->v == l_base_v2->v));
+
+ l_iter_cd_v1 = BM_ELEM_CD_GET_VOID_P(l_iter_v1, cd_loop_offset);
+ l_iter_cd_v2 = BM_ELEM_CD_GET_VOID_P(l_iter_v2, cd_loop_offset);
+
+
+ if ((CustomData_data_equals(cd_loop_type, l_base_cd_v1, l_iter_cd_v1) == 0) ||
+ (CustomData_data_equals(cd_loop_type, l_base_cd_v2, l_iter_cd_v2) == 0))
+ {
+ return false;
+ }
+
+ } while ((l_iter = l_iter->radial_next) != e->l);
+ }
+ return true;
+}
+
bool BM_vert_is_boundary(const BMVert *v)
{
if (v->e) {
@@ -1096,8 +1363,9 @@ BMLoop *BM_face_edge_share_loop(BMFace *f, BMEdge *e)
* \note This is in fact quite a simple check, mainly include this function so the intent is more obvious.
* We know these 2 verts will _always_ make up the loops edge
*/
-void BM_edge_ordered_verts_ex(const BMEdge *edge, BMVert **r_v1, BMVert **r_v2,
- const BMLoop *edge_loop)
+void BM_edge_ordered_verts_ex(
+ const BMEdge *edge, BMVert **r_v1, BMVert **r_v2,
+ const BMLoop *edge_loop)
{
BLI_assert(edge_loop->e == edge);
(void)edge; /* quiet warning in release build */
@@ -1111,6 +1379,46 @@ void BM_edge_ordered_verts(const BMEdge *edge, BMVert **r_v1, BMVert **r_v2)
}
/**
+ * \return The previous loop, over \a eps_sq distance from \a l (or \a NULL if l_stop is reached).
+ */
+BMLoop *BM_loop_find_prev_nodouble(BMLoop *l, BMLoop *l_stop, const float eps_sq)
+{
+ BMLoop *l_step = l->prev;
+
+ BLI_assert(!ELEM(l_stop, NULL, l));
+
+ while (UNLIKELY(len_squared_v3v3(l->v->co, l_step->v->co) < eps_sq)) {
+ l_step = l_step->prev;
+ BLI_assert(l_step != l);
+ if (UNLIKELY(l_step == l_stop)) {
+ return NULL;
+ }
+ }
+
+ return l_step;
+}
+
+/**
+ * \return The next loop, over \a eps_sq distance from \a l (or \a NULL if l_stop is reached).
+ */
+BMLoop *BM_loop_find_next_nodouble(BMLoop *l, BMLoop *l_stop, const float eps_sq)
+{
+ BMLoop *l_step = l->next;
+
+ BLI_assert(!ELEM(l_stop, NULL, l));
+
+ while (UNLIKELY(len_squared_v3v3(l->v->co, l_step->v->co) < eps_sq)) {
+ l_step = l_step->next;
+ BLI_assert(l_step != l);
+ if (UNLIKELY(l_step == l_stop)) {
+ return NULL;
+ }
+ }
+
+ return l_step;
+}
+
+/**
* Check if the loop is convex or concave
* (depends on face normal)
*/
@@ -1132,7 +1440,7 @@ bool BM_loop_is_convex(const BMLoop *l)
*
* \return angle in radians
*/
-float BM_loop_calc_face_angle(BMLoop *l)
+float BM_loop_calc_face_angle(const BMLoop *l)
{
return angle_v3v3v3(l->prev->v->co,
l->v->co,
@@ -1147,7 +1455,7 @@ float BM_loop_calc_face_angle(BMLoop *l)
* \param l The loop to calculate the normal at
* \param r_normal Resulting normal
*/
-void BM_loop_calc_face_normal(BMLoop *l, float r_normal[3])
+void BM_loop_calc_face_normal(const BMLoop *l, float r_normal[3])
{
if (normal_tri_v3(r_normal,
l->prev->v->co,
@@ -1169,7 +1477,7 @@ void BM_loop_calc_face_normal(BMLoop *l, float r_normal[3])
* \param l The loop to calculate the direction at
* \param r_dir Resulting direction
*/
-void BM_loop_calc_face_direction(BMLoop *l, float r_dir[3])
+void BM_loop_calc_face_direction(const BMLoop *l, float r_dir[3])
{
float v_prev[3];
float v_next[3];
@@ -1193,7 +1501,7 @@ void BM_loop_calc_face_direction(BMLoop *l, float r_dir[3])
* \param l The loop to calculate the tangent at
* \param r_tangent Resulting tangent
*/
-void BM_loop_calc_face_tangent(BMLoop *l, float r_tangent[3])
+void BM_loop_calc_face_tangent(const BMLoop *l, float r_tangent[3])
{
float v_prev[3];
float v_next[3];
@@ -1305,7 +1613,7 @@ void BM_edge_calc_face_tangent(const BMEdge *e, const BMLoop *e_loop, float r_ta
*
* \returns the angle in radians
*/
-float BM_vert_calc_edge_angle(BMVert *v)
+float BM_vert_calc_edge_angle_ex(const BMVert *v, const float fallback)
{
BMEdge *e1, *e2;
@@ -1323,22 +1631,27 @@ float BM_vert_calc_edge_angle(BMVert *v)
return (float)M_PI - angle_v3v3v3(v1->co, v->co, v2->co);
}
else {
- return DEG2RADF(90.0f);
+ return fallback;
}
}
+float BM_vert_calc_edge_angle(const BMVert *v)
+{
+ return BM_vert_calc_edge_angle_ex(v, DEG2RADF(90.0f));
+}
+
/**
* \note this isn't optimal to run on an array of verts,
* see 'solidify_add_thickness' for a function which runs on an array.
*/
-float BM_vert_calc_shell_factor(BMVert *v)
+float BM_vert_calc_shell_factor(const BMVert *v)
{
BMIter iter;
BMLoop *l;
float accum_shell = 0.0f;
float accum_angle = 0.0f;
- BM_ITER_ELEM (l, &iter, v, BM_LOOPS_OF_VERT) {
+ BM_ITER_ELEM (l, &iter, (BMVert *)v, BM_LOOPS_OF_VERT) {
const float face_angle = BM_loop_calc_face_angle(l);
accum_shell += shell_v3v3_normalized_to_dist(v->no, l->f->no) * face_angle;
accum_angle += face_angle;
@@ -1353,18 +1666,18 @@ float BM_vert_calc_shell_factor(BMVert *v)
}
/* alternate version of #BM_vert_calc_shell_factor which only
* uses 'hflag' faces, but falls back to all if none found. */
-float BM_vert_calc_shell_factor_ex(BMVert *v, const char hflag)
+float BM_vert_calc_shell_factor_ex(const BMVert *v, const float no[3], const char hflag)
{
BMIter iter;
- BMLoop *l;
+ const BMLoop *l;
float accum_shell = 0.0f;
float accum_angle = 0.0f;
int tot_sel = 0, tot = 0;
- BM_ITER_ELEM (l, &iter, v, BM_LOOPS_OF_VERT) {
+ BM_ITER_ELEM (l, &iter, (BMVert *)v, BM_LOOPS_OF_VERT) {
if (BM_elem_flag_test(l->f, hflag)) { /* <-- main difference to BM_vert_calc_shell_factor! */
const float face_angle = BM_loop_calc_face_angle(l);
- accum_shell += shell_v3v3_normalized_to_dist(v->no, l->f->no) * face_angle;
+ accum_shell += shell_v3v3_normalized_to_dist(no, l->f->no) * face_angle;
accum_angle += face_angle;
tot_sel++;
}
@@ -1390,15 +1703,15 @@ float BM_vert_calc_shell_factor_ex(BMVert *v, const char hflag)
* \note quite an obscure function.
* used in bmesh operators that have a relative scale options,
*/
-float BM_vert_calc_mean_tagged_edge_length(BMVert *v)
+float BM_vert_calc_mean_tagged_edge_length(const BMVert *v)
{
BMIter iter;
BMEdge *e;
int tot;
float length = 0.0f;
- BM_ITER_ELEM_INDEX (e, &iter, v, BM_EDGES_OF_VERT, tot) {
- BMVert *v_other = BM_edge_other_vert(e, v);
+ BM_ITER_ELEM_INDEX (e, &iter, (BMVert *)v, BM_EDGES_OF_VERT, tot) {
+ const BMVert *v_other = BM_edge_other_vert(e, v);
if (BM_elem_flag_test(v_other, BM_ELEM_TAG)) {
length += BM_edge_calc_length(e);
}
@@ -1544,85 +1857,59 @@ BMEdge *BM_edge_find_double(BMEdge *e)
*/
bool BM_face_exists(BMVert **varr, int len, BMFace **r_existface)
{
- BMVert *v_search = varr[0]; /* we can search any of the verts in the array */
- BMIter liter;
- BMLoop *l_search;
-
-
-#if 0
- BM_ITER_ELEM (f, &viter, v_search, BM_FACES_OF_VERT) {
- if (f->len == len) {
- if (BM_verts_in_face(f, varr, len)) {
- if (r_existface) {
- *r_existface = f;
- }
- return true;
- }
- }
- }
-
- if (r_existface) {
- *r_existface = NULL;
- }
- return false;
-
-#else
-
- /* faster to do the flagging once, and inline */
- bool is_init = false;
- bool is_found = false;
- int i;
-
-
- BM_ITER_ELEM (l_search, &liter, v_search, BM_LOOPS_OF_VERT) {
- if (l_search->f->len == len) {
- if (is_init == false) {
- is_init = true;
- for (i = 0; i < len; i++) {
- BLI_assert(!BM_ELEM_API_FLAG_TEST(varr[i], _FLAG_OVERLAP));
- BM_ELEM_API_FLAG_ENABLE(varr[i], _FLAG_OVERLAP);
- }
- }
-
- is_found = true;
-
- {
- BMLoop *l_iter;
+ if (varr[0]->e) {
+ BMEdge *e_iter, *e_first;
+ e_iter = e_first = varr[0]->e;
- /* skip ourselves */
- l_iter = l_search->next;
+ /* would normally use BM_LOOPS_OF_VERT, but this runs so often,
+ * its faster to iterate on the data directly */
+ do {
+ if (e_iter->l) {
+ BMLoop *l_iter_radial, *l_first_radial;
+ l_iter_radial = l_first_radial = e_iter->l;
do {
- if (!BM_ELEM_API_FLAG_TEST(l_iter->v, _FLAG_OVERLAP)) {
- is_found = false;
- break;
+ if ((l_iter_radial->v == varr[0]) &&
+ (l_iter_radial->f->len == len))
+ {
+ /* the fist 2 verts match, now check the remaining (len - 2) faces do too
+ * winding isn't known, so check in both directions */
+ int i_walk = 2;
+
+ if (l_iter_radial->next->v == varr[1]) {
+ BMLoop *l_walk = l_iter_radial->next->next;
+ do {
+ if (l_walk->v != varr[i_walk]) {
+ break;
+ }
+ } while ((l_walk = l_walk->next), ++i_walk != len);
+ }
+ else if (l_iter_radial->prev->v == varr[1]) {
+ BMLoop *l_walk = l_iter_radial->prev->prev;
+ do {
+ if (l_walk->v != varr[i_walk]) {
+ break;
+ }
+ } while ((l_walk = l_walk->prev), ++i_walk != len);
+ }
+
+ if (i_walk == len) {
+ if (r_existface) {
+ *r_existface = l_iter_radial->f;
+ }
+ return true;
+ }
}
- } while ((l_iter = l_iter->next) != l_search);
- }
+ } while ((l_iter_radial = l_iter_radial->radial_next) != l_first_radial);
- if (is_found) {
- if (r_existface) {
- *r_existface = l_search->f;
- }
- break;
}
- }
- }
-
- if (is_found == false) {
- if (r_existface) {
- *r_existface = NULL;
- }
+ } while ((e_iter = BM_DISK_EDGE_NEXT(e_iter, varr[0])) != e_first);
}
- if (is_init == true) {
- for (i = 0; i < len; i++) {
- BM_ELEM_API_FLAG_DISABLE(varr[i], _FLAG_OVERLAP);
- }
+ if (r_existface) {
+ *r_existface = NULL;
}
-
- return is_found;
-#endif
+ return false;
}
@@ -1717,8 +2004,8 @@ bool BM_face_exists_multi(BMVert **varr, BMEdge **earr, int len)
if (/* non-boundary edge */
BM_elem_flag_test(e, BM_ELEM_INTERNAL_TAG) == false &&
/* ...using boundary verts */
- BM_elem_flag_test(e->v1, BM_ELEM_INTERNAL_TAG) == true &&
- BM_elem_flag_test(e->v2, BM_ELEM_INTERNAL_TAG) == true)
+ BM_elem_flag_test(e->v1, BM_ELEM_INTERNAL_TAG) &&
+ BM_elem_flag_test(e->v2, BM_ELEM_INTERNAL_TAG))
{
int tot_face_tag = 0;
BM_ITER_ELEM (f, &fiter, e, BM_FACES_OF_EDGE) {
@@ -1777,7 +2064,7 @@ bool BM_face_exists_multi_edge(BMEdge **earr, int len)
*
* \note The face may contain other verts \b not in \a varr.
*
- * \note Its possible there are more then one overlapping faces,
+ * \note Its possible there are more than one overlapping faces,
* in this case the first one found will be assigned to \a r_f_overlap.
*
* \param varr Array of unordered verts.
@@ -1810,7 +2097,7 @@ bool BM_face_exists_overlap(BMVert **varr, const int len, BMFace **r_f_overlap)
for (i = 0; i < len; i++) {
BM_ITER_ELEM (f, &viter, varr[i], BM_FACES_OF_VERT) {
if (BM_ELEM_API_FLAG_TEST(f, _FLAG_OVERLAP) == 0) {
- if (len <= BM_verts_in_face_count(f, varr, len)) {
+ if (len <= BM_verts_in_face_count(varr, len, f)) {
if (r_f_overlap)
*r_f_overlap = f;
@@ -2061,9 +2348,10 @@ float BM_mesh_calc_volume(BMesh *bm, bool is_signed)
* (having both set is supported too).
* \return The number of groups found.
*/
-int BM_mesh_calc_face_groups(BMesh *bm, int *r_groups_array, int (**r_group_index)[2],
- BMElemFilterFunc filter_fn, void *user_data,
- const char hflag_test, const char htype_step)
+int BM_mesh_calc_face_groups(
+ BMesh *bm, int *r_groups_array, int (**r_group_index)[2],
+ BMElemFilterFunc filter_fn, void *user_data,
+ const char hflag_test, const char htype_step)
{
#ifdef DEBUG
int group_index_len = 1;
@@ -2128,6 +2416,7 @@ int BM_mesh_calc_face_groups(BMesh *bm, int *r_groups_array, int (**r_group_inde
}
BLI_assert(ok == true);
+ UNUSED_VARS_NDEBUG(ok);
/* manage arrays */
if (group_index_len == group_curr) {
@@ -2217,9 +2506,10 @@ int BM_mesh_calc_face_groups(BMesh *bm, int *r_groups_array, int (**r_group_inde
* \note Unlike #BM_mesh_calc_face_groups there is no 'htype_step' argument,
* since we always walk over verts.
*/
-int BM_mesh_calc_edge_groups(BMesh *bm, int *r_groups_array, int (**r_group_index)[2],
- BMElemFilterFunc filter_fn, void *user_data,
- const char hflag_test)
+int BM_mesh_calc_edge_groups(
+ BMesh *bm, int *r_groups_array, int (**r_group_index)[2],
+ BMElemFilterFunc filter_fn, void *user_data,
+ const char hflag_test)
{
#ifdef DEBUG
int group_index_len = 1;
@@ -2244,7 +2534,7 @@ int BM_mesh_calc_edge_groups(BMesh *bm, int *r_groups_array, int (**r_group_inde
BMEdge *e;
int i;
- STACK_INIT(group_array, bm->totface);
+ STACK_INIT(group_array, bm->totedge);
/* init the array */
BM_ITER_MESH_INDEX (e, &iter, bm, BM_EDGES_OF_MESH, i) {
@@ -2282,6 +2572,7 @@ int BM_mesh_calc_edge_groups(BMesh *bm, int *r_groups_array, int (**r_group_inde
}
BLI_assert(ok == true);
+ UNUSED_VARS_NDEBUG(ok);
/* manage arrays */
if (group_index_len == group_curr) {
@@ -2347,6 +2638,9 @@ float bmesh_subd_falloff_calc(const int falloff, float val)
break;
case SUBD_FALLOFF_LIN:
break;
+ case SUBD_FALLOFF_INVSQUARE:
+ val = val * (2.0f - val);
+ break;
default:
BLI_assert(0);
break;
diff --git a/source/blender/bmesh/intern/bmesh_queries.h b/source/blender/bmesh/intern/bmesh_queries.h
index 0d47633dc73..2b18a5c8641 100644
--- a/source/blender/bmesh/intern/bmesh_queries.h
+++ b/source/blender/bmesh/intern/bmesh_queries.h
@@ -27,18 +27,18 @@
* \ingroup bmesh
*/
-bool BM_vert_in_face(BMFace *f, BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-int BM_verts_in_face_count(BMFace *f, BMVert **varr, int len) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-bool BM_verts_in_face(BMFace *f, BMVert **varr, int len) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+bool BM_vert_in_face(BMVert *v, BMFace *f) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+int BM_verts_in_face_count(BMVert **varr, int len, BMFace *f) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+bool BM_verts_in_face(BMVert **varr, int len, BMFace *f) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-bool BM_edge_in_face(BMEdge *e, BMFace *f) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+bool BM_edge_in_face(const BMEdge *e, const BMFace *f) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
BLI_INLINE bool BM_edge_in_loop(const BMEdge *e, const BMLoop *l) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
BLI_INLINE bool BM_vert_in_edge(const BMEdge *e, const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
BLI_INLINE bool BM_verts_in_edge(const BMVert *v1, const BMVert *v2, const BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-float BM_edge_calc_length(BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-float BM_edge_calc_length_squared(BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+float BM_edge_calc_length(const BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+float BM_edge_calc_length_squared(const BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
bool BM_edge_face_pair(BMEdge *e, BMFace **r_fa, BMFace **r_fb) ATTR_NONNULL();
bool BM_edge_loop_pair(BMEdge *e, BMLoop **r_la, BMLoop **r_lb) ATTR_NONNULL();
BLI_INLINE BMVert *BM_edge_other_vert(BMEdge *e, const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
@@ -52,6 +52,9 @@ BMLoop *BM_vert_find_first_loop(BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(
bool BM_vert_pair_share_face_check(
BMVert *v_a, BMVert *v_b) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+bool BM_vert_pair_share_face_check_cb(
+ BMVert *v_a, BMVert *v_b,
+ bool (*test_fn)(BMFace *f, void *user_data), void *user_data) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1, 2, 3);
BMFace *BM_vert_pair_share_face_by_len(
BMVert *v_a, BMVert *v_b,
BMLoop **r_l_a, BMLoop **r_l_b,
@@ -61,30 +64,57 @@ BMFace *BM_vert_pair_share_face_by_angle(
BMLoop **r_l_a, BMLoop **r_l_b,
const bool allow_adjacent) ATTR_NONNULL();
-int BM_vert_edge_count_nonwire(BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-int BM_vert_edge_count(BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-int BM_edge_face_count(BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-int BM_vert_face_count(BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+BMFace *BM_edge_pair_share_face_by_len(
+ BMEdge *e_a, BMEdge *e_b,
+ BMLoop **r_l_a, BMLoop **r_l_b,
+ const bool allow_adjacent) ATTR_NONNULL();
+
+int BM_vert_edge_count_nonwire(const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+#define BM_vert_edge_count_is_equal(v, n) (BM_vert_edge_count_ex(v, (n) + 1) == n)
+#define BM_vert_edge_count_is_over(v, n) (BM_vert_edge_count_ex(v, (n) + 1) == (n) + 1)
+int BM_vert_edge_count_ex(const BMVert *v, const int count_max) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+int BM_vert_edge_count(const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+#define BM_edge_face_count_is_equal(e, n) (BM_edge_face_count_ex(e, (n) + 1) == n)
+#define BM_edge_face_count_is_over(e, n) (BM_edge_face_count_ex(e, (n) + 1) == (n) + 1)
+int BM_edge_face_count_ex(const BMEdge *e, const int count_max) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+int BM_edge_face_count(const BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+#define BM_vert_face_count_is_equal(v, n) (BM_vert_face_count_ex(v, (n) + 1) == n)
+#define BM_vert_face_count_is_over(v, n) (BM_vert_face_count_ex(v, (n) + 1) == (n) + 1)
+int BM_vert_face_count_ex(const BMVert *v, int count_max) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+int BM_vert_face_count(const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
BMEdge *BM_vert_other_disk_edge(BMVert *v, BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-bool BM_vert_is_edge_pair(BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+bool BM_vert_is_edge_pair(const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+bool BM_vert_face_check(BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
bool BM_vert_is_wire(const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
BLI_INLINE bool BM_edge_is_wire(const BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
bool BM_vert_is_manifold(const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+bool BM_vert_is_manifold_region(const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
BLI_INLINE bool BM_edge_is_manifold(const BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
bool BM_vert_is_boundary(const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
BLI_INLINE bool BM_edge_is_boundary(const BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
BLI_INLINE bool BM_edge_is_contiguous(const BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
bool BM_edge_is_convex(const BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+bool BM_edge_is_contiguous_loop_cd(
+ const BMEdge *e,
+ const int cd_loop_type, const int cd_loop_offset)
+ ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+int BM_loop_region_loops_count_ex(BMLoop *l, int *r_loop_total) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1);
+int BM_loop_region_loops_count(BMLoop *l) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1);
bool BM_loop_is_convex(const BMLoop *l) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
BLI_INLINE bool BM_loop_is_adjacent(const BMLoop *l_a, const BMLoop *l_b) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+float BM_loop_point_side_of_loop_test(const BMLoop *l, const float co[3]) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+float BM_loop_point_side_of_edge_test(const BMLoop *l, const float co[3]) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+
+BMLoop *BM_loop_find_prev_nodouble(BMLoop *l, BMLoop *l_stop, const float eps_sq);
+BMLoop *BM_loop_find_next_nodouble(BMLoop *l, BMLoop *l_stop, const float eps_sq);
-float BM_loop_calc_face_angle(BMLoop *l) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-void BM_loop_calc_face_normal(BMLoop *l, float r_normal[3]) ATTR_NONNULL();
-void BM_loop_calc_face_direction(BMLoop *l, float r_normal[3]);
-void BM_loop_calc_face_tangent(BMLoop *l, float r_tangent[3]);
+float BM_loop_calc_face_angle(const BMLoop *l) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+void BM_loop_calc_face_normal(const BMLoop *l, float r_normal[3]) ATTR_NONNULL();
+void BM_loop_calc_face_direction(const BMLoop *l, float r_normal[3]);
+void BM_loop_calc_face_tangent(const BMLoop *l, float r_tangent[3]);
float BM_edge_calc_face_angle_ex(const BMEdge *e, const float fallback) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
float BM_edge_calc_face_angle(const BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
@@ -92,10 +122,11 @@ float BM_edge_calc_face_angle_signed_ex(const BMEdge *e, const float fallback)
float BM_edge_calc_face_angle_signed(const BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
void BM_edge_calc_face_tangent(const BMEdge *e, const BMLoop *e_loop, float r_tangent[3]) ATTR_NONNULL();
-float BM_vert_calc_edge_angle(BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-float BM_vert_calc_shell_factor(BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-float BM_vert_calc_shell_factor_ex(BMVert *v, const char hflag) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-float BM_vert_calc_mean_tagged_edge_length(BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+float BM_vert_calc_edge_angle(const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+float BM_vert_calc_edge_angle_ex(const BMVert *v, const float fallback) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+float BM_vert_calc_shell_factor(const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+float BM_vert_calc_shell_factor_ex(const BMVert *v, const float no[3], const char hflag) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+float BM_vert_calc_mean_tagged_edge_length(const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
BMLoop *BM_face_find_shortest_loop(BMFace *f) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
BMLoop *BM_face_find_longest_loop(BMFace *f) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
@@ -126,8 +157,9 @@ BMLoop *BM_face_vert_share_loop(BMFace *f, BMVert *v) ATTR_WARN_UNUSED_RESULT AT
BMLoop *BM_face_edge_share_loop(BMFace *f, BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
void BM_edge_ordered_verts(const BMEdge *edge, BMVert **r_v1, BMVert **r_v2) ATTR_NONNULL();
-void BM_edge_ordered_verts_ex(const BMEdge *edge, BMVert **r_v1, BMVert **r_v2,
- const BMLoop *edge_loop) ATTR_NONNULL();
+void BM_edge_ordered_verts_ex(
+ const BMEdge *edge, BMVert **r_v1, BMVert **r_v2,
+ const BMLoop *edge_loop) ATTR_NONNULL();
bool BM_vert_is_all_edge_flag_test(const BMVert *v, const char hflag, const bool respect_hide) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
bool BM_vert_is_all_face_flag_test(const BMVert *v, const char hflag, const bool respect_hide) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
@@ -141,12 +173,16 @@ bool BM_face_is_normal_valid(const BMFace *f) ATTR_WARN_UNUSED_RESULT ATTR_NONNU
float BM_mesh_calc_volume(BMesh *bm, bool is_signed) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-int BM_mesh_calc_face_groups(BMesh *bm, int *r_groups_array, int (**r_group_index)[2],
- BMElemFilterFunc filter_fn, void *user_data,
- const char hflag_test, const char htype_step) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1, 2, 3);
-int BM_mesh_calc_edge_groups(BMesh *bm, int *r_groups_array, int (**r_group_index)[2],
- BMElemFilterFunc filter_fn, void *user_data,
- const char hflag_test) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1, 2, 3);
+int BM_mesh_calc_face_groups(
+ BMesh *bm, int *r_groups_array, int (**r_group_index)[2],
+ BMElemFilterFunc filter_fn, void *user_data,
+ const char hflag_test, const char htype_step)
+ ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1, 2, 3);
+int BM_mesh_calc_edge_groups(
+ BMesh *bm, int *r_groups_array, int (**r_group_index)[2],
+ BMElemFilterFunc filter_fn, void *user_data,
+ const char hflag_test)
+ ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1, 2, 3);
/* not really any good place to put this */
float bmesh_subd_falloff_calc(const int falloff, float val) ATTR_WARN_UNUSED_RESULT;
diff --git a/source/blender/bmesh/intern/bmesh_queries_inline.h b/source/blender/bmesh/intern/bmesh_queries_inline.h
index 6162af46837..430ba10fb42 100644
--- a/source/blender/bmesh/intern/bmesh_queries_inline.h
+++ b/source/blender/bmesh/intern/bmesh_queries_inline.h
@@ -30,14 +30,16 @@
* Returns whether or not a given vertex is
* is part of a given edge.
*/
+ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
BLI_INLINE bool BM_vert_in_edge(const BMEdge *e, const BMVert *v)
{
return (ELEM(v, e->v1, e->v2));
}
/**
- * Returns whether or not a given edge is is part of a given loop.
+ * Returns whether or not a given edge is part of a given loop.
*/
+ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1, 2)
BLI_INLINE bool BM_edge_in_loop(const BMEdge *e, const BMLoop *l)
{
return (l->e == e || l->prev->e == e);
@@ -47,6 +49,7 @@ BLI_INLINE bool BM_edge_in_loop(const BMEdge *e, const BMLoop *l)
* Returns whether or not two vertices are in
* a given edge
*/
+ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1, 2, 3)
BLI_INLINE bool BM_verts_in_edge(const BMVert *v1, const BMVert *v2, const BMEdge *e)
{
return ((e->v1 == v1 && e->v2 == v2) ||
@@ -57,6 +60,7 @@ BLI_INLINE bool BM_verts_in_edge(const BMVert *v1, const BMVert *v2, const BMEdg
* Given a edge and one of its vertices, returns
* the other vertex.
*/
+ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1, 2)
BLI_INLINE BMVert *BM_edge_other_vert(BMEdge *e, const BMVert *v)
{
if (e->v1 == v) {
@@ -72,6 +76,7 @@ BLI_INLINE BMVert *BM_edge_other_vert(BMEdge *e, const BMVert *v)
* Tests whether or not the edge is part of a wire.
* (ie: has no faces attached to it)
*/
+ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
BLI_INLINE bool BM_edge_is_wire(const BMEdge *e)
{
return (e->l == NULL);
@@ -83,6 +88,7 @@ BLI_INLINE bool BM_edge_is_wire(const BMEdge *e)
*/
#if 1 /* fast path for checking manifold */
+ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
BLI_INLINE bool BM_edge_is_manifold(const BMEdge *e)
{
const BMLoop *l = e->l;
@@ -100,6 +106,7 @@ BLI_INLINE int BM_edge_is_manifold(BMEdge *e)
* Tests that the edge is manifold and
* that both its faces point the same way.
*/
+ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
BLI_INLINE bool BM_edge_is_contiguous(const BMEdge *e)
{
const BMLoop *l = e->l;
@@ -115,6 +122,7 @@ BLI_INLINE bool BM_edge_is_contiguous(const BMEdge *e)
*/
#if 1 /* fast path for checking boundary */
+ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
BLI_INLINE bool BM_edge_is_boundary(const BMEdge *e)
{
const BMLoop *l = e->l;
@@ -130,6 +138,7 @@ BLI_INLINE int BM_edge_is_boundary(BMEdge *e)
/**
* Tests whether one loop is next to another within the same face.
*/
+ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1, 2)
BLI_INLINE bool BM_loop_is_adjacent(const BMLoop *l_a, const BMLoop *l_b)
{
BLI_assert(l_a->f == l_b->f);
@@ -140,6 +149,7 @@ BLI_INLINE bool BM_loop_is_adjacent(const BMLoop *l_a, const BMLoop *l_b)
/**
* Check if we have a single wire edge user.
*/
+ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
BLI_INLINE bool BM_vert_is_wire_endpoint(const BMVert *v)
{
const BMEdge *e = v->e;
diff --git a/source/blender/bmesh/intern/bmesh_structure.c b/source/blender/bmesh/intern/bmesh_structure.c
index 3e8002c0192..cb302139a4c 100644
--- a/source/blender/bmesh/intern/bmesh_structure.c
+++ b/source/blender/bmesh/intern/bmesh_structure.c
@@ -40,19 +40,56 @@
* MISC utility functions.
*/
-bool bmesh_edge_swapverts(BMEdge *e, BMVert *v_orig, BMVert *v_new)
+void bmesh_disk_vert_swap(BMEdge *e, BMVert *v_dst, BMVert *v_src)
{
- if (e->v1 == v_orig) {
- e->v1 = v_new;
+ if (e->v1 == v_src) {
+ e->v1 = v_dst;
e->v1_disk_link.next = e->v1_disk_link.prev = NULL;
- return true;
}
- else if (e->v2 == v_orig) {
- e->v2 = v_new;
+ else if (e->v2 == v_src) {
+ e->v2 = v_dst;
e->v2_disk_link.next = e->v2_disk_link.prev = NULL;
- return true;
}
- return false;
+ else {
+ BLI_assert(0);
+ }
+}
+
+/**
+ * Handles all connected data, use with care.
+ *
+ * Assumes caller has setup correct state before the swap is done.
+ */
+void bmesh_edge_vert_swap(BMEdge *e, BMVert *v_dst, BMVert *v_src)
+{
+ /* swap out loops */
+ if (e->l) {
+ BMLoop *l_iter, *l_first;
+ l_iter = l_first = e->l;
+ do {
+ if (l_iter->v == v_src) {
+ l_iter->v = v_dst;
+ }
+ else if (l_iter->next->v == v_src) {
+ l_iter->next->v = v_dst;
+ }
+ else {
+ BLI_assert(l_iter->prev->v != v_src);
+ }
+ } while ((l_iter = l_iter->radial_next) != l_first);
+ }
+
+ /* swap out edges */
+ bmesh_disk_vert_replace(e, v_dst, v_src);
+}
+
+void bmesh_disk_vert_replace(BMEdge *e, BMVert *v_dst, BMVert *v_src)
+{
+ BLI_assert(e->v1 == v_src || e->v2 == v_src);
+ bmesh_disk_edge_remove(e, v_src); /* remove e from tv's disk cycle */
+ bmesh_disk_vert_swap(e, v_dst, v_src); /* swap out tv for v_new in e */
+ bmesh_disk_edge_append(e, v_dst); /* add e to v_dst's disk cycle */
+ BLI_assert(e->v1 != e->v2);
}
/**
@@ -88,6 +125,7 @@ bool bmesh_edge_swapverts(BMEdge *e, BMVert *v_orig, BMVert *v_new)
* the disk cycle has no problems dealing with non-manifold conditions involving faces.
*
* Functions relating to this cycle:
+ * - #bmesh_disk_vert_replace
* - #bmesh_disk_edge_append
* - #bmesh_disk_edge_remove
* - #bmesh_disk_edge_next
@@ -206,13 +244,29 @@ int bmesh_disk_count(const BMVert *v)
return count;
}
+int bmesh_disk_count_ex(const BMVert *v, const int count_max)
+{
+ int count = 0;
+ if (v->e) {
+ BMEdge *e_first, *e_iter;
+ e_iter = e_first = v->e;
+ do {
+ count++;
+ if (count == count_max) {
+ break;
+ }
+ } while ((e_iter = bmesh_disk_edge_next(e_iter, v)) != e_first);
+ }
+ return count;
+}
+
bool bmesh_disk_validate(int len, BMEdge *e, BMVert *v)
{
BMEdge *e_iter;
if (!BM_vert_in_edge(e, v))
return false;
- if (bmesh_disk_count(v) != len || len == 0)
+ if (bmesh_disk_count_ex(v, len + 1) != len || len == 0)
return false;
e_iter = e;
@@ -236,9 +290,9 @@ bool bmesh_disk_validate(int len, BMEdge *e, BMVert *v)
int bmesh_disk_facevert_count(const BMVert *v)
{
/* is there an edge on this vert at all */
+ int count = 0;
if (v->e) {
BMEdge *e_first, *e_iter;
- int count = 0;
/* first, loop around edge */
e_first = e_iter = v->e;
@@ -247,11 +301,29 @@ int bmesh_disk_facevert_count(const BMVert *v)
count += bmesh_radial_facevert_count(e_iter->l, v);
}
} while ((e_iter = bmesh_disk_edge_next(e_iter, v)) != e_first);
- return count;
}
- else {
- return 0;
+ return count;
+}
+
+int bmesh_disk_facevert_count_ex(const BMVert *v, const int count_max)
+{
+ /* is there an edge on this vert at all */
+ int count = 0;
+ if (v->e) {
+ BMEdge *e_first, *e_iter;
+
+ /* first, loop around edge */
+ e_first = e_iter = v->e;
+ do {
+ if (e_iter->l) {
+ count += bmesh_radial_facevert_count_ex(e_iter->l, v, count_max - count);
+ if (count == count_max) {
+ break;
+ }
+ }
+ } while ((e_iter = bmesh_disk_edge_next(e_iter, v)) != e_first);
}
+ return count;
}
/**
@@ -456,6 +528,23 @@ int bmesh_radial_facevert_count(const BMLoop *l, const BMVert *v)
return count;
}
+int bmesh_radial_facevert_count_ex(const BMLoop *l, const BMVert *v, const int count_max)
+{
+ const BMLoop *l_iter;
+ int count = 0;
+ l_iter = l;
+ do {
+ if (l_iter->v == v) {
+ count++;
+ if (count == count_max) {
+ break;
+ }
+ }
+ } while ((l_iter = l_iter->radial_next) != l);
+
+ return count;
+}
+
/**
* \brief RADIAL CHECK FACE VERT
*
diff --git a/source/blender/bmesh/intern/bmesh_structure.h b/source/blender/bmesh/intern/bmesh_structure.h
index 29868194bbf..07f94796bb2 100644
--- a/source/blender/bmesh/intern/bmesh_structure.h
+++ b/source/blender/bmesh/intern/bmesh_structure.h
@@ -49,6 +49,7 @@ BLI_INLINE BMEdge *bmesh_disk_edge_next_safe(const BMEdge *e, const BMVert *v) A
BLI_INLINE BMEdge *bmesh_disk_edge_prev_safe(const BMEdge *e, const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
BLI_INLINE BMEdge *bmesh_disk_edge_next(const BMEdge *e, const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
BLI_INLINE BMEdge *bmesh_disk_edge_prev(const BMEdge *e, const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+int bmesh_disk_facevert_count_ex(const BMVert *v, const int count_max) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
int bmesh_disk_facevert_count(const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
BMEdge *bmesh_disk_faceedge_find_first(const BMEdge *e, const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
BMEdge *bmesh_disk_faceedge_find_next(const BMEdge *e, const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
@@ -60,6 +61,7 @@ void bmesh_radial_loop_remove(BMLoop *l, BMEdge *e) ATTR_NONNULL(1);
* bmesh_radial_loop_next(BMLoop *l) / prev.
* just use member access l->radial_next, l->radial_prev now */
+int bmesh_radial_facevert_count_ex(const BMLoop *l, const BMVert *v, const int count_max) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
int bmesh_radial_facevert_count(const BMLoop *l, const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
bool bmesh_radial_facevert_check(const BMLoop *l, const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
BMLoop *bmesh_radial_faceloop_find_first(const BMLoop *l, const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
@@ -68,7 +70,9 @@ BMLoop *bmesh_radial_faceloop_find_vert(const BMFace *f, const BMVert *v) ATTR_W
bool bmesh_radial_validate(int radlen, BMLoop *l) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
/* EDGE UTILITIES */
-bool bmesh_edge_swapverts(BMEdge *e, BMVert *v_orig, BMVert *v_new) ATTR_NONNULL();
+void bmesh_disk_vert_swap(BMEdge *e, BMVert *v_dst, BMVert *v_src) ATTR_NONNULL();
+void bmesh_edge_vert_swap(BMEdge *e, BMVert *v_dst, BMVert *v_src) ATTR_NONNULL();
+void bmesh_disk_vert_replace(BMEdge *e, BMVert *v_dst, BMVert *v_src) ATTR_NONNULL();
BMEdge *bmesh_disk_edge_exists(const BMVert *v1, const BMVert *v2) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
bool bmesh_disk_validate(int len, BMEdge *e, BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
diff --git a/source/blender/bmesh/intern/bmesh_structure_inline.h b/source/blender/bmesh/intern/bmesh_structure_inline.h
index 5b7e890f5ea..64292194ae7 100644
--- a/source/blender/bmesh/intern/bmesh_structure_inline.h
+++ b/source/blender/bmesh/intern/bmesh_structure_inline.h
@@ -27,6 +27,7 @@
#ifndef __BMESH_STRUCTURE_INLINE_H__
#define __BMESH_STRUCTURE_INLINE_H__
+ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1, 2)
BLI_INLINE BMDiskLink *bmesh_disk_edge_link_from_vert(const BMEdge *e, const BMVert *v)
{
BLI_assert(BM_vert_in_edge(e, v));
@@ -40,6 +41,7 @@ BLI_INLINE BMDiskLink *bmesh_disk_edge_link_from_vert(const BMEdge *e, const BMV
*
* \return Pointer to the next edge in the disk cycle for the vertex v.
*/
+ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
BLI_INLINE BMEdge *bmesh_disk_edge_next_safe(const BMEdge *e, const BMVert *v)
{
if (v == e->v1)
@@ -49,6 +51,7 @@ BLI_INLINE BMEdge *bmesh_disk_edge_next_safe(const BMEdge *e, const BMVert *v)
return NULL;
}
+ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
BLI_INLINE BMEdge *bmesh_disk_edge_prev_safe(const BMEdge *e, const BMVert *v)
{
if (v == e->v1)
@@ -58,11 +61,13 @@ BLI_INLINE BMEdge *bmesh_disk_edge_prev_safe(const BMEdge *e, const BMVert *v)
return NULL;
}
+ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1, 2)
BLI_INLINE BMEdge *bmesh_disk_edge_next(const BMEdge *e, const BMVert *v)
{
return BM_DISK_EDGE_NEXT(e, v);
}
+ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1, 2)
BLI_INLINE BMEdge *bmesh_disk_edge_prev(const BMEdge *e, const BMVert *v)
{
return BM_DISK_EDGE_PREV(e, v);
diff --git a/source/blender/bmesh/intern/bmesh_walkers.c b/source/blender/bmesh/intern/bmesh_walkers.c
index 6a5efbe70ac..d16eb572540 100644
--- a/source/blender/bmesh/intern/bmesh_walkers.c
+++ b/source/blender/bmesh/intern/bmesh_walkers.c
@@ -74,10 +74,11 @@ void *BMW_begin(BMWalker *walker, void *start)
* a given type. The elements visited are filtered
* by the bitmask 'searchmask'.
*/
-void BMW_init(BMWalker *walker, BMesh *bm, int type,
- short mask_vert, short mask_edge, short mask_face,
- BMWFlag flag,
- int layer)
+void BMW_init(
+ BMWalker *walker, BMesh *bm, int type,
+ short mask_vert, short mask_edge, short mask_face,
+ BMWFlag flag,
+ int layer)
{
memset(walker, 0, sizeof(BMWalker));
@@ -180,7 +181,7 @@ void *BMW_walk(BMWalker *walker)
* \brief Current Walker State
*
* Returns the first state from the walker state
- * worklist. This state is the the next in the
+ * worklist. This state is the next in the
* worklist for processing.
*/
void *BMW_current_state(BMWalker *walker)
diff --git a/source/blender/bmesh/intern/bmesh_walkers.h b/source/blender/bmesh/intern/bmesh_walkers.h
index d551ea9fba9..f5a801a31c3 100644
--- a/source/blender/bmesh/intern/bmesh_walkers.h
+++ b/source/blender/bmesh/intern/bmesh_walkers.h
@@ -76,10 +76,11 @@ typedef struct BMWalker {
/* initialize a walker. searchmask restricts some (not all) walkers to
* elements with a specific tool flag set. flags is specific to each walker.*/
-void BMW_init(struct BMWalker *walker, BMesh *bm, int type,
- short mask_vert, short mask_edge, short mask_face,
- BMWFlag flag,
- int layer);
+void BMW_init(
+ struct BMWalker *walker, BMesh *bm, int type,
+ short mask_vert, short mask_edge, short mask_face,
+ BMWFlag flag,
+ int layer);
void *BMW_begin(BMWalker *walker, void *start);
void *BMW_step(struct BMWalker *walker);
void BMW_end(struct BMWalker *walker);
@@ -92,6 +93,11 @@ void BMW_state_remove(BMWalker *walker);
void *BMW_walk(BMWalker *walker);
void BMW_reset(BMWalker *walker);
+#define BMW_ITER(ele, walker, data) \
+ for (BM_CHECK_TYPE_ELEM_ASSIGN(ele) = BMW_begin(walker, (BM_CHECK_TYPE_ELEM(data), data)); \
+ ele; \
+ BM_CHECK_TYPE_ELEM_ASSIGN(ele) = BMW_step(walker))
+
/*
* example of usage, walking over an island of tool flagged faces:
*
@@ -108,8 +114,10 @@ void BMW_reset(BMWalker *walker);
enum {
BMW_VERT_SHELL,
+ BMW_LOOP_SHELL,
+ BMW_LOOP_SHELL_WIRE,
BMW_FACE_SHELL,
- BMW_LOOP,
+ BMW_EDGELOOP,
BMW_FACELOOP,
BMW_EDGERING,
BMW_EDGEBOUNDARY,
diff --git a/source/blender/bmesh/intern/bmesh_walkers_impl.c b/source/blender/bmesh/intern/bmesh_walkers_impl.c
index 406dd412d6d..28c3debb93c 100644
--- a/source/blender/bmesh/intern/bmesh_walkers_impl.c
+++ b/source/blender/bmesh/intern/bmesh_walkers_impl.c
@@ -33,7 +33,6 @@
#include "BKE_customdata.h"
#include "bmesh.h"
-#include "intern/bmesh_private.h"
#include "intern/bmesh_walkers_private.h"
/* pop into stack memory (common operation) */
@@ -87,6 +86,30 @@ static bool bmw_mask_check_face(BMWalker *walker, BMFace *f)
/** \} */
+/** \name BMesh Queries (modified to check walker flags)
+ * \{ */
+
+/**
+ * Check for a wire edge, taking ignoring hidden.
+ */
+static bool bmw_edge_is_wire(const BMWalker *walker, const BMEdge *e)
+{
+ if (walker->flag & BMW_FLAG_TEST_HIDDEN) {
+ /* check if this is a wire edge, ignoring hidden faces */
+ if (BM_edge_is_wire(e)) {
+ return true;
+ }
+ else {
+ return BM_edge_is_all_face_flag_test(e, BM_ELEM_HIDDEN, false);
+ }
+ }
+ else {
+ return BM_edge_is_wire(e);
+ }
+}
+/** \} */
+
+
/** \name Shell Walker
* \{
*
@@ -224,6 +247,291 @@ static void *bmw_VertShellWalker_step(BMWalker *walker)
/** \} */
+/** \name LoopShell Walker
+ * \{
+ *
+ * Starts at any element on the mesh and walks over the 'shell' it belongs
+ * to via visiting connected loops.
+ *
+ * \note this is mainly useful to loop over a shell delimited by edges.
+ */
+static void bmw_LoopShellWalker_visitLoop(BMWalker *walker, BMLoop *l)
+{
+ BMwLoopShellWalker *shellWalk = NULL;
+
+ if (BLI_gset_haskey(walker->visit_set, l)) {
+ return;
+ }
+
+ if (!bmw_mask_check_face(walker, l->f)) {
+ return;
+ }
+
+ shellWalk = BMW_state_add(walker);
+ shellWalk->curloop = l;
+ BLI_gset_insert(walker->visit_set, l);
+}
+
+static void bmw_LoopShellWalker_begin(BMWalker *walker, void *data)
+{
+ BMIter iter;
+ BMHeader *h = data;
+
+ if (UNLIKELY(h == NULL)) {
+ return;
+ }
+
+ switch (h->htype) {
+ case BM_LOOP:
+ {
+ /* starting the walk at a vert, add all the edges
+ * to the worklist */
+ BMLoop *l = (BMLoop *)h;
+ bmw_LoopShellWalker_visitLoop(walker, l);
+ break;
+ }
+
+ case BM_VERT:
+ {
+ BMVert *v = (BMVert *)h;
+ BMLoop *l;
+ BM_ITER_ELEM (l, &iter, v, BM_LOOPS_OF_VERT) {
+ bmw_LoopShellWalker_visitLoop(walker, l);
+ }
+ break;
+ }
+ case BM_EDGE:
+ {
+ BMEdge *e = (BMEdge *)h;
+ BMLoop *l;
+ BM_ITER_ELEM (l, &iter, e, BM_LOOPS_OF_EDGE) {
+ bmw_LoopShellWalker_visitLoop(walker, l);
+ }
+ break;
+ }
+ case BM_FACE:
+ {
+ BMFace *f = (BMFace *)h;
+ BMLoop *l = BM_FACE_FIRST_LOOP(f);
+ /* walker will handle other loops within the face */
+ bmw_LoopShellWalker_visitLoop(walker, l);
+ break;
+ }
+ default:
+ BLI_assert(0);
+ }
+}
+
+static void *bmw_LoopShellWalker_yield(BMWalker *walker)
+{
+ BMwLoopShellWalker *shellWalk = BMW_current_state(walker);
+ return shellWalk->curloop;
+}
+
+static void bmw_LoopShellWalker_step_impl(BMWalker *walker, BMLoop *l)
+{
+ BMEdge *e_edj_pair[2];
+ int i;
+
+ /* seems paranoid, but one caller also walks edges */
+ BLI_assert(l->head.htype == BM_LOOP);
+
+ bmw_LoopShellWalker_visitLoop(walker, l->next);
+ bmw_LoopShellWalker_visitLoop(walker, l->prev);
+
+ e_edj_pair[0] = l->e;
+ e_edj_pair[1] = l->prev->e;
+
+ for (i = 0; i < 2; i++) {
+ BMEdge *e = e_edj_pair[i];
+ if (bmw_mask_check_edge(walker, e)) {
+ BMLoop *l_iter, *l_first;
+
+ l_iter = l_first = e->l;
+ do {
+ BMLoop *l_radial = (l_iter->v == l->v) ? l_iter : l_iter->next;
+ BLI_assert(l_radial->v == l->v);
+ if (l != l_radial) {
+ bmw_LoopShellWalker_visitLoop(walker, l_radial);
+ }
+ } while ((l_iter = l_iter->radial_next) != l_first);
+ }
+ }
+}
+
+static void *bmw_LoopShellWalker_step(BMWalker *walker)
+{
+ BMwLoopShellWalker *swalk, owalk;
+ BMLoop *l;
+
+ BMW_state_remove_r(walker, &owalk);
+ swalk = &owalk;
+
+ l = swalk->curloop;
+ bmw_LoopShellWalker_step_impl(walker, l);
+
+ return l;
+}
+
+/** \} */
+
+/** \name LoopShell & 'Wire' Walker
+ * \{
+ *
+ * Piggyback ontop of #BMwLoopShellWalker, but also walk over wire edges
+ * This isn't elegant but users expect it when selecting linked,
+ * so we can support delimiters _and_ walking over wire edges.
+ *
+ * Details:
+ * - can yield edges (as well as loops)
+ * - only step over wire edges.
+ * - verts and edges are stored in `visit_set_alt`.
+ */
+
+static void bmw_LoopShellWalker_visitEdgeWire(BMWalker *walker, BMEdge *e)
+{
+ BMwLoopShellWireWalker *shellWalk = NULL;
+
+ BLI_assert(bmw_edge_is_wire(walker, e));
+
+ if (BLI_gset_haskey(walker->visit_set_alt, e)) {
+ return;
+ }
+
+ if (!bmw_mask_check_edge(walker, e)) {
+ return;
+ }
+
+ shellWalk = BMW_state_add(walker);
+ shellWalk->curelem = (BMElem *)e;
+ BLI_gset_insert(walker->visit_set_alt, e);
+}
+
+static void bmw_LoopShellWireWalker_visitVert(BMWalker *walker, BMVert *v, const BMEdge *e_from)
+{
+ BMEdge *e;
+
+ BLI_assert(v->head.htype == BM_VERT);
+
+ if (BLI_gset_haskey(walker->visit_set_alt, v)) {
+ return;
+ }
+
+ if (!bmw_mask_check_vert(walker, v)) {
+ return;
+ }
+
+ e = v->e;
+ do {
+ if (bmw_edge_is_wire(walker, e) && (e != e_from)) {
+ BMVert *v_other;
+ BMIter iter;
+ BMLoop *l;
+
+ bmw_LoopShellWalker_visitEdgeWire(walker, e);
+
+ /* check if we step onto a non-wire vertex */
+ v_other = BM_edge_other_vert(e, v);
+ BM_ITER_ELEM (l, &iter, v_other, BM_LOOPS_OF_VERT) {
+
+ bmw_LoopShellWalker_visitLoop(walker, l);
+ }
+ }
+ } while ((e = BM_DISK_EDGE_NEXT(e, v)) != v->e);
+
+ BLI_gset_insert(walker->visit_set_alt, v);
+}
+
+static void bmw_LoopShellWireWalker_begin(BMWalker *walker, void *data)
+{
+ BMHeader *h = data;
+
+ if (UNLIKELY(h == NULL)) {
+ return;
+ }
+
+ bmw_LoopShellWalker_begin(walker, data);
+
+ switch (h->htype) {
+ case BM_LOOP:
+ {
+ BMLoop *l = (BMLoop *)h;
+ bmw_LoopShellWireWalker_visitVert(walker, l->v, NULL);
+ break;
+ }
+
+ case BM_VERT:
+ {
+ BMVert *v = (BMVert *)h;
+ if (v->e) {
+ bmw_LoopShellWireWalker_visitVert(walker, v, NULL);
+ }
+ break;
+ }
+ case BM_EDGE:
+ {
+ BMEdge *e = (BMEdge *)h;
+ if (bmw_mask_check_edge(walker, e)) {
+ bmw_LoopShellWireWalker_visitVert(walker, e->v1, NULL);
+ bmw_LoopShellWireWalker_visitVert(walker, e->v2, NULL);
+ }
+ else {
+ BMLoop *l_iter, *l_first;
+
+ l_iter = l_first = e->l;
+ do {
+ bmw_LoopShellWalker_visitLoop(walker, l_iter);
+ bmw_LoopShellWalker_visitLoop(walker, l_iter->next);
+ } while ((l_iter = l_iter->radial_next) != l_first);
+ }
+ break;
+ }
+ case BM_FACE:
+ {
+ /* wire verts will be walked over */
+ break;
+ }
+ default:
+ BLI_assert(0);
+ }
+}
+
+static void *bmw_LoopShellWireWalker_yield(BMWalker *walker)
+{
+ BMwLoopShellWireWalker *shellWalk = BMW_current_state(walker);
+ return shellWalk->curelem;
+}
+
+static void *bmw_LoopShellWireWalker_step(BMWalker *walker)
+{
+ BMwLoopShellWireWalker *swalk, owalk;
+
+ BMW_state_remove_r(walker, &owalk);
+ swalk = &owalk;
+
+ if (swalk->curelem->head.htype == BM_LOOP) {
+ BMLoop *l = (BMLoop *)swalk->curelem;
+
+ bmw_LoopShellWalker_step_impl(walker, l);
+
+ bmw_LoopShellWireWalker_visitVert(walker, l->v, NULL);
+
+ return l;
+ }
+ else {
+ BMEdge *e = (BMEdge *)swalk->curelem;
+
+ BLI_assert(e->head.htype == BM_EDGE);
+
+ bmw_LoopShellWireWalker_visitVert(walker, e->v1, e);
+ bmw_LoopShellWireWalker_visitVert(walker, e->v2, e);
+
+ return e;
+ }
+}
+
+/** \} */
+
/** \name FaceShell Walker
* \{
@@ -544,9 +852,9 @@ static bool bm_edge_is_single(BMEdge *e)
(BM_edge_is_boundary(e->l->next->e) || BM_edge_is_boundary(e->l->prev->e)));
}
-static void bmw_LoopWalker_begin(BMWalker *walker, void *data)
+static void bmw_EdgeLoopWalker_begin(BMWalker *walker, void *data)
{
- BMwLoopWalker *lwalk = NULL, owalk, *owalk_pt;
+ BMwEdgeLoopWalker *lwalk = NULL, owalk, *owalk_pt;
BMEdge *e = data;
BMVert *v;
const int vert_edge_count[2] = {
@@ -594,7 +902,7 @@ static void bmw_LoopWalker_begin(BMWalker *walker, void *data)
/* rewind */
while ((owalk_pt = BMW_current_state(walker))) {
- owalk = *((BMwLoopWalker *)owalk_pt);
+ owalk = *((BMwEdgeLoopWalker *)owalk_pt);
BMW_walk(walker);
}
@@ -607,16 +915,16 @@ static void bmw_LoopWalker_begin(BMWalker *walker, void *data)
BLI_gset_insert(walker->visit_set, owalk.cur);
}
-static void *bmw_LoopWalker_yield(BMWalker *walker)
+static void *bmw_EdgeLoopWalker_yield(BMWalker *walker)
{
- BMwLoopWalker *lwalk = BMW_current_state(walker);
+ BMwEdgeLoopWalker *lwalk = BMW_current_state(walker);
return lwalk->cur;
}
-static void *bmw_LoopWalker_step(BMWalker *walker)
+static void *bmw_EdgeLoopWalker_step(BMWalker *walker)
{
- BMwLoopWalker *lwalk, owalk;
+ BMwEdgeLoopWalker *lwalk, owalk;
BMEdge *e, *nexte = NULL;
BMLoop *l;
BMVert *v;
@@ -738,7 +1046,7 @@ static void *bmw_LoopWalker_step(BMWalker *walker)
(owalk.is_single == false && vert_edge_tot > 2) ||
/* initial edge was a boundary, so is this edge and vertex is only apart of this face
- * this lets us walk over the the boundary of an ngon which is handy */
+ * this lets us walk over the boundary of an ngon which is handy */
(owalk.is_single == true && vert_edge_tot == 2 && BM_edge_is_boundary(e)))
{
/* find next boundary edge in the fan */
@@ -936,7 +1244,7 @@ static void *bmw_FaceLoopWalker_step(BMWalker *walker)
*
* Starts at a tool-flagged edge and walks over the edge ring
* Conditions for starting and stepping the edge ring have been
- * tuned in an attempt to match the edge rings built by EditMesh
+ * tuned to match behavior users expect (dating back to v2.4x).
*/
static void bmw_EdgeringWalker_begin(BMWalker *walker, void *data)
{
@@ -1180,17 +1488,16 @@ static void *bmw_UVEdgeWalker_yield(BMWalker *walker)
static void *bmw_UVEdgeWalker_step(BMWalker *walker)
{
const int type = walker->bm->ldata.layers[walker->layer].type;
+ const int offset = walker->bm->ldata.layers[walker->layer].offset;
+
BMwUVEdgeWalker *lwalk, owalk;
- BMLoop *l, *l2, *l3, *nl, *cl;
- BMIter liter;
- void *d1, *d2;
- int i, j, rlen;
+ BMLoop *l;
+ int i;
BMW_state_remove_r(walker, &owalk);
lwalk = &owalk;
l = lwalk->l;
- nl = l->next;
if (!bmw_mask_check_edge(walker, l->e)) {
return l;
@@ -1199,37 +1506,40 @@ static void *bmw_UVEdgeWalker_step(BMWalker *walker)
/* go over loops around l->v and nl->v and see which ones share l and nl's
* mloopuv's coordinates. in addition, push on l->next if necessary */
for (i = 0; i < 2; i++) {
- cl = i ? nl : l;
- BM_ITER_ELEM (l2, &liter, cl->v, BM_LOOPS_OF_VERT) {
- d1 = CustomData_bmesh_get_layer_n(&walker->bm->ldata,
- cl->head.data, walker->layer);
-
- rlen = BM_edge_face_count(l2->e);
- for (j = 0; j < rlen; j++) {
- if (BLI_gset_haskey(walker->visit_set, l2)) {
+ BMIter liter;
+ BMLoop *l_pivot, *l_radial;
+
+ l_pivot = i ? l->next : l;
+ BM_ITER_ELEM (l_radial, &liter, l_pivot->v, BM_LOOPS_OF_VERT) {
+ BMLoop *l_radial_first = l_radial;
+ void *data_pivot = BM_ELEM_CD_GET_VOID_P(l_pivot, offset);
+
+ do {
+ BMLoop *l_other;
+ void *data_other;
+
+ if (BLI_gset_haskey(walker->visit_set, l_radial)) {
continue;
}
- if (!bmw_mask_check_edge(walker, l2->e)) {
- if (l2->v != cl->v) {
+ if (l_radial->v != l_pivot->v) {
+ if (!bmw_mask_check_edge(walker, l_radial->e)) {
continue;
}
}
- l3 = l2->v != cl->v ? l2->next : l2;
- d2 = CustomData_bmesh_get_layer_n(&walker->bm->ldata,
- l3->head.data, walker->layer);
+ l_other = (l_radial->v != l_pivot->v) ? l_radial->next : l_radial;
+ data_other = BM_ELEM_CD_GET_VOID_P(l_other, offset);
- if (!CustomData_data_equals(type, d1, d2))
+ if (!CustomData_data_equals(type, data_pivot, data_other))
continue;
-
+
lwalk = BMW_state_add(walker);
- BLI_gset_insert(walker->visit_set, l2);
+ BLI_gset_insert(walker->visit_set, l_radial);
- lwalk->l = l2;
+ lwalk->l = l_radial;
- l2 = l2->radial_next;
- }
+ } while ((l_radial = l_radial->radial_next) != l_radial_first);
}
}
@@ -1249,6 +1559,26 @@ static BMWalker bmw_VertShellWalker_Type = {
BM_EDGE, /* valid restrict masks */
};
+static BMWalker bmw_LoopShellWalker_Type = {
+ BM_FACE | BM_LOOP | BM_EDGE | BM_VERT,
+ bmw_LoopShellWalker_begin,
+ bmw_LoopShellWalker_step,
+ bmw_LoopShellWalker_yield,
+ sizeof(BMwLoopShellWalker),
+ BMW_BREADTH_FIRST,
+ BM_EDGE, /* valid restrict masks */
+};
+
+static BMWalker bmw_LoopShellWireWalker_Type = {
+ BM_FACE | BM_LOOP | BM_EDGE | BM_VERT,
+ bmw_LoopShellWireWalker_begin,
+ bmw_LoopShellWireWalker_step,
+ bmw_LoopShellWireWalker_yield,
+ sizeof(BMwLoopShellWireWalker),
+ BMW_BREADTH_FIRST,
+ BM_EDGE, /* valid restrict masks */
+};
+
static BMWalker bmw_FaceShellWalker_Type = {
BM_EDGE,
bmw_FaceShellWalker_begin,
@@ -1279,12 +1609,12 @@ static BMWalker bmw_IslandWalker_Type = {
BM_EDGE | BM_FACE, /* valid restrict masks */
};
-static BMWalker bmw_LoopWalker_Type = {
+static BMWalker bmw_EdgeLoopWalker_Type = {
BM_EDGE,
- bmw_LoopWalker_begin,
- bmw_LoopWalker_step,
- bmw_LoopWalker_yield,
- sizeof(BMwLoopWalker),
+ bmw_EdgeLoopWalker_begin,
+ bmw_EdgeLoopWalker_step,
+ bmw_EdgeLoopWalker_yield,
+ sizeof(BMwEdgeLoopWalker),
BMW_DEPTH_FIRST,
0, /* valid restrict masks */ /* could add flags here but so far none are used */
};
@@ -1341,8 +1671,10 @@ static BMWalker bmw_ConnectedVertexWalker_Type = {
BMWalker *bm_walker_types[] = {
&bmw_VertShellWalker_Type, /* BMW_VERT_SHELL */
+ &bmw_LoopShellWalker_Type, /* BMW_LOOP_SHELL */
+ &bmw_LoopShellWireWalker_Type, /* BMW_LOOP_SHELL_WIRE */
&bmw_FaceShellWalker_Type, /* BMW_FACE_SHELL */
- &bmw_LoopWalker_Type, /* BMW_LOOP */
+ &bmw_EdgeLoopWalker_Type, /* BMW_EDGELOOP */
&bmw_FaceLoopWalker_Type, /* BMW_FACELOOP */
&bmw_EdgeringWalker_Type, /* BMW_EDGERING */
&bmw_EdgeboundaryWalker_Type, /* BMW_EDGEBOUNDARY */
diff --git a/source/blender/bmesh/intern/bmesh_walkers_private.h b/source/blender/bmesh/intern/bmesh_walkers_private.h
index 82d1e760db7..66d812b45d0 100644
--- a/source/blender/bmesh/intern/bmesh_walkers_private.h
+++ b/source/blender/bmesh/intern/bmesh_walkers_private.h
@@ -45,6 +45,16 @@ typedef struct BMwShellWalker {
BMEdge *curedge;
} BMwShellWalker;
+typedef struct BMwLoopShellWalker {
+ BMwGenericWalker header;
+ BMLoop *curloop;
+} BMwLoopShellWalker;
+
+typedef struct BMwLoopShellWireWalker {
+ BMwGenericWalker header;
+ BMElem *curelem;
+} BMwLoopShellWireWalker;
+
typedef struct BMwIslandboundWalker {
BMwGenericWalker header;
BMLoop *base;
@@ -57,14 +67,14 @@ typedef struct BMwIslandWalker {
BMFace *cur;
} BMwIslandWalker;
-typedef struct BMwLoopWalker {
+typedef struct BMwEdgeLoopWalker {
BMwGenericWalker header;
BMEdge *cur, *start;
BMVert *lastv, *startv;
BMFace *f_hub;
bool is_boundary; /* boundary looping changes behavior */
bool is_single; /* single means the edge verts are only connected to 1 face */
-} BMwLoopWalker;
+} BMwEdgeLoopWalker;
typedef struct BMwFaceLoopWalker {
BMwGenericWalker header;
diff --git a/source/blender/bmesh/operators/bmo_bevel.c b/source/blender/bmesh/operators/bmo_bevel.c
index 213a0830e63..d5afb39d7b7 100644
--- a/source/blender/bmesh/operators/bmo_bevel.c
+++ b/source/blender/bmesh/operators/bmo_bevel.c
@@ -35,12 +35,14 @@
void bmo_bevel_exec(BMesh *bm, BMOperator *op)
{
- const float offset = BMO_slot_float_get(op->slots_in, "offset");
- const int offset_type = BMO_slot_int_get(op->slots_in, "offset_type");
- const int seg = BMO_slot_int_get(op->slots_in, "segments");
- const bool vonly = BMO_slot_bool_get(op->slots_in, "vertex_only");
- const float profile = BMO_slot_float_get(op->slots_in, "profile");
- const int material = BMO_slot_int_get(op->slots_in, "material");
+ const float offset = BMO_slot_float_get(op->slots_in, "offset");
+ const int offset_type = BMO_slot_int_get(op->slots_in, "offset_type");
+ const int seg = BMO_slot_int_get(op->slots_in, "segments");
+ const bool vonly = BMO_slot_bool_get(op->slots_in, "vertex_only");
+ const float profile = BMO_slot_float_get(op->slots_in, "profile");
+ const bool clamp_overlap = BMO_slot_bool_get(op->slots_in, "clamp_overlap");
+ const int material = BMO_slot_int_get(op->slots_in, "material");
+ const bool loop_slide = BMO_slot_bool_get(op->slots_in, "loop_slide");
if (offset > 0) {
BMOIter siter;
@@ -61,7 +63,7 @@ void bmo_bevel_exec(BMesh *bm, BMOperator *op)
}
}
- BM_mesh_bevel(bm, offset, offset_type, seg, profile, vonly, false, false, NULL, -1, material);
+ BM_mesh_bevel(bm, offset, offset_type, seg, profile, vonly, false, clamp_overlap, NULL, -1, material, loop_slide);
BMO_slot_buffer_from_enabled_hflag(bm, op, op->slots_out, "faces.out", BM_FACE, BM_ELEM_TAG);
}
diff --git a/source/blender/bmesh/operators/bmo_bridge.c b/source/blender/bmesh/operators/bmo_bridge.c
index e4417477e76..b4570e03c83 100644
--- a/source/blender/bmesh/operators/bmo_bridge.c
+++ b/source/blender/bmesh/operators/bmo_bridge.c
@@ -87,8 +87,9 @@ static void bm_vert_loop_pair(BMesh *bm, BMVert *v1, BMVert *v2, BMLoop **l1, BM
}
/* el_b can have any offset */
-static float bm_edgeloop_offset_length(LinkData *el_a, LinkData *el_b,
- LinkData *el_b_first, const float len_max)
+static float bm_edgeloop_offset_length(
+ LinkData *el_a, LinkData *el_b,
+ LinkData *el_b_first, const float len_max)
{
float len = 0.0f;
BLI_assert(el_a->prev == NULL); /* must be first */
@@ -137,10 +138,11 @@ static bool bm_edge_test_cb(BMEdge *e, void *bm_v)
return BMO_elem_flag_test((BMesh *)bm_v, e, EDGE_MARK);
}
-static void bridge_loop_pair(BMesh *bm,
- struct BMEdgeLoopStore *el_store_a,
- struct BMEdgeLoopStore *el_store_b,
- const bool use_merge, const float merge_factor, const int twist_offset)
+static void bridge_loop_pair(
+ BMesh *bm,
+ struct BMEdgeLoopStore *el_store_a,
+ struct BMEdgeLoopStore *el_store_b,
+ const bool use_merge, const float merge_factor, const int twist_offset)
{
const float eps = 0.00001f;
LinkData *el_a_first, *el_b_first;
@@ -180,20 +182,42 @@ static void bridge_loop_pair(BMesh *bm,
/* normalizing isn't strictly needed but without we may get very large values */
float no[3];
+ float dir_a_orig[3], dir_b_orig[3];
float dir_a[3], dir_b[3];
+ const float *test_a, *test_b;
- sub_v3_v3v3(dir_a,
+ sub_v3_v3v3(dir_a_orig,
((BMVert *)(((LinkData *)lb_a->first)->data))->co,
((BMVert *)(((LinkData *)lb_a->last)->data))->co);
- sub_v3_v3v3(dir_b,
+ sub_v3_v3v3(dir_b_orig,
((BMVert *)(((LinkData *)lb_b->first)->data))->co,
((BMVert *)(((LinkData *)lb_b->last)->data))->co);
/* make the directions point out from the normals, 'no' is used as a temp var */
- cross_v3_v3v3(no, dir_a, el_dir); cross_v3_v3v3(dir_a, no, el_dir);
- cross_v3_v3v3(no, dir_b, el_dir); cross_v3_v3v3(dir_b, no, el_dir);
+ cross_v3_v3v3(no, dir_a_orig, el_dir); cross_v3_v3v3(dir_a, no, el_dir);
+ cross_v3_v3v3(no, dir_b_orig, el_dir); cross_v3_v3v3(dir_b, no, el_dir);
- if (dot_v3v3(dir_a, dir_b) < 0.0f) {
+ if (LIKELY(!is_zero_v3(dir_a) && !is_zero_v3(dir_b))) {
+ test_a = dir_a;
+ test_b = dir_b;
+ }
+ else {
+ /**
+ * This is a corner case:
+ *
+ * <pre>
+ * (loop a) (loop b)
+ * +--------+ +--------+
+ * </pre>
+ *
+ * When loops are aligned to the direction between the loops values of 'dir_a/b' is degenerate,
+ * in this case compare the original directions (before they were corrected by 'el_dir'), see: T43013
+ */
+ test_a = dir_a_orig;
+ test_b = dir_b_orig;
+ }
+
+ if (dot_v3v3(test_a, test_b) < 0.0f) {
BM_edgeloop_flip(bm, el_store_b);
}
diff --git a/source/blender/bmesh/operators/bmo_connect_concave.c b/source/blender/bmesh/operators/bmo_connect_concave.c
new file mode 100644
index 00000000000..107aead6994
--- /dev/null
+++ b/source/blender/bmesh/operators/bmo_connect_concave.c
@@ -0,0 +1,219 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/bmesh/operators/bmo_connect_concave.c
+ * \ingroup bmesh
+ *
+ * Connect vertices so all resulting faces are convex.
+ *
+ * Implementation:
+ *
+ * - triangulate all concave face (tagging convex verts),
+ * - rotate edges (beautify) so edges will connect nearby verts.
+ * - sort long edges (longest first),
+ * put any edges between 2 convex verts last since they often split convex regions.
+ * - merge the sorted edges as long as they don't create convex ngons.
+ */
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_math.h"
+#include "BLI_utildefines.h"
+#include "BLI_alloca.h"
+#include "BLI_memarena.h"
+#include "BLI_heap.h"
+#include "BLI_polyfill2d.h"
+#include "BLI_polyfill2d_beautify.h"
+#include "BLI_edgehash.h"
+
+#include "bmesh.h"
+
+#include "intern/bmesh_operators_private.h" /* own include */
+
+#define EDGE_OUT (1 << 0)
+#define FACE_OUT (1 << 1)
+
+static int bm_edge_length_cmp(const void *a_, const void *b_)
+{
+ const BMEdge *e_a = *(const void **)a_;
+ const BMEdge *e_b = *(const void **)b_;
+
+ int e_a_concave = ((BM_elem_flag_test(e_a->v1, BM_ELEM_TAG)) && (BM_elem_flag_test(e_a->v2, BM_ELEM_TAG)));
+ int e_b_concave = ((BM_elem_flag_test(e_b->v1, BM_ELEM_TAG)) && (BM_elem_flag_test(e_b->v2, BM_ELEM_TAG)));
+
+ /* merge edges between concave edges last since these
+ * are most likely to remain and be the main dividers */
+ if (e_a_concave < e_b_concave) return -1;
+ else if (e_a_concave > e_b_concave) return 1;
+ else {
+ /* otherwise shortest edges last */
+ const float e_a_len = BM_edge_calc_length_squared(e_a);
+ const float e_b_len = BM_edge_calc_length_squared(e_b);
+ if (e_a_len < e_b_len) return 1;
+ else if (e_a_len > e_b_len) return -1;
+ else return 0;
+ }
+}
+
+static bool bm_face_split_by_concave(
+ BMesh *bm, BMFace *f_base, const float eps,
+
+ MemArena *pf_arena,
+ struct Heap *pf_heap, struct EdgeHash *pf_ehash)
+{
+ const int f_base_len = f_base->len;
+ int faces_array_tot = f_base_len - 3;
+ int edges_array_tot = f_base_len - 3;
+ BMFace **faces_array = BLI_array_alloca(faces_array, faces_array_tot);
+ BMEdge **edges_array = BLI_array_alloca(edges_array, edges_array_tot);
+ const int quad_method = 0, ngon_method = 0; /* beauty */
+
+ float normal[3];
+ BLI_assert(f_base->len > 3);
+
+ copy_v3_v3(normal, f_base->no);
+
+ BM_face_triangulate(
+ bm, f_base,
+ faces_array, &faces_array_tot,
+ edges_array, &edges_array_tot,
+ quad_method, ngon_method, false,
+ pf_arena,
+ pf_heap, pf_ehash);
+
+ BLI_assert(edges_array_tot <= f_base_len - 3);
+
+ if (faces_array_tot) {
+ int i;
+ for (i = 0; i < faces_array_tot; i++) {
+ BMFace *f = faces_array[i];
+ BMO_elem_flag_enable(bm, f, FACE_OUT);
+ }
+ }
+ BMO_elem_flag_enable(bm, f_base, FACE_OUT);
+
+ if (edges_array_tot) {
+ int i;
+
+ qsort(edges_array, edges_array_tot, sizeof(*edges_array), bm_edge_length_cmp);
+
+ for (i = 0; i < edges_array_tot; i++) {
+ BMLoop *l_pair[2];
+ BMEdge *e = edges_array[i];
+ BMO_elem_flag_enable(bm, e, EDGE_OUT);
+
+ if (BM_edge_is_contiguous(e) &&
+ BM_edge_loop_pair(e, &l_pair[0], &l_pair[1]))
+ {
+ bool ok = true;
+ int j;
+ for (j = 0; j < 2; j++) {
+ BMLoop *l = l_pair[j];
+
+ /* check that merging the edge (on this side)
+ * wouldn't result in a convex face-loop.
+ *
+ * This is the (l->next, l->prev) we would have once joined.
+ */
+ float cross[3];
+ cross_tri_v3(
+ cross,
+ l->v->co,
+ l->radial_next->next->next->v->co,
+ l->prev->v->co
+ );
+
+ if (dot_v3v3(cross, normal) <= eps) {
+ ok = false;
+ break;
+ }
+ }
+
+ if (ok) {
+ BMFace *f_new, *f_pair[2] = {l_pair[0]->f, l_pair[1]->f};
+ f_new = BM_faces_join(bm, f_pair, 2, true);
+ if (f_new) {
+ BMO_elem_flag_enable(bm, f_new, FACE_OUT);
+ }
+ }
+ }
+ }
+ }
+
+ BLI_heap_clear(pf_heap, NULL);
+ BLI_edgehash_clear_ex(pf_ehash, NULL, BLI_POLYFILL_ALLOC_NGON_RESERVE);
+
+ return true;
+}
+
+static bool bm_face_convex_tag_verts(BMFace *f)
+{
+ bool is_concave = false;
+ if (f->len > 3) {
+ const BMLoop *l_iter, *l_first;
+
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
+ if (BM_loop_is_convex(l_iter) == false) {
+ is_concave = true;
+ BM_elem_flag_enable(l_iter->v, BM_ELEM_TAG);
+ }
+ else {
+ BM_elem_flag_disable(l_iter->v, BM_ELEM_TAG);
+ }
+ } while ((l_iter = l_iter->next) != l_first);
+ }
+ return is_concave;
+}
+
+void bmo_connect_verts_concave_exec(BMesh *bm, BMOperator *op)
+{
+ BMOIter siter;
+ BMFace *f;
+ bool changed = false;
+
+ MemArena *pf_arena;
+ Heap *pf_heap;
+ EdgeHash *pf_ehash;
+
+ pf_arena = BLI_memarena_new(BLI_POLYFILL_ARENA_SIZE, __func__);
+ pf_heap = BLI_heap_new_ex(BLI_POLYFILL_ALLOC_NGON_RESERVE);
+ pf_ehash = BLI_edgehash_new_ex(__func__, BLI_POLYFILL_ALLOC_NGON_RESERVE);
+
+ BMO_ITER (f, &siter, op->slots_in, "faces", BM_FACE) {
+ if (f->len > 3 && bm_face_convex_tag_verts(f)) {
+ if (bm_face_split_by_concave(
+ bm, f, FLT_EPSILON,
+ pf_arena, pf_heap, pf_ehash))
+ {
+ changed = true;
+ }
+ }
+ }
+
+ if (changed) {
+ BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "edges.out", BM_EDGE, EDGE_OUT);
+ BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "faces.out", BM_FACE, FACE_OUT);
+ }
+
+ BLI_memarena_free(pf_arena);
+ BLI_heap_free(pf_heap, NULL);
+ BLI_edgehash_free(pf_ehash, NULL);
+}
diff --git a/source/blender/bmesh/operators/bmo_connect_nonplanar.c b/source/blender/bmesh/operators/bmo_connect_nonplanar.c
index 6859ce2060c..c9ce2c5f6b8 100644
--- a/source/blender/bmesh/operators/bmo_connect_nonplanar.c
+++ b/source/blender/bmesh/operators/bmo_connect_nonplanar.c
@@ -153,23 +153,11 @@ void bmo_connect_verts_nonplanar_exec(BMesh *bm, BMOperator *op)
{
BMOIter siter;
BMFace *f;
- int totface = 0, totloop = 0;
+ bool changed = false;
BLI_LINKSTACK_DECLARE(fstack, BMFace *);
const float angle_limit = BMO_slot_float_get(op->slots_in, "angle_limit");
-
- BMO_ITER (f, &siter, op->slots_in, "faces", BM_FACE) {
- if (f->len > 3) {
- totface += 1;
- totloop += f->len;
- }
- }
-
- if (totface == 0) {
- return;
- }
-
BLI_LINKSTACK_INIT(fstack);
BMO_ITER (f, &siter, op->slots_in, "faces", BM_FACE) {
@@ -188,11 +176,14 @@ void bmo_connect_verts_nonplanar_exec(BMesh *bm, BMOperator *op)
BLI_LINKSTACK_PUSH(fstack, f_pair[j]);
}
}
+ changed = true;
}
}
BLI_LINKSTACK_FREE(fstack);
- BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "edges.out", BM_EDGE, EDGE_OUT);
- BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "faces.out", BM_FACE, FACE_OUT);
+ if (changed) {
+ BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "edges.out", BM_EDGE, EDGE_OUT);
+ BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "faces.out", BM_FACE, FACE_OUT);
+ }
}
diff --git a/source/blender/bmesh/operators/bmo_connect_pair.c b/source/blender/bmesh/operators/bmo_connect_pair.c
index a0acf6ed2c5..12af8902dc5 100644
--- a/source/blender/bmesh/operators/bmo_connect_pair.c
+++ b/source/blender/bmesh/operators/bmo_connect_pair.c
@@ -30,6 +30,7 @@
#include "BLI_math.h"
#include "BLI_utildefines.h"
+#include "BLI_heap.h"
#include "bmesh.h"
@@ -42,8 +43,14 @@
* Method for connecting across many faces.
*
* - use the line between both verts and their normal average to construct a matrix.
- * - using the matrix, we can find all intersecting verts/edges and build connection data.
- * - then walk the connected data and find the shortest path (as we do with other shortest-path functions).
+ * - using the matrix, we can find all intersecting verts/edges.
+ * - walk the connected data and find the shortest path.
+ * - store a heap of paths which are being scanned (#PathContext.states).
+ * - continuously search the shortest path in the heap.
+ * - never step over the same element twice (tag elements as #ELE_TOUCHED).
+ * this avoids going into an eternal loop of there are many possible branches (see T45582).
+ * - when running into a branch, create a new #PathLinkState state and add to the heap.
+ * - when the target is reached, finish - since none of the other paths can be shorter then the one just found.
* - if the connection can't be found - fail.
* - with the connection found, split all edges tagging verts (or tag verts that sit on the intersection).
* - run the standard connect operator.
@@ -56,15 +63,26 @@
/* typically hidden faces */
#define FACE_EXCLUDE 2
+/* any element we've walked over (only do it once!) */
+#define ELE_TOUCHED 4
+
#define FACE_WALK_TEST(f) (CHECK_TYPE_INLINE(f, BMFace *), \
BMO_elem_flag_test(pc->bm_bmoflag, f, FACE_EXCLUDE) == 0)
#define VERT_WALK_TEST(v) (CHECK_TYPE_INLINE(v, BMVert *), \
BMO_elem_flag_test(pc->bm_bmoflag, v, VERT_EXCLUDE) == 0)
+#define ELE_TOUCH_TEST(e) \
+ (CHECK_TYPE_ANY(e, BMVert *, BMEdge *, BMElem *, BMElemF *), \
+ BMO_elem_flag_test(pc->bm_bmoflag, (BMElemF *)e, ELE_TOUCHED))
+#define ELE_TOUCH_MARK(e) \
+ { CHECK_TYPE_ANY(e, BMVert *, BMEdge *, BMElem *, BMElemF *); \
+ BMO_elem_flag_enable(pc->bm_bmoflag, (BMElemF *)e, ELE_TOUCHED); } ((void)0)
+
+
// #define DEBUG_PRINT
typedef struct PathContext {
- ListBase state_lb;
+ Heap *states;
float matrix[3][3];
float axis_sep;
@@ -82,12 +100,10 @@ typedef struct PathContext {
typedef struct PathLink {
struct PathLink *next;
BMElem *ele; /* edge or vert */
- BMElem *ele_from; /* edge or face we game from (not 'next->ele') */
+ BMElem *ele_from; /* edge or face we came from (not 'next->ele') */
} PathLink;
typedef struct PathLinkState {
- struct PathLinkState *next, *prev;
-
/* chain of links */
struct PathLink *link_last;
@@ -96,8 +112,65 @@ typedef struct PathLinkState {
float co_prev[3];
} PathLinkState;
-static int state_isect_co_pair(const PathContext *pc,
- const float co_a[3], const float co_b[3])
+/**
+ \name Min Dist Dir Util
+
+ * Simply getting the closest intersecting vert/edge is _not_ good enough. see T43792
+ * we need to get the closest in both directions since the absolute closest may be a dead-end.
+ *
+ * Logic is simple:
+ *
+ * - first intersection, store the direction.
+ * - successive intersections will update the first distance if its aligned with the first hit.
+ * otherwise update the opposite distance.
+ * - caller stores best outcome in both directions.
+ *
+ * \{ */
+
+typedef struct MinDistDir {
+ /* distance in both directions (FLT_MAX == uninitialized) */
+ float dist_min[2];
+ /* direction of the first intersection found */
+ float dir[3];
+} MinDistDir;
+
+#define MIN_DIST_DIR_INIT {{FLT_MAX, FLT_MAX}}
+
+static int min_dist_dir_test(MinDistDir *mddir, const float dist_dir[3], const float dist_sq)
+{
+
+ if (mddir->dist_min[0] == FLT_MAX) {
+ return 0;
+ }
+ else {
+ if (dot_v3v3(dist_dir, mddir->dir) > 0.0f) {
+ if (dist_sq < mddir->dist_min[0]) {
+ return 0;
+ }
+ }
+ else {
+ if (dist_sq < mddir->dist_min[1]) {
+ return 1;
+ }
+ }
+ }
+
+ return -1;
+}
+
+static void min_dist_dir_update(MinDistDir *dist, const float dist_dir[3])
+{
+ if (dist->dist_min[0] == FLT_MAX) {
+ copy_v3_v3(dist->dir, dist_dir);
+ }
+}
+
+/** \} */
+
+
+static int state_isect_co_pair(
+ const PathContext *pc,
+ const float co_a[3], const float co_b[3])
{
const float diff_a = dot_m3_v3_row_x((float (*)[3])pc->matrix, co_a) - pc->axis_sep;
const float diff_b = dot_m3_v3_row_x((float (*)[3])pc->matrix, co_b) - pc->axis_sep;
@@ -113,15 +186,17 @@ static int state_isect_co_pair(const PathContext *pc,
}
}
-static int state_isect_co_exact(const PathContext *pc,
- const float co[3])
+static int state_isect_co_exact(
+ const PathContext *pc,
+ const float co[3])
{
const float diff = dot_m3_v3_row_x((float (*)[3])pc->matrix, co) - pc->axis_sep;
return (fabsf(diff) <= CONNECT_EPS);
}
-static float state_calc_co_pair_fac(const PathContext *pc,
- const float co_a[3], const float co_b[3])
+static float state_calc_co_pair_fac(
+ const PathContext *pc,
+ const float co_a[3], const float co_b[3])
{
float diff_a, diff_b, diff_tot;
@@ -131,19 +206,21 @@ static float state_calc_co_pair_fac(const PathContext *pc,
return (diff_tot > FLT_EPSILON) ? (diff_a / diff_tot) : 0.5f;
}
-static void state_calc_co_pair(const PathContext *pc,
- const float co_a[3], const float co_b[3],
- float r_co[3])
+static void state_calc_co_pair(
+ const PathContext *pc,
+ const float co_a[3], const float co_b[3],
+ float r_co[3])
{
const float fac = state_calc_co_pair_fac(pc, co_a, co_b);
interp_v3_v3v3(r_co, co_a, co_b, fac);
}
+#ifndef NDEBUG
/**
* Ideally we wouldn't need this and for most cases we don't.
- * But when a face has vertices that are on the boundary more then once this becomes tricky.
+ * But when a face has vertices that are on the boundary more than once this becomes tricky.
*/
-static bool state_link_find(PathLinkState *state, BMElem *ele)
+static bool state_link_find(const PathLinkState *state, BMElem *ele)
{
PathLink *link = state->link_last;
BLI_assert(ELEM(ele->head.htype, BM_VERT, BM_EDGE, BM_FACE));
@@ -156,16 +233,21 @@ static bool state_link_find(PathLinkState *state, BMElem *ele)
}
return false;
}
+#endif
-static void state_link_add(PathContext *pc, PathLinkState *state,
- BMElem *ele, BMElem *ele_from)
+static void state_link_add(
+ PathContext *pc, PathLinkState *state,
+ BMElem *ele, BMElem *ele_from)
{
PathLink *step_new = BLI_mempool_alloc(pc->link_pool);
BLI_assert(ele != ele_from);
BLI_assert(state_link_find(state, ele) == false);
+ /* never walk onto this again */
+ ELE_TOUCH_MARK(ele);
+
#ifdef DEBUG_PRINT
- printf("%s: adding to state %p:%d, %.4f - ", __func__, state, BLI_findindex(&pc->state_lb, state), state->dist);
+ printf("%s: adding to state %p, %.4f - ", __func__, state, state->dist);
if (ele->head.htype == BM_VERT) {
printf("vert %d, ", BM_elem_index_get(ele));
}
@@ -217,12 +299,29 @@ static void state_link_add(PathContext *pc, PathLinkState *state,
}
static PathLinkState *state_dupe_add(
- PathContext *pc,
PathLinkState *state, const PathLinkState *state_orig)
{
state = MEM_mallocN(sizeof(*state), __func__);
*state = *state_orig;
- BLI_addhead(&pc->state_lb, state);
+ return state;
+}
+
+static PathLinkState *state_link_add_test(
+ PathContext *pc, PathLinkState *state, const PathLinkState *state_orig,
+ BMElem *ele, BMElem *ele_from)
+{
+ const bool is_new = (state_orig->link_last != state->link_last);
+ if (is_new) {
+ state = state_dupe_add(state, state_orig);
+ }
+
+ state_link_add(pc, state, ele, ele_from);
+
+ /* after adding a link so we use the updated 'state->dist' */
+ if (is_new) {
+ BLI_heap_insert(pc->states, state->dist, state);
+ }
+
return state;
}
@@ -230,23 +329,47 @@ static PathLinkState *state_dupe_add(
static PathLinkState *state_step__face_edges(
PathContext *pc,
PathLinkState *state, const PathLinkState *state_orig,
- BMLoop *l_iter, BMLoop *l_last)
+ BMLoop *l_iter, BMLoop *l_last,
+ MinDistDir *mddir)
{
+
+ BMLoop *l_iter_best[2] = {NULL, NULL};
+ int i;
+
do {
if (state_isect_co_pair(pc, l_iter->v->co, l_iter->next->v->co)) {
- BMElem *ele_next = (BMElem *)l_iter->e;
- BMElem *ele_next_from = (BMElem *)l_iter->f;
+ float dist_test;
+ float co_isect[3];
+ float dist_dir[3];
+ int index;
- if (FACE_WALK_TEST((BMFace *)ele_next_from) &&
- (state_link_find(state, ele_next) == false))
- {
- if (state_orig->link_last != state->link_last) {
- state = state_dupe_add(pc, state, state_orig);
+ state_calc_co_pair(pc, l_iter->v->co, l_iter->next->v->co, co_isect);
+
+ sub_v3_v3v3(dist_dir, co_isect, state_orig->co_prev);
+ dist_test = len_squared_v3(dist_dir);
+ if ((index = min_dist_dir_test(mddir, dist_dir, dist_test)) != -1) {
+ BMElem *ele_next = (BMElem *)l_iter->e;
+ BMElem *ele_next_from = (BMElem *)l_iter->f;
+
+ if (FACE_WALK_TEST((BMFace *)ele_next_from) &&
+ (ELE_TOUCH_TEST(ele_next) == false))
+ {
+ min_dist_dir_update(mddir, dist_dir);
+ mddir->dist_min[index] = dist_test;
+ l_iter_best[index] = l_iter;
}
- state_link_add(pc, state, ele_next, ele_next_from);
}
}
} while ((l_iter = l_iter->next) != l_last);
+
+ for (i = 0; i < 2; i++) {
+ if ((l_iter = l_iter_best[i])) {
+ BMElem *ele_next = (BMElem *)l_iter->e;
+ BMElem *ele_next_from = (BMElem *)l_iter->f;
+ state = state_link_add_test(pc, state, state_orig, ele_next, ele_next_from);
+ }
+ }
+
return state;
}
@@ -254,23 +377,44 @@ static PathLinkState *state_step__face_edges(
static PathLinkState *state_step__face_verts(
PathContext *pc,
PathLinkState *state, const PathLinkState *state_orig,
- BMLoop *l_iter, BMLoop *l_last)
+ BMLoop *l_iter, BMLoop *l_last,
+ MinDistDir *mddir)
{
+ BMLoop *l_iter_best[2] = {NULL, NULL};
+ int i;
+
do {
if (state_isect_co_exact(pc, l_iter->v->co)) {
- BMElem *ele_next = (BMElem *)l_iter->v;
- BMElem *ele_next_from = (BMElem *)l_iter->f;
-
- if (FACE_WALK_TEST((BMFace *)ele_next_from) &&
- state_link_find(state, ele_next) == false)
- {
- if (state_orig->link_last != state->link_last) {
- state = state_dupe_add(pc, state, state_orig);
+ float dist_test;
+ const float *co_isect = l_iter->v->co;
+ float dist_dir[3];
+ int index;
+
+ sub_v3_v3v3(dist_dir, co_isect, state_orig->co_prev);
+ dist_test = len_squared_v3(dist_dir);
+ if ((index = min_dist_dir_test(mddir, dist_dir, dist_test)) != -1) {
+ BMElem *ele_next = (BMElem *)l_iter->v;
+ BMElem *ele_next_from = (BMElem *)l_iter->f;
+
+ if (FACE_WALK_TEST((BMFace *)ele_next_from) &&
+ (ELE_TOUCH_TEST(ele_next) == false))
+ {
+ min_dist_dir_update(mddir, dist_dir);
+ mddir->dist_min[index] = dist_test;
+ l_iter_best[index] = l_iter;
}
- state_link_add(pc, state, ele_next, ele_next_from);
}
}
} while ((l_iter = l_iter->next) != l_last);
+
+ for (i = 0; i < 2; i++) {
+ if ((l_iter = l_iter_best[i])) {
+ BMElem *ele_next = (BMElem *)l_iter->v;
+ BMElem *ele_next_from = (BMElem *)l_iter->f;
+ state = state_link_add_test(pc, state, state_orig, ele_next, ele_next_from);
+ }
+ }
+
return state;
}
@@ -290,20 +434,12 @@ static bool state_step(PathContext *pc, PathLinkState *state)
if ((l_start->f != ele_from) &&
FACE_WALK_TEST(l_start->f))
{
+ MinDistDir mddir = MIN_DIST_DIR_INIT;
/* very similar to block below */
- if (BM_vert_in_face(l_start->f, pc->v_b)) {
- if (state_orig.link_last != state->link_last) {
- state = state_dupe_add(pc, state, &state_orig);
- }
-
- state_link_add(pc, state, (BMElem *)pc->v_b, (BMElem *)l_start->f);
- }
- else {
- state = state_step__face_edges(pc, state, &state_orig,
- l_start->next, l_start);
- state = state_step__face_verts(pc, state, &state_orig,
- l_start->next->next, l_start);
- }
+ state = state_step__face_edges(pc, state, &state_orig,
+ l_start->next, l_start, &mddir);
+ state = state_step__face_verts(pc, state, &state_orig,
+ l_start->next->next, l_start, &mddir);
}
}
}
@@ -319,24 +455,14 @@ static bool state_step(PathContext *pc, PathLinkState *state)
if ((l_start->f != ele_from) &&
FACE_WALK_TEST(l_start->f))
{
+ MinDistDir mddir = MIN_DIST_DIR_INIT;
/* very similar to block above */
- if (BM_vert_in_face(l_start->f, pc->v_b)) {
- BMElem *ele_next = (BMElem *)pc->v_b;
- BMElem *ele_next_from = (BMElem *)l_start->f;
-
- if (state_orig.link_last != state->link_last) {
- state = state_dupe_add(pc, state, &state_orig);
- }
- state_link_add(pc, state, ele_next, ele_next_from);
- }
- else {
- state = state_step__face_edges(pc, state, &state_orig,
- l_start->next, l_start->prev);
- if (l_start->f->len > 3) {
- /* adjacent verts are handled in state_step__vert_edges */
- state = state_step__face_verts(pc, state, &state_orig,
- l_start->next->next, l_start->prev);
- }
+ state = state_step__face_edges(pc, state, &state_orig,
+ l_start->next, l_start->prev, &mddir);
+ if (l_start->f->len > 3) {
+ /* adjacent verts are handled in state_step__vert_edges */
+ state = state_step__face_verts(pc, state, &state_orig,
+ l_start->next->next, l_start->prev, &mddir);
}
}
}
@@ -351,31 +477,16 @@ static bool state_step(PathContext *pc, PathLinkState *state)
if (((BMElem *)e != ele_from) &&
VERT_WALK_TEST(v_other))
{
- if (v_other == pc->v_b) {
- BMElem *ele_next = (BMElem *)pc->v_b;
+ if (state_isect_co_exact(pc, v_other->co)) {
+ BMElem *ele_next = (BMElem *)v_other;
BMElem *ele_next_from = (BMElem *)e;
-
- if (state_orig.link_last != state->link_last) {
- state = state_dupe_add(pc, state, &state_orig);
- }
- state_link_add(pc, state, ele_next, ele_next_from);
- }
- else {
- if (state_isect_co_exact(pc, v_other->co)) {
- BMElem *ele_next = (BMElem *)v_other;
- BMElem *ele_next_from = (BMElem *)e;
- if (state_link_find(state, ele_next) == false) {
- if (state_orig.link_last != state->link_last) {
- state = state_dupe_add(pc, state, &state_orig);
- }
- state_link_add(pc, state, ele_next, ele_next_from);
- }
+ if (ELE_TOUCH_TEST(ele_next) == false) {
+ state = state_link_add_test(pc, state, &state_orig, ele_next, ele_next_from);
}
}
}
}
}
-
}
else {
BLI_assert(0);
@@ -388,8 +499,7 @@ void bmo_connect_vert_pair_exec(BMesh *bm, BMOperator *op)
BMOpSlot *op_verts_slot = BMO_slot_get(op->slots_in, "verts");
PathContext pc;
- bool found_all;
- float found_dist_best = -1.0f;
+ PathLinkState state_best = {NULL};
if (op_verts_slot->len != 2) {
/* fail! */
@@ -416,7 +526,7 @@ void bmo_connect_vert_pair_exec(BMesh *bm, BMOperator *op)
/* setup context */
{
- BLI_listbase_clear(&pc.state_lb);
+ pc.states = BLI_heap_new();
pc.link_pool = BLI_mempool_create(sizeof(PathLink), 0, 512, BLI_MEMPOOL_NOP);
}
@@ -459,12 +569,22 @@ void bmo_connect_vert_pair_exec(BMesh *bm, BMOperator *op)
#endif
/* get third axis */
+ normalize_v3(basis_dir);
+ normalize_v3(basis_nor);
cross_v3_v3v3(basis_tmp, basis_dir, basis_nor);
+ if (UNLIKELY(normalize_v3(basis_tmp) < FLT_EPSILON)) {
+ ortho_v3_v3(basis_nor, basis_dir);
+ normalize_v3(basis_nor);
+ cross_v3_v3v3(basis_tmp, basis_dir, basis_nor);
+ normalize_v3(basis_tmp);
+ }
- normalize_v3_v3(pc.matrix[0], basis_tmp);
- normalize_v3_v3(pc.matrix[1], basis_dir);
- normalize_v3_v3(pc.matrix[2], basis_nor);
- invert_m3(pc.matrix);
+ copy_v3_v3(pc.matrix[0], basis_tmp);
+ copy_v3_v3(pc.matrix[1], basis_dir);
+ copy_v3_v3(pc.matrix[2], basis_nor);
+ if (invert_m3(pc.matrix) == false) {
+ unit_m3(pc.matrix);
+ }
pc.axis_sep = dot_m3_v3_row_x(pc.matrix, pc.v_a->co);
}
@@ -473,69 +593,61 @@ void bmo_connect_vert_pair_exec(BMesh *bm, BMOperator *op)
{
PathLinkState *state;
state = MEM_callocN(sizeof(*state), __func__);
- BLI_addtail(&pc.state_lb, state);
state_link_add(&pc, state, (BMElem *)pc.v_a, NULL);
+ BLI_heap_insert(pc.states, state->dist, state);
}
- found_all = false;
- while (pc.state_lb.first) {
- PathLinkState *state, *state_next;
- found_all = true;
- for (state = pc.state_lb.first; state; state = state_next) {
- state_next = state->next;
+ while (!BLI_heap_is_empty(pc.states)) {
+
+#ifdef DEBUG_PRINT
+ printf("\n%s: stepping %d\n", __func__, BLI_heap_size(pc.states));
+#endif
+
+ while (!BLI_heap_is_empty(pc.states)) {
+ PathLinkState *state = BLI_heap_popmin(pc.states);
+
+ /* either we insert this into 'pc.states' or its freed */
+ bool continue_search;
+
if (state->link_last->ele == (BMElem *)pc.v_b) {
/* pass, wait until all are found */
#ifdef DEBUG_PRINT
printf("%s: state %p loop found %.4f\n", __func__, state, state->dist);
#endif
- if ((found_dist_best == -1.0f) || (found_dist_best > state->dist)) {
- found_dist_best = state->dist;
- }
+ state_best = *state;
+
+ /* we're done, exit all loops */
+ BLI_heap_clear(pc.states, MEM_freeN);
+ continue_search = false;
}
else if (state_step(&pc, state)) {
- if ((found_dist_best != -1.0f) && (found_dist_best <= state->dist)) {
- BLI_remlink(&pc.state_lb, state);
- MEM_freeN(state);
- }
- found_all = false;
+ continue_search = true;
}
else {
/* didn't reach the end, remove it,
* links are shared between states so just free the link_pool at the end */
- BLI_remlink(&pc.state_lb, state);
- MEM_freeN(state);
+
+#ifdef DEBUG_PRINT
+ printf("%s: state %p removed\n", __func__, state);
+#endif
+ continue_search = false;
}
- }
- if (found_all) {
-#ifdef DEBUG
- for (state = pc.state_lb.first; state; state = state->next) {
- BLI_assert(state->link_last->ele == (BMElem *)pc.v_b);
+ if (continue_search) {
+ BLI_heap_insert(pc.states, state->dist, state);
+ }
+ else {
+ MEM_freeN(state);
}
-#endif
- break;
}
}
- if (BLI_listbase_is_empty(&pc.state_lb)) {
- found_all = false;
- }
-
- if (found_all) {
- PathLinkState *state, *state_best = NULL;
+ if (state_best.link_last) {
PathLink *link;
- float state_best_dist = FLT_MAX;
/* find the best state */
- for (state = pc.state_lb.first; state; state = state->next) {
- if ((state_best == NULL) || (state->dist < state_best_dist)) {
- state_best = state;
- state_best_dist = state_best->dist;
- }
- }
-
- link = state_best->link_last;
+ link = state_best.link_last;
do {
if (link->ele->head.htype == BM_EDGE) {
BMEdge *e = (BMEdge *)link->ele;
@@ -558,16 +670,15 @@ void bmo_connect_vert_pair_exec(BMesh *bm, BMOperator *op)
BMO_elem_flag_enable(bm, pc.v_b, VERT_OUT);
BLI_mempool_destroy(pc.link_pool);
- BLI_freelistN(&pc.state_lb);
+
+ BLI_heap_free(pc.states, MEM_freeN);
#if 1
- if (found_all) {
- /* leave 'check_degenerate' off, if a user tries to cut with 2 verts,
- * always connect even when resulting faces are degenerate [#39418] */
+ if (state_best.link_last) {
BMOperator op_sub;
BMO_op_initf(bm, &op_sub, 0,
- "connect_verts verts=%fv faces_exclude=%s",
- VERT_OUT, op, "faces_exclude");
+ "connect_verts verts=%fv faces_exclude=%s check_degenerate=%b",
+ VERT_OUT, op, "faces_exclude", true);
BMO_op_exec(bm, &op_sub);
BMO_slot_copy(&op_sub, slots_out, "edges.out",
op, slots_out, "edges.out");
diff --git a/source/blender/bmesh/operators/bmo_create.c b/source/blender/bmesh/operators/bmo_create.c
index dd814fa8bfb..1c054e89e39 100644
--- a/source/blender/bmesh/operators/bmo_create.c
+++ b/source/blender/bmesh/operators/bmo_create.c
@@ -39,7 +39,7 @@
/* This is what runs when pressing the F key
* doing the best thing here isn't always easy create vs dissolve, its nice to support
- * but it it _really_ gives issues we might have to not call dissolve. - campbell
+ * but it _really_ gives issues we might have to not call dissolve. - campbell
*/
void bmo_contextual_create_exec(BMesh *bm, BMOperator *op)
{
diff --git a/source/blender/bmesh/operators/bmo_dissolve.c b/source/blender/bmesh/operators/bmo_dissolve.c
index 8cd9ee14bcb..ac0466a74d2 100644
--- a/source/blender/bmesh/operators/bmo_dissolve.c
+++ b/source/blender/bmesh/operators/bmo_dissolve.c
@@ -475,7 +475,7 @@ void bmo_dissolve_limit_exec(BMesh *bm, BMOperator *op)
{
BMOpSlot *einput = BMO_slot_get(op->slots_in, "edges");
BMOpSlot *vinput = BMO_slot_get(op->slots_in, "verts");
- const float angle_max = (float)M_PI / 2.0f;
+ const float angle_max = M_PI_2;
const float angle_limit = min_ff(angle_max, BMO_slot_float_get(op->slots_in, "angle_limit"));
const bool do_dissolve_boundaries = BMO_slot_bool_get(op->slots_in, "use_dissolve_boundaries");
const BMO_Delimit delimit = BMO_slot_int_get(op->slots_in, "delimit");
@@ -494,7 +494,7 @@ void bmo_dissolve_limit_exec(BMesh *bm, BMOperator *op)
static void bm_mesh_edge_collapse_flagged(BMesh *bm, const int flag, const short oflag)
{
- BMO_op_callf(bm, flag, "collapse edges=%fe", oflag);
+ BMO_op_callf(bm, flag, "collapse edges=%fe uvs=%b", oflag, true);
}
void bmo_dissolve_degenerate_exec(BMesh *bm, BMOperator *op)
diff --git a/source/blender/bmesh/operators/bmo_dupe.c b/source/blender/bmesh/operators/bmo_dupe.c
index cd5592f08c9..33048e6c86e 100644
--- a/source/blender/bmesh/operators/bmo_dupe.c
+++ b/source/blender/bmesh/operators/bmo_dupe.c
@@ -44,9 +44,10 @@
*
* Copy an existing vertex from one bmesh to another.
*/
-static BMVert *bmo_vert_copy(BMOperator *op,
- BMOpSlot *slot_vertmap_out,
- BMesh *bm_dst, BMesh *bm_src, BMVert *v_src, GHash *vhash)
+static BMVert *bmo_vert_copy(
+ BMOperator *op,
+ BMOpSlot *slot_vertmap_out,
+ BMesh *bm_dst, BMesh *bm_src, BMVert *v_src, GHash *vhash)
{
BMVert *v_dst;
@@ -72,12 +73,13 @@ static BMVert *bmo_vert_copy(BMOperator *op,
*
* Copy an existing edge from one bmesh to another.
*/
-static BMEdge *bmo_edge_copy(BMOperator *op,
- BMOpSlot *slot_edgemap_out,
- BMOpSlot *slot_boundarymap_out,
- BMesh *bm_dst, BMesh *bm_src,
- BMEdge *e_src,
- GHash *vhash, GHash *ehash)
+static BMEdge *bmo_edge_copy(
+ BMOperator *op,
+ BMOpSlot *slot_edgemap_out,
+ BMOpSlot *slot_boundarymap_out,
+ BMesh *bm_dst, BMesh *bm_src,
+ BMEdge *e_src,
+ GHash *vhash, GHash *ehash)
{
BMEdge *e_dst;
BMVert *e_dst_v1, *e_dst_v2;
@@ -109,7 +111,7 @@ static BMEdge *bmo_edge_copy(BMOperator *op,
/* add to new/old edge map if necassary */
if (rlen < 2) {
- /* not sure what non-manifold cases of greater then three
+ /* not sure what non-manifold cases of greater than three
* radial should do. */
BMO_slot_map_elem_insert(op, slot_boundarymap_out, e_src, e_dst);
}
@@ -131,11 +133,12 @@ static BMEdge *bmo_edge_copy(BMOperator *op,
*
* Copy an existing face from one bmesh to another.
*/
-static BMFace *bmo_face_copy(BMOperator *op,
- BMOpSlot *slot_facemap_out,
- BMesh *bm_dst, BMesh *bm_src,
- BMFace *f_src,
- GHash *vhash, GHash *ehash)
+static BMFace *bmo_face_copy(
+ BMOperator *op,
+ BMOpSlot *slot_facemap_out,
+ BMesh *bm_dst, BMesh *bm_src,
+ BMFace *f_src,
+ GHash *vhash, GHash *ehash)
{
BMFace *f_dst;
BMVert **vtar = BLI_array_alloca(vtar, f_src->len);
diff --git a/source/blender/bmesh/operators/bmo_extrude.c b/source/blender/bmesh/operators/bmo_extrude.c
index 88b53b63abb..4449f223f35 100644
--- a/source/blender/bmesh/operators/bmo_extrude.c
+++ b/source/blender/bmesh/operators/bmo_extrude.c
@@ -39,6 +39,8 @@
#include "intern/bmesh_operators_private.h" /* own include */
+#define USE_EDGE_REGION_FLAGS
+
enum {
EXT_INPUT = 1,
EXT_KEEP = 2,
@@ -135,7 +137,7 @@ void bmo_extrude_discrete_faces_exec(BMesh *bm, BMOperator *op)
* This function won't crash if its not but won't work right either.
* \a e_b is the new edge.
*
- * \note The edge this face comes from needs to be from the first and second verts fo the face.
+ * \note The edge this face comes from needs to be from the first and second verts to the face.
* The caller must ensure this else we will copy from the wrong source.
*/
static void bm_extrude_copy_face_loop_attributes(BMesh *bm, BMFace *f)
@@ -287,6 +289,39 @@ void bmo_extrude_vert_indiv_exec(BMesh *bm, BMOperator *op)
BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "edges.out", BM_EDGE, EXT_KEEP);
}
+#ifdef USE_EDGE_REGION_FLAGS
+/**
+ * When create an edge for an extruded face region
+ * check surrounding edge flags before creating a new edge.
+ */
+static bool bm_extrude_region_edge_flag(const BMVert *v, char r_e_hflag[2])
+{
+ BMEdge *e_iter;
+ const char hflag_enable = BM_ELEM_SEAM;
+ const char hflag_disable = BM_ELEM_SMOOTH;
+ bool ok = false;
+
+ r_e_hflag[0] = 0x0;
+ r_e_hflag[1] = 0xff;
+
+ /* clear flags on both disks */
+ e_iter = v->e;
+ do {
+ if (e_iter->l && !BM_edge_is_boundary(e_iter)) {
+ r_e_hflag[0] |= e_iter->head.hflag;
+ r_e_hflag[1] &= e_iter->head.hflag;
+ ok = true;
+ }
+ } while ((e_iter = BM_DISK_EDGE_NEXT(e_iter, v)) != v->e);
+
+ if (ok) {
+ r_e_hflag[0] &= hflag_enable;
+ r_e_hflag[1] = hflag_disable & ~r_e_hflag[1];
+ }
+ return ok;
+}
+#endif /* USE_EDGE_REGION_FLAGS */
+
void bmo_extrude_face_region_exec(BMesh *bm, BMOperator *op)
{
BMOperator dupeop, delop;
@@ -413,6 +448,9 @@ void bmo_extrude_face_region_exec(BMesh *bm, BMOperator *op)
slot_edges_exclude = BMO_slot_get(op->slots_in, "edges_exclude");
for (e = BMO_iter_new(&siter, dupeop.slots_out, "boundary_map.out", 0); e; e = BMO_iter_step(&siter)) {
BMVert *f_verts[4];
+#ifdef USE_EDGE_REGION_FLAGS
+ BMEdge *f_edges[4];
+#endif
/* this should always be wire, so this is mainly a speedup to avoid map lookup */
if (BM_edge_is_wire(e) && BMO_slot_map_contains(slot_edges_exclude, e)) {
@@ -465,8 +503,38 @@ void bmo_extrude_face_region_exec(BMesh *bm, BMOperator *op)
f_verts[3] = e_new->v2;
}
- /* not sure what to do about example face, pass NULL for now */
+#ifdef USE_EDGE_REGION_FLAGS
+ /* handle new edges */
+ f_edges[0] = e;
+ f_edges[2] = e_new;
+
+ f_edges[1] = BM_edge_exists(f_verts[1], f_verts[2]);
+ if (f_edges[1] == NULL) {
+ char e_hflag[2];
+ bool e_hflag_ok = bm_extrude_region_edge_flag(f_verts[2], e_hflag);
+ f_edges[1] = BM_edge_create(bm, f_verts[1], f_verts[2], NULL, BM_CREATE_NOP);
+ if (e_hflag_ok) {
+ BM_elem_flag_enable(f_edges[1], e_hflag[0]);
+ BM_elem_flag_disable(f_edges[1], e_hflag[1]);
+ }
+ }
+
+ f_edges[3] = BM_edge_exists(f_verts[3], f_verts[0]);
+ if (f_edges[3] == NULL) {
+ char e_hflag[2];
+ bool e_hflag_ok = bm_extrude_region_edge_flag(f_verts[3], e_hflag);
+ f_edges[3] = BM_edge_create(bm, f_verts[3], f_verts[0], NULL, BM_CREATE_NOP);
+ if (e_hflag_ok) {
+ BM_elem_flag_enable(f_edges[3], e_hflag[0]);
+ BM_elem_flag_disable(f_edges[3], e_hflag[1]);
+ }
+ }
+
+ f = BM_face_create(bm, f_verts, f_edges, 4, NULL, BM_CREATE_NOP);
+#else
f = BM_face_create_verts(bm, f_verts, 4, NULL, BM_CREATE_NOP, true);
+#endif
+
bm_extrude_copy_face_loop_attributes(bm, f);
}
@@ -608,10 +676,10 @@ static void calc_solidify_normals(BMesh *bm)
}
else {
/* only one face attached to that edge */
- /* an edge without another attached- the weight on this is
- * undefined, M_PI / 2 is 90d in radians and that seems good enough */
+ /* an edge without another attached- the weight on this is undefined,
+ * M_PI_2 is 90d in radians and that seems good enough */
copy_v3_v3(edge_normal, f1->no);
- mul_v3_fl(edge_normal, M_PI / 2);
+ mul_v3_fl(edge_normal, M_PI_2);
}
add_v3_v3(e->v1->no, edge_normal);
diff --git a/source/blender/bmesh/operators/bmo_fill_attribute.c b/source/blender/bmesh/operators/bmo_fill_attribute.c
index d9f50ac891c..85bca744d86 100644
--- a/source/blender/bmesh/operators/bmo_fill_attribute.c
+++ b/source/blender/bmesh/operators/bmo_fill_attribute.c
@@ -61,8 +61,9 @@ static bool bm_loop_is_face_untag(BMElem *ele, void *UNUSED(user_data))
/**
* Copy all attributes from adjacent untagged faces.
*/
-static void bm_face_copy_shared_all(BMesh *bm, BMLoop *l,
- const bool use_normals, const bool use_data)
+static void bm_face_copy_shared_all(
+ BMesh *bm, BMLoop *l,
+ const bool use_normals, const bool use_data)
{
BMLoop *l_other = l->radial_next;
BMFace *f = l->f, *f_other;
@@ -90,8 +91,9 @@ static void bm_face_copy_shared_all(BMesh *bm, BMLoop *l,
/**
* Flood fill attributes.
*/
-static unsigned int bmesh_face_attribute_fill(BMesh *bm,
- const bool use_normals, const bool use_data)
+static unsigned int bmesh_face_attribute_fill(
+ BMesh *bm,
+ const bool use_normals, const bool use_data)
{
BLI_LINKSTACK_DECLARE(loop_queue_prev, BMLoop *);
BLI_LINKSTACK_DECLARE(loop_queue_next, BMLoop *);
diff --git a/source/blender/bmesh/operators/bmo_fill_grid.c b/source/blender/bmesh/operators/bmo_fill_grid.c
index 40f6937245b..fd1e91a0b30 100644
--- a/source/blender/bmesh/operators/bmo_fill_grid.c
+++ b/source/blender/bmesh/operators/bmo_fill_grid.c
@@ -114,8 +114,9 @@ static void quad_verts_to_barycentric_tri(
/**
* Assign a loop pair from 2 verts (which _must_ share an edge)
*/
-static void bm_loop_pair_from_verts(BMVert *v_a, BMVert *v_b,
- BMLoop *l_pair[2])
+static void bm_loop_pair_from_verts(
+ BMVert *v_a, BMVert *v_b,
+ BMLoop *l_pair[2])
{
BMEdge *e = BM_edge_exists(v_a, v_b);
if (e->l) {
@@ -159,7 +160,7 @@ static void bm_loop_pair_test_copy(BMLoop *l_pair_a[2], BMLoop *l_pair_b[2])
*/
static void bm_loop_interp_from_grid_boundary_4(BMesh *bm, BMLoop *l, BMLoop *l_bound[4], const float w[4])
{
- void *l_cdata[4] = {
+ const void *l_cdata[4] = {
l_bound[0]->head.data,
l_bound[1]->head.data,
l_bound[2]->head.data,
@@ -170,8 +171,7 @@ static void bm_loop_interp_from_grid_boundary_4(BMesh *bm, BMLoop *l, BMLoop *l_
static void bm_loop_interp_from_grid_boundary_2(BMesh *bm, BMLoop *l, BMLoop *l_bound[2], const float t)
{
-
- void *l_cdata[2] = {
+ const void *l_cdata[2] = {
l_bound[0]->head.data,
l_bound[1]->head.data};
@@ -186,8 +186,9 @@ static void bm_loop_interp_from_grid_boundary_2(BMesh *bm, BMLoop *l, BMLoop *l_
/**
* Avoids calling #barycentric_weights_v2_quad often by caching weights into an array.
*/
-static void barycentric_weights_v2_grid_cache(const unsigned int xtot, const unsigned int ytot,
- float (*weight_table)[4])
+static void barycentric_weights_v2_grid_cache(
+ const unsigned int xtot, const unsigned int ytot,
+ float (*weight_table)[4])
{
float x_step = 1.0f / (float)(xtot - 1);
float y_step = 1.0f / (float)(ytot - 1);
@@ -217,9 +218,10 @@ static void barycentric_weights_v2_grid_cache(const unsigned int xtot, const uns
*
* \param v_grid 2d array of verts, all boundary verts must be set, we fill in the middle.
*/
-static void bm_grid_fill_array(BMesh *bm, BMVert **v_grid, const unsigned int xtot, unsigned const int ytot,
- const short mat_nr, const bool use_smooth,
- const bool use_flip, const bool use_interp_simple)
+static void bm_grid_fill_array(
+ BMesh *bm, BMVert **v_grid, const unsigned int xtot, unsigned const int ytot,
+ const short mat_nr, const bool use_smooth,
+ const bool use_flip, const bool use_interp_simple)
{
const bool use_vert_interp = CustomData_has_interp(&bm->vdata);
const bool use_loop_interp = CustomData_has_interp(&bm->ldata);
@@ -346,7 +348,7 @@ static void bm_grid_fill_array(BMesh *bm, BMVert **v_grid, const unsigned int xt
if (use_vert_interp) {
const float *w = weight_table[XY(x, y)];
- void *v_cdata[4] = {
+ const void *v_cdata[4] = {
v_grid[XY(x, 0)]->head.data,
v_grid[XY(0, y)]->head.data,
v_grid[XY(x, ytot - 1)]->head.data,
@@ -486,10 +488,11 @@ static void bm_grid_fill_array(BMesh *bm, BMVert **v_grid, const unsigned int xt
#undef XY
}
-static void bm_grid_fill(BMesh *bm,
- struct BMEdgeLoopStore *estore_a, struct BMEdgeLoopStore *estore_b,
- struct BMEdgeLoopStore *estore_rail_a, struct BMEdgeLoopStore *estore_rail_b,
- const short mat_nr, const bool use_smooth, const bool use_interp_simple)
+static void bm_grid_fill(
+ BMesh *bm,
+ struct BMEdgeLoopStore *estore_a, struct BMEdgeLoopStore *estore_b,
+ struct BMEdgeLoopStore *estore_rail_a, struct BMEdgeLoopStore *estore_rail_b,
+ const short mat_nr, const bool use_smooth, const bool use_interp_simple)
{
#define USE_FLIP_DETECT
diff --git a/source/blender/bmesh/operators/bmo_hull.c b/source/blender/bmesh/operators/bmo_hull.c
index 26a4dbe1e1d..2dfad5a1f47 100644
--- a/source/blender/bmesh/operators/bmo_hull.c
+++ b/source/blender/bmesh/operators/bmo_hull.c
@@ -67,8 +67,9 @@ typedef struct HullTriangle {
/*************************** Hull Triangles ***************************/
-static void hull_add_triangle(BMesh *bm, GSet *hull_triangles, BLI_mempool *pool,
- BMVert *v1, BMVert *v2, BMVert *v3)
+static void hull_add_triangle(
+ BMesh *bm, GSet *hull_triangles, BLI_mempool *pool,
+ BMVert *v1, BMVert *v2, BMVert *v3)
{
HullTriangle *t;
int i;
@@ -189,8 +190,9 @@ static LinkData *final_edges_find_link(ListBase *adj, BMVert *v)
return NULL;
}
-static int hull_final_edges_lookup(HullFinalEdges *final_edges,
- BMVert *v1, BMVert *v2)
+static int hull_final_edges_lookup(
+ HullFinalEdges *final_edges,
+ BMVert *v1, BMVert *v2)
{
ListBase *adj;
@@ -259,8 +261,9 @@ static void hull_final_edges_free(HullFinalEdges *final_edges)
/**************************** Final Output ****************************/
-static void hull_remove_overlapping(BMesh *bm, GSet *hull_triangles,
- HullFinalEdges *final_edges)
+static void hull_remove_overlapping(
+ BMesh *bm, GSet *hull_triangles,
+ HullFinalEdges *final_edges)
{
GSetIterator hull_iter;
@@ -285,8 +288,8 @@ static void hull_remove_overlapping(BMesh *bm, GSet *hull_triangles,
/* Note: can't change ghash while iterating, so mark
* with 'skip' flag rather than deleting triangles */
- if (BM_vert_in_face(f, t->v[1]) &&
- BM_vert_in_face(f, t->v[2]) && f_on_hull)
+ if (BM_vert_in_face(t->v[1], f) &&
+ BM_vert_in_face(t->v[2], f) && f_on_hull)
{
t->skip = true;
BMO_elem_flag_disable(bm, f, HULL_FLAG_INTERIOR_ELE);
@@ -296,8 +299,9 @@ static void hull_remove_overlapping(BMesh *bm, GSet *hull_triangles,
}
}
-static void hull_mark_interior_elements(BMesh *bm, BMOperator *op,
- HullFinalEdges *final_edges)
+static void hull_mark_interior_elements(
+ BMesh *bm, BMOperator *op,
+ HullFinalEdges *final_edges)
{
BMEdge *e;
BMFace *f;
@@ -425,8 +429,9 @@ static int hull_input_vert_count(BMOperator *op)
return count;
}
-static BMVert **hull_input_verts_copy(BMOperator *op,
- const int num_input_verts)
+static BMVert **hull_input_verts_copy(
+ BMOperator *op,
+ const int num_input_verts)
{
BMOIter oiter;
BMVert *v;
@@ -441,8 +446,9 @@ static BMVert **hull_input_verts_copy(BMOperator *op,
return input_verts;
}
-static float (*hull_verts_for_bullet(BMVert **input_verts,
- const int num_input_verts))[3]
+static float (*hull_verts_for_bullet(
+ BMVert **input_verts,
+ const int num_input_verts))[3]
{
float (*coords)[3] = MEM_callocN(sizeof(*coords) * num_input_verts, __func__);
int i;
@@ -454,9 +460,10 @@ static float (*hull_verts_for_bullet(BMVert **input_verts,
return coords;
}
-static BMVert **hull_verts_from_bullet(plConvexHull hull,
- BMVert **input_verts,
- const int num_input_verts)
+static BMVert **hull_verts_from_bullet(
+ plConvexHull hull,
+ BMVert **input_verts,
+ const int num_input_verts)
{
const int num_verts = plConvexHullNumVertices(hull);
BMVert **hull_verts = MEM_mallocN(sizeof(*hull_verts) *
@@ -478,9 +485,10 @@ static BMVert **hull_verts_from_bullet(plConvexHull hull,
return hull_verts;
}
-static void hull_from_bullet(BMesh *bm, BMOperator *op,
- GSet *hull_triangles,
- BLI_mempool *pool)
+static void hull_from_bullet(
+ BMesh *bm, BMOperator *op,
+ GSet *hull_triangles,
+ BLI_mempool *pool)
{
int *fvi = NULL;
BLI_array_declare(fvi);
@@ -529,6 +537,9 @@ static void hull_from_bullet(BMesh *bm, BMOperator *op,
}
BLI_array_free(fvi);
+
+ plConvexHullDelete(hull);
+
MEM_freeN(hull_verts);
MEM_freeN(coords);
MEM_freeN(input_verts);
diff --git a/source/blender/bmesh/operators/bmo_inset.c b/source/blender/bmesh/operators/bmo_inset.c
index b7914e84c50..118a19d3082 100644
--- a/source/blender/bmesh/operators/bmo_inset.c
+++ b/source/blender/bmesh/operators/bmo_inset.c
@@ -208,14 +208,11 @@ static void bm_loop_customdata_merge(
*/
const void *data_src;
- CustomData_data_add(
+ CustomData_data_mix_value(
type,
BM_ELEM_CD_GET_VOID_P(l_a_inner_inset, offset),
- BM_ELEM_CD_GET_VOID_P(l_b_inner_inset, offset));
- CustomData_data_multiply(
- type,
- BM_ELEM_CD_GET_VOID_P(l_a_inner_inset, offset),
- 0.5f);
+ BM_ELEM_CD_GET_VOID_P(l_b_inner_inset, offset),
+ CDT_MIX_MIX, 0.5f);
CustomData_data_copy_value(
type,
BM_ELEM_CD_GET_VOID_P(l_a_inner_inset, offset),
@@ -390,8 +387,10 @@ static void bmo_face_inset_individual(
if (use_interpolate) {
- BM_face_interp_from_face_ex(bm, iface->f, iface->f, true,
- iface->blocks_l, iface->blocks_v, iface->cos_2d, iface->axis_mat);
+ BM_face_interp_from_face_ex(
+ bm, iface->f, iface->f, true,
+ (const void **)iface->blocks_l, (const void **)iface->blocks_v,
+ iface->cos_2d, iface->axis_mat);
/* build rim faces */
l_iter = l_first;
@@ -658,9 +657,10 @@ void bmo_inset_region_exec(BMesh *bm, BMOperator *op)
es->l = es->e_old->l; /* must be a boundary */
}
-
/* run the separate arg */
- bmesh_edge_separate(bm, es->e_old, es->l, false);
+ if (!BM_edge_is_boundary(es->e_old)) {
+ bmesh_edge_separate(bm, es->e_old, es->l, false);
+ }
/* calc edge-split info */
es->e_new = es->l->e;
@@ -972,7 +972,7 @@ void bmo_inset_region_exec(BMesh *bm, BMOperator *op)
v_glue = v_split;
}
else {
- BM_vert_splice(bm, v_split, v_glue);
+ BM_vert_splice(bm, v_glue, v_split);
}
}
}
@@ -993,8 +993,10 @@ void bmo_inset_region_exec(BMesh *bm, BMOperator *op)
for (i = 0; i < iface_array_len; i++) {
if (iface_array[i]) {
InterpFace *iface = iface_array[i];
- BM_face_interp_from_face_ex(bm, iface->f, iface->f, true,
- iface->blocks_l, iface->blocks_v, iface->cos_2d, iface->axis_mat);
+ BM_face_interp_from_face_ex(
+ bm, iface->f, iface->f, true,
+ (const void **)iface->blocks_l, (const void **)iface->blocks_v,
+ iface->cos_2d, iface->axis_mat);
}
}
}
diff --git a/source/blender/bmesh/operators/bmo_join_triangles.c b/source/blender/bmesh/operators/bmo_join_triangles.c
index 6562f26062f..3718f14276c 100644
--- a/source/blender/bmesh/operators/bmo_join_triangles.c
+++ b/source/blender/bmesh/operators/bmo_join_triangles.c
@@ -42,173 +42,276 @@
#include "intern/bmesh_operators_private.h" /* own include */
-#define FACE_OUT (1 << 0)
-
/* assumes edges are validated before reaching this poin */
-static float measure_facepair(const float v1[3], const float v2[3],
- const float v3[3], const float v4[3], float limit)
+static float quad_calc_error(
+ const float v1[3], const float v2[3],
+ const float v3[3], const float v4[3])
{
/* gives a 'weight' to a pair of triangles that join an edge to decide how good a join they would make */
/* Note: this is more complicated than it needs to be and should be cleaned up.. */
- float n1[3], n2[3], measure = 0.0f, angle1, angle2, diff;
- float edgeVec1[3], edgeVec2[3], edgeVec3[3], edgeVec4[3];
- float minarea, maxarea, areaA, areaB;
-
- /* First Test: Normal difference */
- normal_tri_v3(n1, v1, v2, v3);
- normal_tri_v3(n2, v1, v3, v4);
- angle1 = (compare_v3v3(n1, n2, FLT_EPSILON)) ? 0.0f : angle_normalized_v3v3(n1, n2);
-
- normal_tri_v3(n1, v2, v3, v4);
- normal_tri_v3(n2, v4, v1, v2);
- angle2 = (compare_v3v3(n1, n2, FLT_EPSILON)) ? 0.0f : angle_normalized_v3v3(n1, n2);
-
- measure += (angle1 + angle2) * 0.5f;
- if (measure > limit) {
- return measure;
+ float error = 0.0f;
+
+ /* Normal difference */
+ {
+ float n1[3], n2[3];
+ float angle_a, angle_b;
+ float diff;
+
+ normal_tri_v3(n1, v1, v2, v3);
+ normal_tri_v3(n2, v1, v3, v4);
+ angle_a = (compare_v3v3(n1, n2, FLT_EPSILON)) ? 0.0f : angle_normalized_v3v3(n1, n2);
+
+ normal_tri_v3(n1, v2, v3, v4);
+ normal_tri_v3(n2, v4, v1, v2);
+ angle_b = (compare_v3v3(n1, n2, FLT_EPSILON)) ? 0.0f : angle_normalized_v3v3(n1, n2);
+
+ diff = (angle_a + angle_b) / (float)(M_PI * 2);
+
+ error += diff;
}
- /* Second test: Colinearity */
- sub_v3_v3v3(edgeVec1, v1, v2);
- sub_v3_v3v3(edgeVec2, v2, v3);
- sub_v3_v3v3(edgeVec3, v3, v4);
- sub_v3_v3v3(edgeVec4, v4, v1);
-
- normalize_v3(edgeVec1);
- normalize_v3(edgeVec2);
- normalize_v3(edgeVec3);
- normalize_v3(edgeVec4);
-
- /* a completely skinny face is 'pi' after halving */
- diff = 0.25f * (fabsf(angle_normalized_v3v3(edgeVec1, edgeVec2) - (float)M_PI_2) +
- fabsf(angle_normalized_v3v3(edgeVec2, edgeVec3) - (float)M_PI_2) +
- fabsf(angle_normalized_v3v3(edgeVec3, edgeVec4) - (float)M_PI_2) +
- fabsf(angle_normalized_v3v3(edgeVec4, edgeVec1) - (float)M_PI_2));
-
- if (!diff) {
- return 0.0;
+ /* Colinearity */
+ {
+ float edge_vecs[4][3];
+ float diff;
+
+ sub_v3_v3v3(edge_vecs[0], v1, v2);
+ sub_v3_v3v3(edge_vecs[1], v2, v3);
+ sub_v3_v3v3(edge_vecs[2], v3, v4);
+ sub_v3_v3v3(edge_vecs[3], v4, v1);
+
+ normalize_v3(edge_vecs[0]);
+ normalize_v3(edge_vecs[1]);
+ normalize_v3(edge_vecs[2]);
+ normalize_v3(edge_vecs[3]);
+
+ /* a completely skinny face is 'pi' after halving */
+ diff = (fabsf(angle_normalized_v3v3(edge_vecs[0], edge_vecs[1]) - (float)M_PI_2) +
+ fabsf(angle_normalized_v3v3(edge_vecs[1], edge_vecs[2]) - (float)M_PI_2) +
+ fabsf(angle_normalized_v3v3(edge_vecs[2], edge_vecs[3]) - (float)M_PI_2) +
+ fabsf(angle_normalized_v3v3(edge_vecs[3], edge_vecs[0]) - (float)M_PI_2)) / (float)(M_PI * 2);
+
+ error += diff;
}
- measure += diff;
- if (measure > limit) {
- return measure;
+ /* Concavity */
+ {
+ float area_min, area_max, area_a, area_b;
+ float diff;
+
+ area_a = area_tri_v3(v1, v2, v3) + area_tri_v3(v1, v3, v4);
+ area_b = area_tri_v3(v2, v3, v4) + area_tri_v3(v4, v1, v2);
+
+ area_min = min_ff(area_a, area_b);
+ area_max = max_ff(area_a, area_b);
+
+ diff = area_max ? (1.0f - (area_min / area_max)) : 1.0f;
+
+ error += diff;
}
- /* Third test: Concavity */
- areaA = area_tri_v3(v1, v2, v3) + area_tri_v3(v1, v3, v4);
- areaB = area_tri_v3(v2, v3, v4) + area_tri_v3(v4, v1, v2);
+ return error;
+}
+
+static void bm_edge_to_quad_verts(const BMEdge *e, const BMVert *r_v_quad[4])
+{
+ BLI_assert(e->l->f->len == 3 && e->l->radial_next->f->len == 3);
+ BLI_assert(BM_edge_is_manifold(e));
+ r_v_quad[0] = e->l->v;
+ r_v_quad[1] = e->l->prev->v;
+ r_v_quad[2] = e->l->next->v;
+ r_v_quad[3] = e->l->radial_next->prev->v;
+}
+
+/* cache customdata delimiters */
+struct DelimitData_CD {
+ int cd_type;
+ int cd_size;
+ int cd_offset;
+ int cd_offset_end;
+};
+
+struct DelimitData {
+ unsigned int do_seam : 1;
+ unsigned int do_sharp : 1;
+ unsigned int do_mat : 1;
+ unsigned int do_angle_face : 1;
+ unsigned int do_angle_shape : 1;
- if (areaA <= areaB) minarea = areaA;
- else minarea = areaB;
+ float angle_face;
+ float angle_face__cos;
- if (areaA >= areaB) maxarea = areaA;
- else maxarea = areaB;
+ float angle_shape;
- if (!maxarea) measure += 1;
- else measure += (1 - (minarea / maxarea));
+ struct DelimitData_CD cdata[4];
+ int cdata_len;
+};
- return measure;
+static bool bm_edge_is_contiguous_loop_cd_all(
+ const BMEdge *e, const struct DelimitData_CD *delimit_data)
+{
+ int cd_offset;
+ for (cd_offset = delimit_data->cd_offset;
+ cd_offset < delimit_data->cd_offset_end;
+ cd_offset += delimit_data->cd_size)
+ {
+ if (BM_edge_is_contiguous_loop_cd(e, delimit_data->cd_type, cd_offset) == false) {
+ return false;
+ }
+ }
+
+ return true;
}
-#define T2QUV_LIMIT 0.005f
-#define T2QCOL_LIMIT 3
+static bool bm_edge_delimit_cdata(
+ CustomData *ldata, CustomDataType type,
+ struct DelimitData_CD *r_delim_cd)
+{
+ const int layer_len = CustomData_number_of_layers(ldata, type);
+ r_delim_cd->cd_type = type;
+ r_delim_cd->cd_size = CustomData_sizeof(r_delim_cd->cd_type);
+ r_delim_cd->cd_offset = CustomData_get_n_offset(ldata, type, 0);
+ r_delim_cd->cd_offset_end = r_delim_cd->cd_size * layer_len;
+ return (r_delim_cd->cd_offset != -1);
+}
-static bool bm_edge_faces_cmp(BMesh *bm, BMEdge *e, const bool do_uv, const bool do_tf, const bool do_vcol)
+static float bm_edge_is_delimit(
+ const BMEdge *e,
+ const struct DelimitData *delimit_data)
{
- /* first get loops */
- BMLoop *l[4];
-
- l[0] = e->l;
- l[2] = e->l->radial_next;
-
- /* match up loops on each side of an edge corresponding to each vert */
- if (l[0]->v == l[2]->v) {
- l[1] = l[0]->next;
- l[3] = l[1]->next;
+ BMFace *f_a = e->l->f, *f_b = e->l->radial_next->f;
+#if 0
+ const bool is_contig = BM_edge_is_contiguous(e);
+ float angle;
+#endif
+
+ if ((delimit_data->do_seam) &&
+ (BM_elem_flag_test(e, BM_ELEM_SEAM)))
+ {
+ goto fail;
}
- else {
- l[1] = l[0]->next;
- l[3] = l[2];
- l[2] = l[3]->next;
+ if ((delimit_data->do_sharp) &&
+ (BM_elem_flag_test(e, BM_ELEM_SMOOTH) == 0))
+ {
+ goto fail;
}
- /* Test UV's */
- if (do_uv) {
- const MLoopUV *luv[4] = {
- CustomData_bmesh_get(&bm->ldata, l[0]->head.data, CD_MLOOPUV),
- CustomData_bmesh_get(&bm->ldata, l[1]->head.data, CD_MLOOPUV),
- CustomData_bmesh_get(&bm->ldata, l[2]->head.data, CD_MLOOPUV),
- CustomData_bmesh_get(&bm->ldata, l[3]->head.data, CD_MLOOPUV),
- };
-
- /* do UV */
- if (luv[0] && (!compare_v2v2(luv[0]->uv, luv[2]->uv, T2QUV_LIMIT) ||
- !compare_v2v2(luv[1]->uv, luv[3]->uv, T2QUV_LIMIT)))
- {
- return false;
+ if ((delimit_data->do_mat) &&
+ (f_a->mat_nr != f_b->mat_nr))
+ {
+ goto fail;
+ }
+
+ if (delimit_data->do_angle_face) {
+ if (dot_v3v3(f_a->no, f_b->no) < delimit_data->angle_face__cos) {
+ goto fail;
}
}
- if (do_tf) {
- const MTexPoly *tp[2] = {
- CustomData_bmesh_get(&bm->pdata, l[0]->f->head.data, CD_MTEXPOLY),
- CustomData_bmesh_get(&bm->pdata, l[1]->f->head.data, CD_MTEXPOLY),
- };
+ if (delimit_data->do_angle_shape) {
+ const BMVert *verts[4];
+ bm_edge_to_quad_verts(e, verts);
- if (tp[0] && (tp[0]->tpage != tp[1]->tpage)) {
- return false;
+ /* if we're checking the shape at all, a flipped face is out of the question */
+ if (is_quad_flip_v3(verts[0]->co, verts[1]->co, verts[2]->co, verts[3]->co)) {
+ goto fail;
+ }
+ else {
+ float edge_vecs[4][3];
+
+ sub_v3_v3v3(edge_vecs[0], verts[0]->co, verts[1]->co);
+ sub_v3_v3v3(edge_vecs[1], verts[1]->co, verts[2]->co);
+ sub_v3_v3v3(edge_vecs[2], verts[2]->co, verts[3]->co);
+ sub_v3_v3v3(edge_vecs[3], verts[3]->co, verts[0]->co);
+
+ normalize_v3(edge_vecs[0]);
+ normalize_v3(edge_vecs[1]);
+ normalize_v3(edge_vecs[2]);
+ normalize_v3(edge_vecs[3]);
+
+ if ((fabsf(angle_normalized_v3v3(edge_vecs[0], edge_vecs[1]) - (float)M_PI_2) > delimit_data->angle_shape) ||
+ (fabsf(angle_normalized_v3v3(edge_vecs[1], edge_vecs[2]) - (float)M_PI_2) > delimit_data->angle_shape) ||
+ (fabsf(angle_normalized_v3v3(edge_vecs[2], edge_vecs[3]) - (float)M_PI_2) > delimit_data->angle_shape) ||
+ (fabsf(angle_normalized_v3v3(edge_vecs[3], edge_vecs[0]) - (float)M_PI_2) > delimit_data->angle_shape))
+ {
+ goto fail;
+ }
}
}
- /* Test Vertex Colors */
- if (do_vcol) {
- const MLoopCol *lcol[4] = {
- CustomData_bmesh_get(&bm->ldata, l[0]->head.data, CD_MLOOPCOL),
- CustomData_bmesh_get(&bm->ldata, l[1]->head.data, CD_MLOOPCOL),
- CustomData_bmesh_get(&bm->ldata, l[2]->head.data, CD_MLOOPCOL),
- CustomData_bmesh_get(&bm->ldata, l[3]->head.data, CD_MLOOPCOL),
- };
-
- if (lcol[0]) {
- if (!compare_rgb_uchar((unsigned char *)&lcol[0]->r, (unsigned char *)&lcol[2]->r, T2QCOL_LIMIT) ||
- !compare_rgb_uchar((unsigned char *)&lcol[1]->r, (unsigned char *)&lcol[3]->r, T2QCOL_LIMIT))
- {
- return false;
+ if (delimit_data->cdata_len) {
+ int i;
+ for (i = 0; i < delimit_data->cdata_len; i++) {
+ if (!bm_edge_is_contiguous_loop_cd_all(e, &delimit_data->cdata[i])) {
+ goto fail;
}
}
}
+ return false;
+
+fail:
return true;
}
-#define EDGE_MARK 1
-#define EDGE_CHOSEN 2
-
-#define FACE_MARK 1
-#define FACE_INPUT 2
-
+#define EDGE_MARK (1 << 0)
+#define FACE_OUT (1 << 0)
+#define FACE_INPUT (1 << 2)
void bmo_join_triangles_exec(BMesh *bm, BMOperator *op)
{
- const bool do_sharp = BMO_slot_bool_get(op->slots_in, "cmp_sharp");
- const bool do_uv = BMO_slot_bool_get(op->slots_in, "cmp_uvs");
- const bool do_tf = do_uv; /* texture face, make make its own option eventually */
- const bool do_vcol = BMO_slot_bool_get(op->slots_in, "cmp_vcols");
- const bool do_mat = BMO_slot_bool_get(op->slots_in, "cmp_materials");
- const float limit = BMO_slot_float_get(op->slots_in, "limit");
+ float angle_face, angle_shape;
BMIter iter;
BMOIter siter;
BMFace *f;
- BMEdge *e, *e_next;
+ BMEdge *e;
/* data: edge-to-join, sort_value: error weight */
struct SortPointerByFloat *jedges;
unsigned i, totedge;
unsigned int totedge_tag = 0;
+ struct DelimitData delimit_data = {0};
+
+ delimit_data.do_seam = BMO_slot_bool_get(op->slots_in, "cmp_seam");
+ delimit_data.do_sharp = BMO_slot_bool_get(op->slots_in, "cmp_sharp");
+ delimit_data.do_mat = BMO_slot_bool_get(op->slots_in, "cmp_materials");
+
+ angle_face = BMO_slot_float_get(op->slots_in, "angle_face_threshold");
+ if (angle_face < DEG2RADF(180.0f)) {
+ delimit_data.angle_face = angle_face;
+ delimit_data.angle_face__cos = cosf(angle_face);
+ delimit_data.do_angle_face = true;
+ }
+ else {
+ delimit_data.do_angle_face = false;
+ }
+
+ angle_shape = BMO_slot_float_get(op->slots_in, "angle_shape_threshold");
+ if (angle_shape < DEG2RADF(180.0f)) {
+ delimit_data.angle_shape = angle_shape;
+ delimit_data.do_angle_shape = true;
+ }
+ else {
+ delimit_data.do_angle_shape = false;
+ }
+
+ if (BMO_slot_bool_get(op->slots_in, "cmp_uvs") &&
+ bm_edge_delimit_cdata(&bm->ldata, CD_MLOOPUV, &delimit_data.cdata[delimit_data.cdata_len]))
+ {
+ delimit_data.cdata_len += 1;
+ }
+
+ delimit_data.cdata[delimit_data.cdata_len].cd_offset = -1;
+ if (BMO_slot_bool_get(op->slots_in, "cmp_vcols") &&
+ bm_edge_delimit_cdata(&bm->ldata, CD_MLOOPCOL, &delimit_data.cdata[delimit_data.cdata_len]))
+ {
+ delimit_data.cdata_len += 1;
+ }
+
/* flag all edges of all input face */
BMO_ITER (f, &siter, op->slots_in, "faces", BM_FACE) {
if (f->len == 3) {
@@ -220,10 +323,13 @@ void bmo_join_triangles_exec(BMesh *bm, BMOperator *op)
BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
BMFace *f_a, *f_b;
if (BM_edge_face_pair(e, &f_a, &f_b) &&
- (BMO_elem_flag_test(bm, f_a, FACE_INPUT) && BMO_elem_flag_test(bm, f_b, FACE_INPUT)))
+ (BMO_elem_flag_test(bm, f_a, FACE_INPUT) &&
+ BMO_elem_flag_test(bm, f_b, FACE_INPUT)))
{
- BMO_elem_flag_enable(bm, e, EDGE_MARK);
- totedge_tag++;
+ if (!bm_edge_is_delimit(e, &delimit_data)) {
+ BMO_elem_flag_enable(bm, e, EDGE_MARK);
+ totedge_tag++;
+ }
}
}
@@ -236,36 +342,19 @@ void bmo_join_triangles_exec(BMesh *bm, BMOperator *op)
i = 0;
BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
- BMVert *v1, *v2, *v3, *v4;
- BMFace *f_a, *f_b;
- float measure;
+ const BMVert *verts[4];
+ float error;
if (!BMO_elem_flag_test(bm, e, EDGE_MARK))
continue;
- f_a = e->l->f;
- f_b = e->l->radial_next->f;
+ bm_edge_to_quad_verts(e, verts);
- if (do_sharp && !BM_elem_flag_test(e, BM_ELEM_SMOOTH))
- continue;
+ error = quad_calc_error(verts[0]->co, verts[1]->co, verts[2]->co, verts[3]->co);
- if (do_mat && f_a->mat_nr != f_b->mat_nr)
- continue;
-
- if ((do_uv || do_tf || do_vcol) && (bm_edge_faces_cmp(bm, e, do_uv, do_tf, do_vcol) == false))
- continue;
-
- v1 = e->l->v;
- v2 = e->l->prev->v;
- v3 = e->l->next->v;
- v4 = e->l->radial_next->prev->v;
-
- measure = measure_facepair(v1->co, v2->co, v3->co, v4->co, limit);
- if (measure < limit) {
- jedges[i].data = e;
- jedges[i].sort_value = measure;
- i++;
- }
+ jedges[i].data = e;
+ jedges[i].sort_value = error;
+ i++;
}
totedge = i;
@@ -279,27 +368,8 @@ void bmo_join_triangles_exec(BMesh *bm, BMOperator *op)
f_b = e->l->radial_next->f;
/* check if another edge already claimed this face */
- if ((BMO_elem_flag_test(bm, f_a, FACE_MARK) == false) ||
- (BMO_elem_flag_test(bm, f_b, FACE_MARK) == false))
- {
- BMO_elem_flag_enable(bm, f_a, FACE_MARK);
- BMO_elem_flag_enable(bm, f_b, FACE_MARK);
- BMO_elem_flag_enable(bm, e, EDGE_CHOSEN);
- }
- }
-
- MEM_freeN(jedges);
-
- /* join best weighted */
- BM_ITER_MESH_MUTABLE (e, e_next, &iter, bm, BM_EDGES_OF_MESH) {
- BMFace *f_new;
- BMFace *f_a, *f_b;
-
- if (!BMO_elem_flag_test(bm, e, EDGE_CHOSEN))
- continue;
-
- BM_edge_face_pair(e, &f_a, &f_b); /* checked above */
- if ((f_a->len == 3 && f_b->len == 3)) {
+ if ((f_a->len == 3) && (f_b->len == 3)) {
+ BMFace *f_new;
f_new = BM_faces_join_pair(bm, f_a, f_b, e, true);
if (f_new) {
BMO_elem_flag_enable(bm, f_new, FACE_OUT);
@@ -307,39 +377,7 @@ void bmo_join_triangles_exec(BMesh *bm, BMOperator *op)
}
}
- /* join 2-tri islands */
- BM_ITER_MESH_MUTABLE (e, e_next, &iter, bm, BM_EDGES_OF_MESH) {
- if (BMO_elem_flag_test(bm, e, EDGE_MARK)) {
- BMLoop *l_a, *l_b;
- BMFace *f_a, *f_b;
-
- /* ok, this edge wasn't merged, check if it's
- * in a 2-tri-pair island, and if so merge */
- l_a = e->l;
- l_b = e->l->radial_next;
-
- f_a = l_a->f;
- f_b = l_b->f;
-
- /* check the other 2 edges in both tris are untagged */
- if ((f_a->len == 3 && f_b->len == 3) &&
- (BMO_elem_flag_test(bm, l_a->next->e, EDGE_MARK) == false) &&
- (BMO_elem_flag_test(bm, l_a->prev->e, EDGE_MARK) == false) &&
- (BMO_elem_flag_test(bm, l_b->next->e, EDGE_MARK) == false) &&
- (BMO_elem_flag_test(bm, l_b->prev->e, EDGE_MARK) == false) &&
- /* check for faces that use same verts, this is supported but raises an error
- * and cancels the operation when performed from editmode, since this is only
- * two triangles we only need to compare a single vertex */
- (LIKELY(l_a->prev->v != l_b->prev->v)))
- {
- BMFace *f_new;
- f_new = BM_faces_join_pair(bm, f_a, f_b, e, true);
- if (f_new) {
- BMO_elem_flag_enable(bm, f_new, FACE_OUT);
- }
- }
- }
- }
+ MEM_freeN(jedges);
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_normals.c b/source/blender/bmesh/operators/bmo_normals.c
index d0f08871400..f62e445ca18 100644
--- a/source/blender/bmesh/operators/bmo_normals.c
+++ b/source/blender/bmesh/operators/bmo_normals.c
@@ -47,39 +47,79 @@ static bool bmo_recalc_normal_edge_filter_cb(BMElem *ele, void *UNUSED(user_data
}
/**
- * Given an array of faces, recalculate their normals.
- * this functions assumes all faces in the array are connected by edges.
+ * This uses a more comprehensive test to see if the furthest face from the center
+ * is pointing towards the center or not.
*
- * \param bm
- * \param faces Array of connected faces.
- * \param faces_len Length of \a faces
- * \param oflag Flag to check before doing the actual face flipping.
+ * A simple test could just check the dot product of the faces-normal and the direction from the center,
+ * however this can fail for faces which make a sharp spike. eg:
+ *
+ * <pre>
+ * +
+ * |\ <- face
+ * + +
+ * \ \
+ * \ \
+ * \ +--------------+
+ * \ |
+ * \ center -> + |
+ * \ |
+ * +------------+
+ * </pre>
+ *
+ * In the example above, the a\ face can point towards the \a center
+ * which would end up flipping the normals inwards.
+ *
+ * To take these spikes into account, use the normals of the faces edges.
*/
-static void bmo_recalc_face_normals_array(BMesh *bm, BMFace **faces, const int faces_len, const short oflag)
+#define USE_FACE_EDGE_NORMAL_TEST
+
+/**
+ * The center of the entire island is't necessarily well placed,
+ *
+ * This re-calculated a center relative to this face.
+ */
+#ifdef USE_FACE_EDGE_NORMAL_TEST
+# define USE_FACE_LOCAL_CENTER_TEST
+#endif
+
+/**
+ * \return a face index in \a faces and set \a r_is_flip if the face is flipped away from the center.
+ */
+static int recalc_face_normals_find_index(BMesh *bm, BMFace **faces, const int faces_len, bool *r_is_flip)
{
+ float cent_area_accum = 0.0f;
+ float f_len_best_sq;
+
float cent[3], tvec[3];
- float (*faces_center)[3] = MEM_mallocN(sizeof(*faces_center) * faces_len, __func__);
const float cent_fac = 1.0f / (float)faces_len;
- int i, f_start_index;
- const short oflag_flip = oflag | FACE_FLIP;
- float f_len_best_sq;
- BMFace *f;
+ float (*faces_center)[3] = MEM_mallocN(sizeof(*faces_center) * faces_len, __func__);
+ float *faces_area = MEM_mallocN(sizeof(*faces_area) * faces_len, __func__);
+ bool is_flip = false;
+ int f_start_index;
+ int i;
- BLI_LINKSTACK_DECLARE(fstack, BMFace *);
+ UNUSED_VARS_NDEBUG(bm);
zero_v3(cent);
/* first calculate the center */
for (i = 0; i < faces_len; i++) {
float *f_cent = faces_center[i];
+ const float f_area = BM_face_calc_area(faces[i]);
BM_face_calc_center_mean_weighted(faces[i], f_cent);
- madd_v3_v3fl(cent, f_cent, cent_fac);
+ madd_v3_v3fl(cent, f_cent, cent_fac * f_area);
+ cent_area_accum += f_area;
+ faces_area[i] = f_area;
BLI_assert(BMO_elem_flag_test(bm, faces[i], FACE_TEMP) == 0);
BLI_assert(BM_face_is_normal_valid(faces[i]));
}
+ if (cent_area_accum != 0.0f) {
+ mul_v3_fl(cent, 1.0f / cent_area_accum);
+ }
+
f_len_best_sq = -FLT_MAX;
/* used in degenerate cases only */
f_start_index = 0;
@@ -87,19 +127,104 @@ static void bmo_recalc_face_normals_array(BMesh *bm, BMFace **faces, const int f
for (i = 0; i < faces_len; i++) {
float f_len_test_sq;
- if ((f_len_test_sq = len_squared_v3v3(faces_center[i], cent)) > f_len_best_sq) {
- f_len_best_sq = f_len_test_sq;
- f_start_index = i;
+ if (faces_area[i] > FLT_EPSILON) {
+ if ((f_len_test_sq = len_squared_v3v3(faces_center[i], cent)) > f_len_best_sq) {
+ f_len_best_sq = f_len_test_sq;
+ f_start_index = i;
+ }
}
}
- /* make sure the starting face has the correct winding */
- sub_v3_v3v3(tvec, faces_center[f_start_index], cent);
- if (dot_v3v3(tvec, faces[f_start_index]->no) < 0.0f) {
- BMO_elem_flag_enable(bm, faces[f_start_index], FACE_FLIP);
+#ifdef USE_FACE_EDGE_NORMAL_TEST
+ {
+ BMFace *f_test = faces[f_start_index];
+ BMLoop *l_iter, *l_first;
+ float e_len_best_sq = -FLT_MAX;
+ BMLoop *l_other_best = NULL;
+ float no_edge[3];
+ const float *no_best;
+
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f_test);
+ do {
+ if (BM_edge_is_manifold(l_iter->e) &&
+ bmo_recalc_normal_edge_filter_cb((BMElem *)l_iter->e, NULL))
+ {
+ BMLoop *l_other = l_iter->radial_next;
+
+ if (len_squared_v3v3(l_iter->v->co, l_iter->next->v->co) > FLT_EPSILON) {
+ float e_len_test_sq;
+ float e_cent[3];
+ mid_v3_v3v3(e_cent, l_iter->v->co, l_iter->next->v->co);
+ e_len_test_sq = len_squared_v3v3(cent, e_cent);
+ if (e_len_test_sq > e_len_best_sq) {
+ l_other_best = l_other;
+ e_len_best_sq = e_len_test_sq;
+ }
+ }
+ }
+ } while ((l_iter = l_iter->next) != l_first);
+
+ /* furthest edge on furthest face */
+ if (l_other_best) {
+ float e_cent[3];
+
+#ifdef USE_FACE_LOCAL_CENTER_TEST
+ {
+ float f_cent_other[3];
+ BM_face_calc_center_mean_weighted(l_other_best->f, f_cent_other);
+ mid_v3_v3v3(cent, f_cent_other, faces_center[f_start_index]);
+ }
+#endif
+ mid_v3_v3v3(e_cent, l_other_best->e->v1->co, l_other_best->e->v2->co);
+ sub_v3_v3v3(tvec, e_cent, cent);
+
+ madd_v3_v3v3fl(no_edge, f_test->no, l_other_best->f->no, BM_edge_is_contiguous(l_other_best->e) ? 1 : -1);
+ no_best = no_edge;
+ }
+ else {
+ sub_v3_v3v3(tvec, faces_center[f_start_index], cent);
+ no_best = f_test->no;
+ }
+
+ is_flip = (dot_v3v3(tvec, no_best) < 0.0f);
}
+#else
+ sub_v3_v3v3(tvec, faces_center[f_start_index], cent);
+ is_flip = (dot_v3v3(tvec, faces[f_start_index]->no) < 0.0f);
+#endif
+ /* make sure the starting face has the correct winding */
MEM_freeN(faces_center);
+ MEM_freeN(faces_area);
+
+ *r_is_flip = is_flip;
+ return f_start_index;
+}
+
+/**
+ * Given an array of faces, recalculate their normals.
+ * this functions assumes all faces in the array are connected by edges.
+ *
+ * \param bm
+ * \param faces Array of connected faces.
+ * \param faces_len Length of \a faces
+ * \param oflag Flag to check before doing the actual face flipping.
+ */
+static void bmo_recalc_face_normals_array(BMesh *bm, BMFace **faces, const int faces_len, const short oflag)
+{
+ int i, f_start_index;
+ const short oflag_flip = oflag | FACE_FLIP;
+ bool is_flip;
+
+ BMFace *f;
+
+ BLI_LINKSTACK_DECLARE(fstack, BMFace *);
+
+ f_start_index = recalc_face_normals_find_index(bm, faces, faces_len, &is_flip);
+
+ if (is_flip) {
+ BMO_elem_flag_enable(bm, faces[f_start_index], FACE_FLIP);
+ }
/* now that we've found our starting face, make all connected faces
* have the same winding. this is done recursively, using a manual
diff --git a/source/blender/bmesh/operators/bmo_offset_edgeloops.c b/source/blender/bmesh/operators/bmo_offset_edgeloops.c
new file mode 100644
index 00000000000..a2f3f0bb519
--- /dev/null
+++ b/source/blender/bmesh/operators/bmo_offset_edgeloops.c
@@ -0,0 +1,290 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributor(s): Campbell Barton
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/bmesh/operators/bmo_offset_edgeloops.c
+ * \ingroup bmesh
+ *
+ * Simple edge offset functionality.
+ *
+ * \note Actual offset is done by edge-slide.
+ * (this only changes topology)
+ */
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_math.h"
+#include "BLI_alloca.h"
+#include "BLI_stackdefines.h"
+
+#include "BKE_customdata.h"
+
+#include "bmesh.h"
+
+#include "intern/bmesh_operators_private.h" /* own include */
+
+#define USE_CAP_OPTION
+
+#define ELE_NEW (1 << 0)
+
+#ifdef USE_CAP_OPTION
+#define ELE_VERT_ENDPOINT (1 << 1)
+#endif
+
+/* set for debugging */
+#define OFFSET 0.0f
+
+static BMFace *bm_face_split_walk_back(
+ BMesh *bm, BMLoop *l_src,
+ BMLoop **r_l)
+{
+ float (*cos)[3];
+ BMLoop *l_dst;
+ BMFace *f;
+ int num, i;
+
+ for (l_dst = l_src->prev, num = 0; BM_elem_index_get(l_dst->prev->v) != -1; l_dst = l_dst->prev, num++) {
+ /* pass */
+ }
+
+ BLI_assert(num != 0);
+
+ cos = BLI_array_alloca(
+ cos, num);
+
+ for (l_dst = l_src->prev, i = 0; BM_elem_index_get(l_dst->prev->v) != -1; l_dst = l_dst->prev, i++) {
+ copy_v3_v3(cos[num - (i + 1)], l_dst->v->co);
+ }
+
+ f = BM_face_split_n( bm, l_src->f, l_dst->prev, l_src->next, cos, num, r_l, NULL);
+
+ return f;
+}
+
+void bmo_offset_edgeloops_exec(BMesh *bm, BMOperator *op)
+{
+ const int edges_num = BMO_slot_buffer_count(op->slots_in, "edges");
+ BMVert **verts;
+ STACK_DECLARE(verts);
+ int i;
+
+#ifdef USE_CAP_OPTION
+ bool use_cap_endpoint = BMO_slot_bool_get(op->slots_in, "use_cap_endpoint");
+ int v_edges_max = 0;
+#endif
+
+ BMOIter oiter;
+
+ /* only so we can detect new verts (index == -1) */
+ BM_mesh_elem_index_ensure(bm, BM_VERT);
+
+ BM_mesh_elem_hflag_disable_all(bm, BM_VERT | BM_EDGE | BM_FACE, BM_ELEM_TAG, false);
+
+ /* over alloc */
+ verts = MEM_mallocN(sizeof(*verts) * (edges_num * 2), __func__);
+
+ STACK_INIT(verts, (edges_num * 2));
+
+ {
+ BMEdge *e;
+ BMO_ITER (e, &oiter, op->slots_in, "edges", BM_EDGE) {
+ int j;
+
+ BM_elem_flag_enable(e, BM_ELEM_TAG);
+
+ for (j = 0; j < 2; j++) {
+ BMVert *v_edge = *(&(e->v1) + j);
+ if (!BM_elem_flag_test(v_edge, BM_ELEM_TAG)) {
+ BM_elem_flag_enable(v_edge, BM_ELEM_TAG);
+ STACK_PUSH(verts, v_edge);
+ }
+ }
+ }
+ }
+
+
+ /* -------------------------------------------------------------------- */
+ /* Remove verts only used by tagged edges */
+
+ for (i = 0; i < STACK_SIZE(verts); i++) {
+ BMIter iter;
+ int flag = 0;
+ BMEdge *e;
+
+ BM_ITER_ELEM (e, &iter, verts[i], BM_EDGES_OF_VERT) {
+ flag |= BM_elem_flag_test(e, BM_ELEM_TAG) ? 1 : 2;
+ if (flag == (1 | 2)) {
+ break;
+ }
+ }
+
+ /* only boundary verts are interesting */
+ if (flag != (1 | 2)) {
+ STACK_REMOVE(verts, i);
+ }
+ }
+
+ /* possible but unlikely we have no mixed vertices */
+ if (UNLIKELY(STACK_SIZE(verts) == 0)) {
+ MEM_freeN(verts);
+ return;
+ }
+
+ /* main loop */
+ for (i = 0; i < STACK_SIZE(verts); i++) {
+ int v_edges_num = 0;
+ int v_edges_num_untag = 0;
+ BMVert *v = verts[i];
+ BMIter iter;
+ BMEdge *e;
+
+ BM_ITER_ELEM (e, &iter, verts[i], BM_EDGES_OF_VERT) {
+ if (!BM_elem_flag_test(e, BM_ELEM_TAG)) {
+ BMVert *v_other;
+ BMIter liter;
+ BMLoop *l;
+
+ BM_ITER_ELEM (l, &liter, e, BM_LOOPS_OF_EDGE) {
+ BM_elem_flag_enable(l->f, BM_ELEM_TAG);
+ }
+
+ v_other = BM_edge_other_vert(e, v);
+ BM_edge_split(bm, e, v_other, NULL, 1.0f - OFFSET);
+ }
+ else {
+ v_edges_num_untag += 1;
+ }
+
+ v_edges_num += 1;
+ }
+
+#ifdef USE_CAP_OPTION
+ if (v_edges_num_untag == 1) {
+ BMO_elem_flag_enable(bm, v, ELE_VERT_ENDPOINT);
+ }
+
+ CLAMP_MIN(v_edges_max, v_edges_num);
+#endif
+
+ }
+
+
+ for (i = 0; i < STACK_SIZE(verts); i++) {
+ BMVert *v = verts[i];
+ BMIter liter;
+ BMLoop *l;
+
+ BM_ITER_ELEM (l, &liter, v, BM_LOOPS_OF_VERT) {
+ if (BM_elem_flag_test(l->f, BM_ELEM_TAG) &&
+ (l->f->len != 3))
+ {
+ BMFace *f_cmp = l->f;
+ if ((BM_elem_index_get(l->next->v) == -1) &&
+ (BM_elem_index_get(l->prev->v) == -1))
+ {
+#ifdef USE_CAP_OPTION
+ if (use_cap_endpoint || (BMO_elem_flag_test(bm, v, ELE_VERT_ENDPOINT) == 0))
+#endif
+ {
+ BMLoop *l_new;
+ BM_face_split(bm, l->f, l->prev, l->next, &l_new, NULL, true);
+ BLI_assert(f_cmp == l->f);
+ BLI_assert(f_cmp != l_new->f);
+ UNUSED_VARS_NDEBUG(f_cmp);
+ BMO_elem_flag_enable(bm, l_new->e, ELE_NEW);
+ }
+ }
+ else if (l->f->len > 4) {
+ if (BM_elem_flag_test(l->e, BM_ELEM_TAG) !=
+ BM_elem_flag_test(l->prev->e, BM_ELEM_TAG))
+ {
+ if (BM_elem_index_get(l->next->v) == -1) {
+ if (BM_elem_index_get(l->prev->prev->v) == -1) {
+ BMLoop *l_new;
+ BM_face_split(bm, l->f, l->prev->prev, l->next, &l_new, NULL, true);
+ BLI_assert(f_cmp == l->f);
+ BLI_assert(f_cmp != l_new->f);
+ BMO_elem_flag_enable(bm, l_new->e, ELE_NEW);
+ BM_elem_flag_disable(l->f, BM_ELEM_TAG);
+ }
+ else {
+ /* walk backwards */
+ BMLoop *l_new;
+ bm_face_split_walk_back(bm, l, &l_new);
+ do {
+ BMO_elem_flag_enable(bm, l_new->e, ELE_NEW);
+ l_new = l_new->next;
+ } while (BM_vert_is_edge_pair(l_new->v));
+ BM_elem_flag_disable(l->f, BM_ELEM_TAG);
+ }
+ }
+
+ /* Note: instead of duplicate code in alternate direction,
+ * we can be sure to hit the other vertex, so the code above runs. */
+#if 0
+ else if (BM_elem_index_get(l->prev->v) == -1) {
+ if (BM_elem_index_get(l->next->next->v) == -1) {
+ }
+ }
+#endif
+ }
+ }
+ }
+ }
+ }
+
+#ifdef USE_CAP_OPTION
+ if (use_cap_endpoint == false) {
+ BMVert **varr = BLI_array_alloca(varr, v_edges_max);
+ STACK_DECLARE(varr);
+ BMVert *v;
+
+ for (i = 0; i < STACK_SIZE(verts); i++) {
+ BMIter iter;
+ BMEdge *e;
+
+ v = verts[i];
+
+ STACK_INIT(varr, v_edges_max);
+
+ BM_ITER_ELEM (e, &iter, v, BM_EDGES_OF_VERT) {
+ BMVert *v_other;
+ v_other = BM_edge_other_vert(e, v);
+ if (BM_elem_index_get(v_other) == -1) {
+ if (BM_vert_is_edge_pair(v_other)) {
+ /* defer bmesh_jekv to avoid looping over data we're removing */
+ v_other->e = e;
+ STACK_PUSH(varr, v_other);
+ }
+ }
+ }
+
+ while ((v = STACK_POP(varr))) {
+ bmesh_jekv(bm, v->e, v, true, false);
+ }
+ }
+ }
+#endif
+
+ MEM_freeN(verts);
+
+ BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "edges.out", BM_EDGE, ELE_NEW);
+}
diff --git a/source/blender/bmesh/operators/bmo_planar_faces.c b/source/blender/bmesh/operators/bmo_planar_faces.c
new file mode 100644
index 00000000000..2856d3d18a6
--- /dev/null
+++ b/source/blender/bmesh/operators/bmo_planar_faces.c
@@ -0,0 +1,158 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/bmesh/operators/bmo_planar_faces.c
+ * \ingroup bmesh
+ *
+ * Iteratively flatten 4+ sided faces.
+ */
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_math.h"
+#include "BLI_ghash.h"
+
+#include "bmesh.h"
+
+#include "intern/bmesh_operators_private.h" /* own include */
+
+#define ELE_VERT_ADJUST (1 << 0)
+#define ELE_FACE_ADJUST (1 << 1)
+
+struct VertAccum {
+ float co[3];
+ int co_tot;
+};
+
+void bmo_planar_faces_exec(BMesh *bm, BMOperator *op)
+{
+ const float fac = BMO_slot_float_get(op->slots_in, "factor");
+ const int iterations = BMO_slot_int_get(op->slots_in, "iterations");
+ const int faces_num = BMO_slot_buffer_count(op->slots_in, "faces");
+
+ const float eps = 0.00001f;
+ const float eps_sq = SQUARE(eps);
+
+ BMOIter oiter;
+ BMFace *f;
+ BLI_mempool *vert_accum_pool;
+ GHash *vaccum_map;
+ float (*faces_center)[3];
+ int i, iter_step, shared_vert_num;
+
+ faces_center = MEM_mallocN(sizeof(*faces_center) * faces_num, __func__);
+
+ shared_vert_num = 0;
+ BMO_ITER_INDEX (f, &oiter, op->slots_in, "faces", BM_FACE, i) {
+ BMLoop *l_iter, *l_first;
+
+ if (f->len == 3) {
+ continue;
+ }
+
+ BM_face_calc_center_mean_weighted(f, faces_center[i]);
+
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
+ if (!BMO_elem_flag_test(bm, l_iter->v, ELE_VERT_ADJUST)) {
+ BMO_elem_flag_enable(bm, l_iter->v, ELE_VERT_ADJUST);
+ shared_vert_num += 1;
+ }
+ } while ((l_iter = l_iter->next) != l_first);
+
+ BMO_elem_flag_enable(bm, f, ELE_FACE_ADJUST);
+ }
+
+ vert_accum_pool = BLI_mempool_create(sizeof(struct VertAccum), 0, 512, BLI_MEMPOOL_NOP);
+ vaccum_map = BLI_ghash_ptr_new_ex(__func__, shared_vert_num);
+
+ for (iter_step = 0; iter_step < iterations; iter_step++) {
+ GHashIterator gh_iter;
+ bool changed = false;
+
+ BMO_ITER_INDEX (f, &oiter, op->slots_in, "faces", BM_FACE, i) {
+ BMLoop *l_iter, *l_first;
+ float plane[4];
+
+ if (!BMO_elem_flag_test(bm, f, ELE_FACE_ADJUST)) {
+ continue;
+ }
+ BMO_elem_flag_disable(bm, f, ELE_FACE_ADJUST);
+
+ BLI_assert(f->len != 3);
+
+ /* keep original face data (else we 'move' the face) */
+#if 0
+ BM_face_normal_update(f);
+ BM_face_calc_center_mean_weighted(f, f_center);
+#endif
+
+ plane_from_point_normal_v3(plane, faces_center[i], f->no);
+
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
+ struct VertAccum *va;
+ void **va_p;
+ float co[3];
+
+ if (!BLI_ghash_ensure_p(vaccum_map, l_iter->v, &va_p)) {
+ *va_p = BLI_mempool_calloc(vert_accum_pool);
+ }
+ va = *va_p;
+
+ closest_to_plane_normalized_v3(co, plane, l_iter->v->co);
+ va->co_tot += 1;
+
+ interp_v3_v3v3(va->co, va->co, co, 1.0f / (float)va->co_tot);
+ } while ((l_iter = l_iter->next) != l_first);
+ }
+
+ GHASH_ITER (gh_iter, vaccum_map) {
+ BMVert *v = BLI_ghashIterator_getKey(&gh_iter);
+ struct VertAccum *va = BLI_ghashIterator_getValue(&gh_iter);
+ BMIter iter;
+
+ if (len_squared_v3v3(v->co, va->co) > eps_sq) {
+ BMO_elem_flag_enable(bm, v, ELE_VERT_ADJUST);
+ interp_v3_v3v3(v->co, v->co, va->co, fac);
+ changed = true;
+ }
+
+ /* tag for re-calculation */
+ BM_ITER_ELEM (f, &iter, v, BM_FACES_OF_VERT) {
+ if (f->len != 3) {
+ BMO_elem_flag_enable(bm, f, ELE_FACE_ADJUST);
+ }
+ }
+ }
+
+ /* if nothing changed, break out early */
+ if (changed == false) {
+ break;
+ }
+
+ BLI_ghash_clear(vaccum_map, NULL, NULL);
+ BLI_mempool_clear(vert_accum_pool);
+ }
+
+ MEM_freeN(faces_center);
+ BLI_ghash_free(vaccum_map, NULL, NULL);
+ BLI_mempool_destroy(vert_accum_pool);
+}
diff --git a/source/blender/bmesh/operators/bmo_primitive.c b/source/blender/bmesh/operators/bmo_primitive.c
index e69dcca6342..2108a2c0589 100644
--- a/source/blender/bmesh/operators/bmo_primitive.c
+++ b/source/blender/bmesh/operators/bmo_primitive.c
@@ -662,78 +662,46 @@ void bmo_create_cone_exec(BMesh *bm, BMOperator *op)
void bmo_create_cube_exec(BMesh *bm, BMOperator *op)
{
- BMVert *v1, *v2, *v3, *v4, *v5, *v6, *v7, *v8;
- float vec[3], mat[4][4], off = BMO_slot_float_get(op->slots_in, "size") / 2.0f;
+ BMVert *verts[8];
+ float mat[4][4];
+ float off = BMO_slot_float_get(op->slots_in, "size") / 2.0f;
+ int i, x, y, z;
+ const char faces[6][4] = {
+ {1, 3, 2, 0},
+ {3, 7, 6, 2},
+ {7, 5, 4, 6},
+ {5, 1, 0, 4},
+ {0, 2, 6, 4},
+ {5, 7, 3, 1},
+ };
BMO_slot_mat4_get(op->slots_in, "matrix", mat);
if (!off) off = 0.5f;
+ i = 0;
- vec[0] = -off;
- vec[1] = -off;
- vec[2] = -off;
- mul_m4_v3(mat, vec);
- v1 = BM_vert_create(bm, vec, NULL, BM_CREATE_NOP);
- BMO_elem_flag_enable(bm, v1, VERT_MARK);
-
- vec[0] = -off;
- vec[1] = off;
- vec[2] = -off;
- mul_m4_v3(mat, vec);
- v2 = BM_vert_create(bm, vec, NULL, BM_CREATE_NOP);
- BMO_elem_flag_enable(bm, v2, VERT_MARK);
-
- vec[0] = off;
- vec[1] = off;
- vec[2] = -off;
- mul_m4_v3(mat, vec);
- v3 = BM_vert_create(bm, vec, NULL, BM_CREATE_NOP);
- BMO_elem_flag_enable(bm, v3, VERT_MARK);
-
- vec[0] = off;
- vec[1] = -off;
- vec[2] = -off;
- mul_m4_v3(mat, vec);
- v4 = BM_vert_create(bm, vec, NULL, BM_CREATE_NOP);
- BMO_elem_flag_enable(bm, v4, VERT_MARK);
-
- vec[0] = -off;
- vec[1] = -off;
- vec[2] = off;
- mul_m4_v3(mat, vec);
- v5 = BM_vert_create(bm, vec, NULL, BM_CREATE_NOP);
- BMO_elem_flag_enable(bm, v5, VERT_MARK);
-
- vec[0] = -off;
- vec[1] = off;
- vec[2] = off;
- mul_m4_v3(mat, vec);
- v6 = BM_vert_create(bm, vec, NULL, BM_CREATE_NOP);
- BMO_elem_flag_enable(bm, v6, VERT_MARK);
-
- vec[0] = off;
- vec[1] = off;
- vec[2] = off;
- mul_m4_v3(mat, vec);
- v7 = BM_vert_create(bm, vec, NULL, BM_CREATE_NOP);
- BMO_elem_flag_enable(bm, v7, VERT_MARK);
-
- vec[0] = off;
- vec[1] = -off;
- vec[2] = off;
- mul_m4_v3(mat, vec);
- v8 = BM_vert_create(bm, vec, NULL, BM_CREATE_NOP);
- BMO_elem_flag_enable(bm, v8, VERT_MARK);
-
- /* the four sides */
- BM_face_create_quad_tri(bm, v5, v6, v2, v1, NULL, BM_CREATE_NOP);
- BM_face_create_quad_tri(bm, v6, v7, v3, v2, NULL, BM_CREATE_NOP);
- BM_face_create_quad_tri(bm, v7, v8, v4, v3, NULL, BM_CREATE_NOP);
- BM_face_create_quad_tri(bm, v8, v5, v1, v4, NULL, BM_CREATE_NOP);
-
- /* top/bottom */
- BM_face_create_quad_tri(bm, v1, v2, v3, v4, NULL, BM_CREATE_NOP);
- BM_face_create_quad_tri(bm, v8, v7, v6, v5, NULL, BM_CREATE_NOP);
+ for (x = -1; x < 2; x += 2) {
+ for (y = -1; y < 2; y += 2) {
+ for (z = -1; z < 2; z += 2) {
+ float vec[3] = {(float)x * off, (float)y * off, (float)z * off};
+ mul_m4_v3(mat, vec);
+ verts[i] = BM_vert_create(bm, vec, NULL, BM_CREATE_NOP);
+ BMO_elem_flag_enable(bm, verts[i], VERT_MARK);
+ i++;
+ }
+ }
+ }
+
+ for (i = 0; i < ARRAY_SIZE(faces); i++) {
+ BMVert *quad[4] = {
+ verts[faces[i][0]],
+ verts[faces[i][1]],
+ verts[faces[i][2]],
+ verts[faces[i][3]],
+ };
+
+ BM_face_create_verts(bm, quad, 4, NULL, BM_CREATE_NOP, true);
+ }
BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "verts.out", BM_VERT, VERT_MARK);
}
diff --git a/source/blender/bmesh/operators/bmo_removedoubles.c b/source/blender/bmesh/operators/bmo_removedoubles.c
index 75f9feef413..42373ad0ef0 100644
--- a/source/blender/bmesh/operators/bmo_removedoubles.c
+++ b/source/blender/bmesh/operators/bmo_removedoubles.c
@@ -29,9 +29,9 @@
#include "MEM_guardedalloc.h"
#include "BLI_math.h"
-#include "BLI_array.h"
#include "BLI_alloca.h"
#include "BLI_stackdefines.h"
+#include "BLI_stack.h"
#include "BKE_customdata.h"
@@ -198,7 +198,7 @@ void bmo_weld_verts_exec(BMesh *bm, BMOperator *op)
BMO_elem_flag_enable(bm, e, EDGE_COL);
}
else if (!BM_edge_exists(v1, v2)) {
- BM_edge_create(bm, v1, v2, e, BM_CREATE_NO_DOUBLE);
+ BM_edge_create(bm, v1, v2, e, BM_CREATE_NOP);
}
BMO_elem_flag_enable(bm, e, ELE_DEL);
@@ -238,7 +238,7 @@ void bmo_weld_verts_exec(BMesh *bm, BMOperator *op)
static int vergaverco(const void *e1, const void *e2)
{
- const BMVert *v1 = *(void **)e1, *v2 = *(void **)e2;
+ const BMVert *v1 = *(const void **)e1, *v2 = *(const void **)e2;
float x1 = v1->co[0] + v1->co[1] + v1->co[2];
float x2 = v2->co[0] + v2->co[1] + v2->co[2];
@@ -261,7 +261,7 @@ void bmo_pointmerge_facedata_exec(BMesh *bm, BMOperator *op)
BMOIter siter;
BMIter iter;
BMVert *v, *vert_snap;
- BMLoop *l, *firstl = NULL;
+ BMLoop *l, *l_first = NULL;
float fac;
int i, tot;
@@ -273,33 +273,35 @@ void bmo_pointmerge_facedata_exec(BMesh *bm, BMOperator *op)
fac = 1.0f / tot;
BM_ITER_ELEM (l, &iter, vert_snap, BM_LOOPS_OF_VERT) {
- if (!firstl) {
- firstl = l;
+ if (l_first == NULL) {
+ l_first = l;
}
for (i = 0; i < bm->ldata.totlayer; i++) {
if (CustomData_layer_has_math(&bm->ldata, i)) {
- int type = bm->ldata.layers[i].type;
+ const int type = bm->ldata.layers[i].type;
+ const int offset = bm->ldata.layers[i].offset;
void *e1, *e2;
- e1 = CustomData_bmesh_get_layer_n(&bm->ldata, firstl->head.data, i);
- e2 = CustomData_bmesh_get_layer_n(&bm->ldata, l->head.data, i);
+ e1 = BM_ELEM_CD_GET_VOID_P(l_first, offset);
+ e2 = BM_ELEM_CD_GET_VOID_P(l, offset);
CustomData_data_multiply(type, e2, fac);
- if (l != firstl)
+ if (l != l_first) {
CustomData_data_add(type, e1, e2);
+ }
}
}
}
BMO_ITER (v, &siter, op->slots_in, "verts", BM_VERT) {
BM_ITER_ELEM (l, &iter, v, BM_LOOPS_OF_VERT) {
- if (l == firstl) {
+ if (l == l_first) {
continue;
}
- CustomData_bmesh_copy_data(&bm->ldata, &bm->ldata, firstl->head.data, &l->head.data);
+ CustomData_bmesh_copy_data(&bm->ldata, &bm->ldata, l_first->head.data, &l->head.data);
}
}
}
@@ -311,19 +313,20 @@ void bmo_average_vert_facedata_exec(BMesh *bm, BMOperator *op)
BMVert *v;
BMLoop *l /* , *firstl = NULL */;
CDBlockBytes min, max;
- void *block;
- int i, type;
+ int i;
for (i = 0; i < bm->ldata.totlayer; i++) {
+ const int type = bm->ldata.layers[i].type;
+ const int offset = bm->ldata.layers[i].offset;
+
if (!CustomData_layer_has_math(&bm->ldata, i))
continue;
- type = bm->ldata.layers[i].type;
CustomData_data_initminmax(type, &min, &max);
BMO_ITER (v, &siter, op->slots_in, "verts", BM_VERT) {
BM_ITER_ELEM (l, &iter, v, BM_LOOPS_OF_VERT) {
- block = CustomData_bmesh_get_layer_n(&bm->ldata, l->head.data, i);
+ void *block = BM_ELEM_CD_GET_VOID_P(l, offset);
CustomData_data_dominmax(type, block, &min, &max);
}
}
@@ -334,7 +337,7 @@ void bmo_average_vert_facedata_exec(BMesh *bm, BMOperator *op)
BMO_ITER (v, &siter, op->slots_in, "verts", BM_VERT) {
BM_ITER_ELEM (l, &iter, v, BM_LOOPS_OF_VERT) {
- block = CustomData_bmesh_get_layer_n(&bm->ldata, l->head.data, i);
+ void *block = BM_ELEM_CD_GET_VOID_P(l, offset);
CustomData_data_copy_value(type, &min, block);
}
}
@@ -375,13 +378,14 @@ void bmo_collapse_exec(BMesh *bm, BMOperator *op)
BMOperator weldop;
BMWalker walker;
BMIter iter;
- BMEdge *e, **edges = NULL;
- BLI_array_declare(edges);
- float min[3], max[3], center[3];
- unsigned int i, tot;
+ BMEdge *e;
+ BLI_Stack *edge_stack;
BMOpSlot *slot_targetmap;
-
- BMO_op_callf(bm, op->flag, "collapse_uvs edges=%s", op, "edges");
+
+ if (BMO_slot_bool_get(op->slots_in, "uvs")) {
+ BMO_op_callf(bm, op->flag, "collapse_uvs edges=%s", op, "edges");
+ }
+
BMO_op_init(bm, &weldop, op->flag, "weld_verts");
slot_targetmap = BMO_slot_get(weldop.slots_in, "targetmap");
@@ -392,18 +396,20 @@ void bmo_collapse_exec(BMesh *bm, BMOperator *op)
BMW_FLAG_NOP, /* no need to use BMW_FLAG_TEST_HIDDEN, already marked data */
BMW_NIL_LAY);
+ edge_stack = BLI_stack_new(sizeof(BMEdge *), __func__);
+
BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
+ float min[3], max[3], center[3];
BMVert *v_tar;
if (!BMO_elem_flag_test(bm, e, EDGE_MARK))
continue;
- BLI_array_empty(edges);
+ BLI_assert(BLI_stack_is_empty(edge_stack));
INIT_MINMAX(min, max);
- for (e = BMW_begin(&walker, e->v1), tot = 0; e; e = BMW_step(&walker), tot++) {
- BLI_array_grow_one(edges);
- edges[tot] = e;
+ for (e = BMW_begin(&walker, e->v1); e; e = BMW_step(&walker)) {
+ BLI_stack_push(edge_stack, &e);
minmax_v3v3_v3(min, max, e->v1->co);
minmax_v3v3_v3(min, max, e->v2->co);
@@ -413,79 +419,90 @@ void bmo_collapse_exec(BMesh *bm, BMOperator *op)
BM_elem_flag_disable(e->v2, BM_ELEM_TAG);
}
- mid_v3_v3v3(center, min, max);
+ if (!BLI_stack_is_empty(edge_stack)) {
+
+ mid_v3_v3v3(center, min, max);
- /* snap edges to a point. for initial testing purposes anyway */
- v_tar = edges[0]->v1;
+ /* snap edges to a point. for initial testing purposes anyway */
+ e = *(BMEdge **)BLI_stack_peek(edge_stack);
+ v_tar = e->v1;
- for (i = 0; i < tot; i++) {
- unsigned int j;
+ while (!BLI_stack_is_empty(edge_stack)) {
+ unsigned int j;
+ BLI_stack_pop(edge_stack, &e);
- for (j = 0; j < 2; j++) {
- BMVert *v_src = *((&edges[i]->v1) + j);
+ for (j = 0; j < 2; j++) {
+ BMVert *v_src = *((&e->v1) + j);
- copy_v3_v3(v_src->co, center);
- if ((v_src != v_tar) && !BM_elem_flag_test(v_src, BM_ELEM_TAG)) {
- BM_elem_flag_enable(v_src, BM_ELEM_TAG);
- BMO_slot_map_elem_insert(&weldop, slot_targetmap, v_src, v_tar);
+ copy_v3_v3(v_src->co, center);
+ if ((v_src != v_tar) && !BM_elem_flag_test(v_src, BM_ELEM_TAG)) {
+ BM_elem_flag_enable(v_src, BM_ELEM_TAG);
+ BMO_slot_map_elem_insert(&weldop, slot_targetmap, v_src, v_tar);
+ }
}
}
}
}
-
+
+ BLI_stack_free(edge_stack);
+
BMO_op_exec(bm, &weldop);
BMO_op_finish(bm, &weldop);
BMW_end(&walker);
- BLI_array_free(edges);
}
/* uv collapse function */
static void bmo_collapsecon_do_layer(BMesh *bm, const int layer, const short oflag)
{
+ const int type = bm->ldata.layers[layer].type;
+ const int offset = bm->ldata.layers[layer].offset;
BMIter iter, liter;
BMFace *f;
BMLoop *l, *l2;
BMWalker walker;
- void **blocks = NULL;
- BLI_array_declare(blocks);
+ BLI_Stack *block_stack;
CDBlockBytes min, max;
- int i, tot, type = bm->ldata.layers[layer].type;
BMW_init(&walker, bm, BMW_LOOPDATA_ISLAND,
BMW_MASK_NOP, oflag, BMW_MASK_NOP,
BMW_FLAG_NOP, /* no need to use BMW_FLAG_TEST_HIDDEN, already marked data */
layer);
+ block_stack = BLI_stack_new(sizeof(void *), __func__);
+
BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) {
if (BMO_elem_flag_test(bm, l->e, oflag)) {
/* walk */
- BLI_array_empty(blocks);
+ BLI_assert(BLI_stack_is_empty(block_stack));
CustomData_data_initminmax(type, &min, &max);
- for (l2 = BMW_begin(&walker, l), tot = 0; l2; l2 = BMW_step(&walker), tot++) {
- BLI_array_grow_one(blocks);
- blocks[tot] = CustomData_bmesh_get_layer_n(&bm->ldata, l2->head.data, layer);
- CustomData_data_dominmax(type, blocks[tot], &min, &max);
+ for (l2 = BMW_begin(&walker, l); l2; l2 = BMW_step(&walker)) {
+ void *block = BM_ELEM_CD_GET_VOID_P(l2, offset);
+ CustomData_data_dominmax(type, block, &min, &max);
+ BLI_stack_push(block_stack, &block);
}
- if (tot) {
+ if (!BLI_stack_is_empty(block_stack)) {
CustomData_data_multiply(type, &min, 0.5f);
CustomData_data_multiply(type, &max, 0.5f);
CustomData_data_add(type, &min, &max);
/* snap CD (uv, vcol) points to their centroid */
- for (i = 0; i < tot; i++) {
- CustomData_data_copy_value(type, &min, blocks[i]);
+ while (!BLI_stack_is_empty(block_stack)) {
+ void *block;
+ BLI_stack_pop(block_stack, &block);
+ CustomData_data_copy_value(type, &min, block);
}
}
}
}
}
+ BLI_stack_free(block_stack);
+
BMW_end(&walker);
- BLI_array_free(blocks);
}
void bmo_collapse_uvs_exec(BMesh *bm, BMOperator *op)
@@ -519,8 +536,9 @@ void bmo_collapse_uvs_exec(BMesh *bm, BMOperator *op)
}
-static void bmesh_find_doubles_common(BMesh *bm, BMOperator *op,
- BMOperator *optarget, BMOpSlot *optarget_slot)
+static void bmesh_find_doubles_common(
+ BMesh *bm, BMOperator *op,
+ BMOperator *optarget, BMOpSlot *optarget_slot)
{
BMVert **verts;
int verts_len;
@@ -529,7 +547,7 @@ static void bmesh_find_doubles_common(BMesh *bm, BMOperator *op,
const float dist = BMO_slot_float_get(op->slots_in, "dist");
const float dist_sq = dist * dist;
- const float dist3 = (M_SQRT3 + 0.00005f) * dist; /* Just above sqrt(3) */
+ const float dist3 = ((float)M_SQRT3 + 0.00005f) * dist; /* Just above sqrt(3) */
/* Test whether keep_verts arg exists and is non-empty */
if (BMO_slot_exists(op->slots_in, "keep_verts")) {
diff --git a/source/blender/bmesh/operators/bmo_similar.c b/source/blender/bmesh/operators/bmo_similar.c
index f779828a00d..708d57a7a08 100644
--- a/source/blender/bmesh/operators/bmo_similar.c
+++ b/source/blender/bmesh/operators/bmo_similar.c
@@ -102,7 +102,6 @@ void bmo_similar_faces_exec(BMesh *bm, BMOperator *op)
float angle = 0.0f;
SimSel_FaceExt *f_ext = NULL;
int *indices = NULL;
- float t_no[3]; /* temporary normal */
const int type = BMO_slot_int_get(op->slots_in, "type");
const float thresh = BMO_slot_float_get(op->slots_in, "thresh");
const float thresh_radians = thresh * (float)M_PI;
@@ -115,7 +114,7 @@ void bmo_similar_faces_exec(BMesh *bm, BMOperator *op)
num_total = BM_mesh_elem_count(bm, BM_FACE);
/*
- * The first thing to do is to iterate through all the the selected items and mark them since
+ * The first thing to do is to iterate through all the selected items and mark them since
* they will be in the selection anyway.
* This will increase performance, (especially when the number of originally selected faces is high)
* so the overall complexity will be less than $O(mn)$ where is the total number of selected faces,
@@ -158,12 +157,8 @@ void bmo_similar_faces_exec(BMesh *bm, BMOperator *op)
/* compute the center of the polygon */
BM_face_calc_center_mean(f_ext[i].f, f_ext[i].c);
- /* normalize the polygon normal */
- copy_v3_v3(t_no, f_ext[i].f->no);
- normalize_v3(t_no);
-
/* compute the plane distance */
- f_ext[i].d = dot_v3v3(t_no, f_ext[i].c);
+ f_ext[i].d = dot_v3v3(f_ext[i].f->no, f_ext[i].c);
break;
case SIMFACE_AREA:
@@ -212,16 +207,23 @@ void bmo_similar_faces_exec(BMesh *bm, BMOperator *op)
break;
case SIMFACE_COPLANAR:
+ {
+ float sign = 1.0f;
angle = angle_normalized_v3v3(fs->no, fm->no); /* angle -> 0 */
+ /* allow for normal pointing in either direction (just check the plane) */
+ if (angle > (float)M_PI * 0.5f) {
+ angle = (float)M_PI - angle;
+ sign = -1.0f;
+ }
if (angle <= thresh_radians) { /* and dot product difference -> 0 */
- delta_fl = f_ext[i].d - f_ext[indices[idx]].d;
+ delta_fl = f_ext[i].d - (f_ext[indices[idx]].d * sign);
if (bm_sel_similar_cmp_fl(delta_fl, thresh, compare)) {
BMO_elem_flag_enable(bm, fm, FACE_MARK);
cont = false;
}
}
break;
-
+ }
case SIMFACE_AREA:
delta_fl = f_ext[i].area - f_ext[indices[idx]].area;
if (bm_sel_similar_cmp_fl(delta_fl, thresh, compare)) {
@@ -245,6 +247,13 @@ void bmo_similar_faces_exec(BMesh *bm, BMOperator *op)
cont = false;
}
break;
+
+ case SIMFACE_SMOOTH:
+ if (BM_elem_flag_test(fm, BM_ELEM_SMOOTH) == BM_elem_flag_test(fs, BM_ELEM_SMOOTH)) {
+ BMO_elem_flag_enable(bm, fm, FACE_MARK);
+ cont = false;
+ }
+ break;
#ifdef WITH_FREESTYLE
case SIMFACE_FREESTYLE:
if (CustomData_has_layer(&bm->pdata, CD_FREESTYLE_FACE)) {
@@ -405,10 +414,10 @@ void bmo_similar_edges_exec(BMesh *bm, BMOperator *op)
/* compute the angle between the two edges */
angle = angle_normalized_v3v3(e_ext[i].dir, e_ext[indices[idx]].dir);
- if (angle > (float)(M_PI / 2.0)) /* use the smallest angle between the edges */
+ if (angle > (float)M_PI_2) /* use the smallest angle between the edges */
angle = fabsf(angle - (float)M_PI);
- if (angle / (float)(M_PI / 2.0) <= thresh) {
+ if (angle / (float)M_PI_2 <= thresh) {
BMO_elem_flag_enable(bm, e, EDGE_MARK);
cont = false;
}
diff --git a/source/blender/bmesh/operators/bmo_subdivide.c b/source/blender/bmesh/operators/bmo_subdivide.c
index fc507cdbd21..45e3c8d193d 100644
--- a/source/blender/bmesh/operators/bmo_subdivide.c
+++ b/source/blender/bmesh/operators/bmo_subdivide.c
@@ -32,6 +32,7 @@
#include "BLI_rand.h"
#include "BLI_array.h"
#include "BLI_noise.h"
+#include "BLI_stack.h"
#include "BKE_customdata.h"
@@ -79,8 +80,9 @@ static void bmo_subd_init_shape_info(BMesh *bm, SubDParams *params)
}
-typedef void (*subd_pattern_fill_fp)(BMesh *bm, BMFace *face, BMVert **verts,
- const SubDParams *params);
+typedef void (*subd_pattern_fill_fp)(
+ BMesh *bm, BMFace *face, BMVert **verts,
+ const SubDParams *params);
/*
* note: this is a pattern-based edge subdivider.
@@ -162,10 +164,11 @@ static BMEdge *connect_smallest_face(BMesh *bm, BMVert *v_a, BMVert *v_b, BMFace
return NULL;
}
/* calculates offset for co, based on fractal, sphere or smooth settings */
-static void alter_co(BMVert *v, BMEdge *UNUSED(origed), const SubDParams *params, float perc,
- BMVert *vsta, BMVert *vend)
+static void alter_co(
+ BMVert *v, BMEdge *UNUSED(e_orig),
+ const SubDParams *params, const float perc,
+ const BMVert *v_a, const BMVert *v_b)
{
- float tvec[3], fac;
float *co = BM_ELEM_CD_GET_VOID_P(v, params->shape_info.cd_vert_shape_offset_tmp);
int i;
@@ -177,28 +180,26 @@ static void alter_co(BMVert *v, BMEdge *UNUSED(origed), const SubDParams *params
}
else if (params->use_smooth) {
/* we calculate an offset vector vec1[], to be added to *co */
- float len, nor[3], nor1[3], nor2[3], val;
+ float dir[3], tvec[3];
+ float fac, len, val;
- sub_v3_v3v3(nor, vsta->co, vend->co);
- len = 0.5f * normalize_v3(nor);
-
- copy_v3_v3(nor1, vsta->no);
- copy_v3_v3(nor2, vend->no);
+ sub_v3_v3v3(dir, v_a->co, v_b->co);
+ len = (float)M_SQRT1_2 * normalize_v3(dir);
/* cosine angle */
- fac = dot_v3v3(nor, nor1);
- mul_v3_v3fl(tvec, nor1, fac);
+ fac = dot_v3v3(dir, v_a->no);
+ mul_v3_v3fl(tvec, v_a->no, fac);
/* cosine angle */
- fac = -dot_v3v3(nor, nor2);
- madd_v3_v3fl(tvec, nor2, fac);
+ fac = -dot_v3v3(dir, v_b->no);
+ madd_v3_v3fl(tvec, v_b->no, fac);
/* falloff for multi subdivide */
val = fabsf(1.0f - 2.0f * fabsf(0.5f - perc));
val = bmesh_subd_falloff_calc(params->smooth_falloff, val);
if (params->use_smooth_even) {
- val *= BM_vert_calc_shell_factor(v);
+ val *= shell_v3v3_mid_normalized_to_dist(v_a->no, v_b->no);
}
mul_v3_fl(tvec, params->smooth * val * len);
@@ -207,12 +208,13 @@ static void alter_co(BMVert *v, BMEdge *UNUSED(origed), const SubDParams *params
}
if (params->use_fractal) {
- const float len = len_v3v3(vsta->co, vend->co);
- float normal[3], co2[3], base1[3], base2[3];
+ float normal[3], co2[3], base1[3], base2[3], tvec[3];
+ const float len = len_v3v3(v_a->co, v_b->co);
+ float fac;
fac = params->fractal * len;
- mid_v3_v3v3(normal, vsta->no, vend->no);
+ mid_v3_v3v3(normal, v_a->no, v_b->no);
ortho_basis_v3v3_v3(base1, base2, normal);
add_v3_v3v3(co2, v->co, params->fractal_ofs);
@@ -233,9 +235,12 @@ static void alter_co(BMVert *v, BMEdge *UNUSED(origed), const SubDParams *params
* this by getting the normals and coords for each shape key and
* re-calculate the smooth value for each but this is quite involved.
* for now its ok to simply apply the difference IMHO - campbell */
- sub_v3_v3v3(tvec, v->co, co);
if (params->shape_info.totlayer > 1) {
+ float tvec[3];
+
+ sub_v3_v3v3(tvec, v->co, co);
+
/* skip the last layer since its the temp */
i = params->shape_info.totlayer - 1;
co = BM_ELEM_CD_GET_VOID_P(v, params->shape_info.cd_vert_shape_offset);
@@ -249,19 +254,21 @@ static void alter_co(BMVert *v, BMEdge *UNUSED(origed), const SubDParams *params
/* assumes in the edge is the correct interpolated vertices already */
/* percent defines the interpolation, rad and flag are for special options */
/* results in new vertex with correct coordinate, vertex normal and weight group info */
-static BMVert *bm_subdivide_edge_addvert(BMesh *bm, BMEdge *edge, BMEdge *oedge,
- const SubDParams *params, float percent,
- float percent2,
- BMEdge **out, BMVert *vsta, BMVert *vend)
+static BMVert *bm_subdivide_edge_addvert(
+ BMesh *bm, BMEdge *edge, BMEdge *e_orig,
+ const SubDParams *params,
+ const float factor_edge_split, const float factor_subd,
+ BMVert *v_a, BMVert *v_b,
+ BMEdge **r_edge)
{
- BMVert *ev;
+ BMVert *v_new;
- ev = BM_edge_split(bm, edge, edge->v1, out, percent);
+ v_new = BM_edge_split(bm, edge, edge->v1, r_edge, factor_edge_split);
- BMO_elem_flag_enable(bm, ev, ELE_INNER);
+ BMO_elem_flag_enable(bm, v_new, ELE_INNER);
/* offset for smooth or sphere or fractal */
- alter_co(ev, oedge, params, percent2, vsta, vend);
+ alter_co(v_new, e_orig, params, factor_subd, v_a, v_b);
#if 0 //BMESH_TODO
/* clip if needed by mirror modifier */
@@ -278,35 +285,40 @@ static BMVert *bm_subdivide_edge_addvert(BMesh *bm, BMEdge *edge, BMEdge *oedge,
}
#endif
- interp_v3_v3v3(ev->no, vsta->no, vend->no, percent2);
- normalize_v3(ev->no);
+ interp_v3_v3v3(v_new->no, v_a->no, v_b->no, factor_subd);
+ normalize_v3(v_new->no);
- return ev;
+ return v_new;
}
-static BMVert *subdivideedgenum(BMesh *bm, BMEdge *edge, BMEdge *oedge,
- int curpoint, int totpoint, const SubDParams *params,
- BMEdge **newe, BMVert *vsta, BMVert *vend)
+static BMVert *subdivide_edge_num(
+ BMesh *bm, BMEdge *edge, BMEdge *e_orig,
+ int curpoint, int totpoint, const SubDParams *params,
+ BMVert *v_a, BMVert *v_b,
+ BMEdge **r_edge)
{
- BMVert *ev;
- float percent, percent2 = 0.0f;
+ BMVert *v_new;
+ float factor_edge_split, factor_subd;
if (BMO_elem_flag_test(bm, edge, EDGE_PERCENT) && totpoint == 1) {
- percent = BMO_slot_map_float_get(params->slot_edge_percents, edge);
+ factor_edge_split = BMO_slot_map_float_get(params->slot_edge_percents, edge);
+ factor_subd = 0.0f;
}
else {
- percent = 1.0f / (float)(totpoint + 1 - curpoint);
- percent2 = (float)(curpoint + 1) / (float)(totpoint + 1);
-
+ factor_edge_split = 1.0f / (float)(totpoint + 1 - curpoint);
+ factor_subd = (float)(curpoint + 1) / (float)(totpoint + 1);
}
- ev = bm_subdivide_edge_addvert(bm, edge, oedge, params, percent,
- percent2, newe, vsta, vend);
- return ev;
+ v_new = bm_subdivide_edge_addvert(
+ bm, edge, e_orig, params,
+ factor_edge_split, factor_subd,
+ v_a, v_b, r_edge);
+ return v_new;
}
-static void bm_subdivide_multicut(BMesh *bm, BMEdge *edge, const SubDParams *params,
- BMVert *vsta, BMVert *vend)
+static void bm_subdivide_multicut(
+ BMesh *bm, BMEdge *edge, const SubDParams *params,
+ BMVert *v_a, BMVert *v_b)
{
BMEdge *eed = edge, *e_new, e_tmp = *edge;
BMVert *v, v1_tmp = *edge->v1, v2_tmp = *edge->v2, *v1 = edge->v1, *v2 = edge->v2;
@@ -316,15 +328,11 @@ static void bm_subdivide_multicut(BMesh *bm, BMEdge *edge, const SubDParams *par
e_tmp.v2 = &v2_tmp;
for (i = 0; i < numcuts; i++) {
- v = subdivideedgenum(bm, eed, &e_tmp, i, params->numcuts, params, &e_new, vsta, vend);
-
- BMO_elem_flag_enable(bm, v, SUBD_SPLIT);
- BMO_elem_flag_enable(bm, eed, SUBD_SPLIT);
- BMO_elem_flag_enable(bm, e_new, SUBD_SPLIT);
+ v = subdivide_edge_num(bm, eed, &e_tmp, i, params->numcuts, params, v_a, v_b, &e_new);
- BMO_elem_flag_enable(bm, v, ELE_SPLIT);
- BMO_elem_flag_enable(bm, eed, ELE_SPLIT);
- BMO_elem_flag_enable(bm, e_new, SUBD_SPLIT);
+ BMO_elem_flag_enable(bm, v, SUBD_SPLIT | ELE_SPLIT);
+ BMO_elem_flag_enable(bm, eed, SUBD_SPLIT | ELE_SPLIT);
+ BMO_elem_flag_enable(bm, e_new, SUBD_SPLIT | ELE_SPLIT);
BM_CHECK_ELEMENT(v);
if (v->e) BM_CHECK_ELEMENT(v->e);
@@ -437,7 +445,7 @@ static void quad_2edge_split_innervert(BMesh *bm, BMFace *UNUSED(face), BMVert *
e = connect_smallest_face(bm, verts[i], verts[numcuts + (numcuts - i)], &f_new);
e_tmp = *e;
- v = bm_subdivide_edge_addvert(bm, e, &e_tmp, params, 0.5f, 0.5f, &e_new, e->v1, e->v2);
+ v = bm_subdivide_edge_addvert(bm, e, &e_tmp, params, 0.5f, 0.5f, e->v1, e->v2, &e_new);
if (i != numcuts - 1) {
connect_smallest_face(bm, v_last, v, &f_new);
@@ -580,8 +588,7 @@ static void quad_4edge_subdivide(BMesh *bm, BMFace *UNUSED(face), BMVert **verts
e_tmp = *e;
for (a = 0; a < numcuts; a++) {
- v = subdivideedgenum(bm, e, &e_tmp, a, numcuts, params, &e_new,
- v1, v2);
+ v = subdivide_edge_num(bm, e, &e_tmp, a, numcuts, params, v1, v2, &e_new);
BMESH_ASSERT(v != NULL);
@@ -688,8 +695,7 @@ static void tri_3edge_subdivide(BMesh *bm, BMFace *UNUSED(face), BMVert **verts,
e_tmp.v1 = &v1_tmp;
e_tmp.v2 = &v2_tmp;
for (j = 0; j < i; j++) {
- v = subdivideedgenum(bm, e, &e_tmp, j, i, params, &e_new,
- verts[a], verts[b]);
+ v = subdivide_edge_num(bm, e, &e_tmp, j, i, params, verts[a], verts[b], &e_new);
lines[i + 1][j + 1] = v;
BMO_elem_flag_enable(bm, e_new, ELE_INNER);
@@ -766,8 +772,7 @@ void bmo_subdivide_edges_exec(BMesh *bm, BMOperator *op)
BMOpSlot *einput;
const SubDPattern *pat;
SubDParams params;
- SubDFaceData *facedata = NULL;
- BLI_array_declare(facedata);
+ BLI_Stack *facedata;
BMIter viter, fiter, liter;
BMVert *v, **verts = NULL;
BMEdge *edge;
@@ -782,7 +787,7 @@ void bmo_subdivide_edges_exec(BMesh *bm, BMOperator *op)
BLI_array_declare(verts);
float smooth, fractal, along_normal;
bool use_sphere, use_single_edge, use_grid_fill, use_only_quads;
- int cornertype, seed, i, j, matched, a, b, numcuts, totesel, smooth_falloff;
+ int cornertype, seed, i, j, a, b, numcuts, totesel, smooth_falloff;
BMO_slot_buffer_flag_enable(bm, op->slots_in, "edges", BM_EDGE, SUBD_SPLIT);
@@ -802,13 +807,13 @@ void bmo_subdivide_edges_exec(BMesh *bm, BMOperator *op)
patterns[1] = NULL;
/* straight cut is patterns[1] == NULL */
switch (cornertype) {
- case SUBD_PATH:
+ case SUBD_CORNER_PATH:
patterns[1] = &quad_2edge_path;
break;
- case SUBD_INNERVERT:
+ case SUBD_CORNER_INNERVERT:
patterns[1] = &quad_2edge_innervert;
break;
- case SUBD_FAN:
+ case SUBD_CORNER_FAN:
patterns[1] = &quad_2edge_fan;
break;
}
@@ -875,9 +880,12 @@ void bmo_subdivide_edges_exec(BMesh *bm, BMOperator *op)
BM_EDGE, EDGE_PERCENT);
+ facedata = BLI_stack_new(sizeof(SubDFaceData), __func__);
+
BM_ITER_MESH (face, &fiter, bm, BM_FACES_OF_MESH) {
BMEdge *e1 = NULL, *e2 = NULL;
float vec1[3], vec2[3];
+ bool matched = false;
/* skip non-quads if requested */
if (use_only_quads && face->len != 4)
@@ -891,8 +899,6 @@ void bmo_subdivide_edges_exec(BMesh *bm, BMOperator *op)
BLI_array_grow_items(edges, face->len);
BLI_array_grow_items(verts, face->len);
- matched = 0;
-
totesel = 0;
BM_ITER_ELEM_INDEX (l_new, &liter, face, BM_LOOPS_OF_FACE, i) {
edges[i] = l_new->e;
@@ -930,12 +936,13 @@ void bmo_subdivide_edges_exec(BMesh *bm, BMOperator *op)
}
}
if (matched) {
- BLI_array_grow_one(facedata);
- b = BLI_array_count(facedata) - 1;
- facedata[b].pat = pat;
- facedata[b].start = verts[i];
- facedata[b].face = face;
- facedata[b].totedgesel = totesel;
+ SubDFaceData *fd;
+
+ fd = BLI_stack_push_r(facedata);
+ fd->pat = pat;
+ fd->start = verts[i];
+ fd->face = face;
+ fd->totedgesel = totesel;
BMO_elem_flag_enable(bm, face, SUBD_SPLIT);
break;
}
@@ -966,15 +973,15 @@ void bmo_subdivide_edges_exec(BMesh *bm, BMOperator *op)
}
}
if (matched) {
- BLI_array_grow_one(facedata);
- j = BLI_array_count(facedata) - 1;
+ SubDFaceData *fd;
BMO_elem_flag_enable(bm, face, SUBD_SPLIT);
- facedata[j].pat = pat;
- facedata[j].start = verts[a];
- facedata[j].face = face;
- facedata[j].totedgesel = totesel;
+ fd = BLI_stack_push_r(facedata);
+ fd->pat = pat;
+ fd->start = verts[a];
+ fd->face = face;
+ fd->totedgesel = totesel;
break;
}
}
@@ -982,16 +989,16 @@ void bmo_subdivide_edges_exec(BMesh *bm, BMOperator *op)
}
if (!matched && totesel) {
- BLI_array_grow_one(facedata);
- j = BLI_array_count(facedata) - 1;
+ SubDFaceData *fd;
BMO_elem_flag_enable(bm, face, SUBD_SPLIT);
/* must initialize all members here */
- facedata[j].start = NULL;
- facedata[j].pat = NULL;
- facedata[j].totedgesel = totesel;
- facedata[j].face = face;
+ fd = BLI_stack_push_r(facedata);
+ fd->start = NULL;
+ fd->pat = NULL;
+ fd->totedgesel = totesel;
+ fd->face = face;
}
}
@@ -1009,16 +1016,17 @@ void bmo_subdivide_edges_exec(BMesh *bm, BMOperator *op)
copy_v3_v3(v->co, co);
}
- i = 0;
- for (i = 0; i < BLI_array_count(facedata); i++) {
- face = facedata[i].face;
+ for (; !BLI_stack_is_empty(facedata); BLI_stack_discard(facedata)) {
+ SubDFaceData *fd = BLI_stack_peek(facedata);
+
+ face = fd->face;
/* figure out which pattern to use */
BLI_array_empty(verts);
- pat = facedata[i].pat;
+ pat = fd->pat;
- if (!pat && facedata[i].totedgesel == 2) {
+ if (!pat && fd->totedgesel == 2) {
int vlen;
/* ok, no pattern. we still may be able to do something */
@@ -1079,7 +1087,7 @@ void bmo_subdivide_edges_exec(BMesh *bm, BMOperator *op)
BMIter other_fiter;
BM_ITER_ELEM (other_loop, &other_fiter, loops[a]->v, BM_LOOPS_OF_VERT) {
if (other_loop->f != face) {
- if (BM_vert_in_face(other_loop->f, loops[b]->v)) {
+ if (BM_vert_in_face(loops[b]->v, other_loop->f)) {
/* we assume that these verts are not making an edge in the face */
BLI_assert(other_loop->prev->v != loops[a]->v);
BLI_assert(other_loop->next->v != loops[a]->v);
@@ -1131,7 +1139,7 @@ void bmo_subdivide_edges_exec(BMesh *bm, BMOperator *op)
a = 0;
BM_ITER_ELEM_INDEX (l_new, &liter, face, BM_LOOPS_OF_FACE, j) {
- if (l_new->v == facedata[i].start) {
+ if (l_new->v == fd->start) {
a = j + 1;
break;
}
@@ -1156,7 +1164,7 @@ void bmo_subdivide_edges_exec(BMesh *bm, BMOperator *op)
BM_data_layer_free_n(bm, &bm->vdata, CD_SHAPEKEY, params.shape_info.tmpkey);
- if (facedata) BLI_array_free(facedata);
+ BLI_stack_free(facedata);
if (edges) BLI_array_free(edges);
if (verts) BLI_array_free(verts);
BLI_array_free(loops_split);
@@ -1169,14 +1177,15 @@ void bmo_subdivide_edges_exec(BMesh *bm, BMOperator *op)
}
/* editmesh-emulating function */
-void BM_mesh_esubdivide(BMesh *bm, const char edge_hflag,
- const float smooth, const short smooth_falloff, const bool use_smooth_even,
- const float fractal, const float along_normal,
- const int numcuts,
- const int seltype, const int cornertype,
- const short use_single_edge, const short use_grid_fill,
- const short use_only_quads,
- const int seed)
+void BM_mesh_esubdivide(
+ BMesh *bm, const char edge_hflag,
+ const float smooth, const short smooth_falloff, const bool use_smooth_even,
+ const float fractal, const float along_normal,
+ const int numcuts,
+ const int seltype, const int cornertype,
+ const short use_single_edge, const short use_grid_fill,
+ const short use_only_quads,
+ const int seed)
{
BMOperator op;
diff --git a/source/blender/bmesh/operators/bmo_subdivide_edgering.c b/source/blender/bmesh/operators/bmo_subdivide_edgering.c
index c01ad10d716..0e619b4cece 100644
--- a/source/blender/bmesh/operators/bmo_subdivide_edgering.c
+++ b/source/blender/bmesh/operators/bmo_subdivide_edgering.c
@@ -80,8 +80,9 @@ static unsigned int bm_verts_tag_count(BMesh *bm)
}
#endif
-static float bezier_handle_calc_length_v3(const float co_a[3], const float no_a[3],
- const float co_b[3], const float no_b[3])
+static float bezier_handle_calc_length_v3(
+ const float co_a[3], const float no_a[3],
+ const float co_b[3], const float no_b[3])
{
const float dot = dot_v3v3(no_a, no_b);
/* gives closest approx at a circle with 2 parallel handles */
@@ -538,12 +539,13 @@ static void bm_edgering_pair_store_free(
/* -------------------------------------------------------------------- */
/* Interpolation Function */
-static void bm_edgering_pair_interpolate(BMesh *bm, LoopPairStore *lpair,
- struct BMEdgeLoopStore *el_store_a,
- struct BMEdgeLoopStore *el_store_b,
- ListBase *eloops_ring,
- const int interp_mode, const int cuts, const float smooth,
- const float *falloff_cache)
+static void bm_edgering_pair_interpolate(
+ BMesh *bm, LoopPairStore *lpair,
+ struct BMEdgeLoopStore *el_store_a,
+ struct BMEdgeLoopStore *el_store_b,
+ ListBase *eloops_ring,
+ const int interp_mode, const int cuts, const float smooth,
+ const float *falloff_cache)
{
const int resolu = cuts + 2;
const int dims = 3;
@@ -878,9 +880,10 @@ static bool bm_edgering_pair_order_is_flipped(BMesh *UNUSED(bm),
* Takes 2 edge loops that share edges,
* sort their verts and rotates the list so the lined up.
*/
-static void bm_edgering_pair_order(BMesh *bm,
- struct BMEdgeLoopStore *el_store_a,
- struct BMEdgeLoopStore *el_store_b)
+static void bm_edgering_pair_order(
+ BMesh *bm,
+ struct BMEdgeLoopStore *el_store_a,
+ struct BMEdgeLoopStore *el_store_b)
{
ListBase *lb_a = BM_edgeloop_verts_get(el_store_a);
ListBase *lb_b = BM_edgeloop_verts_get(el_store_b);
@@ -951,11 +954,12 @@ static void bm_edgering_pair_order(BMesh *bm,
*
* \note loops are _not_ aligned.
*/
-static void bm_edgering_pair_subdiv(BMesh *bm,
- struct BMEdgeLoopStore *el_store_a,
- struct BMEdgeLoopStore *el_store_b,
- ListBase *eloops_ring,
- const int cuts)
+static void bm_edgering_pair_subdiv(
+ BMesh *bm,
+ struct BMEdgeLoopStore *el_store_a,
+ struct BMEdgeLoopStore *el_store_b,
+ ListBase *eloops_ring,
+ const int cuts)
{
ListBase *lb_a = BM_edgeloop_verts_get(el_store_a);
// ListBase *lb_b = BM_edgeloop_verts_get(el_store_b);
@@ -1043,11 +1047,12 @@ static void bm_edgering_pair_subdiv(BMesh *bm,
bm_edgeloop_vert_tag(el_store_b, false);
}
-static void bm_edgering_pair_ringsubd(BMesh *bm, LoopPairStore *lpair,
- struct BMEdgeLoopStore *el_store_a,
- struct BMEdgeLoopStore *el_store_b,
- const int interp_mode, const int cuts, const float smooth,
- const float *falloff_cache)
+static void bm_edgering_pair_ringsubd(
+ BMesh *bm, LoopPairStore *lpair,
+ struct BMEdgeLoopStore *el_store_a,
+ struct BMEdgeLoopStore *el_store_b,
+ const int interp_mode, const int cuts, const float smooth,
+ const float *falloff_cache)
{
ListBase eloops_ring = {NULL};
bm_edgering_pair_order(bm, el_store_a, el_store_b);
diff --git a/source/blender/bmesh/operators/bmo_triangulate.c b/source/blender/bmesh/operators/bmo_triangulate.c
index 986583cc21b..cb9ba5e361c 100644
--- a/source/blender/bmesh/operators/bmo_triangulate.c
+++ b/source/blender/bmesh/operators/bmo_triangulate.c
@@ -75,6 +75,7 @@ void bmo_triangle_fill_exec(BMesh *bm, BMOperator *op)
GHash *sf_vert_map;
float normal[3];
const int scanfill_flag = BLI_SCANFILL_CALC_HOLES | BLI_SCANFILL_CALC_POLYS | BLI_SCANFILL_CALC_LOOSE;
+ unsigned int nors_tot;
bool calc_winding = false;
sf_vert_map = BLI_ghash_ptr_new_ex(__func__, BMO_slot_buffer_count(op->slots_in, "edges"));
@@ -103,6 +104,7 @@ void bmo_triangle_fill_exec(BMesh *bm, BMOperator *op)
/* sf_edge = */ BLI_scanfill_edge_add(&sf_ctx, UNPACK2(sf_verts));
/* sf_edge->tmp.p = e; */ /* UNUSED */
}
+ nors_tot = BLI_ghash_size(sf_vert_map);
BLI_ghash_free(sf_vert_map, NULL, NULL);
@@ -111,7 +113,6 @@ void bmo_triangle_fill_exec(BMesh *bm, BMOperator *op)
* Since we don't know winding, just accumulate */
ScanFillVert *sf_vert;
struct SortNormal *nors;
- const unsigned int nors_tot = BLI_ghash_size(sf_vert_map);
unsigned int i;
bool is_degenerate = true;
@@ -182,7 +183,11 @@ void bmo_triangle_fill_exec(BMesh *bm, BMOperator *op)
calc_winding = false;
}
- normalize_v3(normal);
+ /* in this case we almost certainly have degenerate geometry,
+ * better set a fallback value as a last resort */
+ if (UNLIKELY(normalize_v3(normal) == 0.0f)) {
+ normal[2] = 1.0f;
+ }
BLI_scanfill_calc_ex(&sf_ctx, scanfill_flag, normal);
diff --git a/source/blender/bmesh/operators/bmo_utils.c b/source/blender/bmesh/operators/bmo_utils.c
index d2d1c0854de..964d0b1dfc6 100644
--- a/source/blender/bmesh/operators/bmo_utils.c
+++ b/source/blender/bmesh/operators/bmo_utils.c
@@ -177,42 +177,112 @@ void bmo_rotate_edges_exec(BMesh *bm, BMOperator *op)
#define SEL_FLAG 1
#define SEL_ORIG 2
-static void bmo_region_extend_extend(BMesh *bm, BMOperator *op, const bool use_faces)
+static void bmo_face_flag_set_flush(BMesh *bm, BMFace *f, const short oflag, const bool value)
+{
+ BMLoop *l_iter;
+ BMLoop *l_first;
+
+ BMO_elem_flag_set(bm, f, oflag, value);
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
+ BMO_elem_flag_set(bm, l_iter->e, oflag, value);
+ BMO_elem_flag_set(bm, l_iter->v, oflag, value);
+ } while ((l_iter = l_iter->next) != l_first);
+}
+
+
+static void bmo_region_extend_expand(
+ BMesh *bm, BMOperator *op,
+ const bool use_faces, const bool use_faces_step)
{
- BMVert *v;
- BMEdge *e;
- BMIter eiter;
BMOIter siter;
if (!use_faces) {
+ BMVert *v;
+
BMO_ITER (v, &siter, op->slots_in, "geom", BM_VERT) {
- BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) {
- if (!BM_elem_flag_test(e, BM_ELEM_HIDDEN))
- if (!BMO_elem_flag_test(bm, e, SEL_ORIG))
+ bool found = false;
+
+ {
+ BMIter eiter;
+ BMEdge *e;
+
+ BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) {
+ if (!BMO_elem_flag_test(bm, e, SEL_ORIG) && !BM_elem_flag_test(e, BM_ELEM_HIDDEN)) {
+ found = true;
break;
+ }
+ }
}
- if (e) {
- BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) {
- if (!BM_elem_flag_test(e, BM_ELEM_HIDDEN)) {
- BMO_elem_flag_enable(bm, e, SEL_FLAG);
- BMO_elem_flag_enable(bm, BM_edge_other_vert(e, v), SEL_FLAG);
+ if (found) {
+ if (!use_faces_step) {
+ BMIter eiter;
+ BMEdge *e;
+
+ BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) {
+ if (!BMO_elem_flag_test(bm, e, SEL_FLAG) && !BM_elem_flag_test(e, BM_ELEM_HIDDEN)) {
+ BMO_elem_flag_enable(bm, e, SEL_FLAG);
+ BMO_elem_flag_enable(bm, BM_edge_other_vert(e, v), SEL_FLAG);
+ }
+ }
+ }
+ else {
+ BMIter fiter;
+ BMFace *f;
+
+ BM_ITER_ELEM (f, &fiter, v, BM_FACES_OF_VERT) {
+ if (!BMO_elem_flag_test(bm, f, SEL_FLAG) && !BM_elem_flag_test(f, BM_ELEM_HIDDEN)) {
+ bmo_face_flag_set_flush(bm, f, SEL_FLAG, true);
+ }
+ }
+
+ /* handle wire edges (when stepping over faces) */
+ {
+ BMIter eiter;
+ BMEdge *e;
+ BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) {
+ if (BM_edge_is_wire(e)) {
+ if (!BMO_elem_flag_test(bm, e, SEL_FLAG) && !BM_elem_flag_test(e, BM_ELEM_HIDDEN)) {
+ BMO_elem_flag_enable(bm, e, SEL_FLAG);
+ BMO_elem_flag_enable(bm, BM_edge_other_vert(e, v), SEL_FLAG);
+ }
+ }
+ }
}
}
}
}
}
else {
- BMIter liter, fiter;
- BMFace *f, *f2;
- BMLoop *l;
+ BMFace *f;
BMO_ITER (f, &siter, op->slots_in, "geom", BM_FACE) {
+ BMIter liter;
+ BMLoop *l;
+
BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) {
- BM_ITER_ELEM (f2, &fiter, l->e, BM_FACES_OF_EDGE) {
- if (!BM_elem_flag_test(f2, BM_ELEM_HIDDEN)) {
- if (!BMO_elem_flag_test(bm, f2, SEL_ORIG)) {
- BMO_elem_flag_enable(bm, f2, SEL_FLAG);
+ if (!use_faces_step) {
+ BMIter fiter;
+ BMFace *f_other;
+
+ BM_ITER_ELEM (f_other, &fiter, l->e, BM_FACES_OF_EDGE) {
+ if (!BMO_elem_flag_test(bm, f_other, SEL_ORIG | SEL_FLAG) &&
+ !BM_elem_flag_test(f_other, BM_ELEM_HIDDEN))
+ {
+ BMO_elem_flag_enable(bm, f_other, SEL_FLAG);
+ }
+ }
+ }
+ else {
+ BMIter fiter;
+ BMFace *f_other;
+
+ BM_ITER_ELEM (f_other, &fiter, l->v, BM_FACES_OF_VERT) {
+ if (!BMO_elem_flag_test(bm, f_other, SEL_ORIG | SEL_FLAG) &&
+ !BM_elem_flag_test(f_other, BM_ELEM_HIDDEN))
+ {
+ BMO_elem_flag_enable(bm, f_other, SEL_FLAG);
}
}
}
@@ -221,43 +291,94 @@ static void bmo_region_extend_extend(BMesh *bm, BMOperator *op, const bool use_f
}
}
-static void bmo_region_extend_constrict(BMesh *bm, BMOperator *op, const bool use_faces)
+static void bmo_region_extend_contract(
+ BMesh *bm, BMOperator *op,
+ const bool use_faces, const bool use_faces_step)
{
- BMVert *v;
- BMEdge *e;
- BMIter eiter;
BMOIter siter;
if (!use_faces) {
+ BMVert *v;
+
BMO_ITER (v, &siter, op->slots_in, "geom", BM_VERT) {
- BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) {
- if (!BM_elem_flag_test(e, BM_ELEM_HIDDEN))
- if (!BMO_elem_flag_test(bm, e, SEL_ORIG))
+ bool found = false;
+
+ if (!use_faces_step) {
+ BMIter eiter;
+ BMEdge *e;
+
+ BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) {
+ if (!BMO_elem_flag_test(bm, e, SEL_ORIG)) {
+ found = true;
break;
+ }
+ }
}
+ else {
+ BMIter fiter;
+ BMFace *f;
- if (e) {
- BMO_elem_flag_enable(bm, v, SEL_FLAG);
+ BM_ITER_ELEM (f, &fiter, v, BM_FACES_OF_VERT) {
+ if (!BMO_elem_flag_test(bm, f, SEL_ORIG)) {
+ found = true;
+ break;
+ }
+ }
- BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) {
- if (!BM_elem_flag_test(e, BM_ELEM_HIDDEN)) {
- BMO_elem_flag_enable(bm, e, SEL_FLAG);
+ /* handle wire edges (when stepping over faces) */
+ if (!found) {
+ BMIter eiter;
+ BMEdge *e;
+
+ BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) {
+ if (BM_edge_is_wire(e)) {
+ if (!BMO_elem_flag_test(bm, e, SEL_ORIG)) {
+ found = true;
+ break;
+ }
+ }
}
}
+ }
+
+ if (found) {
+ BMIter eiter;
+ BMEdge *e;
+
+ BMO_elem_flag_enable(bm, v, SEL_FLAG);
+ BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) {
+ BMO_elem_flag_enable(bm, e, SEL_FLAG);
+ }
}
}
}
else {
- BMIter liter, fiter;
- BMFace *f, *f2;
- BMLoop *l;
+ BMFace *f;
BMO_ITER (f, &siter, op->slots_in, "geom", BM_FACE) {
+ BMIter liter;
+ BMLoop *l;
+
BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) {
- BM_ITER_ELEM (f2, &fiter, l->e, BM_FACES_OF_EDGE) {
- if (!BM_elem_flag_test(f2, BM_ELEM_HIDDEN)) {
- if (!BMO_elem_flag_test(bm, f2, SEL_ORIG)) {
+
+ if (!use_faces_step) {
+ BMIter fiter;
+ BMFace *f_other;
+
+ BM_ITER_ELEM (f_other, &fiter, l->e, BM_FACES_OF_EDGE) {
+ if (!BMO_elem_flag_test(bm, f_other, SEL_ORIG)) {
+ BMO_elem_flag_enable(bm, f, SEL_FLAG);
+ break;
+ }
+ }
+ }
+ else {
+ BMIter fiter;
+ BMFace *f_other;
+
+ BM_ITER_ELEM (f_other, &fiter, l->v, BM_FACES_OF_VERT) {
+ if (!BMO_elem_flag_test(bm, f_other, SEL_ORIG)) {
BMO_elem_flag_enable(bm, f, SEL_FLAG);
break;
}
@@ -271,14 +392,17 @@ static void bmo_region_extend_constrict(BMesh *bm, BMOperator *op, const bool us
void bmo_region_extend_exec(BMesh *bm, BMOperator *op)
{
const bool use_faces = BMO_slot_bool_get(op->slots_in, "use_faces");
- const bool constrict = BMO_slot_bool_get(op->slots_in, "use_constrict");
+ const bool use_face_step = BMO_slot_bool_get(op->slots_in, "use_face_step");
+ const bool constrict = BMO_slot_bool_get(op->slots_in, "use_contract");
BMO_slot_buffer_flag_enable(bm, op->slots_in, "geom", BM_ALL_NOLOOP, SEL_ORIG);
- if (constrict)
- bmo_region_extend_constrict(bm, op, use_faces);
- else
- bmo_region_extend_extend(bm, op, use_faces);
+ if (constrict) {
+ bmo_region_extend_contract(bm, op, use_faces, use_face_step);
+ }
+ else {
+ bmo_region_extend_expand(bm, op, use_faces, use_face_step);
+ }
BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "geom.out", BM_ALL_NOLOOP, SEL_FLAG);
}
@@ -291,6 +415,7 @@ void bmo_smooth_vert_exec(BMesh *UNUSED(bm), BMOperator *op)
BMEdge *e;
float (*cos)[3] = MEM_mallocN(sizeof(*cos) * BMO_slot_buffer_count(op->slots_in, "verts"), __func__);
float *co, *co2, clip_dist = BMO_slot_float_get(op->slots_in, "clip_dist");
+ const float fac = BMO_slot_float_get(op->slots_in, "factor");
int i, j, clipx, clipy, clipz;
int xaxis, yaxis, zaxis;
@@ -322,7 +447,7 @@ void bmo_smooth_vert_exec(BMesh *UNUSED(bm), BMOperator *op)
}
mul_v3_fl(co, 1.0f / (float)j);
- mid_v3_v3v3(co, co, v->co);
+ interp_v3_v3v3(co, v->co, co, fac);
if (clipx && fabsf(v->co[0]) <= clip_dist)
co[0] = 0.0f;
diff --git a/source/blender/bmesh/operators/bmo_wireframe.c b/source/blender/bmesh/operators/bmo_wireframe.c
index 62409fc3987..ac81dde93c0 100644
--- a/source/blender/bmesh/operators/bmo_wireframe.c
+++ b/source/blender/bmesh/operators/bmo_wireframe.c
@@ -26,8 +26,6 @@
* Creates a solid wireframe from connected faces.
*/
-#include "MEM_guardedalloc.h"
-
#include "DNA_material_types.h"
#include "BLI_sys_types.h"
diff --git a/source/blender/bmesh/tools/bmesh_beautify.c b/source/blender/bmesh/tools/bmesh_beautify.c
index 6639e767e77..19fe492c670 100644
--- a/source/blender/bmesh/tools/bmesh_beautify.c
+++ b/source/blender/bmesh/tools/bmesh_beautify.c
@@ -37,6 +37,7 @@
#include "BLI_math.h"
#include "BLI_heap.h"
+#include "BLI_polyfill2d_beautify.h"
#include "MEM_guardedalloc.h"
@@ -96,7 +97,7 @@ static GSet *erot_gset_new(void)
static void erot_state_ex(const BMEdge *e, int v_index[2], int f_index[2])
{
- BLI_assert(BM_edge_is_manifold((BMEdge *)e));
+ BLI_assert(BM_edge_is_manifold(e));
BLI_assert(BM_vert_in_edge(e, e->l->prev->v) == false);
BLI_assert(BM_vert_in_edge(e, e->l->radial_next->prev->v) == false);
@@ -125,22 +126,22 @@ static void erot_state_alternate(const BMEdge *e, EdRotState *e_state)
/* -------------------------------------------------------------------- */
/* Calculate the improvement of rotating the edge */
-/**
- * \return a negative value means the edge can be rotated.
- */
static float bm_edge_calc_rotate_beauty__area(
const float v1[3], const float v2[3], const float v3[3], const float v4[3])
{
/* not a loop (only to be able to break out) */
do {
float v1_xy[2], v2_xy[2], v3_xy[2], v4_xy[2];
- bool is_zero_a, is_zero_b;
/* first get the 2d values */
{
+ const float eps = 1e-5;
float no_a[3], no_b[3];
float no[3];
float axis_mat[3][3];
+ float no_scale;
+ cross_tri_v3(no_a, v2, v3, v4);
+ cross_tri_v3(no_b, v2, v4, v1);
// printf("%p %p %p %p - %p %p\n", v1, v2, v3, v4, e->l->f, e->l->radial_next->f);
BLI_assert((ELEM(v1, v2, v3, v4) == false) &&
@@ -148,97 +149,40 @@ static float bm_edge_calc_rotate_beauty__area(
(ELEM(v3, v1, v2, v4) == false) &&
(ELEM(v4, v1, v2, v3) == false));
- is_zero_a = (normal_tri_v3(no_a, v2, v3, v4) <= FLT_EPSILON);
- is_zero_b = (normal_tri_v3(no_b, v2, v4, v1) <= FLT_EPSILON);
-
- if (LIKELY(is_zero_a == false && is_zero_b == false)) {
- add_v3_v3v3(no, no_a, no_b);
- if (UNLIKELY(normalize_v3(no) <= FLT_EPSILON)) {
- break;
- }
- }
- else if (is_zero_a == false) {
- copy_v3_v3(no, no_a);
- }
- else if (is_zero_b == false) {
- copy_v3_v3(no, no_b);
- }
- else {
- /* both zero area, no useful normal can be calculated */
+ add_v3_v3v3(no, no_a, no_b);
+ if (UNLIKELY((no_scale = normalize_v3(no)) <= FLT_EPSILON)) {
break;
}
- // { float a = angle_normalized_v3v3(no_a, no_b); printf("~ %.7f\n", a); fflush(stdout);}
-
axis_dominant_v3_to_m3(axis_mat, no);
mul_v2_m3v3(v1_xy, axis_mat, v1);
mul_v2_m3v3(v2_xy, axis_mat, v2);
mul_v2_m3v3(v3_xy, axis_mat, v3);
mul_v2_m3v3(v4_xy, axis_mat, v4);
- }
-
- // printf("%p %p %p %p - %p %p\n", v1, v2, v3, v4, e->l->f, e->l->radial_next->f);
-
- if (is_zero_a == false && is_zero_b == false) {
- /* both tri's are valid, check we make a concave quad */
- if (!is_quad_convex_v2(v1_xy, v2_xy, v3_xy, v4_xy)) {
- break;
- }
- }
- else {
- /* one of the tri's was degenerate, chech we're not rotating
- * into a different degenerate shape or flipping the face */
- float area_a, area_b;
- area_a = area_tri_signed_v2(v1_xy, v2_xy, v3_xy);
- area_b = area_tri_signed_v2(v1_xy, v3_xy, v4_xy);
-
- if ((fabsf(area_a) <= FLT_EPSILON) || (fabsf(area_b) <= FLT_EPSILON)) {
- /* one of the new rotations is degenerate */
- break;
- }
-
- if ((area_a >= 0.0f) != (area_b >= 0.0f)) {
- /* rotation would cause flipping */
+ /**
+ * Check if input faces are already flipped.
+ * Logic for 'signum_i' addition is:
+ *
+ * Accept:
+ * - (1, 1) or (-1, -1): same side (common case).
+ * - (-1/1, 0): one degenerate, OK since we may rotate into a valid state.
+ *
+ * Ignore:
+ * - (-1, 1): opposite winding, ignore.
+ * - ( 0, 0): both degenerate, ignore.
+ *
+ * \note The cross product is divided by 'no_scale'
+ * so the rotation calculation is scale independent.
+ */
+ if (!(signum_i_ex(cross_tri_v2(v2_xy, v3_xy, v4_xy) / no_scale, eps) +
+ signum_i_ex(cross_tri_v2(v2_xy, v4_xy, v1_xy) / no_scale, eps)))
+ {
break;
}
}
- {
- /* testing rule: the area divided by the perimeter,
- * check if (1-3) beats the existing (2-4) edge rotation */
- float area_a, area_b;
- float prim_a, prim_b;
- float fac_24, fac_13;
-
- float len_12, len_23, len_34, len_41, len_24, len_13;
-
- /* edges around the quad */
- len_12 = len_v2v2(v1_xy, v2_xy);
- len_23 = len_v2v2(v2_xy, v3_xy);
- len_34 = len_v2v2(v3_xy, v4_xy);
- len_41 = len_v2v2(v4_xy, v1_xy);
- /* edges crossing the quad interior */
- len_13 = len_v2v2(v1_xy, v3_xy);
- len_24 = len_v2v2(v2_xy, v4_xy);
-
- /* edge (2-4), current state */
- area_a = area_tri_v2(v2_xy, v3_xy, v4_xy);
- area_b = area_tri_v2(v2_xy, v4_xy, v1_xy);
- prim_a = len_23 + len_34 + len_24;
- prim_b = len_24 + len_41 + len_12;
- fac_24 = (area_a / prim_a) + (area_b / prim_b);
-
- /* edge (1-3), new state */
- area_a = area_tri_v2(v1_xy, v2_xy, v3_xy);
- area_b = area_tri_v2(v1_xy, v3_xy, v4_xy);
- prim_a = len_12 + len_23 + len_13;
- prim_b = len_34 + len_41 + len_13;
- fac_13 = (area_a / prim_a) + (area_b / prim_b);
-
- /* negative number if (1-3) is an improved state */
- return fac_24 - fac_13;
- }
+ return BLI_polyfill_beautify_quad_rotate_calc(v1_xy, v2_xy, v3_xy, v4_xy);
} while (false);
return FLT_MAX;
@@ -272,6 +216,12 @@ static float bm_edge_calc_rotate_beauty__angle(
return FLT_MAX;
}
+/**
+ * Assuming we have 2 triangles sharing an edge (2 - 4),
+ * check if the edge running from (1 - 3) gives better results.
+ *
+ * \return (negative number means the edge can be rotated, lager == better).
+ */
float BM_verts_calc_rotate_beauty(
const BMVert *v1, const BMVert *v2, const BMVert *v3, const BMVert *v4,
const short flag, const short method)
@@ -324,11 +274,12 @@ BLI_INLINE bool edge_in_array(const BMEdge *e, const BMEdge **edge_array, const
}
/* 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,
+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)
+ const short flag, const short method)
{
if (edge_in_array(e, edge_array, edge_array_len)) {
const int i = BM_elem_index_get(e);
@@ -366,10 +317,11 @@ 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)
+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)
{
int i;
@@ -383,7 +335,7 @@ static void bm_edge_update_beauty_cost(BMEdge *e, Heap *eheap, HeapNode **eheap_
BLI_assert(e->l->f->len == 3 &&
e->l->radial_next->f->len == 3);
- BLI_assert(BM_edge_face_count(e) == 2);
+ BLI_assert(BM_edge_face_count_is_equal(e, 2));
for (i = 0; i < 4; i++) {
bm_edge_update_beauty_cost_single(
@@ -400,9 +352,10 @@ static void bm_edge_update_beauty_cost(BMEdge *e, Heap *eheap, HeapNode **eheap_
/**
* \note This function sets the edge indices to invalid values.
*/
-void BM_mesh_beautify_fill(BMesh *bm, BMEdge **edge_array, const int edge_array_len,
- const short flag, const short method,
- const short oflag_edge, const short oflag_face)
+void BM_mesh_beautify_fill(
+ BMesh *bm, BMEdge **edge_array, const int edge_array_len,
+ const short flag, const short method,
+ const short oflag_edge, const short oflag_face)
{
Heap *eheap; /* edge heap */
HeapNode **eheap_table; /* edge index aligned table pointing to the eheap */
@@ -438,11 +391,11 @@ void BM_mesh_beautify_fill(BMesh *bm, BMEdge **edge_array, const int edge_array_
i = BM_elem_index_get(e);
eheap_table[i] = NULL;
- BLI_assert(BM_edge_face_count(e) == 2);
+ BLI_assert(BM_edge_face_count_is_equal(e, 2));
e = BM_edge_rotate(bm, e, false, BM_EDGEROT_CHECK_EXISTS);
- BLI_assert(e == NULL || BM_edge_face_count(e) == 2);
+ BLI_assert(e == NULL || BM_edge_face_count_is_equal(e, 2));
if (LIKELY(e)) {
GSet *e_state_set = edge_state_arr[i];
diff --git a/source/blender/bmesh/tools/bmesh_beautify.h b/source/blender/bmesh/tools/bmesh_beautify.h
index 7cc17008b50..0d6aa23b81d 100644
--- a/source/blender/bmesh/tools/bmesh_beautify.h
+++ b/source/blender/bmesh/tools/bmesh_beautify.h
@@ -31,12 +31,14 @@ enum {
VERT_RESTRICT_TAG = (1 << 0),
};
-void BM_mesh_beautify_fill(BMesh *bm, BMEdge **edge_array, const int edge_array_len,
- const short flag, const short method,
- const short oflag_edge, const short oflag_face);
+void BM_mesh_beautify_fill(
+ BMesh *bm, BMEdge **edge_array, const int edge_array_len,
+ const short flag, const short method,
+ const short oflag_edge, const short oflag_face);
-float BM_verts_calc_rotate_beauty(const BMVert *v1, const BMVert *v2,
- const BMVert *v3, const BMVert *v4,
- const short flag, const short method);
+float BM_verts_calc_rotate_beauty(
+ const BMVert *v1, const BMVert *v2,
+ const BMVert *v3, const BMVert *v4,
+ const short flag, const short method);
#endif /* __BMESH_BEAUTIFY_H__ */
diff --git a/source/blender/bmesh/tools/bmesh_bevel.c b/source/blender/bmesh/tools/bmesh_bevel.c
index 4a9fb677257..5a7788c0b62 100644
--- a/source/blender/bmesh/tools/bmesh_bevel.c
+++ b/source/blender/bmesh/tools/bmesh_bevel.c
@@ -53,6 +53,10 @@
#define BEVEL_EPSILON 1e-6f
#define BEVEL_EPSILON_SQ 1e-12f
#define BEVEL_EPSILON_BIG 1e-4f
+#define BEVEL_EPSILON_BIG_SQ 1e-8f
+#define BEVEL_EPSILON_ANG DEG2RADF(2.0f)
+#define BEVEL_SMALL_ANG DEG2RADF(10.0f)
+#define BEVEL_MAX_ADJUST_PCT 10.0f
/* happens far too often, uncomment for development */
// #define BEVEL_ASSERT_PROJECT
@@ -183,11 +187,11 @@ typedef struct BevelParams {
float pro_super_r; /* superellipse parameter for edge profile */
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 loop_slide; /* should bevel prefer to slide along edges rather than keep widths spec? */
bool limit_offset; /* should offsets be limited by collisions? */
const struct MDeformVert *dvert; /* vertex group array, maybe set if vertex_only */
int vertex_group; /* vertex group index, maybe set if vertex_only */
- int mat_nr; /* if >= 0, material number for bevel; else material comes from adjacent faces */
+ int mat_nr; /* if >= 0, material number for bevel; else material comes from adjacent faces */
} BevelParams;
// #pragma GCC diagnostic ignored "-Wpadded"
@@ -244,8 +248,9 @@ static void create_mesh_bmvert(BMesh *bm, VMesh *vm, int i, int j, int k, BMVert
BM_elem_flag_disable(nv->v, BM_ELEM_TAG);
}
-static void copy_mesh_vert(VMesh *vm, int ito, int jto, int kto,
- int ifrom, int jfrom, int kfrom)
+static void copy_mesh_vert(
+ VMesh *vm, int ito, int jto, int kto,
+ int ifrom, int jfrom, int kfrom)
{
NewVert *nvto, *nvfrom;
@@ -341,32 +346,64 @@ static EdgeHalf *next_bev(BevVert *bv, EdgeHalf *from_e)
}
/* Return a good representative face (for materials, etc.) for faces
- * created around/near BoundVert v */
-static BMFace *boundvert_rep_face(BoundVert *v)
-{
- BLI_assert(v->efirst != NULL && v->elast != NULL);
- if (v->efirst->fnext == v->elast->fprev)
- return v->efirst->fnext;
- else if (v->efirst->fnext)
- return v->efirst->fnext;
- else
- return v->elast->fprev;
+ * created around/near BoundVert v.
+ * Sometimes care about a second choice, if there is one.
+ * If r_fother parameter is non-NULL and there is another, different,
+ * possible frep, return the other one in that parameter. */
+static BMFace *boundvert_rep_face(BoundVert *v, BMFace **r_fother)
+{
+ BMFace *frep, *frep2;
+
+ frep2 = NULL;
+ if (v->ebev) {
+ frep = v->ebev->fprev;
+ if (v->efirst->fprev != frep)
+ frep2 = v->efirst->fprev;
+ }
+ else {
+ frep = v->efirst->fprev;
+ if (frep) {
+ if (v->elast->fnext != frep)
+ frep2 = v->elast->fnext;
+ else if (v->efirst->fnext != frep)
+ frep2 = v->efirst->fnext;
+ else if (v->elast->fprev != frep)
+ frep2 = v->efirst->fprev;
+ }
+ else if (v->efirst->fnext) {
+ frep = v->efirst->fnext;
+ if (v->elast->fnext != frep)
+ frep2 = v->elast->fnext;
+ }
+ else if (v->elast->fprev) {
+ frep = v->elast->fprev;
+ }
+ }
+ if (r_fother)
+ *r_fother = frep2;
+ return frep;
}
/**
* Make ngon from verts alone.
* Make sure to properly copy face attributes and do custom data interpolation from
* corresponding elements of face_arr, if that is non-NULL, else from facerep.
+ * If edge_arr is non-NULL, then for interpolation purposes only, the corresponding
+ * elements of vert_arr are snapped to any non-NULL edges in that array.
* If mat_nr >= 0 then the material of the face is set to that.
*
* \note ALL face creation goes through this function, this is important to keep!
*/
-static BMFace *bev_create_ngon(BMesh *bm, BMVert **vert_arr, const int totv,
- BMFace **face_arr, BMFace *facerep, int mat_nr, bool do_interp)
+static BMFace *bev_create_ngon(
+ BMesh *bm, BMVert **vert_arr, const int totv,
+ BMFace **face_arr, BMFace *facerep, BMEdge **edge_arr,
+ int mat_nr, bool do_interp)
{
BMIter iter;
BMLoop *l;
BMFace *f, *interp_f;
+ BMEdge *bme;
+ float save_co[3];
int i;
f = BM_face_create_verts(bm, vert_arr, totv, facerep, BM_CREATE_NOP, true);
@@ -384,8 +421,19 @@ static BMFace *bev_create_ngon(BMesh *bm, BMVert **vert_arr, const int totv,
else {
interp_f = facerep;
}
- if (interp_f)
+ if (interp_f) {
+ bme = NULL;
+ if (edge_arr)
+ bme = edge_arr[i];
+ if (bme) {
+ copy_v3_v3(save_co, l->v->co);
+ closest_to_line_segment_v3(l->v->co, save_co, bme->v1->co, bme->v2->co);
+ }
BM_loop_interp_from_face(bm, l, interp_f, true, true);
+ if (bme) {
+ copy_v3_v3(l->v->co, save_co);
+ }
+ }
i++;
}
}
@@ -402,25 +450,32 @@ static BMFace *bev_create_ngon(BMesh *bm, BMVert **vert_arr, const int totv,
return f;
}
-static BMFace *bev_create_quad_tri(BMesh *bm, BMVert *v1, BMVert *v2, BMVert *v3, BMVert *v4,
- BMFace *facerep, int mat_nr, bool do_interp)
+static BMFace *bev_create_quad(
+ BMesh *bm, BMVert *v1, BMVert *v2, BMVert *v3, BMVert *v4,
+ BMFace *f1, BMFace *f2, BMFace *f3, BMFace *f4,
+ int mat_nr)
{
BMVert *varr[4] = {v1, v2, v3, v4};
- return bev_create_ngon(bm, varr, v4 ? 4 : 3, NULL, facerep, mat_nr, do_interp);
+ BMFace *farr[4] = {f1, f2, f3, f4};
+ return bev_create_ngon(bm, varr, 4, farr, f1, NULL, mat_nr, true);
}
-static BMFace *bev_create_quad_tri_ex(BMesh *bm, BMVert *v1, BMVert *v2, BMVert *v3, BMVert *v4,
- BMFace *f1, BMFace *f2, BMFace *f3, BMFace *f4, int mat_nr)
+static BMFace *bev_create_quad_ex(
+ BMesh *bm, BMVert *v1, BMVert *v2, BMVert *v3, BMVert *v4,
+ BMFace *f1, BMFace *f2, BMFace *f3, BMFace *f4,
+ BMEdge *e1, BMEdge *e2, BMEdge *e3, BMEdge *e4,
+ int mat_nr)
{
BMVert *varr[4] = {v1, v2, v3, v4};
BMFace *farr[4] = {f1, f2, f3, f4};
- return bev_create_ngon(bm, varr, v4 ? 4 : 3, farr, f1, mat_nr, true);
+ BMEdge *earr[4] = {e1, e2, e3, e4};
+ return bev_create_ngon(bm, varr, 4, farr, f1, earr, mat_nr, true);
}
-
/* Is Loop layer layer_index contiguous across shared vertex of l1 and l2? */
-static bool contig_ldata_across_loops(BMesh *bm, BMLoop *l1, BMLoop *l2,
- int layer_index)
+static bool contig_ldata_across_loops(
+ BMesh *bm, BMLoop *l1, BMLoop *l2,
+ int layer_index)
{
const int offset = bm->ldata.layers[layer_index].offset;
const int type = bm->ldata.layers[layer_index].type;
@@ -478,71 +533,79 @@ static bool contig_ldata_across_edge(BMesh *bm, BMEdge *e, BMFace *f1, BMFace *f
return true;
}
-/* Like bev_create_quad_tri, but when verts straddle an old edge.
- * e
- * |
- * v1+---|---+v4
- * | | |
- * | | |
- * v2+---|---+v3
- * |
- * f1 | f2
- *
- * Most CustomData for loops can be interpolated in their respective
- * faces' loops, but for UVs and other 'has_math_cd' layers, only
- * do this if the UVs are continuous across the edge e, otherwise pick
- * one side (f1, arbitrarily), and interpolate them all on that side.
- * For face data, use f1 (arbitrarily) as face representative. */
-static BMFace *bev_create_quad_straddle(BMesh *bm, BMVert *v1, BMVert *v2, BMVert *v3, BMVert *v4,
- BMFace *f1, BMFace *f2, int mat_nr, bool is_seam)
-{
- BMFace *f, *facerep;
- BMLoop *l;
+/* Merge (using average) all the UV values for loops of v's faces.
+ * Caller should ensure that no seams are violated by doing this. */
+static void bev_merge_uvs(BMesh *bm, BMVert *v)
+{
BMIter iter;
+ MLoopUV *luv;
+ BMLoop *l;
+ float uv[2];
+ int n;
+ int num_of_uv_layers = CustomData_number_of_layers(&bm->ldata, CD_MLOOPUV);
+ int i;
- f = bev_create_quad_tri(bm, v1, v2, v3, v4, f1, mat_nr, false);
+ for (i = 0; i < num_of_uv_layers; i++) {
+ int cd_loop_uv_offset = CustomData_get_n_offset(&bm->ldata, CD_MLOOPUV, i);
- if (!f)
- return NULL;
+ if (cd_loop_uv_offset == -1)
+ return;
- BM_ITER_ELEM (l, &iter, f, BM_LOOPS_OF_FACE) {
- if (is_seam || l->v == v1 || l->v == v2)
- facerep = f1;
- else
- facerep = f2;
- if (facerep)
- BM_loop_interp_from_face(bm, l, facerep, true, true);
+ n = 0;
+ zero_v2(uv);
+ BM_ITER_ELEM (l, &iter, v, BM_LOOPS_OF_VERT) {
+ luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
+ add_v2_v2(uv, luv->uv);
+ n++;
+ }
+ if (n > 1) {
+ mul_v2_fl(uv, 1.0f / (float)n);
+ BM_ITER_ELEM (l, &iter, v, BM_LOOPS_OF_VERT) {
+ luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
+ copy_v2_v2(luv->uv, uv);
+ }
+ }
}
- return f;
}
-/* Merge (using average) all the UV values for loops of v's faces.
- * Caller should ensure that no seams are violated by doing this. */
-static void bev_merge_uvs(BMesh *bm, BMVert *v)
+/* Merge (using average) the UV values for two specific loops of v: those for faces containing v,
+ * and part of faces that share edge bme */
+static void bev_merge_edge_uvs(BMesh *bm, BMEdge *bme, BMVert *v)
{
BMIter iter;
MLoopUV *luv;
- BMLoop *l;
+ BMLoop *l, *l1, *l2;
float uv[2];
- int n;
- int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
+ int num_of_uv_layers = CustomData_number_of_layers(&bm->ldata, CD_MLOOPUV);
+ int i;
- if (cd_loop_uv_offset == -1)
+ l1 = NULL;
+ l2 = NULL;
+ BM_ITER_ELEM (l, &iter, v, BM_LOOPS_OF_VERT) {
+ if (l->e == bme)
+ l1 = l;
+ else if (l->prev->e == bme)
+ l2 = l;
+ }
+ if (l1 == NULL || l2 == NULL)
return;
- n = 0;
- zero_v2(uv);
- BM_ITER_ELEM (l, &iter, v, BM_LOOPS_OF_VERT) {
- luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
+ for (i = 0; i < num_of_uv_layers; i++) {
+ int cd_loop_uv_offset = CustomData_get_n_offset(&bm->ldata, CD_MLOOPUV, i);
+
+ if (cd_loop_uv_offset == -1)
+ return;
+
+ zero_v2(uv);
+ luv = BM_ELEM_CD_GET_VOID_P(l1, cd_loop_uv_offset);
add_v2_v2(uv, luv->uv);
- n++;
- }
- if (n > 1) {
- mul_v2_fl(uv, 1.0f / (float)n);
- BM_ITER_ELEM (l, &iter, v, BM_LOOPS_OF_VERT) {
- luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
- copy_v2_v2(luv->uv, uv);
- }
+ luv = BM_ELEM_CD_GET_VOID_P(l2, cd_loop_uv_offset);
+ add_v2_v2(uv, luv->uv);
+ mul_v2_fl(uv, 0.5f);
+ luv = BM_ELEM_CD_GET_VOID_P(l1, cd_loop_uv_offset);
+ copy_v2_v2(luv->uv, uv);
+ luv = BM_ELEM_CD_GET_VOID_P(l2, cd_loop_uv_offset);
+ copy_v2_v2(luv->uv, uv);
}
}
@@ -577,10 +640,42 @@ static bool is_outside_edge(EdgeHalf *e, const float co[3], BMVert **ret_closer_
}
}
+/* co should be approximately on the plane between e1 and e2, which share common vert v
+ * and common face f (which cannot be NULL).
+ * Is it between those edges, sweeping CCW? */
+static bool point_between_edges(float co[3], BMVert *v, BMFace *f, EdgeHalf *e1, EdgeHalf *e2)
+{
+ BMVert *v1, *v2;
+ float dir1[3], dir2[3], dirco[3], no[3];
+ float ang11, ang1co;
+
+ v1 = BM_edge_other_vert(e1->e, v);
+ v2 = BM_edge_other_vert(e2->e, v);
+ sub_v3_v3v3(dir1, v->co, v1->co);
+ sub_v3_v3v3(dir2, v->co, v2->co);
+ sub_v3_v3v3(dirco, v->co, co);
+ normalize_v3(dir1);
+ normalize_v3(dir2);
+ normalize_v3(dirco);
+ ang11 = angle_normalized_v3v3(dir1, dir2);
+ ang1co = angle_normalized_v3v3(dir1, dirco);
+ /* angles are in [0,pi]. need to compare cross product with normal to see if they are reflex */
+ cross_v3_v3v3(no, dir1, dir2);
+ if (dot_v3v3(no, f->no) < 0.0f)
+ ang11 = (float)(M_PI * 2.0) - ang11;
+ cross_v3_v3v3(no, dir1, dirco);
+ if (dot_v3v3(no, f->no) < 0.0f)
+ ang1co = (float)(M_PI * 2.0) - ang1co;
+ return (ang11 - ang1co > -BEVEL_EPSILON_ANG);
+}
+
/*
* Calculate the meeting point between the offset edges for e1 and e2, putting answer in meetco.
* e1 and e2 share vertex v and face f (may be NULL) and viewed from the normal side of
* the bevel vertex, e1 precedes e2 in CCW order.
+ * Except: if edges_between is true, there are edges between e1 and e2 in CCW order so they
+ * don't share a common face. We want the meeting point to be on an existing face so it
+ * should be dropped onto one of the intermediate faces, if possible.
* Offset edge is on right of both edges, where e1 enters v and e2 leave it.
* 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
@@ -589,18 +684,29 @@ static bool is_outside_edge(EdgeHalf *e, const float co[3], BMVert **ret_closer_
* 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])
+static void offset_meet(EdgeHalf *e1, EdgeHalf *e2, BMVert *v, BMFace *f, bool edges_between, 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, d;
+ float dir1[3], dir2[3], dir1n[3], dir2p[3], norm_v[3], norm_v1[3], norm_v2[3],
+ norm_perp1[3], norm_perp2[3], off1a[3], off1b[3], off2a[3], off2b[3],
+ isect2[3], dropco[3], plane[4], ang, d;
BMVert *closer_v;
+ EdgeHalf *e, *e1next, *e2prev;
+ BMFace *ff;
+ int isect_kind;
/* get direction vectors for two offset lines */
sub_v3_v3v3(dir1, v->co, BM_edge_other_vert(e1->e, v)->co);
sub_v3_v3v3(dir2, BM_edge_other_vert(e2->e, v)->co, v->co);
+ if (edges_between) {
+ e1next = e1->next;
+ e2prev = e2->prev;
+ sub_v3_v3v3(dir1n, BM_edge_other_vert(e1next->e, v)->co, v->co);
+ sub_v3_v3v3(dir2p, v->co, BM_edge_other_vert(e2prev->e, v)->co);
+ }
+
ang = angle_v3v3(dir1, dir2);
- if (ang < BEVEL_EPSILON_BIG) {
+ if (ang < BEVEL_EPSILON_ANG) {
/* special case: e1 and e2 are parallel; put offset point perp to both, from v.
* need to find a suitable plane.
* if offsets are different, we're out of luck:
@@ -621,7 +727,7 @@ static void offset_meet(EdgeHalf *e1, EdgeHalf *e2, BMVert *v, BMFace *f, float
e2->offset_l = d;
copy_v3_v3(meetco, off1a);
}
- else if (fabsf(ang - (float)M_PI) < BEVEL_EPSILON_BIG) {
+ else if (fabsf(ang - (float)M_PI) < BEVEL_EPSILON_ANG) {
/* 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. */
@@ -635,17 +741,43 @@ static void offset_meet(EdgeHalf *e1, EdgeHalf *e2, BMVert *v, BMFace *f, float
else {
/* Get normal to plane where meet point should be,
* using cross product instead of f->no in case f is non-planar.
+ * Except: sometimes locally there can be a small angle
+ * between dir1 and dir2 that leads to a normal that is actually almost
+ * perpendicular to the face normal; in this case it looks wrong to use
+ * the local (cross-product) normal, so use the face normal if the angle
+ * between dir1 and dir2 is smallish.
* If e1-v-e2 is a reflex angle (viewed from vertex normal side), need to flip.
* Use f->no to figure out which side to look at angle from, as even if
* f is non-planar, will be more accurate than vertex normal */
- cross_v3_v3v3(norm_v, dir2, dir1);
- normalize_v3(norm_v);
- if (dot_v3v3(norm_v, f ? f->no : v->no) < 0.0f)
- negate_v3(norm_v);
+ if (f && ang < BEVEL_SMALL_ANG) {
+ copy_v3_v3(norm_v1, f->no);
+ copy_v3_v3(norm_v2, f->no);
+ }
+ else if (!edges_between) {
+ cross_v3_v3v3(norm_v1, dir2, dir1);
+ normalize_v3(norm_v1);
+ if (dot_v3v3(norm_v1, f ? f->no : v->no) < 0.0f)
+ negate_v3(norm_v1);
+ copy_v3_v3(norm_v2, norm_v1);
+ }
+ else {
+ /* separate faces; get face norms at corners for each separately */
+ cross_v3_v3v3(norm_v1, dir1n, dir1);
+ normalize_v3(norm_v1);
+ f = e1->fnext;
+ if (dot_v3v3(norm_v1, f ? f->no : v->no) < 0.0f)
+ negate_v3(norm_v1);
+ cross_v3_v3v3(norm_v2, dir2, dir2p);
+ normalize_v3(norm_v2);
+ f = e2->fprev;
+ if (dot_v3v3(norm_v2, f ? f->no : v->no) < 0.0f)
+ negate_v3(norm_v2);
+ }
+
/* get vectors perp to each edge, perp to norm_v, and pointing into face */
- cross_v3_v3v3(norm_perp1, dir1, norm_v);
- cross_v3_v3v3(norm_perp2, dir2, norm_v);
+ cross_v3_v3v3(norm_perp1, dir1, norm_v1);
+ cross_v3_v3v3(norm_perp2, dir2, norm_v2);
normalize_v3(norm_perp1);
normalize_v3(norm_perp2);
@@ -657,11 +789,10 @@ static void offset_meet(EdgeHalf *e1, EdgeHalf *e2, BMVert *v, BMFace *f, float
madd_v3_v3fl(off2a, norm_perp2, e2->offset_l);
add_v3_v3v3(off2b, off2a, dir2);
- /* intersect the lines; by construction they should be on the same plane and not parallel */
- if (!isect_line_line_v3(off1a, off1b, off2a, off2b, meetco, isect2)) {
-#ifdef BEVEL_ASSERT_PROJECT
- BLI_assert(!"offset_meet failure");
-#endif
+ /* intersect the lines */
+ isect_kind = isect_line_line_v3(off1a, off1b, off2a, off2b, meetco, isect2);
+ if (isect_kind == 0) {
+ /* lines are collinear: we already tested for this, but this used a different epsilon */
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)
@@ -681,15 +812,38 @@ static void offset_meet(EdgeHalf *e1, EdgeHalf *e2, BMVert *v, BMFace *f, float
copy_v3_v3(meetco, closer_v->co);
e1->offset_r = len_v3v3(meetco, v->co);
}
+ if (edges_between && e1->offset_r > 0.0f && e2->offset_l > 0.0f) {
+ /* Try to drop meetco to a face between e1 and e2 */
+ if (isect_kind == 2) {
+ /* lines didn't meet in 3d: get average of meetco and isect2 */
+ mid_v3_v3v3(meetco, meetco, isect2);
+ }
+ for (e = e1; e != e2; e = e->next) {
+ ff = e->fnext;
+ if (!ff)
+ continue;
+ plane_from_point_normal_v3(plane, v->co, ff->no);
+ closest_to_plane_normalized_v3(dropco, plane, meetco);
+ if (point_between_edges(dropco, v, ff, e, e->next)) {
+ copy_v3_v3(meetco, dropco);
+ break;
+ }
+ }
+ e1->offset_r = dist_to_line_v3(meetco, v->co, BM_edge_other_vert(e1->e, v)->co);
+ e2->offset_l = dist_to_line_v3(meetco, v->co, BM_edge_other_vert(e2->e, v)->co);
+ }
}
}
}
+/* chosen so that 1/sin(BEVEL_GOOD_ANGLE) is about 4, giving that expansion factor to bevel width */
+#define BEVEL_GOOD_ANGLE 0.25f
+
/* 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 */
+ * 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;
@@ -701,7 +855,7 @@ static bool offset_meet_edge(EdgeHalf *e1, EdgeHalf *e2, BMVert *v, float meetc
/* find angle from dir1 to dir2 as viewed from vertex normal side */
ang = angle_normalized_v3v3(dir1, dir2);
- if (ang < BEVEL_EPSILON) {
+ if (fabsf(ang) < BEVEL_GOOD_ANGLE) {
if (r_angle)
*r_angle = 0.0f;
return false;
@@ -712,10 +866,11 @@ static bool offset_meet_edge(EdgeHalf *e1, EdgeHalf *e2, BMVert *v, float meetc
if (r_angle)
*r_angle = ang;
- if (ang - (float)M_PI > BEVEL_EPSILON)
+ if (fabsf(ang - (float)M_PI) < BEVEL_GOOD_ANGLE)
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);
@@ -724,6 +879,17 @@ static bool offset_meet_edge(EdgeHalf *e1, EdgeHalf *e2, BMVert *v, float meetc
return true;
}
+/* Return true if it will look good to put the meeting point where offset_on_edge_between
+ * would put it. This means that neither side sees a reflex angle */
+static bool good_offset_on_edge_between(EdgeHalf *e1, EdgeHalf *e2, EdgeHalf *emid, BMVert *v)
+{
+ float ang;
+ float meet[3];
+
+ return offset_meet_edge(e1, emid, v, meet, &ang) &&
+ offset_meet_edge(emid, e2, v, meet, &ang);
+}
+
/* 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.
@@ -732,8 +898,9 @@ static bool offset_meet_edge(EdgeHalf *e1, EdgeHalf *e2, BMVert *v, float meetc
* 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])
+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];
@@ -782,81 +949,6 @@ static void offset_on_edge_between(BevelParams *bp, EdgeHalf *e1, EdgeHalf *e2,
e2->offset_l = d;
}
-/* 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])
-{
- 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, d;
- int iret;
-
- /* get direction vectors for two offset lines */
- sub_v3_v3v3(dir1, v->co, BM_edge_other_vert(e1->e, v)->co);
- sub_v3_v3v3(dir2, BM_edge_other_vert(e2->e, v)->co, v->co);
- sub_v3_v3v3(dirmid, BM_edge_other_vert(emid->e, v)->co, v->co);
-
- /* get directions into offset planes */
- /* calculate face normals at corner in case faces are nonplanar */
- cross_v3_v3v3(f1no, dirmid, dir1);
- cross_v3_v3v3(f2no, dirmid, dir2);
-
- /* if e1-v-emid or emid-v-e2 are reflex angles, need to flip corner normals */
- if (dot_v3v3(f1no, v->no) < 0.0f)
- negate_v3(f1no);
- if (dot_v3v3(f2no, v->no) < 0.0f)
- negate_v3(f2no);
-
- /* get vectors perpendicular to e1 and e2, pointing into the proper faces */
- cross_v3_v3v3(norm_perp1, dir1, f1no);
- normalize_v3(norm_perp1);
- cross_v3_v3v3(norm_perp2, dir2, f2no);
- normalize_v3(norm_perp2);
-
- /* get points that are offset distances from each line, then another point on each line */
- copy_v3_v3(off1a, v->co);
- madd_v3_v3fl(off1a, norm_perp1, e1->offset_r);
- sub_v3_v3v3(off1b, off1a, dir1);
- copy_v3_v3(off2a, v->co);
- madd_v3_v3fl(off2a, norm_perp2, e2->offset_l);
- add_v3_v3v3(off2b, off2a, dir2);
-
- ang = angle_v3v3(dir1, dir2);
- if (ang < BEVEL_EPSILON_BIG) {
- /* lines are parallel; put intersection on emid */
- offset_on_edge_between(bp, e1, e2, emid, v, meetco);
- }
- else if (fabsf(ang - (float)M_PI) < BEVEL_EPSILON_BIG) {
- 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_squared_v3v3(meetco, isect2) > 100.0f * BEVEL_EPSILON_SQ) {
- /* offset lines don't meet so can't preserve widths */
- offset_on_edge_between(bp, e1, e2, emid, v, meetco);
- }
- }
- /* else iret == 1 and the lines are coplanar so meetco has the intersection */
- }
-}
-
/* Offset by e->offset in plane with normal plane_no, on left if left==true,
* else on right. If no is NULL, choose an arbitrary plane different
* from eh's direction. */
@@ -904,11 +996,11 @@ static void project_to_edge(BMEdge *e, const float co_a[3], const float co_b[3],
/* If there is a bndv->ebev edge, find the mid control point if necessary.
* It is the closest point on the beveled edge to the line segment between
* bndv and bndv->next. */
-static void set_profile_params(BevelParams *bp, BoundVert *bndv)
+static void set_profile_params(BevelParams *bp, BevVert *bv, BoundVert *bndv)
{
EdgeHalf *e;
Profile *pro;
- float co1[3], co2[3], co3[3], d1[3], d2[3], d3[3], l;
+ float co1[3], co2[3], co3[3], d1[3], d2[3], l;
bool do_linear_interp;
copy_v3_v3(co1, bndv->nv.co);
@@ -942,18 +1034,37 @@ static void set_profile_params(BevelParams *bp, BoundVert *bndv)
cross_v3_v3v3(pro->plane_no, d1, d2);
l = normalize_v3(pro->plane_no);
if (l <= BEVEL_EPSILON_BIG) {
- /* co1 - midco -co2 are collinear - project plane that contains that line
- * and is perpendicular to the plane containing it and the beveled edge */
- cross_v3_v3v3(d3, d1, pro->proj_dir);
- normalize_v3(d3);
- cross_v3_v3v3(pro->plane_no, d1, d3);
- l = normalize_v3(pro->plane_no);
- if (l <= BEVEL_EPSILON_BIG) {
- /* whole profile is collinear with edge: just interpolate */
+ /* co1 - midco -co2 are collinear.
+ * Should be case that beveled edge is coplanar with two boundary verts.
+ * If the profile is going to lead into unbeveled edges on each side
+ * (that is, both BoundVerts are "on-edge" points on non-beveled edges)
+ * then in order to get curve in multi-segment case, change projection plane
+ * to be that common plane, projection dir to be the plane normal,
+ * and mid to be the original vertex.
+ * Otherwise, we just want to linearly interpolate between co1 and co2.
+ */
+ if (e->prev->is_bev || e->next->is_bev) {
do_linear_interp = true;
}
- /* signal to weld that this is linear */
- pro->super_r = PRO_LINE_R;
+ else {
+ copy_v3_v3(pro->coa, co1);
+ copy_v3_v3(pro->midco, bv->v->co);
+ copy_v3_v3(pro->cob, co2);
+ sub_v3_v3v3(d1, pro->midco, co1);
+ normalize_v3(d1);
+ sub_v3_v3v3(d2, pro->midco, co2);
+ normalize_v3(d2);
+ cross_v3_v3v3(pro->plane_no, d1, d2);
+ l = normalize_v3(pro->plane_no);
+ if (l <= BEVEL_EPSILON_BIG) {
+ /* whole profile is collinear with edge: just interpolate */
+ do_linear_interp = true;
+ }
+ else {
+ copy_v3_v3(pro->plane_co, bv->v->co);
+ copy_v3_v3(pro->proj_dir, pro->plane_no);
+ }
+ }
}
copy_v3_v3(pro->plane_co, co1);
}
@@ -1055,14 +1166,15 @@ static int bev_ccw_test(BMEdge *a, BMEdge *b, BMFace *f)
* and B has the right side as columns - both extended into homogeneous coords.
* So M = B*(Ainverse). Doing Ainverse by hand gives the code below.
*/
-static bool make_unit_square_map(const float va[3], const float vmid[3], const float vb[3],
- float r_mat[4][4])
+static bool make_unit_square_map(
+ const float va[3], const float vmid[3], const float vb[3],
+ float r_mat[4][4])
{
float vo[3], vd[3], vb_vmid[3], va_vmid[3], vddir[3];
sub_v3_v3v3(va_vmid, vmid, va);
sub_v3_v3v3(vb_vmid, vmid, vb);
- if (fabsf(angle_v3v3(va_vmid, vb_vmid) - (float)M_PI) > 100.0f * BEVEL_EPSILON) {
+ if (fabsf(angle_v3v3(va_vmid, vb_vmid) - (float)M_PI) > BEVEL_EPSILON_ANG) {
sub_v3_v3v3(vo, va, vb_vmid);
cross_v3_v3v3(vddir, vb_vmid, va_vmid);
normalize_v3(vddir);
@@ -1104,8 +1216,9 @@ static bool make_unit_square_map(const float va[3], const float vmid[3], const f
* and 1/2{va+vb+vc-vd}
* and Blender matrices have cols at m[i][*].
*/
-static void make_unit_cube_map(const float va[3], const float vb[3], const float vc[3],
- const float vd[3], float r_mat[4][4])
+static void make_unit_cube_map(
+ const float va[3], const float vb[3], const float vc[3],
+ const float vd[3], float r_mat[4][4])
{
copy_v3_v3(r_mat[0], va);
sub_v3_v3(r_mat[0], vb);
@@ -1386,56 +1499,99 @@ static void set_bound_vert_seams(BevVert *bv)
} while ((v = v->next) != bv->vmesh->boundstart);
}
-/* 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.
- * 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, bool construct)
+static int count_bound_vert_seams(BevVert *bv)
+{
+ int ans, i;
+
+ if (!bv->any_seam)
+ return 0;
+
+ ans = 0;
+ for (i = 0; i < bv->edgecount; i++)
+ if (bv->edges[i].is_seam)
+ ans++;
+ return ans;
+}
+
+/* Is e between two planes where angle between is 180? */
+static bool eh_on_plane(EdgeHalf *e)
+{
+ float dot;
+
+ if (e->fprev && e->fnext) {
+ dot = dot_v3v3(e->fprev->no, e->fnext->no);
+ if (fabsf(dot) <= BEVEL_EPSILON_BIG ||
+ fabsf(dot - 1.0f) <= BEVEL_EPSILON_BIG)
+ {
+ return true;
+ }
+ }
+ return false;
+}
+
+/* Calculate the profiles for all the BoundVerts of VMesh vm */
+static void calculate_vm_profiles(BevelParams *bp, BevVert *bv, VMesh *vm)
{
- MemArena *mem_arena = bp->mem_arena;
- EdgeHalf *efirst, *e, *eother;
BoundVert *v;
- BevVert *bvother;
- VMesh *vm;
+
+ v = vm->boundstart;
+ do {
+ set_profile_params(bp, bv, v);
+ calculate_profile(bp, v);
+ } while ((v = v->next) != vm->boundstart);
+}
+
+/* Implements build_boundary for vertex-only case */
+static void build_boundary_vertex_only(BevelParams *bp, BevVert *bv, bool construct)
+{
+ VMesh *vm = bv->vmesh;
+ EdgeHalf *efirst, *e;
+ BoundVert *v;
float co[3];
- const float *no;
- float lastd;
- vm = bv->vmesh;
+ BLI_assert(bp->vertex_only);
- if (bp->vertex_only) {
- e = efirst = &bv->edges[0];
- }
- 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;
+ e = efirst = &bv->edges[0];
+ do {
+ slide_dist(e, bv->v, e->offset_l, co);
+ if (construct) {
+ v = add_new_bound_vert(bp->mem_arena, vm, co);
+ v->efirst = v->elast = e;
+ e->leftv = v;
+ }
+ else {
+ adjust_bound_vert(e->leftv, co);
+ }
+ } while ((e = e->next) != efirst);
+
+ calculate_vm_profiles(bp, bv, vm);
+
+ if (construct) {
+ set_bound_vert_seams(bv);
+ if (vm->count == 2)
+ vm->mesh_kind = M_NONE;
+ else if (bp->seg == 1)
+ vm->mesh_kind = M_POLY;
+ else
+ vm->mesh_kind = M_ADJ;
}
+}
- BLI_assert(bv->edgecount >= 2); /* since bevel edges incident to 2 faces */
+/* Special case of build_boundary when a single edge is beveled.
+ * The 'width adjust' part of build_boundary has been done already, and
+ * efirst is the first beveled edge at vertex bv. */
+static void build_boundary_terminal_edge(BevelParams *bp, BevVert *bv, EdgeHalf *efirst, bool construct)
+{
+ MemArena *mem_arena = bp->mem_arena;
+ VMesh *vm = bv->vmesh;
+ BoundVert *v;
+ EdgeHalf *e;
+ const float *no;
+ float co[3], d;
- if (bv->edgecount == 2 && bv->selcount == 1) {
- /* special case: beveled edge meets non-beveled one at valence 2 vert */
+ e = efirst;
+ if (bv->edgecount == 2) {
+ /* only 2 edges in, so terminate the edge with an artificial vertex on the unbeveled edge */
no = e->fprev ? e->fprev->no : (e->fnext ? e->fnext->no : NULL);
offset_in_plane(e, no, true, co);
if (construct) {
@@ -1469,116 +1625,52 @@ static void build_boundary(BevelParams *bp, BevVert *bv, bool construct)
else {
adjust_bound_vert(e->next->leftv, co);
}
- set_profile_params(bp, vm->boundstart);
- calculate_profile(bp, vm->boundstart);
- return;
}
-
- lastd = bp->vertex_only ? bv->offset : e->offset_l;
- 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);
- 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 */
- if (e->prev->prev->is_bev) {
- BLI_assert(e->prev->prev != e); /* see: edgecount 2, selcount 1 case */
- /* find meet point between e->prev->prev and e and attach e->prev there */
- if (bp->preserve_widths)
- 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);
- 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);
- 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);
+ else {
+ /* More than 2 edges in. Put on-edge verts on all the other edges
+ * and join with the beveled edge to make a poly or adj mesh,
+ * Because e->prev has offset 0, offset_meet will put co on that edge. */
+ /* TODO: should do something else if angle between e and e->prev > 180 */
+ offset_meet(e->prev, e, bv->v, e->fprev, false, co);
+ 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 {
- /* e is not beveled */
- if (e->next->is_bev) {
- /* next iteration will place e between beveled previous and next edges */
- /* do nothing... */
- }
- else if (e->prev->is_bev) {
- /* on-edge meet between e->prev and e */
- offset_meet(e->prev, e, bv->v, e->fprev, co);
- 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);
- }
+ adjust_bound_vert(e->leftv, co);
+ }
+ e = e->next;
+ offset_meet(e->prev, e, bv->v, e->fprev, false, co);
+ 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);
+ }
+ /* For the edges not adjacent to the beveled edge, slide the bevel amount along. */
+ d = efirst->offset_l_spec;
+ for (e = e->next; e->next != efirst; e = e->next) {
+ slide_dist(e, bv->v, d, co);
+ if (construct) {
+ v = add_new_bound_vert(mem_arena, vm, co);
+ v->efirst = v->elast = e;
+ e->leftv = v;
}
else {
- /* None of e->prev, e, e->next are beveled.
- * could either leave alone or add slide points to make
- * one polygon around bv->v. For now, we choose latter.
- * 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);
- 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);
- }
+ adjust_bound_vert(e->leftv, co);
}
}
- } while ((e = e->next) != efirst);
-
- v = vm->boundstart;
- do {
- set_profile_params(bp, v);
- calculate_profile(bp, v);
- } while ((v = v->next) != vm->boundstart);
+ }
+ calculate_vm_profiles(bp, bv, vm);
- if (bv->selcount == 1 && bv->edgecount >= 3) {
+ if (bv->edgecount >= 3) {
/* special case: snap profile to plane of adjacent two edges */
v = vm->boundstart;
BLI_assert(v->ebev != NULL);
@@ -1589,30 +1681,169 @@ static void build_boundary(BevelParams *bp, BevVert *bv, bool construct)
if (construct) {
set_bound_vert_seams(bv);
- 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;
- else
- vm->mesh_kind = M_POLY;
- }
- else if (vm->count == 2 && bv->edgecount == 3) {
+ 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 (vm->count == 3) {
+ vm->mesh_kind = M_TRI_FAN;
+ }
+ else {
+ vm->mesh_kind = M_POLY;
}
- else if (efirst->seg == 1 || bv->selcount == 1) {
- if (vm->count == 3 && bv->selcount == 1) {
- vm->mesh_kind = M_TRI_FAN;
+ }
+}
+
+/* Return a value that is v if v is within BEVEL_MAX_ADJUST_PCT of the spec (assumed positive),
+ * else clamp to make it at most that far away from spec */
+static float clamp_adjust(float v, float spec)
+{
+ float allowed_delta = spec * (BEVEL_MAX_ADJUST_PCT / 100.0f);
+
+ if (v - spec > allowed_delta)
+ return spec + allowed_delta;
+ else if (spec - v > allowed_delta)
+ return spec - allowed_delta;
+ else
+ return v;
+}
+
+/* Make a circular list of BoundVerts for bv, each of which has the coordinates
+ * of a vertex on the boundary of the beveled vertex bv->v.
+ * 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, bool construct)
+{
+ MemArena *mem_arena = bp->mem_arena;
+ EdgeHalf *efirst, *e, *e2, *e3, *enip, *eip, *eother;
+ BoundVert *v;
+ BevVert *bvother;
+ VMesh *vm;
+ float co[3];
+ int nip, nnip;
+
+ /* Current bevel does nothing if only one edge into a vertex */
+ if (bv->edgecount <= 1)
+ return;
+
+ if (bp->vertex_only) {
+ build_boundary_vertex_only(bp, bv, construct);
+ return;
+ }
+
+ vm = bv->vmesh;
+
+ /* Find a beveled edge to be efirst. Then for each edge, try matching widths to other end. */
+ e = efirst = next_bev(bv, NULL);
+ BLI_assert(e->is_bev);
+ 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 */
+ /* sometimes, adjustment can accumulate errors so use the bp->limit_offset to
+ * let user limit the adjustment to within a reasonable range around spec */
+ if (bp->limit_offset) {
+ e->offset_l = clamp_adjust(eother->offset_r, e->offset_l_spec);
+ e->offset_r = clamp_adjust(eother->offset_l, e->offset_r_spec);
}
else {
- vm->mesh_kind = M_POLY;
+ 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);
+
+ if (bv->selcount == 1) {
+ /* special case: only one beveled edge in */
+ build_boundary_terminal_edge(bp, bv, efirst, construct);
+ return;
+ }
+
+ /* Here: there is more than one beveled edge.
+ * We make BoundVerts to connect the sides of the beveled edges.
+ * Non-beveled edges in between will just join to the appropriate juncture point. */
+ e = efirst;
+ do {
+ BLI_assert(e->is_bev);
+ /* Make the BoundVert for the right side of e; other side will be made
+ * when the beveled edge to the left of e is handled.
+ * Analyze edges until next beveled edge.
+ * They are either "in plane" (preceding and subsequent faces are coplanar)
+ * or not. The "non-in-plane" edges effect silhouette and we prefer to slide
+ * along one of those if possible. */
+ nip = nnip = 0; /* counts of in-plane / not-in-plane */
+ enip = eip = NULL; /* representatives of each */
+ for (e2 = e->next; !e2->is_bev; e2 = e2->next) {
+ if (eh_on_plane(e2)) {
+ nip++;
+ eip = e2;
+ }
+ else {
+ nnip++;
+ enip = e2;
+ }
+ }
+ if (nip == 0 && nnip == 0) {
+ offset_meet(e, e2, bv->v, e->fnext, false, co);
+ }
+ else if (nnip > 0) {
+ if (bp->loop_slide && nnip == 1 && good_offset_on_edge_between(e, e2, enip, bv->v)) {
+ offset_on_edge_between(bp, e, e2, enip, bv->v, co);
+ }
+ else {
+ offset_meet(e, e2, bv->v, NULL, true, co);
+ }
+ }
+ else {
+ /* nip > 0 and nnip == 0 */
+ if (bp->loop_slide && nip == 1 && good_offset_on_edge_between(e, e2, eip, bv->v)) {
+ offset_on_edge_between(bp, e, e2, eip, bv->v, co);
+ }
+ else {
+ offset_meet(e, e2, bv->v, e->fnext, true, co);
+ }
+ }
+ if (construct) {
+ v = add_new_bound_vert(mem_arena, vm, co);
+ v->efirst = e;
+ v->elast = e2;
+ v->ebev = e2;
+ e->rightv = v;
+ e2->leftv = v;
+ for (e3 = e->next; e3 != e2; e3 = e3->next) {
+ e3->leftv = e3->rightv = v;
+ }
+ }
+ else {
+ adjust_bound_vert(e->rightv, co);
+ }
+ e = e2;
+ } while (e != efirst);
+
+ calculate_vm_profiles(bp, bv, vm);
+
+ if (construct) {
+ set_bound_vert_seams(bv);
+
+ if (vm->count == 2) {
+ vm->mesh_kind = M_NONE;
+ }
+ else if (efirst->seg == 1) {
+ vm->mesh_kind = M_POLY;
+ }
+ else {
vm->mesh_kind = M_ADJ;
}
}
@@ -1723,7 +1954,7 @@ static BoundVert *pipe_test(BevVert *bv)
sub_v3_v3v3(dir3, BM_edge_other_vert(v3->ebev->e, bv->v)->co, bv->v->co);
normalize_v3(dir1);
normalize_v3(dir3);
- if (angle_normalized_v3v3(dir1, dir3) < BEVEL_EPSILON_BIG) {
+ if (angle_normalized_v3v3(dir1, dir3) < BEVEL_EPSILON_ANG) {
epipe = v1->ebev;
break;
}
@@ -1736,7 +1967,7 @@ static BoundVert *pipe_test(BevVert *bv)
/* check face planes: all should have normals perpendicular to epipe */
for (e = &bv->edges[0]; e != &bv->edges[bv->edgecount]; e++) {
if (e->fnext) {
- if (dot_v3v3(dir1, e->fnext->no) > BEVEL_EPSILON)
+ if (dot_v3v3(dir1, e->fnext->no) > BEVEL_EPSILON_BIG)
return NULL;
}
}
@@ -1836,9 +2067,10 @@ static void vmesh_center(VMesh *vm, float r_cent[3])
}
}
-static void avg4(float co[3],
- const NewVert *v0, const NewVert *v1,
- const NewVert *v2, const NewVert *v3)
+static void avg4(
+ float co[3],
+ const NewVert *v0, const NewVert *v1,
+ const NewVert *v2, const NewVert *v3)
{
add_v3_v3v3(co, v0->co, v1->co);
add_v3_v3(co, v2->co);
@@ -2229,7 +2461,6 @@ static VMesh *make_cube_corner_adj_vmesh(BevelParams *bp)
BoundVert *bndv;
int i, j, k, ns2;
float co[3], coc[3];
- float w;
if (r == PRO_SQUARE_R)
return make_cube_corner_straight(mem_arena, nseg);
@@ -2262,10 +2493,8 @@ static VMesh *make_cube_corner_adj_vmesh(BevelParams *bp)
bndv = bndv->next;
}
/* center vertex */
- w = (float)(1.0 / M_SQRT3);
- co[0] = w;
- co[1] = w;
- co[2] = w;
+ copy_v3_fl(co, M_SQRT1_3);
+
if (nseg > 2) {
if (r > 1.5f)
mul_v3_fl(co, 1.4f);
@@ -2492,6 +2721,63 @@ static VMesh *pipe_adj_vmesh(BevelParams *bp, BevVert *bv, BoundVert *vpipe)
return vm;
}
+static void get_incident_edges(BMFace *f, BMVert *v, BMEdge **r_e1, BMEdge **r_e2)
+{
+ BMIter iter;
+ BMEdge *e;
+
+ *r_e1 = NULL;
+ *r_e2 = NULL;
+ if (!f)
+ return;
+ BM_ITER_ELEM (e, &iter, f, BM_EDGES_OF_FACE) {
+ if (e->v1 == v || e->v2 == v) {
+ if (*r_e1 == NULL)
+ *r_e1 = e;
+ else if (*r_e2 == NULL)
+ *r_e2 = e;
+ }
+ }
+}
+
+static BMEdge *find_closer_edge(float *co, BMEdge *e1, BMEdge *e2)
+{
+ float dsq1, dsq2;
+
+ BLI_assert(e1 != NULL && e2 != NULL);
+ dsq1 = dist_squared_to_line_segment_v3(co, e1->v1->co, e1->v2->co);
+ dsq2 = dist_squared_to_line_segment_v3(co, e2->v1->co, e2->v2->co);
+ if (dsq1 < dsq2)
+ return e1;
+ else
+ return e2;
+}
+
+/* Snap co to the closest edge of face f. Return the edge in *r_snap_e,
+ * the coordinates of snap point in r_ snap_co,
+ * and the distance squared to the snap point as function return */
+static float snap_face_dist_squared(float *co, BMFace *f, BMEdge **r_snap_e, float *r_snap_co)
+{
+ BMIter iter;
+ BMEdge *beste = NULL;
+ float d2, beste_d2;
+ BMEdge *e;
+ float closest[3];
+
+ beste_d2 = 1e20;
+ BM_ITER_ELEM(e, &iter, f, BM_EDGES_OF_FACE) {
+ closest_to_line_segment_v3(closest, co, e->v1->co, e->v2->co);
+ d2 = len_squared_v3v3(closest, co);
+ if (d2 < beste_d2) {
+ beste_d2 = d2;
+ beste = e;
+ copy_v3_v3(r_snap_co, closest);
+ }
+ }
+ *r_snap_e = beste;
+ return beste_d2;
+}
+
/*
* Given that the boundary is built and the boundary BMVerts have been made,
* calculate the positions of the interior mesh points for the M_ADJ pattern,
@@ -2502,7 +2788,9 @@ static void bevel_build_rings(BevelParams *bp, BMesh *bm, BevVert *bv)
VMesh *vm1, *vm;
BoundVert *v;
BMVert *bmv1, *bmv2, *bmv3, *bmv4;
- BMFace *f, *f2, *f23;
+ BMFace *f, *f2;
+ BMEdge *bme, *bme1, *bme2, *bme3;
+ EdgeHalf *e;
BoundVert *vpipe;
int mat_nr = bp->mat_nr;
@@ -2540,8 +2828,14 @@ static void bevel_build_rings(BevelParams *bp, BMesh *bm, BevVert *bv)
v = vm->boundstart;
do {
i = v->index;
- f = boundvert_rep_face(v);
- f2 = boundvert_rep_face(v->next);
+ f = boundvert_rep_face(v, NULL);
+ f2 = boundvert_rep_face(v->next, NULL);
+ if (bp->vertex_only)
+ e = v->efirst;
+ else
+ e = v->ebev;
+ BLI_assert(e != NULL);
+ bme = e->e;
/* For odd ns, make polys with lower left corner at (i,j,k) for
* j in [0, ns2-1], k in [0, ns2]. And then the center ngon.
* For even ns,
@@ -2553,11 +2847,54 @@ static void bevel_build_rings(BevelParams *bp, BMesh *bm, BevVert *bv)
bmv3 = mesh_vert(vm, i, j + 1, k + 1)->v;
bmv4 = mesh_vert(vm, i, j + 1, k)->v;
BLI_assert(bmv1 && bmv2 && bmv3 && bmv4);
- f23 = f;
- if (odd && k == ns2 && f2 && !v->any_seam)
- f23 = f2;
- bev_create_quad_tri_ex(bm, bmv1, bmv2, bmv3, bmv4,
- f, f23, f23, f, mat_nr);
+ if (bp->vertex_only) {
+ if (j < k) {
+ if (k == ns2 && j == ns2 - 1) {
+ bev_create_quad_ex(bm, bmv1, bmv2, bmv3, bmv4, f2, f2, f2, f2,
+ NULL, NULL, v->next->efirst->e, bme, mat_nr);
+ }
+ else {
+ bev_create_quad(bm, bmv1, bmv2, bmv3, bmv4, f2, f2, f2, f2, mat_nr);
+ }
+ }
+ else if (j > k) {
+ bev_create_quad(bm, bmv1, bmv2, bmv3, bmv4, f2, f2, f2, f2, mat_nr);
+ }
+ else { /* j == k */
+ /* only one edge attached to v, since vertex_only */
+ if (e->is_seam) {
+ bev_create_quad_ex(bm, bmv1, bmv2, bmv3, bmv4, f2, f2, f2, f2,
+ bme, NULL, bme, NULL, mat_nr);
+ }
+ else {
+ bev_create_quad_ex(bm, bmv1, bmv2, bmv3, bmv4, f2, f2, f2, f,
+ bme, NULL, bme, NULL, mat_nr);
+ }
+ }
+ }
+ else { /* edge bevel */
+ if (odd) {
+ if (k == ns2) {
+ if (e->is_seam) {
+ bev_create_quad_ex(bm, bmv1, bmv2, bmv3, bmv4, f, f, f, f,
+ NULL, bme, bme, NULL, mat_nr);
+ }
+ else {
+ bev_create_quad(bm, bmv1, bmv2, bmv3, bmv4, f, f2, f2, f, mat_nr);
+ }
+ }
+ else {
+ bev_create_quad(bm, bmv1, bmv2, bmv3, bmv4, f, f, f, f, mat_nr);
+ }
+ }
+ else {
+ bme1 = k == ns2 - 1 ? bme : NULL;
+ bme3 = j == ns2 - 1 ? v->prev->ebev->e : NULL;
+ bme2 = bme1 != NULL ? bme1 : bme3;
+ bev_create_quad_ex(bm, bmv1, bmv2, bmv3, bmv4, f, f, f, f,
+ NULL, bme1, bme2, bme3, mat_nr);
+ }
+ }
}
}
} while ((v = v->next) != vm->boundstart);
@@ -2576,66 +2913,147 @@ static void bevel_build_rings(BevelParams *bp, BMesh *bm, BevVert *bv)
}
}
} while ((v = v->next) != vm->boundstart);
- if (!bv->any_seam)
- bev_merge_uvs(bm, mesh_vert(vm, 0, ns2, ns2)->v);
+ bmv1 = mesh_vert(vm, 0, ns2, ns2)->v;
+ if (bp->vertex_only || count_bound_vert_seams(bv) <= 1)
+ bev_merge_uvs(bm, bmv1);
}
/* center ngon */
if (odd) {
+ BMFace *frep;
+ BMEdge *frep_e1, *frep_e2, *frep_e;
BMVert **vv = NULL;
BMFace **vf = NULL;
+ BMEdge **ve = NULL;
BLI_array_staticdeclare(vv, BM_DEFAULT_NGON_STACK_SIZE);
BLI_array_staticdeclare(vf, BM_DEFAULT_NGON_STACK_SIZE);
+ BLI_array_staticdeclare(ve, BM_DEFAULT_NGON_STACK_SIZE);
+ if (bv->any_seam) {
+ frep = boundvert_rep_face(vm->boundstart, NULL);
+ get_incident_edges(frep, bv->v, &frep_e1, &frep_e2);
+ }
+ else {
+ frep = NULL;
+ frep_e1 = frep_e2 = NULL;
+ }
v = vm->boundstart;
do {
i = v->index;
BLI_array_append(vv, mesh_vert(vm, i, ns2, ns2)->v);
- BLI_array_append(vf, v->any_seam ? f : boundvert_rep_face(v));
+ if (frep) {
+ BLI_array_append(vf, frep);
+ frep_e = find_closer_edge(mesh_vert(vm, i, ns2, ns2)->v->co, frep_e1, frep_e2);
+ BLI_array_append(ve, v == vm->boundstart ? NULL : frep_e);
+ }
+ else {
+ BLI_array_append(vf, boundvert_rep_face(v, NULL));
+ BLI_array_append(ve, NULL);
+ }
} while ((v = v->next) != vm->boundstart);
- f = boundvert_rep_face(vm->boundstart);
- bev_create_ngon(bm, vv, BLI_array_count(vv), vf, f, mat_nr, true);
+ bev_create_ngon(bm, vv, BLI_array_count(vv), vf, frep, ve, mat_nr, true);
BLI_array_free(vv);
+ BLI_array_free(vf);
+ BLI_array_free(ve);
+ }
+}
+
+/* If we make a poly out of verts around bv, snapping to rep frep, will uv poly have zero area?
+ * The uv poly is made by snapping all outside-of-frep vertices to the closest edge in frep.
+ * Assume that this funciton is called when the only inside-of-frep vertex is vm->boundstart.
+ * The poly will have zero area if the distance of that first vertex to some edge e is zero, and all
+ * the other vertices snap to e or snap to an edge at a point that is essentially on e too. */
+static bool is_bad_uv_poly(BevVert *bv, BMFace *frep)
+{
+ BoundVert *v;
+ BMEdge *snape, *firste;
+ float co[3];
+ VMesh *vm = bv->vmesh;
+ float d2;
+
+ v = vm->boundstart;
+ d2 = snap_face_dist_squared(v->nv.v->co, frep, &firste, co);
+ if (d2 > BEVEL_EPSILON_BIG_SQ || firste == NULL)
+ return false;
+
+ for (v = v->next; v != vm->boundstart; v = v->next) {
+ snap_face_dist_squared(v->nv.v->co, frep, &snape, co);
+ if (snape != firste) {
+ d2 = dist_to_line_v3(co, firste->v1->co, firste->v2->co);
+ if (d2 > BEVEL_EPSILON_BIG_SQ)
+ return false;
+ }
}
+ return true;
}
static BMFace *bevel_build_poly(BevelParams *bp, BMesh *bm, BevVert *bv)
{
- BMFace *f;
+ BMFace *f, *frep, *frep2;
int n, k;
VMesh *vm = bv->vmesh;
BoundVert *v;
- BMFace *frep;
+ BMEdge *frep_e1, *frep_e2, *frep_e;
BMVert **vv = NULL;
BMFace **vf = NULL;
+ BMEdge **ve = NULL;
BLI_array_staticdeclare(vv, BM_DEFAULT_NGON_STACK_SIZE);
BLI_array_staticdeclare(vf, BM_DEFAULT_NGON_STACK_SIZE);
+ BLI_array_staticdeclare(ve, BM_DEFAULT_NGON_STACK_SIZE);
- frep = boundvert_rep_face(vm->boundstart);
+ if (bv->any_seam) {
+ frep = boundvert_rep_face(vm->boundstart, &frep2);
+ if (frep2 && frep && is_bad_uv_poly(bv, frep)) {
+ frep = frep2;
+ }
+ get_incident_edges(frep, bv->v, &frep_e1, &frep_e2);
+ }
+ else {
+ frep = NULL;
+ frep_e1 = frep_e2 = NULL;
+ }
v = vm->boundstart;
n = 0;
do {
/* accumulate vertices for vertex ngon */
/* also accumulate faces in which uv interpolation is to happen for each */
BLI_array_append(vv, v->nv.v);
- BLI_array_append(vf, bv->any_seam ? frep : boundvert_rep_face(v));
+ if (frep) {
+ BLI_array_append(vf, frep);
+ frep_e = find_closer_edge(v->nv.v->co, frep_e1, frep_e2);
+ BLI_array_append(ve, n > 0 ? frep_e : NULL);
+ }
+ else {
+ BLI_array_append(vf, boundvert_rep_face(v, NULL));
+ BLI_array_append(ve, NULL);
+ }
n++;
if (v->ebev && v->ebev->seg > 1) {
for (k = 1; k < v->ebev->seg; k++) {
BLI_array_append(vv, mesh_vert(vm, v->index, 0, k)->v);
- BLI_array_append(vf, bv->any_seam ? frep : boundvert_rep_face(v));
+ if (frep) {
+ BLI_array_append(vf, frep);
+ frep_e = find_closer_edge(mesh_vert(vm, v->index, 0, k)->v->co, frep_e1, frep_e2);
+ BLI_array_append(ve, k < v->ebev->seg / 2 ? NULL : frep_e);
+ }
+ else {
+ BLI_array_append(vf, boundvert_rep_face(v, NULL));
+ BLI_array_append(ve, NULL);
+ }
n++;
}
}
} while ((v = v->next) != vm->boundstart);
if (n > 2) {
- f = bev_create_ngon(bm, vv, n, vf, boundvert_rep_face(v), bp->mat_nr, true);
+ f = bev_create_ngon(bm, vv, n, vf, frep, ve, bp->mat_nr, true);
}
else {
f = NULL;
}
BLI_array_free(vv);
+ BLI_array_free(vf);
+ BLI_array_free(ve);
return f;
}
@@ -2712,23 +3130,60 @@ static void bevel_build_quadstrip(BevelParams *bp, BMesh *bm, BevVert *bv)
}
}
-/* Special case: there is no vmesh pattern because this has only two boundary verts,
- * and there are no faces in the original mesh at the original vertex.
- * Since there will be no rebuilt face to make the edge between the boundary verts,
+/* Special case: vertex bevel with only two boundary verts.
+ * Want to make a curved edge if seg > 0.
+ * If there are no faces in the original mesh at the original vertex,
+ * there will be no rebuilt face to make the edge between the boundary verts,
* we have to make it here. */
-static void bevel_build_one_wire(BMesh *bm, BevVert *bv)
+static void bevel_vert_two_edges(BevelParams *bp, BMesh *bm, BevVert *bv)
{
VMesh *vm = bv->vmesh;
BMVert *v1, *v2;
BMEdge *e_eg;
+ Profile *pro;
+ float co[3];
+ BoundVert *bndv;
+ int ns, k;
- BLI_assert(vm->count == 2);
+ BLI_assert(vm->count == 2 && bp->vertex_only);
v1 = mesh_vert(vm, 0, 0, 0)->v;
v2 = mesh_vert(vm, 1, 0, 0)->v;
- e_eg = bv->edges[0].e;
- BLI_assert(v1 != NULL && v2 != NULL && e_eg != NULL);
- BM_edge_create(bm, v1, v2, e_eg, BM_CREATE_NO_DOUBLE);
+
+ ns = vm->seg;
+ if (ns > 1) {
+ /* Set up profile parameters */
+ bndv = vm->boundstart;
+ pro = &bndv->profile;
+ pro->super_r = bp->pro_super_r;
+ copy_v3_v3(pro->coa, v1->co);
+ copy_v3_v3(pro->cob, v2->co);
+ copy_v3_v3(pro->midco, bv->v->co);
+ /* don't use projection */
+ zero_v3(pro->plane_co);
+ zero_v3(pro->plane_no);
+ zero_v3(pro->proj_dir);
+ calculate_profile(bp, bndv);
+ for (k = 1; k < ns; k++) {
+ get_profile_point(bp, pro, k, ns, co);
+ copy_v3_v3(mesh_vert(vm, 0, 0, k)->co, co);
+ create_mesh_bmvert(bm, vm, 0, 0, k, bv->v);
+ }
+ copy_v3_v3(mesh_vert(vm, 0, 0, ns)->co, v2->co);
+ for (k = 1; k < ns; k++)
+ copy_mesh_vert(vm, 1, 0, ns - k, 0, 0, k);
+ }
+
+ if (BM_vert_face_check(bv->v) == false) {
+ e_eg = bv->edges[0].e;
+ BLI_assert(e_eg != NULL);
+ for (k = 0; k < ns; k++) {
+ v1 = mesh_vert(vm, 0, 0, k)->v;
+ v2 = mesh_vert(vm, 0, 0, k + 1)->v;
+ BLI_assert(v1 != NULL && v2 != NULL);
+ BM_edge_create(bm, v1, v2, e_eg, BM_CREATE_NO_DOUBLE);
+ }
+ }
}
/* Given that the boundary is built, now make the actual BMVerts
@@ -2814,8 +3269,8 @@ static void build_vmesh(BevelParams *bp, BMesh *bm, BevVert *bv)
switch (vm->mesh_kind) {
case M_NONE:
- if (n == 2 && BM_vert_face_count(bv->v) == 0)
- bevel_build_one_wire(bm, bv);
+ if (n == 2 && bp->vertex_only)
+ bevel_vert_two_edges(bp, bm, bv);
break;
case M_POLY:
bevel_build_poly(bp, bm, bv);
@@ -2898,8 +3353,9 @@ static BevVert *bevel_vert_construct(BMesh *bm, BevelParams *bp, BMVert *v)
nwire++;
/* If edge beveling, exclude wire edges from edges array.
* Mark this edge as "chosen" so loop below won't choose it. */
- if (!bp->vertex_only)
+ if (!bp->vertex_only) {
BM_BEVEL_EDGE_TAG_ENABLE(bme);
+ }
}
}
if (!first_bme)
@@ -2935,6 +3391,10 @@ static BevVert *bevel_vert_construct(BMesh *bm, BevelParams *bp, BMVert *v)
}
bv->offset *= weight;
}
+ else if (bp->use_weights) {
+ weight = BM_elem_float_data_get(&bm->vdata, v, CD_BWEIGHT);
+ bv->offset *= weight;
+ }
}
BLI_ghash_insert(bp->vert_hash, v, bv);
@@ -3077,6 +3537,18 @@ static BevVert *bevel_vert_construct(BMesh *bm, BevelParams *bp, BMVert *v)
e->offset_r_spec *= weight;
}
}
+ else if (bp->vertex_only) {
+ /* Weight has already been applied to bv->offset, if present.
+ * Transfer to e->offset_[lr]_spec and treat percent as special case */
+ if (bp->offset_type == BEVEL_AMT_PERCENT) {
+ v2 = BM_edge_other_vert(e->e, bv->v);
+ e->offset_l_spec = BM_edge_calc_length(e->e) * bv->offset / 100.0f;
+ }
+ else {
+ e->offset_l_spec = bv->offset;
+ }
+ e->offset_r_spec = e->offset_l_spec;
+ }
else {
e->offset_l_spec = e->offset_r_spec = 0.0f;
}
@@ -3155,7 +3627,7 @@ static bool bev_rebuild_polygon(BMesh *bm, BevelParams *bp, BMFace *f)
BLI_array_append(vv_fix, bmv);
}
}
- else if (vm->mesh_kind == M_ADJ && vm->seg > 1 && !e->is_bev && !eprev->is_bev) {
+ else if ((vm->mesh_kind == M_ADJ || bp->vertex_only) && vm->seg > 1 && !e->is_bev && !eprev->is_bev) {
BLI_assert(v->prev == vend);
i = vend->index;
for (k = vm->seg - 1; k > 0; k--) {
@@ -3178,7 +3650,7 @@ static bool bev_rebuild_polygon(BMesh *bm, BevelParams *bp, BMFace *f)
}
if (do_rebuild) {
n = BLI_array_count(vv);
- f_new = bev_create_ngon(bm, vv, n, NULL, f, -1, true);
+ f_new = bev_create_ngon(bm, vv, n, NULL, f, NULL, -1, true);
for (k = 0; k < BLI_array_count(vv_fix); k++) {
bev_merge_uvs(bm, vv_fix[k]);
@@ -3376,18 +3848,20 @@ static void weld_cross_attrs_copy(BMesh *bm, BevVert *bv, VMesh *vm, int vmindex
}
}
-
/*
* Build the polygons along the selected Edge
*/
static void bevel_build_edge_polygons(BMesh *bm, BevelParams *bp, BMEdge *bme)
{
BevVert *bv1, *bv2;
- BMVert *bmv1, *bmv2, *bmv3, *bmv4, *bmv1i, *bmv2i, *bmv3i, *bmv4i;
+ BMVert *bmv1, *bmv2, *bmv3, *bmv4;
VMesh *vm1, *vm2;
EdgeHalf *e1, *e2;
- BMEdge *bme1, *bme2;
+ BMEdge *bme1, *bme2, *center_bme;
BMFace *f1, *f2, *f;
+ BMVert *verts[4];
+ BMFace *faces[4];
+ BMEdge *edges[4];
int k, nseg, i1, i2, odd, mid;
int mat_nr = bp->mat_nr;
@@ -3404,11 +3878,15 @@ static void bevel_build_edge_polygons(BMesh *bm, BevelParams *bp, BMEdge *bme)
BLI_assert(e1 && e2);
- /* v4 v3
- * \ /
- * e->v1 - e->v2
- * / \
- * v1 v2
+ /*
+ * bme->v1
+ * / | \
+ * v1--|--v4
+ * | | |
+ * | | |
+ * v2--|--v3
+ * \ | /
+ * bme->v2
*/
nseg = e1->seg;
BLI_assert(nseg > 0 && nseg == e2->seg);
@@ -3422,42 +3900,67 @@ static void bevel_build_edge_polygons(BMesh *bm, BevelParams *bp, BMEdge *bme)
f1 = e1->fprev;
f2 = e1->fnext;
+ faces[0] = faces[1] = f1;
+ faces[2] = faces[3] = f2;
i1 = e1->leftv->index;
i2 = e2->leftv->index;
vm1 = bv1->vmesh;
vm2 = bv2->vmesh;
- if (nseg == 1) {
- bev_create_quad_straddle(bm, bmv1, bmv2, bmv3, bmv4, f1, f2, mat_nr, e1->is_seam);
- }
- else {
- bmv1i = bmv1;
- bmv2i = bmv2;
- odd = nseg % 2;
- mid = nseg / 2;
- for (k = 1; k <= nseg; k++) {
- bmv4i = mesh_vert(vm1, i1, 0, k)->v;
- bmv3i = mesh_vert(vm2, i2, 0, nseg - k)->v;
- if (odd && k == mid + 1) {
- bev_create_quad_straddle(bm, bmv1i, bmv2i, bmv3i, bmv4i, f1, f2, mat_nr, e1->is_seam);
+ verts[0] = bmv1;
+ verts[1] = bmv2;
+ odd = nseg % 2;
+ mid = nseg / 2;
+ center_bme = NULL;
+ for (k = 1; k <= nseg; k++) {
+ verts[3] = mesh_vert(vm1, i1, 0, k)->v;
+ verts[2] = mesh_vert(vm2, i2, 0, nseg - k)->v;
+ if (odd && k == mid + 1) {
+ if (e1->is_seam) {
+ /* straddles a seam: choose to interpolate in f1 and snap right edge to bme */
+ edges[0] = edges[1] = NULL;
+ edges[2] = edges[3] = bme;
+ bev_create_ngon(bm, verts, 4, NULL, f1, edges, mat_nr, true);
}
else {
- f = (k <= mid) ? f1 : f2;
- bev_create_quad_tri(bm, bmv1i, bmv2i, bmv3i, bmv4i, f, mat_nr, true);
+ /* straddles but not a seam: interpolate left half in f1, right half in f2 */
+ bev_create_ngon(bm, verts, 4, faces, NULL, NULL, mat_nr, true);
}
- bmv1i = bmv4i;
- bmv2i = bmv3i;
}
- if (!odd && !e1->is_seam) {
- bev_merge_uvs(bm, mesh_vert(vm1, i1, 0, mid)->v);
- bev_merge_uvs(bm, mesh_vert(vm2, i2, 0, mid)->v);
+ else if (!odd && k == mid) {
+ /* left poly that touches an even center line on right */
+ edges[0] = edges[1] = NULL;
+ edges[2] = edges[3] = bme;
+ bev_create_ngon(bm, verts, 4, NULL, f1, edges, mat_nr, true);
+ center_bme = BM_edge_exists(verts[2], verts[3]);
+ BLI_assert(center_bme != NULL);
+ }
+ else if (!odd && k == mid + 1) {
+ /* right poly that touches an even center line on left */
+ edges[0] = edges[1] = bme;
+ edges[2] = edges[3] = NULL;
+ bev_create_ngon(bm, verts, 4, NULL, f2, edges, mat_nr, true);
+ }
+ else {
+ /* doesn't cross or touch the center line, so interpolate in appropriate f1 or f2 */
+ f = (k <= mid) ? f1 : f2;
+ bev_create_ngon(bm, verts, 4, NULL, f, NULL, mat_nr, true);
}
+ verts[0] = verts[3];
+ verts[1] = verts[2];
+ }
+ if (!odd) {
+ if (!e1->is_seam)
+ bev_merge_edge_uvs(bm, center_bme, mesh_vert(vm1, i1, 0, mid)->v);
+ if (!e2->is_seam)
+ bev_merge_edge_uvs(bm, center_bme, mesh_vert(vm2, i2, 0, mid)->v);
}
/* Fix UVs along end edge joints. A nop unless other side built already. */
- if (!e1->is_seam && bv1->vmesh->mesh_kind == M_NONE)
+ /* TODO: if some seam, may want to do selective merge */
+ if (!bv1->any_seam && bv1->vmesh->mesh_kind == M_NONE)
bev_merge_end_uvs(bm, bv1, e1);
- if (!e2->is_seam && bv2->vmesh->mesh_kind == M_NONE)
+ if (!bv2->any_seam && bv2->vmesh->mesh_kind == M_NONE)
bev_merge_end_uvs(bm, bv2, e2);
/* Copy edge data to first and last edge */
@@ -3529,7 +4032,7 @@ static float find_superellipse_chord_u(float u0, float d2goal, float r)
* Return the u's in *r_params, which should point to an array of size n+1. */
static void find_even_superellipse_params(int n, float r, float *r_params)
{
- float d2low, d2high, d2, d2final, u;
+ float d2low, d2high, d2 = 0.0f, d2final, u;
int i, j, n2;
const int maxiters = 40;
const float d2tol = 1e-6f;
@@ -3679,10 +4182,12 @@ static float bevel_limit_offset(BMesh *bm, BevelParams *bp)
*
* \warning all tagged edges _must_ be manifold.
*/
-void BM_mesh_bevel(BMesh *bm, const float offset, const int offset_type,
- const float segments, const float profile,
- const bool vertex_only, const bool use_weights, const bool limit_offset,
- const struct MDeformVert *dvert, const int vertex_group, const int mat)
+void BM_mesh_bevel(
+ BMesh *bm, const float offset, const int offset_type,
+ const float segments, const float profile,
+ const bool vertex_only, const bool use_weights, const bool limit_offset,
+ const struct MDeformVert *dvert, const int vertex_group, const int mat,
+ const bool loop_slide)
{
BMIter iter;
BMVert *v, *v_next;
@@ -3696,7 +4201,7 @@ void BM_mesh_bevel(BMesh *bm, const float offset, const int offset_type,
bp.pro_super_r = 4.0f * profile; /* convert to superellipse exponent */
bp.vertex_only = vertex_only;
bp.use_weights = use_weights;
- bp.preserve_widths = false;
+ bp.loop_slide = loop_slide;
bp.limit_offset = limit_offset;
bp.dvert = dvert;
bp.vertex_group = vertex_group;
diff --git a/source/blender/bmesh/tools/bmesh_bevel.h b/source/blender/bmesh/tools/bmesh_bevel.h
index 52d8faa5401..386dc8a1fce 100644
--- a/source/blender/bmesh/tools/bmesh_bevel.h
+++ b/source/blender/bmesh/tools/bmesh_bevel.h
@@ -29,9 +29,10 @@
struct MDeformVert;
-void BM_mesh_bevel(BMesh *bm, const float offset, const int offset_type, const float segments,
- const float profile, const bool vertex_only, const bool use_weights,
- const bool limit_offset, const struct MDeformVert *dvert, const int vertex_group,
- const int mat);
+void BM_mesh_bevel(
+ BMesh *bm, const float offset, const int offset_type, const float segments,
+ const float profile, const bool vertex_only, const bool use_weights,
+ const bool limit_offset, const struct MDeformVert *dvert, const int vertex_group,
+ const int mat, const bool loop_slide);
#endif /* __BMESH_BEVEL_H__ */
diff --git a/source/blender/bmesh/tools/bmesh_bisect_plane.c b/source/blender/bmesh/tools/bmesh_bisect_plane.c
index ae9b882cea0..fbcf573acd9 100644
--- a/source/blender/bmesh/tools/bmesh_bisect_plane.c
+++ b/source/blender/bmesh/tools/bmesh_bisect_plane.c
@@ -53,7 +53,7 @@
/* -------------------------------------------------------------------- */
/* Math utils */
-static int plane_point_test_v3(const float plane[4], const float co[3], const float eps, float *r_depth)
+static short plane_point_test_v3(const float plane[4], const float co[3], const float eps, float *r_depth)
{
const float f = plane_point_side_v3(plane, co);
*r_depth = f;
@@ -69,7 +69,8 @@ static int plane_point_test_v3(const float plane[4], const float co[3], const fl
* later we may want to move this into some hash lookup
* to a separate struct, but for now we can store in BMesh data */
-#define BM_VERT_DIR(v) ((v)->head.index) /* Direction -1/0/1 */
+#define BM_VERT_DIR(v) ((short *)(&(v)->head.index))[0] /* Direction -1/0/1 */
+#define BM_VERT_SKIP(v) ((short *)(&(v)->head.index))[1] /* Skip Vert 0/1 */
#define BM_VERT_DIST(v) ((v)->no[0]) /* Distance from the plane. */
#define BM_VERT_SORTVAL(v) ((v)->no[1]) /* Temp value for sorting. */
#define BM_VERT_LOOPINDEX(v) /* The verts index within a face (temp var) */ \
@@ -105,18 +106,19 @@ static int bm_vert_sortval_cb(const void *v_a_v, const void *v_b_v)
if (val_a > val_b) return 1;
else if (val_a < val_b) return -1;
- return 0;
+ else return 0;
}
static void bm_face_bisect_verts(BMesh *bm, BMFace *f, const float plane[4], const short oflag_center)
{
- /* unlikely more then 2 verts are needed */
+ /* unlikely more than 2 verts are needed */
const unsigned int f_len_orig = (unsigned int)f->len;
BMVert **vert_split_arr = BLI_array_alloca(vert_split_arr, f_len_orig);
STACK_DECLARE(vert_split_arr);
BMLoop *l_iter, *l_first;
bool use_dirs[3] = {false, false, false};
+ bool is_inside = false;
STACK_INIT(vert_split_arr, f_len_orig);
@@ -129,6 +131,11 @@ static void bm_face_bisect_verts(BMesh *bm, BMFace *f, const float plane[4], con
do {
if (vert_is_center_test(l_iter->v)) {
BLI_assert(BM_VERT_DIR(l_iter->v) == 0);
+
+ /* if both are -1 or 1, or both are zero:
+ * don't flip 'inside' var while walking */
+ BM_VERT_SKIP(l_iter->v) = (((BM_VERT_DIR(l_iter->prev->v) ^ BM_VERT_DIR(l_iter->next->v))) == 0);
+
STACK_PUSH(vert_split_arr, l_iter->v);
}
use_dirs[BM_VERT_DIR(l_iter->v) + 1] = true;
@@ -230,15 +237,12 @@ static void bm_face_bisect_verts(BMesh *bm, BMFace *f, const float plane[4], con
for (i = 0; i < STACK_SIZE(vert_split_arr) - 1; i++) {
BMVert *v_a = vert_split_arr[i];
BMVert *v_b = vert_split_arr[i + 1];
- float co_mid[2];
- /* geometric test before doing face lookups,
- * find if the split spans a filled region of the polygon. */
- mid_v2_v2v2(co_mid,
- face_verts_proj_2d[BM_VERT_LOOPINDEX(v_a)],
- face_verts_proj_2d[BM_VERT_LOOPINDEX(v_b)]);
+ if (!BM_VERT_SKIP(v_a)) {
+ is_inside = !is_inside;
+ }
- if (isect_point_poly_v2(co_mid, (const float (*)[2])face_verts_proj_2d, f_len_orig, false)) {
+ if (is_inside) {
BMLoop *l_a, *l_b;
bool found = false;
unsigned int j;
@@ -254,7 +258,8 @@ static void bm_face_bisect_verts(BMesh *bm, BMFace *f, const float plane[4], con
}
}
- BLI_assert(found == true);
+ /* ideally wont happen, but it can for self intersecting faces */
+ // BLI_assert(found == true);
/* in fact this simple test is good enough,
* test if the loops are adjacent */
@@ -289,9 +294,10 @@ finally:
* \param use_tag Only bisect tagged edges and faces.
* \param oflag_center Operator flag, enabled for geometry on the axis (existing and created)
*/
-void BM_mesh_bisect_plane(BMesh *bm, float plane[4],
- const bool use_snap_center, const bool use_tag,
- const short oflag_center, const float eps)
+void BM_mesh_bisect_plane(
+ BMesh *bm, const float plane[4],
+ const bool use_snap_center, const bool use_tag,
+ const short oflag_center, const float eps)
{
unsigned int einput_len;
unsigned int i;
diff --git a/source/blender/bmesh/tools/bmesh_bisect_plane.h b/source/blender/bmesh/tools/bmesh_bisect_plane.h
index 15f902642c8..7f3a97c4c79 100644
--- a/source/blender/bmesh/tools/bmesh_bisect_plane.h
+++ b/source/blender/bmesh/tools/bmesh_bisect_plane.h
@@ -27,8 +27,9 @@
* \ingroup bmesh
*/
-void BM_mesh_bisect_plane(BMesh *bm, float plane[4],
- const bool use_snap_center, const bool use_tag,
- const short oflag_center, const float eps);
+void BM_mesh_bisect_plane(
+ BMesh *bm, const float plane[4],
+ const bool use_snap_center, const bool use_tag,
+ const short oflag_center, const float eps);
#endif /* __BMESH_BISECT_PLANE_H__ */
diff --git a/source/blender/bmesh/tools/bmesh_decimate.h b/source/blender/bmesh/tools/bmesh_decimate.h
index a1b26990587..6415da9a0c2 100644
--- a/source/blender/bmesh/tools/bmesh_decimate.h
+++ b/source/blender/bmesh/tools/bmesh_decimate.h
@@ -27,21 +27,22 @@
* \ingroup bmesh
*/
-void BM_mesh_decimate_collapse(BMesh *bm, const float factor, float *vweights, const bool do_triangulate);
+void BM_mesh_decimate_collapse(
+ BMesh *bm, const float factor,
+ float *vweights, float vweight_factor,
+ const bool do_triangulate);
void BM_mesh_decimate_unsubdivide_ex(BMesh *bm, const int iterations, const bool tag_only);
void BM_mesh_decimate_unsubdivide(BMesh *bm, const int iterations);
-void BM_mesh_decimate_dissolve_ex(BMesh *bm, const float angle_limit, const bool do_dissolve_boundaries,
- const BMO_Delimit delimit,
- BMVert **vinput_arr, const int vinput_len,
- BMEdge **einput_arr, const int einput_len,
- const short oflag_out);
-void BM_mesh_decimate_dissolve(BMesh *bm, const float angle_limit, const bool do_dissolve_boundaries,
- const BMO_Delimit delimit);
-
-/* these weights are accumulated so too high values may reach 'inf' too quickly */
-#define BM_MESH_DECIM_WEIGHT_MAX 100000.0f
-#define BM_MESH_DECIM_WEIGHT_EPS (1.0f / BM_MESH_DECIM_WEIGHT_MAX)
+void BM_mesh_decimate_dissolve_ex(
+ BMesh *bm, const float angle_limit, const bool do_dissolve_boundaries,
+ BMO_Delimit delimit,
+ BMVert **vinput_arr, const int vinput_len,
+ BMEdge **einput_arr, const int einput_len,
+ const short oflag_out);
+void BM_mesh_decimate_dissolve(
+ BMesh *bm, const float angle_limit, const bool do_dissolve_boundaries,
+ const BMO_Delimit delimit);
#endif /* __BMESH_DECIMATE_H__ */
diff --git a/source/blender/bmesh/tools/bmesh_decimate_collapse.c b/source/blender/bmesh/tools/bmesh_decimate_collapse.c
index ef1783cc693..43a34331fc2 100644
--- a/source/blender/bmesh/tools/bmesh_decimate_collapse.c
+++ b/source/blender/bmesh/tools/bmesh_decimate_collapse.c
@@ -47,6 +47,12 @@
#define USE_TRIANGULATE
#define USE_VERT_NORMAL_INTERP /* has the advantage that flipped faces don't mess up vertex normals */
+/* if the cost from #BLI_quadric_evaluate is 'noise', fallback to topology */
+#define USE_TOPOLOGY_FALLBACK
+#ifdef USE_TOPOLOGY_FALLBACK
+# define TOPOLOGY_FALLBACK_EPS FLT_EPSILON
+#endif
+
/* these checks are for rare cases that we can't avoid since they are valid meshes still */
#define USE_SAFETY_CHECKS
@@ -77,12 +83,15 @@ static void bm_decim_build_quadrics(BMesh *bm, Quadric *vquadrics)
BMLoop *l_first;
BMLoop *l_iter;
- const float *co = BM_FACE_FIRST_LOOP(f)->v->co;
- const float *no = f->no;
- const float offset = -dot_v3v3(no, co);
+ float center[3];
+ double plane_db[4];
Quadric q;
- BLI_quadric_from_v3_dist(&q, no, offset);
+ BM_face_calc_center_mean(f, center);
+ copy_v3db_v3fl(plane_db, f->no);
+ plane_db[3] = -dot_v3db_v3fl(plane_db, center);
+
+ BLI_quadric_from_plane(&q, plane_db);
l_iter = l_first = BM_FACE_FIRST_LOOP(f);
do {
@@ -94,14 +103,22 @@ static void bm_decim_build_quadrics(BMesh *bm, Quadric *vquadrics)
BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
if (UNLIKELY(BM_edge_is_boundary(e))) {
float edge_vector[3];
- float edge_cross[3];
+ float edge_plane[3];
+ double edge_plane_db[4];
sub_v3_v3v3(edge_vector, e->v2->co, e->v1->co);
f = e->l->f;
- cross_v3_v3v3(edge_cross, edge_vector, f->no);
- if (normalize_v3(edge_cross) > FLT_EPSILON) {
+ cross_v3_v3v3(edge_plane, edge_vector, f->no);
+ copy_v3db_v3fl(edge_plane_db, edge_plane);
+
+ if (normalize_v3_d(edge_plane_db) > (double)FLT_EPSILON) {
Quadric q;
- BLI_quadric_from_v3_dist(&q, edge_cross, -dot_v3v3(edge_cross, e->v1->co));
+ float center[3];
+
+ mid_v3_v3v3(center, e->v1->co, e->v2->co);
+
+ edge_plane_db[3] = -dot_v3db_v3fl(edge_plane_db, center);
+ BLI_quadric_from_plane(&q, edge_plane_db);
BLI_quadric_mul(&q, BOUNDARY_PRESERVE_WEIGHT);
BLI_quadric_add_qu_qu(&vquadrics[BM_elem_index_get(e->v1)], &q);
@@ -112,18 +129,19 @@ static void bm_decim_build_quadrics(BMesh *bm, Quadric *vquadrics)
}
-static void bm_decim_calc_target_co(BMEdge *e, float optimize_co[3],
- const Quadric *vquadrics)
+static void bm_decim_calc_target_co(
+ BMEdge *e, float optimize_co[3],
+ const Quadric *vquadrics)
{
/* compute an edge contraction target for edge 'e'
* this is computed by summing it's vertices quadrics and
* optimizing the result. */
Quadric q;
- BLI_quadric_add_qu_ququ(&q,
- &vquadrics[BM_elem_index_get(e->v1)],
- &vquadrics[BM_elem_index_get(e->v2)]);
-
+ BLI_quadric_add_qu_ququ(
+ &q,
+ &vquadrics[BM_elem_index_get(e->v1)],
+ &vquadrics[BM_elem_index_get(e->v2)]);
if (BLI_quadric_optimize(&q, optimize_co, OPTIMIZE_EPS)) {
return; /* all is good */
@@ -162,13 +180,15 @@ static bool bm_edge_collapse_is_degenerate_flip(BMEdge *e, const float optimize_
cross_v3_v3v3(cross_exist, vec_other, vec_exist);
cross_v3_v3v3(cross_optim, vec_other, vec_optim);
- /* normalize isn't really needed, but ensures the value at a unit we can compare against */
- normalize_v3(cross_exist);
- normalize_v3(cross_optim);
+ /* avoid normalize */
+ if (dot_v3v3(cross_exist, cross_optim) <=
+ (len_squared_v3(cross_exist) + len_squared_v3(cross_optim)) * 0.01f)
+ {
+ return true;
+ }
#else
normal_tri_v3(cross_exist, v->co, co_prev, co_next);
normal_tri_v3(cross_optim, optimize_co, co_prev, co_next);
-#endif
/* use a small value rather then zero so we don't flip a face in multiple steps
* (first making it zero area, then flipping again) */
@@ -176,6 +196,8 @@ static bool bm_edge_collapse_is_degenerate_flip(BMEdge *e, const float optimize_
//printf("no flip\n");
return true;
}
+#endif
+
}
}
}
@@ -183,9 +205,29 @@ static bool bm_edge_collapse_is_degenerate_flip(BMEdge *e, const float optimize_
return false;
}
-static void bm_decim_build_edge_cost_single(BMEdge *e,
- const Quadric *vquadrics, const float *vweights,
- Heap *eheap, HeapNode **eheap_table)
+#ifdef USE_TOPOLOGY_FALLBACK
+/**
+ * when the cost is so small that its not useful (flat surfaces),
+ * fallback to using a 'topology' cost.
+ *
+ * This avoids cases where a flat (or near flat) areas get very un-even geometry.
+ */
+static float bm_decim_build_edge_cost_single_squared__topology(BMEdge *e)
+{
+ return fabsf(dot_v3v3(e->v1->no, e->v2->no)) / min_ff(-len_squared_v3v3(e->v1->co, e->v2->co), -FLT_EPSILON);
+}
+static float bm_decim_build_edge_cost_single__topology(BMEdge *e)
+{
+ return fabsf(dot_v3v3(e->v1->no, e->v2->no)) / min_ff(-len_v3v3(e->v1->co, e->v2->co), -FLT_EPSILON);
+}
+
+#endif /* USE_TOPOLOGY_FALLBACK */
+
+static void bm_decim_build_edge_cost_single(
+ BMEdge *e,
+ const Quadric *vquadrics,
+ const float *vweights, const float vweight_factor,
+ Heap *eheap, HeapNode **eheap_table)
{
const Quadric *q1, *q2;
float optimize_co[3];
@@ -202,8 +244,7 @@ static void bm_decim_build_edge_cost_single(BMEdge *e,
}
else {
/* only collapse tri's */
- eheap_table[BM_elem_index_get(e)] = NULL;
- return;
+ goto clear;
}
}
else if (BM_edge_is_manifold(e)) {
@@ -212,23 +253,11 @@ static void bm_decim_build_edge_cost_single(BMEdge *e,
}
else {
/* only collapse tri's */
- eheap_table[BM_elem_index_get(e)] = NULL;
- return;
+ goto clear;
}
}
else {
- eheap_table[BM_elem_index_get(e)] = NULL;
- return;
- }
-
- if (vweights) {
- if ((vweights[BM_elem_index_get(e->v1)] >= BM_MESH_DECIM_WEIGHT_MAX) &&
- (vweights[BM_elem_index_get(e->v2)] >= BM_MESH_DECIM_WEIGHT_MAX))
- {
- /* skip collapsing this edge */
- eheap_table[BM_elem_index_get(e)] = NULL;
- return;
- }
+ goto clear;
}
/* end sanity check */
@@ -238,36 +267,71 @@ static void bm_decim_build_edge_cost_single(BMEdge *e,
q1 = &vquadrics[BM_elem_index_get(e->v1)];
q2 = &vquadrics[BM_elem_index_get(e->v2)];
- if (vweights == NULL) {
- cost = (BLI_quadric_evaluate(q1, optimize_co) +
- BLI_quadric_evaluate(q2, optimize_co));
- }
- else {
- /* add 1.0 so planar edges are still weighted against */
- cost = (((BLI_quadric_evaluate(q1, optimize_co) + 1.0f) * vweights[BM_elem_index_get(e->v1)]) +
- ((BLI_quadric_evaluate(q2, optimize_co) + 1.0f) * vweights[BM_elem_index_get(e->v2)]));
- }
- // print("COST %.12f\n");
+ cost = (BLI_quadric_evaluate(q1, optimize_co) +
+ BLI_quadric_evaluate(q2, optimize_co));
+
/* 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);
+
+#ifdef USE_TOPOLOGY_FALLBACK
+ if (UNLIKELY(cost < TOPOLOGY_FALLBACK_EPS)) {
+ /* subtract existing cost to further differentiate edges from one another
+ *
+ * keep topology cost below 0.0 so their values don't interfere with quadric cost,
+ * (and they get handled first).
+ * */
+ if (vweights == NULL) {
+ cost = bm_decim_build_edge_cost_single_squared__topology(e) - cost;
+ }
+ else {
+ /* with weights we need to use the real length so we can scale them properly */
+ const float e_weight = (vweights[BM_elem_index_get(e->v1)] +
+ vweights[BM_elem_index_get(e->v2)]);
+ cost = bm_decim_build_edge_cost_single__topology(e) - cost;
+ /* note, this is rather arbitrary max weight is 2 here,
+ * allow for skipping edges 4x the length, based on weights */
+ if (e_weight) {
+ cost *= 1.0f + (e_weight * vweight_factor);
+ }
+
+ BLI_assert(cost <= 0.0f);
+ }
+ }
+ else
+#endif
+ if (vweights) {
+ const float e_weight = 2.0f - (vweights[BM_elem_index_get(e->v1)] +
+ vweights[BM_elem_index_get(e->v2)]);
+ if (e_weight) {
+ cost += (BM_edge_calc_length(e) * ((e_weight * vweight_factor)));
+ }
+ }
+
eheap_table[BM_elem_index_get(e)] = BLI_heap_insert(eheap, cost, e);
+ return;
+
+clear:
+ eheap_table[BM_elem_index_get(e)] = NULL;
}
/* use this for degenerate cases - add back to the heap with an invalid cost,
* this way it may be calculated again if surrounding geometry changes */
-static void bm_decim_invalid_edge_cost_single(BMEdge *e,
- Heap *eheap, HeapNode **eheap_table)
+static void bm_decim_invalid_edge_cost_single(
+ BMEdge *e,
+ Heap *eheap, HeapNode **eheap_table)
{
BLI_assert(eheap_table[BM_elem_index_get(e)] == NULL);
eheap_table[BM_elem_index_get(e)] = BLI_heap_insert(eheap, COST_INVALID, e);
}
-static void bm_decim_build_edge_cost(BMesh *bm,
- const Quadric *vquadrics, const float *vweights,
- Heap *eheap, HeapNode **eheap_table)
+static void bm_decim_build_edge_cost(
+ BMesh *bm,
+ const Quadric *vquadrics,
+ const float *vweights, const float vweight_factor,
+ Heap *eheap, HeapNode **eheap_table)
{
BMIter iter;
BMEdge *e;
@@ -275,7 +339,7 @@ static void bm_decim_build_edge_cost(BMesh *bm,
BM_ITER_MESH_INDEX (e, &iter, bm, BM_EDGES_OF_MESH, i) {
eheap_table[i] = NULL; /* keep sanity check happy */
- bm_decim_build_edge_cost_single(e, vquadrics, vweights, eheap, eheap_table);
+ bm_decim_build_edge_cost_single(e, vquadrics, vweights, vweight_factor, eheap, eheap_table);
}
}
@@ -440,10 +504,11 @@ static void bm_decim_triangulate_end(BMesh *bm)
#ifdef USE_CUSTOMDATA
/**
- * \param v is the target to merge into.
+ * \param l: defines the vert to collapse into.
*/
-static void bm_edge_collapse_loop_customdata(BMesh *bm, BMLoop *l, BMVert *v_clear, BMVert *v_other,
- const float customdata_fac)
+static void bm_edge_collapse_loop_customdata(
+ BMesh *bm, BMLoop *l, BMVert *v_clear, BMVert *v_other,
+ const float customdata_fac)
{
/* disable seam check - the seam check would have to be done per layer, its not really that important */
//#define USE_SEAM
@@ -452,8 +517,6 @@ static void bm_edge_collapse_loop_customdata(BMesh *bm, BMLoop *l, BMVert *v_cle
const bool is_manifold = BM_edge_is_manifold(l->e);
int side;
- /* l defines the vert to collapse into */
-
/* first find the loop of 'v_other' thats attached to the face of 'l' */
if (l->v == v_clear) {
l_clear = l;
@@ -519,13 +582,17 @@ static void bm_edge_collapse_loop_customdata(BMesh *bm, BMLoop *l, BMVert *v_cle
if (CustomData_layer_has_math(&bm->ldata, i)) {
const int offset = bm->ldata.layers[i].offset;
const int type = bm->ldata.layers[i].type;
- void *cd_src[2] = {(char *)src[0] + offset,
- (char *)src[1] + offset};
- void *cd_iter = (char *)l_iter->head.data + offset;
+ const void *cd_src[2] = {
+ POINTER_OFFSET(src[0], offset),
+ POINTER_OFFSET(src[1], offset),
+ };
+ void *cd_iter = POINTER_OFFSET(l_iter->head.data, offset);
/* detect seams */
if (CustomData_data_equals(type, cd_src[0], cd_iter)) {
- CustomData_bmesh_interp_n(&bm->ldata, cd_src, w, NULL, 2, l_iter->head.data, i);
+ CustomData_bmesh_interp_n(
+ &bm->ldata, cd_src, w, NULL, ARRAY_SIZE(cd_src),
+ POINTER_OFFSET(l_iter->head.data, offset), i);
#ifdef USE_SEAM
is_seam = false;
#endif
@@ -691,18 +758,19 @@ static bool bm_edge_collapse_is_degenerate_topology(BMEdge *e_first)
*
* Important - dont add vert/edge/face data on collapsing!
*
- * \param e_clear_other let caller know what edges we remove besides \a e_clear
- * \param customdata_flag merge factor, scales from 0 - 1 ('v_clear' -> 'v_other')
+ * \param r_e_clear_other: Let caller know what edges we remove besides \a e_clear
+ * \param customdata_flag: Merge factor, scales from 0 - 1 ('v_clear' -> 'v_other')
*/
-static bool bm_edge_collapse(BMesh *bm, BMEdge *e_clear, BMVert *v_clear, int r_e_clear_other[2],
+static bool bm_edge_collapse(
+ BMesh *bm, BMEdge *e_clear, BMVert *v_clear, int r_e_clear_other[2],
#ifdef USE_CUSTOMDATA
- const CD_UseFlag customdata_flag,
- const float customdata_fac
+ const CD_UseFlag customdata_flag,
+ const float customdata_fac
#else
- const CD_UseFlag UNUSED(customdata_flag),
- const float UNUSED(customdata_fac)
+ const CD_UseFlag UNUSED(customdata_flag),
+ const float UNUSED(customdata_fac)
#endif
- )
+ )
{
BMVert *v_other;
@@ -719,6 +787,7 @@ static bool bm_edge_collapse(BMesh *bm, BMEdge *e_clear, BMVert *v_clear, int r_
BLI_assert(ok == true);
BLI_assert(l_a->f->len == 3);
BLI_assert(l_b->f->len == 3);
+ UNUSED_VARS_NDEBUG(ok);
/* keep 'v_clear' 0th */
if (BM_vert_in_edge(l_a->prev->e, v_clear)) {
@@ -777,12 +846,12 @@ static bool bm_edge_collapse(BMesh *bm, BMEdge *e_clear, BMVert *v_clear, int r_
BM_edge_kill(bm, e_clear);
v_other->head.hflag |= v_clear->head.hflag;
- BM_vert_splice(bm, v_clear, v_other);
+ BM_vert_splice(bm, v_other, v_clear);
e_a_other[1]->head.hflag |= e_a_other[0]->head.hflag;
e_b_other[1]->head.hflag |= e_b_other[0]->head.hflag;
- BM_edge_splice(bm, e_a_other[0], e_a_other[1]);
- BM_edge_splice(bm, e_b_other[0], e_b_other[1]);
+ BM_edge_splice(bm, e_a_other[1], e_a_other[0]);
+ BM_edge_splice(bm, e_b_other[1], e_b_other[0]);
// BM_mesh_validate(bm);
@@ -826,10 +895,10 @@ static bool bm_edge_collapse(BMesh *bm, BMEdge *e_clear, BMVert *v_clear, int r_
BM_edge_kill(bm, e_clear);
v_other->head.hflag |= v_clear->head.hflag;
- BM_vert_splice(bm, v_clear, v_other);
+ BM_vert_splice(bm, v_other, v_clear);
e_a_other[1]->head.hflag |= e_a_other[0]->head.hflag;
- BM_edge_splice(bm, e_a_other[0], e_a_other[1]);
+ BM_edge_splice(bm, e_a_other[1], e_a_other[0]);
// BM_mesh_validate(bm);
@@ -842,14 +911,17 @@ static bool bm_edge_collapse(BMesh *bm, BMEdge *e_clear, BMVert *v_clear, int r_
/* collapse e the edge, removing e->v2 */
-static void bm_decim_edge_collapse(BMesh *bm, BMEdge *e,
- Quadric *vquadrics, float *vweights,
- Heap *eheap, HeapNode **eheap_table,
- const CD_UseFlag customdata_flag)
+static void bm_decim_edge_collapse(
+ BMesh *bm, BMEdge *e,
+ Quadric *vquadrics,
+ float *vweights, const float vweight_factor,
+ Heap *eheap, HeapNode **eheap_table,
+ const CD_UseFlag customdata_flag)
{
int e_clear_other[2];
BMVert *v_other = e->v1;
- int v_clear_index = BM_elem_index_get(e->v2); /* the vert is removed so only store the index */
+ const int v_other_index = BM_elem_index_get(e->v1);
+ const int v_clear_index = BM_elem_index_get(e->v2); /* the vert is removed so only store the index */
float optimize_co[3];
float customdata_fac;
@@ -892,7 +964,9 @@ static void bm_decim_edge_collapse(BMesh *bm, BMEdge *e,
int i;
if (vweights) {
- vweights[BM_elem_index_get(v_other)] += vweights[v_clear_index];
+ float v_other_weight = interpf(vweights[v_other_index], vweights[v_clear_index], customdata_fac);
+ CLAMP(v_other_weight, 0.0f, 1.0f);
+ vweights[v_other_index] = v_other_weight;
}
e = NULL; /* paranoid safety check */
@@ -909,7 +983,7 @@ static void bm_decim_edge_collapse(BMesh *bm, BMEdge *e,
}
/* update vertex quadric, add kept vertex from killed vertex */
- BLI_quadric_add_qu_qu(&vquadrics[BM_elem_index_get(v_other)], &vquadrics[v_clear_index]);
+ BLI_quadric_add_qu_qu(&vquadrics[v_other_index], &vquadrics[v_clear_index]);
/* update connected normals */
@@ -930,7 +1004,7 @@ static void bm_decim_edge_collapse(BMesh *bm, BMEdge *e,
e_iter = e_first = v_other->e;
do {
BLI_assert(BM_edge_find_double(e_iter) == NULL);
- bm_decim_build_edge_cost_single(e_iter, vquadrics, vweights, eheap, eheap_table);
+ bm_decim_build_edge_cost_single(e_iter, vquadrics, vweights, vweight_factor, eheap, eheap_table);
} while ((e_iter = bmesh_disk_edge_next(e_iter, v_other)) != e_first);
}
@@ -952,7 +1026,7 @@ static void bm_decim_edge_collapse(BMesh *bm, BMEdge *e,
BLI_assert(BM_vert_in_edge(e_outer, l->v) == false);
- bm_decim_build_edge_cost_single(e_outer, vquadrics, vweights, eheap, eheap_table);
+ bm_decim_build_edge_cost_single(e_outer, vquadrics, vweights, vweight_factor, eheap, eheap_table);
}
}
}
@@ -976,7 +1050,11 @@ static void bm_decim_edge_collapse(BMesh *bm, BMEdge *e,
* \param vweights Optional array of vertex aligned weights [0 - 1],
* a vertex group is the usual source for this.
*/
-void BM_mesh_decimate_collapse(BMesh *bm, const float factor, float *vweights, const bool do_triangulate)
+void BM_mesh_decimate_collapse(
+ BMesh *bm,
+ const float factor,
+ float *vweights, float vweight_factor,
+ const bool do_triangulate)
{
Heap *eheap; /* edge heap */
HeapNode **eheap_table; /* edge index aligned table pointing to the eheap */
@@ -1004,7 +1082,7 @@ void BM_mesh_decimate_collapse(BMesh *bm, const float factor, float *vweights, c
/* build initial edge collapse cost data */
bm_decim_build_quadrics(bm, vquadrics);
- bm_decim_build_edge_cost(bm, vquadrics, vweights, eheap, eheap_table);
+ bm_decim_build_edge_cost(bm, vquadrics, vweights, vweight_factor, eheap, eheap_table);
face_tot_target = bm->totface * factor;
bm->elem_index_dirty |= BM_ALL;
@@ -1026,13 +1104,11 @@ void BM_mesh_decimate_collapse(BMesh *bm, const float factor, float *vweights, c
BMEdge *e = BLI_heap_popmin(eheap);
BLI_assert(BM_elem_index_get(e) < tot_edge_orig); /* handy to detect corruptions elsewhere */
- // printf("COST %.10f\n", value);
-
/* under normal conditions wont be accessed again,
* but NULL just incase so we don't use freed node */
eheap_table[BM_elem_index_get(e)] = NULL;
- bm_decim_edge_collapse(bm, e, vquadrics, vweights, eheap, eheap_table, customdata_flag);
+ bm_decim_edge_collapse(bm, e, vquadrics, vweights, vweight_factor, eheap, eheap_table, customdata_flag);
}
diff --git a/source/blender/bmesh/tools/bmesh_decimate_dissolve.c b/source/blender/bmesh/tools/bmesh_decimate_dissolve.c
index 096349e8e9c..a1460cec7d1 100644
--- a/source/blender/bmesh/tools/bmesh_decimate_dissolve.c
+++ b/source/blender/bmesh/tools/bmesh_decimate_dissolve.c
@@ -32,6 +32,8 @@
#include "BLI_math.h"
#include "BLI_heap.h"
+#include "BKE_customdata.h"
+
#include "bmesh.h"
#include "bmesh_decimate.h" /* own include */
@@ -59,7 +61,32 @@ static float bm_vert_edge_face_angle(BMVert *v)
#undef ANGLE_TO_UNIT
}
-static float bm_edge_calc_dissolve_error(const BMEdge *e, const BMO_Delimit delimit)
+struct DelimitData {
+ int cd_loop_type;
+ int cd_loop_size;
+ int cd_loop_offset;
+ int cd_loop_offset_end;
+};
+
+static bool bm_edge_is_contiguous_loop_cd_all(
+ const BMEdge *e, const struct DelimitData *delimit_data)
+{
+ int cd_loop_offset;
+ for (cd_loop_offset = delimit_data->cd_loop_offset;
+ cd_loop_offset < delimit_data->cd_loop_offset_end;
+ cd_loop_offset += delimit_data->cd_loop_size)
+ {
+ if (BM_edge_is_contiguous_loop_cd(e, delimit_data->cd_loop_type, cd_loop_offset) == false) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+static float bm_edge_calc_dissolve_error(
+ const BMEdge *e, const BMO_Delimit delimit,
+ const struct DelimitData *delimit_data)
{
const bool is_contig = BM_edge_is_contiguous(e);
float angle;
@@ -74,6 +101,12 @@ static float bm_edge_calc_dissolve_error(const BMEdge *e, const BMO_Delimit deli
goto fail;
}
+ if ((delimit & BMO_DELIM_SHARP) &&
+ (BM_elem_flag_test(e, BM_ELEM_SMOOTH) == 0))
+ {
+ goto fail;
+ }
+
if ((delimit & BMO_DELIM_MATERIAL) &&
(e->l->f->mat_nr != e->l->radial_next->f->mat_nr))
{
@@ -86,6 +119,12 @@ static float bm_edge_calc_dissolve_error(const BMEdge *e, const BMO_Delimit deli
goto fail;
}
+ if ((delimit & BMO_DELIM_UV) &&
+ (bm_edge_is_contiguous_loop_cd_all(e, delimit_data) == 0))
+ {
+ goto fail;
+ }
+
angle = BM_edge_calc_face_angle(e);
if (is_contig == false) {
angle = (float)M_PI - angle;
@@ -98,17 +137,32 @@ fail:
}
-void BM_mesh_decimate_dissolve_ex(BMesh *bm, const float angle_limit, const bool do_dissolve_boundaries,
- const BMO_Delimit delimit,
- BMVert **vinput_arr, const int vinput_len,
- BMEdge **einput_arr, const int einput_len,
- const short oflag_out)
+void BM_mesh_decimate_dissolve_ex(
+ BMesh *bm, const float angle_limit, const bool do_dissolve_boundaries,
+ BMO_Delimit delimit,
+ BMVert **vinput_arr, const int vinput_len,
+ BMEdge **einput_arr, const int einput_len,
+ const short oflag_out)
{
+ struct DelimitData delimit_data = {0};
const int eheap_table_len = do_dissolve_boundaries ? einput_len : max_ii(einput_len, vinput_len);
void *_heap_table = MEM_mallocN(sizeof(HeapNode *) * eheap_table_len, __func__);
int i;
+ if (delimit & BMO_DELIM_UV) {
+ const int layer_len = CustomData_number_of_layers(&bm->ldata, CD_MLOOPUV);
+ if (layer_len == 0) {
+ delimit &= ~BMO_DELIM_UV;
+ }
+ else {
+ delimit_data.cd_loop_type = CD_MLOOPUV;
+ delimit_data.cd_loop_size = CustomData_sizeof(delimit_data.cd_loop_type);
+ delimit_data.cd_loop_offset = CustomData_get_n_offset(&bm->ldata, CD_MLOOPUV, 0);
+ delimit_data.cd_loop_offset_end = delimit_data.cd_loop_size * layer_len;
+ }
+ }
+
/* --- first edges --- */
if (1) {
BMEdge **earray;
@@ -133,7 +187,7 @@ void BM_mesh_decimate_dissolve_ex(BMesh *bm, const float angle_limit, const bool
/* build heap */
for (i = 0; i < einput_len; i++) {
BMEdge *e = einput_arr[i];
- const float cost = bm_edge_calc_dissolve_error(e, delimit);
+ const float cost = bm_edge_calc_dissolve_error(e, delimit, &delimit_data);
eheap_table[i] = BLI_heap_insert(eheap, cost, e);
BM_elem_index_set(e, i); /* set dirty */
}
@@ -169,7 +223,7 @@ void BM_mesh_decimate_dissolve_ex(BMesh *bm, const float angle_limit, const bool
do {
const int j = BM_elem_index_get(l_iter->e);
if (j != -1 && eheap_table[j]) {
- const float cost = bm_edge_calc_dissolve_error(l_iter->e, delimit);
+ const float cost = bm_edge_calc_dissolve_error(l_iter->e, delimit, &delimit_data);
BLI_heap_remove(eheap, eheap_table[j]);
eheap_table[j] = BLI_heap_insert(eheap, cost, l_iter->e);
}
@@ -189,7 +243,7 @@ void BM_mesh_decimate_dissolve_ex(BMesh *bm, const float angle_limit, const bool
/* prepare for cleanup */
BM_mesh_elem_index_ensure(bm, BM_VERT);
vert_reverse_lookup = MEM_mallocN(sizeof(int) * bm->totvert, __func__);
- fill_vn_i(vert_reverse_lookup, bm->totvert, -1);
+ copy_vn_i(vert_reverse_lookup, bm->totvert, -1);
for (i = 0; i < vinput_len; i++) {
BMVert *v = vinput_arr[i];
vert_reverse_lookup[BM_elem_index_get(v)] = i;
@@ -316,8 +370,9 @@ void BM_mesh_decimate_dissolve_ex(BMesh *bm, const float angle_limit, const bool
MEM_freeN(_heap_table);
}
-void BM_mesh_decimate_dissolve(BMesh *bm, const float angle_limit, const bool do_dissolve_boundaries,
- const BMO_Delimit delimit)
+void BM_mesh_decimate_dissolve(
+ BMesh *bm, const float angle_limit, const bool do_dissolve_boundaries,
+ const BMO_Delimit delimit)
{
int vinput_len;
int einput_len;
diff --git a/source/blender/bmesh/tools/bmesh_edgenet.c b/source/blender/bmesh/tools/bmesh_edgenet.c
index 1328b81b746..2a1946df7ae 100644
--- a/source/blender/bmesh/tools/bmesh_edgenet.c
+++ b/source/blender/bmesh/tools/bmesh_edgenet.c
@@ -166,8 +166,8 @@ static BMFace *bm_edgenet_face_from_path(
{
BMFace *f;
LinkNode *v_lnk;
- unsigned int i;
- unsigned int i_prev;
+ int i;
+ bool ok;
BMVert **vert_arr = BLI_array_alloca(vert_arr, path_len);
BMEdge **edge_arr = BLI_array_alloca(edge_arr, path_len);
@@ -176,11 +176,9 @@ static BMFace *bm_edgenet_face_from_path(
vert_arr[i] = v_lnk->link;
}
- i_prev = path_len - 1;
- for (i = 0; i < path_len; i++) {
- edge_arr[i_prev] = BM_edge_exists(vert_arr[i], vert_arr[i_prev]);
- i_prev = i;
- }
+ ok = BM_edges_from_verts(edge_arr, vert_arr, i);
+ BLI_assert(ok);
+ UNUSED_VARS_NDEBUG(ok);
/* no need for this, we do overlap checks before allowing the path to be used */
#if 0
@@ -448,10 +446,10 @@ static LinkNode *bm_edgenet_path_calc_best(
*
* \param bm The mesh to operate on.
* \param use_edge_tag Only fill tagged edges.
- * \param face_oflag if nonzero, apply all new faces with this bmo flag.
*/
-void BM_mesh_edgenet(BMesh *bm,
- const bool use_edge_tag, const bool use_new_face_tag)
+void BM_mesh_edgenet(
+ BMesh *bm,
+ const bool use_edge_tag, const bool use_new_face_tag)
{
VertNetInfo *vnet_info = MEM_callocN(sizeof(*vnet_info) * (size_t)bm->totvert, __func__);
BLI_mempool *edge_queue_pool = BLI_mempool_create(sizeof(LinkNode), 0, 512, BLI_MEMPOOL_NOP);
diff --git a/source/blender/bmesh/tools/bmesh_edgenet.h b/source/blender/bmesh/tools/bmesh_edgenet.h
index 327a7f5aa23..1ad5cadae7c 100644
--- a/source/blender/bmesh/tools/bmesh_edgenet.h
+++ b/source/blender/bmesh/tools/bmesh_edgenet.h
@@ -27,7 +27,8 @@
* \ingroup bmesh
*/
-void BM_mesh_edgenet(BMesh *bm,
- const bool use_edge_tag, const bool use_new_face_tag);
+void BM_mesh_edgenet(
+ BMesh *bm,
+ const bool use_edge_tag, const bool use_new_face_tag);
#endif /* __BMESH_EDGENET_H__ */
diff --git a/source/blender/bmesh/tools/bmesh_edgesplit.c b/source/blender/bmesh/tools/bmesh_edgesplit.c
index 947b77675d8..a59a5c43c82 100644
--- a/source/blender/bmesh/tools/bmesh_edgesplit.c
+++ b/source/blender/bmesh/tools/bmesh_edgesplit.c
@@ -35,70 +35,15 @@
#include "bmesh_edgesplit.h" /* own include */
-
/**
- * Remove the BM_ELEM_TAG flag for edges we cant split
- *
- * un-tag edges not connected to other tagged edges,
- * unless they are on a boundary
+ * \param use_verts Use flagged verts instead of edges.
+ * \param tag_only Only split tagged edges.
+ * \param copy_select Copy selection history.
*/
-static void bm_edgesplit_validate_seams(BMesh *bm)
-{
- BMIter iter;
- BMEdge *e;
-
- unsigned char *vtouch;
-
- BM_mesh_elem_index_ensure(bm, BM_VERT);
-
- vtouch = MEM_callocN(sizeof(char) * bm->totvert, __func__);
-
- /* tag all boundary verts so as not to untag an edge which is inbetween only 2 faces [] */
- BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
-
- /* unrelated to flag assignment in this function - since this is the
- * only place we loop over all edges, disable tag */
- BM_elem_flag_disable(e, BM_ELEM_INTERNAL_TAG);
-
- if (e->l == NULL) {
- BM_elem_flag_disable(e, BM_ELEM_TAG);
- }
- else if (BM_edge_is_boundary(e)) {
- unsigned char *vt;
- vt = &vtouch[BM_elem_index_get(e->v1)]; if (*vt < 2) (*vt)++;
- vt = &vtouch[BM_elem_index_get(e->v2)]; if (*vt < 2) (*vt)++;
-
- /* while the boundary verts need to be tagged,
- * the edge its self can't be split */
- BM_elem_flag_disable(e, BM_ELEM_TAG);
- }
- }
-
- /* single marked edges unconnected to any other marked edges
- * are illegal, go through and unmark them */
- BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
- if (BM_elem_flag_test(e, BM_ELEM_TAG)) {
- /* lame, but we don't want the count to exceed 255,
- * so just count to 2, its all we need */
- unsigned char *vt;
- vt = &vtouch[BM_elem_index_get(e->v1)]; if (*vt < 2) (*vt)++;
- vt = &vtouch[BM_elem_index_get(e->v2)]; if (*vt < 2) (*vt)++;
- }
- }
- BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
- if (BM_elem_flag_test(e, BM_ELEM_TAG)) {
- if (vtouch[BM_elem_index_get(e->v1)] == 1 &&
- vtouch[BM_elem_index_get(e->v2)] == 1)
- {
- BM_elem_flag_disable(e, BM_ELEM_TAG);
- }
- }
- }
-
- MEM_freeN(vtouch);
-}
-
-void BM_mesh_edgesplit(BMesh *bm, const bool use_verts, const bool tag_only, const bool copy_select)
+void BM_mesh_edgesplit(
+ BMesh *bm,
+ const bool use_verts,
+ const bool tag_only, const bool copy_select)
{
BMIter iter;
BMEdge *e;
@@ -142,43 +87,13 @@ void BM_mesh_edgesplit(BMesh *bm, const bool use_verts, const bool tag_only, con
}
}
- bm_edgesplit_validate_seams(bm);
-
BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
if (BM_elem_flag_test(e, BM_ELEM_TAG)) {
- /* this flag gets copied so we can be sure duplicate edges get it too (important) */
- BM_elem_flag_enable(e, BM_ELEM_INTERNAL_TAG);
-
- /* keep splitting until each loop has its own edge */
- while (!BM_edge_is_boundary(e)) {
- BMLoop *l_sep = e->l;
- bmesh_edge_separate(bm, e, l_sep, copy_select);
- BLI_assert(l_sep->e != e);
-
- if (use_ese) {
- BMEditSelection *ese = BLI_ghash_lookup(ese_gh, e);
- if (UNLIKELY(ese)) {
- BM_select_history_store_after_notest(bm, ese, l_sep->e);
- }
- }
- }
-
BM_elem_flag_enable(e->v1, BM_ELEM_TAG);
BM_elem_flag_enable(e->v2, BM_ELEM_TAG);
}
}
- if (use_verts) {
- BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
- if (BM_elem_flag_test(e->v1, BM_ELEM_TAG) == false) {
- BM_elem_flag_disable(e->v1, BM_ELEM_TAG);
- }
- if (BM_elem_flag_test(e->v2, BM_ELEM_TAG) == false) {
- BM_elem_flag_disable(e->v2, BM_ELEM_TAG);
- }
- }
- }
-
BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
if (BM_elem_flag_test(e, BM_ELEM_TAG)) {
unsigned int i;
@@ -191,7 +106,7 @@ void BM_mesh_edgesplit(BMesh *bm, const bool use_verts, const bool tag_only, con
BMVert **vtar;
int vtar_len;
- bmesh_vert_separate(bm, v, &vtar, &vtar_len, copy_select);
+ BM_vert_separate_hflag(bm, v, BM_ELEM_TAG, copy_select, &vtar, &vtar_len);
/* first value is always in 'v' */
if (vtar_len > 1) {
@@ -208,13 +123,22 @@ void BM_mesh_edgesplit(BMesh *bm, const bool use_verts, const bool tag_only, con
MEM_freeN(vtar);
}
else {
- bmesh_vert_separate(bm, v, NULL, NULL, copy_select);
+ BM_vert_separate_hflag(bm, v, BM_ELEM_TAG, copy_select, NULL, NULL);
}
}
}
}
}
+#ifndef NDEBUG
+ /* ensure we don't have any double edges! */
+ BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
+ if (BM_elem_flag_test(e, BM_ELEM_TAG)) {
+ BLI_assert(BM_edge_find_double(e) == NULL);
+ }
+ }
+#endif
+
if (use_ese) {
BLI_ghash_free(ese_gh, NULL, NULL);
}
diff --git a/source/blender/bmesh/tools/bmesh_edgesplit.h b/source/blender/bmesh/tools/bmesh_edgesplit.h
index bd66f6a9e2f..26040077f43 100644
--- a/source/blender/bmesh/tools/bmesh_edgesplit.h
+++ b/source/blender/bmesh/tools/bmesh_edgesplit.h
@@ -27,6 +27,9 @@
* \ingroup bmesh
*/
-void BM_mesh_edgesplit(BMesh *bm, const bool use_verts, const bool tag_only, const bool copy_select);
+void BM_mesh_edgesplit(
+ BMesh *bm,
+ const bool use_verts,
+ const bool tag_only, const bool copy_select);
#endif /* __BMESH_EDGESPLIT_H__ */
diff --git a/source/blender/bmesh/tools/bmesh_intersect.c b/source/blender/bmesh/tools/bmesh_intersect.c
index 4d87c3e3551..19cf2d29aff 100644
--- a/source/blender/bmesh/tools/bmesh_intersect.c
+++ b/source/blender/bmesh/tools/bmesh_intersect.c
@@ -45,7 +45,9 @@
#include "BLI_linklist_stack.h"
#include "BLI_stackdefines.h"
-#include "BLI_array.h"
+#ifndef NDEBUG
+# include "BLI_array_utils.h"
+#endif
#include "BLI_kdopbvh.h"
@@ -541,7 +543,7 @@ static void bm_isect_tri_tri(
if (((1 << i_b_e0) | (1 << i_b_e1)) & b_mask)
continue;
fac = line_point_factor_v3(fv_a[i_a]->co, fv_b[i_b_e0]->co, fv_b[i_b_e1]->co);
- if ((fac > 0.0f - s->epsilon.eps) && (fac < 1.0 + s->epsilon.eps)) {
+ if ((fac > 0.0f - s->epsilon.eps) && (fac < 1.0f + s->epsilon.eps)) {
float ix[3];
interp_v3_v3v3(ix, fv_b[i_b_e0]->co, fv_b[i_b_e1]->co, fac);
if (len_squared_v3v3(ix, fv_a[i_a]->co) <= s->epsilon.eps2x_sq) {
@@ -579,7 +581,7 @@ static void bm_isect_tri_tri(
if (((1 << i_a_e0) | (1 << i_a_e1)) & a_mask)
continue;
fac = line_point_factor_v3(fv_b[i_b]->co, fv_a[i_a_e0]->co, fv_a[i_a_e1]->co);
- if ((fac > 0.0 - s->epsilon.eps) && (fac < 1.0 + s->epsilon.eps)) {
+ if ((fac > 0.0f - s->epsilon.eps) && (fac < 1.0f + s->epsilon.eps)) {
float ix[3];
interp_v3_v3v3(ix, fv_a[i_a_e0]->co, fv_a[i_a_e1]->co, fac);
if (len_squared_v3v3(ix, fv_b[i_b]->co) <= s->epsilon.eps2x_sq) {
@@ -802,7 +804,7 @@ bool BM_mesh_intersect(
s.edgetri_cache = BLI_ghash_new(BLI_ghashutil_inthash_v4_p, BLI_ghashutil_inthash_v4_cmp, __func__);
s.edge_verts = BLI_ghash_ptr_new(__func__);
- s.face_edges = BLI_ghash_ptr_new(__func__);
+ s.face_edges = BLI_ghash_int_new(__func__);
s.wire_edges = BLI_gset_ptr_new(__func__);
s.vert_dissolve = NULL;
@@ -857,7 +859,7 @@ bool BM_mesh_intersect(
{UNPACK3(looptris[i][2]->v->co)},
};
- BLI_bvhtree_insert(tree_a, i, (float *)t_cos, 3);
+ BLI_bvhtree_insert(tree_a, i, (const float *)t_cos, 3);
}
}
BLI_bvhtree_balance(tree_a);
@@ -874,7 +876,7 @@ bool BM_mesh_intersect(
{UNPACK3(looptris[i][2]->v->co)},
};
- BLI_bvhtree_insert(tree_b, i, (float *)t_cos, 3);
+ BLI_bvhtree_insert(tree_b, i, (const float *)t_cos, 3);
}
}
BLI_bvhtree_balance(tree_b);
@@ -883,7 +885,7 @@ bool BM_mesh_intersect(
tree_b = tree_a;
}
- overlap = BLI_bvhtree_overlap(tree_b, tree_a, &tree_overlap_tot);
+ overlap = BLI_bvhtree_overlap(tree_b, tree_a, &tree_overlap_tot, NULL, NULL);
if (overlap) {
unsigned int i;
@@ -998,13 +1000,13 @@ bool BM_mesh_intersect(
if (BM_vert_in_edge(e, v_prev)) {
v_prev = BM_edge_split(bm, e, v_prev, NULL, CLAMPIS(fac, 0.0f, 1.0f));
- BLI_assert( BM_vert_in_edge(e, v_end));
+ BLI_assert(BM_vert_in_edge(e, v_end));
if (!BM_edge_exists(v_prev, vi) &&
!BM_vert_splice_check_double(v_prev, vi) &&
!BM_vert_pair_share_face_check(v_prev, vi))
{
- BM_vert_splice(bm, v_prev, vi);
+ BM_vert_splice(bm, vi, v_prev);
}
else {
copy_v3_v3(v_prev->co, vi->co);
@@ -1015,6 +1017,7 @@ bool BM_mesh_intersect(
}
}
}
+ UNUSED_VARS_NDEBUG(v_end);
}
}
#endif
@@ -1038,8 +1041,8 @@ bool BM_mesh_intersect(
}
}
- splice_ls = MEM_mallocN((unsigned int)BLI_gset_size(s.wire_edges) * sizeof(*splice_ls), __func__);
- STACK_INIT(splice_ls, (unsigned int)BLI_gset_size(s.wire_edges));
+ splice_ls = MEM_mallocN(BLI_gset_size(s.wire_edges) * sizeof(*splice_ls), __func__);
+ STACK_INIT(splice_ls, BLI_gset_size(s.wire_edges));
for (node = s.vert_dissolve; node; node = node->next) {
BMEdge *e_pair[2];
@@ -1226,7 +1229,7 @@ bool BM_mesh_intersect(
if (!BM_edge_exists(UNPACK2(splice_ls[i])) &&
!BM_vert_splice_check_double(UNPACK2(splice_ls[i])))
{
- BM_vert_splice(bm, UNPACK2(splice_ls[i]));
+ BM_vert_splice(bm, splice_ls[i][1], splice_ls[i][0]);
}
}
}
@@ -1265,10 +1268,8 @@ bool BM_mesh_intersect(
face_edges_split(bm, f, e_ls_base);
}
}
-#else
- (void)totface_orig;
#endif /* USE_NET */
-
+ (void)totface_orig;
#ifdef USE_SEPARATE
if (use_separate) {
diff --git a/source/blender/bmesh/tools/bmesh_path.c b/source/blender/bmesh/tools/bmesh_path.c
index 060d0dd969b..6633803414b 100644
--- a/source/blender/bmesh/tools/bmesh_path.c
+++ b/source/blender/bmesh/tools/bmesh_path.c
@@ -95,7 +95,7 @@ static void verttag_add_adjacent(Heap *heap, BMVert *v_a, BMVert **verts_prev, f
LinkNode *BM_mesh_calc_path_vert(
BMesh *bm, BMVert *v_src, BMVert *v_dst, const bool use_length,
- void *user_data, bool (*test_fn)(BMVert *, void *user_data))
+ bool (*test_fn)(BMVert *, void *user_data), void *user_data)
{
LinkNode *path = NULL;
/* BM_ELEM_TAG flag is used to store visited edges */
@@ -126,7 +126,7 @@ LinkNode *BM_mesh_calc_path_vert(
verts_prev = MEM_callocN(sizeof(*verts_prev) * totvert, __func__);
cost = MEM_mallocN(sizeof(*cost) * totvert, __func__);
- fill_vn_fl(cost, totvert, 1e20f);
+ copy_vn_fl(cost, totvert, 1e20f);
/*
* Arrays are now filled as follows:
@@ -221,7 +221,7 @@ static void edgetag_add_adjacent(Heap *heap, BMEdge *e1, BMEdge **edges_prev, fl
LinkNode *BM_mesh_calc_path_edge(
BMesh *bm, BMEdge *e_src, BMEdge *e_dst, const bool use_length,
- void *user_data, bool (*filter_fn)(BMEdge *, void *user_data))
+ bool (*filter_fn)(BMEdge *, void *user_data), void *user_data)
{
LinkNode *path = NULL;
/* BM_ELEM_TAG flag is used to store visited edges */
@@ -252,7 +252,7 @@ LinkNode *BM_mesh_calc_path_edge(
edges_prev = MEM_callocN(sizeof(*edges_prev) * totedge, "SeamPathPrevious");
cost = MEM_mallocN(sizeof(*cost) * totedge, "SeamPathCost");
- fill_vn_fl(cost, totedge, 1e20f);
+ copy_vn_fl(cost, totedge, 1e20f);
/*
* Arrays are now filled as follows:
@@ -347,7 +347,7 @@ static void facetag_add_adjacent(Heap *heap, BMFace *f_a, BMFace **faces_prev, f
LinkNode *BM_mesh_calc_path_face(
BMesh *bm, BMFace *f_src, BMFace *f_dst, const bool use_length,
- void *user_data, bool (*test_fn)(BMFace *, void *user_data))
+ bool (*test_fn)(BMFace *, void *user_data), void *user_data)
{
LinkNode *path = NULL;
/* BM_ELEM_TAG flag is used to store visited edges */
@@ -378,7 +378,7 @@ LinkNode *BM_mesh_calc_path_face(
faces_prev = MEM_callocN(sizeof(*faces_prev) * totface, __func__);
cost = MEM_mallocN(sizeof(*cost) * totface, __func__);
- fill_vn_fl(cost, totface, 1e20f);
+ copy_vn_fl(cost, totface, 1e20f);
/*
* Arrays are now filled as follows:
diff --git a/source/blender/bmesh/tools/bmesh_path.h b/source/blender/bmesh/tools/bmesh_path.h
index a13290b875e..c39e08e83ef 100644
--- a/source/blender/bmesh/tools/bmesh_path.h
+++ b/source/blender/bmesh/tools/bmesh_path.h
@@ -29,14 +29,17 @@
struct LinkNode *BM_mesh_calc_path_vert(
BMesh *bm, BMVert *v_src, BMVert *v_dst, const bool use_length,
- void *user_data, bool (*filter_fn)(BMVert *, void *));
+ bool (*filter_fn)(BMVert *, void *), void *user_data)
+ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1, 2, 3, 5);
struct LinkNode *BM_mesh_calc_path_edge(
BMesh *bm, BMEdge *e_src, BMEdge *e_dst, const bool use_length,
- void *user_data, bool (*filter_fn)(BMEdge *, void *));
+ bool (*filter_fn)(BMEdge *, void *), void *user_data)
+ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1, 2, 3, 5);
struct LinkNode *BM_mesh_calc_path_face(
BMesh *bm, BMFace *f_src, BMFace *f_dst, const bool use_length,
- void *user_data, bool (*test_fn)(BMFace *, void *));
+ bool (*test_fn)(BMFace *, void *), void *user_data)
+ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1, 2, 3, 5);
#endif /* __BMESH_PATH_H__ */
diff --git a/source/blender/bmesh/tools/bmesh_region_match.c b/source/blender/bmesh/tools/bmesh_region_match.c
new file mode 100644
index 00000000000..a6860a6614a
--- /dev/null
+++ b/source/blender/bmesh/tools/bmesh_region_match.c
@@ -0,0 +1,1519 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/bmesh/tools/bmesh_region_match.c
+ * \ingroup bmesh
+ *
+ * Given a contiguous region of faces,
+ * find multiple matching regions (based on topology) and return them.
+ *
+ * Implementation:
+ *
+ * - Given a face region, find its topological center.
+ * - Compare this with other vertices surrounding geometry with this ones.
+ * (reduce the search space by creating a connectivity ID per vertex
+ * and only run comprehensive tests on those).
+ * - All hashes must be order independent so matching topology can be identified.
+ * - The term UUID here doesn't mean each ID is initially unique.
+ * (uniqueness is improved by re-hashing with connected data).
+ */
+
+#include <string.h>
+
+#include "MEM_guardedalloc.h"
+#include "BLI_listbase.h"
+#include "BLI_linklist.h"
+#include "BLI_alloca.h"
+#include "BLI_ghash.h"
+#include "BLI_mempool.h"
+#include "BLI_linklist_stack.h"
+
+#include "bmesh.h"
+
+#include "tools/bmesh_region_match.h" /* own incldue */
+
+/* avoid re-creating ghash and pools for each search */
+#define USE_WALKER_REUSE
+
+/* do a first-pass id of all vertices,
+ * this avoids expensive checks on every item later on
+ * (works fine without, just slower) */
+#define USE_PIVOT_FASTMATCH
+
+/* otherwise use active element as pivot, for quick tests only */
+#define USE_PIVOT_SEARCH
+
+// #define DEBUG_TIME
+// #define DEBUG_PRINT
+
+#ifdef DEBUG_TIME
+# include "PIL_time.h"
+# include "PIL_time_utildefines.h"
+#endif
+
+#include "BLI_strict_flags.h"
+
+
+/* -------------------------------------------------------------------- */
+/* UUID-Walk API */
+
+/** \name Internal UUIDWalk API
+ * \{ */
+
+#define PRIME_VERT_INIT 100003
+
+typedef uintptr_t UUID_Int;
+
+typedef struct UUIDWalk {
+
+ /* List of faces we can step onto (UUIDFaceStep's) */
+ ListBase faces_step;
+
+ /* Face & Vert UUID's */
+ GHash *verts_uuid;
+ GHash *faces_uuid;
+
+ /* memory pool for LinkNode's */
+ BLI_mempool *link_pool;
+
+ /* memory pool for LinkBase's */
+ BLI_mempool *lbase_pool;
+
+ /* memory pool for UUIDFaceStep's */
+ BLI_mempool *step_pool;
+ BLI_mempool *step_pool_items;
+
+ /* Optionaly use face-tag to isolate search */
+ bool use_face_isolate;
+
+ /* Increment for each pass added */
+ UUID_Int pass;
+
+ /* runtime vars, aviod re-creating each pass */
+ struct {
+ GHash *verts_uuid; /* BMVert -> UUID */
+ GSet *faces_step; /* BMFace */
+
+ GHash *faces_from_uuid; /* UUID -> UUIDFaceStepItem */
+
+ UUID_Int *rehash_store;
+ unsigned int rehash_store_len;
+ } cache;
+
+} UUIDWalk;
+
+/* stores a set of potential faces to step onto */
+typedef struct UUIDFaceStep {
+ struct UUIDFaceStep *next, *prev;
+
+ /* unsorted 'BMFace' */
+ LinkNode *faces;
+
+ /* faces sorted into 'UUIDFaceStepItem' */
+ ListBase items;
+} UUIDFaceStep;
+
+/* store face-lists with same uuid */
+typedef struct UUIDFaceStepItem {
+ struct UUIDFaceStepItem *next, *prev;
+ uintptr_t uuid;
+
+ LinkNode *list;
+ unsigned int list_len;
+} UUIDFaceStepItem;
+
+BLI_INLINE bool bm_uuidwalk_face_test(
+ UUIDWalk *uuidwalk, BMFace *f)
+{
+ if (uuidwalk->use_face_isolate) {
+ return BM_elem_flag_test_bool(f, BM_ELEM_TAG);
+ }
+ else {
+ return true;
+ }
+}
+
+BLI_INLINE bool bm_uuidwalk_vert_lookup(
+ UUIDWalk *uuidwalk, BMVert *v, UUID_Int *r_uuid)
+{
+ void **ret;
+ ret = BLI_ghash_lookup_p(uuidwalk->verts_uuid, v);
+ if (ret) {
+ *r_uuid = (UUID_Int)(*ret);
+ return true;
+ }
+ else {
+ return false;
+ }
+}
+
+BLI_INLINE bool bm_uuidwalk_face_lookup(
+ UUIDWalk *uuidwalk, BMFace *f, UUID_Int *r_uuid)
+{
+ void **ret;
+ ret = BLI_ghash_lookup_p(uuidwalk->faces_uuid, f);
+ if (ret) {
+ *r_uuid = (UUID_Int)(*ret);
+ return true;
+ }
+ else {
+ return false;
+ }
+}
+
+static unsigned int ghashutil_bmelem_indexhash(const void *key)
+{
+ const BMElem *ele = key;
+ return (unsigned int)BM_elem_index_get(ele);
+}
+
+static bool ghashutil_bmelem_indexcmp(const void *a, const void *b)
+{
+ BLI_assert((a != b) == (BM_elem_index_get((BMElem *)a) != BM_elem_index_get((BMElem *)b)));
+ return (a != b);
+}
+
+static GHash *ghash_bmelem_new_ex(
+ const char *info,
+ const unsigned int nentries_reserve)
+{
+ return BLI_ghash_new_ex(ghashutil_bmelem_indexhash, ghashutil_bmelem_indexcmp, info, nentries_reserve);
+}
+
+static GSet *gset_bmelem_new_ex(
+ const char *info,
+ const unsigned int nentries_reserve)
+{
+ return BLI_gset_new_ex(ghashutil_bmelem_indexhash, ghashutil_bmelem_indexcmp, info, nentries_reserve);
+}
+
+
+static GHash *ghash_bmelem_new(const char *info)
+{
+ return ghash_bmelem_new_ex(info, 0);
+}
+
+static GSet *gset_bmelem_new(const char *info)
+{
+ return gset_bmelem_new_ex(info, 0);
+}
+
+
+static void bm_uuidwalk_init(
+ UUIDWalk *uuidwalk,
+ const unsigned int faces_src_region_len,
+ const unsigned int verts_src_region_len)
+{
+ BLI_listbase_clear(&uuidwalk->faces_step);
+
+ uuidwalk->verts_uuid = ghash_bmelem_new_ex(__func__, verts_src_region_len);
+ uuidwalk->faces_uuid = ghash_bmelem_new_ex(__func__, faces_src_region_len);
+
+ uuidwalk->cache.verts_uuid = ghash_bmelem_new(__func__);
+ uuidwalk->cache.faces_step = gset_bmelem_new(__func__);
+
+ /* works because 'int' ghash works for intptr_t too */
+ uuidwalk->cache.faces_from_uuid = BLI_ghash_int_new(__func__);
+
+ uuidwalk->cache.rehash_store = NULL;
+ uuidwalk->cache.rehash_store_len = 0;
+
+ uuidwalk->use_face_isolate = false;
+
+ /* smaller pool's for faster clearing */
+ uuidwalk->link_pool = BLI_mempool_create(sizeof(LinkNode), 64, 64, BLI_MEMPOOL_NOP);
+ uuidwalk->step_pool = BLI_mempool_create(sizeof(UUIDFaceStep), 64, 64, BLI_MEMPOOL_NOP);
+ uuidwalk->step_pool_items = BLI_mempool_create(sizeof(UUIDFaceStepItem), 64, 64, BLI_MEMPOOL_NOP);
+
+ uuidwalk->pass = 1;
+}
+
+static void bm_uuidwalk_clear(
+ UUIDWalk *uuidwalk)
+{
+ BLI_listbase_clear(&uuidwalk->faces_step);
+
+ BLI_ghash_clear(uuidwalk->verts_uuid, NULL, NULL);
+ BLI_ghash_clear(uuidwalk->faces_uuid, NULL, NULL);
+
+ BLI_ghash_clear(uuidwalk->cache.verts_uuid, NULL, NULL);
+ BLI_gset_clear(uuidwalk->cache.faces_step, NULL);
+ BLI_ghash_clear(uuidwalk->cache.faces_from_uuid, NULL, NULL);
+
+ /* keep rehash_store as-is, for reuse */
+
+ uuidwalk->use_face_isolate = false;
+
+ BLI_mempool_clear(uuidwalk->link_pool);
+ BLI_mempool_clear(uuidwalk->step_pool);
+ BLI_mempool_clear(uuidwalk->step_pool_items);
+
+ uuidwalk->pass = 1;
+}
+
+static void bm_uuidwalk_free(
+ UUIDWalk *uuidwalk)
+{
+ /**
+ * Handled by pools
+ *
+ * - uuidwalk->faces_step
+ */
+
+ BLI_ghash_free(uuidwalk->verts_uuid, NULL, NULL);
+ BLI_ghash_free(uuidwalk->faces_uuid, NULL, NULL);
+
+ /* cache */
+ BLI_ghash_free(uuidwalk->cache.verts_uuid, NULL, NULL);
+ BLI_gset_free(uuidwalk->cache.faces_step, NULL);
+ BLI_ghash_free(uuidwalk->cache.faces_from_uuid, NULL, NULL);
+ MEM_SAFE_FREE(uuidwalk->cache.rehash_store);
+
+ BLI_mempool_destroy(uuidwalk->link_pool);
+ BLI_mempool_destroy(uuidwalk->step_pool);
+ BLI_mempool_destroy(uuidwalk->step_pool_items);
+}
+
+static UUID_Int bm_uuidwalk_calc_vert_uuid(
+ UUIDWalk *uuidwalk, BMVert *v)
+{
+#define PRIME_VERT_SMALL 7
+#define PRIME_VERT_MID 43
+#define PRIME_VERT_LARGE 1031
+
+#define PRIME_FACE_SMALL 13
+#define PRIME_FACE_MID 53
+
+ UUID_Int uuid;
+
+ uuid = uuidwalk->pass * PRIME_VERT_LARGE;
+
+ /* vert -> other */
+ {
+ unsigned int tot = 0;
+ BMIter eiter;
+ BMEdge *e;
+ BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) {
+ BMVert *v_other = BM_edge_other_vert(e, v);
+ UUID_Int uuid_other;
+ if (bm_uuidwalk_vert_lookup(uuidwalk, v_other, &uuid_other)) {
+ uuid ^= (uuid_other * PRIME_VERT_SMALL);
+ tot += 1;
+ }
+ }
+ uuid ^= (tot * PRIME_VERT_MID);
+ }
+
+ /* faces */
+ {
+ unsigned int tot = 0;
+ BMIter iter;
+ BMFace *f;
+
+ BM_ITER_ELEM (f, &iter, v, BM_FACES_OF_VERT) {
+ UUID_Int uuid_other;
+ if (bm_uuidwalk_face_lookup(uuidwalk, f, &uuid_other)) {
+ uuid ^= (uuid_other * PRIME_FACE_SMALL);
+ tot += 1;
+ }
+ }
+ uuid ^= (tot * PRIME_FACE_MID);
+ }
+
+ return uuid;
+
+#undef PRIME_VERT_SMALL
+#undef PRIME_VERT_MID
+#undef PRIME_VERT_LARGE
+
+#undef PRIME_FACE_SMALL
+#undef PRIME_FACE_MID
+}
+
+static UUID_Int bm_uuidwalk_calc_face_uuid(
+ UUIDWalk *uuidwalk, BMFace *f)
+{
+#define PRIME_VERT_SMALL 11
+
+#define PRIME_FACE_SMALL 17
+#define PRIME_FACE_LARGE 1013
+
+ UUID_Int uuid;
+
+ uuid = uuidwalk->pass * (unsigned int)f->len * PRIME_FACE_LARGE;
+
+ /* face-verts */
+ {
+ BMLoop *l_iter, *l_first;
+
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
+ UUID_Int uuid_other;
+ if (bm_uuidwalk_vert_lookup(uuidwalk, l_iter->v, &uuid_other)) {
+ uuid ^= (uuid_other * PRIME_VERT_SMALL);
+ }
+ } while ((l_iter = l_iter->next) != l_first);
+ }
+
+ /* face-faces (connected by edge) */
+ {
+ BMLoop *l_iter, *l_first;
+
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
+ if (l_iter->radial_next != l_iter) {
+ BMLoop *l_iter_radial = l_iter->radial_next;
+ do {
+ UUID_Int uuid_other;
+ if (bm_uuidwalk_face_lookup(uuidwalk, l_iter_radial->f, &uuid_other)) {
+ uuid ^= (uuid_other * PRIME_FACE_SMALL);
+ }
+ } while ((l_iter_radial = l_iter_radial->radial_next) != l_iter);
+ }
+ } while ((l_iter = l_iter->next) != l_first);
+ }
+
+ return uuid;
+
+#undef PRIME_VERT_SMALL
+
+#undef PRIME_FACE_SMALL
+#undef PRIME_FACE_LARGE
+}
+
+static void bm_uuidwalk_rehash_reserve(
+ UUIDWalk *uuidwalk, unsigned int rehash_store_len_new)
+{
+ if (UNLIKELY(rehash_store_len_new > uuidwalk->cache.rehash_store_len)) {
+ /* avoid re-allocs */
+ rehash_store_len_new *= 2;
+ uuidwalk->cache.rehash_store =
+ MEM_reallocN(uuidwalk->cache.rehash_store,
+ rehash_store_len_new * sizeof(*uuidwalk->cache.rehash_store));
+ uuidwalk->cache.rehash_store_len = rehash_store_len_new;
+ }
+}
+
+/**
+ * Re-hash all elements, delay updating so as not to create feedback loop.
+ */
+static void bm_uuidwalk_rehash(
+ UUIDWalk *uuidwalk)
+{
+ GHashIterator gh_iter;
+ UUID_Int *uuid_store;
+ unsigned int i;
+
+ unsigned int rehash_store_len_new = MAX2(BLI_ghash_size(uuidwalk->verts_uuid),
+ BLI_ghash_size(uuidwalk->faces_uuid));
+
+ bm_uuidwalk_rehash_reserve(uuidwalk, rehash_store_len_new);
+ uuid_store = uuidwalk->cache.rehash_store;
+
+ /* verts */
+ i = 0;
+ GHASH_ITER (gh_iter, uuidwalk->verts_uuid) {
+ BMVert *v = BLI_ghashIterator_getKey(&gh_iter);
+ uuid_store[i++] = bm_uuidwalk_calc_vert_uuid(uuidwalk, v);
+ }
+ i = 0;
+ GHASH_ITER (gh_iter, uuidwalk->verts_uuid) {
+ void **uuid_p = BLI_ghashIterator_getValue_p(&gh_iter);
+ *((UUID_Int *)uuid_p) = uuid_store[i++];
+ }
+
+ /* faces */
+ i = 0;
+ GHASH_ITER (gh_iter, uuidwalk->faces_uuid) {
+ BMFace *f = BLI_ghashIterator_getKey(&gh_iter);
+ uuid_store[i++] = bm_uuidwalk_calc_face_uuid(uuidwalk, f);
+ }
+ i = 0;
+ GHASH_ITER (gh_iter, uuidwalk->faces_uuid) {
+ void **uuid_p = BLI_ghashIterator_getValue_p(&gh_iter);
+ *((UUID_Int *)uuid_p) = uuid_store[i++];
+ }
+}
+
+static void bm_uuidwalk_rehash_facelinks(
+ UUIDWalk *uuidwalk,
+ LinkNode *faces, const unsigned int faces_len,
+ const bool is_init)
+{
+ UUID_Int *uuid_store;
+ LinkNode *f_link;
+ unsigned int i;
+
+ bm_uuidwalk_rehash_reserve(uuidwalk, faces_len);
+ uuid_store = uuidwalk->cache.rehash_store;
+
+ i = 0;
+ for (f_link = faces; f_link; f_link = f_link->next) {
+ BMFace *f = f_link->link;
+ uuid_store[i++] = bm_uuidwalk_calc_face_uuid(uuidwalk, f);
+ }
+
+ i = 0;
+ if (is_init) {
+ for (f_link = faces; f_link; f_link = f_link->next) {
+ BMFace *f = f_link->link;
+ BLI_ghash_insert(uuidwalk->faces_uuid, f, (void *)uuid_store[i++]);
+ }
+ }
+ else {
+ for (f_link = faces; f_link; f_link = f_link->next) {
+ BMFace *f = f_link->link;
+ void **uuid_p = BLI_ghash_lookup_p(uuidwalk->faces_uuid, f);
+ *((UUID_Int *)uuid_p) = uuid_store[i++];
+ }
+ }
+}
+
+static bool bm_vert_is_uuid_connect(
+ UUIDWalk *uuidwalk, BMVert *v)
+{
+ BMIter eiter;
+ BMEdge *e;
+
+ BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) {
+ BMVert *v_other = BM_edge_other_vert(e, v);
+ if (BLI_ghash_haskey(uuidwalk->verts_uuid, v_other)) {
+ return true;
+ }
+ }
+ return false;
+}
+
+static void bm_uuidwalk_pass_add(
+ UUIDWalk *uuidwalk, LinkNode *faces_pass, const unsigned int faces_pass_len)
+{
+ GHashIterator gh_iter;
+ GHash *verts_uuid_pass;
+ GSet *faces_step_next;
+ LinkNode *f_link;
+
+ UUIDFaceStep *fstep;
+
+ BLI_assert(faces_pass_len == (unsigned int)BLI_linklist_count(faces_pass));
+
+ /* rehash faces now all their verts have been added */
+ bm_uuidwalk_rehash_facelinks(uuidwalk, faces_pass, faces_pass_len, true);
+
+ /* create verts_new */
+ verts_uuid_pass = uuidwalk->cache.verts_uuid;
+ faces_step_next = uuidwalk->cache.faces_step;
+
+ BLI_assert(BLI_ghash_size(verts_uuid_pass) == 0);
+ BLI_assert(BLI_gset_size(faces_step_next) == 0);
+
+ /* Add the face_step data from connected faces, creating new passes */
+ fstep = BLI_mempool_alloc(uuidwalk->step_pool);
+ BLI_addhead(&uuidwalk->faces_step, fstep);
+ fstep->faces = NULL;
+ BLI_listbase_clear(&fstep->items);
+
+ for (f_link = faces_pass; f_link; f_link = f_link->next) {
+ BMFace *f = f_link->link;
+ BMLoop *l_iter, *l_first;
+
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
+ /* fill verts_new */
+ void **val_p;
+ if (!BLI_ghash_haskey(uuidwalk->verts_uuid, l_iter->v) &&
+ !BLI_ghash_ensure_p(verts_uuid_pass, l_iter->v, &val_p) &&
+ (bm_vert_is_uuid_connect(uuidwalk, l_iter->v) == true))
+ {
+ const UUID_Int uuid = bm_uuidwalk_calc_vert_uuid(uuidwalk, l_iter->v);
+ *val_p = (void *)uuid;
+ }
+
+ /* fill faces_step_next */
+ if (l_iter->radial_next != l_iter) {
+ BMLoop *l_iter_radial = l_iter->radial_next;
+ do {
+ if (!BLI_ghash_haskey(uuidwalk->faces_uuid, l_iter_radial->f) &&
+ !BLI_gset_haskey(faces_step_next, l_iter_radial->f) &&
+ (bm_uuidwalk_face_test(uuidwalk, l_iter_radial->f)))
+ {
+ BLI_gset_insert(faces_step_next, l_iter_radial->f);
+
+ /* add to fstep */
+ BLI_linklist_prepend_pool(&fstep->faces, l_iter_radial->f, uuidwalk->link_pool);
+ }
+ } while ((l_iter_radial = l_iter_radial->radial_next) != l_iter);
+ }
+ } while ((l_iter = l_iter->next) != l_first);
+ }
+
+ /* faces_uuid.update(verts_new) */
+ GHASH_ITER (gh_iter, verts_uuid_pass) {
+ BMVert *v = BLI_ghashIterator_getKey(&gh_iter);
+ void *uuid_p = BLI_ghashIterator_getValue(&gh_iter);
+ BLI_ghash_insert(uuidwalk->verts_uuid, v, uuid_p);
+ }
+
+ /* rehash faces now all their verts have been added */
+ bm_uuidwalk_rehash_facelinks(uuidwalk, faces_pass, faces_pass_len, false);
+
+ uuidwalk->pass += 1;
+
+ BLI_ghash_clear(uuidwalk->cache.verts_uuid, NULL, NULL);
+ BLI_gset_clear(uuidwalk->cache.faces_step, NULL);
+}
+
+static int bm_face_len_cmp(const void *v1, const void *v2)
+{
+ const BMFace *f1 = v1, *f2 = v2;
+
+ if (f1->len > f2->len) return 1;
+ else if (f1->len < f2->len) return -1;
+ else return 0;
+}
+
+static unsigned int bm_uuidwalk_init_from_edge(
+ UUIDWalk *uuidwalk, BMEdge *e)
+{
+ BMLoop *l_iter = e->l;
+ unsigned int f_arr_len = (unsigned int)BM_edge_face_count(e);
+ BMFace **f_arr = BLI_array_alloca(f_arr, f_arr_len);
+ unsigned int fstep_num = 0, i = 0;
+
+ do {
+ BMFace *f = l_iter->f;
+ if (bm_uuidwalk_face_test(uuidwalk, f)) {
+ f_arr[i++] = f;
+ }
+ } while ((l_iter = l_iter->radial_next) != e->l);
+ BLI_assert(i <= f_arr_len);
+ f_arr_len = i;
+
+ qsort(f_arr, f_arr_len, sizeof(*f_arr), bm_face_len_cmp);
+
+ /* start us off! */
+ {
+ const UUID_Int uuid = PRIME_VERT_INIT;
+ BLI_ghash_insert(uuidwalk->verts_uuid, e->v1, (void *)uuid);
+ BLI_ghash_insert(uuidwalk->verts_uuid, e->v2, (void *)uuid);
+ }
+
+ /* turning an array into LinkNode's seems odd,
+ * but this is just for initialization,
+ * elsewhere using LinkNode's makes more sense */
+ for (i = 0; i < f_arr_len; ) {
+ LinkNode *faces_pass = NULL;
+ const unsigned int i_init = i;
+ const int f_len = f_arr[i]->len;
+
+ do {
+ BLI_linklist_prepend_pool(&faces_pass, f_arr[i++], uuidwalk->link_pool);
+ } while (i < f_arr_len && (f_len == f_arr[i]->len));
+
+ bm_uuidwalk_pass_add(uuidwalk, faces_pass, i - i_init);
+ BLI_linklist_free_pool(faces_pass, NULL, uuidwalk->link_pool);
+ fstep_num += 1;
+ }
+
+ return fstep_num;
+}
+
+#undef PRIME_VERT_INIT
+
+/** \} */
+
+
+/** \name Internal UUIDFaceStep API
+ * \{ */
+
+static int facestep_sort(const void *a, const void *b)
+{
+ const UUIDFaceStepItem *fstep_a = a;
+ const UUIDFaceStepItem *fstep_b = b;
+ return (fstep_a->uuid > fstep_b->uuid) ? 1 : 0;
+}
+
+/**
+ * Put faces in lists based on their uuid's,
+ * re-run for each pass since rehashing may differentiate face-groups.
+ */
+static bool bm_uuidwalk_facestep_begin(
+ UUIDWalk *uuidwalk, UUIDFaceStep *fstep)
+{
+ LinkNode *f_link, *f_link_next, **f_link_prev_p;
+ bool ok = false;
+
+ BLI_assert(BLI_ghash_size(uuidwalk->cache.faces_from_uuid) == 0);
+ BLI_assert(BLI_listbase_is_empty(&fstep->items));
+
+ f_link_prev_p = &fstep->faces;
+ for (f_link = fstep->faces; f_link; f_link = f_link_next) {
+ BMFace *f = f_link->link;
+ f_link_next = f_link->next;
+
+ /* possible another pass added this face already, free in that case */
+ if (!BLI_ghash_haskey(uuidwalk->faces_uuid, f)) {
+ const UUID_Int uuid = bm_uuidwalk_calc_face_uuid(uuidwalk, f);
+ UUIDFaceStepItem *fstep_item;
+ void **val_p;
+
+ ok = true;
+
+ if (BLI_ghash_ensure_p(uuidwalk->cache.faces_from_uuid, (void *)uuid, &val_p)) {
+ fstep_item = *val_p;
+ }
+ else {
+ fstep_item = *val_p = BLI_mempool_alloc(uuidwalk->step_pool_items);
+
+ /* add to start, so its handled on the next round of passes */
+ BLI_addhead(&fstep->items, fstep_item);
+ fstep_item->uuid = uuid;
+ fstep_item->list = NULL;
+ fstep_item->list_len = 0;
+ }
+
+ BLI_linklist_prepend_pool(&fstep_item->list, f, uuidwalk->link_pool);
+ fstep_item->list_len += 1;
+
+ f_link_prev_p = &f_link->next;
+ }
+ else {
+ *f_link_prev_p = f_link->next;
+ BLI_mempool_free(uuidwalk->link_pool, f_link);
+ }
+ }
+
+ BLI_ghash_clear(uuidwalk->cache.faces_from_uuid, NULL, NULL);
+
+ BLI_listbase_sort(&fstep->items, facestep_sort);
+
+ return ok;
+}
+
+/**
+ * Cleans up temp data from #bm_uuidwalk_facestep_begin
+ */
+static void bm_uuidwalk_facestep_end(
+ UUIDWalk *uuidwalk, UUIDFaceStep *fstep)
+{
+ UUIDFaceStepItem *fstep_item;
+
+ while ((fstep_item = BLI_pophead(&fstep->items))) {
+ BLI_mempool_free(uuidwalk->step_pool_items, fstep_item);
+ }
+}
+
+static void bm_uuidwalk_facestep_free(
+ UUIDWalk *uuidwalk, UUIDFaceStep *fstep)
+{
+ LinkNode *f_link, *f_link_next;
+
+ BLI_assert(BLI_listbase_is_empty(&fstep->items));
+
+ for (f_link = fstep->faces; f_link; f_link = f_link_next) {
+ f_link_next = f_link->next;
+ BLI_mempool_free(uuidwalk->link_pool, f_link);
+ }
+
+ BLI_remlink(&uuidwalk->faces_step, fstep);
+ BLI_mempool_free(uuidwalk->step_pool, fstep);
+}
+
+/** \} */
+
+
+/* -------------------------------------------------------------------- */
+/* Main Loop to match up regions */
+
+/**
+ * Given a face region and 2 candidate verts to begin mapping.
+ * return the matching region or NULL.
+ */
+static BMFace **bm_mesh_region_match_pair(
+#ifdef USE_WALKER_REUSE
+ UUIDWalk *w_src, UUIDWalk *w_dst,
+#endif
+ BMEdge *e_src, BMEdge *e_dst,
+ const unsigned int faces_src_region_len,
+ const unsigned int verts_src_region_len,
+ unsigned int *r_faces_result_len)
+{
+#ifndef USE_WALKER_REUSE
+ UUIDWalk w_src_, w_dst_;
+ UUIDWalk *w_src = &w_src_, *w_dst = &w_dst_;
+#endif
+ BMFace **faces_result = NULL;
+ bool found = false;
+
+ BLI_assert(e_src != e_dst);
+
+#ifndef USE_WALKER_REUSE
+ bm_uuidwalk_init(w_src, faces_src_region_len, verts_src_region_len);
+ bm_uuidwalk_init(w_dst, faces_src_region_len, verts_src_region_len);
+#endif
+
+ w_src->use_face_isolate = true;
+
+ /* setup the initial state */
+ if (UNLIKELY(bm_uuidwalk_init_from_edge(w_src, e_src) !=
+ bm_uuidwalk_init_from_edge(w_dst, e_dst)))
+ {
+ /* should never happen, if verts passed are compatible, but to be safe... */
+ goto finally;
+ }
+
+ bm_uuidwalk_rehash_reserve(w_src, MAX2(faces_src_region_len, verts_src_region_len));
+ bm_uuidwalk_rehash_reserve(w_dst, MAX2(faces_src_region_len, verts_src_region_len));
+
+ while (true) {
+ bool ok = false;
+
+ UUIDFaceStep *fstep_src = w_src->faces_step.first;
+ UUIDFaceStep *fstep_dst = w_dst->faces_step.first;
+
+ BLI_assert(BLI_listbase_count(&w_src->faces_step) == BLI_listbase_count(&w_dst->faces_step));
+
+ while (fstep_src) {
+
+ /* even if the destination has faces,
+ * it's not important, since the source doesn't, free and move-on. */
+ if (fstep_src->faces == NULL) {
+ UUIDFaceStep *fstep_src_next = fstep_src->next;
+ UUIDFaceStep *fstep_dst_next = fstep_dst->next;
+ bm_uuidwalk_facestep_free(w_src, fstep_src);
+ bm_uuidwalk_facestep_free(w_dst, fstep_dst);
+ fstep_src = fstep_src_next;
+ fstep_dst = fstep_dst_next;
+ continue;
+ }
+
+ if (bm_uuidwalk_facestep_begin(w_src, fstep_src) &&
+ bm_uuidwalk_facestep_begin(w_dst, fstep_dst))
+ {
+ /* Step over face-lists with matching UUID's
+ * both lists are sorted, so no need for lookups.
+ * The data is created on 'begin' and cleared on 'end' */
+ UUIDFaceStepItem *fstep_item_src;
+ UUIDFaceStepItem *fstep_item_dst;
+ for (fstep_item_src = fstep_src->items.first,
+ fstep_item_dst = fstep_dst->items.first;
+ fstep_item_src && fstep_item_dst;
+ fstep_item_src = fstep_item_src->next,
+ fstep_item_dst = fstep_item_dst->next)
+ {
+ while ((fstep_item_dst != NULL) &&
+ (fstep_item_dst->uuid < fstep_item_src->uuid))
+ {
+ fstep_item_dst = fstep_item_dst->next;
+ }
+
+ if ((fstep_item_dst == NULL) ||
+ (fstep_item_src->uuid != fstep_item_dst->uuid) ||
+ (fstep_item_src->list_len > fstep_item_dst->list_len))
+ {
+ /* if the target walker has less than the source
+ * then the islands don't match, bail early */
+ ok = false;
+ break;
+ }
+
+ if (fstep_item_src->list_len == fstep_item_dst->list_len) {
+ /* found a match */
+ bm_uuidwalk_pass_add(w_src, fstep_item_src->list, fstep_item_src->list_len);
+ bm_uuidwalk_pass_add(w_dst, fstep_item_dst->list, fstep_item_dst->list_len);
+
+ BLI_linklist_free_pool(fstep_item_src->list, NULL, w_src->link_pool);
+ BLI_linklist_free_pool(fstep_item_dst->list, NULL, w_dst->link_pool);
+
+ fstep_item_src->list = NULL;
+ fstep_item_src->list_len = 0;
+
+ fstep_item_dst->list = NULL;
+ fstep_item_dst->list_len = 0;
+
+ ok = true;
+ }
+ }
+ }
+
+ bm_uuidwalk_facestep_end(w_src, fstep_src);
+ bm_uuidwalk_facestep_end(w_dst, fstep_dst);
+
+ /* lock-step */
+ fstep_src = fstep_src->next;
+ fstep_dst = fstep_dst->next;
+ }
+
+ if (!ok) {
+ break;
+ }
+
+ found = (BLI_ghash_size(w_dst->faces_uuid) == faces_src_region_len);
+ if (found) {
+ break;
+ }
+
+ /* Expensive! but some cases fails without.
+ * (also faster in other cases since it can rule-out invalid regions) */
+ bm_uuidwalk_rehash(w_src);
+ bm_uuidwalk_rehash(w_dst);
+ }
+
+ if (found) {
+ GHashIterator gh_iter;
+ const unsigned int faces_result_len = BLI_ghash_size(w_dst->faces_uuid);
+ unsigned int i;
+
+ faces_result = MEM_mallocN(sizeof(*faces_result) * (faces_result_len + 1), __func__);
+ GHASH_ITER_INDEX (gh_iter, w_dst->faces_uuid, i) {
+ BMFace *f = BLI_ghashIterator_getKey(&gh_iter);
+ faces_result[i] = f;
+ }
+ faces_result[faces_result_len] = NULL;
+ *r_faces_result_len = faces_result_len;
+ }
+ else {
+ *r_faces_result_len = 0;
+ }
+
+finally:
+
+#ifdef USE_WALKER_REUSE
+ bm_uuidwalk_clear(w_src);
+ bm_uuidwalk_clear(w_dst);
+#else
+ bm_uuidwalk_free(w_src);
+ bm_uuidwalk_free(w_dst);
+#endif
+
+ return faces_result;
+}
+
+/**
+ * Tag as visited, avoid re-use.
+ */
+static void bm_face_array_visit(
+ BMFace **faces, const unsigned int faces_len,
+ unsigned int *r_verts_len,
+ bool visit_faces)
+{
+ unsigned int verts_len = 0;
+ unsigned int i;
+ for (i = 0; i < faces_len; i++) {
+ BMFace *f = faces[i];
+ BMLoop *l_iter, *l_first;
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
+ if (r_verts_len) {
+ if (!BM_elem_flag_test(l_iter->v, BM_ELEM_TAG)) {
+ verts_len += 1;
+ }
+ }
+
+ BM_elem_flag_enable(l_iter->e, BM_ELEM_TAG);
+ BM_elem_flag_enable(l_iter->v, BM_ELEM_TAG);
+ } while ((l_iter = l_iter->next) != l_first);
+
+ if (visit_faces) {
+ BM_elem_flag_enable(f, BM_ELEM_TAG);
+ }
+ }
+
+ if (r_verts_len) {
+ *r_verts_len = verts_len;
+ }
+}
+
+#ifdef USE_PIVOT_SEARCH
+
+/** \name Internal UUIDWalk API
+ * \{ */
+
+/* signed user id */
+typedef intptr_t SUID_Int;
+
+static bool bm_edge_is_region_boundary(BMEdge *e)
+{
+ if (e->l->radial_next != e->l) {
+ BMLoop *l_iter = e->l;
+ do {
+ if (!BM_elem_flag_test(l_iter->f, BM_ELEM_TAG)) {
+ return true;
+ }
+ } while ((l_iter = l_iter->radial_next) != e->l);
+ return false;
+ }
+ else {
+ /* boundary */
+ return true;
+ }
+}
+
+static void bm_face_region_pivot_edge_use_best(
+ GHash *gh, BMEdge *e_test,
+ BMEdge **r_e_pivot_best,
+ SUID_Int e_pivot_best_id[2])
+{
+ SUID_Int e_pivot_test_id[2];
+
+ e_pivot_test_id[0] = (SUID_Int)BLI_ghash_lookup(gh, e_test->v1);
+ e_pivot_test_id[1] = (SUID_Int)BLI_ghash_lookup(gh, e_test->v2);
+ if (e_pivot_test_id[0] > e_pivot_test_id[1]) {
+ SWAP(SUID_Int, e_pivot_test_id[0], e_pivot_test_id[1]);
+ }
+
+ if ((*r_e_pivot_best == NULL) ||
+ ((e_pivot_best_id[0] != e_pivot_test_id[0]) ?
+ (e_pivot_best_id[0] < e_pivot_test_id[0]) :
+ (e_pivot_best_id[1] < e_pivot_test_id[1])))
+ {
+ e_pivot_best_id[0] = e_pivot_test_id[0];
+ e_pivot_best_id[1] = e_pivot_test_id[1];
+
+ /* both verts are from the same pass, record this! */
+ *r_e_pivot_best = e_test;
+ }
+}
+
+/* quick id from a boundary vertex */
+static SUID_Int bm_face_region_vert_boundary_id(BMVert *v)
+{
+#define PRIME_VERT_SMALL_A 7
+#define PRIME_VERT_SMALL_B 13
+#define PRIME_VERT_MID_A 103
+#define PRIME_VERT_MID_B 131
+
+ int tot = 0;
+ BMIter iter;
+ BMLoop *l;
+ SUID_Int id = PRIME_VERT_MID_A;
+
+ BM_ITER_ELEM (l, &iter, v, BM_LOOPS_OF_VERT) {
+ const bool is_boundary_vert = (bm_edge_is_region_boundary(l->e) || bm_edge_is_region_boundary(l->prev->e));
+ id ^= l->f->len * (is_boundary_vert ? PRIME_VERT_SMALL_A : PRIME_VERT_SMALL_B);
+ tot += 1;
+ }
+
+ id ^= (tot * PRIME_VERT_MID_B);
+
+ return id ? ABS(id) : 1;
+
+#undef PRIME_VERT_SMALL_A
+#undef PRIME_VERT_SMALL_B
+#undef PRIME_VERT_MID_A
+#undef PRIME_VERT_MID_B
+}
+
+/**
+ * Accumulate id's from a previous pass (swap sign each pass)
+ */
+static SUID_Int bm_face_region_vert_pass_id(GHash *gh, BMVert *v)
+{
+ BMIter eiter;
+ BMEdge *e;
+ SUID_Int tot = 0;
+ SUID_Int v_sum_face_len = 0;
+ SUID_Int v_sum_id = 0;
+ SUID_Int id;
+ SUID_Int id_min = INTPTR_MIN + 1;
+
+#define PRIME_VERT_MID_A 23
+#define PRIME_VERT_MID_B 31
+
+ BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) {
+ if (BM_elem_flag_test(e, BM_ELEM_TAG)) {
+ BMVert *v_other = BM_edge_other_vert(e, v);
+ if (BM_elem_flag_test(v_other, BM_ELEM_TAG)) {
+ /* non-zero values aren't allowed... so no need to check haskey */
+ SUID_Int v_other_id = (SUID_Int)BLI_ghash_lookup(gh, v_other);
+ if (v_other_id > 0) {
+ v_sum_id += v_other_id;
+ tot += 1;
+
+ /* face-count */
+ {
+ BMLoop *l_iter = e->l;
+ do {
+ if (BM_elem_flag_test(l_iter->f, BM_ELEM_TAG)) {
+ v_sum_face_len += l_iter->f->len;
+ }
+ } while ((l_iter = l_iter->radial_next) != e->l);
+ }
+ }
+ }
+ }
+ }
+
+ id = (tot * PRIME_VERT_MID_A);
+ id ^= (v_sum_face_len * PRIME_VERT_MID_B);
+ id ^= v_sum_id;
+
+ /* disallow 0 & min (since it can't be flipped) */
+ id = (UNLIKELY(id == 0) ? 1 : UNLIKELY(id < id_min) ? id_min : id);
+
+ return ABS(id);
+
+#undef PRIME_VERT_MID_A
+#undef PRIME_VERT_MID_B
+}
+
+/**
+ * Take a face region and find the inner-most vertex.
+ * also calculate the number of connections to the boundary,
+ * and the total number unique of verts used by this face region.
+ *
+ * This is only called once on the source region (no need to be highly optimized).
+ */
+static BMEdge *bm_face_region_pivot_edge_find(
+ BMFace **faces_region, unsigned int faces_region_len,
+ unsigned int verts_region_len,
+ unsigned int *r_depth)
+{
+ /* note, keep deterministic where possible (geometry order independent)
+ * this function assumed all visit faces & edges are tagged */
+
+ BLI_LINKSTACK_DECLARE(vert_queue_prev, BMVert *);
+ BLI_LINKSTACK_DECLARE(vert_queue_next, BMVert *);
+
+ GHash *gh = BLI_ghash_ptr_new(__func__);
+ unsigned int i;
+
+ BMEdge *e_pivot = NULL;
+ /* pick any non-boundary edge (not ideal) */
+ BMEdge *e_pivot_fallback = NULL;
+
+ SUID_Int pass = 0;
+
+ /* total verts in 'gs' we have visited - aka - not v_init_none */
+ unsigned int vert_queue_used = 0;
+
+ BLI_LINKSTACK_INIT(vert_queue_prev);
+ BLI_LINKSTACK_INIT(vert_queue_next);
+
+ /* face-verts */
+ for (i = 0; i < faces_region_len; i++) {
+ BMFace *f = faces_region[i];
+
+ BMLoop *l_iter, *l_first;
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
+ BMEdge *e = l_iter->e;
+ if (bm_edge_is_region_boundary(e)) {
+ unsigned int j;
+ for (j = 0; j < 2; j++) {
+ void **val_p;
+ if (!BLI_ghash_ensure_p(gh, (&e->v1)[j], &val_p)) {
+ SUID_Int v_id = bm_face_region_vert_boundary_id((&e->v1)[j]);
+ *val_p = (void *)v_id;
+ BLI_LINKSTACK_PUSH(vert_queue_prev, (&e->v1)[j]);
+ vert_queue_used += 1;
+ }
+ }
+ }
+ else {
+ /* use incase (depth == 0), no interior verts */
+ e_pivot_fallback = e;
+ }
+ } while ((l_iter = l_iter->next) != l_first);
+ }
+
+ while (BLI_LINKSTACK_SIZE(vert_queue_prev)) {
+ BMVert *v;
+ while ((v = BLI_LINKSTACK_POP(vert_queue_prev))) {
+ BMIter eiter;
+ BMEdge *e;
+ BLI_assert(BLI_ghash_haskey(gh, v));
+ BLI_assert((SUID_Int)BLI_ghash_lookup(gh, v) > 0);
+ BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) {
+ if (BM_elem_flag_test(e, BM_ELEM_TAG)) {
+ BMVert *v_other = BM_edge_other_vert(e, v);
+ if (BM_elem_flag_test(v_other, BM_ELEM_TAG)) {
+ void **val_p;
+ if (!BLI_ghash_ensure_p(gh, v_other, &val_p)) {
+ /* add as negative, so we know not to read from them this pass */
+ const SUID_Int v_id_other = -bm_face_region_vert_pass_id(gh, v_other);
+ *val_p = (void *)v_id_other;
+ BLI_LINKSTACK_PUSH(vert_queue_next, v_other);
+ vert_queue_used += 1;
+ }
+ }
+ }
+ }
+ }
+
+ /* flip all the newly added hashes to positive */
+ {
+ LinkNode *v_link;
+ for (v_link = vert_queue_next; v_link; v_link = v_link->next) {
+ SUID_Int *v_id_p = (SUID_Int *)BLI_ghash_lookup_p(gh, v_link->link);
+ *v_id_p = -(*v_id_p);
+ BLI_assert(*v_id_p > 0);
+ }
+ }
+
+ BLI_LINKSTACK_SWAP(vert_queue_prev, vert_queue_next);
+ pass += 1;
+
+ if (vert_queue_used == verts_region_len) {
+ break;
+ }
+ }
+
+ if (BLI_LINKSTACK_SIZE(vert_queue_prev) >= 2) {
+ /* common case - we managed to find some interior verts */
+ LinkNode *v_link;
+ BMEdge *e_pivot_best = NULL;
+ SUID_Int e_pivot_best_id[2] = {0, 0};
+
+ /* temp untag, so we can quickly know what other verts are in this last pass */
+ for (v_link = vert_queue_prev; v_link; v_link = v_link->next) {
+ BMVert *v = v_link->link;
+ BM_elem_flag_disable(v, BM_ELEM_TAG);
+ }
+
+ /* restore correct tagging */
+ for (v_link = vert_queue_prev; v_link; v_link = v_link->next) {
+ BMIter eiter;
+ BMEdge *e_test;
+
+ BMVert *v = v_link->link;
+ BM_elem_flag_enable(v, BM_ELEM_TAG);
+
+ BM_ITER_ELEM (e_test, &eiter, v, BM_EDGES_OF_VERT) {
+ if (BM_elem_flag_test(e_test, BM_ELEM_TAG)) {
+ BMVert *v_other = BM_edge_other_vert(e_test, v);
+ if (BM_elem_flag_test(v_other, BM_ELEM_TAG) == false) {
+ bm_face_region_pivot_edge_use_best(gh, e_test, &e_pivot_best, e_pivot_best_id);
+ }
+ }
+ }
+ }
+
+ e_pivot = e_pivot_best;
+ }
+
+ if ((e_pivot == NULL) && BLI_LINKSTACK_SIZE(vert_queue_prev)) {
+ /* find the best single edge */
+ BMEdge *e_pivot_best = NULL;
+ SUID_Int e_pivot_best_id[2] = {0, 0};
+
+ LinkNode *v_link;
+
+ /* reduce a pass since we're having to step into a previous passes vert,
+ * and will be closer to the boundary */
+ BLI_assert(pass != 0);
+ pass -= 1;
+
+ for (v_link = vert_queue_prev; v_link; v_link = v_link->next) {
+ BMVert *v = v_link->link;
+
+ BMIter eiter;
+ BMEdge *e_test;
+ BM_ITER_ELEM (e_test, &eiter, v, BM_EDGES_OF_VERT) {
+ if (BM_elem_flag_test(e_test, BM_ELEM_TAG)) {
+ BMVert *v_other = BM_edge_other_vert(e_test, v);
+ if (BM_elem_flag_test(v_other, BM_ELEM_TAG)) {
+ bm_face_region_pivot_edge_use_best(gh, e_test, &e_pivot_best, e_pivot_best_id);
+ }
+ }
+ }
+ }
+
+ e_pivot = e_pivot_best;
+ }
+
+ BLI_LINKSTACK_FREE(vert_queue_prev);
+ BLI_LINKSTACK_FREE(vert_queue_next);
+
+ BLI_ghash_free(gh, NULL, NULL);
+
+ if (e_pivot == NULL) {
+#ifdef DEBUG_PRINT
+ printf("%s: using fallback edge!\n", __func__);
+#endif
+ e_pivot = e_pivot_fallback;
+ pass = 0;
+ }
+
+ *r_depth = (unsigned int)pass;
+
+ return e_pivot;
+}
+/** \} */
+
+#endif /* USE_PIVOT_SEARCH */
+
+
+/* -------------------------------------------------------------------- */
+/* Quick UUID pass - identify candidates */
+
+#ifdef USE_PIVOT_FASTMATCH
+
+/** \name Fast Match
+ * \{ */
+
+typedef uintptr_t UUIDFashMatch;
+
+static UUIDFashMatch bm_vert_fasthash_single(BMVert *v)
+{
+ BMIter eiter;
+ BMEdge *e;
+ UUIDFashMatch e_num = 0, f_num = 0, l_num = 0;
+
+#define PRIME_EDGE 7
+#define PRIME_FACE 31
+#define PRIME_LOOP 61
+
+ BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) {
+ if (!BM_edge_is_wire(e)) {
+ BMLoop *l_iter = e->l;
+ e_num += 1;
+ do {
+ f_num += 1;
+ l_num += (unsigned int)l_iter->f->len;
+ } while ((l_iter = l_iter->radial_next) != e->l);
+ }
+ }
+
+ return ((e_num * PRIME_EDGE) ^
+ (f_num * PRIME_FACE) *
+ (l_num * PRIME_LOOP));
+
+#undef PRIME_EDGE
+#undef PRIME_FACE
+#undef PRIME_LOOP
+}
+
+static UUIDFashMatch *bm_vert_fasthash_create(
+ BMesh *bm, const unsigned int depth)
+{
+ UUIDFashMatch *id_prev;
+ UUIDFashMatch *id_curr;
+ unsigned int pass, i;
+ BMVert *v;
+ BMIter iter;
+
+ id_prev = MEM_mallocN(sizeof(*id_prev) * (unsigned int)bm->totvert, __func__);
+ id_curr = MEM_mallocN(sizeof(*id_curr) * (unsigned int)bm->totvert, __func__);
+
+ BM_ITER_MESH_INDEX (v, &iter, bm, BM_VERTS_OF_MESH, i) {
+ id_prev[i] = bm_vert_fasthash_single(v);
+ }
+
+ for (pass = 0; pass < depth; pass++) {
+ BMEdge *e;
+
+ memcpy(id_curr, id_prev, sizeof(*id_prev) * (unsigned int)bm->totvert);
+
+ BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
+ if (BM_edge_is_wire(e) == false) {
+ const int i1 = BM_elem_index_get(e->v1);
+ const int i2 = BM_elem_index_get(e->v2);
+
+ id_curr[i1] += id_prev[i2];
+ id_curr[i2] += id_prev[i1];
+ }
+ }
+ }
+ MEM_freeN(id_prev);
+
+ return id_curr;
+}
+
+static void bm_vert_fasthash_edge_order(
+ UUIDFashMatch *fm, const BMEdge *e, UUIDFashMatch e_fm[2])
+{
+ e_fm[0] = fm[BM_elem_index_get(e->v1)];
+ e_fm[1] = fm[BM_elem_index_get(e->v2)];
+
+ if (e_fm[0] > e_fm[1]) {
+ SWAP(UUIDFashMatch, e_fm[0], e_fm[1]);
+ }
+}
+
+static bool bm_vert_fasthash_edge_is_match(
+ UUIDFashMatch *fm, const BMEdge *e_a, const BMEdge *e_b)
+{
+ UUIDFashMatch e_a_fm[2];
+ UUIDFashMatch e_b_fm[2];
+
+ bm_vert_fasthash_edge_order(fm, e_a, e_a_fm);
+ bm_vert_fasthash_edge_order(fm, e_b, e_b_fm);
+
+ return ((e_a_fm[0] == e_b_fm[0]) &&
+ (e_a_fm[1] == e_b_fm[1]));
+}
+
+static void bm_vert_fasthash_destroy(
+ UUIDFashMatch *fm)
+{
+ MEM_freeN(fm);
+}
+
+/** \} */
+
+#endif /* USE_PIVOT_FASTMATCH */
+
+
+/**
+ * Take a face-region and return a list of matching face-regions.
+ *
+ * \param faces_region A single, contiguous face-region.
+ * \return A list of matching null-terminated face-region arrays.
+ */
+int BM_mesh_region_match(
+ BMesh *bm,
+ BMFace **faces_region, unsigned int faces_region_len,
+ ListBase *r_face_regions)
+{
+ BMEdge *e_src;
+ BMEdge *e_dst;
+ BMIter iter;
+ unsigned int verts_region_len = 0;
+ unsigned int faces_result_len = 0;
+ /* number of steps from e_src to a boundary vert */
+ unsigned int depth;
+
+
+#ifdef USE_WALKER_REUSE
+ UUIDWalk w_src, w_dst;
+#endif
+
+#ifdef USE_PIVOT_FASTMATCH
+ UUIDFashMatch *fm;
+#endif
+
+#ifdef DEBUG_PRINT
+ int search_num = 0;
+#endif
+
+#ifdef DEBUG_TIME
+ TIMEIT_START(region_match);
+#endif
+
+ /* initialize visited verts */
+ BM_mesh_elem_hflag_disable_all(bm, BM_VERT | BM_EDGE | BM_FACE, BM_ELEM_TAG, false);
+ bm_face_array_visit(faces_region, faces_region_len, &verts_region_len, true);
+
+ /* needed for 'ghashutil_bmelem_indexhash' */
+ BM_mesh_elem_index_ensure(bm, BM_VERT | BM_FACE);
+
+#ifdef USE_PIVOT_SEARCH
+ e_src = bm_face_region_pivot_edge_find(
+ faces_region, faces_region_len,
+ verts_region_len, &depth);
+
+ /* see which edge is added */
+#if 0
+ BM_select_history_clear(bm);
+ if (e_src) {
+ BM_select_history_store(bm, e_src);
+ }
+#endif
+
+#else
+ /* quick test only! */
+ e_src = BM_mesh_active_edge_get(bm);
+#endif
+
+ if (e_src == NULL) {
+#ifdef DEBUG_PRINT
+ printf("Couldn't find 'e_src'");
+#endif
+ return 0;
+ }
+
+ BLI_listbase_clear(r_face_regions);
+
+#ifdef USE_PIVOT_FASTMATCH
+ if (depth > 0) {
+ fm = bm_vert_fasthash_create(bm, depth);
+ }
+ else {
+ fm = NULL;
+ }
+#endif
+
+#ifdef USE_WALKER_REUSE
+ bm_uuidwalk_init(&w_src, faces_region_len, verts_region_len);
+ bm_uuidwalk_init(&w_dst, faces_region_len, verts_region_len);
+#endif
+
+ BM_ITER_MESH (e_dst, &iter, bm, BM_EDGES_OF_MESH) {
+ BMFace **faces_result;
+ unsigned int faces_result_len_out;
+
+ if (BM_elem_flag_test(e_dst, BM_ELEM_TAG) || BM_edge_is_wire(e_dst)) {
+ continue;
+ }
+
+#ifdef USE_PIVOT_FASTMATCH
+ if (fm && !bm_vert_fasthash_edge_is_match(fm, e_src, e_dst)) {
+ continue;
+ }
+#endif
+
+#ifdef DEBUG_PRINT
+ search_num += 1;
+#endif
+
+ faces_result = bm_mesh_region_match_pair(
+#ifdef USE_WALKER_REUSE
+ &w_src, &w_dst,
+#endif
+ e_src, e_dst,
+ faces_region_len,
+ verts_region_len,
+ &faces_result_len_out);
+
+ /* tag verts as visited */
+ if (faces_result) {
+ LinkData *link;
+
+ bm_face_array_visit(faces_result, faces_result_len_out, NULL, false);
+
+ link = BLI_genericNodeN(faces_result);
+ BLI_addtail(r_face_regions, link);
+ faces_result_len += 1;
+ }
+ }
+
+#ifdef USE_WALKER_REUSE
+ bm_uuidwalk_free(&w_src);
+ bm_uuidwalk_free(&w_dst);
+#else
+ (void)bm_uuidwalk_clear;
+#endif
+
+#ifdef USE_PIVOT_FASTMATCH
+ if (fm) {
+ bm_vert_fasthash_destroy(fm);
+ }
+#endif
+
+#ifdef DEBUG_PRINT
+ printf("%s: search: %d, found %d\n", __func__, search_num, faces_result_len);
+#endif
+
+#ifdef DEBUG_TIME
+ TIMEIT_END(region_match);
+#endif
+
+ return (int)faces_result_len;
+}
diff --git a/source/blender/bmesh/tools/bmesh_region_match.h b/source/blender/bmesh/tools/bmesh_region_match.h
new file mode 100644
index 00000000000..edf8369b070
--- /dev/null
+++ b/source/blender/bmesh/tools/bmesh_region_match.h
@@ -0,0 +1,33 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __BMESH_REGION_MATCH_H__
+#define __BMESH_REGION_MATCH_H__
+
+/** \file blender/bmesh/tools/bmesh_region_match.h
+ * \ingroup bmesh
+ */
+
+int BM_mesh_region_match(
+ BMesh *bm,
+ BMFace **faces_region, unsigned int faces_region_len,
+ ListBase *r_face_regions);
+
+#endif /* __BMESH_REGION_MATCH_H__ */
diff --git a/source/blender/bmesh/tools/bmesh_triangulate.c b/source/blender/bmesh/tools/bmesh_triangulate.c
index 446c03a543f..6f2aaf28179 100644
--- a/source/blender/bmesh/tools/bmesh_triangulate.c
+++ b/source/blender/bmesh/tools/bmesh_triangulate.c
@@ -27,13 +27,19 @@
*
*/
+#include "DNA_modifier_types.h" /* for MOD_TRIANGULATE_NGON_BEAUTY only */
+
#include "MEM_guardedalloc.h"
#include "BLI_utildefines.h"
#include "BLI_alloca.h"
#include "BLI_memarena.h"
-#include "BLI_listbase.h"
-#include "BLI_scanfill.h"
+#include "BLI_heap.h"
+#include "BLI_edgehash.h"
+
+/* only for defines */
+#include "BLI_polyfill2d.h"
+#include "BLI_polyfill2d_beautify.h"
#include "bmesh.h"
@@ -42,16 +48,27 @@
/**
* a version of #BM_face_triangulate that maps to #BMOpSlot
*/
-static void bm_face_triangulate_mapping(BMesh *bm, BMFace *face, MemArena *sf_arena,
- const int quad_method, const int ngon_method,
- const bool use_tag,
- BMOperator *op, BMOpSlot *slot_facemap_out)
+static void bm_face_triangulate_mapping(
+ BMesh *bm, BMFace *face,
+ const int quad_method, const int ngon_method,
+ const bool use_tag,
+ BMOperator *op, BMOpSlot *slot_facemap_out,
+
+ MemArena *pf_arena,
+ /* use for MOD_TRIANGULATE_NGON_BEAUTY only! */
+ struct Heap *pf_heap, struct EdgeHash *pf_ehash)
{
int faces_array_tot = face->len - 3;
BMFace **faces_array = BLI_array_alloca(faces_array, faces_array_tot);
BLI_assert(face->len > 3);
- BM_face_triangulate(bm, face, faces_array, &faces_array_tot, sf_arena, quad_method, ngon_method, use_tag);
+ BM_face_triangulate(
+ bm, face,
+ faces_array, &faces_array_tot,
+ NULL, NULL,
+ quad_method, ngon_method, use_tag,
+ pf_arena,
+ pf_heap, pf_ehash);
if (faces_array_tot) {
int i;
@@ -63,22 +80,39 @@ static void bm_face_triangulate_mapping(BMesh *bm, BMFace *face, MemArena *sf_ar
}
-void BM_mesh_triangulate(BMesh *bm, const int quad_method, const int ngon_method, const bool tag_only,
- BMOperator *op, BMOpSlot *slot_facemap_out)
+void BM_mesh_triangulate(
+ BMesh *bm, const int quad_method, const int ngon_method, const bool tag_only,
+ BMOperator *op, BMOpSlot *slot_facemap_out)
{
BMIter iter;
BMFace *face;
- MemArena *sf_arena;
+ MemArena *pf_arena;
+ Heap *pf_heap;
+ EdgeHash *pf_ehash;
- sf_arena = BLI_memarena_new(BLI_SCANFILL_ARENA_SIZE, __func__);
+ pf_arena = BLI_memarena_new(BLI_POLYFILL_ARENA_SIZE, __func__);
+
+ if (ngon_method == MOD_TRIANGULATE_NGON_BEAUTY) {
+ pf_heap = BLI_heap_new_ex(BLI_POLYFILL_ALLOC_NGON_RESERVE);
+ pf_ehash = BLI_edgehash_new_ex(__func__, BLI_POLYFILL_ALLOC_NGON_RESERVE);
+ }
+ else {
+ pf_heap = NULL;
+ pf_ehash = NULL;
+ }
if (slot_facemap_out) {
/* same as below but call: bm_face_triangulate_mapping() */
BM_ITER_MESH (face, &iter, bm, BM_FACES_OF_MESH) {
if (face->len > 3) {
if (tag_only == false || BM_elem_flag_test(face, BM_ELEM_TAG)) {
- bm_face_triangulate_mapping(bm, face, sf_arena, quad_method, ngon_method, tag_only,
- op, slot_facemap_out);
+ bm_face_triangulate_mapping(
+ bm, face, quad_method,
+ ngon_method, tag_only,
+ op, slot_facemap_out,
+
+ pf_arena,
+ pf_heap, pf_ehash);
}
}
}
@@ -87,11 +121,22 @@ void BM_mesh_triangulate(BMesh *bm, const int quad_method, const int ngon_method
BM_ITER_MESH (face, &iter, bm, BM_FACES_OF_MESH) {
if (face->len > 3) {
if (tag_only == false || BM_elem_flag_test(face, BM_ELEM_TAG)) {
- BM_face_triangulate(bm, face, NULL, NULL, sf_arena, quad_method, ngon_method, tag_only);
+ BM_face_triangulate(
+ bm, face,
+ NULL, NULL,
+ NULL, NULL,
+ quad_method, ngon_method, tag_only,
+ pf_arena,
+ pf_heap, pf_ehash);
}
}
}
}
- BLI_memarena_free(sf_arena);
+ BLI_memarena_free(pf_arena);
+
+ if (ngon_method == MOD_TRIANGULATE_NGON_BEAUTY) {
+ BLI_heap_free(pf_heap, NULL);
+ BLI_edgehash_free(pf_ehash, NULL);
+ }
}
diff --git a/source/blender/bmesh/tools/bmesh_triangulate.h b/source/blender/bmesh/tools/bmesh_triangulate.h
index 550109ffef9..c6a5e04dfb2 100644
--- a/source/blender/bmesh/tools/bmesh_triangulate.h
+++ b/source/blender/bmesh/tools/bmesh_triangulate.h
@@ -30,7 +30,8 @@
#ifndef __BMESH_TRIANGULATE_H__
#define __BMESH_TRIANGULATE_H__
-void BM_mesh_triangulate(BMesh *bm, const int quad_method, const int ngon_method, const bool tag_only,
- BMOperator *op, BMOpSlot *slot_facemap_out);
+void BM_mesh_triangulate(
+ BMesh *bm, const int quad_method, const int ngon_method, const bool tag_only,
+ BMOperator *op, BMOpSlot *slot_facemap_out);
#endif /* __BMESH_TRIANGULATE_H__ */
diff --git a/source/blender/bmesh/tools/bmesh_wireframe.c b/source/blender/bmesh/tools/bmesh_wireframe.c
index 79fea3e5da1..e79ef52797b 100644
--- a/source/blender/bmesh/tools/bmesh_wireframe.c
+++ b/source/blender/bmesh/tools/bmesh_wireframe.c
@@ -55,8 +55,9 @@ static BMLoop *bm_edge_tag_faceloop(BMEdge *e)
return NULL;
}
-static void bm_vert_boundary_tangent(BMVert *v, float r_no[3], float r_no_face[3],
- BMVert **r_va_other, BMVert **r_vb_other)
+static void bm_vert_boundary_tangent(
+ BMVert *v, float r_no[3], float r_no_face[3],
+ BMVert **r_va_other, BMVert **r_vb_other)
{
BMIter iter;
BMEdge *e_iter;
@@ -159,7 +160,7 @@ static bool bm_loop_is_radial_boundary(BMLoop *l_first)
}
/**
- * \param def_nr -1 for no vertex groups.
+ * \param defgrp_index: Vertex group index, -1 for no vertex groups.
*
* \note All edge tags must be cleared.
* \note Behavior matches MOD_solidify.c
diff --git a/source/blender/collada/AnimationExporter.cpp b/source/blender/collada/AnimationExporter.cpp
index f2c057d32d8..7bea0b70c95 100644
--- a/source/blender/collada/AnimationExporter.cpp
+++ b/source/blender/collada/AnimationExporter.cpp
@@ -24,8 +24,6 @@
#include "AnimationExporter.h"
#include "MaterialExporter.h"
-Global G;
-
template<class Functor>
void forEachObjectInExportSet(Scene *sce, Functor &f, LinkNode *export_set)
{
@@ -76,9 +74,9 @@ void AnimationExporter::operator()(Object *ob)
else
transformName = extract_transform_name(fcu->rna_path);
- if ((!strcmp(transformName, "location") || !strcmp(transformName, "scale")) ||
- (!strcmp(transformName, "rotation_euler") && ob->rotmode == ROT_MODE_EUL) ||
- (!strcmp(transformName, "rotation_quaternion")))
+ if ((STREQ(transformName, "location") || STREQ(transformName, "scale")) ||
+ (STREQ(transformName, "rotation_euler") && ob->rotmode == ROT_MODE_EUL) ||
+ (STREQ(transformName, "rotation_quaternion")))
{
dae_animation(ob, fcu, transformName, false);
}
@@ -98,8 +96,8 @@ void AnimationExporter::operator()(Object *ob)
while (fcu) {
transformName = extract_transform_name(fcu->rna_path);
- if ((!strcmp(transformName, "color")) || (!strcmp(transformName, "spot_size")) ||
- (!strcmp(transformName, "spot_blend")) || (!strcmp(transformName, "distance")))
+ if ((STREQ(transformName, "color")) || (STREQ(transformName, "spot_size")) ||
+ (STREQ(transformName, "spot_blend")) || (STREQ(transformName, "distance")))
{
dae_animation(ob, fcu, transformName, true);
}
@@ -113,10 +111,10 @@ void AnimationExporter::operator()(Object *ob)
while (fcu) {
transformName = extract_transform_name(fcu->rna_path);
- if ((!strcmp(transformName, "lens")) ||
- (!strcmp(transformName, "ortho_scale")) ||
- (!strcmp(transformName, "clip_end")) ||
- (!strcmp(transformName, "clip_start")))
+ if ((STREQ(transformName, "lens")) ||
+ (STREQ(transformName, "ortho_scale")) ||
+ (STREQ(transformName, "clip_end")) ||
+ (STREQ(transformName, "clip_start")))
{
dae_animation(ob, fcu, transformName, true);
}
@@ -134,9 +132,9 @@ void AnimationExporter::operator()(Object *ob)
while (fcu) {
transformName = extract_transform_name(fcu->rna_path);
- if ((!strcmp(transformName, "specular_hardness")) || (!strcmp(transformName, "specular_color")) ||
- (!strcmp(transformName, "diffuse_color")) || (!strcmp(transformName, "alpha")) ||
- (!strcmp(transformName, "ior")))
+ if ((STREQ(transformName, "specular_hardness")) || (STREQ(transformName, "specular_color")) ||
+ (STREQ(transformName, "diffuse_color")) || (STREQ(transformName, "alpha")) ||
+ (STREQ(transformName, "ior")))
{
dae_animation(ob, fcu, transformName, true, ma);
}
@@ -187,7 +185,7 @@ void AnimationExporter::make_anim_frames_from_targets(Object *ob, std::vector<fl
for (con = (bConstraint *)conlist->first; con; con = con->next) {
ListBase targets = {NULL, NULL};
- bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
+ const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
if (!validateConstraints(con)) continue;
@@ -225,7 +223,7 @@ float *AnimationExporter::get_eul_source_for_quat(Object *ob)
while (fcu) {
char *transformName = extract_transform_name(fcu->rna_path);
- if (!strcmp(transformName, "rotation_quaternion") ) {
+ if (STREQ(transformName, "rotation_quaternion") ) {
for (int i = 0; i < fcu->totvert; i++) {
*(quat + (i * 4) + fcu->array_index) = fcu->bezt[i].vec[1][1];
}
@@ -278,17 +276,17 @@ void AnimationExporter::dae_animation(Object *ob, FCurve *fcu, char *transformNa
bool has_tangents = false;
bool quatRotation = false;
- if (!strcmp(transformName, "rotation_quaternion") ) {
+ if (STREQ(transformName, "rotation_quaternion") ) {
fprintf(stderr, "quaternion rotation curves are not supported. rotation curve will not be exported\n");
quatRotation = true;
return;
}
//axis names for colors
- else if (!strcmp(transformName, "color") ||
- !strcmp(transformName, "specular_color") ||
- !strcmp(transformName, "diffuse_color") ||
- !strcmp(transformName, "alpha"))
+ else if (STREQ(transformName, "color") ||
+ STREQ(transformName, "specular_color") ||
+ STREQ(transformName, "diffuse_color") ||
+ STREQ(transformName, "alpha"))
{
const char *axis_names[] = {"R", "G", "B"};
if (fcu->array_index < 3)
@@ -296,10 +294,10 @@ void AnimationExporter::dae_animation(Object *ob, FCurve *fcu, char *transformNa
}
//axis names for transforms
- else if (!strcmp(transformName, "location") ||
- !strcmp(transformName, "scale") ||
- !strcmp(transformName, "rotation_euler") ||
- !strcmp(transformName, "rotation_quaternion"))
+ else if (STREQ(transformName, "location") ||
+ STREQ(transformName, "scale") ||
+ STREQ(transformName, "rotation_euler") ||
+ STREQ(transformName, "rotation_quaternion"))
{
const char *axis_names[] = {"X", "Y", "Z"};
if (fcu->array_index < 3)
@@ -357,7 +355,7 @@ void AnimationExporter::dae_animation(Object *ob, FCurve *fcu, char *transformNa
MEM_freeN(eul);
MEM_freeN(eul_axis);
}
- else if (!strcmp(transformName, "lens") && (ob->type == OB_CAMERA)) {
+ else if (STREQ(transformName, "lens") && (ob->type == OB_CAMERA)) {
output_id = create_lens_source_from_fcurve((Camera *) ob->data, COLLADASW::InputSemantic::OUTPUT, fcu, anim_id);
}
else {
@@ -763,7 +761,7 @@ std::string AnimationExporter::create_source_from_fcurve(COLLADASW::InputSemanti
{
std::string source_id = anim_id + get_semantic_suffix(semantic);
- //bool is_angle = !strcmp(fcu->rna_path, "rotation");
+ //bool is_angle = STREQ(fcu->rna_path, "rotation");
bool is_angle = false;
if (strstr(fcu->rna_path, "rotation") || strstr(fcu->rna_path,"spot_size")) is_angle = true;
@@ -1103,13 +1101,13 @@ std::string AnimationExporter::get_light_param_sid(char *rna_path, int tm_type,
if (rna_path) {
char *name = extract_transform_name(rna_path);
- if (!strcmp(name, "color"))
+ if (STREQ(name, "color"))
tm_type = 1;
- else if (!strcmp(name, "spot_size"))
+ else if (STREQ(name, "spot_size"))
tm_type = 2;
- else if (!strcmp(name, "spot_blend"))
+ else if (STREQ(name, "spot_blend"))
tm_type = 3;
- else if (!strcmp(name, "distance"))
+ else if (STREQ(name, "distance"))
tm_type = 4;
else
tm_type = -1;
@@ -1151,13 +1149,13 @@ std::string AnimationExporter::get_camera_param_sid(char *rna_path, int tm_type,
if (rna_path) {
char *name = extract_transform_name(rna_path);
- if (!strcmp(name, "lens"))
+ if (STREQ(name, "lens"))
tm_type = 0;
- else if (!strcmp(name, "ortho_scale"))
+ else if (STREQ(name, "ortho_scale"))
tm_type = 1;
- else if (!strcmp(name, "clip_end"))
+ else if (STREQ(name, "clip_end"))
tm_type = 2;
- else if (!strcmp(name, "clip_start"))
+ else if (STREQ(name, "clip_start"))
tm_type = 3;
else
@@ -1203,23 +1201,23 @@ std::string AnimationExporter::get_transform_sid(char *rna_path, int tm_type, co
if (rna_path) {
char *name = extract_transform_name(rna_path);
- if (!strcmp(name, "rotation_euler"))
+ if (STREQ(name, "rotation_euler"))
tm_type = 0;
- else if (!strcmp(name, "rotation_quaternion"))
+ else if (STREQ(name, "rotation_quaternion"))
tm_type = 1;
- else if (!strcmp(name, "scale"))
+ else if (STREQ(name, "scale"))
tm_type = 2;
- else if (!strcmp(name, "location"))
+ else if (STREQ(name, "location"))
tm_type = 3;
- else if (!strcmp(name, "specular_hardness"))
+ else if (STREQ(name, "specular_hardness"))
tm_type = 4;
- else if (!strcmp(name, "specular_color"))
+ else if (STREQ(name, "specular_color"))
tm_type = 5;
- else if (!strcmp(name, "diffuse_color"))
+ else if (STREQ(name, "diffuse_color"))
tm_type = 6;
- else if (!strcmp(name, "alpha"))
+ else if (STREQ(name, "alpha"))
tm_type = 7;
- else if (!strcmp(name, "ior"))
+ else if (STREQ(name, "ior"))
tm_type = 8;
else
@@ -1311,7 +1309,7 @@ void AnimationExporter::enable_fcurves(bAction *act, char *bone_name)
for (fcu = (FCurve *)act->curves.first; fcu; fcu = fcu->next) {
if (bone_name) {
- if (!strncmp(fcu->rna_path, prefix, strlen(prefix)))
+ if (STREQLEN(fcu->rna_path, prefix, strlen(prefix)))
fcu->flag &= ~FCURVE_DISABLED;
else
fcu->flag |= FCURVE_DISABLED;
@@ -1378,11 +1376,11 @@ void AnimationExporter::find_frames(Object *ob, std::vector<float> &fra, const c
FCurve *fcu = (FCurve *)ob->adt->action->curves.first;
for (; fcu; fcu = fcu->next) {
- if (prefix && strncmp(prefix, fcu->rna_path, strlen(prefix)))
+ if (prefix && !STREQLEN(prefix, fcu->rna_path, strlen(prefix)))
continue;
char *name = extract_transform_name(fcu->rna_path);
- if (!strcmp(name, tm_name)) {
+ if (STREQ(name, tm_name)) {
for (unsigned int i = 0; i < fcu->totvert; i++) {
float f = fcu->bezt[i].vec[1][0];
if (std::find(fra.begin(), fra.end(), f) == fra.end())
@@ -1528,7 +1526,7 @@ void AnimationExporter::sample_animation(float *v, std::vector<float> &frames, i
bool AnimationExporter::validateConstraints(bConstraint *con)
{
bool valid = true;
- bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
+ const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
/* these we can skip completely (invalid constraints...) */
if (cti == NULL) valid = false;
if (con->flag & (CONSTRAINT_DISABLE | CONSTRAINT_OFF)) valid = false;
@@ -1547,7 +1545,7 @@ void AnimationExporter::calc_ob_mat_at_time(Object *ob, float ctime , float mat[
for (con = (bConstraint *)conlist->first; con; con = con->next) {
ListBase targets = {NULL, NULL};
- bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
+ const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
if (cti && cti->get_constraint_targets) {
bConstraintTarget *ct;
diff --git a/source/blender/collada/AnimationExporter.h b/source/blender/collada/AnimationExporter.h
index 5e7338aef61..4736361ad13 100644
--- a/source/blender/collada/AnimationExporter.h
+++ b/source/blender/collada/AnimationExporter.h
@@ -51,7 +51,6 @@ extern "C"
#include "BKE_object.h"
#include "BKE_constraint.h"
#include "BIK_api.h"
-#include "BKE_global.h"
#include "ED_object.h"
}
@@ -104,7 +103,7 @@ protected:
const ExportSettings *export_settings;
void dae_animation(Object *ob, FCurve *fcu, char *transformName, bool is_param, Material *ma = NULL);
-
+
void export_object_constraint_animation(Object *ob);
void export_morph_animation(Object *ob);
@@ -155,7 +154,7 @@ protected:
std::string create_xyz_source(float *v, int tot, const std::string& anim_id);
std::string create_4x4_source(std::vector<float> &frames, Object * ob_arm, Bone *bone, const std::string& anim_id);
-
+
std::string create_interpolation_source(FCurve *fcu, const std::string& anim_id, const char *axis_name, bool *has_tangents);
std::string fake_interpolation_source(int tot, const std::string& anim_id, const char *axis_name);
diff --git a/source/blender/collada/AnimationImporter.cpp b/source/blender/collada/AnimationImporter.cpp
index 6e2d337a32e..1bcf51f9d1f 100644
--- a/source/blender/collada/AnimationImporter.cpp
+++ b/source/blender/collada/AnimationImporter.cpp
@@ -38,7 +38,7 @@
#include "BLI_path_util.h"
#include "BLI_string.h"
-#include "BLF_translation.h"
+#include "BLT_translation.h"
#include "BKE_action.h"
#include "BKE_armature.h"
@@ -153,15 +153,13 @@ void AnimationImporter::animation_to_fcurves(COLLADAFW::AnimationCurve *curve)
calchandles_fcurve(fcu);
fcurves.push_back(fcu);
+ unused_curves.push_back(fcu);
}
}
break;
default:
fprintf(stderr, "Output dimension of %d is not yet supported (animation id = %s)\n", (int)dim, curve->getOriginalId().c_str());
}
-
- for (std::vector<FCurve *>::iterator it = fcurves.begin(); it != fcurves.end(); it++)
- unused_curves.push_back(*it);
}
@@ -175,6 +173,11 @@ void AnimationImporter::fcurve_deg_to_rad(FCurve *cu)
}
}
+void AnimationImporter::fcurve_is_used(FCurve *fcu)
+{
+ unused_curves.erase(std::remove(unused_curves.begin(), unused_curves.end(), fcu), unused_curves.end());
+}
+
void AnimationImporter::add_fcurves_to_object(Object *ob, std::vector<FCurve *>& curves, char *rna_path, int array_index, Animation *animated)
{
@@ -219,12 +222,13 @@ void AnimationImporter::add_fcurves_to_object(Object *ob, std::vector<FCurve *>&
BLI_strncpy(grp->name, bone_name, sizeof(grp->name));
BLI_addtail(&act->groups, grp);
- BLI_uniquename(&act->groups, grp, CTX_DATA_(BLF_I18NCONTEXT_ID_ACTION, "Group"), '.',
+ BLI_uniquename(&act->groups, grp, CTX_DATA_(BLT_I18NCONTEXT_ID_ACTION, "Group"), '.',
offsetof(bActionGroup, name), 64);
}
/* add F-Curve to group */
action_groups_add_channel(act, grp, fcu);
+ fcurve_is_used(fcu);
}
#if 0
@@ -235,10 +239,8 @@ void AnimationImporter::add_fcurves_to_object(Object *ob, std::vector<FCurve *>&
}
else {
BLI_addtail(&act->curves, fcu);
+ fcurve_is_used(fcu);
}
-
- // curve is used, so remove it from unused_curves
- unused_curves.erase(std::remove(unused_curves.begin(), unused_curves.end(), fcu), unused_curves.end());
}
}
@@ -438,7 +440,7 @@ void AnimationImporter::modify_fcurve(std::vector<FCurve *> *curves, const char
if (array_index == -1) fcu->array_index = i;
else fcu->array_index = array_index;
- unused_curves.erase(std::remove(unused_curves.begin(), unused_curves.end(), fcu), unused_curves.end());
+ fcurve_is_used(fcu);
}
}
@@ -448,7 +450,7 @@ void AnimationImporter::unused_fcurve(std::vector<FCurve *> *curves)
std::vector<FCurve *>::iterator it;
for (it = curves->begin(); it != curves->end(); it++) {
FCurve *fcu = *it;
- unused_curves.erase(std::remove(unused_curves.begin(), unused_curves.end(), fcu), unused_curves.end());
+ fcurve_is_used(fcu);
}
}
@@ -621,6 +623,7 @@ void AnimationImporter:: Assign_color_animations(const COLLADAFW::UniqueId& list
for (iter = animcurves.begin(); iter != animcurves.end(); iter++) {
FCurve *fcu = *iter;
BLI_addtail(AnimCurves, fcu);
+ fcurve_is_used(fcu);
}
}
@@ -649,7 +652,7 @@ void AnimationImporter:: Assign_float_animations(const COLLADAFW::UniqueId& list
for (iter = animcurves.begin(); iter != animcurves.end(); iter++) {
FCurve *fcu = *iter;
/* All anim_types whose values are to be converted from Degree to Radians can be ORed here */
- if (strcmp("spot_size", anim_type)==0) {
+ if (STREQ("spot_size", anim_type)) {
/* NOTE: Do NOT convert if imported file was made by blender <= 2.69.10
* Reason: old blender versions stored spot_size in radians (was a bug)
*/
@@ -660,6 +663,7 @@ void AnimationImporter:: Assign_float_animations(const COLLADAFW::UniqueId& list
/** XXX What About animtype "rotation" ? */
BLI_addtail(AnimCurves, fcu);
+ fcurve_is_used(fcu);
}
}
}
@@ -705,6 +709,7 @@ void AnimationImporter::Assign_lens_animations(const COLLADAFW::UniqueId& listid
}
BLI_addtail(AnimCurves, fcu);
+ fcurve_is_used(fcu);
}
}
}
@@ -840,8 +845,10 @@ void AnimationImporter::apply_matrix_curves(Object *ob, std::vector<FCurve *>& a
add_bone_fcurve(ob, node, newcu[i]);
else
BLI_addtail(curves, newcu[i]);
+ // fcurve_is_used(newcu[i]); // never added to unused
}
+
if (is_joint) {
bPoseChannel *chan = BKE_pose_channel_find_name(ob->pose, bone_name);
chan->rotmode = ROT_MODE_QUAT;
@@ -891,8 +898,6 @@ void AnimationImporter::translate_Animations(COLLADAFW::Node *node,
std::multimap<COLLADAFW::UniqueId, Object *>& object_map,
std::map<COLLADAFW::UniqueId, const COLLADAFW::Object *> FW_object_map)
{
- AnimationImporter::AnimMix *animType = get_animation_type(node, FW_object_map);
-
bool is_joint = node->getType() == COLLADAFW::Node::JOINT;
COLLADAFW::UniqueId uid = node->getUniqueId();
COLLADAFW::Node *root = root_map.find(uid) == root_map.end() ? node : root_map[uid];
@@ -908,6 +913,8 @@ void AnimationImporter::translate_Animations(COLLADAFW::Node *node,
return;
}
+
+ AnimationImporter::AnimMix *animType = get_animation_type(node, FW_object_map);
bAction *act;
if ( (animType->transform) != 0) {
@@ -966,6 +973,7 @@ void AnimationImporter::translate_Animations(COLLADAFW::Node *node,
FCurve *fcu = *iter;
BLI_addtail(AnimCurves, fcu);
+ fcurve_is_used(fcu);
}
}
@@ -1108,6 +1116,8 @@ void AnimationImporter::translate_Animations(COLLADAFW::Node *node,
}
}
}
+
+ delete animType;
}
void AnimationImporter::add_bone_animation_sampled(Object *ob, std::vector<FCurve *>& animcurves, COLLADAFW::Node *root, COLLADAFW::Node *node, COLLADAFW::Transformation *tm)
@@ -1233,6 +1243,7 @@ void AnimationImporter::add_bone_animation_sampled(Object *ob, std::vector<FCurv
// add curves
for (int i = 0; i < totcu; i++) {
add_bone_fcurve(ob, node, newcu[i]);
+ // fcurve_is_used(newcu[i]); // never added to unused
}
bPoseChannel *chan = BKE_pose_channel_find_name(ob->pose, bone_name);
@@ -1832,7 +1843,7 @@ bool AnimationImporter::evaluate_animation(COLLADAFW::Transformation *tm, float
i++;
j = 0;
}
- unused_curves.erase(std::remove(unused_curves.begin(), unused_curves.end(), *it), unused_curves.end());
+ fcurve_is_used(*it);
}
COLLADAFW::Matrix tm(matrix);
@@ -1994,7 +2005,7 @@ void AnimationImporter::add_bone_fcurve(Object *ob, COLLADAFW::Node *node, FCurv
BLI_strncpy(grp->name, bone_name, sizeof(grp->name));
BLI_addtail(&act->groups, grp);
- BLI_uniquename(&act->groups, grp, CTX_DATA_(BLF_I18NCONTEXT_ID_ACTION, "Group"), '.',
+ BLI_uniquename(&act->groups, grp, CTX_DATA_(BLT_I18NCONTEXT_ID_ACTION, "Group"), '.',
offsetof(bActionGroup, name), 64);
}
diff --git a/source/blender/collada/AnimationImporter.h b/source/blender/collada/AnimationImporter.h
index 565fe183d02..15dee8ff5f4 100644
--- a/source/blender/collada/AnimationImporter.h
+++ b/source/blender/collada/AnimationImporter.h
@@ -85,7 +85,10 @@ private:
void fcurve_deg_to_rad(FCurve *cu);
+ void fcurve_is_used(FCurve *fcu);
+
void add_fcurves_to_object(Object *ob, std::vector<FCurve*>& curves, char *rna_path, int array_index, Animation *animated);
+
int typeFlag;
diff --git a/source/blender/collada/ArmatureExporter.cpp b/source/blender/collada/ArmatureExporter.cpp
index 2e92cd9c147..36ab85b9b5b 100644
--- a/source/blender/collada/ArmatureExporter.cpp
+++ b/source/blender/collada/ArmatureExporter.cpp
@@ -168,7 +168,7 @@ void ArmatureExporter::add_bone_node(Bone *bone, Object *ob_arm, Scene *sce,
node.setNodeSid(node_sid);
#if 0
- if (BLI_listbase_is_empty(&bone->childbase) || BLI_countlist(&(bone->childbase)) >= 2) {
+ if (BLI_listbase_is_empty(&bone->childbase) || BLI_listbase_count_ex(&bone->childbase, 2) == 2) {
add_blender_leaf_bone( bone, ob_arm, node);
}
else {
@@ -181,7 +181,7 @@ void ArmatureExporter::add_bone_node(Bone *bone, Object *ob_arm, Scene *sce,
std::list<Object *>::iterator i = child_objects.begin();
while (i != child_objects.end()) {
- if ((*i)->partype == PARBONE && (0 == strcmp((*i)->parsubstr, bone->name))) {
+ if ((*i)->partype == PARBONE && STREQ((*i)->parsubstr, bone->name)) {
float backup_parinv[4][4];
copy_m4_m4(backup_parinv, (*i)->parentinv);
diff --git a/source/blender/collada/ArmatureImporter.cpp b/source/blender/collada/ArmatureImporter.cpp
index e2c36df564a..6ddce75ec33 100644
--- a/source/blender/collada/ArmatureImporter.cpp
+++ b/source/blender/collada/ArmatureImporter.cpp
@@ -37,6 +37,7 @@
#include "BKE_object.h"
#include "BKE_armature.h"
#include "BLI_string.h"
+#include "BLI_listbase.h"
#include "ED_armature.h"
#include "ArmatureImporter.h"
@@ -49,7 +50,22 @@ static const char *bc_get_joint_name(T *node)
return id.size() ? id.c_str() : node->getOriginalId().c_str();
}
-ArmatureImporter::ArmatureImporter(UnitConverter *conv, MeshImporterBase *mesh, Scene *sce) :
+static EditBone *get_edit_bone(bArmature * armature, char *name) {
+ EditBone *eBone;
+
+ for (eBone = (EditBone *)armature->edbo->first; eBone; eBone = eBone->next) {
+ if (STREQ(name, eBone->name))
+ return eBone;
+ }
+
+ return NULL;
+
+}
+
+
+
+ArmatureImporter::ArmatureImporter(UnitConverter *conv, MeshImporterBase *mesh, Scene *sce, const ImportSettings *import_settings) :
+ import_settings(import_settings),
unit_converter(conv),
TransformReader(conv),
scene(sce),
@@ -57,6 +73,15 @@ ArmatureImporter::ArmatureImporter(UnitConverter *conv, MeshImporterBase *mesh,
mesh_importer(mesh) {
}
+void ArmatureImporter::clear_extended_boneset()
+{
+ for (std::map<std::string, BoneExtended *>::iterator it = extended_bones.begin(); it != extended_bones.end(); ++it) {
+ if (it->second != NULL)
+ delete it->second;
+ }
+ extended_bones.clear();
+}
+
ArmatureImporter::~ArmatureImporter()
{
// free skin controller data if we forget to do this earlier
@@ -64,6 +89,7 @@ ArmatureImporter::~ArmatureImporter()
for (it = skin_by_data_uid.begin(); it != skin_by_data_uid.end(); it++) {
it->second.free();
}
+ clear_extended_boneset();
}
#if 0
@@ -83,16 +109,17 @@ JointData *ArmatureImporter::get_joint_data(COLLADAFW::Node *node);
}
#endif
-void ArmatureImporter::create_bone(SkinInfo *skin, COLLADAFW::Node *node, EditBone *parent, int totchild,
+int ArmatureImporter::create_bone(SkinInfo *skin, COLLADAFW::Node *node, EditBone *parent, int totchild,
float parent_mat[4][4], bArmature *arm)
{
float mat[4][4];
float joint_inv_bind_mat[4][4];
+ int chain_length = 0;
//Checking if bone is already made.
std::vector<COLLADAFW::Node *>::iterator it;
it = std::find(finished_joints.begin(), finished_joints.end(), node);
- if (it != finished_joints.end()) return;
+ if (it != finished_joints.end()) return chain_length;
// JointData* jd = get_joint_data(node);
@@ -143,96 +170,156 @@ void ArmatureImporter::create_bone(SkinInfo *skin, COLLADAFW::Node *node, EditBo
// set tail, don't set it to head because 0-length bones are not allowed
add_v3_v3v3(bone->tail, bone->head, vec);
- // set parent tail
+ /* find smallest bone length in armature (used later for leaf bone length) */
if (parent) {
- // XXX increase this to prevent "very" small bones?
- const float epsilon = 0.000001f;
-
- // derive leaf bone length
+ /* guess reasonable leaf bone length */
float length = len_v3v3(parent->head, bone->head);
- if ((length < leaf_bone_length || totbone == 0) && length > epsilon) {
+ if ((length < leaf_bone_length || totbone == 0) && length > MINIMUM_BONE_LENGTH) {
leaf_bone_length = length;
}
-
- if (totchild == 1) {
- copy_v3_v3(parent->tail, bone->head);
-
- // not setting BONE_CONNECTED because this would lock child bone location with respect to parent
- bone->flag |= BONE_CONNECTED;
-
-
- // treat zero-sized bone like a leaf bone
- if (length <= epsilon) {
- add_leaf_bone(parent_mat, parent, node);
- }
- }
-
}
COLLADAFW::NodePointerArray& children = node->getChildNodes();
+
+ BoneExtended &be = add_bone_extended(bone, node);
+ be.set_leaf_bone(true);
+
for (unsigned int i = 0; i < children.getCount(); i++) {
- create_bone(skin, children[i], bone, children.getCount(), mat, arm);
+ int cl = create_bone(skin, children[i], bone, children.getCount(), mat, arm);
+ if (cl > chain_length)
+ chain_length = cl;
}
- // in second case it's not a leaf bone, but we handle it the same way
- if (!children.getCount() || children.getCount() > 1) {
- add_leaf_bone(mat, bone, node);
- }
bone->length = len_v3v3(bone->head, bone->tail);
joint_by_uid[node->getUniqueId()] = node;
finished_joints.push_back(node);
+
+ be.set_chain_length(chain_length + 1);
+
+ return chain_length + 1;
}
-void ArmatureImporter::add_leaf_bone(float mat[4][4], EditBone *bone, COLLADAFW::Node *node)
+/**
+ * Collada only knows Joints, hence bones at the end of a bone chain
+ * don't have a defined length. This function guesses reasonable
+ * tail locations for the affected bones (nodes which don't have any connected child)
+ * Hint: The extended_bones set gets populated in ArmatureImporter::create_bone
+**/
+void ArmatureImporter::fix_leaf_bones(bArmature *armature, Bone *bone)
{
- LeafBone leaf;
+ /* armature has no bones */
+ if (bone == NULL)
+ return;
- leaf.bone = bone;
- copy_m4_m4(leaf.mat, mat);
- BLI_strncpy(leaf.name, bone->name, sizeof(leaf.name));
-
- TagsMap::iterator etit;
- ExtraTags *et = 0;
- etit = uid_tags_map.find(node->getUniqueId().toAscii());
- if (etit != uid_tags_map.end()) {
- et = etit->second;
- //else return;
+ BoneExtended *be = extended_bones[bone->name];
+ if (be != NULL && be->is_leaf_bone() ) {
+ /* Collada only knows Joints, Here we guess a reasonable leaf bone length */
+ float leaf_length = (leaf_bone_length == FLT_MAX) ? 1.0 : leaf_bone_length;
+
+ EditBone *ebone = get_edit_bone(armature, bone->name);
+ float vec[3];
+
+ if (this->import_settings->fix_orientation) {
+ if (ebone->parent != NULL) {
+ EditBone *parent = ebone->parent;
+ sub_v3_v3v3(vec, ebone->head, parent->tail);
+ if (len_squared_v3(vec) < MINIMUM_BONE_LENGTH)
+ {
+ sub_v3_v3v3(vec, parent->tail, parent->head);
+ }
+ }
+ else {
+ vec[2] = 0.1f;
+ sub_v3_v3v3(vec, ebone->tail, ebone->head);
+ }
+ }
+ else {
+ sub_v3_v3v3(vec, ebone->tail, ebone->head);
+ }
- float x, y, z;
- et->setData("tip_x", &x);
- et->setData("tip_y", &y);
- et->setData("tip_z", &z);
- float vec[3] = {x, y, z};
- copy_v3_v3(leaf.bone->tail, leaf.bone->head);
- add_v3_v3v3(leaf.bone->tail, leaf.bone->head, vec);
- }
- else {
- leaf_bones.push_back(leaf);
+ normalize_v3_v3(vec, vec);
+ mul_v3_fl(vec, leaf_length);
+ add_v3_v3v3(ebone->tail, ebone->head, vec);
}
-}
-void ArmatureImporter::fix_leaf_bones( )
-{
- // Collada only knows Joints, Here we guess a reasonable
- // leaf bone length
- float leaf_length = (leaf_bone_length == FLT_MAX) ? 1.0:leaf_bone_length;
+ for (Bone *child = (Bone *)bone->childbase.first; child; child = child->next) {
+ fix_leaf_bones(armature, child);
+ }
- // just setting tail for leaf bones here
- std::vector<LeafBone>::iterator it;
- for (it = leaf_bones.begin(); it != leaf_bones.end(); it++) {
+}
- LeafBone& leaf = *it;
- // pointing up
- float vec[3] = {0.0f, 0.0f, 0.1f};
-
- sub_v3_v3v3(vec, leaf.bone->tail , leaf.bone->head);
- mul_v3_fl(vec, leaf_length);
- add_v3_v3v3(leaf.bone->tail, leaf.bone->head , vec);
+void ArmatureImporter::connect_bone_chains(bArmature *armature, Bone *parentbone, int clip)
+{
+ BoneExtended *dominant_child = NULL;
+ int maxlen = 0;
+ Bone *child = (Bone *)parentbone->childbase.first;
+ if (child && (import_settings->find_chains || child->next==NULL) )
+ {
+ for (; child; child = child->next) {
+ BoneExtended *be = extended_bones[child->name];
+ if (be != NULL) {
+ if (be->get_chain_length() <= clip) {
+ if (be->get_chain_length() > maxlen) {
+ dominant_child = be;
+ maxlen = be->get_chain_length();
+ }
+ else if (be->get_chain_length() == maxlen) {
+ dominant_child = NULL;
+ }
+ }
+ }
+ }
+ }
+ BoneExtended *pbe = extended_bones[parentbone->name];
+ if (dominant_child != NULL) {
+ /* Found a valid chain. Now connect current bone with that chain.*/
+ EditBone *pebone = get_edit_bone(armature, parentbone->name);
+ EditBone *cebone = get_edit_bone(armature, dominant_child->get_name());
+ if (pebone && !(cebone->flag & BONE_CONNECTED)) {
+
+ float vec[3];
+ sub_v3_v3v3(vec, cebone->head, pebone->head);
+
+ /*
+ * It is possible that the child's head is located on the parents head.
+ * When this happens, then moving the parent's tail to the child's head
+ * would result in a zero sized bone and Blender would silently remove the bone.
+ * So we move the tail only when the resulting bone has a minimum length:
+ */
+
+ if (len_squared_v3(vec) > MINIMUM_BONE_LENGTH)
+ {
+ pebone->tail[0] = cebone->head[0];
+ pebone->tail[1] = cebone->head[1];
+ pebone->tail[2] = cebone->head[2];
+
+ if (pbe && pbe->get_chain_length() >= this->import_settings->min_chain_length) {
+ cebone->flag |= BONE_CONNECTED;
+ printf("Connecting chain: parent %s --> %s (child)\n", pebone->name, cebone->name);
+ pbe->set_leaf_bone(false);
+ }
+ }
+ }
+ for (Bone *child = (Bone *)parentbone->childbase.first; child; child = child->next) {
+ ArmatureImporter::connect_bone_chains(armature, child, UNLIMITED_CHAIN_MAX);
+ }
+ }
+ else if (maxlen>1 && maxlen > this->import_settings->min_chain_length) {
+ /* Try again with smaller chain length */
+ ArmatureImporter::connect_bone_chains(armature, parentbone, maxlen - 1);
}
+ else {
+ /* can't connect this Bone. Proceed with children ... */
+ if (pbe) pbe->set_leaf_bone(true);
+ for (Bone *child = (Bone *)parentbone->childbase.first; child; child = child->next) {
+ ArmatureImporter::connect_bone_chains(armature, child, UNLIMITED_CHAIN_MAX);
+ }
+ }
+
}
#if 0
@@ -351,21 +438,26 @@ void ArmatureImporter::create_armature_bones( )
continue;
}
+ clear_extended_boneset();
+
ED_armature_to_edit(armature);
create_bone(NULL, *ri , NULL, (*ri)->getChildNodes().getCount(), NULL, armature);
- //leaf bone tails are derived from the matrix, so no need of this.
- fix_leaf_bones();
+ /* exit armature edit mode to populate the Armature object */
+ ED_armature_from_edit(armature);
+ ED_armature_edit_free(armature);
+
+ /* and step back to edit mode to fix the leaf nodes */
+ ED_armature_to_edit(armature);
+
+ connect_bone_chains(armature, (Bone *)armature->bonebase.first, UNLIMITED_CHAIN_MAX);
+ fix_leaf_bones(armature, (Bone *)armature->bonebase.first);
// exit armature edit mode
unskinned_armature_map[(*ri)->getUniqueId()] = ob_arm;
ED_armature_from_edit(armature);
-
- //This serves no purpose, as pose is automatically reset later, in BKE_where_is_bone()
- //set_pose(ob_arm, *ri, NULL, NULL);
-
ED_armature_edit_free(armature);
DAG_id_tag_update(&ob_arm->id, OB_RECALC_OB | OB_RECALC_DATA);
}
@@ -459,9 +551,11 @@ void ArmatureImporter::create_armature_bones(SkinInfo& skin)
}
// enter armature edit mode
- ED_armature_to_edit((bArmature *)ob_arm->data);
+ bArmature * armature = (bArmature *)ob_arm->data;
+ ED_armature_to_edit(armature);
+
+ clear_extended_boneset();
- leaf_bones.clear();
totbone = 0;
// bone_direction_row = 1; // TODO: don't default to Y but use asset and based on it decide on default row
leaf_bone_length = FLT_MAX;
@@ -480,20 +574,29 @@ void ArmatureImporter::create_armature_bones(SkinInfo& skin)
// since root_joints may contain joints for multiple controllers, we need to filter
if (skin.uses_joint_or_descendant(*ri)) {
- create_bone(&skin, *ri, NULL, (*ri)->getChildNodes().getCount(), NULL, (bArmature *)ob_arm->data);
+ create_bone(&skin, *ri, NULL, (*ri)->getChildNodes().getCount(), NULL, armature);
if (joint_parent_map.find((*ri)->getUniqueId()) != joint_parent_map.end() && !skin.get_parent())
skin.set_parent(joint_parent_map[(*ri)->getUniqueId()]);
}
}
- fix_leaf_bones();
+ /* exit armature edit mode to populate the Armature object */
+ ED_armature_from_edit(armature);
+ ED_armature_edit_free(armature);
+
+ /* and step back to edit mode to fix the leaf nodes */
+ ED_armature_to_edit(armature);
+ if (armature->bonebase.first) {
+ /* Do this only if Armature has bones */
+ connect_bone_chains(armature, (Bone *)armature->bonebase.first, UNLIMITED_CHAIN_MAX);
+ fix_leaf_bones(armature, (Bone *)armature->bonebase.first);
+ }
// exit armature edit mode
- ED_armature_from_edit((bArmature *)ob_arm->data);
- ED_armature_edit_free((bArmature *)ob_arm->data);
+ ED_armature_from_edit(armature);
+ ED_armature_edit_free(armature);
DAG_id_tag_update(&ob_arm->id, OB_RECALC_OB | OB_RECALC_DATA);
-
}
void ArmatureImporter::set_pose(Object *ob_arm, COLLADAFW::Node *root_node, const char *parentname, float parent_mat[4][4])
@@ -538,10 +641,11 @@ void ArmatureImporter::set_pose(Object *ob_arm, COLLADAFW::Node *root_node, con
}
-
-// root - if this joint is the top joint in hierarchy, if a joint
-// is a child of a node (not joint), root should be true since
-// this is where we build armature bones from
+/**
+ * root - if this joint is the top joint in hierarchy, if a joint
+ * is a child of a node (not joint), root should be true since
+ * this is where we build armature bones from
+ **/
void ArmatureImporter::add_root_joint(COLLADAFW::Node *node, Object *parent)
{
root_joints.push_back(node);
@@ -702,7 +806,7 @@ void ArmatureImporter::make_shape_keys()
//insert basis key
kb = BKE_keyblock_add_ctime(key, "Basis", false);
- BKE_key_convert_from_mesh(source_me, kb);
+ BKE_keyblock_convert_from_mesh(source_me, kb);
//insert other shape keys
for (int i = 0 ; i < morphTargetIds.getCount() ; i++ ) {
@@ -716,7 +820,7 @@ void ArmatureImporter::make_shape_keys()
std::string morph_name = *this->mesh_importer->get_geometry_name(me->id.name);
kb = BKE_keyblock_add_ctime(key, morph_name.c_str(), false);
- BKE_key_convert_from_mesh(me, kb);
+ BKE_keyblock_convert_from_mesh(me, kb);
//apply weights
weight = morphWeights.getFloatValues()->getData()[i];
@@ -785,3 +889,71 @@ bool ArmatureImporter::get_joint_bind_mat(float m[4][4], COLLADAFW::Node *joint)
return found;
}
+
+
+/**
+ * BoneExtended is a helper class needed for the Bone chain finder
+ * See ArmatureImporter::fix_leaf_bones()
+ * and ArmatureImporter::connect_bone_chains()
+ **/
+
+BoneExtended::BoneExtended(EditBone *aBone)
+{
+ this->set_name(aBone->name);
+ this->chain_length = 0;
+ this->is_leaf = false;
+}
+
+char *BoneExtended::get_name()
+{
+ return name;
+}
+
+void BoneExtended::set_name(char *aName)
+{
+ BLI_strncpy(name, aName, MAXBONENAME);
+}
+
+int BoneExtended::get_chain_length()
+{
+ return chain_length;
+}
+
+void BoneExtended::set_chain_length(const int aLength)
+{
+ chain_length = aLength;
+}
+
+
+void BoneExtended::set_leaf_bone(bool state)
+{
+ is_leaf = state;
+}
+
+bool BoneExtended::is_leaf_bone()
+{
+ return is_leaf;
+}
+
+BoneExtended &ArmatureImporter::add_bone_extended(EditBone *bone, COLLADAFW::Node *node)
+{
+
+ TagsMap::iterator etit;
+ ExtraTags *et = 0;
+ etit = uid_tags_map.find(node->getUniqueId().toAscii());
+ if (etit != uid_tags_map.end()) {
+ float x, y, z;
+
+ et = etit->second;
+ et->setData("tip_x", &x);
+ et->setData("tip_y", &y);
+ et->setData("tip_z", &z);
+ float vec[3] = { x, y, z };
+ copy_v3_v3(bone->tail, bone->head);
+ add_v3_v3v3(bone->tail, bone->head, vec);
+ }
+
+ BoneExtended *be = new BoneExtended(bone);
+ extended_bones[bone->name] = be;
+ return *be;
+}
diff --git a/source/blender/collada/ArmatureImporter.h b/source/blender/collada/ArmatureImporter.h
index beeac85cc4d..732fda80ff1 100644
--- a/source/blender/collada/ArmatureImporter.h
+++ b/source/blender/collada/ArmatureImporter.h
@@ -54,23 +54,41 @@ extern "C" {
#include "collada_internal.h"
#include "collada_utils.h"
+#include "ImportSettings.h"
+
+#define UNLIMITED_CHAIN_MAX INT_MAX
+#define MINIMUM_BONE_LENGTH 0.000001f
+
+class BoneExtended {
+
+private:
+ char name[MAXBONENAME];
+ int chain_length;
+ bool is_leaf;
+
+public:
+
+ BoneExtended(EditBone *aBone);
+ char *get_name();
+ int get_chain_length();
+
+ void set_name(char *aName);
+ void set_chain_length(const int aLength);
+ void set_leaf_bone(bool state);
+ bool is_leaf_bone();
+};
class ArmatureImporter : private TransformReader
{
private:
Scene *scene;
UnitConverter *unit_converter;
+ const ImportSettings *import_settings;
// std::map<int, JointData> joint_index_to_joint_info_map;
// std::map<COLLADAFW::UniqueId, int> joint_id_to_joint_index_map;
- struct LeafBone {
- // COLLADAFW::Node *node;
- EditBone *bone;
- char name[32];
- float mat[4][4]; // bone matrix, derived from inv_bind_mat
- };
- std::vector<LeafBone> leaf_bones;
+ std::map<std::string, BoneExtended *> extended_bones;
// int bone_direction_row; // XXX not used
float leaf_bone_length;
int totbone;
@@ -106,13 +124,15 @@ private:
JointData *get_joint_data(COLLADAFW::Node *node);
#endif
- void create_bone(SkinInfo* skin, COLLADAFW::Node *node, EditBone *parent, int totchild,
+ int create_bone(SkinInfo* skin, COLLADAFW::Node *node, EditBone *parent, int totchild,
float parent_mat[4][4], bArmature *arm);
- void add_leaf_bone(float mat[4][4], EditBone *bone, COLLADAFW::Node * node);
+ BoneExtended &add_bone_extended(EditBone *bone, COLLADAFW::Node * node);
+ void clear_extended_boneset();
+
+ void fix_leaf_bones(bArmature *armature, Bone *bone);
+ void connect_bone_chains(bArmature *armature, Bone *bone, const int max_chain_length);
- void fix_leaf_bones();
-
void set_pose( Object *ob_arm, COLLADAFW::Node *root_node, const char *parentname, float parent_mat[4][4]);
@@ -137,7 +157,7 @@ private:
TagsMap uid_tags_map;
public:
- ArmatureImporter(UnitConverter *conv, MeshImporterBase *mesh, Scene *sce);
+ ArmatureImporter(UnitConverter *conv, MeshImporterBase *mesh, Scene *sce, const ImportSettings *import_settings);
~ArmatureImporter();
void add_root_joint(COLLADAFW::Node *node, Object *parent);
diff --git a/source/blender/collada/CMakeLists.txt b/source/blender/collada/CMakeLists.txt
index 24daa41201d..293049a1a05 100644
--- a/source/blender/collada/CMakeLists.txt
+++ b/source/blender/collada/CMakeLists.txt
@@ -29,7 +29,7 @@ set(INC
.
../blenkernel
../blenlib
- ../blenfont
+ ../blentranslation
../editors/include
../makesdna
../makesrna
diff --git a/source/blender/collada/ControllerExporter.cpp b/source/blender/collada/ControllerExporter.cpp
index bc1c4172f46..06e151c363b 100644
--- a/source/blender/collada/ControllerExporter.cpp
+++ b/source/blender/collada/ControllerExporter.cpp
@@ -284,7 +284,8 @@ void ControllerExporter::export_skin_controller(Object *ob, Object *ob_arm)
}
if (oob_counter > 0) {
- fprintf(stderr, "Ignored %d Vertex weights which use index to non existing VGroup %ld.\n", oob_counter, joint_index_by_def_index.size());
+ fprintf(stderr, "Ignored %d Vertex weights which use index to non existing VGroup %lu.\n",
+ oob_counter, joint_index_by_def_index.size());
}
}
@@ -473,7 +474,7 @@ static float get_property(Bone *bone, const char *key, float def)
if (bone->prop) {
IDProperty *property = IDP_GetPropertyFromGroup(bone->prop, key);
if (property) {
- switch(property->type) {
+ switch (property->type) {
case IDP_INT:
result = (float)(IDP_Int(property));
break;
@@ -556,7 +557,7 @@ std::string ControllerExporter::add_inv_bind_mats_source(Object *ob_arm, ListBas
COLLADASW::FloatSourceF source(mSW);
source.setId(source_id);
source.setArrayId(source_id + ARRAY_ID_SUFFIX);
- source.setAccessorCount(totjoint); //BLI_countlist(defbase));
+ source.setAccessorCount(totjoint); //BLI_listbase_count(defbase));
source.setAccessorStride(16);
source.setParameterTypeName(&COLLADASW::CSWC::CSW_VALUE_TYPE_FLOAT4x4);
diff --git a/source/blender/collada/DocumentImporter.cpp b/source/blender/collada/DocumentImporter.cpp
index 8101e579098..674a79f0fe7 100644
--- a/source/blender/collada/DocumentImporter.cpp
+++ b/source/blender/collada/DocumentImporter.cpp
@@ -104,7 +104,7 @@ DocumentImporter::DocumentImporter(bContext *C, const ImportSettings *import_set
import_settings(import_settings),
mImportStage(General),
mContext(C),
- armature_importer(&unit_converter, &mesh_importer, CTX_data_scene(C)),
+ armature_importer(&unit_converter, &mesh_importer, CTX_data_scene(C), import_settings),
mesh_importer(&unit_converter, &armature_importer, CTX_data_scene(C)),
anim_importer(&unit_converter, &armature_importer, CTX_data_scene(C))
{
@@ -136,11 +136,14 @@ bool DocumentImporter::import()
const std::string encodedFilename = bc_url_encode(mFilename);
if (!root.loadDocument(encodedFilename)) {
fprintf(stderr, "COLLADAFW::Root::loadDocument() returned false on 1st pass\n");
+ delete ehandler;
return false;
}
- if (errorHandler.hasError())
+ if (errorHandler.hasError()) {
+ delete ehandler;
return false;
+ }
/** TODO set up scene graph and such here */
@@ -151,14 +154,11 @@ bool DocumentImporter::import()
if (!root2.loadDocument(encodedFilename)) {
fprintf(stderr, "COLLADAFW::Root::loadDocument() returned false on 2nd pass\n");
+ delete ehandler;
return false;
}
-
-
- delete ehandler;
- //XXX No longer needed (geometries are now created as bmesh)
- //mesh_importer.bmeshConversion();
+ delete ehandler;
return true;
}
@@ -226,6 +226,7 @@ void DocumentImporter::finish()
for (unsigned int i = 0; i < roots.getCount(); i++) {
std::vector<Object *> *objects_done = write_node(roots[i], NULL, sce, NULL, false);
objects_to_scale->insert(objects_to_scale->end(), objects_done->begin(), objects_done->end());
+ delete objects_done;
}
// update scene
@@ -278,6 +279,8 @@ void DocumentImporter::finish()
}
bc_match_scale(objects_to_scale, unit_converter, !this->import_settings->import_units);
+
+ delete objects_to_scale;
}
@@ -502,6 +505,9 @@ std::vector<Object *> *DocumentImporter::write_node(COLLADAFW::Node *node, COLLA
std::string id = node->getOriginalId();
std::string name = node->getName();
+ // if node has child nodes write them
+ COLLADAFW::NodePointerArray &child_nodes = node->getChildNodes();
+
std::vector<Object *> *objects_done = new std::vector<Object *>();
std::vector<Object *> *root_objects = new std::vector<Object *>();
@@ -527,7 +533,7 @@ std::vector<Object *> *DocumentImporter::write_node(COLLADAFW::Node *node, COLLA
if (parent_node == NULL) {
// for skeletons without root node all has been done above.
// Skeletons with root node are handled further down.
- return root_objects;
+ goto finally;
}
}
else {
@@ -641,7 +647,9 @@ std::vector<Object *> *DocumentImporter::write_node(COLLADAFW::Node *node, COLLA
// XXX: if there're multiple instances, only one is stored
- if (!ob) return root_objects;
+ if (!ob) {
+ goto finally;
+ }
for (std::vector<Object *>::iterator it = objects_done->begin(); it != objects_done->end(); ++it) {
ob = *it;
@@ -676,9 +684,6 @@ std::vector<Object *> *DocumentImporter::write_node(COLLADAFW::Node *node, COLLA
}
}
- // if node has child nodes write them
- COLLADAFW::NodePointerArray &child_nodes = node->getChildNodes();
-
if (objects_done->size() > 0) {
ob = *objects_done->begin();
}
@@ -687,9 +692,15 @@ std::vector<Object *> *DocumentImporter::write_node(COLLADAFW::Node *node, COLLA
}
for (unsigned int i = 0; i < child_nodes.getCount(); i++) {
- write_node(child_nodes[i], node, sce, ob, is_library_node);
+ std::vector<Object *> *child_objects;
+ child_objects = write_node(child_nodes[i], node, sce, ob, is_library_node);
+ delete child_objects;
}
+
+finally:
+ delete objects_done;
+
return root_objects;
}
@@ -728,7 +739,9 @@ bool DocumentImporter::writeLibraryNodes(const COLLADAFW::LibraryNodes *libraryN
const COLLADAFW::NodePointerArray& nodes = libraryNodes->getNodes();
for (unsigned int i = 0; i < nodes.getCount(); i++) {
- write_node(nodes[i], NULL, sce, NULL, true);
+ std::vector<Object *> *child_objects;
+ child_objects = write_node(nodes[i], NULL, sce, NULL, true);
+ delete child_objects;
}
return true;
@@ -774,9 +787,9 @@ MTex *DocumentImporter::create_texture(COLLADAFW::EffectCommon *ef, COLLADAFW::T
return NULL;
}
- ma->mtex[i] = add_mtex();
+ ma->mtex[i] = BKE_texture_mtex_add();
ma->mtex[i]->texco = TEXCO_UV;
- ma->mtex[i]->tex = add_texture(G.main, "Texture");
+ ma->mtex[i]->tex = BKE_texture_add(G.main, "Texture");
ma->mtex[i]->tex->type = TEX_IMAGE;
ma->mtex[i]->tex->ima = uid_image_map[ima_uid];
diff --git a/source/blender/collada/DocumentImporter.h b/source/blender/collada/DocumentImporter.h
index 5a7df9a41cf..62f76dbc022 100644
--- a/source/blender/collada/DocumentImporter.h
+++ b/source/blender/collada/DocumentImporter.h
@@ -51,7 +51,6 @@
-struct Main;
struct bContext;
/** Importer class. */
diff --git a/source/blender/collada/EffectExporter.cpp b/source/blender/collada/EffectExporter.cpp
index 3c35618a4cd..13dc1eda580 100644
--- a/source/blender/collada/EffectExporter.cpp
+++ b/source/blender/collada/EffectExporter.cpp
@@ -133,7 +133,7 @@ void EffectsExporter::writeTextures(COLLADASW::EffectProfile &ep,
if (!ima) return;
// color
- if (t->mapto & (MAP_COL | MAP_COLSPEC)) {
+ if (t->mapto & MAP_COL) {
ep.setDiffuse(createTexture(ima, uvname, sampler), false, "diffuse");
}
// ambient
@@ -141,7 +141,7 @@ void EffectsExporter::writeTextures(COLLADASW::EffectProfile &ep,
ep.setAmbient(createTexture(ima, uvname, sampler), false, "ambient");
}
// specular
- if (t->mapto & MAP_SPEC) {
+ if (t->mapto & (MAP_SPEC | MAP_COLSPEC)) {
ep.setSpecular(createTexture(ima, uvname, sampler), false, "specular");
}
// emission
@@ -263,7 +263,7 @@ void EffectsExporter::operator()(Material *ma, Object *ob)
COLLADASW::Sampler samplers[MAX_MTEX];
//COLLADASW::Surface surfaces[MAX_MTEX];
//void *samp_surf[MAX_MTEX][2];
- void *samp_surf[MAX_MTEX][1];
+ void *samp_surf[MAX_MTEX];
// image to index to samp_surf map
// samp_surf[index] stores 2 pointers, sampler and surface
@@ -302,7 +302,7 @@ void EffectsExporter::operator()(Material *ma, Object *ob)
//surfaces[a] = surface;
// store pointers so they can be used later when we create <texture>s
- samp_surf[b][0] = &samplers[a];
+ samp_surf[b] = &samplers[a];
//samp_surf[b][1] = &surfaces[a];
im_samp_map[key] = b;
@@ -349,7 +349,7 @@ void EffectsExporter::operator()(Material *ma, Object *ob)
key + COLLADASW::Sampler::SURFACE_SID_SUFFIX);
sampler.setImageId(key);
samplers[a] = sampler;
- samp_surf[b][0] = &samplers[a];
+ samp_surf[b] = &samplers[a];
im_samp_map[key] = b;
b++;
a++;
@@ -380,19 +380,19 @@ void EffectsExporter::operator()(Material *ma, Object *ob)
key = translate_id(key);
int i = im_samp_map[key];
std::string uvname = strlen(t->uvname) ? t->uvname : active_uv;
- COLLADASW::Sampler *sampler = (COLLADASW::Sampler *)samp_surf[i][0];
+ COLLADASW::Sampler *sampler = (COLLADASW::Sampler *)samp_surf[i];
writeTextures(ep, key, sampler, t, ima, uvname);
}
std::set<Image *>::iterator uv_t_iter;
int idx;
for (idx = 0, uv_t_iter = uv_textures.begin(); uv_t_iter != uv_textures.end(); uv_t_iter++, idx++ ) {
- if(active_uv_layer>-1 && idx==active_uv_layer) {
+ if (active_uv_layer>-1 && idx==active_uv_layer) {
Image *ima = *uv_t_iter;
std::string key(id_name(ima));
key = translate_id(key);
int i = im_samp_map[key];
- COLLADASW::Sampler *sampler = (COLLADASW::Sampler *)samp_surf[i][0];
+ COLLADASW::Sampler *sampler = (COLLADASW::Sampler *)samp_surf[i];
ep.setDiffuse(createTexture(ima, active_uv, sampler), false, "diffuse");
}
}
diff --git a/source/blender/collada/ErrorHandler.cpp b/source/blender/collada/ErrorHandler.cpp
index 7ac138ac807..b271604f839 100644
--- a/source/blender/collada/ErrorHandler.cpp
+++ b/source/blender/collada/ErrorHandler.cpp
@@ -34,6 +34,8 @@
#include <string.h>
+#include "BLI_utildefines.h"
+
//--------------------------------------------------------------------
ErrorHandler::ErrorHandler() : mError(false)
{
@@ -47,7 +49,7 @@ ErrorHandler::~ErrorHandler()
//--------------------------------------------------------------------
bool ErrorHandler::handleError(const COLLADASaxFWL::IError *error)
{
- mError = true;
+ bool isError = true;
if (error->getErrorClass() == COLLADASaxFWL::IError::ERROR_SAXPARSER) {
COLLADASaxFWL::SaxParserError *saxParserError = (COLLADASaxFWL::SaxParserError *) error;
@@ -55,15 +57,15 @@ bool ErrorHandler::handleError(const COLLADASaxFWL::IError *error)
// Workaround to avoid wrong error
if (parserError.getErrorType() == GeneratedSaxParser::ParserError::ERROR_VALIDATION_MIN_OCCURS_UNMATCHED) {
- if (strcmp(parserError.getElement(), "effect") == 0) {
- mError = false;
+ if (STREQ(parserError.getElement(), "effect")) {
+ isError = false;
}
}
if (parserError.getErrorType() == GeneratedSaxParser::ParserError::ERROR_VALIDATION_SEQUENCE_PREVIOUS_SIBLING_NOT_PRESENT) {
- if (!((strcmp(parserError.getElement(), "extra") == 0) &&
- (strcmp(parserError.getAdditionalText().c_str(), "sibling: fx_profile_abstract") == 0)))
+ if (!(STREQ(parserError.getElement(), "extra") &&
+ STREQ(parserError.getAdditionalText().c_str(), "sibling: fx_profile_abstract")))
{
- mError = false;
+ isError = false;
}
}
@@ -75,11 +77,21 @@ bool ErrorHandler::handleError(const COLLADASaxFWL::IError *error)
}
else if (error->getErrorClass() == COLLADASaxFWL::IError::ERROR_SAXFWL) {
COLLADASaxFWL::SaxFWLError *saxFWLError = (COLLADASaxFWL::SaxFWLError *) error;
+ /*
+ * Accept non critical errors as warnings (i.e. texture not found)
+ * This makes the importer more gracefull, so it now imports what makes sense.
+ */
+ if (saxFWLError->getSeverity() == COLLADASaxFWL::IError::SEVERITY_ERROR_NONCRITICAL) {
+ isError = false;
+ }
+
std::cout << "Sax FWL Error: " << saxFWLError->getErrorMessage() << std::endl;
}
else {
std::cout << "opencollada error: " << error->getFullErrorMessage() << std::endl;
}
- return false;
+ mError |= isError;
+
+ return false; // let OpenCollada decide when to abort
}
diff --git a/source/blender/collada/GeometryExporter.cpp b/source/blender/collada/GeometryExporter.cpp
index 1bf245c39e0..7c7c57f3305 100644
--- a/source/blender/collada/GeometryExporter.cpp
+++ b/source/blender/collada/GeometryExporter.cpp
@@ -159,7 +159,7 @@ void GeometryExporter::operator()(Object *ob)
//skip the basis
kb = kb->next;
for (; kb; kb = kb->next) {
- BKE_key_convert_to_mesh(kb, me);
+ BKE_keyblock_convert_to_mesh(kb, me);
export_key_mesh(ob, me, kb);
}
}
@@ -532,8 +532,8 @@ void GeometryExporter::createTexcoordsSource(std::string geom_id, Mesh *me)
// each <source> will get id like meshName + "map-channel-1"
int active_uv_index = CustomData_get_active_layer_index(&me->ldata, CD_MLOOPUV);
for (int a = 0; a < num_layers; a++) {
-
- if (!this->export_settings->active_uv_only || a == active_uv_index) {
+ int layer_index = CustomData_get_layer_index_n(&me->ldata, CD_MLOOPUV, a);
+ if (!this->export_settings->active_uv_only || layer_index == active_uv_index) {
MLoopUV *mloops = (MLoopUV *)CustomData_get_layer_n(&me->ldata, CD_MLOOPUV, a);
COLLADASW::FloatSourceF source(mSW);
@@ -563,6 +563,11 @@ void GeometryExporter::createTexcoordsSource(std::string geom_id, Mesh *me)
}
}
+bool operator<(const Normal &a, const Normal &b)
+{
+ /* only needed to sort normal vectors and find() them later in a map.*/
+ return a.x < b.x || (a.x == b.x && (a.y < b.y || (a.y == b.y && a.z < b.z)));
+}
//creates <source> for normals
void GeometryExporter::createNormalsSource(std::string geom_id, Mesh *me, std::vector<Normal>& nor)
@@ -596,15 +601,25 @@ void GeometryExporter::createNormalsSource(std::string geom_id, Mesh *me, std::v
void GeometryExporter::create_normals(std::vector<Normal> &normals, std::vector<BCPolygonNormalsIndices> &polygons_normals, Mesh *me)
{
- std::map<unsigned int, unsigned int> shared_normal_indices;
+ std::map<Normal, unsigned int> shared_normal_indices;
int last_normal_index = -1;
MVert *verts = me->mvert;
MLoop *mloops = me->mloop;
+ float(*lnors)[3] = NULL;
+ bool use_custom_normals = false;
+
+ BKE_mesh_calc_normals_split(me);
+ if (CustomData_has_layer(&me->ldata, CD_NORMAL)) {
+ lnors = (float(*)[3])CustomData_get_layer(&me->ldata, CD_NORMAL);
+ use_custom_normals = true;
+ }
+
for (int poly_index = 0; poly_index < me->totpoly; poly_index++) {
MPoly *mpoly = &me->mpoly[poly_index];
+ bool use_vertex_normals = use_custom_normals || mpoly->flag & ME_SMOOTH;
- if (!(mpoly->flag & ME_SMOOTH)) {
+ if (!use_vertex_normals) {
// For flat faces use face normal as vertex normal:
float vector[3];
@@ -615,25 +630,29 @@ void GeometryExporter::create_normals(std::vector<Normal> &normals, std::vector<
last_normal_index++;
}
-
- MLoop *mloop = mloops + mpoly->loopstart;
BCPolygonNormalsIndices poly_indices;
for (int loop_index = 0; loop_index < mpoly->totloop; loop_index++) {
- unsigned int vertex_index = mloop[loop_index].v;
- if (mpoly->flag & ME_SMOOTH) {
- if (shared_normal_indices.find(vertex_index) != shared_normal_indices.end())
- poly_indices.add_index (shared_normal_indices[vertex_index]);
- else {
+ unsigned int loop_idx = mpoly->loopstart + loop_index;
+ if (use_vertex_normals) {
+ float normalized[3];
- float vector[3];
- normal_short_to_float_v3(vector, verts[vertex_index].no);
+ if (use_custom_normals) {
+ normalize_v3_v3(normalized, lnors[loop_idx]);
+ }
+ else {
+ normal_short_to_float_v3(normalized, verts[mloops[loop_index].v].no);
+ normalize_v3(normalized);
+ }
+ Normal n = { normalized[0], normalized[1], normalized[2] };
- Normal n = { vector[0], vector[1], vector[2] };
- normals.push_back(n);
+ if (shared_normal_indices.find(n) != shared_normal_indices.end()) {
+ poly_indices.add_index(shared_normal_indices[n]);
+ }
+ else {
last_normal_index++;
-
poly_indices.add_index(last_normal_index);
- shared_normal_indices[vertex_index] = last_normal_index;
+ shared_normal_indices[n] = last_normal_index;
+ normals.push_back(n);
}
}
else {
diff --git a/source/blender/collada/GeometryExporter.h b/source/blender/collada/GeometryExporter.h
index 4d54e79d796..69d1067e6f4 100644
--- a/source/blender/collada/GeometryExporter.h
+++ b/source/blender/collada/GeometryExporter.h
@@ -48,6 +48,20 @@
extern Object *bc_get_highest_selected_ancestor_or_self(Object *ob);
+class Normal
+{
+ public:
+ float x;
+ float y;
+ float z;
+
+ friend bool operator< (const Normal &, const Normal &);
+
+};
+
+bool operator< (const Normal &, const Normal &);
+
+
// TODO: optimize UV sets by making indexed list with duplicates removed
class GeometryExporter : COLLADASW::LibraryGeometries
{
@@ -56,10 +70,7 @@ class GeometryExporter : COLLADASW::LibraryGeometries
unsigned int v1, v2, v3, v4;
};
- struct Normal
- {
- float x, y, z;
- };
+ Normal n;
Scene *mScene;
diff --git a/source/blender/collada/ImageExporter.cpp b/source/blender/collada/ImageExporter.cpp
index 55fe2034869..aac41e2e93c 100644
--- a/source/blender/collada/ImageExporter.cpp
+++ b/source/blender/collada/ImageExporter.cpp
@@ -67,14 +67,14 @@ void ImagesExporter::export_UV_Image(Image *image, bool use_copies)
return;
}
- bool is_dirty = imbuf->userflags & IB_BITMAPDIRTY;
+ bool is_dirty = (imbuf->userflags & IB_BITMAPDIRTY) != 0;
ImageFormatData imageFormat;
BKE_imbuf_to_image_format(&imageFormat, imbuf);
short image_source = image->source;
bool is_generated = image_source == IMA_SRC_GENERATED;
- bool is_packed = image->packedfile != NULL;
+ bool is_packed = BKE_image_has_packedfile(image);
char export_path[FILE_MAX];
char source_path[FILE_MAX];
@@ -89,7 +89,7 @@ void ImagesExporter::export_UV_Image(Image *image, bool use_copies)
// make absolute destination path
BLI_strncpy(export_file, name.c_str(), sizeof(export_file));
- BKE_add_image_extension(export_file, &imageFormat);
+ BKE_image_path_ensure_ext_from_imformat(export_file, &imageFormat);
BLI_join_dirfile(export_path, sizeof(export_path), export_dir, export_file);
diff --git a/source/blender/collada/ImportSettings.cpp b/source/blender/collada/ImportSettings.cpp
index 74607787f25..9483aa1ac76 100644
--- a/source/blender/collada/ImportSettings.cpp
+++ b/source/blender/collada/ImportSettings.cpp
@@ -20,7 +20,7 @@
* ***** END GPL LICENSE BLOCK *****
*/
-/** \file blender/collada/ExportSettings.cpp
+/** \file blender/collada/ImportSettings.cpp
* \ingroup collada
*/
diff --git a/source/blender/collada/ImportSettings.h b/source/blender/collada/ImportSettings.h
index 3f3a9fb354e..783f58e6bff 100644
--- a/source/blender/collada/ImportSettings.h
+++ b/source/blender/collada/ImportSettings.h
@@ -20,7 +20,7 @@
* ***** END GPL LICENSE BLOCK *****
*/
-/** \file ExportSettings.h
+/** \file ImportSettings.h
* \ingroup collada
*/
@@ -32,7 +32,9 @@
struct ImportSettings {
public:
bool import_units;
-
+ bool find_chains;
+ bool fix_orientation;
+ int min_chain_length;
char *filepath;
};
diff --git a/source/blender/collada/MeshImporter.cpp b/source/blender/collada/MeshImporter.cpp
index a4bf1d28366..2adbdd27cdf 100644
--- a/source/blender/collada/MeshImporter.cpp
+++ b/source/blender/collada/MeshImporter.cpp
@@ -185,7 +185,7 @@ void VCOLDataWrapper::get_vcol(int v_index, MLoopCol *mloopcol)
case COLLADAFW::MeshVertexData::DATA_TYPE_FLOAT:
{
COLLADAFW::ArrayPrimitiveType<float> *values = mVData->getFloatValues();
- if (values->empty()) return;
+ if (values->empty() || values->getCount() <= (v_index * stride + 2)) return; // xxx need to create an eror instead
mloopcol->r = FTOCHAR((*values)[v_index * stride]);
mloopcol->g = FTOCHAR((*values)[v_index * stride + 1]);
@@ -196,7 +196,7 @@ void VCOLDataWrapper::get_vcol(int v_index, MLoopCol *mloopcol)
case COLLADAFW::MeshVertexData::DATA_TYPE_DOUBLE:
{
COLLADAFW::ArrayPrimitiveType<double> *values = mVData->getDoubleValues();
- if (values->empty()) return;
+ if (values->empty() || values->getCount() <= (v_index * stride + 2)) return; // xxx need to create an eror instead
mloopcol->r = FTOCHAR((*values)[v_index * stride]);
mloopcol->g = FTOCHAR((*values)[v_index * stride + 1]);
@@ -225,11 +225,9 @@ void MeshImporter::set_poly_indices(MPoly *mpoly, MLoop *mloop, int loop_index,
void MeshImporter::set_vcol(MLoopCol *mlc, VCOLDataWrapper &vob, int loop_index, COLLADAFW::IndexList &index_list, int count)
{
- COLLADAFW::UIntValuesArray& indices =index_list.getIndices();
int index;
- for(index = 0; index < count; index++,mlc++)
- {
- int v_index = indices[index+loop_index];
+ for (index = 0; index < count; index++, mlc++) {
+ int v_index = index_list.getIndex(index + loop_index);
vob.get_vcol(v_index,mlc);
}
}
@@ -628,6 +626,7 @@ void MeshImporter::read_polys(COLLADAFW::Mesh *collada_mesh, Mesh *me)
unsigned int *position_indices = mp->getPositionIndices().getData();
unsigned int *normal_indices = mp->getNormalIndices().getData();
+
bool mp_has_normals = primitive_has_useable_normals(mp);
bool mp_has_faces = primitive_has_faces(mp);
@@ -708,16 +707,21 @@ void MeshImporter::read_polys(COLLADAFW::Mesh *collada_mesh, Mesh *me)
mpoly->flag |= ME_SMOOTH;
}
- for(unsigned int vcolor_index = 0 ; vcolor_index < index_list_array_vcolor.getCount();vcolor_index++)
- {
- COLLADAFW::IndexList& index_list = *index_list_array_vcolor[vcolor_index];
- COLLADAFW::String colname = extract_vcolname(index_list.getName());
- MLoopCol *mloopcol = (MLoopCol *)CustomData_get_layer_named(&me->ldata, CD_MLOOPCOL, colname.c_str());
- if (mloopcol == NULL) {
- fprintf(stderr, "Collada import: Mesh [%s] : Unknown reference to VCOLOR [#%s].\n", me->id.name, index_list.getName().c_str() );
- }
- else {
- set_vcol(mloopcol+loop_index, vcol, start_index, *index_list_array_vcolor[vcolor_index], vcount);
+
+ if (mp->hasColorIndices()) {
+ int vcolor_count = index_list_array_vcolor.getCount();
+
+ for (unsigned int vcolor_index = 0; vcolor_index < vcolor_count; vcolor_index++) {
+
+ COLLADAFW::IndexList& color_index_list = *mp->getColorIndices(vcolor_index);
+ COLLADAFW::String colname = extract_vcolname(color_index_list.getName());
+ MLoopCol *mloopcol = (MLoopCol *)CustomData_get_layer_named(&me->ldata, CD_MLOOPCOL, colname.c_str());
+ if (mloopcol == NULL) {
+ fprintf(stderr, "Collada import: Mesh [%s] : Unknown reference to VCOLOR [#%s].\n", me->id.name, color_index_list.getName().c_str());
+ }
+ else {
+ set_vcol(mloopcol + loop_index, vcol, start_index, color_index_list, vcount);
+ }
}
}
@@ -810,22 +814,6 @@ bool MeshImporter::is_flat_face(unsigned int *nind, COLLADAFW::MeshVertexData& n
return true;
}
-
-void MeshImporter::bmeshConversion()
-{
- for (std::map<COLLADAFW::UniqueId, Mesh *>::iterator m = uid_mesh_map.begin();
- m != uid_mesh_map.end(); ++m)
- {
- if ((*m).second) {
- Mesh *me = (*m).second;
- BKE_mesh_tessface_clear(me);
- BKE_mesh_calc_normals(me);
- //BKE_mesh_validate(me, 1);
- }
- }
-}
-
-
Object *MeshImporter::get_object_by_geom_uid(const COLLADAFW::UniqueId& geom_uid)
{
if (uid_object_map.find(geom_uid) != uid_object_map.end())
@@ -1063,7 +1051,7 @@ MTFace *MeshImporter::assign_material_to_geom(COLLADAFW::MaterialBinding cmateri
// set texture face
if (color_texture &&
strlen((color_texture)->uvname) &&
- strcmp(layername, color_texture->uvname) != 0) {
+ !STREQ(layername, color_texture->uvname)) {
texture_face = (MTFace *)CustomData_get_layer_named(&me->fdata, CD_MTFACE,
color_texture->uvname);
strcpy(layername, color_texture->uvname);
@@ -1197,7 +1185,12 @@ bool MeshImporter::write_geometry(const COLLADAFW::Geometry *geom)
read_vertices(mesh, me);
read_polys(mesh, me);
- BKE_mesh_calc_edges(me, false, false);
+
+ // must validate before calculating edges
+ BKE_mesh_calc_normals(me);
+ BKE_mesh_validate(me, false, false);
+ // validation does this
+ // BKE_mesh_calc_edges(me, false, false);
// read_lines() must be called after the face edges have been generated.
// Oterwise the loose edges will be silently deleted again.
diff --git a/source/blender/collada/MeshImporter.h b/source/blender/collada/MeshImporter.h
index 9fc1d777f62..9d5fefb83f2 100644
--- a/source/blender/collada/MeshImporter.h
+++ b/source/blender/collada/MeshImporter.h
@@ -161,8 +161,6 @@ public:
MeshImporter(UnitConverter *unitconv, ArmatureImporter *arm, Scene *sce);
- void bmeshConversion();
-
virtual Object *get_object_by_geom_uid(const COLLADAFW::UniqueId& geom_uid);
virtual Mesh *get_mesh_by_geom_uid(const COLLADAFW::UniqueId& geom_uid);
diff --git a/source/blender/collada/SConscript b/source/blender/collada/SConscript
index 1bd3947ff49..7853769a0f8 100644
--- a/source/blender/collada/SConscript
+++ b/source/blender/collada/SConscript
@@ -36,8 +36,8 @@ incs = [
'../ikplugin',
'#/intern/iksolver/extern',
'../blenlib',
- '../blenfont',
'../blenkernel',
+ '../blentranslation',
'../windowmanager',
'../makesdna',
'../makesrna',
diff --git a/source/blender/collada/SceneExporter.cpp b/source/blender/collada/SceneExporter.cpp
index b50b8b0a302..ac8ac2b9867 100644
--- a/source/blender/collada/SceneExporter.cpp
+++ b/source/blender/collada/SceneExporter.cpp
@@ -150,7 +150,7 @@ void SceneExporter::writeNodes(Object *ob, Scene *sce)
if (!instance_controller_created) {
COLLADASW::InstanceGeometry instGeom(mSW);
instGeom.setUrl(COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, get_geometry_id(ob, this->export_settings->use_object_instantiation)));
-
+ instGeom.setName(translate_id(id_name(ob)));
InstanceWriter::add_material_bindings(instGeom.getBindMaterial(), ob, this->export_settings->active_uv_only);
instGeom.add();
@@ -210,7 +210,7 @@ void SceneExporter::writeNodes(Object *ob, Scene *sce)
//not ideal: add the target object name as another parameter.
//No real mapping in the .dae
//Need support for multiple target objects also.
- bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
+ const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
ListBase targets = {NULL, NULL};
if (cti && cti->get_constraint_targets) {
diff --git a/source/blender/collada/SkinInfo.cpp b/source/blender/collada/SkinInfo.cpp
index 75928f9d189..71875d6274a 100644
--- a/source/blender/collada/SkinInfo.cpp
+++ b/source/blender/collada/SkinInfo.cpp
@@ -38,13 +38,16 @@
#include "BLI_math.h"
#include "BLI_compiler_attrs.h"
-#include "BKE_object.h"
#include "DNA_armature_types.h"
#include "DNA_modifier_types.h"
#include "DNA_scene_types.h"
+
+#include "BKE_action.h"
+#include "BKE_object.h"
+#include "BKE_object_deform.h"
+
#include "ED_mesh.h"
#include "ED_object.h"
-#include "BKE_action.h"
#include "SkinInfo.h"
#include "collada_utils.h"
@@ -263,7 +266,7 @@ void SkinInfo::link_armature(bContext *C, Object *ob, std::map<COLLADAFW::Unique
name = bc_get_joint_name(joint_by_uid[(*it).joint_uid]);
}
- ED_vgroup_add_name(ob, (char *)name);
+ BKE_object_defgroup_add_name(ob, name);
}
// <vcount> - number of joints per vertex - joints_per_vertex
diff --git a/source/blender/collada/TransformWriter.cpp b/source/blender/collada/TransformWriter.cpp
index 595787b44ac..e205608a365 100644
--- a/source/blender/collada/TransformWriter.cpp
+++ b/source/blender/collada/TransformWriter.cpp
@@ -102,7 +102,7 @@ void TransformWriter::add_node_transform_ob(COLLADASW::Node& node, Object *ob, B
double d_obmat[4][4];
float f_obmat[4][4];
- /* Export the local Matrix (relative to the object parent) */
+ /* Export the local Matrix (relative to the object parent, be it an object, bone or vertex(-tices)) */
BKE_object_matrix_local_get(ob, f_obmat);
converter.mat4_to_dae_double(d_obmat, f_obmat);
diff --git a/source/blender/collada/collada.cpp b/source/blender/collada/collada.cpp
index 223ab3eca2a..4ca21869ec2 100644
--- a/source/blender/collada/collada.cpp
+++ b/source/blender/collada/collada.cpp
@@ -44,13 +44,18 @@ extern "C"
int collada_import(bContext *C,
const char *filepath,
- int import_units)
+ int import_units,
+ int find_chains,
+ int fix_orientation,
+ int min_chain_length)
{
ImportSettings import_settings;
- import_settings.filepath = (char *)filepath;
-
- import_settings.import_units = import_units != 0;
+ import_settings.filepath = (char *)filepath;
+ import_settings.import_units = import_units != 0;
+ import_settings.find_chains = find_chains != 0;
+ import_settings.fix_orientation = fix_orientation != 0;
+ import_settings.min_chain_length = min_chain_length;
DocumentImporter imp(C, &import_settings);
if (imp.import()) return 1;
@@ -111,16 +116,28 @@ int collada_export(Scene *sce,
eObjectSet objectSet = (export_settings.selected) ? OB_SET_SELECTED : OB_SET_ALL;
export_settings.export_set = BKE_object_relational_superset(sce, objectSet, (eObRelationTypes)includeFilter);
-
- if (export_settings.sort_by_name)
- bc_bubble_sort_by_Object_name(export_settings.export_set);
+ int export_count = BLI_linklist_count(export_settings.export_set);
+
+ if (export_count==0)
+ {
+ if (export_settings.selected) {
+ fprintf(stderr, "Collada: Found no objects to export.\nPlease ensure that all objects which shall be exported are also visible in the 3D Viewport.\n");
+ }
+ else{
+ fprintf(stderr, "Collada: Your scene seems to be empty. No Objects will be exported.\n");
+ }
+ }
+ else {
+ if (export_settings.sort_by_name)
+ bc_bubble_sort_by_Object_name(export_settings.export_set);
+ }
DocumentExporter exporter(&export_settings);
exporter.exportCurrentScene(sce);
BLI_linklist_free(export_settings.export_set, NULL);
- return 1;
+ return export_count;
}
/* end extern C */
diff --git a/source/blender/collada/collada.h b/source/blender/collada/collada.h
index 524c704cdee..6819a62fdf0 100644
--- a/source/blender/collada/collada.h
+++ b/source/blender/collada/collada.h
@@ -55,7 +55,10 @@ struct Scene;
*/
int collada_import(struct bContext *C,
const char *filepath,
- int import_units);
+ int import_units,
+ int find_chains,
+ int fix_orientation,
+ int min_chain_length);
int collada_export(struct Scene *sce,
const char *filepath,
diff --git a/source/blender/collada/collada_internal.cpp b/source/blender/collada/collada_internal.cpp
index 567ee22b3d6..38855013ee1 100644
--- a/source/blender/collada/collada_internal.cpp
+++ b/source/blender/collada/collada_internal.cpp
@@ -94,8 +94,7 @@ void UnitConverter::dae_matrix_to_mat4_(float out[4][4], const COLLADABU::Math::
void UnitConverter::mat4_to_dae(float out[4][4], float in[4][4])
{
- copy_m4_m4(out, in);
- transpose_m4(out);
+ transpose_m4_m4(out, in);
}
void UnitConverter::mat4_to_dae_double(double out[4][4], float in[4][4])
@@ -188,73 +187,77 @@ void TransformBase::decompose(float mat[4][4], float *loc, float eul[3], float q
* must obviously be removed too, otherwise they would be heavily misinterpreted.
*/
const unsigned char translate_start_name_map[256] = {
- 95, 95, 95, 95, 95, 95, 95, 95, 95,
- 95, 95, 95, 95, 95, 95, 95, 95,
- 95, 95, 95, 95, 95, 95, 95, 95,
- 95, 95, 95, 95, 95, 95, 95, 95,
- 95, 95, 95, 95, 95, 95, 95, 95,
- 95, 95, 95, 95, 95, 95, 95, 95,
- 95, 95, 95, 95, 95, 95, 95, 95,
- 95, 95, 95, 95, 95, 95, 95, 95,
- 65, 66, 67, 68, 69, 70, 71, 72,
- 73, 74, 75, 76, 77, 78, 79, 80,
- 81, 82, 83, 84, 85, 86, 87, 88,
- 89, 90, 95, 95, 95, 95, 95, 95,
- 97, 98, 99, 100, 101, 102, 103, 104,
- 105, 106, 107, 108, 109, 110, 111, 112,
- 113, 114, 115, 116, 117, 118, 119, 120,
- 121, 122, 95, 95, 95, 95, 95, 95,
- 95, 95, 95, 95, 95, 95, 95, 95,
- 95, 95, 95, 95, 95, 95, 95, 95,
- 95, 95, 95, 95, 95, 95, 95, 95,
- 95, 95, 95, 95, 95, 95, 95, 95,
- 95, 95, 95, 95, 95, 95, 95, 95,
- 95, 95, 95, 95, 95, 95, 95, 95,
- 95, 95, 95, 95, 95, 95, 95, 95,
- 95, 95, 95, 95, 95, 95, 95, 192,
- 193, 194, 195, 196, 197, 198, 199, 200,
- 201, 202, 203, 204, 205, 206, 207, 208,
- 209, 210, 211, 212, 213, 214, 95, 216,
- 217, 218, 219, 220, 221, 222, 223, 224,
- 225, 226, 227, 228, 229, 230, 231, 232,
- 233, 234, 235, 236, 237, 238, 239, 240,
- 241, 242, 243, 244, 245, 246, 95, 248,
- 249, 250, 251, 252, 253, 254, 255
+
+ 95, 95, 95, 95, 95, 95, 95, 95,
+ 95, 95, 95, 95, 95, 95, 95, 95,
+ 95, 95, 95, 95, 95, 95, 95, 95,
+ 95, 95, 95, 95, 95, 95, 95, 95,
+ 95, 95, 95, 95, 95, 95, 95, 95,
+ 95, 95, 95, 95, 95, 95, 95, 95,
+ 95, 95, 95, 95, 95, 95, 95, 95,
+ 95, 95, 95, 95, 95, 95, 95, 95,
+ 95, 65, 66, 67, 68, 69, 70, 71,
+ 72, 73, 74, 75, 76, 77, 78, 79,
+ 80, 81, 82, 83, 84, 85, 86, 87,
+ 88, 89, 90, 95, 95, 95, 95, 95,
+ 95, 97, 98, 99, 100, 101, 102, 103,
+ 104, 105, 106, 107, 108, 109, 110, 111,
+ 112, 113, 114, 115, 116, 117, 118, 119,
+ 120, 121, 122, 95, 95, 95, 95, 95,
+
+ 128, 129, 130, 131, 132, 133, 134, 135,
+ 136, 137, 138, 139, 140, 141, 142, 143,
+ 144, 145, 146, 147, 148, 149, 150, 151,
+ 152, 153, 154, 155, 156, 157, 158, 159,
+ 160, 161, 162, 163, 164, 165, 166, 167,
+ 168, 169, 170, 171, 172, 173, 174, 175,
+ 176, 177, 178, 179, 180, 181, 182, 183,
+ 184, 185, 186, 187, 188, 189, 190, 191,
+ 192, 193, 194, 195, 196, 197, 198, 199,
+ 200, 201, 202, 203, 204, 205, 206, 207,
+ 208, 209, 210, 211, 212, 213, 214, 215,
+ 216, 217, 218, 219, 220, 221, 222, 223,
+ 224, 225, 226, 227, 228, 229, 230, 231,
+ 232, 233, 234, 235, 236, 237, 238, 239,
+ 240, 241, 242, 243, 244, 245, 246, 247,
+ 248, 249, 250, 251, 252, 253, 254, 255
};
const unsigned char translate_name_map[256] = {
- 95, 95, 95, 95, 95, 95, 95, 95, 95,
- 95, 95, 95, 95, 95, 95, 95, 95,
- 95, 95, 95, 95, 95, 95, 95, 95,
- 95, 95, 95, 95, 95, 95, 95, 95,
- 95, 95, 95, 95, 95, 95, 95, 95,
- 95, 95, 95, 95, 45, 95, 95, 48,
- 49, 50, 51, 52, 53, 54, 55, 56,
- 57, 95, 95, 95, 95, 95, 95, 95,
- 65, 66, 67, 68, 69, 70, 71, 72,
- 73, 74, 75, 76, 77, 78, 79, 80,
- 81, 82, 83, 84, 85, 86, 87, 88,
- 89, 90, 95, 95, 95, 95, 95, 95,
- 97, 98, 99, 100, 101, 102, 103, 104,
- 105, 106, 107, 108, 109, 110, 111, 112,
- 113, 114, 115, 116, 117, 118, 119, 120,
- 121, 122, 95, 95, 95, 95, 95, 95,
- 95, 95, 95, 95, 95, 95, 95, 95,
- 95, 95, 95, 95, 95, 95, 95, 95,
- 95, 95, 95, 95, 95, 95, 95, 95,
- 95, 95, 95, 95, 95, 95, 95, 95,
- 95, 95, 95, 95, 95, 95, 95, 95,
- 95, 95, 95, 95, 95, 95, 95, 95,
- 95, 95, 95, 95, 95, 95, 183, 95,
- 95, 95, 95, 95, 95, 95, 95, 192,
- 193, 194, 195, 196, 197, 198, 199, 200,
- 201, 202, 203, 204, 205, 206, 207, 208,
- 209, 210, 211, 212, 213, 214, 95, 216,
- 217, 218, 219, 220, 221, 222, 223, 224,
- 225, 226, 227, 228, 229, 230, 231, 232,
- 233, 234, 235, 236, 237, 238, 239, 240,
- 241, 242, 243, 244, 245, 246, 95, 248,
- 249, 250, 251, 252, 253, 254, 255
+
+ 95, 95, 95, 95, 95, 95, 95, 95,
+ 95, 95, 95, 95, 95, 95, 95, 95,
+ 95, 95, 95, 95, 95, 95, 95, 95,
+ 95, 95, 95, 95, 95, 95, 95, 95,
+ 95, 95, 95, 95, 95, 95, 95, 95,
+ 95, 95, 95, 95, 95, 45, 95, 95,
+ 48, 49, 50, 51, 52, 53, 54, 55,
+ 56, 57, 95, 95, 95, 95, 95, 95,
+ 95, 65, 66, 67, 68, 69, 70, 71,
+ 72, 73, 74, 75, 76, 77, 78, 79,
+ 80, 81, 82, 83, 84, 85, 86, 87,
+ 88, 89, 90, 95, 95, 95, 95, 95,
+ 95, 97, 98, 99, 100, 101, 102, 103,
+ 104, 105, 106, 107, 108, 109, 110, 111,
+ 112, 113, 114, 115, 116, 117, 118, 119,
+ 120, 121, 122, 95, 95, 95, 95, 95,
+
+ 128, 129, 130, 131, 132, 133, 134, 135,
+ 136, 137, 138, 139, 140, 141, 142, 143,
+ 144, 145, 146, 147, 148, 149, 150, 151,
+ 152, 153, 154, 155, 156, 157, 158, 159,
+ 160, 161, 162, 163, 164, 165, 166, 167,
+ 168, 169, 170, 171, 172, 173, 174, 175,
+ 176, 177, 178, 179, 180, 181, 182, 183,
+ 184, 185, 186, 187, 188, 189, 190, 191,
+ 192, 193, 194, 195, 196, 197, 198, 199,
+ 200, 201, 202, 203, 204, 205, 206, 207,
+ 208, 209, 210, 211, 212, 213, 214, 215,
+ 216, 217, 218, 219, 220, 221, 222, 223,
+ 224, 225, 226, 227, 228, 229, 230, 231,
+ 232, 233, 234, 235, 236, 237, 238, 239,
+ 240, 241, 242, 243, 244, 245, 246, 247,
+ 248, 249, 250, 251, 252, 253, 254, 255
};
typedef std::map< std::string, std::vector<std::string> > map_string_list;
diff --git a/source/blender/collada/collada_utils.cpp b/source/blender/collada/collada_utils.cpp
index d91689ff496..d669487db28 100644
--- a/source/blender/collada/collada_utils.cpp
+++ b/source/blender/collada/collada_utils.cpp
@@ -131,7 +131,7 @@ Object *bc_add_object(Scene *scene, int type, const char *name)
{
Object *ob = BKE_object_add_only_object(G.main, type, name);
- ob->data = BKE_object_obdata_add_from_type(G.main, type);
+ ob->data = BKE_object_obdata_add_from_type(G.main, type, name);
ob->lay = scene->lay;
DAG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
@@ -144,6 +144,7 @@ Mesh *bc_get_mesh_copy(Scene *scene, Object *ob, BC_export_mesh_type export_mesh
{
Mesh *tmpmesh;
CustomDataMask mask = CD_MASK_MESH;
+ Mesh *mesh = (Mesh *)ob->data;
DerivedMesh *dm = NULL;
if (apply_modifiers) {
switch (export_mesh_type) {
@@ -164,16 +165,13 @@ Mesh *bc_get_mesh_copy(Scene *scene, Object *ob, BC_export_mesh_type export_mesh
}
tmpmesh = BKE_mesh_add(G.main, "ColladaMesh"); // name is not important here
- DM_to_mesh(dm, tmpmesh, ob, CD_MASK_MESH);
- dm->release(dm);
+ DM_to_mesh(dm, tmpmesh, ob, CD_MASK_MESH, true);
+ tmpmesh->flag = mesh->flag;
if (triangulate) {
bc_triangulate_mesh(tmpmesh);
}
-
- // XXX Not sure if we need that for ngon_export as well.
BKE_mesh_tessface_ensure(tmpmesh);
-
return tmpmesh;
}
diff --git a/source/blender/compositor/CMakeLists.txt b/source/blender/compositor/CMakeLists.txt
index 4bcdd4d9e34..972db6b71d2 100644
--- a/source/blender/compositor/CMakeLists.txt
+++ b/source/blender/compositor/CMakeLists.txt
@@ -41,6 +41,7 @@ set(INC
../render/intern/include
../../../extern/clew/include
../../../intern/guardedalloc
+ ../../../intern/atomic
)
set(INC_SYS
@@ -90,8 +91,6 @@ set(SRC
intern/COM_OpenCLDevice.h
intern/COM_CompositorContext.cpp
intern/COM_CompositorContext.h
- intern/COM_ChannelInfo.cpp
- intern/COM_ChannelInfo.h
intern/COM_SingleThreadedOperation.cpp
intern/COM_SingleThreadedOperation.h
intern/COM_Debug.cpp
@@ -121,6 +120,8 @@ set(SRC
nodes/COM_TimeNode.h
nodes/COM_SwitchNode.cpp
nodes/COM_SwitchNode.h
+ nodes/COM_SwitchViewNode.cpp
+ nodes/COM_SwitchViewNode.h
nodes/COM_MovieClipNode.cpp
nodes/COM_MovieClipNode.h
nodes/COM_OutputFileNode.cpp
@@ -372,6 +373,8 @@ set(SRC
operations/COM_CompositorOperation.cpp
operations/COM_OutputFileOperation.h
operations/COM_OutputFileOperation.cpp
+ operations/COM_OutputFileMultiViewOperation.h
+ operations/COM_OutputFileMultiViewOperation.cpp
operations/COM_ViewerOperation.h
operations/COM_ViewerOperation.cpp
operations/COM_PreviewOperation.h
@@ -537,9 +540,19 @@ set(SRC
list(APPEND INC
${CMAKE_CURRENT_BINARY_DIR}/operations
)
+
+if(WITH_COMPOSITOR_WERROR)
+ ADD_CHECK_C_COMPILER_FLAG(CMAKE_C_FLAGS C_WERROR -Werror)
+ ADD_CHECK_CXX_COMPILER_FLAG(CMAKE_CXX_FLAGS C_WERROR -Werror)
+endif()
+
data_to_c(${CMAKE_CURRENT_SOURCE_DIR}/operations/COM_OpenCLKernels.cl
${CMAKE_CURRENT_BINARY_DIR}/operations/COM_OpenCLKernels.cl.h SRC)
add_definitions(-DCL_USE_DEPRECATED_OPENCL_1_1_APIS)
+if(WITH_CYCLES AND WITH_CYCLES_DEBUG)
+ add_definitions(-DWITH_CYCLES_DEBUG)
+endif()
+
blender_add_lib(bf_compositor "${SRC}" "${INC}" "${INC_SYS}")
diff --git a/source/blender/compositor/COM_compositor.h b/source/blender/compositor/COM_compositor.h
index 9b22444cf7f..a5d7704a708 100644
--- a/source/blender/compositor/COM_compositor.h
+++ b/source/blender/compositor/COM_compositor.h
@@ -38,7 +38,7 @@ extern "C" {
* @defgroup Node All nodes of the compositor
* @defgroup Operation All operations of the compositor
*
- * @mainpage Introduction of the Blender Compositor
+ * @page Introduction of the Blender Compositor
*
* @section bcomp Blender compositor
* This project redesigns the internals of Blender's compositor. The project has been executed in 2011 by At Mind.
@@ -316,7 +316,8 @@ extern "C" {
* generation in display space
*/
void COM_execute(RenderData *rd, Scene *scene, bNodeTree *editingtree, int rendering,
- const ColorManagedViewSettings *viewSettings, const ColorManagedDisplaySettings *displaySettings);
+ const ColorManagedViewSettings *viewSettings, const ColorManagedDisplaySettings *displaySettings,
+ const char *viewName);
/**
* @brief Deinitialize the compositor caches and allocated memory.
diff --git a/source/blender/compositor/COM_defines.h b/source/blender/compositor/COM_defines.h
index b60fffc6a22..9936914d3d8 100644
--- a/source/blender/compositor/COM_defines.h
+++ b/source/blender/compositor/COM_defines.h
@@ -105,7 +105,9 @@ typedef enum OrderOfChunks {
#define COM_RULE_OF_THIRDS_DIVIDER 100.0f
-#define COM_NUMBER_OF_CHANNELS 4
+#define COM_NUM_CHANNELS_VALUE 1
+#define COM_NUM_CHANNELS_VECTOR 3
+#define COM_NUM_CHANNELS_COLOR 4
#define COM_BLUR_BOKEH_PIXELS 512
diff --git a/source/blender/compositor/SConscript b/source/blender/compositor/SConscript
index eab40873f64..b3fe494a25c 100644
--- a/source/blender/compositor/SConscript
+++ b/source/blender/compositor/SConscript
@@ -50,6 +50,7 @@ incs = [
'../render/intern/include',
'../windowmanager',
'../../../intern/guardedalloc',
+ '../../../intern/atomic',
# data files
env['DATA_HEADERS'],
@@ -58,6 +59,9 @@ incs = [
if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'linuxcross', 'win64-vc'):
incs.append(env['BF_PTHREADS_INC'])
+if env['WITH_BF_CYCLES'] and env['WITH_BF_CYCLES_DEBUG']:
+ defs.append('WITH_CYCLES_DEBUG')
+
if False: # gives link errors 'win' in env['OURPLATFORM']:
# split into 3 modules to work around command length limit on Windows
env.BlenderLib('bf_composite_intern', sources_intern, incs, defines=defs, libtype=['core'], priority=[166])
diff --git a/source/blender/compositor/intern/COM_ChannelInfo.h b/source/blender/compositor/intern/COM_ChannelInfo.h
deleted file mode 100644
index ec78e7e1cb1..00000000000
--- a/source/blender/compositor/intern/COM_ChannelInfo.h
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
- * Copyright 2011, Blender Foundation.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * Contributor:
- * Jeroen Bakker
- * Monique Dewanchand
- */
-
-#ifndef _COM_ChannelInfo_h
-#define _COM_ChannelInfo_h
-
-#include <vector>
-#include "BKE_text.h"
-#include <string>
-#include "DNA_node_types.h"
-#include "BLI_rect.h"
-
-using namespace std;
-
-/**
- * @brief List of possible channel types
- * @ingroup Model
- */
-typedef enum ChannelType {
- COM_CT_ColorComponent /** @brief this channel is contains color information. Specific used is determined by channelnumber, and in the future color space */,
- COM_CT_Alpha /** @brief this channel is contains transparency value */,
- COM_CT_Value /** @brief this channel is contains a value */,
- COM_CT_X /** @brief this channel is contains a X value */,
- COM_CT_Y /** @brief this channel is contains a Y value */,
- COM_CT_Z /** @brief this channel is contains a Z value */,
- COM_CT_W /** @brief this channel is contains a W value */,
- COM_CT_UNUSED /** @brief this channel is unused */
-} ChannelType;
-
-/**
- * @brief ChannelInfo holds information about a channel.
- *
- * Channels are transported from node to node via a NodeLink.
- * ChannelInfo holds specific setting of these channels in order that the to-node of the link
- * Can handle specific logic per channel setting.
- *
- * @note currently this is not used, but a future place to implement color spacing and other things.
- * @ingroup Model
- */
-class ChannelInfo {
-private:
- /**
- * @brief the channel number, in the link. [0-3]
- */
- int m_number;
-
- /**
- * @brief type of channel
- */
- ChannelType m_type;
-
- /**
- * @brieg Is this value in this channel premultiplied with its alpha
- * @note only valid if type = ColorComponent;
- */
- bool m_premultiplied;
-
-// /**
-// * Color space of this value.
-// * only valid when type = ColorComponent;
-// */
-// string colorspacename;
-
-public:
- /**
- * @brief creates a new ChannelInfo and set default values
- */
- ChannelInfo();
-
- /**
- * @brief set the index of this channel in the NodeLink
- */
- void setNumber(const int number) { this->m_number = number; }
-
- /**
- * @brief get the index of this channel in the NodeLink
- */
- const int getNumber() const { return this->m_number; }
-
- /**
- * @brief set the type of channel
- */
- void setType(const ChannelType type) { this->m_type = type; }
-
- /**
- * @brief get the type of channel
- */
- const ChannelType getType() const { return this->m_type; }
-
- /**
- * @brief set the premultiplicatioin of this channel
- */
- void setPremultiplied(const bool premultiplied) { this->m_premultiplied = premultiplied; }
-
- /**
- * @brief is this channel premultiplied
- */
- const bool isPremultiplied() const { return this->m_premultiplied; }
-};
-
-
-#endif
diff --git a/source/blender/compositor/intern/COM_CompositorContext.h b/source/blender/compositor/intern/COM_CompositorContext.h
index a398ae937a3..d7ec653f480 100644
--- a/source/blender/compositor/intern/COM_CompositorContext.h
+++ b/source/blender/compositor/intern/COM_CompositorContext.h
@@ -87,6 +87,11 @@ private:
const ColorManagedViewSettings *m_viewSettings;
const ColorManagedDisplaySettings *m_displaySettings;
+ /**
+ * @brief active rendering view name
+ */
+ const char *m_viewName;
+
public:
/**
* @brief constructor initializes the context with default values.
@@ -180,12 +185,22 @@ public:
* @brief set has this system active openclDevices?
*/
void setHasActiveOpenCLDevices(bool hasAvtiveOpenCLDevices) { this->m_hasActiveOpenCLDevices = hasAvtiveOpenCLDevices; }
-
+
+ /**
+ * @brief get the active rendering view
+ */
+ const char *getViewName() const { return this->m_viewName; }
+
+ /**
+ * @brief set the active rendering view
+ */
+ void setViewName(const char *viewName) { this->m_viewName = viewName; }
+
int getChunksize() const { return this->getbNodeTree()->chunksize; }
void setFastCalculation(bool fastCalculation) {this->m_fastCalculation = fastCalculation;}
bool isFastCalculation() const { return this->m_fastCalculation; }
- bool isGroupnodeBufferEnabled() const { return this->getbNodeTree()->flag & NTREE_COM_GROUPNODE_BUFFER; }
+ bool isGroupnodeBufferEnabled() const { return (this->getbNodeTree()->flag & NTREE_COM_GROUPNODE_BUFFER) != 0; }
};
diff --git a/source/blender/compositor/intern/COM_Converter.cpp b/source/blender/compositor/intern/COM_Converter.cpp
index 99f66bcb5b4..9fa59be4a1c 100644
--- a/source/blender/compositor/intern/COM_Converter.cpp
+++ b/source/blender/compositor/intern/COM_Converter.cpp
@@ -101,6 +101,7 @@ extern "C" {
#include "COM_Stabilize2dNode.h"
#include "COM_SunBeamsNode.h"
#include "COM_SwitchNode.h"
+#include "COM_SwitchViewNode.h"
#include "COM_TextureNode.h"
#include "COM_TimeNode.h"
#include "COM_TonemapNode.h"
@@ -136,6 +137,10 @@ Node *Converter::convert(bNode *b_node)
{
Node *node = NULL;
+ /* ignore undefined nodes with missing or invalid node data */
+ if (!nodeIsRegistered(b_node))
+ return NULL;
+
switch (b_node->type) {
case CMP_NODE_COMPOSITE:
node = new CompositorNode(b_node);
@@ -328,6 +333,9 @@ Node *Converter::convert(bNode *b_node)
case CMP_NODE_SWITCH:
node = new SwitchNode(b_node);
break;
+ case CMP_NODE_SWITCH_VIEW:
+ node = new SwitchViewNode(b_node);
+ break;
case CMP_NODE_GLARE:
node = new GlareNode(b_node);
break;
diff --git a/source/blender/compositor/intern/COM_Debug.cpp b/source/blender/compositor/intern/COM_Debug.cpp
index 470f8fd2ef7..a7b464cde29 100644
--- a/source/blender/compositor/intern/COM_Debug.cpp
+++ b/source/blender/compositor/intern/COM_Debug.cpp
@@ -32,6 +32,7 @@ extern "C" {
#include "BLI_path_util.h"
#include "BLI_string.h"
#include "DNA_node_types.h"
+#include "BKE_appdir.h"
#include "BKE_node.h"
}
@@ -212,7 +213,7 @@ int DebugInfo::graphviz_legend_color(const char *name, const char *color, char *
return len;
}
-int DebugInfo::graphviz_legend_line(const char *name, const char *color, const char *style, char *str, int maxlen)
+int DebugInfo::graphviz_legend_line(const char * /*name*/, const char * /*color*/, const char * /*style*/, char *str, int maxlen)
{
/* XXX TODO */
int len = 0;
@@ -220,7 +221,7 @@ int DebugInfo::graphviz_legend_line(const char *name, const char *color, const c
return len;
}
-int DebugInfo::graphviz_legend_group(const char *name, const char *color, const char *style, char *str, int maxlen)
+int DebugInfo::graphviz_legend_group(const char *name, const char *color, const char * /*style*/, char *str, int maxlen)
{
int len = 0;
len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "<TR><TD>%s</TD><TD CELLPADDING=\"4\"><TABLE BORDER=\"1\" CELLBORDER=\"0\" CELLSPACING=\"0\" CELLPADDING=\"0\"><TR><TD BGCOLOR=\"%s\"></TD></TR></TABLE></TD></TR>\r\n", name, color);
@@ -355,7 +356,7 @@ bool DebugInfo::graphviz_system(const ExecutionSystem *system, char *str, int ma
std::string color;
switch (from->getDataType()) {
case COM_DT_VALUE:
- color = "grey";
+ color = "gray";
break;
case COM_DT_VECTOR:
color = "blue";
@@ -398,7 +399,7 @@ void DebugInfo::graphviz(const ExecutionSystem *system)
char filename[FILE_MAX];
BLI_snprintf(basename, sizeof(basename), "compositor_%d.dot", m_file_index);
- BLI_join_dirfile(filename, sizeof(filename), BLI_temp_dir_session(), basename);
+ BLI_join_dirfile(filename, sizeof(filename), BKE_tempdir_session(), basename);
++m_file_index;
FILE *fp = BLI_fopen(filename, "wb");
diff --git a/source/blender/compositor/intern/COM_ExecutionGroup.cpp b/source/blender/compositor/intern/COM_ExecutionGroup.cpp
index 366c97b50c6..5cb757d7dcb 100644
--- a/source/blender/compositor/intern/COM_ExecutionGroup.cpp
+++ b/source/blender/compositor/intern/COM_ExecutionGroup.cpp
@@ -25,12 +25,13 @@
#include <sstream>
#include <stdlib.h>
+#include "atomic_ops.h"
+
#include "COM_ExecutionGroup.h"
#include "COM_defines.h"
#include "COM_ExecutionSystem.h"
#include "COM_ReadBufferOperation.h"
#include "COM_WriteBufferOperation.h"
-#include "COM_ReadBufferOperation.h"
#include "COM_WorkScheduler.h"
#include "COM_ViewerOperation.h"
#include "COM_ChunkOrder.h"
@@ -238,7 +239,7 @@ void ExecutionGroup::execute(ExecutionSystem *graph)
chunkOrders[index].determineDistance(hotspots, 1);
}
- sort(&chunkOrders[0], &chunkOrders[this->m_numberOfChunks - 1]);
+ std::sort(&chunkOrders[0], &chunkOrders[this->m_numberOfChunks - 1]);
for (index = 0; index < this->m_numberOfChunks; index++) {
chunkOrder[index] = chunkOrders[index].getChunkNumber();
}
@@ -277,7 +278,7 @@ void ExecutionGroup::execute(ExecutionSystem *graph)
chunkOrders[index].determineDistance(hotspots, 9);
}
- sort(&chunkOrders[0], &chunkOrders[this->m_numberOfChunks]);
+ std::sort(&chunkOrders[0], &chunkOrders[this->m_numberOfChunks]);
for (index = 0; index < this->m_numberOfChunks; index++) {
chunkOrder[index] = chunkOrders[index].getChunkNumber();
@@ -377,41 +378,12 @@ MemoryBuffer *ExecutionGroup::constructConsolidatedMemoryBuffer(MemoryProxy *mem
return result;
}
-void ExecutionGroup::printBackgroundStats(void)
-{
- uintptr_t mem_in_use, mmap_in_use, peak_memory;
- float megs_used_memory, mmap_used_memory, megs_peak_memory;
- double execution_time;
- char timestr[64];
-
- execution_time = PIL_check_seconds_timer() - this->m_executionStartTime;
-
- mem_in_use = MEM_get_memory_in_use();
- mmap_in_use = MEM_get_mapped_memory_in_use();
- peak_memory = MEM_get_peak_memory();
-
- megs_used_memory = (mem_in_use - mmap_in_use) / (1024.0 * 1024.0);
- mmap_used_memory = (mmap_in_use) / (1024.0 * 1024.0);
- megs_peak_memory = (peak_memory) / (1024.0 * 1024.0);
-
- fprintf(stdout, "Mem:%.2fM (%.2fM, Peak %.2fM) ",
- megs_used_memory, mmap_used_memory, megs_peak_memory);
-
- BLI_timestr(execution_time, timestr, sizeof(timestr));
- printf("| Elapsed %s ", timestr);
- printf("| Tree %s, Tile %u-%u ", this->m_bTree->id.name + 2,
- this->m_chunksFinished, this->m_numberOfChunks);
-
- fputc('\n', stdout);
- fflush(stdout);
-}
-
void ExecutionGroup::finalizeChunkExecution(int chunkNumber, MemoryBuffer **memoryBuffers)
{
if (this->m_chunkExecutionStates[chunkNumber] == COM_ES_SCHEDULED)
this->m_chunkExecutionStates[chunkNumber] = COM_ES_EXECUTED;
- this->m_chunksFinished++;
+ atomic_add_u(&this->m_chunksFinished, 1);
if (memoryBuffers) {
for (unsigned int index = 0; index < this->m_cachedMaxReadBufferOffset; index++) {
MemoryBuffer *buffer = memoryBuffers[index];
@@ -430,8 +402,11 @@ void ExecutionGroup::finalizeChunkExecution(int chunkNumber, MemoryBuffer **memo
progress /= this->m_numberOfChunks;
this->m_bTree->progress(this->m_bTree->prh, progress);
- if (G.background)
- printBackgroundStats();
+ char buf[128];
+ BLI_snprintf(buf, sizeof(buf), "Compositing | Tile %u-%u",
+ this->m_chunksFinished,
+ this->m_numberOfChunks);
+ this->m_bTree->stats_draw(this->m_bTree->sdh, buf);
}
}
@@ -459,7 +434,8 @@ void ExecutionGroup::determineChunkRect(rcti *rect, const unsigned int chunkNumb
determineChunkRect(rect, xChunk, yChunk);
}
-MemoryBuffer *ExecutionGroup::allocateOutputBuffer(int chunkNumber, rcti *rect)
+MemoryBuffer *ExecutionGroup::allocateOutputBuffer(int /*chunkNumber*/,
+ rcti *rect)
{
// we asume that this method is only called from complex execution groups.
NodeOperation *operation = this->getOutputOperation();
diff --git a/source/blender/compositor/intern/COM_ExecutionGroup.h b/source/blender/compositor/intern/COM_ExecutionGroup.h
index 4b6f51c72c0..99365cdd4a8 100644
--- a/source/blender/compositor/intern/COM_ExecutionGroup.h
+++ b/source/blender/compositor/intern/COM_ExecutionGroup.h
@@ -347,11 +347,6 @@ public:
MemoryBuffer *allocateOutputBuffer(int chunkNumber, rcti *rect);
/**
- * @brief print execution statistics to stdout when running in a background mode
- */
- void printBackgroundStats(void);
-
- /**
* @brief after a chunk is executed the needed resources can be freed or unlocked.
* @param chunknumber
* @param memorybuffers
diff --git a/source/blender/compositor/intern/COM_ExecutionSystem.cpp b/source/blender/compositor/intern/COM_ExecutionSystem.cpp
index 7c08188db90..caeaa07d9f9 100644
--- a/source/blender/compositor/intern/COM_ExecutionSystem.cpp
+++ b/source/blender/compositor/intern/COM_ExecutionSystem.cpp
@@ -43,8 +43,10 @@ extern "C" {
#endif
ExecutionSystem::ExecutionSystem(RenderData *rd, Scene *scene, bNodeTree *editingtree, bool rendering, bool fastcalculation,
- const ColorManagedViewSettings *viewSettings, const ColorManagedDisplaySettings *displaySettings)
+ const ColorManagedViewSettings *viewSettings, const ColorManagedDisplaySettings *displaySettings,
+ const char *viewName)
{
+ this->m_context.setViewName(viewName);
this->m_context.setScene(scene);
this->m_context.setbNodeTree(editingtree);
this->m_context.setPreviewHash(editingtree->previews);
@@ -76,6 +78,8 @@ ExecutionSystem::ExecutionSystem(RenderData *rd, Scene *scene, bNodeTree *editin
viewer_border->xmin < viewer_border->xmax &&
viewer_border->ymin < viewer_border->ymax;
+ editingtree->stats_draw(editingtree->sdh, "Compositing | Determining resolution");
+
for (index = 0; index < this->m_groups.size(); index++) {
resolution[0] = 0;
resolution[1] = 0;
@@ -124,6 +128,9 @@ void ExecutionSystem::set_operations(const Operations &operations, const Groups
void ExecutionSystem::execute()
{
+ const bNodeTree *editingtree = this->m_context.getbNodeTree();
+ editingtree->stats_draw(editingtree->sdh, (char *)"Compositing | Initializing execution");
+
DebugInfo::execute_started(this);
unsigned int order = 0;
@@ -137,11 +144,15 @@ void ExecutionSystem::execute()
}
unsigned int index;
+ // First allocale all write buffer
for (index = 0; index < this->m_operations.size(); index++) {
NodeOperation *operation = this->m_operations[index];
- operation->setbNodeTree(this->m_context.getbNodeTree());
- operation->initExecution();
+ if (operation->isWriteBufferOperation()) {
+ operation->setbNodeTree(this->m_context.getbNodeTree());
+ operation->initExecution();
+ }
}
+ // Connect read buffers to their write buffers
for (index = 0; index < this->m_operations.size(); index++) {
NodeOperation *operation = this->m_operations[index];
if (operation->isReadBufferOperation()) {
@@ -149,6 +160,14 @@ void ExecutionSystem::execute()
readOperation->updateMemoryBuffer();
}
}
+ // initialize other operations
+ for (index = 0; index < this->m_operations.size(); index++) {
+ NodeOperation *operation = this->m_operations[index];
+ if (!operation->isWriteBufferOperation()) {
+ operation->setbNodeTree(this->m_context.getbNodeTree());
+ operation->initExecution();
+ }
+ }
for (index = 0; index < this->m_groups.size(); index++) {
ExecutionGroup *executionGroup = this->m_groups[index];
executionGroup->setChunksize(this->m_context.getChunksize());
@@ -166,6 +185,7 @@ void ExecutionSystem::execute()
WorkScheduler::finish();
WorkScheduler::stop();
+ editingtree->stats_draw(editingtree->sdh, (char *)"Compositing | Deinitializing execution");
for (index = 0; index < this->m_operations.size(); index++) {
NodeOperation *operation = this->m_operations[index];
operation->deinitExecution();
diff --git a/source/blender/compositor/intern/COM_ExecutionSystem.h b/source/blender/compositor/intern/COM_ExecutionSystem.h
index ab903206f0a..41d63fb3a72 100644
--- a/source/blender/compositor/intern/COM_ExecutionSystem.h
+++ b/source/blender/compositor/intern/COM_ExecutionSystem.h
@@ -27,14 +27,11 @@ class ExecutionGroup;
#include "DNA_color_types.h"
#include "DNA_node_types.h"
-#include <vector>
#include "COM_Node.h"
#include "BKE_text.h"
#include "COM_ExecutionGroup.h"
#include "COM_NodeOperation.h"
-using namespace std;
-
/**
* @page execution Execution model
* In order to get to an efficient model for execution, several steps are being done. these steps are explained below.
@@ -154,7 +151,8 @@ public:
* @param rendering [true false]
*/
ExecutionSystem(RenderData *rd, Scene *scene, bNodeTree *editingtree, bool rendering, bool fastcalculation,
- const ColorManagedViewSettings *viewSettings, const ColorManagedDisplaySettings *displaySettings);
+ const ColorManagedViewSettings *viewSettings, const ColorManagedDisplaySettings *displaySettings,
+ const char *viewName);
/**
* Destructor
diff --git a/source/blender/compositor/intern/COM_MemoryBuffer.cpp b/source/blender/compositor/intern/COM_MemoryBuffer.cpp
index c59ecced93c..7ee5e2f7c57 100644
--- a/source/blender/compositor/intern/COM_MemoryBuffer.cpp
+++ b/source/blender/compositor/intern/COM_MemoryBuffer.cpp
@@ -27,6 +27,19 @@
using std::min;
using std::max;
+static unsigned int determine_num_channels(DataType datatype)
+{
+ switch (datatype) {
+ case COM_DT_VALUE:
+ return COM_NUM_CHANNELS_VALUE;
+ case COM_DT_VECTOR:
+ return COM_NUM_CHANNELS_VECTOR;
+ case COM_DT_COLOR:
+ default:
+ return COM_NUM_CHANNELS_COLOR;
+ }
+}
+
unsigned int MemoryBuffer::determineBufferSize()
{
return getWidth() * getHeight();
@@ -34,61 +47,62 @@ unsigned int MemoryBuffer::determineBufferSize()
int MemoryBuffer::getWidth() const
{
- return this->m_rect.xmax - this->m_rect.xmin;
+ return this->m_width;
}
int MemoryBuffer::getHeight() const
{
- return this->m_rect.ymax - this->m_rect.ymin;
+ return this->m_height;
}
MemoryBuffer::MemoryBuffer(MemoryProxy *memoryProxy, unsigned int chunkNumber, rcti *rect)
{
BLI_rcti_init(&this->m_rect, rect->xmin, rect->xmax, rect->ymin, rect->ymax);
+ this->m_width = BLI_rcti_size_x(&this->m_rect);
+ this->m_height = BLI_rcti_size_y(&this->m_rect);
this->m_memoryProxy = memoryProxy;
this->m_chunkNumber = chunkNumber;
- this->m_buffer = (float *)MEM_mallocN_aligned(sizeof(float) * determineBufferSize() * COM_NUMBER_OF_CHANNELS, 16, "COM_MemoryBuffer");
+ this->m_num_channels = determine_num_channels(memoryProxy->getDataType());
+ this->m_buffer = (float *)MEM_mallocN_aligned(sizeof(float) * determineBufferSize() * this->m_num_channels, 16, "COM_MemoryBuffer");
this->m_state = COM_MB_ALLOCATED;
- this->m_datatype = COM_DT_COLOR;
- this->m_chunkWidth = this->m_rect.xmax - this->m_rect.xmin;
+ this->m_datatype = memoryProxy->getDataType();
}
MemoryBuffer::MemoryBuffer(MemoryProxy *memoryProxy, rcti *rect)
{
BLI_rcti_init(&this->m_rect, rect->xmin, rect->xmax, rect->ymin, rect->ymax);
+ this->m_width = BLI_rcti_size_x(&this->m_rect);
+ this->m_height = BLI_rcti_size_y(&this->m_rect);
this->m_memoryProxy = memoryProxy;
this->m_chunkNumber = -1;
- this->m_buffer = (float *)MEM_mallocN_aligned(sizeof(float) * determineBufferSize() * COM_NUMBER_OF_CHANNELS, 16, "COM_MemoryBuffer");
+ this->m_num_channels = determine_num_channels(memoryProxy->getDataType());
+ this->m_buffer = (float *)MEM_mallocN_aligned(sizeof(float) * determineBufferSize() * this->m_num_channels, 16, "COM_MemoryBuffer");
this->m_state = COM_MB_TEMPORARILY;
- this->m_datatype = COM_DT_COLOR;
- this->m_chunkWidth = this->m_rect.xmax - this->m_rect.xmin;
+ this->m_datatype = memoryProxy->getDataType();
+}
+MemoryBuffer::MemoryBuffer(DataType dataType, rcti *rect)
+{
+ BLI_rcti_init(&this->m_rect, rect->xmin, rect->xmax, rect->ymin, rect->ymax);
+ this->m_width = BLI_rcti_size_x(&this->m_rect);
+ this->m_height = BLI_rcti_size_y(&this->m_rect);
+ this->m_height = this->m_rect.ymax - this->m_rect.ymin;
+ this->m_memoryProxy = NULL;
+ this->m_chunkNumber = -1;
+ this->m_num_channels = determine_num_channels(dataType);
+ this->m_buffer = (float *)MEM_mallocN_aligned(sizeof(float) * determineBufferSize() * this->m_num_channels, 16, "COM_MemoryBuffer");
+ this->m_state = COM_MB_TEMPORARILY;
+ this->m_datatype = dataType;
}
MemoryBuffer *MemoryBuffer::duplicate()
{
MemoryBuffer *result = new MemoryBuffer(this->m_memoryProxy, &this->m_rect);
- memcpy(result->m_buffer, this->m_buffer, this->determineBufferSize() * COM_NUMBER_OF_CHANNELS * sizeof(float));
+ memcpy(result->m_buffer, this->m_buffer, this->determineBufferSize() * this->m_num_channels * sizeof(float));
return result;
}
void MemoryBuffer::clear()
{
- memset(this->m_buffer, 0, this->determineBufferSize() * COM_NUMBER_OF_CHANNELS * sizeof(float));
+ memset(this->m_buffer, 0, this->determineBufferSize() * this->m_num_channels * sizeof(float));
}
-float *MemoryBuffer::convertToValueBuffer()
-{
- const unsigned int size = this->determineBufferSize();
- unsigned int i;
-
- float *result = (float *)MEM_mallocN(sizeof(float) * size, __func__);
-
- const float *fp_src = this->m_buffer;
- float *fp_dst = result;
-
- for (i = 0; i < size; i++, fp_dst++, fp_src += COM_NUMBER_OF_CHANNELS) {
- *fp_dst = *fp_src;
- }
-
- return result;
-}
float MemoryBuffer::getMaximumValue()
{
@@ -98,7 +112,7 @@ float MemoryBuffer::getMaximumValue()
const float *fp_src = this->m_buffer;
- for (i = 0; i < size; i++, fp_src += COM_NUMBER_OF_CHANNELS) {
+ for (i = 0; i < size; i++, fp_src += this->m_num_channels) {
float value = *fp_src;
if (value > result) {
result = value;
@@ -116,7 +130,7 @@ float MemoryBuffer::getMaximumValue(rcti *rect)
BLI_rcti_isect(rect, &this->m_rect, &rect_clamp);
if (!BLI_rcti_is_empty(&rect_clamp)) {
- MemoryBuffer *temp = new MemoryBuffer(NULL, &rect_clamp);
+ MemoryBuffer *temp = new MemoryBuffer(this->m_datatype, &rect_clamp);
temp->copyContentFrom(this);
float result = temp->getMaximumValue();
delete temp;
@@ -152,9 +166,9 @@ void MemoryBuffer::copyContentFrom(MemoryBuffer *otherBuffer)
for (otherY = minY; otherY < maxY; otherY++) {
- otherOffset = ((otherY - otherBuffer->m_rect.ymin) * otherBuffer->m_chunkWidth + minX - otherBuffer->m_rect.xmin) * COM_NUMBER_OF_CHANNELS;
- offset = ((otherY - this->m_rect.ymin) * this->m_chunkWidth + minX - this->m_rect.xmin) * COM_NUMBER_OF_CHANNELS;
- memcpy(&this->m_buffer[offset], &otherBuffer->m_buffer[otherOffset], (maxX - minX) * COM_NUMBER_OF_CHANNELS * sizeof(float));
+ otherOffset = ((otherY - otherBuffer->m_rect.ymin) * otherBuffer->m_width + minX - otherBuffer->m_rect.xmin) * this->m_num_channels;
+ offset = ((otherY - this->m_rect.ymin) * this->m_width + minX - this->m_rect.xmin) * this->m_num_channels;
+ memcpy(&this->m_buffer[offset], &otherBuffer->m_buffer[otherOffset], (maxX - minX) * this->m_num_channels * sizeof(float));
}
}
@@ -163,9 +177,8 @@ void MemoryBuffer::writePixel(int x, int y, const float color[4])
if (x >= this->m_rect.xmin && x < this->m_rect.xmax &&
y >= this->m_rect.ymin && y < this->m_rect.ymax)
{
- const int offset = (this->m_chunkWidth * (y - this->m_rect.ymin) + x - this->m_rect.xmin) * COM_NUMBER_OF_CHANNELS;
- copy_v4_v4(&this->m_buffer[offset], color);
- }
+ const int offset = (this->m_width * (y - this->m_rect.ymin) + x - this->m_rect.xmin) * this->m_num_channels;
+ memcpy(&this->m_buffer[offset], color, sizeof(float)*this->m_num_channels); }
}
void MemoryBuffer::addPixel(int x, int y, const float color[4])
@@ -173,63 +186,39 @@ void MemoryBuffer::addPixel(int x, int y, const float color[4])
if (x >= this->m_rect.xmin && x < this->m_rect.xmax &&
y >= this->m_rect.ymin && y < this->m_rect.ymax)
{
- const int offset = (this->m_chunkWidth * (y - this->m_rect.ymin) + x - this->m_rect.xmin) * COM_NUMBER_OF_CHANNELS;
- add_v4_v4(&this->m_buffer[offset], color);
+ const int offset = (this->m_width * (y - this->m_rect.ymin) + x - this->m_rect.xmin) * this->m_num_channels;
+ float *dst = &this->m_buffer[offset];
+ const float *src = color;
+ for (int i = 0; i < this->m_num_channels ; i++, dst++, src++) {
+ *dst += *src;
+ }
}
}
-typedef struct ReadEWAData {
- MemoryBuffer *buffer;
- PixelSampler sampler;
- float ufac, vfac;
-} ReadEWAData;
-
static void read_ewa_pixel_sampled(void *userdata, int x, int y, float result[4])
{
- ReadEWAData *data = (ReadEWAData *) userdata;
- switch (data->sampler) {
- case COM_PS_NEAREST:
- data->buffer->read(result, x, y);
- break;
- case COM_PS_BILINEAR:
- data->buffer->readBilinear(result,
- (float)x + data->ufac,
- (float)y + data->vfac);
- break;
- case COM_PS_BICUBIC:
- /* TOOD(sergey): no readBicubic method yet */
- data->buffer->readBilinear(result,
- (float)x + data->ufac,
- (float)y + data->vfac);
- break;
- default:
- zero_v4(result);
- break;
- }
+ MemoryBuffer *buffer = (MemoryBuffer *) userdata;
+ buffer->read(result, x, y);
}
-void MemoryBuffer::readEWA(float result[4], const float uv[2], const float derivatives[2][2], PixelSampler sampler)
+void MemoryBuffer::readEWA(float *result, const float uv[2], const float derivatives[2][2])
{
- ReadEWAData data;
- data.buffer = this;
- data.sampler = sampler;
- data.ufac = uv[0] - floorf(uv[0]);
- data.vfac = uv[1] - floorf(uv[1]);
-
- int width = this->getWidth(), height = this->getHeight();
+ BLI_assert(this->m_datatype == COM_DT_COLOR);
+ float inv_width = 1.0f / (float)this->getWidth(),
+ inv_height = 1.0f / (float)this->getHeight();
/* TODO(sergey): Render pipeline uses normalized coordinates and derivatives,
* but compositor uses pixel space. For now let's just divide the values and
* switch compositor to normalized space for EWA later.
*/
- float uv_normal[2] = {uv[0] / width, uv[1] / height};
- float du_normal[2] = {derivatives[0][0] / width, derivatives[0][1] / height};
- float dv_normal[2] = {derivatives[1][0] / width, derivatives[1][1] / height};
+ float uv_normal[2] = {uv[0] * inv_width, uv[1] * inv_height};
+ float du_normal[2] = {derivatives[0][0] * inv_width, derivatives[0][1] * inv_height};
+ float dv_normal[2] = {derivatives[1][0] * inv_width, derivatives[1][1] * inv_height};
BLI_ewa_filter(this->getWidth(), this->getHeight(),
false,
true,
uv_normal, du_normal, dv_normal,
read_ewa_pixel_sampled,
- &data,
+ this,
result);
}
diff --git a/source/blender/compositor/intern/COM_MemoryBuffer.h b/source/blender/compositor/intern/COM_MemoryBuffer.h
index d6ef9cd673e..de8c14e1a66 100644
--- a/source/blender/compositor/intern/COM_MemoryBuffer.h
+++ b/source/blender/compositor/intern/COM_MemoryBuffer.h
@@ -83,11 +83,6 @@ private:
unsigned int m_chunkNumber;
/**
- * @brief width of the chunk
- */
- unsigned int m_chunkWidth;
-
- /**
* @brief state of the buffer
*/
MemoryBufferState m_state;
@@ -97,6 +92,15 @@ private:
*/
float *m_buffer;
+ /**
+ * @brief the number of channels of a single value in the buffer.
+ * For value buffers this is 1, vector 3 and color 4
+ */
+ unsigned int m_num_channels;
+
+ int m_width;
+ int m_height;
+
public:
/**
* @brief construct new MemoryBuffer for a chunk
@@ -107,7 +111,12 @@ public:
* @brief construct new temporarily MemoryBuffer for an area
*/
MemoryBuffer(MemoryProxy *memoryProxy, rcti *rect);
-
+
+ /**
+ * @brief construct new temporarily MemoryBuffer for an area
+ */
+ MemoryBuffer(DataType datatype, rcti *rect);
+
/**
* @brief destructor
*/
@@ -117,7 +126,9 @@ public:
* @brief read the ChunkNumber of this MemoryBuffer
*/
unsigned int getChunkNumber() { return this->m_chunkNumber; }
-
+
+ unsigned int get_num_channels() { return this->m_num_channels; }
+
/**
* @brief get the data of this MemoryBuffer
* @note buffer should already be available in memory
@@ -134,8 +145,8 @@ public:
inline void wrap_pixel(int &x, int &y, MemoryBufferExtend extend_x, MemoryBufferExtend extend_y)
{
- int w = m_rect.xmax - m_rect.xmin;
- int h = m_rect.ymax - m_rect.ymin;
+ int w = this->m_width;
+ int h = this->m_height;
x = x - m_rect.xmin;
y = y - m_rect.ymin;
@@ -164,7 +175,39 @@ public:
}
}
- inline void read(float result[4], int x, int y,
+ inline void wrap_pixel(float &x, float &y, MemoryBufferExtend extend_x, MemoryBufferExtend extend_y)
+ {
+ float w = (float)this->m_width;
+ float h = (float)this->m_height;
+ x = x - m_rect.xmin;
+ y = y - m_rect.ymin;
+
+ switch (extend_x) {
+ case COM_MB_CLIP:
+ break;
+ case COM_MB_EXTEND:
+ if (x < 0) x = 0.0f;
+ if (x >= w) x = w;
+ break;
+ case COM_MB_REPEAT:
+ x = fmodf(x, w);
+ break;
+ }
+
+ switch (extend_y) {
+ case COM_MB_CLIP:
+ break;
+ case COM_MB_EXTEND:
+ if (y < 0) y = 0.0f;
+ if (y >= h) y = h;
+ break;
+ case COM_MB_REPEAT:
+ y = fmodf(y, h);
+ break;
+ }
+ }
+
+ inline void read(float *result, int x, int y,
MemoryBufferExtend extend_x = COM_MB_CLIP,
MemoryBufferExtend extend_y = COM_MB_CLIP)
{
@@ -172,81 +215,54 @@ public:
bool clip_y = (extend_y == COM_MB_CLIP && (y < m_rect.ymin || y >= m_rect.ymax));
if (clip_x || clip_y) {
/* clip result outside rect is zero */
- zero_v4(result);
+ memset(result, 0, this->m_num_channels * sizeof(float));
}
else {
- wrap_pixel(x, y, extend_x, extend_y);
- const int offset = (this->m_chunkWidth * y + x) * COM_NUMBER_OF_CHANNELS;
- copy_v4_v4(result, &this->m_buffer[offset]);
+ int u = x;
+ int v = y;
+ this->wrap_pixel(u, v, extend_x, extend_y);
+ const int offset = (this->m_width * y + x) * this->m_num_channels;
+ float *buffer = &this->m_buffer[offset];
+ memcpy(result, buffer, sizeof(float) * this->m_num_channels);
}
}
- inline void readNoCheck(float result[4], int x, int y,
+ inline void readNoCheck(float *result, int x, int y,
MemoryBufferExtend extend_x = COM_MB_CLIP,
MemoryBufferExtend extend_y = COM_MB_CLIP)
{
- wrap_pixel(x, y, extend_x, extend_y);
- const int offset = (this->m_chunkWidth * y + x) * COM_NUMBER_OF_CHANNELS;
+ int u = x;
+ int v = y;
- BLI_assert(offset >= 0);
- BLI_assert(offset < this->determineBufferSize() * COM_NUMBER_OF_CHANNELS);
- BLI_assert(!(extend_x == COM_MB_CLIP && (x < m_rect.xmin || x >= m_rect.xmax)) &&
- !(extend_y == COM_MB_CLIP && (y < m_rect.ymin || y >= m_rect.ymax)));
+ this->wrap_pixel(u, v, extend_x, extend_y);
+ const int offset = (this->m_width * v + u) * this->m_num_channels;
+ BLI_assert(offset >= 0);
+ BLI_assert(offset < this->determineBufferSize() * this->m_num_channels);
+ BLI_assert(!(extend_x == COM_MB_CLIP && (u < m_rect.xmin || u >= m_rect.xmax)) &&
+ !(extend_y == COM_MB_CLIP && (v < m_rect.ymin || v >= m_rect.ymax)));
#if 0
/* always true */
BLI_assert((int)(MEM_allocN_len(this->m_buffer) / sizeof(*this->m_buffer)) ==
(int)(this->determineBufferSize() * COM_NUMBER_OF_CHANNELS));
#endif
-
- copy_v4_v4(result, &this->m_buffer[offset]);
+ float *buffer = &this->m_buffer[offset];
+ memcpy(result, buffer, sizeof(float) * this->m_num_channels);
}
void writePixel(int x, int y, const float color[4]);
void addPixel(int x, int y, const float color[4]);
- inline void readBilinear(float result[4], float x, float y,
+ inline void readBilinear(float *result, float x, float y,
MemoryBufferExtend extend_x = COM_MB_CLIP,
MemoryBufferExtend extend_y = COM_MB_CLIP)
{
- int x1 = floor(x);
- int y1 = floor(y);
- int x2 = x1 + 1;
- int y2 = y1 + 1;
- wrap_pixel(x1, y1, extend_x, extend_y);
- wrap_pixel(x2, y2, extend_x, extend_y);
-
- float valuex = x - x1;
- float valuey = y - y1;
- float mvaluex = 1.0f - valuex;
- float mvaluey = 1.0f - valuey;
-
- float color1[4];
- float color2[4];
- float color3[4];
- float color4[4];
-
- read(color1, x1, y1);
- read(color2, x1, y2);
- read(color3, x2, y1);
- read(color4, x2, y2);
-
- color1[0] = color1[0] * mvaluey + color2[0] * valuey;
- color1[1] = color1[1] * mvaluey + color2[1] * valuey;
- color1[2] = color1[2] * mvaluey + color2[2] * valuey;
- color1[3] = color1[3] * mvaluey + color2[3] * valuey;
-
- color3[0] = color3[0] * mvaluey + color4[0] * valuey;
- color3[1] = color3[1] * mvaluey + color4[1] * valuey;
- color3[2] = color3[2] * mvaluey + color4[2] * valuey;
- color3[3] = color3[3] * mvaluey + color4[3] * valuey;
-
- result[0] = color1[0] * mvaluex + color3[0] * valuex;
- result[1] = color1[1] * mvaluex + color3[1] * valuex;
- result[2] = color1[2] * mvaluex + color3[2] * valuex;
- result[3] = color1[3] * mvaluex + color3[3] * valuex;
+ float u = x;
+ float v = y;
+ this->wrap_pixel(u, v, extend_x, extend_y);
+ BLI_bilinear_interpolation_fl(this->m_buffer, result, this->m_width, this->m_height, this->m_num_channels, u, v);
}
- void readEWA(float result[4], const float uv[2], const float derivatives[2][2], PixelSampler sampler);
+ void readEWA(float *result, const float uv[2], const float derivatives[2][2]);
/**
* @brief is this MemoryBuffer a temporarily buffer (based on an area, not on a chunk)
@@ -284,7 +300,6 @@ public:
MemoryBuffer *duplicate();
- float *convertToValueBuffer();
float getMaximumValue();
float getMaximumValue(rcti *rect);
private:
diff --git a/source/blender/compositor/intern/COM_MemoryProxy.cpp b/source/blender/compositor/intern/COM_MemoryProxy.cpp
index 90ca0baea06..1df3e59db62 100644
--- a/source/blender/compositor/intern/COM_MemoryProxy.cpp
+++ b/source/blender/compositor/intern/COM_MemoryProxy.cpp
@@ -23,10 +23,11 @@
#include "COM_MemoryProxy.h"
-MemoryProxy::MemoryProxy()
+MemoryProxy::MemoryProxy(DataType datatype)
{
this->m_writeBufferOperation = NULL;
this->m_executor = NULL;
+ this->m_datatype = datatype;
}
void MemoryProxy::allocate(unsigned int width, unsigned int height)
diff --git a/source/blender/compositor/intern/COM_MemoryProxy.h b/source/blender/compositor/intern/COM_MemoryProxy.h
index 233b035a2d7..b332852088b 100644
--- a/source/blender/compositor/intern/COM_MemoryProxy.h
+++ b/source/blender/compositor/intern/COM_MemoryProxy.h
@@ -63,8 +63,13 @@ private:
*/
MemoryBuffer *m_buffer;
+ /**
+ * @brief datatype of this MemoryProxy
+ */
+ DataType m_datatype;
+
public:
- MemoryProxy();
+ MemoryProxy(DataType type);
/**
* @brief set the ExecutionGroup that can be scheduled to calculate a certain chunk.
@@ -104,6 +109,8 @@ public:
*/
inline MemoryBuffer *getBuffer() { return this->m_buffer; }
+ inline DataType getDataType() { return this->m_datatype; }
+
#ifdef WITH_CXX_GUARDEDALLOC
MEM_CXX_CLASS_ALLOC_FUNCS("COM:MemoryProxy")
#endif
diff --git a/source/blender/compositor/intern/COM_NodeGraph.cpp b/source/blender/compositor/intern/COM_NodeGraph.cpp
index 2dcf419d81b..c5096a6b352 100644
--- a/source/blender/compositor/intern/COM_NodeGraph.cpp
+++ b/source/blender/compositor/intern/COM_NodeGraph.cpp
@@ -179,6 +179,8 @@ void NodeGraph::add_bNodeLink(const NodeRange &node_range, bNodeLink *b_nodelink
/// @note: ignore invalid links
if (!(b_nodelink->flag & NODE_LINK_VALID))
return;
+ if ((b_nodelink->fromsock->flag & SOCK_UNAVAIL) || (b_nodelink->tosock->flag & SOCK_UNAVAIL))
+ return;
/* Note: a DNA input socket can have multiple NodeInput in the compositor tree! (proxies)
* The output then gets linked to each one of them.
diff --git a/source/blender/compositor/intern/COM_NodeOperation.h b/source/blender/compositor/intern/COM_NodeOperation.h
index d9c16615fb6..7c87524b4b3 100644
--- a/source/blender/compositor/intern/COM_NodeOperation.h
+++ b/source/blender/compositor/intern/COM_NodeOperation.h
@@ -161,7 +161,7 @@ public:
*
* @return bool the result of this method
*/
- virtual bool isOutputOperation(bool rendering) const { return false; }
+ virtual bool isOutputOperation(bool /*rendering*/) const { return false; }
virtual int isSingleThreaded() { return false; }
@@ -175,7 +175,8 @@ public:
* @param chunkNumber the chunkNumber to be calculated
* @param memoryBuffers all input MemoryBuffer's needed
*/
- virtual void executeRegion(rcti *rect, unsigned int chunkNumber) {}
+ virtual void executeRegion(rcti * /*rect*/,
+ unsigned int /*chunkNumber*/) {}
/**
* @brief when a chunk is executed by an OpenCLDevice, this method is called
@@ -189,8 +190,11 @@ public:
* @param memoryBuffers all input MemoryBuffer's needed
* @param outputBuffer the outputbuffer to write to
*/
- virtual void executeOpenCLRegion(OpenCLDevice *device, rcti *rect,
- unsigned int chunkNumber, MemoryBuffer **memoryBuffers, MemoryBuffer *outputBuffer) {}
+ virtual void executeOpenCLRegion(OpenCLDevice * /*device*/,
+ rcti * /*rect*/,
+ unsigned int /*chunkNumber*/,
+ MemoryBuffer ** /*memoryBuffers*/,
+ MemoryBuffer * /*outputBuffer*/) {}
/**
* @brief custom handle to add new tasks to the OpenCL command queue in order to execute a chunk on an GPUDevice
@@ -204,10 +208,12 @@ public:
* @param clMemToCleanUp all created cl_mem references must be added to this list. Framework will clean this after execution
* @param clKernelsToCleanUp all created cl_kernel references must be added to this list. Framework will clean this after execution
*/
- virtual void executeOpenCL(OpenCLDevice *device,
- MemoryBuffer *outputMemoryBuffer, cl_mem clOutputBuffer,
- MemoryBuffer **inputMemoryBuffers, list<cl_mem> *clMemToCleanUp,
- list<cl_kernel> *clKernelsToCleanUp) {}
+ virtual void executeOpenCL(OpenCLDevice * /*device*/,
+ MemoryBuffer * /*outputMemoryBuffer*/,
+ cl_mem /*clOutputBuffer*/,
+ MemoryBuffer ** /*inputMemoryBuffers*/,
+ list<cl_mem> * /*clMemToCleanUp*/,
+ list<cl_kernel> * /*clKernelsToCleanUp*/) {}
virtual void deinitExecution();
bool isResolutionSet() {
diff --git a/source/blender/compositor/intern/COM_NodeOperationBuilder.cpp b/source/blender/compositor/intern/COM_NodeOperationBuilder.cpp
index fb5bc8fcd9b..e899b7b14fd 100644
--- a/source/blender/compositor/intern/COM_NodeOperationBuilder.cpp
+++ b/source/blender/compositor/intern/COM_NodeOperationBuilder.cpp
@@ -101,12 +101,12 @@ void NodeOperationBuilder::convertToOperations(ExecutionSystem *system)
}
}
- add_datatype_conversions();
-
add_operation_input_constants();
resolve_proxies();
+ add_datatype_conversions();
+
determineResolutions();
/* surround complex ops with read/write buffer */
@@ -459,7 +459,8 @@ WriteBufferOperation *NodeOperationBuilder::find_attached_write_buffer_operation
return NULL;
}
-void NodeOperationBuilder::add_input_buffers(NodeOperation *operation, NodeOperationInput *input)
+void NodeOperationBuilder::add_input_buffers(NodeOperation * /*operation*/,
+ NodeOperationInput *input)
{
if (!input->isConnected())
return;
@@ -476,7 +477,7 @@ void NodeOperationBuilder::add_input_buffers(NodeOperation *operation, NodeOpera
/* check of other end already has write operation, otherwise add a new one */
WriteBufferOperation *writeoperation = find_attached_write_buffer_operation(output);
if (!writeoperation) {
- writeoperation = new WriteBufferOperation();
+ writeoperation = new WriteBufferOperation(output->getDataType());
writeoperation->setbNodeTree(m_context->getbNodeTree());
addOperation(writeoperation);
@@ -486,7 +487,7 @@ void NodeOperationBuilder::add_input_buffers(NodeOperation *operation, NodeOpera
}
/* add readbuffer op for the input */
- ReadBufferOperation *readoperation = new ReadBufferOperation();
+ ReadBufferOperation *readoperation = new ReadBufferOperation(output->getDataType());
readoperation->setMemoryProxy(writeoperation->getMemoryProxy());
this->addOperation(readoperation);
@@ -519,7 +520,7 @@ void NodeOperationBuilder::add_output_buffers(NodeOperation *operation, NodeOper
/* if no write buffer operation exists yet, create a new one */
if (!writeOperation) {
- writeOperation = new WriteBufferOperation();
+ writeOperation = new WriteBufferOperation(operation->getOutputSocket()->getDataType());
writeOperation->setbNodeTree(m_context->getbNodeTree());
addOperation(writeOperation);
@@ -534,7 +535,7 @@ void NodeOperationBuilder::add_output_buffers(NodeOperation *operation, NodeOper
if (&target->getOperation() == writeOperation)
continue; /* skip existing write op links */
- ReadBufferOperation *readoperation = new ReadBufferOperation();
+ ReadBufferOperation *readoperation = new ReadBufferOperation(operation->getOutputSocket()->getDataType());
readoperation->setMemoryProxy(writeOperation->getMemoryProxy());
addOperation(readoperation);
diff --git a/source/blender/compositor/intern/COM_OpenCLDevice.cpp b/source/blender/compositor/intern/COM_OpenCLDevice.cpp
index c5b663d2aef..1c9e59a4b7a 100644
--- a/source/blender/compositor/intern/COM_OpenCLDevice.cpp
+++ b/source/blender/compositor/intern/COM_OpenCLDevice.cpp
@@ -24,6 +24,18 @@
#include "COM_WorkScheduler.h"
typedef enum COM_VendorID {NVIDIA = 0x10DE, AMD = 0x1002} COM_VendorID;
+const cl_image_format IMAGE_FORMAT_COLOR = {
+ CL_RGBA,
+ CL_FLOAT
+};
+const cl_image_format IMAGE_FORMAT_VECTOR = {
+ CL_RGB,
+ CL_FLOAT
+};
+const cl_image_format IMAGE_FORMAT_VALUE = {
+ CL_R,
+ CL_FLOAT
+};
OpenCLDevice::OpenCLDevice(cl_context context, cl_device_id device, cl_program program, cl_int vendorId)
{
@@ -72,6 +84,23 @@ cl_mem OpenCLDevice::COM_clAttachMemoryBufferToKernelParameter(cl_kernel kernel,
return COM_clAttachMemoryBufferToKernelParameter(kernel, parameterIndex, offsetIndex, cleanup, inputMemoryBuffers, (ReadBufferOperation *)reader);
}
+const cl_image_format *OpenCLDevice::determineImageFormat(MemoryBuffer *memoryBuffer)
+{
+ const cl_image_format *imageFormat;
+ int num_channels = memoryBuffer->get_num_channels();
+ if (num_channels == 1) {
+ imageFormat = &IMAGE_FORMAT_VALUE;
+ }
+ else if (num_channels == 3) {
+ imageFormat = &IMAGE_FORMAT_VECTOR;
+ }
+ else {
+ imageFormat = &IMAGE_FORMAT_COLOR;
+ }
+
+ return imageFormat;
+}
+
cl_mem OpenCLDevice::COM_clAttachMemoryBufferToKernelParameter(cl_kernel kernel, int parameterIndex, int offsetIndex,
list<cl_mem> *cleanup, MemoryBuffer **inputMemoryBuffers,
ReadBufferOperation *reader)
@@ -80,12 +109,9 @@ cl_mem OpenCLDevice::COM_clAttachMemoryBufferToKernelParameter(cl_kernel kernel,
MemoryBuffer *result = reader->getInputMemoryBuffer(inputMemoryBuffers);
- const cl_image_format imageFormat = {
- CL_RGBA,
- CL_FLOAT
- };
+ const cl_image_format *imageFormat = determineImageFormat(result);
- cl_mem clBuffer = clCreateImage2D(this->m_context, CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, &imageFormat, result->getWidth(),
+ cl_mem clBuffer = clCreateImage2D(this->m_context, CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, imageFormat, result->getWidth(),
result->getHeight(), 0, result->getBuffer(), &error);
if (error != CL_SUCCESS) { printf("CLERROR[%d]: %s\n", error, clewErrorString(error)); }
@@ -154,7 +180,7 @@ void OpenCLDevice::COM_clEnqueueRange(cl_kernel kernel, MemoryBuffer *outputMemo
bool breaked = false;
for (offsety = 0; offsety < height && (!breaked); offsety += localSize) {
- offset.y = offsety;
+ offset.s[1] = offsety;
if (offsety + localSize < height) {
size[1] = localSize;
}
@@ -169,7 +195,7 @@ void OpenCLDevice::COM_clEnqueueRange(cl_kernel kernel, MemoryBuffer *outputMemo
else {
size[0] = width - offsetx;
}
- offset.x = offsetx;
+ offset.s[0] = offsetx;
error = clSetKernelArg(kernel, offsetIndex, sizeof(cl_int2), &offset);
if (error != CL_SUCCESS) { printf("CLERROR[%d]: %s\n", error, clewErrorString(error)); }
diff --git a/source/blender/compositor/intern/COM_OpenCLDevice.h b/source/blender/compositor/intern/COM_OpenCLDevice.h
index 94df2f2b44c..a513954ee0d 100644
--- a/source/blender/compositor/intern/COM_OpenCLDevice.h
+++ b/source/blender/compositor/intern/COM_OpenCLDevice.h
@@ -94,6 +94,12 @@ public:
*/
void execute(WorkPackage *work);
+ /**
+ * @brief determine an image format
+ * @param memorybuffer
+ */
+ static const cl_image_format *determineImageFormat(MemoryBuffer *memoryBuffer);
+
cl_context getContext() { return this->m_context; }
cl_command_queue getQueue() { return this->m_queue; }
diff --git a/source/blender/compositor/intern/COM_SingleThreadedOperation.cpp b/source/blender/compositor/intern/COM_SingleThreadedOperation.cpp
index c300a85bfa3..b17f5d6b429 100644
--- a/source/blender/compositor/intern/COM_SingleThreadedOperation.cpp
+++ b/source/blender/compositor/intern/COM_SingleThreadedOperation.cpp
@@ -33,7 +33,7 @@ void SingleThreadedOperation::initExecution()
initMutex();
}
-void SingleThreadedOperation::executePixel(float output[4], int x, int y, void *data)
+void SingleThreadedOperation::executePixel(float output[4], int x, int y, void * /*data*/)
{
this->m_cachedInstance->readNoCheck(output, x, y);
}
diff --git a/source/blender/compositor/intern/COM_SocketReader.h b/source/blender/compositor/intern/COM_SocketReader.h
index c996ef5bbeb..ab8a3c06ef5 100644
--- a/source/blender/compositor/intern/COM_SocketReader.h
+++ b/source/blender/compositor/intern/COM_SocketReader.h
@@ -63,7 +63,10 @@ protected:
* @param y the y-coordinate of the pixel to calculate in image space
* @param inputBuffers chunks that can be read by their ReadBufferOperation.
*/
- virtual void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) {}
+ virtual void executePixelSampled(float /*output*/[4],
+ float /*x*/,
+ float /*y*/,
+ PixelSampler /*sampler*/) { }
/**
* @brief calculate a single pixel
@@ -74,7 +77,7 @@ protected:
* @param inputBuffers chunks that can be read by their ReadBufferOperation.
* @param chunkData chunk specific data a during execution time.
*/
- virtual void executePixel(float output[4], int x, int y, void *chunkData) {
+ virtual void executePixel(float output[4], int x, int y, void * /*chunkData*/) {
executePixelSampled(output, x, y, COM_PS_NEAREST);
}
@@ -88,7 +91,9 @@ 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[2], float dy[2], PixelSampler sampler) {}
+ virtual void executePixelFiltered(float /*output*/[4],
+ float /*x*/, float /*y*/,
+ float /*dx*/[2], float /*dy*/[2]) {}
public:
inline void readSampled(float result[4], float x, float y, PixelSampler sampler) {
@@ -97,16 +102,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[2], float dy[2], PixelSampler sampler) {
- executePixelFiltered(result, x, y, dx, dy, sampler);
+ inline void readFiltered(float result[4], float x, float y, float dx[2], float dy[2]) {
+ executePixelFiltered(result, x, y, dx, dy);
}
- virtual void *initializeTileData(rcti *rect) { return 0; }
- virtual void deinitializeTileData(rcti *rect, void *data) {}
+ virtual void *initializeTileData(rcti * /*rect*/) { return 0; }
+ virtual void deinitializeTileData(rcti * /*rect*/, void * /*data*/) {}
virtual ~SocketReader() {}
- virtual MemoryBuffer *getInputMemoryBuffer(MemoryBuffer **memoryBuffers) { return 0; }
+ 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 e1016731c7f..fc6ea1299cf 100644
--- a/source/blender/compositor/intern/COM_WorkScheduler.cpp
+++ b/source/blender/compositor/intern/COM_WorkScheduler.cpp
@@ -111,7 +111,9 @@ static void **g_highlightedNodesRead;
}
#endif /* COM_CURRENT_THREADING_MODEL == COM_TM_QUEUE */
#else
+# if COM_CURRENT_THREADING_MODEL != COM_TM_NOTHREAD
#define HIGHLIGHT(wp) {}
+# endif
#endif
void COM_startReadHighlights()
@@ -196,7 +198,7 @@ void WorkScheduler::schedule(ExecutionGroup *group, int chunkNumber)
BLI_thread_queue_push(g_cpuqueue, package);
}
#else
- BLI_thread_queue_push(cpuqueue, package);
+ BLI_thread_queue_push(g_cpuqueue, package);
#endif
#endif
}
@@ -274,7 +276,10 @@ bool WorkScheduler::hasGPUDevices()
#endif
}
-static void CL_CALLBACK clContextError(const char *errinfo, const void *private_info, size_t cb, void *user_data)
+static void CL_CALLBACK clContextError(const char *errinfo,
+ const void * /*private_info*/,
+ size_t /*cb*/,
+ void * /*user_data*/)
{
printf("OPENCL error: %s\n", errinfo);
}
diff --git a/source/blender/compositor/intern/COM_compositor.cpp b/source/blender/compositor/intern/COM_compositor.cpp
index ec9ef6c7e68..7f7fc141aca 100644
--- a/source/blender/compositor/intern/COM_compositor.cpp
+++ b/source/blender/compositor/intern/COM_compositor.cpp
@@ -45,7 +45,8 @@ static void intern_freeCompositorCaches()
void COM_execute(RenderData *rd, Scene *scene, bNodeTree *editingtree, int rendering,
const ColorManagedViewSettings *viewSettings,
- const ColorManagedDisplaySettings *displaySettings)
+ const ColorManagedDisplaySettings *displaySettings,
+ const char *viewName)
{
/* initialize mutex, TODO this mutex init is actually not thread safe and
* should be done somewhere as part of blender startup, all the other
@@ -77,11 +78,12 @@ void COM_execute(RenderData *rd, Scene *scene, bNodeTree *editingtree, int rende
/* set progress bar to 0% and status to init compositing */
editingtree->progress(editingtree->prh, 0.0);
+ editingtree->stats_draw(editingtree->sdh, (char *)"Compositing");
bool twopass = (editingtree->flag & NTREE_TWO_PASS) > 0 && !rendering;
/* initialize execution system */
if (twopass) {
- ExecutionSystem *system = new ExecutionSystem(rd, scene, editingtree, rendering, twopass, viewSettings, displaySettings);
+ ExecutionSystem *system = new ExecutionSystem(rd, scene, editingtree, rendering, twopass, viewSettings, displaySettings, viewName);
system->execute();
delete system;
@@ -94,7 +96,7 @@ void COM_execute(RenderData *rd, Scene *scene, bNodeTree *editingtree, int rende
}
ExecutionSystem *system = new ExecutionSystem(rd, scene, editingtree, rendering, false,
- viewSettings, displaySettings);
+ viewSettings, displaySettings, viewName);
system->execute();
delete system;
diff --git a/source/blender/compositor/nodes/COM_AlphaOverNode.cpp b/source/blender/compositor/nodes/COM_AlphaOverNode.cpp
index 0306d636c8b..e9b99b6aaf1 100644
--- a/source/blender/compositor/nodes/COM_AlphaOverNode.cpp
+++ b/source/blender/compositor/nodes/COM_AlphaOverNode.cpp
@@ -30,7 +30,7 @@
#include "COM_SetValueOperation.h"
#include "DNA_material_types.h" // the ramp types
-void AlphaOverNode::convertToOperations(NodeConverter &converter, const CompositorContext &context) const
+void AlphaOverNode::convertToOperations(NodeConverter &converter, const CompositorContext &/*context*/) const
{
NodeInput *color1Socket = this->getInputSocket(1);
NodeInput *color2Socket = this->getInputSocket(2);
diff --git a/source/blender/compositor/nodes/COM_BlurNode.cpp b/source/blender/compositor/nodes/COM_BlurNode.cpp
index 76e52c14685..f3d0c33d3b3 100644
--- a/source/blender/compositor/nodes/COM_BlurNode.cpp
+++ b/source/blender/compositor/nodes/COM_BlurNode.cpp
@@ -105,6 +105,7 @@ void BlurNode::convertToOperations(NodeConverter &converter, const CompositorCon
GaussianXBlurOperation *operationx = new GaussianXBlurOperation();
operationx->setData(data);
operationx->setQuality(quality);
+ operationx->checkOpenCL();
converter.addOperation(operationx);
converter.mapInputSocket(getInputSocket(1), operationx->getInputSocket(1));
@@ -112,6 +113,7 @@ void BlurNode::convertToOperations(NodeConverter &converter, const CompositorCon
GaussianYBlurOperation *operationy = new GaussianYBlurOperation();
operationy->setData(data);
operationy->setQuality(quality);
+ operationy->checkOpenCL();
converter.addOperation(operationy);
converter.mapInputSocket(getInputSocket(1), operationy->getInputSocket(1));
diff --git a/source/blender/compositor/nodes/COM_BokehBlurNode.cpp b/source/blender/compositor/nodes/COM_BokehBlurNode.cpp
index 636660bc96c..7ab05e438ec 100644
--- a/source/blender/compositor/nodes/COM_BokehBlurNode.cpp
+++ b/source/blender/compositor/nodes/COM_BokehBlurNode.cpp
@@ -62,8 +62,13 @@ void BokehBlurNode::convertToOperations(NodeConverter &converter, const Composit
converter.addOperation(operation);
converter.mapInputSocket(getInputSocket(0), operation->getInputSocket(0));
converter.mapInputSocket(getInputSocket(1), operation->getInputSocket(1));
- converter.mapInputSocket(getInputSocket(2), operation->getInputSocket(2));
- converter.mapInputSocket(getInputSocket(3), operation->getInputSocket(3));
+
+ // NOTE: on the bokeh blur operation the sockets are switched.
+ // for this reason the next two lines are correct.
+ // Fix for T43771
+ converter.mapInputSocket(getInputSocket(2), operation->getInputSocket(3));
+ converter.mapInputSocket(getInputSocket(3), operation->getInputSocket(2));
+
converter.mapOutputSocket(getOutputSocket(0), operation->getOutputSocket());
if (!connectedSizeSocket) {
diff --git a/source/blender/compositor/nodes/COM_BokehImageNode.cpp b/source/blender/compositor/nodes/COM_BokehImageNode.cpp
index c75e9b16336..7b7cfc812aa 100644
--- a/source/blender/compositor/nodes/COM_BokehImageNode.cpp
+++ b/source/blender/compositor/nodes/COM_BokehImageNode.cpp
@@ -29,7 +29,7 @@ BokehImageNode::BokehImageNode(bNode *editorNode) : Node(editorNode)
/* pass */
}
-void BokehImageNode::convertToOperations(NodeConverter &converter, const CompositorContext &context) const
+void BokehImageNode::convertToOperations(NodeConverter &converter, const CompositorContext &/*context*/) const
{
BokehImageOperation *operation = new BokehImageOperation();
operation->setData((NodeBokehImage *)this->getbNode()->storage);
diff --git a/source/blender/compositor/nodes/COM_BrightnessNode.cpp b/source/blender/compositor/nodes/COM_BrightnessNode.cpp
index e684b569945..053f286c66e 100644
--- a/source/blender/compositor/nodes/COM_BrightnessNode.cpp
+++ b/source/blender/compositor/nodes/COM_BrightnessNode.cpp
@@ -29,7 +29,7 @@ BrightnessNode::BrightnessNode(bNode *editorNode) : Node(editorNode)
/* pass */
}
-void BrightnessNode::convertToOperations(NodeConverter &converter, const CompositorContext &context) const
+void BrightnessNode::convertToOperations(NodeConverter &converter, const CompositorContext &/*context*/) const
{
BrightnessOperation *operation = new BrightnessOperation();
converter.addOperation(operation);
diff --git a/source/blender/compositor/nodes/COM_ChannelMatteNode.cpp b/source/blender/compositor/nodes/COM_ChannelMatteNode.cpp
index f356c74cd49..cc573274c34 100644
--- a/source/blender/compositor/nodes/COM_ChannelMatteNode.cpp
+++ b/source/blender/compositor/nodes/COM_ChannelMatteNode.cpp
@@ -30,44 +30,48 @@ ChannelMatteNode::ChannelMatteNode(bNode *editorNode) : Node(editorNode)
/* pass */
}
-void ChannelMatteNode::convertToOperations(NodeConverter &converter, const CompositorContext &context) const
+void ChannelMatteNode::convertToOperations(NodeConverter &converter, const CompositorContext &/*context*/) const
{
bNode *node = this->getbNode();
-
+
NodeInput *inputSocketImage = this->getInputSocket(0);
NodeOutput *outputSocketImage = this->getOutputSocket(0);
NodeOutput *outputSocketMatte = this->getOutputSocket(1);
-
- NodeOperation *convert = NULL;
+
+ NodeOperation *convert = NULL, *inv_convert = NULL;
/* colorspace */
switch (node->custom1) {
case CMP_NODE_CHANNEL_MATTE_CS_RGB:
break;
case CMP_NODE_CHANNEL_MATTE_CS_HSV: /* HSV */
convert = new ConvertRGBToHSVOperation();
+ inv_convert = new ConvertHSVToRGBOperation();
break;
case CMP_NODE_CHANNEL_MATTE_CS_YUV: /* YUV */
convert = new ConvertRGBToYUVOperation();
+ inv_convert = new ConvertYUVToRGBOperation();
break;
case CMP_NODE_CHANNEL_MATTE_CS_YCC: /* YCC */
convert = new ConvertRGBToYCCOperation();
((ConvertRGBToYCCOperation *)convert)->setMode(0); /* BLI_YCC_ITU_BT601 */
+ inv_convert = new ConvertYCCToRGBOperation();
+ ((ConvertYCCToRGBOperation *)inv_convert)->setMode(0); /* BLI_YCC_ITU_BT601 */
break;
default:
break;
}
-
+
ChannelMatteOperation *operation = new ChannelMatteOperation();
/* pass the ui properties to the operation */
operation->setSettings((NodeChroma *)node->storage, node->custom2);
converter.addOperation(operation);
-
+
SetAlphaOperation *operationAlpha = new SetAlphaOperation();
converter.addOperation(operationAlpha);
-
- if (convert) {
+
+ if (convert != NULL) {
converter.addOperation(convert);
-
+
converter.mapInputSocket(inputSocketImage, convert->getInputSocket(0));
converter.addLink(convert->getOutputSocket(), operation->getInputSocket(0));
converter.addLink(convert->getOutputSocket(), operationAlpha->getInputSocket(0));
@@ -76,11 +80,18 @@ void ChannelMatteNode::convertToOperations(NodeConverter &converter, const Compo
converter.mapInputSocket(inputSocketImage, operation->getInputSocket(0));
converter.mapInputSocket(inputSocketImage, operationAlpha->getInputSocket(0));
}
-
+
converter.mapOutputSocket(outputSocketMatte, operation->getOutputSocket(0));
-
converter.addLink(operation->getOutputSocket(), operationAlpha->getInputSocket(1));
- converter.mapOutputSocket(outputSocketImage, operationAlpha->getOutputSocket());
-
- converter.addPreview(operationAlpha->getOutputSocket());
+
+ if (inv_convert != NULL) {
+ converter.addOperation(inv_convert);
+ converter.addLink(operationAlpha->getOutputSocket(0), inv_convert->getInputSocket(0));
+ converter.mapOutputSocket(outputSocketImage, inv_convert->getOutputSocket());
+ converter.addPreview(inv_convert->getOutputSocket());
+ }
+ else {
+ converter.mapOutputSocket(outputSocketImage, operationAlpha->getOutputSocket());
+ converter.addPreview(operationAlpha->getOutputSocket());
+ }
}
diff --git a/source/blender/compositor/nodes/COM_ChromaMatteNode.cpp b/source/blender/compositor/nodes/COM_ChromaMatteNode.cpp
index 90de9358587..6324ca9a3ca 100644
--- a/source/blender/compositor/nodes/COM_ChromaMatteNode.cpp
+++ b/source/blender/compositor/nodes/COM_ChromaMatteNode.cpp
@@ -30,7 +30,7 @@ ChromaMatteNode::ChromaMatteNode(bNode *editorNode) : Node(editorNode)
/* pass */
}
-void ChromaMatteNode::convertToOperations(NodeConverter &converter, const CompositorContext &context) const
+void ChromaMatteNode::convertToOperations(NodeConverter &converter, const CompositorContext &/*context*/) const
{
bNode *editorsnode = getbNode();
diff --git a/source/blender/compositor/nodes/COM_ColorBalanceNode.cpp b/source/blender/compositor/nodes/COM_ColorBalanceNode.cpp
index fc0df046e86..a531493d486 100644
--- a/source/blender/compositor/nodes/COM_ColorBalanceNode.cpp
+++ b/source/blender/compositor/nodes/COM_ColorBalanceNode.cpp
@@ -32,7 +32,7 @@ ColorBalanceNode::ColorBalanceNode(bNode *editorNode) : Node(editorNode)
/* pass */
}
-void ColorBalanceNode::convertToOperations(NodeConverter &converter, const CompositorContext &context) const
+void ColorBalanceNode::convertToOperations(NodeConverter &converter, const CompositorContext &/*context*/) const
{
bNode *node = this->getbNode();
NodeColorBalance *n = (NodeColorBalance *)node->storage;
diff --git a/source/blender/compositor/nodes/COM_ColorCorrectionNode.cpp b/source/blender/compositor/nodes/COM_ColorCorrectionNode.cpp
index 728b51b8dc1..e926d131c1a 100644
--- a/source/blender/compositor/nodes/COM_ColorCorrectionNode.cpp
+++ b/source/blender/compositor/nodes/COM_ColorCorrectionNode.cpp
@@ -29,7 +29,7 @@ ColorCorrectionNode::ColorCorrectionNode(bNode *editorNode) : Node(editorNode)
/* pass */
}
-void ColorCorrectionNode::convertToOperations(NodeConverter &converter, const CompositorContext &context) const
+void ColorCorrectionNode::convertToOperations(NodeConverter &converter, const CompositorContext &/*context*/) const
{
bNode *editorNode = getbNode();
diff --git a/source/blender/compositor/nodes/COM_ColorCurveNode.cpp b/source/blender/compositor/nodes/COM_ColorCurveNode.cpp
index 6dc936302f4..5a4dc79e6b2 100644
--- a/source/blender/compositor/nodes/COM_ColorCurveNode.cpp
+++ b/source/blender/compositor/nodes/COM_ColorCurveNode.cpp
@@ -29,7 +29,7 @@ ColorCurveNode::ColorCurveNode(bNode *editorNode) : Node(editorNode)
/* pass */
}
-void ColorCurveNode::convertToOperations(NodeConverter &converter, const CompositorContext &context) const
+void ColorCurveNode::convertToOperations(NodeConverter &converter, const CompositorContext &/*context*/) const
{
if (this->getInputSocket(2)->isLinked() || this->getInputSocket(3)->isLinked()) {
ColorCurveOperation *operation = new ColorCurveOperation();
diff --git a/source/blender/compositor/nodes/COM_ColorMatteNode.cpp b/source/blender/compositor/nodes/COM_ColorMatteNode.cpp
index def3b18e0fe..f7c20894087 100644
--- a/source/blender/compositor/nodes/COM_ColorMatteNode.cpp
+++ b/source/blender/compositor/nodes/COM_ColorMatteNode.cpp
@@ -30,7 +30,7 @@ ColorMatteNode::ColorMatteNode(bNode *editorNode) : Node(editorNode)
/* pass */
}
-void ColorMatteNode::convertToOperations(NodeConverter &converter, const CompositorContext &context) const
+void ColorMatteNode::convertToOperations(NodeConverter &converter, const CompositorContext &/*context*/) const
{
bNode *editorsnode = getbNode();
diff --git a/source/blender/compositor/nodes/COM_ColorNode.cpp b/source/blender/compositor/nodes/COM_ColorNode.cpp
index 4106cb64798..c3770e79dea 100644
--- a/source/blender/compositor/nodes/COM_ColorNode.cpp
+++ b/source/blender/compositor/nodes/COM_ColorNode.cpp
@@ -29,7 +29,7 @@ ColorNode::ColorNode(bNode *editorNode) : Node(editorNode)
/* pass */
}
-void ColorNode::convertToOperations(NodeConverter &converter, const CompositorContext &context) const
+void ColorNode::convertToOperations(NodeConverter &converter, const CompositorContext &/*context*/) const
{
SetColorOperation *operation = new SetColorOperation();
NodeOutput *output = this->getOutputSocket(0);
diff --git a/source/blender/compositor/nodes/COM_ColorRampNode.cpp b/source/blender/compositor/nodes/COM_ColorRampNode.cpp
index a61ddffbf35..1feaa88bebb 100644
--- a/source/blender/compositor/nodes/COM_ColorRampNode.cpp
+++ b/source/blender/compositor/nodes/COM_ColorRampNode.cpp
@@ -32,7 +32,7 @@ ColorRampNode::ColorRampNode(bNode *editorNode) : Node(editorNode)
/* pass */
}
-void ColorRampNode::convertToOperations(NodeConverter &converter, const CompositorContext &context) const
+void ColorRampNode::convertToOperations(NodeConverter &converter, const CompositorContext &/*context*/) const
{
NodeInput *inputSocket = this->getInputSocket(0);
NodeOutput *outputSocket = this->getOutputSocket(0);
diff --git a/source/blender/compositor/nodes/COM_ColorSpillNode.cpp b/source/blender/compositor/nodes/COM_ColorSpillNode.cpp
index 82454ba7979..f33f2858397 100644
--- a/source/blender/compositor/nodes/COM_ColorSpillNode.cpp
+++ b/source/blender/compositor/nodes/COM_ColorSpillNode.cpp
@@ -29,7 +29,7 @@ ColorSpillNode::ColorSpillNode(bNode *editorNode) : Node(editorNode)
/* pass */
}
-void ColorSpillNode::convertToOperations(NodeConverter &converter, const CompositorContext &context) const
+void ColorSpillNode::convertToOperations(NodeConverter &converter, const CompositorContext &/*context*/) const
{
bNode *editorsnode = getbNode();
@@ -38,16 +38,10 @@ void ColorSpillNode::convertToOperations(NodeConverter &converter, const Composi
NodeOutput *outputSocketImage = this->getOutputSocket(0);
ColorSpillOperation *operation;
- if (editorsnode->custom2 == 0) {
- // Simple color spill
- operation = new ColorSpillOperation();
- }
- else {
- // Average color spill
- operation = new ColorSpillAverageOperation();
- }
+ operation = new ColorSpillOperation();
operation->setSettings((NodeColorspill *)editorsnode->storage);
operation->setSpillChannel(editorsnode->custom1 - 1); // Channel for spilling
+ operation->setSpillMethod(editorsnode->custom2); // Channel method
converter.addOperation(operation);
converter.mapInputSocket(inputSocketImage, operation->getInputSocket(0));
diff --git a/source/blender/compositor/nodes/COM_ColorToBWNode.cpp b/source/blender/compositor/nodes/COM_ColorToBWNode.cpp
index a1616a61b4b..f09c6bac3ee 100644
--- a/source/blender/compositor/nodes/COM_ColorToBWNode.cpp
+++ b/source/blender/compositor/nodes/COM_ColorToBWNode.cpp
@@ -30,7 +30,7 @@ ColorToBWNode::ColorToBWNode(bNode *editorNode) : Node(editorNode)
/* pass */
}
-void ColorToBWNode::convertToOperations(NodeConverter &converter, const CompositorContext &context) const
+void ColorToBWNode::convertToOperations(NodeConverter &converter, const CompositorContext &/*context*/) const
{
NodeInput *colorSocket = this->getInputSocket(0);
NodeOutput *valueSocket = this->getOutputSocket(0);
diff --git a/source/blender/compositor/nodes/COM_CombineColorNode.cpp b/source/blender/compositor/nodes/COM_CombineColorNode.cpp
index c7a3baf809d..a39e946fe5f 100644
--- a/source/blender/compositor/nodes/COM_CombineColorNode.cpp
+++ b/source/blender/compositor/nodes/COM_CombineColorNode.cpp
@@ -72,17 +72,17 @@ void CombineColorNode::convertToOperations(NodeConverter &converter, const Compo
}
-NodeOperation *CombineRGBANode::getColorConverter(const CompositorContext &context) const
+NodeOperation *CombineRGBANode::getColorConverter(const CompositorContext &/*context*/) const
{
return NULL; /* no conversion needed */
}
-NodeOperation *CombineHSVANode::getColorConverter(const CompositorContext &context) const
+NodeOperation *CombineHSVANode::getColorConverter(const CompositorContext &/*context*/) const
{
return new ConvertHSVToRGBOperation();
}
-NodeOperation *CombineYCCANode::getColorConverter(const CompositorContext &context) const
+NodeOperation *CombineYCCANode::getColorConverter(const CompositorContext &/*context*/) const
{
ConvertYCCToRGBOperation *operation = new ConvertYCCToRGBOperation();
bNode *editorNode = this->getbNode();
@@ -90,7 +90,7 @@ NodeOperation *CombineYCCANode::getColorConverter(const CompositorContext &conte
return operation;
}
-NodeOperation *CombineYUVANode::getColorConverter(const CompositorContext &context) const
+NodeOperation *CombineYUVANode::getColorConverter(const CompositorContext &/*context*/) const
{
return new ConvertYUVToRGBOperation();
}
diff --git a/source/blender/compositor/nodes/COM_CompositorNode.cpp b/source/blender/compositor/nodes/COM_CompositorNode.cpp
index 3d79eb693ea..9e8b40d8af4 100644
--- a/source/blender/compositor/nodes/COM_CompositorNode.cpp
+++ b/source/blender/compositor/nodes/COM_CompositorNode.cpp
@@ -34,7 +34,7 @@ void CompositorNode::convertToOperations(NodeConverter &converter, const Composi
bNode *editorNode = this->getbNode();
bool is_active = (editorNode->flag & NODE_DO_OUTPUT_RECALC) ||
context.isRendering();
- bool ignore_alpha = editorNode->custom2 & CMP_NODE_OUTPUT_IGNORE_ALPHA;
+ bool ignore_alpha = (editorNode->custom2 & CMP_NODE_OUTPUT_IGNORE_ALPHA) != 0;
NodeInput *imageSocket = this->getInputSocket(0);
NodeInput *alphaSocket = this->getInputSocket(1);
@@ -43,6 +43,7 @@ void CompositorNode::convertToOperations(NodeConverter &converter, const Composi
CompositorOperation *compositorOperation = new CompositorOperation();
compositorOperation->setSceneName(context.getScene()->id.name);
compositorOperation->setRenderData(context.getRenderData());
+ compositorOperation->setViewName(context.getViewName());
compositorOperation->setbNodeTree(context.getbNodeTree());
/* alpha socket gives either 1 or a custom alpha value if "use alpha" is enabled */
compositorOperation->setUseAlphaInput(ignore_alpha || alphaSocket->isLinked());
diff --git a/source/blender/compositor/nodes/COM_ConvertAlphaNode.cpp b/source/blender/compositor/nodes/COM_ConvertAlphaNode.cpp
index ba31ed6e89c..fbf5dbb6253 100644
--- a/source/blender/compositor/nodes/COM_ConvertAlphaNode.cpp
+++ b/source/blender/compositor/nodes/COM_ConvertAlphaNode.cpp
@@ -23,7 +23,7 @@
#include "COM_ConvertOperation.h"
#include "COM_ExecutionSystem.h"
-void ConvertAlphaNode::convertToOperations(NodeConverter &converter, const CompositorContext &context) const
+void ConvertAlphaNode::convertToOperations(NodeConverter &converter, const CompositorContext &/*context*/) const
{
NodeOperation *operation = NULL;
bNode *node = this->getbNode();
diff --git a/source/blender/compositor/nodes/COM_CornerPinNode.cpp b/source/blender/compositor/nodes/COM_CornerPinNode.cpp
index ea9f22f2840..5e4e463595a 100644
--- a/source/blender/compositor/nodes/COM_CornerPinNode.cpp
+++ b/source/blender/compositor/nodes/COM_CornerPinNode.cpp
@@ -28,7 +28,7 @@ CornerPinNode::CornerPinNode(bNode *editorNode) : Node(editorNode)
{
}
-void CornerPinNode::convertToOperations(NodeConverter &converter, const CompositorContext &context) const
+void CornerPinNode::convertToOperations(NodeConverter &converter, const CompositorContext &/*context*/) const
{
NodeInput *input_image = this->getInputSocket(0);
/* note: socket order differs between UI node and operations:
diff --git a/source/blender/compositor/nodes/COM_CropNode.cpp b/source/blender/compositor/nodes/COM_CropNode.cpp
index 6c3dc93481b..ee148f41c68 100644
--- a/source/blender/compositor/nodes/COM_CropNode.cpp
+++ b/source/blender/compositor/nodes/COM_CropNode.cpp
@@ -29,7 +29,7 @@ CropNode::CropNode(bNode *editorNode) : Node(editorNode)
/* pass */
}
-void CropNode::convertToOperations(NodeConverter &converter, const CompositorContext &context) const
+void CropNode::convertToOperations(NodeConverter &converter, const CompositorContext &/*context*/) const
{
bNode *node = getbNode();
NodeTwoXYs *cropSettings = (NodeTwoXYs *)node->storage;
diff --git a/source/blender/compositor/nodes/COM_DespeckleNode.cpp b/source/blender/compositor/nodes/COM_DespeckleNode.cpp
index bac6337374f..a21885bf42d 100644
--- a/source/blender/compositor/nodes/COM_DespeckleNode.cpp
+++ b/source/blender/compositor/nodes/COM_DespeckleNode.cpp
@@ -29,7 +29,7 @@ DespeckleNode::DespeckleNode(bNode *editorNode) : Node(editorNode)
/* pass */
}
-void DespeckleNode::convertToOperations(NodeConverter &converter, const CompositorContext &context) const
+void DespeckleNode::convertToOperations(NodeConverter &converter, const CompositorContext &/*context*/) const
{
bNode *editorNode = this->getbNode();
NodeInput *inputSocket = this->getInputSocket(0);
diff --git a/source/blender/compositor/nodes/COM_DifferenceMatteNode.cpp b/source/blender/compositor/nodes/COM_DifferenceMatteNode.cpp
index 8870badab09..2cb0e2301ac 100644
--- a/source/blender/compositor/nodes/COM_DifferenceMatteNode.cpp
+++ b/source/blender/compositor/nodes/COM_DifferenceMatteNode.cpp
@@ -30,7 +30,7 @@ DifferenceMatteNode::DifferenceMatteNode(bNode *editorNode) : Node(editorNode)
/* pass */
}
-void DifferenceMatteNode::convertToOperations(NodeConverter &converter, const CompositorContext &context) const
+void DifferenceMatteNode::convertToOperations(NodeConverter &converter, const CompositorContext &/*context*/) const
{
NodeInput *inputSocket = this->getInputSocket(0);
NodeInput *inputSocket2 = this->getInputSocket(1);
diff --git a/source/blender/compositor/nodes/COM_DistanceMatteNode.cpp b/source/blender/compositor/nodes/COM_DistanceMatteNode.cpp
index 704c704c500..99061cf8824 100644
--- a/source/blender/compositor/nodes/COM_DistanceMatteNode.cpp
+++ b/source/blender/compositor/nodes/COM_DistanceMatteNode.cpp
@@ -31,7 +31,7 @@ DistanceMatteNode::DistanceMatteNode(bNode *editorNode) : Node(editorNode)
/* pass */
}
-void DistanceMatteNode::convertToOperations(NodeConverter &converter, const CompositorContext &context) const
+void DistanceMatteNode::convertToOperations(NodeConverter &converter, const CompositorContext &/*context*/) const
{
bNode *editorsnode = getbNode();
NodeChroma *storage = (NodeChroma *)editorsnode->storage;
@@ -66,6 +66,8 @@ void DistanceMatteNode::convertToOperations(NodeConverter &converter, const Comp
ConvertRGBToYCCOperation *operationYCCImage = new ConvertRGBToYCCOperation();
ConvertRGBToYCCOperation *operationYCCMatte = new ConvertRGBToYCCOperation();
+ operationYCCImage->setMode(0); /* BLI_YCC_ITU_BT601 */
+ operationYCCMatte->setMode(0); /* BLI_YCC_ITU_BT601 */
converter.addOperation(operationYCCImage);
converter.addOperation(operationYCCMatte);
@@ -79,10 +81,20 @@ void DistanceMatteNode::convertToOperations(NodeConverter &converter, const Comp
operation = matte;
}
+ converter.mapOutputSocket(outputSocketMatte, operation->getOutputSocket(0));
converter.addLink(operation->getOutputSocket(), operationAlpha->getInputSocket(1));
- converter.mapOutputSocket(outputSocketMatte, operation->getOutputSocket());
- converter.mapOutputSocket(outputSocketImage, operationAlpha->getOutputSocket());
-
- converter.addPreview(operationAlpha->getOutputSocket());
+ if (storage->channel != 1) {
+ ConvertYCCToRGBOperation *inv_convert = new ConvertYCCToRGBOperation();
+ inv_convert->setMode(0); /* BLI_YCC_ITU_BT601 */
+
+ converter.addOperation(inv_convert);
+ converter.addLink(operationAlpha->getOutputSocket(0), inv_convert->getInputSocket(0));
+ converter.mapOutputSocket(outputSocketImage, inv_convert->getOutputSocket());
+ converter.addPreview(inv_convert->getOutputSocket());
+ }
+ else {
+ converter.mapOutputSocket(outputSocketImage, operationAlpha->getOutputSocket());
+ converter.addPreview(operationAlpha->getOutputSocket());
+ }
}
diff --git a/source/blender/compositor/nodes/COM_DoubleEdgeMaskNode.cpp b/source/blender/compositor/nodes/COM_DoubleEdgeMaskNode.cpp
index 1f80eeadf83..c67abb1ab99 100644
--- a/source/blender/compositor/nodes/COM_DoubleEdgeMaskNode.cpp
+++ b/source/blender/compositor/nodes/COM_DoubleEdgeMaskNode.cpp
@@ -29,7 +29,7 @@ DoubleEdgeMaskNode::DoubleEdgeMaskNode(bNode *editorNode) : Node(editorNode)
/* pass */
}
-void DoubleEdgeMaskNode::convertToOperations(NodeConverter &converter, const CompositorContext &context) const
+void DoubleEdgeMaskNode::convertToOperations(NodeConverter &converter, const CompositorContext &/*context*/) const
{
DoubleEdgeMaskOperation *operation;
bNode *bnode = this->getbNode();
diff --git a/source/blender/compositor/nodes/COM_FilterNode.cpp b/source/blender/compositor/nodes/COM_FilterNode.cpp
index 9f3a7ae795c..7493f24ba6b 100644
--- a/source/blender/compositor/nodes/COM_FilterNode.cpp
+++ b/source/blender/compositor/nodes/COM_FilterNode.cpp
@@ -32,7 +32,7 @@ FilterNode::FilterNode(bNode *editorNode) : Node(editorNode)
/* pass */
}
-void FilterNode::convertToOperations(NodeConverter &converter, const CompositorContext &context) const
+void FilterNode::convertToOperations(NodeConverter &converter, const CompositorContext &/*context*/) const
{
NodeInput *inputSocket = this->getInputSocket(0);
NodeInput *inputImageSocket = this->getInputSocket(1);
diff --git a/source/blender/compositor/nodes/COM_FlipNode.cpp b/source/blender/compositor/nodes/COM_FlipNode.cpp
index 1dbcc97143e..0177dc7017a 100644
--- a/source/blender/compositor/nodes/COM_FlipNode.cpp
+++ b/source/blender/compositor/nodes/COM_FlipNode.cpp
@@ -30,7 +30,7 @@ FlipNode::FlipNode(bNode *editorNode) : Node(editorNode)
/* pass */
}
-void FlipNode::convertToOperations(NodeConverter &converter, const CompositorContext &context) const
+void FlipNode::convertToOperations(NodeConverter &converter, const CompositorContext &/*context*/) const
{
NodeInput *inputSocket = this->getInputSocket(0);
NodeOutput *outputSocket = this->getOutputSocket(0);
diff --git a/source/blender/compositor/nodes/COM_GammaNode.cpp b/source/blender/compositor/nodes/COM_GammaNode.cpp
index 046cd9e9a0d..bf24bee55d3 100644
--- a/source/blender/compositor/nodes/COM_GammaNode.cpp
+++ b/source/blender/compositor/nodes/COM_GammaNode.cpp
@@ -29,7 +29,7 @@ GammaNode::GammaNode(bNode *editorNode) : Node(editorNode)
/* pass */
}
-void GammaNode::convertToOperations(NodeConverter &converter, const CompositorContext &context) const
+void GammaNode::convertToOperations(NodeConverter &converter, const CompositorContext &/*context*/) const
{
GammaOperation *operation = new GammaOperation();
converter.addOperation(operation);
diff --git a/source/blender/compositor/nodes/COM_GlareNode.cpp b/source/blender/compositor/nodes/COM_GlareNode.cpp
index 0429a1a80cf..7afe1510ae4 100644
--- a/source/blender/compositor/nodes/COM_GlareNode.cpp
+++ b/source/blender/compositor/nodes/COM_GlareNode.cpp
@@ -36,7 +36,7 @@ GlareNode::GlareNode(bNode *editorNode) : Node(editorNode)
/* pass */
}
-void GlareNode::convertToOperations(NodeConverter &converter, const CompositorContext &context) const
+void GlareNode::convertToOperations(NodeConverter &converter, const CompositorContext &/*context*/) const
{
bNode *node = this->getbNode();
NodeGlare *glare = (NodeGlare *)node->storage;
diff --git a/source/blender/compositor/nodes/COM_HueSaturationValueCorrectNode.cpp b/source/blender/compositor/nodes/COM_HueSaturationValueCorrectNode.cpp
index 003bc91edd3..e159886bb46 100644
--- a/source/blender/compositor/nodes/COM_HueSaturationValueCorrectNode.cpp
+++ b/source/blender/compositor/nodes/COM_HueSaturationValueCorrectNode.cpp
@@ -36,7 +36,7 @@ HueSaturationValueCorrectNode::HueSaturationValueCorrectNode(bNode *editorNode)
/* pass */
}
-void HueSaturationValueCorrectNode::convertToOperations(NodeConverter &converter, const CompositorContext &context) const
+void HueSaturationValueCorrectNode::convertToOperations(NodeConverter &converter, const CompositorContext &/*context*/) const
{
NodeInput *valueSocket = this->getInputSocket(0);
NodeInput *colorSocket = this->getInputSocket(1);
diff --git a/source/blender/compositor/nodes/COM_HueSaturationValueNode.cpp b/source/blender/compositor/nodes/COM_HueSaturationValueNode.cpp
index cdec1250c6e..29c296a896d 100644
--- a/source/blender/compositor/nodes/COM_HueSaturationValueNode.cpp
+++ b/source/blender/compositor/nodes/COM_HueSaturationValueNode.cpp
@@ -35,7 +35,7 @@ HueSaturationValueNode::HueSaturationValueNode(bNode *editorNode) : Node(editorN
/* pass */
}
-void HueSaturationValueNode::convertToOperations(NodeConverter &converter, const CompositorContext &context) const
+void HueSaturationValueNode::convertToOperations(NodeConverter &converter, const CompositorContext &/*context*/) const
{
NodeInput *valueSocket = this->getInputSocket(0);
NodeInput *colorSocket = this->getInputSocket(1);
diff --git a/source/blender/compositor/nodes/COM_ImageNode.cpp b/source/blender/compositor/nodes/COM_ImageNode.cpp
index e105f530eb2..facd422c217 100644
--- a/source/blender/compositor/nodes/COM_ImageNode.cpp
+++ b/source/blender/compositor/nodes/COM_ImageNode.cpp
@@ -32,6 +32,7 @@
#include "COM_SetValueOperation.h"
#include "COM_SetVectorOperation.h"
#include "COM_SetColorOperation.h"
+#include "COM_SeparateColorNode.h"
ImageNode::ImageNode(bNode *editorNode) : Node(editorNode)
{
@@ -39,19 +40,19 @@ ImageNode::ImageNode(bNode *editorNode) : Node(editorNode)
}
NodeOperation *ImageNode::doMultilayerCheck(NodeConverter &converter, RenderLayer *rl, Image *image, ImageUser *user,
- int framenumber, int outputsocketIndex, int passindex, DataType datatype) const
+ int framenumber, int outputsocketIndex, int passindex, int view, DataType datatype) const
{
NodeOutput *outputSocket = this->getOutputSocket(outputsocketIndex);
MultilayerBaseOperation *operation = NULL;
switch (datatype) {
case COM_DT_VALUE:
- operation = new MultilayerValueOperation(passindex);
+ operation = new MultilayerValueOperation(passindex, view);
break;
case COM_DT_VECTOR:
- operation = new MultilayerVectorOperation(passindex);
+ operation = new MultilayerVectorOperation(passindex, view);
break;
case COM_DT_COLOR:
- operation = new MultilayerColorOperation(passindex);
+ operation = new MultilayerColorOperation(passindex, view);
break;
default:
break;
@@ -78,7 +79,6 @@ void ImageNode::convertToOperations(NodeConverter &converter, const CompositorCo
int numberOfOutputs = this->getNumberOfOutputSockets();
bool outputStraightAlpha = (editorNode->custom1 & CMP_NODE_IMAGE_USE_STRAIGHT_OUTPUT) != 0;
BKE_image_user_frame_calc(imageuser, context.getFramenumber(), 0);
-
/* force a load, we assume iuser index will be set OK anyway */
if (image && image->type == IMA_TYPE_MULTILAYER) {
bool is_multilayer_ok = false;
@@ -95,6 +95,9 @@ void ImageNode::convertToOperations(NodeConverter &converter, const CompositorCo
NodeOperation *operation = NULL;
socket = this->getOutputSocket(index);
bNodeSocket *bnodeSocket = socket->getbNodeSocket();
+ RenderPass *rpass = (RenderPass *)BLI_findstring(&rl->passes, bnodeSocket->identifier, offsetof(RenderPass, internal_name));
+ int view = 0;
+
/* Passes in the file can differ from passes stored in sockets (#36755).
* Look up the correct file pass using the socket identifier instead.
*/
@@ -103,35 +106,61 @@ void ImageNode::convertToOperations(NodeConverter &converter, const CompositorCo
int passindex = storage->pass_index;*/
RenderPass *rpass = (RenderPass *)BLI_findlink(&rl->passes, passindex);
#endif
- int passindex;
- RenderPass *rpass;
- for (rpass = (RenderPass *)rl->passes.first, passindex = 0; rpass; rpass = rpass->next, ++passindex)
- if (STREQ(rpass->name, bnodeSocket->identifier))
- break;
+
+ /* returns the image view to use for the current active view */
+ if (BLI_listbase_count_ex(&image->rr->views, 2) > 1) {
+ const int view_image = imageuser->view;
+ const bool is_allview = (view_image == 0); /* if view selected == All (0) */
+
+ if (is_allview) {
+ /* heuristic to match image name with scene names
+ * check if the view name exists in the image */
+ view = BLI_findstringindex(&image->rr->views, context.getViewName(), offsetof(RenderView, name));
+ if (view == -1) view = 0;
+ }
+ else {
+ view = view_image - 1;
+ }
+ }
+
if (rpass) {
- imageuser->pass = passindex;
+ int passindex = BLI_findindex(&rl->passes, rpass);
switch (rpass->channels) {
case 1:
- operation = doMultilayerCheck(converter, rl, image, imageuser, framenumber, index, passindex, COM_DT_VALUE);
+ operation = doMultilayerCheck(converter, rl, image, imageuser, framenumber, index,
+ passindex, view, COM_DT_VALUE);
break;
/* using image operations for both 3 and 4 channels (RGB and RGBA respectively) */
/* XXX any way to detect actual vector images? */
case 3:
- operation = doMultilayerCheck(converter, rl, image, imageuser, framenumber, index, passindex, COM_DT_VECTOR);
+ operation = doMultilayerCheck(converter, rl, image, imageuser, framenumber, index,
+ passindex, view, COM_DT_VECTOR);
break;
case 4:
- operation = doMultilayerCheck(converter, rl, image, imageuser, framenumber, index, passindex, COM_DT_COLOR);
+ operation = doMultilayerCheck(converter, rl, image, imageuser, framenumber, index,
+ passindex, view, COM_DT_COLOR);
break;
default:
/* dummy operation is added below */
break;
}
-
if (index == 0 && operation) {
converter.addPreview(operation->getOutputSocket());
}
+ if (rpass->passtype == SCE_PASS_COMBINED) {
+ BLI_assert(operation != NULL);
+ BLI_assert(index < numberOfOutputs - 1);
+ NodeOutput *outputSocket = this->getOutputSocket(index + 1);
+ SeparateChannelOperation *separate_operation;
+ separate_operation = new SeparateChannelOperation();
+ separate_operation->setChannel(3);
+ converter.addOperation(separate_operation);
+ converter.addLink(operation->getOutputSocket(), separate_operation->getInputSocket(0));
+ converter.mapOutputSocket(outputSocket, separate_operation->getOutputSocket());
+ index++;
+ }
}
-
+
/* incase we can't load the layer */
if (operation == NULL)
converter.setInvalidOutput(getOutputSocket(index));
@@ -152,6 +181,8 @@ void ImageNode::convertToOperations(NodeConverter &converter, const CompositorCo
operation->setImage(image);
operation->setImageUser(imageuser);
operation->setFramenumber(framenumber);
+ operation->setRenderData(context.getRenderData());
+ operation->setViewName(context.getViewName());
converter.addOperation(operation);
if (outputStraightAlpha) {
@@ -174,6 +205,8 @@ void ImageNode::convertToOperations(NodeConverter &converter, const CompositorCo
alphaOperation->setImage(image);
alphaOperation->setImageUser(imageuser);
alphaOperation->setFramenumber(framenumber);
+ alphaOperation->setRenderData(context.getRenderData());
+ alphaOperation->setViewName(context.getViewName());
converter.addOperation(alphaOperation);
converter.mapOutputSocket(alphaImage, alphaOperation->getOutputSocket());
@@ -184,6 +217,8 @@ void ImageNode::convertToOperations(NodeConverter &converter, const CompositorCo
depthOperation->setImage(image);
depthOperation->setImageUser(imageuser);
depthOperation->setFramenumber(framenumber);
+ depthOperation->setRenderData(context.getRenderData());
+ depthOperation->setViewName(context.getViewName());
converter.addOperation(depthOperation);
converter.mapOutputSocket(depthImage, depthOperation->getOutputSocket());
@@ -223,6 +258,7 @@ void ImageNode::convertToOperations(NodeConverter &converter, const CompositorCo
}
if (operation) {
+ /* not supporting multiview for this generic case */
converter.addOperation(operation);
converter.mapOutputSocket(output, operation->getOutputSocket());
}
diff --git a/source/blender/compositor/nodes/COM_ImageNode.h b/source/blender/compositor/nodes/COM_ImageNode.h
index 1daa39a2a1f..267794510e1 100644
--- a/source/blender/compositor/nodes/COM_ImageNode.h
+++ b/source/blender/compositor/nodes/COM_ImageNode.h
@@ -36,7 +36,7 @@ extern "C" {
class ImageNode : public Node {
private:
NodeOperation *doMultilayerCheck(NodeConverter &converter, RenderLayer *rl, Image *image, ImageUser *user,
- int framenumber, int outputsocketIndex, int passindex, DataType datatype) const;
+ int framenumber, int outputsocketIndex, int passtype, int view, DataType datatype) const;
public:
ImageNode(bNode *editorNode);
void convertToOperations(NodeConverter &converter, const CompositorContext &context) const;
diff --git a/source/blender/compositor/nodes/COM_InpaintNode.cpp b/source/blender/compositor/nodes/COM_InpaintNode.cpp
index 1371cdb5f1d..9e78625684d 100644
--- a/source/blender/compositor/nodes/COM_InpaintNode.cpp
+++ b/source/blender/compositor/nodes/COM_InpaintNode.cpp
@@ -31,7 +31,7 @@ InpaintNode::InpaintNode(bNode *editorNode) : Node(editorNode)
/* pass */
}
-void InpaintNode::convertToOperations(NodeConverter &converter, const CompositorContext &context) const
+void InpaintNode::convertToOperations(NodeConverter &converter, const CompositorContext &/*context*/) const
{
bNode *editorNode = this->getbNode();
diff --git a/source/blender/compositor/nodes/COM_InvertNode.cpp b/source/blender/compositor/nodes/COM_InvertNode.cpp
index ed4a21132ca..da499d66c2c 100644
--- a/source/blender/compositor/nodes/COM_InvertNode.cpp
+++ b/source/blender/compositor/nodes/COM_InvertNode.cpp
@@ -30,7 +30,7 @@ InvertNode::InvertNode(bNode *editorNode) : Node(editorNode)
/* pass */
}
-void InvertNode::convertToOperations(NodeConverter &converter, const CompositorContext &context) const
+void InvertNode::convertToOperations(NodeConverter &converter, const CompositorContext &/*context*/) const
{
InvertOperation *operation = new InvertOperation();
bNode *node = this->getbNode();
diff --git a/source/blender/compositor/nodes/COM_LensDistortionNode.cpp b/source/blender/compositor/nodes/COM_LensDistortionNode.cpp
index 32db452e6c2..3d3cc841715 100644
--- a/source/blender/compositor/nodes/COM_LensDistortionNode.cpp
+++ b/source/blender/compositor/nodes/COM_LensDistortionNode.cpp
@@ -30,7 +30,7 @@ LensDistortionNode::LensDistortionNode(bNode *editorNode) : Node(editorNode)
/* pass */
}
-void LensDistortionNode::convertToOperations(NodeConverter &converter, const CompositorContext &context) const
+void LensDistortionNode::convertToOperations(NodeConverter &converter, const CompositorContext &/*context*/) const
{
bNode *editorNode = this->getbNode();
NodeLensDist *data = (NodeLensDist *)editorNode->storage;
diff --git a/source/blender/compositor/nodes/COM_LuminanceMatteNode.cpp b/source/blender/compositor/nodes/COM_LuminanceMatteNode.cpp
index e23ec243ff4..382296a7f3a 100644
--- a/source/blender/compositor/nodes/COM_LuminanceMatteNode.cpp
+++ b/source/blender/compositor/nodes/COM_LuminanceMatteNode.cpp
@@ -30,7 +30,7 @@ LuminanceMatteNode::LuminanceMatteNode(bNode *editorNode) : Node(editorNode)
/* pass */
}
-void LuminanceMatteNode::convertToOperations(NodeConverter &converter, const CompositorContext &context) const
+void LuminanceMatteNode::convertToOperations(NodeConverter &converter, const CompositorContext &/*context*/) const
{
bNode *editorsnode = getbNode();
NodeInput *inputSocket = this->getInputSocket(0);
diff --git a/source/blender/compositor/nodes/COM_MapRangeNode.cpp b/source/blender/compositor/nodes/COM_MapRangeNode.cpp
index 2c164cfad32..148ca00205c 100644
--- a/source/blender/compositor/nodes/COM_MapRangeNode.cpp
+++ b/source/blender/compositor/nodes/COM_MapRangeNode.cpp
@@ -30,7 +30,7 @@ MapRangeNode::MapRangeNode(bNode *editorNode) : Node(editorNode)
/* pass */
}
-void MapRangeNode::convertToOperations(NodeConverter &converter, const CompositorContext &context) const
+void MapRangeNode::convertToOperations(NodeConverter &converter, const CompositorContext &/*context*/) const
{
NodeInput *valueSocket = this->getInputSocket(0);
NodeInput *sourceMinSocket = this->getInputSocket(1);
diff --git a/source/blender/compositor/nodes/COM_MapUVNode.cpp b/source/blender/compositor/nodes/COM_MapUVNode.cpp
index 25ca7b8b8c6..ec38e23ec07 100644
--- a/source/blender/compositor/nodes/COM_MapUVNode.cpp
+++ b/source/blender/compositor/nodes/COM_MapUVNode.cpp
@@ -28,7 +28,7 @@ MapUVNode::MapUVNode(bNode *editorNode) : Node(editorNode)
/* pass */
}
-void MapUVNode::convertToOperations(NodeConverter &converter, const CompositorContext &context) const
+void MapUVNode::convertToOperations(NodeConverter &converter, const CompositorContext &/*context*/) const
{
bNode *node = this->getbNode();
diff --git a/source/blender/compositor/nodes/COM_MapValueNode.cpp b/source/blender/compositor/nodes/COM_MapValueNode.cpp
index d7ee4e6a38b..f04c6a2d316 100644
--- a/source/blender/compositor/nodes/COM_MapValueNode.cpp
+++ b/source/blender/compositor/nodes/COM_MapValueNode.cpp
@@ -30,7 +30,7 @@ MapValueNode::MapValueNode(bNode *editorNode) : Node(editorNode)
/* pass */
}
-void MapValueNode::convertToOperations(NodeConverter &converter, const CompositorContext &context) const
+void MapValueNode::convertToOperations(NodeConverter &converter, const CompositorContext &/*context*/) const
{
TexMapping *storage = (TexMapping *)this->getbNode()->storage;
diff --git a/source/blender/compositor/nodes/COM_MathNode.cpp b/source/blender/compositor/nodes/COM_MathNode.cpp
index ef7046b8165..eb6bb2caf56 100644
--- a/source/blender/compositor/nodes/COM_MathNode.cpp
+++ b/source/blender/compositor/nodes/COM_MathNode.cpp
@@ -24,66 +24,66 @@
#include "COM_MathBaseOperation.h"
#include "COM_ExecutionSystem.h"
-void MathNode::convertToOperations(NodeConverter &converter, const CompositorContext &context) const
+void MathNode::convertToOperations(NodeConverter &converter, const CompositorContext &/*context*/) const
{
MathBaseOperation *operation = NULL;
switch (this->getbNode()->custom1) {
- case 0: /* Add */
+ case NODE_MATH_ADD:
operation = new MathAddOperation();
break;
- case 1: /* Subtract */
+ case NODE_MATH_SUB:
operation = new MathSubtractOperation();
break;
- case 2: /* Multiply */
+ case NODE_MATH_MUL:
operation = new MathMultiplyOperation();
break;
- case 3: /* Divide */
+ case NODE_MATH_DIVIDE:
operation = new MathDivideOperation();
break;
- case 4: /* Sine */
+ case NODE_MATH_SIN:
operation = new MathSineOperation();
break;
- case 5: /* Cosine */
+ case NODE_MATH_COS:
operation = new MathCosineOperation();
break;
- case 6: /* Tangent */
+ case NODE_MATH_TAN:
operation = new MathTangentOperation();
break;
- case 7: /* Arc-Sine */
+ case NODE_MATH_ASIN:
operation = new MathArcSineOperation();
break;
- case 8: /* Arc-Cosine */
+ case NODE_MATH_ACOS:
operation = new MathArcCosineOperation();
break;
- case 9: /* Arc-Tangent */
+ case NODE_MATH_ATAN:
operation = new MathArcTangentOperation();
break;
- case 10: /* Power */
+ case NODE_MATH_POW:
operation = new MathPowerOperation();
break;
- case 11: /* Logarithm */
+ case NODE_MATH_LOG:
operation = new MathLogarithmOperation();
break;
- case 12: /* Minimum */
+ case NODE_MATH_MIN:
operation = new MathMinimumOperation();
break;
- case 13: /* Maximum */
+ case NODE_MATH_MAX:
operation = new MathMaximumOperation();
break;
- case 14: /* Round */
+ case NODE_MATH_ROUND:
operation = new MathRoundOperation();
break;
- case 15: /* Less Than */
+ case NODE_MATH_LESS:
operation = new MathLessThanOperation();
break;
- case 16: /* Greater Than */
+ case NODE_MATH_GREATER:
operation = new MathGreaterThanOperation();
break;
- case 17: /* Modulo */
+ case NODE_MATH_MOD:
operation = new MathModuloOperation();
break;
- case 18: /* Absolute Value */
+ case NODE_MATH_ABS:
operation = new MathAbsoluteOperation();
break;
}
diff --git a/source/blender/compositor/nodes/COM_MixNode.cpp b/source/blender/compositor/nodes/COM_MixNode.cpp
index b12dfc02ed7..0607d6d6705 100644
--- a/source/blender/compositor/nodes/COM_MixNode.cpp
+++ b/source/blender/compositor/nodes/COM_MixNode.cpp
@@ -34,15 +34,15 @@ MixNode::MixNode(bNode *editorNode) : Node(editorNode)
/* pass */
}
-void MixNode::convertToOperations(NodeConverter &converter, const CompositorContext &context) const
+void MixNode::convertToOperations(NodeConverter &converter, const CompositorContext &/*context*/) const
{
NodeInput *valueSocket = this->getInputSocket(0);
NodeInput *color1Socket = this->getInputSocket(1);
NodeInput *color2Socket = this->getInputSocket(2);
NodeOutput *outputSocket = this->getOutputSocket(0);
bNode *editorNode = this->getbNode();
- bool useAlphaPremultiply = this->getbNode()->custom2 & 1;
- bool useClamp = this->getbNode()->custom2 & 2;
+ bool useAlphaPremultiply = (this->getbNode()->custom2 & 1) != 0;
+ bool useClamp = (this->getbNode()->custom2 & 2) != 0;
MixBaseOperation *convertProg;
switch (editorNode->custom1) {
diff --git a/source/blender/compositor/nodes/COM_NormalNode.cpp b/source/blender/compositor/nodes/COM_NormalNode.cpp
index d7c3fd11844..26da61cb9e7 100644
--- a/source/blender/compositor/nodes/COM_NormalNode.cpp
+++ b/source/blender/compositor/nodes/COM_NormalNode.cpp
@@ -31,7 +31,7 @@ NormalNode::NormalNode(bNode *editorNode) : Node(editorNode)
/* pass */
}
-void NormalNode::convertToOperations(NodeConverter &converter, const CompositorContext &context) const
+void NormalNode::convertToOperations(NodeConverter &converter, const CompositorContext &/*context*/) const
{
NodeInput *inputSocket = this->getInputSocket(0);
NodeOutput *outputSocket = this->getOutputSocket(0);
diff --git a/source/blender/compositor/nodes/COM_NormalizeNode.cpp b/source/blender/compositor/nodes/COM_NormalizeNode.cpp
index f6e919c168f..a13fcd2a301 100644
--- a/source/blender/compositor/nodes/COM_NormalizeNode.cpp
+++ b/source/blender/compositor/nodes/COM_NormalizeNode.cpp
@@ -28,7 +28,7 @@ NormalizeNode::NormalizeNode(bNode *editorNode) : Node(editorNode)
/* pass */
}
-void NormalizeNode::convertToOperations(NodeConverter &converter, const CompositorContext &context) const
+void NormalizeNode::convertToOperations(NodeConverter &converter, const CompositorContext &/*context*/) const
{
NormalizeOperation *operation = new NormalizeOperation();
converter.addOperation(operation);
diff --git a/source/blender/compositor/nodes/COM_OutputFileNode.cpp b/source/blender/compositor/nodes/COM_OutputFileNode.cpp
index 92fa74b9a2e..42805d1ff37 100644
--- a/source/blender/compositor/nodes/COM_OutputFileNode.cpp
+++ b/source/blender/compositor/nodes/COM_OutputFileNode.cpp
@@ -23,8 +23,11 @@
#include "COM_OutputFileNode.h"
#include "COM_OutputFileOperation.h"
+#include "COM_OutputFileMultiViewOperation.h"
#include "COM_ExecutionSystem.h"
+#include "BKE_scene.h"
+
#include "BLI_path_util.h"
OutputFileNode::OutputFileNode(bNode *editorNode) : Node(editorNode)
@@ -35,6 +38,7 @@ OutputFileNode::OutputFileNode(bNode *editorNode) : Node(editorNode)
void OutputFileNode::convertToOperations(NodeConverter &converter, const CompositorContext &context) const
{
NodeImageMultiFile *storage = (NodeImageMultiFile *)this->getbNode()->storage;
+ const bool is_multiview = (context.getRenderData()->scemode & R_MULTIVIEW) != 0;
if (!context.isRendering()) {
/* only output files when rendering a sequence -
@@ -43,13 +47,24 @@ void OutputFileNode::convertToOperations(NodeConverter &converter, const Composi
*/
return;
}
-
+
if (storage->format.imtype == R_IMF_IMTYPE_MULTILAYER) {
+ const bool use_half_float = (storage->format.depth == R_IMF_CHAN_DEPTH_16);
/* single output operation for the multilayer file */
- OutputOpenExrMultiLayerOperation *outputOperation = new OutputOpenExrMultiLayerOperation(
- context.getRenderData(), context.getbNodeTree(), storage->base_path, storage->format.exr_codec);
+ OutputOpenExrMultiLayerOperation *outputOperation;
+
+ if (is_multiview && storage->format.views_format == R_IMF_VIEWS_MULTIVIEW) {
+ outputOperation = new OutputOpenExrMultiLayerMultiViewOperation(
+ context.getRenderData(), context.getbNodeTree(), storage->base_path,
+ storage->format.exr_codec, use_half_float, context.getViewName());
+ }
+ else {
+ outputOperation = new OutputOpenExrMultiLayerOperation(
+ context.getRenderData(), context.getbNodeTree(), storage->base_path,
+ storage->format.exr_codec, use_half_float, context.getViewName());
+ }
converter.addOperation(outputOperation);
-
+
int num_inputs = getNumberOfInputSockets();
bool previewAdded = false;
for (int i = 0; i < num_inputs; ++i) {
@@ -76,17 +91,31 @@ void OutputFileNode::convertToOperations(NodeConverter &converter, const Composi
NodeImageMultiFileSocket *sockdata = (NodeImageMultiFileSocket *)input->getbNodeSocket()->storage;
ImageFormatData *format = (sockdata->use_node_format ? &storage->format : &sockdata->format);
char path[FILE_MAX];
-
+
/* combine file path for the input */
BLI_join_dirfile(path, FILE_MAX, storage->base_path, sockdata->path);
-
- OutputSingleLayerOperation *outputOperation = new OutputSingleLayerOperation(
- context.getRenderData(), context.getbNodeTree(), input->getDataType(), format, path,
- context.getViewSettings(), context.getDisplaySettings());
+
+ NodeOperation *outputOperation = NULL;
+
+ if (is_multiview && format->views_format == R_IMF_VIEWS_MULTIVIEW) {
+ outputOperation = new OutputOpenExrSingleLayerMultiViewOperation(
+ context.getRenderData(), context.getbNodeTree(), input->getDataType(), format, path,
+ context.getViewSettings(), context.getDisplaySettings(), context.getViewName());
+ }
+ else if ((!is_multiview) || (format->views_format == R_IMF_VIEWS_INDIVIDUAL)) {
+ outputOperation = new OutputSingleLayerOperation(
+ context.getRenderData(), context.getbNodeTree(), input->getDataType(), format, path,
+ context.getViewSettings(), context.getDisplaySettings(), context.getViewName());
+ }
+ else { /* R_IMF_VIEWS_STEREO_3D */
+ outputOperation = new OutputStereoOperation(
+ context.getRenderData(), context.getbNodeTree(), input->getDataType(), format, path,
+ sockdata->layer, context.getViewSettings(), context.getDisplaySettings(), context.getViewName());
+ }
+
converter.addOperation(outputOperation);
-
converter.mapInputSocket(input, outputOperation->getInputSocket(0));
-
+
if (!previewAdded) {
converter.addNodeInputPreview(input);
previewAdded = true;
diff --git a/source/blender/compositor/nodes/COM_PixelateNode.cpp b/source/blender/compositor/nodes/COM_PixelateNode.cpp
index da3cd74e771..fe806dbf307 100644
--- a/source/blender/compositor/nodes/COM_PixelateNode.cpp
+++ b/source/blender/compositor/nodes/COM_PixelateNode.cpp
@@ -30,7 +30,7 @@ PixelateNode::PixelateNode(bNode *editorNode) : Node(editorNode)
/* pass */
}
-void PixelateNode::convertToOperations(NodeConverter &converter, const CompositorContext &context) const
+void PixelateNode::convertToOperations(NodeConverter &converter, const CompositorContext &/*context*/) const
{
NodeInput *inputSocket = this->getInputSocket(0);
NodeOutput *outputSocket = this->getOutputSocket(0);
diff --git a/source/blender/compositor/nodes/COM_PlaneTrackDeformNode.cpp b/source/blender/compositor/nodes/COM_PlaneTrackDeformNode.cpp
index 9b69bc5a46e..379b9f193e8 100644
--- a/source/blender/compositor/nodes/COM_PlaneTrackDeformNode.cpp
+++ b/source/blender/compositor/nodes/COM_PlaneTrackDeformNode.cpp
@@ -54,6 +54,10 @@ void PlaneTrackDeformNode::convertToOperations(NodeConverter &converter, const C
warp_image_operation->setTrackingObject(data->tracking_object);
warp_image_operation->setPlaneTrackName(data->plane_track_name);
warp_image_operation->setFramenumber(frame_number);
+ if (data->flag & CMP_NODEFLAG_PLANETRACKDEFORM_MOTION_BLUR) {
+ warp_image_operation->setMotionBlurSamples(data->motion_blur_samples);
+ warp_image_operation->setMotionBlurShutter(data->motion_blur_shutter);
+ }
converter.addOperation(warp_image_operation);
converter.mapInputSocket(input_image, warp_image_operation->getInputSocket(0));
@@ -64,6 +68,10 @@ void PlaneTrackDeformNode::convertToOperations(NodeConverter &converter, const C
plane_mask_operation->setTrackingObject(data->tracking_object);
plane_mask_operation->setPlaneTrackName(data->plane_track_name);
plane_mask_operation->setFramenumber(frame_number);
+ if (data->flag & CMP_NODEFLAG_PLANETRACKDEFORM_MOTION_BLUR) {
+ plane_mask_operation->setMotionBlurSamples(data->motion_blur_samples);
+ plane_mask_operation->setMotionBlurShutter(data->motion_blur_shutter);
+ }
converter.addOperation(plane_mask_operation);
converter.mapOutputSocket(output_plane, plane_mask_operation->getOutputSocket());
diff --git a/source/blender/compositor/nodes/COM_PlaneTrackDeformNode.h b/source/blender/compositor/nodes/COM_PlaneTrackDeformNode.h
index 71e6ab12dfc..653100ce6a4 100644
--- a/source/blender/compositor/nodes/COM_PlaneTrackDeformNode.h
+++ b/source/blender/compositor/nodes/COM_PlaneTrackDeformNode.h
@@ -20,7 +20,6 @@
*/
#include "COM_Node.h"
-#include "DNA_node_types.h"
extern "C" {
# include "DNA_movieclip_types.h"
diff --git a/source/blender/compositor/nodes/COM_RenderLayersNode.cpp b/source/blender/compositor/nodes/COM_RenderLayersNode.cpp
index cc66c688379..842edcf35c9 100644
--- a/source/blender/compositor/nodes/COM_RenderLayersNode.cpp
+++ b/source/blender/compositor/nodes/COM_RenderLayersNode.cpp
@@ -27,6 +27,10 @@
#include "COM_ScaleOperation.h"
#include "COM_SetValueOperation.h"
+#ifdef WITH_CYCLES_DEBUG
+# include "RE_pipeline.h"
+#endif
+
RenderLayersNode::RenderLayersNode(bNode *editorNode) : Node(editorNode)
{
/* pass */
@@ -42,7 +46,8 @@ void RenderLayersNode::testSocketLink(NodeConverter &converter, const Compositor
operation->setScene(scene);
operation->setLayerId(layerId);
operation->setRenderData(context.getRenderData());
-
+ operation->setViewName(context.getViewName());
+
converter.mapOutputSocket(outputSocket, operation->getOutputSocket());
converter.addOperation(operation);
@@ -85,4 +90,13 @@ void RenderLayersNode::convertToOperations(NodeConverter &converter, const Compo
testSocketLink(converter, context, 28, new RenderLayersCyclesOperation(SCE_PASS_SUBSURFACE_DIRECT));
testSocketLink(converter, context, 29, new RenderLayersCyclesOperation(SCE_PASS_SUBSURFACE_INDIRECT));
testSocketLink(converter, context, 30, new RenderLayersCyclesOperation(SCE_PASS_SUBSURFACE_COLOR));
+
+#ifdef WITH_CYCLES_DEBUG
+ {
+ Scene *scene = (Scene *)this->getbNode()->id;
+ Render *re = RE_GetRender(scene->id.name);
+ int debug_pass_type = ((re != NULL) ? RE_debug_pass_type_get(re) : scene->r.debug_pass_type);
+ testSocketLink(converter, context, 31, new RenderLayersCyclesDebugOperation(SCE_PASS_DEBUG, debug_pass_type));
+ }
+#endif
}
diff --git a/source/blender/compositor/nodes/COM_RotateNode.cpp b/source/blender/compositor/nodes/COM_RotateNode.cpp
index c5fe88b3636..6fd7e357775 100644
--- a/source/blender/compositor/nodes/COM_RotateNode.cpp
+++ b/source/blender/compositor/nodes/COM_RotateNode.cpp
@@ -31,7 +31,7 @@ RotateNode::RotateNode(bNode *editorNode) : Node(editorNode)
/* pass */
}
-void RotateNode::convertToOperations(NodeConverter &converter, const CompositorContext &context) const
+void RotateNode::convertToOperations(NodeConverter &converter, const CompositorContext &/*context*/) const
{
NodeInput *inputSocket = this->getInputSocket(0);
NodeInput *inputDegreeSocket = this->getInputSocket(1);
diff --git a/source/blender/compositor/nodes/COM_SeparateColorNode.cpp b/source/blender/compositor/nodes/COM_SeparateColorNode.cpp
index a6fa9065364..780ce73d340 100644
--- a/source/blender/compositor/nodes/COM_SeparateColorNode.cpp
+++ b/source/blender/compositor/nodes/COM_SeparateColorNode.cpp
@@ -96,17 +96,17 @@ void SeparateColorNode::convertToOperations(NodeConverter &converter, const Comp
}
-NodeOperation *SeparateRGBANode::getColorConverter(const CompositorContext &context) const
+NodeOperation *SeparateRGBANode::getColorConverter(const CompositorContext &/*context*/) const
{
return NULL; /* no conversion needed */
}
-NodeOperation *SeparateHSVANode::getColorConverter(const CompositorContext &context) const
+NodeOperation *SeparateHSVANode::getColorConverter(const CompositorContext &/*context*/) const
{
return new ConvertRGBToHSVOperation();
}
-NodeOperation *SeparateYCCANode::getColorConverter(const CompositorContext &context) const
+NodeOperation *SeparateYCCANode::getColorConverter(const CompositorContext &/*context*/) const
{
ConvertRGBToYCCOperation *operation = new ConvertRGBToYCCOperation();
bNode *editorNode = this->getbNode();
@@ -114,7 +114,7 @@ NodeOperation *SeparateYCCANode::getColorConverter(const CompositorContext &cont
return operation;
}
-NodeOperation *SeparateYUVANode::getColorConverter(const CompositorContext &context) const
+NodeOperation *SeparateYUVANode::getColorConverter(const CompositorContext &/*context*/) const
{
return new ConvertRGBToYUVOperation();
}
diff --git a/source/blender/compositor/nodes/COM_SetAlphaNode.cpp b/source/blender/compositor/nodes/COM_SetAlphaNode.cpp
index 22ddd5bb157..32c03c695be 100644
--- a/source/blender/compositor/nodes/COM_SetAlphaNode.cpp
+++ b/source/blender/compositor/nodes/COM_SetAlphaNode.cpp
@@ -24,7 +24,7 @@
#include "COM_SetAlphaOperation.h"
#include "COM_ExecutionSystem.h"
-void SetAlphaNode::convertToOperations(NodeConverter &converter, const CompositorContext &context) const
+void SetAlphaNode::convertToOperations(NodeConverter &converter, const CompositorContext &/*context*/) const
{
SetAlphaOperation *operation = new SetAlphaOperation();
diff --git a/source/blender/compositor/nodes/COM_SocketProxyNode.cpp b/source/blender/compositor/nodes/COM_SocketProxyNode.cpp
index 48c8acfc6a1..465a94e8335 100644
--- a/source/blender/compositor/nodes/COM_SocketProxyNode.cpp
+++ b/source/blender/compositor/nodes/COM_SocketProxyNode.cpp
@@ -46,7 +46,7 @@ SocketProxyNode::SocketProxyNode(bNode *editorNode, bNodeSocket *editorInput, bN
this->addOutputSocket(dt, editorOutput);
}
-void SocketProxyNode::convertToOperations(NodeConverter &converter, const CompositorContext &context) const
+void SocketProxyNode::convertToOperations(NodeConverter &converter, const CompositorContext &/*context*/) const
{
NodeOperationOutput *proxy_output = converter.addInputProxy(getInputSocket(0), m_use_conversion);
converter.mapOutputSocket(getOutputSocket(), proxy_output);
@@ -68,13 +68,14 @@ SocketBufferNode::SocketBufferNode(bNode *editorNode, bNodeSocket *editorInput,
this->addOutputSocket(dt, editorOutput);
}
-void SocketBufferNode::convertToOperations(NodeConverter &converter, const CompositorContext &context) const
+void SocketBufferNode::convertToOperations(NodeConverter &converter, const CompositorContext &/*context*/) const
{
NodeOutput *output = this->getOutputSocket(0);
NodeInput *input = this->getInputSocket(0);
- WriteBufferOperation *writeOperation = new WriteBufferOperation();
- ReadBufferOperation *readOperation = new ReadBufferOperation();
+ DataType datatype = output->getDataType();
+ WriteBufferOperation *writeOperation = new WriteBufferOperation(datatype);
+ ReadBufferOperation *readOperation = new ReadBufferOperation(datatype);
readOperation->setMemoryProxy(writeOperation->getMemoryProxy());
converter.addOperation(writeOperation);
converter.addOperation(readOperation);
diff --git a/source/blender/compositor/nodes/COM_SplitViewerNode.cpp b/source/blender/compositor/nodes/COM_SplitViewerNode.cpp
index 15eca0a97e5..0f917d317f9 100644
--- a/source/blender/compositor/nodes/COM_SplitViewerNode.cpp
+++ b/source/blender/compositor/nodes/COM_SplitViewerNode.cpp
@@ -22,6 +22,8 @@
#include "COM_SplitViewerNode.h"
#include "BKE_global.h"
+#include "BKE_image.h"
+#include "BKE_scene.h"
#include "COM_SplitOperation.h"
#include "COM_ViewerOperation.h"
@@ -55,6 +57,8 @@ void SplitViewerNode::convertToOperations(NodeConverter &converter, const Compos
viewerOperation->setImageUser(imageUser);
viewerOperation->setViewSettings(context.getViewSettings());
viewerOperation->setDisplaySettings(context.getDisplaySettings());
+ viewerOperation->setRenderData(context.getRenderData());
+ viewerOperation->setViewName(context.getViewName());
/* defaults - the viewer node has these options but not exposed for split view
* we could use the split to define an area of interest on one axis at least */
diff --git a/source/blender/compositor/nodes/COM_SunBeamsNode.cpp b/source/blender/compositor/nodes/COM_SunBeamsNode.cpp
index ed14acabf36..7cf3c90c786 100644
--- a/source/blender/compositor/nodes/COM_SunBeamsNode.cpp
+++ b/source/blender/compositor/nodes/COM_SunBeamsNode.cpp
@@ -27,7 +27,7 @@ SunBeamsNode::SunBeamsNode(bNode *editorNode) : Node(editorNode)
/* pass */
}
-void SunBeamsNode::convertToOperations(NodeConverter &converter, const CompositorContext &context) const
+void SunBeamsNode::convertToOperations(NodeConverter &converter, const CompositorContext &/*context*/) const
{
NodeInput *inputSocket = this->getInputSocket(0);
NodeOutput *outputSocket = this->getOutputSocket(0);
diff --git a/source/blender/compositor/nodes/COM_SwitchNode.cpp b/source/blender/compositor/nodes/COM_SwitchNode.cpp
index 10f0ee3821d..eb854983d4c 100644
--- a/source/blender/compositor/nodes/COM_SwitchNode.cpp
+++ b/source/blender/compositor/nodes/COM_SwitchNode.cpp
@@ -27,7 +27,7 @@ SwitchNode::SwitchNode(bNode *editorNode) : Node(editorNode)
/* pass */
}
-void SwitchNode::convertToOperations(NodeConverter &converter, const CompositorContext &context) const
+void SwitchNode::convertToOperations(NodeConverter &converter, const CompositorContext &/*context*/) const
{
bool condition = this->getbNode()->custom1;
diff --git a/source/blender/compositor/nodes/COM_SwitchViewNode.cpp b/source/blender/compositor/nodes/COM_SwitchViewNode.cpp
new file mode 100644
index 00000000000..5a23b8b4d9e
--- /dev/null
+++ b/source/blender/compositor/nodes/COM_SwitchViewNode.cpp
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2015, Blender Foundation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributor:
+ * Dalai Felinto
+ */
+
+#include "COM_SwitchViewNode.h"
+#include "BLI_listbase.h"
+
+SwitchViewNode::SwitchViewNode(bNode *editorNode) : Node(editorNode)
+{
+ /* pass */
+}
+
+void SwitchViewNode::convertToOperations(NodeConverter &converter, const CompositorContext &context) const
+{
+ NodeOperationOutput *result;
+ const char *viewName = context.getViewName();
+ bNode *bnode = this->getbNode();
+
+ /* get the internal index of the socket with a matching name */
+ int nr = BLI_findstringindex(&bnode->inputs, viewName, offsetof(bNodeSocket, name));
+ nr = max(nr, 0);
+
+ result = converter.addInputProxy(getInputSocket(nr), false);
+ converter.mapOutputSocket(getOutputSocket(0), result);
+}
diff --git a/source/blender/compositor/nodes/COM_SwitchViewNode.h b/source/blender/compositor/nodes/COM_SwitchViewNode.h
new file mode 100644
index 00000000000..6ab5145bed5
--- /dev/null
+++ b/source/blender/compositor/nodes/COM_SwitchViewNode.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2015, Blender Foundation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributor:
+ * Dalai Felinto
+ */
+
+#ifndef _COM_SwitchViewNode_h_
+#define _COM_SwitchViewNode_h_
+
+#include "COM_Node.h"
+#include "COM_NodeOperation.h"
+#include "DNA_node_types.h"
+/**
+ * @brief SwitchViewNode
+ * @ingroup Node
+ */
+class SwitchViewNode : public Node {
+public:
+ SwitchViewNode(bNode *editorNode);
+ void convertToOperations(NodeConverter &converter, const CompositorContext &context) const;
+};
+#endif
diff --git a/source/blender/compositor/nodes/COM_TextureNode.cpp b/source/blender/compositor/nodes/COM_TextureNode.cpp
index 2ac027ca326..b80ca2fcdbd 100644
--- a/source/blender/compositor/nodes/COM_TextureNode.cpp
+++ b/source/blender/compositor/nodes/COM_TextureNode.cpp
@@ -35,7 +35,7 @@ void TextureNode::convertToOperations(NodeConverter &converter, const Compositor
Tex *texture = (Tex *)editorNode->id;
TextureOperation *operation = new TextureOperation();
const ColorManagedDisplaySettings *displaySettings = context.getDisplaySettings();
- bool sceneColorManage = strcmp(displaySettings->display_device, "None") != 0;
+ bool sceneColorManage = !STREQ(displaySettings->display_device, "None");
operation->setTexture(texture);
operation->setRenderData(context.getRenderData());
operation->setSceneColorManage(sceneColorManage);
diff --git a/source/blender/compositor/nodes/COM_TonemapNode.cpp b/source/blender/compositor/nodes/COM_TonemapNode.cpp
index 5ac73b9f9c2..961139d4855 100644
--- a/source/blender/compositor/nodes/COM_TonemapNode.cpp
+++ b/source/blender/compositor/nodes/COM_TonemapNode.cpp
@@ -29,7 +29,7 @@ TonemapNode::TonemapNode(bNode *editorNode) : Node(editorNode)
/* pass */
}
-void TonemapNode::convertToOperations(NodeConverter &converter, const CompositorContext &context) const
+void TonemapNode::convertToOperations(NodeConverter &converter, const CompositorContext &/*context*/) const
{
NodeTonemap *data = (NodeTonemap *)this->getbNode()->storage;
diff --git a/source/blender/compositor/nodes/COM_TransformNode.cpp b/source/blender/compositor/nodes/COM_TransformNode.cpp
index f1d5771bab3..148409a6427 100644
--- a/source/blender/compositor/nodes/COM_TransformNode.cpp
+++ b/source/blender/compositor/nodes/COM_TransformNode.cpp
@@ -33,7 +33,7 @@ TransformNode::TransformNode(bNode *editorNode) : Node(editorNode)
/* pass */
}
-void TransformNode::convertToOperations(NodeConverter &converter, const CompositorContext &context) const
+void TransformNode::convertToOperations(NodeConverter &converter, const CompositorContext &/*context*/) const
{
NodeInput *imageInput = this->getInputSocket(0);
NodeInput *xInput = this->getInputSocket(1);
diff --git a/source/blender/compositor/nodes/COM_TranslateNode.cpp b/source/blender/compositor/nodes/COM_TranslateNode.cpp
index 990cbe19be2..04dc1d435d3 100644
--- a/source/blender/compositor/nodes/COM_TranslateNode.cpp
+++ b/source/blender/compositor/nodes/COM_TranslateNode.cpp
@@ -57,8 +57,8 @@ void TranslateNode::convertToOperations(NodeConverter &converter, const Composit
converter.mapOutputSocket(outputSocket, operation->getOutputSocket(0));
if (data->wrap_axis) {
- WriteBufferOperation *writeOperation = new WriteBufferOperation();
- WrapOperation *wrapOperation = new WrapOperation();
+ WriteBufferOperation *writeOperation = new WriteBufferOperation(COM_DT_COLOR);
+ WrapOperation *wrapOperation = new WrapOperation(COM_DT_COLOR);
wrapOperation->setMemoryProxy(writeOperation->getMemoryProxy());
wrapOperation->setWrapping(data->wrap_axis);
diff --git a/source/blender/compositor/nodes/COM_ValueNode.cpp b/source/blender/compositor/nodes/COM_ValueNode.cpp
index 62a312da67c..c75d9296807 100644
--- a/source/blender/compositor/nodes/COM_ValueNode.cpp
+++ b/source/blender/compositor/nodes/COM_ValueNode.cpp
@@ -29,7 +29,7 @@ ValueNode::ValueNode(bNode *editorNode) : Node(editorNode)
/* pass */
}
-void ValueNode::convertToOperations(NodeConverter &converter, const CompositorContext &context) const
+void ValueNode::convertToOperations(NodeConverter &converter, const CompositorContext &/*context*/) const
{
SetValueOperation *operation = new SetValueOperation();
NodeOutput *output = this->getOutputSocket(0);
diff --git a/source/blender/compositor/nodes/COM_VectorCurveNode.cpp b/source/blender/compositor/nodes/COM_VectorCurveNode.cpp
index 197b2c8bd0c..7222a018fa0 100644
--- a/source/blender/compositor/nodes/COM_VectorCurveNode.cpp
+++ b/source/blender/compositor/nodes/COM_VectorCurveNode.cpp
@@ -29,7 +29,7 @@ VectorCurveNode::VectorCurveNode(bNode *editorNode) : Node(editorNode)
/* pass */
}
-void VectorCurveNode::convertToOperations(NodeConverter &converter, const CompositorContext &context) const
+void VectorCurveNode::convertToOperations(NodeConverter &converter, const CompositorContext &/*context*/) const
{
VectorCurveOperation *operation = new VectorCurveOperation();
operation->setCurveMapping((CurveMapping *)this->getbNode()->storage);
diff --git a/source/blender/compositor/nodes/COM_ViewLevelsNode.cpp b/source/blender/compositor/nodes/COM_ViewLevelsNode.cpp
index 30f51794e8d..06f12ccc559 100644
--- a/source/blender/compositor/nodes/COM_ViewLevelsNode.cpp
+++ b/source/blender/compositor/nodes/COM_ViewLevelsNode.cpp
@@ -31,7 +31,7 @@ ViewLevelsNode::ViewLevelsNode(bNode *editorNode) : Node(editorNode)
/* pass */
}
-void ViewLevelsNode::convertToOperations(NodeConverter &converter, const CompositorContext &context) const
+void ViewLevelsNode::convertToOperations(NodeConverter &converter, const CompositorContext &/*context*/) const
{
NodeInput *input = this->getInputSocket(0);
if (input->isLinked()) {
diff --git a/source/blender/compositor/nodes/COM_ViewerNode.cpp b/source/blender/compositor/nodes/COM_ViewerNode.cpp
index 07aa960c4d9..ab819ce6e30 100644
--- a/source/blender/compositor/nodes/COM_ViewerNode.cpp
+++ b/source/blender/compositor/nodes/COM_ViewerNode.cpp
@@ -22,6 +22,9 @@
#include "COM_ViewerNode.h"
#include "BKE_global.h"
+#include "BKE_image.h"
+#include "BLI_listbase.h"
+#include "BKE_scene.h"
#include "COM_ViewerOperation.h"
#include "COM_ExecutionSystem.h"
@@ -35,7 +38,7 @@ void ViewerNode::convertToOperations(NodeConverter &converter, const CompositorC
{
bNode *editorNode = this->getbNode();
bool do_output = (editorNode->flag & NODE_DO_OUTPUT_RECALC || context.isRendering()) && (editorNode->flag & NODE_DO_OUTPUT);
- bool ignore_alpha = editorNode->custom2 & CMP_NODE_OUTPUT_IGNORE_ALPHA;
+ bool ignore_alpha = (editorNode->custom2 & CMP_NODE_OUTPUT_IGNORE_ALPHA) != 0;
NodeInput *imageSocket = this->getInputSocket(0);
NodeInput *alphaSocket = this->getInputSocket(1);
@@ -51,6 +54,8 @@ void ViewerNode::convertToOperations(NodeConverter &converter, const CompositorC
viewerOperation->setCenterY(editorNode->custom4);
/* alpha socket gives either 1 or a custom alpha value if "use alpha" is enabled */
viewerOperation->setUseAlphaInput(ignore_alpha || alphaSocket->isLinked());
+ viewerOperation->setRenderData(context.getRenderData());
+ viewerOperation->setViewName(context.getViewName());
viewerOperation->setViewSettings(context.getViewSettings());
viewerOperation->setDisplaySettings(context.getDisplaySettings());
diff --git a/source/blender/compositor/operations/COM_AntiAliasOperation.cpp b/source/blender/compositor/operations/COM_AntiAliasOperation.cpp
index 995c61589cc..2e60c2d3e42 100644
--- a/source/blender/compositor/operations/COM_AntiAliasOperation.cpp
+++ b/source/blender/compositor/operations/COM_AntiAliasOperation.cpp
@@ -45,7 +45,7 @@ void AntiAliasOperation::initExecution()
NodeOperation::initMutex();
}
-void AntiAliasOperation::executePixel(float output[4], int x, int y, void *data)
+void AntiAliasOperation::executePixel(float output[4], int x, int y, void * /*data*/)
{
if (y < 0 || (unsigned int)y >= this->m_height || x < 0 || (unsigned int)x >= this->m_width) {
output[0] = 0.0f;
@@ -66,7 +66,7 @@ void AntiAliasOperation::deinitExecution()
NodeOperation::deinitMutex();
}
-bool AntiAliasOperation::determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output)
+bool AntiAliasOperation::determineDependingAreaOfInterest(rcti * /*input*/, ReadBufferOperation *readOperation, rcti *output)
{
rcti imageInput;
if (this->m_buffer) {
@@ -95,7 +95,7 @@ void *AntiAliasOperation::initializeTileData(rcti *rect)
float *input = tile->getBuffer();
char *valuebuffer = (char *)MEM_mallocN(sizeof(char) * size, __func__);
for (int i = 0; i < size; i++) {
- float in = input[i * COM_NUMBER_OF_CHANNELS];
+ float in = input[i];
valuebuffer[i] = FTOCHAR(in);
}
antialias_tagbuf(tile->getWidth(), tile->getHeight(), valuebuffer);
diff --git a/source/blender/compositor/operations/COM_BilateralBlurOperation.cpp b/source/blender/compositor/operations/COM_BilateralBlurOperation.cpp
index 2527f13c3ed..b24e48f52bc 100644
--- a/source/blender/compositor/operations/COM_BilateralBlurOperation.cpp
+++ b/source/blender/compositor/operations/COM_BilateralBlurOperation.cpp
@@ -65,6 +65,10 @@ void BilateralBlurOperation::executePixel(float output[4], int x, int y, void *d
zero_v4(blurColor);
blurDivider = 0.0f;
+ /* TODO(sergey): This isn't really good bilateral filter, it should be
+ * using gaussian bell for weights. Also sigma_color doesn't seem to be
+ * used correct at all.
+ */
for (int yi = miny; yi < maxy; yi += QualityStepHelper::getStep()) {
for (int xi = minx; xi < maxx; xi += QualityStepHelper::getStep()) {
// read determinator
diff --git a/source/blender/compositor/operations/COM_BlurBaseOperation.cpp b/source/blender/compositor/operations/COM_BlurBaseOperation.cpp
index d5aafc7c2ae..ce42de7a149 100644
--- a/source/blender/compositor/operations/COM_BlurBaseOperation.cpp
+++ b/source/blender/compositor/operations/COM_BlurBaseOperation.cpp
@@ -92,7 +92,7 @@ float *BlurBaseOperation::make_gausstab(float rad, int size)
}
#ifdef __SSE2__
-__m128 *BlurBaseOperation::convert_gausstab_sse(const float *gausstab, float rad, int size)
+__m128 *BlurBaseOperation::convert_gausstab_sse(const float *gausstab, int size)
{
int n = 2 * size + 1;
__m128 *gausstab_sse = (__m128 *) MEM_mallocN_aligned(sizeof(__m128) * n, 16, "gausstab sse");
@@ -133,6 +133,9 @@ float *BlurBaseOperation::make_dist_fac_inverse(float rad, int size, int falloff
case PROP_SHARP:
val = val * val;
break;
+ case PROP_INVSQUARE:
+ val = val * (2.0f - val);
+ break;
case PROP_LIN:
/* fall-through */
#ifndef NDEBUG
diff --git a/source/blender/compositor/operations/COM_BlurBaseOperation.h b/source/blender/compositor/operations/COM_BlurBaseOperation.h
index e97dd4d766d..f9f37479c56 100644
--- a/source/blender/compositor/operations/COM_BlurBaseOperation.h
+++ b/source/blender/compositor/operations/COM_BlurBaseOperation.h
@@ -39,7 +39,7 @@ protected:
BlurBaseOperation(DataType data_type);
float *make_gausstab(float rad, int size);
#ifdef __SSE2__
- __m128 *convert_gausstab_sse(const float *gaustab, float rad, int size);
+ __m128 *convert_gausstab_sse(const float *gaustab, int size);
#endif
float *make_dist_fac_inverse(float rad, int size, int falloff);
diff --git a/source/blender/compositor/operations/COM_BokehBlurOperation.cpp b/source/blender/compositor/operations/COM_BokehBlurOperation.cpp
index f5bca5371e6..189483708b5 100644
--- a/source/blender/compositor/operations/COM_BokehBlurOperation.cpp
+++ b/source/blender/compositor/operations/COM_BokehBlurOperation.cpp
@@ -45,7 +45,7 @@ BokehBlurOperation::BokehBlurOperation() : NodeOperation()
this->m_inputBoundingBoxReader = NULL;
}
-void *BokehBlurOperation::initializeTileData(rcti *rect)
+void *BokehBlurOperation::initializeTileData(rcti * /*rect*/)
{
lockMutex();
if (!this->m_sizeavailable) {
@@ -110,11 +110,11 @@ void BokehBlurOperation::executePixel(float output[4], int x, int y, void *data)
int step = getStep();
- int offsetadd = getOffsetAdd();
+ int offsetadd = getOffsetAdd() * COM_NUM_CHANNELS_COLOR;
float m = this->m_bokehDimension / pixelSize;
for (int ny = miny; ny < maxy; ny += step) {
- int bufferindex = ((minx - bufferstartx) * 4) + ((ny - bufferstarty) * 4 * bufferwidth);
+ int bufferindex = ((minx - bufferstartx) * COM_NUM_CHANNELS_COLOR) + ((ny - bufferstarty) * COM_NUM_CHANNELS_COLOR * bufferwidth);
for (int nx = minx; nx < maxx; nx += step) {
float u = this->m_bokehMidX - (nx - x) * m;
float v = this->m_bokehMidY - (ny - y) * m;
@@ -194,7 +194,7 @@ bool BokehBlurOperation::determineDependingAreaOfInterest(rcti *input, ReadBuffe
void BokehBlurOperation::executeOpenCL(OpenCLDevice *device,
MemoryBuffer *outputMemoryBuffer, cl_mem clOutputBuffer,
MemoryBuffer **inputMemoryBuffers, list<cl_mem> *clMemToCleanUp,
- list<cl_kernel> *clKernelsToCleanUp)
+ list<cl_kernel> * /*clKernelsToCleanUp*/)
{
cl_kernel kernel = device->COM_clCreateKernel("bokehBlurKernel", NULL);
if (!this->m_sizeavailable) {
diff --git a/source/blender/compositor/operations/COM_BokehImageOperation.cpp b/source/blender/compositor/operations/COM_BokehImageOperation.cpp
index 6617fc62ab8..18846f2a2c5 100644
--- a/source/blender/compositor/operations/COM_BokehImageOperation.cpp
+++ b/source/blender/compositor/operations/COM_BokehImageOperation.cpp
@@ -85,7 +85,7 @@ float BokehImageOperation::isInsideBokeh(float distance, float x, float y)
}
return insideBokeh;
}
-void BokehImageOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler)
+void BokehImageOperation::executePixelSampled(float output[4], float x, float y, PixelSampler /*sampler*/)
{
float shift = this->m_data->lensshift;
float shift2 = shift / 2.0f;
@@ -116,7 +116,7 @@ void BokehImageOperation::deinitExecution()
}
}
-void BokehImageOperation::determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2])
+void BokehImageOperation::determineResolution(unsigned int resolution[2], unsigned int /*preferredResolution*/[2])
{
resolution[0] = COM_BLUR_BOKEH_PIXELS;
resolution[1] = COM_BLUR_BOKEH_PIXELS;
diff --git a/source/blender/compositor/operations/COM_CalculateMeanOperation.cpp b/source/blender/compositor/operations/COM_CalculateMeanOperation.cpp
index a2954a20e90..d26dcd17750 100644
--- a/source/blender/compositor/operations/COM_CalculateMeanOperation.cpp
+++ b/source/blender/compositor/operations/COM_CalculateMeanOperation.cpp
@@ -24,7 +24,9 @@
#include "BLI_math.h"
#include "BLI_utildefines.h"
-
+extern "C" {
+#include "IMB_colormanagement.h"
+}
CalculateMeanOperation::CalculateMeanOperation() : NodeOperation()
{
@@ -42,7 +44,9 @@ void CalculateMeanOperation::initExecution()
NodeOperation::initMutex();
}
-void CalculateMeanOperation::executePixel(float output[4], int x, int y, void *data)
+void CalculateMeanOperation::executePixel(float output[4],
+ int /*x*/, int /*y*/,
+ void * /*data*/)
{
output[0] = this->m_result;
}
@@ -53,7 +57,7 @@ void CalculateMeanOperation::deinitExecution()
NodeOperation::deinitMutex();
}
-bool CalculateMeanOperation::determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output)
+bool CalculateMeanOperation::determineDependingAreaOfInterest(rcti * /*input*/, ReadBufferOperation *readOperation, rcti *output)
{
rcti imageInput;
if (this->m_iscalculated) {
@@ -96,7 +100,7 @@ void CalculateMeanOperation::calculateMean(MemoryBuffer *tile)
switch (this->m_setting) {
case 1:
{
- sum += rgb_to_bw(&buffer[offset]);
+ sum += IMB_colormanagement_get_luminance(&buffer[offset]);
break;
}
case 2:
diff --git a/source/blender/compositor/operations/COM_CalculateStandardDeviationOperation.cpp b/source/blender/compositor/operations/COM_CalculateStandardDeviationOperation.cpp
index 0c67da2d552..6b238e53d7b 100644
--- a/source/blender/compositor/operations/COM_CalculateStandardDeviationOperation.cpp
+++ b/source/blender/compositor/operations/COM_CalculateStandardDeviationOperation.cpp
@@ -24,14 +24,18 @@
#include "BLI_math.h"
#include "BLI_utildefines.h"
-
+extern "C" {
+#include "IMB_colormanagement.h"
+}
CalculateStandardDeviationOperation::CalculateStandardDeviationOperation() : CalculateMeanOperation()
{
/* pass */
}
-void CalculateStandardDeviationOperation::executePixel(float output[4], int x, int y, void *data)
+void CalculateStandardDeviationOperation::executePixel(float output[4],
+ int /*x*/, int /*y*/,
+ void * /*data*/)
{
output[0] = this->m_standardDeviation;
}
@@ -55,7 +59,7 @@ void *CalculateStandardDeviationOperation::initializeTileData(rcti *rect)
switch (this->m_setting) {
case 1: /* rgb combined */
{
- float value = rgb_to_bw(&buffer[offset]);
+ float value = IMB_colormanagement_get_luminance(&buffer[offset]);
sum += (value - mean) * (value - mean);
break;
}
diff --git a/source/blender/compositor/operations/COM_ChromaMatteOperation.cpp b/source/blender/compositor/operations/COM_ChromaMatteOperation.cpp
index 3329093882d..9a20ca412e0 100644
--- a/source/blender/compositor/operations/COM_ChromaMatteOperation.cpp
+++ b/source/blender/compositor/operations/COM_ChromaMatteOperation.cpp
@@ -66,6 +66,16 @@ void ChromaMatteOperation::executePixelSampled(float output[4], float x, float y
/* Algorithm from book "Video Demistified," does not include the spill reduction part */
/* find theta, the angle that the color space should be rotated based on key */
+
+ /* rescale to -1.0..1.0 */
+ // inImage[0] = (inImage[0] * 2.0f) - 1.0f; // UNUSED
+ inImage[1] = (inImage[1] * 2.0f) - 1.0f;
+ inImage[2] = (inImage[2] * 2.0f) - 1.0f;
+
+ // inKey[0] = (inKey[0] * 2.0f) - 1.0f; // UNUSED
+ inKey[1] = (inKey[1] * 2.0f) - 1.0f;
+ inKey[2] = (inKey[2] * 2.0f) - 1.0f;
+
theta = atan2(inKey[2], inKey[1]);
/*rotate the cb and cr into x/z space */
@@ -77,7 +87,7 @@ void ChromaMatteOperation::executePixelSampled(float output[4], float x, float y
kfg = x_angle - (fabsf(z_angle) / tanf(acceptance / 2.f));
if (kfg > 0.f) { /* found a pixel that is within key color */
- alpha = (1.f - kfg) * (gain);
+ alpha = 1.0f - (kfg / gain);
beta = atan2(z_angle, x_angle);
diff --git a/source/blender/compositor/operations/COM_ColorCorrectionOperation.cpp b/source/blender/compositor/operations/COM_ColorCorrectionOperation.cpp
index 19209951005..54e0fb41abf 100644
--- a/source/blender/compositor/operations/COM_ColorCorrectionOperation.cpp
+++ b/source/blender/compositor/operations/COM_ColorCorrectionOperation.cpp
@@ -23,6 +23,10 @@
#include "COM_ColorCorrectionOperation.h"
#include "BLI_math.h"
+extern "C" {
+#include "IMB_colormanagement.h"
+}
+
ColorCorrectionOperation::ColorCorrectionOperation() : NodeOperation()
{
this->addInputSocket(COM_DT_COLOR);
@@ -90,7 +94,7 @@ void ColorCorrectionOperation::executePixelSampled(float output[4], float x, flo
lift += (levelShadows * this->m_data->shadows.lift) + (levelMidtones * this->m_data->midtones.lift) + (levelHighlights * this->m_data->highlights.lift);
float invgamma = 1.0f / gamma;
- float luma = rgb_to_luma_y(inputImageColor);
+ float luma = IMB_colormanagement_get_luminance(inputImageColor);
r = inputImageColor[0];
g = inputImageColor[1];
diff --git a/source/blender/compositor/operations/COM_ColorSpillOperation.cpp b/source/blender/compositor/operations/COM_ColorSpillOperation.cpp
index 873ec72d9e9..0769e5d0b01 100644
--- a/source/blender/compositor/operations/COM_ColorSpillOperation.cpp
+++ b/source/blender/compositor/operations/COM_ColorSpillOperation.cpp
@@ -33,6 +33,7 @@ ColorSpillOperation::ColorSpillOperation() : NodeOperation()
this->m_inputImageReader = NULL;
this->m_inputFacReader = NULL;
this->m_spillChannel = 1; // GREEN
+ this->m_spillMethod = 0;
}
void ColorSpillOperation::initExecution()
@@ -91,7 +92,17 @@ void ColorSpillOperation::executePixelSampled(float output[4], float x, float y,
this->m_inputFacReader->readSampled(fac, x, y, sampler);
this->m_inputImageReader->readSampled(input, x, y, sampler);
float rfac = min(1.0f, fac[0]);
- float map = calculateMapValue(rfac, input);
+ float map;
+
+ switch (this->m_spillMethod) {
+ case 0: /* simple */
+ map = rfac * (input[this->m_spillChannel] - (this->m_settings->limscale * input[this->m_settings->limchan]));
+ break;
+ default: /* average */
+ map = rfac * (input[this->m_spillChannel] - (this->m_settings->limscale * AVG(input[this->m_channel2], input[this->m_channel3])));
+ break;
+ }
+
if (map > 0.0f) {
output[0] = input[0] + this->m_rmut * (this->m_settings->uspillr * map);
output[1] = input[1] + this->m_gmut * (this->m_settings->uspillg * map);
@@ -102,13 +113,3 @@ void ColorSpillOperation::executePixelSampled(float output[4], float x, float y,
copy_v4_v4(output, input);
}
}
-float ColorSpillOperation::calculateMapValue(float fac, float *input)
-{
- return fac * (input[this->m_spillChannel] - (this->m_settings->limscale * input[this->m_settings->limchan]));
-}
-
-
-float ColorSpillAverageOperation::calculateMapValue(float fac, float *input)
-{
- return fac * (input[this->m_spillChannel] - (this->m_settings->limscale * AVG(input[this->m_channel2], input[this->m_channel3])));
-}
diff --git a/source/blender/compositor/operations/COM_ColorSpillOperation.h b/source/blender/compositor/operations/COM_ColorSpillOperation.h
index f9dc9ef7e25..3b94c293ec9 100644
--- a/source/blender/compositor/operations/COM_ColorSpillOperation.h
+++ b/source/blender/compositor/operations/COM_ColorSpillOperation.h
@@ -34,6 +34,7 @@ protected:
SocketReader *m_inputImageReader;
SocketReader *m_inputFacReader;
int m_spillChannel;
+ int m_spillMethod;
int m_channel2;
int m_channel3;
float m_rmut, m_gmut, m_bmut;
@@ -53,12 +54,9 @@ public:
void setSettings(NodeColorspill *nodeColorSpill) { this->m_settings = nodeColorSpill; }
void setSpillChannel(int channel) { this->m_spillChannel = channel; }
+ void setSpillMethod(int method) { this->m_spillMethod = method; }
float calculateMapValue(float fac, float *input);
};
-class ColorSpillAverageOperation : public ColorSpillOperation {
-public:
- float calculateMapValue(float fac, float *input);
-};
#endif
diff --git a/source/blender/compositor/operations/COM_CompositorOperation.cpp b/source/blender/compositor/operations/COM_CompositorOperation.cpp
index ef331a50dfd..76f74c144f6 100644
--- a/source/blender/compositor/operations/COM_CompositorOperation.cpp
+++ b/source/blender/compositor/operations/COM_CompositorOperation.cpp
@@ -52,6 +52,7 @@ CompositorOperation::CompositorOperation() : NodeOperation()
this->m_active = false;
this->m_sceneName[0] = '\0';
+ this->m_viewName = NULL;
}
void CompositorOperation::initExecution()
@@ -81,14 +82,16 @@ void CompositorOperation::deinitExecution()
RenderResult *rr = RE_AcquireResultWrite(re);
if (rr) {
- if (rr->rectf != NULL) {
- MEM_freeN(rr->rectf);
+ RenderView *rv = RE_RenderViewGetByName(rr, this->m_viewName);
+
+ if (rv->rectf != NULL) {
+ MEM_freeN(rv->rectf);
}
- rr->rectf = this->m_outputBuffer;
- if (rr->rectz != NULL) {
- MEM_freeN(rr->rectz);
+ rv->rectf = this->m_outputBuffer;
+ if (rv->rectz != NULL) {
+ MEM_freeN(rv->rectz);
}
- rr->rectz = this->m_depthBuffer;
+ rv->rectz = this->m_depthBuffer;
}
else {
if (this->m_outputBuffer) {
@@ -125,7 +128,7 @@ void CompositorOperation::deinitExecution()
}
-void CompositorOperation::executeRegion(rcti *rect, unsigned int tileNumber)
+void CompositorOperation::executeRegion(rcti *rect, unsigned int /*tileNumber*/)
{
float color[8]; // 7 is enough
float *buffer = this->m_outputBuffer;
@@ -138,7 +141,7 @@ void CompositorOperation::executeRegion(rcti *rect, unsigned int tileNumber)
int y2 = rect->ymax;
int offset = (y1 * this->getWidth() + x1);
int add = (this->getWidth() - (x2 - x1));
- int offset4 = offset * COM_NUMBER_OF_CHANNELS;
+ int offset4 = offset * COM_NUM_CHANNELS_COLOR;
int x;
int y;
bool breaked = false;
@@ -196,14 +199,14 @@ void CompositorOperation::executeRegion(rcti *rect, unsigned int tileNumber)
this->m_depthInput->readSampled(color, input_x, input_y, COM_PS_NEAREST);
zbuffer[offset] = color[0];
- offset4 += COM_NUMBER_OF_CHANNELS;
+ offset4 += COM_NUM_CHANNELS_COLOR;
offset++;
if (isBreaked()) {
breaked = true;
}
}
offset += add;
- offset4 += add * COM_NUMBER_OF_CHANNELS;
+ offset4 += add * COM_NUM_CHANNELS_COLOR;
}
}
diff --git a/source/blender/compositor/operations/COM_CompositorOperation.h b/source/blender/compositor/operations/COM_CompositorOperation.h
index 771c32ffd12..e81ba520695 100644
--- a/source/blender/compositor/operations/COM_CompositorOperation.h
+++ b/source/blender/compositor/operations/COM_CompositorOperation.h
@@ -75,13 +75,19 @@ private:
* @brief operation is active for calculating final compo result
*/
bool m_active;
+
+ /**
+ * @brief View name, used for multiview
+ */
+ const char *m_viewName;
public:
CompositorOperation();
const bool isActiveCompositorOutput() const { return this->m_active; }
void executeRegion(rcti *rect, unsigned int tileNumber);
void setSceneName(const char *sceneName) { BLI_strncpy(this->m_sceneName, sceneName, sizeof(this->m_sceneName)); }
+ void setViewName(const char *viewName) { this->m_viewName = viewName; }
void setRenderData(const RenderData *rd) { this->m_rd = rd; }
- bool isOutputOperation(bool rendering) const { return this->isActiveCompositorOutput(); }
+ bool isOutputOperation(bool /*rendering*/) const { return this->isActiveCompositorOutput(); }
void initExecution();
void deinitExecution();
const CompositorPriority getRenderPriority() const { return COM_PRIORITY_MEDIUM; }
diff --git a/source/blender/compositor/operations/COM_ConvertDepthToRadiusOperation.cpp b/source/blender/compositor/operations/COM_ConvertDepthToRadiusOperation.cpp
index ea1443598a9..fa9a957f83c 100644
--- a/source/blender/compositor/operations/COM_ConvertDepthToRadiusOperation.cpp
+++ b/source/blender/compositor/operations/COM_ConvertDepthToRadiusOperation.cpp
@@ -60,7 +60,7 @@ void ConvertDepthToRadiusOperation::initExecution()
this->m_inputOperation = this->getInputSocketReader(0);
float focalDistance = determineFocalDistance();
- if (focalDistance == 0.0f) focalDistance = 1e10f; /* if the dof is 0.0 then set it be be far away */
+ if (focalDistance == 0.0f) focalDistance = 1e10f; /* if the dof is 0.0 then set it to be far away */
this->m_inverseFocalDistance = 1.0f / focalDistance;
this->m_aspect = (this->getWidth() > this->getHeight()) ? (this->getHeight() / (float)this->getWidth()) : (this->getWidth() / (float)this->getHeight());
this->m_aperture = 0.5f * (this->m_cam_lens / (this->m_aspect * cam_sensor)) / this->m_fStop;
diff --git a/source/blender/compositor/operations/COM_ConvertOperation.cpp b/source/blender/compositor/operations/COM_ConvertOperation.cpp
index 6b3e4067b18..8b8e8408208 100644
--- a/source/blender/compositor/operations/COM_ConvertOperation.cpp
+++ b/source/blender/compositor/operations/COM_ConvertOperation.cpp
@@ -22,6 +22,9 @@
#include "COM_ConvertOperation.h"
+extern "C" {
+#include "IMB_colormanagement.h"
+}
ConvertBaseOperation::ConvertBaseOperation()
{
@@ -49,9 +52,9 @@ ConvertValueToColorOperation::ConvertValueToColorOperation() : ConvertBaseOperat
void ConvertValueToColorOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler)
{
- float inputValue[4];
- this->m_inputOperation->readSampled(inputValue, x, y, sampler);
- output[0] = output[1] = output[2] = inputValue[0];
+ float value;
+ this->m_inputOperation->readSampled(&value, x, y, sampler);
+ output[0] = output[1] = output[2] = value;
output[3] = 1.0f;
}
@@ -84,7 +87,7 @@ void ConvertColorToBWOperation::executePixelSampled(float output[4], float x, fl
{
float inputColor[4];
this->m_inputOperation->readSampled(inputColor, x, y, sampler);
- output[0] = rgb_to_bw(inputColor);
+ output[0] = IMB_colormanagement_get_luminance(inputColor);
}
@@ -98,8 +101,9 @@ ConvertColorToVectorOperation::ConvertColorToVectorOperation() : ConvertBaseOper
void ConvertColorToVectorOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler)
{
- this->m_inputOperation->readSampled(output, x, y, sampler);
-}
+ float color[4];
+ this->m_inputOperation->readSampled(color, x, y, sampler);
+ copy_v3_v3(output, color);}
/* ******** Value to Vector ******** */
@@ -112,12 +116,9 @@ ConvertValueToVectorOperation::ConvertValueToVectorOperation() : ConvertBaseOper
void ConvertValueToVectorOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler)
{
- float input[4];
- this->m_inputOperation->readSampled(input, x, y, sampler);
- output[0] = input[0];
- output[1] = input[0];
- output[2] = input[0];
- output[3] = 0.0f;
+ float value;
+ this->m_inputOperation->readSampled(&value, x, y, sampler);
+ output[0] = output[1] = output[2] = value;
}
@@ -292,6 +293,9 @@ void ConvertHSVToRGBOperation::executePixelSampled(float output[4], float x, flo
float inputColor[4];
this->m_inputOperation->readSampled(inputColor, x, y, sampler);
hsv_to_rgb_v(inputColor, output);
+ output[0] = max_ff(output[0], 0.0f);
+ output[1] = max_ff(output[1], 0.0f);
+ output[2] = max_ff(output[2], 0.0f);
output[3] = inputColor[3];
}
diff --git a/source/blender/compositor/operations/COM_ConvolutionEdgeFilterOperation.cpp b/source/blender/compositor/operations/COM_ConvolutionEdgeFilterOperation.cpp
index 657126d458c..e1ada9a8c39 100644
--- a/source/blender/compositor/operations/COM_ConvolutionEdgeFilterOperation.cpp
+++ b/source/blender/compositor/operations/COM_ConvolutionEdgeFilterOperation.cpp
@@ -28,7 +28,7 @@ ConvolutionEdgeFilterOperation::ConvolutionEdgeFilterOperation() : ConvolutionFi
/* pass */
}
-void ConvolutionEdgeFilterOperation::executePixel(float output[4], int x, int y, void *data)
+void ConvolutionEdgeFilterOperation::executePixel(float output[4], int x, int y, void * /*data*/)
{
float in1[4], in2[4], res1[4] = {0.0}, res2[4] = {0.0};
diff --git a/source/blender/compositor/operations/COM_ConvolutionFilterOperation.cpp b/source/blender/compositor/operations/COM_ConvolutionFilterOperation.cpp
index 553a9827ffa..699db11d56e 100644
--- a/source/blender/compositor/operations/COM_ConvolutionFilterOperation.cpp
+++ b/source/blender/compositor/operations/COM_ConvolutionFilterOperation.cpp
@@ -69,7 +69,7 @@ void ConvolutionFilterOperation::deinitExecution()
}
-void ConvolutionFilterOperation::executePixel(float output[4], int x, int y, void *data)
+void ConvolutionFilterOperation::executePixel(float output[4], int x, int y, void * /*data*/)
{
float in1[4];
float in2[4];
diff --git a/source/blender/compositor/operations/COM_CropOperation.cpp b/source/blender/compositor/operations/COM_CropOperation.cpp
index c514b576dcf..e5427589fce 100644
--- a/source/blender/compositor/operations/COM_CropOperation.cpp
+++ b/source/blender/compositor/operations/COM_CropOperation.cpp
@@ -36,27 +36,28 @@ void CropBaseOperation::updateArea()
SocketReader *inputReference = this->getInputSocketReader(0);
float width = inputReference->getWidth();
float height = inputReference->getHeight();
+ NodeTwoXYs local_settings = *this->m_settings;
if (width > 0.0f && height > 0.0f) {
if (this->m_relative) {
- this->m_settings->x1 = width * this->m_settings->fac_x1;
- this->m_settings->x2 = width * this->m_settings->fac_x2;
- this->m_settings->y1 = height * this->m_settings->fac_y1;
- this->m_settings->y2 = height * this->m_settings->fac_y2;
+ local_settings.x1 = width * local_settings.fac_x1;
+ local_settings.x2 = width * local_settings.fac_x2;
+ local_settings.y1 = height * local_settings.fac_y1;
+ local_settings.y2 = height * local_settings.fac_y2;
}
- if (width <= this->m_settings->x1 + 1)
- this->m_settings->x1 = width - 1;
- if (height <= this->m_settings->y1 + 1)
- this->m_settings->y1 = height - 1;
- if (width <= this->m_settings->x2 + 1)
- this->m_settings->x2 = width - 1;
- if (height <= this->m_settings->y2 + 1)
- this->m_settings->y2 = height - 1;
+ if (width <= local_settings.x1 + 1)
+ local_settings.x1 = width - 1;
+ if (height <= local_settings.y1 + 1)
+ local_settings.y1 = height - 1;
+ if (width <= local_settings.x2 + 1)
+ local_settings.x2 = width - 1;
+ if (height <= local_settings.y2 + 1)
+ local_settings.y2 = height - 1;
- this->m_xmax = max(this->m_settings->x1, this->m_settings->x2) + 1;
- this->m_xmin = min(this->m_settings->x1, this->m_settings->x2);
- this->m_ymax = max(this->m_settings->y1, this->m_settings->y2) + 1;
- this->m_ymin = min(this->m_settings->y1, this->m_settings->y2);
+ this->m_xmax = max(local_settings.x1, local_settings.x2) + 1;
+ this->m_xmin = min(local_settings.x1, local_settings.x2);
+ this->m_ymax = max(local_settings.y1, local_settings.y2) + 1;
+ this->m_ymin = min(local_settings.y1, local_settings.y2);
}
else {
this->m_xmax = 0;
@@ -109,9 +110,9 @@ bool CropImageOperation::determineDependingAreaOfInterest(rcti *input, ReadBuffe
return NodeOperation::determineDependingAreaOfInterest(&newInput, readOperation, output);
}
-void CropImageOperation::determineResolution(unsigned int resolution[2], unsigned int preferedResolution[2])
+void CropImageOperation::determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2])
{
- NodeOperation::determineResolution(resolution, preferedResolution);
+ NodeOperation::determineResolution(resolution, preferredResolution);
updateArea();
resolution[0] = this->m_xmax - this->m_xmin;
resolution[1] = this->m_ymax - this->m_ymin;
diff --git a/source/blender/compositor/operations/COM_CropOperation.h b/source/blender/compositor/operations/COM_CropOperation.h
index 4890ede18a9..0b396ca7800 100644
--- a/source/blender/compositor/operations/COM_CropOperation.h
+++ b/source/blender/compositor/operations/COM_CropOperation.h
@@ -56,7 +56,7 @@ private:
public:
CropImageOperation();
bool determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output);
- void determineResolution(unsigned int resolution[2], unsigned int preferedResolution[2]);
+ void determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]);
void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
};
diff --git a/source/blender/compositor/operations/COM_DespeckleOperation.cpp b/source/blender/compositor/operations/COM_DespeckleOperation.cpp
index 186c17845f3..1a827aae67e 100644
--- a/source/blender/compositor/operations/COM_DespeckleOperation.cpp
+++ b/source/blender/compositor/operations/COM_DespeckleOperation.cpp
@@ -52,7 +52,7 @@ BLI_INLINE int color_diff(const float a[3], const float b[3], const float thresh
(fabsf(a[2] - b[2]) > threshold));
}
-void DespeckleOperation::executePixel(float output[4], int x, int y, void *data)
+void DespeckleOperation::executePixel(float output[4], int x, int y, void * /*data*/)
{
float w = 0.0f;
float color_org[4];
diff --git a/source/blender/compositor/operations/COM_DilateErodeOperation.cpp b/source/blender/compositor/operations/COM_DilateErodeOperation.cpp
index cbf4ce693d9..fc3ec7dd11a 100644
--- a/source/blender/compositor/operations/COM_DilateErodeOperation.cpp
+++ b/source/blender/compositor/operations/COM_DilateErodeOperation.cpp
@@ -56,7 +56,7 @@ void DilateErodeThresholdOperation::initExecution()
}
}
-void *DilateErodeThresholdOperation::initializeTileData(rcti *rect)
+void *DilateErodeThresholdOperation::initializeTileData(rcti * /*rect*/)
{
void *buffer = this->m_inputProgram->initializeTileData(NULL);
return buffer;
@@ -82,18 +82,18 @@ void DilateErodeThresholdOperation::executePixel(float output[4], int x, int y,
const int bufferWidth = BLI_rcti_size_x(rect);
int offset;
- this->m_inputProgram->read(inputValue, x, y, NULL);
+ inputBuffer->read(inputValue, x, y);
if (inputValue[0] > sw) {
for (int yi = miny; yi < maxy; yi++) {
const float dy = yi - y;
- offset = ((yi - rect->ymin) * bufferWidth + (minx - rect->xmin)) * 4;
+ offset = ((yi - rect->ymin) * bufferWidth + (minx - rect->xmin));
for (int xi = minx; xi < maxx; xi++) {
if (buffer[offset] < sw) {
const float dx = xi - x;
const float dis = dx * dx + dy * dy;
mindist = min(mindist, dis);
}
- offset += 4;
+ offset ++;
}
}
pixelvalue = -sqrtf(mindist);
@@ -101,15 +101,14 @@ void DilateErodeThresholdOperation::executePixel(float output[4], int x, int y,
else {
for (int yi = miny; yi < maxy; yi++) {
const float dy = yi - y;
- offset = ((yi - rect->ymin) * bufferWidth + (minx - rect->xmin)) * 4;
+ offset = ((yi - rect->ymin) * bufferWidth + (minx - rect->xmin));
for (int xi = minx; xi < maxx; xi++) {
if (buffer[offset] > sw) {
const float dx = xi - x;
const float dis = dx * dx + dy * dy;
mindist = min(mindist, dis);
}
- offset += 4;
-
+ offset ++;
}
}
pixelvalue = sqrtf(mindist);
@@ -181,7 +180,7 @@ void DilateDistanceOperation::initExecution()
}
}
-void *DilateDistanceOperation::initializeTileData(rcti *rect)
+void *DilateDistanceOperation::initializeTileData(rcti * /*rect*/)
{
void *buffer = this->m_inputProgram->initializeTileData(NULL);
return buffer;
@@ -206,14 +205,14 @@ void DilateDistanceOperation::executePixel(float output[4], int x, int y, void *
for (int yi = miny; yi < maxy; yi++) {
const float dy = yi - y;
- offset = ((yi - rect->ymin) * bufferWidth + (minx - rect->xmin)) * 4;
+ offset = ((yi - rect->ymin) * bufferWidth + (minx - rect->xmin));
for (int xi = minx; xi < maxx; xi++) {
const float dx = xi - x;
const float dis = dx * dx + dy * dy;
if (dis <= mindist) {
value = max(buffer[offset], value);
}
- offset += 4;
+ offset ++;
}
}
output[0] = value;
@@ -239,7 +238,7 @@ bool DilateDistanceOperation::determineDependingAreaOfInterest(rcti *input, Read
void DilateDistanceOperation::executeOpenCL(OpenCLDevice *device,
MemoryBuffer *outputMemoryBuffer, cl_mem clOutputBuffer,
MemoryBuffer **inputMemoryBuffers, list<cl_mem> *clMemToCleanUp,
- list<cl_kernel> *clKernelsToCleanUp)
+ list<cl_kernel> * /*clKernelsToCleanUp*/)
{
cl_kernel dilateKernel = device->COM_clCreateKernel("dilateKernel", NULL);
@@ -280,14 +279,14 @@ void ErodeDistanceOperation::executePixel(float output[4], int x, int y, void *d
for (int yi = miny; yi < maxy; yi++) {
const float dy = yi - y;
- offset = ((yi - rect->ymin) * bufferWidth + (minx - rect->xmin)) * 4;
+ offset = ((yi - rect->ymin) * bufferWidth + (minx - rect->xmin));
for (int xi = minx; xi < maxx; xi++) {
const float dx = xi - x;
const float dis = dx * dx + dy * dy;
if (dis <= mindist) {
value = min(buffer[offset], value);
}
- offset += 4;
+ offset ++;
}
}
output[0] = value;
@@ -296,7 +295,7 @@ void ErodeDistanceOperation::executePixel(float output[4], int x, int y, void *d
void ErodeDistanceOperation::executeOpenCL(OpenCLDevice *device,
MemoryBuffer *outputMemoryBuffer, cl_mem clOutputBuffer,
MemoryBuffer **inputMemoryBuffers, list<cl_mem> *clMemToCleanUp,
- list<cl_kernel> *clKernelsToCleanUp)
+ list<cl_kernel> * /*clKernelsToCleanUp*/)
{
cl_kernel erodeKernel = device->COM_clCreateKernel("erodeKernel", NULL);
@@ -383,7 +382,7 @@ void *DilateStepOperation::initializeTileData(rcti *rect)
buf[x] = -FLT_MAX;
}
for (x = xmin; x < xmax; ++x) {
- buf[x - rect->xmin + window - 1] = buffer[4 * (y * width + x)];
+ buf[x - rect->xmin + window - 1] = buffer[(y * width + x)];
}
for (i = 0; i < (bwidth + 3 * half_window) / window; i++) {
@@ -447,7 +446,7 @@ void DilateStepOperation::deinitExecution()
this->m_inputProgram = NULL;
}
-void DilateStepOperation::deinitializeTileData(rcti *rect, void *data)
+void DilateStepOperation::deinitializeTileData(rcti * /*rect*/, void *data)
{
tile_info *tile = (tile_info *)data;
MEM_freeN(tile->buffer);
@@ -510,7 +509,7 @@ void *ErodeStepOperation::initializeTileData(rcti *rect)
buf[x] = FLT_MAX;
}
for (x = xmin; x < xmax; ++x) {
- buf[x - rect->xmin + window - 1] = buffer[4 * (y * width + x)];
+ buf[x - rect->xmin + window - 1] = buffer[(y * width + x)];
}
for (i = 0; i < (bwidth + 3 * half_window) / window; i++) {
diff --git a/source/blender/compositor/operations/COM_DirectionalBlurOperation.cpp b/source/blender/compositor/operations/COM_DirectionalBlurOperation.cpp
index 67f52934b13..14881ebb265 100644
--- a/source/blender/compositor/operations/COM_DirectionalBlurOperation.cpp
+++ b/source/blender/compositor/operations/COM_DirectionalBlurOperation.cpp
@@ -60,25 +60,25 @@ void DirectionalBlurOperation::initExecution()
this->m_center_y_pix = center_y * height;
this->m_tx = itsc * D * cosf(a);
- this->m_ty = -itsc *D *sinf(a);
+ this->m_ty = -itsc * D * sinf(a);
this->m_sc = itsc * zoom;
this->m_rot = itsc * spin;
}
-void DirectionalBlurOperation::executePixel(float output[4], int x, int y, void *data)
+void DirectionalBlurOperation::executePixel(float output[4], int x, int y, void * /*data*/)
{
const int iterations = pow(2.0f, this->m_data->iter);
- float col[4] = {0, 0, 0, 0};
- float col2[4] = {0, 0, 0, 0};
- this->m_inputProgram->readSampled(col2, x, y, COM_PS_NEAREST);
+ float col[4] = {0.0f, 0.0f, 0.0f, 0.0f};
+ float col2[4] = {0.0f, 0.0f, 0.0f, 0.0f};
+ this->m_inputProgram->readSampled(col2, x, y, COM_PS_BILINEAR);
float ltx = this->m_tx;
float lty = this->m_ty;
float lsc = this->m_sc;
float lrot = this->m_rot;
/* blur the image */
for (int i = 0; i < iterations; ++i) {
- const float cs = cos(lrot), ss = sin(lrot);
+ const float cs = cosf(lrot), ss = sinf(lrot);
const float isc = 1.0f / (1.0f + lsc);
const float v = isc * (y - this->m_center_y_pix) + lty;
@@ -87,7 +87,7 @@ void DirectionalBlurOperation::executePixel(float output[4], int x, int y, void
this->m_inputProgram->readSampled(col,
cs * u + ss * v + this->m_center_x_pix,
cs * v - ss * u + this->m_center_y_pix,
- COM_PS_NEAREST);
+ COM_PS_BILINEAR);
add_v4_v4(col2, col);
@@ -104,7 +104,7 @@ void DirectionalBlurOperation::executePixel(float output[4], int x, int y, void
void DirectionalBlurOperation::executeOpenCL(OpenCLDevice *device,
MemoryBuffer *outputMemoryBuffer, cl_mem clOutputBuffer,
MemoryBuffer **inputMemoryBuffers, list<cl_mem> *clMemToCleanUp,
- list<cl_kernel> *clKernelsToCleanUp)
+ list<cl_kernel> * /*clKernelsToCleanUp*/)
{
cl_kernel directionalBlurKernel = device->COM_clCreateKernel("directionalBlurKernel", NULL);
@@ -132,7 +132,7 @@ void DirectionalBlurOperation::deinitExecution()
this->m_inputProgram = NULL;
}
-bool DirectionalBlurOperation::determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output)
+bool DirectionalBlurOperation::determineDependingAreaOfInterest(rcti * /*input*/, ReadBufferOperation *readOperation, rcti *output)
{
rcti newInput;
diff --git a/source/blender/compositor/operations/COM_DisplaceOperation.cpp b/source/blender/compositor/operations/COM_DisplaceOperation.cpp
index 7dacc3239c5..9b3377e887a 100644
--- a/source/blender/compositor/operations/COM_DisplaceOperation.cpp
+++ b/source/blender/compositor/operations/COM_DisplaceOperation.cpp
@@ -49,15 +49,19 @@ void DisplaceOperation::initExecution()
this->m_height_x4 = this->getHeight() * 4;
}
-void DisplaceOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler)
+void DisplaceOperation::executePixelSampled(float output[4], float x, float y, PixelSampler /*sampler*/)
{
float xy[2] = { x, y };
float uv[2], deriv[2][2];
pixelTransform(xy, uv, deriv);
-
- /* 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);
+ if (is_zero_v2(deriv[0]) && is_zero_v2(deriv[1])) {
+ this->m_inputColorProgram->readSampled(output, uv[0], uv[1], COM_PS_BILINEAR);
+ }
+ else {
+ /* EWA filtering (without nearest it gets blurry with NO distortion) */
+ this->m_inputColorProgram->readFiltered(output, uv[0], uv[1], deriv[0], deriv[1]);
+ }
}
bool DisplaceOperation::read_displacement(float x, float y, float xscale, float yscale, const float origin[2], float &r_u, float &r_v)
diff --git a/source/blender/compositor/operations/COM_DoubleEdgeMaskOperation.cpp b/source/blender/compositor/operations/COM_DoubleEdgeMaskOperation.cpp
index 5006720f091..76afedf4b2a 100644
--- a/source/blender/compositor/operations/COM_DoubleEdgeMaskOperation.cpp
+++ b/source/blender/compositor/operations/COM_DoubleEdgeMaskOperation.cpp
@@ -1237,7 +1237,7 @@ DoubleEdgeMaskOperation::DoubleEdgeMaskOperation() : NodeOperation()
this->setComplex(true);
}
-bool DoubleEdgeMaskOperation::determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output)
+bool DoubleEdgeMaskOperation::determineDependingAreaOfInterest(rcti * /*input*/, ReadBufferOperation *readOperation, rcti *output)
{
if (this->m_cachedInstance == NULL) {
rcti newInput;
@@ -1270,11 +1270,9 @@ void *DoubleEdgeMaskOperation::initializeTileData(rcti *rect)
MemoryBuffer *innerMask = (MemoryBuffer *)this->m_inputInnerMask->initializeTileData(rect);
MemoryBuffer *outerMask = (MemoryBuffer *)this->m_inputOuterMask->initializeTileData(rect);
float *data = (float *)MEM_mallocN(sizeof(float) * this->getWidth() * this->getHeight(), __func__);
- float *imask = innerMask->convertToValueBuffer();
- float *omask = outerMask->convertToValueBuffer();
+ float *imask = innerMask->getBuffer();
+ float *omask = outerMask->getBuffer();
doDoubleEdgeMask(imask, omask, data);
- MEM_freeN(imask);
- MEM_freeN(omask);
this->m_cachedInstance = data;
}
unlockMutex();
diff --git a/source/blender/compositor/operations/COM_FastGaussianBlurOperation.cpp b/source/blender/compositor/operations/COM_FastGaussianBlurOperation.cpp
index 705a8c07381..968319b3f46 100644
--- a/source/blender/compositor/operations/COM_FastGaussianBlurOperation.cpp
+++ b/source/blender/compositor/operations/COM_FastGaussianBlurOperation.cpp
@@ -37,7 +37,7 @@ void FastGaussianBlurOperation::executePixel(float output[4], int x, int y, void
newData->read(output, x, y);
}
-bool FastGaussianBlurOperation::determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output)
+bool FastGaussianBlurOperation::determineDependingAreaOfInterest(rcti * /*input*/, ReadBufferOperation *readOperation, rcti *output)
{
rcti newInput;
rcti sizeInput;
@@ -92,16 +92,16 @@ void *FastGaussianBlurOperation::initializeTileData(rcti *rect)
this->m_sy = this->m_data.sizey * this->m_size / 2.0f;
if ((this->m_sx == this->m_sy) && (this->m_sx > 0.f)) {
- for (c = 0; c < COM_NUMBER_OF_CHANNELS; ++c)
+ for (c = 0; c < COM_NUM_CHANNELS_COLOR; ++c)
IIR_gauss(copy, this->m_sx, c, 3);
}
else {
if (this->m_sx > 0.0f) {
- for (c = 0; c < COM_NUMBER_OF_CHANNELS; ++c)
+ for (c = 0; c < COM_NUM_CHANNELS_COLOR; ++c)
IIR_gauss(copy, this->m_sx, c, 1);
}
if (this->m_sy > 0.0f) {
- for (c = 0; c < COM_NUMBER_OF_CHANNELS; ++c)
+ for (c = 0; c < COM_NUM_CHANNELS_COLOR; ++c)
IIR_gauss(copy, this->m_sy, c, 2);
}
}
@@ -120,6 +120,7 @@ void FastGaussianBlurOperation::IIR_gauss(MemoryBuffer *src, float sigma, unsign
unsigned int x, y, sz;
unsigned int i;
float *buffer = src->getBuffer();
+ const unsigned int num_channels = src->get_num_channels();
// <0.5 not valid, though can have a possibly useful sort of sharpening effect
if (sigma < 0.5f) return;
@@ -198,31 +199,31 @@ void FastGaussianBlurOperation::IIR_gauss(MemoryBuffer *src, float sigma, unsign
int offset;
for (y = 0; y < src_height; ++y) {
const int yx = y * src_width;
- offset = yx * COM_NUMBER_OF_CHANNELS + chan;
+ offset = yx * num_channels + chan;
for (x = 0; x < src_width; ++x) {
X[x] = buffer[offset];
- offset += COM_NUMBER_OF_CHANNELS;
+ offset += num_channels;
}
YVV(src_width);
- offset = yx * COM_NUMBER_OF_CHANNELS + chan;
+ offset = yx * num_channels + chan;
for (x = 0; x < src_width; ++x) {
buffer[offset] = Y[x];
- offset += COM_NUMBER_OF_CHANNELS;
+ offset += num_channels;
}
}
}
if (xy & 2) { // V
int offset;
- const int add = src_width * COM_NUMBER_OF_CHANNELS;
+ const int add = src_width * num_channels;
for (x = 0; x < src_width; ++x) {
- offset = x * COM_NUMBER_OF_CHANNELS + chan;
+ offset = x * num_channels + chan;
for (y = 0; y < src_height; ++y) {
X[y] = buffer[offset];
offset += add;
}
YVV(src_height);
- offset = x * COM_NUMBER_OF_CHANNELS + chan;
+ offset = x * num_channels + chan;
for (y = 0; y < src_height; ++y) {
buffer[offset] = Y[y];
offset += add;
@@ -256,7 +257,7 @@ void FastGaussianBlurValueOperation::executePixel(float output[4], int x, int y,
newData->read(output, x, y);
}
-bool FastGaussianBlurValueOperation::determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output)
+bool FastGaussianBlurValueOperation::determineDependingAreaOfInterest(rcti * /*input*/, ReadBufferOperation *readOperation, rcti *output)
{
rcti newInput;
@@ -298,7 +299,7 @@ void *FastGaussianBlurValueOperation::initializeTileData(rcti *rect)
if (this->m_overlay == FAST_GAUSS_OVERLAY_MIN) {
float *src = newBuf->getBuffer();
float *dst = copy->getBuffer();
- for (int i = copy->getWidth() * copy->getHeight(); i != 0; i--, src += COM_NUMBER_OF_CHANNELS, dst += COM_NUMBER_OF_CHANNELS) {
+ for (int i = copy->getWidth() * copy->getHeight(); i != 0; i--, src += COM_NUM_CHANNELS_VALUE, dst += COM_NUM_CHANNELS_VALUE) {
if (*src < *dst) {
*dst = *src;
}
@@ -307,7 +308,7 @@ void *FastGaussianBlurValueOperation::initializeTileData(rcti *rect)
else if (this->m_overlay == FAST_GAUSS_OVERLAY_MAX) {
float *src = newBuf->getBuffer();
float *dst = copy->getBuffer();
- for (int i = copy->getWidth() * copy->getHeight(); i != 0; i--, src += COM_NUMBER_OF_CHANNELS, dst += COM_NUMBER_OF_CHANNELS) {
+ for (int i = copy->getWidth() * copy->getHeight(); i != 0; i--, src += COM_NUM_CHANNELS_VALUE, dst += COM_NUM_CHANNELS_VALUE) {
if (*src > *dst) {
*dst = *src;
}
diff --git a/source/blender/compositor/operations/COM_FlipOperation.cpp b/source/blender/compositor/operations/COM_FlipOperation.cpp
index 3de2ae9dabc..7ff7d694fa8 100644
--- a/source/blender/compositor/operations/COM_FlipOperation.cpp
+++ b/source/blender/compositor/operations/COM_FlipOperation.cpp
@@ -44,8 +44,8 @@ void FlipOperation::deinitExecution()
void FlipOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler)
{
- float nx = this->m_flipX ? this->getWidth() - 1 - x : x;
- float ny = this->m_flipY ? this->getHeight() - 1 - y : y;
+ float nx = this->m_flipX ? ((int)this->getWidth() - 1) - x : x;
+ float ny = this->m_flipY ? ((int)this->getHeight() - 1) - y : y;
this->m_inputOperation->readSampled(output, nx, ny, sampler);
}
@@ -55,16 +55,18 @@ bool FlipOperation::determineDependingAreaOfInterest(rcti *input, ReadBufferOper
rcti newInput;
if (this->m_flipX) {
- newInput.xmax = (this->getWidth() - 1 - input->xmin) + 1;
- newInput.xmin = (this->getWidth() - 1 - input->xmax) - 1;
+ const int w = (int)this->getWidth() - 1;
+ newInput.xmax = (w - input->xmin) + 1;
+ newInput.xmin = (w - input->xmax) - 1;
}
else {
newInput.xmin = input->xmin;
newInput.xmax = input->xmax;
}
if (this->m_flipY) {
- newInput.ymax = (this->getHeight() - 1 - input->ymin) + 1;
- newInput.ymin = (this->getHeight() - 1 - input->ymax) - 1;
+ const int h = (int)this->getHeight() - 1;
+ newInput.ymax = (h - input->ymin) + 1;
+ newInput.ymin = (h - input->ymax) - 1;
}
else {
newInput.ymin = input->ymin;
diff --git a/source/blender/compositor/operations/COM_GaussianAlphaXBlurOperation.cpp b/source/blender/compositor/operations/COM_GaussianAlphaXBlurOperation.cpp
index c78347e7b1c..cbe41076b2a 100644
--- a/source/blender/compositor/operations/COM_GaussianAlphaXBlurOperation.cpp
+++ b/source/blender/compositor/operations/COM_GaussianAlphaXBlurOperation.cpp
@@ -36,7 +36,7 @@ GaussianAlphaXBlurOperation::GaussianAlphaXBlurOperation() : BlurBaseOperation(C
this->m_falloff = -1; /* intentionally invalid, so we can detect uninitialized values */
}
-void *GaussianAlphaXBlurOperation::initializeTileData(rcti *rect)
+void *GaussianAlphaXBlurOperation::initializeTileData(rcti * /*rect*/)
{
lockMutex();
if (!this->m_sizeavailable) {
@@ -102,15 +102,14 @@ void GaussianAlphaXBlurOperation::executePixel(float output[4], int x, int y, vo
/* *** this is the main part which is different to 'GaussianXBlurOperation' *** */
int step = getStep();
- int offsetadd = getOffsetAdd();
- int bufferindex = ((xmin - bufferstartx) * 4) + ((ymin - bufferstarty) * 4 * bufferwidth);
+ int bufferindex = ((xmin - bufferstartx)) + ((ymin - bufferstarty) * bufferwidth);
/* gauss */
float alpha_accum = 0.0f;
float multiplier_accum = 0.0f;
/* dilate */
- float value_max = finv_test(buffer[(x * 4) + (y * 4 * bufferwidth)], do_invert); /* init with the current color to avoid unneeded lookups */
+ float value_max = finv_test(buffer[(x) + (y * bufferwidth)], do_invert); /* init with the current color to avoid unneeded lookups */
float distfacinv_max = 1.0f; /* 0 to 1 */
for (int nx = xmin; nx < xmax; nx += step) {
@@ -134,7 +133,7 @@ void GaussianAlphaXBlurOperation::executePixel(float output[4], int x, int y, vo
distfacinv_max = multiplier;
}
}
- bufferindex += offsetadd;
+ bufferindex += step;
}
/* blend between the max value and gauss blue - gives nice feather */
diff --git a/source/blender/compositor/operations/COM_GaussianAlphaYBlurOperation.cpp b/source/blender/compositor/operations/COM_GaussianAlphaYBlurOperation.cpp
index ab97c8b0d13..30563e8cc45 100644
--- a/source/blender/compositor/operations/COM_GaussianAlphaYBlurOperation.cpp
+++ b/source/blender/compositor/operations/COM_GaussianAlphaYBlurOperation.cpp
@@ -36,7 +36,7 @@ GaussianAlphaYBlurOperation::GaussianAlphaYBlurOperation() : BlurBaseOperation(C
this->m_falloff = -1; /* intentionally invalid, so we can detect uninitialized values */
}
-void *GaussianAlphaYBlurOperation::initializeTileData(rcti *rect)
+void *GaussianAlphaYBlurOperation::initializeTileData(rcti * /*rect*/)
{
lockMutex();
if (!this->m_sizeavailable) {
@@ -108,11 +108,11 @@ void GaussianAlphaYBlurOperation::executePixel(float output[4], int x, int y, vo
float multiplier_accum = 0.0f;
/* dilate */
- float value_max = finv_test(buffer[(x * 4) + (y * 4 * bufferwidth)], do_invert); /* init with the current color to avoid unneeded lookups */
+ float value_max = finv_test(buffer[(x) + (y * bufferwidth)], do_invert); /* init with the current color to avoid unneeded lookups */
float distfacinv_max = 1.0f; /* 0 to 1 */
for (int ny = ymin; ny < ymax; ny += step) {
- int bufferindex = ((xmin - bufferstartx) * 4) + ((ny - bufferstarty) * 4 * bufferwidth);
+ int bufferindex = ((xmin - bufferstartx)) + ((ny - bufferstarty) * bufferwidth);
const int index = (ny - y) + this->m_filtersize;
float value = finv_test(buffer[bufferindex], do_invert);
diff --git a/source/blender/compositor/operations/COM_GaussianBokehBlurOperation.cpp b/source/blender/compositor/operations/COM_GaussianBokehBlurOperation.cpp
index 441b623b589..37d59229e50 100644
--- a/source/blender/compositor/operations/COM_GaussianBokehBlurOperation.cpp
+++ b/source/blender/compositor/operations/COM_GaussianBokehBlurOperation.cpp
@@ -32,7 +32,7 @@ GaussianBokehBlurOperation::GaussianBokehBlurOperation() : BlurBaseOperation(COM
this->m_gausstab = NULL;
}
-void *GaussianBokehBlurOperation::initializeTileData(rcti *rect)
+void *GaussianBokehBlurOperation::initializeTileData(rcti * /*rect*/)
{
lockMutex();
if (!this->m_sizeavailable) {
@@ -205,7 +205,7 @@ GaussianBlurReferenceOperation::GaussianBlurReferenceOperation() : BlurBaseOpera
this->m_maintabs = NULL;
}
-void *GaussianBlurReferenceOperation::initializeTileData(rcti *rect)
+void *GaussianBlurReferenceOperation::initializeTileData(rcti * /*rect*/)
{
void *buffer = getInputOperation(0)->initializeTileData(NULL);
return buffer;
@@ -296,7 +296,7 @@ void GaussianBlurReferenceOperation::executePixel(float output[4], int x, int y,
int minyr = y - refrady < 0 ? -y : -refrady;
int maxyr = y + refrady > imgy ? imgy - y : refrady;
- float *srcd = buffer + COM_NUMBER_OF_CHANNELS * ( (y + minyr) * imgx + x + minxr);
+ float *srcd = buffer + COM_NUM_CHANNELS_COLOR * ( (y + minyr) * imgx + x + minxr);
gausstabx = m_maintabs[refradx - 1];
gausstabcentx = gausstabx + refradx;
@@ -304,9 +304,9 @@ void GaussianBlurReferenceOperation::executePixel(float output[4], int x, int y,
gausstabcenty = gausstaby + refrady;
sum = gval = rval = bval = aval = 0.0f;
- for (i = minyr; i < maxyr; i++, srcd += COM_NUMBER_OF_CHANNELS * imgx) {
+ for (i = minyr; i < maxyr; i++, srcd += COM_NUM_CHANNELS_COLOR * imgx) {
src = srcd;
- for (j = minxr; j < maxxr; j++, src += COM_NUMBER_OF_CHANNELS) {
+ for (j = minxr; j < maxxr; j++, src += COM_NUM_CHANNELS_COLOR) {
val = gausstabcenty[i] * gausstabcentx[j];
sum += val;
diff --git a/source/blender/compositor/operations/COM_GaussianXBlurOperation.cpp b/source/blender/compositor/operations/COM_GaussianXBlurOperation.cpp
index 0aefba3bb7c..29ed4334412 100644
--- a/source/blender/compositor/operations/COM_GaussianXBlurOperation.cpp
+++ b/source/blender/compositor/operations/COM_GaussianXBlurOperation.cpp
@@ -21,6 +21,7 @@
*/
#include "COM_GaussianXBlurOperation.h"
+#include "COM_OpenCLDevice.h"
#include "BLI_math.h"
#include "MEM_guardedalloc.h"
@@ -37,7 +38,7 @@ GaussianXBlurOperation::GaussianXBlurOperation() : BlurBaseOperation(COM_DT_COLO
this->m_filtersize = 0;
}
-void *GaussianXBlurOperation::initializeTileData(rcti *rect)
+void *GaussianXBlurOperation::initializeTileData(rcti * /*rect*/)
{
lockMutex();
if (!this->m_sizeavailable) {
@@ -62,7 +63,6 @@ void GaussianXBlurOperation::initExecution()
this->m_gausstab = BlurBaseOperation::make_gausstab(rad, m_filtersize);
#ifdef __SSE2__
this->m_gausstab_sse = BlurBaseOperation::convert_gausstab_sse(this->m_gausstab,
- rad,
m_filtersize);
#endif
}
@@ -78,7 +78,6 @@ void GaussianXBlurOperation::updateGauss()
this->m_gausstab = BlurBaseOperation::make_gausstab(rad, m_filtersize);
#ifdef __SSE2__
this->m_gausstab_sse = BlurBaseOperation::convert_gausstab_sse(this->m_gausstab,
- rad,
m_filtersize);
#endif
}
@@ -124,6 +123,32 @@ void GaussianXBlurOperation::executePixel(float output[4], int x, int y, void *d
mul_v4_v4fl(output, color_accum, 1.0f / multiplier_accum);
}
+void GaussianXBlurOperation::executeOpenCL(OpenCLDevice *device,
+ MemoryBuffer *outputMemoryBuffer, cl_mem clOutputBuffer,
+ MemoryBuffer **inputMemoryBuffers, list<cl_mem> *clMemToCleanUp,
+ list<cl_kernel> * /*clKernelsToCleanUp*/)
+{
+ cl_kernel gaussianXBlurOperationKernel = device->COM_clCreateKernel("gaussianXBlurOperationKernel", NULL);
+ cl_int filter_size = this->m_filtersize;
+
+ cl_mem gausstab = clCreateBuffer(device->getContext(),
+ CL_MEM_READ_ONLY | CL_MEM_USE_HOST_PTR,
+ sizeof(float) * (this->m_filtersize * 2 + 1),
+ this->m_gausstab,
+ NULL);
+
+ device->COM_clAttachMemoryBufferToKernelParameter(gaussianXBlurOperationKernel, 0, 1, clMemToCleanUp, inputMemoryBuffers, this->m_inputProgram);
+ device->COM_clAttachOutputMemoryBufferToKernelParameter(gaussianXBlurOperationKernel, 2, clOutputBuffer);
+ device->COM_clAttachMemoryBufferOffsetToKernelParameter(gaussianXBlurOperationKernel, 3, outputMemoryBuffer);
+ clSetKernelArg(gaussianXBlurOperationKernel, 4, sizeof(cl_int), &filter_size);
+ device->COM_clAttachSizeToKernelParameter(gaussianXBlurOperationKernel, 5, this);
+ clSetKernelArg(gaussianXBlurOperationKernel, 6, sizeof(cl_mem), &gausstab);
+
+ device->COM_clEnqueueRange(gaussianXBlurOperationKernel, outputMemoryBuffer, 7, this);
+
+ clReleaseMemObject(gausstab);
+}
+
void GaussianXBlurOperation::deinitExecution()
{
BlurBaseOperation::deinitExecution();
diff --git a/source/blender/compositor/operations/COM_GaussianXBlurOperation.h b/source/blender/compositor/operations/COM_GaussianXBlurOperation.h
index e391320a007..d7ae8b1e3dc 100644
--- a/source/blender/compositor/operations/COM_GaussianXBlurOperation.h
+++ b/source/blender/compositor/operations/COM_GaussianXBlurOperation.h
@@ -40,7 +40,12 @@ public:
* @brief the inner loop of this program
*/
void executePixel(float output[4], int x, int y, void *data);
-
+
+ void executeOpenCL(OpenCLDevice *device,
+ MemoryBuffer *outputMemoryBuffer, cl_mem clOutputBuffer,
+ MemoryBuffer **inputMemoryBuffers, list<cl_mem> *clMemToCleanUp,
+ list<cl_kernel> *clKernelsToCleanUp);
+
/**
* @brief initialize the execution
*/
@@ -53,5 +58,9 @@ public:
void *initializeTileData(rcti *rect);
bool determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output);
+
+ void checkOpenCL() {
+ this->setOpenCL(m_data.sizex >= 128);
+ }
};
#endif
diff --git a/source/blender/compositor/operations/COM_GaussianYBlurOperation.cpp b/source/blender/compositor/operations/COM_GaussianYBlurOperation.cpp
index a05a1ab6a23..4b55333c08c 100644
--- a/source/blender/compositor/operations/COM_GaussianYBlurOperation.cpp
+++ b/source/blender/compositor/operations/COM_GaussianYBlurOperation.cpp
@@ -21,6 +21,7 @@
*/
#include "COM_GaussianYBlurOperation.h"
+#include "COM_OpenCLDevice.h"
#include "BLI_math.h"
#include "MEM_guardedalloc.h"
@@ -37,7 +38,7 @@ GaussianYBlurOperation::GaussianYBlurOperation() : BlurBaseOperation(COM_DT_COLO
this->m_filtersize = 0;
}
-void *GaussianYBlurOperation::initializeTileData(rcti *rect)
+void *GaussianYBlurOperation::initializeTileData(rcti * /*rect*/)
{
lockMutex();
if (!this->m_sizeavailable) {
@@ -61,7 +62,6 @@ void GaussianYBlurOperation::initExecution()
this->m_gausstab = BlurBaseOperation::make_gausstab(rad, m_filtersize);
#ifdef __SSE2__
this->m_gausstab_sse = BlurBaseOperation::convert_gausstab_sse(this->m_gausstab,
- rad,
m_filtersize);
#endif
}
@@ -77,7 +77,6 @@ void GaussianYBlurOperation::updateGauss()
this->m_gausstab = BlurBaseOperation::make_gausstab(rad, m_filtersize);
#ifdef __SSE2__
this->m_gausstab_sse = BlurBaseOperation::convert_gausstab_sse(this->m_gausstab,
- rad,
m_filtersize);
#endif
}
@@ -126,6 +125,32 @@ void GaussianYBlurOperation::executePixel(float output[4], int x, int y, void *d
mul_v4_v4fl(output, color_accum, 1.0f / multiplier_accum);
}
+void GaussianYBlurOperation::executeOpenCL(OpenCLDevice *device,
+ MemoryBuffer *outputMemoryBuffer, cl_mem clOutputBuffer,
+ MemoryBuffer **inputMemoryBuffers, list<cl_mem> *clMemToCleanUp,
+ list<cl_kernel> * /*clKernelsToCleanUp*/)
+{
+ cl_kernel gaussianYBlurOperationKernel = device->COM_clCreateKernel("gaussianYBlurOperationKernel", NULL);
+ cl_int filter_size = this->m_filtersize;
+
+ cl_mem gausstab = clCreateBuffer(device->getContext(),
+ CL_MEM_READ_ONLY | CL_MEM_USE_HOST_PTR,
+ sizeof(float) * (this->m_filtersize * 2 + 1),
+ this->m_gausstab,
+ NULL);
+
+ device->COM_clAttachMemoryBufferToKernelParameter(gaussianYBlurOperationKernel, 0, 1, clMemToCleanUp, inputMemoryBuffers, this->m_inputProgram);
+ device->COM_clAttachOutputMemoryBufferToKernelParameter(gaussianYBlurOperationKernel, 2, clOutputBuffer);
+ device->COM_clAttachMemoryBufferOffsetToKernelParameter(gaussianYBlurOperationKernel, 3, outputMemoryBuffer);
+ clSetKernelArg(gaussianYBlurOperationKernel, 4, sizeof(cl_int), &filter_size);
+ device->COM_clAttachSizeToKernelParameter(gaussianYBlurOperationKernel, 5, this);
+ clSetKernelArg(gaussianYBlurOperationKernel, 6, sizeof(cl_mem), &gausstab);
+
+ device->COM_clEnqueueRange(gaussianYBlurOperationKernel, outputMemoryBuffer, 7, this);
+
+ clReleaseMemObject(gausstab);
+}
+
void GaussianYBlurOperation::deinitExecution()
{
BlurBaseOperation::deinitExecution();
diff --git a/source/blender/compositor/operations/COM_GaussianYBlurOperation.h b/source/blender/compositor/operations/COM_GaussianYBlurOperation.h
index 22b6562077d..4b5751c0968 100644
--- a/source/blender/compositor/operations/COM_GaussianYBlurOperation.h
+++ b/source/blender/compositor/operations/COM_GaussianYBlurOperation.h
@@ -40,7 +40,12 @@ public:
* the inner loop of this program
*/
void executePixel(float output[4], int x, int y, void *data);
-
+
+ void executeOpenCL(OpenCLDevice *device,
+ MemoryBuffer *outputMemoryBuffer, cl_mem clOutputBuffer,
+ MemoryBuffer **inputMemoryBuffers, list<cl_mem> *clMemToCleanUp,
+ list<cl_kernel> *clKernelsToCleanUp);
+
/**
* @brief initialize the execution
*/
@@ -53,5 +58,9 @@ public:
void *initializeTileData(rcti *rect);
bool determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output);
+
+ void checkOpenCL() {
+ this->setOpenCL(m_data.sizex >= 128);
+ }
};
#endif
diff --git a/source/blender/compositor/operations/COM_GlareBaseOperation.cpp b/source/blender/compositor/operations/COM_GlareBaseOperation.cpp
index 99c745d7fb0..1acbd2ae090 100644
--- a/source/blender/compositor/operations/COM_GlareBaseOperation.cpp
+++ b/source/blender/compositor/operations/COM_GlareBaseOperation.cpp
@@ -49,13 +49,13 @@ MemoryBuffer *GlareBaseOperation::createMemoryBuffer(rcti *rect2)
rect.ymin = 0;
rect.xmax = getWidth();
rect.ymax = getHeight();
- MemoryBuffer *result = new MemoryBuffer(NULL, &rect);
+ MemoryBuffer *result = new MemoryBuffer(COM_DT_COLOR, &rect);
float *data = result->getBuffer();
this->generateGlare(data, tile, this->m_settings);
return result;
}
-bool GlareBaseOperation::determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output)
+bool GlareBaseOperation::determineDependingAreaOfInterest(rcti * /*input*/, ReadBufferOperation *readOperation, rcti *output)
{
if (isCached()) {
return false;
diff --git a/source/blender/compositor/operations/COM_GlareFogGlowOperation.cpp b/source/blender/compositor/operations/COM_GlareFogGlowOperation.cpp
index 99a7c5b64c4..04993b08ddf 100644
--- a/source/blender/compositor/operations/COM_GlareFogGlowOperation.cpp
+++ b/source/blender/compositor/operations/COM_GlareFogGlowOperation.cpp
@@ -259,8 +259,8 @@ static void convolve(float *dst, MemoryBuffer *in1, MemoryBuffer *in2)
float *kernelBuffer = in2->getBuffer();
float *imageBuffer = in1->getBuffer();
- MemoryBuffer *rdst = new MemoryBuffer(NULL, in1->getRect());
- memset(rdst->getBuffer(), 0, rdst->getWidth() * rdst->getHeight() * COM_NUMBER_OF_CHANNELS * sizeof(float));
+ MemoryBuffer *rdst = new MemoryBuffer(COM_DT_COLOR, in1->getRect());
+ memset(rdst->getBuffer(), 0, rdst->getWidth() * rdst->getHeight() * COM_NUM_CHANNELS_COLOR * sizeof(float));
// convolution result width & height
w2 = 2 * kernelWidth - 1;
@@ -276,7 +276,7 @@ static void convolve(float *dst, MemoryBuffer *in1, MemoryBuffer *in2)
// normalize convolutor
wt[0] = wt[1] = wt[2] = 0.f;
for (y = 0; y < kernelHeight; y++) {
- colp = (fRGB *)&kernelBuffer[y * kernelWidth * COM_NUMBER_OF_CHANNELS];
+ colp = (fRGB *)&kernelBuffer[y * kernelWidth * COM_NUM_CHANNELS_COLOR];
for (x = 0; x < kernelWidth; x++)
add_v3_v3(wt, colp[x]);
}
@@ -284,7 +284,7 @@ static void convolve(float *dst, MemoryBuffer *in1, MemoryBuffer *in2)
if (wt[1] != 0.f) wt[1] = 1.f / wt[1];
if (wt[2] != 0.f) wt[2] = 1.f / wt[2];
for (y = 0; y < kernelHeight; y++) {
- colp = (fRGB *)&kernelBuffer[y * kernelWidth * COM_NUMBER_OF_CHANNELS];
+ colp = (fRGB *)&kernelBuffer[y * kernelWidth * COM_NUM_CHANNELS_COLOR];
for (x = 0; x < kernelWidth; x++)
mul_v3_v3(colp[x], wt);
}
@@ -313,7 +313,7 @@ static void convolve(float *dst, MemoryBuffer *in1, MemoryBuffer *in2)
// in2, channel ch -> data1
for (y = 0; y < kernelHeight; y++) {
fp = &data1ch[y * w2];
- colp = (fRGB *)&kernelBuffer[y * kernelWidth * COM_NUMBER_OF_CHANNELS];
+ colp = (fRGB *)&kernelBuffer[y * kernelWidth * COM_NUM_CHANNELS_COLOR];
for (x = 0; x < kernelWidth; x++)
fp[x] = colp[x][ch];
}
@@ -325,7 +325,7 @@ static void convolve(float *dst, MemoryBuffer *in1, MemoryBuffer *in2)
int yy = ybl * ybsz + y;
if (yy >= imageHeight) continue;
fp = &data2[y * w2];
- colp = (fRGB *)&imageBuffer[yy * imageWidth * COM_NUMBER_OF_CHANNELS];
+ colp = (fRGB *)&imageBuffer[yy * imageWidth * COM_NUM_CHANNELS_COLOR];
for (x = 0; x < xbsz; x++) {
int xx = xbl * xbsz + x;
if (xx >= imageWidth) continue;
@@ -349,7 +349,7 @@ static void convolve(float *dst, MemoryBuffer *in1, MemoryBuffer *in2)
const int yy = ybl * ybsz + y - hh;
if ((yy < 0) || (yy >= imageHeight)) continue;
fp = &data2[y * w2];
- colp = (fRGB *)&rdst->getBuffer()[yy * imageWidth * COM_NUMBER_OF_CHANNELS];
+ colp = (fRGB *)&rdst->getBuffer()[yy * imageWidth * COM_NUM_CHANNELS_COLOR];
for (x = 0; x < (int)w2; x++) {
const int xx = xbl * xbsz + x - hw;
if ((xx < 0) || (xx >= imageWidth)) continue;
@@ -364,7 +364,7 @@ static void convolve(float *dst, MemoryBuffer *in1, MemoryBuffer *in2)
MEM_freeN(data2);
MEM_freeN(data1);
- memcpy(dst, rdst->getBuffer(), sizeof(float) * imageWidth * imageHeight * COM_NUMBER_OF_CHANNELS);
+ memcpy(dst, rdst->getBuffer(), sizeof(float) * imageWidth * imageHeight * COM_NUM_CHANNELS_COLOR);
delete(rdst);
}
@@ -381,7 +381,7 @@ void GlareFogGlowOperation::generateGlare(float *data, MemoryBuffer *inputTile,
// make the convolution kernel
rcti kernelRect;
BLI_rcti_init(&kernelRect, 0, sz, 0, sz);
- ckrn = new MemoryBuffer(NULL, &kernelRect);
+ ckrn = new MemoryBuffer(COM_DT_COLOR, &kernelRect);
scale = 0.25f * sqrtf((float)(sz * sz));
diff --git a/source/blender/compositor/operations/COM_GlareGhostOperation.cpp b/source/blender/compositor/operations/COM_GlareGhostOperation.cpp
index 8854be52ded..eea6588a9a6 100644
--- a/source/blender/compositor/operations/COM_GlareGhostOperation.cpp
+++ b/source/blender/compositor/operations/COM_GlareGhostOperation.cpp
@@ -65,7 +65,7 @@ void GlareGhostOperation::generateGlare(float *data, MemoryBuffer *inputTile, No
if (isBreaked()) breaked = true;
if (!breaked) FastGaussianBlurOperation::IIR_gauss(tbuf2, s2, 2, 3);
- if (settings->iter & 1) ofs = 0.5f; else ofs = 0.f;
+ ofs = (settings->iter & 1) ? 0.5f : 0.0f;
for (x = 0; x < (settings->iter * 4); x++) {
y = x & 3;
cm[x][0] = cm[x][1] = cm[x][2] = 1;
@@ -97,7 +97,7 @@ void GlareGhostOperation::generateGlare(float *data, MemoryBuffer *inputTile, No
}
- memset(tbuf1->getBuffer(), 0, tbuf1->getWidth() * tbuf1->getHeight() * COM_NUMBER_OF_CHANNELS * sizeof(float));
+ memset(tbuf1->getBuffer(), 0, tbuf1->getWidth() * tbuf1->getHeight() * COM_NUM_CHANNELS_COLOR * sizeof(float));
for (n = 1; n < settings->iter && (!breaked); n++) {
for (y = 0; y < gbuf->getHeight() && (!breaked); y++) {
v = ((float)y + 0.5f) / (float)gbuf->getHeight();
@@ -117,9 +117,9 @@ void GlareGhostOperation::generateGlare(float *data, MemoryBuffer *inputTile, No
}
if (isBreaked()) breaked = true;
}
- memcpy(gbuf->getBuffer(), tbuf1->getBuffer(), tbuf1->getWidth() * tbuf1->getHeight() * COM_NUMBER_OF_CHANNELS * sizeof(float));
+ memcpy(gbuf->getBuffer(), tbuf1->getBuffer(), tbuf1->getWidth() * tbuf1->getHeight() * COM_NUM_CHANNELS_COLOR * sizeof(float));
}
- memcpy(data, gbuf->getBuffer(), gbuf->getWidth() * gbuf->getHeight() * COM_NUMBER_OF_CHANNELS * sizeof(float));
+ memcpy(data, gbuf->getBuffer(), gbuf->getWidth() * gbuf->getHeight() * COM_NUM_CHANNELS_COLOR * sizeof(float));
delete gbuf;
delete tbuf1;
diff --git a/source/blender/compositor/operations/COM_GlareStreaksOperation.cpp b/source/blender/compositor/operations/COM_GlareStreaksOperation.cpp
index 5644ff30ef3..deeb5094bd0 100644
--- a/source/blender/compositor/operations/COM_GlareStreaksOperation.cpp
+++ b/source/blender/compositor/operations/COM_GlareStreaksOperation.cpp
@@ -36,7 +36,7 @@ void GlareStreaksOperation::generateGlare(float *data, MemoryBuffer *inputTile,
bool breaked = false;
MemoryBuffer *tsrc = inputTile->duplicate();
- MemoryBuffer *tdst = new MemoryBuffer(NULL, inputTile->getRect());
+ MemoryBuffer *tdst = new MemoryBuffer(COM_DT_COLOR, inputTile->getRect());
tdst->clear();
memset(data, 0, size4 * sizeof(float));
diff --git a/source/blender/compositor/operations/COM_GlareThresholdOperation.cpp b/source/blender/compositor/operations/COM_GlareThresholdOperation.cpp
index 78e1e80cafc..d2bd7cbeeab 100644
--- a/source/blender/compositor/operations/COM_GlareThresholdOperation.cpp
+++ b/source/blender/compositor/operations/COM_GlareThresholdOperation.cpp
@@ -23,6 +23,10 @@
#include "COM_GlareThresholdOperation.h"
#include "BLI_math.h"
+extern "C" {
+#include "IMB_colormanagement.h"
+}
+
GlareThresholdOperation::GlareThresholdOperation() : NodeOperation()
{
this->addInputSocket(COM_DT_COLOR, COM_SC_FIT);
@@ -47,7 +51,7 @@ void GlareThresholdOperation::executePixelSampled(float output[4], float x, floa
const float threshold = this->m_settings->threshold;
this->m_inputProgram->readSampled(output, x, y, sampler);
- if (rgb_to_luma_y(output) >= threshold) {
+ if (IMB_colormanagement_get_luminance(output) >= threshold) {
output[0] -= threshold, output[1] -= threshold, output[2] -= threshold;
output[0] = max(output[0], 0.0f);
output[1] = max(output[1], 0.0f);
diff --git a/source/blender/compositor/operations/COM_ImageOperation.cpp b/source/blender/compositor/operations/COM_ImageOperation.cpp
index 2733c483146..c55366ab370 100644
--- a/source/blender/compositor/operations/COM_ImageOperation.cpp
+++ b/source/blender/compositor/operations/COM_ImageOperation.cpp
@@ -25,6 +25,7 @@
#include "BLI_listbase.h"
#include "DNA_image_types.h"
#include "BKE_image.h"
+#include "BKE_scene.h"
#include "BLI_math.h"
extern "C" {
@@ -48,6 +49,8 @@ BaseImageOperation::BaseImageOperation() : NodeOperation()
this->m_framenumber = 0;
this->m_depthBuffer = NULL;
this->m_numberOfChannels = 0;
+ this->m_rd = NULL;
+ this->m_viewName = NULL;
}
ImageOperation::ImageOperation() : BaseImageOperation()
{
@@ -65,8 +68,16 @@ ImageDepthOperation::ImageDepthOperation() : BaseImageOperation()
ImBuf *BaseImageOperation::getImBuf()
{
ImBuf *ibuf;
-
- ibuf = BKE_image_acquire_ibuf(this->m_image, this->m_imageUser, NULL);
+ ImageUser iuser = *this->m_imageUser;
+
+ if (this->m_image == NULL)
+ return NULL;
+
+ /* local changes to the original ImageUser */
+ if (BKE_image_is_multilayer(this->m_image) == false)
+ iuser.multi_index = BKE_scene_multiview_view_id_get(this->m_rd, this->m_viewName);
+
+ ibuf = BKE_image_acquire_ibuf(this->m_image, &iuser, NULL);
if (ibuf == NULL || (ibuf->rect == NULL && ibuf->rect_float == NULL)) {
BKE_image_release_ibuf(this->m_image, ibuf, NULL);
return NULL;
@@ -96,7 +107,7 @@ void BaseImageOperation::deinitExecution()
BKE_image_release_ibuf(this->m_image, this->m_buffer, NULL);
}
-void BaseImageOperation::determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2])
+void BaseImageOperation::determineResolution(unsigned int resolution[2], unsigned int /*preferredResolution*/[2])
{
ImBuf *stackbuf = getImBuf();
@@ -170,7 +181,7 @@ void ImageAlphaOperation::executePixelSampled(float output[4], float x, float y,
}
}
-void ImageDepthOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler)
+void ImageDepthOperation::executePixelSampled(float output[4], float x, float y, PixelSampler /*sampler*/)
{
if (this->m_depthBuffer == NULL) {
output[0] = 0.0f;
diff --git a/source/blender/compositor/operations/COM_ImageOperation.h b/source/blender/compositor/operations/COM_ImageOperation.h
index 206f1509f60..75222559810 100644
--- a/source/blender/compositor/operations/COM_ImageOperation.h
+++ b/source/blender/compositor/operations/COM_ImageOperation.h
@@ -49,7 +49,9 @@ protected:
int m_imagewidth;
int m_framenumber;
int m_numberOfChannels;
-
+ const RenderData *m_rd;
+ const char *m_viewName;
+
BaseImageOperation();
/**
* Determine the output resolution. The resolution is retrieved from the Renderer
@@ -64,7 +66,8 @@ public:
void deinitExecution();
void setImage(Image *image) { this->m_image = image; }
void setImageUser(ImageUser *imageuser) { this->m_imageUser = imageuser; }
-
+ void setRenderData(const RenderData *rd) { this->m_rd = rd; }
+ void setViewName(const char *viewName) { this->m_viewName = viewName; }
void setFramenumber(int framenumber) { this->m_framenumber = framenumber; }
};
class ImageOperation : public BaseImageOperation {
diff --git a/source/blender/compositor/operations/COM_InpaintOperation.cpp b/source/blender/compositor/operations/COM_InpaintOperation.cpp
index b64c98be0c7..43b7b30319d 100644
--- a/source/blender/compositor/operations/COM_InpaintOperation.cpp
+++ b/source/blender/compositor/operations/COM_InpaintOperation.cpp
@@ -83,8 +83,8 @@ float *InpaintSimpleOperation::get_pixel(int x, int y)
ASSERT_XY_RANGE(x, y);
return &this->m_cached_buffer[
- y * width * COM_NUMBER_OF_CHANNELS +
- x * COM_NUMBER_OF_CHANNELS];
+ y * width * COM_NUM_CHANNELS_COLOR +
+ x * COM_NUM_CHANNELS_COLOR];
}
int InpaintSimpleOperation::mdist(int x, int y)
@@ -241,7 +241,7 @@ void *InpaintSimpleOperation::initializeTileData(rcti *rect)
return this->m_cached_buffer;
}
-void InpaintSimpleOperation::executePixel(float output[4], int x, int y, void *data)
+void InpaintSimpleOperation::executePixel(float output[4], int x, int y, void * /*data*/)
{
this->clamp_xy(x, y);
copy_v4_v4(output, this->get_pixel(x, y));
@@ -268,7 +268,7 @@ void InpaintSimpleOperation::deinitExecution()
this->m_cached_buffer_ready = false;
}
-bool InpaintSimpleOperation::determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output)
+bool InpaintSimpleOperation::determineDependingAreaOfInterest(rcti * /*input*/, ReadBufferOperation *readOperation, rcti *output)
{
if (this->m_cached_buffer_ready) {
return false;
diff --git a/source/blender/compositor/operations/COM_KeyingBlurOperation.cpp b/source/blender/compositor/operations/COM_KeyingBlurOperation.cpp
index 9fb9efe4fc7..72c7512cb23 100644
--- a/source/blender/compositor/operations/COM_KeyingBlurOperation.cpp
+++ b/source/blender/compositor/operations/COM_KeyingBlurOperation.cpp
@@ -49,37 +49,27 @@ void *KeyingBlurOperation::initializeTileData(rcti *rect)
void KeyingBlurOperation::executePixel(float output[4], int x, int y, void *data)
{
MemoryBuffer *inputBuffer = (MemoryBuffer *)data;
+ const int bufferWidth = inputBuffer->getWidth();
float *buffer = inputBuffer->getBuffer();
-
- int bufferWidth = inputBuffer->getWidth();
- int bufferHeight = inputBuffer->getHeight();
-
- int i, count = 0;
-
+ int count = 0;
float average = 0.0f;
if (this->m_axis == 0) {
- for (i = -this->m_size + 1; i < this->m_size; i++) {
- int cx = x + i;
-
- if (cx >= 0 && cx < bufferWidth) {
- int bufferIndex = (y * bufferWidth + cx) * 4;
-
- average += buffer[bufferIndex];
- count++;
- }
+ const int start = max(0, x - this->m_size + 1),
+ end = min(bufferWidth, x + this->m_size);
+ for (int cx = start; cx < end; ++cx) {
+ int bufferIndex = (y * bufferWidth + cx);
+ average += buffer[bufferIndex];
+ count++;
}
}
else {
- for (i = -this->m_size + 1; i < this->m_size; i++) {
- int cy = y + i;
-
- if (cy >= 0 && cy < bufferHeight) {
- int bufferIndex = (cy * bufferWidth + x) * 4;
-
- average += buffer[bufferIndex];
- count++;
- }
+ const int start = max(0, y - this->m_size + 1),
+ end = min(inputBuffer->getHeight(), y + this->m_size);
+ for (int cy = start; cy < end; ++cy) {
+ int bufferIndex = (cy * bufferWidth + x);
+ average += buffer[bufferIndex];
+ count++;
}
}
diff --git a/source/blender/compositor/operations/COM_KeyingClipOperation.cpp b/source/blender/compositor/operations/COM_KeyingClipOperation.cpp
index d9eb7b588a8..d4ba94f240f 100644
--- a/source/blender/compositor/operations/COM_KeyingClipOperation.cpp
+++ b/source/blender/compositor/operations/COM_KeyingClipOperation.cpp
@@ -62,7 +62,7 @@ void KeyingClipOperation::executePixel(float output[4], int x, int y, void *data
int bufferWidth = inputBuffer->getWidth();
int bufferHeight = inputBuffer->getHeight();
- float value = buffer[(y * bufferWidth + x) * 4];
+ float value = buffer[(y * bufferWidth + x)];
bool ok = false;
int start_x = max_ff(0, x - delta + 1),
@@ -83,7 +83,7 @@ void KeyingClipOperation::executePixel(float output[4], int x, int y, void *data
continue;
}
- int bufferIndex = (cy * bufferWidth + cx) * 4;
+ int bufferIndex = (cy * bufferWidth + cx);
float currentValue = buffer[bufferIndex];
if (fabsf(currentValue - value) < tolerance) {
diff --git a/source/blender/compositor/operations/COM_KeyingScreenOperation.cpp b/source/blender/compositor/operations/COM_KeyingScreenOperation.cpp
index 17b85847fcf..dd87578ea78 100644
--- a/source/blender/compositor/operations/COM_KeyingScreenOperation.cpp
+++ b/source/blender/compositor/operations/COM_KeyingScreenOperation.cpp
@@ -188,9 +188,9 @@ KeyingScreenOperation::TriangulationData *KeyingScreenOperation::buildVoronoiTri
BLI_freelistN(&edges);
if (triangulation->triangles_total) {
- rctf *rect;
+ rcti *rect;
rect = triangulation->triangles_AABB =
- (rctf *) MEM_callocN(sizeof(rctf) * triangulation->triangles_total, "voronoi triangulation AABB");
+ (rcti *) MEM_callocN(sizeof(rcti) * triangulation->triangles_total, "voronoi triangulation AABB");
for (i = 0; i < triangulation->triangles_total; i++, rect++) {
int *triangle = triangulation->triangles[i];
@@ -206,11 +206,11 @@ KeyingScreenOperation::TriangulationData *KeyingScreenOperation::buildVoronoiTri
minmax_v2v2_v2(min, max, b->co);
minmax_v2v2_v2(min, max, c->co);
- rect->xmin = min[0];
- rect->ymin = min[1];
+ rect->xmin = (int)min[0];
+ rect->ymin = (int)min[1];
- rect->xmax = max[0];
- rect->ymax = max[1];
+ rect->xmax = (int)max[0] + 1;
+ rect->ymax = (int)max[1] + 1;
}
}
@@ -224,7 +224,6 @@ void *KeyingScreenOperation::initializeTileData(rcti *rect)
int triangles_allocated = 0;
int chunk_size = 20;
int i;
- rctf rect_float;
if (this->m_movieClip == NULL)
return NULL;
@@ -242,14 +241,10 @@ void *KeyingScreenOperation::initializeTileData(rcti *rect)
if (!triangulation)
return NULL;
- BLI_rctf_init(&rect_float, rect->xmin, rect->xmax, rect->ymin, rect->ymax);
-
tile_data = (TileData *) MEM_callocN(sizeof(TileData), "keying screen tile data");
for (i = 0; i < triangulation->triangles_total; i++) {
- bool ok = BLI_rctf_isect(&rect_float, &triangulation->triangles_AABB[i], NULL);
-
- if (ok) {
+ if (BLI_rcti_isect(rect, &triangulation->triangles_AABB[i], NULL)) {
tile_data->triangles_total++;
if (tile_data->triangles_total > triangles_allocated) {
@@ -272,7 +267,7 @@ void *KeyingScreenOperation::initializeTileData(rcti *rect)
return tile_data;
}
-void KeyingScreenOperation::deinitializeTileData(rcti *rect, void *data)
+void KeyingScreenOperation::deinitializeTileData(rcti * /*rect*/, void *data)
{
TileData *tile_data = (TileData *) data;
@@ -283,7 +278,7 @@ void KeyingScreenOperation::deinitializeTileData(rcti *rect, void *data)
MEM_freeN(tile_data);
}
-void KeyingScreenOperation::determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2])
+void KeyingScreenOperation::determineResolution(unsigned int resolution[2], unsigned int /*preferredResolution*/[2])
{
resolution[0] = 0;
resolution[1] = 0;
@@ -316,7 +311,7 @@ void KeyingScreenOperation::executePixel(float output[4], int x, int y, void *da
for (i = 0; i < tile_data->triangles_total; i++) {
int triangle_idx = tile_data->triangles[i];
- rctf *rect = &triangulation->triangles_AABB[triangle_idx];
+ rcti *rect = &triangulation->triangles_AABB[triangle_idx];
if (IN_RANGE_INCL(x, rect->xmin, rect->xmax) && IN_RANGE_INCL(y, rect->ymin, rect->ymax)) {
int *triangle = triangulation->triangles[triangle_idx];
diff --git a/source/blender/compositor/operations/COM_KeyingScreenOperation.h b/source/blender/compositor/operations/COM_KeyingScreenOperation.h
index 10cf48e57f4..b1a5c0c39c7 100644
--- a/source/blender/compositor/operations/COM_KeyingScreenOperation.h
+++ b/source/blender/compositor/operations/COM_KeyingScreenOperation.h
@@ -47,7 +47,7 @@ protected:
VoronoiTriangulationPoint *triangulated_points;
int (*triangles)[3];
int triangulated_points_total, triangles_total;
- rctf *triangles_AABB;
+ rcti *triangles_AABB;
} TriangulationData;
typedef struct TileData {
diff --git a/source/blender/compositor/operations/COM_LuminanceMatteOperation.cpp b/source/blender/compositor/operations/COM_LuminanceMatteOperation.cpp
index 0e48d5963c6..50ac3b5e055 100644
--- a/source/blender/compositor/operations/COM_LuminanceMatteOperation.cpp
+++ b/source/blender/compositor/operations/COM_LuminanceMatteOperation.cpp
@@ -52,7 +52,7 @@ void LuminanceMatteOperation::executePixelSampled(float output[4], float x, floa
this->m_inputImageProgram->readSampled(inColor, x, y, sampler);
/* one line thread-friend algorithm:
- * output[0] = max(inputValue[3], min(high, max(low, ((inColor[0]-low)/(high-low))))
+ * output[0] = max(inputValue[3], min(high, max(low, ((inColor[0] - low) / (high - low))));
*/
/* test range */
diff --git a/source/blender/compositor/operations/COM_MapUVOperation.cpp b/source/blender/compositor/operations/COM_MapUVOperation.cpp
index 6bf730253e7..d091675286d 100644
--- a/source/blender/compositor/operations/COM_MapUVOperation.cpp
+++ b/source/blender/compositor/operations/COM_MapUVOperation.cpp
@@ -41,7 +41,7 @@ void MapUVOperation::initExecution()
this->m_inputUVProgram = this->getInputSocketReader(1);
}
-void MapUVOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler)
+void MapUVOperation::executePixelSampled(float output[4], float x, float y, PixelSampler /*sampler*/)
{
float xy[2] = { x, y };
float uv[2], deriv[2][2], alpha;
@@ -53,7 +53,7 @@ void MapUVOperation::executePixelSampled(float output[4], float x, float y, Pixe
}
/* EWA filtering */
- this->m_inputColorProgram->readFiltered(output, uv[0], uv[1], deriv[0], deriv[1], COM_PS_BILINEAR);
+ this->m_inputColorProgram->readFiltered(output, uv[0], uv[1], deriv[0], deriv[1]);
/* UV to alpha threshold */
const float threshold = this->m_alpha * 0.05f;
@@ -83,11 +83,11 @@ bool MapUVOperation::read_uv(float x, float y, float &r_u, float &r_v, float &r_
return false;
}
else {
- float col[4];
- m_inputUVProgram->readSampled(col, x, y, COM_PS_BILINEAR);
- r_u = col[0] * m_inputColorProgram->getWidth();
- r_v = col[1] * m_inputColorProgram->getHeight();
- r_alpha = col[2];
+ float vector[3];
+ m_inputUVProgram->readSampled(vector, x, y, COM_PS_BILINEAR);
+ r_u = vector[0] * m_inputColorProgram->getWidth();
+ r_v = vector[1] * m_inputColorProgram->getHeight();
+ r_alpha = vector[2];
return true;
}
}
diff --git a/source/blender/compositor/operations/COM_MaskOperation.cpp b/source/blender/compositor/operations/COM_MaskOperation.cpp
index 8c8ba93327d..220b4e908a6 100644
--- a/source/blender/compositor/operations/COM_MaskOperation.cpp
+++ b/source/blender/compositor/operations/COM_MaskOperation.cpp
@@ -1,4 +1,5 @@
/*
+
* Copyright 2012, Blender Foundation.
*
* This program is free software; you can redistribute it and/or
@@ -127,7 +128,7 @@ void MaskOperation::determineResolution(unsigned int resolution[2], unsigned int
}
}
-void MaskOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler)
+void MaskOperation::executePixelSampled(float output[4], float x, float y, PixelSampler /*sampler*/)
{
const float xy[2] = {
(x * this->m_maskWidthInv) + this->m_mask_px_ofs[0],
diff --git a/source/blender/compositor/operations/COM_MixOperation.cpp b/source/blender/compositor/operations/COM_MixOperation.cpp
index 04025329ad4..d379839a457 100644
--- a/source/blender/compositor/operations/COM_MixOperation.cpp
+++ b/source/blender/compositor/operations/COM_MixOperation.cpp
@@ -322,9 +322,9 @@ void MixDifferenceOperation::executePixelSampled(float output[4], float x, float
value *= inputColor2[3];
}
float valuem = 1.0f - value;
- output[0] = valuem * inputColor1[0] + value *fabsf(inputColor1[0] - inputColor2[0]);
- output[1] = valuem * inputColor1[1] + value *fabsf(inputColor1[1] - inputColor2[1]);
- output[2] = valuem * inputColor1[2] + value *fabsf(inputColor1[2] - inputColor2[2]);
+ output[0] = valuem * inputColor1[0] + value * fabsf(inputColor1[0] - inputColor2[0]);
+ output[1] = valuem * inputColor1[1] + value * fabsf(inputColor1[1] - inputColor2[1]);
+ output[2] = valuem * inputColor1[2] + value * fabsf(inputColor1[2] - inputColor2[2]);
output[3] = inputColor1[3];
clampIfNeeded(output);
diff --git a/source/blender/compositor/operations/COM_MixOperation.h b/source/blender/compositor/operations/COM_MixOperation.h
index 479ce161eea..d399edba6e9 100644
--- a/source/blender/compositor/operations/COM_MixOperation.h
+++ b/source/blender/compositor/operations/COM_MixOperation.h
@@ -76,7 +76,7 @@ public:
void setUseValueAlphaMultiply(const bool value) { this->m_valueAlphaMultiply = value; }
- bool useValueAlphaMultiply() { return this->m_valueAlphaMultiply; }
+ inline bool useValueAlphaMultiply() { return this->m_valueAlphaMultiply; }
void setUseClamp(bool value) { this->m_useClamp = value; }
};
diff --git a/source/blender/compositor/operations/COM_MovieClipAttributeOperation.cpp b/source/blender/compositor/operations/COM_MovieClipAttributeOperation.cpp
index 447ca1bb4f6..040a0315d69 100644
--- a/source/blender/compositor/operations/COM_MovieClipAttributeOperation.cpp
+++ b/source/blender/compositor/operations/COM_MovieClipAttributeOperation.cpp
@@ -33,7 +33,9 @@ MovieClipAttributeOperation::MovieClipAttributeOperation() : NodeOperation()
this->m_attribute = MCA_X;
}
-void MovieClipAttributeOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler)
+void MovieClipAttributeOperation::executePixelSampled(float output[4],
+ float /*x*/, float /*y*/,
+ PixelSampler /*sampler*/)
{
if (!this->m_valueSet) {
float loc[2], scale, angle;
diff --git a/source/blender/compositor/operations/COM_MovieClipOperation.cpp b/source/blender/compositor/operations/COM_MovieClipOperation.cpp
index 9a184ae1216..1e4821f0cd3 100644
--- a/source/blender/compositor/operations/COM_MovieClipOperation.cpp
+++ b/source/blender/compositor/operations/COM_MovieClipOperation.cpp
@@ -71,7 +71,7 @@ void MovieClipBaseOperation::deinitExecution()
}
}
-void MovieClipBaseOperation::determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2])
+void MovieClipBaseOperation::determineResolution(unsigned int resolution[2], unsigned int /*preferredResolution*/[2])
{
resolution[0] = 0;
resolution[1] = 0;
@@ -124,9 +124,7 @@ MovieClipAlphaOperation::MovieClipAlphaOperation() : MovieClipBaseOperation()
void MovieClipAlphaOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler)
{
- MovieClipBaseOperation::executePixelSampled(output, x, y, sampler);
- output[0] = output[3];
- output[1] = 0.0f;
- output[2] = 0.0f;
- output[3] = 0.0f;
+ float result[4];
+ MovieClipBaseOperation::executePixelSampled(result, x, y, sampler);
+ output[0] = result[3];
}
diff --git a/source/blender/compositor/operations/COM_MovieDistortionOperation.cpp b/source/blender/compositor/operations/COM_MovieDistortionOperation.cpp
index 50fabb09dbb..4f34d7fb150 100644
--- a/source/blender/compositor/operations/COM_MovieDistortionOperation.cpp
+++ b/source/blender/compositor/operations/COM_MovieDistortionOperation.cpp
@@ -121,7 +121,7 @@ void MovieDistortionOperation::deinitExecution()
}
-void MovieDistortionOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler)
+void MovieDistortionOperation::executePixelSampled(float output[4], float x, float y, PixelSampler /*sampler*/)
{
if (this->m_cache != NULL) {
diff --git a/source/blender/compositor/operations/COM_MovieDistortionOperation.h b/source/blender/compositor/operations/COM_MovieDistortionOperation.h
index 577712eda56..85f075ab65a 100644
--- a/source/blender/compositor/operations/COM_MovieDistortionOperation.h
+++ b/source/blender/compositor/operations/COM_MovieDistortionOperation.h
@@ -36,9 +36,9 @@ extern "C" {
class DistortionCache {
private:
- float m_k1;
- float m_k2;
- float m_k3;
+ short m_distortion_model;
+ float m_k1, m_k2, m_k3;
+ float m_division_k1, m_division_k2;
float m_principal_x;
float m_principal_y;
float m_pixel_aspect;
@@ -59,9 +59,12 @@ public:
bool inverted,
const int margin[2])
{
+ this->m_distortion_model = movieclip->tracking.camera.distortion_model;
this->m_k1 = movieclip->tracking.camera.k1;
this->m_k2 = movieclip->tracking.camera.k2;
this->m_k3 = movieclip->tracking.camera.k3;
+ this->m_division_k1 = movieclip->tracking.camera.division_k1;
+ this->m_division_k2 = movieclip->tracking.camera.division_k2;
this->m_principal_x = movieclip->tracking.camera.principal[0];
this->m_principal_y = movieclip->tracking.camera.principal[1];
this->m_pixel_aspect = movieclip->tracking.camera.pixel_aspect;
@@ -101,9 +104,12 @@ public:
int calibration_width, int claibration_height,
bool inverted)
{
- return this->m_k1 == movieclip->tracking.camera.k1 &&
+ return this->m_distortion_model == movieclip->tracking.camera.distortion_model &&
+ this->m_k1 == movieclip->tracking.camera.k1 &&
this->m_k2 == movieclip->tracking.camera.k2 &&
this->m_k3 == movieclip->tracking.camera.k3 &&
+ this->m_division_k1 == movieclip->tracking.camera.division_k1 &&
+ this->m_division_k2 == movieclip->tracking.camera.division_k2 &&
this->m_principal_x == movieclip->tracking.camera.principal[0] &&
this->m_principal_y == movieclip->tracking.camera.principal[1] &&
this->m_pixel_aspect == movieclip->tracking.camera.pixel_aspect &&
diff --git a/source/blender/compositor/operations/COM_MultilayerImageOperation.cpp b/source/blender/compositor/operations/COM_MultilayerImageOperation.cpp
index 23fba5a7999..b57dd4e32c3 100644
--- a/source/blender/compositor/operations/COM_MultilayerImageOperation.cpp
+++ b/source/blender/compositor/operations/COM_MultilayerImageOperation.cpp
@@ -27,18 +27,27 @@ extern "C" {
# include "IMB_imbuf_types.h"
}
-MultilayerBaseOperation::MultilayerBaseOperation(int passindex) : BaseImageOperation()
+MultilayerBaseOperation::MultilayerBaseOperation(int passindex, int view) : BaseImageOperation()
{
this->m_passId = passindex;
+ this->m_view = view;
}
+
ImBuf *MultilayerBaseOperation::getImBuf()
{
- RenderPass *rpass = (RenderPass *)BLI_findlink(&this->m_renderlayer->passes, this->m_passId);
- if (rpass) {
- this->m_imageUser->pass = m_passId;
- BKE_image_multilayer_index(this->m_image->rr, this->m_imageUser);
- return BaseImageOperation::getImBuf();
+ /* temporarily changes the view to get the right ImBuf */
+ int view = this->m_imageUser->view;
+
+ this->m_imageUser->view = this->m_view;
+ this->m_imageUser->pass = this->m_passId;
+
+ if (BKE_image_multilayer_index(this->m_image->rr, this->m_imageUser)) {
+ ImBuf *ibuf = BaseImageOperation::getImBuf();
+ this->m_imageUser->view = view;
+ return ibuf;
}
+
+ this->m_imageUser->view = view;
return NULL;
}
@@ -74,7 +83,7 @@ void MultilayerColorOperation::executePixelSampled(float output[4], float x, flo
}
}
-void MultilayerValueOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler)
+void MultilayerValueOperation::executePixelSampled(float output[4], float x, float y, PixelSampler /*sampler*/)
{
if (this->m_imageFloatBuffer == NULL) {
output[0] = 0.0f;
@@ -91,7 +100,7 @@ void MultilayerValueOperation::executePixelSampled(float output[4], float x, flo
}
}
-void MultilayerVectorOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler)
+void MultilayerVectorOperation::executePixelSampled(float output[4], float x, float y, PixelSampler /*sampler*/)
{
if (this->m_imageFloatBuffer == NULL) {
output[0] = 0.0f;
diff --git a/source/blender/compositor/operations/COM_MultilayerImageOperation.h b/source/blender/compositor/operations/COM_MultilayerImageOperation.h
index 37bee1b6a8c..46a9319c373 100644
--- a/source/blender/compositor/operations/COM_MultilayerImageOperation.h
+++ b/source/blender/compositor/operations/COM_MultilayerImageOperation.h
@@ -30,6 +30,7 @@
class MultilayerBaseOperation : public BaseImageOperation {
private:
int m_passId;
+ int m_view;
RenderLayer *m_renderlayer;
protected:
ImBuf *getImBuf();
@@ -37,13 +38,13 @@ public:
/**
* Constructor
*/
- MultilayerBaseOperation(int passindex);
+ MultilayerBaseOperation(int passindex, int view);
void setRenderLayer(RenderLayer *renderlayer) { this->m_renderlayer = renderlayer; }
};
class MultilayerColorOperation : public MultilayerBaseOperation {
public:
- MultilayerColorOperation(int passindex) : MultilayerBaseOperation(passindex) {
+ MultilayerColorOperation(int passindex, int view) : MultilayerBaseOperation(passindex, view) {
this->addOutputSocket(COM_DT_COLOR);
}
void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
@@ -51,7 +52,7 @@ public:
class MultilayerValueOperation : public MultilayerBaseOperation {
public:
- MultilayerValueOperation(int passindex) : MultilayerBaseOperation(passindex) {
+ MultilayerValueOperation(int passindex, int view) : MultilayerBaseOperation(passindex, view) {
this->addOutputSocket(COM_DT_VALUE);
}
void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
@@ -59,7 +60,7 @@ public:
class MultilayerVectorOperation : public MultilayerBaseOperation {
public:
- MultilayerVectorOperation(int passindex) : MultilayerBaseOperation(passindex) {
+ MultilayerVectorOperation(int passindex, int view) : MultilayerBaseOperation(passindex, view) {
this->addOutputSocket(COM_DT_VECTOR);
}
void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
diff --git a/source/blender/compositor/operations/COM_NormalizeOperation.cpp b/source/blender/compositor/operations/COM_NormalizeOperation.cpp
index f81b50e6836..504470f1a7e 100644
--- a/source/blender/compositor/operations/COM_NormalizeOperation.cpp
+++ b/source/blender/compositor/operations/COM_NormalizeOperation.cpp
@@ -60,7 +60,7 @@ void NormalizeOperation::deinitExecution()
NodeOperation::deinitMutex();
}
-bool NormalizeOperation::determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output)
+bool NormalizeOperation::determineDependingAreaOfInterest(rcti * /*input*/, ReadBufferOperation *readOperation, rcti *output)
{
rcti imageInput;
if (this->m_cachedInstance) return false;
@@ -104,7 +104,7 @@ void *NormalizeOperation::initializeTileData(rcti *rect)
if ((value < minv) && (value >= -BLENDER_ZMAX)) {
minv = value;
}
- bc += 4;
+ bc ++;
}
minmult->x = minv;
@@ -118,7 +118,7 @@ void *NormalizeOperation::initializeTileData(rcti *rect)
return this->m_cachedInstance;
}
-void NormalizeOperation::deinitializeTileData(rcti *rect, void *data)
+void NormalizeOperation::deinitializeTileData(rcti * /*rect*/, void * /*data*/)
{
/* pass */
}
diff --git a/source/blender/compositor/operations/COM_OpenCLKernels.cl b/source/blender/compositor/operations/COM_OpenCLKernels.cl
index 00b3825d8b3..cbd05cbec17 100644
--- a/source/blender/compositor/operations/COM_OpenCLKernels.cl
+++ b/source/blender/compositor/operations/COM_OpenCLKernels.cl
@@ -80,10 +80,10 @@ __kernel void bokehBlurKernel(__read_only image2d_t boundingBox, __read_only ima
}
//KERNEL --- DEFOCUS /VARIABLESIZEBOKEHBLUR ---
-__kernel void defocusKernel(__read_only image2d_t inputImage, __read_only image2d_t bokehImage,
- __read_only image2d_t inputSize,
- __write_only image2d_t output, int2 offsetInput, int2 offsetOutput,
- int step, int maxBlurScalar, float threshold, float scalar, int2 dimension, int2 offset)
+__kernel void defocusKernel(__read_only image2d_t inputImage, __read_only image2d_t bokehImage,
+ __read_only image2d_t inputSize,
+ __write_only image2d_t output, int2 offsetInput, int2 offsetOutput,
+ int step, int maxBlurScalar, float threshold, float scalar, int2 dimension, int2 offset)
{
float4 color = {1.0f, 0.0f, 0.0f, 1.0f};
int2 coords = {get_global_id(0), get_global_id(1)};
@@ -212,8 +212,8 @@ __kernel void erodeKernel(__read_only image2d_t inputImage, __write_only image2
// KERNEL --- DIRECTIONAL BLUR ---
__kernel void directionalBlurKernel(__read_only image2d_t inputImage, __write_only image2d_t output,
- int2 offsetOutput, int iterations, float scale, float rotation, float2 translate,
- float2 center, int2 offset)
+ int2 offsetOutput, int iterations, float scale, float rotation, float2 translate,
+ float2 center, int2 offset)
{
int2 coords = {get_global_id(0), get_global_id(1)};
coords += offset;
@@ -250,3 +250,66 @@ __kernel void directionalBlurKernel(__read_only image2d_t inputImage, __write_o
write_imagef(output, coords, col);
}
+
+// KERNEL --- GAUSSIAN BLUR ---
+__kernel void gaussianXBlurOperationKernel(__read_only image2d_t inputImage,
+ int2 offsetInput,
+ __write_only image2d_t output,
+ int2 offsetOutput,
+ int filter_size,
+ int2 dimension,
+ __global float *gausstab,
+ int2 offset)
+{
+ float4 color = {0.0f, 0.0f, 0.0f, 0.0f};
+ int2 coords = {get_global_id(0), get_global_id(1)};
+ coords += offset;
+ const int2 realCoordinate = coords + offsetOutput;
+ int2 inputCoordinate = realCoordinate - offsetInput;
+ float weight = 0.0f;
+
+ int xmin = max(realCoordinate.x - filter_size, 0) - offsetInput.x;
+ int xmax = min(realCoordinate.x + filter_size + 1, dimension.x) - offsetInput.x;
+
+ for (int nx = xmin, i = max(filter_size - realCoordinate.x, 0); nx < xmax; ++nx, ++i) {
+ float w = gausstab[i];
+ inputCoordinate.x = nx;
+ color += read_imagef(inputImage, SAMPLER_NEAREST, inputCoordinate) * w;
+ weight += w;
+ }
+
+ color *= (1.0f / weight);
+
+ write_imagef(output, coords, color);
+}
+
+__kernel void gaussianYBlurOperationKernel(__read_only image2d_t inputImage,
+ int2 offsetInput,
+ __write_only image2d_t output,
+ int2 offsetOutput,
+ int filter_size,
+ int2 dimension,
+ __global float *gausstab,
+ int2 offset)
+{
+ float4 color = {0.0f, 0.0f, 0.0f, 0.0f};
+ int2 coords = {get_global_id(0), get_global_id(1)};
+ coords += offset;
+ const int2 realCoordinate = coords + offsetOutput;
+ int2 inputCoordinate = realCoordinate - offsetInput;
+ float weight = 0.0f;
+
+ int ymin = max(realCoordinate.y - filter_size, 0) - offsetInput.y;
+ int ymax = min(realCoordinate.y + filter_size + 1, dimension.y) - offsetInput.y;
+
+ for (int ny = ymin, i = max(filter_size - realCoordinate.y, 0); ny < ymax; ++ny, ++i) {
+ float w = gausstab[i];
+ inputCoordinate.y = ny;
+ color += read_imagef(inputImage, SAMPLER_NEAREST, inputCoordinate) * w;
+ weight += w;
+ }
+
+ color *= (1.0f / weight);
+
+ write_imagef(output, coords, color);
+}
diff --git a/source/blender/compositor/operations/COM_OutputFileMultiViewOperation.cpp b/source/blender/compositor/operations/COM_OutputFileMultiViewOperation.cpp
new file mode 100644
index 00000000000..7786359c06a
--- /dev/null
+++ b/source/blender/compositor/operations/COM_OutputFileMultiViewOperation.cpp
@@ -0,0 +1,322 @@
+/*
+ * Copyright 2015, Blender Foundation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributor:
+ * Jeroen Bakker
+ * Monique Dewanchand
+ * Lukas Tönne
+ * Dalai Felinto
+ */
+
+#include "COM_OutputFileOperation.h"
+#include "COM_OutputFileMultiViewOperation.h"
+
+#include <string.h>
+#include "BLI_listbase.h"
+#include "BLI_path_util.h"
+#include "BLI_string.h"
+#include "BKE_image.h"
+#include "BKE_global.h"
+#include "BKE_main.h"
+#include "BKE_scene.h"
+
+#include "DNA_color_types.h"
+#include "MEM_guardedalloc.h"
+
+extern "C" {
+#include "IMB_imbuf.h"
+#include "IMB_colormanagement.h"
+#include "IMB_imbuf_types.h"
+}
+
+/************************************ OpenEXR Singlelayer Multiview *****************************************/
+
+OutputOpenExrSingleLayerMultiViewOperation::OutputOpenExrSingleLayerMultiViewOperation(
+ const RenderData *rd, const bNodeTree *tree, DataType datatype, ImageFormatData *format, const char *path,
+ const ColorManagedViewSettings *viewSettings, const ColorManagedDisplaySettings *displaySettings,
+ const char *viewName)
+ : OutputSingleLayerOperation(rd, tree, datatype, format, path, viewSettings, displaySettings, viewName)
+{
+}
+
+void *OutputOpenExrSingleLayerMultiViewOperation::get_handle(const char *filename)
+{
+ size_t width = this->getWidth();
+ size_t height = this->getHeight();
+ SceneRenderView *srv;
+
+ if (width != 0 && height != 0) {
+ void *exrhandle;
+
+ exrhandle = IMB_exr_get_handle_name(filename);
+
+ if (!BKE_scene_multiview_is_render_view_first(this->m_rd, this->m_viewName))
+ return exrhandle;
+
+ IMB_exr_clear_channels(exrhandle);
+
+ for (srv = (SceneRenderView *)this->m_rd->views.first; srv; srv = srv->next) {
+ if (BKE_scene_multiview_is_render_view_active(this->m_rd, srv) == false)
+ continue;
+
+ IMB_exr_add_view(exrhandle, srv->name);
+ add_exr_channels(exrhandle, NULL, this->m_datatype, srv->name, width, false, NULL);
+ }
+
+ BLI_make_existing_file(filename);
+
+ /* prepare the file with all the channels */
+
+ if (IMB_exr_begin_write(exrhandle, filename, width, height, this->m_format->exr_codec, NULL) == 0) {
+ printf("Error Writing Singlelayer Multiview Openexr\n");
+ IMB_exr_close(exrhandle);
+ }
+ else {
+ IMB_exr_clear_channels(exrhandle);
+ return exrhandle;
+ }
+ }
+ return NULL;
+}
+
+void OutputOpenExrSingleLayerMultiViewOperation::deinitExecution()
+{
+ unsigned int width = this->getWidth();
+ unsigned int height = this->getHeight();
+
+ if (width != 0 && height != 0) {
+ void *exrhandle;
+ Main *bmain = G.main; /* TODO, have this passed along */
+ char filename[FILE_MAX];
+
+ BKE_image_path_from_imtype(
+ filename, this->m_path, bmain->name, this->m_rd->cfra, R_IMF_IMTYPE_OPENEXR,
+ (this->m_rd->scemode & R_EXTENSION) != 0, true, NULL);
+
+ exrhandle = this->get_handle(filename);
+ add_exr_channels(exrhandle, NULL, this->m_datatype, this->m_viewName, width,
+ this->m_format->depth == R_IMF_CHAN_DEPTH_16, this->m_outputBuffer);
+
+ /* memory can only be freed after we write all views to the file */
+ this->m_outputBuffer = NULL;
+ this->m_imageInput = NULL;
+
+ /* ready to close the file */
+ if (BKE_scene_multiview_is_render_view_last(this->m_rd, this->m_viewName)) {
+ IMB_exr_write_channels(exrhandle);
+
+ /* free buffer memory for all the views */
+ free_exr_channels(exrhandle, this->m_rd, NULL, this->m_datatype);
+
+ /* remove exr handle and data */
+ IMB_exr_close(exrhandle);
+ }
+ }
+}
+
+/************************************ OpenEXR Multilayer Multiview *****************************************/
+
+OutputOpenExrMultiLayerMultiViewOperation::OutputOpenExrMultiLayerMultiViewOperation(
+ const RenderData *rd, const bNodeTree *tree, const char *path,
+ char exr_codec, bool exr_half_float, const char *viewName)
+ : OutputOpenExrMultiLayerOperation(rd, tree, path, exr_codec, exr_half_float, viewName)
+{
+}
+
+void *OutputOpenExrMultiLayerMultiViewOperation::get_handle(const char *filename)
+{
+ unsigned int width = this->getWidth();
+ unsigned int height = this->getHeight();
+
+ if (width != 0 && height != 0) {
+
+ void *exrhandle;
+ SceneRenderView *srv;
+
+ /* get a new global handle */
+ exrhandle = IMB_exr_get_handle_name(filename);
+
+ if (!BKE_scene_multiview_is_render_view_first(this->m_rd, this->m_viewName))
+ return exrhandle;
+
+ IMB_exr_clear_channels(exrhandle);
+
+ /* check renderdata for amount of views */
+ for (srv = (SceneRenderView *) this->m_rd->views.first; srv; srv = srv->next) {
+
+ if (BKE_scene_multiview_is_render_view_active(this->m_rd, srv) == false)
+ continue;
+
+ IMB_exr_add_view(exrhandle, srv->name);
+
+ for (unsigned int i = 0; i < this->m_layers.size(); ++i)
+ add_exr_channels(exrhandle, this->m_layers[i].name, this->m_layers[i].datatype,
+ srv->name, width, this->m_exr_half_float, NULL);
+ }
+
+ BLI_make_existing_file(filename);
+
+ /* prepare the file with all the channels for the header */
+ if (IMB_exr_begin_write(exrhandle, filename, width, height, this->m_exr_codec, NULL) == 0) {
+ printf("Error Writing Multilayer Multiview Openexr\n");
+ IMB_exr_close(exrhandle);
+ }
+ else {
+ IMB_exr_clear_channels(exrhandle);
+ return exrhandle;
+ }
+ }
+ return NULL;
+}
+
+void OutputOpenExrMultiLayerMultiViewOperation::deinitExecution()
+{
+ unsigned int width = this->getWidth();
+ unsigned int height = this->getHeight();
+
+ if (width != 0 && height != 0) {
+ void *exrhandle;
+ Main *bmain = G.main; /* TODO, have this passed along */
+ char filename[FILE_MAX];
+
+ BKE_image_path_from_imtype(
+ filename, this->m_path, bmain->name, this->m_rd->cfra, R_IMF_IMTYPE_MULTILAYER,
+ (this->m_rd->scemode & R_EXTENSION) != 0, true, NULL);
+
+ exrhandle = this->get_handle(filename);
+
+ for (unsigned int i = 0; i < this->m_layers.size(); ++i)
+ add_exr_channels(exrhandle, this->m_layers[i].name, this->m_layers[i].datatype, this->m_viewName,
+ width, this->m_exr_half_float, this->m_layers[i].outputBuffer);
+
+ for (unsigned int i = 0; i < this->m_layers.size(); ++i) {
+ /* memory can only be freed after we write all views to the file */
+ this->m_layers[i].outputBuffer = NULL;
+ this->m_layers[i].imageInput = NULL;
+ }
+
+ /* ready to close the file */
+ if (BKE_scene_multiview_is_render_view_last(this->m_rd, this->m_viewName)) {
+ IMB_exr_write_channels(exrhandle);
+
+ /* free buffer memory for all the views */
+ for (unsigned int i = 0; i < this->m_layers.size(); ++i) {
+ free_exr_channels(exrhandle, this->m_rd, this->m_layers[i].name, this->m_layers[i].datatype);
+ }
+
+ IMB_exr_close(exrhandle);
+ }
+ }
+}
+
+
+/******************************** Stereo3D ******************************/
+
+OutputStereoOperation::OutputStereoOperation(
+ const RenderData *rd, const bNodeTree *tree, DataType datatype, ImageFormatData *format, const char *path,
+ const char *name, const ColorManagedViewSettings *viewSettings, const ColorManagedDisplaySettings *displaySettings,
+ const char *viewName)
+ : OutputSingleLayerOperation(rd, tree, datatype, format, path, viewSettings, displaySettings, viewName)
+{
+ BLI_strncpy(this->m_name, name, sizeof(this->m_name));
+ this->m_channels = get_datatype_size(datatype);
+}
+
+void *OutputStereoOperation::get_handle(const char *filename)
+{
+ size_t width = this->getWidth();
+ size_t height = this->getHeight();
+ const char *names[2] = {STEREO_LEFT_NAME, STEREO_RIGHT_NAME};
+ size_t i;
+
+ if (width != 0 && height != 0) {
+ void *exrhandle;
+
+ exrhandle = IMB_exr_get_handle_name(filename);
+
+ if (!BKE_scene_multiview_is_render_view_first(this->m_rd, this->m_viewName))
+ return exrhandle;
+
+ IMB_exr_clear_channels(exrhandle);
+
+ for (i = 0; i < 2; i++)
+ IMB_exr_add_view(exrhandle, names[i]);
+
+ return exrhandle;
+ }
+ return NULL;
+}
+
+void OutputStereoOperation::deinitExecution()
+{
+ unsigned int width = this->getWidth();
+ unsigned int height = this->getHeight();
+
+ if (width != 0 && height != 0) {
+ void *exrhandle;
+
+ exrhandle = this->get_handle(this->m_path);
+ float *buf = this->m_outputBuffer;
+
+ /* populate single EXR channel with view data */
+ IMB_exr_add_channel(exrhandle, NULL, this->m_name, this->m_viewName, 1, this->m_channels * width * height, buf,
+ this->m_format->depth == R_IMF_CHAN_DEPTH_16);
+
+ this->m_imageInput = NULL;
+ this->m_outputBuffer = NULL;
+
+ /* create stereo ibuf */
+ if (BKE_scene_multiview_is_render_view_last(this->m_rd, this->m_viewName)) {
+ ImBuf *ibuf[3] = {NULL};
+ const char *names[2] = {STEREO_LEFT_NAME, STEREO_RIGHT_NAME};
+ Main *bmain = G.main; /* TODO, have this passed along */
+ char filename[FILE_MAX];
+ int i;
+
+ /* get rectf from EXR */
+ for (i = 0; i < 2; i++) {
+ float *rectf = IMB_exr_channel_rect(exrhandle, NULL, this->m_name, names[i]);
+ ibuf[i] = IMB_allocImBuf(width, height, this->m_format->planes, 0);
+
+ ibuf[i]->channels = this->m_channels;
+ ibuf[i]->rect_float = rectf;
+ ibuf[i]->mall |= IB_rectfloat;
+ ibuf[i]->dither = this->m_rd->dither_intensity;
+
+ /* do colormanagement in the individual views, so it doesn't need to do in the stereo */
+ IMB_colormanagement_imbuf_for_write(ibuf[i], true, false, this->m_viewSettings,
+ this->m_displaySettings, this->m_format);
+ IMB_prepare_write_ImBuf(IMB_isfloat(ibuf[i]), ibuf[i]);
+ }
+
+ /* create stereo buffer */
+ ibuf[2] = IMB_stereo3d_ImBuf(this->m_format, ibuf[0], ibuf[1]);
+
+ BKE_image_path_from_imformat(
+ filename, this->m_path, bmain->name, this->m_rd->cfra, this->m_format,
+ (this->m_rd->scemode & R_EXTENSION) != 0, true, NULL);
+
+ BKE_imbuf_write(ibuf[2], filename, this->m_format);
+
+ /* imbuf knows which rects are not part of ibuf */
+ for (i = 0; i < 3; i++)
+ IMB_freeImBuf(ibuf[i]);
+
+ IMB_exr_close(exrhandle);
+ }
+ }
+}
diff --git a/source/blender/compositor/operations/COM_OutputFileMultiViewOperation.h b/source/blender/compositor/operations/COM_OutputFileMultiViewOperation.h
new file mode 100644
index 00000000000..25ed8816399
--- /dev/null
+++ b/source/blender/compositor/operations/COM_OutputFileMultiViewOperation.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2015, Blender Foundation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributor:
+ * Jeroen Bakker
+ * Monique Dewanchand
+ * Lukas Tönne
+ * Dalai Felinto
+ */
+
+#ifndef _COM_OutputFileMultiViewOperation_h
+#define _COM_OutputFileMultiViewOperation_h
+#include "COM_NodeOperation.h"
+
+#include "BLI_rect.h"
+#include "BLI_path_util.h"
+
+#include "DNA_color_types.h"
+
+#include "intern/openexr/openexr_multi.h"
+
+class OutputOpenExrSingleLayerMultiViewOperation : public OutputSingleLayerOperation {
+private:
+public:
+ OutputOpenExrSingleLayerMultiViewOperation(const RenderData *rd, const bNodeTree *tree, DataType datatype,
+ ImageFormatData *format, const char *path,
+ const ColorManagedViewSettings *viewSettings,
+ const ColorManagedDisplaySettings *displaySettings,
+ const char *viewName);
+
+ void *get_handle(const char *filename);
+ void deinitExecution();
+};
+
+/* Writes inputs into OpenEXR multilayer channels. */
+class OutputOpenExrMultiLayerMultiViewOperation : public OutputOpenExrMultiLayerOperation {
+private:
+public:
+ OutputOpenExrMultiLayerMultiViewOperation(const RenderData *rd, const bNodeTree *tree, const char *path,
+ char exr_codec, bool exr_half_float, const char *viewName);
+
+ void *get_handle(const char *filename);
+ void deinitExecution();
+};
+
+/**/
+class OutputStereoOperation : public OutputSingleLayerOperation {
+private:
+ char m_name[FILE_MAX];
+ size_t m_channels;
+public:
+ OutputStereoOperation(const RenderData *rd, const bNodeTree *tree, DataType datatype,
+ struct ImageFormatData *format, const char *path, const char *name,
+ const ColorManagedViewSettings *viewSettings,
+ const ColorManagedDisplaySettings *displaySettings, const char *viewName);
+ void *get_handle(const char *filename);
+ void deinitExecution();
+};
+
+#endif
diff --git a/source/blender/compositor/operations/COM_OutputFileOperation.cpp b/source/blender/compositor/operations/COM_OutputFileOperation.cpp
index 92e8f309ea1..fdf5a0b48cf 100644
--- a/source/blender/compositor/operations/COM_OutputFileOperation.cpp
+++ b/source/blender/compositor/operations/COM_OutputFileOperation.cpp
@@ -29,6 +29,7 @@
#include "BKE_image.h"
#include "BKE_global.h"
#include "BKE_main.h"
+#include "BKE_scene.h"
#include "DNA_color_types.h"
@@ -39,7 +40,61 @@ extern "C" {
# include "IMB_imbuf_types.h"
}
-static int get_datatype_size(DataType datatype)
+void add_exr_channels(void *exrhandle, const char *layerName, const DataType datatype,
+ const char *viewName, const size_t width, bool use_half_float, float *buf)
+{
+ /* create channels */
+ switch (datatype) {
+ case COM_DT_VALUE:
+ IMB_exr_add_channel(exrhandle, layerName, "V", viewName, 1, width, buf ? buf : NULL, use_half_float);
+ break;
+ case COM_DT_VECTOR:
+ IMB_exr_add_channel(exrhandle, layerName, "X", viewName, 3, 3 * width, buf ? buf : NULL, use_half_float);
+ IMB_exr_add_channel(exrhandle, layerName, "Y", viewName, 3, 3 * width, buf ? buf + 1 : NULL, use_half_float);
+ IMB_exr_add_channel(exrhandle, layerName, "Z", viewName, 3, 3 * width, buf ? buf + 2 : NULL, use_half_float);
+ break;
+ case COM_DT_COLOR:
+ IMB_exr_add_channel(exrhandle, layerName, "R", viewName, 4, 4 * width, buf ? buf : NULL, use_half_float);
+ IMB_exr_add_channel(exrhandle, layerName, "G", viewName, 4, 4 * width, buf ? buf + 1 : NULL, use_half_float);
+ IMB_exr_add_channel(exrhandle, layerName, "B", viewName, 4, 4 * width, buf ? buf + 2 : NULL, use_half_float);
+ IMB_exr_add_channel(exrhandle, layerName, "A", viewName, 4, 4 * width, buf ? buf + 3 : NULL, use_half_float);
+ break;
+ default:
+ break;
+ }
+}
+
+void free_exr_channels(void *exrhandle, const RenderData *rd, const char *layerName, const DataType datatype)
+{
+ SceneRenderView *srv;
+
+ /* check renderdata for amount of views */
+ for (srv = (SceneRenderView *) rd->views.first; srv; srv = srv->next) {
+ float *rect = NULL;
+
+ if (BKE_scene_multiview_is_render_view_active(rd, srv) == false)
+ continue;
+
+ /* the pointer is stored in the first channel of each datatype */
+ switch (datatype) {
+ case COM_DT_VALUE:
+ rect = IMB_exr_channel_rect(exrhandle, layerName, "V", srv->name);
+ break;
+ case COM_DT_VECTOR:
+ rect = IMB_exr_channel_rect(exrhandle, layerName, "X", srv->name);
+ break;
+ case COM_DT_COLOR:
+ rect = IMB_exr_channel_rect(exrhandle, layerName, "R", srv->name);
+ break;
+ default:
+ break;
+ }
+ if (rect)
+ MEM_freeN(rect);
+ }
+}
+
+int get_datatype_size(DataType datatype)
{
switch (datatype) {
case COM_DT_VALUE: return 1;
@@ -94,7 +149,7 @@ static void write_buffer_rect(rcti *rect, const bNodeTree *tree,
OutputSingleLayerOperation::OutputSingleLayerOperation(
const RenderData *rd, const bNodeTree *tree, DataType datatype, ImageFormatData *format, const char *path,
- const ColorManagedViewSettings *viewSettings, const ColorManagedDisplaySettings *displaySettings)
+ const ColorManagedViewSettings *viewSettings, const ColorManagedDisplaySettings *displaySettings, const char *viewName)
{
this->m_rd = rd;
this->m_tree = tree;
@@ -110,6 +165,7 @@ OutputSingleLayerOperation::OutputSingleLayerOperation(
this->m_viewSettings = viewSettings;
this->m_displaySettings = displaySettings;
+ this->m_viewName = viewName;
}
void OutputSingleLayerOperation::initExecution()
@@ -118,7 +174,7 @@ void OutputSingleLayerOperation::initExecution()
this->m_outputBuffer = init_buffer(this->getWidth(), this->getHeight(), this->m_datatype);
}
-void OutputSingleLayerOperation::executeRegion(rcti *rect, unsigned int tileNumber)
+void OutputSingleLayerOperation::executeRegion(rcti *rect, unsigned int /*tileNumber*/)
{
write_buffer_rect(rect, this->m_tree, this->m_imageInput, this->m_outputBuffer, this->getWidth(), this->m_datatype);
}
@@ -131,6 +187,7 @@ void OutputSingleLayerOperation::deinitExecution()
ImBuf *ibuf = IMB_allocImBuf(this->getWidth(), this->getHeight(), this->m_format->planes, 0);
Main *bmain = G.main; /* TODO, have this passed along */
char filename[FILE_MAX];
+ const char *suffix;
ibuf->channels = size;
ibuf->rect_float = this->m_outputBuffer;
@@ -140,9 +197,12 @@ void OutputSingleLayerOperation::deinitExecution()
IMB_colormanagement_imbuf_for_write(ibuf, true, false, m_viewSettings, m_displaySettings,
this->m_format);
- BKE_makepicstring(filename, this->m_path, bmain->name, this->m_rd->cfra,
- this->m_format, (this->m_rd->scemode & R_EXTENSION) != 0, true);
-
+ suffix = BKE_scene_multiview_view_suffix_get(this->m_rd, this->m_viewName);
+
+ BKE_image_path_from_imformat(
+ filename, this->m_path, bmain->name, this->m_rd->cfra, this->m_format,
+ (this->m_rd->scemode & R_EXTENSION) != 0, true, suffix);
+
if (0 == BKE_imbuf_write(ibuf, filename, this->m_format))
printf("Cannot save Node File Output to %s\n", filename);
else
@@ -154,6 +214,7 @@ void OutputSingleLayerOperation::deinitExecution()
this->m_imageInput = NULL;
}
+/******************************* MultiLayer *******************************/
OutputOpenExrLayer::OutputOpenExrLayer(const char *name_, DataType datatype_, bool use_layer_)
{
@@ -167,13 +228,16 @@ OutputOpenExrLayer::OutputOpenExrLayer(const char *name_, DataType datatype_, bo
}
OutputOpenExrMultiLayerOperation::OutputOpenExrMultiLayerOperation(
- const RenderData *rd, const bNodeTree *tree, const char *path, char exr_codec)
+ const RenderData *rd, const bNodeTree *tree, const char *path,
+ char exr_codec, bool exr_half_float, const char *viewName)
{
this->m_rd = rd;
this->m_tree = tree;
BLI_strncpy(this->m_path, path, sizeof(this->m_path));
this->m_exr_codec = exr_codec;
+ this->m_exr_half_float = exr_half_float;
+ this->m_viewName = viewName;
}
void OutputOpenExrMultiLayerOperation::add_layer(const char *name, DataType datatype, bool use_layer)
@@ -193,7 +257,7 @@ void OutputOpenExrMultiLayerOperation::initExecution()
}
}
-void OutputOpenExrMultiLayerOperation::executeRegion(rcti *rect, unsigned int tileNumber)
+void OutputOpenExrMultiLayerOperation::executeRegion(rcti *rect, unsigned int /*tileNumber*/)
{
for (unsigned int i = 0; i < this->m_layers.size(); ++i) {
OutputOpenExrLayer &layer = this->m_layers[i];
@@ -209,55 +273,26 @@ void OutputOpenExrMultiLayerOperation::deinitExecution()
if (width != 0 && height != 0) {
Main *bmain = G.main; /* TODO, have this passed along */
char filename[FILE_MAX];
+ const char *suffix;
void *exrhandle = IMB_exr_get_handle();
-
- BKE_makepicstring_from_type(filename, this->m_path, bmain->name, this->m_rd->cfra, R_IMF_IMTYPE_MULTILAYER,
- (this->m_rd->scemode & R_EXTENSION) != 0, true);
+
+ suffix = BKE_scene_multiview_view_suffix_get(this->m_rd, this->m_viewName);
+ BKE_image_path_from_imtype(
+ filename, this->m_path, bmain->name, this->m_rd->cfra, R_IMF_IMTYPE_MULTILAYER,
+ (this->m_rd->scemode & R_EXTENSION) != 0, true, suffix);
BLI_make_existing_file(filename);
-
+
for (unsigned int i = 0; i < this->m_layers.size(); ++i) {
OutputOpenExrLayer &layer = this->m_layers[i];
if (!layer.imageInput)
continue; /* skip unconnected sockets */
- char channelname[EXR_TOT_MAXNAME];
- BLI_strncpy(channelname, this->m_layers[i].name, sizeof(channelname) - 2);
- char *channelname_ext = channelname + strlen(channelname);
-
- float *buf = this->m_layers[i].outputBuffer;
-
- /* create channels */
- switch (this->m_layers[i].datatype) {
- case COM_DT_VALUE:
- strcpy(channelname_ext, ".V");
- IMB_exr_add_channel(exrhandle, 0, channelname, 1, width, buf);
- break;
- case COM_DT_VECTOR:
- strcpy(channelname_ext, ".X");
- IMB_exr_add_channel(exrhandle, 0, channelname, 3, 3 * width, buf);
- strcpy(channelname_ext, ".Y");
- IMB_exr_add_channel(exrhandle, 0, channelname, 3, 3 * width, buf + 1);
- strcpy(channelname_ext, ".Z");
- IMB_exr_add_channel(exrhandle, 0, channelname, 3, 3 * width, buf + 2);
- break;
- case COM_DT_COLOR:
- strcpy(channelname_ext, ".R");
- IMB_exr_add_channel(exrhandle, 0, channelname, 4, 4 * width, buf);
- strcpy(channelname_ext, ".G");
- IMB_exr_add_channel(exrhandle, 0, channelname, 4, 4 * width, buf + 1);
- strcpy(channelname_ext, ".B");
- IMB_exr_add_channel(exrhandle, 0, channelname, 4, 4 * width, buf + 2);
- strcpy(channelname_ext, ".A");
- IMB_exr_add_channel(exrhandle, 0, channelname, 4, 4 * width, buf + 3);
- break;
- default:
- break;
- }
-
+ add_exr_channels(exrhandle, this->m_layers[i].name, this->m_layers[i].datatype, "", width,
+ this->m_exr_half_float, this->m_layers[i].outputBuffer);
}
/* when the filename has no permissions, this can fail */
- if (IMB_exr_begin_write(exrhandle, filename, width, height, this->m_exr_codec)) {
+ if (IMB_exr_begin_write(exrhandle, filename, width, height, this->m_exr_codec, NULL)) {
IMB_exr_write_channels(exrhandle);
}
else {
@@ -277,3 +312,4 @@ void OutputOpenExrMultiLayerOperation::deinitExecution()
}
}
}
+
diff --git a/source/blender/compositor/operations/COM_OutputFileOperation.h b/source/blender/compositor/operations/COM_OutputFileOperation.h
index 03278c5b149..93468977a66 100644
--- a/source/blender/compositor/operations/COM_OutputFileOperation.h
+++ b/source/blender/compositor/operations/COM_OutputFileOperation.h
@@ -34,7 +34,7 @@
/* Writes the image to a single-layer file. */
class OutputSingleLayerOperation : public NodeOperation {
-private:
+protected:
const RenderData *m_rd;
const bNodeTree *m_tree;
@@ -47,12 +47,14 @@ private:
const ColorManagedViewSettings *m_viewSettings;
const ColorManagedDisplaySettings *m_displaySettings;
+
+ const char *m_viewName;
public:
OutputSingleLayerOperation(const RenderData *rd, const bNodeTree *tree, DataType datatype, ImageFormatData *format, const char *path,
- const ColorManagedViewSettings *viewSettings, const ColorManagedDisplaySettings *displaySettings);
+ const ColorManagedViewSettings *viewSettings, const ColorManagedDisplaySettings *displaySettings, const char *viewName);
void executeRegion(rcti *rect, unsigned int tileNumber);
- bool isOutputOperation(bool rendering) const { return true; }
+ bool isOutputOperation(bool /*rendering*/) const { return true; }
void initExecution();
void deinitExecution();
const CompositorPriority getRenderPriority() const { return COM_PRIORITY_LOW; }
@@ -75,7 +77,7 @@ struct OutputOpenExrLayer {
/* Writes inputs into OpenEXR multilayer channels. */
class OutputOpenExrMultiLayerOperation : public NodeOperation {
-private:
+protected:
typedef std::vector<OutputOpenExrLayer> LayerList;
const RenderData *m_rd;
@@ -83,15 +85,18 @@ private:
char m_path[FILE_MAX];
char m_exr_codec;
+ bool m_exr_half_float;
LayerList m_layers;
+ const char *m_viewName;
public:
- OutputOpenExrMultiLayerOperation(const RenderData *rd, const bNodeTree *tree, const char *path, char exr_codec);
+ OutputOpenExrMultiLayerOperation(const RenderData *rd, const bNodeTree *tree, const char *path,
+ char exr_codec, bool exr_half_float, const char *viewName);
void add_layer(const char *name, DataType datatype, bool use_layer);
void executeRegion(rcti *rect, unsigned int tileNumber);
- bool isOutputOperation(bool rendering) const { return true; }
+ bool isOutputOperation(bool /*rendering*/) const { return true; }
void initExecution();
void deinitExecution();
const CompositorPriority getRenderPriority() const { return COM_PRIORITY_LOW; }
@@ -99,4 +104,9 @@ public:
bool isFileOutputOperation() const { return true; }
};
+void add_exr_channels(void *exrhandle, const char *layerName, const DataType datatype, const char *viewName,
+ const size_t width, bool use_half_float, float *buf);
+void free_exr_channels(void *exrhandle, const RenderData *rd, const char *layerName, const DataType datatype);
+int get_datatype_size(DataType datatype);
+
#endif
diff --git a/source/blender/compositor/operations/COM_PlaneCornerPinOperation.cpp b/source/blender/compositor/operations/COM_PlaneCornerPinOperation.cpp
index fe272000b6e..fb8730c9fa0 100644
--- a/source/blender/compositor/operations/COM_PlaneCornerPinOperation.cpp
+++ b/source/blender/compositor/operations/COM_PlaneCornerPinOperation.cpp
@@ -135,7 +135,7 @@ void *PlaneCornerPinMaskOperation::initializeTileData(rcti *rect)
getInputSocketReader(3) };
float corners[4][2];
readCornersFromSockets(rect, readers, corners);
- calculateCorners(corners, true);
+ calculateCorners(corners, true, 0);
m_corners_ready = true;
}
@@ -194,8 +194,7 @@ void *PlaneCornerPinWarpImageOperation::initializeTileData(rcti *rect)
getInputSocketReader(4) };
float corners[4][2];
readCornersFromSockets(rect, readers, corners);
- calculateCorners(corners, true);
- calculatePerspectiveMatrix();
+ calculateCorners(corners, true, 0);
m_corners_ready = true;
}
diff --git a/source/blender/compositor/operations/COM_PlaneDistortCommonOperation.cpp b/source/blender/compositor/operations/COM_PlaneDistortCommonOperation.cpp
index c507b4cfa98..1145abd076a 100644
--- a/source/blender/compositor/operations/COM_PlaneDistortCommonOperation.cpp
+++ b/source/blender/compositor/operations/COM_PlaneDistortCommonOperation.cpp
@@ -56,36 +56,38 @@ PlaneDistortWarpImageOperation::PlaneDistortWarpImageOperation() :
this->addInputSocket(COM_DT_COLOR, COM_SC_NO_RESIZE);
this->addOutputSocket(COM_DT_COLOR);
this->m_pixelReader = NULL;
+ this->m_motion_blur_samples = 1;
+ this->m_motion_blur_shutter = 0.5f;
this->setComplex(true);
}
-void PlaneDistortWarpImageOperation::calculateCorners(const float corners[4][2], bool normalized)
+void PlaneDistortWarpImageOperation::calculateCorners(const float corners[4][2],
+ bool normalized,
+ int sample)
{
+ BLI_assert(sample < this->m_motion_blur_samples);
+ const int width = this->m_pixelReader->getWidth();
+ const int height = this->m_pixelReader->getHeight();
+ float frame_corners[4][2] = {{0.0f, 0.0f},
+ {(float) width, 0.0f},
+ {(float) width, (float) height},
+ {0.0f, (float) height}};
+ MotionSample *sample_data = &this->m_samples[sample];
if (normalized) {
for (int i = 0; i < 4; i++) {
- this->m_frameSpaceCorners[i][0] = corners[i][0] * this->getWidth();
- this->m_frameSpaceCorners[i][1] = corners[i][1] * this->getHeight();
+ sample_data->frameSpaceCorners[i][0] = corners[i][0] * this->getWidth();
+ sample_data->frameSpaceCorners[i][1] = corners[i][1] * this->getHeight();
}
}
else {
for (int i = 0; i < 4; i++) {
- this->m_frameSpaceCorners[i][0] = corners[i][0];
- this->m_frameSpaceCorners[i][1] = corners[i][1];
+ sample_data->frameSpaceCorners[i][0] = corners[i][0];
+ sample_data->frameSpaceCorners[i][1] = corners[i][1];
}
}
-}
-
-void PlaneDistortWarpImageOperation::calculatePerspectiveMatrix()
-{
- const int width = this->m_pixelReader->getWidth();
- const int height = this->m_pixelReader->getHeight();
- float frame_corners[4][2] = {{0.0f, 0.0f},
- {(float) width, 0.0f},
- {(float) width, (float) height},
- {0.0f, (float) height}};
- BKE_tracking_homography_between_two_quads(this->m_frameSpaceCorners,
+ BKE_tracking_homography_between_two_quads(sample_data->frameSpaceCorners,
frame_corners,
- this->m_perspectiveMatrix);
+ sample_data->perspectiveMatrix);
}
void PlaneDistortWarpImageOperation::initExecution()
@@ -98,37 +100,47 @@ void PlaneDistortWarpImageOperation::deinitExecution()
this->m_pixelReader = NULL;
}
-void PlaneDistortWarpImageOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler)
+void PlaneDistortWarpImageOperation::executePixelSampled(float output[4], float x, float y, PixelSampler /*sampler*/)
{
- float xy[2] = {x, y};
float uv[2];
float deriv[2][2];
-
- pixelTransform(xy, uv, deriv);
-
- m_pixelReader->readFiltered(output, uv[0], uv[1], deriv[0], deriv[1], COM_PS_BILINEAR);
-}
-
-void PlaneDistortWarpImageOperation::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);
+ if (this->m_motion_blur_samples == 1) {
+ warpCoord(x, y, this->m_samples[0].perspectiveMatrix, uv, deriv);
+ m_pixelReader->readFiltered(output,
+ uv[0], uv[1],
+ deriv[0], deriv[1]);
+ }
+ else {
+ zero_v4(output);
+ for (int sample = 0; sample < this->m_motion_blur_samples; ++sample) {
+ float color[4];
+ warpCoord(x, y, this->m_samples[sample].perspectiveMatrix, uv, deriv);
+ m_pixelReader->readFiltered(color,
+ uv[0], uv[1],
+ deriv[0], deriv[1]);
+ add_v4_v4(output, color);
+ }
+ mul_v4_fl(output, 1.0f / (float)this->m_motion_blur_samples);
+ }
}
bool PlaneDistortWarpImageOperation::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], 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);
- for (int i = 0; i < 4; i++) {
- minmax_v2v2_v2(min, max, UVs[i]);
+
+ for (int sample = 0; sample < this->m_motion_blur_samples; ++sample) {
+ float UVs[4][2];
+ float deriv[2][2];
+ MotionSample *sample_data = &this->m_samples[sample];
+ /* TODO(sergey): figure out proper way to do this. */
+ warpCoord(input->xmin - 2, input->ymin - 2, sample_data->perspectiveMatrix, UVs[0], deriv);
+ warpCoord(input->xmax + 2, input->ymin - 2, sample_data->perspectiveMatrix, UVs[1], deriv);
+ warpCoord(input->xmax + 2, input->ymax + 2, sample_data->perspectiveMatrix, UVs[2], deriv);
+ warpCoord(input->xmin - 2, input->ymax + 2, sample_data->perspectiveMatrix, UVs[3], deriv);
+ for (int i = 0; i < 4; i++) {
+ minmax_v2v2_v2(min, max, UVs[i]);
+ }
}
rcti newInput;
@@ -151,20 +163,26 @@ PlaneDistortMaskOperation::PlaneDistortMaskOperation() :
/* Currently hardcoded to 8 samples. */
m_osa = 8;
+ this->m_motion_blur_samples = 1;
+ this->m_motion_blur_shutter = 0.5f;
}
-void PlaneDistortMaskOperation::calculateCorners(const float corners[4][2], bool normalized)
+void PlaneDistortMaskOperation::calculateCorners(const float corners[4][2],
+ bool normalized,
+ int sample)
{
+ BLI_assert(sample < this->m_motion_blur_samples);
+ MotionSample *sample_data = &this->m_samples[sample];
if (normalized) {
for (int i = 0; i < 4; i++) {
- this->m_frameSpaceCorners[i][0] = corners[i][0] * this->getWidth();
- this->m_frameSpaceCorners[i][1] = corners[i][1] * this->getHeight();
+ sample_data->frameSpaceCorners[i][0] = corners[i][0] * this->getWidth();
+ sample_data->frameSpaceCorners[i][1] = corners[i][1] * this->getHeight();
}
}
else {
for (int i = 0; i < 4; i++) {
- this->m_frameSpaceCorners[i][0] = corners[i][0];
- this->m_frameSpaceCorners[i][1] = corners[i][1];
+ sample_data->frameSpaceCorners[i][0] = corners[i][0];
+ sample_data->frameSpaceCorners[i][1] = corners[i][1];
}
}
}
@@ -174,21 +192,47 @@ void PlaneDistortMaskOperation::initExecution()
BLI_jitter_init(m_jitter, m_osa);
}
-void PlaneDistortMaskOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler)
+void PlaneDistortMaskOperation::executePixelSampled(float output[4], float x, float y, PixelSampler /*sampler*/)
{
float point[2];
-
int inside_counter = 0;
- for (int sample = 0; sample < this->m_osa; sample++) {
- point[0] = x + this->m_jitter[sample][0];
- point[1] = y + this->m_jitter[sample][1];
-
- if (isect_point_tri_v2(point, this->m_frameSpaceCorners[0], this->m_frameSpaceCorners[1], this->m_frameSpaceCorners[2]) ||
- isect_point_tri_v2(point, this->m_frameSpaceCorners[0], this->m_frameSpaceCorners[2], this->m_frameSpaceCorners[3]))
+ if (this->m_motion_blur_samples == 1) {
+ MotionSample *sample_data = &this->m_samples[0];
+ for (int sample = 0; sample < this->m_osa; sample++) {
+ point[0] = x + this->m_jitter[sample][0];
+ point[1] = y + this->m_jitter[sample][1];
+ if (isect_point_tri_v2(point, sample_data->frameSpaceCorners[0],
+ sample_data->frameSpaceCorners[1],
+ sample_data->frameSpaceCorners[2]) ||
+ isect_point_tri_v2(point, sample_data->frameSpaceCorners[0],
+ sample_data->frameSpaceCorners[2],
+ sample_data->frameSpaceCorners[3]))
+ {
+ inside_counter++;
+ }
+ }
+ output[0] = (float)inside_counter / this->m_osa;
+ }
+ else {
+ for (int motion_sample = 0;
+ motion_sample < this->m_motion_blur_samples;
+ ++motion_sample)
{
- inside_counter++;
+ MotionSample *sample_data = &this->m_samples[motion_sample];
+ for (int osa_sample = 0; osa_sample < this->m_osa; ++osa_sample) {
+ point[0] = x + this->m_jitter[osa_sample][0];
+ point[1] = y + this->m_jitter[osa_sample][1];
+ if (isect_point_tri_v2(point, sample_data->frameSpaceCorners[0],
+ sample_data->frameSpaceCorners[1],
+ sample_data->frameSpaceCorners[2]) ||
+ isect_point_tri_v2(point, sample_data->frameSpaceCorners[0],
+ sample_data->frameSpaceCorners[2],
+ sample_data->frameSpaceCorners[3]))
+ {
+ inside_counter++;
+ }
+ }
}
+ output[0] = (float)inside_counter / (this->m_osa * this->m_motion_blur_samples);
}
-
- output[0] = (float) inside_counter / this->m_osa;
}
diff --git a/source/blender/compositor/operations/COM_PlaneDistortCommonOperation.h b/source/blender/compositor/operations/COM_PlaneDistortCommonOperation.h
index ee2874c6b46..fc5dd1ff7d8 100644
--- a/source/blender/compositor/operations/COM_PlaneDistortCommonOperation.h
+++ b/source/blender/compositor/operations/COM_PlaneDistortCommonOperation.h
@@ -33,43 +33,72 @@
#include "BLI_listbase.h"
#include "BLI_string.h"
+#define PLANE_DISTORT_MAX_SAMPLES 64
class PlaneDistortWarpImageOperation : public NodeOperation {
protected:
+ struct MotionSample {
+ float frameSpaceCorners[4][2]; /* Corners coordinates in pixel space. */
+ float perspectiveMatrix[3][3];
+ };
SocketReader *m_pixelReader;
- float m_frameSpaceCorners[4][2]; /* Corners coordinates in pixel space. */
- float m_perspectiveMatrix[3][3];
+ MotionSample m_samples[PLANE_DISTORT_MAX_SAMPLES];
+ int m_motion_blur_samples;
+ float m_motion_blur_shutter;
public:
PlaneDistortWarpImageOperation();
- void calculateCorners(const float corners[4][2], bool normalized);
- void calculatePerspectiveMatrix();
+ void calculateCorners(const float corners[4][2],
+ bool normalized,
+ int sample);
void initExecution();
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);
+
+ void setMotionBlurSamples(int samples) {
+ BLI_assert(samples <= PLANE_DISTORT_MAX_SAMPLES);
+ this->m_motion_blur_samples = samples;
+ }
+ void setMotionBlurShutter(float shutter) {
+ this->m_motion_blur_shutter = shutter;
+ }
};
class PlaneDistortMaskOperation : public NodeOperation {
protected:
+ struct MotionSample {
+ float frameSpaceCorners[4][2]; /* Corners coordinates in pixel space. */
+ };
int m_osa;
+ MotionSample m_samples[PLANE_DISTORT_MAX_SAMPLES];
float m_jitter[32][2];
- float m_frameSpaceCorners[4][2]; /* Corners coordinates in pixel space. */
+ int m_motion_blur_samples;
+ float m_motion_blur_shutter;
public:
PlaneDistortMaskOperation();
-
- void calculateCorners(const float corners[4][2], bool normalized);
-
+
+ void calculateCorners(const float corners[4][2],
+ bool normalized,
+ int sample);
+
void initExecution();
-
+
void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
+
+ void setMotionBlurSamples(int samples) {
+ BLI_assert(samples <= PLANE_DISTORT_MAX_SAMPLES);
+ this->m_motion_blur_samples = samples;
+ }
+ void setMotionBlurShutter(float shutter) {
+ this->m_motion_blur_shutter = shutter;
+ }
};
#endif
diff --git a/source/blender/compositor/operations/COM_PlaneTrackOperation.cpp b/source/blender/compositor/operations/COM_PlaneTrackOperation.cpp
index fec39cbfde0..a56aa0cbaa6 100644
--- a/source/blender/compositor/operations/COM_PlaneTrackOperation.cpp
+++ b/source/blender/compositor/operations/COM_PlaneTrackOperation.cpp
@@ -46,47 +46,41 @@ PlaneTrackCommon::PlaneTrackCommon()
this->m_planeTrackName[0] = '\0';
}
-void PlaneTrackCommon::readCornersFromTrack(float corners[4][2])
+void PlaneTrackCommon::readCornersFromTrack(float corners[4][2], float frame)
{
MovieTracking *tracking;
MovieTrackingObject *object;
if (!this->m_movieClip)
return;
-
+
tracking = &this->m_movieClip->tracking;
-
+
object = BKE_tracking_object_get_named(tracking, this->m_trackingObjectName);
if (object) {
MovieTrackingPlaneTrack *plane_track;
-
plane_track = BKE_tracking_plane_track_get_named(tracking, object, this->m_planeTrackName);
-
if (plane_track) {
- MovieTrackingPlaneMarker *plane_marker;
- int clip_framenr = BKE_movieclip_remap_scene_to_clip_frame(this->m_movieClip, this->m_framenumber);
-
- plane_marker = BKE_tracking_plane_marker_get(plane_track, clip_framenr);
- copy_v2_v2(corners[0], plane_marker->corners[0]);
- copy_v2_v2(corners[1], plane_marker->corners[1]);
- copy_v2_v2(corners[2], plane_marker->corners[2]);
- copy_v2_v2(corners[3], plane_marker->corners[3]);
+ float clip_framenr =
+ BKE_movieclip_remap_scene_to_clip_frame(this->m_movieClip,
+ frame);
+ BKE_tracking_plane_marker_get_subframe_corners(plane_track,
+ clip_framenr,
+ corners);
}
}
}
-void PlaneTrackCommon::determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2])
+void PlaneTrackCommon::determineResolution(unsigned int resolution[2], unsigned int /*preferredResolution*/[2])
{
resolution[0] = 0;
resolution[1] = 0;
-
+
if (this->m_movieClip) {
int width, height;
MovieClipUser user = {0};
-
BKE_movieclip_user_set_frame(&user, this->m_framenumber);
BKE_movieclip_get_size(this->m_movieClip, &user, &width, &height);
-
resolution[0] = width;
resolution[1] = height;
}
@@ -98,10 +92,21 @@ void PlaneTrackCommon::determineResolution(unsigned int resolution[2], unsigned
void PlaneTrackMaskOperation::initExecution()
{
PlaneDistortMaskOperation::initExecution();
-
float corners[4][2];
- readCornersFromTrack(corners);
- calculateCorners(corners, true);
+ if (this->m_motion_blur_samples == 1) {
+ readCornersFromTrack(corners, this->m_framenumber);
+ calculateCorners(corners, true, 0);
+ }
+ else {
+ const float frame = (float)this->m_framenumber - this->m_motion_blur_shutter;
+ const float frame_step = (this->m_motion_blur_shutter * 2.0f) / this->m_motion_blur_samples;
+ float frame_iter = frame;
+ for (int sample = 0; sample < this->m_motion_blur_samples; ++sample) {
+ readCornersFromTrack(corners, frame_iter);
+ calculateCorners(corners, true, sample);
+ frame_iter += frame_step;
+ }
+ }
}
/* ******** PlaneTrackWarpImageOperation ******** */
@@ -109,9 +114,20 @@ void PlaneTrackMaskOperation::initExecution()
void PlaneTrackWarpImageOperation::initExecution()
{
PlaneDistortWarpImageOperation::initExecution();
-
+ /* TODO(sergey): De-duplicate with mask operation. */
float corners[4][2];
- readCornersFromTrack(corners);
- calculateCorners(corners, true);
- calculatePerspectiveMatrix();
+ if (this->m_motion_blur_samples == 1) {
+ readCornersFromTrack(corners, this->m_framenumber);
+ calculateCorners(corners, true, 0);
+ }
+ else {
+ const float frame = (float)this->m_framenumber - this->m_motion_blur_shutter;
+ const float frame_step = (this->m_motion_blur_shutter * 2.0f) / this->m_motion_blur_samples;
+ float frame_iter = frame;
+ for (int sample = 0; sample < this->m_motion_blur_samples; ++sample) {
+ readCornersFromTrack(corners, frame_iter);
+ calculateCorners(corners, true, sample);
+ frame_iter += frame_step;
+ }
+ }
}
diff --git a/source/blender/compositor/operations/COM_PlaneTrackOperation.h b/source/blender/compositor/operations/COM_PlaneTrackOperation.h
index 3c5dd783542..41761493e12 100644
--- a/source/blender/compositor/operations/COM_PlaneTrackOperation.h
+++ b/source/blender/compositor/operations/COM_PlaneTrackOperation.h
@@ -43,7 +43,7 @@ protected:
/* note: this class is not an operation itself (to prevent virtual inheritance issues)
* implementation classes must make wrappers to use these methods, see below.
*/
- void readCornersFromTrack(float corners[4][2]);
+ void readCornersFromTrack(float corners[4][2], float frame);
void determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]);
public:
@@ -68,7 +68,7 @@ public:
void determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2])
{
PlaneTrackCommon::determineResolution(resolution, preferredResolution);
-
+
unsigned int temp[2];
NodeOperation::determineResolution(temp, resolution);
}
@@ -81,13 +81,12 @@ public:
PlaneDistortWarpImageOperation(),
PlaneTrackCommon()
{}
-
+
void initExecution();
-
+
void determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2])
{
PlaneTrackCommon::determineResolution(resolution, preferredResolution);
-
unsigned int temp[2];
NodeOperation::determineResolution(temp, resolution);
}
diff --git a/source/blender/compositor/operations/COM_PreviewOperation.cpp b/source/blender/compositor/operations/COM_PreviewOperation.cpp
index 69290cd7c3c..aa667884de6 100644
--- a/source/blender/compositor/operations/COM_PreviewOperation.cpp
+++ b/source/blender/compositor/operations/COM_PreviewOperation.cpp
@@ -85,7 +85,7 @@ void PreviewOperation::deinitExecution()
this->m_input = NULL;
}
-void PreviewOperation::executeRegion(rcti *rect, unsigned int tileNumber)
+void PreviewOperation::executeRegion(rcti *rect, unsigned int /*tileNumber*/)
{
int offset;
float color[4];
diff --git a/source/blender/compositor/operations/COM_PreviewOperation.h b/source/blender/compositor/operations/COM_PreviewOperation.h
index 3e97acec7bb..5da7a25ac5d 100644
--- a/source/blender/compositor/operations/COM_PreviewOperation.h
+++ b/source/blender/compositor/operations/COM_PreviewOperation.h
@@ -45,7 +45,7 @@ public:
PreviewOperation(const ColorManagedViewSettings *viewSettings, const ColorManagedDisplaySettings *displaySettings);
void verifyPreview(bNodeInstanceHash *previews, bNodeInstanceKey key);
- bool isOutputOperation(bool rendering) const { return !G.background; }
+ bool isOutputOperation(bool /*rendering*/) const { return !G.background; }
void initExecution();
void deinitExecution();
const CompositorPriority getRenderPriority() const;
diff --git a/source/blender/compositor/operations/COM_ProjectorLensDistortionOperation.cpp b/source/blender/compositor/operations/COM_ProjectorLensDistortionOperation.cpp
index 7f6079c55aa..02d1809efbb 100644
--- a/source/blender/compositor/operations/COM_ProjectorLensDistortionOperation.cpp
+++ b/source/blender/compositor/operations/COM_ProjectorLensDistortionOperation.cpp
@@ -40,7 +40,7 @@ void ProjectorLensDistortionOperation::initExecution()
this->m_inputProgram = this->getInputSocketReader(0);
}
-void *ProjectorLensDistortionOperation::initializeTileData(rcti *rect)
+void *ProjectorLensDistortionOperation::initializeTileData(rcti * /*rect*/)
{
updateDispersion();
void *buffer = this->m_inputProgram->initializeTileData(NULL);
diff --git a/source/blender/compositor/operations/COM_QualityStepHelper.cpp b/source/blender/compositor/operations/COM_QualityStepHelper.cpp
index d99d6f28eff..4d9c15f9747 100644
--- a/source/blender/compositor/operations/COM_QualityStepHelper.cpp
+++ b/source/blender/compositor/operations/COM_QualityStepHelper.cpp
@@ -37,15 +37,15 @@ void QualityStepHelper::initExecution(QualityHelper helper)
case COM_QUALITY_HIGH:
default:
this->m_step = 1;
- this->m_offsetadd = 4;
+ this->m_offsetadd = 1;
break;
case COM_QUALITY_MEDIUM:
this->m_step = 2;
- this->m_offsetadd = 8;
+ this->m_offsetadd = 2;
break;
case COM_QUALITY_LOW:
this->m_step = 3;
- this->m_offsetadd = 12;
+ this->m_offsetadd = 3;
break;
}
break;
diff --git a/source/blender/compositor/operations/COM_ReadBufferOperation.cpp b/source/blender/compositor/operations/COM_ReadBufferOperation.cpp
index 47d5fc6bcca..6dbe132257a 100644
--- a/source/blender/compositor/operations/COM_ReadBufferOperation.cpp
+++ b/source/blender/compositor/operations/COM_ReadBufferOperation.cpp
@@ -24,15 +24,15 @@
#include "COM_WriteBufferOperation.h"
#include "COM_defines.h"
-ReadBufferOperation::ReadBufferOperation() : NodeOperation()
+ReadBufferOperation::ReadBufferOperation(DataType datatype) : NodeOperation()
{
- this->addOutputSocket(COM_DT_COLOR);
+ this->addOutputSocket(datatype);
this->m_single_value = false;
this->m_offset = 0;
this->m_buffer = NULL;
}
-void *ReadBufferOperation::initializeTileData(rcti *rect)
+void *ReadBufferOperation::initializeTileData(rcti * /*rect*/)
{
return m_buffer;
}
@@ -58,11 +58,19 @@ void ReadBufferOperation::executePixelSampled(float output[4], float x, float y,
/* write buffer has a single value stored at (0,0) */
m_buffer->read(output, 0, 0);
}
- else if (sampler == COM_PS_NEAREST) {
- m_buffer->read(output, x, y);
- }
else {
- m_buffer->readBilinear(output, x, y);
+ switch (sampler) {
+ case COM_PS_NEAREST:
+ m_buffer->read(output, x, y);
+ break;
+ case COM_PS_BILINEAR:
+ default:
+ m_buffer->readBilinear(output, x, y);
+ break;
+ case COM_PS_BICUBIC:
+ m_buffer->readBilinear(output, x, y);
+ break;
+ }
}
}
@@ -81,7 +89,7 @@ void ReadBufferOperation::executePixelExtend(float output[4], float x, float y,
}
}
-void ReadBufferOperation::executePixelFiltered(float output[4], float x, float y, float dx[2], float dy[2], PixelSampler sampler)
+void ReadBufferOperation::executePixelFiltered(float output[4], float x, float y, float dx[2], float dy[2])
{
if (m_single_value) {
/* write buffer has a single value stored at (0,0) */
@@ -90,7 +98,7 @@ void ReadBufferOperation::executePixelFiltered(float output[4], float x, float y
else {
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);
+ m_buffer->readEWA(output, uv, deriv);
}
}
diff --git a/source/blender/compositor/operations/COM_ReadBufferOperation.h b/source/blender/compositor/operations/COM_ReadBufferOperation.h
index 569920d51ef..cd706ed0b75 100644
--- a/source/blender/compositor/operations/COM_ReadBufferOperation.h
+++ b/source/blender/compositor/operations/COM_ReadBufferOperation.h
@@ -25,6 +25,7 @@
#include "COM_NodeOperation.h"
#include "COM_MemoryProxy.h"
+#include "COM_MemoryBuffer.h"
class ReadBufferOperation : public NodeOperation {
private:
@@ -33,7 +34,7 @@ private:
unsigned int m_offset;
MemoryBuffer *m_buffer;
public:
- ReadBufferOperation();
+ ReadBufferOperation(DataType datetype);
void setMemoryProxy(MemoryProxy *memoryProxy) { this->m_memoryProxy = memoryProxy; }
MemoryProxy *getMemoryProxy() { return this->m_memoryProxy; }
void determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]);
@@ -42,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[2], float dy[2], PixelSampler sampler);
+ void executePixelFiltered(float output[4], float x, float y, float dx[2], float dy[2]);
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 06f4f6d77cf..1a7e775113b 100644
--- a/source/blender/compositor/operations/COM_RenderLayersProg.cpp
+++ b/source/blender/compositor/operations/COM_RenderLayersProg.cpp
@@ -23,6 +23,7 @@
#include "COM_RenderLayersProg.h"
#include "BLI_listbase.h"
+#include "BKE_scene.h"
#include "DNA_scene_types.h"
extern "C" {
@@ -57,11 +58,10 @@ void RenderLayersBaseProg::initExecution()
if (srl) {
RenderLayer *rl = RE_GetRenderLayer(rr, srl->name);
- if (rl && rl->rectf) {
- this->m_inputBuffer = RE_RenderLayerGetPass(rl, this->m_renderpass);
-
+ if (rl) {
+ this->m_inputBuffer = RE_RenderLayerGetPass(rl, this->m_renderpass, this->m_viewName);
if (this->m_inputBuffer == NULL && this->m_renderpass == SCE_PASS_COMBINED) {
- this->m_inputBuffer = rl->rectf;
+ this->m_inputBuffer = RE_RenderLayerGetPass(rl, SCE_PASS_COMBINED, this->m_viewName);
}
}
}
@@ -111,15 +111,6 @@ void RenderLayersBaseProg::doInterpolation(float output[4], float x, float y, Pi
BLI_bicubic_interpolation_fl(this->m_inputBuffer, output, width, height, this->m_elementsize, x, y);
break;
}
-
- if (this->m_elementsize == 1) {
- output[1] = 0.0f;
- output[2] = 0.0f;
- output[3] = 0.0f;
- }
- else if (this->m_elementsize == 3) {
- output[3] = 1.0f;
- }
}
void RenderLayersBaseProg::executePixelSampled(float output[4], float x, float y, PixelSampler sampler)
@@ -144,8 +135,39 @@ void RenderLayersBaseProg::executePixelSampled(float output[4], float x, float y
int iy = y - dy;
#endif
+#ifndef NDEBUG
+ {
+ const DataType data_type = this->getOutputSocket()->getDataType();
+ int actual_element_size = this->m_elementsize;
+ int expected_element_size;
+ if (data_type == COM_DT_VALUE) {
+ expected_element_size = 1;
+ }
+ else if (data_type == COM_DT_VECTOR) {
+ expected_element_size = 3;
+ }
+ else if (data_type == COM_DT_COLOR) {
+ expected_element_size = 4;
+ }
+ else {
+ BLI_assert(!"Something horribly wrong just happened");
+ }
+ BLI_assert(expected_element_size == actual_element_size);
+ }
+#endif
+
if (this->m_inputBuffer == NULL) {
- zero_v4(output);
+ int elemsize = this->m_elementsize;
+ if (elemsize == 1) {
+ output[0] = 0.0f;
+ }
+ else if (elemsize == 3) {
+ zero_v3(output);
+ }
+ else {
+ BLI_assert(elemsize == 4);
+ zero_v4(output);
+ }
}
else {
doInterpolation(output, x, y, sampler);
@@ -157,7 +179,7 @@ void RenderLayersBaseProg::deinitExecution()
this->m_inputBuffer = NULL;
}
-void RenderLayersBaseProg::determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2])
+void RenderLayersBaseProg::determineResolution(unsigned int resolution[2], unsigned int /*preferredResolution*/[2])
{
Scene *sce = this->getScene();
Render *re = (sce) ? RE_GetRender(sce->id.name) : NULL;
@@ -173,7 +195,7 @@ void RenderLayersBaseProg::determineResolution(unsigned int resolution[2], unsig
SceneRenderLayer *srl = (SceneRenderLayer *)BLI_findlink(&sce->r.layers, getLayerId());
if (srl) {
RenderLayer *rl = RE_GetRenderLayer(rr, srl->name);
- if (rl && rl->rectf) {
+ if (rl) {
resolution[0] = rl->rectx;
resolution[1] = rl->recty;
}
@@ -192,6 +214,19 @@ RenderLayersAOOperation::RenderLayersAOOperation() : RenderLayersBaseProg(SCE_PA
this->addOutputSocket(COM_DT_COLOR);
}
+
+void RenderLayersAOOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler)
+{
+ float *inputBuffer = this->getInputBuffer();
+ if (inputBuffer == NULL) {
+ zero_v3(output);
+ }
+ else {
+ doInterpolation(output, x, y, sampler);
+ }
+ output[3] = 1.0f;
+}
+
/* ******** Render Layers Alpha Operation ******** */
RenderLayersAlphaProg::RenderLayersAlphaProg() : RenderLayersBaseProg(SCE_PASS_COMBINED, 4)
@@ -204,15 +239,12 @@ void RenderLayersAlphaProg::executePixelSampled(float output[4], float x, float
float *inputBuffer = this->getInputBuffer();
if (inputBuffer == NULL) {
- zero_v4(output);
+ output[0] = 0.0f;
}
else {
float temp[4];
doInterpolation(temp, x, y, sampler);
output[0] = temp[3];
- output[1] = 0.0f;
- output[2] = 0.0f;
- output[3] = 0.0f;
}
}
@@ -227,7 +259,7 @@ RenderLayersColorOperation::RenderLayersColorOperation() : RenderLayersBaseProg(
RenderLayersCyclesOperation::RenderLayersCyclesOperation(int pass) : RenderLayersBaseProg(pass, 3)
{
- this->addOutputSocket(COM_DT_COLOR);
+ this->addOutputSocket(COM_DT_VECTOR);
}
/* ******** Render Layers Depth Operation ******** */
@@ -237,7 +269,7 @@ RenderLayersDepthProg::RenderLayersDepthProg() : RenderLayersBaseProg(SCE_PASS_Z
this->addOutputSocket(COM_DT_VALUE);
}
-void RenderLayersDepthProg::executePixelSampled(float output[4], float x, float y, PixelSampler sampler)
+void RenderLayersDepthProg::executePixelSampled(float output[4], float x, float y, PixelSampler /*sampler*/)
{
int ix = x;
int iy = y;
@@ -245,16 +277,10 @@ void RenderLayersDepthProg::executePixelSampled(float output[4], float x, float
if (inputBuffer == NULL || ix < 0 || iy < 0 || ix >= (int)this->getWidth() || iy >= (int)this->getHeight() ) {
output[0] = 0.0f;
- output[1] = 0.0f;
- output[2] = 0.0f;
- output[3] = 0.0f;
}
else {
unsigned int offset = (iy * this->getWidth() + ix);
output[0] = inputBuffer[offset];
- output[1] = 0.0f;
- output[2] = 0.0f;
- output[3] = 0.0f;
}
}
@@ -262,21 +288,21 @@ void RenderLayersDepthProg::executePixelSampled(float output[4], float x, float
RenderLayersDiffuseOperation::RenderLayersDiffuseOperation() : RenderLayersBaseProg(SCE_PASS_DIFFUSE, 3)
{
- this->addOutputSocket(COM_DT_COLOR);
+ this->addOutputSocket(COM_DT_VECTOR);
}
/* ******** Render Layers Emit Operation ******** */
RenderLayersEmitOperation::RenderLayersEmitOperation() : RenderLayersBaseProg(SCE_PASS_EMIT, 3)
{
- this->addOutputSocket(COM_DT_COLOR);
+ this->addOutputSocket(COM_DT_VECTOR);
}
/* ******** Render Layers Environment Operation ******** */
RenderLayersEnvironmentOperation::RenderLayersEnvironmentOperation() : RenderLayersBaseProg(SCE_PASS_ENVIRONMENT, 3)
{
- this->addOutputSocket(COM_DT_COLOR);
+ this->addOutputSocket(COM_DT_VECTOR);
}
/* ******** Render Layers Image Operation ******** */
@@ -290,7 +316,7 @@ RenderLayersColorProg::RenderLayersColorProg() : RenderLayersBaseProg(SCE_PASS_C
RenderLayersIndirectOperation::RenderLayersIndirectOperation() : RenderLayersBaseProg(SCE_PASS_INDIRECT, 3)
{
- this->addOutputSocket(COM_DT_COLOR);
+ this->addOutputSocket(COM_DT_VECTOR);
}
/* ******** Render Layers Material Index Operation ******** */
@@ -325,28 +351,28 @@ RenderLayersObjectIndexOperation::RenderLayersObjectIndexOperation() : RenderLay
RenderLayersReflectionOperation::RenderLayersReflectionOperation() : RenderLayersBaseProg(SCE_PASS_REFLECT, 3)
{
- this->addOutputSocket(COM_DT_COLOR);
+ this->addOutputSocket(COM_DT_VECTOR);
}
/* ******** Render Layers Refraction Operation ******** */
RenderLayersRefractionOperation::RenderLayersRefractionOperation() : RenderLayersBaseProg(SCE_PASS_REFRACT, 3)
{
- this->addOutputSocket(COM_DT_COLOR);
+ this->addOutputSocket(COM_DT_VECTOR);
}
/* ******** Render Layers Shadow Operation ******** */
RenderLayersShadowOperation::RenderLayersShadowOperation() : RenderLayersBaseProg(SCE_PASS_SHADOW, 3)
{
- this->addOutputSocket(COM_DT_COLOR);
+ this->addOutputSocket(COM_DT_VECTOR);
}
/* ******** Render Layers Specular Operation ******** */
RenderLayersSpecularOperation::RenderLayersSpecularOperation() : RenderLayersBaseProg(SCE_PASS_SPEC, 3)
{
- this->addOutputSocket(COM_DT_COLOR);
+ this->addOutputSocket(COM_DT_VECTOR);
}
/* ******** Render Layers Speed Operation ******** */
@@ -362,3 +388,29 @@ RenderLayersUVOperation::RenderLayersUVOperation() : RenderLayersBaseProg(SCE_PA
{
this->addOutputSocket(COM_DT_VECTOR);
}
+
+/* ******** Debug Render Layers Cycles Operation ******** */
+
+#ifdef WITH_CYCLES_DEBUG
+
+RenderLayersCyclesDebugOperation::RenderLayersCyclesDebugOperation(
+ int pass,
+ int debug_pass_type)
+ : RenderLayersBaseProg(pass, RE_debug_pass_num_channels_get(debug_pass_type))
+{
+ switch (m_elementsize) {
+ case 1:
+ this->addOutputSocket(COM_DT_VALUE);
+ break;
+ case 3:
+ this->addOutputSocket(COM_DT_VECTOR);
+ break;
+ case 4:
+ this->addOutputSocket(COM_DT_COLOR);
+ break;
+ default:
+ BLI_assert(!"Unkown debug pass type element size.");
+ }
+}
+
+#endif
diff --git a/source/blender/compositor/operations/COM_RenderLayersProg.h b/source/blender/compositor/operations/COM_RenderLayersProg.h
index 554e27eb579..89eb2a6954d 100644
--- a/source/blender/compositor/operations/COM_RenderLayersProg.h
+++ b/source/blender/compositor/operations/COM_RenderLayersProg.h
@@ -41,7 +41,7 @@ extern "C" {
* @todo: rename to operation.
*/
class RenderLayersBaseProg : public NodeOperation {
-private:
+protected:
/**
* Reference to the scene object.
*/
@@ -51,7 +51,12 @@ private:
* layerId of the layer where this operation needs to get its data from
*/
short m_layerId;
-
+
+ /**
+ * viewName of the view to use (unless another view is specified by the node
+ */
+ const char *m_viewName;
+
/**
* cached instance to the float buffer inside the layer
*/
@@ -69,7 +74,6 @@ private:
*/
const RenderData *m_rd;
-protected:
/**
* Constructor
*/
@@ -97,6 +101,8 @@ public:
void setRenderData(const RenderData *rd) { this->m_rd = rd; }
void setLayerId(short layerId) { this->m_layerId = layerId; }
short getLayerId() { return this->m_layerId; }
+ void setViewName(const char *viewName) { this->m_viewName = viewName; }
+ const char *getViewName() { return this->m_viewName; }
void initExecution();
void deinitExecution();
void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
@@ -105,6 +111,7 @@ public:
class RenderLayersAOOperation : public RenderLayersBaseProg {
public:
RenderLayersAOOperation();
+ void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
};
class RenderLayersAlphaProg : public RenderLayersBaseProg {
@@ -205,4 +212,12 @@ public:
RenderLayersUVOperation();
};
+#ifdef WITH_CYCLES_DEBUG
+class RenderLayersCyclesDebugOperation : public RenderLayersBaseProg {
+public:
+ RenderLayersCyclesDebugOperation(int pass,
+ int debug_pass_type);
+};
+#endif
+
#endif
diff --git a/source/blender/compositor/operations/COM_ScaleOperation.cpp b/source/blender/compositor/operations/COM_ScaleOperation.cpp
index 23e8ce86fd9..117ae743ee7 100644
--- a/source/blender/compositor/operations/COM_ScaleOperation.cpp
+++ b/source/blender/compositor/operations/COM_ScaleOperation.cpp
@@ -279,7 +279,7 @@ bool ScaleFixedSizeOperation::determineDependingAreaOfInterest(rcti *input, Read
return BaseScaleOperation::determineDependingAreaOfInterest(&newInput, readOperation, output);
}
-void ScaleFixedSizeOperation::determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2])
+void ScaleFixedSizeOperation::determineResolution(unsigned int resolution[2], unsigned int /*preferredResolution*/[2])
{
unsigned int nr[2];
nr[0] = this->m_newWidth;
diff --git a/source/blender/compositor/operations/COM_ScreenLensDistortionOperation.cpp b/source/blender/compositor/operations/COM_ScreenLensDistortionOperation.cpp
index ad9b761da45..acd76fa79a8 100644
--- a/source/blender/compositor/operations/COM_ScreenLensDistortionOperation.cpp
+++ b/source/blender/compositor/operations/COM_ScreenLensDistortionOperation.cpp
@@ -70,7 +70,7 @@ void ScreenLensDistortionOperation::initExecution()
}
}
-void *ScreenLensDistortionOperation::initializeTileData(rcti *rect)
+void *ScreenLensDistortionOperation::initializeTileData(rcti * /*rect*/)
{
void *buffer = this->m_inputProgram->initializeTileData(NULL);
@@ -208,7 +208,7 @@ void ScreenLensDistortionOperation::determineUV(float result[6], float x, float
get_delta(uv_dot, m_k4[2], uv, result + 4);
}
-bool ScreenLensDistortionOperation::determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output)
+bool ScreenLensDistortionOperation::determineDependingAreaOfInterest(rcti * /*input*/, ReadBufferOperation *readOperation, rcti *output)
{
rcti newInputValue;
newInputValue.xmin = 0;
diff --git a/source/blender/compositor/operations/COM_SetColorOperation.cpp b/source/blender/compositor/operations/COM_SetColorOperation.cpp
index 94a863e628b..1a362bc55e2 100644
--- a/source/blender/compositor/operations/COM_SetColorOperation.cpp
+++ b/source/blender/compositor/operations/COM_SetColorOperation.cpp
@@ -27,7 +27,9 @@ SetColorOperation::SetColorOperation() : NodeOperation()
this->addOutputSocket(COM_DT_COLOR);
}
-void SetColorOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler)
+void SetColorOperation::executePixelSampled(float output[4],
+ float /*x*/, float /*y*/,
+ PixelSampler /*sampler*/)
{
copy_v4_v4(output, this->m_color);
}
diff --git a/source/blender/compositor/operations/COM_SetSamplerOperation.cpp b/source/blender/compositor/operations/COM_SetSamplerOperation.cpp
index be72ffd0336..7057ecb14c1 100644
--- a/source/blender/compositor/operations/COM_SetSamplerOperation.cpp
+++ b/source/blender/compositor/operations/COM_SetSamplerOperation.cpp
@@ -37,7 +37,7 @@ void SetSamplerOperation::deinitExecution()
this->m_reader = NULL;
}
-void SetSamplerOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler)
+void SetSamplerOperation::executePixelSampled(float output[4], float x, float y, PixelSampler /*sampler*/)
{
this->m_reader->readSampled(output, x, y, this->m_sampler);
}
diff --git a/source/blender/compositor/operations/COM_SetValueOperation.cpp b/source/blender/compositor/operations/COM_SetValueOperation.cpp
index 51e09a63051..b6cfb760a98 100644
--- a/source/blender/compositor/operations/COM_SetValueOperation.cpp
+++ b/source/blender/compositor/operations/COM_SetValueOperation.cpp
@@ -27,7 +27,9 @@ SetValueOperation::SetValueOperation() : NodeOperation()
this->addOutputSocket(COM_DT_VALUE);
}
-void SetValueOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler)
+void SetValueOperation::executePixelSampled(float output[4],
+ float /*x*/, float /*y*/,
+ PixelSampler /*sampler*/)
{
output[0] = this->m_value;
}
diff --git a/source/blender/compositor/operations/COM_SetVectorOperation.cpp b/source/blender/compositor/operations/COM_SetVectorOperation.cpp
index 17212d78e15..1b0327683a9 100644
--- a/source/blender/compositor/operations/COM_SetVectorOperation.cpp
+++ b/source/blender/compositor/operations/COM_SetVectorOperation.cpp
@@ -28,12 +28,13 @@ SetVectorOperation::SetVectorOperation() : NodeOperation()
this->addOutputSocket(COM_DT_VECTOR);
}
-void SetVectorOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler)
+void SetVectorOperation::executePixelSampled(float output[4],
+ float /*x*/, float /*y*/,
+ PixelSampler /*sampler*/)
{
output[0] = this->m_x;
output[1] = this->m_y;
output[2] = this->m_z;
- output[3] = this->m_w;
}
void SetVectorOperation::determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2])
diff --git a/source/blender/compositor/operations/COM_SplitOperation.cpp b/source/blender/compositor/operations/COM_SplitOperation.cpp
index 367c7eefa25..cd2166591bc 100644
--- a/source/blender/compositor/operations/COM_SplitOperation.cpp
+++ b/source/blender/compositor/operations/COM_SplitOperation.cpp
@@ -56,7 +56,7 @@ void SplitOperation::deinitExecution()
this->m_image2Input = NULL;
}
-void SplitOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler)
+void SplitOperation::executePixelSampled(float output[4], float x, float y, PixelSampler /*sampler*/)
{
int perc = this->m_xSplit ? this->m_splitPercentage * this->getWidth() / 100.0f : this->m_splitPercentage * this->getHeight() / 100.0f;
bool image1 = this->m_xSplit ? x > perc : y > perc;
diff --git a/source/blender/compositor/operations/COM_SunBeamsOperation.cpp b/source/blender/compositor/operations/COM_SunBeamsOperation.cpp
index bcef652a8b5..a681583809c 100644
--- a/source/blender/compositor/operations/COM_SunBeamsOperation.cpp
+++ b/source/blender/compositor/operations/COM_SunBeamsOperation.cpp
@@ -50,34 +50,52 @@ void SunBeamsOperation::initExecution()
* For a target point (x,y) the sector should be chosen such that
* ``u >= v >= 0``
* This removes the need to handle all sorts of special cases.
+ *
+ * Template parameters:
+ * fxu : buffer increment in x for sector u+1
+ * fxv : buffer increment in x for sector v+1
+ * fyu : buffer increment in y for sector u+1
+ * fyv : buffer increment in y for sector v+1
*/
-template <int fxx, int fxy, int fyx, int fyy>
+template <int fxu, int fxv, int fyu, int fyv>
struct BufferLineAccumulator {
/* utility functions implementing the matrix transform to/from sector space */
-
- static inline void buffer_to_sector(int x, int y, int &u, int &v)
+
+ static inline void buffer_to_sector(const float source[2], int x, int y, int &u, int &v)
{
- u = x * fxx + y * fyx;
- v = x * fxy + y * fyy;
+ int x0 = (int)source[0];
+ int y0 = (int)source[1];
+ x -= x0;
+ y -= y0;
+ u = x * fxu + y * fyu;
+ v = x * fxv + y * fyv;
}
- static inline void buffer_to_sector(float x, float y, float &u, float &v)
+ static inline void buffer_to_sector(const float source[2], float x, float y, float &u, float &v)
{
- u = x * fxx + y * fyx;
- v = x * fxy + y * fyy;
+ int x0 = (int)source[0];
+ int y0 = (int)source[1];
+ x -= (float)x0;
+ y -= (float)y0;
+ u = x * fxu + y * fyu;
+ v = x * fxv + y * fyv;
}
- static inline void sector_to_buffer(int u, int v, int &x, int &y)
+ static inline void sector_to_buffer(const float source[2], int u, int v, int &x, int &y)
{
- x = u * fxx + v * fxy;
- y = u * fyx + v * fyy;
+ int x0 = (int)source[0];
+ int y0 = (int)source[1];
+ x = x0 + u * fxu + v * fxv;
+ y = y0 + u * fyu + v * fyv;
}
- static inline void sector_to_buffer(float u, float v, float &x, float &y)
+ static inline void sector_to_buffer(const float source[2], float u, float v, float &x, float &y)
{
- x = u * fxx + v * fxy;
- y = u * fyx + v * fyy;
+ int x0 = (int)source[0];
+ int y0 = (int)source[1];
+ x = (float)x0 + u * fxu + v * fxv;
+ y = (float)y0 + u * fyu + v * fyv;
}
/**
@@ -91,12 +109,12 @@ struct BufferLineAccumulator {
* \param num Total steps in the loop
* \param v, dv Vertical offset in sector space, for line offset perpendicular to the loop axis
*/
- static float *init_buffer_iterator(MemoryBuffer *input, const float source[2], const float pt_ofs[2],
+ static float *init_buffer_iterator(MemoryBuffer *input, const float source[2], const float co[2],
float dist_min, float dist_max,
int &x, int &y, int &num, float &v, float &dv, float &falloff_factor)
{
float pu, pv;
- buffer_to_sector(pt_ofs[0], pt_ofs[1], pu, pv);
+ buffer_to_sector(source, co[0], co[1], pu, pv);
/* line angle */
float tan_phi = pv / pu;
@@ -113,13 +131,11 @@ struct BufferLineAccumulator {
int end = (int)ceilf(umin);
num = end - start;
- sector_to_buffer(end, (int)ceilf(v), x, y);
- x += (int)source[0];
- y += (int)source[1];
+ sector_to_buffer(source, end, (int)ceilf(v), x, y);
falloff_factor = dist_max > dist_min ? dr / (float)(dist_max - dist_min) : 0.0f;
- float *iter = input->getBuffer() + COM_NUMBER_OF_CHANNELS * (x + input->getWidth() * y);
+ float *iter = input->getBuffer() + COM_NUM_CHANNELS_COLOR * (x + input->getWidth() * y);
return iter;
}
@@ -130,7 +146,7 @@ struct BufferLineAccumulator {
* The loop runs backwards(!) over the primary sector space axis u, i.e. increasing distance to pt.
* After each step it decrements v by dv < 1, adding a buffer shift when necessary.
*/
- static void eval(MemoryBuffer *input, float output[4], const float pt_ofs[2], const float source[2],
+ static void eval(MemoryBuffer *input, float output[4], const float co[2], const float source[2],
float dist_min, float dist_max)
{
rcti rect = *input->getRect();
@@ -139,14 +155,16 @@ struct BufferLineAccumulator {
float v, dv;
float falloff_factor;
float border[4];
-
- if ((int)pt_ofs[0] == 0 && (int)pt_ofs[1] == 0) {
- copy_v4_v4(output, input->getBuffer() + COM_NUMBER_OF_CHANNELS * ((int)source[0] + input->getWidth() * (int)source[1]));
+
+ zero_v4(output);
+
+ if ((int)(co[0] - source[0]) == 0 && (int)(co[1] - source[1]) == 0) {
+ copy_v4_v4(output, input->getBuffer() + COM_NUM_CHANNELS_COLOR * ((int)source[0] + input->getWidth() * (int)source[1]));
return;
}
/* initialise the iteration variables */
- float *buffer = init_buffer_iterator(input, source, pt_ofs, dist_min, dist_max, x, y, num, v, dv, falloff_factor);
+ float *buffer = init_buffer_iterator(input, source, co, dist_min, dist_max, x, y, num, v, dv, falloff_factor);
zero_v3(border);
border[3] = 1.0f;
@@ -178,18 +196,18 @@ struct BufferLineAccumulator {
*/
/* decrement u */
- x -= fxx;
- y -= fyx;
- buffer -= (fxx + fyx * buffer_width) * COM_NUMBER_OF_CHANNELS;
+ x -= fxu;
+ y -= fyu;
+ buffer -= (fxu + fyu * buffer_width) * COM_NUM_CHANNELS_COLOR;
/* decrement v (in steps of dv < 1) */
v_local -= dv;
if (v_local < 0.0f) {
v_local += 1.0f;
- x -= fxy;
- y -= fyy;
- buffer -= (fxy + fyy * buffer_width) * COM_NUMBER_OF_CHANNELS;
+ x -= fxv;
+ y -= fyv;
+ buffer -= (fxv + fyv * buffer_width) * COM_NUM_CHANNELS_COLOR;
}
}
@@ -233,21 +251,21 @@ static void accumulate_line(MemoryBuffer *input, float output[4], const float co
if (pt_ofs[0] > 0.0f) {
if (pt_ofs[1] > 0.0f) {
/* 2 */
- BufferLineAccumulator<0, 1, 1, 0>::eval(input, output, pt_ofs, source, dist_min, dist_max);
+ BufferLineAccumulator<0, 1, 1, 0>::eval(input, output, co, source, dist_min, dist_max);
}
else {
/* 7 */
- BufferLineAccumulator<0, 1, -1, 0>::eval(input, output, pt_ofs, source, dist_min, dist_max);
+ BufferLineAccumulator<0, 1, -1, 0>::eval(input, output, co, source, dist_min, dist_max);
}
}
else {
if (pt_ofs[1] > 0.0f) {
/* 3 */
- BufferLineAccumulator<0, -1, 1, 0>::eval(input, output, pt_ofs, source, dist_min, dist_max);
+ BufferLineAccumulator<0, -1, 1, 0>::eval(input, output, co, source, dist_min, dist_max);
}
else {
/* 6 */
- BufferLineAccumulator<0, -1, -1, 0>::eval(input, output, pt_ofs, source, dist_min, dist_max);
+ BufferLineAccumulator<0, -1, -1, 0>::eval(input, output, co, source, dist_min, dist_max);
}
}
}
@@ -255,27 +273,27 @@ static void accumulate_line(MemoryBuffer *input, float output[4], const float co
if (pt_ofs[0] > 0.0f) {
if (pt_ofs[1] > 0.0f) {
/* 1 */
- BufferLineAccumulator< 1, 0, 0, 1>::eval(input, output, pt_ofs, source, dist_min, dist_max);
+ BufferLineAccumulator< 1, 0, 0, 1>::eval(input, output, co, source, dist_min, dist_max);
}
else {
/* 8 */
- BufferLineAccumulator< 1, 0, 0, -1>::eval(input, output, pt_ofs, source, dist_min, dist_max);
+ BufferLineAccumulator< 1, 0, 0, -1>::eval(input, output, co, source, dist_min, dist_max);
}
}
else {
if (pt_ofs[1] > 0.0f) {
/* 4 */
- BufferLineAccumulator<-1, 0, 0, 1>::eval(input, output, pt_ofs, source, dist_min, dist_max);
+ BufferLineAccumulator<-1, 0, 0, 1>::eval(input, output, co, source, dist_min, dist_max);
}
else {
/* 5 */
- BufferLineAccumulator<-1, 0, 0, -1>::eval(input, output, pt_ofs, source, dist_min, dist_max);
+ BufferLineAccumulator<-1, 0, 0, -1>::eval(input, output, co, source, dist_min, dist_max);
}
}
}
}
-void *SunBeamsOperation::initializeTileData(rcti *rect)
+void *SunBeamsOperation::initializeTileData(rcti * /*rect*/)
{
void *buffer = getInputOperation(0)->initializeTileData(NULL);
return buffer;
diff --git a/source/blender/compositor/operations/COM_TextureOperation.cpp b/source/blender/compositor/operations/COM_TextureOperation.cpp
index ede767cbff7..c75c4040823 100644
--- a/source/blender/compositor/operations/COM_TextureOperation.cpp
+++ b/source/blender/compositor/operations/COM_TextureOperation.cpp
@@ -23,8 +23,11 @@
#include "COM_TextureOperation.h"
#include "BLI_listbase.h"
+#include "BLI_threads.h"
#include "BKE_image.h"
+static ThreadMutex mutex_lock = BLI_MUTEX_INITIALIZER;
+
TextureBaseOperation::TextureBaseOperation() : SingleThreadedOperation()
{
this->addInputSocket(COM_DT_VECTOR); //offset
@@ -77,12 +80,9 @@ void TextureBaseOperation::determineResolution(unsigned int resolution[2], unsig
void TextureAlphaOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler)
{
- TextureBaseOperation::executePixelSampled(output, x, y, sampler);
- output[0] = output[3];
- output[1] = 0.0f;
- output[2] = 0.0f;
- output[3] = 0.0f;
-}
+ float color[4];
+ TextureBaseOperation::executePixelSampled(color, x, y, sampler);
+ output[0] = color[3];}
void TextureBaseOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler)
{
@@ -103,7 +103,12 @@ void TextureBaseOperation::executePixelSampled(float output[4], float x, float y
vec[1] = textureSize[1] * (v + textureOffset[1]);
vec[2] = textureSize[2] * textureOffset[2];
- retval = multitex_ext(this->m_texture, vec, NULL, NULL, 0, &texres, m_pool, m_sceneColorManage);
+ /* TODO(sergey): Need to pass thread ID to the multitex code,
+ * then we can avoid having mutex here.
+ */
+ BLI_mutex_lock(&mutex_lock);
+ retval = multitex_ext(this->m_texture, vec, NULL, NULL, 0, &texres, m_pool, m_sceneColorManage, false);
+ BLI_mutex_unlock(&mutex_lock);
if (texres.talpha)
output[3] = texres.ta;
@@ -120,22 +125,27 @@ void TextureBaseOperation::executePixelSampled(float output[4], float x, float y
}
}
-MemoryBuffer *TextureBaseOperation::createMemoryBuffer(rcti *rect2)
+MemoryBuffer *TextureBaseOperation::createMemoryBuffer(rcti * /*rect2*/)
{
int height = getHeight();
int width = getWidth();
+ DataType datatype = this->getOutputSocket()->getDataType();
+ int add = 4;
+ if (datatype == COM_DT_VALUE) {
+ add = 1;
+ }
rcti rect;
rect.xmin = 0;
rect.ymin = 0;
rect.xmax = width;
rect.ymax = height;
- MemoryBuffer *result = new MemoryBuffer(NULL, &rect);
+ MemoryBuffer *result = new MemoryBuffer(datatype, &rect);
float *data = result->getBuffer();
for (int y = 0; y < height; y++) {
- for (int x = 0; x < width; x++, data += 4) {
+ for (int x = 0; x < width; x++, data += add) {
this->executePixelSampled(data, x, y, COM_PS_NEAREST);
}
}
diff --git a/source/blender/compositor/operations/COM_TonemapOperation.cpp b/source/blender/compositor/operations/COM_TonemapOperation.cpp
index e8a578fa131..c581d115a2f 100644
--- a/source/blender/compositor/operations/COM_TonemapOperation.cpp
+++ b/source/blender/compositor/operations/COM_TonemapOperation.cpp
@@ -24,6 +24,10 @@
#include "BLI_math.h"
#include "BLI_utildefines.h"
+extern "C" {
+#include "IMB_colormanagement.h"
+}
+
TonemapOperation::TonemapOperation() : NodeOperation()
{
this->addInputSocket(COM_DT_COLOR, COM_SC_NO_RESIZE);
@@ -69,7 +73,7 @@ void PhotoreceptorTonemapOperation::executePixel(float output[4], int x, int y,
this->m_imageReader->read(output, x, y, NULL);
- const float L = rgb_to_luma_y(output);
+ const float L = IMB_colormanagement_get_luminance(output);
float I_l = output[0] + ic * (L - output[0]);
float I_g = avg->cav[0] + ic * (avg->lav - avg->cav[0]);
float I_a = I_l + ia * (I_g - I_l);
@@ -93,7 +97,7 @@ void TonemapOperation::deinitExecution()
NodeOperation::deinitMutex();
}
-bool TonemapOperation::determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output)
+bool TonemapOperation::determineDependingAreaOfInterest(rcti * /*input*/, ReadBufferOperation *readOperation, rcti *output)
{
rcti imageInput;
@@ -125,7 +129,7 @@ void *TonemapOperation::initializeTileData(rcti *rect)
float Lav = 0.f;
float cav[4] = {0.0f, 0.0f, 0.0f, 0.0f};
while (p--) {
- float L = rgb_to_luma_y(bc);
+ float L = IMB_colormanagement_get_luminance(bc);
Lav += L;
add_v3_v3(cav, bc);
lsum += logf(MAX2(L, 0.0f) + 1e-5f);
@@ -146,7 +150,7 @@ void *TonemapOperation::initializeTileData(rcti *rect)
return this->m_cachedInstance;
}
-void TonemapOperation::deinitializeTileData(rcti *rect, void *data)
+void TonemapOperation::deinitializeTileData(rcti * /*rect*/, void * /*data*/)
{
/* pass */
}
diff --git a/source/blender/compositor/operations/COM_TrackPositionOperation.cpp b/source/blender/compositor/operations/COM_TrackPositionOperation.cpp
index a76e0866d0d..ca169d03fbc 100644
--- a/source/blender/compositor/operations/COM_TrackPositionOperation.cpp
+++ b/source/blender/compositor/operations/COM_TrackPositionOperation.cpp
@@ -102,7 +102,9 @@ void TrackPositionOperation::initExecution()
}
}
-void TrackPositionOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler)
+void TrackPositionOperation::executePixelSampled(float output[4],
+ float /*x*/, float /*y*/,
+ PixelSampler /*sampler*/)
{
output[0] = this->m_markerPos[this->m_axis] - this->m_relativePos[this->m_axis];
diff --git a/source/blender/compositor/operations/COM_TranslateOperation.cpp b/source/blender/compositor/operations/COM_TranslateOperation.cpp
index 191388a42fb..fcf99a10a73 100644
--- a/source/blender/compositor/operations/COM_TranslateOperation.cpp
+++ b/source/blender/compositor/operations/COM_TranslateOperation.cpp
@@ -52,7 +52,7 @@ void TranslateOperation::deinitExecution()
}
-void TranslateOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler)
+void TranslateOperation::executePixelSampled(float output[4], float x, float y, PixelSampler /*sampler*/)
{
ensureDelta();
diff --git a/source/blender/compositor/operations/COM_VariableSizeBokehBlurOperation.cpp b/source/blender/compositor/operations/COM_VariableSizeBokehBlurOperation.cpp
index 4b81001fdab..1ec52571be8 100644
--- a/source/blender/compositor/operations/COM_VariableSizeBokehBlurOperation.cpp
+++ b/source/blender/compositor/operations/COM_VariableSizeBokehBlurOperation.cpp
@@ -62,8 +62,7 @@ void VariableSizeBokehBlurOperation::initExecution()
#endif
QualityStepHelper::initExecution(COM_QH_INCREASE);
}
-struct VariableSizeBokehBlurTileData
-{
+struct VariableSizeBokehBlurTileData {
MemoryBuffer *color;
MemoryBuffer *bokeh;
MemoryBuffer *size;
@@ -89,7 +88,7 @@ void *VariableSizeBokehBlurOperation::initializeTileData(rcti *rect)
return data;
}
-void VariableSizeBokehBlurOperation::deinitializeTileData(rcti *rect, void *data)
+void VariableSizeBokehBlurOperation::deinitializeTileData(rcti * /*rect*/, void *data)
{
VariableSizeBokehBlurTileData *result = (VariableSizeBokehBlurTileData *)data;
delete result;
@@ -137,30 +136,33 @@ void VariableSizeBokehBlurOperation::executePixel(float output[4], int x, int y,
copy_v4_fl(multiplier_accum, 1.0f);
float size_center = tempSize[0] * scalar;
- const int addXStep = QualityStepHelper::getStep() * COM_NUMBER_OF_CHANNELS;
-
+ const int addXStepValue = QualityStepHelper::getStep();
+ const int addYStepValue = addXStepValue;
+ const int addXStepColor = addXStepValue * COM_NUM_CHANNELS_COLOR;
+
if (size_center > this->m_threshold) {
- for (int ny = miny; ny < maxy; ny += QualityStepHelper::getStep()) {
+ for (int ny = miny; ny < maxy; ny += addYStepValue) {
float dy = ny - y;
- int offsetNy = ny * inputSizeBuffer->getWidth() * COM_NUMBER_OF_CHANNELS;
- int offsetNxNy = offsetNy + (minx * COM_NUMBER_OF_CHANNELS);
- for (int nx = minx; nx < maxx; nx += QualityStepHelper::getStep()) {
+ int offsetValueNy = ny * inputSizeBuffer->getWidth();
+ int offsetValueNxNy = offsetValueNy + (minx);
+ int offsetColorNxNy = offsetValueNxNy * COM_NUM_CHANNELS_COLOR;
+ for (int nx = minx; nx < maxx; nx += addXStepValue) {
if (nx != x || ny != y) {
- float size = min(inputSizeFloatBuffer[offsetNxNy] * scalar, size_center);
+ float size = min(inputSizeFloatBuffer[offsetValueNxNy] * scalar, size_center);
if (size > this->m_threshold) {
float dx = nx - x;
if (size > fabsf(dx) && size > fabsf(dy)) {
float uv[2] = {
- (float)(COM_BLUR_BOKEH_PIXELS / 2) + (dx / size) * (float)((COM_BLUR_BOKEH_PIXELS / 2) - 1),
- (float)(COM_BLUR_BOKEH_PIXELS / 2) + (dy / size) * (float)((COM_BLUR_BOKEH_PIXELS / 2) - 1)};
- inputBokehBuffer->readNoCheck(bokeh, uv[0], uv[1]);
- madd_v4_v4v4(color_accum, bokeh, &inputProgramFloatBuffer[offsetNxNy]);
+ (float)(COM_BLUR_BOKEH_PIXELS / 2) + (dx / size) * (float)((COM_BLUR_BOKEH_PIXELS / 2) - 1),
+ (float)(COM_BLUR_BOKEH_PIXELS / 2) + (dy / size) * (float)((COM_BLUR_BOKEH_PIXELS / 2) - 1)};
+ inputBokehBuffer->read(bokeh, uv[0], uv[1]);
+ madd_v4_v4v4(color_accum, bokeh, &inputProgramFloatBuffer[offsetColorNxNy]);
add_v4_v4(multiplier_accum, bokeh);
}
}
}
- offsetNxNy += addXStep;
- }
+ offsetColorNxNy += addXStepColor;
+ offsetValueNxNy += addXStepValue; }
}
}
@@ -184,7 +186,7 @@ void VariableSizeBokehBlurOperation::executePixel(float output[4], int x, int y,
void VariableSizeBokehBlurOperation::executeOpenCL(OpenCLDevice *device,
MemoryBuffer *outputMemoryBuffer, cl_mem clOutputBuffer,
MemoryBuffer **inputMemoryBuffers, list<cl_mem> *clMemToCleanUp,
- list<cl_kernel> *clKernelsToCleanUp)
+ list<cl_kernel> * /*clKernelsToCleanUp*/)
{
cl_kernel defocusKernel = device->COM_clCreateKernel("defocusKernel", NULL);
@@ -197,8 +199,8 @@ void VariableSizeBokehBlurOperation::executeOpenCL(OpenCLDevice *device,
const float max_dim = max(m_width, m_height);
cl_float scalar = this->m_do_size_scale ? (max_dim / 100.0f) : 1.0f;
- maxBlur = (cl_int)sizeMemoryBuffer->getMaximumValue() * scalar;
- maxBlur = min(maxBlur, this->m_maxBlur);
+ maxBlur = (cl_int)min_ff(sizeMemoryBuffer->getMaximumValue() * scalar,
+ (float)this->m_maxBlur);
device->COM_clAttachMemoryBufferToKernelParameter(defocusKernel, 0, -1, clMemToCleanUp, inputMemoryBuffers, this->m_inputProgram);
device->COM_clAttachMemoryBufferToKernelParameter(defocusKernel, 1, -1, clMemToCleanUp, inputMemoryBuffers, this->m_inputBokehProgram);
diff --git a/source/blender/compositor/operations/COM_VectorBlurOperation.cpp b/source/blender/compositor/operations/COM_VectorBlurOperation.cpp
index f5890157440..36f06e92436 100644
--- a/source/blender/compositor/operations/COM_VectorBlurOperation.cpp
+++ b/source/blender/compositor/operations/COM_VectorBlurOperation.cpp
@@ -57,7 +57,7 @@ void VectorBlurOperation::initExecution()
void VectorBlurOperation::executePixel(float output[4], int x, int y, void *data)
{
float *buffer = (float *) data;
- int index = (y * this->getWidth() + x) * COM_NUMBER_OF_CHANNELS;
+ int index = (y * this->getWidth() + x) * COM_NUM_CHANNELS_COLOR;
copy_v4_v4(output, &buffer[index]);
}
@@ -91,7 +91,7 @@ void *VectorBlurOperation::initializeTileData(rcti *rect)
return this->m_cachedInstance;
}
-bool VectorBlurOperation::determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output)
+bool VectorBlurOperation::determineDependingAreaOfInterest(rcti * /*input*/, ReadBufferOperation *readOperation, rcti *output)
{
if (this->m_cachedInstance == NULL) {
rcti newInput;
@@ -108,14 +108,12 @@ bool VectorBlurOperation::determineDependingAreaOfInterest(rcti *input, ReadBuff
void VectorBlurOperation::generateVectorBlur(float *data, MemoryBuffer *inputImage, MemoryBuffer *inputSpeed, MemoryBuffer *inputZ)
{
- float *zbuf = inputZ->convertToValueBuffer();
NodeBlurData blurdata;
blurdata.samples = this->m_settings->samples / QualityStepHelper::getStep();
blurdata.maxspeed = this->m_settings->maxspeed;
blurdata.minspeed = this->m_settings->minspeed;
blurdata.curved = this->m_settings->curved;
blurdata.fac = this->m_settings->fac;
- RE_zbuf_accumulate_vecblur(&blurdata, this->getWidth(), this->getHeight(), data, inputImage->getBuffer(), inputSpeed->getBuffer(), zbuf);
- MEM_freeN((void *)zbuf);
+ RE_zbuf_accumulate_vecblur(&blurdata, this->getWidth(), this->getHeight(), data, inputImage->getBuffer(), inputSpeed->getBuffer(), inputZ->getBuffer());
return;
}
diff --git a/source/blender/compositor/operations/COM_VectorCurveOperation.cpp b/source/blender/compositor/operations/COM_VectorCurveOperation.cpp
index fedc8c6db7d..dfdc54012a8 100644
--- a/source/blender/compositor/operations/COM_VectorCurveOperation.cpp
+++ b/source/blender/compositor/operations/COM_VectorCurveOperation.cpp
@@ -51,7 +51,6 @@ void VectorCurveOperation::executePixelSampled(float output[4], float x, float y
this->m_inputProgram->readSampled(input, x, y, sampler);
curvemapping_evaluate_premulRGBF(this->m_curveMapping, output, input);
- output[3] = input[3];
}
void VectorCurveOperation::deinitExecution()
diff --git a/source/blender/compositor/operations/COM_ViewerOperation.cpp b/source/blender/compositor/operations/COM_ViewerOperation.cpp
index 53c0acd781a..aa47d3427d0 100644
--- a/source/blender/compositor/operations/COM_ViewerOperation.cpp
+++ b/source/blender/compositor/operations/COM_ViewerOperation.cpp
@@ -23,6 +23,7 @@
#include "COM_ViewerOperation.h"
#include "BLI_listbase.h"
#include "BKE_image.h"
+#include "BKE_scene.h"
#include "WM_api.h"
#include "WM_types.h"
#include "PIL_time.h"
@@ -57,6 +58,8 @@ ViewerOperation::ViewerOperation() : NodeOperation()
this->m_imageInput = NULL;
this->m_alphaInput = NULL;
this->m_depthInput = NULL;
+ this->m_rd = NULL;
+ this->m_viewName = NULL;
}
void ViewerOperation::initExecution()
@@ -80,7 +83,7 @@ void ViewerOperation::deinitExecution()
this->m_outputBuffer = NULL;
}
-void ViewerOperation::executeRegion(rcti *rect, unsigned int tileNumber)
+void ViewerOperation::executeRegion(rcti *rect, unsigned int /*tileNumber*/)
{
float *buffer = this->m_outputBuffer;
float *depthbuffer = this->m_depthBuffer;
@@ -123,11 +126,25 @@ void ViewerOperation::executeRegion(rcti *rect, unsigned int tileNumber)
void ViewerOperation::initImage()
{
Image *ima = this->m_image;
+ ImageUser iuser = *this->m_imageUser;
void *lock;
- ImBuf *ibuf = BKE_image_acquire_ibuf(ima, this->m_imageUser, &lock);
+ ImBuf *ibuf;
+
+ /* make sure the image has the correct number of views */
+ if (ima && BKE_scene_multiview_is_render_view_first(this->m_rd, this->m_viewName)) {
+ BKE_image_verify_viewer_views(this->m_rd, ima, this->m_imageUser);
+ }
- if (!ibuf) return;
BLI_lock_thread(LOCK_DRAW_IMAGE);
+
+ /* local changes to the original ImageUser */
+ iuser.multi_index = BKE_scene_multiview_view_id_get(this->m_rd, this->m_viewName);
+ ibuf = BKE_image_acquire_ibuf(ima, &iuser, &lock);
+
+ if (!ibuf) {
+ BLI_unlock_thread(LOCK_DRAW_IMAGE);
+ return;
+ }
if (ibuf->x != (int)getWidth() || ibuf->y != (int)getHeight()) {
imb_freerectImBuf(ibuf);
@@ -146,7 +163,6 @@ void ViewerOperation::initImage()
if (m_doDepthBuffer) {
addzbuffloatImBuf(ibuf);
}
- BLI_unlock_thread(LOCK_DRAW_IMAGE);
/* now we combine the input with ibuf */
this->m_outputBuffer = ibuf->rect_float;
@@ -159,6 +175,8 @@ void ViewerOperation::initImage()
}
BKE_image_release_ibuf(this->m_image, this->m_ibuf, lock);
+
+ BLI_unlock_thread(LOCK_DRAW_IMAGE);
}
void ViewerOperation::updateImage(rcti *rect)
diff --git a/source/blender/compositor/operations/COM_ViewerOperation.h b/source/blender/compositor/operations/COM_ViewerOperation.h
index dcc7ffa3730..107aee3a82f 100644
--- a/source/blender/compositor/operations/COM_ViewerOperation.h
+++ b/source/blender/compositor/operations/COM_ViewerOperation.h
@@ -40,7 +40,9 @@ private:
bool m_doDepthBuffer;
ImBuf *m_ibuf;
bool m_useAlphaInput;
-
+ const RenderData *m_rd;
+ const char *m_viewName;
+
const ColorManagedViewSettings *m_viewSettings;
const ColorManagedDisplaySettings *m_displaySettings;
@@ -53,7 +55,7 @@ public:
void initExecution();
void deinitExecution();
void executeRegion(rcti *rect, unsigned int tileNumber);
- bool isOutputOperation(bool rendering) const { if (G.background) return false; return isActiveViewerOutput(); }
+ bool isOutputOperation(bool /*rendering*/) const { if (G.background) return false; return isActiveViewerOutput(); }
void setImage(Image *image) { this->m_image = image; }
void setImageUser(ImageUser *imageUser) { this->m_imageUser = imageUser; }
const bool isActiveViewerOutput() const { return this->m_active; }
@@ -67,6 +69,8 @@ public:
const CompositorPriority getRenderPriority() const;
bool isViewerOperation() const { return true; }
void setUseAlphaInput(bool value) { this->m_useAlphaInput = value; }
+ void setRenderData(const RenderData *rd) { this->m_rd = rd; }
+ void setViewName(const char *viewName) { this->m_viewName = viewName; }
void setViewSettings(const ColorManagedViewSettings *viewSettings) { this->m_viewSettings = viewSettings; }
void setDisplaySettings(const ColorManagedDisplaySettings *displaySettings) { this->m_displaySettings = displaySettings; }
diff --git a/source/blender/compositor/operations/COM_WrapOperation.cpp b/source/blender/compositor/operations/COM_WrapOperation.cpp
index c30361d1df8..7fbef453a13 100644
--- a/source/blender/compositor/operations/COM_WrapOperation.cpp
+++ b/source/blender/compositor/operations/COM_WrapOperation.cpp
@@ -23,7 +23,7 @@
#include "COM_WrapOperation.h"
-WrapOperation::WrapOperation() : ReadBufferOperation()
+WrapOperation::WrapOperation(DataType datatype) : ReadBufferOperation(datatype)
{
this->m_wrappingType = CMP_NODE_WRAP_NONE;
}
diff --git a/source/blender/compositor/operations/COM_WrapOperation.h b/source/blender/compositor/operations/COM_WrapOperation.h
index 33ea1280564..92c93565691 100644
--- a/source/blender/compositor/operations/COM_WrapOperation.h
+++ b/source/blender/compositor/operations/COM_WrapOperation.h
@@ -29,7 +29,7 @@ class WrapOperation : public ReadBufferOperation {
private:
int m_wrappingType;
public:
- WrapOperation();
+ WrapOperation(DataType datetype);
bool determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output);
void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
diff --git a/source/blender/compositor/operations/COM_WriteBufferOperation.cpp b/source/blender/compositor/operations/COM_WriteBufferOperation.cpp
index 832864b399d..b3c1c00804e 100644
--- a/source/blender/compositor/operations/COM_WriteBufferOperation.cpp
+++ b/source/blender/compositor/operations/COM_WriteBufferOperation.cpp
@@ -25,10 +25,10 @@
#include <stdio.h>
#include "COM_OpenCLDevice.h"
-WriteBufferOperation::WriteBufferOperation() : NodeOperation()
+WriteBufferOperation::WriteBufferOperation(DataType datatype) : NodeOperation()
{
- this->addInputSocket(COM_DT_COLOR);
- this->m_memoryProxy = new MemoryProxy();
+ this->addInputSocket(datatype);
+ this->m_memoryProxy = new MemoryProxy(datatype);
this->m_memoryProxy->setWriteBufferOperation(this);
this->m_memoryProxy->setExecutor(NULL);
}
@@ -57,10 +57,11 @@ void WriteBufferOperation::deinitExecution()
this->m_memoryProxy->free();
}
-void WriteBufferOperation::executeRegion(rcti *rect, unsigned int tileNumber)
+void WriteBufferOperation::executeRegion(rcti *rect, unsigned int /*tileNumber*/)
{
MemoryBuffer *memoryBuffer = this->m_memoryProxy->getBuffer();
float *buffer = memoryBuffer->getBuffer();
+ const int num_channels = memoryBuffer->get_num_channels();
if (this->m_input->isComplex()) {
void *data = this->m_input->initializeTileData(rect);
int x1 = rect->xmin;
@@ -71,10 +72,10 @@ void WriteBufferOperation::executeRegion(rcti *rect, unsigned int tileNumber)
int y;
bool breaked = false;
for (y = y1; y < y2 && (!breaked); y++) {
- int offset4 = (y * memoryBuffer->getWidth() + x1) * COM_NUMBER_OF_CHANNELS;
+ int offset4 = (y * memoryBuffer->getWidth() + x1) * num_channels;
for (x = x1; x < x2; x++) {
this->m_input->read(&(buffer[offset4]), x, y, data);
- offset4 += COM_NUMBER_OF_CHANNELS;
+ offset4 += num_channels;
}
if (isBreaked()) {
breaked = true;
@@ -96,10 +97,10 @@ void WriteBufferOperation::executeRegion(rcti *rect, unsigned int tileNumber)
int y;
bool breaked = false;
for (y = y1; y < y2 && (!breaked); y++) {
- int offset4 = (y * memoryBuffer->getWidth() + x1) * COM_NUMBER_OF_CHANNELS;
+ int offset4 = (y * memoryBuffer->getWidth() + x1) * num_channels;
for (x = x1; x < x2; x++) {
this->m_input->readSampled(&(buffer[offset4]), x, y, COM_PS_NEAREST);
- offset4 += COM_NUMBER_OF_CHANNELS;
+ offset4 += num_channels;
}
if (isBreaked()) {
breaked = true;
@@ -109,7 +110,7 @@ void WriteBufferOperation::executeRegion(rcti *rect, unsigned int tileNumber)
memoryBuffer->setCreatedState();
}
-void WriteBufferOperation::executeOpenCLRegion(OpenCLDevice *device, rcti *rect, unsigned int chunkNumber,
+void WriteBufferOperation::executeOpenCLRegion(OpenCLDevice *device, rcti * /*rect*/, unsigned int /*chunkNumber*/,
MemoryBuffer **inputMemoryBuffers, MemoryBuffer *outputBuffer)
{
float *outputFloatBuffer = outputBuffer->getBuffer();
@@ -126,12 +127,9 @@ void WriteBufferOperation::executeOpenCLRegion(OpenCLDevice *device, rcti *rect,
const unsigned int outputBufferWidth = outputBuffer->getWidth();
const unsigned int outputBufferHeight = outputBuffer->getHeight();
- const cl_image_format imageFormat = {
- CL_RGBA,
- CL_FLOAT
- };
+ const cl_image_format *imageFormat = device->determineImageFormat(outputBuffer);
- cl_mem clOutputBuffer = clCreateImage2D(device->getContext(), CL_MEM_WRITE_ONLY | CL_MEM_USE_HOST_PTR, &imageFormat, outputBufferWidth, outputBufferHeight, 0, outputFloatBuffer, &error);
+ cl_mem clOutputBuffer = clCreateImage2D(device->getContext(), CL_MEM_WRITE_ONLY | CL_MEM_USE_HOST_PTR, imageFormat, outputBufferWidth, outputBufferHeight, 0, outputFloatBuffer, &error);
if (error != CL_SUCCESS) { printf("CLERROR[%d]: %s\n", error, clewErrorString(error)); }
// STEP 2
diff --git a/source/blender/compositor/operations/COM_WriteBufferOperation.h b/source/blender/compositor/operations/COM_WriteBufferOperation.h
index 96466df979c..9220cb179c6 100644
--- a/source/blender/compositor/operations/COM_WriteBufferOperation.h
+++ b/source/blender/compositor/operations/COM_WriteBufferOperation.h
@@ -35,7 +35,7 @@ class WriteBufferOperation : public NodeOperation {
bool m_single_value; /* single value stored in buffer */
NodeOperation *m_input;
public:
- WriteBufferOperation();
+ WriteBufferOperation(DataType datatype);
~WriteBufferOperation();
MemoryProxy *getMemoryProxy() { return this->m_memoryProxy; }
void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
diff --git a/source/blender/datatoc/datatoc_icon.c b/source/blender/datatoc/datatoc_icon.c
index 7df9269a4a8..92048f32a28 100644
--- a/source/blender/datatoc/datatoc_icon.c
+++ b/source/blender/datatoc/datatoc_icon.c
@@ -166,7 +166,8 @@ static bool write_png(const char *name, const unsigned int *pixels,
/* set the individual row-pointers to point at the correct offsets */
for (i = 0; i < height; i++) {
row_pointers[height - 1 - i] = (png_bytep)
- (((unsigned char *)pixels) + (i * width) * bytesperpixel * sizeof(unsigned char));
+ (((const unsigned char *)pixels) +
+ (i * width) * bytesperpixel * sizeof(unsigned char));
}
/* write out the entire image data in one call */
diff --git a/source/blender/datatoc/datatoc_icon.py b/source/blender/datatoc/datatoc_icon.py
index 930d588f859..16092431195 100755
--- a/source/blender/datatoc/datatoc_icon.py
+++ b/source/blender/datatoc/datatoc_icon.py
@@ -113,6 +113,17 @@ def icondir_to_png(path_src, file_dst):
files = [os.path.join(path_src, f) for f in os.listdir(path_src) if f.endswith(".dat")]
+ # First check if we need to bother.
+ if os.path.exists(file_dst):
+ dst_time = os.path.getmtime(file_dst)
+ has_newer = False
+ for f in files:
+ if os.path.getmtime(f) > dst_time:
+ has_newer = True
+ break
+ if not has_newer:
+ return
+
with open(files[0], 'rb') as f_src:
(icon_w, icon_h,
orig_x, orig_y,
diff --git a/source/blender/datatoc/datatoc_icon_split.py b/source/blender/datatoc/datatoc_icon_split.py
index 55f0a5c5f6a..aae907ec340 100755
--- a/source/blender/datatoc/datatoc_icon_split.py
+++ b/source/blender/datatoc/datatoc_icon_split.py
@@ -63,7 +63,7 @@ def image_from_file(filepath):
try:
import bpy
- except:
+ except ImportError:
bpy = None
if bpy is not None:
diff --git a/source/blender/depsgraph/CMakeLists.txt b/source/blender/depsgraph/CMakeLists.txt
new file mode 100644
index 00000000000..f3ff709e98b
--- /dev/null
+++ b/source/blender/depsgraph/CMakeLists.txt
@@ -0,0 +1,122 @@
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# The Original Code is Copyright (C) 2014, Blender Foundation
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): Joshua Leung, Lukas Toenne
+#
+# ***** END GPL LICENSE BLOCK *****
+
+set(INC
+ .
+ intern
+ util
+ ../blenkernel
+ ../blenlib
+ ../bmesh
+ ../makesdna
+ ../makesrna
+ ../modifiers
+ ../windowmanager
+ ../../../intern/atomic
+ ../../../intern/guardedalloc
+)
+
+set(INC_SYS
+)
+
+set(SRC
+ intern/depsgraph.cc
+ intern/depsnode.cc
+ intern/depsnode_component.cc
+ intern/depsnode_operation.cc
+ intern/depsgraph_build.cc
+ intern/depsgraph_build_nodes.cc
+ intern/depsgraph_build_relations.cc
+ intern/depsgraph_debug.cc
+ intern/depsgraph_eval.cc
+ intern/depsgraph_query.cc
+ intern/depsgraph_queue.cc
+ intern/depsgraph_tag.cc
+ intern/depsgraph_type_defines.cc
+ util/depsgraph_util_cycle.cc
+ util/depsgraph_util_pchanmap.cc
+ util/depsgraph_util_transitive.cc
+
+ DEG_depsgraph.h
+ DEG_depsgraph_build.h
+ DEG_depsgraph_debug.h
+ DEG_depsgraph_query.h
+ intern/depsgraph.h
+ intern/depsnode.h
+ intern/depsnode_component.h
+ intern/depsnode_operation.h
+ intern/depsnode_opcodes.h
+ intern/depsgraph_build.h
+ intern/depsgraph_debug.h
+ intern/depsgraph_intern.h
+ intern/depsgraph_queue.h
+ intern/depsgraph_types.h
+
+ util/depsgraph_util_cycle.h
+ util/depsgraph_util_function.h
+ util/depsgraph_util_hash.h
+ util/depsgraph_util_map.h
+ util/depsgraph_util_pchanmap.h
+ util/depsgraph_util_set.h
+ util/depsgraph_util_transitive.h
+)
+
+TEST_UNORDERED_MAP_SUPPORT()
+if(HAVE_STD_UNORDERED_MAP_HEADER)
+ if(HAVE_UNORDERED_MAP_IN_STD_NAMESPACE)
+ add_definitions(-DDEG_STD_UNORDERED_MAP)
+ else()
+ if(HAVE_UNORDERED_MAP_IN_TR1_NAMESPACE)
+ add_definitions(-DDEG_STD_UNORDERED_MAP_IN_TR1_NAMESPACE)
+ else()
+ add_definitions(-DDEG_NO_UNORDERED_MAP)
+ message(STATUS "Replacing unordered_map/set with map/set (warning: slower!)")
+ endif()
+ endif()
+else()
+ if(HAVE_UNORDERED_MAP_IN_TR1_NAMESPACE)
+ add_definitions(-DDEG_TR1_UNORDERED_MAP)
+ else()
+ add_definitions(-DDEG_NO_UNORDERED_MAP)
+ message(STATUS "Replacing unordered_map/set with map/set (warning: slower!)")
+ endif()
+endif()
+
+if(WITH_LEGACY_DEPSGRAPH)
+ add_definitions(-DWITH_LEGACY_DEPSGRAPH)
+endif()
+
+if(WITH_BOOST)
+ list(APPEND INC_SYS
+ ${BOOST_INCLUDE_DIR}
+ )
+ add_definitions(-DHAVE_BOOST_FUNCTION_BINDINGS)
+endif()
+
+if(WITH_OPENSUBDIV)
+ add_definitions(-DWITH_OPENSUBDIV)
+endif()
+
+blender_add_lib(bf_depsgraph "${SRC}" "${INC}" "${INC_SYS}")
diff --git a/source/blender/depsgraph/DEG_depsgraph.h b/source/blender/depsgraph/DEG_depsgraph.h
new file mode 100644
index 00000000000..f37ba71ab65
--- /dev/null
+++ b/source/blender/depsgraph/DEG_depsgraph.h
@@ -0,0 +1,223 @@
+/*
+ * ***** 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.
+ *
+ * Original Author: Joshua Leung
+ * Contributor(s): None Yet
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/depsgraph/DEG_depsgraph.h
+ * \ingroup depsgraph
+ *
+ * Public API for Depsgraph
+ *
+ * Dependency Graph
+ * ================
+ *
+ * The dependency graph tracks relations between various pieces of data in
+ * a Blender file, but mainly just those which make up scene data. It is used
+ * to determine the set of operations need to ensure that all data has been
+ * correctly evaluated in response to changes, based on dependencies and visibility
+ * of affected data.
+ *
+ *
+ * Evaluation Engine
+ * =================
+ *
+ * The evaluation takes the operation-nodes the Depsgraph has tagged for updating,
+ * and schedules them up for being evaluated/executed such that the all dependency
+ * relationship constraints are satisfied.
+ */
+
+/* ************************************************* */
+/* Forward-defined typedefs for core types
+ * - These are used in all depsgraph code and by all callers of Depsgraph API...
+ */
+
+#ifndef __DEG_DEPSGRAPH_H__
+#define __DEG_DEPSGRAPH_H__
+
+/* Dependency Graph */
+typedef struct Depsgraph Depsgraph;
+
+/* ------------------------------------------------ */
+
+struct EvaluationContext;
+struct Main;
+
+struct PointerRNA;
+struct PropertyRNA;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+bool DEG_depsgraph_use_legacy(void);
+void DEG_depsgraph_switch_to_legacy(void);
+void DEG_depsgraph_switch_to_new(void);
+
+/* ************************************************ */
+/* Depsgraph API */
+
+/* CRUD ------------------------------------------- */
+
+// Get main depsgraph instance from context!
+
+/* Create new Depsgraph instance */
+// TODO: what args are needed here? What's the building-graph entry point?
+Depsgraph *DEG_graph_new(void);
+
+/* Free Depsgraph itself and all its data */
+void DEG_graph_free(Depsgraph *graph);
+
+/* Node Types Registry ---------------------------- */
+
+/* Register all node types */
+void DEG_register_node_types(void);
+
+/* Free node type registry on exit */
+void DEG_free_node_types(void);
+
+/* Update Tagging -------------------------------- */
+
+/* Tag node(s) associated with states such as time and visibility */
+void DEG_scene_update_flags(Depsgraph *graph, const bool do_time);
+
+/* Update dependency graph when visible scenes/layers changes. */
+void DEG_graph_on_visible_update(struct Main *bmain, struct Scene *scene);
+
+/* Update all dependency graphs when visible scenes/layers changes. */
+void DEG_on_visible_update(struct Main *bmain, const bool do_time);
+
+/* Tag node(s) associated with changed data for later updates */
+void DEG_graph_id_tag_update(struct Main *bmain,
+ Depsgraph *graph,
+ struct ID *id);
+void DEG_graph_data_tag_update(Depsgraph *graph, const struct PointerRNA *ptr);
+void DEG_graph_property_tag_update(Depsgraph *graph, const struct PointerRNA *ptr, const struct PropertyRNA *prop);
+
+/* Tag given ID for an update in all the dependency graphs. */
+void DEG_id_tag_update(struct ID *id, short flag);
+void DEG_id_tag_update_ex(struct Main *bmain,
+ struct ID *id,
+ short flag);
+
+/* Tag given ID type for update.
+ *
+ * Used by all sort of render engines to quickly check if
+ * IDs of a given type need to be checked for update.
+ */
+void DEG_id_type_tag(struct Main *bmain, short idtype);
+
+void DEG_ids_clear_recalc(struct Main *bmain);
+
+/* Update Flushing ------------------------------- */
+
+/* Flush updates */
+void DEG_graph_flush_updates(struct Main *bmain, Depsgraph *graph);
+
+/* Flush updates for all IDs */
+void DEG_ids_flush_tagged(struct Main *bmain);
+
+/* Check if something was changed in the database and inform
+ * editors about this.
+ */
+void DEG_ids_check_recalc(struct Main *bmain,
+ struct Scene *scene,
+ bool time);
+
+/* Clear all update tags
+ * - For aborted updates, or after successful evaluation
+ */
+void DEG_graph_clear_tags(Depsgraph *graph);
+
+/* ************************************************ */
+/* Evaluation Engine API */
+
+/* Evaluation Context ---------------------------- */
+
+/* Create new evaluation context. */
+struct EvaluationContext *DEG_evaluation_context_new(int mode);
+
+/* Initialize evaluation context.
+ * Used by the areas which currently overrides the context or doesn't have
+ * access to a proper one.
+ */
+void DEG_evaluation_context_init(struct EvaluationContext *eval_ctx, int mode);
+
+/* Free evaluation context. */
+void DEG_evaluation_context_free(struct EvaluationContext *eval_ctx);
+
+/* Graph Evaluation ----------------------------- */
+
+/* Frame changed recalculation entry point
+ * < context_type: context to perform evaluation for
+ * < ctime: (frame) new frame to evaluate values on
+ */
+void DEG_evaluate_on_framechange(struct EvaluationContext *eval_ctx,
+ struct Main *bmain,
+ Depsgraph *graph,
+ float ctime,
+ const int layer);
+
+/* Data changed recalculation entry point.
+ * < context_type: context to perform evaluation for
+ * < layers: visible layers bitmask to update the graph for
+ */
+void DEG_evaluate_on_refresh_ex(struct EvaluationContext *eval_ctx,
+ Depsgraph *graph,
+ const int layers);
+
+/* Data changed recalculation entry point.
+ * < context_type: context to perform evaluation for
+ */
+void DEG_evaluate_on_refresh(struct EvaluationContext *eval_ctx,
+ Depsgraph *graph,
+ struct Scene *scene);
+
+bool DEG_needs_eval(Depsgraph *graph);
+
+/* Editors Integration -------------------------- */
+
+/* Mechanism to allow editors to be informed of depsgraph updates,
+ * to do their own updates based on changes.
+ */
+
+typedef void (*DEG_EditorUpdateIDCb)(struct Main *bmain, struct ID *id);
+typedef void (*DEG_EditorUpdateSceneCb)(struct Main *bmain,
+ struct Scene *scene,
+ int updated);
+typedef void (*DEG_EditorUpdateScenePreCb)(struct Main *bmain,
+ struct Scene *scene,
+ bool time);
+
+/* Set callbacks which are being called when depsgraph changes. */
+void DEG_editors_set_update_cb(DEG_EditorUpdateIDCb id_func,
+ DEG_EditorUpdateSceneCb scene_func,
+ DEG_EditorUpdateScenePreCb scene_pre_func);
+
+void DEG_editors_update_pre(struct Main *bmain, struct Scene *scene, bool time);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* __DEG_DEPSGRAPH_H__ */
diff --git a/source/blender/depsgraph/DEG_depsgraph_build.h b/source/blender/depsgraph/DEG_depsgraph_build.h
new file mode 100644
index 00000000000..f680c47247a
--- /dev/null
+++ b/source/blender/depsgraph/DEG_depsgraph_build.h
@@ -0,0 +1,121 @@
+/*
+ * ***** 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.
+ *
+ * Original Author: Joshua Leung
+ * Contributor(s): Lukas Toenne
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/depsgraph/DEG_depsgraph_build.h
+ * \ingroup depsgraph
+ *
+ * Public API for Depsgraph
+ */
+
+#ifndef __DEG_DEPSGRAPH_BUILD_H__
+#define __DEG_DEPSGRAPH_BUILD_H__
+
+/* ************************************************* */
+
+/* Dependency Graph */
+struct Depsgraph;
+
+/* ------------------------------------------------ */
+
+struct Main;
+struct Scene;
+
+struct PointerRNA;
+struct PropertyRNA;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Graph Building -------------------------------- */
+
+/* Build depsgraph for the given scene, and dump results in given graph container */
+void DEG_graph_build_from_scene(struct Depsgraph *graph, struct Main *bmain, struct Scene *scene);
+
+/* Tag relations from the given graph for update. */
+void DEG_graph_tag_relations_update(struct Depsgraph *graph);
+
+/* Tag all relations in the database for update.*/
+void DEG_relations_tag_update(struct Main *bmain);
+
+/* Create new graph if didn't exist yet,
+ * or update relations if graph was tagged for update.
+ */
+void DEG_scene_relations_update(struct Main *bmain, struct Scene *scene);
+
+/* Rebuild dependency graph only for a given scene. */
+void DEG_scene_relations_rebuild(struct Main *bmain,
+ struct Scene *scene);
+
+/* Delete scene graph. */
+void DEG_scene_graph_free(struct Scene *scene);
+
+/* Add Dependencies ----------------------------- */
+
+/* Handle for components to define their dependencies from callbacks.
+ * This is generated by the depsgraph and passed to dependency callbacks
+ * as a symbolic reference to the current DepsNode.
+ * All relations will be defined in reference to that node.
+ */
+struct DepsNodeHandle;
+
+struct Object;
+
+typedef enum eDepsSceneComponentType {
+ DEG_SCENE_COMP_PARAMETERS, /* Parameters Component - Default when nothing else fits (i.e. just SDNA property setting) */
+ DEG_SCENE_COMP_ANIMATION, /* Animation Component */ // XXX: merge in with parameters?
+ DEG_SCENE_COMP_SEQUENCER, /* Sequencer Component (Scene Only) */
+} eDepsSceneComponentType;
+
+typedef enum eDepsObjectComponentType {
+ DEG_OB_COMP_PARAMETERS, /* Parameters Component - Default when nothing else fits (i.e. just SDNA property setting) */
+ DEG_OB_COMP_PROXY, /* Generic "Proxy-Inherit" Component */ // XXX: Also for instancing of subgraphs?
+ DEG_OB_COMP_ANIMATION, /* Animation Component */ // XXX: merge in with parameters?
+ DEG_OB_COMP_TRANSFORM, /* Transform Component (Parenting/Constraints) */
+ DEG_OB_COMP_GEOMETRY, /* Geometry Component (DerivedMesh/Displist) */
+
+ /* Evaluation-Related Outer Types (with Subdata) */
+ DEG_OB_COMP_EVAL_POSE, /* Pose Component - Owner/Container of Bones Eval */
+ DEG_OB_COMP_BONE, /* Bone Component - Child/Subcomponent of Pose */
+
+ DEG_OB_COMP_EVAL_PARTICLES, /* Particle Systems Component */
+ DEG_OB_COMP_SHADING, /* Material Shading Component */
+} eDepsObjectComponentType;
+
+void DEG_add_scene_relation(struct DepsNodeHandle *node, struct Scene *scene, eDepsSceneComponentType component, const char *description);
+void DEG_add_object_relation(struct DepsNodeHandle *node, struct Object *ob, eDepsObjectComponentType component, const char *description);
+void DEG_add_bone_relation(struct DepsNodeHandle *handle, struct Object *ob, const char *bone_name, eDepsObjectComponentType component, const char *description);
+
+/* TODO(sergey): Remove once all geometry update is granular. */
+void DEG_add_special_eval_flag(struct Depsgraph *graph, struct ID *id, short flag);
+
+/* ************************************************ */
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* __DEG_DEPSGRAPH_BUILD_H__ */
diff --git a/source/blender/depsgraph/DEG_depsgraph_debug.h b/source/blender/depsgraph/DEG_depsgraph_debug.h
new file mode 100644
index 00000000000..374fad63c34
--- /dev/null
+++ b/source/blender/depsgraph/DEG_depsgraph_debug.h
@@ -0,0 +1,111 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2014 Blender Foundation.
+ * All rights reserved.
+ *
+ * Original Author: Lukas Toenne
+ * Contributor(s): None Yet
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/depsgraph/DEG_depsgraph_debug.h
+ * \ingroup depsgraph
+ *
+ * Public API for Querying and Filtering Depsgraph
+ */
+
+#ifndef __DEG_DEPSGRAPH_DEBUG_H__
+#define __DEG_DEPSGRAPH_DEBUG_H__
+
+#include <stdio.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct DepsgraphSettings;
+struct GHash;
+struct ID;
+
+struct Depsgraph;
+struct DepsNode;
+struct DepsRelation;
+
+/* ************************************************ */
+/* Statistics */
+
+typedef struct DepsgraphStatsTimes {
+ float duration_last;
+} DepsgraphStatsTimes;
+
+typedef struct DepsgraphStatsComponent {
+ struct DepsgraphStatsComponent *next, *prev;
+
+ char name[64];
+ DepsgraphStatsTimes times;
+} DepsgraphStatsComponent;
+
+typedef struct DepsgraphStatsID {
+ struct ID *id;
+
+ DepsgraphStatsTimes times;
+ ListBase components;
+} DepsgraphStatsID;
+
+typedef struct DepsgraphStats {
+ struct GHash *id_stats;
+} DepsgraphStats;
+
+struct DepsgraphStats *DEG_stats(void);
+
+void DEG_stats_verify(void);
+
+struct DepsgraphStatsID *DEG_stats_id(struct ID *id);
+
+/* ------------------------------------------------ */
+
+void DEG_stats_simple(const struct Depsgraph *graph,
+ size_t *r_outer,
+ size_t *r_operations,
+ size_t *r_relations);
+
+/* ************************************************ */
+/* Diagram-Based Graph Debugging */
+
+void DEG_debug_graphviz(const struct Depsgraph *graph, FILE *stream, const char *label, bool show_eval);
+
+/* ************************************************ */
+
+/* Compare two dependency graphs. */
+bool DEG_debug_compare(const struct Depsgraph *graph1,
+ const struct Depsgraph *graph2);
+
+/* Check that dependnecies in the graph are really up to date. */
+bool DEG_debug_scene_relations_validate(struct Main *bmain,
+ struct Scene *scene);
+
+
+/* Perform consistency check on the graph. */
+bool DEG_debug_consistency_check(struct Depsgraph *graph);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* __DEG_DEPSGRAPH_DEBUG_H__ */
diff --git a/source/blender/depsgraph/DEG_depsgraph_query.h b/source/blender/depsgraph/DEG_depsgraph_query.h
new file mode 100644
index 00000000000..60d673d4c5b
--- /dev/null
+++ b/source/blender/depsgraph/DEG_depsgraph_query.h
@@ -0,0 +1,195 @@
+/*
+ * ***** 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.
+ *
+ * Original Author: Joshua Leung
+ * Contributor(s): None Yet
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/depsgraph/DEG_depsgraph_query.h
+ * \ingroup depsgraph
+ *
+ * Public API for Querying and Filtering Depsgraph.
+ */
+
+#ifndef __DEG_DEPSGRAPH_QUERY_H__
+#define __DEG_DEPSGRAPH_QUERY_H__
+
+struct ListBase;
+struct ID;
+
+struct Depsgraph;
+struct DepsNode;
+struct DepsRelation;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* ************************************************ */
+/* Type Defines */
+
+/* FilterPredicate Callback
+ *
+ * Defines a callback function which can be supplied to check whether a
+ * node is relevant or not.
+ *
+ * < graph: Depsgraph that we're traversing
+ * < node: The node to check
+ * < userdata: FilterPredicate state data (as needed)
+ * > returns: True if node is relevant
+ */
+typedef bool (*DEG_FilterPredicate)(const struct Depsgraph *graph, const struct DepsNode *node, void *userdata);
+
+
+/* Node Operation
+ *
+ * Performs some action on the given node, provided that the node was
+ * deemed to be relevant to operate on.
+ *
+ * < graph: Depsgraph that we're traversing
+ * < node: The node to perform operation on/with
+ * < userdata: Node Operation's state data (as needed)
+ * > returns: True if traversal should be aborted at this point
+ */
+typedef bool (*DEG_NodeOperation)(const struct Depsgraph *graph, struct DepsNode *node, void *userdata);
+
+/* ************************************************ */
+/* Low-Level Filtering API */
+
+/* Create a filtered copy of the given graph which contains only the
+ * nodes which fulfill the criteria specified using the FilterPredicate
+ * passed in.
+ *
+ * < graph: The graph to be copied and filtered
+ * < filter: FilterPredicate used to check which nodes should be included
+ * (If null, full graph is copied as-is)
+ * < userdata: State data for filter (as necessary)
+ *
+ * > returns: a full copy of all the relevant nodes - the matching subgraph
+ */
+// XXX: is there any need for extra settings/options for how the filtering goes?
+Depsgraph *DEG_graph_filter(const struct Depsgraph *graph, DEG_FilterPredicate *filter, void *userdata);
+
+
+/* Traverse nodes in graph which are deemed relevant,
+ * performing the provided operation on the nodes.
+ *
+ * < graph: The graph to perform operations on
+ * < filter: FilterPredicate used to check which nodes should be included
+ * (If null, all nodes are considered valid targets)
+ * < filter_data: Custom state data for FilterPredicate
+ * (Note: This can be the same as op_data, where appropriate)
+ * < op: NodeOperation to perform on each node
+ * (If null, no graph traversal is performed for efficiency)
+ * < op_data: Custom state data for NodeOperation
+ * (Note: This can be the same as filter_data, where appropriate)
+ */
+void DEG_graph_traverse(const struct Depsgraph *graph,
+ DEG_FilterPredicate *filter, void *filter_data,
+ DEG_NodeOperation *op, void *op_data);
+
+/* ************************************************ */
+/* Node-Based Operations */
+// XXX: do we want to be able to attach conditional requirements here?
+
+/* Find an (outer) node matching given conditions
+ * ! Assumes that there will only be one such node, or that only the first one matters
+ *
+ * < graph: a dependency graph which may or may not contain a node matching these requirements
+ * < query: query conditions for the criteria that the node must satisfy
+ */
+//DepsNode *DEG_node_find(const Depsgraph *graph, DEG_QueryConditions *query);
+
+/* Topology Queries (Direct) ---------------------- */
+
+/* Get list of nodes which directly depend on given node
+ *
+ * > result: list to write results to
+ * < node: the node to find the children/dependents of
+ */
+void DEG_node_get_children(struct ListBase *result, const struct DepsNode *node);
+
+
+/* Get list of nodes which given node directly depends on
+ *
+ * > result: list to write results to
+ * < node: the node to find the dependencies of
+ */
+void DEG_node_get_dependencies(struct ListBase *result, const struct DepsNode *node);
+
+
+/* Topology Queries (Subgraph) -------------------- */
+// XXX: given that subgraphs potentially involve many interconnected nodes, we currently
+// just spit out a copy of the subgraph which matches. This works well for the cases
+// where these are used - mostly for efficient updating of subsets of the nodes.
+
+// XXX: allow supplying a filter predicate to provide further filtering/pruning?
+
+
+/* Get all descendants of a node
+ *
+ * That is, get the subgraph / subset of nodes which are dependent
+ * on the results of the given node.
+ */
+Depsgraph *DEG_node_get_descendants(const struct Depsgraph *graph, const struct DepsNode *node);
+
+
+/* Get all ancestors of a node
+ *
+ * That is, get the subgraph / subset of nodes which the given node
+ * is dependent on in order to be evaluated.
+ */
+Depsgraph *DEG_node_get_ancestors(const struct Depsgraph *graph, const struct DepsNode *node);
+
+/* ************************************************ */
+/* Higher-Level Queries */
+
+/* Get ID-blocks which would be affected if specified ID is modified
+ * < only_direct: True = Only ID-blocks with direct relationships to ID-block will be returned
+ *
+ * > result: (LinkData : ID) a list of ID-blocks matching the specified criteria
+ * > returns: number of matching ID-blocks
+ */
+size_t DEG_query_affected_ids(struct ListBase *result, const struct ID *id, const bool only_direct);
+
+
+/* Get ID-blocks which are needed to update/evaluate specified ID
+ * < only_direct: True = Only ID-blocks with direct relationships to ID-block will be returned
+ *
+ * > result: (LinkData : ID) a list of ID-blocks matching the specified criteria
+ * > returns: number of matching ID-blocks
+ */
+size_t DEG_query_required_ids(struct ListBase *result, const struct ID *id, const bool only_direct);
+
+/* ************************************************ */
+
+/* Check if given ID type was tagged for update. */
+bool DEG_id_type_tagged(struct Main *bmain, short idtype);
+
+/* Get additional evaluation flags for the given ID. */
+short DEG_get_eval_flags_for_id(struct Depsgraph *graph, struct ID *id);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* __DEG_DEPSGRAPH_QUERY_H__ */
diff --git a/source/blender/depsgraph/SConscript b/source/blender/depsgraph/SConscript
new file mode 100644
index 00000000000..7f49e8f4643
--- /dev/null
+++ b/source/blender/depsgraph/SConscript
@@ -0,0 +1,77 @@
+#!/usr/bin/env python
+#
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# The Original Code is Copyright (C) 2013, Blender Foundation
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): Nathan Letwory, Joshua Leung.
+#
+# ***** END GPL LICENSE BLOCK *****
+
+Import('env')
+
+sources = env.Glob('intern/*.cc') + env.Glob('util/*.cc')
+
+incs = [
+ '.',
+ './intern',
+ './util',
+ '#/intern/atomic',
+ '#/intern/guardedalloc',
+ '../bmesh',
+ '../blenlib',
+ '../blenkernel',
+ '../makesdna',
+ '../makesrna',
+ '../modifiers',
+ '../windowmanager',
+ ]
+
+defs = []
+
+if env['WITH_BF_BOOST']:
+ incs.append(env['BF_BOOST_INC'])
+ defs.append('HAVE_BOOST_FUNCTION_BINDINGS')
+
+if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'linuxcross', 'win64-vc', 'win64-mingw'):
+ incs.append(env['BF_PTHREADS_INC'])
+
+
+if env['WITH_UNORDERED_MAP_SUPPORT']:
+ if env['UNORDERED_MAP_HEADER'] == 'unordered_map':
+ if env['UNORDERED_MAP_NAMESPACE'] == 'std':
+ defs.append('DEG_STD_UNORDERED_MAP')
+ elif env['UNORDERED_MAP_NAMESPACE'] == 'std::tr1':
+ defs.append('DEG_STD_UNORDERED_MAP_IN_TR1_NAMESPACE')
+ elif env['UNORDERED_MAP_NAMESPACE'] == 'std::tr1':
+ defs.append('DEG_TR1_UNORDERED_MAP')
+else:
+ print("-- Replacing unordered_map/set with map/set (warning: slower!)")
+ defs.append('DEG_NO_UNORDERED_MAP')
+
+if env['WITH_BF_LEGACY_DEPSGRAPH']:
+ defs.append('WITH_LEGACY_DEPSGRAPH')
+
+if env['WITH_BF_OPENSUBDIV']:
+ defs.append('WITH_OPENSUBDIV')
+
+env.BlenderLib(libname='bf_depsgraph', sources=sources,
+ includes=incs, defines=defs,
+ libtype=['core', 'player'], priority=[200, 40])
diff --git a/source/blender/depsgraph/intern/depsgraph.cc b/source/blender/depsgraph/intern/depsgraph.cc
new file mode 100644
index 00000000000..dedb6e322ba
--- /dev/null
+++ b/source/blender/depsgraph/intern/depsgraph.cc
@@ -0,0 +1,500 @@
+/*
+ * ***** 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.
+ *
+ * Original Author: Joshua Leung
+ * Contributor(s): Sergey Sharybin
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/depsgraph/intern/depsgraph.cc
+ * \ingroup depsgraph
+ *
+ * Core routines for how the Depsgraph works.
+ */
+
+#include <string.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_listbase.h"
+
+extern "C" {
+#include "DNA_action_types.h"
+#include "DNA_armature_types.h"
+#include "DNA_constraint_types.h"
+#include "DNA_key_types.h"
+#include "DNA_object_types.h"
+#include "DNA_sequence_types.h"
+
+#include "BKE_depsgraph.h"
+
+#include "RNA_access.h"
+}
+
+#include "DEG_depsgraph.h"
+#include "depsgraph.h" /* own include */
+#include "depsnode.h"
+#include "depsnode_operation.h"
+#include "depsnode_component.h"
+#include "depsgraph_intern.h"
+
+static DEG_EditorUpdateIDCb deg_editor_update_id_cb = NULL;
+static DEG_EditorUpdateSceneCb deg_editor_update_scene_cb = NULL;
+static DEG_EditorUpdateScenePreCb deg_editor_update_scene_pre_cb = NULL;
+
+Depsgraph::Depsgraph()
+ : root_node(NULL),
+ need_update(false),
+ layers(0)
+{
+ BLI_spin_init(&lock);
+}
+
+Depsgraph::~Depsgraph()
+{
+ /* Free root node - it won't have been freed yet... */
+ clear_id_nodes();
+ clear_subgraph_nodes();
+ if (this->root_node != NULL) {
+ OBJECT_GUARDED_DELETE(this->root_node, RootDepsNode);
+ }
+ BLI_spin_end(&lock);
+}
+
+/* Query Conditions from RNA ----------------------- */
+
+static bool pointer_to_id_node_criteria(const PointerRNA *ptr,
+ const PropertyRNA *prop,
+ ID **id)
+{
+ if (!ptr->type)
+ return false;
+
+ if (!prop) {
+ if (RNA_struct_is_ID(ptr->type)) {
+ *id = (ID *)ptr->data;
+ return true;
+ }
+ }
+
+ return false;
+}
+
+static bool pointer_to_component_node_criteria(const PointerRNA *ptr,
+ const PropertyRNA *prop,
+ ID **id,
+ eDepsNode_Type *type,
+ string *subdata)
+{
+ if (!ptr->type)
+ return false;
+
+ /* Set default values for returns. */
+ *id = (ID *)ptr->id.data; /* For obvious reasons... */
+ *subdata = ""; /* Default to no subdata (e.g. bone) name
+ * lookup in most cases. */
+
+ /* Handling of commonly known scenarios... */
+ if (ptr->type == &RNA_PoseBone) {
+ bPoseChannel *pchan = (bPoseChannel *)ptr->data;
+
+ /* Bone - generally, we just want the bone component... */
+ *type = DEPSNODE_TYPE_BONE;
+ *subdata = pchan->name;
+
+ return true;
+ }
+ else if (ptr->type == &RNA_Bone) {
+ Bone *bone = (Bone *)ptr->data;
+
+ /* armature-level bone, but it ends up going to bone component anyway */
+ // TODO: the ID in thise case will end up being bArmature, not Object as needed!
+ *type = DEPSNODE_TYPE_BONE;
+ *subdata = bone->name;
+ //*id = ...
+
+ return true;
+ }
+ else if (RNA_struct_is_a(ptr->type, &RNA_Constraint)) {
+ Object *ob = (Object *)ptr->id.data;
+ bConstraint *con = (bConstraint *)ptr->data;
+
+ /* object or bone? */
+ if (BLI_findindex(&ob->constraints, con) != -1) {
+ /* object transform */
+ // XXX: for now, we can't address the specific constraint or the constraint stack...
+ *type = DEPSNODE_TYPE_TRANSFORM;
+ return true;
+ }
+ else if (ob->pose) {
+ bPoseChannel *pchan;
+ for (pchan = (bPoseChannel *)ob->pose->chanbase.first; pchan; pchan = pchan->next) {
+ if (BLI_findindex(&pchan->constraints, con) != -1) {
+ /* bone transforms */
+ *type = DEPSNODE_TYPE_BONE;
+ *subdata = pchan->name;
+ return true;
+ }
+ }
+ }
+ }
+ else if (RNA_struct_is_a(ptr->type, &RNA_Modifier)) {
+ //ModifierData *md = (ModifierData *)ptr->data;
+
+ /* Modifier */
+ /* NOTE: subdata is not the same as "operation name",
+ * so although we have unique ops for modifiers,
+ * we can't lump them together
+ */
+ *type = DEPSNODE_TYPE_BONE;
+ //*subdata = md->name;
+
+ return true;
+ }
+ else if (ptr->type == &RNA_Object) {
+ //Object *ob = (Object *)ptr->data;
+
+ /* Transforms props? */
+ if (prop) {
+ const char *prop_identifier = RNA_property_identifier((PropertyRNA *)prop);
+
+ if (strstr(prop_identifier, "location") ||
+ strstr(prop_identifier, "rotation") ||
+ strstr(prop_identifier, "scale"))
+ {
+ *type = DEPSNODE_TYPE_TRANSFORM;
+ return true;
+ }
+ }
+ // ...
+ }
+ else if (ptr->type == &RNA_ShapeKey) {
+ Key *key = (Key *)ptr->id.data;
+
+ /* ShapeKeys are currently handled as geometry on the geometry that owns it */
+ *id = key->from; // XXX
+ *type = DEPSNODE_TYPE_PARAMETERS;
+
+ return true;
+ }
+ else if (RNA_struct_is_a(ptr->type, &RNA_Sequence)) {
+ Sequence *seq = (Sequence *)ptr->data;
+ /* Sequencer strip */
+ *type = DEPSNODE_TYPE_SEQUENCER;
+ *subdata = seq->name; // xxx?
+ return true;
+ }
+
+ if (prop) {
+ /* All unknown data effectively falls under "parameter evaluation" */
+ *type = DEPSNODE_TYPE_PARAMETERS;
+ return true;
+ }
+
+ return false;
+}
+
+/* Convenience wrapper to find node given just pointer + property. */
+DepsNode *Depsgraph::find_node_from_pointer(const PointerRNA *ptr,
+ const PropertyRNA *prop) const
+{
+ ID *id;
+ eDepsNode_Type type;
+ string name;
+
+ /* Get querying conditions. */
+ if (pointer_to_id_node_criteria(ptr, prop, &id)) {
+ return find_id_node(id);
+ }
+ else if (pointer_to_component_node_criteria(ptr, prop, &id, &type, &name)) {
+ IDDepsNode *id_node = find_id_node(id);
+ if (id_node)
+ return id_node->find_component(type, name);
+ }
+
+ return NULL;
+}
+
+/* Node Management ---------------------------- */
+
+RootDepsNode *Depsgraph::add_root_node()
+{
+ if (!root_node) {
+ DepsNodeFactory *factory = DEG_get_node_factory(DEPSNODE_TYPE_ROOT);
+ root_node = (RootDepsNode *)factory->create_node(NULL, "", "Root (Scene)");
+ }
+ return root_node;
+}
+
+TimeSourceDepsNode *Depsgraph::find_time_source(const ID *id) const
+{
+ /* Search for one attached to a particular ID? */
+ if (id) {
+ /* Check if it was added as a component
+ * (as may be done for subgraphs needing timeoffset).
+ */
+ IDDepsNode *id_node = find_id_node(id);
+ if (id_node) {
+ // XXX: review this
+// return id_node->find_component(DEPSNODE_TYPE_TIMESOURCE);
+ }
+ BLI_assert(!"Not implemented yet");
+ }
+ else {
+ /* Use "official" timesource. */
+ return root_node->time_source;
+ }
+ return NULL;
+}
+
+SubgraphDepsNode *Depsgraph::add_subgraph_node(const ID *id)
+{
+ DepsNodeFactory *factory = DEG_get_node_factory(DEPSNODE_TYPE_SUBGRAPH);
+ SubgraphDepsNode *subgraph_node =
+ (SubgraphDepsNode *)factory->create_node(id, "", id->name + 2);
+
+ /* Add to subnodes list. */
+ this->subgraphs.insert(subgraph_node);
+
+ /* if there's an ID associated, add to ID-nodes lookup too */
+ if (id) {
+#if 0
+ /* XXX subgraph node is NOT a true IDDepsNode - what is this supposed to do? */
+ // TODO: what to do if subgraph's ID has already been added?
+ BLI_assert(!graph->find_id_node(id));
+ graph->id_hash[id] = this;
+#endif
+ }
+
+ return subgraph_node;
+}
+
+void Depsgraph::remove_subgraph_node(SubgraphDepsNode *subgraph_node)
+{
+ subgraphs.erase(subgraph_node);
+ OBJECT_GUARDED_DELETE(subgraph_node, SubgraphDepsNode);
+}
+
+void Depsgraph::clear_subgraph_nodes()
+{
+ for (Subgraphs::iterator it = subgraphs.begin();
+ it != subgraphs.end();
+ ++it)
+ {
+ SubgraphDepsNode *subgraph_node = *it;
+ OBJECT_GUARDED_DELETE(subgraph_node, SubgraphDepsNode);
+ }
+ subgraphs.clear();
+}
+
+IDDepsNode *Depsgraph::find_id_node(const ID *id) const
+{
+ IDNodeMap::const_iterator it = this->id_hash.find(id);
+ return it != this->id_hash.end() ? it->second : NULL;
+}
+
+IDDepsNode *Depsgraph::add_id_node(ID *id, const string &name)
+{
+ IDDepsNode *id_node = find_id_node(id);
+ if (!id_node) {
+ DepsNodeFactory *factory = DEG_get_node_factory(DEPSNODE_TYPE_ID_REF);
+ id_node = (IDDepsNode *)factory->create_node(id, "", name);
+ id->flag |= LIB_DOIT;
+ /* register */
+ this->id_hash[id] = id_node;
+ }
+ return id_node;
+}
+
+void Depsgraph::remove_id_node(const ID *id)
+{
+ IDDepsNode *id_node = find_id_node(id);
+ if (id_node) {
+ /* unregister */
+ this->id_hash.erase(id);
+ OBJECT_GUARDED_DELETE(id_node, IDDepsNode);
+ }
+}
+
+void Depsgraph::clear_id_nodes()
+{
+ for (IDNodeMap::const_iterator it = id_hash.begin();
+ it != id_hash.end();
+ ++it)
+ {
+ IDDepsNode *id_node = it->second;
+ OBJECT_GUARDED_DELETE(id_node, IDDepsNode);
+ }
+ id_hash.clear();
+}
+
+/* Add new relationship between two nodes. */
+DepsRelation *Depsgraph::add_new_relation(OperationDepsNode *from,
+ OperationDepsNode *to,
+ eDepsRelation_Type type,
+ const char *description)
+{
+ /* Create new relation, and add it to the graph. */
+ DepsRelation *rel = OBJECT_GUARDED_NEW(DepsRelation, from, to, type, description);
+ /* TODO(sergey): Find a better place for this. */
+#ifdef WITH_OPENSUBDIV
+ ComponentDepsNode *comp_node = from->owner;
+ if (comp_node->type == DEPSNODE_TYPE_GEOMETRY) {
+ IDDepsNode *id_to = to->owner->owner;
+ IDDepsNode *id_from = from->owner->owner;
+ Object *object_to = (Object *)id_to->id;
+ if (id_to != id_from && (object_to->recalc & OB_RECALC_ALL)) {
+ if ((id_from->eval_flags & DAG_EVAL_NEED_CPU) == 0) {
+ id_from->tag_update(this);
+ id_from->eval_flags |= DAG_EVAL_NEED_CPU;
+ }
+ }
+ }
+#endif
+ return rel;
+}
+
+/* Add new relation between two nodes */
+DepsRelation *Depsgraph::add_new_relation(DepsNode *from, DepsNode *to,
+ eDepsRelation_Type type,
+ const char *description)
+{
+ /* Create new relation, and add it to the graph. */
+ DepsRelation *rel = OBJECT_GUARDED_NEW(DepsRelation, from, to, type, description);
+ return rel;
+}
+
+/* ************************ */
+/* Relationships Management */
+
+DepsRelation::DepsRelation(DepsNode *from,
+ DepsNode *to,
+ eDepsRelation_Type type,
+ const char *description)
+ : from(from),
+ to(to),
+ name(description),
+ type(type),
+ flag(0)
+{
+#ifndef NDEBUG
+/*
+ for (OperationDepsNode::Relations::const_iterator it = from->outlinks.begin();
+ it != from->outlinks.end();
+ ++it)
+ {
+ DepsRelation *rel = *it;
+ if (rel->from == from &&
+ rel->to == to &&
+ rel->type == type &&
+ rel->name == description)
+ {
+ BLI_assert(!"Duplicated relation, should not happen!");
+ }
+ }
+*/
+#endif
+
+ /* Hook it up to the nodes which use it. */
+ from->outlinks.insert(this);
+ to->inlinks.insert(this);
+}
+
+DepsRelation::~DepsRelation()
+{
+ /* Sanity check. */
+ BLI_assert(this->from && this->to);
+ /* Remove it from the nodes that use it. */
+ this->from->outlinks.erase(this);
+ this->to->inlinks.erase(this);
+}
+
+/* Low level tagging -------------------------------------- */
+
+/* Tag a specific node as needing updates. */
+void Depsgraph::add_entry_tag(OperationDepsNode *node)
+{
+ /* Sanity check. */
+ if (!node)
+ return;
+
+ /* Add to graph-level set of directly modified nodes to start searching from.
+ * NOTE: this is necessary since we have several thousand nodes to play with...
+ */
+ this->entry_tags.insert(node);
+}
+
+void Depsgraph::clear_all_nodes()
+{
+ clear_id_nodes();
+ clear_subgraph_nodes();
+ id_hash.clear();
+ if (this->root_node) {
+ OBJECT_GUARDED_DELETE(this->root_node, RootDepsNode);
+ root_node = NULL;
+ }
+}
+
+/* **************** */
+/* Public Graph API */
+
+/* Initialize a new Depsgraph */
+Depsgraph *DEG_graph_new()
+{
+ return OBJECT_GUARDED_NEW(Depsgraph);
+}
+
+/* Free graph's contents and graph itself */
+void DEG_graph_free(Depsgraph *graph)
+{
+ OBJECT_GUARDED_DELETE(graph, Depsgraph);
+}
+
+/* Set callbacks which are being called when depsgraph changes. */
+void DEG_editors_set_update_cb(DEG_EditorUpdateIDCb id_func,
+ DEG_EditorUpdateSceneCb scene_func,
+ DEG_EditorUpdateScenePreCb scene_pre_func)
+{
+ deg_editor_update_id_cb = id_func;
+ deg_editor_update_scene_cb = scene_func;
+ deg_editor_update_scene_pre_cb = scene_pre_func;
+}
+
+void DEG_editors_update_pre(Main *bmain, Scene *scene, bool time)
+{
+ if (deg_editor_update_scene_pre_cb != NULL) {
+ deg_editor_update_scene_pre_cb(bmain, scene, time);
+ }
+}
+
+void deg_editors_id_update(Main *bmain, ID *id)
+{
+ if (deg_editor_update_id_cb != NULL) {
+ deg_editor_update_id_cb(bmain, id);
+ }
+}
+
+void deg_editors_scene_update(Main *bmain, Scene *scene, bool updated)
+{
+ if (deg_editor_update_scene_cb != NULL) {
+ deg_editor_update_scene_cb(bmain, scene, updated);
+ }
+}
diff --git a/source/blender/depsgraph/intern/depsgraph.h b/source/blender/depsgraph/intern/depsgraph.h
new file mode 100644
index 00000000000..9533fbd10d5
--- /dev/null
+++ b/source/blender/depsgraph/intern/depsgraph.h
@@ -0,0 +1,224 @@
+/*
+ * ***** 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.
+ *
+ * Original Author: Joshua Leung
+ * Contributor(s): Sergey Sharybin
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/depsgraph/intern/depsgraph.h
+ * \ingroup depsgraph
+ *
+ * Datatypes for internal use in the Depsgraph
+ *
+ * All of these datatypes are only really used within the "core" depsgraph.
+ * In particular, node types declared here form the structure of operations
+ * in the graph.
+ */
+
+#ifndef __DEPSGRAPH_H__
+#define __DEPSGRAPH_H__
+
+#include "BLI_threads.h" /* for SpinLock */
+
+#include "depsgraph_types.h"
+
+#include "depsgraph_util_map.h"
+#include "depsgraph_util_set.h"
+
+struct PointerRNA;
+struct PropertyRNA;
+
+struct DepsNode;
+struct RootDepsNode;
+struct TimeSourceDepsNode;
+struct IDDepsNode;
+struct SubgraphDepsNode;
+struct ComponentDepsNode;
+struct OperationDepsNode;
+
+/* *************************** */
+/* Relationships Between Nodes */
+
+/* Settings/Tags on Relationship */
+typedef enum eDepsRelation_Flag {
+ /* "touched" tag is used when filtering, to know which to collect */
+ DEPSREL_FLAG_TEMP_TAG = (1 << 0),
+
+ /* "cyclic" link - when detecting cycles, this relationship was the one
+ * which triggers a cyclic relationship to exist in the graph
+ */
+ DEPSREL_FLAG_CYCLIC = (1 << 1),
+} eDepsRelation_Flag;
+
+/* B depends on A (A -> B) */
+struct DepsRelation {
+ /* the nodes in the relationship (since this is shared between the nodes) */
+ DepsNode *from; /* A */
+ DepsNode *to; /* B */
+
+ /* relationship attributes */
+ const char *name; /* label for debugging */
+
+ eDepsRelation_Type type; /* type */
+ int flag; /* (eDepsRelation_Flag) */
+
+ DepsRelation(DepsNode *from,
+ DepsNode *to,
+ eDepsRelation_Type type,
+ const char *description);
+
+ ~DepsRelation();
+};
+
+/* ********* */
+/* Depsgraph */
+
+/* Dependency Graph object */
+struct Depsgraph {
+ typedef unordered_map<const ID *, IDDepsNode *> IDNodeMap;
+ typedef unordered_set<SubgraphDepsNode *> Subgraphs;
+ typedef unordered_set<OperationDepsNode *> EntryTags;
+ typedef vector<OperationDepsNode *> OperationNodes;
+
+ Depsgraph();
+ ~Depsgraph();
+
+ /**
+ * Find node which matches the specified description.
+ *
+ * \param id: ID block that is associated with this
+ * \param subdata: identifier used for sub-ID data (e.g. bone)
+ * \param type: type of node we're dealing with
+ * \param name: custom identifier assigned to node
+ *
+ * \return A node matching the required characteristics if it exists
+ * or NULL if no such node exists in the graph.
+ */
+ DepsNode *find_node(const ID *id,
+ eDepsNode_Type type,
+ const string &subdata,
+ const string &name);
+
+ /**
+ * Convenience wrapper to find node given just pointer + property.
+ *
+ * \param ptr: pointer to the data that node will represent
+ * \param prop: optional property affected - providing this effectively results in inner nodes being returned
+ *
+ * \return A node matching the required characteristics if it exists
+ * or NULL if no such node exists in the graph
+ */
+ DepsNode *find_node_from_pointer(const PointerRNA *ptr, const PropertyRNA *prop) const;
+
+ RootDepsNode *add_root_node();
+
+ TimeSourceDepsNode *find_time_source(const ID *id = NULL) const;
+
+ SubgraphDepsNode *add_subgraph_node(const ID *id);
+ void remove_subgraph_node(SubgraphDepsNode *subgraph_node);
+ void clear_subgraph_nodes();
+
+ IDDepsNode *find_id_node(const ID *id) const;
+ IDDepsNode *add_id_node(ID *id, const string &name = "");
+ void remove_id_node(const ID *id);
+ void clear_id_nodes();
+
+ /* Add new relationship between two nodes. */
+ DepsRelation *add_new_relation(OperationDepsNode *from,
+ OperationDepsNode *to,
+ eDepsRelation_Type type,
+ const char *description);
+
+ DepsRelation *add_new_relation(DepsNode *from,
+ DepsNode *to,
+ eDepsRelation_Type type,
+ const char *description);
+
+ /* Tag a specific node as needing updates. */
+ void add_entry_tag(OperationDepsNode *node);
+
+ /* Clear storage used by all nodes. */
+ void clear_all_nodes();
+
+ /* Core Graph Functionality ........... */
+
+ /* <ID : IDDepsNode> mapping from ID blocks to nodes representing these blocks
+ * (for quick lookups). */
+ IDNodeMap id_hash;
+
+ /* "root" node - the one where all evaluation enters from. */
+ RootDepsNode *root_node;
+
+ /* Subgraphs referenced in tree. */
+ Subgraphs subgraphs;
+
+ /* Indicates whether relations needs to be updated. */
+ bool need_update;
+
+ /* Quick-Access Temp Data ............. */
+
+ /* Nodes which have been tagged as "directly modified". */
+ EntryTags entry_tags;
+
+ /* Convenience Data ................... */
+
+ /* XXX: should be collected after building (if actually needed?) */
+ /* All operation nodes, sorted in order of single-thread traversal order. */
+ OperationNodes operations;
+
+ /* Spin lock for threading-critical operations.
+ * Mainly used by graph evaluation.
+ */
+ SpinLock lock;
+
+ /* Layers Visibility .................. */
+
+ /* Visible layers bitfield, used for skipping invisible objects updates. */
+ int layers;
+
+ // XXX: additional stuff like eval contexts, mempools for allocating nodes from, etc.
+};
+
+/**
+ * Helper macros for iterating over set of relationship links
+ * incident on each node.
+ *
+ * \note it is safe to perform removal operations here...
+ *
+ * relations_set[in]: (DepsNode::Relations) set of relationships (in/out links)
+ * relation[out]: (DepsRelation *) identifier where DepsRelation that we're
+ * currently accessing comes up
+ */
+#define DEPSNODE_RELATIONS_ITER_BEGIN(relations_set_, relation_) \
+ { \
+ OperationDepsNode::Relations::const_iterator __rel_iter = relations_set_.begin(); \
+ while (__rel_iter != relations_set_.end()) { \
+ DepsRelation *relation_ = *__rel_iter; \
+ ++__rel_iter; \
+
+ /* ... code for iterator body can be written here ... */
+
+#define DEPSNODE_RELATIONS_ITER_END \
+ } \
+ } ((void)0)
+
+#endif /* __DEPSGRAPH_H__ */
diff --git a/source/blender/depsgraph/intern/depsgraph_build.cc b/source/blender/depsgraph/intern/depsgraph_build.cc
new file mode 100644
index 00000000000..7a2ee2c416a
--- /dev/null
+++ b/source/blender/depsgraph/intern/depsgraph_build.cc
@@ -0,0 +1,370 @@
+/*
+ * ***** 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.
+ *
+ * Original Author: Joshua Leung
+ * Contributor(s): Based on original depsgraph.c code - Blender Foundation (2005-2013)
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/depsgraph/intern/depsgraph_build.cc
+ * \ingroup depsgraph
+ *
+ * Methods for constructing depsgraph.
+ */
+
+#include <stack>
+
+#include "MEM_guardedalloc.h"
+
+extern "C" {
+#include "BLI_blenlib.h"
+#include "BLI_string.h"
+#include "BLI_utildefines.h"
+
+#include "DNA_action_types.h"
+#include "DNA_anim_types.h"
+#include "DNA_armature_types.h"
+#include "DNA_camera_types.h"
+#include "DNA_constraint_types.h"
+#include "DNA_curve_types.h"
+#include "DNA_effect_types.h"
+#include "DNA_group_types.h"
+#include "DNA_key_types.h"
+#include "DNA_lamp_types.h"
+#include "DNA_material_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_meta_types.h"
+#include "DNA_node_types.h"
+#include "DNA_particle_types.h"
+#include "DNA_object_types.h"
+#include "DNA_rigidbody_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_texture_types.h"
+#include "DNA_world_types.h"
+
+#include "BKE_action.h"
+#include "BKE_armature.h"
+#include "BKE_animsys.h"
+#include "BKE_constraint.h"
+#include "BKE_curve.h"
+#include "BKE_effect.h"
+#include "BKE_fcurve.h"
+#include "BKE_group.h"
+#include "BKE_key.h"
+#include "BKE_library.h"
+#include "BKE_main.h"
+#include "BKE_material.h"
+#include "BKE_mball.h"
+#include "BKE_modifier.h"
+#include "BKE_node.h"
+#include "BKE_object.h"
+#include "BKE_particle.h"
+#include "BKE_rigidbody.h"
+#include "BKE_sound.h"
+#include "BKE_texture.h"
+#include "BKE_tracking.h"
+#include "BKE_world.h"
+
+#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_debug.h"
+#include "DEG_depsgraph_build.h"
+
+#include "RNA_access.h"
+#include "RNA_types.h"
+} /* extern "C" */
+
+#include "depsnode.h"
+#include "depsnode_component.h"
+#include "depsgraph_debug.h"
+#include "depsnode_operation.h"
+#include "depsgraph_types.h"
+#include "depsgraph_build.h"
+#include "depsgraph_intern.h"
+
+#include "depsgraph_util_cycle.h"
+#include "depsgraph_util_transitive.h"
+
+/* ****************** */
+/* External Build API */
+
+static eDepsNode_Type deg_build_scene_component_type(eDepsSceneComponentType component)
+{
+ switch (component) {
+ case DEG_SCENE_COMP_PARAMETERS: return DEPSNODE_TYPE_PARAMETERS;
+ case DEG_SCENE_COMP_ANIMATION: return DEPSNODE_TYPE_ANIMATION;
+ case DEG_SCENE_COMP_SEQUENCER: return DEPSNODE_TYPE_SEQUENCER;
+ }
+ return DEPSNODE_TYPE_UNDEFINED;
+}
+
+static eDepsNode_Type deg_build_object_component_type(eDepsObjectComponentType component)
+{
+ switch (component) {
+ case DEG_OB_COMP_PARAMETERS: return DEPSNODE_TYPE_PARAMETERS;
+ case DEG_OB_COMP_PROXY: return DEPSNODE_TYPE_PROXY;
+ case DEG_OB_COMP_ANIMATION: return DEPSNODE_TYPE_ANIMATION;
+ case DEG_OB_COMP_TRANSFORM: return DEPSNODE_TYPE_TRANSFORM;
+ case DEG_OB_COMP_GEOMETRY: return DEPSNODE_TYPE_GEOMETRY;
+ case DEG_OB_COMP_EVAL_POSE: return DEPSNODE_TYPE_EVAL_POSE;
+ case DEG_OB_COMP_BONE: return DEPSNODE_TYPE_BONE;
+ case DEG_OB_COMP_EVAL_PARTICLES: return DEPSNODE_TYPE_EVAL_PARTICLES;
+ case DEG_OB_COMP_SHADING: return DEPSNODE_TYPE_SHADING;
+ }
+ return DEPSNODE_TYPE_UNDEFINED;
+}
+
+void DEG_add_scene_relation(DepsNodeHandle *handle, struct Scene *scene, eDepsSceneComponentType component, const char *description)
+{
+ eDepsNode_Type type = deg_build_scene_component_type(component);
+ ComponentKey comp_key(&scene->id, type);
+ handle->builder->add_node_handle_relation(comp_key, handle, DEPSREL_TYPE_GEOMETRY_EVAL, description);
+}
+
+void DEG_add_object_relation(DepsNodeHandle *handle, struct Object *ob, eDepsObjectComponentType component, const char *description)
+{
+ eDepsNode_Type type = deg_build_object_component_type(component);
+ ComponentKey comp_key(&ob->id, type);
+ handle->builder->add_node_handle_relation(comp_key, handle, DEPSREL_TYPE_GEOMETRY_EVAL, description);
+}
+
+void DEG_add_bone_relation(DepsNodeHandle *handle, struct Object *ob, const char *bone_name, eDepsObjectComponentType component, const char *description)
+{
+ eDepsNode_Type type = deg_build_object_component_type(component);
+ ComponentKey comp_key(&ob->id, type, bone_name);
+
+ // XXX: "Geometry Eval" might not always be true, but this only gets called from modifier building now
+ handle->builder->add_node_handle_relation(comp_key, handle, DEPSREL_TYPE_GEOMETRY_EVAL, description);
+}
+
+void DEG_add_special_eval_flag(Depsgraph *graph, ID *id, short flag)
+{
+ if (graph == NULL) {
+ BLI_assert(!"Graph should always be valid");
+ return;
+ }
+ IDDepsNode *id_node = graph->find_id_node(id);
+ if (id_node == NULL) {
+ BLI_assert(!"ID should always be valid");
+ return;
+ }
+ id_node->eval_flags |= flag;
+}
+
+/* ********************** */
+/* Utilities for Builders */
+
+/* Get unique identifier for FCurves and Drivers */
+string deg_fcurve_id_name(const FCurve *fcu)
+{
+ char index_buf[32];
+ sprintf(index_buf, "[%d]", fcu->array_index);
+
+ return string(fcu->rna_path) + index_buf;
+}
+
+static void deg_graph_build_finalize(Depsgraph *graph)
+{
+ std::stack<OperationDepsNode *> stack;
+
+ for (Depsgraph::OperationNodes::const_iterator it_op = graph->operations.begin();
+ it_op != graph->operations.end();
+ ++it_op)
+ {
+ OperationDepsNode *node = *it_op;
+ node->done = 0;
+ node->num_links_pending = 0;
+ for (OperationDepsNode::Relations::const_iterator it_rel = node->inlinks.begin();
+ it_rel != node->inlinks.end();
+ ++it_rel)
+ {
+ DepsRelation *rel = *it_rel;
+ if ((rel->from->type == DEPSNODE_TYPE_OPERATION) &&
+ (rel->flag & DEPSREL_FLAG_CYCLIC) == 0)
+ {
+ ++node->num_links_pending;
+ }
+ }
+ if (node->num_links_pending == 0) {
+ stack.push(node);
+ }
+ IDDepsNode *id_node = node->owner->owner;
+ id_node->id->flag |= LIB_DOIT;
+ }
+
+ while (!stack.empty()) {
+ OperationDepsNode *node = stack.top();
+ if (node->done == 0 && node->outlinks.size() != 0) {
+ for (OperationDepsNode::Relations::const_iterator it_rel = node->outlinks.begin();
+ it_rel != node->outlinks.end();
+ ++it_rel)
+ {
+ DepsRelation *rel = *it_rel;
+ if (rel->to->type == DEPSNODE_TYPE_OPERATION) {
+ OperationDepsNode *to = (OperationDepsNode *)rel->to;
+ if ((rel->flag & DEPSREL_FLAG_CYCLIC) == 0) {
+ BLI_assert(to->num_links_pending > 0);
+ --to->num_links_pending;
+ }
+ if (to->num_links_pending == 0) {
+ stack.push(to);
+ }
+ }
+ }
+ node->done = 1;
+ }
+ else {
+ stack.pop();
+ IDDepsNode *id_node = node->owner->owner;
+ for (OperationDepsNode::Relations::const_iterator it_rel = node->outlinks.begin();
+ it_rel != node->outlinks.end();
+ ++it_rel)
+ {
+ DepsRelation *rel = *it_rel;
+ if (rel->to->type == DEPSNODE_TYPE_OPERATION) {
+ OperationDepsNode *to = (OperationDepsNode *)rel->to;
+ IDDepsNode *id_to = to->owner->owner;
+ id_node->layers |= id_to->layers;
+ }
+ }
+
+ /* Re-tag ID for update if it was tagged before the relations
+ * update tag.
+ */
+ ID *id = id_node->id;
+ if (id->flag & LIB_ID_RECALC_ALL &&
+ id->flag & LIB_DOIT)
+ {
+ id_node->tag_update(graph);
+ id->flag &= ~LIB_DOIT;
+ }
+ }
+ }
+}
+
+/* ******************** */
+/* Graph Building API's */
+
+/* Build depsgraph for the given scene, and dump results in given graph container */
+// XXX: assume that this is called from outside, given the current scene as the "main" scene
+void DEG_graph_build_from_scene(Depsgraph *graph, Main *bmain, Scene *scene)
+{
+ /* 1) Generate all the nodes in the graph first */
+ DepsgraphNodeBuilder node_builder(bmain, graph);
+ /* create root node for scene first
+ * - this way it should be the first in the graph,
+ * reflecting its role as the entrypoint
+ */
+ node_builder.add_root_node();
+ node_builder.build_scene(bmain, scene);
+
+ /* 2) Hook up relationships between operations - to determine evaluation order */
+ DepsgraphRelationBuilder relation_builder(graph);
+ /* hook scene up to the root node as entrypoint to graph */
+ /* XXX what does this relation actually mean?
+ * it doesnt add any operations anyway and is not clear what part of the scene is to be connected.
+ */
+ //relation_builder.add_relation(RootKey(), IDKey(scene), DEPSREL_TYPE_ROOT_TO_ACTIVE, "Root to Active Scene");
+ relation_builder.build_scene(bmain, scene);
+
+ /* Detect and solve cycles. */
+ deg_graph_detect_cycles(graph);
+
+ /* 3) Simplify the graph by removing redundant relations (to optimise traversal later) */
+ // TODO: it would be useful to have an option to disable this in cases where it is causing trouble
+ if (G.debug_value == 799) {
+ deg_graph_transitive_reduction(graph);
+ }
+
+ /* 4) Flush visibility layer and re-schedule nodes for update. */
+ deg_graph_build_finalize(graph);
+
+#if 0
+ if (!DEG_debug_consistency_check(graph)) {
+ printf("Consistency validation failed, ABORTING!\n");
+ abort();
+ }
+#endif
+}
+
+/* Tag graph relations for update. */
+void DEG_graph_tag_relations_update(Depsgraph *graph)
+{
+ graph->need_update = true;
+}
+
+/* Tag all relations for update. */
+void DEG_relations_tag_update(Main *bmain)
+{
+ for (Scene *scene = (Scene *)bmain->scene.first;
+ scene != NULL;
+ scene = (Scene *)scene->id.next)
+ {
+ if (scene->depsgraph != NULL) {
+ DEG_graph_tag_relations_update(scene->depsgraph);
+ }
+ }
+}
+
+/* Create new graph if didn't exist yet,
+ * or update relations if graph was tagged for update.
+ */
+void DEG_scene_relations_update(Main *bmain, Scene *scene)
+{
+ if (scene->depsgraph == NULL) {
+ /* Rebuild graph from scratch and exit. */
+ scene->depsgraph = DEG_graph_new();
+ DEG_graph_build_from_scene(scene->depsgraph, bmain, scene);
+ return;
+ }
+
+ Depsgraph *graph = scene->depsgraph;
+ if (!graph->need_update) {
+ /* Graph is up to date, nothing to do. */
+ return;
+ }
+
+ /* Clear all previous nodes and operations. */
+ graph->clear_all_nodes();
+ graph->operations.clear();
+ graph->entry_tags.clear();
+
+ /* Build new nodes and relations. */
+ DEG_graph_build_from_scene(graph, bmain, scene);
+
+ graph->need_update = false;
+}
+
+/* Rebuild dependency graph only for a given scene. */
+void DEG_scene_relations_rebuild(Main *bmain, Scene *scene)
+{
+ if (scene->depsgraph != NULL) {
+ DEG_graph_tag_relations_update(scene->depsgraph);
+ }
+ DEG_scene_relations_update(bmain, scene);
+}
+
+void DEG_scene_graph_free(Scene *scene)
+{
+ if (scene->depsgraph) {
+ DEG_graph_free(scene->depsgraph);
+ scene->depsgraph = NULL;
+ }
+}
diff --git a/source/blender/depsgraph/intern/depsgraph_build.h b/source/blender/depsgraph/intern/depsgraph_build.h
new file mode 100644
index 00000000000..c5b04ec299c
--- /dev/null
+++ b/source/blender/depsgraph/intern/depsgraph_build.h
@@ -0,0 +1,408 @@
+/*
+ * ***** 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.
+ *
+ * Original Author: Lukas Toenne
+ * Contributor(s): None Yet
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/depsgraph/intern/depsgraph_build.h
+ * \ingroup depsgraph
+ */
+
+#ifndef __DEPSGRAPH_BUILD_H__
+#define __DEPSGRAPH_BUILD_H__
+
+struct Base;
+struct bGPdata;
+struct ListBase;
+struct GHash;
+struct ID;
+struct FCurve;
+struct Group;
+struct Key;
+struct Main;
+struct Material;
+struct MTex;
+struct bNodeTree;
+struct Object;
+struct bPoseChannel;
+struct bConstraint;
+struct Scene;
+struct Tex;
+struct World;
+
+struct PropertyRNA;
+
+struct Depsgraph;
+struct DepsNode;
+struct DepsNodeHandle;
+struct RootDepsNode;
+struct SubgraphDepsNode;
+struct IDDepsNode;
+struct TimeSourceDepsNode;
+struct ComponentDepsNode;
+struct OperationDepsNode;
+struct RootPChanMap;
+
+struct DepsgraphNodeBuilder {
+ DepsgraphNodeBuilder(Main *bmain, Depsgraph *graph);
+ ~DepsgraphNodeBuilder();
+
+ RootDepsNode *add_root_node();
+ IDDepsNode *add_id_node(ID *id);
+ TimeSourceDepsNode *add_time_source(ID *id);
+
+ ComponentDepsNode *add_component_node(ID *id, eDepsNode_Type comp_type, const string &comp_name = "");
+
+ OperationDepsNode *add_operation_node(ComponentDepsNode *comp_node, eDepsOperation_Type optype,
+ DepsEvalOperationCb op, eDepsOperation_Code opcode, const string &description = "");
+ OperationDepsNode *add_operation_node(ID *id, eDepsNode_Type comp_type, const string &comp_name, eDepsOperation_Type optype,
+ DepsEvalOperationCb op, eDepsOperation_Code opcode, const string &description = "");
+ OperationDepsNode *add_operation_node(ID *id, eDepsNode_Type comp_type, eDepsOperation_Type optype,
+ DepsEvalOperationCb op, eDepsOperation_Code opcode, const string &description = "")
+ {
+ return add_operation_node(id, comp_type, "", optype, op, opcode, description);
+ }
+
+ bool has_operation_node(ID *id, eDepsNode_Type comp_type, const string &comp_name,
+ eDepsOperation_Code opcode, const string &description = "");
+
+ OperationDepsNode *find_operation_node(ID *id,
+ eDepsNode_Type comp_type,
+ const string &comp_name,
+ eDepsOperation_Code opcode,
+ const string &description = "");
+
+ OperationDepsNode *find_operation_node(ID *id,
+ eDepsNode_Type comp_type,
+ eDepsOperation_Code opcode,
+ const string &description = "")
+ {
+ return find_operation_node(id, comp_type, "", opcode, description);
+ }
+
+ void build_scene(Main *bmain, Scene *scene);
+ SubgraphDepsNode *build_subgraph(Group *group);
+ void build_group(Scene *scene, Base *base, Group *group);
+ void build_object(Scene *scene, Base *base, Object *ob);
+ void build_object_transform(Scene *scene, Object *ob);
+ void build_object_constraints(Scene *scene, Object *ob);
+ void build_pose_constraints(Object *ob, bPoseChannel *pchan);
+ void build_rigidbody(Scene *scene);
+ void build_particles(Scene *scene, Object *ob);
+ void build_animdata(ID *id);
+ OperationDepsNode *build_driver(ID *id, FCurve *fcurve);
+ void build_ik_pose(Scene *scene, Object *ob, bPoseChannel *pchan, bConstraint *con);
+ void build_splineik_pose(Scene *scene, Object *ob, bPoseChannel *pchan, bConstraint *con);
+ void build_rig(Scene *scene, Object *ob);
+ void build_proxy_rig(Object *ob);
+ void build_shapekeys(Key *key);
+ void build_obdata_geom(Scene *scene, Object *ob);
+ void build_camera(Object *ob);
+ void build_lamp(Object *ob);
+ void build_nodetree(DepsNode *owner_node, bNodeTree *ntree);
+ void build_material(DepsNode *owner_node, Material *ma);
+ void build_texture(DepsNode *owner_node, Tex *tex);
+ void build_texture_stack(DepsNode *owner_node, MTex **texture_stack);
+ void build_world(World *world);
+ void build_compositor(Scene *scene);
+ void build_gpencil(bGPdata *gpd);
+
+private:
+ Main *m_bmain;
+ Depsgraph *m_graph;
+};
+
+struct RootKey
+{
+ RootKey() {}
+};
+
+struct TimeSourceKey
+{
+ TimeSourceKey() : id(NULL) {}
+ TimeSourceKey(ID *id) : id(id) {}
+
+ string identifier() const
+ {
+ return string("TimeSourceKey");
+ }
+
+ ID *id;
+};
+
+struct ComponentKey
+{
+ ComponentKey() :
+ id(NULL), type(DEPSNODE_TYPE_UNDEFINED), name("")
+ {}
+ ComponentKey(ID *id, eDepsNode_Type type, const string &name = "") :
+ id(id), type(type), name(name)
+ {}
+
+ string identifier() const
+ {
+ const char *idname = (id) ? id->name : "<None>";
+
+ char typebuf[5];
+ sprintf(typebuf, "%d", type);
+
+ return string("ComponentKey(") + idname + ", " + typebuf + ", '" + name + "')";
+ }
+
+ ID *id;
+ eDepsNode_Type type;
+ string name;
+};
+
+struct OperationKey
+{
+ OperationKey() :
+ id(NULL), component_type(DEPSNODE_TYPE_UNDEFINED), component_name(""), opcode(DEG_OPCODE_OPERATION), name("")
+ {}
+
+ OperationKey(ID *id, eDepsNode_Type component_type, const string &name) :
+ id(id), component_type(component_type), component_name(""), opcode(DEG_OPCODE_OPERATION), name(name)
+ {}
+ OperationKey(ID *id, eDepsNode_Type component_type, const string &component_name, const string &name) :
+ id(id), component_type(component_type), component_name(component_name), opcode(DEG_OPCODE_OPERATION), name(name)
+ {}
+
+ OperationKey(ID *id, eDepsNode_Type component_type, eDepsOperation_Code opcode) :
+ id(id), component_type(component_type), component_name(""), opcode(opcode), name("")
+ {}
+ OperationKey(ID *id, eDepsNode_Type component_type, const string &component_name, eDepsOperation_Code opcode) :
+ id(id), component_type(component_type), component_name(component_name), opcode(opcode), name("")
+ {}
+
+ OperationKey(ID *id, eDepsNode_Type component_type, eDepsOperation_Code opcode, const string &name) :
+ id(id), component_type(component_type), component_name(""), opcode(opcode), name(name)
+ {}
+ OperationKey(ID *id, eDepsNode_Type component_type, const string &component_name, eDepsOperation_Code opcode, const string &name) :
+ id(id), component_type(component_type), component_name(component_name), opcode(opcode), name(name)
+ {}
+
+ string identifier() const
+ {
+ char typebuf[5];
+ sprintf(typebuf, "%d", component_type);
+
+ return string("OperationKey(") + "t: " + typebuf + ", cn: '" + component_name + "', c: " + DEG_OPNAMES[opcode] + ", n: '" + name + "')";
+ }
+
+
+ ID *id;
+ eDepsNode_Type component_type;
+ string component_name;
+ eDepsOperation_Code opcode;
+ string name;
+};
+
+struct RNAPathKey
+{
+ // Note: see depsgraph_build.cpp for implementation
+ RNAPathKey(ID *id, const char *path);
+
+ RNAPathKey(ID *id, const PointerRNA &ptr, PropertyRNA *prop) :
+ id(id), ptr(ptr), prop(prop)
+ {}
+
+ string identifier() const
+ {
+ const char *id_name = (id) ? id->name : "<No ID>";
+ const char *prop_name = (prop) ? RNA_property_identifier(prop) : "<No Prop>";
+
+ return string("RnaPathKey(") + "id: " + id_name + ", prop: " + prop_name + "')";
+ }
+
+
+ ID *id;
+ PointerRNA ptr;
+ PropertyRNA *prop;
+};
+
+struct DepsgraphRelationBuilder
+{
+ DepsgraphRelationBuilder(Depsgraph *graph);
+
+ template <typename KeyFrom, typename KeyTo>
+ void add_relation(const KeyFrom &key_from, const KeyTo &key_to,
+ eDepsRelation_Type type, const char *description);
+
+ template <typename KeyTo>
+ void add_relation(const TimeSourceKey &key_from, const KeyTo &key_to,
+ eDepsRelation_Type type, const char *description);
+
+ template <typename KeyType>
+ void add_node_handle_relation(const KeyType &key_from, const DepsNodeHandle *handle,
+ eDepsRelation_Type type, const char *description);
+
+ void build_scene(Main *bmain, Scene *scene);
+ void build_group(Main *bmain, Scene *scene, Object *object, Group *group);
+ void build_object(Main *bmain, Scene *scene, Object *ob);
+ void build_object_parent(Object *ob);
+ void build_constraints(Scene *scene, ID *id, eDepsNode_Type component_type, const char *component_subdata,
+ ListBase *constraints, RootPChanMap *root_map);
+ void build_animdata(ID *id);
+ void build_driver(ID *id, FCurve *fcurve);
+ void build_world(World *world);
+ void build_rigidbody(Scene *scene);
+ void build_particles(Scene *scene, Object *ob);
+ void build_ik_pose(Object *ob, bPoseChannel *pchan, bConstraint *con, RootPChanMap *root_map);
+ void build_splineik_pose(Object *ob, bPoseChannel *pchan, bConstraint *con, RootPChanMap *root_map);
+ void build_rig(Scene *scene, Object *ob);
+ void build_proxy_rig(Object *ob);
+ void build_shapekeys(ID *obdata, Key *key);
+ void build_obdata_geom(Main *bmain, Scene *scene, Object *ob);
+ void build_camera(Object *ob);
+ void build_lamp(Object *ob);
+ void build_nodetree(ID *owner, bNodeTree *ntree);
+ void build_material(ID *owner, Material *ma);
+ void build_texture(ID *owner, Tex *tex);
+ void build_texture_stack(ID *owner, MTex **texture_stack);
+ void build_compositor(Scene *scene);
+ void build_gpencil(ID *owner, bGPdata *gpd);
+
+protected:
+ RootDepsNode *find_node(const RootKey &key) const;
+ TimeSourceDepsNode *find_node(const TimeSourceKey &key) const;
+ ComponentDepsNode *find_node(const ComponentKey &key) const;
+ OperationDepsNode *find_node(const OperationKey &key) const;
+ DepsNode *find_node(const RNAPathKey &key) const;
+ OperationDepsNode *has_node(const OperationKey &key) const;
+
+ void add_time_relation(TimeSourceDepsNode *timesrc, DepsNode *node_to, const char *description);
+ void add_operation_relation(OperationDepsNode *node_from, OperationDepsNode *node_to,
+ eDepsRelation_Type type, const char *description);
+
+ template <typename KeyType>
+ DepsNodeHandle create_node_handle(const KeyType &key, const string &default_name = "");
+
+ bool needs_animdata_node(ID *id);
+
+private:
+ Depsgraph *m_graph;
+};
+
+struct DepsNodeHandle
+{
+ DepsNodeHandle(DepsgraphRelationBuilder *builder, OperationDepsNode *node, const string &default_name = "") :
+ builder(builder),
+ node(node),
+ default_name(default_name)
+ {
+ BLI_assert(node != NULL);
+ }
+
+ DepsgraphRelationBuilder *builder;
+ OperationDepsNode *node;
+ const string &default_name;
+};
+
+/* Utilities for Builders ----------------------------------------------------- */
+
+/* Get unique identifier for FCurves and Drivers */
+string deg_fcurve_id_name(const FCurve *fcu);
+
+template <typename KeyFrom, typename KeyTo>
+void DepsgraphRelationBuilder::add_relation(const KeyFrom &key_from,
+ const KeyTo &key_to,
+ eDepsRelation_Type type,
+ const char *description)
+{
+ DepsNode *node_from = find_node(key_from);
+ DepsNode *node_to = find_node(key_to);
+ OperationDepsNode *op_from = node_from ? node_from->get_exit_operation() : NULL;
+ OperationDepsNode *op_to = node_to ? node_to->get_entry_operation() : NULL;
+ if (op_from && op_to) {
+ add_operation_relation(op_from, op_to, type, description);
+ }
+ else {
+ if (!op_from) {
+ /* XXX TODO handle as error or report if needed */
+ fprintf(stderr, "add_relation(%d, %s) - Could not find op_from (%s)\n",
+ type, description, key_from.identifier().c_str());
+ }
+ else {
+ fprintf(stderr, "add_relation(%d, %s) - Failed, but op_from (%s) was ok\n",
+ type, description, key_from.identifier().c_str());
+ }
+ if (!op_to) {
+ /* XXX TODO handle as error or report if needed */
+ fprintf(stderr, "add_relation(%d, %s) - Could not find op_to (%s)\n",
+ type, description, key_to.identifier().c_str());
+ }
+ else {
+ fprintf(stderr, "add_relation(%d, %s) - Failed, but op_to (%s) was ok\n",
+ type, description, key_to.identifier().c_str());
+ }
+ }
+}
+
+template <typename KeyTo>
+void DepsgraphRelationBuilder::add_relation(const TimeSourceKey &key_from,
+ const KeyTo &key_to,
+ eDepsRelation_Type type,
+ const char *description)
+{
+ (void)type; /* Ignored in release builds. */
+ BLI_assert(type == DEPSREL_TYPE_TIME);
+ TimeSourceDepsNode *time_from = find_node(key_from);
+ DepsNode *node_to = find_node(key_to);
+ OperationDepsNode *op_to = node_to ? node_to->get_entry_operation() : NULL;
+ if (time_from && op_to) {
+ add_time_relation(time_from, op_to, description);
+ }
+ else {
+ }
+}
+
+template <typename KeyType>
+void DepsgraphRelationBuilder::add_node_handle_relation(const KeyType &key_from,
+ const DepsNodeHandle *handle,
+ eDepsRelation_Type type,
+ const char *description)
+{
+ DepsNode *node_from = find_node(key_from);
+ OperationDepsNode *op_from = node_from ? node_from->get_exit_operation() : NULL;
+ OperationDepsNode *op_to = handle->node->get_entry_operation();
+ if (op_from && op_to) {
+ add_operation_relation(op_from, op_to, type, description);
+ }
+ else {
+ if (!op_from) {
+ /* XXX TODO handle as error or report if needed */
+ }
+ if (!op_to) {
+ /* XXX TODO handle as error or report if needed */
+ }
+ }
+}
+
+template <typename KeyType>
+DepsNodeHandle DepsgraphRelationBuilder::create_node_handle(const KeyType &key,
+ const string &default_name)
+{
+ return DepsNodeHandle(this, find_node(key), default_name);
+}
+
+#endif /* __DEPSGRAPH_BUILD_H__ */
diff --git a/source/blender/depsgraph/intern/depsgraph_build_nodes.cc b/source/blender/depsgraph/intern/depsgraph_build_nodes.cc
new file mode 100644
index 00000000000..4463df61f91
--- /dev/null
+++ b/source/blender/depsgraph/intern/depsgraph_build_nodes.cc
@@ -0,0 +1,1204 @@
+/*
+ * ***** 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.
+ *
+ * Original Author: Joshua Leung
+ * Contributor(s): Based on original depsgraph.c code - Blender Foundation (2005-2013)
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/depsgraph/intern/depsgraph_build_nodes.cc
+ * \ingroup depsgraph
+ *
+ * Methods for constructing depsgraph's nodes
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "MEM_guardedalloc.h"
+
+extern "C" {
+#include "BLI_blenlib.h"
+#include "BLI_string.h"
+#include "BLI_utildefines.h"
+
+#include "DNA_action_types.h"
+#include "DNA_anim_types.h"
+#include "DNA_armature_types.h"
+#include "DNA_camera_types.h"
+#include "DNA_constraint_types.h"
+#include "DNA_curve_types.h"
+#include "DNA_effect_types.h"
+#include "DNA_gpencil_types.h"
+#include "DNA_group_types.h"
+#include "DNA_key_types.h"
+#include "DNA_lamp_types.h"
+#include "DNA_material_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_meta_types.h"
+#include "DNA_node_types.h"
+#include "DNA_particle_types.h"
+#include "DNA_object_types.h"
+#include "DNA_rigidbody_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_texture_types.h"
+#include "DNA_world_types.h"
+
+#include "BKE_action.h"
+#include "BKE_armature.h"
+#include "BKE_animsys.h"
+#include "BKE_constraint.h"
+#include "BKE_curve.h"
+#include "BKE_depsgraph.h"
+#include "BKE_effect.h"
+#include "BKE_fcurve.h"
+#include "BKE_idcode.h"
+#include "BKE_group.h"
+#include "BKE_key.h"
+#include "BKE_lattice.h"
+#include "BKE_library.h"
+#include "BKE_main.h"
+#include "BKE_material.h"
+#include "BKE_mesh.h"
+#include "BKE_mball.h"
+#include "BKE_modifier.h"
+#include "BKE_node.h"
+#include "BKE_object.h"
+#include "BKE_particle.h"
+#include "BKE_rigidbody.h"
+#include "BKE_sound.h"
+#include "BKE_texture.h"
+#include "BKE_tracking.h"
+#include "BKE_world.h"
+
+#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_build.h"
+
+#include "RNA_access.h"
+#include "RNA_types.h"
+} /* extern "C" */
+
+#include "depsnode.h"
+#include "depsnode_component.h"
+#include "depsnode_operation.h"
+#include "depsgraph_types.h"
+#include "depsgraph_build.h"
+#include "depsgraph_intern.h"
+
+/* ************ */
+/* Node Builder */
+
+/* **** General purpose functions **** */
+
+DepsgraphNodeBuilder::DepsgraphNodeBuilder(Main *bmain, Depsgraph *graph) :
+ m_bmain(bmain),
+ m_graph(graph)
+{
+}
+
+DepsgraphNodeBuilder::~DepsgraphNodeBuilder()
+{
+}
+
+RootDepsNode *DepsgraphNodeBuilder::add_root_node()
+{
+ return m_graph->add_root_node();
+}
+
+IDDepsNode *DepsgraphNodeBuilder::add_id_node(ID *id)
+{
+ const char *idtype_name = BKE_idcode_to_name(GS(id->name));
+ return m_graph->add_id_node(id, string(id->name + 2) + "[" + idtype_name + "]");
+}
+
+TimeSourceDepsNode *DepsgraphNodeBuilder::add_time_source(ID *id)
+{
+ /* determine which node to attach timesource to */
+ if (id) {
+#if 0 /* XXX TODO */
+ /* get ID node */
+ IDDepsNode id_node = m_graph->find_id_node(id);
+
+ /* depends on what this is... */
+ switch (GS(id->name)) {
+ case ID_SCE: /* Scene - Usually sequencer strip causing time remapping... */
+ {
+ // TODO...
+ }
+ break;
+
+ case ID_GR: /* Group */
+ {
+ // TODO...
+ }
+ break;
+
+ // XXX: time source...
+
+ default: /* Unhandled */
+ printf("%s(): Unhandled ID - %s \n", __func__, id->name);
+ break;
+ }
+#endif
+ }
+ else {
+ /* root-node */
+ RootDepsNode *root_node = m_graph->root_node;
+ if (root_node) {
+ return root_node->add_time_source("Time Source");
+ }
+ }
+
+ return NULL;
+}
+
+ComponentDepsNode *DepsgraphNodeBuilder::add_component_node(
+ ID *id,
+ eDepsNode_Type comp_type,
+ const string &comp_name)
+{
+ IDDepsNode *id_node = add_id_node(id);
+ ComponentDepsNode *comp_node = id_node->add_component(comp_type, comp_name);
+ comp_node->owner = id_node;
+ return comp_node;
+}
+
+OperationDepsNode *DepsgraphNodeBuilder::add_operation_node(
+ ComponentDepsNode *comp_node,
+ eDepsOperation_Type optype,
+ DepsEvalOperationCb op,
+ eDepsOperation_Code opcode,
+ const string &description)
+{
+ OperationDepsNode *op_node = comp_node->has_operation(opcode, description);
+ if (op_node == NULL) {
+ op_node = comp_node->add_operation(optype, op, opcode, description);
+ m_graph->operations.push_back(op_node);
+ }
+ else {
+ fprintf(stderr, "add_operation: Operation already exists - %s has %s at %p\n",
+ comp_node->identifier().c_str(),
+ op_node->identifier().c_str(),
+ op_node);
+ BLI_assert(!"Should not happen!");
+ }
+ return op_node;
+}
+
+OperationDepsNode *DepsgraphNodeBuilder::add_operation_node(
+ ID *id,
+ eDepsNode_Type comp_type,
+ const string &comp_name,
+ eDepsOperation_Type optype,
+ DepsEvalOperationCb op,
+ eDepsOperation_Code opcode,
+ const string &description)
+{
+ ComponentDepsNode *comp_node = add_component_node(id, comp_type, comp_name);
+ return add_operation_node(comp_node, optype, op, opcode, description);
+}
+
+bool DepsgraphNodeBuilder::has_operation_node(ID *id,
+ eDepsNode_Type comp_type,
+ const string &comp_name,
+ eDepsOperation_Code opcode,
+ const string &description)
+{
+ return find_operation_node(id, comp_type, comp_name, opcode, description) != NULL;
+}
+
+OperationDepsNode *DepsgraphNodeBuilder::find_operation_node(
+ ID *id,
+ eDepsNode_Type comp_type,
+ const string &comp_name,
+ eDepsOperation_Code opcode,
+ const string &description)
+{
+ ComponentDepsNode *comp_node = add_component_node(id, comp_type, comp_name);
+ return comp_node->has_operation(opcode, description);
+}
+
+
+/* **** Build functions for entity nodes **** */
+
+void DepsgraphNodeBuilder::build_scene(Main *bmain, Scene *scene)
+{
+ /* LIB_DOIT is used to indicate whether node for given ID was already
+ * created or not. This flag is being set in add_id_node(), so functions
+ * shouldn't bother with setting it, they only might query this flag when
+ * needed.
+ */
+ BKE_main_id_tag_all(bmain, false);
+
+ /* scene ID block */
+ add_id_node(&scene->id);
+
+ /* timesource */
+ add_time_source(NULL);
+
+ /* build subgraph for set, and link this in... */
+ // XXX: depending on how this goes, that scene itself could probably store its
+ // own little partial depsgraph?
+ if (scene->set) {
+ build_scene(bmain, scene->set);
+ }
+
+ /* scene objects */
+ for (Base *base = (Base *)scene->base.first; base; base = base->next) {
+ Object *ob = base->object;
+
+ /* object itself */
+ build_object(scene, base, ob);
+
+ /* object that this is a proxy for */
+ // XXX: the way that proxies work needs to be completely reviewed!
+ if (ob->proxy) {
+ build_object(scene, base, ob->proxy);
+ }
+
+ /* Object dupligroup. */
+ if (ob->dup_group) {
+ build_group(scene, base, ob->dup_group);
+ }
+ }
+
+ /* rigidbody */
+ if (scene->rigidbody_world) {
+ build_rigidbody(scene);
+ }
+
+ /* scene's animation and drivers */
+ if (scene->adt) {
+ build_animdata(&scene->id);
+ }
+
+ /* world */
+ if (scene->world) {
+ build_world(scene->world);
+ }
+
+ /* compo nodes */
+ if (scene->nodetree) {
+ build_compositor(scene);
+ }
+
+ /* sequencer */
+ // XXX...
+
+ /* grease pencil */
+ if (scene->gpd) {
+ build_gpencil(scene->gpd);
+ }
+}
+
+void DepsgraphNodeBuilder::build_group(Scene *scene,
+ Base *base,
+ Group *group)
+{
+ ID *group_id = &group->id;
+ if (group_id->flag & LIB_DOIT) {
+ return;
+ }
+ group_id->flag |= LIB_DOIT;
+
+ for (GroupObject *go = (GroupObject *)group->gobject.first;
+ go != NULL;
+ go = go->next)
+ {
+ build_object(scene, base, go->ob);
+ }
+}
+
+SubgraphDepsNode *DepsgraphNodeBuilder::build_subgraph(Group *group)
+{
+ /* sanity checks */
+ if (!group)
+ return NULL;
+
+ /* create new subgraph's data */
+ Depsgraph *subgraph = DEG_graph_new();
+
+ DepsgraphNodeBuilder subgraph_builder(m_bmain, subgraph);
+
+ /* add group objects */
+ for (GroupObject *go = (GroupObject *)group->gobject.first;
+ go != NULL;
+ go = go->next)
+ {
+ /*Object *ob = go->ob;*/
+
+ /* Each "group object" is effectively a separate instance of the underlying
+ * object data. When the group is evaluated, the transform results and/or
+ * some other attributes end up getting overridden by the group
+ */
+ }
+
+ /* create a node for representing subgraph */
+ SubgraphDepsNode *subgraph_node = m_graph->add_subgraph_node(&group->id);
+ subgraph_node->graph = subgraph;
+
+ /* make a copy of the data this node will need? */
+ // XXX: do we do this now, or later?
+ // TODO: need API function which queries graph's ID's hash, and duplicates those blocks thoroughly with all outside links removed...
+
+ return subgraph_node;
+}
+
+void DepsgraphNodeBuilder::build_object(Scene *scene, Base *base, Object *ob)
+{
+ if (ob->id.flag & LIB_DOIT) {
+ IDDepsNode *id_node = m_graph->find_id_node(&ob->id);
+ id_node->layers = base->lay;
+ return;
+ }
+
+ IDDepsNode *id_node = add_id_node(&ob->id);
+ id_node->layers = base->lay;
+
+ /* standard components */
+ build_object_transform(scene, ob);
+
+
+ /* object data */
+ if (ob->data) {
+ /* type-specific data... */
+ switch (ob->type) {
+ case OB_MESH: /* Geometry */
+ case OB_CURVE:
+ case OB_FONT:
+ case OB_SURF:
+ case OB_MBALL:
+ case OB_LATTICE:
+ {
+ /* TODO(sergey): This way using this object's
+ * properties as driver target works fine.
+ *
+ * Does this depend on other nodes?
+ */
+ add_operation_node(&ob->id, DEPSNODE_TYPE_PARAMETERS, DEPSOP_TYPE_POST, NULL,
+ DEG_OPCODE_PLACEHOLDER, "Parameters Eval");
+
+ build_obdata_geom(scene, ob);
+ /* TODO(sergey): Only for until we support granular
+ * update of curves.
+ */
+ if (ob->type == OB_FONT) {
+ Curve *curve = (Curve *)ob->data;
+ if (curve->textoncurve) {
+ id_node->eval_flags |= DAG_EVAL_NEED_CURVE_PATH;
+ }
+ }
+ break;
+ }
+
+ case OB_ARMATURE: /* Pose */
+ if (ob->id.lib != NULL && ob->proxy_from != NULL) {
+ build_proxy_rig(ob);
+ }
+ else {
+ build_rig(scene, ob);
+ }
+ break;
+
+ case OB_LAMP: /* Lamp */
+ build_lamp(ob);
+ break;
+
+ case OB_CAMERA: /* Camera */
+ build_camera(ob);
+ break;
+
+ default:
+ {
+ ID *obdata = (ID *)ob->data;
+ if ((obdata->flag & LIB_DOIT) == 0) {
+ build_animdata(obdata);
+ }
+ break;
+ }
+ }
+ }
+
+ /* Build animation data,
+ *
+ * Do it now because it's possible object data will affect
+ * on object's level animation, for example in case of rebuilding
+ * pose for proxy.
+ */
+ build_animdata(&ob->id);
+
+ /* particle systems */
+ if (ob->particlesystem.first) {
+ build_particles(scene, ob);
+ }
+
+ /* grease pencil */
+ if (ob->gpd) {
+ build_gpencil(ob->gpd);
+ }
+}
+
+void DepsgraphNodeBuilder::build_object_transform(Scene *scene, Object *ob)
+{
+ /* local transforms (from transform channels - loc/rot/scale + deltas) */
+ add_operation_node(&ob->id, DEPSNODE_TYPE_TRANSFORM,
+ DEPSOP_TYPE_INIT, function_bind(BKE_object_eval_local_transform, _1, scene, ob),
+ DEG_OPCODE_TRANSFORM_LOCAL);
+
+ /* object parent */
+ if (ob->parent) {
+ add_operation_node(&ob->id, DEPSNODE_TYPE_TRANSFORM,
+ DEPSOP_TYPE_EXEC, function_bind(BKE_object_eval_parent, _1, scene, ob),
+ DEG_OPCODE_TRANSFORM_PARENT);
+ }
+
+ /* object constraints */
+ if (ob->constraints.first) {
+ build_object_constraints(scene, ob);
+ }
+
+ /* Temporary uber-update node, which does everything.
+ * It is for the being we're porting old dependencies into the new system.
+ * We'll get rid of this node as soon as all the granular update functions
+ * are filled in.
+ *
+ * TODO(sergey): Get rid of this node.
+ */
+ add_operation_node(&ob->id, DEPSNODE_TYPE_TRANSFORM,
+ DEPSOP_TYPE_EXEC, function_bind(BKE_object_eval_uber_transform, _1, scene, ob),
+ DEG_OPCODE_OBJECT_UBEREVAL);
+
+ /* object transform is done */
+ add_operation_node(&ob->id, DEPSNODE_TYPE_TRANSFORM,
+ DEPSOP_TYPE_POST, function_bind(BKE_object_eval_done, _1, ob),
+ DEG_OPCODE_TRANSFORM_FINAL);
+}
+
+/**
+ * Constraints Graph Notes
+ *
+ * For constraints, we currently only add a operation node to the Transform
+ * or Bone components (depending on whichever type of owner we have).
+ * This represents the entire constraints stack, which is for now just
+ * executed as a single monolithic block. At least initially, this should
+ * be sufficient for ensuring that the porting/refactoring process remains
+ * manageable.
+ *
+ * However, when the time comes for developing "node-based" constraints,
+ * we'll need to split this up into pre/post nodes for "constraint stack
+ * evaluation" + operation nodes for each constraint (i.e. the contents
+ * of the loop body used in the current "solve_constraints()" operation).
+ *
+ * -- Aligorith, August 2013
+ */
+void DepsgraphNodeBuilder::build_object_constraints(Scene *scene, Object *ob)
+{
+ /* create node for constraint stack */
+ add_operation_node(&ob->id, DEPSNODE_TYPE_TRANSFORM,
+ DEPSOP_TYPE_EXEC, function_bind(BKE_object_eval_constraints, _1, scene, ob),
+ DEG_OPCODE_TRANSFORM_CONSTRAINTS);
+}
+
+void DepsgraphNodeBuilder::build_pose_constraints(Object *ob, bPoseChannel *pchan)
+{
+ /* create node for constraint stack */
+ add_operation_node(&ob->id, DEPSNODE_TYPE_BONE, pchan->name,
+ DEPSOP_TYPE_EXEC, function_bind(BKE_pose_constraints_evaluate, _1, ob, pchan),
+ DEG_OPCODE_BONE_CONSTRAINTS);
+}
+
+/**
+ * Build graph nodes for AnimData block
+ * \param id: ID-Block which hosts the AnimData
+ */
+void DepsgraphNodeBuilder::build_animdata(ID *id)
+{
+ AnimData *adt = BKE_animdata_from_id(id);
+
+ if (adt == NULL)
+ return;
+
+ /* animation */
+ if (adt->action || adt->nla_tracks.first || adt->drivers.first) {
+ // XXX: Hook up specific update callbacks for special properties which may need it...
+
+ /* actions and NLA - as a single unit for now, as it gets complicated to schedule otherwise */
+ if ((adt->action) || (adt->nla_tracks.first)) {
+ /* create the node */
+ add_operation_node(id, DEPSNODE_TYPE_ANIMATION,
+ DEPSOP_TYPE_EXEC, function_bind(BKE_animsys_eval_animdata, _1, id),
+ DEG_OPCODE_ANIMATION, id->name);
+
+ // TODO: for each channel affected, we might also want to add some support for running RNA update callbacks on them
+ // (which will be needed for proper handling of drivers later)
+ }
+
+ /* drivers */
+ for (FCurve *fcu = (FCurve *)adt->drivers.first; fcu; fcu = fcu->next) {
+ /* create driver */
+ build_driver(id, fcu);
+ }
+ }
+}
+
+/**
+ * Build graph node(s) for Driver
+ * \param id: ID-Block that driver is attached to
+ * \param fcu: Driver-FCurve
+ */
+OperationDepsNode *DepsgraphNodeBuilder::build_driver(ID *id, FCurve *fcu)
+{
+ ChannelDriver *driver = fcu->driver;
+
+ /* Create data node for this driver */
+ /* TODO(sergey): Avoid creating same operation multiple times,
+ * in the future we need to avoid lookup of the operation as well
+ * and use some tagging magic instead.
+ */
+ OperationDepsNode *driver_op = find_operation_node(id,
+ DEPSNODE_TYPE_PARAMETERS,
+ DEG_OPCODE_DRIVER,
+ deg_fcurve_id_name(fcu));
+
+ if (driver_op == NULL) {
+ driver_op = add_operation_node(id, DEPSNODE_TYPE_PARAMETERS,
+ DEPSOP_TYPE_EXEC, function_bind(BKE_animsys_eval_driver, _1, id, fcu),
+ DEG_OPCODE_DRIVER, deg_fcurve_id_name(fcu));
+ }
+
+ /* tag "scripted expression" drivers as needing Python (due to GIL issues, etc.) */
+ if (driver->type == DRIVER_TYPE_PYTHON) {
+ driver_op->flag |= DEPSOP_FLAG_USES_PYTHON;
+ }
+
+ /* return driver node created */
+ return driver_op;
+}
+
+/* Recursively build graph for world */
+void DepsgraphNodeBuilder::build_world(World *world)
+{
+ ID *world_id = &world->id;
+ if (world_id->flag & LIB_DOIT) {
+ return;
+ }
+
+ /* world itself */
+ IDDepsNode *world_node = add_id_node(world_id); /* world shading/params? */
+
+ build_animdata(world_id);
+
+ /* TODO: other settings? */
+
+ /* textures */
+ build_texture_stack(world_node, world->mtex);
+
+ /* world's nodetree */
+ if (world->nodetree) {
+ build_nodetree(world_node, world->nodetree);
+ }
+}
+
+/* Rigidbody Simulation - Scene Level */
+void DepsgraphNodeBuilder::build_rigidbody(Scene *scene)
+{
+ RigidBodyWorld *rbw = scene->rigidbody_world;
+
+ /**
+ * Rigidbody Simulation Nodes
+ * ==========================
+ *
+ * There are 3 nodes related to Rigidbody Simulation:
+ * 1) "Initialize/Rebuild World" - this is called sparingly, only when the simulation
+ * needs to be rebuilt (mainly after file reload, or moving back to start frame)
+ * 2) "Do Simulation" - perform a simulation step - interleaved between the evaluation
+ * steps for clusters of objects (i.e. between those affected and/or not affected by
+ * the sim for instance)
+ *
+ * 3) "Pull Results" - grab the specific transforms applied for a specific object -
+ * performed as part of object's transform-stack building
+ */
+
+ /* create nodes ------------------------------------------------------------------------ */
+ /* XXX: is this the right component, or do we want to use another one instead? */
+
+ /* init/rebuild operation */
+ /*OperationDepsNode *init_node =*/ add_operation_node(&scene->id, DEPSNODE_TYPE_TRANSFORM,
+ DEPSOP_TYPE_REBUILD, function_bind(BKE_rigidbody_rebuild_sim, _1, scene),
+ DEG_OPCODE_RIGIDBODY_REBUILD);
+
+ /* do-sim operation */
+ // XXX: what happens if we need to split into several groups?
+ OperationDepsNode *sim_node = add_operation_node(&scene->id, DEPSNODE_TYPE_TRANSFORM,
+ DEPSOP_TYPE_SIM, function_bind(BKE_rigidbody_eval_simulation, _1, scene),
+ DEG_OPCODE_RIGIDBODY_SIM);
+
+ /* XXX: For now, the sim node is the only one that really matters here. If any other
+ * sims get added later, we may have to remove these hacks...
+ */
+ sim_node->owner->entry_operation = sim_node;
+ sim_node->owner->exit_operation = sim_node;
+
+
+ /* objects - simulation participants */
+ if (rbw->group) {
+ for (GroupObject *go = (GroupObject *)rbw->group->gobject.first; go; go = go->next) {
+ Object *ob = go->ob;
+
+ if (!ob || (ob->type != OB_MESH))
+ continue;
+
+ /* 2) create operation for flushing results */
+ /* object's transform component - where the rigidbody operation lives */
+ add_operation_node(&ob->id, DEPSNODE_TYPE_TRANSFORM,
+ DEPSOP_TYPE_EXEC, function_bind(BKE_rigidbody_object_sync_transforms, _1, scene, ob),
+ DEG_OPCODE_TRANSFORM_RIGIDBODY);
+ }
+ }
+}
+
+void DepsgraphNodeBuilder::build_particles(Scene *scene, Object *ob)
+{
+ /**
+ * Particle Systems Nodes
+ * ======================
+ *
+ * There are two types of nodes associated with representing
+ * particle systems:
+ * 1) Component (EVAL_PARTICLES) - This is the particle-system
+ * evaluation context for an object. It acts as the container
+ * for all the nodes associated with a particular set of particle
+ * systems.
+ * 2) Particle System Eval Operation - This operation node acts as a
+ * blackbox evaluation step for one particle system referenced by
+ * the particle systems stack. All dependencies link to this operation.
+ */
+
+ /* component for all particle systems */
+ ComponentDepsNode *psys_comp = add_component_node(&ob->id, DEPSNODE_TYPE_EVAL_PARTICLES);
+
+ /* particle systems */
+ for (ParticleSystem *psys = (ParticleSystem *)ob->particlesystem.first; psys; psys = psys->next) {
+ ParticleSettings *part = psys->part;
+
+ /* particle settings */
+ // XXX: what if this is used more than once!
+ build_animdata(&part->id);
+
+ /* this particle system */
+ // TODO: for now, this will just be a placeholder "ubereval" node
+ add_operation_node(psys_comp,
+ DEPSOP_TYPE_EXEC, function_bind(BKE_particle_system_eval, _1, scene, ob, psys),
+ DEG_OPCODE_PSYS_EVAL,
+ psys->name);
+ }
+
+ /* pointcache */
+ // TODO...
+}
+
+/* IK Solver Eval Steps */
+void DepsgraphNodeBuilder::build_ik_pose(Scene *scene, Object *ob, bPoseChannel *pchan, bConstraint *con)
+{
+ bKinematicConstraint *data = (bKinematicConstraint *)con->data;
+
+ /* Find the chain's root. */
+ bPoseChannel *rootchan = BKE_armature_ik_solver_find_root(pchan, data);
+
+ if (has_operation_node(&ob->id, DEPSNODE_TYPE_EVAL_POSE, rootchan->name,
+ DEG_OPCODE_POSE_IK_SOLVER))
+ {
+ return;
+ }
+
+ /* Operation node for evaluating/running IK Solver. */
+ add_operation_node(&ob->id, DEPSNODE_TYPE_EVAL_POSE, rootchan->name,
+ DEPSOP_TYPE_SIM, function_bind(BKE_pose_iktree_evaluate, _1, scene, ob, rootchan),
+ DEG_OPCODE_POSE_IK_SOLVER);
+}
+
+/* Spline IK Eval Steps */
+void DepsgraphNodeBuilder::build_splineik_pose(Scene *scene, Object *ob, bPoseChannel *pchan, bConstraint *con)
+{
+ bSplineIKConstraint *data = (bSplineIKConstraint *)con->data;
+
+ /* Find the chain's root. */
+ bPoseChannel *rootchan = BKE_armature_splineik_solver_find_root(pchan, data);
+
+ /* Operation node for evaluating/running Spline IK Solver.
+ * Store the "root bone" of this chain in the solver, so it knows where to start.
+ */
+ add_operation_node(&ob->id, DEPSNODE_TYPE_EVAL_POSE, rootchan->name,
+ DEPSOP_TYPE_SIM, function_bind(BKE_pose_splineik_evaluate, _1, scene, ob, rootchan),
+ DEG_OPCODE_POSE_SPLINE_IK_SOLVER);
+}
+
+/* Pose/Armature Bones Graph */
+void DepsgraphNodeBuilder::build_rig(Scene *scene, Object *ob)
+{
+ bArmature *arm = (bArmature *)ob->data;
+
+ /* animation and/or drivers linking posebones to base-armature used to define them
+ * NOTE: AnimData here is really used to control animated deform properties,
+ * which ideally should be able to be unique across different instances.
+ * Eventually, we need some type of proxy/isolation mechanism in-between here
+ * to ensure that we can use same rig multiple times in same scene...
+ */
+ build_animdata(&arm->id);
+
+ /* Rebuild pose if not up to date. */
+ if (ob->pose == NULL || (ob->pose->flag & POSE_RECALC)) {
+ BKE_pose_rebuild(ob, arm);
+ /* XXX: Without this animation gets lost in certain circumstances
+ * after loading file. Need to investigate further since it does
+ * not happen with simple scenes..
+ */
+ if (ob->adt) {
+ ob->adt->recalc |= ADT_RECALC_ANIM;
+ }
+ }
+
+ /**
+ * Pose Rig Graph
+ * ==============
+ *
+ * Pose Component:
+ * - Mainly used for referencing Bone components.
+ * - This is where the evaluation operations for init/exec/cleanup
+ * (ik) solvers live, and are later hooked up (so that they can be
+ * interleaved during runtime) with bone-operations they depend on/affect.
+ * - init_pose_eval() and cleanup_pose_eval() are absolute first and last
+ * steps of pose eval process. ALL bone operations must be performed
+ * between these two...
+ *
+ * Bone Component:
+ * - Used for representing each bone within the rig
+ * - Acts to encapsulate the evaluation operations (base matrix + parenting,
+ * and constraint stack) so that they can be easily found.
+ * - Everything else which depends on bone-results hook up to the component only
+ * so that we can redirect those to point at either the the post-IK/
+ * post-constraint/post-matrix steps, as needed.
+ */
+
+ /* pose eval context */
+ add_operation_node(&ob->id, DEPSNODE_TYPE_EVAL_POSE,
+ DEPSOP_TYPE_INIT, function_bind(BKE_pose_eval_init, _1, scene, ob, ob->pose), DEG_OPCODE_POSE_INIT);
+
+ add_operation_node(&ob->id, DEPSNODE_TYPE_EVAL_POSE,
+ DEPSOP_TYPE_POST, function_bind(BKE_pose_eval_flush, _1, scene, ob, ob->pose), DEG_OPCODE_POSE_DONE);
+
+ /* bones */
+ for (bPoseChannel *pchan = (bPoseChannel *)ob->pose->chanbase.first; pchan; pchan = pchan->next) {
+ /* node for bone eval */
+ add_operation_node(&ob->id, DEPSNODE_TYPE_BONE, pchan->name,
+ DEPSOP_TYPE_INIT, NULL, // XXX: BKE_pose_eval_bone_local
+ DEG_OPCODE_BONE_LOCAL);
+
+ add_operation_node(&ob->id, DEPSNODE_TYPE_BONE, pchan->name,
+ DEPSOP_TYPE_EXEC, function_bind(BKE_pose_eval_bone, _1, scene, ob, pchan), // XXX: BKE_pose_eval_bone_pose
+ DEG_OPCODE_BONE_POSE_PARENT);
+
+ add_operation_node(&ob->id, DEPSNODE_TYPE_BONE, pchan->name,
+ DEPSOP_TYPE_OUT, NULL, /* NOTE: dedicated noop for easier relationship construction */
+ DEG_OPCODE_BONE_READY);
+
+ add_operation_node(&ob->id, DEPSNODE_TYPE_BONE, pchan->name,
+ DEPSOP_TYPE_POST, function_bind(BKE_pose_bone_done, _1, pchan),
+ DEG_OPCODE_BONE_DONE);
+
+ /* constraints */
+ if (pchan->constraints.first != NULL) {
+ build_pose_constraints(ob, pchan);
+ }
+
+ /**
+ * IK Solvers...
+ *
+ * - These require separate processing steps are pose-level
+ * to be executed between chains of bones (i.e. once the
+ * base transforms of a bunch of bones is done)
+ *
+ * Unsolved Issues:
+ * - Care is needed to ensure that multi-headed trees work out the same as in ik-tree building
+ * - Animated chain-lengths are a problem...
+ */
+ for (bConstraint *con = (bConstraint *)pchan->constraints.first; con; con = con->next) {
+ switch (con->type) {
+ case CONSTRAINT_TYPE_KINEMATIC:
+ build_ik_pose(scene, ob, pchan, con);
+ break;
+
+ case CONSTRAINT_TYPE_SPLINEIK:
+ build_splineik_pose(scene, ob, pchan, con);
+ break;
+
+ default:
+ break;
+ }
+ }
+ }
+}
+
+void DepsgraphNodeBuilder::build_proxy_rig(Object *ob)
+{
+ ID *obdata = (ID *)ob->data;
+ build_animdata(obdata);
+
+ add_operation_node(&ob->id,
+ DEPSNODE_TYPE_EVAL_POSE,
+ DEPSOP_TYPE_INIT,
+ function_bind(BKE_pose_eval_proxy_copy, _1, ob),
+ DEG_OPCODE_POSE_INIT);
+
+ for (bPoseChannel *pchan = (bPoseChannel *)ob->pose->chanbase.first;
+ pchan != NULL;
+ pchan = pchan->next)
+ {
+ add_operation_node(&ob->id, DEPSNODE_TYPE_BONE, pchan->name,
+ DEPSOP_TYPE_INIT, NULL,
+ DEG_OPCODE_BONE_LOCAL);
+
+ add_operation_node(&ob->id, DEPSNODE_TYPE_BONE, pchan->name,
+ DEPSOP_TYPE_EXEC, NULL,
+ DEG_OPCODE_BONE_READY);
+
+ add_operation_node(&ob->id, DEPSNODE_TYPE_BONE, pchan->name,
+ DEPSOP_TYPE_POST, NULL,
+ DEG_OPCODE_BONE_DONE);
+ }
+
+ add_operation_node(&ob->id,
+ DEPSNODE_TYPE_EVAL_POSE,
+ DEPSOP_TYPE_POST,
+ NULL,
+ DEG_OPCODE_POSE_DONE);
+}
+
+/* Shapekeys */
+void DepsgraphNodeBuilder::build_shapekeys(Key *key)
+{
+ build_animdata(&key->id);
+
+ add_operation_node(&key->id, DEPSNODE_TYPE_GEOMETRY, DEPSOP_TYPE_EXEC, NULL,
+ DEG_OPCODE_PLACEHOLDER, "Shapekey Eval");
+}
+
+/* ObData Geometry Evaluation */
+// XXX: what happens if the datablock is shared!
+void DepsgraphNodeBuilder::build_obdata_geom(Scene *scene, Object *ob)
+{
+ ID *obdata = (ID *)ob->data;
+
+ /* Temporary uber-update node, which does everything.
+ * It is for the being we're porting old dependencies into the new system.
+ * We'll get rid of this node as soon as all the granular update functions
+ * are filled in.
+ *
+ * TODO(sergey): Get rid of this node.
+ */
+ add_operation_node(&ob->id, DEPSNODE_TYPE_GEOMETRY,
+ DEPSOP_TYPE_POST, function_bind(BKE_object_eval_uber_data, _1, scene, ob),
+ DEG_OPCODE_GEOMETRY_UBEREVAL);
+
+ add_operation_node(&ob->id, DEPSNODE_TYPE_GEOMETRY,
+ DEPSOP_TYPE_INIT, NULL,
+ DEG_OPCODE_PLACEHOLDER, "Eval Init");
+
+ // TODO: "Done" operation
+
+ /* ShapeKeys */
+ Key *key = BKE_key_from_object(ob);
+ if (key)
+ build_shapekeys(key);
+
+ /* Modifiers */
+ if (ob->modifiers.first) {
+ ModifierData *md;
+
+ for (md = (ModifierData *)ob->modifiers.first; md; md = md->next) {
+ add_operation_node(&ob->id, DEPSNODE_TYPE_GEOMETRY,
+ DEPSOP_TYPE_EXEC, function_bind(BKE_object_eval_modifier, _1, scene, ob, md),
+ DEG_OPCODE_GEOMETRY_MODIFIER, md->name);
+ }
+ }
+
+ /* materials */
+ if (ob->totcol) {
+ int a;
+
+ for (a = 1; a <= ob->totcol; a++) {
+ Material *ma = give_current_material(ob, a);
+
+ if (ma) {
+ // XXX?!
+ ComponentDepsNode *geom_node = add_component_node(&ob->id, DEPSNODE_TYPE_GEOMETRY);
+ build_material(geom_node, ma);
+ }
+ }
+ }
+
+ /* geometry collision */
+ if (ELEM(ob->type, OB_MESH, OB_CURVE, OB_LATTICE)) {
+ // add geometry collider relations
+ }
+
+ if (obdata->flag & LIB_DOIT) {
+ return;
+ }
+
+ build_animdata(obdata);
+
+ /* nodes for result of obdata's evaluation, and geometry evaluation on object */
+ switch (ob->type) {
+ case OB_MESH:
+ {
+ //Mesh *me = (Mesh *)ob->data;
+
+ /* evaluation operations */
+ add_operation_node(obdata, DEPSNODE_TYPE_GEOMETRY,
+ DEPSOP_TYPE_INIT, function_bind(BKE_mesh_eval_geometry, _1, (Mesh *)obdata),
+ DEG_OPCODE_PLACEHOLDER, "Geometry Eval");
+ break;
+ }
+
+ case OB_MBALL:
+ {
+ Object *mom = BKE_mball_basis_find(scene, ob);
+
+ /* motherball - mom depends on children! */
+ if (mom == ob) {
+ /* metaball evaluation operations */
+ /* NOTE: only the motherball gets evaluated! */
+ add_operation_node(obdata, DEPSNODE_TYPE_GEOMETRY,
+ DEPSOP_TYPE_INIT, function_bind(BKE_mball_eval_geometry, _1, (MetaBall *)obdata),
+ DEG_OPCODE_PLACEHOLDER, "Geometry Eval");
+ }
+ break;
+ }
+
+ case OB_CURVE:
+ case OB_FONT:
+ {
+ /* curve evaluation operations */
+ /* - calculate curve geometry (including path) */
+ add_operation_node(obdata, DEPSNODE_TYPE_GEOMETRY,
+ DEPSOP_TYPE_INIT, function_bind(BKE_curve_eval_geometry, _1, (Curve *)obdata),
+ DEG_OPCODE_PLACEHOLDER, "Geometry Eval");
+
+ /* - calculate curve path - this is used by constraints, etc. */
+ add_operation_node(obdata, DEPSNODE_TYPE_GEOMETRY,
+ DEPSOP_TYPE_EXEC, function_bind(BKE_curve_eval_path, _1, (Curve *)obdata),
+ DEG_OPCODE_GEOMETRY_PATH, "Path");
+ break;
+ }
+
+ case OB_SURF: /* Nurbs Surface */
+ {
+ /* nurbs evaluation operations */
+ add_operation_node(obdata, DEPSNODE_TYPE_GEOMETRY,
+ DEPSOP_TYPE_INIT, function_bind(BKE_curve_eval_geometry, _1, (Curve *)obdata),
+ DEG_OPCODE_PLACEHOLDER, "Geometry Eval");
+ break;
+ }
+
+ case OB_LATTICE: /* Lattice */
+ {
+ /* lattice evaluation operations */
+ add_operation_node(obdata, DEPSNODE_TYPE_GEOMETRY,
+ DEPSOP_TYPE_INIT, function_bind(BKE_lattice_eval_geometry, _1, (Lattice *)obdata),
+ DEG_OPCODE_PLACEHOLDER, "Geometry Eval");
+ break;
+ }
+ }
+
+ add_operation_node(obdata, DEPSNODE_TYPE_GEOMETRY,
+ DEPSOP_TYPE_POST, NULL,
+ DEG_OPCODE_PLACEHOLDER, "Eval Done");
+
+ /* Parameters for driver sources. */
+ add_operation_node(obdata, DEPSNODE_TYPE_PARAMETERS, DEPSOP_TYPE_EXEC, NULL,
+ DEG_OPCODE_PLACEHOLDER, "Parameters Eval");
+}
+
+/* Cameras */
+void DepsgraphNodeBuilder::build_camera(Object *ob)
+{
+ /* TODO: Link scene-camera links in somehow... */
+ Camera *cam = (Camera *)ob->data;
+ ID *camera_id = &cam->id;
+ if (camera_id->flag & LIB_DOIT) {
+ return;
+ }
+
+ build_animdata(&cam->id);
+
+ add_operation_node(camera_id, DEPSNODE_TYPE_PARAMETERS, DEPSOP_TYPE_EXEC, NULL,
+ DEG_OPCODE_PLACEHOLDER, "Parameters Eval");
+
+ if (cam->dof_ob != NULL) {
+ /* TODO(sergey): For now parametrs are on object level. */
+ add_operation_node(&ob->id, DEPSNODE_TYPE_PARAMETERS,
+ DEPSOP_TYPE_EXEC, NULL,
+ DEG_OPCODE_PLACEHOLDER,
+ "Camera DOF");
+ }
+}
+
+/* Lamps */
+void DepsgraphNodeBuilder::build_lamp(Object *ob)
+{
+ Lamp *la = (Lamp *)ob->data;
+ ID *lamp_id = &la->id;
+ if (lamp_id->flag & LIB_DOIT) {
+ return;
+ }
+
+ build_animdata(&la->id);
+
+ /* node for obdata */
+ ComponentDepsNode *param_node = add_component_node(lamp_id, DEPSNODE_TYPE_PARAMETERS);
+
+ /* TODO(sergey): Is it really how we're supposed to work with drivers? */
+ add_operation_node(lamp_id, DEPSNODE_TYPE_PARAMETERS, DEPSOP_TYPE_EXEC, NULL,
+ DEG_OPCODE_PLACEHOLDER, "Parameters Eval");
+
+ /* lamp's nodetree */
+ if (la->nodetree) {
+ build_nodetree(param_node, la->nodetree);
+ }
+
+ /* textures */
+ build_texture_stack(param_node, la->mtex);
+}
+
+void DepsgraphNodeBuilder::build_nodetree(DepsNode *owner_node, bNodeTree *ntree)
+{
+ if (!ntree)
+ return;
+
+ /* nodetree itself */
+ ID *ntree_id = &ntree->id;
+
+ build_animdata(ntree_id);
+
+ /* Parameters for drivers. */
+ add_operation_node(ntree_id, DEPSNODE_TYPE_PARAMETERS, DEPSOP_TYPE_EXEC, NULL,
+ DEG_OPCODE_PLACEHOLDER, "Parameters Eval");
+
+ /* nodetree's nodes... */
+ for (bNode *bnode = (bNode *)ntree->nodes.first; bnode; bnode = bnode->next) {
+ if (bnode->id) {
+ if (GS(bnode->id->name) == ID_MA) {
+ build_material(owner_node, (Material *)bnode->id);
+ }
+ else if (bnode->type == ID_TE) {
+ build_texture(owner_node, (Tex *)bnode->id);
+ }
+ else if (bnode->type == NODE_GROUP) {
+ bNodeTree *ntree = (bNodeTree *)bnode->id;
+ if ((ntree_id->flag & LIB_DOIT) == 0) {
+ build_nodetree(owner_node, ntree);
+ }
+ }
+ }
+ }
+
+ // TODO: link from nodetree to owner_component?
+}
+
+/* Recursively build graph for material */
+void DepsgraphNodeBuilder::build_material(DepsNode *owner_node, Material *ma)
+{
+ ID *ma_id = &ma->id;
+ if (ma_id->flag & LIB_DOIT) {
+ return;
+ }
+
+ /* material itself */
+ add_id_node(ma_id);
+
+ add_operation_node(ma_id, DEPSNODE_TYPE_SHADING,
+ DEPSOP_TYPE_EXEC, NULL,
+ DEG_OPCODE_PLACEHOLDER, "Material Update");
+
+ /* material animation */
+ build_animdata(ma_id);
+
+ /* textures */
+ build_texture_stack(owner_node, ma->mtex);
+
+ /* material's nodetree */
+ build_nodetree(owner_node, ma->nodetree);
+}
+
+/* Texture-stack attached to some shading datablock */
+void DepsgraphNodeBuilder::build_texture_stack(DepsNode *owner_node, MTex **texture_stack)
+{
+ int i;
+
+ /* for now assume that all texture-stacks have same number of max items */
+ for (i = 0; i < MAX_MTEX; i++) {
+ MTex *mtex = texture_stack[i];
+ if (mtex && mtex->tex)
+ build_texture(owner_node, mtex->tex);
+ }
+}
+
+/* Recursively build graph for texture */
+void DepsgraphNodeBuilder::build_texture(DepsNode *owner_node, Tex *tex)
+{
+ ID *tex_id = &tex->id;
+ if (tex_id->flag & LIB_DOIT) {
+ return;
+ }
+ tex_id->flag |= LIB_DOIT;
+ /* texture itself */
+ build_animdata(tex_id);
+ /* texture's nodetree */
+ build_nodetree(owner_node, tex->nodetree);
+}
+
+void DepsgraphNodeBuilder::build_compositor(Scene *scene)
+{
+ /* For now, just a plain wrapper? */
+ // TODO: create compositing component?
+ // XXX: component type undefined!
+ //graph->get_node(&scene->id, NULL, DEPSNODE_TYPE_COMPOSITING, NULL);
+
+ /* for now, nodetrees are just parameters; compositing occurs in internals of renderer... */
+ ComponentDepsNode *owner_node = add_component_node(&scene->id, DEPSNODE_TYPE_PARAMETERS);
+ build_nodetree(owner_node, scene->nodetree);
+}
+
+void DepsgraphNodeBuilder::build_gpencil(bGPdata *gpd)
+{
+ ID *gpd_id = &gpd->id;
+
+ /* gpencil itself */
+ // XXX: what about multiple users of same datablock? This should only get added once
+ add_id_node(gpd_id);
+
+ /* The main reason Grease Pencil is included here is because the animation (and drivers)
+ * need to be hosted somewhere...
+ */
+ build_animdata(gpd_id);
+}
diff --git a/source/blender/depsgraph/intern/depsgraph_build_relations.cc b/source/blender/depsgraph/intern/depsgraph_build_relations.cc
new file mode 100644
index 00000000000..c348adaaf53
--- /dev/null
+++ b/source/blender/depsgraph/intern/depsgraph_build_relations.cc
@@ -0,0 +1,1880 @@
+/*
+ * ***** 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.
+ *
+ * Original Author: Joshua Leung
+ * Contributor(s): Based on original depsgraph.c code - Blender Foundation (2005-2013)
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/depsgraph/intern/depsgraph_build_relations.cc
+ * \ingroup depsgraph
+ *
+ * Methods for constructing depsgraph
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "MEM_guardedalloc.h"
+
+extern "C" {
+#include "BLI_blenlib.h"
+#include "BLI_string.h"
+#include "BLI_utildefines.h"
+
+#include "DNA_action_types.h"
+#include "DNA_anim_types.h"
+#include "DNA_armature_types.h"
+#include "DNA_camera_types.h"
+#include "DNA_constraint_types.h"
+#include "DNA_curve_types.h"
+#include "DNA_effect_types.h"
+#include "DNA_gpencil_types.h"
+#include "DNA_group_types.h"
+#include "DNA_key_types.h"
+#include "DNA_lamp_types.h"
+#include "DNA_material_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_meta_types.h"
+#include "DNA_node_types.h"
+#include "DNA_particle_types.h"
+#include "DNA_object_types.h"
+#include "DNA_rigidbody_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_texture_types.h"
+#include "DNA_world_types.h"
+
+#include "BKE_action.h"
+#include "BKE_armature.h"
+#include "BKE_animsys.h"
+#include "BKE_constraint.h"
+#include "BKE_curve.h"
+#include "BKE_effect.h"
+#include "BKE_fcurve.h"
+#include "BKE_group.h"
+#include "BKE_key.h"
+#include "BKE_library.h"
+#include "BKE_main.h"
+#include "BKE_material.h"
+#include "BKE_mball.h"
+#include "BKE_modifier.h"
+#include "BKE_node.h"
+#include "BKE_object.h"
+#include "BKE_particle.h"
+#include "BKE_rigidbody.h"
+#include "BKE_sound.h"
+#include "BKE_texture.h"
+#include "BKE_tracking.h"
+#include "BKE_world.h"
+
+#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_build.h"
+
+#include "RNA_access.h"
+#include "RNA_types.h"
+} /* extern "C" */
+
+#include "depsnode.h"
+#include "depsnode_component.h"
+#include "depsnode_operation.h"
+#include "depsgraph_build.h"
+#include "depsgraph_debug.h"
+#include "depsgraph_intern.h"
+#include "depsgraph_types.h"
+
+#include "depsgraph_util_pchanmap.h"
+
+/* ***************** */
+/* Relations Builder */
+
+/* **** General purpose functions **** */
+
+RNAPathKey::RNAPathKey(ID *id, const char *path) :
+ id(id)
+{
+ /* create ID pointer for root of path lookup */
+ PointerRNA id_ptr;
+ RNA_id_pointer_create(id, &id_ptr);
+ /* try to resolve path... */
+ int index;
+ if (!RNA_path_resolve_full(&id_ptr, path, &this->ptr, &this->prop, &index)) {
+ this->ptr = PointerRNA_NULL;
+ this->prop = NULL;
+ }
+}
+
+DepsgraphRelationBuilder::DepsgraphRelationBuilder(Depsgraph *graph) :
+ m_graph(graph)
+{
+}
+
+RootDepsNode *DepsgraphRelationBuilder::find_node(const RootKey &key) const
+{
+ (void)key;
+ BLI_assert(!"Doesn't seem to be correct");
+ return m_graph->root_node;
+}
+
+TimeSourceDepsNode *DepsgraphRelationBuilder::find_node(
+ const TimeSourceKey &key) const
+{
+ if (key.id) {
+ /* XXX TODO */
+ return NULL;
+ }
+ else {
+ return m_graph->root_node->time_source;
+ }
+}
+
+ComponentDepsNode *DepsgraphRelationBuilder::find_node(
+ const ComponentKey &key) const
+{
+ IDDepsNode *id_node = m_graph->find_id_node(key.id);
+ if (!id_node) {
+ fprintf(stderr, "find_node component: Could not find ID %s\n",
+ (key.id != NULL) ? key.id->name : "<null>");
+ return NULL;
+ }
+
+ ComponentDepsNode *node = id_node->find_component(key.type, key.name);
+ return node;
+}
+
+OperationDepsNode *DepsgraphRelationBuilder::find_node(
+ const OperationKey &key) const
+{
+ IDDepsNode *id_node = m_graph->find_id_node(key.id);
+ if (!id_node) {
+ fprintf(stderr, "find_node operation: Could not find ID\n");
+ return NULL;
+ }
+
+ ComponentDepsNode *comp_node = id_node->find_component(key.component_type,
+ key.component_name);
+ if (!comp_node) {
+ fprintf(stderr, "find_node operation: Could not find component\n");
+ return NULL;
+ }
+
+ OperationDepsNode *op_node = comp_node->find_operation(key.opcode, key.name);
+ if (!op_node) {
+ fprintf(stderr, "find_node_operation: Failed for (%s, '%s')\n",
+ DEG_OPNAMES[key.opcode], key.name.c_str());
+ }
+ return op_node;
+}
+
+DepsNode *DepsgraphRelationBuilder::find_node(const RNAPathKey &key) const
+{
+ return m_graph->find_node_from_pointer(&key.ptr, key.prop);
+}
+
+OperationDepsNode *DepsgraphRelationBuilder::has_node(
+ const OperationKey &key) const
+{
+ IDDepsNode *id_node = m_graph->find_id_node(key.id);
+ if (!id_node) {
+ return NULL;
+ }
+ ComponentDepsNode *comp_node = id_node->find_component(key.component_type,
+ key.component_name);
+ if (!comp_node) {
+ return NULL;
+ }
+ return comp_node->has_operation(key.opcode, key.name);
+}
+
+void DepsgraphRelationBuilder::add_time_relation(TimeSourceDepsNode *timesrc,
+ DepsNode *node_to,
+ const char *description)
+{
+ if (timesrc && node_to) {
+ m_graph->add_new_relation(timesrc, node_to, DEPSREL_TYPE_TIME, description);
+ }
+ else {
+ DEG_DEBUG_PRINTF("add_time_relation(%p = %s, %p = %s, %s) Failed\n",
+ timesrc, (timesrc) ? timesrc->identifier().c_str() : "<None>",
+ node_to, (node_to) ? node_to->identifier().c_str() : "<None>",
+ description);
+ }
+}
+
+void DepsgraphRelationBuilder::add_operation_relation(
+ OperationDepsNode *node_from,
+ OperationDepsNode *node_to,
+ eDepsRelation_Type type,
+ const char *description)
+{
+ if (node_from && node_to) {
+ m_graph->add_new_relation(node_from, node_to, type, description);
+ }
+ else {
+ DEG_DEBUG_PRINTF("add_operation_relation(%p = %s, %p = %s, %d, %s) Failed\n",
+ node_from, (node_from) ? node_from->identifier().c_str() : "<None>",
+ node_to, (node_to) ? node_to->identifier().c_str() : "<None>",
+ type, description);
+ }
+}
+
+/* **** Functions to build relations between entities **** */
+
+void DepsgraphRelationBuilder::build_scene(Main *bmain, Scene *scene)
+{
+ /* LIB_DOIT is used to indicate whether node for given ID was already
+ * created or not.
+ */
+ BKE_main_id_tag_all(bmain, false);
+
+ if (scene->set) {
+ // TODO: link set to scene, especially our timesource...
+ }
+
+ /* scene objects */
+ for (Base *base = (Base *)scene->base.first; base; base = base->next) {
+ Object *ob = base->object;
+
+ /* object itself */
+ build_object(bmain, scene, ob);
+
+ /* object that this is a proxy for */
+ if (ob->proxy) {
+ build_object(bmain, scene, ob->proxy);
+ /* TODO(sergey): This is an inverted relation, matches old depsgraph
+ * behavior and need to be investigated if it still need to be inverted.
+ */
+ ComponentKey ob_pose_key(&ob->id, DEPSNODE_TYPE_EVAL_POSE);
+ ComponentKey proxy_pose_key(&ob->proxy->id, DEPSNODE_TYPE_EVAL_POSE);
+ add_relation(ob_pose_key, proxy_pose_key, DEPSREL_TYPE_TRANSFORM, "Proxy");
+ }
+
+ /* Object dupligroup. */
+ if (ob->dup_group) {
+ build_group(bmain, scene, ob, ob->dup_group);
+ }
+ }
+
+ /* rigidbody */
+ if (scene->rigidbody_world) {
+ build_rigidbody(scene);
+ }
+
+ /* scene's animation and drivers */
+ if (scene->adt) {
+ build_animdata(&scene->id);
+ }
+
+ /* world */
+ if (scene->world) {
+ build_world(scene->world);
+ }
+
+ /* compo nodes */
+ if (scene->nodetree) {
+ build_compositor(scene);
+ }
+
+ /* grease pencil */
+ if (scene->gpd) {
+ build_gpencil(&scene->id, scene->gpd);
+ }
+}
+
+void DepsgraphRelationBuilder::build_group(Main *bmain,
+ Scene *scene,
+ Object *object,
+ Group *group)
+{
+ ID *group_id = &group->id;
+ bool group_done = (group_id->flag & LIB_DOIT) != 0;
+ OperationKey object_local_transform_key(&object->id,
+ DEPSNODE_TYPE_TRANSFORM,
+ DEG_OPCODE_TRANSFORM_LOCAL);
+ for (GroupObject *go = (GroupObject *)group->gobject.first;
+ go != NULL;
+ go = go->next)
+ {
+ if (!group_done) {
+ build_object(bmain, scene, go->ob);
+ }
+ ComponentKey dupli_transform_key(&go->ob->id, DEPSNODE_TYPE_TRANSFORM);
+ add_relation(dupli_transform_key,
+ object_local_transform_key,
+ DEPSREL_TYPE_TRANSFORM,
+ "Dupligroup");
+ }
+ group_id->flag |= LIB_DOIT;
+}
+
+void DepsgraphRelationBuilder::build_object(Main *bmain, Scene *scene, Object *ob)
+{
+ if (ob->id.flag & LIB_DOIT) {
+ return;
+ }
+
+ /* Object Transforms */
+ eDepsOperation_Code base_op = (ob->parent) ? DEG_OPCODE_TRANSFORM_PARENT : DEG_OPCODE_TRANSFORM_LOCAL;
+ OperationKey base_op_key(&ob->id, DEPSNODE_TYPE_TRANSFORM, base_op);
+
+ OperationKey local_transform_key(&ob->id, DEPSNODE_TYPE_TRANSFORM, DEG_OPCODE_TRANSFORM_LOCAL);
+ OperationKey parent_transform_key(&ob->id, DEPSNODE_TYPE_TRANSFORM, DEG_OPCODE_TRANSFORM_PARENT);
+ OperationKey final_transform_key(&ob->id, DEPSNODE_TYPE_TRANSFORM, DEG_OPCODE_TRANSFORM_FINAL);
+
+ OperationKey ob_ubereval_key(&ob->id, DEPSNODE_TYPE_TRANSFORM, DEG_OPCODE_OBJECT_UBEREVAL);
+
+ /* parenting */
+ if (ob->parent) {
+ /* parent relationship */
+ build_object_parent(ob);
+
+ /* local -> parent */
+ add_relation(local_transform_key, parent_transform_key, DEPSREL_TYPE_COMPONENT_ORDER, "[ObLocal -> ObParent]");
+ }
+
+ /* object constraints */
+ if (ob->constraints.first) {
+ OperationKey constraint_key(&ob->id, DEPSNODE_TYPE_TRANSFORM, DEG_OPCODE_TRANSFORM_CONSTRAINTS);
+
+ /* constraint relations */
+ // TODO: provide base op
+ // XXX: this is broken
+ build_constraints(scene, &ob->id, DEPSNODE_TYPE_TRANSFORM, "", &ob->constraints, NULL);
+
+ /* operation order */
+ add_relation(base_op_key, constraint_key, DEPSREL_TYPE_COMPONENT_ORDER, "[ObBase-> Constraint Stack]");
+ add_relation(constraint_key, final_transform_key, DEPSREL_TYPE_COMPONENT_ORDER, "[ObConstraints -> Done]");
+
+ // XXX
+ add_relation(constraint_key, ob_ubereval_key, DEPSREL_TYPE_COMPONENT_ORDER, "Temp Ubereval");
+ add_relation(ob_ubereval_key, final_transform_key, DEPSREL_TYPE_COMPONENT_ORDER, "Temp Ubereval");
+ }
+ else {
+ /* operation order */
+ add_relation(base_op_key, final_transform_key, DEPSREL_TYPE_COMPONENT_ORDER, "Object Transform");
+
+ // XXX
+ add_relation(base_op_key, ob_ubereval_key, DEPSREL_TYPE_COMPONENT_ORDER, "Temp Ubereval");
+ add_relation(ob_ubereval_key, final_transform_key, DEPSREL_TYPE_COMPONENT_ORDER, "Temp Ubereval");
+ }
+
+
+ /* AnimData */
+ build_animdata(&ob->id);
+
+ // XXX: This should be hooked up by the build_animdata code
+ if (ob->adt && (ob->adt->action || ob->adt->nla_tracks.first)) {
+ ComponentKey adt_key(&ob->id, DEPSNODE_TYPE_ANIMATION);
+ add_relation(adt_key, local_transform_key, DEPSREL_TYPE_OPERATION, "Object Animation");
+ }
+
+
+ /* object data */
+ if (ob->data) {
+ ID *obdata_id = (ID *)ob->data;
+
+ /* ob data animation */
+ build_animdata(obdata_id);
+
+ /* type-specific data... */
+ switch (ob->type) {
+ case OB_MESH: /* Geometry */
+ case OB_CURVE:
+ case OB_FONT:
+ case OB_SURF:
+ case OB_MBALL:
+ case OB_LATTICE:
+ {
+ build_obdata_geom(bmain, scene, ob);
+ break;
+ }
+
+
+ case OB_ARMATURE: /* Pose */
+ if (ob->id.lib != NULL && ob->proxy_from != NULL) {
+ build_proxy_rig(ob);
+ }
+ else {
+ build_rig(scene, ob);
+ }
+ break;
+
+ case OB_LAMP: /* Lamp */
+ build_lamp(ob);
+ break;
+
+ case OB_CAMERA: /* Camera */
+ build_camera(ob);
+ break;
+ }
+
+ Key *key = BKE_key_from_object(ob);
+ if (key != NULL) {
+ ComponentKey geometry_key((ID *)ob->data, DEPSNODE_TYPE_GEOMETRY);
+ ComponentKey key_key(&key->id, DEPSNODE_TYPE_GEOMETRY);
+ add_relation(key_key, geometry_key, DEPSREL_TYPE_GEOMETRY_EVAL, "Shapekeys");
+ }
+ }
+
+ /* particle systems */
+ if (ob->particlesystem.first) {
+ build_particles(scene, ob);
+ }
+
+ /* grease pencil */
+ if (ob->gpd) {
+ build_gpencil(&ob->id, ob->gpd);
+ }
+}
+
+void DepsgraphRelationBuilder::build_object_parent(Object *ob)
+{
+ /* XXX: for now, need to use the component key (not just direct to the parent op), or else the matrix doesn't get reset */
+ // XXX: @sergey - it would be good if we got that backwards flushing working when tagging for updates
+ //OperationKey ob_key(&ob->id, DEPSNODE_TYPE_TRANSFORM, DEG_OPCODE_TRANSFORM_PARENT);
+ ComponentKey ob_key(&ob->id, DEPSNODE_TYPE_TRANSFORM);
+
+ /* type-specific links */
+ switch (ob->partype) {
+ case PARSKEL: /* Armature Deform (Virtual Modifier) */
+ {
+ ComponentKey parent_key(&ob->parent->id, DEPSNODE_TYPE_TRANSFORM);
+ add_relation(parent_key, ob_key, DEPSREL_TYPE_STANDARD, "Armature Deform Parent");
+ break;
+ }
+
+ case PARVERT1: /* Vertex Parent */
+ case PARVERT3:
+ {
+ ComponentKey parent_key(&ob->parent->id, DEPSNODE_TYPE_GEOMETRY);
+ add_relation(parent_key, ob_key, DEPSREL_TYPE_GEOMETRY_EVAL, "Vertex Parent");
+ /* XXX not sure what this is for or how you could be done properly - lukas */
+ //parent_node->customdata_mask |= CD_MASK_ORIGINDEX;
+
+ ComponentKey transform_key(&ob->parent->id, DEPSNODE_TYPE_TRANSFORM);
+ add_relation(transform_key, ob_key, DEPSREL_TYPE_TRANSFORM, "Vertex Parent TFM");
+ break;
+ }
+
+ case PARBONE: /* Bone Parent */
+ {
+ ComponentKey parent_key(&ob->parent->id, DEPSNODE_TYPE_BONE, ob->parsubstr);
+ add_relation(parent_key, ob_key, DEPSREL_TYPE_TRANSFORM, "Bone Parent");
+ break;
+ }
+
+ default:
+ {
+ if (ob->parent->type == OB_LATTICE) {
+ /* Lattice Deform Parent - Virtual Modifier */
+ // XXX: no virtual modifiers should be left!
+ ComponentKey parent_key(&ob->parent->id, DEPSNODE_TYPE_TRANSFORM);
+ ComponentKey geom_key(&ob->parent->id, DEPSNODE_TYPE_GEOMETRY);
+
+ add_relation(parent_key, ob_key, DEPSREL_TYPE_STANDARD, "Lattice Deform Parent");
+ add_relation(geom_key, ob_key, DEPSREL_TYPE_STANDARD, "Lattice Deform Parent Geom");
+ }
+ else if (ob->parent->type == OB_CURVE) {
+ Curve *cu = (Curve *)ob->parent->data;
+
+ if (cu->flag & CU_PATH) {
+ /* Follow Path */
+ ComponentKey parent_key(&ob->parent->id, DEPSNODE_TYPE_GEOMETRY);
+ add_relation(parent_key, ob_key, DEPSREL_TYPE_TRANSFORM, "Curve Follow Parent");
+
+ ComponentKey transform_key(&ob->parent->id, DEPSNODE_TYPE_TRANSFORM);
+ add_relation(transform_key, ob_key, DEPSREL_TYPE_TRANSFORM, "Curve Follow TFM");
+ }
+ else {
+ /* Standard Parent */
+ ComponentKey parent_key(&ob->parent->id, DEPSNODE_TYPE_TRANSFORM);
+ add_relation(parent_key, ob_key, DEPSREL_TYPE_TRANSFORM, "Curve Parent");
+ }
+ }
+ else {
+ /* Standard Parent */
+ ComponentKey parent_key(&ob->parent->id, DEPSNODE_TYPE_TRANSFORM);
+ add_relation(parent_key, ob_key, DEPSREL_TYPE_TRANSFORM, "Parent");
+ }
+ break;
+ }
+ }
+
+ /* exception case: parent is duplivert */
+ if ((ob->type == OB_MBALL) && (ob->parent->transflag & OB_DUPLIVERTS)) {
+ //dag_add_relation(dag, node2, node, DAG_RL_DATA_DATA | DAG_RL_OB_OB, "Duplivert");
+ }
+}
+
+void DepsgraphRelationBuilder::build_constraints(Scene *scene, ID *id, eDepsNode_Type component_type, const char *component_subdata,
+ ListBase *constraints, RootPChanMap *root_map)
+{
+ OperationKey constraint_op_key(id, component_type, component_subdata,
+ (component_type == DEPSNODE_TYPE_BONE) ? DEG_OPCODE_BONE_CONSTRAINTS : DEG_OPCODE_TRANSFORM_CONSTRAINTS);
+
+ /* add dependencies for each constraint in turn */
+ for (bConstraint *con = (bConstraint *)constraints->first; con; con = con->next) {
+ const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
+
+ /* invalid constraint type... */
+ if (cti == NULL)
+ continue;
+
+ /* special case for camera tracking -- it doesn't use targets to define relations */
+ // TODO: we can now represent dependencies in a much richer manner, so review how this is done...
+ if (ELEM(cti->type, CONSTRAINT_TYPE_FOLLOWTRACK, CONSTRAINT_TYPE_CAMERASOLVER, CONSTRAINT_TYPE_OBJECTSOLVER)) {
+ bool depends_on_camera = false;
+
+ if (cti->type == CONSTRAINT_TYPE_FOLLOWTRACK) {
+ bFollowTrackConstraint *data = (bFollowTrackConstraint *)con->data;
+
+ if (((data->clip) || (data->flag & FOLLOWTRACK_ACTIVECLIP)) && data->track[0])
+ depends_on_camera = true;
+
+ if (data->depth_ob) {
+ // DAG_RL_DATA_OB | DAG_RL_OB_OB
+ ComponentKey depth_key(&data->depth_ob->id, DEPSNODE_TYPE_TRANSFORM);
+ add_relation(depth_key, constraint_op_key, DEPSREL_TYPE_TRANSFORM, cti->name);
+ }
+ }
+ else if (cti->type == CONSTRAINT_TYPE_OBJECTSOLVER) {
+ depends_on_camera = true;
+ }
+
+ if (depends_on_camera && scene->camera) {
+ // DAG_RL_DATA_OB | DAG_RL_OB_OB
+ ComponentKey camera_key(&scene->camera->id, DEPSNODE_TYPE_TRANSFORM);
+ add_relation(camera_key, constraint_op_key, DEPSREL_TYPE_TRANSFORM, cti->name);
+ }
+
+ /* tracker <-> constraints */
+ // FIXME: actually motionclip dependency on results of motionclip block here...
+ //dag_add_relation(dag, scenenode, node, DAG_RL_SCENE, "Scene Relation");
+ }
+ else if (cti->get_constraint_targets) {
+ ListBase targets = {NULL, NULL};
+ cti->get_constraint_targets(con, &targets);
+
+ for (bConstraintTarget *ct = (bConstraintTarget *)targets.first; ct; ct = ct->next) {
+ if (!ct->tar)
+ continue;
+
+ if (ELEM(con->type, CONSTRAINT_TYPE_KINEMATIC, CONSTRAINT_TYPE_SPLINEIK)) {
+ /* ignore IK constraints - these are handled separately (on pose level) */
+ }
+ else if (ELEM(con->type, CONSTRAINT_TYPE_FOLLOWPATH, CONSTRAINT_TYPE_CLAMPTO)) {
+ /* these constraints require path geometry data... */
+ ComponentKey target_key(&ct->tar->id, DEPSNODE_TYPE_GEOMETRY);
+ add_relation(target_key, constraint_op_key, DEPSREL_TYPE_GEOMETRY_EVAL, cti->name); // XXX: type = geom_transform
+ // TODO: path dependency
+ }
+ else if ((ct->tar->type == OB_ARMATURE) && (ct->subtarget[0])) {
+ /* bone */
+ if (&ct->tar->id == id) {
+ /* same armature */
+ eDepsOperation_Code target_key_opcode;
+
+ /* Using "done" here breaks in-chain deps, while using "ready" here breaks most production rigs instead...
+ * So, we do a compromise here, and only do this when an IK chain conflict may occur
+ */
+ if (root_map->has_common_root(component_subdata, ct->subtarget)) {
+ target_key_opcode = DEG_OPCODE_BONE_READY;
+ }
+ else {
+ target_key_opcode = DEG_OPCODE_BONE_DONE;
+ }
+
+ OperationKey target_key(&ct->tar->id, DEPSNODE_TYPE_BONE, ct->subtarget, target_key_opcode);
+ add_relation(target_key, constraint_op_key, DEPSREL_TYPE_TRANSFORM, cti->name);
+ }
+ else {
+ /* different armature - we can safely use the result of that */
+ OperationKey target_key(&ct->tar->id, DEPSNODE_TYPE_BONE, ct->subtarget, DEG_OPCODE_BONE_DONE);
+ add_relation(target_key, constraint_op_key, DEPSREL_TYPE_TRANSFORM, cti->name);
+ }
+ }
+ else if (ELEM(ct->tar->type, OB_MESH, OB_LATTICE) && (ct->subtarget[0])) {
+ /* vertex group */
+ /* NOTE: for now, we don't need to represent vertex groups separately... */
+ ComponentKey target_key(&ct->tar->id, DEPSNODE_TYPE_GEOMETRY);
+ add_relation(target_key, constraint_op_key, DEPSREL_TYPE_GEOMETRY_EVAL, cti->name);
+
+ if (ct->tar->type == OB_MESH) {
+ //node2->customdata_mask |= CD_MASK_MDEFORMVERT;
+ }
+ }
+ else if (con->type == CONSTRAINT_TYPE_SHRINKWRAP) {
+ /* Constraints which requires the target object surface. */
+ ComponentKey target_key(&ct->tar->id, DEPSNODE_TYPE_GEOMETRY);
+ add_relation(target_key, constraint_op_key, DEPSREL_TYPE_TRANSFORM, cti->name);
+
+ /* NOTE: obdata eval now doesn't necessarily depend on the object's transform... */
+ ComponentKey target_transform_key(&ct->tar->id, DEPSNODE_TYPE_TRANSFORM);
+ add_relation(target_transform_key, constraint_op_key, DEPSREL_TYPE_TRANSFORM, cti->name);
+ }
+ else {
+ /* standard object relation */
+ // TODO: loc vs rot vs scale?
+ if (&ct->tar->id == id) {
+ /* Constraint targetting own object:
+ * - This case is fine IFF we're dealing with a bone constraint pointing to
+ * its own armature. In that case, it's just transform -> bone.
+ * - If however it is a real self targetting case, just make it depend on the
+ * previous constraint (or the pre-constraint state)...
+ */
+ if ((ct->tar->type == OB_ARMATURE) && (component_type == DEPSNODE_TYPE_BONE)) {
+ OperationKey target_key(&ct->tar->id, DEPSNODE_TYPE_TRANSFORM, DEG_OPCODE_TRANSFORM_FINAL);
+ add_relation(target_key, constraint_op_key, DEPSREL_TYPE_TRANSFORM, cti->name);
+ }
+ else {
+ OperationKey target_key(&ct->tar->id, DEPSNODE_TYPE_TRANSFORM, DEG_OPCODE_TRANSFORM_LOCAL);
+ add_relation(target_key, constraint_op_key, DEPSREL_TYPE_TRANSFORM, cti->name);
+ }
+ }
+ else {
+ /* normal object dependency */
+ OperationKey target_key(&ct->tar->id, DEPSNODE_TYPE_TRANSFORM, DEG_OPCODE_TRANSFORM_FINAL);
+ add_relation(target_key, constraint_op_key, DEPSREL_TYPE_TRANSFORM, cti->name);
+ }
+ }
+
+ /* Constraints which needs world's matrix for transform.
+ * TODO(sergey): More constraints here?
+ */
+ if (ELEM(con->type,
+ CONSTRAINT_TYPE_ROTLIKE,
+ CONSTRAINT_TYPE_SIZELIKE,
+ CONSTRAINT_TYPE_LOCLIKE,
+ CONSTRAINT_TYPE_TRANSLIKE))
+ {
+ /* TODO(sergey): Add used space check. */
+ ComponentKey target_transform_key(&ct->tar->id, DEPSNODE_TYPE_TRANSFORM);
+ add_relation(target_transform_key, constraint_op_key, DEPSREL_TYPE_TRANSFORM, cti->name);
+ }
+
+ }
+
+ if (cti->flush_constraint_targets)
+ cti->flush_constraint_targets(con, &targets, 1);
+ }
+ }
+}
+
+void DepsgraphRelationBuilder::build_animdata(ID *id)
+{
+ AnimData *adt = BKE_animdata_from_id(id);
+
+ if (adt == NULL)
+ return;
+
+ ComponentKey adt_key(id, DEPSNODE_TYPE_ANIMATION);
+
+ /* animation */
+ if (adt->action || adt->nla_tracks.first) {
+ /* wire up dependency to time source */
+ TimeSourceKey time_src_key;
+ add_relation(time_src_key, adt_key, DEPSREL_TYPE_TIME, "[TimeSrc -> Animation]");
+
+ // XXX: Hook up specific update callbacks for special properties which may need it...
+
+ // XXX: animdata "hierarchy" - top-level overrides need to go after lower-down
+ }
+
+ /* drivers */
+ for (FCurve *fcu = (FCurve *)adt->drivers.first; fcu; fcu = fcu->next) {
+ OperationKey driver_key(id, DEPSNODE_TYPE_PARAMETERS, DEG_OPCODE_DRIVER, deg_fcurve_id_name(fcu));
+
+ /* create the driver's relations to targets */
+ build_driver(id, fcu);
+
+ /* prevent driver from occurring before own animation... */
+ if (adt->action || adt->nla_tracks.first) {
+ add_relation(adt_key, driver_key, DEPSREL_TYPE_OPERATION,
+ "[AnimData Before Drivers]");
+ }
+ }
+}
+
+void DepsgraphRelationBuilder::build_driver(ID *id, FCurve *fcu)
+{
+ ChannelDriver *driver = fcu->driver;
+ OperationKey driver_key(id, DEPSNODE_TYPE_PARAMETERS, DEG_OPCODE_DRIVER, deg_fcurve_id_name(fcu));
+ bPoseChannel *pchan = NULL;
+
+ /* create dependency between driver and data affected by it */
+ /* - direct property relationship... */
+ //RNAPathKey affected_key(id, fcu->rna_path);
+ //add_relation(driver_key, affected_key, DEPSREL_TYPE_DRIVER, "[Driver -> Data] DepsRel");
+
+ /* driver -> data components (for interleaved evaluation - bones/constraints/modifiers) */
+ // XXX: this probably should probably be moved out into a separate function
+ if (strstr(fcu->rna_path, "pose.bones[") != NULL) {
+ /* interleaved drivers during bone eval */
+ // TODO: ideally, if this is for a constraint, it goes to said constraint
+ Object *ob = (Object *)id;
+ char *bone_name;
+
+ bone_name = BLI_str_quoted_substrN(fcu->rna_path, "pose.bones[");
+ pchan = BKE_pose_channel_find_name(ob->pose, bone_name);
+
+ if (bone_name) {
+ MEM_freeN(bone_name);
+ bone_name = NULL;
+ }
+
+ if (pchan) {
+ OperationKey bone_key(id, DEPSNODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_LOCAL);
+ add_relation(driver_key, bone_key, DEPSREL_TYPE_DRIVER, "[Driver -> Bone]");
+ }
+ else {
+ fprintf(stderr,
+ "Couldn't find bone name for driver path - '%s'\n",
+ fcu->rna_path);
+ }
+ }
+ else if (GS(id->name) == ID_AR && strstr(fcu->rna_path, "bones[")) {
+ /* drivers on armature-level bone settings (i.e. bbone stuff),
+ * which will affect the evaluation of corresponding pose bones
+ */
+ IDDepsNode *arm_node = m_graph->find_id_node(id);
+ char *bone_name = BLI_str_quoted_substrN(fcu->rna_path, "bones[");
+
+ if (arm_node && bone_name) {
+ /* find objects which use this, and make their eval callbacks depend on this */
+ DEPSNODE_RELATIONS_ITER_BEGIN(arm_node->outlinks, rel)
+ {
+ IDDepsNode *to_node = (IDDepsNode *)rel->to;
+
+ /* we only care about objects with pose data which use this... */
+ if (GS(to_node->id->name) == ID_OB) {
+ Object *ob = (Object *)to_node->id;
+ bPoseChannel *pchan = BKE_pose_channel_find_name(ob->pose, bone_name); // NOTE: ob->pose may be NULL
+
+ if (pchan) {
+ OperationKey bone_key(&ob->id, DEPSNODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_LOCAL);
+ add_relation(driver_key, bone_key, DEPSREL_TYPE_DRIVER, "[Arm Bone -> Driver -> Bone]");
+ }
+ }
+ }
+ DEPSNODE_RELATIONS_ITER_END;
+
+ /* free temp data */
+ MEM_freeN(bone_name);
+ bone_name = NULL;
+ }
+ else {
+ fprintf(stderr,
+ "Couldn't find armature bone name for driver path - '%s'\n",
+ fcu->rna_path);
+ }
+ }
+ else if (GS(id->name) == ID_OB && strstr(fcu->rna_path, "modifiers[")) {
+ /* modifier driver - connect directly to the modifier */
+ char *modifier_name = BLI_str_quoted_substrN(fcu->rna_path, "modifiers[");
+ if (modifier_name) {
+ OperationKey modifier_key(id,
+ DEPSNODE_TYPE_GEOMETRY,
+ DEG_OPCODE_GEOMETRY_MODIFIER,
+ modifier_name);
+ if (has_node(modifier_key)) {
+ add_relation(driver_key, modifier_key, DEPSREL_TYPE_DRIVER, "[Driver -> Modifier]");
+ }
+ else {
+ printf("Unexisting driver RNA path: %s\n", fcu->rna_path);
+ }
+
+ MEM_freeN(modifier_name);
+ }
+ }
+ else if (GS(id->name) == ID_KE && strstr(fcu->rna_path, "key_blocks[")) {
+ /* shape key driver - hook into the base geometry operation */
+ // XXX: double check where this points
+ Key *shape_key = (Key *)id;
+
+ ComponentKey geometry_key(shape_key->from, DEPSNODE_TYPE_GEOMETRY);
+ add_relation(driver_key, geometry_key, DEPSREL_TYPE_DRIVER, "[Driver -> ShapeKey Geom]");
+ }
+ else if (strstr(fcu->rna_path, "key_blocks[")) {
+ ComponentKey geometry_key(id, DEPSNODE_TYPE_GEOMETRY);
+ add_relation(driver_key, geometry_key, DEPSREL_TYPE_DRIVER, "[Driver -> ShapeKey Geom]");
+ }
+ else {
+ if (GS(id->name) == ID_OB) {
+ /* assume that driver affects a transform... */
+ OperationKey local_transform_key(id, DEPSNODE_TYPE_TRANSFORM, DEG_OPCODE_TRANSFORM_LOCAL);
+ add_relation(driver_key, local_transform_key, DEPSREL_TYPE_OPERATION, "[Driver -> Transform]");
+ }
+ else if (GS(id->name) == ID_KE) {
+ ComponentKey geometry_key(id, DEPSNODE_TYPE_GEOMETRY);
+ add_relation(driver_key, geometry_key, DEPSREL_TYPE_GEOMETRY_EVAL, "[Driver -> Shapekey Geometry]");
+ }
+ }
+
+ /* ensure that affected prop's update callbacks will be triggered once done */
+ // TODO: implement this once the functionality to add these links exists in RNA
+ // XXX: the data itself could also set this, if it were to be truly initialised later?
+
+ /* loop over variables to get the target relationships */
+ for (DriverVar *dvar = (DriverVar *)driver->variables.first; dvar; dvar = dvar->next) {
+ /* only used targets */
+ DRIVER_TARGETS_USED_LOOPER(dvar)
+ {
+ if (dtar->id == NULL)
+ continue;
+
+ /* special handling for directly-named bones */
+ if ((dtar->flag & DTAR_FLAG_STRUCT_REF) && (dtar->pchan_name[0])) {
+ Object *ob = (Object *)dtar->id;
+ bPoseChannel *target_pchan = BKE_pose_channel_find_name(ob->pose, dtar->pchan_name);
+ if (target_pchan != NULL) {
+ /* get node associated with bone */
+ // XXX: watch the space!
+ /* Some cases can't use final bone transform, for example:
+ * - Driving the bone with itself (addressed here)
+ * - Relations inside an IK chain (TODO?)
+ */
+ if (dtar->id == id &&
+ pchan != NULL &&
+ STREQ(pchan->name, target_pchan->name))
+ {
+ continue;
+ }
+ OperationKey target_key(dtar->id, DEPSNODE_TYPE_BONE, target_pchan->name, DEG_OPCODE_BONE_DONE);
+ add_relation(target_key, driver_key, DEPSREL_TYPE_DRIVER_TARGET, "[Bone Target -> Driver]");
+ }
+ }
+ else if (dtar->flag & DTAR_FLAG_STRUCT_REF) {
+ /* get node associated with the object's transforms */
+ OperationKey target_key(dtar->id, DEPSNODE_TYPE_TRANSFORM, DEG_OPCODE_TRANSFORM_FINAL);
+ add_relation(target_key, driver_key, DEPSREL_TYPE_DRIVER_TARGET, "[Target -> Driver]");
+ }
+ else if (dtar->rna_path && strstr(dtar->rna_path, "pose.bones[")) {
+ /* workaround for ensuring that local bone transforms don't end up
+ * having to wait for pose eval to finish (to prevent cycles)
+ */
+ Object *ob = (Object *)dtar->id;
+ char *bone_name = BLI_str_quoted_substrN(dtar->rna_path, "pose.bones[");
+ bPoseChannel *target_pchan = BKE_pose_channel_find_name(ob->pose, bone_name);
+ if (bone_name) {
+ MEM_freeN(bone_name);
+ bone_name = NULL;
+ }
+ if (target_pchan) {
+ if (dtar->id == id &&
+ pchan != NULL &&
+ STREQ(pchan->name, target_pchan->name))
+ {
+ continue;
+ }
+ OperationKey bone_key(dtar->id, DEPSNODE_TYPE_BONE, target_pchan->name, DEG_OPCODE_BONE_LOCAL);
+ add_relation(bone_key, driver_key, DEPSREL_TYPE_DRIVER, "[RNA Bone -> Driver]");
+ }
+ }
+ else {
+ /* resolve path to get node */
+ RNAPathKey target_key(dtar->id, dtar->rna_path ? dtar->rna_path : "");
+ add_relation(target_key, driver_key, DEPSREL_TYPE_DRIVER_TARGET, "[RNA Target -> Driver]");
+ }
+ }
+ DRIVER_TARGETS_LOOPER_END
+ }
+
+ /* It's quite tricky to detect if the driver actually depends on time or not,
+ * so for now we'll be quite conservative here about optimization and consider
+ * all python drivers to be depending on time.
+ */
+ if (driver->type == DRIVER_TYPE_PYTHON) {
+ TimeSourceKey time_src_key;
+ add_relation(time_src_key, driver_key, DEPSREL_TYPE_TIME, "[TimeSrc -> Driver]");
+ }
+}
+
+void DepsgraphRelationBuilder::build_world(World *world)
+{
+ ID *world_id = &world->id;
+ if (world_id->flag & LIB_DOIT) {
+ return;
+ }
+ world_id->flag |= LIB_DOIT;
+
+ build_animdata(world_id);
+
+ /* TODO: other settings? */
+
+ /* textures */
+ build_texture_stack(world_id, world->mtex);
+
+ /* world's nodetree */
+ build_nodetree(world_id, world->nodetree);
+}
+
+void DepsgraphRelationBuilder::build_rigidbody(Scene *scene)
+{
+ RigidBodyWorld *rbw = scene->rigidbody_world;
+
+ OperationKey init_key(&scene->id, DEPSNODE_TYPE_TRANSFORM, DEG_OPCODE_RIGIDBODY_REBUILD);
+ OperationKey sim_key(&scene->id, DEPSNODE_TYPE_TRANSFORM, DEG_OPCODE_RIGIDBODY_SIM);
+
+ /* rel between the two sim-nodes */
+ add_relation(init_key, sim_key, DEPSREL_TYPE_OPERATION, "Rigidbody [Init -> SimStep]");
+
+ /* set up dependencies between these operations and other builtin nodes --------------- */
+
+ /* time dependency */
+ TimeSourceKey time_src_key;
+ add_relation(time_src_key, init_key, DEPSREL_TYPE_TIME, "TimeSrc -> Rigidbody Reset/Rebuild (Optional)");
+ add_relation(time_src_key, sim_key, DEPSREL_TYPE_TIME, "TimeSrc -> Rigidbody Sim Step");
+
+ /* objects - simulation participants */
+ if (rbw->group) {
+ for (GroupObject *go = (GroupObject *)rbw->group->gobject.first; go; go = go->next) {
+ Object *ob = go->ob;
+ if (!ob || ob->type != OB_MESH)
+ continue;
+
+ /* hook up evaluation order...
+ * 1) flushing rigidbody results follows base transforms being applied
+ * 2) rigidbody flushing can only be performed after simulation has been run
+ *
+ * 3) simulation needs to know base transforms to figure out what to do
+ * XXX: there's probably a difference between passive and active
+ * - passive don't change, so may need to know full transform...
+ */
+ OperationKey rbo_key(&ob->id, DEPSNODE_TYPE_TRANSFORM, DEG_OPCODE_TRANSFORM_RIGIDBODY);
+
+ eDepsOperation_Code trans_opcode = ob->parent ? DEG_OPCODE_TRANSFORM_PARENT : DEG_OPCODE_TRANSFORM_LOCAL;
+ OperationKey trans_op(&ob->id, DEPSNODE_TYPE_TRANSFORM, trans_opcode);
+
+ add_relation(trans_op, rbo_key, DEPSREL_TYPE_OPERATION, "Base Ob Transform -> RBO Sync");
+ add_relation(sim_key, rbo_key, DEPSREL_TYPE_COMPONENT_ORDER, "Rigidbody Sim Eval -> RBO Sync");
+
+ /* if constraints exist, those depend on the result of the rigidbody sim
+ * - This allows constraints to modify the result of the sim (i.e. clamping)
+ * while still allowing the sim to depend on some changes to the objects.
+ * Also, since constraints are hooked up to the final nodes, this link
+ * means that we can also fit in there too...
+ * - Later, it might be good to include a constraint in the stack allowing us
+ * to control whether rigidbody eval gets interleaved into the constraint stack
+ */
+ if (ob->constraints.first) {
+ OperationKey constraint_key(&ob->id, DEPSNODE_TYPE_TRANSFORM, DEG_OPCODE_TRANSFORM_CONSTRAINTS);
+ add_relation(rbo_key, constraint_key, DEPSREL_TYPE_COMPONENT_ORDER, "RBO Sync -> Ob Constraints");
+ }
+ else {
+ /* final object transform depends on rigidbody */
+ OperationKey done_key(&ob->id, DEPSNODE_TYPE_TRANSFORM, DEG_OPCODE_TRANSFORM_FINAL);
+ add_relation(rbo_key, done_key, DEPSREL_TYPE_COMPONENT_ORDER, "RBO Sync -> Done");
+
+ // XXX: ubereval will be removed eventually, but we still need it in the meantime
+ OperationKey uber_key(&ob->id, DEPSNODE_TYPE_TRANSFORM, DEG_OPCODE_OBJECT_UBEREVAL);
+ add_relation(rbo_key, uber_key, DEPSREL_TYPE_COMPONENT_ORDER, "RBO Sync -> Uber (Temp)");
+ }
+
+
+ /* needed to get correct base values */
+ add_relation(trans_op, sim_key, DEPSREL_TYPE_OPERATION, "Base Ob Transform -> Rigidbody Sim Eval");
+ }
+ }
+
+ /* constraints */
+ if (rbw->constraints) {
+ for (GroupObject *go = (GroupObject *)rbw->constraints->gobject.first; go; go = go->next) {
+ Object *ob = go->ob;
+ if (!ob || !ob->rigidbody_constraint)
+ continue;
+
+ RigidBodyCon *rbc = ob->rigidbody_constraint;
+
+ /* final result of the constraint object's transform controls how the
+ * constraint affects the physics sim for these objects
+ */
+ ComponentKey trans_key(&ob->id, DEPSNODE_TYPE_TRANSFORM);
+ OperationKey ob1_key(&rbc->ob1->id, DEPSNODE_TYPE_TRANSFORM, DEG_OPCODE_TRANSFORM_RIGIDBODY);
+ OperationKey ob2_key(&rbc->ob2->id, DEPSNODE_TYPE_TRANSFORM, DEG_OPCODE_TRANSFORM_RIGIDBODY);
+
+ /* - constrained-objects sync depends on the constraint-holder */
+ add_relation(trans_key, ob1_key, DEPSREL_TYPE_TRANSFORM, "RigidBodyConstraint -> RBC.Object_1");
+ add_relation(trans_key, ob2_key, DEPSREL_TYPE_TRANSFORM, "RigidBodyConstraint -> RBC.Object_2");
+
+ /* - ensure that sim depends on this constraint's transform */
+ add_relation(trans_key, sim_key, DEPSREL_TYPE_TRANSFORM, "RigidBodyConstraint Transform -> RB Simulation");
+ }
+ }
+}
+
+void DepsgraphRelationBuilder::build_particles(Scene *scene, Object *ob)
+{
+ TimeSourceKey time_src_key;
+ OperationKey obdata_ubereval_key(&ob->id,
+ DEPSNODE_TYPE_GEOMETRY,
+ DEG_OPCODE_GEOMETRY_UBEREVAL);
+
+ /* particle systems */
+ for (ParticleSystem *psys = (ParticleSystem *)ob->particlesystem.first; psys; psys = psys->next) {
+ ParticleSettings *part = psys->part;
+
+ /* particle settings */
+ build_animdata(&part->id);
+
+ /* this particle system */
+ OperationKey psys_key(&ob->id, DEPSNODE_TYPE_EVAL_PARTICLES, DEG_OPCODE_PSYS_EVAL, psys->name);
+
+ /* XXX: if particle system is later re-enabled, we must do full rebuild? */
+ if (!psys_check_enabled(ob, psys))
+ continue;
+
+ /* TODO(sergey): Are all particle systems depends on time?
+ * Hair without dynamics i.e.
+ */
+ add_relation(time_src_key, psys_key,
+ DEPSREL_TYPE_TIME,
+ "TimeSrc -> PSys");
+
+ /* TODO(sergey): Currently particle update is just a placeholder,
+ * hook it to the ubereval node so particle system is getting updated
+ * on playback.
+ */
+ add_relation(psys_key,
+ obdata_ubereval_key,
+ DEPSREL_TYPE_OPERATION,
+ "PSys -> UberEval");
+
+#if 0
+ if (ELEM(part->phystype, PART_PHYS_KEYED, PART_PHYS_BOIDS)) {
+ ParticleTarget *pt;
+
+ for (pt = psys->targets.first; pt; pt = pt->next) {
+ if (pt->ob && BLI_findlink(&pt->ob->particlesystem, pt->psys - 1)) {
+ node2 = dag_get_node(dag, pt->ob);
+ dag_add_relation(dag, node2, node, DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Particle Targets");
+ }
+ }
+ }
+
+ if (part->ren_as == PART_DRAW_OB && part->dup_ob) {
+ node2 = dag_get_node(dag, part->dup_ob);
+ /* note that this relation actually runs in the wrong direction, the problem
+ * is that dupli system all have this (due to parenting), and the render
+ * engine instancing assumes particular ordering of objects in list */
+ dag_add_relation(dag, node, node2, DAG_RL_OB_OB, "Particle Object Visualization");
+ if (part->dup_ob->type == OB_MBALL)
+ dag_add_relation(dag, node, node2, DAG_RL_DATA_DATA, "Particle Object Visualization");
+ }
+
+ if (part->ren_as == PART_DRAW_GR && part->dup_group) {
+ for (go = part->dup_group->gobject.first; go; go = go->next) {
+ node2 = dag_get_node(dag, go->ob);
+ dag_add_relation(dag, node2, node, DAG_RL_OB_OB, "Particle Group Visualization");
+ }
+ }
+#endif
+
+ /* effectors */
+ ListBase *effectors = pdInitEffectors(scene, ob, psys, part->effector_weights, false);
+
+ if (effectors) {
+ for (EffectorCache *eff = (EffectorCache *)effectors->first; eff; eff = eff->next) {
+ if (eff->psys) {
+ // XXX: DAG_RL_DATA_DATA | DAG_RL_OB_DATA
+ ComponentKey eff_key(&eff->ob->id, DEPSNODE_TYPE_GEOMETRY); // xxx: particles instead?
+ add_relation(eff_key, psys_key, DEPSREL_TYPE_STANDARD, "Particle Field");
+ }
+ }
+ }
+
+ pdEndEffectors(&effectors);
+
+ /* boids */
+ if (part->boids) {
+ BoidRule *rule = NULL;
+ BoidState *state = NULL;
+
+ for (state = (BoidState *)part->boids->states.first; state; state = state->next) {
+ for (rule = (BoidRule *)state->rules.first; rule; rule = rule->next) {
+ Object *ruleob = NULL;
+ if (rule->type == eBoidRuleType_Avoid)
+ ruleob = ((BoidRuleGoalAvoid *)rule)->ob;
+ else if (rule->type == eBoidRuleType_FollowLeader)
+ ruleob = ((BoidRuleFollowLeader *)rule)->ob;
+
+ if (ruleob) {
+ ComponentKey ruleob_key(&ruleob->id, DEPSNODE_TYPE_TRANSFORM);
+ add_relation(ruleob_key, psys_key, DEPSREL_TYPE_TRANSFORM, "Boid Rule");
+ }
+ }
+ }
+ }
+ }
+
+ /* pointcache */
+ // TODO...
+}
+
+/* IK Solver Eval Steps */
+void DepsgraphRelationBuilder::build_ik_pose(Object *ob,
+ bPoseChannel *pchan,
+ bConstraint *con,
+ RootPChanMap *root_map)
+{
+ bKinematicConstraint *data = (bKinematicConstraint *)con->data;
+
+ /* attach owner to IK Solver too
+ * - assume that owner is always part of chain
+ * - see notes on direction of rel below...
+ */
+ bPoseChannel *rootchan = BKE_armature_ik_solver_find_root(pchan, data);
+ OperationKey solver_key(&ob->id, DEPSNODE_TYPE_EVAL_POSE, rootchan->name, DEG_OPCODE_POSE_IK_SOLVER);
+
+ /* IK target */
+ // XXX: this should get handled as part of the constraint code
+ if (data->tar != NULL) {
+ /* TODO(sergey): For until we'll store partial matricies in the depsgraph,
+ * we create dependency between target object and pose eval component.
+ *
+ * This way we ensuring the whole subtree is updated from scratch without
+ * need of intermediate matricies. This is an overkill, but good enough for
+ * testing IK solver.
+ */
+ // FIXME: geometry targets...
+ ComponentKey pose_key(&ob->id, DEPSNODE_TYPE_EVAL_POSE);
+ if ((data->tar->type == OB_ARMATURE) && (data->subtarget[0])) {
+ /* TODO(sergey): This is only for until granular update stores intermediate result. */
+ if (data->tar != ob) {
+ /* different armature - can just read the results */
+ ComponentKey target_key(&data->tar->id, DEPSNODE_TYPE_BONE, data->subtarget);
+ add_relation(target_key, pose_key, DEPSREL_TYPE_TRANSFORM, con->name);
+ }
+ else {
+ /* same armature - we'll use the ready state only, just in case this bone is in the chain we're solving */
+ OperationKey target_key(&data->tar->id, DEPSNODE_TYPE_BONE, data->subtarget, DEG_OPCODE_BONE_DONE);
+ add_relation(target_key, solver_key, DEPSREL_TYPE_TRANSFORM, con->name);
+ }
+ }
+ else if (ELEM(data->tar->type, OB_MESH, OB_LATTICE) && (data->subtarget[0])) {
+ /* vertex group target */
+ /* NOTE: for now, we don't need to represent vertex groups separately... */
+ ComponentKey target_key(&data->tar->id, DEPSNODE_TYPE_GEOMETRY);
+ add_relation(target_key, solver_key, DEPSREL_TYPE_GEOMETRY_EVAL, con->name);
+
+ if (data->tar->type == OB_MESH) {
+ //node2->customdata_mask |= CD_MASK_MDEFORMVERT;
+ }
+ }
+ else {
+ /* Standard Object Target */
+ ComponentKey target_key(&data->tar->id, DEPSNODE_TYPE_TRANSFORM);
+ add_relation(target_key, pose_key, DEPSREL_TYPE_TRANSFORM, con->name);
+ }
+
+ if ((data->tar == ob) && (data->subtarget[0])) {
+ /* Prevent target's constraints from linking to anything from same
+ * chain that it controls.
+ */
+ root_map->add_bone(data->subtarget, rootchan->name);
+ }
+ }
+
+ /* Pole Target */
+ // XXX: this should get handled as part of the constraint code
+ if (data->poletar != NULL) {
+ if ((data->poletar->type == OB_ARMATURE) && (data->polesubtarget[0])) {
+ // XXX: same armature issues - ready vs done?
+ ComponentKey target_key(&data->poletar->id, DEPSNODE_TYPE_BONE, data->subtarget);
+ add_relation(target_key, solver_key, DEPSREL_TYPE_TRANSFORM, con->name);
+ }
+ else if (ELEM(data->poletar->type, OB_MESH, OB_LATTICE) && (data->subtarget[0])) {
+ /* vertex group target */
+ /* NOTE: for now, we don't need to represent vertex groups separately... */
+ ComponentKey target_key(&data->poletar->id, DEPSNODE_TYPE_GEOMETRY);
+ add_relation(target_key, solver_key, DEPSREL_TYPE_GEOMETRY_EVAL, con->name);
+
+ if (data->poletar->type == OB_MESH) {
+ //node2->customdata_mask |= CD_MASK_MDEFORMVERT;
+ }
+ }
+ else {
+ ComponentKey target_key(&data->poletar->id, DEPSNODE_TYPE_TRANSFORM);
+ add_relation(target_key, solver_key, DEPSREL_TYPE_TRANSFORM, con->name);
+ }
+ }
+
+ DEG_DEBUG_PRINTF("\nStarting IK Build: pchan = %s, target = (%s, %s), segcount = %d\n",
+ pchan->name, data->tar->id.name, data->subtarget, data->rootbone);
+
+ bPoseChannel *parchan = pchan;
+ /* exclude tip from chain? */
+ if (!(data->flag & CONSTRAINT_IK_TIP)) {
+ OperationKey tip_transforms_key(&ob->id, DEPSNODE_TYPE_BONE,
+ parchan->name, DEG_OPCODE_BONE_LOCAL);
+ add_relation(solver_key, tip_transforms_key,
+ DEPSREL_TYPE_TRANSFORM, "IK Solver Result");
+ parchan = pchan->parent;
+ }
+
+ root_map->add_bone(parchan->name, rootchan->name);
+
+ OperationKey parchan_transforms_key(&ob->id, DEPSNODE_TYPE_BONE,
+ parchan->name, DEG_OPCODE_BONE_READY);
+ add_relation(parchan_transforms_key, solver_key,
+ DEPSREL_TYPE_TRANSFORM, "IK Solver Owner");
+
+ /* Walk to the chain's root */
+ //size_t segcount = 0;
+ int segcount = 0;
+
+ while (parchan) {
+ /* Make IK-solver dependent on this bone's result,
+ * since it can only run after the standard results
+ * of the bone are know. Validate links step on the
+ * bone will ensure that users of this bone only
+ * grab the result with IK solver results...
+ */
+ if (parchan != pchan) {
+ OperationKey parent_key(&ob->id, DEPSNODE_TYPE_BONE, parchan->name, DEG_OPCODE_BONE_READY);
+ add_relation(parent_key, solver_key, DEPSREL_TYPE_TRANSFORM, "IK Chain Parent");
+
+ OperationKey done_key(&ob->id, DEPSNODE_TYPE_BONE, parchan->name, DEG_OPCODE_BONE_DONE);
+ add_relation(solver_key, done_key, DEPSREL_TYPE_TRANSFORM, "IK Chain Result");
+ }
+ parchan->flag |= POSE_DONE;
+
+ OperationKey final_transforms_key(&ob->id, DEPSNODE_TYPE_BONE, parchan->name, DEG_OPCODE_BONE_DONE);
+ add_relation(solver_key, final_transforms_key, DEPSREL_TYPE_TRANSFORM, "IK Solver Result");
+
+ root_map->add_bone(parchan->name, rootchan->name);
+
+ /* continue up chain, until we reach target number of items... */
+ DEG_DEBUG_PRINTF(" %d = %s\n", segcount, parchan->name);
+ segcount++;
+ if ((segcount == data->rootbone) || (segcount > 255)) break; /* 255 is weak */
+
+ parchan = parchan->parent;
+ }
+
+ OperationKey flush_key(&ob->id, DEPSNODE_TYPE_EVAL_POSE, DEG_OPCODE_POSE_DONE);
+ add_relation(solver_key, flush_key, DEPSREL_TYPE_OPERATION, "PoseEval Result-Bone Link");
+}
+
+/* Spline IK Eval Steps */
+void DepsgraphRelationBuilder::build_splineik_pose(Object *ob,
+ bPoseChannel *pchan,
+ bConstraint *con,
+ RootPChanMap *root_map)
+{
+ bSplineIKConstraint *data = (bSplineIKConstraint *)con->data;
+ bPoseChannel *rootchan = BKE_armature_splineik_solver_find_root(pchan, data);
+ OperationKey transforms_key(&ob->id, DEPSNODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_READY);
+ OperationKey solver_key(&ob->id, DEPSNODE_TYPE_EVAL_POSE, rootchan->name, DEG_OPCODE_POSE_SPLINE_IK_SOLVER);
+
+ /* attach owner to IK Solver too
+ * - assume that owner is always part of chain
+ * - see notes on direction of rel below...
+ */
+ add_relation(transforms_key, solver_key, DEPSREL_TYPE_TRANSFORM, "Spline IK Solver Owner");
+
+ /* attach path dependency to solver */
+ if (data->tar) {
+ /* TODO(sergey): For until we'll store partial matricies in the depsgraph,
+ * we create dependency between target object and pose eval component.
+ * See IK pose for a bit more information.
+ */
+ // TODO: the bigggest point here is that we need the curve PATH and not just the general geometry...
+ ComponentKey target_key(&data->tar->id, DEPSNODE_TYPE_GEOMETRY);
+ ComponentKey pose_key(&ob->id, DEPSNODE_TYPE_EVAL_POSE);
+ add_relation(target_key, pose_key, DEPSREL_TYPE_TRANSFORM, "[Curve.Path -> Spline IK] DepsRel");
+ }
+
+ pchan->flag |= POSE_DONE;
+ OperationKey final_transforms_key(&ob->id, DEPSNODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_DONE);
+ add_relation(solver_key, final_transforms_key, DEPSREL_TYPE_TRANSFORM, "Spline IK Result");
+
+ root_map->add_bone(pchan->name, rootchan->name);
+
+ /* Walk to the chain's root */
+ //size_t segcount = 0;
+ int segcount = 0;
+
+ for (bPoseChannel *parchan = pchan->parent; parchan; parchan = parchan->parent) {
+ /* Make Spline IK solver dependent on this bone's result,
+ * since it can only run after the standard results
+ * of the bone are know. Validate links step on the
+ * bone will ensure that users of this bone only
+ * grab the result with IK solver results...
+ */
+ if (parchan != pchan) {
+ OperationKey parent_key(&ob->id, DEPSNODE_TYPE_BONE, parchan->name, DEG_OPCODE_BONE_READY);
+ add_relation(parent_key, solver_key, DEPSREL_TYPE_TRANSFORM, "Spline IK Solver Update");
+
+ OperationKey done_key(&ob->id, DEPSNODE_TYPE_BONE, parchan->name, DEG_OPCODE_BONE_DONE);
+ add_relation(solver_key, done_key, DEPSREL_TYPE_TRANSFORM, "IK Chain Result");
+ }
+ parchan->flag |= POSE_DONE;
+
+ OperationKey final_transforms_key(&ob->id, DEPSNODE_TYPE_BONE, parchan->name, DEG_OPCODE_BONE_DONE);
+ add_relation(solver_key, final_transforms_key, DEPSREL_TYPE_TRANSFORM, "Spline IK Solver Result");
+
+ root_map->add_bone(parchan->name, rootchan->name);
+
+ /* continue up chain, until we reach target number of items... */
+ segcount++;
+ if ((segcount == data->chainlen) || (segcount > 255)) break; /* 255 is weak */
+ }
+
+ OperationKey flush_key(&ob->id, DEPSNODE_TYPE_EVAL_POSE, DEG_OPCODE_POSE_DONE);
+ add_relation(solver_key, flush_key, DEPSREL_TYPE_OPERATION, "PoseEval Result-Bone Link");
+}
+
+/* Pose/Armature Bones Graph */
+void DepsgraphRelationBuilder::build_rig(Scene *scene, Object *ob)
+{
+ /* Armature-Data */
+ // TODO: selection status?
+
+ /* attach links between pose operations */
+ OperationKey init_key(&ob->id, DEPSNODE_TYPE_EVAL_POSE, DEG_OPCODE_POSE_INIT);
+ OperationKey flush_key(&ob->id, DEPSNODE_TYPE_EVAL_POSE, DEG_OPCODE_POSE_DONE);
+
+ add_relation(init_key, flush_key, DEPSREL_TYPE_COMPONENT_ORDER, "[Pose Init -> Pose Cleanup]");
+
+ if (ob->adt && (ob->adt->action || ob->adt->nla_tracks.first)) {
+ ComponentKey animation_key(&ob->id, DEPSNODE_TYPE_ANIMATION);
+ add_relation(animation_key, init_key, DEPSREL_TYPE_OPERATION, "Rig Animation");
+ }
+
+ /* IK Solvers...
+ * - These require separate processing steps are pose-level
+ * to be executed between chains of bones (i.e. once the
+ * base transforms of a bunch of bones is done)
+ *
+ * - We build relations for these before the dependencies
+ * between ops in the same component as it is necessary
+ * to check whether such bones are in the same IK chain
+ * (or else we get weird issues with either in-chain
+ * references, or with bones being parented to IK'd bones)
+ *
+ * Unsolved Issues:
+ * - Care is needed to ensure that multi-headed trees work out the same as in ik-tree building
+ * - Animated chain-lengths are a problem...
+ */
+ RootPChanMap root_map;
+ bool pose_depends_on_local_transform = false;
+ for (bPoseChannel *pchan = (bPoseChannel *)ob->pose->chanbase.first; pchan; pchan = pchan->next) {
+ for (bConstraint *con = (bConstraint *)pchan->constraints.first; con; con = con->next) {
+ switch (con->type) {
+ case CONSTRAINT_TYPE_KINEMATIC:
+ build_ik_pose(ob, pchan, con, &root_map);
+ pose_depends_on_local_transform = true;
+ break;
+
+ case CONSTRAINT_TYPE_SPLINEIK:
+ build_splineik_pose(ob, pchan, con, &root_map);
+ pose_depends_on_local_transform = true;
+ break;
+
+ /* Constraints which needs world's matrix for transform.
+ * TODO(sergey): More constraints here?
+ */
+ case CONSTRAINT_TYPE_ROTLIKE:
+ case CONSTRAINT_TYPE_SIZELIKE:
+ case CONSTRAINT_TYPE_LOCLIKE:
+ case CONSTRAINT_TYPE_TRANSLIKE:
+ /* TODO(sergey): Add used space check. */
+ pose_depends_on_local_transform = true;
+ break;
+
+ default:
+ break;
+ }
+ }
+ }
+ //root_map.print_debug();
+
+ if (pose_depends_on_local_transform) {
+ /* TODO(sergey): Once partial updates are possible use relation between
+ * object transform and solver itself in it's build function.
+ */
+ ComponentKey pose_key(&ob->id, DEPSNODE_TYPE_EVAL_POSE);
+ ComponentKey local_transform_key(&ob->id, DEPSNODE_TYPE_TRANSFORM);
+ add_relation(local_transform_key, pose_key, DEPSREL_TYPE_TRANSFORM, "Local Transforms");
+ }
+
+
+ /* links between operations for each bone */
+ for (bPoseChannel *pchan = (bPoseChannel *)ob->pose->chanbase.first; pchan; pchan = pchan->next) {
+ OperationKey bone_local_key(&ob->id, DEPSNODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_LOCAL);
+ OperationKey bone_pose_key(&ob->id, DEPSNODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_POSE_PARENT);
+ OperationKey bone_ready_key(&ob->id, DEPSNODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_READY);
+ OperationKey bone_done_key(&ob->id, DEPSNODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_DONE);
+
+ pchan->flag &= ~POSE_DONE;
+
+ /* pose init to bone local */
+ add_relation(init_key, bone_local_key, DEPSREL_TYPE_OPERATION, "PoseEval Source-Bone Link");
+
+ /* local to pose parenting operation */
+ add_relation(bone_local_key, bone_pose_key, DEPSREL_TYPE_OPERATION, "Bone Local - PoseSpace Link");
+
+ /* parent relation */
+ if (pchan->parent != NULL) {
+ eDepsOperation_Code parent_key_opcode;
+
+ /* NOTE: this difference in handling allows us to prevent lockups while ensuring correct poses for separate chains */
+ if (root_map.has_common_root(pchan->name, pchan->parent->name)) {
+ parent_key_opcode = DEG_OPCODE_BONE_READY;
+ }
+ else {
+ parent_key_opcode = DEG_OPCODE_BONE_DONE;
+ }
+
+ OperationKey parent_key(&ob->id, DEPSNODE_TYPE_BONE, pchan->parent->name, parent_key_opcode);
+ add_relation(parent_key, bone_pose_key, DEPSREL_TYPE_TRANSFORM, "[Parent Bone -> Child Bone]");
+ }
+
+ /* constraints */
+ if (pchan->constraints.first != NULL) {
+ /* constraints stack and constraint dependencies */
+ build_constraints(scene, &ob->id, DEPSNODE_TYPE_BONE, pchan->name, &pchan->constraints, &root_map);
+
+ /* pose -> constraints */
+ OperationKey constraints_key(&ob->id, DEPSNODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_CONSTRAINTS);
+ add_relation(bone_pose_key, constraints_key, DEPSREL_TYPE_OPERATION, "Constraints Stack");
+
+ /* constraints -> ready */
+ // TODO: when constraint stack is exploded, this step should occur before the first IK solver
+ add_relation(constraints_key, bone_ready_key, DEPSREL_TYPE_OPERATION, "Constraints -> Ready");
+ }
+ else {
+ /* pose -> ready */
+ add_relation(bone_pose_key, bone_ready_key, DEPSREL_TYPE_OPERATION, "Pose -> Ready");
+ }
+
+ /* bone ready -> done
+ * NOTE: For bones without IK, this is all that's needed.
+ * For IK chains however, an additional rel is created from IK to done,
+ * with transitive reduction removing this one...
+ */
+ add_relation(bone_ready_key, bone_done_key, DEPSREL_TYPE_OPERATION, "Ready -> Done");
+
+ /* assume that all bones must be done for the pose to be ready (for deformers) */
+ add_relation(bone_done_key, flush_key, DEPSREL_TYPE_OPERATION, "PoseEval Result-Bone Link");
+ }
+}
+
+void DepsgraphRelationBuilder::build_proxy_rig(Object *ob)
+{
+ OperationKey pose_init_key(&ob->id, DEPSNODE_TYPE_EVAL_POSE, DEG_OPCODE_POSE_INIT);
+ OperationKey pose_done_key(&ob->id, DEPSNODE_TYPE_EVAL_POSE, DEG_OPCODE_POSE_DONE);
+ for (bPoseChannel *pchan = (bPoseChannel *)ob->pose->chanbase.first;
+ pchan != NULL;
+ pchan = pchan->next)
+ {
+ OperationKey bone_local_key(&ob->id, DEPSNODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_LOCAL);
+ OperationKey bone_ready_key(&ob->id, DEPSNODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_READY);
+ OperationKey bone_done_key(&ob->id, DEPSNODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_DONE);
+ add_relation(pose_init_key, bone_local_key, DEPSREL_TYPE_OPERATION, "Pose Init -> Bone Local");
+ add_relation(bone_local_key, bone_ready_key, DEPSREL_TYPE_OPERATION, "Local -> Ready");
+ add_relation(bone_ready_key, bone_done_key, DEPSREL_TYPE_OPERATION, "Ready -> Done");
+ add_relation(bone_done_key, pose_done_key, DEPSREL_TYPE_OPERATION, "Bone Done -> Pose Done");
+ }
+}
+
+/* Shapekeys */
+void DepsgraphRelationBuilder::build_shapekeys(ID *obdata, Key *key)
+{
+ ComponentKey obdata_key(obdata, DEPSNODE_TYPE_GEOMETRY);
+
+ /* attach animdata to geometry */
+ build_animdata(&key->id);
+
+ if (key->adt) {
+ // TODO: this should really be handled in build_animdata, since many of these cases will need it
+ if (key->adt->action || key->adt->nla_tracks.first) {
+ ComponentKey adt_key(&key->id, DEPSNODE_TYPE_ANIMATION);
+ add_relation(adt_key, obdata_key, DEPSREL_TYPE_OPERATION, "Animation");
+ }
+
+ /* NOTE: individual shapekey drivers are handled above already */
+ }
+
+ /* attach to geometry */
+ // XXX: aren't shapekeys now done as a pseudo-modifier on object?
+ //ComponentKey key_key(&key->id, DEPSNODE_TYPE_GEOMETRY); // FIXME: this doesn't exist
+ //add_relation(key_key, obdata_key, DEPSREL_TYPE_GEOMETRY_EVAL, "Shapekeys");
+}
+
+/**
+ * ObData Geometry Evaluation
+ * ==========================
+ *
+ * The evaluation of geometry on objects is as follows:
+ * - The actual evaluated of the derived geometry (e.g. DerivedMesh, DispList, etc.)
+ * occurs in the Geometry component of the object which references this. This includes
+ * modifiers, and the temporary "ubereval" for geometry.
+ * - Therefore, each user of a piece of shared geometry data ends up evaluating its own
+ * version of the stuff, complete with whatever modifiers it may use.
+ *
+ * - The datablocks for the geometry data - "obdata" (e.g. ID_ME, ID_CU, ID_LT, etc.) are used for
+ * 1) calculating the bounding boxes of the geometry data,
+ * 2) aggregating inward links from other objects (e.g. for text on curve, etc.)
+ * and also for the links coming from the shapekey datablocks
+ * - Animation/Drivers affecting the parameters of the geometry are made to trigger
+ * updates on the obdata geometry component, which then trigger downstream
+ * re-evaluation of the individual instances of this geometry.
+ */
+// TODO: Materials and lighting should probably get their own component, instead of being lumped under geometry?
+void DepsgraphRelationBuilder::build_obdata_geom(Main *bmain, Scene *scene, Object *ob)
+{
+ ID *obdata = (ID *)ob->data;
+
+ /* Init operation of object-level geometry evaluation. */
+ OperationKey geom_init_key(&ob->id, DEPSNODE_TYPE_GEOMETRY, DEG_OPCODE_PLACEHOLDER, "Eval Init");
+
+ /* get nodes for result of obdata's evaluation, and geometry evaluation on object */
+ ComponentKey obdata_geom_key(obdata, DEPSNODE_TYPE_GEOMETRY);
+ ComponentKey geom_key(&ob->id, DEPSNODE_TYPE_GEOMETRY);
+
+ /* link components to each other */
+ add_relation(obdata_geom_key, geom_key, DEPSREL_TYPE_DATABLOCK, "Object Geometry Base Data");
+
+ /* Modifiers */
+ if (ob->modifiers.first) {
+ ModifierData *md;
+ OperationKey prev_mod_key;
+
+ for (md = (ModifierData *)ob->modifiers.first; md; md = md->next) {
+ const ModifierTypeInfo *mti = modifierType_getInfo((ModifierType)md->type);
+ OperationKey mod_key(&ob->id, DEPSNODE_TYPE_GEOMETRY, DEG_OPCODE_GEOMETRY_MODIFIER, md->name);
+
+ if (md->prev) {
+ /* Stack relation: modifier depends on previous modifier in the stack */
+ add_relation(prev_mod_key, mod_key, DEPSREL_TYPE_GEOMETRY_EVAL, "Modifier Stack");
+ }
+ else {
+ /* Stack relation: first modifier depends on the geometry. */
+ add_relation(geom_init_key, mod_key, DEPSREL_TYPE_GEOMETRY_EVAL, "Modifier Stack");
+ }
+
+ if (mti->updateDepsgraph) {
+ DepsNodeHandle handle = create_node_handle(mod_key);
+ mti->updateDepsgraph(md, bmain, scene, ob, &handle);
+ }
+
+ if (BKE_object_modifier_use_time(ob, md)) {
+ TimeSourceKey time_src_key;
+ add_relation(time_src_key, mod_key, DEPSREL_TYPE_TIME, "Time Source");
+
+ /* Hacky fix for T45633 (Animated modifiers aren't updated)
+ *
+ * This check works because BKE_object_modifier_use_time() tests
+ * for either the modifier needing time, or that it is animated.
+ */
+ /* XXX: Remove this hack when these links are added as part of build_animdata() instead */
+ if (modifier_dependsOnTime(md) == false) {
+ ComponentKey animation_key(&ob->id, DEPSNODE_TYPE_ANIMATION);
+ add_relation(animation_key, mod_key, DEPSREL_TYPE_OPERATION, "Modifier Animation");
+ }
+ }
+
+ prev_mod_key = mod_key;
+ }
+ }
+
+ /* materials */
+ if (ob->totcol) {
+ int a;
+
+ for (a = 1; a <= ob->totcol; a++) {
+ Material *ma = give_current_material(ob, a);
+
+ if (ma)
+ build_material(&ob->id, ma);
+ }
+ }
+
+ /* geometry collision */
+ if (ELEM(ob->type, OB_MESH, OB_CURVE, OB_LATTICE)) {
+ // add geometry collider relations
+ }
+
+ /* Make sure uber update is the last in the dependencies.
+ *
+ * TODO(sergey): Get rid of this node.
+ */
+ if (ob->type != OB_ARMATURE) {
+ /* Armatures does no longer require uber node. */
+ OperationKey obdata_ubereval_key(&ob->id, DEPSNODE_TYPE_GEOMETRY, DEG_OPCODE_GEOMETRY_UBEREVAL);
+ if (ob->modifiers.last) {
+ ModifierData *md = (ModifierData *)ob->modifiers.last;
+ OperationKey mod_key(&ob->id, DEPSNODE_TYPE_GEOMETRY, DEG_OPCODE_GEOMETRY_MODIFIER, md->name);
+ add_relation(mod_key, obdata_ubereval_key, DEPSREL_TYPE_OPERATION, "Object Geometry UberEval");
+ }
+ else {
+ add_relation(geom_init_key, obdata_ubereval_key, DEPSREL_TYPE_OPERATION, "Object Geometry UberEval");
+ }
+ }
+
+ if (obdata->flag & LIB_DOIT) {
+ return;
+ }
+ obdata->flag |= LIB_DOIT;
+
+ /* Link object data evaluation node to exit operation. */
+ OperationKey obdata_geom_eval_key(obdata, DEPSNODE_TYPE_GEOMETRY, DEG_OPCODE_PLACEHOLDER, "Geometry Eval");
+ OperationKey obdata_geom_done_key(obdata, DEPSNODE_TYPE_GEOMETRY, DEG_OPCODE_PLACEHOLDER, "Eval Done");
+ add_relation(obdata_geom_eval_key, obdata_geom_done_key, DEPSREL_TYPE_DATABLOCK, "ObData Geom Eval Done");
+
+ /* type-specific node/links */
+ switch (ob->type) {
+ case OB_MESH:
+ break;
+
+ case OB_MBALL:
+ {
+ Object *mom = BKE_mball_basis_find(scene, ob);
+
+ /* motherball - mom depends on children! */
+ if (mom != ob) {
+ /* non-motherball -> cannot be directly evaluated! */
+ ComponentKey mom_key(&mom->id, DEPSNODE_TYPE_GEOMETRY);
+ add_relation(geom_key, mom_key, DEPSREL_TYPE_GEOMETRY_EVAL, "Metaball Motherball");
+ }
+ break;
+ }
+
+ case OB_CURVE:
+ case OB_FONT:
+ {
+ Curve *cu = (Curve *)obdata;
+
+ /* curve's dependencies */
+ // XXX: these needs geom data, but where is geom stored?
+ if (cu->bevobj) {
+ ComponentKey bevob_key(&cu->bevobj->id, DEPSNODE_TYPE_GEOMETRY);
+ add_relation(bevob_key, geom_key, DEPSREL_TYPE_GEOMETRY_EVAL, "Curve Bevel");
+ }
+ if (cu->taperobj) {
+ ComponentKey taperob_key(&cu->taperobj->id, DEPSNODE_TYPE_GEOMETRY);
+ add_relation(taperob_key, geom_key, DEPSREL_TYPE_GEOMETRY_EVAL, "Curve Taper");
+ }
+ if (ob->type == OB_FONT) {
+ if (cu->textoncurve) {
+ ComponentKey textoncurve_key(&cu->taperobj->id, DEPSNODE_TYPE_GEOMETRY);
+ add_relation(textoncurve_key, geom_key, DEPSREL_TYPE_GEOMETRY_EVAL, "Text on Curve");
+ }
+ }
+ break;
+ }
+
+ case OB_SURF: /* Nurbs Surface */
+ {
+ break;
+ }
+
+ case OB_LATTICE: /* Lattice */
+ {
+ break;
+ }
+ }
+
+ /* ShapeKeys */
+ Key *key = BKE_key_from_object(ob);
+ if (key) {
+ build_shapekeys(obdata, key);
+ }
+
+ if (needs_animdata_node(obdata)) {
+ ComponentKey animation_key(obdata, DEPSNODE_TYPE_ANIMATION);
+ ComponentKey parameters_key(obdata, DEPSNODE_TYPE_PARAMETERS);
+ add_relation(animation_key, parameters_key,
+ DEPSREL_TYPE_COMPONENT_ORDER, "Geom Parameters");
+ /* Evaluation usually depends on animation.
+ * TODO(sergey): Need to re-hook it after granular update is implemented..
+ */
+ add_relation(animation_key, obdata_geom_eval_key, DEPSREL_TYPE_GEOMETRY_EVAL, "Animation");
+ }
+}
+
+/* Cameras */
+// TODO: Link scene-camera links in somehow...
+void DepsgraphRelationBuilder::build_camera(Object *ob)
+{
+ Camera *cam = (Camera *)ob->data;
+ ID *camera_id = &cam->id;
+ if (camera_id->flag & LIB_DOIT) {
+ return;
+ }
+ camera_id->flag |= LIB_DOIT;
+
+ ComponentKey parameters_key(camera_id, DEPSNODE_TYPE_PARAMETERS);
+
+ if (needs_animdata_node(camera_id)) {
+ ComponentKey animation_key(camera_id, DEPSNODE_TYPE_ANIMATION);
+ add_relation(animation_key, parameters_key,
+ DEPSREL_TYPE_COMPONENT_ORDER, "Camera Parameters");
+ }
+
+ /* DOF */
+ if (cam->dof_ob) {
+ ComponentKey ob_param_key(&ob->id, DEPSNODE_TYPE_PARAMETERS);
+ ComponentKey dof_ob_key(&cam->dof_ob->id, DEPSNODE_TYPE_TRANSFORM);
+ add_relation(dof_ob_key, ob_param_key, DEPSREL_TYPE_TRANSFORM, "Camera DOF");
+ }
+}
+
+/* Lamps */
+void DepsgraphRelationBuilder::build_lamp(Object *ob)
+{
+ Lamp *la = (Lamp *)ob->data;
+ ID *lamp_id = &la->id;
+ if (lamp_id->flag & LIB_DOIT) {
+ return;
+ }
+ lamp_id->flag |= LIB_DOIT;
+
+ ComponentKey parameters_key(lamp_id, DEPSNODE_TYPE_PARAMETERS);
+
+ if (needs_animdata_node(lamp_id)) {
+ ComponentKey animation_key(lamp_id, DEPSNODE_TYPE_ANIMATION);
+ add_relation(animation_key, parameters_key,
+ DEPSREL_TYPE_COMPONENT_ORDER, "Lamp Parameters");
+ }
+
+ /* lamp's nodetree */
+ if (la->nodetree) {
+ build_nodetree(lamp_id, la->nodetree);
+ ComponentKey nodetree_key(&la->nodetree->id, DEPSNODE_TYPE_PARAMETERS);
+ add_relation(nodetree_key, parameters_key,
+ DEPSREL_TYPE_COMPONENT_ORDER, "NTree->Lamp Parameters");
+ }
+
+ /* textures */
+ build_texture_stack(lamp_id, la->mtex);
+}
+
+void DepsgraphRelationBuilder::build_nodetree(ID *owner, bNodeTree *ntree)
+{
+ if (!ntree)
+ return;
+
+ ID *ntree_id = &ntree->id;
+
+ build_animdata(ntree_id);
+
+ /* nodetree's nodes... */
+ for (bNode *bnode = (bNode *)ntree->nodes.first; bnode; bnode = bnode->next) {
+ if (bnode->id) {
+ if (GS(bnode->id->name) == ID_MA) {
+ build_material(owner, (Material *)bnode->id);
+ }
+ else if (bnode->type == ID_TE) {
+ build_texture(owner, (Tex *)bnode->id);
+ }
+ else if (bnode->type == NODE_GROUP) {
+ bNodeTree *ntree = (bNodeTree *)bnode->id;
+ if ((ntree_id->flag & LIB_DOIT) == 0) {
+ build_nodetree(owner, ntree);
+ ntree_id->flag |= LIB_DOIT;
+ }
+ }
+ }
+ }
+
+ if (needs_animdata_node(ntree_id)) {
+ ComponentKey parameters_key(ntree_id, DEPSNODE_TYPE_PARAMETERS);
+ ComponentKey animation_key(ntree_id, DEPSNODE_TYPE_ANIMATION);
+ add_relation(animation_key, parameters_key,
+ DEPSREL_TYPE_COMPONENT_ORDER, "NTree Parameters");
+ }
+
+ // TODO: link from nodetree to owner_component?
+}
+
+/* Recursively build graph for material */
+void DepsgraphRelationBuilder::build_material(ID *owner, Material *ma)
+{
+ ID *ma_id = &ma->id;
+ if (ma_id->flag & LIB_DOIT) {
+ return;
+ }
+ ma_id->flag |= LIB_DOIT;
+
+ /* animation */
+ build_animdata(ma_id);
+
+ /* textures */
+ build_texture_stack(owner, ma->mtex);
+
+ /* material's nodetree */
+ build_nodetree(owner, ma->nodetree);
+}
+
+/* Recursively build graph for texture */
+void DepsgraphRelationBuilder::build_texture(ID *owner, Tex *tex)
+{
+ ID *tex_id = &tex->id;
+ if (tex_id->flag & LIB_DOIT) {
+ return;
+ }
+ tex_id->flag |= LIB_DOIT;
+
+ /* texture itself */
+ build_animdata(tex_id);
+
+ /* texture's nodetree */
+ build_nodetree(owner, tex->nodetree);
+}
+
+/* Texture-stack attached to some shading datablock */
+void DepsgraphRelationBuilder::build_texture_stack(ID *owner, MTex **texture_stack)
+{
+ int i;
+
+ /* for now assume that all texture-stacks have same number of max items */
+ for (i = 0; i < MAX_MTEX; i++) {
+ MTex *mtex = texture_stack[i];
+ if (mtex && mtex->tex)
+ build_texture(owner, mtex->tex);
+ }
+}
+
+void DepsgraphRelationBuilder::build_compositor(Scene *scene)
+{
+ /* For now, just a plain wrapper? */
+ build_nodetree(&scene->id, scene->nodetree);
+}
+
+void DepsgraphRelationBuilder::build_gpencil(ID *UNUSED(owner), bGPdata *gpd)
+{
+ /* animation */
+ build_animdata(&gpd->id);
+
+ // TODO: parent object (when that feature is implemented)
+}
+
+bool DepsgraphRelationBuilder::needs_animdata_node(ID *id)
+{
+ AnimData *adt = BKE_animdata_from_id(id);
+ if (adt != NULL) {
+ return adt->action != NULL;
+ }
+ return false;
+}
+
diff --git a/source/blender/depsgraph/intern/depsgraph_debug.cc b/source/blender/depsgraph/intern/depsgraph_debug.cc
new file mode 100644
index 00000000000..54980436733
--- /dev/null
+++ b/source/blender/depsgraph/intern/depsgraph_debug.cc
@@ -0,0 +1,1212 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2014 Blender Foundation.
+ * All rights reserved.
+ *
+ * Original Author: Lukas Toenne
+ * Contributor(s): None Yet
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/depsgraph/intern/depsgraph_debug.cc
+ * \ingroup depsgraph
+ *
+ * Implementation of tools for debugging the depsgraph
+ */
+
+//#include <stdlib.h>
+#include <string.h>
+
+extern "C" {
+#include "BLI_utildefines.h"
+#include "BLI_listbase.h"
+#include "BLI_ghash.h"
+#include "BLI_string.h"
+
+#include "DNA_scene_types.h"
+#include "DNA_userdef_types.h"
+
+#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_debug.h"
+#include "DEG_depsgraph_build.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+} /* extern "C" */
+
+#include "depsgraph_debug.h"
+#include "depsnode.h"
+#include "depsnode_component.h"
+#include "depsnode_operation.h"
+#include "depsgraph_intern.h"
+
+/* ****************** */
+/* Graphviz Debugging */
+
+static SpinLock lock;
+
+#define NL "\r\n"
+
+/* Only one should be enabled, defines whether graphviz nodes
+ * get colored by individual types or classes.
+ */
+#define COLOR_SCHEME_NODE_CLASS 1
+//#define COLOR_SCHEME_NODE_TYPE 2
+
+static const char *deg_debug_graphviz_fontname = "helvetica";
+static float deg_debug_graphviz_graph_label_size = 20.0f;
+static float deg_debug_graphviz_node_label_size = 14.0f;
+static const int deg_debug_max_colors = 12;
+#if 0
+static const char *deg_debug_colors_dark[] = {
+ "#6e8997", "#144f77", "#76945b",
+ "#216a1d", "#a76665", "#971112",
+ "#a87f49", "#0a9540", "#86768e",
+ "#462866", "#a9a965", "#753b1a",
+};
+#endif
+#ifdef COLOR_SCHEME_NODE_TYPE
+static const char *deg_debug_colors[] = {
+ "#a6cee3", "#1f78b4", "#b2df8a",
+ "#33a02c", "#fb9a99", "#e31a1c",
+ "#fdbf6f", "#ff7f00", "#cab2d6",
+ "#6a3d9a", "#ffff99", "#b15928",
+};
+#endif
+static const char *deg_debug_colors_light[] = {
+ "#8dd3c7", "#ffffb3", "#bebada",
+ "#fb8072", "#80b1d3", "#fdb462",
+ "#b3de69", "#fccde5", "#d9d9d9",
+ "#bc80bd", "#ccebc5", "#ffed6f",
+};
+
+#ifdef COLOR_SCHEME_NODE_TYPE
+static const int deg_debug_node_type_color_map[][2] = {
+ {DEPSNODE_TYPE_ROOT, 0},
+ {DEPSNODE_TYPE_TIMESOURCE, 1},
+ {DEPSNODE_TYPE_ID_REF, 2},
+ {DEPSNODE_TYPE_SUBGRAPH, 3},
+
+ /* Outer Types */
+ {DEPSNODE_TYPE_PARAMETERS, 4},
+ {DEPSNODE_TYPE_PROXY, 5},
+ {DEPSNODE_TYPE_ANIMATION, 6},
+ {DEPSNODE_TYPE_TRANSFORM, 7},
+ {DEPSNODE_TYPE_GEOMETRY, 8},
+ {DEPSNODE_TYPE_SEQUENCER, 9},
+ {DEPSNODE_TYPE_SHADING, 10},
+ {-1, 0}
+};
+#endif
+
+#if 0 /* unused */
+static const int deg_debug_relation_type_color_map[][2] = {
+ {DEPSREL_TYPE_STANDARD, 0},
+ {DEPSREL_TYPE_ROOT_TO_ACTIVE, 1},
+ {DEPSREL_TYPE_DATABLOCK, 2},
+ {DEPSREL_TYPE_TIME, 3},
+ {DEPSREL_TYPE_COMPONENT_ORDER, 4},
+ {DEPSREL_TYPE_OPERATION, 5},
+ {DEPSREL_TYPE_DRIVER, 6},
+ {DEPSREL_TYPE_DRIVER_TARGET, 7},
+ {DEPSREL_TYPE_TRANSFORM, 8},
+ {DEPSREL_TYPE_GEOMETRY_EVAL, 9},
+ {DEPSREL_TYPE_UPDATE, 10},
+ {DEPSREL_TYPE_UPDATE_UI, 11},
+ {-1, 0}
+};
+#endif
+
+static int deg_debug_node_color_index(const DepsNode *node)
+{
+#ifdef COLOR_SCHEME_NODE_CLASS
+ /* Some special types. */
+ switch (node->type) {
+ case DEPSNODE_TYPE_ID_REF:
+ return 5;
+ case DEPSNODE_TYPE_OPERATION:
+ {
+ OperationDepsNode *op_node = (OperationDepsNode *)node;
+ if (op_node->is_noop())
+ return 8;
+ }
+
+ default:
+ break;
+ }
+ /* Do others based on class. */
+ switch (node->tclass) {
+ case DEPSNODE_CLASS_OPERATION:
+ return 4;
+ case DEPSNODE_CLASS_COMPONENT:
+ return 1;
+ default:
+ return 9;
+ }
+#endif
+
+#ifdef COLOR_SCHEME_NODE_TYPE
+ const int (*pair)[2];
+ for (pair = deg_debug_node_type_color_map; (*pair)[0] >= 0; ++pair) {
+ if ((*pair)[0] == node->type) {
+ return (*pair)[1];
+ }
+ }
+ return -1;
+#endif
+}
+
+struct DebugContext {
+ FILE *file;
+ bool show_tags;
+ bool show_eval_priority;
+};
+
+static void deg_debug_fprintf(const DebugContext &ctx, const char *fmt, ...) ATTR_PRINTF_FORMAT(2, 3);
+static void deg_debug_fprintf(const DebugContext &ctx, const char *fmt, ...)
+{
+ va_list args;
+ va_start(args, fmt);
+ vfprintf(ctx.file, fmt, args);
+ va_end(args);
+}
+
+static void deg_debug_graphviz_legend_color(const DebugContext &ctx,
+ const char *name,
+ const char *color)
+{
+ deg_debug_fprintf(ctx, "<TR>");
+ deg_debug_fprintf(ctx, "<TD>%s</TD>", name);
+ deg_debug_fprintf(ctx, "<TD BGCOLOR=\"%s\"></TD>", color);
+ deg_debug_fprintf(ctx, "</TR>" NL);
+}
+
+#if 0
+static void deg_debug_graphviz_legend_line(const DebugContext &ctx,
+ const char *name,
+ const char *color,
+ const char *style)
+{
+ /* XXX TODO */
+ deg_debug_fprintf(ctx, "" NL);
+}
+
+static void deg_debug_graphviz_legend_cluster(const DebugContext &ctx,
+ const char *name,
+ const char *color,
+ const char *style)
+{
+ deg_debug_fprintf(ctx, "<TR>");
+ deg_debug_fprintf(ctx, "<TD>%s</TD>", name);
+ deg_debug_fprintf(ctx, "<TD CELLPADDING=\"4\"><TABLE BORDER=\"1\" CELLBORDER=\"0\" CELLSPACING=\"0\" CELLPADDING=\"0\">");
+ deg_debug_fprintf(ctx, "<TR><TD BGCOLOR=\"%s\"></TD></TR>", color);
+ deg_debug_fprintf(ctx, "</TABLE></TD>");
+ deg_debug_fprintf(ctx, "</TR>" NL);
+}
+#endif
+
+static void deg_debug_graphviz_legend(const DebugContext &ctx)
+{
+ deg_debug_fprintf(ctx, "{" NL);
+ deg_debug_fprintf(ctx, "rank = sink;" NL);
+ deg_debug_fprintf(ctx, "Legend [shape=none, margin=0, label=<" NL);
+ deg_debug_fprintf(ctx, " <TABLE BORDER=\"0\" CELLBORDER=\"1\" CELLSPACING=\"0\" CELLPADDING=\"4\">" NL);
+ deg_debug_fprintf(ctx, "<TR><TD COLSPAN=\"2\"><B>Legend</B></TD></TR>" NL);
+
+#ifdef COLOR_SCHEME_NODE_CLASS
+ const char **colors = deg_debug_colors_light;
+ deg_debug_graphviz_legend_color(ctx, "Operation", colors[4]);
+ deg_debug_graphviz_legend_color(ctx, "Component", colors[1]);
+ deg_debug_graphviz_legend_color(ctx, "ID Node", colors[5]);
+ deg_debug_graphviz_legend_color(ctx, "NOOP", colors[8]);
+#endif
+
+#ifdef COLOR_SCHEME_NODE_TYPE
+ const int (*pair)[2];
+ for (pair = deg_debug_node_type_color_map; (*pair)[0] >= 0; ++pair) {
+ DepsNodeFactory *nti = DEG_get_node_factory((eDepsNode_Type)(*pair)[0]);
+ deg_debug_graphviz_legend_color(ctx,
+ nti->tname().c_str(),
+ deg_debug_colors_light[(*pair)[1] % deg_debug_max_colors]);
+ }
+#endif
+
+ deg_debug_fprintf(ctx, "</TABLE>" NL);
+ deg_debug_fprintf(ctx, ">" NL);
+ deg_debug_fprintf(ctx, ",fontname=\"%s\"", deg_debug_graphviz_fontname);
+ deg_debug_fprintf(ctx, "];" NL);
+ deg_debug_fprintf(ctx, "}" NL);
+}
+
+#if 0 /* unused */
+static int deg_debug_relation_type_color_index(eDepsRelation_Type type)
+{
+ const int (*pair)[2];
+ for (pair = deg_debug_relation_type_color_map; (*pair)[0] >= 0; ++pair) {
+ if ((*pair)[0] == type) {
+ return (*pair)[1];
+ }
+ }
+ return -1;
+}
+#endif
+
+static void deg_debug_graphviz_node_color(const DebugContext &ctx,
+ const DepsNode *node)
+{
+ const char *color_default = "black";
+ const char *color_modified = "orangered4";
+ const char *color_update = "dodgerblue3";
+ const char *color = color_default;
+ if (ctx.show_tags) {
+ if (node->tclass == DEPSNODE_CLASS_OPERATION) {
+ OperationDepsNode *op_node = (OperationDepsNode *)node;
+ if (op_node->flag & DEPSOP_FLAG_DIRECTLY_MODIFIED) {
+ color = color_modified;
+ }
+ else if (op_node->flag & DEPSOP_FLAG_NEEDS_UPDATE) {
+ color = color_update;
+ }
+ }
+ }
+ deg_debug_fprintf(ctx, "\"%s\"", color);
+}
+
+static void deg_debug_graphviz_node_penwidth(const DebugContext &ctx,
+ const DepsNode *node)
+{
+ float penwidth_default = 1.0f;
+ float penwidth_modified = 4.0f;
+ float penwidth_update = 4.0f;
+ float penwidth = penwidth_default;
+ if (ctx.show_tags) {
+ if (node->tclass == DEPSNODE_CLASS_OPERATION) {
+ OperationDepsNode *op_node = (OperationDepsNode *)node;
+ if (op_node->flag & DEPSOP_FLAG_DIRECTLY_MODIFIED) {
+ penwidth = penwidth_modified;
+ }
+ else if (op_node->flag & DEPSOP_FLAG_NEEDS_UPDATE) {
+ penwidth = penwidth_update;
+ }
+ }
+ }
+ deg_debug_fprintf(ctx, "\"%f\"", penwidth);
+}
+
+static void deg_debug_graphviz_node_fillcolor(const DebugContext &ctx,
+ const DepsNode *node)
+{
+ const char *defaultcolor = "gainsboro";
+ int color_index = deg_debug_node_color_index(node);
+ const char *fillcolor = color_index < 0 ? defaultcolor : deg_debug_colors_light[color_index % deg_debug_max_colors];
+ deg_debug_fprintf(ctx, "\"%s\"", fillcolor);
+}
+
+#if 0 /* implementation using stripes, a bit too noisy ... */
+static void deg_debug_graphviz_node_fillcolor(const DebugContext &ctx,
+ const DepsNode *node)
+{
+ const char *defaultcolor = "gainsboro";
+ const char *color_needs_update = "orange";
+ const int num_stripes = 10;
+ int color_index = deg_debug_node_color_index(node);
+ const char *base_color = color_index < 0 ? defaultcolor : deg_debug_colors_light[color_index % deg_debug_max_colors];
+ if (ctx.show_tags &&
+ (node->flag & (DEPSNODE_FLAG_DIRECTLY_MODIFIED | DEPSNODE_FLAG_NEEDS_UPDATE))) {
+ deg_debug_fprintf(ctx, "\"");
+ for (int i = 0; i < num_stripes; ++i) {
+ if (i > 0) {
+ deg_debug_fprintf(ctx, ":");
+ }
+ deg_debug_fprintf(ctx, "%s:%s", base_color, color_needs_update);
+ }
+ deg_debug_fprintf(ctx, "\"");
+ }
+ else {
+ deg_debug_fprintf(ctx, "\"%s\"", base_color);
+ }
+}
+#endif
+
+static void deg_debug_graphviz_relation_color(const DebugContext &ctx,
+ const DepsRelation *rel)
+{
+ const char *color_default = "black";
+ const char *color_error = "red4";
+ const char *color = color_default;
+#if 0 /* disabled for now, edge colors are hardly distinguishable */
+ int color = deg_debug_relation_type_color_index(rel->type);
+ if (color < 0) {
+ deg_debug_fprintf(ctx, "%s", defaultcolor);
+ }
+ else {
+ deg_debug_fprintf(ctx, "\"%s\"", deg_debug_colors_dark[color % deg_debug_max_colors]);
+ }
+#else
+ if (rel->flag & DEPSREL_FLAG_CYCLIC)
+ color = color_error;
+
+ deg_debug_fprintf(ctx, "%s", color);
+#endif
+}
+
+static void deg_debug_graphviz_node_style(const DebugContext &ctx, const DepsNode *node)
+{
+ const char *base_style = "filled"; /* default style */
+ if (ctx.show_tags) {
+ if (node->tclass == DEPSNODE_CLASS_OPERATION) {
+ OperationDepsNode *op_node = (OperationDepsNode *)node;
+ if (op_node->flag & (DEPSOP_FLAG_DIRECTLY_MODIFIED | DEPSOP_FLAG_NEEDS_UPDATE)) {
+ base_style = "striped";
+ }
+ }
+ }
+ switch (node->tclass) {
+ case DEPSNODE_CLASS_GENERIC:
+ deg_debug_fprintf(ctx, "\"%s\"", base_style);
+ break;
+ case DEPSNODE_CLASS_COMPONENT:
+ deg_debug_fprintf(ctx, "\"%s\"", base_style);
+ break;
+ case DEPSNODE_CLASS_OPERATION:
+ deg_debug_fprintf(ctx, "\"%s,rounded\"", base_style);
+ break;
+ }
+}
+
+static void deg_debug_graphviz_node_single(const DebugContext &ctx,
+ const DepsNode *node)
+{
+ const char *shape = "box";
+ string name = node->identifier();
+ float priority = -1.0f;
+ if (node->type == DEPSNODE_TYPE_ID_REF) {
+ IDDepsNode *id_node = (IDDepsNode *)node;
+ char buf[256];
+ BLI_snprintf(buf, sizeof(buf), " (Layers: %d)", id_node->layers);
+ name += buf;
+ }
+ if (ctx.show_eval_priority && node->tclass == DEPSNODE_CLASS_OPERATION) {
+ priority = ((OperationDepsNode *)node)->eval_priority;
+ }
+ deg_debug_fprintf(ctx, "// %s\n", name.c_str());
+ deg_debug_fprintf(ctx, "\"node_%p\"", node);
+ deg_debug_fprintf(ctx, "[");
+// deg_debug_fprintf(ctx, "label=<<B>%s</B>>", name);
+ if (priority >= 0.0f) {
+ deg_debug_fprintf(ctx, "label=<%s<BR/>(<I>%.2f</I>)>",
+ name.c_str(),
+ priority);
+ }
+ else {
+ deg_debug_fprintf(ctx, "label=<%s>", name.c_str());
+ }
+ deg_debug_fprintf(ctx, ",fontname=\"%s\"", deg_debug_graphviz_fontname);
+ deg_debug_fprintf(ctx, ",fontsize=%f", deg_debug_graphviz_node_label_size);
+ deg_debug_fprintf(ctx, ",shape=%s", shape);
+ deg_debug_fprintf(ctx, ",style="); deg_debug_graphviz_node_style(ctx, node);
+ deg_debug_fprintf(ctx, ",color="); deg_debug_graphviz_node_color(ctx, node);
+ deg_debug_fprintf(ctx, ",fillcolor="); deg_debug_graphviz_node_fillcolor(ctx, node);
+ deg_debug_fprintf(ctx, ",penwidth="); deg_debug_graphviz_node_penwidth(ctx, node);
+ deg_debug_fprintf(ctx, "];" NL);
+ deg_debug_fprintf(ctx, NL);
+}
+
+static void deg_debug_graphviz_node_cluster_begin(const DebugContext &ctx,
+ const DepsNode *node)
+{
+ string name = node->identifier().c_str();
+ if (node->type == DEPSNODE_TYPE_ID_REF) {
+ IDDepsNode *id_node = (IDDepsNode *)node;
+ char buf[256];
+ BLI_snprintf(buf, sizeof(buf), " (Layers: %d)", id_node->layers);
+ name += buf;
+ }
+ deg_debug_fprintf(ctx, "// %s\n", name.c_str());
+ deg_debug_fprintf(ctx, "subgraph \"cluster_%p\" {" NL, node);
+// deg_debug_fprintf(ctx, "label=<<B>%s</B>>;" NL, name);
+ deg_debug_fprintf(ctx, "label=<%s>;" NL, name.c_str());
+ deg_debug_fprintf(ctx, "fontname=\"%s\";" NL, deg_debug_graphviz_fontname);
+ deg_debug_fprintf(ctx, "fontsize=%f;" NL, deg_debug_graphviz_node_label_size);
+ deg_debug_fprintf(ctx, "margin=\"%d\";" NL, 16);
+ deg_debug_fprintf(ctx, "style="); deg_debug_graphviz_node_style(ctx, node); deg_debug_fprintf(ctx, ";" NL);
+ deg_debug_fprintf(ctx, "color="); deg_debug_graphviz_node_color(ctx, node); deg_debug_fprintf(ctx, ";" NL);
+ deg_debug_fprintf(ctx, "fillcolor="); deg_debug_graphviz_node_fillcolor(ctx, node); deg_debug_fprintf(ctx, ";" NL);
+ deg_debug_fprintf(ctx, "penwidth="); deg_debug_graphviz_node_penwidth(ctx, node); deg_debug_fprintf(ctx, ";" NL);
+ /* dummy node, so we can add edges between clusters */
+ deg_debug_fprintf(ctx, "\"node_%p\"", node);
+ deg_debug_fprintf(ctx, "[");
+ deg_debug_fprintf(ctx, "shape=%s", "point");
+ deg_debug_fprintf(ctx, ",style=%s", "invis");
+ deg_debug_fprintf(ctx, "];" NL);
+ deg_debug_fprintf(ctx, NL);
+}
+
+static void deg_debug_graphviz_node_cluster_end(const DebugContext &ctx)
+{
+ deg_debug_fprintf(ctx, "}" NL);
+ deg_debug_fprintf(ctx, NL);
+}
+
+static void deg_debug_graphviz_graph_nodes(const DebugContext &ctx,
+ const Depsgraph *graph);
+static void deg_debug_graphviz_graph_relations(const DebugContext &ctx,
+ const Depsgraph *graph);
+
+static void deg_debug_graphviz_node(const DebugContext &ctx,
+ const DepsNode *node)
+{
+ switch (node->type) {
+ case DEPSNODE_TYPE_ID_REF:
+ {
+ const IDDepsNode *id_node = (const IDDepsNode *)node;
+ if (id_node->components.empty()) {
+ deg_debug_graphviz_node_single(ctx, node);
+ }
+ else {
+ deg_debug_graphviz_node_cluster_begin(ctx, node);
+ for (IDDepsNode::ComponentMap::const_iterator it = id_node->components.begin();
+ it != id_node->components.end();
+ ++it)
+ {
+ const ComponentDepsNode *comp = it->second;
+ deg_debug_graphviz_node(ctx, comp);
+ }
+ deg_debug_graphviz_node_cluster_end(ctx);
+ }
+ break;
+ }
+ case DEPSNODE_TYPE_SUBGRAPH:
+ {
+ SubgraphDepsNode *sub_node = (SubgraphDepsNode *)node;
+ if (sub_node->graph) {
+ deg_debug_graphviz_node_cluster_begin(ctx, node);
+ deg_debug_graphviz_graph_nodes(ctx, sub_node->graph);
+ deg_debug_graphviz_node_cluster_end(ctx);
+ }
+ else {
+ deg_debug_graphviz_node_single(ctx, node);
+ }
+ break;
+ }
+ case DEPSNODE_TYPE_PARAMETERS:
+ case DEPSNODE_TYPE_ANIMATION:
+ case DEPSNODE_TYPE_TRANSFORM:
+ case DEPSNODE_TYPE_PROXY:
+ case DEPSNODE_TYPE_GEOMETRY:
+ case DEPSNODE_TYPE_SEQUENCER:
+ case DEPSNODE_TYPE_EVAL_POSE:
+ case DEPSNODE_TYPE_BONE:
+ case DEPSNODE_TYPE_SHADING:
+ {
+ ComponentDepsNode *comp_node = (ComponentDepsNode *)node;
+ if (!comp_node->operations.empty()) {
+ deg_debug_graphviz_node_cluster_begin(ctx, node);
+ for (ComponentDepsNode::OperationMap::const_iterator it = comp_node->operations.begin();
+ it != comp_node->operations.end();
+ ++it)
+ {
+ const DepsNode *op_node = it->second;
+ deg_debug_graphviz_node(ctx, op_node);
+ }
+ deg_debug_graphviz_node_cluster_end(ctx);
+ }
+ else {
+ deg_debug_graphviz_node_single(ctx, node);
+ }
+ break;
+ }
+ default:
+ deg_debug_graphviz_node_single(ctx, node);
+ break;
+ }
+}
+
+static bool deg_debug_graphviz_is_cluster(const DepsNode *node)
+{
+ switch (node->type) {
+ case DEPSNODE_TYPE_ID_REF:
+ {
+ const IDDepsNode *id_node = (const IDDepsNode *)node;
+ return !id_node->components.empty();
+ }
+ case DEPSNODE_TYPE_SUBGRAPH:
+ {
+ SubgraphDepsNode *sub_node = (SubgraphDepsNode *)node;
+ return sub_node->graph != NULL;
+ }
+ case DEPSNODE_TYPE_PARAMETERS:
+ case DEPSNODE_TYPE_ANIMATION:
+ case DEPSNODE_TYPE_TRANSFORM:
+ case DEPSNODE_TYPE_PROXY:
+ case DEPSNODE_TYPE_GEOMETRY:
+ case DEPSNODE_TYPE_SEQUENCER:
+ case DEPSNODE_TYPE_EVAL_POSE:
+ case DEPSNODE_TYPE_BONE:
+ {
+ ComponentDepsNode *comp_node = (ComponentDepsNode *)node;
+ return !comp_node->operations.empty();
+ }
+ default:
+ return false;
+ }
+}
+
+static bool deg_debug_graphviz_is_owner(const DepsNode *node,
+ const DepsNode *other)
+{
+ switch (node->tclass) {
+ case DEPSNODE_CLASS_COMPONENT:
+ {
+ ComponentDepsNode *comp_node = (ComponentDepsNode *)node;
+ if (comp_node->owner == other)
+ return true;
+ break;
+ }
+ case DEPSNODE_CLASS_OPERATION:
+ {
+ OperationDepsNode *op_node = (OperationDepsNode *)node;
+ if (op_node->owner == other)
+ return true;
+ else if (op_node->owner->owner == other)
+ return true;
+ break;
+ }
+ default: break;
+ }
+ return false;
+}
+
+static void deg_debug_graphviz_node_relations(const DebugContext &ctx,
+ const DepsNode *node)
+{
+ DEPSNODE_RELATIONS_ITER_BEGIN(node->inlinks, rel)
+ {
+ float penwidth = 2.0f;
+
+ const DepsNode *tail = rel->to; /* same as node */
+ const DepsNode *head = rel->from;
+ deg_debug_fprintf(ctx, "// %s -> %s\n",
+ head->identifier().c_str(),
+ tail->identifier().c_str());
+ deg_debug_fprintf(ctx, "\"node_%p\"", head);
+ deg_debug_fprintf(ctx, " -> ");
+ deg_debug_fprintf(ctx, "\"node_%p\"", tail);
+
+ deg_debug_fprintf(ctx, "[");
+ /* XXX labels on relations are not very helpful:
+ * - they tend to appear too far away to be associated with the edge lines
+ * - names are mostly redundant, reflecting simply their from/to nodes
+ * - no behavior or typing of relations themselves to justify labels
+ */
+#if 0
+ deg_debug_fprintf(ctx, "label=\"%s\"", rel->name);
+ deg_debug_fprintf(ctx, ",fontname=\"%s\"", deg_debug_graphviz_fontname);
+#else
+ /* Note: without label an id seem necessary to avoid bugs in graphviz/dot */
+ deg_debug_fprintf(ctx, "id=\"%s\"", rel->name);
+#endif
+ deg_debug_fprintf(ctx, ",color="); deg_debug_graphviz_relation_color(ctx, rel);
+ deg_debug_fprintf(ctx, ",penwidth=\"%f\"", penwidth);
+ /* NOTE: edge from node to own cluster is not possible and gives graphviz
+ * warning, avoid this here by just linking directly to the invisible
+ * placeholder node
+ */
+ if (deg_debug_graphviz_is_cluster(tail) && !deg_debug_graphviz_is_owner(head, tail)) {
+ deg_debug_fprintf(ctx, ",ltail=\"cluster_%p\"", tail);
+ }
+ if (deg_debug_graphviz_is_cluster(head) && !deg_debug_graphviz_is_owner(tail, head)) {
+ deg_debug_fprintf(ctx, ",lhead=\"cluster_%p\"", head);
+ }
+ deg_debug_fprintf(ctx, "];" NL);
+ deg_debug_fprintf(ctx, NL);
+ }
+ DEPSNODE_RELATIONS_ITER_END;
+
+#if 0
+ if (node->tclass == DEPSNODE_CLASS_COMPONENT) {
+ const ComponentDepsNode *comp_node = (const ComponentDepsNode *)node;
+ for (ComponentDepsNode::OperationMap::const_iterator it = comp_node->operations.begin();
+ it != comp_node->operations.end();
+ ++it)
+ {
+ OperationDepsNode *op_node = it->second;
+ deg_debug_graphviz_node_relations(ctx, op_node);
+ }
+ }
+ else if (node->type == DEPSNODE_TYPE_ID_REF) {
+ const IDDepsNode *id_node = (const IDDepsNode *)node;
+ for (IDDepsNode::ComponentMap::const_iterator it = id_node->components.begin();
+ it != id_node->components.end();
+ ++it)
+ {
+ const ComponentDepsNode *comp = it->second;
+ deg_debug_graphviz_node_relations(ctx, comp);
+ }
+ }
+ else if (node->type == DEPSNODE_TYPE_SUBGRAPH) {
+ SubgraphDepsNode *sub_node = (SubgraphDepsNode *)node;
+ if (sub_node->graph) {
+ deg_debug_graphviz_graph_relations(ctx, sub_node->graph);
+ }
+ }
+#endif
+}
+
+static void deg_debug_graphviz_graph_nodes(const DebugContext &ctx,
+ const Depsgraph *graph)
+{
+ if (graph->root_node) {
+ deg_debug_graphviz_node(ctx, graph->root_node);
+ }
+ for (Depsgraph::IDNodeMap::const_iterator it = graph->id_hash.begin();
+ it != graph->id_hash.end();
+ ++it)
+ {
+ DepsNode *node = it->second;
+ deg_debug_graphviz_node(ctx, node);
+ }
+ TimeSourceDepsNode *time_source = graph->find_time_source(NULL);
+ if (time_source != NULL) {
+ deg_debug_graphviz_node(ctx, time_source);
+ }
+}
+
+static void deg_debug_graphviz_graph_relations(const DebugContext &ctx,
+ const Depsgraph *graph)
+{
+#if 0
+ if (graph->root_node) {
+ deg_debug_graphviz_node_relations(ctx, graph->root_node);
+ }
+ for (Depsgraph::IDNodeMap::const_iterator it = graph->id_hash.begin();
+ it != graph->id_hash.end();
+ ++it)
+ {
+ DepsNode *id_node = it->second;
+ deg_debug_graphviz_node_relations(ctx, id_node);
+ }
+#else
+ /* XXX not in use yet */
+// for (Depsgraph::OperationNodes::const_iterator it = graph->all_opnodes.begin();
+// it != graph->all_opnodes.end();
+// ++it)
+// {
+// OperationDepsNode *op_node = *it;
+// deg_debug_graphviz_node_relations(ctx, op_node);
+// }
+ for (Depsgraph::IDNodeMap::const_iterator it = graph->id_hash.begin();
+ it != graph->id_hash.end();
+ ++it)
+ {
+ IDDepsNode *id_node = it->second;
+ for (IDDepsNode::ComponentMap::const_iterator it = id_node->components.begin();
+ it != id_node->components.end();
+ ++it)
+ {
+ ComponentDepsNode *comp_node = it->second;
+ for (ComponentDepsNode::OperationMap::const_iterator it = comp_node->operations.begin();
+ it != comp_node->operations.end();
+ ++it)
+ {
+ OperationDepsNode *op_node = it->second;
+ deg_debug_graphviz_node_relations(ctx, op_node);
+ }
+ }
+ }
+
+ TimeSourceDepsNode *time_source = graph->find_time_source(NULL);
+ if (time_source != NULL) {
+ deg_debug_graphviz_node_relations(ctx, time_source);
+ }
+#endif
+}
+
+void DEG_debug_graphviz(const Depsgraph *graph, FILE *f, const char *label, bool show_eval)
+{
+#if 0 /* generate shaded color set */
+ static char colors[][3] = {{0xa6, 0xce, 0xe3},{0x1f, 0x78, 0xb4},{0xb2, 0xdf, 0x8a},{0x33, 0xa0, 0x2c},
+ {0xfb, 0x9a, 0x99},{0xe3, 0x1a, 0x1c},{0xfd, 0xbf, 0x6f},{0xff, 0x7f, 0x00},
+ {0xca, 0xb2, 0xd6},{0x6a, 0x3d, 0x9a},{0xff, 0xff, 0x99},{0xb1, 0x59, 0x28}};
+ int i;
+ const float factor = 0.666f;
+ for (i=0; i < 12; ++i)
+ printf("\"#%x%x%x\"\n", (char)(colors[i][0] * factor), (char)(colors[i][1] * factor), (char)(colors[i][2] * factor));
+#endif
+
+ if (!graph) {
+ return;
+ }
+
+ DebugContext ctx;
+ ctx.file = f;
+ ctx.show_tags = show_eval;
+ ctx.show_eval_priority = show_eval;
+
+ deg_debug_fprintf(ctx, "digraph depgraph {" NL);
+ deg_debug_fprintf(ctx, "rankdir=LR;" NL);
+ deg_debug_fprintf(ctx, "graph [");
+ deg_debug_fprintf(ctx, "compound=true");
+ deg_debug_fprintf(ctx, ",labelloc=\"t\"");
+ deg_debug_fprintf(ctx, ",fontsize=%f", deg_debug_graphviz_graph_label_size);
+ deg_debug_fprintf(ctx, ",fontname=\"%s\"", deg_debug_graphviz_fontname);
+ deg_debug_fprintf(ctx, ",label=\"%s\"", label);
+ deg_debug_fprintf(ctx, ",splines=ortho");
+ deg_debug_fprintf(ctx, ",overlap=scalexy"); // XXX: only when using neato
+ deg_debug_fprintf(ctx, "];" NL);
+
+ deg_debug_graphviz_graph_nodes(ctx, graph);
+ deg_debug_graphviz_graph_relations(ctx, graph);
+
+ deg_debug_graphviz_legend(ctx);
+
+ deg_debug_fprintf(ctx, "}" NL);
+}
+
+#undef NL
+
+/* ************************************************ */
+
+static string get_component_name(eDepsNode_Type type, const string &name = "")
+{
+ DepsNodeFactory *factory = DEG_get_node_factory(type);
+ if (name.empty()) {
+ return string(factory->tname());
+ }
+ else {
+ return string(factory->tname()) + " | " + name;
+ }
+}
+
+static void times_clear(DepsgraphStatsTimes &times)
+{
+ times.duration_last = 0.0f;
+}
+
+static void times_add(DepsgraphStatsTimes &times, float time)
+{
+ times.duration_last += time;
+}
+
+void DepsgraphDebug::eval_begin(const EvaluationContext *UNUSED(eval_ctx))
+{
+ /* TODO(sergey): Stats are currently globally disabled. */
+ /* verify_stats(); */
+ reset_stats();
+}
+
+void DepsgraphDebug::eval_end(const EvaluationContext *UNUSED(eval_ctx))
+{
+ WM_main_add_notifier(NC_SPACE | ND_SPACE_INFO_REPORT, NULL);
+}
+
+void DepsgraphDebug::eval_step(const EvaluationContext *UNUSED(eval_ctx),
+ const char *message)
+{
+#ifdef DEG_DEBUG_BUILD
+ if (deg_debug_eval_cb)
+ deg_debug_eval_cb(deg_debug_eval_userdata, message);
+#else
+ (void)message; /* Ignored. */
+#endif
+}
+
+void DepsgraphDebug::task_started(Depsgraph *graph,
+ const OperationDepsNode *node)
+{
+ if (stats) {
+ BLI_spin_lock(&graph->lock);
+
+ ComponentDepsNode *comp = node->owner;
+ ID *id = comp->owner->id;
+
+ DepsgraphStatsID *id_stats = get_id_stats(id, true);
+ times_clear(id_stats->times);
+
+ /* XXX TODO use something like: if (id->flag & ID_DEG_DETAILS) {...} */
+ if (0) {
+ /* XXX component name usage needs cleanup! currently mixes identifier and description strings! */
+ DepsgraphStatsComponent *comp_stats = get_component_stats(id, get_component_name(comp->type, comp->name), true);
+ times_clear(comp_stats->times);
+ }
+
+ BLI_spin_unlock(&graph->lock);
+ }
+}
+
+void DepsgraphDebug::task_completed(Depsgraph *graph,
+ const OperationDepsNode *node,
+ double time)
+{
+ if (stats) {
+ BLI_spin_lock(&graph->lock);
+
+ ComponentDepsNode *comp = node->owner;
+ ID *id = comp->owner->id;
+
+ DepsgraphStatsID *id_stats = get_id_stats(id, true);
+ times_add(id_stats->times, time);
+
+ /* XXX TODO use something like: if (id->flag & ID_DEG_DETAILS) {...} */
+ if (0) {
+ /* XXX component name usage needs cleanup! currently mixes identifier and description strings! */
+ DepsgraphStatsComponent *comp_stats = get_component_stats(id, get_component_name(comp->type, comp->name), true);
+ times_add(comp_stats->times, time);
+ }
+
+ BLI_spin_unlock(&graph->lock);
+ }
+}
+
+/* ********** */
+/* Statistics */
+
+DepsgraphStats *DepsgraphDebug::stats = NULL;
+
+/* GHash callback */
+static void deg_id_stats_free(void *val)
+{
+ DepsgraphStatsID *id_stats = (DepsgraphStatsID *)val;
+
+ if (id_stats) {
+ BLI_freelistN(&id_stats->components);
+ MEM_freeN(id_stats);
+ }
+}
+
+void DepsgraphDebug::stats_init()
+{
+ if (!stats) {
+ stats = (DepsgraphStats *)MEM_callocN(sizeof(DepsgraphStats), "Depsgraph Stats");
+ stats->id_stats = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, "Depsgraph ID Stats Hash");
+ }
+}
+
+void DepsgraphDebug::stats_free()
+{
+ if (stats) {
+ BLI_ghash_free(stats->id_stats, NULL, deg_id_stats_free);
+ MEM_freeN(stats);
+ stats = NULL;
+ }
+}
+
+void DepsgraphDebug::verify_stats()
+{
+ stats_init();
+}
+
+void DepsgraphDebug::reset_stats()
+{
+ if (!stats) {
+ return;
+ }
+
+ /* XXX this doesn't work, will immediately clear all info,
+ * since most depsgraph updates have none or very few updates to handle.
+ *
+ * Could consider clearing only zero-user ID blocks here
+ */
+// BLI_ghash_clear(stats->id_stats, NULL, deg_id_stats_free);
+}
+
+DepsgraphStatsID *DepsgraphDebug::get_id_stats(ID *id, bool create)
+{
+ DepsgraphStatsID *id_stats = (DepsgraphStatsID *)BLI_ghash_lookup(stats->id_stats, id);
+
+ if (!id_stats && create) {
+ id_stats = (DepsgraphStatsID *)MEM_callocN(sizeof(DepsgraphStatsID), "Depsgraph ID Stats");
+ id_stats->id = id;
+
+ BLI_ghash_insert(stats->id_stats, id, id_stats);
+ }
+
+ return id_stats;
+}
+
+DepsgraphStatsComponent *DepsgraphDebug::get_component_stats(
+ DepsgraphStatsID *id_stats,
+ const string &name,
+ bool create)
+{
+ DepsgraphStatsComponent *comp_stats;
+ for (comp_stats = (DepsgraphStatsComponent *)id_stats->components.first;
+ comp_stats != NULL;
+ comp_stats = comp_stats->next)
+ {
+ if (STREQ(comp_stats->name, name.c_str()))
+ break;
+ }
+ if (!comp_stats && create) {
+ comp_stats = (DepsgraphStatsComponent *)MEM_callocN(sizeof(DepsgraphStatsComponent), "Depsgraph Component Stats");
+ BLI_strncpy(comp_stats->name, name.c_str(), sizeof(comp_stats->name));
+ BLI_addtail(&id_stats->components, comp_stats);
+ }
+ return comp_stats;
+}
+
+/* ------------------------------------------------ */
+
+DepsgraphStats *DEG_stats(void)
+{
+ return DepsgraphDebug::stats;
+}
+
+void DEG_stats_verify()
+{
+ DepsgraphDebug::verify_stats();
+}
+
+DepsgraphStatsID *DEG_stats_id(ID *id)
+{
+ if (!DepsgraphDebug::stats) {
+ return NULL;
+ }
+ return DepsgraphDebug::get_id_stats(id, false);
+}
+
+bool DEG_debug_compare(const struct Depsgraph *graph1,
+ const struct Depsgraph *graph2)
+{
+ BLI_assert(graph1 != NULL);
+ BLI_assert(graph2 != NULL);
+ if (graph1->operations.size() != graph2->operations.size()) {
+ return false;
+ }
+ /* TODO(sergey): Currently we only do real stupid check,
+ * which is fast but which isn't 100% reliable.
+ *
+ * Would be cool to make it more robust, but it's good enough
+ * for now. Also, proper graph check is actually NP-complex
+ * problem..
+ */
+ return true;
+}
+
+bool DEG_debug_scene_relations_validate(Main *bmain,
+ Scene *scene)
+{
+ Depsgraph *depsgraph = DEG_graph_new();
+ bool valid = true;
+ DEG_graph_build_from_scene(depsgraph, bmain, scene);
+ if (!DEG_debug_compare(depsgraph, scene->depsgraph)) {
+ fprintf(stderr, "ERROR! Depsgraph wasn't tagged for update when it should have!\n");
+ BLI_assert(!"This should not happen!");
+ valid = false;
+ }
+ DEG_graph_free(depsgraph);
+ return valid;
+}
+
+bool DEG_debug_consistency_check(Depsgraph *graph)
+{
+ /* Validate links exists in both directions. */
+ for (Depsgraph::OperationNodes::const_iterator it_op = graph->operations.begin();
+ it_op != graph->operations.end();
+ ++it_op)
+ {
+ OperationDepsNode *node = *it_op;
+ for (OperationDepsNode::Relations::const_iterator it_rel = node->outlinks.begin();
+ it_rel != node->outlinks.end();
+ ++it_rel)
+ {
+ DepsRelation *rel = *it_rel;
+
+ int counter1 = 0;
+ for (OperationDepsNode::Relations::const_iterator tmp_rel = node->outlinks.begin();
+ tmp_rel != node->outlinks.end();
+ ++tmp_rel)
+ {
+ if (*tmp_rel == rel) {
+ ++counter1;
+ }
+ }
+
+ int counter2 = 0;
+ for (OperationDepsNode::Relations::const_iterator tmp_rel = rel->to->inlinks.begin();
+ tmp_rel != rel->to->inlinks.end();
+ ++tmp_rel)
+ {
+ if (*tmp_rel == rel) {
+ ++counter2;
+ }
+ }
+
+ if (counter1 != counter2) {
+ printf("Relation exists in outgoing direction but not in incoming (%d vs. %d).\n",
+ counter1, counter2);
+ return false;
+ }
+ }
+ }
+
+ for (Depsgraph::OperationNodes::const_iterator it_op = graph->operations.begin();
+ it_op != graph->operations.end();
+ ++it_op)
+ {
+ OperationDepsNode *node = *it_op;
+ for (OperationDepsNode::Relations::const_iterator it_rel = node->inlinks.begin();
+ it_rel != node->inlinks.end();
+ ++it_rel)
+ {
+ DepsRelation *rel = *it_rel;
+
+ int counter1 = 0;
+ for (OperationDepsNode::Relations::const_iterator tmp_rel = node->inlinks.begin();
+ tmp_rel != node->inlinks.end();
+ ++tmp_rel)
+ {
+ if (*tmp_rel == rel) {
+ ++counter1;
+ }
+ }
+
+ int counter2 = 0;
+ for (OperationDepsNode::Relations::const_iterator tmp_rel = rel->from->outlinks.begin();
+ tmp_rel != rel->from->outlinks.end();
+ ++tmp_rel)
+ {
+ if (*tmp_rel == rel) {
+ ++counter2;
+ }
+ }
+
+ if (counter1 != counter2) {
+ printf("Relation exists in incoming direction but not in outcoming (%d vs. %d).\n",
+ counter1, counter2);
+ }
+ }
+ }
+
+ /* Validate node valency calculated in both directions. */
+ for (Depsgraph::OperationNodes::const_iterator it_op = graph->operations.begin();
+ it_op != graph->operations.end();
+ ++it_op)
+ {
+ OperationDepsNode *node = *it_op;
+ node->num_links_pending = 0;
+ node->done = 0;
+ }
+
+ for (Depsgraph::OperationNodes::const_iterator it_op = graph->operations.begin();
+ it_op != graph->operations.end();
+ ++it_op)
+ {
+ OperationDepsNode *node = *it_op;
+ if (node->done) {
+ printf("Node %s is twice in the operations!\n",
+ node->identifier().c_str());
+ return false;
+ }
+ for (OperationDepsNode::Relations::const_iterator it_rel = node->outlinks.begin();
+ it_rel != node->outlinks.end();
+ ++it_rel)
+ {
+ DepsRelation *rel = *it_rel;
+ if (rel->to->type == DEPSNODE_TYPE_OPERATION) {
+ OperationDepsNode *to = (OperationDepsNode *)rel->to;
+ BLI_assert(to->num_links_pending < to->inlinks.size());
+ ++to->num_links_pending;
+ }
+ }
+ node->done = 1;
+ }
+
+ for (Depsgraph::OperationNodes::const_iterator it_op = graph->operations.begin();
+ it_op != graph->operations.end();
+ ++it_op)
+ {
+ OperationDepsNode *node = *it_op;
+ int num_links_pending = 0;
+ for (OperationDepsNode::Relations::const_iterator it_rel = node->inlinks.begin();
+ it_rel != node->inlinks.end();
+ ++it_rel)
+ {
+ DepsRelation *rel = *it_rel;
+ if (rel->from->type == DEPSNODE_TYPE_OPERATION) {
+ ++num_links_pending;
+ }
+ }
+ if (node->num_links_pending != num_links_pending) {
+ printf("Valency mismatch: %s, %u != %d\n",
+ node->identifier().c_str(),
+ node->num_links_pending, num_links_pending);
+ printf("Number of inlinks: %d\n", (int)node->inlinks.size());
+ return false;
+ }
+ }
+ return true;
+}
+
+/* ------------------------------------------------ */
+
+/**
+ * Obtain simple statistics about the complexity of the depsgraph
+ * \param[out] r_outer The number of outer nodes in the graph
+ * \param[out] r_operations The number of operation nodes in the graph
+ * \param[out] r_relations The number of relations between (executable) nodes in the graph
+ */
+void DEG_stats_simple(const Depsgraph *graph, size_t *r_outer,
+ size_t *r_operations, size_t *r_relations)
+{
+ /* number of operations */
+ if (r_operations) {
+ /* All operations should be in this list, allowing us to count the total
+ * number of nodes.
+ */
+ *r_operations = graph->operations.size();
+ }
+
+ /* Count number of outer nodes and/or relations between these. */
+ if (r_outer || r_relations) {
+ size_t tot_outer = 0;
+ size_t tot_rels = 0;
+
+ for (Depsgraph::IDNodeMap::const_iterator it = graph->id_hash.begin();
+ it != graph->id_hash.end();
+ ++it)
+ {
+ IDDepsNode *id_node = it->second;
+ tot_outer++;
+ for (IDDepsNode::ComponentMap::const_iterator it = id_node->components.begin();
+ it != id_node->components.end();
+ ++it)
+ {
+ ComponentDepsNode *comp_node = it->second;
+ tot_outer++;
+ for (ComponentDepsNode::OperationMap::const_iterator it = comp_node->operations.begin();
+ it != comp_node->operations.end();
+ ++it)
+ {
+ OperationDepsNode *op_node = it->second;
+ tot_rels += op_node->inlinks.size();
+ }
+ }
+ }
+
+ TimeSourceDepsNode *time_source = graph->find_time_source(NULL);
+ if (time_source != NULL) {
+ tot_rels += time_source->inlinks.size();
+ }
+
+ if (r_relations) *r_relations = tot_rels;
+ if (r_outer) *r_outer = tot_outer;
+ }
+}
+
diff --git a/source/blender/depsgraph/intern/depsgraph_debug.h b/source/blender/depsgraph/intern/depsgraph_debug.h
new file mode 100644
index 00000000000..64b97855f57
--- /dev/null
+++ b/source/blender/depsgraph/intern/depsgraph_debug.h
@@ -0,0 +1,87 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2013 Blender Foundation.
+ * All rights reserved.
+ *
+ * Original Author: Joshua Leung
+ * Contributor(s): None Yet
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/depsgraph/intern/depsgraph_debug.h
+ * \ingroup depsgraph
+ */
+
+#ifndef __DEPSGRAPH_DEBUG_H__
+#define __DEPSGRAPH_DEBUG_H__
+
+#include "depsgraph_types.h"
+
+extern "C" {
+#include "BKE_global.h"
+}
+
+struct DepsgraphStats;
+struct DepsgraphStatsID;
+struct DepsgraphStatsComponent;
+struct DepsgraphSettings;
+struct EvaluationContext;
+struct OperationDepsNode;
+
+struct Depsgraph;
+
+struct DepsgraphDebug {
+ static DepsgraphStats *stats;
+
+ static void stats_init();
+ static void stats_free();
+
+ static void verify_stats();
+ static void reset_stats();
+
+ static void eval_begin(const EvaluationContext *eval_ctx);
+ static void eval_end(const EvaluationContext *eval_ctx);
+ static void eval_step(const EvaluationContext *eval_ctx,
+ const char *message);
+
+ static void task_started(Depsgraph *graph, const OperationDepsNode *node);
+ static void task_completed(Depsgraph *graph,
+ const OperationDepsNode *node,
+ double time);
+
+ static DepsgraphStatsID *get_id_stats(ID *id, bool create);
+ static DepsgraphStatsComponent *get_component_stats(DepsgraphStatsID *id_stats,
+ const string &name,
+ bool create);
+ static DepsgraphStatsComponent *get_component_stats(ID *id,
+ const string &name,
+ bool create)
+ {
+ return get_component_stats(get_id_stats(id, create), name, create);
+ }
+};
+
+#define DEG_DEBUG_PRINTF(...) \
+ { \
+ if (G.debug & G_DEBUG_DEPSGRAPH) { \
+ fprintf(stderr, __VA_ARGS__); \
+ } \
+ } \
+
+#endif /* __DEPSGRAPH_DEBUG_H__ */
diff --git a/source/blender/depsgraph/intern/depsgraph_eval.cc b/source/blender/depsgraph/intern/depsgraph_eval.cc
new file mode 100644
index 00000000000..e8065766332
--- /dev/null
+++ b/source/blender/depsgraph/intern/depsgraph_eval.cc
@@ -0,0 +1,399 @@
+/*
+ * ***** 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.
+ *
+ * Original Author: Joshua Leung
+ * Contributor(s): None Yet
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/depsgraph/intern/depsgraph_eval.cc
+ * \ingroup depsgraph
+ *
+ * Evaluation engine entrypoints for Depsgraph Engine.
+ */
+
+#include "MEM_guardedalloc.h"
+
+#include "PIL_time.h"
+
+extern "C" {
+#include "BLI_utildefines.h"
+#include "BLI_task.h"
+
+#include "BKE_depsgraph.h"
+#include "BKE_scene.h"
+
+#include "DEG_depsgraph.h"
+} /* extern "C" */
+
+#include "atomic_ops.h"
+
+#include "depsgraph.h"
+#include "depsnode.h"
+#include "depsnode_component.h"
+#include "depsnode_operation.h"
+#include "depsgraph_debug.h"
+
+#ifdef WITH_LEGACY_DEPSGRAPH
+static bool use_legacy_depsgraph = true;
+#endif
+
+bool DEG_depsgraph_use_legacy(void)
+{
+#ifdef DISABLE_NEW_DEPSGRAPH
+ return true;
+#elif defined(WITH_LEGACY_DEPSGRAPH)
+ return use_legacy_depsgraph;
+#else
+ BLI_assert(!"Should not be used with new depsgraph");
+ return false;
+#endif
+}
+
+void DEG_depsgraph_switch_to_legacy(void)
+{
+#ifdef WITH_LEGACY_DEPSGRAPH
+ use_legacy_depsgraph = true;
+#else
+ BLI_assert(!"Should not be used with new depsgraph");
+#endif
+}
+
+void DEG_depsgraph_switch_to_new(void)
+{
+#ifdef WITH_LEGACY_DEPSGRAPH
+ use_legacy_depsgraph = false;
+#else
+ BLI_assert(!"Should not be used with new depsgraph");
+#endif
+}
+
+/* ****************** */
+/* Evaluation Context */
+
+/* Create new evaluation context. */
+EvaluationContext *DEG_evaluation_context_new(int mode)
+{
+ EvaluationContext *eval_ctx =
+ (EvaluationContext *)MEM_callocN(sizeof(EvaluationContext),
+ "EvaluationContext");
+ eval_ctx->mode = mode;
+ return eval_ctx;
+}
+
+/**
+ * Initialize evaluation context.
+ * Used by the areas which currently overrides the context or doesn't have
+ * access to a proper one.
+ */
+void DEG_evaluation_context_init(EvaluationContext *eval_ctx, int mode)
+{
+ eval_ctx->mode = mode;
+}
+
+/* Free evaluation context. */
+void DEG_evaluation_context_free(EvaluationContext *eval_ctx)
+{
+ MEM_freeN(eval_ctx);
+}
+
+/* ********************** */
+/* Evaluation Entrypoints */
+
+/* Forward declarations. */
+static void schedule_children(TaskPool *pool,
+ Depsgraph *graph,
+ OperationDepsNode *node,
+ const int layers);
+
+struct DepsgraphEvalState {
+ EvaluationContext *eval_ctx;
+ Depsgraph *graph;
+ int layers;
+};
+
+static void deg_task_run_func(TaskPool *pool,
+ void *taskdata,
+ int UNUSED(threadid))
+{
+ DepsgraphEvalState *state = (DepsgraphEvalState *)BLI_task_pool_userdata(pool);
+ OperationDepsNode *node = (OperationDepsNode *)taskdata;
+
+ if (!node->is_noop()) {
+ /* Get context. */
+ // TODO: who initialises this? "Init" operations aren't able to initialise it!!!
+ /* TODO(sergey): Wedon't use component contexts at this moment. */
+ /* ComponentDepsNode *comp = node->owner; */
+ BLI_assert(node->owner != NULL);
+
+ /* Take note of current time. */
+ double start_time = PIL_check_seconds_timer();
+ DepsgraphDebug::task_started(state->graph, node);
+
+ /* Should only be the case for NOOPs, which never get to this point. */
+ BLI_assert(node->evaluate);
+
+ /* Perform operation. */
+ node->evaluate(state->eval_ctx);
+
+ /* Note how long this took. */
+ double end_time = PIL_check_seconds_timer();
+ DepsgraphDebug::task_completed(state->graph,
+ node,
+ end_time - start_time);
+ }
+
+ schedule_children(pool, state->graph, node, state->layers);
+}
+
+static void calculate_pending_parents(Depsgraph *graph, int layers)
+{
+ for (Depsgraph::OperationNodes::const_iterator it_op = graph->operations.begin();
+ it_op != graph->operations.end();
+ ++it_op)
+ {
+ OperationDepsNode *node = *it_op;
+ IDDepsNode *id_node = node->owner->owner;
+
+ node->num_links_pending = 0;
+ node->scheduled = false;
+
+ /* count number of inputs that need updates */
+ if ((id_node->layers & layers) != 0 &&
+ (node->flag & DEPSOP_FLAG_NEEDS_UPDATE) != 0)
+ {
+ for (OperationDepsNode::Relations::const_iterator it_rel = node->inlinks.begin();
+ it_rel != node->inlinks.end();
+ ++it_rel)
+ {
+ DepsRelation *rel = *it_rel;
+ if (rel->from->type == DEPSNODE_TYPE_OPERATION &&
+ (rel->flag & DEPSREL_FLAG_CYCLIC) == 0)
+ {
+ OperationDepsNode *from = (OperationDepsNode *)rel->from;
+ IDDepsNode *id_from_node = from->owner->owner;
+ if ((id_from_node->layers & layers) != 0 &&
+ (from->flag & DEPSOP_FLAG_NEEDS_UPDATE) != 0)
+ {
+ ++node->num_links_pending;
+ }
+ }
+ }
+ }
+ }
+}
+
+static void calculate_eval_priority(OperationDepsNode *node)
+{
+ if (node->done) {
+ return;
+ }
+ node->done = 1;
+
+ if (node->flag & DEPSOP_FLAG_NEEDS_UPDATE) {
+ /* XXX standard cost of a node, could be estimated somewhat later on */
+ const float cost = 1.0f;
+ /* NOOP nodes have no cost */
+ node->eval_priority = node->is_noop() ? cost : 0.0f;
+
+ for (OperationDepsNode::Relations::const_iterator it = node->outlinks.begin();
+ it != node->outlinks.end();
+ ++it)
+ {
+ DepsRelation *rel = *it;
+ OperationDepsNode *to = (OperationDepsNode *)rel->to;
+ BLI_assert(to->type == DEPSNODE_TYPE_OPERATION);
+ calculate_eval_priority(to);
+ node->eval_priority += to->eval_priority;
+ }
+ }
+ else {
+ node->eval_priority = 0.0f;
+ }
+}
+
+static void schedule_graph(TaskPool *pool,
+ Depsgraph *graph,
+ const int layers)
+{
+ BLI_spin_lock(&graph->lock);
+ for (Depsgraph::OperationNodes::const_iterator it = graph->operations.begin();
+ it != graph->operations.end();
+ ++it)
+ {
+ OperationDepsNode *node = *it;
+ IDDepsNode *id_node = node->owner->owner;
+ if ((node->flag & DEPSOP_FLAG_NEEDS_UPDATE) &&
+ node->num_links_pending == 0 &&
+ (id_node->layers & layers) != 0)
+ {
+ BLI_task_pool_push(pool, deg_task_run_func, node, false, TASK_PRIORITY_LOW);
+ node->scheduled = true;
+ }
+ }
+ BLI_spin_unlock(&graph->lock);
+}
+
+static void schedule_children(TaskPool *pool,
+ Depsgraph *graph,
+ OperationDepsNode *node,
+ const int layers)
+{
+ for (OperationDepsNode::Relations::const_iterator it = node->outlinks.begin();
+ it != node->outlinks.end();
+ ++it)
+ {
+ DepsRelation *rel = *it;
+ OperationDepsNode *child = (OperationDepsNode *)rel->to;
+ BLI_assert(child->type == DEPSNODE_TYPE_OPERATION);
+
+ if (child->scheduled) {
+ /* Happens when having cyclic dependencies. */
+ continue;
+ }
+
+ IDDepsNode *id_child = child->owner->owner;
+ if ((id_child->layers & layers) != 0 &&
+ (child->flag & DEPSOP_FLAG_NEEDS_UPDATE) != 0)
+ {
+ if ((rel->flag & DEPSREL_FLAG_CYCLIC) == 0) {
+ BLI_assert(child->num_links_pending > 0);
+ atomic_sub_uint32(&child->num_links_pending, 1);
+ }
+
+ if (child->num_links_pending == 0) {
+ BLI_spin_lock(&graph->lock);
+ bool need_schedule = !child->scheduled;
+ child->scheduled = true;
+ BLI_spin_unlock(&graph->lock);
+
+ if (need_schedule) {
+ BLI_task_pool_push(pool, deg_task_run_func, child, false, TASK_PRIORITY_LOW);
+ }
+ }
+ }
+ }
+}
+
+/**
+ * Evaluate all nodes tagged for updating,
+ * \warning This is usually done as part of main loop, but may also be
+ * called from frame-change update.
+ *
+ * \note Time sources should be all valid!
+ */
+void DEG_evaluate_on_refresh_ex(EvaluationContext *eval_ctx,
+ Depsgraph *graph,
+ const int layers)
+{
+ /* Generate base evaluation context, upon which all the others are derived. */
+ // TODO: this needs both main and scene access...
+
+ /* Nothing to update, early out. */
+ if (graph->entry_tags.size() == 0) {
+ return;
+ }
+
+ /* Set time for the current graph evaluation context. */
+ TimeSourceDepsNode *time_src = graph->find_time_source();
+ eval_ctx->ctime = time_src->cfra;
+
+ /* XXX could use a separate pool for each eval context */
+ DepsgraphEvalState state;
+ state.eval_ctx = eval_ctx;
+ state.graph = graph;
+ state.layers = layers;
+
+ TaskScheduler *task_scheduler = BLI_task_scheduler_get();
+ TaskPool *task_pool = BLI_task_pool_create(task_scheduler, &state);
+
+ if (G.debug & G_DEBUG_DEPSGRAPH_NO_THREADS) {
+ BLI_pool_set_num_threads(task_pool, 1);
+ }
+
+ calculate_pending_parents(graph, layers);
+
+ /* Clear tags. */
+ for (Depsgraph::OperationNodes::const_iterator it = graph->operations.begin();
+ it != graph->operations.end();
+ ++it)
+ {
+ OperationDepsNode *node = *it;
+ node->done = 0;
+ }
+
+ /* Calculate priority for operation nodes. */
+ for (Depsgraph::OperationNodes::const_iterator it = graph->operations.begin();
+ it != graph->operations.end();
+ ++it)
+ {
+ OperationDepsNode *node = *it;
+ calculate_eval_priority(node);
+ }
+
+ DepsgraphDebug::eval_begin(eval_ctx);
+
+ schedule_graph(task_pool, graph, layers);
+
+ BLI_task_pool_work_and_wait(task_pool);
+ BLI_task_pool_free(task_pool);
+
+ DepsgraphDebug::eval_end(eval_ctx);
+
+ /* Clear any uncleared tags - just in case. */
+ DEG_graph_clear_tags(graph);
+}
+
+/* Evaluate all nodes tagged for updating. */
+void DEG_evaluate_on_refresh(EvaluationContext *eval_ctx,
+ Depsgraph *graph,
+ Scene *scene)
+{
+ /* Update time on primary timesource. */
+ TimeSourceDepsNode *tsrc = graph->find_time_source();
+ tsrc->cfra = BKE_scene_frame_get(scene);
+
+ DEG_evaluate_on_refresh_ex(eval_ctx, graph, graph->layers);
+}
+
+/* Frame-change happened for root scene that graph belongs to. */
+void DEG_evaluate_on_framechange(EvaluationContext *eval_ctx,
+ Main *bmain,
+ Depsgraph *graph,
+ float ctime,
+ const int layers)
+{
+ /* Update time on primary timesource. */
+ TimeSourceDepsNode *tsrc = graph->find_time_source();
+ tsrc->cfra = ctime;
+
+ tsrc->tag_update(graph);
+
+ DEG_graph_flush_updates(bmain, graph);
+
+ /* Perform recalculation updates. */
+ DEG_evaluate_on_refresh_ex(eval_ctx, graph, layers);
+}
+
+bool DEG_needs_eval(Depsgraph *graph)
+{
+ return graph->entry_tags.size() != 0;
+}
diff --git a/source/blender/depsgraph/intern/depsgraph_intern.h b/source/blender/depsgraph/intern/depsgraph_intern.h
new file mode 100644
index 00000000000..7fdc2454564
--- /dev/null
+++ b/source/blender/depsgraph/intern/depsgraph_intern.h
@@ -0,0 +1,168 @@
+/*
+ * ***** 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.
+ *
+ * Original Author: Joshua Leung
+ * Contributor(s): None Yet
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/depsgraph/intern/depsgraph_intern.h
+ * \ingroup depsgraph
+ *
+ * API's for internal use in the Depsgraph
+ * - Also, defines for "Node Type Info"
+ */
+
+#ifndef __DEPSGRAPH_INTERN_H__
+#define __DEPSGRAPH_INTERN_H__
+
+#include <cstdlib>
+
+#include "MEM_guardedalloc.h"
+
+#include "depsgraph.h"
+#include "depsnode.h"
+
+struct Main;
+struct Group;
+struct Scene;
+
+/* Graph Building ======================================================== */
+
+/**
+ * Build depsgraph for the given group, and dump results in given graph container
+ * This is usually used for building subgraphs for groups to use...
+ */
+void DEG_graph_build_from_group(Depsgraph *graph, struct Main *bmain, struct Group *group);
+
+/* Build subgraph for group */
+DepsNode *DEG_graph_build_group_subgraph(Depsgraph *graph_main, struct Main *bmain, struct Group *group);
+
+/* Graph Copying ========================================================= */
+/* (Part of the Filtering API) */
+
+/**
+ * Depsgraph Copying Context (dcc)
+ *
+ * Keeps track of node relationships/links/etc. during the copy
+ * operation so that they can be safely remapped...
+ */
+typedef struct DepsgraphCopyContext {
+ struct GHash *nodes_hash; /* <DepsNode, DepsNode> mapping from src node to dst node */
+ struct GHash *rels_hash; // XXX: same for relationships?
+
+ // XXX: filtering criteria...
+} DepsgraphCopyContext;
+
+/* Internal Filtering API ---------------------------------------------- */
+
+/* Create filtering context */
+// XXX: needs params for conditions?
+DepsgraphCopyContext *DEG_filter_init(void);
+
+/* Free filtering context once filtering is done */
+void DEG_filter_cleanup(DepsgraphCopyContext *dcc);
+
+
+/* Data Copy Operations ------------------------------------------------ */
+
+/**
+ * Make a (deep) copy of provided node and it's little subgraph
+ * \warning Newly created node is not added to the existing graph
+ * \param dcc: Context info for helping resolve links
+ */
+DepsNode *DEG_copy_node(DepsgraphCopyContext *dcc, const DepsNode *src);
+
+/* Node Types Handling ================================================= */
+
+/* "Typeinfo" for Node Types ------------------------------------------- */
+
+/* Typeinfo Struct (nti) */
+struct DepsNodeFactory {
+ virtual eDepsNode_Type type() const = 0;
+ virtual eDepsNode_Class tclass() const = 0;
+ virtual const char *tname() const = 0;
+
+ virtual DepsNode *create_node(const ID *id, const string &subdata, const string &name) const = 0;
+ virtual DepsNode *copy_node(DepsgraphCopyContext *dcc, const DepsNode *copy) const = 0;
+};
+
+template <class NodeType>
+struct DepsNodeFactoryImpl : public DepsNodeFactory {
+ eDepsNode_Type type() const { return NodeType::typeinfo.type; }
+ eDepsNode_Class tclass() const { return NodeType::typeinfo.tclass; }
+ const char *tname() const { return NodeType::typeinfo.tname; }
+
+ DepsNode *create_node(const ID *id, const string &subdata, const string &name) const
+ {
+ DepsNode *node = OBJECT_GUARDED_NEW(NodeType);
+
+ /* populate base node settings */
+ node->type = type();
+ node->tclass = tclass();
+
+ if (!name.empty())
+ /* set name if provided ... */
+ node->name = name;
+ else
+ /* ... otherwise use default type name */
+ node->name = tname();
+
+ node->init(id, subdata);
+
+ return node;
+ }
+
+ virtual DepsNode *copy_node(DepsgraphCopyContext *dcc, const DepsNode *copy) const
+ {
+ BLI_assert(copy->type == type());
+ DepsNode *node = OBJECT_GUARDED_NEW(NodeType);
+
+ /* populate base node settings */
+ node->type = type();
+ node->tclass = tclass();
+ // XXX: need to review the name here, as we can't have exact duplicates...
+ node->name = copy->name;
+
+ node->copy(dcc, static_cast<const NodeType *>(copy));
+
+ return node;
+ }
+};
+
+/* Typeinfo Management -------------------------------------------------- */
+
+/* Register typeinfo */
+void DEG_register_node_typeinfo(DepsNodeFactory *factory);
+
+/* Get typeinfo for specified type */
+DepsNodeFactory *DEG_get_node_factory(const eDepsNode_Type type);
+
+/* Get typeinfo for provided node */
+DepsNodeFactory *DEG_node_get_factory(const DepsNode *node);
+
+/* Editors Integration -------------------------------------------------- */
+
+void deg_editors_id_update(struct Main *bmain, struct ID *id);
+
+void deg_editors_scene_update(struct Main *bmain, struct Scene *scene, bool updated);
+
+#endif /* __DEPSGRAPH_INTERN_H__ */
diff --git a/source/blender/depsgraph/intern/depsgraph_query.cc b/source/blender/depsgraph/intern/depsgraph_query.cc
new file mode 100644
index 00000000000..73193747b93
--- /dev/null
+++ b/source/blender/depsgraph/intern/depsgraph_query.cc
@@ -0,0 +1,217 @@
+/*
+ * ***** 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.
+ *
+ * Original Author: Joshua Leung
+ * Contributor(s): None Yet
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/depsgraph/intern/depsgraph_query.cc
+ * \ingroup depsgraph
+ *
+ * Implementation of Querying and Filtering API's
+ */
+
+#include "MEM_guardedalloc.h"
+
+extern "C" {
+#include "BLI_utildefines.h"
+#include "BLI_ghash.h"
+
+#include "BKE_main.h"
+
+#include "DEG_depsgraph_query.h"
+} /* extern "C" */
+
+#include "depsgraph_queue.h"
+#include "depsnode.h"
+#include "depsnode_operation.h"
+#include "depsgraph_intern.h"
+
+/* ************************* */
+/* Low-Level Graph Traversal */
+
+#if 0
+/* Prepare for graph traversal, by tagging nodes, etc. */
+static void DEG_graph_traverse_begin(Depsgraph * /*graph*/)
+{
+ /* go over all nodes, initialising the valence counts */
+ // XXX: this will end up being O(|V|), which is bad when we're just updating a few nodes...
+}
+
+/* Perform a traversal of graph from given starting node (in execution order) */
+// TODO: additional flags for controlling the process?
+void DEG_graph_traverse_from_node(Depsgraph *graph, OperationDepsNode *start_node,
+ DEG_FilterPredicate filter, void *filter_data,
+ DEG_NodeOperation op, void *operation_data)
+{
+ DepsgraphQueue *q;
+
+ /* sanity checks */
+ if (ELEM(NULL, graph, start_node, op))
+ return;
+
+ /* add node as starting node to be evaluated, with value of 0 */
+ q = DEG_queue_new();
+
+ start_node->num_links_pending = 0;
+ DEG_queue_push(q, start_node, 0.0f);
+
+ /* while we still have nodes in the queue, grab and work on next one */
+ do {
+ /* grab item at front of queue */
+ // XXX: in practice, we may need to wait until one becomes available...
+ OperationDepsNode *node = (OperationDepsNode *)DEG_queue_pop(q);
+
+ /* perform operation on node */
+ op(graph, node, operation_data);
+
+ /* schedule up operations which depend on this */
+ DEPSNODE_RELATIONS_ITER_BEGIN(node->outlinks, rel)
+ {
+ /* ensure that relationship is not tagged for ignoring (i.e. cyclic, etc.) */
+ // TODO: cyclic refs should probably all get clustered towards the end, so that we can just stop on the first one
+ if ((rel->flag & DEPSREL_FLAG_CYCLIC) == 0) {
+ OperationDepsNode *child_node = (OperationDepsNode *)rel->to;
+
+ /* only visit node if the filtering function agrees */
+ if ((filter == NULL) || filter(graph, child_node, filter_data)) {
+ /* schedule up node... */
+ child_node->num_links_pending--;
+ DEG_queue_push(q, child_node, (float)child_node->num_links_pending);
+ }
+ }
+ }
+ DEPSNODE_RELATIONS_ITER_END;
+ } while (DEG_queue_is_empty(q) == false);
+
+ /* cleanup */
+ DEG_queue_free(q);
+}
+#endif
+
+/* ************************************************************** */
+/* Filtering API - Basically, making a copy of the existing graph */
+
+/* Create filtering context */
+// TODO: allow passing in a number of criteria?
+DepsgraphCopyContext *DEG_filter_init()
+{
+ DepsgraphCopyContext *dcc = (DepsgraphCopyContext *)MEM_callocN(sizeof(DepsgraphCopyContext), "DepsgraphCopyContext");
+
+ /* init hashes for easy lookups */
+ dcc->nodes_hash = BLI_ghash_ptr_new("Depsgraph Filter NodeHash");
+ dcc->rels_hash = BLI_ghash_ptr_new("Depsgraph Filter Relationship Hash"); // XXX?
+
+ /* store filtering criteria? */
+ // xxx...
+
+ return dcc;
+}
+
+/* Cleanup filtering context */
+void DEG_filter_cleanup(DepsgraphCopyContext *dcc)
+{
+ /* sanity check */
+ if (dcc == NULL)
+ return;
+
+ /* free hashes - contents are weren't copied, so are ok... */
+ BLI_ghash_free(dcc->nodes_hash, NULL, NULL);
+ BLI_ghash_free(dcc->rels_hash, NULL, NULL);
+
+ /* clear filtering criteria */
+ // ...
+
+ /* free dcc itself */
+ MEM_freeN(dcc);
+}
+
+/* -------------------------------------------------- */
+
+/* Create a copy of provided node */
+// FIXME: the handling of sub-nodes and links will need to be subject to filtering options...
+// XXX: perhaps this really shouldn't be exposed, as it will just be a sub-step of the evaluation process?
+DepsNode *DEG_copy_node(DepsgraphCopyContext *dcc, const DepsNode *src)
+{
+ /* sanity check */
+ if (src == NULL)
+ return NULL;
+
+ DepsNodeFactory *factory = DEG_get_node_factory(src->type);
+ BLI_assert(factory != NULL);
+ DepsNode *dst = factory->copy_node(dcc, src);
+
+ /* add this node-pair to the hash... */
+ BLI_ghash_insert(dcc->nodes_hash, (DepsNode *)src, dst);
+
+#if 0 /* XXX TODO */
+ /* now, fix up any links in standard "node header" (i.e. DepsNode struct, that all
+ * all others are derived from) that are now corrupt
+ */
+ {
+ /* relationships to other nodes... */
+ // FIXME: how to handle links? We may only have partial set of all nodes still?
+ // XXX: the exact details of how to handle this are really part of the querying API...
+
+ // XXX: BUT, for copying subgraphs, we'll need to define an API for doing this stuff anyways
+ // (i.e. for resolving and patching over links that exist within subtree...)
+ dst->inlinks.clear();
+ dst->outlinks.clear();
+
+ /* clear traversal data */
+ dst->num_links_pending = 0;
+ dst->lasttime = 0;
+ }
+
+ /* fix links */
+ // XXX...
+#endif
+
+ /* return copied node */
+ return dst;
+}
+
+bool DEG_id_type_tagged(Main *bmain, short idtype)
+{
+ return bmain->id_tag_update[((unsigned char *)&idtype)[0]] != 0;
+}
+
+short DEG_get_eval_flags_for_id(Depsgraph *graph, ID *id)
+{
+ if (graph == NULL) {
+ /* Happens when converting objects to mesh from a python script
+ * after modifying scene graph.
+ *
+ * Currently harmless because it's only called for temporary
+ * objects which are out of the DAG anyway.
+ */
+ return 0;
+ }
+
+ IDDepsNode *id_node = graph->find_id_node(id);
+ if (id_node == NULL) {
+ /* TODO(sergey): Does it mean we need to check set scene? */
+ return 0;
+ }
+
+ return id_node->eval_flags;
+}
diff --git a/source/blender/depsgraph/intern/depsgraph_queue.cc b/source/blender/depsgraph/intern/depsgraph_queue.cc
new file mode 100644
index 00000000000..da60d73bc46
--- /dev/null
+++ b/source/blender/depsgraph/intern/depsgraph_queue.cc
@@ -0,0 +1,177 @@
+/*
+ * ***** 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.
+ *
+ * Original Author: Joshua Leung
+ * Contributor(s): None Yet
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/depsgraph/intern/depsgraph_queue.cc
+ * \ingroup depsgraph
+ *
+ * Implementation of special queue type for use in Depsgraph traversals.
+ */
+
+#include <stdlib.h>
+
+#include "MEM_guardedalloc.h"
+
+extern "C" {
+#include "BLI_utildefines.h"
+#include "BLI_heap.h"
+#include "BLI_ghash.h"
+} /* extern "C" */
+
+#include "depsgraph_queue.h"
+
+/* ****************************** */
+/* Depsgraph Queue implementation */
+
+/* Data Management ----------------------------------------- */
+
+DepsgraphQueue *DEG_queue_new(void)
+{
+ DepsgraphQueue *q = (DepsgraphQueue *)MEM_callocN(sizeof(DepsgraphQueue), "DEG_queue_new()");
+
+ /* init data structures for use here */
+ q->pending_heap = BLI_heap_new();
+ q->pending_hash = BLI_ghash_ptr_new("DEG Queue Pending Hash");
+
+ q->ready_heap = BLI_heap_new();
+
+ /* init settings */
+ q->idx = 0;
+ q->tot = 0;
+
+ /* return queue */
+ return q;
+}
+
+void DEG_queue_free(DepsgraphQueue *q)
+{
+ /* free data structures */
+ BLI_assert(BLI_heap_size(q->pending_heap) == 0);
+ BLI_assert(BLI_heap_size(q->ready_heap) == 0);
+ BLI_assert(BLI_ghash_size(q->pending_hash) == 0);
+
+ BLI_heap_free(q->pending_heap, NULL);
+ BLI_heap_free(q->ready_heap, NULL);
+ BLI_ghash_free(q->pending_hash, NULL, NULL);
+
+ /* free queue itself */
+ MEM_freeN(q);
+}
+
+/* Statistics --------------------------------------------- */
+
+/* Get the number of nodes which are we should visit, but are not able to yet */
+size_t DEG_queue_num_pending(DepsgraphQueue *q)
+{
+ return BLI_heap_size(q->pending_heap);
+}
+
+/* Get the number of nodes which are now ready to be visited */
+size_t DEG_queue_num_ready(DepsgraphQueue *q)
+{
+ return BLI_heap_size(q->ready_heap);
+}
+
+/* Get total size of queue */
+size_t DEG_queue_size(DepsgraphQueue *q)
+{
+ return DEG_queue_num_pending(q) + DEG_queue_num_ready(q);
+}
+
+/* Check if queue has any items in it (still passing through) */
+bool DEG_queue_is_empty(DepsgraphQueue *q)
+{
+ return DEG_queue_size(q) == 0;
+}
+
+/* Queue Operations --------------------------------------- */
+
+/**
+ * Add DepsNode to the queue
+ * \param dnode: ``(DepsNode *)`` node to add to the queue
+ * Each node is only added once to the queue; Subsequent pushes
+ * merely update its status (e.g. moving it from "pending" to "ready")
+ * \param cost: new "num_links_pending" count for node *after* it has encountered
+ * via an outlink from the node currently being visited
+ * (i.e. we're one of the dependencies which may now be able to be processed)
+ */
+void DEG_queue_push(DepsgraphQueue *q, void *dnode, float cost)
+{
+ HeapNode *hnode = NULL;
+
+ /* Shortcut: Directly add to ready if node isn't waiting on anything now... */
+ if (cost == 0) {
+ /* node is now ready to be visited - schedule it up for such */
+ if (BLI_ghash_haskey(q->pending_hash, dnode)) {
+ /* remove from pending queue - we're moving it to the scheduling queue */
+ hnode = (HeapNode *)BLI_ghash_lookup(q->pending_hash, dnode);
+ BLI_heap_remove(q->pending_heap, hnode);
+
+ BLI_ghash_remove(q->pending_hash, dnode, NULL, NULL);
+ }
+
+ /* schedule up node using latest count (of ready nodes) */
+ BLI_heap_insert(q->ready_heap, (float)q->idx, dnode);
+ q->idx++;
+ }
+ else {
+ /* node is still waiting on some other ancestors,
+ * so add it to the pending heap in the meantime...
+ */
+ // XXX: is this even necessary now?
+ if (BLI_ghash_haskey(q->pending_hash, dnode)) {
+ /* just update cost on pending node */
+ hnode = (HeapNode *)BLI_ghash_lookup(q->pending_hash, dnode);
+ BLI_heap_remove(q->pending_heap, hnode);
+ BLI_heap_insert(q->pending_heap, cost, hnode);
+ }
+ else {
+ /* add new node to pending queue, and increase size of overall queue */
+ hnode = BLI_heap_insert(q->pending_heap, cost, dnode);
+ q->tot++;
+ }
+ }
+}
+
+/* Grab a "ready" node from the queue */
+void *DEG_queue_pop(DepsgraphQueue *q)
+{
+ /* sanity check: if there are no "ready" nodes,
+ * start pulling from "pending" to keep things moving,
+ * but throw a warning so that we know that something's up here...
+ */
+ if (BLI_heap_is_empty(q->ready_heap)) {
+ // XXX: this should never happen
+ // XXX: if/when it does happen, we may want instead to just wait until something pops up here...
+ printf("DepsgraphHeap Warning: No more ready nodes available. Trying from pending (idx = %d, tot = %d, pending = %d, ready = %d)\n",
+ (int)q->idx, (int)q->tot, (int)DEG_queue_num_pending(q), (int)DEG_queue_num_ready(q));
+
+ return BLI_heap_popmin(q->pending_heap);
+ }
+ else {
+ /* only grab "ready" nodes */
+ return BLI_heap_popmin(q->ready_heap);
+ }
+}
diff --git a/source/blender/depsgraph/intern/depsgraph_queue.h b/source/blender/depsgraph/intern/depsgraph_queue.h
new file mode 100644
index 00000000000..b85d46bd173
--- /dev/null
+++ b/source/blender/depsgraph/intern/depsgraph_queue.h
@@ -0,0 +1,91 @@
+/*
+ * ***** 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.
+ *
+ * Original Author: Joshua Leung
+ * Contributor(s): None Yet
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/depsgraph/intern/depsgraph_queue.h
+ * \ingroup depsgraph
+ *
+ * Defines for special queue type for use in Depsgraph traversals.
+ */
+
+#ifndef __DEPSGRAPH_QUEUE_H__
+#define __DEPSGRAPH_QUEUE_H__
+
+struct DepsNode;
+
+struct Heap;
+struct GHash;
+
+/* *********************************************** */
+/* Dependency Graph Traversal Queue
+ *
+ * There are two parts to this:
+ * a) "Pending" Nodes - This part contains the set of nodes
+ * which are related to those which have been visited
+ * previously, but are not yet ready to actually be visited.
+ * b) "Scheduled" Nodes - These are the nodes whose ancestors
+ * have all been evaluated already, which means that any
+ * or all of them can be picked (in practically in order) to
+ * be visited immediately.
+ *
+ * Internally, the queue makes sure that each node in the graph
+ * only gets added to the queue once. This is because there can
+ * be multiple inlinks to each node given the way that the relations
+ * work.
+ */
+
+/* Depsgraph Queue Type */
+typedef struct DepsgraphQueue {
+ /* Pending */
+ struct Heap *pending_heap; /* (valence:int, DepsNode*) */
+ struct GHash *pending_hash; /* (DepsNode* : HeapNode*>) */
+
+ /* Ready to be visited - fifo */
+ struct Heap *ready_heap; /* (idx:int, DepsNode*) */
+
+ /* Size/Order counts */
+ size_t idx; /* total number of nodes which are/have been ready so far (including those already visited) */
+ size_t tot; /* total number of nodes which have passed through queue; mainly for debug */
+} DepsgraphQueue;
+
+/* ************************** */
+/* Depsgraph Queue Operations */
+
+/* Data management */
+DepsgraphQueue *DEG_queue_new(void);
+void DEG_queue_free(DepsgraphQueue *q);
+
+/* Statistics */
+size_t DEG_queue_num_pending(DepsgraphQueue *q);
+size_t DEG_queue_num_ready(DepsgraphQueue *q);
+
+size_t DEG_queue_size(DepsgraphQueue *q);
+bool DEG_queue_is_empty(DepsgraphQueue *q);
+
+/* Operations */
+void DEG_queue_push(DepsgraphQueue *q, void *dnode, float cost = 0.0f);
+void *DEG_queue_pop(DepsgraphQueue *q);
+
+#endif /* DEPSGRAPH_QUEUE_H */
diff --git a/source/blender/depsgraph/intern/depsgraph_tag.cc b/source/blender/depsgraph/intern/depsgraph_tag.cc
new file mode 100644
index 00000000000..65d75fccad3
--- /dev/null
+++ b/source/blender/depsgraph/intern/depsgraph_tag.cc
@@ -0,0 +1,541 @@
+/*
+ * ***** 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.
+ *
+ * Original Author: Joshua Leung
+ * Contributor(s): None Yet
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/depsgraph/intern/depsgraph_tag.cc
+ * \ingroup depsgraph
+ *
+ * Core routines for how the Depsgraph works.
+ */
+
+#include <stdio.h>
+#include <cstring>
+#include <queue>
+
+extern "C" {
+#include "BLI_utildefines.h"
+
+#include "DNA_object_types.h"
+#include "DNA_particle_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_windowmanager_types.h"
+
+#include "BKE_library.h"
+#include "BKE_main.h"
+#include "BKE_node.h"
+
+#define new new_
+#include "BKE_screen.h"
+#undef new
+
+#include "DEG_depsgraph.h"
+} /* extern "C" */
+
+#include "depsgraph_debug.h"
+#include "depsnode.h"
+#include "depsnode_component.h"
+#include "depsnode_operation.h"
+#include "depsgraph_intern.h"
+
+/* *********************** */
+/* Update Tagging/Flushing */
+
+/* Legacy depsgraph did some special trickery for things like particle systems
+ * when tagging ID for an update. Ideally that tagging needs to become obsolete
+ * in favor of havng dedicated node for that which gets tagged, but for until
+ * design of those areas is more clear we'll do the same legacy code here.
+ * - sergey -
+ */
+#define DEPSGRAPH_USE_LEGACY_TAGGING
+
+namespace {
+
+/* Data-Based Tagging ------------------------------- */
+
+void lib_id_recalc_tag(Main *bmain, ID *id)
+{
+ id->flag |= LIB_ID_RECALC;
+ DEG_id_type_tag(bmain, GS(id->name));
+}
+
+void lib_id_recalc_data_tag(Main *bmain, ID *id)
+{
+ id->flag |= LIB_ID_RECALC_DATA;
+ DEG_id_type_tag(bmain, GS(id->name));
+}
+
+void lib_id_recalc_tag_flag(Main *bmain, ID *id, int flag)
+{
+ if (flag) {
+ /* This bit of code ensures legacy object->recalc flags
+ * are still filled in the same way as it was expected
+ * with the old dependency graph.
+ *
+ * This is because some areas like motion paths and likely
+ * some other physics baking process are doing manual scene
+ * update on all the frames, trying to minimize number of
+ * updates.
+ *
+ * But this flag will also let us to re-construct entry
+ * nodes for update after relations update and after layer
+ * visibility changes.
+ */
+ short idtype = GS(id->name);
+ if (idtype == ID_OB) {
+ Object *object = (Object *)id;
+ object->recalc |= (flag & OB_RECALC_ALL);
+ }
+
+ if (flag & OB_RECALC_OB)
+ lib_id_recalc_tag(bmain, id);
+ if (flag & (OB_RECALC_DATA | PSYS_RECALC))
+ lib_id_recalc_data_tag(bmain, id);
+ }
+ else {
+ lib_id_recalc_tag(bmain, id);
+ }
+}
+
+#ifdef DEPSGRAPH_USE_LEGACY_TAGGING
+void depsgraph_legacy_handle_update_tag(Main *bmain, ID *id, short flag)
+{
+ if (flag) {
+ Object *object;
+ short idtype = GS(id->name);
+ if (idtype == ID_PA) {
+ ParticleSystem *psys;
+ for (object = (Object *)bmain->object.first;
+ object != NULL;
+ object = (Object *)object->id.next)
+ {
+ for (psys = (ParticleSystem *)object->particlesystem.first;
+ psys != NULL;
+ psys = (ParticleSystem *)psys->next)
+ {
+ if (&psys->part->id == id) {
+ DEG_id_tag_update_ex(bmain, &object->id, flag & OB_RECALC_ALL);
+ psys->recalc |= (flag & PSYS_RECALC);
+ }
+ }
+ }
+ }
+ }
+}
+#endif
+
+} /* namespace */
+
+/* Tag all nodes in ID-block for update.
+ * This is a crude measure, but is most convenient for old code.
+ */
+void DEG_graph_id_tag_update(Main *bmain, Depsgraph *graph, ID *id)
+{
+ IDDepsNode *node = graph->find_id_node(id);
+ lib_id_recalc_tag(bmain, id);
+ if (node != NULL) {
+ node->tag_update(graph);
+ }
+}
+
+/* Tag nodes related to a specific piece of data */
+void DEG_graph_data_tag_update(Depsgraph *graph, const PointerRNA *ptr)
+{
+ DepsNode *node = graph->find_node_from_pointer(ptr, NULL);
+ if (node) {
+ node->tag_update(graph);
+ }
+ else {
+ printf("Missing node in %s\n", __func__);
+ BLI_assert(!"Shouldn't happens since it'll miss crucial update.");
+ }
+}
+
+/* Tag nodes related to a specific property. */
+void DEG_graph_property_tag_update(Depsgraph *graph,
+ const PointerRNA *ptr,
+ const PropertyRNA *prop)
+{
+ DepsNode *node = graph->find_node_from_pointer(ptr, prop);
+ if (node) {
+ node->tag_update(graph);
+ }
+ else {
+ printf("Missing node in %s\n", __func__);
+ BLI_assert(!"Shouldn't happens since it'll miss crucial update.");
+ }
+}
+
+/* Tag given ID for an update in all the dependency graphs. */
+void DEG_id_tag_update(ID *id, short flag)
+{
+ DEG_id_tag_update_ex(G.main, id, flag);
+}
+
+void DEG_id_tag_update_ex(Main *bmain, ID *id, short flag)
+{
+ if (id == NULL) {
+ /* Ideally should not happen, but old depsgraph allowed this. */
+ return;
+ }
+ DEG_DEBUG_PRINTF("%s: id=%s flag=%d\n", __func__, id->name, flag);
+ lib_id_recalc_tag_flag(bmain, id, flag);
+ for (Scene *scene = (Scene *)bmain->scene.first;
+ scene != NULL;
+ scene = (Scene *)scene->id.next)
+ {
+ if (scene->depsgraph) {
+ Depsgraph *graph = scene->depsgraph;
+ if (flag == 0) {
+ /* TODO(sergey): Currently blender is still tagging IDs
+ * for recalc just using flag=0. This isn't totally correct
+ * but we'd better deal with such cases and don't fail.
+ */
+ DEG_graph_id_tag_update(bmain, graph, id);
+ continue;
+ }
+ if (flag & OB_RECALC_DATA && GS(id->name) == ID_OB) {
+ Object *object = (Object *)id;
+ if (object->data != NULL) {
+ DEG_graph_id_tag_update(bmain,
+ graph,
+ (ID *)object->data);
+ }
+ }
+ if (flag & (OB_RECALC_OB | OB_RECALC_DATA)) {
+ DEG_graph_id_tag_update(bmain, graph, id);
+ }
+ }
+ }
+
+#ifdef DEPSGRAPH_USE_LEGACY_TAGGING
+ /* Special handling from the legacy depsgraph.
+ * TODO(sergey): Need to get rid of those once all the areas
+ * are re-formulated in terms of franular nodes.
+ */
+ depsgraph_legacy_handle_update_tag(bmain, id, flag);
+#endif
+}
+
+/* Tag given ID type for update. */
+void DEG_id_type_tag(Main *bmain, short idtype)
+{
+ if (idtype == ID_NT) {
+ /* Stupid workaround so parent datablocks of nested nodetree get looped
+ * over when we loop over tagged datablock types.
+ */
+ DEG_id_type_tag(bmain, ID_MA);
+ DEG_id_type_tag(bmain, ID_TE);
+ DEG_id_type_tag(bmain, ID_LA);
+ DEG_id_type_tag(bmain, ID_WO);
+ DEG_id_type_tag(bmain, ID_SCE);
+ }
+ /* We tag based on first ID type character to avoid
+ * looping over all ID's in case there are no tags.
+ */
+ bmain->id_tag_update[((unsigned char *)&idtype)[0]] = 1;
+}
+
+/* Update Flushing ---------------------------------- */
+
+/* FIFO queue for tagged nodes that need flushing */
+/* XXX This may get a dedicated implementation later if needed - lukas */
+typedef std::queue<OperationDepsNode *> FlushQueue;
+
+/* Flush updates from tagged nodes outwards until all affected nodes are tagged. */
+void DEG_graph_flush_updates(Main *bmain, Depsgraph *graph)
+{
+ /* sanity check */
+ if (graph == NULL)
+ return;
+
+ /* Nothing to update, early out. */
+ if (graph->entry_tags.size() == 0) {
+ return;
+ }
+
+ /* TODO(sergey): With a bit of flag magic we can get rid of this
+ * extra loop.
+ */
+ for (Depsgraph::OperationNodes::const_iterator it = graph->operations.begin();
+ it != graph->operations.end();
+ ++it)
+ {
+ OperationDepsNode *node = *it;
+ node->scheduled = false;
+ }
+
+ FlushQueue queue;
+ /* Starting from the tagged "entry" nodes, flush outwards... */
+ /* NOTE: Also need to ensure that for each of these, there is a path back to
+ * root, or else they won't be done.
+ * NOTE: Count how many nodes we need to handle - entry nodes may be
+ * component nodes which don't count for this purpose!
+ */
+ for (Depsgraph::EntryTags::const_iterator it = graph->entry_tags.begin();
+ it != graph->entry_tags.end();
+ ++it)
+ {
+ OperationDepsNode *node = *it;
+ IDDepsNode *id_node = node->owner->owner;
+ queue.push(node);
+ deg_editors_id_update(bmain, id_node->id);
+ node->scheduled = true;
+ }
+
+ while (!queue.empty()) {
+ OperationDepsNode *node = queue.front();
+ queue.pop();
+
+ IDDepsNode *id_node = node->owner->owner;
+ lib_id_recalc_tag(bmain, id_node->id);
+ /* TODO(sergey): For until we've got proper data nodes in the graph. */
+ lib_id_recalc_data_tag(bmain, id_node->id);
+
+ ID *id = id_node->id;
+ /* This code is used to preserve those areas which does direct
+ * object update,
+ *
+ * Plus it ensures visibility changes and relations and layers
+ * visibility update has proper flags to work with.
+ */
+ if (GS(id->name) == ID_OB) {
+ Object *object = (Object *)id;
+ ComponentDepsNode *comp_node = node->owner;
+ if (comp_node->type == DEPSNODE_TYPE_ANIMATION) {
+ object->recalc |= OB_RECALC_TIME;
+ }
+ else if (comp_node->type == DEPSNODE_TYPE_TRANSFORM) {
+ object->recalc |= OB_RECALC_OB;
+ }
+ else {
+ object->recalc |= OB_RECALC_DATA;
+ }
+ }
+
+ /* Flush to nodes along links... */
+ for (OperationDepsNode::Relations::const_iterator it = node->outlinks.begin();
+ it != node->outlinks.end();
+ ++it)
+ {
+ DepsRelation *rel = *it;
+ OperationDepsNode *to_node = (OperationDepsNode *)rel->to;
+ if (to_node->scheduled == false) {
+ to_node->flag |= DEPSOP_FLAG_NEEDS_UPDATE;
+ queue.push(to_node);
+ to_node->scheduled = true;
+ deg_editors_id_update(bmain, id_node->id);
+ }
+ }
+
+ /* TODO(sergey): For until incremental updates are possible
+ * witin a component at least we tag the whole component
+ * for update.
+ */
+ for (ComponentDepsNode::OperationMap::iterator it = node->owner->operations.begin();
+ it != node->owner->operations.end();
+ ++it)
+ {
+ OperationDepsNode *op = it->second;
+ op->flag |= DEPSOP_FLAG_NEEDS_UPDATE;
+ }
+ }
+}
+
+/* Recursively push updates out to all nodes dependent on this,
+ * until all affected are tagged and/or scheduled up for eval
+ */
+void DEG_ids_flush_tagged(Main *bmain)
+{
+ for (Scene *scene = (Scene *)bmain->scene.first;
+ scene != NULL;
+ scene = (Scene *)scene->id.next)
+ {
+ /* TODO(sergey): Only visible scenes? */
+ if (scene->depsgraph != NULL) {
+ DEG_graph_flush_updates(bmain, scene->depsgraph);
+ }
+ }
+}
+
+/* Clear tags from all operation nodes. */
+void DEG_graph_clear_tags(Depsgraph *graph)
+{
+ /* Go over all operation nodes, clearing tags. */
+ for (Depsgraph::OperationNodes::const_iterator it = graph->operations.begin();
+ it != graph->operations.end();
+ ++it)
+ {
+ OperationDepsNode *node = *it;
+
+ /* Clear node's "pending update" settings. */
+ node->flag &= ~(DEPSOP_FLAG_DIRECTLY_MODIFIED | DEPSOP_FLAG_NEEDS_UPDATE);
+ /* Reset so that it can be bumped up again. */
+ node->num_links_pending = 0;
+ node->scheduled = false;
+ }
+
+ /* Clear any entry tags which haven't been flushed. */
+ graph->entry_tags.clear();
+}
+
+/* Update dependency graph when visible scenes/layers changes. */
+void DEG_graph_on_visible_update(Main *bmain, Scene *scene)
+{
+ Depsgraph *graph = scene->depsgraph;
+ wmWindowManager *wm = (wmWindowManager *)bmain->wm.first;
+ int old_layers = graph->layers;
+ if (wm != NULL) {
+ BKE_main_id_flag_listbase(&bmain->scene, LIB_DOIT, true);
+ graph->layers = 0;
+ for (wmWindow *win = (wmWindow *)wm->windows.first;
+ win != NULL;
+ win = (wmWindow *)win->next)
+ {
+ Scene *scene = win->screen->scene;
+ if (scene->id.flag & LIB_DOIT) {
+ graph->layers |= BKE_screen_visible_layers(win->screen, scene);
+ scene->id.flag &= ~LIB_DOIT;
+ }
+ }
+ }
+ else {
+ /* All the layers for background render for now. */
+ graph->layers = (1 << 20) - 1;
+ }
+ if (old_layers != graph->layers) {
+ /* Tag all objects which becomes visible (or which becomes needed for dependencies)
+ * for recalc.
+ *
+ * This is mainly needed on file load only, after that updates of invisible objects
+ * will be stored in the pending list.
+ */
+ for (Depsgraph::OperationNodes::const_iterator it = graph->operations.begin();
+ it != graph->operations.end();
+ ++it)
+ {
+ OperationDepsNode *node = *it;
+ IDDepsNode *id_node = node->owner->owner;
+ ID *id = id_node->id;
+ if ((id->flag & LIB_ID_RECALC_ALL) != 0 ||
+ (id_node->layers & scene->lay_updated) == 0)
+ {
+ id_node->tag_update(graph);
+ }
+ /* A bit of magic: if object->recalc is set it means somebody tagged
+ * it for update. If corresponding ID recalc flags are zero it means
+ * graph has been evaluated after that and the recalc was skipped
+ * because of visibility check.
+ */
+ if (GS(id->name) == ID_OB) {
+ Object *object = (Object *)id;
+ if ((id->flag & LIB_ID_RECALC_ALL) == 0 &&
+ (object->recalc & OB_RECALC_ALL) != 0)
+ {
+ id_node->tag_update(graph);
+ ComponentDepsNode *anim_comp =
+ id_node->find_component(DEPSNODE_TYPE_ANIMATION);
+ if (anim_comp != NULL && object->recalc & OB_RECALC_TIME) {
+ anim_comp->tag_update(graph);
+ }
+ }
+ }
+ }
+ }
+ scene->lay_updated |= graph->layers;
+}
+
+void DEG_on_visible_update(Main *bmain, const bool UNUSED(do_time))
+{
+ for (Scene *scene = (Scene *)bmain->scene.first;
+ scene != NULL;
+ scene = (Scene *)scene->id.next)
+ {
+ if (scene->depsgraph != NULL) {
+ DEG_graph_on_visible_update(bmain, scene);
+ }
+ }
+}
+
+/* Check if something was changed in the database and inform
+ * editors about this.
+ */
+void DEG_ids_check_recalc(Main *bmain, Scene *scene, bool time)
+{
+ ListBase *lbarray[MAX_LIBARRAY];
+ int a;
+ bool updated = false;
+
+ /* Loop over all ID types. */
+ a = set_listbasepointers(bmain, lbarray);
+ while (a--) {
+ ListBase *lb = lbarray[a];
+ ID *id = (ID *)lb->first;
+
+ /* We tag based on first ID type character to avoid
+ * looping over all ID's in case there are no tags.
+ */
+ if (id && bmain->id_tag_update[(unsigned char)id->name[0]]) {
+ updated = true;
+ break;
+ }
+ }
+
+ deg_editors_scene_update(bmain, scene, (updated || time));
+}
+
+void DEG_ids_clear_recalc(Main *bmain)
+{
+ ListBase *lbarray[MAX_LIBARRAY];
+ bNodeTree *ntree;
+ int a;
+
+ /* TODO(sergey): Re-implement POST_UPDATE_HANDLER_WORKAROUND using entry_tags
+ * and id_tags storage from the new dependency graph.
+ */
+
+ /* Loop over all ID types. */
+ a = set_listbasepointers(bmain, lbarray);
+ while (a--) {
+ ListBase *lb = lbarray[a];
+ ID *id = (ID *)lb->first;
+
+ /* We tag based on first ID type character to avoid
+ * looping over all ID's in case there are no tags.
+ */
+ if (id && bmain->id_tag_update[(unsigned char)id->name[0]]) {
+ for (; id; id = (ID *)id->next) {
+ id->flag &= ~(LIB_ID_RECALC | LIB_ID_RECALC_DATA);
+
+ /* Some ID's contain semi-datablock nodetree */
+ ntree = ntreeFromID(id);
+ if (ntree != NULL) {
+ ntree->id.flag &= ~(LIB_ID_RECALC | LIB_ID_RECALC_DATA);
+ }
+ }
+ }
+ }
+
+ memset(bmain->id_tag_update, 0, sizeof(bmain->id_tag_update));
+}
diff --git a/source/blender/depsgraph/intern/depsgraph_type_defines.cc b/source/blender/depsgraph/intern/depsgraph_type_defines.cc
new file mode 100644
index 00000000000..5a3048a4aa3
--- /dev/null
+++ b/source/blender/depsgraph/intern/depsgraph_type_defines.cc
@@ -0,0 +1,102 @@
+/*
+ * ***** 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.
+ *
+ * Original Author: Joshua Leung
+ * Contributor(s): None Yet
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/depsgraph/intern/depsgraph_type_defines.cc
+ * \ingroup depsgraph
+ *
+ * Defines and code for core node types.
+ */
+
+extern "C" {
+#include "BLI_utildefines.h"
+#include "BLI_ghash.h"
+
+#include "DEG_depsgraph.h"
+} /* extern "C" */
+
+#include "depsgraph_intern.h"
+#include "depsnode.h"
+#include "depsnode_component.h"
+#include "depsnode_operation.h"
+
+/* ************ */
+/* External API */
+
+/* Global type registry */
+
+/**
+ * \note For now, this is a hashtable not array, since the core node types
+ * currently do not have contiguous ID values. Using a hash here gives us
+ * more flexibility, albeit using more memory and also sacrificing a little
+ * speed. Later on, when things stabilise we may turn this back to an array
+ * since there are only just a few node types that an array would cope fine...
+ */
+static GHash *_depsnode_typeinfo_registry = NULL;
+
+/* Registration ------------------------------------------- */
+
+/* Register node type */
+void DEG_register_node_typeinfo(DepsNodeFactory *factory)
+{
+ BLI_assert(factory != NULL);
+ BLI_ghash_insert(_depsnode_typeinfo_registry, SET_INT_IN_POINTER(factory->type()), factory);
+}
+
+/* Register all node types */
+void DEG_register_node_types(void)
+{
+ /* initialise registry */
+ _depsnode_typeinfo_registry = BLI_ghash_int_new("Depsgraph Node Type Registry");
+
+ /* register node types */
+ DEG_register_base_depsnodes();
+ DEG_register_component_depsnodes();
+ DEG_register_operation_depsnodes();
+}
+
+/* Free registry on exit */
+void DEG_free_node_types(void)
+{
+ BLI_ghash_free(_depsnode_typeinfo_registry, NULL, NULL);
+}
+
+/* Getters ------------------------------------------------- */
+
+/* Get typeinfo for specified type */
+DepsNodeFactory *DEG_get_node_factory(const eDepsNode_Type type)
+{
+ /* look up type - at worst, it doesn't exist in table yet, and we fail */
+ return (DepsNodeFactory *)BLI_ghash_lookup(_depsnode_typeinfo_registry, SET_INT_IN_POINTER(type));
+}
+
+/* Get typeinfo for provided node */
+DepsNodeFactory *DEG_node_get_factory(const DepsNode *node)
+{
+ if (!node)
+ return NULL;
+
+ return DEG_get_node_factory(node->type);
+}
diff --git a/source/blender/depsgraph/intern/depsgraph_types.h b/source/blender/depsgraph/intern/depsgraph_types.h
new file mode 100644
index 00000000000..f5fbf0bcc76
--- /dev/null
+++ b/source/blender/depsgraph/intern/depsgraph_types.h
@@ -0,0 +1,173 @@
+/*
+ * ***** 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.
+ *
+ * Original Author: Joshua Leung
+ * Contributor(s): None Yet
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/depsgraph/intern/depsgraph_types.h
+ * \ingroup depsgraph
+ *
+ * Datatypes for internal use in the Depsgraph
+ *
+ * All of these datatypes are only really used within the "core" depsgraph.
+ * In particular, node types declared here form the structure of operations
+ * in the graph.
+ */
+
+#ifndef __DEPSGRAPH_TYPES_H__
+#define __DEPSGRAPH_TYPES_H__
+
+#include "depsgraph_util_function.h"
+
+/* TODO(sergey): Ideally we'll just use char* and statically allocated strings
+ * to avoid any possible overhead caused by string (re)allocation/formatting.
+ */
+#include <string>
+#include <vector>
+
+using std::string;
+using std::vector;
+
+struct bAction;
+struct ChannelDriver;
+struct ModifierData;
+struct PointerRNA;
+struct EvaluationContext;
+struct FCurve;
+
+/* Evaluation Operation for atomic operation */
+// XXX: move this to another header that can be exposed?
+typedef function<void(struct EvaluationContext *)> DepsEvalOperationCb;
+
+/* Metatype of Nodes - The general "level" in the graph structure the node serves */
+typedef enum eDepsNode_Class {
+ DEPSNODE_CLASS_GENERIC = 0, /* Types generally unassociated with user-visible entities, but needed for graph functioning */
+
+ DEPSNODE_CLASS_COMPONENT = 1, /* [Outer Node] An "aspect" of evaluating/updating an ID-Block, requiring certain types of evaluation behaviours */
+ DEPSNODE_CLASS_OPERATION = 2, /* [Inner Node] A glorified function-pointer/callback for scheduling up evaluation operations for components, subject to relationship requirements */
+} eDepsNode_Class;
+
+/* Types of Nodes */
+typedef enum eDepsNode_Type {
+ DEPSNODE_TYPE_UNDEFINED = -1, /* fallback type for invalid return value */
+
+ DEPSNODE_TYPE_OPERATION = 0, /* Inner Node (Operation) */
+
+ /* Generic Types */
+ DEPSNODE_TYPE_ROOT = 1, /* "Current Scene" - basically whatever kicks off the evaluation process */
+ DEPSNODE_TYPE_TIMESOURCE = 2, /* Time-Source */
+
+ DEPSNODE_TYPE_ID_REF = 3, /* ID-Block reference - used as landmarks/collection point for components, but not usually part of main graph */
+ DEPSNODE_TYPE_SUBGRAPH = 4, /* Isolated sub-graph - used for keeping instanced data separate from instances using them */
+
+ /* Outer Types */
+ DEPSNODE_TYPE_PARAMETERS = 11, /* Parameters Component - Default when nothing else fits (i.e. just SDNA property setting) */
+ DEPSNODE_TYPE_PROXY = 12, /* Generic "Proxy-Inherit" Component */ // XXX: Also for instancing of subgraphs?
+ DEPSNODE_TYPE_ANIMATION = 13, /* Animation Component */ // XXX: merge in with parameters?
+ DEPSNODE_TYPE_TRANSFORM = 14, /* Transform Component (Parenting/Constraints) */
+ DEPSNODE_TYPE_GEOMETRY = 15, /* Geometry Component (DerivedMesh/Displist) */
+ DEPSNODE_TYPE_SEQUENCER = 16, /* Sequencer Component (Scene Only) */
+
+ /* Evaluation-Related Outer Types (with Subdata) */
+ DEPSNODE_TYPE_EVAL_POSE = 21, /* Pose Component - Owner/Container of Bones Eval */
+ DEPSNODE_TYPE_BONE = 22, /* Bone Component - Child/Subcomponent of Pose */
+
+ DEPSNODE_TYPE_EVAL_PARTICLES = 23, /* Particle Systems Component */
+ DEPSNODE_TYPE_SHADING = 24, /* Material Shading Component */
+} eDepsNode_Type;
+
+/* Identifiers for common operations (as an enum) */
+typedef enum eDepsOperation_Code {
+#define DEF_DEG_OPCODE(label) DEG_OPCODE_##label,
+#include "depsnode_opcodes.h"
+#undef DEF_DEG_OPCODE
+} eDepsOperation_Code;
+
+/* String defines for these opcodes, defined in depsnode_operation.cpp */
+extern const char *DEG_OPNAMES[];
+
+
+/* Type of operation */
+typedef enum eDepsOperation_Type {
+ /* Primary operation types */
+ DEPSOP_TYPE_INIT = 0, /* initialise evaluation data */
+ DEPSOP_TYPE_EXEC = 1, /* standard evaluation step */
+ DEPSOP_TYPE_POST = 2, /* cleanup evaluation data + flush results */
+
+ /* Additional operation types */
+ DEPSOP_TYPE_OUT = 3, /* indicator for outputting a temporary result that other components can use */ // XXX?
+ DEPSOP_TYPE_SIM = 4, /* indicator for things like IK Solvers and Rigidbody Sim steps which modify final results of separate entities at once */
+ DEPSOP_TYPE_REBUILD = 5, /* rebuild internal evaluation data - used for Rigidbody Reset and Armature Rebuild-On-Load */
+} eDepsOperation_Type;
+
+/* Types of relationships between nodes
+ *
+ * This is used to provide additional hints to use when filtering
+ * the graph, so that we can go without doing more extensive
+ * data-level checks...
+ */
+typedef enum eDepsRelation_Type {
+ /* relationship type unknown/irrelevant */
+ DEPSREL_TYPE_STANDARD = 0,
+
+ /* root -> active scene or entity (screen, image, etc.) */
+ DEPSREL_TYPE_ROOT_TO_ACTIVE,
+
+ /* general datablock dependency */
+ DEPSREL_TYPE_DATABLOCK,
+
+ /* time dependency */
+ DEPSREL_TYPE_TIME,
+
+ /* component depends on results of another */
+ DEPSREL_TYPE_COMPONENT_ORDER,
+
+ /* relationship is just used to enforce ordering of operations
+ * (e.g. "init()" callback done before "exec() and "cleanup()")
+ */
+ DEPSREL_TYPE_OPERATION,
+
+ /* relationship results from a property driver affecting property */
+ DEPSREL_TYPE_DRIVER,
+
+ /* relationship is something driver depends on */
+ DEPSREL_TYPE_DRIVER_TARGET,
+
+ /* relationship is used for transform stack
+ * (e.g. parenting, user transforms, constraints)
+ */
+ DEPSREL_TYPE_TRANSFORM,
+
+ /* relationship is used for geometry evaluation
+ * (e.g. metaball "motherball" or modifiers)
+ */
+ DEPSREL_TYPE_GEOMETRY_EVAL,
+
+ /* relationship is used to trigger a post-change validity updates */
+ DEPSREL_TYPE_UPDATE,
+
+ /* relationship is used to trigger editor/screen updates */
+ DEPSREL_TYPE_UPDATE_UI,
+} eDepsRelation_Type;
+
+#endif /* __DEPSGRAPH_TYPES_H__ */
diff --git a/source/blender/depsgraph/intern/depsnode.cc b/source/blender/depsgraph/intern/depsnode.cc
new file mode 100644
index 00000000000..7d4d6890c83
--- /dev/null
+++ b/source/blender/depsgraph/intern/depsnode.cc
@@ -0,0 +1,316 @@
+/*
+ * ***** 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.
+ *
+ * Original Author: Joshua Leung
+ * Contributor(s): None Yet
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/depsgraph/intern/depsnode.cc
+ * \ingroup depsgraph
+ */
+
+#include <stdio.h>
+#include <string.h>
+
+#include "BLI_utildefines.h"
+
+extern "C" {
+#include "DNA_ID.h"
+#include "DNA_anim_types.h"
+
+#include "BKE_animsys.h"
+
+#include "DEG_depsgraph.h"
+}
+
+#include "depsnode.h" /* own include */
+#include "depsnode_component.h"
+#include "depsnode_operation.h"
+#include "depsgraph_intern.h"
+
+/* *************** */
+/* Node Management */
+
+/* Add ------------------------------------------------ */
+
+DepsNode::TypeInfo::TypeInfo(eDepsNode_Type type, const char *tname)
+{
+ this->type = type;
+ if (type == DEPSNODE_TYPE_OPERATION)
+ this->tclass = DEPSNODE_CLASS_OPERATION;
+ else if (type < DEPSNODE_TYPE_PARAMETERS)
+ this->tclass = DEPSNODE_CLASS_GENERIC;
+ else
+ this->tclass = DEPSNODE_CLASS_COMPONENT;
+ this->tname = tname;
+}
+
+DepsNode::DepsNode()
+{
+ this->name[0] = '\0';
+}
+
+DepsNode::~DepsNode()
+{
+ /* free links
+ * note: deleting relations will remove them from the node relations set,
+ * but only touch the same position as we are using here, which is safe.
+ */
+ DEPSNODE_RELATIONS_ITER_BEGIN(this->inlinks, rel)
+ {
+ OBJECT_GUARDED_DELETE(rel, DepsRelation);
+ }
+ DEPSNODE_RELATIONS_ITER_END;
+
+ DEPSNODE_RELATIONS_ITER_BEGIN(this->outlinks, rel)
+ {
+ OBJECT_GUARDED_DELETE(rel, DepsRelation);
+ }
+ DEPSNODE_RELATIONS_ITER_END;
+}
+
+
+/* Generic identifier for Depsgraph Nodes. */
+string DepsNode::identifier() const
+{
+ char typebuf[7];
+ sprintf(typebuf, "(%d)", type);
+
+ return string(typebuf) + " : " + name;
+}
+
+/* ************* */
+/* Generic Nodes */
+
+/* Time Source Node ============================================== */
+
+void TimeSourceDepsNode::tag_update(Depsgraph *graph)
+{
+ for (DepsNode::Relations::const_iterator it = outlinks.begin();
+ it != outlinks.end();
+ ++it)
+ {
+ DepsRelation *rel = *it;
+ DepsNode *node = rel->to;
+ node->tag_update(graph);
+ }
+}
+
+
+/* Root Node ============================================== */
+
+RootDepsNode::RootDepsNode() : scene(NULL), time_source(NULL)
+{
+}
+
+RootDepsNode::~RootDepsNode()
+{
+ OBJECT_GUARDED_DELETE(time_source, TimeSourceDepsNode);
+}
+
+TimeSourceDepsNode *RootDepsNode::add_time_source(const string &name)
+{
+ if (!time_source) {
+ DepsNodeFactory *factory = DEG_get_node_factory(DEPSNODE_TYPE_TIMESOURCE);
+ time_source = (TimeSourceDepsNode *)factory->create_node(NULL, "", name);
+ /*time_source->owner = this;*/ // XXX
+ }
+ return time_source;
+}
+
+DEG_DEPSNODE_DEFINE(RootDepsNode, DEPSNODE_TYPE_ROOT, "Root DepsNode");
+static DepsNodeFactoryImpl<RootDepsNode> DNTI_ROOT;
+
+/* Time Source Node ======================================= */
+
+DEG_DEPSNODE_DEFINE(TimeSourceDepsNode, DEPSNODE_TYPE_TIMESOURCE, "Time Source");
+static DepsNodeFactoryImpl<TimeSourceDepsNode> DNTI_TIMESOURCE;
+
+/* ID Node ================================================ */
+
+/* Initialize 'id' node - from pointer data given. */
+void IDDepsNode::init(const ID *id, const string &UNUSED(subdata))
+{
+ /* Store ID-pointer. */
+ BLI_assert(id != NULL);
+ this->id = (ID *)id;
+ this->layers = (1 << 20) - 1;
+ this->eval_flags = 0;
+
+ /* NOTE: components themselves are created if/when needed.
+ * This prevents problems with components getting added
+ * twice if an ID-Ref needs to be created to house it...
+ */
+}
+
+/* Free 'id' node. */
+IDDepsNode::~IDDepsNode()
+{
+ clear_components();
+}
+
+/* Copy 'id' node. */
+void IDDepsNode::copy(DepsgraphCopyContext *dcc, const IDDepsNode *src)
+{
+ (void)src; /* Ignored. */
+ /* Iterate over items in original hash, adding them to new hash. */
+ for (IDDepsNode::ComponentMap::const_iterator it = this->components.begin();
+ it != this->components.end();
+ ++it)
+ {
+ /* Get current <type : component> mapping. */
+ ComponentIDKey c_key = it->first;
+ DepsNode *old_component = it->second;
+
+ /* Make a copy of component. */
+ ComponentDepsNode *component = (ComponentDepsNode *)DEG_copy_node(dcc, old_component);
+
+ /* Add new node to hash... */
+ this->components[c_key] = component;
+ }
+
+ // TODO: perform a second loop to fix up links?
+ BLI_assert(!"Not expected to be used");
+}
+
+ComponentDepsNode *IDDepsNode::find_component(eDepsNode_Type type,
+ const string &name) const
+{
+ ComponentIDKey key(type, name);
+ ComponentMap::const_iterator it = components.find(key);
+ return it != components.end() ? it->second : NULL;
+}
+
+ComponentDepsNode *IDDepsNode::add_component(eDepsNode_Type type,
+ const string &name)
+{
+ ComponentIDKey key(type, name);
+ ComponentDepsNode *comp_node = find_component(type, name);
+ if (!comp_node) {
+ DepsNodeFactory *factory = DEG_get_node_factory(type);
+ comp_node = (ComponentDepsNode *)factory->create_node(this->id, "", name);
+
+ /* Register. */
+ this->components[key] = comp_node;
+ comp_node->owner = this;
+ }
+ return comp_node;
+}
+
+void IDDepsNode::remove_component(eDepsNode_Type type, const string &name)
+{
+ ComponentIDKey key(type, name);
+ ComponentDepsNode *comp_node = find_component(type, name);
+ if (comp_node) {
+ /* Unregister. */
+ this->components.erase(key);
+ OBJECT_GUARDED_DELETE(comp_node, ComponentDepsNode);
+ }
+}
+
+void IDDepsNode::clear_components()
+{
+ for (ComponentMap::const_iterator it = components.begin();
+ it != components.end();
+ ++it)
+ {
+ ComponentDepsNode *comp_node = it->second;
+ OBJECT_GUARDED_DELETE(comp_node, ComponentDepsNode);
+ }
+ components.clear();
+}
+
+void IDDepsNode::tag_update(Depsgraph *graph)
+{
+ for (ComponentMap::const_iterator it = components.begin();
+ it != components.end();
+ ++it)
+ {
+ ComponentDepsNode *comp_node = it->second;
+ /* TODO(sergey): What about drievrs? */
+ bool do_component_tag = comp_node->type != DEPSNODE_TYPE_ANIMATION;
+ if (comp_node->type == DEPSNODE_TYPE_ANIMATION) {
+ AnimData *adt = BKE_animdata_from_id(id);
+ /* Animation data might be null if relations are tagged for update. */
+ if (adt != NULL && (adt->recalc & ADT_RECALC_ANIM)) {
+ do_component_tag = true;
+ }
+ }
+ if (do_component_tag) {
+ comp_node->tag_update(graph);
+ }
+ }
+}
+
+DEG_DEPSNODE_DEFINE(IDDepsNode, DEPSNODE_TYPE_ID_REF, "ID Node");
+static DepsNodeFactoryImpl<IDDepsNode> DNTI_ID_REF;
+
+/* Subgraph Node ========================================== */
+
+/* Initialize 'subgraph' node - from pointer data given. */
+void SubgraphDepsNode::init(const ID *id, const string &UNUSED(subdata))
+{
+ /* Store ID-ref if provided. */
+ this->root_id = (ID *)id;
+
+ /* NOTE: graph will need to be added manually,
+ * as we don't have any way of passing this down.
+ */
+}
+
+/* Free 'subgraph' node */
+SubgraphDepsNode::~SubgraphDepsNode()
+{
+ /* Only free if graph not shared, of if this node is the first
+ * reference to it...
+ */
+ // XXX: prune these flags a bit...
+ if ((this->flag & SUBGRAPH_FLAG_FIRSTREF) || !(this->flag & SUBGRAPH_FLAG_SHARED)) {
+ /* Free the referenced graph. */
+ DEG_graph_free(this->graph);
+ this->graph = NULL;
+ }
+}
+
+/* Copy 'subgraph' node - Assume that the subgraph doesn't get copied for now... */
+void SubgraphDepsNode::copy(DepsgraphCopyContext * /*dcc*/,
+ const SubgraphDepsNode * /*src*/)
+{
+ //const SubgraphDepsNode *src_node = (const SubgraphDepsNode *)src;
+ //SubgraphDepsNode *dst_node = (SubgraphDepsNode *)dst;
+
+ /* for now, subgraph itself isn't copied... */
+ BLI_assert(!"Not expected to be used");
+}
+
+DEG_DEPSNODE_DEFINE(SubgraphDepsNode, DEPSNODE_TYPE_SUBGRAPH, "Subgraph Node");
+static DepsNodeFactoryImpl<SubgraphDepsNode> DNTI_SUBGRAPH;
+
+
+void DEG_register_base_depsnodes()
+{
+ DEG_register_node_typeinfo(&DNTI_ROOT);
+ DEG_register_node_typeinfo(&DNTI_TIMESOURCE);
+
+ DEG_register_node_typeinfo(&DNTI_ID_REF);
+ DEG_register_node_typeinfo(&DNTI_SUBGRAPH);
+}
diff --git a/source/blender/depsgraph/intern/depsnode.h b/source/blender/depsgraph/intern/depsnode.h
new file mode 100644
index 00000000000..53826ae8e71
--- /dev/null
+++ b/source/blender/depsgraph/intern/depsnode.h
@@ -0,0 +1,248 @@
+/*
+ * ***** 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.
+ *
+ * Original Author: Joshua Leung
+ * Contributor(s): None Yet
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/depsgraph/intern/depsnode.h
+ * \ingroup depsgraph
+ */
+
+#ifndef __DEPSNODE_H__
+#define __DEPSNODE_H__
+
+#include "depsgraph_types.h"
+
+#include "depsgraph_util_hash.h"
+#include "depsgraph_util_map.h"
+#include "depsgraph_util_set.h"
+
+struct ID;
+struct Scene;
+
+struct Depsgraph;
+struct DepsRelation;
+struct DepsgraphCopyContext;
+struct OperationDepsNode;
+
+/* *********************************** */
+/* Base-Defines for Nodes in Depsgraph */
+
+/* All nodes in Depsgraph are descended from this. */
+struct DepsNode {
+ /* Helper class for static typeinfo in subclasses. */
+ struct TypeInfo {
+ TypeInfo(eDepsNode_Type type, const char *tname);
+
+ eDepsNode_Type type;
+ eDepsNode_Class tclass;
+ const char *tname;
+ };
+
+ /* Identifier - mainly for debugging purposes. */
+ string name;
+
+ /* Structural type of node. */
+ eDepsNode_Type type;
+
+ /* Type of data/behaviour represented by node... */
+ eDepsNode_Class tclass;
+
+ /* Relationships between nodes
+ * The reason why all depsgraph nodes are descended from this type (apart
+ * from basic serialization benefits - from the typeinfo) is that we can have
+ * relationships between these nodes!
+ */
+ typedef unordered_set<DepsRelation *> Relations;
+
+ /* Nodes which this one depends on. */
+ Relations inlinks;
+
+ /* Nodes which depend on this one. */
+ Relations outlinks;
+
+ /* Generic tag for traversal algorithms */
+ int done;
+
+ /* Methods. */
+
+ DepsNode();
+ virtual ~DepsNode();
+
+ virtual string identifier() const;
+ string full_identifier() const;
+
+ virtual void init(const ID * /*id*/,
+ const string &/*subdata*/) {}
+ virtual void copy(DepsgraphCopyContext * /*dcc*/,
+ const DepsNode * /*src*/) {}
+
+ virtual void tag_update(Depsgraph * /*graph*/) {}
+
+ virtual OperationDepsNode *get_entry_operation() { return NULL; }
+ virtual OperationDepsNode *get_exit_operation() { return NULL; }
+};
+
+/* Macros for common static typeinfo. */
+#define DEG_DEPSNODE_DECLARE \
+ static const DepsNode::TypeInfo typeinfo
+#define DEG_DEPSNODE_DEFINE(NodeType, type_, tname_) \
+ const DepsNode::TypeInfo NodeType::typeinfo = DepsNode::TypeInfo(type_, tname_)
+
+/* Generic Nodes ======================= */
+
+struct ComponentDepsNode;
+struct IDDepsNode;
+
+/* Time Source Node. */
+struct TimeSourceDepsNode : public DepsNode {
+ /* New "current time". */
+ float cfra;
+
+ /* time-offset relative to the "official" time source that this one has. */
+ float offset;
+
+ // TODO: evaluate() operation needed
+
+ void tag_update(Depsgraph *graph);
+
+ DEG_DEPSNODE_DECLARE;
+};
+
+/* Root Node. */
+struct RootDepsNode : public DepsNode {
+ RootDepsNode();
+ ~RootDepsNode();
+
+ TimeSourceDepsNode *add_time_source(const string &name = "");
+
+ /* scene that this corresponds to */
+ Scene *scene;
+
+ /* Entrypoint node for time-changed. */
+ TimeSourceDepsNode *time_source;
+
+ DEG_DEPSNODE_DECLARE;
+};
+
+/* ID-Block Reference */
+struct IDDepsNode : public DepsNode {
+ struct ComponentIDKey {
+ ComponentIDKey(eDepsNode_Type type, const string &name = "")
+ : type(type), name(name) {}
+
+ bool operator== (const ComponentIDKey &other) const
+ {
+ return type == other.type && name == other.name;
+ }
+
+ eDepsNode_Type type;
+ string name;
+ };
+
+ /* XXX can't specialize std::hash for this purpose, because ComponentIDKey is
+ * a nested type ...
+ *
+ * http://stackoverflow.com/a/951245
+ */
+ struct component_key_hash {
+ bool operator() (const ComponentIDKey &key) const
+ {
+ return hash_combine(hash<int>()(key.type), hash<string>()(key.name));
+ }
+ };
+
+ typedef unordered_map<ComponentIDKey,
+ ComponentDepsNode *,
+ component_key_hash> ComponentMap;
+
+ void init(const ID *id, const string &subdata);
+ void copy(DepsgraphCopyContext *dcc, const IDDepsNode *src);
+ ~IDDepsNode();
+
+ ComponentDepsNode *find_component(eDepsNode_Type type,
+ const string &name = "") const;
+ ComponentDepsNode *add_component(eDepsNode_Type type,
+ const string &name = "");
+ void remove_component(eDepsNode_Type type, const string &name = "");
+ void clear_components();
+
+ void tag_update(Depsgraph *graph);
+
+ /* ID Block referenced. */
+ ID *id;
+
+ /* Hash to make it faster to look up components. */
+ ComponentMap components;
+
+ /* Layers of this node with accumulated layers of it's output relations. */
+ int layers;
+
+ /* Additional flags needed for scene evaluation.
+ * TODO(sergey): Only needed for until really granular updates
+ * of all the entities.
+ */
+ int eval_flags;
+
+ DEG_DEPSNODE_DECLARE;
+};
+
+/* Subgraph Reference. */
+struct SubgraphDepsNode : public DepsNode {
+ void init(const ID *id, const string &subdata);
+ void copy(DepsgraphCopyContext *dcc, const SubgraphDepsNode *src);
+ ~SubgraphDepsNode();
+
+ /* Instanced graph. */
+ Depsgraph *graph;
+
+ /* ID-block at root of subgraph (if applicable). */
+ ID *root_id;
+
+ /* Number of nodes which use/reference this subgraph - if just 1, it may be
+ * possible to merge into main,
+ */
+ size_t num_users;
+
+ /* (eSubgraphRef_Flag) assorted settings for subgraph node. */
+ int flag;
+
+ DEG_DEPSNODE_DECLARE;
+};
+
+/* Flags for subgraph node */
+typedef enum eSubgraphRef_Flag {
+ /* Subgraph referenced is shared with another reference, so shouldn't
+ * free on exit.
+ */
+ SUBGRAPH_FLAG_SHARED = (1 << 0),
+
+ /* Node is first reference to subgraph, so it can be freed when we are
+ * removed.
+ */
+ SUBGRAPH_FLAG_FIRSTREF = (1 << 1),
+} eSubgraphRef_Flag;
+
+void DEG_register_base_depsnodes();
+
+#endif /* __DEPSNODE_H__ */
diff --git a/source/blender/depsgraph/intern/depsnode_component.cc b/source/blender/depsgraph/intern/depsnode_component.cc
new file mode 100644
index 00000000000..1d939c6580d
--- /dev/null
+++ b/source/blender/depsgraph/intern/depsnode_component.cc
@@ -0,0 +1,318 @@
+/*
+ * ***** 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.
+ *
+ * Original Author: Joshua Leung
+ * Contributor(s): None Yet
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/depsgraph/intern/depsnode_component.cc
+ * \ingroup depsgraph
+ */
+
+#include <stdio.h>
+#include <string.h>
+
+extern "C" {
+#include "BLI_utildefines.h"
+
+#include "DNA_object_types.h"
+
+#include "BKE_action.h"
+} /* extern "C" */
+
+#include "depsnode_component.h" /* own include */
+#include "depsnode_operation.h"
+#include "depsgraph_intern.h"
+
+/* *********** */
+/* Outer Nodes */
+
+/* Standard Component Methods ============================= */
+
+ComponentDepsNode::ComponentDepsNode() :
+ entry_operation(NULL),
+ exit_operation(NULL)
+{
+}
+
+/* Initialize 'component' node - from pointer data given */
+void ComponentDepsNode::init(const ID * /*id*/,
+ const string & /*subdata*/)
+{
+ /* hook up eval context? */
+ // XXX: maybe this needs a special API?
+}
+
+/* Copy 'component' node */
+void ComponentDepsNode::copy(DepsgraphCopyContext * /*dcc*/,
+ const ComponentDepsNode * /*src*/)
+{
+#if 0 // XXX: remove all this
+ /* duplicate list of operation nodes */
+ this->operations.clear();
+
+ for (OperationMap::const_iterator it = src->operations.begin(); it != src->operations.end(); ++it) {
+ const string &pchan_name = it->first;
+ OperationDepsNode *src_op = it->second;
+
+ /* recursive copy */
+ DepsNodeFactory *factory = DEG_node_get_factory(src_op);
+ OperationDepsNode *dst_op = (OperationDepsNode *)factory->copy_node(dcc, src_op);
+ this->operations[pchan_name] = dst_op;
+
+ /* fix links... */
+ // ...
+ }
+
+ /* copy evaluation contexts */
+ //
+#endif
+ BLI_assert(!"Not expected to be called");
+}
+
+/* Free 'component' node */
+ComponentDepsNode::~ComponentDepsNode()
+{
+ clear_operations();
+}
+
+string ComponentDepsNode::identifier() const
+{
+ string &idname = this->owner->name;
+
+ char typebuf[7];
+ sprintf(typebuf, "(%d)", type);
+
+ return string(typebuf) + name + " : " + idname;
+}
+
+OperationDepsNode *ComponentDepsNode::find_operation(OperationIDKey key) const
+{
+ OperationMap::const_iterator it = this->operations.find(key);
+
+ if (it != this->operations.end()) {
+ return it->second;
+ }
+ else {
+ fprintf(stderr, "%s: find_operation(%s) failed\n",
+ this->identifier().c_str(), key.identifier().c_str());
+ BLI_assert(!"Request for non-existing operation, should not happen");
+ return NULL;
+ }
+}
+
+OperationDepsNode *ComponentDepsNode::find_operation(eDepsOperation_Code opcode, const string &name) const
+{
+ OperationIDKey key(opcode, name);
+ return find_operation(key);
+}
+
+OperationDepsNode *ComponentDepsNode::has_operation(OperationIDKey key) const
+{
+ OperationMap::const_iterator it = this->operations.find(key);
+ if (it != this->operations.end()) {
+ return it->second;
+ }
+ return NULL;
+}
+
+OperationDepsNode *ComponentDepsNode::has_operation(eDepsOperation_Code opcode,
+ const string &name) const
+{
+ OperationIDKey key(opcode, name);
+ return has_operation(key);
+}
+
+OperationDepsNode *ComponentDepsNode::add_operation(eDepsOperation_Type optype, DepsEvalOperationCb op, eDepsOperation_Code opcode, const string &name)
+{
+ OperationDepsNode *op_node = has_operation(opcode, name);
+ if (!op_node) {
+ DepsNodeFactory *factory = DEG_get_node_factory(DEPSNODE_TYPE_OPERATION);
+ op_node = (OperationDepsNode *)factory->create_node(this->owner->id, "", name);
+
+ /* register opnode in this component's operation set */
+ OperationIDKey key(opcode, name);
+ this->operations[key] = op_node;
+
+ /* set as entry/exit node of component (if appropriate) */
+ if (optype == DEPSOP_TYPE_INIT) {
+ BLI_assert(this->entry_operation == NULL);
+ this->entry_operation = op_node;
+ }
+ else if (optype == DEPSOP_TYPE_POST) {
+ // XXX: review whether DEPSOP_TYPE_OUT is better than DEPSOP_TYPE_POST, or maybe have both?
+ BLI_assert(this->exit_operation == NULL);
+ this->exit_operation = op_node;
+ }
+
+ /* set backlink */
+ op_node->owner = this;
+ }
+ else {
+ fprintf(stderr, "add_operation: Operation already exists - %s has %s at %p\n",
+ this->identifier().c_str(), op_node->identifier().c_str(), op_node);
+ BLI_assert(!"Should not happen!");
+ }
+
+ /* attach extra data */
+ op_node->evaluate = op;
+ op_node->optype = optype;
+ op_node->opcode = opcode;
+ op_node->name = name;
+
+ return op_node;
+}
+
+void ComponentDepsNode::remove_operation(eDepsOperation_Code opcode, const string &name)
+{
+ OperationDepsNode *op_node = find_operation(opcode, name);
+ if (op_node) {
+ /* unregister */
+ this->operations.erase(OperationIDKey(opcode, name));
+ OBJECT_GUARDED_DELETE(op_node, OperationDepsNode);
+ }
+}
+
+void ComponentDepsNode::clear_operations()
+{
+ for (OperationMap::const_iterator it = operations.begin(); it != operations.end(); ++it) {
+ OperationDepsNode *op_node = it->second;
+ OBJECT_GUARDED_DELETE(op_node, OperationDepsNode);
+ }
+ operations.clear();
+}
+
+void ComponentDepsNode::tag_update(Depsgraph *graph)
+{
+ OperationDepsNode *entry_op = get_entry_operation();
+ if (entry_op != NULL && entry_op->flag & DEPSOP_FLAG_NEEDS_UPDATE) {
+ return;
+ }
+ for (OperationMap::const_iterator it = operations.begin(); it != operations.end(); ++it) {
+ OperationDepsNode *op_node = it->second;
+ op_node->tag_update(graph);
+ }
+}
+
+OperationDepsNode *ComponentDepsNode::get_entry_operation()
+{
+ if (entry_operation)
+ return entry_operation;
+ else if (operations.size() == 1)
+ return operations.begin()->second;
+ return NULL;
+}
+
+OperationDepsNode *ComponentDepsNode::get_exit_operation()
+{
+ if (exit_operation)
+ return exit_operation;
+ else if (operations.size() == 1)
+ return operations.begin()->second;
+ return NULL;
+}
+
+/* Parameter Component Defines ============================ */
+
+DEG_DEPSNODE_DEFINE(ParametersComponentDepsNode, DEPSNODE_TYPE_PARAMETERS, "Parameters Component");
+static DepsNodeFactoryImpl<ParametersComponentDepsNode> DNTI_PARAMETERS;
+
+/* Animation Component Defines ============================ */
+
+DEG_DEPSNODE_DEFINE(AnimationComponentDepsNode, DEPSNODE_TYPE_ANIMATION, "Animation Component");
+static DepsNodeFactoryImpl<AnimationComponentDepsNode> DNTI_ANIMATION;
+
+/* Transform Component Defines ============================ */
+
+DEG_DEPSNODE_DEFINE(TransformComponentDepsNode, DEPSNODE_TYPE_TRANSFORM, "Transform Component");
+static DepsNodeFactoryImpl<TransformComponentDepsNode> DNTI_TRANSFORM;
+
+/* Proxy Component Defines ================================ */
+
+DEG_DEPSNODE_DEFINE(ProxyComponentDepsNode, DEPSNODE_TYPE_PROXY, "Proxy Component");
+static DepsNodeFactoryImpl<ProxyComponentDepsNode> DNTI_PROXY;
+
+/* Geometry Component Defines ============================= */
+
+DEG_DEPSNODE_DEFINE(GeometryComponentDepsNode, DEPSNODE_TYPE_GEOMETRY, "Geometry Component");
+static DepsNodeFactoryImpl<GeometryComponentDepsNode> DNTI_GEOMETRY;
+
+/* Sequencer Component Defines ============================ */
+
+DEG_DEPSNODE_DEFINE(SequencerComponentDepsNode, DEPSNODE_TYPE_SEQUENCER, "Sequencer Component");
+static DepsNodeFactoryImpl<SequencerComponentDepsNode> DNTI_SEQUENCER;
+
+/* Pose Component ========================================= */
+
+DEG_DEPSNODE_DEFINE(PoseComponentDepsNode, DEPSNODE_TYPE_EVAL_POSE, "Pose Eval Component");
+static DepsNodeFactoryImpl<PoseComponentDepsNode> DNTI_EVAL_POSE;
+
+/* Bone Component ========================================= */
+
+/* Initialize 'bone component' node - from pointer data given */
+void BoneComponentDepsNode::init(const ID *id, const string &subdata)
+{
+ /* generic component-node... */
+ ComponentDepsNode::init(id, subdata);
+
+ /* name of component comes is bone name */
+ /* TODO(sergey): This sets name to an empty string because subdata is
+ * empty. Is it a bug?
+ */
+ //this->name = subdata;
+
+ /* bone-specific node data */
+ Object *ob = (Object *)id;
+ this->pchan = BKE_pose_channel_find_name(ob->pose, subdata.c_str());
+}
+
+DEG_DEPSNODE_DEFINE(BoneComponentDepsNode, DEPSNODE_TYPE_BONE, "Bone Component");
+static DepsNodeFactoryImpl<BoneComponentDepsNode> DNTI_BONE;
+
+/* Particles Component Defines ============================ */
+
+DEG_DEPSNODE_DEFINE(ParticlesComponentDepsNode, DEPSNODE_TYPE_EVAL_PARTICLES, "Particles Component");
+static DepsNodeFactoryImpl<ParticlesComponentDepsNode> DNTI_EVAL_PARTICLES;
+
+/* Shading Component Defines ============================ */
+
+DEG_DEPSNODE_DEFINE(ShadingComponentDepsNode, DEPSNODE_TYPE_SHADING, "Shading Component");
+static DepsNodeFactoryImpl<ShadingComponentDepsNode> DNTI_SHADING;
+
+
+/* Node Types Register =================================== */
+
+void DEG_register_component_depsnodes()
+{
+ DEG_register_node_typeinfo(&DNTI_PARAMETERS);
+ DEG_register_node_typeinfo(&DNTI_PROXY);
+ DEG_register_node_typeinfo(&DNTI_ANIMATION);
+ DEG_register_node_typeinfo(&DNTI_TRANSFORM);
+ DEG_register_node_typeinfo(&DNTI_GEOMETRY);
+ DEG_register_node_typeinfo(&DNTI_SEQUENCER);
+
+ DEG_register_node_typeinfo(&DNTI_EVAL_POSE);
+ DEG_register_node_typeinfo(&DNTI_BONE);
+
+ DEG_register_node_typeinfo(&DNTI_EVAL_PARTICLES);
+ DEG_register_node_typeinfo(&DNTI_SHADING);
+}
diff --git a/source/blender/depsgraph/intern/depsnode_component.h b/source/blender/depsgraph/intern/depsnode_component.h
new file mode 100644
index 00000000000..e3550bb2371
--- /dev/null
+++ b/source/blender/depsgraph/intern/depsnode_component.h
@@ -0,0 +1,201 @@
+/*
+ * ***** 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.
+ *
+ * Original Author: Joshua Leung
+ * Contributor(s): None Yet
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/depsgraph/intern/depsnode_component.h
+ * \ingroup depsgraph
+ */
+
+#ifndef __DEPSNODE_COMPONENT_H__
+#define __DEPSNODE_COMPONENT_H__
+
+#include "depsnode.h"
+
+#include "depsgraph_util_hash.h"
+#include "depsgraph_util_map.h"
+#include "depsgraph_util_set.h"
+
+struct ID;
+struct bPoseChannel;
+
+struct Depsgraph;
+struct DepsgraphCopyContext;
+struct EvaluationContext;
+struct OperationDepsNode;
+struct BoneComponentDepsNode;
+
+
+/* ID Component - Base type for all components */
+struct ComponentDepsNode : public DepsNode {
+ /* Key used to look up operations within a component */
+ struct OperationIDKey
+ {
+ eDepsOperation_Code opcode;
+ string name;
+
+
+ OperationIDKey() :
+ opcode(DEG_OPCODE_OPERATION), name("")
+ {}
+ OperationIDKey(eDepsOperation_Code opcode) :
+ opcode(opcode), name("")
+ {}
+ OperationIDKey(eDepsOperation_Code opcode, const string &name) :
+ opcode(opcode), name(name)
+ {}
+
+ string identifier() const
+ {
+ char codebuf[5];
+ sprintf(codebuf, "%d", opcode);
+
+ return string("OperationIDKey(") + codebuf + ", " + name + ")";
+ }
+
+ bool operator==(const OperationIDKey &other) const
+ {
+ return (opcode == other.opcode) && (name == other.name);
+ }
+ };
+
+ /* XXX can't specialize std::hash for this purpose, because ComponentKey is a nested type ...
+ * http://stackoverflow.com/a/951245
+ */
+ struct operation_key_hash {
+ bool operator() (const OperationIDKey &key) const
+ {
+ return hash_combine(hash<int>()(key.opcode), hash<string>()(key.name));
+ }
+ };
+
+ /* Typedef for container of operations */
+ typedef unordered_map<OperationIDKey, OperationDepsNode *, operation_key_hash> OperationMap;
+
+
+ ComponentDepsNode();
+ ~ComponentDepsNode();
+
+ void init(const ID *id, const string &subdata);
+ void copy(DepsgraphCopyContext *dcc, const ComponentDepsNode *src);
+
+ string identifier() const;
+
+ /* Find an existing operation, will throw an assert() if it does not exist. */
+ OperationDepsNode *find_operation(OperationIDKey key) const;
+ OperationDepsNode *find_operation(eDepsOperation_Code opcode, const string &name) const;
+
+ /* Check operation exists and return it. */
+ OperationDepsNode *has_operation(OperationIDKey key) const;
+ OperationDepsNode *has_operation(eDepsOperation_Code opcode, const string &name) const;
+
+ /**
+ * Create a new node for representing an operation and add this to graph
+ * \warning If an existing node is found, it will be modified. This helps when node may
+ * have been partially created earlier (e.g. parent ref before parent item is added)
+ *
+ * \param type: Operation node type (corresponding to context/component that it operates in)
+ * \param optype: Role that operation plays within component (i.e. where in eval process)
+ * \param op: The operation to perform
+ * \param name: Identifier for operation - used to find/locate it again
+ */
+ OperationDepsNode *add_operation(eDepsOperation_Type optype, DepsEvalOperationCb op, eDepsOperation_Code opcode, const string &name);
+
+ void remove_operation(eDepsOperation_Code opcode, const string &name);
+ void clear_operations();
+
+ void tag_update(Depsgraph *graph);
+
+ /* Evaluation Context Management .................. */
+
+ /* Initialize component's evaluation context used for the specified purpose */
+ virtual bool eval_context_init(EvaluationContext * /*eval_ctx*/) { return false; }
+ /* Free data in component's evaluation context which is used for the specified purpose
+ * NOTE: this does not free the actual context in question
+ */
+ virtual void eval_context_free(EvaluationContext * /*eval_ctx*/) {}
+
+ OperationDepsNode *get_entry_operation();
+ OperationDepsNode *get_exit_operation();
+
+ IDDepsNode *owner;
+
+ OperationMap operations; /* inner nodes for this component */
+ OperationDepsNode *entry_operation;
+ OperationDepsNode *exit_operation;
+
+ // XXX: a poll() callback to check if component's first node can be started?
+};
+
+/* ---------------------------------------- */
+
+struct ParametersComponentDepsNode : public ComponentDepsNode {
+ DEG_DEPSNODE_DECLARE;
+};
+
+struct AnimationComponentDepsNode : public ComponentDepsNode {
+ DEG_DEPSNODE_DECLARE;
+};
+
+struct TransformComponentDepsNode : public ComponentDepsNode {
+ DEG_DEPSNODE_DECLARE;
+};
+
+struct ProxyComponentDepsNode : public ComponentDepsNode {
+ DEG_DEPSNODE_DECLARE;
+};
+
+struct GeometryComponentDepsNode : public ComponentDepsNode {
+ DEG_DEPSNODE_DECLARE;
+};
+
+struct SequencerComponentDepsNode : public ComponentDepsNode {
+ DEG_DEPSNODE_DECLARE;
+};
+
+struct PoseComponentDepsNode : public ComponentDepsNode {
+ DEG_DEPSNODE_DECLARE;
+};
+
+/* Bone Component */
+struct BoneComponentDepsNode : public ComponentDepsNode {
+ void init(const ID *id, const string &subdata);
+
+ struct bPoseChannel *pchan; /* the bone that this component represents */
+
+ DEG_DEPSNODE_DECLARE;
+};
+
+struct ParticlesComponentDepsNode : public ComponentDepsNode {
+ DEG_DEPSNODE_DECLARE;
+};
+
+struct ShadingComponentDepsNode : public ComponentDepsNode {
+ DEG_DEPSNODE_DECLARE;
+};
+
+
+void DEG_register_component_depsnodes();
+
+#endif /* __DEPSNODE_COMPONENT_H__ */
diff --git a/source/blender/depsgraph/intern/depsnode_opcodes.h b/source/blender/depsgraph/intern/depsnode_opcodes.h
new file mode 100644
index 00000000000..b81822c0ac5
--- /dev/null
+++ b/source/blender/depsgraph/intern/depsnode_opcodes.h
@@ -0,0 +1,145 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2014 Blender Foundation.
+ * All rights reserved.
+ *
+ * Original Author: Joshua Leung
+ * Contributor(s): None Yet
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/depsgraph/intern/depsnode_opcodes.h
+ * \ingroup depsgraph
+ *
+ * \par OpCodes for OperationDepsNodes
+ *
+ * This file defines all the "operation codes" (opcodes) used to identify
+ * common operation node types. The intention of these defines is to have
+ * a fast and reliable way of identifying the relevant nodes within a component
+ * without having to use fragile dynamic strings.
+ *
+ * This file is meant to be used like UI_icons.h. That is, before including
+ * the file, the host file must define the DEG_OPCODE(_label) macro, which
+ * is responsible for converting the define into whatever form is suitable.
+ * Therefore, it intentionally doesn't have header guards.
+ */
+
+
+/* Example macro define: */
+/* #define DEF_DEG_OPCODE(label) DEG_OPCODE_##label, */
+
+/* Generic Operations ------------------------------ */
+
+/* Placeholder for operations which don't need special mention */
+DEF_DEG_OPCODE(OPERATION)
+
+// XXX: Placeholder while porting depsgraph code
+DEF_DEG_OPCODE(PLACEHOLDER)
+
+DEF_DEG_OPCODE(NOOP)
+
+/* Animation, Drivers, etc. ------------------------ */
+
+/* NLA + Action */
+DEF_DEG_OPCODE(ANIMATION)
+
+/* Driver */
+DEF_DEG_OPCODE(DRIVER)
+
+/* Proxy Inherit? */
+//DEF_DEG_OPCODE(PROXY)
+
+/* Transform --------------------------------------- */
+
+/* Transform entry point - local transforms only */
+DEF_DEG_OPCODE(TRANSFORM_LOCAL)
+
+/* Parenting */
+DEF_DEG_OPCODE(TRANSFORM_PARENT)
+
+/* Constraints */
+DEF_DEG_OPCODE(TRANSFORM_CONSTRAINTS)
+//DEF_DEG_OPCODE(TRANSFORM_CONSTRAINTS_INIT)
+//DEF_DEG_OPCODE(TRANSFORM_CONSTRAINT)
+//DEF_DEG_OPCODE(TRANSFORM_CONSTRAINTS_DONE)
+
+/* Rigidbody Sim - Perform Sim */
+DEF_DEG_OPCODE(RIGIDBODY_REBUILD)
+DEF_DEG_OPCODE(RIGIDBODY_SIM)
+
+/* Rigidbody Sim - Copy Results to Object */
+DEF_DEG_OPCODE(TRANSFORM_RIGIDBODY)
+
+/* Transform exitpoint */
+DEF_DEG_OPCODE(TRANSFORM_FINAL)
+
+/* XXX: ubereval is for temporary porting purposes only */
+DEF_DEG_OPCODE(OBJECT_UBEREVAL)
+
+/* Geometry ---------------------------------------- */
+
+/* XXX: Placeholder - UberEval */
+DEF_DEG_OPCODE(GEOMETRY_UBEREVAL)
+
+/* Modifier */
+DEF_DEG_OPCODE(GEOMETRY_MODIFIER)
+
+/* Curve Objects - Path Calculation (used for path-following tools) */
+DEF_DEG_OPCODE(GEOMETRY_PATH)
+
+/* Pose -------------------------------------------- */
+
+/* Init IK Trees, etc. */
+DEF_DEG_OPCODE(POSE_INIT)
+
+/* Free IK Trees + Compute Deform Matrices */
+DEF_DEG_OPCODE(POSE_DONE)
+
+/* IK/Spline Solvers */
+DEF_DEG_OPCODE(POSE_IK_SOLVER)
+DEF_DEG_OPCODE(POSE_SPLINE_IK_SOLVER)
+
+/* Bone -------------------------------------------- */
+
+/* Bone local transforms - Entrypoint */
+DEF_DEG_OPCODE(BONE_LOCAL)
+
+/* Pose-space conversion (includes parent + restpose) */
+DEF_DEG_OPCODE(BONE_POSE_PARENT)
+
+/* Constraints */
+DEF_DEG_OPCODE(BONE_CONSTRAINTS)
+//DEF_DEG_OPCODE(BONE_CONSTRAINTS_INIT)
+//DEF_DEG_OPCODE(BONE_CONSTRAINT)
+//DEF_DEG_OPCODE(BONE_CONSTRAINTS_DONE)
+
+/* Bone transforms are ready
+ * - "READY" This (internal) noop is used to signal that all pre-IK operations are done.
+ * Its role is to help mediate situations where cyclic relations may otherwise form
+ * (i.e. one bone in chain targetting another in same chain)
+ * - "DONE" This noop is used to signal that the bone's final pose transform can be read by others
+ */
+// TODO: deform mats could get calculated in the final_transform ops...
+DEF_DEG_OPCODE(BONE_READY)
+DEF_DEG_OPCODE(BONE_DONE)
+
+/* Particles --------------------------------------- */
+
+/* XXX: placeholder - Particle System eval */
+DEF_DEG_OPCODE(PSYS_EVAL)
diff --git a/source/blender/depsgraph/intern/depsnode_operation.cc b/source/blender/depsgraph/intern/depsnode_operation.cc
new file mode 100644
index 00000000000..6aeb163356b
--- /dev/null
+++ b/source/blender/depsgraph/intern/depsnode_operation.cc
@@ -0,0 +1,104 @@
+/*
+ * ***** 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.
+ *
+ * Original Author: Joshua Leung
+ * Contributor(s): None Yet
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/depsgraph/intern/depsnode_operation.cc
+ * \ingroup depsgraph
+ */
+
+#include "MEM_guardedalloc.h"
+
+extern "C" {
+#include "BLI_utildefines.h"
+} /* extern "C" */
+
+#include "depsnode_operation.h" /* own include */
+#include "depsnode_component.h"
+#include "depsgraph.h"
+#include "depsgraph_intern.h"
+
+/* ******************************************************************* */
+/* OpNode Identifiers Array - Exported to other depsgraph files too... */
+
+/* identifiers for operations */
+const char *DEG_OPNAMES[] = {
+#define DEF_DEG_OPCODE(label) #label,
+#include "depsnode_opcodes.h"
+#undef DEF_DEG_OPCODE
+
+ "<Invalid>"
+};
+
+/* *********** */
+/* Inner Nodes */
+
+OperationDepsNode::OperationDepsNode() :
+ eval_priority(0.0f),
+ flag(0)
+{
+}
+
+OperationDepsNode::~OperationDepsNode()
+{
+}
+
+string OperationDepsNode::identifier() const
+{
+ BLI_assert((opcode > 0) && (opcode < ARRAY_SIZE(DEG_OPNAMES)));
+ return string(DEG_OPNAMES[opcode]) + "(" + name + ")";
+}
+
+/* Full node identifier, including owner name.
+ * used for logging and debug prints.
+ */
+string OperationDepsNode::full_identifier() const
+{
+ string owner_str = "";
+ if (owner->type == DEPSNODE_TYPE_BONE) {
+ owner_str = owner->owner->name + "." + owner->name;
+ }
+ else {
+ owner_str = owner->owner->name;
+ }
+ return owner_str + "." + identifier();
+}
+
+void OperationDepsNode::tag_update(Depsgraph *graph)
+{
+ if (flag & DEPSOP_FLAG_NEEDS_UPDATE) {
+ return;
+ }
+ /* Tag for update, but also note that this was the source of an update. */
+ flag |= (DEPSOP_FLAG_NEEDS_UPDATE | DEPSOP_FLAG_DIRECTLY_MODIFIED);
+ graph->add_entry_tag(this);
+}
+
+DEG_DEPSNODE_DEFINE(OperationDepsNode, DEPSNODE_TYPE_OPERATION, "Operation");
+static DepsNodeFactoryImpl<OperationDepsNode> DNTI_OPERATION;
+
+void DEG_register_operation_depsnodes()
+{
+ DEG_register_node_typeinfo(&DNTI_OPERATION);
+}
diff --git a/source/blender/depsgraph/intern/depsnode_operation.h b/source/blender/depsgraph/intern/depsnode_operation.h
new file mode 100644
index 00000000000..1119e10805d
--- /dev/null
+++ b/source/blender/depsgraph/intern/depsnode_operation.h
@@ -0,0 +1,90 @@
+/*
+ * ***** 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.
+ *
+ * Original Author: Joshua Leung
+ * Contributor(s): None Yet
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/depsgraph/intern/depsnode_operation.h
+ * \ingroup depsgraph
+ */
+
+#ifndef __DEPSNODE_OPERATION_H__
+#define __DEPSNODE_OPERATION_H__
+
+#include "depsnode.h"
+
+struct ID;
+
+struct Depsgraph;
+struct DepsgraphCopyContext;
+
+/* Flags for Depsgraph Nodes */
+typedef enum eDepsOperation_Flag {
+ /* node needs to be updated */
+ DEPSOP_FLAG_NEEDS_UPDATE = (1 << 0),
+
+ /* node was directly modified, causing need for update */
+ /* XXX: intention is to make it easier to tell when we just need to take subgraphs */
+ DEPSOP_FLAG_DIRECTLY_MODIFIED = (1 << 1),
+
+ /* Operation is evaluated using CPython; has GIL and security implications... */
+ DEPSOP_FLAG_USES_PYTHON = (1 << 2),
+} eDepsOperation_Flag;
+
+/* Atomic Operation - Base type for all operations */
+struct OperationDepsNode : public DepsNode {
+
+
+ OperationDepsNode();
+ ~OperationDepsNode();
+
+ string identifier() const;
+ string full_identifier() const;
+
+ void tag_update(Depsgraph *graph);
+
+ bool is_noop() const { return (bool)evaluate == false; }
+
+ OperationDepsNode *get_entry_operation() { return this; }
+ OperationDepsNode *get_exit_operation() { return this; }
+
+ ComponentDepsNode *owner; /* component that contains the operation */
+
+ DepsEvalOperationCb evaluate; /* callback for operation */
+
+
+ uint32_t num_links_pending; /* how many inlinks are we still waiting on before we can be evaluated... */
+ float eval_priority;
+ bool scheduled;
+
+ short optype; /* (eDepsOperation_Type) stage of evaluation */
+ int opcode; /* (eDepsOperation_Code) identifier for the operation being performed */
+
+ int flag; /* (eDepsOperation_Flag) extra settings affecting evaluation */
+
+ DEG_DEPSNODE_DECLARE;
+};
+
+void DEG_register_operation_depsnodes();
+
+#endif /* __DEPSNODE_OPERATION_H__ */
diff --git a/source/blender/depsgraph/util/depsgraph_util_cycle.cc b/source/blender/depsgraph/util/depsgraph_util_cycle.cc
new file mode 100644
index 00000000000..5eae8c087ad
--- /dev/null
+++ b/source/blender/depsgraph/util/depsgraph_util_cycle.cc
@@ -0,0 +1,140 @@
+/*
+ * ***** 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) 2015 Blender Foundation.
+ * All rights reserved.
+ *
+ * Contributor(s): Sergey Sharybin
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/depsgraph/util/depsgraph_util_cycle.cc
+ * \ingroup depsgraph
+ */
+
+#include <cstdio>
+#include <cstdlib>
+#include <stack>
+
+extern "C" {
+#include "BLI_utildefines.h"
+
+#include "DNA_ID.h"
+
+#include "RNA_access.h"
+#include "RNA_types.h"
+}
+
+#include "depsgraph_util_cycle.h"
+#include "depsgraph.h"
+#include "depsnode.h"
+#include "depsnode_component.h"
+#include "depsnode_operation.h"
+
+struct StackEntry {
+ OperationDepsNode *node;
+ StackEntry *from;
+ DepsRelation *via_relation;
+};
+
+void deg_graph_detect_cycles(Depsgraph *graph)
+{
+ /* Not is not visited at all during traversal. */
+ const int NODE_NOT_VISITED = 0;
+ /* Node has been visited during traversal and not in current stack. */
+ const int NODE_VISITED = 1;
+ /* Node has been visited during traversal and is in current stack. */
+ const int NODE_IN_STACK = 2;
+
+ std::stack<StackEntry> traversal_stack;
+ for (Depsgraph::OperationNodes::const_iterator it_op = graph->operations.begin();
+ it_op != graph->operations.end();
+ ++it_op)
+ {
+ OperationDepsNode *node = *it_op;
+ bool has_inlinks = false;
+ for (OperationDepsNode::Relations::const_iterator it_rel = node->inlinks.begin();
+ it_rel != node->inlinks.end();
+ ++it_rel)
+ {
+ DepsRelation *rel = *it_rel;
+ if (rel->from->type == DEPSNODE_TYPE_OPERATION) {
+ has_inlinks = true;
+ }
+ }
+ if (has_inlinks == false) {
+ StackEntry entry;
+ entry.node = node;
+ entry.from = NULL;
+ entry.via_relation = NULL;
+ traversal_stack.push(entry);
+ node->done = NODE_IN_STACK;
+ }
+ else {
+ node->done = NODE_NOT_VISITED;
+ }
+ }
+
+ while (!traversal_stack.empty()) {
+ StackEntry &entry = traversal_stack.top();
+ OperationDepsNode *node = entry.node;
+ bool all_child_traversed = true;
+ for (OperationDepsNode::Relations::const_iterator it_rel = node->outlinks.begin();
+ it_rel != node->outlinks.end();
+ ++it_rel)
+ {
+ DepsRelation *rel = *it_rel;
+ if (rel->to->type == DEPSNODE_TYPE_OPERATION) {
+ OperationDepsNode *to = (OperationDepsNode *)rel->to;
+ if (to->done == NODE_IN_STACK) {
+ printf("Dependency cycle detected:\n");
+ printf(" '%s' depends on '%s' through '%s'\n",
+ to->full_identifier().c_str(),
+ node->full_identifier().c_str(),
+ rel->name);
+
+ StackEntry *current = &entry;
+ while (current->node != to) {
+ BLI_assert(current != NULL);
+ printf(" '%s' depends on '%s' through '%s'\n",
+ current->node->full_identifier().c_str(),
+ current->from->node->full_identifier().c_str(),
+ current->via_relation->name);
+ current = current->from;
+ }
+ /* TODO(sergey): So called roussian rlette cycle solver. */
+ rel->flag |= DEPSREL_FLAG_CYCLIC;
+ }
+ else if (to->done == NODE_NOT_VISITED) {
+ StackEntry new_entry;
+ new_entry.node = to;
+ new_entry.from = &entry;
+ new_entry.via_relation = rel;
+ traversal_stack.push(new_entry);
+ to->done = NODE_IN_STACK;
+ all_child_traversed = false;
+ break;
+ }
+ }
+ }
+ if (all_child_traversed) {
+ node->done = NODE_VISITED;
+ traversal_stack.pop();
+ }
+ }
+}
diff --git a/source/blender/depsgraph/util/depsgraph_util_cycle.h b/source/blender/depsgraph/util/depsgraph_util_cycle.h
new file mode 100644
index 00000000000..fac38b61057
--- /dev/null
+++ b/source/blender/depsgraph/util/depsgraph_util_cycle.h
@@ -0,0 +1,37 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2015 Blender Foundation.
+ * All rights reserved.
+ *
+ * Contributor(s): Sergey Sharybin
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/depsgraph/util/depsgraph_util_cycle.h
+ * \ingroup depsgraph
+ */
+
+#ifndef __DEPSGRAPH_UTIL_CYCLE_H__
+#define __DEPSGRAPH_UTIL_CYCLE_H__
+
+struct Depsgraph;
+
+void deg_graph_detect_cycles(Depsgraph *graph);
+
+#endif /* __DEPSGRAPH_UTIL_CYCLE_H__ */
diff --git a/source/blender/depsgraph/util/depsgraph_util_function.h b/source/blender/depsgraph/util/depsgraph_util_function.h
new file mode 100644
index 00000000000..a4301833408
--- /dev/null
+++ b/source/blender/depsgraph/util/depsgraph_util_function.h
@@ -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.
+ *
+ * The Original Code is Copyright (C) 2014 Blender Foundation.
+ * All rights reserved.
+ *
+ * Original Author: Lukas Toenne
+ * Contributor(s):
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/depsgraph/util/depsgraph_util_function.h
+ * \ingroup depsgraph
+ */
+
+#ifndef __DEPSGRAPH_UTIL_FUNCTION_H__
+#define __DEPSGRAPH_UTIL_FUNCTION_H__
+
+#if (__cplusplus > 199711L)
+
+#include <functional>
+
+using std::function;
+using namespace std::placeholders;
+#define function_bind std::bind
+
+#elif defined(HAVE_BOOST_FUNCTION_BINDINGS)
+
+#include <boost/bind.hpp>
+#include <boost/function.hpp>
+
+using boost::function;
+#define function_bind boost::bind
+
+#else
+
+#pragma message("No available function binding implementation. Using stub instead, disabling new depsgraph")
+
+#ifndef WITH_LEGACY_DEPSGRAPH
+# error "Unable to build new depsgraph and legacy one is disabled."
+#endif
+
+#define DISABLE_NEW_DEPSGRAPH
+
+#include <cstdlib>
+
+template<typename T>
+class function {
+public:
+ function() {};
+ function(void *) {}
+ operator bool() const { return false; }
+ bool operator== (void *) { return false; }
+
+ template<typename T1>
+ void operator() (T1) {
+ BLI_assert(!"Should not be used");
+ }
+};
+
+class Wrap {
+public:
+ Wrap() {}
+ template <typename T>
+ Wrap(T /*arg*/) {}
+};
+
+template <typename T>
+void *function_bind(T func,
+ Wrap arg1 = Wrap(),
+ Wrap arg2 = Wrap(),
+ Wrap arg3 = Wrap(),
+ Wrap arg4 = Wrap(),
+ Wrap arg5 = Wrap(),
+ Wrap arg6 = Wrap(),
+ Wrap arg7 = Wrap())
+{
+ BLI_assert(!"Should not be used");
+ (void)func;
+ (void)arg1;
+ (void)arg2;
+ (void)arg3;
+ (void)arg4;
+ (void)arg5;
+ (void)arg6;
+ (void)arg7;
+ return NULL;
+}
+
+#define _1 Wrap()
+#define _2 Wrap()
+#define _3 Wrap()
+#define _4 Wrap()
+
+#endif
+
+#endif /* __DEPSGRAPH_UTIL_FUNCTION_H__ */
diff --git a/source/blender/depsgraph/util/depsgraph_util_hash.h b/source/blender/depsgraph/util/depsgraph_util_hash.h
new file mode 100644
index 00000000000..bc75627a026
--- /dev/null
+++ b/source/blender/depsgraph/util/depsgraph_util_hash.h
@@ -0,0 +1,72 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2014 Blender Foundation.
+ * All rights reserved.
+ *
+ * Original Author: Brecht van Lommel
+ * Contributor(s): Lukas Toenne
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/depsgraph/util/depsgraph_util_hash.h
+ * \ingroup depsgraph
+ */
+
+#ifndef __DEPSGRAPH_UTIL_HASH_H__
+#define __DEPSGRAPH_UTIL_HASH_H__
+
+#if defined(DEG_NO_UNORDERED_MAP)
+# define DEG_HASH_NAMESPACE_BEGIN
+# define DEG_HASH_NAMESPACE_END
+#endif
+
+#if defined(DEG_TR1_UNORDERED_MAP)
+# include <tr1/unordered_map>
+# define DEG_HASH_NAMESPACE_BEGIN namespace std { namespace tr1 {
+# define DEG_HASH_NAMESPACE_END } }
+using std::tr1::hash;
+#endif
+
+#if defined(DEG_STD_UNORDERED_MAP)
+# include <unordered_map>
+# define DEG_HASH_NAMESPACE_BEGIN namespace std {
+# define DEG_HASH_NAMESPACE_END }
+using std::hash;
+#endif
+
+#if defined(DEG_STD_UNORDERED_MAP_IN_TR1_NAMESPACE)
+# include <unordered_map>
+# define DEG_HASH_NAMESPACE_BEGIN namespace std { namespace tr1 {
+# define DEG_HASH_NAMESPACE_END } }
+using std::tr1::hash;
+#endif
+
+#if !defined(DEG_NO_UNORDERED_MAP) && !defined(DEG_TR1_UNORDERED_MAP) && \
+ !defined(DEG_STD_UNORDERED_MAP) && !defined(DEG_STD_UNORDERED_MAP_IN_TR1_NAMESPACE) // NOLINT
+# error One of: DEG_NO_UNORDERED_MAP, DEG_TR1_UNORDERED_MAP,\
+ DEG_STD_UNORDERED_MAP, DEG_STD_UNORDERED_MAP_IN_TR1_NAMESPACE must be defined! // NOLINT
+#endif
+
+/* XXX this might require 2 different variants for sizeof(size_t) (32 vs 64 bit) */
+inline size_t hash_combine(size_t hash_a, size_t hash_b)
+{
+ return hash_a ^ (hash_b + 0x9e3779b9 + (hash_a << 6) + (hash_a >> 2));
+}
+
+#endif /* __DEPSGRAPH_UTIL_HASH_H__ */
diff --git a/source/blender/depsgraph/util/depsgraph_util_map.h b/source/blender/depsgraph/util/depsgraph_util_map.h
new file mode 100644
index 00000000000..0eae1d79e34
--- /dev/null
+++ b/source/blender/depsgraph/util/depsgraph_util_map.h
@@ -0,0 +1,67 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2014 Blender Foundation.
+ * All rights reserved.
+ *
+ * Original Author: Brecht van Lommel
+ * Contributor(s): Lukas Toenne
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/depsgraph/util/depsgraph_util_map.h
+ * \ingroup depsgraph
+ */
+
+#ifndef __DEPSGRAPH_UTIL_MAP_H__
+#define __DEPSGRAPH_UTIL_MAP_H__
+
+#include <map>
+
+#include "depsgraph_util_hash.h"
+
+using std::map;
+using std::pair;
+
+#if defined(DEG_NO_UNORDERED_MAP)
+# include <map>
+typedef std::map unordered_map;
+#endif
+
+#if defined(DEG_TR1_UNORDERED_MAP)
+# include <tr1/unordered_map>
+using std::tr1::unordered_map;
+#endif
+
+#if defined(DEG_STD_UNORDERED_MAP)
+# include <unordered_map>
+using std::unordered_map;
+#endif
+
+#if defined(DEG_STD_UNORDERED_MAP_IN_TR1_NAMESPACE)
+# include <unordered_map>
+using std::tr1::unordered_map;
+#endif
+
+#if !defined(DEG_NO_UNORDERED_MAP) && !defined(DEG_TR1_UNORDERED_MAP) && \
+ !defined(DEG_STD_UNORDERED_MAP) && !defined(DEG_STD_UNORDERED_MAP_IN_TR1_NAMESPACE) // NOLINT
+# error One of: DEG_NO_UNORDERED_MAP, DEG_TR1_UNORDERED_MAP,\
+ DEG_STD_UNORDERED_MAP, DEG_STD_UNORDERED_MAP_IN_TR1_NAMESPACE must be defined! // NOLINT
+#endif
+
+#endif /* __DEPSGRAPH_UTIL_MAP_H__ */
diff --git a/source/blender/depsgraph/util/depsgraph_util_pchanmap.cc b/source/blender/depsgraph/util/depsgraph_util_pchanmap.cc
new file mode 100644
index 00000000000..80b37ec622d
--- /dev/null
+++ b/source/blender/depsgraph/util/depsgraph_util_pchanmap.cc
@@ -0,0 +1,136 @@
+/*
+ * ***** 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) 2015 Blender Foundation.
+ * All rights reserved.
+ *
+ * Original Author: Sergey Sharybin
+ * Contributor(s): Joshua Leung
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/depsgraph/util/depsgraph_util_pchanmap.cc
+ * \ingroup depsgraph
+ */
+
+#include "depsgraph_util_pchanmap.h"
+
+#include <stdio.h>
+#include <string.h>
+
+extern "C" {
+#include "BLI_utildefines.h"
+#include "BLI_ghash.h"
+}
+
+static void free_rootpchanmap_valueset(void *val)
+{
+ /* Just need to free the set itself - the names stored are all references. */
+ GSet *values = (GSet *)val;
+ BLI_gset_free(values, NULL);
+}
+
+RootPChanMap::RootPChanMap()
+{
+ /* Just create empty map. */
+ m_map = BLI_ghash_str_new("RootPChanMap");
+}
+
+RootPChanMap::~RootPChanMap()
+{
+ /* Free the map, and all the value sets. */
+ BLI_ghash_free(m_map, NULL, free_rootpchanmap_valueset);
+}
+
+/* Debug contents of map */
+void RootPChanMap::print_debug()
+{
+ GHashIterator it1;
+ GSetIterator it2;
+
+ printf("Root PChan Map:\n");
+ GHASH_ITER(it1, m_map) {
+ const char *item = (const char *)BLI_ghashIterator_getKey(&it1);
+ GSet *values = (GSet *)BLI_ghashIterator_getValue(&it1);
+
+ printf(" %s : { ", item);
+ GSET_ITER(it2, values) {
+ const char *val = (const char *)BLI_gsetIterator_getKey(&it2);
+ printf("%s, ", val);
+ }
+ printf("}\n");
+ }
+}
+
+/* Add a mapping. */
+void RootPChanMap::add_bone(const char *bone, const char *root)
+{
+ if (BLI_ghash_haskey(m_map, bone)) {
+ /* Add new entry, but only add the root if it doesn't already
+ * exist in there.
+ */
+ GSet *values = (GSet *)BLI_ghash_lookup(m_map, bone);
+ BLI_gset_add(values, (void *)root);
+ }
+ else {
+ /* Create new set and mapping. */
+ GSet *values = BLI_gset_new(BLI_ghashutil_strhash_p,
+ BLI_ghashutil_strcmp,
+ "RootPChanMap Value Set");
+ BLI_ghash_insert(m_map, (void *)bone, (void *)values);
+
+ /* Add new entry now. */
+ BLI_gset_insert(values, (void *)root);
+ }
+}
+
+/* Check if there's a common root bone between two bones. */
+bool RootPChanMap::has_common_root(const char *bone1, const char *bone2)
+{
+ /* Ensure that both are in the map... */
+ if (BLI_ghash_haskey(m_map, bone1) == false) {
+ //fprintf("RootPChanMap: bone1 '%s' not found (%s => %s)\n", bone1, bone1, bone2);
+ //print_debug();
+ return false;
+ }
+
+ if (BLI_ghash_haskey(m_map, bone2) == false) {
+ //fprintf("RootPChanMap: bone2 '%s' not found (%s => %s)\n", bone2, bone1, bone2);
+ //print_debug();
+ return false;
+ }
+
+ GSet *bone1_roots = (GSet *)BLI_ghash_lookup(m_map, (void *)bone1);
+ GSet *bone2_roots = (GSet *)BLI_ghash_lookup(m_map, (void *)bone2);
+
+ GSetIterator it1, it2;
+ GSET_ITER(it1, bone1_roots) {
+ GSET_ITER(it2, bone2_roots) {
+ const char *v1 = (const char *)BLI_gsetIterator_getKey(&it1);
+ const char *v2 = (const char *)BLI_gsetIterator_getKey(&it2);
+
+ if (strcmp(v1, v2) == 0) {
+ //fprintf("RootPchanMap: %s in common for %s => %s\n", v1, bone1, bone2);
+ return true;
+ }
+ }
+ }
+
+ //fprintf("RootPChanMap: No common root found (%s => %s)\n", bone1, bone2);
+ return false;
+}
diff --git a/source/blender/depsgraph/util/depsgraph_util_pchanmap.h b/source/blender/depsgraph/util/depsgraph_util_pchanmap.h
new file mode 100644
index 00000000000..b7f4c495933
--- /dev/null
+++ b/source/blender/depsgraph/util/depsgraph_util_pchanmap.h
@@ -0,0 +1,59 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2015 Blender Foundation.
+ * All rights reserved.
+ *
+ * Original Author: Sergey Sharybin
+ * Contributor(s): Joshua Leung
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/depsgraph/util/depsgraph_util_pchanmap.h
+ * \ingroup depsgraph
+ */
+
+#ifndef __DEPSGRAPH_UTIL_PCHANMAP_H__
+#define __DEPSGRAPH_UTIL_PCHANMAP_H__
+
+struct RootPChanMap {
+ /* ctor and dtor - Create and free the internal map respectively. */
+ RootPChanMap();
+ ~RootPChanMap();
+
+ /* Debug contents of map. */
+ void print_debug();
+
+ /* Add a mapping. */
+ void add_bone(const char *bone, const char *root);
+
+ /* Check if there's a common root bone between two bones. */
+ bool has_common_root(const char *bone1, const char *bone2);
+
+private:
+ /* The actual map:
+ * - Keys are "strings" (const char *) - not dynamically allocated.
+ * - Values are "sets" (const char *) - not dynamically allocated.
+ *
+ * We don't use the C++ maps here, as it's more convenient to use
+ * Blender's GHash and be able to compare by-value instead of by-ref.
+ */
+ struct GHash *m_map;
+};
+
+#endif /* __DEPSGRAPH_UTIL_PCHANMAP_H__ */
diff --git a/source/blender/depsgraph/util/depsgraph_util_set.h b/source/blender/depsgraph/util/depsgraph_util_set.h
new file mode 100644
index 00000000000..008ec6b74ca
--- /dev/null
+++ b/source/blender/depsgraph/util/depsgraph_util_set.h
@@ -0,0 +1,66 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2014 Blender Foundation.
+ * All rights reserved.
+ *
+ * Original Author: Brecht van Lommel
+ * Contributor(s): Lukas Toenne
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/depsgraph/util/depsgraph_util_set.h
+ * \ingroup depsgraph
+ */
+
+#ifndef __DEPSGRAPH_UTIL_SET_H__
+#define __DEPSGRAPH_UTIL_SET_H__
+
+#include <set>
+
+#include "depsgraph_util_hash.h"
+
+using std::set;
+
+#if defined(DEG_NO_UNORDERED_MAP)
+# include <set>
+typedef std::set unordered_set;
+#endif
+
+#if defined(DEG_TR1_UNORDERED_MAP)
+# include <tr1/unordered_set>
+using std::tr1::unordered_set;
+#endif
+
+#if defined(DEG_STD_UNORDERED_MAP)
+# include <unordered_set>
+using std::unordered_set;
+#endif
+
+#if defined(DEG_STD_UNORDERED_MAP_IN_TR1_NAMESPACE)
+# include <unordered_set>
+using std::tr1::unordered_set;
+#endif
+
+#if !defined(DEG_NO_UNORDERED_MAP) && !defined(DEG_TR1_UNORDERED_MAP) && \
+ !defined(DEG_STD_UNORDERED_MAP) && !defined(DEG_STD_UNORDERED_MAP_IN_TR1_NAMESPACE) // NOLINT
+# error One of: DEG_NO_UNORDERED_MAP, DEG_TR1_UNORDERED_MAP,\
+ DEG_STD_UNORDERED_MAP, DEG_STD_UNORDERED_MAP_IN_TR1_NAMESPACE must be defined! // NOLINT
+#endif
+
+#endif /* __DEPSGRAPH_UTIL_SET_H__ */
diff --git a/source/blender/depsgraph/util/depsgraph_util_transitive.cc b/source/blender/depsgraph/util/depsgraph_util_transitive.cc
new file mode 100644
index 00000000000..98192a9540f
--- /dev/null
+++ b/source/blender/depsgraph/util/depsgraph_util_transitive.cc
@@ -0,0 +1,139 @@
+/*
+ * ***** 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) 2015 Blender Foundation.
+ * All rights reserved.
+ *
+ * Contributor(s): Lukas Toenne,
+ * Sergey Sharybin,
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/depsgraph/util/depsgraph_util_transitive.cc
+ * \ingroup depsgraph
+ */
+
+extern "C" {
+#include "MEM_guardedalloc.h"
+
+#include "BLI_utildefines.h"
+
+#include "DNA_ID.h"
+
+#include "RNA_access.h"
+#include "RNA_types.h"
+}
+
+#include "depsgraph_util_transitive.h"
+#include "depsgraph.h"
+#include "depsnode.h"
+#include "depsnode_component.h"
+#include "depsnode_operation.h"
+
+/* -------------------------------------------------- */
+
+/* Performs a transitive reduction to remove redundant relations.
+ * http://en.wikipedia.org/wiki/Transitive_reduction
+ *
+ * XXX The current implementation is somewhat naive and has O(V*E) worst case
+ * runtime.
+ * A more optimized algorithm can be implemented later, e.g.
+ *
+ * http://www.sciencedirect.com/science/article/pii/0304397588900321/pdf?md5=3391e309b708b6f9cdedcd08f84f4afc&pid=1-s2.0-0304397588900321-main.pdf
+ *
+ * Care has to be taken to make sure the algorithm can handle the cyclic case
+ * too! (unless we can to prevent this case early on).
+ */
+
+enum {
+ OP_VISITED = 1,
+ OP_REACHABLE = 2,
+};
+
+static void deg_graph_tag_paths_recursive(DepsNode *node)
+{
+ if (node->done & OP_VISITED)
+ return;
+ node->done |= OP_VISITED;
+
+ for (OperationDepsNode::Relations::const_iterator it = node->inlinks.begin();
+ it != node->inlinks.end();
+ ++it)
+ {
+ DepsRelation *rel = *it;
+
+ deg_graph_tag_paths_recursive(rel->from);
+ /* Do this only in inlinks loop, so the target node does not get
+ * flagged.
+ */
+ rel->from->done |= OP_REACHABLE;
+ }
+}
+
+void deg_graph_transitive_reduction(Depsgraph *graph)
+{
+ for (Depsgraph::OperationNodes::const_iterator it_target = graph->operations.begin();
+ it_target != graph->operations.end();
+ ++it_target)
+ {
+ OperationDepsNode *target = *it_target;
+
+ /* Clear tags. */
+ for (Depsgraph::OperationNodes::const_iterator it = graph->operations.begin();
+ it != graph->operations.end();
+ ++it)
+ {
+ OperationDepsNode *node = *it;
+ node->done = 0;
+ }
+
+ /* mark nodes from which we can reach the target
+ * start with children, so the target node and direct children are not
+ * flagged.
+ */
+ target->done |= OP_VISITED;
+ for (OperationDepsNode::Relations::const_iterator it = target->inlinks.begin();
+ it != target->inlinks.end();
+ ++it)
+ {
+ DepsRelation *rel = *it;
+
+ deg_graph_tag_paths_recursive(rel->from);
+ }
+
+ /* Eemove redundant paths to the target. */
+ for (DepsNode::Relations::const_iterator it_rel = target->inlinks.begin();
+ it_rel != target->inlinks.end();
+ )
+ {
+ DepsRelation *rel = *it_rel;
+ /* Increment in advance, so we can safely remove the relation. */
+ ++it_rel;
+
+ if (rel->from->type == DEPSNODE_TYPE_TIMESOURCE) {
+ /* HACK: time source nodes don't get "done" flag set/cleared. */
+ /* TODO: there will be other types in future, so iterators above
+ * need modifying.
+ */
+ }
+ else if (rel->from->done & OP_REACHABLE) {
+ OBJECT_GUARDED_DELETE(rel, DepsRelation);
+ }
+ }
+ }
+}
diff --git a/source/blender/depsgraph/util/depsgraph_util_transitive.h b/source/blender/depsgraph/util/depsgraph_util_transitive.h
new file mode 100644
index 00000000000..a80a1d783d7
--- /dev/null
+++ b/source/blender/depsgraph/util/depsgraph_util_transitive.h
@@ -0,0 +1,38 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2015 Blender Foundation.
+ * All rights reserved.
+ *
+ * Contributor(s): Lukas Toenne
+ * Sergey Sharybin,
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/depsgraph/util/depsgraph_util_transitive.h
+ * \ingroup depsgraph
+ */
+
+#ifndef __DEPSGRAPH_UTIL_TRANSITIVE_H__
+#define __DEPSGRAPH_UTIL_TRANSITIVE_H__
+
+struct Depsgraph;
+
+void deg_graph_transitive_reduction(Depsgraph *graph);
+
+#endif /* __DEPSGRAPH_UTIL_TRANSITIVE_H__ */
diff --git a/source/blender/editors/animation/CMakeLists.txt b/source/blender/editors/animation/CMakeLists.txt
index d6030a967d5..473b0e6bc5a 100644
--- a/source/blender/editors/animation/CMakeLists.txt
+++ b/source/blender/editors/animation/CMakeLists.txt
@@ -20,13 +20,15 @@
set(INC
../include
- ../../blenfont
../../blenkernel
../../blenlib
+ ../../blentranslation
+ ../../gpu
../../makesdna
../../makesrna
../../windowmanager
../../../../intern/guardedalloc
+ ../../../../intern/glew-mx
)
set(INC_SYS
@@ -57,4 +59,6 @@ if(WITH_INTERNATIONAL)
add_definitions(-DWITH_INTERNATIONAL)
endif()
+add_definitions(${GL_DEFINITIONS})
+
blender_add_lib(bf_editor_animation "${SRC}" "${INC}" "${INC_SYS}")
diff --git a/source/blender/editors/animation/SConscript b/source/blender/editors/animation/SConscript
index 91d480978c4..fb5ff53cf16 100644
--- a/source/blender/editors/animation/SConscript
+++ b/source/blender/editors/animation/SConscript
@@ -31,17 +31,20 @@ sources = env.Glob('*.c')
incs = [
'#/intern/guardedalloc',
- '#/extern/glew/include',
+ env['BF_GLEW_INC'],
+ '#/intern/glew-mx',
'../include',
- '../../blenfont',
'../../blenkernel',
'../../blenlib',
+ '../../blentranslation',
+ '../../gpu',
'../../makesdna',
'../../makesrna',
'../../windowmanager',
]
defs = []
+defs += env['BF_GL_DEFINITIONS']
if env['WITH_BF_INTERNATIONAL']:
defs.append('WITH_INTERNATIONAL')
diff --git a/source/blender/editors/animation/anim_channels_defines.c b/source/blender/editors/animation/anim_channels_defines.c
index 7d8e278f0cf..6979850c21a 100644
--- a/source/blender/editors/animation/anim_channels_defines.c
+++ b/source/blender/editors/animation/anim_channels_defines.c
@@ -36,7 +36,7 @@
#include "BLI_math.h"
#include "BLI_utildefines.h"
-#include "BLF_translation.h"
+#include "BLT_translation.h"
#include "DNA_anim_types.h"
#include "DNA_armature_types.h"
@@ -61,6 +61,7 @@
#include "RNA_access.h"
+#include "BKE_animsys.h"
#include "BKE_curve.h"
#include "BKE_key.h"
#include "BKE_nla.h"
@@ -109,7 +110,7 @@ static void acf_generic_root_color(bAnimContext *UNUSED(ac), bAnimListElem *UNUS
/* backdrop for top-level widgets (Scene and Object only) */
static void acf_generic_root_backdrop(bAnimContext *ac, bAnimListElem *ale, float yminc, float ymaxc)
{
- bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale);
+ const bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale);
View2D *v2d = &ac->ar->v2d;
short expanded = ANIM_channel_setting_get(ac, ale, ACHANNEL_SETTING_EXPAND) != 0;
short offset = (acf->get_offset) ? acf->get_offset(ac, ale) : 0;
@@ -120,8 +121,8 @@ static void acf_generic_root_backdrop(bAnimContext *ac, bAnimListElem *ale, floa
glColor3fv(color);
/* rounded corners on LHS only - top only when expanded, but bottom too when collapsed */
- uiSetRoundBox((expanded) ? UI_CNR_TOP_LEFT : (UI_CNR_TOP_LEFT | UI_CNR_BOTTOM_LEFT));
- uiDrawBox(GL_POLYGON, offset, yminc, v2d->cur.xmax + EXTRA_SCROLL_PAD, ymaxc, 8);
+ UI_draw_roundbox_corner_set((expanded) ? UI_CNR_TOP_LEFT : (UI_CNR_TOP_LEFT | UI_CNR_BOTTOM_LEFT));
+ UI_draw_roundbox_gl_mode(GL_POLYGON, offset, yminc, v2d->cur.xmax + EXTRA_SCROLL_PAD, ymaxc, 8);
}
@@ -135,7 +136,7 @@ static void acf_generic_dataexpand_color(bAnimContext *UNUSED(ac), bAnimListElem
/* backdrop for data expanders under top-level Scene/Object */
static void acf_generic_dataexpand_backdrop(bAnimContext *ac, bAnimListElem *ale, float yminc, float ymaxc)
{
- bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale);
+ const bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale);
View2D *v2d = &ac->ar->v2d;
short offset = (acf->get_offset) ? acf->get_offset(ac, ale) : 0;
float color[3];
@@ -159,14 +160,16 @@ static bool acf_show_channel_colors(bAnimContext *ac)
{
SpaceAction *saction = (SpaceAction *)ac->sl;
showGroupColors = !(saction->flag & SACTION_NODRAWGCOLORS);
- }
+
break;
+ }
case SPACE_IPO:
{
SpaceIpo *sipo = (SpaceIpo *)ac->sl;
showGroupColors = !(sipo->flag & SIPO_NODRAWGCOLORS);
- }
+
break;
+ }
}
}
@@ -176,7 +179,7 @@ static bool acf_show_channel_colors(bAnimContext *ac)
/* get backdrop color for generic channels */
static void acf_generic_channel_color(bAnimContext *ac, bAnimListElem *ale, float r_color[3])
{
- bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale);
+ const bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale);
bActionGroup *grp = NULL;
short indent = (acf->get_indent_level) ? acf->get_indent_level(ac, ale) : 0;
bool showGroupColors = acf_show_channel_colors(ac);
@@ -216,7 +219,7 @@ static void acf_generic_channel_color(bAnimContext *ac, bAnimListElem *ale, floa
/* backdrop for generic channels */
static void acf_generic_channel_backdrop(bAnimContext *ac, bAnimListElem *ale, float yminc, float ymaxc)
{
- bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale);
+ const bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale);
View2D *v2d = &ac->ar->v2d;
short offset = (acf->get_offset) ? acf->get_offset(ac, ale) : 0;
float color[3];
@@ -268,7 +271,7 @@ static short acf_generic_indention_flexible(bAnimContext *UNUSED(ac), bAnimListE
/* basic offset for channels derived from indention */
static short acf_generic_basic_offset(bAnimContext *ac, bAnimListElem *ale)
{
- bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale);
+ const bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale);
if (acf && acf->get_indent_level)
return acf->get_indent_level(ac, ale) * INDENT_STEP_SIZE;
@@ -408,7 +411,7 @@ static void acf_summary_color(bAnimContext *UNUSED(ac), bAnimListElem *UNUSED(al
/* backdrop for summary widget */
static void acf_summary_backdrop(bAnimContext *ac, bAnimListElem *ale, float yminc, float ymaxc)
{
- bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale);
+ const bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale);
View2D *v2d = &ac->ar->v2d;
float color[3];
@@ -420,8 +423,8 @@ static void acf_summary_backdrop(bAnimContext *ac, bAnimListElem *ale, float ymi
* - top and bottom
* - special hack: make the top a bit higher, since we are first...
*/
- uiSetRoundBox(UI_CNR_TOP_LEFT | UI_CNR_BOTTOM_LEFT);
- uiDrawBox(GL_POLYGON, 0, yminc - 2, v2d->cur.xmax + EXTRA_SCROLL_PAD, ymaxc, 8);
+ UI_draw_roundbox_corner_set(UI_CNR_TOP_LEFT | UI_CNR_BOTTOM_LEFT);
+ UI_draw_roundbox_gl_mode(GL_POLYGON, 0, yminc - 2, v2d->cur.xmax + EXTRA_SCROLL_PAD, ymaxc, 8);
}
/* name for summary entries */
@@ -789,7 +792,7 @@ static void acf_group_color(bAnimContext *ac, bAnimListElem *ale, float r_color[
/* backdrop for group widget */
static void acf_group_backdrop(bAnimContext *ac, bAnimListElem *ale, float yminc, float ymaxc)
{
- bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale);
+ const bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale);
View2D *v2d = &ac->ar->v2d;
short expanded = ANIM_channel_setting_get(ac, ale, ACHANNEL_SETTING_EXPAND) != 0;
short offset = (acf->get_offset) ? acf->get_offset(ac, ale) : 0;
@@ -800,8 +803,8 @@ static void acf_group_backdrop(bAnimContext *ac, bAnimListElem *ale, float yminc
glColor3fv(color);
/* rounded corners on LHS only - top only when expanded, but bottom too when collapsed */
- uiSetRoundBox(expanded ? UI_CNR_TOP_LEFT : (UI_CNR_TOP_LEFT | UI_CNR_BOTTOM_LEFT));
- uiDrawBox(GL_POLYGON, offset, yminc, v2d->cur.xmax + EXTRA_SCROLL_PAD, ymaxc, 8);
+ UI_draw_roundbox_corner_set(expanded ? UI_CNR_TOP_LEFT : (UI_CNR_TOP_LEFT | UI_CNR_BOTTOM_LEFT));
+ UI_draw_roundbox_gl_mode(GL_POLYGON, offset, yminc, v2d->cur.xmax + EXTRA_SCROLL_PAD, ymaxc, 8);
}
/* name for group entries */
@@ -864,7 +867,11 @@ static int acf_group_setting_flag(bAnimContext *ac, eAnimChannel_Settings settin
case ACHANNEL_SETTING_MUTE: /* muted */
return AGRP_MUTED;
-
+
+ case ACHANNEL_SETTING_MOD_OFF: /* muted */
+ *neg = 1;
+ return AGRP_MODIFIERS_OFF;
+
case ACHANNEL_SETTING_PROTECT: /* protected */
return AGRP_PROTECTED;
@@ -945,6 +952,7 @@ static bool acf_fcurve_setting_valid(bAnimContext *ac, bAnimListElem *ale, eAnim
/* unsupported */
case ACHANNEL_SETTING_SOLO: /* Solo Flag is only for NLA */
case ACHANNEL_SETTING_EXPAND: /* F-Curves are not containers */
+ case ACHANNEL_SETTING_PINNED: /* This is only for NLA Actions */
return false;
/* conditionally available */
@@ -982,6 +990,10 @@ static int acf_fcurve_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Settin
case ACHANNEL_SETTING_VISIBLE: /* visibility - graph editor */
return FCURVE_VISIBLE;
+ case ACHANNEL_SETTING_MOD_OFF:
+ *neg = 1;
+ return FCURVE_MOD_OFF;
+
default: /* unsupported */
return 0;
}
@@ -1016,6 +1028,149 @@ static bAnimChannelType ACF_FCURVE =
acf_fcurve_setting_ptr /* pointer for setting */
};
+/* NLA Control FCurves Expander ----------------------- */
+
+/* get backdrop color for nla controls widget */
+static void acf_nla_controls_color(bAnimContext *UNUSED(ac), bAnimListElem *UNUSED(ale), float r_color[3])
+{
+ // TODO: give this its own theme setting?
+ UI_GetThemeColorShade3fv(TH_GROUP, 55, r_color);
+}
+
+/* backdrop for nla controls expander widget */
+static void acf_nla_controls_backdrop(bAnimContext *ac, bAnimListElem *ale, float yminc, float ymaxc)
+{
+ const bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale);
+ View2D *v2d = &ac->ar->v2d;
+ short expanded = ANIM_channel_setting_get(ac, ale, ACHANNEL_SETTING_EXPAND) != 0;
+ short offset = (acf->get_offset) ? acf->get_offset(ac, ale) : 0;
+ float color[3];
+
+ /* set backdrop drawing color */
+ acf->get_backdrop_color(ac, ale, color);
+ glColor3fv(color);
+
+ /* rounded corners on LHS only - top only when expanded, but bottom too when collapsed */
+ UI_draw_roundbox_corner_set(expanded ? UI_CNR_TOP_LEFT : (UI_CNR_TOP_LEFT | UI_CNR_BOTTOM_LEFT));
+ UI_draw_roundbox_gl_mode(GL_POLYGON, offset, yminc, v2d->cur.xmax + EXTRA_SCROLL_PAD, ymaxc, 5);
+}
+
+/* name for nla controls expander entries */
+static void acf_nla_controls_name(bAnimListElem *UNUSED(ale), char *name)
+{
+ BLI_strncpy(name, IFACE_("NLA Strip Controls"), ANIM_CHAN_NAME_SIZE);
+}
+
+/* check if some setting exists for this channel */
+static bool acf_nla_controls_setting_valid(bAnimContext *UNUSED(ac), bAnimListElem *UNUSED(ale), eAnimChannel_Settings setting)
+{
+ /* for now, all settings are supported, though some are only conditionally */
+ switch (setting) {
+ /* supported */
+ case ACHANNEL_SETTING_EXPAND:
+ return true;
+
+ // TOOD: selected?
+
+ default: /* unsupported */
+ return false;
+ }
+}
+
+/* get the appropriate flag(s) for the setting when it is valid */
+static int acf_nla_controls_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Settings setting, bool *neg)
+{
+ /* clear extra return data first */
+ *neg = false;
+
+ switch (setting) {
+ case ACHANNEL_SETTING_EXPAND: /* expanded */
+ *neg = true;
+ return ADT_NLA_SKEYS_COLLAPSED;
+
+ default:
+ /* this shouldn't happen */
+ return 0;
+ }
+}
+
+/* get pointer to the setting */
+static void *acf_nla_controls_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings UNUSED(setting), short *type)
+{
+ AnimData *adt = (AnimData *)ale->data;
+
+ /* all flags are just in adt->flag for now... */
+ return GET_ACF_FLAG_PTR(adt->flag, type);
+}
+
+static int acf_nla_controls_icon(bAnimListElem *UNUSED(ale))
+{
+ return ICON_NLA;
+}
+
+/* NLA Control FCurves Expander type define */
+static bAnimChannelType ACF_NLACONTROLS =
+{
+ "NLA Controls Expander", /* type name */
+ ACHANNEL_ROLE_EXPANDER, /* role */
+
+ acf_nla_controls_color, /* backdrop color */
+ acf_nla_controls_backdrop, /* backdrop */
+ acf_generic_indention_0, /* indent level */
+ acf_generic_group_offset, /* offset */
+
+ acf_nla_controls_name, /* name */
+ NULL, /* name prop */
+ acf_nla_controls_icon, /* icon */
+
+ acf_nla_controls_setting_valid, /* has setting */
+ acf_nla_controls_setting_flag, /* flag for setting */
+ acf_nla_controls_setting_ptr /* pointer for setting */
+};
+
+
+/* NLA Control F-Curve -------------------------------- */
+
+/* name for nla control fcurve entries */
+static void acf_nla_curve_name(bAnimListElem *ale, char *name)
+{
+ NlaStrip *strip = ale->owner;
+ FCurve *fcu = ale->data;
+ PropertyRNA *prop;
+
+ /* try to get RNA property that this shortened path (relative to the strip) refers to */
+ prop = RNA_struct_type_find_property(&RNA_NlaStrip, fcu->rna_path);
+ if (prop) {
+ /* "name" of this strip displays the UI identifier + the name of the NlaStrip */
+ BLI_snprintf(name, 256, "%s (%s)", RNA_property_ui_name(prop), strip->name);
+ }
+ else {
+ /* unknown property... */
+ BLI_snprintf(name, 256, "%s[%d]", fcu->rna_path, fcu->array_index);
+ }
+}
+
+
+/* NLA Control F-Curve type define */
+static bAnimChannelType ACF_NLACURVE =
+{
+ "NLA Control F-Curve", /* type name */
+ ACHANNEL_ROLE_CHANNEL, /* role */
+
+ acf_generic_channel_color, /* backdrop color */
+ acf_generic_channel_backdrop, /* backdrop */
+ acf_generic_indention_1, /* indent level */
+ acf_generic_group_offset, /* offset */
+
+ acf_nla_curve_name, /* name */
+ acf_fcurve_name_prop, /* name prop */
+ NULL, /* icon */
+
+ acf_fcurve_setting_valid, /* has setting */
+ acf_fcurve_setting_flag, /* flag for setting */
+ acf_fcurve_setting_ptr /* pointer for setting */
+};
+
/* Object Action Expander ------------------------------------------- */
// TODO: just get this from RNA?
@@ -2365,6 +2520,83 @@ static bAnimChannelType ACF_DSSPK =
acf_dsspk_setting_ptr /* pointer for setting */
};
+/* GPencil Expander ------------------------------------------- */
+
+// TODO: just get this from RNA?
+static int acf_dsgpencil_icon(bAnimListElem *UNUSED(ale))
+{
+ return ICON_GREASEPENCIL;
+}
+
+/* get the appropriate flag(s) for the setting when it is valid */
+static int acf_dsgpencil_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Settings setting, bool *neg)
+{
+ /* clear extra return data first */
+ *neg = false;
+
+ switch (setting) {
+ case ACHANNEL_SETTING_EXPAND: /* expanded */
+ return GP_DATA_EXPAND;
+
+ case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */
+ return ADT_NLA_EVAL_OFF;
+
+ case ACHANNEL_SETTING_VISIBLE: /* visible (only in Graph Editor) */
+ *neg = true;
+ return ADT_CURVES_NOT_VISIBLE;
+
+ case ACHANNEL_SETTING_SELECT: /* selected */
+ return ADT_UI_SELECTED;
+
+ default: /* unsupported */
+ return 0;
+ }
+}
+
+/* get pointer to the setting */
+static void *acf_dsgpencil_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings setting, short *type)
+{
+ bGPdata *gpd = (bGPdata *)ale->data;
+
+ /* clear extra return data first */
+ *type = 0;
+
+ switch (setting) {
+ case ACHANNEL_SETTING_EXPAND: /* expanded */
+ return GET_ACF_FLAG_PTR(gpd->flag, type);
+
+ case ACHANNEL_SETTING_SELECT: /* selected */
+ case ACHANNEL_SETTING_MUTE: /* muted (for NLA only) */
+ case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */
+ if (gpd->adt)
+ return GET_ACF_FLAG_PTR(gpd->adt->flag, type);
+ return NULL;
+
+ default: /* unsupported */
+ return NULL;
+ }
+}
+
+/* grease pencil expander type define */
+static bAnimChannelType ACF_DSGPENCIL =
+{
+ "GPencil DS Expander", /* type name */
+ ACHANNEL_ROLE_EXPANDER, /* role */
+
+ acf_generic_dataexpand_color, /* backdrop color */
+ acf_generic_dataexpand_backdrop, /* backdrop */
+ acf_generic_indention_1, /* indent level */
+ acf_generic_basic_offset, /* offset */
+
+ acf_generic_idblock_name, /* name */
+ acf_generic_idblock_name_prop, /* name prop */
+ acf_dsgpencil_icon, /* icon */
+
+ acf_generic_dataexpand_setting_valid, /* has setting */
+ acf_dsgpencil_setting_flag, /* flag for setting */
+ acf_dsgpencil_setting_ptr /* pointer for setting */
+};
+
/* ShapeKey Entry ------------------------------------------- */
/* name for ShapeKey */
@@ -2985,7 +3217,7 @@ static void acf_nlaaction_color(bAnimContext *UNUSED(ac), bAnimListElem *ale, fl
/* backdrop for nla action channel */
static void acf_nlaaction_backdrop(bAnimContext *ac, bAnimListElem *ale, float yminc, float ymaxc)
{
- bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale);
+ const bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale);
View2D *v2d = &ac->ar->v2d;
AnimData *adt = ale->adt;
short offset = (acf->get_offset) ? acf->get_offset(ac, ale) : 0;
@@ -3010,12 +3242,12 @@ static void acf_nlaaction_backdrop(bAnimContext *ac, bAnimListElem *ale, float y
/* only on top left corner, to show that this channel sits on top of the preceding ones
* while still linking into the action line strip to the right
*/
- uiSetRoundBox(UI_CNR_TOP_LEFT);
+ UI_draw_roundbox_corner_set(UI_CNR_TOP_LEFT);
/* draw slightly shifted up vertically to look like it has more separation from other channels,
* but we then need to slightly shorten it so that it doesn't look like it overlaps
*/
- uiDrawBox(GL_POLYGON, offset, yminc + NLACHANNEL_SKIP, (float)v2d->cur.xmax, ymaxc + NLACHANNEL_SKIP - 1, 8);
+ UI_draw_roundbox_gl_mode(GL_POLYGON, offset, yminc + NLACHANNEL_SKIP, (float)v2d->cur.xmax, ymaxc + NLACHANNEL_SKIP - 1, 8);
}
/* name for nla action entries */
@@ -3144,6 +3376,9 @@ static void ANIM_init_channel_typeinfo_data(void)
animchannelTypeInfo[type++] = &ACF_GROUP; /* Group */
animchannelTypeInfo[type++] = &ACF_FCURVE; /* F-Curve */
+ animchannelTypeInfo[type++] = &ACF_NLACONTROLS; /* NLA Control FCurve Expander */
+ animchannelTypeInfo[type++] = &ACF_NLACURVE; /* NLA Control FCurve Channel */
+
animchannelTypeInfo[type++] = &ACF_FILLACTD; /* Object Action Expander */
animchannelTypeInfo[type++] = &ACF_FILLDRIVERS; /* Drivers Expander */
@@ -3162,6 +3397,7 @@ static void ANIM_init_channel_typeinfo_data(void)
animchannelTypeInfo[type++] = &ACF_DSLAT; /* Lattice Channel */
animchannelTypeInfo[type++] = &ACF_DSLINESTYLE; /* LineStyle Channel */
animchannelTypeInfo[type++] = &ACF_DSSPK; /* Speaker Channel */
+ animchannelTypeInfo[type++] = &ACF_DSGPENCIL; /* GreasePencil Channel */
animchannelTypeInfo[type++] = &ACF_SHAPEKEY; /* ShapeKey */
@@ -3177,7 +3413,7 @@ static void ANIM_init_channel_typeinfo_data(void)
}
/* Get type info from given channel type */
-bAnimChannelType *ANIM_channel_get_typeinfo(bAnimListElem *ale)
+const bAnimChannelType *ANIM_channel_get_typeinfo(bAnimListElem *ale)
{
/* santiy checks */
if (ale == NULL)
@@ -3198,7 +3434,7 @@ bAnimChannelType *ANIM_channel_get_typeinfo(bAnimListElem *ale)
/* Print debug info string for the given channel */
void ANIM_channel_debug_print_info(bAnimListElem *ale, short indent_level)
{
- bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale);
+ const bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale);
/* print indents */
for (; indent_level > 0; indent_level--)
@@ -3230,7 +3466,7 @@ void ANIM_channel_debug_print_info(bAnimListElem *ale, short indent_level)
*/
short ANIM_channel_setting_get(bAnimContext *ac, bAnimListElem *ale, eAnimChannel_Settings setting)
{
- bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale);
+ const bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale);
/* 1) check that the setting exists for the current context */
if ((acf) && (!acf->has_setting || acf->has_setting(ac, ale, setting))) {
@@ -3303,7 +3539,7 @@ short ANIM_channel_setting_get(bAnimContext *ac, bAnimListElem *ale, eAnimChanne
*/
void ANIM_channel_setting_set(bAnimContext *ac, bAnimListElem *ale, eAnimChannel_Settings setting, eAnimChannels_SetFlag mode)
{
- bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale);
+ const bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale);
/* 1) check that the setting exists for the current context */
if ((acf) && (!acf->has_setting || acf->has_setting(ac, ale, setting))) {
@@ -3348,13 +3584,29 @@ void ANIM_channel_setting_set(bAnimContext *ac, bAnimListElem *ale, eAnimChannel
#define ICON_WIDTH (0.85f * U.widget_unit)
// width of sliders
#define SLIDER_WIDTH (4 * U.widget_unit)
-// width of rename textboxes
-#define RENAME_TEXT_WIDTH (5 * U.widget_unit)
+// min-width of rename textboxes
+#define RENAME_TEXT_MIN_WIDTH (U.widget_unit)
+
+
+/* Helper - Check if a channel needs renaming */
+static bool achannel_is_being_renamed(const bAnimContext *ac, const bAnimChannelType *acf, size_t channel_index)
+{
+ if (acf->name_prop && ac->ads) {
+ /* if rename index matches, this channel is being renamed */
+ if (ac->ads->renameIndex == channel_index + 1) {
+ return true;
+ }
+ }
+
+ /* not being renamed */
+ return false;
+}
+
/* Draw the given channel */
-void ANIM_channel_draw(bAnimContext *ac, bAnimListElem *ale, float yminc, float ymaxc)
+void ANIM_channel_draw(bAnimContext *ac, bAnimListElem *ale, float yminc, float ymaxc, size_t channel_index)
{
- bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale);
+ const bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale);
View2D *v2d = &ac->ar->v2d;
short selected, offset;
float y, ymid, ytext;
@@ -3407,11 +3659,12 @@ void ANIM_channel_draw(bAnimContext *ac, bAnimListElem *ale, float yminc, float
/* step 4) draw special toggles .................................
* - in Graph Editor, checkboxes for visibility in curves area
* - in NLA Editor, glowing dots for solo/not solo...
+ * - in Grease Pencil mode, color swatches for layer color
*/
if (ac->sl) {
if ((ac->spacetype == SPACE_IPO) && acf->has_setting(ac, ale, ACHANNEL_SETTING_VISIBLE)) {
/* for F-Curves, draw color-preview of curve behind checkbox */
- if (ale->type == ANIMTYPE_FCURVE) {
+ if (ELEM(ale->type, ANIMTYPE_FCURVE, ANIMTYPE_NLACURVE)) {
FCurve *fcu = (FCurve *)ale->data;
/* F-Curve channels need to have a special 'color code' box drawn, which is colored with whatever
@@ -3431,11 +3684,16 @@ void ANIM_channel_draw(bAnimContext *ac, bAnimListElem *ale, float yminc, float
/* just skip - drawn as widget now */
offset += ICON_WIDTH;
}
+ else if (ale->type == ANIMTYPE_GPLAYER) {
+ /* just skip - drawn as a widget */
+ offset += ICON_WIDTH;
+ }
}
/* step 5) draw name ............................................... */
- /* TODO: when renaming, we might not want to draw this, especially if name happens to be longer than channel */
- if (acf->name) {
+ /* Don't draw this if renaming... */
+ if (acf->name && !achannel_is_being_renamed(ac, acf, channel_index)) {
+ const uiFontStyle *fstyle = UI_FSTYLE_WIDGET;
char name[ANIM_CHAN_NAME_SIZE]; /* hopefully this will be enough! */
/* set text color */
@@ -3449,10 +3707,10 @@ void ANIM_channel_draw(bAnimContext *ac, bAnimListElem *ale, float yminc, float
acf->name(ale, name);
offset += 3;
- UI_DrawString(offset, ytext, name);
+ UI_fontstyle_draw_simple(fstyle, offset, ytext, name);
/* draw red underline if channel is disabled */
- if ((ale->type == ANIMTYPE_FCURVE) && (ale->flag & FCURVE_DISABLED)) {
+ if (ELEM(ale->type, ANIMTYPE_FCURVE, ANIMTYPE_NLACURVE) && (ale->flag & FCURVE_DISABLED)) {
/* FIXME: replace hardcoded color here, and check on extents! */
glColor3f(1.0f, 0.0f, 0.0f);
glLineWidth(2.0);
@@ -3519,7 +3777,7 @@ void ANIM_channel_draw(bAnimContext *ac, bAnimListElem *ale, float yminc, float
* (only only F-Curves really can support them for now)
* - slider should start before the toggles (if they're visible) to keep a clean line down the side
*/
- if ((draw_sliders) && ELEM(ale->type, ANIMTYPE_FCURVE, ANIMTYPE_SHAPEKEY)) {
+ if ((draw_sliders) && ELEM(ale->type, ANIMTYPE_FCURVE, ANIMTYPE_NLACURVE, ANIMTYPE_SHAPEKEY)) {
/* adjust offset */
offset += SLIDER_WIDTH;
}
@@ -3601,22 +3859,11 @@ static void achannel_nlatrack_solo_widget_cb(bContext *C, void *adt_poin, void *
WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_RENAME, NULL);
}
-/* callback for rename widgets - clear rename-in-progress */
-static void achannel_setting_rename_done_cb(bContext *C, void *ads_poin, void *UNUSED(arg2))
-{
- bDopeSheet *ads = (bDopeSheet *)ads_poin;
-
- /* reset rename index so that edit box disappears now that editing is done */
- ads->renameIndex = 0;
-
- /* send notifiers */
- WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_RENAME, NULL);
-}
-
/* callback for widget sliders - insert keyframes */
static void achannel_setting_slider_cb(bContext *C, void *id_poin, void *fcu_poin)
{
ID *id = (ID *)id_poin;
+ AnimData *adt = BKE_animdata_from_id(id);
FCurve *fcu = (FCurve *)fcu_poin;
ReportList *reports = CTX_wm_reports(C);
@@ -3627,9 +3874,8 @@ static void achannel_setting_slider_cb(bContext *C, void *id_poin, void *fcu_poi
bool done = false;
float cfra;
- /* get current frame */
- // NOTE: this will do for now...
- cfra = (float)CFRA;
+ /* get current frame and apply NLA-mapping to it (if applicable) */
+ cfra = BKE_nla_tweakedit_remap(adt, (float)CFRA, NLATIME_CONVERT_UNMAP);
/* get flags for keyframing */
flag = ANIM_get_keyframing_flags(scene, 1);
@@ -3666,9 +3912,8 @@ static void achannel_setting_slider_shapekey_cb(bContext *C, void *key_poin, voi
bool done = false;
float cfra;
- /* get current frame */
- // NOTE: this will do for now...
- cfra = (float)CFRA;
+ /* get current frame and apply NLA-mapping to it (if applicable) */
+ cfra = BKE_nla_tweakedit_remap(key->adt, (float)CFRA, NLATIME_CONVERT_UNMAP);
/* get flags for keyframing */
flag = ANIM_get_keyframing_flags(scene, 1);
@@ -3699,12 +3944,51 @@ static void achannel_setting_slider_shapekey_cb(bContext *C, void *key_poin, voi
MEM_freeN(rna_path);
}
+/* callback for NLA Control Curve widget sliders - insert keyframes */
+static void achannel_setting_slider_nla_curve_cb(bContext *C, void *UNUSED(id_poin), void *fcu_poin)
+{
+ /* ID *id = (ID *)id_poin; */
+ FCurve *fcu = (FCurve *)fcu_poin;
+
+ PointerRNA ptr;
+ PropertyRNA *prop;
+ int index;
+
+ ReportList *reports = CTX_wm_reports(C);
+ Scene *scene = CTX_data_scene(C);
+ short flag = 0;
+ bool done = false;
+ float cfra;
+
+ /* get current frame - *no* NLA mapping should be done */
+ cfra = (float)CFRA;
+
+ /* get flags for keyframing */
+ flag = ANIM_get_keyframing_flags(scene, 1);
+
+ /* get pointer and property from the slider - this should all match up with the NlaStrip required... */
+ UI_context_active_but_prop_get(C, &ptr, &prop, &index);
+
+ if (fcu && prop) {
+ /* set the special 'replace' flag if on a keyframe */
+ if (fcurve_frame_has_keyframe(fcu, cfra, 0))
+ flag |= INSERTKEY_REPLACE;
+
+ /* insert a keyframe for this F-Curve */
+ done = insert_keyframe_direct(reports, ptr, prop, fcu, cfra, flag);
+
+ if (done)
+ WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL);
+ }
+}
+
/* Draw a widget for some setting */
-static void draw_setting_widget(bAnimContext *ac, bAnimListElem *ale, bAnimChannelType *acf,
+static void draw_setting_widget(bAnimContext *ac, bAnimListElem *ale, const bAnimChannelType *acf,
uiBlock *block, int xpos, int ypos, int setting)
{
short ptrsize, butType;
bool negflag;
+ bool usetoggle = true;
int flag, icon;
void *ptr;
const char *tooltip;
@@ -3721,12 +4005,18 @@ static void draw_setting_widget(bAnimContext *ac, bAnimListElem *ale, bAnimChann
//icon = ((enabled) ? ICON_VISIBLE_IPO_ON : ICON_VISIBLE_IPO_OFF);
icon = ICON_VISIBLE_IPO_OFF;
- if (ale->type == ANIMTYPE_FCURVE)
+ if (ELEM(ale->type, ANIMTYPE_FCURVE, ANIMTYPE_NLACURVE))
tooltip = TIP_("F-Curve is visible in Graph Editor for editing");
else
tooltip = TIP_("Channels are visible in Graph Editor for editing");
break;
-
+
+ case ACHANNEL_SETTING_MOD_OFF: /* modifiers disabled */
+ icon = ICON_MODIFIER;
+ usetoggle = false;
+ tooltip = TIP_("F-Curve modifiers are disabled");
+ break;
+
case ACHANNEL_SETTING_EXPAND: /* expanded triangle */
//icon = ((enabled) ? ICON_TRIA_DOWN : ICON_TRIA_RIGHT);
icon = ICON_TRIA_RIGHT;
@@ -3756,7 +4046,7 @@ static void draw_setting_widget(bAnimContext *ac, bAnimListElem *ale, bAnimChann
//icon = ((enabled) ? ICON_MUTE_IPO_ON : ICON_MUTE_IPO_OFF);
icon = ICON_MUTE_IPO_OFF;
- if (ale->type == ANIMTYPE_FCURVE) {
+ if (ELEM(ale->type, ANIMTYPE_FCURVE, ANIMTYPE_NLACURVE)) {
tooltip = TIP_("Does F-Curve contribute to result");
}
else if ((ac) && (ac->spacetype == SPACE_NLA) && (ale->type != ANIMTYPE_NLATRACK)) {
@@ -3787,11 +4077,18 @@ static void draw_setting_widget(bAnimContext *ac, bAnimListElem *ale, bAnimChann
}
/* type of button */
- if (negflag)
- butType = ICONTOGN;
- else
- butType = ICONTOG;
-
+ if (usetoggle) {
+ if (negflag)
+ butType = UI_BTYPE_ICON_TOGGLE_N;
+ else
+ butType = UI_BTYPE_ICON_TOGGLE;
+ }
+ else {
+ if (negflag)
+ butType = UI_BTYPE_TOGGLE_N;
+ else
+ butType = UI_BTYPE_TOGGLE;
+ }
/* draw button for setting */
if (ptr && flag) {
switch (ptrsize) {
@@ -3819,18 +4116,19 @@ static void draw_setting_widget(bAnimContext *ac, bAnimListElem *ale, bAnimChann
case ACHANNEL_SETTING_PROTECT: /* General - protection flags */
case ACHANNEL_SETTING_MUTE: /* General - muting flags */
case ACHANNEL_SETTING_PINNED: /* NLA Actions - 'map/nomap' */
- uiButSetNFunc(but, achannel_setting_flush_widget_cb, MEM_dupallocN(ale), SET_INT_IN_POINTER(setting));
+ case ACHANNEL_SETTING_MOD_OFF:
+ UI_but_funcN_set(but, achannel_setting_flush_widget_cb, MEM_dupallocN(ale), SET_INT_IN_POINTER(setting));
break;
/* settings needing special attention */
case ACHANNEL_SETTING_SOLO: /* NLA Tracks - Solo toggle */
- uiButSetFunc(but, achannel_nlatrack_solo_widget_cb, ale->adt, ale->data);
+ UI_but_func_set(but, achannel_nlatrack_solo_widget_cb, ale->adt, ale->data);
break;
/* no flushing */
case ACHANNEL_SETTING_EXPAND: /* expanding - cannot flush, otherwise all would open/close at once */
default:
- uiButSetFunc(but, achannel_setting_widget_cb, NULL, NULL);
+ UI_but_func_set(but, achannel_setting_widget_cb, NULL, NULL);
break;
}
}
@@ -3838,12 +4136,13 @@ static void draw_setting_widget(bAnimContext *ac, bAnimListElem *ale, bAnimChann
}
/* Draw UI widgets the given channel */
-void ANIM_channel_draw_widgets(bContext *C, bAnimContext *ac, bAnimListElem *ale, uiBlock *block, float yminc, float ymaxc, size_t channel_index)
+void ANIM_channel_draw_widgets(const bContext *C, bAnimContext *ac, bAnimListElem *ale, uiBlock *block, float yminc, float ymaxc, size_t channel_index)
{
- bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale);
+ const bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale);
View2D *v2d = &ac->ar->v2d;
float y, ymid /*, ytext*/;
short offset;
+ const bool is_being_renamed = achannel_is_being_renamed(ac, acf, channel_index);
/* sanity checks - don't draw anything */
if (ELEM(NULL, acf, ale, block))
@@ -3861,7 +4160,7 @@ void ANIM_channel_draw_widgets(bContext *C, bAnimContext *ac, bAnimListElem *ale
ymid = y - 0.5f * ICON_WIDTH;
/* no button backdrop behind icons */
- uiBlockSetEmboss(block, UI_EMBOSSN);
+ UI_block_emboss_set(block, UI_EMBOSS_NONE);
/* step 1) draw expand widget ....................................... */
if (acf->has_setting(ac, ale, ACHANNEL_SETTING_EXPAND)) {
@@ -3878,6 +4177,7 @@ void ANIM_channel_draw_widgets(bContext *C, bAnimContext *ac, bAnimListElem *ale
/* step 3) draw special toggles .................................
* - in Graph Editor, checkboxes for visibility in curves area
* - in NLA Editor, glowing dots for solo/not solo...
+ * - in Grease Pencil mode, color swatches for layer color
*/
if (ac->sl) {
if ((ac->spacetype == SPACE_IPO) && acf->has_setting(ac, ale, ACHANNEL_SETTING_VISIBLE)) {
@@ -3890,33 +4190,63 @@ void ANIM_channel_draw_widgets(bContext *C, bAnimContext *ac, bAnimListElem *ale
draw_setting_widget(ac, ale, acf, block, offset, ymid, ACHANNEL_SETTING_SOLO);
offset += ICON_WIDTH;
}
+ else if (ale->type == ANIMTYPE_GPLAYER) {
+ /* color swatch for layer color */
+ bGPDlayer *gpl = (bGPDlayer *)ale->data;
+ PointerRNA ptr;
+ float w = ICON_WIDTH / 2.0f;
+
+ RNA_pointer_create(ale->id, &RNA_GPencilLayer, ale->data, &ptr);
+
+ UI_block_align_begin(block);
+
+ UI_block_emboss_set(block, RNA_boolean_get(&ptr, "is_stroke_visible") ? UI_EMBOSS : UI_EMBOSS_NONE);
+ uiDefButR(block, UI_BTYPE_COLOR, 1, "", offset, yminc, w, ICON_WIDTH,
+ &ptr, "color", -1,
+ 0, 0, 0, 0, gpl->info);
+
+ UI_block_emboss_set(block, RNA_boolean_get(&ptr, "is_fill_visible") ? UI_EMBOSS : UI_EMBOSS_NONE);
+ uiDefButR(block, UI_BTYPE_COLOR, 1, "", offset + w, yminc, w, ICON_WIDTH,
+ &ptr, "fill_color", -1,
+ 0, 0, 0, 0, gpl->info);
+
+ UI_block_emboss_set(block, UI_EMBOSS_NONE);
+ UI_block_align_end(block);
+
+ offset += ICON_WIDTH;
+ }
}
/* step 4) draw text - check if renaming widget is in use... */
- if (acf->name_prop && ac->ads) {
- float channel_height = ymaxc - yminc;
+ if (is_being_renamed) {
+ PointerRNA ptr = {{NULL}};
+ PropertyRNA *prop = NULL;
- /* if rename index matches, add widget for this */
- if (ac->ads->renameIndex == channel_index + 1) {
- PointerRNA ptr = {{NULL}};
- PropertyRNA *prop = NULL;
+ /* draw renaming widget if we can get RNA pointer for it
+ * NOTE: property may only be available in some cases, even if we have
+ * a callback available (e.g. broken F-Curve rename)
+ */
+ if (acf->name_prop(ale, &ptr, &prop)) {
+ const short margin_x = 3 * iroundf(UI_DPI_FAC);
+ const short channel_height = iroundf(ymaxc - yminc);
+ const short width = ac->ar->winx - offset - (margin_x * 2);
+ uiBut *but;
- /* draw renaming widget if we can get RNA pointer for it
- * NOTE: property may only be available in some cases, even if we have
- * a callback available (e.g. broken F-Curve rename)
- */
- if (acf->name_prop(ale, &ptr, &prop)) {
- uiBut *but;
-
- uiBlockSetEmboss(block, UI_EMBOSS);
-
- but = uiDefButR(block, TEX, 1, "", offset + 3, yminc, RENAME_TEXT_WIDTH, channel_height,
- &ptr, RNA_property_identifier(prop), -1, 0, 0, -1, -1, NULL);
- uiButSetFunc(but, achannel_setting_rename_done_cb, ac->ads, NULL);
- uiButActiveOnly(C, ac->ar, block, but);
+ UI_block_emboss_set(block, UI_EMBOSS);
+
+ but = uiDefButR(block, UI_BTYPE_TEXT, 1, "", offset + margin_x, yminc,
+ MAX2(width, RENAME_TEXT_MIN_WIDTH), channel_height,
+ &ptr, RNA_property_identifier(prop), -1, 0, 0, -1, -1, NULL);
+
+ /* copy what outliner does here, see outliner_buttons */
+ if (UI_but_active_only(C, ac->ar, block, but) == false) {
+ ac->ads->renameIndex = 0;
- uiBlockSetEmboss(block, UI_EMBOSSN);
+ /* send notifiers */
+ WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_RENAME, NULL);
}
+
+ UI_block_emboss_set(block, UI_EMBOSS_NONE);
}
}
@@ -3925,7 +4255,7 @@ void ANIM_channel_draw_widgets(bContext *C, bAnimContext *ac, bAnimListElem *ale
offset = 0;
// TODO: when drawing sliders, make those draw instead of these toggles if not enough space
- if (v2d) {
+ if (v2d && !is_being_renamed) {
short draw_sliders = 0;
/* check if we need to show the sliders */
@@ -3959,6 +4289,12 @@ void ANIM_channel_draw_widgets(bContext *C, bAnimContext *ac, bAnimListElem *ale
draw_setting_widget(ac, ale, acf, block, (int)v2d->cur.xmax - offset, ymid, ACHANNEL_SETTING_MUTE);
}
+ /* modifiers disable */
+ if (acf->has_setting(ac, ale, ACHANNEL_SETTING_MOD_OFF)) {
+ offset += ICON_WIDTH * 1.2f; /* hack: extra spacing, to avoid touching the mute toggle */
+ draw_setting_widget(ac, ale, acf, block, (int)v2d->cur.xmax - offset, ymid, ACHANNEL_SETTING_MOD_OFF);
+ }
+
/* ----------- */
/* pinned... */
@@ -3972,16 +4308,16 @@ void ANIM_channel_draw_widgets(bContext *C, bAnimContext *ac, bAnimListElem *ale
uiBut *but;
PointerRNA *opptr_b;
- uiBlockSetEmboss(block, UI_EMBOSS);
+ UI_block_emboss_set(block, UI_EMBOSS);
offset += UI_UNIT_X;
- but = uiDefIconButO(block, BUT, "NLA_OT_action_pushdown", WM_OP_INVOKE_DEFAULT, ICON_NLA_PUSHDOWN,
+ but = uiDefIconButO(block, UI_BTYPE_BUT, "NLA_OT_action_pushdown", WM_OP_INVOKE_DEFAULT, ICON_NLA_PUSHDOWN,
(int)v2d->cur.xmax - offset, ymid, UI_UNIT_X, UI_UNIT_X, NULL);
- opptr_b = uiButGetOperatorPtrRNA(but);
+ opptr_b = UI_but_operator_ptr_get(but);
RNA_int_set(opptr_b, "channel_index", channel_index);
- uiBlockSetEmboss(block, UI_EMBOSSN);
+ UI_block_emboss_set(block, UI_EMBOSS_NONE);
}
}
@@ -3993,15 +4329,36 @@ void ANIM_channel_draw_widgets(bContext *C, bAnimContext *ac, bAnimListElem *ale
* and wouldn't be able to auto-keyframe...
* - slider should start before the toggles (if they're visible) to keep a clean line down the side
*/
- if ((draw_sliders) && ELEM(ale->type, ANIMTYPE_FCURVE, ANIMTYPE_SHAPEKEY)) {
+ if ((draw_sliders) && ELEM(ale->type, ANIMTYPE_FCURVE, ANIMTYPE_NLACURVE, ANIMTYPE_SHAPEKEY)) {
/* adjust offset */
// TODO: make slider width dynamic, so that they can be easier to use when the view is wide enough
offset += SLIDER_WIDTH;
/* need backdrop behind sliders... */
- uiBlockSetEmboss(block, UI_EMBOSS);
+ UI_block_emboss_set(block, UI_EMBOSS);
- if (ale->id) { /* Slider using RNA Access -------------------- */
+ if (ale->owner) { /* Slider using custom RNA Access ---------- */
+ if (ale->type == ANIMTYPE_NLACURVE) {
+ NlaStrip *strip = (NlaStrip *)ale->owner;
+ FCurve *fcu = (FCurve *)ale->data;
+ PointerRNA ptr;
+ PropertyRNA *prop;
+
+ /* create RNA pointers */
+ RNA_pointer_create(ale->id, &RNA_NlaStrip, strip, &ptr);
+ prop = RNA_struct_find_property(&ptr, fcu->rna_path);
+
+ /* create property slider */
+ if (prop) {
+ uiBut *but;
+
+ /* create the slider button, and assign relevant callback to ensure keyframes are inserted... */
+ but = uiDefAutoButR(block, &ptr, prop, fcu->array_index, "", ICON_NONE, (int)v2d->cur.xmax - offset, ymid, SLIDER_WIDTH, (int)ymaxc - yminc);
+ UI_but_func_set(but, achannel_setting_slider_nla_curve_cb, ale->id, ale->data);
+ }
+ }
+ }
+ else if (ale->id) { /* Slider using RNA Access --------------- */
PointerRNA id_ptr, ptr;
PropertyRNA *prop;
char *rna_path = NULL;
@@ -4037,9 +4394,9 @@ void ANIM_channel_draw_widgets(bContext *C, bAnimContext *ac, bAnimListElem *ale
/* assign keyframing function according to slider type */
if (ale->type == ANIMTYPE_SHAPEKEY)
- uiButSetFunc(but, achannel_setting_slider_shapekey_cb, ale->id, ale->data);
+ UI_but_func_set(but, achannel_setting_slider_shapekey_cb, ale->id, ale->data);
else
- uiButSetFunc(but, achannel_setting_slider_cb, ale->id, ale->data);
+ UI_but_func_set(but, achannel_setting_slider_cb, ale->id, ale->data);
}
/* free the path if necessary */
diff --git a/source/blender/editors/animation/anim_channels_edit.c b/source/blender/editors/animation/anim_channels_edit.c
index b6ab0407711..8822c8511de 100644
--- a/source/blender/editors/animation/anim_channels_edit.c
+++ b/source/blender/editors/animation/anim_channels_edit.c
@@ -34,6 +34,7 @@
#include "MEM_guardedalloc.h"
+#include "BKE_depsgraph.h"
#include "BLI_blenlib.h"
#include "BLI_utildefines.h"
#include "BLI_listbase.h"
@@ -101,6 +102,7 @@ void ANIM_set_active_channel(bAnimContext *ac, void *data, eAnimCont_Types datat
break;
}
case ANIMTYPE_FCURVE:
+ case ANIMTYPE_NLACURVE:
{
FCurve *fcu = (FCurve *)ale->data;
@@ -129,6 +131,7 @@ void ANIM_set_active_channel(bAnimContext *ac, void *data, eAnimCont_Types datat
case ANIMTYPE_DSLAT:
case ANIMTYPE_DSLINESTYLE:
case ANIMTYPE_DSSPK:
+ case ANIMTYPE_DSGPENCIL:
{
/* need to verify that this data is valid for now */
if (ale->adt) {
@@ -136,6 +139,13 @@ void ANIM_set_active_channel(bAnimContext *ac, void *data, eAnimCont_Types datat
}
break;
}
+ case ANIMTYPE_GPLAYER:
+ {
+ bGPDlayer *gpl = (bGPDlayer *)ale->data;
+
+ ACHANNEL_SET_FLAG(gpl, ACHANNEL_SETFLAG_CLEAR, GP_LAYER_ACTIVE);
+ break;
+ }
}
}
@@ -149,6 +159,7 @@ void ANIM_set_active_channel(bAnimContext *ac, void *data, eAnimCont_Types datat
break;
}
case ANIMTYPE_FCURVE:
+ case ANIMTYPE_NLACURVE:
{
FCurve *fcu = (FCurve *)channel_data;
fcu->flag |= FCURVE_ACTIVE;
@@ -176,6 +187,7 @@ void ANIM_set_active_channel(bAnimContext *ac, void *data, eAnimCont_Types datat
case ANIMTYPE_DSSPK:
case ANIMTYPE_DSNTREE:
case ANIMTYPE_DSTEX:
+ case ANIMTYPE_DSGPENCIL:
{
/* need to verify that this data is valid for now */
if (ale && ale->adt) {
@@ -184,8 +196,14 @@ void ANIM_set_active_channel(bAnimContext *ac, void *data, eAnimCont_Types datat
break;
}
- /* unhandled currently, but may be interesting */
case ANIMTYPE_GPLAYER:
+ {
+ bGPDlayer *gpl = (bGPDlayer *)channel_data;
+ gpl->flag |= GP_LAYER_ACTIVE;
+ break;
+ }
+
+ /* unhandled currently, but may be interesting */
case ANIMTYPE_MASKLAYER:
case ANIMTYPE_SHAPEKEY:
case ANIMTYPE_NLAACTION:
@@ -240,6 +258,7 @@ void ANIM_deselect_anim_channels(bAnimContext *ac, void *data, eAnimCont_Types d
sel = ACHANNEL_SETFLAG_CLEAR;
break;
case ANIMTYPE_FCURVE:
+ case ANIMTYPE_NLACURVE:
if (ale->flag & FCURVE_SELECTED)
sel = ACHANNEL_SETFLAG_CLEAR;
break;
@@ -268,6 +287,7 @@ void ANIM_deselect_anim_channels(bAnimContext *ac, void *data, eAnimCont_Types d
case ANIMTYPE_DSLAT:
case ANIMTYPE_DSLINESTYLE:
case ANIMTYPE_DSSPK:
+ case ANIMTYPE_DSGPENCIL:
{
if ((ale->adt) && (ale->adt->flag & ADT_UI_SELECTED))
sel = ACHANNEL_SETFLAG_CLEAR;
@@ -323,6 +343,7 @@ void ANIM_deselect_anim_channels(bAnimContext *ac, void *data, eAnimCont_Types d
break;
}
case ANIMTYPE_FCURVE:
+ case ANIMTYPE_NLACURVE:
{
FCurve *fcu = (FCurve *)ale->data;
@@ -361,6 +382,7 @@ void ANIM_deselect_anim_channels(bAnimContext *ac, void *data, eAnimCont_Types d
case ANIMTYPE_DSLAT:
case ANIMTYPE_DSLINESTYLE:
case ANIMTYPE_DSSPK:
+ case ANIMTYPE_DSGPENCIL:
{
/* need to verify that this data is valid for now */
if (ale->adt) {
@@ -427,7 +449,7 @@ void ANIM_flush_setting_anim_channels(bAnimContext *ac, ListBase *anim_data, bAn
return;
}
else {
- bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale_setting);
+ const bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale_setting);
if (acf == NULL) {
printf("ERROR: no channel info for the changed channel\n");
@@ -456,7 +478,7 @@ void ANIM_flush_setting_anim_channels(bAnimContext *ac, ListBase *anim_data, bAn
{
/* go backwards in the list, until the highest-ranking element (by indention has been covered) */
for (ale = match->prev; ale; ale = ale->prev) {
- bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale);
+ const bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale);
int level;
/* if no channel info was found, skip, since this type might not have any useful info */
@@ -500,7 +522,7 @@ void ANIM_flush_setting_anim_channels(bAnimContext *ac, ListBase *anim_data, bAn
{
/* go forwards in the list, until the lowest-ranking element (by indention has been covered) */
for (ale = match->next; ale; ale = ale->next) {
- bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale);
+ const bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale);
int level;
/* if no channel info was found, skip, since this type might not have any useful info */
@@ -830,6 +852,7 @@ static void rearrange_animchannel_add_to_islands(ListBase *islands, ListBase *sr
break;
}
case ANIMTYPE_FCURVE:
+ case ANIMTYPE_NLACURVE:
{
FCurve *fcu = (FCurve *)channel;
@@ -843,8 +866,15 @@ static void rearrange_animchannel_add_to_islands(ListBase *islands, ListBase *sr
is_sel = SEL_NLT(nlt);
break;
}
+ case ANIMTYPE_GPLAYER:
+ {
+ bGPDlayer *gpl = (bGPDlayer *)channel;
+
+ is_sel = SEL_GPL(gpl);
+ break;
+ }
default:
- printf("rearrange_animchannel_add_to_islands(): don't know how to handle channels of type %d\n", type);
+ printf("rearrange_animchannel_add_to_islands(): don't know how to handle channels of type %u\n", type);
return;
}
@@ -1167,6 +1197,81 @@ static void rearrange_action_channels(bAnimContext *ac, bAction *act, eRearrange
/* ------------------- */
+static void rearrange_nla_control_channels(bAnimContext *ac, AnimData *adt, eRearrangeAnimChan_Mode mode)
+{
+ ListBase anim_data_visible = {NULL, NULL};
+
+ NlaTrack *nlt;
+ NlaStrip *strip;
+
+ /* get rearranging function */
+ AnimChanRearrangeFp rearrange_func = rearrange_get_mode_func(mode);
+
+ if (rearrange_func == NULL)
+ return;
+
+ /* skip if these curves aren't being shown */
+ if (adt->flag & ADT_NLA_SKEYS_COLLAPSED)
+ return;
+
+ /* Filter visible data. */
+ rearrange_animchannels_filter_visible(&anim_data_visible, ac, ANIMTYPE_NLACURVE);
+
+ /* we cannot rearrange between strips, but within each strip, we can rearrange those curves */
+ for (nlt = adt->nla_tracks.first; nlt; nlt = nlt->next) {
+ for (strip = nlt->strips.first; strip; strip = strip->next) {
+ rearrange_animchannel_islands(&strip->fcurves, rearrange_func, mode, ANIMTYPE_NLACURVE,
+ &anim_data_visible);
+ }
+ }
+
+ /* free temp data */
+ BLI_freelistN(&anim_data_visible);
+}
+
+/* ------------------- */
+
+static void rearrange_gpencil_channels(bAnimContext *ac, eRearrangeAnimChan_Mode mode)
+{
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+
+ /* get rearranging function */
+ AnimChanRearrangeFp rearrange_func = rearrange_get_mode_func(mode);
+
+ if (rearrange_func == NULL)
+ return;
+
+ /* get Grease Pencil datablocks */
+ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_ANIMDATA);
+ ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ ListBase anim_data_visible = {NULL, NULL};
+ bGPdata *gpd = ale->data;
+
+ /* only consider layers if this datablock is open */
+ BLI_assert(ale->type == ANIMTYPE_GPDATABLOCK);
+ if ((gpd->flag & GP_DATA_EXPAND) == 0)
+ continue;
+
+ /* Filter visible data. */
+ rearrange_animchannels_filter_visible(&anim_data_visible, ac, ANIMTYPE_GPLAYER);
+
+ /* rearrange datablock's layers */
+ rearrange_animchannel_islands(&gpd->layers, rearrange_func, mode, ANIMTYPE_GPLAYER, &anim_data_visible);
+
+ /* free visible layers data */
+ BLI_freelistN(&anim_data_visible);
+ }
+
+ /* free GPD channel data */
+ ANIM_animdata_freelist(&anim_data);
+}
+
+/* ------------------- */
+
static int animchannels_rearrange_exec(bContext *C, wmOperator *op)
{
bAnimContext ac;
@@ -1182,7 +1287,7 @@ static int animchannels_rearrange_exec(bContext *C, wmOperator *op)
/* method to move channels depends on the editor */
if (ac.datatype == ANIMCONT_GPENCIL) {
/* Grease Pencil channels */
- printf("Grease Pencil not supported for moving yet\n");
+ rearrange_gpencil_channels(&ac, mode);
}
else if (ac.datatype == ANIMCONT_MASK) {
/* Grease Pencil channels */
@@ -1213,13 +1318,29 @@ static int animchannels_rearrange_exec(bContext *C, wmOperator *op)
rearrange_driver_channels(&ac, adt, mode);
break;
+ case ANIMCONT_ACTION: /* Single Action only... */
case ANIMCONT_SHAPEKEY: // DOUBLE CHECK ME...
- default: /* some collection of actions */
+ {
if (adt->action)
rearrange_action_channels(&ac, adt->action, mode);
else if (G.debug & G_DEBUG)
printf("Animdata has no action\n");
break;
+ }
+
+ default: /* DopeSheet/Graph Editor - Some Actions + NLA Control Curves */
+ {
+ /* NLA Control Curves */
+ if (adt->nla_tracks.first)
+ rearrange_nla_control_channels(&ac, adt, mode);
+
+ /* Action */
+ if (adt->action)
+ rearrange_action_channels(&ac, adt->action, mode);
+ else if (G.debug & G_DEBUG)
+ printf("Animdata has no action\n");
+ break;
+ }
}
}
@@ -1275,9 +1396,9 @@ static int animchannels_grouping_poll(bContext *C)
/* dopesheet and action only - all others are for other datatypes or have no groups */
if (ELEM(saction->mode, SACTCONT_ACTION, SACTCONT_DOPESHEET) == 0)
return 0;
- }
+
break;
-
+ }
case SPACE_IPO:
{
SpaceIpo *sipo = (SpaceIpo *)sl;
@@ -1285,9 +1406,9 @@ static int animchannels_grouping_poll(bContext *C)
/* drivers can't have groups... */
if (sipo->mode != SIPO_MODE_ANIMATION)
return 0;
- }
+
break;
-
+ }
/* unsupported... */
default:
return 0;
@@ -1537,6 +1658,27 @@ static int animchannels_delete_exec(bContext *C, wmOperator *UNUSED(op))
ANIM_fcurve_delete_from_animdata(&ac, adt, fcu);
break;
}
+ case ANIMTYPE_NLACURVE:
+ {
+ /* NLA Control Curve - Deleting it should disable the corresponding setting... */
+ NlaStrip *strip = (NlaStrip *)ale->owner;
+ FCurve *fcu = (FCurve *)ale->data;
+
+ if (STREQ(fcu->rna_path, "strip_time")) {
+ strip->flag &= ~NLASTRIP_FLAG_USR_TIME;
+ }
+ else if (STREQ(fcu->rna_path, "influence")) {
+ strip->flag &= ~NLASTRIP_FLAG_USR_INFLUENCE;
+ }
+ else {
+ printf("ERROR: Trying to delete NLA Control Curve for unknown property '%s'\n", fcu->rna_path);
+ }
+
+ /* unlink and free the F-Curve */
+ BLI_remlink(&strip->fcurves, fcu);
+ free_fcurve(fcu);
+ break;
+ }
case ANIMTYPE_GPLAYER:
{
/* Grease Pencil layer */
@@ -1566,7 +1708,8 @@ static int animchannels_delete_exec(bContext *C, wmOperator *UNUSED(op))
/* send notifier that things have changed */
WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL);
-
+ DAG_relations_tag_update(CTX_data_main(C));
+
return OPERATOR_FINISHED;
}
@@ -1585,175 +1728,6 @@ static void ANIM_OT_channels_delete(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-/* ******************** Set Channel Visibility Operator *********************** */
-/* NOTE: this operator is only valid in the Graph Editor channels region */
-
-static int animchannels_visibility_set_exec(bContext *C, wmOperator *UNUSED(op))
-{
- bAnimContext ac;
- ListBase anim_data = {NULL, NULL};
- ListBase all_data = {NULL, NULL};
- bAnimListElem *ale;
- int filter;
-
- /* get editor data */
- if (ANIM_animdata_get_context(C, &ac) == 0)
- return OPERATOR_CANCELLED;
-
- /* get list of all channels that selection may need to be flushed to
- * - hierarchy mustn't affect what we have access to here...
- */
- filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_CHANNELS | ANIMFILTER_NODUPLIS);
- ANIM_animdata_filter(&ac, &all_data, filter, ac.data, ac.datatype);
-
- /* hide all channels not selected
- * - hierarchy matters if we're doing this from the channels region
- * since we only want to apply this to channels we can "see",
- * and have these affect their relatives
- * - but for Graph Editor, this gets used also from main region
- * where hierarchy doesn't apply, as for [#21276]
- */
- if ((ac.spacetype == SPACE_IPO) && (ac.regiontype != RGN_TYPE_CHANNELS)) {
- /* graph editor (case 2) */
- filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_UNSEL | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_NODUPLIS);
- }
- else {
- /* standard case */
- filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_UNSEL | ANIMFILTER_NODUPLIS);
- }
- ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
-
- for (ale = anim_data.first; ale; ale = ale->next) {
- /* clear setting first */
- ANIM_channel_setting_set(&ac, ale, ACHANNEL_SETTING_VISIBLE, ACHANNEL_SETFLAG_CLEAR);
-
- /* now also flush selection status as appropriate
- * NOTE: in some cases, this may result in repeat flushing being performed
- */
- ANIM_flush_setting_anim_channels(&ac, &all_data, ale, ACHANNEL_SETTING_VISIBLE, 0);
- }
-
- ANIM_animdata_freelist(&anim_data);
-
- /* make all the selected channels visible */
- filter = (ANIMFILTER_SEL | ANIMFILTER_NODUPLIS);
- ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
-
- for (ale = anim_data.first; ale; ale = ale->next) {
- /* hack: skip object channels for now, since flushing those will always flush everything, but they are always included */
- /* TODO: find out why this is the case, and fix that */
- if (ale->type == ANIMTYPE_OBJECT)
- continue;
-
- /* enable the setting */
- ANIM_channel_setting_set(&ac, ale, ACHANNEL_SETTING_VISIBLE, ACHANNEL_SETFLAG_ADD);
-
- /* now, also flush selection status up/down as appropriate */
- ANIM_flush_setting_anim_channels(&ac, &all_data, ale, ACHANNEL_SETTING_VISIBLE, 1);
- }
-
- ANIM_animdata_freelist(&anim_data);
- BLI_freelistN(&all_data);
-
-
- /* send notifier that things have changed */
- WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL);
-
- return OPERATOR_FINISHED;
-}
-
-static void ANIM_OT_channels_visibility_set(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Set Visibility";
- ot->idname = "ANIM_OT_channels_visibility_set";
- ot->description = "Make only the selected animation channels visible in the Graph Editor";
-
- /* api callbacks */
- ot->exec = animchannels_visibility_set_exec;
- ot->poll = ED_operator_graphedit_active;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-}
-
-
-/* ******************** Toggle Channel Visibility Operator *********************** */
-/* NOTE: this operator is only valid in the Graph Editor channels region */
-
-static int animchannels_visibility_toggle_exec(bContext *C, wmOperator *UNUSED(op))
-{
- bAnimContext ac;
- ListBase anim_data = {NULL, NULL};
- ListBase all_data = {NULL, NULL};
- bAnimListElem *ale;
- int filter;
- short vis = ACHANNEL_SETFLAG_ADD;
-
- /* get editor data */
- if (ANIM_animdata_get_context(C, &ac) == 0)
- return OPERATOR_CANCELLED;
-
- /* get list of all channels that selection may need to be flushed to
- * - hierarchy mustn't affect what we have access to here...
- */
- filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_CHANNELS | ANIMFILTER_NODUPLIS);
- ANIM_animdata_filter(&ac, &all_data, filter, ac.data, ac.datatype);
-
- /* filter data
- * - restrict this to only applying on settings we can get to in the list
- */
- filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_SEL | ANIMFILTER_NODUPLIS);
- ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
-
- /* See if we should be making showing all selected or hiding */
- for (ale = anim_data.first; ale; ale = ale->next) {
- /* set the setting in the appropriate way (if available) */
- if (ANIM_channel_setting_get(&ac, ale, ACHANNEL_SETTING_VISIBLE)) {
- vis = ACHANNEL_SETFLAG_CLEAR;
- break;
- }
- }
-
- /* Now set the flags */
- for (ale = anim_data.first; ale; ale = ale->next) {
- /* hack: skip object channels for now, since flushing those will always flush everything, but they are always included */
- /* TODO: find out why this is the case, and fix that */
- if (ale->type == ANIMTYPE_OBJECT)
- continue;
-
- /* change the setting */
- ANIM_channel_setting_set(&ac, ale, ACHANNEL_SETTING_VISIBLE, vis);
-
- /* now, also flush selection status up/down as appropriate */
- ANIM_flush_setting_anim_channels(&ac, &all_data, ale, ACHANNEL_SETTING_VISIBLE, (vis == ACHANNEL_SETFLAG_ADD));
- }
-
- /* cleanup */
- ANIM_animdata_freelist(&anim_data);
- BLI_freelistN(&all_data);
-
- /* send notifier that things have changed */
- WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL);
-
- return OPERATOR_FINISHED;
-}
-
-static void ANIM_OT_channels_visibility_toggle(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Toggle Visibility";
- ot->idname = "ANIM_OT_channels_visibility_toggle";
- ot->description = "Toggle visibility in Graph Editor of all selected animation channels";
-
- /* api callbacks */
- ot->exec = animchannels_visibility_toggle_exec;
- ot->poll = ED_operator_graphedit_active;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-}
-
/* ********************** Set Flags Operator *********************** */
/* defines for setting animation-channel flags */
@@ -2145,7 +2119,7 @@ static int animchannels_clean_empty_exec(bContext *C, wmOperator *UNUSED(op))
/* remove AnimData? */
if (action_empty && nla_empty && drivers_empty) {
- BKE_free_animdata(id);
+ BKE_animdata_free(id);
}
}
@@ -2334,7 +2308,7 @@ static int animchannels_deselectall_exec(bContext *C, wmOperator *op)
/* 'standard' behavior - check if selected, then apply relevant selection */
if (RNA_boolean_get(op->ptr, "invert"))
- ANIM_deselect_anim_channels(&ac, ac.data, ac.datatype, false, ACHANNEL_SETFLAG_TOGGLE);
+ ANIM_deselect_anim_channels(&ac, ac.data, ac.datatype, false, ACHANNEL_SETFLAG_INVERT);
else
ANIM_deselect_anim_channels(&ac, ac.data, ac.datatype, true, ACHANNEL_SETFLAG_ADD);
@@ -2524,12 +2498,13 @@ static void ANIM_OT_channels_select_border(wmOperatorType *ot)
/* ******************* Rename Operator ***************************** */
/* Allow renaming some channels by clicking on them */
-static void rename_anim_channels(bAnimContext *ac, int channel_index)
+static bool rename_anim_channels(bAnimContext *ac, int channel_index)
{
ListBase anim_data = {NULL, NULL};
- bAnimChannelType *acf;
+ const bAnimChannelType *acf;
bAnimListElem *ale;
int filter;
+ bool success = false;
/* get the channel that was clicked on */
/* filter channels */
@@ -2544,7 +2519,7 @@ static void rename_anim_channels(bAnimContext *ac, int channel_index)
printf("Error: animation channel (index = %d) not found in rename_anim_channels()\n", channel_index);
ANIM_animdata_freelist(&anim_data);
- return;
+ return false;
}
/* check that channel can be renamed */
@@ -2564,6 +2539,7 @@ static void rename_anim_channels(bAnimContext *ac, int channel_index)
*/
if (ac->ads) {
ac->ads->renameIndex = channel_index + 1;
+ success = true;
}
}
}
@@ -2571,22 +2547,18 @@ static void rename_anim_channels(bAnimContext *ac, int channel_index)
/* free temp data and tag for refresh */
ANIM_animdata_freelist(&anim_data);
ED_region_tag_redraw(ac->ar);
+ return success;
}
-static int animchannels_rename_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *event)
+static int animchannels_channel_get(bAnimContext *ac, const int mval[2])
{
- bAnimContext ac;
ARegion *ar;
View2D *v2d;
int channel_index;
float x, y;
- /* get editor data */
- if (ANIM_animdata_get_context(C, &ac) == 0)
- return OPERATOR_CANCELLED;
-
/* get useful pointers from animation context data */
- ar = ac.ar;
+ ar = ac->ar;
v2d = &ar->v2d;
/* figure out which channel user clicked in
@@ -2594,20 +2566,36 @@ static int animchannels_rename_invoke(bContext *C, wmOperator *UNUSED(op), const
* so that the tops of channels get caught ok. Since ACHANNEL_FIRST is really ACHANNEL_HEIGHT, we simply use
* ACHANNEL_HEIGHT_HALF.
*/
- UI_view2d_region_to_view(v2d, event->mval[0], event->mval[1], &x, &y);
+ UI_view2d_region_to_view(v2d, mval[0], mval[1], &x, &y);
- if (ac.datatype == ANIMCONT_NLA) {
- SpaceNla *snla = (SpaceNla *)ac.sl;
+ if (ac->datatype == ANIMCONT_NLA) {
+ SpaceNla *snla = (SpaceNla *)ac->sl;
UI_view2d_listview_view_to_cell(v2d, NLACHANNEL_NAMEWIDTH, NLACHANNEL_STEP(snla), 0, (float)NLACHANNEL_HEIGHT_HALF(snla), x, y, NULL, &channel_index);
}
else {
UI_view2d_listview_view_to_cell(v2d, ACHANNEL_NAMEWIDTH, ACHANNEL_STEP, 0, (float)ACHANNEL_HEIGHT_HALF, x, y, NULL, &channel_index);
}
-
+
+ return channel_index;
+}
+
+static int animchannels_rename_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *event)
+{
+ bAnimContext ac;
+ int channel_index;
+
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
+
+ channel_index = animchannels_channel_get(&ac, event->mval);
+
/* handle click */
- rename_anim_channels(&ac, channel_index);
-
- return OPERATOR_FINISHED;
+ if (rename_anim_channels(&ac, channel_index))
+ return OPERATOR_FINISHED;
+ else
+ /* allow event to be handled by selectall operator */
+ return OPERATOR_PASS_THROUGH;
}
static void ANIM_OT_channels_rename(wmOperatorType *ot)
@@ -2736,6 +2724,7 @@ static int mouse_anim_channels(bContext *C, bAnimContext *ac, int channel_index,
case ANIMTYPE_DSLAT:
case ANIMTYPE_DSLINESTYLE:
case ANIMTYPE_DSSPK:
+ case ANIMTYPE_DSGPENCIL:
{
/* sanity checking... */
if (ale->adt) {
@@ -2830,7 +2819,8 @@ static int mouse_anim_channels(bContext *C, bAnimContext *ac, int channel_index,
notifierFlags |= (ND_ANIMCHAN | NA_SELECTED);
break;
}
- case ANIMTYPE_FCURVE:
+ case ANIMTYPE_FCURVE:
+ case ANIMTYPE_NLACURVE:
{
FCurve *fcu = (FCurve *)ale->data;
@@ -2847,7 +2837,7 @@ static int mouse_anim_channels(bContext *C, bAnimContext *ac, int channel_index,
/* if F-Curve is selected now, make F-Curve the 'active' one in the visible list */
if (fcu->flag & FCURVE_SELECTED)
- ANIM_set_active_channel(ac, ac->data, ac->datatype, filter, fcu, ANIMTYPE_FCURVE);
+ ANIM_set_active_channel(ac, ac->data, ac->datatype, filter, fcu, ale->type);
notifierFlags |= (ND_ANIMCHAN | NA_SELECTED);
break;
@@ -2870,6 +2860,19 @@ static int mouse_anim_channels(bContext *C, bAnimContext *ac, int channel_index,
notifierFlags |= (ND_ANIMCHAN | NA_SELECTED);
break;
}
+ case ANIMTYPE_NLACONTROLS:
+ {
+ AnimData *adt = (AnimData *)ale->data;
+
+ /* toggle expand
+ * - Although the triangle widget already allows this, since there's nothing else that can be done here now,
+ * let's just use it for easier expand/collapse for now
+ */
+ adt->flag ^= ADT_NLA_SKEYS_COLLAPSED;
+
+ notifierFlags |= (ND_ANIMCHAN | NA_EDITED);
+ break;
+ }
case ANIMTYPE_GPDATABLOCK:
{
bGPdata *gpd = (bGPdata *)ale->data;
@@ -2897,7 +2900,13 @@ static int mouse_anim_channels(bContext *C, bAnimContext *ac, int channel_index,
gpl->flag |= GP_LAYER_SELECT;
}
- notifierFlags |= (ND_ANIMCHAN | NA_EDITED);
+ /* change active layer, if this is selected (since we must always have an active layer) */
+ if (gpl->flag & GP_LAYER_SELECT) {
+ ANIM_set_active_channel(ac, ac->data, ac->datatype, filter, gpl, ANIMTYPE_GPLAYER);
+ }
+
+ WM_event_add_notifier(C, NC_GPENCIL | NA_EDITED, NULL); /* Grease Pencil updates */
+ notifierFlags |= (ND_ANIMCHAN | NA_EDITED); /* Animation Ediotrs updates */
break;
}
case ANIMTYPE_MASKDATABLOCK:
@@ -3015,6 +3024,105 @@ static void ANIM_OT_channels_click(wmOperatorType *ot)
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
+static bool select_anim_channel_keys(bAnimContext *ac, int channel_index, bool extend)
+{
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+ bool success = false;
+ FCurve *fcu;
+ int i;
+
+ /* get the channel that was clicked on */
+ /* filter channels */
+ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS);
+ ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+
+ /* get channel from index */
+ ale = BLI_findlink(&anim_data, channel_index);
+ if (ale == NULL) {
+ /* channel not found */
+ if (G.debug & G_DEBUG)
+ printf("Error: animation channel (index = %d) not found in rename_anim_channels()\n", channel_index);
+
+ ANIM_animdata_freelist(&anim_data);
+ return false;
+ }
+
+ fcu = (FCurve *)ale->key_data;
+ success = (fcu != NULL);
+
+ ANIM_animdata_freelist(&anim_data);
+
+ /* F-Curve may not have any keyframes */
+ if (fcu && fcu->bezt) {
+ BezTriple *bezt;
+
+ if (!extend) {
+ filter = (ANIMFILTER_DATA_VISIBLE);
+ ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ FCurve *fcu_inner = (FCurve *)ale->key_data;
+
+ if (fcu_inner) {
+ for (i = 0, bezt = fcu_inner->bezt; i < fcu_inner->totvert; i++, bezt++) {
+ bezt->f2 = bezt->f1 = bezt->f3 = 0;
+ }
+ }
+ }
+
+ ANIM_animdata_freelist(&anim_data);
+ }
+
+ for (i = 0, bezt = fcu->bezt; i < fcu->totvert; i++, bezt++) {
+ bezt->f2 = bezt->f1 = bezt->f3 = SELECT;
+ }
+ }
+
+ /* free temp data and tag for refresh */
+ ED_region_tag_redraw(ac->ar);
+ return success;
+}
+
+static int animchannels_channel_select_keys_invoke(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ bAnimContext ac;
+ int channel_index;
+ bool extend = RNA_boolean_get(op->ptr, "extend");
+
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
+
+ channel_index = animchannels_channel_get(&ac, event->mval);
+
+ /* handle click */
+ if (select_anim_channel_keys(&ac, channel_index, extend)) {
+ WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_SELECTED, NULL);
+ return OPERATOR_FINISHED;
+ }
+ else
+ /* allow event to be handled by selectall operator */
+ return OPERATOR_PASS_THROUGH;
+}
+
+static void ANIM_OT_channel_select_keys(wmOperatorType *ot)
+{
+ PropertyRNA *prop;
+
+ /* identifiers */
+ ot->name = "Select Channel keyframes";
+ ot->idname = "ANIM_OT_channel_select_keys";
+ ot->description = "Select all keyframes of channel under mouse";
+
+ /* api callbacks */
+ ot->invoke = animchannels_channel_select_keys_invoke;
+ ot->poll = animedit_poll_channels_active;
+
+ prop = RNA_def_boolean(ot->srna, "extend", false, "Extend", "Extend selection");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+}
+
/* ************************************************************************** */
/* Operator Registration */
@@ -3024,8 +3132,9 @@ void ED_operatortypes_animchannels(void)
WM_operatortype_append(ANIM_OT_channels_select_border);
WM_operatortype_append(ANIM_OT_channels_click);
+ WM_operatortype_append(ANIM_OT_channel_select_keys);
WM_operatortype_append(ANIM_OT_channels_rename);
-
+
WM_operatortype_append(ANIM_OT_channels_find);
WM_operatortype_append(ANIM_OT_channels_setting_enable);
@@ -3042,9 +3151,6 @@ void ED_operatortypes_animchannels(void)
WM_operatortype_append(ANIM_OT_channels_expand);
WM_operatortype_append(ANIM_OT_channels_collapse);
- WM_operatortype_append(ANIM_OT_channels_visibility_toggle);
- WM_operatortype_append(ANIM_OT_channels_visibility_set);
-
WM_operatortype_append(ANIM_OT_channels_fcurves_enable);
WM_operatortype_append(ANIM_OT_channels_clean_empty);
@@ -3068,7 +3174,9 @@ void ED_keymap_animchannels(wmKeyConfig *keyconf)
/* rename */
WM_keymap_add_item(keymap, "ANIM_OT_channels_rename", LEFTMOUSE, KM_PRESS, KM_CTRL, 0);
WM_keymap_add_item(keymap, "ANIM_OT_channels_rename", LEFTMOUSE, KM_DBL_CLICK, 0, 0);
-
+ WM_keymap_add_item(keymap, "ANIM_OT_channel_select_keys", LEFTMOUSE, KM_DBL_CLICK, 0, 0);
+ RNA_boolean_set(WM_keymap_add_item(keymap, "ANIM_OT_channel_select_keys", LEFTMOUSE, KM_DBL_CLICK, KM_SHIFT, 0)->ptr, "extend", true);
+
/* find (i.e. a shortcut for setting the name filter) */
WM_keymap_add_item(keymap, "ANIM_OT_channels_find", FKEY, KM_PRESS, KM_CTRL, 0);
@@ -3110,10 +3218,6 @@ void ED_keymap_animchannels(wmKeyConfig *keyconf)
/* grouping */
WM_keymap_add_item(keymap, "ANIM_OT_channels_group", GKEY, KM_PRESS, KM_CTRL, 0);
WM_keymap_add_item(keymap, "ANIM_OT_channels_ungroup", GKEY, KM_PRESS, KM_ALT, 0);
-
- /* Graph Editor only */
- WM_keymap_add_item(keymap, "ANIM_OT_channels_visibility_set", VKEY, KM_PRESS, 0, 0);
- WM_keymap_add_item(keymap, "ANIM_OT_channels_visibility_toggle", VKEY, KM_PRESS, KM_SHIFT, 0);
}
/* ************************************************************************** */
diff --git a/source/blender/editors/animation/anim_deps.c b/source/blender/editors/animation/anim_deps.c
index f3b47b168e9..a38f5dbc8ea 100644
--- a/source/blender/editors/animation/anim_deps.c
+++ b/source/blender/editors/animation/anim_deps.c
@@ -73,8 +73,10 @@ void ANIM_list_elem_update(Scene *scene, bAnimListElem *ale)
/* tag AnimData for refresh so that other views will update in realtime with these changes */
adt = BKE_animdata_from_id(id);
- if (adt)
+ if (adt) {
adt->recalc |= ADT_RECALC_ANIM;
+ DAG_id_tag_update(id, OB_RECALC_TIME);
+ }
/* update data */
fcu = (ale->datatype == ALE_FCURVE) ? ale->key_data : NULL;
@@ -92,7 +94,7 @@ void ANIM_list_elem_update(Scene *scene, bAnimListElem *ale)
RNA_property_update_main(G.main, scene, &ptr, prop);
}
else {
- /* in other case we do standard depsgaph update, ideally
+ /* in other case we do standard depsgraph update, ideally
* we'd be calling property update functions here too ... */
DAG_id_tag_update(id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME); // XXX or do we want something more restrictive?
}
diff --git a/source/blender/editors/animation/anim_draw.c b/source/blender/editors/animation/anim_draw.c
index 9c3f310a417..ed3d228a93e 100644
--- a/source/blender/editors/animation/anim_draw.c
+++ b/source/blender/editors/animation/anim_draw.c
@@ -34,17 +34,25 @@
#include "DNA_scene_types.h"
#include "DNA_space_types.h"
#include "DNA_userdef_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_object_types.h"
+#include "DNA_gpencil_types.h"
+#include "DNA_mask_types.h"
#include "BLI_math.h"
#include "BLI_timecode.h"
+#include "BLI_utildefines.h"
+#include "BLI_rect.h"
+#include "BLI_dlrbTree.h"
#include "BKE_context.h"
#include "BKE_global.h"
#include "BKE_nla.h"
-#include "BKE_object.h"
+#include "BKE_mask.h"
#include "ED_anim_api.h"
#include "ED_keyframes_edit.h"
+#include "ED_keyframes_draw.h"
#include "RNA_access.h"
@@ -60,9 +68,10 @@
/* Draw current frame number in a little green box beside the current frame indicator */
static void draw_cfra_number(Scene *scene, View2D *v2d, const float cfra, const bool time)
{
+ const uiFontStyle *fstyle = UI_FSTYLE_WIDGET;
float xscale, yscale, x, y;
char numstr[32] = " t"; /* t is the character to start replacing from */
- short slen;
+ int slen;
/* because the frame number text is subject to the same scaling as the contents of the view */
UI_view2d_scale_get(v2d, &xscale, &yscale);
@@ -77,9 +86,10 @@ static void draw_cfra_number(Scene *scene, View2D *v2d, const float cfra, const
BLI_timecode_string_from_time(&numstr[4], sizeof(numstr) - 4, 0, FRA2TIME(cfra), FPS, U.timecode_style);
}
else {
- BLI_timecode_string_from_time_simple(&numstr[4], sizeof(numstr) - 4, 1, cfra);
+ BLI_timecode_string_from_time_seconds(&numstr[4], sizeof(numstr) - 4, 1, cfra);
}
- slen = (short)UI_GetStringWidth(numstr) - 1;
+
+ slen = UI_fontstyle_string_width(fstyle, numstr) - 1;
/* get starting coordinates for drawing */
x = cfra * xscale;
@@ -91,7 +101,7 @@ static void draw_cfra_number(Scene *scene, View2D *v2d, const float cfra, const
/* draw current frame number - black text */
UI_ThemeColor(TH_TEXT);
- UI_DrawString(x - 0.25f * U.widget_unit, y + 0.15f * U.widget_unit, numstr);
+ UI_fontstyle_draw_simple(fstyle, x - 0.25f * U.widget_unit, y + 0.15f * U.widget_unit, numstr);
/* restore view transform */
glScalef(xscale, 1.0, 1.0);
@@ -172,10 +182,14 @@ AnimData *ANIM_nla_mapping_get(bAnimContext *ac, bAnimListElem *ale)
if (G.is_rendering) return NULL;
/* handling depends on the type of animation-context we've got */
- if (ale)
- return ale->adt;
- else
- return NULL;
+ if (ale) {
+ /* NLA Control Curves occur on NLA strips, and shouldn't be subjected to this kind of mapping */
+ if (ale->type != ANIMTYPE_NLACURVE)
+ return ale->adt;
+ }
+
+ /* cannot handle... */
+ return NULL;
}
/* ------------------- */
@@ -261,19 +275,36 @@ short ANIM_get_normalization_flags(bAnimContext *ac)
return 0;
}
-static float normalzation_factor_get(FCurve *fcu, short flag)
+static float normalization_factor_get(Scene *scene, FCurve *fcu, short flag, float *r_offset)
{
- float factor = 1.0f;
+ float factor = 1.0f, offset = 0.0f;
if (flag & ANIM_UNITCONV_RESTORE) {
+ if (r_offset)
+ *r_offset = fcu->prev_offset;
+
return 1.0f / fcu->prev_norm_factor;
}
if (flag & ANIM_UNITCONV_NORMALIZE_FREEZE) {
+ if (r_offset)
+ *r_offset = fcu->prev_offset;
+ if (fcu->prev_norm_factor == 0.0f) {
+ /* Happens when Auto Normalize was disabled before
+ * any curves were displayed.
+ */
+ return 1.0f;
+ }
return fcu->prev_norm_factor;
}
if (G.moving & G_TRANSFORM_FCURVES) {
+ if (r_offset)
+ *r_offset = fcu->prev_offset;
+ if (fcu->prev_norm_factor == 0.0f) {
+ /* Same as above. */
+ return 1.0f;
+ }
return fcu->prev_norm_factor;
}
@@ -282,32 +313,65 @@ static float normalzation_factor_get(FCurve *fcu, short flag)
BezTriple *bezt;
int i;
float max_coord = -FLT_MAX;
+ float min_coord = FLT_MAX;
+ float range;
if (fcu->totvert < 1) {
return 1.0f;
}
- for (i = 0, bezt = fcu->bezt; i < fcu->totvert; i++, bezt++) {
- max_coord = max_ff(max_coord, fabsf(bezt->vec[0][1]));
- max_coord = max_ff(max_coord, fabsf(bezt->vec[1][1]));
- max_coord = max_ff(max_coord, fabsf(bezt->vec[2][1]));
+ if (PRVRANGEON) {
+ for (i = 0, bezt = fcu->bezt; i < fcu->totvert; i++, bezt++) {
+ if (IN_RANGE_INCL(bezt->vec[1][0], scene->r.psfra, scene->r.pefra)) {
+ max_coord = max_ff(max_coord, bezt->vec[0][1]);
+ max_coord = max_ff(max_coord, bezt->vec[1][1]);
+ max_coord = max_ff(max_coord, bezt->vec[2][1]);
+
+ min_coord = min_ff(min_coord, bezt->vec[0][1]);
+ min_coord = min_ff(min_coord, bezt->vec[1][1]);
+ min_coord = min_ff(min_coord, bezt->vec[2][1]);
+ }
+ }
+ }
+ else {
+ for (i = 0, bezt = fcu->bezt; i < fcu->totvert; i++, bezt++) {
+ max_coord = max_ff(max_coord, bezt->vec[0][1]);
+ max_coord = max_ff(max_coord, bezt->vec[1][1]);
+ max_coord = max_ff(max_coord, bezt->vec[2][1]);
+
+ min_coord = min_ff(min_coord, bezt->vec[0][1]);
+ min_coord = min_ff(min_coord, bezt->vec[1][1]);
+ min_coord = min_ff(min_coord, bezt->vec[2][1]);
+ }
}
- if (max_coord > FLT_EPSILON) {
- factor = 1.0f / max_coord;
+ range = max_coord - min_coord;
+
+ if (range > FLT_EPSILON) {
+ factor = 2.0f / range;
}
+ offset = -min_coord - range / 2.0f;
+ }
+ BLI_assert(factor != 0.0f);
+ if (r_offset) {
+ *r_offset = offset;
}
+
fcu->prev_norm_factor = factor;
+ fcu->prev_offset = offset;
return factor;
}
/* Get unit conversion factor for given ID + F-Curve */
-float ANIM_unit_mapping_get_factor(Scene *scene, ID *id, FCurve *fcu, short flag)
+float ANIM_unit_mapping_get_factor(Scene *scene, ID *id, FCurve *fcu, short flag, float *r_offset)
{
if (flag & ANIM_UNITCONV_NORMALIZE) {
- return normalzation_factor_get(fcu, flag);
+ return normalization_factor_get(scene, fcu, flag, r_offset);
}
+ if (r_offset)
+ *r_offset = 0.0f;
+
/* sanity checks */
if (id && fcu && fcu->rna_path) {
PointerRNA ptr, id_ptr;
@@ -335,4 +399,140 @@ float ANIM_unit_mapping_get_factor(Scene *scene, ID *id, FCurve *fcu, short flag
return 1.0f;
}
+static bool find_prev_next_keyframes(struct bContext *C, int *nextfra, int *prevfra)
+{
+ Scene *scene = CTX_data_scene(C);
+ Object *ob = CTX_data_active_object(C);
+ bGPdata *gpd = CTX_data_gpencil_data(C);
+ Mask *mask = CTX_data_edit_mask(C);
+ bDopeSheet ads = {NULL};
+ DLRBT_Tree keys;
+ ActKeyColumn *aknext, *akprev;
+ float cfranext, cfraprev;
+ bool donenext = false, doneprev = false;
+ int nextcount = 0, prevcount = 0;
+
+ cfranext = cfraprev = (float)(CFRA);
+
+ /* init binarytree-list for getting keyframes */
+ BLI_dlrbTree_init(&keys);
+
+ /* seed up dummy dopesheet context with flags to perform necessary filtering */
+ if ((scene->flag & SCE_KEYS_NO_SELONLY) == 0) {
+ /* only selected channels are included */
+ ads.filterflag |= ADS_FILTER_ONLYSEL;
+ }
+
+ /* populate tree with keyframe nodes */
+ scene_to_keylist(&ads, scene, &keys, NULL);
+
+ if (ob)
+ ob_to_keylist(&ads, ob, &keys, NULL);
+
+ gpencil_to_keylist(&ads, gpd, &keys);
+
+ if (mask) {
+ MaskLayer *masklay = BKE_mask_layer_active(mask);
+ mask_to_keylist(&ads, masklay, &keys);
+ }
+
+ /* build linked-list for searching */
+ BLI_dlrbTree_linkedlist_sync(&keys);
+
+ /* find matching keyframe in the right direction */
+ do {
+ aknext = (ActKeyColumn *)BLI_dlrbTree_search_next(&keys, compare_ak_cfraPtr, &cfranext);
+
+ if (aknext) {
+ if (CFRA == (int)aknext->cfra) {
+ /* make this the new starting point for the search and ignore */
+ cfranext = aknext->cfra;
+ }
+ else {
+ /* this changes the frame, so set the frame and we're done */
+ if (++nextcount == U.view_frame_keyframes)
+ donenext = true;
+ }
+ cfranext = aknext->cfra;
+ }
+ } while ((aknext != NULL) && (donenext == false));
+
+ do {
+ akprev = (ActKeyColumn *)BLI_dlrbTree_search_prev(&keys, compare_ak_cfraPtr, &cfraprev);
+
+ if (akprev) {
+ if (CFRA == (int)akprev->cfra) {
+ /* make this the new starting point for the search */
+ }
+ else {
+ /* this changes the frame, so set the frame and we're done */
+ if (++prevcount == U.view_frame_keyframes)
+ doneprev = true;
+ }
+ cfraprev = akprev->cfra;
+ }
+ } while ((akprev != NULL) && (doneprev == false));
+
+ /* free temp stuff */
+ BLI_dlrbTree_free(&keys);
+
+ /* any success? */
+ if (doneprev || donenext) {
+ if (doneprev)
+ *prevfra = cfraprev;
+ else
+ *prevfra = CFRA - (cfranext - CFRA);
+
+ if (donenext)
+ *nextfra = cfranext;
+ else
+ *nextfra = CFRA + (CFRA - cfraprev);
+
+ return true;
+ }
+
+ return false;
+}
+
+void ANIM_center_frame(struct bContext *C, int smooth_viewtx)
+{
+ ARegion *ar = CTX_wm_region(C);
+ Scene *scene = CTX_data_scene(C);
+ float w = BLI_rctf_size_x(&ar->v2d.cur);
+ rctf newrct;
+ int nextfra, prevfra;
+
+ switch (U.view_frame_type) {
+ case ZOOM_FRAME_MODE_SECONDS:
+ {
+ const float fps = FPS;
+ newrct.xmax = scene->r.cfra + U.view_frame_seconds * fps + 1;
+ newrct.xmin = scene->r.cfra - U.view_frame_seconds * fps - 1;
+ newrct.ymax = ar->v2d.cur.ymax;
+ newrct.ymin = ar->v2d.cur.ymin;
+ break;
+ }
+
+ /* hardest case of all, look for all keyframes around frame and display those */
+ case ZOOM_FRAME_MODE_KEYFRAMES:
+ if (find_prev_next_keyframes(C, &nextfra, &prevfra)) {
+ newrct.xmax = nextfra;
+ newrct.xmin = prevfra;
+ newrct.ymax = ar->v2d.cur.ymax;
+ newrct.ymin = ar->v2d.cur.ymin;
+ break;
+ }
+ /* else drop through, keep range instead */
+
+ case ZOOM_FRAME_MODE_KEEP_RANGE:
+ default:
+ newrct.xmax = scene->r.cfra + (w / 2);
+ newrct.xmin = scene->r.cfra - (w / 2);
+ newrct.ymax = ar->v2d.cur.ymax;
+ newrct.ymin = ar->v2d.cur.ymin;
+ break;
+ }
+
+ UI_view2d_smooth_view(C, ar, &newrct, smooth_viewtx);
+}
/* *************************************************** */
diff --git a/source/blender/editors/animation/anim_filter.c b/source/blender/editors/animation/anim_filter.c
index dad25eb04af..8853422df8f 100644
--- a/source/blender/editors/animation/anim_filter.c
+++ b/source/blender/editors/animation/anim_filter.c
@@ -216,7 +216,7 @@ static bool actedit_get_context(bAnimContext *ac, SpaceAction *saction)
/* Get data being edited in Graph Editor (depending on current 'mode') */
static bool graphedit_get_context(bAnimContext *ac, SpaceIpo *sipo)
{
- /* init dopesheet data if non-existant (i.e. for old files) */
+ /* init dopesheet data if non-existent (i.e. for old files) */
if (sipo->ads == NULL) {
sipo->ads = MEM_callocN(sizeof(bDopeSheet), "GraphEdit DopeSheet");
sipo->ads->source = (ID *)ac->scene;
@@ -267,7 +267,7 @@ static bool graphedit_get_context(bAnimContext *ac, SpaceIpo *sipo)
/* Get data being edited in Graph Editor (depending on current 'mode') */
static bool nlaedit_get_context(bAnimContext *ac, SpaceNla *snla)
{
- /* init dopesheet data if non-existant (i.e. for old files) */
+ /* init dopesheet data if non-existent (i.e. for old files) */
if (snla->ads == NULL)
snla->ads = MEM_callocN(sizeof(bDopeSheet), "NlaEdit DopeSheet");
ac->ads = snla->ads;
@@ -423,6 +423,7 @@ bool ANIM_animdata_get_context(const bContext *C, bAnimContext *ac)
* - adtOk: line or block of code to execute for AnimData-blocks case (usually ANIMDATA_ADD_ANIMDATA)
* - nlaOk: line or block of code to execute for NLA tracks+strips case
* - driversOk: line or block of code to execute for Drivers case
+ * - nlaKeysOk: line or block of code for NLA Strip Keyframes case
* - keysOk: line or block of code for Keyframes case
*
* The checks for the various cases are as follows:
@@ -433,9 +434,10 @@ bool ANIM_animdata_get_context(const bContext *C, bAnimContext *ac)
* converted to a new NLA strip, and the filtering options allow this
* 2C) allow non-animated datablocks to be included so that datablocks can be added
* 3) drivers: include drivers from animdata block (for Drivers mode in Graph Editor)
- * 4) normal keyframes: only when there is an active action
+ * 4A) nla strip keyframes: these are the per-strip controls for time and influence
+ * 4B) normal keyframes: only when there is an active action
*/
-#define ANIMDATA_FILTER_CASES(id, adtOk, nlaOk, driversOk, keysOk) \
+#define ANIMDATA_FILTER_CASES(id, adtOk, nlaOk, driversOk, nlaKeysOk, keysOk) \
{ \
if ((id)->adt) { \
if (!(filter_mode & ANIMFILTER_CURVE_VISIBLE) || !((id)->adt->flag & ADT_CURVES_NOT_VISIBLE)) { \
@@ -456,6 +458,9 @@ bool ANIM_animdata_get_context(const bContext *C, bAnimContext *ac)
} \
} \
else { \
+ if (ANIMDATA_HAS_NLA(id)) { \
+ nlaKeysOk \
+ } \
if (ANIMDATA_HAS_KEYS(id)) { \
keysOk \
} \
@@ -771,6 +776,31 @@ static bAnimListElem *make_new_animlistelem(void *data, short datatype, ID *owne
ale->adt = BKE_animdata_from_id(data);
break;
}
+ case ANIMTYPE_DSGPENCIL:
+ {
+ bGPdata *gpd = (bGPdata *)data;
+ AnimData *adt = gpd->adt;
+
+ /* NOTE: we just reuse the same expand filter for this case */
+ ale->flag = EXPANDED_GPD(gpd);
+
+ // XXX: currently, this is only used for access to its animation data
+ ale->key_data = (adt) ? adt->action : NULL;
+ ale->datatype = ALE_ACT;
+
+ ale->adt = BKE_animdata_from_id(data);
+ break;
+ }
+ case ANIMTYPE_NLACONTROLS:
+ {
+ AnimData *adt = (AnimData *)data;
+
+ ale->flag = adt->flag;
+
+ ale->key_data = NULL;
+ ale->datatype = ALE_NONE;
+ break;
+ }
case ANIMTYPE_GROUP:
{
bActionGroup *agrp = (bActionGroup *)data;
@@ -872,7 +902,7 @@ static bAnimListElem *make_new_animlistelem(void *data, short datatype, ID *owne
static bool skip_fcurve_selected_data(bDopeSheet *ads, FCurve *fcu, ID *owner_id, int filter_mode)
{
/* hidden items should be skipped if we only care about visible data, but we aren't interested in hidden stuff */
- short skip_hidden = (filter_mode & ANIMFILTER_DATA_VISIBLE) && !(ads->filterflag & ADS_FILTER_INCL_HIDDEN);
+ const bool skip_hidden = (filter_mode & ANIMFILTER_DATA_VISIBLE) && !(ads->filterflag & ADS_FILTER_INCL_HIDDEN);
if (GS(owner_id->name) == ID_OB) {
Object *ob = (Object *)owner_id;
@@ -962,7 +992,7 @@ static bool skip_fcurve_selected_data(bDopeSheet *ads, FCurve *fcu, ID *owner_id
static bool skip_fcurve_with_name(bDopeSheet *ads, FCurve *fcu, ID *owner_id)
{
bAnimListElem ale_dummy = {NULL};
- bAnimChannelType *acf;
+ const bAnimChannelType *acf;
/* create a dummy wrapper for the F-Curve */
ale_dummy.type = ANIMTYPE_FCURVE;
@@ -1255,7 +1285,7 @@ static size_t animfilter_nla(bAnimContext *UNUSED(ac), ListBase *anim_data, bDop
first = adt->nla_tracks.last;
}
else {
- /* first track to include will the the first one (as per normal) */
+ /* first track to include will the first one (as per normal) */
first = adt->nla_tracks.first;
}
@@ -1271,7 +1301,7 @@ static size_t animfilter_nla(bAnimContext *UNUSED(ac), ListBase *anim_data, bDop
* - active track should still get shown though (even though it has disabled flag set)
*/
// FIXME: the channels after should still get drawn, just 'differently', and after an active-action channel
- if ((adt->flag & ADT_NLA_EDIT_ON) && (nlt->flag & NLATRACK_DISABLED) && !(nlt->flag & NLATRACK_ACTIVE))
+ if ((adt->flag & ADT_NLA_EDIT_ON) && (nlt->flag & NLATRACK_DISABLED) && (adt->act_track != nlt))
continue;
/* only work with this channel and its subchannels if it is editable */
@@ -1280,6 +1310,30 @@ static size_t animfilter_nla(bAnimContext *UNUSED(ac), ListBase *anim_data, bDop
if (ANIMCHANNEL_SELOK(SEL_NLT(nlt))) {
/* only include if this track is active */
if (!(filter_mode & ANIMFILTER_ACTIVE) || (nlt->flag & NLATRACK_ACTIVE)) {
+ /* name based filtering... */
+ if (((ads) && (ads->filterflag & ADS_FILTER_BY_FCU_NAME)) && (owner_id)) {
+ bool track_ok = false, strip_ok = false;
+
+ /* check if the name of the track, or the strips it has are ok... */
+ track_ok = BLI_strcasestr(nlt->name, ads->searchstr);
+
+ if (track_ok == false) {
+ NlaStrip *strip;
+ for (strip = nlt->strips.first; strip; strip = strip->next) {
+ if (BLI_strcasestr(strip->name, ads->searchstr)) {
+ strip_ok = true;
+ break;
+ }
+ }
+ }
+
+ /* skip if both fail this test... */
+ if (!track_ok && !strip_ok) {
+ continue;
+ }
+ }
+
+ /* add the track now that it has passed all our tests */
ANIMCHANNEL_NEW_CHANNEL(nlt, ANIMTYPE_NLATRACK, owner_id);
}
}
@@ -1290,6 +1344,80 @@ static size_t animfilter_nla(bAnimContext *UNUSED(ac), ListBase *anim_data, bDop
return items;
}
+/* Include the control FCurves per NLA Strip in the channel list
+ * NOTE: This is includes the expander too...
+ */
+static size_t animfilter_nla_controls(ListBase *anim_data, bDopeSheet *ads, AnimData *adt, int filter_mode, ID *owner_id)
+{
+ ListBase tmp_data = {NULL, NULL};
+ size_t tmp_items = 0;
+ size_t items = 0;
+
+ /* add control curves from each NLA strip... */
+ /* NOTE: ANIMTYPE_FCURVES are created here, to avoid duplicating the code needed */
+ BEGIN_ANIMFILTER_SUBCHANNELS(((adt->flag & ADT_NLA_SKEYS_COLLAPSED) == 0))
+ {
+ NlaTrack *nlt;
+ NlaStrip *strip;
+
+ /* for now, we only go one level deep - so controls on grouped FCurves are not handled */
+ for (nlt = adt->nla_tracks.first; nlt; nlt = nlt->next) {
+ for (strip = nlt->strips.first; strip; strip = strip->next) {
+ ListBase strip_curves = {NULL, NULL};
+ size_t strip_items = 0;
+
+ /* create the raw items */
+ strip_items += animfilter_fcurves(&strip_curves, ads, strip->fcurves.first, NULL, filter_mode, owner_id);
+
+ /* change their types and add extra data
+ * - There is no point making a separate copy of animfilter_fcurves for this now/yet,
+ * unless we later get per-element control curves for other stuff too
+ */
+ if (strip_items) {
+ bAnimListElem *ale, *ale_n = NULL;
+
+ for (ale = strip_curves.first; ale; ale = ale_n) {
+ ale_n = ale->next;
+
+ /* change the type to being a FCurve for editing NLA strip controls */
+ BLI_assert(ale->type == ANIMTYPE_FCURVE);
+
+ ale->type = ANIMTYPE_NLACURVE;
+ ale->owner = strip;
+
+ ale->adt = NULL; /* XXX: This way, there are no problems with time mapping errors */
+ }
+ }
+
+ /* add strip curves to the set of channels inside the group being collected */
+ BLI_movelisttolist(&tmp_data, &strip_curves);
+ BLI_assert(BLI_listbase_is_empty(&strip_curves));
+ tmp_items += strip_items;
+ }
+ }
+ }
+ END_ANIMFILTER_SUBCHANNELS;
+
+ /* did we find anything? */
+ if (tmp_items) {
+ /* add the expander as a channel first */
+ if (filter_mode & ANIMFILTER_LIST_CHANNELS) {
+ /* currently these channels cannot be selected, so they should be skipped */
+ if ((filter_mode & (ANIMFILTER_SEL | ANIMFILTER_UNSEL)) == 0) {
+ ANIMCHANNEL_NEW_CHANNEL(adt, ANIMTYPE_NLACONTROLS, owner_id);
+ }
+ }
+
+ /* now add the list of collected channels */
+ BLI_movelisttolist(anim_data, &tmp_data);
+ BLI_assert(BLI_listbase_is_empty(&tmp_data));
+ items += tmp_items;
+ }
+
+ /* return the numebr of items added to the list */
+ return items;
+}
+
/* determine what animation data from AnimData block should get displayed */
static size_t animfilter_block_data(bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, ID *id, int filter_mode)
{
@@ -1301,7 +1429,7 @@ static size_t animfilter_block_data(bAnimContext *ac, ListBase *anim_data, bDope
IdAdtTemplate *iat = (IdAdtTemplate *)id;
/* NOTE: this macro is used instead of inlining the logic here, since this sort of filtering is still needed
- * in a few places in he rest of the code still - notably for the few cases where special mode-based
+ * in a few places in the rest of the code still - notably for the few cases where special mode-based
* different types of data expanders are required.
*/
ANIMDATA_FILTER_CASES(iat,
@@ -1317,6 +1445,9 @@ static size_t animfilter_block_data(bAnimContext *ac, ListBase *anim_data, bDope
{ /* Drivers */
items += animfilter_fcurves(anim_data, ads, adt->drivers.first, NULL, filter_mode, id);
},
+ { /* NLA Control Keyframes */
+ items += animfilter_nla_controls(anim_data, ads, adt, filter_mode, id);
+ },
{ /* Keyframes */
items += animfilter_action(ac, anim_data, ads, adt->action, filter_mode, id);
}
@@ -1413,27 +1544,77 @@ static size_t animdata_filter_gpencil(ListBase *anim_data, void *UNUSED(data), i
/* only show if gpd is used by something... */
if (ID_REAL_USERS(gpd) < 1)
continue;
+
+ /* When asked from "AnimData" blocks (i.e. the top-level containers for normal animation),
+ * for convenience, this will return GP Datablocks instead. This may cause issues down
+ * the track, but for now, this will do...
+ */
+ if (filter_mode & ANIMFILTER_ANIMDATA) {
+ /* just add GPD as a channel - this will add everything needed */
+ ANIMCHANNEL_NEW_CHANNEL(gpd, ANIMTYPE_GPDATABLOCK, NULL);
+ }
+ else {
+ /* add gpencil animation channels */
+ BEGIN_ANIMFILTER_SUBCHANNELS(EXPANDED_GPD(gpd))
+ {
+ tmp_items += animdata_filter_gpencil_data(&tmp_data, gpd, filter_mode);
+ }
+ END_ANIMFILTER_SUBCHANNELS;
- /* add gpencil animation channels */
- BEGIN_ANIMFILTER_SUBCHANNELS(EXPANDED_GPD(gpd))
- {
- tmp_items += animdata_filter_gpencil_data(&tmp_data, gpd, filter_mode);
+ /* did we find anything? */
+ if (tmp_items) {
+ /* include data-expand widget first */
+ if (filter_mode & ANIMFILTER_LIST_CHANNELS) {
+ /* add gpd as channel too (if for drawing, and it has layers) */
+ ANIMCHANNEL_NEW_CHANNEL(gpd, ANIMTYPE_GPDATABLOCK, NULL);
+ }
+
+ /* now add the list of collected channels */
+ BLI_movelisttolist(anim_data, &tmp_data);
+ BLI_assert(BLI_listbase_is_empty(&tmp_data));
+ items += tmp_items;
+ }
}
- END_ANIMFILTER_SUBCHANNELS;
+ }
+
+ /* return the number of items added to the list */
+ return items;
+}
+
+/* Helper for Grease Pencil data integrated with main DopeSheet */
+static size_t animdata_filter_ds_gpencil(bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, bGPdata *gpd, int filter_mode)
+{
+ ListBase tmp_data = {NULL, NULL};
+ size_t tmp_items = 0;
+ size_t items = 0;
+
+ /* add relevant animation channels for Grease Pencil */
+ BEGIN_ANIMFILTER_SUBCHANNELS(EXPANDED_GPD(gpd))
+ {
+ /* add animation channels */
+ tmp_items += animfilter_block_data(ac, &tmp_data, ads, &gpd->id, filter_mode);
- /* did we find anything? */
- if (tmp_items) {
- /* include data-expand widget first */
- if (filter_mode & ANIMFILTER_LIST_CHANNELS) {
- /* add gpd as channel too (if for drawing, and it has layers) */
- ANIMCHANNEL_NEW_CHANNEL(gpd, ANIMTYPE_GPDATABLOCK, NULL);
+ /* add Grease Pencil layers */
+ // TODO: do these need a separate expander?
+ // XXX: what order should these go in?
+ }
+ END_ANIMFILTER_SUBCHANNELS;
+
+ /* did we find anything? */
+ if (tmp_items) {
+ /* include data-expand widget first */
+ if (filter_mode & ANIMFILTER_LIST_CHANNELS) {
+ /* check if filtering by active status */
+ // XXX: active check here needs checking
+ if (ANIMCHANNEL_ACTIVEOK(gpd)) {
+ ANIMCHANNEL_NEW_CHANNEL(gpd, ANIMTYPE_DSGPENCIL, gpd);
}
-
- /* now add the list of collected channels */
- BLI_movelisttolist(anim_data, &tmp_data);
- BLI_assert(BLI_listbase_is_empty(&tmp_data));
- items += tmp_items;
}
+
+ /* now add the list of collected channels */
+ BLI_movelisttolist(anim_data, &tmp_data);
+ BLI_assert(BLI_listbase_is_empty(&tmp_data));
+ items += tmp_items;
}
/* return the number of items added to the list */
@@ -1699,6 +1880,12 @@ static size_t animdata_filter_ds_textures(bAnimContext *ac, ListBase *anim_data,
mtex = (MTex **)(&wo->mtex);
break;
}
+ case ID_PA:
+ {
+ ParticleSettings *part = (ParticleSettings *)owner_id;
+ mtex = (MTex **)(&part->mtex);
+ break;
+ }
default:
{
/* invalid/unsupported option */
@@ -1910,8 +2097,12 @@ static size_t animdata_filter_ds_particles(bAnimContext *ac, ListBase *anim_data
/* add particle-system's animation data to temp collection */
BEGIN_ANIMFILTER_SUBCHANNELS(FILTER_PART_OBJD(psys->part))
{
- /* material's animation data */
+ /* particle system's animation data */
tmp_items += animfilter_block_data(ac, &tmp_data, ads, (ID *)psys->part, filter_mode);
+
+ /* textures */
+ if (!(ads->filterflag & ADS_FILTER_NOTEX))
+ tmp_items += animdata_filter_ds_textures(ac, &tmp_data, ads, (ID *)psys->part, filter_mode);
}
END_ANIMFILTER_SUBCHANNELS;
@@ -2139,6 +2330,7 @@ static size_t animdata_filter_ds_obanim(bAnimContext *ac, ListBase *anim_data, b
cdata = adt;
expanded = EXPANDED_DRVD(adt);
},
+ { /* NLA Strip Controls - no dedicated channel for now (XXX) */ },
{ /* Keyframes */
type = ANIMTYPE_FILLACTD;
cdata = adt->action;
@@ -2215,6 +2407,11 @@ static size_t animdata_filter_dopesheet_ob(bAnimContext *ac, ListBase *anim_data
if ((ob->particlesystem.first) && !(ads->filterflag & ADS_FILTER_NOPART)) {
tmp_items += animdata_filter_ds_particles(ac, &tmp_data, ads, ob, filter_mode);
}
+
+ /* grease pencil */
+ if ((ob->gpd) && !(ads->filterflag & ADS_FILTER_NOGPENCIL)) {
+ tmp_items += animdata_filter_ds_gpencil(ac, &tmp_data, ads, ob->gpd, filter_mode);
+ }
}
END_ANIMFILTER_SUBCHANNELS;
@@ -2257,7 +2454,7 @@ static size_t animdata_filter_ds_world(bAnimContext *ac, ListBase *anim_data, bD
/* textures for world */
if (!(ads->filterflag & ADS_FILTER_NOTEX))
- items += animdata_filter_ds_textures(ac, &tmp_data, ads, (ID *)wo, filter_mode);
+ tmp_items += animdata_filter_ds_textures(ac, &tmp_data, ads, (ID *)wo, filter_mode);
/* nodes */
if ((wo->nodetree) && !(ads->filterflag & ADS_FILTER_NONTREE))
@@ -2305,6 +2502,7 @@ static size_t animdata_filter_ds_scene(bAnimContext *ac, ListBase *anim_data, bD
cdata = adt;
expanded = EXPANDED_DRVD(adt);
},
+ { /* NLA Strip Controls - no dedicated channel for now (XXX) */ },
{ /* Keyframes */
type = ANIMTYPE_FILLACTD;
cdata = adt->action;
@@ -2349,6 +2547,7 @@ static size_t animdata_filter_dopesheet_scene(bAnimContext *ac, ListBase *anim_d
BEGIN_ANIMFILTER_SUBCHANNELS(EXPANDED_SCEC(sce))
{
bNodeTree *ntree = sce->nodetree;
+ bGPdata *gpd = sce->gpd;
World *wo = sce->world;
/* Action, Drivers, or NLA for Scene */
@@ -2371,6 +2570,11 @@ static size_t animdata_filter_dopesheet_scene(bAnimContext *ac, ListBase *anim_d
tmp_items += animdata_filter_ds_linestyle(ac, &tmp_data, ads, sce, filter_mode);
}
+ /* grease pencil */
+ if ((gpd) && !(ads->filterflag & ADS_FILTER_NOGPENCIL)) {
+ tmp_items += animdata_filter_ds_gpencil(ac, &tmp_data, ads, gpd, filter_mode);
+ }
+
/* TODO: one day, when sequencer becomes its own datatype, perhaps it should be included here */
}
END_ANIMFILTER_SUBCHANNELS;
@@ -2718,7 +2922,7 @@ size_t ANIM_animdata_filter(bAnimContext *ac, ListBase *anim_data, eAnimFilter_F
/* unhandled */
default:
{
- printf("ANIM_animdata_filter() - Invalid datatype argument %d\n", datatype);
+ printf("ANIM_animdata_filter() - Invalid datatype argument %u\n", datatype);
break;
}
}
diff --git a/source/blender/editors/animation/anim_ipo_utils.c b/source/blender/editors/animation/anim_ipo_utils.c
index 57df6d32f03..ae6894ac546 100644
--- a/source/blender/editors/animation/anim_ipo_utils.c
+++ b/source/blender/editors/animation/anim_ipo_utils.c
@@ -42,7 +42,7 @@
#include "BLI_math.h"
#include "BLI_utildefines.h"
-#include "BLF_translation.h"
+#include "BLT_translation.h"
#include "DNA_anim_types.h"
diff --git a/source/blender/editors/animation/anim_markers.c b/source/blender/editors/animation/anim_markers.c
index 7cd47fab83a..40376c38c3b 100644
--- a/source/blender/editors/animation/anim_markers.c
+++ b/source/blender/editors/animation/anim_markers.c
@@ -266,8 +266,20 @@ void ED_markers_make_cfra_list(ListBase *markers, ListBase *lb, short only_sel)
{
TimeMarker *marker;
- if (markers == NULL)
+ if (lb) {
+ /* Clear the list first, since callers have no way of knowing
+ * whether this terminated early otherwise. This may lead
+ * to crashes if the user didn't clear the memory first.
+ */
+ lb->first = lb->last = NULL;
+ }
+ else {
return;
+ }
+
+ if (markers == NULL) {
+ return;
+ }
for (marker = markers->first; marker; marker = marker->next)
add_marker_to_cfra_elem(lb, marker, only_sel);
@@ -316,19 +328,14 @@ void debug_markers_print_list(ListBase *markers)
/* ************* Marker Drawing ************ */
/* function to draw markers */
-static void draw_marker(View2D *v2d, TimeMarker *marker, int cfra, int flag)
+static void draw_marker(
+ View2D *v2d, const uiFontStyle *fstyle, TimeMarker *marker, int cfra, int flag,
+ /* avoid re-calculating each time */
+ const float ypixels, const float xscale, const float yscale)
{
- float xpos, ypixels, xscale, yscale;
- int icon_id = 0;
-
- xpos = marker->frame;
-
- /* no time correction for framelen! space is drawn with old values */
- ypixels = BLI_rcti_size_y(&v2d->mask);
- UI_view2d_scale_get(v2d, &xscale, &yscale);
-
- glScalef(1.0f / xscale, 1.0f, 1.0f);
-
+ const float xpos = marker->frame * xscale;
+ int icon_id;
+
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
@@ -347,8 +354,8 @@ static void draw_marker(View2D *v2d, TimeMarker *marker, int cfra, int flag)
glColor4ub(0, 0, 0, 96);
glBegin(GL_LINES);
- glVertex2f((xpos * xscale) + 0.5f, 12.0f);
- glVertex2f((xpos * xscale) + 0.5f, (v2d->cur.ymax + 12.0f) * yscale);
+ glVertex2f(xpos + 0.5f, 12.0f);
+ glVertex2f(xpos + 0.5f, (v2d->cur.ymax + 12.0f) * yscale);
glEnd();
setlinestyle(0);
@@ -365,7 +372,7 @@ static void draw_marker(View2D *v2d, TimeMarker *marker, int cfra, int flag)
ICON_MARKER;
}
- UI_icon_draw(xpos * xscale - 0.45f * UI_DPI_ICON_SIZE, UI_DPI_ICON_SIZE, icon_id);
+ UI_icon_draw(xpos - 0.45f * UI_DPI_ICON_SIZE, UI_DPI_ICON_SIZE, icon_id);
glDisable(GL_BLEND);
@@ -378,19 +385,19 @@ static void draw_marker(View2D *v2d, TimeMarker *marker, int cfra, int flag)
if (marker->flag & SELECT) {
UI_ThemeColor(TH_TEXT_HI);
- x = xpos * xscale + 4.0f * UI_DPI_FAC;
+ x = xpos + 4.0f * UI_DPI_FAC;
y = (ypixels <= 39.0f * UI_DPI_FAC) ? (ypixels - 10.0f * UI_DPI_FAC) : 29.0f * UI_DPI_FAC;
y = max_ii(y, min_y);
}
else {
UI_ThemeColor(TH_TEXT);
if ((marker->frame <= cfra) && (marker->frame + 5 > cfra)) {
- x = xpos * xscale + 8.0f * UI_DPI_FAC;
+ x = xpos + 8.0f * UI_DPI_FAC;
y = (ypixels <= 39.0f * UI_DPI_FAC) ? (ypixels - 10.0f * UI_DPI_FAC) : 29.0f * UI_DPI_FAC;
y = max_ii(y, min_y);
}
else {
- x = xpos * xscale + 8.0f * UI_DPI_FAC;
+ x = xpos + 8.0f * UI_DPI_FAC;
y = 17.0f * UI_DPI_FAC;
}
}
@@ -404,39 +411,71 @@ static void draw_marker(View2D *v2d, TimeMarker *marker, int cfra, int flag)
}
#endif
- UI_DrawString(x, y, marker->name);
+ UI_fontstyle_draw_simple(fstyle, x, y, marker->name);
}
-
- glScalef(xscale, 1.0f, 1.0f);
}
/* Draw Scene-Markers in time window */
-void draw_markers_time(const bContext *C, int flag)
+void ED_markers_draw(const bContext *C, int flag)
{
+ const uiFontStyle *fstyle = UI_FSTYLE_WIDGET;
ListBase *markers = ED_context_get_markers(C);
View2D *v2d;
TimeMarker *marker;
Scene *scene;
+ int select_pass;
+ int v2d_clip_range_x[2];
+ float font_width_max;
- if (markers == NULL)
+ /* cache values */
+ float ypixels, xscale, yscale;
+
+ if (markers == NULL || BLI_listbase_is_empty(markers)) {
return;
+ }
scene = CTX_data_scene(C);
v2d = UI_view2d_fromcontext(C);
- /* unselected markers are drawn at the first time */
- for (marker = markers->first; marker; marker = marker->next) {
- if ((marker->flag & SELECT) == 0) {
- draw_marker(v2d, marker, scene->r.cfra, flag);
- }
+ if (flag & DRAW_MARKERS_MARGIN) {
+ const unsigned char shade[4] = {0, 0, 0, 16};
+ glColor4ubv(shade);
+
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+ glRectf(v2d->cur.xmin, 0, v2d->cur.xmax, UI_MARKER_MARGIN_Y);
+
+ glDisable(GL_BLEND);
}
-
- /* selected markers are drawn later */
- for (marker = markers->first; marker; marker = marker->next) {
- if (marker->flag & SELECT) {
- draw_marker(v2d, marker, scene->r.cfra, flag);
+
+ /* no time correction for framelen! space is drawn with old values */
+ ypixels = BLI_rcti_size_y(&v2d->mask);
+ UI_view2d_scale_get(v2d, &xscale, &yscale);
+ glScalef(1.0f / xscale, 1.0f, 1.0f);
+
+ /* x-bounds with offset for text (adjust for long string, avoid checking string width) */
+ font_width_max = (10 * UI_DPI_FAC) / xscale;
+ v2d_clip_range_x[0] = v2d->cur.xmin - (sizeof(marker->name) * font_width_max);
+ v2d_clip_range_x[1] = v2d->cur.xmax + font_width_max;
+
+ /* loop [unselected, selected] */
+ for (select_pass = 0; select_pass <= SELECT; select_pass += SELECT) {
+ /* unselected markers are drawn at the first time */
+ for (marker = markers->first; marker; marker = marker->next) {
+ if ((marker->flag & SELECT) == select_pass) {
+ /* bounds check */
+ if ((marker->frame >= v2d_clip_range_x[0]) &&
+ (marker->frame <= v2d_clip_range_x[1]))
+ {
+ draw_marker(v2d, fstyle, marker, scene->r.cfra, flag,
+ ypixels, xscale, yscale);
+ }
+ }
}
}
+
+ glScalef(xscale, 1.0f, 1.0f);
}
/* ************************ Marker Wrappers API ********************* */
@@ -460,11 +499,32 @@ static int ed_markers_poll_selected_markers(bContext *C)
return ED_markers_get_first_selected(markers) != NULL;
}
+static int ed_markers_poll_selected_no_locked_markers(bContext *C)
+{
+ ListBase *markers = ED_context_get_markers(C);
+ ToolSettings *ts = CTX_data_tool_settings(C);
+
+ if (ts->lock_markers)
+ return 0;
+
+ /* first things first: markers can only exist in timeline views */
+ if (ED_operator_animview_active(C) == 0)
+ return 0;
+
+ /* check if some marker is selected */
+ return ED_markers_get_first_selected(markers) != NULL;
+}
+
+
/* special poll() which checks if there are any markers at all first */
static int ed_markers_poll_markers_exist(bContext *C)
{
ListBase *markers = ED_context_get_markers(C);
+ ToolSettings *ts = CTX_data_tool_settings(C);
+ if (ts->lock_markers)
+ return 0;
+
/* first things first: markers can only exist in timeline views */
if (ED_operator_animview_active(C) == 0)
return 0;
@@ -503,8 +563,9 @@ static int ed_markers_opwrap_invoke_custom(bContext *C, wmOperator *op, const wm
/* return status modifications - for now, make this spacetype dependent as above */
if (sa->spacetype != SPACE_TIME) {
/* unless successful, must add "pass-through" to let normal operator's have a chance at tackling this event */
- if (retval != OPERATOR_FINISHED)
+ if ((retval & (OPERATOR_FINISHED | OPERATOR_INTERFACE)) == 0) {
retval |= OPERATOR_PASS_THROUGH;
+ }
}
return retval;
@@ -901,11 +962,11 @@ static void MARKER_OT_move(wmOperatorType *ot)
ot->exec = ed_marker_move_exec;
ot->invoke = ed_marker_move_invoke_wrapper;
ot->modal = ed_marker_move_modal;
- ot->poll = ed_markers_poll_selected_markers;
+ ot->poll = ed_markers_poll_selected_no_locked_markers;
ot->cancel = ed_marker_move_cancel;
/* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING | OPTYPE_GRAB_POINTER;
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING | OPTYPE_GRAB_CURSOR;
/* rna storage */
RNA_def_int(ot->srna, "frames", 0, INT_MIN, INT_MAX, "Frames", "", INT_MIN, INT_MAX);
@@ -994,7 +1055,7 @@ static void MARKER_OT_duplicate(wmOperatorType *ot)
ot->exec = ed_marker_duplicate_exec;
ot->invoke = ed_marker_duplicate_invoke_wrapper;
ot->modal = ed_marker_move_modal;
- ot->poll = ed_markers_poll_selected_markers;
+ ot->poll = ed_markers_poll_selected_no_locked_markers;
ot->cancel = ed_marker_move_cancel;
/* flags */
@@ -1029,7 +1090,7 @@ static void select_timeline_marker_frame(ListBase *markers, int frame, bool exte
}
BLI_LISTBASE_CIRCULAR_FORWARD_BEGIN (markers, marker, marker_first) {
- /* this way a not-extend select will allways give 1 selected marker */
+ /* this way a not-extend select will always give 1 selected marker */
if (marker->frame == frame) {
marker->flag ^= SELECT;
break;
@@ -1324,7 +1385,7 @@ static void MARKER_OT_delete(wmOperatorType *ot)
/* api callbacks */
ot->invoke = ed_marker_delete_invoke_wrapper;
ot->exec = ed_marker_delete_exec;
- ot->poll = ed_markers_poll_selected_markers;
+ ot->poll = ed_markers_poll_selected_no_locked_markers;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
@@ -1372,7 +1433,7 @@ static void MARKER_OT_rename(wmOperatorType *ot)
/* api callbacks */
ot->invoke = ed_marker_rename_invoke_wrapper;
ot->exec = ed_marker_rename_exec;
- ot->poll = ed_markers_poll_selected_markers;
+ ot->poll = ed_markers_poll_selected_no_locked_markers;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
@@ -1400,6 +1461,11 @@ static int ed_marker_make_links_scene_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
+ if (scene_to->toolsettings->lock_markers) {
+ BKE_report(op->reports, RPT_ERROR, "Target scene has locked markers");
+ return OPERATOR_CANCELLED;
+ }
+
/* copy markers */
for (marker = markers->first; marker; marker = marker->next) {
if (marker->flag & SELECT) {
@@ -1475,13 +1541,13 @@ static void MARKER_OT_camera_bind(wmOperatorType *ot)
{
/* identifiers */
ot->name = "Bind Camera to Markers";
- ot->description = "Bind the active camera to selected markers(s)";
+ ot->description = "Bind the active camera to selected marker(s)";
ot->idname = "MARKER_OT_camera_bind";
/* api callbacks */
ot->exec = ed_marker_camera_bind_exec;
ot->invoke = ed_markers_opwrap_invoke;
- ot->poll = ed_markers_poll_selected_markers;
+ ot->poll = ed_markers_poll_selected_no_locked_markers;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
diff --git a/source/blender/editors/animation/anim_ops.c b/source/blender/editors/animation/anim_ops.c
index 0f202003dd8..262ce0b9e23 100644
--- a/source/blender/editors/animation/anim_ops.c
+++ b/source/blender/editors/animation/anim_ops.c
@@ -41,6 +41,7 @@
#include "DNA_scene_types.h"
#include "BKE_context.h"
+#include "BKE_sequencer.h"
#include "BKE_global.h"
#include "BKE_main.h"
#include "BKE_sound.h"
@@ -55,6 +56,7 @@
#include "ED_anim_api.h"
#include "ED_screen.h"
+#include "ED_sequencer.h"
#include "anim_intern.h"
@@ -92,14 +94,20 @@ static void change_frame_apply(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
-
+ int frame = RNA_int_get(op->ptr, "frame");
+ bool do_snap = RNA_boolean_get(op->ptr, "snap");
+
+ if (do_snap && CTX_wm_space_seq(C)) {
+ frame = BKE_sequencer_find_next_prev_edit(scene, frame, SEQ_SIDE_BOTH, true, false, false);
+ }
+
/* set the new frame number */
- CFRA = RNA_int_get(op->ptr, "frame");
+ CFRA = frame;
FRAMENUMBER_MIN_CLAMP(CFRA);
SUBFRA = 0.0f;
/* do updates */
- sound_seek_scene(bmain, scene);
+ BKE_sound_seek_scene(bmain, scene);
WM_event_add_notifier(C, NC_SCENE | ND_FRAME, scene);
}
@@ -136,6 +144,41 @@ static int frame_from_event(bContext *C, const wmEvent *event)
return frame;
}
+static void change_frame_seq_preview_begin(bContext *C, const wmEvent *event)
+{
+ ScrArea *sa = CTX_wm_area(C);
+ bScreen *screen = CTX_wm_screen(C);
+ if (sa && sa->spacetype == SPACE_SEQ) {
+ SpaceSeq *sseq = sa->spacedata.first;
+ if (ED_space_sequencer_check_show_strip(sseq)) {
+ ED_sequencer_special_preview_set(C, event->mval);
+ }
+ }
+ if (screen)
+ screen->scrubbing = true;
+}
+
+static void change_frame_seq_preview_end(bContext *C)
+{
+ bScreen *screen = CTX_wm_screen(C);
+ bool notify = false;
+
+ if (screen->scrubbing) {
+ screen->scrubbing = false;
+ notify = true;
+ }
+
+ if (ED_sequencer_special_preview_get() != NULL) {
+ ED_sequencer_special_preview_clear();
+ notify = true;
+ }
+
+ if (notify) {
+ Scene *scene = CTX_data_scene(C);
+ WM_event_add_notifier(C, NC_SCENE | ND_FRAME, scene);
+ }
+}
+
/* Modal Operator init */
static int change_frame_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
@@ -144,7 +187,9 @@ static int change_frame_invoke(bContext *C, wmOperator *op, const wmEvent *event
* click-dragging over a range (modal scrubbing).
*/
RNA_int_set(op->ptr, "frame", frame_from_event(C, event));
-
+
+ change_frame_seq_preview_begin(C, event);
+
change_frame_apply(C, op);
/* add temp handler */
@@ -153,14 +198,21 @@ static int change_frame_invoke(bContext *C, wmOperator *op, const wmEvent *event
return OPERATOR_RUNNING_MODAL;
}
+static void change_frame_cancel(bContext *C, wmOperator *UNUSED(op))
+{
+ change_frame_seq_preview_end(C);
+}
+
/* Modal event handling of frame changing */
static int change_frame_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
+ int ret = OPERATOR_RUNNING_MODAL;
/* execute the events */
switch (event->type) {
case ESCKEY:
- return OPERATOR_FINISHED;
-
+ ret = OPERATOR_FINISHED;
+ break;
+
case MOUSEMOVE:
RNA_int_set(op->ptr, "frame", frame_from_event(C, event));
change_frame_apply(C, op);
@@ -173,15 +225,31 @@ static int change_frame_modal(bContext *C, wmOperator *op, const wmEvent *event)
* the modal op) doesn't work for some reason
*/
if (event->val == KM_RELEASE)
- return OPERATOR_FINISHED;
+ ret = OPERATOR_FINISHED;
+ break;
+
+ case LEFTCTRLKEY:
+ case RIGHTCTRLKEY:
+ if (event->val == KM_RELEASE) {
+ RNA_boolean_set(op->ptr, "snap", false);
+ }
+ else if (event->val == KM_PRESS) {
+ RNA_boolean_set(op->ptr, "snap", true);
+ }
break;
}
- return OPERATOR_RUNNING_MODAL;
+ if (ret != OPERATOR_RUNNING_MODAL) {
+ change_frame_seq_preview_end(C);
+ }
+
+ return ret;
}
static void ANIM_OT_change_frame(wmOperatorType *ot)
{
+ PropertyRNA *prop;
+
/* identifiers */
ot->name = "Change Frame";
ot->idname = "ANIM_OT_change_frame";
@@ -190,14 +258,17 @@ static void ANIM_OT_change_frame(wmOperatorType *ot)
/* api callbacks */
ot->exec = change_frame_exec;
ot->invoke = change_frame_invoke;
+ ot->cancel = change_frame_cancel;
ot->modal = change_frame_modal;
ot->poll = change_frame_poll;
/* flags */
- ot->flag = OPTYPE_BLOCKING | OPTYPE_UNDO | OPTYPE_GRAB_POINTER;
+ ot->flag = OPTYPE_BLOCKING | OPTYPE_UNDO | OPTYPE_GRAB_CURSOR;
/* rna */
ot->prop = RNA_def_int(ot->srna, "frame", 0, MINAFRAME, MAXFRAME, "Frame", "", MINAFRAME, MAXFRAME);
+ prop = RNA_def_boolean(ot->srna, "snap", false, "Snap", "");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
/* ****************** set preview range operator ****************************/
diff --git a/source/blender/editors/animation/drivers.c b/source/blender/editors/animation/drivers.c
index 481912f4d1f..b2a34d7c317 100644
--- a/source/blender/editors/animation/drivers.c
+++ b/source/blender/editors/animation/drivers.c
@@ -39,18 +39,13 @@
#include "BLI_utildefines.h"
#include "DNA_anim_types.h"
-#include "DNA_object_types.h"
-#include "DNA_material_types.h"
#include "DNA_texture_types.h"
-#include "DNA_screen_types.h"
-#include "DNA_space_types.h"
#include "BKE_animsys.h"
+#include "BKE_depsgraph.h"
#include "BKE_fcurve.h"
#include "BKE_context.h"
#include "BKE_report.h"
-#include "BKE_material.h"
-#include "BKE_texture.h"
#include "ED_keyframing.h"
@@ -90,7 +85,7 @@ FCurve *verify_driver_fcurve(ID *id, const char rna_path[], const int array_inde
/* init animdata if none available yet */
adt = BKE_animdata_from_id(id);
if ((adt == NULL) && (add))
- adt = BKE_id_add_animdata(id);
+ adt = BKE_animdata_add_id(id);
if (adt == NULL) {
/* if still none (as not allowed to add, or ID doesn't have animdata for some reason) */
return NULL;
@@ -426,74 +421,6 @@ bool ANIM_paste_driver(ReportList *reports, ID *id, const char rna_path[], int a
/* ************************************************** */
/* UI-Button Interface */
-/**
- * Temporary wrapper for driver operators for buttons to make it easier to create
- * such drivers by rerouting all paths through the active object instead so that
- * they will get picked up by the dependency system.
- *
- * \param C Context pointer - for getting active data
- * \param[in,out] ptr RNA pointer for property's datablock. May be modified as result of path remapping.
- * \param prop RNA definition of property to add for
- * \return MEM_alloc'd string representing the path to the property from the given #PointerRNA
- */
-static char *get_driver_path_hack(bContext *C, PointerRNA *ptr, PropertyRNA *prop)
-{
- ID *id = (ID *)ptr->id.data;
- ScrArea *sa = CTX_wm_area(C);
-
- /* get standard path which may be extended */
- char *basepath = RNA_path_from_ID_to_property(ptr, prop);
- char *path = basepath; /* in case no remapping is needed */
-
-
- /* Remapping will only be performed in the Properties Editor, as only this
- * restricts the subspace of options to the 'active' data (a manageable state)
- */
- // TODO: watch out for pinned context?
- if ((sa) && (sa->spacetype == SPACE_BUTS)) {
- Object *ob = CTX_data_active_object(C);
-
- if (ob && id) {
- /* only id-types which can be remapped to go through objects should be considered */
- switch (GS(id->name)) {
- case ID_TE: /* textures */
- {
- Material *ma = give_current_material(ob, ob->actcol);
- Tex *tex = give_current_material_texture(ma);
-
- /* assumes: texture will only be shown if it is active material's active texture it's ok */
- if ((ID *)tex == id) {
- char name_esc_ma[(sizeof(ma->id.name) - 2) * 2];
- char name_esc_tex[(sizeof(tex->id.name) - 2) * 2];
-
- BLI_strescape(name_esc_ma, ma->id.name + 2, sizeof(name_esc_ma));
- BLI_strescape(name_esc_tex, tex->id.name + 2, sizeof(name_esc_tex));
-
- /* create new path */
- // TODO: use RNA path functions to construct step by step instead?
- // FIXME: maybe this isn't even needed anymore...
- path = BLI_sprintfN("material_slots[\"%s\"].material.texture_slots[\"%s\"].texture.%s",
- name_esc_ma, name_esc_tex, basepath);
-
- /* free old one */
- MEM_freeN(basepath);
- }
- break;
- }
- }
-
- /* fix RNA pointer, as we've now changed the ID root by changing the paths */
- if (basepath != path) {
- /* rebase provided pointer so that it starts from object... */
- RNA_pointer_create(&ob->id, ptr->type, ptr->data, ptr);
- }
- }
- }
-
- /* the path should now have been corrected for use */
- return path;
-}
-
/* Add Driver Button Operator ------------------------ */
static int add_driver_button_exec(bContext *C, wmOperator *op)
@@ -505,13 +432,13 @@ static int add_driver_button_exec(bContext *C, wmOperator *op)
const bool all = RNA_boolean_get(op->ptr, "all");
/* try to create driver using property retrieved from UI */
- uiContextActiveProperty(C, &ptr, &prop, &index);
+ UI_context_active_but_prop_get(C, &ptr, &prop, &index);
if (all)
index = -1;
if (ptr.id.data && ptr.data && prop && RNA_property_animateable(&ptr, prop)) {
- char *path = get_driver_path_hack(C, &ptr, prop);
+ char *path = BKE_animdata_driver_path_hack(C, &ptr, prop, NULL);
short flags = CREATEDRIVER_WITH_DEFAULT_DVAR;
if (path) {
@@ -523,8 +450,8 @@ static int add_driver_button_exec(bContext *C, wmOperator *op)
if (success) {
/* send updates */
- uiContextAnimUpdate(C);
-
+ UI_context_update_anim_flag(C);
+ DAG_relations_tag_update(CTX_data_main(C));
WM_event_add_notifier(C, NC_ANIMATION | ND_FCURVES_ORDER, NULL); // XXX
}
@@ -560,22 +487,25 @@ static int remove_driver_button_exec(bContext *C, wmOperator *op)
const bool all = RNA_boolean_get(op->ptr, "all");
/* try to find driver using property retrieved from UI */
- uiContextActiveProperty(C, &ptr, &prop, &index);
+ UI_context_active_but_prop_get(C, &ptr, &prop, &index);
if (all)
index = -1;
if (ptr.id.data && ptr.data && prop) {
- char *path = get_driver_path_hack(C, &ptr, prop);
+ char *path = BKE_animdata_driver_path_hack(C, &ptr, prop, NULL);
- success = ANIM_remove_driver(op->reports, ptr.id.data, path, index, 0);
- MEM_freeN(path);
+ if (path) {
+ success = ANIM_remove_driver(op->reports, ptr.id.data, path, index, 0);
+
+ MEM_freeN(path);
+ }
}
if (success) {
/* send updates */
- uiContextAnimUpdate(C);
-
+ UI_context_update_anim_flag(C);
+ DAG_relations_tag_update(CTX_data_main(C));
WM_event_add_notifier(C, NC_ANIMATION | ND_FCURVES_ORDER, NULL); // XXX
}
@@ -610,16 +540,16 @@ static int copy_driver_button_exec(bContext *C, wmOperator *op)
int index;
/* try to create driver using property retrieved from UI */
- uiContextActiveProperty(C, &ptr, &prop, &index);
+ UI_context_active_but_prop_get(C, &ptr, &prop, &index);
if (ptr.id.data && ptr.data && prop && RNA_property_animateable(&ptr, prop)) {
- char *path = get_driver_path_hack(C, &ptr, prop);
+ char *path = BKE_animdata_driver_path_hack(C, &ptr, prop, NULL);
if (path) {
/* only copy the driver for the button that this was involved for */
success = ANIM_copy_driver(op->reports, ptr.id.data, path, index, 0);
- uiContextAnimUpdate(C);
+ UI_context_update_anim_flag(C);
MEM_freeN(path);
}
@@ -654,16 +584,16 @@ static int paste_driver_button_exec(bContext *C, wmOperator *op)
int index;
/* try to create driver using property retrieved from UI */
- uiContextActiveProperty(C, &ptr, &prop, &index);
+ UI_context_active_but_prop_get(C, &ptr, &prop, &index);
if (ptr.id.data && ptr.data && prop && RNA_property_animateable(&ptr, prop)) {
- char *path = get_driver_path_hack(C, &ptr, prop);
+ char *path = BKE_animdata_driver_path_hack(C, &ptr, prop, NULL);
if (path) {
/* only copy the driver for the button that this was involved for */
success = ANIM_paste_driver(op->reports, ptr.id.data, path, index, 0);
- uiContextAnimUpdate(C);
+ UI_context_update_anim_flag(C);
MEM_freeN(path);
}
diff --git a/source/blender/editors/animation/fmodifier_ui.c b/source/blender/editors/animation/fmodifier_ui.c
index 7ce33e01747..91705d63286 100644
--- a/source/blender/editors/animation/fmodifier_ui.c
+++ b/source/blender/editors/animation/fmodifier_ui.c
@@ -45,7 +45,7 @@
#include "MEM_guardedalloc.h"
-#include "BLF_translation.h"
+#include "BLT_translation.h"
#include "BLI_blenlib.h"
#include "BLI_utildefines.h"
@@ -78,7 +78,7 @@
static void validate_fmodifier_cb(bContext *UNUSED(C), void *fcm_v, void *UNUSED(arg))
{
FModifier *fcm = (FModifier *)fcm_v;
- FModifierTypeInfo *fmi = fmodifier_get_typeinfo(fcm);
+ const FModifierTypeInfo *fmi = fmodifier_get_typeinfo(fcm);
/* call the verify callback on the modifier if applicable */
if (fmi && fmi->verify_data)
@@ -119,17 +119,18 @@ static void draw_modifier__generator(uiLayout *layout, ID *id, FModifier *fcm, s
/* basic settings (backdrop + mode selector + some padding) */
/* col = uiLayoutColumn(layout, true); */ /* UNUSED */
block = uiLayoutGetBlock(layout);
- uiBlockBeginAlign(block);
- but = uiDefButR(block, MENU, B_FMODIFIER_REDRAW, NULL, 0, 0, bwidth, UI_UNIT_Y, &ptr, "mode", -1, 0, 0, -1, -1, NULL);
- uiButSetFunc(but, validate_fmodifier_cb, fcm, NULL);
+ UI_block_align_begin(block);
+ but = uiDefButR(block, UI_BTYPE_MENU, B_FMODIFIER_REDRAW, NULL, 0, 0, bwidth, UI_UNIT_Y, &ptr, "mode", -1, 0, 0, -1, -1, NULL);
+ UI_but_func_set(but, validate_fmodifier_cb, fcm, NULL);
- uiDefButR(block, TOG, B_FMODIFIER_REDRAW, NULL, 0, 0, bwidth, UI_UNIT_Y, &ptr, "use_additive", -1, 0, 0, -1, -1, NULL);
- uiBlockEndAlign(block);
+ uiDefButR(block, UI_BTYPE_TOGGLE, B_FMODIFIER_REDRAW, NULL, 0, 0, bwidth, UI_UNIT_Y, &ptr, "use_additive", -1, 0, 0, -1, -1, NULL);
+ UI_block_align_end(block);
/* now add settings for individual modes */
switch (data->mode) {
case FCM_GENERATOR_POLYNOMIAL: /* polynomial expression */
{
+ const uiFontStyle *fstyle = UI_FSTYLE_WIDGET;
float *cp = NULL;
char xval[32];
unsigned int i;
@@ -138,20 +139,21 @@ static void draw_modifier__generator(uiLayout *layout, ID *id, FModifier *fcm, s
/* draw polynomial order selector */
row = uiLayoutRow(layout, false);
block = uiLayoutGetBlock(row);
- but = uiDefButI(block, NUM, B_FMODIFIER_REDRAW, IFACE_("Poly Order:"), 0.5f * UI_UNIT_X, 0, bwidth, UI_UNIT_Y,
+ but = uiDefButI(block, UI_BTYPE_NUM, B_FMODIFIER_REDRAW, IFACE_("Poly Order:"), 0.5f * UI_UNIT_X, 0, bwidth, UI_UNIT_Y,
&data->poly_order, 1, 100, 0, 0,
TIP_("'Order' of the Polynomial (for a polynomial with n terms, 'order' is n-1)"));
- uiButSetFunc(but, validate_fmodifier_cb, fcm, NULL);
+ UI_but_func_set(but, validate_fmodifier_cb, fcm, NULL);
/* calculate maximum width of label for "x^n" labels */
if (data->arraysize > 2) {
BLI_snprintf(xval, sizeof(xval), "x^%u", data->arraysize);
- maxXWidth = UI_GetStringWidth(xval) + 0.5 * UI_UNIT_X; /* XXX: UI_GetStringWidth is not accurate */
+ /* XXX: UI_fontstyle_string_width is not accurate */
+ maxXWidth = UI_fontstyle_string_width(fstyle, xval) + 0.5 * UI_UNIT_X;
}
else {
/* basic size (just "x") */
- maxXWidth = UI_GetStringWidth("x") + 0.5 * UI_UNIT_X;
+ maxXWidth = UI_fontstyle_string_width(fstyle, "x") + 0.5 * UI_UNIT_X;
}
/* draw controls for each coefficient and a + sign at end of row */
@@ -162,12 +164,12 @@ static void draw_modifier__generator(uiLayout *layout, ID *id, FModifier *fcm, s
for (i = 0; (i < data->arraysize) && (cp); i++, cp++) {
/* To align with first line... */
if (i)
- uiDefBut(block, LABEL, 1, " ", 0, 0, 2 * UI_UNIT_X, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
+ uiDefBut(block, UI_BTYPE_LABEL, 1, " ", 0, 0, 2 * UI_UNIT_X, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
else
- uiDefBut(block, LABEL, 1, "y =", 0, 0, 2 * UI_UNIT_X, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
+ uiDefBut(block, UI_BTYPE_LABEL, 1, "y =", 0, 0, 2 * UI_UNIT_X, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
/* coefficient */
- uiDefButF(block, NUM, B_FMODIFIER_REDRAW, "", 0, 0, bwidth / 2, UI_UNIT_Y, cp, -UI_FLT_MAX, UI_FLT_MAX,
+ uiDefButF(block, UI_BTYPE_NUM, B_FMODIFIER_REDRAW, "", 0, 0, bwidth / 2, UI_UNIT_Y, cp, -UI_FLT_MAX, UI_FLT_MAX,
10, 3, TIP_("Coefficient for polynomial"));
/* 'x' param (and '+' if necessary) */
@@ -177,10 +179,10 @@ static void draw_modifier__generator(uiLayout *layout, ID *id, FModifier *fcm, s
BLI_strncpy(xval, "x", sizeof(xval));
else
BLI_snprintf(xval, sizeof(xval), "x^%u", i);
- uiDefBut(block, LABEL, 1, xval, 0, 0, maxXWidth, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, TIP_("Power of x"));
+ uiDefBut(block, UI_BTYPE_LABEL, 1, xval, 0, 0, maxXWidth, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, TIP_("Power of x"));
if ( (i != (data->arraysize - 1)) || ((i == 0) && data->arraysize == 2) ) {
- uiDefBut(block, LABEL, 1, "+", 0, 0, UI_UNIT_X, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
+ uiDefBut(block, UI_BTYPE_LABEL, 1, "+", 0, 0, UI_UNIT_X, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
/* next coefficient on a new row */
row = uiLayoutRow(layout, true);
@@ -188,7 +190,7 @@ static void draw_modifier__generator(uiLayout *layout, ID *id, FModifier *fcm, s
}
else {
/* For alignment in UI! */
- uiDefBut(block, LABEL, 1, " ", 0, 0, UI_UNIT_X, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
+ uiDefBut(block, UI_BTYPE_LABEL, 1, " ", 0, 0, UI_UNIT_X, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
}
}
break;
@@ -202,10 +204,10 @@ static void draw_modifier__generator(uiLayout *layout, ID *id, FModifier *fcm, s
/* draw polynomial order selector */
row = uiLayoutRow(layout, false);
block = uiLayoutGetBlock(row);
- but = uiDefButI(block, NUM, B_FMODIFIER_REDRAW, IFACE_("Poly Order:"), 0, 0, width - 1.5 * UI_UNIT_X, UI_UNIT_Y,
+ but = uiDefButI(block, UI_BTYPE_NUM, B_FMODIFIER_REDRAW, IFACE_("Poly Order:"), 0, 0, width - 1.5 * UI_UNIT_X, UI_UNIT_Y,
&data->poly_order, 1, 100, 0, 0,
TIP_("'Order' of the Polynomial (for a polynomial with n terms, 'order' is n-1)"));
- uiButSetFunc(but, validate_fmodifier_cb, fcm, NULL);
+ UI_but_func_set(but, validate_fmodifier_cb, fcm, NULL);
/* draw controls for each pair of coefficients */
@@ -216,31 +218,31 @@ static void draw_modifier__generator(uiLayout *layout, ID *id, FModifier *fcm, s
for (i = 0; (i < data->poly_order) && (cp); i++, cp += 2) {
/* To align with first line */
if (i)
- uiDefBut(block, LABEL, 1, " ", 0, 0, 2.5 * UI_UNIT_X, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
+ uiDefBut(block, UI_BTYPE_LABEL, 1, " ", 0, 0, 2.5 * UI_UNIT_X, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
else
- uiDefBut(block, LABEL, 1, "y =", 0, 0, 2.5 * UI_UNIT_X, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
+ uiDefBut(block, UI_BTYPE_LABEL, 1, "y =", 0, 0, 2.5 * UI_UNIT_X, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
/* opening bracket */
- uiDefBut(block, LABEL, 1, "(", 0, 0, UI_UNIT_X, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
+ uiDefBut(block, UI_BTYPE_LABEL, 1, "(", 0, 0, UI_UNIT_X, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
/* coefficients */
- uiDefButF(block, NUM, B_FMODIFIER_REDRAW, "", 0, 0, 5 * UI_UNIT_X, UI_UNIT_Y, cp, -UI_FLT_MAX, UI_FLT_MAX,
+ uiDefButF(block, UI_BTYPE_NUM, B_FMODIFIER_REDRAW, "", 0, 0, 5 * UI_UNIT_X, UI_UNIT_Y, cp, -UI_FLT_MAX, UI_FLT_MAX,
10, 3, TIP_("Coefficient of x"));
- uiDefBut(block, LABEL, 1, "x +", 0, 0, 2 * UI_UNIT_X, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
+ uiDefBut(block, UI_BTYPE_LABEL, 1, "x +", 0, 0, 2 * UI_UNIT_X, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
- uiDefButF(block, NUM, B_FMODIFIER_REDRAW, "", 0, 0, 5 * UI_UNIT_X, UI_UNIT_Y, cp + 1, -UI_FLT_MAX, UI_FLT_MAX,
+ uiDefButF(block, UI_BTYPE_NUM, B_FMODIFIER_REDRAW, "", 0, 0, 5 * UI_UNIT_X, UI_UNIT_Y, cp + 1, -UI_FLT_MAX, UI_FLT_MAX,
10, 3, TIP_("Second coefficient"));
/* closing bracket and multiplication sign */
if ( (i != (data->poly_order - 1)) || ((i == 0) && data->poly_order == 2) ) {
- uiDefBut(block, LABEL, 1, ") \xc3\x97", 0, 0, 2 * UI_UNIT_X, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
+ uiDefBut(block, UI_BTYPE_LABEL, 1, ") \xc3\x97", 0, 0, 2 * UI_UNIT_X, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
/* set up new row for the next pair of coefficients */
row = uiLayoutRow(layout, true);
block = uiLayoutGetBlock(row);
}
else
- uiDefBut(block, LABEL, 1, ") ", 0, 0, 2 * UI_UNIT_X, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
+ uiDefBut(block, UI_BTYPE_LABEL, 1, ") ", 0, 0, 2 * UI_UNIT_X, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
}
break;
}
@@ -439,11 +441,11 @@ static void draw_modifier__envelope(uiLayout *layout, ID *id, FModifier *fcm, sh
row = uiLayoutRow(layout, false);
block = uiLayoutGetBlock(row);
- uiDefBut(block, LABEL, 1, IFACE_("Control Points:"), 0, 0, 7.5 * UI_UNIT_X, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
+ uiDefBut(block, UI_BTYPE_LABEL, 1, IFACE_("Control Points:"), 0, 0, 7.5 * UI_UNIT_X, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
- but = uiDefBut(block, BUT, B_FMODIFIER_REDRAW, IFACE_("Add Point"), 0, 0, 7.5 * UI_UNIT_X, UI_UNIT_Y,
+ but = uiDefBut(block, UI_BTYPE_BUT, B_FMODIFIER_REDRAW, IFACE_("Add Point"), 0, 0, 7.5 * UI_UNIT_X, UI_UNIT_Y,
NULL, 0, 0, 0, 0, TIP_("Add a new control-point to the envelope on the current frame"));
- uiButSetFunc(but, fmod_envelope_addpoint_cb, env, NULL);
+ UI_but_func_set(but, fmod_envelope_addpoint_cb, env, NULL);
/* control points list */
for (i = 0, fed = env->data; i < env->totvert; i++, fed++) {
@@ -451,20 +453,20 @@ static void draw_modifier__envelope(uiLayout *layout, ID *id, FModifier *fcm, sh
row = uiLayoutRow(layout, true);
block = uiLayoutGetBlock(row);
- uiBlockBeginAlign(block);
- but = uiDefButF(block, NUM, B_FMODIFIER_REDRAW, IFACE_("Fra:"), 0, 0, 4.5 * UI_UNIT_X, UI_UNIT_Y,
+ UI_block_align_begin(block);
+ but = uiDefButF(block, UI_BTYPE_NUM, B_FMODIFIER_REDRAW, IFACE_("Fra:"), 0, 0, 4.5 * UI_UNIT_X, UI_UNIT_Y,
&fed->time, -MAXFRAMEF, MAXFRAMEF, 10, 1, TIP_("Frame that envelope point occurs"));
- uiButSetFunc(but, validate_fmodifier_cb, fcm, NULL);
+ UI_but_func_set(but, validate_fmodifier_cb, fcm, NULL);
- uiDefButF(block, NUM, B_FMODIFIER_REDRAW, IFACE_("Min:"), 0, 0, 5 * UI_UNIT_X, UI_UNIT_Y,
+ uiDefButF(block, UI_BTYPE_NUM, B_FMODIFIER_REDRAW, IFACE_("Min:"), 0, 0, 5 * UI_UNIT_X, UI_UNIT_Y,
&fed->min, -UI_FLT_MAX, UI_FLT_MAX, 10, 2, TIP_("Minimum bound of envelope at this point"));
- uiDefButF(block, NUM, B_FMODIFIER_REDRAW, IFACE_("Max:"), 0, 0, 5 * UI_UNIT_X, UI_UNIT_Y,
+ uiDefButF(block, UI_BTYPE_NUM, B_FMODIFIER_REDRAW, IFACE_("Max:"), 0, 0, 5 * UI_UNIT_X, UI_UNIT_Y,
&fed->max, -UI_FLT_MAX, UI_FLT_MAX, 10, 2, TIP_("Maximum bound of envelope at this point"));
- but = uiDefIconBut(block, BUT, B_FMODIFIER_REDRAW, ICON_X, 0, 0, 0.9 * UI_UNIT_X, UI_UNIT_Y,
+ but = uiDefIconBut(block, UI_BTYPE_BUT, B_FMODIFIER_REDRAW, ICON_X, 0, 0, 0.9 * UI_UNIT_X, UI_UNIT_Y,
NULL, 0.0, 0.0, 0.0, 0.0, TIP_("Delete envelope control point"));
- uiButSetFunc(but, fmod_envelope_deletepoint_cb, env, SET_INT_IN_POINTER(i));
- uiBlockBeginAlign(block);
+ UI_but_func_set(but, fmod_envelope_deletepoint_cb, env, SET_INT_IN_POINTER(i));
+ UI_block_align_begin(block);
}
}
@@ -553,7 +555,7 @@ static void draw_modifier__stepped(uiLayout *layout, ID *id, FModifier *fcm, sho
void ANIM_uiTemplate_fmodifier_draw(uiLayout *layout, ID *id, ListBase *modifiers, FModifier *fcm)
{
- FModifierTypeInfo *fmi = fmodifier_get_typeinfo(fcm);
+ const FModifierTypeInfo *fmi = fmodifier_get_typeinfo(fcm);
uiLayout *box, *row, *sub, *col;
uiBlock *block;
uiBut *but;
@@ -575,7 +577,7 @@ void ANIM_uiTemplate_fmodifier_draw(uiLayout *layout, ID *id, ListBase *modifier
sub = uiLayoutRow(row, true);
uiLayoutSetAlignment(sub, UI_LAYOUT_ALIGN_LEFT);
- uiBlockSetEmboss(block, UI_EMBOSSN);
+ UI_block_emboss_set(block, UI_EMBOSS_NONE);
/* expand */
uiItemR(sub, &ptr, "show_expanded", UI_ITEM_R_ICON_ONLY, "", ICON_NONE);
@@ -597,14 +599,14 @@ void ANIM_uiTemplate_fmodifier_draw(uiLayout *layout, ID *id, ListBase *modifier
/* 'mute' button */
uiItemR(sub, &ptr, "mute", UI_ITEM_R_ICON_ONLY, "", ICON_NONE);
- uiBlockSetEmboss(block, UI_EMBOSSN);
+ UI_block_emboss_set(block, UI_EMBOSS_NONE);
/* delete button */
- but = uiDefIconBut(block, BUT, B_REDR, ICON_X, 0, 0, UI_UNIT_X, UI_UNIT_Y,
+ but = uiDefIconBut(block, UI_BTYPE_BUT, B_REDR, ICON_X, 0, 0, UI_UNIT_X, UI_UNIT_Y,
NULL, 0.0, 0.0, 0.0, 0.0, TIP_("Delete F-Curve Modifier"));
- uiButSetFunc(but, delete_fmodifier_cb, modifiers, fcm);
+ UI_but_func_set(but, delete_fmodifier_cb, modifiers, fcm);
- uiBlockSetEmboss(block, UI_EMBOSS);
+ UI_block_emboss_set(block, UI_EMBOSS);
}
/* when modifier is expanded, draw settings */
diff --git a/source/blender/editors/animation/keyframes_draw.c b/source/blender/editors/animation/keyframes_draw.c
index c5e54cc1c7c..6f1883cff55 100644
--- a/source/blender/editors/animation/keyframes_draw.c
+++ b/source/blender/editors/animation/keyframes_draw.c
@@ -39,7 +39,6 @@
#include "MEM_guardedalloc.h"
-#include "BLI_blenlib.h"
#include "BLI_dlrbTree.h"
#include "BLI_utildefines.h"
@@ -106,7 +105,7 @@ static DLRBT_Node *nalloc_ak_bezt(void *data)
/* store settings based on state of BezTriple */
ak->cfra = bezt->vec[1][0];
- ak->sel = BEZSELECTED(bezt) ? SELECT : 0;
+ ak->sel = BEZT_ISSEL_ANY(bezt) ? SELECT : 0;
ak->key_type = BEZKEYTYPE(bezt);
/* set 'modified', since this is used to identify long keyframes */
@@ -122,7 +121,7 @@ static void nupdate_ak_bezt(void *node, void *data)
BezTriple *bezt = (BezTriple *)data;
/* set selection status and 'touched' status */
- if (BEZSELECTED(bezt)) ak->sel = SELECT;
+ if (BEZT_ISSEL_ANY(bezt)) ak->sel = SELECT;
ak->modified += 1;
/* for keyframe type, 'proper' keyframes have priority over breakdowns (and other types for now) */
@@ -155,6 +154,7 @@ static DLRBT_Node *nalloc_ak_gpframe(void *data)
/* store settings based on state of BezTriple */
ak->cfra = gpf->framenum;
ak->sel = (gpf->flag & GP_FRAME_SELECT) ? SELECT : 0;
+ ak->key_type = gpf->key_type;
/* set 'modified', since this is used to identify long keyframes */
ak->modified = 1;
@@ -171,6 +171,10 @@ static void nupdate_ak_gpframe(void *node, void *data)
/* set selection status and 'touched' status */
if (gpf->flag & GP_FRAME_SELECT) ak->sel = SELECT;
ak->modified += 1;
+
+ /* for keyframe type, 'proper' keyframes have priority over breakdowns (and other types for now) */
+ if (gpf->key_type == BEZT_KEYTYPE_KEYFRAME)
+ ak->key_type = BEZT_KEYTYPE_KEYFRAME;
}
/* ......... */
@@ -275,7 +279,7 @@ static ActKeyBlock *bezts_to_new_actkeyblock(BezTriple *prev, BezTriple *beztn)
ab->end = beztn->vec[1][0];
ab->val = beztn->vec[1][1];
- ab->sel = (BEZSELECTED(prev) || BEZSELECTED(beztn)) ? SELECT : 0;
+ ab->sel = (BEZT_ISSEL_ANY(prev) || BEZT_ISSEL_ANY(beztn)) ? SELECT : 0;
ab->modified = 1;
return ab;
@@ -336,7 +340,7 @@ static void add_bezt_to_keyblocks_list(DLRBT_Tree *blocks, BezTriple *first_bezt
*/
if (IS_EQT(ab->start, prev->vec[1][0], BEZT_BINARYSEARCH_THRESH)) {
/* set selection status and 'touched' status */
- if (BEZSELECTED(beztn)) ab->sel = SELECT;
+ if (BEZT_ISSEL_ANY(beztn)) ab->sel = SELECT;
ab->modified++;
/* done... no need to insert */
@@ -524,7 +528,7 @@ void draw_keyframe_shape(float x, float y, float xscale, float hsize, short sel,
}
/* NOTE: we don't use the straight alpha from the theme, or else effects such as
- * greying out protected/muted channels doesn't work correctly!
+ * graying out protected/muted channels doesn't work correctly!
*/
inner_col[3] *= alpha;
glColor4fv(inner_col);
@@ -732,6 +736,21 @@ void draw_action_channel(View2D *v2d, AnimData *adt, bAction *act, float ypos)
BLI_dlrbTree_free(&blocks);
}
+void draw_gpencil_channel(View2D *v2d, bDopeSheet *ads, bGPdata *gpd, float ypos)
+{
+ DLRBT_Tree keys;
+
+ BLI_dlrbTree_init(&keys);
+
+ gpencil_to_keylist(ads, gpd, &keys);
+
+ BLI_dlrbTree_linkedlist_sync(&keys);
+
+ draw_keylist(v2d, &keys, NULL, ypos, 0);
+
+ BLI_dlrbTree_free(&keys);
+}
+
void draw_gpl_channel(View2D *v2d, bDopeSheet *ads, bGPDlayer *gpl, float ypos)
{
DLRBT_Tree keys;
@@ -924,6 +943,20 @@ void action_to_keylist(AnimData *adt, bAction *act, DLRBT_Tree *keys, DLRBT_Tree
}
+void gpencil_to_keylist(bDopeSheet *ads, bGPdata *gpd, DLRBT_Tree *keys)
+{
+ bGPDlayer *gpl;
+
+ if (gpd && keys) {
+ /* for now, just aggregate out all the frames, but only for visible layers */
+ for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ if ((gpl->flag & GP_LAYER_HIDE) == 0) {
+ gpl_to_keylist(ads, gpl, keys);
+ }
+ }
+ }
+}
+
void gpl_to_keylist(bDopeSheet *UNUSED(ads), bGPDlayer *gpl, DLRBT_Tree *keys)
{
bGPDframe *gpf;
diff --git a/source/blender/editors/animation/keyframes_edit.c b/source/blender/editors/animation/keyframes_edit.c
index 83593faff22..bd34f32dda8 100644
--- a/source/blender/editors/animation/keyframes_edit.c
+++ b/source/blender/editors/animation/keyframes_edit.c
@@ -41,9 +41,7 @@
#include "DNA_anim_types.h"
#include "DNA_object_types.h"
-#include "DNA_node_types.h"
#include "DNA_scene_types.h"
-#include "DNA_space_types.h"
#include "BKE_fcurve.h"
@@ -457,7 +455,7 @@ static short ok_bezier_selected(KeyframeEditData *UNUSED(ked), BezTriple *bezt)
/* this macro checks all beztriple handles for selection...
* only one of the verts has to be selected for this to be ok...
*/
- if (BEZSELECTED(bezt))
+ if (BEZT_ISSEL_ANY(bezt))
return KEYFRAME_OK_ALL;
else
return 0;
@@ -548,6 +546,44 @@ static short ok_bezier_region_lasso(KeyframeEditData *ked, BezTriple *bezt)
return 0;
}
+/**
+ * only called from #ok_bezier_region_circle
+ */
+static bool bezier_region_circle_test(
+ const struct KeyframeEdit_CircleData *data_circle,
+ const float xy[2])
+{
+ if (BLI_rctf_isect_pt_v(data_circle->rectf_scaled, xy)) {
+ float xy_view[2];
+
+ BLI_rctf_transform_pt_v(data_circle->rectf_view, data_circle->rectf_scaled, xy_view, xy);
+
+ xy_view[0] = xy_view[0] - data_circle->mval[0];
+ xy_view[1] = xy_view[1] - data_circle->mval[1];
+ return len_squared_v2(xy_view) < data_circle->radius_squared;
+ }
+
+ return false;
+}
+
+
+static short ok_bezier_region_circle(KeyframeEditData *ked, BezTriple *bezt)
+{
+ /* rect is stored in data property (it's of type rectf, but may not be set) */
+ if (ked->data) {
+ short ok = 0;
+
+#define KEY_CHECK_OK(_index) bezier_region_circle_test(ked->data, bezt->vec[_index])
+ KEYFRAME_OK_CHECKS(KEY_CHECK_OK);
+#undef KEY_CHECK_OK
+
+ /* return ok flags */
+ return ok;
+ }
+ else
+ return 0;
+}
+
KeyframeEditFunc ANIM_editkeyframes_ok(short mode)
{
@@ -567,6 +603,8 @@ KeyframeEditFunc ANIM_editkeyframes_ok(short mode)
return ok_bezier_region;
case BEZT_OK_REGION_LASSO: /* only if the point falls within KeyframeEdit_LassoData defined data */
return ok_bezier_region_lasso;
+ case BEZT_OK_REGION_CIRCLE: /* only if the point falls within KeyframeEdit_LassoData defined data */
+ return ok_bezier_region_circle;
default: /* nothing was ok */
return NULL;
}
@@ -643,7 +681,7 @@ static short snap_bezier_nearestsec(KeyframeEditData *ked, BezTriple *bezt)
const float secf = (float)FPS;
if (bezt->f2 & SELECT)
- bezt->vec[1][0] = ((float)floor(bezt->vec[1][0] / secf + 0.5f) * secf);
+ bezt->vec[1][0] = (floorf(bezt->vec[1][0] / secf + 0.5f) * secf);
return 0;
}
@@ -747,7 +785,8 @@ static short mirror_bezier_cframe(KeyframeEditData *ked, BezTriple *bezt)
static short mirror_bezier_yaxis(KeyframeEditData *UNUSED(ked), BezTriple *bezt)
{
if (bezt->f2 & SELECT) {
- mirror_bezier_yaxis_ex(bezt, 0.0f);
+ /* Yes, names are inverted, we are mirroring accross y axis, hence along x axis... */
+ mirror_bezier_xaxis_ex(bezt, 0.0f);
}
return 0;
@@ -756,7 +795,8 @@ static short mirror_bezier_yaxis(KeyframeEditData *UNUSED(ked), BezTriple *bezt)
static short mirror_bezier_xaxis(KeyframeEditData *UNUSED(ked), BezTriple *bezt)
{
if (bezt->f2 & SELECT) {
- mirror_bezier_xaxis_ex(bezt, 0.0f);
+ /* Yes, names are inverted, we are mirroring accross x axis, hence along y axis... */
+ mirror_bezier_yaxis_ex(bezt, 0.0f);
}
return 0;
@@ -776,7 +816,7 @@ static short mirror_bezier_value(KeyframeEditData *ked, BezTriple *bezt)
{
/* value to mirror over is stored in the custom data -> first float value slot */
if (bezt->f2 & SELECT) {
- mirror_bezier_xaxis_ex(bezt, ked->f1);
+ mirror_bezier_yaxis_ex(bezt, ked->f1);
}
return 0;
@@ -1141,7 +1181,7 @@ static short select_bezier_add(KeyframeEditData *ked, BezTriple *bezt)
bezt->f3 |= SELECT;
}
else {
- BEZ_SEL(bezt);
+ BEZT_SEL_ALL(bezt);
}
return 0;
@@ -1159,7 +1199,7 @@ static short select_bezier_subtract(KeyframeEditData *ked, BezTriple *bezt)
bezt->f3 &= ~SELECT;
}
else {
- BEZ_DESEL(bezt);
+ BEZT_DESEL_ALL(bezt);
}
return 0;
@@ -1212,7 +1252,7 @@ static short selmap_build_bezier_more(KeyframeEditData *ked, BezTriple *bezt)
int i = ked->curIndex;
/* if current is selected, just make sure it stays this way */
- if (BEZSELECTED(bezt)) {
+ if (BEZT_ISSEL_ANY(bezt)) {
map[i] = 1;
return 0;
}
@@ -1221,7 +1261,7 @@ static short selmap_build_bezier_more(KeyframeEditData *ked, BezTriple *bezt)
if (i > 0) {
BezTriple *prev = bezt - 1;
- if (BEZSELECTED(prev)) {
+ if (BEZT_ISSEL_ANY(prev)) {
map[i] = 1;
return 0;
}
@@ -1231,7 +1271,7 @@ static short selmap_build_bezier_more(KeyframeEditData *ked, BezTriple *bezt)
if (i < (fcu->totvert - 1)) {
BezTriple *next = bezt + 1;
- if (BEZSELECTED(next)) {
+ if (BEZT_ISSEL_ANY(next)) {
map[i] = 1;
return 0;
}
@@ -1249,12 +1289,12 @@ static short selmap_build_bezier_less(KeyframeEditData *ked, BezTriple *bezt)
/* if current is selected, check the left/right keyframes
* since it might need to be deselected (but otherwise no)
*/
- if (BEZSELECTED(bezt)) {
+ if (BEZT_ISSEL_ANY(bezt)) {
/* if previous is not selected, we're on the tip of an iceberg */
if (i > 0) {
BezTriple *prev = bezt - 1;
- if (BEZSELECTED(prev) == 0)
+ if (BEZT_ISSEL_ANY(prev) == 0)
return 0;
}
else if (i == 0) {
@@ -1266,7 +1306,7 @@ static short selmap_build_bezier_less(KeyframeEditData *ked, BezTriple *bezt)
if (i < (fcu->totvert - 1)) {
BezTriple *next = bezt + 1;
- if (BEZSELECTED(next) == 0)
+ if (BEZT_ISSEL_ANY(next) == 0)
return 0;
}
else if (i == (fcu->totvert - 1)) {
@@ -1304,10 +1344,10 @@ short bezt_selmap_flush(KeyframeEditData *ked, BezTriple *bezt)
/* select or deselect based on whether the map allows it or not */
if (on) {
- BEZ_SEL(bezt);
+ BEZT_SEL_ALL(bezt);
}
else {
- BEZ_DESEL(bezt);
+ BEZT_DESEL_ALL(bezt);
}
return 0;
diff --git a/source/blender/editors/animation/keyframes_general.c b/source/blender/editors/animation/keyframes_general.c
index 56165c36efa..3642c07b758 100644
--- a/source/blender/editors/animation/keyframes_general.c
+++ b/source/blender/editors/animation/keyframes_general.c
@@ -43,13 +43,14 @@
#include "DNA_scene_types.h"
+#include "BKE_action.h"
#include "BKE_fcurve.h"
#include "BKE_report.h"
#include "BKE_library.h"
#include "BKE_global.h"
+#include "BKE_deform.h"
#include "RNA_access.h"
-#include "RNA_enum_types.h"
#include "ED_anim_api.h"
#include "ED_keyframing.h"
@@ -166,11 +167,11 @@ void duplicate_fcurve_keys(FCurve *fcu)
fcu->bezt = newbezt;
/* Unselect the current key */
- BEZ_DESEL(&fcu->bezt[i]);
+ BEZT_DESEL_ALL(&fcu->bezt[i]);
i++;
/* Select the copied key */
- BEZ_SEL(&fcu->bezt[i]);
+ BEZT_SEL_ALL(&fcu->bezt[i]);
}
}
}
@@ -178,17 +179,22 @@ void duplicate_fcurve_keys(FCurve *fcu)
/* **************************************************** */
/* Various Tools */
-/* Basic F-Curve 'cleanup' function that removes 'double points' and unnecessary keyframes on linear-segments only */
-void clean_fcurve(FCurve *fcu, float thresh)
+/* Basic F-Curve 'cleanup' function that removes 'double points' and unnecessary keyframes on linear-segments only
+ * optionally clears up curve if one keyframe with default value remains */
+void clean_fcurve(struct bAnimContext *ac, bAnimListElem *ale, float thresh, bool cleardefault)
{
+ FCurve *fcu = (FCurve *)ale->key_data;
BezTriple *old_bezts, *bezt, *beztn;
BezTriple *lastb;
int totCount, i;
/* check if any points */
- if ((fcu == NULL) || (fcu->bezt == NULL) || (fcu->totvert <= 1))
+ if ((fcu == NULL) || (fcu->bezt == NULL) || (fcu->totvert == 0) ||
+ (!cleardefault && fcu->totvert == 1))
+ {
return;
-
+ }
+
/* make a copy of the old BezTriples, and clear F-Curve */
old_bezts = fcu->bezt;
totCount = fcu->totvert;
@@ -198,13 +204,17 @@ void clean_fcurve(FCurve *fcu, float thresh)
/* now insert first keyframe, as it should be ok */
bezt = old_bezts;
insert_vert_fcurve(fcu, bezt->vec[1][0], bezt->vec[1][1], 0);
+ if (!(bezt->f2 & SELECT)) {
+ lastb = fcu->bezt;
+ lastb->f1 = lastb->f2 = lastb->f3 = 0;
+ }
/* Loop through BezTriples, comparing them. Skip any that do
* not fit the criteria for "ok" points.
*/
for (i = 1; i < totCount; i++) {
float prev[2], cur[2], next[2];
-
+
/* get BezTriples and their values */
if (i < (totCount - 1)) {
beztn = (old_bezts + (i + 1));
@@ -216,10 +226,17 @@ void clean_fcurve(FCurve *fcu, float thresh)
}
lastb = (fcu->bezt + (fcu->totvert - 1));
bezt = (old_bezts + i);
-
+
/* get references for quicker access */
prev[0] = lastb->vec[1][0]; prev[1] = lastb->vec[1][1];
cur[0] = bezt->vec[1][0]; cur[1] = bezt->vec[1][1];
+
+ if (!(bezt->f2 & SELECT)) {
+ insert_vert_fcurve(fcu, cur[0], cur[1], 0);
+ lastb = (fcu->bezt + (fcu->totvert - 1));
+ lastb->f1 = lastb->f2 = lastb->f3 = 0;
+ continue;
+ }
/* check if current bezt occurs at same time as last ok */
if (IS_EQT(cur[0], prev[0], thresh)) {
@@ -227,7 +244,7 @@ void clean_fcurve(FCurve *fcu, float thresh)
* if there is a considerable distance between the points, and also if the
* current is further away than the next one is to the previous.
*/
- if (beztn && (IS_EQT(cur[0], next[0], thresh)) &&
+ if (beztn && (IS_EQT(cur[0], next[0], thresh)) &&
(IS_EQT(next[1], prev[1], thresh) == 0))
{
/* only add if current is further away from previous */
@@ -272,6 +289,34 @@ void clean_fcurve(FCurve *fcu, float thresh)
/* now free the memory used by the old BezTriples */
if (old_bezts)
MEM_freeN(old_bezts);
+
+ /* final step, if there is just one key in fcurve, check if it's
+ * the default value and if is, remove fcurve completely. */
+ if (cleardefault && fcu->totvert == 1) {
+ float default_value = 0.0f;
+ PointerRNA id_ptr, ptr;
+ PropertyRNA *prop;
+ RNA_id_pointer_create(ale->id, &id_ptr);
+
+ /* get property to read from, and get value as appropriate */
+ if (RNA_path_resolve_property(&id_ptr, fcu->rna_path, &ptr, &prop)) {
+ if (RNA_property_type(prop) == PROP_FLOAT)
+ default_value = RNA_property_float_get_default_index(&ptr, prop, fcu->array_index);
+ }
+
+ if (fcu->bezt->vec[1][1] == default_value) {
+ clear_fcurve_keys(fcu);
+
+ /* check if curve is really unused and if it is, return signal for deletion */
+ if ((list_has_suitable_fmodifier(&fcu->modifiers, 0, FMI_TYPE_GENERATE_CURVE) == 0) &&
+ (fcu->driver == NULL))
+ {
+ AnimData *adt = ale->adt;
+ ANIM_fcurve_delete_from_animdata(ac, adt, fcu);
+ ale->key_data = NULL;
+ }
+ }
+ }
}
/* ---------------- */
@@ -296,7 +341,7 @@ void smooth_fcurve(FCurve *fcu)
/* first loop through - count how many verts are selected */
bezt = fcu->bezt;
for (i = 0; i < fcu->totvert; i++, bezt++) {
- if (BEZSELECTED(bezt))
+ if (BEZT_ISSEL_ANY(bezt))
totSel++;
}
@@ -310,7 +355,7 @@ void smooth_fcurve(FCurve *fcu)
/* populate tarray with data of selected points */
bezt = fcu->bezt;
for (i = 0, x = 0; (i < fcu->totvert) && (x < totSel); i++, bezt++) {
- if (BEZSELECTED(bezt)) {
+ if (BEZT_ISSEL_ANY(bezt)) {
/* tsb simply needs pointer to vec, and index */
tsb->h1 = &bezt->vec[0][1];
tsb->h2 = &bezt->vec[1][1];
@@ -399,7 +444,7 @@ void sample_fcurve(FCurve *fcu)
/* find selected keyframes... once pair has been found, add keyframes */
for (i = 0, bezt = fcu->bezt; i < fcu->totvert; i++, bezt++) {
/* check if selected, and which end this is */
- if (BEZSELECTED(bezt)) {
+ if (BEZT_ISSEL_ANY(bezt)) {
if (start) {
/* set end */
end = bezt;
@@ -478,6 +523,7 @@ typedef struct tAnimCopybufItem {
BezTriple *bezt; /* keyframes in buffer */
short id_type; /* Result of GS(id->name)*/
+ bool is_bone; /* special flag for armature bones */
} tAnimCopybufItem;
@@ -541,13 +587,29 @@ short copy_animedit_keys(bAnimContext *ac, ListBase *anim_data)
aci->grp = fcu->grp;
aci->rna_path = MEM_dupallocN(fcu->rna_path);
aci->array_index = fcu->array_index;
+
+ /* detect if this is a bone. We do that here rather than during pasting because ID pointers will get invalidated if we undo.
+ * storing the relevant information here helps avoiding crashes if we undo-repaste */
+ if ((aci->id_type == ID_OB) && (((Object *)aci->id)->type == OB_ARMATURE) && aci->rna_path) {
+ Object *ob = (Object *)aci->id;
+ bPoseChannel *pchan;
+ char *bone_name;
+
+ bone_name = BLI_str_quoted_substrN(aci->rna_path, "pose.bones[");
+ pchan = BKE_pose_channel_find_name(ob->pose, bone_name);
+ if (pchan) {
+ aci->is_bone = true;
+ }
+ if (bone_name) MEM_freeN(bone_name);
+ }
+
BLI_addtail(&animcopybuf, aci);
/* add selected keyframes to buffer */
/* TODO: currently, we resize array every time we add a new vert -
* this works ok as long as it is assumed only a few keys are copied */
for (i = 0, bezt = fcu->bezt; i < fcu->totvert; i++, bezt++) {
- if (BEZSELECTED(bezt)) {
+ if (BEZT_ISSEL_ANY(bezt)) {
/* add to buffer */
newbuf = MEM_callocN(sizeof(BezTriple) * (aci->totvert + 1), "copybuf beztriple");
@@ -560,7 +622,7 @@ short copy_animedit_keys(bAnimContext *ac, ListBase *anim_data)
*nbezt = *bezt;
/* ensure copy buffer is selected so pasted keys are selected */
- BEZ_SEL(nbezt);
+ BEZT_SEL_ALL(nbezt);
/* free old array and set the new */
if (aci->bezt) MEM_freeN(aci->bezt);
@@ -588,19 +650,65 @@ short copy_animedit_keys(bAnimContext *ac, ListBase *anim_data)
return 0;
}
+static void flip_names(tAnimCopybufItem *aci, char **name)
+{
+ if (aci->is_bone) {
+ char *str_start;
+ if ((str_start = strstr(aci->rna_path, "pose.bones["))) {
+ /* ninja coding, try to change the name */
+ char bname_new[MAX_VGROUP_NAME];
+ char *str_iter, *str_end;
+ int length, prefix_l, postfix_l;
+
+ str_start += 12;
+ prefix_l = str_start - aci->rna_path;
+
+ str_end = strchr(str_start, '\"');
+
+ length = str_end - str_start;
+ postfix_l = strlen(str_end);
+
+ /* more ninja stuff, temporary substitute with NULL terminator */
+ str_start[length] = 0;
+ BKE_deform_flip_side_name(bname_new, str_start, false);
+ str_start[length] = '\"';
+
+ str_iter = *name = MEM_mallocN(sizeof(char) * (prefix_l + postfix_l + length + 1), "flipped_path");
+
+ BLI_strncpy(str_iter, aci->rna_path, prefix_l + 1);
+ str_iter += prefix_l;
+ BLI_strncpy(str_iter, bname_new, length + 1);
+ str_iter += length;
+ BLI_strncpy(str_iter, str_end, postfix_l + 1);
+ str_iter[postfix_l] = '\0';
+ }
+ }
+}
+
/* ------------------- */
/* most strict method: exact matches only */
-static tAnimCopybufItem *pastebuf_match_path_full(FCurve *fcu, const short from_single, const short to_simple)
+static tAnimCopybufItem *pastebuf_match_path_full(FCurve *fcu, const short from_single, const short to_simple, bool flip)
{
tAnimCopybufItem *aci;
for (aci = animcopybuf.first; aci; aci = aci->next) {
- /* check that paths exist */
if (to_simple || (aci->rna_path && fcu->rna_path)) {
- if (to_simple || (strcmp(aci->rna_path, fcu->rna_path) == 0)) {
- if ((from_single) || (aci->array_index == fcu->array_index))
+ if (!to_simple && flip && aci->is_bone && fcu->rna_path) {
+ if ((from_single) || (aci->array_index == fcu->array_index)) {
+ char *name = NULL;
+ flip_names(aci, &name);
+ if (STREQ(name, fcu->rna_path)) {
+ MEM_freeN(name);
+ break;
+ }
+ MEM_freeN(name);
+ }
+ }
+ else if (to_simple || STREQ(aci->rna_path, fcu->rna_path)) {
+ if ((from_single) || (aci->array_index == fcu->array_index)) {
break;
+ }
}
}
}
@@ -638,7 +746,7 @@ static tAnimCopybufItem *pastebuf_match_path_property(FCurve *fcu, const short f
int len_path = strlen(fcu->rna_path);
if (len_id <= len_path) {
/* note, paths which end with "] will fail with this test - Animated ID Props */
- if (strcmp(identifier, fcu->rna_path + (len_path - len_id)) == 0) {
+ if (STREQ(identifier, fcu->rna_path + (len_path - len_id))) {
if ((from_single) || (aci->array_index == fcu->array_index))
break;
}
@@ -671,15 +779,37 @@ static tAnimCopybufItem *pastebuf_match_index_only(FCurve *fcu, const short from
/* ................ */
+static void do_curve_mirror_flippping(tAnimCopybufItem *aci, BezTriple *bezt)
+{
+ if (aci->is_bone) {
+ const size_t slength = strlen(aci->rna_path);
+ bool flip = false;
+ if (BLI_strn_endswith(aci->rna_path, "location", slength) && aci->array_index == 0)
+ flip = true;
+ else if (BLI_strn_endswith(aci->rna_path, "rotation_quaternion", slength) && ELEM(aci->array_index, 2, 3))
+ flip = true;
+ else if (BLI_strn_endswith(aci->rna_path, "rotation_euler", slength) && ELEM(aci->array_index, 1, 2))
+ flip = true;
+ else if (BLI_strn_endswith(aci->rna_path, "rotation_axis_angle", slength) && ELEM(aci->array_index, 2, 3))
+ flip = true;
+
+ if (flip) {
+ bezt->vec[0][1] = -bezt->vec[0][1];
+ bezt->vec[1][1] = -bezt->vec[1][1];
+ bezt->vec[2][1] = -bezt->vec[2][1];
+ }
+ }
+}
+
/* helper for paste_animedit_keys() - performs the actual pasting */
-static void paste_animedit_keys_fcurve(FCurve *fcu, tAnimCopybufItem *aci, float offset, const eKeyMergeMode merge_mode)
+static void paste_animedit_keys_fcurve(FCurve *fcu, tAnimCopybufItem *aci, float offset, const eKeyMergeMode merge_mode, bool flip)
{
BezTriple *bezt;
int i;
/* First de-select existing FCurve's keyframes */
for (i = 0, bezt = fcu->bezt; i < fcu->totvert; i++, bezt++) {
- bezt->f2 &= ~SELECT;
+ BEZT_DESEL_ALL(bezt);
}
/* mix mode with existing data */
@@ -724,9 +854,12 @@ static void paste_animedit_keys_fcurve(FCurve *fcu, tAnimCopybufItem *aci, float
}
}
- /* just start pasting, with the the first keyframe on the current frame, and so on */
+ /* just start pasting, with the first keyframe on the current frame, and so on */
for (i = 0, bezt = aci->bezt; i < aci->totvert; i++, bezt++) {
/* temporarily apply offset to src beztriple while copying */
+ if (flip)
+ do_curve_mirror_flippping(aci, bezt);
+
bezt->vec[0][0] += offset;
bezt->vec[1][0] += offset;
bezt->vec[2][0] += offset;
@@ -734,12 +867,16 @@ static void paste_animedit_keys_fcurve(FCurve *fcu, tAnimCopybufItem *aci, float
/* insert the keyframe
* NOTE: we do not want to inherit handles from existing keyframes in this case!
*/
+
insert_bezt_fcurve(fcu, bezt, INSERTKEY_OVERWRITE_FULL);
/* un-apply offset from src beztriple after copying */
bezt->vec[0][0] -= offset;
bezt->vec[1][0] -= offset;
bezt->vec[2][0] -= offset;
+
+ if (flip)
+ do_curve_mirror_flippping(aci, bezt);
}
/* recalculate F-Curve's handles? */
@@ -769,7 +906,7 @@ EnumPropertyItem keyframe_paste_merge_items[] = {
* \return Status code is whether the method FAILED to do anything
*/
short paste_animedit_keys(bAnimContext *ac, ListBase *anim_data,
- const eKeyPasteOffset offset_mode, const eKeyMergeMode merge_mode)
+ const eKeyPasteOffset offset_mode, const eKeyMergeMode merge_mode, bool flip)
{
bAnimListElem *ale;
@@ -817,7 +954,7 @@ short paste_animedit_keys(bAnimContext *ac, ListBase *anim_data,
fcu = (FCurve *)ale->data; /* destination F-Curve */
aci = animcopybuf.first;
- paste_animedit_keys_fcurve(fcu, aci, offset, merge_mode);
+ paste_animedit_keys_fcurve(fcu, aci, offset, merge_mode, false);
}
else {
/* from selected channels
@@ -834,13 +971,14 @@ short paste_animedit_keys(bAnimContext *ac, ListBase *anim_data,
* - if names do matter, only check if id-type is ok for now (group check is not that important)
* - most importantly, rna-paths should match (array indices are unimportant for now)
*/
+ AnimData *adt = ANIM_nla_mapping_get(ac, ale);
FCurve *fcu = (FCurve *)ale->data; /* destination F-Curve */
tAnimCopybufItem *aci = NULL;
switch (pass) {
case 0:
/* most strict, must be exact path match data_path & index */
- aci = pastebuf_match_path_full(fcu, from_single, to_simple);
+ aci = pastebuf_match_path_full(fcu, from_single, to_simple, flip);
break;
case 1:
@@ -857,9 +995,17 @@ short paste_animedit_keys(bAnimContext *ac, ListBase *anim_data,
/* copy the relevant data from the matching buffer curve */
if (aci) {
totmatch++;
- paste_animedit_keys_fcurve(fcu, aci, offset, merge_mode);
+
+ if (adt) {
+ ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 0, 1);
+ paste_animedit_keys_fcurve(fcu, aci, offset, merge_mode, flip);
+ ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 1, 1);
+ }
+ else {
+ paste_animedit_keys_fcurve(fcu, aci, offset, merge_mode, flip);
+ }
}
-
+
ale->update |= ANIM_UPDATE_DEFAULT;
}
diff --git a/source/blender/editors/animation/keyframing.c b/source/blender/editors/animation/keyframing.c
index 4c2d90179a7..479b4272755 100644
--- a/source/blender/editors/animation/keyframing.c
+++ b/source/blender/editors/animation/keyframing.c
@@ -42,7 +42,7 @@
#include "BLI_math.h"
#include "BLI_utildefines.h"
-#include "BLF_translation.h"
+#include "BLT_translation.h"
#include "DNA_anim_types.h"
#include "DNA_armature_types.h"
@@ -130,7 +130,7 @@ bAction *verify_adt_action(ID *id, short add)
/* init animdata if none available yet */
adt = BKE_animdata_from_id(id);
if ((adt == NULL) && (add))
- adt = BKE_id_add_animdata(id);
+ adt = BKE_animdata_add_id(id);
if (adt == NULL) {
/* if still none (as not allowed to add, or ID doesn't have animdata for some reason) */
printf("ERROR: Couldn't add AnimData (ID = %s)\n", (id) ? (id->name) : "<None>");
@@ -152,6 +152,10 @@ bAction *verify_adt_action(ID *id, short add)
* to the wrong places
*/
adt->action->idroot = GS(id->name);
+
+ /* tag depsgraph to be rebuilt to include time dependency */
+ /* XXX: we probably should have bmain passed down, but that involves altering too many API's */
+ DAG_relations_tag_update(G.main);
}
/* return the action */
@@ -658,7 +662,7 @@ static bool visualkey_can_use(PointerRNA *ptr, PropertyRNA *prop)
/* validate data */
if (ELEM(NULL, ptr, ptr->data, prop))
- return 0;
+ return false;
/* get first constraint and determine type of keyframe constraints to check for
* - constraints can be on either Objects or PoseChannels, so we only check if the
@@ -880,7 +884,7 @@ bool insert_keyframe_direct(ReportList *reports, PointerRNA ptr, PropertyRNA *pr
/* no F-Curve to add keyframe to? */
if (fcu == NULL) {
BKE_report(reports, RPT_ERROR, "No F-Curve to add keyframes to");
- return 0;
+ return false;
}
/* F-Curve not editable? */
if (fcurve_is_keyframable(fcu) == 0) {
@@ -888,13 +892,13 @@ bool insert_keyframe_direct(ReportList *reports, PointerRNA ptr, PropertyRNA *pr
"F-Curve with path '%s[%d]' cannot be keyframed, ensure that it is not locked or sampled, "
"and try removing F-Modifiers",
fcu->rna_path, fcu->array_index);
- return 0;
+ return false;
}
/* if no property given yet, try to validate from F-Curve info */
if ((ptr.id.data == NULL) && (ptr.data == NULL)) {
BKE_report(reports, RPT_ERROR, "No RNA pointer available to retrieve values for keyframing from");
- return 0;
+ return false;
}
if (prop == NULL) {
PointerRNA tmp_ptr;
@@ -907,7 +911,7 @@ bool insert_keyframe_direct(ReportList *reports, PointerRNA ptr, PropertyRNA *pr
BKE_reportf(reports, RPT_ERROR,
"Could not insert keyframe, as RNA path is invalid for the given ID (ID = %s, path = %s)",
idname, fcu->rna_path);
- return 0;
+ return false;
}
else {
/* property found, so overwrite 'ptr' to make later code easier */
@@ -956,18 +960,18 @@ bool insert_keyframe_direct(ReportList *reports, PointerRNA ptr, PropertyRNA *pr
/* only return success if keyframe added */
if (insert_mode)
- return 1;
+ return true;
}
else {
/* just insert keyframe */
insert_vert_fcurve(fcu, cfra, curval, flag);
/* return success */
- return 1;
+ return true;
}
/* failed */
- return 0;
+ return false;
}
/* Main Keyframing API call:
@@ -1284,10 +1288,10 @@ static int modify_key_op_poll(bContext *C)
/* if no area or active scene */
if (ELEM(NULL, sa, scene))
- return 0;
+ return false;
/* should be fine */
- return 1;
+ return true;
}
/* Insert Key Operator ------------------------ */
@@ -1402,12 +1406,12 @@ static int insert_key_menu_invoke(bContext *C, wmOperator *op, const wmEvent *UN
uiLayout *layout;
/* call the menu, which will call this operator again, hence the canceled */
- pup = uiPupMenuBegin(C, RNA_struct_ui_name(op->type->srna), ICON_NONE);
- layout = uiPupMenuLayout(pup);
+ pup = UI_popup_menu_begin(C, RNA_struct_ui_name(op->type->srna), ICON_NONE);
+ layout = UI_popup_menu_layout(pup);
uiItemsEnumO(layout, "ANIM_OT_keyframe_insert_menu", "type");
- uiPupMenuEnd(C, pup);
+ UI_popup_menu_end(C, pup);
- return OPERATOR_CANCELLED;
+ return OPERATOR_INTERFACE;
}
else {
/* just call the exec() on the active keyingset */
@@ -1696,7 +1700,7 @@ static int insert_key_button_exec(bContext *C, wmOperator *op)
char *path;
float cfra = (float)CFRA;
short success = 0;
- int a, index, length;
+ int index;
const bool all = RNA_boolean_get(op->ptr, "all");
short flag = 0;
@@ -1704,36 +1708,38 @@ static int insert_key_button_exec(bContext *C, wmOperator *op)
flag = ANIM_get_keyframing_flags(scene, 1);
/* try to insert keyframe using property retrieved from UI */
- uiContextActiveProperty(C, &ptr, &prop, &index);
+ UI_context_active_but_prop_get(C, &ptr, &prop, &index);
if ((ptr.id.data && ptr.data && prop) && RNA_property_animateable(&ptr, prop)) {
- path = RNA_path_from_ID_to_property(&ptr, prop);
-
- if (path) {
- if (all) {
- length = RNA_property_array_length(&ptr, prop);
-
- if (length) index = 0;
- else length = 1;
- }
- else
- length = 1;
-
- for (a = 0; a < length; a++)
- success += insert_keyframe(op->reports, ptr.id.data, NULL, NULL, path, index + a, cfra, flag);
-
- MEM_freeN(path);
- }
- else if (ptr.type == &RNA_NlaStrip) {
- /* handle special vars for NLA-strips */
+ if (ptr.type == &RNA_NlaStrip) {
+ /* Handle special properties for NLA Strips, whose F-Curves are stored on the
+ * strips themselves. These are stored separately or else the properties will
+ * not have any effect.
+ */
NlaStrip *strip = (NlaStrip *)ptr.data;
- FCurve *fcu = list_find_fcurve(&strip->fcurves, RNA_property_identifier(prop), flag);
+ FCurve *fcu = list_find_fcurve(&strip->fcurves, RNA_property_identifier(prop), index);
- success += insert_keyframe_direct(op->reports, ptr, prop, fcu, cfra, 0);
+ success = insert_keyframe_direct(op->reports, ptr, prop, fcu, cfra, 0);
}
else {
- BKE_report(op->reports, RPT_WARNING,
- "Failed to resolve path to property, try manually specifying this using a Keying Set instead");
+ /* standard properties */
+ path = RNA_path_from_ID_to_property(&ptr, prop);
+
+ if (path) {
+ if (all) {
+ /* -1 indicates operating on the entire array (or the property itself otherwise) */
+ index = -1;
+ }
+
+ success = insert_keyframe(op->reports, ptr.id.data, NULL, NULL, path, index, cfra, flag);
+
+ MEM_freeN(path);
+ }
+ else {
+ BKE_report(op->reports, RPT_WARNING,
+ "Failed to resolve path to property, "
+ "try manually specifying this using a Keying Set instead");
+ }
}
}
else {
@@ -1751,7 +1757,7 @@ static int insert_key_button_exec(bContext *C, wmOperator *op)
if (success) {
/* send updates */
- uiContextAnimUpdate(C);
+ UI_context_update_anim_flag(C);
/* send notifiers that keyframes have been changed */
WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_ADDED, NULL);
@@ -1788,32 +1794,62 @@ static int delete_key_button_exec(bContext *C, wmOperator *op)
char *path;
float cfra = (float)CFRA; // XXX for now, don't bother about all the yucky offset crap
short success = 0;
- int a, index, length;
+ int index;
const bool all = RNA_boolean_get(op->ptr, "all");
/* try to insert keyframe using property retrieved from UI */
- uiContextActiveProperty(C, &ptr, &prop, &index);
+ UI_context_active_but_prop_get(C, &ptr, &prop, &index);
if (ptr.id.data && ptr.data && prop) {
- path = RNA_path_from_ID_to_property(&ptr, prop);
-
- if (path) {
- if (all) {
- length = RNA_property_array_length(&ptr, prop);
+ if (ptr.type == &RNA_NlaStrip) {
+ /* Handle special properties for NLA Strips, whose F-Curves are stored on the
+ * strips themselves. These are stored separately or else the properties will
+ * not have any effect.
+ */
+ ID *id = ptr.id.data;
+ NlaStrip *strip = (NlaStrip *)ptr.data;
+ FCurve *fcu = list_find_fcurve(&strip->fcurves, RNA_property_identifier(prop), 0);
+
+ BLI_assert(fcu != NULL); /* NOTE: This should be true, or else we wouldn't be able to get here */
+
+ if (BKE_fcurve_is_protected(fcu)) {
+ BKE_reportf(op->reports, RPT_WARNING,
+ "Not deleting keyframe for locked F-Curve for NLA Strip influence on %s - %s '%s'",
+ strip->name, BKE_idcode_to_name(GS(id->name)), id->name + 2);
+ }
+ else {
+ /* remove the keyframe directly
+ * NOTE: cannot use delete_keyframe_fcurve(), as that will free the curve,
+ * and delete_keyframe() expects the FCurve to be part of an action
+ */
+ bool found = false;
+ int i;
- if (length) index = 0;
- else length = 1;
+ /* try to find index of beztriple to get rid of */
+ i = binarysearch_bezt_index(fcu->bezt, cfra, fcu->totvert, &found);
+ if (found) {
+ /* delete the key at the index (will sanity check + do recalc afterwards) */
+ delete_fcurve_key(fcu, i, 1);
+ success = true;
+ }
}
- else
- length = 1;
-
- for (a = 0; a < length; a++)
- success += delete_keyframe(op->reports, ptr.id.data, NULL, NULL, path, index + a, cfra, 0);
+ }
+ else {
+ /* standard properties */
+ path = RNA_path_from_ID_to_property(&ptr, prop);
- MEM_freeN(path);
+ if (path) {
+ if (all) {
+ /* -1 indicates operating on the entire array (or the property itself otherwise) */
+ index = -1;
+ }
+
+ success = delete_keyframe(op->reports, ptr.id.data, NULL, NULL, path, index, cfra, 0);
+ MEM_freeN(path);
+ }
+ else if (G.debug & G_DEBUG)
+ printf("Button Delete-Key: no path to property\n");
}
- else if (G.debug & G_DEBUG)
- printf("Button Delete-Key: no path to property\n");
}
else if (G.debug & G_DEBUG) {
printf("ptr.data = %p, prop = %p\n", (void *)ptr.data, (void *)prop);
@@ -1822,7 +1858,7 @@ static int delete_key_button_exec(bContext *C, wmOperator *op)
if (success) {
/* send updates */
- uiContextAnimUpdate(C);
+ UI_context_update_anim_flag(C);
/* send notifiers that keyframes have been changed */
WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_REMOVED, NULL);
@@ -1858,28 +1894,22 @@ static int clear_key_button_exec(bContext *C, wmOperator *op)
PropertyRNA *prop = NULL;
char *path;
short success = 0;
- int a, index, length;
+ int index;
const bool all = RNA_boolean_get(op->ptr, "all");
/* try to insert keyframe using property retrieved from UI */
- uiContextActiveProperty(C, &ptr, &prop, &index);
+ UI_context_active_but_prop_get(C, &ptr, &prop, &index);
if (ptr.id.data && ptr.data && prop) {
path = RNA_path_from_ID_to_property(&ptr, prop);
if (path) {
if (all) {
- length = RNA_property_array_length(&ptr, prop);
-
- if (length) index = 0;
- else length = 1;
+ /* -1 indicates operating on the entire array (or the property itself otherwise) */
+ index = -1;
}
- else
- length = 1;
-
- for (a = 0; a < length; a++)
- success += clear_keyframe(op->reports, ptr.id.data, NULL, NULL, path, index + a, 0);
+ success += clear_keyframe(op->reports, ptr.id.data, NULL, NULL, path, index, 0);
MEM_freeN(path);
}
else if (G.debug & G_DEBUG)
@@ -1892,7 +1922,7 @@ static int clear_key_button_exec(bContext *C, wmOperator *op)
if (success) {
/* send updates */
- uiContextAnimUpdate(C);
+ UI_context_update_anim_flag(C);
/* send notifiers that keyframes have been changed */
WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_REMOVED, NULL);
@@ -1922,17 +1952,17 @@ void ANIM_OT_keyframe_clear_button(wmOperatorType *ot)
/* ******************************************* */
/* AUTO KEYFRAME */
-int autokeyframe_cfra_can_key(Scene *scene, ID *id)
+bool autokeyframe_cfra_can_key(Scene *scene, ID *id)
{
float cfra = (float)CFRA; // XXX for now, this will do
/* only filter if auto-key mode requires this */
if (IS_AUTOKEY_ON(scene) == 0)
- return 0;
+ return false;
if (IS_AUTOKEY_MODE(scene, NORMAL)) {
/* can insert anytime we like... */
- return 1;
+ return true;
}
else { /* REPLACE */
/* for whole block - only key if there's a keyframe on that frame already
@@ -1952,7 +1982,7 @@ bool fcurve_frame_has_keyframe(FCurve *fcu, float frame, short filter)
{
/* quick sanity check */
if (ELEM(NULL, fcu, fcu->bezt))
- return 0;
+ return false;
/* we either include all regardless of muting, or only non-muted */
if ((filter & ANIMFILTER_KEYS_MUTED) || (fcu->flag & FCURVE_MUTED) == 0) {
@@ -1965,11 +1995,11 @@ bool fcurve_frame_has_keyframe(FCurve *fcu, float frame, short filter)
if (replace) {
/* sanity check: 'i' may in rare cases exceed arraylen */
if ((i >= 0) && (i < fcu->totvert))
- return 1;
+ return true;
}
}
- return 0;
+ return false;
}
/* Checks whether an Action has a keyframe for a given frame
@@ -1981,11 +2011,11 @@ static bool action_frame_has_keyframe(bAction *act, float frame, short filter)
/* can only find if there is data */
if (act == NULL)
- return 0;
+ return false;
/* if only check non-muted, check if muted */
if ((filter & ANIMFILTER_KEYS_MUTED) || (act->flag & ACT_MUTED))
- return 0;
+ return false;
/* loop over F-Curves, using binary-search to try to find matches
* - this assumes that keyframes are only beztriples
@@ -1994,12 +2024,12 @@ static bool action_frame_has_keyframe(bAction *act, float frame, short filter)
/* only check if there are keyframes (currently only of type BezTriple) */
if (fcu->bezt && fcu->totvert) {
if (fcurve_frame_has_keyframe(fcu, frame, filter))
- return 1;
+ return true;
}
}
/* nothing found */
- return 0;
+ return false;
}
/* Checks whether an Object has a keyframe for a given frame */
@@ -2007,12 +2037,18 @@ static bool object_frame_has_keyframe(Object *ob, float frame, short filter)
{
/* error checking */
if (ob == NULL)
- return 0;
+ return false;
/* check own animation data - specifically, the action it contains */
if ((ob->adt) && (ob->adt->action)) {
- if (action_frame_has_keyframe(ob->adt->action, frame, filter))
- return 1;
+ /* T41525 - When the active action is a NLA strip being edited,
+ * we need to correct the frame number to "look inside" the
+ * remapped action
+ */
+ float ob_frame = BKE_nla_tweakedit_remap(ob->adt, frame, NLATIME_CONVERT_UNMAP);
+
+ if (action_frame_has_keyframe(ob->adt->action, ob_frame, filter))
+ return true;
}
/* try shapekey keyframes (if available, and allowed by filter) */
@@ -2025,7 +2061,7 @@ static bool object_frame_has_keyframe(Object *ob, float frame, short filter)
/* 1. test for relative (with keyframes) */
if (id_frame_has_keyframe((ID *)key, frame, filter))
- return 1;
+ return true;
/* 2. test for time */
/* TODO... yet to be implemented (this feature may evolve before then anyway) */
@@ -2039,7 +2075,7 @@ static bool object_frame_has_keyframe(Object *ob, float frame, short filter)
/* we only retrieve the active material... */
if (id_frame_has_keyframe((ID *)ma, frame, filter))
- return 1;
+ return true;
}
else {
int a;
@@ -2049,13 +2085,13 @@ static bool object_frame_has_keyframe(Object *ob, float frame, short filter)
Material *ma = give_current_material(ob, a + 1);
if (id_frame_has_keyframe((ID *)ma, frame, filter))
- return 1;
+ return true;
}
}
}
/* nothing found */
- return 0;
+ return false;
}
/* --------------- API ------------------- */
@@ -2065,7 +2101,7 @@ bool id_frame_has_keyframe(ID *id, float frame, short filter)
{
/* sanity checks */
if (id == NULL)
- return 0;
+ return false;
/* perform special checks for 'macro' types */
switch (GS(id->name)) {
@@ -2089,7 +2125,7 @@ bool id_frame_has_keyframe(ID *id, float frame, short filter)
/* no keyframe found */
- return 0;
+ return false;
}
/* ************************************************** */
diff --git a/source/blender/editors/animation/keyingsets.c b/source/blender/editors/animation/keyingsets.c
index ad2db0d9c66..4b9a629183e 100644
--- a/source/blender/editors/animation/keyingsets.c
+++ b/source/blender/editors/animation/keyingsets.c
@@ -127,7 +127,7 @@ static int add_default_keyingset_exec(bContext *C, wmOperator *UNUSED(op))
/* call the API func, and set the active keyingset index */
BKE_keyingset_add(&scene->keyingsets, NULL, NULL, flag, keyingflag);
- scene->active_keyingset = BLI_countlist(&scene->keyingsets);
+ scene->active_keyingset = BLI_listbase_count(&scene->keyingsets);
/* send notifiers */
WM_event_add_notifier(C, NC_SCENE | ND_KEYINGSET, NULL);
@@ -216,7 +216,7 @@ static int add_empty_ks_path_exec(bContext *C, wmOperator *op)
/* don't use the API method for this, since that checks on values... */
ksp = MEM_callocN(sizeof(KS_Path), "KeyingSetPath Empty");
BLI_addtail(&ks->paths, ksp);
- ks->active_path = BLI_countlist(&ks->paths);
+ ks->active_path = BLI_listbase_count(&ks->paths);
ksp->groupmode = KSP_GROUP_KSNAME; // XXX?
ksp->idtype = ID_OB;
@@ -316,7 +316,7 @@ static int add_keyingset_button_exec(bContext *C, wmOperator *op)
/* call the API func, and set the active keyingset index */
ks = BKE_keyingset_add(&scene->keyingsets, "ButtonKeyingSet", "Button Keying Set", flag, keyingflag);
- scene->active_keyingset = BLI_countlist(&scene->keyingsets);
+ scene->active_keyingset = BLI_listbase_count(&scene->keyingsets);
}
else if (scene->active_keyingset < 0) {
BKE_report(op->reports, RPT_ERROR, "Cannot add property to built in keying set");
@@ -327,7 +327,7 @@ static int add_keyingset_button_exec(bContext *C, wmOperator *op)
}
/* try to add to keyingset using property retrieved from UI */
- uiContextActiveProperty(C, &ptr, &prop, &index);
+ UI_context_active_but_prop_get(C, &ptr, &prop, &index);
/* check if property is able to be added */
if (ptr.id.data && ptr.data && prop && RNA_property_animateable(&ptr, prop)) {
@@ -347,7 +347,7 @@ static int add_keyingset_button_exec(bContext *C, wmOperator *op)
/* add path to this setting */
BKE_keyingset_add_path(ks, ptr.id.data, NULL, path, index, pflag, KSP_GROUP_KSNAME);
- ks->active_path = BLI_countlist(&ks->paths);
+ ks->active_path = BLI_listbase_count(&ks->paths);
success = 1;
/* free the temp path created */
@@ -413,7 +413,7 @@ static int remove_keyingset_button_exec(bContext *C, wmOperator *op)
}
/* try to add to keyingset using property retrieved from UI */
- uiContextActiveProperty(C, &ptr, &prop, &index);
+ UI_context_active_but_prop_get(C, &ptr, &prop, &index);
if (ptr.id.data && ptr.data && prop) {
path = RNA_path_from_ID_to_property(&ptr, prop);
@@ -472,12 +472,12 @@ static int keyingset_active_menu_invoke(bContext *C, wmOperator *op, const wmEve
uiLayout *layout;
/* call the menu, which will call this operator again, hence the canceled */
- pup = uiPupMenuBegin(C, op->type->name, ICON_NONE);
- layout = uiPupMenuLayout(pup);
+ pup = UI_popup_menu_begin(C, op->type->name, ICON_NONE);
+ layout = UI_popup_menu_layout(pup);
uiItemsEnumO(layout, "ANIM_OT_keying_set_active_set", "type");
- uiPupMenuEnd(C, pup);
+ UI_popup_menu_end(C, pup);
- return OPERATOR_CANCELLED;
+ return OPERATOR_INTERFACE;
}
static int keyingset_active_menu_exec(bContext *C, wmOperator *op)
@@ -556,7 +556,7 @@ KeyingSet *ANIM_builtin_keyingset_get_named(KeyingSet *prevKS, const char name[]
/* loop over KeyingSets checking names */
for (ks = first; ks; ks = ks->next) {
- if (strcmp(name, ks->idname) == 0)
+ if (STREQ(name, ks->idname))
return ks;
}
@@ -603,7 +603,7 @@ void ANIM_keyingset_info_unregister(Main *bmain, KeyingSetInfo *ksi)
ksn = ks->next;
/* remove if matching typeinfo name */
- if (strcmp(ks->typeinfo, ksi->idname) == 0) {
+ if (STREQ(ks->typeinfo, ksi->idname)) {
Scene *scene;
BKE_keyingset_free(ks);
BLI_remlink(&builtin_keyingsets, ks);
@@ -914,6 +914,37 @@ short ANIM_validate_keyingset(bContext *C, ListBase *dsources, KeyingSet *ks)
return 0;
}
+/* Determine which keying flags apply based on the override flags */
+static short keyingset_apply_keying_flags(const short base_flags, const short overrides, const short own_flags)
+{
+ short result = 0;
+
+ /* The logic for whether a keying flag applies is as follows:
+ * - If the flag in question is set in "overrides", that means that the
+ * status of that flag in "own_flags" is used
+ * - If however the flag isn't set, then its value in "base_flags" is used
+ * instead (i.e. no override)
+ */
+#define APPLY_KEYINGFLAG_OVERRIDE(kflag) \
+ if (overrides & kflag) { \
+ result |= (own_flags & kflag); \
+ } \
+ else { \
+ result |= (base_flags & kflag); \
+ }
+
+ /* Apply the flags one by one...
+ * (See rna_def_common_keying_flags() for the supported flags)
+ */
+ APPLY_KEYINGFLAG_OVERRIDE(INSERTKEY_NEEDED)
+ APPLY_KEYINGFLAG_OVERRIDE(INSERTKEY_MATRIX)
+ APPLY_KEYINGFLAG_OVERRIDE(INSERTKEY_XYZ2RGB)
+
+#undef APPLY_KEYINGFLAG_OVERRIDE
+
+ return result;
+}
+
/* Given a KeyingSet and context info (if required), modify keyframes for the channels specified
* by the KeyingSet. This takes into account many of the different combinations of using KeyingSets.
* Returns the number of channels that keyframes were added to
@@ -923,7 +954,8 @@ int ANIM_apply_keyingset(bContext *C, ListBase *dsources, bAction *act, KeyingSe
Scene *scene = CTX_data_scene(C);
ReportList *reports = CTX_wm_reports(C);
KS_Path *ksp;
- int kflag = 0, success = 0;
+ const short base_kflags = ANIM_get_keyframing_flags(scene, 1);
+ short kflag = 0, success = 0;
const char *groupname = NULL;
/* sanity checks */
@@ -932,11 +964,8 @@ int ANIM_apply_keyingset(bContext *C, ListBase *dsources, bAction *act, KeyingSe
/* get flags to use */
if (mode == MODIFYKEY_MODE_INSERT) {
- /* use KeyingSet's flags as base */
- kflag = ks->keyingflag;
-
- /* supplement with info from the context */
- kflag |= ANIM_get_keyframing_flags(scene, 1);
+ /* use context settings as base */
+ kflag = keyingset_apply_keying_flags(base_kflags, ks->keyingoverride, ks->keyingflag);
}
else if (mode == MODIFYKEY_MODE_DELETE)
kflag = 0;
@@ -962,8 +991,8 @@ int ANIM_apply_keyingset(bContext *C, ListBase *dsources, bAction *act, KeyingSe
continue;
}
- /* since keying settings can be defined on the paths too, extend the path before using it */
- kflag2 = (kflag | ksp->keyingflag);
+ /* since keying settings can be defined on the paths too, apply the settings for this path first */
+ kflag2 = keyingset_apply_keying_flags(kflag, ksp->keyingoverride, ksp->keyingflag);
/* get pointer to name of group to add channels to */
if (ksp->groupmode == KSP_GROUP_NONE)
diff --git a/source/blender/editors/armature/BIF_retarget.h b/source/blender/editors/armature/BIF_retarget.h
index 21e85b6fe89..aa56f847f00 100644
--- a/source/blender/editors/armature/BIF_retarget.h
+++ b/source/blender/editors/armature/BIF_retarget.h
@@ -40,7 +40,6 @@ struct bContext;
struct EditBone;
-struct RigJoint;
struct RigGraph;
struct RigNode;
struct RigArc;
diff --git a/source/blender/editors/armature/CMakeLists.txt b/source/blender/editors/armature/CMakeLists.txt
index 9aa17f1e503..1ed70b3cd98 100644
--- a/source/blender/editors/armature/CMakeLists.txt
+++ b/source/blender/editors/armature/CMakeLists.txt
@@ -20,14 +20,15 @@
set(INC
../include
- ../../blenfont
../../blenkernel
../../blenlib
+ ../../blentranslation
+ ../../gpu
../../makesdna
../../makesrna
../../windowmanager
- ../../gpu
../../../../intern/guardedalloc
+ ../../../../intern/glew-mx
)
set(INC_SYS
@@ -74,4 +75,6 @@ if(WITH_OPENNL)
)
endif()
+add_definitions(${GL_DEFINITIONS})
+
blender_add_lib(bf_editor_armature "${SRC}" "${INC}" "${INC_SYS}")
diff --git a/source/blender/editors/armature/SConscript b/source/blender/editors/armature/SConscript
index c68045c9398..9c3959ecb5b 100644
--- a/source/blender/editors/armature/SConscript
+++ b/source/blender/editors/armature/SConscript
@@ -31,20 +31,22 @@ sources = env.Glob('*.c')
incs = [
'#/intern/guardedalloc',
- '#/extern/glew/include',
+ env['BF_GLEW_INC'],
+ '#/intern/glew-mx',
'#/intern/opennl/extern',
'../include',
- '../../blenfont',
'../../blenkernel',
'../../blenlib',
+ '../../blentranslation',
+ '../../gpu',
'../../makesdna',
'../../makesrna',
- '../../gpu',
'../../windowmanager',
]
incs = ' '.join(incs)
defs = []
+defs += env['BF_GL_DEFINITIONS']
if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'linuxcross', 'win64-vc', 'win64-mingw'):
incs += ' ' + env['BF_PTHREADS_INC']
diff --git a/source/blender/editors/armature/armature_add.c b/source/blender/editors/armature/armature_add.c
index eba1bc4d78d..59453f0ac71 100644
--- a/source/blender/editors/armature/armature_add.c
+++ b/source/blender/editors/armature/armature_add.c
@@ -43,6 +43,7 @@
#include "BKE_constraint.h"
#include "BKE_context.h"
#include "BKE_idprop.h"
+#include "BKE_deform.h"
#include "RNA_access.h"
#include "RNA_define.h"
@@ -89,7 +90,7 @@ EditBone *ED_armature_edit_bone_add_primitive(Object *obedit_arm, float length,
bArmature *arm = obedit_arm->data;
EditBone *bone;
- ED_armature_deselect_all(obedit_arm, 0);
+ ED_armature_deselect_all(obedit_arm);
/* Create a bone */
bone = ED_armature_edit_bone_add(arm, "Bone");
@@ -144,7 +145,7 @@ static int armature_click_extrude_exec(bContext *C, wmOperator *UNUSED(op))
to_root = 1;
}
- ED_armature_deselect_all(obedit, 0);
+ ED_armature_deselect_all(obedit);
/* we re-use code for mirror editing... */
flipbone = NULL;
@@ -270,7 +271,7 @@ static EditBone *get_named_editbone(ListBase *edbo, const char *name)
if (name) {
for (eBone = edbo->first; eBone; eBone = eBone->next) {
- if (!strcmp(name, eBone->name))
+ if (STREQ(name, eBone->name))
return eBone;
}
}
@@ -282,12 +283,8 @@ static EditBone *get_named_editbone(ListBase *edbo, const char *name)
* */
void preEditBoneDuplicate(ListBase *editbones)
{
- EditBone *eBone;
-
/* clear temp */
- for (eBone = editbones->first; eBone; eBone = eBone->next) {
- eBone->temp = NULL;
- }
+ ED_armature_ebone_listbase_temp_clear(editbones);
}
/*
@@ -311,7 +308,7 @@ void updateDuplicateSubtargetObjects(EditBone *dupBone, ListBase *editbones, Obj
/* does this constraint have a subtarget in
* this armature?
*/
- bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(curcon);
+ const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(curcon);
ListBase targets = {NULL, NULL};
bConstraintTarget *ct;
@@ -327,8 +324,8 @@ void updateDuplicateSubtargetObjects(EditBone *dupBone, ListBase *editbones, Obj
* so, update the constraint to point at the
* duplicate of the old subtarget.
*/
- if (oldtarget->temp) {
- newtarget = (EditBone *) oldtarget->temp;
+ if (oldtarget->temp.ebone) {
+ newtarget = oldtarget->temp.ebone;
BLI_strncpy(ct->subtarget, newtarget->name, sizeof(ct->subtarget));
}
}
@@ -357,8 +354,8 @@ EditBone *duplicateEditBoneObjects(EditBone *curBone, const char *name, ListBase
/* Copy data from old bone to new bone */
memcpy(eBone, curBone, sizeof(EditBone));
- curBone->temp = eBone;
- eBone->temp = curBone;
+ curBone->temp.ebone = eBone;
+ eBone->temp.ebone = curBone;
if (name != NULL) {
BLI_strncpy(eBone->name, name, sizeof(eBone->name));
@@ -398,13 +395,11 @@ EditBone *duplicateEditBone(EditBone *curBone, const char *name, ListBase *editb
return duplicateEditBoneObjects(curBone, name, editbones, ob, ob);
}
-/* previously adduplicate_armature */
static int armature_duplicate_selected_exec(bContext *C, wmOperator *UNUSED(op))
{
bArmature *arm;
- EditBone *eBone = NULL;
- EditBone *curBone;
- EditBone *firstDup = NULL; /* The beginning of the duplicated bones in the edbo list */
+ EditBone *ebone_iter;
+ EditBone *ebone_first_dupe = NULL; /* The beginning of the duplicated bones in the edbo list */
Object *obedit = CTX_data_edit_object(C);
arm = obedit->data;
@@ -419,77 +414,80 @@ static int armature_duplicate_selected_exec(bContext *C, wmOperator *UNUSED(op))
/* Select mirrored bones */
if (arm->flag & ARM_MIRROR_EDIT) {
- for (curBone = arm->edbo->first; curBone; curBone = curBone->next) {
- if (EBONE_VISIBLE(arm, curBone)) {
- if (curBone->flag & BONE_SELECTED) {
- eBone = ED_armature_bone_get_mirrored(arm->edbo, curBone);
- if (eBone)
- eBone->flag |= BONE_SELECTED;
+ for (ebone_iter = arm->edbo->first; ebone_iter; ebone_iter = ebone_iter->next) {
+ if (EBONE_VISIBLE(arm, ebone_iter) &&
+ (ebone_iter->flag & BONE_SELECTED))
+ {
+ EditBone *ebone;
+
+ ebone = ED_armature_bone_get_mirrored(arm->edbo, ebone_iter);
+ if (ebone) {
+ ebone->flag |= BONE_SELECTED;
}
}
}
}
- /* Find the selected bones and duplicate them as needed */
- for (curBone = arm->edbo->first; curBone && curBone != firstDup; curBone = curBone->next) {
- if (EBONE_VISIBLE(arm, curBone)) {
- if (curBone->flag & BONE_SELECTED) {
-
- eBone = duplicateEditBone(curBone, curBone->name, arm->edbo, obedit);
-
- if (!firstDup)
- firstDup = eBone;
+ /* Find the selected bones and duplicate them as needed */
+ for (ebone_iter = arm->edbo->first; ebone_iter && ebone_iter != ebone_first_dupe; ebone_iter = ebone_iter->next) {
+ if (EBONE_VISIBLE(arm, ebone_iter) &&
+ (ebone_iter->flag & BONE_SELECTED))
+ {
+ EditBone *ebone;
+ ebone = duplicateEditBone(ebone_iter, ebone_iter->name, arm->edbo, obedit);
+
+ if (!ebone_first_dupe) {
+ ebone_first_dupe = ebone;
}
}
}
- /* Run though the list and fix the pointers */
- for (curBone = arm->edbo->first; curBone && curBone != firstDup; curBone = curBone->next) {
- if (EBONE_VISIBLE(arm, curBone)) {
- if (curBone->flag & BONE_SELECTED) {
- eBone = (EditBone *) curBone->temp;
-
- if (!curBone->parent) {
- /* If this bone has no parent,
- * Set the duplicate->parent to NULL
- */
- eBone->parent = NULL;
- }
- else if (curBone->parent->temp) {
- /* If this bone has a parent that was duplicated,
- * Set the duplicate->parent to the curBone->parent->temp
- */
- eBone->parent = (EditBone *)curBone->parent->temp;
- }
- else {
- /* If this bone has a parent that IS not selected,
- * Set the duplicate->parent to the curBone->parent
- */
- eBone->parent = (EditBone *) curBone->parent;
- eBone->flag &= ~BONE_CONNECTED;
- }
-
- /* Lets try to fix any constraint subtargets that might
- * have been duplicated
+ /* Run though the list and fix the pointers */
+ for (ebone_iter = arm->edbo->first; ebone_iter && ebone_iter != ebone_first_dupe; ebone_iter = ebone_iter->next) {
+ if (EBONE_VISIBLE(arm, ebone_iter) &&
+ (ebone_iter->flag & BONE_SELECTED))
+ {
+ EditBone *ebone = ebone_iter->temp.ebone;
+
+ if (!ebone_iter->parent) {
+ /* If this bone has no parent,
+ * Set the duplicate->parent to NULL
+ */
+ ebone->parent = NULL;
+ }
+ else if (ebone_iter->parent->temp.ebone) {
+ /* If this bone has a parent that was duplicated,
+ * Set the duplicate->parent to the curBone->parent->temp
+ */
+ ebone->parent = ebone_iter->parent->temp.ebone;
+ }
+ else {
+ /* If this bone has a parent that IS not selected,
+ * Set the duplicate->parent to the curBone->parent
*/
- updateDuplicateSubtarget(eBone, arm->edbo, obedit);
+ ebone->parent = (EditBone *) ebone_iter->parent;
+ ebone->flag &= ~BONE_CONNECTED;
}
+
+ /* Lets try to fix any constraint subtargets that might
+ * have been duplicated
+ */
+ updateDuplicateSubtarget(ebone, arm->edbo, obedit);
}
}
/* correct the active bone */
- if (arm->act_edbone) {
- eBone = arm->act_edbone;
- if (eBone->temp)
- arm->act_edbone = eBone->temp;
+ if (arm->act_edbone && arm->act_edbone->temp.ebone) {
+ arm->act_edbone = arm->act_edbone->temp.ebone;
}
- /* Deselect the old bones and select the new ones */
- for (curBone = arm->edbo->first; curBone && curBone != firstDup; curBone = curBone->next) {
- if (EBONE_VISIBLE(arm, curBone))
- curBone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
+ /* Deselect the old bones and select the new ones */
+ for (ebone_iter = arm->edbo->first; ebone_iter && ebone_iter != ebone_first_dupe; ebone_iter = ebone_iter->next) {
+ if (EBONE_VISIBLE(arm, ebone_iter)) {
+ ebone_iter->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
+ }
}
ED_armature_validate_active(arm);
@@ -515,6 +513,214 @@ void ARMATURE_OT_duplicate(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
+/**
+ * near duplicate of #armature_duplicate_selected_exec,
+ * except for parenting part (keep in sync)
+ */
+static int armature_symmetrize_exec(bContext *C, wmOperator *op)
+{
+ bArmature *arm;
+ EditBone *ebone_iter;
+ EditBone *ebone_first_dupe = NULL; /* The beginning of the duplicated mirrored bones in the edbo list */
+
+ Object *obedit = CTX_data_edit_object(C);
+ const int direction = RNA_enum_get(op->ptr, "direction");
+ const int axis = 0;
+
+ arm = obedit->data;
+
+ /* cancel if nothing selected */
+ if (CTX_DATA_COUNT(C, selected_bones) == 0)
+ return OPERATOR_CANCELLED;
+
+ ED_armature_sync_selection(arm->edbo); // XXX why is this needed?
+
+ preEditBoneDuplicate(arm->edbo);
+
+ /* Select mirrored bones */
+ for (ebone_iter = arm->edbo->first; ebone_iter; ebone_iter = ebone_iter->next) {
+ if (EBONE_VISIBLE(arm, ebone_iter) &&
+ (ebone_iter->flag & BONE_SELECTED))
+ {
+ char name_flip[MAX_VGROUP_NAME];
+
+ BKE_deform_flip_side_name(name_flip, ebone_iter->name, false);
+
+ if (STREQ(name_flip, ebone_iter->name)) {
+ /* if the name matches, we don't have the potential to be mirrored, just skip */
+ ebone_iter->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
+ }
+ else {
+ EditBone *ebone = ED_armature_bone_find_name(arm->edbo, name_flip);
+
+ if (ebone) {
+ if ((ebone->flag & BONE_SELECTED) == 0) {
+ /* simple case, we're selected, the other bone isn't! */
+ ebone_iter->temp.ebone = ebone;
+ }
+ else {
+ /* complicated - choose which direction to copy */
+ float axis_delta;
+
+ axis_delta = ebone->head[axis] - ebone_iter->head[axis];
+ if (axis_delta == 0.0f) {
+ axis_delta = ebone->tail[axis] - ebone_iter->tail[axis];
+ }
+
+ if (axis_delta == 0.0f) {
+ /* both mirrored bones exist and point to eachother and overlap exactly.
+ *
+ * in this case theres no well defined solution, so de-select both and skip.
+ */
+ ebone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
+ ebone_iter->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
+ }
+ else {
+ EditBone *ebone_src, *ebone_dst;
+ if (((axis_delta < 0.0f) ? -1 : 1) == direction) {
+ ebone_src = ebone;
+ ebone_dst = ebone_iter;
+ }
+ else {
+ ebone_src = ebone_iter;
+ ebone_dst = ebone;
+ }
+
+ ebone_src->temp.ebone = ebone_dst;
+ ebone_dst->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /* Find the selected bones and duplicate them as needed, with mirrored name */
+ for (ebone_iter = arm->edbo->first; ebone_iter && ebone_iter != ebone_first_dupe; ebone_iter = ebone_iter->next) {
+ if (EBONE_VISIBLE(arm, ebone_iter) &&
+ (ebone_iter->flag & BONE_SELECTED) &&
+ /* will be set if the mirror bone already exists (no need to make a new one) */
+ (ebone_iter->temp.ebone == NULL))
+ {
+ char name_flip[MAX_VGROUP_NAME];
+
+ BKE_deform_flip_side_name(name_flip, ebone_iter->name, false);
+
+ /* bones must have a side-suffix */
+ if (!STREQ(name_flip, ebone_iter->name)) {
+ EditBone *ebone;
+
+ ebone = duplicateEditBone(ebone_iter, name_flip, arm->edbo, obedit);
+
+ if (!ebone_first_dupe) {
+ ebone_first_dupe = ebone;
+ }
+ }
+ }
+ }
+
+ /* Run though the list and fix the pointers */
+ for (ebone_iter = arm->edbo->first; ebone_iter && ebone_iter != ebone_first_dupe; ebone_iter = ebone_iter->next) {
+ if (ebone_iter->temp.ebone) {
+ /* copy all flags except for ... */
+ const int flag_copy = ((int)~0) & ~(BONE_SELECTED | BONE_ROOTSEL | BONE_TIPSEL);
+
+ EditBone *ebone = ebone_iter->temp.ebone;
+
+ /* copy flags incase bone is pre-existing data */
+ ebone->flag = (ebone->flag & ~flag_copy) | (ebone_iter->flag & flag_copy);
+
+ if (ebone_iter->parent == NULL) {
+ /* If this bone has no parent,
+ * Set the duplicate->parent to NULL
+ */
+ ebone->parent = NULL;
+ ebone->flag &= ~BONE_CONNECTED;
+ }
+ else {
+ /* the parent may have been duplicated, if not lookup the mirror parent */
+ EditBone *ebone_parent =
+ (ebone_iter->parent->temp.ebone ?
+ ebone_iter->parent->temp.ebone : ED_armature_bone_get_mirrored(arm->edbo, ebone_iter->parent));
+
+ if (ebone_parent == NULL) {
+ /* If the mirror lookup failed, (but the current bone has a parent)
+ * then we can assume the parent has no L/R but is a center bone.
+ * So just use the same parent for both.
+ */
+ ebone_parent = ebone_iter->parent;
+ ebone->flag &= ~BONE_CONNECTED;
+ }
+
+ ebone->parent = ebone_parent;
+ }
+
+ /* Lets try to fix any constraint subtargets that might
+ * have been duplicated
+ */
+ updateDuplicateSubtarget(ebone, arm->edbo, obedit);
+ }
+ }
+
+ transform_armature_mirror_update(obedit);
+
+ /* Selected bones now have their 'temp' pointer set,
+ * so we don't need this anymore */
+
+ /* Deselect the old bones and select the new ones */
+ for (ebone_iter = arm->edbo->first; ebone_iter && ebone_iter != ebone_first_dupe; ebone_iter = ebone_iter->next) {
+ if (EBONE_VISIBLE(arm, ebone_iter)) {
+ ebone_iter->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
+ }
+ }
+
+ /* New bones will be selected, but some of the bones may already exist */
+ for (ebone_iter = arm->edbo->first; ebone_iter && ebone_iter != ebone_first_dupe; ebone_iter = ebone_iter->next) {
+ EditBone *ebone = ebone_iter->temp.ebone;
+ if (ebone && EBONE_SELECTABLE(arm, ebone)) {
+ ED_armature_ebone_select_set(ebone, true);
+ }
+ }
+
+ /* correct the active bone */
+ if (arm->act_edbone && arm->act_edbone->temp.ebone) {
+ arm->act_edbone = arm->act_edbone->temp.ebone;
+ }
+
+ ED_armature_validate_active(arm);
+
+ WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, obedit);
+
+ return OPERATOR_FINISHED;
+}
+
+/* following conventions from #MESH_OT_symmetrize */
+void ARMATURE_OT_symmetrize(wmOperatorType *ot)
+{
+ /* subset of 'symmetrize_direction_items' */
+ static EnumPropertyItem arm_symmetrize_direction_items[] = {
+ {-1, "NEGATIVE_X", 0, "-X to +X", ""},
+ {+1, "POSITIVE_X", 0, "+X to -X", ""},
+ {0, NULL, 0, NULL, NULL}
+ };
+
+ /* identifiers */
+ ot->name = "Symmetrize";
+ ot->idname = "ARMATURE_OT_symmetrize";
+ ot->description = "Enforce symmetry, make copies of the selection or use existing";
+
+ /* api callbacks */
+ ot->exec = armature_symmetrize_exec;
+ ot->poll = ED_operator_editarmature;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ ot->prop = RNA_def_enum(
+ ot->srna, "direction", arm_symmetrize_direction_items, -1,
+ "Direction", "Which sides to copy from and to (when both are selected)");
+}
+
/* ------------------------------------------ */
/* previously extrude_armature */
@@ -704,7 +910,7 @@ static int armature_bone_primitive_add_exec(bContext *C, wmOperator *op)
mul_m3_m3m3(totmat, obmat, viewmat);
invert_m3_m3(imat, totmat);
- ED_armature_deselect_all(obedit, 0);
+ ED_armature_deselect_all(obedit);
/* Create a bone */
bone = ED_armature_edit_bone_add(obedit->data, name);
@@ -830,7 +1036,7 @@ void ARMATURE_OT_subdivide(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
/* Properties */
- prop = RNA_def_int(ot->srna, "number_cuts", 1, 1, INT_MAX, "Number of Cuts", "", 1, 10);
+ prop = RNA_def_int(ot->srna, "number_cuts", 1, 1, 1000, "Number of Cuts", "", 1, 10);
/* avoid re-using last var because it can cause _very_ high poly meshes and annoy users (or worse crash) */
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
diff --git a/source/blender/editors/armature/armature_edit.c b/source/blender/editors/armature/armature_edit.c
index 1e4d9bac246..5a0e70dc5dd 100644
--- a/source/blender/editors/armature/armature_edit.c
+++ b/source/blender/editors/armature/armature_edit.c
@@ -38,8 +38,11 @@
#include "MEM_guardedalloc.h"
+#include "BLT_translation.h"
+
#include "BLI_blenlib.h"
#include "BLI_math.h"
+#include "BLI_ghash.h"
#include "BKE_action.h"
#include "BKE_armature.h"
@@ -70,7 +73,7 @@ void ED_armature_apply_transform(Object *ob, float mat[4][4])
/* Put the armature into editmode */
ED_armature_to_edit(arm);
- /* Transform the bones*/
+ /* Transform the bones */
ED_armature_transform_bones(arm, mat);
/* Turn the list into an armature */
@@ -100,7 +103,7 @@ void ED_armature_transform_bones(struct bArmature *arm, float mat[4][4])
mul_m4_v3(mat, ebone->head);
mul_m4_v3(mat, ebone->tail);
- /* apply the transfiormed roll back */
+ /* apply the transformed roll back */
mat3_to_vec_roll(tmat, NULL, &ebone->roll);
ebone->rad_head *= scale;
@@ -190,7 +193,7 @@ void ED_armature_origin_set(Scene *scene, Object *ob, float cursor[3], int cente
/* Adjust object location for new centerpoint */
if (centermode && obedit == NULL) {
- mul_mat3_m4_v3(ob->obmat, cent); /* ommit translation part */
+ mul_mat3_m4_v3(ob->obmat, cent); /* omit translation part */
add_v3_v3(ob->loc, cent);
}
}
@@ -236,28 +239,49 @@ float ED_rollBoneToVector(EditBone *bone, const float align_axis[3], const bool
return roll;
}
-
+/* note, ranges arithmatic is used below */
typedef enum eCalcRollTypes {
- CALC_ROLL_X = 0,
- CALC_ROLL_Y = 1,
- CALC_ROLL_Z = 2,
-
- CALC_ROLL_TAN_X = 3,
- CALC_ROLL_TAN_Z = 4,
-
- CALC_ROLL_ACTIVE = 5,
- CALC_ROLL_VIEW = 6,
- CALC_ROLL_CURSOR = 7,
+ /* pos */
+ CALC_ROLL_POS_X = 0,
+ CALC_ROLL_POS_Y,
+ CALC_ROLL_POS_Z,
+
+ CALC_ROLL_TAN_POS_X,
+ CALC_ROLL_TAN_POS_Z,
+
+ /* neg */
+ CALC_ROLL_NEG_X,
+ CALC_ROLL_NEG_Y,
+ CALC_ROLL_NEG_Z,
+
+ CALC_ROLL_TAN_NEG_X,
+ CALC_ROLL_TAN_NEG_Z,
+
+ /* no sign */
+ CALC_ROLL_ACTIVE,
+ CALC_ROLL_VIEW,
+ CALC_ROLL_CURSOR,
} eCalcRollTypes;
static EnumPropertyItem prop_calc_roll_types[] = {
- {CALC_ROLL_TAN_X, "X", 0, "Local X Tangent", ""},
- {CALC_ROLL_TAN_Z, "Z", 0, "Local Z Tangent", ""},
+ {0, "", 0, N_("Positive"), ""},
+ {CALC_ROLL_TAN_POS_X, "POS_X", 0, "Local +X Tangent", ""},
+ {CALC_ROLL_TAN_POS_Z, "POS_Z", 0, "Local +Z Tangent", ""},
+
+ {CALC_ROLL_POS_X, "GLOBAL_POS_X", 0, "Global +X Axis", ""},
+ {CALC_ROLL_POS_Y, "GLOBAL_POS_Y", 0, "Global +Y Axis", ""},
+ {CALC_ROLL_POS_Z, "GLOBAL_POS_Z", 0, "Global +Z Axis", ""},
- {CALC_ROLL_X, "GLOBAL_X", 0, "Global X Axis", ""},
- {CALC_ROLL_Y, "GLOBAL_Y", 0, "Global Y Axis", ""},
- {CALC_ROLL_Z, "GLOBAL_Z", 0, "Global Z Axis", ""},
+ {0, "", 0, N_("Negative"), ""},
+ {CALC_ROLL_TAN_NEG_X, "NEG_X", 0, "Local -X Tangent", ""},
+ {CALC_ROLL_TAN_NEG_Z, "NEG_Z", 0, "Local -Z Tangent", ""},
+
+ {CALC_ROLL_NEG_X, "GLOBAL_NEG_X", 0, "Global -X Axis", ""},
+ {CALC_ROLL_NEG_Y, "GLOBAL_NEG_Y", 0, "Global -Y Axis", ""},
+ {CALC_ROLL_NEG_Z, "GLOBAL_NEG_Z", 0, "Global -Z Axis", ""},
+
+ {0, "", 0, N_("Other"), ""},
{CALC_ROLL_ACTIVE, "ACTIVE", 0, "Active Bone", ""},
{CALC_ROLL_VIEW, "VIEW", 0, "View Axis", ""},
{CALC_ROLL_CURSOR, "CURSOR", 0, "Cursor", ""},
@@ -268,15 +292,22 @@ static EnumPropertyItem prop_calc_roll_types[] = {
static int armature_calc_roll_exec(bContext *C, wmOperator *op)
{
Object *ob = CTX_data_edit_object(C);
- const short type = RNA_enum_get(op->ptr, "type");
+ eCalcRollTypes type = RNA_enum_get(op->ptr, "type");
const bool axis_only = RNA_boolean_get(op->ptr, "axis_only");
- const bool axis_flip = RNA_boolean_get(op->ptr, "axis_flip");
+ /* axis_flip when matching the active bone never makes sense */
+ bool axis_flip = ((type >= CALC_ROLL_ACTIVE) ? RNA_boolean_get(op->ptr, "axis_flip") :
+ (type >= CALC_ROLL_TAN_NEG_X) ? true : false);
float imat[3][3];
bArmature *arm = ob->data;
EditBone *ebone;
+ if ((type >= CALC_ROLL_NEG_X) && (type <= CALC_ROLL_TAN_NEG_Z)) {
+ type -= (CALC_ROLL_ACTIVE - CALC_ROLL_NEG_X);
+ axis_flip = true;
+ }
+
copy_m3_m4(imat, ob->obmat);
invert_m3(imat);
@@ -296,11 +327,13 @@ static int armature_calc_roll_exec(bContext *C, wmOperator *op)
float cursor_rel[3];
sub_v3_v3v3(cursor_rel, cursor_local, ebone->head);
if (axis_flip) negate_v3(cursor_rel);
- ebone->roll = ED_rollBoneToVector(ebone, cursor_rel, axis_only);
+ if (normalize_v3(cursor_rel) != 0.0f) {
+ ebone->roll = ED_rollBoneToVector(ebone, cursor_rel, axis_only);
+ }
}
}
}
- else if (ELEM(type, CALC_ROLL_TAN_X, CALC_ROLL_TAN_Z)) {
+ else if (ELEM(type, CALC_ROLL_TAN_POS_X, CALC_ROLL_TAN_POS_Z)) {
for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
if (ebone->parent) {
bool is_edit = (EBONE_VISIBLE(arm, ebone) && EBONE_EDITABLE(ebone));
@@ -321,7 +354,7 @@ static int armature_calc_roll_exec(bContext *C, wmOperator *op)
sub_v3_v3v3(dir_b, ebone_other->head, ebone_other->tail);
normalize_v3(dir_b);
- if (type == CALC_ROLL_TAN_Z) {
+ if (type == CALC_ROLL_TAN_POS_Z) {
cross_v3_v3v3(vec, dir_a, dir_b);
}
else {
@@ -372,7 +405,7 @@ static int armature_calc_roll_exec(bContext *C, wmOperator *op)
copy_v3_v3(vec, mat[2]);
}
else { /* Axis */
- assert(type >= 0 && type <= 5);
+ assert(type <= 5);
if (type < 3) vec[type] = 1.0f;
else vec[type - 2] = -1.0f;
mul_m3_v3(imat, vec);
@@ -421,7 +454,7 @@ void ARMATURE_OT_calculate_roll(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
/* properties */
- ot->prop = RNA_def_enum(ot->srna, "type", prop_calc_roll_types, CALC_ROLL_TAN_X, "Type", "");
+ ot->prop = RNA_def_enum(ot->srna, "type", prop_calc_roll_types, CALC_ROLL_TAN_POS_X, "Type", "");
RNA_def_boolean(ot->srna, "axis_flip", 0, "Flip Axis", "Negate the alignment axis");
RNA_def_boolean(ot->srna, "axis_only", 0, "Shortest Rotation", "Ignore the axis direction, use the shortest rotation to align");
}
@@ -546,6 +579,7 @@ static int armature_fill_bones_exec(bContext *C, wmOperator *op)
Scene *scene = CTX_data_scene(C);
View3D *v3d = CTX_wm_view3d(C);
ListBase points = {NULL, NULL};
+ EditBone *newbone = NULL;
int count;
/* sanity checks */
@@ -567,7 +601,7 @@ static int armature_fill_bones_exec(bContext *C, wmOperator *op)
* 2) between the two joints (order is dependent on active-bone/hierarchy)
* 3+) error (a smarter method involving finding chains needs to be worked out
*/
- count = BLI_countlist(&points);
+ count = BLI_listbase_count(&points);
if (count == 0) {
BKE_report(op->reports, RPT_ERROR, "No joints selected");
@@ -578,94 +612,97 @@ static int armature_fill_bones_exec(bContext *C, wmOperator *op)
float curs[3];
/* Get Points - selected joint */
- ebp = (EditBonePoint *)points.first;
+ ebp = points.first;
/* Get points - cursor (tail) */
invert_m4_m4(obedit->imat, obedit->obmat);
mul_v3_m4v3(curs, obedit->imat, ED_view3d_cursor3d_get(scene, v3d));
/* Create a bone */
- /* newbone = */ add_points_bone(obedit, ebp->vec, curs);
+ newbone = add_points_bone(obedit, ebp->vec, curs);
}
else if (count == 2) {
- EditBonePoint *ebp, *ebp2;
+ EditBonePoint *ebp_a, *ebp_b;
float head[3], tail[3];
short headtail = 0;
/* check that the points don't belong to the same bone */
- ebp = (EditBonePoint *)points.first;
- ebp2 = ebp->next;
+ ebp_a = (EditBonePoint *)points.first;
+ ebp_b = ebp_a->next;
- if ((ebp->head_owner == ebp2->tail_owner) && (ebp->head_owner != NULL)) {
- BKE_report(op->reports, RPT_ERROR, "Same bone selected...");
- BLI_freelistN(&points);
- return OPERATOR_CANCELLED;
- }
- if ((ebp->tail_owner == ebp2->head_owner) && (ebp->tail_owner != NULL)) {
+ if (((ebp_a->head_owner == ebp_b->tail_owner) && (ebp_a->head_owner != NULL)) ||
+ ((ebp_a->tail_owner == ebp_b->head_owner) && (ebp_a->tail_owner != NULL)))
+ {
BKE_report(op->reports, RPT_ERROR, "Same bone selected...");
BLI_freelistN(&points);
return OPERATOR_CANCELLED;
}
/* find which one should be the 'head' */
- if ((ebp->head_owner && ebp2->head_owner) || (ebp->tail_owner && ebp2->tail_owner)) {
- /* rule: whichever one is closer to 3d-cursor */
- float curs[3];
- float vecA[3], vecB[3];
- float distA, distB;
-
- /* get cursor location */
- invert_m4_m4(obedit->imat, obedit->obmat);
- mul_v3_m4v3(curs, obedit->imat, ED_view3d_cursor3d_get(scene, v3d));
-
- /* get distances */
- sub_v3_v3v3(vecA, ebp->vec, curs);
- sub_v3_v3v3(vecB, ebp2->vec, curs);
- distA = len_v3(vecA);
- distB = len_v3(vecB);
-
- /* compare distances - closer one therefore acts as direction for bone to go */
- headtail = (distA < distB) ? 2 : 1;
+ if ((ebp_a->head_owner && ebp_b->head_owner) || (ebp_a->tail_owner && ebp_b->tail_owner)) {
+ /* use active, nice predictable */
+ if (arm->act_edbone && ELEM(arm->act_edbone, ebp_a->head_owner, ebp_a->tail_owner)) {
+ headtail = 1;
+ }
+ else if (arm->act_edbone && ELEM(arm->act_edbone, ebp_b->head_owner, ebp_b->tail_owner)) {
+ headtail = 2;
+ }
+ else {
+ /* rule: whichever one is closer to 3d-cursor */
+ float curs[3];
+ float dist_sq_a, dist_sq_b;
+
+ /* get cursor location */
+ invert_m4_m4(obedit->imat, obedit->obmat);
+ mul_v3_m4v3(curs, obedit->imat, ED_view3d_cursor3d_get(scene, v3d));
+
+ /* get distances */
+ dist_sq_a = len_squared_v3v3(ebp_a->vec, curs);
+ dist_sq_b = len_squared_v3v3(ebp_b->vec, curs);
+
+ /* compare distances - closer one therefore acts as direction for bone to go */
+ headtail = (dist_sq_a < dist_sq_b) ? 2 : 1;
+ }
}
- else if (ebp->head_owner) {
+ else if (ebp_a->head_owner) {
headtail = 1;
}
- else if (ebp2->head_owner) {
+ else if (ebp_b->head_owner) {
headtail = 2;
}
/* assign head/tail combinations */
if (headtail == 2) {
- copy_v3_v3(head, ebp->vec);
- copy_v3_v3(tail, ebp2->vec);
+ copy_v3_v3(head, ebp_a->vec);
+ copy_v3_v3(tail, ebp_b->vec);
}
else if (headtail == 1) {
- copy_v3_v3(head, ebp2->vec);
- copy_v3_v3(tail, ebp->vec);
+ copy_v3_v3(head, ebp_b->vec);
+ copy_v3_v3(tail, ebp_a->vec);
}
/* add new bone and parent it to the appropriate end */
if (headtail) {
- EditBone *newbone = add_points_bone(obedit, head, tail);
+ newbone = add_points_bone(obedit, head, tail);
/* do parenting (will need to set connected flag too) */
if (headtail == 2) {
/* ebp tail or head - tail gets priority */
- if (ebp->tail_owner)
- newbone->parent = ebp->tail_owner;
+ if (ebp_a->tail_owner)
+ newbone->parent = ebp_a->tail_owner;
else
- newbone->parent = ebp->head_owner;
+ newbone->parent = ebp_a->head_owner;
}
else {
- /* ebp2 tail or head - tail gets priority */
- if (ebp2->tail_owner)
- newbone->parent = ebp2->tail_owner;
+ /* ebp_b tail or head - tail gets priority */
+ if (ebp_b->tail_owner)
+ newbone->parent = ebp_b->tail_owner;
else
- newbone->parent = ebp2->head_owner;
+ newbone->parent = ebp_b->head_owner;
}
/* don't set for bone connecting two head points of bones */
- if (ebp->tail_owner || ebp2->tail_owner) {
+ if (ebp_a->tail_owner || ebp_b->tail_owner) {
newbone->flag |= BONE_CONNECTED;
}
}
@@ -676,6 +713,12 @@ static int armature_fill_bones_exec(bContext *C, wmOperator *op)
BLI_freelistN(&points);
return OPERATOR_CANCELLED;
}
+
+ if (newbone) {
+ ED_armature_deselect_all(obedit);
+ arm->act_edbone = newbone;
+ newbone->flag |= BONE_TIPSEL;
+ }
/* updates */
WM_event_add_notifier(C, NC_OBJECT | ND_POSE, obedit);
@@ -945,9 +988,7 @@ static int armature_switch_direction_exec(bContext *C, wmOperator *UNUSED(op))
/* only if selected and editable */
if (EBONE_VISIBLE(arm, ebo) && EBONE_EDITABLE(ebo)) {
/* swap head and tail coordinates */
- SWAP(float, ebo->head[0], ebo->tail[0]);
- SWAP(float, ebo->head[1], ebo->tail[1]);
- SWAP(float, ebo->head[2], ebo->tail[2]);
+ swap_v3_v3(ebo->head, ebo->tail);
/* do parent swapping:
* - use 'child' as new parent
@@ -1191,13 +1232,21 @@ void ARMATURE_OT_split(wmOperatorType *ot)
/* ********************************* Delete ******************************* */
+static bool armature_delete_ebone_cb(const char *bone_name, void *arm_p)
+{
+ bArmature *arm = arm_p;
+ EditBone *ebone;
+
+ ebone = ED_armature_bone_find_name(arm->edbo, bone_name);
+ return (ebone && (ebone->flag & BONE_SELECTED) && (arm->layer & ebone->layer));
+}
+
/* previously delete_armature */
/* only editmode! */
static int armature_delete_selected_exec(bContext *C, wmOperator *UNUSED(op))
{
bArmature *arm;
EditBone *curBone, *ebone_next;
- bConstraint *con;
Object *obedit = CTX_data_edit_object(C); // XXX get from context
bool changed = false;
arm = obedit->data;
@@ -1208,48 +1257,8 @@ static int armature_delete_selected_exec(bContext *C, wmOperator *UNUSED(op))
armature_select_mirrored(arm);
- /* First erase any associated pose channel */
- if (obedit->pose) {
- bPoseChannel *pchan, *pchan_next;
- for (pchan = obedit->pose->chanbase.first; pchan; pchan = pchan_next) {
- pchan_next = pchan->next;
- curBone = ED_armature_bone_find_name(arm->edbo, pchan->name);
-
- if (curBone && (curBone->flag & BONE_SELECTED) && (arm->layer & curBone->layer)) {
- BKE_pose_channel_free(pchan);
- BKE_pose_channels_hash_free(obedit->pose);
- BLI_freelinkN(&obedit->pose->chanbase, pchan);
- }
- else {
- for (con = pchan->constraints.first; con; con = con->next) {
- bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
- ListBase targets = {NULL, NULL};
- bConstraintTarget *ct;
-
- if (cti && cti->get_constraint_targets) {
- cti->get_constraint_targets(con, &targets);
-
- for (ct = targets.first; ct; ct = ct->next) {
- if (ct->tar == obedit) {
- if (ct->subtarget[0]) {
- curBone = ED_armature_bone_find_name(arm->edbo, ct->subtarget);
- if (curBone && (curBone->flag & BONE_SELECTED) && (arm->layer & curBone->layer)) {
- con->flag |= CONSTRAINT_DISABLE;
- ct->subtarget[0] = 0;
- }
- }
- }
- }
-
- if (cti->flush_constraint_targets)
- cti->flush_constraint_targets(con, &targets, 0);
- }
- }
- }
- }
- }
-
-
+ BKE_pose_channels_remove(obedit, armature_delete_ebone_cb, arm);
+
for (curBone = arm->edbo->first; curBone; curBone = ebone_next) {
ebone_next = curBone->next;
if (arm->layer & curBone->layer) {
@@ -1287,6 +1296,170 @@ void ARMATURE_OT_delete(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
+static bool armature_dissolve_ebone_cb(const char *bone_name, void *arm_p)
+{
+ bArmature *arm = arm_p;
+ EditBone *ebone;
+
+ ebone = ED_armature_bone_find_name(arm->edbo, bone_name);
+ return (ebone && (ebone->flag & BONE_DONE));
+}
+
+static int armature_dissolve_selected_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ bArmature *arm;
+ EditBone *ebone, *ebone_next;
+ Object *obedit = CTX_data_edit_object(C);
+ bool changed = false;
+
+ /* store for mirror */
+ GHash *ebone_flag_orig = NULL;
+ int ebone_num = 0;
+
+ arm = obedit->data;
+
+ for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
+ ebone->temp.p = NULL;
+ ebone->flag &= ~BONE_DONE;
+ ebone_num++;
+ }
+
+ if (arm->flag & ARM_MIRROR_EDIT) {
+ GHashIterator gh_iter;
+
+ ebone_flag_orig = BLI_ghash_ptr_new_ex(__func__, ebone_num);
+ for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
+ union { int flag; void *p; } val = {0};
+ val.flag = ebone->flag;
+ BLI_ghash_insert(ebone_flag_orig, ebone, val.p);
+ }
+
+ armature_select_mirrored_ex(arm, BONE_SELECTED | BONE_ROOTSEL | BONE_TIPSEL);
+
+ GHASH_ITER (gh_iter, ebone_flag_orig) {
+ union { int flag; void *p; } *val_p = (void *)BLI_ghashIterator_getValue_p(&gh_iter);
+ ebone = BLI_ghashIterator_getKey(&gh_iter);
+ val_p->flag = ebone->flag & ~val_p->flag;
+ }
+ }
+
+ for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
+ if (ebone->parent && ebone->flag & BONE_CONNECTED) {
+ if (ebone->parent->temp.ebone == ebone->parent) {
+ /* ignore */
+ }
+ else if (ebone->parent->temp.ebone) {
+ /* set ignored */
+ ebone->parent->temp.ebone = ebone->parent;
+ }
+ else {
+ /* set child */
+ ebone->parent->temp.ebone = ebone;
+ }
+ }
+ }
+
+ /* cleanup multiple used bones */
+ for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
+ if (ebone->temp.ebone == ebone) {
+ ebone->temp.ebone = NULL;
+ }
+ }
+
+ for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
+ /* break connections for unseen bones */
+ if (((arm->layer & ebone->layer) &&
+ ((ED_armature_ebone_selectflag_get(ebone) & (BONE_TIPSEL | BONE_SELECTED)))) == 0)
+ {
+ ebone->temp.ebone = NULL;
+ }
+
+ if (((arm->layer & ebone->layer) &&
+ ((ED_armature_ebone_selectflag_get(ebone) & (BONE_ROOTSEL | BONE_SELECTED)))) == 0)
+ {
+ if (ebone->parent && (ebone->flag & BONE_CONNECTED)) {
+ ebone->parent->temp.ebone = NULL;
+ }
+
+ }
+ }
+
+ for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
+
+ if (ebone->parent &&
+ (ebone->parent->temp.ebone == ebone))
+ {
+ ebone->flag |= BONE_DONE;
+ }
+ }
+
+ BKE_pose_channels_remove(obedit, armature_dissolve_ebone_cb, arm);
+
+ for (ebone = arm->edbo->first; ebone; ebone = ebone_next) {
+ ebone_next = ebone->next;
+
+ if (ebone->flag & BONE_DONE) {
+ copy_v3_v3(ebone->parent->tail, ebone->tail);
+ ebone->parent->rad_tail = ebone->rad_tail;
+
+ ED_armature_edit_bone_remove(arm, ebone);
+ changed = true;
+ }
+ }
+
+ if (changed) {
+ for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
+ if (ebone->parent &&
+ ebone->parent->temp.ebone &&
+ (ebone->flag & BONE_CONNECTED) == 0)
+ {
+ ebone->flag |= BONE_CONNECTED;
+ ebone->rad_head = ebone->parent->rad_head;
+ }
+ }
+
+ if (arm->flag & ARM_MIRROR_EDIT) {
+ for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
+ union { int flag; void *p; } *val_p = (void *)BLI_ghash_lookup_p(ebone_flag_orig, ebone);
+ if (val_p && val_p->flag) {
+ ebone->flag &= ~val_p->flag;
+ }
+ }
+ }
+ }
+
+ if (arm->flag & ARM_MIRROR_EDIT) {
+ BLI_ghash_free(ebone_flag_orig, NULL, NULL);
+ }
+
+ if (!changed) {
+ return OPERATOR_CANCELLED;
+ }
+
+ ED_armature_sync_selection(arm->edbo);
+
+ WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, obedit);
+
+ return OPERATOR_FINISHED;
+}
+
+void ARMATURE_OT_dissolve(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Dissolve Selected Bone(s)";
+ ot->idname = "ARMATURE_OT_dissolve";
+ ot->description = "Dissolve selected bones from the armature";
+
+ /* api callbacks */
+ ot->exec = armature_dissolve_selected_exec;
+ ot->poll = ED_operator_editarmature;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+
+
/* ********************************* Show/Hide ******************************* */
static int armature_hide_exec(bContext *C, wmOperator *op)
diff --git a/source/blender/editors/armature/armature_intern.h b/source/blender/editors/armature/armature_intern.h
index 6d616384b9a..2968851f2eb 100644
--- a/source/blender/editors/armature/armature_intern.h
+++ b/source/blender/editors/armature/armature_intern.h
@@ -71,7 +71,9 @@ 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_dissolve(struct wmOperatorType *ot);
void ARMATURE_OT_duplicate(struct wmOperatorType *ot);
+void ARMATURE_OT_symmetrize(struct wmOperatorType *ot);
void ARMATURE_OT_extrude(struct wmOperatorType *ot);
void ARMATURE_OT_hide(struct wmOperatorType *ot);
void ARMATURE_OT_reveal(struct wmOperatorType *ot);
@@ -215,7 +217,7 @@ void POSE_OT_propagate(struct wmOperatorType *ot);
*/
EditBone *make_boneList(struct ListBase *edbo, struct ListBase *bones, struct EditBone *parent, struct Bone *actBone);
-void BIF_sk_selectStroke(struct bContext *C, const int mval[2], short extend);
+bool BIF_sk_selectStroke(struct bContext *C, const int mval[2], const bool extend);
/* duplicate method */
void preEditBoneDuplicate(struct ListBase *editbones);
@@ -233,6 +235,7 @@ EditBone *add_points_bone(struct Object *obedit, float head[3], float tail[3]);
void bone_free(struct bArmature *arm, struct EditBone *bone);
void armature_tag_select_mirrored(struct bArmature *arm);
+void armature_select_mirrored_ex(struct bArmature *arm, const int flag);
void armature_select_mirrored(struct bArmature *arm);
void armature_tag_unselect(struct bArmature *arm);
diff --git a/source/blender/editors/armature/armature_naming.c b/source/blender/editors/armature/armature_naming.c
index 9afc45955bd..56dbdb3a639 100644
--- a/source/blender/editors/armature/armature_naming.c
+++ b/source/blender/editors/armature/armature_naming.c
@@ -38,7 +38,7 @@
#include "BLI_blenlib.h"
#include "BLI_ghash.h"
-#include "BLF_translation.h"
+#include "BLT_translation.h"
#include "BKE_animsys.h"
#include "BKE_action.h"
@@ -104,7 +104,7 @@ static void constraint_bone_name_fix(Object *ob, ListBase *conlist, const char *
bConstraintTarget *ct;
for (curcon = conlist->first; curcon; curcon = curcon->next) {
- bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(curcon);
+ const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(curcon);
ListBase targets = {NULL, NULL};
/* constraint targets */
@@ -141,7 +141,7 @@ void ED_armature_bone_rename(bArmature *arm, const char *oldnamep, const char *n
char oldname[MAXBONENAME];
/* names better differ! */
- if (strncmp(oldnamep, newnamep, MAXBONENAME)) {
+ if (!STREQLEN(oldnamep, newnamep, MAXBONENAME)) {
/* we alter newname string... so make copy */
BLI_strncpy(newname, newnamep, MAXBONENAME);
@@ -219,7 +219,7 @@ void ED_armature_bone_rename(bArmature *arm, const char *oldnamep, const char *n
if (ob->parent && (ob->parent->data == arm)) {
if (ob->partype == PARBONE) {
/* bone name in object */
- if (!strcmp(ob->parsubstr, oldname))
+ if (STREQ(ob->parsubstr, oldname))
BLI_strncpy(ob->parsubstr, newname, MAXBONENAME);
}
}
@@ -267,9 +267,10 @@ void ED_armature_bone_rename(bArmature *arm, const char *oldnamep, const char *n
/* Fix all animdata that may refer to this bone - we can't just do the ones attached to objects, since
* other ID-blocks may have drivers referring to this bone [#29822]
*/
+ // XXX: the ID here is for armatures, but most bone drivers are actually on the object instead...
{
- BKE_all_animdata_fix_paths_rename(&arm->id, "pose.bones", oldname, newname);
+ BKE_animdata_fix_paths_rename_all(&arm->id, "pose.bones", oldname, newname);
}
/* correct view locking */
@@ -284,7 +285,7 @@ void ED_armature_bone_rename(bArmature *arm, const char *oldnamep, const char *n
if (sl->spacetype == SPACE_VIEW3D) {
View3D *v3d = (View3D *)sl;
if (v3d->ob_centre && v3d->ob_centre->data == arm) {
- if (!strcmp(v3d->ob_centre_bone, oldname)) {
+ if (STREQ(v3d->ob_centre_bone, oldname)) {
BLI_strncpy(v3d->ob_centre_bone, newname, MAXBONENAME);
}
}
diff --git a/source/blender/editors/armature/armature_ops.c b/source/blender/editors/armature/armature_ops.c
index b7e38546ca2..e7f036f6911 100644
--- a/source/blender/editors/armature/armature_ops.c
+++ b/source/blender/editors/armature/armature_ops.c
@@ -28,8 +28,6 @@
* \ingroup edarmature
*/
-#include "BLI_math.h"
-
#include "RNA_access.h"
#include "WM_api.h"
@@ -67,7 +65,9 @@ void ED_operatortypes_armature(void)
WM_operatortype_append(ARMATURE_OT_shortest_path_pick);
WM_operatortype_append(ARMATURE_OT_delete);
+ WM_operatortype_append(ARMATURE_OT_dissolve);
WM_operatortype_append(ARMATURE_OT_duplicate);
+ WM_operatortype_append(ARMATURE_OT_symmetrize);
WM_operatortype_append(ARMATURE_OT_extrude);
WM_operatortype_append(ARMATURE_OT_hide);
WM_operatortype_append(ARMATURE_OT_reveal);
@@ -267,8 +267,9 @@ void ED_keymap_armature(wmKeyConfig *keyconf)
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);
+ WM_keymap_add_menu(keymap, "VIEW3D_MT_edit_armature_delete", XKEY, KM_PRESS, 0, 0);
+ WM_keymap_add_menu(keymap, "VIEW3D_MT_edit_armature_delete", DELKEY, KM_PRESS, 0, 0);
+ WM_keymap_add_item(keymap, "ARMATURE_OT_dissolve", XKEY, KM_PRESS, KM_CTRL, 0);
WM_keymap_add_item(keymap, "ARMATURE_OT_duplicate_move", DKEY, KM_PRESS, KM_SHIFT, 0);
WM_keymap_add_item(keymap, "ARMATURE_OT_extrude_move", EKEY, KM_PRESS, 0, 0);
WM_keymap_add_item(keymap, "ARMATURE_OT_extrude_forked", EKEY, KM_PRESS, KM_SHIFT, 0);
@@ -277,7 +278,7 @@ void ED_keymap_armature(wmKeyConfig *keyconf)
WM_keymap_add_item(keymap, "ARMATURE_OT_merge", MKEY, KM_PRESS, KM_ALT, 0);
WM_keymap_add_item(keymap, "ARMATURE_OT_split", YKEY, KM_PRESS, 0, 0);
- WM_keymap_add_item(keymap, "ARMATURE_OT_separate", PKEY, KM_PRESS, KM_CTRL | KM_ALT, 0);
+ WM_keymap_add_item(keymap, "ARMATURE_OT_separate", PKEY, KM_PRESS, 0, 0);
/* set flags */
WM_keymap_add_menu(keymap, "VIEW3D_MT_bone_options_toggle", WKEY, KM_PRESS, KM_SHIFT, 0);
@@ -368,7 +369,7 @@ void ED_keymap_armature(wmKeyConfig *keyconf)
WM_keymap_add_item(keymap, "POSE_OT_select_linked", LKEY, KM_PRESS, 0, 0);
WM_keymap_add_item(keymap, "POSE_OT_select_grouped", GKEY, KM_PRESS, KM_SHIFT, 0);
- WM_keymap_add_item(keymap, "POSE_OT_select_mirror", FKEY, KM_PRESS, KM_SHIFT, 0);
+ WM_keymap_add_item(keymap, "POSE_OT_select_mirror", FKEY, KM_PRESS, KM_SHIFT | KM_CTRL, 0);
WM_keymap_add_item(keymap, "POSE_OT_constraint_add_with_targets", CKEY, KM_PRESS, KM_CTRL | KM_SHIFT, 0);
WM_keymap_add_item(keymap, "POSE_OT_constraints_clear", CKEY, KM_PRESS, KM_CTRL | KM_ALT, 0);
@@ -413,5 +414,6 @@ void ED_keymap_armature(wmKeyConfig *keyconf)
/* menus */
WM_keymap_add_menu(keymap, "VIEW3D_MT_pose_specials", WKEY, KM_PRESS, 0, 0);
+ WM_keymap_add_menu(keymap, "VIEW3D_MT_pose_propagate", PKEY, KM_PRESS, KM_ALT, 0);
}
diff --git a/source/blender/editors/armature/armature_relations.c b/source/blender/editors/armature/armature_relations.c
index 75fa4a5433f..1c342657eec 100644
--- a/source/blender/editors/armature/armature_relations.c
+++ b/source/blender/editors/armature/armature_relations.c
@@ -29,20 +29,26 @@
* \ingroup edarmature
*/
+#include "MEM_guardedalloc.h"
+
+#include "DNA_anim_types.h"
#include "DNA_armature_types.h"
#include "DNA_constraint_types.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
#include "BLI_blenlib.h"
+#include "BLI_ghash.h"
#include "BLI_math.h"
-#include "BLF_translation.h"
+#include "BLT_translation.h"
#include "BKE_action.h"
+#include "BKE_animsys.h"
#include "BKE_constraint.h"
#include "BKE_context.h"
#include "BKE_depsgraph.h"
+#include "BKE_fcurve.h"
#include "BKE_global.h"
#include "BKE_main.h"
#include "BKE_report.h"
@@ -72,7 +78,7 @@ static void joined_armature_fix_links_constraints(
bConstraint *con;
for (con = lb->first; con; con = con->next) {
- bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
+ const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
ListBase targets = {NULL, NULL};
bConstraintTarget *ct;
@@ -98,33 +104,122 @@ static void joined_armature_fix_links_constraints(
/* action constraint? (pose constraints only) */
if (con->type == CONSTRAINT_TYPE_ACTION) {
- bActionConstraint *data = con->data; // XXX old animation system
- bAction *act;
- bActionChannel *achan;
+ bActionConstraint *data = con->data;
if (data->act) {
- act = data->act;
+ BKE_action_fix_paths_rename(&tarArm->id, data->act, "pose.bones[",
+ pchan->name, curbone->name, 0, 0, false);
+ }
+ }
+
+ }
+}
- for (achan = act->chanbase.first; achan; achan = achan->next) {
- if (STREQ(achan->name, pchan->name)) {
- BLI_strncpy(achan->name, curbone->name, sizeof(achan->name));
+/* userdata for joined_armature_fix_animdata_cb() */
+typedef struct tJoinArmature_AdtFixData {
+ Object *srcArm;
+ Object *tarArm;
+
+ GHash *names_map;
+} tJoinArmature_AdtFixData;
+
+/* Callback to pass to void BKE_animdata_main_cb() for fixing driver ID's to point to the new ID */
+/* FIXME: For now, we only care about drivers here. When editing rigs, it's very rare to have animation
+ * on the rigs being edited already, so it should be safe to skip these.
+ */
+static void joined_armature_fix_animdata_cb(ID *id, AnimData *adt, void *user_data)
+{
+ tJoinArmature_AdtFixData *afd = (tJoinArmature_AdtFixData *)user_data;
+ ID *src_id = &afd->srcArm->id;
+ ID *dst_id = &afd->tarArm->id;
+
+ GHashIterator gh_iter;
+ FCurve *fcu;
+
+ /* Fix paths - If this is the target object, it will have some "dirty" paths */
+ if (id == src_id) {
+ /* Fix drivers */
+ for (fcu = adt->drivers.first; fcu; fcu = fcu->next) {
+ /* skip driver if it doesn't affect the bones */
+ if (strstr(fcu->rna_path, "pose.bones[") == NULL) {
+ continue;
+ }
+
+ // FIXME: this is too crude... it just does everything!
+ GHASH_ITER(gh_iter, afd->names_map) {
+ const char *old_name = BLI_ghashIterator_getKey(&gh_iter);
+ const char *new_name = BLI_ghashIterator_getValue(&gh_iter);
+
+ /* only remap if changed; this still means there will be some waste if there aren't many drivers/keys */
+ if (!STREQ(old_name, new_name) && strstr(fcu->rna_path, old_name)) {
+ fcu->rna_path = BKE_animsys_fix_rna_path_rename(id, fcu->rna_path, "pose.bones",
+ old_name, new_name, 0, 0, false);
+
+ /* we don't want to apply a second remapping on this driver now,
+ * so stop trying names, but keep fixing drivers
+ */
+ break;
+ }
+ }
+ }
+ }
+
+
+ /* Driver targets */
+ for (fcu = adt->drivers.first; fcu; fcu = fcu->next) {
+ ChannelDriver *driver = fcu->driver;
+ DriverVar *dvar;
+
+ /* Fix driver references to invalid ID's */
+ for (dvar = driver->variables.first; dvar; dvar = dvar->next) {
+ /* only change the used targets, since the others will need fixing manually anyway */
+ DRIVER_TARGETS_USED_LOOPER(dvar)
+ {
+ /* change the ID's used... */
+ if (dtar->id == src_id) {
+ dtar->id = dst_id;
+
+ /* also check on the subtarget...
+ * XXX: We duplicate the logic from drivers_path_rename_fix() here, with our own
+ * little twists so that we know that it isn't going to clobber the wrong data
+ */
+ if ((dtar->rna_path && strstr(dtar->rna_path, "pose.bones[")) || (dtar->pchan_name[0])) {
+ GHASH_ITER(gh_iter, afd->names_map) {
+ const char *old_name = BLI_ghashIterator_getKey(&gh_iter);
+ const char *new_name = BLI_ghashIterator_getValue(&gh_iter);
+
+ /* only remap if changed */
+ if (!STREQ(old_name, new_name)) {
+ if ((dtar->rna_path) && strstr(dtar->rna_path, old_name)) {
+ /* Fix up path */
+ dtar->rna_path = BKE_animsys_fix_rna_path_rename(id, dtar->rna_path, "pose.bones",
+ old_name, new_name, 0, 0, false);
+ break; /* no need to try any more names for bone path */
+ }
+ else if (STREQ(dtar->pchan_name, old_name)) {
+ /* Change target bone name */
+ BLI_strncpy(dtar->pchan_name, new_name, sizeof(dtar->pchan_name));
+ break; /* no need to try any more names for bone subtarget */
+ }
+ }
+ }
}
}
}
+ DRIVER_TARGETS_LOOPER_END
}
-
}
}
/* Helper function for armature joining - link fixing */
-static void joined_armature_fix_links(Object *tarArm, Object *srcArm, bPoseChannel *pchan, EditBone *curbone)
+static void joined_armature_fix_links(Main *bmain, Object *tarArm, Object *srcArm, bPoseChannel *pchan, EditBone *curbone)
{
Object *ob;
bPose *pose;
bPoseChannel *pchant;
/* let's go through all objects in database */
- for (ob = G.main->object.first; ob; ob = ob->id.next) {
+ for (ob = bmain->object.first; ob; ob = ob->id.next) {
/* do some object-type specific things */
if (ob->type == OB_ARMATURE) {
pose = ob->pose;
@@ -198,8 +293,17 @@ int join_armature_exec(bContext *C, wmOperator *op)
CTX_DATA_BEGIN(C, Base *, base, selected_editable_bases)
{
if ((base->object->type == OB_ARMATURE) && (base->object != ob)) {
+ tJoinArmature_AdtFixData afd = {NULL};
bArmature *curarm = base->object->data;
+ /* we assume that each armature datablock is only used in a single place */
+ BLI_assert(ob->data != base->object->data);
+
+ /* init callback data for fixing up AnimData links later */
+ afd.srcArm = base->object;
+ afd.tarArm = ob;
+ afd.names_map = BLI_ghash_str_new("join_armature_adt_fix");
+
/* Make a list of editbones in current armature */
ED_armature_to_edit(base->object->data);
@@ -219,6 +323,7 @@ int join_armature_exec(bContext *C, wmOperator *op)
/* Get new name */
unique_editbone_name(arm->edbo, curbone->name, NULL);
+ BLI_ghash_insert(afd.names_map, BLI_strdup(pchan->name), curbone->name);
/* Transform the bone */
{
@@ -249,7 +354,7 @@ int join_armature_exec(bContext *C, wmOperator *op)
}
/* Fix Constraints and Other Links to this Bone and Armature */
- joined_armature_fix_links(ob, base->object, pchan, curbone);
+ joined_armature_fix_links(bmain, ob, base->object, pchan, curbone);
/* Rename pchan */
BLI_strncpy(pchan->name, curbone->name, sizeof(pchan->name));
@@ -264,6 +369,37 @@ int join_armature_exec(bContext *C, wmOperator *op)
BKE_pose_channels_hash_free(pose);
}
+ /* Fix all the drivers (and animation data) */
+ BKE_animdata_main_cb(bmain, joined_armature_fix_animdata_cb, &afd);
+ BLI_ghash_free(afd.names_map, MEM_freeN, NULL);
+
+ /* Only copy over animdata now, after all the remapping has been done,
+ * so that we don't have to worry about ambiguities re which armature
+ * a bone came from!
+ */
+ if (base->object->adt) {
+ if (ob->adt == NULL) {
+ /* no animdata, so just use a copy of the whole thing */
+ ob->adt = BKE_animdata_copy(base->object->adt, false);
+ }
+ else {
+ /* merge in data - we'll fix the drivers manually */
+ BKE_animdata_merge_copy(&ob->id, &base->object->id, ADT_MERGECOPY_KEEP_DST, false);
+ }
+ }
+
+ if (curarm->adt) {
+ if (arm->adt == NULL) {
+ /* no animdata, so just use a copy of the whole thing */
+ arm->adt = BKE_animdata_copy(curarm->adt, false);
+ }
+ else {
+ /* merge in data - we'll fix the drivers manually */
+ BKE_animdata_merge_copy(&arm->id, &curarm->id, ADT_MERGECOPY_KEEP_DST, false);
+ }
+ }
+
+ /* Free the old object data */
ED_base_object_free_and_unlink(bmain, scene, base);
}
}
@@ -299,7 +435,7 @@ static void separated_armature_fix_links(Object *origArm, Object *newArm)
if (ob->type == OB_ARMATURE) {
for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
for (con = pchan->constraints.first; con; con = con->next) {
- bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
+ const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
ListBase targets = {NULL, NULL};
bConstraintTarget *ct;
@@ -337,7 +473,7 @@ static void separated_armature_fix_links(Object *origArm, Object *newArm)
/* fix object-level constraints */
if (ob != origArm) {
for (con = ob->constraints.first; con; con = con->next) {
- bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
+ const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
ListBase targets = {NULL, NULL};
bConstraintTarget *ct;
@@ -412,7 +548,7 @@ static void separate_armature_bones(Object *ob, short sel)
for (ebo = arm->edbo->first; ebo; ebo = ebo->next) {
if (ebo->parent == curbone) {
ebo->parent = NULL;
- ebo->temp = NULL; /* this is needed to prevent random crashes with in ED_armature_from_edit */
+ ebo->temp.p = NULL; /* this is needed to prevent random crashes with in ED_armature_from_edit */
ebo->flag &= ~BONE_CONNECTED;
}
}
@@ -505,6 +641,9 @@ static int separate_armature_exec(bContext *C, wmOperator *op)
ED_armature_to_edit(obedit->data);
+ /* parents tips remain selected when connected children are removed. */
+ ED_armature_deselect_all(obedit);
+
BKE_report(op->reports, RPT_INFO, "Separated bones");
/* note, notifier might evolve */
@@ -524,6 +663,7 @@ 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;
@@ -673,8 +813,8 @@ static int armature_parent_set_exec(bContext *C, wmOperator *op)
static int armature_parent_set_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *UNUSED(event))
{
EditBone *actbone = CTX_data_active_bone(C);
- uiPopupMenu *pup = uiPupMenuBegin(C, CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Make Parent"), ICON_NONE);
- uiLayout *layout = uiPupMenuLayout(pup);
+ uiPopupMenu *pup = UI_popup_menu_begin(C, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Make Parent"), ICON_NONE);
+ uiLayout *layout = UI_popup_menu_layout(pup);
int allchildbones = 0;
CTX_DATA_BEGIN(C, EditBone *, ebone, selected_editable_bones)
@@ -691,9 +831,9 @@ static int armature_parent_set_invoke(bContext *C, wmOperator *UNUSED(op), const
if (allchildbones)
uiItemEnumO(layout, "ARMATURE_OT_parent_set", NULL, 0, "type", ARM_PAR_OFFSET);
- uiPupMenuEnd(C, pup);
+ UI_popup_menu_end(C, pup);
- return OPERATOR_CANCELLED;
+ return OPERATOR_INTERFACE;
}
void ARMATURE_OT_parent_set(wmOperatorType *ot)
diff --git a/source/blender/editors/armature/armature_select.c b/source/blender/editors/armature/armature_select.c
index d85a730c88e..dbbdae280f2 100644
--- a/source/blender/editors/armature/armature_select.c
+++ b/source/blender/editors/armature/armature_select.c
@@ -54,9 +54,9 @@
#include "armature_intern.h"
-/* utility macros fro storing a temp int in the bone (selection flag) */
-#define EBONE_PREV_FLAG_GET(ebone) ((void)0, (GET_INT_FROM_POINTER((ebone)->temp)))
-#define EBONE_PREV_FLAG_SET(ebone, val) ((ebone)->temp = SET_INT_IN_POINTER(val))
+/* utility macros for storing a temp int in the bone (selection flag) */
+#define EBONE_PREV_FLAG_GET(ebone) ((void)0, (ebone)->temp.i)
+#define EBONE_PREV_FLAG_SET(ebone, val) ((ebone)->temp.i = val)
/* **************** PoseMode & EditMode Selection Buffer Queries *************************** */
@@ -126,7 +126,7 @@ void *get_bone_from_selectbuffer(Scene *scene, Base *base, unsigned int *buffer,
if (sel) {
if (do_nearest) {
if (minsel > buffer[4 * i + 1]) {
- firstSel = bone;
+ firstSel = data;
minsel = buffer[4 * i + 1];
}
}
@@ -138,12 +138,11 @@ void *get_bone_from_selectbuffer(Scene *scene, Base *base, unsigned int *buffer,
else {
if (do_nearest) {
if (minunsel > buffer[4 * i + 1]) {
- firstunSel = bone;
+ firstunSel = data;
minunsel = buffer[4 * i + 1];
}
}
- else
- {
+ else {
if (!firstunSel) firstunSel = data;
if (takeNext) return data;
}
@@ -175,7 +174,6 @@ void *get_nearest_bone(bContext *C, short findunsel, int x, int y)
rect.xmin = rect.xmax = x;
rect.ymin = rect.ymax = y;
- glInitNames();
hits = view3d_opengl_select(&vc, buffer, MAXPICKBUF, &rect, true);
if (hits > 0)
@@ -255,7 +253,7 @@ static int armature_select_linked_invoke(bContext *C, wmOperator *op, const wmEv
static int armature_select_linked_poll(bContext *C)
{
- return (ED_operator_view3d_active(C) && ED_operator_editarmature(C) );
+ return (ED_operator_view3d_active(C) && ED_operator_editarmature(C));
}
void ARMATURE_OT_select_linked(wmOperatorType *ot)
@@ -289,11 +287,9 @@ static EditBone *get_nearest_editbonepoint(ViewContext *vc, const int mval[2],
rcti rect;
unsigned int buffer[MAXPICKBUF];
unsigned int hitresult, besthitresult = BONESEL_NOSEL;
- int i, mindep = 4;
+ int i, mindep = 5;
short hits;
- glInitNames();
-
/* find the bone after the current active bone, so as to bump up its chances in selection.
* this way overlapping bones will cycle selection state as with objects. */
if (ebone_next_act &&
@@ -346,16 +342,16 @@ static EditBone *get_nearest_editbonepoint(ViewContext *vc, const int mval[2],
dep = 2;
}
else {
- dep = 2;
+ dep = 1;
}
}
else {
/* bone found */
if (findunsel) {
if ((ebone->flag & BONE_SELECTED) == 0)
- dep = 2;
- else
dep = 3;
+ else
+ dep = 4;
}
else {
dep = 3;
@@ -392,61 +388,14 @@ static EditBone *get_nearest_editbonepoint(ViewContext *vc, const int mval[2],
return NULL;
}
-
-
-/* toggle==0: deselect
- * toggle==1: swap (based on test)
- * toggle==2: swap (no test), CURRENTLY UNUSED
- */
-void ED_armature_deselect_all(Object *obedit, int toggle)
+void ED_armature_deselect_all(Object *obedit)
{
bArmature *arm = obedit->data;
- EditBone *eBone;
- int sel = 1;
-
- if (toggle == 1) {
- /* Determine if there are any selected bones
- * and therefore whether we are selecting or deselecting */
- for (eBone = arm->edbo->first; eBone; eBone = eBone->next) {
- // if (arm->layer & eBone->layer) {
- if (eBone->flag & (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL)) {
- sel = 0;
- break;
- }
- // }
- }
- }
- else {
- sel = toggle;
- }
+ EditBone *ebone;
- /* Set the flags */
- for (eBone = arm->edbo->first; eBone; eBone = eBone->next) {
- if (sel == 2) {
- /* invert selection of bone */
- if (EBONE_VISIBLE(arm, eBone)) {
- eBone->flag ^= (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
- if (arm->act_edbone == eBone)
- arm->act_edbone = NULL;
- }
- }
- else if (sel == 1) {
- /* select bone */
- if (EBONE_VISIBLE(arm, eBone)) {
- eBone->flag |= (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
- if (eBone->parent)
- eBone->parent->flag |= (BONE_TIPSEL);
- }
- }
- else {
- /* deselect bone */
- eBone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
- if (arm->act_edbone == eBone)
- arm->act_edbone = NULL;
- }
+ for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
+ ebone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
}
-
- ED_armature_sync_selection(arm->edbo);
}
void ED_armature_deselect_all_visible(Object *obedit)
@@ -486,13 +435,16 @@ bool mouse_armature(bContext *C, const int mval[2], bool extend, bool deselect,
view3d_set_viewcontext(C, &vc);
- BIF_sk_selectStroke(C, mval, extend);
+ if (BIF_sk_selectStroke(C, mval, extend)) {
+ return true;
+ }
nearBone = get_nearest_editbonepoint(&vc, mval, arm->edbo, 1, &selmask);
if (nearBone) {
- if (!extend && !deselect && !toggle)
- ED_armature_deselect_all(obedit, 0);
+ if (!extend && !deselect && !toggle) {
+ ED_armature_deselect_all(obedit);
+ }
/* by definition the non-root connected bones have no root point drawn,
* so a root selection needs to be delivered to the parent tip */
@@ -733,7 +685,7 @@ static void armature_select_more_less(Object *ob, bool more)
}
}
}
- ebone->temp = NULL;
+ ebone->temp.p = NULL;
}
ED_armature_sync_selection(arm->edbo);
@@ -958,81 +910,84 @@ void ARMATURE_OT_select_similar(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
/* properties */
- ot->prop = RNA_def_enum(ot->srna, "type", prop_similar_types, 0, "Type", "");
+ ot->prop = RNA_def_enum(ot->srna, "type", prop_similar_types, SIMEDBONE_LENGTH, "Type", "");
RNA_def_float(ot->srna, "threshold", 0.1f, 0.0f, 1.0f, "Threshold", "", 0.0f, 1.0f);
}
/* ********************* select hierarchy operator ************** */
-/* Get the first available child of an editbone */
-static EditBone *editbone_get_child(bArmature *arm, EditBone *pabone, short use_visibility)
-{
- EditBone *curbone, *chbone = NULL;
-
- for (curbone = arm->edbo->first; curbone; curbone = curbone->next) {
- if (curbone->parent == pabone) {
- if (use_visibility) {
- if ((arm->layer & curbone->layer) && !(pabone->flag & BONE_HIDDEN_A)) {
- chbone = curbone;
- }
- }
- else
- chbone = curbone;
- }
- }
-
- return chbone;
-}
-
static int armature_select_hierarchy_exec(bContext *C, wmOperator *op)
{
Object *obedit = CTX_data_edit_object(C);
Object *ob;
bArmature *arm;
- EditBone *curbone, *pabone, *chbone;
+ EditBone *ebone_active;
int direction = RNA_enum_get(op->ptr, "direction");
const bool add_to_sel = RNA_boolean_get(op->ptr, "extend");
+ bool changed = false;
ob = obedit;
arm = (bArmature *)ob->data;
-
- for (curbone = arm->edbo->first; curbone; curbone = curbone->next) {
- /* only work on bone if it is visible and its selection can change */
- if (EBONE_SELECTABLE(arm, curbone)) {
- if (curbone == arm->act_edbone) {
- if (direction == BONE_SELECT_PARENT) {
- if (curbone->parent == NULL) continue;
- else pabone = curbone->parent;
-
- if (EBONE_VISIBLE(arm, pabone)) {
- pabone->flag |= (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
- arm->act_edbone = pabone;
- if (pabone->parent) pabone->parent->flag |= BONE_TIPSEL;
-
- if (!add_to_sel) curbone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
- break;
- }
-
+
+ ebone_active = arm->act_edbone;
+ if (ebone_active == NULL) {
+ return OPERATOR_CANCELLED;
+ }
+
+ if (direction == BONE_SELECT_PARENT) {
+ if (ebone_active->parent) {
+ EditBone *ebone_parent;
+
+ ebone_parent = ebone_active->parent;
+
+ if (EBONE_SELECTABLE(arm, ebone_parent)) {
+ arm->act_edbone = ebone_parent;
+
+ if (!add_to_sel) {
+ ED_armature_ebone_select_set(ebone_active, false);
}
- else { // BONE_SELECT_CHILD
- chbone = editbone_get_child(arm, curbone, 1);
- if (chbone == NULL) continue;
-
- if (EBONE_SELECTABLE(arm, chbone)) {
- chbone->flag |= (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
- arm->act_edbone = chbone;
-
- if (!add_to_sel) {
- curbone->flag &= ~(BONE_SELECTED | BONE_ROOTSEL);
- if (curbone->parent) curbone->parent->flag &= ~BONE_TIPSEL;
+ ED_armature_ebone_select_set(ebone_parent, true);
+
+ changed = true;
+ }
+ }
+
+ }
+ else { /* BONE_SELECT_CHILD */
+ EditBone *ebone_iter, *ebone_child = NULL;
+ int pass;
+
+ /* first pass, only connected bones (the logical direct child) */
+ for (pass = 0; pass < 2 && (ebone_child == NULL); pass++) {
+ for (ebone_iter = arm->edbo->first; ebone_iter; ebone_iter = ebone_iter->next) {
+ /* possible we have multiple children, some invisible */
+ if (EBONE_SELECTABLE(arm, ebone_iter)) {
+ if (ebone_iter->parent == ebone_active) {
+ if ((pass == 1) || (ebone_iter->flag & BONE_CONNECTED)) {
+ ebone_child = ebone_iter;
+ break;
}
- break;
}
}
}
}
+
+ if (ebone_child) {
+ arm->act_edbone = ebone_child;
+
+ if (!add_to_sel) {
+ ED_armature_ebone_select_set(ebone_active, false);
+ }
+ ED_armature_ebone_select_set(ebone_child, true);
+
+ changed = true;
+ }
}
+ if (changed == false) {
+ return OPERATOR_CANCELLED;
+ }
+
ED_armature_sync_selection(arm->edbo);
WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, ob);
diff --git a/source/blender/editors/armature/armature_skinning.c b/source/blender/editors/armature/armature_skinning.c
index fbc18e977ce..ea1a94fbba6 100644
--- a/source/blender/editors/armature/armature_skinning.c
+++ b/source/blender/editors/armature/armature_skinning.c
@@ -43,6 +43,7 @@
#include "BKE_action.h"
#include "BKE_armature.h"
#include "BKE_deform.h"
+#include "BKE_object_deform.h"
#include "BKE_report.h"
#include "BKE_subsurf.h"
#include "BKE_modifier.h"
@@ -52,7 +53,10 @@
#include "armature_intern.h"
-#include "meshlaplacian.h"
+
+#ifdef WITH_OPENNL
+# include "meshlaplacian.h"
+#endif
#if 0
#include "reeb.h"
@@ -117,7 +121,7 @@ static int vgroup_add_unique_bone_cb(Object *ob, Bone *bone, void *UNUSED(ptr))
*/
if (!(bone->flag & BONE_NO_DEFORM)) {
if (!defgroup_find_name(ob, bone->name)) {
- ED_vgroup_add_name(ob, bone->name);
+ BKE_object_defgroup_add_name(ob, bone->name);
return 1;
}
}
@@ -162,9 +166,15 @@ static int dgroup_skinnable_cb(Object *ob, Bone *bone, void *datap)
else
segments = 1;
- if (!wpmode || ((arm->layer & bone->layer) && (bone->flag & BONE_SELECTED)))
- if (!(defgroup = defgroup_find_name(ob, bone->name)))
- defgroup = ED_vgroup_add_name(ob, bone->name);
+ if (!wpmode || ((arm->layer & bone->layer) && (bone->flag & BONE_SELECTED))) {
+ if (!(defgroup = defgroup_find_name(ob, bone->name))) {
+ defgroup = BKE_object_defgroup_add_name(ob, bone->name);
+ }
+ else if (defgroup->flag & DG_LOCK_WEIGHT) {
+ /* In case vgroup already exists and is locked, do not modify it here. See T43814. */
+ defgroup = NULL;
+ }
+ }
if (data->list != NULL) {
hgroup = (bDeformGroup ***) &data->list;
@@ -238,7 +248,8 @@ static void envelope_bone_weighting(Object *ob, Mesh *mesh, float (*verts)[3], i
}
}
-static void add_verts_to_dgroups(ReportList *reports, Scene *scene, Object *ob, Object *par, int heat, bool mirror)
+static void add_verts_to_dgroups(ReportList *reports, Scene *scene, Object *ob, Object *par,
+ int heat, const bool mirror)
{
/* This functions implements the automatic computation of vertex group
* weights, either through envelopes or using a heat equilibrium.
@@ -275,7 +286,7 @@ static void add_verts_to_dgroups(ReportList *reports, Scene *scene, Object *ob,
if (numbones == 0)
return;
- if (ED_vgroup_data_create(ob->data) == false)
+ if (BKE_object_defgroup_data_create(ob->data) == NULL)
return;
/* create an array of pointer to bones that are skinnable
@@ -418,7 +429,8 @@ static void add_verts_to_dgroups(ReportList *reports, Scene *scene, Object *ob,
MEM_freeN(verts);
}
-void create_vgroups_from_armature(ReportList *reports, Scene *scene, Object *ob, Object *par, int mode, bool mirror)
+void create_vgroups_from_armature(ReportList *reports, Scene *scene, Object *ob, Object *par,
+ const int mode, const bool mirror)
{
/* Lets try to create some vertex groups
* based on the bones of the parent armature.
@@ -426,7 +438,7 @@ void create_vgroups_from_armature(ReportList *reports, Scene *scene, Object *ob,
bArmature *arm = par->data;
if (mode == ARM_GROUPS_NAME) {
- const int defbase_tot = BLI_countlist(&ob->defbase);
+ const int defbase_tot = BLI_listbase_count(&ob->defbase);
int defbase_add;
/* Traverse the bone list, trying to create empty vertex
* groups corresponding to the bone.
@@ -439,7 +451,7 @@ void create_vgroups_from_armature(ReportList *reports, Scene *scene, Object *ob,
ED_vgroup_data_clamp_range(ob->data, defbase_tot);
}
}
- else if (mode == ARM_GROUPS_ENVELOPE || mode == ARM_GROUPS_AUTO) {
+ else if (ELEM(mode, ARM_GROUPS_ENVELOPE, ARM_GROUPS_AUTO)) {
/* Traverse the bone list, trying to create vertex groups
* that are populated with the vertices for which the
* bone is closest.
diff --git a/source/blender/editors/armature/armature_utils.c b/source/blender/editors/armature/armature_utils.c
index 97f69d86aee..61ed7fdc41b 100644
--- a/source/blender/editors/armature/armature_utils.c
+++ b/source/blender/editors/armature/armature_utils.c
@@ -276,18 +276,19 @@ EditBone *ED_armature_bone_get_mirrored(const ListBase *edbo, EditBone *ebo)
/* helper function for tools to work on mirrored parts.
* it leaves mirrored bones selected then too, which is a good indication of what happened */
-void armature_select_mirrored(bArmature *arm)
+void armature_select_mirrored_ex(bArmature *arm, const int flag)
{
+ BLI_assert((flag & ~(BONE_SELECTED | BONE_ROOTSEL | BONE_TIPSEL)) == 0);
/* Select mirrored bones */
if (arm->flag & ARM_MIRROR_EDIT) {
EditBone *curBone, *ebone_mirr;
for (curBone = arm->edbo->first; curBone; curBone = curBone->next) {
if (arm->layer & curBone->layer) {
- if (curBone->flag & BONE_SELECTED) {
+ if (curBone->flag & flag) {
ebone_mirr = ED_armature_bone_get_mirrored(arm->edbo, curBone);
if (ebone_mirr)
- ebone_mirr->flag |= BONE_SELECTED;
+ ebone_mirr->flag |= (curBone->flag & flag);
}
}
}
@@ -295,6 +296,11 @@ void armature_select_mirrored(bArmature *arm)
}
+void armature_select_mirrored(bArmature *arm)
+{
+ armature_select_mirrored_ex(arm, BONE_SELECTED);
+}
+
void armature_tag_select_mirrored(bArmature *arm)
{
EditBone *curBone;
@@ -471,48 +477,78 @@ EditBone *make_boneList(ListBase *edbo, ListBase *bones, EditBone *parent, Bone
return eBoneAct;
}
-/* nasty stuff for converting roll in editbones into bones */
-/* also sets restposition in armature (arm_mat) */
-static void fix_bonelist_roll(ListBase *bonelist, ListBase *editbonelist)
+/* This function:
+ * - sets local head/tail rest locations using parent bone's arm_mat.
+ * - calls BKE_armature_where_is_bone() which uses parent's transform (arm_mat) to define this bone's transform.
+ * - fixes (converts) EditBone roll into Bone roll.
+ * - calls again BKE_armature_where_is_bone(), since roll fiddling may have changed things for our bone...
+ * Note that order is crucial here, we can only handle child if all its parents in chain have already been handled
+ * (this is ensured by recursive process). */
+static void armature_finalize_restpose(ListBase *bonelist, ListBase *editbonelist)
{
Bone *curBone;
EditBone *ebone;
- float premat[3][3];
- float postmat[3][3];
- float difmat[3][3];
- float imat[3][3];
-
+
for (curBone = bonelist->first; curBone; curBone = curBone->next) {
- /* sets local matrix and arm_mat (restpos) */
- BKE_armature_where_is_bone(curBone, curBone->parent);
-
+ /* Set bone's local head/tail.
+ * Note that it's important to use final parent's restpose (arm_mat) here, instead of setting those values
+ * from editbone's matrix (see T46010). */
+ if (curBone->parent) {
+ float parmat_inv[4][4];
+
+ invert_m4_m4(parmat_inv, curBone->parent->arm_mat);
+
+ /* Get the new head and tail */
+ sub_v3_v3v3(curBone->head, curBone->arm_head, curBone->parent->arm_tail);
+ sub_v3_v3v3(curBone->tail, curBone->arm_tail, curBone->parent->arm_tail);
+
+ mul_mat3_m4_v3(parmat_inv, curBone->head);
+ mul_mat3_m4_v3(parmat_inv, curBone->tail);
+ }
+ else {
+ copy_v3_v3(curBone->head, curBone->arm_head);
+ copy_v3_v3(curBone->tail, curBone->arm_tail);
+ }
+
+ /* Set local matrix and arm_mat (restpose).
+ * Do not recurse into children here, armature_finalize_restpose() is already recursive. */
+ BKE_armature_where_is_bone(curBone, curBone->parent, false);
+
/* Find the associated editbone */
- for (ebone = editbonelist->first; ebone; ebone = ebone->next)
- if ((Bone *)ebone->temp == curBone)
- break;
-
- if (ebone) {
- /* Get the ebone premat */
- ED_armature_ebone_to_mat3(ebone, premat);
-
- /* Get the bone postmat */
- copy_m3_m4(postmat, curBone->arm_mat);
-
- invert_m3_m3(imat, premat);
- mul_m3_m3m3(difmat, imat, postmat);
+ for (ebone = editbonelist->first; ebone; ebone = ebone->next) {
+ if (ebone->temp.bone == curBone) {
+ float premat[3][3];
+ float postmat[3][3];
+ float difmat[3][3];
+ float imat[3][3];
+
+ /* Get the ebone premat and its inverse. */
+ ED_armature_ebone_to_mat3(ebone, premat);
+ invert_m3_m3(imat, premat);
+
+ /* Get the bone postmat. */
+ copy_m3_m4(postmat, curBone->arm_mat);
+
+ mul_m3_m3m3(difmat, imat, postmat);
+
#if 0
- printf("Bone %s\n", curBone->name);
- print_m4("premat", premat);
- print_m4("postmat", postmat);
- print_m4("difmat", difmat);
- printf("Roll = %f\n", RAD2DEGF(-atan2(difmat[2][0], difmat[2][2])));
+ printf("Bone %s\n", curBone->name);
+ print_m4("premat", premat);
+ print_m4("postmat", postmat);
+ print_m4("difmat", difmat);
+ printf("Roll = %f\n", RAD2DEGF(-atan2(difmat[2][0], difmat[2][2])));
#endif
- curBone->roll = -atan2f(difmat[2][0], difmat[2][2]);
-
- /* and set restposition again */
- BKE_armature_where_is_bone(curBone, curBone->parent);
+
+ curBone->roll = -atan2f(difmat[2][0], difmat[2][2]);
+
+ /* and set restposition again */
+ BKE_armature_where_is_bone(curBone, curBone->parent, false);
+ break;
+ }
}
- fix_bonelist_roll(&curBone->childbase, editbonelist);
+
+ /* Recurse into children... */
+ armature_finalize_restpose(&curBone->childbase, editbonelist);
}
}
@@ -529,9 +565,9 @@ void ED_armature_from_edit(bArmature *arm)
/* remove zero sized bones, this gives unstable restposes */
for (eBone = arm->edbo->first; eBone; eBone = neBone) {
- float len = len_v3v3(eBone->head, eBone->tail);
+ float len_sq = len_squared_v3v3(eBone->head, eBone->tail);
neBone = eBone->next;
- if (len <= 0.000001f) { /* FLT_EPSILON is too large? */
+ if (len_sq <= SQUARE(0.000001f)) { /* FLT_EPSILON is too large? */
EditBone *fBone;
/* Find any bones that refer to this bone */
@@ -548,7 +584,7 @@ void ED_armature_from_edit(bArmature *arm)
/* Copy the bones from the editData into the armature */
for (eBone = arm->edbo->first; eBone; eBone = eBone->next) {
newBone = MEM_callocN(sizeof(Bone), "bone");
- eBone->temp = newBone; /* Associate the real Bones with the EditBones */
+ eBone->temp.bone = newBone; /* Associate the real Bones with the EditBones */
BLI_strncpy(newBone->name, eBone->name, sizeof(newBone->name));
copy_v3_v3(newBone->arm_head, eBone->head);
@@ -581,48 +617,29 @@ void ED_armature_from_edit(bArmature *arm)
newBone->prop = IDP_CopyProperty(eBone->prop);
}
- /* Fix parenting in a separate pass to ensure ebone->bone connections
- * are valid at this point */
+ /* Fix parenting in a separate pass to ensure ebone->bone connections are valid at this point.
+ * Do not set bone->head/tail here anymore, using EditBone data for that is not OK since our later fiddling
+ * with parent's arm_mat (for roll conversion) may have some small but visible impact on locations (T46010). */
for (eBone = arm->edbo->first; eBone; eBone = eBone->next) {
- newBone = (Bone *)eBone->temp;
+ newBone = eBone->temp.bone;
if (eBone->parent) {
- newBone->parent = (Bone *)eBone->parent->temp;
+ newBone->parent = eBone->parent->temp.bone;
BLI_addtail(&newBone->parent->childbase, newBone);
-
- {
- float M_parentRest[3][3];
- float iM_parentRest[3][3];
-
- /* Get the parent's matrix (rotation only) */
- ED_armature_ebone_to_mat3(eBone->parent, M_parentRest);
-
- /* Invert the parent matrix */
- invert_m3_m3(iM_parentRest, M_parentRest);
-
- /* Get the new head and tail */
- sub_v3_v3v3(newBone->head, eBone->head, eBone->parent->tail);
- sub_v3_v3v3(newBone->tail, eBone->tail, eBone->parent->tail);
-
- mul_m3_v3(iM_parentRest, newBone->head);
- mul_m3_v3(iM_parentRest, newBone->tail);
- }
}
/* ...otherwise add this bone to the armature's bonebase */
else {
- copy_v3_v3(newBone->head, eBone->head);
- copy_v3_v3(newBone->tail, eBone->tail);
BLI_addtail(&arm->bonebase, newBone);
}
}
- /* Make a pass through the new armature to fix rolling */
- /* also builds restposition again (like BKE_armature_where_is) */
- fix_bonelist_roll(&arm->bonebase, arm->edbo);
+ /* Finalize definition of restpose data (roll, bone_mat, arm_mat, head/tail...). */
+ armature_finalize_restpose(&arm->bonebase, arm->edbo);
/* so all users of this armature should get rebuilt */
for (obt = G.main->object.first; obt; obt = obt->id.next) {
- if (obt->data == arm)
+ if (obt->data == arm) {
BKE_pose_rebuild(obt, arm);
+ }
}
DAG_id_tag_update(&arm->id, 0);
@@ -695,24 +712,24 @@ static void ED_armature_ebone_listbase_copy(ListBase *lb_dst, ListBase *lb_src)
if (ebone_dst->prop) {
ebone_dst->prop = IDP_CopyProperty(ebone_dst->prop);
}
- ebone_src->temp = ebone_dst;
+ ebone_src->temp.ebone = ebone_dst;
BLI_addtail(lb_dst, ebone_dst);
}
/* set pointers */
for (ebone_dst = lb_dst->first; ebone_dst; ebone_dst = ebone_dst->next) {
if (ebone_dst->parent) {
- ebone_dst->parent = ebone_dst->parent->temp;
+ ebone_dst->parent = ebone_dst->parent->temp.ebone;
}
}
}
-static void ED_armature_ebone_listbase_temp_clear(ListBase *lb)
+void ED_armature_ebone_listbase_temp_clear(ListBase *lb)
{
EditBone *ebone;
/* be sure they don't hang ever */
for (ebone = lb->first; ebone; ebone = ebone->next) {
- ebone->temp = NULL;
+ ebone->temp.p = NULL;
}
}
@@ -733,7 +750,7 @@ static void undoBones_to_editBones(void *uarmv, void *armv, void *UNUSED(data))
/* active bone */
if (uarm->act_edbone) {
ebone = uarm->act_edbone;
- arm->act_edbone = ebone->temp;
+ arm->act_edbone = ebone->temp.ebone;
}
else {
arm->act_edbone = NULL;
@@ -755,7 +772,7 @@ static void *editBones_to_undoBones(void *armv, void *UNUSED(obdata))
/* active bone */
if (arm->act_edbone) {
ebone = arm->act_edbone;
- uarm->act_edbone = ebone->temp;
+ uarm->act_edbone = ebone->temp.ebone;
}
ED_armature_ebone_listbase_temp_clear(&uarm->lb);
diff --git a/source/blender/editors/armature/editarmature_retarget.c b/source/blender/editors/armature/editarmature_retarget.c
index 647b640ee61..2235f9f92cc 100644
--- a/source/blender/editors/armature/editarmature_retarget.c
+++ b/source/blender/editors/armature/editarmature_retarget.c
@@ -707,7 +707,7 @@ static void RIG_reconnectControlBones(RigGraph *rg)
/* DO SOME MAGIC HERE */
for (pchan = rg->ob->pose->chanbase.first; pchan; pchan = pchan->next) {
for (con = pchan->constraints.first; con; con = con->next) {
- bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
+ const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
ListBase targets = {NULL, NULL};
bConstraintTarget *ct;
@@ -718,7 +718,7 @@ static void RIG_reconnectControlBones(RigGraph *rg)
cti->get_constraint_targets(con, &targets);
for (target_index = 0, ct = targets.first; ct; target_index++, ct = ct->next) {
- if ((ct->tar == rg->ob) && strcmp(ct->subtarget, ctrl->bone->name) == 0) {
+ if ((ct->tar == rg->ob) && STREQ(ct->subtarget, ctrl->bone->name)) {
/* SET bone link to bone corresponding to pchan */
EditBone *link = BLI_ghash_lookup(rg->bones_map, pchan->name);
@@ -832,7 +832,7 @@ static void RIG_reconnectControlBones(RigGraph *rg)
/* DO SOME MAGIC HERE */
for (pchan = rg->ob->pose->chanbase.first; pchan; pchan = pchan->next) {
for (con = pchan->constraints.first; con; con = con->next) {
- bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
+ const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
ListBase targets = {NULL, NULL};
bConstraintTarget *ct;
@@ -841,7 +841,7 @@ static void RIG_reconnectControlBones(RigGraph *rg)
cti->get_constraint_targets(con, &targets);
for (ct = targets.first; ct; ct = ct->next) {
- if ((ct->tar == rg->ob) && strcmp(ct->subtarget, ctrl->bone->name) == 0) {
+ if ((ct->tar == rg->ob) && STREQ(ct->subtarget, ctrl->bone->name)) {
/* SET bone link to ctrl corresponding to pchan */
RigControl *link = BLI_ghash_lookup(rg->controls_map, pchan->name);
@@ -1160,7 +1160,7 @@ static void RIG_arcFromBoneChain(RigGraph *rg, ListBase *list, EditBone *root_bo
last_bone = bone;
- if (strcmp(bone->name, "head") == 0) {
+ if (STREQ(bone->name, "head")) {
contain_head = 1;
}
}
@@ -1205,7 +1205,7 @@ static void RIG_arcFromBoneChain(RigGraph *rg, ListBase *list, EditBone *root_bo
static void RIG_findHead(RigGraph *rg)
{
if (rg->head == NULL) {
- if (BLI_countlist(&rg->arcs) == 1) {
+ if (BLI_listbase_is_single(&rg->arcs)) {
RigArc *arc = rg->arcs.first;
rg->head = (RigNode *)arc->head;
@@ -1958,7 +1958,7 @@ static void retargetArctoArcAggresive(bContext *C, RigGraph *rigg, RigArc *iarc,
#endif
float *vec0, *vec1;
int *best_positions;
- int nb_edges = BLI_countlist(&iarc->edges);
+ int nb_edges = BLI_listbase_count(&iarc->edges);
int nb_joints = nb_edges - 1;
RetargetMethod method = METHOD_MEMOIZE;
int i;
@@ -2152,7 +2152,7 @@ void exec_retargetArctoArc(TaskPool *UNUSED(pool), void *taskdata, int UNUSED(th
RigNode *inode_start = p->inode_start;
ReebArc *earc = iarc->link_mesh;
- if (BLI_countlist(&iarc->edges) == 1) {
+ if (BLI_listbase_is_single(&iarc->edges)) {
RigEdge *edge = iarc->edges.first;
if (testFlipArc(iarc, inode_start)) {
@@ -2454,7 +2454,7 @@ const char *RIG_nameBone(RigGraph *rg, int arc_index, int bone_index)
return "None";
}
- if (bone_index == BLI_countlist(&arc->edges)) {
+ if (bone_index == BLI_listbase_count(&arc->edges)) {
return "Last joint";
}
@@ -2476,10 +2476,10 @@ int RIG_nbJoints(RigGraph *rg)
RigArc *arc;
int total = 0;
- total += BLI_countlist(&rg->nodes);
+ total += BLI_listbase_count(&rg->nodes);
for (arc = rg->arcs.first; arc; arc = arc->next) {
- total += BLI_countlist(&arc->edges) - 1; /* -1 because end nodes are already counted */
+ total += BLI_listbase_count(&arc->edges) - 1; /* -1 because end nodes are already counted */
}
return total;
diff --git a/source/blender/editors/armature/editarmature_sketch.c b/source/blender/editors/armature/editarmature_sketch.c
index d75a23a6322..e4c3f73dd94 100644
--- a/source/blender/editors/armature/editarmature_sketch.c
+++ b/source/blender/editors/armature/editarmature_sketch.c
@@ -31,8 +31,6 @@
#include "BLI_blenlib.h"
#include "BLI_math.h"
-#include "BLF_translation.h"
-
#include "BKE_context.h"
#include "BKE_sketch.h"
@@ -335,11 +333,11 @@ static void sk_autoname(bContext *C, ReebArc *arc)
if (side[0] == '\0') {
valid = 1;
}
- else if (strcmp(side, "R") == 0 || strcmp(side, "L") == 0) {
+ else if (STREQ(side, "R") || STREQ(side, "L")) {
valid = 1;
caps = 1;
}
- else if (strcmp(side, "r") == 0 || strcmp(side, "l") == 0) {
+ else if (STREQ(side, "r") || STREQ(side, "l")) {
valid = 1;
caps = 0;
}
@@ -403,9 +401,7 @@ static void sk_retargetStroke(bContext *C, SK_Stroke *stk)
RigGraph *rg;
invert_m4_m4(imat, obedit->obmat);
-
- copy_m3_m4(tmat, obedit->obmat);
- transpose_m3(tmat);
+ transpose_m3_m4(tmat, obedit->obmat);
arc = sk_strokeToArc(stk, imat, tmat);
@@ -440,7 +436,7 @@ static float sk_clampPointSize(SK_Point *pt, float size)
static void sk_drawPoint(GLUquadric *quad, SK_Point *pt, float size)
{
- glTranslatef(pt->p[0], pt->p[1], pt->p[2]);
+ glTranslate3fv(pt->p);
gluSphere(quad, sk_clampPointSize(pt, size), 8, 8);
}
@@ -459,7 +455,7 @@ static void sk_drawEdge(GLUquadric *quad, SK_Point *pt0, SK_Point *pt1, float si
angle = angle_normalized_v3v3(vec2, vec1);
- glRotatef(angle * (float)(180.0 / M_PI) + 180.0f, axis[0], axis[1], axis[2]);
+ glRotate3fv(angle * (float)(180.0 / M_PI) + 180.0f, axis);
gluCylinder(quad, sk_clampPointSize(pt1, size), sk_clampPointSize(pt0, size), length, 8, 8);
}
@@ -479,7 +475,7 @@ static void sk_drawNormal(GLUquadric *quad, SK_Point *pt, float size, float heig
angle = angle_normalized_v3v3(vec2, pt->no);
- glRotatef(angle * (float)(180.0 / M_PI), axis[0], axis[1], axis[2]);
+ glRotate3fv(angle * (float)(180.0 / M_PI), axis);
glColor3f(0, 1, 1);
gluCylinder(quad, sk_clampPointSize(pt, size), 0, sk_clampPointSize(pt, height), 10, 2);
@@ -1358,9 +1354,7 @@ static void sk_convertStroke(bContext *C, SK_Stroke *stk)
head = NULL;
invert_m4_m4(invmat, obedit->obmat);
-
- copy_m3_m4(tmat, obedit->obmat);
- transpose_m3(tmat);
+ transpose_m3_m4(tmat, obedit->obmat);
for (i = 0; i < stk->nb_points; i++) {
SK_Point *pt = stk->points + i;
@@ -1579,7 +1573,7 @@ static int sk_getIntersections(bContext *C, ListBase *list, SK_Sketch *sketch, S
added = MAX2(s_added, added);
}
- BLI_sortlist(list, cmpIntersections);
+ BLI_listbase_sort(list, cmpIntersections);
return added;
}
@@ -1698,7 +1692,7 @@ int sk_detectCommandGesture(bContext *UNUSED(C), SK_Gesture *gest, SK_Sketch *UN
if (gest->nb_segments > 2 && gest->nb_intersections == 2 && gest->nb_self_intersections == 1) {
SK_Intersection *isect, *self_isect;
- /* get the the last intersection of the first pair */
+ /* get the last intersection of the first pair */
for (isect = gest->intersections.first; isect; isect = isect->next) {
if (isect->stroke == isect->next->stroke) {
isect = isect->next;
@@ -1957,7 +1951,7 @@ static void sk_applyGesture(bContext *C, SK_Sketch *sketch)
/********************************************/
-static int sk_selectStroke(bContext *C, SK_Sketch *sketch, const int mval[2], int extend)
+static bool sk_selectStroke(bContext *C, SK_Sketch *sketch, const int mval[2], const bool extend)
{
ViewContext vc;
rcti rect;
@@ -2118,7 +2112,7 @@ static void sk_drawSketch(Scene *scene, View3D *UNUSED(v3d), SK_Sketch *sketch,
glColor3fv(colors[index]);
glPushMatrix();
- glTranslatef(p->p[0], p->p[1], p->p[2]);
+ glTranslate3fv(p->p);
gluSphere(quad, 0.02, 8, 8);
glPopMatrix();
}
@@ -2245,15 +2239,19 @@ static int sketch_delete(bContext *C, wmOperator *UNUSED(op), const wmEvent *UNU
return OPERATOR_FINISHED;
}
-void BIF_sk_selectStroke(bContext *C, const int mval[2], short extend)
+bool BIF_sk_selectStroke(bContext *C, const int mval[2], const bool extend)
{
ToolSettings *ts = CTX_data_tool_settings(C);
SK_Sketch *sketch = contextSketch(C, 0);
if (sketch != NULL && ts->bone_sketching & BONE_SKETCHING) {
- if (sk_selectStroke(C, sketch, mval, extend))
+ if (sk_selectStroke(C, sketch, mval, extend)) {
ED_area_tag_redraw(CTX_wm_area(C));
+ return true;
+ }
}
+
+ return false;
}
void BIF_convertSketch(bContext *C)
diff --git a/source/blender/editors/armature/meshlaplacian.c b/source/blender/editors/armature/meshlaplacian.c
index 49650fcadbf..b8dc4e1e7ab 100644
--- a/source/blender/editors/armature/meshlaplacian.c
+++ b/source/blender/editors/armature/meshlaplacian.c
@@ -35,8 +35,9 @@
#include "BLI_edgehash.h"
#include "BLI_memarena.h"
#include "BLI_string.h"
+#include "BLI_alloca.h"
-#include "BLF_translation.h"
+#include "BLT_translation.h"
#include "BKE_DerivedMesh.h"
#include "BKE_modifier.h"
@@ -84,9 +85,10 @@ struct LaplacianSystem {
EdgeHash *edgehash; /* edge hash for construction */
struct HeatWeighting {
- MFace *mface;
+ const MLoopTri *mlooptri;
+ const MLoop *mloop; /* needed to find vertices by index */
int totvert;
- int totface;
+ int tottri;
float (*verts)[3]; /* vertex coordinates */
float (*vnors)[3]; /* vertex normals */
@@ -100,7 +102,7 @@ struct LaplacianSystem {
float *mindist; /* minimum distance to a bone for all vertices */
BVHTree *bvhtree; /* ray tracing acceleration structure */
- MFace **vface; /* a face that the vertex belongs to */
+ const MLoopTri **vltree; /* a looptri that the vertex belongs to */
} heat;
#ifdef RIGID_DEFORM
@@ -127,12 +129,12 @@ struct LaplacianSystem {
static void laplacian_increase_edge_count(EdgeHash *edgehash, int v1, int v2)
{
- void **p = BLI_edgehash_lookup_p(edgehash, v1, v2);
+ void **p;
- if (p)
+ if (BLI_edgehash_ensure_p(edgehash, v1, v2, &p))
*p = (void *)((intptr_t)*p + (intptr_t)1);
else
- BLI_edgehash_insert(edgehash, v1, v2, (void *)(intptr_t)1);
+ *p = (void *)((intptr_t)1);
}
static int laplacian_edge_count(EdgeHash *edgehash, int v1, int v2)
@@ -377,30 +379,33 @@ typedef struct BVHCallbackUserData {
LaplacianSystem *sys;
} BVHCallbackUserData;
-static void bvh_callback(void *userdata, int index, const BVHTreeRay *UNUSED(ray), BVHTreeRayHit *hit)
+static void bvh_callback(void *userdata, int index, const BVHTreeRay *ray, BVHTreeRayHit *hit)
{
BVHCallbackUserData *data = (struct BVHCallbackUserData *)userdata;
- MFace *mf = data->sys->heat.mface + index;
+ const MLoopTri *lt = &data->sys->heat.mlooptri[index];
+ const MLoop *mloop = data->sys->heat.mloop;
float (*verts)[3] = data->sys->heat.verts;
- float lambda, uv[2], n[3], dir[3];
+ const float *vtri_co[3];
+ float dist_test;
- mul_v3_v3fl(dir, data->vec, hit->dist);
+ vtri_co[0] = verts[mloop[lt->tri[0]].v];
+ vtri_co[1] = verts[mloop[lt->tri[1]].v];
+ vtri_co[2] = verts[mloop[lt->tri[2]].v];
- if (isect_ray_tri_v3(data->start, dir, verts[mf->v1], verts[mf->v2], verts[mf->v3], &lambda, uv)) {
- normal_tri_v3(n, verts[mf->v1], verts[mf->v2], verts[mf->v3]);
- if (lambda < 1.0f && dot_v3v3(n, data->vec) < -1e-5f) {
- hit->index = index;
- hit->dist *= lambda;
- }
- }
-
- mul_v3_v3fl(dir, data->vec, hit->dist);
-
- if (isect_ray_tri_v3(data->start, dir, verts[mf->v1], verts[mf->v3], verts[mf->v4], &lambda, uv)) {
- normal_tri_v3(n, verts[mf->v1], verts[mf->v3], verts[mf->v4]);
- if (lambda < 1.0f && dot_v3v3(n, data->vec) < -1e-5f) {
- hit->index = index;
- hit->dist *= lambda;
+#ifdef USE_KDOPBVH_WATERTIGHT
+ if (isect_ray_tri_watertight_v3(data->start, ray->isect_precalc, UNPACK3(vtri_co), &dist_test, NULL))
+#else
+ UNUSED_VARS(ray);
+ if (isect_ray_tri_v3(data->start, data->vec, UNPACK3(vtri_co), &dist_test, NULL))
+#endif
+ {
+ if (dist_test < hit->dist) {
+ float n[3];
+ normal_tri_v3(n, UNPACK3(vtri_co));
+ if (dot_v3v3(n, data->vec) < -1e-5f) {
+ hit->index = index;
+ hit->dist = dist_test;
+ }
}
}
}
@@ -408,34 +413,36 @@ static void bvh_callback(void *userdata, int index, const BVHTreeRay *UNUSED(ray
/* Raytracing for vertex to bone/vertex visibility */
static void heat_ray_tree_create(LaplacianSystem *sys)
{
- MFace *mface = sys->heat.mface;
+ const MLoopTri *looptri = sys->heat.mlooptri;
+ const MLoop *mloop = sys->heat.mloop;
float (*verts)[3] = sys->heat.verts;
- int totface = sys->heat.totface;
+ int tottri = sys->heat.tottri;
int totvert = sys->heat.totvert;
int a;
- sys->heat.bvhtree = BLI_bvhtree_new(totface, 0.0f, 4, 6);
- sys->heat.vface = MEM_callocN(sizeof(MFace *) * totvert, "HeatVFaces");
+ sys->heat.bvhtree = BLI_bvhtree_new(tottri, 0.0f, 4, 6);
+ sys->heat.vltree = MEM_callocN(sizeof(MLoopTri *) * totvert, "HeatVFaces");
- for (a = 0; a < totface; a++) {
- MFace *mf = mface + a;
+ for (a = 0; a < tottri; a++) {
+ const MLoopTri *lt = &looptri[a];
float bb[6];
+ int vtri[3];
+
+ vtri[0] = mloop[lt->tri[0]].v;
+ vtri[1] = mloop[lt->tri[1]].v;
+ vtri[2] = mloop[lt->tri[2]].v;
INIT_MINMAX(bb, bb + 3);
- minmax_v3v3_v3(bb, bb + 3, verts[mf->v1]);
- minmax_v3v3_v3(bb, bb + 3, verts[mf->v2]);
- minmax_v3v3_v3(bb, bb + 3, verts[mf->v3]);
- if (mf->v4) {
- minmax_v3v3_v3(bb, bb + 3, verts[mf->v4]);
- }
+ minmax_v3v3_v3(bb, bb + 3, verts[vtri[0]]);
+ minmax_v3v3_v3(bb, bb + 3, verts[vtri[1]]);
+ minmax_v3v3_v3(bb, bb + 3, verts[vtri[2]]);
BLI_bvhtree_insert(sys->heat.bvhtree, a, bb, 2);
//Setup inverse pointers to use on isect.orig
- sys->heat.vface[mf->v1] = mf;
- sys->heat.vface[mf->v2] = mf;
- sys->heat.vface[mf->v3] = mf;
- if (mf->v4) sys->heat.vface[mf->v4] = mf;
+ sys->heat.vltree[vtri[0]] = lt;
+ sys->heat.vltree[vtri[1]] = lt;
+ sys->heat.vltree[vtri[2]] = lt;
}
BLI_bvhtree_balance(sys->heat.bvhtree);
@@ -445,12 +452,12 @@ static int heat_ray_source_visible(LaplacianSystem *sys, int vertex, int source)
{
BVHTreeRayHit hit;
BVHCallbackUserData data;
- MFace *mface;
+ const MLoopTri *lt;
float end[3];
int visible;
- mface = sys->heat.vface[vertex];
- if (!mface)
+ lt = sys->heat.vltree[vertex];
+ if (lt == NULL)
return 1;
data.sys = sys;
@@ -568,8 +575,9 @@ static void heat_calc_vnormals(LaplacianSystem *sys)
static void heat_laplacian_create(LaplacianSystem *sys)
{
- MFace *mface = sys->heat.mface, *mf;
- int totface = sys->heat.totface;
+ const MLoopTri *mlooptri = sys->heat.mlooptri, *lt;
+ const MLoop *mloop = sys->heat.mloop;
+ int tottri = sys->heat.tottri;
int totvert = sys->heat.totvert;
int a;
@@ -582,10 +590,12 @@ static void heat_laplacian_create(LaplacianSystem *sys)
for (a = 0; a < totvert; a++)
laplacian_add_vertex(sys, sys->heat.verts[a], 0);
- for (a = 0, mf = mface; a < totface; a++, mf++) {
- laplacian_add_triangle(sys, mf->v1, mf->v2, mf->v3);
- if (mf->v4)
- laplacian_add_triangle(sys, mf->v1, mf->v3, mf->v4);
+ for (a = 0, lt = mlooptri; a < tottri; a++, lt++) {
+ int vtri[3];
+ vtri[0] = mloop[lt->tri[0]].v;
+ vtri[1] = mloop[lt->tri[1]].v;
+ vtri[2] = mloop[lt->tri[2]].v;
+ laplacian_add_triangle(sys, UNPACK3(vtri));
}
/* for distance computation in set_H */
@@ -598,7 +608,8 @@ static void heat_laplacian_create(LaplacianSystem *sys)
static void heat_system_free(LaplacianSystem *sys)
{
BLI_bvhtree_free(sys->heat.bvhtree);
- MEM_freeN(sys->heat.vface);
+ MEM_freeN(sys->heat.vltree);
+ MEM_freeN((void *)sys->heat.mlooptri);
MEM_freeN(sys->heat.mindist);
MEM_freeN(sys->heat.H);
@@ -626,9 +637,9 @@ void heat_bone_weighting(Object *ob, Mesh *me, float (*verts)[3], int numsource,
float (*root)[3], float (*tip)[3], int *selected, const char **err_str)
{
LaplacianSystem *sys;
+ MLoopTri *mlooptri;
MPoly *mp;
MLoop *ml;
- MFace *mf;
float solution, weight;
int *vertsflipped = NULL, *mask = NULL;
int a, tottri, j, bbone, firstsegment, lastsegment;
@@ -641,15 +652,7 @@ void heat_bone_weighting(Object *ob, Mesh *me, float (*verts)[3], int numsource,
*err_str = NULL;
/* bone heat needs triangulated faces */
- BKE_mesh_tessface_ensure(me);
-
- for (tottri = 0, a = 0, mf = me->mface; a < me->totface; mf++, a++) {
- tottri++;
- if (mf->v4) tottri++;
- }
-
- if (tottri == 0)
- return;
+ tottri = poly_to_tri_count(me->totpoly, me->totloop);
/* count triangles and create mask */
if (ob->mode & OB_MODE_WEIGHT_PAINT &&
@@ -679,8 +682,17 @@ void heat_bone_weighting(Object *ob, Mesh *me, float (*verts)[3], int numsource,
/* create laplacian */
sys = laplacian_system_construct_begin(me->totvert, tottri, 1);
- sys->heat.mface = me->mface;
- sys->heat.totface = me->totface;
+ sys->heat.tottri = poly_to_tri_count(me->totpoly, me->totloop);
+ mlooptri = MEM_mallocN(sizeof(*sys->heat.mlooptri) * sys->heat.tottri, __func__);
+
+ BKE_mesh_recalc_looptri(
+ me->mloop, me->mpoly,
+ me->mvert,
+ me->totloop, me->totpoly,
+ mlooptri);
+
+ sys->heat.mlooptri = mlooptri;
+ sys->heat.mloop = me->mloop;
sys->heat.totvert = me->totvert;
sys->heat.verts = verts;
sys->heat.root = root;
@@ -1041,18 +1053,26 @@ void rigid_deform_end(int cancel)
#define MESHDEFORM_TAG_INTERIOR 2
#define MESHDEFORM_TAG_EXTERIOR 3
+/** minimum length for #MDefBoundIsect.len */
#define MESHDEFORM_LEN_THRESHOLD 1e-6f
#define MESHDEFORM_MIN_INFLUENCE 0.0005f
-static int MESHDEFORM_OFFSET[7][3] = {
+static const int MESHDEFORM_OFFSET[7][3] = {
{0, 0, 0}, {1, 0, 0}, {-1, 0, 0}, {0, 1, 0}, {0, -1, 0}, {0, 0, 1}, {0, 0, -1}
};
typedef struct MDefBoundIsect {
- float co[3], uvw[4];
- int nvert, v[4], facing;
+ /* intersection on the cage 'cagecos' */
+ float co[3];
+ /* non-facing intersections are considered interior */
+ bool facing;
+ /* ray-cast index aligned with MPoly (ray-hit-triangle isn't needed) */
+ int poly_index;
+ /* distance from 'co' to the ray-cast start (clamped to avoid zero division) */
float len;
+ /* weights aligned with the MPoly's loop indices */
+ float poly_weights[0];
} MDefBoundIsect;
typedef struct MDefBindInfluence {
@@ -1091,15 +1111,23 @@ typedef struct MeshDeformBind {
BVHTree *bvhtree;
BVHTreeFromMesh bvhdata;
+
+ /* avoid DM function calls during intersections */
+ struct {
+ const MPoly *mpoly;
+ const MLoop *mloop;
+ const MLoopTri *looptri;
+ const float (*poly_nors)[3];
+ } cagedm_cache;
} MeshDeformBind;
typedef struct MeshDeformIsect {
float start[3];
float vec[3];
+ float vec_length;
float lambda;
- void *face;
- int isect;
+ bool isect;
float u, v;
} MeshDeformIsect;
@@ -1169,34 +1197,41 @@ static int meshdeform_tri_intersect(const float orig[3], const float end[3], con
return 1;
}
+struct MeshRayCallbackData {
+ MeshDeformBind *mdb;
+ MeshDeformIsect *isec;
+};
+
static void harmonic_ray_callback(void *userdata, int index, const BVHTreeRay *ray, BVHTreeRayHit *hit)
{
- void **data = userdata;
- MeshDeformBind *mdb = data[1];
- MFace *mface = data[0], *mf;
- MeshDeformIsect *isec = data[2];
- float no[3], co[3], end[3], uvw[3], dist, face[4][3];
+ struct MeshRayCallbackData *data = userdata;
+ MeshDeformBind *mdb = data->mdb;
+ const MLoop *mloop = mdb->cagedm_cache.mloop;
+ const MLoopTri *looptri = mdb->cagedm_cache.looptri, *lt;
+ const float (*poly_nors)[3] = mdb->cagedm_cache.poly_nors;
+ MeshDeformIsect *isec = data->isec;
+ float no[3], co[3], end[3], uvw[3], dist;
+ float *face[3];
- mf = mface + index;
+ lt = &looptri[index];
- copy_v3_v3(face[0], mdb->cagecos[mf->v1]);
- copy_v3_v3(face[1], mdb->cagecos[mf->v2]);
- copy_v3_v3(face[2], mdb->cagecos[mf->v3]);
- if (mf->v4)
- copy_v3_v3(face[3], mdb->cagecos[mf->v4]);
+ face[0] = mdb->cagecos[mloop[lt->tri[0]].v];
+ face[1] = mdb->cagecos[mloop[lt->tri[1]].v];
+ face[2] = mdb->cagecos[mloop[lt->tri[2]].v];
add_v3_v3v3(end, isec->start, isec->vec);
- if (!meshdeform_tri_intersect(ray->origin, end, face[0], face[1], face[2], co, uvw))
- if (!mf->v4 || !meshdeform_tri_intersect(ray->origin, end, face[0], face[2], face[3], co, uvw))
- return;
-
- if (!mf->v4)
- normal_tri_v3(no, face[0], face[1], face[2]);
- else
- normal_quad_v3(no, face[0], face[1], face[2], face[3]);
-
- dist = len_v3v3(ray->origin, co) / len_v3(isec->vec);
+ if (!meshdeform_tri_intersect(ray->origin, end, UNPACK3(face), co, uvw))
+ return;
+
+ if (poly_nors) {
+ copy_v3_v3(no, poly_nors[lt->poly]);
+ }
+ else {
+ normal_tri_v3(no, UNPACK3(face));
+ }
+
+ dist = len_v3v3(ray->origin, co) / isec->vec_length;
if (dist < hit->dist) {
hit->index = index;
hit->dist = dist;
@@ -1204,19 +1239,18 @@ static void harmonic_ray_callback(void *userdata, int index, const BVHTreeRay *r
isec->isect = (dot_v3v3(no, ray->direction) <= 0.0f);
isec->lambda = dist;
- isec->face = mf;
}
}
static MDefBoundIsect *meshdeform_ray_tree_intersect(MeshDeformBind *mdb, const float co1[3], const float co2[3])
{
- MDefBoundIsect *isect;
BVHTreeRayHit hit;
MeshDeformIsect isect_mdef;
- float (*cagecos)[3];
- void *data[3] = {mdb->cagedm->getTessFaceArray(mdb->cagedm), mdb, &isect_mdef};
- MFace *mface1 = data[0], *mface;
- float vert[4][3], len, end[3];
+ struct MeshRayCallbackData data = {
+ mdb,
+ &isect_mdef,
+ };
+ float end[3], vec_normal[3];
// static float epsilon[3] = {1e-4, 1e-4, 1e-4};
/* happens binding when a cage has no faces */
@@ -1235,42 +1269,41 @@ static MDefBoundIsect *meshdeform_ray_tree_intersect(MeshDeformBind *mdb, const
copy_v3_v3(end, co2);
#endif
sub_v3_v3v3(isect_mdef.vec, end, isect_mdef.start);
+ isect_mdef.vec_length = normalize_v3_v3(vec_normal, isect_mdef.vec);
hit.index = -1;
hit.dist = FLT_MAX;
- if (BLI_bvhtree_ray_cast(mdb->bvhtree, isect_mdef.start, isect_mdef.vec,
- 0.0, &hit, harmonic_ray_callback, data) != -1)
+ if (BLI_bvhtree_ray_cast(mdb->bvhtree, isect_mdef.start, vec_normal,
+ 0.0, &hit, harmonic_ray_callback, &data) != -1)
{
- len = isect_mdef.lambda;
- isect_mdef.face = mface = mface1 + hit.index;
+ const MLoop *mloop = mdb->cagedm_cache.mloop;
+ const MLoopTri *lt = &mdb->cagedm_cache.looptri[hit.index];
+ const MPoly *mp = &mdb->cagedm_cache.mpoly[lt->poly];
+ const float (*cagecos)[3] = mdb->cagecos;
+ const float len = isect_mdef.lambda;
+ MDefBoundIsect *isect;
- /* create MDefBoundIsect */
- isect = BLI_memarena_alloc(mdb->memarena, sizeof(*isect));
+ float (*mp_cagecos)[3] = BLI_array_alloca(mp_cagecos, mp->totloop);
+ int i;
+
+ /* create MDefBoundIsect, and extra for 'poly_weights[]' */
+ isect = BLI_memarena_alloc(mdb->memarena, sizeof(*isect) + (sizeof(float) * mp->totloop));
/* compute intersection coordinate */
- isect->co[0] = co1[0] + isect_mdef.vec[0] * len;
- isect->co[1] = co1[1] + isect_mdef.vec[1] * len;
- isect->co[2] = co1[2] + isect_mdef.vec[2] * len;
+ madd_v3_v3v3fl(isect->co, co1, isect_mdef.vec, len);
- isect->len = len_v3v3(co1, isect->co);
- if (isect->len < MESHDEFORM_LEN_THRESHOLD)
- isect->len = MESHDEFORM_LEN_THRESHOLD;
+ isect->facing = isect_mdef.isect;
- isect->v[0] = mface->v1;
- isect->v[1] = mface->v2;
- isect->v[2] = mface->v3;
- isect->v[3] = mface->v4;
- isect->nvert = (mface->v4) ? 4 : 3;
+ isect->poly_index = lt->poly;
- isect->facing = isect_mdef.isect;
+ isect->len = max_ff(len_v3v3(co1, isect->co), MESHDEFORM_LEN_THRESHOLD);
/* compute mean value coordinates for interpolation */
- cagecos = mdb->cagecos;
- copy_v3_v3(vert[0], cagecos[mface->v1]);
- copy_v3_v3(vert[1], cagecos[mface->v2]);
- copy_v3_v3(vert[2], cagecos[mface->v3]);
- if (mface->v4) copy_v3_v3(vert[3], cagecos[mface->v4]);
- interp_weights_poly_v3(isect->uvw, vert, isect->nvert, isect->co);
+ for (i = 0; i < mp->totloop; i++) {
+ copy_v3_v3(mp_cagecos[i], cagecos[mloop[mp->loopstart + i].v]);
+ }
+
+ interp_weights_poly_v3(isect->poly_weights, mp_cagecos, mp->totloop, isect->co);
return isect;
}
@@ -1303,7 +1336,7 @@ static int meshdeform_inside_cage(MeshDeformBind *mdb, float *co)
/* solving */
-static int meshdeform_index(MeshDeformBind *mdb, int x, int y, int z, int n)
+BLI_INLINE int meshdeform_index(MeshDeformBind *mdb, int x, int y, int z, int n)
{
int size = mdb->size;
@@ -1321,7 +1354,7 @@ static int meshdeform_index(MeshDeformBind *mdb, int x, int y, int z, int n)
return x + y * size + z * size * size;
}
-static void meshdeform_cell_center(MeshDeformBind *mdb, int x, int y, int z, int n, float *center)
+BLI_INLINE void meshdeform_cell_center(MeshDeformBind *mdb, int x, int y, int z, int n, float *center)
{
x += MESHDEFORM_OFFSET[n][0];
y += MESHDEFORM_OFFSET[n][1];
@@ -1418,14 +1451,18 @@ static void meshdeform_bind_floodfill(MeshDeformBind *mdb)
MEM_freeN(stack);
}
-static float meshdeform_boundary_phi(MeshDeformBind *UNUSED(mdb), MDefBoundIsect *isect, int cagevert)
+static float meshdeform_boundary_phi(const MeshDeformBind *mdb, const MDefBoundIsect *isect, int cagevert)
{
- int a;
+ const MLoop *mloop = mdb->cagedm_cache.mloop;
+ const MPoly *mp = &mdb->cagedm_cache.mpoly[isect->poly_index];
+ int i;
+
+ for (i = 0; i < mp->totloop; i++) {
+ if (mloop[mp->loopstart + i].v == cagevert) {
+ return isect->poly_weights[i];
+ }
+ }
- for (a = 0; a < isect->nvert; a++)
- if (isect->v[a] == cagevert)
- return isect->uvw[a];
-
return 0.0f;
}
@@ -1719,7 +1756,7 @@ static void meshdeform_matrix_solve(MeshDeformModifierData *mmd, MeshDeformBind
/* sanity check */
for (b = 0; b < mdb->size3; b++)
if (mdb->tag[b] != MESHDEFORM_TAG_EXTERIOR)
- if (fabs(mdb->totalphi[b] - 1.0f) > 1e-4)
+ if (fabsf(mdb->totalphi[b] - 1.0f) > 1e-4f)
printf("totalphi deficiency [%s|%d] %d: %.10f\n",
(mdb->tag[b] == MESHDEFORM_TAG_INTERIOR) ? "interior" : "boundary", mdb->semibound[b], mdb->varidx[b], mdb->totalphi[b]);
#endif
@@ -1752,7 +1789,7 @@ static void harmonic_coordinates_bind(Scene *UNUSED(scene), MeshDeformModifierDa
mdb->totalphi = MEM_callocN(sizeof(float) * mdb->size3, "MeshDeformBindTotalPhi");
mdb->boundisect = MEM_callocN(sizeof(*mdb->boundisect) * mdb->size3, "MDefBoundIsect");
mdb->semibound = MEM_callocN(sizeof(int) * mdb->size3, "MDefSemiBound");
- mdb->bvhtree = bvhtree_from_mesh_faces(&mdb->bvhdata, mdb->cagedm, FLT_EPSILON * 100, 4, 6);
+ mdb->bvhtree = bvhtree_from_mesh_looptri(&mdb->bvhdata, mdb->cagedm, FLT_EPSILON * 100, 4, 6);
mdb->inside = MEM_callocN(sizeof(int) * mdb->totvert, "MDefInside");
if (mmd->flag & MOD_MDEF_DYNAMIC_BIND)
@@ -1763,6 +1800,15 @@ static void harmonic_coordinates_bind(Scene *UNUSED(scene), MeshDeformModifierDa
mdb->memarena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, "harmonic coords arena");
BLI_memarena_use_calloc(mdb->memarena);
+ /* initialize data from 'cagedm' for reuse */
+ {
+ DerivedMesh *dm = mdb->cagedm;
+ mdb->cagedm_cache.mpoly = dm->getPolyArray(dm);
+ mdb->cagedm_cache.mloop = dm->getLoopArray(dm);
+ mdb->cagedm_cache.looptri = dm->getLoopTriArray(dm);
+ mdb->cagedm_cache.poly_nors = dm->getPolyDataArray(dm, CD_NORMAL); /* can be NULL */
+ }
+
/* make bounding box equal size in all directions, add padding, and compute
* width of the cells */
maxwidth = -1.0f;
diff --git a/source/blender/editors/armature/meshlaplacian.h b/source/blender/editors/armature/meshlaplacian.h
index 820aedc5467..1412136c1a8 100644
--- a/source/blender/editors/armature/meshlaplacian.h
+++ b/source/blender/editors/armature/meshlaplacian.h
@@ -29,11 +29,9 @@
//#define RIGID_DEFORM
-struct Scene;
struct Object;
struct Mesh;
struct bDeformGroup;
-struct MeshDeformModifierData;
#ifdef RIGID_DEFORM
struct EditMesh;
diff --git a/source/blender/editors/armature/pose_edit.c b/source/blender/editors/armature/pose_edit.c
index da68108285f..e87c324d7ec 100644
--- a/source/blender/editors/armature/pose_edit.c
+++ b/source/blender/editors/armature/pose_edit.c
@@ -381,14 +381,14 @@ static void pose_copy_menu(Scene *scene)
* but for constraints (just add local constraints)
*/
if (pose_has_protected_selected(ob, 0)) {
- i = BLI_countlist(&(pchanact->constraints)); /* if there are 24 or less, allow for the user to select constraints */
+ i = BLI_listbase_count(&(pchanact->constraints)); /* if there are 24 or less, allow for the user to select constraints */
if (i < 25)
nr = pupmenu("Copy Pose Attributes %t|Local Location %x1|Local Rotation %x2|Local Size %x3|%l|Visual Location %x9|Visual Rotation %x10|Visual Size %x11|%l|Constraints (All) %x4|Constraints... %x5");
else
nr = pupmenu("Copy Pose Attributes %t|Local Location %x1|Local Rotation %x2|Local Size %x3|%l|Visual Location %x9|Visual Rotation %x10|Visual Size %x11|%l|Constraints (All) %x4");
}
else {
- i = BLI_countlist(&(pchanact->constraints)); /* if there are 24 or less, allow for the user to select constraints */
+ i = BLI_listbase_count(&(pchanact->constraints)); /* if there are 24 or less, allow for the user to select constraints */
if (i < 25)
nr = pupmenu("Copy Pose Attributes %t|Local Location %x1|Local Rotation %x2|Local Size %x3|%l|Visual Location %x9|Visual Rotation %x10|Visual Size %x11|%l|Constraints (All) %x4|Constraints... %x5|%l|Transform Locks %x6|IK Limits %x7|Bone Shape %x8");
else
@@ -436,7 +436,7 @@ static void pose_copy_menu(Scene *scene)
pchan->constflag |= pchanact->constflag;
if (ob->pose)
- ob->pose->flag |= POSE_RECALC;
+ BKE_pose_tag_recalc(bmain, ob->pose);
}
break;
case 6: /* Transform Locks */
@@ -503,7 +503,7 @@ static void pose_copy_menu(Scene *scene)
/* build the puplist of constraints */
for (con = pchanact->constraints.first, i = 0; con; con = con->next, i++) {
const_toggle[i] = 1;
-// add_numbut(i, TOG|INT, con->name, 0, 0, &(const_toggle[i]), "");
+// add_numbut(i, UI_BTYPE_TOGGLE|INT, con->name, 0, 0, &(const_toggle[i]), "");
}
// if (!do_clever_numbuts("Select Constraints", i, REDRAW)) {
@@ -550,7 +550,7 @@ static void pose_copy_menu(Scene *scene)
BKE_pose_update_constraint_flags(ob->pose); /* we could work out the flags but its simpler to do this */
if (ob->pose)
- ob->pose->flag |= POSE_RECALC;
+ BKE_pose_tag_recalc(bmain, ob->pose);
}
DAG_id_tag_update(&ob->id, OB_RECALC_DATA); // and all its relations
@@ -595,7 +595,7 @@ void POSE_OT_flip_names(wmOperatorType *ot)
/* identifiers */
ot->name = "Flip Names";
ot->idname = "POSE_OT_flip_names";
- ot->description = "Flips (and corrects) the axis suffixes of the the names of selected bones";
+ ot->description = "Flips (and corrects) the axis suffixes of the names of selected bones";
/* api callbacks */
ot->exec = pose_flip_names_exec;
@@ -853,7 +853,7 @@ void ARMATURE_OT_armature_layers(wmOperatorType *ot)
/* Present a popup to get the layers that should be used */
static int pose_bone_layers_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- int layers[32] = {0}; /* hardcoded for now - we can only have 32 armature layers, so this should be fine... */
+ int layers[32]; /* hardcoded for now - we can only have 32 armature layers, so this should be fine... */
/* get layers that are active already */
CTX_DATA_BEGIN (C, bPoseChannel *, pchan, selected_pose_bones)
@@ -862,8 +862,7 @@ static int pose_bone_layers_invoke(bContext *C, wmOperator *op, const wmEvent *e
/* loop over the bits for this pchan's layers, adding layers where they're needed */
for (bit = 0; bit < 32; bit++) {
- if (pchan->bone->layer & (1 << bit))
- layers[bit] = 1;
+ layers[bit] = (pchan->bone->layer & (1u << bit)) != 0;
}
}
CTX_DATA_END;
@@ -937,8 +936,9 @@ static int armature_bone_layers_invoke(bContext *C, wmOperator *op, const wmEven
/* loop over the bits for this pchan's layers, adding layers where they're needed */
for (bit = 0; bit < 32; bit++) {
- if (ebone->layer & (1 << bit))
+ if (ebone->layer & (1u << bit)) {
layers[bit] = 1;
+ }
}
}
CTX_DATA_END;
diff --git a/source/blender/editors/armature/pose_group.c b/source/blender/editors/armature/pose_group.c
index 50d9d300d15..4d9df06f33f 100644
--- a/source/blender/editors/armature/pose_group.c
+++ b/source/blender/editors/armature/pose_group.c
@@ -130,6 +130,7 @@ static int pose_groups_menu_invoke(bContext *C, wmOperator *op, const wmEvent *U
{
Object *ob = ED_pose_object_from_context(C);
bPose *pose;
+ PropertyRNA *prop = RNA_struct_find_property(op->ptr, "type");
uiPopupMenu *pup;
uiLayout *layout;
@@ -140,12 +141,23 @@ static int pose_groups_menu_invoke(bContext *C, wmOperator *op, const wmEvent *U
if (ELEM(NULL, ob, ob->pose))
return OPERATOR_CANCELLED;
pose = ob->pose;
+
+ /* If group index is set, try to use it! */
+ if (RNA_property_is_set(op->ptr, prop)) {
+ const int num_groups = BLI_listbase_count(&pose->agroups);
+ const int group = RNA_property_int_get(op->ptr, prop);
+
+ /* just use the active group index, and call the exec callback for the calling operator */
+ if (group > 0 && group <= num_groups) {
+ return op->type->exec(C, op);
+ }
+ }
/* if there's no active group (or active is invalid), create a new menu to find it */
if (pose->active_group <= 0) {
/* create a new menu, and start populating it with group names */
- pup = uiPupMenuBegin(C, op->type->name, ICON_NONE);
- layout = uiPupMenuLayout(pup);
+ pup = UI_popup_menu_begin(C, op->type->name, ICON_NONE);
+ layout = UI_popup_menu_layout(pup);
/* special entry - allow to create new group, then use that
* (not to be used for removing though)
@@ -160,9 +172,9 @@ static int pose_groups_menu_invoke(bContext *C, wmOperator *op, const wmEvent *U
uiItemIntO(layout, grp->name, ICON_NONE, op->idname, "type", i);
/* finish building the menu, and process it (should result in calling self again) */
- uiPupMenuEnd(C, pup);
+ UI_popup_menu_end(C, pup);
- return OPERATOR_CANCELLED;
+ return OPERATOR_INTERFACE;
}
else {
/* just use the active group index, and call the exec callback for the calling operator */
@@ -365,8 +377,8 @@ typedef struct tSortActionGroup {
/* compare bone groups by name */
static int compare_agroup(const void *sgrp_a_ptr, const void *sgrp_b_ptr)
{
- tSortActionGroup *sgrp_a = (tSortActionGroup *)sgrp_a_ptr;
- tSortActionGroup *sgrp_b = (tSortActionGroup *)sgrp_b_ptr;
+ const tSortActionGroup *sgrp_a = sgrp_a_ptr;
+ const tSortActionGroup *sgrp_b = sgrp_b_ptr;
return strcmp(sgrp_a->agrp->name, sgrp_b->agrp->name);
}
@@ -387,7 +399,7 @@ static int group_sort_exec(bContext *C, wmOperator *UNUSED(op))
return OPERATOR_CANCELLED;
/* create temporary array with bone groups and indices */
- agrp_count = BLI_countlist(&pose->agroups);
+ agrp_count = BLI_listbase_count(&pose->agroups);
agrp_array = MEM_mallocN(sizeof(tSortActionGroup) * agrp_count, "sort bone groups");
for (agrp = pose->agroups.first, i = 0; agrp; agrp = agrp->next, i++) {
BLI_assert(i < agrp_count);
diff --git a/source/blender/editors/armature/pose_lib.c b/source/blender/editors/armature/pose_lib.c
index 0609fcc29e8..a984e5d1ccd 100644
--- a/source/blender/editors/armature/pose_lib.c
+++ b/source/blender/editors/armature/pose_lib.c
@@ -35,7 +35,7 @@
#include "BLI_blenlib.h"
#include "BLI_dlrbTree.h"
-#include "BLF_translation.h"
+#include "BLT_translation.h"
#include "DNA_anim_types.h"
#include "DNA_armature_types.h"
@@ -177,6 +177,15 @@ static int has_poselib_pose_data_poll(bContext *C)
return (ob && ob->poselib);
}
+/* Poll callback for operators that require existing PoseLib data (with poses)
+ * as they need to do some editing work on those poses (i.e. not on lib-linked actions)
+ */
+static int has_poselib_pose_data_for_editing_poll(bContext *C)
+{
+ Object *ob = get_poselib_object(C);
+ return (ob && ob->poselib && !ob->poselib->id.lib);
+}
+
/* ----------------------------------- */
/* Initialize a new poselib (whether it is needed or not) */
@@ -357,7 +366,7 @@ void POSELIB_OT_action_sanitize(wmOperatorType *ot)
/* callbacks */
ot->exec = poselib_sanitize_exec;
- ot->poll = has_poselib_pose_data_poll;
+ ot->poll = has_poselib_pose_data_for_editing_poll;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
@@ -365,6 +374,25 @@ void POSELIB_OT_action_sanitize(wmOperatorType *ot)
/* ------------------------------------------ */
+/* Poll callback for adding poses to a PoseLib */
+static int poselib_add_poll(bContext *C)
+{
+ /* There are 2 cases we need to be careful with:
+ * 1) When this operator is invoked from a hotkey, there may be no PoseLib yet
+ * 2) If a PoseLib already exists, we can't edit the action if it is a lib-linked
+ * actions, as data will be lost when saving the file
+ */
+ if (ED_operator_posemode(C)) {
+ Object *ob = get_poselib_object(C);
+ if (ob) {
+ if ((ob->poselib == NULL) || (ob->poselib->id.lib == 0)) {
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
static void poselib_add_menu_invoke__replacemenu(bContext *C, uiLayout *layout, void *UNUSED(arg))
{
Object *ob = get_poselib_object(C);
@@ -404,8 +432,8 @@ static int poselib_add_menu_invoke(bContext *C, wmOperator *op, const wmEvent *U
return OPERATOR_CANCELLED;
/* start building */
- pup = uiPupMenuBegin(C, op->type->name, ICON_NONE);
- layout = uiPupMenuLayout(pup);
+ pup = UI_popup_menu_begin(C, op->type->name, ICON_NONE);
+ layout = UI_popup_menu_layout(pup);
uiLayoutSetOperatorContext(layout, WM_OP_EXEC_DEFAULT);
/* add new (adds to the first unoccupied frame) */
@@ -420,10 +448,10 @@ static int poselib_add_menu_invoke(bContext *C, wmOperator *op, const wmEvent *U
uiItemMenuF(layout, IFACE_("Replace Existing..."), 0, poselib_add_menu_invoke__replacemenu, NULL);
}
- uiPupMenuEnd(C, pup);
+ UI_popup_menu_end(C, pup);
/* this operator is only for a menu, not used further */
- return OPERATOR_CANCELLED;
+ return OPERATOR_INTERFACE;
}
@@ -472,7 +500,7 @@ static int poselib_add_exec(bContext *C, wmOperator *op)
ANIM_apply_keyingset(C, NULL, act, ks, MODIFYKEY_MODE_INSERT, (float)frame);
/* store new 'active' pose number */
- act->active_marker = BLI_countlist(&act->markers);
+ act->active_marker = BLI_listbase_count(&act->markers);
/* done */
return OPERATOR_FINISHED;
@@ -488,7 +516,7 @@ void POSELIB_OT_pose_add(wmOperatorType *ot)
/* api callbacks */
ot->invoke = poselib_add_menu_invoke;
ot->exec = poselib_add_exec;
- ot->poll = ED_operator_posemode;
+ ot->poll = poselib_add_poll;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
@@ -604,7 +632,7 @@ void POSELIB_OT_pose_remove(wmOperatorType *ot)
/* api callbacks */
ot->invoke = WM_menu_invoke;
ot->exec = poselib_remove_exec;
- ot->poll = has_poselib_pose_data_poll;
+ ot->poll = has_poselib_pose_data_for_editing_poll;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
@@ -692,7 +720,7 @@ void POSELIB_OT_pose_rename(wmOperatorType *ot)
/* api callbacks */
ot->invoke = poselib_rename_invoke;
ot->exec = poselib_rename_exec;
- ot->poll = has_poselib_pose_data_poll;
+ ot->poll = has_poselib_pose_data_for_editing_poll;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
@@ -916,7 +944,7 @@ static void poselib_keytag_pose(bContext *C, Scene *scene, tPoseLib_PreviewData
KeyingSet *ks = ANIM_get_keyingset_for_autokeying(scene, ANIM_KS_WHOLE_CHARACTER_ID);
ListBase dsources = {NULL, NULL};
- short autokey = autokeyframe_cfra_can_key(scene, &pld->ob->id);
+ bool autokey = autokeyframe_cfra_can_key(scene, &pld->ob->id);
/* start tagging/keying */
for (agrp = act->groups.first; agrp; agrp = agrp->next) {
@@ -1050,7 +1078,7 @@ static void poselib_preview_get_next(tPoseLib_PreviewData *pld, int step)
LinkData *ld, *ldn, *ldc;
/* free and rebuild if needed (i.e. if search-str changed) */
- if (strcmp(pld->searchstr, pld->searchold)) {
+ if (!STREQ(pld->searchstr, pld->searchold)) {
/* free list of temporary search matches */
BLI_freelistN(&pld->searchp);
@@ -1196,7 +1224,7 @@ static int poselib_preview_handle_event(bContext *UNUSED(C), wmOperator *op, con
/* only accept 'press' event, and ignore 'release', so that we don't get double actions */
if (ELEM(event->val, KM_PRESS, KM_NOTHING) == 0) {
- //printf("PoseLib: skipping event with type '%s' and val %d\n", WM_key_event_string(event->type), event->val);
+ //printf("PoseLib: skipping event with type '%s' and val %d\n", WM_key_event_string(event->type, false), event->val);
return ret;
}
@@ -1348,7 +1376,7 @@ static int poselib_preview_handle_event(bContext *UNUSED(C), wmOperator *op, con
else {
/* change to last pose */
pld->marker = pld->act->markers.last;
- pld->act->active_marker = BLI_countlist(&pld->act->markers);
+ pld->act->active_marker = BLI_listbase_count(&pld->act->markers);
pld->redraw = PL_PREVIEW_REDRAWALL;
}
diff --git a/source/blender/editors/armature/pose_select.c b/source/blender/editors/armature/pose_select.c
index ba5ef4f3b5d..44470c1f827 100644
--- a/source/blender/editors/armature/pose_select.c
+++ b/source/blender/editors/armature/pose_select.c
@@ -62,7 +62,7 @@
#include "armature_intern.h"
-/* utility macros fro storing a temp int in the bone (selection flag) */
+/* utility macros for storing a temp int in the bone (selection flag) */
#define PBONE_PREV_FLAG_GET(pchan) ((void)0, (GET_INT_FROM_POINTER((pchan)->temp)))
#define PBONE_PREV_FLAG_SET(pchan, val) ((pchan)->temp = SET_INT_IN_POINTER(val))
@@ -458,7 +458,7 @@ static int pose_select_constraint_target_exec(bContext *C, wmOperator *UNUSED(op
{
if (pchan->bone->flag & BONE_SELECTED) {
for (con = pchan->constraints.first; con; con = con->next) {
- bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
+ const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
ListBase targets = {NULL, NULL};
bConstraintTarget *ct;
@@ -518,71 +518,67 @@ static int pose_select_hierarchy_exec(bContext *C, wmOperator *op)
{
Object *ob = BKE_object_pose_armature_get(CTX_data_active_object(C));
bArmature *arm = ob->data;
- Bone *curbone, *pabone, *chbone;
+ bPoseChannel *pchan_act;
int direction = RNA_enum_get(op->ptr, "direction");
const bool add_to_sel = RNA_boolean_get(op->ptr, "extend");
- bool found = false;
+ bool changed = false;
- CTX_DATA_BEGIN (C, bPoseChannel *, pchan, visible_pose_bones)
- {
- curbone = pchan->bone;
-
- if ((curbone->flag & BONE_UNSELECTABLE) == 0) {
- if (curbone == arm->act_bone) {
- if (direction == BONE_SELECT_PARENT) {
- if (pchan->parent == NULL) continue;
- else pabone = pchan->parent->bone;
-
- if (PBONE_SELECTABLE(arm, pabone)) {
- if (!add_to_sel) curbone->flag &= ~BONE_SELECTED;
- pabone->flag |= BONE_SELECTED;
- arm->act_bone = pabone;
-
- found = 1;
- break;
- }
+ pchan_act = BKE_pose_channel_active(ob);
+ if (pchan_act == NULL) {
+ return OPERATOR_CANCELLED;
+ }
+
+ if (direction == BONE_SELECT_PARENT) {
+ if (pchan_act->parent) {
+ Bone *bone_parent;
+ bone_parent = pchan_act->parent->bone;
+
+ if (PBONE_SELECTABLE(arm, bone_parent)) {
+ if (!add_to_sel) {
+ pchan_act->bone->flag &= ~BONE_SELECTED;
}
- else { /* direction == BONE_SELECT_CHILD */
- /* the child member is only assigned to connected bones, see [#30340] */
-#if 0
- if (pchan->child == NULL) continue;
- else chbone = pchan->child->bone;
-#else
- /* instead. find _any_ visible child bone, using the first one is a little arbitrary - campbell */
- chbone = pchan->child ? pchan->child->bone : NULL;
- if (chbone == NULL) {
- bPoseChannel *pchan_child;
-
- for (pchan_child = ob->pose->chanbase.first; pchan_child; pchan_child = pchan_child->next) {
- /* possible we have multiple children, some invisible */
- if (PBONE_SELECTABLE(arm, pchan_child->bone)) {
- if (pchan_child->parent == pchan) {
- chbone = pchan_child->bone;
- break;
- }
- }
- }
- }
+ bone_parent->flag |= BONE_SELECTED;
+ arm->act_bone = bone_parent;
- if (chbone == NULL) continue;
-#endif
-
- if (PBONE_SELECTABLE(arm, chbone)) {
- if (!add_to_sel) curbone->flag &= ~BONE_SELECTED;
- chbone->flag |= BONE_SELECTED;
- arm->act_bone = chbone;
-
- found = 1;
- break;
+ changed = true;
+ }
+ }
+ }
+ else { /* direction == BONE_SELECT_CHILD */
+ bPoseChannel *pchan_iter;
+ Bone *bone_child = NULL;
+ int pass;
+
+ /* first pass, only connected bones (the logical direct child) */
+ for (pass = 0; pass < 2 && (bone_child == NULL); pass++) {
+ for (pchan_iter = ob->pose->chanbase.first; pchan_iter; pchan_iter = pchan_iter->next) {
+ /* possible we have multiple children, some invisible */
+ if (PBONE_SELECTABLE(arm, pchan_iter->bone)) {
+ if (pchan_iter->parent == pchan_act) {
+ if ((pass == 1) || (pchan_iter->bone->flag & BONE_CONNECTED)) {
+ bone_child = pchan_iter->bone;
+ break;
+ }
}
}
}
}
+
+ if (bone_child) {
+ arm->act_bone = bone_child;
+
+ if (!add_to_sel) {
+ pchan_act->bone->flag &= ~BONE_SELECTED;
+ }
+ bone_child->flag |= BONE_SELECTED;
+
+ changed = true;
+ }
}
- CTX_DATA_END;
- if (found == 0)
+ if (changed == false) {
return OPERATOR_CANCELLED;
+ }
/* updates */
WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, ob);
@@ -642,7 +638,7 @@ static bool pose_select_same_group(bContext *C, Object *ob, bool extend)
return 0;
/* count the number of groups */
- numGroups = BLI_countlist(&pose->agroups);
+ numGroups = BLI_listbase_count(&pose->agroups);
if (numGroups == 0)
return 0;
@@ -825,7 +821,7 @@ static int pose_select_grouped_exec(bContext *C, wmOperator *op)
break;
default:
- printf("pose_select_grouped() - Unknown selection type %d\n", type);
+ printf("pose_select_grouped() - Unknown selection type %u\n", type);
break;
}
diff --git a/source/blender/editors/armature/pose_slide.c b/source/blender/editors/armature/pose_slide.c
index 5f9f24d23a4..40328e0c06e 100644
--- a/source/blender/editors/armature/pose_slide.c
+++ b/source/blender/editors/armature/pose_slide.c
@@ -43,6 +43,7 @@
#include "BKE_context.h"
#include "BKE_object.h"
#include "BKE_report.h"
+#include "BKE_unit.h"
#include "RNA_access.h"
#include "RNA_define.h"
@@ -53,6 +54,7 @@
#include "ED_armature.h"
#include "ED_keyframes_draw.h"
#include "ED_markers.h"
+#include "ED_numinput.h"
#include "ED_screen.h"
#include "armature_intern.h"
@@ -98,6 +100,8 @@ typedef struct tPoseSlideOp {
int flag; /* unused for now, but can later get used for storing runtime settings.... */
float percentage; /* 0-1 value for determining the influence of whatever is relevant */
+
+ NumInput num; /* numeric input */
} tPoseSlideOp;
/* Pose Sliding Modes */
@@ -154,6 +158,12 @@ static int pose_slide_init(bContext *C, wmOperator *op, short mode)
*/
BLI_dlrbTree_init(&pso->keys);
+ /* initialise numeric input */
+ initNumInput(&pso->num);
+ pso->num.idx_max = 0; /* one axis */
+ pso->num.val_flag[0] |= NUM_NO_NEGATIVE;
+ pso->num.unit_type[0] = B_UNIT_NONE; /* percentages don't have any units... */
+
/* return status is whether we've got all the data we were requested to get */
return 1;
}
@@ -201,6 +211,12 @@ static void pose_slide_apply_val(tPoseSlideOp *pso, FCurve *fcu, float *val)
/* next/end */
eVal = evaluate_fcurve(fcu, (float)pso->nextFrame);
+ /* if both values are equal, don't do anything */
+ if (IS_EQF(sVal, eVal)) {
+ (*val) = sVal;
+ return;
+ }
+
/* calculate the relative weights of the endpoints */
if (pso->mode == POSESLIDE_BREAKDOWN) {
/* get weights from the percentage control */
@@ -234,7 +250,7 @@ static void pose_slide_apply_val(tPoseSlideOp *pso, FCurve *fcu, float *val)
* - perform this weighting a number of times given by the percentage...
*/
int iters = (int)ceil(10.0f * pso->percentage); /* TODO: maybe a sensitivity ctrl on top of this is needed */
-
+
while (iters-- > 0) {
(*val) = (-((sVal * w2) + (eVal * w1)) + ((*val) * 6.0f) ) / 5.0f;
}
@@ -247,7 +263,7 @@ static void pose_slide_apply_val(tPoseSlideOp *pso, FCurve *fcu, float *val)
* - perform this weighting a number of times given by the percentage...
*/
int iters = (int)ceil(10.0f * pso->percentage); /* TODO: maybe a sensitivity ctrl on top of this is needed */
-
+
while (iters-- > 0) {
(*val) = ( ((sVal * w2) + (eVal * w1)) + ((*val) * 5.0f) ) / 6.0f;
}
@@ -320,6 +336,7 @@ static void pose_slide_apply_props(tPoseSlideOp *pso, tPChanFCurveLink *pfl)
if (prop) {
switch (RNA_property_type(prop)) {
+ /* continuous values that can be smoothly interpolated... */
case PROP_FLOAT:
{
float tval = RNA_property_float_get(&ptr, prop);
@@ -327,8 +344,6 @@ static void pose_slide_apply_props(tPoseSlideOp *pso, tPChanFCurveLink *pfl)
RNA_property_float_set(&ptr, prop, tval);
break;
}
- case PROP_BOOLEAN:
- case PROP_ENUM:
case PROP_INT:
{
float tval = (float)RNA_property_int_get(&ptr, prop);
@@ -336,6 +351,23 @@ static void pose_slide_apply_props(tPoseSlideOp *pso, tPChanFCurveLink *pfl)
RNA_property_int_set(&ptr, prop, (int)tval);
break;
}
+
+ /* values which can only take discrete values */
+ case PROP_BOOLEAN:
+ {
+ float tval = (float)RNA_property_boolean_get(&ptr, prop);
+ pose_slide_apply_val(pso, fcu, &tval);
+ RNA_property_boolean_set(&ptr, prop, (int)tval); // XXX: do we need threshold clamping here?
+ break;
+ }
+ case PROP_ENUM:
+ {
+ /* don't handle this case - these don't usually represent interchangeable
+ * set of values which should be interpolated between
+ */
+ break;
+ }
+
default:
/* cannot handle */
//printf("Cannot Pose Slide non-numerical property\n");
@@ -404,11 +436,11 @@ static void pose_slide_apply_quat(tPoseSlideOp *pso, tPChanFCurveLink *pfl)
}
else if (pso->mode == POSESLIDE_PUSH) {
float quat_diff[4], quat_orig[4];
-
+
/* calculate the delta transform from the previous to the current */
/* TODO: investigate ways to favour one transform more? */
sub_qt_qtqt(quat_diff, pchan->quat, quat_prev);
-
+
/* make a copy of the original rotation */
copy_qt_qt(quat_orig, pchan->quat);
@@ -418,7 +450,7 @@ static void pose_slide_apply_quat(tPoseSlideOp *pso, tPChanFCurveLink *pfl)
else {
float quat_interp[4], quat_orig[4];
int iters = (int)ceil(10.0f * pso->percentage); /* TODO: maybe a sensitivity ctrl on top of this is needed */
-
+
/* perform this blending several times until a satisfactory result is reached */
while (iters-- > 0) {
/* calculate the interpolation between the endpoints */
@@ -512,7 +544,7 @@ static void pose_slide_reset(tPoseSlideOp *pso)
/* draw percentage indicator in header */
static void pose_slide_draw_status(tPoseSlideOp *pso)
{
- char status_str[32];
+ char status_str[256];
char mode_str[32];
switch (pso->mode) {
@@ -532,7 +564,18 @@ static void pose_slide_draw_status(tPoseSlideOp *pso)
break;
}
- BLI_snprintf(status_str, sizeof(status_str), "%s: %d %%", mode_str, (int)(pso->percentage * 100.0f));
+ if (hasNumInput(&pso->num)) {
+ Scene *scene = pso->scene;
+ char str_offs[NUM_STR_REP_LEN];
+
+ outputNumInput(&pso->num, str_offs, &scene->unit);
+
+ BLI_snprintf(status_str, sizeof(status_str), "%s: %s", mode_str, str_offs);
+ }
+ else {
+ BLI_snprintf(status_str, sizeof(status_str), "%s: %d %%", mode_str, (int)(pso->percentage * 100.0f));
+ }
+
ED_area_headerprint(pso->sa, status_str);
}
@@ -617,6 +660,7 @@ static int pose_slide_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
tPoseSlideOp *pso = op->customdata;
wmWindow *win = CTX_wm_window(C);
+ const bool has_numinput = hasNumInput(&pso->num);
switch (event->type) {
case LEFTMOUSE: /* confirm */
@@ -656,25 +700,54 @@ static int pose_slide_modal(bContext *C, wmOperator *op, const wmEvent *event)
case MOUSEMOVE: /* calculate new position */
{
- /* calculate percentage based on position of mouse (we only use x-axis for now.
- * since this is more convenient for users to do), and store new percentage value
- */
- pso->percentage = (event->x - pso->ar->winrct.xmin) / ((float)pso->ar->winx);
- RNA_float_set(op->ptr, "percentage", pso->percentage);
-
- /* update percentage indicator in header */
- pose_slide_draw_status(pso);
-
- /* reset transforms (to avoid accumulation errors) */
- pose_slide_reset(pso);
-
- /* apply... */
- pose_slide_apply(C, pso);
+ /* only handle mousemove if not doing numinput */
+ if (has_numinput == false) {
+ /* calculate percentage based on position of mouse (we only use x-axis for now.
+ * since this is more convenient for users to do), and store new percentage value
+ */
+ pso->percentage = (event->x - pso->ar->winrct.xmin) / ((float)pso->ar->winx);
+ RNA_float_set(op->ptr, "percentage", pso->percentage);
+
+ /* update percentage indicator in header */
+ pose_slide_draw_status(pso);
+
+ /* reset transforms (to avoid accumulation errors) */
+ pose_slide_reset(pso);
+
+ /* apply... */
+ pose_slide_apply(C, pso);
+ }
break;
}
- default: /* unhandled event (maybe it was some view manip? */
- /* allow to pass through */
- return OPERATOR_RUNNING_MODAL | OPERATOR_PASS_THROUGH;
+ default:
+ if ((event->val == KM_PRESS) && handleNumInput(C, &pso->num, event)) {
+ float value;
+
+ /* Grab percentage from numeric input, and store this new value for redo
+ * NOTE: users see ints, while internally we use a 0-1 float
+ */
+ value = pso->percentage * 100.0f;
+ applyNumInput(&pso->num, &value);
+
+ pso->percentage = value / 100.0f;
+ CLAMP(pso->percentage, 0.0f, 1.0f);
+ RNA_float_set(op->ptr, "percentage", pso->percentage);
+
+ /* update percentage indicator in header */
+ pose_slide_draw_status(pso);
+
+ /* reset transforms (to avoid accumulation errors) */
+ pose_slide_reset(pso);
+
+ /* apply... */
+ pose_slide_apply(C, pso);
+ break;
+ }
+ else {
+ /* unhandled event - maybe it was some view manip? */
+ /* allow to pass through */
+ return OPERATOR_RUNNING_MODAL | OPERATOR_PASS_THROUGH;
+ }
}
/* still running... */
@@ -898,6 +971,8 @@ typedef enum ePosePropagate_Termination {
/* stop when we run out of keyframes */
POSE_PROPAGATE_BEFORE_END,
+ /* only do on keyframes that are selected */
+ POSE_PROPAGATE_SELECTED_KEYS,
/* only do on the frames where markers are selected */
POSE_PROPAGATE_SELECTED_MARKERS
} ePosePropagate_Termination;
@@ -1098,13 +1173,20 @@ static void pose_propagate_fcurve(wmOperator *op, Object *ob, FCurve *fcu,
* since it may be as of yet unkeyed
* - if starting before the starting frame, don't touch the key, as it may have had some valid
* values
+ * - if only doing selected keyframes, start from the first one
*/
- match = binarysearch_bezt_index(fcu->bezt, startFrame, fcu->totvert, &keyExists);
-
- if (fcu->bezt[match].vec[1][0] < startFrame)
- i = match + 1;
- else
- i = match;
+ if (mode != POSE_PROPAGATE_SELECTED_KEYS) {
+ match = binarysearch_bezt_index(fcu->bezt, startFrame, fcu->totvert, &keyExists);
+
+ if (fcu->bezt[match].vec[1][0] < startFrame)
+ i = match + 1;
+ else
+ i = match;
+ }
+ else {
+ /* selected - start from first keyframe */
+ i = 0;
+ }
for (bezt = &fcu->bezt[i]; i < fcu->totvert; i++, bezt++) {
/* additional termination conditions based on the operator 'mode' property go here... */
@@ -1137,6 +1219,11 @@ static void pose_propagate_fcurve(wmOperator *op, Object *ob, FCurve *fcu,
if (ce == NULL)
continue;
}
+ else if (mode == POSE_PROPAGATE_SELECTED_KEYS) {
+ /* only allow if this keyframe is already selected - skip otherwise */
+ if (BEZT_ISSEL_ANY(bezt) == 0)
+ continue;
+ }
/* just flatten handles, since values will now be the same either side... */
/* TODO: perhaps a fade-out modulation of the value is required here (optional once again)? */
@@ -1219,12 +1306,20 @@ static int pose_propagate_exec(bContext *C, wmOperator *op)
void POSE_OT_propagate(wmOperatorType *ot)
{
static EnumPropertyItem terminate_items[] = {
- {POSE_PROPAGATE_SMART_HOLDS, "WHILE_HELD", 0, "While Held", "Propagate pose to all keyframes after current frame that don't change (Default behavior)"},
- {POSE_PROPAGATE_NEXT_KEY, "NEXT_KEY", 0, "To Next Keyframe", "Propagate pose to first keyframe following the current frame only"},
- {POSE_PROPAGATE_LAST_KEY, "LAST_KEY", 0, "To Last Keyframe", "Propagate pose to the last keyframe only (i.e. making action cyclic)"},
- {POSE_PROPAGATE_BEFORE_FRAME, "BEFORE_FRAME", 0, "Before Frame", "Propagate pose to all keyframes between current frame and 'Frame' property"},
- {POSE_PROPAGATE_BEFORE_END, "BEFORE_END", 0, "Before Last Keyframe", "Propagate pose to all keyframes from current frame until no more are found"},
- {POSE_PROPAGATE_SELECTED_MARKERS, "SELECTED_MARKERS", 0, "On Selected Markers", "Propagate pose to all keyframes occurring on frames with Scene Markers after the current frame"},
+ {POSE_PROPAGATE_SMART_HOLDS, "WHILE_HELD", 0, "While Held",
+ "Propagate pose to all keyframes after current frame that don't change (Default behavior)"},
+ {POSE_PROPAGATE_NEXT_KEY, "NEXT_KEY", 0, "To Next Keyframe",
+ "Propagate pose to first keyframe following the current frame only"},
+ {POSE_PROPAGATE_LAST_KEY, "LAST_KEY", 0, "To Last Keyframe",
+ "Propagate pose to the last keyframe only (i.e. making action cyclic)"},
+ {POSE_PROPAGATE_BEFORE_FRAME, "BEFORE_FRAME", 0, "Before Frame",
+ "Propagate pose to all keyframes between current frame and 'Frame' property"},
+ {POSE_PROPAGATE_BEFORE_END, "BEFORE_END", 0, "Before Last Keyframe",
+ "Propagate pose to all keyframes from current frame until no more are found"},
+ {POSE_PROPAGATE_SELECTED_KEYS, "SELECTED_KEYS", 0, "On Selected Keyframes",
+ "Propagate pose to all selected keyframes"},
+ {POSE_PROPAGATE_SELECTED_MARKERS, "SELECTED_MARKERS", 0, "On Selected Markers",
+ "Propagate pose to all keyframes occurring on frames with Scene Markers after the current frame"},
{0, NULL, 0, NULL, NULL}};
/* identifiers */
diff --git a/source/blender/editors/armature/pose_transform.c b/source/blender/editors/armature/pose_transform.c
index 0cde8f30ace..01e16df9f08 100644
--- a/source/blender/editors/armature/pose_transform.c
+++ b/source/blender/editors/armature/pose_transform.c
@@ -320,7 +320,7 @@ static bPoseChannel *pose_bone_do_paste(Object *ob, bPoseChannel *chan, const bo
if (selOnly)
paste_ok = ((pchan) && (pchan->bone->flag & BONE_SELECTED));
else
- paste_ok = ((pchan != NULL));
+ paste_ok = (pchan != NULL);
/* continue? */
if (paste_ok) {
@@ -811,7 +811,7 @@ void POSE_OT_transforms_clear(wmOperatorType *ot)
static int pose_clear_user_transforms_exec(bContext *C, wmOperator *op)
{
Scene *scene = CTX_data_scene(C);
- Object *ob = CTX_data_active_object(C);
+ Object *ob = BKE_object_pose_armature_get(CTX_data_active_object(C));
float cframe = (float)CFRA;
const bool only_select = RNA_boolean_get(op->ptr, "only_selected");
diff --git a/source/blender/editors/armature/pose_utils.c b/source/blender/editors/armature/pose_utils.c
index 380a3fffc6d..2ba1eedd33b 100644
--- a/source/blender/editors/armature/pose_utils.c
+++ b/source/blender/editors/armature/pose_utils.c
@@ -49,8 +49,6 @@
#include "WM_api.h"
#include "WM_types.h"
-
-
#include "ED_armature.h"
#include "ED_keyframing.h"
@@ -261,7 +259,7 @@ LinkData *poseAnim_mapping_getNextFCurve(ListBase *fcuLinks, LinkData *prev, con
FCurve *fcu = (FCurve *)ld->data;
/* check if paths match */
- if (strcmp(path, fcu->rna_path) == 0)
+ if (STREQ(path, fcu->rna_path))
return ld;
}
diff --git a/source/blender/editors/armature/reeb.c b/source/blender/editors/armature/reeb.c
index 8cc6059e87b..f29d15ff416 100644
--- a/source/blender/editors/armature/reeb.c
+++ b/source/blender/editors/armature/reeb.c
@@ -107,7 +107,7 @@ static VertexData *allocVertexData(EditMesh *em)
EditVert *eve;
int totvert, index;
- totvert = BLI_countlist(&em->verts);
+ totvert = BLI_listbase_count(&em->verts);
data = MEM_callocN(sizeof(VertexData) * totvert, "VertexData");
@@ -1141,7 +1141,7 @@ static int compareNodesWeight(void *vnode1, void *vnode2)
void sortNodes(ReebGraph *rg)
{
- BLI_sortlist(&rg->nodes, compareNodesWeight);
+ BLI_listbase_sort(&rg->nodes, compareNodesWeight);
}
static int compareArcsWeight(void *varc1, void *varc2)
@@ -1166,7 +1166,7 @@ static int compareArcsWeight(void *varc1, void *varc2)
void sortArcs(ReebGraph *rg)
{
- BLI_sortlist(&rg->arcs, compareArcsWeight);
+ BLI_listbase_sort(&rg->arcs, compareArcsWeight);
}
/******************************************* JOINING ***************************************************/
@@ -1512,7 +1512,7 @@ static int filterInternalExternalReebGraph(ReebGraph *rg, float threshold_intern
ReebArc *arc = NULL, *nextArc = NULL;
int value = 0;
- BLI_sortlist(&rg->arcs, compareArcs);
+ BLI_listbase_sort(&rg->arcs, compareArcs);
for (arc = rg->arcs.first; arc; arc = nextArc) {
nextArc = arc->next;
@@ -1632,7 +1632,7 @@ int filterSmartReebGraph(ReebGraph *UNUSED(rg), float UNUSED(threshold))
#if 0 //XXX
ReebArc *arc = NULL, *nextArc = NULL;
- BLI_sortlist(&rg->arcs, compareArcs);
+ BLI_listbase_sort(&rg->arcs, compareArcs);
#ifdef DEBUG_REEB
{
@@ -1867,7 +1867,7 @@ static void spreadWeight(EditMesh *em)
{
EditVert **verts, *eve;
float lastWeight = 0.0f;
- int totvert = BLI_countlist(&em->verts);
+ int totvert = BLI_listbase_count(&em->verts);
int i;
int work_needed = 1;
@@ -2399,9 +2399,9 @@ ReebGraph *generateReebGraph(EditMesh *em, int subdivisions)
rg->resolution = subdivisions;
- /*totvert = BLI_countlist(&em->verts);*/ /*UNUSED*/
+ /*totvert = BLI_listbase_count(&em->verts);*/ /*UNUSED*/
#ifdef DEBUG_REEB
- totfaces = BLI_countlist(&em->faces);
+ totfaces = BLI_listbase_count(&em->faces);
#endif
renormalizeWeight(em, 1.0f);
@@ -2460,7 +2460,7 @@ void renormalizeWeight(EditMesh *em, float newmax)
EditVert *eve;
float minimum, maximum, range;
- if (em == NULL || BLI_countlist(&em->verts) == 0)
+ if (em == NULL || BLI_listbase_is_empty(&em->verts))
return;
/* First pass, determine maximum and minimum */
@@ -2486,7 +2486,7 @@ int weightFromLoc(EditMesh *em, int axis)
{
EditVert *eve;
- if (em == NULL || BLI_countlist(&em->verts) == 0 || axis < 0 || axis > 2)
+ if (em == NULL || BLI_listbase_is_empty(&em->verts) || axis < 0 || axis > 2)
return 0;
/* Copy coordinate in weight */
@@ -2738,7 +2738,7 @@ static void buildIndexedEdges(EditMesh *em, EdgeIndex *indexed_edges)
int tot_indexed = 0;
int offset = 0;
- totvert = BLI_countlist(&em->verts);
+ totvert = BLI_listbase_count(&em->verts);
indexed_edges->offset = MEM_callocN(totvert * sizeof(int), "EdgeIndex offset");
@@ -2791,13 +2791,13 @@ int weightFromDistance(EditMesh *em, EdgeIndex *indexed_edges)
int totvert = 0;
int vCount = 0;
- totvert = BLI_countlist(&em->verts);
+ totvert = BLI_listbase_count(&em->verts);
if (em == NULL || totvert == 0) {
return 0;
}
- totedge = BLI_countlist(&em->edges);
+ totedge = BLI_listbase_count(&em->edges);
if (totedge == 0) {
return 0;
diff --git a/source/blender/editors/armature/reeb.h b/source/blender/editors/armature/reeb.h
index b0e1fd3ae34..a6ef16fed67 100644
--- a/source/blender/editors/armature/reeb.h
+++ b/source/blender/editors/armature/reeb.h
@@ -140,6 +140,7 @@ typedef struct ReebArcIterator {
int stride;
} ReebArcIterator;
+#if 0
struct EditMesh;
struct EdgeIndex;
@@ -152,6 +153,8 @@ void arcToVCol(struct ReebGraph *rg, struct EditMesh *em, int index);
void renormalizeWeight(struct EditMesh *em, float newmax);
ReebGraph *generateReebGraph(struct EditMesh *me, int subdivisions);
+#endif
+
ReebGraph *newReebGraph(void);
void initArcIterator(BArcIterator *iter, struct ReebArc *arc, struct ReebNode *head);
diff --git a/source/blender/editors/curve/CMakeLists.txt b/source/blender/editors/curve/CMakeLists.txt
index 0b449c4334d..83346e9550c 100644
--- a/source/blender/editors/curve/CMakeLists.txt
+++ b/source/blender/editors/curve/CMakeLists.txt
@@ -20,9 +20,9 @@
set(INC
../include
- ../../blenfont
../../blenkernel
../../blenlib
+ ../../blentranslation
../../makesdna
../../makesrna
../../windowmanager
@@ -37,8 +37,8 @@ set(SRC
curve_ops.c
editcurve.c
editcurve_add.c
+ editcurve_select.c
editfont.c
- lorem.c
curve_intern.h
)
diff --git a/source/blender/editors/curve/SConscript b/source/blender/editors/curve/SConscript
index 4760a212a8a..eadec4f65b6 100644
--- a/source/blender/editors/curve/SConscript
+++ b/source/blender/editors/curve/SConscript
@@ -34,9 +34,9 @@ defs = []
incs = [
'#/intern/guardedalloc',
'../include',
- '../../blenfont',
'../../blenkernel',
'../../blenlib',
+ '../../blentranslation',
'../../makesdna',
'../../makesrna',
'../../render/extern/include',
diff --git a/source/blender/editors/curve/curve_intern.h b/source/blender/editors/curve/curve_intern.h
index d54db77754f..29904bf2344 100644
--- a/source/blender/editors/curve/curve_intern.h
+++ b/source/blender/editors/curve/curve_intern.h
@@ -37,9 +37,7 @@ struct ListBase;
struct EditNurb;
struct Object;
struct wmOperatorType;
-
-/* lorem.c */
-extern const char ED_lorem[];
+struct ViewContext;
/* editfont.c */
enum { DEL_ALL, DEL_NEXT_CHAR, DEL_PREV_CHAR, DEL_SELECTION, DEL_NEXT_SEL, DEL_PREV_SEL };
@@ -47,6 +45,25 @@ enum { CASE_LOWER, CASE_UPPER };
enum { LINE_BEGIN, LINE_END, PREV_CHAR, NEXT_CHAR, PREV_WORD, NEXT_WORD,
PREV_LINE, NEXT_LINE, PREV_PAGE, NEXT_PAGE };
+typedef enum eVisible_Types {
+ HIDDEN = true,
+ VISIBLE = false,
+} eVisible_Types;
+
+typedef enum eEndPoint_Types {
+ FIRST = true,
+ LAST = false,
+} eEndPoint_Types;
+
+typedef enum eCurveElem_Types {
+ CURVE_VERTEX = 0,
+ CURVE_SEGMENT,
+} eCurveElem_Types;
+
+/* internal select utils */
+bool select_beztriple(BezTriple *bezt, bool selstatus, short flag, eVisible_Types hidden);
+bool select_bpoint(BPoint *bp, bool selstatus, short flag, bool hidden);
+
void FONT_OT_text_insert(struct wmOperatorType *ot);
void FONT_OT_line_break(struct wmOperatorType *ot);
void FONT_OT_insert_lorem(struct wmOperatorType *ot);
@@ -101,19 +118,6 @@ void CURVE_OT_smooth_weight(struct wmOperatorType *ot);
void CURVE_OT_smooth_radius(struct wmOperatorType *ot);
void CURVE_OT_smooth_tilt(struct wmOperatorType *ot);
-void CURVE_OT_de_select_first(struct wmOperatorType *ot);
-void CURVE_OT_de_select_last(struct wmOperatorType *ot);
-void CURVE_OT_select_all(struct wmOperatorType *ot);
-void CURVE_OT_select_linked(struct wmOperatorType *ot);
-void CURVE_OT_select_linked_pick(struct wmOperatorType *ot);
-void CURVE_OT_select_row(struct wmOperatorType *ot);
-void CURVE_OT_select_next(struct wmOperatorType *ot);
-void CURVE_OT_select_previous(struct wmOperatorType *ot);
-void CURVE_OT_select_more(struct wmOperatorType *ot);
-void CURVE_OT_select_less(struct wmOperatorType *ot);
-void CURVE_OT_select_random(struct wmOperatorType *ot);
-void CURVE_OT_select_nth(struct wmOperatorType *ot);
-
void CURVE_OT_switch_direction(struct wmOperatorType *ot);
void CURVE_OT_subdivide(struct wmOperatorType *ot);
void CURVE_OT_make_segment(struct wmOperatorType *ot);
@@ -124,11 +128,30 @@ void CURVE_OT_cyclic_toggle(struct wmOperatorType *ot);
void CURVE_OT_match_texture_space(struct wmOperatorType *ot);
+bool ED_curve_pick_vert(
+ struct ViewContext *vc, short sel, const int mval[2],
+ struct Nurb **r_nurb, struct BezTriple **r_bezt, struct BPoint **r_bp, short *r_handle);
+
/* 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);
bool ed_editnurb_spin(float viewmat[4][4], struct Object *obedit, const float axis[3], const float cent[3]);
+/* editcurve_select.c */
+void CURVE_OT_de_select_first(struct wmOperatorType *ot);
+void CURVE_OT_de_select_last(struct wmOperatorType *ot);
+void CURVE_OT_select_all(struct wmOperatorType *ot);
+void CURVE_OT_select_linked(struct wmOperatorType *ot);
+void CURVE_OT_select_linked_pick(struct wmOperatorType *ot);
+void CURVE_OT_select_row(struct wmOperatorType *ot);
+void CURVE_OT_select_next(struct wmOperatorType *ot);
+void CURVE_OT_select_previous(struct wmOperatorType *ot);
+void CURVE_OT_select_more(struct wmOperatorType *ot);
+void CURVE_OT_select_less(struct wmOperatorType *ot);
+void CURVE_OT_select_random(struct wmOperatorType *ot);
+void CURVE_OT_select_nth(struct wmOperatorType *ot);
+void CURVE_OT_select_similar(struct wmOperatorType *ot);
+void CURVE_OT_shortest_path_pick(struct wmOperatorType *ot);
/* editcurve_add.c */
void CURVE_OT_primitive_bezier_curve_add(struct wmOperatorType *ot);
diff --git a/source/blender/editors/curve/curve_ops.c b/source/blender/editors/curve/curve_ops.c
index f1b34182439..4828fb3ec5f 100644
--- a/source/blender/editors/curve/curve_ops.c
+++ b/source/blender/editors/curve/curve_ops.c
@@ -36,10 +36,6 @@
#include "DNA_curve_types.h"
#include "DNA_scene_types.h"
-#include "BLI_math.h"
-#include "BLI_blenlib.h"
-
-
#include "RNA_access.h"
#include "WM_api.h"
@@ -58,7 +54,6 @@ void ED_operatortypes_curve(void)
{
WM_operatortype_append(FONT_OT_text_insert);
WM_operatortype_append(FONT_OT_line_break);
- WM_operatortype_append(FONT_OT_insert_lorem);
WM_operatortype_append(FONT_OT_case_toggle);
WM_operatortype_append(FONT_OT_case_set);
@@ -133,6 +128,8 @@ void ED_operatortypes_curve(void)
WM_operatortype_append(CURVE_OT_select_less);
WM_operatortype_append(CURVE_OT_select_random);
WM_operatortype_append(CURVE_OT_select_nth);
+ WM_operatortype_append(CURVE_OT_select_similar);
+ WM_operatortype_append(CURVE_OT_shortest_path_pick);
WM_operatortype_append(CURVE_OT_switch_direction);
WM_operatortype_append(CURVE_OT_subdivide);
@@ -246,12 +243,15 @@ void ED_keymap_curve(wmKeyConfig *keyconf)
WM_keymap_add_item(keymap, "CURVE_OT_select_more", PADPLUSKEY, KM_PRESS, KM_CTRL, 0);
WM_keymap_add_item(keymap, "CURVE_OT_select_less", PADMINUS, KM_PRESS, KM_CTRL, 0);
WM_keymap_add_item(keymap, "CURVE_OT_select_linked", LKEY, KM_PRESS, KM_CTRL, 0);
+ WM_keymap_add_item(keymap, "CURVE_OT_select_similar", GKEY, KM_PRESS, KM_SHIFT, 0);
kmi = WM_keymap_add_item(keymap, "CURVE_OT_select_linked_pick", LKEY, KM_PRESS, 0, 0);
RNA_boolean_set(kmi->ptr, "deselect", false);
kmi = WM_keymap_add_item(keymap, "CURVE_OT_select_linked_pick", LKEY, KM_PRESS, KM_SHIFT, 0);
RNA_boolean_set(kmi->ptr, "deselect", true);
+ WM_keymap_add_item(keymap, "CURVE_OT_shortest_path_pick", SELECTMOUSE, KM_CLICK, KM_CTRL, 0);
+
WM_keymap_add_item(keymap, "CURVE_OT_separate", PKEY, KM_PRESS, 0, 0);
WM_keymap_add_item(keymap, "CURVE_OT_split", YKEY, KM_PRESS, 0, 0);
WM_keymap_add_item(keymap, "CURVE_OT_extrude_move", EKEY, KM_PRESS, 0, 0);
diff --git a/source/blender/editors/curve/editcurve.c b/source/blender/editors/curve/editcurve.c
index a52b2a619dc..f7dab0c0935 100644
--- a/source/blender/editors/curve/editcurve.c
+++ b/source/blender/editors/curve/editcurve.c
@@ -37,12 +37,10 @@
#include "MEM_guardedalloc.h"
#include "BLI_blenlib.h"
-#include "BLI_bitmap.h"
#include "BLI_math.h"
-#include "BLI_rand.h"
#include "BLI_ghash.h"
-#include "BLF_translation.h"
+#include "BLT_translation.h"
#include "BKE_context.h"
#include "BKE_curve.h"
@@ -85,6 +83,7 @@ typedef struct {
GHash *undoIndex;
ListBase fcurves, drivers;
int actnu;
+ int flag;
} UndoCurve;
/* Definitions needed for shape keys */
@@ -95,23 +94,7 @@ typedef struct {
Nurb *orig_nu;
} CVKeyIndex;
-typedef enum eVisible_Types {
- HIDDEN = true,
- VISIBLE = false,
-} eVisible_Types;
-
-typedef enum eEndPoint_Types {
- FIRST = true,
- LAST = false,
-} eEndPoint_Types;
-
-typedef enum eCurveElem_Types {
- CURVE_VERTEX = 0,
- CURVE_SEGMENT,
-} eCurveElem_Types;
-
void selectend_nurb(Object *obedit, enum eEndPoint_Types selfirst, bool doswap, bool selstatus);
-static void select_adjacent_cp(ListBase *editnurb, short next, const bool cont, const bool selstatus);
static void adduplicateflagNurb(Object *obedit, ListBase *newnurb, const short flag, const bool split);
static int curve_delete_segments(Object *obedit, const bool split);
@@ -124,115 +107,9 @@ ListBase *object_editcurve_get(Object *ob)
return NULL;
}
-/* ******************* SELECTION FUNCTIONS ********************* */
-
-
-/* returns 1 in case (de)selection was successful */
-static bool select_beztriple(BezTriple *bezt, bool selstatus, short flag, eVisible_Types hidden)
-{
- if ((bezt->hide == 0) || (hidden == HIDDEN)) {
- if (selstatus == SELECT) { /* selects */
- bezt->f1 |= flag;
- bezt->f2 |= flag;
- bezt->f3 |= flag;
- return true;
- }
- else { /* deselects */
- bezt->f1 &= ~flag;
- bezt->f2 &= ~flag;
- bezt->f3 &= ~flag;
- return true;
- }
- }
-
- return false;
-}
-
-/* returns 1 in case (de)selection was successful */
-static bool select_bpoint(BPoint *bp, bool selstatus, short flag, bool hidden)
-{
- if ((bp->hide == 0) || (hidden == 1)) {
- if (selstatus == SELECT) {
- bp->f1 |= flag;
- return true;
- }
- else {
- bp->f1 &= ~flag;
- return true;
- }
- }
-
- return false;
-}
-
-static bool swap_selection_beztriple(BezTriple *bezt)
-{
- if (bezt->f2 & SELECT)
- return select_beztriple(bezt, DESELECT, SELECT, VISIBLE);
- else
- return select_beztriple(bezt, SELECT, SELECT, VISIBLE);
-}
-
-static bool swap_selection_bpoint(BPoint *bp)
-{
- if (bp->f1 & SELECT)
- return select_bpoint(bp, DESELECT, SELECT, VISIBLE);
- else
- return select_bpoint(bp, SELECT, SELECT, VISIBLE);
-}
-
-int isNurbsel(Nurb *nu)
-{
- BezTriple *bezt;
- BPoint *bp;
- int a;
-
- if (nu->type == CU_BEZIER) {
- bezt = nu->bezt;
- a = nu->pntsu;
- while (a--) {
- if ( (bezt->f1 & SELECT) || (bezt->f2 & SELECT) || (bezt->f3 & SELECT) ) return 1;
- bezt++;
- }
- }
- else {
- bp = nu->bp;
- a = nu->pntsu * nu->pntsv;
- while (a--) {
- if (bp->f1 & SELECT) return 1;
- bp++;
- }
- }
- return 0;
-}
-
-static int isNurbsel_count(Curve *cu, Nurb *nu)
-{
- BezTriple *bezt;
- BPoint *bp;
- int a, sel = 0;
-
- if (nu->type == CU_BEZIER) {
- bezt = nu->bezt;
- a = nu->pntsu;
- while (a--) {
- if (BEZSELECTED_HIDDENHANDLES(cu, bezt)) sel++;
- bezt++;
- }
- }
- else {
- bp = nu->bp;
- a = nu->pntsu * nu->pntsv;
- while (a--) {
- if ( (bp->f1 & SELECT) ) sel++;
- bp++;
- }
- }
- return sel;
-}
-
/* ******************* PRINTS ********************* */
+#if 0
void printknots(Object *obedit)
{
ListBase *editnurb = object_editcurve_get(obedit);
@@ -240,7 +117,7 @@ void printknots(Object *obedit)
int a, num;
for (nu = editnurb->first; nu; nu = nu->next) {
- if (isNurbsel(nu) && nu->type == CU_NURBS) {
+ if (ED_curve_nurb_select_check(nu) && nu->type == CU_NURBS) {
if (nu->knotsu) {
num = KNOTSU(nu);
for (a = 0; a < num; a++) printf("knotu %d: %f\n", a, nu->knotsu[a]);
@@ -252,6 +129,7 @@ void printknots(Object *obedit)
}
}
}
+#endif
/* ********************* Shape keys *************** */
@@ -324,17 +202,17 @@ static void init_editNurb_keyIndex(EditNurb *editnurb, ListBase *origBase)
editnurb->keyindex = gh;
}
-static CVKeyIndex *getCVKeyIndex(EditNurb *editnurb, void *cv)
+static CVKeyIndex *getCVKeyIndex(EditNurb *editnurb, const void *cv)
{
return BLI_ghash_lookup(editnurb->keyindex, cv);
}
-static CVKeyIndex *popCVKeyIndex(EditNurb *editnurb, void *cv)
+static CVKeyIndex *popCVKeyIndex(EditNurb *editnurb, const void *cv)
{
return BLI_ghash_popkey(editnurb->keyindex, cv, NULL);
}
-static BezTriple *getKeyIndexOrig_bezt(EditNurb *editnurb, BezTriple *bezt)
+static BezTriple *getKeyIndexOrig_bezt(EditNurb *editnurb, const BezTriple *bezt)
{
CVKeyIndex *index = getCVKeyIndex(editnurb, bezt);
@@ -367,7 +245,7 @@ static int getKeyIndexOrig_keyIndex(EditNurb *editnurb, void *cv)
return index->key_index;
}
-static void keyIndex_delCV(EditNurb *editnurb, void *cv)
+static void keyIndex_delCV(EditNurb *editnurb, const void *cv)
{
if (!editnurb->keyindex) {
return;
@@ -395,7 +273,7 @@ static void keyIndex_delNurb(EditNurb *editnurb, Nurb *nu)
}
if (nu->bezt) {
- BezTriple *bezt = nu->bezt;
+ const BezTriple *bezt = nu->bezt;
a = nu->pntsu;
while (a--) {
@@ -404,7 +282,7 @@ static void keyIndex_delNurb(EditNurb *editnurb, Nurb *nu)
}
}
else {
- BPoint *bp = nu->bp;
+ const BPoint *bp = nu->bp;
a = nu->pntsu * nu->pntsv;
while (a--) {
@@ -642,25 +520,20 @@ static void keyData_switchDirectionNurb(Curve *cu, Nurb *nu)
static GHash *dupli_keyIndexHash(GHash *keyindex)
{
GHash *gh;
- GHashIterator *hashIter;
+ GHashIterator gh_iter;
gh = BLI_ghash_ptr_new_ex("dupli_keyIndex gh", BLI_ghash_size(keyindex));
- for (hashIter = BLI_ghashIterator_new(keyindex);
- BLI_ghashIterator_done(hashIter) == false;
- BLI_ghashIterator_step(hashIter))
- {
- void *cv = BLI_ghashIterator_getKey(hashIter);
- CVKeyIndex *index = BLI_ghashIterator_getValue(hashIter);
- CVKeyIndex *newIndex = MEM_callocN(sizeof(CVKeyIndex), "dupli_keyIndexHash index");
+ GHASH_ITER (gh_iter, keyindex) {
+ void *cv = BLI_ghashIterator_getKey(&gh_iter);
+ CVKeyIndex *index = BLI_ghashIterator_getValue(&gh_iter);
+ CVKeyIndex *newIndex = MEM_mallocN(sizeof(CVKeyIndex), "dupli_keyIndexHash index");
memcpy(newIndex, index, sizeof(CVKeyIndex));
BLI_ghash_insert(gh, cv, newIndex);
}
- BLI_ghashIterator_free(hashIter);
-
return gh;
}
@@ -766,16 +639,7 @@ static void calc_shapeKeys(Object *obedit)
/* editing the base key should update others */
if (cu->key->type == KEY_RELATIVE) {
- int act_is_basis = 0;
- /* find if this key is a basis for any others */
- for (currkey = cu->key->block.first; currkey; currkey = currkey->next) {
- if (editnurb->shapenr - 1 == currkey->relative) {
- act_is_basis = 1;
- break;
- }
- }
-
- if (act_is_basis) { /* active key is a base */
+ if (BKE_keyblock_is_basis(cu->key, editnurb->shapenr - 1)) { /* active key is a base */
int totvec = 0;
/* Calculate needed memory to store offset */
@@ -1007,7 +871,7 @@ static void fcurve_path_rename(AnimData *adt, const char *orig_rna_path, char *r
for (fcu = orig_curves->first; fcu; fcu = nextfcu) {
nextfcu = fcu->next;
- if (!strncmp(fcu->rna_path, orig_rna_path, len)) {
+ if (STREQLEN(fcu->rna_path, orig_rna_path, len)) {
char *spath, *suffix = fcu->rna_path + len;
nfcu = copy_fcurve(fcu);
spath = nfcu->rna_path;
@@ -1110,10 +974,10 @@ static void curve_rename_fcurves(Curve *cu, ListBase *orig_curves)
for (fcu = orig_curves->first; fcu; fcu = next) {
next = fcu->next;
- if (!strncmp(fcu->rna_path, "splines", 7)) {
+ if (STREQLEN(fcu->rna_path, "splines", 7)) {
const char *ch = strchr(fcu->rna_path, '.');
- if (ch && (!strncmp(ch, ".bezier_points", 14) || !strncmp(ch, ".points", 7)))
+ if (ch && (STREQLEN(ch, ".bezier_points", 14) || STREQLEN(ch, ".points", 7)))
fcurve_remove(adt, orig_curves, fcu);
}
}
@@ -1137,7 +1001,7 @@ static void curve_rename_fcurves(Curve *cu, ListBase *orig_curves)
for (fcu = orig_curves->first; fcu; fcu = next) {
next = fcu->next;
- if (!strncmp(fcu->rna_path, "splines", 7)) fcurve_remove(adt, orig_curves, fcu);
+ if (STREQLEN(fcu->rna_path, "splines", 7)) fcurve_remove(adt, orig_curves, fcu);
else BLI_addtail(&curves, fcu);
}
@@ -1199,7 +1063,7 @@ static int *initialize_index_map(Object *obedit, int *r_old_totvert)
while (a--) {
keyIndex = getCVKeyIndex(editnurb, bezt);
- if (keyIndex) {
+ if (keyIndex && keyIndex->vertex_index + 2 < old_totvert) {
if (keyIndex->switched) {
old_to_new_map[keyIndex->vertex_index] = vertex_index + 2;
old_to_new_map[keyIndex->vertex_index + 1] = vertex_index + 1;
@@ -1358,7 +1222,7 @@ void make_editNurb(Object *obedit)
if (actkey) {
// XXX strcpy(G.editModeTitleExtra, "(Key) ");
undo_editmode_clear();
- BKE_key_convert_to_curve(actkey, cu, &cu->nurb);
+ BKE_keyblock_convert_to_curve(actkey, cu, &cu->nurb);
}
if (editnurb) {
@@ -1395,87 +1259,6 @@ void free_editNurb(Object *obedit)
BKE_curve_editNurb_free(cu);
}
-void ED_curve_deselect_all(EditNurb *editnurb)
-{
- Nurb *nu;
- int a;
-
- for (nu = editnurb->nurbs.first; nu; nu = nu->next) {
- if (nu->bezt) {
- BezTriple *bezt;
- for (bezt = nu->bezt, a = 0; a < nu->pntsu; a++, bezt++) {
- bezt->f1 &= ~SELECT;
- bezt->f2 &= ~SELECT;
- bezt->f3 &= ~SELECT;
- }
- }
- else if (nu->bp) {
- BPoint *bp;
- for (bp = nu->bp, a = 0; a < nu->pntsu * nu->pntsv; a++, bp++) {
- bp->f1 &= ~SELECT;
- }
- }
- }
-}
-
-void ED_curve_select_all(EditNurb *editnurb)
-{
- Nurb *nu;
- int a;
- for (nu = editnurb->nurbs.first; nu; nu = nu->next) {
- if (nu->bezt) {
- BezTriple *bezt;
- for (bezt = nu->bezt, a = 0; a < nu->pntsu; a++, bezt++) {
- if (bezt->hide == 0) {
- bezt->f1 |= SELECT;
- bezt->f2 |= SELECT;
- bezt->f3 |= SELECT;
- }
- }
- }
- else if (nu->bp) {
- BPoint *bp;
- for (bp = nu->bp, a = 0; a < nu->pntsu * nu->pntsv; a++, bp++) {
- if (bp->hide == 0)
- bp->f1 |= SELECT;
- }
- }
- }
-}
-
-void ED_curve_select_swap(EditNurb *editnurb, bool hide_handles)
-{
- Nurb *nu;
- BPoint *bp;
- BezTriple *bezt;
- int a;
-
- for (nu = editnurb->nurbs.first; nu; nu = nu->next) {
- if (nu->type == CU_BEZIER) {
- bezt = nu->bezt;
- a = nu->pntsu;
- while (a--) {
- if (bezt->hide == 0) {
- bezt->f2 ^= SELECT; /* always do the center point */
- if (!hide_handles) {
- bezt->f1 ^= SELECT;
- bezt->f3 ^= SELECT;
- }
- }
- bezt++;
- }
- }
- else {
- bp = nu->bp;
- a = nu->pntsu * nu->pntsv;
- while (a--) {
- swap_selection_bpoint(bp);
- bp++;
- }
- }
- }
-}
-
/******************** separate operator ***********************/
static int separate_exec(bContext *C, wmOperator *op)
@@ -1549,6 +1332,7 @@ void CURVE_OT_separate(wmOperatorType *ot)
ot->description = "Separate selected points from connected unselected points into a new object";
/* api callbacks */
+ ot->invoke = WM_operator_confirm;
ot->exec = separate_exec;
ot->poll = ED_operator_editsurfcurve;
@@ -1893,7 +1677,7 @@ static void ed_curve_delete_selected(Object *obedit)
a = nu->pntsu;
if (a) {
while (a) {
- if (BEZSELECTED_HIDDENHANDLES(cu, bezt)) {
+ if (BEZT_ISSEL_ANY_HIDDENHANDLES(cu, bezt)) {
/* pass */
}
else {
@@ -1955,7 +1739,7 @@ static void ed_curve_delete_selected(Object *obedit)
if (nu->type == CU_BEZIER) {
bezt = nu->bezt;
for (a = 0; a < nu->pntsu; a++) {
- if (BEZSELECTED_HIDDENHANDLES(cu, bezt)) {
+ if (BEZT_ISSEL_ANY_HIDDENHANDLES(cu, bezt)) {
memmove(bezt, bezt + 1, (nu->pntsu - a - 1) * sizeof(BezTriple));
keyIndex_delBezt(editnurb, bezt);
keyIndex_updateBezt(editnurb, bezt + 1, bezt, nu->pntsu - a - 1);
@@ -2015,7 +1799,7 @@ static void ed_curve_delete_selected(Object *obedit)
}
/* only for OB_SURF */
-bool ed_editnurb_extrude_flag(EditNurb *editnurb, short flag)
+bool ed_editnurb_extrude_flag(EditNurb *editnurb, const short flag)
{
Nurb *nu;
BPoint *bp, *bpn, *newbp;
@@ -2244,7 +2028,7 @@ static void adduplicateflagNurb(Object *obedit, ListBase *newnurb,
}
}
else {
- if (isNurbsel(nu)) {
+ if (ED_curve_nurb_select_check(cu, nu)) {
/* a rectangular area in nurb has to be selected and if splitting must be in U or V direction */
usel = MEM_callocN(nu->pntsu, "adduplicateN3");
bp = nu->bp;
@@ -2376,7 +2160,6 @@ static void adduplicateflagNurb(Object *obedit, ListBase *newnurb,
}
else {
/* knots done after duplicate as pntsu may change */
- nu->knotsu = nu->knotsv = NULL;
BKE_nurb_order_clamp_u(nu);
BKE_nurb_knot_calc_u(nu);
@@ -2404,7 +2187,7 @@ static int switch_direction_exec(bContext *C, wmOperator *UNUSED(op))
int i;
for (nu = editnurb->nurbs.first, i = 0; nu; nu = nu->next, i++) {
- if (isNurbsel(nu)) {
+ if (ED_curve_nurb_select_check(cu, nu)) {
BKE_nurb_direction_switch(nu);
keyData_switchDirectionNurb(cu, nu);
if ((i == cu->actnu) && (cu->actvert != CU_ACT_NONE)) {
@@ -2538,7 +2321,7 @@ void CURVE_OT_radius_set(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
/* properties */
- RNA_def_float(ot->srna, "radius", 1.0f, 0.0f, FLT_MAX, "Radius", "", 0.0001f, 10.0f);
+ RNA_def_float(ot->srna, "radius", 1.0f, 0.0f, OBJECT_ADD_SIZE_MAXF, "Radius", "", 0.0001f, 10.0f);
}
/********************* smooth operator ********************/
@@ -2711,7 +2494,7 @@ static void curve_smooth_value(ListBase *editnurb,
for (nu = editnurb->first; nu; nu = nu->next) {
if (nu->bezt) {
-#define BEZT_VALUE(bezt) (*((float *)((char *)bezt + bezt_offsetof)))
+#define BEZT_VALUE(bezt) (*((float *)((char *)(bezt) + bezt_offsetof)))
for (last_sel = 0; last_sel < nu->pntsu; last_sel++) {
/* loop over selection segments of a curve, smooth each */
@@ -2780,7 +2563,7 @@ static void curve_smooth_value(ListBase *editnurb,
#undef BEZT_VALUE
}
else if (nu->bp) {
-#define BP_VALUE(bp) (*((float *)((char *)bp + bp_offset)))
+#define BP_VALUE(bp) (*((float *)((char *)(bp) + bp_offset)))
/* Same as above, keep these the same! */
for (last_sel = 0; last_sel < nu->pntsu; last_sel++) {
@@ -2936,274 +2719,6 @@ void CURVE_OT_smooth_tilt(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-/***************** selection utility *************************/
-
-/* next == 1 -> select next */
-/* next == -1 -> select previous */
-/* cont == 1 -> select continuously */
-/* selstatus, inverts behavior */
-static void select_adjacent_cp(ListBase *editnurb, short next,
- const bool cont, const bool selstatus)
-{
- Nurb *nu;
- BezTriple *bezt;
- BPoint *bp;
- int a;
- bool lastsel = false;
-
- if (next == 0) return;
-
- for (nu = editnurb->first; nu; nu = nu->next) {
- lastsel = false;
- if (nu->type == CU_BEZIER) {
- a = nu->pntsu;
- bezt = nu->bezt;
- if (next < 0) bezt = &nu->bezt[a - 1];
- while (a--) {
- if (a - abs(next) < 0) break;
- if ((lastsel == 0) && (bezt->hide == 0) && ((bezt->f2 & SELECT) || (selstatus == DESELECT))) {
- bezt += next;
- if (!(bezt->f2 & SELECT) || (selstatus == DESELECT)) {
- short sel = select_beztriple(bezt, selstatus, SELECT, VISIBLE);
- if ((sel == 1) && (cont == 0)) lastsel = true;
- }
- }
- else {
- bezt += next;
- lastsel = false;
- }
- /* move around in zigzag way so that we go through each */
- bezt -= (next - next / abs(next));
- }
- }
- else {
- a = nu->pntsu * nu->pntsv;
- bp = nu->bp;
- if (next < 0) bp = &nu->bp[a - 1];
- while (a--) {
- if (a - abs(next) < 0) break;
- if ((lastsel == 0) && (bp->hide == 0) && ((bp->f1 & SELECT) || (selstatus == DESELECT))) {
- bp += next;
- if (!(bp->f1 & SELECT) || (selstatus == DESELECT)) {
- short sel = select_bpoint(bp, selstatus, SELECT, VISIBLE);
- if ((sel == 1) && (cont == 0)) lastsel = true;
- }
- }
- else {
- bp += next;
- lastsel = false;
- }
- /* move around in zigzag way so that we go through each */
- bp -= (next - next / abs(next));
- }
- }
- }
-}
-
-/**************** select start/end operators **************/
-
-/* (de)selects first or last of visible part of each Nurb depending on selFirst
- * selFirst: defines the end of which to select
- * doswap: defines if selection state of each first/last control point is swapped
- * selstatus: selection status in case doswap is false
- */
-void selectend_nurb(Object *obedit, eEndPoint_Types selfirst, bool doswap, bool selstatus)
-{
- ListBase *editnurb = object_editcurve_get(obedit);
- Nurb *nu;
- BPoint *bp;
- BezTriple *bezt;
- Curve *cu;
- int a;
-
- if (obedit == NULL) return;
-
- cu = (Curve *)obedit->data;
- cu->actvert = CU_ACT_NONE;
-
- for (nu = editnurb->first; nu; nu = nu->next) {
- if (nu->type == CU_BEZIER) {
- a = nu->pntsu;
-
- /* which point? */
- if (selfirst == LAST) { /* select last */
- bezt = &nu->bezt[a - 1];
- }
- else { /* select first */
- bezt = nu->bezt;
- }
-
- while (a--) {
- bool sel;
- if (doswap) sel = swap_selection_beztriple(bezt);
- else sel = select_beztriple(bezt, selstatus, SELECT, VISIBLE);
-
- if (sel == true) break;
- }
- }
- else {
- a = nu->pntsu * nu->pntsv;
-
- /* which point? */
- if (selfirst == LAST) { /* select last */
- bp = &nu->bp[a - 1];
- }
- else { /* select first */
- bp = nu->bp;
- }
-
- while (a--) {
- if (bp->hide == 0) {
- bool sel;
- if (doswap) sel = swap_selection_bpoint(bp);
- else sel = select_bpoint(bp, selstatus, SELECT, VISIBLE);
-
- if (sel == true) break;
- }
- }
- }
- }
-}
-
-static int de_select_first_exec(bContext *C, wmOperator *UNUSED(op))
-{
- Object *obedit = CTX_data_edit_object(C);
-
- selectend_nurb(obedit, FIRST, true, DESELECT);
- WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
- BKE_curve_nurb_vert_active_validate(obedit->data);
-
- return OPERATOR_FINISHED;
-}
-
-void CURVE_OT_de_select_first(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "(De)select First";
- ot->idname = "CURVE_OT_de_select_first";
- ot->description = "(De)select first of visible part of each NURBS";
-
- /* api cfirstbacks */
- ot->exec = de_select_first_exec;
- ot->poll = ED_operator_editcurve;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-}
-
-static int de_select_last_exec(bContext *C, wmOperator *UNUSED(op))
-{
- Object *obedit = CTX_data_edit_object(C);
-
- selectend_nurb(obedit, LAST, true, DESELECT);
- WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
- BKE_curve_nurb_vert_active_validate(obedit->data);
-
- return OPERATOR_FINISHED;
-}
-
-void CURVE_OT_de_select_last(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "(De)select Last";
- ot->idname = "CURVE_OT_de_select_last";
- ot->description = "(De)select last of visible part of each NURBS";
-
- /* api clastbacks */
- ot->exec = de_select_last_exec;
- ot->poll = ED_operator_editcurve;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-}
-
-/******************* de select all operator ***************/
-
-static bool nurb_has_selected_cps(ListBase *editnurb)
-{
- Nurb *nu;
- BezTriple *bezt;
- BPoint *bp;
- int a;
-
- for (nu = editnurb->first; nu; nu = nu->next) {
- if (nu->type == CU_BEZIER) {
- a = nu->pntsu;
- bezt = nu->bezt;
- while (a--) {
- if (bezt->hide == 0) {
- if ((bezt->f1 & SELECT) ||
- (bezt->f2 & SELECT) ||
- (bezt->f3 & SELECT))
- {
- return 1;
- }
- }
- bezt++;
- }
- }
- else {
- a = nu->pntsu * nu->pntsv;
- bp = nu->bp;
- while (a--) {
- if ((bp->hide == 0) && (bp->f1 & SELECT)) return 1;
- bp++;
- }
- }
- }
-
- return 0;
-}
-
-static int de_select_all_exec(bContext *C, wmOperator *op)
-{
- Object *obedit = CTX_data_edit_object(C);
- Curve *cu = obedit->data;
- ListBase *editnurb = object_editcurve_get(obedit);
- int action = RNA_enum_get(op->ptr, "action");
-
- if (action == SEL_TOGGLE) {
- action = SEL_SELECT;
- if (nurb_has_selected_cps(editnurb))
- action = SEL_DESELECT;
- }
-
- switch (action) {
- case SEL_SELECT:
- ED_curve_select_all(cu->editnurb);
- break;
- case SEL_DESELECT:
- ED_curve_deselect_all(cu->editnurb);
- break;
- case SEL_INVERT:
- ED_curve_select_swap(cu->editnurb, (cu->drawflag & CU_HIDE_HANDLES) != 0);
- break;
- }
-
- WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
- BKE_curve_nurb_vert_active_validate(cu);
-
- return OPERATOR_FINISHED;
-}
-
-void CURVE_OT_select_all(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "(De)select All";
- ot->idname = "CURVE_OT_select_all";
- ot->description = "(De)select all control points";
-
- /* api callbacks */
- ot->exec = de_select_all_exec;
- ot->poll = ED_operator_editsurfcurve;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- WM_operator_properties_select_all(ot);
-}
-
/********************** hide operator *********************/
static int hide_exec(bContext *C, wmOperator *op)
@@ -3223,11 +2738,11 @@ static int hide_exec(bContext *C, wmOperator *op)
a = nu->pntsu;
sel = 0;
while (a--) {
- if (invert == 0 && BEZSELECTED_HIDDENHANDLES(cu, bezt)) {
+ if (invert == 0 && BEZT_ISSEL_ANY_HIDDENHANDLES(cu, bezt)) {
select_beztriple(bezt, DESELECT, SELECT, HIDDEN);
bezt->hide = 1;
}
- else if (invert && !BEZSELECTED_HIDDENHANDLES(cu, bezt)) {
+ else if (invert && !BEZT_ISSEL_ANY_HIDDENHANDLES(cu, bezt)) {
select_beztriple(bezt, DESELECT, SELECT, HIDDEN);
bezt->hide = 1;
}
@@ -3377,7 +2892,7 @@ static void subdividenurb(Object *obedit, int number_cuts)
break;
}
- if (BEZSELECTED_HIDDENHANDLES(cu, bezt) && BEZSELECTED_HIDDENHANDLES(cu, nextbezt)) {
+ if (BEZT_ISSEL_ANY_HIDDENHANDLES(cu, bezt) && BEZT_ISSEL_ANY_HIDDENHANDLES(cu, nextbezt)) {
amount += number_cuts;
}
bezt++;
@@ -3399,7 +2914,7 @@ static void subdividenurb(Object *obedit, int number_cuts)
break;
}
- if (BEZSELECTED_HIDDENHANDLES(cu, bezt) && BEZSELECTED_HIDDENHANDLES(cu, nextbezt)) {
+ if (BEZT_ISSEL_ANY_HIDDENHANDLES(cu, bezt) && BEZT_ISSEL_ANY_HIDDENHANDLES(cu, nextbezt)) {
float prevvec[3][3];
memcpy(prevvec, bezt->vec, sizeof(float) * 9);
@@ -3758,14 +3273,14 @@ void CURVE_OT_subdivide(wmOperatorType *ot)
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- prop = RNA_def_int(ot->srna, "number_cuts", 1, 1, INT_MAX, "Number of cuts", "", 1, 10);
+ prop = RNA_def_int(ot->srna, "number_cuts", 1, 1, 1000, "Number of cuts", "", 1, 10);
/* avoid re-using last var because it can cause _very_ high poly meshes and annoy users (or worse crash) */
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
/******************** find nearest ************************/
-static void findnearestNurbvert__doClosest(void *userData, Nurb *nu, BPoint *bp, BezTriple *bezt, int beztindex, const float screen_co[2])
+static void ED_curve_pick_vert__doClosest(void *userData, Nurb *nu, BPoint *bp, BezTriple *bezt, int beztindex, const float screen_co[2])
{
struct { BPoint *bp; BezTriple *bezt; Nurb *nurb; float dist; int hpoint, select; float mval_fl[2]; } *data = userData;
@@ -3801,7 +3316,9 @@ static void findnearestNurbvert__doClosest(void *userData, Nurb *nu, BPoint *bp,
}
}
-static short findnearestNurbvert(ViewContext *vc, short sel, const int mval[2], Nurb **nurb, BezTriple **bezt, BPoint **bp)
+bool ED_curve_pick_vert(
+ ViewContext *vc, short sel, const int mval[2],
+ Nurb **r_nurb, BezTriple **r_bezt, BPoint **r_bp, short *r_handle)
{
/* (sel == 1): selected gets a disadvantage */
/* in nurb and bezt or bp the nearest is written */
@@ -3815,46 +3332,54 @@ static short findnearestNurbvert(ViewContext *vc, short sel, const int mval[2],
data.mval_fl[1] = mval[1];
ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d);
- nurbs_foreachScreenVert(vc, findnearestNurbvert__doClosest, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
+ nurbs_foreachScreenVert(vc, ED_curve_pick_vert__doClosest, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
- *nurb = data.nurb;
- *bezt = data.bezt;
- *bp = data.bp;
+ *r_nurb = data.nurb;
+ *r_bezt = data.bezt;
+ *r_bp = data.bp;
+
+ if (r_handle) {
+ *r_handle = data.hpoint;
+ }
- return data.hpoint;
+ return (data.bezt || data.bp);
}
-static void findselectedNurbvert(ListBase *editnurb, Nurb **nu, BezTriple **bezt, BPoint **bp)
+static void findselectedNurbvert(
+ Curve *cu,
+ Nurb **r_nu, BezTriple **r_bezt, BPoint **r_bp)
{
/* in nu and (bezt or bp) selected are written if there's 1 sel. */
/* if more points selected in 1 spline: return only nu, bezt and bp are 0 */
+ ListBase *editnurb = &cu->editnurb->nurbs;
Nurb *nu1;
BezTriple *bezt1;
BPoint *bp1;
int a;
- *nu = NULL;
- *bezt = NULL;
- *bp = NULL;
+ *r_nu = NULL;
+ *r_bezt = NULL;
+ *r_bp = NULL;
+
for (nu1 = editnurb->first; nu1; nu1 = nu1->next) {
if (nu1->type == CU_BEZIER) {
bezt1 = nu1->bezt;
a = nu1->pntsu;
while (a--) {
- if ((bezt1->f1 & SELECT) || (bezt1->f2 & SELECT) || (bezt1->f3 & SELECT)) {
- if (*nu != NULL && *nu != nu1) {
- *nu = NULL;
- *bp = NULL;
- *bezt = NULL;
+ if (BEZT_ISSEL_ANY_HIDDENHANDLES(cu, bezt1)) {
+ if (*r_nu != NULL && *r_nu != nu1) {
+ *r_nu = NULL;
+ *r_bp = NULL;
+ *r_bezt = NULL;
return;
}
- else if (*bezt || *bp) {
- *bp = NULL;
- *bezt = NULL;
+ else if (*r_bezt || *r_bp) {
+ *r_bp = NULL;
+ *r_bezt = NULL;
}
else {
- *bezt = bezt1;
- *nu = nu1;
+ *r_bezt = bezt1;
+ *r_nu = nu1;
}
}
bezt1++;
@@ -3865,19 +3390,19 @@ static void findselectedNurbvert(ListBase *editnurb, Nurb **nu, BezTriple **bezt
a = nu1->pntsu * nu1->pntsv;
while (a--) {
if (bp1->f1 & SELECT) {
- if (*nu != NULL && *nu != nu1) {
- *bp = NULL;
- *bezt = NULL;
- *nu = NULL;
+ if (*r_nu != NULL && *r_nu != nu1) {
+ *r_bp = NULL;
+ *r_bezt = NULL;
+ *r_nu = NULL;
return;
}
- else if (*bezt || *bp) {
- *bp = NULL;
- *bezt = NULL;
+ else if (*r_bezt || *r_bp) {
+ *r_bp = NULL;
+ *r_bezt = NULL;
}
else {
- *bp = bp1;
- *nu = nu1;
+ *r_bp = bp1;
+ *r_nu = nu1;
}
}
bp1++;
@@ -3904,7 +3429,7 @@ static int set_spline_type_exec(bContext *C, wmOperator *op)
}
for (nu = editnurb->first; nu; nu = nu->next) {
- if (isNurbsel(nu)) {
+ if (ED_curve_nurb_select_check(obedit->data, nu)) {
const int pntsu_prev = nu->pntsu;
if (BKE_nurb_type_convert(nu, type, use_handles)) {
changed = true;
@@ -4066,15 +3591,17 @@ static void switchdirection_knots(float *base, int tot)
fp1++;
fp2--;
}
+
/* and make in increasing order again */
- a = tot;
+ a = tot - 1;
fp1 = base;
- fp2 = tempf = MEM_mallocN(sizeof(float) * a, "switchdirect");
+ fp2 = tempf = MEM_mallocN(sizeof(float) * tot, "switchdirect");
while (a--) {
fp2[0] = fabsf(fp1[1] - fp1[0]);
fp1++;
fp2++;
}
+ fp2[0] = 0.0f;
a = tot - 1;
fp1 = base;
@@ -4139,7 +3666,7 @@ typedef struct NurbSort {
static ListBase nsortbase = {NULL, NULL};
/* static NurbSort *nusmain; */ /* this var seems to go unused... at least in this file */
-static void make_selection_list_nurb(ListBase *editnurb)
+static void make_selection_list_nurb(Curve *cu, ListBase *editnurb)
{
ListBase nbase = {NULL, NULL};
NurbSort *nus, *nustest, *headdo, *taildo;
@@ -4149,7 +3676,7 @@ static void make_selection_list_nurb(ListBase *editnurb)
int a;
for (nu = editnurb->first; nu; nu = nu->next) {
- if (isNurbsel(nu)) {
+ if (ED_curve_nurb_select_check(cu, nu)) {
nus = (NurbSort *)MEM_callocN(sizeof(NurbSort), "sort");
BLI_addhead(&nbase, nus);
@@ -4353,7 +3880,7 @@ static int merge_nurb(bContext *C, wmOperator *op)
NurbSort *nus1, *nus2;
bool ok = true;
- make_selection_list_nurb(editnurb);
+ make_selection_list_nurb(cu, editnurb);
if (nsortbase.first == nsortbase.last) {
BLI_freelistN(&nsortbase);
@@ -4428,11 +3955,17 @@ static int make_segment_exec(bContext *C, wmOperator *op)
else nu = NULL;
while (nu) {
- if (isNurbsel(nu)) {
-
- if (nu->pntsu > 1 && nu->pntsv > 1) break;
- if (isNurbsel_count(cu, nu) > 1) break;
- if (isNurbsel_count(cu, nu) == 1) {
+ const int nu_select_num = ED_curve_nurb_select_count(cu, nu);
+ if (nu_select_num) {
+
+ if (nu->pntsu > 1 && nu->pntsv > 1) {
+ break;
+ }
+
+ if (nu_select_num > 1) {
+ break;
+ }
+ else {
/* only 1 selected, not first or last, a little complex, but intuitive */
if (nu->pntsv == 1) {
if ((nu->bp->f1 & SELECT) || (nu->bp[nu->pntsu - 1].f1 & SELECT)) {
@@ -4457,7 +3990,7 @@ static int make_segment_exec(bContext *C, wmOperator *op)
if ((nu->flagu & CU_NURB_CYCLIC) == 0) { /* not cyclic */
if (nu->type == CU_BEZIER) {
- if (BEZSELECTED_HIDDENHANDLES(cu, &(nu->bezt[nu->pntsu - 1]))) {
+ if (BEZT_ISSEL_ANY_HIDDENHANDLES(cu, &(nu->bezt[nu->pntsu - 1]))) {
/* Last point is selected, preferred for nu2 */
if (nu2 == NULL) {
nu2 = nu;
@@ -4468,13 +4001,13 @@ static int make_segment_exec(bContext *C, wmOperator *op)
/* Just in case both of first/last CV are selected check
* whether we really need to switch the direction.
*/
- if (!BEZSELECTED_HIDDENHANDLES(cu, nu1->bezt)) {
+ if (!BEZT_ISSEL_ANY_HIDDENHANDLES(cu, nu1->bezt)) {
BKE_nurb_direction_switch(nu1);
keyData_switchDirectionNurb(cu, nu1);
}
}
}
- else if (BEZSELECTED_HIDDENHANDLES(cu, nu->bezt)) {
+ else if (BEZT_ISSEL_ANY_HIDDENHANDLES(cu, nu->bezt)) {
/* First point is selected, preferred for nu1 */
if (nu1 == NULL) {
nu1 = nu;
@@ -4485,7 +4018,7 @@ static int make_segment_exec(bContext *C, wmOperator *op)
/* Just in case both of first/last CV are selected check
* whether we really need to switch the direction.
*/
- if (!BEZSELECTED_HIDDENHANDLES(cu, &(nu->bezt[nu2->pntsu - 1]))) {
+ if (!BEZT_ISSEL_ANY_HIDDENHANDLES(cu, &(nu->bezt[nu2->pntsu - 1]))) {
BKE_nurb_direction_switch(nu2);
keyData_switchDirectionNurb(cu, nu2);
}
@@ -4584,8 +4117,8 @@ static int make_segment_exec(bContext *C, wmOperator *op)
}
if (!(nu1->flagu & CU_NURB_CYCLIC) && nu1->pntsu > 1) {
- if (nu1->type == CU_BEZIER && BEZSELECTED_HIDDENHANDLES(cu, nu1->bezt) &&
- BEZSELECTED_HIDDENHANDLES(cu, &nu1->bezt[nu1->pntsu - 1]))
+ if (nu1->type == CU_BEZIER && BEZT_ISSEL_ANY_HIDDENHANDLES(cu, nu1->bezt) &&
+ BEZT_ISSEL_ANY_HIDDENHANDLES(cu, &nu1->bezt[nu1->pntsu - 1]))
{
nu1->flagu |= CU_NURB_CYCLIC;
BKE_nurb_handles_calc(nu1);
@@ -4648,25 +4181,22 @@ bool mouse_nurb(bContext *C, const int mval[2], bool extend, bool deselect, bool
location[0] = mval[0];
location[1] = mval[1];
- hand = findnearestNurbvert(&vc, 1, location, &nu, &bezt, &bp);
- if (bezt || bp) {
+ if (ED_curve_pick_vert(&vc, 1, location, &nu, &bezt, &bp, &hand)) {
if (extend) {
if (bezt) {
if (hand == 1) {
select_beztriple(bezt, SELECT, SELECT, HIDDEN);
- BKE_curve_nurb_vert_active_set(cu, nu, bezt);
}
else {
if (hand == 0) bezt->f1 |= SELECT;
else bezt->f3 |= SELECT;
-
- cu->actvert = CU_ACT_NONE;
}
+ BKE_curve_nurb_vert_active_set(cu, nu, bezt);
}
else {
- BKE_curve_nurb_vert_active_set(cu, nu, bp);
select_bpoint(bp, SELECT, SELECT, HIDDEN);
+ BKE_curve_nurb_vert_active_set(cu, nu, bp);
}
}
else if (deselect) {
@@ -4724,18 +4254,16 @@ bool mouse_nurb(bContext *C, const int mval[2], bool extend, bool deselect, bool
if (hand == 1) {
select_beztriple(bezt, SELECT, SELECT, HIDDEN);
- BKE_curve_nurb_vert_active_set(cu, nu, bezt);
}
else {
if (hand == 0) bezt->f1 |= SELECT;
else bezt->f3 |= SELECT;
-
- cu->actvert = CU_ACT_NONE;
}
+ BKE_curve_nurb_vert_active_set(cu, nu, bezt);
}
else {
- BKE_curve_nurb_vert_active_set(cu, nu, bp);
select_bpoint(bp, SELECT, SELECT, HIDDEN);
+ BKE_curve_nurb_vert_active_set(cu, nu, bp);
}
}
@@ -4799,7 +4327,7 @@ bool ed_editnurb_spin(float viewmat[4][4], Object *obedit, const float axis[3],
ok = true;
for (a = 0; a < 7; a++) {
- ok = ed_editnurb_extrude_flag(cu->editnurb, 1);
+ ok = ed_editnurb_extrude_flag(cu->editnurb, SELECT);
if (ok == false)
return changed;
@@ -4820,7 +4348,7 @@ bool ed_editnurb_spin(float viewmat[4][4], Object *obedit, const float axis[3],
if (ok) {
for (nu = editnurb->first; nu; nu = nu->next) {
- if (isNurbsel(nu)) {
+ if (ED_curve_nurb_select_check(cu, nu)) {
nu->orderv = 4;
nu->flagv |= CU_NURB_CYCLIC;
BKE_nurb_knot_calc_v(nu);
@@ -4893,289 +4421,414 @@ void CURVE_OT_spin(wmOperatorType *ot)
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- RNA_def_float_vector_xyz(ot->srna, "center", 3, NULL, -FLT_MAX, FLT_MAX, "Center", "Center in global view space", -FLT_MAX, FLT_MAX);
- RNA_def_float_vector(ot->srna, "axis", 3, NULL, -FLT_MAX, FLT_MAX, "Axis", "Axis in global view space", -1.0f, 1.0f);
+ RNA_def_float_vector_xyz(ot->srna, "center", 3, NULL, -OBJECT_ADD_SIZE_MAXF, OBJECT_ADD_SIZE_MAXF,
+ "Center", "Center in global view space", -1000.0f, 1000.0f);
+ RNA_def_float_vector(ot->srna, "axis", 3, NULL, -1.0f, 1.0f, "Axis", "Axis in global view space", -1.0f, 1.0f);
}
-/***************** add vertex operator **********************/
+/***************** extrude vertex operator **********************/
-static int addvert_Nurb(bContext *C, short mode, float location[3])
+static bool ed_editcurve_extrude(Curve *cu, EditNurb *editnurb)
{
- Object *obedit = CTX_data_edit_object(C);
- Curve *cu = (Curve *)obedit->data;
- EditNurb *editnurb = cu->editnurb;
- Nurb *nu, *newnu = NULL;
- BezTriple *bezt, *newbezt = NULL;
- BPoint *bp, *newbp = NULL;
- float imat[4][4], temp[3];
- bool ok = false;
- BezTriple *bezt_recalc[3] = {NULL};
+ Nurb *nu = NULL;
+ Nurb *nu_last = NULL;
- invert_m4_m4(imat, obedit->obmat);
+ bool changed = false;
- findselectedNurbvert(&editnurb->nurbs, &nu, &bezt, &bp);
-
- if ((nu == NULL) || (nu->type == CU_BEZIER && bezt == NULL) || (nu->type != CU_BEZIER && bp == NULL)) {
- if (mode != 'e') {
- if (cu->actnu != CU_ACT_NONE)
- nu = BLI_findlink(&editnurb->nurbs, cu->actnu);
-
- if (!nu || nu->type == CU_BEZIER) {
- newbezt = (BezTriple *)MEM_callocN(sizeof(BezTriple), "addvert_Nurb");
- newbezt->radius = 1;
- newbezt->alfa = 0;
- BEZ_SEL(newbezt);
- newbezt->h2 = newbezt->h1 = HD_AUTO;
-
- newnu = (Nurb *)MEM_callocN(sizeof(Nurb), "addvert_Nurb newnu");
- if (!nu) {
- /* no selected segment -- create new one which is BEZIER type
- * type couldn't be determined from Curve bt could be changed
- * in the future, so shouldn't make much headache */
- newnu->type = CU_BEZIER;
- newnu->resolu = cu->resolu;
- newnu->flag |= CU_SMOOTH;
- }
- else {
- memcpy(newnu, nu, sizeof(Nurb));
- }
+ Nurb *cu_actnu;
+ union {
+ BezTriple *bezt;
+ BPoint *bp;
+ void *p;
+ } cu_actvert;
- BLI_addtail(&editnurb->nurbs, newnu);
- newnu->bezt = newbezt;
- newnu->pntsu = 1;
+ if (BLI_listbase_is_empty(&editnurb->nurbs)) {
+ return changed;
+ }
- temp[0] = 1;
- temp[1] = 0;
- temp[2] = 0;
+ BKE_curve_nurb_vert_active_get(cu, &cu_actnu, &cu_actvert.p);
+ BKE_curve_nurb_vert_active_set(cu, NULL, NULL);
- copy_v3_v3(newbezt->vec[1], location);
- sub_v3_v3v3(newbezt->vec[0], newbezt->vec[1], temp);
- add_v3_v3v3(newbezt->vec[2], newbezt->vec[1], temp);
+ /* first pass (endpoints) */
+ for (nu = editnurb->nurbs.first; nu; nu = nu->next) {
- mul_m4_v3(imat, newbezt->vec[0]);
- mul_m4_v3(imat, newbezt->vec[1]);
- mul_m4_v3(imat, newbezt->vec[2]);
+ if ((nu->flagu & CU_NURB_CYCLIC) && (nu->pntsu > 1)) {
+ continue;
+ }
- ok = 1;
- nu = newnu;
- }
- else if (nu->pntsv == 1) {
- newbp = (BPoint *)MEM_callocN(sizeof(BPoint), "addvert_Nurb5");
- newbp->radius = 1;
- newbp->alfa = 0;
- newbp->f1 |= SELECT;
+ if (nu->type == CU_BEZIER) {
- newnu = (Nurb *)MEM_mallocN(sizeof(Nurb), "addvert_Nurb newnu");
- memcpy(newnu, nu, sizeof(Nurb));
- BLI_addtail(&editnurb->nurbs, newnu);
- newnu->bp = newbp;
- newnu->orderu = 2;
- newnu->pntsu = 1;
+ /* Check to see if the first bezier point is selected */
+ if (nu->pntsu > 0 && nu->bezt != NULL) {
+ BezTriple *nu_bezt_old = nu->bezt;
+ BezTriple *bezt = nu->bezt;
- mul_v3_m4v3(newbp->vec, imat, location);
- newbp->vec[3] = 1.0;
+ if (BEZT_ISSEL_ANY_HIDDENHANDLES(cu, bezt)) {
+ BezTriple *bezt_new;
+ BEZT_DESEL_ALL(bezt);
- newnu->knotsu = newnu->knotsv = NULL;
- BKE_nurb_knot_calc_u(newnu);
+ bezt_new = MEM_mallocN((nu->pntsu + 1) * sizeof(BezTriple), __func__);
+ ED_curve_beztcpy(editnurb, bezt_new + 1, bezt, nu->pntsu);
+ *bezt_new = *bezt;
- ok = 1;
- nu = newnu;
+
+ MEM_freeN(nu->bezt);
+ nu->bezt = bezt_new;
+
+ nu->pntsu += 1;
+
+ if (ARRAY_HAS_ITEM(cu_actvert.bezt, nu_bezt_old, nu->pntsu - 1)) {
+ cu_actvert.bezt = (cu_actvert.bezt == bezt) ?
+ bezt_new : &nu->bezt[(cu_actvert.bezt - nu_bezt_old) + 1];
+ BKE_curve_nurb_vert_active_set(cu, nu, cu_actvert.bezt);
+ }
+
+ BEZT_SEL_ALL(bezt_new);
+ changed = true;
+ }
}
+ /* Check to see if the last bezier point is selected */
+ if (nu->pntsu > 1) {
+ BezTriple *nu_bezt_old = nu->bezt;
+ BezTriple *bezt = &nu->bezt[nu->pntsu - 1];
+
+ if (BEZT_ISSEL_ANY_HIDDENHANDLES(cu, bezt)) {
+ BezTriple *bezt_new;
+ BEZT_DESEL_ALL(bezt);
+
+ bezt_new = MEM_mallocN((nu->pntsu + 1) * sizeof(BezTriple), __func__);
+ ED_curve_beztcpy(editnurb, bezt_new, nu->bezt, nu->pntsu);
+ bezt_new[nu->pntsu] = *bezt;
+
+ MEM_freeN(nu->bezt);
+ nu->bezt = bezt_new;
+
+ bezt_new += nu->pntsu;
+ nu->pntsu += 1;
+
+ if (ARRAY_HAS_ITEM(cu_actvert.bezt, nu_bezt_old, nu->pntsu - 1)) {
+ cu_actvert.bezt = (cu_actvert.bezt == bezt) ?
+ bezt_new : &nu->bezt[cu_actvert.bezt - nu_bezt_old];
+ BKE_curve_nurb_vert_active_set(cu, nu, cu_actvert.bezt);
+ }
+
+ BEZT_SEL_ALL(bezt_new);
+ changed = true;
+ }
+ }
}
+ else {
- if (!ok)
- return OPERATOR_CANCELLED;
- }
+ /* Check to see if the first bpoint is selected */
+ if (nu->pntsu > 0 && nu->bp != NULL) {
+ BPoint *nu_bp_old = nu->bp;
+ BPoint *bp = nu->bp;
- if (!ok && nu->type == CU_BEZIER) {
- /* which bezpoint? */
- if (bezt == &nu->bezt[nu->pntsu - 1]) { /* last */
- BEZ_DESEL(bezt);
- newbezt = (BezTriple *)MEM_callocN((nu->pntsu + 1) * sizeof(BezTriple), "addvert_Nurb");
- ED_curve_beztcpy(editnurb, newbezt, nu->bezt, nu->pntsu);
- newbezt[nu->pntsu] = *bezt;
- copy_v3_v3(temp, bezt->vec[1]);
- MEM_freeN(nu->bezt);
- nu->bezt = newbezt;
- newbezt += nu->pntsu;
- BEZ_SEL(newbezt);
- newbezt->h1 = newbezt->h2;
- bezt = &nu->bezt[nu->pntsu - 1];
- ok = 1;
+ if (bp->f1 & SELECT) {
+ BPoint *bp_new;
+ bp->f1 &= ~SELECT;
- if (nu->pntsu > 1) {
- bezt_recalc[1] = newbezt;
- bezt_recalc[0] = newbezt - 1;
- }
- }
- else if (bezt == nu->bezt) { /* first */
- BEZ_DESEL(bezt);
- newbezt = (BezTriple *)MEM_callocN((nu->pntsu + 1) * sizeof(BezTriple), "addvert_Nurb");
- ED_curve_beztcpy(editnurb, newbezt + 1, bezt, nu->pntsu);
- *newbezt = *bezt;
- BEZ_SEL(newbezt);
- newbezt->h2 = newbezt->h1;
- copy_v3_v3(temp, bezt->vec[1]);
- MEM_freeN(nu->bezt);
- nu->bezt = newbezt;
- bezt = newbezt + 1;
- ok = 1;
+ bp_new = MEM_mallocN((nu->pntsu + 1) * sizeof(BPoint), __func__);
+ ED_curve_bpcpy(editnurb, bp_new + 1, bp, nu->pntsu);
+ *bp_new = *bp;
+
+ MEM_freeN(nu->bp);
+ nu->bp = bp_new;
+
+ nu->pntsu += 1;
+ BKE_nurb_knot_calc_u(nu);
+
+ if (ARRAY_HAS_ITEM(cu_actvert.bp, nu_bp_old, nu->pntsu - 1)) {
+ cu_actvert.bp = (cu_actvert.bp == bp) ?
+ bp_new : &nu->bp[(cu_actvert.bp - nu_bp_old) + 1];
+ BKE_curve_nurb_vert_active_set(cu, nu, cu_actvert.bp);
+ }
+ bp_new->f1 |= SELECT;
+ changed = true;
+ }
+ }
+
+ /* Check to see if the last bpoint is selected */
if (nu->pntsu > 1) {
- bezt_recalc[1] = newbezt;
- bezt_recalc[2] = newbezt + 1;
+ BPoint *nu_bp_old = nu->bp;
+ BPoint *bp = &nu->bp[nu->pntsu - 1];
+
+ if (bp->f1 & SELECT) {
+ BPoint *bp_new;
+ bp->f1 &= ~SELECT;
+
+ bp_new = MEM_mallocN((nu->pntsu + 1) * sizeof(BPoint), __func__);
+ ED_curve_bpcpy(editnurb, bp_new, nu->bp, nu->pntsu);
+ bp_new[nu->pntsu] = *bp;
+
+ MEM_freeN(nu->bp);
+ nu->bp = bp_new;
+
+ bp_new += nu->pntsu;
+ nu->pntsu += 1;
+
+ if (ARRAY_HAS_ITEM(cu_actvert.bp, nu_bp_old, nu->pntsu - 1)) {
+ cu_actvert.bp = (cu_actvert.bp == bp) ?
+ bp_new : &nu->bp[cu_actvert.bp - nu_bp_old];
+ BKE_curve_nurb_vert_active_set(cu, nu, cu_actvert.bp);
+ }
+
+ BKE_nurb_knot_calc_u(nu);
+
+ bp_new->f1 |= SELECT;
+ changed = true;
+ }
}
}
- else if (mode != 'e') {
- BEZ_DESEL(bezt);
- newbezt = (BezTriple *)MEM_callocN(sizeof(BezTriple), "addvert_Nurb");
- *newbezt = *bezt;
- BEZ_SEL(newbezt);
- newbezt->h2 = newbezt->h1;
- copy_v3_v3(temp, bezt->vec[1]);
+ }
- newnu = (Nurb *)MEM_mallocN(sizeof(Nurb), "addvert_Nurb newnu");
- memcpy(newnu, nu, sizeof(Nurb));
- BLI_addtail(&editnurb->nurbs, newnu);
- newnu->bezt = newbezt;
- newnu->pntsu = 1;
+ /* second pass (interior points) */
+ nu_last = editnurb->nurbs.last;
+ for (nu = editnurb->nurbs.first; (nu != nu_last->next); nu = nu->next) {
+ int i, i_end;
- nu = newnu;
- bezt = newbezt;
- ok = 1;
+ if ((nu->flagu & CU_NURB_CYCLIC) && (nu->pntsu > 1)) {
+ /* all points are interior */
+ i = 0;
+ i_end = nu->pntsu;
}
else {
- bezt = NULL;
+ /* skip endpoints */
+ i = 1;
+ i_end = nu->pntsu - 1;
}
- if (bezt) {
- if (!newnu) nu->pntsu++;
+ if (nu->type == CU_BEZIER) {
+ BezTriple *bezt;
- if (mode == 'e') {
- copy_v3_v3(newbezt->vec[0], bezt->vec[0]);
- copy_v3_v3(newbezt->vec[1], bezt->vec[1]);
- copy_v3_v3(newbezt->vec[2], bezt->vec[2]);
- }
- else {
- mul_v3_m4v3(newbezt->vec[1], imat, location);
- sub_v3_v3v3(temp, newbezt->vec[1], temp);
+ for (bezt = &nu->bezt[i]; i < i_end; i++, bezt++) {
+ if (BEZT_ISSEL_ANY_HIDDENHANDLES(cu, bezt)) {
+ Nurb *nurb_new;
+ BezTriple *bezt_new;
+
+ BEZT_DESEL_ALL(bezt);
+ nurb_new = BKE_nurb_copy(nu, 1, 1);
+ nurb_new->flagu &= ~CU_NURB_CYCLIC;
+ BLI_addtail(&editnurb->nurbs, nurb_new);
+ bezt_new = nurb_new->bezt;
+ ED_curve_beztcpy(editnurb, bezt_new, bezt, 1);
+ BEZT_SEL_ALL(bezt_new);
+
+ if (cu_actvert.bezt == bezt || cu_actnu == NULL) {
+ BKE_curve_nurb_vert_active_set(cu, nurb_new, bezt_new);
+ }
- if (bezt_recalc[1]) {
- const char h1 = bezt_recalc[1]->h1, h2 = bezt_recalc[1]->h2;
- bezt_recalc[1]->h1 = bezt_recalc[1]->h2 = HD_AUTO;
- BKE_nurb_handle_calc(bezt_recalc[1], bezt_recalc[0], bezt_recalc[2], 0);
- bezt_recalc[1]->h1 = h1;
- bezt_recalc[1]->h2 = h2;
- }
- else {
- add_v3_v3v3(newbezt->vec[0], bezt->vec[0], temp);
- add_v3_v3v3(newbezt->vec[2], bezt->vec[2], temp);
+ changed = true;
}
-
+ }
+ }
+ else {
+ BPoint *bp;
+
+ for (bp = &nu->bp[i]; i < i_end; i++, bp++) {
+ if (bp->f1 & SELECT) {
+ Nurb *nurb_new;
+ BPoint *bp_new;
+
+ bp->f1 &= ~SELECT;
+ nurb_new = BKE_nurb_copy(nu, 1, 1);
+ nurb_new->flagu &= ~CU_NURB_CYCLIC;
+ BLI_addtail(&editnurb->nurbs, nurb_new);
+ bp_new = nurb_new->bp;
+ ED_curve_bpcpy(editnurb, bp_new, bp, 1);
+ bp_new->f1 |= SELECT;
+
+ if (cu_actvert.bp == bp || cu_actnu == NULL) {
+ BKE_curve_nurb_vert_active_set(cu, nurb_new, bp_new);
+ }
- if (newnu) BKE_nurb_handles_calc(newnu);
- else BKE_nurb_handles_calc(nu);
+ changed = true;
+ }
}
}
}
- else if (!ok && nu->pntsv == 1) {
- /* which b-point? */
- if (bp == &nu->bp[nu->pntsu - 1]) { /* last */
- bp->f1 = 0;
- newbp = (BPoint *)MEM_callocN((nu->pntsu + 1) * sizeof(BPoint), "addvert_Nurb4");
- ED_curve_bpcpy(editnurb, newbp, nu->bp, nu->pntsu);
- newbp[nu->pntsu] = *bp;
- MEM_freeN(nu->bp);
- nu->bp = newbp;
- newbp += nu->pntsu;
- newbp->f1 |= SELECT;
- bp = newbp - 1;
- ok = 1;
- }
- else if (bp == nu->bp) { /* first */
- bp->f1 = 0;
- newbp = (BPoint *)MEM_callocN((nu->pntsu + 1) * sizeof(BPoint), "addvert_Nurb3");
- ED_curve_bpcpy(editnurb, newbp + 1, bp, nu->pntsu);
- *newbp = *bp;
- newbp->f1 |= SELECT;
- MEM_freeN(nu->bp);
- nu->bp = newbp;
- bp = newbp + 1;
- ok = 1;
- }
- else if (mode != 'e') {
- bp->f1 = 0;
- newbp = (BPoint *)MEM_callocN(sizeof(BPoint), "addvert_Nurb5");
- *newbp = *bp;
- newbp->f1 |= SELECT;
- newnu = (Nurb *)MEM_mallocN(sizeof(Nurb), "addvert_Nurb newnu");
- memcpy(newnu, nu, sizeof(Nurb));
- BLI_addtail(&editnurb->nurbs, newnu);
- newnu->bp = newbp;
- newnu->orderu = 2;
- newnu->pntsu = 1;
- newnu->knotsu = newnu->knotsv = NULL;
+ if (changed == false) {
+ BKE_curve_nurb_vert_active_set(cu, cu_actnu, cu_actvert.p);
+ }
- nu = newnu;
- bp = newbp;
- ok = 1;
+ return changed;
+}
+
+/***************** add vertex operator **********************/
+
+static int ed_editcurve_addvert(Curve *cu, EditNurb *editnurb, const float location[3])
+{
+ Nurb *nu;
+
+ float minmax[2][3];
+ float temp[3];
+ bool nu_has_select = false;
+
+ bool changed = false;
+
+ INIT_MINMAX(minmax[0], minmax[1]);
+
+ for (nu = editnurb->nurbs.first; nu; nu = nu->next) {
+ int i;
+ if (nu->type == CU_BEZIER) {
+ BezTriple *bezt;
+
+ for (i = 0, bezt = nu->bezt; i < nu->pntsu; i++, bezt++) {
+ if (BEZT_ISSEL_ANY_HIDDENHANDLES(cu, bezt)) {
+ minmax_v3v3_v3(UNPACK2(minmax), bezt->vec[1]);
+ nu_has_select = true;
+ }
+ }
}
else {
- bp = NULL;
+ BPoint *bp;
+
+ for (i = 0, bp = nu->bp; i < nu->pntsu; i++, bp++) {
+ if (bp->f1 & SELECT) {
+ minmax_v3v3_v3(UNPACK2(minmax), bp->vec);
+ nu_has_select = true;
+ }
+ }
}
+ }
+
+ if (nu_has_select && ed_editcurve_extrude(cu, editnurb)) {
+ float ofs[3], center[3];
+ int i;
+
+ mid_v3_v3v3(center, minmax[0], minmax[1]);
+ sub_v3_v3v3(ofs, location, center);
- if (bp) {
- if (mode == 'e') {
- copy_v3_v3(newbp->vec, bp->vec);
+ if ((cu->flag & CU_3D) == 0) {
+ ofs[2] = 0.0f;
+ }
+
+ for (nu = editnurb->nurbs.first; nu; nu = nu->next) {
+ if (nu->type == CU_BEZIER) {
+ BezTriple *bezt;
+ for (i = 0, bezt = nu->bezt; i < nu->pntsu; i++, bezt++) {
+ if (BEZT_ISSEL_ANY_HIDDENHANDLES(cu, bezt)) {
+ add_v3_v3(bezt->vec[0], ofs);
+ add_v3_v3(bezt->vec[1], ofs);
+ add_v3_v3(bezt->vec[2], ofs);
+
+ if (((nu->flagu & CU_NURB_CYCLIC) == 0) &&
+ (i == 0 || i == nu->pntsu - 1))
+ {
+ BKE_nurb_handle_calc_simple_auto(nu, bezt);
+ }
+ }
+ }
}
else {
- mul_v3_m4v3(newbp->vec, imat, location);
- newbp->vec[3] = 1.0;
+ BPoint *bp;
- if (!newnu && nu->orderu < 4 && nu->orderu <= nu->pntsu)
- nu->orderu++;
+ for (i = 0, bp = nu->bp; i < nu->pntsu; i++, bp++) {
+ if (bp->f1 & SELECT) {
+ add_v3_v3(bp->vec, ofs);
+ }
+ }
}
+ }
+ changed = true;
+ }
+ else {
+ /* nothing selected: create a new curve */
+ nu = BKE_curve_nurb_active_get(cu);
- if (!newnu) {
- nu->pntsu++;
- BKE_nurb_knot_calc_u(nu);
+ if (!nu || nu->type == CU_BEZIER) {
+ Nurb *nurb_new;
+ BezTriple *bezt_new;
+
+ if (nu) {
+ nurb_new = BKE_nurb_copy(nu, 1, 1);
}
else {
- BKE_nurb_knot_calc_u(newnu);
+ nurb_new = MEM_callocN(sizeof(Nurb), "BLI_editcurve_addvert new_bezt_nurb 2");
+ nurb_new->type = CU_BEZIER;
+ nurb_new->resolu = cu->resolu;
+ nurb_new->orderu = 4;
+ nurb_new->flag |= CU_SMOOTH;
+ BKE_nurb_bezierPoints_add(nurb_new, 1);
}
- }
- }
+ BLI_addtail(&editnurb->nurbs, nurb_new);
- if (ok) {
- if (nu->bezt) {
- BKE_curve_nurb_vert_active_set(cu, nu, newbezt);
+ bezt_new = nurb_new->bezt;
+
+ BEZT_SEL_ALL(bezt_new);
+
+ bezt_new->h1 = HD_AUTO;
+ bezt_new->h2 = HD_AUTO;
+
+ temp[0] = 1.0f;
+ temp[1] = 0.0f;
+ temp[2] = 0.0f;
+
+ copy_v3_v3(bezt_new->vec[1], location);
+ sub_v3_v3v3(bezt_new->vec[0], bezt_new->vec[1], temp);
+ add_v3_v3v3(bezt_new->vec[2], bezt_new->vec[1], temp);
+
+ changed = true;
}
else {
- BKE_curve_nurb_vert_active_set(cu, nu, newbp);
- }
+ Nurb *nurb_new;
+ BPoint *bp_new;
- BKE_nurb_test2D(nu);
+ {
+ nurb_new = MEM_callocN(sizeof(Nurb), __func__);
+ nurb_new->type = CU_POLY;
+ nurb_new->resolu = cu->resolu;
+ nurb_new->flag |= CU_SMOOTH;
+ nurb_new->orderu = 4;
+ BKE_nurb_points_add(nurb_new, 1);
+ }
+ BLI_addtail(&editnurb->nurbs, nurb_new);
- if (ED_curve_updateAnimPaths(obedit->data))
- WM_event_add_notifier(C, NC_OBJECT | ND_KEYS, obedit);
+ bp_new = nurb_new->bp;
- WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
- DAG_id_tag_update(obedit->data, 0);
+ bp_new->f1 |= SELECT;
- return OPERATOR_FINISHED;
+ copy_v3_v3(bp_new->vec, location);
+ bp_new->vec[3] = 1.0f;
+
+ BKE_nurb_knot_calc_u(nurb_new);
+
+ changed = true;
+ }
}
- return OPERATOR_CANCELLED;
+ return changed;
}
static int add_vertex_exec(bContext *C, wmOperator *op)
{
+ Object *obedit = CTX_data_edit_object(C);
+ Curve *cu = obedit->data;
+ EditNurb *editnurb = cu->editnurb;
float location[3];
+ float imat[4][4];
RNA_float_get_array(op->ptr, "location", location);
- return addvert_Nurb(C, 0, location);
+
+ invert_m4_m4(imat, obedit->obmat);
+ mul_m4_v3(imat, location);
+
+ if (ed_editcurve_addvert(cu, editnurb, location)) {
+ if (ED_curve_updateAnimPaths(obedit->data)) {
+ WM_event_add_notifier(C, NC_OBJECT | ND_KEYS, obedit);
+ }
+
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
+ DAG_id_tag_update(obedit->data, 0);
+
+ return OPERATOR_FINISHED;
+ }
+ else {
+ return OPERATOR_CANCELLED;
+ }
}
static int add_vertex_invoke(bContext *C, wmOperator *op, const wmEvent *event)
@@ -5196,7 +4849,7 @@ static int add_vertex_invoke(bContext *C, wmOperator *op, const wmEvent *event)
cu = vc.obedit->data;
- findselectedNurbvert(&cu->editnurb->nurbs, &nu, &bezt, &bp);
+ findselectedNurbvert(cu, &nu, &bezt, &bp);
if (bezt) {
mul_v3_m4v3(location, vc.obedit->obmat, bezt->vec[1]);
@@ -5239,34 +4892,47 @@ void CURVE_OT_vertex_add(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
/* properties */
- RNA_def_float_vector_xyz(ot->srna, "location", 3, NULL, -FLT_MAX, FLT_MAX, "Location", "Location to add new vertex at", -1e4, 1e4);
+ RNA_def_float_vector_xyz(ot->srna, "location", 3, NULL, -OBJECT_ADD_SIZE_MAXF, OBJECT_ADD_SIZE_MAXF,
+ "Location", "Location to add new vertex at", -1.0e4f, 1.0e4f);
}
/***************** extrude operator **********************/
-static int extrude_exec(bContext *C, wmOperator *UNUSED(op))
+static int curve_extrude_exec(bContext *C, wmOperator *UNUSED(op))
{
Object *obedit = CTX_data_edit_object(C);
Curve *cu = obedit->data;
EditNurb *editnurb = cu->editnurb;
- Nurb *nu;
+ bool changed = false;
+ bool as_curve = false;
/* first test: curve? */
- for (nu = editnurb->nurbs.first; nu; nu = nu->next)
- if (nu->pntsv == 1 && isNurbsel_count(cu, nu) == 1)
- break;
+ if (obedit->type != OB_CURVE) {
+ Nurb *nu;
+ for (nu = editnurb->nurbs.first; nu; nu = nu->next) {
+ if ((nu->pntsv == 1) &&
+ (ED_curve_nurb_select_count(cu, nu) == 1))
+ {
+ as_curve = true;
+ break;
+ }
+ }
+ }
- if (obedit->type == OB_CURVE || nu) {
- addvert_Nurb(C, 'e', NULL);
+ if (obedit->type == OB_CURVE || as_curve) {
+ changed = ed_editcurve_extrude(cu, editnurb);
}
else {
- if (ed_editnurb_extrude_flag(editnurb, 1)) { /* '1'= flag */
- if (ED_curve_updateAnimPaths(obedit->data))
- WM_event_add_notifier(C, NC_OBJECT | ND_KEYS, obedit);
+ changed = ed_editnurb_extrude_flag(editnurb, SELECT);
+ }
- WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
- DAG_id_tag_update(obedit->data, 0);
+ if (changed) {
+ if (ED_curve_updateAnimPaths(obedit->data)) {
+ WM_event_add_notifier(C, NC_OBJECT | ND_KEYS, obedit);
}
+
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
+ DAG_id_tag_update(obedit->data, 0);
}
return OPERATOR_FINISHED;
@@ -5280,7 +4946,7 @@ void CURVE_OT_extrude(wmOperatorType *ot)
ot->idname = "CURVE_OT_extrude";
/* api callbacks */
- ot->exec = extrude_exec;
+ ot->exec = curve_extrude_exec;
ot->poll = ED_operator_editsurfcurve;
/* flags */
@@ -5319,7 +4985,7 @@ static int toggle_cyclic_exec(bContext *C, wmOperator *op)
a = nu->pntsu;
bezt = nu->bezt;
while (a--) {
- if (BEZSELECTED_HIDDENHANDLES(cu, bezt)) {
+ if (BEZT_ISSEL_ANY_HIDDENHANDLES(cu, bezt)) {
nu->flagu ^= CU_NURB_CYCLIC;
break;
}
@@ -5382,11 +5048,11 @@ static int toggle_cyclic_invoke(bContext *C, wmOperator *op, const wmEvent *UNUS
for (nu = editnurb->first; nu; nu = nu->next) {
if (nu->pntsu > 1 || nu->pntsv > 1) {
if (nu->type == CU_NURBS) {
- pup = uiPupMenuBegin(C, IFACE_("Direction"), ICON_NONE);
- layout = uiPupMenuLayout(pup);
+ pup = UI_popup_menu_begin(C, IFACE_("Direction"), ICON_NONE);
+ layout = UI_popup_menu_layout(pup);
uiItemsEnumO(layout, op->type->idname, "direction");
- uiPupMenuEnd(C, pup);
- return OPERATOR_CANCELLED;
+ UI_popup_menu_end(C, pup);
+ return OPERATOR_INTERFACE;
}
}
}
@@ -5420,708 +5086,6 @@ void CURVE_OT_cyclic_toggle(wmOperatorType *ot)
RNA_def_enum(ot->srna, "direction", direction_items, 0, "Direction", "Direction to make surface cyclic in");
}
-/***************** select linked operator ******************/
-
-static int select_linked_exec(bContext *C, wmOperator *UNUSED(op))
-{
- Object *obedit = CTX_data_edit_object(C);
- Curve *cu = (Curve *)obedit->data;
- EditNurb *editnurb = cu->editnurb;
- ListBase *nurbs = &editnurb->nurbs;
- Nurb *nu;
- BezTriple *bezt;
- BPoint *bp;
- int a;
-
- for (nu = nurbs->first; nu; nu = nu->next) {
- if (nu->type == CU_BEZIER) {
- bezt = nu->bezt;
- a = nu->pntsu;
- while (a--) {
- if ((bezt->f1 & SELECT) || (bezt->f2 & SELECT) || (bezt->f3 & SELECT)) {
- a = nu->pntsu;
- bezt = nu->bezt;
- while (a--) {
- select_beztriple(bezt, SELECT, SELECT, VISIBLE);
- bezt++;
- }
- break;
- }
- bezt++;
- }
- }
- else {
- bp = nu->bp;
- a = nu->pntsu * nu->pntsv;
- while (a--) {
- if (bp->f1 & SELECT) {
- a = nu->pntsu * nu->pntsv;
- bp = nu->bp;
- while (a--) {
- select_bpoint(bp, SELECT, SELECT, VISIBLE);
- bp++;
- }
- break;
- }
- bp++;
- }
- }
- }
-
- WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
-
- return OPERATOR_FINISHED;
-}
-
-static int select_linked_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
-{
- return select_linked_exec(C, op);
-}
-
-void CURVE_OT_select_linked(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Select Linked All";
- ot->idname = "CURVE_OT_select_linked";
- ot->description = "Select all control points linked to active one";
-
- /* api callbacks */
- ot->exec = select_linked_exec;
- ot->invoke = select_linked_invoke;
- ot->poll = ED_operator_editsurfcurve;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
-}
-
-
-/***************** select linked pick operator ******************/
-
-static int select_linked_pick_invoke(bContext *C, wmOperator *op, const wmEvent *event)
-{
- Object *obedit = CTX_data_edit_object(C);
- ViewContext vc;
- Nurb *nu;
- BezTriple *bezt;
- BPoint *bp;
- int a;
- const bool select = !RNA_boolean_get(op->ptr, "deselect");
-
- view3d_operator_needs_opengl(C);
- view3d_set_viewcontext(C, &vc);
-
- findnearestNurbvert(&vc, 1, event->mval, &nu, &bezt, &bp);
-
- if (bezt) {
- a = nu->pntsu;
- bezt = nu->bezt;
- while (a--) {
- select_beztriple(bezt, select, SELECT, VISIBLE);
- bezt++;
- }
- }
- else if (bp) {
- a = nu->pntsu * nu->pntsv;
- bp = nu->bp;
- while (a--) {
- select_bpoint(bp, select, SELECT, VISIBLE);
- bp++;
- }
- }
-
- WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
- if (!select) {
- BKE_curve_nurb_vert_active_validate(obedit->data);
- }
-
- return OPERATOR_FINISHED;
-}
-
-void CURVE_OT_select_linked_pick(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Select Linked";
- ot->idname = "CURVE_OT_select_linked_pick";
- ot->description = "Select all control points linked to already selected ones";
-
- /* api callbacks */
- ot->invoke = select_linked_pick_invoke;
- ot->poll = ED_operator_editsurfcurve_region_view3d;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- RNA_def_boolean(ot->srna, "deselect", 0, "Deselect", "Deselect linked control points rather than selecting them");
-}
-
-/***************** select row operator **********************/
-
-static int select_row_exec(bContext *C, wmOperator *UNUSED(op))
-{
- Object *obedit = CTX_data_edit_object(C);
- Curve *cu = obedit->data;
- ListBase *editnurb = object_editcurve_get(obedit);
- static BPoint *last = NULL;
- static int direction = 0;
- Nurb *nu = NULL;
- BPoint *bp = NULL;
- int u = 0, v = 0, a, b;
-
- if (!BKE_curve_nurb_vert_active_get(cu, &nu, (void *)&bp))
- return OPERATOR_CANCELLED;
-
- if (last == bp) {
- direction = 1 - direction;
- BKE_nurbList_flag_set(editnurb, 0);
- }
- last = bp;
-
- u = cu->actvert % nu->pntsu;
- v = cu->actvert / nu->pntsu;
- bp = nu->bp;
- for (a = 0; a < nu->pntsv; a++) {
- for (b = 0; b < nu->pntsu; b++, bp++) {
- if (direction) {
- if (a == v) select_bpoint(bp, SELECT, SELECT, VISIBLE);
- }
- else {
- if (b == u) select_bpoint(bp, SELECT, SELECT, VISIBLE);
- }
- }
- }
-
- WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
-
- return OPERATOR_FINISHED;
-}
-
-void CURVE_OT_select_row(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Select Control Point Row";
- ot->idname = "CURVE_OT_select_row";
- ot->description = "Select a row of control points including active one";
-
- /* api callbacks */
- ot->exec = select_row_exec;
- ot->poll = ED_operator_editsurf;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-}
-
-/***************** select next operator **********************/
-
-static int select_next_exec(bContext *C, wmOperator *UNUSED(op))
-{
- Object *obedit = CTX_data_edit_object(C);
- ListBase *editnurb = object_editcurve_get(obedit);
-
- select_adjacent_cp(editnurb, 1, 0, SELECT);
- WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
-
- return OPERATOR_FINISHED;
-}
-
-void CURVE_OT_select_next(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Select Next";
- ot->idname = "CURVE_OT_select_next";
- ot->description = "Select control points following already selected ones along the curves";
-
- /* api callbacks */
- ot->exec = select_next_exec;
- ot->poll = ED_operator_editcurve;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-}
-
-/***************** select previous operator **********************/
-
-static int select_previous_exec(bContext *C, wmOperator *UNUSED(op))
-{
- Object *obedit = CTX_data_edit_object(C);
- ListBase *editnurb = object_editcurve_get(obedit);
-
- select_adjacent_cp(editnurb, -1, 0, SELECT);
- WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
-
- return OPERATOR_FINISHED;
-}
-
-void CURVE_OT_select_previous(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Select Previous";
- ot->idname = "CURVE_OT_select_previous";
- ot->description = "Select control points preceding already selected ones along the curves";
-
- /* api callbacks */
- ot->exec = select_previous_exec;
- ot->poll = ED_operator_editcurve;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-}
-
-/***************** select more operator **********************/
-
-static int select_more_exec(bContext *C, wmOperator *UNUSED(op))
-{
- Object *obedit = CTX_data_edit_object(C);
- ListBase *editnurb = object_editcurve_get(obedit);
- Nurb *nu;
- BPoint *bp, *tempbp;
- int a;
- short sel = 0;
-
- /* note that NURBS surface is a special case because we mimic */
- /* the behavior of "select more" of mesh tools. */
- /* The algorithm is designed to work in planar cases so it */
- /* may not be optimal always (example: end of NURBS sphere) */
- if (obedit->type == OB_SURF) {
- for (nu = editnurb->first; nu; nu = nu->next) {
- BLI_bitmap *selbpoints;
- a = nu->pntsu * nu->pntsv;
- bp = nu->bp;
- selbpoints = BLI_BITMAP_NEW(a, "selectlist");
- while (a > 0) {
- if ((!BLI_BITMAP_TEST(selbpoints, a)) && (bp->hide == 0) && (bp->f1 & SELECT)) {
- /* upper control point */
- if (a % nu->pntsu != 0) {
- tempbp = bp - 1;
- if (!(tempbp->f1 & SELECT)) select_bpoint(tempbp, SELECT, SELECT, VISIBLE);
- }
-
- /* left control point. select only if it is not selected already */
- if (a - nu->pntsu > 0) {
- sel = 0;
- tempbp = bp + nu->pntsu;
- if (!(tempbp->f1 & SELECT)) sel = select_bpoint(tempbp, SELECT, SELECT, VISIBLE);
- /* make sure selected bpoint is discarded */
- if (sel == 1) BLI_BITMAP_ENABLE(selbpoints, a - nu->pntsu);
- }
-
- /* right control point */
- if (a + nu->pntsu < nu->pntsu * nu->pntsv) {
- tempbp = bp - nu->pntsu;
- if (!(tempbp->f1 & SELECT)) select_bpoint(tempbp, SELECT, SELECT, VISIBLE);
- }
-
- /* lower control point. skip next bp in case selection was made */
- if (a % nu->pntsu != 1) {
- sel = 0;
- tempbp = bp + 1;
- if (!(tempbp->f1 & SELECT)) sel = select_bpoint(tempbp, SELECT, SELECT, VISIBLE);
- if (sel) {
- bp++;
- a--;
- }
- }
- }
-
- bp++;
- a--;
- }
-
- MEM_freeN(selbpoints);
- }
- }
- else {
- select_adjacent_cp(editnurb, 1, 0, SELECT);
- select_adjacent_cp(editnurb, -1, 0, SELECT);
- }
-
- WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
-
- return OPERATOR_FINISHED;
-}
-
-void CURVE_OT_select_more(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Select More";
- ot->idname = "CURVE_OT_select_more";
- ot->description = "Select control points directly linked to already selected ones";
-
- /* api callbacks */
- ot->exec = select_more_exec;
- ot->poll = ED_operator_editsurfcurve;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-}
-
-/******************** select less operator *****************/
-
-/* basic method: deselect if control point doesn't have all neighbors selected */
-static int select_less_exec(bContext *C, wmOperator *UNUSED(op))
-{
- Object *obedit = CTX_data_edit_object(C);
- ListBase *editnurb = object_editcurve_get(obedit);
- Nurb *nu;
- BPoint *bp;
- BezTriple *bezt;
- int a;
- int sel = 0;
- short lastsel = false;
-
- if (obedit->type == OB_SURF) {
- for (nu = editnurb->first; nu; nu = nu->next) {
- BLI_bitmap *selbpoints;
- a = nu->pntsu * nu->pntsv;
- bp = nu->bp;
- selbpoints = BLI_BITMAP_NEW(a, "selectlist");
- while (a--) {
- if ((bp->hide == 0) && (bp->f1 & SELECT)) {
- sel = 0;
-
- /* check if neighbors have been selected */
- /* edges of surface are an exception */
- if ((a + 1) % nu->pntsu == 0) {
- sel++;
- }
- else {
- bp--;
- if (BLI_BITMAP_TEST(selbpoints, a + 1) || ((bp->hide == 0) && (bp->f1 & SELECT))) sel++;
- bp++;
- }
-
- if ((a + 1) % nu->pntsu == 1) {
- sel++;
- }
- else {
- bp++;
- if ((bp->hide == 0) && (bp->f1 & SELECT)) sel++;
- bp--;
- }
-
- if (a + 1 > nu->pntsu * nu->pntsv - nu->pntsu) {
- sel++;
- }
- else {
- bp -= nu->pntsu;
- if (BLI_BITMAP_TEST(selbpoints, a + nu->pntsu) || ((bp->hide == 0) && (bp->f1 & SELECT))) sel++;
- bp += nu->pntsu;
- }
-
- if (a < nu->pntsu) {
- sel++;
- }
- else {
- bp += nu->pntsu;
- if ((bp->hide == 0) && (bp->f1 & SELECT)) sel++;
- bp -= nu->pntsu;
- }
-
- if (sel != 4) {
- select_bpoint(bp, DESELECT, SELECT, VISIBLE);
- BLI_BITMAP_ENABLE(selbpoints, a);
- }
- }
- else {
- lastsel = false;
- }
-
- bp++;
- }
-
- MEM_freeN(selbpoints);
- }
- }
- else {
- for (nu = editnurb->first; nu; nu = nu->next) {
- lastsel = false;
- /* check what type of curve/nurb it is */
- if (nu->type == CU_BEZIER) {
- a = nu->pntsu;
- bezt = nu->bezt;
- while (a--) {
- if ((bezt->hide == 0) && (bezt->f2 & SELECT)) {
- sel = (lastsel == 1);
-
- /* check if neighbors have been selected */
- /* first and last are exceptions */
- if (a == nu->pntsu - 1) {
- sel++;
- }
- else {
- bezt--;
- if ((bezt->hide == 0) && (bezt->f2 & SELECT)) sel++;
- bezt++;
- }
-
- if (a == 0) {
- sel++;
- }
- else {
- bezt++;
- if ((bezt->hide == 0) && (bezt->f2 & SELECT)) sel++;
- bezt--;
- }
-
- if (sel != 2) {
- select_beztriple(bezt, DESELECT, SELECT, VISIBLE);
- lastsel = true;
- }
- else {
- lastsel = false;
- }
- }
- else {
- lastsel = false;
- }
-
- bezt++;
- }
- }
- else {
- a = nu->pntsu * nu->pntsv;
- bp = nu->bp;
- while (a--) {
- if ((lastsel == 0) && (bp->hide == 0) && (bp->f1 & SELECT)) {
- if (lastsel != 0) sel = 1;
- else sel = 0;
-
- /* first and last are exceptions */
- if (a == nu->pntsu * nu->pntsv - 1) {
- sel++;
- }
- else {
- bp--;
- if ((bp->hide == 0) && (bp->f1 & SELECT)) sel++;
- bp++;
- }
-
- if (a == 0) {
- sel++;
- }
- else {
- bp++;
- if ((bp->hide == 0) && (bp->f1 & SELECT)) sel++;
- bp--;
- }
-
- if (sel != 2) {
- select_bpoint(bp, DESELECT, SELECT, VISIBLE);
- lastsel = true;
- }
- else {
- lastsel = false;
- }
- }
- else {
- lastsel = false;
- }
-
- bp++;
- }
- }
- }
- }
-
- WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
- BKE_curve_nurb_vert_active_validate(obedit->data);
-
- return OPERATOR_FINISHED;
-}
-
-void CURVE_OT_select_less(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Select Less";
- ot->idname = "CURVE_OT_select_less";
- ot->description = "Reduce current selection by deselecting boundary elements";
-
- /* api callbacks */
- ot->exec = select_less_exec;
- ot->poll = ED_operator_editsurfcurve;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-}
-
-/********************** select random *********************/
-
-static void curve_select_random(ListBase *editnurb, float randfac, bool select)
-{
- Nurb *nu;
- BezTriple *bezt;
- BPoint *bp;
- int a;
-
- for (nu = editnurb->first; nu; nu = nu->next) {
- if (nu->type == CU_BEZIER) {
- bezt = nu->bezt;
- a = nu->pntsu;
- while (a--) {
- if (!bezt->hide) {
- if (BLI_frand() < randfac) {
- select_beztriple(bezt, select, SELECT, VISIBLE);
- }
- }
- bezt++;
- }
- }
- else {
- bp = nu->bp;
- a = nu->pntsu * nu->pntsv;
-
- while (a--) {
- if (!bp->hide) {
- if (BLI_frand() < randfac) {
- select_bpoint(bp, select, SELECT, VISIBLE);
- }
- }
- bp++;
- }
- }
- }
-}
-
-static int curve_select_random_exec(bContext *C, wmOperator *op)
-{
- Object *obedit = CTX_data_edit_object(C);
- ListBase *editnurb = object_editcurve_get(obedit);
- const bool select = (RNA_enum_get(op->ptr, "action") == SEL_SELECT);
- const float randfac = RNA_float_get(op->ptr, "percent") / 100.0f;
-
- curve_select_random(editnurb, randfac, select);
- BKE_curve_nurb_vert_active_validate(obedit->data);
-
- WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
-
- return OPERATOR_FINISHED;
-}
-
-void CURVE_OT_select_random(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Select Random";
- ot->idname = "CURVE_OT_select_random";
- ot->description = "Randomly select some control points";
-
- /* api callbacks */
- ot->exec = curve_select_random_exec;
- ot->poll = ED_operator_editsurfcurve;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- RNA_def_float_percentage(ot->srna, "percent", 50.f, 0.0f, 100.0f, "Percent", "Percentage of elements to select randomly", 0.f, 100.0f);
- WM_operator_properties_select_action_simple(ot, SEL_SELECT);
-}
-
-/********************* every nth number of point *******************/
-
-static void select_nth_bezt(Nurb *nu, BezTriple *bezt, int nth)
-{
- int a, start;
-
- start = bezt - nu->bezt;
- a = nu->pntsu;
- bezt = &nu->bezt[a - 1];
-
- while (a--) {
- if (abs(start - a) % nth) {
- select_beztriple(bezt, DESELECT, SELECT, HIDDEN);
- }
-
- bezt--;
- }
-}
-
-static void select_nth_bp(Nurb *nu, BPoint *bp, int nth)
-{
- int a, startrow, startpnt;
- int dist, row, pnt;
-
- startrow = (bp - nu->bp) / nu->pntsu;
- startpnt = (bp - nu->bp) % nu->pntsu;
-
- a = nu->pntsu * nu->pntsv;
- bp = &nu->bp[a - 1];
- row = nu->pntsv - 1;
- pnt = nu->pntsu - 1;
-
- while (a--) {
- dist = abs(pnt - startpnt) + abs(row - startrow);
- if (dist % nth) {
- select_bpoint(bp, DESELECT, SELECT, HIDDEN);
- }
-
- pnt--;
- if (pnt < 0) {
- pnt = nu->pntsu - 1;
- row--;
- }
-
- bp--;
- }
-}
-
-bool ED_curve_select_nth(Curve *cu, int nth)
-{
- Nurb *nu = NULL;
- void *vert = NULL;
-
- if (!BKE_curve_nurb_vert_active_get(cu, &nu, &vert))
- return false;
-
- if (nu->bezt) {
- select_nth_bezt(nu, vert, nth);
- }
- else {
- select_nth_bp(nu, vert, nth);
- }
-
- return true;
-}
-
-static int select_nth_exec(bContext *C, wmOperator *op)
-{
- Object *obedit = CTX_data_edit_object(C);
- int nth = RNA_int_get(op->ptr, "nth");
-
- if (!ED_curve_select_nth(obedit->data, nth)) {
- if (obedit->type == OB_SURF) {
- BKE_report(op->reports, RPT_ERROR, "Surface has not got active point");
- }
- else {
- BKE_report(op->reports, RPT_ERROR, "Curve has not got active point");
- }
-
- return OPERATOR_CANCELLED;
- }
-
- WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
-
- return OPERATOR_FINISHED;
-}
-
-void CURVE_OT_select_nth(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Checker Deselect";
- ot->description = "Deselect every other vertex";
- ot->idname = "CURVE_OT_select_nth";
-
- /* api callbacks */
- ot->exec = select_nth_exec;
- ot->poll = ED_operator_editsurfcurve;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- RNA_def_int(ot->srna, "nth", 2, 2, INT_MAX, "Nth Selection", "", 2, 100);
-}
-
/********************** add duplicate operator *********************/
static int duplicate_exec(bContext *C, wmOperator *op)
@@ -6189,12 +5153,12 @@ static int curve_delete_segments(Object *obedit, const bool split)
if (nu->type == CU_BEZIER) {
for (a = 0, bezt = nu->bezt; a < nu->pntsu; a++, bezt++) {
- if (!BEZSELECTED_HIDDENHANDLES(cu, bezt)) {
+ if (!BEZT_ISSEL_ANY_HIDDENHANDLES(cu, bezt)) {
enda = a;
if (starta == -1) starta = a;
if (a < nu->pntsu - 1) continue;
}
- else if (a < nu->pntsu - 1 && !BEZSELECTED_HIDDENHANDLES(cu, bezt + 1)) {
+ else if (a < nu->pntsu - 1 && !BEZT_ISSEL_ANY_HIDDENHANDLES(cu, bezt + 1)) {
/* if just single selected point then continue */
continue;
}
@@ -6218,8 +5182,8 @@ static int curve_delete_segments(Object *obedit, const bool split)
bezt2 = &nu->bezt[nu->pntsu - 2];
if ((nu->flagu & CU_NURB_CYCLIC) &&
- BEZSELECTED_HIDDENHANDLES(cu, bezt1) &&
- BEZSELECTED_HIDDENHANDLES(cu, bezt2))
+ BEZT_ISSEL_ANY_HIDDENHANDLES(cu, bezt1) &&
+ BEZT_ISSEL_ANY_HIDDENHANDLES(cu, bezt2))
{
/* check if need to join start of spline to end */
nu1 = BKE_nurb_copy(nu, cut + 1, 1);
@@ -6240,8 +5204,8 @@ static int curve_delete_segments(Object *obedit, const bool split)
bezt2 = &nu->bezt[1];
if ((nu->flagu & CU_NURB_CYCLIC) &&
- BEZSELECTED_HIDDENHANDLES(cu, bezt1) &&
- BEZSELECTED_HIDDENHANDLES(cu, bezt2))
+ BEZT_ISSEL_ANY_HIDDENHANDLES(cu, bezt1) &&
+ BEZT_ISSEL_ANY_HIDDENHANDLES(cu, bezt2))
{
/* check if need to join start of spline to end */
nu1 = BKE_nurb_copy(nu, cut + 1, 1);
@@ -6281,8 +5245,8 @@ static int curve_delete_segments(Object *obedit, const bool split)
bezt1 = nu->bezt;
bezt2 = &nu->bezt[1];
- if (BEZSELECTED_HIDDENHANDLES(cu, bezt1) &&
- BEZSELECTED_HIDDENHANDLES(cu, bezt2))
+ if (BEZT_ISSEL_ANY_HIDDENHANDLES(cu, bezt1) &&
+ BEZT_ISSEL_ANY_HIDDENHANDLES(cu, bezt2))
{
nu1 = BKE_nurb_copy(nu, 1, 1);
ED_curve_beztcpy(editnurb, nu1->bezt, bezt1, 1);
@@ -6292,8 +5256,8 @@ static int curve_delete_segments(Object *obedit, const bool split)
bezt1 = &nu->bezt[nu->pntsu - 1];
bezt2 = &nu->bezt[nu->pntsu - 2];
- if (BEZSELECTED_HIDDENHANDLES(cu, bezt1) &&
- BEZSELECTED_HIDDENHANDLES(cu, bezt2))
+ if (BEZT_ISSEL_ANY_HIDDENHANDLES(cu, bezt1) &&
+ BEZT_ISSEL_ANY_HIDDENHANDLES(cu, bezt2))
{
nu1 = BKE_nurb_copy(nu, 1, 1);
ED_curve_beztcpy(editnurb, nu1->bezt, bezt1, 1);
@@ -6551,7 +5515,6 @@ static int curve_delete_segments(Object *obedit, const bool split)
}
}
- nu->knotsu = nu->knotsv = NULL;
BKE_nurb_order_clamp_u(nu);
BKE_nurb_knot_calc_u(nu);
@@ -6648,13 +5611,13 @@ static int shade_smooth_exec(bContext *C, wmOperator *op)
Object *obedit = CTX_data_edit_object(C);
ListBase *editnurb = object_editcurve_get(obedit);
Nurb *nu;
- int clear = (strcmp(op->idname, "CURVE_OT_shade_flat") == 0);
+ int clear = (STREQ(op->idname, "CURVE_OT_shade_flat"));
if (obedit->type != OB_CURVE)
return OPERATOR_CANCELLED;
for (nu = editnurb->first; nu; nu = nu->next) {
- if (isNurbsel(nu)) {
+ if (ED_curve_nurb_select_check(obedit->data, nu)) {
if (!clear) nu->flag |= CU_SMOOTH;
else nu->flag &= ~CU_SMOOTH;
}
@@ -6812,7 +5775,7 @@ static int clear_tilt_exec(bContext *C, wmOperator *UNUSED(op))
bezt = nu->bezt;
a = nu->pntsu;
while (a--) {
- if (BEZSELECTED_HIDDENHANDLES(cu, bezt)) bezt->alfa = 0.0;
+ if (BEZT_ISSEL_ANY_HIDDENHANDLES(cu, bezt)) bezt->alfa = 0.0;
bezt++;
}
}
@@ -6889,6 +5852,7 @@ static void undoCurve_to_editCurve(void *ucu, void *UNUSED(edata), void *cu_v)
cu->actvert = undoCurve->actvert;
cu->actnu = undoCurve->actnu;
+ cu->flag = undoCurve->flag;
ED_curve_updateAnimPaths(cu);
}
@@ -6928,6 +5892,7 @@ static void *editCurve_to_undoCurve(void *UNUSED(edata), void *cu_v)
undoCurve->actvert = cu->actvert;
undoCurve->actnu = cu->actnu;
+ undoCurve->flag = cu->flag;
return undoCurve;
}
diff --git a/source/blender/editors/curve/editcurve_add.c b/source/blender/editors/curve/editcurve_add.c
index 8a3d4f3f4f5..5347ef05105 100644
--- a/source/blender/editors/curve/editcurve_add.c
+++ b/source/blender/editors/curve/editcurve_add.c
@@ -38,7 +38,7 @@
#include "BLI_blenlib.h"
#include "BLI_math.h"
-#include "BLF_translation.h"
+#include "BLT_translation.h"
#include "BKE_context.h"
#include "BKE_curve.h"
@@ -71,20 +71,20 @@ static const char *get_curve_defname(int type)
if ((type & CU_TYPE) == CU_BEZIER) {
switch (stype) {
- case CU_PRIM_CURVE: return CTX_DATA_(BLF_I18NCONTEXT_ID_CURVE, "BezierCurve");
- case CU_PRIM_CIRCLE: return CTX_DATA_(BLF_I18NCONTEXT_ID_CURVE, "BezierCircle");
- case CU_PRIM_PATH: return CTX_DATA_(BLF_I18NCONTEXT_ID_CURVE, "CurvePath");
+ case CU_PRIM_CURVE: return CTX_DATA_(BLT_I18NCONTEXT_ID_CURVE, "BezierCurve");
+ case CU_PRIM_CIRCLE: return CTX_DATA_(BLT_I18NCONTEXT_ID_CURVE, "BezierCircle");
+ case CU_PRIM_PATH: return CTX_DATA_(BLT_I18NCONTEXT_ID_CURVE, "CurvePath");
default:
- return CTX_DATA_(BLF_I18NCONTEXT_ID_CURVE, "Curve");
+ return CTX_DATA_(BLT_I18NCONTEXT_ID_CURVE, "Curve");
}
}
else {
switch (stype) {
- case CU_PRIM_CURVE: return CTX_DATA_(BLF_I18NCONTEXT_ID_CURVE, "NurbsCurve");
- case CU_PRIM_CIRCLE: return CTX_DATA_(BLF_I18NCONTEXT_ID_CURVE, "NurbsCircle");
- case CU_PRIM_PATH: return CTX_DATA_(BLF_I18NCONTEXT_ID_CURVE, "NurbsPath");
+ case CU_PRIM_CURVE: return CTX_DATA_(BLT_I18NCONTEXT_ID_CURVE, "NurbsCurve");
+ case CU_PRIM_CIRCLE: return CTX_DATA_(BLT_I18NCONTEXT_ID_CURVE, "NurbsCircle");
+ case CU_PRIM_PATH: return CTX_DATA_(BLT_I18NCONTEXT_ID_CURVE, "NurbsPath");
default:
- return CTX_DATA_(BLF_I18NCONTEXT_ID_CURVE, "Curve");
+ return CTX_DATA_(BLT_I18NCONTEXT_ID_CURVE, "Curve");
}
}
}
@@ -94,13 +94,13 @@ static const char *get_surf_defname(int type)
int stype = type & CU_PRIMITIVE;
switch (stype) {
- case CU_PRIM_CURVE: return CTX_DATA_(BLF_I18NCONTEXT_ID_CURVE, "SurfCurve");
- case CU_PRIM_CIRCLE: return CTX_DATA_(BLF_I18NCONTEXT_ID_CURVE, "SurfCircle");
- case CU_PRIM_PATCH: return CTX_DATA_(BLF_I18NCONTEXT_ID_CURVE, "SurfPatch");
- case CU_PRIM_SPHERE: return CTX_DATA_(BLF_I18NCONTEXT_ID_CURVE, "SurfSphere");
- case CU_PRIM_DONUT: return CTX_DATA_(BLF_I18NCONTEXT_ID_CURVE, "SurfTorus");
+ case CU_PRIM_CURVE: return CTX_DATA_(BLT_I18NCONTEXT_ID_CURVE, "SurfCurve");
+ case CU_PRIM_CIRCLE: return CTX_DATA_(BLT_I18NCONTEXT_ID_CURVE, "SurfCircle");
+ case CU_PRIM_PATCH: return CTX_DATA_(BLT_I18NCONTEXT_ID_CURVE, "SurfPatch");
+ case CU_PRIM_SPHERE: return CTX_DATA_(BLT_I18NCONTEXT_ID_CURVE, "SurfSphere");
+ case CU_PRIM_DONUT: return CTX_DATA_(BLT_I18NCONTEXT_ID_CURVE, "SurfTorus");
default:
- return CTX_DATA_(BLF_I18NCONTEXT_ID_CURVE, "Surface");
+ return CTX_DATA_(BLT_I18NCONTEXT_ID_CURVE, "Surface");
}
}
@@ -121,7 +121,7 @@ Nurb *add_nurbs_primitive(bContext *C, Object *obedit, float mat[4][4], int type
const float grid = 1.0f;
const int cutype = (type & CU_TYPE); // poly, bezier, nurbs, etc
const int stype = (type & CU_PRIMITIVE);
- const int force_3d = ((Curve *)obedit->data)->flag & CU_3D; /* could be adding to an existing 3D curve */
+ const bool force_3d = (((Curve *)obedit->data)->flag & CU_3D) != 0; /* could be adding to an existing 3D curve */
unit_m4(umat);
unit_m4(viewmat);
@@ -355,10 +355,10 @@ Nurb *add_nurbs_primitive(bContext *C, Object *obedit, float mat[4][4], int type
mul_mat3_m4_v3(mat, vec);
- ed_editnurb_translate_flag(editnurb, 1, vec);
- ed_editnurb_extrude_flag(cu->editnurb, 1);
+ ed_editnurb_translate_flag(editnurb, SELECT, vec);
+ ed_editnurb_extrude_flag(cu->editnurb, SELECT);
mul_v3_fl(vec, -2.0f);
- ed_editnurb_translate_flag(editnurb, 1, vec);
+ ed_editnurb_translate_flag(editnurb, SELECT, vec);
BLI_remlink(editnurb, nu);
@@ -460,7 +460,7 @@ Nurb *add_nurbs_primitive(bContext *C, Object *obedit, float mat[4][4], int type
if (nu) { /* should always be set */
nu->flag |= CU_SMOOTH;
- cu->actnu = BLI_countlist(editnurb);
+ cu->actnu = BLI_listbase_count(editnurb);
cu->actvert = CU_ACT_NONE;
BKE_nurb_test2D(nu);
@@ -488,9 +488,10 @@ static int curvesurf_prim_add(bContext *C, wmOperator *op, int type, int isSurf)
if (!isSurf) { /* adding curve */
if (obedit == NULL || obedit->type != OB_CURVE) {
+ const char *name = get_curve_defname(type);
Curve *cu;
- obedit = ED_object_add_type(C, OB_CURVE, loc, rot, true, layer);
+ obedit = ED_object_add_type(C, OB_CURVE, name, loc, rot, true, layer);
newob = true;
cu = (Curve *)obedit->data;
@@ -505,7 +506,8 @@ static int curvesurf_prim_add(bContext *C, wmOperator *op, int type, int isSurf)
}
else { /* adding surface */
if (obedit == NULL || obedit->type != OB_SURF) {
- obedit = ED_object_add_type(C, OB_SURF, loc, rot, true, layer);
+ const char *name = get_surf_defname(type);
+ obedit = ED_object_add_type(C, OB_SURF, name, loc, rot, true, layer);
newob = true;
}
else {
@@ -513,27 +515,13 @@ static int curvesurf_prim_add(bContext *C, wmOperator *op, int type, int isSurf)
}
}
- /* rename here, the undo stack checks name for valid undo pushes */
- if (newob) {
- if (obedit->type == OB_CURVE) {
- rename_id((ID *)obedit, get_curve_defname(type));
- rename_id((ID *)obedit->data, get_curve_defname(type));
- }
- else {
- rename_id((ID *)obedit, get_surf_defname(type));
- rename_id((ID *)obedit->data, get_surf_defname(type));
- }
- }
-
/* ED_object_add_type doesnt do an undo, is needed for redo operator on primitive */
if (newob && enter_editmode)
ED_undo_push(C, "Enter Editmode");
- ED_object_new_primitive_matrix(C, obedit, loc, rot, mat, false);
+ ED_object_new_primitive_matrix(C, obedit, loc, rot, mat);
dia = RNA_float_get(op->ptr, "radius");
- mat[0][0] *= dia;
- mat[1][1] *= dia;
- mat[2][2] *= dia;
+ mul_mat3_m4_fl(mat, dia);
nu = add_nurbs_primitive(C, obedit, mat, type, newob);
editnurb = object_editcurve_get(obedit);
diff --git a/source/blender/editors/curve/editcurve_select.c b/source/blender/editors/curve/editcurve_select.c
new file mode 100644
index 00000000000..0f3942b0c90
--- /dev/null
+++ b/source/blender/editors/curve/editcurve_select.c
@@ -0,0 +1,1728 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): John Roper
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/editors/curve/editcurve_select.c
+ * \ingroup edcurve
+ */
+
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_bitmap.h"
+#include "BLI_math.h"
+#include "BLI_rand.h"
+#include "BLI_heap.h"
+
+#include "BKE_context.h"
+#include "BKE_curve.h"
+#include "BKE_fcurve.h"
+#include "BKE_report.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "ED_screen.h"
+#include "ED_types.h"
+#include "ED_view3d.h"
+#include "ED_curve.h"
+
+#include "curve_intern.h"
+
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+
+
+/* returns 1 in case (de)selection was successful */
+bool select_beztriple(BezTriple *bezt, bool selstatus, short flag, eVisible_Types hidden)
+{
+ if ((bezt->hide == 0) || (hidden == HIDDEN)) {
+ if (selstatus == SELECT) { /* selects */
+ bezt->f1 |= flag;
+ bezt->f2 |= flag;
+ bezt->f3 |= flag;
+ return true;
+ }
+ else { /* deselects */
+ bezt->f1 &= ~flag;
+ bezt->f2 &= ~flag;
+ bezt->f3 &= ~flag;
+ return true;
+ }
+ }
+
+ return false;
+}
+
+/* returns 1 in case (de)selection was successful */
+bool select_bpoint(BPoint *bp, bool selstatus, short flag, bool hidden)
+{
+ if ((bp->hide == 0) || (hidden == 1)) {
+ if (selstatus == SELECT) {
+ bp->f1 |= flag;
+ return true;
+ }
+ else {
+ bp->f1 &= ~flag;
+ return true;
+ }
+ }
+
+ return false;
+}
+
+static bool swap_selection_beztriple(BezTriple *bezt)
+{
+ if (bezt->f2 & SELECT)
+ return select_beztriple(bezt, DESELECT, SELECT, VISIBLE);
+ else
+ return select_beztriple(bezt, SELECT, SELECT, VISIBLE);
+}
+
+static bool swap_selection_bpoint(BPoint *bp)
+{
+ if (bp->f1 & SELECT)
+ return select_bpoint(bp, DESELECT, SELECT, VISIBLE);
+ else
+ return select_bpoint(bp, SELECT, SELECT, VISIBLE);
+}
+
+bool ED_curve_nurb_select_check(Curve *cu, Nurb *nu)
+{
+ if (nu->type == CU_BEZIER) {
+ BezTriple *bezt;
+ int i;
+
+ for (i = nu->pntsu, bezt = nu->bezt; i--; bezt++) {
+ if (BEZT_ISSEL_ANY_HIDDENHANDLES(cu, bezt)) {
+ return true;
+ }
+ }
+ }
+ else {
+ BPoint *bp;
+ int i;
+
+ for (i = nu->pntsu * nu->pntsv, bp = nu->bp; i--; bp++) {
+ if (bp->f1 & SELECT) {
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+int ED_curve_nurb_select_count(Curve *cu, Nurb *nu)
+{
+ int sel = 0;
+
+ if (nu->type == CU_BEZIER) {
+ BezTriple *bezt;
+ int i;
+
+ for (i = nu->pntsu, bezt = nu->bezt; i--; bezt++) {
+ if (BEZT_ISSEL_ANY_HIDDENHANDLES(cu, bezt)) {
+ sel++;
+ }
+ }
+ }
+ else {
+ BPoint *bp;
+ int i;
+
+ for (i = nu->pntsu * nu->pntsv, bp = nu->bp; i--; bp++) {
+ if (bp->f1 & SELECT) {
+ sel++;
+ }
+ }
+ }
+
+ return sel;
+}
+
+void ED_curve_nurb_select_all(Nurb *nu)
+{
+ int i;
+
+ if (nu->bezt) {
+ BezTriple *bezt;
+ for (i = nu->pntsu, bezt = nu->bezt; i--; bezt++) {
+ if (bezt->hide == 0) {
+ BEZT_SEL_ALL(bezt);
+ }
+ }
+ }
+ else if (nu->bp) {
+ BPoint *bp;
+ for (i = nu->pntsu * nu->pntsv, bp = nu->bp; i--; bp++) {
+ if (bp->hide == 0) {
+ bp->f1 |= SELECT;
+ }
+ }
+ }
+}
+
+void ED_curve_select_all(EditNurb *editnurb)
+{
+ Nurb *nu;
+ for (nu = editnurb->nurbs.first; nu; nu = nu->next) {
+ ED_curve_nurb_select_all(nu);
+ }
+}
+
+void ED_curve_nurb_deselect_all(Nurb *nu)
+{
+ int i;
+
+ if (nu->bezt) {
+ BezTriple *bezt;
+ for (i = nu->pntsu, bezt = nu->bezt; i--; bezt++) {
+ BEZT_DESEL_ALL(bezt);
+ }
+ }
+ else if (nu->bp) {
+ BPoint *bp;
+ for (i = nu->pntsu * nu->pntsv, bp = nu->bp; i--; bp++) {
+ bp->f1 &= ~SELECT;
+ }
+ }
+}
+
+bool ED_curve_select_check(Curve *cu, struct EditNurb *editnurb)
+{
+ Nurb *nu;
+
+ for (nu = editnurb->nurbs.first; nu; nu = nu->next) {
+ if (ED_curve_nurb_select_check(cu, nu)) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+void ED_curve_deselect_all(EditNurb *editnurb)
+{
+ Nurb *nu;
+
+ for (nu = editnurb->nurbs.first; nu; nu = nu->next) {
+ ED_curve_nurb_deselect_all(nu);
+ }
+}
+
+void ED_curve_select_swap(EditNurb *editnurb, bool hide_handles)
+{
+ Nurb *nu;
+ BPoint *bp;
+ BezTriple *bezt;
+ int a;
+
+ for (nu = editnurb->nurbs.first; nu; nu = nu->next) {
+ if (nu->type == CU_BEZIER) {
+ bezt = nu->bezt;
+ a = nu->pntsu;
+ while (a--) {
+ if (bezt->hide == 0) {
+ bezt->f2 ^= SELECT; /* always do the center point */
+ if (!hide_handles) {
+ bezt->f1 ^= SELECT;
+ bezt->f3 ^= SELECT;
+ }
+ }
+ bezt++;
+ }
+ }
+ else {
+ bp = nu->bp;
+ a = nu->pntsu * nu->pntsv;
+ while (a--) {
+ swap_selection_bpoint(bp);
+ bp++;
+ }
+ }
+ }
+}
+
+/**
+ * \param next: -1/1 for prev/next
+ * \param cont: when true select continuously
+ * \param selstatus: inverts behavior
+ */
+static void select_adjacent_cp(
+ ListBase *editnurb, short next,
+ const bool cont, const bool selstatus)
+{
+ Nurb *nu;
+ BezTriple *bezt;
+ BPoint *bp;
+ int a;
+ bool lastsel = false;
+
+ if (next == 0) return;
+
+ for (nu = editnurb->first; nu; nu = nu->next) {
+ lastsel = false;
+ if (nu->type == CU_BEZIER) {
+ a = nu->pntsu;
+ bezt = nu->bezt;
+ if (next < 0) bezt = &nu->bezt[a - 1];
+ while (a--) {
+ if (a - abs(next) < 0) break;
+ if ((lastsel == 0) && (bezt->hide == 0) && ((bezt->f2 & SELECT) || (selstatus == DESELECT))) {
+ bezt += next;
+ if (!(bezt->f2 & SELECT) || (selstatus == DESELECT)) {
+ short sel = select_beztriple(bezt, selstatus, SELECT, VISIBLE);
+ if ((sel == 1) && (cont == 0)) lastsel = true;
+ }
+ }
+ else {
+ bezt += next;
+ lastsel = false;
+ }
+ /* move around in zigzag way so that we go through each */
+ bezt -= (next - next / abs(next));
+ }
+ }
+ else {
+ a = nu->pntsu * nu->pntsv;
+ bp = nu->bp;
+ if (next < 0) bp = &nu->bp[a - 1];
+ while (a--) {
+ if (a - abs(next) < 0) break;
+ if ((lastsel == 0) && (bp->hide == 0) && ((bp->f1 & SELECT) || (selstatus == DESELECT))) {
+ bp += next;
+ if (!(bp->f1 & SELECT) || (selstatus == DESELECT)) {
+ short sel = select_bpoint(bp, selstatus, SELECT, VISIBLE);
+ if ((sel == 1) && (cont == 0)) lastsel = true;
+ }
+ }
+ else {
+ bp += next;
+ lastsel = false;
+ }
+ /* move around in zigzag way so that we go through each */
+ bp -= (next - next / abs(next));
+ }
+ }
+ }
+}
+
+/**************** select start/end operators **************/
+
+/* (de)selects first or last of visible part of each Nurb depending on selFirst
+ * selFirst: defines the end of which to select
+ * doswap: defines if selection state of each first/last control point is swapped
+ * selstatus: selection status in case doswap is false
+ */
+static void selectend_nurb(Object *obedit, eEndPoint_Types selfirst, bool doswap, bool selstatus)
+{
+ ListBase *editnurb = object_editcurve_get(obedit);
+ Nurb *nu;
+ BPoint *bp;
+ BezTriple *bezt;
+ Curve *cu;
+ int a;
+
+ if (obedit == NULL) return;
+
+ cu = (Curve *)obedit->data;
+ cu->actvert = CU_ACT_NONE;
+
+ for (nu = editnurb->first; nu; nu = nu->next) {
+ if (nu->type == CU_BEZIER) {
+ a = nu->pntsu;
+
+ /* which point? */
+ if (selfirst == LAST) { /* select last */
+ bezt = &nu->bezt[a - 1];
+ }
+ else { /* select first */
+ bezt = nu->bezt;
+ }
+
+ while (a--) {
+ bool sel;
+ if (doswap) sel = swap_selection_beztriple(bezt);
+ else sel = select_beztriple(bezt, selstatus, SELECT, VISIBLE);
+
+ if (sel == true) break;
+ }
+ }
+ else {
+ a = nu->pntsu * nu->pntsv;
+
+ /* which point? */
+ if (selfirst == LAST) { /* select last */
+ bp = &nu->bp[a - 1];
+ }
+ else { /* select first */
+ bp = nu->bp;
+ }
+
+ while (a--) {
+ if (bp->hide == 0) {
+ bool sel;
+ if (doswap) sel = swap_selection_bpoint(bp);
+ else sel = select_bpoint(bp, selstatus, SELECT, VISIBLE);
+
+ if (sel == true) break;
+ }
+ }
+ }
+ }
+}
+
+static int de_select_first_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ Object *obedit = CTX_data_edit_object(C);
+
+ selectend_nurb(obedit, FIRST, true, DESELECT);
+ WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
+ BKE_curve_nurb_vert_active_validate(obedit->data);
+
+ return OPERATOR_FINISHED;
+}
+
+void CURVE_OT_de_select_first(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "(De)select First";
+ ot->idname = "CURVE_OT_de_select_first";
+ ot->description = "(De)select first of visible part of each NURBS";
+
+ /* api cfirstbacks */
+ ot->exec = de_select_first_exec;
+ ot->poll = ED_operator_editcurve;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+static int de_select_last_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ Object *obedit = CTX_data_edit_object(C);
+
+ selectend_nurb(obedit, LAST, true, DESELECT);
+ WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
+ BKE_curve_nurb_vert_active_validate(obedit->data);
+
+ return OPERATOR_FINISHED;
+}
+
+void CURVE_OT_de_select_last(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "(De)select Last";
+ ot->idname = "CURVE_OT_de_select_last";
+ ot->description = "(De)select last of visible part of each NURBS";
+
+ /* api clastbacks */
+ ot->exec = de_select_last_exec;
+ ot->poll = ED_operator_editcurve;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+static int de_select_all_exec(bContext *C, wmOperator *op)
+{
+ Object *obedit = CTX_data_edit_object(C);
+ Curve *cu = obedit->data;
+ int action = RNA_enum_get(op->ptr, "action");
+
+ if (action == SEL_TOGGLE) {
+ action = SEL_SELECT;
+ if (ED_curve_select_check(cu, cu->editnurb)) {
+ action = SEL_DESELECT;
+ }
+ }
+
+ switch (action) {
+ case SEL_SELECT:
+ ED_curve_select_all(cu->editnurb);
+ break;
+ case SEL_DESELECT:
+ ED_curve_deselect_all(cu->editnurb);
+ break;
+ case SEL_INVERT:
+ ED_curve_select_swap(cu->editnurb, (cu->drawflag & CU_HIDE_HANDLES) != 0);
+ break;
+ }
+
+ WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
+ BKE_curve_nurb_vert_active_validate(cu);
+
+ return OPERATOR_FINISHED;
+}
+
+void CURVE_OT_select_all(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "(De)select All";
+ ot->idname = "CURVE_OT_select_all";
+ ot->description = "(De)select all control points";
+
+ /* api callbacks */
+ ot->exec = de_select_all_exec;
+ ot->poll = ED_operator_editsurfcurve;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ WM_operator_properties_select_all(ot);
+}
+
+
+
+/***************** select linked operator ******************/
+
+static int select_linked_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ Object *obedit = CTX_data_edit_object(C);
+ Curve *cu = (Curve *)obedit->data;
+ EditNurb *editnurb = cu->editnurb;
+ ListBase *nurbs = &editnurb->nurbs;
+ Nurb *nu;
+
+ for (nu = nurbs->first; nu; nu = nu->next) {
+ if (ED_curve_nurb_select_check(cu, nu)) {
+ ED_curve_nurb_select_all(nu);
+ }
+ }
+
+ WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
+
+ return OPERATOR_FINISHED;
+}
+
+static int select_linked_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
+{
+ return select_linked_exec(C, op);
+}
+
+void CURVE_OT_select_linked(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Select Linked All";
+ ot->idname = "CURVE_OT_select_linked";
+ ot->description = "Select all control points linked to active one";
+
+ /* api callbacks */
+ ot->exec = select_linked_exec;
+ ot->invoke = select_linked_invoke;
+ ot->poll = ED_operator_editsurfcurve;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+}
+
+
+/***************** select linked pick operator ******************/
+
+static int select_linked_pick_invoke(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ Object *obedit = CTX_data_edit_object(C);
+ ViewContext vc;
+ Nurb *nu;
+ BezTriple *bezt;
+ BPoint *bp;
+ int a;
+ const bool select = !RNA_boolean_get(op->ptr, "deselect");
+
+ view3d_operator_needs_opengl(C);
+ view3d_set_viewcontext(C, &vc);
+
+ if (!ED_curve_pick_vert(&vc, 1, event->mval, &nu, &bezt, &bp, NULL)) {
+ return OPERATOR_CANCELLED;
+ }
+
+ if (bezt) {
+ a = nu->pntsu;
+ bezt = nu->bezt;
+ while (a--) {
+ select_beztriple(bezt, select, SELECT, VISIBLE);
+ bezt++;
+ }
+ }
+ else if (bp) {
+ a = nu->pntsu * nu->pntsv;
+ bp = nu->bp;
+ while (a--) {
+ select_bpoint(bp, select, SELECT, VISIBLE);
+ bp++;
+ }
+ }
+
+ WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
+ if (!select) {
+ BKE_curve_nurb_vert_active_validate(obedit->data);
+ }
+
+ return OPERATOR_FINISHED;
+}
+
+void CURVE_OT_select_linked_pick(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Select Linked";
+ ot->idname = "CURVE_OT_select_linked_pick";
+ ot->description = "Select all control points linked to already selected ones";
+
+ /* api callbacks */
+ ot->invoke = select_linked_pick_invoke;
+ ot->poll = ED_operator_editsurfcurve_region_view3d;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_boolean(ot->srna, "deselect", 0, "Deselect", "Deselect linked control points rather than selecting them");
+}
+
+/***************** select row operator **********************/
+
+static int select_row_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ Object *obedit = CTX_data_edit_object(C);
+ Curve *cu = obedit->data;
+ ListBase *editnurb = object_editcurve_get(obedit);
+ static BPoint *last = NULL;
+ static int direction = 0;
+ Nurb *nu = NULL;
+ BPoint *bp = NULL;
+ int u = 0, v = 0, a, b;
+
+ if (!BKE_curve_nurb_vert_active_get(cu, &nu, (void *)&bp))
+ return OPERATOR_CANCELLED;
+
+ if (last == bp) {
+ direction = 1 - direction;
+ BKE_nurbList_flag_set(editnurb, 0);
+ }
+ last = bp;
+
+ u = cu->actvert % nu->pntsu;
+ v = cu->actvert / nu->pntsu;
+ bp = nu->bp;
+ for (a = 0; a < nu->pntsv; a++) {
+ for (b = 0; b < nu->pntsu; b++, bp++) {
+ if (direction) {
+ if (a == v) select_bpoint(bp, SELECT, SELECT, VISIBLE);
+ }
+ else {
+ if (b == u) select_bpoint(bp, SELECT, SELECT, VISIBLE);
+ }
+ }
+ }
+
+ WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
+
+ return OPERATOR_FINISHED;
+}
+
+void CURVE_OT_select_row(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Select Control Point Row";
+ ot->idname = "CURVE_OT_select_row";
+ ot->description = "Select a row of control points including active one";
+
+ /* api callbacks */
+ ot->exec = select_row_exec;
+ ot->poll = ED_operator_editsurf;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+/***************** select next operator **********************/
+
+static int select_next_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ Object *obedit = CTX_data_edit_object(C);
+ ListBase *editnurb = object_editcurve_get(obedit);
+
+ select_adjacent_cp(editnurb, 1, 0, SELECT);
+ WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
+
+ return OPERATOR_FINISHED;
+}
+
+void CURVE_OT_select_next(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Select Next";
+ ot->idname = "CURVE_OT_select_next";
+ ot->description = "Select control points following already selected ones along the curves";
+
+ /* api callbacks */
+ ot->exec = select_next_exec;
+ ot->poll = ED_operator_editcurve;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+/***************** select previous operator **********************/
+
+static int select_previous_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ Object *obedit = CTX_data_edit_object(C);
+ ListBase *editnurb = object_editcurve_get(obedit);
+
+ select_adjacent_cp(editnurb, -1, 0, SELECT);
+ WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
+
+ return OPERATOR_FINISHED;
+}
+
+void CURVE_OT_select_previous(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Select Previous";
+ ot->idname = "CURVE_OT_select_previous";
+ ot->description = "Select control points preceding already selected ones along the curves";
+
+ /* api callbacks */
+ ot->exec = select_previous_exec;
+ ot->poll = ED_operator_editcurve;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+/***************** select more operator **********************/
+
+static int select_more_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ Object *obedit = CTX_data_edit_object(C);
+ ListBase *editnurb = object_editcurve_get(obedit);
+ Nurb *nu;
+ BPoint *bp, *tempbp;
+ int a;
+ short sel = 0;
+
+ /* note that NURBS surface is a special case because we mimic */
+ /* the behavior of "select more" of mesh tools. */
+ /* The algorithm is designed to work in planar cases so it */
+ /* may not be optimal always (example: end of NURBS sphere) */
+ if (obedit->type == OB_SURF) {
+ for (nu = editnurb->first; nu; nu = nu->next) {
+ BLI_bitmap *selbpoints;
+ a = nu->pntsu * nu->pntsv;
+ bp = nu->bp;
+ selbpoints = BLI_BITMAP_NEW(a, "selectlist");
+ while (a > 0) {
+ if ((!BLI_BITMAP_TEST(selbpoints, a)) && (bp->hide == 0) && (bp->f1 & SELECT)) {
+ /* upper control point */
+ if (a % nu->pntsu != 0) {
+ tempbp = bp - 1;
+ if (!(tempbp->f1 & SELECT)) select_bpoint(tempbp, SELECT, SELECT, VISIBLE);
+ }
+
+ /* left control point. select only if it is not selected already */
+ if (a - nu->pntsu > 0) {
+ sel = 0;
+ tempbp = bp + nu->pntsu;
+ if (!(tempbp->f1 & SELECT)) sel = select_bpoint(tempbp, SELECT, SELECT, VISIBLE);
+ /* make sure selected bpoint is discarded */
+ if (sel == 1) BLI_BITMAP_ENABLE(selbpoints, a - nu->pntsu);
+ }
+
+ /* right control point */
+ if (a + nu->pntsu < nu->pntsu * nu->pntsv) {
+ tempbp = bp - nu->pntsu;
+ if (!(tempbp->f1 & SELECT)) select_bpoint(tempbp, SELECT, SELECT, VISIBLE);
+ }
+
+ /* lower control point. skip next bp in case selection was made */
+ if (a % nu->pntsu != 1) {
+ sel = 0;
+ tempbp = bp + 1;
+ if (!(tempbp->f1 & SELECT)) sel = select_bpoint(tempbp, SELECT, SELECT, VISIBLE);
+ if (sel) {
+ bp++;
+ a--;
+ }
+ }
+ }
+
+ bp++;
+ a--;
+ }
+
+ MEM_freeN(selbpoints);
+ }
+ }
+ else {
+ select_adjacent_cp(editnurb, 1, 0, SELECT);
+ select_adjacent_cp(editnurb, -1, 0, SELECT);
+ }
+
+ WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
+
+ return OPERATOR_FINISHED;
+}
+
+void CURVE_OT_select_more(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Select More";
+ ot->idname = "CURVE_OT_select_more";
+ ot->description = "Select control points directly linked to already selected ones";
+
+ /* api callbacks */
+ ot->exec = select_more_exec;
+ ot->poll = ED_operator_editsurfcurve;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+/******************** select less operator *****************/
+
+/* basic method: deselect if control point doesn't have all neighbors selected */
+static int select_less_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ Object *obedit = CTX_data_edit_object(C);
+ ListBase *editnurb = object_editcurve_get(obedit);
+ Nurb *nu;
+ BPoint *bp;
+ BezTriple *bezt;
+ int a;
+ int sel = 0;
+ short lastsel = false;
+
+ if (obedit->type == OB_SURF) {
+ for (nu = editnurb->first; nu; nu = nu->next) {
+ BLI_bitmap *selbpoints;
+ a = nu->pntsu * nu->pntsv;
+ bp = nu->bp;
+ selbpoints = BLI_BITMAP_NEW(a, "selectlist");
+ while (a--) {
+ if ((bp->hide == 0) && (bp->f1 & SELECT)) {
+ sel = 0;
+
+ /* check if neighbors have been selected */
+ /* edges of surface are an exception */
+ if ((a + 1) % nu->pntsu == 0) {
+ sel++;
+ }
+ else {
+ bp--;
+ if (BLI_BITMAP_TEST(selbpoints, a + 1) || ((bp->hide == 0) && (bp->f1 & SELECT))) sel++;
+ bp++;
+ }
+
+ if ((a + 1) % nu->pntsu == 1) {
+ sel++;
+ }
+ else {
+ bp++;
+ if ((bp->hide == 0) && (bp->f1 & SELECT)) sel++;
+ bp--;
+ }
+
+ if (a + 1 > nu->pntsu * nu->pntsv - nu->pntsu) {
+ sel++;
+ }
+ else {
+ bp -= nu->pntsu;
+ if (BLI_BITMAP_TEST(selbpoints, a + nu->pntsu) || ((bp->hide == 0) && (bp->f1 & SELECT))) sel++;
+ bp += nu->pntsu;
+ }
+
+ if (a < nu->pntsu) {
+ sel++;
+ }
+ else {
+ bp += nu->pntsu;
+ if ((bp->hide == 0) && (bp->f1 & SELECT)) sel++;
+ bp -= nu->pntsu;
+ }
+
+ if (sel != 4) {
+ select_bpoint(bp, DESELECT, SELECT, VISIBLE);
+ BLI_BITMAP_ENABLE(selbpoints, a);
+ }
+ }
+ else {
+ lastsel = false;
+ }
+
+ bp++;
+ }
+
+ MEM_freeN(selbpoints);
+ }
+ }
+ else {
+ for (nu = editnurb->first; nu; nu = nu->next) {
+ lastsel = false;
+ /* check what type of curve/nurb it is */
+ if (nu->type == CU_BEZIER) {
+ a = nu->pntsu;
+ bezt = nu->bezt;
+ while (a--) {
+ if ((bezt->hide == 0) && (bezt->f2 & SELECT)) {
+ sel = (lastsel == 1);
+
+ /* check if neighbors have been selected */
+ /* first and last are exceptions */
+ if (a == nu->pntsu - 1) {
+ sel++;
+ }
+ else {
+ bezt--;
+ if ((bezt->hide == 0) && (bezt->f2 & SELECT)) sel++;
+ bezt++;
+ }
+
+ if (a == 0) {
+ sel++;
+ }
+ else {
+ bezt++;
+ if ((bezt->hide == 0) && (bezt->f2 & SELECT)) sel++;
+ bezt--;
+ }
+
+ if (sel != 2) {
+ select_beztriple(bezt, DESELECT, SELECT, VISIBLE);
+ lastsel = true;
+ }
+ else {
+ lastsel = false;
+ }
+ }
+ else {
+ lastsel = false;
+ }
+
+ bezt++;
+ }
+ }
+ else {
+ a = nu->pntsu * nu->pntsv;
+ bp = nu->bp;
+ while (a--) {
+ if ((lastsel == 0) && (bp->hide == 0) && (bp->f1 & SELECT)) {
+ if (lastsel != 0) sel = 1;
+ else sel = 0;
+
+ /* first and last are exceptions */
+ if (a == nu->pntsu * nu->pntsv - 1) {
+ sel++;
+ }
+ else {
+ bp--;
+ if ((bp->hide == 0) && (bp->f1 & SELECT)) sel++;
+ bp++;
+ }
+
+ if (a == 0) {
+ sel++;
+ }
+ else {
+ bp++;
+ if ((bp->hide == 0) && (bp->f1 & SELECT)) sel++;
+ bp--;
+ }
+
+ if (sel != 2) {
+ select_bpoint(bp, DESELECT, SELECT, VISIBLE);
+ lastsel = true;
+ }
+ else {
+ lastsel = false;
+ }
+ }
+ else {
+ lastsel = false;
+ }
+
+ bp++;
+ }
+ }
+ }
+ }
+
+ WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
+ BKE_curve_nurb_vert_active_validate(obedit->data);
+
+ return OPERATOR_FINISHED;
+}
+
+void CURVE_OT_select_less(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Select Less";
+ ot->idname = "CURVE_OT_select_less";
+ ot->description = "Reduce current selection by deselecting boundary elements";
+
+ /* api callbacks */
+ ot->exec = select_less_exec;
+ ot->poll = ED_operator_editsurfcurve;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+/********************** select random *********************/
+
+static void curve_select_random(ListBase *editnurb, float randfac, bool select)
+{
+ Nurb *nu;
+ BezTriple *bezt;
+ BPoint *bp;
+ int a;
+
+ for (nu = editnurb->first; nu; nu = nu->next) {
+ if (nu->type == CU_BEZIER) {
+ bezt = nu->bezt;
+ a = nu->pntsu;
+ while (a--) {
+ if (!bezt->hide) {
+ if (BLI_frand() < randfac) {
+ select_beztriple(bezt, select, SELECT, VISIBLE);
+ }
+ }
+ bezt++;
+ }
+ }
+ else {
+ bp = nu->bp;
+ a = nu->pntsu * nu->pntsv;
+
+ while (a--) {
+ if (!bp->hide) {
+ if (BLI_frand() < randfac) {
+ select_bpoint(bp, select, SELECT, VISIBLE);
+ }
+ }
+ bp++;
+ }
+ }
+ }
+}
+
+static int curve_select_random_exec(bContext *C, wmOperator *op)
+{
+ Object *obedit = CTX_data_edit_object(C);
+ ListBase *editnurb = object_editcurve_get(obedit);
+ const bool select = (RNA_enum_get(op->ptr, "action") == SEL_SELECT);
+ const float randfac = RNA_float_get(op->ptr, "percent") / 100.0f;
+
+ curve_select_random(editnurb, randfac, select);
+ BKE_curve_nurb_vert_active_validate(obedit->data);
+
+ WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
+
+ return OPERATOR_FINISHED;
+}
+
+void CURVE_OT_select_random(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Select Random";
+ ot->idname = "CURVE_OT_select_random";
+ ot->description = "Randomly select some control points";
+
+ /* api callbacks */
+ ot->exec = curve_select_random_exec;
+ ot->poll = ED_operator_editsurfcurve;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_float_percentage(ot->srna, "percent", 50.f, 0.0f, 100.0f,
+ "Percent", "Percentage of elements to select randomly", 0.0f, 100.0f);
+ WM_operator_properties_select_action_simple(ot, SEL_SELECT);
+}
+
+/********************* every nth number of point *******************/
+
+static void select_nth_bezt(Nurb *nu, BezTriple *bezt, int nth, int skip, int offset)
+{
+ int a, start;
+
+ start = bezt - nu->bezt;
+ a = nu->pntsu;
+ bezt = &nu->bezt[a - 1];
+
+ while (a--) {
+ const int depth = abs(start - a);
+ if ((offset + depth) % (skip + nth) >= skip) {
+ select_beztriple(bezt, DESELECT, SELECT, HIDDEN);
+ }
+
+ bezt--;
+ }
+}
+
+static void select_nth_bp(Nurb *nu, BPoint *bp, int nth, int skip, int offset)
+{
+ int a, startrow, startpnt;
+ int row, pnt;
+
+ startrow = (bp - nu->bp) / nu->pntsu;
+ startpnt = (bp - nu->bp) % nu->pntsu;
+
+ a = nu->pntsu * nu->pntsv;
+ bp = &nu->bp[a - 1];
+ row = nu->pntsv - 1;
+ pnt = nu->pntsu - 1;
+
+ while (a--) {
+ const int depth = abs(pnt - startpnt) + abs(row - startrow);
+ if ((offset + depth) % (skip + nth) >= skip) {
+ select_bpoint(bp, DESELECT, SELECT, HIDDEN);
+ }
+
+ pnt--;
+ if (pnt < 0) {
+ pnt = nu->pntsu - 1;
+ row--;
+ }
+
+ bp--;
+ }
+}
+
+bool ED_curve_select_nth(Curve *cu, int nth, int skip, int offset)
+{
+ Nurb *nu = NULL;
+ void *vert = NULL;
+
+ if (!BKE_curve_nurb_vert_active_get(cu, &nu, &vert))
+ return false;
+
+ if (nu->bezt) {
+ select_nth_bezt(nu, vert, nth, skip, offset);
+ }
+ else {
+ select_nth_bp(nu, vert, nth, skip, offset);
+ }
+
+ return true;
+}
+
+static int select_nth_exec(bContext *C, wmOperator *op)
+{
+ Object *obedit = CTX_data_edit_object(C);
+ const int nth = RNA_int_get(op->ptr, "nth") - 1;
+ const int skip = RNA_int_get(op->ptr, "skip");
+ int offset = RNA_int_get(op->ptr, "offset");
+
+ /* so input of offset zero ends up being (nth - 1) */
+ offset = mod_i(offset, nth + skip);
+
+ if (!ED_curve_select_nth(obedit->data, nth, skip, offset)) {
+ if (obedit->type == OB_SURF) {
+ BKE_report(op->reports, RPT_ERROR, "Surface has not got active point");
+ }
+ else {
+ BKE_report(op->reports, RPT_ERROR, "Curve has not got active point");
+ }
+
+ return OPERATOR_CANCELLED;
+ }
+
+ WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
+
+ return OPERATOR_FINISHED;
+}
+
+void CURVE_OT_select_nth(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Checker Deselect";
+ ot->description = "Deselect every other vertex";
+ ot->idname = "CURVE_OT_select_nth";
+
+ /* api callbacks */
+ ot->exec = select_nth_exec;
+ ot->poll = ED_operator_editsurfcurve;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ RNA_def_int(ot->srna, "nth", 2, 2, INT_MAX, "Nth Selection", "", 2, 100);
+ RNA_def_int(ot->srna, "skip", 1, 1, INT_MAX, "Skip", "", 1, 100);
+ RNA_def_int(ot->srna, "offset", 0, INT_MIN, INT_MAX, "Offset", "", -100, 100);
+}
+
+
+/* -------------------------------------------------------------------- */
+/* Select Similar */
+
+/** \name Select Similar
+ * \{ */
+
+enum {
+ SIM_CMP_EQ = 0,
+ SIM_CMP_GT,
+ SIM_CMP_LT,
+};
+
+static EnumPropertyItem curve_prop_similar_compare_types[] = {
+ {SIM_CMP_EQ, "EQUAL", 0, "Equal", ""},
+ {SIM_CMP_GT, "GREATER", 0, "Greater", ""},
+ {SIM_CMP_LT, "LESS", 0, "Less", ""},
+
+ {0, NULL, 0, NULL, NULL}
+};
+
+enum {
+ SIMCURHAND_TYPE = 0,
+ SIMCURHAND_RADIUS,
+ SIMCURHAND_WEIGHT,
+ SIMCURHAND_DIRECTION,
+};
+
+static EnumPropertyItem curve_prop_similar_types[] = {
+ {SIMCURHAND_TYPE, "TYPE", 0, "Type", ""},
+ {SIMCURHAND_RADIUS, "RADIUS", 0, "Radius", ""},
+ {SIMCURHAND_WEIGHT, "WEIGHT", 0, "Weight", ""},
+ {SIMCURHAND_DIRECTION, "DIRECTION", 0, "Direction", ""},
+ {0, NULL, 0, NULL, NULL}
+};
+
+static int curve_select_similar_cmp_fl(const float delta, const float thresh, const int compare)
+{
+ switch (compare) {
+ case SIM_CMP_EQ:
+ return (fabsf(delta) <= thresh);
+ case SIM_CMP_GT:
+ return ((delta + thresh) >= 0.0f);
+ case SIM_CMP_LT:
+ return ((delta - thresh) <= 0.0f);
+ default:
+ BLI_assert(0);
+ return 0;
+ }
+}
+
+
+static void curve_select_similar_direction__bezt(Nurb *nu, const float dir_ref[3], float angle_cos)
+{
+ BezTriple *bezt;
+ int i;
+
+ for (i = nu->pntsu, bezt = nu->bezt; i--; bezt++) {
+ if (!bezt->hide) {
+ float dir[3];
+ BKE_nurb_bezt_calc_normal(nu, bezt, dir);
+ if (fabsf(dot_v3v3(dir_ref, dir)) >= angle_cos) {
+ select_beztriple(bezt, SELECT, SELECT, VISIBLE);
+ }
+ }
+ }
+}
+
+static void curve_select_similar_direction__bp(Nurb *nu, const float dir_ref[3], float angle_cos)
+{
+ BPoint *bp;
+ int i;
+
+ for (i = nu->pntsu * nu->pntsv, bp = nu->bp; i--; bp++) {
+ if (!bp->hide) {
+ float dir[3];
+ BKE_nurb_bpoint_calc_normal(nu, bp, dir);
+ if (fabsf(dot_v3v3(dir_ref, dir)) >= angle_cos) {
+ select_bpoint(bp, SELECT, SELECT, VISIBLE);
+ }
+ }
+ }
+}
+
+static bool curve_select_similar_direction(ListBase *editnurb, Curve *cu, float thresh)
+{
+ Nurb *nu, *act_nu;
+ void *act_vert;
+ float dir[3];
+ float angle_cos;
+
+ if (!BKE_curve_nurb_vert_active_get(cu, &act_nu, &act_vert)) {
+ return false;
+ }
+
+ if (act_nu->type == CU_BEZIER) {
+ BKE_nurb_bezt_calc_normal(act_nu, act_vert, dir);
+ }
+ else {
+ BKE_nurb_bpoint_calc_normal(act_nu, act_vert, dir);
+ }
+
+ /* map 0-1 to radians, 'cos' for comparison */
+ angle_cos = cosf(thresh * (float)M_PI_2);
+
+ for (nu = editnurb->first; nu; nu = nu->next) {
+ if (nu->type == CU_BEZIER) {
+ curve_select_similar_direction__bezt(nu, dir, angle_cos);
+ }
+ else {
+ curve_select_similar_direction__bp(nu, dir, angle_cos);
+ }
+ }
+
+ return true;
+}
+
+static void curve_select_similar_radius__bezt(Nurb *nu, float radius_ref, int compare, float thresh)
+{
+ BezTriple *bezt;
+ int i;
+
+ for (i = nu->pntsu, bezt = nu->bezt; i--; bezt++) {
+ if (!bezt->hide) {
+ if (curve_select_similar_cmp_fl(bezt->radius - radius_ref, thresh, compare)) {
+ select_beztriple(bezt, SELECT, SELECT, VISIBLE);
+ }
+ }
+ }
+}
+
+static void curve_select_similar_radius__bp(Nurb *nu, float radius_ref, int compare, float thresh)
+{
+ BPoint *bp;
+ int i;
+
+ for (i = nu->pntsu * nu->pntsv, bp = nu->bp; i--; bp++) {
+ if (!bp->hide) {
+ if (curve_select_similar_cmp_fl(bp->radius - radius_ref, thresh, compare)) {
+ select_bpoint(bp, SELECT, SELECT, VISIBLE);
+ }
+ }
+ }
+}
+
+static bool curve_select_similar_radius(ListBase *editnurb, Curve *cu, float compare, float thresh)
+{
+ Nurb *nu, *act_nu;
+ void *act_vert;
+ float radius_ref;
+
+ if (!BKE_curve_nurb_vert_active_get(cu, &act_nu, &act_vert)) {
+ return false;
+ }
+
+ if (act_nu->type == CU_BEZIER) {
+ radius_ref = ((BezTriple *)act_vert)->radius;
+ }
+ else {
+ radius_ref = ((BPoint *)act_vert)->radius;
+ }
+
+ /* make relative */
+ thresh *= radius_ref;
+
+ for (nu = editnurb->first; nu; nu = nu->next) {
+ if (nu->type == CU_BEZIER) {
+ curve_select_similar_radius__bezt(nu, radius_ref, compare, thresh);
+ }
+ else {
+ curve_select_similar_radius__bp(nu, radius_ref, compare, thresh);
+ }
+ }
+
+ return true;
+}
+
+static void curve_select_similar_weight__bezt(Nurb *nu, float weight_ref, int compare, float thresh)
+{
+ BezTriple *bezt;
+ int i;
+
+ for (i = nu->pntsu, bezt = nu->bezt; i--; bezt++) {
+ if (!bezt->hide) {
+ if (curve_select_similar_cmp_fl(bezt->weight - weight_ref, thresh, compare)) {
+ select_beztriple(bezt, SELECT, SELECT, VISIBLE);
+ }
+ }
+ }
+}
+
+static void curve_select_similar_weight__bp(Nurb *nu, float weight_ref, int compare, float thresh)
+{
+ BPoint *bp;
+ int i;
+
+ for (i = nu->pntsu * nu->pntsv, bp = nu->bp; i--; bp++) {
+ if (!bp->hide) {
+ if (curve_select_similar_cmp_fl(bp->weight - weight_ref, thresh, compare)) {
+ select_bpoint(bp, SELECT, SELECT, VISIBLE);
+ }
+ }
+ }
+}
+
+static bool curve_select_similar_weight(ListBase *editnurb, Curve *cu, float compare, float thresh)
+{
+ Nurb *nu, *act_nu;
+ void *act_vert;
+ float weight_ref;
+
+ if (!BKE_curve_nurb_vert_active_get(cu, &act_nu, &act_vert))
+ return false;
+
+ if (act_nu->type == CU_BEZIER) {
+ weight_ref = ((BezTriple *)act_vert)->weight;
+ }
+ else {
+ weight_ref = ((BPoint *)act_vert)->weight;
+ }
+
+ for (nu = editnurb->first; nu; nu = nu->next) {
+ if (nu->type == CU_BEZIER) {
+ curve_select_similar_weight__bezt(nu, weight_ref, compare, thresh);
+ }
+ else {
+ curve_select_similar_weight__bp(nu, weight_ref, compare, thresh);
+ }
+ }
+
+ return true;
+}
+
+static bool curve_select_similar_type(ListBase *editnurb, Curve *cu)
+{
+ Nurb *nu, *act_nu;
+ int type_ref;
+
+ /* Get active nurb type */
+ act_nu = BKE_curve_nurb_active_get(cu);
+
+ if (!act_nu)
+ return false;
+
+ /* Get the active nurb type */
+ type_ref = act_nu->type;
+
+ for (nu = editnurb->first; nu; nu = nu->next) {
+ if (nu->type == type_ref) {
+ ED_curve_nurb_select_all(nu);
+ }
+ }
+
+ return true;
+}
+
+static int curve_select_similar_exec(bContext *C, wmOperator *op)
+{
+ Object *obedit = CTX_data_edit_object(C);
+ Curve *cu = obedit->data;
+ ListBase *editnurb = object_editcurve_get(obedit);
+ bool changed = false;
+
+ /* Get props */
+ const int type = RNA_enum_get(op->ptr, "type");
+ const float thresh = RNA_float_get(op->ptr, "threshold");
+ const int compare = RNA_enum_get(op->ptr, "compare");
+
+ switch (type) {
+ case SIMCURHAND_TYPE:
+ changed = curve_select_similar_type(editnurb, cu);
+ break;
+ case SIMCURHAND_RADIUS:
+ changed = curve_select_similar_radius(editnurb, cu, compare, thresh);
+ break;
+ case SIMCURHAND_WEIGHT:
+ changed = curve_select_similar_weight(editnurb, cu, compare, thresh);
+ break;
+ case SIMCURHAND_DIRECTION:
+ changed = curve_select_similar_direction(editnurb, cu, thresh);
+ break;
+ }
+
+ if (changed) {
+ WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
+ return OPERATOR_FINISHED;
+ }
+ else {
+ return OPERATOR_CANCELLED;
+ }
+}
+
+void CURVE_OT_select_similar(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Select Similar";
+ ot->idname = "CURVE_OT_select_similar";
+ ot->description = "Select similar curve points by property type";
+
+ /* api callbacks */
+ ot->invoke = WM_menu_invoke;
+ ot->exec = curve_select_similar_exec;
+ ot->poll = ED_operator_editsurfcurve;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ ot->prop = RNA_def_enum(ot->srna, "type", curve_prop_similar_types, SIMCURHAND_WEIGHT, "Type", "");
+ RNA_def_enum(ot->srna, "compare", curve_prop_similar_compare_types, SIM_CMP_EQ, "Compare", "");
+ RNA_def_float(ot->srna, "threshold", 0.1, 0.0, FLT_MAX, "Threshold", "", 0.0, 100.0);
+}
+
+/** \} */
+
+
+/* -------------------------------------------------------------------- */
+/* Select Shortest Path */
+
+/** \name Select Path
+ * \{ */
+
+static float curve_calc_dist_pair(const Nurb *nu, int a, int b)
+{
+ const float *a_fl, *b_fl;
+
+ if (nu->type == CU_BEZIER) {
+ a_fl = nu->bezt[a].vec[1];
+ b_fl = nu->bezt[b].vec[1];
+ }
+ else {
+ a_fl = nu->bp[a].vec;
+ b_fl = nu->bp[b].vec;
+ }
+
+ return len_v3v3(a_fl, b_fl);
+}
+
+static float curve_calc_dist_span(Nurb *nu, int vert_src, int vert_dst)
+{
+ const int u = nu->pntsu;
+ int i_prev, i;
+ float dist = 0.0f;
+
+ BLI_assert(nu->pntsv == 1);
+
+ i_prev = vert_src;
+ i = (i_prev + 1) % u;
+
+ while (true) {
+ dist += curve_calc_dist_pair(nu, i_prev, i);
+
+ if (i == vert_dst) {
+ break;
+ }
+ i = (i + 1) % u;
+ }
+ return dist;
+}
+
+static void curve_select_shortest_path_curve(Nurb *nu, int vert_src, int vert_dst)
+{
+ const int u = nu->pntsu;
+ int i;
+
+ if (vert_src > vert_dst) {
+ SWAP(int, vert_src, vert_dst);
+ }
+
+ if (nu->flagu & CU_NURB_CYCLIC) {
+ if (curve_calc_dist_span(nu, vert_src, vert_dst) >
+ curve_calc_dist_span(nu, vert_dst, vert_src))
+ {
+ SWAP(int, vert_src, vert_dst);
+ }
+ }
+
+ i = vert_src;
+ while (true) {
+ if (nu->type & CU_BEZIER) {
+ select_beztriple(&nu->bezt[i], SELECT, SELECT, HIDDEN);
+ }
+ else {
+ select_bpoint(&nu->bp[i], SELECT, SELECT, HIDDEN);
+ }
+
+ if (i == vert_dst) {
+ break;
+ }
+ i = (i + 1) % u;
+ }
+}
+
+static void curve_select_shortest_path_surf(Nurb *nu, int vert_src, int vert_dst)
+{
+ Heap *heap;
+
+ int i, vert_curr;
+
+ int totu = nu->pntsu;
+ int totv = nu->pntsv;
+ int vert_num = totu * totv;
+
+ /* custom data */
+ struct PointAdj {
+ int vert, vert_prev;
+ float cost;
+ } *data;
+
+ /* init connectivity data */
+ data = MEM_mallocN(sizeof(*data) * vert_num, __func__);
+ for (i = 0; i < vert_num; i++) {
+ data[i].vert = i;
+ data[i].vert_prev = -1;
+ data[i].cost = FLT_MAX;
+ }
+
+ /* init heap */
+ heap = BLI_heap_new();
+
+ BLI_heap_insert(heap, 0.0f, &data[vert_src].vert);
+ data[vert_src].cost = 0.0f;
+ data[vert_src].vert_prev = vert_src; /* nop */
+
+ while (!BLI_heap_is_empty(heap)) {
+ int axis, sign;
+ int u, v;
+
+ vert_curr = *((int *)BLI_heap_popmin(heap));
+ if (vert_curr == vert_dst) {
+ break;
+ }
+
+ BKE_nurb_index_to_uv(nu, vert_curr, &u, &v);
+
+ /* loop over 4 adjacent verts */
+ for (sign = -1; sign != 3; sign += 2) {
+ for (axis = 0; axis != 2; axis += 1) {
+ int uv_other[2] = {u, v};
+ int vert_other;
+
+ uv_other[axis] += sign;
+
+ vert_other = BKE_nurb_index_from_uv(nu, uv_other[0], uv_other[1]);
+ if (vert_other != -1) {
+ const float dist = data[vert_curr].cost + curve_calc_dist_pair(nu, vert_curr, vert_other);
+
+ if (data[vert_other].cost > dist) {
+ data[vert_other].cost = dist;
+ if (data[vert_other].vert_prev == -1) {
+ BLI_heap_insert(heap, data[vert_other].cost, &data[vert_other].vert);
+ }
+ data[vert_other].vert_prev = vert_curr;
+ }
+ }
+
+ }
+ }
+
+ }
+
+ BLI_heap_free(heap, NULL);
+
+ if (vert_curr == vert_dst) {
+ i = 0;
+ while (vert_curr != vert_src && i++ < vert_num) {
+ if (nu->type == CU_BEZIER) {
+ select_beztriple(&nu->bezt[vert_curr], SELECT, SELECT, HIDDEN);
+ }
+ else {
+ select_bpoint(&nu->bp[vert_curr], SELECT, SELECT, HIDDEN);
+ }
+ vert_curr = data[vert_curr].vert_prev;
+ }
+ }
+
+ MEM_freeN(data);
+}
+
+static int edcu_shortest_path_pick_invoke(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ Object *obedit = CTX_data_edit_object(C);
+ Curve *cu = obedit->data;
+ Nurb *nu_src = BKE_curve_nurb_active_get(cu);
+ int vert_src = cu->actvert;
+
+ ViewContext vc;
+ Nurb *nu_dst;
+ BezTriple *bezt_dst;
+ BPoint *bp_dst;
+ int vert_dst;
+ void *vert_dst_p;
+
+ if (vert_src == CU_ACT_NONE) {
+ return OPERATOR_PASS_THROUGH;
+ }
+
+ view3d_operator_needs_opengl(C);
+ view3d_set_viewcontext(C, &vc);
+
+ if (!ED_curve_pick_vert(&vc, 1, event->mval, &nu_dst, &bezt_dst, &bp_dst, NULL)) {
+ return OPERATOR_PASS_THROUGH;
+ }
+
+ if (nu_src != nu_dst) {
+ BKE_report(op->reports, RPT_ERROR, "Control point belongs to another spline");
+ return OPERATOR_CANCELLED;
+ }
+
+ vert_dst_p = bezt_dst ? (void *)bezt_dst : (void *)bp_dst;
+ vert_dst = BKE_curve_nurb_vert_index_get(nu_dst, vert_dst_p);
+ if (vert_src == vert_dst) {
+ return OPERATOR_CANCELLED;
+ }
+
+ if ((obedit->type == OB_SURF) && (nu_src->pntsv > 1)) {
+ curve_select_shortest_path_surf(nu_src, vert_src, vert_dst);
+ }
+ else {
+ curve_select_shortest_path_curve(nu_src, vert_src, vert_dst);
+ }
+
+ BKE_curve_nurb_vert_active_set(cu, nu_dst, vert_dst_p);
+
+ WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
+ return OPERATOR_FINISHED;
+}
+
+void CURVE_OT_shortest_path_pick(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Pick Shortest Path";
+ ot->idname = "CURVE_OT_shortest_path_pick";
+ ot->description = "Select shortest path between two selections";
+
+ /* api callbacks */
+ ot->invoke = edcu_shortest_path_pick_invoke;
+ ot->poll = ED_operator_editsurfcurve_region_view3d;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+/** \} */
diff --git a/source/blender/editors/curve/editfont.c b/source/blender/editors/curve/editfont.c
index 4655deec4c4..ea6b6154be8 100644
--- a/source/blender/editors/curve/editfont.c
+++ b/source/blender/editors/curve/editfont.c
@@ -275,57 +275,6 @@ static void text_update_edited(bContext *C, Object *obedit, int mode)
WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
}
-/********************** insert lorem operator *********************/
-
-static int insert_lorem_exec(bContext *C, wmOperator *UNUSED(op))
-{
- Object *obedit = CTX_data_edit_object(C);
- const char *p, *p2;
- int i;
- static const char *lastlorem = NULL;
-
- if (lastlorem)
- p = lastlorem;
- else
- p = ED_lorem;
-
- i = rand() / (RAND_MAX / 6) + 4;
-
- for (p2 = p; *p2 && i; p2++) {
- insert_into_textbuf(obedit, *p2);
-
- if (*p2 == '.')
- i--;
- }
-
- lastlorem = p2 + 1;
- if (strlen(lastlorem) < 5)
- lastlorem = ED_lorem;
-
- insert_into_textbuf(obedit, '\n');
- insert_into_textbuf(obedit, '\n');
-
- DAG_id_tag_update(obedit->data, 0);
- WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
-
- return OPERATOR_FINISHED;
-}
-
-void FONT_OT_insert_lorem(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Insert Lorem";
- ot->description = "Insert placeholder text";
- ot->idname = "FONT_OT_insert_lorem";
-
- /* api callbacks */
- ot->exec = insert_lorem_exec;
- ot->poll = ED_operator_editfont;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-}
-
/* -------------------------------------------------------------------- */
/* Generic Paste Functions */
@@ -500,8 +449,8 @@ void FONT_OT_text_paste_from_file(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
/* properties */
- WM_operator_properties_filesel(ot, FOLDERFILE | TEXTFILE, FILE_SPECIAL, FILE_OPENFILE,
- WM_FILESEL_FILEPATH, FILE_DEFAULTDISPLAY);
+ WM_operator_properties_filesel(ot, FILE_TYPE_FOLDER | FILE_TYPE_TEXT, FILE_SPECIAL, FILE_OPENFILE,
+ WM_FILESEL_FILEPATH, FILE_DEFAULTDISPLAY, FILE_SORT_ALPHA);
}
@@ -558,8 +507,8 @@ void FONT_OT_text_paste_from_clipboard(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
/* properties */
- WM_operator_properties_filesel(ot, FOLDERFILE | TEXTFILE, FILE_SPECIAL, FILE_OPENFILE,
- WM_FILESEL_FILEPATH, FILE_DEFAULTDISPLAY);
+ WM_operator_properties_filesel(ot, FILE_TYPE_FOLDER | FILE_TYPE_TEXT, FILE_SPECIAL, FILE_OPENFILE,
+ WM_FILESEL_FILEPATH, FILE_DEFAULTDISPLAY, FILE_SORT_ALPHA);
}
/******************* text to object operator ********************/
@@ -577,7 +526,7 @@ static void txt_add_object(bContext *C, TextLine *firstline, int totline, const
int a;
float rot[3] = {0.f, 0.f, 0.f};
- obedit = BKE_object_add(bmain, scene, OB_FONT);
+ obedit = BKE_object_add(bmain, scene, OB_FONT, NULL);
base = scene->basact;
/* seems to assume view align ? TODO - look into this, could be an operator option */
@@ -668,7 +617,7 @@ void ED_text_to_object(bContext *C, Text *text, const bool split_lines)
offset[1] = 0.0f;
offset[2] = 0.0f;
- txt_add_object(C, text->lines.first, BLI_countlist(&text->lines), offset);
+ txt_add_object(C, text->lines.first, BLI_listbase_count(&text->lines), offset);
}
}
@@ -1417,7 +1366,7 @@ static int insert_text_invoke(bContext *C, wmOperator *op, const wmEvent *event)
accentcode = 0;
}
else if (event->utf8_buf[0]) {
- BLI_strncpy_wchar_from_utf8(inserted_text, event->utf8_buf, 2);
+ inserted_text[0] = BLI_str_utf8_as_unicode(event->utf8_buf);
ascii = inserted_text[0];
insert_into_textbuf(obedit, ascii);
accentcode = 0;
@@ -1744,7 +1693,7 @@ static void font_ui_template_init(bContext *C, wmOperator *op)
PropertyPointerRNA *pprop;
op->customdata = pprop = MEM_callocN(sizeof(PropertyPointerRNA), "OpenPropertyPointerRNA");
- uiIDContextProperty(C, &pprop->ptr, &pprop->prop);
+ UI_context_active_but_prop_get_templateID(C, &pprop->ptr, &pprop->prop);
}
static void font_open_cancel(bContext *UNUSED(C), wmOperator *op)
@@ -1835,8 +1784,8 @@ void FONT_OT_open(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
/* properties */
- WM_operator_properties_filesel(ot, FOLDERFILE | FTFONTFILE, FILE_SPECIAL, FILE_OPENFILE,
- WM_FILESEL_FILEPATH | WM_FILESEL_RELPATH, FILE_DEFAULTDISPLAY);
+ WM_operator_properties_filesel(ot, FILE_TYPE_FOLDER | FILE_TYPE_FTFONT, FILE_SPECIAL, FILE_OPENFILE,
+ WM_FILESEL_FILEPATH | WM_FILESEL_RELPATH, FILE_DEFAULTDISPLAY, FILE_SORT_ALPHA);
}
/******************* delete operator *********************/
@@ -1848,7 +1797,7 @@ static int font_unlink_exec(bContext *C, wmOperator *op)
PointerRNA idptr;
PropertyPointerRNA pprop;
- uiIDContextProperty(C, &pprop.ptr, &pprop.prop);
+ UI_context_active_but_prop_get_templateID(C, &pprop.ptr, &pprop.prop);
if (pprop.prop == NULL) {
BKE_report(op->reports, RPT_ERROR, "Incorrect context for running font unlink");
@@ -1884,8 +1833,8 @@ static void undoFont_to_editFont(void *strv, void *ecu, void *UNUSED(obdata))
EditFont *ef = cu->editfont;
const char *str = strv;
- ef->pos = *((short *)str);
- ef->len = *((short *)(str + 2));
+ ef->pos = *((const short *)str);
+ ef->len = *((const short *)(str + 2));
memcpy(ef->textbuf, str + 4, (ef->len + 1) * sizeof(wchar_t));
memcpy(ef->textbufinfo, str + 4 + (ef->len + 1) * sizeof(wchar_t), ef->len * sizeof(CharInfo));
diff --git a/source/blender/editors/curve/lorem.c b/source/blender/editors/curve/lorem.c
deleted file mode 100644
index 59bf3f50dbc..00000000000
--- a/source/blender/editors/curve/lorem.c
+++ /dev/null
@@ -1,658 +0,0 @@
-/*
- * ***** BEGIN GPL LICENSE BLOCK *****
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-
-/** \file blender/editors/curve/lorem.c
- * \ingroup edcurve
- */
-
-
-#include "BLI_sys_types.h"
-#include "curve_intern.h"
-
-const char ED_lorem[] = {
-76, 111, 114, 101, 109, 32, 105, 112, 115, 117, 109, 32, 100, 111, 108, 111, 114, 32, 115, 105, 116, 32, 97, 109, 101, 116, 44, 32, 99,
-111, 110, 115, 101, 99, 116, 101, 116, 117, 101, 114, 32, 97, 100, 105, 112, 105, 115, 99, 105, 110, 103, 32, 101, 108, 105, 116, 46, 32, 65, 108, 105,
-113, 117, 97, 109, 32, 116, 114, 105, 115, 116, 105, 113, 117, 101, 32, 105, 110, 116, 101, 114, 100, 117, 109, 32, 115, 101, 109, 46, 32, 78, 117, 108,
-108, 97, 109, 32, 112, 114, 101, 116, 105, 117, 109, 44, 32, 116, 111, 114, 116, 111, 114, 32, 110, 111, 110, 32, 101, 117, 105, 115, 109, 111, 100, 32,
-118, 97, 114, 105, 117, 115, 44, 32, 110, 117, 108, 108, 97, 32, 111, 100, 105, 111, 32, 115, 111, 100, 97, 108, 101, 115, 32, 110, 117, 108, 108, 97,
-44, 32, 97, 116, 32, 98, 105, 98, 101, 110, 100, 117, 109, 32, 108, 111, 114, 101, 109, 32, 109, 101, 116, 117, 115, 32, 115, 101, 100, 32, 110, 117,
-108, 108, 97, 46, 32, 86, 101, 115, 116, 105, 98, 117, 108, 117, 109, 32, 105, 110, 32, 108, 101, 99, 116, 117, 115, 32, 97, 116, 32, 112, 101, 100,
-101, 32, 98, 108, 97, 110, 100, 105, 116, 32, 118, 105, 118, 101, 114, 114, 97, 46, 32, 70, 117, 115, 99, 101, 32, 115, 99, 101, 108, 101, 114, 105,
-115, 113, 117, 101, 32, 105, 112, 115, 117, 109, 32, 110, 101, 99, 32, 101, 110, 105, 109, 46, 32, 70, 117, 115, 99, 101, 32, 101, 117, 105, 115, 109,
-111, 100, 32, 110, 117, 110, 99, 32, 105, 100, 32, 101, 110, 105, 109, 46, 32, 73, 110, 32, 118, 101, 110, 101, 110, 97, 116, 105, 115, 32, 99, 117,
-114, 115, 117, 115, 32, 97, 114, 99, 117, 46, 32, 65, 101, 110, 101, 97, 110, 32, 113, 117, 105, 115, 32, 100, 117, 105, 46, 32, 77, 97, 101, 99,
-101, 110, 97, 115, 32, 108, 97, 111, 114, 101, 101, 116, 46, 32, 78, 117, 108, 108, 97, 32, 116, 101, 109, 112, 111, 114, 44, 32, 97, 114, 99, 117,
-32, 112, 117, 108, 118, 105, 110, 97, 114, 32, 112, 114, 101, 116, 105, 117, 109, 32, 115, 117, 115, 99, 105, 112, 105, 116, 44, 32, 116, 111, 114, 116,
-111, 114, 32, 119, 105, 115, 105, 32, 100, 97, 112, 105, 98, 117, 115, 32, 108, 105, 98, 101, 114, 111, 44, 32, 105, 100, 32, 111, 114, 110, 97, 114,
-101, 32, 102, 101, 108, 105, 115, 32, 105, 112, 115, 117, 109, 32, 115, 117, 115, 99, 105, 112, 105, 116, 32, 112, 117, 114, 117, 115, 46, 32, 77, 97,
-101, 99, 101, 110, 97, 115, 32, 105, 112, 115, 117, 109, 46, 32, 77, 111, 114, 98, 105, 32, 99, 117, 114, 115, 117, 115, 46, 32, 86, 101, 115, 116,
-105, 98, 117, 108, 117, 109, 32, 100, 105, 97, 109, 32, 112, 117, 114, 117, 115, 44, 32, 99, 111, 109, 109, 111, 100, 111, 32, 101, 116, 44, 32, 99,
-111, 110, 118, 97, 108, 108, 105, 115, 32, 101, 117, 44, 32, 112, 111, 115, 117, 101, 114, 101, 32, 97, 116, 44, 32, 108, 105, 103, 117, 108, 97, 46,
-32, 78, 117, 108, 108, 97, 32, 97, 108, 105, 113, 117, 97, 109, 32, 97, 108, 105, 113, 117, 101, 116, 32, 108, 111, 114, 101, 109, 46, 32, 78, 117,
-110, 99, 32, 101, 116, 32, 109, 97, 117, 114, 105, 115, 32, 104, 101, 110, 100, 114, 101, 114, 105, 116, 32, 101, 115, 116, 32, 98, 105, 98, 101, 110,
-100, 117, 109, 32, 115, 117, 115, 99, 105, 112, 105, 116, 46, 32, 68, 111, 110, 101, 99, 32, 112, 101, 108, 108, 101, 110, 116, 101, 115, 113, 117, 101,
-32, 108, 105, 98, 101, 114, 111, 32, 101, 117, 32, 110, 105, 115, 108, 46, 32, 80, 101, 108, 108, 101, 110, 116, 101, 115, 113, 117, 101, 32, 101, 103,
-101, 116, 32, 108, 105, 98, 101, 114, 111, 46, 32, 68, 111, 110, 101, 99, 32, 116, 101, 109, 112, 117, 115, 32, 105, 112, 115, 117, 109, 32, 115, 101,
-100, 32, 113, 117, 97, 109, 46, 32, 83, 101, 100, 32, 98, 108, 97, 110, 100, 105, 116, 32, 110, 117, 110, 99, 32, 113, 117, 105, 115, 32, 101, 110,
-105, 109, 46, 32, 81, 117, 105, 115, 113, 117, 101, 32, 108, 101, 99, 116, 117, 115, 32, 100, 105, 97, 109, 44, 32, 97, 100, 105, 112, 105, 115, 99,
-105, 110, 103, 32, 104, 101, 110, 100, 114, 101, 114, 105, 116, 44, 32, 112, 108, 97, 99, 101, 114, 97, 116, 32, 110, 111, 110, 44, 32, 112, 117, 108,
-118, 105, 110, 97, 114, 32, 105, 100, 44, 32, 102, 101, 108, 105, 115, 46, 32, 73, 110, 32, 99, 111, 110, 103, 117, 101, 32, 109, 97, 103, 110, 97,
-32, 115, 105, 116, 32, 97, 109, 101, 116, 32, 117, 114, 110, 97, 46, 32, 78, 117, 110, 99, 32, 110, 111, 110, 32, 97, 117, 103, 117, 101, 32, 115,
-101, 100, 32, 110, 105, 115, 108, 32, 100, 105, 99, 116, 117, 109, 32, 108, 97, 111, 114, 101, 101, 116, 46, 32, 67, 117, 109, 32, 115, 111, 99, 105,
-105, 115, 32, 110, 97, 116, 111, 113, 117, 101, 32, 112, 101, 110, 97, 116, 105, 98, 117, 115, 32, 101, 116, 32, 109, 97, 103, 110, 105, 115, 32, 100,
-105, 115, 32, 112, 97, 114, 116, 117, 114, 105, 101, 110, 116, 32, 109, 111, 110, 116, 101, 115, 44, 32, 110, 97, 115, 99, 101, 116, 117, 114, 32, 114,
-105, 100, 105, 99, 117, 108, 117, 115, 32, 109, 117, 115, 46, 32, 73, 110, 32, 118, 101, 110, 101, 110, 97, 116, 105, 115, 32, 100, 97, 112, 105, 98,
-117, 115, 32, 109, 97, 115, 115, 97, 46, 32, 78, 117, 108, 108, 97, 32, 104, 101, 110, 100, 114, 101, 114, 105, 116, 32, 115, 97, 112, 105, 101, 110,
-32, 101, 116, 32, 113, 117, 97, 109, 46, 32, 78, 117, 110, 99, 32, 97, 99, 32, 109, 97, 103, 110, 97, 32, 108, 111, 98, 111, 114, 116, 105, 115,
-32, 116, 101, 108, 108, 117, 115, 32, 116, 105, 110, 99, 105, 100, 117, 110, 116, 32, 112, 111, 115, 117, 101, 114, 101, 46, 32, 67, 114, 97, 115, 32,
-97, 117, 103, 117, 101, 32, 109, 97, 117, 114, 105, 115, 44, 32, 109, 97, 116, 116, 105, 115, 32, 108, 111, 98, 111, 114, 116, 105, 115, 44, 32, 102,
-101, 114, 109, 101, 110, 116, 117, 109, 32, 97, 116, 44, 32, 115, 101, 109, 112, 101, 114, 32, 97, 99, 44, 32, 116, 101, 108, 108, 117, 115, 46, 32,
-67, 114, 97, 115, 32, 118, 105, 116, 97, 101, 32, 108, 105, 103, 117, 108, 97, 32, 115, 105, 116, 32, 97, 109, 101, 116, 32, 115, 101, 109, 32, 112,
-111, 115, 117, 101, 114, 101, 32, 105, 97, 99, 117, 108, 105, 115, 46, 32, 65, 108, 105, 113, 117, 97, 109, 32, 99, 111, 110, 100, 105, 109, 101, 110,
-116, 117, 109, 32, 101, 108, 101, 105, 102, 101, 110, 100, 32, 102, 101, 108, 105, 115, 46, 32, 85, 116, 32, 115, 105, 116, 32, 97, 109, 101, 116, 32,
-115, 97, 112, 105, 101, 110, 46, 32, 83, 117, 115, 112, 101, 110, 100, 105, 115, 115, 101, 32, 112, 111, 116, 101, 110, 116, 105, 46, 32, 77, 97, 117,
-114, 105, 115, 32, 117, 114, 110, 97, 46, 32, 85, 116, 32, 101, 117, 32, 101, 110, 105, 109, 32, 101, 117, 32, 97, 110, 116, 101, 32, 112, 111, 114,
-116, 97, 32, 118, 101, 115, 116, 105, 98, 117, 108, 117, 109, 46, 32, 65, 101, 110, 101, 97, 110, 32, 115, 99, 101, 108, 101, 114, 105, 115, 113, 117,
-101, 32, 101, 115, 116, 32, 97, 99, 32, 102, 101, 108, 105, 115, 46, 32, 83, 117, 115, 112, 101, 110, 100, 105, 115, 115, 101, 32, 97, 117, 99, 116,
-111, 114, 46, 32, 78, 117, 110, 99, 32, 112, 101, 108, 108, 101, 110, 116, 101, 115, 113, 117, 101, 46, 32, 77, 111, 114, 98, 105, 32, 108, 97, 111,
-114, 101, 101, 116, 32, 97, 110, 116, 101, 32, 101, 116, 32, 110, 105, 98, 104, 46, 32, 68, 111, 110, 101, 99, 32, 102, 101, 117, 103, 105, 97, 116,
-32, 97, 114, 99, 117, 32, 101, 103, 101, 116, 32, 101, 110, 105, 109, 46, 32, 77, 111, 114, 98, 105, 32, 118, 101, 104, 105, 99, 117, 108, 97, 32,
-116, 111, 114, 116, 111, 114, 32, 97, 99, 32, 105, 112, 115, 117, 109, 46, 32, 81, 117, 105, 115, 113, 117, 101, 32, 108, 97, 99, 117, 115, 32, 97,
-114, 99, 117, 44, 32, 101, 108, 101, 109, 101, 110, 116, 117, 109, 32, 97, 99, 44, 32, 102, 97, 117, 99, 105, 98, 117, 115, 32, 118, 101, 108, 44,
-32, 112, 111, 115, 117, 101, 114, 101, 32, 105, 100, 44, 32, 101, 115, 116, 46, 32, 80, 114, 111, 105, 110, 32, 99, 111, 109, 109, 111, 100, 111, 32,
-103, 114, 97, 118, 105, 100, 97, 32, 115, 101, 109, 46, 32, 86, 105, 118, 97, 109, 117, 115, 32, 116, 105, 110, 99, 105, 100, 117, 110, 116, 32, 118,
-101, 104, 105, 99, 117, 108, 97, 32, 108, 105, 98, 101, 114, 111, 46, 32, 80, 104, 97, 115, 101, 108, 108, 117, 115, 32, 119, 105, 115, 105, 46, 32,
-77, 97, 101, 99, 101, 110, 97, 115, 32, 112, 114, 101, 116, 105, 117, 109, 32, 116, 101, 108, 108, 117, 115, 32, 101, 117, 32, 115, 97, 112, 105, 101,
-110, 46, 32, 78, 117, 110, 99, 32, 115, 105, 116, 32, 97, 109, 101, 116, 32, 110, 117, 110, 99, 46, 32, 73, 110, 32, 104, 97, 99, 32, 104, 97,
-98, 105, 116, 97, 115, 115, 101, 32, 112, 108, 97, 116, 101, 97, 32, 100, 105, 99, 116, 117, 109, 115, 116, 46, 32, 65, 101, 110, 101, 97, 110, 32,
-100, 105, 99, 116, 117, 109, 32, 110, 101, 113, 117, 101, 32, 115, 101, 100, 32, 116, 111, 114, 116, 111, 114, 46, 32, 68, 111, 110, 101, 99, 32, 101,
-116, 32, 101, 114, 97, 116, 46, 32, 86, 101, 115, 116, 105, 98, 117, 108, 117, 109, 32, 97, 110, 116, 101, 32, 105, 112, 115, 117, 109, 32, 112, 114,
-105, 109, 105, 115, 32, 105, 110, 32, 102, 97, 117, 99, 105, 98, 117, 115, 32, 111, 114, 99, 105, 32, 108, 117, 99, 116, 117, 115, 32, 101, 116, 32,
-117, 108, 116, 114, 105, 99, 101, 115, 32, 112, 111, 115, 117, 101, 114, 101, 32, 99, 117, 98, 105, 108, 105, 97, 32, 67, 117, 114, 97, 101, 59, 32,
-83, 101, 100, 32, 106, 117, 115, 116, 111, 32, 116, 117, 114, 112, 105, 115, 44, 32, 115, 99, 101, 108, 101, 114, 105, 115, 113, 117, 101, 32, 117, 116,
-44, 32, 109, 97, 116, 116, 105, 115, 32, 115, 105, 116, 32, 97, 109, 101, 116, 44, 32, 111, 114, 110, 97, 114, 101, 32, 114, 117, 116, 114, 117, 109,
-44, 32, 109, 97, 115, 115, 97, 46, 32, 86, 101, 115, 116, 105, 98, 117, 108, 117, 109, 32, 98, 105, 98, 101, 110, 100, 117, 109, 32, 101, 110, 105,
-109, 32, 115, 105, 116, 32, 97, 109, 101, 116, 32, 118, 101, 108, 105, 116, 46, 32, 86, 105, 118, 97, 109, 117, 115, 32, 116, 101, 108, 108, 117, 115,
-32, 105, 112, 115, 117, 109, 44, 32, 108, 117, 99, 116, 117, 115, 32, 117, 116, 44, 32, 99, 111, 110, 115, 101, 99, 116, 101, 116, 117, 101, 114, 32,
-118, 105, 116, 97, 101, 44, 32, 100, 105, 103, 110, 105, 115, 115, 105, 109, 32, 110, 111, 110, 44, 32, 108, 105, 103, 117, 108, 97, 46, 32, 80, 104,
-97, 115, 101, 108, 108, 117, 115, 32, 108, 97, 99, 105, 110, 105, 97, 32, 119, 105, 115, 105, 32, 97, 116, 32, 101, 115, 116, 46, 32, 68, 111, 110,
-101, 99, 32, 101, 108, 105, 116, 32, 119, 105, 115, 105, 44, 32, 99, 111, 109, 109, 111, 100, 111, 32, 110, 111, 110, 44, 32, 112, 108, 97, 99, 101,
-114, 97, 116, 32, 105, 110, 44, 32, 99, 111, 110, 118, 97, 108, 108, 105, 115, 32, 105, 100, 44, 32, 101, 108, 105, 116, 46, 32, 78, 117, 110, 99,
-32, 100, 111, 108, 111, 114, 32, 100, 111, 108, 111, 114, 44, 32, 118, 101, 115, 116, 105, 98, 117, 108, 117, 109, 32, 105, 100, 44, 32, 98, 105, 98,
-101, 110, 100, 117, 109, 32, 118, 105, 116, 97, 101, 44, 32, 108, 97, 99, 105, 110, 105, 97, 32, 105, 100, 44, 32, 101, 114, 97, 116, 46, 32, 67,
-114, 97, 115, 32, 115, 105, 116, 32, 97, 109, 101, 116, 32, 101, 114, 111, 115, 46, 32, 83, 117, 115, 112, 101, 110, 100, 105, 115, 115, 101, 32, 115,
-117, 115, 99, 105, 112, 105, 116, 32, 108, 111, 98, 111, 114, 116, 105, 115, 32, 108, 101, 99, 116, 117, 115, 46, 32, 67, 108, 97, 115, 115, 32, 97,
-112, 116, 101, 110, 116, 32, 116, 97, 99, 105, 116, 105, 32, 115, 111, 99, 105, 111, 115, 113, 117, 32, 97, 100, 32, 108, 105, 116, 111, 114, 97, 32,
-116, 111, 114, 113, 117, 101, 110, 116, 32, 112, 101, 114, 32, 99, 111, 110, 117, 98, 105, 97, 32, 110, 111, 115, 116, 114, 97, 44, 32, 112, 101, 114,
-32, 105, 110, 99, 101, 112, 116, 111, 115, 32, 104, 121, 109, 101, 110, 97, 101, 111, 115, 46, 32, 67, 114, 97, 115, 32, 111, 114, 99, 105, 46, 32,
-80, 114, 97, 101, 115, 101, 110, 116, 32, 109, 97, 115, 115, 97, 32, 117, 114, 110, 97, 44, 32, 108, 111, 98, 111, 114, 116, 105, 115, 32, 115, 101,
-109, 112, 101, 114, 44, 32, 97, 117, 99, 116, 111, 114, 32, 97, 44, 32, 112, 114, 101, 116, 105, 117, 109, 32, 118, 105, 116, 97, 101, 44, 32, 116,
-101, 108, 108, 117, 115, 46, 32, 67, 117, 114, 97, 98, 105, 116, 117, 114, 32, 97, 116, 32, 112, 117, 114, 117, 115, 46, 32, 77, 111, 114, 98, 105,
-32, 116, 111, 114, 116, 111, 114, 32, 113, 117, 97, 109, 44, 32, 105, 109, 112, 101, 114, 100, 105, 101, 116, 32, 118, 101, 110, 101, 110, 97, 116, 105,
-115, 44, 32, 101, 103, 101, 115, 116, 97, 115, 32, 97, 44, 32, 99, 117, 114, 115, 117, 115, 32, 101, 117, 44, 32, 101, 115, 116, 46, 32, 78, 117,
-110, 99, 32, 105, 110, 116, 101, 114, 100, 117, 109, 32, 108, 101, 99, 116, 117, 115, 32, 115, 105, 116, 32, 97, 109, 101, 116, 32, 108, 105, 98, 101,
-114, 111, 46, 32, 81, 117, 105, 115, 113, 117, 101, 32, 100, 105, 103, 110, 105, 115, 115, 105, 109, 32, 112, 108, 97, 99, 101, 114, 97, 116, 32, 108,
-105, 103, 117, 108, 97, 46, 32, 78, 117, 110, 99, 32, 112, 111, 114, 116, 116, 105, 116, 111, 114, 32, 112, 111, 115, 117, 101, 114, 101, 32, 97, 114,
-99, 117, 46, 32, 77, 97, 117, 114, 105, 115, 32, 102, 97, 117, 99, 105, 98, 117, 115, 32, 113, 117, 97, 109, 32, 97, 116, 32, 109, 97, 115, 115,
-97, 46, 32, 86, 105, 118, 97, 109, 117, 115, 32, 115, 111, 100, 97, 108, 101, 115, 32, 97, 108, 105, 113, 117, 101, 116, 32, 109, 97, 117, 114, 105,
-115, 46, 32, 73, 110, 32, 105, 100, 32, 97, 110, 116, 101, 46, 32, 80, 101, 108, 108, 101, 110, 116, 101, 115, 113, 117, 101, 32, 118, 97, 114, 105,
-117, 115, 32, 105, 112, 115, 117, 109, 32, 105, 110, 32, 97, 114, 99, 117, 46, 32, 70, 117, 115, 99, 101, 32, 109, 97, 117, 114, 105, 115, 32, 108,
-97, 99, 117, 115, 44, 32, 116, 114, 105, 115, 116, 105, 113, 117, 101, 32, 97, 99, 44, 32, 108, 111, 98, 111, 114, 116, 105, 115, 32, 113, 117, 105,
-115, 44, 32, 108, 111, 98, 111, 114, 116, 105, 115, 32, 108, 117, 99, 116, 117, 115, 44, 32, 112, 101, 100, 101, 46, 32, 83, 101, 100, 32, 119, 105,
-115, 105, 46, 32, 86, 101, 115, 116, 105, 98, 117, 108, 117, 109, 32, 109, 97, 116, 116, 105, 115, 46, 32, 77, 97, 101, 99, 101, 110, 97, 115, 32,
-104, 101, 110, 100, 114, 101, 114, 105, 116, 32, 115, 101, 109, 32, 110, 101, 99, 32, 112, 117, 114, 117, 115, 46, 32, 80, 114, 111, 105, 110, 32, 105,
-100, 32, 113, 117, 97, 109, 46, 32, 67, 114, 97, 115, 32, 110, 101, 99, 32, 109, 97, 117, 114, 105, 115, 46, 32, 73, 110, 116, 101, 103, 101, 114,
-32, 111, 114, 99, 105, 46, 32, 78, 117, 108, 108, 97, 109, 32, 100, 117, 105, 32, 115, 101, 109, 44, 32, 109, 111, 108, 101, 115, 116, 105, 101, 32,
-115, 101, 100, 44, 32, 101, 103, 101, 115, 116, 97, 115, 32, 113, 117, 105, 115, 44, 32, 99, 117, 114, 115, 117, 115, 32, 105, 110, 44, 32, 109, 97,
-103, 110, 97, 46, 32, 77, 97, 117, 114, 105, 115, 32, 110, 101, 113, 117, 101, 32, 108, 97, 99, 117, 115, 44, 32, 99, 111, 110, 115, 101, 99, 116,
-101, 116, 117, 101, 114, 32, 110, 101, 99, 44, 32, 115, 97, 103, 105, 116, 116, 105, 115, 32, 101, 117, 44, 32, 112, 111, 114, 116, 116, 105, 116, 111,
-114, 32, 101, 103, 101, 116, 44, 32, 100, 117, 105, 46, 32, 70, 117, 115, 99, 101, 32, 99, 111, 110, 115, 101, 99, 116, 101, 116, 117, 101, 114, 46,
-32, 68, 111, 110, 101, 99, 32, 110, 101, 99, 32, 116, 101, 108, 108, 117, 115, 32, 113, 117, 105, 115, 32, 108, 101, 111, 32, 108, 111, 98, 111, 114,
-116, 105, 115, 32, 117, 108, 108, 97, 109, 99, 111, 114, 112, 101, 114, 46, 32, 69, 116, 105, 97, 109, 32, 109, 101, 116, 117, 115, 32, 117, 114, 110,
-97, 44, 32, 97, 108, 105, 113, 117, 101, 116, 32, 112, 114, 101, 116, 105, 117, 109, 44, 32, 117, 108, 116, 114, 105, 99, 101, 115, 32, 101, 117, 44,
-32, 99, 117, 114, 115, 117, 115, 32, 117, 116, 44, 32, 116, 117, 114, 112, 105, 115, 46, 32, 77, 111, 114, 98, 105, 32, 98, 105, 98, 101, 110, 100,
-117, 109, 32, 118, 101, 104, 105, 99, 117, 108, 97, 32, 108, 101, 99, 116, 117, 115, 46, 32, 83, 101, 100, 32, 110, 111, 110, 32, 97, 110, 116, 101,
-32, 118, 105, 116, 97, 101, 32, 97, 114, 99, 117, 32, 112, 101, 108, 108, 101, 110, 116, 101, 115, 113, 117, 101, 32, 116, 101, 109, 112, 111, 114, 46,
-32, 70, 117, 115, 99, 101, 32, 115, 101, 100, 32, 108, 105, 103, 117, 108, 97, 32, 105, 110, 32, 115, 101, 109, 32, 116, 101, 109, 112, 111, 114, 32,
-105, 109, 112, 101, 114, 100, 105, 101, 116, 46, 32, 65, 108, 105, 113, 117, 97, 109, 32, 118, 101, 108, 32, 101, 115, 116, 46, 32, 80, 104, 97, 115,
-101, 108, 108, 117, 115, 32, 115, 111, 108, 108, 105, 99, 105, 116, 117, 100, 105, 110, 32, 115, 111, 108, 108, 105, 99, 105, 116, 117, 100, 105, 110, 32,
-110, 105, 98, 104, 46, 32, 67, 108, 97, 115, 115, 32, 97, 112, 116, 101, 110, 116, 32, 116, 97, 99, 105, 116, 105, 32, 115, 111, 99, 105, 111, 115,
-113, 117, 32, 97, 100, 32, 108, 105, 116, 111, 114, 97, 32, 116, 111, 114, 113, 117, 101, 110, 116, 32, 112, 101, 114, 32, 99, 111, 110, 117, 98, 105,
-97, 32, 110, 111, 115, 116, 114, 97, 44, 32, 112, 101, 114, 32, 105, 110, 99, 101, 112, 116, 111, 115, 32, 104, 121, 109, 101, 110, 97, 101, 111, 115,
-46, 32, 83, 101, 100, 32, 118, 101, 108, 32, 108, 101, 111, 32, 110, 101, 99, 32, 101, 114, 111, 115, 32, 98, 108, 97, 110, 100, 105, 116, 32, 105,
-109, 112, 101, 114, 100, 105, 101, 116, 46, 32, 78, 117, 108, 108, 97, 32, 102, 97, 99, 105, 108, 105, 115, 105, 46, 32, 83, 117, 115, 112, 101, 110,
-100, 105, 115, 115, 101, 32, 108, 111, 98, 111, 114, 116, 105, 115, 44, 32, 100, 117, 105, 32, 117, 116, 32, 102, 114, 105, 110, 103, 105, 108, 108, 97,
-32, 104, 101, 110, 100, 114, 101, 114, 105, 116, 44, 32, 106, 117, 115, 116, 111, 32, 112, 117, 114, 117, 115, 32, 117, 108, 108, 97, 109, 99, 111, 114,
-112, 101, 114, 32, 108, 105, 103, 117, 108, 97, 44, 32, 117, 108, 116, 114, 105, 99, 105, 101, 115, 32, 117, 108, 116, 114, 105, 99, 101, 115, 32, 100,
-111, 108, 111, 114, 32, 101, 110, 105, 109, 32, 105, 110, 32, 108, 105, 98, 101, 114, 111, 46, 32, 83, 101, 100, 32, 101, 108, 101, 109, 101, 110, 116,
-117, 109, 44, 32, 112, 101, 100, 101, 32, 101, 103, 101, 116, 32, 112, 111, 114, 116, 97, 32, 99, 111, 110, 118, 97, 108, 108, 105, 115, 44, 32, 100,
-117, 105, 32, 110, 117, 108, 108, 97, 32, 100, 105, 103, 110, 105, 115, 115, 105, 109, 32, 112, 101, 100, 101, 44, 32, 101, 103, 101, 116, 32, 118, 101,
-104, 105, 99, 117, 108, 97, 32, 111, 100, 105, 111, 32, 97, 110, 116, 101, 32, 97, 116, 32, 115, 101, 109, 46, 32, 80, 101, 108, 108, 101, 110, 116,
-101, 115, 113, 117, 101, 32, 104, 97, 98, 105, 116, 97, 110, 116, 32, 109, 111, 114, 98, 105, 32, 116, 114, 105, 115, 116, 105, 113, 117, 101, 32, 115,
-101, 110, 101, 99, 116, 117, 115, 32, 101, 116, 32, 110, 101, 116, 117, 115, 32, 101, 116, 32, 109, 97, 108, 101, 115, 117, 97, 100, 97, 32, 102, 97,
-109, 101, 115, 32, 97, 99, 32, 116, 117, 114, 112, 105, 115, 32, 101, 103, 101, 115, 116, 97, 115, 46, 32, 83, 101, 100, 32, 117, 108, 108, 97, 109,
-99, 111, 114, 112, 101, 114, 32, 116, 105, 110, 99, 105, 100, 117, 110, 116, 32, 105, 112, 115, 117, 109, 46, 32, 70, 117, 115, 99, 101, 32, 114, 105,
-115, 117, 115, 32, 110, 105, 98, 104, 44, 32, 97, 99, 99, 117, 109, 115, 97, 110, 32, 115, 105, 116, 32, 97, 109, 101, 116, 44, 32, 116, 101, 109,
-112, 117, 115, 32, 101, 103, 101, 116, 44, 32, 116, 114, 105, 115, 116, 105, 113, 117, 101, 32, 97, 99, 44, 32, 110, 101, 113, 117, 101, 46, 32, 83,
-101, 100, 32, 113, 117, 105, 115, 32, 108, 111, 114, 101, 109, 32, 117, 116, 32, 116, 111, 114, 116, 111, 114, 32, 102, 97, 99, 105, 108, 105, 115, 105,
-115, 32, 102, 101, 114, 109, 101, 110, 116, 117, 109, 46, 32, 70, 117, 115, 99, 101, 32, 112, 117, 108, 118, 105, 110, 97, 114, 32, 113, 117, 97, 109,
-32, 115, 105, 116, 32, 97, 109, 101, 116, 32, 105, 112, 115, 117, 109, 46, 32, 77, 111, 114, 98, 105, 32, 97, 99, 32, 101, 108, 105, 116, 32, 113,
-117, 105, 115, 32, 116, 101, 108, 108, 117, 115, 32, 109, 97, 108, 101, 115, 117, 97, 100, 97, 32, 98, 108, 97, 110, 100, 105, 116, 46, 32, 77, 97,
-101, 99, 101, 110, 97, 115, 32, 115, 117, 115, 99, 105, 112, 105, 116, 32, 115, 111, 108, 108, 105, 99, 105, 116, 117, 100, 105, 110, 32, 115, 101, 109,
-46, 32, 78, 97, 109, 32, 115, 101, 100, 32, 101, 114, 111, 115, 32, 118, 101, 108, 32, 108, 97, 99, 117, 115, 32, 108, 111, 98, 111, 114, 116, 105,
-115, 32, 99, 111, 110, 103, 117, 101, 46, 32, 80, 114, 111, 105, 110, 32, 105, 110, 116, 101, 114, 100, 117, 109, 32, 110, 117, 110, 99, 32, 108, 111,
-98, 111, 114, 116, 105, 115, 32, 111, 114, 99, 105, 46, 32, 68, 111, 110, 101, 99, 32, 101, 103, 101, 115, 116, 97, 115, 32, 101, 110, 105, 109, 32,
-101, 117, 32, 111, 100, 105, 111, 46, 32, 86, 101, 115, 116, 105, 98, 117, 108, 117, 109, 32, 105, 100, 32, 109, 101, 116, 117, 115, 46, 32, 80, 101,
-108, 108, 101, 110, 116, 101, 115, 113, 117, 101, 32, 97, 117, 99, 116, 111, 114, 44, 32, 115, 101, 109, 32, 118, 97, 114, 105, 117, 115, 32, 108, 117,
-99, 116, 117, 115, 32, 116, 101, 109, 112, 117, 115, 44, 32, 108, 105, 98, 101, 114, 111, 32, 109, 97, 103, 110, 97, 32, 99, 117, 114, 115, 117, 115,
-32, 110, 101, 113, 117, 101, 44, 32, 101, 116, 32, 112, 111, 114, 116, 116, 105, 116, 111, 114, 32, 100, 105, 97, 109, 32, 100, 105, 97, 109, 32, 113,
-117, 105, 115, 32, 112, 117, 114, 117, 115, 46, 32, 86, 101, 115, 116, 105, 98, 117, 108, 117, 109, 32, 115, 105, 116, 32, 97, 109, 101, 116, 32, 100,
-111, 108, 111, 114, 46, 32, 78, 117, 108, 108, 97, 32, 105, 110, 32, 109, 97, 103, 110, 97, 46, 32, 67, 114, 97, 115, 32, 105, 100, 32, 100, 105,
-97, 109, 32, 97, 116, 32, 108, 101, 99, 116, 117, 115, 32, 102, 97, 117, 99, 105, 98, 117, 115, 32, 112, 108, 97, 99, 101, 114, 97, 116, 46, 32,
-78, 117, 110, 99, 32, 112, 111, 114, 116, 97, 32, 112, 111, 115, 117, 101, 114, 101, 32, 115, 97, 112, 105, 101, 110, 46, 32, 69, 116, 105, 97, 109,
-32, 115, 99, 101, 108, 101, 114, 105, 115, 113, 117, 101, 46, 32, 67, 108, 97, 115, 115, 32, 97, 112, 116, 101, 110, 116, 32, 116, 97, 99, 105, 116,
-105, 32, 115, 111, 99, 105, 111, 115, 113, 117, 32, 97, 100, 32, 108, 105, 116, 111, 114, 97, 32, 116, 111, 114, 113, 117, 101, 110, 116, 32, 112, 101,
-114, 32, 99, 111, 110, 117, 98, 105, 97, 32, 110, 111, 115, 116, 114, 97, 44, 32, 112, 101, 114, 32, 105, 110, 99, 101, 112, 116, 111, 115, 32, 104,
-121, 109, 101, 110, 97, 101, 111, 115, 46, 32, 65, 108, 105, 113, 117, 97, 109, 32, 112, 101, 108, 108, 101, 110, 116, 101, 115, 113, 117, 101, 32, 109,
-105, 32, 115, 101, 100, 32, 116, 111, 114, 116, 111, 114, 46, 32, 77, 97, 101, 99, 101, 110, 97, 115, 32, 101, 108, 101, 105, 102, 101, 110, 100, 32,
-100, 105, 97, 109, 32, 110, 111, 110, 32, 117, 114, 110, 97, 46, 32, 68, 111, 110, 101, 99, 32, 108, 117, 99, 116, 117, 115, 32, 112, 104, 97, 114,
-101, 116, 114, 97, 32, 116, 101, 108, 108, 117, 115, 46, 32, 80, 114, 111, 105, 110, 32, 97, 99, 32, 105, 112, 115, 117, 109, 32, 101, 103, 101, 116,
-32, 108, 105, 98, 101, 114, 111, 32, 98, 105, 98, 101, 110, 100, 117, 109, 32, 118, 111, 108, 117, 116, 112, 97, 116, 46, 32, 67, 114, 97, 115, 32,
-105, 100, 32, 116, 101, 108, 108, 117, 115, 46, 32, 78, 117, 108, 108, 97, 32, 110, 111, 110, 32, 114, 105, 115, 117, 115, 46, 32, 73, 110, 32, 100,
-111, 108, 111, 114, 46, 32, 70, 117, 115, 99, 101, 32, 115, 99, 101, 108, 101, 114, 105, 115, 113, 117, 101, 32, 113, 117, 97, 109, 32, 105, 110, 32,
-109, 97, 115, 115, 97, 32, 117, 108, 116, 114, 105, 99, 101, 115, 32, 112, 111, 114, 116, 97, 46, 32, 77, 111, 114, 98, 105, 32, 117, 116, 32, 100,
-111, 108, 111, 114, 32, 101, 117, 32, 109, 97, 115, 115, 97, 32, 101, 103, 101, 115, 116, 97, 115, 32, 99, 111, 110, 100, 105, 109, 101, 110, 116, 117,
-109, 46, 32, 77, 97, 117, 114, 105, 115, 32, 118, 117, 108, 112, 117, 116, 97, 116, 101, 46, 32, 73, 110, 32, 104, 97, 99, 32, 104, 97, 98, 105,
-116, 97, 115, 115, 101, 32, 112, 108, 97, 116, 101, 97, 32, 100, 105, 99, 116, 117, 109, 115, 116, 46, 32, 83, 117, 115, 112, 101, 110, 100, 105, 115,
-115, 101, 32, 112, 111, 116, 101, 110, 116, 105, 46, 32, 77, 97, 117, 114, 105, 115, 32, 118, 101, 104, 105, 99, 117, 108, 97, 32, 108, 101, 111, 32,
-105, 110, 32, 116, 111, 114, 116, 111, 114, 46, 32, 77, 97, 117, 114, 105, 115, 32, 118, 101, 108, 32, 101, 114, 97, 116, 32, 97, 32, 117, 114, 110,
-97, 32, 108, 97, 111, 114, 101, 101, 116, 32, 115, 101, 109, 112, 101, 114, 46, 32, 80, 101, 108, 108, 101, 110, 116, 101, 115, 113, 117, 101, 32, 117,
-116, 32, 109, 101, 116, 117, 115, 32, 97, 99, 32, 116, 101, 108, 108, 117, 115, 32, 99, 111, 109, 109, 111, 100, 111, 32, 101, 108, 101, 105, 102, 101,
-110, 100, 46, 32, 83, 117, 115, 112, 101, 110, 100, 105, 115, 115, 101, 32, 113, 117, 105, 115, 32, 117, 114, 110, 97, 46, 32, 67, 117, 114, 97, 98,
-105, 116, 117, 114, 32, 108, 97, 99, 105, 110, 105, 97, 32, 100, 105, 103, 110, 105, 115, 115, 105, 109, 32, 100, 117, 105, 46, 32, 78, 97, 109, 32,
-110, 101, 99, 32, 97, 110, 116, 101, 46, 32, 73, 110, 32, 105, 100, 32, 101, 110, 105, 109, 46, 32, 65, 101, 110, 101, 97, 110, 32, 109, 97, 116,
-116, 105, 115, 32, 101, 110, 105, 109, 46, 32, 73, 110, 32, 117, 116, 32, 110, 101, 113, 117, 101, 32, 112, 111, 114, 116, 116, 105, 116, 111, 114, 32,
-114, 105, 115, 117, 115, 32, 104, 101, 110, 100, 114, 101, 114, 105, 116, 32, 116, 105, 110, 99, 105, 100, 117, 110, 116, 46, 32, 83, 117, 115, 112, 101,
-110, 100, 105, 115, 115, 101, 32, 112, 111, 116, 101, 110, 116, 105, 46, 32, 85, 116, 32, 118, 101, 115, 116, 105, 98, 117, 108, 117, 109, 32, 108, 101,
-99, 116, 117, 115, 32, 118, 105, 116, 97, 101, 32, 116, 111, 114, 116, 111, 114, 46, 32, 68, 117, 105, 115, 32, 118, 101, 108, 105, 116, 46, 32, 78,
-117, 108, 108, 97, 32, 102, 97, 99, 105, 108, 105, 115, 105, 46, 32, 73, 110, 116, 101, 103, 101, 114, 32, 115, 105, 116, 32, 97, 109, 101, 116, 32,
-117, 114, 110, 97, 46, 32, 67, 114, 97, 115, 32, 118, 97, 114, 105, 117, 115, 32, 116, 111, 114, 116, 111, 114, 32, 105, 110, 32, 112, 101, 100, 101,
-46, 32, 83, 101, 100, 32, 102, 97, 99, 105, 108, 105, 115, 105, 115, 46, 32, 80, 114, 97, 101, 115, 101, 110, 116, 32, 108, 97, 99, 105, 110, 105,
-97, 32, 108, 105, 98, 101, 114, 111, 32, 110, 101, 99, 32, 110, 105, 98, 104, 46, 32, 68, 111, 110, 101, 99, 32, 97, 108, 105, 113, 117, 97, 109,
-32, 114, 105, 115, 117, 115, 32, 110, 111, 110, 32, 110, 105, 115, 108, 46, 32, 78, 97, 109, 32, 97, 32, 110, 117, 110, 99, 32, 101, 116, 32, 102,
-101, 108, 105, 115, 32, 116, 101, 109, 112, 111, 114, 32, 102, 101, 117, 103, 105, 97, 116, 46, 32, 78, 117, 110, 99, 32, 109, 101, 116, 117, 115, 46,
-32, 86, 101, 115, 116, 105, 98, 117, 108, 117, 109, 32, 101, 117, 105, 115, 109, 111, 100, 44, 32, 109, 101, 116, 117, 115, 32, 105, 110, 32, 115, 101,
-109, 112, 101, 114, 32, 108, 97, 111, 114, 101, 101, 116, 44, 32, 117, 114, 110, 97, 32, 105, 112, 115, 117, 109, 32, 112, 104, 97, 114, 101, 116, 114,
-97, 32, 108, 111, 114, 101, 109, 44, 32, 115, 101, 100, 32, 117, 108, 116, 114, 105, 99, 105, 101, 115, 32, 109, 97, 103, 110, 97, 32, 108, 111, 114,
-101, 109, 32, 115, 105, 116, 32, 97, 109, 101, 116, 32, 119, 105, 115, 105, 46, 32, 83, 101, 100, 32, 119, 105, 115, 105, 46, 32, 78, 117, 108, 108,
-97, 109, 32, 102, 97, 99, 105, 108, 105, 115, 105, 115, 32, 101, 108, 105, 116, 32, 115, 101, 100, 32, 110, 105, 115, 108, 46, 32, 80, 104, 97, 115,
-101, 108, 108, 117, 115, 32, 109, 97, 116, 116, 105, 115, 32, 108, 101, 111, 32, 110, 101, 99, 32, 109, 97, 115, 115, 97, 46, 32, 65, 101, 110, 101,
-97, 110, 32, 109, 97, 108, 101, 115, 117, 97, 100, 97, 46, 32, 67, 114, 97, 115, 32, 119, 105, 115, 105, 32, 101, 114, 97, 116, 44, 32, 108, 111,
-98, 111, 114, 116, 105, 115, 32, 110, 101, 99, 44, 32, 99, 117, 114, 115, 117, 115, 32, 101, 103, 101, 116, 44, 32, 108, 111, 98, 111, 114, 116, 105,
-115, 32, 97, 116, 44, 32, 108, 105, 98, 101, 114, 111, 46, 32, 73, 110, 32, 109, 97, 115, 115, 97, 32, 110, 105, 115, 108, 44, 32, 114, 117, 116,
-114, 117, 109, 32, 110, 111, 110, 44, 32, 99, 117, 114, 115, 117, 115, 32, 110, 101, 99, 44, 32, 102, 97, 117, 99, 105, 98, 117, 115, 32, 115, 101,
-100, 44, 32, 108, 97, 99, 117, 115, 46, 32, 80, 101, 108, 108, 101, 110, 116, 101, 115, 113, 117, 101, 32, 109, 97, 108, 101, 115, 117, 97, 100, 97,
-46, 32, 67, 114, 97, 115, 32, 101, 117, 105, 115, 109, 111, 100, 44, 32, 110, 101, 113, 117, 101, 32, 97, 99, 32, 115, 117, 115, 99, 105, 112, 105,
-116, 32, 116, 101, 109, 112, 117, 115, 44, 32, 118, 101, 108, 105, 116, 32, 108, 111, 114, 101, 109, 32, 108, 117, 99, 116, 117, 115, 32, 101, 108, 105,
-116, 44, 32, 100, 97, 112, 105, 98, 117, 115, 32, 114, 104, 111, 110, 99, 117, 115, 32, 119, 105, 115, 105, 32, 101, 115, 116, 32, 117, 116, 32, 115,
-101, 109, 46, 32, 80, 114, 111, 105, 110, 32, 118, 117, 108, 112, 117, 116, 97, 116, 101, 32, 101, 110, 105, 109, 32, 105, 110, 32, 101, 114, 111, 115,
-32, 101, 108, 101, 109, 101, 110, 116, 117, 109, 32, 97, 99, 99, 117, 109, 115, 97, 110, 46, 32, 85, 116, 32, 108, 111, 114, 101, 109, 32, 110, 105,
-115, 108, 44, 32, 104, 101, 110, 100, 114, 101, 114, 105, 116, 32, 101, 116, 44, 32, 105, 110, 116, 101, 114, 100, 117, 109, 32, 110, 101, 99, 44, 32,
-108, 97, 99, 105, 110, 105, 97, 32, 105, 110, 44, 32, 100, 111, 108, 111, 114, 46, 32, 68, 117, 105, 115, 32, 110, 101, 99, 32, 113, 117, 97, 109,
-46, 32, 80, 114, 97, 101, 115, 101, 110, 116, 32, 118, 101, 108, 105, 116, 32, 102, 101, 108, 105, 115, 44, 32, 112, 111, 115, 117, 101, 114, 101, 32,
-105, 100, 44, 32, 108, 117, 99, 116, 117, 115, 32, 113, 117, 105, 115, 44, 32, 108, 97, 111, 114, 101, 101, 116, 32, 117, 116, 44, 32, 105, 112, 115,
-117, 109, 46, 32, 80, 114, 97, 101, 115, 101, 110, 116, 32, 101, 103, 101, 116, 32, 97, 114, 99, 117, 46, 32, 77, 97, 117, 114, 105, 115, 32, 109,
-97, 115, 115, 97, 32, 102, 101, 108, 105, 115, 44, 32, 111, 114, 110, 97, 114, 101, 32, 110, 111, 110, 44, 32, 117, 108, 116, 114, 105, 99, 101, 115,
-32, 105, 100, 44, 32, 116, 114, 105, 115, 116, 105, 113, 117, 101, 32, 105, 110, 44, 32, 101, 108, 105, 116, 46, 32, 80, 101, 108, 108, 101, 110, 116,
-101, 115, 113, 117, 101, 32, 104, 97, 98, 105, 116, 97, 110, 116, 32, 109, 111, 114, 98, 105, 32, 116, 114, 105, 115, 116, 105, 113, 117, 101, 32, 115,
-101, 110, 101, 99, 116, 117, 115, 32, 101, 116, 32, 110, 101, 116, 117, 115, 32, 101, 116, 32, 109, 97, 108, 101, 115, 117, 97, 100, 97, 32, 102, 97,
-109, 101, 115, 32, 97, 99, 32, 116, 117, 114, 112, 105, 115, 32, 101, 103, 101, 115, 116, 97, 115, 46, 32, 80, 104, 97, 115, 101, 108, 108, 117, 115,
-32, 118, 117, 108, 112, 117, 116, 97, 116, 101, 44, 32, 109, 105, 32, 97, 99, 32, 98, 105, 98, 101, 110, 100, 117, 109, 32, 102, 97, 99, 105, 108,
-105, 115, 105, 115, 44, 32, 108, 105, 98, 101, 114, 111, 32, 101, 110, 105, 109, 32, 115, 117, 115, 99, 105, 112, 105, 116, 32, 108, 101, 111, 44, 32,
-110, 111, 110, 32, 110, 111, 110, 117, 109, 109, 121, 32, 112, 101, 100, 101, 32, 100, 105, 97, 109, 32, 101, 103, 101, 116, 32, 110, 105, 98, 104, 46,
-32, 83, 101, 100, 32, 116, 101, 109, 112, 117, 115, 46, 32, 65, 101, 110, 101, 97, 110, 32, 105, 110, 116, 101, 114, 100, 117, 109, 32, 115, 117, 115,
-99, 105, 112, 105, 116, 32, 100, 117, 105, 46, 32, 65, 108, 105, 113, 117, 97, 109, 32, 101, 114, 97, 116, 32, 118, 111, 108, 117, 116, 112, 97, 116,
-46, 32, 85, 116, 32, 109, 97, 108, 101, 115, 117, 97, 100, 97, 46, 32, 78, 97, 109, 32, 99, 111, 109, 109, 111, 100, 111, 44, 32, 110, 117, 108,
-108, 97, 32, 117, 116, 32, 102, 114, 105, 110, 103, 105, 108, 108, 97, 32, 114, 117, 116, 114, 117, 109, 44, 32, 111, 114, 99, 105, 32, 101, 108, 105,
-116, 32, 118, 105, 118, 101, 114, 114, 97, 32, 100, 105, 97, 109, 44, 32, 118, 105, 116, 97, 101, 32, 109, 111, 108, 108, 105, 115, 32, 111, 100, 105,
-111, 32, 111, 100, 105, 111, 32, 101, 116, 32, 112, 117, 114, 117, 115, 46, 32, 65, 108, 105, 113, 117, 97, 109, 32, 101, 114, 97, 116, 32, 118, 111,
-108, 117, 116, 112, 97, 116, 46, 32, 83, 101, 100, 32, 97, 108, 105, 113, 117, 101, 116, 32, 108, 111, 98, 111, 114, 116, 105, 115, 32, 105, 112, 115,
-117, 109, 46, 32, 73, 110, 32, 117, 116, 32, 101, 115, 116, 46, 32, 69, 116, 105, 97, 109, 32, 99, 111, 110, 100, 105, 109, 101, 110, 116, 117, 109,
-46, 32, 86, 101, 115, 116, 105, 98, 117, 108, 117, 109, 32, 112, 101, 108, 108, 101, 110, 116, 101, 115, 113, 117, 101, 32, 116, 111, 114, 116, 111, 114,
-32, 112, 117, 108, 118, 105, 110, 97, 114, 32, 108, 97, 99, 117, 115, 46, 32, 65, 101, 110, 101, 97, 110, 32, 111, 114, 99, 105, 46, 32, 83, 117,
-115, 112, 101, 110, 100, 105, 115, 115, 101, 32, 108, 97, 99, 117, 115, 32, 110, 117, 108, 108, 97, 44, 32, 110, 111, 110, 117, 109, 109, 121, 32, 97,
-44, 32, 100, 105, 99, 116, 117, 109, 32, 118, 105, 116, 97, 101, 44, 32, 101, 103, 101, 115, 116, 97, 115, 32, 113, 117, 105, 115, 44, 32, 101, 114,
-111, 115, 46, 32, 68, 111, 110, 101, 99, 32, 97, 117, 99, 116, 111, 114, 32, 103, 114, 97, 118, 105, 100, 97, 32, 110, 105, 115, 108, 46, 32, 67,
-114, 97, 115, 32, 97, 99, 32, 101, 115, 116, 32, 114, 117, 116, 114, 117, 109, 32, 97, 117, 103, 117, 101, 32, 112, 117, 108, 118, 105, 110, 97, 114,
-32, 111, 114, 110, 97, 114, 101, 46, 32, 80, 104, 97, 115, 101, 108, 108, 117, 115, 32, 109, 97, 117, 114, 105, 115, 32, 110, 105, 98, 104, 44, 32,
-118, 117, 108, 112, 117, 116, 97, 116, 101, 32, 105, 110, 44, 32, 114, 104, 111, 110, 99, 117, 115, 32, 105, 109, 112, 101, 114, 100, 105, 101, 116, 44,
-32, 100, 97, 112, 105, 98, 117, 115, 32, 101, 103, 101, 116, 44, 32, 108, 97, 99, 117, 115, 46, 32, 78, 97, 109, 32, 110, 117, 110, 99, 32, 109,
-97, 117, 114, 105, 115, 44, 32, 115, 117, 115, 99, 105, 112, 105, 116, 32, 97, 116, 44, 32, 117, 108, 116, 114, 105, 99, 105, 101, 115, 32, 97, 44,
-32, 102, 97, 99, 105, 108, 105, 115, 105, 115, 32, 97, 116, 44, 32, 116, 101, 108, 108, 117, 115, 46, 32, 78, 97, 109, 32, 97, 99, 99, 117, 109,
-115, 97, 110, 32, 109, 111, 108, 108, 105, 115, 32, 108, 105, 98, 101, 114, 111, 46, 32, 86, 105, 118, 97, 109, 117, 115, 32, 99, 111, 110, 100, 105,
-109, 101, 110, 116, 117, 109, 32, 109, 97, 116, 116, 105, 115, 32, 101, 115, 116, 46, 32, 68, 111, 110, 101, 99, 32, 108, 97, 99, 117, 115, 46, 32,
-78, 117, 108, 108, 97, 109, 32, 97, 99, 32, 115, 97, 112, 105, 101, 110, 32, 105, 100, 32, 109, 97, 115, 115, 97, 32, 108, 111, 98, 111, 114, 116,
-105, 115, 32, 109, 111, 108, 101, 115, 116, 105, 101, 46, 32, 80, 101, 108, 108, 101, 110, 116, 101, 115, 113, 117, 101, 32, 101, 108, 101, 109, 101, 110,
-116, 117, 109, 46, 32, 80, 114, 111, 105, 110, 32, 117, 116, 32, 112, 117, 114, 117, 115, 46, 32, 73, 110, 116, 101, 103, 101, 114, 32, 101, 116, 32,
-115, 97, 112, 105, 101, 110, 32, 113, 117, 105, 115, 32, 116, 117, 114, 112, 105, 115, 32, 99, 111, 109, 109, 111, 100, 111, 32, 109, 111, 108, 108, 105,
-115, 46, 32, 78, 117, 108, 108, 97, 32, 99, 111, 110, 115, 101, 113, 117, 97, 116, 46, 32, 80, 114, 111, 105, 110, 32, 97, 32, 119, 105, 115, 105,
-32, 117, 116, 32, 116, 101, 108, 108, 117, 115, 32, 98, 108, 97, 110, 100, 105, 116, 32, 101, 108, 101, 109, 101, 110, 116, 117, 109, 46, 32, 65, 108,
-105, 113, 117, 97, 109, 32, 110, 117, 108, 108, 97, 32, 108, 111, 114, 101, 109, 44, 32, 98, 105, 98, 101, 110, 100, 117, 109, 32, 97, 99, 44, 32,
-109, 97, 108, 101, 115, 117, 97, 100, 97, 32, 118, 101, 108, 44, 32, 101, 108, 101, 109, 101, 110, 116, 117, 109, 32, 101, 116, 44, 32, 109, 101, 116,
-117, 115, 46, 32, 80, 104, 97, 115, 101, 108, 108, 117, 115, 32, 101, 103, 101, 115, 116, 97, 115, 32, 110, 105, 98, 104, 32, 101, 116, 32, 108, 105,
-103, 117, 108, 97, 46, 32, 86, 105, 118, 97, 109, 117, 115, 32, 100, 105, 97, 109, 32, 111, 100, 105, 111, 44, 32, 108, 97, 99, 105, 110, 105, 97,
-32, 113, 117, 105, 115, 44, 32, 109, 97, 108, 101, 115, 117, 97, 100, 97, 32, 113, 117, 105, 115, 44, 32, 115, 111, 108, 108, 105, 99, 105, 116, 117,
-100, 105, 110, 32, 117, 116, 44, 32, 101, 114, 111, 115, 46, 32, 80, 104, 97, 115, 101, 108, 108, 117, 115, 32, 97, 108, 105, 113, 117, 101, 116, 32,
-108, 111, 114, 101, 109, 32, 97, 99, 32, 105, 112, 115, 117, 109, 46, 32, 83, 101, 100, 32, 99, 117, 114, 115, 117, 115, 32, 116, 101, 108, 108, 117,
-115, 32, 97, 99, 32, 111, 114, 99, 105, 46, 32, 80, 104, 97, 115, 101, 108, 108, 117, 115, 32, 97, 116, 32, 110, 117, 108, 108, 97, 46, 32, 68,
-111, 110, 101, 99, 32, 112, 111, 114, 116, 97, 32, 115, 111, 100, 97, 108, 101, 115, 32, 97, 110, 116, 101, 46, 32, 80, 101, 108, 108, 101, 110, 116,
-101, 115, 113, 117, 101, 32, 104, 97, 98, 105, 116, 97, 110, 116, 32, 109, 111, 114, 98, 105, 32, 116, 114, 105, 115, 116, 105, 113, 117, 101, 32, 115,
-101, 110, 101, 99, 116, 117, 115, 32, 101, 116, 32, 110, 101, 116, 117, 115, 32, 101, 116, 32, 109, 97, 108, 101, 115, 117, 97, 100, 97, 32, 102, 97,
-109, 101, 115, 32, 97, 99, 32, 116, 117, 114, 112, 105, 115, 32, 101, 103, 101, 115, 116, 97, 115, 46, 32, 83, 101, 100, 32, 105, 100, 32, 108, 101,
-99, 116, 117, 115, 32, 97, 116, 32, 109, 97, 115, 115, 97, 32, 117, 108, 108, 97, 109, 99, 111, 114, 112, 101, 114, 32, 116, 114, 105, 115, 116, 105,
-113, 117, 101, 46, 32, 83, 117, 115, 112, 101, 110, 100, 105, 115, 115, 101, 32, 112, 111, 114, 116, 116, 105, 116, 111, 114, 32, 108, 97, 99, 117, 115,
-46, 32, 73, 110, 32, 104, 97, 99, 32, 104, 97, 98, 105, 116, 97, 115, 115, 101, 32, 112, 108, 97, 116, 101, 97, 32, 100, 105, 99, 116, 117, 109,
-115, 116, 46, 32, 78, 117, 110, 99, 32, 110, 111, 110, 32, 116, 117, 114, 112, 105, 115, 46, 32, 83, 101, 100, 32, 115, 97, 103, 105, 116, 116, 105,
-115, 46, 32, 77, 111, 114, 98, 105, 32, 108, 97, 111, 114, 101, 101, 116, 32, 115, 99, 101, 108, 101, 114, 105, 115, 113, 117, 101, 32, 100, 117, 105,
-46, 32, 78, 97, 109, 32, 97, 114, 99, 117, 32, 116, 101, 108, 108, 117, 115, 44, 32, 116, 101, 109, 112, 111, 114, 32, 118, 105, 116, 97, 101, 44,
-32, 118, 101, 115, 116, 105, 98, 117, 108, 117, 109, 32, 101, 116, 44, 32, 105, 109, 112, 101, 114, 100, 105, 101, 116, 32, 117, 116, 44, 32, 118, 101,
-108, 105, 116, 46, 32, 73, 110, 32, 115, 105, 116, 32, 97, 109, 101, 116, 32, 97, 117, 103, 117, 101, 32, 97, 32, 97, 114, 99, 117, 32, 118, 111,
-108, 117, 116, 112, 97, 116, 32, 115, 117, 115, 99, 105, 112, 105, 116, 46, 32, 68, 111, 110, 101, 99, 32, 100, 105, 99, 116, 117, 109, 32, 117, 108,
-116, 114, 105, 99, 101, 115, 32, 108, 101, 99, 116, 117, 115, 46, 32, 80, 104, 97, 115, 101, 108, 108, 117, 115, 32, 97, 32, 112, 117, 114, 117, 115,
-32, 101, 116, 32, 111, 114, 99, 105, 32, 100, 105, 99, 116, 117, 109, 32, 108, 97, 99, 105, 110, 105, 97, 46, 32, 85, 116, 32, 108, 101, 111, 46,
-32, 67, 114, 97, 115, 32, 115, 101, 109, 112, 101, 114, 44, 32, 108, 111, 114, 101, 109, 32, 115, 105, 116, 32, 97, 109, 101, 116, 32, 116, 105, 110,
-99, 105, 100, 117, 110, 116, 32, 99, 111, 110, 103, 117, 101, 44, 32, 106, 117, 115, 116, 111, 32, 101, 114, 111, 115, 32, 118, 97, 114, 105, 117, 115,
-32, 112, 101, 100, 101, 44, 32, 105, 110, 32, 98, 105, 98, 101, 110, 100, 117, 109, 32, 116, 117, 114, 112, 105, 115, 32, 108, 101, 99, 116, 117, 115,
-32, 110, 111, 110, 32, 101, 114, 111, 115, 46, 32, 80, 104, 97, 115, 101, 108, 108, 117, 115, 32, 113, 117, 97, 109, 46, 32, 83, 117, 115, 112, 101,
-110, 100, 105, 115, 115, 101, 32, 109, 97, 116, 116, 105, 115, 32, 115, 111, 108, 108, 105, 99, 105, 116, 117, 100, 105, 110, 32, 109, 97, 103, 110, 97,
-46, 32, 65, 101, 110, 101, 97, 110, 32, 102, 97, 99, 105, 108, 105, 115, 105, 115, 32, 100, 105, 97, 109, 32, 118, 101, 108, 32, 110, 105, 115, 108,
-32, 110, 111, 110, 117, 109, 109, 121, 32, 99, 111, 110, 100, 105, 109, 101, 110, 116, 117, 109, 46, 32, 83, 117, 115, 112, 101, 110, 100, 105, 115, 115,
-101, 32, 118, 101, 108, 32, 100, 111, 108, 111, 114, 46, 32, 86, 101, 115, 116, 105, 98, 117, 108, 117, 109, 32, 110, 111, 110, 117, 109, 109, 121, 46,
-32, 77, 97, 117, 114, 105, 115, 32, 105, 109, 112, 101, 114, 100, 105, 101, 116, 32, 115, 101, 109, 112, 101, 114, 32, 97, 110, 116, 101, 46, 32, 77,
-97, 101, 99, 101, 110, 97, 115, 32, 118, 117, 108, 112, 117, 116, 97, 116, 101, 32, 101, 114, 111, 115, 46, 32, 86, 101, 115, 116, 105, 98, 117, 108,
-117, 109, 32, 97, 99, 32, 100, 111, 108, 111, 114, 46, 32, 70, 117, 115, 99, 101, 32, 114, 105, 115, 117, 115, 32, 109, 101, 116, 117, 115, 44, 32,
-97, 108, 105, 113, 117, 101, 116, 32, 101, 103, 101, 116, 44, 32, 102, 97, 99, 105, 108, 105, 115, 105, 115, 32, 101, 116, 44, 32, 102, 101, 117, 103,
-105, 97, 116, 32, 118, 101, 108, 44, 32, 111, 114, 99, 105, 46, 32, 85, 116, 32, 97, 116, 32, 110, 117, 110, 99, 32, 105, 100, 32, 97, 110, 116,
-101, 32, 115, 111, 100, 97, 108, 101, 115, 32, 118, 117, 108, 112, 117, 116, 97, 116, 101, 46, 32, 68, 117, 105, 115, 32, 116, 114, 105, 115, 116, 105,
-113, 117, 101, 32, 109, 97, 116, 116, 105, 115, 32, 97, 110, 116, 101, 46, 32, 86, 101, 115, 116, 105, 98, 117, 108, 117, 109, 32, 110, 101, 113, 117,
-101, 32, 109, 97, 117, 114, 105, 115, 44, 32, 108, 97, 111, 114, 101, 101, 116, 32, 105, 100, 44, 32, 99, 111, 110, 103, 117, 101, 32, 105, 110, 116,
-101, 114, 100, 117, 109, 44, 32, 97, 108, 105, 113, 117, 101, 116, 32, 117, 116, 44, 32, 100, 105, 97, 109, 46, 32, 78, 117, 108, 108, 97, 32, 118,
-111, 108, 117, 116, 112, 97, 116, 32, 98, 108, 97, 110, 100, 105, 116, 32, 109, 97, 103, 110, 97, 46, 32, 68, 111, 110, 101, 99, 32, 97, 99, 99,
-117, 109, 115, 97, 110, 32, 99, 111, 110, 103, 117, 101, 32, 100, 105, 97, 109, 46, 32, 69, 116, 105, 97, 109, 32, 118, 101, 108, 32, 100, 117, 105,
-32, 101, 103, 101, 116, 32, 110, 105, 115, 108, 32, 116, 101, 109, 112, 111, 114, 32, 118, 97, 114, 105, 117, 115, 46, 32, 67, 114, 97, 115, 32, 100,
-105, 99, 116, 117, 109, 32, 109, 97, 115, 115, 97, 32, 115, 101, 100, 32, 101, 110, 105, 109, 46, 32, 67, 114, 97, 115, 32, 117, 114, 110, 97, 32,
-116, 111, 114, 116, 111, 114, 44, 32, 102, 114, 105, 110, 103, 105, 108, 108, 97, 32, 97, 99, 44, 32, 117, 108, 108, 97, 109, 99, 111, 114, 112, 101,
-114, 32, 105, 110, 44, 32, 101, 117, 105, 115, 109, 111, 100, 32, 118, 101, 108, 44, 32, 97, 114, 99, 117, 46, 32, 77, 111, 114, 98, 105, 32, 112,
-111, 115, 117, 101, 114, 101, 32, 108, 117, 99, 116, 117, 115, 32, 97, 117, 103, 117, 101, 46, 32, 65, 108, 105, 113, 117, 97, 109, 32, 100, 117, 105,
-32, 100, 117, 105, 44, 32, 97, 100, 105, 112, 105, 115, 99, 105, 110, 103, 32, 105, 110, 44, 32, 108, 111, 98, 111, 114, 116, 105, 115, 32, 101, 117,
-44, 32, 108, 117, 99, 116, 117, 115, 32, 101, 117, 44, 32, 110, 117, 108, 108, 97, 46, 32, 67, 114, 97, 115, 32, 118, 101, 108, 105, 116, 32, 112,
-101, 100, 101, 44, 32, 117, 108, 108, 97, 109, 99, 111, 114, 112, 101, 114, 32, 115, 105, 116, 32, 97, 109, 101, 116, 44, 32, 102, 101, 117, 103, 105,
-97, 116, 32, 105, 110, 44, 32, 97, 117, 99, 116, 111, 114, 32, 118, 105, 116, 97, 101, 44, 32, 97, 110, 116, 101, 46, 32, 83, 117, 115, 112, 101,
-110, 100, 105, 115, 115, 101, 32, 100, 105, 99, 116, 117, 109, 32, 102, 114, 105, 110, 103, 105, 108, 108, 97, 32, 109, 97, 117, 114, 105, 115, 46, 32,
-73, 110, 32, 97, 32, 110, 105, 98, 104, 46, 32, 68, 111, 110, 101, 99, 32, 97, 99, 32, 108, 105, 103, 117, 108, 97, 46, 32, 73, 110, 32, 113,
-117, 97, 109, 46, 32, 80, 114, 97, 101, 115, 101, 110, 116, 32, 118, 105, 116, 97, 101, 32, 117, 114, 110, 97, 32, 117, 108, 116, 114, 105, 99, 105,
-101, 115, 32, 115, 101, 109, 32, 97, 108, 105, 113, 117, 97, 109, 32, 112, 108, 97, 99, 101, 114, 97, 116, 46, 32, 65, 108, 105, 113, 117, 97, 109,
-32, 101, 114, 97, 116, 32, 118, 111, 108, 117, 116, 112, 97, 116, 46, 32, 78, 97, 109, 32, 101, 115, 116, 46, 32, 68, 111, 110, 101, 99, 32, 102,
-97, 117, 99, 105, 98, 117, 115, 32, 115, 111, 100, 97, 108, 101, 115, 32, 109, 101, 116, 117, 115, 46, 32, 85, 116, 32, 99, 111, 110, 103, 117, 101,
-46, 32, 68, 111, 110, 101, 99, 32, 97, 114, 99, 117, 32, 116, 101, 108, 108, 117, 115, 44, 32, 112, 104, 97, 114, 101, 116, 114, 97, 32, 97, 99,
-44, 32, 118, 117, 108, 112, 117, 116, 97, 116, 101, 32, 97, 99, 44, 32, 109, 111, 108, 108, 105, 115, 32, 115, 101, 100, 44, 32, 108, 101, 99, 116,
-117, 115, 46, 32, 78, 117, 108, 108, 97, 32, 102, 97, 99, 105, 108, 105, 115, 105, 46, 32, 78, 117, 108, 108, 97, 109, 32, 118, 111, 108, 117, 116,
-112, 97, 116, 32, 110, 117, 110, 99, 32, 101, 116, 32, 102, 101, 108, 105, 115, 46, 32, 83, 101, 100, 32, 112, 101, 100, 101, 32, 111, 100, 105, 111,
-44, 32, 116, 105, 110, 99, 105, 100, 117, 110, 116, 32, 105, 110, 44, 32, 118, 111, 108, 117, 116, 112, 97, 116, 32, 109, 97, 108, 101, 115, 117, 97,
-100, 97, 44, 32, 102, 101, 117, 103, 105, 97, 116, 32, 103, 114, 97, 118, 105, 100, 97, 44, 32, 110, 117, 108, 108, 97, 46, 32, 78, 117, 108, 108,
-97, 32, 97, 108, 105, 113, 117, 97, 109, 32, 112, 101, 100, 101, 32, 118, 105, 116, 97, 101, 32, 97, 114, 99, 117, 46, 32, 80, 114, 111, 105, 110,
-32, 118, 101, 108, 105, 116, 32, 101, 108, 105, 116, 44, 32, 110, 111, 110, 117, 109, 109, 121, 32, 115, 105, 116, 32, 97, 109, 101, 116, 44, 32, 101,
-108, 101, 109, 101, 110, 116, 117, 109, 32, 118, 105, 116, 97, 101, 44, 32, 118, 97, 114, 105, 117, 115, 32, 118, 105, 116, 97, 101, 44, 32, 100, 111,
-108, 111, 114, 46, 32, 68, 111, 110, 101, 99, 32, 114, 117, 116, 114, 117, 109, 32, 105, 112, 115, 117, 109, 32, 101, 117, 32, 109, 105, 46, 32, 65,
-108, 105, 113, 117, 97, 109, 32, 101, 116, 32, 115, 101, 109, 46, 32, 73, 110, 32, 97, 100, 105, 112, 105, 115, 99, 105, 110, 103, 32, 114, 104, 111,
-110, 99, 117, 115, 32, 118, 101, 108, 105, 116, 46, 32, 78, 97, 109, 32, 118, 105, 118, 101, 114, 114, 97, 32, 115, 99, 101, 108, 101, 114, 105, 115,
-113, 117, 101, 32, 97, 114, 99, 117, 46, 32, 65, 108, 105, 113, 117, 97, 109, 32, 115, 101, 109, 46, 32, 83, 101, 100, 32, 116, 105, 110, 99, 105,
-100, 117, 110, 116, 32, 110, 117, 108, 108, 97, 32, 113, 117, 105, 115, 32, 109, 97, 115, 115, 97, 46, 32, 77, 97, 117, 114, 105, 115, 32, 102, 97,
-117, 99, 105, 98, 117, 115, 32, 116, 101, 109, 112, 117, 115, 32, 110, 117, 110, 99, 46, 32, 80, 104, 97, 115, 101, 108, 108, 117, 115, 32, 99, 111,
-110, 100, 105, 109, 101, 110, 116, 117, 109, 46, 32, 67, 117, 114, 97, 98, 105, 116, 117, 114, 32, 97, 108, 105, 113, 117, 101, 116, 32, 105, 97, 99,
-117, 108, 105, 115, 32, 115, 97, 112, 105, 101, 110, 46, 32, 78, 117, 110, 99, 32, 114, 104, 111, 110, 99, 117, 115, 44, 32, 111, 100, 105, 111, 32,
-118, 105, 116, 97, 101, 32, 98, 105, 98, 101, 110, 100, 117, 109, 32, 100, 105, 103, 110, 105, 115, 115, 105, 109, 44, 32, 116, 101, 108, 108, 117, 115,
-32, 108, 105, 98, 101, 114, 111, 32, 99, 111, 109, 109, 111, 100, 111, 32, 105, 112, 115, 117, 109, 44, 32, 117, 116, 32, 115, 111, 108, 108, 105, 99,
-105, 116, 117, 100, 105, 110, 32, 110, 105, 115, 108, 32, 110, 105, 115, 108, 32, 118, 101, 108, 32, 106, 117, 115, 116, 111, 46, 32, 78, 117, 108, 108,
-97, 32, 102, 97, 99, 105, 108, 105, 115, 105, 46, 32, 80, 114, 97, 101, 115, 101, 110, 116, 32, 98, 108, 97, 110, 100, 105, 116, 32, 101, 110, 105,
-109, 32, 117, 116, 32, 106, 117, 115, 116, 111, 46, 32, 80, 114, 111, 105, 110, 32, 101, 108, 101, 109, 101, 110, 116, 117, 109, 44, 32, 101, 108, 105,
-116, 32, 101, 103, 101, 116, 32, 97, 99, 99, 117, 109, 115, 97, 110, 32, 112, 117, 108, 118, 105, 110, 97, 114, 44, 32, 111, 114, 99, 105, 32, 113,
-117, 97, 109, 32, 97, 117, 99, 116, 111, 114, 32, 110, 101, 113, 117, 101, 44, 32, 115, 101, 100, 32, 99, 111, 110, 118, 97, 108, 108, 105, 115, 32,
-100, 105, 97, 109, 32, 112, 117, 114, 117, 115, 32, 118, 101, 108, 32, 102, 101, 108, 105, 115, 46, 32, 83, 101, 100, 32, 111, 114, 99, 105, 32, 108,
-101, 111, 44, 32, 101, 108, 101, 105, 102, 101, 110, 100, 32, 118, 101, 108, 44, 32, 98, 108, 97, 110, 100, 105, 116, 32, 110, 111, 110, 44, 32, 115,
-101, 109, 112, 101, 114, 32, 101, 117, 44, 32, 112, 117, 114, 117, 115, 46, 32, 80, 114, 111, 105, 110, 32, 98, 105, 98, 101, 110, 100, 117, 109, 44,
-32, 108, 105, 98, 101, 114, 111, 32, 97, 99, 32, 99, 111, 110, 115, 101, 99, 116, 101, 116, 117, 101, 114, 32, 99, 111, 109, 109, 111, 100, 111, 44,
-32, 101, 114, 111, 115, 32, 115, 97, 112, 105, 101, 110, 32, 98, 108, 97, 110, 100, 105, 116, 32, 110, 105, 115, 108, 44, 32, 101, 117, 32, 101, 108,
-101, 105, 102, 101, 110, 100, 32, 110, 105, 98, 104, 32, 110, 105, 98, 104, 32, 118, 101, 108, 32, 108, 101, 99, 116, 117, 115, 46, 32, 86, 105, 118,
-97, 109, 117, 115, 32, 112, 108, 97, 99, 101, 114, 97, 116, 46, 32, 73, 110, 116, 101, 103, 101, 114, 32, 111, 100, 105, 111, 32, 100, 111, 108, 111,
-114, 44, 32, 112, 104, 97, 114, 101, 116, 114, 97, 32, 110, 111, 110, 44, 32, 115, 111, 100, 97, 108, 101, 115, 32, 105, 100, 44, 32, 118, 105, 118,
-101, 114, 114, 97, 32, 101, 103, 101, 116, 44, 32, 100, 105, 97, 109, 46, 32, 78, 117, 110, 99, 32, 109, 97, 117, 114, 105, 115, 32, 109, 97, 103,
-110, 97, 44, 32, 101, 103, 101, 115, 116, 97, 115, 32, 113, 117, 105, 115, 44, 32, 102, 101, 117, 103, 105, 97, 116, 32, 105, 100, 44, 32, 102, 101,
-114, 109, 101, 110, 116, 117, 109, 32, 118, 105, 118, 101, 114, 114, 97, 44, 32, 109, 105, 46, 32, 65, 101, 110, 101, 97, 110, 32, 115, 117, 115, 99,
-105, 112, 105, 116, 32, 110, 105, 115, 108, 32, 110, 111, 110, 32, 110, 117, 110, 99, 46, 32, 80, 114, 111, 105, 110, 32, 113, 117, 105, 115, 32, 108,
-101, 99, 116, 117, 115, 32, 97, 99, 32, 116, 101, 108, 108, 117, 115, 32, 110, 111, 110, 117, 109, 109, 121, 32, 99, 111, 109, 109, 111, 100, 111, 46,
-32, 78, 117, 110, 99, 32, 101, 103, 101, 116, 32, 100, 105, 97, 109, 32, 97, 99, 32, 101, 108, 105, 116, 32, 118, 101, 115, 116, 105, 98, 117, 108,
-117, 109, 32, 97, 117, 99, 116, 111, 114, 46, 32, 69, 116, 105, 97, 109, 32, 118, 117, 108, 112, 117, 116, 97, 116, 101, 44, 32, 111, 100, 105, 111,
-32, 115, 101, 100, 32, 108, 97, 99, 105, 110, 105, 97, 32, 99, 111, 110, 115, 101, 113, 117, 97, 116, 44, 32, 106, 117, 115, 116, 111, 32, 109, 105,
-32, 118, 117, 108, 112, 117, 116, 97, 116, 101, 32, 112, 117, 114, 117, 115, 44, 32, 115, 105, 116, 32, 97, 109, 101, 116, 32, 101, 117, 105, 115, 109,
-111, 100, 32, 108, 105, 98, 101, 114, 111, 32, 109, 101, 116, 117, 115, 32, 115, 101, 100, 32, 116, 111, 114, 116, 111, 114, 46, 32, 77, 97, 101, 99,
-101, 110, 97, 115, 32, 97, 99, 32, 101, 108, 105, 116, 32, 115, 101, 100, 32, 108, 111, 114, 101, 109, 32, 118, 117, 108, 112, 117, 116, 97, 116, 101,
-32, 103, 114, 97, 118, 105, 100, 97, 46, 32, 80, 114, 111, 105, 110, 32, 108, 101, 99, 116, 117, 115, 32, 101, 114, 111, 115, 44, 32, 117, 108, 108,
-97, 109, 99, 111, 114, 112, 101, 114, 32, 105, 100, 44, 32, 118, 111, 108, 117, 116, 112, 97, 116, 32, 113, 117, 105, 115, 44, 32, 99, 111, 110, 100,
-105, 109, 101, 110, 116, 117, 109, 32, 116, 105, 110, 99, 105, 100, 117, 110, 116, 44, 32, 115, 97, 112, 105, 101, 110, 46, 32, 83, 101, 100, 32, 101,
-116, 32, 109, 97, 115, 115, 97, 32, 101, 103, 101, 116, 32, 108, 111, 114, 101, 109, 32, 97, 108, 105, 113, 117, 101, 116, 32, 116, 101, 109, 112, 117,
-115, 46, 32, 68, 117, 105, 115, 32, 112, 111, 114, 116, 116, 105, 116, 111, 114, 32, 110, 105, 115, 108, 32, 110, 111, 110, 32, 114, 105, 115, 117, 115,
-46, 32, 78, 97, 109, 32, 105, 100, 32, 113, 117, 97, 109, 46, 32, 78, 117, 108, 108, 97, 109, 32, 101, 115, 116, 46, 32, 80, 114, 111, 105, 110,
-32, 111, 114, 99, 105, 32, 100, 105, 97, 109, 44, 32, 112, 111, 115, 117, 101, 114, 101, 32, 101, 116, 44, 32, 112, 104, 97, 114, 101, 116, 114, 97,
-32, 99, 111, 109, 109, 111, 100, 111, 44, 32, 100, 105, 99, 116, 117, 109, 32, 118, 101, 108, 44, 32, 101, 110, 105, 109, 46, 32, 80, 114, 111, 105,
-110, 32, 101, 103, 101, 116, 32, 101, 114, 97, 116, 46, 32, 68, 111, 110, 101, 99, 32, 110, 105, 115, 108, 46, 32, 77, 97, 101, 99, 101, 110, 97,
-115, 32, 97, 117, 99, 116, 111, 114, 32, 118, 101, 108, 105, 116, 32, 117, 116, 32, 112, 101, 100, 101, 46, 32, 78, 117, 110, 99, 32, 118, 105, 116,
-97, 101, 32, 108, 101, 99, 116, 117, 115, 32, 110, 101, 99, 32, 108, 105, 98, 101, 114, 111, 32, 116, 105, 110, 99, 105, 100, 117, 110, 116, 32, 104,
-101, 110, 100, 114, 101, 114, 105, 116, 46, 32, 81, 117, 105, 115, 113, 117, 101, 32, 118, 97, 114, 105, 117, 115, 44, 32, 101, 114, 97, 116, 32, 117,
-108, 116, 114, 105, 99, 101, 115, 32, 117, 108, 116, 114, 105, 99, 101, 115, 32, 101, 117, 105, 115, 109, 111, 100, 44, 32, 112, 117, 114, 117, 115, 32,
-108, 97, 99, 117, 115, 32, 100, 105, 99, 116, 117, 109, 32, 101, 114, 111, 115, 44, 32, 97, 116, 32, 99, 111, 110, 100, 105, 109, 101, 110, 116, 117,
-109, 32, 101, 110, 105, 109, 32, 100, 117, 105, 32, 110, 101, 99, 32, 109, 97, 103, 110, 97, 46, 32, 77, 111, 114, 98, 105, 32, 100, 105, 97, 109,
-46, 32, 80, 104, 97, 115, 101, 108, 108, 117, 115, 32, 115, 101, 100, 32, 101, 115, 116, 46, 32, 80, 104, 97, 115, 101, 108, 108, 117, 115, 32, 110,
-101, 99, 32, 108, 105, 98, 101, 114, 111, 32, 105, 110, 32, 97, 114, 99, 117, 32, 102, 114, 105, 110, 103, 105, 108, 108, 97, 32, 115, 111, 108, 108,
-105, 99, 105, 116, 117, 100, 105, 110, 46, 32, 73, 110, 32, 114, 117, 116, 114, 117, 109, 32, 110, 105, 115, 108, 32, 97, 116, 32, 97, 114, 99, 117,
-46, 32, 78, 117, 108, 108, 97, 32, 102, 97, 99, 105, 108, 105, 115, 105, 46, 32, 77, 97, 117, 114, 105, 115, 32, 100, 105, 103, 110, 105, 115, 115,
-105, 109, 46, 32, 69, 116, 105, 97, 109, 32, 101, 115, 116, 32, 109, 97, 117, 114, 105, 115, 44, 32, 112, 104, 97, 114, 101, 116, 114, 97, 32, 115,
-101, 100, 44, 32, 118, 105, 118, 101, 114, 114, 97, 32, 101, 116, 44, 32, 116, 105, 110, 99, 105, 100, 117, 110, 116, 32, 115, 101, 100, 44, 32, 110,
-101, 113, 117, 101, 46, 32, 85, 116, 32, 97, 116, 32, 108, 101, 99, 116, 117, 115, 32, 105, 100, 32, 110, 105, 98, 104, 32, 108, 117, 99, 116, 117,
-115, 32, 111, 114, 110, 97, 114, 101, 46, 32, 77, 97, 117, 114, 105, 115, 32, 118, 97, 114, 105, 117, 115, 32, 112, 111, 114, 116, 116, 105, 116, 111,
-114, 32, 114, 105, 115, 117, 115, 46, 32, 85, 116, 32, 118, 117, 108, 112, 117, 116, 97, 116, 101, 32, 97, 108, 105, 113, 117, 101, 116, 32, 114, 105,
-115, 117, 115, 46, 32, 86, 101, 115, 116, 105, 98, 117, 108, 117, 109, 32, 108, 117, 99, 116, 117, 115, 32, 110, 101, 113, 117, 101, 32, 115, 105, 116,
-32, 97, 109, 101, 116, 32, 110, 117, 110, 99, 46, 32, 68, 117, 105, 115, 32, 102, 101, 114, 109, 101, 110, 116, 117, 109, 32, 110, 105, 98, 104, 46,
-32, 80, 101, 108, 108, 101, 110, 116, 101, 115, 113, 117, 101, 32, 100, 97, 112, 105, 98, 117, 115, 46, 32, 80, 114, 111, 105, 110, 32, 101, 114, 111,
-115, 32, 108, 105, 98, 101, 114, 111, 44, 32, 97, 108, 105, 113, 117, 97, 109, 32, 110, 111, 110, 44, 32, 99, 111, 110, 100, 105, 109, 101, 110, 116,
-117, 109, 32, 97, 44, 32, 115, 111, 100, 97, 108, 101, 115, 32, 117, 116, 44, 32, 116, 117, 114, 112, 105, 115, 46, 32, 73, 110, 116, 101, 103, 101,
-114, 32, 97, 99, 99, 117, 109, 115, 97, 110, 32, 109, 105, 32, 115, 101, 100, 32, 108, 111, 114, 101, 109, 46, 32, 86, 101, 115, 116, 105, 98, 117,
-108, 117, 109, 32, 112, 101, 108, 108, 101, 110, 116, 101, 115, 113, 117, 101, 32, 115, 111, 100, 97, 108, 101, 115, 32, 110, 105, 115, 108, 46, 32, 78,
-117, 108, 108, 97, 32, 101, 117, 32, 106, 117, 115, 116, 111, 32, 113, 117, 105, 115, 32, 100, 117, 105, 32, 112, 114, 101, 116, 105, 117, 109, 32, 114,
-104, 111, 110, 99, 117, 115, 46, 32, 80, 114, 97, 101, 115, 101, 110, 116, 32, 118, 105, 118, 101, 114, 114, 97, 32, 99, 111, 109, 109, 111, 100, 111,
-32, 109, 105, 46, 32, 77, 97, 101, 99, 101, 110, 97, 115, 32, 100, 111, 108, 111, 114, 32, 108, 105, 98, 101, 114, 111, 44, 32, 118, 105, 118, 101,
-114, 114, 97, 32, 97, 44, 32, 101, 108, 101, 109, 101, 110, 116, 117, 109, 32, 118, 105, 116, 97, 101, 44, 32, 97, 108, 105, 113, 117, 101, 116, 32,
-118, 105, 116, 97, 101, 44, 32, 100, 117, 105, 46, 32, 77, 97, 117, 114, 105, 115, 32, 99, 111, 110, 118, 97, 108, 108, 105, 115, 32, 108, 101, 99,
-116, 117, 115, 32, 101, 116, 32, 109, 105, 46, 32, 77, 97, 117, 114, 105, 115, 32, 115, 97, 103, 105, 116, 116, 105, 115, 46, 32, 83, 101, 100, 32,
-97, 114, 99, 117, 46, 32, 80, 101, 108, 108, 101, 110, 116, 101, 115, 113, 117, 101, 32, 97, 117, 99, 116, 111, 114, 46, 32, 68, 111, 110, 101, 99,
-32, 112, 101, 108, 108, 101, 110, 116, 101, 115, 113, 117, 101, 32, 112, 117, 114, 117, 115, 32, 110, 111, 110, 32, 116, 101, 108, 108, 117, 115, 46, 32,
-85, 116, 32, 108, 101, 111, 32, 119, 105, 115, 105, 44, 32, 117, 108, 116, 114, 105, 99, 101, 115, 32, 115, 105, 116, 32, 97, 109, 101, 116, 44, 32,
-117, 108, 116, 114, 105, 99, 101, 115, 32, 101, 117, 44, 32, 103, 114, 97, 118, 105, 100, 97, 32, 97, 99, 44, 32, 108, 105, 98, 101, 114, 111, 46,
-32, 77, 97, 117, 114, 105, 115, 32, 102, 101, 114, 109, 101, 110, 116, 117, 109, 32, 100, 97, 112, 105, 98, 117, 115, 32, 100, 105, 97, 109, 46, 32,
-73, 110, 116, 101, 103, 101, 114, 32, 113, 117, 105, 115, 32, 108, 97, 99, 117, 115, 32, 100, 97, 112, 105, 98, 117, 115, 32, 111, 100, 105, 111, 32,
-112, 101, 108, 108, 101, 110, 116, 101, 115, 113, 117, 101, 32, 118, 97, 114, 105, 117, 115, 46, 32, 70, 117, 115, 99, 101, 32, 112, 101, 100, 101, 32,
-113, 117, 97, 109, 44, 32, 118, 101, 104, 105, 99, 117, 108, 97, 32, 117, 116, 44, 32, 112, 117, 108, 118, 105, 110, 97, 114, 32, 101, 116, 44, 32,
-116, 105, 110, 99, 105, 100, 117, 110, 116, 32, 115, 101, 100, 44, 32, 102, 101, 108, 105, 115, 46, 32, 67, 117, 114, 97, 98, 105, 116, 117, 114, 32,
-101, 114, 111, 115, 32, 101, 110, 105, 109, 44, 32, 118, 117, 108, 112, 117, 116, 97, 116, 101, 32, 115, 101, 100, 44, 32, 97, 108, 105, 113, 117, 97,
-109, 32, 97, 99, 44, 32, 101, 117, 105, 115, 109, 111, 100, 32, 97, 99, 44, 32, 101, 114, 97, 116, 46, 32, 85, 116, 32, 100, 105, 103, 110, 105,
-115, 115, 105, 109, 44, 32, 108, 97, 99, 117, 115, 32, 97, 32, 105, 110, 116, 101, 114, 100, 117, 109, 32, 105, 97, 99, 117, 108, 105, 115, 44, 32,
-101, 110, 105, 109, 32, 111, 114, 99, 105, 32, 112, 111, 115, 117, 101, 114, 101, 32, 110, 117, 110, 99, 44, 32, 110, 101, 99, 32, 117, 108, 116, 114,
-105, 99, 105, 101, 115, 32, 108, 101, 99, 116, 117, 115, 32, 114, 105, 115, 117, 115, 32, 105, 110, 32, 111, 100, 105, 111, 46, 32, 69, 116, 105, 97,
-109, 32, 101, 116, 32, 109, 97, 115, 115, 97, 32, 105, 100, 32, 100, 117, 105, 32, 99, 111, 109, 109, 111, 100, 111, 32, 118, 101, 104, 105, 99, 117,
-108, 97, 46, 32, 78, 117, 110, 99, 32, 98, 108, 97, 110, 100, 105, 116, 32, 116, 111, 114, 116, 111, 114, 32, 113, 117, 105, 115, 32, 100, 117, 105,
-46, 32, 81, 117, 105, 115, 113, 117, 101, 32, 110, 105, 115, 108, 46, 32, 83, 101, 100, 32, 118, 101, 110, 101, 110, 97, 116, 105, 115, 32, 98, 108,
-97, 110, 100, 105, 116, 32, 108, 105, 103, 117, 108, 97, 46, 32, 70, 117, 115, 99, 101, 32, 118, 105, 118, 101, 114, 114, 97, 32, 105, 109, 112, 101,
-114, 100, 105, 101, 116, 32, 109, 97, 103, 110, 97, 46, 32, 68, 111, 110, 101, 99, 32, 101, 103, 101, 116, 32, 110, 117, 110, 99, 32, 113, 117, 105,
-115, 32, 101, 115, 116, 32, 112, 104, 97, 114, 101, 116, 114, 97, 32, 108, 111, 98, 111, 114, 116, 105, 115, 46, 32, 86, 101, 115, 116, 105, 98, 117,
-108, 117, 109, 32, 113, 117, 105, 115, 32, 108, 101, 99, 116, 117, 115, 46, 32, 77, 97, 117, 114, 105, 115, 32, 118, 101, 108, 32, 111, 114, 99, 105,
-32, 108, 111, 98, 111, 114, 116, 105, 115, 32, 110, 117, 110, 99, 32, 102, 101, 114, 109, 101, 110, 116, 117, 109, 32, 98, 105, 98, 101, 110, 100, 117,
-109, 46, 32, 80, 101, 108, 108, 101, 110, 116, 101, 115, 113, 117, 101, 32, 101, 103, 101, 116, 32, 108, 101, 111, 46, 32, 77, 111, 114, 98, 105, 32,
-118, 101, 108, 32, 117, 114, 110, 97, 32, 115, 105, 116, 32, 97, 109, 101, 116, 32, 101, 114, 97, 116, 32, 102, 101, 114, 109, 101, 110, 116, 117, 109,
-32, 102, 97, 99, 105, 108, 105, 115, 105, 115, 46, 32, 83, 101, 100, 32, 118, 117, 108, 112, 117, 116, 97, 116, 101, 44, 32, 108, 105, 98, 101, 114,
-111, 32, 101, 116, 32, 115, 111, 108, 108, 105, 99, 105, 116, 117, 100, 105, 110, 32, 99, 111, 110, 103, 117, 101, 44, 32, 119, 105, 115, 105, 32, 108,
-101, 99, 116, 117, 115, 32, 115, 111, 100, 97, 108, 101, 115, 32, 100, 111, 108, 111, 114, 44, 32, 101, 103, 101, 116, 32, 109, 111, 108, 101, 115, 116,
-105, 101, 32, 109, 97, 103, 110, 97, 32, 111, 114, 99, 105, 32, 118, 101, 108, 32, 116, 101, 108, 108, 117, 115, 46, 32, 83, 101, 100, 32, 116, 101,
-109, 112, 111, 114, 32, 97, 110, 116, 101, 32, 101, 116, 32, 101, 110, 105, 109, 46, 32, 77, 97, 117, 114, 105, 115, 32, 101, 108, 105, 116, 46, 32,
-67, 117, 114, 97, 98, 105, 116, 117, 114, 32, 117, 108, 108, 97, 109, 99, 111, 114, 112, 101, 114, 32, 118, 101, 104, 105, 99, 117, 108, 97, 32, 109,
-97, 115, 115, 97, 46, 32, 83, 101, 100, 32, 118, 105, 118, 101, 114, 114, 97, 46, 32, 68, 117, 105, 115, 32, 110, 117, 108, 108, 97, 46, 32, 78,
-97, 109, 32, 98, 105, 98, 101, 110, 100, 117, 109, 46, 32, 78, 97, 109, 32, 116, 111, 114, 116, 111, 114, 32, 108, 111, 114, 101, 109, 44, 32, 117,
-108, 108, 97, 109, 99, 111, 114, 112, 101, 114, 32, 118, 105, 116, 97, 101, 44, 32, 100, 105, 99, 116, 117, 109, 32, 115, 101, 100, 44, 32, 112, 111,
-115, 117, 101, 114, 101, 32, 101, 117, 44, 32, 106, 117, 115, 116, 111, 46, 32, 65, 108, 105, 113, 117, 97, 109, 32, 97, 100, 105, 112, 105, 115, 99,
-105, 110, 103, 32, 97, 114, 99, 117, 32, 118, 105, 116, 97, 101, 32, 116, 117, 114, 112, 105, 115, 46, 32, 68, 111, 110, 101, 99, 32, 109, 97, 108,
-101, 115, 117, 97, 100, 97, 32, 112, 111, 115, 117, 101, 114, 101, 32, 108, 105, 98, 101, 114, 111, 46, 32, 85, 116, 32, 115, 101, 100, 32, 116, 101,
-108, 108, 117, 115, 46, 32, 70, 117, 115, 99, 101, 32, 115, 101, 100, 32, 110, 117, 110, 99, 32, 101, 103, 101, 116, 32, 110, 105, 115, 108, 32, 100,
-97, 112, 105, 98, 117, 115, 32, 109, 97, 108, 101, 115, 117, 97, 100, 97, 46, 32, 83, 117, 115, 112, 101, 110, 100, 105, 115, 115, 101, 32, 112, 111,
-116, 101, 110, 116, 105, 46, 32, 73, 110, 116, 101, 103, 101, 114, 32, 116, 114, 105, 115, 116, 105, 113, 117, 101, 32, 108, 105, 98, 101, 114, 111, 32,
-101, 116, 32, 109, 101, 116, 117, 115, 46, 32, 86, 105, 118, 97, 109, 117, 115, 32, 112, 111, 115, 117, 101, 114, 101, 46, 32, 77, 97, 101, 99, 101,
-110, 97, 115, 32, 110, 111, 110, 32, 115, 101, 109, 32, 110, 111, 110, 32, 113, 117, 97, 109, 32, 102, 101, 114, 109, 101, 110, 116, 117, 109, 32, 98,
-108, 97, 110, 100, 105, 116, 46, 32, 68, 117, 105, 115, 32, 114, 105, 115, 117, 115, 32, 116, 101, 108, 108, 117, 115, 44, 32, 114, 117, 116, 114, 117,
-109, 32, 118, 105, 116, 97, 101, 44, 32, 105, 109, 112, 101, 114, 100, 105, 101, 116, 32, 110, 101, 99, 44, 32, 109, 97, 108, 101, 115, 117, 97, 100,
-97, 32, 110, 101, 99, 44, 32, 105, 112, 115, 117, 109, 46, 32, 78, 117, 110, 99, 32, 113, 117, 97, 109, 32, 100, 111, 108, 111, 114, 44, 32, 108,
-117, 99, 116, 117, 115, 32, 101, 103, 101, 116, 44, 32, 112, 108, 97, 99, 101, 114, 97, 116, 32, 110, 111, 110, 44, 32, 114, 104, 111, 110, 99, 117,
-115, 32, 97, 116, 44, 32, 116, 101, 108, 108, 117, 115, 46, 32, 68, 117, 105, 115, 32, 112, 101, 100, 101, 32, 108, 101, 99, 116, 117, 115, 44, 32,
-109, 97, 116, 116, 105, 115, 32, 97, 100, 105, 112, 105, 115, 99, 105, 110, 103, 44, 32, 116, 101, 109, 112, 111, 114, 32, 117, 116, 44, 32, 112, 111,
-114, 116, 97, 32, 97, 116, 44, 32, 109, 105, 46, 32, 80, 101, 108, 108, 101, 110, 116, 101, 115, 113, 117, 101, 32, 114, 105, 115, 117, 115, 32, 110,
-117, 108, 108, 97, 44, 32, 115, 111, 100, 97, 108, 101, 115, 32, 115, 101, 100, 44, 32, 105, 110, 116, 101, 114, 100, 117, 109, 32, 105, 100, 44, 32,
-110, 111, 110, 117, 109, 109, 121, 32, 118, 105, 116, 97, 101, 44, 32, 108, 105, 103, 117, 108, 97, 46, 32, 77, 111, 114, 98, 105, 32, 112, 117, 108,
-118, 105, 110, 97, 114, 32, 112, 101, 100, 101, 32, 117, 116, 32, 109, 97, 115, 115, 97, 46, 32, 78, 117, 110, 99, 32, 114, 105, 115, 117, 115, 32,
-109, 97, 117, 114, 105, 115, 44, 32, 116, 105, 110, 99, 105, 100, 117, 110, 116, 32, 101, 116, 44, 32, 102, 97, 117, 99, 105, 98, 117, 115, 32, 101,
-117, 44, 32, 115, 117, 115, 99, 105, 112, 105, 116, 32, 118, 101, 108, 44, 32, 111, 114, 99, 105, 46, 32, 73, 110, 32, 102, 97, 117, 99, 105, 98,
-117, 115, 32, 102, 101, 108, 105, 115, 32, 105, 110, 32, 97, 114, 99, 117, 46, 32, 78, 117, 108, 108, 97, 32, 115, 105, 116, 32, 97, 109, 101, 116,
-32, 101, 108, 105, 116, 46, 32, 78, 117, 108, 108, 97, 32, 101, 114, 97, 116, 32, 115, 97, 112, 105, 101, 110, 44, 32, 115, 97, 103, 105, 116, 116,
-105, 115, 32, 101, 103, 101, 116, 44, 32, 100, 105, 103, 110, 105, 115, 115, 105, 109, 32, 101, 103, 101, 116, 44, 32, 118, 105, 118, 101, 114, 114, 97,
-32, 101, 117, 44, 32, 102, 101, 108, 105, 115, 46, 32, 78, 97, 109, 32, 97, 99, 32, 105, 112, 115, 117, 109, 46, 32, 83, 117, 115, 112, 101, 110,
-100, 105, 115, 115, 101, 32, 118, 117, 108, 112, 117, 116, 97, 116, 101, 32, 116, 117, 114, 112, 105, 115, 32, 118, 101, 108, 32, 115, 101, 109, 32, 108,
-97, 99, 105, 110, 105, 97, 32, 117, 108, 108, 97, 109, 99, 111, 114, 112, 101, 114, 46, 32, 77, 97, 117, 114, 105, 115, 32, 111, 114, 110, 97, 114,
-101, 32, 105, 112, 115, 117, 109, 32, 115, 101, 100, 32, 108, 105, 103, 117, 108, 97, 46, 32, 68, 117, 105, 115, 32, 102, 97, 99, 105, 108, 105, 115,
-105, 115, 32, 110, 101, 113, 117, 101, 32, 113, 117, 105, 115, 32, 111, 114, 99, 105, 46, 32, 78, 117, 108, 108, 97, 109, 32, 101, 116, 32, 101, 114,
-97, 116, 32, 101, 116, 32, 111, 114, 99, 105, 32, 108, 97, 99, 105, 110, 105, 97, 32, 112, 101, 108, 108, 101, 110, 116, 101, 115, 113, 117, 101, 46,
-32, 68, 111, 110, 101, 99, 32, 97, 99, 32, 105, 112, 115, 117, 109, 46, 32, 68, 117, 105, 115, 32, 109, 111, 108, 101, 115, 116, 105, 101, 32, 105,
-112, 115, 117, 109, 32, 97, 99, 32, 97, 114, 99, 117, 46, 32, 65, 101, 110, 101, 97, 110, 32, 99, 111, 110, 103, 117, 101, 32, 97, 99, 99, 117,
-109, 115, 97, 110, 32, 97, 110, 116, 101, 46, 32, 73, 110, 116, 101, 103, 101, 114, 32, 98, 105, 98, 101, 110, 100, 117, 109, 44, 32, 108, 101, 111,
-32, 117, 116, 32, 111, 114, 110, 97, 114, 101, 32, 97, 108, 105, 113, 117, 97, 109, 44, 32, 110, 117, 110, 99, 32, 101, 114, 97, 116, 32, 99, 111,
-110, 100, 105, 109, 101, 110, 116, 117, 109, 32, 97, 114, 99, 117, 44, 32, 117, 116, 32, 112, 117, 108, 118, 105, 110, 97, 114, 32, 109, 105, 32, 97,
-117, 103, 117, 101, 32, 101, 116, 32, 110, 117, 108, 108, 97, 46, 32, 81, 117, 105, 115, 113, 117, 101, 32, 108, 97, 99, 105, 110, 105, 97, 32, 97,
-108, 105, 113, 117, 101, 116, 32, 119, 105, 115, 105, 46, 32, 86, 105, 118, 97, 109, 117, 115, 32, 110, 101, 99, 32, 100, 117, 105, 46, 32, 69, 116,
-105, 97, 109, 32, 119, 105, 115, 105, 32, 108, 101, 111, 44, 32, 101, 117, 105, 115, 109, 111, 100, 32, 118, 105, 116, 97, 101, 44, 32, 118, 117, 108,
-112, 117, 116, 97, 116, 101, 32, 97, 44, 32, 100, 105, 99, 116, 117, 109, 32, 118, 105, 116, 97, 101, 44, 32, 113, 117, 97, 109, 46, 32, 81, 117,
-105, 115, 113, 117, 101, 32, 113, 117, 105, 115, 32, 116, 111, 114, 116, 111, 114, 46, 32, 69, 116, 105, 97, 109, 32, 105, 110, 116, 101, 114, 100, 117,
-109, 46, 32, 73, 110, 32, 109, 97, 115, 115, 97, 32, 101, 114, 97, 116, 44, 32, 112, 111, 114, 116, 116, 105, 116, 111, 114, 32, 115, 101, 100, 44,
-32, 116, 105, 110, 99, 105, 100, 117, 110, 116, 32, 118, 101, 108, 44, 32, 118, 101, 104, 105, 99, 117, 108, 97, 32, 102, 114, 105, 110, 103, 105, 108,
-108, 97, 44, 32, 97, 117, 103, 117, 101, 46, 32, 78, 117, 108, 108, 97, 32, 118, 101, 108, 32, 117, 114, 110, 97, 46, 32, 73, 110, 32, 108, 105,
-98, 101, 114, 111, 32, 109, 105, 44, 32, 112, 114, 101, 116, 105, 117, 109, 32, 115, 101, 100, 44, 32, 109, 97, 116, 116, 105, 115, 32, 116, 101, 109,
-112, 117, 115, 44, 32, 115, 97, 103, 105, 116, 116, 105, 115, 32, 115, 101, 100, 44, 32, 109, 97, 115, 115, 97, 46, 32, 83, 117, 115, 112, 101, 110,
-100, 105, 115, 115, 101, 32, 113, 117, 97, 109, 32, 119, 105, 115, 105, 44, 32, 102, 101, 114, 109, 101, 110, 116, 117, 109, 32, 113, 117, 105, 115, 44,
-32, 115, 97, 103, 105, 116, 116, 105, 115, 32, 97, 116, 44, 32, 99, 111, 110, 115, 101, 113, 117, 97, 116, 32, 101, 103, 101, 116, 44, 32, 111, 100,
-105, 111, 46, 32, 78, 117, 108, 108, 97, 109, 32, 105, 109, 112, 101, 114, 100, 105, 101, 116, 44, 32, 112, 117, 114, 117, 115, 32, 113, 117, 105, 115,
-32, 97, 108, 105, 113, 117, 97, 109, 32, 99, 117, 114, 115, 117, 115, 44, 32, 116, 117, 114, 112, 105, 115, 32, 111, 100, 105, 111, 32, 101, 103, 101,
-115, 116, 97, 115, 32, 106, 117, 115, 116, 111, 44, 32, 112, 108, 97, 99, 101, 114, 97, 116, 32, 103, 114, 97, 118, 105, 100, 97, 32, 116, 117, 114,
-112, 105, 115, 32, 119, 105, 115, 105, 32, 118, 101, 108, 32, 116, 111, 114, 116, 111, 114, 46, 32, 78, 117, 110, 99, 32, 117, 108, 116, 114, 105, 99,
-105, 101, 115, 32, 112, 111, 114, 116, 97, 32, 112, 117, 114, 117, 115, 46, 32, 80, 114, 111, 105, 110, 32, 101, 108, 101, 109, 101, 110, 116, 117, 109,
-32, 101, 114, 97, 116, 32, 97, 99, 32, 111, 114, 99, 105, 46, 32, 85, 116, 32, 118, 101, 108, 32, 109, 97, 103, 110, 97, 32, 110, 101, 99, 32,
-109, 105, 32, 102, 101, 117, 103, 105, 97, 116, 32, 116, 105, 110, 99, 105, 100, 117, 110, 116, 46, 32, 85, 116, 32, 108, 105, 103, 117, 108, 97, 46,
-32, 86, 101, 115, 116, 105, 98, 117, 108, 117, 109, 32, 97, 110, 116, 101, 32, 105, 112, 115, 117, 109, 32, 112, 114, 105, 109, 105, 115, 32, 105, 110,
-32, 102, 97, 117, 99, 105, 98, 117, 115, 32, 111, 114, 99, 105, 32, 108, 117, 99, 116, 117, 115, 32, 101, 116, 32, 117, 108, 116, 114, 105, 99, 101,
-115, 32, 112, 111, 115, 117, 101, 114, 101, 32, 99, 117, 98, 105, 108, 105, 97, 32, 67, 117, 114, 97, 101, 59, 32, 68, 111, 110, 101, 99, 32, 101,
-116, 32, 109, 97, 103, 110, 97, 32, 105, 110, 32, 100, 105, 97, 109, 32, 112, 111, 114, 116, 97, 32, 110, 111, 110, 117, 109, 109, 121, 46, 32, 77,
-97, 101, 99, 101, 110, 97, 115, 32, 117, 116, 32, 115, 101, 109, 32, 105, 110, 32, 116, 117, 114, 112, 105, 115, 32, 102, 101, 114, 109, 101, 110, 116,
-117, 109, 32, 118, 105, 118, 101, 114, 114, 97, 46, 32, 83, 117, 115, 112, 101, 110, 100, 105, 115, 115, 101, 32, 97, 116, 32, 111, 114, 99, 105, 46,
-32, 80, 101, 108, 108, 101, 110, 116, 101, 115, 113, 117, 101, 32, 104, 97, 98, 105, 116, 97, 110, 116, 32, 109, 111, 114, 98, 105, 32, 116, 114, 105,
-115, 116, 105, 113, 117, 101, 32, 115, 101, 110, 101, 99, 116, 117, 115, 32, 101, 116, 32, 110, 101, 116, 117, 115, 32, 101, 116, 32, 109, 97, 108, 101,
-115, 117, 97, 100, 97, 32, 102, 97, 109, 101, 115, 32, 97, 99, 32, 116, 117, 114, 112, 105, 115, 32, 101, 103, 101, 115, 116, 97, 115, 46, 32, 86,
-101, 115, 116, 105, 98, 117, 108, 117, 109, 32, 97, 110, 116, 101, 32, 105, 112, 115, 117, 109, 32, 112, 114, 105, 109, 105, 115, 32, 105, 110, 32, 102,
-97, 117, 99, 105, 98, 117, 115, 32, 111, 114, 99, 105, 32, 108, 117, 99, 116, 117, 115, 32, 101, 116, 32, 117, 108, 116, 114, 105, 99, 101, 115, 32,
-112, 111, 115, 117, 101, 114, 101, 32, 99, 117, 98, 105, 108, 105, 97, 32, 67, 117, 114, 97, 101, 59, 32, 80, 101, 108, 108, 101, 110, 116, 101, 115,
-113, 117, 101, 32, 114, 117, 116, 114, 117, 109, 32, 101, 108, 101, 105, 102, 101, 110, 100, 32, 106, 117, 115, 116, 111, 46, 32, 78, 117, 108, 108, 97,
-109, 32, 118, 105, 116, 97, 101, 32, 112, 101, 100, 101, 46, 32, 68, 111, 110, 101, 99, 32, 99, 111, 110, 100, 105, 109, 101, 110, 116, 117, 109, 32,
-110, 105, 98, 104, 32, 101, 116, 32, 111, 100, 105, 111, 46, 32, 83, 101, 100, 32, 101, 116, 32, 109, 101, 116, 117, 115, 46, 32, 67, 108, 97, 115,
-115, 32, 97, 112, 116, 101, 110, 116, 32, 116, 97, 99, 105, 116, 105, 32, 115, 111, 99, 105, 111, 115, 113, 117, 32, 97, 100, 32, 108, 105, 116, 111,
-114, 97, 32, 116, 111, 114, 113, 117, 101, 110, 116, 32, 112, 101, 114, 32, 99, 111, 110, 117, 98, 105, 97, 32, 110, 111, 115, 116, 114, 97, 44, 32,
-112, 101, 114, 32, 105, 110, 99, 101, 112, 116, 111, 115, 32, 104, 121, 109, 101, 110, 97, 101, 111, 115, 46, 32, 78, 97, 109, 32, 116, 101, 109, 112,
-117, 115, 46, 32, 83, 101, 100, 32, 97, 99, 32, 119, 105, 115, 105, 46, 32, 73, 110, 32, 104, 97, 99, 32, 104, 97, 98, 105, 116, 97, 115, 115,
-101, 32, 112, 108, 97, 116, 101, 97, 32, 100, 105, 99, 116, 117, 109, 115, 116, 46, 32, 83, 101, 100, 32, 115, 101, 100, 32, 119, 105, 115, 105, 46,
-32, 85, 116, 32, 102, 97, 99, 105, 108, 105, 115, 105, 115, 32, 116, 101, 108, 108, 117, 115, 32, 110, 111, 110, 32, 108, 105, 103, 117, 108, 97, 46,
-32, 73, 110, 116, 101, 103, 101, 114, 32, 109, 101, 116, 117, 115, 46, 32, 73, 110, 32, 108, 97, 99, 105, 110, 105, 97, 32, 100, 117, 105, 46, 32,
-67, 117, 114, 97, 98, 105, 116, 117, 114, 32, 111, 114, 110, 97, 114, 101, 46, 32, 77, 97, 117, 114, 105, 115, 32, 118, 101, 108, 32, 117, 114, 110,
-97, 46, 32, 78, 97, 109, 32, 99, 111, 110, 115, 101, 99, 116, 101, 116, 117, 101, 114, 32, 100, 105, 103, 110, 105, 115, 115, 105, 109, 32, 117, 114,
-110, 97, 46, 32, 78, 117, 110, 99, 32, 101, 108, 101, 109, 101, 110, 116, 117, 109, 32, 112, 111, 114, 116, 116, 105, 116, 111, 114, 32, 101, 114, 97,
-116, 46, 32, 83, 101, 100, 32, 98, 108, 97, 110, 100, 105, 116, 44, 32, 114, 105, 115, 117, 115, 32, 110, 111, 110, 32, 99, 111, 109, 109, 111, 100,
-111, 32, 110, 111, 110, 117, 109, 109, 121, 44, 32, 108, 105, 103, 117, 108, 97, 32, 101, 114, 97, 116, 32, 102, 101, 114, 109, 101, 110, 116, 117, 109,
-32, 110, 105, 98, 104, 44, 32, 101, 117, 32, 102, 97, 99, 105, 108, 105, 115, 105, 115, 32, 97, 110, 116, 101, 32, 110, 101, 113, 117, 101, 32, 115,
-101, 100, 32, 115, 101, 109, 46, 32, 69, 116, 105, 97, 109, 32, 115, 99, 101, 108, 101, 114, 105, 115, 113, 117, 101, 32, 106, 117, 115, 116, 111, 32,
-101, 103, 101, 116, 32, 119, 105, 115, 105, 46, 32, 78, 117, 110, 99, 32, 100, 105, 103, 110, 105, 115, 115, 105, 109, 46, 32, 80, 114, 111, 105, 110,
-32, 112, 117, 108, 118, 105, 110, 97, 114, 32, 113, 117, 97, 109, 32, 110, 111, 110, 32, 108, 101, 99, 116, 117, 115, 46, 32, 80, 114, 111, 105, 110,
-32, 117, 116, 32, 116, 117, 114, 112, 105, 115, 32, 113, 117, 105, 115, 32, 97, 117, 103, 117, 101, 32, 112, 101, 108, 108, 101, 110, 116, 101, 115, 113,
-117, 101, 32, 100, 105, 99, 116, 117, 109, 46, 32, 70, 117, 115, 99, 101, 32, 101, 116, 32, 108, 111, 114, 101, 109, 46, 32, 65, 108, 105, 113, 117,
-97, 109, 32, 117, 114, 110, 97, 32, 108, 97, 99, 117, 115, 44, 32, 98, 108, 97, 110, 100, 105, 116, 32, 115, 101, 100, 44, 32, 118, 101, 115, 116,
-105, 98, 117, 108, 117, 109, 32, 115, 105, 116, 32, 97, 109, 101, 116, 44, 32, 112, 108, 97, 99, 101, 114, 97, 116, 32, 101, 116, 44, 32, 100, 111,
-108, 111, 114, 46, 32, 67, 117, 114, 97, 98, 105, 116, 117, 114, 32, 97, 117, 99, 116, 111, 114, 32, 101, 114, 97, 116, 32, 110, 101, 99, 32, 108,
-111, 114, 101, 109, 46, 32, 80, 104, 97, 115, 101, 108, 108, 117, 115, 32, 117, 114, 110, 97, 32, 119, 105, 115, 105, 44, 32, 108, 97, 99, 105, 110,
-105, 97, 32, 117, 116, 44, 32, 109, 111, 108, 101, 115, 116, 105, 101, 32, 116, 105, 110, 99, 105, 100, 117, 110, 116, 44, 32, 99, 111, 110, 100, 105,
-109, 101, 110, 116, 117, 109, 32, 105, 100, 44, 32, 111, 100, 105, 111, 46, 32, 67, 117, 114, 97, 98, 105, 116, 117, 114, 32, 99, 111, 110, 118, 97,
-108, 108, 105, 115, 32, 117, 108, 108, 97, 109, 99, 111, 114, 112, 101, 114, 32, 106, 117, 115, 116, 111, 46, 32, 68, 111, 110, 101, 99, 32, 118, 101,
-115, 116, 105, 98, 117, 108, 117, 109, 32, 101, 115, 116, 32, 97, 99, 32, 113, 117, 97, 109, 46, 32, 78, 117, 108, 108, 97, 109, 32, 118, 105, 116,
-97, 101, 32, 101, 108, 105, 116, 32, 101, 117, 32, 109, 97, 115, 115, 97, 32, 118, 97, 114, 105, 117, 115, 32, 118, 117, 108, 112, 117, 116, 97, 116,
-101, 46, 32, 78, 117, 108, 108, 97, 32, 102, 97, 99, 105, 108, 105, 115, 105, 46, 32, 83, 117, 115, 112, 101, 110, 100, 105, 115, 115, 101, 32, 112,
-111, 116, 101, 110, 116, 105, 46, 32, 80, 114, 97, 101, 115, 101, 110, 116, 32, 110, 111, 110, 32, 108, 105, 98, 101, 114, 111, 46, 32, 78, 117, 108,
-108, 97, 109, 32, 116, 114, 105, 115, 116, 105, 113, 117, 101, 32, 109, 97, 115, 115, 97, 32, 105, 100, 32, 109, 97, 103, 110, 97, 32, 118, 105, 118,
-101, 114, 114, 97, 32, 99, 111, 109, 109, 111, 100, 111, 46, 32, 86, 101, 115, 116, 105, 98, 117, 108, 117, 109, 32, 108, 105, 98, 101, 114, 111, 32,
-116, 111, 114, 116, 111, 114, 44, 32, 108, 117, 99, 116, 117, 115, 32, 97, 99, 44, 32, 118, 105, 118, 101, 114, 114, 97, 32, 99, 111, 110, 103, 117,
-101, 44, 32, 99, 111, 110, 115, 101, 99, 116, 101, 116, 117, 101, 114, 32, 118, 101, 108, 44, 32, 108, 105, 98, 101, 114, 111, 46, 32, 65, 101, 110,
-101, 97, 110, 32, 97, 114, 99, 117, 32, 97, 117, 103, 117, 101, 44, 32, 108, 117, 99, 116, 117, 115, 32, 105, 100, 44, 32, 108, 97, 111, 114, 101,
-101, 116, 32, 112, 117, 108, 118, 105, 110, 97, 114, 44, 32, 100, 105, 99, 116, 117, 109, 32, 115, 101, 100, 44, 32, 108, 101, 99, 116, 117, 115, 46,
-32, 68, 111, 110, 101, 99, 32, 118, 101, 115, 116, 105, 98, 117, 108, 117, 109, 32, 118, 111, 108, 117, 116, 112, 97, 116, 32, 100, 111, 108, 111, 114,
-46, 32, 80, 101, 108, 108, 101, 110, 116, 101, 115, 113, 117, 101, 32, 104, 97, 98, 105, 116, 97, 110, 116, 32, 109, 111, 114, 98, 105, 32, 116, 114,
-105, 115, 116, 105, 113, 117, 101, 32, 115, 101, 110, 101, 99, 116, 117, 115, 32, 101, 116, 32, 110, 101, 116, 117, 115, 32, 101, 116, 32, 109, 97, 108,
-101, 115, 117, 97, 100, 97, 32, 102, 97, 109, 101, 115, 32, 97, 99, 32, 116, 117, 114, 112, 105, 115, 32, 101, 103, 101, 115, 116, 97, 115, 46, 32,
-80, 101, 108, 108, 101, 110, 116, 101, 115, 113, 117, 101, 32, 97, 117, 103, 117, 101, 32, 116, 117, 114, 112, 105, 115, 44, 32, 108, 97, 111, 114, 101,
-101, 116, 32, 110, 101, 99, 44, 32, 109, 97, 108, 101, 115, 117, 97, 100, 97, 32, 97, 116, 44, 32, 110, 111, 110, 117, 109, 109, 121, 32, 118, 105,
-116, 97, 101, 44, 32, 110, 105, 98, 104, 46, 32, 69, 116, 105, 97, 109, 32, 111, 114, 99, 105, 32, 115, 97, 112, 105, 101, 110, 44, 32, 99, 111,
-110, 103, 117, 101, 32, 105, 110, 44, 32, 112, 111, 114, 116, 116, 105, 116, 111, 114, 32, 115, 105, 116, 32, 97, 109, 101, 116, 44, 32, 114, 117, 116,
-114, 117, 109, 32, 118, 101, 108, 44, 32, 110, 105, 98, 104, 46, 32, 73, 110, 116, 101, 103, 101, 114, 32, 101, 117, 32, 108, 111, 114, 101, 109, 46,
-32, 77, 97, 117, 114, 105, 115, 32, 112, 114, 101, 116, 105, 117, 109, 32, 108, 101, 111, 32, 101, 116, 32, 101, 108, 105, 116, 46, 32, 73, 110, 32,
-110, 111, 110, 117, 109, 109, 121, 32, 117, 108, 116, 114, 105, 99, 105, 101, 115, 32, 115, 97, 112, 105, 101, 110, 46, 32, 77, 97, 117, 114, 105, 115,
-32, 118, 97, 114, 105, 117, 115, 46, 32, 77, 97, 117, 114, 105, 115, 32, 115, 101, 100, 32, 108, 105, 98, 101, 114, 111, 46, 32, 67, 117, 114, 97,
-98, 105, 116, 117, 114, 32, 117, 108, 108, 97, 109, 99, 111, 114, 112, 101, 114, 32, 101, 108, 105, 116, 32, 101, 117, 32, 112, 117, 114, 117, 115, 46,
-32, 86, 101, 115, 116, 105, 98, 117, 108, 117, 109, 32, 118, 101, 108, 105, 116, 32, 112, 101, 100, 101, 44, 32, 115, 101, 109, 112, 101, 114, 32, 115,
-105, 116, 32, 97, 109, 101, 116, 44, 32, 108, 111, 98, 111, 114, 116, 105, 115, 32, 118, 105, 116, 97, 101, 44, 32, 116, 105, 110, 99, 105, 100, 117,
-110, 116, 32, 118, 101, 108, 44, 32, 100, 117, 105, 46, 32, 78, 117, 108, 108, 97, 32, 110, 101, 113, 117, 101, 32, 97, 110, 116, 101, 44, 32, 115,
-97, 103, 105, 116, 116, 105, 115, 32, 101, 117, 44, 32, 118, 101, 115, 116, 105, 98, 117, 108, 117, 109, 32, 101, 116, 44, 32, 108, 97, 99, 105, 110,
-105, 97, 32, 97, 44, 32, 108, 105, 98, 101, 114, 111, 46, 32, 77, 111, 114, 98, 105, 32, 115, 105, 116, 32, 97, 109, 101, 116, 32, 119, 105, 115,
-105, 46, 32, 80, 101, 108, 108, 101, 110, 116, 101, 115, 113, 117, 101, 32, 110, 111, 110, 32, 102, 101, 108, 105, 115, 32, 113, 117, 105, 115, 32, 97,
-114, 99, 117, 32, 98, 105, 98, 101, 110, 100, 117, 109, 32, 111, 114, 110, 97, 114, 101, 46, 32, 65, 101, 110, 101, 97, 110, 32, 101, 110, 105, 109,
-32, 109, 101, 116, 117, 115, 44, 32, 99, 111, 109, 109, 111, 100, 111, 32, 101, 117, 44, 32, 104, 101, 110, 100, 114, 101, 114, 105, 116, 32, 110, 111,
-110, 117, 109, 109, 121, 44, 32, 101, 117, 105, 115, 109, 111, 100, 32, 117, 116, 44, 32, 113, 117, 97, 109, 46, 32, 78, 117, 108, 108, 97, 32, 101,
-108, 101, 105, 102, 101, 110, 100, 32, 110, 105, 115, 108, 32, 113, 117, 105, 115, 32, 100, 111, 108, 111, 114, 46, 32, 67, 108, 97, 115, 115, 32, 97,
-112, 116, 101, 110, 116, 32, 116, 97, 99, 105, 116, 105, 32, 115, 111, 99, 105, 111, 115, 113, 117, 32, 97, 100, 32, 108, 105, 116, 111, 114, 97, 32,
-116, 111, 114, 113, 117, 101, 110, 116, 32, 112, 101, 114, 32, 99, 111, 110, 117, 98, 105, 97, 32, 110, 111, 115, 116, 114, 97, 44, 32, 112, 101, 114,
-32, 105, 110, 99, 101, 112, 116, 111, 115, 32, 104, 121, 109, 101, 110, 97, 101, 111, 115, 46, 32, 77, 97, 101, 99, 101, 110, 97, 115, 32, 112, 101,
-108, 108, 101, 110, 116, 101, 115, 113, 117, 101, 32, 109, 97, 115, 115, 97, 32, 105, 110, 32, 101, 114, 97, 116, 32, 109, 111, 108, 101, 115, 116, 105,
-101, 32, 109, 111, 108, 101, 115, 116, 105, 101, 46, 32, 77, 97, 117, 114, 105, 115, 32, 100, 105, 103, 110, 105, 115, 115, 105, 109, 32, 100, 97, 112,
-105, 98, 117, 115, 32, 108, 105, 98, 101, 114, 111, 46, 32, 83, 101, 100, 32, 115, 101, 100, 32, 114, 105, 115, 117, 115, 32, 105, 100, 32, 110, 101,
-113, 117, 101, 32, 100, 105, 99, 116, 117, 109, 32, 111, 114, 110, 97, 114, 101, 46, 32, 83, 101, 100, 32, 101, 117, 32, 108, 105, 103, 117, 108, 97,
-32, 97, 116, 32, 102, 101, 108, 105, 115, 32, 115, 111, 100, 97, 108, 101, 115, 32, 97, 99, 99, 117, 109, 115, 97, 110, 46, 32, 83, 101, 100, 32,
-105, 110, 116, 101, 114, 100, 117, 109, 44, 32, 117, 114, 110, 97, 32, 110, 111, 110, 32, 112, 104, 97, 114, 101, 116, 114, 97, 32, 104, 101, 110, 100,
-114, 101, 114, 105, 116, 44, 32, 113, 117, 97, 109, 32, 109, 105, 32, 111, 114, 110, 97, 114, 101, 32, 108, 105, 98, 101, 114, 111, 44, 32, 105, 100,
-32, 102, 114, 105, 110, 103, 105, 108, 108, 97, 32, 116, 111, 114, 116, 111, 114, 32, 111, 114, 99, 105, 32, 110, 111, 110, 32, 118, 101, 108, 105, 116,
-46, 32, 65, 108, 105, 113, 117, 97, 109, 32, 110, 101, 99, 32, 114, 105, 115, 117, 115, 46, 32, 68, 111, 110, 101, 99, 32, 97, 116, 32, 110, 117,
-110, 99, 32, 118, 105, 116, 97, 101, 32, 116, 101, 108, 108, 117, 115, 32, 109, 111, 108, 101, 115, 116, 105, 101, 32, 118, 101, 115, 116, 105, 98, 117,
-108, 117, 109, 46, 32, 80, 101, 108, 108, 101, 110, 116, 101, 115, 113, 117, 101, 32, 118, 101, 108, 32, 106, 117, 115, 116, 111, 46, 32, 68, 117, 105,
-115, 32, 108, 105, 103, 117, 108, 97, 32, 108, 105, 98, 101, 114, 111, 44, 32, 118, 117, 108, 112, 117, 116, 97, 116, 101, 32, 113, 117, 105, 115, 44,
-32, 97, 100, 105, 112, 105, 115, 99, 105, 110, 103, 32, 98, 105, 98, 101, 110, 100, 117, 109, 44, 32, 102, 101, 117, 103, 105, 97, 116, 32, 118, 105,
-116, 97, 101, 44, 32, 118, 101, 108, 105, 116, 46, 32, 86, 105, 118, 97, 109, 117, 115, 32, 101, 116, 32, 97, 114, 99, 117, 46, 32, 70, 117, 115,
-99, 101, 32, 101, 103, 101, 116, 32, 113, 117, 97, 109, 46, 32, 85, 116, 32, 97, 110, 116, 101, 46, 32, 83, 117, 115, 112, 101, 110, 100, 105, 115,
-115, 101, 32, 102, 101, 117, 103, 105, 97, 116, 32, 109, 101, 116, 117, 115, 32, 110, 111, 110, 32, 105, 112, 115, 117, 109, 46, 32, 78, 117, 108, 108,
-97, 32, 116, 101, 109, 112, 117, 115, 32, 108, 101, 111, 32, 117, 116, 32, 109, 105, 46, 32, 67, 117, 114, 97, 98, 105, 116, 117, 114, 32, 118, 105,
-116, 97, 101, 32, 110, 105, 115, 108, 46, 32, 86, 105, 118, 97, 109, 117, 115, 32, 101, 108, 101, 109, 101, 110, 116, 117, 109, 46, 32, 69, 116, 105,
-97, 109, 32, 97, 32, 111, 114, 99, 105, 46, 32, 86, 101, 115, 116, 105, 98, 117, 108, 117, 109, 32, 97, 110, 116, 101, 32, 105, 112, 115, 117, 109,
-32, 112, 114, 105, 109, 105, 115, 32, 105, 110, 32, 102, 97, 117, 99, 105, 98, 117, 115, 32, 111, 114, 99, 105, 32, 108, 117, 99, 116, 117, 115, 32,
-101, 116, 32, 117, 108, 116, 114, 105, 99, 101, 115, 32, 112, 111, 115, 117, 101, 114, 101, 32, 99, 117, 98, 105, 108, 105, 97, 32, 67, 117, 114, 97,
-101, 59, 32, 86, 105, 118, 97, 109, 117, 115, 32, 117, 114, 110, 97, 32, 113, 117, 97, 109, 44, 32, 116, 105, 110, 99, 105, 100, 117, 110, 116, 32,
-97, 116, 44, 32, 117, 108, 116, 114, 105, 99, 101, 115, 32, 118, 101, 108, 44, 32, 102, 101, 117, 103, 105, 97, 116, 32, 101, 103, 101, 116, 44, 32,
-110, 117, 108, 108, 97, 46, 32, 77, 97, 101, 99, 101, 110, 97, 115, 32, 108, 97, 99, 117, 115, 32, 109, 97, 103, 110, 97, 44, 32, 110, 111, 110,
-117, 109, 109, 121, 32, 101, 117, 44, 32, 105, 97, 99, 117, 108, 105, 115, 32, 115, 101, 100, 44, 32, 99, 111, 110, 115, 101, 99, 116, 101, 116, 117,
-101, 114, 32, 113, 117, 105, 115, 44, 32, 101, 110, 105, 109, 46, 32, 80, 114, 97, 101, 115, 101, 110, 116, 32, 97, 32, 101, 114, 111, 115, 46, 32,
-65, 108, 105, 113, 117, 97, 109, 32, 110, 111, 110, 117, 109, 109, 121, 32, 100, 105, 103, 110, 105, 115, 115, 105, 109, 32, 110, 101, 113, 117, 101, 46,
-32, 78, 117, 108, 108, 97, 32, 101, 110, 105, 109, 46, 32, 80, 114, 97, 101, 115, 101, 110, 116, 32, 109, 111, 108, 101, 115, 116, 105, 101, 44, 32,
-111, 114, 99, 105, 32, 113, 117, 105, 115, 32, 116, 114, 105, 115, 116, 105, 113, 117, 101, 32, 118, 111, 108, 117, 116, 112, 97, 116, 44, 32, 108, 97,
-99, 117, 115, 32, 109, 101, 116, 117, 115, 32, 108, 117, 99, 116, 117, 115, 32, 115, 97, 112, 105, 101, 110, 44, 32, 101, 116, 32, 102, 97, 99, 105,
-108, 105, 115, 105, 115, 32, 101, 114, 111, 115, 32, 110, 101, 113, 117, 101, 32, 105, 100, 32, 115, 97, 112, 105, 101, 110, 46, 32, 78, 117, 110, 99,
-32, 99, 111, 110, 100, 105, 109, 101, 110, 116, 117, 109, 32, 100, 111, 108, 111, 114, 32, 118, 101, 108, 32, 111, 114, 99, 105, 46, 32, 73, 110, 116,
-101, 103, 101, 114, 32, 119, 105, 115, 105, 32, 100, 105, 97, 109, 44, 32, 112, 111, 114, 116, 116, 105, 116, 111, 114, 32, 115, 105, 116, 32, 97, 109,
-101, 116, 44, 32, 102, 101, 117, 103, 105, 97, 116, 32, 105, 110, 44, 32, 100, 97, 112, 105, 98, 117, 115, 32, 105, 110, 44, 32, 108, 101, 99, 116,
-117, 115, 46, 32, 65, 108, 105, 113, 117, 97, 109, 32, 101, 114, 97, 116, 32, 118, 111, 108, 117, 116, 112, 97, 116, 46, 32, 81, 117, 105, 115, 113,
-117, 101, 32, 109, 111, 108, 108, 105, 115, 32, 116, 117, 114, 112, 105, 115, 32, 118, 105, 116, 97, 101, 32, 116, 111, 114, 116, 111, 114, 46, 32, 77,
-97, 117, 114, 105, 115, 32, 116, 117, 114, 112, 105, 115, 32, 109, 105, 44, 32, 112, 114, 101, 116, 105, 117, 109, 32, 117, 116, 44, 32, 117, 108, 116,
-114, 105, 99, 101, 115, 32, 115, 101, 100, 44, 32, 112, 111, 114, 116, 97, 32, 105, 110, 44, 32, 106, 117, 115, 116, 111, 46, 32, 83, 117, 115, 112,
-101, 110, 100, 105, 115, 115, 101, 32, 112, 111, 115, 117, 101, 114, 101, 46, 32, 81, 117, 105, 115, 113, 117, 101, 32, 117, 108, 116, 114, 105, 99, 105,
-101, 115, 32, 108, 97, 99, 117, 115, 32, 118, 105, 116, 97, 101, 32, 101, 110, 105, 109, 46, 32, 68, 111, 110, 101, 99, 32, 108, 97, 99, 117, 115,
-46, 32, 83, 117, 115, 112, 101, 110, 100, 105, 115, 115, 101, 32, 112, 111, 116, 101, 110, 116, 105, 46, 32, 68, 111, 110, 101, 99, 32, 109, 111, 108,
-101, 115, 116, 105, 101, 44, 32, 109, 97, 103, 110, 97, 32, 115, 101, 100, 32, 101, 117, 105, 115, 109, 111, 100, 32, 100, 105, 99, 116, 117, 109, 44,
-32, 109, 97, 103, 110, 97, 32, 109, 97, 103, 110, 97, 32, 105, 110, 116, 101, 114, 100, 117, 109, 32, 100, 105, 97, 109, 44, 32, 118, 105, 116, 97,
-101, 32, 115, 97, 103, 105, 116, 116, 105, 115, 32, 108, 101, 111, 32, 108, 111, 114, 101, 109, 32, 97, 99, 32, 110, 101, 113, 117, 101, 46, 32, 67,
-114, 97, 115, 32, 109, 101, 116, 117, 115, 46, 32, 81, 117, 105, 115, 113, 117, 101, 32, 110, 117, 110, 99, 46, 32, 68, 117, 105, 115, 32, 99, 111,
-110, 115, 101, 99, 116, 101, 116, 117, 101, 114, 46, 32, 86, 101, 115, 116, 105, 98, 117, 108, 117, 109, 32, 103, 114, 97, 118, 105, 100, 97, 32, 115,
-111, 108, 108, 105, 99, 105, 116, 117, 100, 105, 110, 32, 117, 114, 110, 97, 46, 32, 73, 110, 116, 101, 103, 101, 114, 32, 118, 111, 108, 117, 116, 112,
-97, 116, 44, 32, 109, 97, 115, 115, 97, 32, 113, 117, 105, 115, 32, 117, 108, 116, 114, 105, 99, 101, 115, 32, 112, 117, 108, 118, 105, 110, 97, 114,
-44, 32, 101, 114, 111, 115, 32, 112, 117, 114, 117, 115, 32, 100, 105, 103, 110, 105, 115, 115, 105, 109, 32, 110, 117, 110, 99, 44, 32, 101, 103, 101,
-116, 32, 114, 104, 111, 110, 99, 117, 115, 32, 101, 110, 105, 109, 32, 108, 101, 99, 116, 117, 115, 32, 113, 117, 105, 115, 32, 116, 111, 114, 116, 111,
-114, 46, 32, 73, 110, 116, 101, 103, 101, 114, 32, 108, 97, 99, 105, 110, 105, 97, 32, 113, 117, 97, 109, 32, 113, 117, 105, 115, 32, 101, 114, 97,
-116, 32, 99, 111, 110, 118, 97, 108, 108, 105, 115, 32, 109, 97, 116, 116, 105, 115, 46, 32, 83, 117, 115, 112, 101, 110, 100, 105, 115, 115, 101, 32,
-105, 97, 99, 117, 108, 105, 115, 32, 112, 111, 115, 117, 101, 114, 101, 32, 118, 101, 108, 105, 116, 46, 32, 69, 116, 105, 97, 109, 32, 116, 101, 108,
-108, 117, 115, 32, 101, 110, 105, 109, 44, 32, 97, 108, 105, 113, 117, 101, 116, 32, 110, 101, 99, 44, 32, 108, 97, 111, 114, 101, 101, 116, 32, 97,
-44, 32, 109, 111, 108, 101, 115, 116, 105, 101, 32, 110, 111, 110, 44, 32, 118, 101, 108, 105, 116, 46, 32, 81, 117, 105, 115, 113, 117, 101, 32, 108,
-97, 99, 117, 115, 32, 118, 101, 108, 105, 116, 44, 32, 101, 108, 101, 105, 102, 101, 110, 100, 32, 105, 109, 112, 101, 114, 100, 105, 101, 116, 44, 32,
-102, 114, 105, 110, 103, 105, 108, 108, 97, 32, 105, 100, 44, 32, 100, 97, 112, 105, 98, 117, 115, 32, 115, 99, 101, 108, 101, 114, 105, 115, 113, 117,
-101, 44, 32, 108, 101, 99, 116, 117, 115, 46, 32, 78, 117, 108, 108, 97, 32, 113, 117, 105, 115, 32, 108, 111, 114, 101, 109, 46, 32, 78, 117, 108,
-108, 97, 32, 109, 97, 108, 101, 115, 117, 97, 100, 97, 32, 110, 101, 113, 117, 101, 32, 101, 116, 32, 100, 117, 105, 46, 32, 80, 104, 97, 115, 101,
-108, 108, 117, 115, 32, 109, 97, 108, 101, 115, 117, 97, 100, 97, 32, 117, 108, 116, 114, 105, 99, 105, 101, 115, 32, 111, 100, 105, 111, 46, 32, 80,
-104, 97, 115, 101, 108, 108, 117, 115, 32, 118, 105, 116, 97, 101, 32, 108, 105, 103, 117, 108, 97, 46, 32, 80, 101, 108, 108, 101, 110, 116, 101, 115,
-113, 117, 101, 32, 102, 101, 117, 103, 105, 97, 116, 32, 97, 114, 99, 117, 32, 97, 116, 32, 101, 114, 97, 116, 46, 32, 86, 105, 118, 97, 109, 117,
-115, 32, 117, 116, 32, 101, 114, 111, 115, 32, 117, 116, 32, 108, 111, 114, 101, 109, 32, 112, 117, 108, 118, 105, 110, 97, 114, 32, 105, 97, 99, 117,
-108, 105, 115, 46, 32, 80, 114, 111, 105, 110, 32, 108, 111, 98, 111, 114, 116, 105, 115, 32, 105, 112, 115, 117, 109, 32, 105, 100, 32, 110, 117, 110,
-99, 46, 32, 67, 117, 114, 97, 98, 105, 116, 117, 114, 32, 118, 101, 108, 32, 109, 97, 115, 115, 97, 46, 32, 83, 117, 115, 112, 101, 110, 100, 105,
-115, 115, 101, 32, 110, 117, 108, 108, 97, 32, 105, 112, 115, 117, 109, 44, 32, 109, 97, 108, 101, 115, 117, 97, 100, 97, 32, 118, 101, 108, 44, 32,
-112, 111, 115, 117, 101, 114, 101, 32, 101, 103, 101, 116, 44, 32, 109, 111, 108, 108, 105, 115, 32, 97, 116, 44, 32, 114, 105, 115, 117, 115, 46, 32,
-86, 101, 115, 116, 105, 98, 117, 108, 117, 109, 32, 115, 101, 100, 32, 100, 105, 97, 109, 32, 105, 100, 32, 101, 115, 116, 32, 100, 97, 112, 105, 98,
-117, 115, 32, 117, 108, 116, 114, 105, 99, 101, 115, 46, 32, 80, 114, 111, 105, 110, 32, 116, 101, 109, 112, 117, 115, 44, 32, 101, 114, 111, 115, 32,
-97, 32, 115, 99, 101, 108, 101, 114, 105, 115, 113, 117, 101, 32, 118, 101, 115, 116, 105, 98, 117, 108, 117, 109, 44, 32, 105, 112, 115, 117, 109, 32,
-97, 114, 99, 117, 32, 97, 108, 105, 113, 117, 97, 109, 32, 109, 105, 44, 32, 117, 116, 32, 102, 101, 117, 103, 105, 97, 116, 32, 108, 105, 98, 101,
-114, 111, 32, 111, 100, 105, 111, 32, 105, 110, 32, 110, 105, 115, 108, 46, 32, 81, 117, 105, 115, 113, 117, 101, 32, 101, 116, 32, 109, 97, 115, 115,
-97, 32, 97, 32, 109, 97, 117, 114, 105, 115, 32, 108, 117, 99, 116, 117, 115, 32, 99, 111, 110, 103, 117, 101, 46, 32, 85, 116, 32, 105, 100, 32,
-101, 114, 111, 115, 46, 32, 70, 117, 115, 99, 101, 32, 97, 110, 116, 101, 32, 101, 114, 111, 115, 44, 32, 112, 104, 97, 114, 101, 116, 114, 97, 32,
-110, 111, 110, 44, 32, 109, 111, 108, 101, 115, 116, 105, 101, 32, 116, 114, 105, 115, 116, 105, 113, 117, 101, 44, 32, 98, 105, 98, 101, 110, 100, 117,
-109, 32, 115, 105, 116, 32, 97, 109, 101, 116, 44, 32, 119, 105, 115, 105, 46, 32, 80, 104, 97, 115, 101, 108, 108, 117, 115, 32, 114, 117, 116, 114,
-117, 109, 44, 32, 100, 111, 108, 111, 114, 32, 101, 116, 32, 115, 101, 109, 112, 101, 114, 32, 101, 108, 101, 109, 101, 110, 116, 117, 109, 44, 32, 101,
-114, 111, 115, 32, 97, 110, 116, 101, 32, 109, 97, 108, 101, 115, 117, 97, 100, 97, 32, 109, 97, 115, 115, 97, 44, 32, 115, 101, 100, 32, 115, 111,
-108, 108, 105, 99, 105, 116, 117, 100, 105, 110, 32, 108, 101, 99, 116, 117, 115, 32, 118, 101, 108, 105, 116, 32, 101, 116, 32, 109, 97, 115, 115, 97,
-46, 32, 73, 110, 32, 97, 117, 99, 116, 111, 114, 46, 32, 65, 108, 105, 113, 117, 97, 109, 32, 101, 114, 97, 116, 32, 118, 111, 108, 117, 116, 112,
-97, 116, 46, 32, 69, 116, 105, 97, 109, 32, 114, 105, 115, 117, 115, 32, 108, 101, 111, 44, 32, 118, 117, 108, 112, 117, 116, 97, 116, 101, 32, 115,
-117, 115, 99, 105, 112, 105, 116, 44, 32, 115, 111, 108, 108, 105, 99, 105, 116, 117, 100, 105, 110, 32, 101, 116, 44, 32, 115, 111, 100, 97, 108, 101,
-115, 32, 101, 103, 101, 116, 44, 32, 110, 105, 115, 108, 46, 32, 86, 101, 115, 116, 105, 98, 117, 108, 117, 109, 32, 97, 110, 116, 101, 32, 105, 112,
-115, 117, 109, 32, 112, 114, 105, 109, 105, 115, 32, 105, 110, 32, 102, 97, 117, 99, 105, 98, 117, 115, 32, 111, 114, 99, 105, 32, 108, 117, 99, 116,
-117, 115, 32, 101, 116, 32, 117, 108, 116, 114, 105, 99, 101, 115, 32, 112, 111, 115, 117, 101, 114, 101, 32, 99, 117, 98, 105, 108, 105, 97, 32, 67,
-117, 114, 97, 101, 59, 32, 67, 117, 114, 97, 98, 105, 116, 117, 114, 32, 108, 111, 98, 111, 114, 116, 105, 115, 44, 32, 108, 105, 98, 101, 114, 111,
-32, 97, 99, 32, 108, 97, 111, 114, 101, 101, 116, 32, 109, 111, 108, 108, 105, 115, 44, 32, 108, 105, 103, 117, 108, 97, 32, 108, 101, 111, 32, 112,
-111, 114, 116, 97, 32, 119, 105, 115, 105, 44, 32, 117, 116, 32, 101, 117, 105, 115, 109, 111, 100, 32, 102, 101, 108, 105, 115, 32, 108, 105, 103, 117,
-108, 97, 32, 105, 100, 32, 101, 108, 105, 116, 46, 32, 86, 105, 118, 97, 109, 117, 115, 32, 109, 97, 108, 101, 115, 117, 97, 100, 97, 32, 110, 117,
-108, 108, 97, 32, 101, 117, 32, 101, 110, 105, 109, 46, 32, 68, 111, 110, 101, 99, 32, 97, 99, 99, 117, 109, 115, 97, 110, 32, 102, 97, 117, 99,
-105, 98, 117, 115, 32, 111, 114, 99, 105, 46, 32, 78, 117, 108, 108, 97, 32, 108, 97, 99, 105, 110, 105, 97, 32, 97, 110, 116, 101, 46, 32, 80,
-114, 97, 101, 115, 101, 110, 116, 32, 97, 116, 32, 110, 105, 98, 104, 46, 32, 77, 97, 117, 114, 105, 115, 32, 112, 111, 114, 116, 97, 32, 100, 105,
-103, 110, 105, 115, 115, 105, 109, 32, 119, 105, 115, 105, 46, 32, 85, 116, 32, 108, 97, 99, 105, 110, 105, 97, 32, 116, 111, 114, 116, 111, 114, 32,
-110, 101, 99, 32, 110, 117, 110, 99, 46, 32, 80, 104, 97, 115, 101, 108, 108, 117, 115, 32, 101, 116, 32, 97, 117, 103, 117, 101, 46, 32, 73, 110,
-116, 101, 103, 101, 114, 32, 114, 104, 111, 110, 99, 117, 115, 44, 32, 108, 105, 98, 101, 114, 111, 32, 97, 32, 112, 101, 108, 108, 101, 110, 116, 101,
-115, 113, 117, 101, 32, 114, 104, 111, 110, 99, 117, 115, 44, 32, 116, 111, 114, 116, 111, 114, 32, 115, 97, 112, 105, 101, 110, 32, 108, 111, 98, 111,
-114, 116, 105, 115, 32, 112, 101, 100, 101, 44, 32, 101, 103, 101, 116, 32, 99, 111, 110, 100, 105, 109, 101, 110, 116, 117, 109, 32, 115, 97, 112, 105,
-101, 110, 32, 114, 105, 115, 117, 115, 32, 118, 105, 116, 97, 101, 32, 101, 108, 105, 116, 46, 32, 83, 117, 115, 112, 101, 110, 100, 105, 115, 115, 101,
-32, 115, 101, 100, 32, 116, 117, 114, 112, 105, 115, 32, 117, 116, 32, 100, 111, 108, 111, 114, 32, 112, 108, 97, 99, 101, 114, 97, 116, 32, 100, 105,
-103, 110, 105, 115, 115, 105, 109, 46, 32, 81, 117, 105, 115, 113, 117, 101, 32, 113, 117, 105, 115, 32, 108, 101, 111, 46, 32, 67, 114, 97, 115, 32,
-117, 108, 116, 114, 105, 99, 101, 115, 46, 32, 77, 97, 101, 99, 101, 110, 97, 115, 32, 104, 101, 110, 100, 114, 101, 114, 105, 116, 32, 97, 117, 99,
-116, 111, 114, 32, 116, 111, 114, 116, 111, 114, 46, 32, 69, 116, 105, 97, 109, 32, 115, 105, 116, 32, 97, 109, 101, 116, 32, 97, 114, 99, 117, 46,
-0};
diff --git a/source/blender/editors/gpencil/CMakeLists.txt b/source/blender/editors/gpencil/CMakeLists.txt
index 904ad4892ed..83a13abb33f 100644
--- a/source/blender/editors/gpencil/CMakeLists.txt
+++ b/source/blender/editors/gpencil/CMakeLists.txt
@@ -23,11 +23,14 @@ set(INC
../../blenfont
../../blenkernel
../../blenlib
+ ../../blentranslation
../../imbuf
+ ../../gpu
../../makesdna
../../makesrna
../../windowmanager
../../../../intern/guardedalloc
+ ../../../../intern/glew-mx
)
set(INC_SYS
@@ -37,11 +40,14 @@ set(INC_SYS
set(SRC
drawgpencil.c
editaction_gpencil.c
- gpencil_buttons.c
+ gpencil_convert.c
+ gpencil_data.c
gpencil_edit.c
gpencil_ops.c
gpencil_paint.c
+ gpencil_select.c
gpencil_undo.c
+ gpencil_utils.c
gpencil_intern.h
)
@@ -50,4 +56,6 @@ if(WITH_INTERNATIONAL)
add_definitions(-DWITH_INTERNATIONAL)
endif()
+add_definitions(${GL_DEFINITIONS})
+
blender_add_lib(bf_editor_gpencil "${SRC}" "${INC}" "${INC_SYS}")
diff --git a/source/blender/editors/gpencil/SConscript b/source/blender/editors/gpencil/SConscript
index 8b891fcb8cf..3830a164b7b 100644
--- a/source/blender/editors/gpencil/SConscript
+++ b/source/blender/editors/gpencil/SConscript
@@ -31,12 +31,14 @@ sources = env.Glob('*.c')
incs = [
'#/intern/guardedalloc',
- '#/extern/glew/include',
+ env['BF_GLEW_INC'],
+ '#/intern/glew-mx',
'#/intern/elbeem/extern',
'../include',
'../../blenfont',
'../../blenkernel',
'../../blenlib',
+ '../../blentranslation',
'../../bmesh',
'../../gpu',
'../../imbuf',
@@ -47,6 +49,7 @@ incs = [
]
defs = []
+defs += env['BF_GL_DEFINITIONS']
if env['WITH_BF_INTERNATIONAL']:
defs.append('WITH_INTERNATIONAL')
diff --git a/source/blender/editors/gpencil/drawgpencil.c b/source/blender/editors/gpencil/drawgpencil.c
index 5a838d7bc39..6b71c0ac053 100644
--- a/source/blender/editors/gpencil/drawgpencil.c
+++ b/source/blender/editors/gpencil/drawgpencil.c
@@ -27,6 +27,7 @@
* \ingroup edgpencil
*/
+
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
@@ -39,6 +40,9 @@
#include "BLI_math.h"
#include "BLI_utildefines.h"
+#include "BLF_api.h"
+#include "BLT_translation.h"
+
#include "DNA_gpencil_types.h"
#include "DNA_scene_types.h"
#include "DNA_screen_types.h"
@@ -56,9 +60,11 @@
#include "BIF_glutil.h"
#include "ED_gpencil.h"
+#include "ED_screen.h"
#include "ED_view3d.h"
-#include "gpencil_intern.h"
+#include "UI_interface_icons.h"
+#include "UI_resources.h"
/* ************************************************** */
/* GREASE PENCIL DRAWING */
@@ -73,6 +79,9 @@ typedef enum eDrawStrokeFlags {
GP_DRAWDATA_ONLYI2D = (1 << 3), /* only draw 'image' strokes */
GP_DRAWDATA_IEDITHACK = (1 << 4), /* special hack for drawing strokes in Image Editor (weird coordinates) */
GP_DRAWDATA_NO_XRAY = (1 << 5), /* don't draw xray in 3D view (which is default) */
+ GP_DRAWDATA_NO_ONIONS = (1 << 6), /* no onionskins should be drawn (for animation playback) */
+ GP_DRAWDATA_VOLUMETRIC = (1 << 7), /* draw strokes as "volumetric" circular billboards */
+ GP_DRAWDATA_FILL = (1 << 8), /* fill insides/bounded-regions of strokes */
} eDrawStrokeFlags;
@@ -111,22 +120,22 @@ static void gp_draw_stroke_buffer(tGPspoint *points, int totpoints, short thickn
/* draw stroke curve */
if (G.debug & G_DEBUG) setlinestyle(2);
-
- glLineWidth(oldpressure * thickness);
+
+ glLineWidth(max_ff(oldpressure * thickness, 1.0));
glBegin(GL_LINE_STRIP);
-
+
for (i = 0, pt = points; i < totpoints && pt; i++, pt++) {
/* if there was a significant pressure change, stop the curve, change the thickness of the stroke,
* and continue drawing again (since line-width cannot change in middle of GL_LINE_STRIP)
*/
if (fabsf(pt->pressure - oldpressure) > 0.2f) {
glEnd();
- glLineWidth(pt->pressure * thickness);
+ glLineWidth(max_ff(pt->pressure * thickness, 1.0f));
glBegin(GL_LINE_STRIP);
/* need to roll-back one point to ensure that there are no gaps in the stroke */
if (i != 0) glVertex2iv(&(pt - 1)->x);
-
+
/* now the point we want... */
glVertex2iv(&pt->x);
@@ -136,20 +145,230 @@ static void gp_draw_stroke_buffer(tGPspoint *points, int totpoints, short thickn
glVertex2iv(&pt->x);
}
glEnd();
-
+
/* reset for predictable OpenGL context */
glLineWidth(1.0f);
-
+
if (G.debug & G_DEBUG) setlinestyle(0);
}
}
+/* --------- 2D Stroke Drawing Helpers --------- */
+
+/* helper function to calculate x-y drawing coordinates for 2D points */
+static void gp_calc_2d_stroke_xy(bGPDspoint *pt, short sflag, int offsx, int offsy, int winx, int winy, float r_co[2])
+{
+ if (sflag & GP_STROKE_2DSPACE) {
+ r_co[0] = pt->x;
+ r_co[1] = pt->y;
+ }
+ else if (sflag & GP_STROKE_2DIMAGE) {
+ const float x = (float)((pt->x * winx) + offsx);
+ const float y = (float)((pt->y * winy) + offsy);
+
+ r_co[0] = x;
+ r_co[1] = y;
+ }
+ else {
+ const float x = (float)(pt->x / 100 * winx) + offsx;
+ const float y = (float)(pt->y / 100 * winy) + offsy;
+
+ r_co[0] = x;
+ r_co[1] = y;
+ }
+}
+
+/* ----------- Volumetric Strokes --------------- */
+
+/* draw a 2D buffer stroke in "volumetric" style
+ * NOTE: the stroke buffer doesn't have any coordinate offsets/transforms
+ */
+static void gp_draw_stroke_volumetric_buffer(tGPspoint *points, int totpoints, short thickness,
+ short dflag, short UNUSED(sflag))
+{
+ GLUquadricObj *qobj = gluNewQuadric();
+ float modelview[4][4];
+
+ tGPspoint *pt;
+ int i;
+
+ /* error checking */
+ if ((points == NULL) || (totpoints <= 0))
+ return;
+
+ /* check if buffer can be drawn */
+ if (dflag & (GP_DRAWDATA_ONLY3D | GP_DRAWDATA_ONLYV2D))
+ return;
+
+ /* get basic matrix - should be camera space (i.e "identity") */
+ glGetFloatv(GL_MODELVIEW_MATRIX, (float *)modelview);
+
+ /* draw points */
+ glPushMatrix();
+
+ for (i = 0, pt = points; i < totpoints; i++, pt++) {
+ /* set the transformed position */
+ // TODO: scale should change based on zoom level, which requires proper translation mult too!
+ modelview[3][0] = pt->x;
+ modelview[3][1] = pt->y;
+
+ glLoadMatrixf((float *)modelview);
+
+ /* draw the disk using the current state... */
+ gluDisk(qobj, 0.0, pt->pressure * thickness, 32, 1);
+
+
+ modelview[3][0] = modelview[3][1] = 0.0f;
+ }
+
+ glPopMatrix();
+ gluDeleteQuadric(qobj);
+}
+
+/* draw a 2D strokes in "volumetric" style */
+static void gp_draw_stroke_volumetric_2d(bGPDspoint *points, int totpoints, short thickness,
+ short dflag, short sflag,
+ int offsx, int offsy, int winx, int winy)
+{
+ GLUquadricObj *qobj = gluNewQuadric();
+ float modelview[4][4];
+ float baseloc[3];
+ float scalefac = 1.0f;
+
+ bGPDspoint *pt;
+ int i;
+
+
+ /* HACK: We need a scale factor for the drawing in the image editor,
+ * which seems to use 1 unit as it's maximum size, whereas everything
+ * else assumes 1 unit = 1 pixel. Otherwise, we only get a massive blob.
+ */
+ if ((dflag & GP_DRAWDATA_IEDITHACK) && (dflag & GP_DRAWDATA_ONLYV2D)) {
+ scalefac = 0.001f;
+ }
+
+ /* get basic matrix */
+ glGetFloatv(GL_MODELVIEW_MATRIX, (float *)modelview);
+ copy_v3_v3(baseloc, modelview[3]);
+
+ /* draw points */
+ glPushMatrix();
+
+ for (i = 0, pt = points; i < totpoints; i++, pt++) {
+ /* set the transformed position */
+ float co[2];
+
+ gp_calc_2d_stroke_xy(pt, sflag, offsx, offsy, winx, winy, co);
+ translate_m4(modelview, co[0], co[1], 0.0f);
+
+ glLoadMatrixf((float *)modelview);
+
+ /* draw the disk using the current state... */
+ gluDisk(qobj, 0.0, pt->pressure * thickness * scalefac, 32, 1);
+
+ /* restore matrix */
+ copy_v3_v3(modelview[3], baseloc);
+ }
+
+ glPopMatrix();
+ gluDeleteQuadric(qobj);
+}
+
+/* draw a 3D stroke in "volumetric" style */
+static void gp_draw_stroke_volumetric_3d(bGPDspoint *points, int totpoints, short thickness,
+ short UNUSED(dflag), short UNUSED(sflag))
+{
+ GLUquadricObj *qobj = gluNewQuadric();
+
+ float base_modelview[4][4], modelview[4][4];
+ float base_loc[3];
+
+ bGPDspoint *pt;
+ int i;
+
+
+ /* Get the basic modelview matrix we use for performing calculations */
+ glGetFloatv(GL_MODELVIEW_MATRIX, (float *)base_modelview);
+ copy_v3_v3(base_loc, base_modelview[3]);
+
+ /* Create the basic view-aligned billboard matrix we're going to actually draw qobj with:
+ * - We need to knock out the rotation so that we are
+ * simply left with a camera-facing billboard
+ * - The scale factors here are chosen so that the thickness
+ * is relatively reasonable. Otherwise, it gets far too
+ * large!
+ */
+ scale_m4_fl(modelview, 0.1f);
+
+ /* draw each point as a disk... */
+ glPushMatrix();
+
+ for (i = 0, pt = points; i < totpoints && pt; i++, pt++) {
+ /* apply translation to base_modelview, so that the translated point is put in the right place */
+ translate_m4(base_modelview, pt->x, pt->y, pt->z);
+
+ /* copy the translation component to the billboard matrix we're going to use,
+ * then reset the base matrix to the original values so that we can do the same
+ * for the next point without accumulation/pollution effects
+ */
+ copy_v3_v3(modelview[3], base_modelview[3]); /* copy offset value */
+ copy_v3_v3(base_modelview[3], base_loc); /* restore */
+
+ /* apply our billboard matrix for drawing... */
+ glLoadMatrixf((float *)modelview);
+
+ /* draw the disk using the current state... */
+ gluDisk(qobj, 0.0, pt->pressure * thickness, 32, 1);
+ }
+
+ glPopMatrix();
+ gluDeleteQuadric(qobj);
+}
+
+
+/* --------------- Stroke Fills ----------------- */
+
+/* draw fills for shapes */
+static void gp_draw_stroke_fill(bGPDspoint *points, int totpoints, short UNUSED(thickness),
+ short UNUSED(dflag), short sflag,
+ int offsx, int offsy, int winx, int winy)
+{
+ bGPDspoint *pt;
+ int i;
+
+ BLI_assert(totpoints >= 3);
+
+ /* As an initial implementation, we use the OpenGL filled polygon drawing
+ * here since it's the easiest option to implement for this case. It does
+ * come with limitations (notably for concave shapes), though it shouldn't
+ * be much of an issue in most cases.
+ */
+ glBegin(GL_POLYGON);
+
+ for (i = 0, pt = points; i < totpoints; i++, pt++) {
+ if (sflag & GP_STROKE_3DSPACE) {
+ glVertex3fv(&pt->x);
+ }
+ else {
+ float co[2];
+
+ gp_calc_2d_stroke_xy(pt, sflag, offsx, offsy, winx, winy, co);
+ glVertex2fv(co);
+ }
+ }
+
+ glEnd();
+}
+
/* ----- Existing Strokes Drawing (3D and Point) ------ */
/* draw a given stroke - just a single dot (only one point) */
static void gp_draw_stroke_point(bGPDspoint *points, short thickness, short dflag, short sflag,
int offsx, int offsy, int winx, int winy)
{
+ /* set point thickness (since there's only one of these) */
+ glPointSize((float)(thickness + 2) * points->pressure);
+
/* draw point */
if (sflag & GP_STROKE_3DSPACE) {
glBegin(GL_POINTS);
@@ -160,18 +379,7 @@ static void gp_draw_stroke_point(bGPDspoint *points, short thickness, short dfla
float co[2];
/* get coordinates of point */
- if (sflag & GP_STROKE_2DSPACE) {
- co[0] = points->x;
- co[1] = points->y;
- }
- else if (sflag & GP_STROKE_2DIMAGE) {
- co[0] = (points->x * winx) + offsx;
- co[1] = (points->y * winy) + offsy;
- }
- else {
- co[0] = (points->x / 100 * winx) + offsx;
- co[1] = (points->y / 100 * winy) + offsy;
- }
+ gp_calc_2d_stroke_xy(points, sflag, offsx, offsy, winx, winy, co);
/* if thickness is less than GP_DRAWTHICKNESS_SPECIAL, simple dot looks ok
* - also mandatory in if Image Editor 'image-based' dot
@@ -185,13 +393,13 @@ static void gp_draw_stroke_point(bGPDspoint *points, short thickness, short dfla
}
else {
/* draw filled circle as is done in circf (but without the matrix push/pops which screwed things up) */
- GLUquadricObj *qobj = gluNewQuadric();
+ GLUquadricObj *qobj = gluNewQuadric();
- gluQuadricDrawStyle(qobj, GLU_FILL);
+ gluQuadricDrawStyle(qobj, GLU_FILL);
/* need to translate drawing position, but must reset after too! */
- glTranslatef(co[0], co[1], 0.0);
- gluDisk(qobj, 0.0, thickness, 32, 1);
+ glTranslate2fv(co);
+ gluDisk(qobj, 0.0, thickness, 32, 1);
glTranslatef(-co[0], -co[1], 0.0);
gluDeleteQuadric(qobj);
@@ -200,14 +408,14 @@ static void gp_draw_stroke_point(bGPDspoint *points, short thickness, short dfla
}
/* draw a given stroke in 3d (i.e. in 3d-space), using simple ogl lines */
-static void gp_draw_stroke_3d(bGPDspoint *points, int totpoints, short thickness, short debug)
+static void gp_draw_stroke_3d(bGPDspoint *points, int totpoints, short thickness, bool debug, short UNUSED(sflag))
{
bGPDspoint *pt;
float curpressure = points[0].pressure;
int i;
/* draw stroke curve */
- glLineWidth(curpressure * thickness);
+ glLineWidth(max_ff(curpressure * thickness, 1.0f));
glBegin(GL_LINE_STRIP);
for (i = 0, pt = points; i < totpoints && pt; i++, pt++) {
/* if there was a significant pressure change, stop the curve, change the thickness of the stroke,
@@ -217,7 +425,7 @@ static void gp_draw_stroke_3d(bGPDspoint *points, int totpoints, short thickness
if (fabsf(pt->pressure - curpressure) > 0.2f / (float)thickness) {
glEnd();
curpressure = pt->pressure;
- glLineWidth(curpressure * thickness);
+ glLineWidth(max_ff(curpressure * thickness, 1.0f));
glBegin(GL_LINE_STRIP);
/* need to roll-back one point to ensure that there are no gaps in the stroke */
@@ -231,9 +439,12 @@ static void gp_draw_stroke_3d(bGPDspoint *points, int totpoints, short thickness
}
}
glEnd();
-
+
/* draw debug points of curve on top? */
+ /* XXX: for now, we represent "selected" strokes in the same way as debug, which isn't used anymore */
if (debug) {
+ glPointSize((float)(thickness + 2));
+
glBegin(GL_POINTS);
for (i = 0, pt = points; i < totpoints && pt; i++, pt++)
glVertex3fv(&pt->x);
@@ -244,46 +455,22 @@ static void gp_draw_stroke_3d(bGPDspoint *points, int totpoints, short thickness
/* ----- Fancy 2D-Stroke Drawing ------ */
/* draw a given stroke in 2d */
-static void gp_draw_stroke(bGPDspoint *points, int totpoints, short thickness_s, short dflag, short sflag,
- short debug, int offsx, int offsy, int winx, int winy)
+static void gp_draw_stroke_2d(bGPDspoint *points, int totpoints, short thickness_s, short dflag, short sflag,
+ bool debug, int offsx, int offsy, int winx, int winy)
{
/* otherwise thickness is twice that of the 3D view */
float thickness = (float)thickness_s * 0.5f;
-
- /* if thickness is less than GP_DRAWTHICKNESS_SPECIAL, 'smooth' opengl lines look better
- * - 'smooth' opengl lines are also required if Image Editor 'image-based' stroke
- */
- if ((thickness < GP_DRAWTHICKNESS_SPECIAL) ||
- ((dflag & GP_DRAWDATA_IEDITHACK) && (dflag & GP_DRAWDATA_ONLYV2D)))
- {
- bGPDspoint *pt;
- int i;
-
- glBegin(GL_LINE_STRIP);
- for (i = 0, pt = points; i < totpoints && pt; i++, pt++) {
- if (sflag & GP_STROKE_2DSPACE) {
- glVertex2f(pt->x, pt->y);
- }
- else if (sflag & GP_STROKE_2DIMAGE) {
- const float x = (pt->x * winx) + offsx;
- const float y = (pt->y * winy) + offsy;
-
- glVertex2f(x, y);
- }
- else {
- const float x = (pt->x / 100 * winx) + offsx;
- const float y = (pt->y / 100 * winy) + offsy;
-
- glVertex2f(x, y);
- }
- }
- glEnd();
+
+ /* strokes in Image Editor need a scale factor, since units there are not pixels! */
+ float scalefac = 1.0f;
+ if ((dflag & GP_DRAWDATA_IEDITHACK) && (dflag & GP_DRAWDATA_ONLYV2D)) {
+ scalefac = 0.001f;
}
/* tessellation code - draw stroke as series of connected quads with connection
* edges rotated to minimize shrinking artifacts, and rounded endcaps
*/
- else {
+ {
bGPDspoint *pt1, *pt2;
float pm[2];
int i;
@@ -299,22 +486,8 @@ static void gp_draw_stroke(bGPDspoint *points, int totpoints, short thickness_s,
float pthick; /* thickness at segment point */
/* get x and y coordinates from points */
- if (sflag & GP_STROKE_2DSPACE) {
- s0[0] = pt1->x; s0[1] = pt1->y;
- s1[0] = pt2->x; s1[1] = pt2->y;
- }
- else if (sflag & GP_STROKE_2DIMAGE) {
- s0[0] = (pt1->x * winx) + offsx;
- s0[1] = (pt1->y * winy) + offsy;
- s1[0] = (pt2->x * winx) + offsx;
- s1[1] = (pt2->y * winy) + offsy;
- }
- else {
- s0[0] = (pt1->x / 100 * winx) + offsx;
- s0[1] = (pt1->y / 100 * winy) + offsy;
- s1[0] = (pt2->x / 100 * winx) + offsx;
- s1[1] = (pt2->y / 100 * winy) + offsy;
- }
+ gp_calc_2d_stroke_xy(pt1, sflag, offsx, offsy, winx, winy, s0);
+ gp_calc_2d_stroke_xy(pt2, sflag, offsx, offsy, winx, winy, s1);
/* calculate gradient and normal - 'angle'=(ny/nx) */
m1[1] = s1[1] - s0[1];
@@ -324,12 +497,12 @@ static void gp_draw_stroke(bGPDspoint *points, int totpoints, short thickness_s,
m2[0] = m1[1];
/* always use pressure from first point here */
- pthick = (pt1->pressure * thickness);
+ pthick = (pt1->pressure * thickness * scalefac);
/* if the first segment, start of segment is segment's normal */
if (i == 0) {
- /* draw start cap first
- * - make points slightly closer to center (about halfway across)
+ /* draw start cap first
+ * - make points slightly closer to center (about halfway across)
*/
mt[0] = m2[0] * pthick * 0.5f;
mt[1] = m2[1] * pthick * 0.5f;
@@ -369,7 +542,7 @@ static void gp_draw_stroke(bGPDspoint *points, int totpoints, short thickness_s,
mb[1] = (pm[1] + m2[1]) / 2;
normalize_v2(mb);
- /* calculate gradient to apply
+ /* calculate gradient to apply
* - as basis, use just pthick * bisector gradient
* - if cross-section not as thick as it should be, add extra padding to fix it
*/
@@ -399,7 +572,7 @@ static void gp_draw_stroke(bGPDspoint *points, int totpoints, short thickness_s,
/* if last segment, also draw end of segment (defined as segment's normal) */
if (i == totpoints - 2) {
/* for once, we use second point's pressure (otherwise it won't be drawn) */
- pthick = (pt2->pressure * thickness);
+ pthick = (pt2->pressure * thickness * scalefac);
/* calculate points for end of segment */
mt[0] = m2[0] * pthick;
@@ -417,8 +590,8 @@ static void gp_draw_stroke(bGPDspoint *points, int totpoints, short thickness_s,
glVertex2fv(t1);
- /* draw end cap as last step
- * - make points slightly closer to center (about halfway across)
+ /* draw end cap as last step
+ * - make points slightly closer to center (about halfway across)
*/
mt[0] = m2[0] * pthick * 0.5f;
mt[1] = m2[1] * pthick * 0.5f;
@@ -446,54 +619,61 @@ static void gp_draw_stroke(bGPDspoint *points, int totpoints, short thickness_s,
bGPDspoint *pt;
int i;
+ glPointSize((float)(thickness_s + 2));
+
glBegin(GL_POINTS);
for (i = 0, pt = points; i < totpoints && pt; i++, pt++) {
- if (sflag & GP_STROKE_2DSPACE) {
- glVertex2fv(&pt->x);
- }
- else if (sflag & GP_STROKE_2DIMAGE) {
- const float x = (float)((pt->x * winx) + offsx);
- const float y = (float)((pt->y * winy) + offsy);
-
- glVertex2f(x, y);
- }
- else {
- const float x = (float)(pt->x / 100 * winx) + offsx;
- const float y = (float)(pt->y / 100 * winy) + offsy;
-
- glVertex2f(x, y);
- }
+ float co[2];
+
+ gp_calc_2d_stroke_xy(pt, sflag, offsx, offsy, winx, winy, co);
+ glVertex2fv(co);
}
glEnd();
}
}
-/* ----- General Drawing ------ */
+/* ----- Strokes Drawing ------ */
+
+/* Helper for doing all the checks on whether a stroke can be drawn */
+static bool gp_can_draw_stroke(const bGPDstroke *gps, const int dflag)
+{
+ /* skip stroke if it isn't in the right display space for this drawing context */
+ /* 1) 3D Strokes */
+ if ((dflag & GP_DRAWDATA_ONLY3D) && !(gps->flag & GP_STROKE_3DSPACE))
+ return false;
+ if (!(dflag & GP_DRAWDATA_ONLY3D) && (gps->flag & GP_STROKE_3DSPACE))
+ return false;
+
+ /* 2) Screen Space 2D Strokes */
+ if ((dflag & GP_DRAWDATA_ONLYV2D) && !(gps->flag & GP_STROKE_2DSPACE))
+ return false;
+ if (!(dflag & GP_DRAWDATA_ONLYV2D) && (gps->flag & GP_STROKE_2DSPACE))
+ return false;
+
+ /* 3) Image Space (2D) */
+ if ((dflag & GP_DRAWDATA_ONLYI2D) && !(gps->flag & GP_STROKE_2DIMAGE))
+ return false;
+ if (!(dflag & GP_DRAWDATA_ONLYI2D) && (gps->flag & GP_STROKE_2DIMAGE))
+ return false;
+
+
+ /* skip stroke if it doesn't have any valid data */
+ if ((gps->points == NULL) || (gps->totpoints < 1))
+ return false;
+
+ /* stroke can be drawn */
+ return true;
+}
/* draw a set of strokes */
static void gp_draw_strokes(bGPDframe *gpf, int offsx, int offsy, int winx, int winy, int dflag,
- short debug, short lthick, const float color[4])
+ bool debug, short lthick, const float color[4], const float fill_color[4])
{
bGPDstroke *gps;
- /* set color first (may need to reset it again later too) */
- glColor4fv(color);
-
for (gps = gpf->strokes.first; gps; gps = gps->next) {
- /* check if stroke can be drawn - checks here generally fall into pairs */
- if ((dflag & GP_DRAWDATA_ONLY3D) && !(gps->flag & GP_STROKE_3DSPACE))
- continue;
- if (!(dflag & GP_DRAWDATA_ONLY3D) && (gps->flag & GP_STROKE_3DSPACE))
- continue;
- if ((dflag & GP_DRAWDATA_ONLYV2D) && !(gps->flag & GP_STROKE_2DSPACE))
- continue;
- if (!(dflag & GP_DRAWDATA_ONLYV2D) && (gps->flag & GP_STROKE_2DSPACE))
- continue;
- if ((dflag & GP_DRAWDATA_ONLYI2D) && !(gps->flag & GP_STROKE_2DIMAGE))
- continue;
- if (!(dflag & GP_DRAWDATA_ONLYI2D) && (gps->flag & GP_STROKE_2DIMAGE))
- continue;
- if ((gps->points == NULL) || (gps->totpoints < 1))
+ /* check if stroke can be drawn */
+ if (gp_can_draw_stroke(gps, dflag) == false)
continue;
/* check which stroke-drawer to use */
@@ -515,11 +695,27 @@ static void gp_draw_strokes(bGPDframe *gpf, int offsx, int offsy, int winx, int
#endif
}
- if (gps->totpoints == 1) {
- gp_draw_stroke_point(gps->points, lthick, dflag, gps->flag, offsx, offsy, winx, winy);
+ /* 3D Fill */
+ if ((dflag & GP_DRAWDATA_FILL) && (gps->totpoints >= 3)) {
+ glColor4fv(fill_color);
+ gp_draw_stroke_fill(gps->points, gps->totpoints, lthick, dflag, gps->flag, offsx, offsy, winx, winy);
+ }
+
+ /* 3D Stroke */
+ glColor4fv(color);
+
+ if (dflag & GP_DRAWDATA_VOLUMETRIC) {
+ /* volumetric stroke drawing */
+ gp_draw_stroke_volumetric_3d(gps->points, gps->totpoints, lthick, dflag, gps->flag);
}
else {
- gp_draw_stroke_3d(gps->points, gps->totpoints, lthick, debug);
+ /* 3D Lines - OpenGL primitives-based */
+ if (gps->totpoints == 1) {
+ gp_draw_stroke_point(gps->points, lthick, dflag, gps->flag, offsx, offsy, winx, winy);
+ }
+ else {
+ gp_draw_stroke_3d(gps->points, gps->totpoints, lthick, debug, gps->flag);
+ }
}
if (no_xray) {
@@ -534,116 +730,301 @@ static void gp_draw_strokes(bGPDframe *gpf, int offsx, int offsy, int winx, int
}
}
else {
- if (gps->totpoints == 1) {
- gp_draw_stroke_point(gps->points, lthick, dflag, gps->flag, offsx, offsy, winx, winy);
+ /* 2D - Fill */
+ if ((dflag & GP_DRAWDATA_FILL) && (gps->totpoints >= 3)) {
+ glColor4fv(fill_color);
+ gp_draw_stroke_fill(gps->points, gps->totpoints, lthick, dflag, gps->flag, offsx, offsy, winx, winy);
+ }
+
+ /* 2D Strokes... */
+ glColor4fv(color);
+
+ if (dflag & GP_DRAWDATA_VOLUMETRIC) {
+ /* blob/disk-based "volumetric" drawing */
+ gp_draw_stroke_volumetric_2d(gps->points, gps->totpoints, lthick, dflag, gps->flag, offsx, offsy, winx, winy);
}
else {
- gp_draw_stroke(gps->points, gps->totpoints, lthick, dflag, gps->flag, debug, offsx, offsy, winx, winy);
+ /* normal 2D strokes */
+ if (gps->totpoints == 1) {
+ gp_draw_stroke_point(gps->points, lthick, dflag, gps->flag, offsx, offsy, winx, winy);
+ }
+ else {
+ gp_draw_stroke_2d(gps->points, gps->totpoints, lthick, dflag, gps->flag, debug, offsx, offsy, winx, winy);
+ }
}
}
}
}
-/* draw grease-pencil datablock */
-static void gp_draw_data(bGPdata *gpd, int offsx, int offsy, int winx, int winy, int cfra, int dflag)
+/* Draw selected verts for strokes being edited */
+static void gp_draw_strokes_edit(bGPDframe *gpf, int offsx, int offsy, int winx, int winy, short dflag, const float tcolor[3])
{
- bGPDlayer *gpl;
+ bGPDstroke *gps;
- /* reset line drawing style (in case previous user didn't reset) */
- setlinestyle(0);
+ const bool no_xray = (dflag & GP_DRAWDATA_NO_XRAY) != 0;
+ int mask_orig = 0;
- /* turn on smooth lines (i.e. anti-aliasing) */
- glEnable(GL_LINE_SMOOTH);
+ /* set up depth masks... */
+ if (dflag & GP_DRAWDATA_ONLY3D) {
+ if (no_xray) {
+ glGetIntegerv(GL_DEPTH_WRITEMASK, &mask_orig);
+ glDepthMask(0);
+ glEnable(GL_DEPTH_TEST);
+
+ /* first arg is normally rv3d->dist, but this isn't
+ * available here and seems to work quite well without */
+ bglPolygonOffset(1.0f, 1.0f);
+#if 0
+ glEnable(GL_POLYGON_OFFSET_LINE);
+ glPolygonOffset(-1.0f, -1.0f);
+#endif
+ }
+ }
- /* turn on alpha-blending */
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- glEnable(GL_BLEND);
+
+ /* draw stroke verts */
+ for (gps = gpf->strokes.first; gps; gps = gps->next) {
+ bGPDspoint *pt;
+ float vsize, bsize;
+ int i;
+
+ /* check if stroke can be drawn */
+ if (gp_can_draw_stroke(gps, dflag) == false)
+ continue;
+
+ /* Optimisation: only draw points for selected strokes
+ * We assume that selected points can only occur in
+ * strokes that are selected too.
+ */
+ if ((gps->flag & GP_STROKE_SELECT) == 0)
+ continue;
+
+ /* Get size of verts:
+ * - The selected state needs to be larger than the unselected state so that
+ * they stand out more.
+ * - We use the theme setting for size of the unselected verts
+ */
+ bsize = UI_GetThemeValuef(TH_GP_VERTEX_SIZE);
+ if ((int)bsize > 8) {
+ vsize = 10.0f;
+ bsize = 8.0f;
+ }
+ else {
+ vsize = bsize + 2;
+ }
+
+ /* First Pass: Draw all the verts (i.e. these become the unselected state) */
+ if (tcolor != NULL) {
+ /* for now, we assume that the base color of the points is not too close to the real color */
+ glColor3fv(tcolor);
+ }
+ else {
+ /* this doesn't work well with the default theme and black strokes... */
+ UI_ThemeColor(TH_GP_VERTEX);
+ }
+ glPointSize(bsize);
+
+ glBegin(GL_POINTS);
+ for (i = 0, pt = gps->points; i < gps->totpoints && pt; i++, pt++) {
+ if (gps->flag & GP_STROKE_3DSPACE) {
+ glVertex3fv(&pt->x);
+ }
+ else {
+ float co[2];
+
+ gp_calc_2d_stroke_xy(pt, gps->flag, offsx, offsy, winx, winy, co);
+ glVertex2fv(co);
+ }
+ }
+ glEnd();
- /* loop over layers, drawing them */
+
+ /* Second Pass: Draw only verts which are selected */
+ UI_ThemeColor(TH_GP_VERTEX_SELECT);
+ glPointSize(vsize);
+
+ glBegin(GL_POINTS);
+ for (i = 0, pt = gps->points; i < gps->totpoints && pt; i++, pt++) {
+ if (pt->flag & GP_SPOINT_SELECT) {
+ if (gps->flag & GP_STROKE_3DSPACE) {
+ glVertex3fv(&pt->x);
+ }
+ else {
+ float co[2];
+
+ gp_calc_2d_stroke_xy(pt, gps->flag, offsx, offsy, winx, winy, co);
+ glVertex2fv(co);
+ }
+ }
+ }
+ glEnd();
+ }
+
+
+ /* clear depth mask */
+ if (dflag & GP_DRAWDATA_ONLY3D) {
+ if (no_xray) {
+ glDepthMask(mask_orig);
+ glDisable(GL_DEPTH_TEST);
+
+ bglPolygonOffset(0.0, 0.0);
+#if 0
+ glDisable(GL_POLYGON_OFFSET_LINE);
+ glPolygonOffset(0, 0);
+#endif
+ }
+ }
+}
+
+/* ----- General Drawing ------ */
+
+/* draw onion-skinning for a layer */
+static void gp_draw_onionskins(bGPDlayer *gpl, bGPDframe *gpf, int offsx, int offsy, int winx, int winy,
+ int UNUSED(cfra), int dflag, bool debug, short lthick)
+{
+ const float alpha = gpl->color[3];
+ float color[4];
+
+ /* 1) Draw Previous Frames First */
+ if (gpl->flag & GP_LAYER_GHOST_PREVCOL) {
+ copy_v3_v3(color, gpl->gcolor_prev);
+ }
+ else {
+ copy_v3_v3(color, gpl->color);
+ }
+
+ if (gpl->gstep) {
+ bGPDframe *gf;
+ float fac;
+
+ /* draw previous frames first */
+ for (gf = gpf->prev; gf; gf = gf->prev) {
+ /* check if frame is drawable */
+ if ((gpf->framenum - gf->framenum) <= gpl->gstep) {
+ /* alpha decreases with distance from curframe index */
+ fac = 1.0f - ((float)(gpf->framenum - gf->framenum) / (float)(gpl->gstep + 1));
+ color[3] = alpha * fac * 0.66f;
+ gp_draw_strokes(gf, offsx, offsy, winx, winy, dflag, debug, lthick, color, color);
+ }
+ else
+ break;
+ }
+ }
+ else {
+ /* draw the strokes for the ghost frames (at half of the alpha set by user) */
+ if (gpf->prev) {
+ color[3] = (alpha / 7);
+ gp_draw_strokes(gpf->prev, offsx, offsy, winx, winy, dflag, debug, lthick, color, color);
+ }
+ }
+
+
+ /* 2) Now draw next frames */
+ if (gpl->flag & GP_LAYER_GHOST_NEXTCOL) {
+ copy_v3_v3(color, gpl->gcolor_next);
+ }
+ else {
+ copy_v3_v3(color, gpl->color);
+ }
+
+ if (gpl->gstep_next) {
+ bGPDframe *gf;
+ float fac;
+
+ /* now draw next frames */
+ for (gf = gpf->next; gf; gf = gf->next) {
+ /* check if frame is drawable */
+ if ((gf->framenum - gpf->framenum) <= gpl->gstep_next) {
+ /* alpha decreases with distance from curframe index */
+ fac = 1.0f - ((float)(gf->framenum - gpf->framenum) / (float)(gpl->gstep_next + 1));
+ color[3] = alpha * fac * 0.66f;
+ gp_draw_strokes(gf, offsx, offsy, winx, winy, dflag, debug, lthick, color, color);
+ }
+ else
+ break;
+ }
+ }
+ else {
+ /* draw the strokes for the ghost frames (at half of the alpha set by user) */
+ if (gpf->next) {
+ color[3] = (alpha / 4);
+ gp_draw_strokes(gpf->next, offsx, offsy, winx, winy, dflag, debug, lthick, color, color);
+ }
+ }
+
+ /* 3) restore alpha */
+ glColor4fv(gpl->color);
+}
+
+/* loop over gpencil data layers, drawing them */
+static void gp_draw_data_layers(bGPdata *gpd, int offsx, int offsy, int winx, int winy, int cfra, int dflag)
+{
+ bGPDlayer *gpl;
+
for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
bGPDframe *gpf;
- short debug = (gpl->flag & GP_LAYER_DRAWDEBUG) ? 1 : 0;
+ bool debug = (gpl->flag & GP_LAYER_DRAWDEBUG) ? true : false;
short lthick = gpl->thickness;
- float color[4], tcolor[4];
/* don't draw layer if hidden */
- if (gpl->flag & GP_LAYER_HIDE)
+ if (gpl->flag & GP_LAYER_HIDE)
continue;
/* get frame to draw */
gpf = gpencil_layer_getframe(gpl, cfra, 0);
- if (gpf == NULL)
+ if (gpf == NULL)
continue;
- /* set color, stroke thickness, and point size */
+ /* set basic stroke thickness */
glLineWidth(lthick);
- copy_v4_v4(color, gpl->color); // just for copying 4 array elements
- copy_v4_v4(tcolor, gpl->color); // additional copy of color (for ghosting)
- glColor4fv(color);
- glPointSize((float)(gpl->thickness + 2));
- /* apply xray layer setting */
- if (gpl->flag & GP_LAYER_NO_XRAY) dflag |= GP_DRAWDATA_NO_XRAY;
- else dflag &= ~GP_DRAWDATA_NO_XRAY;
+ /* Add layer drawing settings to the set of "draw flags"
+ * NOTE: If the setting doesn't apply, it *must* be cleared,
+ * as dflag's carry over from the previous layer
+ */
+#define GP_DRAWFLAG_APPLY(condition, draw_flag_value) { \
+ if (condition) dflag |= (draw_flag_value); \
+ else dflag &= ~(draw_flag_value); \
+ } (void)0
+
+ /* xray... */
+ GP_DRAWFLAG_APPLY((gpl->flag & GP_LAYER_NO_XRAY), GP_DRAWDATA_NO_XRAY);
+
+ /* volumetric strokes... */
+ GP_DRAWFLAG_APPLY((gpl->flag & GP_LAYER_VOLUMETRIC), GP_DRAWDATA_VOLUMETRIC);
+
+ /* fill strokes... */
+ // XXX: this is not a very good limit
+ GP_DRAWFLAG_APPLY((gpl->fill[3] > 0.001f), GP_DRAWDATA_FILL);
+#undef GP_DRAWFLAG_APPLY
/* draw 'onionskins' (frame left + right) */
- if (gpl->flag & GP_LAYER_ONIONSKIN) {
- /* drawing method - only immediately surrounding (gstep = 0),
- * or within a frame range on either side (gstep > 0)*/
- if (gpl->gstep) {
- bGPDframe *gf;
- float fac;
-
- /* draw previous frames first */
- for (gf = gpf->prev; gf; gf = gf->prev) {
- /* check if frame is drawable */
- if ((gpf->framenum - gf->framenum) <= gpl->gstep) {
- /* alpha decreases with distance from curframe index */
- fac = 1.0f - ((float)(gpf->framenum - gf->framenum) / (float)(gpl->gstep + 1));
- tcolor[3] = color[3] * fac * 0.66f;
- gp_draw_strokes(gf, offsx, offsy, winx, winy, dflag, debug, lthick, tcolor);
- }
- else
- break;
- }
-
- /* now draw next frames */
- for (gf = gpf->next; gf; gf = gf->next) {
- /* check if frame is drawable */
- if ((gf->framenum - gpf->framenum) <= gpl->gstep) {
- /* alpha decreases with distance from curframe index */
- fac = 1.0f - ((float)(gf->framenum - gpf->framenum) / (float)(gpl->gstep + 1));
- tcolor[3] = color[3] * fac * 0.66f;
- gp_draw_strokes(gf, offsx, offsy, winx, winy, dflag, debug, lthick, tcolor);
- }
- else
- break;
- }
-
- /* restore alpha */
- glColor4fv(color);
- }
- else {
- /* draw the strokes for the ghost frames (at half of the alpha set by user) */
- if (gpf->prev) {
- tcolor[3] = (color[3] / 7);
- gp_draw_strokes(gpf->prev, offsx, offsy, winx, winy, dflag, debug, lthick, tcolor);
- }
-
- if (gpf->next) {
- tcolor[3] = (color[3] / 4);
- gp_draw_strokes(gpf->next, offsx, offsy, winx, winy, dflag, debug, lthick, tcolor);
- }
-
- /* restore alpha */
- glColor4fv(color);
- }
+ if ((gpl->flag & GP_LAYER_ONIONSKIN) && !(dflag & GP_DRAWDATA_NO_ONIONS)) {
+ /* Drawing method - only immediately surrounding (gstep = 0),
+ * or within a frame range on either side (gstep > 0)
+ */
+ gp_draw_onionskins(gpl, gpf, offsx, offsy, winx, winy, cfra, dflag, debug, lthick);
}
/* draw the strokes already in active frame */
- tcolor[3] = color[3];
- gp_draw_strokes(gpf, offsx, offsy, winx, winy, dflag, debug, lthick, tcolor);
+ gp_draw_strokes(gpf, offsx, offsy, winx, winy, dflag, debug, lthick, gpl->color, gpl->fill);
+
+ /* Draw verts of selected strokes
+ * - when doing OpenGL renders, we don't want to be showing these, as that ends up flickering
+ * - locked layers can't be edited, so there's no point showing these verts
+ * as they will have no bearings on what gets edited
+ * - only show when in editmode, since operators shouldn't work otherwise
+ * (NOTE: doing it this way means that the toggling editmode shows visible change immediately)
+ */
+ /* XXX: perhaps we don't want to show these when users are drawing... */
+ if ((G.f & G_RENDER_OGL) == 0 &&
+ (gpl->flag & GP_LAYER_LOCKED) == 0 &&
+ (gpd->flag & GP_DATA_STROKE_EDITMODE))
+ {
+ gp_draw_strokes_edit(gpf, offsx, offsy, winx, winy, dflag,
+ (gpl->color[3] < 0.95f) ? gpl->color : NULL);
+ }
/* Check if may need to draw the active stroke cache, only if this layer is the active layer
* that is being edited. (Stroke buffer is currently stored in gp-data)
@@ -651,22 +1032,135 @@ static void gp_draw_data(bGPdata *gpd, int offsx, int offsy, int winx, int winy,
if (ED_gpencil_session_active() && (gpl->flag & GP_LAYER_ACTIVE) &&
(gpf->flag & GP_FRAME_PAINT))
{
+ /* Set color for drawing buffer stroke - since this may not be set yet */
+ glColor4fv(gpl->color);
+
/* Buffer stroke needs to be drawn with a different linestyle
- * to help differentiate them from normal strokes. */
- gp_draw_stroke_buffer(gpd->sbuffer, gpd->sbuffer_size, lthick, dflag, gpd->sbuffer_sflag);
+ * to help differentiate them from normal strokes.
+ *
+ * It should also be noted that sbuffer contains temporary point types
+ * i.e. tGPspoints NOT bGPDspoints
+ */
+ if (gpl->flag & GP_LAYER_VOLUMETRIC) {
+ gp_draw_stroke_volumetric_buffer(gpd->sbuffer, gpd->sbuffer_size, lthick, dflag, gpd->sbuffer_sflag);
+ }
+ else {
+ gp_draw_stroke_buffer(gpd->sbuffer, gpd->sbuffer_size, lthick, dflag, gpd->sbuffer_sflag);
+ }
}
}
+}
+
+/* draw a short status message in the top-right corner */
+static void gp_draw_status_text(bGPdata *gpd, ARegion *ar)
+{
+ rcti rect;
+
+ /* Cannot draw any status text when drawing OpenGL Renders */
+ if (G.f & G_RENDER_OGL)
+ return;
+
+ /* Get bounds of region - Necessary to avoid problems with region overlap */
+ ED_region_visible_rect(ar, &rect);
+
+ /* for now, this should only be used to indicate when we are in stroke editmode */
+ if (gpd->flag & GP_DATA_STROKE_EDITMODE) {
+ const char *printable = IFACE_("GPencil Stroke Editing");
+ float printable_size[2];
+ int xco, yco;
+
+ BLF_width_and_height_default(printable, BLF_DRAW_STR_DUMMY_MAX, &printable_size[0], &printable_size[1]);
+
+ xco = (rect.xmax - U.widget_unit) - (int)printable_size[0];
+ yco = (rect.ymax - U.widget_unit);
+
+ /* text label */
+ UI_ThemeColor(TH_TEXT_HI);
+#ifdef WITH_INTERNATIONAL
+ BLF_draw_default(xco, yco, 0.0f, printable, BLF_DRAW_STR_DUMMY_MAX);
+#else
+ BLF_draw_default_ascii(xco, yco, 0.0f, printable, BLF_DRAW_STR_DUMMY_MAX);
+#endif
+
+ /* grease pencil icon... */
+ // XXX: is this too intrusive?
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glEnable(GL_BLEND);
+
+ xco -= U.widget_unit;
+ yco -= (int)printable_size[1] / 2;
+
+ UI_icon_draw(xco, yco, ICON_GREASEPENCIL);
+
+ glDisable(GL_BLEND);
+ }
+}
+
+/* draw grease-pencil datablock */
+static void gp_draw_data(bGPdata *gpd, int offsx, int offsy, int winx, int winy, int cfra, int dflag)
+{
+ /* reset line drawing style (in case previous user didn't reset) */
+ setlinestyle(0);
+
+ /* turn on smooth lines (i.e. anti-aliasing) */
+ glEnable(GL_LINE_SMOOTH);
+
+ /* XXX: turn on some way of ensuring that the polygon edges get smoothed
+ * GL_POLYGON_SMOOTH is nasty and shouldn't be used, as it ends up
+ * creating internal white rays due to the ways it accumulates stuff
+ */
+
+ /* turn on alpha-blending */
+ if (GLEW_VERSION_1_4) {
+ glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
+ }
+ else {
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ }
+
+ glEnable(GL_BLEND);
+
+ /* draw! */
+ gp_draw_data_layers(gpd, offsx, offsy, winx, winy, cfra, dflag);
/* turn off alpha blending, then smooth lines */
glDisable(GL_BLEND); // alpha blending
glDisable(GL_LINE_SMOOTH); // smooth lines
-
+
/* restore initial gl conditions */
glLineWidth(1.0);
glPointSize(1.0);
glColor4f(0, 0, 0, 1);
}
+/* if we have strokes for scenes (3d view)/clips (movie clip editor)
+ * and objects/tracks, multiple data blocks have to be drawn */
+static void gp_draw_data_all(Scene *scene, bGPdata *gpd, int offsx, int offsy, int winx, int winy,
+ int cfra, int dflag, const char spacetype)
+{
+ bGPdata *gpd_source = NULL;
+
+ if (scene) {
+ if (spacetype == SPACE_VIEW3D) {
+ gpd_source = (scene->gpd ? scene->gpd : NULL);
+ }
+ else if (spacetype == SPACE_CLIP && scene->clip) {
+ /* currently drawing only gpencil data from either clip or track, but not both - XXX fix logic behind */
+ gpd_source = (scene->clip->gpd ? scene->clip->gpd : NULL);
+ }
+
+ if (gpd_source) {
+ gp_draw_data(gpd_source, offsx, offsy, winx, winy, cfra, dflag);
+ }
+ }
+
+ /* scene/clip data has already been drawn, only object/track data is drawn here
+ * if gpd_source == gpd, we don't have any object/track data and we can skip */
+ if (gpd_source == NULL || (gpd_source && gpd_source != gpd)) {
+ gp_draw_data(gpd, offsx, offsy, winx, winy, cfra, dflag);
+ }
+}
+
/* ----- Grease Pencil Sketches Drawing API ------ */
/* ............................
@@ -693,7 +1187,7 @@ void ED_gpencil_draw_2dimage(const bContext *C)
case SPACE_IMAGE: /* image */
case SPACE_CLIP: /* clip */
{
-
+
/* just draw using standard scaling (settings here are currently ignored anyways) */
/* FIXME: the opengl poly-strokes don't draw at right thickness when done this way, so disabled */
offsx = 0;
@@ -714,8 +1208,8 @@ void ED_gpencil_draw_2dimage(const bContext *C)
sizex = ar->winx;
sizey = ar->winy;
- /* NOTE: I2D was used in 2.4x, but the old settings for that have been deprecated
- * and everything moved to standard View2d
+ /* NOTE: I2D was used in 2.4x, but the old settings for that have been deprecated
+ * and everything moved to standard View2d
*/
dflag |= GP_DRAWDATA_ONLYV2D;
break;
@@ -732,10 +1226,10 @@ void ED_gpencil_draw_2dimage(const bContext *C)
/* draw it! */
- gp_draw_data(gpd, offsx, offsy, sizex, sizey, CFRA, dflag);
+ gp_draw_data_all(scene, gpd, offsx, offsy, sizex, sizey, CFRA, dflag, sa->spacetype);
}
-/* draw grease-pencil sketches to specified 2d-view assuming that matrices are already set correctly
+/* draw grease-pencil sketches to specified 2d-view assuming that matrices are already set correctly
* Note: this gets called twice - first time with onlyv2d=1 to draw 'canvas' strokes,
* second time with onlyv2d=0 for screen-aligned strokes */
void ED_gpencil_draw_view2d(const bContext *C, bool onlyv2d)
@@ -758,10 +1252,15 @@ void ED_gpencil_draw_view2d(const bContext *C, bool onlyv2d)
/* draw it! */
if (onlyv2d) dflag |= (GP_DRAWDATA_ONLYV2D | GP_DRAWDATA_NOSTATUS);
- gp_draw_data(gpd, 0, 0, ar->winx, ar->winy, CFRA, dflag);
+ gp_draw_data_all(scene, gpd, 0, 0, ar->winx, ar->winy, CFRA, dflag, sa->spacetype);
+
+ /* draw status text (if in screen/pixel-space) */
+ if (onlyv2d == false) {
+ gp_draw_status_text(gpd, ar);
+ }
}
-/* draw grease-pencil sketches to specified 3d-view assuming that matrices are already set correctly
+/* draw grease-pencil sketches to specified 3d-view assuming that matrices are already set correctly
* Note: this gets called twice - first time with only3d=1 to draw 3d-strokes,
* second time with only3d=0 for screen-aligned strokes */
void ED_gpencil_draw_view3d(Scene *scene, View3D *v3d, ARegion *ar, bool only3d)
@@ -770,17 +1269,17 @@ void ED_gpencil_draw_view3d(Scene *scene, View3D *v3d, ARegion *ar, bool only3d)
int dflag = 0;
RegionView3D *rv3d = ar->regiondata;
int offsx, offsy, winx, winy;
-
+
/* check that we have grease-pencil stuff to draw */
gpd = ED_gpencil_data_get_active_v3d(scene, v3d);
if (gpd == NULL) return;
-
+
/* when rendering to the offscreen buffer we don't want to
* deal with the camera border, otherwise map the coords to the camera border. */
if ((rv3d->persp == RV3D_CAMOB) && !(G.f & G_RENDER_OGL)) {
rctf rectf;
ED_view3d_calc_camera_border(scene, ar, v3d, rv3d, &rectf, true); /* no shift */
-
+
offsx = iroundf(rectf.xmin);
offsy = iroundf(rectf.ymin);
winx = iroundf(rectf.xmax - rectf.xmin);
@@ -793,17 +1292,34 @@ void ED_gpencil_draw_view3d(Scene *scene, View3D *v3d, ARegion *ar, bool only3d)
winy = ar->winy;
}
+ /* set flags */
+ if (only3d) {
+ /* 3D strokes/3D space:
+ * - only 3D space points
+ * - don't status text either (as it's the wrong space)
+ */
+ dflag |= (GP_DRAWDATA_ONLY3D | GP_DRAWDATA_NOSTATUS);
+ }
+
+ if (v3d->flag2 & V3D_RENDER_OVERRIDE) {
+ /* don't draw status text when "only render" flag is set */
+ dflag |= GP_DRAWDATA_NOSTATUS;
+ }
+
/* draw it! */
- if (only3d) dflag |= (GP_DRAWDATA_ONLY3D | GP_DRAWDATA_NOSTATUS);
-
- gp_draw_data(gpd, offsx, offsy, winx, winy, CFRA, dflag);
+ gp_draw_data_all(scene, gpd, offsx, offsy, winx, winy, CFRA, dflag, v3d->spacetype);
+
+ /* draw status text (if in screen/pixel-space) */
+ if (only3d == false) {
+ gp_draw_status_text(gpd, ar);
+ }
}
-void ED_gpencil_draw_ex(bGPdata *gpd, int winx, int winy, const int cfra)
+void ED_gpencil_draw_ex(Scene *scene, bGPdata *gpd, int winx, int winy, const int cfra, const char spacetype)
{
int dflag = GP_DRAWDATA_NOSTATUS | GP_DRAWDATA_ONLYV2D;
-
- gp_draw_data(gpd, 0, 0, winx, winy, cfra, dflag);
+
+ gp_draw_data_all(scene, gpd, 0, 0, winx, winy, cfra, dflag, spacetype);
}
/* ************************************************** */
diff --git a/source/blender/editors/gpencil/editaction_gpencil.c b/source/blender/editors/gpencil/editaction_gpencil.c
index dba80164e93..a2ba6216f9c 100644
--- a/source/blender/editors/gpencil/editaction_gpencil.c
+++ b/source/blender/editors/gpencil/editaction_gpencil.c
@@ -27,7 +27,7 @@
* \ingroup edgpencil
*/
-
+
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
@@ -49,8 +49,6 @@
#include "ED_keyframes_edit.h"
#include "ED_markers.h"
-#include "gpencil_intern.h"
-
/* ***************************************** */
/* NOTE ABOUT THIS FILE:
* This file contains code for editing Grease Pencil data in the Action Editor
@@ -75,7 +73,7 @@ bool ED_gplayer_frames_looper(bGPDlayer *gpl, Scene *scene, short (*gpf_cb)(bGPD
if (gpf_cb(gpf, scene))
return true;
}
-
+
/* nothing to return */
return false;
}
@@ -115,7 +113,7 @@ bool ED_gplayer_frame_select_check(bGPDlayer *gpl)
bGPDframe *gpf;
/* error checking */
- if (gpl == NULL)
+ if (gpl == NULL)
return false;
/* stop at the first one found */
@@ -153,9 +151,9 @@ void ED_gpencil_select_frames(bGPDlayer *gpl, short select_mode)
bGPDframe *gpf;
/* error checking */
- if (gpl == NULL)
+ if (gpl == NULL)
return;
-
+
/* handle according to mode */
for (gpf = gpl->frames.first; gpf; gpf = gpf->next) {
gpframe_select(gpf, select_mode);
@@ -166,7 +164,7 @@ void ED_gpencil_select_frames(bGPDlayer *gpl, short select_mode)
void ED_gplayer_frame_select_set(bGPDlayer *gpl, short mode)
{
/* error checking */
- if (gpl == NULL)
+ if (gpl == NULL)
return;
/* now call the standard function */
@@ -178,11 +176,11 @@ void ED_gpencil_select_frame(bGPDlayer *gpl, int selx, short select_mode)
{
bGPDframe *gpf;
- if (gpl == NULL)
+ if (gpl == NULL)
return;
-
+
gpf = BKE_gpencil_layer_find_frame(gpl, selx);
-
+
if (gpf) {
gpframe_select(gpf, select_mode);
}
@@ -215,7 +213,7 @@ bool ED_gplayer_frames_delete(bGPDlayer *gpl)
/* error checking */
if (gpl == NULL)
return false;
-
+
/* check for frames to delete */
for (gpf = gpl->frames.first; gpf; gpf = gpfn) {
gpfn = gpf->next;
@@ -223,7 +221,7 @@ bool ED_gplayer_frames_delete(bGPDlayer *gpl)
if (gpf->flag & GP_FRAME_SELECT)
changed |= gpencil_layer_delframe(gpl, gpf);
}
-
+
return changed;
}
@@ -242,7 +240,7 @@ void ED_gplayer_frames_duplicate(bGPDlayer *gpl)
/* duplicate this frame */
if (gpf->flag & GP_FRAME_SELECT) {
- bGPDframe *gpfd;
+ bGPDframe *gpfd;
/* duplicate frame, and deselect self */
gpfd = gpencil_frame_duplicate(gpf);
@@ -253,6 +251,23 @@ void ED_gplayer_frames_duplicate(bGPDlayer *gpl)
}
}
+/* Set keyframe type for selected frames from given gp-layer
+ * \param type The type of keyframe (eBezTriple_KeyframeType) to set selected frames to
+ */
+void ED_gplayer_frames_keytype_set(bGPDlayer *gpl, short type)
+{
+ bGPDframe *gpf;
+
+ if (gpl == NULL)
+ return;
+
+ for (gpf = gpl->frames.first; gpf; gpf = gpf->next) {
+ if (gpf->flag & GP_FRAME_SELECT) {
+ gpf->key_type = type;
+ }
+ }
+}
+
#if 0 // XXX disabled until grease pencil code stabilises again
/* -------------------------------------- */
/* Copy and Paste Tools */
@@ -263,7 +278,7 @@ void ED_gplayer_frames_duplicate(bGPDlayer *gpl)
* the current frame and the 'first keyframe' (i.e. the earliest one in all channels).
* - The earliest frame is calculated per copy operation.
*/
-
+
/* globals for copy/paste data (like for other copy/paste buffers) */
ListBase gpcopybuf = {NULL, NULL};
static int gpcopy_firstframe = 999999999;
@@ -271,7 +286,7 @@ static int gpcopy_firstframe = 999999999;
/* This function frees any MEM_calloc'ed copy/paste buffer data */
void free_gpcopybuf()
{
- free_gpencil_layers(&gpcopybuf);
+ free_gpencil_layers(&gpcopybuf);
BLI_listbase_clear(&gpcopybuf);
gpcopy_firstframe = 999999999;
@@ -375,7 +390,7 @@ void paste_gpdata(Scene *scene)
/* find suitable layer from buffer to use to paste from */
for (gpls = gpcopybuf.first; gpls; gpls = gpls->next) {
/* check if layer name matches */
- if ((no_name) || (strcmp(gpls->info, gpld->info) == 0))
+ if ((no_name) || STREQ(gpls->info, gpld->info))
break;
}
@@ -398,8 +413,8 @@ void paste_gpdata(Scene *scene)
//sa = gpencil_data_findowner((bGPdata *)ale->owner);
sa = NULL;
- /* this should be the right frame... as it may be a pre-existing frame,
- * must make sure that only compatible stroke types get copied over
+ /* this should be the right frame... as it may be a pre-existing frame,
+ * must make sure that only compatible stroke types get copied over
* - we cannot just add a duplicate frame, as that would cause errors
* - need to check for compatible types to minimize memory usage (copying 'junk' over)
*/
@@ -418,14 +433,14 @@ void paste_gpdata(Scene *scene)
if ((gps->flag == 0) || (gps->flag & GP_STROKE_3DSPACE))
stroke_ok = 1;
break;
-
+
case SPACE_NODE: /* Nodes Editor: either screen-aligned or view-aligned */
case SPACE_IMAGE: /* Image Editor: either screen-aligned or view\image-aligned */
case SPACE_CLIP: /* Image Editor: either screen-aligned or view\image-aligned */
if ((gps->flag == 0) || (gps->flag & GP_STROKE_2DSPACE))
stroke_ok = 1;
break;
-
+
case SPACE_SEQ: /* Sequence Editor: either screen-aligned or view-aligned */
if ((gps->flag == 0) || (gps->flag & GP_STROKE_2DIMAGE))
stroke_ok = 1;
@@ -567,9 +582,9 @@ static short mirror_gpf_marker(bGPDframe *gpf, Scene *scene)
/* In order for this mirror function to work without
* any extra arguments being added, we use the case
- * of bezt==NULL to denote that we should find the
+ * of bezt==NULL to denote that we should find the
* marker to mirror over. The static pointer is safe
- * to use this way, as it will be set to null after
+ * to use this way, as it will be set to null after
* each cycle in which this is called.
*/
diff --git a/source/blender/editors/gpencil/gpencil_buttons.c b/source/blender/editors/gpencil/gpencil_buttons.c
deleted file mode 100644
index 0acff8fc0a5..00000000000
--- a/source/blender/editors/gpencil/gpencil_buttons.c
+++ /dev/null
@@ -1,378 +0,0 @@
-/*
- * ***** BEGIN GPL LICENSE BLOCK *****
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * The Original Code is Copyright (C) 2008, Blender Foundation, Joshua Leung
- * This is a new part of Blender
- *
- * Contributor(s): Joshua Leung
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-
-/** \file blender/editors/gpencil/gpencil_buttons.c
- * \ingroup edgpencil
- */
-
-
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <stddef.h>
-
-#include "BLI_blenlib.h"
-
-#include "BLF_translation.h"
-
-#include "DNA_gpencil_types.h"
-#include "DNA_screen_types.h"
-#include "DNA_space_types.h"
-
-#include "BKE_context.h"
-#include "BKE_global.h"
-#include "BKE_gpencil.h"
-
-#include "WM_api.h"
-#include "WM_types.h"
-
-#include "RNA_access.h"
-
-#include "ED_gpencil.h"
-
-#include "UI_interface.h"
-#include "UI_resources.h"
-
-#include "gpencil_intern.h"
-
-/* ************************************************** */
-/* GREASE PENCIL PANEL-UI DRAWING */
-
-/* Every space which implements Grease-Pencil functionality should have a panel
- * for the settings. All of the space-dependent parts should be coded in the panel
- * code for that space, but the rest is all handled by generic panel here.
- */
-
-/* ------- Callbacks ----------- */
-/* These are just 'dummy wrappers' around gpencil api calls */
-
-/* make layer active one after being clicked on */
-static void gp_ui_activelayer_cb(bContext *C, void *gpd, void *gpl)
-{
- /* make sure the layer we want to remove is the active one */
- gpencil_layer_setactive(gpd, gpl);
-
- WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
-}
-
-/* delete 'active' layer */
-static void gp_ui_dellayer_cb(bContext *C, void *gpd, void *gpl)
-{
- gpencil_layer_delete((bGPdata *)gpd, (bGPDlayer *)gpl);
-
- WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
-}
-
-/* move layer up */
-static void gp_ui_layer_up_cb(bContext *C, void *gpd_v, void *gpl_v)
-{
- bGPdata *gpd = gpd_v;
- bGPDlayer *gpl = gpl_v;
-
- BLI_remlink(&gpd->layers, gpl);
- BLI_insertlinkbefore(&gpd->layers, gpl->prev, gpl);
-
- WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
-}
-
-/* move layer down */
-static void gp_ui_layer_down_cb(bContext *C, void *gpd_v, void *gpl_v)
-{
- bGPdata *gpd = gpd_v;
- bGPDlayer *gpl = gpl_v;
-
- BLI_remlink(&gpd->layers, gpl);
- BLI_insertlinkafter(&gpd->layers, gpl->next, gpl);
-
- WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
-}
-
-/* ------- Drawing Code ------- */
-
-/* draw the controls for a given layer */
-static void gp_drawui_layer(uiLayout *layout, bGPdata *gpd, bGPDlayer *gpl, const bool is_v3d)
-{
- uiLayout *box = NULL, *split = NULL;
- uiLayout *col = NULL;
- uiLayout *row = NULL, *sub = NULL;
- uiBlock *block;
- uiBut *but;
- PointerRNA ptr;
- int icon;
-
- /* make pointer to layer data */
- RNA_pointer_create((ID *)gpd, &RNA_GPencilLayer, gpl, &ptr);
-
- /* unless button has own callback, it adds this callback to button */
- block = uiLayoutGetBlock(layout);
- uiBlockSetFunc(block, gp_ui_activelayer_cb, gpd, gpl);
-
- /* draw header ---------------------------------- */
- /* get layout-row + UI-block for header */
- box = uiLayoutBox(layout);
-
- row = uiLayoutRow(box, false);
- uiLayoutSetAlignment(row, UI_LAYOUT_ALIGN_EXPAND);
- block = uiLayoutGetBlock(row); /* err... */
-
- uiBlockSetEmboss(block, UI_EMBOSSN);
-
- /* left-align ............................... */
- sub = uiLayoutRow(row, false);
-
- /* active */
- block = uiLayoutGetBlock(sub);
- icon = (gpl->flag & GP_LAYER_ACTIVE) ? ICON_RADIOBUT_ON : ICON_RADIOBUT_OFF;
- but = uiDefIconButBitI(block, TOG, GP_LAYER_ACTIVE, 0, icon, 0, 0, UI_UNIT_X, UI_UNIT_Y,
- &gpl->flag, 0.0, 0.0, 0.0, 0.0, TIP_("Set active layer"));
- uiButSetFunc(but, gp_ui_activelayer_cb, gpd, gpl);
-
- /* locked */
- icon = (gpl->flag & GP_LAYER_LOCKED) ? ICON_LOCKED : ICON_UNLOCKED;
- uiItemR(sub, &ptr, "lock", 0, "", icon);
-
- /* when layer is locked or hidden, only draw header */
- if (gpl->flag & (GP_LAYER_LOCKED | GP_LAYER_HIDE)) {
- char name[256]; /* gpl->info is 128, but we need space for 'locked/hidden' as well */
-
- /* visibility button (only if hidden but not locked!) */
- if ((gpl->flag & GP_LAYER_HIDE) && !(gpl->flag & GP_LAYER_LOCKED))
- uiItemR(sub, &ptr, "hide", 0, "", ICON_RESTRICT_VIEW_ON);
-
- /* name */
- if (gpl->flag & GP_LAYER_HIDE)
- BLI_snprintf(name, sizeof(name), IFACE_("%s (Hidden)"), gpl->info);
- else
- BLI_snprintf(name, sizeof(name), IFACE_("%s (Locked)"), gpl->info);
- uiItemL(sub, name, ICON_NONE);
-
- /* delete button (only if hidden but not locked!) */
- if ((gpl->flag & GP_LAYER_HIDE) && !(gpl->flag & GP_LAYER_LOCKED)) {
- /* right-align ............................... */
- sub = uiLayoutRow(row, true);
- uiLayoutSetAlignment(sub, UI_LAYOUT_ALIGN_RIGHT);
- block = uiLayoutGetBlock(sub); /* XXX... err... */
-
- but = uiDefIconBut(block, BUT, 0, ICON_X, 0, 0, UI_UNIT_X, UI_UNIT_Y,
- NULL, 0.0, 0.0, 0.0, 0.0, TIP_("Delete layer"));
- uiButSetFunc(but, gp_ui_dellayer_cb, gpd, gpl);
- }
- uiBlockSetEmboss(block, UI_EMBOSS);
- }
- else {
- /* draw rest of header -------------------------------- */
- /* visibility button */
- uiItemR(sub, &ptr, "hide", 0, "", ICON_RESTRICT_VIEW_OFF);
-
- /* frame locking */
- /* TODO: this needs its own icons... */
- icon = (gpl->flag & GP_LAYER_FRAMELOCK) ? ICON_RENDER_STILL : ICON_RENDER_ANIMATION;
- uiItemR(sub, &ptr, "lock_frame", 0, "", icon);
-
- uiBlockSetEmboss(block, UI_EMBOSS);
-
- /* name */
- uiItemR(sub, &ptr, "info", 0, "", ICON_NONE);
-
- /* move up/down */
- uiBlockBeginAlign(block);
-
- if (gpl->prev) {
- but = uiDefIconBut(block, BUT, 0, ICON_TRIA_UP, 0, 0, UI_UNIT_X, UI_UNIT_Y,
- NULL, 0.0, 0.0, 0.0, 0.0, TIP_("Move layer up"));
- uiButSetFunc(but, gp_ui_layer_up_cb, gpd, gpl);
- }
- if (gpl->next) {
- but = uiDefIconBut(block, BUT, 0, ICON_TRIA_DOWN, 0, 0, UI_UNIT_X, UI_UNIT_Y,
- NULL, 0.0, 0.0, 0.0, 0.0, TIP_("Move layer down"));
- uiButSetFunc(but, gp_ui_layer_down_cb, gpd, gpl);
- }
-
- uiBlockEndAlign(block);
-
- /* delete 'button' */
- uiBlockSetEmboss(block, UI_EMBOSSN);
- /* right-align ............................... */
- sub = uiLayoutRow(row, true);
- uiLayoutSetAlignment(sub, UI_LAYOUT_ALIGN_RIGHT);
- block = uiLayoutGetBlock(sub); /* XXX... err... */
-
- but = uiDefIconBut(block, BUT, 0, ICON_X, 0, 0, UI_UNIT_X, UI_UNIT_Y,
- NULL, 0.0, 0.0, 0.0, 0.0, TIP_("Delete layer"));
- uiButSetFunc(but, gp_ui_dellayer_cb, gpd, gpl);
- uiBlockSetEmboss(block, UI_EMBOSS);
-
- /* new backdrop ----------------------------------- */
- box = uiLayoutBox(layout);
- split = uiLayoutSplit(box, 0.5f, false);
-
- /* draw settings ---------------------------------- */
- /* left column ..................... */
- col = uiLayoutColumn(split, false);
-
- /* color */
- sub = uiLayoutColumn(col, true);
- uiItemR(sub, &ptr, "color", 0, "", ICON_NONE);
- uiItemR(sub, &ptr, "alpha", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
-
- /* stroke thickness */
- uiItemR(col, &ptr, "line_width", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
-
- /* debugging options */
- if (G.debug & G_DEBUG) {
- uiItemR(col, &ptr, "show_points", 0, NULL, ICON_NONE);
- }
-
- /* right column ................... */
- col = uiLayoutColumn(split, false);
-
- /* onion-skinning */
- sub = uiLayoutColumn(col, true);
- uiItemR(sub, &ptr, "use_onion_skinning", 0, NULL, ICON_NONE);
- uiItemR(sub, &ptr, "ghost_range_max", 0, IFACE_("Frames"), ICON_NONE);
-
- /* 3d-view specific drawing options */
- if (is_v3d) {
- uiItemR(col, &ptr, "show_x_ray", 0, NULL, ICON_NONE);
- }
- }
-}
-
-/* stroke drawing options available */
-typedef enum eGP_Stroke_Ops {
- STROKE_OPTS_NORMAL = 0,
- STROKE_OPTS_V3D_OFF,
- STROKE_OPTS_V3D_ON,
-} eGP_Stroke_Ops;
-
-static void draw_gpencil_space_specials(const bContext *C, uiLayout *layout)
-{
- uiLayout *col, *row;
- SpaceClip *sc = CTX_wm_space_clip(C);
-
- col = uiLayoutColumn(layout, false);
-
- if (sc) {
- bScreen *screen = CTX_wm_screen(C);
- PointerRNA sc_ptr;
-
- RNA_pointer_create(&screen->id, &RNA_SpaceClipEditor, sc, &sc_ptr);
- row = uiLayoutRow(col, true);
- uiItemR(row, &sc_ptr, "grease_pencil_source", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
- }
-}
-
-/* Draw the contents for a grease-pencil panel*/
-static void draw_gpencil_panel(bContext *C, uiLayout *layout, bGPdata *gpd, PointerRNA *ctx_ptr)
-{
- PointerRNA gpd_ptr;
- bGPDlayer *gpl;
- uiLayout *col, *row;
- SpaceClip *sc = CTX_wm_space_clip(C);
- short v3d_stroke_opts = STROKE_OPTS_NORMAL;
- const bool is_v3d = CTX_wm_view3d(C) != NULL;
-
- /* make new PointerRNA for Grease Pencil block */
- RNA_id_pointer_create((ID *)gpd, &gpd_ptr);
-
- /* draw gpd settings first ------------------------------------- */
- col = uiLayoutColumn(layout, false);
-
- /* current Grease Pencil block */
- /* TODO: show some info about who owns this? */
- uiTemplateID(col, C, ctx_ptr, "grease_pencil", "GPENCIL_OT_data_add", NULL, "GPENCIL_OT_data_unlink");
-
- /* add new layer button - can be used even when no data, since it can add a new block too */
- uiItemO(col, IFACE_("New Layer"), ICON_NONE, "GPENCIL_OT_layer_add");
- row = uiLayoutRow(col, true);
- uiItemO(row, IFACE_("Delete Frame"), ICON_NONE, "GPENCIL_OT_active_frame_delete");
- uiItemO(row, IFACE_("Convert"), ICON_NONE, "GPENCIL_OT_convert");
-
- /* sanity checks... */
- if (gpd == NULL)
- return;
-
- /* draw each layer --------------------------------------------- */
- for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
- col = uiLayoutColumn(layout, true);
- gp_drawui_layer(col, gpd, gpl, is_v3d);
- }
-
- /* draw gpd drawing settings first ------------------------------------- */
- col = uiLayoutColumn(layout, true);
- /* label */
- uiItemL(col, IFACE_("Drawing Settings:"), ICON_NONE);
-
- /* check whether advanced 3D-View drawing space options can be used */
- if (is_v3d) {
- if (gpd->flag & (GP_DATA_DEPTH_STROKE | GP_DATA_DEPTH_VIEW))
- v3d_stroke_opts = STROKE_OPTS_V3D_ON;
- else
- v3d_stroke_opts = STROKE_OPTS_V3D_OFF;
- }
-
- /* drawing space options */
- row = uiLayoutRow(col, true);
- uiItemEnumR_string(row, &gpd_ptr, "draw_mode", "VIEW", NULL, ICON_NONE);
- uiItemEnumR_string(row, &gpd_ptr, "draw_mode", "CURSOR", NULL, ICON_NONE);
-
- if (sc == NULL) {
- row = uiLayoutRow(col, true);
- uiLayoutSetActive(row, v3d_stroke_opts);
- uiItemEnumR_string(row, &gpd_ptr, "draw_mode", "SURFACE", NULL, ICON_NONE);
- uiItemEnumR_string(row, &gpd_ptr, "draw_mode", "STROKE", NULL, ICON_NONE);
-
- row = uiLayoutRow(col, false);
- uiLayoutSetActive(row, v3d_stroke_opts == STROKE_OPTS_V3D_ON);
- uiItemR(row, &gpd_ptr, "use_stroke_endpoints", 0, NULL, ICON_NONE);
- }
-}
-
-void ED_gpencil_panel_standard_header(const bContext *C, Panel *pa)
-{
- PointerRNA ptr;
- RNA_pointer_create((ID *)CTX_wm_screen(C), &RNA_Space, CTX_wm_space_data(C), &ptr);
-
- uiItemR(pa->layout, &ptr, "show_grease_pencil", 0, "", ICON_NONE);
-}
-
-/* Standard panel to be included wherever Grease Pencil is used... */
-void ED_gpencil_panel_standard(const bContext *C, Panel *pa)
-{
- bGPdata **gpd_ptr = NULL;
- PointerRNA ptr;
-
- /* if (v3d->flag2 & V3D_DISPGP)... etc. */
-
- draw_gpencil_space_specials(C, pa->layout);
-
- /* get pointer to Grease Pencil Data */
- gpd_ptr = ED_gpencil_data_get_pointers((bContext *)C, &ptr);
-
- if (gpd_ptr)
- draw_gpencil_panel((bContext *)C, pa->layout, *gpd_ptr, &ptr);
-}
-
-/* ************************************************** */
diff --git a/source/blender/editors/gpencil/gpencil_convert.c b/source/blender/editors/gpencil/gpencil_convert.c
new file mode 100644
index 00000000000..e8d73eaffdf
--- /dev/null
+++ b/source/blender/editors/gpencil/gpencil_convert.c
@@ -0,0 +1,1484 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2008, Blender Foundation
+ * This is a new part of Blender
+ *
+ * Contributor(s): Joshua Leung
+ * Bastien Montagne
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ *
+ * Operator for converting Grease Pencil data to geometry
+ */
+
+/** \file blender/editors/gpencil/gpencil_convert.c
+ * \ingroup edgpencil
+ */
+
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <math.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_math.h"
+#include "BLI_blenlib.h"
+#include "BLI_rand.h"
+#include "BLI_utildefines.h"
+
+#include "BLT_translation.h"
+
+#include "DNA_anim_types.h"
+#include "DNA_curve_types.h"
+#include "DNA_object_types.h"
+#include "DNA_node_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_space_types.h"
+#include "DNA_view3d_types.h"
+#include "DNA_gpencil_types.h"
+
+#include "BKE_context.h"
+#include "BKE_curve.h"
+#include "BKE_depsgraph.h"
+#include "BKE_fcurve.h"
+#include "BKE_global.h"
+#include "BKE_gpencil.h"
+#include "BKE_library.h"
+#include "BKE_object.h"
+#include "BKE_report.h"
+#include "BKE_scene.h"
+#include "BKE_screen.h"
+#include "BKE_tracking.h"
+
+#include "UI_interface.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+
+#include "UI_view2d.h"
+
+#include "ED_gpencil.h"
+#include "ED_view3d.h"
+#include "ED_clip.h"
+#include "ED_keyframing.h"
+
+#include "gpencil_intern.h"
+
+/* ************************************************ */
+/* Grease Pencil to Data Operator */
+
+/* defines for possible modes */
+enum {
+ GP_STROKECONVERT_PATH = 1,
+ GP_STROKECONVERT_CURVE,
+ GP_STROKECONVERT_POLY,
+};
+
+/* Defines for possible timing modes */
+enum {
+ GP_STROKECONVERT_TIMING_NONE = 1,
+ GP_STROKECONVERT_TIMING_LINEAR = 2,
+ GP_STROKECONVERT_TIMING_FULL = 3,
+ GP_STROKECONVERT_TIMING_CUSTOMGAP = 4,
+};
+
+/* RNA enum define */
+static EnumPropertyItem prop_gpencil_convertmodes[] = {
+ {GP_STROKECONVERT_PATH, "PATH", 0, "Path", ""},
+ {GP_STROKECONVERT_CURVE, "CURVE", 0, "Bezier Curve", ""},
+ {GP_STROKECONVERT_POLY, "POLY", 0, "Polygon Curve", ""},
+ {0, NULL, 0, NULL, NULL}
+};
+
+static EnumPropertyItem prop_gpencil_convert_timingmodes_restricted[] = {
+ {GP_STROKECONVERT_TIMING_NONE, "NONE", 0, "No Timing", "Ignore timing"},
+ {GP_STROKECONVERT_TIMING_LINEAR, "LINEAR", 0, "Linear", "Simple linear timing"},
+ {0, NULL, 0, NULL, NULL},
+};
+
+static EnumPropertyItem prop_gpencil_convert_timingmodes[] = {
+ {GP_STROKECONVERT_TIMING_NONE, "NONE", 0, "No Timing", "Ignore timing"},
+ {GP_STROKECONVERT_TIMING_LINEAR, "LINEAR", 0, "Linear", "Simple linear timing"},
+ {GP_STROKECONVERT_TIMING_FULL, "FULL", 0, "Original", "Use the original timing, gaps included"},
+ {GP_STROKECONVERT_TIMING_CUSTOMGAP, "CUSTOMGAP", 0, "Custom Gaps",
+ "Use the original timing, but with custom gap lengths (in frames)"},
+ {0, NULL, 0, NULL, NULL},
+};
+
+static EnumPropertyItem *rna_GPConvert_mode_items(bContext *UNUSED(C), PointerRNA *ptr, PropertyRNA *UNUSED(prop),
+ bool *UNUSED(r_free))
+{
+ if (RNA_boolean_get(ptr, "use_timing_data")) {
+ return prop_gpencil_convert_timingmodes;
+ }
+ return prop_gpencil_convert_timingmodes_restricted;
+}
+
+/* --- */
+
+/* convert the coordinates from the given stroke point into 3d-coordinates
+ * - assumes that the active space is the 3D-View
+ */
+static void gp_strokepoint_convertcoords(bContext *C, bGPDstroke *gps, bGPDspoint *pt, float p3d[3], rctf *subrect)
+{
+ Scene *scene = CTX_data_scene(C);
+ View3D *v3d = CTX_wm_view3d(C);
+ ARegion *ar = CTX_wm_region(C);
+
+ if (gps->flag & GP_STROKE_3DSPACE) {
+ /* directly use 3d-coordinates */
+ copy_v3_v3(p3d, &pt->x);
+ }
+ else {
+ const float *fp = ED_view3d_cursor3d_get(scene, v3d);
+ float mvalf[2];
+
+ /* get screen coordinate */
+ if (gps->flag & GP_STROKE_2DSPACE) {
+ View2D *v2d = &ar->v2d;
+ UI_view2d_view_to_region_fl(v2d, pt->x, pt->y, &mvalf[0], &mvalf[1]);
+ }
+ else {
+ if (subrect) {
+ mvalf[0] = (((float)pt->x / 100.0f) * BLI_rctf_size_x(subrect)) + subrect->xmin;
+ mvalf[1] = (((float)pt->y / 100.0f) * BLI_rctf_size_y(subrect)) + subrect->ymin;
+ }
+ else {
+ mvalf[0] = (float)pt->x / 100.0f * ar->winx;
+ mvalf[1] = (float)pt->y / 100.0f * ar->winy;
+ }
+ }
+
+ ED_view3d_win_to_3d(ar, fp, mvalf, p3d);
+ }
+}
+
+/* --- */
+
+/* temp struct for gp_stroke_path_animation() */
+typedef struct tGpTimingData {
+ /* Data set from operator settings */
+ int mode;
+ int frame_range; /* Number of frames evaluated for path animation */
+ int start_frame, end_frame;
+ bool realtime; /* Will overwrite end_frame in case of Original or CustomGap timing... */
+ float gap_duration, gap_randomness; /* To be used with CustomGap mode*/
+ int seed;
+
+ /* Data set from points, used to compute final timing FCurve */
+ int num_points, cur_point;
+
+ /* Distances */
+ float *dists;
+ float tot_dist;
+
+ /* Times */
+ float *times; /* Note: Gap times will be negative! */
+ float tot_time, gap_tot_time;
+ double inittime;
+
+ /* Only used during creation of dists & times lists. */
+ float offset_time;
+} tGpTimingData;
+
+/* Init point buffers for timing data.
+ * Note this assumes we only grow those arrays!
+ */
+static void gp_timing_data_set_nbr(tGpTimingData *gtd, const int nbr)
+{
+ float *tmp;
+
+ BLI_assert(nbr > gtd->num_points);
+
+ /* distances */
+ tmp = gtd->dists;
+ gtd->dists = MEM_callocN(sizeof(float) * nbr, __func__);
+ if (tmp) {
+ memcpy(gtd->dists, tmp, sizeof(float) * gtd->num_points);
+ MEM_freeN(tmp);
+ }
+
+ /* times */
+ tmp = gtd->times;
+ gtd->times = MEM_callocN(sizeof(float) * nbr, __func__);
+ if (tmp) {
+ memcpy(gtd->times, tmp, sizeof(float) * gtd->num_points);
+ MEM_freeN(tmp);
+ }
+
+ gtd->num_points = nbr;
+}
+
+/* add stroke point to timing buffers */
+static void gp_timing_data_add_point(tGpTimingData *gtd, const double stroke_inittime, const float time,
+ const float delta_dist)
+{
+ float delta_time = 0.0f;
+ const int cur_point = gtd->cur_point;
+
+ if (!cur_point) {
+ /* Special case, first point, if time is not 0.0f we have to compensate! */
+ gtd->offset_time = -time;
+ gtd->times[cur_point] = 0.0f;
+ }
+ else if (time < 0.0f) {
+ /* This is a gap, negative value! */
+ gtd->times[cur_point] = -(((float)(stroke_inittime - gtd->inittime)) + time + gtd->offset_time);
+ delta_time = -gtd->times[cur_point] - gtd->times[cur_point - 1];
+
+ gtd->gap_tot_time += delta_time;
+ }
+ else {
+ gtd->times[cur_point] = (((float)(stroke_inittime - gtd->inittime)) + time + gtd->offset_time);
+ delta_time = gtd->times[cur_point] - fabsf(gtd->times[cur_point - 1]);
+ }
+
+ gtd->tot_time += delta_time;
+ gtd->tot_dist += delta_dist;
+ gtd->dists[cur_point] = gtd->tot_dist;
+
+ gtd->cur_point++;
+}
+
+/* In frames! Binary search for FCurve keys have a threshold of 0.01, so we can't set
+ * arbitrarily close points - this is esp. important with NoGaps mode!
+ */
+#define MIN_TIME_DELTA 0.02f
+
+/* Loop over next points to find the end of the stroke, and compute */
+static int gp_find_end_of_stroke_idx(tGpTimingData *gtd, RNG *rng, const int idx, const int nbr_gaps,
+ int *nbr_done_gaps, const float tot_gaps_time, const float delta_time,
+ float *next_delta_time)
+{
+ int j;
+
+ for (j = idx + 1; j < gtd->num_points; j++) {
+ if (gtd->times[j] < 0) {
+ gtd->times[j] = -gtd->times[j];
+ if (gtd->mode == GP_STROKECONVERT_TIMING_CUSTOMGAP) {
+ /* In this mode, gap time between this stroke and the next should be 0 currently...
+ * So we have to compute its final duration!
+ */
+ if (gtd->gap_randomness > 0.0f) {
+ /* We want gaps that are in gtd->gap_duration +/- gtd->gap_randomness range,
+ * and which sum to exactly tot_gaps_time...
+ */
+ int rem_gaps = nbr_gaps - (*nbr_done_gaps);
+ if (rem_gaps < 2) {
+ /* Last gap, just give remaining time! */
+ *next_delta_time = tot_gaps_time;
+ }
+ else {
+ float delta, min, max;
+
+ /* This code ensures that if the first gaps have been shorter than average gap_duration,
+ * next gaps will tend to be longer (i.e. try to recover the lateness), and vice-versa!
+ */
+ delta = delta_time - (gtd->gap_duration * (*nbr_done_gaps));
+
+ /* Clamp min between [-gap_randomness, 0.0], with lower delta giving higher min */
+ min = -gtd->gap_randomness - delta;
+ CLAMP(min, -gtd->gap_randomness, 0.0f);
+
+ /* Clamp max between [0.0, gap_randomness], with lower delta giving higher max */
+ max = gtd->gap_randomness - delta;
+ CLAMP(max, 0.0f, gtd->gap_randomness);
+ *next_delta_time += gtd->gap_duration + (BLI_rng_get_float(rng) * (max - min)) + min;
+ }
+ }
+ else {
+ *next_delta_time += gtd->gap_duration;
+ }
+ }
+ (*nbr_done_gaps)++;
+ break;
+ }
+ }
+
+ return j - 1;
+}
+
+static void gp_stroke_path_animation_preprocess_gaps(tGpTimingData *gtd, RNG *rng, int *nbr_gaps, float *tot_gaps_time)
+{
+ int i;
+ float delta_time = 0.0f;
+
+ for (i = 0; i < gtd->num_points; i++) {
+ if (gtd->times[i] < 0 && i) {
+ (*nbr_gaps)++;
+ gtd->times[i] = -gtd->times[i] - delta_time;
+ delta_time += gtd->times[i] - gtd->times[i - 1];
+ gtd->times[i] = -gtd->times[i - 1]; /* Temp marker, values *have* to be different! */
+ }
+ else {
+ gtd->times[i] -= delta_time;
+ }
+ }
+ gtd->tot_time -= delta_time;
+
+ *tot_gaps_time = (float)(*nbr_gaps) * gtd->gap_duration;
+ gtd->tot_time += *tot_gaps_time;
+ if (G.debug & G_DEBUG) {
+ printf("%f, %f, %f, %d\n", gtd->tot_time, delta_time, *tot_gaps_time, *nbr_gaps);
+ }
+ if (gtd->gap_randomness > 0.0f) {
+ BLI_rng_srandom(rng, gtd->seed);
+ }
+}
+
+static void gp_stroke_path_animation_add_keyframes(ReportList *reports, PointerRNA ptr, PropertyRNA *prop, FCurve *fcu,
+ Curve *cu, tGpTimingData *gtd, RNG *rng, const float time_range,
+ const int nbr_gaps, const float tot_gaps_time)
+{
+ /* Use actual recorded timing! */
+ const float time_start = (float)gtd->start_frame;
+
+ float last_valid_time = 0.0f;
+ int end_stroke_idx = -1, start_stroke_idx = 0;
+ float end_stroke_time = 0.0f;
+
+ /* CustomGaps specific */
+ float delta_time = 0.0f, next_delta_time = 0.0f;
+ int nbr_done_gaps = 0;
+
+ int i;
+ float cfra;
+
+ /* This is a bit tricky, as:
+ * - We can't add arbitrarily close points on FCurve (in time).
+ * - We *must* have all "caps" points of all strokes in FCurve, as much as possible!
+ */
+ for (i = 0; i < gtd->num_points; i++) {
+ /* If new stroke... */
+ if (i > end_stroke_idx) {
+ start_stroke_idx = i;
+ delta_time = next_delta_time;
+ /* find end of that new stroke */
+ end_stroke_idx = gp_find_end_of_stroke_idx(gtd, rng, i, nbr_gaps, &nbr_done_gaps,
+ tot_gaps_time, delta_time, &next_delta_time);
+ /* This one should *never* be negative! */
+ end_stroke_time = time_start + ((gtd->times[end_stroke_idx] + delta_time) / gtd->tot_time * time_range);
+ }
+
+ /* Simple proportional stuff... */
+ cu->ctime = gtd->dists[i] / gtd->tot_dist * cu->pathlen;
+ cfra = time_start + ((gtd->times[i] + delta_time) / gtd->tot_time * time_range);
+
+ /* And now, the checks about timing... */
+ if (i == start_stroke_idx) {
+ /* If first point of a stroke, be sure it's enough ahead of last valid keyframe, and
+ * that the end point of the stroke is far enough!
+ * In case it is not, we keep the end point...
+ * Note that with CustomGaps mode, this is here we set the actual gap timing!
+ */
+ if ((end_stroke_time - last_valid_time) > MIN_TIME_DELTA * 2) {
+ if ((cfra - last_valid_time) < MIN_TIME_DELTA) {
+ cfra = last_valid_time + MIN_TIME_DELTA;
+ }
+ insert_keyframe_direct(reports, ptr, prop, fcu, cfra, INSERTKEY_FAST);
+ last_valid_time = cfra;
+ }
+ else if (G.debug & G_DEBUG) {
+ printf("\t Skipping start point %d, too close from end point %d\n", i, end_stroke_idx);
+ }
+ }
+ else if (i == end_stroke_idx) {
+ /* Always try to insert end point of a curve (should be safe enough, anyway...) */
+ if ((cfra - last_valid_time) < MIN_TIME_DELTA) {
+ cfra = last_valid_time + MIN_TIME_DELTA;
+ }
+ insert_keyframe_direct(reports, ptr, prop, fcu, cfra, INSERTKEY_FAST);
+ last_valid_time = cfra;
+ }
+ else {
+ /* Else ("middle" point), we only insert it if it's far enough from last keyframe,
+ * and also far enough from (not yet added!) end_stroke keyframe!
+ */
+ if ((cfra - last_valid_time) > MIN_TIME_DELTA && (end_stroke_time - cfra) > MIN_TIME_DELTA) {
+ insert_keyframe_direct(reports, ptr, prop, fcu, cfra, INSERTKEY_FAST);
+ last_valid_time = cfra;
+ }
+ else if (G.debug & G_DEBUG) {
+ printf("\t Skipping \"middle\" point %d, too close from last added point or end point %d\n",
+ i, end_stroke_idx);
+ }
+ }
+ }
+}
+
+static void gp_stroke_path_animation(bContext *C, ReportList *reports, Curve *cu, tGpTimingData *gtd)
+{
+ Scene *scene = CTX_data_scene(C);
+ bAction *act;
+ FCurve *fcu;
+ PointerRNA ptr;
+ PropertyRNA *prop = NULL;
+ int nbr_gaps = 0, i;
+
+ if (gtd->mode == GP_STROKECONVERT_TIMING_NONE)
+ return;
+
+ /* gap_duration and gap_randomness are in frames, but we need seconds!!! */
+ gtd->gap_duration = FRA2TIME(gtd->gap_duration);
+ gtd->gap_randomness = FRA2TIME(gtd->gap_randomness);
+
+ /* Enable path! */
+ cu->flag |= CU_PATH;
+ cu->pathlen = gtd->frame_range;
+
+ /* Get RNA pointer to read/write path time values */
+ RNA_id_pointer_create((ID *)cu, &ptr);
+ prop = RNA_struct_find_property(&ptr, "eval_time");
+
+ /* Ensure we have an F-Curve to add keyframes to */
+ act = verify_adt_action((ID *)cu, true);
+ fcu = verify_fcurve(act, NULL, &ptr, "eval_time", 0, true);
+
+ if (G.debug & G_DEBUG) {
+ printf("%s: tot len: %f\t\ttot time: %f\n", __func__, gtd->tot_dist, gtd->tot_time);
+ for (i = 0; i < gtd->num_points; i++) {
+ printf("\tpoint %d:\t\tlen: %f\t\ttime: %f\n", i, gtd->dists[i], gtd->times[i]);
+ }
+ }
+
+ if (gtd->mode == GP_STROKECONVERT_TIMING_LINEAR) {
+ float cfra;
+
+ /* Linear extrapolation! */
+ fcu->extend = FCURVE_EXTRAPOLATE_LINEAR;
+
+ cu->ctime = 0.0f;
+ cfra = (float)gtd->start_frame;
+ insert_keyframe_direct(reports, ptr, prop, fcu, cfra, INSERTKEY_FAST);
+
+ cu->ctime = cu->pathlen;
+ if (gtd->realtime) {
+ cfra += (float)TIME2FRA(gtd->tot_time); /* Seconds to frames */
+ }
+ else {
+ cfra = (float)gtd->end_frame;
+ }
+ insert_keyframe_direct(reports, ptr, prop, fcu, cfra, INSERTKEY_FAST);
+ }
+ else {
+ /* Use actual recorded timing! */
+ RNG *rng = BLI_rng_new(0);
+ float time_range;
+
+ /* CustomGaps specific */
+ float tot_gaps_time = 0.0f;
+
+ /* Pre-process gaps, in case we don't want to keep their original timing */
+ if (gtd->mode == GP_STROKECONVERT_TIMING_CUSTOMGAP) {
+ gp_stroke_path_animation_preprocess_gaps(gtd, rng, &nbr_gaps, &tot_gaps_time);
+ }
+
+ if (gtd->realtime) {
+ time_range = (float)TIME2FRA(gtd->tot_time); /* Seconds to frames */
+ }
+ else {
+ time_range = (float)(gtd->end_frame - gtd->start_frame);
+ }
+
+ if (G.debug & G_DEBUG) {
+ printf("GP Stroke Path Conversion: Starting keying!\n");
+ }
+
+ gp_stroke_path_animation_add_keyframes(reports, ptr, prop, fcu, cu, gtd, rng, time_range,
+ nbr_gaps, tot_gaps_time);
+
+ BLI_rng_free(rng);
+ }
+
+ /* As we used INSERTKEY_FAST mode, we need to recompute all curve's handles now */
+ calchandles_fcurve(fcu);
+
+ if (G.debug & G_DEBUG) {
+ printf("%s: \ntot len: %f\t\ttot time: %f\n", __func__, gtd->tot_dist, gtd->tot_time);
+ for (i = 0; i < gtd->num_points; i++) {
+ printf("\tpoint %d:\t\tlen: %f\t\ttime: %f\n", i, gtd->dists[i], gtd->times[i]);
+ }
+ printf("\n\n");
+ }
+
+ WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL);
+
+ /* send updates */
+ DAG_id_tag_update(&cu->id, 0);
+}
+
+#undef MIN_TIME_DELTA
+
+#define GAP_DFAC 0.01f
+#define WIDTH_CORR_FAC 0.1f
+#define BEZT_HANDLE_FAC 0.3f
+
+/* convert stroke to 3d path */
+
+/* helper */
+static void gp_stroke_to_path_add_point(tGpTimingData *gtd, BPoint *bp, const float p[3], const float prev_p[3],
+ const bool do_gtd, const double inittime, const float time,
+ const float width, const float rad_fac, float minmax_weights[2])
+{
+ copy_v3_v3(bp->vec, p);
+ bp->vec[3] = 1.0f;
+
+ /* set settings */
+ bp->f1 = SELECT;
+ bp->radius = width * rad_fac;
+ bp->weight = width;
+ CLAMP(bp->weight, 0.0f, 1.0f);
+ if (bp->weight < minmax_weights[0]) {
+ minmax_weights[0] = bp->weight;
+ }
+ else if (bp->weight > minmax_weights[1]) {
+ minmax_weights[1] = bp->weight;
+ }
+
+ /* Update timing data */
+ if (do_gtd) {
+ gp_timing_data_add_point(gtd, inittime, time, len_v3v3(prev_p, p));
+ }
+}
+
+static void gp_stroke_to_path(bContext *C, bGPDlayer *gpl, bGPDstroke *gps, Curve *cu, rctf *subrect, Nurb **curnu,
+ float minmax_weights[2], const float rad_fac, bool stitch, const bool add_start_point,
+ const bool add_end_point, tGpTimingData *gtd)
+{
+ bGPDspoint *pt;
+ Nurb *nu = (curnu) ? *curnu : NULL;
+ BPoint *bp, *prev_bp = NULL;
+ const bool do_gtd = (gtd->mode != GP_STROKECONVERT_TIMING_NONE);
+ const int add_start_end_points = (add_start_point ? 1 : 0) + (add_end_point ? 1 : 0);
+ int i, old_nbp = 0;
+
+ /* create new 'nurb' or extend current one within the curve */
+ if (nu) {
+ old_nbp = nu->pntsu;
+
+ /* If stitch, the first point of this stroke is already present in current nu.
+ * Else, we have to add two additional points to make the zero-radius link between strokes.
+ */
+ BKE_nurb_points_add(nu, gps->totpoints + (stitch ? -1 : 2) + add_start_end_points);
+ }
+ else {
+ nu = (Nurb *)MEM_callocN(sizeof(Nurb), "gpstroke_to_path(nurb)");
+
+ nu->pntsu = gps->totpoints + add_start_end_points;
+ nu->pntsv = 1;
+ nu->orderu = 2; /* point-to-point! */
+ nu->type = CU_NURBS;
+ nu->flagu = CU_NURB_ENDPOINT;
+ nu->resolu = cu->resolu;
+ nu->resolv = cu->resolv;
+ nu->knotsu = NULL;
+
+ nu->bp = (BPoint *)MEM_callocN(sizeof(BPoint) * nu->pntsu, "bpoints");
+
+ stitch = false; /* Security! */
+ }
+
+ if (do_gtd) {
+ gp_timing_data_set_nbr(gtd, nu->pntsu);
+ }
+
+ /* If needed, make the link between both strokes with two zero-radius additional points */
+ /* About "zero-radius" point interpolations:
+ * - If we have at least two points in current curve (most common case), we linearly extrapolate
+ * the last segment to get the first point (p1) position and timing.
+ * - If we do not have those (quite odd, but may happen), we linearly interpolate the last point
+ * with the first point of the current stroke.
+ * The same goes for the second point, first segment of the current stroke is "negatively" extrapolated
+ * if it exists, else (if the stroke is a single point), linear interpolation with last curve point...
+ */
+ if (curnu && !stitch && old_nbp) {
+ float p1[3], p2[3], p[3], next_p[3];
+ float dt1 = 0.0f, dt2 = 0.0f;
+
+ BLI_assert(gps->prev != NULL);
+
+ prev_bp = NULL;
+ if ((old_nbp > 1) && (gps->prev->totpoints > 1)) {
+ /* Only use last curve segment if previous stroke was not a single-point one! */
+ prev_bp = &nu->bp[old_nbp - 2];
+ }
+ bp = &nu->bp[old_nbp - 1];
+
+ /* First point */
+ gp_strokepoint_convertcoords(C, gps, gps->points, p, subrect);
+ if (prev_bp) {
+ interp_v3_v3v3(p1, bp->vec, prev_bp->vec, -GAP_DFAC);
+ if (do_gtd) {
+ const int idx = gps->prev->totpoints - 1;
+ dt1 = interpf(gps->prev->points[idx - 1].time, gps->prev->points[idx].time, -GAP_DFAC);
+ }
+ }
+ else {
+ interp_v3_v3v3(p1, bp->vec, p, GAP_DFAC);
+ if (do_gtd) {
+ dt1 = interpf(gps->inittime - gps->prev->inittime, 0.0f, GAP_DFAC);
+ }
+ }
+ bp++;
+ gp_stroke_to_path_add_point(gtd, bp, p1, (bp - 1)->vec, do_gtd, gps->prev->inittime, dt1,
+ 0.0f, rad_fac, minmax_weights);
+
+ /* Second point */
+ /* Note dt2 is always negative, which marks the gap. */
+ if (gps->totpoints > 1) {
+ gp_strokepoint_convertcoords(C, gps, gps->points + 1, next_p, subrect);
+ interp_v3_v3v3(p2, p, next_p, -GAP_DFAC);
+ if (do_gtd) {
+ dt2 = interpf(gps->points[1].time, gps->points[0].time, -GAP_DFAC);
+ }
+ }
+ else {
+ interp_v3_v3v3(p2, p, bp->vec, GAP_DFAC);
+ if (do_gtd) {
+ dt2 = interpf(gps->prev->inittime - gps->inittime, 0.0f, GAP_DFAC);
+ }
+ }
+ bp++;
+ gp_stroke_to_path_add_point(gtd, bp, p2, p1, do_gtd, gps->inittime, dt2, 0.0f, rad_fac, minmax_weights);
+
+ old_nbp += 2;
+ }
+ else if (add_start_point) {
+ float p[3], next_p[3];
+ float dt = 0.0f;
+
+ gp_strokepoint_convertcoords(C, gps, gps->points, p, subrect);
+ if (gps->totpoints > 1) {
+ gp_strokepoint_convertcoords(C, gps, gps->points + 1, next_p, subrect);
+ interp_v3_v3v3(p, p, next_p, -GAP_DFAC);
+ if (do_gtd) {
+ dt = interpf(gps->points[1].time, gps->points[0].time, -GAP_DFAC);
+ }
+ }
+ else {
+ p[0] -= GAP_DFAC; /* Rather arbitrary... */
+ dt = -GAP_DFAC; /* Rather arbitrary too! */
+ }
+ bp = &nu->bp[old_nbp];
+ /* Note we can't give anything else than 0.0 as time here, since a negative one (which would be expected value)
+ * would not work (it would be *before* gtd->inittime, which is not supported currently).
+ */
+ gp_stroke_to_path_add_point(gtd, bp, p, p, do_gtd, gps->inittime, dt, 0.0f, rad_fac, minmax_weights);
+
+ old_nbp++;
+ }
+
+ if (old_nbp) {
+ prev_bp = &nu->bp[old_nbp - 1];
+ }
+
+ /* add points */
+ for (i = (stitch) ? 1 : 0, pt = &gps->points[(stitch) ? 1 : 0], bp = &nu->bp[old_nbp];
+ i < gps->totpoints;
+ i++, pt++, bp++)
+ {
+ float p[3];
+ float width = pt->pressure * gpl->thickness * WIDTH_CORR_FAC;
+
+ /* get coordinates to add at */
+ gp_strokepoint_convertcoords(C, gps, pt, p, subrect);
+
+ gp_stroke_to_path_add_point(gtd, bp, p, (prev_bp) ? prev_bp->vec : p, do_gtd, gps->inittime, pt->time,
+ width, rad_fac, minmax_weights);
+
+ prev_bp = bp;
+ }
+
+ if (add_end_point) {
+ float p[3];
+ float dt = 0.0f;
+
+ if (gps->totpoints > 1) {
+ interp_v3_v3v3(p, prev_bp->vec, (prev_bp - 1)->vec, -GAP_DFAC);
+ if (do_gtd) {
+ const int idx = gps->totpoints - 1;
+ dt = interpf(gps->points[idx - 1].time, gps->points[idx].time, -GAP_DFAC);
+ }
+ }
+ else {
+ copy_v3_v3(p, prev_bp->vec);
+ p[0] += GAP_DFAC; /* Rather arbitrary... */
+ dt = GAP_DFAC; /* Rather arbitrary too! */
+ }
+ /* Note bp has already been incremented in main loop above, so it points to the right place. */
+ gp_stroke_to_path_add_point(gtd, bp, p, prev_bp->vec, do_gtd, gps->inittime, dt, 0.0f, rad_fac, minmax_weights);
+ }
+
+ /* add nurb to curve */
+ if (!curnu || !*curnu) {
+ BLI_addtail(&cu->nurb, nu);
+ }
+ if (curnu) {
+ *curnu = nu;
+ }
+
+ BKE_nurb_knot_calc_u(nu);
+}
+
+/* convert stroke to 3d bezier */
+
+/* helper */
+static void gp_stroke_to_bezier_add_point(tGpTimingData *gtd, BezTriple *bezt,
+ const float p[3], const float h1[3], const float h2[3], const float prev_p[3],
+ const bool do_gtd, const double inittime, const float time,
+ const float width, const float rad_fac, float minmax_weights[2])
+{
+ copy_v3_v3(bezt->vec[0], h1);
+ copy_v3_v3(bezt->vec[1], p);
+ copy_v3_v3(bezt->vec[2], h2);
+
+ /* set settings */
+ bezt->h1 = bezt->h2 = HD_FREE;
+ bezt->f1 = bezt->f2 = bezt->f3 = SELECT;
+ bezt->radius = width * rad_fac;
+ bezt->weight = width;
+ CLAMP(bezt->weight, 0.0f, 1.0f);
+ if (bezt->weight < minmax_weights[0]) {
+ minmax_weights[0] = bezt->weight;
+ }
+ else if (bezt->weight > minmax_weights[1]) {
+ minmax_weights[1] = bezt->weight;
+ }
+
+ /* Update timing data */
+ if (do_gtd) {
+ gp_timing_data_add_point(gtd, inittime, time, len_v3v3(prev_p, p));
+ }
+}
+
+static void gp_stroke_to_bezier(bContext *C, bGPDlayer *gpl, bGPDstroke *gps, Curve *cu, rctf *subrect, Nurb **curnu,
+ float minmax_weights[2], const float rad_fac, bool stitch, const bool add_start_point,
+ const bool add_end_point, tGpTimingData *gtd)
+{
+ bGPDspoint *pt;
+ Nurb *nu = (curnu) ? *curnu : NULL;
+ BezTriple *bezt, *prev_bezt = NULL;
+ int i, tot, old_nbezt = 0;
+ const int add_start_end_points = (add_start_point ? 1 : 0) + (add_end_point ? 1 : 0);
+ float p3d_cur[3], p3d_prev[3], p3d_next[3], h1[3], h2[3];
+ const bool do_gtd = (gtd->mode != GP_STROKECONVERT_TIMING_NONE);
+
+ /* create new 'nurb' or extend current one within the curve */
+ if (nu) {
+ old_nbezt = nu->pntsu;
+ /* If we do stitch, first point of current stroke is assumed the same as last point of previous stroke,
+ * so no need to add it.
+ * If no stitch, we want to add two additional points to make a "zero-radius" link between both strokes.
+ */
+ BKE_nurb_bezierPoints_add(nu, gps->totpoints + ((stitch) ? -1 : 2) + add_start_end_points);
+ }
+ else {
+ nu = (Nurb *)MEM_callocN(sizeof(Nurb), "gpstroke_to_bezier(nurb)");
+
+ nu->pntsu = gps->totpoints + add_start_end_points;
+ nu->resolu = 12;
+ nu->resolv = 12;
+ nu->type = CU_BEZIER;
+ nu->bezt = (BezTriple *)MEM_callocN(sizeof(BezTriple) * nu->pntsu, "bezts");
+
+ stitch = false; /* Security! */
+ }
+
+ if (do_gtd) {
+ gp_timing_data_set_nbr(gtd, nu->pntsu);
+ }
+
+ tot = gps->totpoints;
+
+ /* get initial coordinates */
+ pt = gps->points;
+ if (tot) {
+ gp_strokepoint_convertcoords(C, gps, pt, (stitch) ? p3d_prev : p3d_cur, subrect);
+ if (tot > 1) {
+ gp_strokepoint_convertcoords(C, gps, pt + 1, (stitch) ? p3d_cur : p3d_next, subrect);
+ }
+ if (stitch && tot > 2) {
+ gp_strokepoint_convertcoords(C, gps, pt + 2, p3d_next, subrect);
+ }
+ }
+
+ /* If needed, make the link between both strokes with two zero-radius additional points */
+ if (curnu && old_nbezt) {
+ BLI_assert(gps->prev != NULL);
+
+ /* Update last point's second handle */
+ if (stitch) {
+ bezt = &nu->bezt[old_nbezt - 1];
+ interp_v3_v3v3(h2, bezt->vec[1], p3d_cur, BEZT_HANDLE_FAC);
+ copy_v3_v3(bezt->vec[2], h2);
+ pt++;
+ }
+
+ /* Create "link points" */
+ /* About "zero-radius" point interpolations:
+ * - If we have at least two points in current curve (most common case), we linearly extrapolate
+ * the last segment to get the first point (p1) position and timing.
+ * - If we do not have those (quite odd, but may happen), we linearly interpolate the last point
+ * with the first point of the current stroke.
+ * The same goes for the second point, first segment of the current stroke is "negatively" extrapolated
+ * if it exists, else (if the stroke is a single point), linear interpolation with last curve point...
+ */
+ else {
+ float p1[3], p2[3];
+ float dt1 = 0.0f, dt2 = 0.0f;
+
+ prev_bezt = NULL;
+ if ((old_nbezt > 1) && (gps->prev->totpoints > 1)) {
+ /* Only use last curve segment if previous stroke was not a single-point one! */
+ prev_bezt = &nu->bezt[old_nbezt - 2];
+ }
+ bezt = &nu->bezt[old_nbezt - 1];
+
+ /* First point */
+ if (prev_bezt) {
+ interp_v3_v3v3(p1, prev_bezt->vec[1], bezt->vec[1], 1.0f + GAP_DFAC);
+ if (do_gtd) {
+ const int idx = gps->prev->totpoints - 1;
+ dt1 = interpf(gps->prev->points[idx - 1].time, gps->prev->points[idx].time, -GAP_DFAC);
+ }
+ }
+ else {
+ interp_v3_v3v3(p1, bezt->vec[1], p3d_cur, GAP_DFAC);
+ if (do_gtd) {
+ dt1 = interpf(gps->inittime - gps->prev->inittime, 0.0f, GAP_DFAC);
+ }
+ }
+
+ /* Second point */
+ /* Note dt2 is always negative, which marks the gap. */
+ if (tot > 1) {
+ interp_v3_v3v3(p2, p3d_cur, p3d_next, -GAP_DFAC);
+ if (do_gtd) {
+ dt2 = interpf(gps->points[1].time, gps->points[0].time, -GAP_DFAC);
+ }
+ }
+ else {
+ interp_v3_v3v3(p2, p3d_cur, bezt->vec[1], GAP_DFAC);
+ if (do_gtd) {
+ dt2 = interpf(gps->prev->inittime - gps->inittime, 0.0f, GAP_DFAC);
+ }
+ }
+
+ /* Second handle of last point of previous stroke. */
+ interp_v3_v3v3(h2, bezt->vec[1], p1, BEZT_HANDLE_FAC);
+ copy_v3_v3(bezt->vec[2], h2);
+
+ /* First point */
+ interp_v3_v3v3(h1, p1, bezt->vec[1], BEZT_HANDLE_FAC);
+ interp_v3_v3v3(h2, p1, p2, BEZT_HANDLE_FAC);
+ bezt++;
+ gp_stroke_to_bezier_add_point(gtd, bezt, p1, h1, h2, (bezt - 1)->vec[1], do_gtd, gps->prev->inittime, dt1,
+ 0.0f, rad_fac, minmax_weights);
+
+ /* Second point */
+ interp_v3_v3v3(h1, p2, p1, BEZT_HANDLE_FAC);
+ interp_v3_v3v3(h2, p2, p3d_cur, BEZT_HANDLE_FAC);
+ bezt++;
+ gp_stroke_to_bezier_add_point(gtd, bezt, p2, h1, h2, p1, do_gtd, gps->inittime, dt2,
+ 0.0f, rad_fac, minmax_weights);
+
+ old_nbezt += 2;
+ copy_v3_v3(p3d_prev, p2);
+ }
+ }
+ else if (add_start_point) {
+ float p[3];
+ float dt = 0.0f;
+
+ if (gps->totpoints > 1) {
+ interp_v3_v3v3(p, p3d_cur, p3d_next, -GAP_DFAC);
+ if (do_gtd) {
+ dt = interpf(gps->points[1].time, gps->points[0].time, -GAP_DFAC);
+ }
+ }
+ else {
+ copy_v3_v3(p, p3d_cur);
+ p[0] -= GAP_DFAC; /* Rather arbitrary... */
+ dt = -GAP_DFAC; /* Rather arbitrary too! */
+ }
+ interp_v3_v3v3(h1, p, p3d_cur, -BEZT_HANDLE_FAC);
+ interp_v3_v3v3(h2, p, p3d_cur, BEZT_HANDLE_FAC);
+ bezt = &nu->bezt[old_nbezt];
+ gp_stroke_to_bezier_add_point(gtd, bezt, p, h1, h2, p, do_gtd, gps->inittime, dt,
+ 0.0f, rad_fac, minmax_weights);
+
+ old_nbezt++;
+ copy_v3_v3(p3d_prev, p);
+ }
+
+ if (old_nbezt) {
+ prev_bezt = &nu->bezt[old_nbezt - 1];
+ }
+
+ /* add points */
+ for (i = stitch ? 1 : 0, bezt = &nu->bezt[old_nbezt]; i < tot; i++, pt++, bezt++) {
+ float width = pt->pressure * gpl->thickness * WIDTH_CORR_FAC;
+
+ if (i || old_nbezt) {
+ interp_v3_v3v3(h1, p3d_cur, p3d_prev, BEZT_HANDLE_FAC);
+ }
+ else {
+ interp_v3_v3v3(h1, p3d_cur, p3d_next, -BEZT_HANDLE_FAC);
+ }
+
+ if (i < tot - 1) {
+ interp_v3_v3v3(h2, p3d_cur, p3d_next, BEZT_HANDLE_FAC);
+ }
+ else {
+ interp_v3_v3v3(h2, p3d_cur, p3d_prev, -BEZT_HANDLE_FAC);
+ }
+
+ gp_stroke_to_bezier_add_point(gtd, bezt, p3d_cur, h1, h2, prev_bezt ? prev_bezt->vec[1] : p3d_cur,
+ do_gtd, gps->inittime, pt->time, width, rad_fac, minmax_weights);
+
+ /* shift coord vects */
+ copy_v3_v3(p3d_prev, p3d_cur);
+ copy_v3_v3(p3d_cur, p3d_next);
+
+ if (i + 2 < tot) {
+ gp_strokepoint_convertcoords(C, gps, pt + 2, p3d_next, subrect);
+ }
+
+ prev_bezt = bezt;
+ }
+
+ if (add_end_point) {
+ float p[3];
+ float dt = 0.0f;
+
+ if (gps->totpoints > 1) {
+ interp_v3_v3v3(p, prev_bezt->vec[1], (prev_bezt - 1)->vec[1], -GAP_DFAC);
+ if (do_gtd) {
+ const int idx = gps->totpoints - 1;
+ dt = interpf(gps->points[idx - 1].time, gps->points[idx].time, -GAP_DFAC);
+ }
+ }
+ else {
+ copy_v3_v3(p, prev_bezt->vec[1]);
+ p[0] += GAP_DFAC; /* Rather arbitrary... */
+ dt = GAP_DFAC; /* Rather arbitrary too! */
+ }
+
+ /* Second handle of last point of this stroke. */
+ interp_v3_v3v3(h2, prev_bezt->vec[1], p, BEZT_HANDLE_FAC);
+ copy_v3_v3(prev_bezt->vec[2], h2);
+
+ /* The end point */
+ interp_v3_v3v3(h1, p, prev_bezt->vec[1], BEZT_HANDLE_FAC);
+ interp_v3_v3v3(h2, p, prev_bezt->vec[1], -BEZT_HANDLE_FAC);
+ /* Note bezt has already been incremented in main loop above, so it points to the right place. */
+ gp_stroke_to_bezier_add_point(gtd, bezt, p, h1, h2, prev_bezt->vec[1], do_gtd, gps->inittime, dt,
+ 0.0f, rad_fac, minmax_weights);
+ }
+
+ /* must calculate handles or else we crash */
+ BKE_nurb_handles_calc(nu);
+
+ if (!curnu || !*curnu) {
+ BLI_addtail(&cu->nurb, nu);
+ }
+ if (curnu) {
+ *curnu = nu;
+ }
+}
+
+#undef GAP_DFAC
+#undef WIDTH_CORR_FAC
+#undef BEZT_HANDLE_FAC
+
+static void gp_stroke_finalize_curve_endpoints(Curve *cu)
+{
+ /* start */
+ Nurb *nu = cu->nurb.first;
+ int i = 0;
+ if (nu->bezt) {
+ BezTriple *bezt = nu->bezt;
+ if (bezt) {
+ bezt[i].weight = bezt[i].radius = 0.0f;
+ }
+ }
+ else if (nu->bp) {
+ BPoint *bp = nu->bp;
+ if (bp) {
+ bp[i].weight = bp[i].radius = 0.0f;
+ }
+ }
+
+ /* end */
+ nu = cu->nurb.last;
+ i = nu->pntsu - 1;
+ if (nu->bezt) {
+ BezTriple *bezt = nu->bezt;
+ if (bezt) {
+ bezt[i].weight = bezt[i].radius = 0.0f;
+ }
+ }
+ else if (nu->bp) {
+ BPoint *bp = nu->bp;
+ if (bp) {
+ bp[i].weight = bp[i].radius = 0.0f;
+ }
+ }
+}
+
+static void gp_stroke_norm_curve_weights(Curve *cu, const float minmax_weights[2])
+{
+ Nurb *nu;
+ const float delta = minmax_weights[0];
+ float fac;
+ int i;
+
+ /* when delta == minmax_weights[0] == minmax_weights[1], we get div by zero [#35686] */
+ if (IS_EQF(delta, minmax_weights[1]))
+ fac = 1.0f;
+ else
+ fac = 1.0f / (minmax_weights[1] - delta);
+
+ for (nu = cu->nurb.first; nu; nu = nu->next) {
+ if (nu->bezt) {
+ BezTriple *bezt = nu->bezt;
+ for (i = 0; i < nu->pntsu; i++, bezt++) {
+ bezt->weight = (bezt->weight - delta) * fac;
+ }
+ }
+ else if (nu->bp) {
+ BPoint *bp = nu->bp;
+ for (i = 0; i < nu->pntsu; i++, bp++) {
+ bp->weight = (bp->weight - delta) * fac;
+ }
+ }
+ }
+}
+
+static int gp_camera_view_subrect(bContext *C, rctf *subrect)
+{
+ View3D *v3d = CTX_wm_view3d(C);
+ ARegion *ar = CTX_wm_region(C);
+
+ if (v3d) {
+ RegionView3D *rv3d = ar->regiondata;
+
+ /* for camera view set the subrect */
+ if (rv3d->persp == RV3D_CAMOB) {
+ Scene *scene = CTX_data_scene(C);
+ ED_view3d_calc_camera_border(scene, ar, v3d, rv3d, subrect, true); /* no shift */
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+/* convert a given grease-pencil layer to a 3d-curve representation (using current view if appropriate) */
+static void gp_layer_to_curve(bContext *C, ReportList *reports, bGPdata *gpd, bGPDlayer *gpl, const int mode,
+ const bool norm_weights, const float rad_fac, const bool link_strokes, tGpTimingData *gtd)
+{
+ struct Main *bmain = CTX_data_main(C);
+ View3D *v3d = CTX_wm_view3d(C); /* may be NULL */
+ Scene *scene = CTX_data_scene(C);
+ bGPDframe *gpf = gpencil_layer_getframe(gpl, CFRA, 0);
+ bGPDstroke *gps, *prev_gps = NULL;
+ Object *ob;
+ Curve *cu;
+ Nurb *nu = NULL;
+ Base *base_orig = BASACT, *base_new = NULL;
+ float minmax_weights[2] = {1.0f, 0.0f};
+
+ /* camera framing */
+ rctf subrect, *subrect_ptr = NULL;
+
+ /* error checking */
+ if (ELEM(NULL, gpd, gpl, gpf))
+ return;
+
+ /* only convert if there are any strokes on this layer's frame to convert */
+ if (BLI_listbase_is_empty(&gpf->strokes))
+ return;
+
+ /* initialize camera framing */
+ if (gp_camera_view_subrect(C, &subrect)) {
+ subrect_ptr = &subrect;
+ }
+
+ /* init the curve object (remove rotation and get curve data from it)
+ * - must clear transforms set on object, as those skew our results
+ */
+ ob = BKE_object_add_only_object(bmain, OB_CURVE, gpl->info);
+ cu = ob->data = BKE_curve_add(bmain, gpl->info, OB_CURVE);
+ base_new = BKE_scene_base_add(scene, ob);
+
+ cu->flag |= CU_3D;
+
+ gtd->inittime = ((bGPDstroke *)gpf->strokes.first)->inittime;
+
+ /* add points to curve */
+ for (gps = gpf->strokes.first; gps; gps = gps->next) {
+ const bool add_start_point = (link_strokes && !(prev_gps));
+ const bool add_end_point = (link_strokes && !(gps->next));
+
+ /* Detect new strokes created because of GP_STROKE_BUFFER_MAX reached, and stitch them to previous one. */
+ bool stitch = false;
+ if (prev_gps) {
+ bGPDspoint *pt1 = &prev_gps->points[prev_gps->totpoints - 1];
+ bGPDspoint *pt2 = &gps->points[0];
+
+ if ((pt1->x == pt2->x) && (pt1->y == pt2->y)) {
+ stitch = true;
+ }
+ }
+
+ /* Decide whether we connect this stroke to previous one */
+ if (!(stitch || link_strokes)) {
+ nu = NULL;
+ }
+
+ switch (mode) {
+ case GP_STROKECONVERT_PATH:
+ gp_stroke_to_path(C, gpl, gps, cu, subrect_ptr, &nu, minmax_weights, rad_fac, stitch,
+ add_start_point, add_end_point, gtd);
+ break;
+ case GP_STROKECONVERT_CURVE:
+ case GP_STROKECONVERT_POLY: /* convert after */
+ gp_stroke_to_bezier(C, gpl, gps, cu, subrect_ptr, &nu, minmax_weights, rad_fac, stitch,
+ add_start_point, add_end_point, gtd);
+ break;
+ default:
+ BLI_assert(!"invalid mode");
+ break;
+ }
+ prev_gps = gps;
+ }
+
+ /* If link_strokes, be sure first and last points have a zero weight/size! */
+ if (link_strokes) {
+ gp_stroke_finalize_curve_endpoints(cu);
+ }
+
+ /* Update curve's weights, if needed */
+ if (norm_weights && ((minmax_weights[0] > 0.0f) || (minmax_weights[1] < 1.0f))) {
+ gp_stroke_norm_curve_weights(cu, minmax_weights);
+ }
+
+ /* Create the path animation, if needed */
+ gp_stroke_path_animation(C, reports, cu, gtd);
+
+ if (mode == GP_STROKECONVERT_POLY) {
+ for (nu = cu->nurb.first; nu; nu = nu->next) {
+ BKE_nurb_type_convert(nu, CU_POLY, false);
+ }
+ }
+
+ /* set the layer and select */
+ base_new->lay = ob->lay = base_orig ? base_orig->lay : BKE_screen_view3d_layer_active(v3d, scene);
+ base_new->flag = ob->flag = base_new->flag | SELECT;
+}
+
+/* --- */
+
+/* Check a GP layer has valid timing data! Else, most timing options are hidden in the operator.
+ * op may be NULL.
+ */
+static bool gp_convert_check_has_valid_timing(bContext *C, bGPDlayer *gpl, wmOperator *op)
+{
+ Scene *scene = CTX_data_scene(C);
+ bGPDframe *gpf = NULL;
+ bGPDstroke *gps = NULL;
+ bGPDspoint *pt;
+ double base_time, cur_time, prev_time = -1.0;
+ int i;
+ bool valid = true;
+
+ if (!gpl || !(gpf = gpencil_layer_getframe(gpl, CFRA, 0)) || !(gps = gpf->strokes.first))
+ return false;
+
+ do {
+ base_time = cur_time = gps->inittime;
+ if (cur_time <= prev_time) {
+ valid = false;
+ break;
+ }
+
+ prev_time = cur_time;
+ for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
+ cur_time = base_time + (double)pt->time;
+ /* First point of a stroke should have the same time as stroke's inittime,
+ * so it's the only case where equality is allowed!
+ */
+ if ((i && cur_time <= prev_time) || (cur_time < prev_time)) {
+ valid = false;
+ break;
+ }
+ prev_time = cur_time;
+ }
+
+ if (!valid) {
+ break;
+ }
+ } while ((gps = gps->next));
+
+ if (op) {
+ RNA_boolean_set(op->ptr, "use_timing_data", valid);
+ }
+ return valid;
+}
+
+/* Check end_frame is always > start frame! */
+static void gp_convert_set_end_frame(struct Main *UNUSED(main), struct Scene *UNUSED(scene), struct PointerRNA *ptr)
+{
+ int start_frame = RNA_int_get(ptr, "start_frame");
+ int end_frame = RNA_int_get(ptr, "end_frame");
+
+ if (end_frame <= start_frame) {
+ RNA_int_set(ptr, "end_frame", start_frame + 1);
+ }
+}
+
+static int gp_convert_poll(bContext *C)
+{
+ bGPdata *gpd = ED_gpencil_data_get_active(C);
+ bGPDlayer *gpl = NULL;
+ bGPDframe *gpf = NULL;
+ ScrArea *sa = CTX_wm_area(C);
+ Scene *scene = CTX_data_scene(C);
+
+ /* only if the current view is 3D View, if there's valid data (i.e. at least one stroke!),
+ * and if we are not in edit mode!
+ */
+ return ((sa && sa->spacetype == SPACE_VIEW3D) &&
+ (gpl = gpencil_layer_getactive(gpd)) &&
+ (gpf = gpencil_layer_getframe(gpl, CFRA, 0)) &&
+ (gpf->strokes.first) &&
+ (scene->obedit == NULL));
+}
+
+static int gp_convert_layer_exec(bContext *C, wmOperator *op)
+{
+ PropertyRNA *prop = RNA_struct_find_property(op->ptr, "use_timing_data");
+ bGPdata *gpd = ED_gpencil_data_get_active(C);
+ bGPDlayer *gpl = gpencil_layer_getactive(gpd);
+ Scene *scene = CTX_data_scene(C);
+ const int mode = RNA_enum_get(op->ptr, "type");
+ const bool norm_weights = RNA_boolean_get(op->ptr, "use_normalize_weights");
+ const float rad_fac = RNA_float_get(op->ptr, "radius_multiplier");
+ const bool link_strokes = RNA_boolean_get(op->ptr, "use_link_strokes");
+ bool valid_timing;
+ tGpTimingData gtd;
+
+ /* check if there's data to work with */
+ if (gpd == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "No Grease Pencil data to work on");
+ return OPERATOR_CANCELLED;
+ }
+
+ if (!RNA_property_is_set(op->ptr, prop) && !gp_convert_check_has_valid_timing(C, gpl, op)) {
+ BKE_report(op->reports, RPT_WARNING,
+ "Current Grease Pencil strokes have no valid timing data, most timing options will be hidden!");
+ }
+ valid_timing = RNA_property_boolean_get(op->ptr, prop);
+
+ gtd.mode = RNA_enum_get(op->ptr, "timing_mode");
+ /* Check for illegal timing mode! */
+ if (!valid_timing && !ELEM(gtd.mode, GP_STROKECONVERT_TIMING_NONE, GP_STROKECONVERT_TIMING_LINEAR)) {
+ gtd.mode = GP_STROKECONVERT_TIMING_LINEAR;
+ RNA_enum_set(op->ptr, "timing_mode", gtd.mode);
+ }
+ if (!link_strokes) {
+ gtd.mode = GP_STROKECONVERT_TIMING_NONE;
+ }
+
+ /* grab all relevant settings */
+ gtd.frame_range = RNA_int_get(op->ptr, "frame_range");
+ gtd.start_frame = RNA_int_get(op->ptr, "start_frame");
+ gtd.realtime = valid_timing ? RNA_boolean_get(op->ptr, "use_realtime") : false;
+ gtd.end_frame = RNA_int_get(op->ptr, "end_frame");
+ gtd.gap_duration = RNA_float_get(op->ptr, "gap_duration");
+ gtd.gap_randomness = RNA_float_get(op->ptr, "gap_randomness");
+ gtd.gap_randomness = min_ff(gtd.gap_randomness, gtd.gap_duration);
+ gtd.seed = RNA_int_get(op->ptr, "seed");
+ gtd.num_points = gtd.cur_point = 0;
+ gtd.dists = gtd.times = NULL;
+ gtd.tot_dist = gtd.tot_time = gtd.gap_tot_time = 0.0f;
+ gtd.inittime = 0.0;
+ gtd.offset_time = 0.0f;
+
+ /* perform conversion */
+ gp_layer_to_curve(C, op->reports, gpd, gpl, mode, norm_weights, rad_fac, link_strokes, &gtd);
+
+ /* free temp memory */
+ if (gtd.dists) {
+ MEM_freeN(gtd.dists);
+ gtd.dists = NULL;
+ }
+ if (gtd.times) {
+ MEM_freeN(gtd.times);
+ gtd.times = NULL;
+ }
+
+ /* notifiers */
+ WM_event_add_notifier(C, NC_OBJECT | NA_ADDED, NULL);
+ WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene);
+
+ /* done */
+ return OPERATOR_FINISHED;
+}
+
+static bool gp_convert_draw_check_prop(PointerRNA *ptr, PropertyRNA *prop)
+{
+ const char *prop_id = RNA_property_identifier(prop);
+ const bool link_strokes = RNA_boolean_get(ptr, "use_link_strokes");
+ int timing_mode = RNA_enum_get(ptr, "timing_mode");
+ bool realtime = RNA_boolean_get(ptr, "use_realtime");
+ float gap_duration = RNA_float_get(ptr, "gap_duration");
+ float gap_randomness = RNA_float_get(ptr, "gap_randomness");
+ const bool valid_timing = RNA_boolean_get(ptr, "use_timing_data");
+
+ /* Always show those props */
+ if (STREQ(prop_id, "type") ||
+ STREQ(prop_id, "use_normalize_weights") ||
+ STREQ(prop_id, "radius_multiplier") ||
+ STREQ(prop_id, "use_link_strokes"))
+ {
+ return true;
+ }
+
+ /* Never show this prop */
+ if (STREQ(prop_id, "use_timing_data"))
+ return false;
+
+ if (link_strokes) {
+ /* Only show when link_stroke is true */
+ if (STREQ(prop_id, "timing_mode"))
+ return true;
+
+ if (timing_mode != GP_STROKECONVERT_TIMING_NONE) {
+ /* Only show when link_stroke is true and stroke timing is enabled */
+ if (STREQ(prop_id, "frame_range") ||
+ STREQ(prop_id, "start_frame"))
+ {
+ return true;
+ }
+
+ /* Only show if we have valid timing data! */
+ if (valid_timing && STREQ(prop_id, "use_realtime"))
+ return true;
+
+ /* Only show if realtime or valid_timing is false! */
+ if ((!realtime || !valid_timing) && STREQ(prop_id, "end_frame"))
+ return true;
+
+ if (valid_timing && timing_mode == GP_STROKECONVERT_TIMING_CUSTOMGAP) {
+ /* Only show for custom gaps! */
+ if (STREQ(prop_id, "gap_duration"))
+ return true;
+
+ /* Only show randomness for non-null custom gaps! */
+ if (STREQ(prop_id, "gap_randomness") && (gap_duration > 0.0f))
+ return true;
+
+ /* Only show seed for randomize action! */
+ if (STREQ(prop_id, "seed") && (gap_duration > 0.0f) && (gap_randomness > 0.0f))
+ return true;
+ }
+ }
+ }
+
+ /* Else, hidden! */
+ return false;
+}
+
+static void gp_convert_ui(bContext *C, wmOperator *op)
+{
+ uiLayout *layout = op->layout;
+ wmWindowManager *wm = CTX_wm_manager(C);
+ PointerRNA ptr;
+
+ RNA_pointer_create(&wm->id, op->type->srna, op->properties, &ptr);
+
+ /* Main auto-draw call */
+ uiDefAutoButsRNA(layout, &ptr, gp_convert_draw_check_prop, '\0');
+}
+
+void GPENCIL_OT_convert(wmOperatorType *ot)
+{
+ PropertyRNA *prop;
+
+ /* identifiers */
+ ot->name = "Convert Grease Pencil";
+ ot->idname = "GPENCIL_OT_convert";
+ ot->description = "Convert the active Grease Pencil layer to a new Curve Object";
+
+ /* callbacks */
+ ot->invoke = WM_menu_invoke;
+ ot->exec = gp_convert_layer_exec;
+ ot->poll = gp_convert_poll;
+ ot->ui = gp_convert_ui;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ ot->prop = RNA_def_enum(ot->srna, "type", prop_gpencil_convertmodes, 0, "Type", "Which type of curve to convert to");
+
+ RNA_def_boolean(ot->srna, "use_normalize_weights", true, "Normalize Weight",
+ "Normalize weight (set from stroke width)");
+ RNA_def_float(ot->srna, "radius_multiplier", 1.0f, 0.0f, 1000.0f, "Radius Fac",
+ "Multiplier for the points' radii (set from stroke width)", 0.0f, 10.0f);
+ RNA_def_boolean(ot->srna, "use_link_strokes", true, "Link Strokes",
+ "Whether to link strokes with zero-radius sections of curves");
+
+ prop = RNA_def_enum(ot->srna, "timing_mode", prop_gpencil_convert_timingmodes, GP_STROKECONVERT_TIMING_FULL,
+ "Timing Mode", "How to use timing data stored in strokes");
+ RNA_def_enum_funcs(prop, rna_GPConvert_mode_items);
+
+ RNA_def_int(ot->srna, "frame_range", 100, 1, 10000, "Frame Range",
+ "The duration of evaluation of the path control curve", 1, 1000);
+ RNA_def_int(ot->srna, "start_frame", 1, 1, 100000, "Start Frame",
+ "The start frame of the path control curve", 1, 100000);
+ RNA_def_boolean(ot->srna, "use_realtime", false, "Realtime",
+ "Whether the path control curve reproduces the drawing in realtime, starting from Start Frame");
+ prop = RNA_def_int(ot->srna, "end_frame", 250, 1, 100000, "End Frame",
+ "The end frame of the path control curve (if Realtime is not set)", 1, 100000);
+ RNA_def_property_update_runtime(prop, gp_convert_set_end_frame);
+
+ RNA_def_float(ot->srna, "gap_duration", 0.0f, 0.0f, 10000.0f, "Gap Duration",
+ "Custom Gap mode: (Average) length of gaps, in frames "
+ "(Note: Realtime value, will be scaled if Realtime is not set)", 0.0f, 1000.0f);
+ RNA_def_float(ot->srna, "gap_randomness", 0.0f, 0.0f, 10000.0f, "Gap Randomness",
+ "Custom Gap mode: Number of frames that gap lengths can vary", 0.0f, 1000.0f);
+ RNA_def_int(ot->srna, "seed", 0, 0, 1000, "Random Seed",
+ "Custom Gap mode: Random generator seed", 0, 100);
+
+ /* Note: Internal use, this one will always be hidden by UI code... */
+ prop = RNA_def_boolean(ot->srna, "use_timing_data", false, "Has Valid Timing",
+ "Whether the converted Grease Pencil layer has valid timing data (internal use)");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+}
+
+/* ************************************************ */
diff --git a/source/blender/editors/gpencil/gpencil_data.c b/source/blender/editors/gpencil/gpencil_data.c
new file mode 100644
index 00000000000..de966776645
--- /dev/null
+++ b/source/blender/editors/gpencil/gpencil_data.c
@@ -0,0 +1,447 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2008, Blender Foundation, Joshua Leung
+ * This is a new part of Blender
+ *
+ * Contributor(s): Joshua Leung
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ *
+ * Operators for dealing with GP datablocks and layers
+ */
+
+/** \file blender/editors/gpencil/gpencil_data.c
+ * \ingroup edgpencil
+ */
+
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <math.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_utildefines.h"
+
+#include "BLT_translation.h"
+
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_space_types.h"
+#include "DNA_view3d_types.h"
+#include "DNA_gpencil_types.h"
+
+#include "BKE_context.h"
+#include "BKE_global.h"
+#include "BKE_gpencil.h"
+#include "BKE_library.h"
+#include "BKE_object.h"
+#include "BKE_report.h"
+#include "BKE_scene.h"
+#include "BKE_screen.h"
+
+#include "UI_interface.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+
+#include "ED_gpencil.h"
+
+#include "gpencil_intern.h"
+
+
+/* ************************************************ */
+/* Datablock Operators */
+
+/* ******************* Add New Data ************************ */
+
+/* add new datablock - wrapper around API */
+static int gp_data_add_exec(bContext *C, wmOperator *op)
+{
+ bGPdata **gpd_ptr = ED_gpencil_data_get_pointers(C, NULL);
+
+ if (gpd_ptr == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "Nowhere for grease pencil data to go");
+ return OPERATOR_CANCELLED;
+ }
+ else {
+ /* decrement user count and add new datablock */
+ bGPdata *gpd = (*gpd_ptr);
+
+ id_us_min(&gpd->id);
+ *gpd_ptr = gpencil_data_addnew(DATA_("GPencil"));
+ }
+
+ /* notifiers */
+ WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
+
+ return OPERATOR_FINISHED;
+}
+
+void GPENCIL_OT_data_add(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Grease Pencil Add New";
+ ot->idname = "GPENCIL_OT_data_add";
+ ot->description = "Add new Grease Pencil datablock";
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* callbacks */
+ ot->exec = gp_data_add_exec;
+ ot->poll = gp_add_poll;
+}
+
+/* ******************* Unlink Data ************************ */
+
+/* poll callback for adding data/layers - special */
+static int gp_data_unlink_poll(bContext *C)
+{
+ bGPdata **gpd_ptr = ED_gpencil_data_get_pointers(C, NULL);
+
+ /* if we have access to some active data, make sure there's a datablock before enabling this */
+ return (gpd_ptr && *gpd_ptr);
+}
+
+
+/* unlink datablock - wrapper around API */
+static int gp_data_unlink_exec(bContext *C, wmOperator *op)
+{
+ bGPdata **gpd_ptr = ED_gpencil_data_get_pointers(C, NULL);
+
+ if (gpd_ptr == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "Nowhere for grease pencil data to go");
+ return OPERATOR_CANCELLED;
+ }
+ else {
+ /* just unlink datablock now, decreasing its user count */
+ bGPdata *gpd = (*gpd_ptr);
+
+ id_us_min(&gpd->id);
+ *gpd_ptr = NULL;
+ }
+
+ /* notifiers */
+ WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
+
+ return OPERATOR_FINISHED;
+}
+
+void GPENCIL_OT_data_unlink(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Grease Pencil Unlink";
+ ot->idname = "GPENCIL_OT_data_unlink";
+ ot->description = "Unlink active Grease Pencil datablock";
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* callbacks */
+ ot->exec = gp_data_unlink_exec;
+ ot->poll = gp_data_unlink_poll;
+}
+
+
+/* ************************************************ */
+/* Layer Operators */
+
+/* ******************* Add New Layer ************************ */
+
+/* add new layer - wrapper around API */
+static int gp_layer_add_exec(bContext *C, wmOperator *op)
+{
+ bGPdata **gpd_ptr = ED_gpencil_data_get_pointers(C, NULL);
+
+ /* if there's no existing Grease-Pencil data there, add some */
+ if (gpd_ptr == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "Nowhere for grease pencil data to go");
+ return OPERATOR_CANCELLED;
+ }
+ if (*gpd_ptr == NULL)
+ *gpd_ptr = gpencil_data_addnew(DATA_("GPencil"));
+
+ /* add new layer now */
+ gpencil_layer_addnew(*gpd_ptr, DATA_("GP_Layer"), 1);
+
+ /* notifiers */
+ WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
+
+ return OPERATOR_FINISHED;
+}
+
+void GPENCIL_OT_layer_add(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Add New Layer";
+ ot->idname = "GPENCIL_OT_layer_add";
+ ot->description = "Add new Grease Pencil layer for the active Grease Pencil datablock";
+
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* callbacks */
+ ot->exec = gp_layer_add_exec;
+ ot->poll = gp_add_poll;
+}
+
+/* ******************* Remove Active Layer ************************* */
+
+static int gp_layer_remove_exec(bContext *C, wmOperator *op)
+{
+ bGPdata *gpd = ED_gpencil_data_get_active(C);
+ bGPDlayer *gpl = gpencil_layer_getactive(gpd);
+
+ /* sanity checks */
+ if (ELEM(NULL, gpd, gpl))
+ return OPERATOR_CANCELLED;
+
+ if (gpl->flag & GP_LAYER_LOCKED) {
+ BKE_report(op->reports, RPT_ERROR, "Cannot delete locked layers");
+ return OPERATOR_CANCELLED;
+ }
+
+ /* make the layer before this the new active layer
+ * - use the one after if this is the first
+ * - if this is the only layer, this naturally becomes NULL
+ */
+ if (gpl->prev)
+ gpencil_layer_setactive(gpd, gpl->prev);
+ else
+ gpencil_layer_setactive(gpd, gpl->next);
+
+ /* delete the layer now... */
+ gpencil_layer_delete(gpd, gpl);
+
+ /* notifiers */
+ WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
+
+ return OPERATOR_FINISHED;
+}
+
+void GPENCIL_OT_layer_remove(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Remove Layer";
+ ot->idname = "GPENCIL_OT_layer_remove";
+ ot->description = "Remove active Grease Pencil layer";
+
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* callbacks */
+ ot->exec = gp_layer_remove_exec;
+ ot->poll = gp_active_layer_poll;
+}
+
+/* ******************* Move Layer Up/Down ************************** */
+
+enum {
+ GP_LAYER_MOVE_UP = -1,
+ GP_LAYER_MOVE_DOWN = 1
+};
+
+static int gp_layer_move_exec(bContext *C, wmOperator *op)
+{
+ bGPdata *gpd = ED_gpencil_data_get_active(C);
+ bGPDlayer *gpl = gpencil_layer_getactive(gpd);
+
+ int direction = RNA_enum_get(op->ptr, "type");
+
+ /* sanity checks */
+ if (ELEM(NULL, gpd, gpl))
+ return OPERATOR_CANCELLED;
+
+ /* up or down? */
+ if (direction == GP_LAYER_MOVE_UP) {
+ /* up */
+ BLI_remlink(&gpd->layers, gpl);
+ BLI_insertlinkbefore(&gpd->layers, gpl->prev, gpl);
+ }
+ else {
+ /* down */
+ BLI_remlink(&gpd->layers, gpl);
+ BLI_insertlinkafter(&gpd->layers, gpl->next, gpl);
+ }
+
+ /* notifiers */
+ WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
+
+ return OPERATOR_FINISHED;
+}
+
+void GPENCIL_OT_layer_move(wmOperatorType *ot)
+{
+ static EnumPropertyItem slot_move[] = {
+ {GP_LAYER_MOVE_UP, "UP", 0, "Up", ""},
+ {GP_LAYER_MOVE_DOWN, "DOWN", 0, "Down", ""},
+ {0, NULL, 0, NULL, NULL}
+ };
+
+ /* identifiers */
+ ot->name = "Move Grease Pencil Layer";
+ ot->idname = "GPENCIL_OT_layer_move";
+ ot->description = "Move the active Grease Pencil layer up/down in the list";
+
+ /* api callbacks */
+ ot->exec = gp_layer_move_exec;
+ ot->poll = gp_active_layer_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ ot->prop = RNA_def_enum(ot->srna, "type", slot_move, 0, "Type", "");
+}
+
+/* ********************* Duplicate Layer ************************** */
+
+static int gp_layer_copy_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ bGPdata *gpd = ED_gpencil_data_get_active(C);
+ bGPDlayer *gpl = gpencil_layer_getactive(gpd);
+ bGPDlayer *new_layer;
+
+ /* sanity checks */
+ if (ELEM(NULL, gpd, gpl))
+ return OPERATOR_CANCELLED;
+
+ /* make copy of layer, and add it immediately after the existing layer */
+ new_layer = gpencil_layer_duplicate(gpl);
+ BLI_insertlinkafter(&gpd->layers, gpl, new_layer);
+
+ /* ensure new layer has a unique name, and is now the active layer */
+ BLI_uniquename(&gpd->layers, new_layer, DATA_("GP_Layer"), '.', offsetof(bGPDlayer, info), sizeof(new_layer->info));
+ gpencil_layer_setactive(gpd, new_layer);
+
+ /* notifiers */
+ WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
+
+ return OPERATOR_FINISHED;
+}
+
+void GPENCIL_OT_layer_duplicate(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Duplicate Layer";
+ ot->idname = "GPENCIL_OT_layer_duplicate";
+ ot->description = "Make a copy of the active Grease Pencil layer";
+
+ /* callbacks */
+ ot->exec = gp_layer_copy_exec;
+ ot->poll = gp_active_layer_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+/* *********************** Hide Layers ******************************** */
+
+static int gp_hide_exec(bContext *C, wmOperator *op)
+{
+ bGPdata *gpd = ED_gpencil_data_get_active(C);
+ bGPDlayer *layer = gpencil_layer_getactive(gpd);
+ bool unselected = RNA_boolean_get(op->ptr, "unselected");
+
+ /* sanity checks */
+ if (ELEM(NULL, gpd, layer))
+ return OPERATOR_CANCELLED;
+
+ if (unselected) {
+ bGPDlayer *gpl;
+
+ /* hide unselected */
+ for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ if (gpl != layer) {
+ gpl->flag |= GP_LAYER_HIDE;
+ }
+ }
+ }
+ else {
+ /* hide selected/active */
+ layer->flag |= GP_LAYER_HIDE;
+ }
+
+ /* notifiers */
+ WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
+
+ return OPERATOR_FINISHED;
+}
+
+void GPENCIL_OT_hide(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Hide Layer(s)";
+ ot->idname = "GPENCIL_OT_hide";
+ ot->description = "Hide selected/unselected Grease Pencil layers";
+
+ /* callbacks */
+ ot->exec = gp_hide_exec;
+ ot->poll = gp_active_layer_poll; /* NOTE: we need an active layer to play with */
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* props */
+ RNA_def_boolean(ot->srna, "unselected", 0, "Unselected", "Hide unselected rather than selected layers");
+}
+
+/* ********************** Show All Layers ***************************** */
+
+/* poll callback for showing layers */
+static int gp_reveal_poll(bContext *C)
+{
+ return ED_gpencil_data_get_active(C) != NULL;
+}
+
+static int gp_reveal_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ bGPdata *gpd = ED_gpencil_data_get_active(C);
+ bGPDlayer *gpl;
+
+ /* sanity checks */
+ if (gpd == NULL)
+ return OPERATOR_CANCELLED;
+
+ /* make all layers visible */
+ for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ gpl->flag &= ~GP_LAYER_HIDE;
+ }
+
+ /* notifiers */
+ WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
+
+ return OPERATOR_FINISHED;
+}
+
+void GPENCIL_OT_reveal(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Show All Layers";
+ ot->idname = "GPENCIL_OT_reveal";
+ ot->description = "Show all Grease Pencil layers";
+
+ /* callbacks */
+ ot->exec = gp_reveal_exec;
+ ot->poll = gp_reveal_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+/* ************************************************ */
diff --git a/source/blender/editors/gpencil/gpencil_edit.c b/source/blender/editors/gpencil/gpencil_edit.c
index 13334448941..5c37a0a5b60 100644
--- a/source/blender/editors/gpencil/gpencil_edit.c
+++ b/source/blender/editors/gpencil/gpencil_edit.c
@@ -21,12 +21,15 @@
* Contributor(s): Joshua Leung
*
* ***** END GPL LICENSE BLOCK *****
+ *
+ * Operators for editing Grease Pencil strokes
*/
/** \file blender/editors/gpencil/gpencil_edit.c
* \ingroup edgpencil
*/
+
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
@@ -37,15 +40,10 @@
#include "BLI_math.h"
#include "BLI_blenlib.h"
-#include "BLI_rand.h"
#include "BLI_utildefines.h"
-#include "BLF_translation.h"
+#include "BLT_translation.h"
-#include "DNA_anim_types.h"
-#include "DNA_curve_types.h"
-#include "DNA_object_types.h"
-#include "DNA_node_types.h"
#include "DNA_scene_types.h"
#include "DNA_screen_types.h"
#include "DNA_space_types.h"
@@ -53,17 +51,11 @@
#include "DNA_gpencil_types.h"
#include "BKE_context.h"
-#include "BKE_curve.h"
-#include "BKE_depsgraph.h"
-#include "BKE_fcurve.h"
#include "BKE_global.h"
#include "BKE_gpencil.h"
#include "BKE_library.h"
-#include "BKE_object.h"
#include "BKE_report.h"
-#include "BKE_scene.h"
#include "BKE_screen.h"
-#include "BKE_tracking.h"
#include "UI_interface.h"
@@ -77,261 +69,369 @@
#include "ED_gpencil.h"
#include "ED_view3d.h"
-#include "ED_clip.h"
-#include "ED_keyframing.h"
#include "gpencil_intern.h"
-
/* ************************************************ */
-/* Context Wrangling... */
+/* Stroke Editing Operators */
-/* Get pointer to active Grease Pencil datablock, and an RNA-pointer to trace back to whatever owns it */
-bGPdata **ED_gpencil_data_get_pointers(const bContext *C, PointerRNA *ptr)
+/* poll callback for all stroke editing operators */
+static int gp_stroke_edit_poll(bContext *C)
{
- ID *screen_id = (ID *)CTX_wm_screen(C);
- Scene *scene = CTX_data_scene(C);
- ScrArea *sa = CTX_wm_area(C);
-
- /* if there's an active area, check if the particular editor may
- * have defined any special Grease Pencil context for editing...
- */
- if (sa) {
- switch (sa->spacetype) {
- case SPACE_VIEW3D: /* 3D-View */
- {
- Object *ob = CTX_data_active_object(C);
-
- /* TODO: we can include other data-types such as bones later if need be... */
-
- /* just in case no active/selected object */
- if (ob && (ob->flag & SELECT)) {
- /* for now, as long as there's an object, default to using that in 3D-View */
- if (ptr) RNA_id_pointer_create(&ob->id, ptr);
- return &ob->gpd;
- }
- break;
- }
- case SPACE_NODE: /* Nodes Editor */
- {
- SpaceNode *snode = (SpaceNode *)CTX_wm_space_data(C);
+ /* NOTE: this is a bit slower, but is the most accurate... */
+ return CTX_DATA_COUNT(C, editable_gpencil_strokes) != 0;
+}
- /* return the GP data for the active node block/node */
- if (snode && snode->nodetree) {
- /* for now, as long as there's an active node tree, default to using that in the Nodes Editor */
- if (ptr) RNA_id_pointer_create(&snode->nodetree->id, ptr);
- return &snode->nodetree->gpd;
- }
+/* ************** Duplicate Selected Strokes **************** */
- /* even when there is no node-tree, don't allow this to flow to scene */
- return NULL;
+/* Make copies of selected point segments in a selected stroke */
+static void gp_duplicate_points(const bGPDstroke *gps, ListBase *new_strokes)
+{
+ bGPDspoint *pt;
+ int i;
+
+ int start_idx = -1;
+
+
+ /* Step through the original stroke's points:
+ * - We accumulate selected points (from start_idx to current index)
+ * and then convert that to a new stroke
+ */
+ for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
+ /* searching for start, are waiting for end? */
+ if (start_idx == -1) {
+ /* is this the first selected point for a new island? */
+ if (pt->flag & GP_SPOINT_SELECT) {
+ start_idx = i;
}
- case SPACE_SEQ: /* Sequencer */
- {
- SpaceSeq *sseq = (SpaceSeq *)CTX_wm_space_data(C);
-
- /* for now, Grease Pencil data is associated with the space (actually preview region only) */
- /* XXX our convention for everything else is to link to data though... */
- if (ptr) RNA_pointer_create(screen_id, &RNA_SpaceSequenceEditor, sseq, ptr);
- return &sseq->gpd;
+ }
+ else {
+ size_t len = 0;
+
+ /* is this the end of current island yet?
+ * 1) Point i-1 was the last one that was selected
+ * 2) Point i is the last in the array
+ */
+ if ((pt->flag & GP_SPOINT_SELECT) == 0) {
+ len = i - start_idx;
}
- case SPACE_IMAGE: /* Image/UV Editor */
- {
- SpaceImage *sima = (SpaceImage *)CTX_wm_space_data(C);
-
- /* for now, Grease Pencil data is associated with the space... */
- /* XXX our convention for everything else is to link to data though... */
- if (ptr) RNA_pointer_create(screen_id, &RNA_SpaceImageEditor, sima, ptr);
- return &sima->gpd;
+ else if (i == gps->totpoints - 1) {
+ len = i - start_idx + 1;
}
- case SPACE_CLIP: /* Nodes Editor */
- {
- SpaceClip *sc = (SpaceClip *)CTX_wm_space_data(C);
- MovieClip *clip = ED_space_clip_get_clip(sc);
-
- if (clip) {
- if (sc->gpencil_src == SC_GPENCIL_SRC_TRACK) {
- MovieTrackingTrack *track = BKE_tracking_track_get_active(&clip->tracking);
-
- if (!track)
- return NULL;
-
- if (ptr)
- RNA_pointer_create(&clip->id, &RNA_MovieTrackingTrack, track, ptr);
-
- return &track->gpd;
- }
- else {
- if (ptr)
- RNA_id_pointer_create(&clip->id, ptr);
-
- return &clip->gpd;
- }
- }
- break;
+ //printf("copying from %d to %d = %d\n", start_idx, i, len);
+
+ /* make copies of the relevant data */
+ if (len) {
+ bGPDstroke *gpsd;
+
+ /* make a stupid copy first of the entire stroke (to get the flags too) */
+ gpsd = MEM_dupallocN(gps);
+
+ /* now, make a new points array, and copy of the relevant parts */
+ gpsd->points = MEM_callocN(sizeof(bGPDspoint) * len, "gps stroke points copy");
+ memcpy(gpsd->points, gps->points + start_idx, sizeof(bGPDspoint) * len);
+ gpsd->totpoints = len;
+
+ /* add to temp buffer */
+ gpsd->next = gpsd->prev = NULL;
+ BLI_addtail(new_strokes, gpsd);
+
+ /* cleanup + reset for next */
+ start_idx = -1;
}
- default: /* unsupported space */
- return NULL;
}
}
-
- /* just fall back on the scene's GP data */
- if (ptr) RNA_id_pointer_create((ID *)scene, ptr);
- return (scene) ? &scene->gpd : NULL;
-}
-
-/* Get the active Grease Pencil datablock */
-bGPdata *ED_gpencil_data_get_active(const bContext *C)
-{
- bGPdata **gpd_ptr = ED_gpencil_data_get_pointers(C, NULL);
- return (gpd_ptr) ? *(gpd_ptr) : NULL;
-}
-
-bGPdata *ED_gpencil_data_get_active_v3d(Scene *scene, View3D *v3d)
-{
- Base *base = scene->basact;
- bGPdata *gpd = NULL;
- /* We have to make sure active object is actually visible and selected, else we must use default scene gpd,
- * to be consistent with ED_gpencil_data_get_active's behavior.
- */
-
- if (base && TESTBASE(v3d, base)) {
- gpd = base->object->gpd;
- }
- return gpd ? gpd : scene->gpd;
-}
-
-/* ************************************************ */
-/* Panel Operators */
-
-/* poll callback for adding data/layers - special */
-static int gp_add_poll(bContext *C)
-{
- /* the base line we have is that we have somewhere to add Grease Pencil data */
- return ED_gpencil_data_get_pointers(C, NULL) != NULL;
}
-/* ******************* Add New Data ************************ */
-
-/* add new datablock - wrapper around API */
-static int gp_data_add_exec(bContext *C, wmOperator *op)
+static int gp_duplicate_exec(bContext *C, wmOperator *op)
{
- bGPdata **gpd_ptr = ED_gpencil_data_get_pointers(C, NULL);
-
- if (gpd_ptr == NULL) {
- BKE_report(op->reports, RPT_ERROR, "Nowhere for grease pencil data to go");
+ bGPdata *gpd = ED_gpencil_data_get_active(C);
+
+ if (gpd == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "No Grease Pencil data");
return OPERATOR_CANCELLED;
}
- else {
- /* decrement user count and add new datablock */
- bGPdata *gpd = (*gpd_ptr);
-
- id_us_min(&gpd->id);
- *gpd_ptr = gpencil_data_addnew(DATA_("GPencil"));
+
+ /* for each visible (and editable) layer's selected strokes,
+ * copy the strokes into a temporary buffer, then append
+ * once all done
+ */
+ CTX_DATA_BEGIN(C, bGPDlayer *, gpl, editable_gpencil_layers)
+ {
+ ListBase new_strokes = {NULL, NULL};
+ bGPDframe *gpf = gpl->actframe;
+ bGPDstroke *gps;
+
+ if (gpf == NULL)
+ continue;
+
+ /* make copies of selected strokes, and deselect these once we're done */
+ for (gps = gpf->strokes.first; gps; gps = gps->next) {
+ /* skip strokes that are invalid for current view */
+ if (ED_gpencil_stroke_can_use(C, gps) == false)
+ continue;
+
+ if (gps->flag & GP_STROKE_SELECT) {
+ if (gps->totpoints == 1) {
+ /* Special Case: If there's just a single point in this stroke... */
+ bGPDstroke *gpsd;
+
+ /* make direct copies of the stroke and its points */
+ gpsd = MEM_dupallocN(gps);
+ gpsd->points = MEM_dupallocN(gps->points);
+
+ /* add to temp buffer */
+ gpsd->next = gpsd->prev = NULL;
+ BLI_addtail(&new_strokes, gpsd);
+ }
+ else {
+ /* delegate to a helper, as there's too much to fit in here (for copying subsets)... */
+ gp_duplicate_points(gps, &new_strokes);
+ }
+
+ /* deselect original stroke, or else the originals get moved too
+ * (when using the copy + move macro)
+ */
+ gps->flag &= ~GP_STROKE_SELECT;
+ }
+ }
+
+ /* add all new strokes in temp buffer to the frame (preventing double-copies) */
+ BLI_movelisttolist(&gpf->strokes, &new_strokes);
+ BLI_assert(new_strokes.first == NULL);
}
-
- /* notifiers */
+ CTX_DATA_END;
+
+ /* updates */
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
-
+
return OPERATOR_FINISHED;
}
-void GPENCIL_OT_data_add(wmOperatorType *ot)
+void GPENCIL_OT_duplicate(wmOperatorType *ot)
{
/* identifiers */
- ot->name = "Grease Pencil Add New";
- ot->idname = "GPENCIL_OT_data_add";
- ot->description = "Add new Grease Pencil datablock";
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
+ ot->name = "Duplicate Strokes";
+ ot->idname = "GPENCIL_OT_duplicate";
+ ot->description = "Duplicate the selected Grease Pencil strokes";
+
/* callbacks */
- ot->exec = gp_data_add_exec;
- ot->poll = gp_add_poll;
+ ot->exec = gp_duplicate_exec;
+ ot->poll = gp_stroke_edit_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-/* ******************* Unlink Data ************************ */
+/* ******************* Copy/Paste Strokes ************************* */
+/* Grease Pencil stroke data copy/paste buffer:
+ * - The copy operation collects all segments of selected strokes,
+ * dumping "ready to be copied" copies of the strokes into the buffer.
+ * - The paste operation makes a copy of those elements, and adds them
+ * to the active layer. This effectively flattens down the strokes
+ * from several different layers into a single layer.
+ */
-/* poll callback for adding data/layers - special */
-static int gp_data_unlink_poll(bContext *C)
-{
- bGPdata **gpd_ptr = ED_gpencil_data_get_pointers(C, NULL);
+/* list of bGPDstroke instances */
+static ListBase gp_strokes_copypastebuf = {NULL, NULL};
- /* if we have access to some active data, make sure there's a datablock before enabling this */
- return (gpd_ptr && *gpd_ptr);
+/* Free copy/paste buffer data */
+void ED_gpencil_strokes_copybuf_free(void)
+{
+ bGPDstroke *gps, *gpsn;
+
+ for (gps = gp_strokes_copypastebuf.first; gps; gps = gpsn) {
+ gpsn = gps->next;
+
+ MEM_freeN(gps->points);
+ BLI_freelinkN(&gp_strokes_copypastebuf, gps);
+ }
+
+ BLI_listbase_clear(&gp_strokes_copypastebuf);
}
+/* --------------------- */
+/* Copy selected strokes */
-/* unlink datablock - wrapper around API */
-static int gp_data_unlink_exec(bContext *C, wmOperator *op)
+static int gp_strokes_copy_exec(bContext *C, wmOperator *op)
{
- bGPdata **gpd_ptr = ED_gpencil_data_get_pointers(C, NULL);
-
- if (gpd_ptr == NULL) {
- BKE_report(op->reports, RPT_ERROR, "Nowhere for grease pencil data to go");
+ bGPdata *gpd = ED_gpencil_data_get_active(C);
+
+ if (gpd == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "No Grease Pencil data");
return OPERATOR_CANCELLED;
}
- else {
- /* just unlink datablock now, decreasing its user count */
- bGPdata *gpd = (*gpd_ptr);
-
- id_us_min(&gpd->id);
- *gpd_ptr = NULL;
+
+ /* clear the buffer first */
+ ED_gpencil_strokes_copybuf_free();
+
+ /* for each visible (and editable) layer's selected strokes,
+ * copy the strokes into a temporary buffer, then append
+ * once all done
+ */
+ CTX_DATA_BEGIN(C, bGPDlayer *, gpl, editable_gpencil_layers)
+ {
+ bGPDframe *gpf = gpl->actframe;
+ bGPDstroke *gps;
+
+ if (gpf == NULL)
+ continue;
+
+ /* make copies of selected strokes, and deselect these once we're done */
+ for (gps = gpf->strokes.first; gps; gps = gps->next) {
+ /* skip strokes that are invalid for current view */
+ if (ED_gpencil_stroke_can_use(C, gps) == false)
+ continue;
+
+ if (gps->flag & GP_STROKE_SELECT) {
+ if (gps->totpoints == 1) {
+ /* Special Case: If there's just a single point in this stroke... */
+ bGPDstroke *gpsd;
+
+ /* make direct copies of the stroke and its points */
+ gpsd = MEM_dupallocN(gps);
+ gpsd->points = MEM_dupallocN(gps->points);
+
+ /* add to temp buffer */
+ gpsd->next = gpsd->prev = NULL;
+ BLI_addtail(&gp_strokes_copypastebuf, gpsd);
+ }
+ else {
+ /* delegate to a helper, as there's too much to fit in here (for copying subsets)... */
+ gp_duplicate_points(gps, &gp_strokes_copypastebuf);
+ }
+ }
+ }
}
-
- /* notifiers */
- WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
-
+ CTX_DATA_END;
+
+ /* done - no updates needed */
return OPERATOR_FINISHED;
}
-void GPENCIL_OT_data_unlink(wmOperatorType *ot)
+void GPENCIL_OT_copy(wmOperatorType *ot)
{
/* identifiers */
- ot->name = "Grease Pencil Unlink";
- ot->idname = "GPENCIL_OT_data_unlink";
- ot->description = "Unlink active Grease Pencil datablock";
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
+ ot->name = "Copy Strokes";
+ ot->idname = "GPENCIL_OT_copy";
+ ot->description = "Copy selected Grease Pencil points and strokes";
+
/* callbacks */
- ot->exec = gp_data_unlink_exec;
- ot->poll = gp_data_unlink_poll;
+ ot->exec = gp_strokes_copy_exec;
+ ot->poll = gp_stroke_edit_poll;
+
+ /* flags */
+ //ot->flag = OPTYPE_REGISTER;
}
-/* ******************* Add New Layer ************************ */
+/* --------------------- */
+/* Paste selected strokes */
-/* add new layer - wrapper around API */
-static int gp_layer_add_exec(bContext *C, wmOperator *op)
+static int gp_strokes_paste_exec(bContext *C, wmOperator *op)
{
- bGPdata **gpd_ptr = ED_gpencil_data_get_pointers(C, NULL);
-
- /* if there's no existing Grease-Pencil data there, add some */
- if (gpd_ptr == NULL) {
- BKE_report(op->reports, RPT_ERROR, "Nowhere for grease pencil data to go");
+ Scene *scene = CTX_data_scene(C);
+ bGPdata *gpd = ED_gpencil_data_get_active(C);
+ bGPDlayer *gpl = CTX_data_active_gpencil_layer(C);
+ bGPDframe *gpf;
+
+ /* check for various error conditions */
+ if (gpd == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "No Grease Pencil data");
return OPERATOR_CANCELLED;
}
- if (*gpd_ptr == NULL)
- *gpd_ptr = gpencil_data_addnew(DATA_("GPencil"));
-
- /* add new layer now */
- gpencil_layer_addnew(*gpd_ptr, DATA_("GP_Layer"), 1);
-
- /* notifiers */
+ else if (gp_strokes_copypastebuf.first == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "No strokes to paste, select and copy some points before trying again");
+ return OPERATOR_CANCELLED;
+ }
+ else if (gpl == NULL) {
+ /* no active layer - let's just create one */
+ gpl = gpencil_layer_addnew(gpd, DATA_("GP_Layer"), 1);
+ }
+ else if (gpl->flag & (GP_LAYER_HIDE | GP_LAYER_LOCKED)) {
+ BKE_report(op->reports, RPT_ERROR, "Can not paste strokes when active layer is hidden or locked");
+ return OPERATOR_CANCELLED;
+ }
+ else {
+ /* Check that some of the strokes in the buffer can be used */
+ bGPDstroke *gps;
+ bool ok = false;
+
+ for (gps = gp_strokes_copypastebuf.first; gps; gps = gps->next) {
+ if (ED_gpencil_stroke_can_use(C, gps)) {
+ ok = true;
+ break;
+ }
+ }
+
+ if (ok == false) {
+ /* XXX: this check is not 100% accurate (i.e. image editor is incompatible with normal 2D strokes),
+ * but should be enough to give users a good idea of what's going on
+ */
+ if (CTX_wm_area(C)->spacetype == SPACE_VIEW3D)
+ BKE_report(op->reports, RPT_ERROR, "Cannot paste 2D strokes in 3D View");
+ else
+ BKE_report(op->reports, RPT_ERROR, "Cannot paste 3D strokes in 2D editors");
+
+ return OPERATOR_CANCELLED;
+ }
+ }
+
+ /* Deselect all strokes first */
+ CTX_DATA_BEGIN(C, bGPDstroke *, gps, editable_gpencil_strokes)
+ {
+ bGPDspoint *pt;
+ int i;
+
+ for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
+ pt->flag &= ~GP_SPOINT_SELECT;
+ }
+
+ gps->flag &= ~GP_STROKE_SELECT;
+ }
+ CTX_DATA_END;
+
+ /* Ensure we have a frame to draw into
+ * NOTE: Since this is an op which creates strokes,
+ * we are obliged to add a new frame if one
+ * doesn't exist already
+ */
+ gpf = gpencil_layer_getframe(gpl, CFRA, true);
+
+ if (gpf) {
+ bGPDstroke *gps;
+
+ /* Copy each stroke into the layer */
+ for (gps = gp_strokes_copypastebuf.first; gps; gps = gps->next) {
+ if (ED_gpencil_stroke_can_use(C, gps)) {
+ bGPDstroke *new_stroke = MEM_dupallocN(gps);
+
+ new_stroke->points = MEM_dupallocN(gps->points);
+ new_stroke->next = new_stroke->prev = NULL;
+
+ BLI_addtail(&gpf->strokes, new_stroke);
+ }
+ }
+ }
+
+ /* updates */
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
-
+
return OPERATOR_FINISHED;
}
-void GPENCIL_OT_layer_add(wmOperatorType *ot)
+void GPENCIL_OT_paste(wmOperatorType *ot)
{
/* identifiers */
- ot->name = "Add New Layer";
- ot->idname = "GPENCIL_OT_layer_add";
- ot->description = "Add new Grease Pencil layer for the active Grease Pencil datablock";
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
+ ot->name = "Paste Strokes";
+ ot->idname = "GPENCIL_OT_paste";
+ ot->description = "Paste previously copied strokes into active layer";
+
/* callbacks */
- ot->exec = gp_layer_add_exec;
- ot->poll = gp_add_poll;
+ ot->exec = gp_strokes_paste_exec;
+ ot->poll = gp_stroke_edit_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/* ******************* Delete Active Frame ************************ */
@@ -340,7 +440,7 @@ static int gp_actframe_delete_poll(bContext *C)
{
bGPdata *gpd = ED_gpencil_data_get_active(C);
bGPDlayer *gpl = gpencil_layer_getactive(gpd);
-
+
/* only if there's an active layer with an active frame */
return (gpl && gpl->actframe);
}
@@ -352,7 +452,7 @@ static int gp_actframe_delete_exec(bContext *C, wmOperator *op)
bGPdata *gpd = ED_gpencil_data_get_active(C);
bGPDlayer *gpl = gpencil_layer_getactive(gpd);
bGPDframe *gpf = gpencil_layer_getframe(gpl, CFRA, 0);
-
+
/* if there's no existing Grease-Pencil data there, add some */
if (gpd == NULL) {
BKE_report(op->reports, RPT_ERROR, "No grease pencil data");
@@ -362,13 +462,13 @@ static int gp_actframe_delete_exec(bContext *C, wmOperator *op)
BKE_report(op->reports, RPT_ERROR, "No active frame to delete");
return OPERATOR_CANCELLED;
}
-
+
/* delete it... */
gpencil_layer_delframe(gpl, gpf);
-
+
/* notifiers */
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
-
+
return OPERATOR_FINISHED;
}
@@ -378,1406 +478,338 @@ void GPENCIL_OT_active_frame_delete(wmOperatorType *ot)
ot->name = "Delete Active Frame";
ot->idname = "GPENCIL_OT_active_frame_delete";
ot->description = "Delete the active frame for the active Grease Pencil datablock";
+
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
+
/* callbacks */
ot->exec = gp_actframe_delete_exec;
ot->poll = gp_actframe_delete_poll;
}
-/* ************************************************ */
-/* Grease Pencil to Data Operator */
-
-/* defines for possible modes */
-enum {
- GP_STROKECONVERT_PATH = 1,
- GP_STROKECONVERT_CURVE,
- GP_STROKECONVERT_POLY,
-};
-
-/* Defines for possible timing modes */
-enum {
- GP_STROKECONVERT_TIMING_NONE = 1,
- GP_STROKECONVERT_TIMING_LINEAR = 2,
- GP_STROKECONVERT_TIMING_FULL = 3,
- GP_STROKECONVERT_TIMING_CUSTOMGAP = 4,
-};
+/* ******************* Delete Operator ************************ */
-/* RNA enum define */
-static EnumPropertyItem prop_gpencil_convertmodes[] = {
- {GP_STROKECONVERT_PATH, "PATH", 0, "Path", ""},
- {GP_STROKECONVERT_CURVE, "CURVE", 0, "Bezier Curve", ""},
- {GP_STROKECONVERT_POLY, "POLY", 0, "Polygon Curve", ""},
- {0, NULL, 0, NULL, NULL}
-};
+typedef enum eGP_DeleteMode {
+ /* delete selected stroke points */
+ GP_DELETEOP_POINTS = 0,
+ /* delete selected strokes */
+ GP_DELETEOP_STROKES = 1,
+ /* delete active frame */
+ GP_DELETEOP_FRAME = 2,
+} eGP_DeleteMode;
-static EnumPropertyItem prop_gpencil_convert_timingmodes_restricted[] = {
- {GP_STROKECONVERT_TIMING_NONE, "NONE", 0, "No Timing", "Ignore timing"},
- {GP_STROKECONVERT_TIMING_LINEAR, "LINEAR", 0, "Linear", "Simple linear timing"},
- {0, NULL, 0, NULL, NULL},
-};
-static EnumPropertyItem prop_gpencil_convert_timingmodes[] = {
- {GP_STROKECONVERT_TIMING_NONE, "NONE", 0, "No Timing", "Ignore timing"},
- {GP_STROKECONVERT_TIMING_LINEAR, "LINEAR", 0, "Linear", "Simple linear timing"},
- {GP_STROKECONVERT_TIMING_FULL, "FULL", 0, "Original", "Use the original timing, gaps included"},
- {GP_STROKECONVERT_TIMING_CUSTOMGAP, "CUSTOMGAP", 0, "Custom Gaps",
- "Use the original timing, but with custom gap lengths (in frames)"},
- {0, NULL, 0, NULL, NULL},
-};
-
-static EnumPropertyItem *rna_GPConvert_mode_items(bContext *UNUSED(C), PointerRNA *ptr, PropertyRNA *UNUSED(prop),
- bool *UNUSED(r_free))
+/* Delete selected strokes */
+static int gp_delete_selected_strokes(bContext *C)
{
- if (RNA_boolean_get(ptr, "use_timing_data")) {
- return prop_gpencil_convert_timingmodes;
- }
- return prop_gpencil_convert_timingmodes_restricted;
-}
-
-/* --- */
-
-/* convert the coordinates from the given stroke point into 3d-coordinates
- * - assumes that the active space is the 3D-View
- */
-static void gp_strokepoint_convertcoords(bContext *C, bGPDstroke *gps, bGPDspoint *pt, float p3d[3], rctf *subrect)
-{
- Scene *scene = CTX_data_scene(C);
- View3D *v3d = CTX_wm_view3d(C);
- ARegion *ar = CTX_wm_region(C);
-
- if (gps->flag & GP_STROKE_3DSPACE) {
- /* directly use 3d-coordinates */
- copy_v3_v3(p3d, &pt->x);
- }
- else {
- const float *fp = ED_view3d_cursor3d_get(scene, v3d);
- float mvalf[2];
-
- /* get screen coordinate */
- if (gps->flag & GP_STROKE_2DSPACE) {
- View2D *v2d = &ar->v2d;
- UI_view2d_view_to_region_fl(v2d, pt->x, pt->y, &mvalf[0], &mvalf[1]);
- }
- else {
- if (subrect) {
- mvalf[0] = (((float)pt->x / 100.0f) * BLI_rctf_size_x(subrect)) + subrect->xmin;
- mvalf[1] = (((float)pt->y / 100.0f) * BLI_rctf_size_y(subrect)) + subrect->ymin;
- }
- else {
- mvalf[0] = (float)pt->x / 100.0f * ar->winx;
- mvalf[1] = (float)pt->y / 100.0f * ar->winy;
- }
- }
-
- ED_view3d_win_to_3d(ar, fp, mvalf, p3d);
- }
-}
-
-/* --- */
-
-/* temp struct for gp_stroke_path_animation() */
-typedef struct tGpTimingData {
- /* Data set from operator settings */
- int mode;
- int frame_range; /* Number of frames evaluated for path animation */
- int start_frame, end_frame;
- bool realtime; /* Will overwrite end_frame in case of Original or CustomGap timing... */
- float gap_duration, gap_randomness; /* To be used with CustomGap mode*/
- int seed;
-
- /* Data set from points, used to compute final timing FCurve */
- int num_points, cur_point;
-
- /* Distances */
- float *dists;
- float tot_dist;
-
- /* Times */
- float *times; /* Note: Gap times will be negative! */
- float tot_time, gap_tot_time;
- double inittime;
-
- /* Only used during creation of dists & times lists. */
- float offset_time;
-} tGpTimingData;
-
-/* Init point buffers for timing data.
- * Note this assumes we only grow those arrays!
- */
-static void gp_timing_data_set_nbr(tGpTimingData *gtd, const int nbr)
-{
- float *tmp;
-
- BLI_assert(nbr > gtd->num_points);
-
- /* distances */
- tmp = gtd->dists;
- gtd->dists = MEM_callocN(sizeof(float) * nbr, __func__);
- if (tmp) {
- memcpy(gtd->dists, tmp, sizeof(float) * gtd->num_points);
- MEM_freeN(tmp);
- }
-
- /* times */
- tmp = gtd->times;
- gtd->times = MEM_callocN(sizeof(float) * nbr, __func__);
- if (tmp) {
- memcpy(gtd->times, tmp, sizeof(float) * gtd->num_points);
- MEM_freeN(tmp);
- }
-
- gtd->num_points = nbr;
-}
-
-/* add stroke point to timing buffers */
-static void gp_timing_data_add_point(tGpTimingData *gtd, const double stroke_inittime, const float time,
- const float delta_dist)
-{
- float delta_time = 0.0f;
- const int cur_point = gtd->cur_point;
-
- if (!cur_point) {
- /* Special case, first point, if time is not 0.0f we have to compensate! */
- gtd->offset_time = -time;
- gtd->times[cur_point] = 0.0f;
- }
- else if (time < 0.0f) {
- /* This is a gap, negative value! */
- gtd->times[cur_point] = -(((float)(stroke_inittime - gtd->inittime)) + time + gtd->offset_time);
- delta_time = -gtd->times[cur_point] - gtd->times[cur_point - 1];
-
- gtd->gap_tot_time += delta_time;
+ bool changed = false;
+
+ CTX_DATA_BEGIN(C, bGPDlayer *, gpl, editable_gpencil_layers)
+ {
+ bGPDframe *gpf = gpl->actframe;
+ bGPDstroke *gps, *gpsn;
+
+ if (gpf == NULL)
+ continue;
+
+ /* simply delete strokes which are selected */
+ for (gps = gpf->strokes.first; gps; gps = gpsn) {
+ gpsn = gps->next;
+
+ /* skip strokes that are invalid for current view */
+ if (ED_gpencil_stroke_can_use(C, gps) == false)
+ continue;
+
+ /* free stroke if selected */
+ if (gps->flag & GP_STROKE_SELECT) {
+ /* free stroke memory arrays, then stroke itself */
+ if (gps->points) MEM_freeN(gps->points);
+ BLI_freelinkN(&gpf->strokes, gps);
+
+ changed = true;
+ }
+ }
+ }
+ CTX_DATA_END;
+
+ if (changed) {
+ WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
+ return OPERATOR_FINISHED;
}
else {
- gtd->times[cur_point] = (((float)(stroke_inittime - gtd->inittime)) + time + gtd->offset_time);
- delta_time = gtd->times[cur_point] - fabsf(gtd->times[cur_point - 1]);
+ return OPERATOR_CANCELLED;
}
-
- gtd->tot_time += delta_time;
- gtd->tot_dist += delta_dist;
- gtd->dists[cur_point] = gtd->tot_dist;
-
- gtd->cur_point++;
}
-/* In frames! Binary search for FCurve keys have a threshold of 0.01, so we can't set
- * arbitrarily close points - this is esp. important with NoGaps mode!
- */
-#define MIN_TIME_DELTA 0.02f
-
-/* Loop over next points to find the end of the stroke, and compute */
-static int gp_find_end_of_stroke_idx(tGpTimingData *gtd, RNG *rng, const int idx, const int nbr_gaps,
- int *nbr_done_gaps, const float tot_gaps_time, const float delta_time,
- float *next_delta_time)
+/* Delete selected points but keep the stroke */
+static int gp_dissolve_selected_points(bContext *C)
{
- int j;
-
- for (j = idx + 1; j < gtd->num_points; j++) {
- if (gtd->times[j] < 0) {
- gtd->times[j] = -gtd->times[j];
- if (gtd->mode == GP_STROKECONVERT_TIMING_CUSTOMGAP) {
- /* In this mode, gap time between this stroke and the next should be 0 currently...
- * So we have to compute its final duration!
- */
- if (gtd->gap_randomness > 0.0f) {
- /* We want gaps that are in gtd->gap_duration +/- gtd->gap_randomness range,
- * and which sum to exactly tot_gaps_time...
- */
- int rem_gaps = nbr_gaps - (*nbr_done_gaps);
- if (rem_gaps < 2) {
- /* Last gap, just give remaining time! */
- *next_delta_time = tot_gaps_time;
- }
- else {
- float delta, min, max;
-
- /* This code ensures that if the first gaps have been shorter than average gap_duration,
- * next gaps will tend to be longer (i.e. try to recover the lateness), and vice-versa!
- */
- delta = delta_time - (gtd->gap_duration * (*nbr_done_gaps));
-
- /* Clamp min between [-gap_randomness, 0.0], with lower delta giving higher min */
- min = -gtd->gap_randomness - delta;
- CLAMP(min, -gtd->gap_randomness, 0.0f);
-
- /* Clamp max between [0.0, gap_randomness], with lower delta giving higher max */
- max = gtd->gap_randomness - delta;
- CLAMP(max, 0.0f, gtd->gap_randomness);
- *next_delta_time += gtd->gap_duration + (BLI_rng_get_float(rng) * (max - min)) + min;
+ bool changed = false;
+
+ CTX_DATA_BEGIN(C, bGPDlayer *, gpl, editable_gpencil_layers)
+ {
+ bGPDframe *gpf = gpl->actframe;
+ bGPDstroke *gps, *gpsn;
+
+ if (gpf == NULL)
+ continue;
+
+ /* simply delete points from selected strokes
+ * NOTE: we may still have to remove the stroke if it ends up having no points!
+ */
+ for (gps = gpf->strokes.first; gps; gps = gpsn) {
+ gpsn = gps->next;
+
+ /* skip strokes that are invalid for current view */
+ if (ED_gpencil_stroke_can_use(C, gps) == false)
+ continue;
+
+ if (gps->flag & GP_STROKE_SELECT) {
+ bGPDspoint *pt;
+ int i;
+
+ int tot = gps->totpoints; /* number of points in new buffer */
+
+ /* First Pass: Count how many points are selected (i.e. how many to remove) */
+ for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
+ if (pt->flag & GP_SPOINT_SELECT) {
+ /* selected point - one of the points to remove */
+ tot--;
}
}
- else {
- *next_delta_time += gtd->gap_duration;
+
+ /* if no points are left, we simply delete the entire stroke */
+ if (tot <= 0) {
+ /* remove the entire stroke */
+ MEM_freeN(gps->points);
+ BLI_freelinkN(&gpf->strokes, gps);
}
- }
- (*nbr_done_gaps)++;
- break;
- }
- }
-
- return j - 1;
-}
-
-static void gp_stroke_path_animation_preprocess_gaps(tGpTimingData *gtd, RNG *rng, int *nbr_gaps, float *tot_gaps_time)
-{
- int i;
- float delta_time = 0.0f;
-
- for (i = 0; i < gtd->num_points; i++) {
- if (gtd->times[i] < 0 && i) {
- (*nbr_gaps)++;
- gtd->times[i] = -gtd->times[i] - delta_time;
- delta_time += gtd->times[i] - gtd->times[i - 1];
- gtd->times[i] = -gtd->times[i - 1]; /* Temp marker, values *have* to be different! */
- }
- else {
- gtd->times[i] -= delta_time;
- }
- }
- gtd->tot_time -= delta_time;
-
- *tot_gaps_time = (float)(*nbr_gaps) * gtd->gap_duration;
- gtd->tot_time += *tot_gaps_time;
- if (G.debug & G_DEBUG) {
- printf("%f, %f, %f, %d\n", gtd->tot_time, delta_time, *tot_gaps_time, *nbr_gaps);
- }
- if (gtd->gap_randomness > 0.0f) {
- BLI_rng_srandom(rng, gtd->seed);
- }
-}
-
-static void gp_stroke_path_animation_add_keyframes(ReportList *reports, PointerRNA ptr, PropertyRNA *prop, FCurve *fcu,
- Curve *cu, tGpTimingData *gtd, RNG *rng, const float time_range,
- const int nbr_gaps, const float tot_gaps_time)
-{
- /* Use actual recorded timing! */
- const float time_start = (float)gtd->start_frame;
-
- float last_valid_time = 0.0f;
- int end_stroke_idx = -1, start_stroke_idx = 0;
- float end_stroke_time = 0.0f;
-
- /* CustomGaps specific */
- float delta_time = 0.0f, next_delta_time = 0.0f;
- int nbr_done_gaps = 0;
-
- int i;
- float cfra;
-
- /* This is a bit tricky, as:
- * - We can't add arbitrarily close points on FCurve (in time).
- * - We *must* have all "caps" points of all strokes in FCurve, as much as possible!
- */
- for (i = 0; i < gtd->num_points; i++) {
- /* If new stroke... */
- if (i > end_stroke_idx) {
- start_stroke_idx = i;
- delta_time = next_delta_time;
- /* find end of that new stroke */
- end_stroke_idx = gp_find_end_of_stroke_idx(gtd, rng, i, nbr_gaps, &nbr_done_gaps,
- tot_gaps_time, delta_time, &next_delta_time);
- /* This one should *never* be negative! */
- end_stroke_time = time_start + ((gtd->times[end_stroke_idx] + delta_time) / gtd->tot_time * time_range);
- }
-
- /* Simple proportional stuff... */
- cu->ctime = gtd->dists[i] / gtd->tot_dist * cu->pathlen;
- cfra = time_start + ((gtd->times[i] + delta_time) / gtd->tot_time * time_range);
-
- /* And now, the checks about timing... */
- if (i == start_stroke_idx) {
- /* If first point of a stroke, be sure it's enough ahead of last valid keyframe, and
- * that the end point of the stroke is far enough!
- * In case it is not, we keep the end point...
- * Note that with CustomGaps mode, this is here we set the actual gap timing!
- */
- if ((end_stroke_time - last_valid_time) > MIN_TIME_DELTA * 2) {
- if ((cfra - last_valid_time) < MIN_TIME_DELTA) {
- cfra = last_valid_time + MIN_TIME_DELTA;
+ else {
+ /* just copy all unselected into a smaller buffer */
+ bGPDspoint *new_points = MEM_callocN(sizeof(bGPDspoint) * tot, "new gp stroke points copy");
+ bGPDspoint *npt = new_points;
+
+ for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
+ if ((pt->flag & GP_SPOINT_SELECT) == 0) {
+ *npt = *pt;
+ npt++;
+ }
+ }
+
+ /* free the old buffer */
+ MEM_freeN(gps->points);
+
+ /* save the new buffer */
+ gps->points = new_points;
+ gps->totpoints = tot;
+
+ /* deselect the stroke, since none of its selected points will still be selected */
+ gps->flag &= ~GP_STROKE_SELECT;
}
- insert_keyframe_direct(reports, ptr, prop, fcu, cfra, INSERTKEY_FAST);
- last_valid_time = cfra;
- }
- else if (G.debug & G_DEBUG) {
- printf("\t Skipping start point %d, too close from end point %d\n", i, end_stroke_idx);
- }
- }
- else if (i == end_stroke_idx) {
- /* Always try to insert end point of a curve (should be safe enough, anyway...) */
- if ((cfra - last_valid_time) < MIN_TIME_DELTA) {
- cfra = last_valid_time + MIN_TIME_DELTA;
- }
- insert_keyframe_direct(reports, ptr, prop, fcu, cfra, INSERTKEY_FAST);
- last_valid_time = cfra;
- }
- else {
- /* Else ("middle" point), we only insert it if it's far enough from last keyframe,
- * and also far enough from (not yet added!) end_stroke keyframe!
- */
- if ((cfra - last_valid_time) > MIN_TIME_DELTA && (end_stroke_time - cfra) > MIN_TIME_DELTA) {
- insert_keyframe_direct(reports, ptr, prop, fcu, cfra, INSERTKEY_FAST);
- last_valid_time = cfra;
- }
- else if (G.debug & G_DEBUG) {
- printf("\t Skipping \"middle\" point %d, too close from last added point or end point %d\n",
- i, end_stroke_idx);
+
+ changed = true;
}
}
}
-}
-
-static void gp_stroke_path_animation(bContext *C, ReportList *reports, Curve *cu, tGpTimingData *gtd)
-{
- Scene *scene = CTX_data_scene(C);
- bAction *act;
- FCurve *fcu;
- PointerRNA ptr;
- PropertyRNA *prop = NULL;
- int nbr_gaps = 0, i;
-
- if (gtd->mode == GP_STROKECONVERT_TIMING_NONE)
- return;
-
- /* gap_duration and gap_randomness are in frames, but we need seconds!!! */
- gtd->gap_duration = FRA2TIME(gtd->gap_duration);
- gtd->gap_randomness = FRA2TIME(gtd->gap_randomness);
-
- /* Enable path! */
- cu->flag |= CU_PATH;
- cu->pathlen = gtd->frame_range;
-
- /* Get RNA pointer to read/write path time values */
- RNA_id_pointer_create((ID *)cu, &ptr);
- prop = RNA_struct_find_property(&ptr, "eval_time");
-
- /* Ensure we have an F-Curve to add keyframes to */
- act = verify_adt_action((ID *)cu, true);
- fcu = verify_fcurve(act, NULL, &ptr, "eval_time", 0, true);
-
- if (G.debug & G_DEBUG) {
- printf("%s: tot len: %f\t\ttot time: %f\n", __func__, gtd->tot_dist, gtd->tot_time);
- for (i = 0; i < gtd->num_points; i++) {
- printf("\tpoint %d:\t\tlen: %f\t\ttime: %f\n", i, gtd->dists[i], gtd->times[i]);
- }
- }
-
- if (gtd->mode == GP_STROKECONVERT_TIMING_LINEAR) {
- float cfra;
-
- /* Linear extrapolation! */
- fcu->extend = FCURVE_EXTRAPOLATE_LINEAR;
-
- cu->ctime = 0.0f;
- cfra = (float)gtd->start_frame;
- insert_keyframe_direct(reports, ptr, prop, fcu, cfra, INSERTKEY_FAST);
-
- cu->ctime = cu->pathlen;
- if (gtd->realtime) {
- cfra += (float)TIME2FRA(gtd->tot_time); /* Seconds to frames */
- }
- else {
- cfra = (float)gtd->end_frame;
- }
- insert_keyframe_direct(reports, ptr, prop, fcu, cfra, INSERTKEY_FAST);
+ CTX_DATA_END;
+
+ if (changed) {
+ WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
+ return OPERATOR_FINISHED;
}
else {
- /* Use actual recorded timing! */
- RNG *rng = BLI_rng_new(0);
- float time_range;
-
- /* CustomGaps specific */
- float tot_gaps_time = 0.0f;
-
- /* Pre-process gaps, in case we don't want to keep their original timing */
- if (gtd->mode == GP_STROKECONVERT_TIMING_CUSTOMGAP) {
- gp_stroke_path_animation_preprocess_gaps(gtd, rng, &nbr_gaps, &tot_gaps_time);
- }
-
- if (gtd->realtime) {
- time_range = (float)TIME2FRA(gtd->tot_time); /* Seconds to frames */
- }
- else {
- time_range = (float)(gtd->end_frame - gtd->start_frame);
- }
-
- if (G.debug & G_DEBUG) {
- printf("GP Stroke Path Conversion: Starting keying!\n");
- }
-
- gp_stroke_path_animation_add_keyframes(reports, ptr, prop, fcu, cu, gtd, rng, time_range,
- nbr_gaps, tot_gaps_time);
-
- BLI_rng_free(rng);
- }
-
- /* As we used INSERTKEY_FAST mode, we need to recompute all curve's handles now */
- calchandles_fcurve(fcu);
-
- if (G.debug & G_DEBUG) {
- printf("%s: \ntot len: %f\t\ttot time: %f\n", __func__, gtd->tot_dist, gtd->tot_time);
- for (i = 0; i < gtd->num_points; i++) {
- printf("\tpoint %d:\t\tlen: %f\t\ttime: %f\n", i, gtd->dists[i], gtd->times[i]);
- }
- printf("\n\n");
- }
-
- WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL);
-
- /* send updates */
- DAG_id_tag_update(&cu->id, 0);
-}
-
-#undef MIN_TIME_DELTA
-
-#define GAP_DFAC 0.01f
-#define WIDTH_CORR_FAC 0.1f
-#define BEZT_HANDLE_FAC 0.3f
-
-/* convert stroke to 3d path */
-
-/* helper */
-static void gp_stroke_to_path_add_point(tGpTimingData *gtd, BPoint *bp, const float p[3], const float prev_p[3],
- const bool do_gtd, const double inittime, const float time,
- const float width, const float rad_fac, float minmax_weights[2])
-{
- copy_v3_v3(bp->vec, p);
- bp->vec[3] = 1.0f;
-
- /* set settings */
- bp->f1 = SELECT;
- bp->radius = width * rad_fac;
- bp->weight = width;
- CLAMP(bp->weight, 0.0f, 1.0f);
- if (bp->weight < minmax_weights[0]) {
- minmax_weights[0] = bp->weight;
- }
- else if (bp->weight > minmax_weights[1]) {
- minmax_weights[1] = bp->weight;
- }
-
- /* Update timing data */
- if (do_gtd) {
- gp_timing_data_add_point(gtd, inittime, time, len_v3v3(prev_p, p));
+ return OPERATOR_CANCELLED;
}
}
-static void gp_stroke_to_path(bContext *C, bGPDlayer *gpl, bGPDstroke *gps, Curve *cu, rctf *subrect, Nurb **curnu,
- float minmax_weights[2], const float rad_fac, bool stitch, const bool add_start_point,
- const bool add_end_point, tGpTimingData *gtd)
+/* Split selected strokes into segments, splitting on selected points */
+static int gp_delete_selected_points(bContext *C)
{
- bGPDspoint *pt;
- Nurb *nu = (curnu) ? *curnu : NULL;
- BPoint *bp, *prev_bp = NULL;
- const bool do_gtd = (gtd->mode != GP_STROKECONVERT_TIMING_NONE);
- const int add_start_end_points = (add_start_point ? 1 : 0) + (add_end_point ? 1 : 0);
- int i, old_nbp = 0;
-
- /* create new 'nurb' or extend current one within the curve */
- if (nu) {
- old_nbp = nu->pntsu;
-
- /* If stitch, the first point of this stroke is already present in current nu.
- * Else, we have to add two additional points to make the zero-radius link between strokes.
- */
- BKE_nurb_points_add(nu, gps->totpoints + (stitch ? -1 : 2) + add_start_end_points);
- }
- else {
- nu = (Nurb *)MEM_callocN(sizeof(Nurb), "gpstroke_to_path(nurb)");
-
- nu->pntsu = gps->totpoints + add_start_end_points;
- nu->pntsv = 1;
- nu->orderu = 2; /* point-to-point! */
- nu->type = CU_NURBS;
- nu->flagu = CU_NURB_ENDPOINT;
- nu->resolu = cu->resolu;
- nu->resolv = cu->resolv;
- nu->knotsu = NULL;
-
- nu->bp = (BPoint *)MEM_callocN(sizeof(BPoint) * nu->pntsu, "bpoints");
-
- stitch = false; /* Security! */
- }
-
- if (do_gtd) {
- gp_timing_data_set_nbr(gtd, nu->pntsu);
- }
-
- /* If needed, make the link between both strokes with two zero-radius additional points */
- /* About "zero-radius" point interpolations:
- * - If we have at least two points in current curve (most common case), we linearly extrapolate
- * the last segment to get the first point (p1) position and timing.
- * - If we do not have those (quite odd, but may happen), we linearly interpolate the last point
- * with the first point of the current stroke.
- * The same goes for the second point, first segment of the current stroke is "negatively" extrapolated
- * if it exists, else (if the stroke is a single point), linear interpolation with last curve point...
- */
- if (curnu && !stitch && old_nbp) {
- float p1[3], p2[3], p[3], next_p[3];
- float dt1 = 0.0f, dt2 = 0.0f;
-
- BLI_assert(gps->prev != NULL);
-
- prev_bp = NULL;
- if ((old_nbp > 1) && (gps->prev->totpoints > 1)) {
- /* Only use last curve segment if previous stroke was not a single-point one! */
- prev_bp = &nu->bp[old_nbp - 2];
- }
- bp = &nu->bp[old_nbp - 1];
-
- /* First point */
- gp_strokepoint_convertcoords(C, gps, gps->points, p, subrect);
- if (prev_bp) {
- interp_v3_v3v3(p1, bp->vec, prev_bp->vec, -GAP_DFAC);
- if (do_gtd) {
- const int idx = gps->prev->totpoints - 1;
- dt1 = interpf(gps->prev->points[idx - 1].time, gps->prev->points[idx].time, -GAP_DFAC);
- }
- }
- else {
- interp_v3_v3v3(p1, bp->vec, p, GAP_DFAC);
- if (do_gtd) {
- dt1 = interpf(gps->inittime - gps->prev->inittime, 0.0f, GAP_DFAC);
- }
- }
- bp++;
- gp_stroke_to_path_add_point(gtd, bp, p1, (bp - 1)->vec, do_gtd, gps->prev->inittime, dt1,
- 0.0f, rad_fac, minmax_weights);
-
- /* Second point */
- /* Note dt2 is always negative, which marks the gap. */
- if (gps->totpoints > 1) {
- gp_strokepoint_convertcoords(C, gps, gps->points + 1, next_p, subrect);
- interp_v3_v3v3(p2, p, next_p, -GAP_DFAC);
- if (do_gtd) {
- dt2 = interpf(gps->points[1].time, gps->points[0].time, -GAP_DFAC);
- }
- }
- else {
- interp_v3_v3v3(p2, p, bp->vec, GAP_DFAC);
- if (do_gtd) {
- dt2 = interpf(gps->prev->inittime - gps->inittime, 0.0f, GAP_DFAC);
- }
- }
- bp++;
- gp_stroke_to_path_add_point(gtd, bp, p2, p1, do_gtd, gps->inittime, dt2, 0.0f, rad_fac, minmax_weights);
-
- old_nbp += 2;
- }
- else if (add_start_point) {
- float p[3], next_p[3];
- float dt = 0.0f;
-
- gp_strokepoint_convertcoords(C, gps, gps->points, p, subrect);
- if (gps->totpoints > 1) {
- gp_strokepoint_convertcoords(C, gps, gps->points + 1, next_p, subrect);
- interp_v3_v3v3(p, p, next_p, -GAP_DFAC);
- if (do_gtd) {
- dt = interpf(gps->points[1].time, gps->points[0].time, -GAP_DFAC);
- }
- }
- else {
- p[0] -= GAP_DFAC; /* Rather arbitrary... */
- dt = -GAP_DFAC; /* Rather arbitrary too! */
- }
- bp = &nu->bp[old_nbp];
- /* Note we can't give anything else than 0.0 as time here, since a negative one (which would be expected value)
- * would not work (it would be *before* gtd->inittime, which is not supported currently).
- */
- gp_stroke_to_path_add_point(gtd, bp, p, p, do_gtd, gps->inittime, dt, 0.0f, rad_fac, minmax_weights);
-
- old_nbp++;
- }
-
- if (old_nbp) {
- prev_bp = &nu->bp[old_nbp - 1];
- }
-
- /* add points */
- for (i = (stitch) ? 1 : 0, pt = &gps->points[(stitch) ? 1 : 0], bp = &nu->bp[old_nbp];
- i < gps->totpoints;
- i++, pt++, bp++)
+ bool changed = false;
+
+ CTX_DATA_BEGIN(C, bGPDlayer *, gpl, editable_gpencil_layers)
{
- float p[3];
- float width = pt->pressure * gpl->thickness * WIDTH_CORR_FAC;
-
- /* get coordinates to add at */
- gp_strokepoint_convertcoords(C, gps, pt, p, subrect);
-
- gp_stroke_to_path_add_point(gtd, bp, p, (prev_bp) ? prev_bp->vec : p, do_gtd, gps->inittime, pt->time,
- width, rad_fac, minmax_weights);
-
- prev_bp = bp;
- }
-
- if (add_end_point) {
- float p[3];
- float dt = 0.0f;
-
- if (gps->totpoints > 1) {
- interp_v3_v3v3(p, prev_bp->vec, (prev_bp - 1)->vec, -GAP_DFAC);
- if (do_gtd) {
- const int idx = gps->totpoints - 1;
- dt = interpf(gps->points[idx - 1].time, gps->points[idx].time, -GAP_DFAC);
- }
- }
- else {
- copy_v3_v3(p, prev_bp->vec);
- p[0] += GAP_DFAC; /* Rather arbitrary... */
- dt = GAP_DFAC; /* Rather arbitrary too! */
- }
- /* Note bp has already been incremented in main loop above, so it points to the right place. */
- gp_stroke_to_path_add_point(gtd, bp, p, prev_bp->vec, do_gtd, gps->inittime, dt, 0.0f, rad_fac, minmax_weights);
- }
-
- /* add nurb to curve */
- if (!curnu || !*curnu) {
- BLI_addtail(&cu->nurb, nu);
- }
- if (curnu) {
- *curnu = nu;
- }
-
- BKE_nurb_knot_calc_u(nu);
-}
-
-/* convert stroke to 3d bezier */
-
-/* helper */
-static void gp_stroke_to_bezier_add_point(tGpTimingData *gtd, BezTriple *bezt,
- const float p[3], const float h1[3], const float h2[3], const float prev_p[3],
- const bool do_gtd, const double inittime, const float time,
- const float width, const float rad_fac, float minmax_weights[2])
-{
- copy_v3_v3(bezt->vec[0], h1);
- copy_v3_v3(bezt->vec[1], p);
- copy_v3_v3(bezt->vec[2], h2);
-
- /* set settings */
- bezt->h1 = bezt->h2 = HD_FREE;
- bezt->f1 = bezt->f2 = bezt->f3 = SELECT;
- bezt->radius = width * rad_fac;
- bezt->weight = width;
- CLAMP(bezt->weight, 0.0f, 1.0f);
- if (bezt->weight < minmax_weights[0]) {
- minmax_weights[0] = bezt->weight;
- }
- else if (bezt->weight > minmax_weights[1]) {
- minmax_weights[1] = bezt->weight;
- }
-
- /* Update timing data */
- if (do_gtd) {
- gp_timing_data_add_point(gtd, inittime, time, len_v3v3(prev_p, p));
- }
-}
-
-static void gp_stroke_to_bezier(bContext *C, bGPDlayer *gpl, bGPDstroke *gps, Curve *cu, rctf *subrect, Nurb **curnu,
- float minmax_weights[2], const float rad_fac, bool stitch, const bool add_start_point,
- const bool add_end_point, tGpTimingData *gtd)
-{
- bGPDspoint *pt;
- Nurb *nu = (curnu) ? *curnu : NULL;
- BezTriple *bezt, *prev_bezt = NULL;
- int i, tot, old_nbezt = 0;
- const int add_start_end_points = (add_start_point ? 1 : 0) + (add_end_point ? 1 : 0);
- float p3d_cur[3], p3d_prev[3], p3d_next[3], h1[3], h2[3];
- const bool do_gtd = (gtd->mode != GP_STROKECONVERT_TIMING_NONE);
-
- /* create new 'nurb' or extend current one within the curve */
- if (nu) {
- old_nbezt = nu->pntsu;
- /* If we do stitch, first point of current stroke is assumed the same as last point of previous stroke,
- * so no need to add it.
- * If no stitch, we want to add two additional points to make a "zero-radius" link between both strokes.
- */
- BKE_nurb_bezierPoints_add(nu, gps->totpoints + ((stitch) ? -1 : 2) + add_start_end_points);
- }
- else {
- nu = (Nurb *)MEM_callocN(sizeof(Nurb), "gpstroke_to_bezier(nurb)");
-
- nu->pntsu = gps->totpoints + add_start_end_points;
- nu->resolu = 12;
- nu->resolv = 12;
- nu->type = CU_BEZIER;
- nu->bezt = (BezTriple *)MEM_callocN(sizeof(BezTriple) * nu->pntsu, "bezts");
-
- stitch = false; /* Security! */
- }
-
- if (do_gtd) {
- gp_timing_data_set_nbr(gtd, nu->pntsu);
- }
-
- tot = gps->totpoints;
-
- /* get initial coordinates */
- pt = gps->points;
- if (tot) {
- gp_strokepoint_convertcoords(C, gps, pt, (stitch) ? p3d_prev : p3d_cur, subrect);
- if (tot > 1) {
- gp_strokepoint_convertcoords(C, gps, pt + 1, (stitch) ? p3d_cur : p3d_next, subrect);
- }
- if (stitch && tot > 2) {
- gp_strokepoint_convertcoords(C, gps, pt + 2, p3d_next, subrect);
- }
- }
-
- /* If needed, make the link between both strokes with two zero-radius additional points */
- if (curnu && old_nbezt) {
- BLI_assert(gps->prev != NULL);
-
- /* Update last point's second handle */
- if (stitch) {
- bezt = &nu->bezt[old_nbezt - 1];
- interp_v3_v3v3(h2, bezt->vec[1], p3d_cur, BEZT_HANDLE_FAC);
- copy_v3_v3(bezt->vec[2], h2);
- pt++;
- }
-
- /* Create "link points" */
- /* About "zero-radius" point interpolations:
- * - If we have at least two points in current curve (most common case), we linearly extrapolate
- * the last segment to get the first point (p1) position and timing.
- * - If we do not have those (quite odd, but may happen), we linearly interpolate the last point
- * with the first point of the current stroke.
- * The same goes for the second point, first segment of the current stroke is "negatively" extrapolated
- * if it exists, else (if the stroke is a single point), linear interpolation with last curve point...
- */
- else {
- float p1[3], p2[3];
- float dt1 = 0.0f, dt2 = 0.0f;
-
- prev_bezt = NULL;
- if ((old_nbezt > 1) && (gps->prev->totpoints > 1)) {
- /* Only use last curve segment if previous stroke was not a single-point one! */
- prev_bezt = &nu->bezt[old_nbezt - 2];
- }
- bezt = &nu->bezt[old_nbezt - 1];
-
- /* First point */
- if (prev_bezt) {
- interp_v3_v3v3(p1, prev_bezt->vec[1], bezt->vec[1], 1.0f + GAP_DFAC);
- if (do_gtd) {
- const int idx = gps->prev->totpoints - 1;
- dt1 = interpf(gps->prev->points[idx - 1].time, gps->prev->points[idx].time, -GAP_DFAC);
- }
- }
- else {
- interp_v3_v3v3(p1, bezt->vec[1], p3d_cur, GAP_DFAC);
- if (do_gtd) {
- dt1 = interpf(gps->inittime - gps->prev->inittime, 0.0f, GAP_DFAC);
- }
- }
-
- /* Second point */
- /* Note dt2 is always negative, which marks the gap. */
- if (tot > 1) {
- interp_v3_v3v3(p2, p3d_cur, p3d_next, -GAP_DFAC);
- if (do_gtd) {
- dt2 = interpf(gps->points[1].time, gps->points[0].time, -GAP_DFAC);
+ bGPDframe *gpf = gpl->actframe;
+ bGPDstroke *gps, *gpsn;
+
+ if (gpf == NULL)
+ continue;
+
+ /* simply delete strokes which are selected */
+ for (gps = gpf->strokes.first; gps; gps = gpsn) {
+ gpsn = gps->next;
+
+ /* skip strokes that are invalid for current view */
+ if (ED_gpencil_stroke_can_use(C, gps) == false)
+ continue;
+
+
+ if (gps->flag & GP_STROKE_SELECT) {
+ bGPDspoint *pt;
+ int i;
+
+ /* The algorithm used here is as follows:
+ * 1) We firstly identify the number of "islands" of non-selected points
+ * which will all end up being in new strokes.
+ * - In the most extreme case (i.e. every other vert is a 1-vert island),
+ * we have at most n / 2 islands
+ * - Once we start having larger islands than that, the number required
+ * becomes much less
+ * 2) Each island gets converted to a new stroke
+ */
+ typedef struct tGPDeleteIsland {
+ int start_idx;
+ int end_idx;
+ } tGPDeleteIsland;
+
+ tGPDeleteIsland *islands = MEM_callocN(sizeof(tGPDeleteIsland) * (gps->totpoints + 1) / 2, "gp_point_islands");
+ bool in_island = false;
+ int num_islands = 0;
+
+ /* First Pass: Identify start/end of islands */
+ for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
+ if (pt->flag & GP_SPOINT_SELECT) {
+ /* selected - stop accumulating to island */
+ in_island = false;
+ }
+ else {
+ /* unselected - start of a new island? */
+ int idx;
+
+ if (in_island) {
+ /* extend existing island */
+ idx = num_islands - 1;
+ islands[idx].end_idx = i;
+ }
+ else {
+ /* start of new island */
+ in_island = true;
+ num_islands++;
+
+ idx = num_islands - 1;
+ islands[idx].start_idx = islands[idx].end_idx = i;
+ }
+ }
}
- }
- else {
- interp_v3_v3v3(p2, p3d_cur, bezt->vec[1], GAP_DFAC);
- if (do_gtd) {
- dt2 = interpf(gps->prev->inittime - gps->inittime, 0.0f, GAP_DFAC);
+
+ /* Watch out for special case where No islands = All points selected = Delete Stroke only */
+ if (num_islands) {
+ /* there are islands, so create a series of new strokes, adding them before the "next" stroke */
+ int idx;
+
+ /* deselect old stroke, since it will be used as template for the new strokes */
+ gps->flag &= ~GP_STROKE_SELECT;
+
+ /* create each new stroke... */
+ for (idx = 0; idx < num_islands; idx++) {
+ tGPDeleteIsland *island = &islands[idx];
+ bGPDstroke *new_stroke = MEM_dupallocN(gps);
+
+ /* compute new buffer size (+ 1 needed as the endpoint index is "inclusive") */
+ new_stroke->totpoints = island->end_idx - island->start_idx + 1;
+ new_stroke->points = MEM_callocN(sizeof(bGPDspoint) * new_stroke->totpoints, "gp delete stroke fragment");
+
+ /* copy over the relevant points */
+ memcpy(new_stroke->points, gps->points + island->start_idx, sizeof(bGPDspoint) * new_stroke->totpoints);
+
+ /* add new stroke to the frame */
+ if (gpsn) {
+ BLI_insertlinkbefore(&gpf->strokes, gpsn, new_stroke);
+ }
+ else {
+ BLI_addtail(&gpf->strokes, new_stroke);
+ }
+ }
}
- }
-
- /* Second handle of last point of previous stroke. */
- interp_v3_v3v3(h2, bezt->vec[1], p1, BEZT_HANDLE_FAC);
- copy_v3_v3(bezt->vec[2], h2);
-
- /* First point */
- interp_v3_v3v3(h1, p1, bezt->vec[1], BEZT_HANDLE_FAC);
- interp_v3_v3v3(h2, p1, p2, BEZT_HANDLE_FAC);
- bezt++;
- gp_stroke_to_bezier_add_point(gtd, bezt, p1, h1, h2, (bezt - 1)->vec[1], do_gtd, gps->prev->inittime, dt1,
- 0.0f, rad_fac, minmax_weights);
-
- /* Second point */
- interp_v3_v3v3(h1, p2, p1, BEZT_HANDLE_FAC);
- interp_v3_v3v3(h2, p2, p3d_cur, BEZT_HANDLE_FAC);
- bezt++;
- gp_stroke_to_bezier_add_point(gtd, bezt, p2, h1, h2, p1, do_gtd, gps->inittime, dt2,
- 0.0f, rad_fac, minmax_weights);
-
- old_nbezt += 2;
- copy_v3_v3(p3d_prev, p2);
- }
- }
- else if (add_start_point) {
- float p[3];
- float dt = 0.0f;
-
- if (gps->totpoints > 1) {
- interp_v3_v3v3(p, p3d_cur, p3d_next, -GAP_DFAC);
- if (do_gtd) {
- dt = interpf(gps->points[1].time, gps->points[0].time, -GAP_DFAC);
+
+ /* free islands */
+ MEM_freeN(islands);
+
+ /* Delete the old stroke */
+ MEM_freeN(gps->points);
+ BLI_freelinkN(&gpf->strokes, gps);
+
+ changed = true;
}
}
- else {
- copy_v3_v3(p, p3d_cur);
- p[0] -= GAP_DFAC; /* Rather arbitrary... */
- dt = -GAP_DFAC; /* Rather arbitrary too! */
- }
- interp_v3_v3v3(h1, p, p3d_cur, -BEZT_HANDLE_FAC);
- interp_v3_v3v3(h2, p, p3d_cur, BEZT_HANDLE_FAC);
- bezt = &nu->bezt[old_nbezt];
- gp_stroke_to_bezier_add_point(gtd, bezt, p, h1, h2, p, do_gtd, gps->inittime, dt,
- 0.0f, rad_fac, minmax_weights);
-
- old_nbezt++;
- copy_v3_v3(p3d_prev, p);
}
-
- if (old_nbezt) {
- prev_bezt = &nu->bezt[old_nbezt - 1];
+ CTX_DATA_END;
+
+ if (changed) {
+ WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
+ return OPERATOR_FINISHED;
}
-
- /* add points */
- for (i = stitch ? 1 : 0, bezt = &nu->bezt[old_nbezt]; i < tot; i++, pt++, bezt++) {
- float width = pt->pressure * gpl->thickness * WIDTH_CORR_FAC;
-
- if (i || old_nbezt) {
- interp_v3_v3v3(h1, p3d_cur, p3d_prev, BEZT_HANDLE_FAC);
- }
- else {
- interp_v3_v3v3(h1, p3d_cur, p3d_next, -BEZT_HANDLE_FAC);
- }
-
- if (i < tot - 1) {
- interp_v3_v3v3(h2, p3d_cur, p3d_next, BEZT_HANDLE_FAC);
- }
- else {
- interp_v3_v3v3(h2, p3d_cur, p3d_prev, -BEZT_HANDLE_FAC);
- }
-
- gp_stroke_to_bezier_add_point(gtd, bezt, p3d_cur, h1, h2, prev_bezt ? prev_bezt->vec[1] : p3d_cur,
- do_gtd, gps->inittime, pt->time, width, rad_fac, minmax_weights);
-
- /* shift coord vects */
- copy_v3_v3(p3d_prev, p3d_cur);
- copy_v3_v3(p3d_cur, p3d_next);
-
- if (i + 2 < tot) {
- gp_strokepoint_convertcoords(C, gps, pt + 2, p3d_next, subrect);
- }
-
- prev_bezt = bezt;
- }
-
- if (add_end_point) {
- float p[3];
- float dt = 0.0f;
-
- if (gps->totpoints > 1) {
- interp_v3_v3v3(p, prev_bezt->vec[1], (prev_bezt - 1)->vec[1], -GAP_DFAC);
- if (do_gtd) {
- const int idx = gps->totpoints - 1;
- dt = interpf(gps->points[idx - 1].time, gps->points[idx].time, -GAP_DFAC);
- }
- }
- else {
- copy_v3_v3(p, prev_bezt->vec[1]);
- p[0] += GAP_DFAC; /* Rather arbitrary... */
- dt = GAP_DFAC; /* Rather arbitrary too! */
- }
-
- /* Second handle of last point of this stroke. */
- interp_v3_v3v3(h2, prev_bezt->vec[1], p, BEZT_HANDLE_FAC);
- copy_v3_v3(prev_bezt->vec[2], h2);
-
- /* The end point */
- interp_v3_v3v3(h1, p, prev_bezt->vec[1], BEZT_HANDLE_FAC);
- interp_v3_v3v3(h2, p, prev_bezt->vec[1], -BEZT_HANDLE_FAC);
- /* Note bezt has already been incremented in main loop above, so it points to the right place. */
- gp_stroke_to_bezier_add_point(gtd, bezt, p, h1, h2, prev_bezt->vec[1], do_gtd, gps->inittime, dt,
- 0.0f, rad_fac, minmax_weights);
- }
-
- /* must calculate handles or else we crash */
- BKE_nurb_handles_calc(nu);
-
- if (!curnu || !*curnu) {
- BLI_addtail(&cu->nurb, nu);
- }
- if (curnu) {
- *curnu = nu;
- }
-}
-
-#undef GAP_DFAC
-#undef WIDTH_CORR_FAC
-#undef BEZT_HANDLE_FAC
-
-static void gp_stroke_finalize_curve_endpoints(Curve *cu)
-{
- /* start */
- Nurb *nu = cu->nurb.first;
- int i = 0;
- if (nu->bezt) {
- BezTriple *bezt = nu->bezt;
- if (bezt) {
- bezt[i].weight = bezt[i].radius = 0.0f;
- }
- }
- else if (nu->bp) {
- BPoint *bp = nu->bp;
- if (bp) {
- bp[i].weight = bp[i].radius = 0.0f;
- }
- }
-
- /* end */
- nu = cu->nurb.last;
- i = nu->pntsu - 1;
- if (nu->bezt) {
- BezTriple *bezt = nu->bezt;
- if (bezt) {
- bezt[i].weight = bezt[i].radius = 0.0f;
- }
- }
- else if (nu->bp) {
- BPoint *bp = nu->bp;
- if (bp) {
- bp[i].weight = bp[i].radius = 0.0f;
- }
- }
-}
-
-static void gp_stroke_norm_curve_weights(Curve *cu, const float minmax_weights[2])
-{
- Nurb *nu;
- const float delta = minmax_weights[0];
- float fac;
- int i;
-
- /* when delta == minmax_weights[0] == minmax_weights[1], we get div by zero [#35686] */
- if (IS_EQF(delta, minmax_weights[1]))
- fac = 1.0f;
- else
- fac = 1.0f / (minmax_weights[1] - delta);
-
- for (nu = cu->nurb.first; nu; nu = nu->next) {
- if (nu->bezt) {
- BezTriple *bezt = nu->bezt;
- for (i = 0; i < nu->pntsu; i++, bezt++) {
- bezt->weight = (bezt->weight - delta) * fac;
- }
- }
- else if (nu->bp) {
- BPoint *bp = nu->bp;
- for (i = 0; i < nu->pntsu; i++, bp++) {
- bp->weight = (bp->weight - delta) * fac;
- }
- }
- }
-}
-
-static int gp_camera_view_subrect(bContext *C, rctf *subrect)
-{
- View3D *v3d = CTX_wm_view3d(C);
- ARegion *ar = CTX_wm_region(C);
-
- if (v3d) {
- RegionView3D *rv3d = ar->regiondata;
-
- /* for camera view set the subrect */
- if (rv3d->persp == RV3D_CAMOB) {
- Scene *scene = CTX_data_scene(C);
- ED_view3d_calc_camera_border(scene, ar, v3d, rv3d, subrect, true); /* no shift */
- return 1;
- }
- }
-
- return 0;
-}
-
-/* convert a given grease-pencil layer to a 3d-curve representation (using current view if appropriate) */
-static void gp_layer_to_curve(bContext *C, ReportList *reports, bGPdata *gpd, bGPDlayer *gpl, const int mode,
- const bool norm_weights, const float rad_fac, const bool link_strokes, tGpTimingData *gtd)
-{
- struct Main *bmain = CTX_data_main(C);
- View3D *v3d = CTX_wm_view3d(C); /* may be NULL */
- Scene *scene = CTX_data_scene(C);
- bGPDframe *gpf = gpencil_layer_getframe(gpl, CFRA, 0);
- bGPDstroke *gps, *prev_gps = NULL;
- Object *ob;
- Curve *cu;
- Nurb *nu = NULL;
- Base *base_orig = BASACT, *base_new = NULL;
- float minmax_weights[2] = {1.0f, 0.0f};
-
- /* camera framing */
- rctf subrect, *subrect_ptr = NULL;
-
- /* error checking */
- if (ELEM(NULL, gpd, gpl, gpf))
- return;
-
- /* only convert if there are any strokes on this layer's frame to convert */
- if (BLI_listbase_is_empty(&gpf->strokes))
- return;
-
- /* initialize camera framing */
- if (gp_camera_view_subrect(C, &subrect)) {
- subrect_ptr = &subrect;
- }
-
- /* init the curve object (remove rotation and get curve data from it)
- * - must clear transforms set on object, as those skew our results
- */
- ob = BKE_object_add_only_object(bmain, OB_CURVE, gpl->info);
- cu = ob->data = BKE_curve_add(bmain, gpl->info, OB_CURVE);
- base_new = BKE_scene_base_add(scene, ob);
-
- cu->flag |= CU_3D;
-
- gtd->inittime = ((bGPDstroke *)gpf->strokes.first)->inittime;
-
- /* add points to curve */
- for (gps = gpf->strokes.first; gps; gps = gps->next) {
- const bool add_start_point = (link_strokes && !(prev_gps));
- const bool add_end_point = (link_strokes && !(gps->next));
-
- /* Detect new strokes created because of GP_STROKE_BUFFER_MAX reached, and stitch them to previous one. */
- bool stitch = false;
- if (prev_gps) {
- bGPDspoint *pt1 = &prev_gps->points[prev_gps->totpoints - 1];
- bGPDspoint *pt2 = &gps->points[0];
-
- if ((pt1->x == pt2->x) && (pt1->y == pt2->y)) {
- stitch = true;
- }
- }
-
- /* Decide whether we connect this stroke to previous one */
- if (!(stitch || link_strokes)) {
- nu = NULL;
- }
-
- switch (mode) {
- case GP_STROKECONVERT_PATH:
- gp_stroke_to_path(C, gpl, gps, cu, subrect_ptr, &nu, minmax_weights, rad_fac, stitch,
- add_start_point, add_end_point, gtd);
- break;
- case GP_STROKECONVERT_CURVE:
- case GP_STROKECONVERT_POLY: /* convert after */
- gp_stroke_to_bezier(C, gpl, gps, cu, subrect_ptr, &nu, minmax_weights, rad_fac, stitch,
- add_start_point, add_end_point, gtd);
- break;
- default:
- BLI_assert(!"invalid mode");
- break;
- }
- prev_gps = gps;
- }
-
- /* If link_strokes, be sure first and last points have a zero weight/size! */
- if (link_strokes) {
- gp_stroke_finalize_curve_endpoints(cu);
- }
-
- /* Update curve's weights, if needed */
- if (norm_weights && ((minmax_weights[0] > 0.0f) || (minmax_weights[1] < 1.0f))) {
- gp_stroke_norm_curve_weights(cu, minmax_weights);
- }
-
- /* Create the path animation, if needed */
- gp_stroke_path_animation(C, reports, cu, gtd);
-
- if (mode == GP_STROKECONVERT_POLY) {
- for (nu = cu->nurb.first; nu; nu = nu->next) {
- BKE_nurb_type_convert(nu, CU_POLY, false);
- }
+ else {
+ return OPERATOR_CANCELLED;
}
-
- /* set the layer and select */
- base_new->lay = ob->lay = base_orig ? base_orig->lay : BKE_screen_view3d_layer_active(v3d, scene);
- base_new->flag = ob->flag = base_new->flag | SELECT;
}
-/* --- */
-/* Check a GP layer has valid timing data! Else, most timing options are hidden in the operator.
- * op may be NULL.
- */
-static bool gp_convert_check_has_valid_timing(bContext *C, bGPDlayer *gpl, wmOperator *op)
+static int gp_delete_exec(bContext *C, wmOperator *op)
{
- Scene *scene = CTX_data_scene(C);
- bGPDframe *gpf = NULL;
- bGPDstroke *gps = NULL;
- bGPDspoint *pt;
- double base_time, cur_time, prev_time = -1.0;
- int i;
- bool valid = true;
-
- if (!gpl || !(gpf = gpencil_layer_getframe(gpl, CFRA, 0)) || !(gps = gpf->strokes.first))
- return false;
-
- do {
- base_time = cur_time = gps->inittime;
- if (cur_time <= prev_time) {
- valid = false;
+ eGP_DeleteMode mode = RNA_enum_get(op->ptr, "type");
+ int result = OPERATOR_CANCELLED;
+
+ switch (mode) {
+ case GP_DELETEOP_STROKES: /* selected strokes */
+ result = gp_delete_selected_strokes(C);
break;
- }
-
- prev_time = cur_time;
- for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
- cur_time = base_time + (double)pt->time;
- /* First point of a stroke should have the same time as stroke's inittime,
- * so it's the only case where equality is allowed!
- */
- if ((i && cur_time <= prev_time) || (cur_time < prev_time)) {
- valid = false;
- break;
- }
- prev_time = cur_time;
- }
-
- if (!valid) {
+
+ case GP_DELETEOP_POINTS: /* selected points (breaks the stroke into segments) */
+ result = gp_delete_selected_points(C);
break;
- }
- } while ((gps = gps->next));
- if (op) {
- RNA_boolean_set(op->ptr, "use_timing_data", valid);
- }
- return valid;
-}
-
-/* Check end_frame is always > start frame! */
-static void gp_convert_set_end_frame(struct Main *UNUSED(main), struct Scene *UNUSED(scene), struct PointerRNA *ptr)
-{
- int start_frame = RNA_int_get(ptr, "start_frame");
- int end_frame = RNA_int_get(ptr, "end_frame");
-
- if (end_frame <= start_frame) {
- RNA_int_set(ptr, "end_frame", start_frame + 1);
+ case GP_DELETEOP_FRAME: /* active frame */
+ result = gp_actframe_delete_exec(C, op);
+ break;
}
+
+ return result;
}
-static int gp_convert_poll(bContext *C)
+void GPENCIL_OT_delete(wmOperatorType *ot)
{
- bGPdata *gpd = ED_gpencil_data_get_active(C);
- bGPDlayer *gpl = NULL;
- bGPDframe *gpf = NULL;
- ScrArea *sa = CTX_wm_area(C);
- Scene *scene = CTX_data_scene(C);
-
- /* only if the current view is 3D View, if there's valid data (i.e. at least one stroke!),
- * and if we are not in edit mode!
- */
- return ((sa && sa->spacetype == SPACE_VIEW3D) &&
- (gpl = gpencil_layer_getactive(gpd)) &&
- (gpf = gpencil_layer_getframe(gpl, CFRA, 0)) &&
- (gpf->strokes.first) &&
- (scene->obedit == NULL));
-}
-
-static int gp_convert_layer_exec(bContext *C, wmOperator *op)
-{
- PropertyRNA *prop = RNA_struct_find_property(op->ptr, "use_timing_data");
- bGPdata *gpd = ED_gpencil_data_get_active(C);
- bGPDlayer *gpl = gpencil_layer_getactive(gpd);
- Scene *scene = CTX_data_scene(C);
- const int mode = RNA_enum_get(op->ptr, "type");
- const bool norm_weights = RNA_boolean_get(op->ptr, "use_normalize_weights");
- const float rad_fac = RNA_float_get(op->ptr, "radius_multiplier");
- const bool link_strokes = RNA_boolean_get(op->ptr, "use_link_strokes");
- bool valid_timing;
- tGpTimingData gtd;
-
- /* check if there's data to work with */
- if (gpd == NULL) {
- BKE_report(op->reports, RPT_ERROR, "No Grease Pencil data to work on");
- return OPERATOR_CANCELLED;
- }
-
- if (!RNA_property_is_set(op->ptr, prop) && !gp_convert_check_has_valid_timing(C, gpl, op)) {
- BKE_report(op->reports, RPT_WARNING,
- "Current Grease Pencil strokes have no valid timing data, most timing options will be hidden!");
- }
- valid_timing = RNA_property_boolean_get(op->ptr, prop);
-
- gtd.mode = RNA_enum_get(op->ptr, "timing_mode");
- /* Check for illegal timing mode! */
- if (!valid_timing && !ELEM(gtd.mode, GP_STROKECONVERT_TIMING_NONE, GP_STROKECONVERT_TIMING_LINEAR)) {
- gtd.mode = GP_STROKECONVERT_TIMING_LINEAR;
- RNA_enum_set(op->ptr, "timing_mode", gtd.mode);
- }
- if (!link_strokes) {
- gtd.mode = GP_STROKECONVERT_TIMING_NONE;
- }
-
- /* grab all relevant settings */
- gtd.frame_range = RNA_int_get(op->ptr, "frame_range");
- gtd.start_frame = RNA_int_get(op->ptr, "start_frame");
- gtd.realtime = valid_timing ? RNA_boolean_get(op->ptr, "use_realtime") : false;
- gtd.end_frame = RNA_int_get(op->ptr, "end_frame");
- gtd.gap_duration = RNA_float_get(op->ptr, "gap_duration");
- gtd.gap_randomness = RNA_float_get(op->ptr, "gap_randomness");
- gtd.gap_randomness = min_ff(gtd.gap_randomness, gtd.gap_duration);
- gtd.seed = RNA_int_get(op->ptr, "seed");
- gtd.num_points = gtd.cur_point = 0;
- gtd.dists = gtd.times = NULL;
- gtd.tot_dist = gtd.tot_time = gtd.gap_tot_time = 0.0f;
- gtd.inittime = 0.0;
- gtd.offset_time = 0.0f;
-
- /* perform conversion */
- gp_layer_to_curve(C, op->reports, gpd, gpl, mode, norm_weights, rad_fac, link_strokes, &gtd);
-
- /* free temp memory */
- if (gtd.dists) {
- MEM_freeN(gtd.dists);
- gtd.dists = NULL;
- }
- if (gtd.times) {
- MEM_freeN(gtd.times);
- gtd.times = NULL;
- }
-
- /* notifiers */
- WM_event_add_notifier(C, NC_OBJECT | NA_ADDED, NULL);
- WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene);
-
- /* done */
- return OPERATOR_FINISHED;
-}
-
-static bool gp_convert_draw_check_prop(PointerRNA *ptr, PropertyRNA *prop)
-{
- const char *prop_id = RNA_property_identifier(prop);
- const bool link_strokes = RNA_boolean_get(ptr, "use_link_strokes");
- int timing_mode = RNA_enum_get(ptr, "timing_mode");
- bool realtime = RNA_boolean_get(ptr, "use_realtime");
- float gap_duration = RNA_float_get(ptr, "gap_duration");
- float gap_randomness = RNA_float_get(ptr, "gap_randomness");
- const bool valid_timing = RNA_boolean_get(ptr, "use_timing_data");
-
- /* Always show those props */
- if (strcmp(prop_id, "type") == 0 ||
- strcmp(prop_id, "use_normalize_weights") == 0 ||
- strcmp(prop_id, "radius_multiplier") == 0 ||
- strcmp(prop_id, "use_link_strokes") == 0)
- {
- return true;
- }
-
- /* Never show this prop */
- if (strcmp(prop_id, "use_timing_data") == 0)
- return false;
-
- if (link_strokes) {
- /* Only show when link_stroke is true */
- if (strcmp(prop_id, "timing_mode") == 0)
- return true;
-
- if (timing_mode != GP_STROKECONVERT_TIMING_NONE) {
- /* Only show when link_stroke is true and stroke timing is enabled */
- if (strcmp(prop_id, "frame_range") == 0 ||
- strcmp(prop_id, "start_frame") == 0)
- {
- return true;
- }
-
- /* Only show if we have valid timing data! */
- if (valid_timing && strcmp(prop_id, "use_realtime") == 0)
- return true;
-
- /* Only show if realtime or valid_timing is false! */
- if ((!realtime || !valid_timing) && strcmp(prop_id, "end_frame") == 0)
- return true;
-
- if (valid_timing && timing_mode == GP_STROKECONVERT_TIMING_CUSTOMGAP) {
- /* Only show for custom gaps! */
- if (strcmp(prop_id, "gap_duration") == 0)
- return true;
-
- /* Only show randomness for non-null custom gaps! */
- if (strcmp(prop_id, "gap_randomness") == 0 && (gap_duration > 0.0f))
- return true;
-
- /* Only show seed for randomize action! */
- if (strcmp(prop_id, "seed") == 0 && (gap_duration > 0.0f) && (gap_randomness > 0.0f))
- return true;
- }
- }
- }
-
- /* Else, hidden! */
- return false;
+ static EnumPropertyItem prop_gpencil_delete_types[] = {
+ {GP_DELETEOP_POINTS, "POINTS", 0, "Points", "Delete selected points and split strokes into segments"},
+ {GP_DELETEOP_STROKES, "STROKES", 0, "Strokes", "Delete selected strokes"},
+ {GP_DELETEOP_FRAME, "FRAME", 0, "Frame", "Delete active frame"},
+ {0, NULL, 0, NULL, NULL}
+ };
+
+ /* identifiers */
+ ot->name = "Delete...";
+ ot->idname = "GPENCIL_OT_delete";
+ ot->description = "Delete selected Grease Pencil strokes, vertices, or frames";
+
+ /* callbacks */
+ ot->invoke = WM_menu_invoke;
+ ot->exec = gp_delete_exec;
+ ot->poll = gp_stroke_edit_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_UNDO | OPTYPE_REGISTER;
+
+ /* props */
+ ot->prop = RNA_def_enum(ot->srna, "type", prop_gpencil_delete_types, 0, "Type", "Method used for deleting Grease Pencil data");
}
-static void gp_convert_ui(bContext *C, wmOperator *op)
+static int gp_dissolve_exec(bContext *C, wmOperator *UNUSED(op))
{
- uiLayout *layout = op->layout;
- wmWindowManager *wm = CTX_wm_manager(C);
- PointerRNA ptr;
-
- RNA_pointer_create(&wm->id, op->type->srna, op->properties, &ptr);
-
- /* Main auto-draw call */
- uiDefAutoButsRNA(layout, &ptr, gp_convert_draw_check_prop, '\0');
+ return gp_dissolve_selected_points(C);
}
-void GPENCIL_OT_convert(wmOperatorType *ot)
+void GPENCIL_OT_dissolve(wmOperatorType *ot)
{
- PropertyRNA *prop;
-
/* identifiers */
- ot->name = "Convert Grease Pencil";
- ot->idname = "GPENCIL_OT_convert";
- ot->description = "Convert the active Grease Pencil layer to a new Curve Object";
+ ot->name = "Dissolve";
+ ot->idname = "GPENCIL_OT_dissolve";
+ ot->description = "Delete selected points without splitting strokes";
/* callbacks */
- ot->invoke = WM_menu_invoke;
- ot->exec = gp_convert_layer_exec;
- ot->poll = gp_convert_poll;
- ot->ui = gp_convert_ui;
+ ot->exec = gp_dissolve_exec;
+ ot->poll = gp_stroke_edit_poll;
/* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- ot->prop = RNA_def_enum(ot->srna, "type", prop_gpencil_convertmodes, 0, "Type", "Which type of curve to convert to");
-
- RNA_def_boolean(ot->srna, "use_normalize_weights", true, "Normalize Weight",
- "Normalize weight (set from stroke width)");
- RNA_def_float(ot->srna, "radius_multiplier", 1.0f, 0.0f, 1000.0f, "Radius Fac",
- "Multiplier for the points' radii (set from stroke width)", 0.0f, 10.0f);
- RNA_def_boolean(ot->srna, "use_link_strokes", true, "Link Strokes",
- "Whether to link strokes with zero-radius sections of curves");
-
- prop = RNA_def_enum(ot->srna, "timing_mode", prop_gpencil_convert_timingmodes, GP_STROKECONVERT_TIMING_FULL,
- "Timing Mode", "How to use timing data stored in strokes");
- RNA_def_enum_funcs(prop, rna_GPConvert_mode_items);
-
- RNA_def_int(ot->srna, "frame_range", 100, 1, 10000, "Frame Range",
- "The duration of evaluation of the path control curve", 1, 1000);
- RNA_def_int(ot->srna, "start_frame", 1, 1, 100000, "Start Frame",
- "The start frame of the path control curve", 1, 100000);
- RNA_def_boolean(ot->srna, "use_realtime", false, "Realtime",
- "Whether the path control curve reproduces the drawing in realtime, starting from Start Frame");
- prop = RNA_def_int(ot->srna, "end_frame", 250, 1, 100000, "End Frame",
- "The end frame of the path control curve (if Realtime is not set)", 1, 100000);
- RNA_def_property_update_runtime(prop, gp_convert_set_end_frame);
-
- RNA_def_float(ot->srna, "gap_duration", 0.0f, 0.0f, 10000.0f, "Gap Duration",
- "Custom Gap mode: (Average) length of gaps, in frames "
- "(Note: Realtime value, will be scaled if Realtime is not set)", 0.0f, 1000.0f);
- RNA_def_float(ot->srna, "gap_randomness", 0.0f, 0.0f, 10000.0f, "Gap Randomness",
- "Custom Gap mode: Number of frames that gap lengths can vary", 0.0f, 1000.0f);
- RNA_def_int(ot->srna, "seed", 0, 0, 1000, "Random Seed",
- "Custom Gap mode: Random generator seed", 0, 100);
-
- /* Note: Internal use, this one will always be hidden by UI code... */
- prop = RNA_def_boolean(ot->srna, "use_timing_data", false, "Has Valid Timing",
- "Whether the converted Grease Pencil layer has valid timing data (internal use)");
- RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+ ot->flag = OPTYPE_UNDO | OPTYPE_REGISTER;
}
/* ************************************************ */
diff --git a/source/blender/editors/gpencil/gpencil_intern.h b/source/blender/editors/gpencil/gpencil_intern.h
index 28eb1355caf..290935a06cf 100644
--- a/source/blender/editors/gpencil/gpencil_intern.h
+++ b/source/blender/editors/gpencil/gpencil_intern.h
@@ -31,15 +31,80 @@
#ifndef __GPENCIL_INTERN_H__
#define __GPENCIL_INTERN_H__
-/* internal exports only */
+#include "DNA_vec_types.h"
-/* ***************************************************** */
-/* Operator Defines */
+/* internal exports only */
struct bGPdata;
+struct bGPDstroke;
+struct bGPDspoint;
+
+struct ARegion;
+struct View2D;
struct wmOperatorType;
+
+/* ***************************************************** */
+/* Internal API */
+
+/* Stroke Coordinates API ------------------------------ */
+/* gpencil_utils.c */
+
+typedef struct GP_SpaceConversion {
+ struct bGPdata *gpd;
+ struct bGPDlayer *gpl;
+
+ struct ScrArea *sa;
+ struct ARegion *ar;
+ struct View2D *v2d;
+
+ rctf *subrect; /* for using the camera rect within the 3d view */
+ rctf subrect_data;
+
+ float mat[4][4]; /* transform matrix on the strokes (introduced in [b770964]) */
+} GP_SpaceConversion;
+
+
+/**
+ * Check whether a given stroke segment is inside a circular brush
+ *
+ * \param mval The current screen-space coordinates (midpoint) of the brush
+ * \param mvalo The previous screen-space coordinates (midpoint) of the brush (NOT CURRENTLY USED)
+ * \param rad The radius of the brush
+ *
+ * \param x0, y0 The screen-space x and y coordinates of the start of the stroke segment
+ * \param x1, y1 The screen-space x and y coordinates of the end of the stroke segment
+ */
+bool gp_stroke_inside_circle(const int mval[2], const int UNUSED(mvalo[2]),
+ int rad, int x0, int y0, int x1, int y1);
+
+
+/**
+ * Init settings for stroke point space conversions
+ *
+ * \param[out] r_gsc The space conversion settings struct, populated with necessary params
+ */
+void gp_point_conversion_init(struct bContext *C, GP_SpaceConversion *r_gsc);
+
+/**
+ * Convert a Grease Pencil coordinate (i.e. can be 2D or 3D) to screenspace (2D)
+ *
+ * \param[out] r_x The screen-space x-coordinate of the point
+ * \param[out] r_y The screen-space y-coordinate of the point
+ */
+void gp_point_to_xy(GP_SpaceConversion *settings, struct bGPDstroke *gps, struct bGPDspoint *pt,
+ int *r_x, int *r_y);
+
+/* Poll Callbacks ------------------------------------ */
+/* gpencil_utils.c */
+
+int gp_add_poll(struct bContext *C);
+int gp_active_layer_poll(struct bContext *C);
+
+/* ***************************************************** */
+/* Operator Defines */
+
/* drawing ---------- */
void GPENCIL_OT_draw(struct wmOperatorType *ot);
@@ -52,12 +117,36 @@ typedef enum eGPencil_PaintModes {
GP_PAINTMODE_DRAW_POLY
} eGPencil_PaintModes;
+/* stroke editing ----- */
+
+void GPENCIL_OT_select(struct wmOperatorType *ot);
+void GPENCIL_OT_select_all(struct wmOperatorType *ot);
+void GPENCIL_OT_select_circle(struct wmOperatorType *ot);
+void GPENCIL_OT_select_border(struct wmOperatorType *ot);
+void GPENCIL_OT_select_lasso(struct wmOperatorType *ot);
+
+void GPENCIL_OT_select_linked(struct wmOperatorType *ot);
+void GPENCIL_OT_select_more(struct wmOperatorType *ot);
+void GPENCIL_OT_select_less(struct wmOperatorType *ot);
+
+void GPENCIL_OT_duplicate(struct wmOperatorType *ot);
+void GPENCIL_OT_delete(struct wmOperatorType *ot);
+void GPENCIL_OT_dissolve(struct wmOperatorType *ot);
+void GPENCIL_OT_copy(struct wmOperatorType *ot);
+void GPENCIL_OT_paste(struct wmOperatorType *ot);
+
/* buttons editing --- */
void GPENCIL_OT_data_add(struct wmOperatorType *ot);
void GPENCIL_OT_data_unlink(struct wmOperatorType *ot);
void GPENCIL_OT_layer_add(struct wmOperatorType *ot);
+void GPENCIL_OT_layer_remove(struct wmOperatorType *ot);
+void GPENCIL_OT_layer_move(struct wmOperatorType *ot);
+void GPENCIL_OT_layer_duplicate(struct wmOperatorType *ot);
+
+void GPENCIL_OT_hide(struct wmOperatorType *ot);
+void GPENCIL_OT_reveal(struct wmOperatorType *ot);
void GPENCIL_OT_active_frame_delete(struct wmOperatorType *ot);
@@ -76,17 +165,17 @@ void gpencil_undo_finish(void);
/* This struct defines a structure used for quick access */
typedef struct bActListElem {
struct bActListElem *next, *prev;
-
+
void *data; /* source data this elem represents */
int type; /* one of the ACTTYPE_* values */
int flag; /* copy of elem's flags for quick access */
int index; /* copy of adrcode where applicable */
-
+
void *key_data; /* motion data - ipo or ipo-curve */
short datatype; /* type of motion data to expect */
-
+
struct bActionGroup *grp; /* action group that owns the channel */
-
+
void *owner; /* will either be an action channel or fake ipo-channel (for keys) */
short ownertype; /* type of owner */
} bActListElem;
diff --git a/source/blender/editors/gpencil/gpencil_ops.c b/source/blender/editors/gpencil/gpencil_ops.c
index 75ff0895931..ab56565f4ca 100644
--- a/source/blender/editors/gpencil/gpencil_ops.c
+++ b/source/blender/editors/gpencil/gpencil_ops.c
@@ -34,7 +34,9 @@
#include "BLI_sys_types.h"
-#include "BLI_blenlib.h"
+#include "BKE_context.h"
+
+#include "DNA_gpencil_types.h"
#include "WM_api.h"
#include "WM_types.h"
@@ -42,34 +44,199 @@
#include "RNA_access.h"
#include "ED_gpencil.h"
+#include "ED_object.h"
+#include "ED_transform.h"
#include "gpencil_intern.h"
/* ****************************************** */
-/* Generic Editing Keymap */
+/* Grease Pencil Keymaps */
-void ED_keymap_gpencil(wmKeyConfig *keyconf)
+/* Generic Drawing Keymap */
+static void ed_keymap_gpencil_general(wmKeyConfig *keyconf)
{
wmKeyMap *keymap = WM_keymap_find(keyconf, "Grease Pencil", 0, 0);
wmKeyMapItem *kmi;
- /* Draw */
-
+ /* Draw --------------------------------------- */
/* draw */
kmi = WM_keymap_add_item(keymap, "GPENCIL_OT_draw", LEFTMOUSE, KM_PRESS, 0, DKEY);
RNA_enum_set(kmi->ptr, "mode", GP_PAINTMODE_DRAW);
-
+ RNA_boolean_set(kmi->ptr, "wait_for_input", false);
+
/* draw - straight lines */
kmi = WM_keymap_add_item(keymap, "GPENCIL_OT_draw", LEFTMOUSE, KM_PRESS, KM_CTRL, DKEY);
RNA_enum_set(kmi->ptr, "mode", GP_PAINTMODE_DRAW_STRAIGHT);
-
+ RNA_boolean_set(kmi->ptr, "wait_for_input", false);
+
/* draw - poly lines */
kmi = WM_keymap_add_item(keymap, "GPENCIL_OT_draw", RIGHTMOUSE, KM_PRESS, KM_CTRL, DKEY);
RNA_enum_set(kmi->ptr, "mode", GP_PAINTMODE_DRAW_POLY);
-
+ RNA_boolean_set(kmi->ptr, "wait_for_input", false);
+
/* erase */
kmi = WM_keymap_add_item(keymap, "GPENCIL_OT_draw", RIGHTMOUSE, KM_PRESS, 0, DKEY);
RNA_enum_set(kmi->ptr, "mode", GP_PAINTMODE_ERASER);
+ RNA_boolean_set(kmi->ptr, "wait_for_input", false);
+
+ /* Viewport Tools ------------------------------- */
+
+ /* Enter EditMode */
+ kmi = WM_keymap_add_item(keymap, "WM_OT_context_toggle", TABKEY, KM_PRESS, 0, DKEY);
+ RNA_string_set(kmi->ptr, "data_path", "gpencil_data.use_stroke_edit_mode");
+
+ /* Pie Menu - For standard tools */
+ WM_keymap_add_menu_pie(keymap, "GPENCIL_PIE_tool_palette", QKEY, KM_PRESS, 0, DKEY);
+ WM_keymap_add_menu_pie(keymap, "GPENCIL_PIE_settings_palette", WKEY, KM_PRESS, 0, DKEY);
+}
+
+/* ==================== */
+
+/* Poll callback for stroke editing mode */
+static int gp_stroke_editmode_poll(bContext *C)
+{
+ bGPdata *gpd = CTX_data_gpencil_data(C);
+ return (gpd && (gpd->flag & GP_DATA_STROKE_EDITMODE));
+}
+
+/* Stroke Editing Keymap - Only when editmode is enabled */
+static void ed_keymap_gpencil_editing(wmKeyConfig *keyconf)
+{
+ wmKeyMap *keymap = WM_keymap_find(keyconf, "Grease Pencil Stroke Edit Mode", 0, 0);
+ wmKeyMapItem *kmi;
+
+ /* set poll callback - so that this keymap only gets enabled when stroke editmode is enabled */
+ keymap->poll = gp_stroke_editmode_poll;
+
+ /* ----------------------------------------------- */
+
+ /* Exit EditMode */
+ kmi = WM_keymap_add_item(keymap, "WM_OT_context_toggle", TABKEY, KM_PRESS, 0, 0);
+ RNA_string_set(kmi->ptr, "data_path", "gpencil_data.use_stroke_edit_mode");
+
+ /* Brush Settings */
+ /* NOTE: We cannot expose these in the standard keymap, as they will interfere with regular hotkeys
+ * in other modes. However, when we are dealing with Stroke Edit Mode, we know for certain
+ * that the only data being edited is that of the Grease Pencil strokes
+ */
+
+ /* FKEY = Eraser Radius */
+ kmi = WM_keymap_add_item(keymap, "WM_OT_radial_control", FKEY, KM_PRESS, 0, 0);
+ RNA_string_set(kmi->ptr, "data_path_primary", "user_preferences.edit.grease_pencil_eraser_radius");
+
+ /* Selection ------------------------------------- */
+ /* select all */
+ kmi = WM_keymap_add_item(keymap, "GPENCIL_OT_select_all", AKEY, KM_PRESS, 0, 0);
+ RNA_enum_set(kmi->ptr, "action", SEL_TOGGLE);
+
+ kmi = WM_keymap_add_item(keymap, "GPENCIL_OT_select_all", IKEY, KM_PRESS, KM_CTRL, 0);
+ RNA_enum_set(kmi->ptr, "action", SEL_INVERT);
+
+ /* circle select */
+ WM_keymap_add_item(keymap, "GPENCIL_OT_select_circle", CKEY, KM_PRESS, 0, 0);
+
+ /* border select */
+ WM_keymap_add_item(keymap, "GPENCIL_OT_select_border", BKEY, KM_PRESS, 0, 0);
+
+ /* lasso select */
+ kmi = WM_keymap_add_item(keymap, "GPENCIL_OT_select_lasso", EVT_TWEAK_A, KM_ANY, KM_CTRL, 0);
+ RNA_boolean_set(kmi->ptr, "deselect", false);
+ kmi = WM_keymap_add_item(keymap, "GPENCIL_OT_select_lasso", EVT_TWEAK_A, KM_ANY, KM_SHIFT | KM_CTRL, 0);
+ RNA_boolean_set(kmi->ptr, "deselect", true);
+
+ /* normal select */
+ WM_keymap_add_item(keymap, "GPENCIL_OT_select", SELECTMOUSE, KM_PRESS, 0, 0);
+
+ kmi = WM_keymap_add_item(keymap, "GPENCIL_OT_select", SELECTMOUSE, KM_PRESS, KM_SHIFT, 0);
+ RNA_boolean_set(kmi->ptr, "extend", true);
+ RNA_boolean_set(kmi->ptr, "toggle", true);
+
+ /* whole stroke select */
+ kmi = WM_keymap_add_item(keymap, "GPENCIL_OT_select", SELECTMOUSE, KM_PRESS, KM_ALT, 0);
+ RNA_boolean_set(kmi->ptr, "entire_strokes", true);
+
+ /* select linked */
+ /* NOTE: While LKEY is redundant, not having it breaks the mode illusion too much */
+ WM_keymap_add_item(keymap, "GPENCIL_OT_select_linked", LKEY, KM_PRESS, 0, 0);
+ WM_keymap_add_item(keymap, "GPENCIL_OT_select_linked", LKEY, KM_PRESS, KM_CTRL, 0);
+
+ /* select more/less */
+ WM_keymap_add_item(keymap, "GPENCIL_OT_select_more", PADPLUSKEY, KM_PRESS, KM_CTRL, 0);
+ WM_keymap_add_item(keymap, "GPENCIL_OT_select_less", PADMINUS, KM_PRESS, KM_CTRL, 0);
+
+
+ /* Editing ----------------------------------------- */
+
+ /* duplicate and move selected points */
+ WM_keymap_add_item(keymap, "GPENCIL_OT_duplicate_move", DKEY, KM_PRESS, KM_SHIFT, 0);
+
+ /* delete */
+ WM_keymap_add_menu(keymap, "VIEW3D_MT_edit_gpencil_delete", XKEY, KM_PRESS, 0, 0);
+ WM_keymap_add_menu(keymap, "VIEW3D_MT_edit_gpencil_delete", DELKEY, KM_PRESS, 0, 0);
+
+ WM_keymap_add_item(keymap, "GPENCIL_OT_dissolve", XKEY, KM_PRESS, KM_CTRL, 0);
+ WM_keymap_add_item(keymap, "GPENCIL_OT_dissolve", DELKEY, KM_PRESS, KM_CTRL, 0);
+
+ /* copy + paste */
+ WM_keymap_add_item(keymap, "GPENCIL_OT_copy", CKEY, KM_PRESS, KM_CTRL, 0);
+ WM_keymap_add_item(keymap, "GPENCIL_OT_paste", VKEY, KM_PRESS, KM_CTRL, 0);
+
+#ifdef __APPLE__
+ WM_keymap_add_item(keymap, "GPENCIL_OT_copy", CKEY, KM_PRESS, KM_OSKEY, 0);
+ WM_keymap_add_item(keymap, "GPENCIL_OT_paste", VKEY, KM_PRESS, KM_OSKEY, 0);
+#endif
+
+ /* Show/Hide */
+ /* NOTE: These are available only in EditMode now, since they clash with general-purpose hotkeys */
+ WM_keymap_add_item(keymap, "GPENCIL_OT_reveal", HKEY, KM_PRESS, KM_ALT, 0);
+
+ kmi = WM_keymap_add_item(keymap, "GPENCIL_OT_hide", HKEY, KM_PRESS, 0, 0);
+ RNA_boolean_set(kmi->ptr, "unselected", false);
+
+ kmi = WM_keymap_add_item(keymap, "GPENCIL_OT_hide", HKEY, KM_PRESS, KM_SHIFT, 0);
+ RNA_boolean_set(kmi->ptr, "unselected", true);
+
+
+ /* Transform Tools */
+ kmi = WM_keymap_add_item(keymap, "TRANSFORM_OT_translate", GKEY, KM_PRESS, 0, 0);
+ RNA_boolean_set(kmi->ptr, "gpencil_strokes", true);
+
+ kmi = WM_keymap_add_item(keymap, "TRANSFORM_OT_translate", EVT_TWEAK_S, KM_ANY, 0, 0);
+ RNA_boolean_set(kmi->ptr, "gpencil_strokes", true);
+
+ kmi = WM_keymap_add_item(keymap, "TRANSFORM_OT_rotate", RKEY, KM_PRESS, 0, 0);
+ RNA_boolean_set(kmi->ptr, "gpencil_strokes", true);
+
+ kmi = WM_keymap_add_item(keymap, "TRANSFORM_OT_resize", SKEY, KM_PRESS, 0, 0);
+ RNA_boolean_set(kmi->ptr, "gpencil_strokes", true);
+
+ kmi = WM_keymap_add_item(keymap, "TRANSFORM_OT_mirror", MKEY, KM_PRESS, KM_CTRL, 0);
+ RNA_boolean_set(kmi->ptr, "gpencil_strokes", true);
+
+ kmi = WM_keymap_add_item(keymap, "TRANSFORM_OT_bend", WKEY, KM_PRESS, KM_SHIFT, 0);
+ RNA_boolean_set(kmi->ptr, "gpencil_strokes", true);
+
+ WM_keymap_add_item(keymap, "TRANSFORM_OT_tosphere", SKEY, KM_PRESS, KM_ALT | KM_SHIFT, 0);
+ RNA_boolean_set(kmi->ptr, "gpencil_strokes", true);
+
+ WM_keymap_add_item(keymap, "TRANSFORM_OT_shear", SKEY, KM_PRESS, KM_ALT | KM_CTRL | KM_SHIFT, 0);
+ RNA_boolean_set(kmi->ptr, "gpencil_strokes", true);
+
+ kmi = WM_keymap_add_item(keymap, "TRANSFORM_OT_transform", SKEY, KM_PRESS, KM_ALT, 0);
+ RNA_enum_set(kmi->ptr, "mode", TFM_GPENCIL_SHRINKFATTEN);
+ RNA_boolean_set(kmi->ptr, "gpencil_strokes", true);
+
+ /* Proportional Editing */
+ ED_keymap_proportional_cycle(keyconf, keymap);
+ ED_keymap_proportional_editmode(keyconf, keymap, true);
+}
+
+/* ==================== */
+
+void ED_keymap_gpencil(wmKeyConfig *keyconf)
+{
+ ed_keymap_gpencil_general(keyconf);
+ ed_keymap_gpencil_editing(keyconf);
}
/* ****************************************** */
@@ -80,18 +247,55 @@ void ED_operatortypes_gpencil(void)
WM_operatortype_append(GPENCIL_OT_draw);
+ /* Editing (Strokes) ------------ */
+
+ WM_operatortype_append(GPENCIL_OT_select);
+ WM_operatortype_append(GPENCIL_OT_select_all);
+ WM_operatortype_append(GPENCIL_OT_select_circle);
+ WM_operatortype_append(GPENCIL_OT_select_border);
+ WM_operatortype_append(GPENCIL_OT_select_lasso);
+
+ WM_operatortype_append(GPENCIL_OT_select_linked);
+ WM_operatortype_append(GPENCIL_OT_select_more);
+ WM_operatortype_append(GPENCIL_OT_select_less);
+
+ WM_operatortype_append(GPENCIL_OT_duplicate);
+ WM_operatortype_append(GPENCIL_OT_delete);
+ WM_operatortype_append(GPENCIL_OT_dissolve);
+ WM_operatortype_append(GPENCIL_OT_copy);
+ WM_operatortype_append(GPENCIL_OT_paste);
+
/* Editing (Buttons) ------------ */
WM_operatortype_append(GPENCIL_OT_data_add);
WM_operatortype_append(GPENCIL_OT_data_unlink);
WM_operatortype_append(GPENCIL_OT_layer_add);
+ WM_operatortype_append(GPENCIL_OT_layer_remove);
+ WM_operatortype_append(GPENCIL_OT_layer_move);
+ WM_operatortype_append(GPENCIL_OT_layer_duplicate);
+
+ WM_operatortype_append(GPENCIL_OT_hide);
+ WM_operatortype_append(GPENCIL_OT_reveal);
WM_operatortype_append(GPENCIL_OT_active_frame_delete);
WM_operatortype_append(GPENCIL_OT_convert);
-
+
/* Editing (Time) --------------- */
}
+void ED_operatormacros_gpencil(void)
+{
+ wmOperatorType *ot;
+ wmOperatorTypeMacro *otmacro;
+
+ ot = WM_operatortype_append_macro("GPENCIL_OT_duplicate_move", "Duplicate Strokes",
+ "Make copies of the selected Grease Pencil strokes and move them",
+ OPTYPE_UNDO | OPTYPE_REGISTER);
+ WM_operatortype_macro_define(ot, "GPENCIL_OT_duplicate");
+ otmacro = WM_operatortype_macro_define(ot, "TRANSFORM_OT_translate");
+ RNA_boolean_set(otmacro->ptr, "gpencil_strokes", true);
+}
+
/* ****************************************** */
diff --git a/source/blender/editors/gpencil/gpencil_paint.c b/source/blender/editors/gpencil/gpencil_paint.c
index afecdd91599..df88da073ca 100644
--- a/source/blender/editors/gpencil/gpencil_paint.c
+++ b/source/blender/editors/gpencil/gpencil_paint.c
@@ -27,6 +27,7 @@
* \ingroup edgpencil
*/
+
#include <stdio.h>
#include <stddef.h>
#include <stdlib.h>
@@ -39,7 +40,7 @@
#include "BLI_math.h"
#include "BLI_utildefines.h"
-#include "BLF_translation.h"
+#include "BLT_translation.h"
#include "PIL_time.h"
@@ -47,6 +48,7 @@
#include "BKE_context.h"
#include "BKE_global.h"
#include "BKE_report.h"
+#include "BKE_screen.h"
#include "BKE_tracking.h"
#include "DNA_object_types.h"
@@ -86,11 +88,13 @@ typedef struct tGPsdata {
rctf *subrect; /* for using the camera rect within the 3d view */
rctf subrect_data;
+ GP_SpaceConversion gsc; /* settings to pass to gp_points_to_xy() */
+
PointerRNA ownerPtr; /* pointer to owner of gp-datablock */
bGPdata *gpd; /* gp-datablock layer comes from */
bGPDlayer *gpl; /* layer we're working on */
bGPDframe *gpf; /* frame we're working on */
-
+
short status; /* current status of painting */
short paintmode; /* mode for painting */
@@ -110,9 +114,10 @@ typedef struct tGPsdata {
double inittime; /* Used when converting to path */
double curtime; /* Used when converting to path */
double ocurtime; /* Used when converting to path */
-
+
float imat[4][4]; /* inverted transformation matrix applying when converting coords from screen-space
* to region space */
+ float mat[4][4];
float custom_color[4]; /* custom color - hack for enforcing a particular color for track/mask editing */
@@ -218,7 +223,7 @@ static void gp_get_3d_reference(tGPsdata *p, float vec[3])
if (p->ownerPtr.type == &RNA_Object) {
Object *ob = (Object *)p->ownerPtr.data;
- /* active Object
+ /* active Object
* - use relative distance of 3D-cursor from object center
*/
sub_v3_v3v3(vec, fp, ob->loc);
@@ -243,13 +248,13 @@ static bool gp_stroke_filtermval(tGPsdata *p, const int mval[2], int pmval[2])
if (p->gpd->sbuffer_size == 0)
return true;
- /* check if mouse moved at least certain distance on both axes (best case)
+ /* check if mouse moved at least certain distance on both axes (best case)
* - aims to eliminate some jitter-noise from input when trying to draw straight lines freehand
*/
else if ((dx > MIN_MANHATTEN_PX) && (dy > MIN_MANHATTEN_PX))
return true;
- /* check if the distance since the last point is significant enough
+ /* check if the distance since the last point is significant enough
* - prevents points being added too densely
* - distance here doesn't use sqrt to prevent slowness... we should still be safe from overflows though
*/
@@ -279,7 +284,7 @@ static void gp_stroke_convertcoords(tGPsdata *p, const int mval[2], float out[3]
float rvec[3], dvec[3];
float mval_f[2] = {UNPACK2(mval)};
float zfac;
-
+
/* Current method just converts each point in screen-coordinates to
* 3D-coordinates using the 3D-cursor as reference. In general, this
* works OK, but it could of course be improved.
@@ -291,7 +296,7 @@ static void gp_stroke_convertcoords(tGPsdata *p, const int mval[2], float out[3]
gp_get_3d_reference(p, rvec);
zfac = ED_view3d_calc_zfac(p->ar->regiondata, rvec, NULL);
-
+
if (ED_view3d_project_float_global(p->ar, rvec, mval_prj, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) {
sub_v2_v2v2(mval_f, mval_prj, mval_f);
ED_view3d_win_to_delta(p->ar, mval_f, dvec, zfac);
@@ -327,7 +332,7 @@ static short gp_stroke_addpoint(tGPsdata *p, const int mval[2], float pressure,
{
bGPdata *gpd = p->gpd;
tGPspoint *pt;
-
+
/* check painting mode */
if (p->paintmode == GP_PAINTMODE_DRAW_STRAIGHT) {
/* straight lines only - i.e. only store start and end point in buffer */
@@ -337,29 +342,25 @@ static short gp_stroke_addpoint(tGPsdata *p, const int mval[2], float pressure,
/* store settings */
copy_v2_v2_int(&pt->x, mval);
- pt->pressure = pressure;
+ pt->pressure = 1.0f; /* T44932 - Pressure vals are unreliable, so ignore for now */
pt->time = (float)(curtime - p->inittime);
/* increment buffer size */
gpd->sbuffer_size++;
}
else {
- /* normally, we just reset the endpoint to the latest value
+ /* just reset the endpoint to the latest value
* - assume that pointers for this are always valid...
*/
pt = ((tGPspoint *)(gpd->sbuffer) + 1);
/* store settings */
copy_v2_v2_int(&pt->x, mval);
- pt->pressure = pressure;
+ pt->pressure = 1.0f; /* T44932 - Pressure vals are unreliable, so ignore for now */
pt->time = (float)(curtime - p->inittime);
- /* if this is just the second point we've added, increment the buffer size
- * so that it will be drawn properly...
- * otherwise, just leave it alone, otherwise we get problems
- */
- if (gpd->sbuffer_size != 2)
- gpd->sbuffer_size = 2;
+ /* now the buffer has 2 points (and shouldn't be allowed to get any larger) */
+ gpd->sbuffer_size = 2;
}
/* can keep carrying on this way :) */
@@ -393,7 +394,7 @@ static short gp_stroke_addpoint(tGPsdata *p, const int mval[2], float pressure,
/* store settings */
copy_v2_v2_int(&pt->x, mval);
- pt->pressure = pressure;
+ pt->pressure = 1.0f; /* T44932 - Pressure vals are unreliable, so ignore for now */
pt->time = (float)(curtime - p->inittime);
/* if there's stroke for this poly line session add (or replace last) point
@@ -438,7 +439,7 @@ static short gp_stroke_addpoint(tGPsdata *p, const int mval[2], float pressure,
return GP_STROKEADD_NORMAL;
}
-
+
/* return invalid state for now... */
return GP_STROKEADD_INVALID;
}
@@ -458,12 +459,12 @@ static void gp_stroke_smooth(tGPsdata *p)
if ((cmx <= 2) || (gpd->sbuffer == NULL))
return;
- /* Calculate smoothing coordinates using weighted-averages
+ /* Calculate smoothing coordinates using weighted-averages
* WARNING: we do NOT smooth first and last points (to avoid shrinkage)
*/
spt = (tGPspoint *)gpd->sbuffer;
- /* This (tmp_spt) small array stores the last two points' original coordinates,
+ /* This (tmp_spt) small array stores the last two points' original coordinates,
* as we don't want to use already averaged ones! It is used as a cyclic buffer...
*/
tmp_spt[0] = *spt;
@@ -482,7 +483,7 @@ static void gp_stroke_smooth(tGPsdata *p)
}
}
-/* simplify a stroke (in buffer) before storing it
+/* simplify a stroke (in buffer) before storing it
* - applies a reverse Chaikin filter
* - code adapted from etch-a-ton branch (editarmature_sketch.c)
*/
@@ -502,7 +503,7 @@ static void gp_stroke_simplify(tGPsdata *p)
if ((num_points <= 4) || (old_points == NULL))
return;
- /* clear buffer (but don't free mem yet) so that we can write to it
+ /* clear buffer (but don't free mem yet) so that we can write to it
* - firstly set sbuffer to NULL, so a new one is allocated
* - secondly, reset flag after, as it gets cleared auto
*/
@@ -569,7 +570,7 @@ static void gp_stroke_newfrombuffer(tGPsdata *p)
/* since strokes are so fine, when using their depth we need a margin otherwise they might get missed */
int depth_margin = (p->gpd->flag & GP_DATA_DEPTH_STROKE) ? 4 : 0;
- /* get total number of points to allocate space for
+ /* get total number of points to allocate space for
* - drawing straight-lines only requires the endpoints
*/
if (p->paintmode == GP_PAINTMODE_DRAW_STRAIGHT)
@@ -625,7 +626,7 @@ static void gp_stroke_newfrombuffer(tGPsdata *p)
pt++;
}
-
+
if (totelem == 2) {
/* last point if applicable */
ptc = ((tGPspoint *)gpd->sbuffer) + (gpd->sbuffer_size - 1);
@@ -746,7 +747,7 @@ static short gp_stroke_eraser_splitdel(bGPDframe *gpf, bGPDstroke *gps, int i)
/* free stroke points, then stroke */
MEM_freeN(pt_tmp);
BLI_freelinkN(&gpf->strokes, gps);
-
+
/* nothing left in stroke, so stop */
return 1;
}
@@ -755,7 +756,7 @@ static short gp_stroke_eraser_splitdel(bGPDframe *gpf, bGPDstroke *gps, int i)
else if (i == gps->totpoints - 2) {
/* allocate new points array, and assign most of the old stroke there */
gps->totpoints--;
- gps->points = MEM_callocN(sizeof(bGPDspoint) * gps->totpoints, "gp_stroke_points");
+ gps->points = MEM_mallocN(sizeof(bGPDspoint) * gps->totpoints, "gp_stroke_points");
memcpy(gps->points, pt_tmp, sizeof(bGPDspoint) * gps->totpoints);
/* free temp buffer */
@@ -769,7 +770,7 @@ static short gp_stroke_eraser_splitdel(bGPDframe *gpf, bGPDstroke *gps, int i)
else if (i == 0) {
/* allocate new points array, and assign most of the old stroke there */
gps->totpoints--;
- gps->points = MEM_callocN(sizeof(bGPDspoint) * gps->totpoints, "gp_stroke_points");
+ gps->points = MEM_mallocN(sizeof(bGPDspoint) * gps->totpoints, "gp_stroke_points");
memcpy(gps->points, pt_tmp + 1, sizeof(bGPDspoint) * gps->totpoints);
/* We must adjust timings!
@@ -806,7 +807,7 @@ static short gp_stroke_eraser_splitdel(bGPDframe *gpf, bGPDstroke *gps, int i)
BLI_insertlinkafter(&gpf->strokes, gps, gsn);
gsn->totpoints = gps->totpoints - i;
- gsn->points = MEM_callocN(sizeof(bGPDspoint) * gsn->totpoints, "gp_stroke_points");
+ gsn->points = MEM_mallocN(sizeof(bGPDspoint) * gsn->totpoints, "gp_stroke_points");
memcpy(gsn->points, pt_tmp + i, sizeof(bGPDspoint) * gsn->totpoints);
/* We must adjust timings of this new stroke!
@@ -830,8 +831,8 @@ static short gp_stroke_eraser_splitdel(bGPDframe *gpf, bGPDstroke *gps, int i)
/* adjust existing stroke */
gps->totpoints = i;
- gps->points = MEM_callocN(sizeof(bGPDspoint) * gps->totpoints, "gp_stroke_points");
- memcpy(gps->points, pt_tmp, sizeof(bGPDspoint) * i);
+ gps->points = MEM_mallocN(sizeof(bGPDspoint) * gps->totpoints, "gp_stroke_points");
+ memcpy(gps->points, pt_tmp, sizeof(bGPDspoint) * gps->totpoints);
/* free temp buffer */
MEM_freeN(pt_tmp);
@@ -852,8 +853,7 @@ static float view3d_point_depth(const RegionView3D *rv3d, const float co[3])
}
}
-static bool gp_stroke_eraser_is_occluded(tGPsdata *p,
- const bGPDspoint *pt, const int x, const int y)
+static bool gp_stroke_eraser_is_occluded(tGPsdata *p, const bGPDspoint *pt, const int x, const int y)
{
if ((p->sa->spacetype == SPACE_VIEW3D) &&
(p->flags & GP_PAINTFLAG_V3D_ERASER_DEPTH))
@@ -861,11 +861,11 @@ static bool gp_stroke_eraser_is_occluded(tGPsdata *p,
RegionView3D *rv3d = p->ar->regiondata;
const int mval[2] = {x, y};
float mval_3d[3];
-
+
if (ED_view3d_autodist_simple(p->ar, mval, mval_3d, 0, NULL)) {
const float depth_mval = view3d_point_depth(rv3d, mval_3d);
const float depth_pt = view3d_point_depth(rv3d, &pt->x);
-
+
if (depth_pt > depth_mval) {
return true;
}
@@ -874,53 +874,6 @@ static bool gp_stroke_eraser_is_occluded(tGPsdata *p,
return false;
}
-/* eraser tool - check if part of stroke occurs within last segment drawn by eraser */
-static short gp_stroke_eraser_strokeinside(const int mval[2], const int UNUSED(mvalo[2]),
- int rad, int x0, int y0, int x1, int y1)
-{
- /* simple within-radius check for now */
- const float mval_fl[2] = {mval[0], mval[1]};
- const float screen_co_a[2] = {x0, y0};
- const float screen_co_b[2] = {x1, y1};
-
- if (edge_inside_circle(mval_fl, rad, screen_co_a, screen_co_b)) {
- return true;
- }
-
- /* not inside */
- return false;
-}
-
-static void gp_point_to_xy(ARegion *ar, View2D *v2d, rctf *subrect, bGPDstroke *gps, bGPDspoint *pt,
- int *r_x, int *r_y)
-{
- int xyval[2];
-
- if (gps->flag & GP_STROKE_3DSPACE) {
- if (ED_view3d_project_int_global(ar, &pt->x, xyval, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) {
- *r_x = xyval[0];
- *r_y = xyval[1];
- }
- else {
- *r_x = V2D_IS_CLIPPED;
- *r_y = V2D_IS_CLIPPED;
- }
- }
- else if (gps->flag & GP_STROKE_2DSPACE) {
- UI_view2d_view_to_region_clip(v2d, pt->x, pt->y, r_x, r_y);
- }
- else {
- if (subrect == NULL) { /* normal 3D view */
- *r_x = (int)(pt->x / 100 * ar->winx);
- *r_y = (int)(pt->y / 100 * ar->winy);
- }
- else { /* camera view, use subrect */
- *r_x = (int)((pt->x / 100) * BLI_rctf_size_x(subrect)) + subrect->xmin;
- *r_y = (int)((pt->y / 100) * BLI_rctf_size_y(subrect)) + subrect->ymin;
- }
- }
-}
-
/* eraser tool - evaluation per stroke */
/* TODO: this could really do with some optimization (KD-Tree/BVH?) */
@@ -934,12 +887,12 @@ static void gp_stroke_eraser_dostroke(tGPsdata *p,
if (gps->totpoints == 0) {
/* just free stroke */
- if (gps->points)
+ if (gps->points)
MEM_freeN(gps->points);
BLI_freelinkN(&gpf->strokes, gps);
}
else if (gps->totpoints == 1) {
- gp_point_to_xy(p->ar, p->v2d, p->subrect, gps, gps->points, &x0, &y0);
+ gp_point_to_xy(&p->gsc, gps, gps->points, &x0, &y0);
/* do boundbox check first */
if ((!ELEM(V2D_IS_CLIPPED, x0, y0)) && BLI_rcti_isect_pt(rect, x0, y0)) {
@@ -952,7 +905,7 @@ static void gp_stroke_eraser_dostroke(tGPsdata *p,
}
}
else {
- /* loop over the points in the stroke, checking for intersections
+ /* loop over the points in the stroke, checking for intersections
* - an intersection will require the stroke to be split
*/
for (i = 0; (i + 1) < gps->totpoints; i++) {
@@ -960,8 +913,8 @@ static void gp_stroke_eraser_dostroke(tGPsdata *p,
pt1 = gps->points + i;
pt2 = gps->points + i + 1;
- gp_point_to_xy(p->ar, p->v2d, p->subrect, gps, pt1, &x0, &y0);
- gp_point_to_xy(p->ar, p->v2d, p->subrect, gps, pt2, &x1, &y1);
+ gp_point_to_xy(&p->gsc, gps, pt1, &x0, &y0);
+ gp_point_to_xy(&p->gsc, gps, pt2, &x1, &y1);
/* check that point segment of the boundbox of the eraser stroke */
if (((!ELEM(V2D_IS_CLIPPED, x0, y0)) && BLI_rcti_isect_pt(rect, x0, y0)) ||
@@ -971,7 +924,7 @@ static void gp_stroke_eraser_dostroke(tGPsdata *p,
* eraser region (either within stroke painted, or on its lines)
* - this assumes that linewidth is irrelevant
*/
- if (gp_stroke_eraser_strokeinside(mval, mvalo, rad, x0, y0, x1, y1)) {
+ if (gp_stroke_inside_circle(mval, mvalo, rad, x0, y0, x1, y1)) {
if ((gp_stroke_eraser_is_occluded(p, pt1, x0, y0) == false) ||
(gp_stroke_eraser_is_occluded(p, pt2, x1, y1) == false))
{
@@ -997,16 +950,16 @@ static void gp_stroke_doeraser(tGPsdata *p)
rect.ymin = p->mval[1] - p->radius;
rect.xmax = p->mval[0] + p->radius;
rect.ymax = p->mval[1] + p->radius;
-
+
if (p->sa->spacetype == SPACE_VIEW3D) {
if (p->flags & GP_PAINTFLAG_V3D_ERASER_DEPTH) {
View3D *v3d = p->sa->spacedata.first;
-
+
view3d_region_operator_needs_opengl(p->win, p->ar);
ED_view3d_autodist_init(p->scene, p->ar, v3d, 0);
}
}
-
+
/* loop over strokes, checking segments for intersections */
for (gps = gpf->strokes.first; gps; gps = gpn) {
gpn = gps->next;
@@ -1037,13 +990,13 @@ static void gp_session_validatebuffer(tGPsdata *p)
/* reset flags */
gpd->sbuffer_sflag = 0;
-
+
/* reset inittime */
p->inittime = 0.0;
}
/* (re)init new painting data */
-static int gp_session_initdata(bContext *C, tGPsdata *p)
+static bool gp_session_initdata(bContext *C, tGPsdata *p)
{
bGPdata **gpd_ptr = NULL;
ScrArea *curarea = CTX_wm_area(C);
@@ -1060,8 +1013,9 @@ static int gp_session_initdata(bContext *C, tGPsdata *p)
/* pass on current scene and window */
p->scene = CTX_data_scene(C);
p->win = CTX_wm_window(C);
-
+
unit_m4(p->imat);
+ unit_m4(p->mat);
switch (curarea->spacetype) {
/* supported views first */
@@ -1070,9 +1024,10 @@ static int gp_session_initdata(bContext *C, tGPsdata *p)
/* View3D *v3d = curarea->spacedata.first; */
/* RegionView3D *rv3d = ar->regiondata; */
- /* set current area
+ /* set current area
* - must verify that region data is 3D-view (and not something else)
*/
+ /* CAUTION: If this is the "toolbar", then this will change on the first stroke */
p->sa = curarea;
p->ar = ar;
@@ -1125,7 +1080,13 @@ static int gp_session_initdata(bContext *C, tGPsdata *p)
case SPACE_CLIP:
{
SpaceClip *sc = curarea->spacedata.first;
+ MovieClip *clip = ED_space_clip_get_clip(sc);
+ if (clip == NULL) {
+ p->status = GP_STATUS_ERROR;
+ return false;
+ }
+
/* set the current area */
p->sa = curarea;
p->ar = ar;
@@ -1140,14 +1101,22 @@ static int gp_session_initdata(bContext *C, tGPsdata *p)
p->custom_color[3] = 0.9f;
if (sc->gpencil_src == SC_GPENCIL_SRC_TRACK) {
- MovieClip *clip = ED_space_clip_get_clip(sc);
int framenr = ED_space_clip_get_clip_frame_number(sc);
MovieTrackingTrack *track = BKE_tracking_track_get_active(&clip->tracking);
- MovieTrackingMarker *marker = BKE_tracking_marker_get(track, framenr);
-
- p->imat[3][0] -= marker->pos[0];
- p->imat[3][1] -= marker->pos[1];
+ MovieTrackingMarker *marker = track ? BKE_tracking_marker_get(track, framenr) : NULL;
+
+ if (marker) {
+ p->imat[3][0] -= marker->pos[0];
+ p->imat[3][1] -= marker->pos[1];
+ }
+ else {
+ p->status = GP_STATUS_ERROR;
+ return false;
+ }
}
+
+ invert_m4_m4(p->mat, p->imat);
+ copy_m4_m4(p->gsc.mat, p->mat);
break;
}
/* unsupported views */
@@ -1192,10 +1161,10 @@ static int gp_session_initdata(bContext *C, tGPsdata *p)
static tGPsdata *gp_session_initpaint(bContext *C)
{
tGPsdata *p = NULL;
-
+
/* create new context data */
p = MEM_callocN(sizeof(tGPsdata), "GPencil Drawing Data");
-
+
gp_session_initdata(C, p);
/* return context data for running paint operator */
@@ -1226,7 +1195,7 @@ static void gp_session_cleanup(tGPsdata *p)
/* init new stroke */
static void gp_paint_initstroke(tGPsdata *p, short paintmode)
-{
+{
/* get active layer (or add a new one if non-existent) */
p->gpl = gpencil_layer_getactive(p->gpd);
if (p->gpl == NULL) {
@@ -1241,7 +1210,7 @@ static void gp_paint_initstroke(tGPsdata *p, short paintmode)
printf("Error: Cannot paint on locked layer\n");
return;
}
-
+
/* get active frame (add a new one if not matching frame) */
p->gpf = gpencil_layer_getframe(p->gpl, p->scene->r.cfra, 1);
if (p->gpf == NULL) {
@@ -1257,7 +1226,7 @@ static void gp_paint_initstroke(tGPsdata *p, short paintmode)
p->paintmode = paintmode;
if (p->paintmode == GP_PAINTMODE_ERASER) {
p->gpd->sbuffer_sflag |= GP_STROKE_ERASER;
-
+
/* check if we should respect depth while erasing */
if (p->sa->spacetype == SPACE_VIEW3D) {
if (p->gpl->flag & GP_LAYER_NO_XRAY) {
@@ -1265,12 +1234,23 @@ static void gp_paint_initstroke(tGPsdata *p, short paintmode)
}
}
}
-
+ else {
+ /* disable eraser flags - so that we can switch modes during a session */
+ p->gpd->sbuffer_sflag &= ~GP_STROKE_ERASER;
+
+ if (p->sa->spacetype == SPACE_VIEW3D) {
+ if (p->gpl->flag & GP_LAYER_NO_XRAY) {
+ p->flags &= ~GP_PAINTFLAG_V3D_ERASER_DEPTH;
+ }
+ }
+ }
+
/* set 'initial run' flag, which is only used to denote when a new stroke is starting */
p->flags |= GP_PAINTFLAG_FIRSTRUN;
-
+
/* when drawing in the camera view, in 2D space, set the subrect */
+ p->subrect = NULL;
if (!(p->gpd->flag & GP_DATA_VIEWALIGN)) {
if (p->sa->spacetype == SPACE_VIEW3D) {
View3D *v3d = p->sa->spacedata.first;
@@ -1283,7 +1263,21 @@ static void gp_paint_initstroke(tGPsdata *p, short paintmode)
}
}
}
-
+
+ /* init stroke point space-conversion settings... */
+ p->gsc.gpd = p->gpd;
+ p->gsc.gpl = p->gpl;
+
+ p->gsc.sa = p->sa;
+ p->gsc.ar = p->ar;
+ p->gsc.v2d = p->v2d;
+
+ p->gsc.subrect_data = p->subrect_data;
+ p->gsc.subrect = p->subrect;
+
+ copy_m4_m4(p->gsc.mat, p->mat);
+
+
/* check if points will need to be made in view-aligned space */
if (p->gpd->flag & GP_DATA_VIEWALIGN) {
switch (p->sa->spacetype) {
@@ -1333,7 +1327,7 @@ static void gp_paint_initstroke(tGPsdata *p, short paintmode)
/* finish off a stroke (clears buffer, but doesn't finish the paint operation) */
static void gp_paint_strokeend(tGPsdata *p)
{
- /* for surface sketching, need to set the right OpenGL context stuff so that
+ /* for surface sketching, need to set the right OpenGL context stuff so that
* the conversions will project the values correctly...
*/
if (gpencil_project_check(p)) {
@@ -1388,13 +1382,18 @@ static void gpencil_draw_eraser(bContext *UNUSED(C), int x, int y, void *p_ptr)
glTranslatef((float)x, (float)y, 0.0f);
- glColor4ub(255, 255, 255, 128);
-
glEnable(GL_LINE_SMOOTH);
glEnable(GL_BLEND);
+ glColor4ub(255, 100, 100, 20);
+ glutil_draw_filled_arc(0.0, M_PI * 2.0, p->radius, 40);
+
+ setlinestyle(6);
+
+ glColor4ub(255, 100, 100, 200);
glutil_draw_lined_arc(0.0, M_PI * 2.0, p->radius, 40);
+ setlinestyle(0);
glDisable(GL_BLEND);
glDisable(GL_LINE_SMOOTH);
@@ -1410,9 +1409,9 @@ static void gpencil_draw_toggle_eraser_cursor(bContext *C, tGPsdata *p, short en
WM_paint_cursor_end(CTX_wm_manager(C), p->erasercursor);
p->erasercursor = NULL;
}
- else if (enable) {
+ else if (enable && !p->erasercursor) {
/* enable cursor */
- p->erasercursor = WM_paint_cursor_activate(CTX_wm_manager(C),
+ p->erasercursor = WM_paint_cursor_activate(CTX_wm_manager(C),
NULL, /* XXX */
gpencil_draw_eraser, p);
}
@@ -1437,12 +1436,14 @@ static void gpencil_draw_exit(bContext *C, wmOperator *op)
if (p->paintmode == GP_PAINTMODE_ERASER) {
/* turn off radial brush cursor */
gpencil_draw_toggle_eraser_cursor(C, p, false);
-
- /* if successful, store the new eraser size to be used again next time */
- if (p->status == GP_STATUS_DONE)
- U.gp_eraser = p->radius;
}
+ /* always store the new eraser size to be used again next time
+ * NOTE: Do this even when not in eraser mode, as eraser may
+ * have been toggled at some point.
+ */
+ U.gp_eraser = p->radius;
+
/* cleanup */
gp_paint_cleanup(p);
gp_session_cleanup(p);
@@ -1493,6 +1494,15 @@ static int gpencil_draw_init(bContext *C, wmOperator *op)
/* ------------------------------- */
+/* ensure that the correct cursor icon is set */
+static void gpencil_draw_cursor_set(tGPsdata *p)
+{
+ if (p->paintmode == GP_PAINTMODE_ERASER)
+ WM_cursor_modal_set(p->win, BC_CROSSCURSOR); /* XXX need a better cursor */
+ else
+ WM_cursor_modal_set(p->win, BC_PAINTBRUSHCURSOR);
+}
+
/* update UI indicators of status, including cursor and header prints */
static void gpencil_draw_status_indicators(tGPsdata *p)
{
@@ -1519,13 +1529,13 @@ static void gpencil_draw_status_indicators(tGPsdata *p)
ED_area_headerprint(p->sa, IFACE_("Grease Pencil Freehand Session: Hold and drag LMB to draw | "
"ESC/Enter to end"));
break;
-
+
default: /* unhandled future cases */
ED_area_headerprint(p->sa, IFACE_("Grease Pencil Session: ESC/Enter to end"));
break;
}
break;
-
+
case GP_STATUS_ERROR:
case GP_STATUS_DONE:
/* clear status string */
@@ -1608,7 +1618,7 @@ static void gpencil_draw_apply_event(wmOperator *op, const wmEvent *event)
/* handle pressure sensitivity (which is supplied by tablets) */
if (event->tablet_data) {
- wmTabletData *wmtab = event->tablet_data;
+ const wmTabletData *wmtab = event->tablet_data;
tablet = (wmtab->Active != EVT_TABLET_NONE);
p->pressure = wmtab->Pressure;
@@ -1619,15 +1629,6 @@ static void gpencil_draw_apply_event(wmOperator *op, const wmEvent *event)
else
p->pressure = 1.0f;
- /* fill in stroke data (not actually used directly by gpencil_draw_apply) */
- RNA_collection_add(op->ptr, "stroke", &itemptr);
-
- mousef[0] = p->mval[0];
- mousef[1] = p->mval[1];
- RNA_float_set_array(&itemptr, "mouse", mousef);
- RNA_float_set(&itemptr, "pressure", p->pressure);
- RNA_boolean_set(&itemptr, "is_start", (p->flags & GP_PAINTFLAG_FIRSTRUN));
-
/* special exception for start of strokes (i.e. maybe for just a dot) */
if (p->flags & GP_PAINTFLAG_FIRSTRUN) {
p->flags &= ~GP_PAINTFLAG_FIRSTRUN;
@@ -1644,6 +1645,15 @@ static void gpencil_draw_apply_event(wmOperator *op, const wmEvent *event)
return;
}
+ /* fill in stroke data (not actually used directly by gpencil_draw_apply) */
+ RNA_collection_add(op->ptr, "stroke", &itemptr);
+
+ mousef[0] = p->mval[0];
+ mousef[1] = p->mval[1];
+ RNA_float_set_array(&itemptr, "mouse", mousef);
+ RNA_float_set(&itemptr, "pressure", p->pressure);
+ RNA_boolean_set(&itemptr, "is_start", (p->flags & GP_PAINTFLAG_FIRSTRUN) != 0);
+
RNA_float_set(&itemptr, "time", p->curtime - p->inittime);
/* apply the current latest drawing point */
@@ -1714,7 +1724,7 @@ static int gpencil_draw_exec(bContext *C, wmOperator *op)
gpencil_draw_apply(op, p);
}
RNA_END;
-
+
/* printf("\tGP - done\n"); */
/* cleanup */
@@ -1733,14 +1743,13 @@ static int gpencil_draw_exec(bContext *C, wmOperator *op)
static int gpencil_draw_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
tGPsdata *p = NULL;
- wmWindow *win = CTX_wm_window(C);
if (G.debug & G_DEBUG)
printf("GPencil - Starting Drawing\n");
/* try to initialize context data needed while drawing */
if (!gpencil_draw_init(C, op)) {
- if (op->customdata)
+ if (op->customdata)
MEM_freeN(op->customdata);
if (G.debug & G_DEBUG)
printf("\tGP - no valid data\n");
@@ -1748,28 +1757,25 @@ static int gpencil_draw_invoke(bContext *C, wmOperator *op, const wmEvent *event
}
else
p = op->customdata;
-
+
/* TODO: set any additional settings that we can take from the events?
* TODO? if tablet is erasing, force eraser to be on? */
-
+
/* TODO: move cursor setting stuff to stroke-start so that paintmode can be changed midway... */
-
+
/* if eraser is on, draw radial aid */
if (p->paintmode == GP_PAINTMODE_ERASER) {
gpencil_draw_toggle_eraser_cursor(C, p, true);
}
- /* set cursor */
- if (p->paintmode == GP_PAINTMODE_ERASER)
- WM_cursor_modal_set(win, BC_CROSSCURSOR); /* XXX need a better cursor */
- else
- WM_cursor_modal_set(win, BC_PAINTBRUSHCURSOR);
-
- /* special hack: if there was an initial event, then we were invoked via a hotkey, and
- * painting should start immediately. Otherwise, this was called from a toolbar, in which
- * case we should wait for the mouse to be clicked.
+ /* set cursor
+ * NOTE: This may change later (i.e. intentionally via brush toggle,
+ * or unintentionally if the user scrolls outside the area)...
*/
- if (event->val == KM_PRESS) {
+ gpencil_draw_cursor_set(p);
+
+ /* only start drawing immediately if we're allowed to do so... */
+ if (RNA_boolean_get(op->ptr, "wait_for_input") == false) {
/* hotkey invoked - start drawing */
/* printf("\tGP - set first spot\n"); */
p->status = GP_STATUS_PAINTING;
@@ -1780,6 +1786,7 @@ static int gpencil_draw_invoke(bContext *C, wmOperator *op, const wmEvent *event
else {
/* toolbar invoked - don't start drawing yet... */
/* printf("\tGP - hotkey invoked... waiting for click-drag\n"); */
+ op->flag |= OP_IS_MODAL_CURSOR_REGION;
}
WM_event_add_notifier(C, NC_GPENCIL | NA_EDITED, NULL);
@@ -1817,8 +1824,10 @@ static tGPsdata *gpencil_stroke_begin(bContext *C, wmOperator *op)
if (gp_session_initdata(C, p))
gp_paint_initstroke(p, p->paintmode);
- if (p->status != GP_STATUS_ERROR)
+ if (p->status != GP_STATUS_ERROR) {
p->status = GP_STATUS_PAINTING;
+ op->flag &= ~OP_IS_MODAL_CURSOR_REGION;
+ }
return op->customdata;
}
@@ -1826,15 +1835,16 @@ static tGPsdata *gpencil_stroke_begin(bContext *C, wmOperator *op)
static void gpencil_stroke_end(wmOperator *op)
{
tGPsdata *p = op->customdata;
-
+
gp_paint_cleanup(p);
-
+
gpencil_undo_push(p->gpd);
-
+
gp_session_cleanup(p);
-
+
p->status = GP_STATUS_IDLING;
-
+ op->flag |= OP_IS_MODAL_CURSOR_REGION;
+
p->gpd = NULL;
p->gpl = NULL;
p->gpf = NULL;
@@ -1858,11 +1868,19 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, const wmEvent *event)
* better in tools that immediately apply
* in 3D space.
*/
+
+ if (p->status == GP_STATUS_IDLING) {
+ ARegion *ar = CTX_wm_region(C);
+ p->ar = ar;
+ }
/* we don't pass on key events, GP is used with key-modifiers - prevents Dkey to insert drivers */
if (ISKEYBOARD(event->type)) {
- if (ELEM(event->type, LEFTARROWKEY, DOWNARROWKEY, RIGHTARROWKEY, UPARROWKEY)) {
- /* allow some keys - for frame changing: [#33412] */
+ if (ELEM(event->type, LEFTARROWKEY, DOWNARROWKEY, RIGHTARROWKEY, UPARROWKEY, ZKEY)) {
+ /* allow some keys:
+ * - for frame changing [#33412]
+ * - for undo (during sketching sessions)
+ */
}
else {
estate = OPERATOR_RUNNING_MODAL;
@@ -1871,7 +1889,7 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, const wmEvent *event)
//printf("\tGP - handle modal event...\n");
- /* exit painting mode (and/or end current stroke)
+ /* exit painting mode (and/or end current stroke)
* NOTE: cannot do RIGHTMOUSE (as is standard for canceling) as that would break polyline [#32647]
*/
if (ELEM(event->type, RETKEY, PADENTER, ESCKEY, SPACEKEY)) {
@@ -1881,17 +1899,18 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, const wmEvent *event)
estate = OPERATOR_FINISHED;
}
- /* toggle painting mode upon mouse-button movement
+ /* toggle painting mode upon mouse-button movement
* - LEFTMOUSE = standard drawing (all) / straight line drawing (all) / polyline (toolbox only)
* - RIGHTMOUSE = polyline (hotkey) / eraser (all)
* (Disabling RIGHTMOUSE case here results in bugs like [#32647])
+ * also making sure we have a valid event value, to not exit too early
*/
- if (ELEM(event->type, LEFTMOUSE, RIGHTMOUSE)) {
+ if (ELEM(event->type, LEFTMOUSE, RIGHTMOUSE) && (event->val != KM_NOTHING)) {
/* if painting, end stroke */
if (p->status == GP_STATUS_PAINTING) {
int sketch = 0;
- /* basically, this should be mouse-button up = end stroke
+ /* basically, this should be mouse-button up = end stroke
* BUT what happens next depends on whether we 'painting sessions' is enabled
*/
sketch |= GPENCIL_SKETCH_SESSIONS_ON(p->scene);
@@ -1903,6 +1922,27 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, const wmEvent *event)
/* printf("\t\tGP - end stroke only\n"); */
gpencil_stroke_end(op);
+ /* If eraser mode is on, turn it off after the stroke finishes
+ * NOTE: This just makes it nicer to work with drawing sessions
+ */
+ if (p->paintmode == GP_PAINTMODE_ERASER) {
+ p->paintmode = RNA_enum_get(op->ptr, "mode");
+
+ /* if the original mode was *still* eraser,
+ * we'll let it say for now, since this gives
+ * users an opportunity to have visual feedback
+ * when adjusting eraser size
+ */
+ if (p->paintmode != GP_PAINTMODE_ERASER) {
+ /* turn off cursor...
+ * NOTE: this should be enough for now
+ * Just hiding this makes it seem like
+ * you can paint again...
+ */
+ gpencil_draw_toggle_eraser_cursor(C, p, false);
+ }
+ }
+
/* we've just entered idling state, so this event was processed (but no others yet) */
estate = OPERATOR_RUNNING_MODAL;
@@ -1916,15 +1956,88 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, const wmEvent *event)
}
}
else if (event->val == KM_PRESS) {
- /* not painting, so start stroke (this should be mouse-button down) */
- p = gpencil_stroke_begin(C, op);
+ bool in_bounds = false;
- if (p->status == GP_STATUS_ERROR) {
+ /* Check if we're outside the bounds of the active region
+ * NOTE: An exception here is that if launched from the toolbar,
+ * whatever region we're now in should become the new region
+ */
+ if ((p->ar) && (p->ar->regiontype == RGN_TYPE_TOOLS)) {
+ /* Change to whatever region is now under the mouse */
+ ARegion *current_region = BKE_area_find_region_xy(p->sa, RGN_TYPE_ANY, event->x, event->y);
+
+ if (G.debug & G_DEBUG) {
+ printf("found alternative region %p (old was %p) - at %d %d (sa: %d %d -> %d %d)\n",
+ current_region, p->ar, event->x, event->y,
+ p->sa->totrct.xmin, p->sa->totrct.ymin, p->sa->totrct.xmax, p->sa->totrct.ymax);
+ }
+
+ if (current_region) {
+ /* Assume that since we found the cursor in here, it is in bounds
+ * and that this should be the region that we begin drawing in
+ */
+ p->ar = current_region;
+ in_bounds = true;
+ }
+ else {
+ /* Out of bounds, or invalid in some other way */
+ p->status = GP_STATUS_ERROR;
+ estate = OPERATOR_CANCELLED;
+
+ if (G.debug & G_DEBUG)
+ printf("%s: Region under cursor is out of bounds, so cannot be drawn on\n", __func__);
+ }
+ }
+ else if (p->ar) {
+ rcti region_rect;
+
+ /* Perform bounds check using */
+ ED_region_visible_rect(p->ar, &region_rect);
+ in_bounds = BLI_rcti_isect_pt_v(&region_rect, event->mval);
+ }
+ else {
+ /* No region */
+ p->status = GP_STATUS_ERROR;
estate = OPERATOR_CANCELLED;
+
+ if (G.debug & G_DEBUG)
+ printf("%s: No active region found in GP Paint session data\n", __func__);
+ }
+
+ if (in_bounds) {
+ /* Switch paintmode (temporarily if need be) based on which button was used
+ * NOTE: This is to make it more convenient to erase strokes when using drawing sessions
+ */
+ if (event->type == LEFTMOUSE) {
+ /* restore drawmode to default */
+ p->paintmode = RNA_enum_get(op->ptr, "mode");
+ }
+ else if (event->type == RIGHTMOUSE) {
+ /* turn on eraser */
+ p->paintmode = GP_PAINTMODE_ERASER;
+ }
+
+ gpencil_draw_toggle_eraser_cursor(C, p, p->paintmode == GP_PAINTMODE_ERASER);
+
+ /* not painting, so start stroke (this should be mouse-button down) */
+ p = gpencil_stroke_begin(C, op);
+
+ if (p->status == GP_STATUS_ERROR) {
+ estate = OPERATOR_CANCELLED;
+ }
+ }
+ else if (p->status != GP_STATUS_ERROR) {
+ /* User clicked outside bounds of window while idling, so exit paintmode
+ * NOTE: Don't eter this case if an error occurred while finding the
+ * region (as above)
+ */
+ p->status = GP_STATUS_DONE;
+ estate = OPERATOR_FINISHED;
}
}
else {
p->status = GP_STATUS_IDLING;
+ op->flag |= OP_IS_MODAL_CURSOR_REGION;
}
}
@@ -1960,12 +2073,12 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, const wmEvent *event)
case PADPLUSKEY:
p->radius += 5;
break;
-
+
case WHEELUPMOUSE: /* smaller */
case PADMINUS:
p->radius -= 5;
- if (p->radius < 0)
+ if (p->radius < 0)
p->radius = 0;
break;
}
@@ -1976,7 +2089,7 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, const wmEvent *event)
/* event handled, so just tag as running modal */
estate = OPERATOR_RUNNING_MODAL;
}
- /* there shouldn't be any other events, but just in case there are, let's swallow them
+ /* there shouldn't be any other events, but just in case there are, let's swallow them
* (i.e. to prevent problems with undo)
*/
else {
@@ -1988,9 +2101,11 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, const wmEvent *event)
/* gpencil modal operator stores area, which can be removed while using it (like fullscreen) */
if (0 == gpencil_area_exists(C, p->sa))
estate = OPERATOR_CANCELLED;
- else
+ else {
/* update status indicators - cursor, header, etc. */
gpencil_draw_status_indicators(p);
+ gpencil_draw_cursor_set(p); /* cursor may have changed outside our control - T44084 */
+ }
/* process last operations before exiting */
switch (estate) {
@@ -1999,7 +2114,7 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, const wmEvent *event)
gpencil_draw_exit(C, op);
WM_event_add_notifier(C, NC_GPENCIL | NA_EDITED, NULL);
break;
-
+
case OPERATOR_CANCELLED:
gpencil_draw_exit(C, op);
break;
@@ -2046,6 +2161,8 @@ void GPENCIL_OT_draw(wmOperatorType *ot)
/* settings for drawing */
ot->prop = RNA_def_enum(ot->srna, "mode", prop_gpencil_drawmodes, 0, "Mode", "Way to interpret mouse movements");
-
RNA_def_collection_runtime(ot->srna, "stroke", &RNA_OperatorStrokeElement, "Stroke", "");
+
+ /* NOTE: wait for input is enabled by default, so that all UI code can work properly without needing users to know about this */
+ RNA_def_boolean(ot->srna, "wait_for_input", true, "Wait for Input", "Wait for first click instead of painting immediately");
}
diff --git a/source/blender/editors/gpencil/gpencil_select.c b/source/blender/editors/gpencil/gpencil_select.c
new file mode 100644
index 00000000000..0dd91019a8c
--- /dev/null
+++ b/source/blender/editors/gpencil/gpencil_select.c
@@ -0,0 +1,930 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2014, Blender Foundation
+ * This is a new part of Blender
+ *
+ * Contributor(s): Joshua Leung
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/editors/gpencil/gpencil_select.c
+ * \ingroup edgpencil
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <math.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_lasso.h"
+#include "BLI_utildefines.h"
+#include "BLI_math_vector.h"
+
+#include "DNA_gpencil_types.h"
+#include "DNA_screen_types.h"
+
+#include "BKE_context.h"
+#include "BKE_gpencil.h"
+#include "BKE_report.h"
+
+#include "UI_interface.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+
+#include "UI_view2d.h"
+
+#include "ED_gpencil.h"
+
+#include "gpencil_intern.h"
+
+/* ********************************************** */
+/* Polling callbacks */
+
+static int gpencil_select_poll(bContext *C)
+{
+ bGPdata *gpd = ED_gpencil_data_get_active(C);
+ bGPDlayer *gpl = gpencil_layer_getactive(gpd);
+
+ /* only if there's an active layer with an active frame */
+ return (gpl && gpl->actframe);
+}
+
+/* ********************************************** */
+/* Select All Operator */
+
+static int gpencil_select_all_exec(bContext *C, wmOperator *op)
+{
+ bGPdata *gpd = ED_gpencil_data_get_active(C);
+ int action = RNA_enum_get(op->ptr, "action");
+
+ if (gpd == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "No Grease Pencil data");
+ return OPERATOR_CANCELLED;
+ }
+
+ /* for "toggle", test for existing selected strokes */
+ if (action == SEL_TOGGLE) {
+ action = SEL_SELECT;
+
+ CTX_DATA_BEGIN(C, bGPDstroke *, gps, editable_gpencil_strokes)
+ {
+ if (gps->flag & GP_STROKE_SELECT) {
+ action = SEL_DESELECT;
+ break; // XXX: this only gets out of the inner loop...
+ }
+ }
+ CTX_DATA_END;
+ }
+
+ /* if deselecting, we need to deselect strokes across all frames
+ * - Currently, an exception is only given for deselection
+ * Selecting and toggling should only affect what's visible,
+ * while deselecting helps clean up unintended/forgotten
+ * stuff on other frames
+ */
+ if (action == SEL_DESELECT) {
+ /* deselect strokes across editable layers
+ * NOTE: we limit ourselves to editable layers, since once a layer is "locked/hidden
+ * nothing should be able to touch it
+ */
+ CTX_DATA_BEGIN(C, bGPDlayer *, gpl, editable_gpencil_layers)
+ {
+ bGPDframe *gpf;
+
+ /* deselect all strokes on all frames */
+ for (gpf = gpl->frames.first; gpf; gpf = gpf->next) {
+ bGPDstroke *gps;
+
+ for (gps = gpf->strokes.first; gps; gps = gps->next) {
+ bGPDspoint *pt;
+ int i;
+
+ /* only edit strokes that are valid in this view... */
+ if (ED_gpencil_stroke_can_use(C, gps)) {
+ for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
+ pt->flag &= ~GP_SPOINT_SELECT;
+ }
+
+ gps->flag &= ~GP_STROKE_SELECT;
+ }
+ }
+ }
+ }
+ CTX_DATA_END;
+ }
+ else {
+ /* select or deselect all strokes */
+ CTX_DATA_BEGIN(C, bGPDstroke *, gps, editable_gpencil_strokes)
+ {
+ bGPDspoint *pt;
+ int i;
+ bool selected = false;
+
+ /* Change selection status of all points, then make the stroke match */
+ for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
+ switch (action) {
+ case SEL_SELECT:
+ pt->flag |= GP_SPOINT_SELECT;
+ break;
+ //case SEL_DESELECT:
+ // pt->flag &= ~GP_SPOINT_SELECT;
+ // break;
+ case SEL_INVERT:
+ pt->flag ^= GP_SPOINT_SELECT;
+ break;
+ }
+
+ if (pt->flag & GP_SPOINT_SELECT)
+ selected = true;
+ }
+
+ /* Change status of stroke */
+ if (selected)
+ gps->flag |= GP_STROKE_SELECT;
+ else
+ gps->flag &= ~GP_STROKE_SELECT;
+ }
+ CTX_DATA_END;
+ }
+
+ /* updates */
+ WM_event_add_notifier(C, NC_GPENCIL | NA_SELECTED, NULL);
+ return OPERATOR_FINISHED;
+}
+
+void GPENCIL_OT_select_all(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "(De)select All Strokes";
+ ot->idname = "GPENCIL_OT_select_all";
+ ot->description = "Change selection of all Grease Pencil strokes currently visible";
+
+ /* callbacks */
+ ot->exec = gpencil_select_all_exec;
+ ot->poll = gpencil_select_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ WM_operator_properties_select_all(ot);
+}
+
+/* ********************************************** */
+/* Select Linked */
+
+static int gpencil_select_linked_exec(bContext *C, wmOperator *op)
+{
+ bGPdata *gpd = ED_gpencil_data_get_active(C);
+
+ if (gpd == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "No Grease Pencil data");
+ return OPERATOR_CANCELLED;
+ }
+
+ /* select all points in selected strokes */
+ CTX_DATA_BEGIN(C, bGPDstroke *, gps, editable_gpencil_strokes)
+ {
+ if (gps->flag & GP_STROKE_SELECT) {
+ bGPDspoint *pt;
+ int i;
+
+ for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
+ pt->flag |= GP_SPOINT_SELECT;
+ }
+ }
+ }
+ CTX_DATA_END;
+
+ /* updates */
+ WM_event_add_notifier(C, NC_GPENCIL | NA_SELECTED, NULL);
+ return OPERATOR_FINISHED;
+}
+
+void GPENCIL_OT_select_linked(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Select Linked";
+ ot->idname = "GPENCIL_OT_select_linked";
+ ot->description = "Select all points in same strokes as already selected points";
+
+ /* callbacks */
+ ot->exec = gpencil_select_linked_exec;
+ ot->poll = gpencil_select_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+/* ********************************************** */
+/* Select More */
+
+static int gpencil_select_more_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ CTX_DATA_BEGIN(C, bGPDstroke *, gps, editable_gpencil_strokes)
+ {
+ if (gps->flag & GP_STROKE_SELECT) {
+ bGPDspoint *pt;
+ int i;
+ bool prev_sel;
+
+ /* First Pass: Go in forward order, expanding selection if previous was selected (pre changes)...
+ * - This pass covers the "after" edges of selection islands
+ */
+ prev_sel = false;
+ for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
+ if (pt->flag & GP_SPOINT_SELECT) {
+ /* selected point - just set flag for next point */
+ prev_sel = true;
+ }
+ else {
+ /* unselected point - expand selection if previous was selected... */
+ if (prev_sel) {
+ pt->flag |= GP_SPOINT_SELECT;
+ }
+ prev_sel = false;
+ }
+ }
+
+ /* Second Pass: Go in reverse order, doing the same as before (except in opposite order)
+ * - This pass covers the "before" edges of selection islands
+ */
+ prev_sel = false;
+ for (pt -= 1; i > 0; i--, pt--) {
+ if (pt->flag & GP_SPOINT_SELECT) {
+ prev_sel = true;
+ }
+ else {
+ /* unselected point - expand selection if previous was selected... */
+ if (prev_sel) {
+ pt->flag |= GP_SPOINT_SELECT;
+ }
+ prev_sel = false;
+ }
+ }
+ }
+ }
+ CTX_DATA_END;
+
+ /* updates */
+ WM_event_add_notifier(C, NC_GPENCIL | NA_SELECTED, NULL);
+ return OPERATOR_FINISHED;
+}
+
+void GPENCIL_OT_select_more(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Select More";
+ ot->idname = "GPENCIL_OT_select_more";
+ ot->description = "Grow sets of selected Grease Pencil points";
+
+ /* callbacks */
+ ot->exec = gpencil_select_more_exec;
+ ot->poll = gpencil_select_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+/* ********************************************** */
+/* Select Less */
+
+static int gpencil_select_less_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ CTX_DATA_BEGIN(C, bGPDstroke *, gps, editable_gpencil_strokes)
+ {
+ if (gps->flag & GP_STROKE_SELECT) {
+ bGPDspoint *pt;
+ int i;
+ bool prev_sel;
+
+ /* First Pass: Go in forward order, shrinking selection if previous was not selected (pre changes)...
+ * - This pass covers the "after" edges of selection islands
+ */
+ prev_sel = false;
+ for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
+ if (pt->flag & GP_SPOINT_SELECT) {
+ /* shrink if previous wasn't selected */
+ if (prev_sel == false) {
+ pt->flag &= ~GP_SPOINT_SELECT;
+ }
+ prev_sel = true;
+ }
+ else {
+ /* mark previous as being unselected - and hence, is trigger for shrinking */
+ prev_sel = false;
+ }
+ }
+
+ /* Second Pass: Go in reverse order, doing the same as before (except in opposite order)
+ * - This pass covers the "before" edges of selection islands
+ */
+ prev_sel = false;
+ for (pt -= 1; i > 0; i--, pt--) {
+ if (pt->flag & GP_SPOINT_SELECT) {
+ /* shrink if previous wasn't selected */
+ if (prev_sel == false) {
+ pt->flag &= ~GP_SPOINT_SELECT;
+ }
+ prev_sel = true;
+ }
+ else {
+ /* mark previous as being unselected - and hence, is trigger for shrinking */
+ prev_sel = false;
+ }
+ }
+ }
+ }
+ CTX_DATA_END;
+
+ /* updates */
+ WM_event_add_notifier(C, NC_GPENCIL | NA_SELECTED, NULL);
+ return OPERATOR_FINISHED;
+}
+
+void GPENCIL_OT_select_less(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Select Less";
+ ot->idname = "GPENCIL_OT_select_less";
+ ot->description = "Shrink sets of selected Grease Pencil points";
+
+ /* callbacks */
+ ot->exec = gpencil_select_less_exec;
+ ot->poll = gpencil_select_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+/* ********************************************** */
+/* Circle Select Operator */
+
+/* Helper to check if a given stroke is within the area */
+/* NOTE: Code here is adapted (i.e. copied directly) from gpencil_paint.c::gp_stroke_eraser_dostroke()
+ * It would be great to de-duplicate the logic here sometime, but that can wait...
+ */
+static bool gp_stroke_do_circle_sel(bGPDstroke *gps, GP_SpaceConversion *gsc,
+ const int mx, const int my, const int radius,
+ const bool select, rcti *rect)
+{
+ bGPDspoint *pt1, *pt2;
+ int x0 = 0, y0 = 0, x1 = 0, y1 = 0;
+ int i;
+ bool changed = false;
+
+ if (gps->totpoints == 1) {
+ gp_point_to_xy(gsc, gps, gps->points, &x0, &y0);
+
+ /* do boundbox check first */
+ if ((!ELEM(V2D_IS_CLIPPED, x0, y0)) && BLI_rcti_isect_pt(rect, x0, y0)) {
+ /* only check if point is inside */
+ if (((x0 - mx) * (x0 - mx) + (y0 - my) * (y0 - my)) <= radius * radius) {
+ /* change selection */
+ if (select) {
+ gps->points->flag |= GP_SPOINT_SELECT;
+ gps->flag |= GP_STROKE_SELECT;
+ }
+ else {
+ gps->points->flag &= ~GP_SPOINT_SELECT;
+ gps->flag &= ~GP_STROKE_SELECT;
+ }
+
+ return true;
+ }
+ }
+ }
+ else {
+ /* Loop over the points in the stroke, checking for intersections
+ * - an intersection means that we touched the stroke
+ */
+ for (i = 0; (i + 1) < gps->totpoints; i++) {
+ /* get points to work with */
+ pt1 = gps->points + i;
+ pt2 = gps->points + i + 1;
+
+ gp_point_to_xy(gsc, gps, pt1, &x0, &y0);
+ gp_point_to_xy(gsc, gps, pt2, &x1, &y1);
+
+ /* check that point segment of the boundbox of the selection stroke */
+ if (((!ELEM(V2D_IS_CLIPPED, x0, y0)) && BLI_rcti_isect_pt(rect, x0, y0)) ||
+ ((!ELEM(V2D_IS_CLIPPED, x1, y1)) && BLI_rcti_isect_pt(rect, x1, y1)))
+ {
+ int mval[2] = {mx, my};
+ int mvalo[2] = {mx, my}; /* dummy - this isn't used... */
+
+ /* check if point segment of stroke had anything to do with
+ * eraser region (either within stroke painted, or on its lines)
+ * - this assumes that linewidth is irrelevant
+ */
+ if (gp_stroke_inside_circle(mval, mvalo, radius, x0, y0, x1, y1)) {
+ /* change selection of stroke, and then of both points
+ * (as the last point otherwise wouldn't get selected
+ * as we only do n-1 loops through)
+ */
+ if (select) {
+ pt1->flag |= GP_SPOINT_SELECT;
+ pt2->flag |= GP_SPOINT_SELECT;
+
+ changed = true;
+ }
+ else {
+ pt1->flag &= ~GP_SPOINT_SELECT;
+ pt2->flag &= ~GP_SPOINT_SELECT;
+
+ changed = true;
+ }
+ }
+ }
+ }
+
+ /* Ensure that stroke selection is in sync with its points */
+ gpencil_stroke_sync_selection(gps);
+ }
+
+ return changed;
+}
+
+
+static int gpencil_circle_select_exec(bContext *C, wmOperator *op)
+{
+ ScrArea *sa = CTX_wm_area(C);
+
+ const int mx = RNA_int_get(op->ptr, "x");
+ const int my = RNA_int_get(op->ptr, "y");
+ const int radius = RNA_int_get(op->ptr, "radius");
+
+ const int gesture_mode = RNA_int_get(op->ptr, "gesture_mode");
+ const bool select = (gesture_mode == GESTURE_MODAL_SELECT);
+
+ GP_SpaceConversion gsc = {NULL};
+ rcti rect = {0}; /* for bounding rect around circle (for quicky intersection testing) */
+
+ bool changed = false;
+
+
+ /* sanity checks */
+ if (sa == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "No active area");
+ return OPERATOR_CANCELLED;
+ }
+
+ /* init space conversion stuff */
+ gp_point_conversion_init(C, &gsc);
+
+
+ /* rect is rectangle of selection circle */
+ rect.xmin = mx - radius;
+ rect.ymin = my - radius;
+ rect.xmax = mx + radius;
+ rect.ymax = my + radius;
+
+
+ /* find visible strokes, and select if hit */
+ CTX_DATA_BEGIN(C, bGPDstroke *, gps, editable_gpencil_strokes)
+ {
+ changed |= gp_stroke_do_circle_sel(gps, &gsc, mx, my, radius, select, &rect);
+ }
+ CTX_DATA_END;
+
+ /* updates */
+ if (changed) {
+ WM_event_add_notifier(C, NC_GPENCIL | NA_SELECTED, NULL);
+ }
+
+ return OPERATOR_FINISHED;
+}
+
+void GPENCIL_OT_select_circle(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Circle Select";
+ ot->description = "Select Grease Pencil strokes using brush selection";
+ ot->idname = "GPENCIL_OT_select_circle";
+
+ /* callbacks */
+ ot->invoke = WM_gesture_circle_invoke;
+ ot->modal = WM_gesture_circle_modal;
+ ot->exec = gpencil_circle_select_exec;
+ ot->poll = gpencil_select_poll;
+ ot->cancel = WM_gesture_circle_cancel;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_int(ot->srna, "x", 0, INT_MIN, INT_MAX, "X", "", INT_MIN, INT_MAX);
+ RNA_def_int(ot->srna, "y", 0, INT_MIN, INT_MAX, "Y", "", INT_MIN, INT_MAX);
+ RNA_def_int(ot->srna, "radius", 1, 1, INT_MAX, "Radius", "", 1, INT_MAX);
+ RNA_def_int(ot->srna, "gesture_mode", 0, INT_MIN, INT_MAX, "Gesture Mode", "", INT_MIN, INT_MAX);
+}
+
+/* ********************************************** */
+/* Box Selection */
+
+static int gpencil_border_select_exec(bContext *C, wmOperator *op)
+{
+ ScrArea *sa = CTX_wm_area(C);
+
+ const int gesture_mode = RNA_int_get(op->ptr, "gesture_mode");
+ const bool select = (gesture_mode == GESTURE_MODAL_SELECT);
+ const bool extend = RNA_boolean_get(op->ptr, "extend");
+
+ GP_SpaceConversion gsc = {NULL};
+ rcti rect = {0};
+
+ bool changed = false;
+
+
+ /* sanity checks */
+ if (sa == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "No active area");
+ return OPERATOR_CANCELLED;
+ }
+
+ /* init space conversion stuff */
+ gp_point_conversion_init(C, &gsc);
+
+
+ /* deselect all strokes first? */
+ if (select && !extend) {
+ CTX_DATA_BEGIN(C, bGPDstroke *, gps, editable_gpencil_strokes)
+ {
+ bGPDspoint *pt;
+ int i;
+
+ for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
+ pt->flag &= ~GP_SPOINT_SELECT;
+ }
+
+ gps->flag &= ~GP_STROKE_SELECT;
+ }
+ CTX_DATA_END;
+ }
+
+ /* get settings from operator */
+ WM_operator_properties_border_to_rcti(op, &rect);
+
+ /* select/deselect points */
+ CTX_DATA_BEGIN(C, bGPDstroke *, gps, editable_gpencil_strokes)
+ {
+ bGPDspoint *pt;
+ int i;
+
+ for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
+ int x0, y0;
+
+ /* convert point coords to screenspace */
+ gp_point_to_xy(&gsc, gps, pt, &x0, &y0);
+
+ /* test if in selection rect */
+ if ((!ELEM(V2D_IS_CLIPPED, x0, y0)) && BLI_rcti_isect_pt(&rect, x0, y0)) {
+ if (select) {
+ pt->flag |= GP_SPOINT_SELECT;
+ }
+ else {
+ pt->flag &= ~GP_SPOINT_SELECT;
+ }
+
+ changed = true;
+ }
+ }
+
+ /* Ensure that stroke selection is in sync with its points */
+ gpencil_stroke_sync_selection(gps);
+ }
+ CTX_DATA_END;
+
+ /* updates */
+ if (changed) {
+ WM_event_add_notifier(C, NC_GPENCIL | NA_SELECTED, NULL);
+ }
+
+ return OPERATOR_FINISHED;
+}
+
+void GPENCIL_OT_select_border(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Border Select";
+ ot->description = "Select Grease Pencil strokes within a rectangular region";
+ ot->idname = "GPENCIL_OT_select_border";
+
+ /* callbacks */
+ ot->invoke = WM_border_select_invoke;
+ ot->exec = gpencil_border_select_exec;
+ ot->modal = WM_border_select_modal;
+ ot->cancel = WM_border_select_cancel;
+
+ ot->poll = gpencil_select_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* rna */
+ WM_operator_properties_gesture_border(ot, true);
+}
+
+/* ********************************************** */
+/* Lasso */
+
+static int gpencil_lasso_select_exec(bContext *C, wmOperator *op)
+{
+ GP_SpaceConversion gsc = {NULL};
+ rcti rect = {0};
+
+ const bool extend = RNA_boolean_get(op->ptr, "extend");
+ const bool select = !RNA_boolean_get(op->ptr, "deselect");
+
+ int mcords_tot;
+ const int (*mcords)[2] = WM_gesture_lasso_path_to_array(C, op, &mcords_tot);
+
+ bool changed = false;
+
+ /* sanity check */
+ if (mcords == NULL)
+ return OPERATOR_PASS_THROUGH;
+
+ /* compute boundbox of lasso (for faster testing later) */
+ BLI_lasso_boundbox(&rect, mcords, mcords_tot);
+
+ /* init space conversion stuff */
+ gp_point_conversion_init(C, &gsc);
+
+ /* deselect all strokes first? */
+ if (select && !extend) {
+ CTX_DATA_BEGIN(C, bGPDstroke *, gps, editable_gpencil_strokes)
+ {
+ bGPDspoint *pt;
+ int i;
+
+ for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
+ pt->flag &= ~GP_SPOINT_SELECT;
+ }
+
+ gps->flag &= ~GP_STROKE_SELECT;
+ }
+ CTX_DATA_END;
+ }
+
+ /* select/deselect points */
+ CTX_DATA_BEGIN(C, bGPDstroke *, gps, editable_gpencil_strokes)
+ {
+ bGPDspoint *pt;
+ int i;
+
+ for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
+ int x0, y0;
+
+ /* convert point coords to screenspace */
+ gp_point_to_xy(&gsc, gps, pt, &x0, &y0);
+
+ /* test if in lasso boundbox + within the lasso noose */
+ if ((!ELEM(V2D_IS_CLIPPED, x0, y0)) && BLI_rcti_isect_pt(&rect, x0, y0) &&
+ BLI_lasso_is_point_inside(mcords, mcords_tot, x0, y0, INT_MAX))
+ {
+ if (select) {
+ pt->flag |= GP_SPOINT_SELECT;
+ }
+ else {
+ pt->flag &= ~GP_SPOINT_SELECT;
+ }
+
+ changed = true;
+ }
+ }
+
+ /* Ensure that stroke selection is in sync with its points */
+ gpencil_stroke_sync_selection(gps);
+ }
+ CTX_DATA_END;
+
+ /* cleanup */
+ MEM_freeN((void *)mcords);
+
+ /* updates */
+ if (changed) {
+ WM_event_add_notifier(C, NC_GPENCIL | NA_SELECTED, NULL);
+ }
+
+ return OPERATOR_FINISHED;
+}
+
+void GPENCIL_OT_select_lasso(wmOperatorType *ot)
+{
+ ot->name = "Lasso Select Strokes";
+ ot->description = "Select Grease Pencil strokes using lasso selection";
+ ot->idname = "GPENCIL_OT_select_lasso";
+
+ ot->invoke = WM_gesture_lasso_invoke;
+ ot->modal = WM_gesture_lasso_modal;
+ ot->exec = gpencil_lasso_select_exec;
+ ot->poll = gpencil_select_poll;
+ ot->cancel = WM_gesture_lasso_cancel;
+
+ /* flags */
+ ot->flag = OPTYPE_UNDO;
+
+ RNA_def_collection_runtime(ot->srna, "path", &RNA_OperatorMousePath, "Path", "");
+ RNA_def_boolean(ot->srna, "deselect", 0, "Deselect", "Deselect rather than select items");
+ RNA_def_boolean(ot->srna, "extend", 1, "Extend", "Extend selection instead of deselecting everything first");
+}
+
+/* ********************************************** */
+/* Mouse Click to Select */
+
+static int gpencil_select_exec(bContext *C, wmOperator *op)
+{
+ ScrArea *sa = CTX_wm_area(C);
+
+ /* "radius" is simply a threshold (screen space) to make it easier to test with a tolerance */
+ const float radius = 0.75f * U.widget_unit;
+ const int radius_squared = (int)(radius * radius);
+
+ bool extend = RNA_boolean_get(op->ptr, "extend");
+ bool deselect = RNA_boolean_get(op->ptr, "deselect");
+ bool toggle = RNA_boolean_get(op->ptr, "toggle");
+ bool whole = RNA_boolean_get(op->ptr, "entire_strokes");
+
+ int mval[2] = {0};
+
+ GP_SpaceConversion gsc = {NULL};
+
+ bGPDstroke *hit_stroke = NULL;
+ bGPDspoint *hit_point = NULL;
+ int hit_distance = radius_squared;
+
+ /* sanity checks */
+ if (sa == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "No active area");
+ return OPERATOR_CANCELLED;
+ }
+
+ /* init space conversion stuff */
+ gp_point_conversion_init(C, &gsc);
+
+ /* get mouse location */
+ RNA_int_get_array(op->ptr, "location", mval);
+
+ /* First Pass: Find stroke point which gets hit */
+ /* XXX: maybe we should go from the top of the stack down instead... */
+ CTX_DATA_BEGIN(C, bGPDstroke *, gps, editable_gpencil_strokes)
+ {
+ bGPDspoint *pt;
+ int i;
+
+ /* firstly, check for hit-point */
+ for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
+ int xy[2];
+
+ gp_point_to_xy(&gsc, gps, pt, &xy[0], &xy[1]);
+
+ /* do boundbox check first */
+ if (!ELEM(V2D_IS_CLIPPED, xy[0], xy[1])) {
+ const int pt_distance = len_manhattan_v2v2_int(mval, xy);
+
+ /* check if point is inside */
+ if (pt_distance <= radius_squared) {
+ /* only use this point if it is a better match than the current hit - T44685 */
+ if (pt_distance < hit_distance) {
+ hit_stroke = gps;
+ hit_point = pt;
+ hit_distance = pt_distance;
+ }
+ }
+ }
+ }
+ }
+ CTX_DATA_END;
+
+ /* Abort if nothing hit... */
+ if (ELEM(NULL, hit_stroke, hit_point)) {
+ return OPERATOR_CANCELLED;
+ }
+
+ /* adjust selection behaviour - for toggle option */
+ if (toggle) {
+ deselect = (hit_point->flag & GP_SPOINT_SELECT) != 0;
+ }
+
+ /* If not extending selection, deselect everything else */
+ if (extend == false) {
+ CTX_DATA_BEGIN(C, bGPDstroke *, gps, editable_gpencil_strokes)
+ {
+ /* deselect stroke and its points if selected */
+ if (gps->flag & GP_STROKE_SELECT) {
+ bGPDspoint *pt;
+ int i;
+
+ /* deselect points */
+ for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
+ pt->flag &= ~GP_SPOINT_SELECT;
+ }
+
+ /* deselect stroke itself too */
+ gps->flag &= ~GP_STROKE_SELECT;
+ }
+ }
+ CTX_DATA_END;
+ }
+
+ /* Perform selection operations... */
+ if (whole) {
+ bGPDspoint *pt;
+ int i;
+
+ /* entire stroke's points */
+ for (i = 0, pt = hit_stroke->points; i < hit_stroke->totpoints; i++, pt++) {
+ if (deselect == false)
+ pt->flag |= GP_SPOINT_SELECT;
+ else
+ pt->flag &= ~GP_SPOINT_SELECT;
+ }
+
+ /* stroke too... */
+ if (deselect == false)
+ hit_stroke->flag |= GP_STROKE_SELECT;
+ else
+ hit_stroke->flag &= ~GP_STROKE_SELECT;
+ }
+ else {
+ /* just the point (and the stroke) */
+ if (deselect == false) {
+ /* we're adding selection, so selection must be true */
+ hit_point->flag |= GP_SPOINT_SELECT;
+ hit_stroke->flag |= GP_STROKE_SELECT;
+ }
+ else {
+ /* deselect point */
+ hit_point->flag &= ~GP_SPOINT_SELECT;
+
+ /* ensure that stroke is selected correctly */
+ gpencil_stroke_sync_selection(hit_stroke);
+ }
+ }
+
+ /* updates */
+ if (hit_point != NULL) {
+ WM_event_add_notifier(C, NC_GPENCIL | NA_SELECTED, NULL);
+ }
+
+ return OPERATOR_FINISHED;
+}
+
+static int gpencil_select_invoke(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ RNA_int_set_array(op->ptr, "location", event->mval);
+ return gpencil_select_exec(C, op);
+}
+
+void GPENCIL_OT_select(wmOperatorType *ot)
+{
+ PropertyRNA *prop;
+
+ /* identifiers */
+ ot->name = "Select";
+ ot->description = "Select Grease Pencil strokes and/or stroke points";
+ ot->idname = "GPENCIL_OT_select";
+
+ /* callbacks */
+ ot->invoke = gpencil_select_invoke;
+ ot->exec = gpencil_select_exec;
+ ot->poll = gpencil_select_poll;
+
+ /* flag */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ WM_operator_properties_mouse_select(ot);
+
+ prop = RNA_def_boolean(ot->srna, "entire_strokes", false, "Entire Strokes", "Select entire strokes instead of just the nearest stroke vertex");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+
+ prop = RNA_def_int_vector(ot->srna, "location", 2, NULL, INT_MIN, INT_MAX, "Location", "Mouse location", INT_MIN, INT_MAX);
+ RNA_def_property_flag(prop, PROP_HIDDEN);
+}
+
+/* ********************************************** */
diff --git a/source/blender/editors/gpencil/gpencil_undo.c b/source/blender/editors/gpencil/gpencil_undo.c
index ff92d69f39d..34e640a4b7b 100644
--- a/source/blender/editors/gpencil/gpencil_undo.c
+++ b/source/blender/editors/gpencil/gpencil_undo.c
@@ -29,6 +29,7 @@
* \ingroup edgpencil
*/
+
#include <stdlib.h>
#include <string.h>
@@ -53,7 +54,7 @@
typedef struct bGPundonode {
struct bGPundonode *next, *prev;
-
+
char name[BKE_UNDO_STR_MAX];
struct bGPdata *gpd;
} bGPundonode;
@@ -69,13 +70,13 @@ int ED_gpencil_session_active(void)
int ED_undo_gpencil_step(bContext *C, int step, const char *name)
{
bGPdata **gpd_ptr = NULL, *new_gpd = NULL;
-
+
gpd_ptr = ED_gpencil_data_get_pointers(C, NULL);
-
+
if (step == 1) { /* undo */
//printf("\t\tGP - undo step\n");
if (cur_node->prev) {
- if (!name || strcmp(cur_node->name, name) == 0) {
+ if (!name || STREQ(cur_node->name, name)) {
cur_node = cur_node->prev;
new_gpd = cur_node->gpd;
}
@@ -84,24 +85,24 @@ int ED_undo_gpencil_step(bContext *C, int step, const char *name)
else if (step == -1) {
//printf("\t\tGP - redo step\n");
if (cur_node->next) {
- if (!name || strcmp(cur_node->name, name) == 0) {
+ if (!name || STREQ(cur_node->name, name)) {
cur_node = cur_node->next;
new_gpd = cur_node->gpd;
}
}
}
-
+
if (new_gpd) {
if (gpd_ptr) {
if (*gpd_ptr) {
bGPdata *gpd = *gpd_ptr;
bGPDlayer *gpl, *gpld;
-
+
free_gpencil_layers(&gpd->layers);
-
+
/* copy layers */
BLI_listbase_clear(&gpd->layers);
-
+
for (gpl = new_gpd->layers.first; gpl; gpl = gpl->next) {
/* make a copy of source layer and its data */
gpld = gpencil_layer_duplicate(gpl);
@@ -110,9 +111,9 @@ int ED_undo_gpencil_step(bContext *C, int step, const char *name)
}
}
}
-
+
WM_event_add_notifier(C, NC_GPENCIL | NA_EDITED, NULL);
-
+
return OPERATOR_FINISHED;
}
@@ -124,46 +125,56 @@ void gpencil_undo_init(bGPdata *gpd)
void gpencil_undo_push(bGPdata *gpd)
{
bGPundonode *undo_node;
-
+
//printf("\t\tGP - undo push\n");
-
+
if (cur_node) {
/* remove all un-done nodes from stack */
undo_node = cur_node->next;
-
+
while (undo_node) {
bGPundonode *next_node = undo_node->next;
-
+
+ /* HACK: animdata wasn't duplicated, so it shouldn't be freed here,
+ * or else the real copy will segfault when accessed
+ */
+ undo_node->gpd->adt = NULL;
+
BKE_gpencil_free(undo_node->gpd);
MEM_freeN(undo_node->gpd);
-
+
BLI_freelinkN(&undo_nodes, undo_node);
-
+
undo_node = next_node;
}
}
-
+
/* create new undo node */
undo_node = MEM_callocN(sizeof(bGPundonode), "gpencil undo node");
- undo_node->gpd = gpencil_data_duplicate(gpd);
-
+ undo_node->gpd = gpencil_data_duplicate(gpd, true);
+
cur_node = undo_node;
-
+
BLI_addtail(&undo_nodes, undo_node);
}
void gpencil_undo_finish(void)
{
bGPundonode *undo_node = undo_nodes.first;
-
+
while (undo_node) {
+ /* HACK: animdata wasn't duplicated, so it shouldn't be freed here,
+ * or else the real copy will segfault when accessed
+ */
+ undo_node->gpd->adt = NULL;
+
BKE_gpencil_free(undo_node->gpd);
MEM_freeN(undo_node->gpd);
-
+
undo_node = undo_node->next;
}
-
+
BLI_freelistN(&undo_nodes);
-
+
cur_node = NULL;
}
diff --git a/source/blender/editors/gpencil/gpencil_utils.c b/source/blender/editors/gpencil/gpencil_utils.c
new file mode 100644
index 00000000000..0d7aac7f48f
--- /dev/null
+++ b/source/blender/editors/gpencil/gpencil_utils.c
@@ -0,0 +1,375 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2014, Blender Foundation
+ *
+ * Contributor(s): Joshua Leung
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/editors/gpencil/gpencil_utils.c
+ * \ingroup edgpencil
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <math.h>
+
+#include "BLI_math.h"
+#include "BLI_blenlib.h"
+#include "BLI_utildefines.h"
+
+#include "DNA_gpencil_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_space_types.h"
+#include "DNA_view3d_types.h"
+
+#include "BKE_context.h"
+#include "BKE_gpencil.h"
+#include "BKE_tracking.h"
+
+#include "WM_api.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+
+#include "UI_view2d.h"
+
+#include "ED_gpencil.h"
+#include "ED_clip.h"
+#include "ED_view3d.h"
+
+#include "gpencil_intern.h"
+
+/* ******************************************************** */
+/* Context Wrangling... */
+
+/* Get pointer to active Grease Pencil datablock, and an RNA-pointer to trace back to whatever owns it,
+ * when context info is not available.
+ */
+bGPdata **ED_gpencil_data_get_pointers_direct(ID *screen_id, Scene *scene, ScrArea *sa, Object *ob, PointerRNA *ptr)
+{
+ /* if there's an active area, check if the particular editor may
+ * have defined any special Grease Pencil context for editing...
+ */
+ if (sa) {
+ SpaceLink *sl = sa->spacedata.first;
+
+ switch (sa->spacetype) {
+ case SPACE_VIEW3D: /* 3D-View */
+ case SPACE_TIME: /* Timeline - XXX: this is a hack to get it to show GP keyframes for 3D view */
+ case SPACE_ACTION: /* DepeSheet - XXX: this is a hack to get the keyframe jump operator to take GP Keyframes into account */
+ {
+ BLI_assert(scene && ELEM(scene->toolsettings->gpencil_src,
+ GP_TOOL_SOURCE_SCENE, GP_TOOL_SOURCE_OBJECT));
+
+ if (scene->toolsettings->gpencil_src == GP_TOOL_SOURCE_OBJECT) {
+ /* legacy behaviour for usage with old addons requiring object-linked to objects */
+
+ /* just in case no active/selected object... */
+ if (ob && (ob->flag & SELECT)) {
+ /* for now, as long as there's an object, default to using that in 3D-View */
+ if (ptr) RNA_id_pointer_create(&ob->id, ptr);
+ return &ob->gpd;
+ }
+ /* else: defaults to scene... */
+ }
+ else {
+ if (ptr) RNA_id_pointer_create(&scene->id, ptr);
+ return &scene->gpd;
+ }
+ break;
+ }
+ case SPACE_NODE: /* Nodes Editor */
+ {
+ SpaceNode *snode = (SpaceNode *)sl;
+
+ /* return the GP data for the active node block/node */
+ if (snode && snode->nodetree) {
+ /* for now, as long as there's an active node tree, default to using that in the Nodes Editor */
+ if (ptr) RNA_id_pointer_create(&snode->nodetree->id, ptr);
+ return &snode->nodetree->gpd;
+ }
+
+ /* even when there is no node-tree, don't allow this to flow to scene */
+ return NULL;
+ }
+ case SPACE_SEQ: /* Sequencer */
+ {
+ SpaceSeq *sseq = (SpaceSeq *)sl;
+
+ /* for now, Grease Pencil data is associated with the space (actually preview region only) */
+ /* XXX our convention for everything else is to link to data though... */
+ if (ptr) RNA_pointer_create(screen_id, &RNA_SpaceSequenceEditor, sseq, ptr);
+ return &sseq->gpd;
+ }
+ case SPACE_IMAGE: /* Image/UV Editor */
+ {
+ SpaceImage *sima = (SpaceImage *)sl;
+
+ /* for now, Grease Pencil data is associated with the space... */
+ /* XXX our convention for everything else is to link to data though... */
+ if (ptr) RNA_pointer_create(screen_id, &RNA_SpaceImageEditor, sima, ptr);
+ return &sima->gpd;
+ }
+ case SPACE_CLIP: /* Nodes Editor */
+ {
+ SpaceClip *sc = (SpaceClip *)sl;
+ MovieClip *clip = ED_space_clip_get_clip(sc);
+
+ if (clip) {
+ if (sc->gpencil_src == SC_GPENCIL_SRC_TRACK) {
+ MovieTrackingTrack *track = BKE_tracking_track_get_active(&clip->tracking);
+
+ if (!track)
+ return NULL;
+
+ if (ptr)
+ RNA_pointer_create(&clip->id, &RNA_MovieTrackingTrack, track, ptr);
+
+ return &track->gpd;
+ }
+ else {
+ if (ptr)
+ RNA_id_pointer_create(&clip->id, ptr);
+
+ return &clip->gpd;
+ }
+ }
+ break;
+ }
+ default: /* unsupported space */
+ return NULL;
+ }
+ }
+
+ /* just fall back on the scene's GP data */
+ if (ptr) RNA_id_pointer_create((ID *)scene, ptr);
+ return (scene) ? &scene->gpd : NULL;
+}
+
+/* Get pointer to active Grease Pencil datablock, and an RNA-pointer to trace back to whatever owns it */
+bGPdata **ED_gpencil_data_get_pointers(const bContext *C, PointerRNA *ptr)
+{
+ ID *screen_id = (ID *)CTX_wm_screen(C);
+ Scene *scene = CTX_data_scene(C);
+ ScrArea *sa = CTX_wm_area(C);
+ Object *ob = CTX_data_active_object(C);
+
+ return ED_gpencil_data_get_pointers_direct(screen_id, scene, sa, ob, ptr);
+}
+
+/* -------------------------------------------------------- */
+
+/* Get the active Grease Pencil datablock, when context is not available */
+bGPdata *ED_gpencil_data_get_active_direct(ID *screen_id, Scene *scene, ScrArea *sa, Object *ob)
+{
+ bGPdata **gpd_ptr = ED_gpencil_data_get_pointers_direct(screen_id, scene, sa, ob, NULL);
+ return (gpd_ptr) ? *(gpd_ptr) : NULL;
+}
+
+/* Get the active Grease Pencil datablock */
+bGPdata *ED_gpencil_data_get_active(const bContext *C)
+{
+ bGPdata **gpd_ptr = ED_gpencil_data_get_pointers(C, NULL);
+ return (gpd_ptr) ? *(gpd_ptr) : NULL;
+}
+
+/* -------------------------------------------------------- */
+
+// XXX: this should be removed... We really shouldn't duplicate logic like this!
+bGPdata *ED_gpencil_data_get_active_v3d(Scene *scene, View3D *v3d)
+{
+ Base *base = scene->basact;
+ bGPdata *gpd = NULL;
+ /* We have to make sure active object is actually visible and selected, else we must use default scene gpd,
+ * to be consistent with ED_gpencil_data_get_active's behavior.
+ */
+
+ if (base && TESTBASE(v3d, base)) {
+ gpd = base->object->gpd;
+ }
+ return gpd ? gpd : scene->gpd;
+}
+
+/* ******************************************************** */
+/* Poll Callbacks */
+
+/* poll callback for adding data/layers - special */
+int gp_add_poll(bContext *C)
+{
+ /* the base line we have is that we have somewhere to add Grease Pencil data */
+ return ED_gpencil_data_get_pointers(C, NULL) != NULL;
+}
+
+/* poll callback for checking if there is an active layer */
+int gp_active_layer_poll(bContext *C)
+{
+ bGPdata *gpd = ED_gpencil_data_get_active(C);
+ bGPDlayer *gpl = gpencil_layer_getactive(gpd);
+
+ return (gpl != NULL);
+}
+
+/* ******************************************************** */
+/* Brush Tool Core */
+
+/* Check if part of stroke occurs within last segment drawn by eraser */
+bool gp_stroke_inside_circle(const int mval[2], const int UNUSED(mvalo[2]),
+ int rad, int x0, int y0, int x1, int y1)
+{
+ /* simple within-radius check for now */
+ const float mval_fl[2] = {mval[0], mval[1]};
+ const float screen_co_a[2] = {x0, y0};
+ const float screen_co_b[2] = {x1, y1};
+
+ if (edge_inside_circle(mval_fl, rad, screen_co_a, screen_co_b)) {
+ return true;
+ }
+
+ /* not inside */
+ return false;
+}
+
+/* ******************************************************** */
+/* Stroke Validity Testing */
+
+/* Check whether given stroke can be edited given the supplied context */
+// XXX: do we need additional flags for screenspace vs dataspace?
+bool ED_gpencil_stroke_can_use_direct(const ScrArea *sa, const bGPDstroke *gps)
+{
+ /* sanity check */
+ if (ELEM(NULL, sa, gps))
+ return false;
+
+ /* filter stroke types by flags + spacetype */
+ if (gps->flag & GP_STROKE_3DSPACE) {
+ /* 3D strokes - only in 3D view */
+ return (sa->spacetype == SPACE_VIEW3D);
+ }
+ else if (gps->flag & GP_STROKE_2DIMAGE) {
+ /* Special "image" strokes - only in Image Editor */
+ return (sa->spacetype == SPACE_IMAGE);
+ }
+ else if (gps->flag & GP_STROKE_2DSPACE) {
+ /* 2D strokes (dataspace) - for any 2D view (i.e. everything other than 3D view) */
+ return (sa->spacetype != SPACE_VIEW3D);
+ }
+ else {
+ /* view aligned - anything goes */
+ return true;
+ }
+}
+
+/* Check whether given stroke can be edited in the current context */
+bool ED_gpencil_stroke_can_use(const bContext *C, const bGPDstroke *gps)
+{
+ ScrArea *sa = CTX_wm_area(C);
+ return ED_gpencil_stroke_can_use_direct(sa, gps);
+}
+
+/* ******************************************************** */
+/* Space Conversion */
+
+/* Init handling for space-conversion function (from passed-in parameters) */
+void gp_point_conversion_init(bContext *C, GP_SpaceConversion *r_gsc)
+{
+ ScrArea *sa = CTX_wm_area(C);
+ ARegion *ar = CTX_wm_region(C);
+
+ /* zero out the storage (just in case) */
+ memset(r_gsc, 0, sizeof(GP_SpaceConversion));
+ unit_m4(r_gsc->mat);
+
+ /* store settings */
+ r_gsc->sa = sa;
+ r_gsc->ar = ar;
+ r_gsc->v2d = &ar->v2d;
+
+ /* init region-specific stuff */
+ if (sa->spacetype == SPACE_VIEW3D) {
+ wmWindow *win = CTX_wm_window(C);
+ Scene *scene = CTX_data_scene(C);
+ View3D *v3d = (View3D *)CTX_wm_space_data(C);
+ RegionView3D *rv3d = ar->regiondata;
+
+ /* init 3d depth buffers */
+ view3d_operator_needs_opengl(C);
+
+ view3d_region_operator_needs_opengl(win, ar);
+ ED_view3d_autodist_init(scene, ar, v3d, 0);
+
+ /* for camera view set the subrect */
+ if (rv3d->persp == RV3D_CAMOB) {
+ ED_view3d_calc_camera_border(scene, ar, v3d, rv3d, &r_gsc->subrect_data, true); /* no shift */
+ r_gsc->subrect = &r_gsc->subrect_data;
+ }
+ }
+}
+
+
+/* Convert Grease Pencil points to screen-space values
+ * WARNING: This assumes that the caller has already checked whether the stroke in question can be drawn
+ */
+void gp_point_to_xy(GP_SpaceConversion *gsc, bGPDstroke *gps, bGPDspoint *pt,
+ int *r_x, int *r_y)
+{
+ ARegion *ar = gsc->ar;
+ View2D *v2d = gsc->v2d;
+ rctf *subrect = gsc->subrect;
+ int xyval[2];
+
+ /* sanity checks */
+ BLI_assert(!(gps->flag & GP_STROKE_3DSPACE) || (gsc->sa->spacetype == SPACE_VIEW3D));
+ BLI_assert(!(gps->flag & GP_STROKE_2DSPACE) || (gsc->sa->spacetype != SPACE_VIEW3D));
+
+
+ if (gps->flag & GP_STROKE_3DSPACE) {
+ if (ED_view3d_project_int_global(ar, &pt->x, xyval, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) {
+ *r_x = xyval[0];
+ *r_y = xyval[1];
+ }
+ else {
+ *r_x = V2D_IS_CLIPPED;
+ *r_y = V2D_IS_CLIPPED;
+ }
+ }
+ else if (gps->flag & GP_STROKE_2DSPACE) {
+ float vec[3] = {pt->x, pt->y, 0.0f};
+ mul_m4_v3(gsc->mat, vec);
+ UI_view2d_view_to_region_clip(v2d, vec[0], vec[1], r_x, r_y);
+ }
+ else {
+ if (subrect == NULL) {
+ /* normal 3D view (or view space) */
+ *r_x = (int)(pt->x / 100 * ar->winx);
+ *r_y = (int)(pt->y / 100 * ar->winy);
+ }
+ else {
+ /* camera view, use subrect */
+ *r_x = (int)((pt->x / 100) * BLI_rctf_size_x(subrect)) + subrect->xmin;
+ *r_y = (int)((pt->y / 100) * BLI_rctf_size_y(subrect)) + subrect->ymin;
+ }
+ }
+}
+
+/* ******************************************************** */
diff --git a/source/blender/editors/include/BIF_gl.h b/source/blender/editors/include/BIF_gl.h
index 9fa603966b6..e2a24b9fed7 100644
--- a/source/blender/editors/include/BIF_gl.h
+++ b/source/blender/editors/include/BIF_gl.h
@@ -33,18 +33,8 @@
#ifndef __BIF_GL_H__
#define __BIF_GL_H__
-#include "GL/glew.h"
-
-#ifdef __APPLE__
-
-/* hacking pointsize and linewidth */
-# define glPointSize(f) glPointSize(U.pixelsize * (f))
-# define glLineWidth(f) glLineWidth(U.pixelsize * (f))
-#else
- /* avoid include mismatch by referencing 'U' from both */
-# define glPointSize(f) glPointSize(((void)U.pixelsize, (f)))
-# define glLineWidth(f) glLineWidth(((void)U.pixelsize, (f)))
-#endif
+#include "GPU_glew.h"
+#include "BLI_utildefines.h"
/*
* these should be phased out. cpack should be replaced in
@@ -58,26 +48,58 @@
* */
void cpack(unsigned int x);
-
+#ifdef WITH_GL_PROFILE_COMPAT
#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)
# define glMultMatrixf(x) \
glMultMatrixf(_Generic((x), \
float *: (float *)(x), \
+ float [16]: (float *)(x), \
float (*)[4]: (float *)(x), \
+ float [4][4]: (float *)(x), \
const float *: (float *)(x), \
- const float (*)[4]: (float *)(x)) \
+ const float [16]: (float *)(x), \
+ const float (*)[4]: (float *)(x), \
+ const float [4][4]: (float *)(x)) \
)
# define glLoadMatrixf(x) \
glLoadMatrixf(_Generic((x), \
float *: (float *)(x), \
- float (*)[4]: (float *)(x)) \
+ float [16]: (float *)(x), \
+ float (*)[4]: (float *)(x), \
+ float [4][4]: (float *)(x)) \
)
#else
# define glMultMatrixf(x) glMultMatrixf((float *)(x))
# define glLoadMatrixf(x) glLoadMatrixf((float *)(x))
-#endif
+#endif /* C11 */
+#endif /* WITH_GL_PROFILE_COMPAT */
+
+
+/* hacking pointsize and linewidth */
+#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)
+# define glPointSize(f) glPointSize(U.pixelsize * _Generic((f), double: (float)(f), default: (f)))
+# define glLineWidth(f) glLineWidth(U.pixelsize * _Generic((f), double: (float)(f), default: (f)))
+#else
+# define glPointSize(f) glPointSize(U.pixelsize * (f))
+# define glLineWidth(f) glLineWidth(U.pixelsize * (f))
+#endif /* C11 */
#define GLA_PIXEL_OFS 0.375f
+
+BLI_INLINE void glTranslate3fv(const float vec[3]) { glTranslatef(UNPACK3(vec)); }
+BLI_INLINE void glTranslate2fv(const float vec[2]) { glTranslatef(UNPACK2(vec), 0.0f); }
+BLI_INLINE void glTranslate3dv(const double vec[3]) { glTranslated(UNPACK3(vec)); }
+BLI_INLINE void glTranslate2dv(const double vec[2]) { glTranslated(UNPACK2(vec), 0.0f); }
+
+BLI_INLINE void glScale3fv(const float vec[3]) { glScalef(UNPACK3(vec)); }
+BLI_INLINE void glScale2fv(const float vec[2]) { glScalef(UNPACK2(vec), 0.0); }
+BLI_INLINE void glScale3dv(const double vec[3]) { glScaled(UNPACK3(vec)); }
+BLI_INLINE void glScale2dv(const double vec[2]) { glScaled(UNPACK2(vec), 0.0); }
+
+/* v2 versions don't make much sense for rotation */
+BLI_INLINE void glRotate3fv(const float angle, const float vec[3]) { glRotatef(angle, UNPACK3(vec)); }
+BLI_INLINE void glRotate3dv(const double angle, const double vec[3]) { glRotated(angle, UNPACK3(vec)); }
+
#endif /* #ifdef __BIF_GL_H__ */
diff --git a/source/blender/editors/include/BIF_glutil.h b/source/blender/editors/include/BIF_glutil.h
index b401f06f484..b904417cfcb 100644
--- a/source/blender/editors/include/BIF_glutil.h
+++ b/source/blender/editors/include/BIF_glutil.h
@@ -41,10 +41,12 @@ struct ColorManagedDisplaySettings;
void fdrawbezier(float vec[4][3]);
void fdrawline(float x1, float y1, float x2, float y2);
void fdrawbox(float x1, float y1, float x2, float y2);
-void sdrawline(short x1, short y1, short x2, short y2);
-void sdrawtri(short x1, short y1, short x2, short y2);
-void sdrawtrifill(short x1, short y1, short x2, short y2);
-void sdrawbox(short x1, short y1, short x2, short y2);
+void sdrawline(int x1, int y1, int x2, int y2);
+#if 0
+void sdrawtri(int x1, int y1, int x2, int y2);
+void sdrawtrifill(int x1, int y1, int x2, int y2);
+#endif
+void sdrawbox(int x1, int y1, int x2, int y2);
void sdrawXORline(int x0, int y0, int x1, int y1);
void sdrawXORline4(int nr, int x0, int y0, int x1, int y1);
@@ -88,13 +90,13 @@ void glutil_draw_lined_arc(float start, float angle, float radius, int nsegments
void glutil_draw_filled_arc(float start, float angle, float radius, int nsegments);
/**
- * Routines an integer value as obtained by glGetIntegerv.
+ * Returns an integer value as obtained by glGetIntegerv.
* The param must cause only one value to be gotten from GL.
*/
int glaGetOneInteger(int param);
/**
- * Routines a float value as obtained by glGetIntegerv.
+ * Returns a float value as obtained by glGetFloatv.
* The param must cause only one value to be gotten from GL.
*/
float glaGetOneFloat(int param);
@@ -162,8 +164,8 @@ void glaDrawPixelsTexScaled(float x, float y, int img_w, int img_h, int format,
/** Define a 2D area (viewport, scissor, matrices) for OpenGL rendering.
*
- * glwDefine2DArea and glaBegin2DDraw set up an OpenGL state appropriate
- * for drawing using both vertice (Vertex, etc) and raster (RasterPos, Rect)
+ * glaDefine2DArea and glaBegin2DDraw set up an OpenGL state appropriate
+ * for drawing using both vertex (Vertex, etc) and raster (RasterPos, Rect)
* commands. All coordinates should be at integer positions. There is little
* to no reason to use glVertex2f etc. functions during 2D rendering, and
* thus no reason to +-0.5 the coordinates or perform other silly
@@ -179,8 +181,8 @@ typedef struct gla2DDrawInfo gla2DDrawInfo;
#if 0
gla2DDrawInfo *glaBegin2DDraw(struct rcti *screen_rect, struct rctf *world_rect);
-void gla2DDrawTranslatePt(gla2DDrawInfo *di, float wo_x, float wo_y, int *sc_x_r, int *sc_y_r);
-void gla2DDrawTranslatePtv(gla2DDrawInfo *di, float world[2], int screen_r[2]);
+void gla2DDrawTranslatePt(gla2DDrawInfo *di, float wo_x, float wo_y, int *r_sc_x, int *r_sc_y);
+void gla2DDrawTranslatePtv(gla2DDrawInfo *di, float world[2], int r_screen[2]);
void glaEnd2DDraw(gla2DDrawInfo *di);
diff --git a/source/blender/editors/include/ED_anim_api.h b/source/blender/editors/include/ED_anim_api.h
index 956ec308daa..3c8442218be 100644
--- a/source/blender/editors/include/ED_anim_api.h
+++ b/source/blender/editors/include/ED_anim_api.h
@@ -49,7 +49,6 @@ struct Object;
struct bDopeSheet;
struct bAction;
-struct bActionGroup;
struct FCurve;
struct FModifier;
@@ -115,13 +114,17 @@ typedef struct bAnimListElem {
int flag; /* copy of elem's flags for quick access */
int index; /* for un-named data, the index of the data in its collection */
- short update; /* (eAnim_Update_Flags) tag the element for updating */
+ char update; /* (eAnim_Update_Flags) tag the element for updating */
+ char tag; /* tag the included data. Temporary always */
+
short datatype; /* (eAnim_KeyType) type of motion data to expect */
void *key_data; /* motion data - mostly F-Curves, but can be other types too */
struct ID *id; /* ID block that channel is attached to */
struct AnimData *adt; /* source of the animation data attached to ID block (for convenience) */
+
+ void *owner; /* for per-element F-Curves (e.g. NLA Control Curves), the element that this represents (e.g. NlaStrip) */
} bAnimListElem;
@@ -141,6 +144,9 @@ typedef enum eAnim_ChannelType {
ANIMTYPE_GROUP,
ANIMTYPE_FCURVE,
+ ANIMTYPE_NLACONTROLS,
+ ANIMTYPE_NLACURVE,
+
ANIMTYPE_FILLACTD,
ANIMTYPE_FILLDRIVERS,
@@ -159,6 +165,7 @@ typedef enum eAnim_ChannelType {
ANIMTYPE_DSLAT,
ANIMTYPE_DSLINESTYLE,
ANIMTYPE_DSSPK,
+ ANIMTYPE_DSGPENCIL,
ANIMTYPE_SHAPEKEY,
@@ -405,7 +412,8 @@ typedef enum eAnimChannel_Settings {
ACHANNEL_SETTING_EXPAND = 3,
ACHANNEL_SETTING_VISIBLE = 4, /* only for Graph Editor */
ACHANNEL_SETTING_SOLO = 5, /* only for NLA Tracks */
- ACHANNEL_SETTING_PINNED = 6 /* only for NLA Actions */
+ ACHANNEL_SETTING_PINNED = 6, /* only for NLA Actions */
+ ACHANNEL_SETTING_MOD_OFF = 7
} eAnimChannel_Settings;
@@ -449,15 +457,15 @@ typedef struct bAnimChannelType {
/* ------------------------ Drawing API -------------------------- */
/* Get typeinfo for the given channel */
-bAnimChannelType *ANIM_channel_get_typeinfo(bAnimListElem *ale);
+const bAnimChannelType *ANIM_channel_get_typeinfo(bAnimListElem *ale);
/* Print debugging info about a given channel */
void ANIM_channel_debug_print_info(bAnimListElem *ale, short indent_level);
/* Draw the given channel */
-void ANIM_channel_draw(bAnimContext *ac, bAnimListElem *ale, float yminc, float ymaxc);
+void ANIM_channel_draw(bAnimContext *ac, bAnimListElem *ale, float yminc, float ymaxc, size_t channel_index);
/* Draw the widgets for the given channel */
-void ANIM_channel_draw_widgets(struct bContext *C, bAnimContext *ac, bAnimListElem *ale, struct uiBlock *block, float yminc, float ymaxc, size_t channel_index);
+void ANIM_channel_draw_widgets(const struct bContext *C, bAnimContext *ac, bAnimListElem *ale, struct uiBlock *block, float yminc, float ymaxc, size_t channel_index);
/* ------------------------ Editing API -------------------------- */
@@ -610,7 +618,7 @@ typedef enum eAnimUnitConv_Flags {
short ANIM_get_normalization_flags(bAnimContext *ac);
/* Get unit conversion factor for given ID + F-Curve */
-float ANIM_unit_mapping_get_factor(struct Scene *scene, struct ID *id, struct FCurve *fcu, short flag);
+float ANIM_unit_mapping_get_factor(struct Scene *scene, struct ID *id, struct FCurve *fcu, short flag, float *r_offset);
/* ------------- Utility macros ----------------------- */
@@ -652,6 +660,7 @@ void ANIM_list_elem_update(struct Scene *scene, bAnimListElem *ale);
/* data -> channels syncing */
void ANIM_sync_animchannels_to_data(const struct bContext *C);
+void ANIM_center_frame(struct bContext *C, int smooth_viewtx);
/* ************************************************* */
/* OPERATORS */
@@ -669,6 +678,16 @@ void ED_operatormacros_graph(void);
void ED_operatormacros_action(void);
/* ************************************************ */
+/* Animation Editor Exports */
+/* XXX: Should we be doing these here, or at all? */
+
+/* Action Editor - Action Management */
+struct AnimData *ED_actedit_animdata_from_context(struct bContext *C);
+void ED_animedit_unlink_action(struct bContext *C, struct ID *id,
+ struct AnimData *adt, struct bAction *act,
+ struct ReportList *reports, bool force_delete);
+
+/* ************************************************ */
#endif /* __ED_ANIM_API_H__ */
diff --git a/source/blender/editors/include/ED_armature.h b/source/blender/editors/include/ED_armature.h
index 24c80cbf005..35bb12ddaad 100644
--- a/source/blender/editors/include/ED_armature.h
+++ b/source/blender/editors/include/ED_armature.h
@@ -39,16 +39,12 @@ struct Base;
struct bContext;
struct Bone;
struct bPoseChannel;
-struct DerivedMesh;
struct IDProperty;
struct ListBase;
struct MeshDeformModifierData;
struct Object;
-struct RegionView3D;
struct ReportList;
struct Scene;
-struct SK_Sketch;
-struct View3D;
struct ViewContext;
struct wmKeyConfig;
struct wmOperator;
@@ -59,8 +55,6 @@ typedef struct EditBone {
struct EditBone *parent; /* Editbones have a one-way link (i.e. children refer
* to parents. This is converted to a two-way link for
* normal bones when leaving editmode. */
- void *temp; /* Used to store temporary data */
-
char name[64]; /* MAXBONENAME */
float roll; /* Roll along axis. We'll ultimately use the axis/angle method
* for determining the transformation matrix of the bone. The axis
@@ -83,6 +77,14 @@ typedef struct EditBone {
float oldlength; /* for envelope scaling */
short segments;
+
+ /* Used to store temporary data */
+ union {
+ struct EditBone *ebone;
+ struct Bone *bone;
+ void *p;
+ int i;
+ } temp;
} EditBone;
#define BONESEL_ROOT (1 << 28)
@@ -119,10 +121,12 @@ void ED_keymap_armature(struct wmKeyConfig *keyconf);
void ED_armature_from_edit(struct bArmature *arm);
void ED_armature_to_edit(struct bArmature *arm);
void ED_armature_edit_free(struct bArmature *arm);
-void ED_armature_deselect_all(struct Object *obedit, int toggle);
+void ED_armature_ebone_listbase_temp_clear(struct ListBase *lb);
+
+void ED_armature_deselect_all(struct Object *obedit);
void ED_armature_deselect_all_visible(struct Object *obedit);
-int ED_do_pose_selectbuffer(struct Scene *scene, struct Base *base, unsigned int *buffer,
+int ED_do_pose_selectbuffer(struct Scene *scene, struct Base *base, unsigned int *buffer,
short hits, bool extend, bool deselect, bool toggle, bool do_nearest);
bool mouse_armature(struct bContext *C, const int mval[2], bool extend, bool deselect, bool toggle);
int join_armature_exec(struct bContext *C, struct wmOperator *op);
@@ -157,9 +161,11 @@ void ED_armature_transform(struct bArmature *arm, float mat[4][4]);
#define ARM_GROUPS_ENVELOPE 2
#define ARM_GROUPS_AUTO 3
-void create_vgroups_from_armature(struct ReportList *reports, struct Scene *scene, struct Object *ob, struct Object *par, int mode, bool mirror);
+void create_vgroups_from_armature(struct ReportList *reports, struct Scene *scene, struct Object *ob,
+ struct Object *par, const int mode, const bool mirror);
-void unique_editbone_name(struct ListBase *ebones, char *name, EditBone *bone); /* if bone is already in list, pass it as param to ignore it */
+/* if bone is already in list, pass it as param to ignore it */
+void unique_editbone_name(struct ListBase *ebones, char *name, EditBone *bone);
void ED_armature_bone_rename(struct bArmature *arm, const char *oldnamep, const char *newnamep);
void undo_push_armature(struct bContext *C, const char *name);
diff --git a/source/blender/editors/include/ED_buttons.h b/source/blender/editors/include/ED_buttons.h
index 64c16605dec..9a987d7618c 100644
--- a/source/blender/editors/include/ED_buttons.h
+++ b/source/blender/editors/include/ED_buttons.h
@@ -37,4 +37,6 @@ bool ED_texture_context_check_particles(const struct bContext *C);
bool ED_texture_context_check_linestyle(const struct bContext *C);
bool ED_texture_context_check_others(const struct bContext *C);
+void ED_buttons_id_unref(struct SpaceButs *sbuts, const struct ID *id);
+
#endif /* __ED_BUTTONS_H__ */
diff --git a/source/blender/editors/include/ED_curve.h b/source/blender/editors/include/ED_curve.h
index 58e64f30b05..6d53209688d 100644
--- a/source/blender/editors/include/ED_curve.h
+++ b/source/blender/editors/include/ED_curve.h
@@ -31,13 +31,10 @@
#ifndef __ED_CURVE_H__
#define __ED_CURVE_H__
-struct Base;
struct bContext;
struct Nurb;
struct Object;
-struct Scene;
struct Text;
-struct View3D;
struct wmOperator;
struct wmKeyConfig;
struct Curve;
@@ -51,11 +48,6 @@ void ED_operatormacros_curve(void);
void ED_keymap_curve(struct wmKeyConfig *keyconf);
/* editcurve.c */
-void ED_curve_deselect_all(struct EditNurb *editnurb);
-void ED_curve_select_all(struct EditNurb *editnurb);
-void ED_curve_select_swap(struct EditNurb *editnurb, bool hide_handles);
-
-
void undo_push_curve(struct bContext *C, const char *name);
ListBase *object_editcurve_get(struct Object *ob);
@@ -67,10 +59,20 @@ bool mouse_nurb(struct bContext *C, const int mval[2], bool extend, bool dese
struct Nurb *add_nurbs_primitive(struct bContext *C, struct Object *obedit, float mat[4][4], int type, int newob);
-int isNurbsel(struct Nurb *nu);
+bool ED_curve_nurb_select_check(struct Curve *cu, struct Nurb *nu);
+int ED_curve_nurb_select_count(struct Curve *cu, struct Nurb *nu);
+void ED_curve_nurb_select_all(struct Nurb *nu);
+void ED_curve_nurb_deselect_all(struct Nurb *nu);
int join_curve_exec(struct bContext *C, struct wmOperator *op);
+/* editcurve_select.c */
+bool ED_curve_select_check(struct Curve *cu, struct EditNurb *editnurb);
+void ED_curve_deselect_all(struct EditNurb *editnurb);
+void ED_curve_select_all(struct EditNurb *editnurb);
+void ED_curve_select_swap(struct EditNurb *editnurb, bool hide_handles);
+bool ED_curve_select_nth(struct Curve *cu, int nth, int skip, int offset);
+
/* editfont.h */
void undo_push_font(struct bContext *C, const char *name);
void make_editText(struct Object *obedit);
@@ -79,8 +81,6 @@ void free_editText(struct Object *obedit);
void ED_text_to_object(struct bContext *C, struct Text *text, const bool split_lines);
-bool ED_curve_select_nth(struct Curve *cu, int nth);
-
void ED_curve_beztcpy(struct EditNurb *editnurb, struct BezTriple *dst, struct BezTriple *src, int count);
void ED_curve_bpcpy(struct EditNurb *editnurb, struct BPoint *dst, struct BPoint *src, int count);
@@ -90,7 +90,9 @@ bool ED_curve_active_center(struct Curve *cu, float center[3]);
bool mouse_font(struct bContext *C, const int mval[2], bool extend, bool deselect, bool toggle);
+#if 0
/* debug only */
void printknots(struct Object *obedit);
+#endif
#endif /* __ED_CURVE_H__ */
diff --git a/source/blender/editors/include/ED_fileselect.h b/source/blender/editors/include/ED_fileselect.h
index f2a6ce0b129..186a2a26825 100644
--- a/source/blender/editors/include/ED_fileselect.h
+++ b/source/blender/editors/include/ED_fileselect.h
@@ -33,6 +33,7 @@
struct ARegion;
struct FileSelectParams;
+struct ScrArea;
struct SpaceFile;
struct bContext;
struct wmWindowManager;
@@ -40,17 +41,13 @@ struct wmWindowManager;
#define FILE_LAYOUT_HOR 1
#define FILE_LAYOUT_VER 2
-#define MAX_FILE_COLUMN 8
+#define MAX_FILE_COLUMN 4
typedef enum FileListColumns {
COLUMN_NAME = 0,
COLUMN_DATE,
COLUMN_TIME,
COLUMN_SIZE,
- COLUMN_MODE1,
- COLUMN_MODE2,
- COLUMN_MODE3,
- COLUMN_OWNER
} FileListColumns;
typedef struct FileLayout {
@@ -71,6 +68,9 @@ typedef struct FileLayout {
int dirty;
int textheight;
float column_widths[MAX_FILE_COLUMN];
+
+ /* When we change display size, we may have to update static strings like size of files... */
+ short curr_size;
} FileLayout;
typedef struct FileSelection {
@@ -100,13 +100,48 @@ void ED_fileselect_layout_tilepos(FileLayout *layout, int tile, int *x, int *y);
void ED_operatormacros_file(void);
-void ED_fileselect_clear(struct wmWindowManager *wm, struct SpaceFile *sfile);
+void ED_fileselect_clear(struct wmWindowManager *wm, struct ScrArea *sa, struct SpaceFile *sfile);
-void ED_fileselect_exit(struct wmWindowManager *wm, struct SpaceFile *sfile);
+void ED_fileselect_exit(struct wmWindowManager *wm, struct ScrArea *sa, struct SpaceFile *sfile);
int ED_file_extension_icon(const char *relname);
void ED_file_read_bookmarks(void);
+void ED_file_change_dir(struct bContext *C, const bool checkdir);
+
+/* File menu stuff */
+
+typedef enum FSMenuCategory {
+ FS_CATEGORY_SYSTEM,
+ FS_CATEGORY_SYSTEM_BOOKMARKS,
+ FS_CATEGORY_BOOKMARKS,
+ FS_CATEGORY_RECENT
+} FSMenuCategory;
+
+typedef enum FSMenuInsert {
+ FS_INSERT_SORTED = (1 << 0),
+ FS_INSERT_SAVE = (1 << 1),
+ FS_INSERT_FIRST = (1 << 2), /* moves the item to the front of the list when its not already there */
+ FS_INSERT_LAST = (1 << 3), /* just append to preseve delivered order */
+} FSMenuInsert;
+
+struct FSMenu;
+struct FSMenuEntry;
+
+struct FSMenu *ED_fsmenu_get(void);
+struct FSMenuEntry *ED_fsmenu_get_category(struct FSMenu *fsmenu, FSMenuCategory category);
+void ED_fsmenu_set_category(struct FSMenu *fsmenu, FSMenuCategory category, struct FSMenuEntry *fsm_head);
+
+int ED_fsmenu_get_nentries(struct FSMenu *fsmenu, FSMenuCategory category);
+
+struct FSMenuEntry *ED_fsmenu_get_entry(struct FSMenu *fsmenu, FSMenuCategory category, int index);
+
+char *ED_fsmenu_entry_get_path(struct FSMenuEntry *fsentry);
+void ED_fsmenu_entry_set_path(struct FSMenuEntry *fsentry, const char *path);
+
+char *ED_fsmenu_entry_get_name(struct FSMenuEntry *fsentry);
+void ED_fsmenu_entry_set_name(struct FSMenuEntry *fsentry, const char *name);
+
#endif /* __ED_FILESELECT_H__ */
diff --git a/source/blender/editors/include/ED_gpencil.h b/source/blender/editors/include/ED_gpencil.h
index 05fb76b7aea..448f2c83aad 100644
--- a/source/blender/editors/include/ED_gpencil.h
+++ b/source/blender/editors/include/ED_gpencil.h
@@ -30,20 +30,18 @@
#ifndef __ED_GPENCIL_H__
#define __ED_GPENCIL_H__
+struct ID;
struct ListBase;
struct bContext;
-struct bScreen;
struct ScrArea;
struct ARegion;
struct View3D;
-struct SpaceNode;
-struct SpaceSeq;
+struct Object;
struct bGPdata;
struct bGPDlayer;
struct bGPDframe;
+struct bGPDstroke;
struct PointerRNA;
-struct Panel;
-struct ImBuf;
struct wmKeyConfig;
@@ -65,14 +63,37 @@ typedef struct tGPspoint {
/* ----------- Grease Pencil Tools/Context ------------- */
+/* Context-dependent */
struct bGPdata **ED_gpencil_data_get_pointers(const struct bContext *C, struct PointerRNA *ptr);
struct bGPdata *ED_gpencil_data_get_active(const struct bContext *C);
+
+/* Context independent (i.e. each required part is passed in instead) */
+struct bGPdata **ED_gpencil_data_get_pointers_direct(struct ID *screen_id, struct Scene *scene,
+ struct ScrArea *sa, struct Object *ob,
+ struct PointerRNA *ptr);
+struct bGPdata *ED_gpencil_data_get_active_direct(struct ID *screen_id, struct Scene *scene,
+ struct ScrArea *sa, struct Object *ob);
+
+/* 3D View */
struct bGPdata *ED_gpencil_data_get_active_v3d(struct Scene *scene, struct View3D *v3d);
+/* ----------- Stroke Editing Utilities ---------------- */
+
+bool ED_gpencil_stroke_can_use_direct(const struct ScrArea *sa, const struct bGPDstroke *gps);
+bool ED_gpencil_stroke_can_use(const struct bContext *C, const struct bGPDstroke *gps);
+
/* ----------- Grease Pencil Operators ----------------- */
void ED_keymap_gpencil(struct wmKeyConfig *keyconf);
+
void ED_operatortypes_gpencil(void);
+void ED_operatormacros_gpencil(void);
+
+/* ------------- Copy-Paste Buffers -------------------- */
+
+/* Strokes copybuf */
+void ED_gpencil_strokes_copybuf_free(void);
+
/* ------------ Grease-Pencil Drawing API ------------------ */
/* drawgpencil.c */
@@ -80,10 +101,8 @@ void ED_operatortypes_gpencil(void);
void ED_gpencil_draw_2dimage(const struct bContext *C);
void ED_gpencil_draw_view2d(const struct bContext *C, bool onlyv2d);
void ED_gpencil_draw_view3d(struct Scene *scene, struct View3D *v3d, struct ARegion *ar, bool only3d);
-void ED_gpencil_draw_ex(struct bGPdata *gpd, int winx, int winy, const int cfra);
-
-void ED_gpencil_panel_standard_header(const struct bContext *C, struct Panel *pa);
-void ED_gpencil_panel_standard(const struct bContext *C, struct Panel *pa);
+void ED_gpencil_draw_ex(struct Scene *scene, struct bGPdata *gpd, int winx, int winy,
+ const int cfra, const char spacetype);
/* ----------- Grease-Pencil AnimEdit API ------------------ */
bool ED_gplayer_frames_looper(struct bGPDlayer *gpl, struct Scene *scene,
@@ -99,6 +118,8 @@ void ED_gpencil_select_frame(struct bGPDlayer *gpl, int selx, short select_mode
bool ED_gplayer_frames_delete(struct bGPDlayer *gpl);
void ED_gplayer_frames_duplicate(struct bGPDlayer *gpl);
+void ED_gplayer_frames_keytype_set(struct bGPDlayer *gpl, short type);
+
void ED_gplayer_snap_frames(struct bGPDlayer *gpl, struct Scene *scene, short mode);
#if 0
diff --git a/source/blender/editors/include/ED_image.h b/source/blender/editors/include/ED_image.h
index db13c628ade..4c4cec2ee29 100644
--- a/source/blender/editors/include/ED_image.h
+++ b/source/blender/editors/include/ED_image.h
@@ -31,12 +31,11 @@
#define __ED_IMAGE_H__
struct SpaceImage;
-struct Main;
struct bContext;
struct Image;
struct ImageUser;
+struct ImBuf;
struct ToolSettings;
-struct uiBlock;
struct wmWindowManager;
struct ARegion;
struct Scene;
@@ -48,7 +47,7 @@ struct Mask *ED_space_image_get_mask(struct SpaceImage *sima);
void ED_space_image_set_mask(struct bContext *C, struct SpaceImage *sima, struct Mask *mask);
bool ED_space_image_color_sample(struct Scene *scene, struct SpaceImage *sima, struct ARegion *ar, int mval[2], float r_col[3]);
-struct ImBuf *ED_space_image_acquire_buffer(struct SpaceImage *sima, void **lock_r);
+struct ImBuf *ED_space_image_acquire_buffer(struct SpaceImage *sima, void **r_lock);
void ED_space_image_release_buffer(struct SpaceImage *sima, struct ImBuf *ibuf, void *lock);
bool ED_space_image_has_buffer(struct SpaceImage *sima);
@@ -58,8 +57,10 @@ void ED_space_image_get_aspect(struct SpaceImage *sima, float *aspx, float *aspy
void ED_space_image_get_zoom(struct SpaceImage *sima, struct ARegion *ar, float *zoomx, float *zoomy);
void ED_space_image_get_uv_aspect(struct SpaceImage *sima, float *aspx, float *aspy);
-void ED_space_image_paint_update(struct wmWindowManager *wm, struct ToolSettings *settings);
-void ED_space_image_uv_sculpt_update(struct wmWindowManager *wm, struct ToolSettings *settings);
+void ED_space_image_scopes_update(const struct bContext *C, struct SpaceImage *sima, struct ImBuf *ibuf, bool use_view_settings);
+
+void ED_space_image_paint_update(struct wmWindowManager *wm, struct Scene *scene);
+void ED_space_image_uv_sculpt_update(struct wmWindowManager *wm, struct Scene *scene);
void ED_image_get_uv_aspect(struct Image *ima, struct ImageUser *iuser, float *aspx, float *aspy);
void ED_image_mouse_pos(struct SpaceImage *sima, struct ARegion *ar, const int mval[2], float co[2]);
@@ -69,8 +70,6 @@ void ED_image_point_pos__reverse(struct SpaceImage *sima, struct ARegion *ar, co
bool ED_space_image_show_render(struct SpaceImage *sima);
bool ED_space_image_show_paint(struct SpaceImage *sima);
bool ED_space_image_show_uvedit(struct SpaceImage *sima, struct Object *obedit);
-bool ED_space_image_show_texpaint(struct SpaceImage *sima, struct Object *ob);
-bool ED_space_image_show_uvshadow(struct SpaceImage *sima, struct Object *obedit);
bool ED_space_image_paint_curve(const struct bContext *C);
@@ -81,5 +80,7 @@ int ED_space_image_maskedit_mask_poll(struct bContext *C);
void ED_image_draw_info(struct Scene *scene, struct ARegion *ar, bool color_manage, bool use_default_view, int channels, int x, int y,
const unsigned char cp[4], const float fp[4], const float linearcol[4], int *zp, float *zpf);
+bool ED_space_image_show_cache(struct SpaceImage *sima);
+
#endif /* __ED_IMAGE_H__ */
diff --git a/source/blender/editors/include/ED_keyframes_draw.h b/source/blender/editors/include/ED_keyframes_draw.h
index 58a262e150a..7d163da0db0 100644
--- a/source/blender/editors/include/ED_keyframes_draw.h
+++ b/source/blender/editors/include/ED_keyframes_draw.h
@@ -34,7 +34,6 @@
struct bAnimContext;
struct AnimData;
-struct BezTriple;
struct FCurve;
struct bDopeSheet;
struct bAction;
@@ -120,8 +119,9 @@ void draw_object_channel(struct View2D *v2d, struct bDopeSheet *ads, struct Obje
void draw_scene_channel(struct View2D *v2d, struct bDopeSheet *ads, struct Scene *sce, float ypos);
/* DopeSheet Summary */
void draw_summary_channel(struct View2D *v2d, struct bAnimContext *ac, float ypos);
-/* Grease Pencil Layer */
-// XXX not restored
+/* Grease Pencil datablock summary */
+void draw_gpencil_channel(struct View2D *v2d, struct bDopeSheet *ads, struct bGPdata *gpd, float ypos);
+/* Grease Pencil Layer */
void draw_gpl_channel(struct View2D *v2d, struct bDopeSheet *ads, struct bGPDlayer *gpl, float ypos);
/* Mask Layer */
void draw_masklay_channel(struct View2D *v2d, struct bDopeSheet *ads, struct MaskLayer *masklay, float ypos);
@@ -139,11 +139,11 @@ void ob_to_keylist(struct bDopeSheet *ads, struct Object *ob, struct DLRBT_Tree
void scene_to_keylist(struct bDopeSheet *ads, struct Scene *sce, struct DLRBT_Tree *keys, struct DLRBT_Tree *blocks);
/* DopeSheet Summary */
void summary_to_keylist(struct bAnimContext *ac, struct DLRBT_Tree *keys, struct DLRBT_Tree *blocks);
+/* Grease Pencil datablock summary */
+void gpencil_to_keylist(struct bDopeSheet *ads, struct bGPdata *gpd, struct DLRBT_Tree *keys);
/* Grease Pencil Layer */
-// XXX not restored
void gpl_to_keylist(struct bDopeSheet *ads, struct bGPDlayer *gpl, struct DLRBT_Tree *keys);
/* Mask */
-// XXX not restored
void mask_to_keylist(struct bDopeSheet *UNUSED(ads), struct MaskLayer *masklay, struct DLRBT_Tree *keys);
/* ActKeyColumn API ---------------- */
diff --git a/source/blender/editors/include/ED_keyframes_edit.h b/source/blender/editors/include/ED_keyframes_edit.h
index c8365689803..c6ef303b694 100644
--- a/source/blender/editors/include/ED_keyframes_edit.h
+++ b/source/blender/editors/include/ED_keyframes_edit.h
@@ -41,12 +41,6 @@ struct Scene;
/* ************************************************ */
/* Common Macros and Defines */
-/* --------- BezTriple Selection ------------- */
-
-#define BEZ_SEL(bezt) { (bezt)->f1 |= SELECT; (bezt)->f2 |= SELECT; (bezt)->f3 |= SELECT; } (void)0
-#define BEZ_DESEL(bezt) { (bezt)->f1 &= ~SELECT; (bezt)->f2 &= ~SELECT; (bezt)->f3 &= ~SELECT; } (void)0
-#define BEZ_INVSEL(bezt) { (bezt)->f1 ^= SELECT; (bezt)->f2 ^= SELECT; (bezt)->f3 ^= SELECT; } (void)0
-
/* --------- Tool Flags ------------ */
/* bezt validation */
@@ -58,6 +52,7 @@ typedef enum eEditKeyframes_Validate {
BEZT_OK_VALUERANGE,
BEZT_OK_REGION,
BEZT_OK_REGION_LASSO,
+ BEZT_OK_REGION_CIRCLE,
} eEditKeyframes_Validate;
/* ------------ */
@@ -107,6 +102,14 @@ struct KeyframeEdit_LassoData {
int mcords_tot;
};
+/* use with BEZT_OK_REGION_CIRCLE */
+struct KeyframeEdit_CircleData {
+ const rctf *rectf_scaled;
+ const rctf *rectf_view;
+ float mval[2];
+ float radius_squared;
+};
+
/* ************************************************ */
/* Non-Destuctive Editing API (keyframes_edit.c) */
@@ -233,7 +236,7 @@ short bezt_selmap_flush(KeyframeEditData *ked, struct BezTriple *bezt);
/* ----------- BezTriple Callback (Assorted Utilities) ---------- */
-/* used to calculate the the average location of all relevant BezTriples by summing their locations */
+/* used to calculate the average location of all relevant BezTriples by summing their locations */
short bezt_calc_average(KeyframeEditData *ked, struct BezTriple *bezt);
/* used to extract a set of cfra-elems from the keyframes */
@@ -252,7 +255,7 @@ bool delete_fcurve_keys(struct FCurve *fcu);
void clear_fcurve_keys(struct FCurve *fcu);
void duplicate_fcurve_keys(struct FCurve *fcu);
-void clean_fcurve(struct FCurve *fcu, float thresh);
+void clean_fcurve(struct bAnimContext *ac, struct bAnimListElem *ale, float thresh, bool cleardefault);
void smooth_fcurve(struct FCurve *fcu);
void sample_fcurve(struct FCurve *fcu);
@@ -261,7 +264,7 @@ void sample_fcurve(struct FCurve *fcu);
void free_anim_copybuf(void);
short copy_animedit_keys(struct bAnimContext *ac, ListBase *anim_data);
short paste_animedit_keys(struct bAnimContext *ac, ListBase *anim_data,
- const eKeyPasteOffset offset_mode, const eKeyMergeMode merge_mode);
+ const eKeyPasteOffset offset_mode, const eKeyMergeMode merge_mode, bool flip);
/* ************************************************ */
diff --git a/source/blender/editors/include/ED_keyframing.h b/source/blender/editors/include/ED_keyframing.h
index 5c7b3c531be..5d76c9e0f6f 100644
--- a/source/blender/editors/include/ED_keyframing.h
+++ b/source/blender/editors/include/ED_keyframing.h
@@ -46,10 +46,8 @@ struct FCurve;
struct BezTriple;
struct bPoseChannel;
-struct bConstraint;
struct bContext;
-struct wmOperatorType;
struct ReportList;
struct PointerRNA;
@@ -293,7 +291,7 @@ bool ANIM_paste_driver(struct ReportList *reports, struct ID *id, const char rna
(U.autokey_flag & AUTOKEY_FLAG_##flag))
/* auto-keyframing feature - checks for whether anything should be done for the current frame */
-int autokeyframe_cfra_can_key(struct Scene *scene, struct ID *id);
+bool autokeyframe_cfra_can_key(struct Scene *scene, struct ID *id);
/* ************ Keyframe Checking ******************** */
diff --git a/source/blender/editors/include/ED_lattice.h b/source/blender/editors/include/ED_lattice.h
index 6636319dc9b..6fe1524cb6d 100644
--- a/source/blender/editors/include/ED_lattice.h
+++ b/source/blender/editors/include/ED_lattice.h
@@ -32,7 +32,6 @@
#define __ED_LATTICE_H__
struct Object;
-struct Lattice;
void free_editLatt(struct Object *ob);
void make_editLatt(struct Object *obedit);
diff --git a/source/blender/editors/include/ED_markers.h b/source/blender/editors/include/ED_markers.h
index 76d36623b60..5eaf459a4e1 100644
--- a/source/blender/editors/include/ED_markers.h
+++ b/source/blender/editors/include/ED_markers.h
@@ -43,10 +43,11 @@ struct TimeMarker;
/* flags for drawing markers */
enum {
DRAW_MARKERS_LINES = (1 << 0),
- DRAW_MARKERS_LOCAL = (1 << 1)
+ DRAW_MARKERS_LOCAL = (1 << 1),
+ DRAW_MARKERS_MARGIN = (1 << 2),
};
-void draw_markers_time(const struct bContext *C, int flag);
+void ED_markers_draw(const struct bContext *C, int flag);
/* Backend API ----------------------------- */
diff --git a/source/blender/editors/include/ED_mask.h b/source/blender/editors/include/ED_mask.h
index 97fd553ea19..1f13b46ff2a 100644
--- a/source/blender/editors/include/ED_mask.h
+++ b/source/blender/editors/include/ED_mask.h
@@ -31,10 +31,10 @@
#ifndef __ED_MASK_H__
#define __ED_MASK_H__
+struct bContext;
struct wmKeyConfig;
struct MaskLayer;
struct MaskLayerShape;
-struct wmEvent;
/* mask_edit.c */
void ED_mask_get_size(struct ScrArea *sa, int *width, int *height);
@@ -49,6 +49,7 @@ void ED_mask_point_pos__reverse(struct ScrArea *sa, struct ARegion *ar,
float x, float y, float *xr, float *yr);
void ED_mask_cursor_location_get(struct ScrArea *sa, float cursor[2]);
+bool ED_mask_selected_minmax(const struct bContext *C, float min[2], float max[2]);
void ED_operatortypes_mask(void);
void ED_keymap_mask(struct wmKeyConfig *keyconf);
diff --git a/source/blender/editors/include/ED_mball.h b/source/blender/editors/include/ED_mball.h
index 5e774c63841..05a4ccabd1b 100644
--- a/source/blender/editors/include/ED_mball.h
+++ b/source/blender/editors/include/ED_mball.h
@@ -32,7 +32,6 @@
#define __ED_MBALL_H__
struct bContext;
-struct MetaBall;
struct Object;
struct wmKeyConfig;
diff --git a/source/blender/editors/include/ED_mesh.h b/source/blender/editors/include/ED_mesh.h
index 6a562da0a0e..8e19ec839d8 100644
--- a/source/blender/editors/include/ED_mesh.h
+++ b/source/blender/editors/include/ED_mesh.h
@@ -40,39 +40,27 @@ struct View3D;
struct ARegion;
struct bContext;
struct wmOperator;
-struct wmWindowManager;
struct wmKeyConfig;
struct ReportList;
-struct EditSelection;
struct ViewContext;
struct bDeformGroup;
-struct MDeformWeight;
struct MDeformVert;
struct Scene;
struct Mesh;
-struct MFace;
-struct MEdge;
-struct MVert;
-struct MCol;
struct UvVertMap;
struct UvMapVert;
-struct CustomData;
struct BMEditMesh;
-struct BMEditSelection;
struct BMesh;
struct BMVert;
struct BMLoop;
struct BMBVHTree;
-struct MLoopCol;
struct BMEdge;
struct BMFace;
struct UvVertMap;
struct UvMapVert;
struct ToolSettings;
-struct Material;
struct Object;
struct rcti;
-struct MeshStatVis;
/* editmesh_utils.c */
void EDBM_verts_mirror_cache_begin_ex(struct BMEditMesh *em, const int axis,
@@ -101,8 +89,8 @@ struct DerivedMesh *EDBM_mesh_deform_dm_get(struct BMEditMesh *em);
* verts select/deselect edges and faces, if in edge select mode,
* edges select/deselect faces and vertices, and in face select mode faces select/deselect
* edges and vertices.*/
-void EDBM_select_more(struct BMEditMesh *em);
-void EDBM_select_less(struct BMEditMesh *em);
+void EDBM_select_more(struct BMEditMesh *em, const bool use_face_step);
+void EDBM_select_less(struct BMEditMesh *em, const bool use_face_step);
void EDBM_selectmode_flush_ex(struct BMEditMesh *em, const short selectmode);
void EDBM_selectmode_flush(struct BMEditMesh *em);
@@ -119,7 +107,9 @@ void EDBM_mesh_reveal(struct BMEditMesh *em);
void EDBM_update_generic(struct BMEditMesh *em, const bool do_tessface, const bool is_destructive);
-struct UvElementMap *BM_uv_element_map_create(struct BMesh *bm, const bool selected, const bool do_islands);
+struct UvElementMap *BM_uv_element_map_create(
+ struct BMesh *bm,
+ const bool selected, const bool use_winding, const bool do_islands);
void BM_uv_element_map_free(struct UvElementMap *vmap);
struct UvElement *BM_uv_element_get(struct UvElementMap *map, struct BMFace *efa, struct BMLoop *l);
@@ -128,7 +118,9 @@ struct MTexPoly *EDBM_mtexpoly_active_get(struct BMEditMesh *em, struct BMFace *
void BM_uv_vert_map_free(struct UvVertMap *vmap);
struct UvMapVert *BM_uv_vert_map_at_index(struct UvVertMap *vmap, unsigned int v);
-struct UvVertMap *BM_uv_vert_map_create(struct BMesh *bm, bool use_select, const float limit[2]);
+struct UvVertMap *BM_uv_vert_map_create(
+ struct BMesh *bm,
+ const float limit[2], const bool use_select, const bool use_winding);
void EDBM_flag_enable_all(struct BMEditMesh *em, const char hflag);
void EDBM_flag_disable_all(struct BMEditMesh *em, const char hflag);
@@ -149,9 +141,27 @@ bool EDBM_backbuf_border_mask_init(struct ViewContext *vc, const int mcords[][2]
short xmin, short ymin, short xmax, short ymax);
bool EDBM_backbuf_circle_init(struct ViewContext *vc, short xs, short ys, short rads);
-struct BMVert *EDBM_vert_find_nearest(struct ViewContext *vc, float *r_dist, const bool sel, const bool strict);
-struct BMEdge *EDBM_edge_find_nearest(struct ViewContext *vc, float *r_dist);
-struct BMFace *EDBM_face_find_nearest(struct ViewContext *vc, float *r_dist);
+struct BMVert *EDBM_vert_find_nearest_ex(
+ struct ViewContext *vc, float *r_dist,
+ const bool use_select_bias, bool use_cycle);
+struct BMVert *EDBM_vert_find_nearest(
+ struct ViewContext *vc, float *r_dist);
+
+struct BMEdge *EDBM_edge_find_nearest_ex(
+ struct ViewContext *vc, float *r_dist,
+ float *r_dist_center,
+ const bool use_select_bias, const bool use_cycle,
+ struct BMEdge **r_eed_zbuf);
+struct BMEdge *EDBM_edge_find_nearest(
+ struct ViewContext *vc, float *r_dist);
+
+struct BMFace *EDBM_face_find_nearest_ex(
+ struct ViewContext *vc, float *r_dist,
+ float *r_dist_center,
+ const bool use_select_bias, const bool use_cycle,
+ struct BMFace **r_efa_zbuf);
+struct BMFace *EDBM_face_find_nearest(
+ struct ViewContext *vc, float *r_dist);
bool EDBM_select_pick(struct bContext *C, const int mval[2], bool extend, bool deselect, bool toggle);
@@ -220,14 +230,8 @@ void ED_mesh_mirrtopo_free(MirrTopoStore_t *mesh_topo_store);
#define WEIGHT_SUBTRACT 3
bool ED_vgroup_sync_from_pose(struct Object *ob);
-struct bDeformGroup *ED_vgroup_add(struct Object *ob);
-struct bDeformGroup *ED_vgroup_add_name(struct Object *ob, const char *name);
-void ED_vgroup_delete(struct Object *ob, struct bDeformGroup *defgroup);
-void ED_vgroup_clear(struct Object *ob);
void ED_vgroup_select_by_name(struct Object *ob, const char *name);
-bool ED_vgroup_data_create(struct ID *id);
void ED_vgroup_data_clamp_range(struct ID *id, const int total);
-bool ED_vgroup_array_get(struct ID *id, struct MDeformVert **dvert_arr, int *dvert_tot);
bool ED_vgroup_array_copy(struct Object *ob, struct Object *ob_from);
bool ED_vgroup_parray_alloc(struct ID *id, struct MDeformVert ***dvert_arr, int *dvert_tot,
const bool use_vert_sel);
@@ -239,13 +243,16 @@ void ED_vgroup_parray_mirror_assign(struct Object *ob,
void ED_vgroup_parray_remove_zero(struct MDeformVert **dvert_array, const int dvert_tot,
const bool *vgroup_validmap, const int vgroup_tot,
const float epsilon, const bool keep_single);
+void ED_vgroup_parray_to_weight_array(const struct MDeformVert **dvert_array, const int dvert_tot,
+ float *dvert_weights, const int def_nr);
+void ED_vgroup_parray_from_weight_array(struct MDeformVert **dvert_array, const int dvert_tot,
+ const float *dvert_weights, const int def_nr,
+ const bool remove_zero);
void ED_vgroup_mirror(struct Object *ob,
const bool mirror_weights, const bool flip_vgroups,
const bool all_vgroups, const bool use_topology,
int *r_totmirr, int *r_totfail);
-bool ED_vgroup_object_is_edit_mode(struct Object *ob);
-
void ED_vgroup_vert_add(struct Object *ob, struct bDeformGroup *dg, int vertnum, float weight, int assignmode);
void ED_vgroup_vert_remove(struct Object *ob, struct bDeformGroup *dg, int vertnum);
float ED_vgroup_vert_weight(struct Object *ob, struct bDeformGroup *dg, int vertnum);
@@ -264,9 +271,10 @@ void ED_mesh_faces_remove(struct Mesh *mesh, struct ReportList *reports, int cou
void ED_mesh_edges_remove(struct Mesh *mesh, struct ReportList *reports, int count);
void ED_mesh_vertices_remove(struct Mesh *mesh, struct ReportList *reports, int count);
-void ED_mesh_calc_tessface(struct Mesh *mesh);
+void ED_mesh_calc_tessface(struct Mesh *mesh, bool free_mpoly);
void ED_mesh_update(struct Mesh *mesh, struct bContext *C, int calc_edges, int calc_tessface);
+void ED_mesh_uv_texture_ensure(struct Mesh *me, const char *name);
int ED_mesh_uv_texture_add(struct Mesh *me, const char *name, const bool active_set);
bool ED_mesh_uv_texture_remove_index(struct Mesh *me, const int n);
bool ED_mesh_uv_texture_remove_active(struct Mesh *me);
diff --git a/source/blender/editors/include/ED_node.h b/source/blender/editors/include/ED_node.h
index 824c82a0069..1445308c485 100644
--- a/source/blender/editors/include/ED_node.h
+++ b/source/blender/editors/include/ED_node.h
@@ -33,7 +33,6 @@
struct ID;
struct Main;
-struct Material;
struct Scene;
struct Tex;
struct bContext;
@@ -104,6 +103,8 @@ void ED_node_set_active(struct Main *bmain, struct bNodeTree *ntree, struct bNod
void ED_node_composite_job(const struct bContext *C, struct bNodeTree *nodetree, struct Scene *scene_owner);
+void ED_node_id_unref(struct SpaceNode *snode, const ID *id);
+
/* node_ops.c */
void ED_operatormacros_node(void);
diff --git a/source/blender/editors/include/ED_object.h b/source/blender/editors/include/ED_object.h
index 2328f7d5135..c62bdc1ba87 100644
--- a/source/blender/editors/include/ED_object.h
+++ b/source/blender/editors/include/ED_object.h
@@ -35,33 +35,17 @@
extern "C" {
#endif
-struct BMEdge;
-struct BMFace;
-struct BMVert;
-struct BPoint;
struct Base;
-struct BezTriple;
-struct Curve;
-struct EditBone;
struct EnumPropertyItem;
struct ID;
-struct KeyBlock;
-struct Lattice;
struct Main;
-struct Mesh;
-struct MetaElem;
struct ModifierData;
-struct HookModifierData;
-struct Nurb;
struct Object;
struct ReportList;
struct Scene;
-struct View3D;
-struct ViewContext;
struct bConstraint;
struct bContext;
struct bPoseChannel;
-struct wmEvent;
struct wmKeyConfig;
struct wmKeyMap;
struct wmOperator;
@@ -93,7 +77,7 @@ typedef enum eParentType {
PAR_PATH_CONST,
PAR_LATTICE,
PAR_VERTEX,
- PAR_VERTEX_TRI
+ PAR_VERTEX_TRI,
} eParentType;
#ifdef __RNA_TYPES_H__
@@ -101,9 +85,10 @@ extern struct EnumPropertyItem prop_clear_parent_types[];
extern struct EnumPropertyItem prop_make_parent_types[];
#endif
-int ED_object_parent_set(struct ReportList *reports, struct Main *bmain, struct Scene *scene, struct Object *ob,
- struct Object *par, int partype, bool xmirror, bool keep_transform, const int vert_par[3]);
-void ED_object_parent_clear(struct Object *ob, int type);
+bool ED_object_parent_set(struct ReportList *reports, struct Main *bmain, struct Scene *scene, struct Object *ob,
+ struct Object *par, int partype, const bool xmirror, const bool keep_transform,
+ const int vert_par[3]);
+void ED_object_parent_clear(struct Object *ob, const int type);
struct Base *ED_object_scene_link(struct Scene *scene, struct Object *ob);
void ED_keymap_proportional_cycle(struct wmKeyConfig *keyconf, struct wmKeyMap *keymap);
@@ -122,7 +107,7 @@ void ED_base_object_free_and_unlink(struct Main *bmain, struct Scene *scene, str
/* single object duplicate, if (dupflag == 0), fully linked, else it uses the flags given */
struct Base *ED_object_add_duplicate(struct Main *bmain, struct Scene *scene, struct Base *base, int dupflag);
-void ED_object_parent(struct Object *ob, struct Object *parent, int type, const char *substr);
+void ED_object_parent(struct Object *ob, struct Object *parent, const int type, const char *substr);
bool ED_object_mode_compat_set(struct bContext *C, struct Object *ob, int mode, struct ReportList *reports);
void ED_object_toggle_modes(struct bContext *C, int mode);
@@ -137,12 +122,18 @@ void ED_object_editmode_exit(struct bContext *C, int flag);
void ED_object_editmode_enter(struct bContext *C, int flag);
bool ED_object_editmode_load(struct Object *obedit);
+bool ED_object_editmode_calc_active_center(struct Object *obedit, const bool select_only, float r_center[3]);
+
void ED_object_location_from_view(struct bContext *C, float loc[3]);
void ED_object_rotation_from_view(struct bContext *C, float rot[3], const char align_axis);
void ED_object_base_init_transform(struct bContext *C, struct Base *base, const float loc[3], const float rot[3]);
-float ED_object_new_primitive_matrix(struct bContext *C, struct Object *editob,
- const float loc[3], const float rot[3], float primmat[4][4],
- bool apply_diameter);
+float ED_object_new_primitive_matrix(
+ struct bContext *C, struct Object *editob,
+ const float loc[3], const float rot[3], float primmat[4][4]);
+
+
+/* Avoid allowing too much insane values even by typing (typos can hang/crash Blender otherwise). */
+#define OBJECT_ADD_SIZE_MAXF 1.0e12f
void ED_object_add_unit_props(struct wmOperatorType *ot);
void ED_object_add_generic_props(struct wmOperatorType *ot, bool do_editmode);
@@ -151,10 +142,12 @@ bool ED_object_add_generic_get_opts(struct bContext *C, struct wmOperator *op, c
bool *enter_editmode, unsigned int *layer, bool *is_view_aligned);
struct Object *ED_object_add_type(
- struct bContext *C, int type, const float loc[3], const float rot[3],
- bool enter_editmode, unsigned int layer) ATTR_RETURNS_NONNULL;
+ struct bContext *C,
+ int type, const char *name, const float loc[3], const float rot[3],
+ bool enter_editmode, unsigned int layer)
+ ATTR_NONNULL(1) ATTR_RETURNS_NONNULL;
-void ED_object_single_users(struct Main *bmain, struct Scene *scene, bool full, bool copy_groups);
+void ED_object_single_users(struct Main *bmain, struct Scene *scene, const bool full, const bool copy_groups);
void ED_object_single_user(struct Main *bmain, struct Scene *scene, struct Object *ob);
/* object motion paths */
@@ -172,6 +165,9 @@ void ED_object_constraint_set_active(struct Object *ob, struct bConstraint *con)
void ED_object_constraint_update(struct Object *ob);
void ED_object_constraint_dependency_update(struct Main *bmain, struct Object *ob);
+void ED_object_constraint_tag_update(struct Object *ob, struct bConstraint *con);
+void ED_object_constraint_dependency_tag_update(struct Main *bmain, struct Object *ob, struct bConstraint *con);
+
/* object_lattice.c */
bool mouse_lattice(struct bContext *C, const int mval[2], bool extend, bool deselect, bool toggle);
void undo_push_lattice(struct bContext *C, const char *name);
@@ -208,12 +204,6 @@ bool ED_object_multires_update_totlevels_cb(struct Object *ob, void *totlevel_v)
/* object_select.c */
void ED_object_select_linked_by_id(struct bContext *C, struct ID *id);
-
-bool *ED_vgroup_subset_from_select_type(struct Object *ob, enum eVGroupSelect subset_type,
- int *r_vgroup_tot, int *r_subset_count);
-void ED_vgroup_subset_to_index_array(const bool *vgroup_validmap, const int vgroup_tot,
- int *r_vgroup_subset_map);
-
struct EnumPropertyItem *ED_object_vgroup_selection_itemf_helper(
const struct bContext *C,
struct PointerRNA *ptr,
diff --git a/source/blender/editors/include/ED_outliner.h b/source/blender/editors/include/ED_outliner.h
new file mode 100644
index 00000000000..af4af8e2f5d
--- /dev/null
+++ b/source/blender/editors/include/ED_outliner.h
@@ -0,0 +1,36 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2015, Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file ED_outliner.h
+ * \ingroup editors
+ */
+
+#ifndef __ED_OUTLINER_H__
+#define __ED_OUTLINER_H__
+
+struct ID;
+struct SpaceOops;
+
+/* Used to check whether a given texture context is valid in current context. */
+void ED_outliner_id_unref(struct SpaceOops *so, const struct ID *id);
+
+#endif /* __ED_OUTLINER_H__ */
diff --git a/source/blender/editors/include/ED_paint.h b/source/blender/editors/include/ED_paint.h
index decd79fcc7b..e46f4b966c0 100644
--- a/source/blender/editors/include/ED_paint.h
+++ b/source/blender/editors/include/ED_paint.h
@@ -26,7 +26,6 @@
#define __ED_PAINT_H__
struct bContext;
-struct RegionView3D;
struct wmKeyConfig;
struct wmOperator;
@@ -47,9 +46,9 @@ typedef bool (*UndoCleanupCb)(struct bContext *C, struct ListBase *lb);
int ED_undo_paint_step(struct bContext *C, int type, int step, const char *name);
void ED_undo_paint_step_num(struct bContext *C, int type, int num);
-const char *ED_undo_paint_get_name(struct bContext *C, int type, int nr, int *active);
+const char *ED_undo_paint_get_name(struct bContext *C, int type, int nr, bool *r_active);
void ED_undo_paint_free(void);
-int ED_undo_paint_valid(int type, const char *name);
+bool ED_undo_paint_is_valid(int type, const char *name);
bool ED_undo_paint_empty(int type);
void ED_undo_paint_push_begin(int type, const char *name, UndoRestoreCb restore, UndoFreeCb free, UndoCleanupCb cleanup);
void ED_undo_paint_push_end(int type);
@@ -59,7 +58,7 @@ void ED_undo_paint_push_end(int type);
void ED_image_undo_restore(struct bContext *C, struct ListBase *lb);
void ED_image_undo_free(struct ListBase *lb);
void ED_imapaint_clear_partial_redraw(void);
-void ED_imapaint_dirty_region(struct Image *ima, struct ImBuf *ibuf, int x, int y, int w, int h);
+void ED_imapaint_dirty_region(struct Image *ima, struct ImBuf *ibuf, int x, int y, int w, int h, bool find_old);
void ED_imapaint_bucket_fill(struct bContext *C, float color[3], struct wmOperator *op);
#endif /* __ED_PAINT_H__ */
diff --git a/source/blender/editors/include/ED_particle.h b/source/blender/editors/include/ED_particle.h
index f9516f255cf..6cb8c0cfb19 100644
--- a/source/blender/editors/include/ED_particle.h
+++ b/source/blender/editors/include/ED_particle.h
@@ -35,10 +35,7 @@
struct bContext;
struct Object;
struct ParticleEditSettings;
-struct ParticleSystem;
-struct RadialControl;
struct rcti;
-struct wmKeyConfig;
struct PTCacheEdit;
struct Scene;
@@ -69,9 +66,9 @@ void PE_undo_push(struct Scene *scene, const char *str);
void PE_undo_step(struct Scene *scene, int step);
void PE_undo(struct Scene *scene);
void PE_redo(struct Scene *scene);
-int PE_undo_valid(struct Scene *scene);
+bool PE_undo_is_valid(struct Scene *scene);
void PE_undo_number(struct Scene *scene, int nr);
-const char *PE_undo_get_name(struct Scene *scene, int nr, int *active);
+const char *PE_undo_get_name(struct Scene *scene, int nr, bool *r_active);
#endif /* __ED_PARTICLE_H__ */
diff --git a/source/blender/editors/include/ED_render.h b/source/blender/editors/include/ED_render.h
index 14595a4c668..707d7c6c693 100644
--- a/source/blender/editors/include/ED_render.h
+++ b/source/blender/editors/include/ED_render.h
@@ -35,12 +35,9 @@ struct ID;
struct Main;
struct MTex;
struct Render;
-struct RenderInfo;
struct Scene;
struct ScrArea;
-struct RegionView3D;
-struct RenderEngine;
-struct View3D;
+struct wmWindowManager;
/* render_ops.c */
@@ -50,23 +47,13 @@ void ED_operatortypes_render(void);
void ED_render_id_flush_update(struct Main *bmain, struct ID *id);
void ED_render_engine_changed(struct Main *bmain);
-void ED_render_engine_area_exit(struct ScrArea *sa);
+void ED_render_engine_area_exit(struct Main *bmain, struct ScrArea *sa);
void ED_render_scene_update(struct Main *bmain, struct Scene *scene, int updated);
+void ED_render_scene_update_pre(struct Main *bmain, struct Scene *scene, bool time);
-void ED_viewport_render_kill_jobs(const struct bContext *C, bool free_database);
+void ED_viewport_render_kill_jobs(struct wmWindowManager *wm, struct Main *bmain, bool free_database);
struct Scene *ED_render_job_get_scene(const struct bContext *C);
-
-/* render_preview.c */
-
-/* stores rendered preview - is also used for icons */
-typedef struct RenderInfo {
- int pr_rectx;
- int pr_recty;
- short curtile, tottile;
- rcti disprect; /* storage for view3d preview rect */
- unsigned int *rect;
- struct Render *re; /* persistent render */
-} RenderInfo;
+struct Scene *ED_render_job_get_current_scene(const struct bContext *C);
/* Render the preview
*
@@ -74,18 +61,23 @@ typedef struct RenderInfo {
* - PR_BUTS_RENDER: preview is rendered for buttons window
* - PR_ICON_RENDER: preview is rendered for icons. hopefully fast enough for at least 32x32
* - PR_NODE_RENDER: preview is rendered for node editor
+ * - PR_ICON_DEFERRED: No render, we just ensure deferred icon data gets generated.
*/
-#define PR_BUTS_RENDER 0
-#define PR_ICON_RENDER 1
-#define PR_NODE_RENDER 2
+enum {
+ PR_BUTS_RENDER = 0,
+ PR_ICON_RENDER = 1,
+ PR_NODE_RENDER = 2,
+ PR_ICON_DEFERRED = 3,
+};
-void ED_preview_init_dbase(void);
+void ED_preview_ensure_dbase(void);
void ED_preview_free_dbase(void);
void ED_preview_shader_job(const struct bContext *C, void *owner, struct ID *id, struct ID *parent, struct MTex *slot, int sizex, int sizey, int method);
+void ED_preview_icon_render(struct Main *bmain, struct Scene *scene, struct ID *id, unsigned int *rect, int sizex, int sizey);
void ED_preview_icon_job(const struct bContext *C, void *owner, struct ID *id, unsigned int *rect, int sizex, int sizey);
-void ED_preview_kill_jobs(const struct bContext *C);
+void ED_preview_kill_jobs(struct wmWindowManager *wm, struct Main *bmain);
void ED_preview_draw(const struct bContext *C, void *idp, void *parentp, void *slot, rcti *rect);
diff --git a/source/blender/editors/include/ED_screen.h b/source/blender/editors/include/ED_screen.h
index d31be3e961f..5bc606ca725 100644
--- a/source/blender/editors/include/ED_screen.h
+++ b/source/blender/editors/include/ED_screen.h
@@ -42,7 +42,6 @@ struct wmNotifier;
struct wmEvent;
struct wmKeyConfig;
struct bContext;
-struct SpaceType;
struct Scene;
struct bScreen;
struct ARegion;
@@ -58,15 +57,19 @@ void ED_region_set(const struct bContext *C, struct ARegion *ar);
void ED_region_update_rect(struct bContext *C, struct ARegion *ar);
void ED_region_init(struct bContext *C, struct ARegion *ar);
void ED_region_tag_redraw(struct ARegion *ar);
-void ED_region_tag_redraw_partial(struct ARegion *ar, struct rcti *rct);
+void ED_region_tag_redraw_partial(struct ARegion *ar, const struct rcti *rct);
void ED_region_tag_redraw_overlay(struct ARegion *ar);
void ED_region_tag_refresh_ui(struct ARegion *ar);
void ED_region_panels_init(struct wmWindowManager *wm, struct ARegion *ar);
-void ED_region_panels(const struct bContext *C, struct ARegion *ar, int vertical, const char *context, int contextnr);
+void ED_region_panels(
+ const struct bContext *C, struct ARegion *ar,
+ const char *context, int contextnr,
+ const bool vertical);
void ED_region_header_init(struct ARegion *ar);
void ED_region_header(const struct bContext *C, struct ARegion *ar);
void ED_region_toggle_hidden(struct bContext *C, struct ARegion *ar);
-void ED_region_info_draw(struct ARegion *ar, const char *text, int block, float fill_color[4]);
+void ED_region_info_draw(struct ARegion *ar, const char *text, float fill_color[4], const bool full_redraw);
+void ED_region_image_metadata_draw(int x, int y, struct ImBuf *ibuf, rctf frame, float zoomx, float zoomy);
void ED_region_grid_draw(struct ARegion *ar, float zoomx, float zoomy);
float ED_region_blend_factor(struct ARegion *ar);
void ED_region_visible_rect(struct ARegion *ar, struct rcti *rect);
@@ -76,7 +79,6 @@ void ED_region_visible_rect(struct ARegion *ar, struct rcti *rect);
void ED_spacetypes_keymap(struct wmKeyConfig *keyconf);
int ED_area_header_switchbutton(const struct bContext *C, struct uiBlock *block, int yco);
-
/* areas */
void ED_area_initialize(struct wmWindowManager *wm, struct wmWindow *win, struct ScrArea *sa);
void ED_area_exit(struct bContext *C, struct ScrArea *sa);
@@ -86,6 +88,7 @@ void ED_area_tag_redraw(ScrArea *sa);
void ED_area_tag_redraw_regiontype(ScrArea *sa, int type);
void ED_area_tag_refresh(ScrArea *sa);
void ED_area_do_refresh(struct bContext *C, ScrArea *sa);
+void ED_area_azones_update(ScrArea *sa, const int mouse_xy[]);
void ED_area_headerprint(ScrArea *sa, const char *str);
void ED_area_newspace(struct bContext *C, ScrArea *sa, int type);
void ED_area_prevspace(struct bContext *C, ScrArea *sa);
@@ -99,19 +102,21 @@ void ED_screen_refresh(struct wmWindowManager *wm, struct wmWindow *win);
void ED_screen_do_listen(struct bContext *C, struct wmNotifier *note);
bScreen *ED_screen_duplicate(struct wmWindow *win, struct bScreen *sc);
bScreen *ED_screen_add(struct wmWindow *win, struct Scene *scene, const char *name);
-void ED_screen_set(struct bContext *C, struct bScreen *sc);
-void ED_screen_delete(struct bContext *C, struct bScreen *sc);
+bool ED_screen_set(struct bContext *C, struct bScreen *sc);
+bool ED_screen_delete(struct bContext *C, struct bScreen *sc);
void ED_screen_set_scene(struct bContext *C, struct bScreen *screen, struct Scene *scene);
-void ED_screen_delete_scene(struct bContext *C, struct Scene *scene);
+bool ED_screen_delete_scene(struct bContext *C, struct Scene *scene);
void ED_screen_set_subwinactive(struct bContext *C, struct wmEvent *event);
void ED_screen_exit(struct bContext *C, struct wmWindow *window, struct bScreen *screen);
void ED_screen_animation_timer(struct bContext *C, int redraws, int refresh, int sync, int enable);
void ED_screen_animation_timer_update(struct bScreen *screen, int redraws, int refresh);
+void ED_screen_restore_temp_type(struct bContext *C, ScrArea *sa);
ScrArea *ED_screen_full_newspace(struct bContext *C, ScrArea *sa, int type);
-void ED_screen_full_prevspace(struct bContext *C, ScrArea *sa);
+void ED_screen_full_prevspace(struct bContext *C, ScrArea *sa, const bool was_prev_temp);
void ED_screen_full_restore(struct bContext *C, ScrArea *sa);
-struct ScrArea *ED_screen_full_toggle(struct bContext *C, struct wmWindow *win, struct ScrArea *sa);
+struct ScrArea *ED_screen_state_toggle(struct bContext *C, struct wmWindow *win, struct ScrArea *sa, const short state);
void ED_screens_header_tools_menu_create(struct bContext *C, struct uiLayout *layout, void *arg);
+bool ED_screen_stereo3d_required(struct bScreen *screen);
/* anim */
void ED_update_for_newframe(struct Main *bmain, struct Scene *scene, int mute);
@@ -119,6 +124,7 @@ void ED_update_for_newframe(struct Main *bmain, struct Scene *scene, int mute
void ED_refresh_viewport_fps(struct bContext *C);
int ED_screen_animation_play(struct bContext *C, int sync, int mode);
bScreen *ED_screen_animation_playing(const struct wmWindowManager *wm);
+bScreen *ED_screen_animation_no_scrub(const struct wmWindowManager *wm);
/* screen keymaps */
void ED_operatortypes_screen(void);
diff --git a/source/blender/editors/include/ED_screen_types.h b/source/blender/editors/include/ED_screen_types.h
index 2b02606c6d9..effecf43839 100644
--- a/source/blender/editors/include/ED_screen_types.h
+++ b/source/blender/editors/include/ED_screen_types.h
@@ -93,10 +93,13 @@ typedef struct AZone {
short x1, y1, x2, y2;
/* for clip */
rcti rect;
+ /* for fade in/out */
+ float alpha;
} AZone;
/* actionzone type */
#define AZONE_AREA 1 /* corner widgets for splitting areas */
#define AZONE_REGION 2 /* when a region is collapsed, draw a handle to expose */
+#define AZONE_FULLSCREEN 3 /* when in editor fullscreen draw a corner to go to normal mode */
#endif /* __ED_SCREEN_TYPES_H__ */
diff --git a/source/blender/editors/include/ED_sculpt.h b/source/blender/editors/include/ED_sculpt.h
index 85ff9b5d246..6daaac5bb42 100644
--- a/source/blender/editors/include/ED_sculpt.h
+++ b/source/blender/editors/include/ED_sculpt.h
@@ -41,8 +41,6 @@ struct rcti;
void ED_operatortypes_sculpt(void);
void ED_sculpt_redraw_planes_get(float planes[4][4], struct ARegion *ar,
struct RegionView3D *rv3d, struct Object *ob);
-void ED_sculpt_stroke_get_average(struct Object *ob, float stroke[3]);
-bool ED_sculpt_minmax(struct bContext *C, float min[3], float max[3]);
int ED_sculpt_mask_box_select(struct bContext *C, struct ViewContext *vc, const struct rcti *rect, bool select, bool extend);
#endif /* __ED_SCULPT_H__ */
diff --git a/source/blender/editors/include/ED_sequencer.h b/source/blender/editors/include/ED_sequencer.h
index 4e9d67df61e..94885c2abe0 100644
--- a/source/blender/editors/include/ED_sequencer.h
+++ b/source/blender/editors/include/ED_sequencer.h
@@ -27,6 +27,7 @@
#ifndef __ED_SEQUENCER_H__
#define __ED_SEQUENCER_H__
+struct bContext;
struct Scene;
struct Sequence;
struct SpaceSeq;
@@ -39,7 +40,12 @@ bool ED_space_sequencer_check_show_maskedit(struct SpaceSeq *sseq, struct Scene
int ED_space_sequencer_maskedit_poll(struct bContext *C);
bool ED_space_sequencer_check_show_imbuf(struct SpaceSeq *sseq);
+bool ED_space_sequencer_check_show_strip(struct SpaceSeq *sseq);
void ED_operatormacros_sequencer(void);
+Sequence *ED_sequencer_special_preview_get(void);
+void ED_sequencer_special_preview_set(struct bContext *C, const int mval[2]);
+void ED_sequencer_special_preview_clear(void);
+
#endif /* __ED_SEQUENCER_H__ */
diff --git a/source/blender/editors/include/ED_text.h b/source/blender/editors/include/ED_text.h
index 9a36cb3d6ab..5df7d9cfaef 100644
--- a/source/blender/editors/include/ED_text.h
+++ b/source/blender/editors/include/ED_text.h
@@ -31,8 +31,11 @@
#define __ED_TEXT_H__
struct bContext;
+struct SpaceText;
+struct ARegion;
void ED_text_undo_step(struct bContext *C, int step);
+bool ED_text_region_location_from_cursor(struct SpaceText *st, struct ARegion *ar, const int cursor_co[2], int r_pixel_co[2]);
#endif /* __ED_TEXT_H__ */
diff --git a/source/blender/editors/include/ED_transform.h b/source/blender/editors/include/ED_transform.h
index daa6864b5aa..b14ba45a64d 100644
--- a/source/blender/editors/include/ED_transform.h
+++ b/source/blender/editors/include/ED_transform.h
@@ -35,17 +35,14 @@
/* ******************* Registration Function ********************** */
struct ARegion;
-struct EnumPropertyItem;
struct ListBase;
struct Object;
struct View3D;
struct bContext;
-struct uiLayout;
struct wmEvent;
struct wmKeyConfig;
struct wmKeyMap;
struct wmOperatorType;
-struct wmWindowManager;
void transform_keymap_for_space(struct wmKeyConfig *keyconf, struct wmKeyMap *keymap, int spaceid);
void transform_operatortypes(void);
@@ -73,6 +70,7 @@ enum TfmMode {
TFM_BONE_ENVELOPE,
TFM_CURVE_SHRINKFATTEN,
TFM_MASK_SHRINKFATTEN,
+ TFM_GPENCIL_SHRINKFATTEN,
TFM_BONE_ROLL,
TFM_TIME_TRANSLATE,
TFM_TIME_SLIDE,
@@ -85,7 +83,8 @@ enum TfmMode {
TFM_ALIGN,
TFM_EDGE_SLIDE,
TFM_VERT_SLIDE,
- TFM_SEQ_SLIDE
+ TFM_SEQ_SLIDE,
+ TFM_BONE_ENVELOPE_DIST,
};
/* TRANSFORM CONTEXTS */
@@ -99,6 +98,7 @@ enum TfmMode {
#define CTX_MOVIECLIP (1 << 6)
#define CTX_MASK (1 << 7)
#define CTX_PAINT_CURVE (1 << 8)
+#define CTX_GPENCIL_STROKES (1 << 9)
/* Standalone call to get the transformation center corresponding to the current situation
* returns 1 if successful, 0 otherwise (usually means there's no selection)
@@ -107,7 +107,6 @@ enum TfmMode {
bool calculateTransformCenter(struct bContext *C, int centerMode, float cent3d[3], float cent2d[2]);
struct TransInfo;
-struct ScrArea;
struct Base;
struct Scene;
struct Object;
@@ -128,7 +127,7 @@ void BIF_createTransformOrientation(struct bContext *C, struct ReportList *repor
void BIF_selectTransformOrientation(struct bContext *C, struct TransformOrientation *ts);
void BIF_selectTransformOrientationValue(struct bContext *C, int orientation);
-void ED_getTransformOrientationMatrix(const struct bContext *C, float orientation_mat[3][3], const bool activeOnly);
+void ED_getTransformOrientationMatrix(const struct bContext *C, float orientation_mat[3][3], const short around);
int BIF_countTransformOrientation(const struct bContext *C);
@@ -146,6 +145,7 @@ int BIF_countTransformOrientation(const struct bContext *C);
#define P_CORRECT_UV (1 << 8)
#define P_NO_DEFAULTS (1 << 10)
#define P_NO_TEXSPACE (1 << 11)
+#define P_GPENCIL_EDIT (1 << 12)
void Transform_Properties(struct wmOperatorType *ot, int flags);
diff --git a/source/blender/editors/include/ED_util.h b/source/blender/editors/include/ED_util.h
index 6d9f1c4eda0..496ce7f2c60 100644
--- a/source/blender/editors/include/ED_util.h
+++ b/source/blender/editors/include/ED_util.h
@@ -31,22 +31,18 @@
#ifndef __ED_UTIL_H__
#define __ED_UTIL_H__
-struct Scene;
-struct Object;
struct bContext;
-struct ARegion;
-struct uiBlock;
struct wmOperator;
struct wmOperatorType;
-struct BMEditMesh;
-struct Mesh;
/* ed_util.c */
void ED_editors_init(struct bContext *C);
void ED_editors_exit(struct bContext *C);
-void ED_editors_flush_edits(const struct bContext *C, bool for_render);
+bool ED_editors_flush_edits(const struct bContext *C, bool for_render);
+
+void ED_spacedata_id_unref(struct SpaceLink *sl, const struct ID *id);
/* ************** Undo ************************ */
@@ -66,7 +62,7 @@ int ED_undo_operator_repeat(struct bContext *C, struct wmOperator *op);
void ED_undo_operator_repeat_cb(struct bContext *C, void *arg_op, void *arg_unused);
void ED_undo_operator_repeat_cb_evt(struct bContext *C, void *arg_op, int arg_unused);
-int ED_undo_valid(const struct bContext *C, const char *undoname);
+bool ED_undo_is_valid(const struct bContext *C, const char *undoname);
/* undo_editmode.c */
void undo_editmode_push(struct bContext *C, const char *name,
diff --git a/source/blender/editors/include/ED_uvedit.h b/source/blender/editors/include/ED_uvedit.h
index 4b82fa40c6a..535683823bf 100644
--- a/source/blender/editors/include/ED_uvedit.h
+++ b/source/blender/editors/include/ED_uvedit.h
@@ -31,18 +31,17 @@
#define __ED_UVEDIT_H__
struct ARegionType;
+struct BMesh;
struct BMEditMesh;
struct BMFace;
struct BMLoop;
struct Image;
struct ImageUser;
-struct MTFace;
struct MTexPoly;
struct Main;
struct Object;
struct Scene;
struct SpaceImage;
-struct bContext;
struct bNode;
struct wmKeyConfig;
@@ -52,6 +51,7 @@ void ED_keymap_uvedit(struct wmKeyConfig *keyconf);
void ED_uvedit_assign_image(struct Main *bmain, struct Scene *scene, struct Object *obedit, struct Image *ima, struct Image *previma);
bool ED_uvedit_minmax(struct Scene *scene, struct Image *ima, struct Object *obedit, float min[2], float max[2]);
+void ED_uvedit_select_all(struct BMesh *bm);
bool ED_object_get_active_image(struct Object *ob, int mat_nr,
struct Image **r_ima, struct ImageUser **r_iuser, struct bNode **r_node, struct bNodeTree **r_ntree);
@@ -92,19 +92,24 @@ void uvedit_uv_select_disable(struct BMEditMesh *em, struct Scene *scene, struct
bool ED_uvedit_nearest_uv(struct Scene *scene, struct Object *obedit, struct Image *ima,
const float co[2], float r_uv[2]);
+void ED_uvedit_get_aspect(struct Scene *scene, struct Object *ob, struct BMesh *em, float *aspx, float *aspy);
+
/* uvedit_unwrap_ops.c */
void ED_uvedit_live_unwrap_begin(struct Scene *scene, struct Object *obedit);
void ED_uvedit_live_unwrap_re_solve(void);
void ED_uvedit_live_unwrap_end(short cancel);
void ED_uvedit_live_unwrap(struct Scene *scene, struct Object *obedit);
+void ED_uvedit_pack_islands(struct Scene *scene, struct Object *ob, struct BMesh *bm, bool selected, bool correct_aspect, bool do_rotate);
+void ED_uvedit_unwrap_cube_project(struct Object *ob, struct BMesh *bm, float cube_size, bool use_select);
/* single call up unwrap using scene settings, used for edge tag unwrapping */
void ED_unwrap_lscm(struct Scene *scene, struct Object *obedit, const short sel);
+
/* uvedit_draw.c */
-void draw_image_cursor(struct ARegion *ar, const float cursor[2]);
-void draw_uvedit_main(struct SpaceImage *sima, struct ARegion *ar, struct Scene *scene, struct Object *obedit, struct Object *obact);
+void ED_image_draw_cursor(struct ARegion *ar, const float cursor[2]);
+void ED_uvedit_draw_main(struct SpaceImage *sima, struct ARegion *ar, struct Scene *scene, struct Object *obedit, struct Object *obact);
/* uvedit_buttons.c */
void ED_uvedit_buttons_register(struct ARegionType *art);
diff --git a/source/blender/editors/include/ED_view3d.h b/source/blender/editors/include/ED_view3d.h
index bd4f37cfb1e..416e821b3f8 100644
--- a/source/blender/editors/include/ED_view3d.h
+++ b/source/blender/editors/include/ED_view3d.h
@@ -61,6 +61,11 @@ struct rcti;
struct wmOperator;
struct wmOperatorType;
struct wmWindow;
+struct wmWindowManager;
+struct GPUFX;
+struct GPUOffScreen;
+struct GPUFXSettings;
+enum eGPUFXFlags;
/* for derivedmesh drawing callbacks, for view3d_select, .... */
typedef struct ViewContext {
@@ -99,7 +104,7 @@ void ED_view3d_lastview_store(struct RegionView3D *rv3d);
/* Depth buffer */
void ED_view3d_depth_update(struct ARegion *ar);
-float ED_view3d_depth_read_cached(struct ViewContext *vc, int x, int y);
+float ED_view3d_depth_read_cached(const struct ViewContext *vc, int x, int y);
void ED_view3d_depth_tag_update(struct RegionView3D *rv3d);
/* Projection */
@@ -214,55 +219,67 @@ void ED_view3d_win_to_vector(const struct ARegion *ar, const float mval[2], floa
bool ED_view3d_win_to_segment(const struct ARegion *ar, struct View3D *v3d, const float mval[2],
float r_ray_start[3], float r_ray_end[3], const bool do_clip);
void ED_view3d_ob_project_mat_get(const struct RegionView3D *v3d, struct Object *ob, float pmat[4][4]);
+void ED_view3d_ob_project_mat_get_from_obmat(const struct RegionView3D *rv3d, float obmat[4][4], float pmat[4][4]);
void ED_view3d_unproject(struct bglMats *mats, float out[3], const float x, const float y, const float z);
/* end */
-void ED_view3d_dist_range_get(struct View3D *v3d,
- float r_dist_range[2]);
-bool ED_view3d_clip_range_get(struct View3D *v3d, struct RegionView3D *rv3d,
- float *r_clipsta, float *r_clipend, const bool use_ortho_factor);
-bool ED_view3d_viewplane_get(struct View3D *v3d, struct RegionView3D *rv3d, int winxi, int winyi,
- struct rctf *r_viewplane, float *r_clipsta, float *r_clipend, float *r_pixsize);
+void ED_view3d_dist_range_get(
+ const struct View3D *v3d,
+ float r_dist_range[2]);
+bool ED_view3d_clip_range_get(
+ const struct View3D *v3d, const struct RegionView3D *rv3d,
+ float *r_clipsta, float *r_clipend, const bool use_ortho_factor);
+bool ED_view3d_viewplane_get(
+ const struct View3D *v3d, const 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);
-void ED_view3d_calc_camera_border_size(struct Scene *scene, struct ARegion *ar,
- struct View3D *v3d, struct RegionView3D *rv3d,
- float r_size[2]);
+void ED_view3d_calc_camera_border(
+ const struct Scene *scene, const struct ARegion *ar,
+ const struct View3D *v3d, const struct RegionView3D *rv3d,
+ struct rctf *r_viewborder, const bool no_shift);
+void ED_view3d_calc_camera_border_size(
+ const struct Scene *scene, const struct ARegion *ar,
+ const struct View3D *v3d, const struct RegionView3D *rv3d,
+ float r_size[2]);
bool ED_view3d_calc_render_border(struct Scene *scene, struct View3D *v3d,
struct ARegion *ar, struct rcti *rect);
+void ED_view3d_clipping_calc_from_boundbox(float clip[6][4], const struct BoundBox *clipbb, const bool is_flip);
void ED_view3d_clipping_calc(struct BoundBox *bb, float planes[4][4], struct bglMats *mats, const struct rcti *rect);
void ED_view3d_clipping_local(struct RegionView3D *rv3d, float mat[4][4]);
-bool ED_view3d_clipping_test(struct RegionView3D *rv3d, const float co[3], const bool is_local);
+bool ED_view3d_clipping_test(const struct RegionView3D *rv3d, const float co[3], const bool is_local);
void ED_view3d_clipping_set(struct RegionView3D *rv3d);
void ED_view3d_clipping_enable(void);
void ED_view3d_clipping_disable(void);
-float ED_view3d_pixel_size(struct RegionView3D *rv3d, const float co[3]);
+float ED_view3d_pixel_size(const struct RegionView3D *rv3d, const float co[3]);
-float ED_view3d_radius_to_persp_dist(const float angle, const float radius);
-float ED_view3d_radius_to_ortho_dist(const float lens, const float radius);
+float ED_view3d_radius_to_dist_persp(const float angle, const float radius);
+float ED_view3d_radius_to_dist_ortho(const float lens, const float radius);
+float ED_view3d_radius_to_dist(
+ const struct View3D *v3d, const struct ARegion *ar,
+ const char persp, const bool use_aspect,
+ const float radius);
void drawcircball(int mode, const float cent[3], float rad, float tmat[4][4]);
/* backbuffer select and draw support */
-void view3d_validate_backbuf(struct ViewContext *vc);
-struct ImBuf *view3d_read_backbuf(struct ViewContext *vc, short xmin, short ymin, short xmax, short ymax);
-unsigned int view3d_sample_backbuf_rect(struct ViewContext *vc, const int mval[2], int size,
- unsigned int min, unsigned int max, float *dist, short strict,
- void *handle, bool (*indextest)(void *handle, unsigned int index));
-unsigned int view3d_sample_backbuf(struct ViewContext *vc, int x, int y);
-
-/* draws and does a 4x4 sample */
-bool ED_view3d_autodist(struct Scene *scene, struct ARegion *ar, struct View3D *v3d,
- const int mval[2], float mouse_worldloc[3],
- const bool alphaoverride, const float fallback_depth_pt[3]);
+void ED_view3d_backbuf_validate(struct ViewContext *vc);
+struct ImBuf *ED_view3d_backbuf_read(struct ViewContext *vc, int xmin, int ymin, int xmax, int ymax);
+unsigned int ED_view3d_backbuf_sample_rect(
+ struct ViewContext *vc, const int mval[2], int size,
+ unsigned int min, unsigned int max, float *r_dist);
+int ED_view3d_backbuf_sample_size_clamp(struct ARegion *ar, const float dist);
+unsigned int ED_view3d_backbuf_sample(struct ViewContext *vc, int x, int y);
+
+bool ED_view3d_autodist(
+ struct Scene *scene, struct ARegion *ar, struct View3D *v3d,
+ const int mval[2], float mouse_worldloc[3],
+ const bool alphaoverride, const float fallback_depth_pt[3]);
/* only draw so ED_view3d_autodist_simple can be called many times after */
void ED_view3d_autodist_init(struct Scene *scene, struct ARegion *ar, struct View3D *v3d, int mode);
@@ -271,7 +288,8 @@ bool ED_view3d_autodist_depth(struct ARegion *ar, const int mval[2], int margin,
bool ED_view3d_autodist_depth_seg(struct ARegion *ar, const int mval_sta[2], const int mval_end[2], int margin, float *depth);
/* select */
-#define MAXPICKBUF 10000
+#define MAXPICKELEMS 2500
+#define MAXPICKBUF (4 * MAXPICKELEMS)
short view3d_opengl_select(struct ViewContext *vc, unsigned int *buffer, unsigned int bufsize, const struct rcti *input, bool do_nearest);
/* view3d_select.c */
@@ -303,14 +321,17 @@ int ED_view3d_scene_layer_set(int lay, const int *values, int *active);
bool ED_view3d_context_activate(struct bContext *C);
void ED_view3d_draw_offscreen_init(struct Scene *scene, struct View3D *v3d);
-void ED_view3d_draw_offscreen(struct Scene *scene, struct View3D *v3d, struct ARegion *ar,
- int winx, int winy, float viewmat[4][4], float winmat[4][4], bool do_bgpic, bool do_sky);
+void ED_view3d_draw_offscreen(
+ struct Scene *scene, struct View3D *v3d, struct ARegion *ar, int winx, int winy, float viewmat[4][4],
+ float winmat[4][4], bool do_bgpic, bool do_sky, bool is_persp,
+ struct GPUOffScreen *ofs,
+ struct GPUFX *fx, struct GPUFXSettings *fx_settings,
+ const char *viewname);
struct ImBuf *ED_view3d_draw_offscreen_imbuf(struct Scene *scene, struct View3D *v3d, struct ARegion *ar, int sizex, int sizey, unsigned int flag,
- bool draw_background, int alpha_mode, char err_out[256]);
+ bool draw_background, int alpha_mode, const char *viewname, char err_out[256]);
struct ImBuf *ED_view3d_draw_offscreen_imbuf_simple(struct Scene *scene, struct Object *camera, int width, int height, unsigned int flag, int drawtype,
- bool use_solid_tex, bool draw_background, int alpha_mode, char err_out[256]);
-void ED_view3d_offscreen_sky_color_get(struct Scene *scene, float sky_color[3]);
+ bool use_solid_tex, bool use_gpencil, bool draw_background, int alpha_mode, const char *viewname, char err_out[256]);
struct Base *ED_view3d_give_base_under_cursor(struct bContext *C, const int mval[2]);
void ED_view3d_quadview_update(struct ScrArea *sa, struct ARegion *ar, bool do_clip);
@@ -318,17 +339,16 @@ void ED_view3d_update_viewmat(struct Scene *scene, struct View3D *v3d, struct AR
bool ED_view3d_quat_from_axis_view(const char view, float quat[4]);
char ED_view3d_quat_to_axis_view(const float quat[4], const float epsilon);
char ED_view3d_lock_view_from_index(int index);
+char ED_view3d_axis_view_opposite(char view);
bool ED_view3d_lock(struct RegionView3D *rv3d);
-uint64_t ED_view3d_datamask(struct Scene *scene, struct View3D *v3d);
-uint64_t ED_view3d_screen_datamask(struct bScreen *screen);
+uint64_t ED_view3d_datamask(const struct Scene *scene, const struct View3D *v3d);
+uint64_t ED_view3d_screen_datamask(const struct bScreen *screen);
-bool ED_view3d_view_lock_check(struct View3D *v3d, struct RegionView3D *rv3d);
-
-bool ED_view3d_offset_lock_check(struct View3D *v3d, struct RegionView3D *rv3d);
+bool ED_view3d_offset_lock_check(const struct View3D *v3d, const struct RegionView3D *rv3d);
/* camera lock functions */
-bool ED_view3d_camera_lock_check(struct View3D *v3d, struct RegionView3D *rv3d);
+bool ED_view3d_camera_lock_check(const struct View3D *v3d, const struct RegionView3D *rv3d);
/* copy the camera to the view before starting a view transformation */
void ED_view3d_camera_lock_init_ex(struct View3D *v3d, struct RegionView3D *rv3d, const bool calc_dist);
void ED_view3d_camera_lock_init(struct View3D *v3d, struct RegionView3D *rv3d);
@@ -368,6 +388,10 @@ void ED_view3d_operator_properties_viewmat_get(struct wmOperator *op, int *winx,
#endif
/* render */
+void ED_view3d_stop_render_preview(struct wmWindowManager *wm, struct ARegion *ar);
void ED_view3d_shade_update(struct Main *bmain, struct Scene *scene, struct View3D *v3d, struct ScrArea *sa);
+#define V3D_IS_ZBUF(v3d) \
+ (((v3d)->flag & V3D_ZBUF_SELECT) && ((v3d)->drawtype > OB_WIRE))
+
#endif /* __ED_VIEW3D_H__ */
diff --git a/source/blender/editors/include/UI_icons.h b/source/blender/editors/include/UI_icons.h
index 1d79cf749f9..e6421b0de41 100644
--- a/source/blender/editors/include/UI_icons.h
+++ b/source/blender/editors/include/UI_icons.h
@@ -54,7 +54,7 @@ DEF_ICON(DOT)
DEF_ICON(COLLAPSEMENU)
DEF_ICON(X)
#ifndef DEF_ICON_BLANK_SKIP
- DEF_ICON(BLANK005)
+ DEF_ICON(BLANK005) /* XXX 'DOWNARROW' icon! */
#endif
DEF_ICON(GO_LEFT)
DEF_ICON(PLUG)
@@ -251,9 +251,7 @@ DEF_ICON(EMPTY_DATA)
DEF_ICON(SETTINGS)
DEF_ICON(RENDER_ANIMATION)
DEF_ICON(RENDER_STILL)
-#ifndef DEF_ICON_BLANK_SKIP
- DEF_ICON(BLANK080F)
-#endif
+DEF_ICON(LIBRARY_DATA_BROKEN)
DEF_ICON(BOIDS)
DEF_ICON(STRANDS)
DEF_ICON(LIBRARY_DATA_INDIRECT)
@@ -426,13 +424,11 @@ DEF_ICON(CURVE_PATH)
DEF_ICON(COLOR_RED)
DEF_ICON(COLOR_GREEN)
DEF_ICON(COLOR_BLUE)
-#ifndef DEF_ICON_BLANK_SKIP
- DEF_ICON(BLANK652)
- DEF_ICON(BLANK653)
- DEF_ICON(BLANK654)
- DEF_ICON(BLANK655)
-#endif
-
+DEF_ICON(TRIA_RIGHT_BAR)
+DEF_ICON(TRIA_DOWN_BAR)
+DEF_ICON(TRIA_LEFT_BAR)
+DEF_ICON(TRIA_UP_BAR)
+
/* EMPTY */
DEF_ICON(FORCE_FORCE)
DEF_ICON(FORCE_WIND)
@@ -463,11 +459,13 @@ DEF_ICON(FORCE_SMOKEFLOW)
DEF_ICON(BLANK685)
/* EMPTY */
- DEF_ICON(BLANK690)
- DEF_ICON(BLANK691)
- DEF_ICON(BLANK692)
- DEF_ICON(BLANK693)
- DEF_ICON(BLANK694)
+ DEF_ICON(BLANK690) /* XXX 'Temperature' icon! */
+ DEF_ICON(BLANK691) /* XXX 'Temperature' icon! */
+ DEF_ICON(BLANK692) /* XXX 'Gear' icon! */
+#endif
+DEF_ICON(NODE_INSERT_ON)
+DEF_ICON(NODE_INSERT_OFF)
+#ifndef DEF_ICON_BLANK_SKIP
DEF_ICON(BLANK695)
DEF_ICON(BLANK696)
DEF_ICON(BLANK697)
@@ -591,9 +589,9 @@ DEF_ICON(MOD_WARP)
DEF_ICON(MOD_SKIN)
DEF_ICON(MOD_TRIANGULATE)
DEF_ICON(MOD_WIREFRAME)
+DEF_ICON(MOD_DATA_TRANSFER)
+DEF_ICON(MOD_NORMALEDIT)
#ifndef DEF_ICON_BLANK_SKIP
- DEF_ICON(BLANK167)
- DEF_ICON(BLANK168)
DEF_ICON(BLANK169)
DEF_ICON(BLANK170)
DEF_ICON(BLANK171)
@@ -691,7 +689,7 @@ DEF_ICON(RNDCURVE)
DEF_ICON(PROP_OFF)
DEF_ICON(PROP_ON)
DEF_ICON(PROP_CON)
-DEF_ICON(SCULPT_DYNTOPO)
+DEF_ICON(SCULPT_DYNTOPO) /* XXX Empty icon! */
DEF_ICON(PARTICLE_POINT)
DEF_ICON(PARTICLE_TIP)
DEF_ICON(PARTICLE_PATH)
@@ -704,14 +702,12 @@ DEF_ICON(MANIPUL)
DEF_ICON(SNAP_OFF)
DEF_ICON(SNAP_ON)
DEF_ICON(SNAP_NORMAL)
-DEF_ICON(SNAP_INCREMENT)
+DEF_ICON(SNAP_GRID)
DEF_ICON(SNAP_VERTEX)
DEF_ICON(SNAP_EDGE)
DEF_ICON(SNAP_FACE)
DEF_ICON(SNAP_VOLUME)
-#ifndef DEF_ICON_BLANK_SKIP
- DEF_ICON(BLANK220)
-#endif
+DEF_ICON(SNAP_INCREMENT)
DEF_ICON(STICKY_UVS_LOC)
DEF_ICON(STICKY_UVS_DISABLE)
DEF_ICON(STICKY_UVS_VERT)
@@ -878,8 +874,8 @@ DEF_ICON(FORWARD)
DEF_ICON(BLANK312)
DEF_ICON(BLANK313)
DEF_ICON(BLANK314)
- DEF_ICON(BLANK315)
#endif
+DEF_ICON(FILE_HIDDEN)
DEF_ICON(FILE_BACKUP)
DEF_ICON(DISK_DRIVE)
diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h
index bc794bf3350..ba3e3a61aee 100644
--- a/source/blender/editors/include/UI_interface.h
+++ b/source/blender/editors/include/UI_interface.h
@@ -35,19 +35,15 @@
#include "BLI_compiler_attrs.h"
#include "BLI_sys_types.h" /* size_t */
#include "RNA_types.h"
-#include "DNA_userdef_types.h"
/* Struct Declarations */
struct ID;
-struct Main;
struct ListBase;
struct ARegion;
-struct ARegionType;
struct ScrArea;
struct wmEvent;
struct wmWindow;
-struct wmWindowManager;
struct wmOperator;
struct AutoComplete;
struct bContext;
@@ -58,18 +54,14 @@ struct PointerRNA;
struct PropertyRNA;
struct ReportList;
struct rcti;
-struct rctf;
struct uiList;
struct uiStyle;
struct uiFontStyle;
struct uiWidgetColors;
-struct ColorBand;
-struct CurveMapping;
struct Image;
struct ImageUser;
struct wmOperatorType;
struct uiWidgetColors;
-struct Tex;
struct MTex;
struct ImBuf;
struct bNodeTree;
@@ -93,25 +85,29 @@ typedef struct uiLayout uiLayout;
/* names */
#define UI_MAX_DRAW_STR 400
#define UI_MAX_NAME_STR 128
+#define UI_MAX_SHORTCUT_STR 64
/* use for clamping popups within the screen */
#define UI_SCREEN_MARGIN 10
/* 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 */
-#define UI_EMBOSST 3 /* Table */
-#define UI_EMBOSSR 4 /* Pie Menu */
+enum {
+ UI_EMBOSS = 0, /* use widget style for drawing */
+ UI_EMBOSS_NONE = 1, /* Nothing, only icon and/or text */
+ UI_EMBOSS_PULLDOWN = 2, /* Pulldown menu style */
+ UI_EMBOSS_RADIAL = 3, /* Pie Menu */
+};
/* uiBlock->direction */
-#define UI_DIRECTION (UI_TOP | UI_DOWN | UI_LEFT | UI_RIGHT)
-#define UI_TOP (1 << 0)
-#define UI_DOWN (1 << 1)
-#define UI_LEFT (1 << 2)
-#define UI_RIGHT (1 << 3)
-#define UI_CENTER (1 << 4)
-#define UI_SHIFT_FLIPPED (1 << 5)
+enum {
+ UI_DIR_UP = (1 << 0),
+ UI_DIR_DOWN = (1 << 1),
+ UI_DIR_LEFT = (1 << 2),
+ UI_DIR_RIGHT = (1 << 3),
+ UI_DIR_CENTER_Y = (1 << 4),
+
+ UI_DIR_ALL = (UI_DIR_UP | UI_DIR_DOWN | UI_DIR_LEFT | UI_DIR_RIGHT),
+};
#if 0
/* uiBlock->autofill (not yet used) */
@@ -121,8 +117,8 @@ typedef struct uiLayout uiLayout;
/* uiBlock->flag (controls) */
#define UI_BLOCK_LOOP (1 << 0)
-#define UI_BLOCK_REDRAW (1 << 1)
-#define UI_BLOCK_SEARCH_MENU (1 << 2)
+#define UI_BLOCK_IS_FLIP (1 << 1)
+#define UI_BLOCK_NO_FLIP (1 << 2)
#define UI_BLOCK_NUMSELECT (1 << 3)
#define UI_BLOCK_NO_WIN_CLIP (1 << 4) /* don't apply window clipping */ /* was UI_BLOCK_ENTER_OK */
#define UI_BLOCK_CLIPBOTTOM (1 << 5)
@@ -131,7 +127,7 @@ typedef struct uiLayout uiLayout;
#define UI_BLOCK_KEEP_OPEN (1 << 8)
#define UI_BLOCK_POPUP (1 << 9)
#define UI_BLOCK_OUT_1 (1 << 10)
-#define UI_BLOCK_NO_FLIP (1 << 11)
+#define UI_BLOCK_SEARCH_MENU (1 << 11)
#define UI_BLOCK_POPUP_MEMORY (1 << 12)
#define UI_BLOCK_CLIP_EVENTS (1 << 13) /* stop handling mouse events */
@@ -156,31 +152,33 @@ typedef struct uiLayout uiLayout;
/* 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). */
- UI_BUT_DRAG_MULTI = (1 << 25), /* edit this button as well as the active button (not just dragging) */
- UI_BUT_SCA_LINK_GREY = (1 << 26), /* used to flag if sca links shoud be grey out */
- UI_BUT_HAS_SEP_CHAR = (1 << 27), /* but->str contains UI_SEP_CHAR, used for key shortcuts */
- UI_BUT_TIP_FORCE = (1 << 28), /* force show tooltips when holding option/alt if U's USER_TOOLTIPS is off */
+ UI_BUT_ICON_SUBMENU = (1 << 6),
+ UI_BUT_ICON_PREVIEW = (1 << 7),
+
+ UI_BUT_NODE_LINK = (1 << 8),
+ UI_BUT_NODE_ACTIVE = (1 << 9),
+ UI_BUT_DRAG_LOCK = (1 << 10),
+ UI_BUT_DISABLED = (1 << 11),
+ UI_BUT_COLOR_LOCK = (1 << 12),
+ UI_BUT_ANIMATED = (1 << 13),
+ UI_BUT_ANIMATED_KEY = (1 << 14),
+ UI_BUT_DRIVEN = (1 << 15),
+ UI_BUT_REDALERT = (1 << 16),
+ UI_BUT_INACTIVE = (1 << 17),
+ UI_BUT_LAST_ACTIVE = (1 << 18),
+ UI_BUT_UNDO = (1 << 19),
+ UI_BUT_IMMEDIATE = (1 << 20),
+ UI_BUT_NO_UTF8 = (1 << 21),
+
+ UI_BUT_VEC_SIZE_LOCK = (1 << 22), /* used to flag if color hsv-circle should keep luminance */
+ UI_BUT_COLOR_CUBIC = (1 << 23), /* cubic saturation for the color wheel */
+ UI_BUT_LIST_ITEM = (1 << 24), /* This but is "inside" a list item (currently used to change theme colors). */
+ UI_BUT_DRAG_MULTI = (1 << 25), /* edit this button as well as the active button (not just dragging) */
+ UI_BUT_SCA_LINK_GREY = (1 << 26), /* used to flag if sca links shoud be gray out */
+ UI_BUT_HAS_SEP_CHAR = (1 << 27), /* but->str contains UI_SEP_CHAR, used for key shortcuts */
+ UI_BUT_TIP_FORCE = (1 << 28), /* force show tooltips when holding option/alt if U's USER_TOOLTIPS is off */
+ UI_BUT_TEXTEDIT_UPDATE = (1 << 29), /* when widget is in textedit mode, update value on each char stroke */
+ UI_BUT_SEARCH_UNLINK = (1 << 30), /* show unlink for search button */
};
#define UI_PANEL_WIDTH 340
@@ -234,56 +232,56 @@ typedef enum {
/* assigned to but->type, OR'd with the flags above when passing args */
typedef enum {
- BUT = (1 << 9),
- ROW = (2 << 9),
- TOG = (3 << 9),
- NUM = (5 << 9),
- TEX = (6 << 9),
- TOGN = (9 << 9),
- LABEL = (10 << 9),
- MENU = (11 << 9), /* Dropdown list, actually! */
- ICONTOG = (13 << 9),
- NUMSLI = (14 << 9),
- COLOR = (15 << 9),
- SCROLL = (18 << 9),
- BLOCK = (19 << 9),
- BUTM = (20 << 9),
- SEPR = (21 << 9),
- LINK = (22 << 9),
- INLINK = (23 << 9),
- KEYEVT = (24 << 9),
- HSVCUBE = (26 << 9),
- PULLDOWN = (27 << 9), /* Menu, actually! */
- ROUNDBOX = (28 << 9),
- BUT_COLORBAND = (30 << 9),
- BUT_NORMAL = (31 << 9),
- BUT_CURVE = (32 << 9),
- ICONTOGN = (34 << 9),
- LISTBOX = (35 << 9),
- LISTROW = (36 << 9),
- TOGBUT = (37 << 9),
- OPTION = (38 << 9),
- OPTIONN = (39 << 9),
- TRACKPREVIEW = (40 << 9),
- /* buttons with value >= SEARCH_MENU don't get undo pushes */
- SEARCH_MENU = (41 << 9),
- BUT_EXTRA = (42 << 9),
- HSVCIRCLE = (43 << 9),
- HOTKEYEVT = (46 << 9),
- BUT_IMAGE = (47 << 9),
- HISTOGRAM = (48 << 9),
- WAVEFORM = (49 << 9),
- VECTORSCOPE = (50 << 9),
- PROGRESSBAR = (51 << 9),
- SEARCH_MENU_UNLINK = (52 << 9),
- NODESOCKET = (53 << 9),
- SEPRLINE = (54 << 9),
- GRIP = (55 << 9),
+ UI_BTYPE_BUT = (1 << 9),
+ UI_BTYPE_ROW = (2 << 9),
+ UI_BTYPE_TEXT = (3 << 9),
+ UI_BTYPE_MENU = (4 << 9), /* dropdown list */
+ UI_BTYPE_BUT_MENU = (5 << 9),
+ UI_BTYPE_NUM = (6 << 9), /* number button */
+ UI_BTYPE_NUM_SLIDER = (7 << 9), /* number slider */
+ UI_BTYPE_TOGGLE = (8 << 9),
+ UI_BTYPE_TOGGLE_N = (9 << 9),
+ UI_BTYPE_ICON_TOGGLE = (10 << 9),
+ UI_BTYPE_ICON_TOGGLE_N = (11 << 9),
+ UI_BTYPE_BUT_TOGGLE = (12 << 9), /* same as regular toggle, but no on/off state displayed */
+ UI_BTYPE_CHECKBOX = (13 << 9), /* similar to toggle, display a 'tick' */
+ UI_BTYPE_CHECKBOX_N = (14 << 9),
+ UI_BTYPE_COLOR = (15 << 9),
+ UI_BTYPE_SCROLL = (18 << 9),
+ UI_BTYPE_BLOCK = (19 << 9),
+ UI_BTYPE_LABEL = (20 << 9),
+ UI_BTYPE_LINK = (22 << 9),
+ UI_BTYPE_INLINK = (23 << 9),
+ UI_BTYPE_KEY_EVENT = (24 << 9),
+ UI_BTYPE_HSVCUBE = (26 << 9),
+ UI_BTYPE_PULLDOWN = (27 << 9), /* menu (often used in headers), **_MENU /w different draw-type */
+ UI_BTYPE_ROUNDBOX = (28 << 9),
+ UI_BTYPE_COLORBAND = (30 << 9),
+ UI_BTYPE_UNITVEC = (31 << 9), /* sphere widget (used to input a unit-vector, aka normal) */
+ UI_BTYPE_CURVE = (32 << 9),
+ UI_BTYPE_LISTBOX = (36 << 9),
+ UI_BTYPE_LISTROW = (37 << 9),
+ UI_BTYPE_HSVCIRCLE = (38 << 9),
+ UI_BTYPE_TRACK_PREVIEW = (40 << 9),
+
+ /* buttons with value >= UI_BTYPE_SEARCH_MENU don't get undo pushes */
+ UI_BTYPE_SEARCH_MENU = (41 << 9),
+ UI_BTYPE_EXTRA = (42 << 9),
+ UI_BTYPE_HOTKEY_EVENT = (46 << 9),
+ UI_BTYPE_IMAGE = (47 << 9), /* non-interactive image, used for splash screen */
+ UI_BTYPE_HISTOGRAM = (48 << 9),
+ UI_BTYPE_WAVEFORM = (49 << 9),
+ UI_BTYPE_VECTORSCOPE = (50 << 9),
+ UI_BTYPE_PROGRESS_BAR = (51 << 9),
+ UI_BTYPE_NODE_SOCKET = (53 << 9),
+ UI_BTYPE_SEPR = (54 << 9),
+ UI_BTYPE_SEPR_LINE = (55 << 9),
+ UI_BTYPE_GRIP = (56 << 9), /* resize handle (resize uilist) */
} eButType;
#define BUTTYPE (63 << 9)
-/* gradient types, for color picker HSVCUBE etc */
+/* gradient types, for color picker UI_BTYPE_HSVCUBE etc */
#define UI_GRAD_SV 0
#define UI_GRAD_HV 1
#define UI_GRAD_HS 2
@@ -301,35 +299,45 @@ typedef enum {
* Functions to draw various shapes, taking theme settings into account.
* Used for code that draws its own UI style elements. */
-void uiRoundBox(float minx, float miny, float maxx, float maxy, float rad);
-void uiSetRoundBox(int type);
-int uiGetRoundBox(void);
-void uiRoundRect(float minx, float miny, float maxx, float maxy, float rad);
-void uiDrawBoxShadow(unsigned char alpha, float minx, float miny, float maxx, float maxy);
-void uiDrawBox(int mode, float minx, float miny, float maxx, float maxy, float rad);
-void uiDrawBoxShade(int mode, float minx, float miny, float maxx, float maxy, float rad, float shadetop, float shadedown);
-void uiDrawBoxVerticalShade(int mode, float minx, float miny, float maxx, float maxy, float rad, float shadeLeft, float shadeRight);
+void UI_draw_roundbox(float minx, float miny, float maxx, float maxy, float rad);
+void UI_draw_roundbox_corner_set(int type);
+int UI_draw_roundbox_corner_get(void);
+void UI_draw_roundbox_unfilled(float minx, float miny, float maxx, float maxy, float rad);
+void UI_draw_box_shadow(unsigned char alpha, float minx, float miny, float maxx, float maxy);
+void UI_draw_roundbox_gl_mode(int mode, float minx, float miny, float maxx, float maxy, float rad);
+void UI_draw_roundbox_shade_x(int mode, float minx, float miny, float maxx, float maxy, float rad, float shadetop, float shadedown);
+void UI_draw_roundbox_shade_y(int mode, float minx, float miny, float maxx, float maxy, float rad, float shadeLeft, float shadeRight);
+void UI_draw_text_underline(int pos_x, int pos_y, int len, int height);
+
+void UI_draw_safe_areas(
+ float x1, float x2, float y1, float y2,
+ const float title_aspect[2], const float action_aspect[2]);
/* state for scrolldrawing */
#define UI_SCROLL_PRESSED (1 << 0)
#define UI_SCROLL_ARROWS (1 << 1)
#define UI_SCROLL_NO_OUTLINE (1 << 2)
-void uiWidgetScrollDraw(struct uiWidgetColors *wcol, const struct rcti *rect, const struct rcti *slider, int state);
+void UI_draw_widget_scroll(struct uiWidgetColors *wcol, const struct rcti *rect, const struct rcti *slider, int state);
+
+/* Shortening string helper. */
+float UI_text_clip_middle_ex(
+ struct uiFontStyle *fstyle, char *str, float okwidth, const float minwidth,
+ const size_t max_len, const char rpart_sep);
/* Callbacks
*
- * uiBlockSetHandleFunc/ButmFunc are for handling events through a callback.
+ * UI_block_func_handle_set/ButmFunc are for handling events through a callback.
* HandleFunc gets the retval passed on, and ButmFunc gets a2. The latter is
* mostly for compatibility with older code.
*
- * uiButSetCompleteFunc is for tab completion.
+ * UI_but_func_complete_set is for tab completion.
*
* uiButSearchFunc is for name buttons, showing a popup with matches
*
- * uiBlockSetFunc and uiButSetFunc are callbacks run when a button is used,
+ * UI_block_func_set and UI_but_func_set are callbacks run when a button is used,
* in case events, operators or RNA are not sufficient to handle the button.
*
- * uiButSetNFunc will free the argument with MEM_freeN. */
+ * UI_but_funcN_set will free the argument with MEM_freeN. */
typedef struct uiSearchItems uiSearchItems;
@@ -338,6 +346,9 @@ typedef void (*uiButHandleRenameFunc)(struct bContext *C, void *arg, char *origs
typedef void (*uiButHandleNFunc)(struct bContext *C, void *argN, void *arg2);
typedef int (*uiButCompleteFunc)(struct bContext *C, char *str, void *arg);
typedef void (*uiButSearchFunc)(const struct bContext *C, void *arg, const char *str, uiSearchItems *items);
+/* Must return allocated string. */
+typedef char *(*uiButToolTipFunc)(struct bContext *C, void *argN, const char *tip);
+
typedef void (*uiBlockHandleFunc)(struct bContext *C, void *arg, int event);
/* Menu Callbacks */
@@ -348,30 +359,35 @@ typedef void (*uiMenuHandleFunc)(struct bContext *C, void *arg, int event);
/* Popup Menus
*
* Functions used to create popup menus. For more extended menus the
- * uiPupMenuBegin/End functions can be used to define own items with
+ * UI_popup_menu_begin/End functions can be used to define own items with
* the uiItem functions in between. If it is a simple confirmation menu
* or similar, popups can be created with a single function call. */
typedef struct uiPopupMenu uiPopupMenu;
-struct uiPopupMenu *uiPupMenuBegin(struct bContext *C, const char *title, int icon) ATTR_NONNULL();
-void uiPupMenuEnd(struct bContext *C, struct uiPopupMenu *head);
-struct uiLayout *uiPupMenuLayout(uiPopupMenu *head);
+struct uiPopupMenu *UI_popup_menu_begin(struct bContext *C, const char *title, int icon) ATTR_NONNULL();
+void UI_popup_menu_end(struct bContext *C, struct uiPopupMenu *head);
+struct uiLayout *UI_popup_menu_layout(uiPopupMenu *head);
-void uiPupMenuReports(struct bContext *C, struct ReportList *reports) ATTR_NONNULL();
-bool uiPupMenuInvoke(struct bContext *C, const char *idname, struct ReportList *reports) ATTR_NONNULL(1, 2);
+void UI_popup_menu_reports(struct bContext *C, struct ReportList *reports) ATTR_NONNULL();
+int UI_popup_menu_invoke(struct bContext *C, const char *idname, struct ReportList *reports) ATTR_NONNULL(1, 2);
/* Pie menus */
typedef struct uiPieMenu uiPieMenu;
-void uiPieMenuInvoke(struct bContext *C, const char *idname, const struct wmEvent *event);
-void uiPieOperatorEnumInvoke(struct bContext *C, const char *title, const char *opname,
- const char *propname, const struct wmEvent *event);
-void uiPieEnumInvoke(struct bContext *C, const char *title, const char *path, const struct wmEvent *event);
-
-struct uiPieMenu *uiPieMenuBegin(struct bContext *C, const char *title, int icon, const struct wmEvent *event) ATTR_NONNULL();
-void uiPieMenuEnd(struct bContext *C, uiPieMenu *pie);
-struct uiLayout *uiPieMenuLayout(struct uiPieMenu *pie);
+int UI_pie_menu_invoke(struct bContext *C, const char *idname, const struct wmEvent *event);
+int UI_pie_menu_invoke_from_operator_enum(
+ struct bContext *C, const char *title, const char *opname,
+ const char *propname, const struct wmEvent *event);
+int UI_pie_menu_invoke_from_rna_enum(
+ struct bContext *C, const char *title,
+ const char *path, const struct wmEvent *event);
+
+struct uiPieMenu *UI_pie_menu_begin(
+ struct bContext *C, const char *title, int icon,
+ const struct wmEvent *event) ATTR_NONNULL();
+void UI_pie_menu_end(struct bContext *C, uiPieMenu *pie);
+struct uiLayout *UI_pie_menu_layout(struct uiPieMenu *pie);
/* Popup Blocks
*
* Functions used to create popup blocks. These are like popup menus
@@ -380,12 +396,12 @@ struct uiLayout *uiPieMenuLayout(struct uiPieMenu *pie);
typedef uiBlock * (*uiBlockCreateFunc)(struct bContext *C, struct ARegion *ar, void *arg1);
typedef void (*uiBlockCancelFunc)(struct bContext *C, void *arg1);
-void uiPupBlock(struct bContext *C, uiBlockCreateFunc func, void *arg);
-void uiPupBlockO(struct bContext *C, uiBlockCreateFunc func, void *arg, const char *opname, int opcontext);
-void uiPupBlockEx(struct bContext *C, uiBlockCreateFunc func, uiBlockHandleFunc popup_func, uiBlockCancelFunc cancel_func, void *arg);
+void UI_popup_block_invoke(struct bContext *C, uiBlockCreateFunc func, void *arg);
+void UI_popup_block_invoke_ex(struct bContext *C, uiBlockCreateFunc func, void *arg, const char *opname, int opcontext);
+void UI_popup_block_ex(struct bContext *C, uiBlockCreateFunc func, uiBlockHandleFunc popup_func, uiBlockCancelFunc cancel_func, void *arg);
/* void uiPupBlockOperator(struct bContext *C, uiBlockCreateFunc func, struct wmOperator *op, int opcontext); */ /* UNUSED */
-void uiPupBlockClose(struct bContext *C, uiBlock *block);
+void UI_popup_block_close(struct bContext *C, struct wmWindow *win, uiBlock *block);
/* Blocks
*
@@ -398,29 +414,29 @@ void uiPupBlockClose(struct bContext *C, uiBlock *block);
*
* */
-uiBlock *uiBeginBlock(const struct bContext *C, struct ARegion *region, const char *name, short dt);
-void uiEndBlock_ex(const struct bContext *C, uiBlock *block, const int xy[2]);
-void uiEndBlock(const struct bContext *C, uiBlock *block);
-void uiDrawBlock(const struct bContext *C, struct uiBlock *block);
-void uiBlockUpdateFromOld(const struct bContext *C, struct uiBlock *block);
+uiBlock *UI_block_begin(const struct bContext *C, struct ARegion *region, const char *name, short dt);
+void UI_block_end_ex(const struct bContext *C, uiBlock *block, const int xy[2]);
+void UI_block_end(const struct bContext *C, uiBlock *block);
+void UI_block_draw(const struct bContext *C, struct uiBlock *block);
+void UI_block_update_from_old(const struct bContext *C, struct uiBlock *block);
-uiBlock *uiGetBlock(const char *name, struct ARegion *ar);
+uiBlock *UI_block_find_in_region(const char *name, struct ARegion *ar);
-void uiBlockSetEmboss(uiBlock *block, char dt);
+void UI_block_emboss_set(uiBlock *block, char dt);
-void uiFreeBlock(const struct bContext *C, uiBlock *block);
-void uiFreeBlocks(const struct bContext *C, struct ListBase *lb);
-void uiFreeInactiveBlocks(const struct bContext *C, struct ListBase *lb);
-void uiFreeActiveButtons(const struct bContext *C, struct bScreen *screen);
+void UI_block_free(const struct bContext *C, uiBlock *block);
+void UI_blocklist_free(const struct bContext *C, struct ListBase *lb);
+void UI_blocklist_free_inactive(const struct bContext *C, struct ListBase *lb);
+void UI_screen_free_active_but(const struct bContext *C, struct bScreen *screen);
-void uiBlockSetRegion(uiBlock *block, struct ARegion *region);
+void UI_block_region_set(uiBlock *block, struct ARegion *region);
-void uiBlockSetButLock(uiBlock *block, bool val, const char *lockstr);
-void uiBlockClearButLock(uiBlock *block);
+void UI_block_lock_set(uiBlock *block, bool val, const char *lockstr);
+void UI_block_lock_clear(uiBlock *block);
/* automatic aligning, horiz or verical */
-void uiBlockBeginAlign(uiBlock *block);
-void uiBlockEndAlign(uiBlock *block);
+void UI_block_align_begin(uiBlock *block);
+void UI_block_align_end(uiBlock *block);
/* block bounds/position calculation */
typedef enum {
@@ -433,45 +449,54 @@ typedef enum {
UI_BLOCK_BOUNDS_PIE_CENTER,
} eBlockBoundsCalc;
-void uiBoundsBlock(struct uiBlock *block, int addval);
-void uiTextBoundsBlock(uiBlock *block, int addval);
-void uiPopupBoundsBlock(uiBlock *block, int addval, int mx, int my);
-void uiMenuPopupBoundsBlock(uiBlock *block, int addvall, int mx, int my);
-void uiCenteredBoundsBlock(uiBlock *block, int addval);
-void uiExplicitBoundsBlock(uiBlock *block, int minx, int miny, int maxx, int maxy);
+void UI_block_bounds_set_normal(struct uiBlock *block, int addval);
+void UI_block_bounds_set_text(uiBlock *block, int addval);
+void UI_block_bounds_set_popup(uiBlock *block, int addval, int mx, int my);
+void UI_block_bounds_set_menu(uiBlock *block, int addvall, int mx, int my);
+void UI_block_bounds_set_centered(uiBlock *block, int addval);
+void UI_block_bounds_set_explicit(uiBlock *block, int minx, int miny, int maxx, int maxy);
-int uiBlocksGetYMin(struct ListBase *lb);
+int UI_blocklist_min_y_get(struct ListBase *lb);
-void uiBlockSetDirection(uiBlock *block, char direction);
-void uiBlockFlipOrder(uiBlock *block);
-void uiBlockSetFlag(uiBlock *block, int flag);
-void uiBlockClearFlag(uiBlock *block, int flag);
+void UI_block_direction_set(uiBlock *block, char direction);
+void UI_block_order_flip(uiBlock *block);
+void UI_block_flag_enable(uiBlock *block, int flag);
+void UI_block_flag_disable(uiBlock *block, int flag);
-int uiButGetRetVal(uiBut *but);
+int UI_but_return_value_get(uiBut *but);
-void uiButSetDragID(uiBut *but, struct ID *id);
-void uiButSetDragRNA(uiBut *but, struct PointerRNA *ptr);
-void uiButSetDragPath(uiBut *but, const char *path);
-void uiButSetDragName(uiBut *but, const char *name);
-void uiButSetDragValue(uiBut *but);
-void uiButSetDragImage(uiBut *but, const char *path, int icon, struct ImBuf *ima, float scale);
+void UI_but_drag_set_id(uiBut *but, struct ID *id);
+void UI_but_drag_set_rna(uiBut *but, struct PointerRNA *ptr);
+void UI_but_drag_set_path(uiBut *but, const char *path, const bool use_free);
+void UI_but_drag_set_name(uiBut *but, const char *name);
+void UI_but_drag_set_value(uiBut *but);
+void UI_but_drag_set_image(
+ uiBut *but, const char *path, int icon, struct ImBuf *ima, float scale, const bool use_free);
bool UI_but_active_drop_name(struct bContext *C);
bool UI_but_active_drop_color(struct bContext *C);
-void uiButSetFlag(uiBut *but, int flag);
-void uiButClearFlag(uiBut *but, int flag);
+void UI_but_flag_enable(uiBut *but, int flag);
+void UI_but_flag_disable(uiBut *but, int flag);
-void uiButSetDrawFlag(uiBut *but, int flag);
-void uiButClearDrawFlag(uiBut *but, int flag);
+void UI_but_drawflag_enable(uiBut *but, int flag);
+void UI_but_drawflag_disable(uiBut *but, int flag);
-void uiButSetMenuFromPulldown(uiBut *but);
+void UI_but_type_set_menu_from_pulldown(uiBut *but);
/* special button case, only draw it when used actively, for outliner etc */
-bool uiButActiveOnly(const struct bContext *C, struct ARegion *ar, uiBlock *block, uiBut *but);
+bool UI_but_active_only(const struct bContext *C, struct ARegion *ar, uiBlock *block, uiBut *but);
-void uiButExecute(const struct bContext *C, uiBut *but);
+void UI_but_execute(const struct bContext *C, uiBut *but);
+bool UI_but_online_manual_id(
+ const uiBut *but,
+ char *r_str, size_t maxlength)
+ ATTR_WARN_UNUSED_RESULT;
+bool UI_but_online_manual_id_from_active(
+ const struct bContext *C,
+ char *r_str, size_t maxlength)
+ ATTR_WARN_UNUSED_RESULT;
/* Buttons
*
@@ -544,10 +569,10 @@ uiBut *uiDefIconTextButO(uiBlock *block, int type, const char *opname, int opcon
uiBut *uiDefIconTextButO_ptr(uiBlock *block, int type, struct wmOperatorType *ot, int opcontext, int icon, const char *str, int x, int y, short width, short height, const char *tip);
/* for passing inputs to ButO buttons */
-struct PointerRNA *uiButGetOperatorPtrRNA(uiBut *but);
+struct PointerRNA *UI_but_operator_ptr_get(uiBut *but);
-void uiButSetUnitType(uiBut *but, const int unit_type);
-int uiButGetUnitType(const uiBut *but);
+void UI_but_unit_type_set(uiBut *but, const int unit_type);
+int UI_but_unit_type_get(const uiBut *but);
enum {
BUT_GET_RNAPROP_IDENTIFIER = 1,
@@ -572,7 +597,7 @@ typedef struct uiStringInfo {
/* Note: Expects pointers to uiStringInfo structs as parameters.
* Will fill them with translated strings, when possible.
* Strings in uiStringInfo must be MEM_freeN'ed by caller. */
-void uiButGetStrInfo(struct bContext *C, uiBut *but, ...) ATTR_SENTINEL(0);
+void UI_but_string_info_get(struct bContext *C, uiBut *but, ...) ATTR_SENTINEL(0);
/* Edit i18n stuff. */
/* Name of the main py op from i18n addon. */
@@ -602,8 +627,8 @@ void uiButGetStrInfo(struct bContext *C, uiBut *but, ...) ATTR_SENTINEL(0);
#define UI_ID_PREVIEWS (1 << 11)
#define UI_ID_FULL (UI_ID_RENAME | UI_ID_BROWSE | UI_ID_ADD_NEW | UI_ID_OPEN | UI_ID_ALONE | UI_ID_DELETE | UI_ID_LOCAL)
-int uiIconFromID(struct ID *id);
-int uiIconFromReportType(int type);
+int UI_icon_from_id(struct ID *id);
+int UI_icon_from_report_type(int type);
uiBut *uiDefPulldownBut(uiBlock *block, uiBlockCreateFunc func, void *arg, const char *str, int x, int y, short width, short height, const char *tip);
uiBut *uiDefMenuBut(uiBlock *block, uiMenuCreateFunc func, void *arg, const char *str, int x, int y, short width, short height, const char *tip);
@@ -632,41 +657,45 @@ int uiDefAutoButsRNA(uiLayout *layout, struct PointerRNA *ptr, bool (*check_prop
* Game engine logic brick links. Non-functional currently in 2.5,
* code to handle and draw these is disabled internally. */
-void uiSetButLink(struct uiBut *but, void **poin, void ***ppoin, short *tot, int from, int to);
+void UI_but_link_set(struct uiBut *but, void **poin, void ***ppoin, short *tot, int from, int to);
-void uiComposeLinks(uiBlock *block);
-uiBut *uiFindInlink(uiBlock *block, void *poin);
+void UI_block_links_compose(uiBlock *block);
+uiBut *UI_block_links_find_inlink(uiBlock *block, void *poin);
/* use inside searchfunc to add items */
-bool uiSearchItemAdd(uiSearchItems *items, const char *name, void *poin, int iconid);
+bool UI_search_item_add(uiSearchItems *items, const char *name, void *poin, int iconid);
/* bfunc gets search item *poin as arg2, or if NULL the old string */
-void uiButSetSearchFunc(uiBut *but, uiButSearchFunc sfunc, void *arg1, uiButHandleFunc bfunc, void *active);
+void UI_but_func_search_set(uiBut *but, uiButSearchFunc sfunc, void *arg1, uiButHandleFunc bfunc, void *active);
/* height in pixels, it's using hardcoded values still */
-int uiSearchBoxHeight(void);
-int uiSearchBoxWidth(void);
+int UI_searchbox_size_y(void);
+int UI_searchbox_size_x(void);
/* check if a string is in an existing search box */
-int uiSearchItemFindIndex(uiSearchItems *items, const char *name);
+int UI_search_items_find_index(uiSearchItems *items, const char *name);
+
+void UI_block_func_handle_set(uiBlock *block, uiBlockHandleFunc func, void *arg);
+void UI_block_func_butmenu_set(uiBlock *block, uiMenuHandleFunc func, void *arg);
+void UI_block_func_set(uiBlock *block, uiButHandleFunc func, void *arg1, void *arg2);
+void UI_block_funcN_set(uiBlock *block, uiButHandleNFunc funcN, void *argN, void *arg2);
-void uiBlockSetHandleFunc(uiBlock *block, uiBlockHandleFunc func, void *arg);
-void uiBlockSetButmFunc(uiBlock *block, uiMenuHandleFunc func, void *arg);
-void uiBlockSetFunc(uiBlock *block, uiButHandleFunc func, void *arg1, void *arg2);
-void uiBlockSetNFunc(uiBlock *block, uiButHandleNFunc funcN, void *argN, void *arg2);
+void UI_but_func_rename_set(uiBut *but, uiButHandleRenameFunc func, void *arg1);
+void UI_but_func_set(uiBut *but, uiButHandleFunc func, void *arg1, void *arg2);
+void UI_but_funcN_set(uiBut *but, uiButHandleNFunc funcN, void *argN, void *arg2);
-void uiButSetRenameFunc(uiBut *but, uiButHandleRenameFunc func, void *arg1);
-void uiButSetFunc(uiBut *but, uiButHandleFunc func, void *arg1, void *arg2);
-void uiButSetNFunc(uiBut *but, uiButHandleNFunc funcN, void *argN, void *arg2);
+void UI_but_func_complete_set(uiBut *but, uiButCompleteFunc func, void *arg);
-void uiButSetCompleteFunc(uiBut *but, uiButCompleteFunc func, void *arg);
+void UI_but_func_drawextra_set(
+ uiBlock *block,
+ void (*func)(const struct bContext *C, void *, void *, void *, struct rcti *rect),
+ void *arg1, void *arg2);
-void uiBlockSetDrawExtraFunc(uiBlock *block,
- void (*func)(const struct bContext *C, void *, void *, void *, struct rcti *rect),
- void *arg1, void *arg2);
+void UI_but_func_tooltip_set(uiBut *but, uiButToolTipFunc func, void *argN);
+void UI_but_tooltip_timer_remove(struct bContext *C, uiBut *but);
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);
+void UI_but_focus_on_enter_event(struct wmWindow *win, uiBut *but);
/* Autocomplete
*
@@ -680,9 +709,9 @@ typedef struct AutoComplete AutoComplete;
#define AUTOCOMPLETE_FULL_MATCH 1
#define AUTOCOMPLETE_PARTIAL_MATCH 2
-AutoComplete *autocomplete_begin(const char *startname, size_t maxlen);
-void autocomplete_do_name(AutoComplete *autocpl, const char *name);
-int autocomplete_end(AutoComplete *autocpl, char *autoname);
+AutoComplete *UI_autocomplete_begin(const char *startname, size_t maxlen);
+void UI_autocomplete_update_name(AutoComplete *autocpl, const char *name);
+int UI_autocomplete_end(AutoComplete *autocpl, char *autoname);
/* Panels
*
@@ -690,15 +719,15 @@ int autocomplete_end(AutoComplete *autocpl, char *autoname);
* could use a good cleanup, though how they will function in 2.5 is
* not clear yet so we postpone that. */
-void uiBeginPanels(const struct bContext *C, struct ARegion *ar);
-void uiEndPanels(const struct bContext *C, struct ARegion *ar, int *x, int *y);
-void uiDrawPanels(const struct bContext *C, struct ARegion *ar);
+void UI_panels_begin(const struct bContext *C, struct ARegion *ar);
+void UI_panels_end(const struct bContext *C, struct ARegion *ar, int *x, int *y);
+void UI_panels_draw(const struct bContext *C, struct ARegion *ar);
-struct Panel *uiPanelFindByType(struct ARegion *ar, struct PanelType *pt);
-struct Panel *uiBeginPanel(struct ScrArea *sa, struct ARegion *ar, uiBlock *block,
- struct PanelType *pt, struct Panel *pa, bool *r_open);
-void uiEndPanel(uiBlock *block, int width, int height);
-void uiScalePanels(struct ARegion *ar, float new_width);
+struct Panel *UI_panel_find_by_type(struct ARegion *ar, struct PanelType *pt);
+struct Panel *UI_panel_begin(struct ScrArea *sa, struct ARegion *ar, uiBlock *block,
+ struct PanelType *pt, struct Panel *pa, bool *r_open);
+void UI_panel_end(uiBlock *block, int width, int height);
+void UI_panels_scale(struct ARegion *ar, float new_width);
bool UI_panel_category_is_visible(struct ARegion *ar);
void UI_panel_category_add(struct ARegion *ar, const char *name);
@@ -717,10 +746,10 @@ void UI_panel_category_draw_all(struct ARegion *ar, const
* handling WM events. Mostly this is done automatic by modules such
* as screen/ if ED_KEYMAP_UI is set, or internally in popup functions. */
-void UI_add_region_handlers(struct ListBase *handlers);
-void UI_add_popup_handlers(struct bContext *C, struct ListBase *handlers, uiPopupBlockHandle *popup, const bool accept_dbl_click);
-void UI_remove_popup_handlers(struct ListBase *handlers, uiPopupBlockHandle *popup);
-void UI_remove_popup_handlers_all(struct bContext *C, struct ListBase *handlers);
+void UI_region_handlers_add(struct ListBase *handlers);
+void UI_popup_handlers_add(struct bContext *C, struct ListBase *handlers, uiPopupBlockHandle *popup, const char flag);
+void UI_popup_handlers_remove(struct ListBase *handlers, uiPopupBlockHandle *popup);
+void UI_popup_handlers_remove_all(struct bContext *C, struct ListBase *handlers);
/* Module
*
@@ -797,9 +826,9 @@ enum {
/* not apart of the corner flags but mixed in some functions */
#define UI_RB_ALPHA (UI_CNR_ALL + 1)
-uiLayout *uiBlockLayout(uiBlock *block, int dir, int type, int x, int y, int size, int em, int padding, struct uiStyle *style);
-void uiBlockSetCurLayout(uiBlock *block, uiLayout *layout);
-void uiBlockLayoutResolve(uiBlock *block, int *x, int *y);
+uiLayout *UI_block_layout(uiBlock *block, int dir, int type, int x, int y, int size, int em, int padding, struct uiStyle *style);
+void UI_block_layout_set_current(uiBlock *block, uiLayout *layout);
+void UI_block_layout_resolve(uiBlock *block, int *x, int *y);
uiBlock *uiLayoutGetBlock(uiLayout *layout);
@@ -810,7 +839,7 @@ const char *uiLayoutIntrospect(uiLayout *layout); // XXX - testing
void uiLayoutOperatorButs(const struct bContext *C, struct uiLayout *layout, struct wmOperator *op,
bool (*check_prop)(struct PointerRNA *, struct PropertyRNA *),
const char label_align, const short flag);
-struct MenuType *uiButGetMenuType(uiBut *but);
+struct MenuType *UI_but_menutype_get(uiBut *but);
void uiLayoutSetOperatorContext(uiLayout *layout, int opcontext);
void uiLayoutSetActive(uiLayout *layout, bool active);
@@ -861,7 +890,7 @@ uiLayout *uiTemplateConstraint(uiLayout *layout, struct PointerRNA *ptr);
void uiTemplatePreview(uiLayout *layout, struct bContext *C, struct ID *id, int show_buttons, struct ID *parent,
struct MTex *slot, const char *preview_id);
void uiTemplateColorRamp(uiLayout *layout, struct PointerRNA *ptr, const char *propname, int expand);
-void uiTemplateIconView(uiLayout *layout, struct PointerRNA *ptr, const char *propname);
+void uiTemplateIconView(uiLayout *layout, struct PointerRNA *ptr, const char *propname, int show_labels, float icon_scale);
void uiTemplateHistogram(uiLayout *layout, struct PointerRNA *ptr, const char *propname);
void uiTemplateWaveform(uiLayout *layout, struct PointerRNA *ptr, const char *propname);
void uiTemplateVectorscope(uiLayout *layout, struct PointerRNA *ptr, const char *propname);
@@ -873,11 +902,15 @@ void uiTemplateLayers(uiLayout *layout, struct PointerRNA *ptr, const char *prop
PointerRNA *used_ptr, const char *used_propname, int active_layer);
void uiTemplateGameStates(uiLayout *layout, struct PointerRNA *ptr, const char *propname,
PointerRNA *used_ptr, const char *used_propname, int active_state);
-void uiTemplateImage(uiLayout *layout, struct bContext *C, struct PointerRNA *ptr, const char *propname, struct PointerRNA *userptr, int compact);
+void uiTemplateImage(uiLayout *layout, struct bContext *C, struct PointerRNA *ptr, const char *propname, struct PointerRNA *userptr, int compact, int multiview);
void uiTemplateImageSettings(uiLayout *layout, struct PointerRNA *imfptr, int color_management);
+void uiTemplateImageStereo3d(uiLayout *layout, struct PointerRNA *stereo3d_format_ptr);
+void uiTemplateImageViews(uiLayout *layout, struct PointerRNA *imaptr);
+void uiTemplateImageFormatViews(uiLayout *layout, PointerRNA *imfptr, PointerRNA *ptr);
void uiTemplateImageLayers(uiLayout *layout, struct bContext *C, struct Image *ima, struct ImageUser *iuser);
+void uiTemplateImageInfo(uiLayout *layout, struct bContext *C, struct Image *ima, struct ImageUser *iuser);
void uiTemplateRunningJobs(uiLayout *layout, struct bContext *C);
-void uiOperatorSearch_But(uiBut *but);
+void UI_but_func_operator_search(uiBut *but);
void uiTemplateOperatorSearch(uiLayout *layout);
void uiTemplateHeader3D(uiLayout *layout, struct bContext *C);
void uiTemplateEditModeSelection(uiLayout *layout, struct bContext *C);
@@ -890,7 +923,8 @@ void uiTemplateNodeSocket(uiLayout *layout, struct bContext *C, float *color);
#define UI_UL_DEFAULT_CLASS_NAME "UI_UL_list"
void uiTemplateList(uiLayout *layout, struct bContext *C, const char *listtype_name, const char *list_id,
struct PointerRNA *dataptr, const char *propname, struct PointerRNA *active_dataptr,
- const char *active_propname, int rows, int maxrows, int layout_type, int columns);
+ const char *active_propname, const char *item_dyntip_propname,
+ int rows, int maxrows, int layout_type, int columns);
void uiTemplateNodeLink(uiLayout *layout, struct bNodeTree *ntree, struct bNode *node, struct bNodeSocket *input);
void uiTemplateNodeView(uiLayout *layout, struct bContext *C, struct bNodeTree *ntree, struct bNode *node, struct bNodeSocket *input);
void uiTemplateTextureUser(uiLayout *layout, struct bContext *C);
@@ -921,6 +955,7 @@ PointerRNA uiItemFullO(uiLayout *layout, const char *idname, const char *name, i
void uiItemR(uiLayout *layout, struct PointerRNA *ptr, const char *propname, int flag, const char *name, int icon);
void uiItemFullR(uiLayout *layout, struct PointerRNA *ptr, struct PropertyRNA *prop, int index, int value, int flag, const char *name, int icon);
+void uiItemEnumR_prop(uiLayout *layout, const char *name, int icon, struct PointerRNA *ptr, PropertyRNA *prop, int value);
void uiItemEnumR(uiLayout *layout, const char *name, int icon, struct PointerRNA *ptr, const char *propname, int value);
void uiItemEnumR_string(uiLayout *layout, struct PointerRNA *ptr, const char *propname, const char *value, const char *name, int icon);
void uiItemsEnumR(uiLayout *layout, struct PointerRNA *ptr, const char *propname);
@@ -935,6 +970,7 @@ void uiItemS(uiLayout *layout); /* separator */
void uiItemMenuF(uiLayout *layout, const char *name, int icon, uiMenuCreateFunc func, void *arg);
void uiItemMenuEnumO(uiLayout *layout, struct bContext *C, const char *opname, const char *propname, const char *name, int icon);
+void uiItemMenuEnumR_prop(uiLayout *layout, struct PointerRNA *ptr, PropertyRNA *prop, const char *name, int icon);
void uiItemMenuEnumR(uiLayout *layout, struct PointerRNA *ptr, const char *propname, const char *name, int icon);
/* UI Operators */
@@ -943,32 +979,42 @@ typedef struct uiDragColorHandle {
bool gamma_corrected;
} uiDragColorHandle;
-void UI_buttons_operatortypes(void);
+void ED_button_operatortypes(void);
void UI_drop_color_copy(struct wmDrag *drag, struct wmDropBox *drop);
int UI_drop_color_poll(struct bContext *C, struct wmDrag *drag, const struct wmEvent *event);
+bool UI_context_copy_to_selected_list(
+ struct bContext *C, struct PointerRNA *ptr, struct PropertyRNA *prop,
+ struct ListBase *r_lb, bool *r_use_path_from_id, char **r_path);
+
/* Helpers for Operators */
-uiBut *uiContextActiveButton(const struct bContext *C);
-void uiContextActiveProperty(const struct bContext *C, struct PointerRNA *ptr, struct PropertyRNA **prop, int *index);
-void uiContextActivePropertyHandle(struct bContext *C);
-struct wmOperator *uiContextActiveOperator(const struct bContext *C);
-void uiContextAnimUpdate(const struct bContext *C);
-void uiFileBrowseContextProperty(const struct bContext *C, struct PointerRNA *ptr, struct PropertyRNA **prop);
-void uiIDContextProperty(struct bContext *C, struct PointerRNA *ptr, struct PropertyRNA **prop);
+uiBut *UI_context_active_but_get(const struct bContext *C);
+void UI_context_active_but_prop_get(const struct bContext *C, struct PointerRNA *ptr, struct PropertyRNA **prop, int *index);
+void UI_context_active_but_prop_handle(struct bContext *C);
+struct wmOperator *UI_context_active_operator_get(const struct bContext *C);
+void UI_context_update_anim_flag(const struct bContext *C);
+void UI_context_active_but_prop_get_filebrowser(const struct bContext *C, struct PointerRNA *r_ptr, struct PropertyRNA **r_prop, bool *r_is_undo);
+void UI_context_active_but_prop_get_templateID(struct bContext *C, struct PointerRNA *ptr, struct PropertyRNA **prop);
/* Styled text draw */
-void uiStyleFontSet(struct uiFontStyle *fs);
-void uiStyleFontDrawExt(struct uiFontStyle *fs, const 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);
+void UI_fontstyle_set(const struct uiFontStyle *fs);
+void UI_fontstyle_draw_ex(
+ const struct uiFontStyle *fs, const struct rcti *rect, const char *str,
+ size_t len, float *r_xofs, float *r_yofs);
+void UI_fontstyle_draw(const struct uiFontStyle *fs, const struct rcti *rect, const char *str);
+void UI_fontstyle_draw_rotated(const struct uiFontStyle *fs, const struct rcti *rect, const char *str);
+void UI_fontstyle_draw_simple(const struct uiFontStyle *fs, float x, float y, const char *str);
+void UI_fontstyle_draw_simple_backdrop(
+ const struct uiFontStyle *fs, float x, float y, const char *str,
+ const unsigned char fg[4], const unsigned char bg[4]);
+
+int UI_fontstyle_string_width(const struct uiFontStyle *fs, const char *str);
+int UI_fontstyle_height_max(const struct uiFontStyle *fs);
-int UI_GetStringWidth(const char *str); // XXX temp
-void UI_DrawString(float x, float y, const char *str); // XXX temp
-void UI_DrawTriIcon(float x, float y, char dir);
+void UI_draw_icon_tri(float x, float y, char dir);
-uiStyle *UI_GetStyle(void); /* use for fonts etc */
-uiStyle *UI_GetStyleDraw(void); /* DPI scaled settings for drawing */
+struct uiStyle *UI_style_get(void); /* use for fonts etc */
+struct uiStyle *UI_style_get_dpi(void); /* DPI scaled settings for drawing */
/* linker workaround ack! */
void UI_template_fix_linking(void);
@@ -988,12 +1034,18 @@ void UI_butstore_free(uiBlock *block, uiButStore *bs);
bool UI_butstore_is_valid(uiButStore *bs);
bool UI_butstore_is_registered(uiBlock *block, uiBut *but);
void UI_butstore_register(uiButStore *bs_handle, uiBut **but_p);
+bool UI_butstore_register_update(uiBlock *block, uiBut *but_dst, const uiBut *but_src);
void UI_butstore_unregister(uiButStore *bs_handle, uiBut **but_p);
/* Float precision helpers */
#define UI_PRECISION_FLOAT_MAX 7
+/* For float buttons the 'step' (or a1), is scaled */
+#define UI_PRECISION_FLOAT_SCALE 0.01f
+
+/* Typical UI text */
+#define UI_FSTYLE_WIDGET (const uiFontStyle *)&(UI_style_get()->widget)
-int uiFloatPrecisionCalc(int prec, double value);
+int UI_calc_float_precision(int prec, double value);
#endif /* __UI_INTERFACE_H__ */
diff --git a/source/blender/editors/include/UI_interface_icons.h b/source/blender/editors/include/UI_interface_icons.h
index 6104505ef58..945ac1b6db9 100644
--- a/source/blender/editors/include/UI_interface_icons.h
+++ b/source/blender/editors/include/UI_interface_icons.h
@@ -33,15 +33,13 @@
#define __UI_INTERFACE_ICONS_H__
struct bContext;
-struct Image;
-struct ImBuf;
-struct World;
-struct Tex;
-struct Lamp;
-struct Material;
+struct ID;
+struct Scene;
struct PreviewImage;
struct PointerRNA;
+enum eIconSizes;
+
typedef struct IconFile {
struct IconFile *next, *prev;
char filename[256]; /* FILE_MAXFILE size */
@@ -54,7 +52,7 @@ typedef struct IconFile {
#define ICON_DEFAULT_HEIGHT_SCALE ((int)(UI_UNIT_Y * 0.8f))
#define ICON_DEFAULT_WIDTH_SCALE ((int)(UI_UNIT_X * 0.8f))
-#define PREVIEW_DEFAULT_HEIGHT 96
+#define PREVIEW_DEFAULT_HEIGHT 128
/*
* Resizable Icons for Blender
@@ -63,10 +61,14 @@ void UI_icons_init(int first_dyn_id);
int UI_icon_get_width(int icon_id);
int UI_icon_get_height(int icon_id);
+void UI_id_icon_render(
+ const struct bContext *C, struct Scene *scene, struct ID *id, const bool big, const bool use_job);
+int UI_preview_render_size(enum eIconSizes size);
+
void UI_icon_draw(float x, float y, int icon_id);
void UI_icon_draw_preview(float x, float y, int icon_id);
void UI_icon_draw_preview_aspect(float x, float y, int icon_id, float aspect);
-void UI_icon_draw_preview_aspect_size(float x, float y, int icon_id, float aspect, int size);
+void UI_icon_draw_preview_aspect_size(float x, float y, int icon_id, float aspect, float alpha, int size);
void UI_icon_draw_aspect(float x, float y, int icon_id, float aspect, float alpha);
void UI_icon_draw_aspect_color(float x, float y, int icon_id, float aspect, const float rgb[3]);
@@ -80,5 +82,6 @@ int UI_iconfile_get_index(const char *filename);
struct PreviewImage *UI_icon_to_preview(int icon_id);
int UI_rnaptr_icon_get(struct bContext *C, struct PointerRNA *ptr, int rnaicon, const bool big);
+int UI_idcode_icon_get(const int idcode);
#endif /* __UI_INTERFACE_ICONS_H__ */
diff --git a/source/blender/editors/include/UI_resources.h b/source/blender/editors/include/UI_resources.h
index 872bd32b75b..2b19b6180e5 100644
--- a/source/blender/editors/include/UI_resources.h
+++ b/source/blender/editors/include/UI_resources.h
@@ -87,6 +87,7 @@ enum {
TH_GRID,
TH_WIRE,
+ TH_WIRE_INNER,
TH_WIRE_EDIT,
TH_SELECT,
TH_ACTIVE,
@@ -110,6 +111,8 @@ enum {
TH_FACE_DOT,
TH_FACEDOT_SIZE,
TH_CFRAME,
+ TH_TIME_KEYFRAME,
+ TH_TIME_GP_KEYFRAME,
TH_NURB_ULINE,
TH_NURB_VLINE,
TH_NURB_SEL_ULINE,
@@ -206,6 +209,10 @@ enum {
TH_HANDLE_VERTEX_SELECT,
TH_HANDLE_VERTEX_SIZE,
+ TH_GP_VERTEX,
+ TH_GP_VERTEX_SELECT,
+ TH_GP_VERTEX_SIZE,
+
TH_DOPESHEET_CHANNELOB,
TH_DOPESHEET_CHANNELSUBOB,
@@ -265,6 +272,8 @@ enum {
TH_NLA_SOUND,
TH_NLA_SOUND_SEL,
+ TH_WIDGET_EMBOSS,
+
TH_AXIS_X, /* X/Y/Z Axis */
TH_AXIS_Y,
TH_AXIS_Z,
@@ -284,13 +293,22 @@ enum {
TH_INFO_DEBUG,
TH_INFO_DEBUG_TEXT,
TH_VIEW_OVERLAY,
+
+ TH_V3D_CLIPPING_BORDER,
+
+ TH_METADATA_BG,
+ TH_METADATA_TEXT
};
/* XXX WARNING: previous is saved in file, so do not change order! */
/* specific defines per space should have higher define values */
struct bTheme;
-struct PointerRNA;
+
+struct bThemeState {
+ struct bTheme *theme;
+ int spacetype, regionid;
+};
// THE CODERS API FOR THEMES:
@@ -345,12 +363,18 @@ void UI_GetColorPtrBlendShade3ubv(const unsigned char cp1[3], const unsigned
// clear the openGL ClearColor using the input colorid
void UI_ThemeClearColor(int colorid);
+// clear the openGL ClearColor using the input colorid using optional transparency
+void UI_ThemeClearColorAlpha(int colorid, float alpha);
+
// internal (blender) usage only, for init and set active
void UI_SetTheme(int spacetype, int regionid);
// get current theme
struct bTheme *UI_GetTheme(void);
+void UI_Theme_Store(struct bThemeState *theme_state);
+void UI_Theme_Restore(struct bThemeState *theme_state);
+
// return shadow width outside menus and popups */
int UI_ThemeMenuShadowWidth(void);
diff --git a/source/blender/editors/include/UI_view2d.h b/source/blender/editors/include/UI_view2d.h
index cb7cf3ee404..2c8f5f6590a 100644
--- a/source/blender/editors/include/UI_view2d.h
+++ b/source/blender/editors/include/UI_view2d.h
@@ -162,7 +162,7 @@ void UI_view2d_zoom_cache_reset(void);
/* view matrix operations */
void UI_view2d_view_ortho(struct View2D *v2d);
-void UI_view2d_view_orthoSpecial(struct ARegion *ar, struct View2D *v2d, short xaxis);
+void UI_view2d_view_orthoSpecial(struct ARegion *ar, struct View2D *v2d, const bool xaxis);
void UI_view2d_view_restore(const struct bContext *C);
/* grid drawing */
@@ -233,6 +233,6 @@ void ED_keymap_view2d(struct wmKeyConfig *keyconf);
void UI_view2d_smooth_view(struct bContext *C, struct ARegion *ar,
const struct rctf *cur, const int smooth_viewtx);
+#define UI_MARKER_MARGIN_Y (42 * UI_DPI_FAC)
#endif /* __UI_VIEW2D_H__ */
-
diff --git a/source/blender/editors/interface/CMakeLists.txt b/source/blender/editors/interface/CMakeLists.txt
index e13517adbb3..3efb4921bbe 100644
--- a/source/blender/editors/interface/CMakeLists.txt
+++ b/source/blender/editors/interface/CMakeLists.txt
@@ -23,6 +23,7 @@ set(INC
../../blenfont
../../blenkernel
../../blenlib
+ ../../blentranslation
../../gpu
../../imbuf
../../makesdna
@@ -30,6 +31,7 @@ set(INC
../../python
../../windowmanager
../../../../intern/guardedalloc
+ ../../../../intern/glew-mx
)
set(INC_SYS
@@ -70,4 +72,12 @@ if(WITH_PYTHON)
add_definitions(-DWITH_PYTHON)
endif()
+if(WIN32)
+ if(WITH_INPUT_IME)
+ add_definitions(-DWITH_INPUT_IME)
+ endif()
+endif()
+
+add_definitions(${GL_DEFINITIONS})
+
blender_add_lib(bf_editor_interface "${SRC}" "${INC}" "${INC_SYS}")
diff --git a/source/blender/editors/interface/SConscript b/source/blender/editors/interface/SConscript
index 1936e17a7bb..ea6f35c54e6 100644
--- a/source/blender/editors/interface/SConscript
+++ b/source/blender/editors/interface/SConscript
@@ -31,11 +31,13 @@ sources = env.Glob('*.c')
incs = [
'#/intern/guardedalloc',
- '#/extern/glew/include',
+ env['BF_GLEW_INC'],
+ '#/intern/glew-mx',
'../include',
'../../blenfont',
'../../blenkernel',
'../../blenlib',
+ '../../blentranslation',
'../../gpu',
'../../imbuf',
'../../makesdna',
@@ -46,6 +48,11 @@ incs = [
]
defs = []
+defs += env['BF_GL_DEFINITIONS']
+
+if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'win64-vc', 'win64-mingw'):
+ if env['WITH_BF_IME']:
+ defs.append('WITH_INPUT_IME')
if env['WITH_BF_INTERNATIONAL']:
defs.append('WITH_INTERNATIONAL')
diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c
index b987f970b9e..78021612195 100644
--- a/source/blender/editors/interface/interface.c
+++ b/source/blender/editors/interface/interface.c
@@ -37,6 +37,7 @@
#include "MEM_guardedalloc.h"
+#include "DNA_object_types.h"
#include "DNA_scene_types.h"
#include "DNA_screen_types.h"
#include "DNA_userdef_types.h"
@@ -58,7 +59,7 @@
#include "BIF_gl.h"
#include "BLF_api.h"
-#include "BLF_translation.h"
+#include "BLT_translation.h"
#include "UI_interface.h"
@@ -76,20 +77,20 @@
#include "interface_intern.h"
-/* avoid unneeded calls to ui_get_but_val */
+/* avoid unneeded calls to ui_but_value_get */
#define UI_BUT_VALUE_UNSET DBL_MAX
-#define UI_GET_BUT_VALUE_INIT(_but, _value) if (_value == DBL_MAX) { (_value) = ui_get_but_val(_but); } (void)0
+#define UI_GET_BUT_VALUE_INIT(_but, _value) if (_value == DBL_MAX) { (_value) = ui_but_value_get(_but); } (void)0
#define B_NOP -1
-/*
- * a full doc with API notes can be found in bf-blender/trunk/blender/doc/guides/interface_API.txt
+/**
+ * a full doc with API notes can be found in 'blender/doc/guides/interface_API.txt'
*
- * uiBlahBlah() external function
- * ui_blah_blah() internal function
+ * `uiBlahBlah()` external function.
+ * `ui_blah_blah()` internal function.
*/
-static void ui_free_but(const bContext *C, uiBut *but);
+static void ui_but_free(const bContext *C, uiBut *but);
bool ui_block_is_menu(const uiBlock *block)
{
@@ -103,17 +104,17 @@ bool ui_block_is_pie_menu(const uiBlock *block)
return ((block->flag & UI_BLOCK_RADIAL) != 0);
}
-static bool ui_is_but_unit_radians_ex(UnitSettings *unit, const int unit_type)
+static bool ui_but_is_unit_radians_ex(UnitSettings *unit, const int unit_type)
{
return (unit->system_rotation == USER_UNIT_ROT_RADIANS && unit_type == PROP_UNIT_ROTATION);
}
-static bool ui_is_but_unit_radians(const uiBut *but)
+static bool ui_but_is_unit_radians(const uiBut *but)
{
UnitSettings *unit = but->block->unit;
- const int unit_type = uiButGetUnitType(but);
+ const int unit_type = UI_but_unit_type_get(but);
- return ui_is_but_unit_radians_ex(unit, unit_type);
+ return ui_but_is_unit_radians_ex(unit, unit_type);
}
/* ************* window matrix ************** */
@@ -209,6 +210,28 @@ void ui_window_to_region(const ARegion *ar, int *x, int *y)
*y -= ar->winrct.ymin;
}
+void ui_region_to_window(const ARegion *ar, int *x, int *y)
+{
+ *x += ar->winrct.xmin;
+ *y += ar->winrct.ymin;
+}
+
+/**
+ * Popups will add a margin to #ARegion.winrct for shadow,
+ * for interactivity (point-inside tests for eg), we want the winrct without the margin added.
+ */
+void ui_region_winrct_get_no_margin(const struct ARegion *ar, struct rcti *r_rect)
+{
+ uiBlock *block = ar->uiblocks.first;
+ if (block && (block->flag & UI_BLOCK_LOOP) && (block->flag & UI_BLOCK_RADIAL) == 0) {
+ BLI_rcti_rctf_copy_floor(r_rect, &block->rect);
+ BLI_rcti_translate(r_rect, ar->winrct.xmin, ar->winrct.ymin);
+ }
+ else {
+ *r_rect = ar->winrct;
+ }
+}
+
/* ******************* block calc ************************* */
void ui_block_translate(uiBlock *block, int x, int y)
@@ -222,16 +245,16 @@ void ui_block_translate(uiBlock *block, int x, int y)
BLI_rctf_translate(&block->rect, x, y);
}
-static void ui_text_bounds_block(uiBlock *block, float offset)
+static void ui_block_bounds_calc_text(uiBlock *block, float offset)
{
- uiStyle *style = UI_GetStyle();
+ uiStyle *style = UI_style_get();
uiBut *bt, *init_col_bt, *col_bt;
int i = 0, j, x1addval = offset;
- uiStyleFontSet(&style->widget);
+ UI_fontstyle_set(&style->widget);
for (init_col_bt = bt = block->buttons.first; bt; bt = bt->next) {
- if (!ELEM(bt->type, SEPR, SEPRLINE)) {
+ if (!ELEM(bt->type, UI_BTYPE_SEPR, UI_BTYPE_SEPR_LINE)) {
j = BLF_width(style->widget.uifont_id, bt->drawstr, sizeof(bt->drawstr));
if (j > i)
@@ -244,7 +267,7 @@ static void ui_text_bounds_block(uiBlock *block, float offset)
col_bt->rect.xmin = x1addval;
col_bt->rect.xmax = x1addval + i + block->bounds;
- ui_check_but(col_bt); /* clips text again */
+ ui_but_update(col_bt); /* clips text again */
}
/* And we prepare next column. */
@@ -259,11 +282,11 @@ static void ui_text_bounds_block(uiBlock *block, float offset)
col_bt->rect.xmin = x1addval;
col_bt->rect.xmax = max_ff(x1addval + i + block->bounds, offset + block->minbounds);
- ui_check_but(col_bt); /* clips text again */
+ ui_but_update(col_bt); /* clips text again */
}
}
-void ui_bounds_block(uiBlock *block)
+void ui_block_bounds_calc(uiBlock *block)
{
uiBut *bt;
int xof;
@@ -292,7 +315,7 @@ void ui_bounds_block(uiBlock *block)
/* hardcoded exception... but that one is annoying with larger safety */
bt = block->buttons.first;
- if (bt && strncmp(bt->str, "ERROR", 5) == 0) xof = 10;
+ if (bt && STREQLEN(bt->str, "ERROR", 5)) xof = 10;
else xof = 40;
block->safety.xmin = block->rect.xmin - xof;
@@ -301,7 +324,7 @@ void ui_bounds_block(uiBlock *block)
block->safety.ymax = block->rect.ymax + xof;
}
-static void ui_centered_bounds_block(wmWindow *window, uiBlock *block)
+static void ui_block_bounds_calc_centered(wmWindow *window, uiBlock *block)
{
int xmax, ymax;
int startx, starty;
@@ -313,7 +336,7 @@ static void ui_centered_bounds_block(wmWindow *window, uiBlock *block)
xmax = WM_window_pixels_x(window);
ymax = WM_window_pixels_y(window);
- ui_bounds_block(block);
+ ui_block_bounds_calc(block);
width = BLI_rctf_size_x(&block->rect);
height = BLI_rctf_size_y(&block->rect);
@@ -324,11 +347,11 @@ static void ui_centered_bounds_block(wmWindow *window, uiBlock *block)
ui_block_translate(block, startx - block->rect.xmin, starty - block->rect.ymin);
/* now recompute bounds and safety */
- ui_bounds_block(block);
+ ui_block_bounds_calc(block);
}
-static void ui_centered_pie_bounds_block(uiBlock *block)
+static void ui_block_bounds_calc_centered_pie(uiBlock *block)
{
const int xy[2] = {
block->pie_data.pie_center_spawned[0],
@@ -338,11 +361,12 @@ static void ui_centered_pie_bounds_block(uiBlock *block)
ui_block_translate(block, xy[0], xy[1]);
/* now recompute bounds and safety */
- ui_bounds_block(block);
+ ui_block_bounds_calc(block);
}
-static void ui_popup_bounds_block(wmWindow *window, uiBlock *block,
- eBlockBoundsCalc bounds_calc, const int xy[2])
+static void ui_block_bounds_calc_popup(
+ wmWindow *window, uiBlock *block,
+ eBlockBoundsCalc bounds_calc, const int xy[2])
{
int startx, starty, endx, endy, width, height, oldwidth, oldheight;
int oldbounds, xmax, ymax;
@@ -351,7 +375,7 @@ static void ui_popup_bounds_block(wmWindow *window, uiBlock *block,
oldbounds = block->bounds;
/* compute mouse position with user defined offset */
- ui_bounds_block(block);
+ ui_block_bounds_calc(block);
xmax = WM_window_pixels_x(window);
ymax = WM_window_pixels_y(window);
@@ -363,13 +387,13 @@ static void ui_popup_bounds_block(wmWindow *window, uiBlock *block,
if (bounds_calc == UI_BLOCK_BOUNDS_POPUP_MENU) {
if (block->flag & UI_BLOCK_LOOP) {
block->bounds = 2.5f * UI_UNIT_X;
- ui_text_bounds_block(block, block->rect.xmin);
+ ui_block_bounds_calc_text(block, block->rect.xmin);
}
}
/* next we recompute bounds */
block->bounds = oldbounds;
- ui_bounds_block(block);
+ ui_block_bounds_calc(block);
/* and we adjust the position to fit within window */
width = BLI_rctf_size_x(&block->rect);
@@ -380,7 +404,7 @@ static void ui_popup_bounds_block(wmWindow *window, uiBlock *block,
oldheight = oldheight > 0 ? oldheight : MAX2(1, height);
/* offset block based on mouse position, user offset is scaled
- * along in case we resized the block in ui_text_bounds_block */
+ * along in case we resized the block in ui_block_bounds_calc_text */
startx = xy[0] + block->rect.xmin + (block->mx * width) / oldwidth;
starty = xy[1] + block->rect.ymin + (block->my * height) / oldheight;
@@ -404,11 +428,11 @@ static void ui_popup_bounds_block(wmWindow *window, uiBlock *block,
ui_block_translate(block, startx - block->rect.xmin, starty - block->rect.ymin);
/* now recompute bounds and safety */
- ui_bounds_block(block);
+ ui_block_bounds_calc(block);
}
/* used for various cases */
-void uiBoundsBlock(uiBlock *block, int addval)
+void UI_block_bounds_set_normal(uiBlock *block, int addval)
{
if (block == NULL)
return;
@@ -418,14 +442,14 @@ void uiBoundsBlock(uiBlock *block, int addval)
}
/* used for pulldowns */
-void uiTextBoundsBlock(uiBlock *block, int addval)
+void UI_block_bounds_set_text(uiBlock *block, int addval)
{
block->bounds = addval;
block->bounds_type = UI_BLOCK_BOUNDS_TEXT;
}
/* used for block popups */
-void uiPopupBoundsBlock(uiBlock *block, int addval, int mx, int my)
+void UI_block_bounds_set_popup(uiBlock *block, int addval, int mx, int my)
{
block->bounds = addval;
block->bounds_type = UI_BLOCK_BOUNDS_POPUP_MOUSE;
@@ -434,7 +458,7 @@ void uiPopupBoundsBlock(uiBlock *block, int addval, int mx, int my)
}
/* used for menu popups */
-void uiMenuPopupBoundsBlock(uiBlock *block, int addval, int mx, int my)
+void UI_block_bounds_set_menu(uiBlock *block, int addval, int mx, int my)
{
block->bounds = addval;
block->bounds_type = UI_BLOCK_BOUNDS_POPUP_MENU;
@@ -443,13 +467,13 @@ void uiMenuPopupBoundsBlock(uiBlock *block, int addval, int mx, int my)
}
/* used for centered popups, i.e. splash */
-void uiCenteredBoundsBlock(uiBlock *block, int addval)
+void UI_block_bounds_set_centered(uiBlock *block, int addval)
{
block->bounds = addval;
block->bounds_type = UI_BLOCK_BOUNDS_POPUP_CENTER;
}
-void uiExplicitBoundsBlock(uiBlock *block, int minx, int miny, int maxx, int maxy)
+void UI_block_bounds_set_explicit(uiBlock *block, int minx, int miny, int maxx, int maxy)
{
block->rect.xmin = minx;
block->rect.ymin = miny;
@@ -458,21 +482,21 @@ void uiExplicitBoundsBlock(uiBlock *block, int minx, int miny, int maxx, int max
block->bounds_type = UI_BLOCK_BOUNDS_NONE;
}
-static int ui_but_float_precision(uiBut *but, double value)
+static int ui_but_calc_float_precision(uiBut *but, double value)
{
int prec = (int)but->a2;
/* first check for various special cases:
* * If button is radians, we want additional precision (see T39861).
* * If prec is not set, we fallback to a simple default */
- if (ui_is_but_unit_radians(but) && prec < 5) {
+ if (ui_but_is_unit_radians(but) && prec < 5) {
prec = 5;
}
else if (prec == -1) {
prec = (but->hardmax < 10.001f) ? 3 : 2;
}
- return uiFloatPrecisionCalc(prec, value);
+ return UI_calc_float_precision(prec, value);
}
/* ************** LINK LINE DRAWING ************* */
@@ -507,14 +531,14 @@ static void ui_draw_links(uiBlock *block)
uiBut *but;
uiLinkLine *line;
- /* Draw the grey out lines. Do this first so they appear at the
+ /* Draw the gray out lines. Do this first so they appear at the
* bottom of inactive or active lines.
* As we go, remember if we see any active or selected lines. */
bool found_selectline = false;
bool found_activeline = false;
for (but = block->buttons.first; but; but = but->next) {
- if (but->type == LINK && but->link) {
+ if (but->type == UI_BTYPE_LINK && but->link) {
for (line = but->link->lines.first; line; line = line->next) {
if (!(line->from->flag & UI_ACTIVE) && !(line->to->flag & UI_ACTIVE)) {
if (line->deactive)
@@ -531,7 +555,7 @@ static void ui_draw_links(uiBlock *block)
/* Draw the inactive lines (lines with neither button being hovered over) */
for (but = block->buttons.first; but; but = but->next) {
- if (but->type == LINK && but->link) {
+ if (but->type == UI_BTYPE_LINK && but->link) {
for (line = but->link->lines.first; line; line = line->next) {
if (!(line->from->flag & UI_ACTIVE) && !(line->to->flag & UI_ACTIVE)) {
if (!line->deactive)
@@ -542,10 +566,10 @@ static void ui_draw_links(uiBlock *block)
}
/* Draw any active lines (lines with either button being hovered over).
- * Do this last so they appear on top of inactive and grey out lines. */
+ * Do this last so they appear on top of inactive and gray out lines. */
if (found_activeline) {
for (but = block->buttons.first; but; but = but->next) {
- if (but->type == LINK && but->link) {
+ if (but->type == UI_BTYPE_LINK && but->link) {
for (line = but->link->lines.first; line; line = line->next) {
if ((line->from->flag & UI_ACTIVE) || (line->to->flag & UI_ACTIVE))
ui_draw_linkline(line, !found_selectline, false);
@@ -603,8 +627,8 @@ static void ui_but_update_linklines(uiBlock *block, uiBut *oldbut, uiBut *newbut
uiLinkLine *line;
uiBut *but;
- /* if active button is LINK */
- if (newbut->type == LINK && newbut->link) {
+ /* if active button is UI_BTYPE_LINK */
+ if (newbut->type == UI_BTYPE_LINK && newbut->link) {
SWAP(uiLink *, oldbut->link, newbut->link);
@@ -618,7 +642,7 @@ static void ui_but_update_linklines(uiBlock *block, uiBut *oldbut, uiBut *newbut
/* check all other button links */
for (but = block->buttons.first; but; but = but->next) {
- if (but != newbut && but->type == LINK && but->link) {
+ if (but != newbut && but->type == UI_BTYPE_LINK && but->link) {
for (line = but->link->lines.first; line; line = line->next) {
if (line->to == newbut)
line->to = oldbut;
@@ -710,6 +734,7 @@ static bool ui_but_update_from_old_block(const bContext *C, uiBlock *block, uiBu
if (oldbut->poin != (char *)oldbut) {
SWAP(char *, oldbut->poin, but->poin);
SWAP(void *, oldbut->func_argN, but->func_argN);
+ SWAP(void *, oldbut->tip_argN, but->tip_argN);
}
oldbut->flag = (oldbut->flag & ~flag_copy) | (but->flag & flag_copy);
@@ -717,11 +742,15 @@ static bool ui_but_update_from_old_block(const bContext *C, uiBlock *block, uiBu
/* copy hardmin for list rows to prevent 'sticking' highlight to mouse position
* when scrolling without moving mouse (see [#28432]) */
- if (ELEM(oldbut->type, ROW, LISTROW))
+ if (ELEM(oldbut->type, UI_BTYPE_ROW, UI_BTYPE_LISTROW))
oldbut->hardmax = but->hardmax;
ui_but_update_linklines(block, oldbut, but);
+ if (!BLI_listbase_is_empty(&block->butstore)) {
+ UI_butstore_register_update(block, oldbut, but);
+ }
+
/* move/copy string from the new button to the old */
/* needed for alt+mouse wheel over enums */
if (but->str != but->strdata) {
@@ -741,8 +770,12 @@ static bool ui_but_update_from_old_block(const bContext *C, uiBlock *block, uiBu
BLI_strncpy(oldbut->strdata, but->strdata, sizeof(oldbut->strdata));
}
+ if (but->dragpoin && (but->dragflag & UI_BUT_DRAGPOIN_FREE)) {
+ SWAP(void *, but->dragpoin, oldbut->dragpoin);
+ }
+
BLI_remlink(&block->buttons, but);
- ui_free_but(C, but);
+ ui_but_free(C, but);
/* note: if layout hasn't been applied yet, it uses old button pointers... */
}
@@ -754,7 +787,7 @@ static bool ui_but_update_from_old_block(const bContext *C, uiBlock *block, uiBu
/* ensures one button can get activated, and in case the buttons
* draw are the same this gives O(1) lookup for each button */
BLI_remlink(&oldblock->buttons, oldbut);
- ui_free_but(C, oldbut);
+ ui_but_free(C, oldbut);
}
return found_active;
@@ -763,7 +796,7 @@ static bool ui_but_update_from_old_block(const bContext *C, uiBlock *block, uiBu
/* needed for temporarily rename buttons, such as in outliner or file-select,
* they should keep calling uiDefButs to keep them alive */
/* returns 0 when button removed */
-bool uiButActiveOnly(const bContext *C, ARegion *ar, uiBlock *block, uiBut *but)
+bool UI_but_active_only(const bContext *C, ARegion *ar, uiBlock *block, uiBut *but)
{
uiBlock *oldblock;
uiBut *oldbut;
@@ -784,11 +817,11 @@ bool uiButActiveOnly(const bContext *C, ARegion *ar, uiBlock *block, uiBut *but)
}
}
if ((activate == true) || (found == false)) {
- ui_button_activate_do((bContext *)C, ar, but);
+ ui_but_activate_event((bContext *)C, ar, but);
}
else if ((found == true) && (isactive == false)) {
BLI_remlink(&block->buttons, but);
- ui_free_but(C, but);
+ ui_but_free(C, but);
return false;
}
@@ -796,18 +829,18 @@ bool uiButActiveOnly(const bContext *C, ARegion *ar, uiBlock *block, uiBut *but)
}
/* simulate button click */
-void uiButExecute(const bContext *C, uiBut *but)
+void UI_but_execute(const bContext *C, uiBut *but)
{
ARegion *ar = CTX_wm_region(C);
void *active_back;
- ui_button_execute_begin((bContext *)C, ar, but, &active_back);
+ ui_but_execute_begin((bContext *)C, ar, but, &active_back);
/* Value is applied in begin. No further action required. */
- ui_button_execute_end((bContext *)C, ar, but, active_back);
+ ui_but_execute_end((bContext *)C, ar, but, active_back);
}
/* use to check if we need to disable undo, but don't make any changes
* returns false if undo needs to be disabled. */
-static bool ui_is_but_rna_undo(const uiBut *but)
+static bool ui_but_is_rna_undo(const uiBut *but)
{
if (but->rnapoin.id.data) {
/* avoid undo push for buttons who's ID are screen or wm level
@@ -850,7 +883,13 @@ static void ui_menu_block_set_keyaccels(uiBlock *block)
* fun first pass on all buttons so first word chars always get first priority */
for (but = block->buttons.first; but; but = but->next) {
- if (!ELEM(but->type, BUT, BUTM, MENU, BLOCK, PULLDOWN) || (but->flag & UI_HIDDEN)) {
+ if (!ELEM(but->type,
+ UI_BTYPE_BUT,
+ UI_BTYPE_BUT_MENU,
+ UI_BTYPE_MENU, UI_BTYPE_BLOCK,
+ UI_BTYPE_PULLDOWN) ||
+ (but->flag & UI_HIDDEN))
+ {
/* pass */
}
else if (but->menu_key == '\0') {
@@ -930,7 +969,7 @@ void ui_but_add_shortcut(uiBut *but, const char *shortcut_str, const bool do_str
MEM_freeN(butstr_orig);
but->str = but->strdata;
but->flag |= UI_BUT_HAS_SEP_CHAR;
- ui_check_but(but);
+ ui_but_update(but);
}
}
@@ -942,13 +981,11 @@ static bool ui_but_event_operator_string(const bContext *C, uiBut *but, char *bu
if (but->optype) {
IDProperty *prop = (but->opptr) ? but->opptr->data : NULL;
- if (WM_key_event_operator_string(C, but->optype->idname, but->opcontext, prop, true,
- buf, buf_len))
- {
+ if (WM_key_event_operator_string(C, but->optype->idname, but->opcontext, prop, true, buf_len, buf)) {
found = true;
}
}
- else if ((mt = uiButGetMenuType(but))) {
+ else if ((mt = UI_but_menutype_get(but))) {
IDProperty *prop_menu;
IDProperty *prop_menu_name;
@@ -959,8 +996,8 @@ static bool ui_but_event_operator_string(const bContext *C, uiBut *but, char *bu
IDP_AssignString(prop_menu_name, mt->idname, sizeof(mt->idname));
- if (WM_key_event_operator_string(C, "WM_OT_call_menu", WM_OP_INVOKE_REGION_WIN, prop_menu, true,
- buf, buf_len))
+ if (WM_key_event_operator_string(C, "WM_OT_call_menu", WM_OP_INVOKE_REGION_WIN, prop_menu,
+ true, buf_len, buf))
{
found = true;
}
@@ -1065,7 +1102,7 @@ static bool ui_but_event_property_operator_string(const bContext *C, uiBut *but,
for (i = 0; (i < num_ops) && (ctx_toggle_opnames[i]); i++) {
//printf("\t%s\n", ctx_toggle_opnames[i]);
if (WM_key_event_operator_string(C, ctx_toggle_opnames[i], WM_OP_INVOKE_REGION_WIN, prop_path, false,
- buf, buf_len))
+ buf_len, buf))
{
found = true;
break;
@@ -1082,13 +1119,16 @@ static bool ui_but_event_property_operator_string(const bContext *C, uiBut *but,
return found;
}
-/* this goes in a seemingly weird pattern:
+/**
+ * This goes in a seemingly weird pattern:
*
+ * <pre>
* 4
* 5 6
* 1 2
* 7 8
* 3
+ * </pre>
*
* but it's actually quite logical. It's designed to be 'upwards compatible'
* for muscle memory so that the menu item locations are fixed and don't move
@@ -1147,7 +1187,7 @@ static void ui_menu_block_set_keymaps(const bContext *C, uiBlock *block)
}
}
-void uiBlockUpdateFromOld(const bContext *C, uiBlock *block)
+void UI_block_update_from_old(const bContext *C, uiBlock *block)
{
uiBut *but_old;
uiBut *but;
@@ -1163,20 +1203,19 @@ void uiBlockUpdateFromOld(const bContext *C, uiBlock *block)
for (but = block->buttons.first; but; but = but->next) {
if (ui_but_update_from_old_block(C, block, &but, &but_old)) {
- ui_check_but(but);
+ ui_but_update(but);
}
}
block->auto_open = block->oldblock->auto_open;
block->auto_open_last = block->oldblock->auto_open_last;
block->tooltipdisabled = block->oldblock->tooltipdisabled;
- copy_v3_v3(ui_block_hsv_get(block),
- ui_block_hsv_get(block->oldblock));
+ BLI_movelisttolist(&block->color_pickers.list, &block->oldblock->color_pickers.list);
block->oldblock = NULL;
}
-void uiEndBlock_ex(const bContext *C, uiBlock *block, const int xy[2])
+void UI_block_end_ex(const bContext *C, uiBlock *block, const int xy[2])
{
wmWindow *window = CTX_wm_window(C);
Scene *scene = CTX_data_scene(C);
@@ -1184,7 +1223,7 @@ void uiEndBlock_ex(const bContext *C, uiBlock *block, const int xy[2])
BLI_assert(block->active);
- uiBlockUpdateFromOld(C, block);
+ UI_block_update_from_old(C, block);
/* inherit flags from 'old' buttons that was drawn here previous, based
* on matching buttons, we need this to make button event handling non
@@ -1214,9 +1253,9 @@ void uiEndBlock_ex(const bContext *C, uiBlock *block, const int xy[2])
/* handle pending stuff */
if (block->layouts.first) {
- uiBlockLayoutResolve(block, NULL, NULL);
+ UI_block_layout_resolve(block, NULL, NULL);
}
- ui_block_do_align(block);
+ ui_block_align_calc(block);
if ((block->flag & UI_BLOCK_LOOP) && (block->flag & UI_BLOCK_NUMSELECT)) {
ui_menu_block_set_keyaccels(block); /* could use a different flag to check */
}
@@ -1230,40 +1269,40 @@ void uiEndBlock_ex(const bContext *C, uiBlock *block, const int xy[2])
case UI_BLOCK_BOUNDS_NONE:
break;
case UI_BLOCK_BOUNDS:
- ui_bounds_block(block);
+ ui_block_bounds_calc(block);
break;
case UI_BLOCK_BOUNDS_TEXT:
- ui_text_bounds_block(block, 0.0f);
+ ui_block_bounds_calc_text(block, 0.0f);
break;
case UI_BLOCK_BOUNDS_POPUP_CENTER:
- ui_centered_bounds_block(window, block);
+ ui_block_bounds_calc_centered(window, block);
break;
case UI_BLOCK_BOUNDS_PIE_CENTER:
- ui_centered_pie_bounds_block(block);
+ ui_block_bounds_calc_centered_pie(block);
break;
/* fallback */
case UI_BLOCK_BOUNDS_POPUP_MOUSE:
case UI_BLOCK_BOUNDS_POPUP_MENU:
- ui_popup_bounds_block(window, block, block->bounds_type, xy);
+ ui_block_bounds_calc_popup(window, block, block->bounds_type, xy);
break;
}
if (block->rect.xmin == 0.0f && block->rect.xmax == 0.0f) {
- uiBoundsBlock(block, 0);
+ UI_block_bounds_set_normal(block, 0);
}
if (block->flag & UI_BUT_ALIGN) {
- uiBlockEndAlign(block);
+ UI_block_align_end(block);
}
block->endblock = 1;
}
-void uiEndBlock(const bContext *C, uiBlock *block)
+void UI_block_end(const bContext *C, uiBlock *block)
{
wmWindow *window = CTX_wm_window(C);
- uiEndBlock_ex(C, block, &window->eventstate->x);
+ UI_block_end_ex(C, block, &window->eventstate->x);
}
/* ************** BLOCK DRAWING FUNCTION ************* */
@@ -1291,38 +1330,26 @@ static void ui_but_to_pixelrect(rcti *rect, const ARegion *ar, uiBlock *block, u
rctf rectf;
ui_block_to_window_rctf(ar, block, &rectf, (but) ? &but->rect : &block->rect);
-
- rectf.xmin -= ar->winrct.xmin;
- rectf.ymin -= ar->winrct.ymin;
- rectf.xmax -= ar->winrct.xmin;
- rectf.ymax -= ar->winrct.ymin;
-
- rect->xmin = floorf(rectf.xmin);
- rect->ymin = floorf(rectf.ymin);
- rect->xmax = floorf(rectf.xmax);
- rect->ymax = floorf(rectf.ymax);
+ BLI_rcti_rctf_copy_floor(rect, &rectf);
+ BLI_rcti_translate(rect, -ar->winrct.xmin, -ar->winrct.ymin);
}
/* uses local copy of style, to scale things down, and allow widgets to change stuff */
-void uiDrawBlock(const bContext *C, uiBlock *block)
+void UI_block_draw(const bContext *C, uiBlock *block)
{
- uiStyle style = *UI_GetStyleDraw(); /* XXX pass on as arg */
+ uiStyle style = *UI_style_get_dpi(); /* XXX pass on as arg */
ARegion *ar;
uiBut *but;
rcti rect;
int multisample_enabled;
- /* early exit if cancelled */
- if ((block->flag & UI_BLOCK_RADIAL) && (block->pie_data.flags & UI_PIE_FINISHED))
- return;
-
/* get menu region or area region */
ar = CTX_wm_menu(C);
if (!ar)
ar = CTX_wm_region(C);
if (!block->endblock)
- uiEndBlock(C, block);
+ UI_block_end(C, block);
/* disable AA, makes widgets too blurry */
multisample_enabled = glIsEnabled(GL_MULTISAMPLE_ARB);
@@ -1389,12 +1416,12 @@ void uiDrawBlock(const bContext *C, uiBlock *block)
*
* \return (0 == UNSELECT), (1 == SELECT), (-1 == DO-NOTHING)
*/
-int ui_is_but_push_ex(uiBut *but, double *value)
+int ui_but_is_pushed_ex(uiBut *but, double *value)
{
int is_push = 0;
if (but->bit) {
- const bool state = ELEM(but->type, TOGN, ICONTOGN, OPTIONN) ? false : true;
+ const bool state = ELEM(but->type, UI_BTYPE_TOGGLE_N, UI_BTYPE_ICON_TOGGLE_N, UI_BTYPE_CHECKBOX_N) ? false : true;
int lvalue;
UI_GET_BUT_VALUE_INIT(but, *value);
lvalue = (int)*value;
@@ -1407,27 +1434,27 @@ int ui_is_but_push_ex(uiBut *but, double *value)
}
else {
switch (but->type) {
- case BUT:
- case HOTKEYEVT:
- case KEYEVT:
- case COLOR:
+ case UI_BTYPE_BUT:
+ case UI_BTYPE_HOTKEY_EVENT:
+ case UI_BTYPE_KEY_EVENT:
+ case UI_BTYPE_COLOR:
is_push = -1;
break;
- case TOGBUT:
- case TOG:
- case ICONTOG:
- case OPTION:
+ case UI_BTYPE_BUT_TOGGLE:
+ case UI_BTYPE_TOGGLE:
+ case UI_BTYPE_ICON_TOGGLE:
+ case UI_BTYPE_CHECKBOX:
UI_GET_BUT_VALUE_INIT(but, *value);
if (*value != (double)but->hardmin) is_push = true;
break;
- case ICONTOGN:
- case TOGN:
- case OPTIONN:
+ case UI_BTYPE_ICON_TOGGLE_N:
+ case UI_BTYPE_TOGGLE_N:
+ case UI_BTYPE_CHECKBOX_N:
UI_GET_BUT_VALUE_INIT(but, *value);
if (*value == 0.0) is_push = true;
break;
- case ROW:
- case LISTROW:
+ case UI_BTYPE_ROW:
+ case UI_BTYPE_LISTROW:
UI_GET_BUT_VALUE_INIT(but, *value);
/* support for rna enum buts */
if (but->rnaprop && (RNA_property_flag(but->rnaprop) & PROP_ENUM_FLAG)) {
@@ -1445,15 +1472,15 @@ int ui_is_but_push_ex(uiBut *but, double *value)
return is_push;
}
-int ui_is_but_push(uiBut *but)
+int ui_but_is_pushed(uiBut *but)
{
double value = UI_BUT_VALUE_UNSET;
- return ui_is_but_push_ex(but, &value);
+ return ui_but_is_pushed_ex(but, &value);
}
-static void ui_check_but_select(uiBut *but, double *value)
+static void ui_but_update_select_flag(uiBut *but, double *value)
{
- switch (ui_is_but_push_ex(but, value)) {
+ switch (ui_but_is_pushed_ex(but, value)) {
case true:
but->flag |= UI_SELECT;
break;
@@ -1463,13 +1490,13 @@ static void ui_check_but_select(uiBut *but, double *value)
}
}
-static uiBut *ui_find_inlink(uiBlock *block, void *poin)
+static uiBut *ui_linkline_find_inlink(uiBlock *block, void *poin)
{
uiBut *but;
but = block->buttons.first;
while (but) {
- if (but->type == INLINK) {
+ if (but->type == UI_BTYPE_INLINK) {
if (but->poin == poin) return but;
}
but = but->next;
@@ -1477,7 +1504,7 @@ static uiBut *ui_find_inlink(uiBlock *block, void *poin)
return NULL;
}
-static void ui_add_link_line(ListBase *listb, uiBut *but, uiBut *bt, short deactive)
+static void ui_linkline_add(ListBase *listb, uiBut *but, uiBut *bt, short deactive)
{
uiLinkLine *line;
@@ -1488,12 +1515,12 @@ static void ui_add_link_line(ListBase *listb, uiBut *but, uiBut *bt, short deact
line->deactive = deactive;
}
-uiBut *uiFindInlink(uiBlock *block, void *poin)
+uiBut *UI_block_links_find_inlink(uiBlock *block, void *poin)
{
- return ui_find_inlink(block, poin);
+ return ui_linkline_find_inlink(block, poin);
}
-void uiComposeLinks(uiBlock *block)
+void UI_block_links_compose(uiBlock *block)
{
uiBut *but, *bt;
uiLink *link;
@@ -1502,7 +1529,7 @@ void uiComposeLinks(uiBlock *block)
but = block->buttons.first;
while (but) {
- if (but->type == LINK) {
+ if (but->type == UI_BTYPE_LINK) {
link = but->link;
/* for all pointers in the array */
@@ -1510,26 +1537,26 @@ void uiComposeLinks(uiBlock *block)
if (link->ppoin) {
ppoin = link->ppoin;
for (a = 0; a < *(link->totlink); a++) {
- bt = ui_find_inlink(block, (*ppoin)[a]);
+ bt = ui_linkline_find_inlink(block, (*ppoin)[a]);
if (bt) {
if ((but->flag & UI_BUT_SCA_LINK_GREY) || (bt->flag & UI_BUT_SCA_LINK_GREY)) {
- ui_add_link_line(&link->lines, but, bt, true);
+ ui_linkline_add(&link->lines, but, bt, true);
}
else {
- ui_add_link_line(&link->lines, but, bt, false);
+ ui_linkline_add(&link->lines, but, bt, false);
}
}
}
}
else if (link->poin) {
- bt = ui_find_inlink(block, *link->poin);
+ bt = ui_linkline_find_inlink(block, *link->poin);
if (bt) {
if ((but->flag & UI_BUT_SCA_LINK_GREY) || (bt->flag & UI_BUT_SCA_LINK_GREY)) {
- ui_add_link_line(&link->lines, but, bt, true);
+ ui_linkline_add(&link->lines, but, bt, true);
}
else {
- ui_add_link_line(&link->lines, but, bt, false);
+ ui_linkline_add(&link->lines, but, bt, false);
}
}
}
@@ -1542,7 +1569,7 @@ void uiComposeLinks(uiBlock *block)
/* ************************************************ */
-void uiBlockSetButLock(uiBlock *block, bool val, const char *lockstr)
+void UI_block_lock_set(uiBlock *block, bool val, const char *lockstr)
{
if (val) {
block->lock = val;
@@ -1550,7 +1577,7 @@ void uiBlockSetButLock(uiBlock *block, bool val, const char *lockstr)
}
}
-void uiBlockClearButLock(uiBlock *block)
+void UI_block_lock_clear(uiBlock *block)
{
block->lock = false;
block->lockstr = NULL;
@@ -1558,7 +1585,7 @@ void uiBlockClearButLock(uiBlock *block)
/* *************************************************************** */
-void ui_delete_linkline(uiLinkLine *line, uiBut *but)
+void ui_linkline_remove(uiLinkLine *line, uiBut *but)
{
uiLink *link;
int a, b;
@@ -1599,7 +1626,7 @@ void ui_delete_linkline(uiLinkLine *line, uiBut *but)
* an edit override pointer while dragging for example */
/* for buttons pointing to color for example */
-void ui_get_but_vectorf(uiBut *but, float vec[3])
+void ui_but_v3_get(uiBut *but, float vec[3])
{
PropertyRNA *prop;
int a;
@@ -1645,13 +1672,13 @@ void ui_get_but_vectorf(uiBut *but, float vec[3])
}
}
- if (but->type == BUT_NORMAL) {
+ if (but->type == UI_BTYPE_UNITVEC) {
normalize_v3(vec);
}
}
/* for buttons pointing to color for example */
-void ui_set_but_vectorf(uiBut *but, const float vec[3])
+void ui_but_v3_set(uiBut *but, const float vec[3])
{
PropertyRNA *prop;
@@ -1691,7 +1718,7 @@ void ui_set_but_vectorf(uiBut *but, const float vec[3])
}
}
-bool ui_is_but_float(const uiBut *but)
+bool ui_but_is_float(const uiBut *but)
{
if (but->pointype == UI_BUT_POIN_FLOAT && but->poin)
return true;
@@ -1702,28 +1729,31 @@ bool ui_is_but_float(const uiBut *but)
return false;
}
-bool ui_is_but_bool(const uiBut *but)
+bool ui_but_is_bool(const uiBut *but)
{
- if (ELEM(but->type, TOG, TOGN, ICONTOG, ICONTOGN))
+ if (ELEM(but->type, UI_BTYPE_TOGGLE, UI_BTYPE_TOGGLE_N, UI_BTYPE_ICON_TOGGLE, UI_BTYPE_ICON_TOGGLE_N))
return true;
if (but->rnaprop && RNA_property_type(but->rnaprop) == PROP_BOOLEAN)
return true;
+ if ((but->rnaprop && RNA_property_type(but->rnaprop) == PROP_ENUM) && (but->type == UI_BTYPE_ROW))
+ return true;
+
return false;
}
-bool ui_is_but_unit(const uiBut *but)
+bool ui_but_is_unit(const uiBut *but)
{
UnitSettings *unit = but->block->unit;
- const int unit_type = uiButGetUnitType(but);
+ const int unit_type = UI_but_unit_type_get(but);
if (unit_type == PROP_UNIT_NONE)
return false;
#if 1 /* removed so angle buttons get correct snapping */
- if (ui_is_but_unit_radians_ex(unit, unit_type))
+ if (ui_but_is_unit_radians_ex(unit, unit_type))
return false;
#endif
@@ -1743,7 +1773,7 @@ bool ui_is_but_unit(const uiBut *but)
/**
* Check if this button is similar enough to be grouped with another.
*/
-bool ui_is_but_compatible(const uiBut *but_a, const uiBut *but_b)
+bool ui_but_is_compatible(const uiBut *but_a, const uiBut *but_b)
{
if (but_a->type != but_b->type)
return false;
@@ -1751,12 +1781,10 @@ bool ui_is_but_compatible(const uiBut *but_a, const uiBut *but_b)
return false;
if (but_a->rnaprop) {
+ /* skip 'rnapoin.data', 'rnapoin.id.data'
+ * allow different data to have the same props edited at once */
if (but_a->rnapoin.type != but_b->rnapoin.type)
return false;
- if (but_a->rnapoin.data != but_b->rnapoin.data)
- return false;
- if (but_a->rnapoin.id.data != but_b->rnapoin.id.data)
- return false;
if (RNA_property_type(but_a->rnaprop) != RNA_property_type(but_b->rnaprop))
return false;
if (RNA_property_subtype(but_a->rnaprop) != RNA_property_subtype(but_b->rnaprop))
@@ -1766,7 +1794,7 @@ bool ui_is_but_compatible(const uiBut *but_a, const uiBut *but_b)
return true;
}
-bool ui_is_but_rna_valid(uiBut *but)
+bool ui_but_is_rna_valid(uiBut *but)
{
if (but->rnaprop == NULL || RNA_struct_contains_property(&but->rnapoin, but->rnaprop)) {
return true;
@@ -1777,7 +1805,17 @@ bool ui_is_but_rna_valid(uiBut *but)
}
}
-double ui_get_but_val(uiBut *but)
+/**
+ * Checks if the button supports ctrl+mousewheel cycling
+ */
+bool ui_but_supports_cycling(const uiBut *but)
+{
+ return ((ELEM(but->type, UI_BTYPE_ROW, UI_BTYPE_NUM, UI_BTYPE_NUM_SLIDER, UI_BTYPE_LISTBOX)) ||
+ (but->type == UI_BTYPE_MENU && ui_but_menu_step_poll(but)) ||
+ (but->type == UI_BTYPE_COLOR && but->a1 != -1));
+}
+
+double ui_but_value_get(uiBut *but)
{
PropertyRNA *prop;
double value = 0.0;
@@ -1833,7 +1871,7 @@ double ui_get_but_val(uiBut *but)
return value;
}
-void ui_set_but_val(uiBut *but, double value)
+void ui_but_value_set(uiBut *but, double value)
{
PropertyRNA *prop;
@@ -1912,18 +1950,18 @@ void ui_set_but_val(uiBut *but, double value)
value = *((float *)but->poin) = (float)value;
}
- ui_check_but_select(but, &value);
+ ui_but_update_select_flag(but, &value);
}
-int ui_get_but_string_max_length(uiBut *but)
+int ui_but_string_get_max_length(uiBut *but)
{
- if (ELEM(but->type, TEX, SEARCH_MENU, SEARCH_MENU_UNLINK))
+ if (ELEM(but->type, UI_BTYPE_TEXT, UI_BTYPE_SEARCH_MENU))
return but->hardmax;
else
return UI_MAX_DRAW_STR;
}
-uiBut *ui_get_but_drag_multi_edit(uiBut *but)
+uiBut *ui_but_drag_multi_edit_get(uiBut *but)
{
uiBut *but_iter;
@@ -1938,10 +1976,60 @@ uiBut *ui_get_but_drag_multi_edit(uiBut *but)
return but_iter;
}
+/** \name Check to show extra icons
+ *
+ * Extra icons are shown on the right hand side of buttons.
+ * \{ */
+
+static bool ui_but_icon_extra_is_visible_search_unlink(const uiBut *but)
+{
+ BLI_assert(but->type == UI_BTYPE_SEARCH_MENU);
+ return ((but->editstr == NULL) &&
+ (but->drawstr[0] != '\0') &&
+ (but->flag & UI_BUT_SEARCH_UNLINK));
+}
+
+static bool ui_but_icon_extra_is_visible_eyedropper(uiBut *but)
+{
+ StructRNA *type;
+ short idcode;
+
+ BLI_assert(but->type == UI_BTYPE_SEARCH_MENU && (but->flag & UI_BUT_SEARCH_UNLINK));
+
+ if (but->rnaprop == NULL) {
+ return false;
+ }
+
+ type = RNA_property_pointer_type(&but->rnapoin, but->rnaprop);
+ idcode = RNA_type_to_ID_code(type);
+
+
+ return ((but->editstr == NULL) &&
+ (idcode == ID_OB || OB_DATA_SUPPORT_ID(idcode)));
+}
+
+uiButExtraIconType ui_but_icon_extra_get(uiBut *but)
+{
+ if ((but->flag & UI_BUT_SEARCH_UNLINK) == 0) {
+ /* pass */
+ }
+ else if (ui_but_icon_extra_is_visible_search_unlink(but)) {
+ return UI_BUT_ICONEXTRA_UNLINK;
+ }
+ else if (ui_but_icon_extra_is_visible_eyedropper(but)) {
+ return UI_BUT_ICONEXTRA_EYEDROPPER;
+ }
+
+ return UI_BUT_ICONEXTRA_NONE;
+}
+
+/** \} */
+
+
static double ui_get_but_scale_unit(uiBut *but, double value)
{
UnitSettings *unit = but->block->unit;
- int unit_type = uiButGetUnitType(but);
+ int unit_type = UI_but_unit_type_get(but);
/* Time unit is a bit special, not handled by BKE_scene_unit_scale() for now. */
if (unit_type == PROP_UNIT_TIME) { /* WARNING - using evil_C :| */
@@ -1954,11 +2042,11 @@ static double ui_get_but_scale_unit(uiBut *but, double value)
}
/* str will be overwritten */
-void ui_convert_to_unit_alt_name(uiBut *but, char *str, size_t maxlen)
+void ui_but_convert_to_unit_alt_name(uiBut *but, char *str, size_t maxlen)
{
- if (ui_is_but_unit(but)) {
+ if (ui_but_is_unit(but)) {
UnitSettings *unit = but->block->unit;
- int unit_type = uiButGetUnitType(but);
+ int unit_type = UI_but_unit_type_get(but);
char *orig_str;
orig_str = BLI_strdup(str);
@@ -1976,7 +2064,7 @@ static void ui_get_but_string_unit(uiBut *but, char *str, int len_max, double va
{
UnitSettings *unit = but->block->unit;
const bool do_split = (unit->flag & USER_UNIT_OPT_SPLIT) != 0;
- int unit_type = uiButGetUnitType(but);
+ int unit_type = UI_but_unit_type_get(but);
int precision;
if (unit->scale_length < 0.0001f) unit->scale_length = 1.0f; // XXX do_versions
@@ -1998,15 +2086,33 @@ static void ui_get_but_string_unit(uiBut *but, char *str, int len_max, double va
static float ui_get_but_step_unit(uiBut *but, float step_default)
{
- int unit_type = RNA_SUBTYPE_UNIT_VALUE(uiButGetUnitType(but));
- double step;
-
- step = bUnit_ClosestScalar(ui_get_but_scale_unit(but, step_default), but->block->unit->system, unit_type);
+ int unit_type = RNA_SUBTYPE_UNIT_VALUE(UI_but_unit_type_get(but));
+ const double step_orig = step_default * UI_PRECISION_FLOAT_SCALE;
+ /* Scaling up 'step_origg ' here is a bit arbitrary, its just giving better scales from user POV */
+ const double scale_step = ui_get_but_scale_unit(but, step_orig * 10);
+ const double step = bUnit_ClosestScalar(scale_step, but->block->unit->system, unit_type);
/* -1 is an error value */
if (step != -1.0) {
+ const double scale_unit = ui_get_but_scale_unit(but, 1.0);
+ const double step_unit = bUnit_ClosestScalar(scale_unit, but->block->unit->system, unit_type);
+ double step_final;
+
BLI_assert(step > 0.0);
- return (float)(step / ui_get_but_scale_unit(but, 1.0)) * 100.0f;
+
+ step_final = (step / scale_unit) / UI_PRECISION_FLOAT_SCALE;
+
+ if (step == step_unit) {
+ /* Logic here is to scale by the original 'step_orig'
+ * only when the unit step matches the scaled step.
+ *
+ * This is needed for units that don't have a wide range of scales (degrees for eg.).
+ * Without this we can't select between a single degree, or a 10th of a degree.
+ */
+ step_final *= step_orig;
+ }
+
+ return (float)step_final;
}
else {
return step_default;
@@ -2016,9 +2122,9 @@ static float ui_get_but_step_unit(uiBut *but, float step_default)
/**
* \param float_precision For number buttons the precision to use or -1 to fallback to the button default.
*/
-void ui_get_but_string_ex(uiBut *but, char *str, const size_t maxlen, const int float_precision)
+void ui_but_string_get_ex(uiBut *but, char *str, const size_t maxlen, const int float_precision)
{
- if (but->rnaprop && ELEM(but->type, TEX, SEARCH_MENU, SEARCH_MENU_UNLINK)) {
+ if (but->rnaprop && ELEM(but->type, UI_BTYPE_TEXT, UI_BTYPE_SEARCH_MENU)) {
PropertyType type;
const char *buf = NULL;
int buf_len;
@@ -2050,17 +2156,23 @@ void ui_get_but_string_ex(uiBut *but, char *str, const size_t maxlen, const int
str[0] = '\0';
}
else if (buf && buf != str) {
+ BLI_assert(maxlen <= buf_len + 1);
/* string was too long, we have to truncate */
- memcpy(str, buf, MIN2(maxlen, (size_t)(buf_len + 1)));
+ if (ui_but_is_utf8(but)) {
+ BLI_strncpy_utf8(str, buf, maxlen);
+ }
+ else {
+ BLI_strncpy(str, buf, maxlen);
+ }
MEM_freeN((void *)buf);
}
}
- else if (but->type == TEX) {
+ else if (but->type == UI_BTYPE_TEXT) {
/* string */
BLI_strncpy(str, but->poin, maxlen);
return;
}
- else if (ELEM(but->type, SEARCH_MENU, SEARCH_MENU_UNLINK)) {
+ else if (but->type == UI_BTYPE_SEARCH_MENU) {
/* string */
BLI_strncpy(str, but->poin, maxlen);
return;
@@ -2072,14 +2184,14 @@ void ui_get_but_string_ex(uiBut *but, char *str, const size_t maxlen, const int
/* number editing */
double value;
- value = ui_get_but_val(but);
+ value = ui_but_value_get(but);
- if (ui_is_but_float(but)) {
- if (ui_is_but_unit(but)) {
+ if (ui_but_is_float(but)) {
+ if (ui_but_is_unit(but)) {
ui_get_but_string_unit(but, str, maxlen, value, false, float_precision);
}
else {
- const int prec = (float_precision == -1) ? ui_but_float_precision(but, value) : float_precision;
+ const int prec = (float_precision == -1) ? ui_but_calc_float_precision(but, value) : float_precision;
BLI_snprintf(str, maxlen, "%.*f", prec, value);
}
}
@@ -2087,9 +2199,9 @@ void ui_get_but_string_ex(uiBut *but, char *str, const size_t maxlen, const int
BLI_snprintf(str, maxlen, "%d", (int)value);
}
}
-void ui_get_but_string(uiBut *but, char *str, const size_t maxlen)
+void ui_but_string_get(uiBut *but, char *str, const size_t maxlen)
{
- ui_get_but_string_ex(but, str, maxlen, -1);
+ ui_but_string_get_ex(but, str, maxlen, -1);
}
#ifdef WITH_PYTHON
@@ -2097,7 +2209,7 @@ void ui_get_but_string(uiBut *but, char *str, const size_t maxlen)
static bool ui_set_but_string_eval_num_unit(bContext *C, uiBut *but, const char *str, double *value)
{
char str_unit_convert[256];
- const int unit_type = uiButGetUnitType(but);
+ const int unit_type = UI_but_unit_type_get(but);
BLI_strncpy(str_unit_convert, str, sizeof(str_unit_convert));
@@ -2112,14 +2224,14 @@ static bool ui_set_but_string_eval_num_unit(bContext *C, uiBut *but, const char
#endif /* WITH_PYTHON */
-bool ui_set_but_string_eval_num(bContext *C, uiBut *but, const char *str, double *value)
+bool ui_but_string_set_eval_num(bContext *C, uiBut *but, const char *str, double *value)
{
bool ok = false;
#ifdef WITH_PYTHON
if (str[0] != '\0') {
- bool is_unit_but = (ui_is_but_float(but) && ui_is_but_unit(but));
+ bool is_unit_but = (ui_but_is_float(but) && ui_but_is_unit(but));
/* only enable verbose if we won't run again with units */
if (BPY_button_exec(C, str, value, is_unit_but == false) != -1) {
/* if the value parsed ok without unit conversion this button may still need a unit multiplier */
@@ -2152,10 +2264,36 @@ bool ui_set_but_string_eval_num(bContext *C, uiBut *but, const char *str, double
return ok;
}
+/* just the assignment/free part */
+static void ui_but_string_set_internal(uiBut *but, const char *str, size_t str_len)
+{
+ BLI_assert(str_len == strlen(str));
+ BLI_assert(but->str == NULL);
+ str_len += 1;
+
+ if (str_len > UI_MAX_NAME_STR) {
+ but->str = MEM_mallocN(str_len, "ui_def_but str");
+ }
+ else {
+ but->str = but->strdata;
+ }
+ memcpy(but->str, str, str_len);
+}
+
+static void ui_but_string_free_internal(uiBut *but)
+{
+ if (but->str) {
+ if (but->str != but->strdata) {
+ MEM_freeN(but->str);
+ }
+ /* must call 'ui_but_string_set_internal' after */
+ but->str = NULL;
+ }
+}
-bool ui_set_but_string(bContext *C, uiBut *but, const char *str)
+bool ui_but_string_set(bContext *C, uiBut *but, const char *str)
{
- if (but->rnaprop && ELEM(but->type, TEX, SEARCH_MENU, SEARCH_MENU_UNLINK)) {
+ if (but->rnaprop && ELEM(but->type, UI_BTYPE_TEXT, UI_BTYPE_SEARCH_MENU)) {
if (RNA_property_editable(&but->rnapoin, but->rnaprop)) {
PropertyType type;
@@ -2200,14 +2338,14 @@ bool ui_set_but_string(bContext *C, uiBut *but, const char *str)
}
}
}
- else if (but->type == TEX) {
+ else if (but->type == UI_BTYPE_TEXT) {
/* string */
- if (ui_is_but_utf8(but)) BLI_strncpy_utf8(but->poin, str, but->hardmax);
+ if (ui_but_is_utf8(but)) BLI_strncpy_utf8(but->poin, str, but->hardmax);
else BLI_strncpy(but->poin, str, but->hardmax);
return true;
}
- else if (ELEM(but->type, SEARCH_MENU, SEARCH_MENU_UNLINK)) {
+ else if (but->type == UI_BTYPE_SEARCH_MENU) {
/* string */
BLI_strncpy(but->poin, str, but->hardmax);
return true;
@@ -2224,38 +2362,38 @@ bool ui_set_but_string(bContext *C, uiBut *but, const char *str)
/* number editing */
double value;
- if (ui_set_but_string_eval_num(C, but, str, &value) == false) {
+ if (ui_but_string_set_eval_num(C, but, str, &value) == false) {
+ WM_report_banner_show(C);
return false;
}
- if (!ui_is_but_float(but)) value = (int)floor(value + 0.5);
+ if (!ui_but_is_float(but)) value = (int)floor(value + 0.5);
/* not that we use hard limits here */
if (value < (double)but->hardmin) value = but->hardmin;
if (value > (double)but->hardmax) value = but->hardmax;
- ui_set_but_val(but, value);
+ ui_but_value_set(but, value);
return true;
}
return false;
}
-void ui_set_but_default(bContext *C, const bool all, const bool use_afterfunc)
+void ui_but_default_set(bContext *C, const bool all, const bool use_afterfunc)
{
- const char *opstring = "UI_OT_reset_default_button";
+ wmOperatorType *ot = WM_operatortype_find("UI_OT_reset_default_button", true);
if (use_afterfunc) {
PointerRNA *ptr;
- wmOperatorType *ot = WM_operatortype_find(opstring, 0);
ptr = ui_handle_afterfunc_add_operator(ot, WM_OP_EXEC_DEFAULT, true);
RNA_boolean_set(ptr, "all", all);
}
else {
PointerRNA ptr;
- WM_operator_properties_create(&ptr, opstring);
+ WM_operator_properties_create_ptr(&ptr, ot);
RNA_boolean_set(&ptr, "all", all);
- WM_operator_name_call(C, opstring, WM_OP_EXEC_DEFAULT, &ptr);
+ WM_operator_name_call_ptr(C, ot, WM_OP_EXEC_DEFAULT, &ptr);
WM_operator_properties_free(&ptr);
}
}
@@ -2371,7 +2509,7 @@ static void ui_set_but_soft_range(uiBut *but)
but->softmax = softmax;
}
else if (but->poin && (but->pointype & UI_BUT_POIN_TYPES)) {
- float value = ui_get_but_val(but);
+ float value = ui_but_value_get(but);
CLAMP(value, but->hardmin, but->hardmax);
but->softmin = min_ff(but->softmin, value);
but->softmax = max_ff(but->softmax, value);
@@ -2392,7 +2530,7 @@ static void ui_free_link(uiLink *link)
}
/* can be called with C==NULL */
-static void ui_free_but(const bContext *C, uiBut *but)
+static void ui_but_free(const bContext *C, uiBut *but)
{
if (but->opptr) {
WM_operator_properties_free(but->opptr);
@@ -2403,12 +2541,16 @@ static void ui_free_but(const bContext *C, uiBut *but)
MEM_freeN(but->func_argN);
}
+ if (but->tip_argN) {
+ MEM_freeN(but->tip_argN);
+ }
+
if (but->active) {
/* XXX solve later, buttons should be free-able without context ideally,
* however they may have open tooltips or popup windows, which need to
* be closed using a context pointer */
if (C) {
- ui_button_active_free(C, but);
+ ui_but_active_free(C, but);
}
else {
if (but->active) {
@@ -2421,24 +2563,28 @@ static void ui_free_but(const bContext *C, uiBut *but)
}
ui_free_link(but->link);
- if ((but->type == BUT_IMAGE) && but->poin) {
+ if ((but->type == UI_BTYPE_IMAGE) && but->poin) {
IMB_freeImBuf((struct ImBuf *)but->poin);
}
+ if (but->dragpoin && (but->dragflag & UI_BUT_DRAGPOIN_FREE)) {
+ MEM_freeN(but->dragpoin);
+ }
+
BLI_assert(UI_butstore_is_registered(but->block, but) == false);
MEM_freeN(but);
}
/* can be called with C==NULL */
-void uiFreeBlock(const bContext *C, uiBlock *block)
+void UI_block_free(const bContext *C, uiBlock *block)
{
uiBut *but;
UI_butstore_clear(block);
while ((but = BLI_pophead(&block->buttons))) {
- ui_free_but(C, but);
+ ui_but_free(C, but);
}
if (block->unit) {
@@ -2452,21 +2598,22 @@ void uiFreeBlock(const bContext *C, uiBlock *block)
CTX_store_free_list(&block->contexts);
BLI_freelistN(&block->saferct);
+ BLI_freelistN(&block->color_pickers.list);
MEM_freeN(block);
}
/* can be called with C==NULL */
-void uiFreeBlocks(const bContext *C, ListBase *lb)
+void UI_blocklist_free(const bContext *C, ListBase *lb)
{
uiBlock *block;
while ((block = BLI_pophead(lb))) {
- uiFreeBlock(C, block);
+ UI_block_free(C, block);
}
}
-void uiFreeInactiveBlocks(const bContext *C, ListBase *lb)
+void UI_blocklist_free_inactive(const bContext *C, ListBase *lb)
{
uiBlock *block, *nextblock;
@@ -2476,7 +2623,7 @@ void uiFreeInactiveBlocks(const bContext *C, ListBase *lb)
if (!block->handle) {
if (!block->active) {
BLI_remlink(lb, block);
- uiFreeBlock(C, block);
+ UI_block_free(C, block);
}
else
block->active = 0;
@@ -2484,7 +2631,7 @@ void uiFreeInactiveBlocks(const bContext *C, ListBase *lb)
}
}
-void uiBlockSetRegion(uiBlock *block, ARegion *region)
+void UI_block_region_set(uiBlock *block, ARegion *region)
{
ListBase *lb = &region->uiblocks;
uiBlock *oldblock = NULL;
@@ -2507,7 +2654,7 @@ void uiBlockSetRegion(uiBlock *block, ARegion *region)
block->oldblock = oldblock;
}
-uiBlock *uiBeginBlock(const bContext *C, ARegion *region, const char *name, short dt)
+uiBlock *UI_block_begin(const bContext *C, ARegion *region, const char *name, short dt)
{
uiBlock *block;
wmWindow *window;
@@ -2540,7 +2687,7 @@ uiBlock *uiBeginBlock(const bContext *C, ARegion *region, const char *name, shor
BLI_strncpy(block->name, name, sizeof(block->name));
if (region)
- uiBlockSetRegion(block, region);
+ UI_block_region_set(block, region);
/* window matrix and aspect */
if (region && region->swinid) {
@@ -2564,23 +2711,23 @@ uiBlock *uiBeginBlock(const bContext *C, ARegion *region, const char *name, shor
return block;
}
-uiBlock *uiGetBlock(const char *name, ARegion *ar)
+uiBlock *UI_block_find_in_region(const char *name, ARegion *ar)
{
return BLI_findstring(&ar->uiblocks, name, offsetof(uiBlock, name));
}
-void uiBlockSetEmboss(uiBlock *block, char dt)
+void UI_block_emboss_set(uiBlock *block, char dt)
{
block->dt = dt;
}
-void ui_check_but(uiBut *but)
+void ui_but_update(uiBut *but)
{
/* if something changed in the button */
double value = UI_BUT_VALUE_UNSET;
// float okwidth; // UNUSED
- ui_check_but_select(but, &value);
+ ui_but_update_select_flag(but, &value);
/* only update soft range while not editing */
if (!(but->editval || but->editstr || but->editvec)) {
@@ -2593,16 +2740,20 @@ void ui_check_but(uiBut *but)
/* test for min and max, icon sliders, etc */
switch (but->type) {
- case NUM:
- case SCROLL:
- case NUMSLI:
+ case UI_BTYPE_NUM:
+ case UI_BTYPE_SCROLL:
+ case UI_BTYPE_NUM_SLIDER:
UI_GET_BUT_VALUE_INIT(but, value);
- if (value < (double)but->hardmin) ui_set_but_val(but, but->hardmin);
- else if (value > (double)but->hardmax) ui_set_but_val(but, but->hardmax);
+ if (value < (double)but->hardmin) ui_but_value_set(but, but->hardmin);
+ else if (value > (double)but->hardmax) ui_but_value_set(but, but->hardmax);
+
+ /* max must never be smaller than min! Both being equal is allowed though */
+ BLI_assert(but->softmin <= but->softmax &&
+ but->hardmin <= but->hardmax);
break;
- case ICONTOG:
- case ICONTOGN:
+ case UI_BTYPE_ICON_TOGGLE:
+ case UI_BTYPE_ICON_TOGGLE_N:
if (!but->rnaprop || (RNA_property_flag(but->rnaprop) & PROP_ICONS_CONSECUTIVE)) {
if (but->flag & UI_SELECT) but->iconadd = 1;
else but->iconadd = 0;
@@ -2621,7 +2772,7 @@ void ui_check_but(uiBut *but)
/* name: */
switch (but->type) {
- case MENU:
+ case UI_BTYPE_MENU:
if (BLI_rctf_size_x(&but->rect) > 24.0f) {
/* only needed for menus in popup blocks that don't recreate buttons on redraw */
if (but->block->flag & UI_BLOCK_LOOP) {
@@ -2631,7 +2782,9 @@ void ui_check_but(uiBut *but)
if (RNA_property_enum_name_gettexted(but->block->evil_C,
&but->rnapoin, but->rnaprop, value, &buf))
{
- BLI_strncpy(but->str, buf, sizeof(but->strdata));
+ size_t slen = strlen(buf);
+ ui_but_string_free_internal(but);
+ ui_but_string_set_internal(but, buf, slen);
}
}
}
@@ -2639,8 +2792,8 @@ void ui_check_but(uiBut *but)
}
break;
- case NUM:
- case NUMSLI:
+ case UI_BTYPE_NUM:
+ case UI_BTYPE_NUM_SLIDER:
if (!but->editstr) {
const char *drawstr_suffix = NULL;
@@ -2650,7 +2803,7 @@ void ui_check_but(uiBut *but)
slen = BLI_strncpy_rlen(but->drawstr, but->str, sizeof(but->drawstr));
- if (ui_is_but_float(but)) {
+ if (ui_but_is_float(but)) {
if (value == (double) FLT_MAX) {
slen += BLI_strncpy_rlen(but->drawstr + slen, "inf", sizeof(but->drawstr) - slen);
}
@@ -2658,18 +2811,18 @@ void ui_check_but(uiBut *but)
slen += BLI_strncpy_rlen(but->drawstr + slen, "-inf", sizeof(but->drawstr) - slen);
}
/* support length type buttons */
- else if (ui_is_but_unit(but)) {
+ else if (ui_but_is_unit(but)) {
char new_str[sizeof(but->drawstr)];
ui_get_but_string_unit(but, new_str, sizeof(new_str), value, true, -1);
slen += BLI_strncpy_rlen(but->drawstr + slen, new_str, sizeof(but->drawstr) - slen);
}
else {
- const int prec = ui_but_float_precision(but, value);
- slen += BLI_snprintf(but->drawstr + slen, sizeof(but->drawstr) - slen, "%.*f", prec, value);
+ const int prec = ui_but_calc_float_precision(but, value);
+ slen += BLI_snprintf_rlen(but->drawstr + slen, sizeof(but->drawstr) - slen, "%.*f", prec, value);
}
}
else {
- slen += BLI_snprintf(but->drawstr + slen, sizeof(but->drawstr) - slen, "%d", (int)value);
+ slen += BLI_snprintf_rlen(but->drawstr + slen, sizeof(but->drawstr) - slen, "%d", (int)value);
}
if (but->rnaprop) {
@@ -2690,11 +2843,11 @@ void ui_check_but(uiBut *but)
}
break;
- case LABEL:
- if (ui_is_but_float(but)) {
+ case UI_BTYPE_LABEL:
+ if (ui_but_is_float(but)) {
int prec;
UI_GET_BUT_VALUE_INIT(but, value);
- prec = ui_but_float_precision(but, value);
+ prec = ui_but_calc_float_precision(but, value);
BLI_snprintf(but->drawstr, sizeof(but->drawstr), "%s%.*f", but->str, prec, value);
}
else {
@@ -2703,18 +2856,17 @@ void ui_check_but(uiBut *but)
break;
- case TEX:
- case SEARCH_MENU:
- case SEARCH_MENU_UNLINK:
+ case UI_BTYPE_TEXT:
+ case UI_BTYPE_SEARCH_MENU:
if (!but->editstr) {
char str[UI_MAX_DRAW_STR];
- ui_get_but_string(but, str, UI_MAX_DRAW_STR);
+ ui_but_string_get(but, str, UI_MAX_DRAW_STR);
BLI_snprintf(but->drawstr, sizeof(but->drawstr), "%s%s", but->str, str);
}
break;
- case KEYEVT:
+ case UI_BTYPE_KEY_EVENT:
{
const char *str;
if (but->flag & UI_SELECT) {
@@ -2722,12 +2874,12 @@ void ui_check_but(uiBut *but)
}
else {
UI_GET_BUT_VALUE_INIT(but, value);
- str = WM_key_event_string((short)value);
+ str = WM_key_event_string((short)value, false);
}
BLI_snprintf(but->drawstr, UI_MAX_DRAW_STR, "%s%s", but->str, str);
break;
}
- case HOTKEYEVT:
+ case UI_BTYPE_HOTKEY_EVENT:
if (but->flag & UI_SELECT) {
if (but->modifier_key) {
@@ -2754,8 +2906,8 @@ void ui_check_but(uiBut *but)
break;
- case HSVCUBE:
- case HSVCIRCLE:
+ case UI_BTYPE_HSVCUBE:
+ case UI_BTYPE_HSVCIRCLE:
break;
default:
BLI_strncpy(but->drawstr, but->str, UI_MAX_DRAW_STR);
@@ -2771,10 +2923,10 @@ void ui_check_but(uiBut *but)
}
-void uiBlockBeginAlign(uiBlock *block)
+void UI_block_align_begin(uiBlock *block)
{
/* if other align was active, end it */
- if (block->flag & UI_BUT_ALIGN) uiBlockEndAlign(block);
+ if (block->flag & UI_BUT_ALIGN) UI_block_align_end(block);
block->flag |= UI_BUT_ALIGN_DOWN;
block->alignnr++;
@@ -2800,17 +2952,17 @@ static bool buts_are_horiz(uiBut *but1, uiBut *but2)
return (dx <= dy);
}
-void uiBlockEndAlign(uiBlock *block)
+void UI_block_align_end(uiBlock *block)
{
block->flag &= ~UI_BUT_ALIGN; /* all 4 flags */
}
bool ui_but_can_align(uiBut *but)
{
- return !ELEM(but->type, LABEL, OPTION, OPTIONN, SEPR, SEPRLINE);
+ return !ELEM(but->type, UI_BTYPE_LABEL, UI_BTYPE_CHECKBOX, UI_BTYPE_CHECKBOX_N, UI_BTYPE_SEPR, UI_BTYPE_SEPR_LINE);
}
-static void ui_block_do_align_but(uiBut *first, short nr)
+static void ui_block_align_calc_but(uiBut *first, short nr)
{
uiBut *prev, *but = NULL, *next;
int flag = 0, cols = 0, rows = 0;
@@ -2950,7 +3102,7 @@ static void ui_block_do_align_but(uiBut *first, short nr)
}
}
-void ui_block_do_align(uiBlock *block)
+void ui_block_align_calc(uiBlock *block)
{
uiBut *but;
short nr;
@@ -2959,7 +3111,7 @@ void ui_block_do_align(uiBlock *block)
for (but = block->buttons.first; but; ) {
if (but->alignnr) {
nr = but->alignnr;
- ui_block_do_align_but(but, nr);
+ ui_block_align_calc_but(but, nr);
/* skip with same number */
for (; but && but->alignnr == nr; but = but->next) {
@@ -2976,39 +3128,54 @@ void ui_block_do_align(uiBlock *block)
}
}
-struct ColorManagedDisplay *ui_block_display_get(uiBlock *block)
+struct ColorManagedDisplay *ui_block_cm_display_get(uiBlock *block)
{
return IMB_colormanagement_display_get_named(block->display_device);
}
-void ui_block_to_display_space_v3(uiBlock *block, float pixel[3])
+void ui_block_cm_to_display_space_v3(uiBlock *block, float pixel[3])
{
- struct ColorManagedDisplay *display = ui_block_display_get(block);
+ struct ColorManagedDisplay *display = ui_block_cm_display_get(block);
IMB_colormanagement_scene_linear_to_display_v3(pixel, display);
}
-void ui_block_to_scene_linear_v3(uiBlock *block, float pixel[3])
+void ui_block_cm_to_scene_linear_v3(uiBlock *block, float pixel[3])
{
- struct ColorManagedDisplay *display = ui_block_display_get(block);
+ struct ColorManagedDisplay *display = ui_block_cm_display_get(block);
IMB_colormanagement_display_to_scene_linear_v3(pixel, display);
}
+void ui_block_cm_to_display_space_range(uiBlock *block, float *min, float *max)
+{
+ struct ColorManagedDisplay *display = ui_block_cm_display_get(block);
+ float pixel[3];
+
+ copy_v3_fl(pixel, *min);
+ IMB_colormanagement_scene_linear_to_display_v3(pixel, display);
+ *min = min_fff(UNPACK3(pixel));
+
+ copy_v3_fl(pixel, *max);
+ IMB_colormanagement_scene_linear_to_display_v3(pixel, display);
+ *max = max_fff(UNPACK3(pixel));
+}
+
/**
* \brief ui_def_but is the function that draws many button types
*
- * \param x,y The lower left hand corner of the button (X axis)
- * \param width,height The size of the button.
+ * \param x, y: The lower left hand corner of the button (X axis)
+ * \param width, height: The size of the button.
*
* for float buttons:
- * - \a a1 Click Step (how much to change the value each click)
- * - \a a2 Number of decimal point values to display. 0 defaults to 3 (0.000)
- * 1,2,3, and a maximum of 4, all greater values will be clamped to 4.
+ * \param a1: Click Step (how much to change the value each click)
+ * \param a2: Number of decimal point values to display. 0 defaults to 3 (0.000)
+ * 1,2,3, and a maximum of 4, all greater values will be clamped to 4.
*/
-static uiBut *ui_def_but(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)
+static uiBut *ui_def_but(
+ 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;
int slen;
@@ -3016,7 +3183,7 @@ static uiBut *ui_def_but(uiBlock *block, int type, int retval, const char *str,
BLI_assert(width >= 0 && height >= 0);
/* we could do some more error checks here */
- if ((type & BUTTYPE) == LABEL) {
+ if ((type & BUTTYPE) == UI_BTYPE_LABEL) {
BLI_assert((poin != NULL || min != 0.0f || max != 0.0f || (a1 == 0.0f && a2 != 0.0f) || (a1 != 0.0f && a1 != 1.0f)) == false);
}
@@ -3039,13 +3206,7 @@ static uiBut *ui_def_but(uiBlock *block, int type, int retval, const char *str,
but->retval = retval;
slen = strlen(str);
- if (slen >= UI_MAX_NAME_STR) {
- but->str = MEM_mallocN(slen + 1, "ui_def_but str");
- }
- else {
- but->str = but->strdata;
- }
- memcpy(but->str, str, slen + 1);
+ ui_but_string_set_internal(but, str, slen);
but->rect.xmin = x;
but->rect.ymin = y;
@@ -3079,7 +3240,7 @@ static uiBut *ui_def_but(uiBlock *block, int type, int retval, const char *str,
but->pos = -1; /* cursor invisible */
- if (ELEM(but->type, NUM, NUMSLI)) { /* add a space to name */
+ if (ELEM(but->type, UI_BTYPE_NUM, UI_BTYPE_NUM_SLIDER)) { /* add a space to name */
/* slen remains unchanged from previous assignment, ensure this stays true */
if (slen > 0 && slen < UI_MAX_NAME_STR - 2) {
if (but->str[slen - 1] != ' ') {
@@ -3093,12 +3254,15 @@ static uiBut *ui_def_but(uiBlock *block, int type, int retval, const char *str,
but->drawflag |= (UI_BUT_TEXT_LEFT | UI_BUT_ICON_LEFT);
}
else if ((block->flag & UI_BLOCK_LOOP) ||
- ELEM(but->type, MENU, TEX, LABEL, BLOCK, BUTM, SEARCH_MENU, PROGRESSBAR, SEARCH_MENU_UNLINK))
+ ELEM(but->type,
+ UI_BTYPE_MENU, UI_BTYPE_TEXT, UI_BTYPE_LABEL,
+ UI_BTYPE_BLOCK, UI_BTYPE_BUT_MENU, UI_BTYPE_SEARCH_MENU,
+ UI_BTYPE_PROGRESS_BAR))
{
but->drawflag |= (UI_BUT_TEXT_LEFT | UI_BUT_ICON_LEFT);
}
#ifdef USE_NUMBUTS_LR_ALIGN
- else if (ELEM(but->type, NUM, NUMSLI)) {
+ else if (ELEM(but->type, UI_BTYPE_NUM, UI_BTYPE_NUM_SLIDER)) {
but->drawflag |= UI_BUT_TEXT_LEFT;
}
#endif
@@ -3112,9 +3276,18 @@ static uiBut *ui_def_but(uiBlock *block, int type, int retval, const char *str,
}
/* keep track of UI_interface.h */
- if (ELEM(but->type, BLOCK, BUT, LABEL, PULLDOWN, ROUNDBOX, LISTBOX, BUTM, SCROLL, SEPR, SEPRLINE, GRIP)) {}
- else if (but->type >= SEARCH_MENU) {}
- else but->flag |= UI_BUT_UNDO;
+ if (ELEM(but->type,
+ UI_BTYPE_BLOCK, UI_BTYPE_BUT, UI_BTYPE_LABEL,
+ UI_BTYPE_PULLDOWN, UI_BTYPE_ROUNDBOX, UI_BTYPE_LISTBOX,
+ UI_BTYPE_BUT_MENU, UI_BTYPE_SCROLL, UI_BTYPE_GRIP,
+ UI_BTYPE_SEPR, UI_BTYPE_SEPR_LINE) ||
+ (but->type >= UI_BTYPE_SEARCH_MENU))
+ {
+ /* pass */
+ }
+ else {
+ but->flag |= UI_BUT_UNDO;
+ }
BLI_addtail(&block->buttons, but);
@@ -3131,6 +3304,19 @@ static uiBut *ui_def_but(uiBlock *block, int type, int retval, const char *str,
return but;
}
+void ui_def_but_icon(uiBut *but, const int icon, const int flag)
+{
+ if (icon) {
+ ui_icon_ensure_deferred(but->block->evil_C, icon, (flag & UI_BUT_ICON_PREVIEW) != 0);
+ }
+ but->icon = (BIFIconID)icon;
+ but->flag |= flag;
+
+ if (but->str && but->str[0]) {
+ but->drawflag |= UI_BUT_ICON_LEFT;
+ }
+}
+
static void ui_def_but_rna__disable(uiBut *but)
{
but->flag |= UI_BUT_DISABLED;
@@ -3155,13 +3341,13 @@ static void ui_def_but_rna__menu(bContext *UNUSED(C), uiLayout *layout, void *bu
int column_start = 0, column_end = 0;
int nbr_entries_nosepr = 0;
- uiBlockSetFlag(block, UI_BLOCK_MOVEMOUSE_QUIT);
+ UI_block_flag_enable(block, UI_BLOCK_MOVEMOUSE_QUIT);
RNA_property_enum_items_gettexted(block->evil_C, &but->rnapoin, but->rnaprop, &item_array, NULL, &free);
/* we dont want nested rows, cols in menus */
- uiBlockSetCurLayout(block, layout);
+ UI_block_layout_set_current(block, layout);
for (item = item_array; item->identifier; item++, totitems++) {
if (!item->identifier[0]) {
@@ -3190,7 +3376,7 @@ static void ui_def_but_rna__menu(bContext *UNUSED(C), uiLayout *layout, void *bu
rows++;
/* Title */
- uiDefBut(block, LABEL, 0, RNA_property_ui_name(but->rnaprop),
+ uiDefBut(block, UI_BTYPE_LABEL, 0, RNA_property_ui_name(but->rnaprop),
0, 0, UI_UNIT_X * 5, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
uiItemS(layout);
@@ -3233,7 +3419,7 @@ static void ui_def_but_rna__menu(bContext *UNUSED(C), uiLayout *layout, void *bu
}
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, item->name, 0, 0, UI_UNIT_X * 5, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
+ uiDefBut(block, UI_BTYPE_LABEL, 0, item->name, 0, 0, UI_UNIT_X * 5, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
}
}
else {
@@ -3242,21 +3428,24 @@ static void ui_def_but_rna__menu(bContext *UNUSED(C), uiLayout *layout, void *bu
}
else {
if (item->icon) {
- uiDefIconTextButI(block, BUTM, B_NOP, item->icon, item->name, 0, 0,
+ uiDefIconTextButI(block, UI_BTYPE_BUT_MENU, B_NOP, item->icon, item->name, 0, 0,
UI_UNIT_X * 5, UI_UNIT_Y, &handle->retvalue, item->value, 0.0, 0, -1, item->description);
}
else {
- uiDefButI(block, BUTM, B_NOP, item->name, 0, 0,
+ uiDefButI(block, UI_BTYPE_BUT_MENU, B_NOP, item->name, 0, 0,
UI_UNIT_X * 5, UI_UNIT_X, &handle->retvalue, item->value, 0.0, 0, -1, item->description);
}
}
}
- uiBlockSetCurLayout(block, layout);
+ UI_block_layout_set_current(block, layout);
if (free) {
MEM_freeN(item_array);
}
+
+ BLI_assert((block->flag & UI_BLOCK_IS_FLIP) == 0);
+ block->flag |= UI_BLOCK_IS_FLIP;
}
/**
@@ -3267,23 +3456,24 @@ static void ui_def_but_rna__menu(bContext *UNUSED(C), uiLayout *layout, void *bu
* When this kind of change won't disrupt branches, best look into making more
* of our UI functions take prop rather then propname.
*/
-static uiBut *ui_def_but_rna(uiBlock *block, int type, int retval, 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)
+static uiBut *ui_def_but_rna(
+ uiBlock *block, int type, int retval, 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)
{
const PropertyType proptype = RNA_property_type(prop);
uiBut *but;
int icon = 0;
uiMenuCreateFunc func = NULL;
- if (ELEM(type, COLOR, HSVCIRCLE, HSVCUBE)) {
+ if (ELEM(type, UI_BTYPE_COLOR, UI_BTYPE_HSVCIRCLE, UI_BTYPE_HSVCUBE)) {
BLI_assert(index == -1);
}
/* use rna values if parameters are not specified */
- if ((proptype == PROP_ENUM) && ELEM(type, MENU, ROW, LISTROW)) {
- /* MENU is handled a little differently here */
+ if ((proptype == PROP_ENUM) && ELEM(type, UI_BTYPE_MENU, UI_BTYPE_ROW, UI_BTYPE_LISTROW)) {
+ /* UI_BTYPE_MENU is handled a little differently here */
EnumPropertyItem *item;
int value;
bool free;
@@ -3291,7 +3481,7 @@ static uiBut *ui_def_but_rna(uiBlock *block, int type, int retval, const char *s
RNA_property_enum_items(block->evil_C, ptr, prop, &item, NULL, &free);
- if (type == MENU) {
+ if (type == UI_BTYPE_MENU) {
value = RNA_property_enum_get(ptr, prop);
}
else {
@@ -3312,7 +3502,7 @@ static uiBut *ui_def_but_rna(uiBlock *block, int type, int retval, const char *s
}
else {
if (!str) {
- if (type == MENU) {
+ if (type == UI_BTYPE_MENU) {
str = "";
}
else {
@@ -3321,7 +3511,7 @@ static uiBut *ui_def_but_rna(uiBlock *block, int type, int retval, const char *s
}
}
- if (type == MENU) {
+ if (type == UI_BTYPE_MENU) {
func = ui_def_but_rna__menu;
}
@@ -3346,7 +3536,7 @@ static uiBut *ui_def_but_rna(uiBlock *block, int type, int retval, const char *s
RNA_property_int_range(ptr, prop, &hardmin, &hardmax);
RNA_property_int_ui_range(ptr, prop, &softmin, &softmax, &step);
- if (!ELEM(type, ROW, LISTROW) && min == max) {
+ if (!ELEM(type, UI_BTYPE_ROW, UI_BTYPE_LISTROW) && min == max) {
min = hardmin;
max = hardmax;
}
@@ -3361,7 +3551,7 @@ static uiBut *ui_def_but_rna(uiBlock *block, int type, int retval, const char *s
RNA_property_float_range(ptr, prop, &hardmin, &hardmax);
RNA_property_float_ui_range(ptr, prop, &softmin, &softmax, &step, &precision);
- if (!ELEM(type, ROW, LISTROW) && min == max) {
+ if (!ELEM(type, UI_BTYPE_ROW, UI_BTYPE_LISTROW) && min == max) {
min = hardmin;
max = hardmax;
}
@@ -3390,27 +3580,23 @@ static uiBut *ui_def_but_rna(uiBlock *block, int type, int retval, const char *s
but->rnaindex = 0;
if (icon) {
- but->icon = (BIFIconID)icon;
- but->flag |= UI_HAS_ICON;
- if (str[0]) {
- but->drawflag |= UI_BUT_ICON_LEFT;
- }
+ ui_def_but_icon(but, icon, UI_HAS_ICON);
}
- if ((type == MENU) && (but->dt == UI_EMBOSSP)) {
- but->flag |= UI_ICON_SUBMENU;
+ if ((type == UI_BTYPE_MENU) && (but->dt == UI_EMBOSS_PULLDOWN)) {
+ but->flag |= UI_BUT_ICON_SUBMENU;
}
if (!RNA_property_editable(&but->rnapoin, prop)) {
ui_def_but_rna__disable(but);
}
- if (but->flag & UI_BUT_UNDO && (ui_is_but_rna_undo(but) == false)) {
+ if (but->flag & UI_BUT_UNDO && (ui_but_is_rna_undo(but) == false)) {
but->flag &= ~UI_BUT_UNDO;
}
/* If this button uses units, calculate the step from this */
- if ((proptype == PROP_FLOAT) && ui_is_but_unit(but)) {
+ if ((proptype == PROP_FLOAT) && ui_but_is_unit(but)) {
but->a1 = ui_get_but_step_unit(but, but->a1);
}
@@ -3457,7 +3643,7 @@ static uiBut *ui_def_but_operator_ptr(uiBlock *block, int type, wmOperatorType *
but = ui_def_but(block, type, -1, str, x, y, width, height, NULL, 0, 0, 0, 0, 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 */
+ but->flag &= ~UI_BUT_UNDO; /* no need for ui_but_is_rna_undo(), we never need undo here */
if (!ot) {
but->flag |= UI_BUT_DISABLED;
@@ -3472,7 +3658,7 @@ uiBut *uiDefBut(uiBlock *block, int type, int retval, const char *str, int x, in
{
uiBut *but = ui_def_but(block, type, retval, str, x, y, width, height, poin, min, max, a1, a2, tip);
- ui_check_but(but);
+ ui_but_update(but);
return but;
}
@@ -3512,7 +3698,7 @@ struct AutoComplete {
const char *startname;
};
-AutoComplete *autocomplete_begin(const char *startname, size_t maxlen)
+AutoComplete *UI_autocomplete_begin(const char *startname, size_t maxlen)
{
AutoComplete *autocpl;
@@ -3525,7 +3711,7 @@ AutoComplete *autocomplete_begin(const char *startname, size_t maxlen)
return autocpl;
}
-void autocomplete_do_name(AutoComplete *autocpl, const char *name)
+void UI_autocomplete_update_name(AutoComplete *autocpl, const char *name)
{
char *truncate = autocpl->truncate;
const char *startname = autocpl->startname;
@@ -3555,7 +3741,7 @@ void autocomplete_do_name(AutoComplete *autocpl, const char *name)
}
}
-int autocomplete_end(AutoComplete *autocpl, char *autoname)
+int UI_autocomplete_end(AutoComplete *autocpl, char *autoname)
{
int match = AUTOCOMPLETE_NO_MATCH;
if (autocpl->truncate[0]) {
@@ -3578,14 +3764,13 @@ int autocomplete_end(AutoComplete *autocpl, char *autoname)
return match;
}
-static void ui_check_but_and_iconize(uiBut *but, int icon)
+static void ui_but_update_and_icon_set(uiBut *but, int icon)
{
if (icon) {
- but->icon = (BIFIconID) icon;
- but->flag |= UI_HAS_ICON;
+ ui_def_but_icon(but, icon, UI_HAS_ICON);
}
- ui_check_but(but);
+ ui_but_update(but);
}
static uiBut *uiDefButBit(uiBlock *block, int type, int bit, 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)
@@ -3634,14 +3819,14 @@ uiBut *uiDefButR(uiBlock *block, int type, int retval, const char *str, int x, i
{
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(but);
+ ui_but_update(but);
return but;
}
uiBut *uiDefButR_prop(uiBlock *block, int type, int retval, 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)
{
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(but);
+ ui_but_update(but);
return but;
}
@@ -3649,7 +3834,7 @@ uiBut *uiDefButO_ptr(uiBlock *block, int type, wmOperatorType *ot, int opcontext
{
uiBut *but;
but = ui_def_but_operator_ptr(block, type, ot, opcontext, str, x, y, width, height, tip);
- ui_check_but(but);
+ ui_but_update(but);
return but;
}
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)
@@ -3663,7 +3848,7 @@ uiBut *uiDefButO(uiBlock *block, int type, const char *opname, int opcontext, co
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)
{
uiBut *but = ui_def_but(block, type, retval, "", x, y, width, height, poin, min, max, a1, a2, tip);
- ui_check_but_and_iconize(but, icon);
+ ui_but_update_and_icon_set(but, icon);
return but;
}
static uiBut *uiDefIconButBit(uiBlock *block, int type, int bit, 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)
@@ -3713,14 +3898,14 @@ uiBut *uiDefIconButR(uiBlock *block, int type, int retval, int icon, int x, int
{
uiBut *but;
but = ui_def_but_rna_propname(block, type, retval, "", x, y, width, height, ptr, propname, index, min, max, a1, a2, tip);
- ui_check_but_and_iconize(but, icon);
+ ui_but_update_and_icon_set(but, icon);
return but;
}
uiBut *uiDefIconButR_prop(uiBlock *block, int type, int retval, int icon, 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)
{
uiBut *but;
but = ui_def_but_rna(block, type, retval, "", x, y, width, height, ptr, prop, index, min, max, a1, a2, tip);
- ui_check_but_and_iconize(but, icon);
+ ui_but_update_and_icon_set(but, icon);
return but;
}
@@ -3728,7 +3913,7 @@ uiBut *uiDefIconButO_ptr(uiBlock *block, int type, wmOperatorType *ot, int opcon
{
uiBut *but;
but = ui_def_but_operator_ptr(block, type, ot, opcontext, "", x, y, width, height, tip);
- ui_check_but_and_iconize(but, icon);
+ ui_but_update_and_icon_set(but, icon);
return but;
}
uiBut *uiDefIconButO(uiBlock *block, int type, const char *opname, int opcontext, int icon, int x, int y, short width, short height, const char *tip)
@@ -3741,7 +3926,7 @@ uiBut *uiDefIconButO(uiBlock *block, int type, const char *opname, int opcontext
uiBut *uiDefIconTextBut(uiBlock *block, int type, 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)
{
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);
+ ui_but_update_and_icon_set(but, icon);
but->drawflag |= UI_BUT_ICON_LEFT;
return but;
}
@@ -3792,7 +3977,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);
+ ui_but_update_and_icon_set(but, icon);
but->drawflag |= UI_BUT_ICON_LEFT;
return but;
}
@@ -3800,7 +3985,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);
+ ui_but_update_and_icon_set(but, icon);
but->drawflag |= UI_BUT_ICON_LEFT;
return but;
}
@@ -3808,7 +3993,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);
+ ui_but_update_and_icon_set(but, icon);
but->drawflag |= UI_BUT_ICON_LEFT;
return but;
}
@@ -3820,7 +4005,7 @@ uiBut *uiDefIconTextButO(uiBlock *block, int type, const char *opname, int opcon
/* END Button containing both string label and icon */
-void uiSetButLink(uiBut *but, void **poin, void ***ppoin, short *tot, int from, int to)
+void UI_but_link_set(uiBut *but, void **poin, void ***ppoin, short *tot, int from, int to)
{
uiLink *link;
@@ -3835,7 +4020,7 @@ void uiSetButLink(uiBut *but, void **poin, void ***ppoin, short *tot, int from,
/* cruft to make uiBlock and uiBut private */
-int uiBlocksGetYMin(ListBase *lb)
+int UI_blocklist_min_y_get(ListBase *lb)
{
uiBlock *block;
int min = 0;
@@ -3847,13 +4032,13 @@ int uiBlocksGetYMin(ListBase *lb)
return min;
}
-void uiBlockSetDirection(uiBlock *block, char direction)
+void UI_block_direction_set(uiBlock *block, char direction)
{
block->direction = direction;
}
/* this call escapes if there's alignment flags */
-void uiBlockFlipOrder(uiBlock *block)
+void UI_block_order_flip(uiBlock *block)
{
uiBut *but;
float centy, miny = 10000, maxy = -10000;
@@ -3875,92 +4060,120 @@ void uiBlockFlipOrder(uiBlock *block)
but->rect.ymax = centy - (but->rect.ymax - centy);
SWAP(float, but->rect.ymin, but->rect.ymax);
}
+
+ block->flag ^= UI_BLOCK_IS_FLIP;
}
-void uiBlockSetFlag(uiBlock *block, int flag)
+void UI_block_flag_enable(uiBlock *block, int flag)
{
block->flag |= flag;
}
-void uiBlockClearFlag(uiBlock *block, int flag)
+void UI_block_flag_disable(uiBlock *block, int flag)
{
block->flag &= ~flag;
}
-void uiButSetFlag(uiBut *but, int flag)
+void UI_but_flag_enable(uiBut *but, int flag)
{
but->flag |= flag;
}
-void uiButClearFlag(uiBut *but, int flag)
+void UI_but_flag_disable(uiBut *but, int flag)
{
but->flag &= ~flag;
}
-void uiButSetDrawFlag(uiBut *but, int flag)
+void UI_but_drawflag_enable(uiBut *but, int flag)
{
but->drawflag |= flag;
}
-void uiButClearDrawFlag(uiBut *but, int flag)
+void UI_but_drawflag_disable(uiBut *but, int flag)
{
but->drawflag &= ~flag;
}
-void uiButSetMenuFromPulldown(uiBut *but)
+void UI_but_type_set_menu_from_pulldown(uiBut *but)
{
- BLI_assert(but->type == PULLDOWN);
- but->type = MENU;
- uiButClearDrawFlag(but, UI_BUT_TEXT_RIGHT);
- uiButSetDrawFlag(but, UI_BUT_TEXT_LEFT);
+ BLI_assert(but->type == UI_BTYPE_PULLDOWN);
+ but->type = UI_BTYPE_MENU;
+ UI_but_drawflag_disable(but, UI_BUT_TEXT_RIGHT);
+ UI_but_drawflag_enable(but, UI_BUT_TEXT_LEFT);
}
-int uiButGetRetVal(uiBut *but)
+int UI_but_return_value_get(uiBut *but)
{
return but->retval;
}
-void uiButSetDragID(uiBut *but, ID *id)
+void UI_but_drag_set_id(uiBut *but, ID *id)
{
but->dragtype = WM_DRAG_ID;
+ if ((but->dragflag & UI_BUT_DRAGPOIN_FREE)) {
+ MEM_SAFE_FREE(but->dragpoin);
+ but->dragflag &= ~UI_BUT_DRAGPOIN_FREE;
+ }
but->dragpoin = (void *)id;
}
-void uiButSetDragRNA(uiBut *but, PointerRNA *ptr)
+void UI_but_drag_set_rna(uiBut *but, PointerRNA *ptr)
{
but->dragtype = WM_DRAG_RNA;
+ if ((but->dragflag & UI_BUT_DRAGPOIN_FREE)) {
+ MEM_SAFE_FREE(but->dragpoin);
+ but->dragflag &= ~UI_BUT_DRAGPOIN_FREE;
+ }
but->dragpoin = (void *)ptr;
}
-void uiButSetDragPath(uiBut *but, const char *path)
+void UI_but_drag_set_path(uiBut *but, const char *path, const bool use_free)
{
but->dragtype = WM_DRAG_PATH;
+ if ((but->dragflag & UI_BUT_DRAGPOIN_FREE)) {
+ MEM_SAFE_FREE(but->dragpoin);
+ but->dragflag &= ~UI_BUT_DRAGPOIN_FREE;
+ }
but->dragpoin = (void *)path;
+ if (use_free) {
+ but->dragflag |= UI_BUT_DRAGPOIN_FREE;
+ }
}
-void uiButSetDragName(uiBut *but, const char *name)
+void UI_but_drag_set_name(uiBut *but, const char *name)
{
but->dragtype = WM_DRAG_NAME;
+ if ((but->dragflag & UI_BUT_DRAGPOIN_FREE)) {
+ MEM_SAFE_FREE(but->dragpoin);
+ but->dragflag &= ~UI_BUT_DRAGPOIN_FREE;
+ }
but->dragpoin = (void *)name;
}
/* value from button itself */
-void uiButSetDragValue(uiBut *but)
+void UI_but_drag_set_value(uiBut *but)
{
but->dragtype = WM_DRAG_VALUE;
}
-void uiButSetDragImage(uiBut *but, const char *path, int icon, struct ImBuf *imb, float scale)
+void UI_but_drag_set_image(uiBut *but, const char *path, int icon, struct ImBuf *imb, float scale, const bool use_free)
{
but->dragtype = WM_DRAG_PATH;
- but->icon = icon; /* no flag UI_HAS_ICON, so icon doesnt draw in button */
+ ui_def_but_icon(but, icon, 0); /* no flag UI_HAS_ICON, so icon doesnt draw in button */
+ if ((but->dragflag & UI_BUT_DRAGPOIN_FREE)) {
+ MEM_SAFE_FREE(but->dragpoin);
+ but->dragflag &= ~UI_BUT_DRAGPOIN_FREE;
+ }
but->dragpoin = (void *)path;
+ if (use_free) {
+ but->dragflag |= UI_BUT_DRAGPOIN_FREE;
+ }
but->imb = imb;
but->imb_scale = scale;
}
-PointerRNA *uiButGetOperatorPtrRNA(uiBut *but)
+PointerRNA *UI_but_operator_ptr_get(uiBut *but)
{
if (but->optype && !but->opptr) {
but->opptr = MEM_callocN(sizeof(PointerRNA), "uiButOpPtr");
@@ -3970,12 +4183,12 @@ PointerRNA *uiButGetOperatorPtrRNA(uiBut *but)
return but->opptr;
}
-void uiButSetUnitType(uiBut *but, const int unit_type)
+void UI_but_unit_type_set(uiBut *but, const int unit_type)
{
but->unit_type = (unsigned char)(RNA_SUBTYPE_UNIT_VALUE(unit_type));
}
-int uiButGetUnitType(const uiBut *but)
+int UI_but_unit_type_get(const uiBut *but)
{
int ownUnit = (int)but->unit_type;
@@ -3991,26 +4204,26 @@ int uiButGetUnitType(const uiBut *but)
}
}
-void uiBlockSetHandleFunc(uiBlock *block, uiBlockHandleFunc func, void *arg)
+void UI_block_func_handle_set(uiBlock *block, uiBlockHandleFunc func, void *arg)
{
block->handle_func = func;
block->handle_func_arg = arg;
}
-void uiBlockSetButmFunc(uiBlock *block, uiMenuHandleFunc func, void *arg)
+void UI_block_func_butmenu_set(uiBlock *block, uiMenuHandleFunc func, void *arg)
{
block->butm_func = func;
block->butm_func_arg = arg;
}
-void uiBlockSetFunc(uiBlock *block, uiButHandleFunc func, void *arg1, void *arg2)
+void UI_block_func_set(uiBlock *block, uiButHandleFunc func, void *arg1, void *arg2)
{
block->func = func;
block->func_arg1 = arg1;
block->func_arg2 = arg2;
}
-void uiBlockSetNFunc(uiBlock *block, uiButHandleNFunc funcN, void *argN, void *arg2)
+void UI_block_funcN_set(uiBlock *block, uiButHandleNFunc funcN, void *argN, void *arg2)
{
if (block->func_argN) {
MEM_freeN(block->func_argN);
@@ -4021,27 +4234,27 @@ void uiBlockSetNFunc(uiBlock *block, uiButHandleNFunc funcN, void *argN, void *a
block->func_arg2 = arg2;
}
-void uiButSetRenameFunc(uiBut *but, uiButHandleRenameFunc func, void *arg1)
+void UI_but_func_rename_set(uiBut *but, uiButHandleRenameFunc func, void *arg1)
{
but->rename_func = func;
but->rename_arg1 = arg1;
}
-void uiBlockSetDrawExtraFunc(uiBlock *block, void (*func)(const bContext *C, void *idv, void *arg1, void *arg2, rcti *rect), void *arg1, void *arg2)
+void UI_but_func_drawextra_set(uiBlock *block, void (*func)(const bContext *C, void *idv, void *arg1, void *arg2, rcti *rect), void *arg1, void *arg2)
{
block->drawextra = func;
block->drawextra_arg1 = arg1;
block->drawextra_arg2 = arg2;
}
-void uiButSetFunc(uiBut *but, uiButHandleFunc func, void *arg1, void *arg2)
+void UI_but_func_set(uiBut *but, uiButHandleFunc func, void *arg1, void *arg2)
{
but->func = func;
but->func_arg1 = arg1;
but->func_arg2 = arg2;
}
-void uiButSetNFunc(uiBut *but, uiButHandleNFunc funcN, void *argN, void *arg2)
+void UI_but_funcN_set(uiBut *but, uiButHandleNFunc funcN, void *argN, void *arg2)
{
if (but->func_argN) {
MEM_freeN(but->func_argN);
@@ -4052,75 +4265,82 @@ void uiButSetNFunc(uiBut *but, uiButHandleNFunc funcN, void *argN, void *arg2)
but->func_arg2 = arg2;
}
-void uiButSetCompleteFunc(uiBut *but, uiButCompleteFunc func, void *arg)
+void UI_but_func_complete_set(uiBut *but, uiButCompleteFunc func, void *arg)
{
but->autocomplete_func = func;
but->autofunc_arg = arg;
}
+void UI_but_func_tooltip_set(uiBut *but, uiButToolTipFunc func, void *argN)
+{
+ but->tip_func = func;
+ if (but->tip_argN) {
+ MEM_freeN(but->tip_argN);
+ }
+ but->tip_argN = argN;
+}
+
uiBut *uiDefBlockBut(uiBlock *block, uiBlockCreateFunc func, void *arg, const char *str, int x, int y, short width, short height, const char *tip)
{
- uiBut *but = ui_def_but(block, BLOCK, 0, str, x, y, width, height, arg, 0.0, 0.0, 0.0, 0.0, tip);
+ uiBut *but = ui_def_but(block, UI_BTYPE_BLOCK, 0, str, x, y, width, height, arg, 0.0, 0.0, 0.0, 0.0, tip);
but->block_create_func = func;
- ui_check_but(but);
+ ui_but_update(but);
return but;
}
uiBut *uiDefBlockButN(uiBlock *block, uiBlockCreateFunc func, void *argN, const char *str, int x, int y, short width, short height, const char *tip)
{
- uiBut *but = ui_def_but(block, BLOCK, 0, str, x, y, width, height, NULL, 0.0, 0.0, 0.0, 0.0, tip);
+ uiBut *but = ui_def_but(block, UI_BTYPE_BLOCK, 0, str, x, y, width, height, NULL, 0.0, 0.0, 0.0, 0.0, tip);
but->block_create_func = func;
if (but->func_argN) {
MEM_freeN(but->func_argN);
}
but->func_argN = argN;
- ui_check_but(but);
+ ui_but_update(but);
return but;
}
uiBut *uiDefPulldownBut(uiBlock *block, uiBlockCreateFunc func, void *arg, const char *str, int x, int y, short width, short height, const char *tip)
{
- uiBut *but = ui_def_but(block, PULLDOWN, 0, str, x, y, width, height, arg, 0.0, 0.0, 0.0, 0.0, tip);
+ uiBut *but = ui_def_but(block, UI_BTYPE_PULLDOWN, 0, str, x, y, width, height, arg, 0.0, 0.0, 0.0, 0.0, tip);
but->block_create_func = func;
- ui_check_but(but);
+ ui_but_update(but);
return but;
}
uiBut *uiDefMenuBut(uiBlock *block, uiMenuCreateFunc func, void *arg, const char *str, int x, int y, short width, short height, const char *tip)
{
- uiBut *but = ui_def_but(block, PULLDOWN, 0, str, x, y, width, height, arg, 0.0, 0.0, 0.0, 0.0, tip);
+ uiBut *but = ui_def_but(block, UI_BTYPE_PULLDOWN, 0, str, x, y, width, height, arg, 0.0, 0.0, 0.0, 0.0, tip);
but->menu_create_func = func;
- ui_check_but(but);
+ ui_but_update(but);
return but;
}
uiBut *uiDefIconTextMenuBut(uiBlock *block, uiMenuCreateFunc func, void *arg, int icon, const char *str, int x, int y, short width, short height, const char *tip)
{
- uiBut *but = ui_def_but(block, PULLDOWN, 0, str, x, y, width, height, arg, 0.0, 0.0, 0.0, 0.0, tip);
+ uiBut *but = ui_def_but(block, UI_BTYPE_PULLDOWN, 0, str, x, y, width, height, arg, 0.0, 0.0, 0.0, 0.0, tip);
- but->icon = (BIFIconID) icon;
- but->flag |= UI_HAS_ICON;
+ ui_def_but_icon(but, icon, UI_HAS_ICON);
but->drawflag |= UI_BUT_ICON_LEFT;
- but->flag |= UI_ICON_SUBMENU;
+ but->flag |= UI_BUT_ICON_SUBMENU;
but->menu_create_func = func;
- ui_check_but(but);
+ ui_but_update(but);
return but;
}
uiBut *uiDefIconMenuBut(uiBlock *block, uiMenuCreateFunc func, void *arg, int icon, int x, int y, short width, short height, const char *tip)
{
- uiBut *but = ui_def_but(block, PULLDOWN, 0, "", x, y, width, height, arg, 0.0, 0.0, 0.0, 0.0, tip);
+ uiBut *but = ui_def_but(block, UI_BTYPE_PULLDOWN, 0, "", x, y, width, height, arg, 0.0, 0.0, 0.0, 0.0, tip);
- but->icon = (BIFIconID) icon;
- but->flag |= UI_HAS_ICON;
+ ui_def_but_icon(but, icon, UI_HAS_ICON);
but->drawflag &= ~UI_BUT_ICON_LEFT;
but->menu_create_func = func;
- ui_check_but(but);
+ ui_but_update(but);
return but;
}
@@ -4128,18 +4348,18 @@ uiBut *uiDefIconMenuBut(uiBlock *block, uiMenuCreateFunc func, void *arg, int ic
/* Block button containing both string label and icon */
uiBut *uiDefIconTextBlockBut(uiBlock *block, uiBlockCreateFunc func, void *arg, int icon, const char *str, int x, int y, short width, short height, const char *tip)
{
- uiBut *but = ui_def_but(block, BLOCK, 0, str, x, y, width, height, arg, 0.0, 0.0, 0.0, 0.0, tip);
+ uiBut *but = ui_def_but(block, UI_BTYPE_BLOCK, 0, str, x, y, width, height, arg, 0.0, 0.0, 0.0, 0.0, tip);
- /* XXX temp, old menu calls pass on icon arrow, which is now UI_ICON_SUBMENU flag */
+ /* XXX temp, old menu calls pass on icon arrow, which is now UI_BUT_ICON_SUBMENU flag */
if (icon != ICON_RIGHTARROW_THIN) {
- but->icon = (BIFIconID) icon;
+ ui_def_but_icon(but, icon, 0);
but->drawflag |= UI_BUT_ICON_LEFT;
}
but->flag |= UI_HAS_ICON;
- but->flag |= UI_ICON_SUBMENU;
+ but->flag |= UI_BUT_ICON_SUBMENU;
but->block_create_func = func;
- ui_check_but(but);
+ ui_but_update(but);
return but;
}
@@ -4147,23 +4367,22 @@ uiBut *uiDefIconTextBlockBut(uiBlock *block, uiBlockCreateFunc func, void *arg,
/* Block button containing icon */
uiBut *uiDefIconBlockBut(uiBlock *block, uiBlockCreateFunc func, void *arg, int retval, int icon, int x, int y, short width, short height, const char *tip)
{
- uiBut *but = ui_def_but(block, BLOCK, retval, "", x, y, width, height, arg, 0.0, 0.0, 0.0, 0.0, tip);
-
- but->icon = (BIFIconID) icon;
- but->flag |= UI_HAS_ICON;
+ uiBut *but = ui_def_but(block, UI_BTYPE_BLOCK, retval, "", x, y, width, height, arg, 0.0, 0.0, 0.0, 0.0, tip);
+ ui_def_but_icon(but, icon, UI_HAS_ICON);
+
but->drawflag |= UI_BUT_ICON_LEFT;
but->block_create_func = func;
- ui_check_but(but);
+ ui_but_update(but);
return but;
}
uiBut *uiDefKeyevtButS(uiBlock *block, int retval, const char *str, int x, int y, short width, short height, short *spoin, const char *tip)
{
- uiBut *but = ui_def_but(block, KEYEVT | UI_BUT_POIN_SHORT, retval, str, x, y, width, height, spoin, 0.0, 0.0, 0.0, 0.0, tip);
- ui_check_but(but);
+ uiBut *but = ui_def_but(block, UI_BTYPE_KEY_EVENT | UI_BUT_POIN_SHORT, retval, str, x, y, width, height, spoin, 0.0, 0.0, 0.0, 0.0, tip);
+ ui_but_update(but);
return but;
}
@@ -4171,44 +4390,46 @@ uiBut *uiDefKeyevtButS(uiBlock *block, int retval, const char *str, int x, int y
/* modkeypoin will be set to KM_SHIFT, KM_ALT, KM_CTRL, KM_OSKEY bits */
uiBut *uiDefHotKeyevtButS(uiBlock *block, int retval, const char *str, int x, int y, short width, short height, short *keypoin, short *modkeypoin, const char *tip)
{
- uiBut *but = ui_def_but(block, HOTKEYEVT | UI_BUT_POIN_SHORT, retval, str, x, y, width, height, keypoin, 0.0, 0.0, 0.0, 0.0, tip);
+ uiBut *but = ui_def_but(block, UI_BTYPE_HOTKEY_EVENT | UI_BUT_POIN_SHORT, retval, str, x, y, width, height, keypoin, 0.0, 0.0, 0.0, 0.0, tip);
but->modifier_key = *modkeypoin;
- ui_check_but(but);
+ ui_but_update(but);
return but;
}
-/* arg is pointer to string/name, use uiButSetSearchFunc() below to make this work */
+/* arg is pointer to string/name, use UI_but_func_search_set() below to make this work */
/* here a1 and a2, if set, control thumbnail preview rows/cols */
uiBut *uiDefSearchBut(uiBlock *block, void *arg, int retval, int icon, int maxlen, int x, int y, short width, short height, float a1, float a2, const char *tip)
{
- uiBut *but = ui_def_but(block, SEARCH_MENU, retval, "", x, y, width, height, arg, 0.0, maxlen, a1, a2, tip);
-
- but->icon = (BIFIconID) icon;
- but->flag |= UI_HAS_ICON;
+ uiBut *but = ui_def_but(block, UI_BTYPE_SEARCH_MENU, retval, "", x, y, width, height, arg, 0.0, maxlen, a1, a2, tip);
+ ui_def_but_icon(but, icon, UI_HAS_ICON);
+
but->drawflag |= UI_BUT_ICON_LEFT | UI_BUT_TEXT_LEFT;
- ui_check_but(but);
+ ui_but_update(but);
return but;
}
-/* arg is user value, searchfunc and handlefunc both get it as arg */
-/* if active set, button opens with this item visible and selected */
-void uiButSetSearchFunc(uiBut *but, uiButSearchFunc sfunc, void *arg, uiButHandleFunc bfunc, void *active)
+/**
+ * \param sfunc, bfunc: both get it as \a arg.
+ * \param arg: user value,
+ * \param active: when set, button opens with this item visible and selected.
+ */
+void UI_but_func_search_set(uiBut *but, uiButSearchFunc sfunc, void *arg, uiButHandleFunc bfunc, void *active)
{
but->search_func = sfunc;
but->search_arg = arg;
- uiButSetFunc(but, bfunc, arg, active);
+ UI_but_func_set(but, bfunc, arg, active);
/* search buttons show red-alert if item doesn't exist, not for menus */
if (0 == (but->block->flag & UI_BLOCK_LOOP)) {
/* skip empty buttons, not all buttons need input, we only show invalid */
if (but->drawstr[0])
- ui_but_search_test(but);
+ ui_but_search_refresh(but);
}
}
@@ -4227,7 +4448,7 @@ static void operator_enum_search_cb(const struct bContext *C, void *but, const c
__func__, ot->idname, RNA_property_identifier(prop));
}
else {
- PointerRNA *ptr = uiButGetOperatorPtrRNA(but); /* Will create it if needed! */
+ PointerRNA *ptr = UI_but_operator_ptr_get(but); /* Will create it if needed! */
EnumPropertyItem *item, *item_array;
bool do_free;
@@ -4236,7 +4457,7 @@ static void operator_enum_search_cb(const struct bContext *C, void *but, const c
for (item = item_array; item->identifier; item++) {
/* note: need to give the index rather than the identifier because the enum can be freed */
if (BLI_strcasestr(item->name, str)) {
- if (false == uiSearchItemAdd(items, item->name, SET_INT_IN_POINTER(item->value), 0))
+ if (false == UI_search_item_add(items, item->name, SET_INT_IN_POINTER(item->value), 0))
break;
}
}
@@ -4249,7 +4470,7 @@ static void operator_enum_search_cb(const struct bContext *C, void *but, const c
static void operator_enum_call_cb(struct bContext *UNUSED(C), void *but, void *arg2)
{
wmOperatorType *ot = ((uiBut *)but)->optype;
- PointerRNA *opptr = uiButGetOperatorPtrRNA(but); /* Will create it if needed! */
+ PointerRNA *opptr = UI_but_operator_ptr_get(but); /* Will create it if needed! */
if (ot) {
if (ot->prop) {
@@ -4265,22 +4486,25 @@ static void operator_enum_call_cb(struct bContext *UNUSED(C), void *but, void *a
}
}
-/* Same parameters as for uiDefSearchBut, with additional operator type and properties, used by callback
- * to call again the right op with the right options (properties values). */
-uiBut *uiDefSearchButO_ptr(uiBlock *block, wmOperatorType *ot, IDProperty *properties,
- void *arg, int retval, int icon, int maxlen, int x, int y,
- short width, short height, float a1, float a2, const char *tip)
+/**
+ * Same parameters as for uiDefSearchBut, with additional operator type and properties, used by callback
+ * to call again the right op with the right options (properties values).
+ */
+uiBut *uiDefSearchButO_ptr(
+ uiBlock *block, wmOperatorType *ot, IDProperty *properties,
+ void *arg, int retval, int icon, int maxlen, int x, int y,
+ short width, short height, float a1, float a2, const char *tip)
{
uiBut *but;
but = uiDefSearchBut(block, arg, retval, icon, maxlen, x, y, width, height, a1, a2, tip);
- uiButSetSearchFunc(but, operator_enum_search_cb, but, operator_enum_call_cb, NULL);
+ UI_but_func_search_set(but, operator_enum_search_cb, but, operator_enum_call_cb, NULL);
but->optype = ot;
but->opcontext = WM_OP_EXEC_DEFAULT;
if (properties) {
- PointerRNA *ptr = uiButGetOperatorPtrRNA(but);
+ PointerRNA *ptr = UI_but_operator_ptr_get(but);
/* Copy idproperties. */
ptr->data = IDP_CopyProperty(properties);
}
@@ -4288,10 +4512,11 @@ uiBut *uiDefSearchButO_ptr(uiBlock *block, wmOperatorType *ot, IDProperty *prope
return but;
}
-/* push a new event onto event queue to activate the given button
+/**
+ * push a new event onto event queue to activate the given button
* (usually a text-field) upon entering a popup
*/
-void uiButSetFocusOnEnter(wmWindow *win, uiBut *but)
+void UI_but_focus_on_enter_event(wmWindow *win, uiBut *but)
{
wmEvent event;
@@ -4305,7 +4530,7 @@ void uiButSetFocusOnEnter(wmWindow *win, uiBut *but)
wm_event_add(win, &event);
}
-void uiButGetStrInfo(bContext *C, uiBut *but, ...)
+void UI_but_string_info_get(bContext *C, uiBut *but, ...)
{
va_list args;
uiStringInfo *si;
@@ -4321,14 +4546,29 @@ void uiButGetStrInfo(bContext *C, uiBut *but, ...)
if (type == BUT_GET_LABEL) {
if (but->str) {
- tmp = BLI_strdup(but->str);
+ const char *str_sep;
+ size_t str_len;
+
+ if ((but->flag & UI_BUT_HAS_SEP_CHAR) &&
+ (str_sep = strrchr(but->str, UI_SEP_CHAR)))
+ {
+ str_len = (str_sep - but->str);
+ }
+ else {
+ str_len = strlen(but->str);
+ }
+
+ tmp = BLI_strdupn(but->str, str_len);
}
else {
type = BUT_GET_RNA_LABEL; /* Fail-safe solution... */
}
}
else if (type == BUT_GET_TIP) {
- if (but->tip && but->tip[0])
+ if (but->tip_func) {
+ tmp = but->tip_func(C, but->tip_argN, but->tip);
+ }
+ else if (but->tip && but->tip[0])
tmp = BLI_strdup(but->tip);
else
type = BUT_GET_RNA_TIP; /* Fail-safe solution... */
@@ -4343,8 +4583,8 @@ void uiButGetStrInfo(bContext *C, uiBut *but, ...)
tmp = BLI_strdup(RNA_struct_identifier(but->rnapoin.type));
else if (but->optype)
tmp = BLI_strdup(but->optype->idname);
- else if (ELEM(but->type, MENU, PULLDOWN)) {
- MenuType *mt = uiButGetMenuType(but);
+ else if (ELEM(but->type, UI_BTYPE_MENU, UI_BTYPE_PULLDOWN)) {
+ MenuType *mt = UI_but_menutype_get(but);
if (mt)
tmp = BLI_strdup(mt->idname);
}
@@ -4368,8 +4608,8 @@ void uiButGetStrInfo(bContext *C, uiBut *but, ...)
tmp = BLI_strdup(t);
}
}
- else if (ELEM(but->type, MENU, PULLDOWN)) {
- MenuType *mt = uiButGetMenuType(but);
+ else if (ELEM(but->type, UI_BTYPE_MENU, UI_BTYPE_PULLDOWN)) {
+ MenuType *mt = UI_but_menutype_get(but);
if (mt) {
/* not all menus are from python */
if (mt->ext.srna) {
@@ -4385,18 +4625,18 @@ void uiButGetStrInfo(bContext *C, uiBut *but, ...)
}
}
else if (type == BUT_GET_RNA_LABEL_CONTEXT) {
- const char *_tmp = BLF_I18NCONTEXT_DEFAULT;
+ const char *_tmp = BLT_I18NCONTEXT_DEFAULT;
if (but->rnaprop)
_tmp = RNA_property_translation_context(but->rnaprop);
else if (but->optype)
_tmp = RNA_struct_translation_context(but->optype->srna);
- else if (ELEM(but->type, MENU, PULLDOWN)) {
- MenuType *mt = uiButGetMenuType(but);
+ else if (ELEM(but->type, UI_BTYPE_MENU, UI_BTYPE_PULLDOWN)) {
+ MenuType *mt = UI_but_menutype_get(but);
if (mt)
_tmp = RNA_struct_translation_context(mt->ext.srna);
}
- if (BLF_is_default_context(_tmp)) {
- _tmp = BLF_I18NCONTEXT_DEFAULT_BPYRNA;
+ if (BLT_is_default_context(_tmp)) {
+ _tmp = BLT_I18NCONTEXT_DEFAULT_BPYRNA;
}
tmp = BLI_strdup(_tmp);
}
@@ -4410,10 +4650,10 @@ void uiButGetStrInfo(bContext *C, uiBut *but, ...)
/* enum property */
ptr = &but->rnapoin;
prop = but->rnaprop;
- value = (but->type == ROW) ? (int)but->hardmax : (int)ui_get_but_val(but);
+ value = (but->type == UI_BTYPE_ROW) ? (int)but->hardmax : (int)ui_but_value_get(but);
}
else if (but->optype) {
- PointerRNA *opptr = uiButGetOperatorPtrRNA(but);
+ PointerRNA *opptr = UI_but_operator_ptr_get(but);
wmOperatorType *ot = but->optype;
/* if the default property of the operator is enum and it is set,
@@ -4498,6 +4738,6 @@ void UI_reinit_font(void)
void UI_exit(void)
{
ui_resources_free();
- ui_button_clipboard_free();
+ ui_but_clipboard_free();
}
diff --git a/source/blender/editors/interface/interface_anim.c b/source/blender/editors/interface/interface_anim.c
index fa0832b6273..37895a711fd 100644
--- a/source/blender/editors/interface/interface_anim.c
+++ b/source/blender/editors/interface/interface_anim.c
@@ -34,15 +34,14 @@
#include "DNA_scene_types.h"
#include "DNA_screen_types.h"
-#include "BLI_listbase.h"
#include "BLI_string.h"
#include "BLI_string_utf8.h"
#include "BLI_utildefines.h"
#include "BKE_context.h"
-#include "BKE_animsys.h"
#include "BKE_fcurve.h"
#include "BKE_global.h"
+#include "BKE_nla.h"
#include "ED_keyframing.h"
@@ -55,28 +54,42 @@
#include "interface_intern.h"
-static FCurve *ui_but_get_fcurve(uiBut *but, bAction **action, bool *r_driven)
+static FCurve *ui_but_get_fcurve(uiBut *but, AnimData **adt, bAction **action, bool *r_driven, bool *r_special)
{
/* for entire array buttons we check the first component, it's not perfect
* but works well enough in typical cases */
int rnaindex = (but->rnaindex == -1) ? 0 : but->rnaindex;
- return rna_get_fcurve(&but->rnapoin, but->rnaprop, rnaindex, action, r_driven);
+ return rna_get_fcurve_context_ui(but->block->evil_C, &but->rnapoin, but->rnaprop, rnaindex, adt, action, r_driven, r_special);
}
void ui_but_anim_flag(uiBut *but, float cfra)
{
+ AnimData *adt;
+ bAction *act;
FCurve *fcu;
bool driven;
-
+ bool special;
+
but->flag &= ~(UI_BUT_ANIMATED | UI_BUT_ANIMATED_KEY | UI_BUT_DRIVEN);
-
- fcu = ui_but_get_fcurve(but, NULL, &driven);
-
+
+ /* NOTE: "special" is reserved for special F-Curves stored on the animation data
+ * itself (which are used to animate properties of the animation data).
+ * We count those as "animated" too for now
+ */
+ fcu = ui_but_get_fcurve(but, &adt, &act, &driven, &special);
+
if (fcu) {
if (!driven) {
but->flag |= UI_BUT_ANIMATED;
+ /* T41525 - When the active action is a NLA strip being edited,
+ * we need to correct the frame number to "look inside" the
+ * remapped action
+ */
+ if (adt)
+ cfra = BKE_nla_tweakedit_remap(adt, cfra, NLATIME_CONVERT_UNMAP);
+
if (fcurve_frame_has_keyframe(fcu, cfra, 0))
but->flag |= UI_BUT_ANIMATED_KEY;
}
@@ -90,10 +103,10 @@ bool ui_but_anim_expression_get(uiBut *but, char *str, size_t maxlen)
{
FCurve *fcu;
ChannelDriver *driver;
- bool driven;
-
- fcu = ui_but_get_fcurve(but, NULL, &driven);
-
+ bool driven, special;
+
+ fcu = ui_but_get_fcurve(but, NULL, NULL, &driven, &special);
+
if (fcu && driven) {
driver = fcu->driver;
@@ -110,9 +123,9 @@ bool ui_but_anim_expression_set(uiBut *but, const char *str)
{
FCurve *fcu;
ChannelDriver *driver;
- bool driven;
+ bool driven, special;
- fcu = ui_but_get_fcurve(but, NULL, &driven);
+ fcu = ui_but_get_fcurve(but, NULL, NULL, &driven, &special);
if (fcu && driven) {
driver = fcu->driver;
@@ -207,10 +220,28 @@ void ui_but_anim_autokey(bContext *C, uiBut *but, Scene *scene, float cfra)
bAction *action;
FCurve *fcu;
bool driven;
+ bool special;
- fcu = ui_but_get_fcurve(but, &action, &driven);
-
- if (fcu && !driven) {
+ fcu = ui_but_get_fcurve(but, NULL, &action, &driven, &special);
+
+ if (fcu == NULL)
+ return;
+
+ if (special) {
+ /* NLA Strip property */
+ if (IS_AUTOKEY_ON(scene)) {
+ ReportList *reports = CTX_wm_reports(C);
+ PointerRNA ptr = {{NULL}};
+ PropertyRNA *prop = NULL;
+ int index;
+
+ UI_context_active_but_prop_get(C, &ptr, &prop, &index);
+
+ insert_keyframe_direct(reports, ptr, prop, fcu, cfra, 0);
+ WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL);
+ }
+ }
+ else if (!driven) {
id = but->rnapoin.id.data;
/* TODO: this should probably respect the keyingset only option for anim */
@@ -219,7 +250,14 @@ void ui_but_anim_autokey(bContext *C, uiBut *but, Scene *scene, float cfra)
short flag = ANIM_get_keyframing_flags(scene, 1);
fcu->flag &= ~FCURVE_SELECTED;
- insert_keyframe(reports, id, action, ((fcu->grp) ? (fcu->grp->name) : (NULL)), fcu->rna_path, fcu->array_index, cfra, flag);
+
+ /* Note: We use but->rnaindex instead of fcu->array_index,
+ * because a button may control all items of an array at once.
+ * E.g., color wheels (see T42567). */
+ BLI_assert((fcu->array_index == but->rnaindex) || (but->rnaindex == -1));
+ insert_keyframe(reports, id, action, ((fcu->grp) ? (fcu->grp->name) : (NULL)),
+ fcu->rna_path, but->rnaindex, cfra, flag);
+
WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL);
}
}
@@ -227,54 +265,54 @@ void ui_but_anim_autokey(bContext *C, uiBut *but, Scene *scene, float cfra)
void ui_but_anim_insert_keyframe(bContext *C)
{
- /* this operator calls uiContextActiveProperty */
+ /* this operator calls UI_context_active_but_prop_get */
WM_operator_name_call(C, "ANIM_OT_keyframe_insert_button", WM_OP_INVOKE_DEFAULT, NULL);
}
void ui_but_anim_delete_keyframe(bContext *C)
{
- /* this operator calls uiContextActiveProperty */
+ /* this operator calls UI_context_active_but_prop_get */
WM_operator_name_call(C, "ANIM_OT_keyframe_delete_button", WM_OP_INVOKE_DEFAULT, NULL);
}
void ui_but_anim_clear_keyframe(bContext *C)
{
- /* this operator calls uiContextActiveProperty */
+ /* this operator calls UI_context_active_but_prop_get */
WM_operator_name_call(C, "ANIM_OT_keyframe_clear_button", WM_OP_INVOKE_DEFAULT, NULL);
}
void ui_but_anim_add_driver(bContext *C)
{
- /* this operator calls uiContextActiveProperty */
+ /* this operator calls UI_context_active_but_prop_get */
WM_operator_name_call(C, "ANIM_OT_driver_button_add", WM_OP_INVOKE_DEFAULT, NULL);
}
void ui_but_anim_remove_driver(bContext *C)
{
- /* this operator calls uiContextActiveProperty */
+ /* this operator calls UI_context_active_but_prop_get */
WM_operator_name_call(C, "ANIM_OT_driver_button_remove", WM_OP_INVOKE_DEFAULT, NULL);
}
void ui_but_anim_copy_driver(bContext *C)
{
- /* this operator calls uiContextActiveProperty */
+ /* this operator calls UI_context_active_but_prop_get */
WM_operator_name_call(C, "ANIM_OT_copy_driver_button", WM_OP_INVOKE_DEFAULT, NULL);
}
void ui_but_anim_paste_driver(bContext *C)
{
- /* this operator calls uiContextActiveProperty */
+ /* this operator calls UI_context_active_but_prop_get */
WM_operator_name_call(C, "ANIM_OT_paste_driver_button", WM_OP_INVOKE_DEFAULT, NULL);
}
void ui_but_anim_add_keyingset(bContext *C)
{
- /* this operator calls uiContextActiveProperty */
+ /* this operator calls UI_context_active_but_prop_get */
WM_operator_name_call(C, "ANIM_OT_keyingset_button_add", WM_OP_INVOKE_DEFAULT, NULL);
}
void ui_but_anim_remove_keyingset(bContext *C)
{
- /* this operator calls uiContextActiveProperty */
+ /* this operator calls UI_context_active_but_prop_get */
WM_operator_name_call(C, "ANIM_OT_keyingset_button_remove", WM_OP_INVOKE_DEFAULT, NULL);
}
diff --git a/source/blender/editors/interface/interface_draw.c b/source/blender/editors/interface/interface_draw.c
index 235d7652539..84767eae350 100644
--- a/source/blender/editors/interface/interface_draw.c
+++ b/source/blender/editors/interface/interface_draw.c
@@ -62,21 +62,21 @@
static int roundboxtype = UI_CNR_ALL;
-void uiSetRoundBox(int type)
+void UI_draw_roundbox_corner_set(int type)
{
/* Not sure the roundbox function is the best place to change this
- * if this is undone, its not that big a deal, only makes curves edges
+ * if this is undone, it's not that big a deal, only makes curves edges
* square for the */
roundboxtype = type;
}
-int uiGetRoundBox(void)
+int UI_draw_roundbox_corner_get(void)
{
return roundboxtype;
}
-void uiDrawBox(int mode, float minx, float miny, float maxx, float maxy, float rad)
+void UI_draw_roundbox_gl_mode(int mode, float minx, float miny, float maxx, float maxy, float rad)
{
float vec[7][2] = {{0.195, 0.02}, {0.383, 0.067}, {0.55, 0.169}, {0.707, 0.293},
{0.831, 0.45}, {0.924, 0.617}, {0.98, 0.805}};
@@ -152,7 +152,9 @@ static void round_box_shade_col(const float col1[3], float const col2[3], const
/* linear horizontal shade within button or in outline */
/* view2d scrollers use it */
-void uiDrawBoxShade(int mode, float minx, float miny, float maxx, float maxy, float rad, float shadetop, float shadedown)
+void UI_draw_roundbox_shade_x(
+ int mode, float minx, float miny, float maxx, float maxy,
+ float rad, float shadetop, float shadedown)
{
float vec[7][2] = {{0.195, 0.02}, {0.383, 0.067}, {0.55, 0.169}, {0.707, 0.293},
{0.831, 0.45}, {0.924, 0.617}, {0.98, 0.805}};
@@ -260,8 +262,9 @@ void uiDrawBoxShade(int mode, float minx, float miny, float maxx, float maxy, fl
/* linear vertical shade within button or in outline */
/* view2d scrollers use it */
-void uiDrawBoxVerticalShade(int mode, float minx, float miny, float maxx, float maxy,
- float rad, float shadeLeft, float shadeRight)
+void UI_draw_roundbox_shade_y(
+ int mode, float minx, float miny, float maxx, float maxy,
+ float rad, float shadeLeft, float shadeRight)
{
float vec[7][2] = {{0.195, 0.02}, {0.383, 0.067}, {0.55, 0.169}, {0.707, 0.293},
{0.831, 0.45}, {0.924, 0.617}, {0.98, 0.805}};
@@ -365,7 +368,7 @@ void uiDrawBoxVerticalShade(int mode, float minx, float miny, float maxx, float
}
/* plain antialiased unfilled rectangle */
-void uiRoundRect(float minx, float miny, float maxx, float maxy, float rad)
+void UI_draw_roundbox_unfilled(float minx, float miny, float maxx, float maxy, float rad)
{
float color[4];
@@ -380,18 +383,24 @@ void uiRoundRect(float minx, float miny, float maxx, float maxy, float rad)
glEnable(GL_LINE_SMOOTH);
glEnable(GL_BLEND);
- uiDrawBox(GL_LINE_LOOP, minx, miny, maxx, maxy, rad);
+ UI_draw_roundbox_gl_mode(GL_LINE_LOOP, minx, miny, maxx, maxy, rad);
glDisable(GL_BLEND);
glDisable(GL_LINE_SMOOTH);
}
/* (old, used in outliner) plain antialiased filled box */
-void uiRoundBox(float minx, float miny, float maxx, float maxy, float rad)
+void UI_draw_roundbox(float minx, float miny, float maxx, float maxy, float rad)
{
ui_draw_anti_roundbox(GL_POLYGON, minx, miny, maxx, maxy, rad, roundboxtype & UI_RB_ALPHA);
}
+void UI_draw_text_underline(int pos_x, int pos_y, int len, int height)
+{
+ int ofs_y = 4 * U.pixelsize;
+ glRecti(pos_x, pos_y - ofs_y, pos_x + len, pos_y - ofs_y + (height * U.pixelsize));
+}
+
/* ************** SPECIAL BUTTON DRAWING FUNCTIONS ************* */
void ui_draw_but_IMAGE(ARegion *UNUSED(ar), uiBut *but, uiWidgetColors *UNUSED(wcol), const rcti *rect)
@@ -441,6 +450,51 @@ void ui_draw_but_IMAGE(ARegion *UNUSED(ar), uiBut *but, uiWidgetColors *UNUSED(w
#endif
}
+/**
+ * Draw title and text safe areas.
+ *
+ * The first 4 parameters are the offsets for the view, not the zones.
+ */
+void UI_draw_safe_areas(
+ float x1, float x2, float y1, float y2,
+ const float title_aspect[2], const float action_aspect[2])
+{
+ const float size_x_half = (x2 - x1) * 0.5f;
+ const float size_y_half = (y2 - y1) * 0.5f;
+
+ const float *safe_areas[] = {title_aspect, action_aspect};
+ int i, safe_len = ARRAY_SIZE(safe_areas);
+ bool is_first = true;
+
+ for (i = 0; i < safe_len; i++) {
+ if (safe_areas[i][0] || safe_areas[i][1]) {
+ float margin_x, margin_y;
+ float minx, miny, maxx, maxy;
+
+ if (is_first) {
+ UI_ThemeColorBlendShade(TH_VIEW_OVERLAY, TH_BACK, 0.25f, 0);
+ is_first = false;
+ }
+
+ margin_x = safe_areas[i][0] * size_x_half;
+ margin_y = safe_areas[i][1] * size_y_half;
+
+ minx = x1 + margin_x;
+ miny = y1 + margin_y;
+ maxx = x2 - margin_x;
+ maxy = y2 - margin_y;
+
+ glBegin(GL_LINE_LOOP);
+ glVertex2f(maxx, miny);
+ glVertex2f(maxx, maxy);
+ glVertex2f(minx, maxy);
+ glVertex2f(minx, miny);
+ glEnd();
+ }
+ }
+}
+
+
static void draw_scope_end(const rctf *rect, GLint *scissor)
{
/* restore scissortest */
@@ -450,12 +504,13 @@ static void draw_scope_end(const rctf *rect, GLint *scissor)
/* outline */
glColor4f(0.f, 0.f, 0.f, 0.5f);
- uiSetRoundBox(UI_CNR_ALL);
- uiDrawBox(GL_LINE_LOOP, rect->xmin - 1, rect->ymin, rect->xmax + 1, rect->ymax + 1, 3.0f);
+ UI_draw_roundbox_corner_set(UI_CNR_ALL);
+ UI_draw_roundbox_gl_mode(GL_LINE_LOOP, rect->xmin - 1, rect->ymin, rect->xmax + 1, rect->ymax + 1, 3.0f);
}
-static void histogram_draw_one(float r, float g, float b, float alpha,
- float x, float y, float w, float h, const float *data, int res, const bool is_line)
+static void histogram_draw_one(
+ float r, float g, float b, float alpha,
+ float x, float y, float w, float h, const float *data, int res, const bool is_line)
{
int i;
@@ -485,7 +540,7 @@ static void histogram_draw_one(float r, float g, float b, float alpha,
glColor4f(r, g, b, alpha);
glShadeModel(GL_FLAT);
- glBegin(GL_QUAD_STRIP);
+ glBegin(GL_TRIANGLE_STRIP);
glVertex2f(x, y);
glVertex2f(x, y + (data[0] * h));
for (i = 1; i < res; i++) {
@@ -533,10 +588,10 @@ void ui_draw_but_HISTOGRAM(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wcol)
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-
- glColor4f(0.f, 0.f, 0.f, 0.3f);
- uiSetRoundBox(UI_CNR_ALL);
- uiDrawBox(GL_POLYGON, rect.xmin - 1, rect.ymin - 1, rect.xmax + 1, rect.ymax + 1, 3.0f);
+
+ UI_ThemeColor4(TH_PREVIEW_BACK);
+ UI_draw_roundbox_corner_set(UI_CNR_ALL);
+ UI_draw_roundbox_gl_mode(GL_POLYGON, rect.xmin - 1, rect.ymin - 1, rect.xmax + 1, rect.ymax + 1, 3.0f);
/* need scissor test, histogram can draw outside of boundary */
glGetIntegerv(GL_VIEWPORT, scissor);
@@ -620,10 +675,10 @@ void ui_draw_but_WAVEFORM(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wcol),
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-
- glColor4f(0.f, 0.f, 0.f, 0.3f);
- uiSetRoundBox(UI_CNR_ALL);
- uiDrawBox(GL_POLYGON, rect.xmin - 1, rect.ymin - 1, rect.xmax + 1, rect.ymax + 1, 3.0f);
+
+ UI_ThemeColor4(TH_PREVIEW_BACK);
+ UI_draw_roundbox_corner_set(UI_CNR_ALL);
+ UI_draw_roundbox_gl_mode(GL_POLYGON, rect.xmin - 1, rect.ymin - 1, rect.xmax + 1, rect.ymax + 1, 3.0f);
/* need scissor test, waveform can draw outside of boundary */
glGetIntegerv(GL_VIEWPORT, scissor);
@@ -768,8 +823,8 @@ static void vectorscope_draw_target(float centerx, float centery, float diam, co
if (u > 0 && v >= 0) tangle = atanf(v / u);
else if (u > 0 && v < 0) tangle = atanf(v / u) + 2.0f * (float)M_PI;
else if (u < 0) tangle = atanf(v / u) + (float)M_PI;
- else if (u == 0 && v > 0.0f) tangle = (float)M_PI / 2.0f;
- else if (u == 0 && v < 0.0f) tangle = -(float)M_PI / 2.0f;
+ else if (u == 0 && v > 0.0f) tangle = M_PI_2;
+ else if (u == 0 && v < 0.0f) tangle = -M_PI_2;
tampli = sqrtf(u * u + v * v);
/* small target vary by 2.5 degree and 2.5 IRE unit */
@@ -839,10 +894,10 @@ void ui_draw_but_VECTORSCOPE(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wco
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-
- glColor4f(0.f, 0.f, 0.f, 0.3f);
- uiSetRoundBox(UI_CNR_ALL);
- uiDrawBox(GL_POLYGON, rect.xmin - 1, rect.ymin - 1, rect.xmax + 1, rect.ymax + 1, 3.0f);
+
+ UI_ThemeColor4(TH_PREVIEW_BACK);
+ UI_draw_roundbox_corner_set(UI_CNR_ALL);
+ UI_draw_roundbox_gl_mode(GL_POLYGON, rect.xmin - 1, rect.ymin - 1, rect.xmax + 1, rect.ymax + 1, 3.0f);
/* need scissor test, hvectorscope can draw outside of boundary */
glGetIntegerv(GL_VIEWPORT, scissor);
@@ -1067,7 +1122,7 @@ void ui_draw_but_COLORBAND(uiBut *but, uiWidgetColors *UNUSED(wcol), const rcti
if (coba == NULL) return;
if (but->block->color_profile)
- display = ui_block_display_get(but->block);
+ display = ui_block_cm_display_get(but->block);
x1 = rect->xmin;
sizex = rect->xmax - x1;
@@ -1093,7 +1148,7 @@ void ui_draw_but_COLORBAND(uiBut *but, uiWidgetColors *UNUSED(wcol), const rcti
v1[1] = y1 + sizey_solid;
v2[1] = rect->ymax;
- glBegin(GL_QUAD_STRIP);
+ glBegin(GL_TRIANGLE_STRIP);
for (a = 0; a <= sizex; a++) {
pos = ((float)a) / sizex;
do_colorband(coba, pos, colf);
@@ -1112,7 +1167,7 @@ void ui_draw_but_COLORBAND(uiBut *but, uiWidgetColors *UNUSED(wcol), const rcti
v1[1] = y1;
v2[1] = y1 + sizey_solid;
- glBegin(GL_QUAD_STRIP);
+ glBegin(GL_TRIANGLE_STRIP);
for (a = 0; a <= sizex; a++) {
pos = ((float)a) / sizex;
do_colorband(coba, pos, colf);
@@ -1158,7 +1213,7 @@ void ui_draw_but_COLORBAND(uiBut *but, uiWidgetColors *UNUSED(wcol), const rcti
}
}
-void ui_draw_but_NORMAL(uiBut *but, uiWidgetColors *wcol, const rcti *rect)
+void ui_draw_but_UNITVEC(uiBut *but, uiWidgetColors *wcol, const rcti *rect)
{
static GLuint displist = 0;
int a, old[8];
@@ -1171,8 +1226,8 @@ void ui_draw_but_NORMAL(uiBut *but, uiWidgetColors *wcol, const rcti *rect)
/* backdrop */
glColor3ubv((unsigned char *)wcol->inner);
- uiSetRoundBox(UI_CNR_ALL);
- uiDrawBox(GL_POLYGON, rect->xmin, rect->ymin, rect->xmax, rect->ymax, 5.0f);
+ UI_draw_roundbox_corner_set(UI_CNR_ALL);
+ UI_draw_roundbox_gl_mode(GL_POLYGON, rect->xmin, rect->ymin, rect->xmax, rect->ymax, 5.0f);
/* sphere color */
glMaterialfv(GL_FRONT, GL_DIFFUSE, diffn);
@@ -1189,7 +1244,7 @@ void ui_draw_but_NORMAL(uiBut *but, uiWidgetColors *wcol, const rcti *rect)
glEnable(GL_LIGHT7);
glEnable(GL_LIGHTING);
- ui_get_but_vectorf(but, dir);
+ ui_but_v3_get(but, dir);
dir[3] = 0.0f; /* glLightfv needs 4 args, 0.0 is sun */
glLightfv(GL_LIGHT7, GL_POSITION, dir);
@@ -1206,8 +1261,8 @@ void ui_draw_but_NORMAL(uiBut *but, uiWidgetColors *wcol, const rcti *rect)
size = BLI_rcti_size_x(rect) / 200.f;
else
size = BLI_rcti_size_y(rect) / 200.f;
-
- glScalef(size, size, size);
+
+ glScalef(size, size, MIN2(size, 1.0f));
if (displist == 0) {
GLUquadricObj *qobj;
@@ -1399,7 +1454,7 @@ void ui_draw_but_CURVE(ARegion *ar, uiBut *but, uiWidgetColors *wcol, const rcti
glEnd();
}
else if (cumap->cur == 3) {
- float lum = rgb_to_bw(cumap->sample);
+ float lum = IMB_colormanagement_get_luminance(cumap->sample);
glColor3ub(240, 240, 240);
glBegin(GL_LINES);
@@ -1511,8 +1566,8 @@ void ui_draw_but_TRACKPREVIEW(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wc
if (scopes->track_disabled) {
glColor4f(0.7f, 0.3f, 0.3f, 0.3f);
- uiSetRoundBox(UI_CNR_ALL);
- uiDrawBox(GL_POLYGON, rect.xmin - 1, rect.ymin, rect.xmax + 1, rect.ymax + 1, 3.0f);
+ UI_draw_roundbox_corner_set(UI_CNR_ALL);
+ UI_draw_roundbox_gl_mode(GL_POLYGON, rect.xmin - 1, rect.ymin, rect.xmax + 1, rect.ymax + 1, 3.0f);
ok = 1;
}
@@ -1559,8 +1614,8 @@ void ui_draw_but_TRACKPREVIEW(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wc
if (scopes->use_track_mask) {
glColor4f(0.0f, 0.0f, 0.0f, 0.3f);
- uiSetRoundBox(UI_CNR_ALL);
- uiDrawBox(GL_POLYGON, rect.xmin - 1, rect.ymin, rect.xmax + 1, rect.ymax + 1, 3.0f);
+ UI_draw_roundbox_corner_set(UI_CNR_ALL);
+ UI_draw_roundbox_gl_mode(GL_POLYGON, rect.xmin - 1, rect.ymin, rect.xmax + 1, rect.ymax + 1, 3.0f);
}
glaDrawPixelsSafe(rect.xmin, rect.ymin + 1, drawibuf->x, drawibuf->y,
@@ -1600,8 +1655,8 @@ void ui_draw_but_TRACKPREVIEW(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wc
if (!ok) {
glColor4f(0.f, 0.f, 0.f, 0.3f);
- uiSetRoundBox(UI_CNR_ALL);
- uiDrawBox(GL_POLYGON, rect.xmin - 1, rect.ymin, rect.xmax + 1, rect.ymax + 1, 3.0f);
+ UI_draw_roundbox_corner_set(UI_CNR_ALL);
+ UI_draw_roundbox_gl_mode(GL_POLYGON, rect.xmin - 1, rect.ymin, rect.xmax + 1, rect.ymax + 1, 3.0f);
}
/* outline */
@@ -1717,7 +1772,7 @@ static void ui_shadowbox(float minx, float miny, float maxx, float maxy, float s
glShadeModel(GL_FLAT);
}
-void uiDrawBoxShadow(unsigned char alpha, float minx, float miny, float maxx, float maxy)
+void UI_draw_box_shadow(unsigned char alpha, float minx, float miny, float maxx, float maxy)
{
/* accumulated outline boxes to make shade not linear, is more pleasant */
ui_shadowbox(minx, miny, maxx, maxy, 11.0, (20 * alpha) >> 8);
@@ -1727,7 +1782,7 @@ void uiDrawBoxShadow(unsigned char alpha, float minx, float miny, float maxx, fl
}
-void ui_dropshadow(const rctf *rct, float radius, float aspect, float alpha, int UNUSED(select))
+void ui_draw_dropshadow(const rctf *rct, float radius, float aspect, float alpha, int UNUSED(select))
{
int i;
float rad;
@@ -1758,13 +1813,13 @@ void ui_dropshadow(const rctf *rct, float radius, float aspect, float alpha, int
glColor4f(0.0f, 0.0f, 0.0f, calpha);
calpha += dalpha;
- uiDrawBox(GL_POLYGON, rct->xmin - a, rct->ymin - a, rct->xmax + a, rct->ymax - 10.0f + a, rad + a);
+ UI_draw_roundbox_gl_mode(GL_POLYGON, rct->xmin - a, rct->ymin - a, rct->xmax + a, rct->ymax - 10.0f + a, rad + a);
}
/* outline emphasis */
glEnable(GL_LINE_SMOOTH);
glColor4ub(0, 0, 0, 100);
- uiDrawBox(GL_LINE_LOOP, rct->xmin - 0.5f, rct->ymin - 0.5f, rct->xmax + 0.5f, rct->ymax + 0.5f, radius + 0.5f);
+ UI_draw_roundbox_gl_mode(GL_LINE_LOOP, rct->xmin - 0.5f, rct->ymin - 0.5f, rct->xmax + 0.5f, rct->ymax + 0.5f, radius + 0.5f);
glDisable(GL_LINE_SMOOTH);
glDisable(GL_BLEND);
diff --git a/source/blender/editors/interface/interface_eyedropper.c b/source/blender/editors/interface/interface_eyedropper.c
index 5b7915e20c5..ceea4ff42d9 100644
--- a/source/blender/editors/interface/interface_eyedropper.c
+++ b/source/blender/editors/interface/interface_eyedropper.c
@@ -36,10 +36,13 @@
#include "BLI_blenlib.h"
#include "BLI_math_vector.h"
+#include "BLT_translation.h"
+
#include "BKE_context.h"
#include "BKE_screen.h"
#include "BKE_report.h"
#include "BKE_idcode.h"
+#include "BKE_unit.h"
#include "RNA_access.h"
@@ -64,6 +67,38 @@
#include "ED_screen.h"
#include "ED_view3d.h"
+/* -------------------------------------------------------------------- */
+/* Utility Functions
+ */
+/** \name Generic Shared Functions
+ * \{ */
+
+static void eyedropper_draw_cursor_text(const struct bContext *C, ARegion *ar, const char *name)
+{
+ const uiFontStyle *fstyle = UI_FSTYLE_WIDGET;
+ wmWindow *win = CTX_wm_window(C);
+ int x = win->eventstate->x;
+ int y = win->eventstate->y;
+ const unsigned char fg[4] = {255, 255, 255, 255};
+ const unsigned char bg[4] = {0, 0, 0, 50};
+
+
+ if ((name[0] == '\0') ||
+ (BLI_rcti_isect_pt(&ar->winrct, x, y) == false))
+ {
+ return;
+ }
+
+ x = x - ar->winrct.xmin;
+ y = y - ar->winrct.ymin;
+
+ y += U.widget_unit;
+
+ UI_fontstyle_draw_simple_backdrop(fstyle, x, y, name, fg, bg);
+}
+
+/** \} */
+
/* -------------------------------------------------------------------- */
/* Eyedropper
@@ -91,7 +126,7 @@ static bool eyedropper_init(bContext *C, wmOperator *op)
op->customdata = eye = MEM_callocN(sizeof(Eyedropper), "Eyedropper");
- uiContextActiveProperty(C, &eye->ptr, &eye->prop, &eye->index);
+ UI_context_active_but_prop_get(C, &eye->ptr, &eye->prop, &eye->index);
if ((eye->ptr.data == NULL) ||
(eye->prop == NULL) ||
@@ -139,43 +174,42 @@ static void eyedropper_color_sample_fl(bContext *C, Eyedropper *UNUSED(eye), int
/* we could use some clever */
wmWindow *win = CTX_wm_window(C);
- ScrArea *sa;
- for (sa = win->screen->areabase.first; sa; sa = sa->next) {
- if (BLI_rcti_isect_pt(&sa->totrct, mx, my)) {
- if (sa->spacetype == SPACE_IMAGE) {
- ARegion *ar = BKE_area_find_region_type(sa, RGN_TYPE_WINDOW);
- if (ar && BLI_rcti_isect_pt(&ar->winrct, mx, my)) {
- SpaceImage *sima = sa->spacedata.first;
- int mval[2] = {mx - ar->winrct.xmin,
- my - ar->winrct.ymin};
-
- if (ED_space_image_color_sample(CTX_data_scene(C), sima, ar, mval, r_col)) {
- return;
- }
+ ScrArea *sa = BKE_screen_find_area_xy(win->screen, SPACE_TYPE_ANY, mx, my);
+
+ if (sa) {
+ if (sa->spacetype == SPACE_IMAGE) {
+ ARegion *ar = BKE_area_find_region_xy(sa, RGN_TYPE_WINDOW, mx, my);
+ if (ar) {
+ SpaceImage *sima = sa->spacedata.first;
+ int mval[2] = {mx - ar->winrct.xmin,
+ my - ar->winrct.ymin};
+
+ if (ED_space_image_color_sample(CTX_data_scene(C), sima, ar, mval, r_col)) {
+ return;
}
}
- else if (sa->spacetype == SPACE_NODE) {
- ARegion *ar = BKE_area_find_region_type(sa, RGN_TYPE_WINDOW);
- if (ar && BLI_rcti_isect_pt(&ar->winrct, mx, my)) {
- SpaceNode *snode = sa->spacedata.first;
- int mval[2] = {mx - ar->winrct.xmin,
- my - ar->winrct.ymin};
-
- if (ED_space_node_color_sample(CTX_data_scene(C), snode, ar, mval, r_col)) {
- return;
- }
+ }
+ else if (sa->spacetype == SPACE_NODE) {
+ ARegion *ar = BKE_area_find_region_xy(sa, RGN_TYPE_WINDOW, mx, my);
+ if (ar) {
+ SpaceNode *snode = sa->spacedata.first;
+ int mval[2] = {mx - ar->winrct.xmin,
+ my - ar->winrct.ymin};
+
+ if (ED_space_node_color_sample(CTX_data_scene(C), snode, ar, mval, r_col)) {
+ return;
}
}
- else if (sa->spacetype == SPACE_CLIP) {
- ARegion *ar = BKE_area_find_region_type(sa, RGN_TYPE_WINDOW);
- if (ar && BLI_rcti_isect_pt(&ar->winrct, mx, my)) {
- SpaceClip *sc = sa->spacedata.first;
- int mval[2] = {mx - ar->winrct.xmin,
- my - ar->winrct.ymin};
-
- if (ED_space_clip_color_sample(CTX_data_scene(C), sc, ar, mval, r_col)) {
- return;
- }
+ }
+ else if (sa->spacetype == SPACE_CLIP) {
+ ARegion *ar = BKE_area_find_region_xy(sa, RGN_TYPE_WINDOW, mx, my);
+ if (ar) {
+ SpaceClip *sc = sa->spacedata.first;
+ int mval[2] = {mx - ar->winrct.xmin,
+ my - ar->winrct.ymin};
+
+ if (ED_space_clip_color_sample(CTX_data_scene(C), sc, ar, mval, r_col)) {
+ return;
}
}
}
@@ -328,7 +362,7 @@ void UI_OT_eyedropper_color(wmOperatorType *ot)
/* identifiers */
ot->name = "Eyedropper";
ot->idname = "UI_OT_eyedropper_color";
- ot->description = "Sample a color from the Blender Window to store in a property";
+ ot->description = "Sample a data-block from the 3D view";
/* api callbacks */
ot->invoke = eyedropper_invoke;
@@ -338,20 +372,20 @@ void UI_OT_eyedropper_color(wmOperatorType *ot)
ot->poll = eyedropper_poll;
/* flags */
- ot->flag = OPTYPE_BLOCKING;
+ ot->flag = OPTYPE_BLOCKING | OPTYPE_INTERNAL;
/* properties */
}
+
/** \} */
/* -------------------------------------------------------------------- */
-/* Data Dropper
- *
- * note: datadropper is only internal name to avoid confusion in this file
- */
+/* Data Dropper */
/** \name Eyedropper (ID data-blocks)
+ *
+ * \note: datadropper is only internal name to avoid confusion in this file.
* \{ */
typedef struct DataDropper {
@@ -369,31 +403,7 @@ typedef struct DataDropper {
static void datadropper_draw_cb(const struct bContext *C, ARegion *ar, void *arg)
{
DataDropper *ddr = arg;
- int width;
- const char *name = ddr->name;
- wmWindow *win = CTX_wm_window(C);
- int x = win->eventstate->x;
- int y = win->eventstate->y;
-
- if ((name[0] == '\0') ||
- (BLI_rcti_isect_pt(&ar->winrct, x, y) == false))
- {
- return;
- }
-
- width = UI_GetStringWidth(name);
- x = x - ar->winrct.xmin;
- y = y - ar->winrct.ymin;
-
- y += 20;
-
- glColor4ub(0, 0, 0, 50);
-
- uiSetRoundBox(UI_CNR_ALL | UI_RB_ALPHA);
- uiRoundBox(x, y, x + width + 8, y + 15, 4);
-
- glColor4ub(255, 255, 255, 255);
- UI_DrawString(x + 4, y + 4, name);
+ eyedropper_draw_cursor_text(C, ar, ddr->name);
}
@@ -411,7 +421,7 @@ static int datadropper_init(bContext *C, wmOperator *op)
op->customdata = ddr = MEM_callocN(sizeof(DataDropper), "DataDropper");
- uiContextActiveProperty(C, &ddr->ptr, &ddr->prop, &index_dummy);
+ UI_context_active_but_prop_get(C, &ddr->ptr, &ddr->prop, &index_dummy);
if ((ddr->ptr.data == NULL) ||
(ddr->prop == NULL) ||
@@ -427,7 +437,8 @@ static int datadropper_init(bContext *C, wmOperator *op)
type = RNA_property_pointer_type(&ddr->ptr, ddr->prop);
ddr->idcode = RNA_type_to_ID_code(type);
BLI_assert(ddr->idcode != 0);
- ddr->idcode_name = BKE_idcode_to_name(ddr->idcode);
+ /* Note we can translate here (instead of on draw time), because this struct has very short lifetime. */
+ ddr->idcode_name = TIP_(BKE_idcode_to_name(ddr->idcode));
return true;
}
@@ -447,6 +458,8 @@ static void datadropper_exit(bContext *C, wmOperator *op)
op->customdata = NULL;
}
+
+ WM_event_add_mousemove(C);
}
static void datadropper_cancel(bContext *C, wmOperator *op)
@@ -464,53 +477,49 @@ static void datadropper_id_sample_pt(bContext *C, DataDropper *ddr, int mx, int
/* we could use some clever */
wmWindow *win = CTX_wm_window(C);
- ScrArea *sa;
+ ScrArea *sa = BKE_screen_find_area_xy(win->screen, -1, mx, my);
ScrArea *area_prev = CTX_wm_area(C);
ARegion *ar_prev = CTX_wm_region(C);
ddr->name[0] = '\0';
- for (sa = win->screen->areabase.first; sa; sa = sa->next) {
- if (BLI_rcti_isect_pt(&sa->totrct, mx, my)) {
- if (sa->spacetype == SPACE_VIEW3D) {
- ARegion *ar = BKE_area_find_region_type(sa, RGN_TYPE_WINDOW);
- if (ar && BLI_rcti_isect_pt(&ar->winrct, mx, my)) {
- const int mval[2] = {
- mx - ar->winrct.xmin,
- my - ar->winrct.ymin};
- Base *base;
-
- CTX_wm_area_set(C, sa);
- CTX_wm_region_set(C, ar);
-
- /* grr, always draw else we leave stale text */
- ED_region_tag_redraw(ar);
-
- base = ED_view3d_give_base_under_cursor(C, mval);
- if (base) {
- Object *ob = base->object;
- ID *id = NULL;
- if (ddr->idcode == ID_OB) {
- id = (ID *)ob;
+ if (sa) {
+ if (sa->spacetype == SPACE_VIEW3D) {
+ ARegion *ar = BKE_area_find_region_xy(sa, RGN_TYPE_WINDOW, mx, my);
+ if (ar) {
+ const int mval[2] = {
+ mx - ar->winrct.xmin,
+ my - ar->winrct.ymin};
+ Base *base;
+
+ CTX_wm_area_set(C, sa);
+ CTX_wm_region_set(C, ar);
+
+ /* grr, always draw else we leave stale text */
+ ED_region_tag_redraw(ar);
+
+ base = ED_view3d_give_base_under_cursor(C, mval);
+ if (base) {
+ Object *ob = base->object;
+ ID *id = NULL;
+ if (ddr->idcode == ID_OB) {
+ id = (ID *)ob;
+ }
+ else if (ob->data) {
+ if (GS(((ID *)ob->data)->name) == ddr->idcode) {
+ id = (ID *)ob->data;
}
- else if (ob->data) {
- if (GS(((ID *)ob->data)->name) == ddr->idcode) {
- id = (ID *)ob->data;
- }
- else {
- BLI_snprintf(ddr->name, sizeof(ddr->name), "Incompatible, expected a %s",
- ddr->idcode_name);
- }
- }
-
- if (id) {
- BLI_snprintf(ddr->name, sizeof(ddr->name), "%s: %s",
- ddr->idcode_name, id->name + 2);
- *r_id = id;
+ else {
+ BLI_snprintf(ddr->name, sizeof(ddr->name), "Incompatible, expected a %s",
+ ddr->idcode_name);
}
+ }
- break;
+ if (id) {
+ BLI_snprintf(ddr->name, sizeof(ddr->name), "%s: %s",
+ ddr->idcode_name, id->name + 2);
+ *r_id = id;
}
}
}
@@ -627,7 +636,7 @@ void UI_OT_eyedropper_id(wmOperatorType *ot)
/* identifiers */
ot->name = "Eyedropper Datablock";
ot->idname = "UI_OT_eyedropper_id";
- ot->description = "Sample a color from the Blender Window to store in a property";
+ ot->description = "Sample a datablock from the Blender Window to store in a property";
/* api callbacks */
ot->invoke = datadropper_invoke;
@@ -637,7 +646,312 @@ void UI_OT_eyedropper_id(wmOperatorType *ot)
ot->poll = datadropper_poll;
/* flags */
- ot->flag = OPTYPE_BLOCKING;
+ ot->flag = OPTYPE_BLOCKING | OPTYPE_INTERNAL;
+
+ /* properties */
+}
+
+/** \} */
+
+
+/* -------------------------------------------------------------------- */
+/* Depth Dropper */
+
+/** \name Eyedropper (Depth)
+ *
+ * \note: depthdropper is only internal name to avoid confusion in this file.
+ * \{ */
+
+typedef struct DepthDropper {
+ PointerRNA ptr;
+ PropertyRNA *prop;
+
+ bool accum_start; /* has mouse been presed */
+ float accum_depth;
+ int accum_tot;
+
+ ARegionType *art;
+ void *draw_handle_pixel;
+ char name[200];
+} DepthDropper;
+
+
+static void depthdropper_draw_cb(const struct bContext *C, ARegion *ar, void *arg)
+{
+ DepthDropper *ddr = arg;
+ eyedropper_draw_cursor_text(C, ar, ddr->name);
+}
+
+
+static int depthdropper_init(bContext *C, wmOperator *op)
+{
+ DepthDropper *ddr;
+ int index_dummy;
+
+ SpaceType *st;
+ ARegionType *art;
+
+ st = BKE_spacetype_from_id(SPACE_VIEW3D);
+ art = BKE_regiontype_from_id(st, RGN_TYPE_WINDOW);
+
+ op->customdata = ddr = MEM_callocN(sizeof(DepthDropper), "DepthDropper");
+
+ UI_context_active_but_prop_get(C, &ddr->ptr, &ddr->prop, &index_dummy);
+
+ /* fallback to the active camera's dof */
+ if (ddr->prop == NULL) {
+ RegionView3D *rv3d = CTX_wm_region_view3d(C);
+ if (rv3d && rv3d->persp == RV3D_CAMOB) {
+ View3D *v3d = CTX_wm_view3d(C);
+ if (v3d->camera && v3d->camera->data && (((ID *)v3d->camera->data)->lib == NULL)) {
+ RNA_id_pointer_create(v3d->camera->data, &ddr->ptr);
+ ddr->prop = RNA_struct_find_property(&ddr->ptr, "dof_distance");
+ }
+ }
+ }
+
+ if ((ddr->ptr.data == NULL) ||
+ (ddr->prop == NULL) ||
+ (RNA_property_editable(&ddr->ptr, ddr->prop) == false) ||
+ (RNA_property_type(ddr->prop) != PROP_FLOAT))
+ {
+ return false;
+ }
+
+ ddr->art = art;
+ ddr->draw_handle_pixel = ED_region_draw_cb_activate(art, depthdropper_draw_cb, ddr, REGION_DRAW_POST_PIXEL);
+
+ return true;
+}
+
+static void depthdropper_exit(bContext *C, wmOperator *op)
+{
+ WM_cursor_modal_restore(CTX_wm_window(C));
+
+ if (op->customdata) {
+ DepthDropper *ddr = (DepthDropper *)op->customdata;
+
+ if (ddr->art) {
+ ED_region_draw_cb_exit(ddr->art, ddr->draw_handle_pixel);
+ }
+
+ MEM_freeN(op->customdata);
+
+ op->customdata = NULL;
+ }
+}
+
+static void depthdropper_cancel(bContext *C, wmOperator *op)
+{
+ depthdropper_exit(C, op);
+}
+
+/* *** depthdropper id helper functions *** */
+/**
+ * \brief get the ID from the screen.
+ *
+ */
+static void depthdropper_depth_sample_pt(bContext *C, DepthDropper *ddr, int mx, int my, float *r_depth)
+{
+
+ /* we could use some clever */
+ wmWindow *win = CTX_wm_window(C);
+ ScrArea *sa = BKE_screen_find_area_xy(win->screen, SPACE_TYPE_ANY, mx, my);
+ Scene *scene = win->screen->scene;
+ UnitSettings *unit = &scene->unit;
+ const bool do_split = (unit->flag & USER_UNIT_OPT_SPLIT) != 0;
+
+ ScrArea *area_prev = CTX_wm_area(C);
+ ARegion *ar_prev = CTX_wm_region(C);
+
+ ddr->name[0] = '\0';
+
+ if (sa) {
+ if (sa->spacetype == SPACE_VIEW3D) {
+ ARegion *ar = BKE_area_find_region_xy(sa, RGN_TYPE_WINDOW, mx, my);
+ if (ar) {
+ View3D *v3d = sa->spacedata.first;
+ RegionView3D *rv3d = ar->regiondata;
+ /* weak, we could pass in some reference point */
+ const float *view_co = v3d->camera ? v3d->camera->obmat[3] : rv3d->viewinv[3];
+ const int mval[2] = {
+ mx - ar->winrct.xmin,
+ my - ar->winrct.ymin};
+ float co[3];
+
+ CTX_wm_area_set(C, sa);
+ CTX_wm_region_set(C, ar);
+
+ /* grr, always draw else we leave stale text */
+ ED_region_tag_redraw(ar);
+
+ view3d_operator_needs_opengl(C);
+
+ if (ED_view3d_autodist(scene, ar, v3d, mval, co, true, NULL)) {
+ const float mval_center_fl[2] = {
+ (float)ar->winx / 2,
+ (float)ar->winy / 2};
+ float co_align[3];
+
+ /* quick way to get view-center aligned point */
+ ED_view3d_win_to_3d(ar, co, mval_center_fl, co_align);
+
+ *r_depth = len_v3v3(view_co, co_align);
+
+ bUnit_AsString(ddr->name, sizeof(ddr->name),
+ (double)*r_depth,
+ 4, unit->system, B_UNIT_LENGTH, do_split, false);
+ }
+ else {
+ BLI_strncpy(ddr->name, "Nothing under cursor", sizeof(ddr->name));
+ }
+ }
+ }
+ }
+
+ CTX_wm_area_set(C, area_prev);
+ CTX_wm_region_set(C, ar_prev);
+}
+
+/* sets the sample depth RGB, maintaining A */
+static void depthdropper_depth_set(bContext *C, DepthDropper *ddr, const float depth)
+{
+ RNA_property_float_set(&ddr->ptr, ddr->prop, depth);
+ RNA_property_update(C, &ddr->ptr, ddr->prop);
+}
+
+/* set sample from accumulated values */
+static void depthdropper_depth_set_accum(bContext *C, DepthDropper *ddr)
+{
+ float depth = ddr->accum_depth;
+ if (ddr->accum_tot) {
+ depth /= (float)ddr->accum_tot;
+ }
+ depthdropper_depth_set(C, ddr, depth);
+}
+
+/* single point sample & set */
+static void depthdropper_depth_sample(bContext *C, DepthDropper *ddr, int mx, int my)
+{
+ float depth = -1.0f;
+ if (depth != -1.0f) {
+ depthdropper_depth_sample_pt(C, ddr, mx, my, &depth);
+ depthdropper_depth_set(C, ddr, depth);
+ }
+}
+
+static void depthdropper_depth_sample_accum(bContext *C, DepthDropper *ddr, int mx, int my)
+{
+ float depth = -1.0f;
+ depthdropper_depth_sample_pt(C, ddr, mx, my, &depth);
+ if (depth != -1.0f) {
+ ddr->accum_depth += depth;
+ ddr->accum_tot++;
+ }
+}
+
+/* main modal status check */
+static int depthdropper_modal(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ DepthDropper *ddr = (DepthDropper *)op->customdata;
+
+ switch (event->type) {
+ case ESCKEY:
+ case RIGHTMOUSE:
+ depthdropper_cancel(C, op);
+ return OPERATOR_CANCELLED;
+ case LEFTMOUSE:
+ if (event->val == KM_RELEASE) {
+ if (ddr->accum_tot == 0) {
+ depthdropper_depth_sample(C, ddr, event->x, event->y);
+ }
+ else {
+ depthdropper_depth_set_accum(C, ddr);
+ }
+ depthdropper_exit(C, op);
+ return OPERATOR_FINISHED;
+ }
+ else if (event->val == KM_PRESS) {
+ /* enable accum and make first sample */
+ ddr->accum_start = true;
+ depthdropper_depth_sample_accum(C, ddr, event->x, event->y);
+ }
+ break;
+ case MOUSEMOVE:
+ if (ddr->accum_start) {
+ /* button is pressed so keep sampling */
+ depthdropper_depth_sample_accum(C, ddr, event->x, event->y);
+ depthdropper_depth_set_accum(C, ddr);
+ }
+ break;
+ case SPACEKEY:
+ if (event->val == KM_RELEASE) {
+ ddr->accum_tot = 0;
+ ddr->accum_depth = 0.0f;
+ depthdropper_depth_sample_accum(C, ddr, event->x, event->y);
+ depthdropper_depth_set_accum(C, ddr);
+ }
+ break;
+ }
+
+ return OPERATOR_RUNNING_MODAL;
+}
+
+/* Modal Operator init */
+static int depthdropper_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
+{
+ /* init */
+ if (depthdropper_init(C, op)) {
+ WM_cursor_modal_set(CTX_wm_window(C), BC_EYEDROPPER_CURSOR);
+
+ /* add temp handler */
+ WM_event_add_modal_handler(C, op);
+
+ return OPERATOR_RUNNING_MODAL;
+ }
+ else {
+ depthdropper_exit(C, op);
+ return OPERATOR_CANCELLED;
+ }
+}
+
+/* Repeat operator */
+static int depthdropper_exec(bContext *C, wmOperator *op)
+{
+ /* init */
+ if (depthdropper_init(C, op)) {
+ /* cleanup */
+ depthdropper_exit(C, op);
+
+ return OPERATOR_FINISHED;
+ }
+ else {
+ return OPERATOR_CANCELLED;
+ }
+}
+
+static int depthdropper_poll(bContext *C)
+{
+ if (!CTX_wm_window(C)) return 0;
+ else return 1;
+}
+
+void UI_OT_eyedropper_depth(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Eyedropper Depth";
+ ot->idname = "UI_OT_eyedropper_depth";
+ ot->description = "Sample depth from the 3D view";
+
+ /* api callbacks */
+ ot->invoke = depthdropper_invoke;
+ ot->modal = depthdropper_modal;
+ ot->cancel = depthdropper_cancel;
+ ot->exec = depthdropper_exec;
+ ot->poll = depthdropper_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_BLOCKING | OPTYPE_INTERNAL;
/* properties */
}
diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c
index d3c9ec1fafb..fe5a5031725 100644
--- a/source/blender/editors/interface/interface_handlers.c
+++ b/source/blender/editors/interface/interface_handlers.c
@@ -52,11 +52,11 @@
#include "BLI_linklist.h"
#include "BLI_string.h"
#include "BLI_string_utf8.h"
+#include "BLI_string_cursor_utf8.h"
#include "BLI_rect.h"
#include "BLI_utildefines.h"
-#include "BLI_string_cursor_utf8.h"
-#include "BLF_translation.h"
+#include "BLT_translation.h"
#include "PIL_time.h"
@@ -87,6 +87,11 @@
#include "WM_api.h"
#include "WM_types.h"
+#ifdef WITH_INPUT_IME
+# include "wm_window.h"
+# include "BLT_lang.h"
+#endif
+
/* place the mouse at the scaled down location when un-grabbing */
#define USE_CONT_MOUSE_CORRECT
/* support dragging toggle buttons */
@@ -95,6 +100,9 @@
/* support dragging multiple number buttons at once */
#define USE_DRAG_MULTINUM
+/* allow dragging/editing all other selected items at once */
+#define USE_ALLSELECT
+
/* so we can avoid very small mouse-moves from jumping away from keyboard navigation [#34936] */
#define USE_KEYNAV_LIMIT
@@ -103,10 +111,14 @@
#define UI_MAX_PASSWORD_STR 128
+/* This hack is needed because we don't have a good way to re-reference keymap items once added: T42944 */
+#define USE_KEYMAP_ADD_HACK
+
/* proto */
-static void ui_add_smart_controller(bContext *C, uiBut *from, uiBut *to);
-static void ui_add_link(bContext *C, uiBut *from, uiBut *to);
+static void ui_but_smart_controller_add(bContext *C, uiBut *from, uiBut *to);
+static void ui_but_link_add(bContext *C, uiBut *from, uiBut *to);
static int ui_do_but_EXIT(bContext *C, uiBut *but, struct uiHandleButtonData *data, const wmEvent *event);
+static bool ui_but_find_select_in_enum__cmp(const uiBut *but_a, const uiBut *but_b);
#ifdef USE_KEYNAV_LIMIT
static void ui_mouse_motion_keynav_init(struct uiKeyNavLock *keynav, const wmEvent *event);
@@ -150,17 +162,63 @@ typedef enum uiHandleButtonState {
} uiHandleButtonState;
+#ifdef USE_ALLSELECT
+
+/* Unfortunately theres no good way handle more generally:
+ * (propagate single clicks on layer buttons to other objects) */
+#define USE_ALLSELECT_LAYER_HACK
+
+typedef struct uiSelectContextElem {
+ PointerRNA ptr;
+ union {
+ bool val_b;
+ int val_i;
+ float val_f;
+ };
+} uiSelectContextElem;
+
+typedef struct uiSelectContextStore {
+ uiSelectContextElem *elems;
+ int elems_len;
+ bool do_free;
+ bool is_enabled;
+ /* When set, simply copy values (don't apply difference).
+ * Rules are:
+ * - dragging numbers uses delta.
+ * - typing in values will assign to all. */
+ bool is_copy;
+} uiSelectContextStore;
+
+static bool ui_selectcontext_begin(
+ bContext *C, uiBut *but, struct uiSelectContextStore *selctx_data);
+static void ui_selectcontext_end(
+ uiBut *but, uiSelectContextStore *selctx_data);
+static void ui_selectcontext_apply(
+ bContext *C, uiBut *but, struct uiSelectContextStore *selctx_data,
+ const double value, const double value_orig);
+
+#define IS_ALLSELECT_EVENT(event) ((event)->alt != 0)
+
+/** just show a tinted color so users know its activated */
+#define UI_BUT_IS_SELECT_CONTEXT UI_BUT_NODE_ACTIVE
+
+#endif /* USE_ALLSELECT */
+
+
#ifdef USE_DRAG_MULTINUM
-/* how far to drag before we check for gesture direction (in pixels),
+/**
+ * how far to drag before we check for gesture direction (in pixels),
* note: half the height of a button is about right... */
#define DRAG_MULTINUM_THRESHOLD_DRAG_X (UI_UNIT_Y / 4)
-/* how far to drag horizontally before we stop checking which buttons the gesture spans (in pixels),
+/**
+ * how far to drag horizontally before we stop checking which buttons the gesture spans (in pixels),
* locking down the buttons so we can drag freely without worrying about vertical movement. */
#define DRAG_MULTINUM_THRESHOLD_DRAG_Y (UI_UNIT_Y / 4)
-/* how strict to be when detecting a vertical gesture, [0.5 == sloppy], [0.9 == strict], (unsigned dot-product)
+/**
+ * how strict to be when detecting a vertical gesture, [0.5 == sloppy], [0.9 == strict], (unsigned dot-product)
* note: we should be quite strict here, since doing a vertical gesture by accident should be avoided,
* however with some care a user should be able to do a vertical movement without *missing*. */
#define DRAG_MULTINUM_THRESHOLD_VERTICAL (0.75f)
@@ -170,6 +228,10 @@ typedef enum uiHandleButtonState {
typedef struct uiButMultiState {
double origvalue;
uiBut *but;
+
+#ifdef USE_ALLSELECT
+ uiSelectContextStore select_others;
+#endif
} uiButMultiState;
typedef struct uiHandleButtonMulti {
@@ -202,8 +264,6 @@ typedef struct uiHandleButtonMulti {
#endif /* USE_DRAG_MULTINUM */
-
-
typedef struct uiHandleButtonData {
wmWindowManager *wm;
wmWindow *window;
@@ -252,16 +312,16 @@ typedef struct uiHandleButtonData {
CBData *dragcbd;
#ifdef USE_CONT_MOUSE_CORRECT
- /* when ungrabbing buttons which are #ui_is_a_warp_but(), we may want to position them
+ /* when ungrabbing buttons which are #ui_but_is_cursor_warp(), we may want to position them
* FLT_MAX signifies do-nothing, use #ui_block_to_window_fl() to get this into a usable space */
float ungrab_mval[2];
#endif
- /* menu open (watch uiFreeActiveButtons) */
+ /* menu open (watch UI_screen_free_active_but) */
uiPopupBlockHandle *menu;
int menuretval;
- /* search box (watch uiFreeActiveButtons) */
+ /* search box (watch UI_screen_free_active_but) */
ARegion *searchbox;
#ifdef USE_KEYNAV_LIMIT
struct uiKeyNavLock searchbox_keynav_state;
@@ -272,6 +332,10 @@ typedef struct uiHandleButtonData {
uiHandleButtonMulti multi_data;
#endif
+#ifdef USE_ALLSELECT
+ uiSelectContextStore select_others;
+#endif
+
/* post activate */
uiButtonActivateType posttype;
uiBut *postbut;
@@ -313,21 +377,21 @@ typedef struct uiAfterFunc {
-static bool ui_is_but_interactive(const uiBut *but, const bool labeledit);
+static bool ui_but_is_interactive(const uiBut *but, const bool labeledit);
static bool ui_but_contains_pt(uiBut *but, float mx, float my);
-static bool ui_mouse_inside_button(ARegion *ar, uiBut *but, int x, int y);
+static bool ui_but_contains_point_px(ARegion *ar, uiBut *but, int x, int y);
static uiBut *ui_but_find_mouse_over_ex(ARegion *ar, const int x, const int y, const bool labeledit);
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 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);
#ifdef USE_DRAG_MULTINUM
-static void ui_multibut_restore(uiHandleButtonData *data, uiBlock *block);
+static void ui_multibut_restore(bContext *C, uiHandleButtonData *data, uiBlock *block);
static uiButMultiState *ui_multibut_lookup(uiHandleButtonData *data, const uiBut *but);
#endif
@@ -348,11 +412,17 @@ static enum eSnapType ui_event_to_snap(const wmEvent *event)
return (event->ctrl) ? (event->shift) ? SNAP_ON_SMALL : SNAP_ON : SNAP_OFF;
}
+static bool ui_event_is_snap(const wmEvent *event)
+{
+ return (ELEM(event->type, LEFTCTRLKEY, RIGHTCTRLKEY) ||
+ ELEM(event->type, LEFTSHIFTKEY, RIGHTSHIFTKEY));
+}
+
static void ui_color_snap_hue(const enum eSnapType snap, float *r_hue)
{
const float snap_increment = (snap == SNAP_ON_SMALL) ? 24 : 12;
BLI_assert(snap != SNAP_OFF);
- *r_hue = floorf(0.5f + ((*r_hue) * snap_increment)) / snap_increment;
+ *r_hue = roundf((*r_hue) * snap_increment) / snap_increment;
}
/* assumes event type is MOUSEPAN */
@@ -390,7 +460,17 @@ void ui_pan_to_scroll(const wmEvent *event, int *type, int *val)
bool ui_but_is_editable(const uiBut *but)
{
- return !ELEM(but->type, LABEL, SEPR, SEPRLINE, ROUNDBOX, LISTBOX, PROGRESSBAR);
+ return !ELEM(but->type,
+ UI_BTYPE_LABEL, UI_BTYPE_SEPR, UI_BTYPE_SEPR_LINE,
+ UI_BTYPE_ROUNDBOX, UI_BTYPE_LISTBOX, UI_BTYPE_PROGRESS_BAR);
+}
+
+bool ui_but_is_editable_as_text(const uiBut *but)
+{
+ return ELEM(but->type,
+ UI_BTYPE_TEXT, UI_BTYPE_NUM, UI_BTYPE_NUM_SLIDER,
+ UI_BTYPE_SEARCH_MENU);
+
}
static uiBut *ui_but_prev(uiBut *but)
@@ -435,10 +515,13 @@ static uiBut *ui_but_last(uiBlock *block)
return NULL;
}
-static bool ui_is_a_warp_but(uiBut *but)
+static bool ui_but_is_cursor_warp(uiBut *but)
{
if (U.uiflag & USER_CONTINUOUS_MOUSE) {
- if (ELEM(but->type, NUM, NUMSLI, HSVCIRCLE, TRACKPREVIEW, HSVCUBE, BUT_CURVE)) {
+ if (ELEM(but->type,
+ UI_BTYPE_NUM, UI_BTYPE_NUM_SLIDER, UI_BTYPE_HSVCIRCLE,
+ UI_BTYPE_TRACK_PREVIEW, UI_BTYPE_HSVCUBE, UI_BTYPE_CURVE))
+ {
return true;
}
}
@@ -451,10 +534,9 @@ static float ui_mouse_scale_warp_factor(const bool shift)
return shift ? 0.05f : 1.0f;
}
-static void ui_mouse_scale_warp(uiHandleButtonData *data,
- const float mx, const float my,
- float *r_mx, float *r_my,
- const bool shift)
+static void ui_mouse_scale_warp(
+ uiHandleButtonData *data, const float mx, const float my,
+ float *r_mx, float *r_my, const bool shift)
{
const float fac = ui_mouse_scale_warp_factor(shift);
@@ -464,7 +546,7 @@ static void ui_mouse_scale_warp(uiHandleButtonData *data,
}
/* file selectors are exempt from utf-8 checks */
-bool ui_is_but_utf8(const uiBut *but)
+bool ui_but_is_utf8(const uiBut *but)
{
if (but->rnaprop) {
const int subtype = RNA_property_subtype(but->rnaprop);
@@ -523,7 +605,7 @@ static void ui_apply_but_func(bContext *C, uiBut *but)
* with these functions removing the buttons we are working with */
if (but->func || but->funcN || block->handle_func || but->rename_func ||
- (but->type == BUTM && block->butm_func) || but->optype || but->rnaprop)
+ (but->type == UI_BTYPE_BUT_MENU && block->butm_func) || but->optype || but->rnaprop)
{
after = ui_afterfunc_new();
@@ -548,7 +630,7 @@ static void ui_apply_but_func(bContext *C, uiBut *but)
after->handle_func_arg = block->handle_func_arg;
after->retval = but->retval;
- if (but->type == BUTM) {
+ if (but->type == UI_BTYPE_BUT_MENU) {
after->butm_func = block->butm_func;
after->butm_func_arg = block->butm_func_arg;
after->a2 = but->a2;
@@ -570,8 +652,8 @@ static void ui_apply_but_func(bContext *C, uiBut *but)
}
}
-/* typically call ui_apply_undo(), ui_apply_autokey() */
-static void ui_apply_undo(uiBut *but)
+/* typically call ui_apply_but_undo(), ui_apply_but_autokey() */
+static void ui_apply_but_undo(uiBut *but)
{
uiAfterFunc *after;
@@ -579,8 +661,8 @@ static void ui_apply_undo(uiBut *but)
const char *str = NULL;
/* define which string to use for undo */
- if (ELEM(but->type, LINK, INLINK)) str = "Add button link";
- else if (but->type == MENU) str = but->drawstr;
+ if (ELEM(but->type, UI_BTYPE_LINK, UI_BTYPE_INLINK)) str = "Add button link";
+ else if (but->type == UI_BTYPE_MENU) str = but->drawstr;
else if (but->drawstr[0]) str = but->drawstr;
else str = but->tip;
@@ -595,7 +677,7 @@ static void ui_apply_undo(uiBut *but)
}
}
-static void ui_apply_autokey(bContext *C, uiBut *but)
+static void ui_apply_but_autokey(bContext *C, uiBut *but)
{
Scene *scene = CTX_data_scene(C);
@@ -689,7 +771,7 @@ static void ui_apply_but_BUT(bContext *C, uiBut *but, uiHandleButtonData *data)
static void ui_apply_but_BUTM(bContext *C, uiBut *but, uiHandleButtonData *data)
{
- ui_set_but_val(but, but->hardmin);
+ ui_but_value_set(but, but->hardmin);
ui_apply_but_func(C, but);
data->retval = but->retval;
@@ -698,10 +780,10 @@ static void ui_apply_but_BUTM(bContext *C, uiBut *but, uiHandleButtonData *data)
static void ui_apply_but_BLOCK(bContext *C, uiBut *but, uiHandleButtonData *data)
{
- if (but->type == MENU)
- ui_set_but_val(but, data->value);
+ if (but->type == UI_BTYPE_MENU)
+ ui_but_value_set(but, data->value);
- ui_check_but(but);
+ ui_but_update(but);
ui_apply_but_func(C, but);
data->retval = but->retval;
data->applied = true;
@@ -712,7 +794,7 @@ static void ui_apply_but_TOG(bContext *C, uiBut *but, uiHandleButtonData *data)
double value;
int w, lvalue, push;
- value = ui_get_but_val(but);
+ value = ui_but_value_get(but);
lvalue = (int)value;
if (but->bit) {
@@ -720,17 +802,17 @@ static void ui_apply_but_TOG(bContext *C, uiBut *but, uiHandleButtonData *data)
if (w) lvalue = UI_BITBUT_CLR(lvalue, but->bitnr);
else lvalue = UI_BITBUT_SET(lvalue, but->bitnr);
- ui_set_but_val(but, (double)lvalue);
- if (but->type == ICONTOG || but->type == ICONTOGN) ui_check_but(but);
+ ui_but_value_set(but, (double)lvalue);
+ if (but->type == UI_BTYPE_ICON_TOGGLE || but->type == UI_BTYPE_ICON_TOGGLE_N) ui_but_update(but);
}
else {
if (value == 0.0) push = 1;
else push = 0;
- if (ELEM(but->type, TOGN, ICONTOGN, OPTIONN)) push = !push;
- ui_set_but_val(but, (double)push);
- if (but->type == ICONTOG || but->type == ICONTOGN) ui_check_but(but);
+ if (ELEM(but->type, UI_BTYPE_TOGGLE_N, UI_BTYPE_ICON_TOGGLE_N, UI_BTYPE_CHECKBOX_N)) push = !push;
+ ui_but_value_set(but, (double)push);
+ if (but->type == UI_BTYPE_ICON_TOGGLE || but->type == UI_BTYPE_ICON_TOGGLE_N) ui_but_update(but);
}
ui_apply_but_func(C, but);
@@ -743,14 +825,14 @@ static void ui_apply_but_ROW(bContext *C, uiBlock *block, uiBut *but, uiHandleBu
{
uiBut *bt;
- ui_set_but_val(but, but->hardmax);
+ ui_but_value_set(but, but->hardmax);
ui_apply_but_func(C, but);
/* states of other row buttons */
for (bt = block->buttons.first; bt; bt = bt->next)
- if (bt != but && bt->poin == but->poin && ELEM(bt->type, ROW, LISTROW))
- ui_check_but(bt);
+ if (bt != but && bt->poin == but->poin && ELEM(bt->type, UI_BTYPE_ROW, UI_BTYPE_LISTROW))
+ ui_but_update(bt);
data->retval = but->retval;
data->applied = true;
@@ -761,14 +843,21 @@ static void ui_apply_but_TEX(bContext *C, uiBut *but, uiHandleButtonData *data)
if (!data->str)
return;
- ui_set_but_string(C, but, data->str);
- ui_check_but(but);
+ ui_but_string_set(C, but, data->str);
+ ui_but_update(but);
- /* give butfunc the original text too */
- /* feature used for bone renaming, channels, etc */
- /* afterfunc frees origstr */
- but->rename_orig = data->origstr;
- data->origstr = NULL;
+ /* give butfunc a copy of the original text too.
+ * feature used for bone renaming, channels, etc.
+ * afterfunc frees rename_orig */
+ if (data->origstr && (but->flag & UI_BUT_TEXTEDIT_UPDATE)) {
+ /* In this case, we need to keep origstr available, to restore real org string in case we cancel after
+ * having typed something already. */
+ but->rename_orig = BLI_strdup(data->origstr);
+ }
+ else {
+ but->rename_orig = data->origstr;
+ data->origstr = NULL;
+ }
ui_apply_but_func(C, but);
data->retval = but->retval;
@@ -778,8 +867,8 @@ static void ui_apply_but_TEX(bContext *C, uiBut *but, uiHandleButtonData *data)
static void ui_apply_but_NUM(bContext *C, uiBut *but, uiHandleButtonData *data)
{
if (data->str) {
- if (ui_set_but_string(C, but, data->str)) {
- data->value = ui_get_but_val(but);
+ if (ui_but_string_set(C, but, data->str)) {
+ data->value = ui_but_value_get(but);
}
else {
data->cancel = true;
@@ -787,9 +876,9 @@ static void ui_apply_but_NUM(bContext *C, uiBut *but, uiHandleButtonData *data)
}
}
else
- ui_set_but_val(but, data->value);
+ ui_but_value_set(but, data->value);
- ui_check_but(but);
+ ui_but_update(but);
ui_apply_but_func(C, but);
data->retval = but->retval;
@@ -798,8 +887,8 @@ static void ui_apply_but_NUM(bContext *C, uiBut *but, uiHandleButtonData *data)
static void ui_apply_but_VEC(bContext *C, uiBut *but, uiHandleButtonData *data)
{
- ui_set_but_vectorf(but, data->vec);
- ui_check_but(but);
+ ui_but_v3_set(but, data->vec);
+ ui_but_update(but);
ui_apply_but_func(C, but);
data->retval = but->retval;
@@ -836,7 +925,7 @@ static void ui_multibut_add(uiHandleButtonData *data, uiBut *but)
mbut_state = MEM_callocN(sizeof(*mbut_state), __func__);
mbut_state->but = but;
- mbut_state->origvalue = ui_get_but_val(but);
+ mbut_state->origvalue = ui_but_value_get(but);
BLI_linklist_prepend(&data->multi_data.mbuts, mbut_state);
@@ -860,7 +949,7 @@ static uiButMultiState *ui_multibut_lookup(uiHandleButtonData *data, const uiBut
return NULL;
}
-static void ui_multibut_restore(uiHandleButtonData *data, uiBlock *block)
+static void ui_multibut_restore(bContext *C, uiHandleButtonData *data, uiBlock *block)
{
uiBut *but;
@@ -868,7 +957,17 @@ static void ui_multibut_restore(uiHandleButtonData *data, uiBlock *block)
if (but->flag & UI_BUT_DRAG_MULTI) {
uiButMultiState *mbut_state = ui_multibut_lookup(data, but);
if (mbut_state) {
- ui_set_but_val(but, mbut_state->origvalue);
+ ui_but_value_set(but, mbut_state->origvalue);
+
+#ifdef USE_ALLSELECT
+ if (mbut_state->select_others.elems_len > 0) {
+ ui_selectcontext_apply(
+ C, but, &mbut_state->select_others,
+ mbut_state->origvalue, mbut_state->origvalue);
+ }
+#else
+ UNUSED_VARS(C);
+#endif
}
}
}
@@ -876,7 +975,26 @@ static void ui_multibut_restore(uiHandleButtonData *data, uiBlock *block)
static void ui_multibut_free(uiHandleButtonData *data, uiBlock *block)
{
+#ifdef USE_ALLSELECT
+ if (data->multi_data.mbuts) {
+ LinkNode *list = data->multi_data.mbuts;
+ while (list) {
+ LinkNode *next = list->next;
+ uiButMultiState *mbut_state = list->link;
+
+ if (mbut_state->select_others.elems) {
+ MEM_freeN(mbut_state->select_others.elems);
+ }
+
+ MEM_freeN(list->link);
+ MEM_freeN(list);
+ list = next;
+ }
+ }
+#else
BLI_linklist_freeN(data->multi_data.mbuts);
+#endif
+
data->multi_data.mbuts = NULL;
if (data->multi_data.bs_mbuts) {
@@ -915,11 +1033,11 @@ static bool ui_multibut_states_tag(uiBut *but_active, uiHandleButtonData *data,
drag_prev = true;
}
- if (ui_is_but_interactive(but, false)) {
+ if (ui_but_is_interactive(but, false)) {
/* drag checks */
if (but_active != but) {
- if (ui_is_but_compatible(but_active, but)) {
+ if (ui_but_is_compatible(but_active, but)) {
BLI_assert(but->active == NULL);
@@ -945,6 +1063,7 @@ static void ui_multibut_states_create(uiBut *but_active, uiHandleButtonData *dat
uiBut *but;
BLI_assert(data->multi_data.init == BUTTON_MULTI_INIT_SETUP);
+ BLI_assert(data->multi_data.has_mbuts);
data->multi_data.bs_mbuts = UI_butstore_create(but_active->block);
@@ -981,13 +1100,31 @@ static void ui_multibut_states_apply(bContext *C, uiHandleButtonData *data, uiBl
if (mbut_state) {
void *active_back;
- ui_button_execute_begin(C, ar, but, &active_back);
+ ui_but_execute_begin(C, ar, but, &active_back);
+
+#ifdef USE_ALLSELECT
+ if (data->select_others.is_enabled) {
+ /* init once! */
+ if (mbut_state->select_others.elems_len == 0) {
+ ui_selectcontext_begin(C, but, &mbut_state->select_others);
+ }
+ if (mbut_state->select_others.elems_len == 0) {
+ mbut_state->select_others.elems_len = -1;
+ }
+ }
+
+ /* needed so we apply the right deltas */
+ but->active->origvalue = mbut_state->origvalue;
+ but->active->select_others = mbut_state->select_others;
+ but->active->select_others.do_free = false;
+#endif
+
BLI_assert(active_back == NULL);
/* no need to check 'data->state' here */
if (data->str) {
/* entering text (set all) */
but->active->value = data->value;
- ui_set_but_string(C, but, data->str);
+ ui_but_string_set(C, but, data->str);
}
else {
/* dragging (use delta) */
@@ -1001,7 +1138,7 @@ static void ui_multibut_states_apply(bContext *C, uiHandleButtonData *data, uiBl
/* clamp based on soft limits, see: T40154 */
CLAMP(but->active->value, (double)but->softmin, (double)but->softmax);
}
- ui_button_execute_end(C, ar, but, active_back);
+ ui_but_execute_end(C, ar, but, active_back);
}
else {
/* highly unlikely */
@@ -1030,8 +1167,9 @@ typedef struct uiDragToggleHandle {
int xy_last[2];
} uiDragToggleHandle;
-static bool ui_drag_toggle_set_xy_xy(bContext *C, ARegion *ar, const bool is_set, const eButType but_type_start,
- const int xy_src[2], const int xy_dst[2])
+static bool ui_drag_toggle_set_xy_xy(
+ bContext *C, ARegion *ar, const bool is_set, const eButType but_type_start,
+ const int xy_src[2], const int xy_dst[2])
{
/* popups such as layers won't re-evaluate on redraw */
const bool do_check = (ar->regiontype == RGN_TYPE_TEMPORARY);
@@ -1050,18 +1188,18 @@ static bool ui_drag_toggle_set_xy_xy(bContext *C, ARegion *ar, const bool is_set
for (but = block->buttons.first; but; but = but->next) {
/* 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 (ui_but_is_interactive(but, true)) {
if (BLI_rctf_isect_segment(&but->rect, xy_a_block, xy_b_block)) {
/* execute the button */
- if (ui_is_but_bool(but) && but->type == but_type_start) {
+ if (ui_but_is_bool(but) && but->type == but_type_start) {
/* is it pressed? */
- bool is_set_but = ui_is_but_push(but);
- BLI_assert(ui_is_but_bool(but) == true);
+ bool is_set_but = ui_but_is_pushed(but);
+ BLI_assert(ui_but_is_bool(but) == true);
if (is_set_but != is_set) {
- uiButExecute(C, but);
+ UI_but_execute(C, but);
if (do_check) {
- ui_check_but(but);
+ ui_but_update(but);
}
changed = true;
}
@@ -1164,7 +1302,7 @@ static int ui_handler_region_drag_toggle(bContext *C, const wmEvent *event, void
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);
+ ui_apply_but_undo(but);
}
WM_event_remove_ui_handler(&win->modalhandlers,
@@ -1181,9 +1319,9 @@ static int ui_handler_region_drag_toggle(bContext *C, const wmEvent *event, void
}
}
-static bool ui_is_but_drag_toggle(const uiBut *but)
+static bool ui_but_is_drag_toggle(const uiBut *but)
{
- return ((ui_is_but_bool(but) == true) &&
+ return ((ui_but_is_bool(but) == true) &&
/* menu check is importnt so the button dragged over isn't removed instantly */
(ui_block_is_menu(but->block) == false));
}
@@ -1191,7 +1329,268 @@ static bool ui_is_but_drag_toggle(const uiBut *but)
#endif /* USE_DRAG_TOGGLE */
-static bool ui_but_mouse_inside_icon(uiBut *but, ARegion *ar, const wmEvent *event)
+#ifdef USE_ALLSELECT
+
+static bool ui_selectcontext_begin(
+ bContext *C, uiBut *but, uiSelectContextStore *selctx_data)
+{
+ PointerRNA ptr, lptr, idptr;
+ PropertyRNA *prop, *lprop;
+ bool success = false;
+ int index;
+
+ char *path = NULL;
+ ListBase lb = {NULL};
+
+ ptr = but->rnapoin;
+ prop = but->rnaprop;
+ index = but->rnaindex;
+
+ /* for now don't support whole colors */
+ if (index == -1)
+ return false;
+
+ /* if there is a valid property that is editable... */
+ if (ptr.data && prop) {
+ CollectionPointerLink *link;
+ bool use_path_from_id;
+ int i;
+
+ /* some facts we want to know */
+ const bool is_array = RNA_property_array_check(prop);
+ const int rna_type = RNA_property_type(prop);
+
+ if (!UI_context_copy_to_selected_list(C, &ptr, prop, &lb, &use_path_from_id, &path)) {
+ goto finally;
+ }
+
+ selctx_data->elems_len = BLI_listbase_count(&lb);
+ if (selctx_data->elems_len == 0) {
+ goto finally;
+ }
+
+ selctx_data->elems = MEM_mallocN(sizeof(uiSelectContextElem) * selctx_data->elems_len, __func__);
+
+ for (i = 0, link = lb.first; i < selctx_data->elems_len; i++, link = link->next) {
+ uiSelectContextElem *other = &selctx_data->elems[i];
+ /* TODO,. de-duplicate copy_to_selected_button */
+ if (link->ptr.data != ptr.data) {
+ if (use_path_from_id) {
+ /* Path relative to ID. */
+ lprop = NULL;
+ RNA_id_pointer_create(link->ptr.id.data, &idptr);
+ RNA_path_resolve_property(&idptr, path, &lptr, &lprop);
+ }
+ else if (path) {
+ /* Path relative to elements from list. */
+ lprop = NULL;
+ RNA_path_resolve_property(&link->ptr, path, &lptr, &lprop);
+ }
+ else {
+ lptr = link->ptr;
+ lprop = prop;
+ }
+
+ /* lptr might not be the same as link->ptr! */
+ if ((lptr.data != ptr.data) &&
+ (lprop == prop) &&
+ RNA_property_editable(&lptr, lprop))
+ {
+ other->ptr = lptr;
+ if (is_array) {
+ if (rna_type == PROP_FLOAT) {
+ other->val_f = RNA_property_float_get_index(&lptr, lprop, index);
+ }
+ else if (rna_type == PROP_INT) {
+ other->val_i = RNA_property_int_get_index(&lptr, lprop, index);
+ }
+ /* ignored for now */
+#if 0
+ else if (rna_type == PROP_BOOLEAN) {
+ other->val_b = RNA_property_boolean_get_index(&lptr, lprop, index);
+ }
+#endif
+ }
+ else {
+ if (rna_type == PROP_FLOAT) {
+ other->val_f = RNA_property_float_get(&lptr, lprop);
+ }
+ else if (rna_type == PROP_INT) {
+ other->val_i = RNA_property_int_get(&lptr, lprop);
+ }
+ /* ignored for now */
+#if 0
+ else if (rna_type == PROP_BOOLEAN) {
+ other->val_b = RNA_property_boolean_get(&lptr, lprop);
+ }
+ else if (rna_type == PROP_ENUM) {
+ other->val_i = RNA_property_enum_get(&lptr, lprop);
+ }
+#endif
+ }
+
+ continue;
+ }
+ }
+
+ selctx_data->elems_len -= 1;
+ i -= 1;
+ }
+ }
+
+ success = (selctx_data->elems_len != 0);
+
+finally:
+ if (selctx_data->elems_len == 0) {
+ MEM_SAFE_FREE(selctx_data->elems);
+ }
+
+ MEM_SAFE_FREE(path);
+ BLI_freelistN(&lb);
+
+ /* caller can clear */
+ selctx_data->do_free = true;
+
+ if (success) {
+ but->flag |= UI_BUT_IS_SELECT_CONTEXT;
+ }
+
+ return success;
+}
+
+static void ui_selectcontext_end(
+ uiBut *but, uiSelectContextStore *selctx_data)
+{
+ if (selctx_data->do_free) {
+ if (selctx_data->elems) {
+ MEM_freeN(selctx_data->elems);
+ }
+ }
+
+ but->flag &= ~UI_BUT_IS_SELECT_CONTEXT;
+}
+
+static void ui_selectcontext_apply(
+ bContext *C, uiBut *but, uiSelectContextStore *selctx_data,
+ const double value, const double value_orig)
+{
+ if (selctx_data->elems) {
+ PropertyRNA *prop = but->rnaprop;
+ PropertyRNA *lprop = but->rnaprop;
+ int index = but->rnaindex;
+ int i;
+ const bool use_delta = (selctx_data->is_copy == false);
+
+ union {
+ bool b;
+ int i;
+ float f;
+ } delta, min, max;
+
+ const bool is_array = RNA_property_array_check(prop);
+ const int rna_type = RNA_property_type(prop);
+
+ if (rna_type == PROP_FLOAT) {
+ delta.f = use_delta ? (value - value_orig) : value;
+ RNA_property_float_range(&but->rnapoin, prop, &min.f, &max.f);
+ }
+ else if (rna_type == PROP_INT) {
+ delta.i = use_delta ? ((int)value - (int)value_orig) : (int)value;
+ RNA_property_int_range(&but->rnapoin, prop, &min.i, &max.i);
+ }
+ else if (rna_type == PROP_ENUM) {
+ delta.i = RNA_property_enum_get(&but->rnapoin, prop); /* not a delta infact */
+ }
+ else if (rna_type == PROP_BOOLEAN) {
+ if (is_array) {
+ delta.b = RNA_property_boolean_get_index(&but->rnapoin, prop, index); /* not a delta infact */
+ }
+ else {
+ delta.b = RNA_property_boolean_get(&but->rnapoin, prop); /* not a delta infact */
+ }
+ }
+
+#ifdef USE_ALLSELECT_LAYER_HACK
+ /* make up for not having 'handle_layer_buttons' */
+ {
+ PropertySubType subtype = RNA_property_subtype(prop);
+
+ if ((rna_type == PROP_BOOLEAN) &&
+ ELEM(subtype, PROP_LAYER, PROP_LAYER_MEMBER) &&
+ is_array &&
+ /* could check for 'handle_layer_buttons' */
+ but->func)
+ {
+ wmWindow *win = CTX_wm_window(C);
+ if (!win->eventstate->shift) {
+ const int len = RNA_property_array_length(&but->rnapoin, prop);
+ int *tmparray = MEM_callocN(sizeof(int) * len, __func__);
+
+ tmparray[index] = true;
+
+ for (i = 0; i < selctx_data->elems_len; i++) {
+ uiSelectContextElem *other = &selctx_data->elems[i];
+ PointerRNA lptr = other->ptr;
+ RNA_property_boolean_set_array(&lptr, lprop, tmparray);
+ RNA_property_update(C, &lptr, lprop);
+ }
+
+ MEM_freeN(tmparray);
+
+ return;
+ }
+ }
+ }
+#endif
+
+ for (i = 0; i < selctx_data->elems_len; i++) {
+ uiSelectContextElem *other = &selctx_data->elems[i];
+ PointerRNA lptr = other->ptr;
+
+ if (rna_type == PROP_FLOAT) {
+ float other_value = use_delta ? (other->val_f + delta.f) : delta.f;
+ CLAMP(other_value, min.f, max.f);
+ if (is_array) {
+ RNA_property_float_set_index(&lptr, lprop, index, other_value);
+ }
+ else {
+ RNA_property_float_set(&lptr, lprop, other_value);
+ }
+ }
+ else if (rna_type == PROP_INT) {
+ int other_value = use_delta ? (other->val_i + delta.i) : delta.i;
+ CLAMP(other_value, min.i, max.i);
+ if (is_array) {
+ RNA_property_int_set_index(&lptr, lprop, index, other_value);
+ }
+ else {
+ RNA_property_int_set(&lptr, lprop, other_value);
+ }
+ }
+ else if (rna_type == PROP_BOOLEAN) {
+ const bool other_value = delta.b;
+ if (is_array) {
+ RNA_property_boolean_set_index(&lptr, lprop, index, other_value);
+ }
+ else {
+ RNA_property_boolean_set(&lptr, lprop, delta.b);
+ }
+ }
+ else if (rna_type == PROP_ENUM) {
+ const int other_value = delta.i;
+ BLI_assert(!is_array);
+ RNA_property_enum_set(&lptr, lprop, other_value);
+ }
+
+ RNA_property_update(C, &lptr, prop);
+ }
+ }
+}
+
+#endif /* USE_ALLSELECT */
+
+
+static bool ui_but_contains_point_px_icon(uiBut *but, ARegion *ar, const wmEvent *event)
{
rcti rect;
int x = event->x, y = event->y;
@@ -1200,7 +1599,7 @@ static bool ui_but_mouse_inside_icon(uiBut *but, ARegion *ar, const wmEvent *eve
BLI_rcti_rctf_copy(&rect, &but->rect);
- if (but->imb || but->type == COLOR) {
+ if (but->imb || but->type == UI_BTYPE_COLOR) {
/* use button size itself */
}
else if (but->drawflag & UI_BUT_ICON_LEFT) {
@@ -1215,7 +1614,7 @@ static bool ui_but_mouse_inside_icon(uiBut *but, ARegion *ar, const wmEvent *eve
return BLI_rcti_isect_pt(&rect, x, y);
}
-static bool ui_but_start_drag(bContext *C, uiBut *but, uiHandleButtonData *data, const wmEvent *event)
+static bool ui_but_drag_init(bContext *C, uiBut *but, uiHandleButtonData *data, const wmEvent *event)
{
/* prevent other WM gestures to start while we try to drag */
WM_gestures_remove(C);
@@ -1225,15 +1624,15 @@ static bool ui_but_start_drag(bContext *C, uiBut *but, uiHandleButtonData *data,
button_activate_state(C, but, BUTTON_STATE_EXIT);
data->cancel = true;
#ifdef USE_DRAG_TOGGLE
- if (ui_is_but_bool(but)) {
+ if (ui_but_is_bool(but)) {
uiDragToggleHandle *drag_info = MEM_callocN(sizeof(*drag_info), __func__);
ARegion *ar_prev;
/* call here because regular mouse-up event wont run,
* typically 'button_activate_exit()' handles this */
- ui_apply_autokey(C, but);
+ ui_apply_but_autokey(C, but);
- drag_info->is_set = ui_is_but_push(but);
+ drag_info->is_set = ui_but_is_pushed(but);
drag_info->but_cent_start[0] = BLI_rctf_cent_x(&but->rect);
drag_info->but_cent_start[1] = BLI_rctf_cent_y(&but->rect);
drag_info->but_type_start = but->type;
@@ -1244,16 +1643,17 @@ static bool ui_but_start_drag(bContext *C, uiBut *but, uiHandleButtonData *data,
ar_prev = CTX_wm_region(C);
CTX_wm_region_set(C, data->region);
- WM_event_add_ui_handler(C, &data->window->modalhandlers,
- ui_handler_region_drag_toggle,
- ui_handler_region_drag_toggle_remove,
- drag_info, false);
+ WM_event_add_ui_handler(
+ C, &data->window->modalhandlers,
+ ui_handler_region_drag_toggle,
+ ui_handler_region_drag_toggle_remove,
+ drag_info, WM_HANDLER_BLOCKING);
CTX_wm_region_set(C, ar_prev);
}
else
#endif
- if (but->type == COLOR) {
+ if (but->type == UI_BTYPE_COLOR) {
bool valid = false;
uiDragColorHandle *drag_info = MEM_callocN(sizeof(*drag_info), __func__);
@@ -1288,7 +1688,7 @@ static bool ui_but_start_drag(bContext *C, uiBut *but, uiHandleButtonData *data,
else {
wmDrag *drag;
- drag = WM_event_start_drag(C, but->icon, but->dragtype, but->dragpoin, ui_get_but_val(but), WM_DRAG_NOP);
+ drag = WM_event_start_drag(C, but->icon, but->dragtype, but->dragpoin, ui_but_value_get(but), WM_DRAG_NOP);
if (but->imb)
WM_event_drag_image(drag, but->imb, but->imb_scale, BLI_rctf_size_x(&but->rect), BLI_rctf_size_y(&but->rect));
}
@@ -1300,7 +1700,7 @@ static bool ui_but_start_drag(bContext *C, uiBut *but, uiHandleButtonData *data,
/* ********************** linklines *********************** */
-static void ui_delete_active_linkline(uiBlock *block)
+static void ui_linkline_remove_active(uiBlock *block)
{
uiBut *but;
uiLink *link;
@@ -1308,7 +1708,7 @@ static void ui_delete_active_linkline(uiBlock *block)
int a, b;
for (but = block->buttons.first; but; but = but->next) {
- if (but->type == LINK && but->link) {
+ if (but->type == UI_BTYPE_LINK && but->link) {
for (line = but->link->lines.first; line; line = nline) {
nline = line->next;
@@ -1349,7 +1749,7 @@ static void ui_delete_active_linkline(uiBlock *block)
}
-static uiLinkLine *ui_is_a_link(uiBut *from, uiBut *to)
+static uiLinkLine *ui_but_find_link(uiBut *from, uiBut *to)
{
uiLinkLine *line;
uiLink *link;
@@ -1367,7 +1767,7 @@ static uiLinkLine *ui_is_a_link(uiBut *from, uiBut *to)
/* XXX BAD BAD HACK, fixme later **************** */
/* Try to add an AND Controller between the sensor and the actuator logic bricks and to connect them all */
-static void ui_add_smart_controller(bContext *C, uiBut *from, uiBut *to)
+static void ui_but_smart_controller_add(bContext *C, uiBut *from, uiBut *to)
{
Object *ob = NULL;
bSensor *sens_iter;
@@ -1422,15 +1822,15 @@ static void ui_add_smart_controller(bContext *C, uiBut *from, uiBut *to)
/* (4) link the sensor->controller->actuator */
tmp_but = MEM_callocN(sizeof(uiBut), "uiBut");
- uiSetButLink(tmp_but, (void **)&cont, (void ***)&(cont->links), &(cont->totlinks), from->link->tocode, (int)to->hardmin);
+ UI_but_link_set(tmp_but, (void **)&cont, (void ***)&(cont->links), &(cont->totlinks), from->link->tocode, (int)to->hardmin);
tmp_but->hardmin = from->link->tocode;
tmp_but->poin = (char *)cont;
- tmp_but->type = INLINK;
- ui_add_link(C, from, tmp_but);
+ tmp_but->type = UI_BTYPE_INLINK;
+ ui_but_link_add(C, from, tmp_but);
- tmp_but->type = LINK;
- ui_add_link(C, tmp_but, to);
+ tmp_but->type = UI_BTYPE_LINK;
+ ui_but_link_add(C, tmp_but, to);
/* (5) garbage collection */
MEM_freeN(tmp_but->link);
@@ -1439,7 +1839,7 @@ static void ui_add_smart_controller(bContext *C, uiBut *from, uiBut *to)
WM_operator_properties_free(&props_ptr);
}
-static void ui_add_link(bContext *C, uiBut *from, uiBut *to)
+static void ui_but_link_add(bContext *C, uiBut *from, uiBut *to)
{
/* in 'from' we have to add a link to 'to' */
uiLink *link;
@@ -1447,22 +1847,22 @@ static void ui_add_link(bContext *C, uiBut *from, uiBut *to)
void **oldppoin;
int a;
- if ((line = ui_is_a_link(from, to))) {
+ if ((line = ui_but_find_link(from, to))) {
line->flag |= UI_SELECT;
- ui_delete_active_linkline(from->block);
+ ui_linkline_remove_active(from->block);
return;
}
- if (from->type == INLINK && to->type == INLINK) {
+ if (from->type == UI_BTYPE_INLINK && to->type == UI_BTYPE_INLINK) {
return;
}
- else if (from->type == LINK && to->type == INLINK) {
+ else if (from->type == UI_BTYPE_LINK && to->type == UI_BTYPE_INLINK) {
if (from->link->tocode != (int)to->hardmin) {
- ui_add_smart_controller(C, from, to);
+ ui_but_smart_controller_add(C, from, to);
return;
}
}
- else if (from->type == INLINK && to->type == LINK) {
+ else if (from->type == UI_BTYPE_INLINK && to->type == UI_BTYPE_LINK) {
if (to->link->tocode == (int)from->hardmin) {
return;
}
@@ -1497,15 +1897,15 @@ static void ui_apply_but_LINK(bContext *C, uiBut *but, uiHandleButtonData *data)
uiBut *bt;
for (bt = but->block->buttons.first; bt; bt = bt->next) {
- if (ui_mouse_inside_button(ar, bt, but->linkto[0] + ar->winrct.xmin, but->linkto[1] + ar->winrct.ymin) )
+ if (ui_but_contains_point_px(ar, bt, but->linkto[0] + ar->winrct.xmin, but->linkto[1] + ar->winrct.ymin) )
break;
}
if (bt && bt != but) {
- if (!ELEM(bt->type, LINK, INLINK) || !ELEM(but->type, LINK, INLINK))
+ if (!ELEM(bt->type, UI_BTYPE_LINK, UI_BTYPE_INLINK) || !ELEM(but->type, UI_BTYPE_LINK, UI_BTYPE_INLINK))
return;
- if (but->type == LINK) ui_add_link(C, but, bt);
- else ui_add_link(C, bt, but);
+ if (but->type == UI_BTYPE_LINK) ui_but_link_add(C, but, bt);
+ else ui_but_link_add(C, bt, but);
ui_apply_but_func(C, but);
data->retval = but->retval;
@@ -1542,7 +1942,7 @@ static void ui_apply_but_TRACKPREVIEW(bContext *C, uiBut *but, uiHandleButtonDat
}
-static void ui_apply_button(bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, const bool interactive)
+static void ui_apply_but(bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, const bool interactive)
{
char *editstr;
double *editval;
@@ -1562,9 +1962,8 @@ static void ui_apply_button(bContext *C, uiBlock *block, uiBut *but, uiHandleBut
data->str = data->origstr;
data->origstr = NULL;
data->value = data->origvalue;
- data->origvalue = 0.0;
copy_v3_v3(data->vec, data->origvec);
- data->origvec[0] = data->origvec[1] = data->origvec[2] = 0.0f;
+ /* postpone clearing origdata */
}
else {
/* we avoid applying interactive edits a second time
@@ -1575,6 +1974,27 @@ static void ui_apply_button(bContext *C, uiBlock *block, uiBut *but, uiHandleBut
else if (data->applied_interactive) {
return;
}
+
+#ifdef USE_ALLSELECT
+# ifdef USE_DRAG_MULTINUM
+ if (but->flag & UI_BUT_DRAG_MULTI) {
+ /* pass */
+ }
+ else
+# endif
+ if (data->select_others.elems_len == 0) {
+ wmWindow *win = CTX_wm_window(C);
+ /* may have been enabled before activating */
+ if (data->select_others.is_enabled || IS_ALLSELECT_EVENT(win->eventstate)) {
+ ui_selectcontext_begin(C, but, &data->select_others);
+ data->select_others.is_enabled = true;
+ }
+ }
+ if (data->select_others.elems_len == 0) {
+ /* dont check again */
+ data->select_others.elems_len = -1;
+ }
+#endif
}
/* ensures we are writing actual values */
@@ -1591,76 +2011,75 @@ static void ui_apply_button(bContext *C, uiBlock *block, uiBut *but, uiHandleBut
/* handle different types */
switch (but->type) {
- case BUT:
+ case UI_BTYPE_BUT:
ui_apply_but_BUT(C, but, data);
break;
- case TEX:
- case SEARCH_MENU_UNLINK:
- case SEARCH_MENU:
+ case UI_BTYPE_TEXT:
+ case UI_BTYPE_SEARCH_MENU:
ui_apply_but_TEX(C, but, data);
break;
- case TOGBUT:
- case TOG:
- case ICONTOG:
- case ICONTOGN:
- case TOGN:
- case OPTION:
- case OPTIONN:
+ case UI_BTYPE_BUT_TOGGLE:
+ case UI_BTYPE_TOGGLE:
+ case UI_BTYPE_TOGGLE_N:
+ case UI_BTYPE_ICON_TOGGLE:
+ case UI_BTYPE_ICON_TOGGLE_N:
+ case UI_BTYPE_CHECKBOX:
+ case UI_BTYPE_CHECKBOX_N:
ui_apply_but_TOG(C, but, data);
break;
- case ROW:
- case LISTROW:
+ case UI_BTYPE_ROW:
+ case UI_BTYPE_LISTROW:
ui_apply_but_ROW(C, block, but, data);
break;
- case SCROLL:
- case GRIP:
- case NUM:
- case NUMSLI:
+ case UI_BTYPE_SCROLL:
+ case UI_BTYPE_GRIP:
+ case UI_BTYPE_NUM:
+ case UI_BTYPE_NUM_SLIDER:
ui_apply_but_NUM(C, but, data);
break;
- case MENU:
- case BLOCK:
- case PULLDOWN:
+ case UI_BTYPE_MENU:
+ case UI_BTYPE_BLOCK:
+ case UI_BTYPE_PULLDOWN:
ui_apply_but_BLOCK(C, but, data);
break;
- case COLOR:
+ case UI_BTYPE_COLOR:
if (data->cancel)
ui_apply_but_VEC(C, but, data);
else
ui_apply_but_BLOCK(C, but, data);
break;
- case BUTM:
+ case UI_BTYPE_BUT_MENU:
ui_apply_but_BUTM(C, but, data);
break;
- case BUT_NORMAL:
- case HSVCUBE:
- case HSVCIRCLE:
+ case UI_BTYPE_UNITVEC:
+ case UI_BTYPE_HSVCUBE:
+ case UI_BTYPE_HSVCIRCLE:
ui_apply_but_VEC(C, but, data);
break;
- case BUT_COLORBAND:
+ case UI_BTYPE_COLORBAND:
ui_apply_but_COLORBAND(C, but, data);
break;
- case BUT_CURVE:
+ case UI_BTYPE_CURVE:
ui_apply_but_CURVE(C, but, data);
break;
- case KEYEVT:
- case HOTKEYEVT:
+ case UI_BTYPE_KEY_EVENT:
+ case UI_BTYPE_HOTKEY_EVENT:
ui_apply_but_BUT(C, but, data);
break;
- case LINK:
- case INLINK:
+ case UI_BTYPE_LINK:
+ case UI_BTYPE_INLINK:
ui_apply_but_LINK(C, but, data);
break;
- case BUT_IMAGE:
+ case UI_BTYPE_IMAGE:
ui_apply_but_IMAGE(C, but, data);
break;
- case HISTOGRAM:
+ case UI_BTYPE_HISTOGRAM:
ui_apply_but_HISTOGRAM(C, but, data);
break;
- case WAVEFORM:
+ case UI_BTYPE_WAVEFORM:
ui_apply_but_WAVEFORM(C, but, data);
break;
- case TRACKPREVIEW:
+ case UI_BTYPE_TRACK_PREVIEW:
ui_apply_but_TRACKPREVIEW(C, but, data);
break;
default:
@@ -1671,7 +2090,7 @@ static void ui_apply_button(bContext *C, uiBlock *block, uiBut *but, uiHandleBut
if (data->multi_data.has_mbuts) {
if (data->multi_data.init == BUTTON_MULTI_INIT_ENABLE) {
if (data->cancel) {
- ui_multibut_restore(data, block);
+ ui_multibut_restore(C, data, block);
}
else {
ui_multibut_states_apply(C, data, block);
@@ -1680,6 +2099,15 @@ static void ui_apply_button(bContext *C, uiBlock *block, uiBut *but, uiHandleBut
}
#endif
+#ifdef USE_ALLSELECT
+ ui_selectcontext_apply(C, but, &data->select_others, data->value, data->origvalue);
+#endif
+
+ if (data->cancel) {
+ data->origvalue = 0.0;
+ zero_v3(data->origvec);
+ }
+
but->editstr = editstr;
but->editval = editval;
but->editvec = editvec;
@@ -1698,13 +2126,13 @@ static void ui_but_drop(bContext *C, const wmEvent *event, uiBut *but, uiHandleB
for (wmd = drags->first; wmd; wmd = wmd->next) {
if (wmd->type == WM_DRAG_ID) {
/* align these types with UI_but_active_drop_name */
- if (ELEM(but->type, TEX, SEARCH_MENU, SEARCH_MENU_UNLINK)) {
+ if (ELEM(but->type, UI_BTYPE_TEXT, UI_BTYPE_SEARCH_MENU)) {
ID *id = (ID *)wmd->poin;
button_activate_state(C, but, BUTTON_STATE_TEXT_EDITING);
BLI_strncpy(data->str, id->name + 2, data->maxlen);
- if (ELEM(but->type, SEARCH_MENU, SEARCH_MENU_UNLINK)) {
+ if (ELEM(but->type, UI_BTYPE_SEARCH_MENU)) {
but->changed = true;
ui_searchbox_update(C, data->searchbox, but, true);
}
@@ -1751,7 +2179,7 @@ static void ui_but_copy_paste(bContext *C, uiBut *but, uiHandleButtonData *data,
/* numeric value */
- if (ELEM(but->type, NUM, NUMSLI)) {
+ if (ELEM(but->type, UI_BTYPE_NUM, UI_BTYPE_NUM_SLIDER)) {
if (but->poin == NULL && but->rnapoin.data == NULL) {
/* pass */
@@ -1760,7 +2188,7 @@ static void ui_but_copy_paste(bContext *C, uiBut *but, uiHandleButtonData *data,
/* Get many decimal places, then strip trailing zeros.
* note: too high values start to give strange results (6 or so is ok) */
char buf_copy[UI_MAX_DRAW_STR];
- ui_get_but_string_ex(but, buf_copy, sizeof(buf_copy), 6);
+ ui_but_string_get_ex(but, buf_copy, sizeof(buf_copy), 6);
BLI_str_rstrip_float_zero(buf_copy, '\0');
WM_clipboard_text_set(buf_copy, 0);
@@ -1768,17 +2196,17 @@ static void ui_but_copy_paste(bContext *C, uiBut *but, uiHandleButtonData *data,
else {
double val;
- if (ui_set_but_string_eval_num(C, but, buf_paste, &val)) {
+ if (ui_but_string_set_eval_num(C, but, buf_paste, &val)) {
button_activate_state(C, but, BUTTON_STATE_NUM_EDITING);
data->value = val;
- ui_set_but_string(C, but, buf_paste);
+ ui_but_string_set(C, but, buf_paste);
button_activate_state(C, but, BUTTON_STATE_EXIT);
}
}
}
/* NORMAL button */
- else if (but->type == BUT_NORMAL) {
+ else if (but->type == UI_BTYPE_UNITVEC) {
float xyz[3];
if (but->poin == NULL && but->rnapoin.data == NULL) {
@@ -1786,7 +2214,7 @@ static void ui_but_copy_paste(bContext *C, uiBut *but, uiHandleButtonData *data,
}
else if (mode == 'c') {
char buf_copy[UI_MAX_DRAW_STR];
- ui_get_but_vectorf(but, xyz);
+ ui_but_v3_get(but, xyz);
BLI_snprintf(buf_copy, sizeof(buf_copy), "[%f, %f, %f]", xyz[0], xyz[1], xyz[2]);
WM_clipboard_text_set(buf_copy, 0);
}
@@ -1797,7 +2225,7 @@ static void ui_but_copy_paste(bContext *C, uiBut *but, uiHandleButtonData *data,
xyz[2] = 1.0;
}
button_activate_state(C, but, BUTTON_STATE_NUM_EDITING);
- ui_set_but_vectorf(but, xyz);
+ ui_but_v3_set(but, xyz);
button_activate_state(C, but, BUTTON_STATE_EXIT);
}
}
@@ -1805,7 +2233,7 @@ static void ui_but_copy_paste(bContext *C, uiBut *but, uiHandleButtonData *data,
/* RGB triple */
- else if (but->type == COLOR) {
+ else if (but->type == UI_BTYPE_COLOR) {
float rgba[4];
if (but->poin == NULL && but->rnapoin.data == NULL) {
@@ -1819,7 +2247,7 @@ static void ui_but_copy_paste(bContext *C, uiBut *but, uiHandleButtonData *data,
else
rgba[3] = 1.0f;
- ui_get_but_vectorf(but, rgba);
+ ui_but_v3_get(but, rgba);
/* convert to linear color to do compatible copy between gamma and non-gamma */
if (but->rnaprop && RNA_property_subtype(but->rnaprop) == PROP_COLOR_GAMMA)
srgb_to_linearrgb_v3_v3(rgba, rgba);
@@ -1835,7 +2263,7 @@ static void ui_but_copy_paste(bContext *C, uiBut *but, uiHandleButtonData *data,
linearrgb_to_srgb_v3_v3(rgba, rgba);
button_activate_state(C, but, BUTTON_STATE_NUM_EDITING);
- ui_set_but_vectorf(but, rgba);
+ ui_but_v3_set(but, rgba);
if (but->rnaprop && RNA_property_array_length(&but->rnapoin, but->rnaprop) == 4)
RNA_property_float_set_index(&but->rnapoin, but->rnaprop, 3, rgba[3]);
@@ -1845,7 +2273,7 @@ static void ui_but_copy_paste(bContext *C, uiBut *but, uiHandleButtonData *data,
}
/* text/string and ID data */
- else if (ELEM(but->type, TEX, SEARCH_MENU, SEARCH_MENU_UNLINK)) {
+ else if (ELEM(but->type, UI_BTYPE_TEXT, UI_BTYPE_SEARCH_MENU)) {
uiHandleButtonData *active_data = but->active;
if (but->poin == NULL && but->rnapoin.data == NULL) {
@@ -1860,12 +2288,12 @@ static void ui_but_copy_paste(bContext *C, uiBut *but, uiHandleButtonData *data,
else {
button_activate_state(C, but, BUTTON_STATE_TEXT_EDITING);
- if (ui_is_but_utf8(but))
+ if (ui_but_is_utf8(but))
BLI_strncpy_utf8(active_data->str, buf_paste, active_data->maxlen);
else
BLI_strncpy(active_data->str, buf_paste, active_data->maxlen);
- if (ELEM(but->type, SEARCH_MENU, SEARCH_MENU_UNLINK)) {
+ if (but->type == UI_BTYPE_SEARCH_MENU) {
/* else uiSearchboxData.active member is not updated [#26856] */
but->changed = true;
ui_searchbox_update(C, data->searchbox, but, true);
@@ -1874,7 +2302,7 @@ static void ui_but_copy_paste(bContext *C, uiBut *but, uiHandleButtonData *data,
}
}
/* colorband (not supported by system clipboard) */
- else if (but->type == BUT_COLORBAND) {
+ else if (but->type == UI_BTYPE_COLORBAND) {
if (mode == 'c') {
if (but->poin != NULL) {
memcpy(&but_copypaste_coba, but->poin, sizeof(ColorBand));
@@ -1891,7 +2319,7 @@ static void ui_but_copy_paste(bContext *C, uiBut *but, uiHandleButtonData *data,
}
}
}
- else if (but->type == BUT_CURVE) {
+ else if (but->type == UI_BTYPE_CURVE) {
if (mode == 'c') {
if (but->poin != NULL) {
but_copypaste_curve_alive = true;
@@ -1916,7 +2344,7 @@ static void ui_but_copy_paste(bContext *C, uiBut *but, uiHandleButtonData *data,
if (mode == 'c') {
PointerRNA *opptr;
char *str;
- opptr = uiButGetOperatorPtrRNA(but); /* allocated when needed, the button owns it */
+ opptr = UI_but_operator_ptr_get(but); /* allocated when needed, the button owns it */
str = WM_operator_pystring_ex(C, NULL, false, true, but->optype, opptr);
@@ -1926,8 +2354,8 @@ static void ui_but_copy_paste(bContext *C, uiBut *but, uiHandleButtonData *data,
}
}
/* menu (any type) */
- else if (ELEM(but->type, MENU, PULLDOWN)) {
- MenuType *mt = uiButGetMenuType(but);
+ else if (ELEM(but->type, UI_BTYPE_MENU, UI_BTYPE_PULLDOWN)) {
+ MenuType *mt = UI_but_menutype_get(but);
if (mt) {
char str[32 + sizeof(mt->idname)];
BLI_snprintf(str, sizeof(str), "bpy.ops.wm.call_menu(name=\"%s\")", mt->idname);
@@ -1940,15 +2368,17 @@ static void ui_but_copy_paste(bContext *C, uiBut *but, uiHandleButtonData *data,
}
}
-/* ************************ password text ******************************
+/**
+ * Password Text
+ * =============
*
* Functions to convert password strings that should not be displayed
- * to asterisk representation (e.g. mysecretpasswd -> *************)
+ * to asterisk representation (e.g. 'mysecretpasswd' -> '*************')
*
* It converts every UTF-8 character to an asterisk, and also remaps
* the cursor position and selection start/end.
*
- * Note: remaping is used, because password could contain UTF-8 characters.
+ * \note: remaping is used, because password could contain UTF-8 characters.
*
*/
@@ -1971,7 +2401,7 @@ static int ui_text_position_to_hidden(uiBut *but, int pos)
return BLI_strnlen_utf8(butstr, pos);
}
-void ui_button_text_password_hide(char password_str[UI_MAX_PASSWORD_STR], uiBut *but, const bool restore)
+void ui_but_text_password_hide(char password_str[UI_MAX_PASSWORD_STR], uiBut *but, const bool restore)
{
char *butstr;
@@ -2034,7 +2464,7 @@ static bool ui_textedit_delete_selection(uiBut *but, uiHandleButtonData *data)
*/
static void ui_textedit_set_cursor_pos(uiBut *but, uiHandleButtonData *data, const float x)
{
- uiStyle *style = UI_GetStyle(); // XXX pass on as arg
+ uiStyle *style = UI_style_get(); // XXX pass on as arg
uiFontStyle *fstyle = &style->widget;
const float aspect = but->block->aspect;
const short fstyle_points_prev = fstyle->points;
@@ -2047,18 +2477,18 @@ static void ui_textedit_set_cursor_pos(uiBut *but, uiHandleButtonData *data, con
ui_fontscale(&fstyle->points, aspect);
- uiStyleFontSet(fstyle);
+ UI_fontstyle_set(fstyle);
if (fstyle->kerning == 1) /* for BLF_width */
BLF_enable(fstyle->uifont_id, BLF_KERNING_DEFAULT);
- ui_button_text_password_hide(password_str, but, false);
+ ui_but_text_password_hide(password_str, but, false);
origstr = MEM_mallocN(sizeof(char) * data->maxlen, "ui_textedit origstr");
BLI_strncpy(origstr, but->editstr, data->maxlen);
- if (ELEM(but->type, TEX, SEARCH_MENU, SEARCH_MENU_UNLINK)) {
+ if (ELEM(but->type, UI_BTYPE_TEXT, UI_BTYPE_SEARCH_MENU)) {
if (but->flag & UI_HAS_ICON) {
startx += UI_DPI_ICON_SIZE / aspect;
}
@@ -2128,7 +2558,7 @@ static void ui_textedit_set_cursor_pos(uiBut *but, uiHandleButtonData *data, con
if (fstyle->kerning == 1)
BLF_disable(fstyle->uifont_id, BLF_KERNING_DEFAULT);
- ui_button_text_password_hide(password_str, but, true);
+ ui_but_text_password_hide(password_str, but, true);
MEM_freeN(origstr);
@@ -2145,14 +2575,16 @@ static void ui_textedit_set_cursor_select(uiBut *but, uiHandleButtonData *data,
if (data->selextend == EXTEND_RIGHT) but->selend = but->pos;
else if (data->selextend == EXTEND_LEFT) but->selsta = but->pos;
- ui_check_but(but);
+ ui_but_update(but);
}
-/* this is used for both utf8 and ascii, its meant to be used for single keys,
+/**
+ * This is used for both utf8 and ascii, its meant to be used for single keys,
* notice the buffer is either copied or not, so its not suitable for pasting in
* - campbell */
-static bool ui_textedit_type_buf(uiBut *but, uiHandleButtonData *data,
- const char *utf8_buf, int utf8_buf_len)
+static bool ui_textedit_type_buf(
+ uiBut *but, uiHandleButtonData *data,
+ const char *utf8_buf, int utf8_buf_len)
{
char *str;
int len;
@@ -2185,7 +2617,7 @@ static bool ui_textedit_type_ascii(uiBut *but, uiHandleButtonData *data, char as
{
char buf[2] = {ascii, '\0'};
- if (ui_is_but_utf8(but) && (BLI_str_utf8_size(buf) == -1)) {
+ if (ui_but_is_utf8(but) && (BLI_str_utf8_size(buf) == -1)) {
printf("%s: entering invalid ascii char into an ascii key (%d)\n",
__func__, (int)(unsigned char)ascii);
@@ -2196,15 +2628,16 @@ static bool ui_textedit_type_ascii(uiBut *but, uiHandleButtonData *data, char as
return ui_textedit_type_buf(but, data, buf, 1);
}
-static void ui_textedit_move(uiBut *but, uiHandleButtonData *data, strCursorJumpDirection direction,
- const bool select, strCursorJumpType jump)
+static void ui_textedit_move(
+ uiBut *but, uiHandleButtonData *data, strCursorJumpDirection direction,
+ const bool select, strCursorJumpType jump)
{
const char *str = data->str;
const int len = strlen(str);
const int pos_prev = but->pos;
const bool has_sel = (but->selend - but->selsta) > 0;
- ui_check_but(but);
+ ui_but_update(but);
/* special case, quit selection and set cursor */
if (has_sel && !select) {
@@ -2356,7 +2789,7 @@ static bool ui_textedit_copypaste(uiBut *but, uiHandleButtonData *data, const in
/* paste */
if (mode == UI_TEXTEDIT_PASTE) {
- /* TODO, ensure UTF8 ui_is_but_utf8() - campbell */
+ /* TODO, ensure UTF8 ui_but_is_utf8() - campbell */
/* extract the first line from the clipboard */
pbuf = WM_clipboard_text_get_firstline(false, &buf_len);
@@ -2412,9 +2845,65 @@ static bool ui_textedit_copypaste(uiBut *but, uiHandleButtonData *data, const in
return changed;
}
+#ifdef WITH_INPUT_IME
+/* test if the translation context allows IME input - used to
+ * avoid weird character drawing if IME inputs non-ascii chars */
+static bool ui_ime_is_lang_supported(void)
+{
+ const char *uilng = BLT_lang_get();
+ const bool is_lang_supported = STREQ(uilng, "zh_CN") ||
+ STREQ(uilng, "zh_TW") ||
+ STREQ(uilng, "ja_JP");
+
+ return ((U.transopts & USER_DOTRANSLATE) && is_lang_supported);
+}
+
+/* enable ime, and set up uibut ime data */
+static void ui_textedit_ime_begin(wmWindow *win, uiBut *UNUSED(but))
+{
+ /* XXX Is this really needed? */
+ int x, y;
+
+ BLI_assert(win->ime_data == NULL);
+
+ /* enable IME and position to cursor, it's a trick */
+ x = win->eventstate->x;
+ /* flip y and move down a bit, prevent the IME panel cover the edit button */
+ y = win->eventstate->y - 12;
+
+ wm_window_IME_begin(win, x, y, 0, 0, true);
+}
+
+/* disable ime, and clear uibut ime data */
+static void ui_textedit_ime_end(wmWindow *win, uiBut *UNUSED(but))
+{
+ wm_window_IME_end(win);
+}
+
+void ui_but_ime_reposition(uiBut *but, int x, int y, bool complete)
+{
+ BLI_assert(but->active);
+
+ ui_region_to_window(but->active->region, &x, &y);
+ wm_window_IME_begin(but->active->window, x, y - 4, 0, 0, complete);
+}
+
+wmIMEData *ui_but_ime_data_get(uiBut *but)
+{
+ if (but->active && but->active->window) {
+ return but->active->window->ime_data;
+ }
+ else {
+ return NULL;
+ }
+}
+#endif /* WITH_INPUT_IME */
+
static void ui_textedit_begin(bContext *C, uiBut *but, uiHandleButtonData *data)
{
+ wmWindow *win = CTX_wm_window(C);
int len;
+ const bool is_num_but = ELEM(but->type, UI_BTYPE_NUM, UI_BTYPE_NUM_SLIDER);
if (data->str) {
MEM_freeN(data->str);
@@ -2426,24 +2915,34 @@ static void ui_textedit_begin(bContext *C, uiBut *but, uiHandleButtonData *data)
if (data->applied_interactive) {
/* remove any small changes so canceling edit doesn't restore invalid value: T40538 */
data->cancel = true;
- ui_apply_button(C, but->block, but, data, true);
+ ui_apply_but(C, but->block, but, data, true);
data->cancel = false;
data->applied_interactive = false;
}
#endif
+#ifdef USE_ALLSELECT
+ if (is_num_but) {
+ if (IS_ALLSELECT_EVENT(win->eventstate)) {
+ data->select_others.is_enabled = true;
+ data->select_others.is_copy = true;
+
+ }
+ }
+#endif
+
/* retrieve string */
- data->maxlen = ui_get_but_string_max_length(but);
+ data->maxlen = ui_but_string_get_max_length(but);
data->str = MEM_callocN(sizeof(char) * data->maxlen + 1, "textedit str");
- ui_get_but_string(but, data->str, data->maxlen);
+ ui_but_string_get(but, data->str, data->maxlen);
- if (ui_is_but_float(but) && !ui_is_but_unit(but)) {
+ if (ui_but_is_float(but) && !ui_but_is_unit(but)) {
BLI_str_rstrip_float_zero(data->str, '\0');
}
- if (ELEM(but->type, NUM, NUMSLI)) {
- ui_convert_to_unit_alt_name(but, data->str, data->maxlen);
+ if (is_num_but) {
+ ui_but_convert_to_unit_alt_name(but, data->str, data->maxlen);
}
/* won't change from now on */
@@ -2460,7 +2959,7 @@ static void ui_textedit_begin(bContext *C, uiBut *but, uiHandleButtonData *data)
but->selend = len;
/* optional searchbox */
- if (ELEM(but->type, SEARCH_MENU, SEARCH_MENU_UNLINK)) {
+ if (but->type == UI_BTYPE_SEARCH_MENU) {
data->searchbox = ui_searchbox_create(C, data->region, but);
ui_searchbox_update(C, data->searchbox, but, true); /* true = reset */
}
@@ -2468,15 +2967,23 @@ static void ui_textedit_begin(bContext *C, uiBut *but, uiHandleButtonData *data)
/* reset alert flag (avoid confusion, will refresh on exit) */
but->flag &= ~UI_BUT_REDALERT;
- ui_check_but(but);
-
- WM_cursor_modal_set(CTX_wm_window(C), BC_TEXTEDITCURSOR);
+ ui_but_update(but);
+
+ WM_cursor_modal_set(win, BC_TEXTEDITCURSOR);
+
+#ifdef WITH_INPUT_IME
+ if (is_num_but == false && ui_ime_is_lang_supported()) {
+ ui_textedit_ime_begin(win, but);
+ }
+#endif
}
static void ui_textedit_end(bContext *C, uiBut *but, uiHandleButtonData *data)
{
+ wmWindow *win = CTX_wm_window(C);
+
if (but) {
- if (ui_is_but_utf8(but)) {
+ if (ui_but_is_utf8(but)) {
int strip = BLI_utf8_invalid_strip(but->editstr, strlen(but->editstr));
/* not a file?, strip non utf-8 chars */
if (strip) {
@@ -2505,7 +3012,13 @@ static void ui_textedit_end(bContext *C, uiBut *but, uiHandleButtonData *data)
but->pos = -1;
}
- WM_cursor_modal_restore(CTX_wm_window(C));
+ WM_cursor_modal_restore(win);
+
+#ifdef WITH_INPUT_IME
+ if (win->ime_data) {
+ ui_textedit_ime_end(win, but);
+ }
+#endif
}
static void ui_textedit_next_but(uiBlock *block, uiBut *actbut, uiHandleButtonData *data)
@@ -2513,11 +3026,11 @@ static void ui_textedit_next_but(uiBlock *block, uiBut *actbut, uiHandleButtonDa
uiBut *but;
/* label and roundbox can overlap real buttons (backdrops...) */
- if (ELEM(actbut->type, LABEL, SEPR, SEPRLINE, ROUNDBOX, LISTBOX))
+ if (ELEM(actbut->type, UI_BTYPE_LABEL, UI_BTYPE_SEPR, UI_BTYPE_SEPR_LINE, UI_BTYPE_ROUNDBOX, UI_BTYPE_LISTBOX))
return;
for (but = actbut->next; but; but = but->next) {
- if (ELEM(but->type, TEX, NUM, NUMSLI, SEARCH_MENU, SEARCH_MENU_UNLINK)) {
+ if (ui_but_is_editable_as_text(but)) {
if (!(but->flag & UI_BUT_DISABLED)) {
data->postbut = but;
data->posttype = BUTTON_ACTIVATE_TEXT_EDITING;
@@ -2526,7 +3039,7 @@ static void ui_textedit_next_but(uiBlock *block, uiBut *actbut, uiHandleButtonDa
}
}
for (but = block->buttons.first; but != actbut; but = but->next) {
- if (ELEM(but->type, TEX, NUM, NUMSLI, SEARCH_MENU, SEARCH_MENU_UNLINK)) {
+ if (ui_but_is_editable_as_text(but)) {
if (!(but->flag & UI_BUT_DISABLED)) {
data->postbut = but;
data->posttype = BUTTON_ACTIVATE_TEXT_EDITING;
@@ -2541,11 +3054,11 @@ static void ui_textedit_prev_but(uiBlock *block, uiBut *actbut, uiHandleButtonDa
uiBut *but;
/* label and roundbox can overlap real buttons (backdrops...) */
- if (ELEM(actbut->type, LABEL, SEPR, SEPRLINE, ROUNDBOX, LISTBOX))
+ if (ELEM(actbut->type, UI_BTYPE_LABEL, UI_BTYPE_SEPR, UI_BTYPE_SEPR_LINE, UI_BTYPE_ROUNDBOX, UI_BTYPE_LISTBOX))
return;
for (but = actbut->prev; but; but = but->prev) {
- if (ELEM(but->type, TEX, NUM, NUMSLI, SEARCH_MENU, SEARCH_MENU_UNLINK)) {
+ if (ui_but_is_editable_as_text(but)) {
if (!(but->flag & UI_BUT_DISABLED)) {
data->postbut = but;
data->posttype = BUTTON_ACTIVATE_TEXT_EDITING;
@@ -2554,7 +3067,7 @@ static void ui_textedit_prev_but(uiBlock *block, uiBut *actbut, uiHandleButtonDa
}
}
for (but = block->buttons.last; but != actbut; but = but->prev) {
- if (ELEM(but->type, TEX, NUM, NUMSLI, SEARCH_MENU, SEARCH_MENU_UNLINK)) {
+ if (ui_but_is_editable_as_text(but)) {
if (!(but->flag & UI_BUT_DISABLED)) {
data->postbut = but;
data->posttype = BUTTON_ACTIVATE_TEXT_EDITING;
@@ -2570,6 +3083,14 @@ static void ui_do_but_textedit(bContext *C, uiBlock *block, uiBut *but, uiHandle
int retval = WM_UI_HANDLER_CONTINUE;
bool changed = false, inbox = false, update = false;
+#ifdef WITH_INPUT_IME
+ wmWindow *win = CTX_wm_window(C);
+ wmIMEData *ime_data = win->ime_data;
+ bool is_ime_composing = ime_data && ime_data->is_ime_composing;
+#else
+ bool is_ime_composing = false;
+#endif
+
switch (event->type) {
case MOUSEMOVE:
case MOUSEPAN:
@@ -2590,6 +3111,12 @@ static void ui_do_but_textedit(bContext *C, uiBlock *block, uiBut *but, uiHandle
case RIGHTMOUSE:
case ESCKEY:
if (event->val == KM_PRESS) {
+#ifdef WITH_INPUT_IME
+ /* skips button handling since it is not wanted */
+ if (is_ime_composing) {
+ break;
+ }
+#endif
data->cancel = true;
data->escapecancel = true;
button_activate_state(C, but, BUTTON_STATE_EXIT);
@@ -2647,12 +3174,12 @@ static void ui_do_but_textedit(bContext *C, uiBlock *block, uiBut *but, uiHandle
}
}
- if (event->val == KM_PRESS) {
+ if (event->val == KM_PRESS && !is_ime_composing) {
switch (event->type) {
case VKEY:
case XKEY:
case CKEY:
- if (event->ctrl || event->oskey) {
+ if (IS_EVENT_MOD(event, ctrl, oskey)) {
if (event->type == VKEY)
changed = ui_textedit_copypaste(but, data, UI_TEXTEDIT_PASTE);
else if (event->type == CKEY)
@@ -2682,6 +3209,9 @@ static void ui_do_but_textedit(bContext *C, uiBlock *block, uiBut *but, uiHandle
ui_searchbox_event(C, data->searchbox, but, event);
break;
}
+ if (event->type == WHEELDOWNMOUSE) {
+ break;
+ }
/* fall-through */
case ENDKEY:
ui_textedit_move(but, data, STRCUR_DIR_NEXT,
@@ -2697,6 +3227,9 @@ static void ui_do_but_textedit(bContext *C, uiBlock *block, uiBut *but, uiHandle
ui_searchbox_event(C, data->searchbox, but, event);
break;
}
+ if (event->type == WHEELUPMOUSE) {
+ break;
+ }
/* fall-through */
case HOMEKEY:
ui_textedit_move(but, data, STRCUR_DIR_PREV,
@@ -2725,10 +3258,10 @@ static void ui_do_but_textedit(bContext *C, uiBlock *block, uiBut *but, uiHandle
/* Ctrl + A: Select all */
#if defined(__APPLE__)
/* OSX uses cmd-a systemwide, so add it */
- if ((event->oskey && !(event->alt || event->shift || event->ctrl)) ||
- (event->ctrl && !(event->alt || event->shift || event->oskey)))
+ if ((event->oskey && !IS_EVENT_MOD(event, shift, alt, ctrl)) ||
+ (event->ctrl && !IS_EVENT_MOD(event, shift, alt, oskey)))
#else
- if (event->ctrl && !(event->alt || event->shift || event->oskey))
+ if (event->ctrl && !IS_EVENT_MOD(event, shift, alt, oskey))
#endif
{
ui_textedit_move(but, data, STRCUR_DIR_PREV,
@@ -2747,11 +3280,9 @@ static void ui_do_but_textedit(bContext *C, uiBlock *block, uiBut *but, uiHandle
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 */
- else if (event->shift || event->ctrl || event->alt || event->oskey) {
+ else if (IS_EVENT_MOD(event, shift, ctrl, alt, oskey)) {
ui_textedit_prev_but(block, but, data);
button_activate_state(C, but, BUTTON_STATE_EXIT);
}
@@ -2763,13 +3294,21 @@ static void ui_do_but_textedit(bContext *C, uiBlock *block, uiBut *but, uiHandle
break;
}
- if ((event->ascii || event->utf8_buf[0]) && (retval == WM_UI_HANDLER_CONTINUE)) {
+ if ((event->ascii || event->utf8_buf[0]) &&
+ (retval == WM_UI_HANDLER_CONTINUE)
+#ifdef WITH_INPUT_IME
+ &&
+ !is_ime_composing &&
+ !WM_event_is_ime_switch(event)
+#endif
+ )
+ {
char ascii = event->ascii;
const char *utf8_buf = event->utf8_buf;
/* exception that's useful for number buttons, some keyboard
* numpads have a comma instead of a period */
- if (ELEM(but->type, NUM, NUMSLI)) { /* could use data->min*/
+ if (ELEM(but->type, UI_BTYPE_NUM, UI_BTYPE_NUM_SLIDER)) { /* could use data->min*/
if (event->type == PADPERIOD && ascii == ',') {
ascii = '.';
utf8_buf = NULL; /* force ascii fallback */
@@ -2793,18 +3332,38 @@ static void ui_do_but_textedit(bContext *C, uiBlock *block, uiBut *but, uiHandle
retval = WM_UI_HANDLER_BREAK;
}
- /* textbutton with magnifier icon: do live update for search button */
- if (but->icon == ICON_VIEWZOOM)
+ /* textbutton with this flag: do live update (e.g. for search buttons) */
+ if (but->flag & UI_BUT_TEXTEDIT_UPDATE) {
update = true;
+ }
+ }
+
+#ifdef WITH_INPUT_IME
+ if (event->type == WM_IME_COMPOSITE_START || event->type == WM_IME_COMPOSITE_EVENT) {
+ changed = true;
+
+ if (event->type == WM_IME_COMPOSITE_START && but->selend > but->selsta) {
+ ui_textedit_delete_selection(but, data);
+ }
+ if (event->type == WM_IME_COMPOSITE_EVENT && ime_data->result_len) {
+ ui_textedit_type_buf(
+ but, data,
+ ime_data->str_result,
+ ime_data->result_len);
+ }
}
+ else if (event->type == WM_IME_COMPOSITE_END) {
+ changed = true;
+ }
+#endif
if (changed) {
- /* only update when typing for TAB key */
+ /* only do live update when but flag request it (UI_BUT_TEXTEDIT_UPDATE). */
if (update && data->interactive) {
- ui_apply_button(C, block, but, data, true);
+ ui_apply_but(C, block, but, data, true);
}
else {
- ui_check_but(but);
+ ui_but_update(but);
}
but->changed = true;
@@ -2839,7 +3398,7 @@ static void ui_do_but_textedit_select(bContext *C, uiBlock *block, uiBut *but, u
}
if (retval == WM_UI_HANDLER_BREAK) {
- ui_check_but(but);
+ ui_but_update(but);
ED_region_tag_redraw(data->region);
}
}
@@ -2848,22 +3407,22 @@ static void ui_do_but_textedit_select(bContext *C, uiBlock *block, uiBut *but, u
static void ui_numedit_begin(uiBut *but, uiHandleButtonData *data)
{
- if (but->type == BUT_CURVE) {
+ if (but->type == UI_BTYPE_CURVE) {
but->editcumap = (CurveMapping *)but->poin;
}
- else if (but->type == BUT_COLORBAND) {
+ else if (but->type == UI_BTYPE_COLORBAND) {
data->coba = (ColorBand *)but->poin;
but->editcoba = data->coba;
}
- else if (ELEM(but->type, BUT_NORMAL, HSVCUBE, HSVCIRCLE, COLOR)) {
- ui_get_but_vectorf(but, data->origvec);
+ else if (ELEM(but->type, UI_BTYPE_UNITVEC, UI_BTYPE_HSVCUBE, UI_BTYPE_HSVCIRCLE, UI_BTYPE_COLOR)) {
+ ui_but_v3_get(but, data->origvec);
copy_v3_v3(data->vec, data->origvec);
but->editvec = data->vec;
}
else {
float softrange, softmin, softmax;
- data->startvalue = ui_get_but_val(but);
+ data->startvalue = ui_but_value_get(but);
data->origvalue = data->startvalue;
data->value = data->origvalue;
but->editval = &data->value;
@@ -2897,10 +3456,10 @@ static void ui_numedit_end(uiBut *but, uiHandleButtonData *data)
static void ui_numedit_apply(bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data)
{
if (data->interactive) {
- ui_apply_button(C, block, but, data, true);
+ ui_apply_but(C, block, but, data, true);
}
else {
- ui_check_but(but);
+ ui_but_update(but);
}
ED_region_tag_redraw(data->region);
@@ -2908,7 +3467,7 @@ static void ui_numedit_apply(bContext *C, uiBlock *block, uiBut *but, uiHandleBu
/* ****************** menu opening for various types **************** */
-static void ui_blockopen_begin(bContext *C, uiBut *but, uiHandleButtonData *data)
+static void ui_block_open_begin(bContext *C, uiBut *but, uiHandleButtonData *data)
{
uiBlockCreateFunc func = NULL;
uiBlockHandleCreateFunc handlefunc = NULL;
@@ -2916,8 +3475,8 @@ static void ui_blockopen_begin(bContext *C, uiBut *but, uiHandleButtonData *data
void *arg = NULL;
switch (but->type) {
- case BLOCK:
- case PULLDOWN:
+ case UI_BTYPE_BLOCK:
+ case UI_BTYPE_PULLDOWN:
if (but->menu_create_func) {
menufunc = but->menu_create_func;
arg = but->poin;
@@ -2927,13 +3486,13 @@ static void ui_blockopen_begin(bContext *C, uiBut *but, uiHandleButtonData *data
arg = but->poin ? but->poin : but->func_argN;
}
break;
- case MENU:
+ case UI_BTYPE_MENU:
BLI_assert(but->menu_create_func);
menufunc = but->menu_create_func;
arg = but->poin;
break;
- case COLOR:
- ui_get_but_vectorf(but, data->origvec);
+ case UI_BTYPE_COLOR:
+ ui_but_v3_get(but, data->origvec);
copy_v3_v3(data->vec, data->origvec);
but->editvec = data->vec;
@@ -2957,11 +3516,20 @@ static void ui_blockopen_begin(bContext *C, uiBut *but, uiHandleButtonData *data
data->menu->popup = but->block->handle->popup;
}
+#ifdef USE_ALLSELECT
+ {
+ wmWindow *win = CTX_wm_window(C);
+ if (IS_ALLSELECT_EVENT(win->eventstate)) {
+ data->select_others.is_enabled = true;
+ }
+ }
+#endif
+
/* this makes adjacent blocks auto open from now on */
//if (but->block->auto_open == 0) but->block->auto_open = 1;
}
-static void ui_blockopen_end(bContext *C, uiBut *but, uiHandleButtonData *data)
+static void ui_block_open_end(bContext *C, uiBut *but, uiHandleButtonData *data)
{
if (but) {
but->editval = NULL;
@@ -2976,7 +3544,7 @@ static void ui_blockopen_end(bContext *C, uiBut *but, uiHandleButtonData *data)
}
}
-int ui_button_open_menu_direction(uiBut *but)
+int ui_but_menu_direction(uiBut *but)
{
uiHandleButtonData *data = but->active;
@@ -2986,14 +3554,18 @@ 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)
+/**
+ * Hack for #uiList #UI_BTYPE_LISTROW buttons to "give" events to overlaying #UI_BTYPE_TEXT buttons
+ * (Ctrl-Click 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 && !(labelbut->flag & UI_BUT_DISABLED)) {
+ if (labelbut && labelbut->type == UI_BTYPE_TEXT && !(labelbut->flag & UI_BUT_DISABLED)) {
/* exit listrow */
data->cancel = true;
button_activate_exit(C, but, data, false, false);
@@ -3050,16 +3622,16 @@ static int ui_do_but_HOTKEYEVT(bContext *C, uiBut *but, uiHandleButtonData *data
}
}
else if (data->state == BUTTON_STATE_WAIT_KEY_EVENT) {
-
- if (event->type == MOUSEMOVE)
+ if (ELEM(event->type, MOUSEMOVE, INBETWEEN_MOUSEMOVE)) {
return WM_UI_HANDLER_CONTINUE;
-
+ }
+
if (event->type == LEFTMOUSE && event->val == KM_PRESS) {
/* only cancel if click outside the button */
- if (ui_mouse_inside_button(but->active->region, but, event->x, event->y) == 0) {
+ if (ui_but_contains_point_px(but->active->region, but, event->x, event->y) == 0) {
/* data->cancel doesnt work, this button opens immediate */
if (but->flag & UI_BUT_IMMEDIATE)
- ui_set_but_val(but, 0);
+ ui_but_value_set(but, 0);
else
data->cancel = true;
button_activate_state(C, but, BUTTON_STATE_EXIT);
@@ -3074,14 +3646,14 @@ static int ui_do_but_HOTKEYEVT(bContext *C, uiBut *but, uiHandleButtonData *data
if (event->ctrl) but->modifier_key |= KM_CTRL;
if (event->oskey) but->modifier_key |= KM_OSKEY;
- ui_check_but(but);
+ ui_but_update(but);
ED_region_tag_redraw(data->region);
if (event->val == KM_PRESS) {
if (ISHOTKEY(event->type)) {
- if (WM_key_event_string(event->type)[0])
- ui_set_but_val(but, event->type);
+ if (WM_key_event_string(event->type, false)[0])
+ ui_but_value_set(but, event->type);
else
data->cancel = true;
@@ -3111,12 +3683,13 @@ static int ui_do_but_KEYEVT(bContext *C, uiBut *but, uiHandleButtonData *data, c
}
}
else if (data->state == BUTTON_STATE_WAIT_KEY_EVENT) {
- if (event->type == MOUSEMOVE)
+ if (ELEM(event->type, MOUSEMOVE, INBETWEEN_MOUSEMOVE)) {
return WM_UI_HANDLER_CONTINUE;
+ }
if (event->val == KM_PRESS) {
- if (WM_key_event_string(event->type)[0])
- ui_set_but_val(but, event->type);
+ if (WM_key_event_string(event->type, false)[0])
+ ui_but_value_set(but, event->type);
else
data->cancel = true;
@@ -3131,10 +3704,10 @@ static int ui_do_but_TEX(bContext *C, uiBlock *block, uiBut *but, uiHandleButton
{
if (data->state == BUTTON_STATE_HIGHLIGHT) {
if (ELEM(event->type, LEFTMOUSE, EVT_BUT_OPEN, PADENTER, RETKEY) && event->val == KM_PRESS) {
- if (ELEM(event->type, PADENTER, RETKEY) && (!ui_is_but_utf8(but))) {
+ if (ELEM(event->type, PADENTER, RETKEY) && (!ui_but_is_utf8(but))) {
/* pass - allow filesel, enter to execute */
}
- else if (but->dt == UI_EMBOSSN && !event->ctrl) {
+ else if (but->dt == UI_EMBOSS_NONE && !event->ctrl) {
/* pass */
}
else {
@@ -3157,9 +3730,11 @@ static int ui_do_but_TEX(bContext *C, uiBlock *block, uiBut *but, uiHandleButton
static int ui_do_but_SEARCH_UNLINK(bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, const wmEvent *event)
{
+ uiButExtraIconType extra_icon_type;
+
/* unlink icon is on right */
- if (ELEM(event->type, LEFTMOUSE, EVT_BUT_OPEN, PADENTER, RETKEY) && event->val == KM_PRESS &&
- ui_is_but_search_unlink_visible(but))
+ if ((ELEM(event->type, LEFTMOUSE, EVT_BUT_OPEN, PADENTER, RETKEY)) &&
+ ((extra_icon_type = ui_but_icon_extra_get(but)) != UI_BUT_ICONEXTRA_NONE))
{
ARegion *ar = data->region;
rcti rect;
@@ -3170,14 +3745,29 @@ static int ui_do_but_SEARCH_UNLINK(bContext *C, uiBlock *block, uiBut *but, uiHa
BLI_rcti_rctf_copy(&rect, &but->rect);
rect.xmin = rect.xmax - (BLI_rcti_size_y(&rect));
+ /* handle click on unlink/eyedropper icon */
if (BLI_rcti_isect_pt(&rect, x, y)) {
- /* most likely NULL, but let's check, and give it temp zero string */
- if (data->str == NULL)
- data->str = MEM_callocN(1, "temp str");
- data->str[0] = 0;
+ /* doing this on KM_PRESS calls eyedropper after clicking unlink icon */
+ if (event->val == KM_RELEASE) {
+ /* unlink */
+ if (extra_icon_type == UI_BUT_ICONEXTRA_UNLINK) {
+ /* most likely NULL, but let's check, and give it temp zero string */
+ if (data->str == NULL) {
+ data->str = MEM_callocN(1, "temp str");
+ }
+ data->str[0] = 0;
- ui_apply_but_TEX(C, but, data);
- button_activate_state(C, but, BUTTON_STATE_EXIT);
+ ui_apply_but_TEX(C, but, data);
+ button_activate_state(C, but, BUTTON_STATE_EXIT);
+ }
+ /* eyedropper */
+ else if (extra_icon_type == UI_BUT_ICONEXTRA_EYEDROPPER) {
+ WM_operator_name_call(C, "UI_OT_eyedropper_id", WM_OP_INVOKE_DEFAULT, NULL);
+ }
+ else {
+ BLI_assert(0);
+ }
+ }
return WM_UI_HANDLER_BREAK;
}
@@ -3189,12 +3779,12 @@ static int ui_do_but_TOG(bContext *C, uiBut *but, uiHandleButtonData *data, cons
{
#ifdef USE_DRAG_TOGGLE
if (data->state == BUTTON_STATE_HIGHLIGHT) {
- if (event->type == LEFTMOUSE && event->val == KM_PRESS && ui_is_but_drag_toggle(but)) {
+ if (event->type == LEFTMOUSE && event->val == KM_PRESS && ui_but_is_drag_toggle(but)) {
#if 0 /* UNUSED */
data->togdual = event->ctrl;
data->togonly = !event->shift;
#endif
- ui_apply_button(C, but->block, but, data, true);
+ ui_apply_but(C, but->block, but, data, true);
button_activate_state(C, but, BUTTON_STATE_WAIT_DRAG);
data->dragstartx = event->x;
data->dragstarty = event->y;
@@ -3216,6 +3806,38 @@ static int ui_do_but_TOG(bContext *C, uiBut *but, uiHandleButtonData *data, cons
button_activate_state(C, but, BUTTON_STATE_EXIT);
return WM_UI_HANDLER_BREAK;
}
+ else if (ELEM(event->type, WHEELDOWNMOUSE, WHEELUPMOUSE) && event->ctrl) {
+ /* Support alt+wheel on expanded enum rows */
+ if (but->type == UI_BTYPE_ROW) {
+ const int direction = (event->type == WHEELDOWNMOUSE) ? -1 : 1;
+ uiBut *but_select = ui_but_find_select_in_enum(but, direction);
+ if (but_select) {
+ uiBut *but_other = (direction == -1) ? but_select->next : but_select->prev;
+ if (but_other && ui_but_find_select_in_enum__cmp(but, but_other)) {
+ ARegion *ar = data->region;
+
+ data->cancel = true;
+ button_activate_exit(C, but, data, false, false);
+
+ /* Activate the text button. */
+ button_activate_init(C, ar, but_other, BUTTON_ACTIVATE_OVER);
+ data = but_other->active;
+ if (data) {
+ ui_apply_but(C, but->block, but_other, but_other->active, true);
+ button_activate_exit(C, but_other, data, false, false);
+
+ /* restore active button */
+ button_activate_init(C, ar, but, BUTTON_ACTIVATE_OVER);
+ }
+ else {
+ /* shouldn't happen */
+ BLI_assert(0);
+ }
+ }
+ }
+ return WM_UI_HANDLER_BREAK;
+ }
+ }
}
return WM_UI_HANDLER_CONTINUE;
}
@@ -3227,7 +3849,7 @@ static int ui_do_but_EXIT(bContext *C, uiBut *but, uiHandleButtonData *data, con
/* first handle click on icondrag type button */
if (event->type == LEFTMOUSE && but->dragpoin) {
- if (ui_but_mouse_inside_icon(but, data->region, event)) {
+ if (ui_but_contains_point_px_icon(but, data->region, event)) {
/* tell the button to wait and keep checking further events to
* see if it should start dragging */
@@ -3238,7 +3860,7 @@ static int ui_do_but_EXIT(bContext *C, uiBut *but, uiHandleButtonData *data, con
}
}
#ifdef USE_DRAG_TOGGLE
- if (event->type == LEFTMOUSE && ui_is_but_drag_toggle(but)) {
+ if (event->type == LEFTMOUSE && ui_but_is_drag_toggle(but)) {
button_activate_state(C, but, BUTTON_STATE_WAIT_DRAG);
data->dragstartx = event->x;
data->dragstarty = event->y;
@@ -3249,7 +3871,7 @@ static int ui_do_but_EXIT(bContext *C, uiBut *but, uiHandleButtonData *data, con
if (ELEM(event->type, LEFTMOUSE, PADENTER, RETKEY) && event->val == KM_PRESS) {
int ret = WM_UI_HANDLER_BREAK;
/* XXX (a bit ugly) Special case handling for filebrowser drag button */
- if (but->dragpoin && but->imb && ui_but_mouse_inside_icon(but, data->region, event)) {
+ if (but->dragpoin && but->imb && ui_but_contains_point_px_icon(but, data->region, event)) {
ret = WM_UI_HANDLER_CONTINUE;
}
button_activate_state(C, but, BUTTON_STATE_EXIT);
@@ -3259,7 +3881,7 @@ static int ui_do_but_EXIT(bContext *C, uiBut *but, uiHandleButtonData *data, con
else if (data->state == BUTTON_STATE_WAIT_DRAG) {
/* this function also ends state */
- if (ui_but_start_drag(C, but, data, event)) {
+ if (ui_but_drag_init(C, but, data, event)) {
return WM_UI_HANDLER_BREAK;
}
@@ -3280,8 +3902,9 @@ static int ui_do_but_EXIT(bContext *C, uiBut *but, uiHandleButtonData *data, con
}
/* var names match ui_numedit_but_NUM */
-static float ui_numedit_apply_snapf(uiBut *but, float tempf, float softmin, float softmax, float softrange,
- const enum eSnapType snap)
+static float ui_numedit_apply_snapf(
+ uiBut *but, float tempf, float softmin, float softmax, float softrange,
+ const enum eSnapType snap)
{
if (tempf == softmin || tempf == softmax || snap == SNAP_OFF) {
/* pass */
@@ -3289,9 +3912,9 @@ static float ui_numedit_apply_snapf(uiBut *but, float tempf, float softmin, floa
else {
float fac = 1.0f;
- if (ui_is_but_unit(but)) {
+ if (ui_but_is_unit(but)) {
UnitSettings *unit = but->block->unit;
- int unit_type = RNA_SUBTYPE_UNIT_VALUE(uiButGetUnitType(but));
+ int unit_type = RNA_SUBTYPE_UNIT_VALUE(UI_but_unit_type_get(but));
if (bUnit_IsValid(unit->system, unit_type)) {
fac = (float)bUnit_BaseScalar(unit->system, unit_type);
@@ -3309,15 +3932,25 @@ static float ui_numedit_apply_snapf(uiBut *but, float tempf, float softmin, floa
softrange /= fac;
}
+ /* workaround, too high snapping values */
+ /* snapping by 10's for float buttons is quite annoying (location, scale...),
+ * but allow for rotations */
+ if (softrange >= 21.0f) {
+ int unit_type = UI_but_unit_type_get(but);
+ if (!ELEM(unit_type, PROP_UNIT_ROTATION)) {
+ softrange = 20.0f;
+ }
+ }
+
if (snap == SNAP_ON) {
- if (softrange < 2.10f) tempf = 0.1f * floorf(10.0f * tempf);
- else if (softrange < 21.0f) tempf = floorf(tempf);
- else tempf = 10.0f * floorf(tempf / 10.0f);
+ if (softrange < 2.10f) tempf = roundf(tempf * 10.0f) * 0.1f;
+ else if (softrange < 21.0f) tempf = roundf(tempf);
+ else tempf = roundf(tempf * 0.1f) * 10.0f;
}
else if (snap == SNAP_ON_SMALL) {
- if (softrange < 2.10f) tempf = 0.01f * floorf(100.0f * tempf);
- else if (softrange < 21.0f) tempf = 0.1f * floorf(10.0f * tempf);
- else tempf = floor(tempf);
+ if (softrange < 2.10f) tempf = roundf(tempf * 100.0f) * 0.01f;
+ else if (softrange < 21.0f) tempf = roundf(tempf * 10.0f) * 0.1f;
+ else tempf = roundf(tempf);
}
else {
BLI_assert(0);
@@ -3330,8 +3963,9 @@ static float ui_numedit_apply_snapf(uiBut *but, float tempf, float softmin, floa
return tempf;
}
-static float ui_numedit_apply_snap(int temp, float softmin, float softmax,
- const enum eSnapType snap)
+static float ui_numedit_apply_snap(
+ int temp, float softmin, float softmax,
+ const enum eSnapType snap)
{
if (temp == softmin || temp == softmax)
return temp;
@@ -3350,14 +3984,15 @@ static float ui_numedit_apply_snap(int temp, float softmin, float softmax,
return temp;
}
-static bool ui_numedit_but_NUM(uiBut *but, uiHandleButtonData *data,
- int mx,
- const enum eSnapType snap, float fac)
+static bool ui_numedit_but_NUM(
+ uiBut *but, uiHandleButtonData *data,
+ int mx,
+ const enum eSnapType snap, float fac)
{
float deler, tempf, softmin, softmax, softrange;
int lvalue, temp;
bool changed = false;
- const bool is_float = ui_is_but_float(but);
+ const bool is_float = ui_but_is_float(but);
if (mx == data->draglastx)
return changed;
@@ -3381,7 +4016,7 @@ static bool ui_numedit_but_NUM(uiBut *but, uiHandleButtonData *data,
softmax = but->softmax;
softrange = softmax - softmin;
- if (ui_is_a_warp_but(but)) {
+ if (ui_but_is_cursor_warp(but)) {
/* Mouse location isn't screen clamped to the screen so use a linear mapping
* 2px == 1-int, or 1px == 1-ClickStep */
if (is_float) {
@@ -3468,7 +4103,7 @@ static bool ui_numedit_but_NUM(uiBut *but, uiHandleButtonData *data,
if (!is_float) {
- temp = floorf(tempf + 0.5f);
+ temp = iroundf(tempf);
temp = ui_numedit_apply_snap(temp, softmin, softmax, snap);
@@ -3521,11 +4156,11 @@ static int ui_do_but_NUM(bContext *C, uiBlock *block, uiBut *but, uiHandleButton
/* XXX hardcoded keymap check.... */
if (type == MOUSEPAN && event->alt)
retval = WM_UI_HANDLER_BREAK; /* allow accumulating values, otherwise scrolling gets preference */
- else if (type == WHEELDOWNMOUSE && event->alt) {
+ else if (type == WHEELDOWNMOUSE && event->ctrl) {
mx = but->rect.xmin;
click = 1;
}
- else if (type == WHEELUPMOUSE && event->alt) {
+ else if (type == WHEELUPMOUSE && event->ctrl) {
mx = but->rect.xmax;
click = 1;
}
@@ -3535,7 +4170,7 @@ static int ui_do_but_NUM(bContext *C, uiBlock *block, uiBut *but, uiHandleButton
retval = WM_UI_HANDLER_BREAK;
}
else if (event->type == LEFTMOUSE) {
- data->dragstartx = data->draglastx = ui_is_a_warp_but(but) ? screen_mx : mx;
+ data->dragstartx = data->draglastx = ui_but_is_cursor_warp(but) ? screen_mx : mx;
button_activate_state(C, but, BUTTON_STATE_NUM_EDITING);
retval = WM_UI_HANDLER_BREAK;
}
@@ -3580,7 +4215,7 @@ static int ui_do_but_NUM(bContext *C, uiBlock *block, uiBut *but, uiHandleButton
click = 1;
}
}
- else if (event->type == MOUSEMOVE) {
+ else if ((event->type == MOUSEMOVE) || ui_event_is_snap(event)) {
const enum eSnapType snap = ui_event_to_snap(event);
float fac;
@@ -3591,9 +4226,8 @@ static int ui_do_but_NUM(bContext *C, uiBlock *block, uiBut *but, uiHandleButton
fac = 1.0f;
if (event->shift) fac /= 10.0f;
- if (event->alt) fac /= 20.0f;
- if (ui_numedit_but_NUM(but, data, (ui_is_a_warp_but(but) ? screen_mx : mx), snap, fac))
+ if (ui_numedit_but_NUM(but, data, (ui_but_is_cursor_warp(but) ? screen_mx : mx), snap, fac))
ui_numedit_apply(C, block, but, data);
#ifdef USE_DRAG_MULTINUM
else if (data->multi_data.has_mbuts) {
@@ -3626,7 +4260,7 @@ static int ui_do_but_NUM(bContext *C, uiBlock *block, uiBut *but, uiHandleButton
handlewidth = min_ff(BLI_rctf_size_x(&but->rect) / 3, BLI_rctf_size_y(&but->rect));
- if (!ui_is_but_float(but)) {
+ if (!ui_but_is_float(but)) {
if (mx < (but->rect.xmin + handlewidth)) {
button_activate_state(C, but, BUTTON_STATE_NUM_EDITING);
@@ -3657,7 +4291,7 @@ static int ui_do_but_NUM(bContext *C, uiBlock *block, uiBut *but, uiHandleButton
if (mx < (but->rect.xmin + handlewidth)) {
button_activate_state(C, but, BUTTON_STATE_NUM_EDITING);
- tempf = (float)data->value - 0.01f * but->a1;
+ tempf = (float)data->value - (UI_PRECISION_FLOAT_SCALE * but->a1);
if (tempf < softmin) tempf = softmin;
data->value = tempf;
@@ -3666,7 +4300,7 @@ static int ui_do_but_NUM(bContext *C, uiBlock *block, uiBut *but, uiHandleButton
else if (mx > but->rect.xmax - handlewidth) {
button_activate_state(C, but, BUTTON_STATE_NUM_EDITING);
- tempf = (float)data->value + 0.01f * but->a1;
+ tempf = (float)data->value + (UI_PRECISION_FLOAT_SCALE * but->a1);
if (tempf > softmax) tempf = softmax;
data->value = tempf;
@@ -3686,9 +4320,10 @@ static int ui_do_but_NUM(bContext *C, uiBlock *block, uiBut *but, uiHandleButton
return retval;
}
-static bool ui_numedit_but_SLI(uiBut *but, uiHandleButtonData *data,
- int mx, const bool is_horizontal,
- const bool snap, const bool shift)
+static bool ui_numedit_but_SLI(
+ uiBut *but, uiHandleButtonData *data,
+ int mx, const bool is_horizontal,
+ const bool snap, const bool shift)
{
float deler, f, tempf, softmin, softmax, softrange;
int temp, lvalue;
@@ -3704,11 +4339,11 @@ static bool ui_numedit_but_SLI(uiBut *but, uiHandleButtonData *data,
/* yes, 'mx' as both x/y is intentional */
ui_mouse_scale_warp(data, mx, mx, &mx_fl, &my_fl, shift);
- if (but->type == NUMSLI) {
+ if (but->type == UI_BTYPE_NUM_SLIDER) {
offs = (BLI_rctf_size_y(&but->rect) / 2.0f);
deler = BLI_rctf_size_x(&but->rect) - offs;
}
- else if (but->type == SCROLL) {
+ else if (but->type == UI_BTYPE_SCROLL) {
const float size = (is_horizontal) ? BLI_rctf_size_x(&but->rect) : -BLI_rctf_size_y(&but->rect);
deler = size * (but->softmax - but->softmin) / (but->softmax - but->softmin + but->a1);
offs = 0.0;
@@ -3724,7 +4359,7 @@ static bool ui_numedit_but_SLI(uiBut *but, uiHandleButtonData *data,
/* deal with mouse correction */
#ifdef USE_CONT_MOUSE_CORRECT
- if (ui_is_a_warp_but(but)) {
+ if (ui_but_is_cursor_warp(but)) {
/* OK but can go outside bounds */
if (is_horizontal) {
data->ungrab_mval[0] = (but->rect.xmin + offs) + (f * deler);
@@ -3741,24 +4376,24 @@ static bool ui_numedit_but_SLI(uiBut *but, uiHandleButtonData *data,
tempf = softmin + f * softrange;
- temp = floorf(tempf + 0.5f);
+ temp = iroundf(tempf);
if (snap) {
if (tempf == softmin || tempf == softmax) {
/* pass */
}
- else if (ui_is_but_float(but)) {
+ else if (ui_but_is_float(but)) {
if (shift) {
if (tempf == softmin || tempf == softmax) {}
- else if (softmax - softmin < 2.10f) tempf = 0.01f * floorf(100.0f * tempf);
- else if (softmax - softmin < 21.0f) tempf = 0.1f * floorf(10.0f * tempf);
- else tempf = floorf(tempf);
+ else if (softrange < 2.10f) tempf = roundf(tempf * 100.0f) * 0.01f;
+ else if (softrange < 21.0f) tempf = roundf(tempf * 10.0f) * 0.1f;
+ else tempf = roundf(tempf);
}
else {
- if (softmax - softmin < 2.10f) tempf = 0.1f * floorf(10.0f * tempf);
- else if (softmax - softmin < 21.0f) tempf = floorf(tempf);
- else tempf = 10.0f * floorf(tempf / 10.0f);
+ if (softrange < 2.10f) tempf = roundf(tempf * 10.0f) * 0.1f;
+ else if (softrange < 21.0f) tempf = roundf(tempf);
+ else tempf = roundf(tempf * 0.1f) * 10.0f;
}
}
else {
@@ -3767,8 +4402,8 @@ static bool ui_numedit_but_SLI(uiBut *but, uiHandleButtonData *data,
}
}
- if (!ui_is_but_float(but)) {
- lvalue = floor(data->value + 0.5);
+ if (!ui_but_is_float(but)) {
+ lvalue = round(data->value);
CLAMP(temp, softmin, softmax);
@@ -3810,11 +4445,11 @@ static int ui_do_but_SLI(bContext *C, uiBlock *block, uiBut *but, uiHandleButton
/* XXX hardcoded keymap check.... */
if (type == MOUSEPAN && event->alt)
retval = WM_UI_HANDLER_BREAK; /* allow accumulating values, otherwise scrolling gets preference */
- else if (type == WHEELDOWNMOUSE && event->alt) {
+ else if (type == WHEELDOWNMOUSE && event->ctrl) {
mx = but->rect.xmin;
click = 2;
}
- else if (type == WHEELUPMOUSE && event->alt) {
+ else if (type == WHEELUPMOUSE && event->ctrl) {
mx = but->rect.xmax;
click = 2;
}
@@ -3823,7 +4458,8 @@ static int ui_do_but_SLI(bContext *C, uiBlock *block, uiBut *but, uiHandleButton
button_activate_state(C, but, BUTTON_STATE_TEXT_EDITING);
retval = WM_UI_HANDLER_BREAK;
}
- /* alt-click on sides to get "arrows" like in NUM buttons, and match wheel usage above */
+#ifndef USE_ALLSELECT
+ /* alt-click on sides to get "arrows" like in UI_BTYPE_NUM buttons, and match wheel usage above */
else if (event->type == LEFTMOUSE && event->alt) {
int halfpos = BLI_rctf_cent_x(&but->rect);
click = 2;
@@ -3832,6 +4468,7 @@ static int ui_do_but_SLI(bContext *C, uiBlock *block, uiBut *but, uiHandleButton
else
mx = but->rect.xmax;
}
+#endif
else if (event->type == LEFTMOUSE) {
data->dragstartx = mx;
data->draglastx = mx;
@@ -3877,7 +4514,7 @@ static int ui_do_but_SLI(bContext *C, uiBlock *block, uiBut *but, uiHandleButton
click = 1;
}
}
- else if (event->type == MOUSEMOVE) {
+ else if ((event->type == MOUSEMOVE) || ui_event_is_snap(event)) {
#ifdef USE_DRAG_MULTINUM
data->multi_data.drag_dir[0] += abs(data->draglastx - mx);
data->multi_data.drag_dir[1] += abs(data->draglasty - my);
@@ -3931,7 +4568,7 @@ static int ui_do_but_SLI(bContext *C, uiBlock *block, uiBut *but, uiHandleButton
f = softmin + f * softrange;
- if (!ui_is_but_float(but)) {
+ if (!ui_but_is_float(but)) {
if (f < temp) temp--;
else temp++;
@@ -4097,7 +4734,7 @@ static int ui_do_but_BLOCK(bContext *C, uiBut *but, uiHandleButtonData *data, co
/* first handle click on icondrag type button */
if (event->type == LEFTMOUSE && but->dragpoin && event->val == KM_PRESS) {
- if (ui_but_mouse_inside_icon(but, data->region, event)) {
+ if (ui_but_contains_point_px_icon(but, data->region, event)) {
button_activate_state(C, but, BUTTON_STATE_WAIT_DRAG);
data->dragstartx = event->x;
data->dragstarty = event->y;
@@ -4105,7 +4742,7 @@ static int ui_do_but_BLOCK(bContext *C, uiBut *but, uiHandleButtonData *data, co
}
}
#ifdef USE_DRAG_TOGGLE
- if (event->type == LEFTMOUSE && event->val == KM_PRESS && (ui_is_but_drag_toggle(but))) {
+ if (event->type == LEFTMOUSE && event->val == KM_PRESS && (ui_but_is_drag_toggle(but))) {
button_activate_state(C, but, BUTTON_STATE_WAIT_DRAG);
data->dragstartx = event->x;
data->dragstarty = event->y;
@@ -4117,14 +4754,14 @@ static int ui_do_but_BLOCK(bContext *C, uiBut *but, uiHandleButtonData *data, co
button_activate_state(C, but, BUTTON_STATE_MENU_OPEN);
return WM_UI_HANDLER_BREAK;
}
- else if (but->type == MENU) {
- if (ELEM(event->type, WHEELDOWNMOUSE, WHEELUPMOUSE) && event->alt) {
+ else if (but->type == UI_BTYPE_MENU) {
+ if (ELEM(event->type, WHEELDOWNMOUSE, WHEELUPMOUSE) && event->ctrl) {
const int direction = (event->type == WHEELDOWNMOUSE) ? -1 : 1;
- data->value = ui_step_name_menu(but, direction);
+ data->value = ui_but_menu_step(but, direction);
button_activate_state(C, but, BUTTON_STATE_EXIT);
- ui_apply_button(C, but->block, but, data, true);
+ ui_apply_but(C, but->block, but, data, true);
/* button's state need to be changed to EXIT so moving mouse away from this mouse wouldn't lead
* to cancel changes made to this button, but changing state to EXIT also makes no button active for
@@ -4153,12 +4790,12 @@ static int ui_do_but_BLOCK(bContext *C, uiBut *but, uiHandleButtonData *data, co
else if (data->state == BUTTON_STATE_WAIT_DRAG) {
/* this function also ends state */
- if (ui_but_start_drag(C, but, data, event)) {
+ if (ui_but_drag_init(C, but, data, event)) {
return WM_UI_HANDLER_BREAK;
}
/* outside icon quit, not needed if drag activated */
- if (0 == ui_but_mouse_inside_icon(but, data->region, event)) {
+ if (0 == ui_but_contains_point_px_icon(but, data->region, event)) {
button_activate_state(C, but, BUTTON_STATE_EXIT);
data->cancel = true;
return WM_UI_HANDLER_BREAK;
@@ -4174,9 +4811,10 @@ static int ui_do_but_BLOCK(bContext *C, uiBut *but, uiHandleButtonData *data, co
return WM_UI_HANDLER_CONTINUE;
}
-static bool ui_numedit_but_NORMAL(uiBut *but, uiHandleButtonData *data,
- int mx, int my,
- const enum eSnapType snap)
+static bool ui_numedit_but_UNITVEC(
+ uiBut *but, uiHandleButtonData *data,
+ int mx, int my,
+ const enum eSnapType snap)
{
float dx, dy, rad, radsq, mrad, *fp;
int mdx, mdy;
@@ -4242,7 +4880,7 @@ static bool ui_numedit_but_NORMAL(uiBut *but, uiHandleButtonData *data,
* do this in "angle" space - this gives increments of same size */
for (i = 0; i < 3; i++) {
angle = asinf(fp[i]);
- angle_snap = floorf(0.5f + (angle / snap_steps_angle)) * snap_steps_angle;
+ angle_snap = roundf((angle / snap_steps_angle)) * snap_steps_angle;
fp[i] = sinf(angle_snap);
}
normalize_v3(fp);
@@ -4270,7 +4908,7 @@ static int ui_do_but_COLOR(bContext *C, uiBut *but, uiHandleButtonData *data, co
/* first handle click on icondrag type button */
if (event->type == LEFTMOUSE && but->dragpoin && event->val == KM_PRESS) {
ui_palette_set_active(but);
- if (ui_but_mouse_inside_icon(but, data->region, event)) {
+ if (ui_but_contains_point_px_icon(but, data->region, event)) {
button_activate_state(C, but, BUTTON_STATE_WAIT_DRAG);
data->dragstartx = event->x;
data->dragstarty = event->y;
@@ -4292,11 +4930,13 @@ static int ui_do_but_COLOR(bContext *C, uiBut *but, uiHandleButtonData *data, co
button_activate_state(C, but, BUTTON_STATE_MENU_OPEN);
return WM_UI_HANDLER_BREAK;
}
- else if (ELEM(event->type, MOUSEPAN, WHEELDOWNMOUSE, WHEELUPMOUSE) && event->alt) {
- float *hsv = ui_block_hsv_get(but->block);
+ else if (ELEM(event->type, MOUSEPAN, WHEELDOWNMOUSE, WHEELUPMOUSE) && event->ctrl) {
+ ColorPicker *cpicker = but->custom_data;
+ float hsv_static[3] = {0.0f};
+ float *hsv = cpicker ? cpicker->color_data : hsv_static;
float col[3];
- ui_get_but_vectorf(but, col);
+ ui_but_v3_get(but, col);
rgb_to_hsv_compat_v(col, hsv);
if (event->type == WHEELDOWNMOUSE)
@@ -4309,10 +4949,10 @@ static int ui_do_but_COLOR(bContext *C, uiBut *but, uiHandleButtonData *data, co
}
hsv_to_rgb_v(hsv, data->vec);
- ui_set_but_vectorf(but, data->vec);
+ ui_but_v3_set(but, data->vec);
button_activate_state(C, but, BUTTON_STATE_EXIT);
- ui_apply_button(C, but->block, but, data, true);
+ ui_apply_but(C, but->block, but, data, true);
return WM_UI_HANDLER_BREAK;
}
else if ((int)(but->a1) == UI_PALETTE_COLOR &&
@@ -4324,18 +4964,24 @@ static int ui_do_but_COLOR(bContext *C, uiBut *but, uiHandleButtonData *data, co
BKE_palette_color_remove(palette, color);
button_activate_state(C, but, BUTTON_STATE_EXIT);
+
+ /* this is risky. it works OK for now,
+ * but if it gives trouble we should delay execution */
+ but->rnapoin = PointerRNA_NULL;
+ but->rnaprop = NULL;
+
return WM_UI_HANDLER_BREAK;
}
}
else if (data->state == BUTTON_STATE_WAIT_DRAG) {
/* this function also ends state */
- if (ui_but_start_drag(C, but, data, event)) {
+ if (ui_but_drag_init(C, but, data, event)) {
return WM_UI_HANDLER_BREAK;
}
/* outside icon quit, not needed if drag activated */
- if (0 == ui_but_mouse_inside_icon(but, data->region, event)) {
+ if (0 == ui_but_contains_point_px_icon(but, data->region, event)) {
button_activate_state(C, but, BUTTON_STATE_EXIT);
data->cancel = true;
return WM_UI_HANDLER_BREAK;
@@ -4354,7 +5000,7 @@ static int ui_do_but_COLOR(bContext *C, uiBut *but, uiHandleButtonData *data, co
if (but->rnaprop && RNA_property_subtype(but->rnaprop) == PROP_COLOR_GAMMA) {
RNA_property_float_get_array(&but->rnapoin, but->rnaprop, target);
- ui_block_to_scene_linear_v3(but->block, target);
+ ui_block_cm_to_scene_linear_v3(but->block, target);
}
else if (but->rnaprop && RNA_property_subtype(but->rnaprop) == PROP_COLOR) {
RNA_property_float_get_array(&but->rnapoin, but->rnaprop, target);
@@ -4367,7 +5013,7 @@ static int ui_do_but_COLOR(bContext *C, uiBut *but, uiHandleButtonData *data, co
}
else if (but->rnaprop && RNA_property_subtype(but->rnaprop) == PROP_COLOR) {
RNA_property_float_get_array(&but->rnapoin, but->rnaprop, color);
- ui_block_to_display_space_v3(but->block, color);
+ ui_block_cm_to_display_space_v3(but->block, color);
BKE_brush_color_set(scene, brush, color);
}
}
@@ -4389,7 +5035,7 @@ static int ui_do_but_COLOR(bContext *C, uiBut *but, uiHandleButtonData *data, co
return WM_UI_HANDLER_CONTINUE;
}
-static int ui_do_but_NORMAL(bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, const wmEvent *event)
+static int ui_do_but_UNITVEC(bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, const wmEvent *event)
{
int mx, my;
@@ -4407,17 +5053,17 @@ static int ui_do_but_NORMAL(bContext *C, uiBlock *block, uiBut *but, uiHandleBut
button_activate_state(C, but, BUTTON_STATE_NUM_EDITING);
/* also do drag the first time */
- if (ui_numedit_but_NORMAL(but, data, mx, my, snap))
+ if (ui_numedit_but_UNITVEC(but, data, mx, my, snap))
ui_numedit_apply(C, block, but, data);
return WM_UI_HANDLER_BREAK;
}
}
else if (data->state == BUTTON_STATE_NUM_EDITING) {
- if (event->type == MOUSEMOVE) {
- if (mx != data->draglastx || my != data->draglasty) {
+ if ((event->type == MOUSEMOVE) || ui_event_is_snap(event)) {
+ if (mx != data->draglastx || my != data->draglasty || event->type != MOUSEMOVE) {
const enum eSnapType snap = ui_event_to_snap(event);
- if (ui_numedit_but_NORMAL(but, data, mx, my, snap))
+ if (ui_numedit_but_UNITVEC(but, data, mx, my, snap))
ui_numedit_apply(C, block, but, data);
}
}
@@ -4468,21 +5114,23 @@ static void ui_color_picker_to_rgb_HSVCUBE_v(uiBut *but, const float hsv[3], flo
hsv_to_rgb_v(hsv, rgb);
}
-static bool ui_numedit_but_HSVCUBE(uiBut *but, uiHandleButtonData *data,
- int mx, int my,
- const enum eSnapType snap, const bool shift)
+static bool ui_numedit_but_HSVCUBE(
+ uiBut *but, uiHandleButtonData *data,
+ int mx, int my,
+ const enum eSnapType snap, const bool shift)
{
+ ColorPicker *cpicker = but->custom_data;
+ float *hsv = cpicker->color_data;
float rgb[3];
- float *hsv = ui_block_hsv_get(but->block);
float x, y;
float mx_fl, my_fl;
bool changed = true;
- bool use_display_colorspace = ui_color_picker_use_display_colorspace(but);
+ bool use_display_colorspace = ui_but_is_colorpicker_display_space(but);
ui_mouse_scale_warp(data, mx, my, &mx_fl, &my_fl, shift);
#ifdef USE_CONT_MOUSE_CORRECT
- if (ui_is_a_warp_but(but)) {
+ if (ui_but_is_cursor_warp(but)) {
/* OK but can go outside bounds */
data->ungrab_mval[0] = mx_fl;
data->ungrab_mval[1] = my_fl;
@@ -4490,10 +5138,10 @@ static bool ui_numedit_but_HSVCUBE(uiBut *but, uiHandleButtonData *data,
}
#endif
- ui_get_but_vectorf(but, rgb);
+ ui_but_v3_get(but, rgb);
if (use_display_colorspace)
- ui_block_to_display_space_v3(but->block, rgb);
+ ui_block_cm_to_display_space_v3(but->block, rgb);
ui_rgb_to_color_picker_HSVCUBE_compat_v(but, rgb, hsv);
@@ -4507,9 +5155,9 @@ static bool ui_numedit_but_HSVCUBE(uiBut *but, uiHandleButtonData *data,
/* calculate original hsv again */
copy_v3_v3(rgb, data->origvec);
if (use_display_colorspace)
- ui_block_to_display_space_v3(but->block, rgb);
+ ui_block_cm_to_display_space_v3(but->block, rgb);
- copy_v3_v3(hsvo, ui_block_hsv_get(but->block));
+ copy_v3_v3(hsvo, hsv);
ui_rgb_to_color_picker_HSVCUBE_compat_v(but, rgb, hsvo);
@@ -4528,8 +5176,8 @@ static bool ui_numedit_but_HSVCUBE(uiBut *but, uiHandleButtonData *data,
switch ((int)but->a1) {
case UI_GRAD_SV:
- hsv[2] = x;
- hsv[1] = y;
+ hsv[1] = x;
+ hsv[2] = y;
break;
case UI_GRAD_HV:
hsv[0] = x;
@@ -4552,11 +5200,16 @@ static bool ui_numedit_but_HSVCUBE(uiBut *but, uiHandleButtonData *data,
hsv[2] = y;
break;
case UI_GRAD_V_ALT:
+ {
/* vertical 'value' strip */
-
+ float min = but->softmin, max = but->softmax;
+ if (use_display_colorspace) {
+ ui_block_cm_to_display_space_range(but->block, &min, &max);
+ }
/* exception only for value strip - use the range set in but->min/max */
- hsv[2] = y * (but->softmax - but->softmin) + but->softmin;
+ hsv[2] = y * (max - min) + min;
break;
+ }
default:
BLI_assert(0);
break;
@@ -4571,7 +5224,7 @@ static bool ui_numedit_but_HSVCUBE(uiBut *but, uiHandleButtonData *data,
ui_color_picker_to_rgb_HSVCUBE_v(but, hsv, rgb);
if (use_display_colorspace)
- ui_block_to_scene_linear_v3(but->block, rgb);
+ ui_block_cm_to_scene_linear_v3(but->block, rgb);
/* clamp because with color conversion we can exceed range [#34295] */
if (but->a1 == UI_GRAD_V_ALT) {
@@ -4586,27 +5239,29 @@ static bool ui_numedit_but_HSVCUBE(uiBut *but, uiHandleButtonData *data,
return changed;
}
-static void ui_ndofedit_but_HSVCUBE(uiBut *but, uiHandleButtonData *data,
- const wmNDOFMotionData *ndof,
- const enum eSnapType snap, const bool shift)
+static void ui_ndofedit_but_HSVCUBE(
+ uiBut *but, uiHandleButtonData *data,
+ const wmNDOFMotionData *ndof,
+ const enum eSnapType snap, const bool shift)
{
- float *hsv = ui_block_hsv_get(but->block);
+ ColorPicker *cpicker = but->custom_data;
+ float *hsv = cpicker->color_data;
const float hsv_v_max = max_ff(hsv[2], but->softmax);
float rgb[3];
float sensitivity = (shift ? 0.15f : 0.3f) * ndof->dt;
- bool use_display_colorspace = ui_color_picker_use_display_colorspace(but);
+ bool use_display_colorspace = ui_but_is_colorpicker_display_space(but);
- ui_get_but_vectorf(but, rgb);
+ ui_but_v3_get(but, rgb);
if (use_display_colorspace)
- ui_block_to_display_space_v3(but->block, rgb);
+ ui_block_cm_to_display_space_v3(but->block, rgb);
ui_rgb_to_color_picker_HSVCUBE_compat_v(but, rgb, hsv);
switch ((int)but->a1) {
case UI_GRAD_SV:
- hsv[2] += ndof->rvec[2] * sensitivity;
- hsv[1] += ndof->rvec[0] * sensitivity;
+ hsv[1] += ndof->rvec[2] * sensitivity;
+ hsv[2] += ndof->rvec[0] * sensitivity;
break;
case UI_GRAD_HV:
hsv[0] += ndof->rvec[2] * sensitivity;
@@ -4651,10 +5306,10 @@ static void ui_ndofedit_but_HSVCUBE(uiBut *but, uiHandleButtonData *data,
ui_color_picker_to_rgb_HSVCUBE_v(but, hsv, rgb);
if (use_display_colorspace)
- ui_block_to_scene_linear_v3(but->block, rgb);
+ ui_block_cm_to_scene_linear_v3(but->block, rgb);
copy_v3_v3(data->vec, rgb);
- ui_set_but_vectorf(but, data->vec);
+ ui_but_v3_set(but, data->vec);
}
static int ui_do_but_HSVCUBE(bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, const wmEvent *event)
@@ -4688,7 +5343,7 @@ static int ui_do_but_HSVCUBE(bContext *C, uiBlock *block, uiBut *but, uiHandleBu
ui_ndofedit_but_HSVCUBE(but, data, ndof, snap, event->shift != 0);
button_activate_state(C, but, BUTTON_STATE_EXIT);
- ui_apply_button(C, but->block, but, data, true);
+ ui_apply_but(C, but->block, but, data, true);
return WM_UI_HANDLER_BREAK;
}
@@ -4703,19 +5358,20 @@ static int ui_do_but_HSVCUBE(bContext *C, uiBlock *block, uiBut *but, uiHandleBu
if (ELEM(len, 3, 4)) {
float rgb[3], def_hsv[3];
float def[4];
- float *hsv = ui_block_hsv_get(but->block);
-
+ ColorPicker *cpicker = but->custom_data;
+ float *hsv = cpicker->color_data;
+
RNA_property_float_get_default_array(&but->rnapoin, but->rnaprop, def);
ui_rgb_to_color_picker_HSVCUBE_v(but, def, def_hsv);
- ui_get_but_vectorf(but, rgb);
+ ui_but_v3_get(but, rgb);
ui_rgb_to_color_picker_HSVCUBE_compat_v(but, rgb, hsv);
def_hsv[0] = hsv[0];
def_hsv[1] = hsv[1];
ui_color_picker_to_rgb_HSVCUBE_v(but, def_hsv, rgb);
- ui_set_but_vectorf(but, rgb);
+ ui_but_v3_set(but, rgb);
RNA_property_update(C, &but->rnapoin, but->rnaprop);
return WM_UI_HANDLER_BREAK;
@@ -4731,8 +5387,8 @@ static int ui_do_but_HSVCUBE(bContext *C, uiBlock *block, uiBut *but, uiHandleBu
button_activate_state(C, but, BUTTON_STATE_EXIT);
}
}
- else if (event->type == MOUSEMOVE) {
- if (mx != data->draglastx || my != data->draglasty) {
+ else if ((event->type == MOUSEMOVE) || ui_event_is_snap(event)) {
+ if (mx != data->draglastx || my != data->draglasty || event->type != MOUSEMOVE) {
const enum eSnapType snap = ui_event_to_snap(event);
if (ui_numedit_but_HSVCUBE(but, data, mx, my, snap, event->shift != 0))
@@ -4749,21 +5405,23 @@ static int ui_do_but_HSVCUBE(bContext *C, uiBlock *block, uiBut *but, uiHandleBu
return WM_UI_HANDLER_CONTINUE;
}
-static bool ui_numedit_but_HSVCIRCLE(uiBut *but, uiHandleButtonData *data,
- float mx, float my,
- const enum eSnapType snap, const bool shift)
+static bool ui_numedit_but_HSVCIRCLE(
+ uiBut *but, uiHandleButtonData *data,
+ float mx, float my,
+ const enum eSnapType snap, const bool shift)
{
rcti rect;
bool changed = true;
float mx_fl, my_fl;
float rgb[3];
- float *hsv = ui_block_hsv_get(but->block);
- bool use_display_colorspace = ui_color_picker_use_display_colorspace(but);
+ ColorPicker *cpicker = but->custom_data;
+ float *hsv = cpicker->color_data;
+ bool use_display_colorspace = ui_but_is_colorpicker_display_space(but);
ui_mouse_scale_warp(data, mx, my, &mx_fl, &my_fl, shift);
#ifdef USE_CONT_MOUSE_CORRECT
- if (ui_is_a_warp_but(but)) {
+ if (ui_but_is_cursor_warp(but)) {
/* OK but can go outside bounds */
data->ungrab_mval[0] = mx_fl;
data->ungrab_mval[1] = my_fl;
@@ -4780,9 +5438,9 @@ static bool ui_numedit_but_HSVCIRCLE(uiBut *but, uiHandleButtonData *data,
BLI_rcti_rctf_copy(&rect, &but->rect);
- ui_get_but_vectorf(but, rgb);
+ ui_but_v3_get(but, rgb);
if (use_display_colorspace)
- ui_block_to_display_space_v3(but->block, rgb);
+ ui_block_cm_to_display_space_v3(but->block, rgb);
ui_rgb_to_color_picker_compat_v(rgb, hsv);
@@ -4793,8 +5451,8 @@ static bool ui_numedit_but_HSVCIRCLE(uiBut *but, uiHandleButtonData *data,
if (hsv[2] == 0.f) hsv[2] = 0.0001f;
}
else {
- if (hsv[2] == 0.f) hsv[2] = 0.0001f;
- if (hsv[2] == 1.f) hsv[2] = 0.9999f;
+ if (hsv[2] == 0.0f) hsv[2] = 0.0001f;
+ if (hsv[2] >= 0.9999f) hsv[2] = 0.9999f;
}
}
@@ -4803,10 +5461,10 @@ static bool ui_numedit_but_HSVCIRCLE(uiBut *but, uiHandleButtonData *data,
float xpos, ypos, hsvo[3], rgbo[3];
/* calculate original hsv again */
- copy_v3_v3(hsvo, ui_block_hsv_get(but->block));
+ copy_v3_v3(hsvo, hsv);
copy_v3_v3(rgbo, data->origvec);
if (use_display_colorspace)
- ui_block_to_display_space_v3(but->block, rgbo);
+ ui_block_cm_to_display_space_v3(but->block, rgbo);
ui_rgb_to_color_picker_compat_v(rgbo, hsvo);
@@ -4835,9 +5493,9 @@ static bool ui_numedit_but_HSVCIRCLE(uiBut *but, uiHandleButtonData *data,
}
if (use_display_colorspace)
- ui_block_to_scene_linear_v3(but->block, rgb);
+ ui_block_cm_to_scene_linear_v3(but->block, rgb);
- ui_set_but_vectorf(but, rgb);
+ ui_but_v3_set(but, rgb);
data->draglastx = mx;
data->draglasty = my;
@@ -4845,19 +5503,21 @@ static bool ui_numedit_but_HSVCIRCLE(uiBut *but, uiHandleButtonData *data,
return changed;
}
-static void ui_ndofedit_but_HSVCIRCLE(uiBut *but, uiHandleButtonData *data,
- const wmNDOFMotionData *ndof,
- const enum eSnapType snap, const bool shift)
+static void ui_ndofedit_but_HSVCIRCLE(
+ uiBut *but, uiHandleButtonData *data,
+ const wmNDOFMotionData *ndof,
+ const enum eSnapType snap, const bool shift)
{
- float *hsv = ui_block_hsv_get(but->block);
- bool use_display_colorspace = ui_color_picker_use_display_colorspace(but);
+ ColorPicker *cpicker = but->custom_data;
+ float *hsv = cpicker->color_data;
+ bool use_display_colorspace = ui_but_is_colorpicker_display_space(but);
float rgb[3];
float phi, r /*, sqr */ /* UNUSED */, v[2];
float sensitivity = (shift ? 0.06f : 0.3f) * ndof->dt;
- ui_get_but_vectorf(but, rgb);
+ ui_but_v3_get(but, rgb);
if (use_display_colorspace)
- ui_block_to_display_space_v3(but->block, rgb);
+ ui_block_cm_to_display_space_v3(but->block, rgb);
ui_rgb_to_color_picker_compat_v(rgb, hsv);
/* Convert current color on hue/sat disc to circular coordinates phi, r */
@@ -4910,14 +5570,16 @@ static void ui_ndofedit_but_HSVCIRCLE(uiBut *but, uiHandleButtonData *data,
}
if (use_display_colorspace)
- ui_block_to_scene_linear_v3(but->block, data->vec);
+ ui_block_cm_to_scene_linear_v3(but->block, data->vec);
- ui_set_but_vectorf(but, data->vec);
+ ui_but_v3_set(but, data->vec);
}
static int ui_do_but_HSVCIRCLE(bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, const wmEvent *event)
{
+ ColorPicker *cpicker = but->custom_data;
+ float *hsv = cpicker->color_data;
int mx, my;
mx = event->x;
my = event->y;
@@ -4945,7 +5607,7 @@ static int ui_do_but_HSVCIRCLE(bContext *C, uiBlock *block, uiBut *but, uiHandle
ui_ndofedit_but_HSVCIRCLE(but, data, ndof, snap, event->shift != 0);
button_activate_state(C, but, BUTTON_STATE_EXIT);
- ui_apply_button(C, but->block, but, data, true);
+ ui_apply_but(C, but->block, but, data, true);
return WM_UI_HANDLER_BREAK;
}
@@ -4959,20 +5621,19 @@ static int ui_do_but_HSVCIRCLE(bContext *C, uiBlock *block, uiBut *but, uiHandle
if (len >= 3) {
float rgb[3], def_hsv[3];
float *def;
- float *hsv = ui_block_hsv_get(but->block);
def = MEM_callocN(sizeof(float) * len, "reset_defaults - float");
RNA_property_float_get_default_array(&but->rnapoin, but->rnaprop, def);
ui_color_picker_to_rgb_v(def, def_hsv);
- ui_get_but_vectorf(but, rgb);
+ ui_but_v3_get(but, rgb);
ui_rgb_to_color_picker_compat_v(rgb, hsv);
def_hsv[0] = hsv[0];
def_hsv[2] = hsv[2];
hsv_to_rgb_v(def_hsv, rgb);
- ui_set_but_vectorf(but, rgb);
+ ui_but_v3_set(but, rgb);
RNA_property_update(C, &but->rnapoin, but->rnaprop);
@@ -4991,19 +5652,17 @@ static int ui_do_but_HSVCIRCLE(bContext *C, uiBlock *block, uiBut *but, uiHandle
}
/* XXX hardcoded keymap check.... */
else if (event->type == WHEELDOWNMOUSE) {
- float *hsv = ui_block_hsv_get(but->block);
hsv[2] = CLAMPIS(hsv[2] - 0.05f, 0.0f, 1.0f);
- ui_set_but_hsv(but); /* converts to rgb */
+ ui_but_hsv_set(but); /* converts to rgb */
ui_numedit_apply(C, block, but, data);
}
else if (event->type == WHEELUPMOUSE) {
- float *hsv = ui_block_hsv_get(but->block);
hsv[2] = CLAMPIS(hsv[2] + 0.05f, 0.0f, 1.0f);
- ui_set_but_hsv(but); /* converts to rgb */
+ ui_but_hsv_set(but); /* converts to rgb */
ui_numedit_apply(C, block, but, data);
}
- else if (event->type == MOUSEMOVE) {
- if (mx != data->draglastx || my != data->draglasty) {
+ else if ((event->type == MOUSEMOVE) || ui_event_is_snap(event)) {
+ if (mx != data->draglastx || my != data->draglasty || event->type != MOUSEMOVE) {
const enum eSnapType snap = ui_event_to_snap(event);
if (ui_numedit_but_HSVCIRCLE(but, data, mx, my, snap, event->shift != 0)) {
@@ -5049,7 +5708,9 @@ static int ui_do_but_COLORBAND(bContext *C, uiBlock *block, uiBut *but, uiHandle
{
ColorBand *coba;
CBData *cbd;
- int mx, my, a, xco, mindist = 12;
+ /* ignore zoom-level for mindist */
+ int mindist = (50 * UI_DPI_FAC) * block->aspect;
+ int mx, my, a, xco;
mx = event->x;
my = event->y;
@@ -5106,7 +5767,8 @@ static int ui_do_but_COLORBAND(bContext *C, uiBlock *block, uiBut *but, uiHandle
return WM_UI_HANDLER_CONTINUE;
}
-static bool ui_numedit_but_CURVE(uiBlock *block, uiBut *but, uiHandleButtonData *data,
+static bool ui_numedit_but_CURVE(
+ uiBlock *block, uiBut *but, uiHandleButtonData *data,
int evtx, int evty,
bool snap, const bool shift)
{
@@ -5156,8 +5818,8 @@ static bool ui_numedit_but_CURVE(uiBlock *block, uiBut *but, uiHandleButtonData
cmp[a].x += fx;
cmp[a].y += fy;
if (snap) {
- cmp[a].x = 0.125f * floorf(0.5f + 8.0f * cmp[a].x);
- cmp[a].y = 0.125f * floorf(0.5f + 8.0f * cmp[a].y);
+ cmp[a].x = 0.125f * roundf(8.0f * cmp[a].x);
+ cmp[a].y = 0.125f * roundf(8.0f * cmp[a].y);
}
if (cmp[a].x != origx || cmp[a].y != origy)
moved_point = true;
@@ -5176,7 +5838,7 @@ static bool ui_numedit_but_CURVE(uiBlock *block, uiBut *but, uiHandleButtonData
#ifdef USE_CONT_MOUSE_CORRECT
/* note: using 'cmp_last' is weak since there may be multiple points selected,
* but in practice this isnt really an issue */
- if (ui_is_a_warp_but(but)) {
+ if (ui_but_is_cursor_warp(but)) {
/* OK but can go outside bounds */
data->ungrab_mval[0] = but->rect.xmin + ((cmp_last->x - cumap->curr.xmin) * zoomx);
data->ungrab_mval[1] = but->rect.ymin + ((cmp_last->y - cumap->curr.ymin) * zoomy);
@@ -5374,7 +6036,7 @@ static bool ui_numedit_but_HISTOGRAM(uiBut *but, uiHandleButtonData *data, int m
float dy = my - data->draglasty;
/* scale histogram values (dy / 10 for better control) */
- const float yfac = min_ff(powf(hist->ymax, 2.0f), 1.0f) * 0.5f;
+ const float yfac = min_ff(pow2f(hist->ymax), 1.0f) * 0.5f;
hist->ymax += (dy * 0.1f) * yfac;
/* 0.1 allows us to see HDR colors up to 10 */
@@ -5540,9 +6202,10 @@ static int ui_do_but_LINK(bContext *C, uiBut *but, uiHandleButtonData *data, con
return WM_UI_HANDLER_CONTINUE;
}
-static bool ui_numedit_but_TRACKPREVIEW(bContext *C, uiBut *but, uiHandleButtonData *data,
- int mx, int my,
- const bool shift)
+static bool ui_numedit_but_TRACKPREVIEW(
+ bContext *C, uiBut *but, uiHandleButtonData *data,
+ int mx, int my,
+ const bool shift)
{
MovieClipScopes *scopes = (MovieClipScopes *)but->poin;
bool changed = true;
@@ -5632,7 +6295,7 @@ static void but_shortcut_name_func(bContext *C, void *arg1, int UNUSED(event))
/* complex code to change name of button */
if (WM_key_event_operator_string(C, but->optype->idname, but->opcontext, prop, true,
- shortcut_str, sizeof(shortcut_str)))
+ sizeof(shortcut_str), shortcut_str))
{
ui_but_add_shortcut(but, shortcut_str, true);
}
@@ -5652,7 +6315,7 @@ static uiBlock *menu_change_shortcut(bContext *C, ARegion *ar, void *arg)
wmKeyMapItem *kmi;
PointerRNA ptr;
uiLayout *layout;
- uiStyle *style = UI_GetStyleDraw();
+ uiStyle *style = UI_style_get_dpi();
IDProperty *prop = (but->opptr) ? but->opptr->data : NULL;
int kmi_id = WM_key_event_operator_id(C, but->optype->idname, but->opcontext, prop, true, &km);
@@ -5660,20 +6323,24 @@ static uiBlock *menu_change_shortcut(bContext *C, ARegion *ar, void *arg)
RNA_pointer_create(&wm->id, &RNA_KeyMapItem, kmi, &ptr);
- block = uiBeginBlock(C, ar, "_popup", UI_EMBOSS);
- uiBlockSetHandleFunc(block, but_shortcut_name_func, but);
- uiBlockSetFlag(block, UI_BLOCK_MOVEMOUSE_QUIT);
- uiBlockSetDirection(block, UI_CENTER);
+ block = UI_block_begin(C, ar, "_popup", UI_EMBOSS);
+ UI_block_func_handle_set(block, but_shortcut_name_func, but);
+ UI_block_flag_enable(block, UI_BLOCK_MOVEMOUSE_QUIT);
+ UI_block_direction_set(block, UI_DIR_CENTER_Y);
- layout = uiBlockLayout(block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, 0, 0, 200, 20, 0, style);
+ layout = UI_block_layout(block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, 0, 0, 200, 20, 0, style);
uiItemR(layout, &ptr, "type", UI_ITEM_R_FULL_EVENT | UI_ITEM_R_IMMEDIATE, "", ICON_NONE);
- uiPopupBoundsBlock(block, 6, -50, 26);
+ UI_block_bounds_set_popup(block, 6, -50, 26);
return block;
}
+#ifdef USE_KEYMAP_ADD_HACK
+static int g_kmi_id_hack;
+#endif
+
static uiBlock *menu_add_shortcut(bContext *C, ARegion *ar, void *arg)
{
wmWindowManager *wm = CTX_wm_manager(C);
@@ -5683,7 +6350,7 @@ static uiBlock *menu_add_shortcut(bContext *C, ARegion *ar, void *arg)
wmKeyMapItem *kmi;
PointerRNA ptr;
uiLayout *layout;
- uiStyle *style = UI_GetStyleDraw();
+ uiStyle *style = UI_style_get_dpi();
IDProperty *prop = (but->opptr) ? but->opptr->data : NULL;
int kmi_id;
@@ -5705,16 +6372,19 @@ static uiBlock *menu_add_shortcut(bContext *C, ARegion *ar, void *arg)
RNA_pointer_create(&wm->id, &RNA_KeyMapItem, kmi, &ptr);
- block = uiBeginBlock(C, ar, "_popup", UI_EMBOSS);
- uiBlockSetHandleFunc(block, but_shortcut_name_func, but);
- uiBlockSetDirection(block, UI_CENTER);
+ block = UI_block_begin(C, ar, "_popup", UI_EMBOSS);
+ UI_block_func_handle_set(block, but_shortcut_name_func, but);
+ UI_block_direction_set(block, UI_DIR_CENTER_Y);
- layout = uiBlockLayout(block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, 0, 0, 200, 20, 0, style);
+ layout = UI_block_layout(block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, 0, 0, 200, 20, 0, style);
uiItemR(layout, &ptr, "type", UI_ITEM_R_FULL_EVENT | UI_ITEM_R_IMMEDIATE, "", ICON_NONE);
- uiPopupBoundsBlock(block, 6, -50, 26);
-
+ UI_block_bounds_set_popup(block, 6, -50, 26);
+
+#ifdef USE_KEYMAP_ADD_HACK
+ g_kmi_id_hack = kmi_id;
+#endif
return block;
}
@@ -5723,9 +6393,20 @@ static void menu_add_shortcut_cancel(struct bContext *C, void *arg1)
uiBut *but = (uiBut *)arg1;
wmKeyMap *km;
wmKeyMapItem *kmi;
- IDProperty *prop = (but->opptr) ? but->opptr->data : NULL;
- int kmi_id = WM_key_event_operator_id(C, but->optype->idname, but->opcontext, prop, true, &km);
-
+#ifndef USE_KEYMAP_ADD_HACK
+ IDProperty *prop;
+#endif
+ int kmi_id;
+
+#ifdef USE_KEYMAP_ADD_HACK
+ km = WM_keymap_guess_opname(C, but->optype->idname);
+ kmi_id = g_kmi_id_hack;
+ UNUSED_VARS(but);
+#else
+ prop = (but->opptr) ? but->opptr->data : NULL;
+ kmi_id = WM_key_event_operator_id(C, but->optype->idname, but->opcontext, prop, true, &km);
+#endif
+
kmi = WM_keymap_item_find_id(km, kmi_id);
WM_keymap_remove_item(km, kmi);
}
@@ -5733,8 +6414,8 @@ static void menu_add_shortcut_cancel(struct bContext *C, void *arg1)
static void popup_change_shortcut_func(bContext *C, void *arg1, void *UNUSED(arg2))
{
uiBut *but = (uiBut *)arg1;
- button_timers_tooltip_remove(C, but);
- uiPupBlock(C, menu_change_shortcut, but);
+ UI_but_tooltip_timer_remove(C, but);
+ UI_popup_block_invoke(C, menu_change_shortcut, but);
}
static void remove_shortcut_func(bContext *C, void *arg1, void *UNUSED(arg2))
@@ -5754,8 +6435,8 @@ static void remove_shortcut_func(bContext *C, void *arg1, void *UNUSED(arg2))
static void popup_add_shortcut_func(bContext *C, void *arg1, void *UNUSED(arg2))
{
uiBut *but = (uiBut *)arg1;
- button_timers_tooltip_remove(C, but);
- uiPupBlockEx(C, menu_add_shortcut, NULL, menu_add_shortcut_cancel, but);
+ UI_but_tooltip_timer_remove(C, but);
+ UI_popup_block_ex(C, menu_add_shortcut, NULL, menu_add_shortcut_cancel, but);
}
/**
@@ -5770,8 +6451,8 @@ void ui_panel_menu(bContext *C, ARegion *ar, Panel *pa)
RNA_pointer_create(&sc->id, &RNA_Panel, pa, &ptr);
- pup = uiPupMenuBegin(C, IFACE_("Panel"), ICON_NONE);
- layout = uiPupMenuLayout(pup);
+ pup = UI_popup_menu_begin(C, IFACE_("Panel"), ICON_NONE);
+ layout = UI_popup_menu_layout(pup);
if (UI_panel_category_is_visible(ar)) {
char tmpstr[80];
BLI_snprintf(tmpstr, sizeof(tmpstr), "%s" UI_SEP_CHAR_S "%s", IFACE_("Pin"), IFACE_("Shift+Left Mouse"));
@@ -5785,7 +6466,7 @@ void ui_panel_menu(bContext *C, ARegion *ar, Panel *pa)
}
}
- uiPupMenuEnd(C, pup);
+ UI_popup_menu_end(C, pup);
}
static bool ui_but_menu(bContext *C, uiBut *but)
@@ -5799,17 +6480,17 @@ static bool ui_but_menu(bContext *C, uiBut *but)
/* return 0;*/
/* having this menu for some buttons makes no sense */
- if (but->type == BUT_IMAGE) {
+ if (but->type == UI_BTYPE_IMAGE) {
return false;
}
- button_timers_tooltip_remove(C, but);
+ UI_but_tooltip_timer_remove(C, but);
/* highly unlikely getting the label ever fails */
- uiButGetStrInfo(C, but, &label, NULL);
+ UI_but_string_info_get(C, but, &label, NULL);
- pup = uiPupMenuBegin(C, label.strinfo ? label.strinfo : "", ICON_NONE);
- layout = uiPupMenuLayout(pup);
+ pup = UI_popup_menu_begin(C, label.strinfo ? label.strinfo : "", ICON_NONE);
+ layout = UI_popup_menu_layout(pup);
if (label.strinfo)
MEM_freeN(label.strinfo);
@@ -5835,19 +6516,19 @@ static bool ui_but_menu(bContext *C, uiBut *but)
if (but->flag & UI_BUT_ANIMATED_KEY) {
/* replace/delete keyfraemes */
if (is_array_component) {
- uiItemBooleanO(layout, CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Replace Keyframes"),
+ uiItemBooleanO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Replace Keyframes"),
ICON_NONE, "ANIM_OT_keyframe_insert_button", "all", 1);
- uiItemBooleanO(layout, CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Replace Single Keyframe"),
+ uiItemBooleanO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Replace Single Keyframe"),
ICON_NONE, "ANIM_OT_keyframe_insert_button", "all", 0);
- uiItemBooleanO(layout, CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Delete Keyframes"),
+ uiItemBooleanO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Delete Keyframes"),
ICON_NONE, "ANIM_OT_keyframe_delete_button", "all", 1);
- uiItemBooleanO(layout, CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Delete Single Keyframe"),
+ uiItemBooleanO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Delete Single Keyframe"),
ICON_NONE, "ANIM_OT_keyframe_delete_button", "all", 0);
}
else {
- uiItemBooleanO(layout, CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Replace Keyframe"),
+ uiItemBooleanO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Replace Keyframe"),
ICON_NONE, "ANIM_OT_keyframe_insert_button", "all", 1);
- uiItemBooleanO(layout, CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Delete Keyframe"),
+ uiItemBooleanO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Delete Keyframe"),
ICON_NONE, "ANIM_OT_keyframe_delete_button", "all", 1);
}
@@ -5861,26 +6542,26 @@ static bool ui_but_menu(bContext *C, uiBut *but)
}
else if (is_anim) {
if (is_array_component) {
- uiItemBooleanO(layout, CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Insert Keyframes"),
+ uiItemBooleanO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Insert Keyframes"),
ICON_NONE, "ANIM_OT_keyframe_insert_button", "all", 1);
- uiItemBooleanO(layout, CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Insert Single Keyframe"),
+ uiItemBooleanO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Insert Single Keyframe"),
ICON_NONE, "ANIM_OT_keyframe_insert_button", "all", 0);
}
else {
- uiItemBooleanO(layout, CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Insert Keyframe"),
+ uiItemBooleanO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Insert Keyframe"),
ICON_NONE, "ANIM_OT_keyframe_insert_button", "all", 1);
}
}
- if (but->flag & UI_BUT_ANIMATED) {
+ if ((but->flag & UI_BUT_ANIMATED) && (but->rnapoin.type != &RNA_NlaStrip)) {
if (is_array_component) {
- uiItemBooleanO(layout, CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Clear Keyframes"),
+ uiItemBooleanO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Clear Keyframes"),
ICON_NONE, "ANIM_OT_keyframe_clear_button", "all", 1);
- uiItemBooleanO(layout, CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Clear Single Keyframes"),
+ uiItemBooleanO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Clear Single Keyframes"),
ICON_NONE, "ANIM_OT_keyframe_clear_button", "all", 0);
}
else {
- uiItemBooleanO(layout, CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Clear Keyframes"),
+ uiItemBooleanO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Clear Keyframes"),
ICON_NONE, "ANIM_OT_keyframe_clear_button", "all", 1);
}
}
@@ -5890,20 +6571,20 @@ static bool ui_but_menu(bContext *C, uiBut *but)
uiItemS(layout);
if (is_array_component) {
- uiItemBooleanO(layout, CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Delete Drivers"),
+ uiItemBooleanO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Delete Drivers"),
ICON_NONE, "ANIM_OT_driver_button_remove", "all", 1);
- uiItemBooleanO(layout, CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Delete Single Driver"),
+ uiItemBooleanO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Delete Single Driver"),
ICON_NONE, "ANIM_OT_driver_button_remove", "all", 0);
}
else {
- uiItemBooleanO(layout, CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Delete Driver"),
+ uiItemBooleanO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Delete Driver"),
ICON_NONE, "ANIM_OT_driver_button_remove", "all", 1);
}
- uiItemO(layout, CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Copy Driver"),
+ uiItemO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Copy Driver"),
ICON_NONE, "ANIM_OT_copy_driver_button");
if (ANIM_driver_can_paste()) {
- uiItemO(layout, CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Paste Driver"),
+ uiItemO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Paste Driver"),
ICON_NONE, "ANIM_OT_paste_driver_button");
}
}
@@ -5914,18 +6595,18 @@ static bool ui_but_menu(bContext *C, uiBut *but)
uiItemS(layout);
if (is_array_component) {
- uiItemBooleanO(layout, CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Add Drivers"),
+ uiItemBooleanO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Add Drivers"),
ICON_NONE, "ANIM_OT_driver_button_add", "all", 1);
- uiItemBooleanO(layout, CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Add Single Driver"),
+ uiItemBooleanO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Add Single Driver"),
ICON_NONE, "ANIM_OT_driver_button_add", "all", 0);
}
else {
- uiItemBooleanO(layout, CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Add Driver"),
+ uiItemBooleanO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Add Driver"),
ICON_NONE, "ANIM_OT_driver_button_add", "all", 1);
}
if (ANIM_driver_can_paste()) {
- uiItemO(layout, CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Paste Driver"),
+ uiItemO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Paste Driver"),
ICON_NONE, "ANIM_OT_paste_driver_button");
}
}
@@ -5936,17 +6617,17 @@ static bool ui_but_menu(bContext *C, uiBut *but)
uiItemS(layout);
if (is_array_component) {
- uiItemBooleanO(layout, CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Add All to Keying Set"),
+ uiItemBooleanO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Add All to Keying Set"),
ICON_NONE, "ANIM_OT_keyingset_button_add", "all", 1);
- uiItemBooleanO(layout, CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Add Single to Keying Set"),
+ uiItemBooleanO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Add Single to Keying Set"),
ICON_NONE, "ANIM_OT_keyingset_button_add", "all", 0);
- uiItemO(layout, CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Remove from Keying Set"),
+ uiItemO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Remove from Keying Set"),
ICON_NONE, "ANIM_OT_keyingset_button_remove");
}
else {
- uiItemBooleanO(layout, CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Add to Keying Set"),
+ uiItemBooleanO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Add to Keying Set"),
ICON_NONE, "ANIM_OT_keyingset_button_add", "all", 1);
- uiItemO(layout, CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Remove from Keying Set"),
+ uiItemO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Remove from Keying Set"),
ICON_NONE, "ANIM_OT_keyingset_button_remove");
}
}
@@ -5959,23 +6640,23 @@ static bool ui_but_menu(bContext *C, uiBut *but)
* Paste Property Value */
if (is_array_component) {
- uiItemBooleanO(layout, CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Reset All to Default Values"),
+ uiItemBooleanO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Reset All to Default Values"),
ICON_NONE, "UI_OT_reset_default_button", "all", 1);
- uiItemBooleanO(layout, CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Reset Single to Default Value"),
+ uiItemBooleanO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Reset Single to Default Value"),
ICON_NONE, "UI_OT_reset_default_button", "all", 0);
}
else {
- uiItemBooleanO(layout, CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Reset to Default Value"),
+ uiItemBooleanO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Reset to Default Value"),
ICON_NONE, "UI_OT_reset_default_button", "all", 1);
}
if (is_editable /*&& is_idprop*/ && is_set) {
- uiItemO(layout, CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Unset"),
+ uiItemO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Unset"),
ICON_NONE, "UI_OT_unset_property_button");
}
- uiItemO(layout, CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Copy Data Path"),
+ uiItemO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Copy Data Path"),
ICON_NONE, "UI_OT_copy_data_path_button");
- uiItemO(layout, CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Copy To Selected"),
+ uiItemO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Copy To Selected"),
ICON_NONE, "UI_OT_copy_to_selected_button");
uiItemS(layout);
@@ -6000,26 +6681,26 @@ static bool ui_but_menu(bContext *C, uiBut *but)
/* would rather use a block but, but gets weirdly positioned... */
//uiDefBlockBut(block, menu_change_shortcut, but, "Change Shortcut", 0, 0, uiLayoutGetWidth(layout), UI_UNIT_Y, "");
- but2 = uiDefIconTextBut(block, BUT, 0, 0, CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Change Shortcut"),
+ but2 = uiDefIconTextBut(block, UI_BTYPE_BUT, 0, 0, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Change Shortcut"),
0, 0, w, UI_UNIT_Y, NULL, 0, 0, 0, 0, "");
- uiButSetFunc(but2, popup_change_shortcut_func, but, NULL);
+ UI_but_func_set(but2, popup_change_shortcut_func, but, NULL);
- but2 = uiDefIconTextBut(block, BUT, 0, 0, CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Remove Shortcut"),
+ but2 = uiDefIconTextBut(block, UI_BTYPE_BUT, 0, 0, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Remove Shortcut"),
0, 0, w, UI_UNIT_Y, NULL, 0, 0, 0, 0, "");
- uiButSetFunc(but2, remove_shortcut_func, but, NULL);
+ UI_but_func_set(but2, remove_shortcut_func, but, NULL);
}
/* only show 'add' if there's a suitable key map for it to go in */
else if (WM_keymap_guess_opname(C, but->optype->idname)) {
- but2 = uiDefIconTextBut(block, BUT, 0, 0, CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Add Shortcut"),
+ but2 = uiDefIconTextBut(block, UI_BTYPE_BUT, 0, 0, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Add Shortcut"),
0, 0, w, UI_UNIT_Y, NULL, 0, 0, 0, 0, "");
- uiButSetFunc(but2, popup_add_shortcut_func, but, NULL);
+ UI_but_func_set(but2, popup_add_shortcut_func, but, NULL);
}
uiItemS(layout);
}
/* Show header tools for header buttons. */
- {
+ if (ui_block_is_menu(but->block) == false) {
ARegion *ar = CTX_wm_region(C);
if (ar && (ar->regiontype == RGN_TYPE_HEADER)) {
uiItemMenuF(layout, IFACE_("Header"), ICON_NONE, ED_screens_header_tools_menu_create, NULL);
@@ -6031,18 +6712,13 @@ static bool ui_but_menu(bContext *C, uiBut *but)
char buf[512];
PointerRNA ptr_props;
- if (but->rnapoin.data && but->rnaprop) {
- BLI_snprintf(buf, sizeof(buf), "%s.%s",
- RNA_struct_identifier(but->rnapoin.type), RNA_property_identifier(but->rnaprop));
-
- WM_operator_properties_create(&ptr_props, "WM_OT_doc_view_manual");
- RNA_string_set(&ptr_props, "doc_id", buf);
- uiItemFullO(layout, "WM_OT_doc_view_manual", CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Online Manual"),
- ICON_NONE, ptr_props.data, WM_OP_EXEC_DEFAULT, 0);
+ if (UI_but_online_manual_id(but, buf, sizeof(buf))) {
+ uiItemO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Online Manual"),
+ ICON_NONE, "WM_OT_doc_view_manual_ui_context");
WM_operator_properties_create(&ptr_props, "WM_OT_doc_view");
RNA_string_set(&ptr_props, "doc_id", buf);
- uiItemFullO(layout, "WM_OT_doc_view", CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Online Python Reference"),
+ uiItemFullO(layout, "WM_OT_doc_view", CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Online Python Reference"),
ICON_NONE, ptr_props.data, WM_OP_EXEC_DEFAULT, 0);
/* XXX inactive option, not for public! */
@@ -6054,30 +6730,6 @@ static bool ui_but_menu(bContext *C, uiBut *but)
uiItemFullO(layout, "WM_OT_doc_edit", "Submit Description", ICON_NONE, ptr_props.data, WM_OP_INVOKE_DEFAULT, 0);
#endif
}
- else if (but->optype) {
- WM_operator_py_idname(buf, but->optype->idname);
-
-
- WM_operator_properties_create(&ptr_props, "WM_OT_doc_view_manual");
- RNA_string_set(&ptr_props, "doc_id", buf);
- uiItemFullO(layout, "WM_OT_doc_view_manual", CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Online Manual"),
- ICON_NONE, ptr_props.data, WM_OP_EXEC_DEFAULT, 0);
-
- WM_operator_properties_create(&ptr_props, "WM_OT_doc_view");
- RNA_string_set(&ptr_props, "doc_id", buf);
- uiItemFullO(layout, "WM_OT_doc_view", CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Online Python Reference"),
- ICON_NONE, ptr_props.data, WM_OP_EXEC_DEFAULT, 0);
-
- /* XXX inactive option, not for public! */
-#if 0
- WM_operator_properties_create(&ptr_props, "WM_OT_doc_edit");
- RNA_string_set(&ptr_props, "doc_id", buf);
- RNA_string_set(&ptr_props, "doc_new", but->optype->description);
-
- uiItemFullO(layout, "WM_OT_doc_edit", CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Submit Description"),
- ICON_NONE, ptr_props.data, WM_OP_INVOKE_DEFAULT, 0);
-#endif
- }
}
/* perhaps we should move this into (G.debug & G_DEBUG) - campbell */
@@ -6086,7 +6738,7 @@ static bool ui_but_menu(bContext *C, uiBut *but)
}
uiItemFullO(layout, "UI_OT_edittranslation_init", NULL, ICON_NONE, NULL, WM_OP_INVOKE_DEFAULT, 0);
- uiPupMenuEnd(C, pup);
+ UI_popup_menu_end(C, pup);
return true;
}
@@ -6104,9 +6756,11 @@ 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)) {
+ if (ELEM(event->type, CKEY, VKEY) && event->val == KM_PRESS &&
+ IS_EVENT_MOD(event, ctrl, oskey))
+ {
/* Specific handling for listrows, we try to find their overlapping tex button. */
- if (but->type == LISTROW) {
+ if (but->type == UI_BTYPE_LISTROW) {
uiBut *labelbut = ui_but_list_row_text_activate(C, but, data, event, BUTTON_ACTIVATE_OVER);
if (labelbut) {
but = labelbut;
@@ -6123,15 +6777,17 @@ static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, const wmEvent *
}
/* handle eyedropper */
else if ((event->type == EKEY) && (event->val == KM_PRESS)) {
- if (event->alt || event->shift || event->ctrl || event->oskey) {
+ if (IS_EVENT_MOD(event, shift, ctrl, alt, oskey)) {
/* pass */
}
else {
- if (but->type == COLOR) {
+ if (but->type == UI_BTYPE_COLOR) {
WM_operator_name_call(C, "UI_OT_eyedropper_color", WM_OP_INVOKE_DEFAULT, NULL);
return WM_UI_HANDLER_BREAK;
}
- else if (but->type == SEARCH_MENU_UNLINK) {
+ else if ((but->type == UI_BTYPE_SEARCH_MENU) &&
+ (but->flag & UI_BUT_SEARCH_UNLINK))
+ {
if (but->rnaprop && RNA_property_type(but->rnaprop) == PROP_POINTER) {
StructRNA *type = RNA_property_pointer_type(&but->rnapoin, but->rnaprop);
const short idcode = RNA_type_to_ID_code(type);
@@ -6141,11 +6797,21 @@ static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, const wmEvent *
}
}
}
+ else if (but->type == UI_BTYPE_NUM) {
+ if (but->rnaprop &&
+ (RNA_property_type(but->rnaprop) == PROP_FLOAT) &&
+ (RNA_property_subtype(but->rnaprop) & PROP_UNIT_LENGTH) &&
+ (RNA_property_array_check(but->rnaprop) == false))
+ {
+ WM_operator_name_call(C, "UI_OT_eyedropper_depth", WM_OP_INVOKE_DEFAULT, NULL);
+ return WM_UI_HANDLER_BREAK;
+ }
+ }
}
}
/* handle keyframing */
else if ((event->type == IKEY) &&
- !ELEM(KM_MOD_FIRST, event->ctrl, event->oskey) &&
+ !IS_EVENT_MOD(event, ctrl, oskey) &&
(event->val == KM_PRESS))
{
if (event->alt) {
@@ -6166,7 +6832,7 @@ static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, const wmEvent *
}
/* handle drivers */
else if ((event->type == DKEY) &&
- !ELEM(KM_MOD_FIRST, event->ctrl, event->oskey, event->shift) &&
+ !IS_EVENT_MOD(event, shift, ctrl, oskey) &&
(event->val == KM_PRESS))
{
if (event->alt)
@@ -6180,7 +6846,7 @@ static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, const wmEvent *
}
/* handle keyingsets */
else if ((event->type == KKEY) &&
- !ELEM(KM_MOD_FIRST, event->ctrl, event->oskey, event->shift) &&
+ !IS_EVENT_MOD(event, shift, ctrl, oskey) &&
(event->val == KM_PRESS))
{
if (event->alt)
@@ -6193,7 +6859,10 @@ static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, const wmEvent *
return WM_UI_HANDLER_BREAK;
}
/* handle menu */
- else if (event->type == RIGHTMOUSE && event->val == KM_PRESS) {
+ else if ((event->type == RIGHTMOUSE) &&
+ !IS_EVENT_MOD(event, shift, ctrl, alt, oskey) &&
+ (event->val == KM_PRESS))
+ {
/* RMB has two options now */
if (ui_but_menu(C, but)) {
return WM_UI_HANDLER_BREAK;
@@ -6220,107 +6889,112 @@ static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, const wmEvent *
}
switch (but->type) {
- case BUT:
+ case UI_BTYPE_BUT:
retval = ui_do_but_BUT(C, but, data, event);
break;
- case KEYEVT:
+ case UI_BTYPE_KEY_EVENT:
retval = ui_do_but_KEYEVT(C, but, data, event);
break;
- case HOTKEYEVT:
+ case UI_BTYPE_HOTKEY_EVENT:
retval = ui_do_but_HOTKEYEVT(C, but, data, event);
break;
- case TOGBUT:
- case TOG:
- case ICONTOG:
- case ICONTOGN:
- case TOGN:
- case OPTION:
- case OPTIONN:
+ case UI_BTYPE_BUT_TOGGLE:
+ case UI_BTYPE_TOGGLE:
+ case UI_BTYPE_ICON_TOGGLE:
+ case UI_BTYPE_ICON_TOGGLE_N:
+ case UI_BTYPE_TOGGLE_N:
+ case UI_BTYPE_CHECKBOX:
+ case UI_BTYPE_CHECKBOX_N:
+ case UI_BTYPE_ROW:
retval = ui_do_but_TOG(C, but, data, event);
break;
- case SCROLL:
+ case UI_BTYPE_SCROLL:
retval = ui_do_but_SCROLL(C, block, but, data, event);
break;
- case GRIP:
+ case UI_BTYPE_GRIP:
retval = ui_do_but_GRIP(C, block, but, data, event);
break;
- case NUM:
+ case UI_BTYPE_NUM:
retval = ui_do_but_NUM(C, block, but, data, event);
break;
- case NUMSLI:
+ case UI_BTYPE_NUM_SLIDER:
retval = ui_do_but_SLI(C, block, but, data, event);
break;
- case LISTBOX:
+ case UI_BTYPE_LISTBOX:
/* Nothing to do! */
break;
- case LISTROW:
+ case UI_BTYPE_LISTROW:
retval = ui_do_but_LISTROW(C, but, data, event);
break;
- case ROUNDBOX:
- case LABEL:
- case ROW:
- case BUT_IMAGE:
- case PROGRESSBAR:
- case NODESOCKET:
+ case UI_BTYPE_ROUNDBOX:
+ case UI_BTYPE_LABEL:
+ case UI_BTYPE_IMAGE:
+ case UI_BTYPE_PROGRESS_BAR:
+ case UI_BTYPE_NODE_SOCKET:
retval = ui_do_but_EXIT(C, but, data, event);
break;
- case HISTOGRAM:
+ case UI_BTYPE_HISTOGRAM:
retval = ui_do_but_HISTOGRAM(C, block, but, data, event);
break;
- case WAVEFORM:
+ case UI_BTYPE_WAVEFORM:
retval = ui_do_but_WAVEFORM(C, block, but, data, event);
break;
- case VECTORSCOPE:
+ case UI_BTYPE_VECTORSCOPE:
/* Nothing to do! */
break;
- case TEX:
- case SEARCH_MENU:
+ case UI_BTYPE_TEXT:
+ case UI_BTYPE_SEARCH_MENU:
+ if ((but->type == UI_BTYPE_SEARCH_MENU) &&
+ (but->flag & UI_BUT_SEARCH_UNLINK))
+ {
+ retval = ui_do_but_SEARCH_UNLINK(C, block, but, data, event);
+ if (retval & WM_UI_HANDLER_BREAK) {
+ break;
+ }
+ }
retval = ui_do_but_TEX(C, block, but, data, event);
break;
- case SEARCH_MENU_UNLINK:
- retval = ui_do_but_SEARCH_UNLINK(C, block, but, data, event);
- break;
- case MENU:
- case BLOCK:
- case PULLDOWN:
+ case UI_BTYPE_MENU:
+ case UI_BTYPE_BLOCK:
+ case UI_BTYPE_PULLDOWN:
retval = ui_do_but_BLOCK(C, but, data, event);
break;
- case BUTM:
+ case UI_BTYPE_BUT_MENU:
retval = ui_do_but_BUT(C, but, data, event);
break;
- case COLOR:
+ case UI_BTYPE_COLOR:
if (but->a1 == -1) /* signal to prevent calling up color picker */
retval = ui_do_but_EXIT(C, but, data, event);
else
retval = ui_do_but_COLOR(C, but, data, event);
break;
- case BUT_NORMAL:
- retval = ui_do_but_NORMAL(C, block, but, data, event);
+ case UI_BTYPE_UNITVEC:
+ retval = ui_do_but_UNITVEC(C, block, but, data, event);
break;
- case BUT_COLORBAND:
+ case UI_BTYPE_COLORBAND:
retval = ui_do_but_COLORBAND(C, block, but, data, event);
break;
- case BUT_CURVE:
+ case UI_BTYPE_CURVE:
retval = ui_do_but_CURVE(C, block, but, data, event);
break;
- case HSVCUBE:
+ case UI_BTYPE_HSVCUBE:
retval = ui_do_but_HSVCUBE(C, block, but, data, event);
break;
- case HSVCIRCLE:
+ case UI_BTYPE_HSVCIRCLE:
retval = ui_do_but_HSVCIRCLE(C, block, but, data, event);
break;
- case LINK:
- case INLINK:
+ case UI_BTYPE_LINK:
+ case UI_BTYPE_INLINK:
retval = ui_do_but_LINK(C, but, data, event);
break;
- case TRACKPREVIEW:
+ case UI_BTYPE_TRACK_PREVIEW:
retval = ui_do_but_TRACKPREVIEW(C, block, but, data, event);
break;
/* quiet warnings for unhandled types */
- case SEPR:
- case SEPRLINE:
- case BUT_EXTRA:
+ case UI_BTYPE_SEPR:
+ case UI_BTYPE_SEPR_LINE:
+ case UI_BTYPE_EXTRA:
break;
}
@@ -6333,7 +7007,7 @@ static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, const wmEvent *
(event->type == BACKSPACEKEY && event->val == KM_PRESS))
{
/* ctrl+backspace = reset active button; backspace = reset a whole array*/
- ui_set_but_default(C, !event->ctrl, true);
+ ui_but_default_set(C, !event->ctrl, true);
ED_region_tag_redraw(data->region);
retval = WM_UI_HANDLER_BREAK;
}
@@ -6345,7 +7019,7 @@ static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, const wmEvent *
/* if we started dragging, progress on any event */
(data->multi_data.init == BUTTON_MULTI_INIT_SETUP))
{
- if (ELEM(but->type, NUM, NUMSLI) &&
+ if (ELEM(but->type, UI_BTYPE_NUM, UI_BTYPE_NUM_SLIDER) &&
ELEM(data->state, BUTTON_STATE_TEXT_EDITING, BUTTON_STATE_NUM_EDITING))
{
/* initialize! */
@@ -6379,8 +7053,13 @@ static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, const wmEvent *
/* just to be sure, check we're dragging more hoz then virt */
abs(event->prevx - event->x) > abs(event->prevy - event->y)))
{
- ui_multibut_states_create(but, data);
- data->multi_data.init = BUTTON_MULTI_INIT_ENABLE;
+ if (data->multi_data.has_mbuts) {
+ ui_multibut_states_create(but, data);
+ data->multi_data.init = BUTTON_MULTI_INIT_ENABLE;
+ }
+ else {
+ data->multi_data.init = BUTTON_MULTI_INIT_DISABLE;
+ }
}
}
@@ -6431,7 +7110,46 @@ static bool ui_but_isect_pie_seg(uiBlock *block, uiBut *but)
return false;
}
-uiBut *ui_but_find_activated(ARegion *ar)
+static bool ui_but_find_select_in_enum__cmp(const uiBut *but_a, const uiBut *but_b)
+{
+ return ((but_a->type == but_b->type) &&
+ (but_a->alignnr == but_b->alignnr) &&
+ (but_a->poin == but_b->poin) &&
+ (but_a->rnapoin.type == but_b->rnapoin.type) &&
+ (but_a->rnaprop == but_b->rnaprop));
+}
+
+/**
+ * Finds the pressed button in an aligned row (typically an expanded enum).
+ *
+ * \param direction Use when there may be multiple buttons pressed.
+ */
+uiBut *ui_but_find_select_in_enum(uiBut *but, int direction)
+{
+ uiBut *but_iter = but;
+ uiBut *but_found = NULL;
+ BLI_assert(ELEM(direction, -1, 1));
+
+ while ((but_iter->prev) &&
+ ui_but_find_select_in_enum__cmp(but_iter->prev, but))
+ {
+ but_iter = but_iter->prev;
+ }
+
+ while (but_iter && ui_but_find_select_in_enum__cmp(but_iter, but)) {
+ if (but_iter->flag & UI_SELECT) {
+ but_found = but_iter;
+ if (direction == 1) {
+ break;
+ }
+ }
+ but_iter = but_iter->next;
+ }
+
+ return but_found;
+}
+
+uiBut *ui_but_find_active_in_region(ARegion *ar)
{
uiBlock *block;
uiBut *but;
@@ -6444,26 +7162,26 @@ uiBut *ui_but_find_activated(ARegion *ar)
return NULL;
}
-bool ui_button_is_active(ARegion *ar)
+bool ui_but_is_active(ARegion *ar)
{
- return (ui_but_find_activated(ar) != NULL);
+ return (ui_but_find_active_in_region(ar) != NULL);
}
/* is called by notifier */
-void uiFreeActiveButtons(const bContext *C, bScreen *screen)
+void UI_screen_free_active_but(const bContext *C, bScreen *screen)
{
ScrArea *sa = screen->areabase.first;
for (; sa; sa = sa->next) {
ARegion *ar = sa->regionbase.first;
for (; ar; ar = ar->next) {
- uiBut *but = ui_but_find_activated(ar);
+ uiBut *but = ui_but_find_active_in_region(ar);
if (but) {
uiHandleButtonData *data = but->active;
if (data->menu == NULL && data->searchbox == NULL)
if (data->state == BUTTON_STATE_HIGHLIGHT)
- ui_button_active_free(C, but);
+ ui_but_active_free(C, but);
}
}
}
@@ -6476,10 +7194,10 @@ void uiFreeActiveButtons(const bContext *C, bScreen *screen)
bool UI_but_active_drop_name(bContext *C)
{
ARegion *ar = CTX_wm_region(C);
- uiBut *but = ui_but_find_activated(ar);
+ uiBut *but = ui_but_find_active_in_region(ar);
if (but) {
- if (ELEM(but->type, TEX, SEARCH_MENU, SEARCH_MENU_UNLINK))
+ if (ELEM(but->type, UI_BTYPE_TEXT, UI_BTYPE_SEARCH_MENU))
return 1;
}
@@ -6491,9 +7209,9 @@ bool UI_but_active_drop_color(bContext *C)
ARegion *ar = CTX_wm_region(C);
if (ar) {
- uiBut *but = ui_but_find_activated(ar);
+ uiBut *but = ui_but_find_active_in_region(ar);
- if (but && but->type == COLOR)
+ if (but && but->type == UI_BTYPE_COLOR)
return true;
}
@@ -6513,12 +7231,16 @@ static void ui_blocks_set_tooltips(ARegion *ar, const bool enable)
block->tooltipdisabled = !enable;
}
-static bool ui_mouse_inside_region(ARegion *ar, int x, int y)
+static bool ui_region_contains_point_px(ARegion *ar, int x, int y)
{
- uiBlock *block;
-
+ uiBlock *block = ar->uiblocks.first;
+ rcti winrct;
+
+ /* scale down area rect to exclude shadow */
+ ui_region_winrct_get_no_margin(ar, &winrct);
+
/* check if the mouse is in the region */
- if (!BLI_rcti_isect_pt(&ar->winrct, x, y)) {
+ if (!BLI_rcti_isect_pt(&winrct, x, y)) {
for (block = ar->uiblocks.first; block; block = block->next)
block->auto_open = false;
@@ -6547,11 +7269,11 @@ static bool ui_mouse_inside_region(ARegion *ar, int x, int y)
return true;
}
-static bool ui_mouse_inside_button(ARegion *ar, uiBut *but, int x, int y)
+static bool ui_but_contains_point_px(ARegion *ar, uiBut *but, int x, int y)
{
uiBlock *block = but->block;
float mx, my;
- if (!ui_mouse_inside_region(ar, x, y))
+ if (!ui_region_contains_point_px(ar, x, y))
return false;
mx = x;
@@ -6559,7 +7281,7 @@ static bool ui_mouse_inside_button(ARegion *ar, uiBut *but, int x, int y)
ui_window_to_block_fl(ar, block, &mx, &my);
- if (but->dt == UI_EMBOSSR) {
+ if (but->pie_dir != UI_RADIAL_NONE) {
if (!ui_but_isect_pie_seg(block, but)) {
return false;
}
@@ -6573,34 +7295,27 @@ 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.
+ * Note: ctrl is kind of a hack currently, so that non-embossed UI_BTYPE_TEXT button behaves as a label when ctrl is not pressed.
*/
-static bool ui_is_but_interactive(const uiBut *but, const bool labeledit)
+static bool ui_but_is_interactive(const uiBut *but, const bool labeledit)
{
- /* note, LABEL is included for highlights, this allows drags */
- if ((but->type == LABEL) && but->dragpoin == NULL)
+ /* note, UI_BTYPE_LABEL is included for highlights, this allows drags */
+ if ((but->type == UI_BTYPE_LABEL) && but->dragpoin == NULL)
return false;
- if (ELEM(but->type, ROUNDBOX, SEPR, SEPRLINE, LISTBOX))
+ if (ELEM(but->type, UI_BTYPE_ROUNDBOX, UI_BTYPE_SEPR, UI_BTYPE_SEPR_LINE, UI_BTYPE_LISTBOX))
return false;
if (but->flag & UI_HIDDEN)
return false;
if (but->flag & UI_SCROLLED)
return false;
- if ((but->type == TEX) && (but->dt == UI_EMBOSSN) && !labeledit)
+ if ((but->type == UI_BTYPE_TEXT) && (but->dt == UI_EMBOSS_NONE) && !labeledit)
return false;
- if ((but->type == LISTROW) && labeledit)
+ if ((but->type == UI_BTYPE_LISTROW) && labeledit)
return false;
return true;
}
-bool ui_is_but_search_unlink_visible(const uiBut *but)
-{
- BLI_assert(but->type == SEARCH_MENU_UNLINK);
- return ((but->editstr == NULL) &&
- (but->drawstr[0] != '\0'));
-}
-
/* 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)
{
@@ -6610,7 +7325,7 @@ static uiBut *ui_but_find_mouse_over_ex(ARegion *ar, const int x, const int y, c
// if (!win->active)
// return NULL;
- if (!ui_mouse_inside_region(ar, x, y))
+ if (!ui_region_contains_point_px(ar, x, y))
return NULL;
for (block = ar->uiblocks.first; block; block = block->next) {
@@ -6619,7 +7334,7 @@ static uiBut *ui_but_find_mouse_over_ex(ARegion *ar, const int x, const int y, c
ui_window_to_block_fl(ar, block, &mx, &my);
for (but = block->buttons.last; but; but = but->prev) {
- if (ui_is_but_interactive(but, labeledit)) {
+ if (ui_but_is_interactive(but, labeledit)) {
if (but->pie_dir != UI_RADIAL_NONE) {
if (ui_but_isect_pie_seg(block, but)) {
butover = but;
@@ -6651,13 +7366,13 @@ static uiBut *ui_but_find_mouse_over(ARegion *ar, const wmEvent *event)
}
-static uiBut *ui_list_find_mouse_over(ARegion *ar, int x, int y)
+static uiBut *ui_list_find_mouse_over_ex(ARegion *ar, int x, int y)
{
uiBlock *block;
uiBut *but;
float mx, my;
- if (!ui_mouse_inside_region(ar, x, y))
+ if (!ui_region_contains_point_px(ar, x, y))
return NULL;
for (block = ar->uiblocks.first; block; block = block->next) {
@@ -6666,7 +7381,7 @@ static uiBut *ui_list_find_mouse_over(ARegion *ar, int x, int y)
ui_window_to_block_fl(ar, block, &mx, &my);
for (but = block->buttons.last; but; but = but->prev) {
- if (but->type == LISTBOX && ui_but_contains_pt(but, mx, my)) {
+ if (but->type == UI_BTYPE_LISTBOX && ui_but_contains_pt(but, mx, my)) {
return but;
}
}
@@ -6675,6 +7390,11 @@ static uiBut *ui_list_find_mouse_over(ARegion *ar, int x, int y)
return NULL;
}
+static uiBut *ui_list_find_mouse_over(ARegion *ar, const wmEvent *event)
+{
+ return ui_list_find_mouse_over_ex(ar, event->x, event->y);
+}
+
/* ****************** button state handling **************************/
static bool button_modal_state(uiHandleButtonState state)
@@ -6688,7 +7408,8 @@ static bool button_modal_state(uiHandleButtonState state)
BUTTON_STATE_MENU_OPEN);
}
-static void button_timers_tooltip_remove(bContext *C, uiBut *but)
+/* removes tooltip timer from active but (meaning tooltip is disabled until it's reenabled again) */
+void UI_but_tooltip_timer_remove(bContext *C, uiBut *but)
{
uiHandleButtonData *data;
@@ -6747,14 +7468,14 @@ static void button_activate_state(bContext *C, uiBut *but, uiHandleButtonState s
button_tooltip_timer_reset(C, but);
/* automatic open pulldown block timer */
- if (ELEM(but->type, BLOCK, PULLDOWN)) {
+ if (ELEM(but->type, UI_BTYPE_BLOCK, UI_BTYPE_PULLDOWN)) {
if (data->used_mouse && !data->autoopentimer) {
int time;
if (but->block->auto_open == true) { /* test for toolbox */
time = 1;
}
- else if ((but->block->flag & UI_BLOCK_LOOP && but->type != BLOCK) || but->block->auto_open == true) {
+ else if ((but->block->flag & UI_BLOCK_LOOP && but->type != UI_BTYPE_BLOCK) || but->block->auto_open == true) {
time = 5 * U.menuthreshold2;
}
else if (U.uiflag & USER_MENUOPENAUTO) {
@@ -6772,7 +7493,7 @@ static void button_activate_state(bContext *C, uiBut *but, uiHandleButtonState s
}
else {
but->flag |= UI_SELECT;
- button_timers_tooltip_remove(C, but);
+ UI_but_tooltip_timer_remove(C, but);
}
/* text editing */
@@ -6785,7 +7506,7 @@ static void button_activate_state(bContext *C, uiBut *but, uiHandleButtonState s
/* number editing */
if (state == BUTTON_STATE_NUM_EDITING) {
- if (ui_is_a_warp_but(but))
+ if (ui_but_is_cursor_warp(but))
WM_cursor_grab_enable(CTX_wm_window(C), true, true, NULL);
ui_numedit_begin(but, data);
}
@@ -6795,7 +7516,7 @@ static void button_activate_state(bContext *C, uiBut *but, uiHandleButtonState s
if (but->flag & UI_BUT_DRIVEN)
WM_report(C, RPT_INFO, "Can't edit driven number value, see graph editor for the driver setup.");
- if (ui_is_a_warp_but(but)) {
+ if (ui_but_is_cursor_warp(but)) {
#ifdef USE_CONT_MOUSE_CORRECT
if (data->ungrab_mval[0] != FLT_MAX) {
@@ -6816,9 +7537,9 @@ static void button_activate_state(bContext *C, uiBut *but, uiHandleButtonState s
}
/* menu open */
if (state == BUTTON_STATE_MENU_OPEN)
- ui_blockopen_begin(C, but, data);
+ ui_block_open_begin(C, but, data);
else if (data->state == BUTTON_STATE_MENU_OPEN)
- ui_blockopen_end(C, but, data);
+ ui_block_open_end(C, but, data);
/* add a short delay before exiting, to ensure there is some feedback */
if (state == BUTTON_STATE_WAIT_FLASH) {
@@ -6834,7 +7555,7 @@ static void button_activate_state(bContext *C, uiBut *but, uiHandleButtonState s
if (!(but->block->handle && but->block->handle->popup)) {
if (button_modal_state(state)) {
if (!button_modal_state(data->state))
- WM_event_add_ui_handler(C, &data->window->modalhandlers, ui_handler_region_menu, NULL, data, false);
+ WM_event_add_ui_handler(C, &data->window->modalhandlers, ui_handler_region_menu, NULL, data, 0);
}
else {
if (button_modal_state(data->state)) {
@@ -6852,13 +7573,13 @@ static void button_activate_state(bContext *C, uiBut *but, uiHandleButtonState s
data->state = state;
if (state != BUTTON_STATE_EXIT) {
- /* When objects for eg. are removed, running ui_check_but() can access
+ /* When objects for eg. are removed, running ui_but_update() can access
* the removed data - so disable update on exit. Also in case of
* highlight when not in a popup menu, we remove because data used in
* button below popup might have been removed by action of popup. Needs
* a more reliable solution... */
if (state != BUTTON_STATE_HIGHLIGHT || (but->block->flag & UI_BLOCK_LOOP))
- ui_check_but(but);
+ ui_but_update(but);
}
/* redraw */
@@ -6879,7 +7600,7 @@ static void button_activate_init(bContext *C, ARegion *ar, uiBut *but, uiButtonA
copy_v2_fl(data->ungrab_mval, FLT_MAX);
#endif
- if (ELEM(but->type, BUT_CURVE, SEARCH_MENU, SEARCH_MENU_UNLINK)) {
+ if (ELEM(but->type, UI_BTYPE_CURVE, UI_BTYPE_SEARCH_MENU)) {
/* XXX curve is temp */
}
else {
@@ -6906,7 +7627,7 @@ static void button_activate_init(bContext *C, ARegion *ar, uiBut *but, uiButtonA
/* activate right away */
if (but->flag & UI_BUT_IMMEDIATE) {
- if (but->type == HOTKEYEVT)
+ if (but->type == UI_BTYPE_HOTKEY_EVENT)
button_activate_state(C, but, BUTTON_STATE_WAIT_KEY_EVENT);
/* .. more to be added here */
}
@@ -6933,19 +7654,20 @@ static void button_activate_init(bContext *C, ARegion *ar, uiBut *but, uiButtonA
else if (type == BUTTON_ACTIVATE_APPLY)
button_activate_state(C, but, BUTTON_STATE_WAIT_FLASH);
- if (but->type == GRIP) {
+ if (but->type == UI_BTYPE_GRIP) {
const bool horizontal = (BLI_rctf_size_x(&but->rect) < BLI_rctf_size_y(&but->rect));
WM_cursor_modal_set(data->window, horizontal ? CURSOR_X_MOVE : CURSOR_Y_MOVE);
}
}
-static void button_activate_exit(bContext *C, uiBut *but, uiHandleButtonData *data,
- const bool mousemove, const bool onfree)
+static void button_activate_exit(
+ bContext *C, uiBut *but, uiHandleButtonData *data,
+ const bool mousemove, const bool onfree)
{
uiBlock *block = but->block;
uiBut *bt;
- if (but->type == GRIP) {
+ if (but->type == UI_BTYPE_GRIP) {
WM_cursor_modal_restore(data->window);
}
@@ -6955,7 +7677,7 @@ static void button_activate_exit(bContext *C, uiBut *but, uiHandleButtonData *da
/* apply the button action or value */
if (!onfree)
- ui_apply_button(C, block, but, data, false);
+ ui_apply_but(C, block, but, data, false);
#ifdef USE_DRAG_MULTINUM
if (data->multi_data.has_mbuts) {
@@ -6964,7 +7686,7 @@ static void button_activate_exit(bContext *C, uiBut *but, uiHandleButtonData *da
bt->flag &= ~UI_BUT_DRAG_MULTI;
if (!data->cancel) {
- ui_apply_autokey(C, bt);
+ ui_apply_but_autokey(C, bt);
}
}
}
@@ -6988,8 +7710,8 @@ static void button_activate_exit(bContext *C, uiBut *but, uiHandleButtonData *da
if (!onfree && !data->cancel) {
/* autokey & undo push */
- ui_apply_undo(but);
- ui_apply_autokey(C, but);
+ ui_apply_but_undo(but);
+ ui_apply_but_autokey(C, but);
/* popup menu memory */
if (block->flag & UI_BLOCK_POPUP_MEMORY)
@@ -7012,6 +7734,10 @@ static void button_activate_exit(bContext *C, uiBut *but, uiHandleButtonData *da
if (data->origstr)
MEM_freeN(data->origstr);
+#ifdef USE_ALLSELECT
+ ui_selectcontext_end(but, &data->select_others);
+#endif
+
/* redraw (data is but->active!) */
ED_region_tag_redraw(data->region);
@@ -7024,7 +7750,7 @@ static void button_activate_exit(bContext *C, uiBut *but, uiHandleButtonData *da
but->flag &= ~(UI_ACTIVE | UI_SELECT);
but->flag |= UI_BUT_LAST_ACTIVE;
if (!onfree)
- ui_check_but(but);
+ ui_but_update(but);
/* adds empty mousemove in queue for re-init handler, in case mouse is
* still over a button. we cannot just check for this ourselfs because
@@ -7033,7 +7759,7 @@ static void button_activate_exit(bContext *C, uiBut *but, uiHandleButtonData *da
WM_event_add_mousemove(C);
}
-void ui_button_active_free(const bContext *C, uiBut *but)
+void ui_but_active_free(const bContext *C, uiBut *but)
{
uiHandleButtonData *data;
@@ -7099,13 +7825,13 @@ static uiBut *ui_context_rna_button_active(const bContext *C)
return ui_context_button_active(C, ui_context_rna_button_active_test);
}
-uiBut *uiContextActiveButton(const struct bContext *C)
+uiBut *UI_context_active_but_get(const struct bContext *C)
{
return ui_context_button_active(C, NULL);
}
/* helper function for insert keyframe, reset to default, etc operators */
-void uiContextActiveProperty(const bContext *C, struct PointerRNA *ptr, struct PropertyRNA **prop, int *index)
+void UI_context_active_but_prop_get(const bContext *C, struct PointerRNA *ptr, struct PropertyRNA **prop, int *index)
{
uiBut *activebut = ui_context_rna_button_active(C);
@@ -7122,7 +7848,7 @@ void uiContextActiveProperty(const bContext *C, struct PointerRNA *ptr, struct P
}
}
-void uiContextActivePropertyHandle(bContext *C)
+void UI_context_active_but_prop_handle(bContext *C)
{
uiBut *activebut = ui_context_rna_button_active(C);
if (activebut) {
@@ -7136,7 +7862,7 @@ void uiContextActivePropertyHandle(bContext *C)
}
}
-wmOperator *uiContextActiveOperator(const struct bContext *C)
+wmOperator *UI_context_active_operator_get(const struct bContext *C)
{
ARegion *ar_ctx = CTX_wm_region(C);
uiBlock *block;
@@ -7174,7 +7900,7 @@ wmOperator *uiContextActiveOperator(const struct bContext *C)
}
/* helper function for insert keyframe, reset to default, etc operators */
-void uiContextAnimUpdate(const bContext *C)
+void UI_context_update_anim_flag(const bContext *C)
{
Scene *scene = CTX_data_scene(C);
ARegion *ar = CTX_wm_region(C);
@@ -7218,7 +7944,7 @@ void uiContextAnimUpdate(const bContext *C)
/************** handle activating a button *************/
-static uiBut *uit_but_find_open_event(ARegion *ar, const wmEvent *event)
+static uiBut *ui_but_find_open_event(ARegion *ar, const wmEvent *event)
{
uiBlock *block;
uiBut *but;
@@ -7249,7 +7975,7 @@ static int ui_handle_button_over(bContext *C, const wmEvent *event, ARegion *ar)
}
}
else if (event->type == EVT_BUT_OPEN) {
- but = uit_but_find_open_event(ar, event);
+ but = ui_but_find_open_event(ar, event);
if (but) {
button_activate_init(C, ar, but, BUTTON_ACTIVATE_OVER);
ui_do_button(C, but->block, but, event);
@@ -7259,8 +7985,8 @@ static int ui_handle_button_over(bContext *C, const wmEvent *event, ARegion *ar)
return WM_UI_HANDLER_CONTINUE;
}
-/* exported to interface.c: uiButActiveOnly() */
-void ui_button_activate_do(bContext *C, ARegion *ar, uiBut *but)
+/* exported to interface.c: UI_but_active_only() */
+void ui_but_activate_event(bContext *C, ARegion *ar, uiBut *but)
{
wmWindow *win = CTX_wm_window(C);
wmEvent event;
@@ -7282,12 +8008,12 @@ void ui_button_activate_do(bContext *C, ARegion *ar, uiBut *but)
* exported so menus can start with a highlighted button,
* even if the mouse isnt over it
*/
-void ui_button_activate_over(bContext *C, ARegion *ar, uiBut *but)
+void ui_but_activate_over(bContext *C, ARegion *ar, uiBut *but)
{
button_activate_init(C, ar, but, BUTTON_ACTIVATE_OVER);
}
-void ui_button_execute_begin(struct bContext *UNUSED(C), struct ARegion *ar, uiBut *but, void **active_back)
+void ui_but_execute_begin(struct bContext *UNUSED(C), struct ARegion *ar, uiBut *but, void **active_back)
{
/* note: ideally we would not have to change 'but->active' however
* some functions we call don't use data (as they should be doing) */
@@ -7298,12 +8024,12 @@ void ui_button_execute_begin(struct bContext *UNUSED(C), struct ARegion *ar, uiB
data->region = ar;
}
-void ui_button_execute_end(struct bContext *C, struct ARegion *UNUSED(ar), uiBut *but, void *active_back)
+void ui_but_execute_end(struct bContext *C, struct ARegion *UNUSED(ar), uiBut *but, void *active_back)
{
- ui_apply_button(C, but->block, but, but->active, true);
+ ui_apply_but(C, but->block, but, but->active, true);
if ((but->flag & UI_BUT_DRAG_MULTI) == 0) {
- ui_apply_autokey(C, but);
+ ui_apply_but_autokey(C, but);
}
/* use onfree event so undo is handled by caller and apply is already done above */
button_activate_exit((bContext *)C, but, but->active, false, true);
@@ -7315,7 +8041,7 @@ static void ui_handle_button_activate(bContext *C, ARegion *ar, uiBut *but, uiBu
uiBut *oldbut;
uiHandleButtonData *data;
- oldbut = ui_but_find_activated(ar);
+ oldbut = ui_but_find_active_in_region(ar);
if (oldbut) {
data = oldbut->active;
data->cancel = true;
@@ -7353,8 +8079,9 @@ static int ui_handle_button_event(bContext *C, const wmEvent *event, uiBut *but)
uiBut *but_other = ui_but_find_mouse_over(ar, event);
bool exit = false;
- if ((!ui_block_is_menu(block) || ui_block_is_pie_menu(but->block)) &&
- !ui_mouse_inside_button(ar, but, event->x, event->y))
+ /* always deactivate button for pie menus, else moving to blank space will leave activated */
+ if ((!ui_block_is_menu(block) || ui_block_is_pie_menu(block)) &&
+ !ui_but_contains_point_px(ar, but, event->x, event->y))
{
exit = true;
}
@@ -7389,19 +8116,19 @@ static int ui_handle_button_event(bContext *C, const wmEvent *event, uiBut *but)
WM_event_remove_timer(data->wm, data->window, data->autoopentimer);
data->autoopentimer = NULL;
- if (ui_mouse_inside_button(ar, but, event->x, event->y))
+ if (ui_but_contains_point_px(ar, but, event->x, event->y))
button_activate_state(C, but, BUTTON_STATE_MENU_OPEN);
}
retval = WM_UI_HANDLER_CONTINUE;
break;
}
- /* XXX hardcoded keymap check... but anyway, while view changes, tooltips should be removed */
+ /* XXX hardcoded keymap check... but anyway, while view changes, tooltips should be removed */
case WHEELUPMOUSE:
case WHEELDOWNMOUSE:
case MIDDLEMOUSE:
case MOUSEPAN:
- button_timers_tooltip_remove(C, but);
+ UI_but_tooltip_timer_remove(C, but);
/* fall-through */
default:
/* handle button type specific events */
@@ -7417,7 +8144,7 @@ static int ui_handle_button_event(bContext *C, const wmEvent *event, uiBut *but)
break;
case MOUSEMOVE:
- if (ELEM(but->type, LINK, INLINK)) {
+ if (ELEM(but->type, UI_BTYPE_LINK, UI_BTYPE_INLINK)) {
ARegion *ar = data->region;
but->flag |= UI_SELECT;
ui_do_button(C, block, but, event);
@@ -7426,7 +8153,7 @@ static int ui_handle_button_event(bContext *C, const wmEvent *event, uiBut *but)
else {
/* deselect the button when moving the mouse away */
/* also de-activate for buttons that only show higlights */
- if (ui_mouse_inside_button(ar, but, event->x, event->y)) {
+ if (ui_but_contains_point_px(ar, but, event->x, event->y)) {
if (!(but->flag & UI_SELECT)) {
but->flag |= (UI_SELECT | UI_ACTIVE);
data->cancel = false;
@@ -7471,7 +8198,7 @@ static int ui_handle_button_event(bContext *C, const wmEvent *event, uiBut *but)
uiBut *bt;
if (data->menu && data->menu->region) {
- if (ui_mouse_inside_region(data->menu->region, event->x, event->y)) {
+ if (ui_region_contains_point_px(data->menu->region, event->x, event->y)) {
break;
}
}
@@ -7479,7 +8206,7 @@ static int ui_handle_button_event(bContext *C, const wmEvent *event, uiBut *but)
bt = ui_but_find_mouse_over(ar, event);
if (bt && bt->active != data) {
- if (but->type != COLOR) { /* exception */
+ if (but->type != UI_BTYPE_COLOR) { /* exception */
data->cancel = true;
}
button_activate_state(C, but, BUTTON_STATE_EXIT);
@@ -7526,21 +8253,15 @@ static int ui_handle_button_event(bContext *C, const wmEvent *event, uiBut *but)
return retval;
}
-static int ui_handle_list_event(bContext *C, const wmEvent *event, ARegion *ar)
+static int ui_handle_list_event(bContext *C, const wmEvent *event, ARegion *ar, uiBut *listbox)
{
- uiBut *but;
uiList *ui_list;
uiListDyn *dyn_data;
int retval = WM_UI_HANDLER_CONTINUE;
int type = event->type, val = event->val;
int mx, my;
- but = ui_list_find_mouse_over(ar, event->x, event->y);
- if (!but) {
- return retval;
- }
-
- ui_list = but->custom_data;
+ ui_list = listbox->custom_data;
if (!ui_list || !ui_list->dyn_data) {
return retval;
}
@@ -7548,7 +8269,7 @@ static int ui_handle_list_event(bContext *C, const wmEvent *event, ARegion *ar)
mx = event->x;
my = event->y;
- ui_window_to_block(ar, but->block, &mx, &my);
+ ui_window_to_block(ar, listbox->block, &mx, &my);
/* convert pan to scrollwheel */
if (type == MOUSEPAN) {
@@ -7562,9 +8283,9 @@ static int ui_handle_list_event(bContext *C, const wmEvent *event, ARegion *ar)
if (val == KM_PRESS) {
if (ELEM(type, UPARROWKEY, DOWNARROWKEY) ||
- ((ELEM(type, WHEELUPMOUSE, WHEELDOWNMOUSE) && event->alt)))
+ ((ELEM(type, WHEELUPMOUSE, WHEELDOWNMOUSE) && event->ctrl)))
{
- const int value_orig = RNA_property_int_get(&but->rnapoin, but->rnaprop);
+ const int value_orig = RNA_property_int_get(&listbox->rnapoin, listbox->rnaprop);
int value, min, max, inc;
/* activate up/down the list */
@@ -7617,14 +8338,14 @@ static int ui_handle_list_event(bContext *C, const wmEvent *event, ARegion *ar)
CLAMP(value, 0, dyn_data->items_len - 1);
- RNA_property_int_range(&but->rnapoin, but->rnaprop, &min, &max);
+ RNA_property_int_range(&listbox->rnapoin, listbox->rnaprop, &min, &max);
CLAMP(value, min, max);
if (value != value_orig) {
- RNA_property_int_set(&but->rnapoin, but->rnaprop, value);
- RNA_property_update(C, &but->rnapoin, but->rnaprop);
+ RNA_property_int_set(&listbox->rnapoin, listbox->rnaprop, value);
+ RNA_property_update(C, &listbox->rnapoin, listbox->rnaprop);
- ui_apply_undo(but);
+ ui_apply_but_undo(listbox);
ui_list->flag |= UILST_SCROLL_TO_ACTIVE_ITEM;
ED_region_tag_redraw(ar);
@@ -7668,18 +8389,18 @@ static void ui_handle_button_return_submenu(bContext *C, const wmEvent *event, u
/* copy over return values from the closing menu */
if ((menu->menuretval & UI_RETURN_OK) || (menu->menuretval & UI_RETURN_UPDATE)) {
- if (but->type == COLOR)
+ if (but->type == UI_BTYPE_COLOR)
copy_v3_v3(data->vec, menu->retvec);
- else if (but->type == MENU)
+ else if (but->type == UI_BTYPE_MENU)
data->value = menu->retvalue;
}
if (menu->menuretval & UI_RETURN_UPDATE) {
if (data->interactive) {
- ui_apply_button(C, but->block, but, data, true);
+ ui_apply_but(C, but->block, but, data, true);
}
else {
- ui_check_but(but);
+ ui_but_update(but);
}
menu->menuretval = 0;
@@ -7693,7 +8414,7 @@ static void ui_handle_button_return_submenu(bContext *C, const wmEvent *event, u
button_activate_exit(C, but, data, true, false);
}
else if (menu->menuretval & UI_RETURN_OUT) {
- if (event->type == MOUSEMOVE && ui_mouse_inside_button(data->region, but, event->x, event->y)) {
+ if (event->type == MOUSEMOVE && ui_but_contains_point_px(data->region, but, event->x, event->y)) {
button_activate_state(C, but, BUTTON_STATE_HIGHLIGHT);
}
else {
@@ -7712,13 +8433,14 @@ static void ui_handle_button_return_submenu(bContext *C, const wmEvent *event, u
/* ************************* menu handling *******************************/
-/* function used to prevent loosing the open menu when using nested pulldowns,
+/**
+ * Function used to prevent loosing the open menu when using nested pulldowns,
* when moving mouse towards the pulldown menu over other buttons that could
* steal the highlight from the current button, only checks:
*
* - while mouse moves in triangular area defined old mouse position and
- * left/right side of new menu
- * - only for 1 second
+ * left/right side of new menu.
+ * - only for 1 second.
*/
static void ui_mouse_motion_towards_init_ex(uiPopupBlockHandle *menu, const int xy[2], const bool force)
@@ -7747,8 +8469,9 @@ static void ui_mouse_motion_towards_reinit(uiPopupBlockHandle *menu, const int x
ui_mouse_motion_towards_init_ex(menu, xy, true);
}
-static bool ui_mouse_motion_towards_check(uiBlock *block, uiPopupBlockHandle *menu, const int xy[2],
- const bool use_wiggle_room)
+static bool ui_mouse_motion_towards_check(
+ uiBlock *block, uiPopupBlockHandle *menu, const int xy[2],
+ const bool use_wiggle_room)
{
float p1[2], p2[2], p3[2], p4[2];
float oldp[2] = {menu->towards_xy[0], menu->towards_xy[1]};
@@ -7936,8 +8659,9 @@ static int ui_menu_scroll(ARegion *ar, uiBlock *block, int my, uiBut *to_bt)
*
* Without this keyboard navigation from menu's wont work.
*/
-static bool ui_menu_pass_event_to_parent_if_nonactive(uiPopupBlockHandle *menu, const uiBut *but,
- const int level, const int retval)
+static bool ui_menu_pass_event_to_parent_if_nonactive(
+ uiPopupBlockHandle *menu, const uiBut *but,
+ const int level, const int retval)
{
if ((level != 0) && (but == NULL)) {
menu->menuretval = UI_RETURN_OUT | UI_RETURN_OUT_PARENT;
@@ -7953,7 +8677,7 @@ static bool ui_menu_pass_event_to_parent_if_nonactive(uiPopupBlockHandle *menu,
static int ui_handle_menu_button(bContext *C, const wmEvent *event, uiPopupBlockHandle *menu)
{
ARegion *ar = menu->region;
- uiBut *but = ui_but_find_activated(ar);
+ uiBut *but = ui_but_find_active_in_region(ar);
int retval;
if (but) {
@@ -7965,11 +8689,11 @@ static int ui_handle_menu_button(bContext *C, const wmEvent *event, uiPopupBlock
else if (!ui_block_is_menu(but->block) || ui_block_is_pie_menu(but->block)) {
/* pass, skip for dialogs */
}
- else if (!ui_mouse_inside_region(but->active->region, event->x, event->y)) {
+ else if (!ui_region_contains_point_px(but->active->region, event->x, event->y)) {
/* pass, needed to click-exit outside of non-flaoting menus */
}
else if ((!ELEM(event->type, MOUSEMOVE, WHEELUPMOUSE, WHEELDOWNMOUSE, MOUSEPAN)) && ISMOUSE(event->type)) {
- if (!ui_mouse_inside_button(but->active->region, but, event->x, event->y)) {
+ if (!ui_but_contains_point_px(but->active->region, but, event->x, event->y)) {
but = NULL;
}
}
@@ -7994,7 +8718,7 @@ static int ui_handle_menu_button(bContext *C, const wmEvent *event, uiPopupBlock
return retval;
}
-void ui_block_calculate_pie_segment(uiBlock *block, const float event_xy[2])
+float ui_block_calc_pie_segment(uiBlock *block, const float event_xy[2])
{
float seg1[2];
float seg2[2];
@@ -8011,11 +8735,12 @@ void ui_block_calculate_pie_segment(uiBlock *block, const float event_xy[2])
len = normalize_v2_v2(block->pie_data.pie_dir, seg2);
- /* ten pixels for now, a bit arbitrary */
if (len < U.pie_menu_threshold * U.pixelsize)
block->pie_data.flags |= UI_PIE_INVALID_DIR;
else
block->pie_data.flags &= ~UI_PIE_INVALID_DIR;
+
+ return len;
}
static int ui_handle_menu_event(
@@ -8024,7 +8749,7 @@ static int ui_handle_menu_event(
{
ARegion *ar;
uiBlock *block;
- uiBut *but, *bt;
+ uiBut *but;
int mx, my, retval;
bool inside;
bool inside_title; /* check for title dragging */
@@ -8043,7 +8768,7 @@ static int ui_handle_menu_event(
inside_title = inside && ((my + (UI_UNIT_Y * 1.5f)) > block->rect.ymax);
/* if there's an active modal button, don't check events or outside, except for search menu */
- but = ui_but_find_activated(ar);
+ but = ui_but_find_active_in_region(ar);
#ifdef USE_DRAG_POPUP
if (menu->is_grab) {
@@ -8119,15 +8844,15 @@ static int ui_handle_menu_event(
if (ui_menu_pass_event_to_parent_if_nonactive(menu, but, level, retval))
break;
- but = ui_but_find_activated(ar);
+ but = ui_but_find_active_in_region(ar);
if (!but) {
/* no item active, we make first active */
- if (block->direction & UI_TOP) but = ui_but_last(block);
+ if (block->direction & UI_DIR_UP) but = ui_but_last(block);
else but = ui_but_first(block);
}
- if (but && ELEM(but->type, BLOCK, PULLDOWN))
+ if (but && ELEM(but->type, UI_BTYPE_BLOCK, UI_BTYPE_PULLDOWN))
ui_handle_button_activate(C, ar, but, BUTTON_ACTIVATE_OPEN);
}
@@ -8140,7 +8865,7 @@ static int ui_handle_menu_event(
case WHEELDOWNMOUSE:
case MOUSEPAN:
/* arrowkeys: only handle for block_loop blocks */
- if (event->alt || event->shift || event->ctrl || event->oskey) {
+ if (IS_EVENT_MOD(event, shift, ctrl, alt, oskey)) {
/* pass */
}
else if (inside || (block->flag & UI_BLOCK_LOOP)) {
@@ -8152,7 +8877,9 @@ static int ui_handle_menu_event(
ui_pan_to_scroll(event, &type, &val);
if (val == KM_PRESS) {
- const eButType type_flip = BUT | ROW;
+ const bool is_next =
+ (ELEM(type, DOWNARROWKEY, WHEELDOWNMOUSE) ==
+ ((block->flag & UI_BLOCK_IS_FLIP) != 0));
if (ui_menu_pass_event_to_parent_if_nonactive(menu, but, level, retval))
break;
@@ -8161,58 +8888,24 @@ static int ui_handle_menu_event(
ui_mouse_motion_keynav_init(&menu->keynav_state, event);
#endif
- but = ui_but_find_activated(ar);
+ but = ui_but_find_active_in_region(ar);
if (but) {
- /* is there a situation where UI_LEFT or UI_RIGHT would also change navigation direction? */
- if (((ELEM(type, DOWNARROWKEY, WHEELDOWNMOUSE)) && (block->direction & UI_DOWN)) ||
- ((ELEM(type, DOWNARROWKEY, WHEELDOWNMOUSE)) && (block->direction & UI_RIGHT)) ||
- ((ELEM(type, UPARROWKEY, WHEELUPMOUSE)) && (block->direction & UI_TOP)))
- {
- /* the following is just a hack - uiBut->type set to BUT and BUTM have there menus built
- * opposite ways - this should be changed so that all popup-menus use the same uiBlock->direction */
- if (but->type & type_flip)
- but = ui_but_next(but);
- else
- but = ui_but_prev(but);
- }
- else {
- if (but->type & type_flip)
- but = ui_but_prev(but);
- else
- but = ui_but_next(but);
- }
-
- if (but) {
- ui_handle_button_activate(C, ar, but, BUTTON_ACTIVATE);
- ui_menu_scroll(ar, block, my, but);
- }
+ /* next button */
+ but = is_next ? ui_but_next(but) : ui_but_prev(but);
}
if (!but) {
- if (((ELEM(type, UPARROWKEY, WHEELUPMOUSE)) && (block->direction & UI_DOWN)) ||
- ((ELEM(type, UPARROWKEY, WHEELUPMOUSE)) && (block->direction & UI_RIGHT)) ||
- ((ELEM(type, DOWNARROWKEY, WHEELDOWNMOUSE)) && (block->direction & UI_TOP)))
- {
- if ((bt = ui_but_first(block)) && (bt->type & type_flip)) {
- bt = ui_but_last(block);
- }
- else {
- /* keep ui_but_first() */
- }
- }
- else {
- if ((bt = ui_but_first(block)) && (bt->type & type_flip)) {
- /* keep ui_but_first() */
- }
- else {
- bt = ui_but_last(block);
- }
+ /* wrap button */
+ uiBut *but_wrap;
+ but_wrap = is_next ? ui_but_first(block) : ui_but_last(block);
+ if (but_wrap) {
+ but = but_wrap;
}
+ }
- if (bt) {
- ui_handle_button_activate(C, ar, bt, BUTTON_ACTIVATE);
- ui_menu_scroll(ar, block, my, bt);
- }
+ if (but) {
+ ui_handle_button_activate(C, ar, but, BUTTON_ACTIVATE);
+ ui_menu_scroll(ar, block, my, but);
}
}
@@ -8254,7 +8947,7 @@ static int ui_handle_menu_event(
for (but = block->buttons.first; but; but = but->next) {
bool doit = false;
- if (!ELEM(but->type, LABEL, SEPR, SEPRLINE))
+ if (!ELEM(but->type, UI_BTYPE_LABEL, UI_BTYPE_SEPR, UI_BTYPE_SEPR_LINE))
count++;
/* exception for rna layer buts */
@@ -8272,7 +8965,7 @@ static int ui_handle_menu_event(
if (doit) {
/* activate buttons but open menu's */
uiButtonActivateType activate;
- if (but->type == PULLDOWN) {
+ if (but->type == UI_BTYPE_PULLDOWN) {
activate = BUTTON_ACTIVATE_OPEN;
}
else {
@@ -8317,9 +9010,7 @@ static int ui_handle_menu_event(
case ZKEY:
{
if ((event->val == KM_PRESS || event->val == KM_DBL_CLICK) &&
- (event->shift == 0) &&
- (event->ctrl == 0) &&
- (event->oskey == 0))
+ !IS_EVENT_MOD(event, shift, ctrl, oskey))
{
if (ui_menu_pass_event_to_parent_if_nonactive(menu, but, level, retval))
break;
@@ -8327,20 +9018,20 @@ static int ui_handle_menu_event(
for (but = block->buttons.first; but; but = but->next) {
if (but->menu_key == event->type) {
- if (ELEM(but->type, BUT, BUTM)) {
+ if (ELEM(but->type, UI_BTYPE_BUT, UI_BTYPE_BUT_MENU)) {
/* mainly for operator buttons */
ui_handle_button_activate(C, ar, but, BUTTON_ACTIVATE_APPLY);
}
- else if (ELEM(but->type, BLOCK, PULLDOWN)) {
+ else if (ELEM(but->type, UI_BTYPE_BLOCK, UI_BTYPE_PULLDOWN)) {
/* open submenus (like right arrow key) */
ui_handle_button_activate(C, ar, but, BUTTON_ACTIVATE_OPEN);
}
- else if (but->type == MENU) {
+ else if (but->type == UI_BTYPE_MENU) {
/* activate menu items */
ui_handle_button_activate(C, ar, but, BUTTON_ACTIVATE);
}
else {
- printf("%s: error, but->menu_key type: %d\n", __func__, but->type);
+ printf("%s: error, but->menu_key type: %u\n", __func__, but->type);
}
break;
@@ -8400,16 +9091,16 @@ static int ui_handle_menu_event(
else if (ELEM(event->type, RETKEY, PADENTER) && event->val == KM_PRESS) {
/* enter will always close this block, we let the event
* get handled by the button if it is activated, otherwise we cancel */
- if (!ui_but_find_activated(ar))
+ if (!ui_but_find_active_in_region(ar))
menu->menuretval = UI_RETURN_CANCEL | UI_RETURN_POPUP_OK;
}
#ifdef USE_DRAG_POPUP
else if ((event->type == LEFTMOUSE) && (event->val == KM_PRESS) &&
(inside && is_floating && inside_title))
{
- if (!but || !ui_mouse_inside_button(ar, but, event->x, event->y)) {
+ if (!but || !ui_but_contains_point_px(ar, but, event->x, event->y)) {
if (but) {
- button_timers_tooltip_remove(C, but);
+ UI_but_tooltip_timer_remove(C, but);
}
menu->is_grab = true;
@@ -8487,7 +9178,10 @@ static int ui_handle_menu_return_submenu(bContext *C, const wmEvent *event, uiPo
ar = menu->region;
block = ar->uiblocks.first;
- but = ui_but_find_activated(ar);
+ but = ui_but_find_active_in_region(ar);
+
+ BLI_assert(but);
+
data = but->active;
submenu = data->menu;
@@ -8520,14 +9214,6 @@ static int ui_handle_menu_return_submenu(bContext *C, const wmEvent *event, uiPo
}
if (menu->menuretval) {
- /* pie menus should not close but wait for release instead */
- if ((block->flag & UI_BLOCK_RADIAL) &&
- !(block->pie_data.flags & UI_PIE_CLICK_STYLE))
- {
- menu->menuretval = 0;
- block->pie_data.flags |= UI_PIE_FINISHED;
- }
-
return WM_UI_HANDLER_CONTINUE;
}
else {
@@ -8537,18 +9223,18 @@ static int ui_handle_menu_return_submenu(bContext *C, const wmEvent *event, uiPo
static bool ui_but_pie_menu_supported_apply(uiBut *but)
{
- return (but->type != NUMSLI);
+ return (!ELEM(but->type, UI_BTYPE_NUM_SLIDER, UI_BTYPE_NUM));
}
-static int ui_but_pie_menu_apply(bContext *C, uiPopupBlockHandle *menu, uiBut *but, bool force_close, bool click_style)
+static int ui_but_pie_menu_apply(bContext *C, uiPopupBlockHandle *menu, uiBut *but, bool force_close)
{
int retval = WM_UI_HANDLER_BREAK;
if (but && ui_but_pie_menu_supported_apply(but)) {
- if (but->type == MENU) {
+ if (but->type == UI_BTYPE_MENU) {
/* forcing the pie menu to close will not handle menus */
if (!force_close) {
- uiBut *active_but = ui_but_find_activated(menu->region);
+ uiBut *active_but = ui_but_find_active_in_region(menu->region);
if (active_but) {
button_activate_exit(C, active_but, active_but->active, false, false);
@@ -8562,27 +9248,14 @@ static int ui_but_pie_menu_apply(bContext *C, uiPopupBlockHandle *menu, uiBut *b
}
}
else {
- ui_apply_button(C, but->block, but, but->active, false);
+ ui_apply_but(C, but->block, but, but->active, false);
button_activate_exit((bContext *)C, but, but->active, false, true);
- if (!(click_style || force_close)) {
- but->block->pie_data.flags |= UI_PIE_FINISHED;
- menu->menuretval = 0;
- }
- else {
- menu->menuretval = UI_RETURN_OK;
- }
+ menu->menuretval = UI_RETURN_OK;
}
}
else {
- uiBlock *block = menu->region->uiblocks.first;
-
- if (!(click_style || force_close)) {
- block->pie_data.flags |= UI_PIE_FINISHED;
- }
- else {
- menu->menuretval = UI_RETURN_CANCEL;
- }
+ menu->menuretval = UI_RETURN_CANCEL;
ED_region_tag_redraw(menu->region);
}
@@ -8596,7 +9269,7 @@ static uiBut *ui_block_pie_dir_activate(uiBlock *block, const wmEvent *event, Ra
if ((block->flag & UI_BLOCK_NUMSELECT) && event->val == KM_PRESS) {
for (but = block->buttons.first; but; but = but->next) {
- if (but->pie_dir == dir && !ELEM(but->type, SEPR, SEPRLINE)) {
+ if (but->pie_dir == dir && !ELEM(but->type, UI_BTYPE_SEPR, UI_BTYPE_SEPR_LINE)) {
return but;
}
}
@@ -8605,23 +9278,23 @@ static uiBut *ui_block_pie_dir_activate(uiBlock *block, const wmEvent *event, Ra
return NULL;
}
-static int ui_but_pie_button_activate(bContext *C, uiBut *but, uiPopupBlockHandle *menu, bool is_click_style)
+static int ui_but_pie_button_activate(bContext *C, uiBut *but, uiPopupBlockHandle *menu)
{
uiBut *active_but;
if (but == NULL)
return WM_UI_HANDLER_BREAK;
- active_but = ui_but_find_activated(menu->region);
+ active_but = ui_but_find_active_in_region(menu->region);
if (active_but)
button_activate_exit(C, active_but, active_but->active, false, false);
button_activate_init(C, menu->region, but, BUTTON_ACTIVATE_OVER);
- return ui_but_pie_menu_apply(C, menu, but, false, is_click_style);
+ return ui_but_pie_menu_apply(C, menu, but, false);
}
-static int ui_handler_pie(bContext *C, const wmEvent *event, uiPopupBlockHandle *menu)
+static int ui_pie_handler(bContext *C, const wmEvent *event, uiPopupBlockHandle *menu)
{
ARegion *ar;
uiBlock *block;
@@ -8629,6 +9302,7 @@ static int ui_handler_pie(bContext *C, const wmEvent *event, uiPopupBlockHandle
float event_xy[2];
double duration;
bool is_click_style;
+ float dist;
/* we block all events, this is modal interaction, except for drop events which is described below */
int retval = WM_UI_HANDLER_BREAK;
@@ -8652,6 +9326,13 @@ static int ui_handler_pie(bContext *C, const wmEvent *event, uiPopupBlockHandle
duration = menu->scrolltimer->duration;
+ event_xy[0] = event->x;
+ event_xy[1] = event->y;
+
+ ui_window_to_block_fl(ar, block, &event_xy[0], &event_xy[1]);
+
+ dist = ui_block_calc_pie_segment(block, event_xy);
+
if (event->type == TIMER) {
if (event->customdata == menu->scrolltimer) {
/* deactivate initial direction after a while */
@@ -8686,7 +9367,7 @@ static int ui_handler_pie(bContext *C, const wmEvent *event, uiPopupBlockHandle
mul_v2_fl(vec, pie_radius);
add_v2_v2(vec, center);
- mul_v2_fl(vec, fac);
+ mul_v2_fl(vec, fac);
add_v2_v2(vec, block->pie_data.pie_center_spawned);
BLI_rctf_recenter(&but->rect, vec[0], vec[1]);
@@ -8697,27 +9378,29 @@ static int ui_handler_pie(bContext *C, const wmEvent *event, uiPopupBlockHandle
ED_region_tag_redraw(ar);
}
}
- }
- event_xy[0] = event->x;
- event_xy[1] = event->y;
+ /* check pie velociy here if gesture has ended */
+ if (block->pie_data.flags & UI_PIE_GESTURE_END_WAIT) {
+ float len_sq = 10;
- ui_window_to_block_fl(ar, block, &event_xy[0], &event_xy[1]);
+ /* use a time threshold to ensure we leave time to the mouse to move */
+ if (duration - block->pie_data.duration_gesture > 0.02) {
+ len_sq = len_squared_v2v2(event_xy, block->pie_data.last_pos);
+ copy_v2_v2(block->pie_data.last_pos, event_xy);
+ block->pie_data.duration_gesture = duration;
+ }
- ui_block_calculate_pie_segment(block, event_xy);
+ if (len_sq < 1.0f) {
+ uiBut *but = ui_but_find_active_in_region(menu->region);
- if (block->pie_data.flags & UI_PIE_FINISHED) {
- if ((event->type == block->pie_data.event && event->val == KM_RELEASE) ||
- ((event->type == RIGHTMOUSE || event->type == ESCKEY) && (event->val == KM_PRESS)))
- {
- menu->menuretval = UI_RETURN_OK;
+ if (but) {
+ return ui_but_pie_menu_apply(C, menu, but, true);
+ }
+ }
}
-
- ED_region_tag_redraw(ar);
- return WM_UI_HANDLER_BREAK;
}
- if (event->type == block->pie_data.event) {
+ if (event->type == block->pie_data.event && !is_click_style) {
if (event->val != KM_RELEASE) {
ui_handle_menu_button(C, event, menu);
@@ -8733,10 +9416,18 @@ static int ui_handler_pie(bContext *C, const wmEvent *event, uiPopupBlockHandle
if (!(block->pie_data.flags & UI_PIE_DRAG_STYLE)) {
block->pie_data.flags |= UI_PIE_CLICK_STYLE;
}
- else if (!is_click_style) {
- uiBut *but = ui_but_find_activated(menu->region);
+ else {
+ uiBut *but = ui_but_find_active_in_region(menu->region);
+
+ if (but && (U.pie_menu_confirm > 0) &&
+ (dist >= U.pie_menu_threshold + U.pie_menu_confirm))
+ {
+ if (but)
+ return ui_but_pie_menu_apply(C, menu, but, true);
+ }
+
+ retval = ui_but_pie_menu_apply(C, menu, but, true);
- retval = ui_but_pie_menu_apply(C, menu, but, true, is_click_style);
}
}
}
@@ -8746,9 +9437,24 @@ static int ui_handler_pie(bContext *C, const wmEvent *event, uiPopupBlockHandle
switch (event->type) {
case MOUSEMOVE:
- if (len_squared_v2v2(event_xy, block->pie_data.pie_center_init) > PIE_CLICK_THRESHOLD_SQ) {
- block->pie_data.flags |= UI_PIE_DRAG_STYLE;
+ if (!is_click_style) {
+ float len_sq = len_squared_v2v2(event_xy, block->pie_data.pie_center_init);
+
+ /* here we use the initial position explicitly */
+ if (len_sq > PIE_CLICK_THRESHOLD_SQ) {
+ block->pie_data.flags |= UI_PIE_DRAG_STYLE;
+ }
+
+ /* here instead, we use the offset location to account for the initial direction timeout */
+ if ((U.pie_menu_confirm > 0) &&
+ (dist >= U.pie_menu_threshold + U.pie_menu_confirm))
+ {
+ block->pie_data.flags |= UI_PIE_GESTURE_END_WAIT;
+ copy_v2_v2(block->pie_data.last_pos, event_xy);
+ block->pie_data.duration_gesture = duration;
+ }
}
+
ui_handle_menu_button(C, event, menu);
/* mouse move should always refresh the area for pie menus */
@@ -8756,21 +9462,19 @@ static int ui_handler_pie(bContext *C, const wmEvent *event, uiPopupBlockHandle
break;
case LEFTMOUSE:
- if (event->val == KM_PRESS) {
- uiBut *but = ui_but_find_activated(menu->region);
- retval = ui_but_pie_menu_apply(C, menu, but, false, is_click_style);
+ if (is_click_style) {
+ if (block->pie_data.flags & UI_PIE_INVALID_DIR) {
+ menu->menuretval = UI_RETURN_CANCEL;
+ }
+ else {
+ retval = ui_handle_menu_button(C, event, menu);
+ }
}
break;
case ESCKEY:
case RIGHTMOUSE:
- if (!is_click_style) {
- block->pie_data.flags |= UI_PIE_FINISHED;
- menu->menuretval = 0;
- ED_region_tag_redraw(ar);
- }
- else
- menu->menuretval = UI_RETURN_CANCEL;
+ menu->menuretval = UI_RETURN_CANCEL;
break;
case AKEY:
@@ -8801,13 +9505,11 @@ static int ui_handler_pie(bContext *C, const wmEvent *event, uiPopupBlockHandle
case ZKEY:
{
if ((event->val == KM_PRESS || event->val == KM_DBL_CLICK) &&
- (event->shift == 0) &&
- (event->ctrl == 0) &&
- (event->oskey == 0))
+ !IS_EVENT_MOD(event, shift, ctrl, oskey))
{
for (but = block->buttons.first; but; but = but->next) {
if (but->menu_key == event->type) {
- ui_but_pie_button_activate(C, but, menu, is_click_style);
+ ui_but_pie_button_activate(C, but, menu);
}
}
}
@@ -8828,7 +9530,7 @@ static int ui_handler_pie(bContext *C, const wmEvent *event, uiPopupBlockHandle
CASE_NUM_TO_DIR(9, UI_RADIAL_NE);
{
but = ui_block_pie_dir_activate(block, event, num_dir);
- retval = ui_but_pie_button_activate(C, but, menu, is_click_style);
+ retval = ui_but_pie_button_activate(C, but, menu);
break;
}
#undef CASE_NUM_TO_DIR
@@ -8852,7 +9554,7 @@ static int ui_handle_menus_recursive(
bool do_towards_reinit = false;
/* check if we have a submenu, and handle events for it first */
- but = ui_but_find_activated(menu->region);
+ but = ui_but_find_active_in_region(menu->region);
data = (but) ? but->active : NULL;
submenu = (data) ? data->menu : NULL;
@@ -8879,7 +9581,7 @@ static int ui_handle_menus_recursive(
/* now handle events for our own menu */
if (retval == WM_UI_HANDLER_CONTINUE || event->type == TIMER) {
- const bool do_but_search = (but && ELEM(but->type, SEARCH_MENU, SEARCH_MENU_UNLINK));
+ const bool do_but_search = (but && (but->type == UI_BTYPE_SEARCH_MENU));
if (submenu && submenu->menuretval) {
const bool do_ret_out_parent = (submenu->menuretval & UI_RETURN_OUT_PARENT) != 0;
retval = ui_handle_menu_return_submenu(C, event, menu);
@@ -8901,7 +9603,7 @@ static int ui_handle_menus_recursive(
if (block->flag & UI_BLOCK_MOVEMOUSE_QUIT) {
/* when there is a active search button and we close it,
* we need to reinit the mouse coords [#35346] */
- if (ui_but_find_activated(menu->region) != but) {
+ if (ui_but_find_active_in_region(menu->region) != but) {
do_towards_reinit = true;
}
}
@@ -8910,7 +9612,7 @@ static int ui_handle_menus_recursive(
uiBlock *block = menu->region->uiblocks.first;
if (block->flag & UI_BLOCK_RADIAL)
- retval = ui_handler_pie(C, event, menu);
+ retval = ui_pie_handler(C, event, menu);
else if (event->type == LEFTMOUSE || event->val != KM_DBL_CLICK)
retval = ui_handle_menu_event(C, event, menu, level, is_parent_inside, is_parent_menu, is_floating);
}
@@ -8925,10 +9627,10 @@ static int ui_handle_menus_recursive(
/* *************** UI event handlers **************** */
-static int ui_handler_region(bContext *C, const wmEvent *event, void *UNUSED(userdata))
+static int ui_region_handler(bContext *C, const wmEvent *event, void *UNUSED(userdata))
{
ARegion *ar;
- uiBut *but;
+ uiBut *but, *listbox;
int retval;
/* here we handle buttons at the region level, non-modal */
@@ -8940,12 +9642,13 @@ 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);
+ but = ui_but_find_active_in_region(ar);
+ listbox = ui_list_find_mouse_over(ar, event);
- retval = ui_handler_panel_region(C, event, ar);
+ retval = ui_handler_panel_region(C, event, ar, listbox ? listbox : but);
- if (retval == WM_UI_HANDLER_CONTINUE)
- retval = ui_handle_list_event(C, event, ar);
+ if (retval == WM_UI_HANDLER_CONTINUE && listbox)
+ retval = ui_handle_list_event(C, event, ar, listbox);
if (retval == WM_UI_HANDLER_CONTINUE) {
if (but)
@@ -8964,7 +9667,7 @@ static int ui_handler_region(bContext *C, const wmEvent *event, void *UNUSED(use
return retval;
}
-static void ui_handler_remove_region(bContext *C, void *UNUSED(userdata))
+static void ui_region_handler_remove(bContext *C, void *UNUSED(userdata))
{
bScreen *sc;
ARegion *ar;
@@ -8972,40 +9675,58 @@ static void ui_handler_remove_region(bContext *C, void *UNUSED(userdata))
ar = CTX_wm_region(C);
if (ar == NULL) return;
- uiFreeBlocks(C, &ar->uiblocks);
+ UI_blocklist_free(C, &ar->uiblocks);
sc = CTX_wm_screen(C);
if (sc == NULL) return;
/* delayed apply callbacks, but not for screen level regions, those
* we rather do at the very end after closing them all, which will
- * be done in ui_handler_region/window */
+ * be done in ui_region_handler/window */
if (BLI_findindex(&sc->regionbase, ar) == -1)
ui_apply_but_funcs_after(C);
}
+/* handle buttons at the window level, modal, for example while
+ * number sliding, text editing, or when a menu block is open */
static int ui_handler_region_menu(bContext *C, const wmEvent *event, void *UNUSED(userdata))
{
ARegion *ar;
uiBut *but;
- /* here we handle buttons at the window level, modal, for example
- * while number sliding, text editing, or when a menu block is open */
ar = CTX_wm_menu(C);
if (!ar)
ar = CTX_wm_region(C);
- but = ui_but_find_activated(ar);
+ but = ui_but_find_active_in_region(ar);
if (but) {
+ bScreen *screen = CTX_wm_screen(C);
+ ARegion *ar_temp;
uiBut *but_other;
uiHandleButtonData *data;
+ bool is_inside_menu = false;
+
+ /* look for a popup menu containing the mouse */
+ for (ar_temp = screen->regionbase.first; ar_temp; ar_temp = ar_temp->next) {
+ rcti winrct;
+
+ ui_region_winrct_get_no_margin(ar_temp, &winrct);
+
+ if (BLI_rcti_isect_pt_v(&winrct, &event->x)) {
+ BLI_assert(ar_temp->type->regionid == RGN_TYPE_TEMPORARY);
+
+ is_inside_menu = true;
+ break;
+ }
+ }
/* handle activated button events */
data = but->active;
if ((data->state == BUTTON_STATE_MENU_OPEN) &&
- (but->type == PULLDOWN) &&
+ (is_inside_menu == false) && /* make sure mouse isn't inside another menu (see T43247) */
+ (but->type == UI_BTYPE_PULLDOWN) &&
(but_other = ui_but_find_mouse_over(ar, event)) &&
(but != but_other) &&
(but->type == but_other->type))
@@ -9051,12 +9772,13 @@ static int ui_handler_region_menu(bContext *C, const wmEvent *event, void *UNUSE
}
/* two types of popups, one with operator + enum, other with regular callbacks */
-static int ui_handler_popup(bContext *C, const wmEvent *event, void *userdata)
+static int ui_popup_handler(bContext *C, const wmEvent *event, void *userdata)
{
uiPopupBlockHandle *menu = userdata;
struct ARegion *menu_region;
/* we block all events, this is modal interaction, except for drop events which is described below */
int retval = WM_UI_HANDLER_BREAK;
+ bool reset_pie = false;
menu_region = CTX_wm_menu(C);
CTX_wm_menu_set(C, menu->region);
@@ -9077,9 +9799,17 @@ static int ui_handler_popup(bContext *C, const wmEvent *event, void *userdata)
wmWindow *win = CTX_wm_window(C);
/* copy values, we have to free first (closes region) */
uiPopupBlockHandle temp = *menu;
+ uiBlock *block = menu->region->uiblocks.first;
+
+ /* set last pie event to allow chained pie spawning */
+ if (block->flag & UI_BLOCK_RADIAL) {
+ win->last_pie_event = block->pie_data.event;
+ reset_pie = true;
+ }
ui_popup_block_free(C, menu);
- UI_remove_popup_handlers(&win->modalhandlers, menu);
+ UI_popup_handlers_remove(&win->modalhandlers, menu);
+ CTX_wm_menu_set(C, NULL);
#ifdef USE_DRAG_TOGGLE
{
@@ -9108,12 +9838,20 @@ static int ui_handler_popup(bContext *C, const wmEvent *event, void *userdata)
/* delayed apply callbacks */
ui_apply_but_funcs_after(C);
+ if (reset_pie) {
+ /* reaqcuire window in case pie invalidates it somehow */
+ wmWindow *win = CTX_wm_window(C);
+
+ if (win)
+ win->last_pie_event = EVENT_NONE;
+ }
+
CTX_wm_region_set(C, menu_region);
return retval;
}
-static void ui_handler_remove_popup(bContext *C, void *userdata)
+static void ui_popup_handler_remove(bContext *C, void *userdata)
{
uiPopupBlockHandle *menu = userdata;
@@ -9124,36 +9862,37 @@ static void ui_handler_remove_popup(bContext *C, void *userdata)
ui_apply_but_funcs_after(C);
}
-void UI_add_region_handlers(ListBase *handlers)
+void UI_region_handlers_add(ListBase *handlers)
{
- WM_event_remove_ui_handler(handlers, ui_handler_region, ui_handler_remove_region, NULL, false);
- WM_event_add_ui_handler(NULL, handlers, ui_handler_region, ui_handler_remove_region, NULL, false);
+ WM_event_remove_ui_handler(handlers, ui_region_handler, ui_region_handler_remove, NULL, false);
+ WM_event_add_ui_handler(NULL, handlers, ui_region_handler, ui_region_handler_remove, NULL, 0);
}
-void UI_add_popup_handlers(bContext *C, ListBase *handlers, uiPopupBlockHandle *popup, const bool accept_dbl_click)
+void UI_popup_handlers_add(bContext *C, ListBase *handlers, uiPopupBlockHandle *popup, const char flag)
{
- WM_event_add_ui_handler(C, handlers, ui_handler_popup, ui_handler_remove_popup, popup, accept_dbl_click);
+ WM_event_add_ui_handler(C, handlers, ui_popup_handler, ui_popup_handler_remove, popup, flag);
}
-void UI_remove_popup_handlers(ListBase *handlers, uiPopupBlockHandle *popup)
+void UI_popup_handlers_remove(ListBase *handlers, uiPopupBlockHandle *popup)
{
- WM_event_remove_ui_handler(handlers, ui_handler_popup, ui_handler_remove_popup, popup, false);
+ WM_event_remove_ui_handler(handlers, ui_popup_handler, ui_popup_handler_remove, popup, false);
}
-void UI_remove_popup_handlers_all(bContext *C, ListBase *handlers)
+void UI_popup_handlers_remove_all(bContext *C, ListBase *handlers)
{
- WM_event_free_ui_handler_all(C, handlers, ui_handler_popup, ui_handler_remove_popup);
+ WM_event_free_ui_handler_all(C, handlers, ui_popup_handler, ui_popup_handler_remove);
}
-bool UI_textbutton_activate_rna(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;
for (block = ar->uiblocks.first; block; block = block->next) {
for (but = block->buttons.first; but; but = but->next) {
- if (but->type == TEX) {
+ if (but->type == UI_BTYPE_TEXT) {
if (but->rnaprop && but->rnapoin.data == rna_poin_data) {
if (STREQ(RNA_property_identifier(but->rnaprop), rna_prop_id)) {
break;
@@ -9166,7 +9905,7 @@ bool UI_textbutton_activate_rna(const bContext *C, ARegion *ar,
}
if (but) {
- uiButActiveOnly(C, ar, block, but);
+ UI_but_active_only(C, ar, block, but);
return true;
}
else {
@@ -9182,7 +9921,7 @@ bool UI_textbutton_activate_but(const bContext *C, uiBut *actbut)
for (block = ar->uiblocks.first; block; block = block->next) {
for (but = block->buttons.first; but; but = but->next)
- if (but == actbut && but->type == TEX)
+ if (but == actbut && but->type == UI_BTYPE_TEXT)
break;
if (but)
@@ -9190,7 +9929,7 @@ bool UI_textbutton_activate_but(const bContext *C, uiBut *actbut)
}
if (but) {
- uiButActiveOnly(C, ar, block, but);
+ UI_but_active_only(C, ar, block, but);
return true;
}
else {
@@ -9199,7 +9938,7 @@ bool UI_textbutton_activate_but(const bContext *C, uiBut *actbut)
}
-void ui_button_clipboard_free(void)
+void ui_but_clipboard_free(void)
{
curvemapping_free_data(&but_copypaste_curve);
}
diff --git a/source/blender/editors/interface/interface_icons.c b/source/blender/editors/interface/interface_icons.c
index 51dd9166e46..796a7646b87 100644
--- a/source/blender/editors/interface/interface_icons.c
+++ b/source/blender/editors/interface/interface_icons.c
@@ -51,9 +51,11 @@
#include "BKE_context.h"
#include "BKE_global.h"
#include "BKE_icons.h"
+#include "BKE_appdir.h"
#include "IMB_imbuf.h"
#include "IMB_imbuf_types.h"
+#include "IMB_thumbs.h"
#include "BIF_gl.h"
#include "BIF_glutil.h"
@@ -587,7 +589,7 @@ static void init_internal_icons(void)
#if 0 // temp disabled
if ((btheme != NULL) && btheme->tui.iconfile[0]) {
- char *icondir = BLI_get_folder(BLENDER_DATAFILES, "icons");
+ char *icondir = BKE_appdir_folder_id(BLENDER_DATAFILES, "icons");
char iconfilestr[FILE_MAX];
if (icondir) {
@@ -702,12 +704,12 @@ static void init_iconfile_list(struct ListBase *list)
const char *icondir;
BLI_listbase_clear(list);
- icondir = BLI_get_folder(BLENDER_DATAFILES, "icons");
+ icondir = BKE_appdir_folder_id(BLENDER_DATAFILES, "icons");
if (icondir == NULL)
return;
- totfile = BLI_dir_contents(icondir, &dir);
+ totfile = BLI_filelist_dir_contents(icondir, &dir);
for (i = 0; i < totfile; i++) {
if ((dir[i].type & S_IFREG)) {
@@ -755,7 +757,7 @@ static void init_iconfile_list(struct ListBase *list)
}
}
- BLI_free_filelist(dir, totfile);
+ BLI_filelist_free(dir, totfile);
dir = NULL;
}
@@ -887,11 +889,9 @@ int UI_icon_get_height(int icon_id)
void UI_icons_init(int first_dyn_id)
{
-#ifdef WITH_HEADLESS
- (void)first_dyn_id;
-#else
- init_iconfile_list(&iconfilelist);
BKE_icons_init(first_dyn_id);
+#ifndef WITH_HEADLESS
+ init_iconfile_list(&iconfilelist);
init_internal_icons();
init_brush_icons();
init_matcap_icons();
@@ -900,20 +900,23 @@ void UI_icons_init(int first_dyn_id)
/* Render size for preview images and icons
*/
-static int preview_render_size(enum eIconSizes size)
+int UI_preview_render_size(enum eIconSizes size)
{
switch (size) {
- case ICON_SIZE_ICON: return 32;
- case ICON_SIZE_PREVIEW: return PREVIEW_DEFAULT_HEIGHT;
+ case ICON_SIZE_ICON:
+ return ICON_RENDER_DEFAULT_HEIGHT;
+ case ICON_SIZE_PREVIEW:
+ return PREVIEW_RENDER_DEFAULT_HEIGHT;
+ default:
+ return 0;
}
- return 0;
}
/* Create rect for the icon
*/
static void icon_create_rect(struct PreviewImage *prv_img, enum eIconSizes size)
{
- unsigned int render_size = preview_render_size(size);
+ unsigned int render_size = UI_preview_render_size(size);
if (!prv_img) {
if (G.debug & G_DEBUG)
@@ -922,15 +925,53 @@ static void icon_create_rect(struct PreviewImage *prv_img, enum eIconSizes size)
else if (!prv_img->rect[size]) {
prv_img->w[size] = render_size;
prv_img->h[size] = render_size;
- prv_img->changed[size] = 1;
+ prv_img->flag[size] |= PRV_CHANGED;
prv_img->changed_timestamp[size] = 0;
prv_img->rect[size] = MEM_callocN(render_size * render_size * sizeof(unsigned int), "prv_rect");
}
}
+void ui_icon_ensure_deferred(const bContext *C, const int icon_id, const bool big)
+{
+ Icon *icon = BKE_icon_get(icon_id);
+
+ if (icon) {
+ DrawInfo *di = (DrawInfo *)icon->drawinfo;
+
+ if (!di) {
+ di = icon_create_drawinfo();
+
+ icon->drawinfo = di;
+ icon->drawinfo_free = UI_icons_free_drawinfo;
+ }
+
+ if (di) {
+ if (di->type == ICON_TYPE_PREVIEW) {
+ PreviewImage *prv = (icon->type != 0) ? BKE_previewimg_id_ensure((ID *)icon->obj) : icon->obj;
+
+ if (prv) {
+ const int size = big ? ICON_SIZE_PREVIEW : ICON_SIZE_ICON;
+
+ if (!prv->use_deferred || prv->rect[size] || (prv->flag[size] & PRV_USER_EDITED)) {
+ return;
+ }
+
+ icon_create_rect(prv, size);
+
+ /* Always using job (background) version. */
+ ED_preview_icon_job(C, prv, NULL, prv->rect[size], prv->w[size], prv->h[size]);
+
+ prv->flag[size] &= ~PRV_CHANGED;
+ }
+ }
+ }
+ }
+}
+
/* only called when icon has changed */
/* only call with valid pointer from UI_icon_draw */
-static void icon_set_image(bContext *C, ID *id, PreviewImage *prv_img, enum eIconSizes size)
+static void icon_set_image(
+ const bContext *C, Scene *scene, ID *id, PreviewImage *prv_img, enum eIconSizes size, const bool use_job)
{
if (!prv_img) {
if (G.debug & G_DEBUG)
@@ -938,10 +979,24 @@ static void icon_set_image(bContext *C, ID *id, PreviewImage *prv_img, enum eIco
return;
}
+ if (prv_img->flag[size] & PRV_USER_EDITED) {
+ /* user-edited preview, do not auto-update! */
+ return;
+ }
+
icon_create_rect(prv_img, size);
- ED_preview_icon_job(C, prv_img, id, prv_img->rect[size],
- prv_img->w[size], prv_img->h[size]);
+ if (use_job) {
+ /* Job (background) version */
+ ED_preview_icon_job(C, prv_img, id, prv_img->rect[size], prv_img->w[size], prv_img->h[size]);
+ }
+ else {
+ if (!scene) {
+ scene = CTX_data_scene(C);
+ }
+ /* Immediate version */
+ ED_preview_icon_render(CTX_data_main(C), scene, id, prv_img->rect[size], prv_img->w[size], prv_img->h[size]);
+ }
}
PreviewImage *UI_icon_to_preview(int icon_id)
@@ -950,22 +1005,32 @@ PreviewImage *UI_icon_to_preview(int icon_id)
if (icon) {
DrawInfo *di = (DrawInfo *)icon->drawinfo;
- if (di && di->data.buffer.image) {
- ImBuf *bbuf;
-
- bbuf = IMB_ibImageFromMemory(di->data.buffer.image->datatoc_rect, di->data.buffer.image->datatoc_size, IB_rect, NULL, "<matcap buffer>");
- if (bbuf) {
- PreviewImage *prv = BKE_previewimg_create();
-
- prv->rect[0] = bbuf->rect;
+ if (di) {
+ if (di->type == ICON_TYPE_PREVIEW) {
+ PreviewImage *prv = (icon->type != 0) ? BKE_previewimg_id_ensure((ID *)icon->obj) : icon->obj;
- prv->w[0] = bbuf->x;
- prv->h[0] = bbuf->y;
-
- bbuf->rect = NULL;
- IMB_freeImBuf(bbuf);
-
- return prv;
+ if (prv) {
+ return BKE_previewimg_copy(prv);
+ }
+ }
+ else if (di->data.buffer.image) {
+ ImBuf *bbuf;
+
+ bbuf = IMB_ibImageFromMemory(di->data.buffer.image->datatoc_rect, di->data.buffer.image->datatoc_size,
+ IB_rect, NULL, __func__);
+ if (bbuf) {
+ PreviewImage *prv = BKE_previewimg_create();
+
+ prv->rect[0] = bbuf->rect;
+
+ prv->w[0] = bbuf->x;
+ prv->h[0] = bbuf->y;
+
+ bbuf->rect = NULL;
+ IMB_freeImBuf(bbuf);
+
+ return prv;
+ }
}
}
}
@@ -976,6 +1041,10 @@ static void icon_draw_rect(float x, float y, int w, int h, float UNUSED(aspect),
unsigned int *rect, float alpha, const float rgb[3], const bool is_preview)
{
ImBuf *ima = NULL;
+ int draw_w = w;
+ int draw_h = h;
+ int draw_x = x;
+ int draw_y = y;
/* sanity check */
if (w <= 0 || h <= 0 || w > 2000 || h > 2000) {
@@ -995,21 +1064,34 @@ static void icon_draw_rect(float x, float y, int w, int h, float UNUSED(aspect),
}
/* rect contains image in 'rendersize', we only scale if needed */
- if (rw != w && rh != h) {
+ if (rw != w || rh != h) {
+ /* preserve aspect ratio and center */
+ if (rw > rh) {
+ draw_w = w;
+ draw_h = (int)(((float)rh / (float)rw) * (float)w);
+ draw_y += (h - draw_h) / 2;
+ }
+ else if (rw < rh) {
+ draw_w = (int)(((float)rw / (float)rh) * (float)h);
+ draw_h = h;
+ draw_x += (w - draw_w) / 2;
+ }
+ /* if the image is squared, the draw_ initialization values are good */
+
/* first allocate imbuf for scaling and copy preview into it */
ima = IMB_allocImBuf(rw, rh, 32, IB_rect);
memcpy(ima->rect, rect, rw * rh * sizeof(unsigned int));
- IMB_scaleImBuf(ima, w, h); /* scale it */
+ IMB_scaleImBuf(ima, draw_w, draw_h); /* scale it */
rect = ima->rect;
}
/* draw */
if (is_preview) {
- glaDrawPixelsSafe(x, y, w, h, w, GL_RGBA, GL_UNSIGNED_BYTE, rect);
+ glaDrawPixelsSafe(draw_x, draw_y, draw_w, draw_h, draw_w, GL_RGBA, GL_UNSIGNED_BYTE, rect);
}
else {
- glRasterPos2f(x, y);
- glDrawPixels(w, h, GL_RGBA, GL_UNSIGNED_BYTE, rect);
+ glRasterPos2f(draw_x, draw_y);
+ glDrawPixels(draw_w, draw_h, GL_RGBA, GL_UNSIGNED_BYTE, rect);
}
if (ima)
@@ -1026,8 +1108,9 @@ static void icon_draw_rect(float x, float y, int w, int h, float UNUSED(aspect),
}
}
-static void icon_draw_texture(float x, float y, float w, float h, int ix, int iy,
- int UNUSED(iw), int ih, float alpha, const float rgb[3])
+static void icon_draw_texture(
+ float x, float y, float w, float h, int ix, int iy,
+ int UNUSED(iw), int ih, float alpha, const float rgb[3])
{
float x1, x2, y1, y2;
@@ -1069,16 +1152,20 @@ static void icon_draw_texture(float x, float y, float w, float h, int ix, int iy
static int get_draw_size(enum eIconSizes size)
{
switch (size) {
- case ICON_SIZE_ICON: return ICON_DEFAULT_HEIGHT;
- case ICON_SIZE_PREVIEW: return PREVIEW_DEFAULT_HEIGHT;
+ case ICON_SIZE_ICON:
+ return ICON_DEFAULT_HEIGHT;
+ case ICON_SIZE_PREVIEW:
+ return PREVIEW_DEFAULT_HEIGHT;
+ default:
+ return 0;
}
- return 0;
}
-static void icon_draw_size(float x, float y, int icon_id, float aspect, float alpha, const float rgb[3],
- enum eIconSizes size, int draw_size, const bool UNUSED(nocreate), const bool is_preview)
+static void icon_draw_size(
+ float x, float y, int icon_id, float aspect, float alpha, const float rgb[3],
+ enum eIconSizes size, int draw_size, const bool UNUSED(nocreate), const bool is_preview)
{
bTheme *btheme = UI_GetTheme();
Icon *icon = NULL;
@@ -1134,45 +1221,52 @@ static void icon_draw_size(float x, float y, int icon_id, float aspect, float al
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}
else if (di->type == ICON_TYPE_PREVIEW) {
- PreviewImage *pi = BKE_previewimg_get((ID *)icon->obj);
+ PreviewImage *pi = (icon->type != 0) ? BKE_previewimg_id_ensure((ID *)icon->obj) : icon->obj;
if (pi) {
/* no create icon on this level in code */
if (!pi->rect[size]) return; /* something has gone wrong! */
/* preview images use premul alpha ... */
- glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
- icon_draw_rect(x, y, w, h, aspect, pi->w[size], pi->h[size], pi->rect[size], 1.0f, NULL, is_preview);
+ if (GLEW_VERSION_1_4) {
+ glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
+ }
+ else {
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ }
+
+ icon_draw_rect(x, y, w, h, aspect, pi->w[size], pi->h[size], pi->rect[size], alpha, rgb, is_preview);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}
}
}
-static void ui_id_preview_image_render_size(bContext *C, ID *id, PreviewImage *pi, int size)
+static void ui_id_preview_image_render_size(
+ const bContext *C, Scene *scene, ID *id, PreviewImage *pi, int size, const bool use_job)
{
- if ((pi->changed[size] || !pi->rect[size])) { /* changed only ever set by dynamic icons */
+ if (((pi->flag[size] & PRV_CHANGED) || !pi->rect[size])) { /* changed only ever set by dynamic icons */
/* create the rect if necessary */
- icon_set_image(C, id, pi, size);
+ icon_set_image(C, scene, id, pi, size, use_job);
- pi->changed[size] = 0;
+ pi->flag[size] &= ~PRV_CHANGED;
}
}
-static void ui_id_icon_render(bContext *C, ID *id, const bool big)
+void UI_id_icon_render(const bContext *C, Scene *scene, ID *id, const bool big, const bool use_job)
{
- PreviewImage *pi = BKE_previewimg_get(id);
+ PreviewImage *pi = BKE_previewimg_id_ensure(id);
if (pi) {
if (big)
- ui_id_preview_image_render_size(C, id, pi, ICON_SIZE_PREVIEW); /* bigger preview size */
+ ui_id_preview_image_render_size(C, scene, id, pi, ICON_SIZE_PREVIEW, use_job); /* bigger preview size */
else
- ui_id_preview_image_render_size(C, id, pi, ICON_SIZE_ICON); /* icon size */
+ ui_id_preview_image_render_size(C, scene, id, pi, ICON_SIZE_ICON, use_job); /* icon size */
}
}
-static void ui_id_brush_render(bContext *C, ID *id)
+static void ui_id_brush_render(const bContext *C, ID *id)
{
- PreviewImage *pi = BKE_previewimg_get(id);
+ PreviewImage *pi = BKE_previewimg_id_ensure(id);
enum eIconSizes i;
if (!pi)
@@ -1181,20 +1275,20 @@ static void ui_id_brush_render(bContext *C, ID *id)
for (i = 0; i < NUM_ICON_SIZES; i++) {
/* check if rect needs to be created; changed
* only set by dynamic icons */
- if ((pi->changed[i] || !pi->rect[i])) {
- icon_set_image(C, id, pi, i);
- pi->changed[i] = 0;
+ if (((pi->flag[i] & PRV_CHANGED) || !pi->rect[i])) {
+ icon_set_image(C, NULL, id, pi, i, true);
+ pi->flag[i] &= ~PRV_CHANGED;
}
}
}
-static int ui_id_brush_get_icon(bContext *C, ID *id)
+static int ui_id_brush_get_icon(const bContext *C, ID *id)
{
Brush *br = (Brush *)id;
if (br->flag & BRUSH_CUSTOM_ICON) {
- BKE_icon_getid(id);
+ BKE_icon_id_ensure(id);
ui_id_brush_render(C, id);
}
else {
@@ -1242,7 +1336,7 @@ static int ui_id_brush_get_icon(bContext *C, ID *id)
return id->icon_id;
}
-int ui_id_icon_get(bContext *C, ID *id, const bool big)
+int ui_id_icon_get(const bContext *C, ID *id, const bool big)
{
int iconid = 0;
@@ -1256,9 +1350,9 @@ int ui_id_icon_get(bContext *C, ID *id, const bool big)
case ID_IM: /* fall through */
case ID_WO: /* fall through */
case ID_LA: /* fall through */
- iconid = BKE_icon_getid(id);
+ iconid = BKE_icon_id_ensure(id);
/* checks if not exists, or changed */
- ui_id_icon_render(C, id, big);
+ UI_id_icon_render(C, NULL, id, big, true);
break;
default:
break;
@@ -1305,8 +1399,73 @@ int UI_rnaptr_icon_get(bContext *C, PointerRNA *ptr, int rnaicon, const bool big
return rnaicon;
}
-static void icon_draw_at_size(float x, float y, int icon_id, float aspect, float alpha,
- enum eIconSizes size, const bool nocreate)
+int UI_idcode_icon_get(const int idcode)
+{
+ switch (idcode) {
+ case ID_AC:
+ return ICON_ANIM_DATA;
+ case ID_AR:
+ return ICON_ARMATURE_DATA;
+ case ID_BR:
+ return ICON_BRUSH_DATA;
+ case ID_CA:
+ return ICON_CAMERA_DATA;
+ case ID_CU:
+ return ICON_CURVE_DATA;
+ case ID_GD:
+ return ICON_GREASEPENCIL;
+ case ID_GR:
+ return ICON_GROUP;
+ case ID_IM:
+ return ICON_IMAGE_DATA;
+ case ID_LA:
+ return ICON_LAMP_DATA;
+ case ID_LS:
+ return ICON_LINE_DATA;
+ case ID_LT:
+ return ICON_LATTICE_DATA;
+ case ID_MA:
+ return ICON_MATERIAL_DATA;
+ case ID_MB:
+ return ICON_META_DATA;
+ case ID_MC:
+ return ICON_CLIP;
+ case ID_ME:
+ return ICON_MESH_DATA;
+ case ID_MSK:
+ return ICON_MOD_MASK; /* TODO! this would need its own icon! */
+ case ID_NT:
+ return ICON_NODETREE;
+ case ID_OB:
+ return ICON_OBJECT_DATA;
+ case ID_PA:
+ return ICON_PARTICLE_DATA;
+ case ID_PAL:
+ return ICON_COLOR; /* TODO! this would need its own icon! */
+ case ID_PC:
+ return ICON_CURVE_BEZCURVE; /* TODO! this would need its own icon! */
+ case ID_SCE:
+ return ICON_SCENE_DATA;
+ case ID_SPK:
+ return ICON_SPEAKER;
+ case ID_SO:
+ return ICON_SOUND;
+ case ID_TE:
+ return ICON_TEXTURE_DATA;
+ case ID_TXT:
+ return ICON_TEXT;
+ case ID_VF:
+ return ICON_FONT_DATA;
+ case ID_WO:
+ return ICON_WORLD_DATA;
+ default:
+ return ICON_NONE;
+ }
+}
+
+static void icon_draw_at_size(
+ float x, float y, int icon_id, float aspect, float alpha,
+ enum eIconSizes size, const bool nocreate)
{
int draw_size = get_draw_size(size);
icon_draw_size(x, y, icon_id, aspect, alpha, NULL, size, draw_size, nocreate, false);
@@ -1344,8 +1503,8 @@ void UI_icon_draw_preview_aspect(float x, float y, int icon_id, float aspect)
icon_draw_at_size(x, y, icon_id, aspect, 1.0f, ICON_SIZE_PREVIEW, 0);
}
-void UI_icon_draw_preview_aspect_size(float x, float y, int icon_id, float aspect, int size)
+void UI_icon_draw_preview_aspect_size(float x, float y, int icon_id, float aspect, float alpha, int size)
{
- icon_draw_size(x, y, icon_id, aspect, 1.0f, NULL, ICON_SIZE_PREVIEW, size, false, true);
+ icon_draw_size(x, y, icon_id, aspect, alpha, NULL, ICON_SIZE_PREVIEW, size, false, true);
}
diff --git a/source/blender/editors/interface/interface_intern.h b/source/blender/editors/interface/interface_intern.h
index 2f66c4a9900..032efad885e 100644
--- a/source/blender/editors/interface/interface_intern.h
+++ b/source/blender/editors/interface/interface_intern.h
@@ -36,14 +36,13 @@
#include "BLI_compiler_attrs.h"
#include "UI_resources.h"
#include "RNA_types.h"
+#include "DNA_listBase.h"
struct ARegion;
struct bContext;
-struct IDProperty;
struct uiHandleButtonData;
struct wmEvent;
struct wmOperatorType;
-struct wmWindow;
struct wmTimer;
struct uiStyle;
struct uiWidgetColors;
@@ -67,7 +66,7 @@ typedef enum {
/* standard set */
UI_WTYPE_LABEL,
UI_WTYPE_TOGGLE,
- UI_WTYPE_OPTION,
+ UI_WTYPE_CHECKBOX,
UI_WTYPE_RADIO,
UI_WTYPE_NUMBER,
UI_WTYPE_SLIDER,
@@ -95,7 +94,7 @@ typedef enum {
UI_WTYPE_ICON,
UI_WTYPE_SWATCH,
UI_WTYPE_RGB_PICKER,
- UI_WTYPE_NORMAL,
+ UI_WTYPE_UNITVEC,
UI_WTYPE_BOX,
UI_WTYPE_SCROLL,
UI_WTYPE_LISTITEM,
@@ -122,6 +121,19 @@ enum {
/* warn: rest of uiBut->flag in UI_interface.h */
};
+/* some buttons display icons only under special conditions
+ * (e.g. 'x' icon in search menu) - used with ui_but_icon_extra_get */
+typedef enum uiButExtraIconType {
+ UI_BUT_ICONEXTRA_NONE = 1,
+ UI_BUT_ICONEXTRA_UNLINK,
+ UI_BUT_ICONEXTRA_EYEDROPPER,
+} uiButExtraIconType;
+
+/* uiBut->dragflag */
+enum {
+ UI_BUT_DRAGPOIN_FREE = (1 << 0),
+};
+
/* but->pie_dir */
typedef enum RadialDirection {
UI_RADIAL_NONE = -1,
@@ -157,7 +169,7 @@ extern const short ui_radial_dir_to_angle[8];
#define UI_BITBUT_SET(a, b) ( (a) | 1 << (b) )
#define UI_BITBUT_CLR(a, b) ( (a) & ~(1 << (b)) )
/* bit-row */
-#define UI_BITBUT_ROW(min, max) (((max) >= 31 ? 0xFFFFFFFF : (1 << (max + 1)) - 1) - ((min) ? ((1 << (min)) - 1) : 0) )
+#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
@@ -168,9 +180,9 @@ enum {
UI_PIE_INITIAL_DIRECTION = (1 << 1), /* use initial center of pie menu to calculate direction */
UI_PIE_DRAG_STYLE = (1 << 2), /* pie menu is drag style */
UI_PIE_INVALID_DIR = (1 << 3), /* mouse not far enough from center position */
- UI_PIE_FINISHED = (1 << 4), /* pie menu finished but we still wait for a release event */
- UI_PIE_CLICK_STYLE = (1 << 5), /* pie menu changed to click style, click to confirm */
- UI_PIE_ANIMATION_FINISHED = (1 << 6), /* pie animation finished, do not calculate any more motio */
+ UI_PIE_CLICK_STYLE = (1 << 4), /* pie menu changed to click style, click to confirm */
+ UI_PIE_ANIMATION_FINISHED = (1 << 5), /* pie animation finished, do not calculate any more motion */
+ UI_PIE_GESTURE_END_WAIT = (1 << 6), /* pie gesture selection has been done, now wait for mouse motion to end */
};
#define PIE_CLICK_THRESHOLD_SQ 50.0f
@@ -212,20 +224,20 @@ struct uiBut {
/* both these values use depends on the button type
* (polymorphic struct or union would be nicer for this stuff) */
- /* (type == HSVCUBE), Use UI_GRAD_* values.
- * (type == NUM), Use to store RNA 'step' value, for dragging and click-step.
- * (type == LABEL), Use (a1 == 1.0f) to use a2 as a blending factor (wow, this is imaginative!).
- * (type == SCROLL) Use as scroll size.
- * (type == SEARCH_MENU) Use as number or rows.
- * (type == COLOR) Use as indication of color palette
+ /* (type == UI_BTYPE_HSVCUBE), Use UI_GRAD_* values.
+ * (type == UI_BTYPE_NUM), Use to store RNA 'step' value, for dragging and click-step.
+ * (type == UI_BTYPE_LABEL), Use (a1 == 1.0f) to use a2 as a blending factor (wow, this is imaginative!).
+ * (type == UI_BTYPE_SCROLL) Use as scroll size.
+ * (type == UI_BTYPE_SEARCH_MENU) Use as number or rows.
+ * (type == UI_BTYPE_COLOR) Use as indication of color palette
*/
float a1;
- /* (type == HSVCIRCLE ), Use to store the luminosity.
- * (type == NUM), Use to store RNA 'precision' value, for dragging and click-step.
- * (type == LABEL), If (a1 == 1.0f) use a2 as a blending factor.
- * (type == SEARCH_MENU) Use as number or columns.
- * (type == COLOR) Use as index in palette (not so good, needs refactor)
+ /* (type == UI_BTYPE_HSVCIRCLE ), Use to store the luminosity.
+ * (type == UI_BTYPE_NUM), Use to store RNA 'precision' value, for dragging and click-step.
+ * (type == UI_BTYPE_LABEL), If (a1 == 1.0f) use a2 as a blending factor.
+ * (type == UI_BTYPE_SEARCH_MENU) Use as number or columns.
+ * (type == UI_BTYPE_COLOR) Use as index in palette (not so good, needs refactor)
*/
float a2;
@@ -253,21 +265,25 @@ struct uiBut {
uiLink *link;
short linkto[2]; /* region relative coords */
- const char *tip, *lockstr;
+ const char *tip;
+ uiButToolTipFunc tip_func;
+ void *tip_argN;
+
+ const char *lockstr;
BIFIconID icon;
bool lock;
- char dt; /* drawtype: UI_EMBOSS, UI_EMBOSSN ... etc, copied from the block */
+ char dt; /* drawtype: UI_EMBOSS, UI_EMBOSS_NONE ... etc, copied from the block */
signed char pie_dir; /* direction in a pie menu, used for collision detection (RadialDirection) */
char changed; /* could be made into a single flag */
unsigned char unit_type; /* so buttons can support unit systems which are not RNA */
short modifier_key;
short iconadd;
- /* BLOCK data */
+ /* UI_BTYPE_BLOCK data */
uiBlockCreateFunc block_create_func;
- /* PULLDOWN/MENU data */
+ /* UI_BTYPE_PULLDOWN/UI_BTYPE_MENU data */
uiMenuCreateFunc menu_create_func;
/* RNA data */
@@ -286,6 +302,7 @@ struct uiBut {
/* Draggable data, type is WM_DRAG_... */
char dragtype;
+ short dragflag;
void *dragpoin;
struct ImBuf *imb;
float imb_scale;
@@ -306,10 +323,22 @@ struct uiBut {
uiBlock *block;
};
+typedef struct ColorPicker {
+ struct ColorPicker *next, *prev;
+ float color_data[3]; /* colr data may be HSV or HSL for now */
+ int representation; /* store hsv/hsl value */
+} ColorPicker;
+
+typedef struct ColorPickerData {
+ ListBase list;
+} ColorPickerData;
+
struct PieMenuData {
float pie_dir[2];
float pie_center_init[2];
float pie_center_spawned[2];
+ float last_pos[2];
+ double duration_gesture;
int flags;
int event; /* initial event used to fire the pie menu, store here so we can query for release */
float alphafac;
@@ -363,7 +392,7 @@ struct uiBlock {
short alignnr;
char direction;
- char dt; /* drawtype: UI_EMBOSS, UI_EMBOSSN ... etc, copied to buttons */
+ char dt; /* drawtype: UI_EMBOSS, UI_EMBOSS_NONE ... etc, copied to buttons */
bool auto_open;
char _pad[7];
double auto_open_last;
@@ -373,7 +402,7 @@ struct uiBlock {
char lock;
char active; /* to keep blocks while drawing and free them afterwards */
char tooltipdisabled; /* to avoid tooltip after click */
- char endblock; /* uiEndBlock done? */
+ char endblock; /* UI_block_end done? */
eBlockBoundsCalc bounds_type; /* for doing delayed */
int mx, my;
@@ -390,7 +419,7 @@ struct uiBlock {
void *evil_C; /* XXX hack for dynamic operator enums */
struct UnitSettings *unit; /* unit system, used a lot for numeric buttons so include here rather then fetching through the scene every time. */
- float _hsv[3]; /* XXX, only access via ui_block_hsv_get() */
+ ColorPickerData color_pickers; /* XXX, only accessed by color picker templates */
bool color_profile; /* color profile for correcting linear colors for display */
@@ -408,7 +437,7 @@ typedef struct uiSafetyRct {
/* interface.c */
-extern void ui_delete_linkline(uiLinkLine *line, uiBut *but);
+extern void ui_linkline_remove(uiLinkLine *line, uiBut *but);
void ui_fontscale(short *points, float aspect);
@@ -420,49 +449,56 @@ extern void ui_block_to_window_rctf(const struct ARegion *ar, uiBlock *block, rc
extern void ui_window_to_block_fl(const struct ARegion *ar, uiBlock *block, float *x, float *y);
extern void ui_window_to_block(const struct ARegion *ar, uiBlock *block, int *x, int *y);
extern void ui_window_to_region(const ARegion *ar, int *x, int *y);
-
-extern double ui_get_but_val(uiBut *but);
-extern void ui_set_but_val(uiBut *but, double value);
-extern void ui_set_but_hsv(uiBut *but);
-extern void ui_get_but_vectorf(uiBut *but, float vec[3]);
-extern void ui_set_but_vectorf(uiBut *but, const float vec[3]);
-
-extern void ui_hsvcircle_vals_from_pos(float *val_rad, float *val_dist, const rcti *rect,
- const float mx, const float my);
+extern void ui_region_to_window(const struct ARegion *ar, int *x, int *y);
+extern void ui_region_winrct_get_no_margin(const struct ARegion *ar, struct rcti *r_rect);
+
+extern double ui_but_value_get(uiBut *but);
+extern void ui_but_value_set(uiBut *but, double value);
+extern void ui_but_hsv_set(uiBut *but);
+extern void ui_but_v3_get(uiBut *but, float vec[3]);
+extern void ui_but_v3_set(uiBut *but, const float vec[3]);
+
+extern void ui_hsvcircle_vals_from_pos(
+ float *val_rad, float *val_dist, const rcti *rect,
+ const float mx, const float my);
extern void ui_hsvcircle_pos_from_vals(struct uiBut *but, const rcti *rect, float *hsv, float *xpos, float *ypos);
extern void ui_hsvcube_pos_from_vals(struct uiBut *but, const rcti *rect, float *hsv, float *xp, float *yp);
-bool ui_color_picker_use_display_colorspace(struct uiBut *but);
+bool ui_but_is_colorpicker_display_space(struct uiBut *but);
+
+extern void ui_but_string_get_ex(uiBut *but, char *str, const size_t maxlen, const int float_precision) ATTR_NONNULL();
+extern void ui_but_string_get(uiBut *but, char *str, const size_t maxlen) ATTR_NONNULL();
+extern void ui_but_convert_to_unit_alt_name(uiBut *but, char *str, size_t maxlen) ATTR_NONNULL();
+extern bool ui_but_string_set(struct bContext *C, uiBut *but, const char *str) ATTR_NONNULL();
+extern bool ui_but_string_set_eval_num(struct bContext *C, uiBut *but, const char *str, double *value) ATTR_NONNULL();
+extern int ui_but_string_get_max_length(uiBut *but);
+extern uiBut *ui_but_drag_multi_edit_get(uiBut *but);
-extern void ui_get_but_string_ex(uiBut *but, char *str, const size_t maxlen, const int float_precision) ATTR_NONNULL();
-extern void ui_get_but_string(uiBut *but, char *str, const size_t maxlen) ATTR_NONNULL();
-extern void ui_convert_to_unit_alt_name(uiBut *but, char *str, size_t maxlen) ATTR_NONNULL();
-extern bool ui_set_but_string(struct bContext *C, uiBut *but, const char *str) ATTR_NONNULL();
-extern bool ui_set_but_string_eval_num(struct bContext *C, uiBut *but, const char *str, double *value) ATTR_NONNULL();
-extern int ui_get_but_string_max_length(uiBut *but);
-extern uiBut *ui_get_but_drag_multi_edit(uiBut *but);
+void ui_def_but_icon(uiBut *but, const int icon, const int flag);
+extern uiButExtraIconType ui_but_icon_extra_get(uiBut *but);
-extern void ui_set_but_default(struct bContext *C, const bool all, const bool use_afterfunc);
+extern void ui_but_default_set(struct bContext *C, const bool all, const bool use_afterfunc);
-extern void ui_check_but(uiBut *but);
-extern bool ui_is_but_float(const uiBut *but) ATTR_WARN_UNUSED_RESULT;
-extern bool ui_is_but_bool(const uiBut *but) ATTR_WARN_UNUSED_RESULT;
-extern bool ui_is_but_unit(const uiBut *but) ATTR_WARN_UNUSED_RESULT;
-extern bool ui_is_but_compatible(const uiBut *but_a, const uiBut *but_b) ATTR_WARN_UNUSED_RESULT;
-extern bool ui_is_but_rna_valid(uiBut *but) ATTR_WARN_UNUSED_RESULT;
-extern bool ui_is_but_utf8(const uiBut *but) ATTR_WARN_UNUSED_RESULT;
-extern bool ui_is_but_search_unlink_visible(const uiBut *but) ATTR_WARN_UNUSED_RESULT;
+extern void ui_but_update(uiBut *but);
+extern bool ui_but_is_float(const uiBut *but) ATTR_WARN_UNUSED_RESULT;
+extern bool ui_but_is_bool(const uiBut *but) ATTR_WARN_UNUSED_RESULT;
+extern bool ui_but_is_unit(const uiBut *but) ATTR_WARN_UNUSED_RESULT;
+extern bool ui_but_is_compatible(const uiBut *but_a, const uiBut *but_b) ATTR_WARN_UNUSED_RESULT;
+extern bool ui_but_is_rna_valid(uiBut *but) ATTR_WARN_UNUSED_RESULT;
+extern bool ui_but_is_utf8(const uiBut *but) ATTR_WARN_UNUSED_RESULT;
+extern bool ui_but_supports_cycling(const uiBut *but) ATTR_WARN_UNUSED_RESULT;
-extern int ui_is_but_push_ex(uiBut *but, double *value) ATTR_WARN_UNUSED_RESULT;
-extern int ui_is_but_push(uiBut *but) ATTR_WARN_UNUSED_RESULT;
+extern int ui_but_is_pushed_ex(uiBut *but, double *value) ATTR_WARN_UNUSED_RESULT;
+extern int ui_but_is_pushed(uiBut *but) ATTR_WARN_UNUSED_RESULT;
-extern void ui_bounds_block(uiBlock *block);
+extern void ui_block_bounds_calc(uiBlock *block);
extern void ui_block_translate(uiBlock *block, int x, int y);
-extern void ui_block_do_align(uiBlock *block);
+extern void ui_block_align_calc(uiBlock *block);
-extern struct ColorManagedDisplay *ui_block_display_get(uiBlock *block);
-void ui_block_to_display_space_v3(uiBlock *block, float pixel[3]);
-void ui_block_to_scene_linear_v3(uiBlock *block, float pixel[3]);
+extern struct ColorManagedDisplay *ui_block_cm_display_get(uiBlock *block);
+void ui_block_cm_to_display_space_v3(uiBlock *block, float pixel[3]);
+void ui_block_cm_to_scene_linear_v3(uiBlock *block, float pixel[3]);
+void ui_block_cm_to_display_space_range(uiBlock *block, float *min, float *max);
/* interface_regions.c */
@@ -538,7 +574,7 @@ void ui_popup_menu_memory_set(uiBlock *block, struct uiBut *but);
void ui_popup_translate(struct bContext *C, struct ARegion *ar, const int mdiff[2]);
-float *ui_block_hsv_get(struct uiBlock *block);
+ColorPicker *ui_block_colorpicker_create(struct uiBlock *block);
void ui_popup_block_scrolltest(struct uiBlock *block);
void ui_rgb_to_color_picker_compat_v(const float rgb[3], float r_cp[3]);
@@ -555,29 +591,34 @@ int ui_searchbox_autocomplete(struct bContext *C, struct ARegion *ar, uiBut *but
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);
-void ui_but_search_test(uiBut *but);
+void ui_but_search_refresh(uiBut *but);
-uiBlock *ui_popup_block_refresh(struct bContext *C, uiPopupBlockHandle *handle,
- ARegion *butregion, uiBut *but);
+uiBlock *ui_popup_block_refresh(
+ struct bContext *C, uiPopupBlockHandle *handle,
+ ARegion *butregion, uiBut *but);
-uiPopupBlockHandle *ui_popup_block_create(struct bContext *C, struct ARegion *butregion, uiBut *but,
- uiBlockCreateFunc create_func, uiBlockHandleCreateFunc handle_create_func,
- void *arg);
-uiPopupBlockHandle *ui_popup_menu_create(struct bContext *C, struct ARegion *butregion, uiBut *but,
- uiMenuCreateFunc create_func, void *arg);
+uiPopupBlockHandle *ui_popup_block_create(
+ struct bContext *C, struct ARegion *butregion, uiBut *but,
+ uiBlockCreateFunc create_func, uiBlockHandleCreateFunc handle_create_func,
+ void *arg);
+uiPopupBlockHandle *ui_popup_menu_create(
+ struct bContext *C, struct ARegion *butregion, uiBut *but,
+ uiMenuCreateFunc create_func, void *arg);
void ui_popup_block_free(struct bContext *C, uiPopupBlockHandle *handle);
-int ui_step_name_menu(uiBut *but, int step);
+int ui_but_menu_step(uiBut *but, int step);
+bool ui_but_menu_step_poll(const uiBut *but);
-struct AutoComplete;
/* interface_panel.c */
-extern int ui_handler_panel_region(struct bContext *C, const struct wmEvent *event, struct ARegion *ar);
+extern int ui_handler_panel_region(
+ struct bContext *C, const struct wmEvent *event,
+ struct ARegion *ar, const uiBut *active_but);
extern void ui_draw_aligned_panel(struct uiStyle *style, uiBlock *block, const rcti *rect, const bool show_pin);
/* interface_draw.c */
-extern void ui_dropshadow(const rctf *rct, float radius, float aspect, float alpha, int select);
+extern void ui_draw_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);
@@ -585,7 +626,7 @@ void ui_draw_but_HISTOGRAM(ARegion *ar, uiBut *but, struct uiWidgetColors *wcol,
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_UNITVEC(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);
@@ -594,25 +635,32 @@ void ui_draw_but_NODESOCKET(ARegion *ar, uiBut *but, struct uiWidgetColors *wcol
/* interface_handlers.c */
PointerRNA *ui_handle_afterfunc_add_operator(struct wmOperatorType *ot, int opcontext, bool create_props);
extern void ui_pan_to_scroll(const struct wmEvent *event, int *type, int *val);
-extern void ui_button_activate_do(struct bContext *C, struct ARegion *ar, uiBut *but);
-extern void ui_button_activate_over(struct bContext *C, struct ARegion *ar, uiBut *but);
-extern void ui_button_execute_begin(struct bContext *C, struct ARegion *ar, uiBut *but, void **active_back);
-extern void ui_button_execute_end(struct bContext *C, struct ARegion *ar, uiBut *but, void *active_back);
-extern void ui_button_active_free(const struct bContext *C, uiBut *but);
-extern bool ui_button_is_active(struct ARegion *ar) ATTR_WARN_UNUSED_RESULT;
-extern int ui_button_open_menu_direction(uiBut *but);
-extern void ui_button_text_password_hide(char password_str[UI_MAX_DRAW_STR], uiBut *but, const bool restore);
-extern uiBut *ui_but_find_activated(struct ARegion *ar);
+extern void ui_but_activate_event(struct bContext *C, struct ARegion *ar, uiBut *but);
+extern void ui_but_activate_over(struct bContext *C, struct ARegion *ar, uiBut *but);
+extern void ui_but_execute_begin(struct bContext *C, struct ARegion *ar, uiBut *but, void **active_back);
+extern void ui_but_execute_end(struct bContext *C, struct ARegion *ar, uiBut *but, void *active_back);
+extern void ui_but_active_free(const struct bContext *C, uiBut *but);
+extern bool ui_but_is_active(struct ARegion *ar) ATTR_WARN_UNUSED_RESULT;
+extern int ui_but_menu_direction(uiBut *but);
+extern void ui_but_text_password_hide(char password_str[UI_MAX_DRAW_STR], uiBut *but, const bool restore);
+extern uiBut *ui_but_find_select_in_enum(uiBut *but, int direction);
+extern uiBut *ui_but_find_active_in_region(struct ARegion *ar);
bool ui_but_is_editable(const uiBut *but);
+bool ui_but_is_editable_as_text(const uiBut *but);
void ui_but_pie_dir_visual(RadialDirection dir, float vec[2]);
void ui_but_pie_dir(RadialDirection dir, float vec[2]);
-void ui_block_calculate_pie_segment(struct uiBlock *block, const float event_xy[2]);
+float ui_block_calc_pie_segment(struct uiBlock *block, const float event_xy[2]);
-void ui_button_clipboard_free(void);
+void ui_but_clipboard_free(void);
void ui_panel_menu(struct bContext *C, ARegion *ar, Panel *pa);
uiBut *ui_but_find_old(uiBlock *block_old, const uiBut *but_new);
uiBut *ui_but_find_new(uiBlock *block_old, const uiBut *but_new);
+#ifdef WITH_INPUT_IME
+void ui_but_ime_reposition(uiBut *but, int x, int y, bool complete);
+struct wmIMEData *ui_but_ime_data_get(uiBut *but);
+#endif
+
/* interface_widgets.c */
void ui_draw_anti_tria(float x1, float y1, float x2, float y2, float x3, float y3);
void ui_draw_anti_roundbox(int mode, float minx, float miny, float maxx, float maxy, float rad, bool use_alpha);
@@ -633,12 +681,14 @@ void ui_draw_menu_item(struct uiFontStyle *fstyle, rcti *rect, const char *name,
void ui_draw_preview_item(struct uiFontStyle *fstyle, rcti *rect, const char *name, int iconid, int state);
#define UI_TEXT_MARGIN_X 0.4f
+#define UI_POPUP_MARGIN (UI_DPI_FAC * 12)
/* interface_style.c */
void uiStyleInit(void);
/* interface_icons.c */
-int ui_id_icon_get(struct bContext *C, struct ID *id, const bool big);
+void ui_icon_ensure_deferred(const struct bContext *C, const int icon_id, const bool big);
+int ui_id_icon_get(const struct bContext *C, struct ID *id, const bool big);
/* resources.c */
void init_userdef_do_versions(void);
@@ -673,5 +723,6 @@ void ui_but_anim_autokey(struct bContext *C, uiBut *but, struct Scene *scene, fl
/* interface_eyedropper.c */
void UI_OT_eyedropper_color(struct wmOperatorType *ot);
void UI_OT_eyedropper_id(struct wmOperatorType *ot);
+void UI_OT_eyedropper_depth(struct wmOperatorType *ot);
#endif /* __INTERFACE_INTERN_H__ */
diff --git a/source/blender/editors/interface/interface_layout.c b/source/blender/editors/interface/interface_layout.c
index c2bd6d307d1..67b4f183c82 100644
--- a/source/blender/editors/interface/interface_layout.c
+++ b/source/blender/editors/interface/interface_layout.c
@@ -43,7 +43,7 @@
#include "BLI_utildefines.h"
#include "BLI_math.h"
-#include "BLF_translation.h"
+#include "BLT_translation.h"
#include "BKE_context.h"
#include "BKE_global.h"
@@ -184,7 +184,7 @@ static const char *ui_item_name_add_colon(const char *name, char namestr[UI_MAX_
return name;
}
-static int ui_item_fit(int item, int pos, int all, int available, int last, int alignment, int *offset)
+static int ui_item_fit(int item, int pos, int all, int available, bool is_last, int alignment, int *offset)
{
if (offset)
*offset = 0;
@@ -195,7 +195,7 @@ static int ui_item_fit(int item, int pos, int all, int available, int last, int
if (all > available) {
/* contents is bigger than available space */
- if (last)
+ if (is_last)
return available - pos;
else
return (item * available) / all;
@@ -203,7 +203,7 @@ static int ui_item_fit(int item, int pos, int all, int available, int last, int
else {
/* contents is smaller or equal to available space */
if (alignment == UI_LAYOUT_ALIGN_EXPAND) {
- if (last)
+ if (is_last)
return available - pos;
else
return (item * available) / all;
@@ -235,9 +235,10 @@ static int ui_text_icon_width(uiLayout *layout, const char *name, int icon, bool
variable = (ui_layout_vary_direction(layout) == UI_ITEM_VARY_X);
if (variable) {
+ const uiFontStyle *fstyle = UI_FSTYLE_WIDGET;
/* it may seem odd that the icon only adds (UI_UNIT_X / 4)
* but taking margins into account its fine */
- return (UI_GetStringWidth(name) +
+ return (UI_fontstyle_string_width(fstyle, name) +
(UI_UNIT_X * ((compact ? 1.25f : 1.50f) +
(icon ? 0.25f : 0.0f))));
}
@@ -286,7 +287,7 @@ static void ui_item_position(uiItem *item, int x, int y, int w, int h)
bitem->but->rect.xmax = x + w;
bitem->but->rect.ymax = y + h;
- ui_check_but(bitem->but); /* for strlen */
+ ui_but_update(bitem->but); /* for strlen */
}
else {
uiLayout *litem = (uiLayout *)item;
@@ -350,14 +351,15 @@ static void ui_layer_but_cb(bContext *C, void *arg_but, void *arg_index)
RNA_property_update(C, ptr, prop);
for (cbut = but->block->buttons.first; cbut; cbut = cbut->next)
- ui_check_but(cbut);
+ ui_but_update(cbut);
}
}
/* create buttons for an item with an RNA array */
-static void ui_item_array(uiLayout *layout, uiBlock *block, const char *name, int icon,
- PointerRNA *ptr, PropertyRNA *prop, int len, int x, int y, int w, int UNUSED(h),
- int expand, int slider, int toggle, int icon_only)
+static void ui_item_array(
+ uiLayout *layout, uiBlock *block, const char *name, int icon,
+ PointerRNA *ptr, PropertyRNA *prop, int len, int x, int y, int w, int UNUSED(h),
+ bool expand, bool slider, bool toggle, bool icon_only)
{
uiStyle *style = layout->root->style;
uiBut *but;
@@ -371,11 +373,11 @@ static void ui_item_array(uiLayout *layout, uiBlock *block, const char *name, in
subtype = RNA_property_subtype(prop);
sub = ui_item_local_sublayout(layout, layout, 1);
- uiBlockSetCurLayout(block, sub);
+ UI_block_layout_set_current(block, sub);
/* create label */
if (name[0])
- uiDefBut(block, LABEL, 0, name, 0, 0, w, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
+ uiDefBut(block, UI_BTYPE_LABEL, 0, name, 0, 0, w, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
/* create buttons */
if (type == PROP_BOOLEAN && ELEM(subtype, PROP_LAYER, PROP_LAYER_MEMBER)) {
@@ -386,7 +388,7 @@ static void ui_item_array(uiLayout *layout, uiBlock *block, const char *name, in
unsigned int layer_used = 0;
unsigned int layer_active = 0;
- uiBlockSetCurLayout(block, uiLayoutAbsolute(layout, false));
+ UI_block_layout_set_current(block, uiLayoutAbsolute(layout, false));
unit = UI_UNIT_X * 0.75;
butw = unit;
@@ -410,7 +412,7 @@ static void ui_item_array(uiLayout *layout, uiBlock *block, const char *name, in
}
for (b = 0; b < cols; b++) {
- uiBlockBeginAlign(block);
+ UI_block_align_begin(block);
for (a = 0; a < colbuts; a++) {
const int layer_num = a + b * colbuts;
@@ -428,7 +430,7 @@ static void ui_item_array(uiLayout *layout, uiBlock *block, const char *name, in
but = uiDefAutoButR(block, ptr, prop, layer_num, "", icon, x + butw * a, y + buth, butw, buth);
if (subtype == PROP_LAYER_MEMBER)
- uiButSetFunc(but, ui_layer_but_cb, but, SET_INT_IN_POINTER(layer_num));
+ UI_but_func_set(but, ui_layer_but_cb, but, SET_INT_IN_POINTER(layer_num));
}
for (a = 0; a < colbuts; a++) {
const int layer_num = a + len / 2 + b * colbuts;
@@ -446,9 +448,9 @@ static void ui_item_array(uiLayout *layout, uiBlock *block, const char *name, in
but = uiDefAutoButR(block, ptr, prop, layer_num, "", icon, x + butw * a, y, butw, buth);
if (subtype == PROP_LAYER_MEMBER)
- uiButSetFunc(but, ui_layer_but_cb, but, SET_INT_IN_POINTER(layer_num));
+ UI_but_func_set(but, ui_layer_but_cb, but, SET_INT_IN_POINTER(layer_num));
}
- uiBlockEndAlign(block);
+ UI_block_align_end(block);
x += colbuts * butw + style->buttonspacex;
}
@@ -457,7 +459,7 @@ static void ui_item_array(uiLayout *layout, uiBlock *block, const char *name, in
int totdim, dim_size[3]; /* 3 == RNA_MAX_ARRAY_DIMENSION */
int row, col;
- uiBlockSetCurLayout(block, uiLayoutAbsolute(layout, true));
+ UI_block_layout_set_current(block, uiLayoutAbsolute(layout, true));
totdim = RNA_property_array_dimension(ptr, prop, dim_size);
if (totdim != 2) return; /* only 2D matrices supported in UI so far */
@@ -470,12 +472,12 @@ static void ui_item_array(uiLayout *layout, uiBlock *block, const char *name, in
row = a / dim_size[0];
but = uiDefAutoButR(block, ptr, prop, a, "", ICON_NONE, x + w * col, y + (dim_size[1] * UI_UNIT_Y) - (row * UI_UNIT_Y), w, UI_UNIT_Y);
- if (slider && but->type == NUM)
- but->type = NUMSLI;
+ if (slider && but->type == UI_BTYPE_NUM)
+ but->type = UI_BTYPE_NUM_SLIDER;
}
}
else if (subtype == PROP_DIRECTION && !expand) {
- uiDefButR_prop(block, BUT_NORMAL, 0, name, x, y, UI_UNIT_X * 3, UI_UNIT_Y * 3, ptr, prop, 0, 0, 0, -1, -1, NULL);
+ uiDefButR_prop(block, UI_BTYPE_UNITVEC, 0, name, x, y, UI_UNIT_X * 3, UI_UNIT_Y * 3, ptr, prop, -1, 0, 0, -1, -1, NULL);
}
else {
/* note, this block of code is a bit arbitrary and has just been made
@@ -500,8 +502,8 @@ static void ui_item_array(uiLayout *layout, uiBlock *block, const char *name, in
}
/* show checkboxes for rna on a non-emboss block (menu for eg) */
- if (type == PROP_BOOLEAN && ELEM(layout->root->block->dt, UI_EMBOSSN, UI_EMBOSSP)) {
- boolarr = MEM_callocN(sizeof(int) * len, "ui_item_array");
+ if (type == PROP_BOOLEAN && ELEM(layout->root->block->dt, UI_EMBOSS_NONE, UI_EMBOSS_PULLDOWN)) {
+ boolarr = MEM_callocN(sizeof(int) * len, __func__);
RNA_property_boolean_get_array(ptr, prop, boolarr);
}
@@ -509,12 +511,12 @@ static void ui_item_array(uiLayout *layout, uiBlock *block, const char *name, in
if (!icon_only) str[0] = RNA_property_array_item_char(prop, a);
if (boolarr) icon = boolarr[a] ? ICON_CHECKBOX_HLT : ICON_CHECKBOX_DEHLT;
but = uiDefAutoButR(block, ptr, prop, a, str, icon, 0, 0, w, UI_UNIT_Y);
- if (slider && but->type == NUM)
- but->type = NUMSLI;
- if (toggle && but->type == OPTION)
- but->type = TOG;
+ if (slider && but->type == UI_BTYPE_NUM)
+ but->type = UI_BTYPE_NUM_SLIDER;
+ if (toggle && but->type == UI_BTYPE_CHECKBOX)
+ but->type = UI_BTYPE_TOGGLE;
if ((a == 0) && (subtype == PROP_AXISANGLE))
- uiButSetUnitType(but, PROP_UNIT_ROTATION);
+ UI_but_unit_type_set(but, PROP_UNIT_ROTATION);
}
if (boolarr) {
@@ -523,7 +525,7 @@ static void ui_item_array(uiLayout *layout, uiBlock *block, const char *name, in
}
}
- uiBlockSetCurLayout(block, layout);
+ UI_block_layout_set_current(block, layout);
}
static void ui_item_enum_expand_handle(bContext *C, void *arg1, void *arg2)
@@ -544,8 +546,9 @@ static void ui_item_enum_expand_handle(bContext *C, void *arg1, void *arg2)
RNA_property_enum_set(&but->rnapoin, but->rnaprop, current_value);
}
}
-static void ui_item_enum_expand(uiLayout *layout, uiBlock *block, PointerRNA *ptr, PropertyRNA *prop,
- const char *uiname, int h, int icon_only)
+static void ui_item_enum_expand(
+ uiLayout *layout, uiBlock *block, PointerRNA *ptr, PropertyRNA *prop,
+ const char *uiname, int h, bool icon_only)
{
/* XXX The way this function currently handles uiname parameter is insane and inconsistent with general UI API:
* * uiname is the *enum property* label.
@@ -571,13 +574,13 @@ static void ui_item_enum_expand(uiLayout *layout, uiBlock *block, PointerRNA *pt
/* we dont want nested rows, cols in menus */
if (radial) {
layout_radial = uiLayoutRadial(layout);
- uiBlockSetCurLayout(block, layout_radial);
+ UI_block_layout_set_current(block, layout_radial);
}
else if (layout->root->type != UI_LAYOUT_MENU) {
- uiBlockSetCurLayout(block, ui_item_local_sublayout(layout, layout, 1));
+ UI_block_layout_set_current(block, ui_item_local_sublayout(layout, layout, 1));
}
else {
- uiBlockSetCurLayout(block, layout);
+ UI_block_layout_set_current(block, layout);
}
for (item = item_array; item->identifier; item++) {
@@ -593,20 +596,20 @@ static void ui_item_enum_expand(uiLayout *layout, uiBlock *block, PointerRNA *pt
itemw = ui_text_icon_width(block->curlayout, icon_only ? "" : name, icon, 0);
if (icon && name[0] && !icon_only)
- but = uiDefIconTextButR_prop(block, ROW, 0, icon, name, 0, 0, itemw, h, ptr, prop, -1, 0, value, -1, -1, NULL);
+ but = uiDefIconTextButR_prop(block, UI_BTYPE_ROW, 0, icon, name, 0, 0, itemw, h, ptr, prop, -1, 0, value, -1, -1, NULL);
else if (icon)
- but = uiDefIconButR_prop(block, ROW, 0, icon, 0, 0, itemw, h, ptr, prop, -1, 0, value, -1, -1, NULL);
+ but = uiDefIconButR_prop(block, UI_BTYPE_ROW, 0, icon, 0, 0, itemw, h, ptr, prop, -1, 0, value, -1, -1, NULL);
else
- but = uiDefButR_prop(block, ROW, 0, name, 0, 0, itemw, h, ptr, prop, -1, 0, value, -1, -1, NULL);
+ but = uiDefButR_prop(block, UI_BTYPE_ROW, 0, name, 0, 0, itemw, h, ptr, prop, -1, 0, value, -1, -1, NULL);
if (RNA_property_flag(prop) & PROP_ENUM_FLAG) {
- uiButSetFunc(but, ui_item_enum_expand_handle, but, SET_INT_IN_POINTER(value));
+ UI_but_func_set(but, ui_item_enum_expand_handle, but, SET_INT_IN_POINTER(value));
}
if (ui_layout_local_dir(layout) != UI_LAYOUT_HORIZONTAL)
but->drawflag |= UI_BUT_TEXT_LEFT;
}
- uiBlockSetCurLayout(block, layout);
+ UI_block_layout_set_current(block, layout);
if (free) {
MEM_freeN(item_array);
@@ -634,16 +637,16 @@ static uiBut *ui_item_with_label(uiLayout *layout, uiBlock *block, const char *n
int labelw;
sub = uiLayoutRow(layout, layout->align);
- uiBlockSetCurLayout(block, sub);
+ UI_block_layout_set_current(block, sub);
if (name[0]) {
- /* XXX UI_GetStringWidth is not accurate */
+ /* XXX UI_fontstyle_string_width is not accurate */
#if 0
- labelw = UI_GetStringWidth(name);
+ labelw = UI_fontstyle_string_width(fstyle, name);
CLAMP(labelw, w / 4, 3 * w / 4);
#endif
labelw = w / 3;
- uiDefBut(block, LABEL, 0, name, x, y, labelw, h, NULL, 0.0, 0.0, 0, 0, "");
+ uiDefBut(block, UI_BTYPE_LABEL, 0, name, x, y, labelw, h, NULL, 0.0, 0.0, 0, 0, "");
w = w - labelw;
}
@@ -651,43 +654,46 @@ static uiBut *ui_item_with_label(uiLayout *layout, uiBlock *block, const char *n
subtype = RNA_property_subtype(prop);
if (subtype == PROP_FILEPATH || subtype == PROP_DIRPATH) {
- uiBlockSetCurLayout(block, uiLayoutRow(sub, true));
+ UI_block_layout_set_current(block, uiLayoutRow(sub, true));
but = uiDefAutoButR(block, ptr, prop, index, "", icon, x, y, w - UI_UNIT_X, h);
- /* BUTTONS_OT_file_browse calls uiFileBrowseContextProperty */
- uiDefIconButO(block, BUT, subtype == PROP_DIRPATH ? "BUTTONS_OT_directory_browse" : "BUTTONS_OT_file_browse",
+ /* BUTTONS_OT_file_browse calls UI_context_active_but_prop_get_filebrowser */
+ uiDefIconButO(block, UI_BTYPE_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);
+ uiDefButR_prop(block, UI_BTYPE_KEY_EVENT, 0, name, x, y, w, h, ptr, prop, index, 0, 0, -1, -1, NULL);
}
else if (flag & UI_ITEM_R_FULL_EVENT) {
if (RNA_struct_is_a(ptr->type, &RNA_KeyMapItem)) {
char buf[128];
- WM_keymap_item_to_string(ptr->data, buf, sizeof(buf));
+ WM_keymap_item_to_string(ptr->data, false, sizeof(buf), buf);
- but = uiDefButR_prop(block, HOTKEYEVT, 0, buf, x, y, w, h, ptr, prop, 0, 0, 0, -1, -1, NULL);
- uiButSetFunc(but, ui_keymap_but_cb, but, NULL);
+ but = uiDefButR_prop(block, UI_BTYPE_HOTKEY_EVENT, 0, buf, x, y, w, h, ptr, prop, 0, 0, 0, -1, -1, NULL);
+ UI_but_func_set(but, ui_keymap_but_cb, but, NULL);
if (flag & UI_ITEM_R_IMMEDIATE)
- uiButSetFlag(but, UI_BUT_IMMEDIATE);
+ UI_but_flag_enable(but, UI_BUT_IMMEDIATE);
}
}
else
but = uiDefAutoButR(block, ptr, prop, index, (type == PROP_ENUM && !(flag & UI_ITEM_R_ICON_ONLY)) ? NULL : "", icon, x, y, w, h);
- uiBlockSetCurLayout(block, layout);
+ UI_block_layout_set_current(block, layout);
return but;
}
-void uiFileBrowseContextProperty(const bContext *C, PointerRNA *ptr, PropertyRNA **prop)
+void UI_context_active_but_prop_get_filebrowser(
+ const bContext *C,
+ PointerRNA *r_ptr, PropertyRNA **r_prop, bool *r_is_undo)
{
ARegion *ar = CTX_wm_region(C);
uiBlock *block;
uiBut *but, *prevbut;
- memset(ptr, 0, sizeof(*ptr));
- *prop = NULL;
+ memset(r_ptr, 0, sizeof(*r_ptr));
+ *r_prop = NULL;
+ *r_is_undo = false;
if (!ar)
return;
@@ -699,8 +705,9 @@ void uiFileBrowseContextProperty(const bContext *C, PointerRNA *ptr, PropertyRNA
/* find the button before the active one */
if ((but->flag & UI_BUT_LAST_ACTIVE) && prevbut && prevbut->rnapoin.data) {
if (RNA_property_type(prevbut->rnaprop) == PROP_STRING) {
- *ptr = prevbut->rnapoin;
- *prop = prevbut->rnaprop;
+ *r_ptr = prevbut->rnapoin;
+ *r_prop = prevbut->rnaprop;
+ *r_is_undo = (prevbut->flag & UI_BUT_UNDO) != 0;
return;
}
}
@@ -729,14 +736,14 @@ static void ui_item_disabled(uiLayout *layout, const char *name)
uiBut *but;
int w;
- uiBlockSetCurLayout(block, layout);
+ UI_block_layout_set_current(block, layout);
if (!name)
name = "";
w = ui_text_icon_width(layout, name, 0, 0);
- but = uiDefBut(block, LABEL, 0, name, 0, 0, w, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
+ but = uiDefBut(block, UI_BTYPE_LABEL, 0, name, 0, 0, w, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
but->flag |= UI_BUT_DISABLED;
but->lock = true;
but->lockstr = "";
@@ -760,24 +767,24 @@ PointerRNA uiItemFullO_ptr(uiLayout *layout, wmOperatorType *ot, const char *nam
icon = ICON_BLANK1;
/* create button */
- uiBlockSetCurLayout(block, layout);
+ UI_block_layout_set_current(block, layout);
w = ui_text_icon_width(layout, name, icon, 0);
if (flag & UI_ITEM_R_NO_BG)
- uiBlockSetEmboss(block, UI_EMBOSSN);
+ UI_block_emboss_set(block, UI_EMBOSS_NONE);
/* create the button */
if (icon) {
if (name[0]) {
- but = uiDefIconTextButO_ptr(block, BUT, ot, context, icon, name, 0, 0, w, UI_UNIT_Y, NULL);
+ but = uiDefIconTextButO_ptr(block, UI_BTYPE_BUT, ot, context, icon, name, 0, 0, w, UI_UNIT_Y, NULL);
}
else {
- but = uiDefIconButO_ptr(block, BUT, ot, context, icon, 0, 0, w, UI_UNIT_Y, NULL);
+ but = uiDefIconButO_ptr(block, UI_BTYPE_BUT, ot, context, icon, 0, 0, w, UI_UNIT_Y, NULL);
}
}
else {
- but = uiDefButO_ptr(block, BUT, ot, context, name, 0, 0, w, UI_UNIT_Y, NULL);
+ but = uiDefButO_ptr(block, UI_BTYPE_BUT, ot, context, name, 0, 0, w, UI_UNIT_Y, NULL);
}
assert(but->optype != NULL);
@@ -787,14 +794,14 @@ PointerRNA uiItemFullO_ptr(uiLayout *layout, wmOperatorType *ot, const char *nam
but->drawflag |= UI_BUT_TEXT_LEFT;
if (flag & UI_ITEM_R_NO_BG)
- uiBlockSetEmboss(block, UI_EMBOSS);
+ UI_block_emboss_set(block, UI_EMBOSS);
if (layout->redalert)
- uiButSetFlag(but, UI_BUT_REDALERT);
+ UI_but_flag_enable(but, UI_BUT_REDALERT);
/* assign properties */
if (properties || (flag & UI_ITEM_O_RETURN_PROPS)) {
- PointerRNA *opptr = uiButGetOperatorPtrRNA(but);
+ PointerRNA *opptr = UI_but_operator_ptr_get(but);
if (properties) {
opptr->data = properties;
@@ -876,8 +883,9 @@ void uiItemEnumO(uiLayout *layout, const char *opname, const char *name, int ico
}
-void uiItemsFullEnumO(uiLayout *layout, const char *opname, const char *propname, IDProperty *properties,
- int context, int flag)
+void uiItemsFullEnumO(
+ uiLayout *layout, const char *opname, const char *propname, IDProperty *properties,
+ int context, int flag)
{
wmOperatorType *ot = WM_operatortype_find(opname, 0); /* print error next */
@@ -904,7 +912,7 @@ void uiItemsFullEnumO(uiLayout *layout, const char *opname, const char *propname
if (prop && RNA_property_type(prop) == PROP_ENUM) {
EnumPropertyItem *item, *item_array = NULL;
bool free;
- uiLayout *split;
+ uiLayout *split = NULL;
uiLayout *target;
if (radial) {
@@ -958,7 +966,7 @@ void uiItemsFullEnumO(uiLayout *layout, const char *opname, const char *propname
}
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,
+ but = uiDefBut(block, UI_BTYPE_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);
@@ -977,6 +985,9 @@ void uiItemsFullEnumO(uiLayout *layout, const char *opname, const char *propname
if (free) {
MEM_freeN(item_array);
}
+
+ /* intentionally don't touch UI_BLOCK_IS_FLIP here,
+ * we don't know the context this is called in */
}
else if (prop && RNA_property_type(prop) != PROP_ENUM) {
RNA_warning("%s.%s, not an enum type", RNA_struct_identifier(ptr.type), propname);
@@ -1000,7 +1011,7 @@ void uiItemEnumO_value(uiLayout *layout, const char *name, int icon, const char
PointerRNA ptr;
PropertyRNA *prop;
- UI_OPERATOR_ERROR_RET(ot, opname, return );
+ UI_OPERATOR_ERROR_RET(ot, opname, return);
WM_operator_properties_create_ptr(&ptr, ot);
@@ -1032,7 +1043,7 @@ void uiItemEnumO_string(uiLayout *layout, const char *name, int icon, const char
int value;
bool free;
- UI_OPERATOR_ERROR_RET(ot, opname, return );
+ UI_OPERATOR_ERROR_RET(ot, opname, return);
WM_operator_properties_create_ptr(&ptr, ot);
@@ -1071,7 +1082,7 @@ void uiItemBooleanO(uiLayout *layout, const char *name, int icon, const char *op
wmOperatorType *ot = WM_operatortype_find(opname, 0); /* print error next */
PointerRNA ptr;
- UI_OPERATOR_ERROR_RET(ot, opname, return );
+ UI_OPERATOR_ERROR_RET(ot, opname, return);
WM_operator_properties_create_ptr(&ptr, ot);
RNA_boolean_set(&ptr, propname, value);
@@ -1084,7 +1095,7 @@ void uiItemIntO(uiLayout *layout, const char *name, int icon, const char *opname
wmOperatorType *ot = WM_operatortype_find(opname, 0); /* print error next */
PointerRNA ptr;
- UI_OPERATOR_ERROR_RET(ot, opname, return );
+ UI_OPERATOR_ERROR_RET(ot, opname, return);
WM_operator_properties_create_ptr(&ptr, ot);
RNA_int_set(&ptr, propname, value);
@@ -1097,7 +1108,7 @@ void uiItemFloatO(uiLayout *layout, const char *name, int icon, const char *opna
wmOperatorType *ot = WM_operatortype_find(opname, 0); /* print error next */
PointerRNA ptr;
- UI_OPERATOR_ERROR_RET(ot, opname, return );
+ UI_OPERATOR_ERROR_RET(ot, opname, return);
WM_operator_properties_create_ptr(&ptr, ot);
RNA_float_set(&ptr, propname, value);
@@ -1110,7 +1121,7 @@ void uiItemStringO(uiLayout *layout, const char *name, int icon, const char *opn
wmOperatorType *ot = WM_operatortype_find(opname, 0); /* print error next */
PointerRNA ptr;
- UI_OPERATOR_ERROR_RET(ot, opname, return );
+ UI_OPERATOR_ERROR_RET(ot, opname, return);
WM_operator_properties_create_ptr(&ptr, ot);
RNA_string_set(&ptr, propname, value);
@@ -1125,8 +1136,9 @@ void uiItemO(uiLayout *layout, const char *name, int icon, const char *opname)
/* RNA property items */
-static void ui_item_rna_size(uiLayout *layout, const char *name, int icon, PointerRNA *ptr, PropertyRNA *prop,
- int index, int icon_only, int *r_w, int *r_h)
+static void ui_item_rna_size(
+ uiLayout *layout, const char *name, int icon, PointerRNA *ptr, PropertyRNA *prop,
+ int index, bool icon_only, int *r_w, int *r_h)
{
PropertyType type;
PropertySubType subtype;
@@ -1196,10 +1208,11 @@ void uiItemFullR(uiLayout *layout, PointerRNA *ptr, PropertyRNA *prop, int index
uiBut *but = NULL;
PropertyType type;
char namestr[UI_MAX_NAME_STR];
- int len, w, h, slider, toggle, expand, icon_only, no_bg;
+ int len, w, h;
+ bool slider, toggle, expand, icon_only, no_bg;
bool is_array;
- uiBlockSetCurLayout(block, layout);
+ UI_block_layout_set_current(block, layout);
/* retrieve info */
type = RNA_property_type(prop);
@@ -1232,7 +1245,11 @@ void uiItemFullR(uiLayout *layout, PointerRNA *ptr, PropertyRNA *prop, int index
name = ui_item_name_add_colon(name, namestr);
}
- if (layout->root->type == UI_LAYOUT_MENU) {
+ /* menus and pie-menus don't show checkbox without this */
+ if ((layout->root->type == UI_LAYOUT_MENU) ||
+ /* use checkboxes only as a fallback in pie-menu's, when no icon is defined */
+ ((layout->root->type == UI_LAYOUT_PIEMENU) && (icon == ICON_NONE)))
+ {
if (type == PROP_BOOLEAN && ((is_array == false) || (index != RNA_NO_INDEX))) {
if (is_array) icon = (RNA_property_boolean_get_index(ptr, prop, index)) ? ICON_CHECKBOX_HLT : ICON_CHECKBOX_DEHLT;
else icon = (RNA_property_boolean_get(ptr, prop)) ? ICON_CHECKBOX_HLT : ICON_CHECKBOX_DEHLT;
@@ -1248,17 +1265,17 @@ void uiItemFullR(uiLayout *layout, PointerRNA *ptr, PropertyRNA *prop, int index
}
}
- slider = (flag & UI_ITEM_R_SLIDER);
- toggle = (flag & UI_ITEM_R_TOGGLE);
- expand = (flag & UI_ITEM_R_EXPAND);
- icon_only = (flag & UI_ITEM_R_ICON_ONLY);
- no_bg = (flag & UI_ITEM_R_NO_BG);
+ slider = (flag & UI_ITEM_R_SLIDER) != 0;
+ toggle = (flag & UI_ITEM_R_TOGGLE) != 0;
+ expand = (flag & UI_ITEM_R_EXPAND) != 0;
+ icon_only = (flag & UI_ITEM_R_ICON_ONLY) != 0;
+ no_bg = (flag & UI_ITEM_R_NO_BG) != 0;
/* get size */
ui_item_rna_size(layout, name, icon, ptr, prop, index, icon_only, &w, &h);
if (no_bg)
- uiBlockSetEmboss(block, UI_EMBOSSN);
+ UI_block_emboss_set(block, UI_EMBOSS_NONE);
/* array property */
if (index == RNA_NO_INDEX && is_array)
@@ -1266,11 +1283,11 @@ void uiItemFullR(uiLayout *layout, PointerRNA *ptr, PropertyRNA *prop, int index
/* enum item */
else if (type == PROP_ENUM && index == RNA_ENUM_VALUE) {
if (icon && name[0] && !icon_only)
- uiDefIconTextButR_prop(block, ROW, 0, icon, name, 0, 0, w, h, ptr, prop, -1, 0, value, -1, -1, NULL);
+ uiDefIconTextButR_prop(block, UI_BTYPE_ROW, 0, icon, name, 0, 0, w, h, ptr, prop, -1, 0, value, -1, -1, NULL);
else if (icon)
- uiDefIconButR_prop(block, ROW, 0, icon, 0, 0, w, h, ptr, prop, -1, 0, value, -1, -1, NULL);
+ uiDefIconButR_prop(block, UI_BTYPE_ROW, 0, icon, 0, 0, w, h, ptr, prop, -1, 0, value, -1, -1, NULL);
else
- uiDefButR_prop(block, ROW, 0, name, 0, 0, w, h, ptr, prop, -1, 0, value, -1, -1, NULL);
+ uiDefButR_prop(block, UI_BTYPE_ROW, 0, name, 0, 0, w, h, ptr, prop, -1, 0, value, -1, -1, NULL);
}
/* expanded enum */
else if (type == PROP_ENUM && (expand || RNA_property_flag(prop) & PROP_ENUM_FLAG))
@@ -1281,29 +1298,29 @@ void uiItemFullR(uiLayout *layout, PointerRNA *ptr, PropertyRNA *prop, int index
ui_but_add_search(but, ptr, prop, NULL, NULL);
if (layout->redalert)
- uiButSetFlag(but, UI_BUT_REDALERT);
+ UI_but_flag_enable(but, UI_BUT_REDALERT);
}
/* single button */
else {
but = uiDefAutoButR(block, ptr, prop, index, name, icon, 0, 0, w, h);
- if (slider && but->type == NUM)
- but->type = NUMSLI;
+ if (slider && but->type == UI_BTYPE_NUM)
+ but->type = UI_BTYPE_NUM_SLIDER;
- if (toggle && but->type == OPTION)
- but->type = TOG;
+ if (toggle && but->type == UI_BTYPE_CHECKBOX)
+ but->type = UI_BTYPE_TOGGLE;
if (layout->redalert)
- uiButSetFlag(but, UI_BUT_REDALERT);
+ UI_but_flag_enable(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 (but && (block->flag & UI_BLOCK_LIST_ITEM) && (but->type == UI_BTYPE_TEXT) && (but->dt & UI_EMBOSS_NONE)) {
+ UI_but_flag_enable(but, UI_BUT_LIST_ITEM);
}
if (no_bg)
- uiBlockSetEmboss(block, UI_EMBOSS);
+ UI_block_emboss_set(block, UI_EMBOSS);
/* ensure text isn't added to icon_only buttons */
if (but && icon_only) {
@@ -1325,11 +1342,23 @@ void uiItemR(uiLayout *layout, PointerRNA *ptr, const char *propname, int flag,
uiItemFullR(layout, ptr, prop, RNA_NO_INDEX, 0, flag, name, icon);
}
+void uiItemEnumR_prop(uiLayout *layout, const char *name, int icon, struct PointerRNA *ptr, PropertyRNA *prop, int value)
+{
+ if (RNA_property_type(prop) != PROP_ENUM) {
+ const char *propname = RNA_property_identifier(prop);
+ ui_item_disabled(layout, propname);
+ RNA_warning("property not an enum: %s.%s", RNA_struct_identifier(ptr->type), propname);
+ return;
+ }
+
+ uiItemFullR(layout, ptr, prop, RNA_ENUM_VALUE, value, 0, name, icon);
+}
+
void uiItemEnumR(uiLayout *layout, const char *name, int icon, struct PointerRNA *ptr, const char *propname, int value)
{
PropertyRNA *prop = RNA_struct_find_property(ptr, propname);
- if (!prop || RNA_property_type(prop) != PROP_ENUM) {
+ if (prop == NULL) {
ui_item_disabled(layout, propname);
RNA_warning("property not found: %s.%s", RNA_struct_identifier(ptr->type), propname);
return;
@@ -1405,7 +1434,7 @@ void uiItemsEnumR(uiLayout *layout, struct PointerRNA *ptr, const char *propname
for (i = 0; i < totitem; i++) {
if (item[i].identifier[0]) {
- uiItemEnumR(column, item[i].name, ICON_NONE, ptr, propname, item[i].value);
+ uiItemEnumR_prop(column, item[i].name, item[i].icon, ptr, prop, item[i].value);
ui_but_tip_from_enum_item(block->buttons.last, &item[i]);
}
else {
@@ -1431,6 +1460,9 @@ void uiItemsEnumR(uiLayout *layout, struct PointerRNA *ptr, const char *propname
MEM_freeN(item);
}
}
+
+ /* intentionally don't touch UI_BLOCK_IS_FLIP here,
+ * we don't know the context this is called in */
}
/* Pointer RNA button with search */
@@ -1444,8 +1476,8 @@ typedef struct CollItemSearch {
static int sort_search_items_list(const void *a, const void *b)
{
- CollItemSearch *cis1 = (CollItemSearch *)a;
- CollItemSearch *cis2 = (CollItemSearch *)b;
+ const CollItemSearch *cis1 = a;
+ const CollItemSearch *cis2 = b;
if (BLI_strcasecmp(cis1->name, cis2->name) > 0)
return 1;
@@ -1460,7 +1492,7 @@ static void rna_search_cb(const struct bContext *C, void *arg_but, const char *s
int i = 0, iconid = 0, flag = RNA_property_flag(but->rnaprop);
ListBase *items_list = MEM_callocN(sizeof(ListBase), "items_list");
CollItemSearch *cis;
- const int skip_filter = !but->changed;
+ const bool skip_filter = !but->changed;
/* build a temporary list of relevant items first */
RNA_PROP_BEGIN (&but->rnasearchpoin, itemptr, but->rnasearchprop)
@@ -1486,7 +1518,7 @@ static void rna_search_cb(const struct bContext *C, void *arg_but, const char *s
BLI_strncpy(name_ui, id->name + 2, sizeof(name_ui));
#endif
name = BLI_strdup(name_ui);
- iconid = ui_id_icon_get((bContext *)C, id, false);
+ iconid = ui_id_icon_get(C, id, false);
}
else {
name = RNA_struct_name_get_alloc(&itemptr, NULL, 0, NULL); /* could use the string length here */
@@ -1508,11 +1540,11 @@ static void rna_search_cb(const struct bContext *C, void *arg_but, const char *s
}
RNA_PROP_END;
- BLI_sortlist(items_list, sort_search_items_list);
+ BLI_listbase_sort(items_list, sort_search_items_list);
/* add search items from temporary list */
for (cis = items_list->first; cis; cis = cis->next) {
- if (false == uiSearchItemAdd(items, cis->name, SET_INT_IN_POINTER(cis->index), cis->iconid)) {
+ if (false == UI_search_item_add(items, cis->name, SET_INT_IN_POINTER(cis->index), cis->iconid)) {
break;
}
}
@@ -1564,11 +1596,14 @@ void ui_but_add_search(uiBut *but, PointerRNA *ptr, PropertyRNA *prop, PointerRN
/* turn button into search button */
if (searchprop) {
- but->type = RNA_property_is_unlink(prop) ? SEARCH_MENU_UNLINK : SEARCH_MENU;
+ but->type = UI_BTYPE_SEARCH_MENU;
but->hardmax = MAX2(but->hardmax, 256.0f);
but->rnasearchpoin = *searchptr;
but->rnasearchprop = searchprop;
but->drawflag |= UI_BUT_ICON_LEFT | UI_BUT_TEXT_LEFT;
+ if (RNA_property_is_unlink(prop)) {
+ but->flag |= UI_BUT_SEARCH_UNLINK;
+ }
if (RNA_property_type(prop) == PROP_ENUM) {
/* XXX, this will have a menu string,
@@ -1576,7 +1611,7 @@ void ui_but_add_search(uiBut *but, PointerRNA *ptr, PropertyRNA *prop, PointerRN
but->str[0] = 0;
}
- uiButSetSearchFunc(but, rna_search_cb, but, NULL, NULL);
+ UI_but_func_search_set(but, rna_search_cb, but, NULL, NULL);
}
}
@@ -1663,19 +1698,23 @@ static void ui_item_menutype_func(bContext *C, uiLayout *layout, void *arg_mt)
if (layout->context)
CTX_store_set(C, NULL);
+
+ /* menus are created flipped (from event handling pov) */
+ layout->root->block->flag ^= UI_BLOCK_IS_FLIP;
}
-static uiBut *ui_item_menu(uiLayout *layout, const char *name, int icon, uiMenuCreateFunc func, void *arg, void *argN,
- const char *tip, bool force_menu)
+static uiBut *ui_item_menu(
+ uiLayout *layout, const char *name, int icon, uiMenuCreateFunc func, void *arg, void *argN,
+ const char *tip, bool force_menu)
{
uiBlock *block = layout->root->block;
uiBut *but;
int w, h;
- uiBlockSetCurLayout(block, layout);
+ UI_block_layout_set_current(block, layout);
if (layout->root->type == UI_LAYOUT_HEADER)
- uiBlockSetEmboss(block, UI_EMBOSS);
+ UI_block_emboss_set(block, UI_EMBOSS);
if (!name)
name = "";
@@ -1709,12 +1748,12 @@ static uiBut *ui_item_menu(uiLayout *layout, const char *name, int icon, uiMenuC
}
if (layout->root->type == UI_LAYOUT_HEADER) {
- uiBlockSetEmboss(block, UI_EMBOSS);
+ UI_block_emboss_set(block, UI_EMBOSS);
}
if (ELEM(layout->root->type, UI_LAYOUT_PANEL, UI_LAYOUT_TOOLBAR) ||
(force_menu && layout->root->type != UI_LAYOUT_MENU)) /* We never want a dropdown in menu! */
{
- uiButSetMenuFromPulldown(but);
+ UI_but_type_set_menu_from_pulldown(but);
}
return but;
@@ -1748,7 +1787,7 @@ static uiBut *uiItemL_(uiLayout *layout, const char *name, int icon)
uiBut *but;
int w;
- uiBlockSetCurLayout(block, layout);
+ UI_block_layout_set_current(block, layout);
if (!name)
name = "";
@@ -1758,11 +1797,11 @@ static uiBut *uiItemL_(uiLayout *layout, const char *name, int icon)
w = ui_text_icon_width(layout, name, icon, 0);
if (icon && name[0])
- but = uiDefIconTextBut(block, LABEL, 0, icon, name, 0, 0, w, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
+ but = uiDefIconTextBut(block, UI_BTYPE_LABEL, 0, icon, name, 0, 0, w, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
else if (icon)
- but = uiDefIconBut(block, LABEL, 0, icon, 0, 0, w, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
+ but = uiDefIconBut(block, UI_BTYPE_LABEL, 0, icon, 0, 0, w, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
else
- but = uiDefBut(block, LABEL, 0, name, 0, 0, w, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
+ but = uiDefBut(block, UI_BTYPE_LABEL, 0, name, 0, 0, w, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
/* to compensate for string size padding in ui_text_icon_width,
* make text aligned right if the layout is aligned right.
@@ -1791,7 +1830,7 @@ void uiItemLDrag(uiLayout *layout, PointerRNA *ptr, const char *name, int icon)
if (ptr && ptr->type)
if (RNA_struct_is_ID(ptr->type))
- uiButSetDragID(but, ptr->id.data);
+ UI_but_drag_set_id(but, ptr->id.data);
}
@@ -1803,7 +1842,7 @@ void uiItemV(uiLayout *layout, const char *name, int icon, int argval)
int *retvalue = (block->handle) ? &block->handle->retvalue : NULL;
int w;
- uiBlockSetCurLayout(block, layout);
+ UI_block_layout_set_current(block, layout);
if (!name)
name = "";
@@ -1813,11 +1852,11 @@ void uiItemV(uiLayout *layout, const char *name, int icon, int argval)
w = ui_text_icon_width(layout, name, icon, 0);
if (icon && name[0])
- uiDefIconTextButI(block, BUT, argval, icon, name, 0, 0, w, UI_UNIT_Y, retvalue, 0.0, 0.0, 0, -1, "");
+ uiDefIconTextButI(block, UI_BTYPE_BUT, argval, icon, name, 0, 0, w, UI_UNIT_Y, retvalue, 0.0, 0.0, 0, -1, "");
else if (icon)
- uiDefIconButI(block, BUT, argval, icon, 0, 0, w, UI_UNIT_Y, retvalue, 0.0, 0.0, 0, -1, "");
+ uiDefIconButI(block, UI_BTYPE_BUT, argval, icon, 0, 0, w, UI_UNIT_Y, retvalue, 0.0, 0.0, 0, -1, "");
else
- uiDefButI(block, BUT, argval, name, 0, 0, w, UI_UNIT_Y, retvalue, 0.0, 0.0, 0, -1, "");
+ uiDefButI(block, UI_BTYPE_BUT, argval, name, 0, 0, w, UI_UNIT_Y, retvalue, 0.0, 0.0, 0, -1, "");
}
/* separator item */
@@ -1827,8 +1866,8 @@ void uiItemS(uiLayout *layout)
bool is_menu = ui_block_is_menu(block);
int space = (is_menu) ? 0.45f * UI_UNIT_X : 0.3f * UI_UNIT_X;
- uiBlockSetCurLayout(block, layout);
- uiDefBut(block, (is_menu) ? SEPRLINE : SEPR, 0, "", 0, 0, space, space, NULL, 0.0, 0.0, 0, 0, "");
+ UI_block_layout_set_current(block, layout);
+ uiDefBut(block, (is_menu) ? UI_BTYPE_SEPR_LINE : UI_BTYPE_SEPR, 0, "", 0, 0, space, space, NULL, 0.0, 0.0, 0, 0, "");
}
/* level items */
@@ -1856,8 +1895,10 @@ static void menu_item_enum_opname_menu(bContext *UNUSED(C), uiLayout *layout, vo
uiLayoutSetOperatorContext(layout, lvl->opcontext);
uiItemsEnumO(layout, lvl->opname, lvl->propname);
+ layout->root->block->flag |= UI_BLOCK_IS_FLIP;
+
/* override default, needed since this was assumed pre 2.70 */
- uiBlockSetDirection(layout->root->block, UI_DOWN);
+ UI_block_direction_set(layout->root->block, UI_DIR_DOWN);
}
void uiItemMenuEnumO(uiLayout *layout, bContext *C, const char *opname, const char *propname, const char *name, int icon)
@@ -1866,7 +1907,7 @@ void uiItemMenuEnumO(uiLayout *layout, bContext *C, const char *opname, const ch
MenuItemLevel *lvl;
uiBut *but;
- UI_OPERATOR_ERROR_RET(ot, opname, return );
+ UI_OPERATOR_ERROR_RET(ot, opname, return);
if (!ot->srna) {
ui_item_disabled(layout, opname);
@@ -1895,7 +1936,7 @@ void uiItemMenuEnumO(uiLayout *layout, bContext *C, const char *opname, const ch
{
char keybuf[128];
if (WM_key_event_operator_string(C, ot->idname, layout->root->opcontext, NULL, false,
- keybuf, sizeof(keybuf)))
+ sizeof(keybuf), keybuf))
{
ui_but_add_shortcut(but, keybuf, false);
}
@@ -1908,19 +1949,12 @@ static void menu_item_enum_rna_menu(bContext *UNUSED(C), uiLayout *layout, void
uiLayoutSetOperatorContext(layout, lvl->opcontext);
uiItemsEnumR(layout, &lvl->rnapoin, lvl->propname);
+ layout->root->block->flag |= UI_BLOCK_IS_FLIP;
}
-void uiItemMenuEnumR(uiLayout *layout, struct PointerRNA *ptr, const char *propname, const char *name, int icon)
+void uiItemMenuEnumR_prop(uiLayout *layout, struct PointerRNA *ptr, PropertyRNA *prop, const char *name, int icon)
{
MenuItemLevel *lvl;
- PropertyRNA *prop;
-
- prop = RNA_struct_find_property(ptr, propname);
- if (!prop) {
- ui_item_disabled(layout, propname);
- RNA_warning("property not found: %s.%s", RNA_struct_identifier(ptr->type), propname);
- return;
- }
if (!name)
name = RNA_property_ui_name(prop);
@@ -1929,12 +1963,26 @@ void uiItemMenuEnumR(uiLayout *layout, struct PointerRNA *ptr, const char *propn
lvl = MEM_callocN(sizeof(MenuItemLevel), "MenuItemLevel");
lvl->rnapoin = *ptr;
- BLI_strncpy(lvl->propname, propname, sizeof(lvl->propname));
+ BLI_strncpy(lvl->propname, RNA_property_identifier(prop), sizeof(lvl->propname));
lvl->opcontext = layout->root->opcontext;
ui_item_menu(layout, name, icon, menu_item_enum_rna_menu, NULL, lvl, RNA_property_description(prop), false);
}
+void uiItemMenuEnumR(uiLayout *layout, struct PointerRNA *ptr, const char *propname, const char *name, int icon)
+{
+ PropertyRNA *prop;
+
+ prop = RNA_struct_find_property(ptr, propname);
+ if (!prop) {
+ ui_item_disabled(layout, propname);
+ RNA_warning("property not found: %s.%s", RNA_struct_identifier(ptr->type), propname);
+ return;
+ }
+
+ uiItemMenuEnumR_prop(layout, ptr, prop, name, icon);
+}
+
/**************************** Layout Items ***************************/
/* single-row layout */
@@ -2118,7 +2166,11 @@ static void ui_litem_layout_column(uiLayout *litem)
static RadialDirection ui_get_radialbut_vec(float vec[2], short itemnum)
{
RadialDirection dir;
- BLI_assert(itemnum < 8);
+
+ if (itemnum >= 8) {
+ itemnum %= 8;
+ printf("Warning: Pie menus with more than 8 items are currently unsupported\n");
+ }
dir = ui_radial_dir_order[itemnum];
ui_but_pie_dir(dir, vec);
@@ -2129,7 +2181,7 @@ static RadialDirection ui_get_radialbut_vec(float vec[2], short itemnum)
static bool ui_item_is_radial_displayable(uiItem *item)
{
- if ((item->type == ITEM_BUTTON) && (((uiButtonItem *)item)->but->type == LABEL))
+ if ((item->type == ITEM_BUTTON) && (((uiButtonItem *)item)->but->type == UI_BTYPE_LABEL))
return false;
return true;
@@ -2138,7 +2190,7 @@ static bool ui_item_is_radial_displayable(uiItem *item)
static bool ui_item_is_radial_drawable(uiButtonItem *bitem)
{
- if (ELEM(bitem->but->type, SEPR, SEPRLINE))
+ if (ELEM(bitem->but->type, UI_BTYPE_SEPR, UI_BTYPE_SEPR_LINE))
return false;
return true;
@@ -2194,7 +2246,7 @@ static void ui_litem_layout_radial(uiLayout *litem)
bitem->but->rect.xmax += 1.5f * UI_UNIT_X;
/* enable drawing as pie item if supported by widget */
if (ui_item_is_radial_drawable(bitem))
- bitem->but->dt = UI_EMBOSSR;
+ bitem->but->dt = UI_EMBOSS_RADIAL;
}
ui_item_size(item, &itemw, &itemh);
@@ -2499,7 +2551,7 @@ static void ui_litem_layout_split(uiLayout *litem)
uiLayoutItemSplit *split = (uiLayoutItemSplit *)litem;
uiItem *item;
float percentage;
- const int tot = BLI_countlist(&litem->items);
+ const int tot = BLI_listbase_count(&litem->items);
int itemh, x, y, w, colw = 0;
if (tot == 0)
@@ -2587,7 +2639,7 @@ uiLayout *uiLayoutRow(uiLayout *layout, int align)
litem->w = layout->w;
BLI_addtail(&layout->items, litem);
- uiBlockSetCurLayout(layout->root->block, litem);
+ UI_block_layout_set_current(layout->root->block, litem);
return litem;
}
@@ -2608,7 +2660,7 @@ uiLayout *uiLayoutColumn(uiLayout *layout, int align)
litem->w = layout->w;
BLI_addtail(&layout->items, litem);
- uiBlockSetCurLayout(layout->root->block, litem);
+ UI_block_layout_set_current(layout->root->block, litem);
return litem;
}
@@ -2630,7 +2682,7 @@ uiLayout *uiLayoutColumnFlow(uiLayout *layout, int number, int align)
flow->number = number;
BLI_addtail(&layout->items, flow);
- uiBlockSetCurLayout(layout->root->block, &flow->litem);
+ UI_block_layout_set_current(layout->root->block, &flow->litem);
return &flow->litem;
}
@@ -2650,7 +2702,7 @@ static uiLayoutItemBx *ui_layout_box(uiLayout *layout, int type)
box->litem.w = layout->w;
BLI_addtail(&layout->items, box);
- uiBlockSetCurLayout(layout->root->block, &box->litem);
+ UI_block_layout_set_current(layout->root->block, &box->litem);
box->roundbox = uiDefBut(layout->root->block, type, 0, "", 0, 0, 0, 0, NULL, 0.0, 0.0, 0, 0, "");
@@ -2670,7 +2722,7 @@ uiLayout *uiLayoutRadial(uiLayout *layout)
for (item = layout->root->layout->items.first; item; item = item->next) {
litem = (uiLayout *)item;
if (litem->item.type == ITEM_LAYOUT_RADIAL) {
- uiBlockSetCurLayout(layout->root->block, litem);
+ UI_block_layout_set_current(layout->root->block, litem);
return litem;
}
}
@@ -2685,7 +2737,7 @@ uiLayout *uiLayoutRadial(uiLayout *layout)
litem->w = layout->w;
BLI_addtail(&layout->root->layout->items, litem);
- uiBlockSetCurLayout(layout->root->block, litem);
+ UI_block_layout_set_current(layout->root->block, litem);
return litem;
}
@@ -2693,10 +2745,11 @@ uiLayout *uiLayoutRadial(uiLayout *layout)
uiLayout *uiLayoutBox(uiLayout *layout)
{
- return (uiLayout *)ui_layout_box(layout, ROUNDBOX);
+ return (uiLayout *)ui_layout_box(layout, UI_BTYPE_ROUNDBOX);
}
-/* Check all buttons defined in this layout, and set any button flagged as UI_BUT_LIST_ITEM as active/selected.
+/**
+ * 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)
@@ -2707,15 +2760,16 @@ void ui_layout_list_set_labels_active(uiLayout *layout)
ui_layout_list_set_labels_active((uiLayout *)(&bitem->item));
}
else if (bitem->but->flag & UI_BUT_LIST_ITEM) {
- uiButSetFlag(bitem->but, UI_SELECT);
+ UI_but_flag_enable(bitem->but, UI_SELECT);
}
}
}
-uiLayout *uiLayoutListBox(uiLayout *layout, uiList *ui_list, PointerRNA *ptr, PropertyRNA *prop, PointerRNA *actptr,
- PropertyRNA *actprop)
+uiLayout *uiLayoutListBox(
+ uiLayout *layout, uiList *ui_list, PointerRNA *ptr, PropertyRNA *prop, PointerRNA *actptr,
+ PropertyRNA *actprop)
{
- uiLayoutItemBx *box = ui_layout_box(layout, LISTBOX);
+ uiLayoutItemBx *box = ui_layout_box(layout, UI_BTYPE_LISTBOX);
uiBut *but = box->roundbox;
but->custom_data = ui_list;
@@ -2747,7 +2801,7 @@ uiLayout *uiLayoutAbsolute(uiLayout *layout, int align)
litem->redalert = layout->redalert;
BLI_addtail(&layout->items, litem);
- uiBlockSetCurLayout(layout->root->block, litem);
+ UI_block_layout_set_current(layout->root->block, litem);
return litem;
}
@@ -2775,7 +2829,7 @@ uiLayout *uiLayoutOverlap(uiLayout *layout)
litem->redalert = layout->redalert;
BLI_addtail(&layout->items, litem);
- uiBlockSetCurLayout(layout->root->block, litem);
+ UI_block_layout_set_current(layout->root->block, litem);
return litem;
}
@@ -2797,7 +2851,7 @@ uiLayout *uiLayoutSplit(uiLayout *layout, float percentage, int align)
split->percentage = percentage;
BLI_addtail(&layout->items, split);
- uiBlockSetCurLayout(layout->root->block, &split->litem);
+ UI_block_layout_set_current(layout->root->block, &split->litem);
return &split->litem;
}
@@ -3052,7 +3106,7 @@ static void ui_item_layout(uiItem *item)
static void ui_layout_end(uiBlock *block, uiLayout *layout, int *x, int *y)
{
if (layout->root->handlefunc)
- uiBlockSetHandleFunc(block, layout->root->handlefunc, layout->root->argv);
+ UI_block_func_handle_set(block, layout->root->handlefunc, layout->root->argv);
ui_item_estimate(&layout->item);
ui_item_layout(&layout->item);
@@ -3085,12 +3139,12 @@ static void ui_layout_add_padding_button(uiLayoutRoot *root)
uiLayout *prev_layout = block->curlayout;
block->curlayout = root->layout;
- uiDefBut(block, SEPR, 0, "", 0, 0, root->padding, root->padding, NULL, 0.0, 0.0, 0, 0, "");
+ uiDefBut(block, UI_BTYPE_SEPR, 0, "", 0, 0, root->padding, root->padding, NULL, 0.0, 0.0, 0, 0, "");
block->curlayout = prev_layout;
}
}
-uiLayout *uiBlockLayout(uiBlock *block, int dir, int type, int x, int y, int size, int em, int padding, uiStyle *style)
+uiLayout *UI_block_layout(uiBlock *block, int dir, int type, int x, int y, int size, int em, int padding, uiStyle *style)
{
uiLayout *layout;
uiLayoutRoot *root;
@@ -3145,7 +3199,7 @@ int uiLayoutGetOperatorContext(uiLayout *layout)
}
-void uiBlockSetCurLayout(uiBlock *block, uiLayout *layout)
+void UI_block_layout_set_current(uiBlock *block, uiLayout *layout)
{
block->curlayout = layout;
}
@@ -3176,7 +3230,7 @@ void uiLayoutSetFunc(uiLayout *layout, uiMenuHandleFunc handlefunc, void *argv)
layout->root->argv = argv;
}
-void uiBlockLayoutResolve(uiBlock *block, int *x, int *y)
+void UI_block_layout_resolve(uiBlock *block, int *x, int *y)
{
uiLayoutRoot *root;
@@ -3252,7 +3306,7 @@ static void ui_intro_items(DynStr *ds, ListBase *lb)
/* could also use the INT but this is nicer*/
switch (item->type) {
case ITEM_BUTTON: BLI_dynstr_append(ds, "'type':'BUTTON', "); break;
- case ITEM_LAYOUT_ROW: BLI_dynstr_append(ds, "'type':'ROW', "); break;
+ case ITEM_LAYOUT_ROW: BLI_dynstr_append(ds, "'type':'UI_BTYPE_ROW', "); break;
case ITEM_LAYOUT_COLUMN: BLI_dynstr_append(ds, "'type':'COLUMN', "); break;
case ITEM_LAYOUT_COLUMN_FLOW: BLI_dynstr_append(ds, "'type':'COLUMN_FLOW', "); break;
case ITEM_LAYOUT_ROW_FLOW: BLI_dynstr_append(ds, "'type':'ROW_FLOW', "); break;
@@ -3312,9 +3366,10 @@ static void ui_layout_operator_buts__reset_cb(bContext *UNUSED(C), void *op_pt,
#endif
/* this function does not initialize the layout, functions can be called on the layout before and after */
-void uiLayoutOperatorButs(const bContext *C, uiLayout *layout, wmOperator *op,
- bool (*check_prop)(struct PointerRNA *, struct PropertyRNA *),
- const char label_align, const short flag)
+void uiLayoutOperatorButs(
+ const bContext *C, uiLayout *layout, wmOperator *op,
+ bool (*check_prop)(struct PointerRNA *, struct PropertyRNA *),
+ const char label_align, const short flag)
{
if (!op->properties) {
IDPropertyTemplate val = {0};
@@ -3328,11 +3383,15 @@ void uiLayoutOperatorButs(const bContext *C, uiLayout *layout, wmOperator *op,
/* poll() on this operator may still fail, at the moment there is no nice feedback when this happens
* just fails silently */
if (!WM_operator_repeat_check(C, op)) {
- uiBlockSetButLock(uiLayoutGetBlock(layout), true, "Operator can't' redo");
+ UI_block_lock_set(uiLayoutGetBlock(layout), true, "Operator can't' redo");
/* XXX, could give some nicer feedback or not show redo panel at all? */
uiItemL(layout, IFACE_("* Redo Unsupported *"), ICON_NONE);
}
+ else {
+ /* useful for macros where only one of the steps can't be re-done */
+ UI_block_lock_clear(uiLayoutGetBlock(layout));
+ }
/* menu */
if (op->type->flag & OPTYPE_PRESET) {
@@ -3388,9 +3447,9 @@ void uiLayoutOperatorButs(const bContext *C, uiLayout *layout, wmOperator *op,
col = uiLayoutColumn(layout, false);
block = uiLayoutGetBlock(col);
- but = uiDefIconTextBut(block, BUT, 0, ICON_FILE_REFRESH, IFACE_("Reset"), 0, 0, UI_UNIT_X, UI_UNIT_Y,
+ but = uiDefIconTextBut(block, UI_BTYPE_BUT, 0, ICON_FILE_REFRESH, IFACE_("Reset"), 0, 0, UI_UNIT_X, UI_UNIT_Y,
NULL, 0.0, 0.0, 0.0, 0.0, TIP_("Reset operator defaults"));
- uiButSetFunc(but, ui_layout_operator_buts__reset_cb, op, NULL);
+ UI_but_func_set(but, ui_layout_operator_buts__reset_cb, op, NULL);
}
#endif
@@ -3403,7 +3462,7 @@ void uiLayoutOperatorButs(const bContext *C, uiLayout *layout, wmOperator *op,
for (but = block->buttons.first; but; but = but->next) {
/* no undo for buttons for operator redo panels */
- uiButClearFlag(but, UI_BUT_UNDO);
+ UI_but_flag_disable(but, UI_BUT_UNDO);
/* only for popups, see [#36109] */
@@ -3411,8 +3470,8 @@ void uiLayoutOperatorButs(const bContext *C, uiLayout *layout, wmOperator *op,
* - this is used for allowing operators with popups to rename stuff with fewer clicks
*/
if (is_popup) {
- if ((but->rnaprop == op->type->prop) && (but->type == TEX)) {
- uiButSetFocusOnEnter(CTX_wm_window(C), but);
+ if ((but->rnaprop == op->type->prop) && (but->type == UI_BTYPE_TEXT)) {
+ UI_but_focus_on_enter_event(CTX_wm_window(C), but);
}
}
}
@@ -3420,7 +3479,7 @@ void uiLayoutOperatorButs(const bContext *C, uiLayout *layout, wmOperator *op,
}
/* this is a bit of a hack but best keep it in one place at least */
-MenuType *uiButGetMenuType(uiBut *but)
+MenuType *UI_but_menutype_get(uiBut *but)
{
if (but->menu_create_func == ui_item_menutype_func) {
return (MenuType *)but->poin;
diff --git a/source/blender/editors/interface/interface_ops.c b/source/blender/editors/interface/interface_ops.c
index 817445cc14e..6ac657fa7a3 100644
--- a/source/blender/editors/interface/interface_ops.c
+++ b/source/blender/editors/interface/interface_ops.c
@@ -33,19 +33,20 @@
#include "DNA_screen_types.h"
#include "DNA_text_types.h" /* for UI_OT_reports_to_text */
+#include "DNA_object_types.h" /* for OB_DATA_SUPPORT_ID */
#include "BLI_blenlib.h"
#include "BLI_math_color.h"
#include "BLF_api.h"
-#include "BLF_translation.h"
+#include "BLT_lang.h"
#include "BKE_context.h"
#include "BKE_screen.h"
#include "BKE_global.h"
+#include "BKE_node.h"
#include "BKE_text.h" /* for UI_OT_reports_to_text */
#include "BKE_report.h"
-#include "BKE_paint.h"
#include "RNA_access.h"
#include "RNA_define.h"
@@ -98,7 +99,7 @@ static int copy_data_path_button_poll(bContext *C)
char *path;
int index;
- uiContextActiveProperty(C, &ptr, &prop, &index);
+ UI_context_active_but_prop_get(C, &ptr, &prop, &index);
if (ptr.id.data && ptr.data && prop) {
path = RNA_path_from_ID_to_property(&ptr, prop);
@@ -120,7 +121,7 @@ static int copy_data_path_button_exec(bContext *C, wmOperator *UNUSED(op))
int index;
/* try to create driver using property retrieved from UI */
- uiContextActiveProperty(C, &ptr, &prop, &index);
+ UI_context_active_but_prop_get(C, &ptr, &prop, &index);
if (ptr.id.data && ptr.data && prop) {
path = RNA_path_from_ID_to_property(&ptr, prop);
@@ -160,7 +161,7 @@ static int operator_button_property_finish(bContext *C, PointerRNA *ptr, Propert
RNA_property_update(C, ptr, prop);
/* as if we pressed the button */
- uiContextActivePropertyHandle(C);
+ UI_context_active_but_prop_handle(C);
/* Since we don't want to undo _all_ edits to settings, eg window
* edits on the screen or on operator settings.
@@ -180,7 +181,7 @@ static int reset_default_button_poll(bContext *C)
PropertyRNA *prop;
int index;
- uiContextActiveProperty(C, &ptr, &prop, &index);
+ UI_context_active_but_prop_get(C, &ptr, &prop, &index);
return (ptr.data && prop && RNA_property_editable(&ptr, prop));
}
@@ -193,7 +194,7 @@ static int reset_default_button_exec(bContext *C, wmOperator *op)
const bool all = RNA_boolean_get(op->ptr, "all");
/* try to reset the nominated setting to its default value */
- uiContextActiveProperty(C, &ptr, &prop, &index);
+ UI_context_active_but_prop_get(C, &ptr, &prop, &index);
/* if there is a valid property that is editable... */
if (ptr.data && prop && RNA_property_editable(&ptr, prop)) {
@@ -231,7 +232,7 @@ static int unset_property_button_exec(bContext *C, wmOperator *UNUSED(op))
int index;
/* try to unset the nominated property */
- uiContextActiveProperty(C, &ptr, &prop, &index);
+ UI_context_active_but_prop_get(C, &ptr, &prop, &index);
/* if there is a valid property that is editable... */
if (ptr.data && prop && RNA_property_editable(&ptr, prop) &&
@@ -262,7 +263,7 @@ static void UI_OT_unset_property_button(wmOperatorType *ot)
/* Copy To Selected Operator ------------------------ */
-static bool copy_to_selected_list(
+bool UI_context_copy_to_selected_list(
bContext *C, PointerRNA *ptr, PropertyRNA *prop,
ListBase *r_lb, bool *r_use_path_from_id, char **r_path)
{
@@ -275,9 +276,66 @@ static bool copy_to_selected_list(
else if (RNA_struct_is_a(ptr->type, &RNA_PoseBone)) {
*r_lb = CTX_data_collection_get(C, "selected_pose_bones");
}
+ else if (RNA_struct_is_a(ptr->type, &RNA_Bone)) {
+ ListBase lb;
+ lb = CTX_data_collection_get(C, "selected_pose_bones");
+
+ if (!BLI_listbase_is_empty(&lb)) {
+ CollectionPointerLink *link;
+ for (link = lb.first; link; link = link->next) {
+ bPoseChannel *pchan = link->ptr.data;
+ RNA_pointer_create(link->ptr.id.data, &RNA_Bone, pchan->bone, &link->ptr);
+ }
+ }
+
+ *r_lb = lb;
+ }
else if (RNA_struct_is_a(ptr->type, &RNA_Sequence)) {
*r_lb = CTX_data_collection_get(C, "selected_editable_sequences");
}
+ else if (RNA_struct_is_a(ptr->type, &RNA_Node) ||
+ RNA_struct_is_a(ptr->type, &RNA_NodeSocket))
+ {
+ ListBase lb = {NULL, NULL};
+ char *path = NULL;
+ bNode *node = NULL;
+
+ /* Get the node we're editing */
+ if (RNA_struct_is_a(ptr->type, &RNA_NodeSocket)) {
+ bNodeTree *ntree = ptr->id.data;
+ bNodeSocket *sock = ptr->data;
+ if (nodeFindNode(ntree, sock, &node, NULL)) {
+ if ((path = RNA_path_resolve_from_type_to_property(ptr, prop, &RNA_Node)) != NULL) {
+ /* we're good! */
+ }
+ else {
+ node = NULL;
+ }
+ }
+ }
+ else {
+ node = ptr->data;
+ }
+
+ /* Now filter by type */
+ if (node) {
+ CollectionPointerLink *link, *link_next;
+ lb = CTX_data_collection_get(C, "selected_nodes");
+
+ for (link = lb.first; link; link = link_next) {
+ bNode *node_data = link->ptr.data;
+ link_next = link->next;
+
+ if (node_data->type != node->type) {
+ BLI_remlink(&lb, link);
+ MEM_freeN(link);
+ }
+ }
+ }
+
+ *r_lb = lb;
+ *r_path = path;
+ }
else if (ptr->id.data) {
ID *id = ptr->id.data;
@@ -286,6 +344,51 @@ static bool copy_to_selected_list(
*r_use_path_from_id = true;
*r_path = RNA_path_from_ID_to_property(ptr, prop);
}
+ else if (OB_DATA_SUPPORT_ID(GS(id->name))) {
+ /* check we're using the active object */
+ const short id_code = GS(id->name);
+ ListBase lb = CTX_data_collection_get(C, "selected_editable_objects");
+ char *path = RNA_path_from_ID_to_property(ptr, prop);
+
+ /* de-duplicate obdata */
+ if (!BLI_listbase_is_empty(&lb)) {
+ CollectionPointerLink *link, *link_next;
+
+ for (link = lb.first; link; link = link->next) {
+ Object *ob = link->ptr.id.data;
+ if (ob->data) {
+ ID *id_data = ob->data;
+ id_data->flag |= LIB_DOIT;
+ }
+ }
+
+ for (link = lb.first; link; link = link_next) {
+ Object *ob = link->ptr.id.data;
+ ID *id_data = ob->data;
+ link_next = link->next;
+
+ if ((id_data == NULL) ||
+ (id_data->flag & LIB_DOIT) == 0 ||
+ (id_data->lib) ||
+ (GS(id_data->name) != id_code))
+ {
+ BLI_remlink(&lb, link);
+ MEM_freeN(link);
+ }
+ else {
+ /* avoid prepending 'data' to the path */
+ RNA_id_pointer_create(id_data, &link->ptr);
+ }
+
+ if (id_data) {
+ id_data->flag &= ~LIB_DOIT;
+ }
+ }
+ }
+
+ *r_lb = lb;
+ *r_path = path;
+ }
else if (GS(id->name) == ID_SCE) {
/* Sequencer's ID is scene :/ */
/* Try to recursively find an RNA_Sequence ancestor, to handle situations like T41062... */
@@ -317,7 +420,7 @@ static bool copy_to_selected_button(bContext *C, bool all, bool poll)
int index;
/* try to reset the nominated setting to its default value */
- uiContextActiveProperty(C, &ptr, &prop, &index);
+ UI_context_active_but_prop_get(C, &ptr, &prop, &index);
/* if there is a valid property that is editable... */
if (ptr.data && prop) {
@@ -326,7 +429,7 @@ static bool copy_to_selected_button(bContext *C, bool all, bool poll)
CollectionPointerLink *link;
ListBase lb;
- if (!copy_to_selected_list(C, &ptr, prop, &lb, &use_path_from_id, &path))
+ if (!UI_context_copy_to_selected_list(C, &ptr, prop, &lb, &use_path_from_id, &path))
return success;
for (link = lb.first; link; link = link->next) {
@@ -516,7 +619,7 @@ static bool ui_editsource_uibut_match(uiBut *but_a, uiBut *but_b)
(but_a->rnaprop == but_b->rnaprop) &&
(but_a->optype == but_b->optype) &&
(but_a->unit_type == but_b->unit_type) &&
- (strncmp(but_a->drawstr, but_b->drawstr, UI_MAX_DRAW_STR) == 0))
+ STREQLEN(but_a->drawstr, but_b->drawstr, UI_MAX_DRAW_STR))
{
return true;
}
@@ -554,8 +657,9 @@ void UI_editsource_active_but_test(uiBut *but)
BLI_ghash_insert(ui_editsource_info->hash, but, but_store);
}
-static int editsource_text_edit(bContext *C, wmOperator *op,
- char filepath[FILE_MAX], int line)
+static int editsource_text_edit(
+ bContext *C, wmOperator *op,
+ char filepath[FILE_MAX], int line)
{
struct Main *bmain = CTX_data_main(C);
Text *text;
@@ -595,7 +699,7 @@ static int editsource_text_edit(bContext *C, wmOperator *op,
static int editsource_exec(bContext *C, wmOperator *op)
{
- uiBut *but = uiContextActiveButton(C);
+ uiBut *but = UI_context_active_but_get(C);
if (but) {
GHashIterator ghi;
@@ -605,7 +709,7 @@ static int editsource_exec(bContext *C, wmOperator *op)
int ret;
/* needed else the active button does not get tested */
- uiFreeActiveButtons(C, CTX_wm_screen(C));
+ UI_screen_free_active_but(C, CTX_wm_screen(C));
// printf("%s: begin\n", __func__);
@@ -614,6 +718,7 @@ static int editsource_exec(bContext *C, wmOperator *op)
/* redraw and get active button python info */
ED_region_do_draw(C, ar);
+ ar->do_draw = false;
for (BLI_ghashIterator_init(&ghi, ui_editsource_info->hash);
BLI_ghashIterator_done(&ghi) == false;
@@ -668,10 +773,12 @@ static void UI_OT_editsource(wmOperatorType *ot)
}
/* ------------------------------------------------------------------------- */
-/* EditTranslation utility funcs and operator,
- * Note: this includes utility functions and button matching checks.
- * this only works in conjunction with a py operator! */
+/**
+ * EditTranslation utility funcs and operator,
+ * \note: this includes utility functions and button matching checks.
+ * this only works in conjunction with a py operator!
+ */
static void edittranslation_find_po_file(const char *root, const char *uilng, char *path, const size_t maxlen)
{
char tstr[32]; /* Should be more than enough! */
@@ -715,7 +822,7 @@ static void edittranslation_find_po_file(const char *root, const char *uilng, ch
static int edittranslation_exec(bContext *C, wmOperator *op)
{
- uiBut *but = uiContextActiveButton(C);
+ uiBut *but = UI_context_active_but_get(C);
int ret = OPERATOR_CANCELLED;
if (but) {
@@ -723,7 +830,7 @@ static int edittranslation_exec(bContext *C, wmOperator *op)
PointerRNA ptr;
char popath[FILE_MAX];
const char *root = U.i18ndir;
- const char *uilng = BLF_lang_get();
+ const char *uilng = BLT_lang_get();
uiStringInfo but_label = {BUT_GET_LABEL, NULL};
uiStringInfo rna_label = {BUT_GET_RNA_LABEL, NULL};
@@ -755,7 +862,7 @@ static int edittranslation_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
- uiButGetStrInfo(C, but, &but_label, &rna_label, &enum_label, &but_tip, &rna_tip, &enum_tip,
+ UI_but_string_info_get(C, but, &but_label, &rna_label, &enum_label, &but_tip, &rna_tip, &enum_tip,
&rna_struct, &rna_prop, &rna_enum, &rna_ctxt, NULL);
WM_operator_properties_create_ptr(&ptr, ot);
@@ -818,9 +925,9 @@ static void UI_OT_edittranslation_init(wmOperatorType *ot)
static int reloadtranslation_exec(bContext *UNUSED(C), wmOperator *UNUSED(op))
{
- BLF_lang_init();
+ BLT_lang_init();
BLF_cache_clear();
- BLF_lang_set(NULL);
+ BLT_lang_set(NULL);
UI_reinit_font();
return OPERATOR_FINISHED;
}
@@ -859,7 +966,7 @@ int UI_drop_color_poll(struct bContext *C, wmDrag *drag, const wmEvent *UNUSED(e
void UI_drop_color_copy(wmDrag *drag, wmDropBox *drop)
{
- uiDragColorHandle *drag_info = (uiDragColorHandle *)drag->poin;
+ uiDragColorHandle *drag_info = drag->poin;
RNA_float_set_array(drop->ptr, "color", drag_info->color);
RNA_boolean_set(drop->ptr, "gamma", drag_info->gamma_corrected);
@@ -877,9 +984,9 @@ static int drop_color_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(
/* find button under mouse, check if it has RNA color property and
* if it does copy the data */
- but = ui_but_find_activated(ar);
+ but = ui_but_find_active_in_region(ar);
- if (but && but->type == COLOR && but->rnaprop) {
+ if (but && but->type == UI_BTYPE_COLOR && but->rnaprop) {
const int color_len = RNA_property_array_length(&but->rnapoin, but->rnaprop);
BLI_assert(color_len <= 4);
@@ -890,13 +997,13 @@ static int drop_color_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(
if (RNA_property_subtype(but->rnaprop) == PROP_COLOR_GAMMA) {
if (!gamma)
- ui_block_to_display_space_v3(but->block, color);
+ ui_block_cm_to_display_space_v3(but->block, color);
RNA_property_float_set_array(&but->rnapoin, but->rnaprop, color);
RNA_property_update(C, &but->rnapoin, but->rnaprop);
}
else if (RNA_property_subtype(but->rnaprop) == PROP_COLOR) {
if (gamma)
- ui_block_to_scene_linear_v3(but->block, color);
+ ui_block_cm_to_scene_linear_v3(but->block, color);
RNA_property_float_set_array(&but->rnapoin, but->rnaprop, color);
RNA_property_update(C, &but->rnapoin, but->rnaprop);
}
@@ -922,6 +1029,7 @@ static void UI_OT_drop_color(wmOperatorType *ot)
ot->description = "Drop colors to buttons";
ot->invoke = drop_color_invoke;
+ ot->flag = OPTYPE_INTERNAL;
RNA_def_float_color(ot->srna, "color", 3, NULL, 0.0, FLT_MAX, "Color", "Source color", 0.0, 1.0);
RNA_def_boolean(ot->srna, "gamma", 0, "Gamma Corrected", "The source color is gamma corrected ");
@@ -932,7 +1040,7 @@ static void UI_OT_drop_color(wmOperatorType *ot)
/* ********************************************************* */
/* Registration */
-void UI_buttons_operatortypes(void)
+void ED_button_operatortypes(void)
{
WM_operatortype_append(UI_OT_reset_default_theme);
WM_operatortype_append(UI_OT_copy_data_path_button);
@@ -950,4 +1058,5 @@ void UI_buttons_operatortypes(void)
/* external */
WM_operatortype_append(UI_OT_eyedropper_color);
WM_operatortype_append(UI_OT_eyedropper_id);
+ WM_operatortype_append(UI_OT_eyedropper_depth);
}
diff --git a/source/blender/editors/interface/interface_panel.c b/source/blender/editors/interface/interface_panel.c
index 9265ca0d4b9..5ee7556a042 100644
--- a/source/blender/editors/interface/interface_panel.c
+++ b/source/blender/editors/interface/interface_panel.c
@@ -43,7 +43,7 @@
#include "BLI_math.h"
#include "BLI_utildefines.h"
-#include "BLF_translation.h"
+#include "BLT_translation.h"
#include "DNA_userdef_types.h"
@@ -82,6 +82,14 @@
/* only show pin header button for pinned panels */
#define USE_PIN_HIDDEN
+/* the state of the mouse position relative to the panel */
+typedef enum uiPanelMouseState {
+ PANEL_MOUSE_OUTSIDE, /* mouse is not in the panel */
+ PANEL_MOUSE_INSIDE_CONTENT, /* mouse is in the actual panel content */
+ PANEL_MOUSE_INSIDE_HEADER, /* mouse is in the panel header */
+ PANEL_MOUSE_INSIDE_SCALE, /* mouse is inside panel scale widget */
+} uiPanelMouseState;
+
typedef enum uiHandlePanelState {
PANEL_STATE_DRAG,
PANEL_STATE_DRAG_SCALE,
@@ -202,12 +210,13 @@ static void ui_panel_copy_offset(Panel *pa, Panel *papar)
}
-/* XXX Disabled paneltab handling for now. Old 2.4x feature, *DO NOT* confuse it with new tool tabs in 2.70. ;)
- * See also T41704.
+/**
+ * XXX Disabled paneltab handling for now. Old 2.4x feature, *DO NOT* confuse it with new tool tabs in 2.70. ;)
+ * See also T41704.
*/
/* #define UI_USE_PANELTAB */
-Panel *uiPanelFindByType(ARegion *ar, PanelType *pt)
+Panel *UI_panel_find_by_type(ARegion *ar, PanelType *pt)
{
Panel *pa;
const char *idname = pt->idname;
@@ -233,9 +242,9 @@ Panel *uiPanelFindByType(ARegion *ar, PanelType *pt)
}
/**
- * \note \a pa should be return value from #uiPanelFindByType and can be NULL.
+ * \note \a pa should be return value from #UI_panel_find_by_type and can be NULL.
*/
-Panel *uiBeginPanel(ScrArea *sa, ARegion *ar, uiBlock *block, PanelType *pt, Panel *pa, bool *r_open)
+Panel *UI_panel_begin(ScrArea *sa, ARegion *ar, uiBlock *block, PanelType *pt, Panel *pa, bool *r_open)
{
Panel *palast, *panext;
const char *drawname = CTX_IFACE_(pt->translation_context, pt->label);
@@ -336,7 +345,7 @@ Panel *uiBeginPanel(ScrArea *sa, ARegion *ar, uiBlock *block, PanelType *pt, Pan
return pa;
}
-void uiEndPanel(uiBlock *block, int width, int height)
+void UI_panel_end(uiBlock *block, int width, int height)
{
Panel *pa = block->panel;
@@ -363,12 +372,12 @@ void uiEndPanel(uiBlock *block, int width, int height)
static void ui_offset_panel_block(uiBlock *block)
{
- uiStyle *style = UI_GetStyleDraw();
+ uiStyle *style = UI_style_get_dpi();
uiBut *but;
int ofsy;
/* compute bounds and offset */
- ui_bounds_block(block);
+ ui_block_bounds_calc(block);
ofsy = block->panel->sizey - style->panelspace;
@@ -401,7 +410,7 @@ static void uiPanelPop(uiBlock *UNUSED(block))
#endif
/* triangle 'icon' for panel header */
-void UI_DrawTriIcon(float x, float y, char dir)
+void UI_draw_icon_tri(float x, float y, char dir)
{
float f3 = 0.15 * U.widget_unit;
float f5 = 0.25 * U.widget_unit;
@@ -542,14 +551,14 @@ static void ui_draw_aligned_panel_header(uiStyle *style, uiBlock *block, const r
if (dir == 'h') {
hrect.xmin = rect->xmin + pnl_icons;
hrect.ymin += 2.0f / block->aspect;
- uiStyleFontDraw(&style->paneltitle, &hrect, activename);
+ UI_fontstyle_draw(&style->paneltitle, &hrect, activename);
}
else {
/* ignore 'pnl_icons', otherwise the text gets offset horizontally
* + 0.001f to avoid flirting with float inaccuracy
*/
hrect.xmin = rect->xmin + (PNL_ICON + 5) / block->aspect + 0.001f;
- uiStyleFontDrawRotated(&style->paneltitle, &hrect, activename);
+ UI_fontstyle_draw_rotated(&style->paneltitle, &hrect, activename);
}
}
@@ -560,6 +569,8 @@ void ui_draw_aligned_panel(uiStyle *style, uiBlock *block, const rcti *rect, con
rcti headrect;
rctf itemrect;
int ofsx;
+ const bool is_closed_x = (panel->flag & PNL_CLOSEDX) ? true : false;
+ const bool is_closed_y = (panel->flag & PNL_CLOSEDY) ? true : false;
if (panel->paneltab) return;
if (panel->type && (panel->type->flag & PNL_NO_HEADER)) return;
@@ -572,7 +583,7 @@ void ui_draw_aligned_panel(uiStyle *style, uiBlock *block, const rcti *rect, con
{
float minx = rect->xmin;
- float maxx = rect->xmax;
+ float maxx = is_closed_x ? (minx + PNL_HEADER / block->aspect) : rect->xmax;
float y = headrect.ymax;
glEnable(GL_BLEND);
@@ -587,8 +598,11 @@ void ui_draw_aligned_panel(uiStyle *style, uiBlock *block, const rcti *rect, con
}
else if (!(panel->runtime_flag & PNL_FIRST)) {
/* draw embossed separator */
- minx += 5.0f / block->aspect;
- maxx -= 5.0f / block->aspect;
+
+ if (is_closed_x == false) {
+ minx += 5.0f / block->aspect;
+ maxx -= 5.0f / block->aspect;
+ }
glColor4f(0.0f, 0.0f, 0.0f, 0.5f);
fdrawline(minx, y, maxx, y);
@@ -615,7 +629,7 @@ void ui_draw_aligned_panel(uiStyle *style, uiBlock *block, const rcti *rect, con
}
/* horizontal title */
- if (!(panel->flag & PNL_CLOSEDX)) {
+ if (is_closed_x == false) {
ui_draw_aligned_panel_header(style, block, &headrect, 'h');
/* itemrect smaller */
@@ -631,9 +645,10 @@ void ui_draw_aligned_panel(uiStyle *style, uiBlock *block, const rcti *rect, con
/* if the panel is minimized vertically:
* (------)
*/
- if (panel->flag & PNL_CLOSEDY) {
+ if (is_closed_y) {
+ /* skip */
}
- else if (panel->flag & PNL_CLOSEDX) {
+ else if (is_closed_x) {
/* draw vertical title */
ui_draw_aligned_panel_header(style, block, &headrect, 'v');
}
@@ -641,11 +656,11 @@ void ui_draw_aligned_panel(uiStyle *style, uiBlock *block, const rcti *rect, con
else {
/* in some occasions, draw a border */
if (panel->flag & PNL_SELECT) {
- if (panel->control & UI_PNL_SOLID) uiSetRoundBox(UI_CNR_ALL);
- else uiSetRoundBox(UI_CNR_NONE);
+ if (panel->control & UI_PNL_SOLID) UI_draw_roundbox_corner_set(UI_CNR_ALL);
+ else UI_draw_roundbox_corner_set(UI_CNR_NONE);
UI_ThemeColorShade(TH_BACK, -120);
- uiRoundRect(0.5f + rect->xmin, 0.5f + rect->ymin, 0.5f + rect->xmax, 0.5f + headrect.ymax + 1, 8);
+ UI_draw_roundbox_unfilled(0.5f + rect->xmin, 0.5f + rect->ymin, 0.5f + rect->xmax, 0.5f + headrect.ymax + 1, 8);
}
/* panel backdrop */
@@ -680,9 +695,9 @@ void ui_draw_aligned_panel(uiStyle *style, uiBlock *block, const rcti *rect, con
BLI_rctf_scale(&itemrect, 0.35f);
- if (panel->flag & PNL_CLOSEDY)
+ if (is_closed_y)
ui_draw_tria_rect(&itemrect, 'h');
- else if (panel->flag & PNL_CLOSEDX)
+ else if (is_closed_x)
ui_draw_tria_rect(&itemrect, 'h');
else
ui_draw_tria_rect(&itemrect, 'v');
@@ -729,11 +744,13 @@ typedef struct PanelSort {
Panel *pa, *orig;
} PanelSort;
-/* note about sorting;
+/**
+ * \note about sorting;
* the sortorder has a lower value for new panels being added.
* however, that only works to insert a single panel, when more new panels get
* added the coordinates of existing panels and the previously stored to-be-inserted
- * panels do not match for sorting */
+ * panels do not match for sorting
+ */
static int find_leftmost_panel(const void *a1, const void *a2)
{
@@ -753,9 +770,13 @@ static int find_highest_panel(const void *a1, const void *a2)
const PanelSort *ps1 = a1, *ps2 = a2;
/* stick uppermost header-less panels to the top of the region -
- * prevent them from being sorted */
- if (ps1->pa->sortorder < ps2->pa->sortorder && ps1->pa->type->flag & PNL_NO_HEADER) return -1;
-
+ * prevent them from being sorted (multiple header-less panels have to be sorted though) */
+ if (ps1->pa->type->flag & PNL_NO_HEADER && ps2->pa->type->flag & PNL_NO_HEADER) {
+ /* skip and check for ofs and sortorder below */
+ }
+ else if (ps1->pa->type->flag & PNL_NO_HEADER) return -1;
+ else if (ps2->pa->type->flag & PNL_NO_HEADER) return 1;
+
if (ps1->pa->ofsy + ps1->pa->sizey < ps2->pa->ofsy + ps2->pa->sizey) return 1;
else if (ps1->pa->ofsy + ps1->pa->sizey > ps2->pa->ofsy + ps2->pa->sizey) return -1;
else if (ps1->pa->sortorder > ps2->pa->sortorder) return 1;
@@ -938,7 +959,7 @@ static void ui_do_animate(const bContext *C, Panel *panel)
}
}
-void uiBeginPanels(const bContext *UNUSED(C), ARegion *ar)
+void UI_panels_begin(const bContext *UNUSED(C), ARegion *ar)
{
Panel *pa;
@@ -953,7 +974,7 @@ void uiBeginPanels(const bContext *UNUSED(C), ARegion *ar)
}
/* only draws blocks with panels */
-void uiEndPanels(const bContext *C, ARegion *ar, int *x, int *y)
+void UI_panels_end(const bContext *C, ARegion *ar, int *x, int *y)
{
ScrArea *sa = CTX_wm_area(C);
uiBlock *block;
@@ -1012,7 +1033,7 @@ void uiEndPanels(const bContext *C, ARegion *ar, int *x, int *y)
ui_panels_size(sa, ar, x, y);
}
-void uiDrawPanels(const bContext *C, ARegion *ar)
+void UI_panels_draw(const bContext *C, ARegion *ar)
{
uiBlock *block;
@@ -1021,18 +1042,18 @@ void uiDrawPanels(const bContext *C, ARegion *ar)
/* draw panels, selected on top */
for (block = ar->uiblocks.first; block; block = block->next) {
if (block->active && block->panel && !(block->panel->flag & PNL_SELECT)) {
- uiDrawBlock(C, block);
+ UI_block_draw(C, block);
}
}
for (block = ar->uiblocks.first; block; block = block->next) {
if (block->active && block->panel && (block->panel->flag & PNL_SELECT)) {
- uiDrawBlock(C, block);
+ UI_block_draw(C, block);
}
}
}
-void uiScalePanels(ARegion *ar, float new_width)
+void UI_panels_scale(ARegion *ar, float new_width)
{
uiBlock *block;
uiBut *but;
@@ -1040,7 +1061,6 @@ void uiScalePanels(ARegion *ar, float new_width)
for (block = ar->uiblocks.first; block; block = block->next) {
if (block->panel) {
float fac = new_width / (float)block->panel->sizex;
- printf("scaled %f\n", fac);
block->panel->sizex = new_width;
for (but = block->buttons.first; but; but = but->next) {
@@ -1124,6 +1144,157 @@ static void ui_do_drag(const bContext *C, const wmEvent *event, Panel *panel)
/******************* region level panel interaction *****************/
+static uiPanelMouseState ui_panel_mouse_state_get(const uiBlock *block, const Panel *pa, const int mx, const int my)
+{
+ /* open panel */
+ if (pa->flag & PNL_CLOSEDX) {
+ if ((block->rect.xmin <= mx) && (block->rect.xmin + PNL_HEADER >= mx)) {
+ return PANEL_MOUSE_INSIDE_HEADER;
+ }
+ }
+ /* outside left/right side */
+ else if ((block->rect.xmin > mx) || (block->rect.xmax < mx)) {
+ /* pass */
+ }
+ else if ((block->rect.ymax <= my) && (block->rect.ymax + PNL_HEADER >= my)) {
+ return PANEL_MOUSE_INSIDE_HEADER;
+ }
+ /* open panel */
+ else if (!(pa->flag & PNL_CLOSEDY)) {
+ if (pa->control & UI_PNL_SCALE) {
+ if (block->rect.xmax - PNL_HEADER <= mx) {
+ if (block->rect.ymin + PNL_HEADER >= my) {
+ return PANEL_MOUSE_INSIDE_SCALE;
+ }
+ }
+ }
+ if ((block->rect.xmin <= mx) && (block->rect.xmax >= mx)) {
+ if ((block->rect.ymin <= my) && (block->rect.ymax + PNL_HEADER >= my)) {
+ return PANEL_MOUSE_INSIDE_CONTENT;
+ }
+ }
+ }
+ return PANEL_MOUSE_OUTSIDE;
+}
+
+typedef struct uiPanelDragCollapseHandle {
+ bool was_first_open;
+ int xy_init[2];
+} uiPanelDragCollapseHandle;
+
+static void ui_panel_drag_collapse_handler_remove(bContext *UNUSED(C), void *userdata)
+{
+ uiPanelDragCollapseHandle *dragcol_data = userdata;
+ MEM_freeN(dragcol_data);
+}
+
+static void ui_panel_drag_collapse(bContext *C, uiPanelDragCollapseHandle *dragcol_data, const int xy_dst[2])
+{
+ ScrArea *sa = CTX_wm_area(C);
+ ARegion *ar = CTX_wm_region(C);
+ uiBlock *block;
+ Panel *pa;
+
+ for (block = ar->uiblocks.first; block; block = block->next) {
+ float xy_a_block[2] = {UNPACK2(dragcol_data->xy_init)};
+ float xy_b_block[2] = {UNPACK2(xy_dst)};
+ rctf rect = block->rect;
+ int oldflag;
+ const bool is_horizontal = (panel_aligned(sa, ar) == BUT_HORIZONTAL);
+
+ if ((pa = block->panel) == 0 || (pa->type && (pa->type->flag & PNL_NO_HEADER))) {
+ continue;
+ }
+ oldflag = pa->flag;
+
+ /* lock one axis */
+ if (is_horizontal) {
+ xy_b_block[1] = dragcol_data->xy_init[1];
+ }
+ else {
+ xy_b_block[0] = dragcol_data->xy_init[0];
+ }
+
+ /* use cursor coords in block space */
+ ui_window_to_block_fl(ar, block, &xy_a_block[0], &xy_a_block[1]);
+ ui_window_to_block_fl(ar, block, &xy_b_block[0], &xy_b_block[1]);
+
+ /* set up rect to match header size */
+ rect.ymin = rect.ymax;
+ rect.ymax = rect.ymin + PNL_HEADER;
+ if (pa->flag & PNL_CLOSEDX) {
+ rect.xmax = rect.xmin + PNL_HEADER;
+ }
+
+ /* touch all panels between last mouse coord and the current one */
+ if (BLI_rctf_isect_segment(&rect, xy_a_block, xy_b_block)) {
+ /* force panel to close */
+ if (dragcol_data->was_first_open == true) {
+ pa->flag |= (is_horizontal ? PNL_CLOSEDX : PNL_CLOSEDY);
+ }
+ /* force panel to open */
+ else {
+ pa->flag &= ~PNL_CLOSED;
+ }
+
+ /* if pa->flag has changed this means a panel was opened/closed here */
+ if (pa->flag != oldflag) {
+ panel_activate_state(C, pa, PANEL_STATE_ANIMATION);
+ }
+ }
+ }
+}
+
+/**
+ * Panel drag-collapse (modal handler)
+ * Clicking and dragging over panels toggles their collapse state based on the panel that was first
+ * dragged over. If it was open all affected panels incl the initial one are closed and vise versa.
+ */
+static int ui_panel_drag_collapse_handler(bContext *C, const wmEvent *event, void *userdata)
+{
+ wmWindow *win = CTX_wm_window(C);
+ uiPanelDragCollapseHandle *dragcol_data = userdata;
+ short retval = WM_UI_HANDLER_CONTINUE;
+
+ switch (event->type) {
+ case MOUSEMOVE:
+ ui_panel_drag_collapse(C, dragcol_data, &event->x);
+
+ retval = WM_UI_HANDLER_BREAK;
+ break;
+ case LEFTMOUSE:
+ if (event->val == KM_RELEASE) {
+ /* done! */
+ WM_event_remove_ui_handler(
+ &win->modalhandlers,
+ ui_panel_drag_collapse_handler,
+ ui_panel_drag_collapse_handler_remove,
+ dragcol_data, true);
+ ui_panel_drag_collapse_handler_remove(C, dragcol_data);
+ }
+ /* don't let any left-mouse event fall through! */
+ retval = WM_UI_HANDLER_BREAK;
+ break;
+ }
+
+ return retval;
+}
+
+static void ui_panel_drag_collapse_handler_add(const bContext *C, const bool was_open)
+{
+ wmWindow *win = CTX_wm_window(C);
+ wmEvent *event = win->eventstate;
+ uiPanelDragCollapseHandle *dragcol_data = MEM_mallocN(sizeof(*dragcol_data), __func__);
+
+ dragcol_data->was_first_open = was_open;
+ copy_v2_v2_int(dragcol_data->xy_init, &event->x);
+
+ WM_event_add_ui_handler(
+ C, &win->modalhandlers,
+ ui_panel_drag_collapse_handler,
+ ui_panel_drag_collapse_handler_remove,
+ dragcol_data, 0);
+}
/* this function is supposed to call general window drawing too */
/* also it supposes a block has panel, and isn't a menu */
@@ -1183,23 +1354,39 @@ static void ui_handle_panel_header(const bContext *C, uiBlock *block, int mx, in
ED_region_tag_redraw(ar);
}
else { /* collapse */
- if (ctrl)
+ if (ctrl) {
panels_collapse_all(sa, ar, block->panel);
+ /* reset the view - we don't want to display a view without content */
+ UI_view2d_offset(&ar->v2d, 0.0f, 1.0f);
+ }
+
if (block->panel->flag & PNL_CLOSED) {
block->panel->flag &= ~PNL_CLOSED;
/* snap back up so full panel aligns with screen edge */
if (block->panel->snap & PNL_SNAP_BOTTOM)
block->panel->ofsy = 0;
+
+ if (event == LEFTMOUSE) {
+ ui_panel_drag_collapse_handler_add(C, false);
+ }
}
else if (align == BUT_HORIZONTAL) {
block->panel->flag |= PNL_CLOSEDX;
+
+ if (event == LEFTMOUSE) {
+ ui_panel_drag_collapse_handler_add(C, true);
+ }
}
else {
- /* snap down to bottom screen edge*/
+ /* snap down to bottom screen edge */
block->panel->flag |= PNL_CLOSEDY;
if (block->panel->snap & PNL_SNAP_BOTTOM)
block->panel->ofsy = -block->panel->sizey;
+
+ if (event == LEFTMOUSE) {
+ ui_panel_drag_collapse_handler_add(C, true);
+ }
}
for (pa = ar->panels.first; pa; pa = pa->next) {
@@ -1226,7 +1413,7 @@ static void ui_handle_panel_header(const bContext *C, uiBlock *block, int mx, in
bool UI_panel_category_is_visible(ARegion *ar)
{
- /* more then one */
+ /* more than one */
return ar->panels_category.first && ar->panels_category.first != ar->panels_category.last;
}
@@ -1327,11 +1514,12 @@ void UI_panel_category_clear_all(ARegion *ar)
BLI_freelistN(&ar->panels_category);
}
-/* based on uiDrawBox, check on making a version which allows us to skip some sides */
-static void ui_panel_category_draw_tab(int mode, float minx, float miny, float maxx, float maxy, float rad,
- int roundboxtype,
- const bool use_highlight, const bool use_shadow,
- const unsigned char highlight_fade[3])
+/* based on UI_draw_roundbox_gl_mode, check on making a version which allows us to skip some sides */
+static void ui_panel_category_draw_tab(
+ int mode, float minx, float miny, float maxx, float maxy, float rad,
+ int roundboxtype,
+ const bool use_highlight, const bool use_shadow,
+ const unsigned char highlight_fade[3])
{
float vec[4][2] = {
{0.195, 0.02},
@@ -1420,7 +1608,7 @@ void UI_panel_category_draw_all(ARegion *ar, const char *category_id_active)
/* no tab outlines for */
// #define USE_FLAT_INACTIVE
View2D *v2d = &ar->v2d;
- uiStyle *style = UI_GetStyle();
+ uiStyle *style = UI_style_get();
const uiFontStyle *fstyle = &style->widget;
const int fontid = fstyle->uifont_id;
short fstyle_points = fstyle->points;
@@ -1486,8 +1674,8 @@ void UI_panel_category_draw_all(ARegion *ar, const char *category_id_active)
}
BLF_enable(fontid, BLF_ROTATION);
- BLF_rotation(fontid, M_PI / 2);
- //uiStyleFontSet(&style->widget);
+ BLF_rotation(fontid, M_PI_2);
+ //UI_fontstyle_set(&style->widget);
ui_fontscale(&fstyle_points, aspect / (U.pixelsize * 1.1f));
BLF_size(fontid, fstyle_points, U.dpi);
@@ -1662,7 +1850,7 @@ void UI_panel_category_draw_all(ARegion *ar, const char *category_id_active)
/* 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, ARegion *ar)
+int ui_handler_panel_region(bContext *C, const wmEvent *event, ARegion *ar, const uiBut *active_but)
{
uiBlock *block;
Panel *pa;
@@ -1690,20 +1878,26 @@ int ui_handler_panel_region(bContext *C, const wmEvent *event, ARegion *ar)
/* first check if the mouse is in the tab region */
if (event->ctrl || (event->mval[0] < ((PanelCategoryDyn *)ar->panels_category.first)->rect.xmax)) {
- const char *category = UI_panel_category_active_get(ar, false);
- if (LIKELY(category)) {
- PanelCategoryDyn *pc_dyn = UI_panel_category_find(ar, category);
- if (LIKELY(pc_dyn)) {
- pc_dyn = (event->type == WHEELDOWNMOUSE) ? pc_dyn->next : pc_dyn->prev;
- if (pc_dyn) {
- /* intentionally don't reset scroll in this case,
- * this allows for quick browsing between tabs */
- UI_panel_category_active_set(ar, pc_dyn->idname);
- ED_region_tag_redraw(ar);
+ if (active_but && ui_but_supports_cycling(active_but)) {
+ /* skip - exception to make cycling buttons
+ * using ctrl+mousewheel work in tabbed regions */
+ }
+ else {
+ const char *category = UI_panel_category_active_get(ar, false);
+ if (LIKELY(category)) {
+ PanelCategoryDyn *pc_dyn = UI_panel_category_find(ar, category);
+ if (LIKELY(pc_dyn)) {
+ pc_dyn = (event->type == WHEELDOWNMOUSE) ? pc_dyn->next : pc_dyn->prev;
+ if (pc_dyn) {
+ /* intentionally don't reset scroll in this case,
+ * this allows for quick browsing between tabs */
+ UI_panel_category_active_set(ar, pc_dyn->idname);
+ ED_region_tag_redraw(ar);
+ }
}
}
+ retval = WM_UI_HANDLER_BREAK;
}
- retval = WM_UI_HANDLER_BREAK;
}
}
}
@@ -1714,8 +1908,8 @@ int ui_handler_panel_region(bContext *C, const wmEvent *event, ARegion *ar)
}
for (block = ar->uiblocks.last; block; block = block->prev) {
- bool inside = false, inside_header = false, inside_scale = false;
-
+ uiPanelMouseState mouse_state;
+
mx = event->x;
my = event->y;
ui_window_to_block(ar, block, &mx, &my);
@@ -1727,33 +1921,12 @@ int ui_handler_panel_region(bContext *C, const wmEvent *event, ARegion *ar)
continue;
if (pa->type && pa->type->flag & PNL_NO_HEADER) /* XXX - accessed freed panels when scripts reload, need to fix. */
continue;
-
- /* clicked at panel header? */
- if (pa->flag & PNL_CLOSEDX) {
- if (block->rect.xmin <= mx && block->rect.xmin + PNL_HEADER >= mx)
- 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 = 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 = true;
- }
- if (block->rect.xmin <= mx && block->rect.xmax >= mx)
- if (block->rect.ymin <= my && block->rect.ymax + PNL_HEADER >= my)
- inside = true;
- }
-
+
+ mouse_state = ui_panel_mouse_state_get(block, pa, mx, my);
+
/* XXX hardcoded key warning */
- if ((inside || inside_header) && event->val == KM_PRESS) {
- if (event->type == AKEY && !ELEM(KM_MOD_FIRST, event->ctrl, event->oskey, event->shift, event->alt)) {
+ if (ELEM(mouse_state, PANEL_MOUSE_INSIDE_CONTENT, PANEL_MOUSE_INSIDE_HEADER) && event->val == KM_PRESS) {
+ if (event->type == AKEY && ((event->ctrl + event->oskey + event->shift + event->alt) == 0)) {
if (pa->flag & PNL_CLOSEDY) {
if ((block->rect.ymax <= my) && (block->rect.ymax + PNL_HEADER >= my))
@@ -1768,16 +1941,16 @@ int ui_handler_panel_region(bContext *C, const wmEvent *event, ARegion *ar)
}
/* on active button, do not handle panels */
- if (ui_button_is_active(ar))
+ if (ui_but_is_active(ar))
continue;
- if (inside || inside_header) {
+ if (ELEM(mouse_state, PANEL_MOUSE_INSIDE_CONTENT, PANEL_MOUSE_INSIDE_HEADER)) {
if (event->val == KM_PRESS) {
/* open close on header */
if (ELEM(event->type, RETKEY, PADENTER)) {
- if (inside_header) {
+ if (mouse_state == PANEL_MOUSE_INSIDE_HEADER) {
ui_handle_panel_header(C, block, mx, my, RETKEY, event->ctrl, event->shift);
retval = WM_UI_HANDLER_BREAK;
break;
@@ -1787,12 +1960,12 @@ int ui_handler_panel_region(bContext *C, const wmEvent *event, ARegion *ar)
/* all inside clicks should return in break - overlapping/float panels */
retval = WM_UI_HANDLER_BREAK;
- if (inside_header) {
- ui_handle_panel_header(C, block, mx, my, 0, event->ctrl, event->shift);
+ if (mouse_state == PANEL_MOUSE_INSIDE_HEADER) {
+ ui_handle_panel_header(C, block, mx, my, event->type, event->ctrl, event->shift);
retval = WM_UI_HANDLER_BREAK;
break;
}
- else if (inside_scale && !(pa->flag & PNL_CLOSED)) {
+ else if ((mouse_state == PANEL_MOUSE_INSIDE_SCALE) && !(pa->flag & PNL_CLOSED)) {
panel_activate_state(C, pa, PANEL_STATE_DRAG_SCALE);
retval = WM_UI_HANDLER_BREAK;
break;
@@ -1800,7 +1973,7 @@ int ui_handler_panel_region(bContext *C, const wmEvent *event, ARegion *ar)
}
else if (event->type == RIGHTMOUSE) {
- if (inside_header) {
+ if (mouse_state == PANEL_MOUSE_INSIDE_HEADER) {
ui_panel_menu(C, ar, block->panel);
retval = WM_UI_HANDLER_BREAK;
break;
@@ -1939,7 +2112,7 @@ static void panel_activate_state(const bContext *C, Panel *pa, uiHandlePanelStat
data = MEM_callocN(sizeof(uiHandlePanelData), "uiHandlePanelData");
pa->activedata = data;
- WM_event_add_ui_handler(C, &win->modalhandlers, ui_handler_panel, ui_handler_remove_panel, pa, false);
+ WM_event_add_ui_handler(C, &win->modalhandlers, ui_handler_panel, ui_handler_remove_panel, pa, 0);
}
if (ELEM(state, PANEL_STATE_ANIMATION, PANEL_STATE_DRAG))
diff --git a/source/blender/editors/interface/interface_regions.c b/source/blender/editors/interface/interface_regions.c
index 9b450b8fdf4..0b586dd9fca 100644
--- a/source/blender/editors/interface/interface_regions.c
+++ b/source/blender/editors/interface/interface_regions.c
@@ -27,8 +27,6 @@
* \ingroup edinterface
*/
-
-
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
@@ -54,7 +52,6 @@
#include "WM_types.h"
#include "wm_draw.h"
#include "wm_subwindow.h"
-#include "wm_window.h"
#include "RNA_access.h"
@@ -65,7 +62,7 @@
#include "UI_view2d.h"
#include "BLF_api.h"
-#include "BLF_translation.h"
+#include "BLT_translation.h"
#include "ED_screen.h"
@@ -73,8 +70,9 @@
#include "interface_intern.h"
-#define MENU_TOP 8
+#define MENU_TOP (int)(8 * UI_DPI_FAC)
#define MENU_PADDING (int)(0.2f * UI_UNIT_Y)
+#define MENU_BORDER (int)(0.3f * U.widget_unit)
static int rna_property_enum_step(const bContext *C, PointerRNA *ptr, PropertyRNA *prop, int direction)
{
@@ -109,20 +107,27 @@ static int rna_property_enum_step(const bContext *C, PointerRNA *ptr, PropertyRN
return value;
}
-int ui_step_name_menu(uiBut *but, int direction)
+bool ui_but_menu_step_poll(const uiBut *but)
{
+ BLI_assert(but->type == UI_BTYPE_MENU);
+
/* currenly only RNA buttons */
- if ((but->rnaprop == NULL) || (RNA_property_type(but->rnaprop) != PROP_ENUM)) {
- printf("%s: cannot cycle button '%s'", __func__, but->str);
- return 0;
+ return (but->rnaprop && RNA_property_type(but->rnaprop) == PROP_ENUM);
+}
+
+int ui_but_menu_step(uiBut *but, int direction)
+{
+ if (ui_but_menu_step_poll(but)) {
+ return rna_property_enum_step(but->block->evil_C, &but->rnapoin, but->rnaprop, direction);
}
- return rna_property_enum_step(but->block->evil_C, &but->rnapoin, but->rnaprop, direction);
+ printf("%s: cannot cycle button '%s'\n", __func__, but->str);
+ return 0;
}
/******************** Creating Temporary regions ******************/
-static ARegion *ui_add_temporary_region(bScreen *sc)
+static ARegion *ui_region_temp_add(bScreen *sc)
{
ARegion *ar;
@@ -135,7 +140,7 @@ static ARegion *ui_add_temporary_region(bScreen *sc)
return ar;
}
-static void ui_remove_temporary_region(bContext *C, bScreen *sc, ARegion *ar)
+static void ui_region_temp_remove(bContext *C, bScreen *sc, ARegion *ar)
{
wmWindow *win = CTX_wm_window(C);
if (win)
@@ -150,13 +155,14 @@ static void ui_remove_temporary_region(bContext *C, bScreen *sc, ARegion *ar)
#define UI_TIP_PAD_FAC 1.3f
#define UI_TIP_PADDING (int)(UI_TIP_PAD_FAC * UI_UNIT_Y)
+#define UI_TIP_MAXWIDTH 600
#define MAX_TOOLTIP_LINES 8
typedef struct uiTooltipData {
rcti bbox;
uiFontStyle fstyle;
- char lines[MAX_TOOLTIP_LINES][512];
- char header[512], active_info[512];
+ char lines[MAX_TOOLTIP_LINES][2048];
+ char header[2048], active_info[2048];
struct {
enum {
UI_TIP_STYLE_NORMAL = 0,
@@ -173,6 +179,14 @@ typedef struct uiTooltipData {
} color_id : 4;
int is_pad : 1;
} format[MAX_TOOLTIP_LINES];
+
+ struct {
+ unsigned int x_pos; /* x cursor position at the end of the last line */
+ unsigned int lines; /* number of lines, 1 or more with word-wrap */
+ } line_geom[MAX_TOOLTIP_LINES];
+
+ int wrap_width;
+
int totline;
int toth, lineh;
} uiTooltipData;
@@ -182,9 +196,10 @@ typedef struct uiTooltipData {
BLI_STATIC_ASSERT(UI_TIP_LC_MAX == UI_TIP_LC_ALERT + 1, "invalid lc-max");
BLI_STATIC_ASSERT(sizeof(((uiTooltipData *)NULL)->format[0]) <= sizeof(int), "oversize");
-static void rgb_tint(float col[3],
- float h, float h_strength,
- float v, float v_strength)
+static void rgb_tint(
+ float col[3],
+ float h, float h_strength,
+ float v, float v_strength)
{
float col_hsv_from[3];
float col_hsv_to[3];
@@ -225,7 +240,7 @@ static void ui_tooltip_region_draw_cb(const bContext *UNUSED(C), ARegion *ar)
wmOrtho2_region_ui(ar);
/* draw background */
- ui_draw_tooltip_background(UI_GetStyle(), NULL, &bbox);
+ ui_draw_tooltip_background(UI_style_get(), NULL, &bbox);
/* set background_color */
rgb_uchar_to_float(background_color, (const unsigned char *)theme->inner);
@@ -244,69 +259,83 @@ static void ui_tooltip_region_draw_cb(const bContext *UNUSED(C), ARegion *ar)
/* tone_fg = rgb_to_grayscale(main_color); */
/* mix the colors */
- rgb_tint(value_color, 0.0f, 0.0f, tone_bg, 0.2f); /* light grey */
+ rgb_tint(value_color, 0.0f, 0.0f, tone_bg, 0.2f); /* light gray */
rgb_tint(active_color, 0.6f, 0.2f, tone_bg, 0.2f); /* light blue */
- rgb_tint(normal_color, 0.0f, 0.0f, tone_bg, 0.4f); /* grey */
- rgb_tint(python_color, 0.0f, 0.0f, tone_bg, 0.5f); /* dark grey */
+ rgb_tint(normal_color, 0.0f, 0.0f, tone_bg, 0.4f); /* gray */
+ rgb_tint(python_color, 0.0f, 0.0f, tone_bg, 0.5f); /* dark gray */
rgb_tint(alert_color, 0.0f, 0.8f, tone_bg, 0.1f); /* red */
/* draw text */
+ BLF_wordwrap(data->fstyle.uifont_id, data->wrap_width);
+ BLF_wordwrap(blf_mono_font, data->wrap_width);
bbox.xmin += 0.5f * pad_px; /* add padding to the text */
- bbox.ymax -= 0.5f * (BLI_rcti_size_y(&bbox) - data->toth);
- bbox.ymin = bbox.ymax - data->lineh;
+ bbox.ymax -= 0.25f * pad_px;
for (i = 0; i < data->totline; i++) {
+ bbox.ymin = bbox.ymax - (data->lineh * data->line_geom[i].lines);
if (data->format[i].style == UI_TIP_STYLE_HEADER) {
/* draw header and active data (is done here to be able to change color) */
uiFontStyle fstyle_header = data->fstyle;
- float xofs;
+ float xofs, yofs;
/* override text-style */
fstyle_header.shadow = 1;
- fstyle_header.shadowcolor = rgb_to_luma(tip_colors[UI_TIP_LC_MAIN]);
+ fstyle_header.shadowcolor = rgb_to_grayscale(tip_colors[UI_TIP_LC_MAIN]);
fstyle_header.shadx = fstyle_header.shady = 0;
fstyle_header.shadowalpha = 1.0f;
+ fstyle_header.word_wrap = true;
- uiStyleFontSet(&fstyle_header);
+ UI_fontstyle_set(&fstyle_header);
glColor3fv(tip_colors[UI_TIP_LC_MAIN]);
- uiStyleFontDraw(&fstyle_header, &bbox, data->header);
+ UI_fontstyle_draw(&fstyle_header, &bbox, data->header);
- xofs = BLF_width(fstyle_header.uifont_id, data->header, sizeof(data->header));
+ /* offset to the end of the last line */
+ xofs = data->line_geom[i].x_pos;
+ yofs = data->lineh * (data->line_geom[i].lines - 1);
bbox.xmin += xofs;
+ bbox.ymax -= yofs;
glColor3fv(tip_colors[UI_TIP_LC_ACTIVE]);
- uiStyleFontDraw(&data->fstyle, &bbox, data->active_info);
+ fstyle_header.shadow = 0;
+ UI_fontstyle_draw(&fstyle_header, &bbox, data->active_info);
+ /* undo offset */
bbox.xmin -= xofs;
+ bbox.ymax += yofs;
}
else if (data->format[i].style == UI_TIP_STYLE_MONO) {
uiFontStyle fstyle_mono = data->fstyle;
fstyle_mono.uifont_id = blf_mono_font;
+ fstyle_mono.word_wrap = true;
- uiStyleFontSet(&fstyle_mono);
+ UI_fontstyle_set(&fstyle_mono);
/* XXX, needed because we dont have mono in 'U.uifonts' */
BLF_size(fstyle_mono.uifont_id, fstyle_mono.points * U.pixelsize, U.dpi);
glColor3fv(tip_colors[data->format[i].color_id]);
- uiStyleFontDraw(&fstyle_mono, &bbox, data->lines[i]);
+ UI_fontstyle_draw(&fstyle_mono, &bbox, data->lines[i]);
}
else {
+ uiFontStyle fstyle_normal = data->fstyle;
BLI_assert(data->format[i].style == UI_TIP_STYLE_NORMAL);
+ fstyle_normal.word_wrap = true;
+
/* draw remaining data */
- uiStyleFontSet(&data->fstyle);
+ UI_fontstyle_set(&fstyle_normal);
glColor3fv(tip_colors[data->format[i].color_id]);
- uiStyleFontDraw(&data->fstyle, &bbox, data->lines[i]);
+ UI_fontstyle_draw(&fstyle_normal, &bbox, data->lines[i]);
}
+
+ bbox.ymax -= data->lineh * data->line_geom[i].lines;
+
if ((i + 1 != data->totline) && data->format[i + 1].is_pad) {
- bbox.ymax -= data->lineh * UI_TIP_PAD_FAC;
- bbox.ymin -= data->lineh * UI_TIP_PAD_FAC;
- }
- else {
- bbox.ymax -= data->lineh;
- bbox.ymin -= data->lineh;
+ bbox.ymax -= data->lineh * (UI_TIP_PAD_FAC - 1);
}
}
+ BLF_disable(data->fstyle.uifont_id, BLF_WORD_WRAP);
+ BLF_disable(blf_mono_font, BLF_WORD_WRAP);
+
if (multisample_enabled)
glEnable(GL_MULTISAMPLE_ARB);
}
@@ -324,7 +353,7 @@ ARegion *ui_tooltip_create(bContext *C, ARegion *butregion, uiBut *but)
{
const float pad_px = UI_TIP_PADDING;
wmWindow *win = CTX_wm_window(C);
- uiStyle *style = UI_GetStyle();
+ uiStyle *style = UI_style_get();
static ARegionType type;
ARegion *ar;
uiTooltipData *data;
@@ -332,10 +361,11 @@ ARegion *ui_tooltip_create(bContext *C, ARegion *butregion, uiBut *but)
char buf[512];
/* aspect values that shrink text are likely unreadable */
const float aspect = min_ff(1.0f, but->block->aspect);
- float fonth, fontw;
- int winx, ofsx, ofsy, w = 0, h, i;
+ int fonth, fontw;
+ int winx, ofsx, ofsy, h, i;
rctf rect_fl;
rcti rect_i;
+ int font_flag = 0;
uiStringInfo but_tip = {BUT_GET_TIP, NULL};
uiStringInfo enum_label = {BUT_GET_RNAENUM_LABEL, NULL};
@@ -351,7 +381,7 @@ ARegion *ui_tooltip_create(bContext *C, ARegion *butregion, uiBut *but)
/* create tooltip data */
data = MEM_callocN(sizeof(uiTooltipData), "uiTooltipData");
- uiButGetStrInfo(C, but, &but_tip, &enum_label, &enum_tip, &op_keymap, &prop_keymap, &rna_struct, &rna_prop, NULL);
+ UI_but_string_info_get(C, but, &but_tip, &enum_label, &enum_tip, &op_keymap, &prop_keymap, &rna_struct, &rna_prop, NULL);
/* Tip */
if (but_tip.strinfo) {
@@ -364,8 +394,9 @@ ARegion *ui_tooltip_create(bContext *C, ARegion *butregion, uiBut *but)
data->totline++;
/* special case enum rna buttons */
- if ((but->type & ROW) && but->rnaprop && RNA_property_flag(but->rnaprop) & PROP_ENUM_FLAG) {
- BLI_strncpy(data->lines[data->totline], IFACE_("(Shift-click to select multiple)"), sizeof(data->lines[0]));
+ if ((but->type & UI_BTYPE_ROW) && but->rnaprop && RNA_property_flag(but->rnaprop) & PROP_ENUM_FLAG) {
+ BLI_strncpy(data->lines[data->totline], IFACE_("(Shift-Click/Drag to select multiple)"),
+ sizeof(data->lines[0]));
data->format[data->totline].color_id = UI_TIP_LC_NORMAL;
data->totline++;
@@ -396,11 +427,11 @@ ARegion *ui_tooltip_create(bContext *C, ARegion *butregion, uiBut *but)
data->totline++;
}
- if (ELEM(but->type, TEX, SEARCH_MENU, SEARCH_MENU_UNLINK)) {
+ if (ELEM(but->type, UI_BTYPE_TEXT, UI_BTYPE_SEARCH_MENU)) {
/* better not show the value of a password */
if ((but->rnaprop && (RNA_property_subtype(but->rnaprop) == PROP_PASSWORD)) == 0) {
/* full string */
- ui_get_but_string(but, buf, sizeof(buf));
+ ui_but_string_get(but, buf, sizeof(buf));
if (buf[0]) {
BLI_snprintf(data->lines[data->totline], sizeof(data->lines[0]), TIP_("Value: %s"), buf);
data->format[data->totline].is_pad = true;
@@ -411,7 +442,7 @@ ARegion *ui_tooltip_create(bContext *C, ARegion *butregion, uiBut *but)
}
if (but->rnaprop) {
- int unit_type = uiButGetUnitType(but);
+ int unit_type = UI_but_unit_type_get(but);
if (unit_type == PROP_UNIT_ROTATION) {
if (RNA_property_type(but->rnaprop) == PROP_FLOAT) {
@@ -445,7 +476,7 @@ ARegion *ui_tooltip_create(bContext *C, ARegion *butregion, uiBut *but)
else if (but->optype) {
PointerRNA *opptr;
char *str;
- opptr = uiButGetOperatorPtrRNA(but); /* allocated when needed, the button owns it */
+ opptr = UI_but_operator_ptr_get(but); /* allocated when needed, the button owns it */
/* so the context is passed to itemf functions (some py itemf functions use it) */
WM_operator_properties_sanitize(opptr, false);
@@ -513,9 +544,10 @@ ARegion *ui_tooltip_create(bContext *C, ARegion *butregion, uiBut *but)
}
if (data_path) {
+ const char *data_delim = (data_path[0] == '[') ? "" : ".";
BLI_snprintf(data->lines[data->totline], sizeof(data->lines[0]),
- "%s.%s", /* no need to translate */
- id_path, data_path);
+ "%s%s%s", /* no need to translate */
+ id_path, data_delim, data_path);
MEM_freeN(data_path);
}
else if (prop) {
@@ -556,7 +588,7 @@ ARegion *ui_tooltip_create(bContext *C, ARegion *butregion, uiBut *but)
}
/* create area region */
- ar = ui_add_temporary_region(CTX_wm_screen(C));
+ ar = ui_region_temp_add(CTX_wm_screen(C));
memset(&type, 0, sizeof(ARegionType));
type.draw = ui_tooltip_region_draw_cb;
@@ -568,7 +600,18 @@ ARegion *ui_tooltip_create(bContext *C, ARegion *butregion, uiBut *but)
data->fstyle = style->widget; /* copy struct */
ui_fontscale(&data->fstyle.points, aspect);
- uiStyleFontSet(&data->fstyle);
+ UI_fontstyle_set(&data->fstyle);
+
+ data->wrap_width = min_ii(UI_TIP_MAXWIDTH * U.pixelsize / aspect, WM_window_pixels_x(win) - (UI_TIP_PADDING * 2));
+
+ font_flag |= BLF_WORD_WRAP;
+ if (data->fstyle.kerning == 1) {
+ font_flag |= BLF_KERNING_DEFAULT;
+ }
+ BLF_enable(data->fstyle.uifont_id, font_flag);
+ BLF_enable(blf_mono_font, font_flag);
+ BLF_wordwrap(data->fstyle.uifont_id, data->wrap_width);
+ BLF_wordwrap(blf_mono_font, data->wrap_width);
/* these defines tweaked depending on font */
#define TIP_BORDER_X (16.0f / aspect)
@@ -577,33 +620,43 @@ ARegion *ui_tooltip_create(bContext *C, ARegion *butregion, uiBut *but)
h = BLF_height_max(data->fstyle.uifont_id);
for (i = 0, fontw = 0, fonth = 0; i < data->totline; i++) {
+ struct ResultBLF info;
+ int w, x_pos = 0;
+
if (data->format[i].style == UI_TIP_STYLE_HEADER) {
- w = BLF_width(data->fstyle.uifont_id, data->header, sizeof(data->header));
- if (enum_label.strinfo)
- w += BLF_width(data->fstyle.uifont_id, data->active_info, sizeof(data->active_info));
+ w = BLF_width_ex(data->fstyle.uifont_id, data->header, sizeof(data->header), &info);
+ if (enum_label.strinfo) {
+ x_pos = info.width + (U.widget_unit / 2);
+ w = max_ii(w, x_pos + BLF_width(data->fstyle.uifont_id, data->active_info, sizeof(data->active_info)));
+ }
}
else if (data->format[i].style == UI_TIP_STYLE_MONO) {
BLF_size(blf_mono_font, data->fstyle.points * U.pixelsize, U.dpi);
- w = BLF_width(blf_mono_font, data->lines[i], sizeof(data->lines[i]));
+ w = BLF_width_ex(blf_mono_font, data->lines[i], sizeof(data->lines[i]), &info);
}
else {
BLI_assert(data->format[i].style == UI_TIP_STYLE_NORMAL);
- w = BLF_width(data->fstyle.uifont_id, data->lines[i], sizeof(data->lines[i]));
+
+ w = BLF_width_ex(data->fstyle.uifont_id, data->lines[i], sizeof(data->lines[i]), &info);
}
- fontw = max_ff(fontw, (float)w);
+ fontw = max_ii(fontw, w);
+ fonth += h * info.lines;
if ((i + 1 != data->totline) && data->format[i + 1].is_pad) {
- fonth += h * UI_TIP_PAD_FAC;
- }
- else {
- fonth += h;
+ fonth += h * (UI_TIP_PAD_FAC - 1);
}
+
+ data->line_geom[i].lines = info.lines;
+ data->line_geom[i].x_pos = x_pos;
}
//fontw *= aspect;
+ BLF_disable(data->fstyle.uifont_id, font_flag);
+ BLF_disable(blf_mono_font, font_flag);
+
ar->regiondata = data;
data->toth = fonth;
@@ -668,18 +721,18 @@ ARegion *ui_tooltip_create(bContext *C, ARegion *butregion, uiBut *but)
/* widget rect, in region coords */
{
- int width = UI_ThemeMenuShadowWidth();
+ const int margin = UI_POPUP_MARGIN;
- data->bbox.xmin = width;
- data->bbox.xmax = BLI_rcti_size_x(&rect_i) - width;
- data->bbox.ymin = width;
+ data->bbox.xmin = margin;
+ data->bbox.xmax = BLI_rcti_size_x(&rect_i) - margin;
+ data->bbox.ymin = margin;
data->bbox.ymax = BLI_rcti_size_y(&rect_i);
/* region bigger for shadow */
- ar->winrct.xmin = rect_i.xmin - width;
- ar->winrct.xmax = rect_i.xmax + width;
- ar->winrct.ymin = rect_i.ymin - width;
- ar->winrct.ymax = rect_i.ymax + width;
+ ar->winrct.xmin = rect_i.xmin - margin;
+ ar->winrct.xmax = rect_i.xmax + margin;
+ ar->winrct.ymin = rect_i.ymin - margin;
+ ar->winrct.ymax = rect_i.ymax + margin;
}
/* adds subwindow */
@@ -693,7 +746,7 @@ ARegion *ui_tooltip_create(bContext *C, ARegion *butregion, uiBut *but)
void ui_tooltip_free(bContext *C, ARegion *ar)
{
- ui_remove_temporary_region(C, CTX_wm_screen(C), ar);
+ ui_region_temp_remove(C, CTX_wm_screen(C), ar);
}
@@ -728,11 +781,11 @@ typedef struct uiSearchboxData {
/* exported for use by search callbacks */
/* returns zero if nothing to add */
-bool uiSearchItemAdd(uiSearchItems *items, const char *name, void *poin, int iconid)
+bool UI_search_item_add(uiSearchItems *items, const char *name, void *poin, int iconid)
{
/* hijack for autocomplete */
if (items->autocpl) {
- autocomplete_do_name(items->autocpl, name);
+ UI_autocomplete_update_name(items->autocpl, name);
return true;
}
@@ -767,17 +820,17 @@ bool uiSearchItemAdd(uiSearchItems *items, const char *name, void *poin, int ico
return true;
}
-int uiSearchBoxHeight(void)
+int UI_searchbox_size_y(void)
{
return SEARCH_ITEMS * UI_UNIT_Y + 2 * MENU_TOP;
}
-int uiSearchBoxWidth(void)
+int UI_searchbox_size_x(void)
{
return 12 * UI_UNIT_X;
}
-int uiSearchItemFindIndex(uiSearchItems *items, const char *name)
+int UI_search_items_find_index(uiSearchItems *items, const char *name)
{
int i;
for (i = 0; i < items->totitem; i++) {
@@ -817,7 +870,7 @@ static void ui_searchbox_select(bContext *C, ARegion *ar, uiBut *but, int step)
}
else {
/* only let users step into an 'unset' state for unlink buttons */
- data->active = (but->type == SEARCH_MENU_UNLINK) ? -1 : 0;
+ data->active = (but->flag & UI_BUT_SEARCH_UNLINK) ? -1 : 0;
}
}
@@ -828,8 +881,8 @@ static void ui_searchbox_butrect(rcti *r_rect, uiSearchboxData *data, int itemnr
{
/* thumbnail preview */
if (data->preview) {
- int butw = BLI_rcti_size_x(&data->bbox) / data->prv_cols;
- int buth = (BLI_rcti_size_y(&data->bbox) - 2 * MENU_TOP) / data->prv_rows;
+ int butw = (BLI_rcti_size_x(&data->bbox) - 2 * MENU_BORDER) / data->prv_cols;
+ int buth = (BLI_rcti_size_y(&data->bbox) - 2 * MENU_BORDER) / data->prv_rows;
int row, col;
*r_rect = data->bbox;
@@ -837,10 +890,10 @@ static void ui_searchbox_butrect(rcti *r_rect, uiSearchboxData *data, int itemnr
col = itemnr % data->prv_cols;
row = itemnr / data->prv_cols;
- r_rect->xmin += col * butw;
+ r_rect->xmin += MENU_BORDER + (col * butw);
r_rect->xmax = r_rect->xmin + butw;
- r_rect->ymax = data->bbox.ymax - MENU_TOP - (row * buth);
+ r_rect->ymax -= MENU_BORDER + (row * buth);
r_rect->ymin = r_rect->ymax - buth;
}
/* list view */
@@ -860,7 +913,7 @@ static void ui_searchbox_butrect(rcti *r_rect, uiSearchboxData *data, int itemnr
int ui_searchbox_find_index(ARegion *ar, const char *name)
{
uiSearchboxData *data = ar->regiondata;
- return uiSearchItemFindIndex(&data->items, name);
+ return UI_search_items_find_index(&data->items, name);
}
/* x and y in screencoords */
@@ -888,7 +941,7 @@ bool ui_searchbox_apply(uiBut *but, ARegion *ar)
return true;
}
- else if (but->type == SEARCH_MENU_UNLINK) {
+ else if (but->flag & UI_BUT_SEARCH_UNLINK) {
/* It is valid for _UNLINK flavor to have no active element (it's a valid way to unlink). */
but->editstr[0] = '\0';
@@ -1014,11 +1067,11 @@ int ui_searchbox_autocomplete(bContext *C, ARegion *ar, uiBut *but, char *str)
int match = AUTOCOMPLETE_NO_MATCH;
if (str[0]) {
- data->items.autocpl = autocomplete_begin(str, ui_get_but_string_max_length(but));
+ data->items.autocpl = UI_autocomplete_begin(str, ui_but_string_get_max_length(but));
but->search_func(C, but->search_arg, but->editstr, &data->items);
- match = autocomplete_end(data->items.autocpl, str);
+ match = UI_autocomplete_end(data->items.autocpl, str);
data->items.autocpl = NULL;
}
@@ -1046,14 +1099,8 @@ static void ui_searchbox_region_draw_cb(const bContext *UNUSED(C), ARegion *ar)
ui_searchbox_butrect(&rect, data, a);
/* widget itself */
- if (data->preview) {
- ui_draw_preview_item(&data->fstyle, &rect, data->items.names[a], data->items.icons[a],
- (a == data->active) ? UI_ACTIVE : 0);
- }
- else {
- ui_draw_menu_item(&data->fstyle, &rect, data->items.names[a], data->items.icons[a],
- (a == data->active) ? UI_ACTIVE : 0, data->use_sep);
- }
+ ui_draw_preview_item(&data->fstyle, &rect, data->items.names[a], data->items.icons[a],
+ (a == data->active) ? UI_ACTIVE : 0);
}
/* indicate more */
@@ -1118,18 +1165,19 @@ static void ui_searchbox_region_free_cb(ARegion *ar)
ARegion *ui_searchbox_create(bContext *C, ARegion *butregion, uiBut *but)
{
wmWindow *win = CTX_wm_window(C);
- uiStyle *style = UI_GetStyle();
+ uiStyle *style = UI_style_get();
static ARegionType type;
ARegion *ar;
uiSearchboxData *data;
float aspect = but->block->aspect;
rctf rect_fl;
rcti rect_i;
+ const int margin = UI_POPUP_MARGIN;
int winx /*, winy */, ofsx, ofsy;
int i;
/* create area region */
- ar = ui_add_temporary_region(CTX_wm_screen(C));
+ ar = ui_region_temp_add(CTX_wm_screen(C));
memset(&type, 0, sizeof(ARegionType));
type.draw = ui_searchbox_region_draw_cb;
@@ -1144,7 +1192,7 @@ ARegion *ui_searchbox_create(bContext *C, ARegion *butregion, uiBut *but)
data->fstyle = style->widget; /* copy struct */
data->fstyle.align = UI_STYLE_TEXT_CENTER;
ui_fontscale(&data->fstyle.points, aspect);
- uiStyleFontSet(&data->fstyle);
+ UI_fontstyle_set(&data->fstyle);
ar->regiondata = data;
@@ -1166,35 +1214,33 @@ ARegion *ui_searchbox_create(bContext *C, ARegion *butregion, uiBut *but)
/* compute position */
if (but->block->flag & UI_BLOCK_SEARCH_MENU) {
- int width = UI_ThemeMenuShadowWidth();
+ const int search_but_h = BLI_rctf_size_y(&but->rect) + 10;
/* this case is search menu inside other menu */
/* we copy region size */
ar->winrct = butregion->winrct;
/* widget rect, in region coords */
- data->bbox.xmin = width;
- data->bbox.xmax = BLI_rcti_size_x(&ar->winrct) - width;
- /* Do not use shadow width for height, gives insane margin with big shadows, and issue T41548 with small ones */
- data->bbox.ymin = 8 * UI_DPI_FAC;
- data->bbox.ymax = BLI_rcti_size_y(&ar->winrct) - 8 * UI_DPI_FAC;
+ data->bbox.xmin = margin;
+ data->bbox.xmax = BLI_rcti_size_x(&ar->winrct) - margin;
+ data->bbox.ymin = margin;
+ data->bbox.ymax = BLI_rcti_size_y(&ar->winrct) - margin;
/* check if button is lower half */
if (but->rect.ymax < BLI_rctf_cent_y(&but->block->rect)) {
- data->bbox.ymin += BLI_rctf_size_y(&but->rect);
+ data->bbox.ymin += search_but_h;
}
else {
- data->bbox.ymax -= BLI_rctf_size_y(&but->rect);
+ data->bbox.ymax -= search_but_h;
}
}
else {
- const int searchbox_width = uiSearchBoxWidth();
- const int shadow_width = UI_ThemeMenuShadowWidth();
+ const int searchbox_width = UI_searchbox_size_x();
rect_fl.xmin = but->rect.xmin - 5; /* align text with button */
rect_fl.xmax = but->rect.xmax + 5; /* symmetrical */
rect_fl.ymax = but->rect.ymin;
- rect_fl.ymin = rect_fl.ymax - uiSearchBoxHeight();
+ rect_fl.ymin = rect_fl.ymax - UI_searchbox_size_y();
ofsx = (but->block->panel) ? but->block->panel->ofsx : 0;
ofsy = (but->block->panel) ? but->block->panel->ofsy : 0;
@@ -1244,15 +1290,15 @@ ARegion *ui_searchbox_create(bContext *C, ARegion *butregion, uiBut *but)
}
/* widget rect, in region coords */
- data->bbox.xmin = shadow_width;
- data->bbox.xmax = BLI_rcti_size_x(&rect_i) + shadow_width;
- data->bbox.ymin = shadow_width;
- data->bbox.ymax = BLI_rcti_size_y(&rect_i) + shadow_width;
+ data->bbox.xmin = margin;
+ data->bbox.xmax = BLI_rcti_size_x(&rect_i) + margin;
+ data->bbox.ymin = margin;
+ data->bbox.ymax = BLI_rcti_size_y(&rect_i) + margin;
/* region bigger for shadow */
- ar->winrct.xmin = rect_i.xmin - shadow_width;
- ar->winrct.xmax = rect_i.xmax + shadow_width;
- ar->winrct.ymin = rect_i.ymin - shadow_width;
+ ar->winrct.xmin = rect_i.xmin - margin;
+ ar->winrct.xmax = rect_i.xmax + margin;
+ ar->winrct.ymin = rect_i.ymin - margin;
ar->winrct.ymax = rect_i.ymax;
}
@@ -1282,12 +1328,12 @@ ARegion *ui_searchbox_create(bContext *C, ARegion *butregion, uiBut *but)
void ui_searchbox_free(bContext *C, ARegion *ar)
{
- ui_remove_temporary_region(C, CTX_wm_screen(C), ar);
+ ui_region_temp_remove(C, CTX_wm_screen(C), ar);
}
/* sets red alert if button holds a string it can't find */
/* XXX weak: search_func adds all partial matches... */
-void ui_but_search_test(uiBut *but)
+void ui_but_search_refresh(uiBut *but)
{
uiSearchItems *items;
int x1;
@@ -1311,11 +1357,11 @@ void ui_but_search_test(uiBut *but)
/* only redalert when we are sure of it, this can miss cases when >10 matches */
if (items->totitem == 0) {
- uiButSetFlag(but, UI_BUT_REDALERT);
+ UI_but_flag_enable(but, UI_BUT_REDALERT);
}
else if (items->more == 0) {
- if (uiSearchItemFindIndex(items, but->drawstr) == -1) {
- uiButSetFlag(but, UI_BUT_REDALERT);
+ if (UI_search_items_find_index(items, but->drawstr) == -1) {
+ UI_but_flag_enable(but, UI_BUT_REDALERT);
}
}
@@ -1343,7 +1389,7 @@ static void ui_block_position(wmWindow *window, ARegion *butregion, uiBut *but,
ui_block_to_window_rctf(butregion, but->block, &butrct, &but->rect);
/* widget_roundbox_set has this correction too, keep in sync */
- if (but->type != PULLDOWN) {
+ if (but->type != UI_BTYPE_PULLDOWN) {
if (but->drawflag & UI_BUT_ALIGN_TOP)
butrct.ymax += U.pixelsize;
if (but->drawflag & UI_BUT_ALIGN_LEFT)
@@ -1377,7 +1423,7 @@ static void ui_block_position(wmWindow *window, ARegion *butregion, uiBut *but,
/* aspect /= (float)xsize;*/ /*UNUSED*/
{
- int left = 0, right = 0, top = 0, down = 0;
+ bool left = 0, right = 0, top = 0, down = 0;
int winx, winy;
// int offscreen;
@@ -1385,8 +1431,12 @@ static void ui_block_position(wmWindow *window, ARegion *butregion, uiBut *but,
winy = WM_window_pixels_y(window);
// wm_window_get_size(window, &winx, &winy);
- if (block->direction & UI_CENTER) center = ysize / 2;
- else center = 0;
+ if (block->direction & UI_DIR_CENTER_Y) {
+ center = ysize / 2;
+ }
+ else {
+ center = 0;
+ }
/* check if there's space at all */
if (butrct.xmin - xsize > 0.0f) left = 1;
@@ -1401,69 +1451,66 @@ static void ui_block_position(wmWindow *window, ARegion *butregion, uiBut *but,
down = 1;
}
- dir1 = block->direction & UI_DIRECTION;
+ dir1 = (block->direction & UI_DIR_ALL);
/* secundary directions */
- if (dir1 & (UI_TOP | UI_DOWN)) {
- if (dir1 & UI_LEFT) dir2 = UI_LEFT;
- else if (dir1 & UI_RIGHT) dir2 = UI_RIGHT;
- dir1 &= (UI_TOP | UI_DOWN);
+ if (dir1 & (UI_DIR_UP | UI_DIR_DOWN)) {
+ if (dir1 & UI_DIR_LEFT) dir2 = UI_DIR_LEFT;
+ else if (dir1 & UI_DIR_RIGHT) dir2 = UI_DIR_RIGHT;
+ dir1 &= (UI_DIR_UP | UI_DIR_DOWN);
}
- if ((dir2 == 0) && (dir1 == UI_LEFT || dir1 == UI_RIGHT)) dir2 = UI_DOWN;
- if ((dir2 == 0) && (dir1 == UI_TOP || dir1 == UI_DOWN)) dir2 = UI_LEFT;
+ if ((dir2 == 0) && (dir1 == UI_DIR_LEFT || dir1 == UI_DIR_RIGHT)) dir2 = UI_DIR_DOWN;
+ if ((dir2 == 0) && (dir1 == UI_DIR_UP || dir1 == UI_DIR_DOWN)) dir2 = UI_DIR_LEFT;
/* no space at all? don't change */
if (left || right) {
- if (dir1 == UI_LEFT && left == 0) dir1 = UI_RIGHT;
- if (dir1 == UI_RIGHT && right == 0) dir1 = UI_LEFT;
+ if (dir1 == UI_DIR_LEFT && left == 0) dir1 = UI_DIR_RIGHT;
+ if (dir1 == UI_DIR_RIGHT && right == 0) dir1 = UI_DIR_LEFT;
/* this is aligning, not append! */
- if (dir2 == UI_LEFT && right == 0) dir2 = UI_RIGHT;
- if (dir2 == UI_RIGHT && left == 0) dir2 = UI_LEFT;
+ if (dir2 == UI_DIR_LEFT && right == 0) dir2 = UI_DIR_RIGHT;
+ if (dir2 == UI_DIR_RIGHT && left == 0) dir2 = UI_DIR_LEFT;
}
if (down || top) {
- if (dir1 == UI_TOP && top == 0) dir1 = UI_DOWN;
- if (dir1 == UI_DOWN && down == 0) dir1 = UI_TOP;
- if (dir2 == UI_TOP && top == 0) dir2 = UI_DOWN;
- if (dir2 == UI_DOWN && down == 0) dir2 = UI_TOP;
+ if (dir1 == UI_DIR_UP && top == 0) dir1 = UI_DIR_DOWN;
+ if (dir1 == UI_DIR_DOWN && down == 0) dir1 = UI_DIR_UP;
+ BLI_assert(dir2 != UI_DIR_UP);
+// if (dir2 == UI_DIR_UP && top == 0) dir2 = UI_DIR_DOWN;
+ if (dir2 == UI_DIR_DOWN && down == 0) dir2 = UI_DIR_UP;
}
- if (dir1 == UI_LEFT) {
+ if (dir1 == UI_DIR_LEFT) {
xof = butrct.xmin - block->rect.xmax;
- if (dir2 == UI_TOP) yof = butrct.ymin - block->rect.ymin - center - MENU_PADDING;
- else yof = butrct.ymax - block->rect.ymax + center + MENU_PADDING;
+ if (dir2 == UI_DIR_UP) yof = butrct.ymin - block->rect.ymin - center - MENU_PADDING;
+ else yof = butrct.ymax - block->rect.ymax + center + MENU_PADDING;
}
- else if (dir1 == UI_RIGHT) {
+ else if (dir1 == UI_DIR_RIGHT) {
xof = butrct.xmax - block->rect.xmin;
- if (dir2 == UI_TOP) yof = butrct.ymin - block->rect.ymin - center - MENU_PADDING;
- else yof = butrct.ymax - block->rect.ymax + center + MENU_PADDING;
+ if (dir2 == UI_DIR_UP) yof = butrct.ymin - block->rect.ymin - center - MENU_PADDING;
+ else yof = butrct.ymax - block->rect.ymax + center + MENU_PADDING;
}
- else if (dir1 == UI_TOP) {
+ else if (dir1 == UI_DIR_UP) {
yof = butrct.ymax - block->rect.ymin;
- if (dir2 == UI_RIGHT) xof = butrct.xmax - block->rect.xmax;
- else xof = butrct.xmin - block->rect.xmin;
+ if (dir2 == UI_DIR_RIGHT) xof = butrct.xmax - block->rect.xmax;
+ else xof = butrct.xmin - block->rect.xmin;
/* changed direction? */
if ((dir1 & block->direction) == 0) {
- if (block->direction & UI_SHIFT_FLIPPED)
- xof += dir2 == UI_LEFT ? 25 : -25;
- uiBlockFlipOrder(block);
+ UI_block_order_flip(block);
}
}
- else if (dir1 == UI_DOWN) {
+ else if (dir1 == UI_DIR_DOWN) {
yof = butrct.ymin - block->rect.ymax;
- if (dir2 == UI_RIGHT) xof = butrct.xmax - block->rect.xmax;
- else xof = butrct.xmin - block->rect.xmin;
+ if (dir2 == UI_DIR_RIGHT) xof = butrct.xmax - block->rect.xmax;
+ else xof = butrct.xmin - block->rect.xmin;
/* changed direction? */
if ((dir1 & block->direction) == 0) {
- if (block->direction & UI_SHIFT_FLIPPED)
- xof += dir2 == UI_LEFT ? 25 : -25;
- uiBlockFlipOrder(block);
+ UI_block_order_flip(block);
}
}
/* and now we handle the exception; no space below or to top */
if (top == 0 && down == 0) {
- if (dir1 == UI_LEFT || dir1 == UI_RIGHT) {
+ if (dir1 == UI_DIR_LEFT || dir1 == UI_DIR_RIGHT) {
/* align with bottom of screen */
// yof = ysize; (not with menu scrolls)
}
@@ -1471,7 +1518,7 @@ static void ui_block_position(wmWindow *window, ARegion *butregion, uiBut *but,
/* or no space left or right */
if (left == 0 && right == 0) {
- if (dir1 == UI_TOP || dir1 == UI_DOWN) {
+ if (dir1 == UI_DIR_UP || dir1 == UI_DIR_DOWN) {
/* align with left size of screen */
xof = -block->rect.xmin + 5;
}
@@ -1493,8 +1540,8 @@ static void ui_block_position(wmWindow *window, ARegion *butregion, uiBut *but,
BLI_rctf_translate(&bt->rect, xof, yof);
- /* ui_check_but recalculates drawstring size in pixels */
- ui_check_but(bt);
+ /* ui_but_update recalculates drawstring size in pixels */
+ ui_but_update(bt);
}
BLI_rctf_translate(&block->rect, xof, yof);
@@ -1522,8 +1569,8 @@ static void ui_block_position(wmWindow *window, ARegion *butregion, uiBut *but,
/* exception for switched pulldowns... */
if (dir1 && (dir1 & block->direction) == 0) {
- if (dir2 == UI_RIGHT) block->safety.xmax = block->rect.xmax + 3;
- if (dir2 == UI_LEFT) block->safety.xmin = block->rect.xmin - 3;
+ if (dir2 == UI_DIR_RIGHT) block->safety.xmax = block->rect.xmax + 3;
+ if (dir2 == UI_DIR_LEFT) block->safety.xmin = block->rect.xmin - 3;
}
block->direction = dir1;
}
@@ -1551,7 +1598,7 @@ static void ui_block_region_draw(const bContext *C, ARegion *ar)
}
for (block = ar->uiblocks.first; block; block = block->next)
- uiDrawBlock(C, block);
+ UI_block_draw(C, block);
}
static void ui_popup_block_clip(wmWindow *window, uiBlock *block)
@@ -1633,20 +1680,20 @@ void ui_popup_block_scrolltest(uiBlock *block)
static void ui_popup_block_remove(bContext *C, uiPopupBlockHandle *handle)
{
- ui_remove_temporary_region(C, CTX_wm_screen(C), handle->region);
+ ui_region_temp_remove(C, CTX_wm_screen(C), handle->region);
if (handle->scrolltimer)
WM_event_remove_timer(CTX_wm_manager(C), CTX_wm_window(C), handle->scrolltimer);
}
/**
- * Called for creatign new popups and refreshing existing ones.
+ * Called for creating new popups and refreshing existing ones.
*/
uiBlock *ui_popup_block_refresh(
bContext *C, uiPopupBlockHandle *handle,
ARegion *butregion, uiBut *but)
{
- const int width = UI_ThemeMenuShadowWidth();
+ const int margin = UI_POPUP_MARGIN;
wmWindow *window = CTX_wm_window(C);
ARegion *ar = handle->region;
@@ -1667,7 +1714,7 @@ uiBlock *ui_popup_block_refresh(
else
block = handle_create_func(C, handle, arg);
- /* callbacks _must_ leave this for us, otherwise we can't call uiBlockUpdateFromOld */
+ /* callbacks _must_ leave this for us, otherwise we can't call UI_block_update_from_old */
BLI_assert(!block->endblock);
/* ensure we don't use mouse coords here! */
@@ -1685,14 +1732,9 @@ uiBlock *ui_popup_block_refresh(
ar->regiondata = handle;
- /* set UI_BLOCK_NUMSELECT before uiEndBlock() so we get alphanumeric keys assigned */
- if (but) {
- if (but->type == PULLDOWN) {
- block->flag |= UI_BLOCK_NUMSELECT;
- }
- }
- else {
- block->flag |= UI_BLOCK_POPUP | UI_BLOCK_NUMSELECT;
+ /* set UI_BLOCK_NUMSELECT before UI_block_end() so we get alphanumeric keys assigned */
+ if (but == NULL) {
+ block->flag |= UI_BLOCK_POPUP;
}
block->flag |= UI_BLOCK_LOOP;
@@ -1701,7 +1743,7 @@ uiBlock *ui_popup_block_refresh(
block->oldblock = NULL;
if (!block->endblock)
- uiEndBlock_ex(C, block, handle->popup_create_vars.event_xy);
+ UI_block_end_ex(C, block, handle->popup_create_vars.event_xy);
/* if this is being created from a button */
if (but) {
@@ -1756,7 +1798,7 @@ uiBlock *ui_popup_block_refresh(
ar->winrct.ymin = 0;
ar->winrct.ymax = winy;
- ui_block_calculate_pie_segment(block, block->pie_data.pie_center_init);
+ ui_block_calc_pie_segment(block, block->pie_data.pie_center_init);
/* lastly set the buttons at the center of the pie menu, ready for animation */
if (U.pie_animation_timeout > 0) {
@@ -1773,9 +1815,9 @@ uiBlock *ui_popup_block_refresh(
/* the block and buttons were positioned in window space as in 2.4x, now
* these menu blocks are regions so we bring it back to region space.
* additionally we add some padding for the menu shadow or rounded menus */
- ar->winrct.xmin = block->rect.xmin - width;
- ar->winrct.xmax = block->rect.xmax + width;
- ar->winrct.ymin = block->rect.ymin - width;
+ ar->winrct.xmin = block->rect.xmin - margin;
+ ar->winrct.xmax = block->rect.xmax + margin;
+ ar->winrct.ymin = block->rect.ymin - margin;
ar->winrct.ymax = block->rect.ymax + MENU_TOP;
ui_block_translate(block, -ar->winrct.xmin, -ar->winrct.ymin);
@@ -1783,8 +1825,8 @@ uiBlock *ui_popup_block_refresh(
if (block_old) {
block->oldblock = block_old;
- uiBlockUpdateFromOld(C, block);
- uiFreeInactiveBlocks(C, &ar->uiblocks);
+ UI_block_update_from_old(C, block);
+ UI_blocklist_free_inactive(C, &ar->uiblocks);
}
/* checks which buttons are visible, sets flags to prevent draw (do after region init) */
@@ -1810,9 +1852,10 @@ uiBlock *ui_popup_block_refresh(
return block;
}
-uiPopupBlockHandle *ui_popup_block_create(bContext *C, ARegion *butregion, uiBut *but,
- uiBlockCreateFunc create_func, uiBlockHandleCreateFunc handle_create_func,
- void *arg)
+uiPopupBlockHandle *ui_popup_block_create(
+ bContext *C, ARegion *butregion, uiBut *but,
+ uiBlockCreateFunc create_func, uiBlockHandleCreateFunc handle_create_func,
+ void *arg)
{
wmWindow *window = CTX_wm_window(C);
static ARegionType type;
@@ -1835,7 +1878,7 @@ uiPopupBlockHandle *ui_popup_block_create(bContext *C, ARegion *butregion, uiBut
copy_v2_v2_int(handle->popup_create_vars.event_xy, &window->eventstate->x);
/* create area region */
- ar = ui_add_temporary_region(CTX_wm_screen(C));
+ ar = ui_region_temp_add(CTX_wm_screen(C));
handle->region = ar;
memset(&type, 0, sizeof(ARegionType));
@@ -1843,7 +1886,7 @@ uiPopupBlockHandle *ui_popup_block_create(bContext *C, ARegion *butregion, uiBut
type.regionid = RGN_TYPE_TEMPORARY;
ar->type = &type;
- UI_add_region_handlers(&ar->handlers);
+ UI_region_handlers_add(&ar->handlers);
block = ui_popup_block_refresh(C, handle, butregion, but);
handle = block->handle;
@@ -1875,21 +1918,23 @@ static void ui_warp_pointer(int x, int y)
/********************* Color Button ****************/
/* for picker, while editing hsv */
-void ui_set_but_hsv(uiBut *but)
+void ui_but_hsv_set(uiBut *but)
{
float col[3];
- const float *hsv = ui_block_hsv_get(but->block);
-
+ ColorPicker *cpicker = but->custom_data;
+ float *hsv = cpicker->color_data;
+
ui_color_picker_to_rgb_v(hsv, col);
- ui_set_but_vectorf(but, col);
+ ui_but_v3_set(but, col);
}
-/* also used by small picker, be careful with name checks below... */
-static void ui_update_block_buts_rgb(uiBlock *block, const float rgb[3], bool is_display_space)
+/* Updates all buttons who share the same color picker as the one passed
+ * also used by small picker, be careful with name checks below... */
+static void ui_update_color_picker_buts_rgb(uiBlock *block, ColorPicker *cpicker, const float rgb[3], bool is_display_space)
{
uiBut *bt;
- float *hsv = ui_block_hsv_get(block);
+ float *hsv = cpicker->color_data;
struct ColorManagedDisplay *display = NULL;
/* this is to keep the H and S value when V is equal to zero
* and we are working in HSV mode, of course!
@@ -1902,21 +1947,24 @@ static void ui_update_block_buts_rgb(uiBlock *block, const float rgb[3], bool is
float rgb_display[3];
copy_v3_v3(rgb_display, rgb);
- ui_block_to_display_space_v3(block, rgb_display);
+ ui_block_cm_to_display_space_v3(block, rgb_display);
ui_rgb_to_color_picker_compat_v(rgb_display, hsv);
}
if (block->color_profile)
- display = ui_block_display_get(block);
+ display = ui_block_cm_display_get(block);
/* this updates button strings, is hackish... but button pointers are on stack of caller function */
for (bt = block->buttons.first; bt; bt = bt->next) {
+ if (bt->custom_data != cpicker)
+ continue;
+
if (bt->rnaprop) {
- ui_set_but_vectorf(bt, rgb);
+ ui_but_v3_set(bt, rgb);
}
- else if (strcmp(bt->str, "Hex: ") == 0) {
+ else if (STREQ(bt->str, "Hex: ")) {
float rgb_gamma[3];
unsigned char rgb_gamma_uchar[3];
double intpart;
@@ -1942,33 +1990,33 @@ static void ui_update_block_buts_rgb(uiBlock *block, const float rgb[3], bool is
}
else if (bt->str[1] == ' ') {
if (bt->str[0] == 'R') {
- ui_set_but_val(bt, rgb[0]);
+ ui_but_value_set(bt, rgb[0]);
}
else if (bt->str[0] == 'G') {
- ui_set_but_val(bt, rgb[1]);
+ ui_but_value_set(bt, rgb[1]);
}
else if (bt->str[0] == 'B') {
- ui_set_but_val(bt, rgb[2]);
+ ui_but_value_set(bt, rgb[2]);
}
else if (bt->str[0] == 'H') {
- ui_set_but_val(bt, hsv[0]);
+ ui_but_value_set(bt, hsv[0]);
}
else if (bt->str[0] == 'S') {
- ui_set_but_val(bt, hsv[1]);
+ ui_but_value_set(bt, hsv[1]);
}
else if (bt->str[0] == 'V') {
- ui_set_but_val(bt, hsv[2]);
+ ui_but_value_set(bt, hsv[2]);
}
else if (bt->str[0] == 'L') {
- ui_set_but_val(bt, hsv[2]);
+ ui_but_value_set(bt, hsv[2]);
}
}
- ui_check_but(bt);
+ ui_but_update(bt);
}
}
-static void do_picker_rna_cb(bContext *UNUSED(C), void *bt1, void *UNUSED(arg))
+static void ui_colorpicker_rna_cb(bContext *UNUSED(C), void *bt1, void *UNUSED(arg))
{
uiBut *but = (uiBut *)bt1;
uiPopupBlockHandle *popup = but->block->handle;
@@ -1978,38 +2026,40 @@ static void do_picker_rna_cb(bContext *UNUSED(C), void *bt1, void *UNUSED(arg))
if (prop) {
RNA_property_float_get_array(&ptr, prop, rgb);
- ui_update_block_buts_rgb(but->block, rgb, (RNA_property_subtype(prop) == PROP_COLOR_GAMMA));
+ ui_update_color_picker_buts_rgb(but->block, but->custom_data, rgb, (RNA_property_subtype(prop) == PROP_COLOR_GAMMA));
}
if (popup)
popup->menuretval = UI_RETURN_UPDATE;
}
-static void do_color_wheel_rna_cb(bContext *UNUSED(C), void *bt1, void *UNUSED(arg))
+static void ui_color_wheel_rna_cb(bContext *UNUSED(C), void *bt1, void *UNUSED(arg))
{
uiBut *but = (uiBut *)bt1;
uiPopupBlockHandle *popup = but->block->handle;
float rgb[3];
- const float *hsv = ui_block_hsv_get(but->block);
- bool use_display_colorspace = ui_color_picker_use_display_colorspace(but);
+ ColorPicker *cpicker = but->custom_data;
+ float *hsv = cpicker->color_data;
+ bool use_display_colorspace = ui_but_is_colorpicker_display_space(but);
ui_color_picker_to_rgb_v(hsv, rgb);
/* hsv is saved in display space so convert back */
if (use_display_colorspace) {
- ui_block_to_scene_linear_v3(but->block, rgb);
+ ui_block_cm_to_scene_linear_v3(but->block, rgb);
}
- ui_update_block_buts_rgb(but->block, rgb, !use_display_colorspace);
+ ui_update_color_picker_buts_rgb(but->block, cpicker, rgb, !use_display_colorspace);
if (popup)
popup->menuretval = UI_RETURN_UPDATE;
}
-static void do_hex_rna_cb(bContext *UNUSED(C), void *bt1, void *hexcl)
+static void ui_colorpicker_hex_rna_cb(bContext *UNUSED(C), void *bt1, void *hexcl)
{
uiBut *but = (uiBut *)bt1;
uiPopupBlockHandle *popup = but->block->handle;
+ ColorPicker *cpicker = but->custom_data;
char *hexcol = (char *)hexcl;
float rgb[3];
@@ -2018,16 +2068,16 @@ static void do_hex_rna_cb(bContext *UNUSED(C), void *bt1, void *hexcl)
/* Hex code is assumed to be in sRGB space (coming from other applications, web, etc) */
if (but->block->color_profile) {
/* so we need to linearise it for Blender */
- ui_block_to_scene_linear_v3(but->block, rgb);
+ ui_block_cm_to_scene_linear_v3(but->block, rgb);
}
- ui_update_block_buts_rgb(but->block, rgb, false);
+ ui_update_color_picker_buts_rgb(but->block, cpicker, rgb, false);
if (popup)
popup->menuretval = UI_RETURN_UPDATE;
}
-static void close_popup_cb(bContext *UNUSED(C), void *bt1, void *UNUSED(arg))
+static void ui_popup_close_cb(bContext *UNUSED(C), void *bt1, void *UNUSED(arg))
{
uiBut *but = (uiBut *)bt1;
uiPopupBlockHandle *popup = but->block->handle;
@@ -2036,23 +2086,23 @@ static void close_popup_cb(bContext *UNUSED(C), void *bt1, void *UNUSED(arg))
popup->menuretval = UI_RETURN_OK;
}
-static void picker_new_hide_reveal(uiBlock *block, short colormode)
+static void ui_colorpicker_hide_reveal(uiBlock *block, short colormode)
{
uiBut *bt;
/* tag buttons */
for (bt = block->buttons.first; bt; bt = bt->next) {
- if ((bt->func == do_picker_rna_cb) && bt->type == NUMSLI && bt->rnaindex != 3) {
+ if ((bt->func == ui_colorpicker_rna_cb) && bt->type == UI_BTYPE_NUM_SLIDER && bt->rnaindex != 3) {
/* RGB sliders (color circle and alpha are always shown) */
if (colormode == 0) bt->flag &= ~UI_HIDDEN;
else bt->flag |= UI_HIDDEN;
}
- else if (bt->func == do_color_wheel_rna_cb) {
+ else if (bt->func == ui_color_wheel_rna_cb) {
/* HSV sliders */
if (colormode == 1) bt->flag &= ~UI_HIDDEN;
else bt->flag |= UI_HIDDEN;
}
- else if (bt->func == do_hex_rna_cb || bt->type == LABEL) {
+ else if (bt->func == ui_colorpicker_hex_rna_cb || bt->type == UI_BTYPE_LABEL) {
/* hex input or gamma correction status label */
if (colormode == 2) bt->flag &= ~UI_HIDDEN;
else bt->flag |= UI_HIDDEN;
@@ -2060,11 +2110,11 @@ static void picker_new_hide_reveal(uiBlock *block, short colormode)
}
}
-static void do_picker_new_mode_cb(bContext *UNUSED(C), void *bt1, void *UNUSED(arg))
+static void ui_colorpicker_create_mode_cb(bContext *UNUSED(C), void *bt1, void *UNUSED(arg))
{
uiBut *bt = bt1;
- short colormode = ui_get_but_val(bt);
- picker_new_hide_reveal(bt->block, colormode);
+ short colormode = ui_but_value_get(bt);
+ ui_colorpicker_hide_reveal(bt->block, colormode);
}
#define PICKER_H (7.5f * U.widget_unit)
@@ -2074,43 +2124,47 @@ static void do_picker_new_mode_cb(bContext *UNUSED(C), void *bt1, void *UNUSED(a
#define PICKER_TOTAL_W (PICKER_W + PICKER_SPACE + PICKER_BAR)
-static void circle_picker(uiBlock *block, PointerRNA *ptr, PropertyRNA *prop)
+static void ui_colorpicker_circle(uiBlock *block, PointerRNA *ptr, PropertyRNA *prop, ColorPicker *cpicker)
{
uiBut *bt;
/* HS circle */
- bt = uiDefButR_prop(block, HSVCIRCLE, 0, "", 0, 0, PICKER_H, PICKER_W, ptr, prop, -1, 0.0, 0.0, 0.0, 0, TIP_("Color"));
- uiButSetFunc(bt, do_picker_rna_cb, bt, NULL);
+ bt = uiDefButR_prop(block, UI_BTYPE_HSVCIRCLE, 0, "", 0, 0, PICKER_H, PICKER_W, ptr, prop, -1, 0.0, 0.0, 0.0, 0, TIP_("Color"));
+ UI_but_func_set(bt, ui_colorpicker_rna_cb, bt, NULL);
+ bt->custom_data = cpicker;
/* value */
if (U.color_picker_type == USER_CP_CIRCLE_HSL) {
- bt = uiDefButR_prop(block, HSVCUBE, 0, "", PICKER_W + PICKER_SPACE, 0, PICKER_BAR, PICKER_H, ptr, prop, -1, 0.0, 0.0, UI_GRAD_L_ALT, 0, "Lightness");
- uiButSetFunc(bt, do_picker_rna_cb, bt, NULL);
+ bt = uiDefButR_prop(block, UI_BTYPE_HSVCUBE, 0, "", PICKER_W + PICKER_SPACE, 0, PICKER_BAR, PICKER_H, ptr, prop, -1, 0.0, 0.0, UI_GRAD_L_ALT, 0, "Lightness");
+ UI_but_func_set(bt, ui_colorpicker_rna_cb, bt, NULL);
}
else {
- bt = uiDefButR_prop(block, HSVCUBE, 0, "", PICKER_W + PICKER_SPACE, 0, PICKER_BAR, PICKER_H, ptr, prop, -1, 0.0, 0.0, UI_GRAD_V_ALT, 0, TIP_("Value"));
- uiButSetFunc(bt, do_picker_rna_cb, bt, NULL);
+ bt = uiDefButR_prop(block, UI_BTYPE_HSVCUBE, 0, "", PICKER_W + PICKER_SPACE, 0, PICKER_BAR, PICKER_H, ptr, prop, -1, 0.0, 0.0, UI_GRAD_V_ALT, 0, TIP_("Value"));
+ UI_but_func_set(bt, ui_colorpicker_rna_cb, bt, NULL);
}
+ bt->custom_data = cpicker;
}
-static void square_picker(uiBlock *block, PointerRNA *ptr, PropertyRNA *prop, int type)
+static void ui_colorpicker_square(uiBlock *block, PointerRNA *ptr, PropertyRNA *prop, int type, ColorPicker *cpicker)
{
uiBut *bt;
int bartype = type + 3;
/* HS square */
- bt = uiDefButR_prop(block, HSVCUBE, 0, "", 0, PICKER_BAR + PICKER_SPACE, PICKER_TOTAL_W, PICKER_H, ptr, prop, -1, 0.0, 0.0, type, 0, TIP_("Color"));
- uiButSetFunc(bt, do_picker_rna_cb, bt, NULL);
+ bt = uiDefButR_prop(block, UI_BTYPE_HSVCUBE, 0, "", 0, PICKER_BAR + PICKER_SPACE, PICKER_TOTAL_W, PICKER_H, ptr, prop, -1, 0.0, 0.0, type, 0, TIP_("Color"));
+ UI_but_func_set(bt, ui_colorpicker_rna_cb, bt, NULL);
+ bt->custom_data = cpicker;
/* value */
- bt = uiDefButR_prop(block, HSVCUBE, 0, "", 0, 0, PICKER_TOTAL_W, PICKER_BAR, ptr, prop, -1, 0.0, 0.0, bartype, 0, TIP_("Value"));
- uiButSetFunc(bt, do_picker_rna_cb, bt, NULL);
+ bt = uiDefButR_prop(block, UI_BTYPE_HSVCUBE, 0, "", 0, 0, PICKER_TOTAL_W, PICKER_BAR, ptr, prop, -1, 0.0, 0.0, bartype, 0, TIP_("Value"));
+ UI_but_func_set(bt, ui_colorpicker_rna_cb, bt, NULL);
+ bt->custom_data = cpicker;
}
/* a HS circle, V slider, rgb/hsv/hex sliders */
-static void uiBlockPicker(uiBlock *block, float rgba[4], PointerRNA *ptr, PropertyRNA *prop, bool show_picker)
+static void ui_block_colorpicker(uiBlock *block, float rgba[4], PointerRNA *ptr, PropertyRNA *prop, bool show_picker)
{
static short colormode = 0; /* temp? 0=rgb, 1=hsv, 2=hex */
uiBut *bt;
@@ -2120,8 +2174,9 @@ static void uiBlockPicker(uiBlock *block, float rgba[4], PointerRNA *ptr, Proper
float rgb_gamma[3];
unsigned char rgb_gamma_uchar[3];
float softmin, softmax, hardmin, hardmax, step, precision;
- float *hsv = ui_block_hsv_get(block);
int yco;
+ ColorPicker *cpicker = ui_block_colorpicker_create(block);
+ float *hsv = cpicker->color_data;
width = PICKER_TOTAL_W;
butwidth = width - 1.5f * UI_UNIT_X;
@@ -2137,7 +2192,7 @@ static void uiBlockPicker(uiBlock *block, float rgba[4], PointerRNA *ptr, Proper
/* make a display version, for Hex code */
copy_v3_v3(rgb_gamma, rgba);
- ui_block_to_display_space_v3(block, rgb_gamma);
+ ui_block_cm_to_display_space_v3(block, rgb_gamma);
}
/* sneaky way to check for alpha */
@@ -2149,75 +2204,86 @@ static void uiBlockPicker(uiBlock *block, float rgba[4], PointerRNA *ptr, Proper
switch (U.color_picker_type) {
case USER_CP_SQUARE_SV:
- square_picker(block, ptr, prop, UI_GRAD_SV);
+ ui_colorpicker_square(block, ptr, prop, UI_GRAD_SV, cpicker);
break;
case USER_CP_SQUARE_HS:
- square_picker(block, ptr, prop, UI_GRAD_HS);
+ ui_colorpicker_square(block, ptr, prop, UI_GRAD_HS, cpicker);
break;
case USER_CP_SQUARE_HV:
- square_picker(block, ptr, prop, UI_GRAD_HV);
+ ui_colorpicker_square(block, ptr, prop, UI_GRAD_HV, cpicker);
break;
/* user default */
case USER_CP_CIRCLE_HSV:
case USER_CP_CIRCLE_HSL:
default:
- circle_picker(block, ptr, prop);
+ ui_colorpicker_circle(block, ptr, prop, cpicker);
break;
}
/* mode */
yco = -1.5f * UI_UNIT_Y;
- uiBlockBeginAlign(block);
- bt = uiDefButS(block, ROW, 0, IFACE_("RGB"), 0, yco, width / 3, UI_UNIT_Y, &colormode, 0.0, 0.0, 0, 0, "");
- uiButSetFunc(bt, do_picker_new_mode_cb, bt, NULL);
+ UI_block_align_begin(block);
+ bt = uiDefButS(block, UI_BTYPE_ROW, 0, IFACE_("RGB"), 0, yco, width / 3, UI_UNIT_Y, &colormode, 0.0, 0.0, 0, 0, "");
+ UI_but_func_set(bt, ui_colorpicker_create_mode_cb, bt, NULL);
+ bt->custom_data = cpicker;
if (U.color_picker_type == USER_CP_CIRCLE_HSL)
- bt = uiDefButS(block, ROW, 0, IFACE_("HSL"), width / 3, yco, width / 3, UI_UNIT_Y, &colormode, 0.0, 1.0, 0, 0, "");
+ bt = uiDefButS(block, UI_BTYPE_ROW, 0, IFACE_("HSL"), width / 3, yco, width / 3, UI_UNIT_Y, &colormode, 0.0, 1.0, 0, 0, "");
else
- bt = uiDefButS(block, ROW, 0, IFACE_("HSV"), width / 3, yco, width / 3, UI_UNIT_Y, &colormode, 0.0, 1.0, 0, 0, "");
- uiButSetFunc(bt, do_picker_new_mode_cb, bt, NULL);
- bt = uiDefButS(block, ROW, 0, IFACE_("Hex"), 2 * width / 3, yco, width / 3, UI_UNIT_Y, &colormode, 0.0, 2.0, 0, 0, "");
- uiButSetFunc(bt, do_picker_new_mode_cb, bt, NULL);
- uiBlockEndAlign(block);
+ bt = uiDefButS(block, UI_BTYPE_ROW, 0, IFACE_("HSV"), width / 3, yco, width / 3, UI_UNIT_Y, &colormode, 0.0, 1.0, 0, 0, "");
+ UI_but_func_set(bt, ui_colorpicker_create_mode_cb, bt, NULL);
+ bt->custom_data = cpicker;
+ bt = uiDefButS(block, UI_BTYPE_ROW, 0, IFACE_("Hex"), 2 * width / 3, yco, width / 3, UI_UNIT_Y, &colormode, 0.0, 2.0, 0, 0, "");
+ UI_but_func_set(bt, ui_colorpicker_create_mode_cb, bt, NULL);
+ bt->custom_data = cpicker;
+ UI_block_align_end(block);
yco = -3.0f * UI_UNIT_Y;
if (show_picker) {
- bt = uiDefIconButO(block, BUT, "UI_OT_eyedropper_color", WM_OP_INVOKE_DEFAULT, ICON_EYEDROPPER, butwidth + 10, yco, UI_UNIT_X, UI_UNIT_Y, NULL);
- uiButSetFunc(bt, close_popup_cb, bt, NULL);
+ bt = uiDefIconButO(block, UI_BTYPE_BUT, "UI_OT_eyedropper_color", WM_OP_INVOKE_DEFAULT, ICON_EYEDROPPER, butwidth + 10, yco, UI_UNIT_X, UI_UNIT_Y, NULL);
+ UI_but_func_set(bt, ui_popup_close_cb, bt, NULL);
+ bt->custom_data = cpicker;
}
/* 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"));
- 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"));
- 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"));
- uiButSetFunc(bt, do_picker_rna_cb, bt, NULL);
+ UI_block_align_begin(block);
+ bt = uiDefButR_prop(block, UI_BTYPE_NUM_SLIDER, 0, IFACE_("R:"), 0, yco, butwidth, UI_UNIT_Y, ptr, prop, 0, 0.0, 0.0, 0, 3, TIP_("Red"));
+ UI_but_func_set(bt, ui_colorpicker_rna_cb, bt, NULL);
+ bt->custom_data = cpicker;
+ bt = uiDefButR_prop(block, UI_BTYPE_NUM_SLIDER, 0, IFACE_("G:"), 0, yco -= UI_UNIT_Y, butwidth, UI_UNIT_Y, ptr, prop, 1, 0.0, 0.0, 0, 3, TIP_("Green"));
+ UI_but_func_set(bt, ui_colorpicker_rna_cb, bt, NULL);
+ bt->custom_data = cpicker;
+ bt = uiDefButR_prop(block, UI_BTYPE_NUM_SLIDER, 0, IFACE_("B:"), 0, yco -= UI_UNIT_Y, butwidth, UI_UNIT_Y, ptr, prop, 2, 0.0, 0.0, 0, 3, TIP_("Blue"));
+ UI_but_func_set(bt, ui_colorpicker_rna_cb, bt, NULL);
+ bt->custom_data = cpicker;
/* could use uiItemFullR(col, ptr, prop, -1, 0, UI_ITEM_R_EXPAND|UI_ITEM_R_SLIDER, "", ICON_NONE);
- * but need to use uiButSetFunc for updating other fake buttons */
+ * but need to use UI_but_func_set for updating other fake buttons */
/* 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"));
- uiButSetFunc(bt, do_color_wheel_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"));
- uiButSetFunc(bt, do_color_wheel_rna_cb, bt, hsv);
+ UI_block_align_begin(block);
+ bt = uiDefButF(block, UI_BTYPE_NUM_SLIDER, 0, IFACE_("H:"), 0, yco, butwidth, UI_UNIT_Y, hsv, 0.0, 1.0, 10, 3, TIP_("Hue"));
+ UI_but_func_set(bt, ui_color_wheel_rna_cb, bt, hsv);
+ bt->custom_data = cpicker;
+ bt = uiDefButF(block, UI_BTYPE_NUM_SLIDER, 0, IFACE_("S:"), 0, yco -= UI_UNIT_Y, butwidth, UI_UNIT_Y, hsv + 1, 0.0, 1.0, 10, 3, TIP_("Saturation"));
+ UI_but_func_set(bt, ui_color_wheel_rna_cb, bt, hsv);
+ bt->custom_data = cpicker;
if (U.color_picker_type == USER_CP_CIRCLE_HSL)
- bt = uiDefButF(block, NUMSLI, 0, IFACE_("L:"), 0, yco -= UI_UNIT_Y, butwidth, UI_UNIT_Y, hsv + 2, 0.0, 1.0, 10, 3, TIP_("Lightness"));
+ bt = uiDefButF(block, UI_BTYPE_NUM_SLIDER, 0, IFACE_("L:"), 0, yco -= UI_UNIT_Y, butwidth, UI_UNIT_Y, hsv + 2, 0.0, 1.0, 10, 3, TIP_("Lightness"));
else
- 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, UI_BTYPE_NUM_SLIDER, 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_color_wheel_rna_cb, bt, hsv);
+ UI_but_func_set(bt, ui_color_wheel_rna_cb, bt, hsv);
+ bt->custom_data = cpicker;
- uiBlockEndAlign(block);
+ UI_block_align_end(block);
if (rgba[3] != FLT_MAX) {
- bt = uiDefButR_prop(block, NUMSLI, 0, IFACE_("A: "), 0, yco -= UI_UNIT_Y, butwidth, UI_UNIT_Y, ptr, prop, 3, 0.0, 0.0, 0, 3, TIP_("Alpha"));
- uiButSetFunc(bt, do_picker_rna_cb, bt, NULL);
+ bt = uiDefButR_prop(block, UI_BTYPE_NUM_SLIDER, 0, IFACE_("A: "), 0, yco -= UI_UNIT_Y, butwidth, UI_UNIT_Y, ptr, prop, 3, 0.0, 0.0, 0, 3, TIP_("Alpha"));
+ UI_but_func_set(bt, ui_colorpicker_rna_cb, bt, NULL);
+ bt->custom_data = cpicker;
}
else {
rgba[3] = 1.0f;
@@ -2227,17 +2293,18 @@ static void uiBlockPicker(uiBlock *block, float rgba[4], PointerRNA *ptr, Proper
BLI_snprintf(hexcol, sizeof(hexcol), "%02X%02X%02X", UNPACK3_EX((unsigned int), rgb_gamma_uchar, ));
yco = -3.0f * UI_UNIT_Y;
- bt = uiDefBut(block, TEX, 0, IFACE_("Hex: "), 0, yco, butwidth, UI_UNIT_Y, hexcol, 0, 8, 0, 0, TIP_("Hex triplet for color (#RRGGBB)"));
- uiButSetFunc(bt, do_hex_rna_cb, bt, hexcol);
- uiDefBut(block, LABEL, 0, IFACE_("(Gamma Corrected)"), 0, yco - UI_UNIT_Y, butwidth, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
+ bt = uiDefBut(block, UI_BTYPE_TEXT, 0, IFACE_("Hex: "), 0, yco, butwidth, UI_UNIT_Y, hexcol, 0, 8, 0, 0, TIP_("Hex triplet for color (#RRGGBB)"));
+ UI_but_func_set(bt, ui_colorpicker_hex_rna_cb, bt, hexcol);
+ bt->custom_data = cpicker;
+ uiDefBut(block, UI_BTYPE_LABEL, 0, IFACE_("(Gamma Corrected)"), 0, yco - UI_UNIT_Y, butwidth, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
ui_rgb_to_color_picker_v(rgb_gamma, hsv);
- picker_new_hide_reveal(block, colormode);
+ ui_colorpicker_hide_reveal(block, colormode);
}
-static int ui_picker_small_wheel_cb(const bContext *UNUSED(C), uiBlock *block, const wmEvent *event)
+static int ui_colorpicker_small_wheel_cb(const bContext *UNUSED(C), uiBlock *block, const wmEvent *event)
{
float add = 0.0f;
@@ -2250,16 +2317,17 @@ static int ui_picker_small_wheel_cb(const bContext *UNUSED(C), uiBlock *block, c
uiBut *but;
for (but = block->buttons.first; but; but = but->next) {
- if (but->type == HSVCUBE && but->active == NULL) {
+ if (but->type == UI_BTYPE_HSVCUBE && but->active == NULL) {
uiPopupBlockHandle *popup = block->handle;
float rgb[3];
- float *hsv = ui_block_hsv_get(block);
- bool use_display_colorspace = ui_color_picker_use_display_colorspace(but);
+ ColorPicker *cpicker = but->custom_data;
+ float *hsv = cpicker->color_data;
+ bool use_display_colorspace = ui_but_is_colorpicker_display_space(but);
- ui_get_but_vectorf(but, rgb);
+ ui_but_v3_get(but, rgb);
if (use_display_colorspace)
- ui_block_to_display_space_v3(block, rgb);
+ ui_block_cm_to_display_space_v3(block, rgb);
ui_rgb_to_color_picker_compat_v(rgb, hsv);
@@ -2267,11 +2335,11 @@ static int ui_picker_small_wheel_cb(const bContext *UNUSED(C), uiBlock *block, c
ui_color_picker_to_rgb_v(hsv, rgb);
if (use_display_colorspace)
- ui_block_to_scene_linear_v3(block, rgb);
+ ui_block_cm_to_scene_linear_v3(block, rgb);
- ui_set_but_vectorf(but, rgb);
+ ui_but_v3_set(but, rgb);
- ui_update_block_buts_rgb(block, rgb, !use_display_colorspace);
+ ui_update_color_picker_buts_rgb(block, cpicker, rgb, !use_display_colorspace);
if (popup)
popup->menuretval = UI_RETURN_UPDATE;
@@ -2288,7 +2356,7 @@ uiBlock *ui_block_func_COLOR(bContext *C, uiPopupBlockHandle *handle, void *arg_
uiBlock *block;
bool show_picker = true;
- block = uiBeginBlock(C, handle->region, __func__, UI_EMBOSS);
+ block = UI_block_begin(C, handle->region, __func__, UI_EMBOSS);
if (RNA_property_subtype(but->rnaprop) == PROP_COLOR_GAMMA) {
block->color_profile = false;
@@ -2304,15 +2372,15 @@ uiBlock *ui_block_func_COLOR(bContext *C, uiPopupBlockHandle *handle, void *arg_
copy_v3_v3(handle->retvec, but->editvec);
- uiBlockPicker(block, handle->retvec, &but->rnapoin, but->rnaprop, show_picker);
+ ui_block_colorpicker(block, handle->retvec, &but->rnapoin, but->rnaprop, show_picker);
- block->flag = UI_BLOCK_LOOP | UI_BLOCK_REDRAW | UI_BLOCK_KEEP_OPEN | UI_BLOCK_OUT_1 | UI_BLOCK_MOVEMOUSE_QUIT;
- uiBoundsBlock(block, 0.5 * UI_UNIT_X);
+ block->flag = UI_BLOCK_LOOP | UI_BLOCK_KEEP_OPEN | UI_BLOCK_OUT_1 | UI_BLOCK_MOVEMOUSE_QUIT;
+ UI_block_bounds_set_normal(block, 0.5 * UI_UNIT_X);
- block->block_event_func = ui_picker_small_wheel_cb;
+ block->block_event_func = ui_colorpicker_small_wheel_cb;
/* and lets go */
- block->direction = UI_TOP;
+ block->direction = UI_DIR_UP;
return block;
}
@@ -2448,39 +2516,39 @@ static uiBlock *ui_block_func_POPUP(bContext *C, uiPopupBlockHandle *handle, voi
/* allow overriding the direction from menu_func */
direction = pup->block->direction;
}
- else if ((pup->but->type == PULLDOWN) ||
- (uiButGetMenuType(pup->but) != NULL))
+ else if ((pup->but->type == UI_BTYPE_PULLDOWN) ||
+ (UI_but_menutype_get(pup->but) != NULL))
{
- direction = UI_DOWN;
+ direction = UI_DIR_DOWN;
}
else {
- direction = UI_TOP;
+ direction = UI_DIR_UP;
}
}
else {
minwidth = 50;
- direction = UI_DOWN;
+ direction = UI_DIR_DOWN;
}
- flip = (direction == UI_DOWN);
+ flip = (direction == UI_DIR_DOWN);
block = pup->block;
/* in some cases we create the block before the region,
* so we set it delayed here if necessary */
if (BLI_findindex(&handle->region->uiblocks, block) == -1)
- uiBlockSetRegion(block, handle->region);
+ UI_block_region_set(block, handle->region);
block->direction = direction;
- uiBlockLayoutResolve(block, &width, &height);
+ UI_block_layout_resolve(block, &width, &height);
- uiBlockSetFlag(block, UI_BLOCK_MOVEMOUSE_QUIT);
+ UI_block_flag_enable(block, UI_BLOCK_MOVEMOUSE_QUIT);
if (pup->popup) {
uiBut *but_activate = NULL;
- uiBlockSetFlag(block, UI_BLOCK_LOOP | UI_BLOCK_REDRAW | UI_BLOCK_NUMSELECT);
- uiBlockSetDirection(block, direction);
+ UI_block_flag_enable(block, UI_BLOCK_LOOP | UI_BLOCK_NUMSELECT);
+ UI_block_direction_set(block, direction);
/* offset the mouse position, possibly based on earlier selection */
if ((block->flag & UI_BLOCK_POPUP_MEMORY) &&
@@ -2518,11 +2586,11 @@ static uiBlock *ui_block_func_POPUP(bContext *C, uiPopupBlockHandle *handle, voi
* to be within the window bounds may move it away from the mouse,
* This ensures we set an item to be active. */
if (but_activate) {
- ui_button_activate_over(C, handle->region, but_activate);
+ ui_but_activate_over(C, handle->region, but_activate);
}
block->minbounds = minwidth;
- uiMenuPopupBoundsBlock(block, 1, offset[0], offset[1]);
+ UI_block_bounds_set_menu(block, 1, offset[0], offset[1]);
}
else {
/* for a header menu we set the direction automatic */
@@ -2531,35 +2599,36 @@ static uiBlock *ui_block_func_POPUP(bContext *C, uiPopupBlockHandle *handle, voi
if (sa && sa->headertype == HEADERDOWN) {
ARegion *ar = CTX_wm_region(C);
if (ar && ar->regiontype == RGN_TYPE_HEADER) {
- uiBlockSetDirection(block, UI_TOP);
- uiBlockFlipOrder(block);
+ UI_block_direction_set(block, UI_DIR_UP);
+ UI_block_order_flip(block);
}
}
}
block->minbounds = minwidth;
- uiTextBoundsBlock(block, 3.0f * UI_UNIT_X);
+ UI_block_bounds_set_text(block, 3.0f * UI_UNIT_X);
}
/* if menu slides out of other menu, override direction */
if (pup->slideout)
- uiBlockSetDirection(block, UI_RIGHT);
+ UI_block_direction_set(block, UI_DIR_RIGHT);
return pup->block;
}
-uiPopupBlockHandle *ui_popup_menu_create(bContext *C, ARegion *butregion, uiBut *but,
- uiMenuCreateFunc menu_func, void *arg)
+uiPopupBlockHandle *ui_popup_menu_create(
+ bContext *C, ARegion *butregion, uiBut *but,
+ uiMenuCreateFunc menu_func, void *arg)
{
wmWindow *window = CTX_wm_window(C);
- uiStyle *style = UI_GetStyleDraw();
+ uiStyle *style = UI_style_get_dpi();
uiPopupBlockHandle *handle;
uiPopupMenu *pup;
pup = MEM_callocN(sizeof(uiPopupMenu), __func__);
- pup->block = uiBeginBlock(C, NULL, __func__, UI_EMBOSSP);
+ pup->block = UI_block_begin(C, NULL, __func__, UI_EMBOSS_PULLDOWN);
pup->block->flag |= UI_BLOCK_NUMSELECT; /* default menus to numselect */
- pup->layout = uiBlockLayout(pup->block, UI_LAYOUT_VERTICAL, UI_LAYOUT_MENU, 0, 0, 200, 0, MENU_PADDING, style);
+ pup->layout = UI_block_layout(pup->block, UI_LAYOUT_VERTICAL, UI_LAYOUT_MENU, 0, 0, 200, 0, MENU_PADDING, style);
pup->slideout = but ? ui_block_is_menu(but->block) : false;
pup->but = but;
uiLayoutSetOperatorContext(pup->layout, WM_OP_INVOKE_REGION_WIN);
@@ -2596,7 +2665,7 @@ uiPopupBlockHandle *ui_popup_menu_create(bContext *C, ARegion *butregion, uiBut
if (!but) {
handle->popup = true;
- UI_add_popup_handlers(C, &window->modalhandlers, handle, false);
+ UI_popup_handlers_add(C, &window->modalhandlers, handle, 0);
WM_event_add_mousemove(C);
}
@@ -2608,16 +2677,16 @@ uiPopupBlockHandle *ui_popup_menu_create(bContext *C, ARegion *butregion, uiBut
/******************** Popup Menu API with begin and end ***********************/
/* only return handler, and set optional title */
-uiPopupMenu *uiPupMenuBegin(bContext *C, const char *title, int icon)
+uiPopupMenu *UI_popup_menu_begin(bContext *C, const char *title, int icon)
{
- uiStyle *style = UI_GetStyleDraw();
+ uiStyle *style = UI_style_get_dpi();
uiPopupMenu *pup = MEM_callocN(sizeof(uiPopupMenu), "popup menu");
uiBut *but;
- pup->block = uiBeginBlock(C, NULL, __func__, UI_EMBOSSP);
- pup->block->flag |= UI_BLOCK_POPUP_MEMORY;
+ pup->block = UI_block_begin(C, NULL, __func__, UI_EMBOSS_PULLDOWN);
+ pup->block->flag |= UI_BLOCK_POPUP_MEMORY | UI_BLOCK_IS_FLIP;
pup->block->puphash = ui_popup_menu_hash(title);
- pup->layout = uiBlockLayout(pup->block, UI_LAYOUT_VERTICAL, UI_LAYOUT_MENU, 0, 0, 200, 0, MENU_PADDING, style);
+ pup->layout = UI_block_layout(pup->block, UI_LAYOUT_VERTICAL, UI_LAYOUT_MENU, 0, 0, 200, 0, MENU_PADDING, style);
/* note, this intentionally differs from the menu & submenu default because many operators
* use popups like this to select one of their options - where having invoke doesn't make sense */
@@ -2632,10 +2701,10 @@ uiPopupMenu *uiPupMenuBegin(bContext *C, const char *title, int icon)
if (icon) {
BLI_snprintf(titlestr, sizeof(titlestr), " %s", title);
- uiDefIconTextBut(pup->block, LABEL, 0, icon, titlestr, 0, 0, 200, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
+ uiDefIconTextBut(pup->block, UI_BTYPE_LABEL, 0, icon, titlestr, 0, 0, 200, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
}
else {
- but = uiDefBut(pup->block, LABEL, 0, title, 0, 0, 200, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
+ but = uiDefBut(pup->block, UI_BTYPE_LABEL, 0, title, 0, 0, 200, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
but->drawflag = UI_BUT_TEXT_LEFT;
}
@@ -2646,7 +2715,7 @@ uiPopupMenu *uiPupMenuBegin(bContext *C, const char *title, int icon)
}
/* set the whole structure to work */
-void uiPupMenuEnd(bContext *C, uiPopupMenu *pup)
+void UI_popup_menu_end(bContext *C, uiPopupMenu *pup)
{
wmWindow *window = CTX_wm_window(C);
uiPopupBlockHandle *menu;
@@ -2658,13 +2727,13 @@ void uiPupMenuEnd(bContext *C, uiPopupMenu *pup)
menu = ui_popup_block_create(C, NULL, NULL, NULL, ui_block_func_POPUP, pup);
menu->popup = true;
- UI_add_popup_handlers(C, &window->modalhandlers, menu, false);
+ UI_popup_handlers_add(C, &window->modalhandlers, menu, 0);
WM_event_add_mousemove(C);
MEM_freeN(pup);
}
-uiLayout *uiPupMenuLayout(uiPopupMenu *pup)
+uiLayout *UI_popup_menu_layout(uiPopupMenu *pup)
{
return pup->layout;
}
@@ -2683,11 +2752,11 @@ static uiBlock *ui_block_func_PIE(bContext *UNUSED(C), uiPopupBlockHandle *handl
/* in some cases we create the block before the region,
* so we set it delayed here if necessary */
if (BLI_findindex(&handle->region->uiblocks, block) == -1)
- uiBlockSetRegion(block, handle->region);
+ UI_block_region_set(block, handle->region);
- uiBlockLayoutResolve(block, &width, &height);
+ UI_block_layout_resolve(block, &width, &height);
- uiBlockSetFlag(block, UI_BLOCK_LOOP | UI_BLOCK_REDRAW | UI_BLOCK_NUMSELECT);
+ UI_block_flag_enable(block, UI_BLOCK_LOOP | UI_BLOCK_NUMSELECT);
block->minbounds = minwidth;
block->bounds = 1;
@@ -2701,26 +2770,56 @@ static uiBlock *ui_block_func_PIE(bContext *UNUSED(C), uiPopupBlockHandle *handl
return pie->block_radial;
}
-static float uiPieTitleWidth(const char *name, int icon)
+static float ui_pie_menu_title_width(const char *name, int icon)
{
- return (UI_GetStringWidth(name) +
+ const uiFontStyle *fstyle = UI_FSTYLE_WIDGET;
+ return (UI_fontstyle_string_width(fstyle, name) +
(UI_UNIT_X * (1.50f + (icon ? 0.25f : 0.0f))));
}
-uiPieMenu *uiPieMenuBegin(struct bContext *C, const char *title, int icon, const wmEvent *event)
+uiPieMenu *UI_pie_menu_begin(struct bContext *C, const char *title, int icon, const wmEvent *event)
{
- uiStyle *style = UI_GetStyleDraw();
- uiPieMenu *pie = MEM_callocN(sizeof(uiPopupMenu), "pie menu");
+ uiStyle *style;
+ uiPieMenu *pie;
+ short event_type;
- pie->block_radial = uiBeginBlock(C, NULL, __func__, UI_EMBOSS);
+ wmWindow *win = CTX_wm_window(C);
+
+ style = UI_style_get_dpi();
+ pie = MEM_callocN(sizeof(uiPopupMenu), "pie menu");
+
+ pie->block_radial = UI_block_begin(C, NULL, __func__, UI_EMBOSS);
/* may be useful later to allow spawning pies
* from old positions */
/* pie->block_radial->flag |= UI_BLOCK_POPUP_MEMORY; */
pie->block_radial->puphash = ui_popup_menu_hash(title);
pie->block_radial->flag |= UI_BLOCK_RADIAL;
- pie->block_radial->pie_data.event = event->type;
- pie->layout = uiBlockLayout(pie->block_radial, UI_LAYOUT_VERTICAL, UI_LAYOUT_PIEMENU, 0, 0, 200, 0, 0, style);
+ /* if pie is spawned by a left click, it is always assumed to be click style */
+ if (event->type == LEFTMOUSE) {
+ pie->block_radial->pie_data.flags |= UI_PIE_CLICK_STYLE;
+ pie->block_radial->pie_data.event = EVENT_NONE;
+ win->lock_pie_event = EVENT_NONE;
+ }
+ else {
+ if (win->last_pie_event != EVENT_NONE) {
+ /* original pie key has been released, so don't propagate the event */
+ if (win->lock_pie_event == EVENT_NONE) {
+ event_type = EVENT_NONE;
+ pie->block_radial->pie_data.flags |= UI_PIE_CLICK_STYLE;
+ }
+ else
+ event_type = win->last_pie_event;
+ }
+ else {
+ event_type = event->type;
+ }
+
+ pie->block_radial->pie_data.event = event_type;
+ win->lock_pie_event = event_type;
+ }
+
+ pie->layout = UI_block_layout(pie->block_radial, UI_LAYOUT_VERTICAL, UI_LAYOUT_PIEMENU, 0, 0, 200, 0, 0, style);
pie->mx = event->x;
pie->my = event->y;
@@ -2731,12 +2830,12 @@ uiPieMenu *uiPieMenuBegin(struct bContext *C, const char *title, int icon, const
int w;
if (icon) {
BLI_snprintf(titlestr, sizeof(titlestr), " %s", title);
- w = uiPieTitleWidth(titlestr, icon);
- but = uiDefIconTextBut(pie->block_radial, LABEL, 0, icon, titlestr, 0, 0, w, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
+ w = ui_pie_menu_title_width(titlestr, icon);
+ but = uiDefIconTextBut(pie->block_radial, UI_BTYPE_LABEL, 0, icon, titlestr, 0, 0, w, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
}
else {
- w = uiPieTitleWidth(title, 0);
- but = uiDefBut(pie->block_radial, LABEL, 0, title, 0, 0, w, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
+ w = ui_pie_menu_title_width(title, 0);
+ but = uiDefBut(pie->block_radial, UI_BTYPE_LABEL, 0, title, 0, 0, w, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
}
/* do not align left */
but->drawflag &= ~UI_BUT_TEXT_LEFT;
@@ -2745,7 +2844,7 @@ uiPieMenu *uiPieMenuBegin(struct bContext *C, const char *title, int icon, const
return pie;
}
-void uiPieMenuEnd(bContext *C, uiPieMenu *pie)
+void UI_pie_menu_end(bContext *C, uiPieMenu *pie)
{
wmWindow *window = CTX_wm_window(C);
uiPopupBlockHandle *menu;
@@ -2754,18 +2853,20 @@ void uiPieMenuEnd(bContext *C, uiPieMenu *pie)
menu->popup = true;
menu->towardstime = PIL_check_seconds_timer();
- UI_add_popup_handlers(C, &window->modalhandlers, menu, true);
+ UI_popup_handlers_add(
+ C, &window->modalhandlers,
+ menu, WM_HANDLER_ACCEPT_DBL_CLICK);
WM_event_add_mousemove(C);
MEM_freeN(pie);
}
-uiLayout *uiPieMenuLayout(uiPieMenu *pie)
+uiLayout *UI_pie_menu_layout(uiPieMenu *pie)
{
return pie->layout;
}
-void uiPieMenuInvoke(struct bContext *C, const char *idname, const wmEvent *event)
+int UI_pie_menu_invoke(struct bContext *C, const char *idname, const wmEvent *event)
{
uiPieMenu *pie;
uiLayout *layout;
@@ -2774,14 +2875,14 @@ void uiPieMenuInvoke(struct bContext *C, const char *idname, const wmEvent *even
if (mt == NULL) {
printf("%s: named menu \"%s\" not found\n", __func__, idname);
- return;
+ return OPERATOR_CANCELLED;
}
if (mt->poll && mt->poll(C, mt) == 0)
- return;
+ return OPERATOR_CANCELLED;
- pie = uiPieMenuBegin(C, IFACE_(mt->label), ICON_NONE, event);
- layout = uiPieMenuLayout(pie);
+ pie = UI_pie_menu_begin(C, IFACE_(mt->label), ICON_NONE, event);
+ layout = UI_pie_menu_layout(pie);
menu.layout = layout;
menu.type = mt;
@@ -2792,26 +2893,32 @@ void uiPieMenuInvoke(struct bContext *C, const char *idname, const wmEvent *even
mt->draw(C, &menu);
- uiPieMenuEnd(C, pie);
+ UI_pie_menu_end(C, pie);
+
+ return OPERATOR_INTERFACE;
}
-void uiPieOperatorEnumInvoke(struct bContext *C, const char *title, const char *opname,
- const char *propname, const wmEvent *event)
+int UI_pie_menu_invoke_from_operator_enum(
+ struct bContext *C, const char *title, const char *opname,
+ const char *propname, const wmEvent *event)
{
uiPieMenu *pie;
uiLayout *layout;
- pie = uiPieMenuBegin(C, IFACE_(title), ICON_NONE, event);
- layout = uiPieMenuLayout(pie);
+ pie = UI_pie_menu_begin(C, IFACE_(title), ICON_NONE, event);
+ layout = UI_pie_menu_layout(pie);
layout = uiLayoutRadial(layout);
uiItemsEnumO(layout, opname, propname);
- uiPieMenuEnd(C, pie);
+ UI_pie_menu_end(C, pie);
+
+ return OPERATOR_INTERFACE;
}
-void uiPieEnumInvoke(struct bContext *C, const char *title, const char *path,
- const wmEvent *event)
+int UI_pie_menu_invoke_from_rna_enum(
+ struct bContext *C, const char *title, const char *path,
+ const wmEvent *event)
{
PointerRNA ctx_ptr;
PointerRNA r_ptr;
@@ -2822,28 +2929,31 @@ void uiPieEnumInvoke(struct bContext *C, const char *title, const char *path,
RNA_pointer_create(NULL, &RNA_Context, C, &ctx_ptr);
if (!RNA_path_resolve(&ctx_ptr, path, &r_ptr, &r_prop)) {
- return;
+ return OPERATOR_CANCELLED;
}
/* invalid property, only accept enums */
if (RNA_property_type(r_prop) != PROP_ENUM) {
BLI_assert(0);
- return;
+ return OPERATOR_CANCELLED;
}
- pie = uiPieMenuBegin(C, IFACE_(title), ICON_NONE, event);
- layout = uiPieMenuLayout(pie);
+ pie = UI_pie_menu_begin(C, IFACE_(title), ICON_NONE, event);
+
+ layout = UI_pie_menu_layout(pie);
layout = uiLayoutRadial(layout);
uiItemFullR(layout, &r_ptr, r_prop, RNA_NO_INDEX, 0, UI_ITEM_R_EXPAND, NULL, 0);
- uiPieMenuEnd(C, pie);
+ UI_pie_menu_end(C, pie);
+
+ return OPERATOR_INTERFACE;
}
/*************************** Standard Popup Menus ****************************/
-void uiPupMenuReports(bContext *C, ReportList *reports)
+void UI_popup_menu_reports(bContext *C, ReportList *reports)
{
Report *report;
@@ -2864,8 +2974,8 @@ void uiPupMenuReports(bContext *C, ReportList *reports)
if (pup == NULL) {
char title[UI_MAX_DRAW_STR];
BLI_snprintf(title, sizeof(title), "%s: %s", IFACE_("Report"), report->typestr);
- pup = uiPupMenuBegin(C, title, ICON_NONE);
- layout = uiPupMenuLayout(pup);
+ pup = UI_popup_menu_begin(C, title, ICON_NONE);
+ layout = UI_popup_menu_layout(pup);
}
else {
uiItemS(layout);
@@ -2873,7 +2983,7 @@ void uiPupMenuReports(bContext *C, ReportList *reports)
/* split each newline into a label */
msg = report->message;
- icon = uiIconFromReportType(report->type);
+ icon = UI_icon_from_report_type(report->type);
do {
char buf[UI_MAX_DRAW_STR];
msg_next = strchr(msg, '\n');
@@ -2888,11 +2998,11 @@ void uiPupMenuReports(bContext *C, ReportList *reports)
}
if (pup) {
- uiPupMenuEnd(C, pup);
+ UI_popup_menu_end(C, pup);
}
}
-bool uiPupMenuInvoke(bContext *C, const char *idname, ReportList *reports)
+int UI_popup_menu_invoke(bContext *C, const char *idname, ReportList *reports)
{
uiPopupMenu *pup;
uiLayout *layout;
@@ -2901,14 +3011,14 @@ bool uiPupMenuInvoke(bContext *C, const char *idname, ReportList *reports)
if (mt == NULL) {
BKE_reportf(reports, RPT_ERROR, "Menu \"%s\" not found", idname);
- return false;
+ return OPERATOR_CANCELLED;
}
if (mt->poll && mt->poll(C, mt) == 0)
- return false;
+ return OPERATOR_CANCELLED;
- pup = uiPupMenuBegin(C, IFACE_(mt->label), ICON_NONE);
- layout = uiPupMenuLayout(pup);
+ pup = UI_popup_menu_begin(C, IFACE_(mt->label), ICON_NONE);
+ layout = UI_popup_menu_layout(pup);
menu.layout = layout;
menu.type = mt;
@@ -2919,15 +3029,15 @@ bool uiPupMenuInvoke(bContext *C, const char *idname, ReportList *reports)
mt->draw(C, &menu);
- uiPupMenuEnd(C, pup);
+ UI_popup_menu_end(C, pup);
- return true;
+ return OPERATOR_INTERFACE;
}
/*************************** Popup Block API **************************/
-void uiPupBlockO(bContext *C, uiBlockCreateFunc func, void *arg, const char *opname, int opcontext)
+void UI_popup_block_invoke_ex(bContext *C, uiBlockCreateFunc func, void *arg, const char *opname, int opcontext)
{
wmWindow *window = CTX_wm_window(C);
uiPopupBlockHandle *handle;
@@ -2937,16 +3047,16 @@ void uiPupBlockO(bContext *C, uiBlockCreateFunc func, void *arg, const char *opn
handle->optype = (opname) ? WM_operatortype_find(opname, 0) : NULL;
handle->opcontext = opcontext;
- UI_add_popup_handlers(C, &window->modalhandlers, handle, false);
+ UI_popup_handlers_add(C, &window->modalhandlers, handle, 0);
WM_event_add_mousemove(C);
}
-void uiPupBlock(bContext *C, uiBlockCreateFunc func, void *arg)
+void UI_popup_block_invoke(bContext *C, uiBlockCreateFunc func, void *arg)
{
- uiPupBlockO(C, func, arg, NULL, WM_OP_INVOKE_DEFAULT);
+ UI_popup_block_invoke_ex(C, func, arg, NULL, WM_OP_INVOKE_DEFAULT);
}
-void uiPupBlockEx(bContext *C, uiBlockCreateFunc func, uiBlockHandleFunc popup_func, uiBlockCancelFunc cancel_func, void *arg)
+void UI_popup_block_ex(bContext *C, uiBlockCreateFunc func, uiBlockHandleFunc popup_func, uiBlockCancelFunc cancel_func, void *arg)
{
wmWindow *window = CTX_wm_window(C);
uiPopupBlockHandle *handle;
@@ -2960,7 +3070,7 @@ void uiPupBlockEx(bContext *C, uiBlockCreateFunc func, uiBlockHandleFunc popup_f
handle->cancel_func = cancel_func;
// handle->opcontext = opcontext;
- UI_add_popup_handlers(C, &window->modalhandlers, handle, false);
+ UI_popup_handlers_add(C, &window->modalhandlers, handle, 0);
WM_event_add_mousemove(C);
}
@@ -2979,27 +3089,28 @@ void uiPupBlockOperator(bContext *C, uiBlockCreateFunc func, wmOperator *op, int
handle->cancel_func = confirm_cancel_operator;
handle->opcontext = opcontext;
- UI_add_popup_handlers(C, &window->modalhandlers, handle);
+ UI_popup_handlers_add(C, &window->modalhandlers, handle, 0);
WM_event_add_mousemove(C);
}
#endif
-void uiPupBlockClose(bContext *C, uiBlock *block)
+void UI_popup_block_close(bContext *C, wmWindow *win, uiBlock *block)
{
+ /* if loading new .blend while popup is open, window will be NULL */
if (block->handle) {
- wmWindow *win = CTX_wm_window(C);
-
- /* if loading new .blend while popup is open, window will be NULL */
if (win) {
- UI_remove_popup_handlers(&win->modalhandlers, block->handle);
+ UI_popup_handlers_remove(&win->modalhandlers, block->handle);
ui_popup_block_free(C, block->handle);
}
}
}
-float *ui_block_hsv_get(uiBlock *block)
+ColorPicker *ui_block_colorpicker_create(struct uiBlock *block)
{
- return block->_hsv;
+ ColorPicker *cpicker = MEM_callocN(sizeof(ColorPicker), "color_picker");
+ BLI_addhead(&block->color_pickers.list, cpicker);
+
+ return cpicker;
}
void ui_rgb_to_color_picker_compat_v(const float rgb[3], float r_cp[3])
diff --git a/source/blender/editors/interface/interface_style.c b/source/blender/editors/interface/interface_style.c
index c27789c0fc9..25a187c43ad 100644
--- a/source/blender/editors/interface/interface_style.c
+++ b/source/blender/editors/interface/interface_style.c
@@ -45,9 +45,12 @@
#include "BKE_global.h"
+#include "BIF_gl.h"
#include "BLF_api.h"
-#include "BLF_translation.h"
+#ifdef WITH_INTERNATIONAL
+# include "BLT_translation.h"
+#endif
#include "UI_interface.h"
@@ -61,7 +64,7 @@
/* style + theme + layout-engine = UI */
-/*
+/**
* This is a complete set of layout rules, the 'state' of the Layout
* Engine. Multiple styles are possible, defined via C or Python. Styles
* get a name, and will typically get activated per region type, like
@@ -145,16 +148,38 @@ static uiFont *uifont_to_blfont(int id)
/* *************** draw ************************ */
-void uiStyleFontDrawExt(uiFontStyle *fs, const rcti *rect, const char *str,
- size_t len, float *r_xofs, float *r_yofs)
+void UI_fontstyle_draw_ex(
+ const uiFontStyle *fs, const rcti *rect, const char *str,
+ size_t len, float *r_xofs, float *r_yofs)
{
- float height;
int xofs = 0, yofs;
+ int font_flag = BLF_CLIPPING;
- uiStyleFontSet(fs);
+ UI_fontstyle_set(fs);
- height = BLF_ascender(fs->uifont_id);
- yofs = ceil(0.5f * (BLI_rcti_size_y(rect) - height));
+ /* set the flag */
+ if (fs->shadow) {
+ font_flag |= BLF_SHADOW;
+ BLF_shadow(fs->uifont_id, fs->shadow, fs->shadowcolor, fs->shadowcolor, fs->shadowcolor, fs->shadowalpha);
+ BLF_shadow_offset(fs->uifont_id, fs->shadx, fs->shady);
+ }
+ if (fs->kerning == 1) {
+ font_flag |= BLF_KERNING_DEFAULT;
+ }
+ if (fs->word_wrap == 1) {
+ font_flag |= BLF_WORD_WRAP;
+ }
+
+ BLF_enable(fs->uifont_id, font_flag);
+
+ if (fs->word_wrap == 1) {
+ /* draw from boundbox top */
+ yofs = BLI_rcti_size_y(rect) - BLF_height_max(fs->uifont_id);
+ }
+ else {
+ /* draw from boundbox center */
+ yofs = ceil(0.5f * (BLI_rcti_size_y(rect) - BLF_ascender(fs->uifont_id)));
+ }
if (fs->align == UI_STYLE_TEXT_CENTER) {
xofs = floor(0.5f * (BLI_rcti_size_x(rect) - BLF_width(fs->uifont_id, str, len)));
@@ -169,45 +194,34 @@ void uiStyleFontDrawExt(uiFontStyle *fs, const rcti *rect, const char *str,
/* clip is very strict, so we give it some space */
BLF_clipping(fs->uifont_id, rect->xmin - 2, rect->ymin - 4, rect->xmax + 1, rect->ymax + 4);
- BLF_enable(fs->uifont_id, BLF_CLIPPING);
BLF_position(fs->uifont_id, rect->xmin + xofs, rect->ymin + yofs, 0.0f);
- if (fs->shadow) {
- BLF_enable(fs->uifont_id, BLF_SHADOW);
- BLF_shadow(fs->uifont_id, fs->shadow, fs->shadowcolor, fs->shadowcolor, fs->shadowcolor, fs->shadowalpha);
- BLF_shadow_offset(fs->uifont_id, fs->shadx, fs->shady);
- }
-
- if (fs->kerning == 1)
- BLF_enable(fs->uifont_id, BLF_KERNING_DEFAULT);
-
BLF_draw(fs->uifont_id, str, len);
- BLF_disable(fs->uifont_id, BLF_CLIPPING);
- if (fs->shadow)
- BLF_disable(fs->uifont_id, BLF_SHADOW);
- if (fs->kerning == 1)
- BLF_disable(fs->uifont_id, BLF_KERNING_DEFAULT);
+
+ BLF_disable(fs->uifont_id, font_flag);
*r_xofs = xofs;
*r_yofs = yofs;
}
-void uiStyleFontDraw(uiFontStyle *fs, const rcti *rect, const char *str)
+void UI_fontstyle_draw(const uiFontStyle *fs, const rcti *rect, const char *str)
{
float xofs, yofs;
- uiStyleFontDrawExt(fs, rect, str,
- BLF_DRAW_STR_DUMMY_MAX, &xofs, &yofs);
+
+ UI_fontstyle_draw_ex(
+ fs, rect, str,
+ BLF_DRAW_STR_DUMMY_MAX, &xofs, &yofs);
}
/* drawn same as above, but at 90 degree angle */
-void uiStyleFontDrawRotated(uiFontStyle *fs, const rcti *rect, const char *str)
+void UI_fontstyle_draw_rotated(const uiFontStyle *fs, const rcti *rect, const char *str)
{
float height;
int xofs, yofs;
float angle;
rcti txtrect;
- uiStyleFontSet(fs);
+ UI_fontstyle_set(fs);
height = BLF_ascender(fs->uifont_id);
/* becomes x-offset when rotated */
@@ -218,7 +232,7 @@ void uiStyleFontDrawRotated(uiFontStyle *fs, const rcti *rect, const char *str)
/* rotate counter-clockwise for now (assumes left-to-right language)*/
xofs += height;
yofs = BLF_width(fs->uifont_id, str, BLF_DRAW_STR_DUMMY_MAX) + 5;
- angle = (float)M_PI / 2.0f;
+ angle = M_PI_2;
/* translate rect to vertical */
txtrect.xmin = rect->xmin - BLI_rcti_size_y(rect);
@@ -253,20 +267,84 @@ void uiStyleFontDrawRotated(uiFontStyle *fs, const rcti *rect, const char *str)
BLF_disable(fs->uifont_id, BLF_KERNING_DEFAULT);
}
+/**
+ * Similar to #UI_fontstyle_draw
+ * but ignore alignment, shadow & no clipping rect.
+ *
+ * For drawing on-screen labels.
+ */
+void UI_fontstyle_draw_simple(const uiFontStyle *fs, float x, float y, const char *str)
+{
+ if (fs->kerning == 1)
+ BLF_enable(fs->uifont_id, BLF_KERNING_DEFAULT);
+
+ UI_fontstyle_set(fs);
+ BLF_position(fs->uifont_id, x, y, 0.0f);
+ BLF_draw(fs->uifont_id, str, BLF_DRAW_STR_DUMMY_MAX);
+
+ if (fs->kerning == 1)
+ BLF_disable(fs->uifont_id, BLF_KERNING_DEFAULT);
+}
+
+/**
+ * Same as #UI_fontstyle_draw but draw a colored backdrop.
+ */
+void UI_fontstyle_draw_simple_backdrop(
+ const uiFontStyle *fs, float x, float y, const char *str,
+ const unsigned char fg[4], const unsigned char bg[4])
+{
+ if (fs->kerning == 1)
+ BLF_enable(fs->uifont_id, BLF_KERNING_DEFAULT);
+
+ UI_fontstyle_set(fs);
+
+ {
+ const float width = BLF_width(fs->uifont_id, str, BLF_DRAW_STR_DUMMY_MAX);
+ const float height = BLF_height_max(fs->uifont_id);
+ const float decent = BLF_descender(fs->uifont_id);
+ const float margin = height / 4.0f;
+
+ /* backdrop */
+ glColor4ubv(bg);
+
+ UI_draw_roundbox_corner_set(UI_CNR_ALL | UI_RB_ALPHA);
+ UI_draw_roundbox(
+ x - margin,
+ (y + decent) - margin,
+ x + width + margin,
+ (y + decent) + height + margin,
+ margin);
+
+ glColor4ubv(fg);
+ }
+
+
+ BLF_position(fs->uifont_id, x, y, 0.0f);
+ BLF_draw(fs->uifont_id, str, BLF_DRAW_STR_DUMMY_MAX);
+
+ if (fs->kerning == 1)
+ BLF_disable(fs->uifont_id, BLF_KERNING_DEFAULT);
+}
+
+
/* ************** helpers ************************ */
/* XXX: read a style configure */
-uiStyle *UI_GetStyle(void)
+uiStyle *UI_style_get(void)
{
+#if 0
uiStyle *style = NULL;
/* offset is two struct uiStyle pointers */
- /* style = BLI_findstring(&U.uistyles, "Unifont Style", sizeof(style) * 2) */;
+ style = BLI_findstring(&U.uistyles, "Unifont Style", sizeof(style) * 2);
return (style != NULL) ? style : U.uistyles.first;
+#else
+ return U.uistyles.first;
+#endif
}
/* for drawing, scaled with DPI setting */
-uiStyle *UI_GetStyleDraw(void)
+uiStyle *UI_style_get_dpi(void)
{
- uiStyle *style = UI_GetStyle();
+ uiStyle *style = UI_style_get();
static uiStyle _style;
_style = *style;
@@ -289,41 +367,29 @@ uiStyle *UI_GetStyleDraw(void)
return &_style;
}
-/* temporarily, does widget font */
-int UI_GetStringWidth(const char *str)
+int UI_fontstyle_string_width(const uiFontStyle *fs, const char *str)
{
- uiStyle *style = UI_GetStyle();
- uiFontStyle *fstyle = &style->widget;
int width;
- if (fstyle->kerning == 1) /* for BLF_width */
- BLF_enable(fstyle->uifont_id, BLF_KERNING_DEFAULT);
+ if (fs->kerning == 1) /* for BLF_width */
+ BLF_enable(fs->uifont_id, BLF_KERNING_DEFAULT);
- uiStyleFontSet(fstyle);
- width = BLF_width(fstyle->uifont_id, str, BLF_DRAW_STR_DUMMY_MAX);
+ UI_fontstyle_set(fs);
+ width = BLF_width(fs->uifont_id, str, BLF_DRAW_STR_DUMMY_MAX);
- if (fstyle->kerning == 1)
- BLF_disable(fstyle->uifont_id, BLF_KERNING_DEFAULT);
+ if (fs->kerning == 1)
+ BLF_disable(fs->uifont_id, BLF_KERNING_DEFAULT);
return width;
}
-/* temporarily, does widget font */
-void UI_DrawString(float x, float y, const char *str)
+int UI_fontstyle_height_max(const uiFontStyle *fs)
{
- uiStyle *style = UI_GetStyle();
-
- if (style->widget.kerning == 1)
- BLF_enable(style->widget.uifont_id, BLF_KERNING_DEFAULT);
-
- uiStyleFontSet(&style->widget);
- BLF_position(style->widget.uifont_id, x, y, 0.0f);
- BLF_draw(style->widget.uifont_id, str, BLF_DRAW_STR_DUMMY_MAX);
-
- if (style->widget.kerning == 1)
- BLF_disable(style->widget.uifont_id, BLF_KERNING_DEFAULT);
+ UI_fontstyle_set(fs);
+ return BLF_height_max(fs->uifont_id);
}
+
/* ************** init exit ************************ */
/* called on each startup.blend read */
@@ -396,11 +462,10 @@ void uiStyleInit(void)
if (font->blf_id == -1) {
font->blf_id = BLF_load_mem("default", (unsigned char *)datatoc_bfont_ttf, datatoc_bfont_ttf_size);
}
- else {
- BLF_default_set(font->blf_id);
- }
}
+ BLF_default_set(font->blf_id);
+
if (font->blf_id == -1) {
if (G.debug & G_DEBUG)
printf("%s: error, no fonts available\n", __func__);
@@ -451,7 +516,7 @@ void uiStyleInit(void)
BLF_size(blf_mono_font_render, 12 * U.pixelsize, 72);
}
-void uiStyleFontSet(uiFontStyle *fs)
+void UI_fontstyle_set(const uiFontStyle *fs)
{
uiFont *font = uifont_to_blfont(fs->uifont_id);
diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c
index b0bea42e3bc..1238b883e9a 100644
--- a/source/blender/editors/interface/interface_templates.c
+++ b/source/blender/editors/interface/interface_templates.c
@@ -31,7 +31,6 @@
#include "MEM_guardedalloc.h"
-#include "DNA_dynamicpaint_types.h"
#include "DNA_node_types.h"
#include "DNA_scene_types.h"
#include "DNA_object_types.h"
@@ -48,7 +47,7 @@
#include "BLI_fnmatch.h"
#include "BLF_api.h"
-#include "BLF_translation.h"
+#include "BLT_translation.h"
#include "BKE_colortools.h"
#include "BKE_context.h"
@@ -74,7 +73,6 @@
#include "ED_util.h"
#include "RNA_access.h"
-#include "RNA_enum_types.h"
#include "WM_api.h"
#include "WM_types.h"
@@ -156,9 +154,9 @@ static void id_search_cb(const bContext *C, void *arg_template, const char *str,
char name_ui[MAX_ID_NAME + 1];
name_uiprefix_id(name_ui, id);
- iconid = ui_id_icon_get((bContext *)C, id, template->preview);
+ iconid = ui_id_icon_get(C, id, template->preview);
- if (false == uiSearchItemAdd(items, name_ui, id, iconid))
+ if (false == UI_search_item_add(items, name_ui, id, iconid))
break;
}
}
@@ -183,38 +181,38 @@ static uiBlock *id_search_menu(bContext *C, ARegion *ar, void *arg_litem)
/* get active id for showing first item */
idptr = RNA_property_pointer_get(&template.ptr, template.prop);
- block = uiBeginBlock(C, ar, "_popup", UI_EMBOSS);
- uiBlockSetFlag(block, UI_BLOCK_LOOP | UI_BLOCK_REDRAW | UI_BLOCK_SEARCH_MENU);
+ block = UI_block_begin(C, ar, "_popup", UI_EMBOSS);
+ UI_block_flag_enable(block, UI_BLOCK_LOOP | UI_BLOCK_SEARCH_MENU);
/* preview thumbnails */
if (template.prv_rows > 0 && template.prv_cols > 0) {
int w = 4 * U.widget_unit * template.prv_cols;
- int h = 4 * U.widget_unit * template.prv_rows + U.widget_unit;
+ int h = 5 * U.widget_unit * template.prv_rows;
/* fake button, it holds space for search items */
- uiDefBut(block, LABEL, 0, "", 10, 15, w, h, NULL, 0, 0, 0, 0, NULL);
+ uiDefBut(block, UI_BTYPE_LABEL, 0, "", 10, 26, w, h, NULL, 0, 0, 0, 0, NULL);
but = uiDefSearchBut(block, search, 0, ICON_VIEWZOOM, sizeof(search), 10, 0, w, UI_UNIT_Y,
template.prv_rows, template.prv_cols, "");
- uiButSetSearchFunc(but, id_search_cb, &template, id_search_call_cb, idptr.data);
+ UI_but_func_search_set(but, id_search_cb, &template, id_search_call_cb, idptr.data);
}
/* list view */
else {
- const int searchbox_width = uiSearchBoxWidth();
- const int searchbox_height = uiSearchBoxHeight();
+ const int searchbox_width = UI_searchbox_size_x();
+ const int searchbox_height = UI_searchbox_size_y();
/* fake button, it holds space for search items */
- uiDefBut(block, LABEL, 0, "", 10, 15, searchbox_width, searchbox_height, NULL, 0, 0, 0, 0, NULL);
+ uiDefBut(block, UI_BTYPE_LABEL, 0, "", 10, 15, searchbox_width, searchbox_height, NULL, 0, 0, 0, 0, NULL);
but = uiDefSearchBut(block, search, 0, ICON_VIEWZOOM, sizeof(search), 10, 0, searchbox_width, UI_UNIT_Y - 1, 0, 0, "");
- uiButSetSearchFunc(but, id_search_cb, &template, id_search_call_cb, idptr.data);
+ UI_but_func_search_set(but, id_search_cb, &template, id_search_call_cb, idptr.data);
}
- uiBoundsBlock(block, 0.3f * U.widget_unit);
- uiBlockSetDirection(block, UI_DOWN);
+ UI_block_bounds_set_normal(block, 0.3f * U.widget_unit);
+ UI_block_direction_set(block, UI_DIR_DOWN);
/* give search-field focus */
- uiButSetFocusOnEnter(win, but);
+ UI_but_focus_on_enter_event(win, but);
/* this type of search menu requires undo */
but->flag |= UI_BUT_UNDO;
@@ -225,7 +223,7 @@ static uiBlock *id_search_menu(bContext *C, ARegion *ar, void *arg_litem)
/* This is for browsing and editing the ID-blocks used */
/* for new/open operators */
-void uiIDContextProperty(bContext *C, PointerRNA *ptr, PropertyRNA **prop)
+void UI_context_active_but_prop_get_templateID(bContext *C, PointerRNA *ptr, PropertyRNA **prop)
{
TemplateID *template;
ARegion *ar = CTX_wm_region(C);
@@ -268,15 +266,18 @@ static void template_id_cb(bContext *C, void *arg_litem, void *arg_event)
break;
case UI_ID_OPEN:
case UI_ID_ADD_NEW:
- /* these call uiIDContextProperty */
+ /* these call UI_context_active_but_prop_get_templateID */
break;
case UI_ID_DELETE:
memset(&idptr, 0, sizeof(idptr));
RNA_property_pointer_set(&template->ptr, template->prop, idptr);
RNA_property_update(C, &template->ptr, template->prop);
- if (id && CTX_wm_window(C)->eventstate->shift) /* useful hidden functionality, */
+ if (id && CTX_wm_window(C)->eventstate->shift) {
+ /* only way to force-remove data (on save) */
+ id->flag &= ~LIB_FAKEUSER;
id->us = 0;
+ }
break;
case UI_ID_FAKE_USER:
@@ -352,6 +353,8 @@ static const char *template_id_browse_tip(StructRNA *type)
case ID_BR: return N_("Browse Brush to be linked");
case ID_PA: return N_("Browse Particle Settings to be linked");
case ID_GD: return N_("Browse Grease Pencil Data to be linked");
+ case ID_MC: return N_("Browse Movie Clip to be linked");
+ case ID_MSK: return N_("Browse Mask to be linked");
case ID_PAL: return N_("Browse Palette Data to be linked");
case ID_PC: return N_("Browse Paint Curve Data to be linked");
}
@@ -359,45 +362,23 @@ static const char *template_id_browse_tip(StructRNA *type)
return N_("Browse ID data to be linked");
}
-/* Return a type-based i18n context, needed e.g. by "New" button.
+/**
+ * \return a type-based i18n context, needed e.g. by "New" button.
* In most languages, this adjective takes different form based on gender of type name...
*/
#ifdef WITH_INTERNATIONAL
static const char *template_id_context(StructRNA *type)
{
if (type) {
- switch (RNA_type_to_ID_code(type)) {
- case ID_SCE: return BLF_I18NCONTEXT_ID_SCENE;
- case ID_OB: return BLF_I18NCONTEXT_ID_OBJECT;
- case ID_ME: return BLF_I18NCONTEXT_ID_MESH;
- case ID_CU: return BLF_I18NCONTEXT_ID_CURVE;
- case ID_MB: return BLF_I18NCONTEXT_ID_METABALL;
- case ID_MA: return BLF_I18NCONTEXT_ID_MATERIAL;
- case ID_TE: return BLF_I18NCONTEXT_ID_TEXTURE;
- case ID_IM: return BLF_I18NCONTEXT_ID_IMAGE;
- case ID_LS: return BLF_I18NCONTEXT_ID_FREESTYLELINESTYLE;
- case ID_LT: return BLF_I18NCONTEXT_ID_LATTICE;
- case ID_LA: return BLF_I18NCONTEXT_ID_LAMP;
- case ID_CA: return BLF_I18NCONTEXT_ID_CAMERA;
- case ID_WO: return BLF_I18NCONTEXT_ID_WORLD;
- case ID_SCR: return BLF_I18NCONTEXT_ID_SCREEN;
- case ID_TXT: return BLF_I18NCONTEXT_ID_TEXT;
- case ID_SPK: return BLF_I18NCONTEXT_ID_SPEAKER;
- case ID_SO: return BLF_I18NCONTEXT_ID_SOUND;
- case ID_AR: return BLF_I18NCONTEXT_ID_ARMATURE;
- case ID_AC: return BLF_I18NCONTEXT_ID_ACTION;
- case ID_NT: return BLF_I18NCONTEXT_ID_NODETREE;
- case ID_BR: return BLF_I18NCONTEXT_ID_BRUSH;
- case ID_PA: return BLF_I18NCONTEXT_ID_PARTICLESETTINGS;
- case ID_GD: return BLF_I18NCONTEXT_ID_GPENCIL;
- }
- }
- return BLF_I18NCONTEXT_DEFAULT;
+ return BKE_idcode_to_translation_context(RNA_type_to_ID_code(type));
+ }
+ return BLT_I18NCONTEXT_DEFAULT;
}
#endif
-static void template_ID(bContext *C, uiLayout *layout, TemplateID *template, StructRNA *type, short idcode, int flag,
- const char *newop, const char *openop, const char *unlinkop)
+static void template_ID(
+ bContext *C, uiLayout *layout, TemplateID *template, StructRNA *type, short idcode, int flag,
+ const char *newop, const char *openop, const char *unlinkop)
{
uiBut *but;
uiBlock *block;
@@ -412,7 +393,7 @@ static void template_ID(bContext *C, uiLayout *layout, TemplateID *template, Str
// lb = template->idlb;
block = uiLayoutGetBlock(layout);
- uiBlockBeginAlign(block);
+ UI_block_align_begin(block);
if (idptr.type)
type = idptr.type;
@@ -422,25 +403,24 @@ static void template_ID(bContext *C, uiLayout *layout, TemplateID *template, Str
but = uiDefBlockButN(block, id_search_menu, MEM_dupallocN(template), "", 0, 0, UI_UNIT_X * 6, UI_UNIT_Y * 6,
TIP_(template_id_browse_tip(type)));
- but->icon = id ? ui_id_icon_get(C, id, true) : RNA_struct_ui_icon(type);
- uiButSetFlag(but, UI_HAS_ICON | UI_ICON_PREVIEW);
+ ui_def_but_icon(but, id ? ui_id_icon_get(C, id, true) : RNA_struct_ui_icon(type),
+ UI_HAS_ICON | UI_BUT_ICON_PREVIEW);
if ((idfrom && idfrom->lib) || !editable)
- uiButSetFlag(but, UI_BUT_DISABLED);
+ UI_but_flag_enable(but, UI_BUT_DISABLED);
uiLayoutRow(layout, true);
}
else if (flag & UI_ID_BROWSE) {
but = uiDefBlockButN(block, id_search_menu, MEM_dupallocN(template), "", 0, 0, UI_UNIT_X * 1.6, UI_UNIT_Y,
TIP_(template_id_browse_tip(type)));
- but->icon = RNA_struct_ui_icon(type);
+ ui_def_but_icon(but, RNA_struct_ui_icon(type), UI_HAS_ICON);
/* default dragging of icon for id browse buttons */
- uiButSetDragID(but, id);
- uiButSetFlag(but, UI_HAS_ICON);
- uiButSetDrawFlag(but, UI_BUT_ICON_LEFT);
+ UI_but_drag_set_id(but, id);
+ UI_but_drawflag_enable(but, UI_BUT_ICON_LEFT);
if ((idfrom && idfrom->lib) || !editable)
- uiButSetFlag(but, UI_BUT_DISABLED);
+ UI_but_flag_enable(but, UI_BUT_DISABLED);
}
/* text button with name */
@@ -450,37 +430,39 @@ static void template_ID(bContext *C, uiLayout *layout, TemplateID *template, Str
//text_idbutton(id, name);
name[0] = '\0';
- but = uiDefButR(block, TEX, 0, name, 0, 0, UI_UNIT_X * 6, UI_UNIT_Y,
+ but = uiDefButR(block, UI_BTYPE_TEXT, 0, name, 0, 0, UI_UNIT_X * 6, UI_UNIT_Y,
&idptr, "name", -1, 0, 0, -1, -1, RNA_struct_ui_description(type));
- uiButSetNFunc(but, template_id_cb, MEM_dupallocN(template), SET_INT_IN_POINTER(UI_ID_RENAME));
- if (user_alert) uiButSetFlag(but, UI_BUT_REDALERT);
+ UI_but_funcN_set(but, template_id_cb, MEM_dupallocN(template), SET_INT_IN_POINTER(UI_ID_RENAME));
+ if (user_alert) UI_but_flag_enable(but, UI_BUT_REDALERT);
if (id->lib) {
if (id->flag & LIB_INDIRECT) {
- but = uiDefIconBut(block, BUT, 0, ICON_LIBRARY_DATA_INDIRECT, 0, 0, UI_UNIT_X, UI_UNIT_Y,
+ but = uiDefIconBut(block, UI_BTYPE_BUT, 0, ICON_LIBRARY_DATA_INDIRECT, 0, 0, UI_UNIT_X, UI_UNIT_Y,
NULL, 0, 0, 0, 0, TIP_("Indirect library datablock, cannot change"));
- uiButSetFlag(but, UI_BUT_DISABLED);
+ UI_but_flag_enable(but, UI_BUT_DISABLED);
}
else {
- but = uiDefIconBut(block, BUT, 0, ICON_LIBRARY_DATA_DIRECT, 0, 0, UI_UNIT_X, UI_UNIT_Y,
+ but = uiDefIconBut(block, UI_BTYPE_BUT, 0, ICON_LIBRARY_DATA_DIRECT, 0, 0, UI_UNIT_X, UI_UNIT_Y,
NULL, 0, 0, 0, 0, TIP_("Direct linked library datablock, click to make local"));
if (!id_make_local(id, true /* test */) || (idfrom && idfrom->lib))
- uiButSetFlag(but, UI_BUT_DISABLED);
+ UI_but_flag_enable(but, UI_BUT_DISABLED);
}
- uiButSetNFunc(but, template_id_cb, MEM_dupallocN(template), SET_INT_IN_POINTER(UI_ID_LOCAL));
+ UI_but_funcN_set(but, template_id_cb, MEM_dupallocN(template), SET_INT_IN_POINTER(UI_ID_LOCAL));
}
if (id->us > 1) {
char numstr[32];
+ short numstr_len;
- BLI_snprintf(numstr, sizeof(numstr), "%d", id->us);
+ numstr_len = BLI_snprintf(numstr, sizeof(numstr), "%d", id->us);
- but = uiDefBut(block, BUT, 0, numstr, 0, 0, UI_UNIT_X + ((id->us < 10) ? 0 : 10), UI_UNIT_Y,
- NULL, 0, 0, 0, 0,
+ but = uiDefBut(block, UI_BTYPE_BUT, 0, numstr, 0, 0,
+ numstr_len * 0.2f * UI_UNIT_X + UI_UNIT_X, UI_UNIT_Y, NULL, 0, 0, 0, 0,
TIP_("Display number of users of this data (click to make a single-user copy)"));
+ but->flag |= UI_BUT_UNDO;
- uiButSetNFunc(but, template_id_cb, MEM_dupallocN(template), SET_INT_IN_POINTER(UI_ID_ALONE));
+ UI_but_funcN_set(but, template_id_cb, MEM_dupallocN(template), SET_INT_IN_POINTER(UI_ID_ALONE));
if (/* test only */
(id_copy(id, NULL, true) == false) ||
(idfrom && idfrom->lib) ||
@@ -488,14 +470,14 @@ static void template_ID(bContext *C, uiLayout *layout, TemplateID *template, Str
/* object in editmode - don't change data */
(idfrom && GS(idfrom->name) == ID_OB && (((Object *)idfrom)->mode & OB_MODE_EDIT)))
{
- uiButSetFlag(but, UI_BUT_DISABLED);
+ UI_but_flag_enable(but, UI_BUT_DISABLED);
}
}
- if (user_alert) uiButSetFlag(but, UI_BUT_REDALERT);
+ if (user_alert) UI_but_flag_enable(but, UI_BUT_REDALERT);
if (id->lib == NULL && !(ELEM(GS(id->name), ID_GR, ID_SCE, ID_SCR, ID_TXT, ID_OB))) {
- uiDefButR(block, TOG, 0, "F", 0, 0, UI_UNIT_X, UI_UNIT_Y, &idptr, "use_fake_user", -1, 0, 0, -1, -1, NULL);
+ uiDefButR(block, UI_BTYPE_TOGGLE, 0, "F", 0, 0, UI_UNIT_X, UI_UNIT_Y, &idptr, "use_fake_user", -1, 0, 0, -1, -1, NULL);
}
}
@@ -503,54 +485,54 @@ static void template_ID(bContext *C, uiLayout *layout, TemplateID *template, Str
int w = id ? UI_UNIT_X : (flag & UI_ID_OPEN) ? UI_UNIT_X * 3 : UI_UNIT_X * 6;
/* i18n markup, does nothing! */
- BLF_I18N_MSGID_MULTI_CTXT("New", BLF_I18NCONTEXT_DEFAULT,
- BLF_I18NCONTEXT_ID_SCENE,
- BLF_I18NCONTEXT_ID_OBJECT,
- BLF_I18NCONTEXT_ID_MESH,
- BLF_I18NCONTEXT_ID_CURVE,
- BLF_I18NCONTEXT_ID_METABALL,
- BLF_I18NCONTEXT_ID_MATERIAL,
- BLF_I18NCONTEXT_ID_TEXTURE,
- BLF_I18NCONTEXT_ID_IMAGE,
- BLF_I18NCONTEXT_ID_LATTICE,
- BLF_I18NCONTEXT_ID_LAMP,
- BLF_I18NCONTEXT_ID_CAMERA,
- BLF_I18NCONTEXT_ID_WORLD,
- BLF_I18NCONTEXT_ID_SCREEN,
- BLF_I18NCONTEXT_ID_TEXT,
+ BLT_I18N_MSGID_MULTI_CTXT("New", BLT_I18NCONTEXT_DEFAULT,
+ BLT_I18NCONTEXT_ID_SCENE,
+ BLT_I18NCONTEXT_ID_OBJECT,
+ BLT_I18NCONTEXT_ID_MESH,
+ BLT_I18NCONTEXT_ID_CURVE,
+ BLT_I18NCONTEXT_ID_METABALL,
+ BLT_I18NCONTEXT_ID_MATERIAL,
+ BLT_I18NCONTEXT_ID_TEXTURE,
+ BLT_I18NCONTEXT_ID_IMAGE,
+ BLT_I18NCONTEXT_ID_LATTICE,
+ BLT_I18NCONTEXT_ID_LAMP,
+ BLT_I18NCONTEXT_ID_CAMERA,
+ BLT_I18NCONTEXT_ID_WORLD,
+ BLT_I18NCONTEXT_ID_SCREEN,
+ BLT_I18NCONTEXT_ID_TEXT,
);
- BLF_I18N_MSGID_MULTI_CTXT("New", BLF_I18NCONTEXT_ID_SPEAKER,
- BLF_I18NCONTEXT_ID_SOUND,
- BLF_I18NCONTEXT_ID_ARMATURE,
- BLF_I18NCONTEXT_ID_ACTION,
- BLF_I18NCONTEXT_ID_NODETREE,
- BLF_I18NCONTEXT_ID_BRUSH,
- BLF_I18NCONTEXT_ID_PARTICLESETTINGS,
- BLF_I18NCONTEXT_ID_GPENCIL,
- BLF_I18NCONTEXT_ID_FREESTYLELINESTYLE,
+ BLT_I18N_MSGID_MULTI_CTXT("New", BLT_I18NCONTEXT_ID_SPEAKER,
+ BLT_I18NCONTEXT_ID_SOUND,
+ BLT_I18NCONTEXT_ID_ARMATURE,
+ BLT_I18NCONTEXT_ID_ACTION,
+ BLT_I18NCONTEXT_ID_NODETREE,
+ BLT_I18NCONTEXT_ID_BRUSH,
+ BLT_I18NCONTEXT_ID_PARTICLESETTINGS,
+ BLT_I18NCONTEXT_ID_GPENCIL,
+ BLT_I18NCONTEXT_ID_FREESTYLELINESTYLE,
);
if (newop) {
- but = uiDefIconTextButO(block, BUT, newop, WM_OP_INVOKE_DEFAULT, ICON_ZOOMIN,
+ but = uiDefIconTextButO(block, UI_BTYPE_BUT, newop, WM_OP_INVOKE_DEFAULT, ICON_ZOOMIN,
(id) ? "" : CTX_IFACE_(template_id_context(type), "New"), 0, 0, w, UI_UNIT_Y, NULL);
- uiButSetNFunc(but, template_id_cb, MEM_dupallocN(template), SET_INT_IN_POINTER(UI_ID_ADD_NEW));
+ UI_but_funcN_set(but, template_id_cb, MEM_dupallocN(template), SET_INT_IN_POINTER(UI_ID_ADD_NEW));
}
else {
- but = uiDefIconTextBut(block, BUT, 0, ICON_ZOOMIN, (id) ? "" : CTX_IFACE_(template_id_context(type), "New"),
+ but = uiDefIconTextBut(block, UI_BTYPE_BUT, 0, ICON_ZOOMIN, (id) ? "" : CTX_IFACE_(template_id_context(type), "New"),
0, 0, w, UI_UNIT_Y, NULL, 0, 0, 0, 0, NULL);
- uiButSetNFunc(but, template_id_cb, MEM_dupallocN(template), SET_INT_IN_POINTER(UI_ID_ADD_NEW));
+ UI_but_funcN_set(but, template_id_cb, MEM_dupallocN(template), SET_INT_IN_POINTER(UI_ID_ADD_NEW));
}
if ((idfrom && idfrom->lib) || !editable)
- uiButSetFlag(but, UI_BUT_DISABLED);
+ UI_but_flag_enable(but, UI_BUT_DISABLED);
}
/* Due to space limit in UI - skip the "open" icon for packed data, and allow to unpack.
* Only for images, sound and fonts */
if (id && BKE_pack_check(id)) {
- but = uiDefIconButO(block, BUT, "FILE_OT_unpack_item", WM_OP_INVOKE_REGION_WIN, ICON_PACKAGE, 0, 0,
+ but = uiDefIconButO(block, UI_BTYPE_BUT, "FILE_OT_unpack_item", WM_OP_INVOKE_REGION_WIN, ICON_PACKAGE, 0, 0,
UI_UNIT_X, UI_UNIT_Y, TIP_("Packed File, click to unpack"));
- uiButGetOperatorPtrRNA(but);
+ UI_but_operator_ptr_get(but);
RNA_string_set(but->opptr, "id_name", id->name + 2);
RNA_int_set(but->opptr, "id_type", GS(id->name));
@@ -560,18 +542,18 @@ static void template_ID(bContext *C, uiLayout *layout, TemplateID *template, Str
int w = id ? UI_UNIT_X : (flag & UI_ID_ADD_NEW) ? UI_UNIT_X * 3 : UI_UNIT_X * 6;
if (openop) {
- but = uiDefIconTextButO(block, BUT, openop, WM_OP_INVOKE_DEFAULT, ICON_FILESEL, (id) ? "" : IFACE_("Open"),
+ but = uiDefIconTextButO(block, UI_BTYPE_BUT, openop, WM_OP_INVOKE_DEFAULT, ICON_FILESEL, (id) ? "" : IFACE_("Open"),
0, 0, w, UI_UNIT_Y, NULL);
- uiButSetNFunc(but, template_id_cb, MEM_dupallocN(template), SET_INT_IN_POINTER(UI_ID_OPEN));
+ UI_but_funcN_set(but, template_id_cb, MEM_dupallocN(template), SET_INT_IN_POINTER(UI_ID_OPEN));
}
else {
- but = uiDefIconTextBut(block, BUT, 0, ICON_FILESEL, (id) ? "" : IFACE_("Open"), 0, 0, w, UI_UNIT_Y,
+ but = uiDefIconTextBut(block, UI_BTYPE_BUT, 0, ICON_FILESEL, (id) ? "" : IFACE_("Open"), 0, 0, w, UI_UNIT_Y,
NULL, 0, 0, 0, 0, NULL);
- uiButSetNFunc(but, template_id_cb, MEM_dupallocN(template), SET_INT_IN_POINTER(UI_ID_OPEN));
+ UI_but_funcN_set(but, template_id_cb, MEM_dupallocN(template), SET_INT_IN_POINTER(UI_ID_OPEN));
}
if ((idfrom && idfrom->lib) || !editable)
- uiButSetFlag(but, UI_BUT_DISABLED);
+ UI_but_flag_enable(but, UI_BUT_DISABLED);
}
/* delete button */
@@ -581,26 +563,26 @@ static void template_ID(bContext *C, uiLayout *layout, TemplateID *template, Str
but = NULL;
if (unlinkop) {
- but = uiDefIconButO(block, BUT, unlinkop, WM_OP_INVOKE_REGION_WIN, ICON_X, 0, 0, UI_UNIT_X, UI_UNIT_Y, NULL);
+ but = uiDefIconButO(block, UI_BTYPE_BUT, unlinkop, WM_OP_INVOKE_REGION_WIN, ICON_X, 0, 0, UI_UNIT_X, UI_UNIT_Y, NULL);
/* so we can access the template from operators, font unlinking needs this */
- uiButSetNFunc(but, NULL, MEM_dupallocN(template), NULL);
+ UI_but_funcN_set(but, NULL, MEM_dupallocN(template), NULL);
}
else {
if ((RNA_property_flag(template->prop) & PROP_NEVER_UNLINK) == 0) {
- but = uiDefIconBut(block, BUT, 0, ICON_X, 0, 0, UI_UNIT_X, UI_UNIT_Y, NULL, 0, 0, 0, 0,
+ but = uiDefIconBut(block, UI_BTYPE_BUT, 0, ICON_X, 0, 0, UI_UNIT_X, UI_UNIT_Y, NULL, 0, 0, 0, 0,
TIP_("Unlink datablock "
"(Shift + Click to set users to zero, data will then not be saved)"));
- uiButSetNFunc(but, template_id_cb, MEM_dupallocN(template), SET_INT_IN_POINTER(UI_ID_DELETE));
+ UI_but_funcN_set(but, template_id_cb, MEM_dupallocN(template), SET_INT_IN_POINTER(UI_ID_DELETE));
if (RNA_property_flag(template->prop) & PROP_NEVER_NULL) {
- uiButSetFlag(but, UI_BUT_DISABLED);
+ UI_but_flag_enable(but, UI_BUT_DISABLED);
}
}
}
if (but) {
if ((idfrom && idfrom->lib) || !editable) {
- uiButSetFlag(but, UI_BUT_DISABLED);
+ UI_but_flag_enable(but, UI_BUT_DISABLED);
}
}
}
@@ -608,11 +590,12 @@ static void template_ID(bContext *C, uiLayout *layout, TemplateID *template, Str
if (idcode == ID_TE)
uiTemplateTextureShow(layout, C, &template->ptr, template->prop);
- uiBlockEndAlign(block);
+ UI_block_align_end(block);
}
-static void ui_template_id(uiLayout *layout, bContext *C, PointerRNA *ptr, const char *propname, const char *newop,
- const char *openop, const char *unlinkop, int flag, int prv_rows, int prv_cols)
+static void ui_template_id(
+ uiLayout *layout, bContext *C, PointerRNA *ptr, const char *propname, const char *newop,
+ const char *openop, const char *unlinkop, int flag, int prv_rows, int prv_cols)
{
TemplateID *template;
PropertyRNA *prop;
@@ -652,21 +635,24 @@ static void ui_template_id(uiLayout *layout, bContext *C, PointerRNA *ptr, const
MEM_freeN(template);
}
-void uiTemplateID(uiLayout *layout, bContext *C, PointerRNA *ptr, const char *propname, const char *newop,
- const char *openop, const char *unlinkop)
+void uiTemplateID(
+ uiLayout *layout, bContext *C, PointerRNA *ptr, const char *propname, const char *newop,
+ const char *openop, const char *unlinkop)
{
ui_template_id(layout, C, ptr, propname, newop, openop, unlinkop,
UI_ID_BROWSE | UI_ID_RENAME | UI_ID_DELETE, 0, 0);
}
-void uiTemplateIDBrowse(uiLayout *layout, bContext *C, PointerRNA *ptr, const char *propname, const char *newop,
- const char *openop, const char *unlinkop)
+void uiTemplateIDBrowse(
+ uiLayout *layout, bContext *C, PointerRNA *ptr, const char *propname, const char *newop,
+ const char *openop, const char *unlinkop)
{
ui_template_id(layout, C, ptr, propname, newop, openop, unlinkop, UI_ID_BROWSE | UI_ID_RENAME, 0, 0);
}
-void uiTemplateIDPreview(uiLayout *layout, bContext *C, PointerRNA *ptr, const char *propname, const char *newop,
- const char *openop, const char *unlinkop, int rows, int cols)
+void uiTemplateIDPreview(
+ uiLayout *layout, bContext *C, PointerRNA *ptr, const char *propname, const char *newop,
+ const char *openop, const char *unlinkop, int rows, int cols)
{
ui_template_id(layout, C, ptr, propname, newop, openop, unlinkop,
UI_ID_BROWSE | UI_ID_RENAME | UI_ID_DELETE | UI_ID_PREVIEWS, rows, cols);
@@ -674,13 +660,15 @@ void uiTemplateIDPreview(uiLayout *layout, bContext *C, PointerRNA *ptr, const c
/************************ ID Chooser Template ***************************/
-/* This is for selecting the type of ID-block to use, and then from the relevant type choosing the block to use
+/**
+ * This is for selecting the type of ID-block to use, and then from the relevant type choosing the block to use
*
* - propname: property identifier for property that ID-pointer gets stored to
* - proptypename: property identifier for property used to determine the type of ID-pointer that can be used
*/
-void uiTemplateAnyID(uiLayout *layout, PointerRNA *ptr, const char *propname, const char *proptypename,
- const char *text)
+void uiTemplateAnyID(
+ uiLayout *layout, PointerRNA *ptr, const char *propname, const char *proptypename,
+ const char *text)
{
PropertyRNA *propID, *propType;
uiLayout *split, *row, *sub;
@@ -733,7 +721,8 @@ void uiTemplateAnyID(uiLayout *layout, PointerRNA *ptr, const char *propname, co
/* ---------- */
-/* This is creating/editing RNA-Paths
+/**
+ * This is creating/editing RNA-Paths
*
* - ptr: struct which holds the path property
* - propname: property identifier for property that path gets stored to
@@ -814,10 +803,11 @@ static int modifier_is_simulation(ModifierData *md)
}
}
-static uiLayout *draw_modifier(uiLayout *layout, Scene *scene, Object *ob,
- ModifierData *md, int index, int cageIndex, int lastCageIndex)
+static uiLayout *draw_modifier(
+ uiLayout *layout, Scene *scene, Object *ob,
+ ModifierData *md, int index, int cageIndex, int lastCageIndex)
{
- ModifierTypeInfo *mti = modifierType_getInfo(md->type);
+ const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
PointerRNA ptr;
uiBut *but;
uiBlock *block;
@@ -842,26 +832,27 @@ static uiLayout *draw_modifier(uiLayout *layout, Scene *scene, Object *ob,
/* VIRTUAL MODIFIER */
/* XXX this is not used now, since these cannot be accessed via RNA */
BLI_snprintf(str, sizeof(str), IFACE_("%s parent deform"), md->name);
- uiDefBut(block, LABEL, 0, str, 0, 0, 185, UI_UNIT_Y, NULL, 0.0, 0.0, 0.0, 0.0, TIP_("Modifier name"));
+ uiDefBut(block, UI_BTYPE_LABEL, 0, str, 0, 0, 185, UI_UNIT_Y, NULL, 0.0, 0.0, 0.0, 0.0, TIP_("Modifier name"));
- but = uiDefBut(block, BUT, 0, IFACE_("Make Real"), 0, 0, 80, 16, NULL, 0.0, 0.0, 0.0, 0.0,
+ but = uiDefBut(block, UI_BTYPE_BUT, 0, IFACE_("Make Real"), 0, 0, 80, 16, NULL, 0.0, 0.0, 0.0, 0.0,
TIP_("Convert virtual modifier to a real modifier"));
- uiButSetFunc(but, modifiers_convertToReal, ob, md);
+ UI_but_func_set(but, modifiers_convertToReal, ob, md);
}
else {
/* REAL MODIFIER */
row = uiLayoutRow(box, false);
block = uiLayoutGetBlock(row);
- uiBlockSetEmboss(block, UI_EMBOSSN);
+ UI_block_emboss_set(block, UI_EMBOSS_NONE);
/* Open/Close ................................. */
uiItemR(row, &ptr, "show_expanded", 0, "", ICON_NONE);
/* modifier-type icon */
uiItemL(row, "", RNA_struct_ui_icon(ptr.type));
- uiBlockSetEmboss(block, UI_EMBOSS);
+ UI_block_emboss_set(block, UI_EMBOSS);
/* modifier name */
+ md->scene = scene;
if (mti->isDisabled && mti->isDisabled(md, 0)) {
uiLayoutSetRedAlert(row, true);
}
@@ -869,7 +860,7 @@ static uiLayout *draw_modifier(uiLayout *layout, Scene *scene, Object *ob,
uiLayoutSetRedAlert(row, false);
/* mode enabling buttons */
- uiBlockBeginAlign(block);
+ UI_block_align_begin(block);
/* Softbody not allowed in this situation, enforce! */
if (((md->type != eModifierType_Softbody && md->type != eModifierType_Collision) || !(ob->pd && ob->pd->deflect)) &&
(md->type != eModifierType_Surface) )
@@ -900,10 +891,10 @@ static uiLayout *draw_modifier(uiLayout *layout, Scene *scene, Object *ob,
if (ELEM(md->type, eModifierType_Hook, eModifierType_Softbody, eModifierType_MeshDeform)) {
/* add disabled pre-tessellated button, so users could have
* message for this modifiers */
- but = uiDefIconButBitI(block, TOG, eModifierMode_ApplyOnSpline, 0, ICON_SURFACE_DATA, 0, 0,
+ but = uiDefIconButBitI(block, UI_BTYPE_TOGGLE, eModifierMode_ApplyOnSpline, 0, ICON_SURFACE_DATA, 0, 0,
UI_UNIT_X - 2, UI_UNIT_Y, &md->mode, 0.0, 0.0, 0.0, 0.0,
TIP_("This modifier can only be applied on splines' points"));
- uiButSetFlag(but, UI_BUT_DISABLED);
+ UI_but_flag_enable(but, UI_BUT_DISABLED);
}
else if (mti->type != eModifierTypeType_Constructive) {
/* constructive modifiers tessellates curve before applying */
@@ -911,23 +902,29 @@ static uiLayout *draw_modifier(uiLayout *layout, Scene *scene, Object *ob,
}
}
- uiBlockEndAlign(block);
+ UI_block_align_end(block);
/* Up/Down + Delete ........................... */
- uiBlockBeginAlign(block);
+ UI_block_align_begin(block);
uiItemO(row, "", ICON_TRIA_UP, "OBJECT_OT_modifier_move_up");
uiItemO(row, "", ICON_TRIA_DOWN, "OBJECT_OT_modifier_move_down");
- uiBlockEndAlign(block);
+ UI_block_align_end(block);
- uiBlockSetEmboss(block, UI_EMBOSSN);
+ UI_block_emboss_set(block, UI_EMBOSS_NONE);
/* When Modifier is a simulation, show button to switch to context rather than the delete button. */
- if (modifier_can_delete(md) && (!modifier_is_simulation(md) || STREQ(scene->r.engine, "BLENDER_GAME")))
+ if (modifier_can_delete(md) &&
+ (!modifier_is_simulation(md) ||
+ STREQ(scene->r.engine, RE_engine_id_BLENDER_GAME)))
+ {
uiItemO(row, "", ICON_X, "OBJECT_OT_modifier_remove");
- else if (modifier_is_simulation(md) == 1)
+ }
+ else if (modifier_is_simulation(md) == 1) {
uiItemStringO(row, "", ICON_BUTS, "WM_OT_properties_context_change", "context", "PHYSICS");
- else if (modifier_is_simulation(md) == 2)
+ }
+ else if (modifier_is_simulation(md) == 2) {
uiItemStringO(row, "", ICON_BUTS, "WM_OT_properties_context_change", "context", "PARTICLES");
- uiBlockSetEmboss(block, UI_EMBOSS);
+ }
+ UI_block_emboss_set(block, UI_EMBOSS);
}
@@ -939,39 +936,39 @@ static uiLayout *draw_modifier(uiLayout *layout, Scene *scene, Object *ob,
if (!ELEM(md->type, eModifierType_Collision, eModifierType_Surface)) {
/* only here obdata, the rest of modifiers is ob level */
- uiBlockSetButLock(block, BKE_object_obdata_is_libdata(ob), ERROR_LIBDATA_MESSAGE);
+ UI_block_lock_set(block, BKE_object_obdata_is_libdata(ob), ERROR_LIBDATA_MESSAGE);
if (md->type == eModifierType_ParticleSystem) {
ParticleSystem *psys = ((ParticleSystemModifierData *)md)->psys;
if (!(ob->mode & OB_MODE_PARTICLE_EDIT)) {
if (ELEM(psys->part->ren_as, PART_DRAW_GR, PART_DRAW_OB))
- uiItemO(row, CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Convert"), ICON_NONE,
+ uiItemO(row, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Convert"), ICON_NONE,
"OBJECT_OT_duplicates_make_real");
else if (psys->part->ren_as == PART_DRAW_PATH && psys->pathcache)
- uiItemO(row, CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Convert"), ICON_NONE,
+ uiItemO(row, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Convert"), ICON_NONE,
"OBJECT_OT_modifier_convert");
}
}
else {
uiLayoutSetOperatorContext(row, WM_OP_INVOKE_DEFAULT);
- uiItemEnumO(row, "OBJECT_OT_modifier_apply", CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Apply"),
+ uiItemEnumO(row, "OBJECT_OT_modifier_apply", CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Apply"),
0, "apply_as", MODIFIER_APPLY_DATA);
if (modifier_isSameTopology(md) && !modifier_isNonGeometrical(md)) {
uiItemEnumO(row, "OBJECT_OT_modifier_apply",
- CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Apply as Shape Key"),
+ CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Apply as Shape Key"),
0, "apply_as", MODIFIER_APPLY_SHAPE);
}
}
- uiBlockClearButLock(block);
- uiBlockSetButLock(block, ob && ob->id.lib, ERROR_LIBDATA_MESSAGE);
+ UI_block_lock_clear(block);
+ UI_block_lock_set(block, ob && ob->id.lib, ERROR_LIBDATA_MESSAGE);
if (!ELEM(md->type, eModifierType_Fluidsim, eModifierType_Softbody, eModifierType_ParticleSystem,
eModifierType_Cloth, eModifierType_Smoke))
{
- uiItemO(row, CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Copy"), ICON_NONE,
+ uiItemO(row, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Copy"), ICON_NONE,
"OBJECT_OT_modifier_copy");
}
}
@@ -1013,7 +1010,7 @@ uiLayout *uiTemplateModifier(uiLayout *layout, bContext *C, PointerRNA *ptr)
return NULL;
}
- uiBlockSetButLock(uiLayoutGetBlock(layout), (ob && ob->id.lib), ERROR_LIBDATA_MESSAGE);
+ UI_block_lock_set(uiLayoutGetBlock(layout), (ob && ob->id.lib), ERROR_LIBDATA_MESSAGE);
/* find modifier and draw it */
cageIndex = modifiers_getCageIndex(scene, ob, &lastCageIndex, 0);
@@ -1052,7 +1049,8 @@ static void do_constraint_panels(bContext *C, void *ob_pt, int event)
case B_CONSTRAINT_CHANGETARGET:
{
Main *bmain = CTX_data_main(C);
- if (ob->pose) ob->pose->flag |= POSE_RECALC; /* checks & sorts pose channels */
+ if (ob->pose)
+ BKE_pose_tag_recalc(bmain, ob->pose); /* checks & sorts pose channels */
DAG_relations_tag_update(bmain);
break;
}
@@ -1082,7 +1080,7 @@ static void constraint_active_func(bContext *UNUSED(C), void *ob_v, void *con_v)
static uiLayout *draw_constraint(uiLayout *layout, Object *ob, bConstraint *con)
{
bPoseChannel *pchan = BKE_pose_channel_active(ob);
- bConstraintTypeInfo *cti;
+ const bConstraintTypeInfo *cti;
uiBlock *block;
uiLayout *result = NULL, *col, *box, *row;
PointerRNA ptr;
@@ -1107,8 +1105,8 @@ static uiLayout *draw_constraint(uiLayout *layout, Object *ob, bConstraint *con)
/* unless button has own callback, it adds this callback to button */
block = uiLayoutGetBlock(layout);
- uiBlockSetHandleFunc(block, do_constraint_panels, ob);
- uiBlockSetFunc(block, constraint_active_func, ob, con);
+ UI_block_func_handle_set(block, do_constraint_panels, ob);
+ UI_block_func_set(block, constraint_active_func, ob, con);
RNA_pointer_create(&ob->id, &RNA_Constraint, con, &ptr);
@@ -1122,12 +1120,12 @@ static uiLayout *draw_constraint(uiLayout *layout, Object *ob, bConstraint *con)
/* Draw constraint header */
/* open/close */
- uiBlockSetEmboss(block, UI_EMBOSSN);
+ UI_block_emboss_set(block, UI_EMBOSS_NONE);
uiItemR(row, &ptr, "show_expanded", UI_ITEM_R_ICON_ONLY, "", ICON_NONE);
- uiBlockSetEmboss(block, UI_EMBOSS);
+ UI_block_emboss_set(block, UI_EMBOSS);
/* name */
- uiDefBut(block, LABEL, B_CONSTRAINT_TEST, typestr,
+ uiDefBut(block, UI_BTYPE_LABEL, B_CONSTRAINT_TEST, typestr,
xco + 0.5f * UI_UNIT_X, yco, 5 * UI_UNIT_X, 0.9f * UI_UNIT_Y, NULL, 0.0, 0.0, 0.0, 0.0, "");
if (con->flag & CONSTRAINT_DISABLE)
@@ -1143,15 +1141,15 @@ static uiLayout *draw_constraint(uiLayout *layout, Object *ob, bConstraint *con)
/* proxy-protected constraints cannot be edited, so hide up/down + close buttons */
if (proxy_protected) {
- uiBlockSetEmboss(block, UI_EMBOSSN);
+ UI_block_emboss_set(block, UI_EMBOSS_NONE);
/* draw a ghost icon (for proxy) and also a lock beside it, to show that constraint is "proxy locked" */
- uiDefIconBut(block, BUT, B_CONSTRAINT_TEST, ICON_GHOST, xco + 12.2f * UI_UNIT_X, yco, 0.95f * UI_UNIT_X, 0.95f * UI_UNIT_Y,
+ uiDefIconBut(block, UI_BTYPE_BUT, B_CONSTRAINT_TEST, ICON_GHOST, xco + 12.2f * UI_UNIT_X, yco, 0.95f * UI_UNIT_X, 0.95f * UI_UNIT_Y,
NULL, 0.0, 0.0, 0.0, 0.0, TIP_("Proxy Protected"));
- uiDefIconBut(block, BUT, B_CONSTRAINT_TEST, ICON_LOCKED, xco + 13.1f * UI_UNIT_X, yco, 0.95f * UI_UNIT_X, 0.95f * UI_UNIT_Y,
+ uiDefIconBut(block, UI_BTYPE_BUT, B_CONSTRAINT_TEST, ICON_LOCKED, xco + 13.1f * UI_UNIT_X, yco, 0.95f * UI_UNIT_X, 0.95f * UI_UNIT_Y,
NULL, 0.0, 0.0, 0.0, 0.0, TIP_("Proxy Protected"));
- uiBlockSetEmboss(block, UI_EMBOSS);
+ UI_block_emboss_set(block, UI_EMBOSS);
}
else {
short prev_proxylock, show_upbut, show_downbut;
@@ -1177,33 +1175,33 @@ static uiLayout *draw_constraint(uiLayout *layout, Object *ob, bConstraint *con)
show_downbut = (con->next) ? 1 : 0;
/* enabled */
- uiBlockSetEmboss(block, UI_EMBOSSN);
+ UI_block_emboss_set(block, UI_EMBOSS_NONE);
uiItemR(row, &ptr, "mute", 0, "",
(con->flag & CONSTRAINT_OFF) ? ICON_RESTRICT_VIEW_ON : ICON_RESTRICT_VIEW_OFF);
- uiBlockSetEmboss(block, UI_EMBOSS);
+ UI_block_emboss_set(block, UI_EMBOSS);
uiLayoutSetOperatorContext(row, WM_OP_INVOKE_DEFAULT);
/* up/down */
if (show_upbut || show_downbut) {
- uiBlockBeginAlign(block);
+ UI_block_align_begin(block);
if (show_upbut)
uiItemO(row, "", ICON_TRIA_UP, "CONSTRAINT_OT_move_up");
if (show_downbut)
uiItemO(row, "", ICON_TRIA_DOWN, "CONSTRAINT_OT_move_down");
- uiBlockEndAlign(block);
+ UI_block_align_end(block);
}
/* Close 'button' - emboss calls here disable drawing of 'button' behind X */
- uiBlockSetEmboss(block, UI_EMBOSSN);
+ UI_block_emboss_set(block, UI_EMBOSS_NONE);
uiItemO(row, "", ICON_X, "CONSTRAINT_OT_delete");
- uiBlockSetEmboss(block, UI_EMBOSS);
+ UI_block_emboss_set(block, UI_EMBOSS);
}
/* Set but-locks for protected settings (magic numbers are used here!) */
if (proxy_protected)
- uiBlockSetButLock(block, true, IFACE_("Cannot edit Proxy-Protected Constraint"));
+ UI_block_lock_set(block, true, IFACE_("Cannot edit Proxy-Protected Constraint"));
/* Draw constraint data */
if ((con->flag & CONSTRAINT_EXPAND) == 0) {
@@ -1216,7 +1214,7 @@ static uiLayout *draw_constraint(uiLayout *layout, Object *ob, bConstraint *con)
}
/* clear any locks set up for proxies/lib-linking */
- uiBlockClearButLock(block);
+ UI_block_lock_clear(block);
return result;
}
@@ -1240,7 +1238,7 @@ uiLayout *uiTemplateConstraint(uiLayout *layout, PointerRNA *ptr)
return NULL;
}
- uiBlockSetButLock(uiLayoutGetBlock(layout), (ob && ob->id.lib), ERROR_LIBDATA_MESSAGE);
+ UI_block_lock_set(uiLayoutGetBlock(layout), (ob && ob->id.lib), ERROR_LIBDATA_MESSAGE);
/* hrms, the temporal constraint should not draw! */
if (con->type == CONSTRAINT_TYPE_KINEMATIC) {
@@ -1270,8 +1268,9 @@ static void do_preview_buttons(bContext *C, void *arg, int event)
}
}
-void uiTemplatePreview(uiLayout *layout, bContext *C, ID *id, int show_buttons, ID *parent, MTex *slot,
- const char *preview_id)
+void uiTemplatePreview(
+ uiLayout *layout, bContext *C, ID *id, int show_buttons, ID *parent, MTex *slot,
+ const char *preview_id)
{
uiLayout *row, *col;
uiBlock *block;
@@ -1345,11 +1344,11 @@ void uiTemplatePreview(uiLayout *layout, bContext *C, ID *id, int show_buttons,
uiLayoutSetKeepAspect(col, true);
/* add preview */
- uiDefBut(block, BUT_EXTRA, 0, "", 0, 0, UI_UNIT_X * 10, ui_preview->height, pid, 0.0, 0.0, 0, 0, "");
- uiBlockSetDrawExtraFunc(block, ED_preview_draw, pparent, slot);
- uiBlockSetHandleFunc(block, do_preview_buttons, NULL);
+ uiDefBut(block, UI_BTYPE_EXTRA, 0, "", 0, 0, UI_UNIT_X * 10, ui_preview->height, pid, 0.0, 0.0, 0, 0, "");
+ UI_but_func_drawextra_set(block, ED_preview_draw, pparent, slot);
+ UI_block_func_handle_set(block, do_preview_buttons, NULL);
- uiDefIconButS(block, GRIP, 0, ICON_GRIP, 0, 0, UI_UNIT_X * 10, (short)(UI_UNIT_Y * 0.3f), &ui_preview->height,
+ uiDefIconButS(block, UI_BTYPE_GRIP, 0, ICON_GRIP, 0, 0, UI_UNIT_X * 10, (short)(UI_UNIT_Y * 0.3f), &ui_preview->height,
UI_UNIT_Y, UI_UNIT_Y * 50.0f, 0.0f, 0.0f, "");
/* add buttons */
@@ -1371,25 +1370,25 @@ void uiTemplatePreview(uiLayout *layout, bContext *C, ID *id, int show_buttons,
RNA_pointer_create(id, &RNA_Texture, tex, &texture_ptr);
uiLayoutRow(layout, true);
- uiDefButS(block, ROW, B_MATPRV, IFACE_("Texture"), 0, 0, UI_UNIT_X * 10, UI_UNIT_Y,
+ uiDefButS(block, UI_BTYPE_ROW, B_MATPRV, IFACE_("Texture"), 0, 0, UI_UNIT_X * 10, UI_UNIT_Y,
pr_texture, 10, TEX_PR_TEXTURE, 0, 0, "");
if (GS(parent->name) == ID_MA) {
- uiDefButS(block, ROW, B_MATPRV, IFACE_("Material"), 0, 0, UI_UNIT_X * 10, UI_UNIT_Y,
+ uiDefButS(block, UI_BTYPE_ROW, B_MATPRV, IFACE_("Material"), 0, 0, UI_UNIT_X * 10, UI_UNIT_Y,
pr_texture, 10, TEX_PR_OTHER, 0, 0, "");
}
else if (GS(parent->name) == ID_LA) {
- uiDefButS(block, ROW, B_MATPRV, IFACE_("Lamp"), 0, 0, UI_UNIT_X * 10, UI_UNIT_Y,
+ uiDefButS(block, UI_BTYPE_ROW, B_MATPRV, IFACE_("Lamp"), 0, 0, UI_UNIT_X * 10, UI_UNIT_Y,
pr_texture, 10, TEX_PR_OTHER, 0, 0, "");
}
else if (GS(parent->name) == ID_WO) {
- uiDefButS(block, ROW, B_MATPRV, IFACE_("World"), 0, 0, UI_UNIT_X * 10, UI_UNIT_Y,
+ uiDefButS(block, UI_BTYPE_ROW, B_MATPRV, IFACE_("World"), 0, 0, UI_UNIT_X * 10, UI_UNIT_Y,
pr_texture, 10, TEX_PR_OTHER, 0, 0, "");
}
else if (GS(parent->name) == ID_LS) {
- uiDefButS(block, ROW, B_MATPRV, IFACE_("Line Style"), 0, 0, UI_UNIT_X * 10, UI_UNIT_Y,
+ uiDefButS(block, UI_BTYPE_ROW, B_MATPRV, IFACE_("Line Style"), 0, 0, UI_UNIT_X * 10, UI_UNIT_Y,
pr_texture, 10, TEX_PR_OTHER, 0, 0, "");
}
- uiDefButS(block, ROW, B_MATPRV, IFACE_("Both"), 0, 0, UI_UNIT_X * 10, UI_UNIT_Y,
+ uiDefButS(block, UI_BTYPE_ROW, B_MATPRV, IFACE_("Both"), 0, 0, UI_UNIT_X * 10, UI_UNIT_Y,
pr_texture, 10, TEX_PR_BOTH, 0, 0, "");
/* Alpha button for texture preview */
@@ -1479,8 +1478,9 @@ static void colorband_update_cb(bContext *UNUSED(C), void *bt_v, void *coba_v)
bt->rnapoin.data = coba->data + coba->cur;
}
-static void colorband_buttons_layout(uiLayout *layout, uiBlock *block, ColorBand *coba, const rctf *butr,
- RNAUpdateCb *cb, int expand)
+static void colorband_buttons_layout(
+ uiLayout *layout, uiBlock *block, ColorBand *coba, const rctf *butr,
+ RNAUpdateCb *cb, int expand)
{
uiLayout *row, *split, *subsplit;
uiBut *bt;
@@ -1493,28 +1493,28 @@ static void colorband_buttons_layout(uiLayout *layout, uiBlock *block, ColorBand
split = uiLayoutSplit(layout, 0.4f, false);
- uiBlockSetEmboss(block, UI_EMBOSSN);
- uiBlockBeginAlign(block);
+ UI_block_emboss_set(block, UI_EMBOSS_NONE);
+ UI_block_align_begin(block);
row = uiLayoutRow(split, false);
- bt = uiDefIconTextBut(block, BUT, 0, ICON_ZOOMIN, "", 0, 0, 2.0f * unit, UI_UNIT_Y, NULL,
+ bt = uiDefIconTextBut(block, UI_BTYPE_BUT, 0, ICON_ZOOMIN, "", 0, 0, 2.0f * unit, UI_UNIT_Y, NULL,
0, 0, 0, 0, TIP_("Add a new color stop to the colorband"));
- uiButSetNFunc(bt, colorband_add_cb, MEM_dupallocN(cb), coba);
+ UI_but_funcN_set(bt, colorband_add_cb, MEM_dupallocN(cb), coba);
- bt = uiDefIconTextBut(block, BUT, 0, ICON_ZOOMOUT, "", xs + 2.0f * unit, ys + UI_UNIT_Y, 2.0f * unit, UI_UNIT_Y,
+ bt = uiDefIconTextBut(block, UI_BTYPE_BUT, 0, ICON_ZOOMOUT, "", xs + 2.0f * unit, ys + UI_UNIT_Y, 2.0f * unit, UI_UNIT_Y,
NULL, 0, 0, 0, 0, TIP_("Delete the active position"));
- uiButSetNFunc(bt, colorband_del_cb, MEM_dupallocN(cb), coba);
+ UI_but_funcN_set(bt, colorband_del_cb, MEM_dupallocN(cb), coba);
- bt = uiDefIconTextBut(block, BUT, 0, ICON_ARROW_LEFTRIGHT, "", xs + 4.0f * unit, ys + UI_UNIT_Y, 2.0f * unit, UI_UNIT_Y,
+ bt = uiDefIconTextBut(block, UI_BTYPE_BUT, 0, ICON_ARROW_LEFTRIGHT, "", xs + 4.0f * unit, ys + UI_UNIT_Y, 2.0f * unit, UI_UNIT_Y,
NULL, 0, 0, 0, 0, TIP_("Flip the color ramp"));
- uiButSetNFunc(bt, colorband_flip_cb, MEM_dupallocN(cb), coba);
- uiBlockEndAlign(block);
- uiBlockSetEmboss(block, UI_EMBOSS);
+ UI_but_funcN_set(bt, colorband_flip_cb, MEM_dupallocN(cb), coba);
+ UI_block_align_end(block);
+ UI_block_emboss_set(block, UI_EMBOSS);
row = uiLayoutRow(split, false);
- uiBlockBeginAlign(block);
+ UI_block_align_begin(block);
uiItemR(row, &ptr, "color_mode", 0, "", ICON_NONE);
if (ELEM(coba->color_mode, COLBAND_BLEND_HSV, COLBAND_BLEND_HSL)) {
uiItemR(row, &ptr, "hue_interpolation", 0, "", ICON_NONE);
@@ -1522,12 +1522,12 @@ static void colorband_buttons_layout(uiLayout *layout, uiBlock *block, ColorBand
else { /* COLBAND_BLEND_RGB */
uiItemR(row, &ptr, "interpolation", 0, "", ICON_NONE);
}
- uiBlockEndAlign(block);
+ UI_block_align_end(block);
row = uiLayoutRow(layout, false);
- bt = uiDefBut(block, BUT_COLORBAND, 0, "", xs, ys, BLI_rctf_size_x(butr), UI_UNIT_Y, coba, 0, 0, 0, 0, "");
- uiButSetNFunc(bt, rna_update_cb, MEM_dupallocN(cb), NULL);
+ bt = uiDefBut(block, UI_BTYPE_COLORBAND, 0, "", xs, ys, BLI_rctf_size_x(butr), UI_UNIT_Y, coba, 0, 0, 0, 0, "");
+ UI_but_funcN_set(bt, rna_update_cb, MEM_dupallocN(cb), NULL);
row = uiLayoutRow(layout, false);
@@ -1540,34 +1540,36 @@ static void colorband_buttons_layout(uiLayout *layout, uiBlock *block, ColorBand
split = uiLayoutSplit(layout, 0.3f, false);
row = uiLayoutRow(split, false);
- uiDefButS(block, NUM, 0, "", 0, 0, 5.0f * UI_UNIT_X, UI_UNIT_Y, &coba->cur, 0.0, (float)(MAX2(0, coba->tot - 1)),
+ uiDefButS(block, UI_BTYPE_NUM, 0, "", 0, 0, 5.0f * UI_UNIT_X, UI_UNIT_Y, &coba->cur, 0.0, (float)(MAX2(0, coba->tot - 1)),
0, 0, TIP_("Choose active color stop"));
row = uiLayoutRow(split, false);
uiItemR(row, &ptr, "position", 0, IFACE_("Pos"), ICON_NONE);
bt = block->buttons.last;
- uiButSetFunc(bt, colorband_update_cb, bt, coba);
+ bt->a1 = 1.0f; /* gives a bit more precision for modifying position */
+ UI_but_func_set(bt, colorband_update_cb, bt, coba);
row = uiLayoutRow(layout, false);
uiItemR(row, &ptr, "color", 0, "", ICON_NONE);
bt = block->buttons.last;
- uiButSetNFunc(bt, rna_update_cb, MEM_dupallocN(cb), NULL);
+ UI_but_funcN_set(bt, rna_update_cb, MEM_dupallocN(cb), NULL);
}
else {
split = uiLayoutSplit(layout, 0.5f, false);
subsplit = uiLayoutSplit(split, 0.35f, false);
row = uiLayoutRow(subsplit, false);
- uiDefButS(block, NUM, 0, "", 0, 0, 5.0f * UI_UNIT_X, UI_UNIT_Y, &coba->cur, 0.0, (float)(MAX2(0, coba->tot - 1)),
+ uiDefButS(block, UI_BTYPE_NUM, 0, "", 0, 0, 5.0f * UI_UNIT_X, UI_UNIT_Y, &coba->cur, 0.0, (float)(MAX2(0, coba->tot - 1)),
0, 0, TIP_("Choose active color stop"));
row = uiLayoutRow(subsplit, false);
uiItemR(row, &ptr, "position", UI_ITEM_R_SLIDER, IFACE_("Pos"), ICON_NONE);
bt = block->buttons.last;
- uiButSetFunc(bt, colorband_update_cb, bt, coba);
+ bt->a1 = 1.0f; /* gives a bit more precision for modifying position */
+ UI_but_func_set(bt, colorband_update_cb, bt, coba);
row = uiLayoutRow(split, false);
uiItemR(row, &ptr, "color", 0, "", ICON_NONE);
bt = block->buttons.last;
- uiButSetNFunc(bt, rna_update_cb, MEM_dupallocN(cb), NULL);
+ UI_but_funcN_set(bt, rna_update_cb, MEM_dupallocN(cb), NULL);
}
}
}
@@ -1598,55 +1600,69 @@ void uiTemplateColorRamp(uiLayout *layout, PointerRNA *ptr, const char *propname
block = uiLayoutAbsoluteBlock(layout);
id = cptr.id.data;
- uiBlockSetButLock(block, (id && id->lib), ERROR_LIBDATA_MESSAGE);
+ UI_block_lock_set(block, (id && id->lib), ERROR_LIBDATA_MESSAGE);
colorband_buttons_layout(layout, block, cptr.data, &rect, cb, expand);
- uiBlockClearButLock(block);
+ UI_block_lock_clear(block);
MEM_freeN(cb);
}
/********************* Icon viewer Template ************************/
+typedef struct IconViewMenuArgs {
+ PointerRNA ptr;
+ PropertyRNA *prop;
+ bool show_labels;
+ float icon_scale;
+} IconViewMenuArgs;
/* ID Search browse menu, open */
-static uiBlock *icon_view_menu(bContext *C, ARegion *ar, void *arg_litem)
+static uiBlock *ui_icon_view_menu_cb(bContext *C, ARegion *ar, void *arg_litem)
{
- static RNAUpdateCb cb;
+ static IconViewMenuArgs args;
uiBlock *block;
uiBut *but;
- int icon;
+ int icon, value;
EnumPropertyItem *item;
int a;
bool free;
+ int w, h;
/* arg_litem is malloced, can be freed by parent button */
- cb = *((RNAUpdateCb *)arg_litem);
-
- /* unused */
- // icon = RNA_property_enum_get(&cb.ptr, cb.prop);
-
- block = uiBeginBlock(C, ar, "_popup", UI_EMBOSS);
- uiBlockSetFlag(block, UI_BLOCK_LOOP | UI_BLOCK_REDRAW);
-
-
- RNA_property_enum_items(C, &cb.ptr, cb.prop, &item, NULL, &free);
-
+ args = *((IconViewMenuArgs *) arg_litem);
+ w = UI_UNIT_X * (args.icon_scale);
+ h = UI_UNIT_X * (args.icon_scale + args.show_labels);
+
+ block = UI_block_begin(C, ar, "_popup", UI_EMBOSS_PULLDOWN);
+ UI_block_flag_enable(block, UI_BLOCK_LOOP);
+
+ RNA_property_enum_items(C, &args.ptr, args.prop, &item, NULL, &free);
+
for (a = 0; item[a].identifier; a++) {
int x, y;
-
- /* XXX hardcoded size to 5 x unit */
- x = (a % 8) * UI_UNIT_X * 5;
- y = (a / 8) * UI_UNIT_X * 5;
-
+
+ x = (a % 8) * w;
+ y = (a / 8) * h;
+
icon = item[a].icon;
- but = uiDefIconButR_prop(block, ROW, 0, icon, x, y, UI_UNIT_X * 5, UI_UNIT_Y * 5, &cb.ptr, cb.prop, -1, 0, icon, -1, -1, NULL);
- uiButSetFlag(but, UI_HAS_ICON | UI_ICON_PREVIEW);
+ value = item[a].value;
+ if (args.show_labels) {
+ but = uiDefIconTextButR_prop(
+ block, UI_BTYPE_ROW, 0, icon, item[a].name, x, y, w, h,
+ &args.ptr, args.prop, -1, 0, value, -1, -1, NULL);
+ }
+ else {
+ but = uiDefIconButR_prop(
+ block, UI_BTYPE_ROW, 0, icon, x, y, w, h,
+ &args.ptr, args.prop, -1, 0, value, -1, -1, NULL);
+ }
+ ui_def_but_icon(but, icon, UI_HAS_ICON | UI_BUT_ICON_PREVIEW);
}
- uiBoundsBlock(block, 0.3f * U.widget_unit);
- uiBlockSetDirection(block, UI_TOP);
+ UI_block_bounds_set_normal(block, 0.3f * U.widget_unit);
+ UI_block_direction_set(block, UI_DIR_DOWN);
if (free) {
MEM_freeN(item);
@@ -1655,40 +1671,43 @@ static uiBlock *icon_view_menu(bContext *C, ARegion *ar, void *arg_litem)
return block;
}
-void uiTemplateIconView(uiLayout *layout, PointerRNA *ptr, const char *propname)
+/**
+ * \param icon_scale: Scale of the icon, 1x == button height.
+ */
+void uiTemplateIconView(uiLayout *layout, PointerRNA *ptr, const char *propname, int show_labels, float icon_scale)
{
PropertyRNA *prop = RNA_struct_find_property(ptr, propname);
- RNAUpdateCb *cb;
+ IconViewMenuArgs *cb_args;
+ EnumPropertyItem *items;
uiBlock *block;
uiBut *but;
-// rctf rect; /* UNUSED */
- int icon;
-
- if (!prop || RNA_property_type(prop) != PROP_ENUM)
+ int value, icon = ICON_NONE, tot_items;
+ bool free_items;
+
+ if (!prop || RNA_property_type(prop) != PROP_ENUM) {
+ RNA_warning("property of type Enum not found: %s.%s", RNA_struct_identifier(ptr->type), propname);
return;
-
- icon = RNA_property_enum_get(ptr, prop);
-
- cb = MEM_callocN(sizeof(RNAUpdateCb), "RNAUpdateCb");
- cb->ptr = *ptr;
- cb->prop = prop;
-
-// rect.xmin = 0; rect.xmax = 10.0f * UI_UNIT_X;
-// rect.ymin = 0; rect.ymax = 10.0f * UI_UNIT_X;
-
+ }
+
block = uiLayoutAbsoluteBlock(layout);
- but = uiDefBlockButN(block, icon_view_menu, MEM_dupallocN(cb), "", 0, 0, UI_UNIT_X * 6, UI_UNIT_Y * 6, "");
+ RNA_property_enum_items(block->evil_C, ptr, prop, &items, &tot_items, &free_items);
+ value = RNA_property_enum_get(ptr, prop);
+ RNA_enum_icon_from_value(items, value, &icon);
-
-// but = uiDefIconButR_prop(block, ROW, 0, icon, 0, 0, BLI_rctf_size_x(&rect), BLI_rctf_size_y(&rect), ptr, prop, -1, 0, icon, -1, -1, NULL);
-
- but->icon = icon;
- uiButSetFlag(but, UI_HAS_ICON | UI_ICON_PREVIEW);
-
- uiButSetNFunc(but, rna_update_cb, MEM_dupallocN(cb), NULL);
-
- MEM_freeN(cb);
+ cb_args = MEM_callocN(sizeof(IconViewMenuArgs), __func__);
+ cb_args->ptr = *ptr;
+ cb_args->prop = prop;
+ cb_args->show_labels = show_labels;
+ cb_args->icon_scale = icon_scale;
+
+ but = uiDefBlockButN(block, ui_icon_view_menu_cb, cb_args, "", 0, 0, UI_UNIT_X * 6, UI_UNIT_Y * 6, "");
+
+ ui_def_but_icon(but, icon, UI_HAS_ICON | UI_BUT_ICON_PREVIEW);
+
+ if (free_items) {
+ MEM_freeN(items);
+ }
}
/********************* Histogram Template ************************/
@@ -1719,10 +1738,10 @@ void uiTemplateHistogram(uiLayout *layout, PointerRNA *ptr, const char *propname
col = uiLayoutColumn(layout, true);
block = uiLayoutGetBlock(col);
- uiDefBut(block, HISTOGRAM, 0, "", 0, 0, UI_UNIT_X * 10, hist->height, hist, 0, 0, 0, 0, "");
+ uiDefBut(block, UI_BTYPE_HISTOGRAM, 0, "", 0, 0, UI_UNIT_X * 10, hist->height, hist, 0, 0, 0, 0, "");
/* Resize grip. */
- uiDefIconButI(block, GRIP, 0, ICON_GRIP, 0, 0, UI_UNIT_X * 10, (short)(UI_UNIT_Y * 0.3f), &hist->height,
+ uiDefIconButI(block, UI_BTYPE_GRIP, 0, ICON_GRIP, 0, 0, UI_UNIT_X * 10, (short)(UI_UNIT_Y * 0.3f), &hist->height,
UI_UNIT_Y, UI_UNIT_Y * 20.0f, 0.0f, 0.0f, "");
}
@@ -1754,10 +1773,10 @@ void uiTemplateWaveform(uiLayout *layout, PointerRNA *ptr, const char *propname)
scopes->wavefrm_height = UI_UNIT_Y * 20;
}
- uiDefBut(block, WAVEFORM, 0, "", 0, 0, UI_UNIT_X * 10, scopes->wavefrm_height, scopes, 0, 0, 0, 0, "");
+ uiDefBut(block, UI_BTYPE_WAVEFORM, 0, "", 0, 0, UI_UNIT_X * 10, scopes->wavefrm_height, scopes, 0, 0, 0, 0, "");
/* Resize grip. */
- uiDefIconButI(block, GRIP, 0, ICON_GRIP, 0, 0, UI_UNIT_X * 10, (short)(UI_UNIT_Y * 0.3f), &scopes->wavefrm_height,
+ uiDefIconButI(block, UI_BTYPE_GRIP, 0, ICON_GRIP, 0, 0, UI_UNIT_X * 10, (short)(UI_UNIT_Y * 0.3f), &scopes->wavefrm_height,
UI_UNIT_Y, UI_UNIT_Y * 20.0f, 0.0f, 0.0f, "");
}
@@ -1789,10 +1808,10 @@ void uiTemplateVectorscope(uiLayout *layout, PointerRNA *ptr, const char *propna
col = uiLayoutColumn(layout, true);
block = uiLayoutGetBlock(col);
- uiDefBut(block, VECTORSCOPE, 0, "", 0, 0, UI_UNIT_X * 10, scopes->vecscope_height, scopes, 0, 0, 0, 0, "");
+ uiDefBut(block, UI_BTYPE_VECTORSCOPE, 0, "", 0, 0, UI_UNIT_X * 10, scopes->vecscope_height, scopes, 0, 0, 0, 0, "");
/* Resize grip. */
- uiDefIconButI(block, GRIP, 0, ICON_GRIP, 0, 0, UI_UNIT_X * 10, (short)(UI_UNIT_Y * 0.3f), &scopes->vecscope_height,
+ uiDefIconButI(block, UI_BTYPE_GRIP, 0, ICON_GRIP, 0, 0, UI_UNIT_X * 10, (short)(UI_UNIT_Y * 0.3f), &scopes->vecscope_height,
UI_UNIT_Y, UI_UNIT_Y * 20.0f, 0.0f, 0.0f, "");
}
@@ -1879,28 +1898,27 @@ static uiBlock *curvemap_clipping_func(bContext *C, ARegion *ar, void *cumap_v)
uiBut *bt;
float width = 8 * UI_UNIT_X;
- block = uiBeginBlock(C, ar, __func__, UI_EMBOSS);
+ block = UI_block_begin(C, ar, __func__, UI_EMBOSS);
/* use this for a fake extra empy space around the buttons */
- uiDefBut(block, LABEL, 0, "", -4, 16, width + 8, 6 * UI_UNIT_Y, NULL, 0, 0, 0, 0, "");
+ uiDefBut(block, UI_BTYPE_LABEL, 0, "", -4, 16, width + 8, 6 * UI_UNIT_Y, NULL, 0, 0, 0, 0, "");
- bt = uiDefButBitI(block, TOG, CUMA_DO_CLIP, 1, IFACE_("Use Clipping"),
+ bt = uiDefButBitI(block, UI_BTYPE_TOGGLE, CUMA_DO_CLIP, 1, IFACE_("Use Clipping"),
0, 5 * UI_UNIT_Y, width, UI_UNIT_Y, &cumap->flag, 0.0, 0.0, 10, 0, "");
- uiButSetFunc(bt, curvemap_buttons_setclip, cumap, NULL);
+ UI_but_func_set(bt, curvemap_buttons_setclip, cumap, NULL);
- uiBlockBeginAlign(block);
- uiDefButF(block, NUM, 0, IFACE_("Min X "), 0, 4 * UI_UNIT_Y, width, UI_UNIT_Y,
+ UI_block_align_begin(block);
+ uiDefButF(block, UI_BTYPE_NUM, 0, IFACE_("Min X "), 0, 4 * UI_UNIT_Y, width, UI_UNIT_Y,
&cumap->clipr.xmin, -100.0, cumap->clipr.xmax, 10, 2, "");
- uiDefButF(block, NUM, 0, IFACE_("Min Y "), 0, 3 * UI_UNIT_Y, width, UI_UNIT_Y,
+ uiDefButF(block, UI_BTYPE_NUM, 0, IFACE_("Min Y "), 0, 3 * UI_UNIT_Y, width, UI_UNIT_Y,
&cumap->clipr.ymin, -100.0, cumap->clipr.ymax, 10, 2, "");
- uiDefButF(block, NUM, 0, IFACE_("Max X "), 0, 2 * UI_UNIT_Y, width, UI_UNIT_Y,
+ uiDefButF(block, UI_BTYPE_NUM, 0, IFACE_("Max X "), 0, 2 * UI_UNIT_Y, width, UI_UNIT_Y,
&cumap->clipr.xmax, cumap->clipr.xmin, 100.0, 10, 2, "");
- uiDefButF(block, NUM, 0, IFACE_("Max Y "), 0, UI_UNIT_Y, width, UI_UNIT_Y,
+ uiDefButF(block, UI_BTYPE_NUM, 0, IFACE_("Max Y "), 0, UI_UNIT_Y, width, UI_UNIT_Y,
&cumap->clipr.ymax, cumap->clipr.ymin, 100.0, 10, 2, "");
- uiBlockSetDirection(block, UI_RIGHT);
+ UI_block_direction_set(block, UI_DIR_RIGHT);
- uiEndBlock(C, block);
return block;
}
@@ -1956,26 +1974,25 @@ static uiBlock *curvemap_tools_posslope_func(bContext *C, ARegion *ar, void *cum
uiBlock *block;
short yco = 0, menuwidth = 10 * UI_UNIT_X;
- block = uiBeginBlock(C, ar, __func__, UI_EMBOSS);
- uiBlockSetButmFunc(block, curvemap_tools_dofunc, cumap_v);
+ block = UI_block_begin(C, ar, __func__, UI_EMBOSS);
+ UI_block_func_butmenu_set(block, curvemap_tools_dofunc, cumap_v);
- uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, IFACE_("Reset View"), 0, yco -= UI_UNIT_Y,
+ uiDefIconTextBut(block, UI_BTYPE_BUT_MENU, 1, ICON_BLANK1, IFACE_("Reset View"), 0, yco -= UI_UNIT_Y,
menuwidth, UI_UNIT_Y, NULL, 0.0, 0.0, 0, UICURVE_FUNC_RESET_VIEW, "");
- uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, IFACE_("Vector Handle"), 0, yco -= UI_UNIT_Y,
+ uiDefIconTextBut(block, UI_BTYPE_BUT_MENU, 1, ICON_BLANK1, IFACE_("Vector Handle"), 0, yco -= UI_UNIT_Y,
menuwidth, UI_UNIT_Y, NULL, 0.0, 0.0, 0, UICURVE_FUNC_HANDLE_VECTOR, "");
- uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, IFACE_("Auto Handle"), 0, yco -= UI_UNIT_Y,
+ uiDefIconTextBut(block, UI_BTYPE_BUT_MENU, 1, ICON_BLANK1, IFACE_("Auto Handle"), 0, yco -= UI_UNIT_Y,
menuwidth, UI_UNIT_Y, NULL, 0.0, 0.0, 0, UICURVE_FUNC_HANDLE_AUTO, "");
- uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, IFACE_("Extend Horizontal"), 0, yco -= UI_UNIT_Y,
+ uiDefIconTextBut(block, UI_BTYPE_BUT_MENU, 1, ICON_BLANK1, IFACE_("Extend Horizontal"), 0, yco -= UI_UNIT_Y,
menuwidth, UI_UNIT_Y, NULL, 0.0, 0.0, 0, UICURVE_FUNC_EXTEND_HOZ, "");
- uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, IFACE_("Extend Extrapolated"), 0, yco -= UI_UNIT_Y,
+ uiDefIconTextBut(block, UI_BTYPE_BUT_MENU, 1, ICON_BLANK1, IFACE_("Extend Extrapolated"), 0, yco -= UI_UNIT_Y,
menuwidth, UI_UNIT_Y, NULL, 0.0, 0.0, 0, UICURVE_FUNC_EXTEND_EXP, "");
- uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, IFACE_("Reset Curve"), 0, yco -= UI_UNIT_Y,
+ uiDefIconTextBut(block, UI_BTYPE_BUT_MENU, 1, ICON_BLANK1, IFACE_("Reset Curve"), 0, yco -= UI_UNIT_Y,
menuwidth, UI_UNIT_Y, NULL, 0.0, 0.0, 0, UICURVE_FUNC_RESET_POS, "");
- uiBlockSetDirection(block, UI_RIGHT);
- uiTextBoundsBlock(block, 50);
+ UI_block_direction_set(block, UI_DIR_RIGHT);
+ UI_block_bounds_set_text(block, 50);
- uiEndBlock(C, block);
return block;
}
@@ -1984,26 +2001,25 @@ static uiBlock *curvemap_tools_negslope_func(bContext *C, ARegion *ar, void *cum
uiBlock *block;
short yco = 0, menuwidth = 10 * UI_UNIT_X;
- block = uiBeginBlock(C, ar, __func__, UI_EMBOSS);
- uiBlockSetButmFunc(block, curvemap_tools_dofunc, cumap_v);
+ block = UI_block_begin(C, ar, __func__, UI_EMBOSS);
+ UI_block_func_butmenu_set(block, curvemap_tools_dofunc, cumap_v);
- uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, IFACE_("Reset View"), 0, yco -= UI_UNIT_Y,
+ uiDefIconTextBut(block, UI_BTYPE_BUT_MENU, 1, ICON_BLANK1, IFACE_("Reset View"), 0, yco -= UI_UNIT_Y,
menuwidth, UI_UNIT_Y, NULL, 0.0, 0.0, 0, UICURVE_FUNC_RESET_VIEW, "");
- uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, IFACE_("Vector Handle"), 0, yco -= UI_UNIT_Y,
+ uiDefIconTextBut(block, UI_BTYPE_BUT_MENU, 1, ICON_BLANK1, IFACE_("Vector Handle"), 0, yco -= UI_UNIT_Y,
menuwidth, UI_UNIT_Y, NULL, 0.0, 0.0, 0, UICURVE_FUNC_HANDLE_VECTOR, "");
- uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, IFACE_("Auto Handle"), 0, yco -= UI_UNIT_Y,
+ uiDefIconTextBut(block, UI_BTYPE_BUT_MENU, 1, ICON_BLANK1, IFACE_("Auto Handle"), 0, yco -= UI_UNIT_Y,
menuwidth, UI_UNIT_Y, NULL, 0.0, 0.0, 0, UICURVE_FUNC_HANDLE_AUTO, "");
- uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, IFACE_("Extend Horizontal"), 0, yco -= UI_UNIT_Y,
+ uiDefIconTextBut(block, UI_BTYPE_BUT_MENU, 1, ICON_BLANK1, IFACE_("Extend Horizontal"), 0, yco -= UI_UNIT_Y,
menuwidth, UI_UNIT_Y, NULL, 0.0, 0.0, 0, UICURVE_FUNC_EXTEND_HOZ, "");
- uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, IFACE_("Extend Extrapolated"), 0, yco -= UI_UNIT_Y,
+ uiDefIconTextBut(block, UI_BTYPE_BUT_MENU, 1, ICON_BLANK1, IFACE_("Extend Extrapolated"), 0, yco -= UI_UNIT_Y,
menuwidth, UI_UNIT_Y, NULL, 0.0, 0.0, 0, UICURVE_FUNC_EXTEND_EXP, "");
- uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, IFACE_("Reset Curve"), 0, yco -= UI_UNIT_Y,
+ uiDefIconTextBut(block, UI_BTYPE_BUT_MENU, 1, ICON_BLANK1, IFACE_("Reset Curve"), 0, yco -= UI_UNIT_Y,
menuwidth, UI_UNIT_Y, NULL, 0.0, 0.0, 0, UICURVE_FUNC_RESET_NEG, "");
- uiBlockSetDirection(block, UI_RIGHT);
- uiTextBoundsBlock(block, 50);
+ UI_block_direction_set(block, UI_DIR_RIGHT);
+ UI_block_bounds_set_text(block, 50);
- uiEndBlock(C, block);
return block;
}
@@ -2012,22 +2028,21 @@ static uiBlock *curvemap_brush_tools_func(bContext *C, ARegion *ar, void *cumap_
uiBlock *block;
short yco = 0, menuwidth = 10 * UI_UNIT_X;
- block = uiBeginBlock(C, ar, __func__, UI_EMBOSS);
- uiBlockSetButmFunc(block, curvemap_tools_dofunc, cumap_v);
+ block = UI_block_begin(C, ar, __func__, UI_EMBOSS);
+ UI_block_func_butmenu_set(block, curvemap_tools_dofunc, cumap_v);
- uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, IFACE_("Reset View"), 0, yco -= UI_UNIT_Y,
+ uiDefIconTextBut(block, UI_BTYPE_BUT_MENU, 1, ICON_BLANK1, IFACE_("Reset View"), 0, yco -= UI_UNIT_Y,
menuwidth, UI_UNIT_Y, NULL, 0.0, 0.0, 0, UICURVE_FUNC_RESET_VIEW, "");
- uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, IFACE_("Vector Handle"), 0, yco -= UI_UNIT_Y,
+ uiDefIconTextBut(block, UI_BTYPE_BUT_MENU, 1, ICON_BLANK1, IFACE_("Vector Handle"), 0, yco -= UI_UNIT_Y,
menuwidth, UI_UNIT_Y, NULL, 0.0, 0.0, 0, UICURVE_FUNC_HANDLE_VECTOR, "");
- uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, IFACE_("Auto Handle"), 0, yco -= UI_UNIT_Y,
+ uiDefIconTextBut(block, UI_BTYPE_BUT_MENU, 1, ICON_BLANK1, IFACE_("Auto Handle"), 0, yco -= UI_UNIT_Y,
menuwidth, UI_UNIT_Y, NULL, 0.0, 0.0, 0, UICURVE_FUNC_HANDLE_AUTO, "");
- uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, IFACE_("Reset Curve"), 0, yco -= UI_UNIT_Y,
+ uiDefIconTextBut(block, UI_BTYPE_BUT_MENU, 1, ICON_BLANK1, IFACE_("Reset Curve"), 0, yco -= UI_UNIT_Y,
menuwidth, UI_UNIT_Y, NULL, 0.0, 0.0, 0, UICURVE_FUNC_RESET_NEG, "");
- uiBlockSetDirection(block, UI_RIGHT);
- uiTextBoundsBlock(block, 50);
+ UI_block_direction_set(block, UI_DIR_RIGHT);
+ UI_block_bounds_set_text(block, 50);
- uiEndBlock(C, block);
return block;
}
@@ -2062,8 +2077,9 @@ static void curvemap_buttons_reset(bContext *C, void *cb_v, void *cumap_v)
}
/* still unsure how this call evolves... we use labeltype for defining what curve-channels to show */
-static void curvemap_buttons_layout(uiLayout *layout, PointerRNA *ptr, char labeltype, int levels,
- int brush, int neg_slope, RNAUpdateCb *cb)
+static void curvemap_buttons_layout(
+ uiLayout *layout, PointerRNA *ptr, char labeltype, int levels,
+ int brush, int neg_slope, RNAUpdateCb *cb)
{
CurveMapping *cumap = ptr->data;
CurveMap *cm = &cumap->cm[cumap->cur];
@@ -2086,16 +2102,16 @@ static void curvemap_buttons_layout(uiLayout *layout, PointerRNA *ptr, char labe
uiLayoutSetAlignment(sub, UI_LAYOUT_ALIGN_LEFT);
if (cumap->cm[0].curve) {
- bt = uiDefButI(block, ROW, 0, "X", 0, 0, dx, dx, &cumap->cur, 0.0, 0.0, 0.0, 0.0, "");
- uiButSetFunc(bt, curvemap_buttons_redraw, NULL, NULL);
+ bt = uiDefButI(block, UI_BTYPE_ROW, 0, "X", 0, 0, dx, dx, &cumap->cur, 0.0, 0.0, 0.0, 0.0, "");
+ UI_but_func_set(bt, curvemap_buttons_redraw, NULL, NULL);
}
if (cumap->cm[1].curve) {
- bt = uiDefButI(block, ROW, 0, "Y", 0, 0, dx, dx, &cumap->cur, 0.0, 1.0, 0.0, 0.0, "");
- uiButSetFunc(bt, curvemap_buttons_redraw, NULL, NULL);
+ bt = uiDefButI(block, UI_BTYPE_ROW, 0, "Y", 0, 0, dx, dx, &cumap->cur, 0.0, 1.0, 0.0, 0.0, "");
+ UI_but_func_set(bt, curvemap_buttons_redraw, NULL, NULL);
}
if (cumap->cm[2].curve) {
- bt = uiDefButI(block, ROW, 0, "Z", 0, 0, dx, dx, &cumap->cur, 0.0, 2.0, 0.0, 0.0, "");
- uiButSetFunc(bt, curvemap_buttons_redraw, NULL, NULL);
+ bt = uiDefButI(block, UI_BTYPE_ROW, 0, "Z", 0, 0, dx, dx, &cumap->cur, 0.0, 2.0, 0.0, 0.0, "");
+ UI_but_func_set(bt, curvemap_buttons_redraw, NULL, NULL);
}
}
else if (labeltype == 'c') {
@@ -2104,20 +2120,20 @@ static void curvemap_buttons_layout(uiLayout *layout, PointerRNA *ptr, char labe
uiLayoutSetAlignment(sub, UI_LAYOUT_ALIGN_LEFT);
if (cumap->cm[3].curve) {
- bt = uiDefButI(block, ROW, 0, "C", 0, 0, dx, dx, &cumap->cur, 0.0, 3.0, 0.0, 0.0, "");
- uiButSetFunc(bt, curvemap_buttons_redraw, NULL, NULL);
+ bt = uiDefButI(block, UI_BTYPE_ROW, 0, "C", 0, 0, dx, dx, &cumap->cur, 0.0, 3.0, 0.0, 0.0, "");
+ UI_but_func_set(bt, curvemap_buttons_redraw, NULL, NULL);
}
if (cumap->cm[0].curve) {
- bt = uiDefButI(block, ROW, 0, "R", 0, 0, dx, dx, &cumap->cur, 0.0, 0.0, 0.0, 0.0, "");
- uiButSetFunc(bt, curvemap_buttons_redraw, NULL, NULL);
+ bt = uiDefButI(block, UI_BTYPE_ROW, 0, "R", 0, 0, dx, dx, &cumap->cur, 0.0, 0.0, 0.0, 0.0, "");
+ UI_but_func_set(bt, curvemap_buttons_redraw, NULL, NULL);
}
if (cumap->cm[1].curve) {
- bt = uiDefButI(block, ROW, 0, "G", 0, 0, dx, dx, &cumap->cur, 0.0, 1.0, 0.0, 0.0, "");
- uiButSetFunc(bt, curvemap_buttons_redraw, NULL, NULL);
+ bt = uiDefButI(block, UI_BTYPE_ROW, 0, "G", 0, 0, dx, dx, &cumap->cur, 0.0, 1.0, 0.0, 0.0, "");
+ UI_but_func_set(bt, curvemap_buttons_redraw, NULL, NULL);
}
if (cumap->cm[2].curve) {
- bt = uiDefButI(block, ROW, 0, "B", 0, 0, dx, dx, &cumap->cur, 0.0, 2.0, 0.0, 0.0, "");
- uiButSetFunc(bt, curvemap_buttons_redraw, NULL, NULL);
+ bt = uiDefButI(block, UI_BTYPE_ROW, 0, "B", 0, 0, dx, dx, &cumap->cur, 0.0, 2.0, 0.0, 0.0, "");
+ UI_but_func_set(bt, curvemap_buttons_redraw, NULL, NULL);
}
}
else if (labeltype == 'h') {
@@ -2126,16 +2142,16 @@ static void curvemap_buttons_layout(uiLayout *layout, PointerRNA *ptr, char labe
uiLayoutSetAlignment(sub, UI_LAYOUT_ALIGN_LEFT);
if (cumap->cm[0].curve) {
- bt = uiDefButI(block, ROW, 0, "H", 0, 0, dx, dx, &cumap->cur, 0.0, 0.0, 0.0, 0.0, "");
- uiButSetFunc(bt, curvemap_buttons_redraw, NULL, NULL);
+ bt = uiDefButI(block, UI_BTYPE_ROW, 0, "H", 0, 0, dx, dx, &cumap->cur, 0.0, 0.0, 0.0, 0.0, "");
+ UI_but_func_set(bt, curvemap_buttons_redraw, NULL, NULL);
}
if (cumap->cm[1].curve) {
- bt = uiDefButI(block, ROW, 0, "S", 0, 0, dx, dx, &cumap->cur, 0.0, 1.0, 0.0, 0.0, "");
- uiButSetFunc(bt, curvemap_buttons_redraw, NULL, NULL);
+ bt = uiDefButI(block, UI_BTYPE_ROW, 0, "S", 0, 0, dx, dx, &cumap->cur, 0.0, 1.0, 0.0, 0.0, "");
+ UI_but_func_set(bt, curvemap_buttons_redraw, NULL, NULL);
}
if (cumap->cm[2].curve) {
- bt = uiDefButI(block, ROW, 0, "V", 0, 0, dx, dx, &cumap->cur, 0.0, 2.0, 0.0, 0.0, "");
- uiButSetFunc(bt, curvemap_buttons_redraw, NULL, NULL);
+ bt = uiDefButI(block, UI_BTYPE_ROW, 0, "V", 0, 0, dx, dx, &cumap->cur, 0.0, 2.0, 0.0, 0.0, "");
+ UI_but_func_set(bt, curvemap_buttons_redraw, NULL, NULL);
}
}
else
@@ -2147,13 +2163,13 @@ static void curvemap_buttons_layout(uiLayout *layout, PointerRNA *ptr, char labe
/* operation buttons */
sub = uiLayoutRow(row, true);
- uiBlockSetEmboss(block, UI_EMBOSSN);
+ UI_block_emboss_set(block, UI_EMBOSS_NONE);
- bt = uiDefIconBut(block, BUT, 0, ICON_ZOOMIN, 0, 0, dx, dx, NULL, 0.0, 0.0, 0.0, 0.0, TIP_("Zoom in"));
- uiButSetFunc(bt, curvemap_buttons_zoom_in, cumap, NULL);
+ bt = uiDefIconBut(block, UI_BTYPE_BUT, 0, ICON_ZOOMIN, 0, 0, dx, dx, NULL, 0.0, 0.0, 0.0, 0.0, TIP_("Zoom in"));
+ UI_but_func_set(bt, curvemap_buttons_zoom_in, cumap, NULL);
- bt = uiDefIconBut(block, BUT, 0, ICON_ZOOMOUT, 0, 0, dx, dx, NULL, 0.0, 0.0, 0.0, 0.0, TIP_("Zoom out"));
- uiButSetFunc(bt, curvemap_buttons_zoom_out, cumap, NULL);
+ bt = uiDefIconBut(block, UI_BTYPE_BUT, 0, ICON_ZOOMOUT, 0, 0, dx, dx, NULL, 0.0, 0.0, 0.0, 0.0, TIP_("Zoom out"));
+ UI_but_func_set(bt, curvemap_buttons_zoom_out, cumap, NULL);
if (brush)
bt = uiDefIconBlockBut(block, curvemap_brush_tools_func, cumap, 0, ICON_MODIFIER, 0, 0, dx, dx, TIP_("Tools"));
@@ -2164,23 +2180,23 @@ static void curvemap_buttons_layout(uiLayout *layout, PointerRNA *ptr, char labe
bt = uiDefIconBlockBut(block, curvemap_tools_posslope_func, cumap, 0, ICON_MODIFIER,
0, 0, dx, dx, TIP_("Tools"));
- uiButSetNFunc(bt, rna_update_cb, MEM_dupallocN(cb), NULL);
+ UI_but_funcN_set(bt, rna_update_cb, MEM_dupallocN(cb), NULL);
icon = (cumap->flag & CUMA_DO_CLIP) ? ICON_CLIPUV_HLT : ICON_CLIPUV_DEHLT;
bt = uiDefIconBlockBut(block, curvemap_clipping_func, cumap, 0, icon, 0, 0, dx, dx, TIP_("Clipping Options"));
- uiButSetNFunc(bt, rna_update_cb, MEM_dupallocN(cb), NULL);
+ UI_but_funcN_set(bt, rna_update_cb, MEM_dupallocN(cb), NULL);
- bt = uiDefIconBut(block, BUT, 0, ICON_X, 0, 0, dx, dx, NULL, 0.0, 0.0, 0.0, 0.0, TIP_("Delete points"));
- uiButSetNFunc(bt, curvemap_buttons_delete, MEM_dupallocN(cb), cumap);
+ bt = uiDefIconBut(block, UI_BTYPE_BUT, 0, ICON_X, 0, 0, dx, dx, NULL, 0.0, 0.0, 0.0, 0.0, TIP_("Delete points"));
+ UI_but_funcN_set(bt, curvemap_buttons_delete, MEM_dupallocN(cb), cumap);
- uiBlockSetEmboss(block, UI_EMBOSS);
+ UI_block_emboss_set(block, UI_EMBOSS);
- uiBlockSetNFunc(block, rna_update_cb, MEM_dupallocN(cb), NULL);
+ UI_block_funcN_set(block, rna_update_cb, MEM_dupallocN(cb), NULL);
/* curve itself */
size = uiLayoutGetWidth(layout);
row = uiLayoutRow(layout, false);
- uiDefBut(block, BUT_CURVE, 0, "", 0, 0, size, 8.0f * UI_UNIT_X, cumap, 0.0f, 1.0f, bg, 0, "");
+ uiDefBut(block, UI_BTYPE_CURVE, 0, "", 0, 0, size, 8.0f * UI_UNIT_X, cumap, 0.0f, 1.0f, bg, 0, "");
/* sliders for selected point */
for (i = 0; i < cm->totpoint; i++) {
@@ -2202,10 +2218,10 @@ static void curvemap_buttons_layout(uiLayout *layout, PointerRNA *ptr, char labe
}
uiLayoutRow(layout, true);
- uiBlockSetNFunc(block, curvemap_buttons_update, MEM_dupallocN(cb), cumap);
- uiDefButF(block, NUM, 0, "X", 0, 2 * UI_UNIT_Y, UI_UNIT_X * 10, UI_UNIT_Y,
+ UI_block_funcN_set(block, curvemap_buttons_update, MEM_dupallocN(cb), cumap);
+ uiDefButF(block, UI_BTYPE_NUM, 0, "X", 0, 2 * UI_UNIT_Y, UI_UNIT_X * 10, UI_UNIT_Y,
&cmp->x, bounds.xmin, bounds.xmax, 1, 5, "");
- uiDefButF(block, NUM, 0, "Y", 0, 1 * UI_UNIT_Y, UI_UNIT_X * 10, UI_UNIT_Y,
+ uiDefButF(block, UI_BTYPE_NUM, 0, "Y", 0, 1 * UI_UNIT_Y, UI_UNIT_X * 10, UI_UNIT_Y,
&cmp->y, bounds.ymin, bounds.ymax, 1, 5, "");
}
@@ -2216,16 +2232,17 @@ static void curvemap_buttons_layout(uiLayout *layout, PointerRNA *ptr, char labe
uiItemR(uiLayoutColumn(split, false), ptr, "white_level", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
uiLayoutRow(layout, false);
- bt = uiDefBut(block, BUT, 0, IFACE_("Reset"), 0, 0, UI_UNIT_X * 10, UI_UNIT_Y, NULL, 0.0f, 0.0f, 0, 0,
+ bt = uiDefBut(block, UI_BTYPE_BUT, 0, IFACE_("Reset"), 0, 0, UI_UNIT_X * 10, UI_UNIT_Y, NULL, 0.0f, 0.0f, 0, 0,
TIP_("Reset Black/White point and curves"));
- uiButSetNFunc(bt, curvemap_buttons_reset, MEM_dupallocN(cb), cumap);
+ UI_but_funcN_set(bt, curvemap_buttons_reset, MEM_dupallocN(cb), cumap);
}
- uiBlockSetNFunc(block, NULL, NULL, NULL);
+ UI_block_funcN_set(block, NULL, NULL, NULL);
}
-void uiTemplateCurveMapping(uiLayout *layout, PointerRNA *ptr, const char *propname, int type,
- int levels, int brush, int neg_slope)
+void uiTemplateCurveMapping(
+ uiLayout *layout, PointerRNA *ptr, const char *propname, int type,
+ int levels, int brush, int neg_slope)
{
RNAUpdateCb *cb;
PropertyRNA *prop = RNA_struct_find_property(ptr, propname);
@@ -2254,11 +2271,11 @@ void uiTemplateCurveMapping(uiLayout *layout, PointerRNA *ptr, const char *propn
cb->prop = prop;
id = cptr.id.data;
- uiBlockSetButLock(block, (id && id->lib), ERROR_LIBDATA_MESSAGE);
+ UI_block_lock_set(block, (id && id->lib), ERROR_LIBDATA_MESSAGE);
curvemap_buttons_layout(layout, &cptr, type, levels, brush, neg_slope, cb);
- uiBlockClearButLock(block);
+ UI_block_lock_clear(block);
MEM_freeN(cb);
}
@@ -2268,13 +2285,15 @@ void uiTemplateCurveMapping(uiLayout *layout, PointerRNA *ptr, const char *propn
#define WHEEL_SIZE (5 * U.widget_unit)
/* This template now follows User Preference for type - name is not correct anymore... */
-void uiTemplateColorPicker(uiLayout *layout, PointerRNA *ptr, const char *propname, int value_slider,
- int lock, int lock_luminosity, int cubic)
+void uiTemplateColorPicker(
+ uiLayout *layout, PointerRNA *ptr, const char *propname, int value_slider,
+ int lock, int lock_luminosity, int cubic)
{
PropertyRNA *prop = RNA_struct_find_property(ptr, propname);
uiBlock *block = uiLayoutGetBlock(layout);
uiLayout *col, *row;
uiBut *but = NULL;
+ ColorPicker *cpicker = ui_block_colorpicker_create(block);
float softmin, softmax, step, precision;
if (!prop) {
@@ -2289,15 +2308,15 @@ void uiTemplateColorPicker(uiLayout *layout, PointerRNA *ptr, const char *propna
switch (U.color_picker_type) {
case USER_CP_SQUARE_SV:
- but = uiDefButR_prop(block, HSVCUBE, 0, "", 0, 0, WHEEL_SIZE, WHEEL_SIZE, ptr, prop,
+ but = uiDefButR_prop(block, UI_BTYPE_HSVCUBE, 0, "", 0, 0, WHEEL_SIZE, WHEEL_SIZE, ptr, prop,
-1, 0.0, 0.0, UI_GRAD_SV, 0, "");
break;
case USER_CP_SQUARE_HS:
- but = uiDefButR_prop(block, HSVCUBE, 0, "", 0, 0, WHEEL_SIZE, WHEEL_SIZE, ptr, prop,
+ but = uiDefButR_prop(block, UI_BTYPE_HSVCUBE, 0, "", 0, 0, WHEEL_SIZE, WHEEL_SIZE, ptr, prop,
-1, 0.0, 0.0, UI_GRAD_HS, 0, "");
break;
case USER_CP_SQUARE_HV:
- but = uiDefButR_prop(block, HSVCUBE, 0, "", 0, 0, WHEEL_SIZE, WHEEL_SIZE, ptr, prop,
+ but = uiDefButR_prop(block, UI_BTYPE_HSVCUBE, 0, "", 0, 0, WHEEL_SIZE, WHEEL_SIZE, ptr, prop,
-1, 0.0, 0.0, UI_GRAD_HV, 0, "");
break;
@@ -2305,12 +2324,14 @@ void uiTemplateColorPicker(uiLayout *layout, PointerRNA *ptr, const char *propna
case USER_CP_CIRCLE_HSV:
case USER_CP_CIRCLE_HSL:
default:
- but = uiDefButR_prop(block, HSVCIRCLE, 0, "", 0, 0, WHEEL_SIZE, WHEEL_SIZE, ptr, prop,
+ but = uiDefButR_prop(block, UI_BTYPE_HSVCIRCLE, 0, "", 0, 0, WHEEL_SIZE, WHEEL_SIZE, ptr, prop,
-1, 0.0, 0.0, 0, 0, "");
break;
}
+ but->custom_data = cpicker;
+
if (lock) {
but->flag |= UI_BUT_COLOR_LOCK;
}
@@ -2330,33 +2351,35 @@ void uiTemplateColorPicker(uiLayout *layout, PointerRNA *ptr, const char *propna
switch (U.color_picker_type) {
case USER_CP_CIRCLE_HSL:
uiItemS(row);
- uiDefButR_prop(block, HSVCUBE, 0, "", WHEEL_SIZE + 6, 0, 14, WHEEL_SIZE, ptr, prop,
- -1, softmin, softmax, UI_GRAD_L_ALT, 0, "");
+ but = uiDefButR_prop(block, UI_BTYPE_HSVCUBE, 0, "", WHEEL_SIZE + 6, 0, 14, WHEEL_SIZE, ptr, prop,
+ -1, softmin, softmax, UI_GRAD_L_ALT, 0, "");
break;
case USER_CP_SQUARE_SV:
uiItemS(col);
- uiDefButR_prop(block, HSVCUBE, 0, "", 0, 4, WHEEL_SIZE, 18, ptr, prop,
- -1, softmin, softmax, UI_GRAD_SV + 3, 0, "");
+ but = uiDefButR_prop(block, UI_BTYPE_HSVCUBE, 0, "", 0, 4, WHEEL_SIZE, 18, ptr, prop,
+ -1, softmin, softmax, UI_GRAD_SV + 3, 0, "");
break;
case USER_CP_SQUARE_HS:
uiItemS(col);
- uiDefButR_prop(block, HSVCUBE, 0, "", 0, 4, WHEEL_SIZE, 18, ptr, prop,
- -1, softmin, softmax, UI_GRAD_HS + 3, 0, "");
+ but = uiDefButR_prop(block, UI_BTYPE_HSVCUBE, 0, "", 0, 4, WHEEL_SIZE, 18, ptr, prop,
+ -1, softmin, softmax, UI_GRAD_HS + 3, 0, "");
break;
case USER_CP_SQUARE_HV:
uiItemS(col);
- uiDefButR_prop(block, HSVCUBE, 0, "", 0, 4, WHEEL_SIZE, 18, ptr, prop,
- -1, softmin, softmax, UI_GRAD_HV + 3, 0, "");
+ but = uiDefButR_prop(block, UI_BTYPE_HSVCUBE, 0, "", 0, 4, WHEEL_SIZE, 18, ptr, prop,
+ -1, softmin, softmax, UI_GRAD_HV + 3, 0, "");
break;
/* user default */
case USER_CP_CIRCLE_HSV:
default:
uiItemS(row);
- uiDefButR_prop(block, HSVCUBE, 0, "", WHEEL_SIZE + 6, 0, 14, WHEEL_SIZE, ptr, prop,
- -1, softmin, softmax, UI_GRAD_V_ALT, 0, "");
+ but = uiDefButR_prop(block, UI_BTYPE_HSVCUBE, 0, "", WHEEL_SIZE + 6, 0, 14, WHEEL_SIZE, ptr, prop,
+ -1, softmin, softmax, UI_GRAD_V_ALT, 0, "");
break;
}
+
+ but->custom_data = cpicker;
}
}
@@ -2384,15 +2407,12 @@ void uiTemplatePalette(uiLayout *layout, PointerRNA *ptr, const char *propname,
palette = cptr.data;
- /* first delete any pending colors */
- BKE_palette_cleanup(palette);
-
color = palette->colors.first;
col = uiLayoutColumn(layout, true);
uiLayoutRow(col, true);
- uiDefIconButO(block, BUT, "PALETTE_OT_color_add", WM_OP_INVOKE_DEFAULT, ICON_ZOOMIN, 0, 0, UI_UNIT_X, UI_UNIT_Y, NULL);
- uiDefIconButO(block, BUT, "PALETTE_OT_color_delete", WM_OP_INVOKE_DEFAULT, ICON_ZOOMOUT, 0, 0, UI_UNIT_X, UI_UNIT_Y, NULL);
+ uiDefIconButO(block, UI_BTYPE_BUT, "PALETTE_OT_color_add", WM_OP_INVOKE_DEFAULT, ICON_ZOOMIN, 0, 0, UI_UNIT_X, UI_UNIT_Y, NULL);
+ uiDefIconButO(block, UI_BTYPE_BUT, "PALETTE_OT_color_delete", WM_OP_INVOKE_DEFAULT, ICON_ZOOMOUT, 0, 0, UI_UNIT_X, UI_UNIT_Y, NULL);
col = uiLayoutColumn(layout, true);
uiLayoutRow(col, true);
@@ -2406,7 +2426,7 @@ void uiTemplatePalette(uiLayout *layout, PointerRNA *ptr, const char *propname,
}
RNA_pointer_create(&palette->id, &RNA_PaletteColor, color, &ptr);
- uiDefButR(block, COLOR, 0, "", 0, 0, UI_UNIT_X, UI_UNIT_Y, &ptr, "color", -1, 0.0, 1.0,
+ uiDefButR(block, UI_BTYPE_COLOR, 0, "", 0, 0, UI_UNIT_X, UI_UNIT_Y, &ptr, "color", -1, 0.0, 1.0,
UI_PALETTE_COLOR, col_id, "");
row_cols++;
col_id++;
@@ -2438,12 +2458,13 @@ static void handle_layer_buttons(bContext *C, void *arg1, void *arg2)
/* see view3d_header.c */
}
-/* TODO:
- * - for now, grouping of layers is determined by dividing up the length of
- * the array of layer bitflags */
-
-void uiTemplateLayers(uiLayout *layout, PointerRNA *ptr, const char *propname,
- PointerRNA *used_ptr, const char *used_propname, int active_layer)
+/**
+ * \todo for now, grouping of layers is determined by dividing up the length of
+ * the array of layer bitflags
+ */
+void uiTemplateLayers(
+ uiLayout *layout, PointerRNA *ptr, const char *propname,
+ PointerRNA *used_ptr, const char *used_propname, int active_layer)
{
uiLayout *uRow, *uCol;
PropertyRNA *prop, *used_prop = NULL;
@@ -2502,15 +2523,16 @@ void uiTemplateLayers(uiLayout *layout, PointerRNA *ptr, const char *propname,
icon = ICON_LAYER_USED;
but = uiDefAutoButR(block, ptr, prop, layer, "", icon, 0, 0, UI_UNIT_X / 2, UI_UNIT_Y / 2);
- uiButSetFunc(but, handle_layer_buttons, but, SET_INT_IN_POINTER(layer));
- but->type = TOG;
+ UI_but_func_set(but, handle_layer_buttons, but, SET_INT_IN_POINTER(layer));
+ but->type = UI_BTYPE_TOGGLE;
}
}
}
}
-void uiTemplateGameStates(uiLayout *layout, PointerRNA *ptr, const char *propname,
- PointerRNA *used_ptr, const char *used_propname, int active_state)
+void uiTemplateGameStates(
+ uiLayout *layout, PointerRNA *ptr, const char *propname,
+ PointerRNA *used_ptr, const char *used_propname, int active_state)
{
uiLayout *uRow, *uCol;
PropertyRNA *prop, *used_prop = NULL;
@@ -2569,10 +2591,10 @@ void uiTemplateGameStates(uiLayout *layout, PointerRNA *ptr, const char *propnam
else if (used_prop && RNA_property_boolean_get_index(used_ptr, used_prop, state))
icon = ICON_LAYER_USED;
- but = uiDefIconButR_prop(block, ICONTOG, 0, icon, 0, 0, UI_UNIT_X / 2, UI_UNIT_Y / 2, ptr, prop,
+ but = uiDefIconButR_prop(block, UI_BTYPE_ICON_TOGGLE, 0, icon, 0, 0, UI_UNIT_X / 2, UI_UNIT_Y / 2, ptr, prop,
state, 0, 0, -1, -1, sca_state_name_get(ob, state));
- uiButSetFunc(but, handle_layer_buttons, but, SET_INT_IN_POINTER(state));
- but->type = TOG;
+ UI_but_func_set(but, handle_layer_buttons, but, SET_INT_IN_POINTER(state));
+ but->type = UI_BTYPE_TOGGLE;
}
}
}
@@ -2580,10 +2602,11 @@ void uiTemplateGameStates(uiLayout *layout, PointerRNA *ptr, const char *propnam
/************************* List Template **************************/
-static void uilist_draw_item_default(struct uiList *ui_list, struct bContext *UNUSED(C), struct uiLayout *layout,
- struct PointerRNA *UNUSED(dataptr), struct PointerRNA *itemptr, int icon,
- struct PointerRNA *UNUSED(active_dataptr), const char *UNUSED(active_propname),
- int UNUSED(index), int UNUSED(flt_flag))
+static void uilist_draw_item_default(
+ struct uiList *ui_list, struct bContext *UNUSED(C), struct uiLayout *layout,
+ struct PointerRNA *UNUSED(dataptr), struct PointerRNA *itemptr, int icon,
+ struct PointerRNA *UNUSED(active_dataptr), const char *UNUSED(active_propname),
+ int UNUSED(index), int UNUSED(flt_flag))
{
PropertyRNA *nameprop = RNA_struct_name_property(itemptr->type);
@@ -2658,7 +2681,7 @@ static void uilist_filter_items_default(struct uiList *ui_list, struct bContext
names = MEM_callocN(sizeof(StringCmp) * len, "StringCmp");
}
if (filter_raw[0]) {
- size_t idx = 0, slen = strlen(filter_raw);
+ size_t slen = strlen(filter_raw);
dyn_data->items_filter_flags = MEM_callocN(sizeof(int) * len, "items_filter_flags");
dyn_data->items_shown = 0;
@@ -2670,15 +2693,7 @@ static void uilist_filter_items_default(struct uiList *ui_list, struct bContext
else {
filter = filter_dyn = MEM_mallocN((slen + 3) * sizeof(char), "filter_dyn");
}
- if (filter_raw[idx] != '*') {
- filter[idx++] = '*';
- }
- memcpy(filter + idx, filter_raw, slen);
- idx += slen;
- if (filter[idx - 1] != '*') {
- filter[idx++] = '*';
- }
- filter[idx] = '\0';
+ BLI_strncpy_ensure_pad(filter, filter_raw, '*', slen + 3);
}
RNA_PROP_BEGIN (dataptr, itemptr, prop)
@@ -2758,8 +2773,9 @@ typedef struct {
int end_idx; /* Index of last item to display + 1. */
} uiListLayoutdata;
-static void prepare_list(uiList *ui_list, int len, int activei, int rows, int maxrows, int columns,
- uiListLayoutdata *layoutdata)
+static void uilist_prepare(
+ uiList *ui_list, int len, int activei, int rows, int maxrows, int columns,
+ uiListLayoutdata *layoutdata)
{
uiListDyn *dyn_data = ui_list->dyn_data;
int activei_row, max_scroll;
@@ -2812,7 +2828,7 @@ static void prepare_list(uiList *ui_list, int len, int activei, int rows, int ma
layoutdata->end_idx = min_ii(layoutdata->start_idx + rows * columns, len);
}
-static void ui_list_resize_update_cb(bContext *UNUSED(C), void *arg1, void *UNUSED(arg2))
+static void uilist_resize_update_cb(bContext *UNUSED(C), void *arg1, void *UNUSED(arg2))
{
uiList *ui_list = arg1;
uiListDyn *dyn_data = ui_list->dyn_data;
@@ -2827,9 +2843,28 @@ static void ui_list_resize_update_cb(bContext *UNUSED(C), void *arg1, void *UNUS
}
}
-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)
+static void *uilist_item_use_dynamic_tooltip(PointerRNA *itemptr, const char *propname)
+{
+ if (propname && propname[0] && itemptr && itemptr->data) {
+ PropertyRNA *prop = RNA_struct_find_property(itemptr, propname);
+
+ if (prop && (RNA_property_type(prop) == PROP_STRING)) {
+ return RNA_property_string_get_alloc(itemptr, prop, NULL, 0, NULL);
+ }
+ }
+ return NULL;
+}
+
+static char *uilist_item_tooltip_func(bContext *UNUSED(C), void *argN, const char *tip)
+{
+ char *dyn_tooltip = argN;
+ return BLI_sprintfN("%s - %s", tip, dyn_tooltip);
+}
+
+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,
+ const char *item_dyntip_propname, int rows, int maxrows, int layout_type, int columns)
{
uiListType *ui_list_type;
uiList *ui_list = NULL;
@@ -2856,7 +2891,7 @@ void uiTemplateList(uiLayout *layout, bContext *C, const char *listtype_name, co
/* validate arguments */
/* Forbid default UI_UL_DEFAULT_CLASS_NAME list class without a custom list_id! */
- if (!strcmp(UI_UL_DEFAULT_CLASS_NAME, listtype_name) && !(list_id && list_id[0])) {
+ if (STREQ(UI_UL_DEFAULT_CLASS_NAME, listtype_name) && !(list_id && list_id[0])) {
RNA_warning("template_list using default '%s' UIList class must provide a custom list_id",
UI_UL_DEFAULT_CLASS_NAME);
return;
@@ -3037,25 +3072,30 @@ void uiTemplateList(uiLayout *layout, bContext *C, const char *listtype_name, co
col = uiLayoutColumn(row, true);
/* init numbers */
- prepare_list(ui_list, len, activei, rows, maxrows, 1, &layoutdata);
+ uilist_prepare(ui_list, len, activei, rows, maxrows, 1, &layoutdata);
if (dataptr->data && prop) {
/* create list items */
for (i = layoutdata.start_idx; i < layoutdata.end_idx; i++) {
PointerRNA *itemptr = &items_ptr[i].item;
+ void *dyntip_data;
int org_i = items_ptr[i].org_idx;
int flt_flag = items_ptr[i].flt_flag;
subblock = uiLayoutGetBlock(col);
overlap = uiLayoutOverlap(col);
- uiBlockSetFlag(subblock, UI_BLOCK_LIST_ITEM);
+ UI_block_flag_enable(subblock, UI_BLOCK_LIST_ITEM);
/* list item behind label & other buttons */
sub = uiLayoutRow(overlap, false);
- but = uiDefButR_prop(subblock, LISTROW, 0, "", 0, 0, UI_UNIT_X * 10, UI_UNIT_Y,
- active_dataptr, activeprop, 0, 0, org_i, 0, 0, TIP_("Double click to rename"));
+ but = uiDefButR_prop(subblock, UI_BTYPE_LISTROW, 0, "", 0, 0, UI_UNIT_X * 10, UI_UNIT_Y,
+ active_dataptr, activeprop, 0, 0, org_i, 0, 0,
+ TIP_("Double click to rename"));
+ if ((dyntip_data = uilist_item_use_dynamic_tooltip(itemptr, item_dyntip_propname))) {
+ UI_but_func_tooltip_set(but, uilist_item_tooltip_func, dyntip_data);
+ }
sub = uiLayoutRow(overlap, false);
@@ -3070,7 +3110,7 @@ void uiTemplateList(uiLayout *layout, bContext *C, const char *listtype_name, co
ui_layout_list_set_labels_active(sub);
}
- uiBlockClearFlag(subblock, UI_BLOCK_LIST_ITEM);
+ UI_block_flag_disable(subblock, UI_BLOCK_LIST_ITEM);
}
}
@@ -3082,7 +3122,7 @@ void uiTemplateList(uiLayout *layout, bContext *C, const char *listtype_name, co
/* add scrollbar */
if (len > layoutdata.visual_items) {
col = uiLayoutColumn(row, false);
- uiDefButI(block, SCROLL, 0, "", 0, 0, UI_UNIT_X * 0.75, UI_UNIT_Y * dyn_data->visual_height,
+ uiDefButI(block, UI_BTYPE_SCROLL, 0, "", 0, 0, UI_UNIT_X * 0.75, UI_UNIT_Y * dyn_data->visual_height,
&ui_list->list_scroll, 0, dyn_data->height - dyn_data->visual_height,
dyn_data->visual_height, 0, "");
}
@@ -3108,10 +3148,10 @@ void uiTemplateList(uiLayout *layout, bContext *C, const char *listtype_name, co
/* next/prev button */
BLI_snprintf(numstr, sizeof(numstr), "%d :", dyn_data->items_shown);
- but = uiDefIconTextButR_prop(block, NUM, 0, 0, numstr, 0, 0, UI_UNIT_X * 5, UI_UNIT_Y,
+ but = uiDefIconTextButR_prop(block, UI_BTYPE_NUM, 0, 0, numstr, 0, 0, UI_UNIT_X * 5, UI_UNIT_Y,
active_dataptr, activeprop, 0, 0, 0, 0, 0, "");
if (dyn_data->items_shown == 0)
- uiButSetFlag(but, UI_BUT_DISABLED);
+ UI_but_flag_enable(but, UI_BUT_DISABLED);
break;
case UILST_LAYOUT_GRID:
box = uiLayoutListBox(layout, ui_list, dataptr, prop, active_dataptr, activeprop);
@@ -3120,7 +3160,7 @@ void uiTemplateList(uiLayout *layout, bContext *C, const char *listtype_name, co
col = uiLayoutColumn(row, true);
subrow = NULL; /* Quite gcc warning! */
- prepare_list(ui_list, len, activei, rows, maxrows, columns, &layoutdata);
+ uilist_prepare(ui_list, len, activei, rows, maxrows, columns, &layoutdata);
if (dataptr->data && prop) {
/* create list items */
@@ -3136,14 +3176,14 @@ void uiTemplateList(uiLayout *layout, bContext *C, const char *listtype_name, co
subblock = uiLayoutGetBlock(subrow);
overlap = uiLayoutOverlap(subrow);
- uiBlockSetFlag(subblock, UI_BLOCK_LIST_ITEM);
+ UI_block_flag_enable(subblock, UI_BLOCK_LIST_ITEM);
/* list item behind label & other buttons */
sub = uiLayoutRow(overlap, false);
- but = uiDefButR_prop(subblock, LISTROW, 0, "", 0, 0, UI_UNIT_X * 10, UI_UNIT_Y,
+ but = uiDefButR_prop(subblock, UI_BTYPE_LISTROW, 0, "", 0, 0, UI_UNIT_X * 10, UI_UNIT_Y,
active_dataptr, activeprop, 0, 0, org_i, 0, 0, NULL);
- uiButSetDrawFlag(but, UI_BUT_NO_TOOLTIP);
+ UI_but_drawflag_enable(but, UI_BUT_NO_TOOLTIP);
sub = uiLayoutRow(overlap, false);
@@ -3156,7 +3196,7 @@ void uiTemplateList(uiLayout *layout, bContext *C, const char *listtype_name, co
ui_layout_list_set_labels_active(sub);
}
- uiBlockClearFlag(subblock, UI_BLOCK_LIST_ITEM);
+ UI_block_flag_disable(subblock, UI_BLOCK_LIST_ITEM);
}
}
@@ -3170,8 +3210,8 @@ void uiTemplateList(uiLayout *layout, bContext *C, const char *listtype_name, co
/* add scrollbar */
if (len > layoutdata.visual_items) {
- col = uiLayoutColumn(row, false);
- uiDefButI(block, SCROLL, 0, "", 0, 0, UI_UNIT_X * 0.75, UI_UNIT_Y * dyn_data->visual_height,
+ /* col = */ uiLayoutColumn(row, false);
+ uiDefButI(block, UI_BTYPE_SCROLL, 0, "", 0, 0, UI_UNIT_X * 0.75, UI_UNIT_Y * dyn_data->visual_height,
&ui_list->list_scroll, 0, dyn_data->height - dyn_data->visual_height,
dyn_data->visual_height, 0, "");
}
@@ -3179,8 +3219,8 @@ void uiTemplateList(uiLayout *layout, bContext *C, const char *listtype_name, co
}
if (glob) {
- /* About GRIP drag-resize:
- * We can't directly use results from GRIP button, since we have a rather complex behavior here
+ /* About UI_BTYPE_GRIP drag-resize:
+ * We can't directly use results from a grip button, since we have a rather complex behavior here
* (sizing by discrete steps and, overall, autosize feature).
* Since we *never* know whether we are grip-resizing or not (because there is no callback for when a
* button enters/leaves its "edit mode"), we use the fact that grip-controlled value (dyn_data->resize)
@@ -3193,37 +3233,37 @@ void uiTemplateList(uiLayout *layout, bContext *C, const char *listtype_name, co
row = uiLayoutRow(glob, true);
subblock = uiLayoutGetBlock(row);
- uiBlockSetEmboss(subblock, UI_EMBOSSN);
+ UI_block_emboss_set(subblock, UI_EMBOSS_NONE);
if (ui_list->filter_flag & UILST_FLT_SHOW) {
- but = uiDefIconButBitI(subblock, TOG, UILST_FLT_SHOW, 0, ICON_DISCLOSURE_TRI_DOWN, 0, 0,
+ but = uiDefIconButBitI(subblock, UI_BTYPE_TOGGLE, UILST_FLT_SHOW, 0, ICON_DISCLOSURE_TRI_DOWN, 0, 0,
UI_UNIT_X, UI_UNIT_Y * 0.5f, &(ui_list->filter_flag), 0, 0, 0, 0,
TIP_("Hide filtering options"));
- uiButClearFlag(but, UI_BUT_UNDO); /* skip undo on screen buttons */
+ UI_but_flag_disable(but, UI_BUT_UNDO); /* skip undo on screen buttons */
- but = uiDefIconButI(subblock, GRIP, 0, ICON_GRIP, 0, 0, UI_UNIT_X * 10.0f, UI_UNIT_Y * 0.5f,
+ but = uiDefIconButI(subblock, UI_BTYPE_GRIP, 0, ICON_GRIP, 0, 0, UI_UNIT_X * 10.0f, UI_UNIT_Y * 0.5f,
&dyn_data->resize, 0.0, 0.0, 0, 0, "");
- uiButSetFunc(but, ui_list_resize_update_cb, ui_list, NULL);
+ UI_but_func_set(but, uilist_resize_update_cb, ui_list, NULL);
- uiBlockSetEmboss(subblock, UI_EMBOSS);
+ UI_block_emboss_set(subblock, UI_EMBOSS);
col = uiLayoutColumn(glob, false);
subblock = uiLayoutGetBlock(col);
- uiDefBut(subblock, SEPR, 0, "", 0, 0, UI_UNIT_X, UI_UNIT_Y * 0.05f, NULL, 0.0, 0.0, 0, 0, "");
+ uiDefBut(subblock, UI_BTYPE_SEPR, 0, "", 0, 0, UI_UNIT_X, UI_UNIT_Y * 0.05f, NULL, 0.0, 0.0, 0, 0, "");
draw_filter(ui_list, C, col);
}
else {
- but = uiDefIconButBitI(subblock, TOG, UILST_FLT_SHOW, 0, ICON_DISCLOSURE_TRI_RIGHT, 0, 0,
+ but = uiDefIconButBitI(subblock, UI_BTYPE_TOGGLE, UILST_FLT_SHOW, 0, ICON_DISCLOSURE_TRI_RIGHT, 0, 0,
UI_UNIT_X, UI_UNIT_Y * 0.5f, &(ui_list->filter_flag), 0, 0, 0, 0,
TIP_("Show filtering options"));
- uiButClearFlag(but, UI_BUT_UNDO); /* skip undo on screen buttons */
+ UI_but_flag_disable(but, UI_BUT_UNDO); /* skip undo on screen buttons */
- but = uiDefIconButI(subblock, GRIP, 0, ICON_GRIP, 0, 0, UI_UNIT_X * 10.0f, UI_UNIT_Y * 0.5f,
+ but = uiDefIconButI(subblock, UI_BTYPE_GRIP, 0, ICON_GRIP, 0, 0, UI_UNIT_X * 10.0f, UI_UNIT_Y * 0.5f,
&dyn_data->resize, 0.0, 0.0, 0, 0, "");
- uiButSetFunc(but, ui_list_resize_update_cb, ui_list, NULL);
+ UI_but_func_set(but, uilist_resize_update_cb, ui_list, NULL);
- uiBlockSetEmboss(subblock, UI_EMBOSS);
+ UI_block_emboss_set(subblock, UI_EMBOSS);
}
}
@@ -3244,42 +3284,42 @@ static void operator_call_cb(bContext *C, void *UNUSED(arg1), void *arg2)
static void operator_search_cb(const bContext *C, void *UNUSED(arg), const char *str, uiSearchItems *items)
{
- GHashIterator *iter = WM_operatortype_iter();
+ GHashIterator iter;
- for (; !BLI_ghashIterator_done(iter); BLI_ghashIterator_step(iter)) {
- wmOperatorType *ot = BLI_ghashIterator_getValue(iter);
+ for (WM_operatortype_iter(&iter); !BLI_ghashIterator_done(&iter); BLI_ghashIterator_step(&iter)) {
+ wmOperatorType *ot = BLI_ghashIterator_getValue(&iter);
+ const char *ot_ui_name = CTX_IFACE_(ot->translation_context, ot->name);
if ((ot->flag & OPTYPE_INTERNAL) && (G.debug & G_DEBUG_WM) == 0)
continue;
- if (BLI_strcasestr(ot->name, str)) {
+ if (BLI_strcasestr(ot_ui_name, str)) {
if (WM_operator_poll((bContext *)C, ot)) {
char name[256];
- int len = strlen(ot->name);
+ int len = strlen(ot_ui_name);
/* display name for menu, can hold hotkey */
- BLI_strncpy(name, ot->name, sizeof(name));
+ BLI_strncpy(name, ot_ui_name, sizeof(name));
/* check for hotkey */
if (len < sizeof(name) - 6) {
if (WM_key_event_operator_string(C, ot->idname, WM_OP_EXEC_DEFAULT, NULL, true,
- &name[len + 1], sizeof(name) - len - 1))
+ sizeof(name) - len - 1, &name[len + 1]))
{
name[len] = UI_SEP_CHAR;
}
}
- if (false == uiSearchItemAdd(items, name, ot, 0))
+ if (false == UI_search_item_add(items, name, ot, 0))
break;
}
}
}
- BLI_ghashIterator_free(iter);
}
-void uiOperatorSearch_But(uiBut *but)
+void UI_but_func_operator_search(uiBut *but)
{
- uiButSetSearchFunc(but, operator_search_cb, NULL, operator_call_cb, NULL);
+ UI_but_func_search_set(but, operator_search_cb, NULL, operator_call_cb, NULL);
}
void uiTemplateOperatorSearch(uiLayout *layout)
@@ -3289,10 +3329,10 @@ void uiTemplateOperatorSearch(uiLayout *layout)
static char search[256] = "";
block = uiLayoutGetBlock(layout);
- uiBlockSetCurLayout(block, layout);
+ UI_block_layout_set_current(block, layout);
but = uiDefSearchBut(block, search, 0, ICON_VIEWZOOM, sizeof(search), 0, 0, UI_UNIT_X * 6, UI_UNIT_Y, 0, 0, "");
- uiOperatorSearch_But(but);
+ UI_but_func_operator_search(but);
}
/************************* Running Jobs Template **************************/
@@ -3303,7 +3343,8 @@ void uiTemplateOperatorSearch(uiLayout *layout)
#define B_STOPCOMPO 4
#define B_STOPSEQ 5
#define B_STOPCLIP 6
-#define B_STOPOTHER 7
+#define B_STOPFILE 7
+#define B_STOPOTHER 8
static void do_running_jobs(bContext *C, void *UNUSED(arg), int event)
{
@@ -3326,6 +3367,9 @@ static void do_running_jobs(bContext *C, void *UNUSED(arg), int event)
case B_STOPCLIP:
WM_jobs_stop(CTX_wm_manager(C), CTX_wm_area(C), NULL);
break;
+ case B_STOPFILE:
+ WM_jobs_stop(CTX_wm_manager(C), CTX_wm_area(C), NULL);
+ break;
case B_STOPOTHER:
G.is_break = true;
break;
@@ -3342,9 +3386,9 @@ void uiTemplateRunningJobs(uiLayout *layout, bContext *C)
int handle_event;
block = uiLayoutGetBlock(layout);
- uiBlockSetCurLayout(block, layout);
+ UI_block_layout_set_current(block, layout);
- uiBlockSetHandleFunc(block, do_running_jobs, NULL);
+ UI_block_func_handle_set(block, do_running_jobs, NULL);
if (sa->spacetype == SPACE_SEQ) {
if (WM_jobs_test(wm, sa, WM_JOB_TYPE_ANY))
@@ -3356,6 +3400,12 @@ void uiTemplateRunningJobs(uiLayout *layout, bContext *C)
owner = sa;
handle_event = B_STOPCLIP;
}
+ else if (sa->spacetype == SPACE_FILE) {
+ if (WM_jobs_test(wm, sa, WM_JOB_TYPE_FILESEL_READDIR)) {
+ owner = sa;
+ }
+ handle_event = B_STOPFILE;
+ }
else {
Scene *scene;
/* another scene can be rendering too, for example via compositor */
@@ -3394,18 +3444,18 @@ void uiTemplateRunningJobs(uiLayout *layout, bContext *C)
ui_abs = uiLayoutAbsolute(layout, false);
(void)ui_abs; /* UNUSED */
- uiDefIconBut(block, BUT, handle_event, ICON_PANEL_CLOSE, 0, UI_UNIT_Y * 0.1, UI_UNIT_X * 0.8, UI_UNIT_Y * 0.8,
+ uiDefIconBut(block, UI_BTYPE_BUT, handle_event, ICON_PANEL_CLOSE, 0, UI_UNIT_Y * 0.1, UI_UNIT_X * 0.8, UI_UNIT_Y * 0.8,
NULL, 0.0f, 0.0f, 0, 0, TIP_("Stop this job"));
- uiDefBut(block, PROGRESSBAR, 0, WM_jobs_name(wm, owner),
+ uiDefBut(block, UI_BTYPE_PROGRESS_BAR, 0, WM_jobs_name(wm, owner),
UI_UNIT_X, 0, UI_UNIT_X * 5.0f, UI_UNIT_Y, NULL, 0.0f, 0.0f, WM_jobs_progress(wm, owner), 0, TIP_("Progress"));
uiLayoutRow(layout, false);
}
if (WM_jobs_test(wm, screen, WM_JOB_TYPE_SCREENCAST))
- uiDefIconTextBut(block, BUT, B_STOPCAST, ICON_CANCEL, IFACE_("Capture"), 0, 0, UI_UNIT_X * 4.25f, UI_UNIT_Y,
+ uiDefIconTextBut(block, UI_BTYPE_BUT, B_STOPCAST, ICON_CANCEL, IFACE_("Capture"), 0, 0, UI_UNIT_X * 4.25f, UI_UNIT_Y,
NULL, 0.0f, 0.0f, 0, 0, TIP_("Stop screencast"));
if (screen->animtimer)
- uiDefIconTextBut(block, BUT, B_STOPANIM, ICON_CANCEL, IFACE_("Anim Player"), 0, 0, UI_UNIT_X * 5.0f, UI_UNIT_Y,
+ uiDefIconTextBut(block, UI_BTYPE_BUT, B_STOPANIM, ICON_CANCEL, IFACE_("Anim Player"), 0, 0, UI_UNIT_X * 5.0f, UI_UNIT_Y,
NULL, 0.0f, 0.0f, 0, 0, TIP_("Stop animation playback"));
}
@@ -3420,7 +3470,7 @@ void uiTemplateReportsBanner(uiLayout *layout, bContext *C)
uiLayout *ui_abs;
uiBlock *block;
uiBut *but;
- uiStyle *style = UI_GetStyle();
+ uiStyle *style = UI_style_get();
int width;
int icon;
@@ -3434,42 +3484,43 @@ void uiTemplateReportsBanner(uiLayout *layout, bContext *C)
ui_abs = uiLayoutAbsolute(layout, false);
block = uiLayoutGetBlock(ui_abs);
- width = BLF_width(style->widget.uifont_id, report->message, report->len);
+ UI_fontstyle_set(&style->widgetlabel);
+ width = BLF_width(style->widgetlabel.uifont_id, report->message, report->len);
width = min_ii((int)(rti->widthfac * width), width);
width = max_ii(width, 10);
/* make a box around the report to make it stand out */
- uiBlockBeginAlign(block);
- but = uiDefBut(block, ROUNDBOX, 0, "", 0, 0, UI_UNIT_X + 10, UI_UNIT_Y, NULL, 0.0f, 0.0f, 0, 0, "");
- /* set the report's bg color in but->col - ROUNDBOX feature */
+ UI_block_align_begin(block);
+ but = uiDefBut(block, UI_BTYPE_ROUNDBOX, 0, "", 0, 0, UI_UNIT_X + 10, UI_UNIT_Y, NULL, 0.0f, 0.0f, 0, 0, "");
+ /* set the report's bg color in but->col - UI_BTYPE_ROUNDBOX feature */
rgb_float_to_uchar(but->col, rti->col);
but->col[3] = 255;
- but = uiDefBut(block, ROUNDBOX, 0, "", UI_UNIT_X + 10, 0, UI_UNIT_X + width, UI_UNIT_Y,
+ but = uiDefBut(block, UI_BTYPE_ROUNDBOX, 0, "", UI_UNIT_X + 10, 0, UI_UNIT_X + width, UI_UNIT_Y,
NULL, 0.0f, 0.0f, 0, 0, "");
but->col[0] = but->col[1] = but->col[2] = FTOCHAR(rti->grayscale);
but->col[3] = 255;
- uiBlockEndAlign(block);
+ UI_block_align_end(block);
/* icon and report message on top */
- icon = uiIconFromReportType(report->type);
+ icon = UI_icon_from_report_type(report->type);
/* XXX: temporary operator to dump all reports to a text block, but only if more than 1 report
* to be shown instead of icon when appropriate...
*/
- uiBlockSetEmboss(block, UI_EMBOSSN);
+ UI_block_emboss_set(block, UI_EMBOSS_NONE);
if (reports->list.first != reports->list.last)
- uiDefIconButO(block, BUT, "UI_OT_reports_to_textblock", WM_OP_INVOKE_REGION_WIN, icon, 2, 0, UI_UNIT_X,
+ uiDefIconButO(block, UI_BTYPE_BUT, "UI_OT_reports_to_textblock", WM_OP_INVOKE_REGION_WIN, icon, 2, 0, UI_UNIT_X,
UI_UNIT_Y, TIP_("Click to see the remaining reports in text block: 'Recent Reports'"));
else
- uiDefIconBut(block, LABEL, 0, icon, 2, 0, UI_UNIT_X, UI_UNIT_Y, NULL, 0.0f, 0.0f, 0, 0, "");
+ uiDefIconBut(block, UI_BTYPE_LABEL, 0, icon, 2, 0, UI_UNIT_X, UI_UNIT_Y, NULL, 0.0f, 0.0f, 0, 0, "");
- uiBlockSetEmboss(block, UI_EMBOSS);
+ UI_block_emboss_set(block, UI_EMBOSS);
- uiDefBut(block, LABEL, 0, report->message, UI_UNIT_X + 10, 0, UI_UNIT_X + width, UI_UNIT_Y,
+ uiDefBut(block, UI_BTYPE_LABEL, 0, report->message, UI_UNIT_X + 10, 0, UI_UNIT_X + width, UI_UNIT_Y,
NULL, 0.0f, 0.0f, 0, 0, "");
}
@@ -3518,11 +3569,11 @@ static void template_keymap_item_properties(uiLayout *layout, const char *title,
if (is_set) {
/* unset operator */
uiBlock *block = uiLayoutGetBlock(row);
- uiBlockSetEmboss(block, UI_EMBOSSN);
- but = uiDefIconButO(block, BUT, "UI_OT_unset_property_button", WM_OP_EXEC_DEFAULT, ICON_X, 0, 0, UI_UNIT_X, UI_UNIT_Y, NULL);
+ UI_block_emboss_set(block, UI_EMBOSS_NONE);
+ but = uiDefIconButO(block, UI_BTYPE_BUT, "UI_OT_unset_property_button", WM_OP_EXEC_DEFAULT, ICON_X, 0, 0, UI_UNIT_X, UI_UNIT_Y, NULL);
but->rnapoin = *ptr;
but->rnaprop = prop;
- uiBlockSetEmboss(block, UI_EMBOSS);
+ UI_block_emboss_set(block, UI_EMBOSS);
}
}
RNA_STRUCT_END;
@@ -3542,7 +3593,7 @@ void uiTemplateKeymapItemProperties(uiLayout *layout, PointerRNA *ptr)
for (; but; but = but->next) {
/* operator buttons may store props for use (file selector, [#36492]) */
if (but->rnaprop) {
- uiButSetFunc(but, keymap_item_modified, ptr->data, NULL);
+ UI_but_func_set(but, keymap_item_modified, ptr->data, NULL);
}
}
}
@@ -3565,8 +3616,7 @@ void uiTemplateColorspaceSettings(uiLayout *layout, PointerRNA *ptr, const char
colorspace_settings_ptr = RNA_property_pointer_get(ptr, prop);
- uiItemL(layout, IFACE_("Input Color Space:"), ICON_NONE);
- uiItemR(layout, &colorspace_settings_ptr, "name", 0, "", ICON_NONE);
+ uiItemR(layout, &colorspace_settings_ptr, "name", 0, IFACE_("Color Space"), ICON_NONE);
}
void uiTemplateColormanagedViewSettings(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr, const char *propname)
@@ -3617,15 +3667,15 @@ static uiBlock *component_menu(bContext *C, ARegion *ar, void *args_v)
uiBlock *block;
uiLayout *layout;
- block = uiBeginBlock(C, ar, __func__, UI_EMBOSS);
- uiBlockSetFlag(block, UI_BLOCK_KEEP_OPEN);
+ block = UI_block_begin(C, ar, __func__, UI_EMBOSS);
+ UI_block_flag_enable(block, UI_BLOCK_KEEP_OPEN);
- layout = uiLayoutColumn(uiBlockLayout(block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, 0, 0, UI_UNIT_X * 6, UI_UNIT_Y, 0, UI_GetStyle()), 0);
+ layout = uiLayoutColumn(UI_block_layout(block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, 0, 0, UI_UNIT_X * 6, UI_UNIT_Y, 0, UI_style_get()), 0);
uiItemR(layout, &args->ptr, args->propname, UI_ITEM_R_EXPAND, "", ICON_NONE);
- uiBoundsBlock(block, 6);
- uiBlockSetDirection(block, UI_DOWN);
+ UI_block_bounds_set_normal(block, 6);
+ UI_block_direction_set(block, UI_DIR_DOWN);
return block;
}
@@ -3639,7 +3689,7 @@ void uiTemplateComponentMenu(uiLayout *layout, PointerRNA *ptr, const char *prop
BLI_strncpy(args->propname, propname, sizeof(args->propname));
block = uiLayoutGetBlock(layout);
- uiBlockBeginAlign(block);
+ UI_block_align_begin(block);
but = uiDefBlockButN(block, component_menu, args, name, 0, 0, UI_UNIT_X * 6, UI_UNIT_Y, "");
/* set rna directly, uiDefBlockButN doesn't do this */
@@ -3647,7 +3697,7 @@ void uiTemplateComponentMenu(uiLayout *layout, PointerRNA *ptr, const char *prop
but->rnaprop = RNA_struct_find_property(ptr, propname);
but->rnaindex = 0;
- uiBlockEndAlign(block);
+ UI_block_align_end(block);
}
/************************* Node Socket Icon **************************/
@@ -3658,14 +3708,14 @@ void uiTemplateNodeSocket(uiLayout *layout, bContext *UNUSED(C), float *color)
uiBut *but;
block = uiLayoutGetBlock(layout);
- uiBlockBeginAlign(block);
+ UI_block_align_begin(block);
/* XXX using explicit socket colors is not quite ideal.
* Eventually it should be possible to use theme colors for this purpose,
* but this requires a better design for extendable color palettes in user prefs.
*/
- but = uiDefBut(block, NODESOCKET, 0, "", 0, 0, UI_UNIT_X, UI_UNIT_Y, NULL, 0, 0, 0, 0, "");
+ but = uiDefBut(block, UI_BTYPE_NODE_SOCKET, 0, "", 0, 0, UI_UNIT_X, UI_UNIT_Y, NULL, 0, 0, 0, 0, "");
rgba_float_to_uchar(but->col, color);
- uiBlockEndAlign(block);
+ UI_block_align_end(block);
}
diff --git a/source/blender/editors/interface/interface_utils.c b/source/blender/editors/interface/interface_utils.c
index 008ea84b607..1d51c0588b6 100644
--- a/source/blender/editors/interface/interface_utils.c
+++ b/source/blender/editors/interface/interface_utils.c
@@ -41,7 +41,7 @@
#include "BLI_string.h"
#include "BLI_listbase.h"
-#include "BLF_translation.h"
+#include "BLT_translation.h"
#include "BKE_report.h"
@@ -52,6 +52,9 @@
#include "UI_interface.h"
#include "UI_resources.h"
+#include "WM_api.h"
+#include "WM_types.h"
+
#include "interface_intern.h"
@@ -70,11 +73,11 @@ uiBut *uiDefAutoButR(uiBlock *block, PointerRNA *ptr, PropertyRNA *prop, int ind
return NULL;
if (icon && name && name[0] == '\0')
- but = uiDefIconButR_prop(block, ICONTOG, 0, icon, x1, y1, x2, y2, ptr, prop, index, 0, 0, -1, -1, NULL);
+ but = uiDefIconButR_prop(block, UI_BTYPE_ICON_TOGGLE, 0, icon, x1, y1, x2, y2, ptr, prop, index, 0, 0, -1, -1, NULL);
else if (icon)
- but = uiDefIconTextButR_prop(block, ICONTOG, 0, icon, name, x1, y1, x2, y2, ptr, prop, index, 0, 0, -1, -1, NULL);
+ but = uiDefIconTextButR_prop(block, UI_BTYPE_ICON_TOGGLE, 0, icon, name, x1, y1, x2, y2, ptr, prop, index, 0, 0, -1, -1, NULL);
else
- but = uiDefButR_prop(block, OPTION, 0, name, x1, y1, x2, y2, ptr, prop, index, 0, 0, -1, -1, NULL);
+ but = uiDefButR_prop(block, UI_BTYPE_CHECKBOX, 0, name, x1, y1, x2, y2, ptr, prop, index, 0, 0, -1, -1, NULL);
break;
}
case PROP_INT:
@@ -83,30 +86,42 @@ uiBut *uiDefAutoButR(uiBlock *block, PointerRNA *ptr, PropertyRNA *prop, int ind
int arraylen = RNA_property_array_length(ptr, prop);
if (arraylen && index == -1) {
- if (ELEM(RNA_property_subtype(prop), PROP_COLOR, PROP_COLOR_GAMMA))
- but = uiDefButR_prop(block, COLOR, 0, name, x1, y1, x2, y2, ptr, prop, -1, 0, 0, -1, -1, NULL);
+ if (ELEM(RNA_property_subtype(prop), PROP_COLOR, PROP_COLOR_GAMMA)) {
+ but = uiDefButR_prop(block, UI_BTYPE_COLOR, 0, name, x1, y1, x2, y2, ptr, prop, -1, 0, 0, -1, -1, NULL);
+ }
+ else {
+ return NULL;
+ }
}
else if (RNA_property_subtype(prop) == PROP_PERCENTAGE || RNA_property_subtype(prop) == PROP_FACTOR)
- but = uiDefButR_prop(block, NUMSLI, 0, name, x1, y1, x2, y2, ptr, prop, index, 0, 0, -1, -1, NULL);
+ but = uiDefButR_prop(block, UI_BTYPE_NUM_SLIDER, 0, name, x1, y1, x2, y2, ptr, prop, index, 0, 0, -1, -1, NULL);
else
- but = uiDefButR_prop(block, NUM, 0, name, x1, y1, x2, y2, ptr, prop, index, 0, 0, -1, -1, NULL);
+ but = uiDefButR_prop(block, UI_BTYPE_NUM, 0, name, x1, y1, x2, y2, ptr, prop, index, 0, 0, -1, -1, NULL);
+
+ if (RNA_property_flag(prop) & PROP_TEXTEDIT_UPDATE) {
+ UI_but_flag_enable(but, UI_BUT_TEXTEDIT_UPDATE);
+ }
break;
}
case PROP_ENUM:
if (icon && name && name[0] == '\0')
- but = uiDefIconButR_prop(block, MENU, 0, icon, x1, y1, x2, y2, ptr, prop, index, 0, 0, -1, -1, NULL);
+ but = uiDefIconButR_prop(block, UI_BTYPE_MENU, 0, icon, x1, y1, x2, y2, ptr, prop, index, 0, 0, -1, -1, NULL);
else if (icon)
- but = uiDefIconTextButR_prop(block, MENU, 0, icon, NULL, x1, y1, x2, y2, ptr, prop, index, 0, 0, -1, -1, NULL);
+ but = uiDefIconTextButR_prop(block, UI_BTYPE_MENU, 0, icon, NULL, x1, y1, x2, y2, ptr, prop, index, 0, 0, -1, -1, NULL);
else
- but = uiDefButR_prop(block, MENU, 0, name, x1, y1, x2, y2, ptr, prop, index, 0, 0, -1, -1, NULL);
+ but = uiDefButR_prop(block, UI_BTYPE_MENU, 0, name, x1, y1, x2, y2, ptr, prop, index, 0, 0, -1, -1, NULL);
break;
case PROP_STRING:
if (icon && name && name[0] == '\0')
- but = uiDefIconButR_prop(block, TEX, 0, icon, x1, y1, x2, y2, ptr, prop, index, 0, 0, -1, -1, NULL);
+ but = uiDefIconButR_prop(block, UI_BTYPE_TEXT, 0, icon, x1, y1, x2, y2, ptr, prop, index, 0, 0, -1, -1, NULL);
else if (icon)
- but = uiDefIconTextButR_prop(block, TEX, 0, icon, name, x1, y1, x2, y2, ptr, prop, index, 0, 0, -1, -1, NULL);
+ but = uiDefIconTextButR_prop(block, UI_BTYPE_TEXT, 0, icon, name, x1, y1, x2, y2, ptr, prop, index, 0, 0, -1, -1, NULL);
else
- but = uiDefButR_prop(block, TEX, 0, name, x1, y1, x2, y2, ptr, prop, index, 0, 0, -1, -1, NULL);
+ but = uiDefButR_prop(block, UI_BTYPE_TEXT, 0, name, x1, y1, x2, y2, ptr, prop, index, 0, 0, -1, -1, NULL);
+
+ if (RNA_property_flag(prop) & PROP_TEXTEDIT_UPDATE) {
+ UI_but_flag_enable(but, UI_BUT_TEXTEDIT_UPDATE);
+ }
break;
case PROP_POINTER:
{
@@ -119,15 +134,15 @@ uiBut *uiDefAutoButR(uiBlock *block, PointerRNA *ptr, PropertyRNA *prop, int ind
if (icon == ICON_DOT)
icon = 0;
- but = uiDefIconTextButR_prop(block, SEARCH_MENU, 0, icon, name, x1, y1, x2, y2, ptr, prop, index, 0, 0, -1, -1, NULL);
+ but = uiDefIconTextButR_prop(block, UI_BTYPE_SEARCH_MENU, 0, icon, name, x1, y1, x2, y2, ptr, prop, index, 0, 0, -1, -1, NULL);
break;
}
case PROP_COLLECTION:
{
char text[256];
BLI_snprintf(text, sizeof(text), IFACE_("%d items"), RNA_property_collection_length(ptr, prop));
- but = uiDefBut(block, LABEL, 0, text, x1, y1, x2, y2, NULL, 0, 0, 0, 0, NULL);
- uiButSetFlag(but, UI_BUT_DISABLED);
+ but = uiDefBut(block, UI_BTYPE_LABEL, 0, text, x1, y1, x2, y2, NULL, 0, 0, 0, 0, NULL);
+ UI_but_flag_enable(but, UI_BUT_DISABLED);
break;
}
default:
@@ -142,9 +157,10 @@ uiBut *uiDefAutoButR(uiBlock *block, PointerRNA *ptr, PropertyRNA *prop, int ind
* \a check_prop callback filters functions to avoid drawing certain properties,
* in cases where PROP_HIDDEN flag can't be used for a property.
*/
-int uiDefAutoButsRNA(uiLayout *layout, PointerRNA *ptr,
- bool (*check_prop)(PointerRNA *, PropertyRNA *),
- const char label_align)
+int uiDefAutoButsRNA(
+ uiLayout *layout, PointerRNA *ptr,
+ bool (*check_prop)(PointerRNA *, PropertyRNA *),
+ const char label_align)
{
uiLayout *split, *col;
int flag;
@@ -201,7 +217,7 @@ int uiDefAutoButsRNA(uiLayout *layout, PointerRNA *ptr,
/***************************** ID Utilities *******************************/
-int uiIconFromID(ID *id)
+int UI_icon_from_id(ID *id)
{
Object *ob;
PointerRNA ptr;
@@ -219,7 +235,7 @@ int uiIconFromID(ID *id)
if (ob->type == OB_EMPTY)
return ICON_EMPTY_DATA;
else
- return uiIconFromID(ob->data);
+ return UI_icon_from_id(ob->data);
}
/* otherwise get it through RNA, creating the pointer
@@ -230,7 +246,7 @@ int uiIconFromID(ID *id)
}
/* see: report_type_str */
-int uiIconFromReportType(int type)
+int UI_icon_from_report_type(int type)
{
if (type & RPT_ERROR_ALL)
return ICON_ERROR;
@@ -247,7 +263,7 @@ int uiIconFromReportType(int type)
/**
* Returns the best "UI" precision for given floating value, so that e.g. 10.000001 rather gets drawn as '10'...
*/
-int uiFloatPrecisionCalc(int prec, double value)
+int UI_calc_float_precision(int prec, double value)
{
static const double pow10_neg[UI_PRECISION_FLOAT_MAX + 1] = {1e0, 1e-1, 1e-2, 1e-3, 1e-4, 1e-5, 1e-6, 1e-7};
static const double max_pow = 10000000.0; /* pow(10, UI_PRECISION_FLOAT_MAX) */
@@ -297,6 +313,34 @@ int uiFloatPrecisionCalc(int prec, double value)
return prec;
}
+bool UI_but_online_manual_id(const uiBut *but, char *r_str, size_t maxlength)
+{
+ if (but->rnapoin.id.data && but->rnapoin.data && but->rnaprop) {
+ BLI_snprintf(r_str, maxlength, "%s.%s", RNA_struct_identifier(but->rnapoin.type),
+ RNA_property_identifier(but->rnaprop));
+ return true;
+ }
+ else if (but->optype) {
+ WM_operator_py_idname(r_str, but->optype->idname);
+ return true;
+ }
+
+ *r_str = '\0';
+ return false;
+}
+
+bool UI_but_online_manual_id_from_active(const struct bContext *C, char *r_str, size_t maxlength)
+{
+ uiBut *but = UI_context_active_but_get(C);
+
+ if (but) {
+ return UI_but_online_manual_id(but, r_str, maxlength);
+ }
+
+ *r_str = '\0';
+ return false;
+}
+
/* -------------------------------------------------------------------- */
/* Modal Button Store API */
@@ -390,6 +434,27 @@ void UI_butstore_unregister(uiButStore *bs_handle, uiBut **but_p)
}
/**
+ * Update the pointer for a registered button.
+ */
+bool UI_butstore_register_update(uiBlock *block, uiBut *but_dst, const uiBut *but_src)
+{
+ uiButStore *bs_handle;
+ bool found = false;
+
+ for (bs_handle = block->butstore.first; bs_handle; bs_handle = bs_handle->next) {
+ uiButStoreElem *bs_elem;
+ for (bs_elem = bs_handle->items.first; bs_elem; bs_elem = bs_elem->next) {
+ if (*bs_elem->but_p == but_src) {
+ *bs_elem->but_p = but_dst;
+ found = true;
+ }
+ }
+ }
+
+ return found;
+}
+
+/**
* NULL all pointers, don't free since the owner needs to be able to inspect.
*/
void UI_butstore_clear(uiBlock *block)
diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c
index 11b9b9c83cc..5d37f5c0fcf 100644
--- a/source/blender/editors/interface/interface_widgets.c
+++ b/source/blender/editors/interface/interface_widgets.c
@@ -27,7 +27,6 @@
* \ingroup edinterface
*/
-
#include <limits.h>
#include <stdlib.h>
#include <string.h>
@@ -56,19 +55,22 @@
#include "UI_interface.h"
#include "UI_interface_icons.h"
-
#include "interface_intern.h"
+#ifdef WITH_INPUT_IME
+# include "WM_types.h"
+#endif
+
/* icons are 80% of height of button (16 pixels inside 20 height) */
#define ICON_SIZE_FROM_BUTRECT(rect) (0.8f * BLI_rcti_size_y(rect))
/* ************** widget base functions ************** */
-/*
+/**
* - in: roundbox codes for corner types and radius
- * - return: array of [size][2][x,y] points, the edges of the roundbox, + UV coords
+ * - return: array of `[size][2][x, y]` points, the edges of the roundbox, + UV coords
*
* - draw black box with alpha 0 on exact button boundbox
- * - for ever AA step:
+ * - for every AA step:
* - draw the inner part for a round filled box, with color blend codes or texture coords
* - draw outline in outline color
* - draw outer part, bottom half, extruded 1 pixel to bottom, for emboss shadow
@@ -98,14 +100,14 @@ typedef struct uiWidgetBase {
float inner_v[WIDGET_SIZE_MAX][2];
float inner_uv[WIDGET_SIZE_MAX][2];
- bool inner, outline, emboss, shadedir;
+ bool draw_inner, draw_outline, draw_emboss, draw_shadedir;
uiWidgetTrias tria1;
uiWidgetTrias tria2;
} uiWidgetBase;
-/* uiWidgetType: for time being only for visual appearance,
+/** uiWidgetType: for time being only for visual appearance,
* later, a handling callback can be added too
*/
typedef struct uiWidgetType {
@@ -198,7 +200,7 @@ void ui_draw_anti_tria(float x1, float y1, float x2, float y2, float x3, float y
/* for each AA step */
for (j = 0; j < WIDGET_AA_JITTER; j++) {
- glTranslatef(jit[j][0], jit[j][1], 0.0f);
+ glTranslate2fv(jit[j]);
glDrawArrays(GL_TRIANGLES, 0, 3);
glTranslatef(-jit[j][0], -jit[j][1], 0.0f);
}
@@ -221,8 +223,8 @@ void ui_draw_anti_roundbox(int mode, float minx, float miny, float maxx, float m
glColor4fv(color);
for (j = 0; j < WIDGET_AA_JITTER; j++) {
- glTranslatef(jit[j][0], jit[j][1], 0.0f);
- uiDrawBox(mode, minx, miny, maxx, maxy, rad);
+ glTranslate2fv(jit[j]);
+ UI_draw_roundbox_gl_mode(mode, minx, miny, maxx, maxy, rad);
glTranslatef(-jit[j][0], -jit[j][1], 0.0f);
}
@@ -235,10 +237,10 @@ static void widget_init(uiWidgetBase *wtb)
wtb->tria1.tot = 0;
wtb->tria2.tot = 0;
- wtb->inner = 1;
- wtb->outline = 1;
- wtb->emboss = 1;
- wtb->shadedir = 1;
+ wtb->draw_inner = true;
+ wtb->draw_outline = true;
+ wtb->draw_emboss = true;
+ wtb->draw_shadedir = true;
}
/* helper call, makes shadow rect, with 'sun' above menu, so only shadow to left/right/bottom */
@@ -490,12 +492,12 @@ static void widget_draw_tria_ex(
minsize = min_ii(BLI_rcti_size_x(rect), BLI_rcti_size_y(rect));
/* center position and size */
- centx = (float)rect->xmin + 0.5f * minsize;
+ centx = (float)rect->xmin + 0.4f * minsize;
centy = (float)rect->ymin + 0.5f * minsize;
sizex = sizey = -0.5f * triasize * minsize;
if (where == 'r') {
- centx = (float)rect->xmax - 0.5f * minsize;
+ centx = (float)rect->xmax - 0.4f * minsize;
sizex = -sizex;
}
else if (where == 't') {
@@ -545,12 +547,12 @@ static void widget_menu_trias(uiWidgetTrias *tria, const rcti *rect)
{
float centx, centy, size;
int a;
-
+
/* center position and size */
centx = rect->xmax - 0.32f * BLI_rcti_size_y(rect);
centy = rect->ymin + 0.50f * BLI_rcti_size_y(rect);
- size = 0.4f * (float)BLI_rcti_size_y(rect);
-
+ size = 0.4f * BLI_rcti_size_y(rect);
+
for (a = 0; a < 6; a++) {
tria->vec[a][0] = size * menu_tria_vert[a][0] + centx;
tria->vec[a][1] = size * menu_tria_vert[a][1] + centy;
@@ -583,7 +585,6 @@ static void widget_check_trias(uiWidgetTrias *tria, const rcti *rect)
/* prepares shade colors */
static void shadecolors4(char coltop[4], char coldown[4], const char *color, short shadetop, short shadedown)
{
-
coltop[0] = CLAMPIS(color[0] + shadetop, 0, 255);
coltop[1] = CLAMPIS(color[1] + shadetop, 0, 255);
coltop[2] = CLAMPIS(color[2] + shadetop, 0, 255);
@@ -600,42 +601,42 @@ static void round_box_shade_col4_r(unsigned char r_col[4], const char col1[4], c
const int faci = FTOCHAR(fac);
const int facm = 255 - faci;
- r_col[0] = (faci * col1[0] + facm * col2[0]) >> 8;
- r_col[1] = (faci * col1[1] + facm * col2[1]) >> 8;
- r_col[2] = (faci * col1[2] + facm * col2[2]) >> 8;
- r_col[3] = (faci * col1[3] + facm * col2[3]) >> 8;
+ r_col[0] = (faci * col1[0] + facm * col2[0]) / 256;
+ r_col[1] = (faci * col1[1] + facm * col2[1]) / 256;
+ r_col[2] = (faci * col1[2] + facm * col2[2]) / 256;
+ r_col[3] = (faci * col1[3] + facm * col2[3]) / 256;
}
-static void widget_verts_to_quad_strip(uiWidgetBase *wtb, const int totvert, float quad_strip[WIDGET_SIZE_MAX * 2 + 2][2])
+static void widget_verts_to_triangle_strip(uiWidgetBase *wtb, const int totvert, float triangle_strip[WIDGET_SIZE_MAX * 2 + 2][2])
{
int a;
for (a = 0; a < totvert; a++) {
- copy_v2_v2(quad_strip[a * 2], wtb->outer_v[a]);
- copy_v2_v2(quad_strip[a * 2 + 1], wtb->inner_v[a]);
+ copy_v2_v2(triangle_strip[a * 2], wtb->outer_v[a]);
+ copy_v2_v2(triangle_strip[a * 2 + 1], wtb->inner_v[a]);
}
- copy_v2_v2(quad_strip[a * 2], wtb->outer_v[0]);
- copy_v2_v2(quad_strip[a * 2 + 1], wtb->inner_v[0]);
+ copy_v2_v2(triangle_strip[a * 2], wtb->outer_v[0]);
+ copy_v2_v2(triangle_strip[a * 2 + 1], wtb->inner_v[0]);
}
-static void widget_verts_to_quad_strip_open(uiWidgetBase *wtb, const int totvert, float quad_strip[WIDGET_SIZE_MAX * 2][2])
+static void widget_verts_to_triangle_strip_open(uiWidgetBase *wtb, const int totvert, float triangle_strip[WIDGET_SIZE_MAX * 2][2])
{
int a;
for (a = 0; a < totvert; a++) {
- quad_strip[a * 2][0] = wtb->outer_v[a][0];
- quad_strip[a * 2][1] = wtb->outer_v[a][1];
- quad_strip[a * 2 + 1][0] = wtb->outer_v[a][0];
- quad_strip[a * 2 + 1][1] = wtb->outer_v[a][1] - 1.0f;
+ triangle_strip[a * 2][0] = wtb->outer_v[a][0];
+ triangle_strip[a * 2][1] = wtb->outer_v[a][1];
+ triangle_strip[a * 2 + 1][0] = wtb->outer_v[a][0];
+ triangle_strip[a * 2 + 1][1] = wtb->outer_v[a][1] - 1.0f;
}
}
static void widgetbase_outline(uiWidgetBase *wtb)
{
- float quad_strip[WIDGET_SIZE_MAX * 2 + 2][2]; /* + 2 because the last pair is wrapped */
- widget_verts_to_quad_strip(wtb, wtb->totvert, quad_strip);
+ float triangle_strip[WIDGET_SIZE_MAX * 2 + 2][2]; /* + 2 because the last pair is wrapped */
+ widget_verts_to_triangle_strip(wtb, wtb->totvert, triangle_strip);
glEnableClientState(GL_VERTEX_ARRAY);
- glVertexPointer(2, GL_FLOAT, 0, quad_strip);
- glDrawArrays(GL_QUAD_STRIP, 0, wtb->totvert * 2 + 2);
+ glVertexPointer(2, GL_FLOAT, 0, triangle_strip);
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, wtb->totvert * 2 + 2);
glDisableClientState(GL_VERTEX_ARRAY);
}
@@ -646,7 +647,7 @@ static void widgetbase_draw(uiWidgetBase *wtb, uiWidgetColors *wcol)
glEnable(GL_BLEND);
/* backdrop non AA */
- if (wtb->inner) {
+ if (wtb->draw_inner) {
if (wcol->shaded == 0) {
if (wcol->alpha_check) {
float inner_v_half[WIDGET_SIZE_MAX][2];
@@ -712,7 +713,7 @@ static void widgetbase_draw(uiWidgetBase *wtb, uiWidgetColors *wcol)
glShadeModel(GL_SMOOTH);
for (a = 0; a < wtb->totvert; a++, col_pt += 4) {
- round_box_shade_col4_r(col_pt, col1, col2, wtb->inner_uv[a][wtb->shadedir]);
+ round_box_shade_col4_r(col_pt, col1, col2, wtb->inner_uv[a][wtb->draw_shadedir ? 1 : 0]);
}
glEnableClientState(GL_VERTEX_ARRAY);
@@ -728,38 +729,43 @@ static void widgetbase_draw(uiWidgetBase *wtb, uiWidgetColors *wcol)
}
/* for each AA step */
- if (wtb->outline) {
- float quad_strip[WIDGET_SIZE_MAX * 2 + 2][2]; /* + 2 because the last pair is wrapped */
- float quad_strip_emboss[WIDGET_SIZE_MAX * 2][2]; /* only for emboss */
+ if (wtb->draw_outline) {
+ float triangle_strip[WIDGET_SIZE_MAX * 2 + 2][2]; /* + 2 because the last pair is wrapped */
+ float triangle_strip_emboss[WIDGET_SIZE_MAX * 2][2]; /* only for emboss */
const unsigned char tcol[4] = {wcol->outline[0],
wcol->outline[1],
wcol->outline[2],
wcol->outline[3] / WIDGET_AA_JITTER};
- widget_verts_to_quad_strip(wtb, wtb->totvert, quad_strip);
+ widget_verts_to_triangle_strip(wtb, wtb->totvert, triangle_strip);
- if (wtb->emboss) {
- widget_verts_to_quad_strip_open(wtb, wtb->halfwayvert, quad_strip_emboss);
+ if (wtb->draw_emboss) {
+ widget_verts_to_triangle_strip_open(wtb, wtb->halfwayvert, triangle_strip_emboss);
}
glEnableClientState(GL_VERTEX_ARRAY);
for (j = 0; j < WIDGET_AA_JITTER; j++) {
- glTranslatef(jit[j][0], jit[j][1], 0.0f);
+ unsigned char emboss[4];
+
+ glTranslate2fv(jit[j]);
/* outline */
glColor4ubv(tcol);
- glVertexPointer(2, GL_FLOAT, 0, quad_strip);
- glDrawArrays(GL_QUAD_STRIP, 0, wtb->totvert * 2 + 2);
-
+ glVertexPointer(2, GL_FLOAT, 0, triangle_strip);
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, wtb->totvert * 2 + 2);
+
/* emboss bottom shadow */
- if (wtb->emboss) {
- glColor4f(1.0f, 1.0f, 1.0f, 0.02f);
+ if (wtb->draw_emboss) {
+ UI_GetThemeColor4ubv(TH_WIDGET_EMBOSS, emboss);
- glVertexPointer(2, GL_FLOAT, 0, quad_strip_emboss);
- glDrawArrays(GL_QUAD_STRIP, 0, wtb->halfwayvert * 2);
+ if (emboss[3]) {
+ glColor4ubv(emboss);
+ glVertexPointer(2, GL_FLOAT, 0, triangle_strip_emboss);
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, wtb->halfwayvert * 2);
+ }
}
glTranslatef(-jit[j][0], -jit[j][1], 0.0f);
@@ -774,9 +780,10 @@ static void widgetbase_draw(uiWidgetBase *wtb, uiWidgetColors *wcol)
wcol->item[1],
wcol->item[2],
(unsigned char)((float)wcol->item[3] / WIDGET_AA_JITTER)};
+
/* for each AA step */
for (j = 0; j < WIDGET_AA_JITTER; j++) {
- glTranslatef(jit[j][0], jit[j][1], 0.0f);
+ glTranslate2fv(jit[j]);
if (wtb->tria1.tot) {
glColor4ubv(tcol);
@@ -792,7 +799,6 @@ static void widgetbase_draw(uiWidgetBase *wtb, uiWidgetColors *wcol)
}
glDisable(GL_BLEND);
-
}
/* *********************** text/icon ************************************** */
@@ -801,7 +807,7 @@ static void widgetbase_draw(uiWidgetBase *wtb, uiWidgetColors *wcol)
#define PREVIEW_PAD 4
-static void widget_draw_preview(BIFIconID icon, float UNUSED(alpha), const rcti *rect)
+static void widget_draw_preview(BIFIconID icon, float alpha, const rcti *rect)
{
int w, h, size;
@@ -817,25 +823,26 @@ static void widget_draw_preview(BIFIconID icon, float UNUSED(alpha), const rcti
int x = rect->xmin + w / 2 - size / 2;
int y = rect->ymin + h / 2 - size / 2;
- UI_icon_draw_preview_aspect_size(x, y, icon, 1.0f, size);
+ UI_icon_draw_preview_aspect_size(x, y, icon, 1.0f, alpha, size);
}
}
static int ui_but_draw_menu_icon(const uiBut *but)
{
- return (but->flag & UI_ICON_SUBMENU) && (but->dt == UI_EMBOSSP);
+ return (but->flag & UI_BUT_ICON_SUBMENU) && (but->dt == UI_EMBOSS_PULLDOWN);
}
/* icons have been standardized... and this call draws in untransformed coordinates */
-static void widget_draw_icon(const uiBut *but, BIFIconID icon, float alpha, const rcti *rect,
- const bool show_menu_icon)
+static void widget_draw_icon(
+ const uiBut *but, BIFIconID icon, float alpha, const rcti *rect,
+ const bool show_menu_icon)
{
float xs = 0.0f, ys = 0.0f;
float aspect, height;
- if (but->flag & UI_ICON_PREVIEW) {
+ if (but->flag & UI_BUT_ICON_PREVIEW) {
glEnable(GL_BLEND);
widget_draw_preview(icon, alpha, rect);
glDisable(GL_BLEND);
@@ -843,20 +850,20 @@ static void widget_draw_icon(const uiBut *but, BIFIconID icon, float alpha, cons
}
/* this icon doesn't need draw... */
- if (icon == ICON_BLANK1 && (but->flag & UI_ICON_SUBMENU) == 0) return;
+ if (icon == ICON_BLANK1 && (but->flag & UI_BUT_ICON_SUBMENU) == 0) return;
aspect = but->block->aspect / UI_DPI_FAC;
height = ICON_DEFAULT_HEIGHT / aspect;
/* calculate blend color */
- if (ELEM(but->type, TOG, ROW, TOGN, LISTROW)) {
+ if (ELEM(but->type, UI_BTYPE_TOGGLE, UI_BTYPE_ROW, UI_BTYPE_TOGGLE_N, UI_BTYPE_LISTROW)) {
if (but->flag & UI_SELECT) {}
else if (but->flag & UI_ACTIVE) {}
else alpha = 0.5f;
}
/* extra feature allows more alpha blending */
- if ((but->type == LABEL) && but->a1 == 1.0f)
+ if ((but->type == UI_BTYPE_LABEL) && but->a1 == 1.0f)
alpha *= but->a2;
glEnable(GL_BLEND);
@@ -866,7 +873,7 @@ static void widget_draw_icon(const uiBut *but, BIFIconID icon, float alpha, cons
if (but->drawflag & UI_BUT_ICON_LEFT) {
if (but->block->flag & UI_BLOCK_LOOP) {
- if (ELEM(but->type, SEARCH_MENU, SEARCH_MENU_UNLINK))
+ if (but->type == UI_BTYPE_SEARCH_MENU)
xs = rect->xmin + 4.0f * ofs;
else
xs = rect->xmin + ofs;
@@ -922,12 +929,14 @@ static void ui_text_clip_give_next_off(uiBut *but, const char *str)
but->ofs += bytes;
}
-/* Helper.
+/**
+ * Helper.
* This func assumes things like kerning handling have already been handled!
* Return the length of modified (right-clipped + ellipsis) string.
*/
-static void ui_text_clip_right_ex(uiFontStyle *fstyle, char *str, const size_t max_len, const float okwidth,
- const char *sep, const int sep_len, const float sep_strwidth, size_t *r_final_len)
+static void ui_text_clip_right_ex(
+ uiFontStyle *fstyle, char *str, const size_t max_len, const float okwidth,
+ const char *sep, const int sep_len, const float sep_strwidth, size_t *r_final_len)
{
float tmp;
int l_end;
@@ -959,15 +968,20 @@ static void ui_text_clip_right_ex(uiFontStyle *fstyle, char *str, const size_t m
* If rpart_sep is not Null, the part of str starting to first occurrence of rpart_sep is preserved at all cost (useful
* for strings with shortcuts, like 'AVeryLongFooBarLabelForMenuEntry|Ctrl O' -> 'AVeryLong...MenuEntry|Ctrl O').
*/
-static float ui_text_clip_middle_ex(uiFontStyle *fstyle, char *str, float okwidth, const float minwidth,
- const size_t max_len, const char *rpart_sep)
+float UI_text_clip_middle_ex(
+ uiFontStyle *fstyle, char *str, float okwidth, const float minwidth,
+ const size_t max_len, const char rpart_sep)
{
float strwidth;
+ /* Add some epsilon to OK width, avoids 'ellipsing' text that nearly fits!
+ * Better to have a small piece of the last char cut out, than two remaining chars replaced by an allipsis... */
+ okwidth += 1.0f + UI_DPI_FAC;
+
BLI_assert(str[0]);
/* need to set this first */
- uiStyleFontSet(fstyle);
+ UI_fontstyle_set(fstyle);
if (fstyle->kerning == 1) { /* for BLF_width */
BLF_enable(fstyle->uifont_id, BLF_KERNING_DEFAULT);
@@ -989,7 +1003,7 @@ static float ui_text_clip_middle_ex(uiFontStyle *fstyle, char *str, float okwidt
size_t final_lpart_len;
if (rpart_sep) {
- rpart = strstr(str, rpart_sep);
+ rpart = strrchr(str, rpart_sep);
if (rpart) {
rpart_len = strlen(rpart);
@@ -1060,34 +1074,34 @@ static float ui_text_clip_middle_ex(uiFontStyle *fstyle, char *str, float okwidt
}
/**
- * Wrapper around ui_text_clip_middle_ex.
+ * Wrapper around UI_text_clip_middle_ex.
*/
static void ui_text_clip_middle(uiFontStyle *fstyle, uiBut *but, const rcti *rect)
{
/* No margin for labels! */
- const int border = ELEM(but->type, LABEL, MENU) ? 0 : (int)(UI_TEXT_CLIP_MARGIN + 0.5f);
+ const int border = ELEM(but->type, UI_BTYPE_LABEL, UI_BTYPE_MENU) ? 0 : (int)(UI_TEXT_CLIP_MARGIN + 0.5f);
const float okwidth = (float)max_ii(BLI_rcti_size_x(rect) - border, 0);
const size_t max_len = sizeof(but->drawstr);
const float minwidth = (float)(UI_DPI_ICON_SIZE) / but->block->aspect * 2.0f;
but->ofs = 0;
- but->strwidth = ui_text_clip_middle_ex(fstyle, but->drawstr, okwidth, minwidth, max_len, NULL);
+ but->strwidth = UI_text_clip_middle_ex(fstyle, but->drawstr, okwidth, minwidth, max_len, '\0');
}
/**
* Like ui_text_clip_middle(), but protect/preserve at all cost the right part of the string after sep.
* Useful for strings with shortcuts (like 'AVeryLongFooBarLabelForMenuEntry|Ctrl O' -> 'AVeryLong...MenuEntry|Ctrl O').
*/
-static void ui_text_clip_middle_protect_right(uiFontStyle *fstyle, uiBut *but, const rcti *rect, const char *rsep)
+static void ui_text_clip_middle_protect_right(uiFontStyle *fstyle, uiBut *but, const rcti *rect, const char rsep)
{
/* No margin for labels! */
- const int border = ELEM(but->type, LABEL, MENU) ? 0 : (int)(UI_TEXT_CLIP_MARGIN + 0.5f);
+ const int border = ELEM(but->type, UI_BTYPE_LABEL, UI_BTYPE_MENU) ? 0 : (int)(UI_TEXT_CLIP_MARGIN + 0.5f);
const float okwidth = (float)max_ii(BLI_rcti_size_x(rect) - border, 0);
const size_t max_len = sizeof(but->drawstr);
const float minwidth = (float)(UI_DPI_ICON_SIZE) / but->block->aspect * 2.0f;
but->ofs = 0;
- but->strwidth = ui_text_clip_middle_ex(fstyle, but->drawstr, okwidth, minwidth, max_len, rsep);
+ but->strwidth = UI_text_clip_middle_ex(fstyle, but->drawstr, okwidth, minwidth, max_len, rsep);
}
/**
@@ -1101,7 +1115,7 @@ static void ui_text_clip_cursor(uiFontStyle *fstyle, uiBut *but, const rcti *rec
BLI_assert(but->editstr && but->pos >= 0);
/* need to set this first */
- uiStyleFontSet(fstyle);
+ UI_fontstyle_set(fstyle);
if (fstyle->kerning == 1) /* for BLF_width */
BLF_enable(fstyle->uifont_id, BLF_KERNING_DEFAULT);
@@ -1164,7 +1178,7 @@ static void ui_text_clip_right_label(uiFontStyle *fstyle, uiBut *but, const rcti
const char *cpend = but->drawstr + drawstr_len;
/* need to set this first */
- uiStyleFontSet(fstyle);
+ UI_fontstyle_set(fstyle);
if (fstyle->kerning == 1) /* for BLF_width */
BLF_enable(fstyle->uifont_id, BLF_KERNING_DEFAULT);
@@ -1208,7 +1222,6 @@ static void ui_text_clip_right_label(uiFontStyle *fstyle, uiBut *but, const rcti
but->strwidth = BLF_width(fstyle->uifont_id, but->drawstr + but->ofs, sizeof(but->drawstr) - but->ofs);
if (but->strwidth < 10) break;
}
-
}
@@ -1226,6 +1239,50 @@ static void ui_text_clip_right_label(uiFontStyle *fstyle, uiBut *but, const rcti
BLF_disable(fstyle->uifont_id, BLF_KERNING_DEFAULT);
}
+#ifdef WITH_INPUT_IME
+static void widget_draw_text_ime_underline(
+ uiFontStyle *fstyle, uiWidgetColors *wcol, uiBut *but, const rcti *rect,
+ const wmIMEData *ime_data, const char *drawstr)
+{
+ int ofs_x, width;
+ int rect_x = BLI_rcti_size_x(rect);
+ int sel_start = ime_data->sel_start, sel_end = ime_data->sel_end;
+
+ if (drawstr[0] != 0) {
+ if (but->pos >= but->ofs) {
+ ofs_x = BLF_width(fstyle->uifont_id, drawstr + but->ofs, but->pos - but->ofs);
+ }
+ else {
+ ofs_x = 0;
+ }
+
+ width = BLF_width(fstyle->uifont_id, drawstr + but->ofs,
+ ime_data->composite_len + but->pos - but->ofs);
+
+ glColor4ubv((unsigned char *)wcol->text);
+ UI_draw_text_underline(rect->xmin + ofs_x, rect->ymin + 6 * U.pixelsize, min_ii(width, rect_x - 2) - ofs_x, 1);
+
+ /* draw the thick line */
+ if (sel_start != -1 && sel_end != -1) {
+ sel_end -= sel_start;
+ sel_start += but->pos;
+
+ if (sel_start >= but->ofs) {
+ ofs_x = BLF_width(fstyle->uifont_id, drawstr + but->ofs, sel_start - but->ofs);
+ }
+ else {
+ ofs_x = 0;
+ }
+
+ width = BLF_width(fstyle->uifont_id, drawstr + but->ofs,
+ sel_end + sel_start - but->ofs);
+
+ UI_draw_text_underline(rect->xmin + ofs_x, rect->ymin + 6 * U.pixelsize, min_ii(width, rect_x - 2) - ofs_x, 2);
+ }
+ }
+}
+#endif /* WITH_INPUT_IME */
+
static void widget_draw_text(uiFontStyle *fstyle, uiWidgetColors *wcol, uiBut *but, rcti *rect)
{
int drawstr_left_len = UI_MAX_DRAW_STR;
@@ -1233,7 +1290,11 @@ static void widget_draw_text(uiFontStyle *fstyle, uiWidgetColors *wcol, uiBut *b
const char *drawstr_right = NULL;
bool use_right_only = false;
- uiStyleFontSet(fstyle);
+#ifdef WITH_INPUT_IME
+ const wmIMEData *ime_data;
+#endif
+
+ UI_fontstyle_set(fstyle);
if (but->editstr || (but->drawflag & UI_BUT_TEXT_LEFT))
fstyle->align = UI_STYLE_TEXT_LEFT;
@@ -1249,7 +1310,7 @@ static void widget_draw_text(uiFontStyle *fstyle, uiWidgetColors *wcol, uiBut *b
/* Special case: when we're entering text for multiple buttons,
* don't draw the text for any of the multi-editing buttons */
if (UNLIKELY(but->flag & UI_BUT_DRAG_MULTI)) {
- uiBut *but_edit = ui_get_but_drag_multi_edit(but);
+ uiBut *but_edit = ui_but_drag_multi_edit_get(but);
if (but_edit) {
drawstr = but_edit->editstr;
fstyle->align = UI_STYLE_TEXT_LEFT;
@@ -1260,13 +1321,30 @@ static void widget_draw_text(uiFontStyle *fstyle, uiWidgetColors *wcol, uiBut *b
/* max length isn't used in this case,
* we rely on string being NULL terminated. */
drawstr_left_len = INT_MAX;
- drawstr = but->editstr;
+
+#ifdef WITH_INPUT_IME
+ /* FIXME, IME is modifying 'const char *drawstr! */
+ ime_data = ui_but_ime_data_get(but);
+
+ if (ime_data && ime_data->composite_len) {
+ /* insert composite string into cursor pos */
+ BLI_snprintf((char *)drawstr, UI_MAX_DRAW_STR, "%s%s%s",
+ but->editstr, ime_data->str_composite,
+ but->editstr + but->pos);
+ }
+ else
+#endif
+ {
+ drawstr = but->editstr;
+ }
}
}
- /* text button selection and cursor */
+ /* text button selection, cursor, composite underline */
if (but->editstr && but->pos != -1) {
+ int but_pos_ofs;
+ int tx, ty;
/* text button selection */
if ((but->selend - but->selsta) > 0) {
@@ -1292,18 +1370,44 @@ static void widget_draw_text(uiFontStyle *fstyle, uiWidgetColors *wcol, uiBut *b
}
/* text cursor */
+ but_pos_ofs = but->pos;
+
+#ifdef WITH_INPUT_IME
+ /* if is ime compositing, move the cursor */
+ if (ime_data && ime_data->composite_len && ime_data->cursor_pos != -1) {
+ but_pos_ofs += ime_data->cursor_pos;
+ }
+#endif
+
if (but->pos >= but->ofs) {
int t;
if (drawstr[0] != 0) {
- t = BLF_width(fstyle->uifont_id, drawstr + but->ofs, but->pos - but->ofs);
+ t = BLF_width(fstyle->uifont_id, drawstr + but->ofs, but_pos_ofs - but->ofs);
}
else {
t = 0;
}
- glColor3f(0.20, 0.6, 0.9);
- glRecti(rect->xmin + t, rect->ymin + 2, rect->xmin + t + 2, rect->ymax - 2);
+ glColor3f(0.2, 0.6, 0.9);
+
+ tx = rect->xmin + t + 2;
+ ty = rect->ymin + 2;
+
+ /* draw cursor */
+ glRecti(rect->xmin + t, ty, tx, rect->ymax - 2);
+ }
+
+#ifdef WITH_INPUT_IME
+ if (ime_data && ime_data->composite_len) {
+ /* ime cursor following */
+ if (but->pos >= but->ofs) {
+ ui_but_ime_reposition(but, tx + 5, ty + 3, false);
+ }
+
+ /* composite underline */
+ widget_draw_text_ime_underline(fstyle, wcol, but, rect, ime_data, drawstr);
}
+#endif
}
if (fstyle->kerning == 1)
@@ -1328,7 +1432,7 @@ static void widget_draw_text(uiFontStyle *fstyle, uiWidgetColors *wcol, uiBut *b
}
#ifdef USE_NUMBUTS_LR_ALIGN
- if (!drawstr_right && ELEM(but->type, NUM, NUMSLI) &&
+ if (!drawstr_right && ELEM(but->type, UI_BTYPE_NUM, UI_BTYPE_NUM_SLIDER) &&
/* if we're editing or multi-drag (fake editing), then use left alignment */
(but->editstr == NULL) && (drawstr == but->drawstr))
{
@@ -1355,7 +1459,7 @@ static void widget_draw_text(uiFontStyle *fstyle, uiWidgetColors *wcol, uiBut *b
/* for underline drawing */
float font_xofs, font_yofs;
- uiStyleFontDrawExt(fstyle, rect, drawstr + but->ofs,
+ UI_fontstyle_draw_ex(fstyle, rect, drawstr + but->ofs,
drawstr_left_len - but->ofs, &font_xofs, &font_yofs);
if (but->menu_key != '\0') {
@@ -1395,7 +1499,7 @@ static void widget_draw_text(uiFontStyle *fstyle, uiWidgetColors *wcol, uiBut *b
if (drawstr_right) {
fstyle->align = UI_STYLE_TEXT_RIGHT;
rect->xmax -= UI_TEXT_CLIP_MARGIN;
- uiStyleFontDraw(fstyle, rect, drawstr_right);
+ UI_fontstyle_draw(fstyle, rect, drawstr_right);
}
}
@@ -1405,11 +1509,12 @@ static void widget_draw_text_icon(uiFontStyle *fstyle, uiWidgetColors *wcol, uiB
const bool show_menu_icon = ui_but_draw_menu_icon(but);
float alpha = (float)wcol->text[3] / 255.0f;
char password_str[UI_MAX_DRAW_STR];
+ uiButExtraIconType extra_icon_type;
- ui_button_text_password_hide(password_str, but, false);
+ ui_but_text_password_hide(password_str, but, false);
/* check for button text label */
- if (but->type == MENU && (but->flag & UI_BUT_NODE_LINK)) {
+ if (but->type == UI_BTYPE_MENU && (but->flag & UI_BUT_NODE_LINK)) {
rcti temp = *rect;
temp.xmin = rect->xmax - BLI_rcti_size_y(rect) - 1;
widget_draw_icon(but, ICON_LAYER_USED, alpha, &temp, false);
@@ -1418,7 +1523,34 @@ static void widget_draw_text_icon(uiFontStyle *fstyle, uiWidgetColors *wcol, uiB
/* If there's an icon too (made with uiDefIconTextBut) then draw the icon
* and offset the text label to accommodate it */
- if (but->flag & UI_HAS_ICON || show_menu_icon) {
+ /* Big previews with optional text label below */
+ if (but->flag & UI_BUT_ICON_PREVIEW && ui_block_is_menu(but->block)) {
+ const BIFIconID icon = (but->flag & UI_HAS_ICON) ? but->icon + but->iconadd : ICON_NONE;
+ int icon_size = BLI_rcti_size_y(rect);
+ int text_size = 0;
+
+ /* This is a bit britle, but avoids adding an 'UI_BUT_HAS_LABEL' flag to but... */
+ if (icon_size > BLI_rcti_size_x(rect)) {
+ /* button is not square, it has extra height for label */
+ text_size = UI_UNIT_Y;
+ icon_size -= text_size;
+ }
+
+ /* draw icon in rect above the space reserved for the label */
+ rect->ymin += text_size;
+ glEnable(GL_BLEND);
+ widget_draw_preview(icon, alpha, rect);
+ glDisable(GL_BLEND);
+
+ /* offset rect to draw label in */
+ rect->ymin -= text_size;
+ rect->ymax -= icon_size;
+
+ /* vertically centering text */
+ rect->ymin += UI_UNIT_Y / 2;
+ }
+ /* Icons on the left with optional text label on the right */
+ else if (but->flag & UI_HAS_ICON || show_menu_icon) {
const BIFIconID icon = (but->flag & UI_HAS_ICON) ? but->icon + but->iconadd : ICON_NONE;
const float icon_size = ICON_SIZE_FROM_BUTRECT(rect);
@@ -1444,11 +1576,23 @@ static void widget_draw_text_icon(uiFontStyle *fstyle, uiWidgetColors *wcol, uiB
}
/* unlink icon for this button type */
- if ((but->type == SEARCH_MENU_UNLINK) && ui_is_but_search_unlink_visible(but)) {
+ if ((but->type == UI_BTYPE_SEARCH_MENU) &&
+ ((extra_icon_type = ui_but_icon_extra_get(but)) != UI_BUT_ICONEXTRA_NONE))
+ {
rcti temp = *rect;
temp.xmin = temp.xmax - (BLI_rcti_size_y(rect) * 1.08f);
- widget_draw_icon(but, ICON_X, alpha, &temp, false);
+
+ if (extra_icon_type == UI_BUT_ICONEXTRA_UNLINK) {
+ widget_draw_icon(but, ICON_X, alpha, &temp, false);
+ }
+ else if (extra_icon_type == UI_BUT_ICONEXTRA_EYEDROPPER) {
+ widget_draw_icon(but, ICON_EYEDROPPER, alpha, &temp, false);
+ }
+ else {
+ BLI_assert(0);
+ }
+
rect->xmax -= ICON_SIZE_FROM_BUTRECT(rect);
}
@@ -1461,12 +1605,12 @@ static void widget_draw_text_icon(uiFontStyle *fstyle, uiWidgetColors *wcol, uiB
but->ofs = 0;
but->strwidth = 0;
}
- else if (ELEM(but->type, NUM, NUMSLI)) {
+ else if (ELEM(but->type, UI_BTYPE_NUM, UI_BTYPE_NUM_SLIDER)) {
ui_text_clip_right_label(fstyle, but, rect);
}
- else if ((but->block->flag & UI_BLOCK_LOOP) && (but->type == BUT)) {
+ else if (but->flag & UI_BUT_HAS_SEP_CHAR) {
/* Clip middle, but protect in all case right part containing the shortcut, if any. */
- ui_text_clip_middle_protect_right(fstyle, but, rect, "|");
+ ui_text_clip_middle_protect_right(fstyle, but, rect, UI_SEP_CHAR);
}
else {
ui_text_clip_middle(fstyle, but, rect);
@@ -1475,7 +1619,7 @@ static void widget_draw_text_icon(uiFontStyle *fstyle, uiWidgetColors *wcol, uiB
/* always draw text for textbutton cursor */
widget_draw_text(fstyle, wcol, but, rect);
- ui_button_text_password_hide(password_str, but, true);
+ ui_but_text_password_hide(password_str, but, true);
}
#undef UI_TEXT_CLIP_MARGIN
@@ -1483,17 +1627,6 @@ static void widget_draw_text_icon(uiFontStyle *fstyle, uiWidgetColors *wcol, uiB
/* *********************** widget types ************************************* */
-
-/* uiWidgetStateColors
- * char inner_anim[4];
- * char inner_anim_sel[4];
- * char inner_key[4];
- * char inner_key_sel[4];
- * char inner_driven[4];
- * char inner_driven_sel[4];
- * float blend;
- */
-
static struct uiWidgetStateColors wcol_state_colors = {
{115, 190, 76, 255},
{90, 166, 51, 255},
@@ -1504,18 +1637,6 @@ static struct uiWidgetStateColors wcol_state_colors = {
0.5f, 0.0f
};
-/* uiWidgetColors
- * char outline[3];
- * char inner[4];
- * char inner_sel[4];
- * char item[3];
- * char text[3];
- * char text_sel[3];
- *
- * short shaded;
- * float shadetop, shadedown;
- */
-
static struct uiWidgetColors wcol_num = {
{25, 25, 25, 255},
{180, 180, 180, 255},
@@ -1646,7 +1767,7 @@ static struct uiWidgetColors wcol_tooltip = {
{45, 45, 45, 230},
{100, 100, 100, 255},
- {160, 160, 160, 255},
+ {255, 255, 255, 255},
{255, 255, 255, 255},
0,
@@ -1808,6 +1929,23 @@ static void widget_state_blend(char cp[3], const char cpstate[3], const float fa
}
}
+/* put all widget colors on half alpha, use local storage */
+static void ui_widget_color_disabled(uiWidgetType *wt)
+{
+ static uiWidgetColors wcol_theme_s;
+
+ wcol_theme_s = *wt->wcol_theme;
+
+ wcol_theme_s.outline[3] *= 0.5;
+ wcol_theme_s.inner[3] *= 0.5;
+ wcol_theme_s.inner_sel[3] *= 0.5;
+ wcol_theme_s.item[3] *= 0.5;
+ wcol_theme_s.text[3] *= 0.5;
+ wcol_theme_s.text_sel[3] *= 0.5;
+
+ wt->wcol_theme = &wcol_theme_s;
+}
+
/* copy colors from theme, and set changes in it based on state */
static void widget_state(uiWidgetType *wt, int state)
{
@@ -1817,6 +1955,10 @@ static void widget_state(uiWidgetType *wt, int state)
/* Override default widget's colors. */
bTheme *btheme = UI_GetTheme();
wt->wcol_theme = &btheme->tui.wcol_list_item;
+
+ if (state & (UI_BUT_DISABLED | UI_BUT_INACTIVE)) {
+ ui_widget_color_disabled(wt);
+ }
}
wt->wcol = *(wt->wcol_theme);
@@ -1998,7 +2140,7 @@ static void widget_softshadow(const rcti *rect, int roundboxalign, const float r
rcti rect1 = *rect;
float alphastep;
int step, totvert;
- float quad_strip[WIDGET_SIZE_MAX * 2 + 2][2];
+ float triangle_strip[WIDGET_SIZE_MAX * 2 + 2][2];
const float radout = UI_ThemeMenuShadowWidth();
/* disabled shadow */
@@ -2026,10 +2168,10 @@ static void widget_softshadow(const rcti *rect, int roundboxalign, const float r
glColor4f(0.0f, 0.0f, 0.0f, alphastep * (1.0f - expfac));
- widget_verts_to_quad_strip(&wtb, totvert, quad_strip);
+ widget_verts_to_triangle_strip(&wtb, totvert, triangle_strip);
- glVertexPointer(2, GL_FLOAT, 0, quad_strip);
- glDrawArrays(GL_QUAD_STRIP, 0, totvert * 2); /* add + 2 for getting a complete soft rect. Now it skips top edge to allow transparent menus */
+ glVertexPointer(2, GL_FLOAT, 0, triangle_strip);
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, totvert * 2); /* add + 2 for getting a complete soft rect. Now it skips top edge to allow transparent menus */
}
glDisableClientState(GL_VERTEX_ARRAY);
@@ -2047,11 +2189,11 @@ static void widget_menu_back(uiWidgetColors *wcol, rcti *rect, int flag, int dir
//rect->ymin -= 4.0;
//rect->ymax += 4.0;
}
- else if (direction == UI_DOWN) {
+ else if (direction == UI_DIR_DOWN) {
roundboxalign = (UI_CNR_BOTTOM_RIGHT | UI_CNR_BOTTOM_LEFT);
rect->ymin -= 0.1f * U.widget_unit;
}
- else if (direction == UI_TOP) {
+ else if (direction == UI_DIR_UP) {
roundboxalign = UI_CNR_TOP_LEFT | UI_CNR_TOP_RIGHT;
rect->ymax += 0.1f * U.widget_unit;
}
@@ -2060,7 +2202,7 @@ static void widget_menu_back(uiWidgetColors *wcol, rcti *rect, int flag, int dir
widget_softshadow(rect, roundboxalign, 0.25f * U.widget_unit);
round_box_edges(&wtb, roundboxalign, rect, 0.25f * U.widget_unit);
- wtb.emboss = 0;
+ wtb.draw_emboss = false;
widgetbase_draw(&wtb, wcol);
glDisable(GL_BLEND);
@@ -2069,7 +2211,6 @@ static void widget_menu_back(uiWidgetColors *wcol, rcti *rect, int flag, int dir
static void ui_hsv_cursor(float x, float y)
{
-
glPushMatrix();
glTranslatef(x, y, 0.0f);
@@ -2084,7 +2225,6 @@ static void ui_hsv_cursor(float x, float y)
glDisable(GL_LINE_SMOOTH);
glPopMatrix();
-
}
void ui_hsvcircle_vals_from_pos(float *val_rad, float *val_dist, const rcti *rect,
@@ -2110,10 +2250,10 @@ void ui_hsvcircle_pos_from_vals(uiBut *but, const rcti *rect, float *hsv, float
float radius = (float)min_ii(BLI_rcti_size_x(rect), BLI_rcti_size_y(rect)) / 2.0f;
float ang, radius_t;
- ang = 2.0f * (float)M_PI * hsv[0] + 0.5f * (float)M_PI;
+ ang = 2.0f * (float)M_PI * hsv[0] + (float)M_PI_2;
if ((but->flag & UI_BUT_COLOR_CUBIC) && (U.color_picker_type == USER_CP_CIRCLE_HSV))
- radius_t = (1.0f - powf(1.0f - hsv[1], 3.0f));
+ radius_t = (1.0f - pow3f(1.0f - hsv[1]));
else
radius_t = hsv[1];
@@ -2131,14 +2271,15 @@ static void ui_draw_but_HSVCIRCLE(uiBut *but, uiWidgetColors *wcol, const rcti *
float radius = (float)min_ii(BLI_rcti_size_x(rect), BLI_rcti_size_y(rect)) / 2.0f;
/* gouraud triangle fan */
- const float *hsv_ptr = ui_block_hsv_get(but->block);
+ ColorPicker *cpicker = but->custom_data;
+ const float *hsv_ptr = cpicker->color_data;
float xpos, ypos, ang = 0.0f;
float rgb[3], hsvo[3], hsv[3], col[3], colcent[3];
int a;
- bool color_profile = ui_color_picker_use_display_colorspace(but);
+ bool color_profile = ui_but_is_colorpicker_display_space(but);
/* color */
- ui_get_but_vectorf(but, rgb);
+ ui_but_v3_get(but, rgb);
/* since we use compat functions on both 'hsv' and 'hsvo', they need to be initialized */
hsvo[0] = hsv[0] = hsv_ptr[0];
@@ -2146,7 +2287,7 @@ static void ui_draw_but_HSVCIRCLE(uiBut *but, uiWidgetColors *wcol, const rcti *
hsvo[2] = hsv[2] = hsv_ptr[2];
if (color_profile)
- ui_block_to_display_space_v3(but->block, rgb);
+ ui_block_cm_to_display_space_v3(but->block, rgb);
ui_rgb_to_color_picker_compat_v(rgb, hsv);
copy_v3_v3(hsvo, hsv);
@@ -2158,12 +2299,12 @@ static void ui_draw_but_HSVCIRCLE(uiBut *but, uiWidgetColors *wcol, const rcti *
* Useful for color correction tools where you're only interested in hue. */
if (but->flag & UI_BUT_COLOR_LOCK) {
if (U.color_picker_type == USER_CP_CIRCLE_HSV)
- hsv[2] = 1.f;
+ hsv[2] = 1.0f;
else
hsv[2] = 0.5f;
}
- ui_color_picker_to_rgb(0.f, 0.f, hsv[2], colcent, colcent + 1, colcent + 2);
+ ui_color_picker_to_rgb(0.0f, 0.0f, hsv[2], colcent, colcent + 1, colcent + 2);
glShadeModel(GL_SMOOTH);
@@ -2209,7 +2350,7 @@ static void ui_draw_but_HSVCIRCLE(uiBut *but, uiWidgetColors *wcol, const rcti *
void ui_draw_gradient(const rcti *rect, const float hsv[3], const int type, const float alpha)
{
/* allows for 4 steps (red->yellow) */
- const float color_step = (1.0 / 48.0);
+ const float color_step = 1.0f / 48.0f;
int a;
float h = hsv[0], s = hsv[1], v = hsv[2];
float dx, dy, sx1, sx2, sy;
@@ -2222,9 +2363,9 @@ void ui_draw_gradient(const rcti *rect, const float hsv[3], const int type, cons
switch (type) {
case UI_GRAD_SV:
hsv_to_rgb(h, 0.0, 0.0, &col1[0][0], &col1[0][1], &col1[0][2]);
- hsv_to_rgb(h, 0.333, 0.0, &col1[1][0], &col1[1][1], &col1[1][2]);
- hsv_to_rgb(h, 0.666, 0.0, &col1[2][0], &col1[2][1], &col1[2][2]);
- hsv_to_rgb(h, 1.0, 0.0, &col1[3][0], &col1[3][1], &col1[3][2]);
+ hsv_to_rgb(h, 0.0, 0.333, &col1[1][0], &col1[1][1], &col1[1][2]);
+ hsv_to_rgb(h, 0.0, 0.666, &col1[2][0], &col1[2][1], &col1[2][2]);
+ hsv_to_rgb(h, 0.0, 1.0, &col1[3][0], &col1[3][1], &col1[3][2]);
break;
case UI_GRAD_HV:
hsv_to_rgb(0.0, s, 0.0, &col1[0][0], &col1[0][1], &col1[0][2]);
@@ -2239,26 +2380,26 @@ void ui_draw_gradient(const rcti *rect, const float hsv[3], const int type, cons
hsv_to_rgb(0.0, 1.0, v, &col1[3][0], &col1[3][1], &col1[3][2]);
break;
case UI_GRAD_H:
- hsv_to_rgb(0.0, 1.0, 1.0, &col1[0][0], &col1[0][1], &col1[0][2]);
+ hsv_to_rgb(0.0, 1.0, 1.0, &col1[0][0], &col1[0][1], &col1[0][2]);
copy_v3_v3(col1[1], col1[0]);
copy_v3_v3(col1[2], col1[0]);
copy_v3_v3(col1[3], col1[0]);
break;
case UI_GRAD_S:
- hsv_to_rgb(1.0, 0.0, 1.0, &col1[1][0], &col1[1][1], &col1[1][2]);
+ hsv_to_rgb(1.0, 0.0, 1.0, &col1[1][0], &col1[1][1], &col1[1][2]);
copy_v3_v3(col1[0], col1[1]);
copy_v3_v3(col1[2], col1[1]);
copy_v3_v3(col1[3], col1[1]);
break;
case UI_GRAD_V:
- hsv_to_rgb(1.0, 1.0, 0.0, &col1[2][0], &col1[2][1], &col1[2][2]);
+ hsv_to_rgb(1.0, 1.0, 0.0, &col1[2][0], &col1[2][1], &col1[2][2]);
copy_v3_v3(col1[0], col1[2]);
copy_v3_v3(col1[1], col1[2]);
copy_v3_v3(col1[3], col1[2]);
break;
default:
assert(!"invalid 'type' argument");
- hsv_to_rgb(1.0, 1.0, 1.0, &col1[2][0], &col1[2][1], &col1[2][2]);
+ hsv_to_rgb(1.0, 1.0, 1.0, &col1[2][0], &col1[2][1], &col1[2][2]);
copy_v3_v3(col1[0], col1[2]);
copy_v3_v3(col1[1], col1[2]);
copy_v3_v3(col1[3], col1[2]);
@@ -2279,10 +2420,10 @@ void ui_draw_gradient(const rcti *rect, const float hsv[3], const int type, cons
/* new color */
switch (type) {
case UI_GRAD_SV:
- hsv_to_rgb(h, 0.0, dx, &col1[0][0], &col1[0][1], &col1[0][2]);
- hsv_to_rgb(h, 0.333, dx, &col1[1][0], &col1[1][1], &col1[1][2]);
- hsv_to_rgb(h, 0.666, dx, &col1[2][0], &col1[2][1], &col1[2][2]);
- hsv_to_rgb(h, 1.0, dx, &col1[3][0], &col1[3][1], &col1[3][2]);
+ hsv_to_rgb(h, dx, 0.0, &col1[0][0], &col1[0][1], &col1[0][2]);
+ hsv_to_rgb(h, dx, 0.333, &col1[1][0], &col1[1][1], &col1[1][2]);
+ hsv_to_rgb(h, dx, 0.666, &col1[2][0], &col1[2][1], &col1[2][2]);
+ hsv_to_rgb(h, dx, 1.0, &col1[3][0], &col1[3][1], &col1[3][2]);
break;
case UI_GRAD_HV:
hsv_to_rgb(dx_next, s, 0.0, &col1[0][0], &col1[0][1], &col1[0][2]);
@@ -2297,23 +2438,21 @@ void ui_draw_gradient(const rcti *rect, const float hsv[3], const int type, cons
hsv_to_rgb(dx_next, 1.0, v, &col1[3][0], &col1[3][1], &col1[3][2]);
break;
case UI_GRAD_H:
- {
/* annoying but without this the color shifts - could be solved some other way
* - campbell */
- hsv_to_rgb(dx_next, 1.0, 1.0, &col1[0][0], &col1[0][1], &col1[0][2]);
+ hsv_to_rgb(dx_next, 1.0, 1.0, &col1[0][0], &col1[0][1], &col1[0][2]);
copy_v3_v3(col1[1], col1[0]);
copy_v3_v3(col1[2], col1[0]);
copy_v3_v3(col1[3], col1[0]);
break;
- }
case UI_GRAD_S:
- hsv_to_rgb(h, dx, 1.0, &col1[1][0], &col1[1][1], &col1[1][2]);
+ hsv_to_rgb(h, dx, 1.0, &col1[1][0], &col1[1][1], &col1[1][2]);
copy_v3_v3(col1[0], col1[1]);
copy_v3_v3(col1[2], col1[1]);
copy_v3_v3(col1[3], col1[1]);
break;
case UI_GRAD_V:
- hsv_to_rgb(h, 1.0, dx, &col1[2][0], &col1[2][1], &col1[2][2]);
+ hsv_to_rgb(h, 1.0, dx, &col1[2][0], &col1[2][1], &col1[2][2]);
copy_v3_v3(col1[0], col1[2]);
copy_v3_v3(col1[1], col1[2]);
copy_v3_v3(col1[3], col1[2]);
@@ -2342,12 +2481,11 @@ void ui_draw_gradient(const rcti *rect, const float hsv[3], const int type, cons
}
glEnd();
}
-
+
glShadeModel(GL_FLAT);
-
}
-bool ui_color_picker_use_display_colorspace(uiBut *but)
+bool ui_but_is_colorpicker_display_space(uiBut *but)
{
bool color_profile = but->block->color_profile;
@@ -2365,7 +2503,7 @@ void ui_hsvcube_pos_from_vals(uiBut *but, const rcti *rect, float *hsv, float *x
switch ((int)but->a1) {
case UI_GRAD_SV:
- x = hsv[2]; y = hsv[1]; break;
+ x = hsv[1]; y = hsv[2]; break;
case UI_GRAD_HV:
x = hsv[0]; y = hsv[2]; break;
case UI_GRAD_HS:
@@ -2387,27 +2525,27 @@ void ui_hsvcube_pos_from_vals(uiBut *but, const rcti *rect, float *hsv, float *x
y = (hsv[2] - but->softmin) / (but->softmax - but->softmin);
break;
}
-
+
/* cursor */
*xp = rect->xmin + x * BLI_rcti_size_x(rect);
*yp = rect->ymin + y * BLI_rcti_size_y(rect);
-
}
static void ui_draw_but_HSVCUBE(uiBut *but, const rcti *rect)
{
float rgb[3];
float x = 0.0f, y = 0.0f;
- const float *hsv = ui_block_hsv_get(but->block);
+ ColorPicker *cpicker = but->custom_data;
+ float *hsv = cpicker->color_data;
float hsv_n[3];
- bool use_display_colorspace = ui_color_picker_use_display_colorspace(but);
+ bool use_display_colorspace = ui_but_is_colorpicker_display_space(but);
copy_v3_v3(hsv_n, hsv);
- ui_get_but_vectorf(but, rgb);
+ ui_but_v3_get(but, rgb);
if (use_display_colorspace)
- ui_block_to_display_space_v3(but->block, rgb);
+ ui_block_cm_to_display_space_v3(but->block, rgb);
rgb_to_hsv_compat_v(rgb, hsv_n);
@@ -2436,10 +2574,10 @@ static void ui_draw_but_HSV_v(uiBut *but, const rcti *rect)
if (but->rnaprop && RNA_property_subtype(but->rnaprop) == PROP_COLOR_GAMMA)
color_profile = false;
- ui_get_but_vectorf(but, rgb);
+ ui_but_v3_get(but, rgb);
if (color_profile)
- ui_block_to_display_space_v3(but->block, rgb);
+ ui_block_cm_to_display_space_v3(but->block, rgb);
if (but->a1 == UI_GRAD_L_ALT)
rgb_to_hsl_v(rgb, hsv);
@@ -2449,8 +2587,11 @@ static void ui_draw_but_HSV_v(uiBut *but, const rcti *rect)
/* map v from property range to [0,1] */
if (but->a1 == UI_GRAD_V_ALT) {
- float range = but->softmax - but->softmin;
- v = (v - but->softmin) / range;
+ float min = but->softmin, max = but->softmax;
+ if (color_profile) {
+ ui_block_cm_to_display_space_range(but->block, &min, &max);
+ }
+ v = (v - min) / (max - min);
}
widget_init(&wtb);
@@ -2471,9 +2612,8 @@ static void ui_draw_but_HSV_v(uiBut *but, const rcti *rect)
x = rect->xmin + 0.5f * BLI_rcti_size_x(rect);
y = rect->ymin + v * BLI_rcti_size_y(rect);
CLAMP(y, rect->ymin + 3.0f, rect->ymax - 3.0f);
-
+
ui_hsv_cursor(x, y);
-
}
@@ -2558,7 +2698,8 @@ bool ui_link_bezier_points(const rcti *rect, float coord_array[][2], int resol)
BKE_curve_forward_diff_bezier(vec[0][0], vec[1][0], vec[2][0], vec[3][0], &coord_array[0][0], resol, sizeof(float[2]));
BKE_curve_forward_diff_bezier(vec[0][1], vec[1][1], vec[2][1], vec[3][1], &coord_array[0][1], resol, sizeof(float[2]));
- return 1;
+ /* TODO: why return anything if always true? */
+ return true;
}
#define LINK_RESOL 24
@@ -2567,9 +2708,10 @@ void ui_draw_link_bezier(const rcti *rect)
float coord_array[LINK_RESOL + 1][2];
if (ui_link_bezier_points(rect, coord_array, LINK_RESOL)) {
+#if 0 /* unused */
/* we can reuse the dist variable here to increment the GL curve eval amount*/
- // const float dist = 1.0f / (float)LINK_RESOL; // UNUSED
-
+ const float dist = 1.0f / (float)LINK_RESOL;
+#endif
glEnable(GL_BLEND);
glEnable(GL_LINE_SMOOTH);
@@ -2580,12 +2722,11 @@ void ui_draw_link_bezier(const rcti *rect)
glDisable(GL_BLEND);
glDisable(GL_LINE_SMOOTH);
-
}
}
/* function in use for buttons and for view2d sliders */
-void uiWidgetScrollDraw(uiWidgetColors *wcol, const rcti *rect, const rcti *slider, int state)
+void UI_draw_widget_scroll(uiWidgetColors *wcol, const rcti *rect, const rcti *slider, int state)
{
uiWidgetBase wtb;
int horizontal;
@@ -2602,7 +2743,7 @@ void uiWidgetScrollDraw(uiWidgetColors *wcol, const rcti *rect, const rcti *slid
else
rad = 0.5f * BLI_rcti_size_x(rect);
- wtb.shadedir = (horizontal) ? 1 : 0;
+ wtb.draw_shadedir = (horizontal) ? true : false;
/* draw back part, colors swapped and shading inverted */
if (horizontal)
@@ -2631,11 +2772,11 @@ void uiWidgetScrollDraw(uiWidgetColors *wcol, const rcti *rect, const rcti *slid
}
/* draw */
- wtb.emboss = 0; /* only emboss once */
+ wtb.draw_emboss = false; /* only emboss once */
/* exception for progress bar */
if (state & UI_SCROLL_NO_OUTLINE) {
- SWAP(bool, outline, wtb.outline);
+ SWAP(bool, outline, wtb.draw_outline);
}
round_box_edges(&wtb, UI_CNR_ALL, slider, rad);
@@ -2658,7 +2799,7 @@ void uiWidgetScrollDraw(uiWidgetColors *wcol, const rcti *rect, const rcti *slid
widgetbase_draw(&wtb, wcol);
if (state & UI_SCROLL_NO_OUTLINE) {
- SWAP(bool, outline, wtb.outline);
+ SWAP(bool, outline, wtb.draw_outline);
}
}
}
@@ -2671,7 +2812,7 @@ static void widget_scroll(uiBut *but, uiWidgetColors *wcol, rcti *rect, int stat
int horizontal;
/* calculate slider part */
- value = ui_get_but_val(but);
+ value = ui_but_value_get(but);
size = (but->softmax + but->a1 - but->softmin);
size = max_ff(size, 2.0f);
@@ -2721,7 +2862,7 @@ static void widget_scroll(uiBut *but, uiWidgetColors *wcol, rcti *rect, int stat
state = UI_SCROLL_PRESSED;
else
state = 0;
- uiWidgetScrollDraw(wcol, rect, &rect1, state);
+ UI_draw_widget_scroll(wcol, rect, &rect1, state);
}
static void widget_progressbar(uiBut *but, uiWidgetColors *wcol, rcti *rect, int UNUSED(state), int UNUSED(roundboxalign))
@@ -2743,7 +2884,7 @@ static void widget_progressbar(uiBut *but, uiWidgetColors *wcol, rcti *rect, int
rect_bar.xmax = rect_bar.xmin + w;
- uiWidgetScrollDraw(wcol, &rect_prog, &rect_bar, UI_SCROLL_NO_OUTLINE);
+ UI_draw_widget_scroll(wcol, &rect_prog, &rect_bar, UI_SCROLL_NO_OUTLINE);
/* raise text a bit */
rect->ymin += 6 * UI_DPI_FAC;
@@ -2772,7 +2913,7 @@ static void widget_numslider(uiBut *but, uiWidgetColors *wcol, rcti *rect, int s
uiWidgetBase wtb, wtb1;
rcti rect1;
double value;
- float offs, toffs, fac;
+ float offs, toffs, fac = 0;
char outline[3];
widget_init(&wtb);
@@ -2785,7 +2926,7 @@ static void widget_numslider(uiBut *but, uiWidgetColors *wcol, rcti *rect, int s
toffs = offs * 0.75f;
round_box_edges(&wtb, roundboxalign, rect, offs);
- wtb.outline = 0;
+ wtb.draw_outline = false;
widgetbase_draw(&wtb, wcol);
/* draw left/right parts only when not in text editing */
@@ -2802,13 +2943,15 @@ static void widget_numslider(uiBut *but, uiWidgetColors *wcol, rcti *rect, int s
rect1 = *rect;
- value = ui_get_but_val(but);
- fac = ((float)value - but->softmin) * (BLI_rcti_size_x(&rect1) - offs) / (but->softmax - but->softmin);
+ value = ui_but_value_get(but);
+ if ((but->softmax - but->softmin) > 0) {
+ fac = ((float)value - but->softmin) * (BLI_rcti_size_x(&rect1) - offs) / (but->softmax - but->softmin);
+ }
/* left part of slider, always rounded */
rect1.xmax = rect1.xmin + ceil(offs + U.pixelsize);
round_box_edges(&wtb1, roundboxalign & ~(UI_CNR_TOP_RIGHT | UI_CNR_BOTTOM_RIGHT), &rect1, offs);
- wtb1.outline = 0;
+ wtb1.draw_outline = false;
widgetbase_draw(&wtb1, wcol);
/* right part of slider, interpolate roundness */
@@ -2833,8 +2976,8 @@ static void widget_numslider(uiBut *but, uiWidgetColors *wcol, rcti *rect, int s
}
/* outline */
- wtb.outline = 1;
- wtb.inner = 0;
+ wtb.draw_outline = true;
+ wtb.draw_inner = false;
widgetbase_draw(&wtb, wcol);
/* add space at either side of the button so text aligns with numbuttons (which have arrow icons) */
@@ -2842,7 +2985,6 @@ static void widget_numslider(uiBut *but, uiWidgetColors *wcol, rcti *rect, int s
rect->xmax -= toffs;
rect->xmin += toffs;
}
-
}
/* I think 3 is sufficient border to indicate keyed status */
@@ -2873,7 +3015,7 @@ static void widget_swatch(uiBut *but, uiWidgetColors *wcol, rcti *rect, int stat
rad = 0.25f * U.widget_unit;
round_box_edges(&wtb, roundboxalign, rect, rad);
- ui_get_but_vectorf(but, col);
+ ui_but_v3_get(but, col);
if (state & (UI_BUT_ANIMATED | UI_BUT_ANIMATED_KEY | UI_BUT_DRIVEN | UI_BUT_REDALERT)) {
/* draw based on state - color for keyed etc */
@@ -2889,7 +3031,7 @@ static void widget_swatch(uiBut *but, uiWidgetColors *wcol, rcti *rect, int stat
}
if (color_profile)
- ui_block_to_display_space_v3(but->block, col);
+ ui_block_cm_to_display_space_v3(but->block, col);
rgba_float_to_uchar((unsigned char *)wcol->inner, col);
@@ -2902,12 +3044,9 @@ static void widget_swatch(uiBut *but, uiWidgetColors *wcol, rcti *rect, int stat
float width = rect->xmax - rect->xmin;
float height = rect->ymax - rect->ymin;
/* find color luminance and change it slightly */
- float bw = rgb_to_bw(col);
-
- if (bw > 0.5)
- bw -= 0.5;
- else
- bw += 0.5;
+ float bw = rgb_to_grayscale(col);
+
+ bw += (bw < 0.5f) ? 0.5f : -0.5f;
glColor4f(bw, bw, bw, 1.0);
glBegin(GL_TRIANGLES);
@@ -2918,9 +3057,9 @@ static void widget_swatch(uiBut *but, uiWidgetColors *wcol, rcti *rect, int stat
}
}
-static void widget_normal(uiBut *but, uiWidgetColors *wcol, rcti *rect, int UNUSED(state), int UNUSED(roundboxalign))
+static void widget_unitvec(uiBut *but, uiWidgetColors *wcol, rcti *rect, int UNUSED(state), int UNUSED(roundboxalign))
{
- ui_draw_but_NORMAL(but, wcol, rect);
+ ui_draw_but_UNITVEC(but, wcol, rect);
}
static void widget_icon_has_anim(uiBut *but, uiWidgetColors *wcol, rcti *rect, int state, int roundboxalign)
@@ -2930,14 +3069,14 @@ static void widget_icon_has_anim(uiBut *but, uiWidgetColors *wcol, rcti *rect, i
float rad;
widget_init(&wtb);
- wtb.outline = 0;
+ wtb.draw_outline = false;
/* rounded */
rad = 0.5f * BLI_rcti_size_y(rect);
round_box_edges(&wtb, UI_CNR_ALL, rect, rad);
widgetbase_draw(&wtb, wcol);
}
- else if (but->type == NUM) {
+ else if (but->type == UI_BTYPE_NUM) {
/* Draw number buttons still with left/right
* triangles when field is not embossed */
widget_numbut_embossn(but, wcol, rect, state, roundboxalign);
@@ -2960,7 +3099,6 @@ static void widget_textbut(uiWidgetColors *wcol, rcti *rect, int state, int roun
round_box_edges(&wtb, roundboxalign, rect, rad);
widgetbase_draw(&wtb, wcol);
-
}
@@ -3046,7 +3184,7 @@ static void widget_menu_itembut(uiWidgetColors *wcol, rcti *rect, int UNUSED(sta
widget_init(&wtb);
/* not rounded, no outline */
- wtb.outline = 0;
+ wtb.draw_outline = false;
round_box_edges(&wtb, 0, rect, 0.0f);
widgetbase_draw(&wtb, wcol);
@@ -3060,7 +3198,7 @@ static void widget_menu_radial_itembut(uiBut *but, uiWidgetColors *wcol, rcti *r
widget_init(&wtb);
- wtb.emboss = 0;
+ wtb.draw_emboss = false;
rad = 0.5f * BLI_rcti_size_y(rect);
round_box_edges(&wtb, UI_CNR_ALL, rect, rad);
@@ -3083,7 +3221,7 @@ static void widget_list_itembut(uiWidgetColors *wcol, rcti *rect, int UNUSED(sta
widget_init(&wtb);
/* rounded, but no outline */
- wtb.outline = 0;
+ wtb.draw_outline = false;
rad = 0.2f * U.widget_unit;
round_box_edges(&wtb, UI_CNR_ALL, rect, rad);
@@ -3156,7 +3294,6 @@ static void widget_radiobut(uiWidgetColors *wcol, rcti *rect, int UNUSED(state),
round_box_edges(&wtb, roundboxalign, rect, rad);
widgetbase_draw(&wtb, wcol);
-
}
static void widget_box(uiBut *but, uiWidgetColors *wcol, rcti *rect, int UNUSED(state), int roundboxalign)
@@ -3197,7 +3334,6 @@ static void widget_but(uiWidgetColors *wcol, rcti *rect, int UNUSED(state), int
round_box_edges(&wtb, roundboxalign, rect, rad);
widgetbase_draw(&wtb, wcol);
-
}
static void widget_roundbut(uiWidgetColors *wcol, rcti *rect, int UNUSED(state), int roundboxalign)
@@ -3238,10 +3374,9 @@ static void widget_draw_extra_mask(const bContext *C, uiBut *but, uiWidgetType *
/* outline */
round_box_edges(&wtb, UI_CNR_ALL, rect, rad);
- wtb.outline = 1;
- wtb.inner = 0;
+ wtb.draw_outline = true;
+ wtb.draw_inner = false;
widgetbase_draw(&wtb, &wt->wcol);
-
}
static uiWidgetType *widget_type(uiWidgetTypeEnum type)
@@ -3270,7 +3405,7 @@ static uiWidgetType *widget_type(uiWidgetTypeEnum type)
wt.wcol_theme = &btheme->tui.wcol_toggle;
break;
- case UI_WTYPE_OPTION:
+ case UI_WTYPE_CHECKBOX:
wt.wcol_theme = &btheme->tui.wcol_option;
wt.draw = widget_optionbut;
break;
@@ -3374,8 +3509,8 @@ static uiWidgetType *widget_type(uiWidgetTypeEnum type)
case UI_WTYPE_RGB_PICKER:
break;
- case UI_WTYPE_NORMAL:
- wt.custom = widget_normal;
+ case UI_WTYPE_UNITVEC:
+ wt.custom = widget_unitvec;
break;
case UI_WTYPE_SCROLL:
@@ -3410,7 +3545,7 @@ static int widget_roundbox_set(uiBut *but, rcti *rect)
int roundbox = UI_CNR_ALL;
/* alignment */
- if ((but->drawflag & UI_BUT_ALIGN) && but->type != PULLDOWN) {
+ if ((but->drawflag & UI_BUT_ALIGN) && but->type != UI_BTYPE_PULLDOWN) {
/* ui_block_position has this correction too, keep in sync */
if (but->drawflag & UI_BUT_ALIGN_TOP)
@@ -3451,34 +3586,17 @@ static int widget_roundbox_set(uiBut *but, rcti *rect)
/* align with open menu */
if (but->active) {
- int direction = ui_button_open_menu_direction(but);
+ int direction = ui_but_menu_direction(but);
- if (direction == UI_TOP) roundbox &= ~(UI_CNR_TOP_RIGHT | UI_CNR_TOP_LEFT);
- else if (direction == UI_DOWN) roundbox &= ~(UI_CNR_BOTTOM_RIGHT | UI_CNR_BOTTOM_LEFT);
- else if (direction == UI_LEFT) roundbox &= ~(UI_CNR_TOP_LEFT | UI_CNR_BOTTOM_LEFT);
- else if (direction == UI_RIGHT) roundbox &= ~(UI_CNR_TOP_RIGHT | UI_CNR_BOTTOM_RIGHT);
+ if (direction == UI_DIR_UP) roundbox &= ~(UI_CNR_TOP_RIGHT | UI_CNR_TOP_LEFT);
+ else if (direction == UI_DIR_DOWN) roundbox &= ~(UI_CNR_BOTTOM_RIGHT | UI_CNR_BOTTOM_LEFT);
+ else if (direction == UI_DIR_LEFT) roundbox &= ~(UI_CNR_TOP_LEFT | UI_CNR_BOTTOM_LEFT);
+ else if (direction == UI_DIR_RIGHT) roundbox &= ~(UI_CNR_TOP_RIGHT | UI_CNR_BOTTOM_RIGHT);
}
return roundbox;
}
-/* put all widget colors on half alpha, use local storage */
-static void ui_widget_color_disabled(uiWidgetType *wt)
-{
- static uiWidgetColors wcol_theme_s;
-
- wcol_theme_s = *wt->wcol_theme;
-
- wcol_theme_s.outline[3] *= 0.5;
- wcol_theme_s.inner[3] *= 0.5;
- wcol_theme_s.inner_sel[3] *= 0.5;
- wcol_theme_s.item[3] *= 0.5;
- wcol_theme_s.text[3] *= 0.5;
- wcol_theme_s.text_sel[3] *= 0.5;
-
- wt->wcol_theme = &wcol_theme_s;
-}
-
/* conversion from old to new buttons, so still messy */
void ui_draw_but(const bContext *C, ARegion *ar, uiStyle *style, uiBut *but, rcti *rect)
{
@@ -3488,12 +3606,12 @@ void ui_draw_but(const bContext *C, ARegion *ar, uiStyle *style, uiBut *but, rct
uiWidgetType *wt = NULL;
/* handle menus separately */
- if (but->dt == UI_EMBOSSP) {
+ if (but->dt == UI_EMBOSS_PULLDOWN) {
switch (but->type) {
- case LABEL:
+ case UI_BTYPE_LABEL:
widget_draw_text_icon(&style->widgetlabel, &tui->wcol_menu_back, but, rect);
break;
- case SEPRLINE:
+ case UI_BTYPE_SEPR_LINE:
ui_draw_separator(rect, &tui->wcol_menu_item);
break;
default:
@@ -3501,17 +3619,18 @@ void ui_draw_but(const bContext *C, ARegion *ar, uiStyle *style, uiBut *but, rct
break;
}
}
- else if (but->dt == UI_EMBOSSN) {
+ else if (but->dt == UI_EMBOSS_NONE) {
/* "nothing" */
wt = widget_type(UI_WTYPE_ICON);
}
- else if (but->dt == UI_EMBOSSR) {
+ else if (but->dt == UI_EMBOSS_RADIAL) {
wt = widget_type(UI_WTYPE_MENU_ITEM_RADIAL);
}
else {
-
+ BLI_assert(but->dt == UI_EMBOSS);
+
switch (but->type) {
- case LABEL:
+ case UI_BTYPE_LABEL:
if (but->block->flag & UI_BLOCK_LOOP)
widget_draw_text_icon(&style->widgetlabel, &tui->wcol_menu_back, but, rect);
else {
@@ -3520,51 +3639,50 @@ void ui_draw_but(const bContext *C, ARegion *ar, uiStyle *style, uiBut *but, rct
}
break;
- case SEPR:
- case SEPRLINE:
+ case UI_BTYPE_SEPR:
+ case UI_BTYPE_SEPR_LINE:
break;
- case BUT:
+ case UI_BTYPE_BUT:
wt = widget_type(UI_WTYPE_EXEC);
break;
- case NUM:
+ case UI_BTYPE_NUM:
wt = widget_type(UI_WTYPE_NUMBER);
break;
- case NUMSLI:
+ case UI_BTYPE_NUM_SLIDER:
wt = widget_type(UI_WTYPE_SLIDER);
break;
- case ROW:
+ case UI_BTYPE_ROW:
wt = widget_type(UI_WTYPE_RADIO);
break;
- case LISTROW:
+ case UI_BTYPE_LISTROW:
wt = widget_type(UI_WTYPE_LISTITEM);
break;
- case TEX:
+ case UI_BTYPE_TEXT:
wt = widget_type(UI_WTYPE_NAME);
break;
-
- case SEARCH_MENU_UNLINK:
- case SEARCH_MENU:
+
+ case UI_BTYPE_SEARCH_MENU:
wt = widget_type(UI_WTYPE_NAME);
if (but->block->flag & UI_BLOCK_LOOP)
wt->wcol_theme = &btheme->tui.wcol_menu_back;
break;
- case TOGBUT:
- case TOG:
- case TOGN:
+ case UI_BTYPE_BUT_TOGGLE:
+ case UI_BTYPE_TOGGLE:
+ case UI_BTYPE_TOGGLE_N:
wt = widget_type(UI_WTYPE_TOGGLE);
break;
- case OPTION:
- case OPTIONN:
+ case UI_BTYPE_CHECKBOX:
+ case UI_BTYPE_CHECKBOX_N:
if (!(but->flag & UI_HAS_ICON)) {
- wt = widget_type(UI_WTYPE_OPTION);
+ wt = widget_type(UI_WTYPE_CHECKBOX);
but->drawflag |= UI_BUT_TEXT_LEFT;
}
else
@@ -3576,8 +3694,8 @@ void ui_draw_but(const bContext *C, ARegion *ar, uiStyle *style, uiBut *but, rct
break;
- case MENU:
- case BLOCK:
+ case UI_BTYPE_MENU:
+ case UI_BTYPE_BLOCK:
if (but->flag & UI_BUT_NODE_LINK) {
/* new node-link button, not active yet XXX */
wt = widget_type(UI_WTYPE_MENU_NODE_LINK);
@@ -3589,7 +3707,7 @@ void ui_draw_but(const bContext *C, ARegion *ar, uiStyle *style, uiBut *but, rct
* add updown arrows if there is room. */
if ((!but->str[0] && but->icon && (BLI_rcti_size_x(rect) < BLI_rcti_size_y(rect) + 2)) ||
/* disable for brushes also */
- (but->flag & UI_ICON_PREVIEW))
+ (but->flag & UI_BUT_ICON_PREVIEW))
{
/* no arrows */
wt = widget_type(UI_WTYPE_MENU_ICON_RADIO);
@@ -3600,35 +3718,35 @@ void ui_draw_but(const bContext *C, ARegion *ar, uiStyle *style, uiBut *but, rct
}
break;
- case PULLDOWN:
+ case UI_BTYPE_PULLDOWN:
wt = widget_type(UI_WTYPE_PULLDOWN);
break;
- case BUTM:
+ case UI_BTYPE_BUT_MENU:
wt = widget_type(UI_WTYPE_MENU_ITEM);
break;
- case COLOR:
+ case UI_BTYPE_COLOR:
wt = widget_type(UI_WTYPE_SWATCH);
break;
- case ROUNDBOX:
- case LISTBOX:
+ case UI_BTYPE_ROUNDBOX:
+ case UI_BTYPE_LISTBOX:
wt = widget_type(UI_WTYPE_BOX);
break;
- case LINK:
- case INLINK:
+ case UI_BTYPE_LINK:
+ case UI_BTYPE_INLINK:
wt = widget_type(UI_WTYPE_ICON);
wt->custom = widget_link;
break;
- case BUT_EXTRA:
+ case UI_BTYPE_EXTRA:
widget_draw_extra_mask(C, but, widget_type(UI_WTYPE_BOX), rect);
break;
- case HSVCUBE:
+ case UI_BTYPE_HSVCUBE:
if (ELEM(but->a1, UI_GRAD_V_ALT, UI_GRAD_L_ALT)) { /* vertical V slider, uses new widget draw now */
ui_draw_but_HSV_v(but, rect);
}
@@ -3637,56 +3755,56 @@ void ui_draw_but(const bContext *C, ARegion *ar, uiStyle *style, uiBut *but, rct
}
break;
- case HSVCIRCLE:
+ case UI_BTYPE_HSVCIRCLE:
ui_draw_but_HSVCIRCLE(but, &tui->wcol_regular, rect);
break;
- case BUT_COLORBAND:
+ case UI_BTYPE_COLORBAND:
ui_draw_but_COLORBAND(but, &tui->wcol_regular, rect);
break;
- case BUT_NORMAL:
- wt = widget_type(UI_WTYPE_NORMAL);
+ case UI_BTYPE_UNITVEC:
+ wt = widget_type(UI_WTYPE_UNITVEC);
break;
- case BUT_IMAGE:
+ case UI_BTYPE_IMAGE:
ui_draw_but_IMAGE(ar, but, &tui->wcol_regular, rect);
break;
- case HISTOGRAM:
+ case UI_BTYPE_HISTOGRAM:
ui_draw_but_HISTOGRAM(ar, but, &tui->wcol_regular, rect);
break;
- case WAVEFORM:
+ case UI_BTYPE_WAVEFORM:
ui_draw_but_WAVEFORM(ar, but, &tui->wcol_regular, rect);
break;
- case VECTORSCOPE:
+ case UI_BTYPE_VECTORSCOPE:
ui_draw_but_VECTORSCOPE(ar, but, &tui->wcol_regular, rect);
break;
- case BUT_CURVE:
+ case UI_BTYPE_CURVE:
ui_draw_but_CURVE(ar, but, &tui->wcol_regular, rect);
break;
- case PROGRESSBAR:
+ case UI_BTYPE_PROGRESS_BAR:
wt = widget_type(UI_WTYPE_PROGRESSBAR);
fstyle = &style->widgetlabel;
break;
- case SCROLL:
+ case UI_BTYPE_SCROLL:
wt = widget_type(UI_WTYPE_SCROLL);
break;
- case GRIP:
+ case UI_BTYPE_GRIP:
wt = widget_type(UI_WTYPE_ICON);
break;
- case TRACKPREVIEW:
+ case UI_BTYPE_TRACK_PREVIEW:
ui_draw_but_TRACKPREVIEW(ar, but, &tui->wcol_regular, rect);
break;
- case NODESOCKET:
+ case UI_BTYPE_NODE_SOCKET:
ui_draw_but_NODESOCKET(ar, but, &tui->wcol_regular, rect);
break;
@@ -3706,24 +3824,24 @@ void ui_draw_but(const bContext *C, ARegion *ar, uiStyle *style, uiBut *but, rct
state = but->flag;
if ((but->editstr) ||
- (UNLIKELY(but->flag & UI_BUT_DRAG_MULTI) && ui_get_but_drag_multi_edit(but)))
+ (UNLIKELY(but->flag & UI_BUT_DRAG_MULTI) && ui_but_drag_multi_edit_get(but)))
{
state |= UI_TEXTINPUT;
}
if (state & (UI_BUT_DISABLED | UI_BUT_INACTIVE))
- if (but->dt != UI_EMBOSSP)
+ if (but->dt != UI_EMBOSS_PULLDOWN)
disabled = true;
if (disabled)
ui_widget_color_disabled(wt);
-
+
wt->state(wt, state);
if (wt->custom)
wt->custom(but, &wt->wcol, rect, state, roundboxalign);
else if (wt->draw)
wt->draw(&wt->wcol, rect, state, roundboxalign);
-
+
if (disabled)
glEnable(GL_BLEND);
wt->text(fstyle, &wt->wcol, but, rect);
@@ -3731,7 +3849,7 @@ void ui_draw_but(const bContext *C, ARegion *ar, uiStyle *style, uiBut *but, rct
glDisable(GL_BLEND);
// if (state & (UI_BUT_DISABLED | UI_BUT_INACTIVE))
-// if (but->dt != UI_EMBOSSP)
+// if (but->dt != UI_EMBOSS_PULLDOWN)
// widget_disabled(&disablerect);
}
}
@@ -3750,12 +3868,12 @@ void ui_draw_menu_back(uiStyle *UNUSED(style), uiBlock *block, rcti *rect)
if (block->flag & UI_BLOCK_CLIPTOP) {
/* XXX no scaling for UI here yet */
glColor3ubv((unsigned char *)wt->wcol.text);
- UI_DrawTriIcon(BLI_rcti_cent_x(rect), rect->ymax - 8, 't');
+ UI_draw_icon_tri(BLI_rcti_cent_x(rect), rect->ymax - 8, 't');
}
if (block->flag & UI_BLOCK_CLIPBOTTOM) {
/* XXX no scaling for UI here yet */
glColor3ubv((unsigned char *)wt->wcol.text);
- UI_DrawTriIcon(BLI_rcti_cent_x(rect), rect->ymin + 10, 'v');
+ UI_draw_icon_tri(BLI_rcti_cent_x(rect), rect->ymin + 10, 'v');
}
}
}
@@ -3825,7 +3943,6 @@ static void draw_disk_shaded(
glVertex2f(c * radius_ext, s * radius_ext);
}
glEnd();
-
}
void ui_draw_pie_center(uiBlock *block)
@@ -3842,7 +3959,7 @@ void ui_draw_pie_center(uiBlock *block)
int subd = 40;
float angle = atan2f(pie_dir[1], pie_dir[0]);
- float range = (block->pie_data.flags & UI_PIE_DEGREES_RANGE_LARGE) ? ((float)M_PI / 2.0f) : ((float)M_PI / 4.0f);
+ float range = (block->pie_data.flags & UI_PIE_DEGREES_RANGE_LARGE) ? M_PI_2 : M_PI_4;
glPushMatrix();
glTranslatef(cx, cy, 0.0f);
@@ -3874,6 +3991,14 @@ void ui_draw_pie_center(uiBlock *block)
glutil_draw_lined_arc(0.0f, (float)M_PI * 2.0f, pie_radius_internal, subd);
glutil_draw_lined_arc(0.0f, (float)M_PI * 2.0f, pie_radius_external, subd);
+ if (U.pie_menu_confirm > 0 && !(block->pie_data.flags & (UI_PIE_INVALID_DIR | UI_PIE_CLICK_STYLE))) {
+ float pie_confirm_radius = U.pixelsize * (pie_radius_internal + U.pie_menu_confirm);
+ float pie_confirm_external = U.pixelsize * (pie_radius_internal + U.pie_menu_confirm + 7.0f);
+
+ glColor4ub(btheme->tui.wcol_pie_menu.text_sel[0], btheme->tui.wcol_pie_menu.text_sel[1], btheme->tui.wcol_pie_menu.text_sel[2], 64);
+ draw_disk_shaded(angle - range / 2.0f, range, pie_confirm_radius, pie_confirm_external, subd, NULL, NULL, false);
+ }
+
glDisable(GL_BLEND);
glPopMatrix();
}
@@ -3906,7 +4031,6 @@ void ui_draw_search_back(uiStyle *UNUSED(style), uiBlock *block, rcti *rect)
wt->draw(&wt->wcol, rect, block->flag, UI_CNR_ALL);
else
wt->draw(&wt->wcol, rect, 0, UI_CNR_ALL);
-
}
@@ -3921,7 +4045,7 @@ void ui_draw_menu_item(uiFontStyle *fstyle, rcti *rect, const char *name, int ic
wt->state(wt, state);
wt->draw(&wt->wcol, rect, 0, 0);
- uiStyleFontSet(fstyle);
+ UI_fontstyle_set(fstyle);
fstyle->align = UI_STYLE_TEXT_LEFT;
/* text location offset */
@@ -3935,7 +4059,7 @@ void ui_draw_menu_item(uiFontStyle *fstyle, rcti *rect, const char *name, int ic
*cpoin = 0;
/* need to set this first */
- uiStyleFontSet(fstyle);
+ UI_fontstyle_set(fstyle);
if (fstyle->kerning == 1) { /* for BLF_width */
BLF_enable(fstyle->uifont_id, BLF_KERNING_DEFAULT);
@@ -3956,10 +4080,10 @@ void ui_draw_menu_item(uiFontStyle *fstyle, rcti *rect, const char *name, int ic
const float minwidth = (float)(UI_DPI_ICON_SIZE);
BLI_strncpy(drawstr, name, sizeof(drawstr));
- ui_text_clip_middle_ex(fstyle, drawstr, okwidth, minwidth, max_len, NULL);
+ UI_text_clip_middle_ex(fstyle, drawstr, okwidth, minwidth, max_len, '\0');
glColor4ubv((unsigned char *)wt->wcol.text);
- uiStyleFontDraw(fstyle, rect, drawstr);
+ UI_fontstyle_draw(fstyle, rect, drawstr);
}
/* part text right aligned */
@@ -3967,7 +4091,7 @@ void ui_draw_menu_item(uiFontStyle *fstyle, rcti *rect, const char *name, int ic
if (cpoin) {
fstyle->align = UI_STYLE_TEXT_RIGHT;
rect->xmax = _rect.xmax - 5;
- uiStyleFontDraw(fstyle, rect, cpoin + 1);
+ UI_fontstyle_draw(fstyle, rect, cpoin + 1);
*cpoin = UI_SEP_CHAR;
}
}
@@ -3991,39 +4115,31 @@ void ui_draw_menu_item(uiFontStyle *fstyle, rcti *rect, const char *name, int ic
void ui_draw_preview_item(uiFontStyle *fstyle, rcti *rect, const char *name, int iconid, int state)
{
- rcti trect = *rect, bg_rect;
+ rcti trect = *rect;
+ const float text_size = UI_UNIT_Y;
float font_dims[2] = {0.0f, 0.0f};
uiWidgetType *wt = widget_type(UI_WTYPE_MENU_ITEM);
+ /* drawing button background */
wt->state(wt, state);
wt->draw(&wt->wcol, rect, 0, 0);
+ /* draw icon in rect above the space reserved for the label */
+ rect->ymin += text_size;
glEnable(GL_BLEND);
widget_draw_preview(iconid, 1.0f, rect);
+ glDisable(GL_BLEND);
BLF_width_and_height(fstyle->uifont_id, name, BLF_DRAW_STR_DUMMY_MAX, &font_dims[0], &font_dims[1]);
/* text rect */
trect.xmin += 0;
- trect.xmax = trect.xmin + font_dims[0] + 10;
- trect.ymin += 10;
+ trect.xmax = trect.xmin + font_dims[0] + U.widget_unit / 2;
+ trect.ymin += U.widget_unit / 2;
trect.ymax = trect.ymin + font_dims[1];
if (trect.xmax > rect->xmax - PREVIEW_PAD)
trect.xmax = rect->xmax - PREVIEW_PAD;
- bg_rect = trect;
- bg_rect.xmin = rect->xmin + PREVIEW_PAD;
- bg_rect.ymin = rect->ymin + PREVIEW_PAD;
- bg_rect.xmax = rect->xmax - PREVIEW_PAD;
- bg_rect.ymax += PREVIEW_PAD / 2;
-
- if (bg_rect.xmax > rect->xmax - PREVIEW_PAD)
- bg_rect.xmax = rect->xmax - PREVIEW_PAD;
-
- glColor4ubv((unsigned char *)wt->wcol_theme->inner_sel);
- glRecti(bg_rect.xmin, bg_rect.ymin, bg_rect.xmax, bg_rect.ymax);
- glDisable(GL_BLEND);
-
{
char drawstr[UI_MAX_DRAW_STR];
const float okwidth = (float)BLI_rcti_size_x(&trect);
@@ -4031,9 +4147,9 @@ void ui_draw_preview_item(uiFontStyle *fstyle, rcti *rect, const char *name, int
const float minwidth = (float)(UI_DPI_ICON_SIZE);
BLI_strncpy(drawstr, name, sizeof(drawstr));
- ui_text_clip_middle_ex(fstyle, drawstr, okwidth, minwidth, max_len, NULL);
+ UI_text_clip_middle_ex(fstyle, drawstr, okwidth, minwidth, max_len, '\0');
glColor4ubv((unsigned char *)wt->wcol.text);
- uiStyleFontDraw(fstyle, &trect, drawstr);
+ UI_fontstyle_draw(fstyle, &trect, drawstr);
}
}
diff --git a/source/blender/editors/interface/resources.c b/source/blender/editors/interface/resources.c
index 0879f335c68..568f7569e0b 100644
--- a/source/blender/editors/interface/resources.c
+++ b/source/blender/editors/interface/resources.c
@@ -45,6 +45,7 @@
#include "BLI_utildefines.h"
#include "BLI_math.h"
+#include "BKE_appdir.h"
#include "BKE_DerivedMesh.h"
#include "BKE_global.h"
#include "BKE_main.h"
@@ -60,9 +61,16 @@
/* global for themes */
typedef void (*VectorDrawFunc)(int x, int y, int w, int h, float alpha);
-static bTheme *theme_active = NULL;
-static int theme_spacetype = SPACE_VIEW3D;
-static int theme_regionid = RGN_TYPE_WINDOW;
+/* be sure to keep 'bThemeState' in sync */
+static struct bThemeState g_theme_state = {
+ NULL,
+ SPACE_VIEW3D,
+ RGN_TYPE_WINDOW,
+};
+
+#define theme_active g_theme_state.theme
+#define theme_spacetype g_theme_state.spacetype
+#define theme_regionid g_theme_state.regionid
void ui_resources_init(void)
{
@@ -271,6 +279,8 @@ const unsigned char *UI_ThemeGetColorPtr(bTheme *btheme, int spacetype, int colo
cp = ts->view_overlay; break;
case TH_WIRE:
cp = ts->wire; break;
+ case TH_WIRE_INNER:
+ cp = ts->syntaxr; break;
case TH_WIRE_EDIT:
cp = ts->wire_edit; break;
case TH_LAMP:
@@ -369,6 +379,10 @@ const unsigned char *UI_ThemeGetColorPtr(bTheme *btheme, int spacetype, int colo
cp = ts->keyborder_select; break;
case TH_CFRAME:
cp = ts->cframe; break;
+ case TH_TIME_KEYFRAME:
+ cp = ts->time_keyframe; break;
+ case TH_TIME_GP_KEYFRAME:
+ cp = ts->time_gp_keyframe; break;
case TH_NURB_ULINE:
cp = ts->nurb_uline; break;
case TH_NURB_VLINE:
@@ -503,6 +517,17 @@ const unsigned char *UI_ThemeGetColorPtr(bTheme *btheme, int spacetype, int colo
case TH_HANDLE_VERTEX_SIZE:
cp = &ts->handle_vertex_size;
break;
+
+ case TH_GP_VERTEX:
+ cp = ts->gp_vertex;
+ break;
+ case TH_GP_VERTEX_SELECT:
+ cp = ts->gp_vertex_select;
+ break;
+ case TH_GP_VERTEX_SIZE:
+ cp = &ts->gp_vertex_size;
+ break;
+
case TH_DOPESHEET_CHANNELOB:
cp = ts->ds_channel;
break;
@@ -544,6 +569,13 @@ const unsigned char *UI_ThemeGetColorPtr(bTheme *btheme, int spacetype, int colo
cp = ts->paint_curve_pivot;
break;
+ case TH_METADATA_BG:
+ cp = ts->metadatabg;
+ break;
+ case TH_METADATA_TEXT:
+ cp = ts->metadatatext;
+ break;
+
case TH_UV_OTHERS:
cp = ts->uv_others;
break;
@@ -617,6 +649,9 @@ const unsigned char *UI_ThemeGetColorPtr(bTheme *btheme, int spacetype, int colo
cp = ts->nla_sound_sel;
break;
+ case TH_WIDGET_EMBOSS:
+ cp = btheme->tui.widget_emboss; break;
+
case TH_AXIS_X:
cp = btheme->tui.xaxis; break;
case TH_AXIS_Y:
@@ -654,11 +689,14 @@ const unsigned char *UI_ThemeGetColorPtr(bTheme *btheme, int spacetype, int colo
case TH_INFO_DEBUG_TEXT:
cp = ts->info_debug_text;
break;
+ case TH_V3D_CLIPPING_BORDER:
+ cp = ts->clipping_border_3d;
+ break;
}
}
}
- return (unsigned char *)cp;
+ return (const unsigned char *)cp;
}
/* use this call to init new bone color sets in Theme */
@@ -786,8 +824,9 @@ static void ui_theme_space_init_handles_color(ThemeSpace *theme_space)
rgba_char_args_set(theme_space->act_spline, 0xdb, 0x25, 0x12, 255);
}
-/* initialize default theme
- * Note: when you add new colors, created & saved themes need initialized
+/**
+ * initialize default theme
+ * \note: when you add new colors, created & saved themes need initialized
* use function below, init_userdef_do_versions()
*/
void ui_theme_init_default(void)
@@ -813,6 +852,10 @@ void ui_theme_init_default(void)
btheme->tui.panel.show_header = false;
rgba_char_args_set(btheme->tui.panel.header, 0, 0, 0, 25);
+ rgba_char_args_set(btheme->tui.wcol_tooltip.text, 255, 255, 255, 255);
+
+ rgba_char_args_set_fl(btheme->tui.widget_emboss, 1.0f, 1.0f, 1.0f, 0.02f);
+
rgba_char_args_set(btheme->tui.xaxis, 220, 0, 0, 255);
rgba_char_args_set(btheme->tui.yaxis, 0, 220, 0, 255);
rgba_char_args_set(btheme->tui.zaxis, 0, 0, 220, 255);
@@ -883,6 +926,9 @@ void ui_theme_init_default(void)
rgba_char_args_set(btheme->tv3d.freestyle_face_mark, 0x7f, 0xff, 0x7f, 51);
rgba_char_args_set_fl(btheme->tv3d.paint_curve_handle, 0.5f, 1.0f, 0.5f, 0.5f);
rgba_char_args_set_fl(btheme->tv3d.paint_curve_pivot, 1.0f, 0.5f, 0.5f, 0.5f);
+ rgba_char_args_set(btheme->tv3d.gp_vertex, 0, 0, 0, 255);
+ rgba_char_args_set(btheme->tv3d.gp_vertex_select, 255, 133, 0, 255);
+ btheme->tv3d.gp_vertex_size = 3;
btheme->tv3d.facedot_size = 4;
@@ -916,6 +962,7 @@ void ui_theme_init_default(void)
rgba_char_args_set(btheme->tv3d.gradients.high_gradient, 58, 58, 58, 255);
btheme->tv3d.gradients.show_grad = false;
+ rgba_char_args_set(btheme->tv3d.clipping_border_3d, 50, 50, 50, 255);
/* space buttons */
/* to have something initialized */
btheme->tbuts = btheme->tv3d;
@@ -1030,7 +1077,7 @@ void ui_theme_init_default(void)
rgba_char_args_set(btheme->tima.face, 255, 255, 255, 10);
rgba_char_args_set(btheme->tima.face_select, 255, 133, 0, 60);
rgba_char_args_set(btheme->tima.editmesh_active, 255, 255, 255, 128);
- rgba_char_args_set_fl(btheme->tima.preview_back, 0.45, 0.45, 0.45, 1.0);
+ rgba_char_args_set_fl(btheme->tima.preview_back, 0.0, 0.0, 0.0, 0.3);
rgba_char_args_set_fl(btheme->tima.preview_stitch_face, 0.5, 0.5, 0.0, 0.2);
rgba_char_args_set_fl(btheme->tima.preview_stitch_edge, 1.0, 0.0, 1.0, 0.2);
rgba_char_args_set_fl(btheme->tima.preview_stitch_vert, 0.0, 0.0, 1.0, 0.2);
@@ -1059,7 +1106,7 @@ void ui_theme_init_default(void)
rgba_char_args_set(btheme->text.syntaxd, 50, 0, 140, 255); /* Decorator/Preprocessor Dir. Blue-purple */
rgba_char_args_set(btheme->text.syntaxr, 140, 60, 0, 255); /* Reserved Orange*/
rgba_char_args_set(btheme->text.syntaxb, 128, 0, 80, 255); /* Builtin Red-purple */
- rgba_char_args_set(btheme->text.syntaxs, 76, 76, 76, 255); /* Grey (mix between fg/bg) */
+ rgba_char_args_set(btheme->text.syntaxs, 76, 76, 76, 255); /* Gray (mix between fg/bg) */
/* space oops */
btheme->toops = btheme->tv3d;
@@ -1102,8 +1149,12 @@ void ui_theme_init_default(void)
rgba_char_args_set_fl(btheme->ttime.grid, 0.36, 0.36, 0.36, 1.0);
rgba_char_args_set(btheme->ttime.shade1, 173, 173, 173, 255); /* sliders */
+ rgba_char_args_set(btheme->ttime.time_keyframe, 0xDD, 0xD7, 0x00, 1.0);
+ rgba_char_args_set(btheme->ttime.time_gp_keyframe, 0xB5, 0xE6, 0x1D, 1.0);
+
/* space node, re-uses syntax and console color storage */
btheme->tnode = btheme->tv3d;
+ rgba_char_args_set(btheme->tnode.syntaxr, 115, 115, 115, 255); /* wire inner color */
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 */
@@ -1183,6 +1234,18 @@ bTheme *UI_GetTheme(void)
return U.themes.first;
}
+/**
+ * for the rare case we need to temp swap in a different theme (offscreen render)
+ */
+void UI_Theme_Store(struct bThemeState *theme_state)
+{
+ *theme_state = g_theme_state;
+}
+void UI_Theme_Restore(struct bThemeState *theme_state)
+{
+ g_theme_state = *theme_state;
+}
+
/* for space windows only */
void UI_ThemeColor(int colorid)
{
@@ -1449,8 +1512,9 @@ void UI_GetColorPtrShade3ubv(const unsigned char cp[3], unsigned char col[3], in
}
/* get a 3 byte color, blended and shaded between two other char color pointers */
-void UI_GetColorPtrBlendShade3ubv(const unsigned char cp1[3], const unsigned char cp2[3], unsigned char col[3],
- float fac, int offset)
+void UI_GetColorPtrBlendShade3ubv(
+ const unsigned char cp1[3], const unsigned char cp2[3], unsigned char col[3],
+ float fac, int offset)
{
int r, g, b;
@@ -1473,9 +1537,17 @@ void UI_ThemeClearColor(int colorid)
float col[3];
UI_GetThemeColor3fv(colorid, col);
- glClearColor(col[0], col[1], col[2], 0.0);
+ glClearColor(col[0], col[1], col[2], 0.0f);
}
+void UI_ThemeClearColorAlpha(int colorid, float alpha)
+{
+ float col[3];
+ UI_GetThemeColor3fv(colorid, col);
+ glClearColor(col[0], col[1], col[2], alpha);
+}
+
+
int UI_ThemeMenuShadowWidth(void)
{
bTheme *btheme = UI_GetTheme();
@@ -1512,6 +1584,8 @@ void init_userdef_do_versions(void)
{
Main *bmain = G.main;
+#define USER_VERSION_ATLEAST(ver, subver) MAIN_VERSION_ATLEAST(bmain, ver, subver)
+
/* the UserDef struct is not corrected with do_versions() .... ugh! */
if (U.wheellinescroll == 0) U.wheellinescroll = 3;
if (U.menuthreshold1 == 0) {
@@ -1523,8 +1597,8 @@ void init_userdef_do_versions(void)
U.tb_rightmouse = 5;
}
if (U.mixbufsize == 0) U.mixbufsize = 2048;
- if (strcmp(U.tempdir, "/") == 0) {
- BLI_system_temporary_dir(U.tempdir);
+ if (STREQ(U.tempdir, "/")) {
+ BKE_tempdir_system_init(U.tempdir);
}
if (U.autokey_mode == 0) {
/* 'add/replace' but not on */
@@ -1540,8 +1614,8 @@ void init_userdef_do_versions(void)
U.tw_size = 25; /* percentage of window size */
U.tw_handlesize = 16; /* percentage of widget radius */
}
- if (U.pad_rot_angle == 0)
- U.pad_rot_angle = 15;
+ if (U.pad_rot_angle == 0.0f)
+ U.pad_rot_angle = 15.0f;
/* graph editor - unselected F-Curve visibility */
if (U.fcu_inactive_alpha == 0) {
@@ -1552,17 +1626,17 @@ void init_userdef_do_versions(void)
/* run in case this was on and is now off in the user prefs [#28096] */
vDM_ColorBand_store((U.flag & USER_CUSTOM_RANGE) ? (&U.coba_weight) : NULL, UI_GetTheme()->tv3d.vertex_unreferenced);
- if (bmain->versionfile <= 191) {
+ if (!USER_VERSION_ATLEAST(192, 0)) {
strcpy(U.sounddir, "/");
}
/* patch to set Dupli Armature */
- if (bmain->versionfile < 220) {
+ if (!USER_VERSION_ATLEAST(220, 0)) {
U.dupflag |= USER_DUP_ARM;
}
/* added seam, normal color, undo */
- if (bmain->versionfile <= 234) {
+ if (!USER_VERSION_ATLEAST(235, 0)) {
bTheme *btheme;
U.uiflag |= USER_GLOBALUNDO;
@@ -1585,12 +1659,12 @@ void init_userdef_do_versions(void)
}
}
}
- if (bmain->versionfile <= 235) {
+ if (!USER_VERSION_ATLEAST(236, 0)) {
/* illegal combo... */
if (U.flag & USER_LMOUSESELECT)
U.flag &= ~USER_TWOBUTTONMOUSE;
}
- if (bmain->versionfile <= 236) {
+ if (!USER_VERSION_ATLEAST(237, 0)) {
bTheme *btheme;
/* new space type */
for (btheme = U.themes.first; btheme; btheme = btheme->next) {
@@ -1611,7 +1685,7 @@ void init_userdef_do_versions(void)
}
}
}
- if (bmain->versionfile <= 237) {
+ if (!USER_VERSION_ATLEAST(238, 0)) {
bTheme *btheme;
/* bone colors */
for (btheme = U.themes.first; btheme; btheme = btheme->next) {
@@ -1622,7 +1696,7 @@ void init_userdef_do_versions(void)
}
}
}
- if (bmain->versionfile <= 238) {
+ if (!USER_VERSION_ATLEAST(239, 0)) {
bTheme *btheme;
/* bone colors */
for (btheme = U.themes.first; btheme; btheme = btheme->next) {
@@ -1633,7 +1707,7 @@ void init_userdef_do_versions(void)
}
}
}
- if (bmain->versionfile <= 239) {
+ if (!USER_VERSION_ATLEAST(240, 0)) {
bTheme *btheme;
for (btheme = U.themes.first; btheme; btheme = btheme->next) {
@@ -1647,7 +1721,7 @@ void init_userdef_do_versions(void)
}
if (U.obcenter_dia == 0) U.obcenter_dia = 6;
}
- if (bmain->versionfile <= 241) {
+ if (!USER_VERSION_ATLEAST(242, 0)) {
bTheme *btheme;
for (btheme = U.themes.first; btheme; btheme = btheme->next) {
/* Node editor theme, check for alpha==0 is safe, then color was never set */
@@ -1687,7 +1761,7 @@ void init_userdef_do_versions(void)
}
}
- if (bmain->versionfile <= 242) {
+ if (!USER_VERSION_ATLEAST(243, 0)) {
bTheme *btheme;
for (btheme = U.themes.first; btheme; btheme = btheme->next) {
@@ -1705,11 +1779,11 @@ void init_userdef_do_versions(void)
}
}
}
- if (bmain->versionfile <= 243) {
+ if (!USER_VERSION_ATLEAST(244, 0)) {
/* set default number of recently-used files (if not set) */
if (U.recent_files == 0) U.recent_files = 10;
}
- if (bmain->versionfile < 245 || (bmain->versionfile == 245 && bmain->subversionfile < 3)) {
+ if (!USER_VERSION_ATLEAST(245, 3)) {
bTheme *btheme;
for (btheme = U.themes.first; btheme; btheme = btheme->next) {
rgba_char_args_set(btheme->tv3d.editmesh_active, 255, 255, 255, 128);
@@ -1717,7 +1791,7 @@ void init_userdef_do_versions(void)
if (U.coba_weight.tot == 0)
init_colorband(&U.coba_weight, true);
}
- if ((bmain->versionfile < 245) || (bmain->versionfile == 245 && bmain->subversionfile < 11)) {
+ if (!USER_VERSION_ATLEAST(245, 3)) {
bTheme *btheme;
for (btheme = U.themes.first; btheme; btheme = btheme->next) {
/* these should all use the same color */
@@ -1730,7 +1804,7 @@ void init_userdef_do_versions(void)
rgba_char_args_set(btheme->ttime.cframe, 0x60, 0xc0, 0x40, 255);
}
}
- if ((bmain->versionfile < 245) || (bmain->versionfile == 245 && bmain->subversionfile < 13)) {
+ if (!USER_VERSION_ATLEAST(245, 3)) {
bTheme *btheme;
for (btheme = U.themes.first; btheme; btheme = btheme->next) {
/* action channel groups (recolor anyway) */
@@ -1742,10 +1816,10 @@ void init_userdef_do_versions(void)
ui_theme_init_boneColorSets(btheme);
}
}
- if ((bmain->versionfile < 245) || (bmain->versionfile == 245 && bmain->subversionfile < 16)) {
+ if (!USER_VERSION_ATLEAST(245, 3)) {
U.flag |= USER_ADD_VIEWALIGNED | USER_ADD_EDITMODE;
}
- if ((bmain->versionfile < 247) || (bmain->versionfile == 247 && bmain->subversionfile <= 2)) {
+ if (!USER_VERSION_ATLEAST(245, 3)) {
bTheme *btheme;
/* adjust themes */
@@ -1767,7 +1841,7 @@ void init_userdef_do_versions(void)
rgba_char_args_set(btheme->tseq.vertex_select, col[0], col[1], col[2], 255);
}
}
- if (bmain->versionfile < 250) {
+ if (!USER_VERSION_ATLEAST(250, 0)) {
bTheme *btheme;
for (btheme = U.themes.first; btheme; btheme = btheme->next) {
@@ -1808,7 +1882,7 @@ void init_userdef_do_versions(void)
U.ipo_new = BEZT_IPO_BEZ;
}
- if (bmain->versionfile < 250 || (bmain->versionfile == 250 && bmain->subversionfile < 1)) {
+ if (!USER_VERSION_ATLEAST(250, 1)) {
bTheme *btheme;
for (btheme = U.themes.first; btheme; btheme = btheme->next) {
@@ -1831,7 +1905,7 @@ void init_userdef_do_versions(void)
}
}
- if (bmain->versionfile < 250 || (bmain->versionfile == 250 && bmain->subversionfile < 3)) {
+ if (!USER_VERSION_ATLEAST(250, 3)) {
/* new audio system */
if (U.audiochannels == 0)
U.audiochannels = 2;
@@ -1849,59 +1923,60 @@ void init_userdef_do_versions(void)
U.audiorate = 44100;
}
- if (bmain->versionfile < 250 || (bmain->versionfile == 250 && bmain->subversionfile < 5))
+ if (!USER_VERSION_ATLEAST(250, 3)) {
U.gameflags |= USER_DISABLE_VBO;
+ }
- if (bmain->versionfile < 250 || (bmain->versionfile == 250 && bmain->subversionfile < 8)) {
+ if (!USER_VERSION_ATLEAST(250, 8)) {
wmKeyMap *km;
for (km = U.user_keymaps.first; km; km = km->next) {
- if (strcmp(km->idname, "Armature_Sketch") == 0)
+ if (STREQ(km->idname, "Armature_Sketch"))
strcpy(km->idname, "Armature Sketch");
- else if (strcmp(km->idname, "View3D") == 0)
+ else if (STREQ(km->idname, "View3D"))
strcpy(km->idname, "3D View");
- else if (strcmp(km->idname, "View3D Generic") == 0)
+ else if (STREQ(km->idname, "View3D Generic"))
strcpy(km->idname, "3D View Generic");
- else if (strcmp(km->idname, "EditMesh") == 0)
+ else if (STREQ(km->idname, "EditMesh"))
strcpy(km->idname, "Mesh");
- else if (strcmp(km->idname, "TimeLine") == 0)
+ else if (STREQ(km->idname, "TimeLine"))
strcpy(km->idname, "Timeline");
- else if (strcmp(km->idname, "UVEdit") == 0)
+ else if (STREQ(km->idname, "UVEdit"))
strcpy(km->idname, "UV Editor");
- else if (strcmp(km->idname, "Animation_Channels") == 0)
+ else if (STREQ(km->idname, "Animation_Channels"))
strcpy(km->idname, "Animation Channels");
- else if (strcmp(km->idname, "GraphEdit Keys") == 0)
+ else if (STREQ(km->idname, "GraphEdit Keys"))
strcpy(km->idname, "Graph Editor");
- else if (strcmp(km->idname, "GraphEdit Generic") == 0)
+ else if (STREQ(km->idname, "GraphEdit Generic"))
strcpy(km->idname, "Graph Editor Generic");
- else if (strcmp(km->idname, "Action_Keys") == 0)
+ else if (STREQ(km->idname, "Action_Keys"))
strcpy(km->idname, "Dopesheet");
- else if (strcmp(km->idname, "NLA Data") == 0)
+ else if (STREQ(km->idname, "NLA Data"))
strcpy(km->idname, "NLA Editor");
- else if (strcmp(km->idname, "Node Generic") == 0)
+ else if (STREQ(km->idname, "Node Generic"))
strcpy(km->idname, "Node Editor");
- else if (strcmp(km->idname, "Logic Generic") == 0)
+ else if (STREQ(km->idname, "Logic Generic"))
strcpy(km->idname, "Logic Editor");
- else if (strcmp(km->idname, "File") == 0)
+ else if (STREQ(km->idname, "File"))
strcpy(km->idname, "File Browser");
- else if (strcmp(km->idname, "FileMain") == 0)
+ else if (STREQ(km->idname, "FileMain"))
strcpy(km->idname, "File Browser Main");
- else if (strcmp(km->idname, "FileButtons") == 0)
+ else if (STREQ(km->idname, "FileButtons"))
strcpy(km->idname, "File Browser Buttons");
- else if (strcmp(km->idname, "Buttons Generic") == 0)
+ else if (STREQ(km->idname, "Buttons Generic"))
strcpy(km->idname, "Property Editor");
}
}
- if (bmain->versionfile < 250 || (bmain->versionfile == 250 && bmain->subversionfile < 16)) {
+ if (!USER_VERSION_ATLEAST(250, 16)) {
if (U.wmdrawmethod == USER_DRAW_TRIPLE)
U.wmdrawmethod = USER_DRAW_AUTOMATIC;
}
- if (bmain->versionfile < 252 || (bmain->versionfile == 252 && bmain->subversionfile < 3)) {
+ if (!USER_VERSION_ATLEAST(252, 3)) {
if (U.flag & USER_LMOUSESELECT)
U.flag &= ~USER_TWOBUTTONMOUSE;
}
- if (bmain->versionfile < 252 || (bmain->versionfile == 252 && bmain->subversionfile < 4)) {
+ if (!USER_VERSION_ATLEAST(252, 4)) {
bTheme *btheme;
/* default new handle type is auto handles */
@@ -1916,7 +1991,7 @@ void init_userdef_do_versions(void)
rgba_char_args_set_fl(btheme->tv3d.edge_crease, 0.8, 0, 0.6, 1.0);
}
}
- if (bmain->versionfile <= 252) {
+ if (!USER_VERSION_ATLEAST(253, 0)) {
bTheme *btheme;
/* init new curve colors */
@@ -1925,7 +2000,7 @@ void init_userdef_do_versions(void)
rgba_char_args_set(btheme->tv3d.lastsel_point, 0xff, 0xff, 0xff, 255);
}
}
- if (bmain->versionfile < 252 || (bmain->versionfile == 252 && bmain->subversionfile < 5)) {
+ if (!USER_VERSION_ATLEAST(252, 5)) {
bTheme *btheme;
/* interface_widgets.c */
@@ -1948,7 +2023,7 @@ void init_userdef_do_versions(void)
}
}
- if (bmain->versionfile < 255 || (bmain->versionfile == 255 && bmain->subversionfile < 2)) {
+ if (!USER_VERSION_ATLEAST(255, 2)) {
bTheme *btheme;
for (btheme = U.themes.first; btheme; btheme = btheme->next) {
rgba_char_args_set(btheme->tv3d.extra_edge_len, 32, 0, 0, 255);
@@ -1957,27 +2032,27 @@ void init_userdef_do_versions(void)
}
}
- if (bmain->versionfile < 256 || (bmain->versionfile == 256 && bmain->subversionfile < 4)) {
+ if (!USER_VERSION_ATLEAST(256, 4)) {
bTheme *btheme;
for (btheme = U.themes.first; btheme; btheme = btheme->next) {
if ((btheme->tv3d.outline_width) == 0) btheme->tv3d.outline_width = 1;
}
}
- if (bmain->versionfile < 257) {
+ if (!USER_VERSION_ATLEAST(257, 0)) {
/* clear "AUTOKEY_FLAG_ONLYKEYINGSET" flag from userprefs,
* so that it doesn't linger around from old configs like a ghost */
U.autokey_flag &= ~AUTOKEY_FLAG_ONLYKEYINGSET;
}
- if (bmain->versionfile < 258 || (bmain->versionfile == 258 && bmain->subversionfile < 2)) {
+ if (!USER_VERSION_ATLEAST(258, 2)) {
bTheme *btheme;
for (btheme = U.themes.first; btheme; btheme = btheme->next) {
btheme->tnode.noodle_curving = 5;
}
}
- if (bmain->versionfile < 259 || (bmain->versionfile == 259 && bmain->subversionfile < 1)) {
+ if (!USER_VERSION_ATLEAST(259, 1)) {
bTheme *btheme;
for (btheme = U.themes.first; btheme; btheme = btheme->next) {
@@ -1985,7 +2060,7 @@ void init_userdef_do_versions(void)
}
}
- if (bmain->versionfile < 260 || (bmain->versionfile == 260 && bmain->subversionfile < 3)) {
+ if (!USER_VERSION_ATLEAST(260, 3)) {
bTheme *btheme;
/* if new keyframes handle default is stuff "auto", make it "auto-clamped" instead
@@ -2034,7 +2109,7 @@ void init_userdef_do_versions(void)
}
}
- if (bmain->versionfile < 260 || (bmain->versionfile == 260 && bmain->subversionfile < 5)) {
+ if (!USER_VERSION_ATLEAST(260, 5)) {
bTheme *btheme;
for (btheme = U.themes.first; btheme; btheme = btheme->next) {
@@ -2043,7 +2118,7 @@ void init_userdef_do_versions(void)
}
}
- if (bmain->versionfile < 261 || (bmain->versionfile == 261 && bmain->subversionfile < 4)) {
+ if (!USER_VERSION_ATLEAST(261, 4)) {
bTheme *btheme;
for (btheme = U.themes.first; btheme; btheme = btheme->next) {
rgba_char_args_set_fl(btheme->tima.preview_stitch_face, 0.071, 0.259, 0.694, 0.150);
@@ -2060,7 +2135,7 @@ void init_userdef_do_versions(void)
U.use_16bit_textures = true;
}
- if (bmain->versionfile < 262 || (bmain->versionfile == 262 && bmain->subversionfile < 2)) {
+ if (!USER_VERSION_ATLEAST(262, 2)) {
bTheme *btheme;
for (btheme = U.themes.first; btheme; btheme = btheme->next) {
if (btheme->tui.wcol_menu_item.item[3] == 255)
@@ -2068,7 +2143,7 @@ void init_userdef_do_versions(void)
}
}
- if (bmain->versionfile < 262 || (bmain->versionfile == 262 && bmain->subversionfile < 3)) {
+ if (!USER_VERSION_ATLEAST(262, 3)) {
bTheme *btheme;
for (btheme = U.themes.first; btheme; btheme = btheme->next) {
if (btheme->tui.wcol_tooltip.inner[3] == 0) {
@@ -2080,7 +2155,7 @@ void init_userdef_do_versions(void)
}
}
- if (bmain->versionfile < 262 || (bmain->versionfile == 262 && bmain->subversionfile < 4)) {
+ if (!USER_VERSION_ATLEAST(262, 4)) {
bTheme *btheme;
for (btheme = U.themes.first; btheme; btheme = btheme->next) {
if (btheme->tseq.movieclip[3] == 0) {
@@ -2089,7 +2164,7 @@ void init_userdef_do_versions(void)
}
}
- if (bmain->versionfile < 263 || (bmain->versionfile == 263 && bmain->subversionfile < 2)) {
+ if (!USER_VERSION_ATLEAST(263, 2)) {
bTheme *btheme;
for (btheme = U.themes.first; btheme; btheme = btheme->next) {
if (btheme->tclip.strip[0] == 0) {
@@ -2100,13 +2175,13 @@ void init_userdef_do_versions(void)
}
}
- if (bmain->versionfile < 263 || (bmain->versionfile == 263 && bmain->subversionfile < 6)) {
+ if (!USER_VERSION_ATLEAST(263, 6)) {
bTheme *btheme;
for (btheme = U.themes.first; btheme; btheme = btheme->next)
rgba_char_args_set(btheme->tv3d.skin_root, 180, 77, 77, 255);
}
- if (bmain->versionfile < 263 || (bmain->versionfile == 263 && bmain->subversionfile < 7)) {
+ if (!USER_VERSION_ATLEAST(263, 7)) {
bTheme *btheme;
for (btheme = U.themes.first; btheme; btheme = btheme->next) {
@@ -2129,7 +2204,7 @@ void init_userdef_do_versions(void)
}
}
- if (bmain->versionfile < 263 || (bmain->versionfile == 263 && bmain->subversionfile < 11)) {
+ if (!USER_VERSION_ATLEAST(263, 11)) {
bTheme *btheme;
for (btheme = U.themes.first; btheme; btheme = btheme->next) {
if (btheme->tseq.mask[3] == 0) {
@@ -2138,14 +2213,14 @@ void init_userdef_do_versions(void)
}
}
- if (bmain->versionfile < 263 || (bmain->versionfile == 263 && bmain->subversionfile < 15)) {
+ if (!USER_VERSION_ATLEAST(263, 15)) {
bTheme *btheme;
for (btheme = U.themes.first; btheme; btheme = btheme->next) {
rgba_char_args_set(btheme->tv3d.bone_pose_active, 140, 255, 255, 80);
}
}
- if (bmain->versionfile < 263 || (bmain->versionfile == 263 && bmain->subversionfile < 16)) {
+ if (!USER_VERSION_ATLEAST(263, 16)) {
bTheme *btheme;
for (btheme = U.themes.first; btheme; btheme = btheme->next) {
@@ -2157,7 +2232,7 @@ void init_userdef_do_versions(void)
}
}
- if (bmain->versionfile < 263 || (bmain->versionfile == 263 && bmain->subversionfile < 22)) {
+ if (!USER_VERSION_ATLEAST(263, 22)) {
bTheme *btheme;
for (btheme = U.themes.first; btheme; btheme = btheme->next) {
@@ -2169,7 +2244,7 @@ void init_userdef_do_versions(void)
}
}
- if (bmain->versionfile < 264 || (bmain->versionfile == 264 && bmain->subversionfile < 9)) {
+ if (!USER_VERSION_ATLEAST(264, 9)) {
bTheme *btheme;
for (btheme = U.themes.first; btheme; btheme = btheme->next) {
@@ -2179,7 +2254,7 @@ void init_userdef_do_versions(void)
}
}
- if (U.versionfile < 267) {
+ if (!USER_VERSION_ATLEAST(267, 0)) {
/* Freestyle color settings */
bTheme *btheme;
@@ -2238,7 +2313,7 @@ void init_userdef_do_versions(void)
U.tweak_threshold = 10;
}
- if (bmain->versionfile < 265 || (bmain->versionfile == 265 && bmain->subversionfile < 1)) {
+ if (!USER_VERSION_ATLEAST(265, 1)) {
bTheme *btheme;
for (btheme = U.themes.first; btheme; btheme = btheme->next) {
@@ -2254,7 +2329,7 @@ void init_userdef_do_versions(void)
}
/* panel header/backdrop supported locally per editor now */
- if (bmain->versionfile < 265 || (bmain->versionfile == 265 && bmain->subversionfile < 2)) {
+ if (!USER_VERSION_ATLEAST(265, 2)) {
bTheme *btheme;
for (btheme = U.themes.first; btheme; btheme = btheme->next) {
@@ -2271,7 +2346,10 @@ void init_userdef_do_versions(void)
}
/* NOTE!! from now on use U.versionfile and U.subversionfile */
- if (U.versionfile < 266) {
+#undef USER_VERSION_ATLEAST
+#define USER_VERSION_ATLEAST(ver, subver) MAIN_VERSION_ATLEAST((&(U)), ver, subver)
+
+ if (!USER_VERSION_ATLEAST(266, 0)) {
bTheme *btheme;
for (btheme = U.themes.first; btheme; btheme = btheme->next) {
@@ -2283,23 +2361,23 @@ void init_userdef_do_versions(void)
}
}
- if (U.versionfile < 265 || (U.versionfile == 265 && U.subversionfile < 4)) {
+ if (!USER_VERSION_ATLEAST(265, 4)) {
bTheme *btheme;
for (btheme = U.themes.first; btheme; btheme = btheme->next) {
rgba_char_args_set(btheme->text.syntaxd, 50, 0, 140, 255); /* Decorator/Preprocessor Dir. Blue-purple */
rgba_char_args_set(btheme->text.syntaxr, 140, 60, 0, 255); /* Reserved Orange */
- rgba_char_args_set(btheme->text.syntaxs, 76, 76, 76, 255); /* Grey (mix between fg/bg) */
+ rgba_char_args_set(btheme->text.syntaxs, 76, 76, 76, 255); /* Gray (mix between fg/bg) */
}
}
- if (U.versionfile < 265 || (U.versionfile == 265 && U.subversionfile < 6)) {
+ if (!USER_VERSION_ATLEAST(265, 6)) {
bTheme *btheme;
for (btheme = U.themes.first; btheme; btheme = btheme->next) {
copy_v4_v4_char(btheme->tv3d.gradients.high_gradient, btheme->tv3d.back);
}
}
- if (U.versionfile < 265 || (U.versionfile == 265 && U.subversionfile < 9)) {
+ if (!USER_VERSION_ATLEAST(265, 9)) {
bTheme *btheme;
for (btheme = U.themes.first; btheme; btheme = btheme->next) {
rgba_char_args_test_set(btheme->tnode.syntaxs, 151, 116, 116, 255); /* matte nodes */
@@ -2307,23 +2385,21 @@ void init_userdef_do_versions(void)
}
}
- if (U.versionfile < 265 || (U.versionfile == 265 && U.subversionfile < 11)) {
+ if (!USER_VERSION_ATLEAST(265, 11)) {
bTheme *btheme;
for (btheme = U.themes.first; btheme; btheme = btheme->next) {
rgba_char_args_test_set(btheme->tconsole.console_select, 255, 255, 255, 48);
}
}
- if (U.versionfile < 266 || (U.versionfile == 266 && U.subversionfile < 2)) {
+ if (!USER_VERSION_ATLEAST(266, 2)) {
bTheme *btheme;
for (btheme = U.themes.first; btheme; btheme = btheme->next) {
rgba_char_args_test_set(btheme->tnode.console_output, 223, 202, 53, 255); /* interface nodes */
}
}
- /* NOTE!! from now on use U.versionfile and U.subversionfile */
-
- if (U.versionfile < 268 || (U.versionfile == 268 && U.subversionfile < 3)) {
+ if (!USER_VERSION_ATLEAST(268, 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);
@@ -2331,7 +2407,7 @@ void init_userdef_do_versions(void)
}
}
- if (U.versionfile < 269 || (U.versionfile == 269 && U.subversionfile < 5)) {
+ if (!USER_VERSION_ATLEAST(269, 5)) {
bTheme *btheme;
for (btheme = U.themes.first; btheme; btheme = btheme->next) {
rgba_char_args_set(btheme->tima.wire_edit, 192, 192, 192, 255);
@@ -2339,7 +2415,7 @@ void init_userdef_do_versions(void)
}
}
- if (U.versionfile < 269 || (U.versionfile == 269 && U.subversionfile < 6)) {
+ if (!USER_VERSION_ATLEAST(269, 6)) {
bTheme *btheme;
for (btheme = U.themes.first; btheme; btheme = btheme->next) {
char r, g, b;
@@ -2360,7 +2436,7 @@ void init_userdef_do_versions(void)
}
}
- if (U.versionfile < 269 || (U.versionfile == 269 && U.subversionfile < 8)) {
+ if (!USER_VERSION_ATLEAST(269, 8)) {
bTheme *btheme;
for (btheme = U.themes.first; btheme; btheme = btheme->next) {
rgba_char_args_test_set(btheme->tinfo.info_selected, 96, 128, 255, 255);
@@ -2376,7 +2452,7 @@ void init_userdef_do_versions(void)
}
}
- if (U.versionfile < 269 || (U.versionfile == 269 && U.subversionfile < 9)) {
+ if (!USER_VERSION_ATLEAST(269, 9)) {
bTheme *btheme;
U.tw_size = U.tw_size * 5.0f;
@@ -2416,7 +2492,7 @@ void init_userdef_do_versions(void)
}
}
- if (U.versionfile < 269 || (U.versionfile == 269 && U.subversionfile < 10)) {
+ if (!USER_VERSION_ATLEAST(269, 10)) {
bTheme *btheme;
for (btheme = U.themes.first; btheme; btheme = btheme->next) {
ThemeSpace *ts;
@@ -2430,24 +2506,25 @@ void init_userdef_do_versions(void)
}
}
- if (U.versionfile < 271) {
+ if (!USER_VERSION_ATLEAST(271, 0)) {
bTheme *btheme;
for (btheme = U.themes.first; btheme; btheme = btheme->next) {
rgba_char_args_set(btheme->tui.wcol_tooltip.text, 255, 255, 255, 255);
}
}
- if (U.versionfile < 272 || (U.versionfile == 272 && U.subversionfile < 2)) {
+ if (!USER_VERSION_ATLEAST(272, 2)) {
bTheme *btheme;
for (btheme = U.themes.first; btheme; btheme = btheme->next) {
rgba_char_args_set_fl(btheme->tv3d.paint_curve_handle, 0.5f, 1.0f, 0.5f, 0.5f);
rgba_char_args_set_fl(btheme->tv3d.paint_curve_pivot, 1.0f, 0.5f, 0.5f, 0.5f);
rgba_char_args_set_fl(btheme->tima.paint_curve_handle, 0.5f, 1.0f, 0.5f, 0.5f);
rgba_char_args_set_fl(btheme->tima.paint_curve_pivot, 1.0f, 0.5f, 0.5f, 0.5f);
+ rgba_char_args_set(btheme->tnode.syntaxr, 115, 115, 115, 255);
}
}
- if (U.versionfile < 271 || (U.versionfile == 271 && U.subversionfile < 5)) {
+ if (!USER_VERSION_ATLEAST(271, 5)) {
bTheme *btheme;
struct uiWidgetColors wcol_pie_menu = {
@@ -2477,7 +2554,7 @@ void init_userdef_do_versions(void)
}
}
- if (U.versionfile < 271 || (U.versionfile == 271 && U.subversionfile < 6)) {
+ if (!USER_VERSION_ATLEAST(271, 6)) {
bTheme *btheme;
for (btheme = U.themes.first; btheme; btheme = btheme->next) {
/* check for (alpha == 0) is safe, then color was never set */
@@ -2487,12 +2564,100 @@ void init_userdef_do_versions(void)
}
}
+ if (!USER_VERSION_ATLEAST(272, 3)) {
+ bTheme *btheme;
+ for (btheme = U.themes.first; btheme; btheme = btheme->next) {
+ rgba_char_args_set_fl(btheme->tui.widget_emboss, 1.0f, 1.0f, 1.0f, 0.02f);
+ }
+ }
+
+ if (!USER_VERSION_ATLEAST(273, 1)) {
+ bTheme *btheme;
+ for (btheme = U.themes.first; btheme; btheme = btheme->next) {
+ /* Grease Pencil vertex settings */
+ rgba_char_args_set(btheme->tv3d.gp_vertex, 0, 0, 0, 255);
+ rgba_char_args_set(btheme->tv3d.gp_vertex_select, 255, 133, 0, 255);
+ btheme->tv3d.gp_vertex_size = 3;
+
+ rgba_char_args_set(btheme->tseq.gp_vertex, 0, 0, 0, 255);
+ rgba_char_args_set(btheme->tseq.gp_vertex_select, 255, 133, 0, 255);
+ btheme->tseq.gp_vertex_size = 3;
+
+ rgba_char_args_set(btheme->tima.gp_vertex, 0, 0, 0, 255);
+ rgba_char_args_set(btheme->tima.gp_vertex_select, 255, 133, 0, 255);
+ btheme->tima.gp_vertex_size = 3;
+
+ rgba_char_args_set(btheme->tnode.gp_vertex, 0, 0, 0, 255);
+ rgba_char_args_set(btheme->tnode.gp_vertex_select, 255, 133, 0, 255);
+ btheme->tnode.gp_vertex_size = 3;
+
+ /* Timeline Keyframe Indicators */
+ rgba_char_args_set(btheme->ttime.time_keyframe, 0xDD, 0xD7, 0x00, 1.0);
+ rgba_char_args_set(btheme->ttime.time_gp_keyframe, 0xB5, 0xE6, 0x1D, 1.0);
+ }
+ }
+
+ if (!USER_VERSION_ATLEAST(273, 5)) {
+ bTheme *btheme;
+ for (btheme = U.themes.first; btheme; btheme = btheme->next) {
+ unsigned char *cp = (unsigned char *)btheme->tv3d.clipping_border_3d;
+ int c;
+ copy_v4_v4_char((char *)cp, btheme->tv3d.back);
+ c = cp[0] - 8;
+ CLAMP(c, 0, 255);
+ cp[0] = c;
+ c = cp[1] - 8;
+ CLAMP(c, 0, 255);
+ cp[1] = c;
+ c = cp[2] - 8;
+ CLAMP(c, 0, 255);
+ cp[2] = c;
+ cp[3] = 255;
+ }
+ }
+
+ if (!USER_VERSION_ATLEAST(274, 5)) {
+ bTheme *btheme;
+ for (btheme = U.themes.first; btheme; btheme = btheme->next) {
+ copy_v4_v4_char(btheme->tima.metadatatext, btheme->tima.text_hi);
+ copy_v4_v4_char(btheme->tseq.metadatatext, btheme->tseq.text_hi);
+ }
+ }
+
+ if (!USER_VERSION_ATLEAST(275, 1)) {
+ bTheme *btheme;
+ for (btheme = U.themes.first; btheme; btheme = btheme->next) {
+ copy_v4_v4_char(btheme->tclip.metadatatext, btheme->tseq.text_hi);
+ }
+ }
+
+ if (!USER_VERSION_ATLEAST(275, 2)) {
+ U.ndof_deadzone = 0.1;
+ }
+
+ if (!USER_VERSION_ATLEAST(275, 4)) {
+ U.node_margin = 80;
+ }
+
+ if (!USER_VERSION_ATLEAST(276, 1)) {
+ bTheme *btheme;
+ for (btheme = U.themes.first; btheme; btheme = btheme->next) {
+ rgba_char_args_set_fl(btheme->tima.preview_back, 0.0f, 0.0f, 0.0f, 0.3f);
+ }
+ }
+
if (U.pixelsize == 0.0f)
U.pixelsize = 1.0f;
if (U.image_draw_method == 0)
U.image_draw_method = IMAGE_DRAW_METHOD_2DTEXTURE;
+ // keep the following until the new audaspace is default to be built with
+#ifdef WITH_SYSTEM_AUDASPACE
+ // we default to the first audio device
+ U.audiodevice = 0;
+#endif
+
/* funny name, but it is GE stuff, moves userdef stuff to engine */
// XXX space_set_commmandline_options();
/* this timer uses U */
diff --git a/source/blender/editors/interface/view2d.c b/source/blender/editors/interface/view2d.c
index d48faa34618..5f0c3ff6993 100644
--- a/source/blender/editors/interface/view2d.c
+++ b/source/blender/editors/interface/view2d.c
@@ -99,11 +99,12 @@ BLI_INLINE void clamp_rctf_to_rcti(rcti *dst, const rctf *src)
/* XXX still unresolved: scrolls hide/unhide vs region mask handling */
/* XXX there's V2D_SCROLL_HORIZONTAL_HIDE and V2D_SCROLL_HORIZONTAL_FULLR ... */
-/* helper to allow scrollbars to dynamically hide
- * - returns a copy of the scrollbar settings with the flags to display
- * horizontal/vertical scrollbars removed
- * - input scroll value is the v2d->scroll var
- * - hide flags are set per region at drawtime
+/**
+ * helper to allow scrollbars to dynamically hide
+ * - returns a copy of the scrollbar settings with the flags to display
+ * horizontal/vertical scrollbars removed
+ * - input scroll value is the v2d->scroll var
+ * - hide flags are set per region at drawtime
*/
static int view2d_scroll_mapped(int scroll)
{
@@ -197,16 +198,17 @@ static void view2d_masks(View2D *v2d, int check_scrollers)
/* Refresh and Validation */
-/* Initialize all relevant View2D data (including view rects if first time) and/or refresh mask sizes after view resize
- * - for some of these presets, it is expected that the region will have defined some
- * additional settings necessary for the customization of the 2D viewport to its requirements
- * - this function should only be called from region init() callbacks, where it is expected that
- * this is called before UI_view2d_size_update(), as this one checks that the rects are properly initialized.
+/**
+ * Initialize all relevant View2D data (including view rects if first time) and/or refresh mask sizes after view resize
+ * - for some of these presets, it is expected that the region will have defined some
+ * additional settings necessary for the customization of the 2D viewport to its requirements
+ * - this function should only be called from region init() callbacks, where it is expected that
+ * this is called before UI_view2d_size_update(), as this one checks that the rects are properly initialized.
*/
void UI_view2d_region_reinit(View2D *v2d, short type, int winx, int winy)
{
bool tot_changed = false, do_init;
- uiStyle *style = UI_GetStyle();
+ uiStyle *style = UI_style_get();
do_init = (v2d->flag & V2D_IS_INITIALISED) == 0;
@@ -320,7 +322,7 @@ void UI_view2d_region_reinit(View2D *v2d, short type, int winx, int winy)
if (do_init) {
float panelzoom = (style) ? style->panelzoom : 1.0f;
- float scrolw = v2d->scroll & V2D_SCROLL_RIGHT ? V2D_SCROLL_WIDTH : 0.0f;
+ float scrolw = (v2d->scroll & V2D_SCROLL_RIGHT) ? V2D_SCROLL_WIDTH : 0.0f;
v2d->tot.xmin = 0.0f;
v2d->tot.xmax = winx - scrolw;
@@ -361,8 +363,9 @@ void UI_view2d_region_reinit(View2D *v2d, short type, int winx, int winy)
}
-/* Ensure View2D rects remain in a viable configuration
- * - cur is not allowed to be: larger than max, smaller than min, or outside of tot
+/**
+ * Ensure View2D rects remain in a viable configuration
+ * 'cur' is not allowed to be: larger than max, smaller than min, or outside of 'tot'
*/
// XXX pre2.5 -> this used to be called test_view2d()
static void ui_view2d_curRect_validate_resize(View2D *v2d, int resize, int mask_scrollers)
@@ -371,7 +374,8 @@ static void ui_view2d_curRect_validate_resize(View2D *v2d, int resize, int mask_
float winx, winy;
rctf *cur, *tot;
- /* use mask as size of region that View2D resides in, as it takes into account scrollbars already */
+ /* use mask as size of region that View2D resides in, as it takes into account
+ * scrollbars already - keep in sync with zoomx/zoomy in view_zoomstep_apply_ex! */
winx = (float)(BLI_rcti_size_x(&v2d->mask) + 1);
winy = (float)(BLI_rcti_size_y(&v2d->mask) + 1);
@@ -393,6 +397,7 @@ static void ui_view2d_curRect_validate_resize(View2D *v2d, int resize, int mask_
*/
totwidth = BLI_rctf_size_x(tot);
totheight = BLI_rctf_size_y(tot);
+ /* keep in sync with zoomx/zoomy in view_zoomstep_apply_ex! */
curwidth = width = BLI_rctf_size_x(cur);
curheight = height = BLI_rctf_size_y(cur);
@@ -840,7 +845,8 @@ void UI_view2d_sync(bScreen *screen, ScrArea *area, View2D *v2dcur, int flag)
}
-/* Restore 'cur' rect to standard orientation (i.e. optimal maximum view of tot)
+/**
+ * Restore 'cur' rect to standard orientation (i.e. optimal maximum view of tot)
* This does not take into account if zooming the view on an axis will improve the view (if allowed)
*/
void UI_view2d_curRect_reset(View2D *v2d)
@@ -1096,10 +1102,12 @@ void UI_view2d_view_ortho(View2D *v2d)
glLoadIdentity();
}
-/* Set view matrices to only use one axis of 'cur' only
- * - xaxis = if non-zero, only use cur x-axis, otherwise use cur-yaxis (mostly this will be used for x)
+/**
+ * Set view matrices to only use one axis of 'cur' only
+ *
+ * \param xaxis: if non-zero, only use cur x-axis, otherwise use cur-yaxis (mostly this will be used for x)
*/
-void UI_view2d_view_orthoSpecial(ARegion *ar, View2D *v2d, short xaxis)
+void UI_view2d_view_orthoSpecial(ARegion *ar, View2D *v2d, const bool xaxis)
{
rctf curmasked;
float xofs, yofs;
@@ -1190,20 +1198,23 @@ static void step_to_grid(float *step, int *power, int unit)
}
}
-/* Initialize settings necessary for drawing gridlines in a 2d-view
- * - Currently, will return pointer to View2DGrid struct that needs to
- * be freed with UI_view2d_grid_free()
- * - Is used for scrollbar drawing too (for units drawing)
- * - Units + clamping args will be checked, to make sure they are valid values that can be used
- * so it is very possible that we won't return grid at all!
- *
- * - xunits,yunits = V2D_UNIT_* grid steps in seconds or frames
- * - xclamp,yclamp = V2D_CLAMP_* only show whole-number intervals
- * - winx = width of region we're drawing to, note: not used but keeping for completeness.
- * - winy = height of region we're drawing into
+/**
+ * Initialize settings necessary for drawing gridlines in a 2d-view
+ *
+ * - Currently, will return pointer to View2DGrid struct that needs to
+ * be freed with UI_view2d_grid_free()
+ * - Is used for scrollbar drawing too (for units drawing)
+ * - Units + clamping args will be checked, to make sure they are valid values that can be used
+ * so it is very possible that we won't return grid at all!
+ *
+ * - xunits,yunits = V2D_UNIT_* grid steps in seconds or frames
+ * - xclamp,yclamp = V2D_CLAMP_* only show whole-number intervals
+ * - winx = width of region we're drawing to, note: not used but keeping for completeness.
+ * - winy = height of region we're drawing into
*/
-View2DGrid *UI_view2d_grid_calc(Scene *scene, View2D *v2d,
- short xunits, short xclamp, short yunits, short yclamp, int UNUSED(winx), int winy)
+View2DGrid *UI_view2d_grid_calc(
+ Scene *scene, View2D *v2d,
+ short xunits, short xclamp, short yunits, short yclamp, int UNUSED(winx), int winy)
{
View2DGrid *grid;
@@ -1481,9 +1492,11 @@ void UI_view2d_grid_free(View2DGrid *grid)
/* *********************************************************************** */
/* Scrollers */
-/* View2DScrollers is typedef'd in UI_view2d.h
- * WARNING: the start of this struct must not change, as view2d_ops.c uses this too.
- * For now, we don't need to have a separate (internal) header for structs like this...
+/**
+ * View2DScrollers is typedef'd in UI_view2d.h
+ *
+ * \warning The start of this struct must not change, as view2d_ops.c uses this too.
+ * For now, we don't need to have a separate (internal) header for structs like this...
*/
struct View2DScrollers {
/* focus bubbles */
@@ -1500,8 +1513,9 @@ struct View2DScrollers {
};
/* Calculate relevant scroller properties */
-View2DScrollers *UI_view2d_scrollers_calc(const bContext *C, View2D *v2d,
- short xunits, short xclamp, short yunits, short yclamp)
+View2DScrollers *UI_view2d_scrollers_calc(
+ const bContext *C, View2D *v2d,
+ short xunits, short xclamp, short yunits, short yclamp)
{
View2DScrollers *scrollers;
rcti vert, hor;
@@ -1649,7 +1663,7 @@ static void scroll_printstr(Scene *scene, float x, float y, float val, int power
BLI_timecode_string_from_time(timecode_str, sizeof(timecode_str), power, val, FPS, U.timecode_style);
}
else {
- BLI_timecode_string_from_time_simple(timecode_str, sizeof(timecode_str), power, val);
+ BLI_timecode_string_from_time_seconds(timecode_str, sizeof(timecode_str), power, val);
}
/* get length of string, and adjust printing location to fit it into the horizontal scrollbar */
@@ -1719,7 +1733,7 @@ void UI_view2d_scrollers_draw(const bContext *C, View2D *v2d, View2DScrollers *v
glRecti(v2d->hor.xmin, v2d->hor.ymin, v2d->hor.xmax, v2d->hor.ymax);
}
- uiWidgetScrollDraw(&wcol, &hor, &slider, state);
+ UI_draw_widget_scroll(&wcol, &hor, &slider, state);
/* scale indicators */
if ((scroll & V2D_SCROLL_SCALE_HORIZONTAL) && (vs->grid)) {
@@ -1820,7 +1834,7 @@ void UI_view2d_scrollers_draw(const bContext *C, View2D *v2d, View2DScrollers *v
glRecti(v2d->vert.xmin, v2d->vert.ymin, v2d->vert.xmax, v2d->vert.ymax);
}
- uiWidgetScrollDraw(&wcol, &vert, &slider, state);
+ UI_draw_widget_scroll(&wcol, &vert, &slider, state);
/* scale indiators */
@@ -1851,7 +1865,7 @@ void UI_view2d_scrollers_draw(const bContext *C, View2D *v2d, View2DScrollers *v
/* draw vertical steps */
if (dfac > 0.0f) {
- BLF_rotation_default(M_PI / 2);
+ BLF_rotation_default(M_PI_2);
BLF_enable_default(BLF_ROTATION);
for (; fac < vert.ymax - 10; fac += dfac, val += grid->dy) {
@@ -1883,18 +1897,22 @@ void UI_view2d_scrollers_free(View2DScrollers *scrollers)
/* *********************************************************************** */
/* List View Utilities */
-/* Get the view-coordinates of the nominated cell
- * - columnwidth, rowheight = size of each 'cell'
- * - startx, starty = coordinates (in 'tot' rect space) that the list starts from
- * This should be (0,0) for most views. However, for those where the starting row was offsetted
- * (like for Animation Editor channel lists, to make the first entry more visible), these will be
- * the min-coordinates of the first item.
- * - column, row = the 2d-coordinates (in 2D-view / 'tot' rect space) the cell exists at
- * - rect = coordinates of the cell (passed as single var instead of 4 separate, as it's more useful this way)
+/** Get the view-coordinates of the nominated cell
+ *
+ * \param columnwidth, rowheight: size of each 'cell'
+ * \param startx, starty: coordinates (in 'tot' rect space) that the list starts from.
+ * This should be (0,0) for most views. However, for those where the starting row was offsetted
+ * (like for Animation Editor channel lists, to make the first entry more visible), these will be
+ * the min-coordinates of the first item.
+ * \param column, row: The 2d-coordinates
+ * (in 2D-view / 'tot' rect space) the cell exists at
+ * \param rect: coordinates of the cell
+ * (passed as single var instead of 4 separate, as it's more useful this way)
*/
-void UI_view2d_listview_cell_to_view(View2D *v2d, float columnwidth, float rowheight,
- float startx, float starty,
- int column, int row, rctf *rect)
+void UI_view2d_listview_cell_to_view(
+ View2D *v2d, float columnwidth, float rowheight,
+ float startx, float starty,
+ int column, int row, rctf *rect)
{
/* sanity checks */
if (ELEM(NULL, v2d, rect)) {
@@ -1928,17 +1946,20 @@ void UI_view2d_listview_cell_to_view(View2D *v2d, float columnwidth, float rowhe
}
}
-/* Get the 'cell' (row, column) that the given 2D-view coordinates (i.e. in 'tot' rect space) lie in.
- * - columnwidth, rowheight = size of each 'cell'
- * - startx, starty = coordinates (in 'tot' rect space) that the list starts from
- * This should be (0,0) for most views. However, for those where the starting row was offsetted
- * (like for Animation Editor channel lists, to make the first entry more visible), these will be
- * the min-coordinates of the first item.
- * - viewx, viewy = 2D-coordinates (in 2D-view / 'tot' rect space) to get the cell for
- * - column, row = the 'coordinates' of the relevant 'cell'
+/**
+ * Get the 'cell' (row, column) that the given 2D-view coordinates (i.e. in 'tot' rect space) lie in.
+ *
+ * \param columnwidth, rowheight: size of each 'cell'
+ * \param startx, starty: coordinates (in 'tot' rect space) that the list starts from.
+ * This should be (0,0) for most views. However, for those where the starting row was offsetted
+ * (like for Animation Editor channel lists, to make the first entry more visible), these will be
+ * the min-coordinates of the first item.
+ * \param viewx, viewy: 2D-coordinates (in 2D-view / 'tot' rect space) to get the cell for
+ * \param column, row: the 'coordinates' of the relevant 'cell'
*/
-void UI_view2d_listview_view_to_cell(View2D *v2d, float columnwidth, float rowheight, float startx, float starty,
- float viewx, float viewy, int *column, int *row)
+void UI_view2d_listview_view_to_cell(
+ View2D *v2d, float columnwidth, float rowheight, float startx, float starty,
+ float viewx, float viewy, int *column, int *row)
{
/* adjust view coordinates to be all positive ints, corrected for the start offset */
const int x = (int)(floorf(fabsf(viewx) + 0.5f) - startx);
@@ -1965,13 +1986,16 @@ void UI_view2d_listview_view_to_cell(View2D *v2d, float columnwidth, float rowhe
*row = 0;
}
-/* Get the 'extreme' (min/max) column and row indices which are visible within the 'cur' rect
- * - columnwidth, rowheight = size of each 'cell'
- * - startx, starty = coordinates that the list starts from, which should be (0,0) for most views
- * - column/row_min/max = the starting and ending column/row indices
+/**
+ * Get the 'extreme' (min/max) column and row indices which are visible within the 'cur' rect
+ *
+ * \param columnwidth, rowheight: Size of each 'cell'
+ * \param startx, starty: Coordinates that the list starts from, which should be (0,0) for most views
+ * \param column_min, column_max, row_min, row_max: The starting and ending column/row indices
*/
-void UI_view2d_listview_visible_cells(View2D *v2d, float columnwidth, float rowheight, float startx, float starty,
- int *column_min, int *column_max, int *row_min, int *row_max)
+void UI_view2d_listview_visible_cells(
+ View2D *v2d, float columnwidth, float rowheight, float startx, float starty,
+ int *column_min, int *column_max, int *row_min, int *row_max)
{
/* using 'cur' rect coordinates, call the cell-getting function to get the cells for this */
if (v2d) {
@@ -1997,10 +2021,11 @@ float UI_view2d_region_to_view_y(struct View2D *v2d, float y)
return (v2d->cur.ymin + (BLI_rctf_size_y(&v2d->cur) * (y - v2d->mask.ymin) / BLI_rcti_size_y(&v2d->mask)));
}
-/* Convert from screen/region space to 2d-View space
- *
- * - x,y = coordinates to convert
- * - viewx,viewy = resultant coordinates
+/**
+ * Convert from screen/region space to 2d-View space
+ *
+ * \param x, y: coordinates to convert
+ * \param r_view_x, r_view_y: resultant coordinates
*/
void UI_view2d_region_to_view(View2D *v2d, float x, float y, float *r_view_x, float *r_view_y)
{
@@ -2028,11 +2053,12 @@ float UI_view2d_view_to_region_y(View2D *v2d, float y)
return (v2d->mask.ymin + (((y - v2d->cur.ymin) / BLI_rctf_size_y(&v2d->cur)) * BLI_rcti_size_y(&v2d->mask)));
}
-/* Convert from 2d-View space to screen/region space
- * - Coordinates are clamped to lie within bounds of region
+/**
+ * Convert from 2d-View space to screen/region space
+ * \note Coordinates are clamped to lie within bounds of region
*
- * - x,y = coordinates to convert
- * - regionx,regiony = resultant coordinates
+ * \param x, y: Coordinates to convert.
+ * \param r_region_x, r_region_y: Resultant coordinates.
*/
bool UI_view2d_view_to_region_clip(View2D *v2d, float x, float y, int *r_region_x, int *r_region_y)
{
@@ -2055,11 +2081,13 @@ bool UI_view2d_view_to_region_clip(View2D *v2d, float x, float y, int *r_region_
}
}
-/* Convert from 2d-view space to screen/region space
- * - Coordinates are NOT clamped to lie within bounds of region
+/**
+ * Convert from 2d-view space to screen/region space
+ *
+ * \note Coordinates are NOT clamped to lie within bounds of region.
*
- * - x,y = coordinates to convert
- * - regionx,regiony = resultant coordinates
+ * \param x, y: Coordinates to convert.
+ * \param r_region_x, r_region_y: Resultant coordinates.
*/
void UI_view2d_view_to_region(View2D *v2d, float x, float y, int *r_region_x, int *r_region_y)
{
@@ -2173,25 +2201,30 @@ View2D *UI_view2d_fromcontext_rwin(const bContext *C)
}
-/* Calculate the scale per-axis of the drawing-area
- * - Is used to inverse correct drawing of icons, etc. that need to follow view
- * but not be affected by scale
+/**
+ * Calculate the scale per-axis of the drawing-area
*
- * - x,y = scale on each axis
+ * Is used to inverse correct drawing of icons, etc. that need to follow view
+ * but not be affected by scale
+ *
+ * \param x, y: scale on each axis
*/
void UI_view2d_scale_get(View2D *v2d, float *x, float *y)
{
if (x) *x = BLI_rcti_size_x(&v2d->mask) / BLI_rctf_size_x(&v2d->cur);
if (y) *y = BLI_rcti_size_y(&v2d->mask) / BLI_rctf_size_y(&v2d->cur);
}
-/* Same as UI_view2d_scale_get() - 1.0f / x, y */
+/**
+ * Same as ``UI_view2d_scale_get() - 1.0f / x, y``
+ */
void UI_view2d_scale_get_inverse(View2D *v2d, float *x, float *y)
{
if (x) *x = BLI_rctf_size_x(&v2d->cur) / BLI_rcti_size_x(&v2d->mask);
if (y) *y = BLI_rctf_size_y(&v2d->cur) / BLI_rcti_size_y(&v2d->mask);
}
-/* Simple functions for consistent center offset access.
+/**
+ * Simple functions for consistent center offset access.
* Used by node editor to shift view center for each individual node tree.
*/
void UI_view2d_center_get(struct View2D *v2d, float *x, float *y)
@@ -2237,13 +2270,15 @@ void UI_view2d_offset(struct View2D *v2d, float xfac, float yfac)
UI_view2d_curRect_validate(v2d);
}
-/* Check if mouse is within scrollers
- * - Returns appropriate code for match
- * 'h' = in horizontal scroller
- * 'v' = in vertical scroller
- * 0 = not in scroller
- *
- * - x,y = mouse coordinates in screen (not region) space
+/**
+ * Check if mouse is within scrollers
+ *
+ * \param x, y: Mouse coordinates in screen (not region) space.
+ *
+ * \return appropriate code for match.
+ * - 'h' = in horizontal scroller.
+ * - 'v' = in vertical scroller.
+ * - 0 = not in scroller.
*/
short UI_view2d_mouse_in_scrollers(const bContext *C, View2D *v2d, int x, int y)
{
@@ -2286,8 +2321,9 @@ typedef struct View2DString {
static MemArena *g_v2d_strings_arena = NULL;
static View2DString *g_v2d_strings = NULL;
-void UI_view2d_text_cache_add(View2D *v2d, float x, float y,
- const char *str, size_t str_len, const char col[4])
+void UI_view2d_text_cache_add(
+ View2D *v2d, float x, float y,
+ const char *str, size_t str_len, const char col[4])
{
int mval[2];
@@ -2305,7 +2341,7 @@ void UI_view2d_text_cache_add(View2D *v2d, float x, float y,
BLI_LINKS_PREPEND(g_v2d_strings, v2s);
- v2s->col.pack = *((int *)col);
+ v2s->col.pack = *((const int *)col);
memset(&v2s->rect, 0, sizeof(v2s->rect));
@@ -2317,8 +2353,9 @@ void UI_view2d_text_cache_add(View2D *v2d, float x, float y,
}
/* no clip (yet) */
-void UI_view2d_text_cache_add_rectf(View2D *v2d, const rctf *rect_view,
- const char *str, size_t str_len, const char col[4])
+void UI_view2d_text_cache_add_rectf(
+ View2D *v2d, const rctf *rect_view,
+ const char *str, size_t str_len, const char col[4])
{
rcti rect;
@@ -2336,7 +2373,7 @@ void UI_view2d_text_cache_add_rectf(View2D *v2d, const rctf *rect_view,
BLI_LINKS_PREPEND(g_v2d_strings, v2s);
- v2s->col.pack = *((int *)col);
+ v2s->col.pack = *((const int *)col);
v2s->rect = rect;
diff --git a/source/blender/editors/interface/view2d_ops.c b/source/blender/editors/interface/view2d_ops.c
index 2b84c0678ae..07275d6be2a 100644
--- a/source/blender/editors/interface/view2d_ops.c
+++ b/source/blender/editors/interface/view2d_ops.c
@@ -63,12 +63,13 @@ static int view2d_poll(bContext *C)
/* ********************************************************* */
/* VIEW PANNING OPERATOR */
-/* This group of operators come in several forms:
- * 1) Modal 'dragging' with MMB - where movement of mouse dictates amount to pan view by
- * 2) Scrollwheel 'steps' - rolling mousewheel by one step moves view by predefined amount
+/**
+ * This group of operators come in several forms:
+ * -# Modal 'dragging' with MMB - where movement of mouse dictates amount to pan view by
+ * -# Scrollwheel 'steps' - rolling mousewheel by one step moves view by predefined amount
*
- * In order to make sure this works, each operator must define the following RNA-Operator Props:
- * deltax, deltay - define how much to move view by (relative to zoom-correction factor)
+ * In order to make sure this works, each operator must define the following RNA-Operator Props:
+ * - `deltax, deltay` - define how much to move view by (relative to zoom-correction factor)
*/
/* ------------------ Shared 'core' stuff ---------------------- */
@@ -275,8 +276,8 @@ static int view_pan_modal(bContext *C, wmOperator *op, const wmEvent *event)
view_pan_apply(C, op);
break;
}
- /* XXX - Mode switching isn't implemented. See comments in 36818.
- * switch to zoom */
+ /* XXX - Mode switching isn't implemented. See comments in 36818.
+ * switch to zoom */
#if 0
case LEFTMOUSE:
if (event->val == KM_PRESS) {
@@ -328,7 +329,7 @@ static void VIEW2D_OT_pan(wmOperatorType *ot)
ot->cancel = view_pan_cancel;
/* operator is modal */
- ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_POINTER;
+ ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_CURSOR;
/* rna - must keep these in sync with the other operators */
RNA_def_int(ot->srna, "deltax", 0, INT_MIN, INT_MAX, "Delta X", "", INT_MIN, INT_MAX);
@@ -525,15 +526,18 @@ static void VIEW2D_OT_scroll_up(wmOperatorType *ot)
/* ********************************************************* */
/* SINGLE-STEP VIEW ZOOMING OPERATOR */
-/* This group of operators come in several forms:
- * 1) Scrollwheel 'steps' - rolling mousewheel by one step zooms view by predefined amount
- * 2) Scrollwheel 'steps' + alt + ctrl/shift - zooms view on one axis only (ctrl=x, shift=y) // XXX this could be implemented...
- * 3) Pad +/- Keys - pressing each key moves the zooms the view by a predefined amount
+/**
+ * This group of operators come in several forms:
+ * -# Scrollwheel 'steps' - rolling mousewheel by one step zooms view by predefined amount.
+ * -# Scrollwheel 'steps' + alt + ctrl/shift - zooms view on one axis only (ctrl=x, shift=y).
+ * XXX this could be implemented...
+ * -# Pad +/- Keys - pressing each key moves the zooms the view by a predefined amount.
*
* In order to make sure this works, each operator must define the following RNA-Operator Props:
- * zoomfacx, zoomfacy - These two zoom factors allow for non-uniform scaling.
- * It is safe to scale by 0, as these factors are used to determine
- * amount to enlarge 'cur' by
+ *
+ * - zoomfacx, zoomfacy - These two zoom factors allow for non-uniform scaling.
+ * It is safe to scale by 0, as these factors are used to determine.
+ * amount to enlarge 'cur' by.
*/
/* ------------------ 'Shared' stuff ------------------------ */
@@ -620,11 +624,13 @@ static int view_zoom_poll(bContext *C)
}
/* apply transform to view (i.e. adjust 'cur' rect) */
-static void view_zoomstep_apply_ex(bContext *C, v2dViewZoomData *vzd, const bool use_mousepos,
- const float facx, const float facy)
+static void view_zoomstep_apply_ex(
+ bContext *C, v2dViewZoomData *vzd, const bool use_mousepos,
+ const float facx, const float facy)
{
ARegion *ar = CTX_wm_region(C);
View2D *v2d = &ar->v2d;
+ const rctf cur_old = v2d->cur;
float dx, dy;
/* calculate amount to move view by, ensuring symmetry so the
@@ -651,17 +657,25 @@ static void view_zoomstep_apply_ex(bContext *C, v2dViewZoomData *vzd, const bool
v2d->cur.xmax -= 2 * dx;
}
else {
+
+ v2d->cur.xmin += dx;
+ v2d->cur.xmax -= dx;
+
if (use_mousepos && (U.uiflag & USER_ZOOM_TO_MOUSEPOS)) {
- float mval_fac = (vzd->mx_2d - v2d->cur.xmin) / BLI_rctf_size_x(&v2d->cur);
- float mval_faci = 1.0f - mval_fac;
- float ofs = (mval_fac * dx) - (mval_faci * dx);
-
- v2d->cur.xmin += ofs + dx;
- v2d->cur.xmax += ofs - dx;
- }
- else {
- v2d->cur.xmin += dx;
- v2d->cur.xmax -= dx;
+ /* get zoom fac the same way as in ui_view2d_curRect_validate_resize - better keep in sync! */
+ const float zoomx = (float)(BLI_rcti_size_x(&v2d->mask) + 1) / BLI_rctf_size_x(&v2d->cur);
+
+ /* only move view to mouse if zoom fac is inside minzoom/maxzoom */
+ if (((v2d->keepzoom & V2D_LIMITZOOM) == 0) ||
+ IN_RANGE_INCL(zoomx, v2d->minzoom, v2d->maxzoom))
+ {
+ float mval_fac = (vzd->mx_2d - cur_old.xmin) / BLI_rctf_size_x(&cur_old);
+ float mval_faci = 1.0f - mval_fac;
+ float ofs = (mval_fac * dx) - (mval_faci * dx);
+
+ v2d->cur.xmin += ofs;
+ v2d->cur.xmax += ofs;
+ }
}
}
}
@@ -676,17 +690,25 @@ static void view_zoomstep_apply_ex(bContext *C, v2dViewZoomData *vzd, const bool
v2d->cur.ymax -= 2 * dy;
}
else {
+
+ v2d->cur.ymin += dy;
+ v2d->cur.ymax -= dy;
+
if (use_mousepos && (U.uiflag & USER_ZOOM_TO_MOUSEPOS)) {
- float mval_fac = (vzd->my_2d - v2d->cur.ymin) / BLI_rctf_size_y(&v2d->cur);
- float mval_faci = 1.0f - mval_fac;
- float ofs = (mval_fac * dy) - (mval_faci * dy);
-
- v2d->cur.ymin += ofs + dy;
- v2d->cur.ymax += ofs - dy;
- }
- else {
- v2d->cur.ymin += dy;
- v2d->cur.ymax -= dy;
+ /* get zoom fac the same way as in ui_view2d_curRect_validate_resize - better keep in sync! */
+ const float zoomy = (float)(BLI_rcti_size_y(&v2d->mask) + 1) / BLI_rctf_size_y(&v2d->cur);
+
+ /* only move view to mouse if zoom fac is inside minzoom/maxzoom */
+ if (((v2d->keepzoom & V2D_LIMITZOOM) == 0) ||
+ IN_RANGE_INCL(zoomy, v2d->minzoom, v2d->maxzoom))
+ {
+ float mval_fac = (vzd->my_2d - cur_old.ymin) / BLI_rctf_size_y(&cur_old);
+ float mval_faci = 1.0f - mval_fac;
+ float ofs = (mval_fac * dy) - (mval_faci * dy);
+
+ v2d->cur.ymin += ofs;
+ v2d->cur.ymax += ofs;
+ }
}
}
}
@@ -854,10 +876,11 @@ static void VIEW2D_OT_zoom_out(wmOperatorType *ot)
/* ********************************************************* */
/* DRAG-ZOOM OPERATOR */
-/* MMB Drag - allows non-uniform scaling by dragging mouse
+/**
+ * MMB Drag - allows non-uniform scaling by dragging mouse
*
- * In order to make sure this works, each operator must define the following RNA-Operator Props:
- * deltax, deltay - amounts to add to each side of the 'cur' rect
+ * In order to make sure this works, each operator must define the following RNA-Operator Props:
+ * - `deltax, deltay` - amounts to add to each side of the 'cur' rect
*/
/* apply transform to view (i.e. adjust 'cur' rect) */
@@ -1162,7 +1185,7 @@ static void VIEW2D_OT_zoom(wmOperatorType *ot)
ot->poll = view_zoom_poll;
/* operator is repeatable */
- ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_POINTER;
+ ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_CURSOR;
/* rna - must keep these in sync with the other operators */
prop = RNA_def_float(ot->srna, "deltax", 0, -FLT_MAX, FLT_MAX, "Delta X", "", -FLT_MAX, FLT_MAX);
@@ -1174,10 +1197,12 @@ static void VIEW2D_OT_zoom(wmOperatorType *ot)
/* ********************************************************* */
/* BORDER-ZOOM */
-/* The user defines a rect using standard borderselect tools, and we use this rect to
+/**
+ * The user defines a rect using standard borderselect tools, and we use this rect to
* define the new zoom-level of the view in the following ways:
- * 1) LEFTMOUSE - zoom in to view
- * 2) RIGHTMOUSE - zoom out of view
+ *
+ * -# LEFTMOUSE - zoom in to view
+ * -# RIGHTMOUSE - zoom out of view
*
* Currently, these key mappings are hardcoded, but it shouldn't be too important to
* have custom keymappings for this...
@@ -1389,8 +1414,9 @@ static float smooth_view_rect_to_fac(const rctf *rect_a, const rctf *rect_b)
/* will start timer if appropriate */
/* the arguments are the desired situation */
-void UI_view2d_smooth_view(bContext *C, ARegion *ar,
- const rctf *cur, const int smooth_viewtx)
+void UI_view2d_smooth_view(
+ bContext *C, ARegion *ar,
+ const rctf *cur, const int smooth_viewtx)
{
wmWindowManager *wm = CTX_wm_manager(C);
wmWindow *win = CTX_wm_window(C);
@@ -1515,13 +1541,14 @@ static void VIEW2D_OT_smoothview(wmOperatorType *ot)
/* ********************************************************* */
/* SCROLLERS */
-/* Scrollers should behave in the following ways, when clicked on with LMB (and dragged):
- * 1) 'Handles' on end of 'bubble' - when the axis that the scroller represents is zoomable,
- * enlarge 'cur' rect on the relevant side
- * 2) 'Bubble'/'bar' - just drag, and bar should move with mouse (view pans opposite)
+/**
+ * Scrollers should behave in the following ways, when clicked on with LMB (and dragged):
+ * -# 'Handles' on end of 'bubble' - when the axis that the scroller represents is zoomable,
+ * enlarge 'cur' rect on the relevant side.
+ * -# 'Bubble'/'bar' - just drag, and bar should move with mouse (view pans opposite).
*
- * In order to make sure this works, each operator must define the following RNA-Operator Props:
- * deltax, deltay - define how much to move view by (relative to zoom-correction factor)
+ * In order to make sure this works, each operator must define the following RNA-Operator Props:
+ * - `deltax, deltay` - define how much to move view by (relative to zoom-correction factor)
*/
/* customdata for scroller-invoke data */
@@ -1543,10 +1570,12 @@ typedef struct v2dScrollerMove {
} v2dScrollerMove;
-/* View2DScrollers is typedef'd in UI_view2d.h
+/**
+ * #View2DScrollers is typedef'd in UI_view2d.h
* This is a CUT DOWN VERSION of the 'real' version, which is defined in view2d.c, as we only need focus bubble info
- * WARNING: the start of this struct must not change, so that it stays in sync with the 'real' version
- * For now, we don't need to have a separate (internal) header for structs like this...
+ *
+ * \warning: The start of this struct must not change, so that it stays in sync with the 'real' version
+ * For now, we don't need to have a separate (internal) header for structs like this...
*/
struct View2DScrollers {
/* focus bubbles */
@@ -1565,10 +1594,12 @@ enum {
/* ------------------------ */
-/* check if mouse is within scroller handle
- * - mouse = relevant mouse coordinate in region space
- * - sc_min, sc_max = extents of scroller 'groove' (potential available space for scroller)
- * - sh_min, sh_max = positions of scrollbar handles
+/**
+ * Check if mouse is within scroller handle.
+ *
+ * \param mouse: relevant mouse coordinate in region space.
+ * \param sc_min, sc_max: extents of scroller 'groove' (potential available space for scroller).
+ * \param sh_min, sh_max: positions of scrollbar handles.
*/
static short mouse_in_scroller_handle(int mouse, int sc_min, int sc_max, int sh_min, int sh_max)
{
@@ -1772,7 +1803,10 @@ static void scroller_activate_apply(bContext *C, wmOperator *op)
UI_view2d_sync(CTX_wm_screen(C), CTX_wm_area(C), v2d, V2D_LOCK_COPY);
}
-/* handle user input for scrollers - calculations of mouse-movement need to be done here, not in the apply callback! */
+/**
+ * Handle user input for scrollers - calculations of mouse-movement need to be done here,
+ * not in the apply callback!
+ */
static int scroller_activate_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
v2dScrollerMove *vsm = op->customdata;
@@ -1951,7 +1985,7 @@ static void VIEW2D_OT_scroller_activate(wmOperatorType *ot)
static int reset_exec(bContext *C, wmOperator *UNUSED(op))
{
- uiStyle *style = UI_GetStyle();
+ uiStyle *style = UI_style_get();
ARegion *ar = CTX_wm_region(C);
View2D *v2d = &ar->v2d;
int winx, winy;
diff --git a/source/blender/editors/io/CMakeLists.txt b/source/blender/editors/io/CMakeLists.txt
index f331dea5c5c..828cb494eab 100644
--- a/source/blender/editors/io/CMakeLists.txt
+++ b/source/blender/editors/io/CMakeLists.txt
@@ -20,9 +20,9 @@
set(INC
../include
- ../../blenfont
../../blenkernel
../../blenlib
+ ../../blentranslation
../../bmesh
../../makesdna
../../makesrna
diff --git a/source/blender/editors/io/SConscript b/source/blender/editors/io/SConscript
index 0facb24e2c3..2b1a638b891 100644
--- a/source/blender/editors/io/SConscript
+++ b/source/blender/editors/io/SConscript
@@ -33,9 +33,9 @@ defs = []
incs = [
'../include',
- '../../blenfont',
'../../blenkernel',
'../../blenlib',
+ '../../blentranslation',
'../../collada',
'../../makesrna',
'../../windowmanager',
diff --git a/source/blender/editors/io/io_collada.c b/source/blender/editors/io/io_collada.c
index a4130540b1b..021b040fdd5 100644
--- a/source/blender/editors/io/io_collada.c
+++ b/source/blender/editors/io/io_collada.c
@@ -30,7 +30,7 @@
#ifdef WITH_COLLADA
#include "DNA_scene_types.h"
-#include "BLF_translation.h"
+#include "BLT_translation.h"
#include "BLI_blenlib.h"
#include "BLI_utildefines.h"
@@ -96,7 +96,9 @@ static int wm_collada_export_exec(bContext *C, wmOperator *op)
int use_object_instantiation;
int sort_by_name;
int export_transformation_type;
- int open_sim;
+ int open_sim;
+
+ int export_count;
if (!RNA_struct_property_is_set(op->ptr, "filepath")) {
BKE_report(op->reports, RPT_ERROR, "No filename given");
@@ -148,33 +150,36 @@ static int wm_collada_export_exec(bContext *C, wmOperator *op)
ED_object_editmode_load(CTX_data_edit_object(C));
-
- if (collada_export(CTX_data_scene(C),
- filepath,
- apply_modifiers,
- export_mesh_type,
- selected,
- include_children,
- include_armatures,
- include_shapekeys,
- deform_bones_only,
-
- active_uv_only,
- include_uv_textures,
- include_material_textures,
- use_texture_copies,
-
- triangulate,
- use_object_instantiation,
- sort_by_name,
- export_transformation_type,
- open_sim))
- {
- return OPERATOR_FINISHED;
+ export_count = collada_export(CTX_data_scene(C),
+ filepath,
+ apply_modifiers,
+ export_mesh_type,
+ selected,
+ include_children,
+ include_armatures,
+ include_shapekeys,
+ deform_bones_only,
+
+ active_uv_only,
+ include_uv_textures,
+ include_material_textures,
+ use_texture_copies,
+
+ triangulate,
+ use_object_instantiation,
+ sort_by_name,
+ export_transformation_type,
+ open_sim);
+
+ if (export_count == 0) {
+ BKE_report(op->reports, RPT_WARNING, "Export file is empty");
+ return OPERATOR_CANCELLED;
}
else {
- BKE_report(op->reports, RPT_WARNING, "Export file not created");
- return OPERATOR_CANCELLED;
+ char buff[100];
+ sprintf(buff, "Exported %d Objects", export_count);
+ BKE_report(op->reports, RPT_INFO, buff);
+ return OPERATOR_FINISHED;
}
}
@@ -293,8 +298,8 @@ void WM_OT_collada_export(wmOperatorType *ot)
ot->ui = wm_collada_export_draw;
- WM_operator_properties_filesel(ot, FOLDERFILE | COLLADAFILE, FILE_BLENDER, FILE_SAVE,
- WM_FILESEL_FILEPATH, FILE_DEFAULTDISPLAY);
+ WM_operator_properties_filesel(ot, FILE_TYPE_FOLDER | FILE_TYPE_COLLADA, FILE_BLENDER, FILE_SAVE,
+ WM_FILESEL_FILEPATH, FILE_DEFAULTDISPLAY, FILE_SORT_ALPHA);
RNA_def_boolean(ot->srna,
"apply_modifiers", 0, "Apply Modifiers",
@@ -322,11 +327,11 @@ void WM_OT_collada_export(wmOperatorType *ot)
"Only export deforming bones with armatures");
- RNA_def_boolean(ot->srna, "active_uv_only", 0, "Only Active UV layer",
- "Export textures assigned to the object UV maps");
+ RNA_def_boolean(ot->srna, "active_uv_only", 0, "Only Selected UV Map",
+ "Export only the selected UV Map");
RNA_def_boolean(ot->srna, "include_uv_textures", 0, "Include UV Textures",
- "Export textures assigned to the object UV maps");
+ "Export textures assigned to the object UV Maps");
RNA_def_boolean(ot->srna, "include_material_textures", 0, "Include Material Textures",
"Export textures assigned to the object Materials");
@@ -350,8 +355,8 @@ void WM_OT_collada_export(wmOperatorType *ot)
RNA_def_enum(ot->srna, "export_transformation_type_selection", prop_bc_export_transformation_type, 0,
"Transform", "Transformation type for translation, scale and rotation");
- RNA_def_boolean(ot->srna, "open_sim", 0, "Export for OpenSim",
- "Compatibility mode for OpenSim and compatible online worlds");
+ RNA_def_boolean(ot->srna, "open_sim", 0, "Export to SL/OpenSim",
+ "Compatibility mode for SL, OpenSim and other compatible online worlds");
}
@@ -360,6 +365,9 @@ static int wm_collada_import_exec(bContext *C, wmOperator *op)
{
char filename[FILE_MAX];
int import_units;
+ int find_chains;
+ int fix_orientation;
+ int min_chain_length;
if (!RNA_struct_property_is_set(op->ptr, "filepath")) {
BKE_report(op->reports, RPT_ERROR, "No filename given");
@@ -367,10 +375,19 @@ static int wm_collada_import_exec(bContext *C, wmOperator *op)
}
/* Options panel */
- import_units = RNA_boolean_get(op->ptr, "import_units");
+ import_units = RNA_boolean_get(op->ptr, "import_units");
+ find_chains = RNA_boolean_get(op->ptr, "find_chains");
+ fix_orientation = RNA_boolean_get(op->ptr, "fix_orientation");
+ min_chain_length = RNA_int_get(op->ptr, "min_chain_length");
RNA_string_get(op->ptr, "filepath", filename);
- if (collada_import(C, filename, import_units)) {
+ if (collada_import(
+ C, filename,
+ import_units,
+ find_chains,
+ fix_orientation,
+ min_chain_length))
+ {
return OPERATOR_FINISHED;
}
else {
@@ -390,6 +407,19 @@ static void uiCollada_importSettings(uiLayout *layout, PointerRNA *imfptr)
row = uiLayoutRow(box, false);
uiItemR(row, imfptr, "import_units", 0, NULL, ICON_NONE);
+
+ box = uiLayoutBox(layout);
+ row = uiLayoutRow(box, false);
+ uiItemL(row, IFACE_("Armature Options:"), ICON_MESH_DATA);
+
+ row = uiLayoutRow(box, false);
+ uiItemR(row, imfptr, "fix_orientation", 0, NULL, ICON_NONE);
+
+ row = uiLayoutRow(box, false);
+ uiItemR(row, imfptr, "find_chains", 0, NULL, ICON_NONE);
+
+ row = uiLayoutRow(box, false);
+ uiItemR(row, imfptr, "min_chain_length", 0, NULL, ICON_NONE);
}
static void wm_collada_import_draw(bContext *UNUSED(C), wmOperator *op)
@@ -414,13 +444,31 @@ void WM_OT_collada_import(wmOperatorType *ot)
ot->ui = wm_collada_import_draw;
- WM_operator_properties_filesel(ot, FOLDERFILE | COLLADAFILE, FILE_BLENDER, FILE_OPENFILE,
- WM_FILESEL_FILEPATH, FILE_DEFAULTDISPLAY);
+ WM_operator_properties_filesel(ot, FILE_TYPE_FOLDER | FILE_TYPE_COLLADA, FILE_BLENDER, FILE_OPENFILE,
+ WM_FILESEL_FILEPATH, FILE_DEFAULTDISPLAY, FILE_SORT_ALPHA);
+
+ RNA_def_boolean(ot->srna,
+ "import_units", 0, "Import Units",
+ "If disabled match import to Blender's current Unit settings, "
+ "otherwise use the settings from the Imported scene");
+
+ RNA_def_boolean(ot->srna,
+ "fix_orientation", 0, "Fix Leaf Bones",
+ "Fix Orientation of Leaf Bones (Collada does only support Joints)");
RNA_def_boolean(ot->srna,
- "import_units", 0, "Import Units",
- "If disabled match import to Blender's current Unit settings, "
- "otherwise use the settings from the Imported scene");
+ "find_chains", 0, "Find Bone Chains",
+ "Find best matching Bone Chains and ensure bones in chain are connected");
+
+ RNA_def_int(ot->srna,
+ "min_chain_length",
+ 0,
+ 0,
+ INT_MAX,
+ "Minimum Chain Length",
+ "When searching Bone Chains disregard chains of length below this value",
+ 0,
+ INT_MAX);
}
#endif
diff --git a/source/blender/editors/io/io_ops.c b/source/blender/editors/io/io_ops.c
index a33340cc39a..a70a51a60be 100644
--- a/source/blender/editors/io/io_ops.c
+++ b/source/blender/editors/io/io_ops.c
@@ -28,16 +28,13 @@
* \ingroup collada
*/
-
-#include "io_collada.h"
-
-#include "BLI_utildefines.h"
-
-#include "WM_types.h"
-#include "WM_api.h"
-
#include "io_ops.h" /* own include */
+#ifdef WITH_COLLADA
+# include "io_collada.h"
+# include "WM_api.h"
+#endif
+
void ED_operatortypes_io(void)
{
#ifdef WITH_COLLADA
diff --git a/source/blender/editors/mask/CMakeLists.txt b/source/blender/editors/mask/CMakeLists.txt
index b1cf6db3144..033d034cf4e 100644
--- a/source/blender/editors/mask/CMakeLists.txt
+++ b/source/blender/editors/mask/CMakeLists.txt
@@ -25,10 +25,12 @@ set(INC
../include
../../blenkernel
../../blenlib
+ ../../gpu
../../makesdna
../../makesrna
../../windowmanager
../../../../intern/guardedalloc
+ ../../../../intern/glew-mx
)
set(INC_SYS
@@ -48,4 +50,6 @@ set(SRC
mask_intern.h
)
+add_definitions(${GL_DEFINITIONS})
+
blender_add_lib(bf_editor_mask "${SRC}" "${INC}" "${INC_SYS}")
diff --git a/source/blender/editors/mask/SConscript b/source/blender/editors/mask/SConscript
index 9dd521e3a7c..c4e6daaf5df 100644
--- a/source/blender/editors/mask/SConscript
+++ b/source/blender/editors/mask/SConscript
@@ -30,13 +30,16 @@ Import ('env')
sources = env.Glob('*.c')
defs = []
+defs += env['BF_GL_DEFINITIONS']
incs = [
'#/intern/guardedalloc',
- '#/extern/glew/include',
+ env['BF_GLEW_INC'],
+ '#/intern/glew-mx',
'../include',
'../../blenkernel',
'../../blenlib',
+ '../../gpu',
'../../makesdna',
'../../makesrna',
'../../windowmanager',
diff --git a/source/blender/editors/mask/mask_add.c b/source/blender/editors/mask/mask_add.c
index b816103de13..822bb429f9e 100644
--- a/source/blender/editors/mask/mask_add.c
+++ b/source/blender/editors/mask/mask_add.c
@@ -57,12 +57,14 @@ bool ED_mask_find_nearest_diff_point(const bContext *C,
struct Mask *mask,
const float normal_co[2],
int threshold, bool feather,
+ float tangent[2],
+ const bool use_deform,
+ const bool use_project,
MaskLayer **masklay_r,
MaskSpline **spline_r,
MaskSplinePoint **point_r,
- float *u_r, float tangent[2],
- const bool use_deform,
- const bool use_project)
+ float *u_r,
+ float *score_r)
{
ScrArea *sa = CTX_wm_area(C);
ARegion *ar = CTX_wm_region(C);
@@ -70,9 +72,9 @@ bool ED_mask_find_nearest_diff_point(const bContext *C,
MaskLayer *masklay, *point_masklay;
MaskSpline *point_spline;
MaskSplinePoint *point = NULL;
- float dist = FLT_MAX, co[2];
+ float dist_best_sq = FLT_MAX, co[2];
int width, height;
- float u;
+ float u = 0.0f;
float scalex, scaley;
ED_mask_get_size(sa, &width, &height);
@@ -121,7 +123,7 @@ bool ED_mask_find_nearest_diff_point(const bContext *C,
}
for (j = 0; j < tot_point - 1; j++) {
- float cur_dist, a[2], b[2];
+ float dist_sq, a[2], b[2];
a[0] = points[2 * j] * scalex;
a[1] = points[2 * j + 1] * scaley;
@@ -129,16 +131,16 @@ bool ED_mask_find_nearest_diff_point(const bContext *C,
b[0] = points[2 * j + 2] * scalex;
b[1] = points[2 * j + 3] * scaley;
- cur_dist = dist_to_line_segment_v2(co, a, b);
+ dist_sq = dist_squared_to_line_segment_v2(co, a, b);
- if (cur_dist < dist) {
+ if (dist_sq < dist_best_sq) {
if (tangent)
sub_v2_v2v2(tangent, &diff_points[2 * j + 2], &diff_points[2 * j]);
point_masklay = masklay;
point_spline = spline;
point = use_deform ? &spline->points[(cur_point - spline->points_deform)] : cur_point;
- dist = cur_dist;
+ dist_best_sq = dist_sq;
u = (float)j / tot_point;
}
}
@@ -152,7 +154,7 @@ bool ED_mask_find_nearest_diff_point(const bContext *C,
}
}
- if (point && dist < threshold) {
+ if (point && dist_best_sq < threshold) {
if (masklay_r)
*masklay_r = point_masklay;
@@ -171,6 +173,10 @@ bool ED_mask_find_nearest_diff_point(const bContext *C,
*u_r = u;
}
+ if (score_r) {
+ *score_r = dist_best_sq;
+ }
+
return true;
}
@@ -339,7 +345,9 @@ static bool add_vertex_subdivide(const bContext *C, Mask *mask, const float co[2
float tangent[2];
float u;
- if (ED_mask_find_nearest_diff_point(C, mask, co, threshold, false, &masklay, &spline, &point, &u, tangent, true, true)) {
+ if (ED_mask_find_nearest_diff_point(C, mask, co, threshold, false, tangent, true, true,
+ &masklay, &spline, &point, &u, NULL))
+ {
MaskSplinePoint *new_point;
int point_index = point - spline->points;
@@ -624,7 +632,9 @@ static int add_feather_vertex_exec(bContext *C, wmOperator *op)
if (point)
return OPERATOR_FINISHED;
- if (ED_mask_find_nearest_diff_point(C, mask, co, threshold, true, &masklay, &spline, &point, &u, NULL, true, true)) {
+ if (ED_mask_find_nearest_diff_point(C, mask, co, threshold, true, NULL, true, true,
+ &masklay, &spline, &point, &u, NULL))
+ {
Scene *scene = CTX_data_scene(C);
float w = BKE_mask_point_weight(spline, point, u);
float weight_scalar = BKE_mask_point_weight_scalar(spline, point, u);
diff --git a/source/blender/editors/mask/mask_draw.c b/source/blender/editors/mask/mask_draw.c
index 7e767d8f6c8..2efa9e211c9 100644
--- a/source/blender/editors/mask/mask_draw.c
+++ b/source/blender/editors/mask/mask_draw.c
@@ -253,7 +253,7 @@ static void draw_spline_points(const bContext *C, MaskLayer *masklay, MaskSpline
return;
if (sc)
- undistort = sc->clip && (sc->user.render_flag & MCLIP_PROXY_RENDER_UNDISTORT) != 0;
+ undistort = sc->clip && (sc->user.render_flag & MCLIP_PROXY_RENDER_UNDISTORT);
/* TODO, add this to sequence editor */
handle_size = UI_GetThemeValuef(TH_HANDLE_VERTEX_SIZE) * U.pixelsize;
@@ -422,7 +422,7 @@ static void mask_draw_curve_type(const bContext *C, MaskSpline *spline, float (*
float (*points)[2] = orig_points;
if (sc) {
- int undistort = sc->clip && sc->user.render_flag & MCLIP_PROXY_RENDER_UNDISTORT;
+ const bool undistort = sc->clip && (sc->user.render_flag & MCLIP_PROXY_RENDER_UNDISTORT);
if (undistort) {
int i;
diff --git a/source/blender/editors/mask/mask_edit.c b/source/blender/editors/mask/mask_edit.c
index e2eb32e86d9..e1a58d529b6 100644
--- a/source/blender/editors/mask/mask_edit.c
+++ b/source/blender/editors/mask/mask_edit.c
@@ -35,6 +35,7 @@
#include "BKE_context.h"
#include "BKE_mask.h"
+#include "DNA_mask_types.h"
#include "DNA_scene_types.h"
#include "WM_api.h"
@@ -397,6 +398,58 @@ void ED_mask_cursor_location_get(ScrArea *sa, float cursor[2])
}
}
+bool ED_mask_selected_minmax(const bContext *C, float min[2], float max[2])
+{
+ Mask *mask = CTX_data_edit_mask(C);
+ MaskLayer *mask_layer;
+ bool ok = false;
+ INIT_MINMAX2(min, max);
+ for (mask_layer = mask->masklayers.first;
+ mask_layer != NULL;
+ mask_layer = mask_layer->next)
+ {
+ MaskSpline *spline;
+ if (mask_layer->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) {
+ continue;
+ }
+ for (spline = mask_layer->splines.first;
+ spline != NULL;
+ spline = spline->next)
+ {
+ MaskSplinePoint *points_array = BKE_mask_spline_point_array(spline);
+ int i;
+ for (i = 0; i < spline->tot_point; i++) {
+ MaskSplinePoint *point = &spline->points[i];
+ MaskSplinePoint *deform_point = &points_array[i];
+ BezTriple *bezt = &point->bezt;
+ float handle[2];
+ if (!MASKPOINT_ISSEL_ANY(point)) {
+ continue;
+ }
+ if (bezt->f2 & SELECT) {
+ minmax_v2v2_v2(min, max, deform_point->bezt.vec[1]);
+ }
+ if (BKE_mask_point_handles_mode_get(point) == MASK_HANDLE_MODE_STICK) {
+ BKE_mask_point_handle(deform_point, MASK_WHICH_HANDLE_STICK, handle);
+ minmax_v2v2_v2(min, max, handle);
+ }
+ else {
+ if ((bezt->f1 & SELECT) && (bezt->h1 != HD_VECT)) {
+ BKE_mask_point_handle(deform_point, MASK_WHICH_HANDLE_LEFT, handle);
+ minmax_v2v2_v2(min, max, handle);
+ }
+ if ((bezt->f3 & SELECT) && (bezt->h2 != HD_VECT)) {
+ BKE_mask_point_handle(deform_point, MASK_WHICH_HANDLE_RIGHT, handle);
+ minmax_v2v2_v2(min, max, handle);
+ }
+ }
+ ok = true;
+ }
+ }
+ }
+ return ok;
+}
+
/********************** registration *********************/
void ED_operatortypes_mask(void)
diff --git a/source/blender/editors/mask/mask_intern.h b/source/blender/editors/mask/mask_intern.h
index 6899cf7e6f5..66a6c75272e 100644
--- a/source/blender/editors/mask/mask_intern.h
+++ b/source/blender/editors/mask/mask_intern.h
@@ -34,7 +34,6 @@
struct bContext;
struct Mask;
-struct wmEvent;
struct wmOperatorType;
/* internal exports only */
@@ -44,12 +43,14 @@ bool ED_mask_find_nearest_diff_point(const struct bContext *C,
struct Mask *mask,
const float normal_co[2],
int threshold, bool feather,
+ float tangent[2],
+ const bool use_deform,
+ const bool use_project,
struct MaskLayer **masklay_r,
struct MaskSpline **spline_r,
struct MaskSplinePoint **point_r,
- float *u_r, float tangent[2],
- const bool use_deform,
- const bool use_project);
+ float *u_r,
+ float *score_r);
void MASK_OT_add_vertex(struct wmOperatorType *ot);
void MASK_OT_add_feather_vertex(struct wmOperatorType *ot);
diff --git a/source/blender/editors/mask/mask_ops.c b/source/blender/editors/mask/mask_ops.c
index 2497095aca6..bf8630ff843 100644
--- a/source/blender/editors/mask/mask_ops.c
+++ b/source/blender/editors/mask/mask_ops.c
@@ -510,12 +510,13 @@ static bool spline_under_mouse_get(const bContext *C,
MaskLayer **mask_layer_r,
MaskSpline **mask_spline_r)
{
+ const float threshold = 19.0f;
ScrArea *sa = CTX_wm_area(C);
SpaceClip *sc = CTX_wm_space_clip(C);
MaskLayer *mask_layer;
int width, height;
float pixel_co[2];
- float closest_dist_squared;
+ float closest_dist_squared = 0.0f;
MaskLayer *closest_layer = NULL;
MaskSpline *closest_spline = NULL;
bool undistort = false;
@@ -580,7 +581,18 @@ static bool spline_under_mouse_get(const bContext *C,
}
}
}
- if (closest_spline != NULL) {
+ if (closest_dist_squared < SQUARE(threshold) && closest_spline != NULL) {
+ float diff_score;
+ if (ED_mask_find_nearest_diff_point(C, mask, co, threshold,
+ false, NULL, true, false,
+ NULL, NULL, NULL, NULL,
+ &diff_score))
+ {
+ if (SQUARE(diff_score) < closest_dist_squared) {
+ return false;
+ }
+ }
+
*mask_layer_r = closest_layer;
*mask_spline_r = closest_spline;
return true;
@@ -772,7 +784,7 @@ static int slide_point_invoke(bContext *C, wmOperator *op, const wmEvent *event)
SlidePointData *slidedata;
if (mask == NULL) {
- return OPERATOR_CANCELLED;
+ return OPERATOR_PASS_THROUGH;
}
slidedata = slide_point_customdata(C, op, event);
@@ -1164,7 +1176,7 @@ static bool slide_spline_curvature_check(bContext *C, const wmEvent *event)
{
Mask *mask = CTX_data_edit_mask(C);
float co[2];
- const float threshold = 19;
+ const float threshold = 19.0f;
ED_mask_mouse_pos(CTX_wm_area(C), CTX_wm_region(C), event->mval, co);
@@ -1182,7 +1194,7 @@ static bool slide_spline_curvature_check(bContext *C, const wmEvent *event)
static SlideSplineCurvatureData *slide_spline_curvature_customdata(
bContext *C, const wmEvent *event)
{
- const float threshold = 19;
+ const float threshold = 19.0f;
Mask *mask = CTX_data_edit_mask(C);
SlideSplineCurvatureData *slide_data;
@@ -1195,8 +1207,9 @@ static SlideSplineCurvatureData *slide_spline_curvature_customdata(
ED_mask_mouse_pos(CTX_wm_area(C), CTX_wm_region(C), event->mval, co);
if (!ED_mask_find_nearest_diff_point(C, mask, co, threshold, false,
+ NULL, true, false,
&mask_layer, &spline, &point, &u,
- NULL, true, false))
+ NULL))
{
return NULL;
}
@@ -1273,7 +1286,7 @@ static int slide_spline_curvature_invoke(bContext *C, wmOperator *op, const wmEv
SlideSplineCurvatureData *slide_data;
if (mask == NULL) {
- return OPERATOR_CANCELLED;
+ return OPERATOR_PASS_THROUGH;
}
/* Be sure we don't conflict with point slide here. */
@@ -2196,7 +2209,7 @@ static int mask_duplicate_exec(bContext *C, wmOperator *UNUSED(op))
}
if (end >= start) {
int tot_point;
- int tot_point_shape_start;
+ int tot_point_shape_start = 0;
MaskSpline *new_spline = BKE_mask_spline_add(mask_layer);
MaskSplinePoint *new_point;
int b;
@@ -2294,6 +2307,10 @@ static int copy_splines_exec(bContext *C, wmOperator *UNUSED(op))
Mask *mask = CTX_data_edit_mask(C);
MaskLayer *mask_layer = BKE_mask_layer_active(mask);
+ if (mask_layer == NULL) {
+ return OPERATOR_CANCELLED;
+ }
+
BKE_mask_clipboard_copy_from_layer(mask_layer);
return OPERATOR_FINISHED;
diff --git a/source/blender/editors/mask/mask_relationships.c b/source/blender/editors/mask/mask_relationships.c
index e02561d839c..4e0aa8f84ae 100644
--- a/source/blender/editors/mask/mask_relationships.c
+++ b/source/blender/editors/mask/mask_relationships.c
@@ -39,7 +39,6 @@
#include "BKE_tracking.h"
#include "DNA_mask_types.h"
-#include "DNA_object_types.h" /* SELECT */
#include "WM_api.h"
#include "WM_types.h"
diff --git a/source/blender/editors/mesh/CMakeLists.txt b/source/blender/editors/mesh/CMakeLists.txt
index 0cb2dd1eb68..0280f662a26 100644
--- a/source/blender/editors/mesh/CMakeLists.txt
+++ b/source/blender/editors/mesh/CMakeLists.txt
@@ -21,9 +21,9 @@
set(INC
../include
../uvedit
- ../../blenfont
../../blenkernel
../../blenlib
+ ../../blentranslation
../../bmesh
../../gpu
../../imbuf
@@ -32,6 +32,7 @@ set(INC
../../render/extern/include
../../windowmanager
../../../../intern/guardedalloc
+ ../../../../intern/glew-mx
)
set(INC_SYS
@@ -86,4 +87,6 @@ if(WITH_BULLET)
add_definitions(-DWITH_BULLET)
endif()
+add_definitions(${GL_DEFINITIONS})
+
blender_add_lib(bf_editor_mesh "${SRC}" "${INC}" "${INC_SYS}")
diff --git a/source/blender/editors/mesh/SConscript b/source/blender/editors/mesh/SConscript
index 6fa48c12eca..df58b2a90b3 100644
--- a/source/blender/editors/mesh/SConscript
+++ b/source/blender/editors/mesh/SConscript
@@ -30,15 +30,17 @@ Import ('env')
sources = env.Glob('*.c')
defs = []
+defs += env['BF_GL_DEFINITIONS']
incs = [
'#/intern/guardedalloc',
- '#/extern/glew/include',
+ env['BF_GLEW_INC'],
+ '#/intern/glew-mx',
'../include',
'../uvedit',
- '../../blenfont',
'../../blenkernel',
'../../blenlib',
+ '../../blentranslation',
'../../bmesh',
'../../gpu',
'../../imbuf',
diff --git a/source/blender/editors/mesh/editface.c b/source/blender/editors/mesh/editface.c
index 87b429f1165..0017cd3c2ae 100644
--- a/source/blender/editors/mesh/editface.c
+++ b/source/blender/editors/mesh/editface.c
@@ -31,8 +31,6 @@
#include "BLI_math.h"
#include "BLI_bitmap.h"
-#include "BLF_translation.h"
-
#include "IMB_imbuf_types.h"
#include "IMB_imbuf.h"
@@ -64,9 +62,8 @@ void paintface_flush_flags(Object *ob)
Mesh *me = BKE_mesh_from_object(ob);
DerivedMesh *dm = ob->derivedFinal;
MPoly *polys, *mp_orig;
- MFace *faces;
const int *index_array = NULL;
- int totface, totpoly;
+ int totpoly;
int i;
if (me == NULL)
@@ -81,26 +78,7 @@ void paintface_flush_flags(Object *ob)
if (dm == NULL)
return;
- /*
- * Try to push updated mesh poly flags to three other data sets:
- * - Mesh polys => Mesh tess faces
- * - Mesh polys => Final derived polys
- * - Final derived polys => Final derived tessfaces
- */
-
- if ((index_array = CustomData_get_layer(&me->fdata, CD_ORIGINDEX))) {
- faces = me->mface;
- totface = me->totface;
-
- /* loop over tessfaces */
- for (i = 0; i < totface; i++) {
- if (index_array[i] != ORIGINDEX_NONE) {
- /* Copy flags onto the original tessface from its original poly */
- mp_orig = me->mpoly + index_array[i];
- faces[i].flag = mp_orig->flag;
- }
- }
- }
+ /* Mesh polys => Final derived polys */
if ((index_array = CustomData_get_layer(&dm->polyData, CD_ORIGINDEX))) {
polys = dm->getPolyArray(dm);
@@ -115,21 +93,6 @@ void paintface_flush_flags(Object *ob)
}
}
}
-
- if ((index_array = CustomData_get_layer(&dm->faceData, CD_ORIGINDEX))) {
- polys = dm->getPolyArray(dm);
- faces = dm->getTessFaceArray(dm);
- totface = dm->getNumTessFaces(dm);
-
- /* loop over tessfaces */
- for (i = 0; i < totface; i++) {
- if (index_array[i] != ORIGINDEX_NONE) {
- /* Copy flags onto the final tessface from its final poly */
- mp_orig = polys + index_array[i];
- faces[i].flag = mp_orig->flag;
- }
- }
- }
}
void paintface_hide(Object *ob, const bool unselected)
@@ -428,13 +391,15 @@ int do_paintface_box_select(ViewContext *vc, rcti *rect, bool select, bool exten
unsigned int *rt;
char *selar;
int a, index;
- int sx = BLI_rcti_size_x(rect) + 1;
- int sy = BLI_rcti_size_y(rect) + 1;
+ const int size[2] = {
+ BLI_rcti_size_x(rect) + 1,
+ BLI_rcti_size_y(rect) + 1};
me = BKE_mesh_from_object(ob);
- if (me == NULL || me->totpoly == 0 || sx * sy <= 0)
+ if ((me == NULL) || (me->totpoly == 0) || (size[0] * size[1] <= 0)) {
return OPERATOR_CANCELLED;
+ }
selar = MEM_callocN(me->totpoly + 1, "selar");
@@ -448,18 +413,23 @@ int do_paintface_box_select(ViewContext *vc, rcti *rect, bool select, bool exten
}
}
- view3d_validate_backbuf(vc);
+ ED_view3d_backbuf_validate(vc);
- ibuf = IMB_allocImBuf(sx, sy, 32, IB_rect);
+ ibuf = IMB_allocImBuf(size[0], size[1], 32, IB_rect);
rt = ibuf->rect;
- view3d_opengl_read_pixels(vc->ar, rect->xmin, rect->ymin, sx, sy, GL_RGBA, GL_UNSIGNED_BYTE, ibuf->rect);
- if (ENDIAN_ORDER == B_ENDIAN) IMB_convert_rgba_to_abgr(ibuf);
+ view3d_opengl_read_pixels(vc->ar, rect->xmin, rect->ymin, size[0], size[1], GL_RGBA, GL_UNSIGNED_BYTE, ibuf->rect);
+ if (ENDIAN_ORDER == B_ENDIAN) {
+ IMB_convert_rgba_to_abgr(ibuf);
+ }
+ WM_framebuffer_to_index_array(ibuf->rect, size[0] * size[1]);
- a = sx * sy;
+ a = size[0] * size[1];
while (a--) {
if (*rt) {
- index = WM_framebuffer_to_index(*rt);
- if (index <= me->totpoly) selar[index] = 1;
+ index = *rt;
+ if (index <= me->totpoly) {
+ selar[index] = 1;
+ }
}
rt++;
}
@@ -627,7 +597,7 @@ void paintvert_select_ungrouped(Object *ob, bool extend, bool flush_flags)
/* ********************* MESH VERTEX MIRR TOPO LOOKUP *************** */
/* note, this is not the best place for the function to be but moved
- * here to for the purpose of syncing with bmesh */
+ * here for the purpose of syncing with bmesh */
typedef unsigned int MirrTopoHash_t;
diff --git a/source/blender/editors/mesh/editmesh_add.c b/source/blender/editors/mesh/editmesh_add.c
index b288a02a3d1..e073a255f73 100644
--- a/source/blender/editors/mesh/editmesh_add.c
+++ b/source/blender/editors/mesh/editmesh_add.c
@@ -32,8 +32,9 @@
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
+#include "BLI_math.h"
-#include "BLF_translation.h"
+#include "BLT_translation.h"
#include "BKE_context.h"
#include "BKE_library.h"
@@ -51,6 +52,10 @@
#include "mesh_intern.h" /* own include */
+
+#define MESH_ADD_VERTS_MAXI 10000000
+
+
/* ********* add primitive operators ************* */
static Object *make_prim_init(bContext *C, const char *idname,
@@ -61,17 +66,14 @@ static Object *make_prim_init(bContext *C, const char *idname,
*was_editmode = false;
if (obedit == NULL || obedit->type != OB_MESH) {
- obedit = ED_object_add_type(C, OB_MESH, loc, rot, false, layer);
-
- rename_id((ID *)obedit, idname);
- rename_id((ID *)obedit->data, idname);
+ obedit = ED_object_add_type(C, OB_MESH, idname, loc, rot, false, layer);
/* create editmode */
ED_object_editmode_enter(C, EM_DO_UNDO | EM_IGNORE_LAYER); /* rare cases the active layer is messed up */
*was_editmode = true;
}
- *dia = ED_object_new_primitive_matrix(C, obedit, loc, rot, mat, false);
+ *dia = ED_object_new_primitive_matrix(C, obedit, loc, rot, mat);
return obedit;
}
@@ -106,7 +108,7 @@ static int add_primitive_plane_exec(bContext *C, wmOperator *op)
WM_operator_view3d_unit_defaults(C, op);
ED_object_add_generic_get_opts(C, op, 'Z', loc, rot, &enter_editmode, &layer, NULL);
- obedit = make_prim_init(C, CTX_DATA_(BLF_I18NCONTEXT_ID_MESH, "Plane"), &dia, mat, &was_editmode, loc, rot, layer);
+ obedit = make_prim_init(C, CTX_DATA_(BLT_I18NCONTEXT_ID_MESH, "Plane"), &dia, mat, &was_editmode, loc, rot, layer);
em = BKE_editmesh_from_object(obedit);
if (!EDBM_op_call_and_selectf(
@@ -151,7 +153,7 @@ static int add_primitive_cube_exec(bContext *C, wmOperator *op)
WM_operator_view3d_unit_defaults(C, op);
ED_object_add_generic_get_opts(C, op, 'Z', loc, rot, &enter_editmode, &layer, NULL);
- obedit = make_prim_init(C, CTX_DATA_(BLF_I18NCONTEXT_ID_MESH, "Cube"), &dia, mat, &was_editmode, loc, rot, layer);
+ obedit = make_prim_init(C, CTX_DATA_(BLT_I18NCONTEXT_ID_MESH, "Cube"), &dia, mat, &was_editmode, loc, rot, layer);
em = BKE_editmesh_from_object(obedit);
if (!EDBM_op_call_and_selectf(
@@ -207,7 +209,7 @@ static int add_primitive_circle_exec(bContext *C, wmOperator *op)
WM_operator_view3d_unit_defaults(C, op);
ED_object_add_generic_get_opts(C, op, 'Z', loc, rot, &enter_editmode, &layer, NULL);
- obedit = make_prim_init(C, CTX_DATA_(BLF_I18NCONTEXT_ID_MESH, "Circle"), &dia, mat, &was_editmode, loc, rot, layer);
+ obedit = make_prim_init(C, CTX_DATA_(BLT_I18NCONTEXT_ID_MESH, "Circle"), &dia, mat, &was_editmode, loc, rot, layer);
em = BKE_editmesh_from_object(obedit);
if (!EDBM_op_call_and_selectf(
@@ -239,7 +241,7 @@ void MESH_OT_primitive_circle_add(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
/* props */
- RNA_def_int(ot->srna, "vertices", 32, 3, INT_MAX, "Vertices", "", 3, 500);
+ RNA_def_int(ot->srna, "vertices", 32, 3, MESH_ADD_VERTS_MAXI, "Vertices", "", 3, 500);
ED_object_add_unit_props(ot);
RNA_def_enum(ot->srna, "fill_type", fill_type_items, 0, "Fill Type", "");
@@ -260,7 +262,7 @@ static int add_primitive_cylinder_exec(bContext *C, wmOperator *op)
WM_operator_view3d_unit_defaults(C, op);
ED_object_add_generic_get_opts(C, op, 'Z', loc, rot, &enter_editmode, &layer, NULL);
- obedit = make_prim_init(C, CTX_DATA_(BLF_I18NCONTEXT_ID_MESH, "Cylinder"), &dia, mat, &was_editmode, loc, rot, layer);
+ obedit = make_prim_init(C, CTX_DATA_(BLT_I18NCONTEXT_ID_MESH, "Cylinder"), &dia, mat, &was_editmode, loc, rot, layer);
em = BKE_editmesh_from_object(obedit);
if (!EDBM_op_call_and_selectf(
@@ -297,9 +299,9 @@ void MESH_OT_primitive_cylinder_add(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
/* props */
- RNA_def_int(ot->srna, "vertices", 32, 3, INT_MAX, "Vertices", "", 3, 500);
+ RNA_def_int(ot->srna, "vertices", 32, 3, MESH_ADD_VERTS_MAXI, "Vertices", "", 3, 500);
ED_object_add_unit_props(ot);
- prop = RNA_def_float(ot->srna, "depth", 2.0f, 0.0, FLT_MAX, "Depth", "", 0.001, 100.00);
+ prop = RNA_def_float(ot->srna, "depth", 2.0f, 0.0, OBJECT_ADD_SIZE_MAXF, "Depth", "", 0.001, 100.00);
RNA_def_property_subtype(prop, PROP_DISTANCE);
RNA_def_enum(ot->srna, "end_fill_type", fill_type_items, 1, "Cap Fill Type", "");
@@ -320,7 +322,7 @@ static int add_primitive_cone_exec(bContext *C, wmOperator *op)
WM_operator_view3d_unit_defaults(C, op);
ED_object_add_generic_get_opts(C, op, 'Z', loc, rot, &enter_editmode, &layer, NULL);
- obedit = make_prim_init(C, CTX_DATA_(BLF_I18NCONTEXT_ID_MESH, "Cone"), &dia, mat, &was_editmode, loc, rot, layer);
+ obedit = make_prim_init(C, CTX_DATA_(BLT_I18NCONTEXT_ID_MESH, "Cone"), &dia, mat, &was_editmode, loc, rot, layer);
em = BKE_editmesh_from_object(obedit);
if (!EDBM_op_call_and_selectf(
@@ -354,12 +356,12 @@ void MESH_OT_primitive_cone_add(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
/* props */
- RNA_def_int(ot->srna, "vertices", 32, 3, INT_MAX, "Vertices", "", 3, 500);
- prop = RNA_def_float(ot->srna, "radius1", 1.0f, 0.0, FLT_MAX, "Radius 1", "", 0.001, 100.00);
+ RNA_def_int(ot->srna, "vertices", 32, 3, MESH_ADD_VERTS_MAXI, "Vertices", "", 3, 500);
+ prop = RNA_def_float(ot->srna, "radius1", 1.0f, 0.0, OBJECT_ADD_SIZE_MAXF, "Radius 1", "", 0.001, 100.00);
RNA_def_property_subtype(prop, PROP_DISTANCE);
- prop = RNA_def_float(ot->srna, "radius2", 0.0f, 0.0, FLT_MAX, "Radius 2", "", 0.001, 100.00);
+ prop = RNA_def_float(ot->srna, "radius2", 0.0f, 0.0, OBJECT_ADD_SIZE_MAXF, "Radius 2", "", 0.001, 100.00);
RNA_def_property_subtype(prop, PROP_DISTANCE);
- prop = RNA_def_float(ot->srna, "depth", 2.0f, 0.0, FLT_MAX, "Depth", "", 0.001, 100.00);
+ prop = RNA_def_float(ot->srna, "depth", 2.0f, 0.0, OBJECT_ADD_SIZE_MAXF, "Depth", "", 0.001, 100.00);
RNA_def_property_subtype(prop, PROP_DISTANCE);
RNA_def_enum(ot->srna, "end_fill_type", fill_type_items, 1, "Base Fill Type", "");
@@ -377,7 +379,7 @@ static int add_primitive_grid_exec(bContext *C, wmOperator *op)
WM_operator_view3d_unit_defaults(C, op);
ED_object_add_generic_get_opts(C, op, 'Z', loc, rot, &enter_editmode, &layer, NULL);
- obedit = make_prim_init(C, CTX_DATA_(BLF_I18NCONTEXT_ID_MESH, "Grid"), &dia, mat, &was_editmode, loc, rot, layer);
+ obedit = make_prim_init(C, CTX_DATA_(BLT_I18NCONTEXT_ID_MESH, "Grid"), &dia, mat, &was_editmode, loc, rot, layer);
em = BKE_editmesh_from_object(obedit);
if (!EDBM_op_call_and_selectf(
@@ -410,8 +412,10 @@ void MESH_OT_primitive_grid_add(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
/* props */
- 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);
+ /* Note that if you use MESH_ADD_VERTS_MAXI for both x and y at the same time you will still reach
+ * impossible values (10^12 vertices or so...). */
+ RNA_def_int(ot->srna, "x_subdivisions", 10, 2, MESH_ADD_VERTS_MAXI, "X Subdivisions", "", 2, 1000);
+ RNA_def_int(ot->srna, "y_subdivisions", 10, 2, MESH_ADD_VERTS_MAXI, "Y Subdivisions", "", 2, 1000);
ED_object_add_unit_props(ot);
ED_object_add_generic_props(ot, true);
@@ -421,7 +425,9 @@ static int add_primitive_monkey_exec(bContext *C, wmOperator *op)
{
Object *obedit;
BMEditMesh *em;
- float loc[3], rot[3], mat[4][4], dia;
+ float mat[4][4];
+ float loc[3], rot[3];
+ float dia;
bool enter_editmode;
unsigned int layer;
bool was_editmode;
@@ -429,11 +435,9 @@ static int add_primitive_monkey_exec(bContext *C, wmOperator *op)
WM_operator_view3d_unit_defaults(C, op);
ED_object_add_generic_get_opts(C, op, 'Y', loc, rot, &enter_editmode, &layer, NULL);
- obedit = make_prim_init(C, CTX_DATA_(BLF_I18NCONTEXT_ID_MESH, "Suzanne"), &dia, mat, &was_editmode, loc, rot, layer);
+ obedit = make_prim_init(C, CTX_DATA_(BLT_I18NCONTEXT_ID_MESH, "Suzanne"), &dia, mat, &was_editmode, loc, rot, layer);
dia = RNA_float_get(op->ptr, "radius");
- mat[0][0] *= dia;
- mat[1][1] *= dia;
- mat[2][2] *= dia;
+ mul_mat3_m4_fl(mat, dia);
em = BKE_editmesh_from_object(obedit);
@@ -478,7 +482,7 @@ static int add_primitive_uvsphere_exec(bContext *C, wmOperator *op)
WM_operator_view3d_unit_defaults(C, op);
ED_object_add_generic_get_opts(C, op, 'Z', loc, rot, &enter_editmode, &layer, NULL);
- obedit = make_prim_init(C, CTX_DATA_(BLF_I18NCONTEXT_ID_MESH, "Sphere"), &dia, mat, &was_editmode, loc, rot, layer);
+ obedit = make_prim_init(C, CTX_DATA_(BLT_I18NCONTEXT_ID_MESH, "Sphere"), &dia, mat, &was_editmode, loc, rot, layer);
em = BKE_editmesh_from_object(obedit);
if (!EDBM_op_call_and_selectf(
@@ -512,9 +516,9 @@ void MESH_OT_primitive_uv_sphere_add(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
/* props */
- RNA_def_int(ot->srna, "segments", 32, 3, INT_MAX, "Segments", "", 3, 500);
- RNA_def_int(ot->srna, "ring_count", 16, 3, INT_MAX, "Rings", "", 3, 500);
- prop = RNA_def_float(ot->srna, "size", 1.0f, 0.0, FLT_MAX, "Size", "", 0.001, 100.00);
+ RNA_def_int(ot->srna, "segments", 32, 3, MESH_ADD_VERTS_MAXI / 100, "Segments", "", 3, 500);
+ RNA_def_int(ot->srna, "ring_count", 16, 3, MESH_ADD_VERTS_MAXI / 100, "Rings", "", 3, 500);
+ prop = RNA_def_float(ot->srna, "size", 1.0f, 0.0, OBJECT_ADD_SIZE_MAXF, "Size", "", 0.001, 100.00);
RNA_def_property_subtype(prop, PROP_DISTANCE);
ED_object_add_generic_props(ot, true);
@@ -531,7 +535,7 @@ static int add_primitive_icosphere_exec(bContext *C, wmOperator *op)
WM_operator_view3d_unit_defaults(C, op);
ED_object_add_generic_get_opts(C, op, 'Z', loc, rot, &enter_editmode, &layer, NULL);
- obedit = make_prim_init(C, CTX_DATA_(BLF_I18NCONTEXT_ID_MESH, "Icosphere"), &dia, mat, &was_editmode, loc, rot, layer);
+ obedit = make_prim_init(C, CTX_DATA_(BLT_I18NCONTEXT_ID_MESH, "Icosphere"), &dia, mat, &was_editmode, loc, rot, layer);
em = BKE_editmesh_from_object(obedit);
if (!EDBM_op_call_and_selectf(
@@ -565,8 +569,8 @@ void MESH_OT_primitive_ico_sphere_add(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
/* props */
- RNA_def_int(ot->srna, "subdivisions", 2, 1, INT_MAX, "Subdivisions", "", 1, 8);
- prop = RNA_def_float(ot->srna, "size", 1.0f, 0.0f, FLT_MAX, "Size", "", 0.001f, 100.00);
+ RNA_def_int(ot->srna, "subdivisions", 2, 1, 10, "Subdivisions", "", 1, 8);
+ prop = RNA_def_float(ot->srna, "size", 1.0f, 0.0f, OBJECT_ADD_SIZE_MAXF, "Size", "", 0.001f, 100.00);
RNA_def_property_subtype(prop, PROP_DISTANCE);
ED_object_add_generic_props(ot, true);
diff --git a/source/blender/editors/mesh/editmesh_bevel.c b/source/blender/editors/mesh/editmesh_bevel.c
index 48d5113a279..ce6856321d2 100644
--- a/source/blender/editors/mesh/editmesh_bevel.c
+++ b/source/blender/editors/mesh/editmesh_bevel.c
@@ -31,7 +31,7 @@
#include "BLI_string.h"
#include "BLI_math.h"
-#include "BLF_translation.h"
+#include "BLT_translation.h"
#include "BKE_context.h"
#include "BKE_global.h"
@@ -75,7 +75,8 @@ typedef struct {
static void edbm_bevel_update_header(bContext *C, wmOperator *op)
{
- const char *str = IFACE_("Confirm: (Enter/LMB), Cancel: (Esc/RMB), Mode: %s (M), Offset: %s, Segments: %d");
+ const char *str = IFACE_("Confirm: (Enter/LMB), Cancel: (Esc/RMB), Mode: %s (M), Clamp Overlap: %s (C), "
+ "Vertex Only: %s (V), Offset: %s, Segments: %d");
char msg[HEADER_LENGTH];
ScrArea *sa = CTX_wm_area(C);
@@ -96,7 +97,10 @@ static void edbm_bevel_update_header(bContext *C, wmOperator *op)
RNA_property_enum_name_gettexted(C, op->ptr, prop, RNA_property_enum_get(op->ptr, prop), &type_str);
- BLI_snprintf(msg, HEADER_LENGTH, str, type_str, offset_str, RNA_int_get(op->ptr, "segments"));
+ BLI_snprintf(msg, HEADER_LENGTH, str, type_str,
+ WM_bool_as_string(RNA_boolean_get(op->ptr, "clamp_overlap")),
+ WM_bool_as_string(RNA_boolean_get(op->ptr, "vertex_only")),
+ offset_str, RNA_int_get(op->ptr, "segments"));
ED_area_headerprint(sa, msg);
}
@@ -150,7 +154,9 @@ static bool edbm_bevel_calc(wmOperator *op)
const int segments = RNA_int_get(op->ptr, "segments");
const float profile = RNA_float_get(op->ptr, "profile");
const bool vertex_only = RNA_boolean_get(op->ptr, "vertex_only");
+ const bool clamp_overlap = RNA_boolean_get(op->ptr, "clamp_overlap");
int material = RNA_int_get(op->ptr, "material");
+ const bool loop_slide = RNA_boolean_get(op->ptr, "loop_slide");
/* revert to original mesh */
if (opdata->is_modal) {
@@ -161,8 +167,9 @@ static bool edbm_bevel_calc(wmOperator *op)
material = CLAMPIS(material, -1, em->ob->totcol - 1);
EDBM_op_init(em, &bmop, op,
- "bevel geom=%hev offset=%f segments=%i vertex_only=%b offset_type=%i profile=%f material=%i",
- BM_ELEM_SELECT, offset, segments, vertex_only, offset_type, profile, material);
+ "bevel geom=%hev offset=%f segments=%i vertex_only=%b offset_type=%i profile=%f clamp_overlap=%b "
+ "material=%i loop_slide=%b",
+ BM_ELEM_SELECT, offset, segments, vertex_only, offset_type, profile, clamp_overlap, material, loop_slide);
BMO_op_exec(em->bm, &bmop);
@@ -408,6 +415,31 @@ static int edbm_bevel_modal(bContext *C, wmOperator *op, const wmEvent *event)
edbm_bevel_update_header(C, op);
handled = true;
break;
+ case CKEY:
+ if (event->val == KM_RELEASE)
+ break;
+
+ {
+ PropertyRNA *prop = RNA_struct_find_property(op->ptr, "clamp_overlap");
+ RNA_property_enum_set(op->ptr, prop, !RNA_property_boolean_get(op->ptr, prop));
+ }
+ edbm_bevel_calc(op);
+ edbm_bevel_update_header(C, op);
+ handled = true;
+ break;
+ case VKEY:
+ if (event->val == KM_RELEASE)
+ break;
+
+ {
+ PropertyRNA *prop = RNA_struct_find_property(op->ptr, "vertex_only");
+ RNA_property_enum_set(op->ptr, prop, !RNA_property_boolean_get(op->ptr, prop));
+ }
+ edbm_bevel_calc(op);
+ edbm_bevel_update_header(C, op);
+ handled = true;
+ break;
+
}
/* Modal numinput inactive, try to handle numeric inputs last... */
@@ -460,13 +492,16 @@ void MESH_OT_bevel(wmOperatorType *ot)
ot->poll = ED_operator_editmesh;
/* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_GRAB_POINTER | OPTYPE_BLOCKING;
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_GRAB_CURSOR | OPTYPE_BLOCKING;
RNA_def_enum(ot->srna, "offset_type", offset_type_items, 0, "Amount Type", "What distance Amount measures");
- prop = RNA_def_float(ot->srna, "offset", 0.0f, -FLT_MAX, FLT_MAX, "Amount", "", 0.0f, 1.0f);
+ prop = RNA_def_float(ot->srna, "offset", 0.0f, -1e6f, 1e6f, "Amount", "", 0.0f, 1.0f);
RNA_def_property_float_array_funcs_runtime(prop, NULL, NULL, mesh_ot_bevel_offset_range_func);
RNA_def_int(ot->srna, "segments", 1, 1, 50, "Segments", "Segments for curved edge", 1, 8);
RNA_def_float(ot->srna, "profile", 0.5f, 0.15f, 1.0f, "Profile", "Controls profile shape (0.5 = round)", 0.15f, 1.0f);
- RNA_def_boolean(ot->srna, "vertex_only", false, "Vertex only", "Bevel only vertices");
+ RNA_def_boolean(ot->srna, "vertex_only", false, "Vertex Only", "Bevel only vertices");
+ RNA_def_boolean(ot->srna, "clamp_overlap", false, "Clamp Overlap",
+ "Do not allow beveled edges/vertices to overlap each other");
+ RNA_def_boolean(ot->srna, "loop_slide", true, "Loop Slide", "Prefer slide along edge to even widths");
RNA_def_int(ot->srna, "material", -1, -1, INT_MAX, "Material", "Material for bevel faces (-1 means use adjacent faces)", -1, 100);
}
diff --git a/source/blender/editors/mesh/editmesh_bisect.c b/source/blender/editors/mesh/editmesh_bisect.c
index 6a54f1979cf..08d0697e0f1 100644
--- a/source/blender/editors/mesh/editmesh_bisect.c
+++ b/source/blender/editors/mesh/editmesh_bisect.c
@@ -33,7 +33,7 @@
#include "BLI_math.h"
-#include "BLF_translation.h"
+#include "BLT_translation.h"
#include "BKE_global.h"
#include "BKE_context.h"
@@ -264,7 +264,7 @@ static int mesh_bisect_exec(bContext *C, wmOperator *op)
invert_m4_m4(imat, obedit->obmat);
mul_m4_v3(imat, plane_co);
- mul_mat3_m4_v3(imat, plane_no);
+ mul_transposed_mat3_m4_v3(obedit->obmat, plane_no);
EDBM_op_init(em, &bmop, op,
"bisect_plane geom=%hvef plane_co=%v plane_no=%v dist=%f clear_inner=%b clear_outer=%b",
@@ -335,11 +335,11 @@ void MESH_OT_bisect(struct wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- prop = RNA_def_float_vector(ot->srna, "plane_co", 3, NULL, -FLT_MAX, FLT_MAX,
- "Plane Point", "A point on the plane", -FLT_MAX, FLT_MAX);
+ prop = RNA_def_float_vector(ot->srna, "plane_co", 3, NULL, -1e12f, 1e12f,
+ "Plane Point", "A point on the plane", -1e4f, 1e4f);
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
- prop = RNA_def_float_vector(ot->srna, "plane_no", 3, NULL, -FLT_MAX, FLT_MAX,
- "Plane Normal", "The direction the plane points", -FLT_MAX, FLT_MAX);
+ prop = RNA_def_float_vector(ot->srna, "plane_no", 3, NULL, -1.0f, 1.0f,
+ "Plane Normal", "The direction the plane points", -1.0f, 1.0f);
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
RNA_def_boolean(ot->srna, "use_fill", false, "Fill", "Fill in the cut");
diff --git a/source/blender/editors/mesh/editmesh_extrude.c b/source/blender/editors/mesh/editmesh_extrude.c
index 3e403387a67..a020fed0835 100644
--- a/source/blender/editors/mesh/editmesh_extrude.c
+++ b/source/blender/editors/mesh/editmesh_extrude.c
@@ -54,18 +54,6 @@
#include "mesh_intern.h" /* own include */
-/* allow accumulated normals to form a new direction but don't
- * accept direct opposite directions else they will cancel each other out */
-static void add_normal_aligned(float nor[3], const float add[3])
-{
- if (dot_v3v3(nor, add) < -0.9999f) {
- sub_v3_v3(nor, add);
- }
- else {
- add_v3_v3(nor, add);
- }
-}
-
static void edbm_extrude_edge_exclude_mirror(
Object *obedit, BMEditMesh *em,
const char hflag,
@@ -137,7 +125,7 @@ static void edbm_extrude_edge_exclude_mirror(
/* individual face extrude */
/* will use vertex normals for extrusion directions, so *nor is unaffected */
-static short edbm_extrude_discrete_faces(BMEditMesh *em, wmOperator *op, const char hflag, float *UNUSED(nor))
+static bool edbm_extrude_discrete_faces(BMEditMesh *em, wmOperator *op, const char hflag)
{
BMOIter siter;
BMIter liter;
@@ -165,14 +153,14 @@ static short edbm_extrude_discrete_faces(BMEditMesh *em, wmOperator *op, const c
}
if (!EDBM_op_finish(em, &bmop, op, true)) {
- return 0;
+ return false;
}
- return 's'; /* s is shrink/fatten */
+ return true;
}
/* extrudes individual edges */
-static short edbm_extrude_edges_indiv(BMEditMesh *em, wmOperator *op, const char hflag, float *UNUSED(nor))
+static bool edbm_extrude_edges_indiv(BMEditMesh *em, wmOperator *op, const char hflag)
{
BMesh *bm = em->bm;
BMOperator bmop;
@@ -191,14 +179,14 @@ static short edbm_extrude_edges_indiv(BMEditMesh *em, wmOperator *op, const char
BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_out, "geom.out", BM_VERT | BM_EDGE, BM_ELEM_SELECT, true);
if (!EDBM_op_finish(em, &bmop, op, true)) {
- return 0;
+ return false;
}
- return 'n'; /* n is normal grab */
+ return true;
}
/* extrudes individual vertices */
-static short edbm_extrude_verts_indiv(BMEditMesh *em, wmOperator *op, const char hflag, float *UNUSED(nor))
+static bool edbm_extrude_verts_indiv(BMEditMesh *em, wmOperator *op, const char hflag)
{
BMOperator bmop;
@@ -214,27 +202,55 @@ static short edbm_extrude_verts_indiv(BMEditMesh *em, wmOperator *op, const char
BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_out, "verts.out", BM_VERT, BM_ELEM_SELECT, true);
if (!EDBM_op_finish(em, &bmop, op, true)) {
- return 0;
+ return false;
}
- return 'g'; /* g is grab */
+ return true;
}
-static short edbm_extrude_edge_ex(
+static char edbm_extrude_htype_from_em_select(BMEditMesh *em)
+{
+ char htype = BM_ALL_NOLOOP;
+
+ if (em->selectmode & SCE_SELECT_VERTEX) {
+ /* pass */
+ }
+ else if (em->selectmode & SCE_SELECT_EDGE) {
+ htype &= ~BM_VERT;
+ }
+ else {
+ htype &= ~(BM_VERT | BM_EDGE);
+ }
+
+ if (em->bm->totedgesel == 0) {
+ htype &= ~(BM_EDGE | BM_FACE);
+ }
+ else if (em->bm->totfacesel == 0) {
+ htype &= ~BM_FACE;
+ }
+
+ return htype;
+}
+
+static bool edbm_extrude_ex(
Object *obedit, BMEditMesh *em,
- const char hflag, float nor[3],
+ char htype, const char hflag,
const bool use_mirror,
const bool use_select_history)
{
BMesh *bm = em->bm;
BMOIter siter;
BMOperator extop;
- BMFace *f;
BMElem *ele;
+ /* needed to remove the faces left behind */
+ if (htype & BM_FACE) {
+ htype |= BM_EDGE;
+ }
+
BMO_op_init(bm, &extop, BMO_FLAG_DEFAULTS, "extrude_face_region");
BMO_slot_bool_set(extop.slots_in, "use_select_history", use_select_history);
- BMO_slot_buffer_from_enabled_hflag(bm, &extop, extop.slots_in, "geom", BM_VERT | BM_EDGE | BM_FACE, hflag);
+ BMO_slot_buffer_from_enabled_hflag(bm, &extop, extop.slots_in, "geom", htype, hflag);
if (use_mirror) {
BMOpSlot *slot_edges_exclude;
@@ -248,61 +264,14 @@ static short edbm_extrude_edge_ex(
BM_SELECT_HISTORY_RESTORE(bm);
BMO_op_exec(bm, &extop);
-
- zero_v3(nor);
- BMO_ITER (ele, &siter, extop.slots_out, "geom.out", BM_ALL) {
+ BMO_ITER (ele, &siter, extop.slots_out, "geom.out", BM_ALL_NOLOOP) {
BM_elem_select_set(bm, ele, true);
-
- if (ele->head.htype == BM_FACE) {
- f = (BMFace *)ele;
- add_normal_aligned(nor, f->no);
- }
}
- normalize_v3(nor);
-
BMO_op_finish(bm, &extop);
- /* grab / normal constraint */
- return is_zero_v3(nor) ? 'g' : 'n';
-}
-
-static short edbm_extrude_edge(
- Object *obedit, BMEditMesh *em,
- const char hflag, float nor[3])
-{
- return edbm_extrude_edge_ex(obedit, em, hflag, nor, true, true);
-}
-
-static short edbm_extrude_vert(Object *obedit, BMEditMesh *em, const char hflag, float nor[3])
-{
- BMIter iter;
- BMEdge *eed;
-
- /* ensure vert flags are consistent for edge selections */
- BM_ITER_MESH (eed, &iter, em->bm, BM_EDGES_OF_MESH) {
- if (BM_elem_flag_test(eed, hflag)) {
- if (hflag & BM_ELEM_SELECT) {
- BM_vert_select_set(em->bm, eed->v1, true);
- BM_vert_select_set(em->bm, eed->v2, true);
- }
-
- BM_elem_flag_enable(eed->v1, hflag & ~BM_ELEM_SELECT);
- BM_elem_flag_enable(eed->v2, hflag & ~BM_ELEM_SELECT);
- }
- else {
- if (BM_elem_flag_test(eed->v1, hflag) && BM_elem_flag_test(eed->v2, hflag)) {
- if (hflag & BM_ELEM_SELECT) {
- BM_edge_select_set(em->bm, eed, true);
- }
-
- BM_elem_flag_enable(eed, hflag & ~BM_ELEM_SELECT);
- }
- }
- }
-
- return edbm_extrude_edge(obedit, em, hflag, nor);
+ return true;
}
static int edbm_extrude_repeat_exec(bContext *C, wmOperator *op)
@@ -314,7 +283,7 @@ static int edbm_extrude_repeat_exec(bContext *C, wmOperator *op)
const int steps = RNA_int_get(op->ptr, "steps");
const float offs = RNA_float_get(op->ptr, "offset");
- float dvec[3], tmat[3][3], bmat[3][3], nor[3] = {0.0, 0.0, 0.0};
+ float dvec[3], tmat[3][3], bmat[3][3];
short a;
/* dvec */
@@ -327,7 +296,7 @@ static int edbm_extrude_repeat_exec(bContext *C, wmOperator *op)
mul_m3_v3(tmat, dvec);
for (a = 0; a < steps; a++) {
- edbm_extrude_edge_ex(obedit, em, BM_ELEM_SELECT, nor, false, false);
+ edbm_extrude_ex(obedit, em, BM_ALL_NOLOOP, BM_ELEM_SELECT, false, false);
BMO_op_callf(
em->bm, BMO_FLAG_DEFAULTS,
@@ -357,92 +326,63 @@ void MESH_OT_extrude_repeat(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
/* props */
- RNA_def_float(ot->srna, "offset", 2.0f, 0.0f, FLT_MAX, "Offset", "", 0.0f, 100.0f);
- RNA_def_int(ot->srna, "steps", 10, 0, INT_MAX, "Steps", "", 0, 180);
+ RNA_def_float(ot->srna, "offset", 2.0f, 0.0f, 1e12f, "Offset", "", 0.0f, 100.0f);
+ RNA_def_int(ot->srna, "steps", 10, 0, 1000000, "Steps", "", 0, 180);
}
/* generic extern called extruder */
-static int edbm_extrude_mesh(Scene *scene, Object *obedit, BMEditMesh *em, wmOperator *op, float *norin)
+static bool edbm_extrude_mesh(Object *obedit, BMEditMesh *em, wmOperator *op)
{
- short nr, transmode = 0;
- float stacknor[3] = {0.0f, 0.0f, 0.0f};
- float *nor = norin ? norin : stacknor;
-
- zero_v3(nor);
+ bool changed = false;
+ const char htype = edbm_extrude_htype_from_em_select(em);
+ enum {NONE = 0, ELEM_FLAG, VERT_ONLY, EDGE_ONLY} nr;
if (em->selectmode & SCE_SELECT_VERTEX) {
- if (em->bm->totvertsel == 0) nr = 0;
- else if (em->bm->totvertsel == 1) nr = 4;
- else if (em->bm->totedgesel == 0) nr = 4;
- else if (em->bm->totfacesel == 0)
- nr = 3;
- else if (em->bm->totfacesel == 1)
- nr = 1;
- else
- nr = 1;
+ if (em->bm->totvertsel == 0) nr = NONE;
+ else if (em->bm->totvertsel == 1) nr = VERT_ONLY;
+ else if (em->bm->totedgesel == 0) nr = VERT_ONLY;
+ else nr = ELEM_FLAG;
}
else if (em->selectmode & SCE_SELECT_EDGE) {
- if (em->bm->totedgesel == 0) nr = 0;
-
- nr = 1;
+ if (em->bm->totedgesel == 0) nr = NONE;
+ else if (em->bm->totfacesel == 0) nr = EDGE_ONLY;
+ else nr = ELEM_FLAG;
}
else {
- if (em->bm->totfacesel == 0) nr = 0;
- else if (em->bm->totfacesel == 1) nr = 1;
- else
- nr = 1;
+ if (em->bm->totfacesel == 0) nr = NONE;
+ else nr = ELEM_FLAG;
}
- if (nr < 1) return 'g';
-
- if (nr == 1 && (em->selectmode & SCE_SELECT_VERTEX))
- transmode = edbm_extrude_vert(obedit, em, BM_ELEM_SELECT, nor);
- else if (nr == 1) transmode = edbm_extrude_edge(obedit, em, BM_ELEM_SELECT, nor);
- else if (nr == 4) transmode = edbm_extrude_verts_indiv(em, op, BM_ELEM_SELECT, nor);
- else if (nr == 3) transmode = edbm_extrude_edges_indiv(em, op, BM_ELEM_SELECT, nor);
- else transmode = edbm_extrude_discrete_faces(em, op, BM_ELEM_SELECT, nor);
+ switch (nr) {
+ case NONE:
+ return false;
+ case ELEM_FLAG:
+ changed = edbm_extrude_ex(obedit, em, htype, BM_ELEM_SELECT, true, true);
+ break;
+ case VERT_ONLY:
+ changed = edbm_extrude_verts_indiv(em, op, BM_ELEM_SELECT);
+ break;
+ case EDGE_ONLY:
+ changed = edbm_extrude_edges_indiv(em, op, BM_ELEM_SELECT);
+ break;
+ }
- if (transmode == 0) {
- BKE_report(op->reports, RPT_ERROR, "Not a valid selection for extrude");
+ if (changed) {
+ return true;
}
else {
-
- /* We need to force immediate calculation here because
- * transform may use derived objects (which are now stale).
- *
- * This shouldn't be necessary, derived queries should be
- * automatically building this data if invalid. Or something.
- */
-// DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
- BKE_object_handle_update(G.main->eval_ctx, scene, obedit);
-
- /* individual faces? */
- if (nr == 2) {
-// initTransform(TFM_SHRINKFATTEN, CTX_NO_PET|CTX_NO_MIRROR);
-// Transform();
- }
- else {
-// initTransform(TFM_TRANSLATION, CTX_NO_PET|CTX_NO_MIRROR);
- if (transmode == 'n') {
- mul_m4_v3(obedit->obmat, nor);
- sub_v3_v3v3(nor, nor, obedit->obmat[3]);
-// BIF_setSingleAxisConstraint(nor, "along normal");
- }
-// Transform();
- }
+ BKE_report(op->reports, RPT_ERROR, "Not a valid selection for extrude");
+ return false;
}
-
- return transmode;
}
/* extrude without transform */
static int edbm_extrude_region_exec(bContext *C, wmOperator *op)
{
- Scene *scene = CTX_data_scene(C);
Object *obedit = CTX_data_edit_object(C);
BMEditMesh *em = BKE_editmesh_from_object(obedit);
- edbm_extrude_mesh(scene, obedit, em, op, NULL);
+ edbm_extrude_mesh(obedit, em, op);
/* This normally happens when pushing undo but modal operators
* like this one don't push undo data until after modal mode is
@@ -476,9 +416,8 @@ static int edbm_extrude_verts_exec(bContext *C, wmOperator *op)
{
Object *obedit = CTX_data_edit_object(C);
BMEditMesh *em = BKE_editmesh_from_object(obedit);
- float nor[3];
- edbm_extrude_verts_indiv(em, op, BM_ELEM_SELECT, nor);
+ edbm_extrude_verts_indiv(em, op, BM_ELEM_SELECT);
EDBM_update_generic(em, true, true);
@@ -507,9 +446,8 @@ static int edbm_extrude_edges_exec(bContext *C, wmOperator *op)
{
Object *obedit = CTX_data_edit_object(C);
BMEditMesh *em = BKE_editmesh_from_object(obedit);
- float nor[3];
- edbm_extrude_edges_indiv(em, op, BM_ELEM_SELECT, nor);
+ edbm_extrude_edges_indiv(em, op, BM_ELEM_SELECT);
EDBM_update_generic(em, true, true);
@@ -538,9 +476,8 @@ static int edbm_extrude_faces_exec(bContext *C, wmOperator *op)
{
Object *obedit = CTX_data_edit_object(C);
BMEditMesh *em = BKE_editmesh_from_object(obedit);
- float nor[3];
- edbm_extrude_discrete_faces(em, op, BM_ELEM_SELECT, nor);
+ edbm_extrude_discrete_faces(em, op, BM_ELEM_SELECT);
EDBM_update_generic(em, true, true);
@@ -573,12 +510,11 @@ static int edbm_dupli_extrude_cursor_invoke(bContext *C, wmOperator *op, const w
float min[3], max[3];
bool done = false;
bool use_proj;
-
+
em_setup_viewcontext(C, &vc);
ED_view3d_init_mats_rv3d(vc.obedit, vc.rv3d);
-
use_proj = ((vc.scene->toolsettings->snap_flag & SCE_SNAP) &&
(vc.scene->toolsettings->snap_mode == SCE_SNAP_MODE_FACE));
@@ -593,6 +529,7 @@ static int edbm_dupli_extrude_cursor_invoke(bContext *C, wmOperator *op, const w
/* call extrude? */
if (done) {
+ const char extrude_htype = edbm_extrude_htype_from_em_select(vc.em);
const bool rot_src = RNA_boolean_get(op->ptr, "rotate_source");
BMEdge *eed;
float vec[3], cent[3], mat[3][3];
@@ -637,8 +574,7 @@ static int edbm_dupli_extrude_cursor_invoke(bContext *C, wmOperator *op, const w
mul_mat3_m4_v3(vc.obedit->imat, nor); /* local space */
/* correct the normal to be aligned on the view plane */
- copy_v3_v3(view_vec, vc.rv3d->viewinv[2]);
- mul_mat3_m4_v3(vc.obedit->imat, view_vec);
+ mul_v3_mat3_m4v3(view_vec, vc.obedit->imat, vc.rv3d->viewinv[2]);
cross_v3_v3v3(cross, nor, view_vec);
cross_v3_v3v3(nor, view_vec, cross);
normalize_v3(nor);
@@ -686,7 +622,7 @@ static int edbm_dupli_extrude_cursor_invoke(bContext *C, wmOperator *op, const w
EMBM_project_snap_verts(C, vc.ar, vc.em);
}
- edbm_extrude_edge(vc.obedit, vc.em, BM_ELEM_SELECT, nor);
+ edbm_extrude_ex(vc.obedit, vc.em, extrude_htype, BM_ELEM_SELECT, true, true);
EDBM_op_callf(vc.em, op, "rotate verts=%hv cent=%v matrix=%m3",
BM_ELEM_SELECT, cent, mat);
EDBM_op_callf(vc.em, op, "translate verts=%hv vec=%v",
@@ -742,7 +678,7 @@ void MESH_OT_dupli_extrude_cursor(wmOperatorType *ot)
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- RNA_def_boolean(ot->srna, "rotate_source", 1, "Rotate Source", "Rotate initial selection giving better shape");
+ RNA_def_boolean(ot->srna, "rotate_source", true, "Rotate Source", "Rotate initial selection giving better shape");
}
@@ -765,6 +701,11 @@ static int edbm_spin_exec(bContext *C, wmOperator *op)
angle = -angle;
dupli = RNA_boolean_get(op->ptr, "dupli");
+ if (is_zero_v3(axis)) {
+ BKE_report(op->reports, RPT_ERROR, "Invalid/unset axis");
+ return OPERATOR_CANCELLED;
+ }
+
/* keep the values in worldspace since we're passing the obmat */
if (!EDBM_op_init(em, &spinop, op,
"spin geom=%hvef cent=%v axis=%v dvec=%v steps=%i angle=%f space=%m4 use_duplicate=%b",
@@ -809,19 +750,21 @@ void MESH_OT_spin(wmOperatorType *ot)
/* api callbacks */
ot->invoke = edbm_spin_invoke;
ot->exec = edbm_spin_exec;
- ot->poll = EDBM_view3d_poll;
+ ot->poll = ED_operator_editmesh;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
/* props */
- RNA_def_int(ot->srna, "steps", 9, 0, INT_MAX, "Steps", "Steps", 0, INT_MAX);
+ RNA_def_int(ot->srna, "steps", 9, 0, 1000000, "Steps", "Steps", 0, 1000);
RNA_def_boolean(ot->srna, "dupli", 0, "Dupli", "Make Duplicates");
- prop = RNA_def_float(ot->srna, "angle", DEG2RADF(90.0f), -FLT_MAX, FLT_MAX, "Angle", "Angle", DEG2RADF(-360.0f), DEG2RADF(360.0f));
+ prop = RNA_def_float(ot->srna, "angle", DEG2RADF(90.0f), -1e12f, 1e12f, "Angle", "Rotation for each step",
+ DEG2RADF(-360.0f), DEG2RADF(360.0f));
RNA_def_property_subtype(prop, PROP_ANGLE);
- RNA_def_float_vector(ot->srna, "center", 3, NULL, -FLT_MAX, FLT_MAX, "Center", "Center in global view space", -FLT_MAX, FLT_MAX);
- RNA_def_float_vector(ot->srna, "axis", 3, NULL, -FLT_MAX, FLT_MAX, "Axis", "Axis in global view space", -1.0f, 1.0f);
+ RNA_def_float_vector(ot->srna, "center", 3, NULL, -1e12f, 1e12f,
+ "Center", "Center in global view space", -1e4f, 1e4f);
+ RNA_def_float_vector(ot->srna, "axis", 3, NULL, -1.0f, 1.0f, "Axis", "Axis in global view space", -1.0f, 1.0f);
}
@@ -844,6 +787,11 @@ static int edbm_screw_exec(bContext *C, wmOperator *op)
RNA_float_get_array(op->ptr, "center", cent);
RNA_float_get_array(op->ptr, "axis", axis);
+ if (is_zero_v3(axis)) {
+ BKE_report(op->reports, RPT_ERROR, "Invalid/unset axis");
+ return OPERATOR_CANCELLED;
+ }
+
/* find two vertices with valence count == 1, more or less is wrong */
v1 = NULL;
v2 = NULL;
@@ -927,17 +875,17 @@ void MESH_OT_screw(wmOperatorType *ot)
/* api callbacks */
ot->invoke = edbm_screw_invoke;
ot->exec = edbm_screw_exec;
- ot->poll = EDBM_view3d_poll;
+ ot->poll = ED_operator_editmesh;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
/* props */
- RNA_def_int(ot->srna, "steps", 9, 1, INT_MAX, "Steps", "Steps", 3, 256);
- RNA_def_int(ot->srna, "turns", 1, 1, INT_MAX, "Turns", "Turns", 1, 256);
+ RNA_def_int(ot->srna, "steps", 9, 1, 100000, "Steps", "Steps", 3, 256);
+ RNA_def_int(ot->srna, "turns", 1, 1, 100000, "Turns", "Turns", 1, 256);
- RNA_def_float_vector(ot->srna, "center", 3, NULL, -FLT_MAX, FLT_MAX,
- "Center", "Center in global view space", -FLT_MAX, FLT_MAX);
- RNA_def_float_vector(ot->srna, "axis", 3, NULL, -FLT_MAX, FLT_MAX,
+ RNA_def_float_vector(ot->srna, "center", 3, NULL, -1e12f, 1e12f,
+ "Center", "Center in global view space", -1e4f, 1e4f);
+ RNA_def_float_vector(ot->srna, "axis", 3, NULL, -1.0f, 1.0f,
"Axis", "Axis in global view space", -1.0f, 1.0f);
}
diff --git a/source/blender/editors/mesh/editmesh_inset.c b/source/blender/editors/mesh/editmesh_inset.c
index a90a002f29a..c037b0c6b0f 100644
--- a/source/blender/editors/mesh/editmesh_inset.c
+++ b/source/blender/editors/mesh/editmesh_inset.c
@@ -31,7 +31,7 @@
#include "BLI_string.h"
#include "BLI_math.h"
-#include "BLF_translation.h"
+#include "BLT_translation.h"
#include "BKE_context.h"
#include "BKE_global.h"
@@ -499,7 +499,7 @@ void MESH_OT_inset(wmOperatorType *ot)
ot->poll = ED_operator_editmesh;
/* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_GRAB_POINTER | OPTYPE_BLOCKING;
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_GRAB_CURSOR | OPTYPE_BLOCKING;
/* properties */
RNA_def_boolean(ot->srna, "use_boundary", true, "Boundary", "Inset face boundaries");
@@ -507,14 +507,14 @@ void MESH_OT_inset(wmOperatorType *ot)
RNA_def_boolean(ot->srna, "use_relative_offset", false, "Offset Relative", "Scale the offset by surrounding geometry");
RNA_def_boolean(ot->srna, "use_edge_rail", false, "Edge Rail", "Inset the region along existing edges");
- prop = RNA_def_float(ot->srna, "thickness", 0.01f, 0.0f, FLT_MAX, "Thickness", "", 0.0f, 10.0f);
+ prop = RNA_def_float(ot->srna, "thickness", 0.01f, 0.0f, 1e12f, "Thickness", "", 0.0f, 10.0f);
/* use 1 rather then 10 for max else dragging the button moves too far */
RNA_def_property_ui_range(prop, 0.0, 1.0, 0.01, 4);
- prop = RNA_def_float(ot->srna, "depth", 0.0f, -FLT_MAX, FLT_MAX, "Depth", "", -10.0f, 10.0f);
+ prop = RNA_def_float(ot->srna, "depth", 0.0f, -1e12f, 1e12f, "Depth", "", -10.0f, 10.0f);
RNA_def_property_ui_range(prop, -10.0f, 10.0f, 0.01, 4);
RNA_def_boolean(ot->srna, "use_outset", false, "Outset", "Outset rather than inset");
- RNA_def_boolean(ot->srna, "use_select_inset", true, "Select Outer", "Select the new inset faces");
+ RNA_def_boolean(ot->srna, "use_select_inset", false, "Select Outer", "Select the new inset faces");
RNA_def_boolean(ot->srna, "use_individual", false, "Individual", "Individual Face Inset");
RNA_def_boolean(ot->srna, "use_interpolate", true, "Interpolate", "Blend face data across the inset");
}
diff --git a/source/blender/editors/mesh/editmesh_intersect.c b/source/blender/editors/mesh/editmesh_intersect.c
index df6776950d7..e2e4638254b 100644
--- a/source/blender/editors/mesh/editmesh_intersect.c
+++ b/source/blender/editors/mesh/editmesh_intersect.c
@@ -38,7 +38,6 @@
#include "RNA_access.h"
#include "RNA_define.h"
-#include "WM_api.h"
#include "WM_types.h"
#include "ED_mesh.h"
@@ -334,7 +333,7 @@ static int edbm_face_split_by_edges_exec(bContext *C, wmOperator *UNUSED(op))
BMVert *v_other = BM_edge_other_vert(e, v);
float e_dir[3];
- /* we wan't closest to zero */
+ /* we want closest to zero */
float dot_best = FLT_MAX;
sub_v3_v3v3(e_dir, v_other->co, v->co);
diff --git a/source/blender/editors/mesh/editmesh_knife.c b/source/blender/editors/mesh/editmesh_knife.c
index 76c41adf444..dbbf49a527b 100644
--- a/source/blender/editors/mesh/editmesh_knife.c
+++ b/source/blender/editors/mesh/editmesh_knife.c
@@ -46,7 +46,7 @@
#include "BLI_smallhash.h"
#include "BLI_memarena.h"
-#include "BLF_translation.h"
+#include "BLT_translation.h"
#include "BKE_DerivedMesh.h"
#include "BKE_context.h"
@@ -66,6 +66,8 @@
#include "WM_types.h"
#include "DNA_object_types.h"
+
+#include "UI_interface.h"
#include "UI_resources.h"
#include "RNA_access.h"
@@ -75,10 +77,16 @@
#define KMAXDIST 10 /* max mouse distance from edge before not detecting it */
+/* WARNING: knife float precision is fragile:
+ * be careful before making changes here see: (T43229, T42864, T42459, T41164).
+ */
#define KNIFE_FLT_EPS 0.00001f
#define KNIFE_FLT_EPS_SQUARED (KNIFE_FLT_EPS * KNIFE_FLT_EPS)
#define KNIFE_FLT_EPSBIG 0.0005f
-#define KNIFE_FLT_EPS_PX 0.2f
+
+#define KNIFE_FLT_EPS_PX_VERT 0.5f
+#define KNIFE_FLT_EPS_PX_EDGE 0.05f
+#define KNIFE_FLT_EPS_PX_FACE 0.05f
typedef struct KnifeColors {
unsigned char line[3];
@@ -97,7 +105,7 @@ typedef struct KnifeVert {
float co[3], cageco[3], sco[2]; /* sco is screen coordinates for cageco */
bool is_face, in_space;
- bool draw;
+ bool is_cut; /* along a cut created by user input (will draw too) */
} KnifeVert;
typedef struct Ref {
@@ -111,7 +119,7 @@ typedef struct KnifeEdge {
ListBase faces;
BMEdge *e /* , *e_old */; /* non-NULL if this is an original edge */
- bool draw;
+ bool is_cut; /* along a cut created by user input (will draw too) */
} KnifeEdge;
typedef struct KnifeLineHit {
@@ -152,6 +160,7 @@ typedef struct KnifeTool_OpData {
float mval[2]; /* mouse value with snapping applied */
//bContext *C;
+ Scene *scene;
Object *ob;
BMEditMesh *em;
@@ -174,8 +183,10 @@ typedef struct KnifeTool_OpData {
KnifeLineHit *linehits;
int totlinehit;
- /* Data for mouse-position-derived data (cur) and previous click (prev) */
- KnifePosData curr, prev;
+ /* Data for mouse-position-derived data */
+ KnifePosData curr; /* current point under the cursor */
+ KnifePosData prev; /* last added cut (a line draws from the cursor to this) */
+ KnifePosData init; /* the first point in the cut-list, used for closing the loop */
int totkedge, totkvert;
@@ -198,6 +209,8 @@ typedef struct KnifeTool_OpData {
bool is_ortho;
float ortho_extent;
+ float ortho_extent_center[3];
+
float clipsta, clipend;
enum {
@@ -206,6 +219,7 @@ typedef struct KnifeTool_OpData {
MODE_CONNECT,
MODE_PANNING
} mode;
+ bool is_drag_hold;
int prevmode;
bool snap_midpoints;
@@ -226,6 +240,22 @@ typedef struct KnifeTool_OpData {
const float (*cagecos)[3];
} KnifeTool_OpData;
+enum {
+ KNF_MODAL_CANCEL = 1,
+ KNF_MODAL_CONFIRM,
+ KNF_MODAL_MIDPOINT_ON,
+ KNF_MODAL_MIDPOINT_OFF,
+ KNF_MODAL_NEW_CUT,
+ KNF_MODEL_IGNORE_SNAP_ON,
+ KNF_MODEL_IGNORE_SNAP_OFF,
+ KNF_MODAL_ADD_CUT,
+ KNF_MODAL_ANGLE_SNAP_TOGGLE,
+ KNF_MODAL_CUT_THROUGH_TOGGLE,
+ KNF_MODAL_PANNING,
+ KNF_MODAL_ADD_CUT_CLOSED,
+};
+
+
static ListBase *knife_get_face_kedges(KnifeTool_OpData *kcd, BMFace *f);
static void knife_input_ray_segment(KnifeTool_OpData *kcd, const float mval[2], const float ofs,
@@ -233,20 +263,35 @@ static void knife_input_ray_segment(KnifeTool_OpData *kcd, const float mval[2],
static bool knife_verts_edge_in_face(KnifeVert *v1, KnifeVert *v2, BMFace *f);
-static void knife_update_header(bContext *C, KnifeTool_OpData *kcd)
+static void knifetool_free_bmbvh(KnifeTool_OpData *kcd);
+
+static void knife_update_header(bContext *C, wmOperator *op, KnifeTool_OpData *kcd)
{
-#define HEADER_LENGTH 256
- char header[HEADER_LENGTH];
+ char header[UI_MAX_DRAW_STR];
+ char buf[UI_MAX_DRAW_STR];
+
+ char *p = buf;
+ int available_len = sizeof(buf);
+
+#define WM_MODALKEY(_id) \
+ WM_modalkeymap_operator_items_to_string_buf(op->type, (_id), true, UI_MAX_SHORTCUT_STR, &available_len, &p)
+
+ BLI_snprintf(header, sizeof(header), IFACE_("%s: confirm, %s: cancel, "
+ "%s: start/define cut, %s: close cut, %s: new cut, "
+ "%s: midpoint snap (%s), %s: ignore snap (%s), "
+ "%s: angle constraint (%s), %s: cut through (%s), "
+ "%s: panning"),
+ WM_MODALKEY(KNF_MODAL_CONFIRM), WM_MODALKEY(KNF_MODAL_CANCEL),
+ WM_MODALKEY(KNF_MODAL_ADD_CUT), WM_MODALKEY(KNF_MODAL_ADD_CUT_CLOSED), WM_MODALKEY(KNF_MODAL_NEW_CUT),
+ WM_MODALKEY(KNF_MODAL_MIDPOINT_ON), WM_bool_as_string(kcd->snap_midpoints),
+ WM_MODALKEY(KNF_MODEL_IGNORE_SNAP_ON), WM_bool_as_string(kcd->ignore_edge_snapping),
+ WM_MODALKEY(KNF_MODAL_ANGLE_SNAP_TOGGLE), WM_bool_as_string(kcd->angle_snapping),
+ WM_MODALKEY(KNF_MODAL_CUT_THROUGH_TOGGLE), WM_bool_as_string(kcd->cut_through),
+ WM_MODALKEY(KNF_MODAL_PANNING));
+
+#undef WM_MODALKEY
- BLI_snprintf(header, HEADER_LENGTH, IFACE_("LMB: define cut lines, Return/Spacebar: confirm, Esc or RMB: cancel, "
- "E: new cut, Ctrl: midpoint snap (%s), Shift: ignore snap (%s), "
- "C: angle constrain (%s), Z: cut through (%s)"),
- WM_bool_as_string(kcd->snap_midpoints),
- WM_bool_as_string(kcd->ignore_edge_snapping),
- WM_bool_as_string(kcd->angle_snapping),
- WM_bool_as_string(kcd->cut_through));
ED_area_headerprint(CTX_wm_area(C), header);
-#undef HEADER_LENGTH
}
static void knife_project_v2(const KnifeTool_OpData *kcd, const float co[3], float sco[2])
@@ -526,7 +571,7 @@ static KnifeVert *knife_split_edge(
newkfe->v1 = kfe->v1;
newkfe->v2 = new_knife_vert(kcd, co, cageco);
- newkfe->v2->draw = 1;
+ newkfe->v2->is_cut = true;
if (kfe->e) {
knife_add_edge_faces_to_vert(kcd, newkfe->v2, kfe->e);
}
@@ -551,7 +596,7 @@ static KnifeVert *knife_split_edge(
knife_add_to_vert_edges(kcd, newkfe);
- newkfe->draw = kfe->draw;
+ newkfe->is_cut = kfe->is_cut;
newkfe->e = kfe->e;
*r_kfe = newkfe;
@@ -559,6 +604,16 @@ static KnifeVert *knife_split_edge(
return newkfe->v2;
}
+static void linehit_to_knifepos(KnifePosData *kpos, KnifeLineHit *lh)
+{
+ kpos->bmface = lh->f;
+ kpos->vert = lh->v;
+ kpos->edge = lh->kfe;
+ copy_v3_v3(kpos->cage, lh->cagehit);
+ copy_v3_v3(kpos->co, lh->hit);
+ copy_v2_v2(kpos->mval, lh->schit);
+}
+
/* primary key: lambda along cut
* secondary key: lambda along depth
* tertiary key: pointer comparisons of verts if both snapped to verts
@@ -590,6 +645,7 @@ static void prepare_linehits_for_cut(KnifeTool_OpData *kcd)
{
KnifeLineHit *linehits, *lhi, *lhj;
int i, j, n;
+ bool is_double = false;
n = kcd->totlinehit;
linehits = kcd->linehits;
@@ -613,7 +669,11 @@ static void prepare_linehits_for_cut(KnifeTool_OpData *kcd)
{
break;
}
- lhj->l = -1.0f;
+
+ if (lhi->kfe == lhj->kfe) {
+ lhj->l = -1.0f;
+ is_double = true;
+ }
}
for (j = i + 1; j < n; j++) {
lhj = &linehits[j];
@@ -622,37 +682,42 @@ static void prepare_linehits_for_cut(KnifeTool_OpData *kcd)
{
break;
}
- if (lhj->kfe || lhi->v == lhj->v) {
+ if ((lhj->kfe && (lhi->kfe == lhj->kfe)) ||
+ (lhi->v == lhj->v))
+ {
lhj->l = -1.0f;
+ is_double = true;
}
}
}
}
- /* delete-in-place loop: copying from pos j to pos i+1 */
- i = 0;
- j = 1;
- while (j < n) {
- lhi = &linehits[i];
- lhj = &linehits[j];
- if (lhj->l == -1.0f) {
- j++; /* skip copying this one */
- }
- else {
- /* copy unless a no-op */
- if (lhi->l == -1.0f) {
- /* could happen if linehits[0] is being deleted */
- memcpy(&linehits[i], &linehits[j], sizeof(KnifeLineHit));
+ if (is_double) {
+ /* delete-in-place loop: copying from pos j to pos i+1 */
+ i = 0;
+ j = 1;
+ while (j < n) {
+ lhi = &linehits[i];
+ lhj = &linehits[j];
+ if (lhj->l == -1.0f) {
+ j++; /* skip copying this one */
}
else {
- if (i + 1 != j)
- memcpy(&linehits[i + 1], &linehits[j], sizeof(KnifeLineHit));
- i++;
+ /* copy unless a no-op */
+ if (lhi->l == -1.0f) {
+ /* could happen if linehits[0] is being deleted */
+ memcpy(&linehits[i], &linehits[j], sizeof(KnifeLineHit));
+ }
+ else {
+ if (i + 1 != j)
+ memcpy(&linehits[i + 1], &linehits[j], sizeof(KnifeLineHit));
+ i++;
+ }
+ j++;
}
- j++;
}
+ kcd->totlinehit = i + 1;
}
- kcd->totlinehit = i + 1;
}
/* Add hit to list of hits in facehits[f], where facehits is a map, if not already there */
@@ -667,9 +732,38 @@ static void add_hit_to_facehits(KnifeTool_OpData *kcd, GHash *facehits, BMFace *
knife_append_list_no_dup(kcd, lst, hit);
}
+/**
+ * special purpose function, if the linehit is connected to a real edge/vert
+ * return true if \a co is outside the face.
+ */
+static bool knife_add_single_cut__is_linehit_outside_face(BMFace *f, const KnifeLineHit *lh, const float co[3])
+{
+
+ if (lh->v && lh->v->v) {
+ BMLoop *l; /* side-of-loop */
+ if ((l = BM_face_vert_share_loop(f, lh->v->v)) &&
+ (BM_loop_point_side_of_loop_test(l, co) < 0.0f))
+ {
+ return true;
+ }
+ }
+ else if ((lh->kfe && lh->kfe->e)) {
+ BMLoop *l; /* side-of-edge */
+ if ((l = BM_face_edge_share_loop(f, lh->kfe->e)) &&
+ (BM_loop_point_side_of_edge_test(l, co) < 0.0f))
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+
static void knife_add_single_cut(KnifeTool_OpData *kcd, KnifeLineHit *lh1, KnifeLineHit *lh2, BMFace *f)
{
KnifeEdge *kfe, *kfe2;
+ BMEdge *e_base;
if ((lh1->v && lh1->v == lh2->v) ||
(lh1->kfe && lh1->kfe == lh2->kfe))
@@ -677,6 +771,25 @@ static void knife_add_single_cut(KnifeTool_OpData *kcd, KnifeLineHit *lh1, Knife
return;
}
+ /* if the cut is on an edge, just tag that its a cut and return */
+ if ((lh1->v && lh2->v) &&
+ (lh1->v->v && lh2->v && lh2->v->v) &&
+ (e_base = BM_edge_exists(lh1->v->v, lh2->v->v)))
+ {
+ kfe = get_bm_knife_edge(kcd, e_base);
+ kfe->is_cut = true;
+ kfe->e = e_base;
+ return;
+ }
+ else {
+ if (knife_add_single_cut__is_linehit_outside_face(f, lh1, lh2->hit) ||
+ knife_add_single_cut__is_linehit_outside_face(f, lh2, lh1->hit))
+ {
+ return;
+ }
+ }
+
+
/* Check if edge actually lies within face (might not, if this face is concave) */
if ((lh1->v && !lh1->kfe) && (lh2->v && !lh2->kfe)) {
if (!knife_verts_edge_in_face(lh1->v, lh2->v, f)) {
@@ -685,7 +798,7 @@ static void knife_add_single_cut(KnifeTool_OpData *kcd, KnifeLineHit *lh1, Knife
}
kfe = new_knife_edge(kcd);
- kfe->draw = true;
+ kfe->is_cut = true;
kfe->basef = f;
if (lh1->v) {
@@ -698,7 +811,7 @@ static void knife_add_single_cut(KnifeTool_OpData *kcd, KnifeLineHit *lh1, Knife
else {
BLI_assert(lh1->f);
kfe->v1 = new_knife_vert(kcd, lh1->hit, lh1->cagehit);
- kfe->v1->draw = true;
+ kfe->v1->is_cut = true;
kfe->v1->is_face = true;
knife_append_list(kcd, &kfe->v1->faces, lh1->f);
lh1->v = kfe->v1; /* record the KnifeVert for this hit */
@@ -714,7 +827,7 @@ static void knife_add_single_cut(KnifeTool_OpData *kcd, KnifeLineHit *lh1, Knife
else {
BLI_assert(lh2->f);
kfe->v2 = new_knife_vert(kcd, lh2->hit, lh2->cagehit);
- kfe->v2->draw = true;
+ kfe->v2->is_cut = true;
kfe->v2->is_face = true;
knife_append_list(kcd, &kfe->v2->faces, lh2->f);
lh2->v = kfe->v2; /* record the KnifeVert for this hit */
@@ -735,23 +848,13 @@ static void knife_add_single_cut(KnifeTool_OpData *kcd, KnifeLineHit *lh1, Knife
static void knife_cut_face(KnifeTool_OpData *kcd, BMFace *f, ListBase *hits)
{
Ref *r;
- KnifeLineHit *lh, *prevlh;
- int n;
- (void) kcd;
-
- n = BLI_countlist(hits);
- if (n < 2)
+ if (BLI_listbase_count_ex(hits, 2) != 2)
return;
- prevlh = NULL;
- for (r = hits->first; r; r = r->next) {
- lh = (KnifeLineHit *)r->ref;
- if (prevlh)
- knife_add_single_cut(kcd, prevlh, lh, f);
- prevlh = lh;
+ for (r = hits->first; r->next; r = r->next) {
+ knife_add_single_cut(kcd, r->ref, r->next->ref, f);
}
-
}
/* User has just left-clicked after the first time.
@@ -771,7 +874,9 @@ static void knife_add_cut(KnifeTool_OpData *kcd)
prepare_linehits_for_cut(kcd);
if (kcd->totlinehit == 0) {
- kcd->prev = kcd->curr;
+ if (kcd->is_drag_hold == false) {
+ kcd->prev = kcd->curr;
+ }
return;
}
@@ -806,10 +911,19 @@ static void knife_add_cut(KnifeTool_OpData *kcd)
/* set up for next cut */
kcd->prev = kcd->curr;
+
+
if (kcd->prev.bmface) {
+ KnifeLineHit *lh;
/* was "in face" but now we have a KnifeVert it is snapped to */
+ lh = &kcd->linehits[kcd->totlinehit - 1];
+ kcd->prev.vert = lh->v;
kcd->prev.bmface = NULL;
- kcd->prev.vert = kcd->linehits[kcd->totlinehit - 1].v;
+ }
+
+ if (kcd->is_drag_hold) {
+ lh = &kcd->linehits[kcd->totlinehit - 1];
+ linehit_to_knifepos(&kcd->prev, lh);
}
BLI_ghash_free(facehits, NULL, NULL);
@@ -1055,7 +1169,7 @@ static void knifetool_draw(const bContext *C, ARegion *UNUSED(ar), void *arg)
BLI_mempool_iternew(kcd->kedges, &iter);
for (kfe = BLI_mempool_iterstep(&iter); kfe; kfe = BLI_mempool_iterstep(&iter)) {
- if (!kfe->draw)
+ if (!kfe->is_cut)
continue;
glColor3ubv(kcd->colors.line);
@@ -1077,7 +1191,7 @@ static void knifetool_draw(const bContext *C, ARegion *UNUSED(ar), void *arg)
glBegin(GL_POINTS);
BLI_mempool_iternew(kcd->kverts, &iter);
for (kfv = BLI_mempool_iterstep(&iter); kfv; kfv = BLI_mempool_iterstep(&iter)) {
- if (!kfv->draw)
+ if (!kfv->is_cut)
continue;
glColor3ubv(kcd->colors.point);
@@ -1169,25 +1283,154 @@ static bool knife_ray_intersect_face(
return false;
}
-/* Calculate maximum excursion from (0,0,0) of mesh */
+/**
+ * Calculate the center and maximum excursion of mesh.
+ */
static void calc_ortho_extent(KnifeTool_OpData *kcd)
{
BMIter iter;
BMVert *v;
BMesh *bm = kcd->em->bm;
- float max_xyz = 0.0f;
- int i;
+ float min[3], max[3];
- BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
- for (i = 0; i < 3; i++)
- max_xyz = max_ff(max_xyz, fabsf(v->co[i]));
+ INIT_MINMAX(min, max);
+
+ if (kcd->cagecos) {
+ minmax_v3v3_v3_array(min, max, kcd->cagecos, bm->totvert);
}
- kcd->ortho_extent = max_xyz;
+ else {
+ BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
+ minmax_v3v3_v3(min, max, v->co);
+ }
+ }
+
+ kcd->ortho_extent = len_v3v3(min, max) / 2;
+ mid_v3_v3v3(kcd->ortho_extent_center, min, max);
}
-/* Check if p is visible (not clipped, not occluded by another face).
- * s in screen projection of p. */
-static bool point_is_visible(KnifeTool_OpData *kcd, const float p[3], const float s[2], bglMats *mats)
+static BMElem *bm_elem_from_knife_vert(KnifeVert *kfv, KnifeEdge **r_kfe)
+{
+ BMElem *ele_test;
+ KnifeEdge *kfe = NULL;
+
+ /* vert? */
+ ele_test = (BMElem *)kfv->v;
+
+ if (r_kfe || ele_test == NULL) {
+ if (kfv->v == NULL) {
+ Ref *ref;
+ for (ref = kfv->edges.first; ref; ref = ref->next) {
+ kfe = ref->ref;
+ if (kfe->e) {
+ if (r_kfe) {
+ *r_kfe = kfe;
+ }
+ break;
+ }
+ }
+ }
+ }
+
+ /* edge? */
+ if (ele_test == NULL) {
+ if (kfe) {
+ ele_test = (BMElem *)kfe->e;
+ }
+ }
+
+ /* face? */
+ if (ele_test == NULL) {
+ if (BLI_listbase_is_single(&kfe->faces)) {
+ ele_test = ((Ref *)kfe->faces.first)->ref;
+ }
+ }
+
+ return ele_test;
+}
+
+static BMElem *bm_elem_from_knife_edge(KnifeEdge *kfe)
+{
+ BMElem *ele_test;
+
+ ele_test = (BMElem *)kfe->e;
+
+ if (ele_test == NULL) {
+ ele_test = (BMElem *)kfe->basef;
+ }
+
+ return ele_test;
+}
+
+/* Do edges e1 and e2 go between exactly the same coordinates? */
+static bool coinciding_edges(BMEdge *e1, BMEdge *e2)
+{
+ const float *co11, *co12, *co21, *co22;
+
+ co11 = e1->v1->co;
+ co12 = e1->v2->co;
+ co21 = e2->v1->co;
+ co22 = e2->v2->co;
+ if ((equals_v3v3(co11, co21) && equals_v3v3(co12, co22)) ||
+ (equals_v3v3(co11, co22) && equals_v3v3(co12, co21)))
+ {
+ return true;
+ }
+ else {
+ return false;
+ }
+}
+
+/* Callback used in point_is_visible to exclude hits on the faces that are the same
+ * as or contain the hitting element (which is in user_data).
+ * Also (see T44492) want to exclude hits on faces that butt up to the hitting element
+ * (e.g., when you double an edge by an edge split).
+ */
+static bool bm_ray_cast_cb_elem_not_in_face_check(BMFace *f, void *user_data)
+{
+ bool ans;
+ BMEdge *e, *e2;
+ BMIter iter;
+
+ switch (((BMElem *)user_data)->head.htype) {
+ case BM_FACE:
+ ans = (BMFace *)user_data != f;
+ break;
+ case BM_EDGE:
+ e = (BMEdge *)user_data;
+ ans = !BM_edge_in_face(e, f);
+ if (ans) {
+ /* Is it a boundary edge, coincident with a split edge? */
+ if (BM_edge_is_boundary(e)) {
+ BM_ITER_ELEM(e2, &iter, f, BM_EDGES_OF_FACE) {
+ if (coinciding_edges(e, e2)) {
+ ans = false;
+ break;
+ }
+ }
+ }
+ }
+ break;
+ case BM_VERT:
+ ans = !BM_vert_in_face((BMVert *)user_data, f);
+ break;
+ default:
+ ans = true;
+ break;
+ }
+ return ans;
+}
+
+
+/**
+ * Check if \a p is visible (not clipped, not occluded by another face).
+ * s in screen projection of p.
+ *
+ * \param ele_test Optional vert/edge/face to use when \a p is on the surface of the geometry,
+ * intersecting faces matching this face (or connected when an vert/edge) will be ignored.
+ */
+static bool point_is_visible(
+ KnifeTool_OpData *kcd, const float p[3], const float s[2], bglMats *mats,
+ BMElem *ele_test)
{
BMFace *f_hit;
@@ -1211,7 +1454,7 @@ static bool point_is_visible(KnifeTool_OpData *kcd, const float p[3], const floa
/* make p_ofs a little towards view, so ray doesn't hit p's face. */
sub_v3_v3(view, p);
dist = normalize_v3(view);
- madd_v3_v3v3fl(p_ofs, p, view, KNIFE_FLT_EPSBIG * 3.0f);
+ copy_v3_v3(p_ofs, p);
/* avoid projecting behind the viewpoint */
if (kcd->is_ortho && (kcd->vc.rv3d->persp != RV3D_CAMOB)) {
@@ -1230,9 +1473,19 @@ static bool point_is_visible(KnifeTool_OpData *kcd, const float p[3], const floa
}
/* see if there's a face hit between p1 and the view */
- f_hit = BKE_bmbvh_ray_cast(kcd->bmbvh, p_ofs, view, KNIFE_FLT_EPS, &dist, NULL, NULL);
- if (f_hit)
+ if (ele_test) {
+ f_hit = BKE_bmbvh_ray_cast_filter(
+ kcd->bmbvh, p_ofs, view, KNIFE_FLT_EPS, &dist, NULL, NULL,
+ bm_ray_cast_cb_elem_not_in_face_check, ele_test);
+ }
+ else {
+ f_hit = BKE_bmbvh_ray_cast(
+ kcd->bmbvh, p_ofs, view, KNIFE_FLT_EPS, &dist, NULL, NULL);
+ }
+
+ if (f_hit) {
return false;
+ }
}
return true;
@@ -1240,14 +1493,20 @@ static bool point_is_visible(KnifeTool_OpData *kcd, const float p[3], const floa
/* Clip the line (v1, v2) to planes perpendicular to it and distances d from
* the closest point on the line to the origin */
-static void clip_to_ortho_planes(float v1[3], float v2[3], float d)
+static void clip_to_ortho_planes(float v1[3], float v2[3], const float center[3], const float d)
{
- float closest[3];
- const float origin[3] = {0.0f, 0.0f, 0.0f};
+ float closest[3], dir[3];
+
+ sub_v3_v3v3(dir, v1, v2);
+ normalize_v3(dir);
+
+ /* could be v1 or v2 */
+ sub_v3_v3(v1, center);
+ project_plane_v3_v3v3(closest, v1, dir);
+ add_v3_v3(closest, center);
- closest_to_line_v3(closest, origin, v1, v2);
- dist_ensure_v3_v3fl(v1, closest, d);
- dist_ensure_v3_v3fl(v2, closest, d);
+ madd_v3_v3v3fl(v1, closest, dir, d);
+ madd_v3_v3v3fl(v2, closest, dir, -d);
}
static void set_linehit_depth(KnifeTool_OpData *kcd, KnifeLineHit *lh)
@@ -1274,6 +1533,7 @@ static void knife_find_line_hits(KnifeTool_OpData *kcd)
SmallHashIter hiter;
KnifeLineHit hit;
void *val;
+ void **val_p;
float plane_cos[12];
float s[2], se1[2], se2[2], sint[2];
float r1[3], r2[3];
@@ -1281,10 +1541,11 @@ static void knife_find_line_hits(KnifeTool_OpData *kcd)
float vert_tol, vert_tol_sq;
float line_tol, line_tol_sq;
float face_tol, face_tol_sq;
- float eps_scale;
int isect_kind;
unsigned int tot;
int i;
+ const bool use_hit_prev = true;
+ const bool use_hit_curr = (kcd->is_drag_hold == false);
bgl_get_mats(&mats);
@@ -1329,8 +1590,8 @@ static void knife_find_line_hits(KnifeTool_OpData *kcd)
if (kcd->is_ortho && (kcd->vc.rv3d->persp != RV3D_CAMOB)) {
if (kcd->ortho_extent == 0.0f)
calc_ortho_extent(kcd);
- clip_to_ortho_planes(v1, v3, kcd->ortho_extent + 10.0f);
- clip_to_ortho_planes(v2, v4, kcd->ortho_extent + 10.0f);
+ clip_to_ortho_planes(v1, v3, kcd->ortho_extent_center, kcd->ortho_extent + 10.0f);
+ clip_to_ortho_planes(v2, v4, kcd->ortho_extent_center, kcd->ortho_extent + 10.0f);
}
/* First use bvh tree to find faces, knife edges, and knife verts that might
@@ -1346,7 +1607,7 @@ static void knife_find_line_hits(KnifeTool_OpData *kcd)
BLI_bvhtree_insert(planetree, 0, plane_cos, 4);
BLI_bvhtree_balance(planetree);
- results = BLI_bvhtree_overlap(tree, planetree, &tot);
+ results = BLI_bvhtree_overlap(tree, planetree, &tot, NULL, NULL);
if (!results) {
BLI_bvhtree_free(planetree);
return;
@@ -1360,6 +1621,11 @@ static void knife_find_line_hits(KnifeTool_OpData *kcd)
ls = (BMLoop **)kcd->em->looptris[result->indexA];
f = ls[0]->f;
set_lowest_face_tri(kcd, f, result->indexA);
+
+ /* occlude but never cut unselected faces (when only_select is used) */
+ if (kcd->only_select && !BM_elem_flag_test(f, BM_ELEM_SELECT)) {
+ continue;
+ }
/* for faces, store index of lowest hit looptri in hash */
if (BLI_smallhash_haskey(&faces, (uintptr_t)f)) {
continue;
@@ -1374,27 +1640,18 @@ static void knife_find_line_hits(KnifeTool_OpData *kcd)
continue;
BLI_smallhash_insert(&kfes, (uintptr_t)kfe, kfe);
v = kfe->v1;
- if (!BLI_smallhash_haskey(&kfvs, (uintptr_t)v))
- BLI_smallhash_insert(&kfvs, (uintptr_t)v, v);
+ BLI_smallhash_reinsert(&kfvs, (uintptr_t)v, v);
v = kfe->v2;
- if (!BLI_smallhash_haskey(&kfvs, (uintptr_t)v))
- BLI_smallhash_insert(&kfvs, (uintptr_t)v, v);
+ BLI_smallhash_reinsert(&kfvs, (uintptr_t)v, v);
}
}
/* Now go through the candidates and find intersections */
/* These tolerances, in screen space, are for intermediate hits, as ends are already snapped to screen */
- {
- /* Scale the epsilon by the zoom level
- * to compensate for projection imprecision, see T41164 */
- float zoom_xy[2] = {kcd->vc.rv3d->winmat[0][0],
- kcd->vc.rv3d->winmat[1][1]};
- eps_scale = len_v2(zoom_xy);
- }
- vert_tol = KNIFE_FLT_EPS_PX * eps_scale;
- line_tol = KNIFE_FLT_EPS_PX * eps_scale;
- face_tol = max_ff(vert_tol, line_tol);
+ vert_tol = KNIFE_FLT_EPS_PX_VERT;
+ line_tol = KNIFE_FLT_EPS_PX_EDGE;
+ face_tol = KNIFE_FLT_EPS_PX_FACE;
vert_tol_sq = vert_tol * vert_tol;
line_tol_sq = line_tol * line_tol;
@@ -1403,30 +1660,55 @@ static void knife_find_line_hits(KnifeTool_OpData *kcd)
/* Assume these tolerances swamp floating point rounding errors in calculations below */
/* first look for vertex hits */
- for (val = BLI_smallhash_iternew(&kfvs, &hiter, (uintptr_t *)&v); val;
- val = BLI_smallhash_iternext(&hiter, (uintptr_t *)&v))
+ for (val_p = BLI_smallhash_iternew_p(&kfvs, &hiter, (uintptr_t *)&v); val_p;
+ val_p = BLI_smallhash_iternext_p(&hiter, (uintptr_t *)&v))
{
+ KnifeEdge *kfe_hit = NULL;
+
knife_project_v2(kcd, v->cageco, s);
d = dist_squared_to_line_segment_v2(s, s1, s2);
- if (d <= vert_tol_sq) {
- if (point_is_visible(kcd, v->cageco, s, &mats)) {
- memset(&hit, 0, sizeof(hit));
- hit.v = v;
- copy_v3_v3(hit.hit, v->co);
- copy_v3_v3(hit.cagehit, v->cageco);
- copy_v2_v2(hit.schit, s);
- set_linehit_depth(kcd, &hit);
- BLI_array_append(linehits, hit);
+ if ((d <= vert_tol_sq) &&
+ (point_is_visible(kcd, v->cageco, s, &mats, bm_elem_from_knife_vert(v, &kfe_hit))))
+ {
+ memset(&hit, 0, sizeof(hit));
+ hit.v = v;
+
+ /* If this isn't from an existing BMVert, it may have been added to a BMEdge originally.
+ * knowing if the hit comes from an edge is important for edge-in-face checks later on
+ * see: #knife_add_single_cut -> #knife_verts_edge_in_face, T42611 */
+ if (kfe_hit) {
+ hit.kfe = kfe_hit;
}
+
+ copy_v3_v3(hit.hit, v->co);
+ copy_v3_v3(hit.cagehit, v->cageco);
+ copy_v2_v2(hit.schit, s);
+ set_linehit_depth(kcd, &hit);
+ BLI_array_append(linehits, hit);
+ }
+ else {
+ /* note that these vertes aren't used */
+ *val_p = NULL;
}
}
+
/* now edge hits; don't add if a vertex at end of edge should have hit */
for (val = BLI_smallhash_iternew(&kfes, &hiter, (uintptr_t *)&kfe); val;
val = BLI_smallhash_iternext(&hiter, (uintptr_t *)&kfe))
{
+ int kfe_verts_in_cut;
+ /* if we intersect both verts, don't attempt to intersect the edge */
+
+ kfe_verts_in_cut = (BLI_smallhash_lookup(&kfvs, (intptr_t)kfe->v1) != NULL) +
+ (BLI_smallhash_lookup(&kfvs, (intptr_t)kfe->v2) != NULL);
+
+ if (kfe_verts_in_cut == 2) {
+ continue;
+ }
+
knife_project_v2(kcd, kfe->v1->cageco, se1);
knife_project_v2(kcd, kfe->v2->cageco, se2);
- isect_kind = isect_seg_seg_v2_point(s1, s2, se1, se2, sint);
+ isect_kind = (kfe_verts_in_cut) ? -1 : isect_seg_seg_v2_point(s1, s2, se1, se2, sint);
if (isect_kind == -1) {
/* isect_seg_seg_v2 doesn't do tolerance test around ends of s1-s2 */
closest_to_line_segment_v2(sint, s1, se1, se2);
@@ -1449,7 +1731,7 @@ static void knife_find_line_hits(KnifeTool_OpData *kcd)
* Need to find 3d intersection of ray through sint */
knife_input_ray_segment(kcd, sint, 1.0f, r1, r2);
isect_kind = isect_line_line_v3(kfe->v1->cageco, kfe->v2->cageco, r1, r2, p_cage, p_cage_tmp);
- if (isect_kind >= 1 && point_is_visible(kcd, p_cage, sint, &mats)) {
+ if (isect_kind >= 1 && point_is_visible(kcd, p_cage, sint, &mats, bm_elem_from_knife_edge(kfe))) {
memset(&hit, 0, sizeof(hit));
if (kcd->snap_midpoints) {
/* choose intermediate point snap too */
@@ -1477,8 +1759,8 @@ static void knife_find_line_hits(KnifeTool_OpData *kcd)
{
float p[3], p_cage[3];
- if (knife_ray_intersect_face(kcd, s1, v1, v3, f, face_tol_sq, p, p_cage)) {
- if (point_is_visible(kcd, p_cage, s1, &mats)) {
+ if (use_hit_prev && knife_ray_intersect_face(kcd, s1, v1, v3, f, face_tol_sq, p, p_cage)) {
+ if (point_is_visible(kcd, p_cage, s1, &mats, (BMElem *)f)) {
memset(&hit, 0, sizeof(hit));
hit.f = f;
copy_v3_v3(hit.hit, p);
@@ -1488,8 +1770,9 @@ static void knife_find_line_hits(KnifeTool_OpData *kcd)
BLI_array_append(linehits, hit);
}
}
- if (knife_ray_intersect_face(kcd, s2, v2, v4, f, face_tol_sq, p, p_cage)) {
- if (point_is_visible(kcd, p_cage, s2, &mats)) {
+
+ if (use_hit_curr && knife_ray_intersect_face(kcd, s2, v2, v4, f, face_tol_sq, p, p_cage)) {
+ if (point_is_visible(kcd, p_cage, s2, &mats, (BMElem *)f)) {
memset(&hit, 0, sizeof(hit));
hit.f = f;
copy_v3_v3(hit.hit, p);
@@ -1543,13 +1826,18 @@ static BMFace *knife_find_closest_face(KnifeTool_OpData *kcd, float co[3], float
float dist = KMAXDIST;
float origin[3];
float origin_ofs[3];
- float ray[3];
+ float ray[3], ray_normal[3];
/* unproject to find view ray */
knife_input_ray_segment(kcd, kcd->curr.mval, 1.0f, origin, origin_ofs);
sub_v3_v3v3(ray, origin_ofs, origin);
+ normalize_v3_v3(ray_normal, ray);
- f = BKE_bmbvh_ray_cast(kcd->bmbvh, origin, ray, 0.0f, NULL, co, cageco);
+ f = BKE_bmbvh_ray_cast(kcd->bmbvh, origin, ray_normal, 0.0f, NULL, co, cageco);
+
+ if (f && kcd->only_select && BM_elem_flag_test(f, BM_ELEM_SELECT) == 0) {
+ f = NULL;
+ }
if (is_space)
*is_space = !f;
@@ -1913,7 +2201,10 @@ static int knife_update_active(KnifeTool_OpData *kcd)
kcd->curr.vert = knife_find_closest_vert(kcd, kcd->curr.co, kcd->curr.cage, &kcd->curr.bmface, &kcd->curr.is_space);
- if (!kcd->curr.vert) {
+ if (!kcd->curr.vert &&
+ /* no edge snapping while dragging (edges are too sticky when cuts are immediate) */
+ !kcd->is_drag_hold)
+ {
kcd->curr.edge = knife_find_closest_edge(kcd, kcd->curr.co, kcd->curr.cage,
&kcd->curr.bmface, &kcd->curr.is_space);
}
@@ -1942,34 +2233,17 @@ static int knife_update_active(KnifeTool_OpData *kcd)
return 1;
}
-/* sort list of kverts by fraction along edge e */
-static void sort_by_frac_along(ListBase *lst, BMEdge *e)
+static int sort_verts_by_dist_cb(void *co_p, const void *cur_a_p, const void *cur_b_p)
{
- /* note, since we know the point is along the edge, sort from distance to v1co */
- const float *v1co = e->v1->co;
- Ref *cur = NULL, *prev = NULL, *next = NULL;
-
- if (lst->first == lst->last)
- return;
+ const KnifeVert *cur_a = ((const Ref *)cur_a_p)->ref;
+ const KnifeVert *cur_b = ((const Ref *)cur_b_p)->ref;
+ const float *co = co_p;
+ const float a_sq = len_squared_v3v3(co, cur_a->co);
+ const float b_sq = len_squared_v3v3(co, cur_b->co);
- for (cur = ((Ref *)lst->first)->next; cur; cur = next) {
- KnifeVert *vcur = cur->ref;
- const float vcur_fac_sq = len_squared_v3v3(v1co, vcur->co);
-
- next = cur->next;
- prev = cur->prev;
-
- BLI_remlink(lst, cur);
-
- while (prev) {
- KnifeVert *vprev = prev->ref;
- if (len_squared_v3v3(v1co, vprev->co) <= vcur_fac_sq)
- break;
- prev = prev->prev;
- }
-
- BLI_insertlinkafter(lst, prev, cur);
- }
+ if (a_sq < b_sq) return -1;
+ else if (a_sq > b_sq) return 1;
+ else return 0;
}
/* The chain so far goes from an instantiated vertex to kfv (some may be reversed).
@@ -2063,7 +2337,7 @@ static ListBase *find_chain(KnifeTool_OpData *kcd, ListBase *fedges)
break;
}
if (ans) {
- BLI_assert(BLI_countlist(ans) > 0);
+ BLI_assert(!BLI_listbase_is_empty(ans));
for (r = ans->first; r; r = r->next) {
ref = find_ref(fedges, r->ref);
BLI_assert(ref != NULL);
@@ -2157,7 +2431,7 @@ static ListBase *find_hole(KnifeTool_OpData *kcd, ListBase *fedges)
static bool find_hole_chains(KnifeTool_OpData *kcd, ListBase *hole, BMFace *f, ListBase **mainchain,
ListBase **sidechain)
{
- float **fco, **hco;
+ float (*fco)[2], (*hco)[2];
BMVert **fv;
KnifeVert **hv;
KnifeEdge **he;
@@ -2171,7 +2445,7 @@ static bool find_hole_chains(KnifeTool_OpData *kcd, ListBase *hole, BMFace *f, L
int besti[2], bestj[2];
float dist_sq, dist_best_sq;
- nh = BLI_countlist(hole);
+ nh = BLI_listbase_count(hole);
nf = f->len;
if (nh < 2 || nf < 3)
return false;
@@ -2179,8 +2453,8 @@ static bool find_hole_chains(KnifeTool_OpData *kcd, ListBase *hole, BMFace *f, L
/* Gather 2d projections of hole and face vertex coordinates.
* Use best-axis projection - not completely accurate, maybe revisit */
axis_dominant_v3(&ax, &ay, f->no);
- hco = BLI_memarena_alloc(kcd->arena, nh * sizeof(float *));
- fco = BLI_memarena_alloc(kcd->arena, nf * sizeof(float *));
+ hco = BLI_memarena_alloc(kcd->arena, nh * sizeof(float[2]));
+ fco = BLI_memarena_alloc(kcd->arena, nf * sizeof(float[2]));
hv = BLI_memarena_alloc(kcd->arena, nh * sizeof(KnifeVert *));
fv = BLI_memarena_alloc(kcd->arena, nf * sizeof(BMVert *));
he = BLI_memarena_alloc(kcd->arena, nh * sizeof(KnifeEdge *));
@@ -2198,7 +2472,6 @@ static bool find_hole_chains(KnifeTool_OpData *kcd, ListBase *hole, BMFace *f, L
kfv = kfvother;
BLI_assert(kfv == kfe->v1 || kfv == kfe->v2);
}
- hco[i] = BLI_memarena_alloc(kcd->arena, 2 * sizeof(float));
hco[i][0] = kfv->co[ax];
hco[i][1] = kfv->co[ay];
hv[i] = kfv;
@@ -2208,7 +2481,6 @@ static bool find_hole_chains(KnifeTool_OpData *kcd, ListBase *hole, BMFace *f, L
j = 0;
BM_ITER_ELEM (v, &iter, f, BM_VERTS_OF_FACE) {
- fco[j] = BLI_memarena_alloc(kcd->arena, 2 * sizeof(float));
fco[j][0] = v->co[ax];
fco[j][1] = v->co[ay];
fv[j] = v;
@@ -2302,13 +2574,22 @@ static bool knife_verts_edge_in_face(KnifeVert *v1, KnifeVert *v2, BMFace *f)
{
bool v1_inside, v2_inside;
bool v1_inface, v2_inface;
+ BMLoop *l1, *l2;
if (!f || !v1 || !v2)
return false;
+ l1 = v1->v ? BM_face_vert_share_loop(f, v1->v) : NULL;
+ l2 = v2->v ? BM_face_vert_share_loop(f, v2->v) : NULL;
+
+ if ((l1 && l2) && BM_loop_is_adjacent(l1, l2)) {
+ /* boundary-case, always false to avoid edge-in-face checks below */
+ return false;
+ }
+
/* find out if v1 and v2, if set, are part of the face */
- v1_inface = v1->v ? BM_vert_in_face(f, v1->v) : false;
- v2_inface = v2->v ? BM_vert_in_face(f, v2->v) : false;
+ v1_inface = (l1 != NULL);
+ v2_inface = (l2 != NULL);
/* BM_face_point_inside_test uses best-axis projection so this isn't most accurate test... */
v1_inside = v1_inface ? false : BM_face_point_inside_test(f, v1->co);
@@ -2350,7 +2631,7 @@ static void knife_make_chain_cut(KnifeTool_OpData *kcd, BMFace *f, ListBase *cha
KnifeVert *kfv, *kfvprev;
BMLoop *l_new, *l_iter;
int i;
- int nco = BLI_countlist(chain) - 1;
+ int nco = BLI_listbase_count(chain) - 1;
float (*cos)[3] = BLI_array_alloca(cos, nco);
KnifeVert **kverts = BLI_array_alloca(kverts, nco);
@@ -2423,7 +2704,7 @@ static void knife_make_face_cuts(KnifeTool_OpData *kcd, BMFace *f, ListBase *kfe
Ref *ref, *refnext;
int count, oldcount;
- oldcount = BLI_countlist(kfedges);
+ oldcount = BLI_listbase_count(kfedges);
while ((chain = find_chain(kcd, kfedges)) != NULL) {
ListBase fnew_kfedges;
knife_make_chain_cut(kcd, f, chain, &fnew);
@@ -2452,7 +2733,7 @@ static void knife_make_face_cuts(KnifeTool_OpData *kcd, BMFace *f, ListBase *kfe
/* find_chain should always remove edges if it returns true,
* but guard against infinite loop anyway */
- count = BLI_countlist(kfedges);
+ count = BLI_listbase_count(kfedges);
if (count >= oldcount) {
BLI_assert(!"knife find_chain infinite loop");
return;
@@ -2520,7 +2801,7 @@ static void knife_make_face_cuts(KnifeTool_OpData *kcd, BMFace *f, ListBase *kfe
break;
/* find_hole should always remove edges if it returns true,
* but guard against infinite loop anyway */
- count = BLI_countlist(kfedges);
+ count = BLI_listbase_count(kfedges);
if (count >= oldcount) {
BLI_assert(!"knife find_hole infinite loop");
return;
@@ -2552,6 +2833,14 @@ static void knife_make_cuts(KnifeTool_OpData *kcd)
/* put list of cutting edges for a face into fhash, keyed by face */
BLI_mempool_iternew(kcd->kedges, &iter);
for (kfe = BLI_mempool_iterstep(&iter); kfe; kfe = BLI_mempool_iterstep(&iter)) {
+
+ /* select edges that lie directly on the cut */
+ if (kcd->select_result) {
+ if (kfe->e && kfe->is_cut) {
+ BM_edge_select_set(bm, kfe->e, true);
+ }
+ }
+
f = kfe->basef;
if (!f || kfe->e)
continue;
@@ -2588,7 +2877,8 @@ static void knife_make_cuts(KnifeTool_OpData *kcd)
for (lst = BLI_smallhash_iternew(ehash, &hiter, (uintptr_t *)&e); lst;
lst = BLI_smallhash_iternext(&hiter, (uintptr_t *)&e))
{
- sort_by_frac_along(lst, e);
+ BLI_listbase_sort_r(lst, sort_verts_by_dist_cb, e->v1->co);
+
for (ref = lst->first; ref; ref = ref->next) {
kfv = ref->ref;
pct = line_point_factor_v3(kfv->co, e->v1->co, e->v2->co);
@@ -2619,6 +2909,9 @@ static void knifetool_finish_ex(KnifeTool_OpData *kcd)
EDBM_selectmode_flush(kcd->em);
EDBM_mesh_normals_update(kcd->em);
EDBM_update_generic(kcd->em, true, true);
+
+ /* re-tessellating makes this invalid, dont use again by accident */
+ knifetool_free_bmbvh(kcd);
}
static void knifetool_finish(wmOperator *op)
{
@@ -2632,8 +2925,7 @@ static void knife_recalc_projmat(KnifeTool_OpData *kcd)
ED_view3d_ob_project_mat_get(kcd->ar->regiondata, kcd->ob, kcd->projmat);
invert_m4_m4(kcd->projmat_inv, kcd->projmat);
- copy_v3_v3(kcd->proj_zaxis, kcd->vc.rv3d->viewinv[2]);
- mul_mat3_m4_v3(kcd->ob->imat, kcd->proj_zaxis);
+ mul_v3_mat3_m4v3(kcd->proj_zaxis, kcd->ob->imat, kcd->vc.rv3d->viewinv[2]);
normalize_v3(kcd->proj_zaxis);
kcd->is_ortho = ED_view3d_clip_range_get(kcd->vc.v3d, kcd->vc.rv3d,
@@ -2663,14 +2955,12 @@ static void knifetool_exit_ex(bContext *C, KnifeTool_OpData *kcd)
BLI_ghash_free(kcd->kedgefacemap, NULL, NULL);
BLI_ghash_free(kcd->facetrimap, NULL, NULL);
- BKE_bmbvh_free(kcd->bmbvh);
BLI_memarena_free(kcd->arena);
/* tag for redraw */
ED_region_tag_redraw(kcd->ar);
- if (kcd->cagecos)
- MEM_freeN((void *)kcd->cagecos);
+ knifetool_free_bmbvh(kcd);
if (kcd->linehits)
MEM_freeN(kcd->linehits);
@@ -2701,6 +2991,32 @@ static void knifetool_update_mval_i(KnifeTool_OpData *kcd, const int mval_i[2])
knifetool_update_mval(kcd, mval);
}
+static void knifetool_init_bmbvh(KnifeTool_OpData *kcd)
+{
+ BM_mesh_elem_index_ensure(kcd->em->bm, BM_VERT);
+
+ kcd->cagecos = (const float (*)[3])BKE_editmesh_vertexCos_get(kcd->em, kcd->scene, NULL);
+
+ kcd->bmbvh = BKE_bmbvh_new_from_editmesh(
+ kcd->em,
+ BMBVH_RETURN_ORIG |
+ ((kcd->only_select && kcd->cut_through) ? BMBVH_RESPECT_SELECT : BMBVH_RESPECT_HIDDEN),
+ kcd->cagecos, false);
+}
+
+static void knifetool_free_bmbvh(KnifeTool_OpData *kcd)
+{
+ if (kcd->bmbvh) {
+ BKE_bmbvh_free(kcd->bmbvh);
+ kcd->bmbvh = NULL;
+ }
+
+ if (kcd->cagecos) {
+ MEM_freeN((void *)kcd->cagecos);
+ kcd->cagecos = NULL;
+ }
+}
+
/* called when modal loop selection gets set up... */
static void knifetool_init(bContext *C, KnifeTool_OpData *kcd,
const bool only_select, const bool cut_through, const bool is_interactive)
@@ -2709,6 +3025,7 @@ static void knifetool_init(bContext *C, KnifeTool_OpData *kcd,
Object *obedit = CTX_data_edit_object(C);
/* assign the drawing handle for drawing preview line... */
+ kcd->scene = scene;
kcd->ob = obedit;
kcd->ar = CTX_wm_region(C);
@@ -2716,14 +3033,12 @@ static void knifetool_init(bContext *C, KnifeTool_OpData *kcd,
kcd->em = BKE_editmesh_from_object(kcd->ob);
- BM_mesh_elem_index_ensure(kcd->em->bm, BM_VERT);
-
- kcd->cagecos = (const float (*)[3])BKE_editmesh_vertexCos_get(kcd->em, scene, NULL);
+ /* cut all the way through the mesh if use_occlude_geometry button not pushed */
+ kcd->is_interactive = is_interactive;
+ kcd->cut_through = cut_through;
+ kcd->only_select = only_select;
- kcd->bmbvh = BKE_bmbvh_new_from_editmesh(kcd->em,
- BMBVH_RETURN_ORIG |
- (only_select ? BMBVH_RESPECT_SELECT : BMBVH_RESPECT_HIDDEN),
- kcd->cagecos, false);
+ knifetool_init_bmbvh(kcd);
kcd->arena = BLI_memarena_new(MEM_SIZE_OPTIMAL(1 << 15), "knife");
kcd->vthresh = KMAXDIST - 1;
@@ -2742,11 +3057,6 @@ static void knifetool_init(bContext *C, KnifeTool_OpData *kcd,
kcd->kedgefacemap = BLI_ghash_ptr_new("knife kedgefacemap");
kcd->facetrimap = BLI_ghash_ptr_new("knife facetrimap");
- /* cut all the way through the mesh if use_occlude_geometry button not pushed */
- kcd->is_interactive = is_interactive;
- kcd->cut_through = cut_through;
- kcd->only_select = only_select;
-
/* can't usefully select resulting edges in face mode */
kcd->select_result = (kcd->em->selectmode != SCE_SELECT_FACE);
@@ -2789,31 +3099,19 @@ static int knifetool_invoke(bContext *C, wmOperator *op, const wmEvent *event)
knifetool_init(C, kcd, only_select, cut_through, true);
+ op->flag |= OP_IS_MODAL_CURSOR_REGION;
+
/* add a modal handler for this operator - handles loop selection */
WM_cursor_modal_set(CTX_wm_window(C), BC_KNIFECURSOR);
WM_event_add_modal_handler(C, op);
knifetool_update_mval_i(kcd, event->mval);
- knife_update_header(C, kcd);
+ knife_update_header(C, op, kcd);
return OPERATOR_RUNNING_MODAL;
}
-enum {
- KNF_MODAL_CANCEL = 1,
- KNF_MODAL_CONFIRM,
- KNF_MODAL_MIDPOINT_ON,
- KNF_MODAL_MIDPOINT_OFF,
- KNF_MODAL_NEW_CUT,
- KNF_MODEL_IGNORE_SNAP_ON,
- KNF_MODEL_IGNORE_SNAP_OFF,
- KNF_MODAL_ADD_CUT,
- KNF_MODAL_ANGLE_SNAP_TOGGLE,
- KNF_MODAL_CUT_THROUGH_TOGGLE,
- KNF_MODAL_PANNING
-};
-
wmKeyMap *knifetool_modal_keymap(wmKeyConfig *keyconf)
{
static EnumPropertyItem modal_items[] = {
@@ -2842,7 +3140,8 @@ wmKeyMap *knifetool_modal_keymap(wmKeyConfig *keyconf)
/* items for modal map */
WM_modalkeymap_add_item(keymap, ESCKEY, KM_PRESS, KM_ANY, 0, KNF_MODAL_CANCEL);
WM_modalkeymap_add_item(keymap, MIDDLEMOUSE, KM_ANY, KM_ANY, 0, KNF_MODAL_PANNING);
- WM_modalkeymap_add_item(keymap, LEFTMOUSE, KM_PRESS, KM_ANY, 0, KNF_MODAL_ADD_CUT);
+ WM_modalkeymap_add_item(keymap, LEFTMOUSE, KM_DBL_CLICK, KM_ANY, 0, KNF_MODAL_ADD_CUT_CLOSED);
+ WM_modalkeymap_add_item(keymap, LEFTMOUSE, KM_ANY, KM_ANY, 0, KNF_MODAL_ADD_CUT);
WM_modalkeymap_add_item(keymap, RIGHTMOUSE, KM_PRESS, KM_ANY, 0, KNF_MODAL_CANCEL);
WM_modalkeymap_add_item(keymap, RETKEY, KM_PRESS, KM_ANY, 0, KNF_MODAL_CONFIRM);
WM_modalkeymap_add_item(keymap, PADENTER, KM_PRESS, KM_ANY, 0, KNF_MODAL_CONFIRM);
@@ -2879,6 +3178,9 @@ static int knifetool_modal(bContext *C, wmOperator *op, const wmEvent *event)
return OPERATOR_FINISHED;
}
+ em_setup_viewcontext(C, &kcd->vc);
+ kcd->ar = kcd->vc.ar;
+
view3d_operator_needs_opengl(C);
ED_view3d_init_mats_rv3d(obedit, kcd->vc.rv3d); /* needed to initialize clipping */
@@ -2910,7 +3212,7 @@ static int knifetool_modal(bContext *C, wmOperator *op, const wmEvent *event)
knife_recalc_projmat(kcd);
knife_update_active(kcd);
- knife_update_header(C, kcd);
+ knife_update_header(C, op, kcd);
ED_region_tag_redraw(kcd->ar);
do_refresh = true;
break;
@@ -2919,30 +3221,30 @@ static int knifetool_modal(bContext *C, wmOperator *op, const wmEvent *event)
knife_recalc_projmat(kcd);
knife_update_active(kcd);
- knife_update_header(C, kcd);
+ knife_update_header(C, op, kcd);
ED_region_tag_redraw(kcd->ar);
do_refresh = true;
break;
case KNF_MODEL_IGNORE_SNAP_ON:
ED_region_tag_redraw(kcd->ar);
kcd->ignore_vert_snapping = kcd->ignore_edge_snapping = true;
- knife_update_header(C, kcd);
+ knife_update_header(C, op, kcd);
do_refresh = true;
break;
case KNF_MODEL_IGNORE_SNAP_OFF:
ED_region_tag_redraw(kcd->ar);
kcd->ignore_vert_snapping = kcd->ignore_edge_snapping = false;
- knife_update_header(C, kcd);
+ knife_update_header(C, op, kcd);
do_refresh = true;
break;
case KNF_MODAL_ANGLE_SNAP_TOGGLE:
kcd->angle_snapping = !kcd->angle_snapping;
- knife_update_header(C, kcd);
+ knife_update_header(C, op, kcd);
do_refresh = true;
break;
case KNF_MODAL_CUT_THROUGH_TOGGLE:
kcd->cut_through = !kcd->cut_through;
- knife_update_header(C, kcd);
+ knife_update_header(C, op, kcd);
do_refresh = true;
break;
case KNF_MODAL_NEW_CUT:
@@ -2953,16 +3255,53 @@ static int knifetool_modal(bContext *C, wmOperator *op, const wmEvent *event)
case KNF_MODAL_ADD_CUT:
knife_recalc_projmat(kcd);
- if (kcd->mode == MODE_DRAGGING) {
- knife_add_cut(kcd);
+ /* get the value of the event which triggered this one */
+ if (event->prevval != KM_RELEASE) {
+ if (kcd->mode == MODE_DRAGGING) {
+ knife_add_cut(kcd);
+ }
+ else if (kcd->mode != MODE_PANNING) {
+ knife_start_cut(kcd);
+ kcd->mode = MODE_DRAGGING;
+ kcd->init = kcd->curr;
+ }
+
+ /* freehand drawing is incompatible with cut-through */
+ if (kcd->cut_through == false) {
+ kcd->is_drag_hold = true;
+ }
}
- else if (kcd->mode != MODE_PANNING) {
- knife_start_cut(kcd);
- kcd->mode = MODE_DRAGGING;
+ else {
+ kcd->is_drag_hold = false;
+
+ /* needed because the last face 'hit' is ignored when dragging */
+ knifetool_update_mval(kcd, kcd->curr.mval);
}
ED_region_tag_redraw(kcd->ar);
break;
+ case KNF_MODAL_ADD_CUT_CLOSED:
+ if (kcd->mode == MODE_DRAGGING) {
+
+ /* shouldn't be possible with default key-layout, just incase... */
+ if (kcd->is_drag_hold) {
+ kcd->is_drag_hold = false;
+ knifetool_update_mval(kcd, kcd->curr.mval);
+ }
+
+ kcd->prev = kcd->curr;
+ kcd->curr = kcd->init;
+
+ knife_project_v2(kcd, kcd->curr.cage, kcd->curr.mval);
+ knifetool_update_mval(kcd, kcd->curr.mval);
+
+ knife_add_cut(kcd);
+
+ /* KNF_MODAL_NEW_CUT */
+ knife_finish_cut(kcd);
+ kcd->mode = MODE_IDLE;
+ }
+ break;
case KNF_MODAL_PANNING:
if (event->val != KM_RELEASE) {
if (kcd->mode != MODE_PANNING) {
@@ -2989,12 +3328,25 @@ static int knifetool_modal(bContext *C, wmOperator *op, const wmEvent *event)
case MOUSEMOVE: /* mouse moved somewhere to select another loop */
if (kcd->mode != MODE_PANNING) {
knifetool_update_mval_i(kcd, event->mval);
+
+ if (kcd->is_drag_hold) {
+ if (kcd->totlinehit >= 2) {
+ knife_add_cut(kcd);
+ }
+ }
}
break;
}
}
+ if (kcd->mode == MODE_DRAGGING) {
+ op->flag &= ~OP_IS_MODAL_CURSOR_REGION;
+ }
+ else {
+ op->flag |= OP_IS_MODAL_CURSOR_REGION;
+ }
+
if (do_refresh) {
/* we don't really need to update mval,
* but this happens to be the best way to refresh at the moment */
@@ -3036,16 +3388,14 @@ void MESH_OT_knife_tool(wmOperatorType *ot)
* tessellation here seems way overkill,
* but without this its very hard to know of a point is inside the face
*/
-static void edvm_mesh_knife_face_point(BMFace *f, float r_cent[3])
+static void edbm_mesh_knife_face_point(BMFace *f, float r_cent[3])
{
const int tottri = f->len - 2;
BMLoop **loops = BLI_array_alloca(loops, f->len);
unsigned int (*index)[3] = BLI_array_alloca(index, tottri);
int j;
-
- const float *best_co[3] = {NULL};
- float best_area = -1.0f;
- bool ok = false;
+ int j_best = 0; /* use as fallback when unset */
+ float area_best = -1.0f;
BM_face_calc_tessellation(f, loops, index);
@@ -3055,52 +3405,35 @@ static void edvm_mesh_knife_face_point(BMFace *f, float r_cent[3])
const float *p3 = loops[index[j][2]]->v->co;
float area;
- float cross[3];
- cross_v3_v3v3(cross, p2, p3);
- area = fabsf(dot_v3v3(p1, cross));
- if (area > best_area) {
- best_co[0] = p1;
- best_co[1] = p2;
- best_co[2] = p3;
- best_area = area;
- ok = true;
+ area = area_squared_tri_v3(p1, p2, p3);
+ if (area > area_best) {
+ j_best = j;
+ area_best = area;
}
}
- if (ok) {
- mid_v3_v3v3v3(r_cent, best_co[0], best_co[1], best_co[2]);
- }
- else {
- mid_v3_v3v3v3(r_cent, loops[0]->v->co, loops[1]->v->co, loops[2]->v->co);
- }
+ mid_v3_v3v3v3(
+ r_cent,
+ loops[index[j_best][0]]->v->co,
+ loops[index[j_best][1]]->v->co,
+ loops[index[j_best][2]]->v->co);
}
-static bool edbm_mesh_knife_face_isect(ARegion *ar, LinkNode *polys, BMFace *f, float projmat[4][4])
+static bool edbm_mesh_knife_point_isect(LinkNode *polys, const float cent_ss[2])
{
- float cent_ss[2];
- float cent[3];
-
- edvm_mesh_knife_face_point(f, cent);
-
- ED_view3d_project_float_v2_m4(ar, cent, cent_ss, projmat);
-
- /* check */
- {
- LinkNode *p = polys;
- int isect = 0;
+ LinkNode *p = polys;
+ int isect = 0;
- while (p) {
- const float (*mval_fl)[2] = p->link;
- const int mval_tot = MEM_allocN_len(mval_fl) / sizeof(*mval_fl);
- isect += (int)isect_point_poly_v2(cent_ss, mval_fl, mval_tot - 1, false);
- p = p->next;
- }
-
- if (isect % 2) {
- return true;
- }
+ while (p) {
+ const float (*mval_fl)[2] = p->link;
+ const int mval_tot = MEM_allocN_len(mval_fl) / sizeof(*mval_fl);
+ isect += (int)isect_point_poly_v2(cent_ss, mval_fl, mval_tot - 1, false);
+ p = p->next;
}
+ if (isect % 2) {
+ return true;
+ }
return false;
}
@@ -3110,6 +3443,7 @@ static bool edbm_mesh_knife_face_isect(ARegion *ar, LinkNode *polys, BMFace *f,
void EDBM_mesh_knife(bContext *C, LinkNode *polys, bool use_tag, bool cut_through)
{
KnifeTool_OpData *kcd;
+ bglMats mats;
view3d_operator_needs_opengl(C);
@@ -3128,6 +3462,10 @@ void EDBM_mesh_knife(bContext *C, LinkNode *polys, bool use_tag, bool cut_throug
if (use_tag) {
BM_mesh_elem_hflag_enable_all(kcd->em->bm, BM_EDGE, BM_ELEM_TAG, false);
}
+
+ if (kcd->cut_through == false) {
+ bgl_get_mats(&mats);
+ }
}
/* execute */
@@ -3171,6 +3509,11 @@ void EDBM_mesh_knife(bContext *C, LinkNode *polys, bool use_tag, bool cut_throug
bool keep_search;
+ /* freed on knifetool_finish_ex, but we need again to check if points are visible */
+ if (kcd->cut_through == false) {
+ knifetool_init_bmbvh(kcd);
+ }
+
ED_view3d_ob_project_mat_get(kcd->ar->regiondata, kcd->ob, projmat);
/* use face-loop tag to store if we have intersected */
@@ -3192,7 +3535,10 @@ void EDBM_mesh_knife(bContext *C, LinkNode *polys, bool use_tag, bool cut_throug
BMFace *f;
BMIter fiter;
BM_ITER_ELEM (f, &fiter, e, BM_FACES_OF_EDGE) {
- if (edbm_mesh_knife_face_isect(kcd->ar, polys, f, projmat)) {
+ float cent[3], cent_ss[2];
+ edbm_mesh_knife_face_point(f, cent);
+ knife_project_v2(kcd, cent, cent_ss);
+ if (edbm_mesh_knife_point_isect(polys, cent_ss)) {
BM_elem_flag_enable(f, BM_ELEM_TAG);
}
}
@@ -3225,7 +3571,12 @@ void EDBM_mesh_knife(bContext *C, LinkNode *polys, bool use_tag, bool cut_throug
} while ((l_iter = l_iter->next) != l_first && (found == false));
if (found) {
- if (edbm_mesh_knife_face_isect(kcd->ar, polys, f, projmat)) {
+ float cent[3], cent_ss[2];
+ edbm_mesh_knife_face_point(f, cent);
+ knife_project_v2(kcd, cent, cent_ss);
+ if ((kcd->cut_through || point_is_visible(kcd, cent, cent_ss, &mats, (BMElem *)f)) &&
+ edbm_mesh_knife_point_isect(polys, cent_ss))
+ {
BM_elem_flag_enable(f, BM_ELEM_TAG);
keep_search = true;
}
diff --git a/source/blender/editors/mesh/editmesh_knife_project.c b/source/blender/editors/mesh/editmesh_knife_project.c
index 553c1faa36a..0d3cc07589b 100644
--- a/source/blender/editors/mesh/editmesh_knife_project.c
+++ b/source/blender/editors/mesh/editmesh_knife_project.c
@@ -166,7 +166,7 @@ void MESH_OT_knife_project(wmOperatorType *ot)
/* callbacks */
ot->exec = knifeproject_exec;
- ot->poll = ED_operator_editmesh_view3d;
+ ot->poll = ED_operator_editmesh_region_view3d;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING;
diff --git a/source/blender/editors/mesh/editmesh_loopcut.c b/source/blender/editors/mesh/editmesh_loopcut.c
index 12be32b764e..c612ebfcc24 100644
--- a/source/blender/editors/mesh/editmesh_loopcut.c
+++ b/source/blender/editors/mesh/editmesh_loopcut.c
@@ -32,11 +32,11 @@
#include "MEM_guardedalloc.h"
-#include "BLI_array.h"
+#include "BLI_stack.h"
#include "BLI_string.h"
#include "BLI_math.h"
-#include "BLF_translation.h"
+#include "BLT_translation.h"
#include "BKE_context.h"
#include "BKE_modifier.h"
@@ -224,7 +224,8 @@ static void edgering_preview_calc_edges(RingSelOpData *lcd, DerivedMesh *dm, con
BMEdge *eed, *eed_last;
BMVert *v[2][2] = {{NULL}}, *v_last;
float (*edges)[2][3] = NULL;
- BLI_array_declare(edges);
+ BLI_Stack *edge_stack;
+
int i, tot = 0;
BMW_init(&walker, bm, BMW_EDGERING,
@@ -232,10 +233,27 @@ static void edgering_preview_calc_edges(RingSelOpData *lcd, DerivedMesh *dm, con
BMW_FLAG_TEST_HIDDEN,
BMW_NIL_LAY);
+
+ edge_stack = BLI_stack_new(sizeof(BMEdge *), __func__);
+
+ eed_last = NULL;
+ for (eed = eed_last = BMW_begin(&walker, lcd->eed); eed; eed = BMW_step(&walker)) {
+ BLI_stack_push(edge_stack, &eed);
+ }
+ BMW_end(&walker);
+
+
+ eed_start = *(BMEdge **)BLI_stack_peek(edge_stack);
+
+ edges = MEM_mallocN(
+ (sizeof(*edges) * (BLI_stack_count(edge_stack) + (eed_last != eed_start))) * previewlines, __func__);
+
v_last = NULL;
eed_last = NULL;
- for (eed = eed_start = BMW_begin(&walker, eed_start); eed; eed = BMW_step(&walker)) {
+ while (!BLI_stack_is_empty(edge_stack)) {
+ BLI_stack_pop(edge_stack, &eed);
+
if (eed_last) {
if (v_last) {
v[1][0] = v[0][0];
@@ -250,8 +268,6 @@ static void edgering_preview_calc_edges(RingSelOpData *lcd, DerivedMesh *dm, con
edgering_find_order(eed_last, eed, v_last, v);
v_last = v[0][0];
- BLI_array_grow_items(edges, previewlines);
-
for (i = 1; i <= previewlines; i++) {
const float fac = (i / ((float)previewlines + 1));
float v_cos[2][2][3];
@@ -279,8 +295,6 @@ static void edgering_preview_calc_edges(RingSelOpData *lcd, DerivedMesh *dm, con
edgering_find_order(eed_last, eed_start, v_last, v);
- BLI_array_grow_items(edges, previewlines);
-
for (i = 1; i <= previewlines; i++) {
const float fac = (i / ((float)previewlines + 1));
float v_cos[2][2][3];
@@ -297,7 +311,8 @@ static void edgering_preview_calc_edges(RingSelOpData *lcd, DerivedMesh *dm, con
}
}
- BMW_end(&walker);
+ BLI_stack_free(edge_stack);
+
lcd->edges = edges;
lcd->totedge = tot;
}
@@ -362,9 +377,9 @@ static void edgering_select(RingSelOpData *lcd)
}
BMW_init(&walker, em->bm, BMW_EDGERING,
- BMW_MASK_NOP, BMW_MASK_NOP, BMW_MASK_NOP,
- BMW_FLAG_TEST_HIDDEN,
- BMW_NIL_LAY);
+ BMW_MASK_NOP, BMW_MASK_NOP, BMW_MASK_NOP,
+ BMW_FLAG_TEST_HIDDEN,
+ BMW_NIL_LAY);
for (eed = BMW_begin(&walker, eed_start); eed; eed = BMW_step(&walker)) {
BM_edge_select_set(em->bm, eed, true);
@@ -412,11 +427,12 @@ static void ringsel_finish(bContext *C, wmOperator *op)
BM_mesh_esubdivide(em->bm, BM_ELEM_SELECT,
smoothness, smooth_falloff, true,
0.0f, 0.0f,
- cuts, seltype, SUBD_PATH, 0, true,
+ cuts, seltype, SUBD_CORNER_PATH, 0, true,
use_only_quads, 0);
- /* when used in a macro tessface is already re-recalculated */
- EDBM_update_generic(em, (is_macro == false), true);
+ /* when used in a macro the tessfaces will be recalculated anyway,
+ * this is needed here because modifiers depend on updated tessellation, see T45920 */
+ EDBM_update_generic(em, true, true);
if (is_single) {
/* de-select endpoints */
@@ -553,6 +569,7 @@ static int loopcut_init(bContext *C, wmOperator *op, const wmEvent *event)
/* add a modal handler for this operator - handles loop selection */
if (is_interactive) {
+ op->flag |= OP_IS_MODAL_CURSOR_REGION;
WM_event_add_modal_handler(C, op);
}
@@ -639,6 +656,9 @@ static int loopcut_modal(bContext *C, wmOperator *op, const wmEvent *event)
bool show_cuts = false;
const bool has_numinput = hasNumInput(&lcd->num);
+ em_setup_viewcontext(C, &lcd->vc);
+ lcd->ar = lcd->vc.ar;
+
view3d_operator_needs_opengl(C);
/* using the keyboard to input the number of cuts */
@@ -825,21 +845,21 @@ void MESH_OT_loopcut(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING;
/* properties */
- prop = RNA_def_int(ot->srna, "number_cuts", 1, 1, INT_MAX, "Number of Cuts", "", 1, 100);
+ prop = RNA_def_int(ot->srna, "number_cuts", 1, 1, 1000000, "Number of Cuts", "", 1, 100);
/* avoid re-using last var because it can cause _very_ high poly meshes and annoy users (or worse crash) */
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
- prop = RNA_def_float(ot->srna, "smoothness", 0.0f, -FLT_MAX, FLT_MAX,
+ prop = RNA_def_float(ot->srna, "smoothness", 0.0f, -1e3f, 1e3f,
"Smoothness", "Smoothness factor", -SUBD_SMOOTH_MAX, SUBD_SMOOTH_MAX);
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
prop = RNA_def_property(ot->srna, "falloff", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, proportional_falloff_curve_only_items);
- RNA_def_property_enum_default(prop, PROP_ROOT);
+ RNA_def_property_enum_default(prop, PROP_INVSQUARE);
RNA_def_property_ui_text(prop, "Falloff", "Falloff type the feather");
- RNA_def_property_translation_context(prop, BLF_I18NCONTEXT_ID_CURVE); /* Abusing id_curve :/ */
+ RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_CURVE); /* Abusing id_curve :/ */
- prop = RNA_def_int(ot->srna, "edge_index", -1, -1, INT_MAX, "Number of Cuts", "", 0, INT_MAX);
+ prop = RNA_def_int(ot->srna, "edge_index", -1, -1, INT_MAX, "Edge Index", "", 0, INT_MAX);
RNA_def_property_flag(prop, PROP_HIDDEN);
#ifdef USE_LOOPSLIDE_HACK
diff --git a/source/blender/editors/mesh/editmesh_path.c b/source/blender/editors/mesh/editmesh_path.c
index 44d03da93a2..72dfb89e5f3 100644
--- a/source/blender/editors/mesh/editmesh_path.c
+++ b/source/blender/editors/mesh/editmesh_path.c
@@ -32,9 +32,12 @@
#include "DNA_scene_types.h"
#include "DNA_object_types.h"
#include "DNA_mesh_types.h"
-#include "DNA_meshdata_types.h"
#include "DNA_windowmanager_types.h"
+#ifdef WITH_FREESTYLE
+# include "DNA_meshdata_types.h"
+#endif
+
#include "BLI_math.h"
#include "BLI_linklist.h"
@@ -91,7 +94,7 @@ static bool mouse_mesh_shortest_path_vert(ViewContext *vc)
float dist = ED_view3d_select_dist_px();
const bool use_length = true;
- v_dst = EDBM_vert_find_nearest(vc, &dist, false, false);
+ v_dst = EDBM_vert_find_nearest(vc, &dist);
if (v_dst) {
struct UserData user_data = {bm, vc->obedit->data, vc->scene};
LinkNode *path = NULL;
@@ -99,7 +102,7 @@ static bool mouse_mesh_shortest_path_vert(ViewContext *vc)
if (v_act && (v_act != v_dst)) {
if ((path = BM_mesh_calc_path_vert(bm, v_act, v_dst, use_length,
- &user_data, verttag_filter_cb)))
+ verttag_filter_cb, &user_data)))
{
BM_select_history_remove(bm, v_act);
}
@@ -267,7 +270,7 @@ static bool mouse_mesh_shortest_path_edge(ViewContext *vc)
if (e_act && (e_act != e_dst)) {
if ((path = BM_mesh_calc_path_edge(bm, e_act, e_dst, use_length,
- &user_data, edgetag_filter_cb)))
+ edgetag_filter_cb, &user_data)))
{
BM_select_history_remove(bm, e_act);
}
@@ -388,7 +391,7 @@ static bool mouse_mesh_shortest_path_face(ViewContext *vc)
if (f_act) {
if (f_act != f_dst) {
if ((path = BM_mesh_calc_path_face(bm, f_act, f_dst, use_length,
- &user_data, facetag_filter_cb)))
+ facetag_filter_cb, &user_data)))
{
BM_select_history_remove(bm, f_act);
}
@@ -513,11 +516,6 @@ void MESH_OT_shortest_path_pick(wmOperatorType *ot)
/* -------------------------------------------------------------------- */
/* Select path between existing selection */
-static bool ele_filter_visible_cb(BMElem *ele, void *UNUSED(user_data))
-{
- return !BM_elem_flag_test(ele, BM_ELEM_HIDDEN);
-}
-
static int edbm_shortest_path_select_exec(bContext *C, wmOperator *op)
{
Object *ob = CTX_data_edit_object(C);
@@ -577,17 +575,17 @@ static int edbm_shortest_path_select_exec(bContext *C, wmOperator *op)
case BM_VERT:
path = BM_mesh_calc_path_vert(
bm, (BMVert *)ele_src, (BMVert *)ele_dst, use_length,
- NULL, (bool (*)(BMVert *, void *))ele_filter_visible_cb);
+ BM_elem_cb_check_hflag_disabled_simple(BMVert *, BM_ELEM_HIDDEN));
break;
case BM_EDGE:
path = BM_mesh_calc_path_edge(
bm, (BMEdge *)ele_src, (BMEdge *)ele_dst, use_length,
- NULL, (bool (*)(BMEdge *, void *))ele_filter_visible_cb);
+ BM_elem_cb_check_hflag_disabled_simple(BMEdge *, BM_ELEM_HIDDEN));
break;
case BM_FACE:
path = BM_mesh_calc_path_face(
bm, (BMFace *)ele_src, (BMFace *)ele_dst, use_length,
- NULL, (bool (*)(BMFace *, void *))ele_filter_visible_cb);
+ BM_elem_cb_check_hflag_disabled_simple(BMFace *, BM_ELEM_HIDDEN));
break;
}
diff --git a/source/blender/editors/mesh/editmesh_rip.c b/source/blender/editors/mesh/editmesh_rip.c
index 3b993332db0..c7a7828f3b2 100644
--- a/source/blender/editors/mesh/editmesh_rip.c
+++ b/source/blender/editors/mesh/editmesh_rip.c
@@ -63,9 +63,10 @@
* point and would result in the same distance.
*/
#define INSET_DEFAULT 0.00001f
-static float edbm_rip_edgedist_squared(ARegion *ar, float mat[4][4],
- const float co1[3], const float co2[3], const float mvalf[2],
- const float inset)
+static float edbm_rip_edgedist_squared(
+ ARegion *ar, float mat[4][4],
+ const float co1[3], const float co2[3], const float mvalf[2],
+ const float inset)
{
float vec1[2], vec2[2], dist_sq;
@@ -89,8 +90,9 @@ static float edbm_rip_edgedist_squared(ARegion *ar, float mat[4][4],
}
#if 0
-static float edbm_rip_linedist(ARegion *ar, float mat[4][4],
- const float co1[3], const float co2[3], const float mvalf[2])
+static float edbm_rip_linedist(
+ ARegion *ar, float mat[4][4],
+ const float co1[3], const float co2[3], const float mvalf[2])
{
float vec1[2], vec2[2];
@@ -114,9 +116,10 @@ static void edbm_calc_loop_co(BMLoop *l, float l_mid_co[3])
}
-static float edbm_rip_edge_side_measure(BMEdge *e, BMLoop *e_l,
- ARegion *ar,
- float projectMat[4][4], const float fmval[2])
+static float edbm_rip_edge_side_measure(
+ BMEdge *e, BMLoop *e_l,
+ ARegion *ar,
+ float projectMat[4][4], const float fmval[2])
{
float cent[3] = {0, 0, 0}, mid[3];
@@ -309,8 +312,7 @@ static EdgeLoopPair *edbm_ripsel_looptag_helper(BMesh *bm)
uid_start = uid;
uid = uid_end + bm->totedge;
- BLI_array_grow_one(eloop_pairs);
- lp = &eloop_pairs[BLI_array_count(eloop_pairs) - 1];
+ lp = BLI_array_append_ret(eloop_pairs);
BM_edge_loop_pair(e_last, &lp->l_a, &lp->l_b); /* no need to check, we know this will be true */
@@ -323,8 +325,7 @@ static EdgeLoopPair *edbm_ripsel_looptag_helper(BMesh *bm)
}
/* null terminate */
- BLI_array_grow_one(eloop_pairs);
- lp = &eloop_pairs[BLI_array_count(eloop_pairs) - 1];
+ lp = BLI_array_append_ret(eloop_pairs);
lp->l_a = lp->l_b = NULL;
return eloop_pairs;
@@ -534,14 +535,14 @@ static int edbm_rip_invoke__vert(bContext *C, wmOperator *op, const wmEvent *eve
BMesh *bm = em->bm;
BMIter iter, liter;
BMLoop *l;
- BMEdge *e, *e2;
+ BMEdge *e_best;
BMVert *v;
const int totvert_orig = bm->totvert;
int i;
float projectMat[4][4], fmval[3] = {event->mval[0], event->mval[1]};
float dist_sq = FLT_MAX;
float d;
- bool is_wire;
+ bool is_wire, is_manifold_region;
BMEditSelection ese;
int totboundary_edge = 0;
@@ -561,65 +562,91 @@ static int edbm_rip_invoke__vert(bContext *C, wmOperator *op, const wmEvent *eve
}
}
- /* this should be impossible, but sanity checks are a good thing */
- if (!v)
+ /* (v == NULL) should be impossible */
+ if ((v == NULL) || (v->e == NULL)) {
return OPERATOR_CANCELLED;
+ }
is_wire = BM_vert_is_wire(v);
+ is_manifold_region = BM_vert_is_manifold_region(v);
- e2 = NULL;
+ e_best = NULL;
- if (v->e) {
+ {
+ BMEdge *e;
/* find closest edge to mouse cursor */
BM_ITER_ELEM (e, &iter, v, BM_EDGES_OF_VERT) {
- const bool is_boundary = BM_edge_is_boundary(e);
/* consider wire as boundary for this purpose,
* otherwise we can't a face away from a wire edge */
- totboundary_edge += (is_boundary != 0 || BM_edge_is_wire(e));
+ totboundary_edge += (BM_edge_is_boundary(e) || BM_edge_is_wire(e));
if (!BM_elem_flag_test(e, BM_ELEM_HIDDEN)) {
- if (is_boundary == false && BM_edge_is_manifold(e)) {
+ if ((is_manifold_region == false) || BM_edge_is_manifold(e)) {
d = edbm_rip_edgedist_squared(ar, projectMat, e->v1->co, e->v2->co, fmval, INSET_DEFAULT);
- if ((e2 == NULL) || (d < dist_sq)) {
+ if ((e_best == NULL) || (d < dist_sq)) {
dist_sq = d;
- e2 = e;
+ e_best = e;
}
}
}
}
+ }
- /* if we are ripping a single vertex from 3 faces,
- * then measure the distance to the face corner as well as the edge */
- if (BM_vert_face_count(v) == 3 &&
- BM_vert_edge_count(v) == 3)
- {
- BMEdge *e_all[3];
- BMLoop *l_all[3];
- int i1, i2;
-
- BM_iter_as_array(bm, BM_EDGES_OF_VERT, v, (void **)e_all, 3);
- BM_iter_as_array(bm, BM_LOOPS_OF_VERT, v, (void **)l_all, 3);
-
- /* not do a loop similar to the one above, but test against loops */
- for (i1 = 0; i1 < 3; i1++) {
- /* consider wire as boundary for this purpose,
- * otherwise we can't a face away from a wire edge */
- float l_mid_co[3];
- l = l_all[i1];
- edbm_calc_loop_co(l, l_mid_co);
- d = edbm_rip_edgedist_squared(ar, projectMat, l->v->co, l_mid_co, fmval, INSET_DEFAULT);
- if ((e2 == NULL) || (d < dist_sq)) {
- dist_sq = d;
-
- /* find the edge that is not in this loop */
- e2 = NULL;
- for (i2 = 0; i2 < 3; i2++) {
- if (!BM_edge_in_loop(e_all[i2], l)) {
- e2 = e_all[i2];
- break;
- }
+ if (e_best && (is_manifold_region == false)) {
+ /* Try to split off a non-manifold fan (when we have multiple disconnected fans) */
+ BMLoop *l_sep = e_best->l->v == v ? e_best->l : e_best->l->next;
+ BMVert *v_new;
+
+ BLI_assert(l_sep->v == v);
+ v_new = bmesh_urmv_loop_region(bm, l_sep);
+ BLI_assert(BM_vert_find_first_loop(v));
+
+ BM_vert_select_set(bm, v, false);
+ BM_select_history_remove(bm, v);
+
+ BM_vert_select_set(bm, v_new, true);
+ if (ese.ele) {
+ BM_select_history_store(bm, v_new);
+ }
+
+ if (do_fill) {
+ BM_edge_create(bm, v, v_new, NULL, BM_CREATE_NOP);
+ }
+
+ return OPERATOR_FINISHED;
+ }
+
+ /* if we are ripping a single vertex from 3 faces,
+ * then measure the distance to the face corner as well as the edge */
+ if (BM_vert_face_count_is_equal(v, 3) &&
+ BM_vert_edge_count_is_equal(v, 3))
+ {
+ BMEdge *e_all[3];
+ BMLoop *l_all[3];
+ int i1, i2;
+
+ BM_iter_as_array(bm, BM_EDGES_OF_VERT, v, (void **)e_all, 3);
+ BM_iter_as_array(bm, BM_LOOPS_OF_VERT, v, (void **)l_all, 3);
+
+ /* not do a loop similar to the one above, but test against loops */
+ for (i1 = 0; i1 < 3; i1++) {
+ /* consider wire as boundary for this purpose,
+ * otherwise we can't a face away from a wire edge */
+ float l_mid_co[3];
+ l = l_all[i1];
+ edbm_calc_loop_co(l, l_mid_co);
+ d = edbm_rip_edgedist_squared(ar, projectMat, l->v->co, l_mid_co, fmval, INSET_DEFAULT);
+ if ((e_best == NULL) || (d < dist_sq)) {
+ dist_sq = d;
+
+ /* find the edge that is not in this loop */
+ e_best = NULL;
+ for (i2 = 0; i2 < 3; i2++) {
+ if (!BM_edge_in_loop(e_all[i2], l)) {
+ e_best = e_all[i2];
+ break;
}
- BLI_assert(e2 != NULL);
}
+ BLI_assert(e_best != NULL);
}
}
}
@@ -628,7 +655,7 @@ static int edbm_rip_invoke__vert(bContext *C, wmOperator *op, const wmEvent *eve
* split off vertex if...
* - we cant find an edge - this means we are ripping a faces vert that is connected to other
* geometry only at the vertex.
- * - the boundary edge total is greater then 2,
+ * - the boundary edge total is greater than 2,
* in this case edge split _can_ work but we get far nicer results if we use this special case.
* - there are only 2 edges but we are a wire vert. */
if ((is_wire == false && totboundary_edge > 2) ||
@@ -679,6 +706,7 @@ static int edbm_rip_invoke__vert(bContext *C, wmOperator *op, const wmEvent *eve
}
}
else {
+ BMEdge *e;
/* a wire vert, find the best edge */
BM_ITER_ELEM (e, &iter, vout[i], BM_EDGES_OF_VERT) {
if (!BM_elem_flag_test(e, BM_ELEM_HIDDEN)) {
@@ -696,6 +724,15 @@ static int edbm_rip_invoke__vert(bContext *C, wmOperator *op, const wmEvent *eve
}
}
+ /* vout[0] == best
+ * vout[1] == glue
+ * vout[2+] == splice with glue (when vout_len > 2)
+ */
+ if (vi_best != 0) {
+ SWAP(BMVert *, vout[0], vout[vi_best]);
+ vi_best = 0;
+ }
+
/* select the vert from the best region */
v = vout[vi_best];
BM_vert_select_set(bm, v, true);
@@ -706,18 +743,15 @@ static int edbm_rip_invoke__vert(bContext *C, wmOperator *op, const wmEvent *eve
/* splice all others back together */
if (vout_len > 2) {
-
- /* vout[0] == best
- * vout[1] == glue
- * vout[2+] == splice with glue
- */
- if (vi_best != 0) {
- SWAP(BMVert *, vout[0], vout[vi_best]);
- vi_best = 0;
+ for (i = 2; i < vout_len; i++) {
+ BM_vert_splice(bm, vout[1], vout[i]);
}
+ }
- for (i = 2; i < vout_len; i++) {
- BM_vert_splice(bm, vout[i], vout[1]);
+ if (do_fill) {
+ if (do_fill) {
+ /* match extrude vert-order */
+ BM_edge_create(bm, vout[1], vout[0], NULL, BM_CREATE_NOP);
}
}
@@ -727,7 +761,7 @@ static int edbm_rip_invoke__vert(bContext *C, wmOperator *op, const wmEvent *eve
}
}
- if (!e2) {
+ if (!e_best) {
BKE_report(op->reports, RPT_ERROR, "Selected vertex has no edge/face pairs attached");
return OPERATOR_CANCELLED;
}
@@ -736,20 +770,51 @@ static int edbm_rip_invoke__vert(bContext *C, wmOperator *op, const wmEvent *eve
/* unlike edge split, for single vertex split we only use the operator in one of the cases
* but both allocate fill */
- /* rip two adjacent edges */
- if (BM_edge_is_boundary(e2) || BM_vert_face_count(v) == 2) {
- /* Don't run the edge split operator in this case */
+ {
BMVert *v_rip;
+ BMLoop *larr[2];
+ int larr_len = 0;
- l = BM_edge_vert_share_loop(e2->l, v);
+ /* rip two adjacent edges */
+ if (BM_edge_is_boundary(e_best) || BM_vert_face_count_is_equal(v, 2)) {
+ /* Don't run the edge split operator in this case */
- /* only tag for face-fill (we don't call the operator) */
- if (BM_edge_is_boundary(e2)) {
- BM_elem_flag_enable(e2, BM_ELEM_TAG);
+ l = BM_edge_vert_share_loop(e_best->l, v);
+ larr[larr_len] = l;
+ larr_len++;
+
+ /* only tag for face-fill (we don't call the operator) */
+ if (BM_edge_is_boundary(e_best)) {
+ BM_elem_flag_enable(e_best, BM_ELEM_TAG);
+ }
+ else {
+ BM_elem_flag_enable(l->e, BM_ELEM_TAG);
+ BM_elem_flag_enable(l->prev->e, BM_ELEM_TAG);
+ }
}
else {
- BM_elem_flag_enable(l->e, BM_ELEM_TAG);
- BM_elem_flag_enable(l->prev->e, BM_ELEM_TAG);
+ if (BM_edge_is_manifold(e_best)) {
+ BMLoop *l_iter, *l_first;
+ l_iter = l_first = e_best->l;
+ do {
+ larr[larr_len] = BM_edge_vert_share_loop(l_iter, v);
+
+ if (do_fill) {
+ /* Only needed when filling...
+ * Also, we never want to tag best edge, that one won't change during split. See T44618. */
+ if (larr[larr_len]->e == e_best) {
+ BM_elem_flag_enable(larr[larr_len]->prev->e, BM_ELEM_TAG);
+ }
+ else {
+ BM_elem_flag_enable(larr[larr_len]->e, BM_ELEM_TAG);
+ }
+ }
+ larr_len++;
+ } while ((l_iter = l_iter->radial_next) != l_first);
+ }
+ else {
+ /* looks like there are no split edges, we could just return/report-error? - Campbell */
+ }
}
/* keep directly before edgesplit */
@@ -757,13 +822,12 @@ static int edbm_rip_invoke__vert(bContext *C, wmOperator *op, const wmEvent *eve
fill_uloop_pairs = edbm_tagged_loop_pairs_to_fill(bm);
}
-#if 0
- v_rip = BM_face_vert_separate(bm, l->f, v);
-#else
- v_rip = BM_face_loop_separate(bm, l);
-#endif
-
- BLI_assert(v_rip);
+ if (larr_len) {
+ v_rip = BM_face_loop_separate_multi(bm, larr, larr_len);
+ }
+ else {
+ v_rip = NULL;
+ }
if (v_rip) {
BM_vert_select_set(bm, v_rip, true);
@@ -773,27 +837,6 @@ static int edbm_rip_invoke__vert(bContext *C, wmOperator *op, const wmEvent *eve
return OPERATOR_CANCELLED;
}
}
- else {
- if (BM_edge_is_manifold(e2)) {
- l = e2->l;
- e = BM_loop_other_edge_loop(l, v)->e;
- BM_elem_flag_enable(e, BM_ELEM_TAG);
-
- l = e2->l->radial_next;
- e = BM_loop_other_edge_loop(l, v)->e;
- BM_elem_flag_enable(e, BM_ELEM_TAG);
- }
- else {
- /* looks like there are no split edges, we could just return/report-error? - Campbell */
- }
-
- /* keep directly before edgesplit */
- if (do_fill) {
- fill_uloop_pairs = edbm_tagged_loop_pairs_to_fill(bm);
- }
-
- BM_mesh_edgesplit(em->bm, true, true, true);
- }
{
/* --- select which vert --- */
@@ -856,7 +899,7 @@ static int edbm_rip_invoke__edge(bContext *C, wmOperator *op, const wmEvent *eve
BMesh *bm = em->bm;
BMIter iter, eiter;
BMLoop *l;
- BMEdge *e, *e2;
+ BMEdge *e_best;
BMVert *v;
const int totedge_orig = bm->totedge;
float projectMat[4][4], fmval[3] = {event->mval[0], event->mval[1]};
@@ -870,11 +913,12 @@ static int edbm_rip_invoke__edge(bContext *C, wmOperator *op, const wmEvent *eve
/* expand edge selection */
BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
+ BMEdge *e;
bool all_manifold;
int totedge_manifold; /* manifold, visible edges */
int i;
- e2 = NULL;
+ e_best = NULL;
i = 0;
totedge_manifold = 0;
all_manifold = true;
@@ -886,7 +930,7 @@ static int edbm_rip_invoke__edge(bContext *C, wmOperator *op, const wmEvent *eve
/* important to check selection rather then tag here
* else we get feedback loop */
if (BM_elem_flag_test(e, BM_ELEM_SELECT)) {
- e2 = e;
+ e_best = e;
i++;
}
totedge_manifold++;
@@ -899,18 +943,18 @@ static int edbm_rip_invoke__edge(bContext *C, wmOperator *op, const wmEvent *eve
}
/* single edge, extend */
- if (i == 1 && e2->l) {
+ if (i == 1 && e_best->l) {
/* note: if the case of 3 edges has one change in loop stepping,
* if this becomes more involved we may be better off splitting
* the 3 edge case into its own else-if branch */
if ((totedge_manifold == 4 || totedge_manifold == 3) || (all_manifold == false)) {
- BMLoop *l_a = e2->l;
+ BMLoop *l_a = e_best->l;
BMLoop *l_b = l_a->radial_next;
/* find the best face to follow, this way the edge won't point away from
* the mouse when there are more than 4 (takes the shortest face fan around) */
- l = (edbm_rip_edge_side_measure(e2, l_a, ar, projectMat, fmval) <
- edbm_rip_edge_side_measure(e2, l_b, ar, projectMat, fmval)) ? l_a : l_b;
+ l = (edbm_rip_edge_side_measure(e_best, l_a, ar, projectMat, fmval) <
+ edbm_rip_edge_side_measure(e_best, l_b, ar, projectMat, fmval)) ? l_a : l_b;
l = BM_loop_other_edge_loop(l, v);
/* important edge is manifold else we can be attempting to split off a fan that don't budge,
@@ -928,7 +972,7 @@ static int edbm_rip_invoke__edge(bContext *C, wmOperator *op, const wmEvent *eve
}
}
else {
- e = BM_vert_other_disk_edge(v, e2);
+ e = BM_vert_other_disk_edge(v, e_best);
if (e) {
BLI_assert(!BM_elem_flag_test(e, BM_ELEM_TAG));
diff --git a/source/blender/editors/mesh/editmesh_rip_edge.c b/source/blender/editors/mesh/editmesh_rip_edge.c
index 5daf33fae3b..a501dfc8c2c 100644
--- a/source/blender/editors/mesh/editmesh_rip_edge.c
+++ b/source/blender/editors/mesh/editmesh_rip_edge.c
@@ -24,8 +24,6 @@
* based on mouse cursor position, split of vertices along the closest edge.
*/
-#include "MEM_guardedalloc.h"
-
#include "DNA_object_types.h"
#include "BLI_math.h"
@@ -34,9 +32,6 @@
#include "BKE_report.h"
#include "BKE_editmesh.h"
-#include "RNA_define.h"
-#include "RNA_access.h"
-
#include "WM_types.h"
#include "ED_mesh.h"
@@ -177,7 +172,7 @@ static int edbm_rip_edge_invoke(bContext *C, wmOperator *UNUSED(op), const wmEve
ED_view3d_project_float_v2_m4(ar, v_other->co, v_other_sco, projectMat);
- /* avoid comparing with view-axis aligned edges (less then a pixel) */
+ /* avoid comparing with view-axis aligned edges (less than a pixel) */
if (len_squared_v2v2(v_sco, v_other_sco) > 1.0f) {
float v_dir[2];
diff --git a/source/blender/editors/mesh/editmesh_select.c b/source/blender/editors/mesh/editmesh_select.c
index 9cdfb43ae15..7f22ff7c241 100644
--- a/source/blender/editors/mesh/editmesh_select.c
+++ b/source/blender/editors/mesh/editmesh_select.c
@@ -36,9 +36,9 @@
#include "BLI_linklist.h"
#include "BLI_linklist_stack.h"
#include "BLI_math.h"
+#include "BLI_math_bits.h"
#include "BLI_rand.h"
#include "BLI_array.h"
-#include "BLI_smallhash.h"
#include "BKE_context.h"
#include "BKE_report.h"
@@ -53,6 +53,7 @@
#include "RNA_access.h"
#include "RNA_define.h"
+#include "RNA_enum_types.h"
#include "ED_mesh.h"
#include "ED_screen.h"
@@ -62,10 +63,10 @@
#include "DNA_meshdata_types.h"
#include "DNA_object_types.h"
-#include "GPU_extensions.h"
-
#include "UI_resources.h"
+#include "bmesh_tools.h"
+
#include "mesh_intern.h" /* own include */
/* use bmesh operator flags for a few operators */
@@ -197,13 +198,14 @@ bool EDBM_backbuf_border_init(ViewContext *vc, short xmin, short ymin, short xma
unsigned int *dr;
int a;
- if (vc->obedit == NULL || vc->v3d->drawtype < OB_SOLID || (vc->v3d->flag & V3D_ZBUF_SELECT) == 0) {
+ if (vc->obedit == NULL || !V3D_IS_ZBUF(vc->v3d)) {
return false;
}
- buf = view3d_read_backbuf(vc, xmin, ymin, xmax, ymax);
- if (buf == NULL) return false;
- if (bm_vertoffs == 0) return false;
+ buf = ED_view3d_backbuf_read(vc, xmin, ymin, xmax, ymax);
+ if ((buf == NULL) || (bm_vertoffs == 0)) {
+ return false;
+ }
dr = buf->rect;
@@ -272,13 +274,14 @@ bool EDBM_backbuf_border_mask_init(ViewContext *vc, const int mcords[][2], short
return false;
}
}
- else if (vc->v3d->drawtype < OB_SOLID || (vc->v3d->flag & V3D_ZBUF_SELECT) == 0) {
+ else if (!V3D_IS_ZBUF(vc->v3d)) {
return false;
}
- buf = view3d_read_backbuf(vc, xmin, ymin, xmax, ymax);
- if (buf == NULL) return false;
- if (bm_vertoffs == 0) return false;
+ buf = ED_view3d_backbuf_read(vc, xmin, ymin, xmax, ymax);
+ if ((buf == NULL) || (bm_vertoffs == 0)) {
+ return false;
+ }
dr = buf->rect;
@@ -321,15 +324,16 @@ bool EDBM_backbuf_circle_init(ViewContext *vc, short xs, short ys, short rads)
return false;
}
}
- else if (vc->v3d->drawtype < OB_SOLID || (vc->v3d->flag & V3D_ZBUF_SELECT) == 0) {
+ else if (!V3D_IS_ZBUF(vc->v3d)) {
return false;
}
xmin = xs - rads; xmax = xs + rads;
ymin = ys - rads; ymax = ys + rads;
- buf = view3d_read_backbuf(vc, xmin, ymin, xmax, ymax);
- if (bm_vertoffs == 0) return false;
- if (buf == NULL) return false;
+ buf = ED_view3d_backbuf_read(vc, xmin, ymin, xmax, ymax);
+ if ((buf == NULL) || (bm_vertoffs == 0)) {
+ return false;
+ }
dr = buf->rect;
@@ -351,196 +355,369 @@ bool EDBM_backbuf_circle_init(ViewContext *vc, short xs, short ys, short rads)
}
+
+/* -------------------------------------------------------------------- */
+
+/** \name Find Nearest Vert/Edge/Face
+ *
+ * \note Screen-space manhatten distances are used here,
+ * since its faster and good enough for the purpose of selection.
+ *
+ * \note \a dist_bias is used so we can bias against selected items.
+ * when choosing between elements of a single type, but return the real distance
+ * to avoid the bias interfering with distance comparisons when mixing types.
+ * \{ */
+
+#define FIND_NEAR_SELECT_BIAS 5
+#define FIND_NEAR_CYCLE_THRESHOLD_MIN 3
+
+struct NearestVertUserData_Hit {
+ float dist;
+ float dist_bias;
+ int index;
+ BMVert *vert;
+};
+
+struct NearestVertUserData {
+ float mval_fl[2];
+ bool use_select_bias;
+ bool use_cycle;
+ int cycle_index_prev;
+
+ struct NearestVertUserData_Hit hit;
+ struct NearestVertUserData_Hit hit_cycle;
+};
+
static void findnearestvert__doClosest(void *userData, BMVert *eve, const float screen_co[2], int index)
{
- struct { float mval_fl[2], pass, select, strict; float dist, lastIndex, closestIndex; BMVert *closest; } *data = userData;
+ struct NearestVertUserData *data = userData;
+ float dist_test, dist_test_bias;
- if (data->pass == 0) {
- if (index <= data->lastIndex)
- return;
- }
- else {
- if (index > data->lastIndex)
- return;
+ dist_test = dist_test_bias = len_manhattan_v2v2(data->mval_fl, screen_co);
+
+ if (data->use_select_bias && BM_elem_flag_test(eve, BM_ELEM_SELECT)) {
+ dist_test_bias += FIND_NEAR_SELECT_BIAS;
}
- if (data->dist > 3) {
- float dist_test = len_manhattan_v2v2(data->mval_fl, screen_co);
- if (BM_elem_flag_test(eve, BM_ELEM_SELECT) == data->select) {
- if (data->strict == 1) {
- return;
- }
- else {
- dist_test += 5;
- }
- }
+ if (dist_test_bias < data->hit.dist_bias) {
+ data->hit.dist_bias = dist_test_bias;
+ data->hit.dist = dist_test;
+ data->hit.index = index;
+ data->hit.vert = eve;
+ }
- if (dist_test < data->dist) {
- data->dist = dist_test;
- data->closest = eve;
- data->closestIndex = index;
+ if (data->use_cycle) {
+ if ((data->hit_cycle.vert == NULL) &&
+ (index > data->cycle_index_prev) &&
+ (dist_test_bias < FIND_NEAR_CYCLE_THRESHOLD_MIN))
+ {
+ data->hit_cycle.dist_bias = dist_test_bias;
+ data->hit_cycle.dist = dist_test;
+ data->hit_cycle.index = index;
+ data->hit_cycle.vert = eve;
}
}
}
-
-
-
-static bool findnearestvert__backbufIndextest(void *handle, unsigned int index)
-{
- BMEditMesh *em = (BMEditMesh *)handle;
- BMVert *eve = BM_vert_at_index_find(em->bm, index - 1);
- return !(eve && BM_elem_flag_test(eve, BM_ELEM_SELECT));
-}
/**
- * findnearestvert
- *
- * dist (in/out): minimal distance to the nearest and at the end, actual distance
- * sel: selection bias
- * if SELECT, selected vertice are given a 5 pixel bias to make them further than unselect verts
- * if 0, unselected vertice are given the bias
- * strict: if 1, the vertice corresponding to the sel parameter are ignored and not just biased
+ * Nearest vertex under the cursor.
+ *
+ * \param r_dist (in/out), minimal distance to the nearest and at the end, actual distance
+ * \param use_select_bias
+ * - When true, selected vertice are given a 5 pixel bias to make them further than unselect verts.
+ * - When false, unselected vertice are given the bias.
+ * \param use_cycle Cycle over elements within #FIND_NEAR_CYCLE_THRESHOLD_MIN in order of index.
*/
-BMVert *EDBM_vert_find_nearest(ViewContext *vc, float *r_dist, const bool sel, const bool strict)
+BMVert *EDBM_vert_find_nearest_ex(
+ ViewContext *vc, float *r_dist,
+ const bool use_select_bias, bool use_cycle)
{
- if (vc->v3d->drawtype > OB_WIRE && (vc->v3d->flag & V3D_ZBUF_SELECT)) {
- float distance;
+ BMesh *bm = vc->em->bm;
+
+ if (V3D_IS_ZBUF(vc->v3d)) {
+ const int dist_px = ED_view3d_backbuf_sample_size_clamp(vc->ar, *r_dist);
+ float dist_test;
unsigned int index;
BMVert *eve;
- if (strict) {
- index = view3d_sample_backbuf_rect(vc, vc->mval, 50, bm_wireoffs, 0xFFFFFF, &distance,
- strict, vc->em, findnearestvert__backbufIndextest);
- }
- else {
- index = view3d_sample_backbuf_rect(vc, vc->mval, 50, bm_wireoffs, 0xFFFFFF, &distance,
- 0, NULL, NULL);
- }
-
- eve = index ? BM_vert_at_index_find(vc->em->bm, index - 1) : NULL;
+ index = ED_view3d_backbuf_sample_rect(
+ vc, vc->mval, dist_px, bm_wireoffs, 0xFFFFFF, &dist_test);
+ eve = index ? BM_vert_at_index_find_or_table(bm, index - 1) : NULL;
- if (eve && distance < *r_dist) {
- *r_dist = distance;
- return eve;
- }
- else {
- return NULL;
+ if (eve) {
+ if (dist_test < *r_dist) {
+ *r_dist = dist_test;
+ return eve;
+ }
}
-
+ return NULL;
}
else {
- struct { float mval_fl[2], pass, select, strict; float dist, lastIndex, closestIndex; BMVert *closest; } data;
- static int lastSelectedIndex = 0;
- static BMVert *lastSelected = NULL;
-
- if (lastSelected && BM_vert_at_index_find(vc->em->bm, lastSelectedIndex) != lastSelected) {
- lastSelectedIndex = 0;
- lastSelected = NULL;
+ struct NearestVertUserData data = {{0}};
+ const struct NearestVertUserData_Hit *hit;
+ const eV3DProjTest clip_flag = V3D_PROJ_TEST_CLIP_DEFAULT;
+
+ static int prev_select_index = 0;
+ static const BMVert *prev_select_elem = NULL;
+
+ if ((use_cycle == false) ||
+ (prev_select_elem && (prev_select_elem != BM_vert_at_index_find_or_table(bm, prev_select_index))))
+ {
+ prev_select_index = 0;
+ prev_select_elem = NULL;
}
- data.lastIndex = lastSelectedIndex;
data.mval_fl[0] = vc->mval[0];
data.mval_fl[1] = vc->mval[1];
- data.select = sel ? BM_ELEM_SELECT : 0;
- data.dist = *r_dist;
- data.strict = strict;
- data.closest = NULL;
- data.closestIndex = 0;
-
- data.pass = 0;
+ data.use_select_bias = use_select_bias;
+ data.use_cycle = use_cycle;
+ data.hit.dist = data.hit_cycle.dist = \
+ data.hit.dist_bias = data.hit_cycle.dist_bias = *r_dist;
+ data.cycle_index_prev = prev_select_index;
ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d);
+ mesh_foreachScreenVert(vc, findnearestvert__doClosest, &data, clip_flag);
- mesh_foreachScreenVert(vc, findnearestvert__doClosest, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
+ hit = (data.use_cycle && data.hit_cycle.vert) ? &data.hit_cycle : &data.hit;
+ *r_dist = hit->dist;
- if (data.dist > 3) {
- data.pass = 1;
- mesh_foreachScreenVert(vc, findnearestvert__doClosest, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
- }
+ prev_select_elem = hit->vert;
+ prev_select_index = hit->index;
- *r_dist = data.dist;
- lastSelected = data.closest;
- lastSelectedIndex = data.closestIndex;
+ return hit->vert;
+ }
+}
- return data.closest;
+BMVert *EDBM_vert_find_nearest(ViewContext *vc, float *r_dist)
+{
+ return EDBM_vert_find_nearest_ex(vc, r_dist, false, false);
+}
+
+/* find the distance to the edge we already have */
+struct NearestEdgeUserData_ZBuf {
+ float mval_fl[2];
+ float dist;
+ const BMEdge *edge_test;
+};
+
+static void find_nearest_edge_center__doZBuf(
+ void *userData, BMEdge *eed,
+ const float screen_co_a[2], const float screen_co_b[2],
+ int UNUSED(index))
+{
+ struct NearestEdgeUserData_ZBuf *data = userData;
+
+ if (eed == data->edge_test) {
+ float dist_test;
+ float screen_co_mid[2];
+
+ mid_v2_v2v2(screen_co_mid, screen_co_a, screen_co_b);
+ dist_test = len_manhattan_v2v2(data->mval_fl, screen_co_mid);
+
+ if (dist_test < data->dist) {
+ data->dist = dist_test;
+ }
}
}
+struct NearestEdgeUserData_Hit {
+ float dist;
+ float dist_bias;
+ int index;
+ BMEdge *edge;
+
+ /* edges only, un-biased manhatten distance to which ever edge we pick
+ * (not used for choosing) */
+ float dist_center;
+};
+
+struct NearestEdgeUserData {
+ ViewContext vc;
+ float mval_fl[2];
+ bool use_select_bias;
+ bool use_cycle;
+ int cycle_index_prev;
+
+ struct NearestEdgeUserData_Hit hit;
+ struct NearestEdgeUserData_Hit hit_cycle;
+};
+
/* note; uses v3d, so needs active 3d window */
-static void findnearestedge__doClosest(void *userData, BMEdge *eed, const float screen_co_a[2], const float screen_co_b[2], int UNUSED(index))
+static void find_nearest_edge__doClosest(
+ void *userData, BMEdge *eed,
+ const float screen_co_a[2], const float screen_co_b[2],
+ int index)
{
- struct { ViewContext vc; float mval_fl[2]; float dist; BMEdge *closest; } *data = userData;
- int distance;
+ struct NearestEdgeUserData *data = userData;
+ float dist_test, dist_test_bias;
- distance = dist_to_line_segment_v2(data->mval_fl, screen_co_a, screen_co_b);
-
- if (BM_elem_flag_test(eed, BM_ELEM_SELECT)) {
- distance += 5;
+ float fac = line_point_factor_v2(data->mval_fl, screen_co_a, screen_co_b);
+ float screen_co[2];
+
+ if (fac <= 0.0f) {
+ fac = 0.0f;
+ copy_v2_v2(screen_co, screen_co_a);
+ }
+ else if (fac >= 1.0f) {
+ fac = 1.0f;
+ copy_v2_v2(screen_co, screen_co_b);
+ }
+ else {
+ interp_v2_v2v2(screen_co, screen_co_a, screen_co_b, fac);
}
- if (distance < data->dist) {
- if (data->vc.rv3d->rflag & RV3D_CLIPPING) {
- float lambda = line_point_factor_v2(data->mval_fl, screen_co_a, screen_co_b);
- float vec[3];
+ dist_test = dist_test_bias = len_manhattan_v2v2(data->mval_fl, screen_co);
- vec[0] = eed->v1->co[0] + lambda * (eed->v2->co[0] - eed->v1->co[0]);
- vec[1] = eed->v1->co[1] + lambda * (eed->v2->co[1] - eed->v1->co[1]);
- vec[2] = eed->v1->co[2] + lambda * (eed->v2->co[2] - eed->v1->co[2]);
+ if (data->use_select_bias && BM_elem_flag_test(eed, BM_ELEM_SELECT)) {
+ dist_test_bias += FIND_NEAR_SELECT_BIAS;
+ }
- if (ED_view3d_clipping_test(data->vc.rv3d, vec, true) == 0) {
- data->dist = distance;
- data->closest = eed;
- }
+ if (data->vc.rv3d->rflag & RV3D_CLIPPING) {
+ float vec[3];
+
+ interp_v3_v3v3(vec, eed->v1->co, eed->v2->co, fac);
+ if (ED_view3d_clipping_test(data->vc.rv3d, vec, true)) {
+ return;
}
- else {
- data->dist = distance;
- data->closest = eed;
+ }
+
+ if (dist_test_bias < data->hit.dist_bias) {
+ float screen_co_mid[2];
+
+ data->hit.dist_bias = dist_test_bias;
+ data->hit.dist = dist_test;
+ data->hit.index = index;
+ data->hit.edge = eed;
+
+ mid_v2_v2v2(screen_co_mid, screen_co_a, screen_co_b);
+ data->hit.dist_center = len_manhattan_v2v2(data->mval_fl, screen_co_mid);
+ }
+
+ if (data->use_cycle) {
+ if ((data->hit_cycle.edge == NULL) &&
+ (index > data->cycle_index_prev) &&
+ (dist_test_bias < FIND_NEAR_CYCLE_THRESHOLD_MIN))
+ {
+ float screen_co_mid[2];
+
+ data->hit_cycle.dist_bias = dist_test_bias;
+ data->hit_cycle.dist = dist_test;
+ data->hit_cycle.index = index;
+ data->hit_cycle.edge = eed;
+
+ mid_v2_v2v2(screen_co_mid, screen_co_a, screen_co_b);
+ data->hit_cycle.dist_center = len_manhattan_v2v2(data->mval_fl, screen_co_mid);
}
}
}
-BMEdge *EDBM_edge_find_nearest(ViewContext *vc, float *r_dist)
+
+BMEdge *EDBM_edge_find_nearest_ex(
+ ViewContext *vc, float *r_dist,
+ float *r_dist_center,
+ const bool use_select_bias, const bool use_cycle,
+ BMEdge **r_eed_zbuf)
{
+ BMesh *bm = vc->em->bm;
- if (vc->v3d->drawtype > OB_WIRE && (vc->v3d->flag & V3D_ZBUF_SELECT)) {
- float distance;
+ if (V3D_IS_ZBUF(vc->v3d)) {
+ const int dist_px = ED_view3d_backbuf_sample_size_clamp(vc->ar, *r_dist);
+ float dist_test = 0.0f;
unsigned int index;
BMEdge *eed;
- view3d_validate_backbuf(vc);
-
- index = view3d_sample_backbuf_rect(vc, vc->mval, 50, bm_solidoffs, bm_wireoffs, &distance, 0, NULL, NULL);
- eed = index ? BM_edge_at_index_find(vc->em->bm, index - 1) : NULL;
-
- if (eed && distance < *r_dist) {
- *r_dist = distance;
- return eed;
+ ED_view3d_backbuf_validate(vc);
+
+ index = ED_view3d_backbuf_sample_rect(vc, vc->mval, dist_px, bm_solidoffs, bm_wireoffs, &dist_test);
+ eed = index ? BM_edge_at_index_find_or_table(bm, index - 1) : NULL;
+
+ if (r_eed_zbuf) {
+ *r_eed_zbuf = eed;
}
- else {
- return NULL;
+
+ /* exception for faces (verts don't need this) */
+ if (r_dist_center && eed) {
+ struct NearestEdgeUserData_ZBuf data;
+
+ data.mval_fl[0] = vc->mval[0];
+ data.mval_fl[1] = vc->mval[1];
+ data.dist = FLT_MAX;
+ data.edge_test = eed;
+
+ ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d);
+
+ mesh_foreachScreenEdge(vc, find_nearest_edge_center__doZBuf, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
+
+ *r_dist_center = data.dist;
+ }
+ /* end exception */
+
+ if (eed) {
+ if (dist_test < *r_dist) {
+ *r_dist = dist_test;
+ return eed;
+ }
}
+ return NULL;
}
else {
- struct { ViewContext vc; float mval_fl[2]; float dist; BMEdge *closest; } data;
+ struct NearestEdgeUserData data = {{0}};
+ const struct NearestEdgeUserData_Hit *hit;
+ /* interpolate along the edge before doing a clipping plane test */
+ const eV3DProjTest clip_flag = V3D_PROJ_TEST_CLIP_DEFAULT & ~V3D_PROJ_TEST_CLIP_BB;
+
+ static int prev_select_index = 0;
+ static const BMEdge *prev_select_elem = NULL;
+
+ if ((use_cycle == false) ||
+ (prev_select_elem && (prev_select_elem != BM_edge_at_index_find_or_table(bm, prev_select_index))))
+ {
+ prev_select_index = 0;
+ prev_select_elem = NULL;
+ }
data.vc = *vc;
data.mval_fl[0] = vc->mval[0];
data.mval_fl[1] = vc->mval[1];
- data.dist = *r_dist;
- data.closest = NULL;
+ data.use_select_bias = use_select_bias;
+ data.use_cycle = use_cycle;
+ data.hit.dist = data.hit_cycle.dist = \
+ data.hit.dist_bias = data.hit_cycle.dist_bias = *r_dist;
+ data.cycle_index_prev = prev_select_index;
+
ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d);
+ mesh_foreachScreenEdge(vc, find_nearest_edge__doClosest, &data, clip_flag);
- mesh_foreachScreenEdge(vc, findnearestedge__doClosest, &data, V3D_PROJ_TEST_CLIP_WIN);
+ hit = (data.use_cycle && data.hit_cycle.edge) ? &data.hit_cycle : &data.hit;
+ *r_dist = hit->dist;
+ if (r_dist_center) {
+ *r_dist_center = hit->dist_center;
+ }
+
+ prev_select_elem = hit->edge;
+ prev_select_index = hit->index;
- *r_dist = data.dist;
- return data.closest;
+ return hit->edge;
}
}
-static void findnearestface__getDistance(void *userData, BMFace *efa, const float screen_co[2], int UNUSED(index))
+BMEdge *EDBM_edge_find_nearest(
+ ViewContext *vc, float *r_dist)
+{
+ return EDBM_edge_find_nearest_ex(vc, r_dist, NULL, false, false, NULL);
+}
+
+/* find the distance to the face we already have */
+struct NearestFaceUserData_ZBuf {
+ float mval_fl[2];
+ float dist;
+ const BMFace *face_test;
+};
+
+static void find_nearest_face_center__doZBuf(void *userData, BMFace *efa, const float screen_co[2], int UNUSED(index))
{
- struct { float mval_fl[2]; float dist; BMFace *toFace; } *data = userData;
+ struct NearestFaceUserData_ZBuf *data = userData;
- if (efa == data->toFace) {
+ if (efa == data->face_test) {
const float dist_test = len_manhattan_v2v2(data->mval_fl, screen_co);
if (dist_test < data->dist) {
@@ -548,96 +725,152 @@ static void findnearestface__getDistance(void *userData, BMFace *efa, const floa
}
}
}
+
+
+struct NearestFaceUserData_Hit {
+ float dist;
+ float dist_bias;
+ int index;
+ BMFace *face;
+};
+
+struct NearestFaceUserData {
+ float mval_fl[2];
+ bool use_select_bias;
+ bool use_cycle;
+ int cycle_index_prev;
+
+ struct NearestFaceUserData_Hit hit;
+ struct NearestFaceUserData_Hit hit_cycle;
+};
+
static void findnearestface__doClosest(void *userData, BMFace *efa, const float screen_co[2], int index)
{
- struct { float mval_fl[2], pass; float dist, lastIndex, closestIndex; BMFace *closest; } *data = userData;
+ struct NearestFaceUserData *data = userData;
+ float dist_test, dist_test_bias;
- if (data->pass == 0) {
- if (index <= data->lastIndex)
- return;
- }
- else {
- if (index > data->lastIndex)
- return;
+ dist_test = dist_test_bias = len_manhattan_v2v2(data->mval_fl, screen_co);
+
+ if (data->use_select_bias && BM_elem_flag_test(efa, BM_ELEM_SELECT)) {
+ dist_test_bias += FIND_NEAR_SELECT_BIAS;
}
- if (data->dist > 3) {
- const float dist_test = len_manhattan_v2v2(data->mval_fl, screen_co);
+ if (dist_test_bias < data->hit.dist_bias) {
+ data->hit.dist_bias = dist_test_bias;
+ data->hit.dist = dist_test;
+ data->hit.index = index;
+ data->hit.face = efa;
+ }
- if (dist_test < data->dist) {
- data->dist = dist_test;
- data->closest = efa;
- data->closestIndex = index;
+ if (data->use_cycle) {
+ if ((data->hit_cycle.face == NULL) &&
+ (index > data->cycle_index_prev) &&
+ (dist_test_bias < FIND_NEAR_CYCLE_THRESHOLD_MIN))
+ {
+ data->hit_cycle.dist_bias = dist_test_bias;
+ data->hit_cycle.dist = dist_test;
+ data->hit_cycle.index = index;
+ data->hit_cycle.face = efa;
}
}
}
-BMFace *EDBM_face_find_nearest(ViewContext *vc, float *r_dist)
+
+BMFace *EDBM_face_find_nearest_ex(
+ ViewContext *vc, float *r_dist,
+ float *r_dist_center,
+ const bool use_select_bias, const bool use_cycle,
+ BMFace **r_efa_zbuf)
{
+ BMesh *bm = vc->em->bm;
- if (vc->v3d->drawtype > OB_WIRE && (vc->v3d->flag & V3D_ZBUF_SELECT)) {
+ if (V3D_IS_ZBUF(vc->v3d)) {
+ float dist_test = 0.0f;
unsigned int index;
BMFace *efa;
- view3d_validate_backbuf(vc);
+ ED_view3d_backbuf_validate(vc);
- index = view3d_sample_backbuf(vc, vc->mval[0], vc->mval[1]);
- efa = index ? BM_face_at_index_find(vc->em->bm, index - 1) : NULL;
+ index = ED_view3d_backbuf_sample(vc, vc->mval[0], vc->mval[1]);
+ efa = index ? BM_face_at_index_find_or_table(bm, index - 1) : NULL;
- if (efa) {
- struct { float mval_fl[2]; float dist; BMFace *toFace; } data;
+ if (r_efa_zbuf) {
+ *r_efa_zbuf = efa;
+ }
+
+ /* exception for faces (verts don't need this) */
+ if (r_dist_center && efa) {
+ struct NearestFaceUserData_ZBuf data;
data.mval_fl[0] = vc->mval[0];
data.mval_fl[1] = vc->mval[1];
data.dist = FLT_MAX;
- data.toFace = efa;
+ data.face_test = efa;
ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d);
- mesh_foreachScreenFace(vc, findnearestface__getDistance, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
+ mesh_foreachScreenFace(vc, find_nearest_face_center__doZBuf, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
- if ((vc->em->selectmode == SCE_SELECT_FACE) || (data.dist < *r_dist)) { /* only faces, no dist check */
- *r_dist = data.dist;
+ *r_dist_center = data.dist;
+ }
+ /* end exception */
+
+ if (efa) {
+ if (dist_test < *r_dist) {
+ *r_dist = dist_test;
return efa;
}
}
-
return NULL;
}
else {
- struct { float mval_fl[2], pass; float dist, lastIndex, closestIndex; BMFace *closest; } data;
- static int lastSelectedIndex = 0;
- static BMFace *lastSelected = NULL;
+ struct NearestFaceUserData data = {{0}};
+ const struct NearestFaceUserData_Hit *hit;
+ const eV3DProjTest clip_flag = V3D_PROJ_TEST_CLIP_DEFAULT;
+
+ static int prev_select_index = 0;
+ static const BMFace *prev_select_elem = NULL;
- if (lastSelected && BM_face_at_index_find(vc->em->bm, lastSelectedIndex) != lastSelected) {
- lastSelectedIndex = 0;
- lastSelected = NULL;
+ if ((use_cycle == false) ||
+ (prev_select_elem && (prev_select_elem != BM_face_at_index_find_or_table(bm, prev_select_index))))
+ {
+ prev_select_index = 0;
+ prev_select_elem = NULL;
}
- data.lastIndex = lastSelectedIndex;
data.mval_fl[0] = vc->mval[0];
data.mval_fl[1] = vc->mval[1];
- data.dist = *r_dist;
- data.closest = NULL;
- data.closestIndex = 0;
+ data.use_select_bias = use_select_bias;
+ data.use_cycle = use_cycle;
+ data.hit.dist = data.hit_cycle.dist = \
+ data.hit.dist_bias = data.hit_cycle.dist_bias = *r_dist;
+ data.cycle_index_prev = prev_select_index;
- data.pass = 0;
ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d);
- mesh_foreachScreenFace(vc, findnearestface__doClosest, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
+ mesh_foreachScreenFace(vc, findnearestface__doClosest, &data, clip_flag);
- if (data.dist > 3.0f) {
- data.pass = 1;
- mesh_foreachScreenFace(vc, findnearestface__doClosest, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
+ hit = (data.use_cycle && data.hit_cycle.face) ? &data.hit_cycle : &data.hit;
+ *r_dist = hit->dist;
+ if (r_dist_center) {
+ *r_dist_center = hit->dist;
}
- *r_dist = data.dist;
- lastSelected = data.closest;
- lastSelectedIndex = data.closestIndex;
+ prev_select_elem = hit->face;
+ prev_select_index = hit->index;
- return data.closest;
+ return hit->face;
}
}
+BMFace *EDBM_face_find_nearest(ViewContext *vc, float *r_dist)
+{
+ return EDBM_face_find_nearest_ex(vc, r_dist, NULL, false, false, NULL);
+}
+
+#undef FIND_NEAR_SELECT_BIAS
+#undef FIND_NEAR_CYCLE_THRESHOLD_MIN
+
+
/* best distance based on screen coords.
* use em->selectmode to define how to use
* selected vertices and edges get disadvantage
@@ -646,35 +879,78 @@ BMFace *EDBM_face_find_nearest(ViewContext *vc, float *r_dist)
static int unified_findnearest(ViewContext *vc, BMVert **r_eve, BMEdge **r_eed, BMFace **r_efa)
{
BMEditMesh *em = vc->em;
- float dist = ED_view3d_select_dist_px();
-
- *r_eve = NULL;
- *r_eed = NULL;
- *r_efa = NULL;
+ static short mval_prev[2] = {-1, -1};
+ /* only cycle while the mouse remains still */
+ const bool use_cycle = ((mval_prev[0] == vc->mval[0]) && (mval_prev[1] == vc->mval[1]));
+ const float dist_init = ED_view3d_select_dist_px();
+ /* since edges select lines, we give dots advantage of ~20 pix */
+ const float dist_margin = (dist_init / 2);
+ float dist = dist_init;
+ BMFace *efa_zbuf = NULL;
+ BMEdge *eed_zbuf = NULL;
+ BMVert *eve = NULL;
+ BMEdge *eed = NULL;
+ BMFace *efa = NULL;
+
+
/* no afterqueue (yet), so we check it now, otherwise the em_xxxofs indices are bad */
- view3d_validate_backbuf(vc);
-
- if (em->selectmode & SCE_SELECT_VERTEX)
- *r_eve = EDBM_vert_find_nearest(vc, &dist, BM_ELEM_SELECT, 0);
- if (em->selectmode & SCE_SELECT_FACE)
- *r_efa = EDBM_face_find_nearest(vc, &dist);
+ ED_view3d_backbuf_validate(vc);
+
+ if ((dist > 0.0f) && em->selectmode & SCE_SELECT_FACE) {
+ float dist_center = 0.0f;
+ float *dist_center_p = (em->selectmode & (SCE_SELECT_EDGE | SCE_SELECT_VERTEX)) ? &dist_center : NULL;
+ efa = EDBM_face_find_nearest_ex(vc, &dist, dist_center_p, true, use_cycle, &efa_zbuf);
+ if (efa && dist_center_p) {
+ dist = min_ff(dist_margin, dist_center);
+ }
+ }
- dist -= 20; /* since edges select lines, we give dots advantage of 20 pix */
- if (em->selectmode & SCE_SELECT_EDGE)
- *r_eed = EDBM_edge_find_nearest(vc, &dist);
+ if ((dist > 0.0f) && (em->selectmode & SCE_SELECT_EDGE)) {
+ float dist_center = 0.0f;
+ float *dist_center_p = (em->selectmode & SCE_SELECT_VERTEX) ? &dist_center : NULL;
+ eed = EDBM_edge_find_nearest_ex(vc, &dist, dist_center_p, true, use_cycle, &eed_zbuf);
+ if (eed && dist_center_p) {
+ dist = min_ff(dist_margin, dist_center);
+ }
+ }
+
+ if ((dist > 0.0f) && em->selectmode & SCE_SELECT_VERTEX) {
+ eve = EDBM_vert_find_nearest_ex(vc, &dist, true, use_cycle);
+ }
/* return only one of 3 pointers, for frontbuffer redraws */
- if (*r_eed) {
- *r_efa = NULL; *r_eve = NULL;
+ if (eve) {
+ efa = NULL; eed = NULL;
}
- else if (*r_efa) {
- *r_eve = NULL;
+ else if (eed) {
+ efa = NULL;
}
-
- return (*r_eve || *r_eed || *r_efa);
+
+ /* there may be a face under the cursor, who's center if too far away
+ * use this if all else fails, it makes sense to select this */
+ if ((eve || eed || efa) == 0) {
+ if (eed_zbuf) {
+ eed = eed_zbuf;
+ }
+ else if (efa_zbuf) {
+ efa = efa_zbuf;
+ }
+ }
+
+ mval_prev[0] = vc->mval[0];
+ mval_prev[1] = vc->mval[1];
+
+ *r_eve = eve;
+ *r_eed = eed;
+ *r_efa = efa;
+
+ return (eve || eed || efa);
}
+/** \} */
+
+
/* **************** SIMILAR "group" SELECTS. FACE, EDGE AND VERTEX ************** */
static EnumPropertyItem prop_similar_compare_types[] = {
{SIM_CMP_EQ, "EQUAL", 0, "Equal", ""},
@@ -709,6 +985,7 @@ static EnumPropertyItem prop_similar_types[] = {
{SIMFACE_PERIMETER, "PERIMETER", 0, "Perimeter", ""},
{SIMFACE_NORMAL, "NORMAL", 0, "Normal", ""},
{SIMFACE_COPLANAR, "COPLANAR", 0, "Co-planar", ""},
+ {SIMFACE_SMOOTH, "SMOOTH", 0, "Flat/Smooth", ""},
#ifdef WITH_FREESTYLE
{SIMFACE_FREESTYLE, "FREESTYLE_FACE", 0, "Freestyle Face Marks", ""},
#endif
@@ -886,7 +1163,7 @@ static EnumPropertyItem *select_similar_type_itemf(bContext *C, PointerRNA *UNUS
#ifdef WITH_FREESTYLE
const int a_end = SIMFACE_FREESTYLE;
#else
- const int a_end = SIMFACE_COPLANAR;
+ const int a_end = SIMFACE_SMOOTH;
#endif
for (a = SIMFACE_MATERIAL; a <= a_end; a++) {
RNA_enum_items_add_value(&item, &totitem, prop_similar_types, a);
@@ -899,7 +1176,7 @@ static EnumPropertyItem *select_similar_type_itemf(bContext *C, PointerRNA *UNUS
return item;
}
- return NULL;
+ return prop_similar_types;
}
void MESH_OT_select_similar(wmOperatorType *ot)
@@ -925,7 +1202,98 @@ void MESH_OT_select_similar(wmOperatorType *ot)
RNA_def_enum(ot->srna, "compare", prop_similar_compare_types, SIM_CMP_EQ, "Compare", "");
- RNA_def_float(ot->srna, "threshold", 0.0, 0.0, 1.0, "Threshold", "", 0.0, 1.0);
+ RNA_def_float(ot->srna, "threshold", 0.0f, 0.0f, 1.0f, "Threshold", "", 0.0f, 1.0f);
+}
+
+
+/* -------------------------------------------------------------------- */
+/* Select Similar Regions */
+
+static int edbm_select_similar_region_exec(bContext *C, wmOperator *op)
+{
+ Object *obedit = CTX_data_edit_object(C);
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ BMesh *bm = em->bm;
+ bool changed = false;
+
+ /* group vars */
+ int *groups_array;
+ int (*group_index)[2];
+ int group_tot;
+ int i;
+
+ if (bm->totfacesel < 2) {
+ BKE_report(op->reports, RPT_ERROR, "No face regions selected");
+ return OPERATOR_CANCELLED;
+ }
+
+ groups_array = MEM_mallocN(sizeof(*groups_array) * bm->totfacesel, __func__);
+ group_tot = BM_mesh_calc_face_groups(bm, groups_array, &group_index,
+ NULL, NULL,
+ BM_ELEM_SELECT, BM_VERT);
+
+ BM_mesh_elem_table_ensure(bm, BM_FACE);
+
+ for (i = 0; i < group_tot; i++) {
+ ListBase faces_regions;
+ int tot;
+
+ const int fg_sta = group_index[i][0];
+ const int fg_len = group_index[i][1];
+ int j;
+ BMFace **fg = MEM_mallocN(sizeof(*fg) * fg_len, __func__);
+
+
+ for (j = 0; j < fg_len; j++) {
+ fg[j] = BM_face_at_index(bm, groups_array[fg_sta + j]);
+ }
+
+ tot = BM_mesh_region_match(bm, fg, fg_len, &faces_regions);
+
+ MEM_freeN(fg);
+
+ if (tot) {
+ LinkData *link;
+ while ((link = BLI_pophead(&faces_regions))) {
+ BMFace *f, **faces = link->data;
+ unsigned int i = 0;
+ while ((f = faces[i++])) {
+ BM_face_select_set(bm, f, true);
+ }
+ MEM_freeN(faces);
+ MEM_freeN(link);
+
+ changed = true;
+ }
+ }
+ }
+
+ MEM_freeN(groups_array);
+ MEM_freeN(group_index);
+
+ if (changed) {
+ WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit);
+ }
+ else {
+ BKE_report(op->reports, RPT_WARNING, "No matching face regions found");
+ }
+
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_select_similar_region(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Select Similar Regions";
+ ot->idname = "MESH_OT_select_similar_region";
+ ot->description = "Select similar face regions to the current selection";
+
+ /* api callbacks */
+ ot->exec = edbm_select_similar_region_exec;
+ ot->poll = ED_operator_editmesh;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
@@ -1090,7 +1458,7 @@ static int edbm_loop_multiselect_exec(bContext *C, wmOperator *op)
else {
for (edindex = 0; edindex < totedgesel; edindex += 1) {
eed = edarray[edindex];
- walker_select(em, BMW_LOOP, eed, true);
+ walker_select(em, BMW_EDGELOOP, eed, true);
}
EDBM_selectmode_flush(em);
}
@@ -1148,12 +1516,12 @@ static void mouse_mesh_loop_edge(BMEditMesh *em, BMEdge *eed, bool select, bool
{
bool edge_boundary = false;
- /* cycle between BMW_LOOP / BMW_EDGEBOUNDARY */
+ /* cycle between BMW_EDGELOOP / BMW_EDGEBOUNDARY */
if (select_cycle && BM_edge_is_boundary(eed)) {
int tot[2];
/* if the loops selected toggle the boundaries */
- walker_select_count(em, BMW_LOOP, eed, select, false,
+ walker_select_count(em, BMW_EDGELOOP, eed, select, false,
&tot[0], &tot[1]);
if (tot[select] == 0) {
edge_boundary = true;
@@ -1175,7 +1543,7 @@ static void mouse_mesh_loop_edge(BMEditMesh *em, BMEdge *eed, bool select, bool
walker_select(em, BMW_EDGEBOUNDARY, eed, select);
}
else {
- walker_select(em, BMW_LOOP, eed, select);
+ walker_select(em, BMW_EDGELOOP, eed, select);
}
}
@@ -1197,9 +1565,9 @@ static bool mouse_mesh_loop(bContext *C, const int mval[2], bool extend, bool de
em = vc.em;
/* no afterqueue (yet), so we check it now, otherwise the bm_xxxofs indices are bad */
- view3d_validate_backbuf(&vc);
+ ED_view3d_backbuf_validate(&vc);
- eed = EDBM_edge_find_nearest(&vc, &dist);
+ eed = EDBM_edge_find_nearest_ex(&vc, &dist, NULL, true, true, NULL);
if (eed == NULL) {
return false;
}
@@ -1645,7 +2013,7 @@ void EDBM_selectmode_set(BMEditMesh *em)
/**
* Expand & Contract the Selection
- * (used when chaning modes and Ctrl key held)
+ * (used when changing modes and Ctrl key held)
*
* Flush the selection up:
* - vert -> edge
@@ -1953,7 +2321,7 @@ bool EDBM_select_interior_faces(BMEditMesh *em)
ok = true;
BM_ITER_ELEM (eed, &eiter, efa, BM_EDGES_OF_FACE) {
- if (BM_edge_face_count(eed) < 3) {
+ if (!BM_edge_face_count_is_over(eed, 2)) {
ok = false;
break;
}
@@ -1971,16 +2339,107 @@ bool EDBM_select_interior_faces(BMEditMesh *em)
/************************ Select Linked Operator *************************/
-static void linked_limit_default(bContext *C, wmOperator *op)
+struct DelimitData {
+ int cd_loop_type;
+ int cd_loop_offset;
+};
+
+static bool select_linked_delimit_test(
+ BMEdge *e, int delimit,
+ const struct DelimitData *delimit_data)
{
- if (!RNA_struct_property_is_set(op->ptr, "limit")) {
- Object *obedit = CTX_data_edit_object(C);
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
- if (em->selectmode == SCE_SELECT_FACE)
- RNA_boolean_set(op->ptr, "limit", true);
- else
- RNA_boolean_set(op->ptr, "limit", false);
+ BLI_assert(delimit);
+
+ if (delimit & BMO_DELIM_SEAM) {
+ if (BM_elem_flag_test(e, BM_ELEM_SEAM)) {
+ return true;
+ }
+ }
+
+ if (delimit & BMO_DELIM_SHARP) {
+ if (BM_elem_flag_test(e, BM_ELEM_SMOOTH) == 0) {
+ return true;
+ }
+ }
+
+ if (delimit & BMO_DELIM_NORMAL) {
+ if (!BM_edge_is_contiguous(e)) {
+ return true;
+ }
+ }
+
+ if (delimit & BMO_DELIM_MATERIAL) {
+ if (e->l && e->l->radial_next != e->l) {
+ const short mat_nr = e->l->f->mat_nr;
+ BMLoop *l_iter = e->l->radial_next;
+ do {
+ if (l_iter->f->mat_nr != mat_nr) {
+ return true;
+ }
+ } while ((l_iter = l_iter->radial_next) != e->l);
+ }
+ }
+
+ if (delimit & BMO_DELIM_UV) {
+ if (BM_edge_is_contiguous_loop_cd(e, delimit_data->cd_loop_type, delimit_data->cd_loop_offset) == 0) {
+ return true;
+ }
}
+
+ return false;
+}
+
+static void select_linked_delimit_validate(BMesh *bm, int *delimit)
+{
+ if ((*delimit) & BMO_DELIM_UV) {
+ if (!CustomData_has_layer(&bm->ldata, CD_MLOOPUV)) {
+ (*delimit) &= ~BMO_DELIM_UV;
+ }
+ }
+}
+
+static void select_linked_delimit_begin(BMesh *bm, short selectmode, int delimit)
+{
+ struct DelimitData delimit_data = {0};
+
+ BMIter iter;
+ BMEdge *e;
+
+ if (delimit & BMO_DELIM_UV) {
+ delimit_data.cd_loop_type = CD_MLOOPUV;
+ delimit_data.cd_loop_offset = CustomData_get_offset(&bm->ldata, delimit_data.cd_loop_type);
+ if (delimit_data.cd_loop_offset == -1) {
+ delimit &= ~BMO_DELIM_UV;
+ }
+ }
+
+ /* grr, shouldn't need to alloc BMO flags here */
+ BM_mesh_elem_toolflags_ensure(bm);
+ if (selectmode == SCE_SELECT_FACE) {
+ BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
+ const bool is_walk_ok = (
+ (select_linked_delimit_test(e, delimit, &delimit_data) == false));
+
+ BMO_elem_flag_set(bm, e, BMO_ELE_TAG, is_walk_ok);
+ }
+ }
+ else {
+ /* don't delimit selected edges in vert/edge mode */
+ BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
+ const bool is_walk_ok = (
+ BM_elem_flag_test(e, BM_ELEM_SELECT) ||
+ (select_linked_delimit_test(e, delimit, &delimit_data) == false));
+
+ BMO_elem_flag_set(bm, e, BMO_ELE_TAG, is_walk_ok);
+ }
+ }
+}
+
+static void select_linked_delimit_end(BMEditMesh *em)
+{
+ BMesh *bm = em->bm;
+
+ BM_mesh_elem_toolflags_clear(bm);
}
static int edbm_select_linked_exec(bContext *C, wmOperator *op)
@@ -1989,72 +2448,141 @@ static int edbm_select_linked_exec(bContext *C, wmOperator *op)
BMEditMesh *em = BKE_editmesh_from_object(obedit);
BMesh *bm = em->bm;
BMIter iter;
- BMEdge *e;
BMWalker walker;
- int limit;
+ int delimit = RNA_enum_get(op->ptr, "delimit");
- linked_limit_default(C, op);
+ select_linked_delimit_validate(bm, &delimit);
- limit = RNA_boolean_get(op->ptr, "limit");
+ if (delimit) {
+ select_linked_delimit_begin(em->bm, em->selectmode, delimit);
+ }
- if (em->selectmode == SCE_SELECT_FACE) {
- BMFace *efa;
+ if (em->selectmode & SCE_SELECT_VERTEX) {
+ BMVert *v;
- BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- BM_elem_flag_set(efa, BM_ELEM_TAG, BM_elem_flag_test(efa, BM_ELEM_SELECT));
+ BM_ITER_MESH (v, &iter, em->bm, BM_VERTS_OF_MESH) {
+ BM_elem_flag_set(v, BM_ELEM_TAG, BM_elem_flag_test(v, BM_ELEM_SELECT));
}
- if (limit) {
- /* grr, shouldn't need to alloc BMO flags here */
- BM_mesh_elem_toolflags_ensure(bm);
- BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
- BMO_elem_flag_set(bm, e, BMO_ELE_TAG, !BM_elem_flag_test(e, BM_ELEM_SEAM));
+ BMW_init(&walker, em->bm, delimit ? BMW_LOOP_SHELL_WIRE : BMW_VERT_SHELL,
+ BMW_MASK_NOP, delimit ? BMO_ELE_TAG : BMW_MASK_NOP, BMW_MASK_NOP,
+ BMW_FLAG_TEST_HIDDEN,
+ BMW_NIL_LAY);
+
+ if (delimit) {
+ BM_ITER_MESH (v, &iter, em->bm, BM_VERTS_OF_MESH) {
+ if (BM_elem_flag_test(v, BM_ELEM_TAG)) {
+ BMElem *ele_walk;
+ BMW_ITER (ele_walk, &walker, v) {
+ if (ele_walk->head.htype == BM_LOOP) {
+ BMVert *v_step = ((BMLoop *)ele_walk)->v;
+ BM_vert_select_set(em->bm, v_step, true);
+ BM_elem_flag_disable(v_step, BM_ELEM_TAG);
+ }
+ else {
+ BMEdge *e_step = (BMEdge *)ele_walk;
+ BLI_assert(ele_walk->head.htype == BM_EDGE);
+ BM_edge_select_set(em->bm, e_step, true);
+ BM_elem_flag_disable(e_step->v1, BM_ELEM_TAG);
+ BM_elem_flag_disable(e_step->v2, BM_ELEM_TAG);
+ }
+ }
+ }
+ }
+ }
+ else {
+ BM_ITER_MESH (v, &iter, em->bm, BM_VERTS_OF_MESH) {
+ if (BM_elem_flag_test(v, BM_ELEM_TAG)) {
+ BMEdge *e_walk;
+ BMW_ITER (e_walk, &walker, v) {
+ BM_edge_select_set(em->bm, e_walk, true);
+ BM_elem_flag_disable(e_walk, BM_ELEM_TAG);
+ }
+ }
}
}
- BMW_init(&walker, bm, BMW_ISLAND,
- BMW_MASK_NOP, limit ? BMO_ELE_TAG : BMW_MASK_NOP, BMW_MASK_NOP,
+ BMW_end(&walker);
+
+ EDBM_selectmode_flush(em);
+ }
+ else if (em->selectmode & SCE_SELECT_EDGE) {
+ BMEdge *e;
+
+ BM_ITER_MESH (e, &iter, em->bm, BM_EDGES_OF_MESH) {
+ BM_elem_flag_set(e, BM_ELEM_TAG, BM_elem_flag_test(e, BM_ELEM_SELECT));
+ }
+
+ BMW_init(&walker, em->bm, delimit ? BMW_LOOP_SHELL_WIRE : BMW_VERT_SHELL,
+ BMW_MASK_NOP, delimit ? BMO_ELE_TAG : BMW_MASK_NOP, BMW_MASK_NOP,
BMW_FLAG_TEST_HIDDEN,
BMW_NIL_LAY);
- BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- if (BM_elem_flag_test(efa, BM_ELEM_TAG)) {
- for (efa = BMW_begin(&walker, efa); efa; efa = BMW_step(&walker)) {
- BM_face_select_set(bm, efa, true);
- BM_elem_flag_disable(efa, BM_ELEM_TAG);
+ if (delimit) {
+ BM_ITER_MESH (e, &iter, em->bm, BM_EDGES_OF_MESH) {
+ if (BM_elem_flag_test(e, BM_ELEM_TAG)) {
+ BMElem *ele_walk;
+ BMW_ITER (ele_walk, &walker, e) {
+ if (ele_walk->head.htype == BM_LOOP) {
+ BMLoop *l_step = (BMLoop *)ele_walk;
+ BM_edge_select_set(em->bm, l_step->e, true);
+ BM_edge_select_set(em->bm, l_step->prev->e, true);
+ BM_elem_flag_disable(l_step->e, BM_ELEM_TAG);
+ }
+ else {
+ BMEdge *e_step = (BMEdge *)ele_walk;
+ BLI_assert(ele_walk->head.htype == BM_EDGE);
+ BM_edge_select_set(em->bm, e_step, true);
+ BM_elem_flag_disable(e_step, BM_ELEM_TAG);
+ }
+ }
+ }
+ }
+ }
+ else {
+ BM_ITER_MESH (e, &iter, em->bm, BM_EDGES_OF_MESH) {
+ if (BM_elem_flag_test(e, BM_ELEM_TAG)) {
+ BMEdge *e_walk;
+ BMW_ITER (e_walk, &walker, e) {
+ BM_edge_select_set(em->bm, e_walk, true);
+ BM_elem_flag_disable(e_walk, BM_ELEM_TAG);
+ }
}
}
}
+
BMW_end(&walker);
- if (limit) {
- BM_mesh_elem_toolflags_clear(bm);
- }
+ EDBM_selectmode_flush(em);
}
else {
- BMVert *v;
+ BMFace *f;
- BM_ITER_MESH (v, &iter, em->bm, BM_VERTS_OF_MESH) {
- BM_elem_flag_set(v, BM_ELEM_TAG, BM_elem_flag_test(v, BM_ELEM_SELECT));
+ BM_ITER_MESH (f, &iter, em->bm, BM_FACES_OF_MESH) {
+ BM_elem_flag_set(f, BM_ELEM_TAG, BM_elem_flag_test(f, BM_ELEM_SELECT));
}
- BMW_init(&walker, em->bm, BMW_VERT_SHELL,
- BMW_MASK_NOP, BMW_MASK_NOP, BMW_MASK_NOP,
+ BMW_init(&walker, bm, BMW_ISLAND,
+ BMW_MASK_NOP, delimit ? BMO_ELE_TAG : BMW_MASK_NOP, BMW_MASK_NOP,
BMW_FLAG_TEST_HIDDEN,
BMW_NIL_LAY);
- BM_ITER_MESH (v, &iter, em->bm, BM_VERTS_OF_MESH) {
- if (BM_elem_flag_test(v, BM_ELEM_TAG)) {
- for (e = BMW_begin(&walker, v); e; e = BMW_step(&walker)) {
- BM_edge_select_set(em->bm, e, true);
- BM_elem_flag_disable(e, BM_ELEM_TAG);
+ BM_ITER_MESH (f, &iter, em->bm, BM_FACES_OF_MESH) {
+ if (BM_elem_flag_test(f, BM_ELEM_TAG)) {
+ BMFace *f_walk;
+ BMW_ITER (f_walk, &walker, f) {
+ BM_face_select_set(bm, f_walk, true);
+ BM_elem_flag_disable(f_walk, BM_ELEM_TAG);
}
}
}
+
BMW_end(&walker);
+ }
- EDBM_selectmode_flush(em);
+ if (delimit) {
+ select_linked_delimit_end(em);
}
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit);
@@ -2076,99 +2604,211 @@ void MESH_OT_select_linked(wmOperatorType *ot)
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- RNA_def_boolean(ot->srna, "limit", 0, "Limit by Seams", "");
+ RNA_def_enum_flag(ot->srna, "delimit", mesh_delimit_mode_items, BMO_DELIM_SEAM, "Delimit",
+ "Delimit selected region");
+}
+
+static int edbm_select_linked_pick_exec(bContext *C, wmOperator *op);
+
+static void edbm_select_linked_pick_ex(
+ BMEditMesh *em,
+ BMVert *eve, BMEdge *eed, BMFace *efa,
+ bool sel, int delimit)
+{
+ BMesh *bm = em->bm;
+ BMWalker walker;
+
+ select_linked_delimit_validate(bm, &delimit);
+
+ if (delimit) {
+ select_linked_delimit_begin(bm, em->selectmode, delimit);
+ }
+
+ /* Note: logic closely matches 'edbm_select_linked_exec', keep in sync */
+
+ if ((em->selectmode & SCE_SELECT_VERTEX) && eve) {
+
+ BMW_init(&walker, bm, delimit ? BMW_LOOP_SHELL_WIRE : BMW_VERT_SHELL,
+ BMW_MASK_NOP, delimit ? BMO_ELE_TAG : BMW_MASK_NOP, BMW_MASK_NOP,
+ BMW_FLAG_TEST_HIDDEN,
+ BMW_NIL_LAY);
+
+ if (delimit) {
+ BMElem *ele_walk;
+ BMW_ITER (ele_walk, &walker, eve) {
+ if (ele_walk->head.htype == BM_LOOP) {
+ BMVert *v_step = ((BMLoop *)ele_walk)->v;
+ BM_vert_select_set(bm, v_step, sel);
+ }
+ else {
+ BMEdge *e_step = (BMEdge *)ele_walk;
+ BLI_assert(ele_walk->head.htype == BM_EDGE);
+ BM_edge_select_set(bm, e_step, sel);
+ }
+ }
+ }
+ else {
+ BMEdge *e_walk;
+ BMW_ITER (e_walk, &walker, eve) {
+ BM_edge_select_set(bm, e_walk, sel);
+ }
+ }
+
+ BMW_end(&walker);
+
+ EDBM_selectmode_flush(em);
+ }
+ else if ((em->selectmode & SCE_SELECT_EDGE) && eed) {
+
+ BMW_init(&walker, bm, delimit ? BMW_LOOP_SHELL_WIRE : BMW_VERT_SHELL,
+ BMW_MASK_NOP, delimit ? BMO_ELE_TAG : BMW_MASK_NOP, BMW_MASK_NOP,
+ BMW_FLAG_TEST_HIDDEN,
+ BMW_NIL_LAY);
+
+ if (delimit) {
+ BMElem *ele_walk;
+ BMW_ITER (ele_walk, &walker, eed) {
+ if (ele_walk->head.htype == BM_LOOP) {
+ BMEdge *e_step = ((BMLoop *)ele_walk)->e;
+ BM_edge_select_set(bm, e_step, sel);
+ }
+ else {
+ BMEdge *e_step = (BMEdge *)ele_walk;
+ BLI_assert(ele_walk->head.htype == BM_EDGE);
+ BM_edge_select_set(bm, e_step, sel);
+ }
+ }
+ }
+ else {
+ BMEdge *e_walk;
+ BMW_ITER (e_walk, &walker, eed) {
+ BM_edge_select_set(bm, e_walk, sel);
+ }
+ }
+
+ BMW_end(&walker);
+
+ EDBM_selectmode_flush(em);
+ }
+ else if ((em->selectmode & SCE_SELECT_FACE) && efa) {
+
+ BMW_init(&walker, bm, BMW_ISLAND,
+ BMW_MASK_NOP, delimit ? BMO_ELE_TAG : BMW_MASK_NOP, BMW_MASK_NOP,
+ BMW_FLAG_TEST_HIDDEN,
+ BMW_NIL_LAY);
+
+ {
+ BMFace *f_walk;
+ BMW_ITER (f_walk, &walker, efa) {
+ BM_face_select_set(bm, f_walk, sel);
+ BM_elem_flag_disable(f_walk, BM_ELEM_TAG);
+ }
+ }
+
+ BMW_end(&walker);
+ }
+
+ if (delimit) {
+ select_linked_delimit_end(em);
+ }
}
static int edbm_select_linked_pick_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
Object *obedit = CTX_data_edit_object(C);
ViewContext vc;
- BMesh *bm;
- BMWalker walker;
BMEditMesh *em;
+ BMesh *bm;
BMVert *eve;
- BMEdge *e, *eed;
+ BMEdge *eed;
BMFace *efa;
const bool sel = !RNA_boolean_get(op->ptr, "deselect");
+ const int delimit = RNA_enum_get(op->ptr, "delimit");
+ int index;
- int limit;
-
- linked_limit_default(C, op);
-
- limit = RNA_boolean_get(op->ptr, "limit");
+ if (RNA_struct_property_is_set(op->ptr, "index")) {
+ return edbm_select_linked_pick_exec(C, op);
+ }
/* unified_finednearest needs ogl */
view3d_operator_needs_opengl(C);
-
+
/* setup view context for argument to callbacks */
em_setup_viewcontext(C, &vc);
em = vc.em;
+ bm = em->bm;
- if (em->bm->totedge == 0)
+ if (bm->totedge == 0) {
return OPERATOR_CANCELLED;
-
- bm = em->bm;
+ }
vc.mval[0] = event->mval[0];
vc.mval[1] = event->mval[1];
-
+
/* return warning! */
-
if (unified_findnearest(&vc, &eve, &eed, &efa) == 0) {
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit);
-
+
return OPERATOR_CANCELLED;
}
-
- if (em->selectmode == SCE_SELECT_FACE) {
- BMIter iter;
- if (efa == NULL)
- return OPERATOR_CANCELLED;
+ edbm_select_linked_pick_ex(em, eve, eed, efa, sel, delimit);
- if (limit) {
- /* grr, shouldn't need to alloc BMO flags here */
- BM_mesh_elem_toolflags_ensure(bm);
- /* hflag no-seam --> bmo-tag */
- BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
- BMO_elem_flag_set(bm, e, BMO_ELE_TAG, !BM_elem_flag_test(e, BM_ELEM_SEAM));
- }
- }
-
- /* walk */
- BMW_init(&walker, bm, BMW_ISLAND,
- BMW_MASK_NOP, limit ? BMO_ELE_TAG : BMW_MASK_NOP, BMW_MASK_NOP,
- BMW_FLAG_TEST_HIDDEN,
- BMW_NIL_LAY);
-
- for (efa = BMW_begin(&walker, efa); efa; efa = BMW_step(&walker)) {
- BM_face_select_set(bm, efa, sel);
- }
- BMW_end(&walker);
+ /* to support redo */
+ if ((em->selectmode & SCE_SELECT_VERTEX) && eve) {
+ BM_mesh_elem_index_ensure(bm, BM_VERT);
+ index = BM_elem_index_get(eve);
+ }
+ else if ((em->selectmode & SCE_SELECT_EDGE) && eed) {
+ BM_mesh_elem_index_ensure(bm, BM_EDGE);
+ index = BM_elem_index_get(eed) + bm->totvert;
+ }
+ else if ((em->selectmode & SCE_SELECT_FACE) && efa) {
+ BM_mesh_elem_index_ensure(bm, BM_FACE);
+ index = BM_elem_index_get(efa) + bm->totvert + bm->totedge;
}
else {
- if (efa) {
- eed = BM_FACE_FIRST_LOOP(efa)->e;
- }
- else if (!eed) {
- if (!eve || !eve->e)
- return OPERATOR_CANCELLED;
+ index = -1;
+ }
- eed = eve->e;
- }
+ RNA_int_set(op->ptr, "index", index);
- BMW_init(&walker, bm, BMW_VERT_SHELL,
- BMW_MASK_NOP, BMW_MASK_NOP, BMW_MASK_NOP,
- BMW_FLAG_TEST_HIDDEN,
- BMW_NIL_LAY);
+ WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit);
- for (e = BMW_begin(&walker, eed->v1); e; e = BMW_step(&walker)) {
- BM_edge_select_set(bm, e, sel);
- }
- BMW_end(&walker);
+ return OPERATOR_FINISHED;
+}
- EDBM_selectmode_flush(em);
+
+static int edbm_select_linked_pick_exec(bContext *C, wmOperator *op)
+{
+ Object *obedit = CTX_data_edit_object(C);
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ BMesh *bm = em->bm;
+ int index;
+ BMVert *eve = NULL;
+ BMEdge *eed = NULL;
+ BMFace *efa = NULL;
+ const bool sel = !RNA_boolean_get(op->ptr, "deselect");
+ const int delimit = RNA_enum_get(op->ptr, "delimit");
+
+ index = RNA_int_get(op->ptr, "index");
+ if (index < 0 || index >= (bm->totvert + bm->totedge + bm->totface)) {
+ return OPERATOR_CANCELLED;
+ }
+
+ if (index < bm->totvert) {
+ eve = BM_vert_at_index_find_or_table(bm, index);
+ }
+ else if (index < (bm->totvert + bm->totedge)) {
+ index -= bm->totvert;
+ eed = BM_edge_at_index_find_or_table(bm, index);
}
+ else if (index < (bm->totvert + bm->totedge + bm->totface)) {
+ index -= (bm->totvert + bm->totedge);
+ efa = BM_face_at_index_find_or_table(bm, index);
+ }
+
+ edbm_select_linked_pick_ex(em, eve, eed, efa, sel, delimit);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit);
@@ -2177,6 +2817,8 @@ static int edbm_select_linked_pick_invoke(bContext *C, wmOperator *op, const wmE
void MESH_OT_select_linked_pick(wmOperatorType *ot)
{
+ PropertyRNA *prop;
+
/* identifiers */
ot->name = "Select Linked";
ot->idname = "MESH_OT_select_linked_pick";
@@ -2184,13 +2826,19 @@ void MESH_OT_select_linked_pick(wmOperatorType *ot)
/* api callbacks */
ot->invoke = edbm_select_linked_pick_invoke;
+ ot->exec = edbm_select_linked_pick_exec;
ot->poll = ED_operator_editmesh;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
RNA_def_boolean(ot->srna, "deselect", 0, "Deselect", "");
- RNA_def_boolean(ot->srna, "limit", 0, "Limit by Seams", "");
+ RNA_def_enum_flag(ot->srna, "delimit", mesh_delimit_mode_items, BMO_DELIM_SEAM, "Delimit",
+ "Delimit selected region");
+
+ /* use for redo */
+ prop = RNA_def_int(ot->srna, "index", -1, -1, INT_MAX, "", "", 0, INT_MAX);
+ RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
}
@@ -2381,12 +3029,13 @@ void MESH_OT_select_mirror(wmOperatorType *ot)
/* ******************** **************** */
-static int edbm_select_more_exec(bContext *C, wmOperator *UNUSED(op))
+static int edbm_select_more_exec(bContext *C, wmOperator *op)
{
Object *obedit = CTX_data_edit_object(C);
BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ const bool use_face_step = RNA_boolean_get(op->ptr, "use_face_step");
- EDBM_select_more(em);
+ EDBM_select_more(em, use_face_step);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit);
return OPERATOR_FINISHED;
@@ -2405,14 +3054,17 @@ void MESH_OT_select_more(wmOperatorType *ot)
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ RNA_def_boolean(ot->srna, "use_face_step", true, "Face Step", "Connected faces (instead of edges)");
}
-static int edbm_select_less_exec(bContext *C, wmOperator *UNUSED(op))
+static int edbm_select_less_exec(bContext *C, wmOperator *op)
{
Object *obedit = CTX_data_edit_object(C);
BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ const bool use_face_step = RNA_boolean_get(op->ptr, "use_face_step");
- EDBM_select_less(em);
+ EDBM_select_less(em, use_face_step);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit);
return OPERATOR_FINISHED;
@@ -2431,6 +3083,8 @@ void MESH_OT_select_less(wmOperatorType *ot)
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ RNA_def_boolean(ot->srna, "use_face_step", true, "Face Step", "Connected faces (instead of edges)");
}
/**
@@ -2457,7 +3111,7 @@ static bool bm_edge_is_select_isolated(BMEdge *e)
/* Walk all reachable elements of the same type as h_act in breadth-first
* order, starting from h_act. Deselects elements if the depth when they
* are reached is not a multiple of "nth". */
-static void walker_deselect_nth(BMEditMesh *em, int nth, int offset, BMHeader *h_act)
+static void walker_deselect_nth(BMEditMesh *em, int nth, int skip, int offset, BMHeader *h_act)
{
BMElem *ele;
BMesh *bm = em->bm;
@@ -2523,7 +3177,8 @@ static void walker_deselect_nth(BMEditMesh *em, int nth, int offset, BMHeader *h
for (ele = BMW_begin(&walker, h_act); ele != NULL; ele = BMW_step(&walker)) {
if (!BM_elem_flag_test(ele, BM_ELEM_TAG)) {
/* Deselect elements that aren't at "nth" depth from active */
- if ((offset + BMW_current_depth(&walker)) % nth) {
+ const int depth = BMW_current_depth(&walker) - 1;
+ if ((offset + depth) % (skip + nth) >= skip) {
BM_elem_select_set(bm, ele, false);
}
BM_elem_flag_enable(ele, BM_ELEM_TAG);
@@ -2590,7 +3245,7 @@ static void deselect_nth_active(BMEditMesh *em, BMVert **r_eve, BMEdge **r_eed,
}
}
-static bool edbm_deselect_nth(BMEditMesh *em, int nth, int offset)
+static bool edbm_deselect_nth(BMEditMesh *em, int nth, int skip, int offset)
{
BMVert *v;
BMEdge *e;
@@ -2599,15 +3254,15 @@ static bool edbm_deselect_nth(BMEditMesh *em, int nth, int offset)
deselect_nth_active(em, &v, &e, &f);
if (v) {
- walker_deselect_nth(em, nth, offset, &v->head);
+ walker_deselect_nth(em, nth, skip, offset, &v->head);
return true;
}
else if (e) {
- walker_deselect_nth(em, nth, offset, &e->head);
+ walker_deselect_nth(em, nth, skip, offset, &e->head);
return true;
}
else if (f) {
- walker_deselect_nth(em, nth, offset, &f->head);
+ walker_deselect_nth(em, nth, skip, offset, &f->head);
return true;
}
@@ -2618,15 +3273,14 @@ static int edbm_select_nth_exec(bContext *C, wmOperator *op)
{
Object *obedit = CTX_data_edit_object(C);
BMEditMesh *em = BKE_editmesh_from_object(obedit);
- const int nth = RNA_int_get(op->ptr, "nth");
+ const int nth = RNA_int_get(op->ptr, "nth") - 1;
+ const int skip = RNA_int_get(op->ptr, "skip");
int offset = RNA_int_get(op->ptr, "offset");
/* so input of offset zero ends up being (nth - 1) */
- offset = mod_i(offset, nth);
- /* depth starts at 1, this keeps active item selected */
- offset -= 1;
+ offset = mod_i(offset, nth + skip);
- if (edbm_deselect_nth(em, nth, offset) == false) {
+ if (edbm_deselect_nth(em, nth, skip, offset) == false) {
BKE_report(op->reports, RPT_ERROR, "Mesh has no active vert/edge/face");
return OPERATOR_CANCELLED;
}
@@ -2652,6 +3306,7 @@ void MESH_OT_select_nth(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
RNA_def_int(ot->srna, "nth", 2, 2, INT_MAX, "Nth Selection", "", 2, 100);
+ RNA_def_int(ot->srna, "skip", 1, 1, INT_MAX, "Skip", "", 1, 100);
RNA_def_int(ot->srna, "offset", 0, INT_MIN, INT_MAX, "Offset", "", -100, 100);
}
@@ -2842,7 +3497,7 @@ static int edbm_select_non_manifold_exec(bContext *C, wmOperator *op)
if ((use_wire && BM_edge_is_wire(e)) ||
(use_boundary && BM_edge_is_boundary(e)) ||
(use_non_contiguous && (BM_edge_is_manifold(e) && !BM_edge_is_contiguous(e))) ||
- (use_multi_face && (BM_edge_face_count(e) > 2)))
+ (use_multi_face && (BM_edge_face_count_is_over(e, 2))))
{
/* check we never select perfect edge (in test above) */
BLI_assert(!(BM_edge_is_manifold(e) && BM_edge_is_contiguous(e)));
@@ -2952,8 +3607,8 @@ void MESH_OT_select_random(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
/* props */
- RNA_def_float_percentage(ot->srna, "percent", 50.f, 0.0f, 100.0f,
- "Percent", "Percentage of elements to select randomly", 0.f, 100.0f);
+ RNA_def_float_percentage(ot->srna, "percent", 50.0f, 0.0f, 100.0f,
+ "Percent", "Percentage of elements to select randomly", 0.0f, 100.0f);
WM_operator_properties_select_action_simple(ot, SEL_SELECT);
}
@@ -3041,7 +3696,7 @@ static int edbm_select_axis_exec(bContext *C, wmOperator *op)
else {
BMVert *v;
BMIter iter;
- const float limit = CTX_data_tool_settings(C)->doublimit; // XXX
+ const float limit = RNA_float_get(op->ptr, "threshold");
float value = v_act->co[axis];
if (mode == 0)
@@ -3106,6 +3761,7 @@ void MESH_OT_select_axis(wmOperatorType *ot)
/* properties */
RNA_def_enum(ot->srna, "mode", axis_mode_items, 0, "Axis Mode", "Axis side to use when selecting");
RNA_def_enum(ot->srna, "axis", axis_items_xyz, 0, "Axis", "Select the axis to compare each vertex on");
+ RNA_def_float(ot->srna, "threshold", 0.0001f, 0.000001f, 50.0f, "Threshold", "", 0.00001f, 10.0f);
}
@@ -3267,8 +3923,8 @@ static int loop_find_region(BMLoop *l, int flag,
static int verg_radial(const void *va, const void *vb)
{
- BMEdge *e_a = *((BMEdge **)va);
- BMEdge *e_b = *((BMEdge **)vb);
+ const BMEdge *e_a = *((const BMEdge **)va);
+ const BMEdge *e_b = *((const BMEdge **)vb);
int a, b;
a = BM_edge_face_count(e_a);
diff --git a/source/blender/editors/mesh/editmesh_tools.c b/source/blender/editors/mesh/editmesh_tools.c
index 3f1023b7fb4..d3937188358 100644
--- a/source/blender/editors/mesh/editmesh_tools.c
+++ b/source/blender/editors/mesh/editmesh_tools.c
@@ -55,7 +55,7 @@
#include "BKE_main.h"
#include "BKE_editmesh.h"
-#include "BLF_translation.h"
+#include "BLT_translation.h"
#include "RNA_define.h"
#include "RNA_access.h"
@@ -90,13 +90,13 @@ static int edbm_subdivide_exec(bContext *C, wmOperator *op)
const float along_normal = RNA_float_get(op->ptr, "fractal_along_normal");
if (RNA_boolean_get(op->ptr, "quadtri") &&
- RNA_enum_get(op->ptr, "quadcorner") == SUBD_STRAIGHT_CUT)
+ RNA_enum_get(op->ptr, "quadcorner") == SUBD_CORNER_STRAIGHT_CUT)
{
- RNA_enum_set(op->ptr, "quadcorner", SUBD_INNERVERT);
+ RNA_enum_set(op->ptr, "quadcorner", SUBD_CORNER_INNERVERT);
}
BM_mesh_esubdivide(em->bm, BM_ELEM_SELECT,
- smooth, SUBD_FALLOFF_ROOT, false,
+ smooth, SUBD_FALLOFF_INVSQUARE, false,
fractal, along_normal,
cuts,
SUBDIV_SELECT_ORIG, RNA_enum_get(op->ptr, "quadcorner"),
@@ -110,10 +110,10 @@ static int edbm_subdivide_exec(bContext *C, wmOperator *op)
/* Note, these values must match delete_mesh() event values */
static EnumPropertyItem prop_mesh_cornervert_types[] = {
- {SUBD_INNERVERT, "INNERVERT", 0, "Inner Vert", ""},
- {SUBD_PATH, "PATH", 0, "Path", ""},
- {SUBD_STRAIGHT_CUT, "STRAIGHT_CUT", 0, "Straight Cut", ""},
- {SUBD_FAN, "FAN", 0, "Fan", ""},
+ {SUBD_CORNER_INNERVERT, "INNERVERT", 0, "Inner Vert", ""},
+ {SUBD_CORNER_PATH, "PATH", 0, "Path", ""},
+ {SUBD_CORNER_STRAIGHT_CUT, "STRAIGHT_CUT", 0, "Straight Cut", ""},
+ {SUBD_CORNER_FAN, "FAN", 0, "Fan", ""},
{0, NULL, 0, NULL, NULL}
};
@@ -134,19 +134,20 @@ void MESH_OT_subdivide(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
/* properties */
- prop = RNA_def_int(ot->srna, "number_cuts", 1, 1, INT_MAX, "Number of Cuts", "", 1, 10);
+ prop = RNA_def_int(ot->srna, "number_cuts", 1, 1, 100, "Number of Cuts", "", 1, 10);
/* avoid re-using last var because it can cause _very_ high poly meshes and annoy users (or worse crash) */
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
- RNA_def_float(ot->srna, "smoothness", 0.0f, 0.0f, FLT_MAX, "Smoothness", "Smoothness factor", 0.0f, 1.0f);
+ RNA_def_float(ot->srna, "smoothness", 0.0f, 0.0f, 1e3f, "Smoothness", "Smoothness factor", 0.0f, 1.0f);
RNA_def_boolean(ot->srna, "quadtri", 0, "Quad/Tri Mode", "Tries to prevent ngons");
- RNA_def_enum(ot->srna, "quadcorner", prop_mesh_cornervert_types, SUBD_STRAIGHT_CUT,
+ RNA_def_enum(ot->srna, "quadcorner", prop_mesh_cornervert_types, SUBD_CORNER_STRAIGHT_CUT,
"Quad Corner Type", "How to subdivide quad corners (anything other than Straight Cut will prevent ngons)");
- RNA_def_float(ot->srna, "fractal", 0.0f, 0.0f, FLT_MAX, "Fractal", "Fractal randomness factor", 0.0f, 1000.0f);
- RNA_def_float(ot->srna, "fractal_along_normal", 0.0f, 0.0f, 1.0f, "Along Normal", "Apply fractal displacement along normal only", 0.0f, 1.0f);
- RNA_def_int(ot->srna, "seed", 0, 0, 10000, "Random Seed", "Seed for the random number generator", 0, 50);
+ RNA_def_float(ot->srna, "fractal", 0.0f, 0.0f, 1e6f, "Fractal", "Fractal randomness factor", 0.0f, 1000.0f);
+ RNA_def_float(ot->srna, "fractal_along_normal", 0.0f, 0.0f, 1.0f,
+ "Along Normal", "Apply fractal displacement along normal only", 0.0f, 1.0f);
+ RNA_def_int(ot->srna, "seed", 0, 0, INT_MAX, "Random Seed", "Seed for the random number generator", 0, 255);
}
/* -------------------------------------------------------------------- */
@@ -176,24 +177,24 @@ static void mesh_operator_edgering_props(wmOperatorType *ot, const int cuts_defa
PropertyRNA *prop;
- prop = RNA_def_int(ot->srna, "number_cuts", cuts_default, 0, INT_MAX, "Number of Cuts", "", 0, 64);
+ prop = RNA_def_int(ot->srna, "number_cuts", cuts_default, 0, 1000, "Number of Cuts", "", 0, 64);
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
RNA_def_enum(ot->srna, "interpolation", prop_subd_edgering_types, SUBD_RING_INTERP_PATH,
"Interpolation", "Interpolation method");
- RNA_def_float(ot->srna, "smoothness", 1.0f, 0.0f, FLT_MAX,
+ RNA_def_float(ot->srna, "smoothness", 1.0f, 0.0f, 1e3f,
"Smoothness", "Smoothness factor", 0.0f, 2.0f);
/* profile-shape */
- RNA_def_float(ot->srna, "profile_shape_factor", 0.0f, -FLT_MAX, FLT_MAX,
- "Profile Factor", "", -2.0f, 2.0f);
+ RNA_def_float(ot->srna, "profile_shape_factor", 0.0f, -1e3f, 1e3f,
+ "Profile Factor", "How much intermediary new edges are shrunk/expanded", -2.0f, 2.0f);
prop = RNA_def_property(ot->srna, "profile_shape", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, proportional_falloff_curve_only_items);
RNA_def_property_enum_default(prop, PROP_SMOOTH);
RNA_def_property_ui_text(prop, "Profile Shape", "Shape of the profile");
- RNA_def_property_translation_context(prop, BLF_I18NCONTEXT_ID_CURVE); /* Abusing id_curve :/ */
+ RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_CURVE); /* Abusing id_curve :/ */
}
static void mesh_operator_edgering_props_get(wmOperator *op, struct EdgeRingOpSubdProps *op_props)
@@ -289,7 +290,7 @@ void MESH_OT_unsubdivide(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
/* props */
- RNA_def_int(ot->srna, "iterations", 2, 1, INT_MAX, "Iterations", "Number of times to unsubdivide", 1, 100);
+ RNA_def_int(ot->srna, "iterations", 2, 1, 1000, "Iterations", "Number of times to unsubdivide", 1, 100);
}
void EMBM_project_snap_verts(bContext *C, ARegion *ar, BMEditMesh *em)
@@ -313,6 +314,16 @@ void EMBM_project_snap_verts(bContext *C, ARegion *ar, BMEditMesh *em)
}
}
+
+/* Note, these values must match delete_mesh() event values */
+enum {
+ MESH_DELETE_VERT = 0,
+ MESH_DELETE_EDGE = 1,
+ MESH_DELETE_FACE = 2,
+ MESH_DELETE_EDGE_FACE = 3,
+ MESH_DELETE_ONLY_FACE = 4,
+};
+
static void edbm_report_delete_info(ReportList *reports, BMesh *bm, const int totelem[3])
{
BKE_reportf(reports, RPT_INFO,
@@ -320,45 +331,38 @@ static void edbm_report_delete_info(ReportList *reports, BMesh *bm, const int to
totelem[0] - bm->totvert, totelem[1] - bm->totedge, totelem[2] - bm->totface);
}
-/* Note, these values must match delete_mesh() event values */
-static EnumPropertyItem prop_mesh_delete_types[] = {
- {0, "VERT", 0, "Vertices", ""},
- {1, "EDGE", 0, "Edges", ""},
- {2, "FACE", 0, "Faces", ""},
- {3, "EDGE_FACE", 0, "Only Edges & Faces", ""},
- {4, "ONLY_FACE", 0, "Only Faces", ""},
- {0, NULL, 0, NULL, NULL}
-};
-
static int edbm_delete_exec(bContext *C, wmOperator *op)
{
Object *obedit = CTX_data_edit_object(C);
BMEditMesh *em = BKE_editmesh_from_object(obedit);
const int type = RNA_enum_get(op->ptr, "type");
- if (type == 0) {
- if (!EDBM_op_callf(em, op, "delete geom=%hv context=%i", BM_ELEM_SELECT, DEL_VERTS)) /* Erase Vertices */
- return OPERATOR_CANCELLED;
- }
- else if (type == 1) {
- if (!EDBM_op_callf(em, op, "delete geom=%he context=%i", BM_ELEM_SELECT, DEL_EDGES)) /* Erase Edges */
- return OPERATOR_CANCELLED;
- }
- else if (type == 2) {
- if (!EDBM_op_callf(em, op, "delete geom=%hf context=%i", BM_ELEM_SELECT, DEL_FACES)) /* Erase Faces */
- return OPERATOR_CANCELLED;
- }
- else if (type == 3) {
- if (!EDBM_op_callf(em, op, "delete geom=%hef context=%i", BM_ELEM_SELECT, DEL_EDGESFACES)) /* Edges and Faces */
- return OPERATOR_CANCELLED;
- }
- else if (type == 4) {
- //"Erase Only Faces";
- if (!EDBM_op_callf(em, op, "delete geom=%hf context=%i",
- BM_ELEM_SELECT, DEL_ONLYFACES))
- {
- return OPERATOR_CANCELLED;
- }
+ switch (type) {
+ case MESH_DELETE_VERT:
+ if (!EDBM_op_callf(em, op, "delete geom=%hv context=%i", BM_ELEM_SELECT, DEL_VERTS)) /* Erase Vertices */
+ return OPERATOR_CANCELLED;
+ break;
+ case MESH_DELETE_EDGE:
+ if (!EDBM_op_callf(em, op, "delete geom=%he context=%i", BM_ELEM_SELECT, DEL_EDGES)) /* Erase Edges */
+ return OPERATOR_CANCELLED;
+ break;
+ case MESH_DELETE_FACE:
+ if (!EDBM_op_callf(em, op, "delete geom=%hf context=%i", BM_ELEM_SELECT, DEL_FACES)) /* Erase Faces */
+ return OPERATOR_CANCELLED;
+ break;
+ case MESH_DELETE_EDGE_FACE:
+ /* Edges and Faces */
+ if (!EDBM_op_callf(em, op, "delete geom=%hef context=%i", BM_ELEM_SELECT, DEL_EDGESFACES))
+ return OPERATOR_CANCELLED;
+ break;
+ case MESH_DELETE_ONLY_FACE:
+ /* Only faces. */
+ if (!EDBM_op_callf(em, op, "delete geom=%hf context=%i", BM_ELEM_SELECT, DEL_ONLYFACES))
+ return OPERATOR_CANCELLED;
+ break;
+ default:
+ BLI_assert(0);
+ break;
}
EDBM_flag_disable_all(em, BM_ELEM_SELECT);
@@ -370,6 +374,15 @@ static int edbm_delete_exec(bContext *C, wmOperator *op)
void MESH_OT_delete(wmOperatorType *ot)
{
+ static EnumPropertyItem prop_mesh_delete_types[] = {
+ {MESH_DELETE_VERT, "VERT", 0, "Vertices", ""},
+ {MESH_DELETE_EDGE, "EDGE", 0, "Edges", ""},
+ {MESH_DELETE_FACE, "FACE", 0, "Faces", ""},
+ {MESH_DELETE_EDGE_FACE, "EDGE_FACE", 0, "Only Edges & Faces", ""},
+ {MESH_DELETE_ONLY_FACE, "ONLY_FACE", 0, "Only Faces", ""},
+ {0, NULL, 0, NULL, NULL}
+ };
+
/* identifiers */
ot->name = "Delete";
ot->description = "Delete selected vertices, edges or faces";
@@ -385,7 +398,8 @@ void MESH_OT_delete(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
/* props */
- ot->prop = RNA_def_enum(ot->srna, "type", prop_mesh_delete_types, 0, "Type", "Method used for deleting mesh data");
+ ot->prop = RNA_def_enum(ot->srna, "type", prop_mesh_delete_types, MESH_DELETE_VERT,
+ "Type", "Method used for deleting mesh data");
}
@@ -492,7 +506,7 @@ static int edbm_collapse_edge_exec(bContext *C, wmOperator *op)
Object *obedit = CTX_data_edit_object(C);
BMEditMesh *em = BKE_editmesh_from_object(obedit);
- if (!EDBM_op_callf(em, op, "collapse edges=%he", BM_ELEM_SELECT))
+ if (!EDBM_op_callf(em, op, "collapse edges=%he uvs=%b", BM_ELEM_SELECT, true))
return OPERATOR_CANCELLED;
EDBM_update_generic(em, true, true);
@@ -877,23 +891,49 @@ static int edbm_vert_connect_exec(bContext *C, wmOperator *op)
BMEditMesh *em = BKE_editmesh_from_object(obedit);
BMesh *bm = em->bm;
BMOperator bmop;
- const bool is_pair = (bm->totvertsel == 2);
- int len;
-
+ bool is_pair = (bm->totvertsel == 2);
+ int len = 0;
+ bool check_degenerate = true;
+ const int verts_len = bm->totvertsel;
+ BMVert **verts;
+
+ verts = MEM_mallocN(sizeof(*verts) * verts_len, __func__);
+ {
+ BMIter iter;
+ BMVert *v;
+ int i = 0;
+
+ BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
+ if (BM_elem_flag_test(v, BM_ELEM_SELECT)) {
+ verts[i++] = v;
+ }
+ }
+
+ if (is_pair) {
+ if (BM_vert_pair_share_face_check_cb(
+ verts[0], verts[1],
+ BM_elem_cb_check_hflag_disabled_simple(BMFace *, BM_ELEM_HIDDEN)))
+ {
+ check_degenerate = false;
+ is_pair = false;
+ }
+ }
+ }
+
if (is_pair) {
if (!EDBM_op_init(em, &bmop, op,
- "connect_vert_pair verts=%hv verts_exclude=%hv faces_exclude=%hf",
- BM_ELEM_SELECT, BM_ELEM_HIDDEN, BM_ELEM_HIDDEN))
+ "connect_vert_pair verts=%eb verts_exclude=%hv faces_exclude=%hf",
+ verts, verts_len, BM_ELEM_HIDDEN, BM_ELEM_HIDDEN))
{
- return OPERATOR_CANCELLED;
+ goto finally;
}
}
else {
if (!EDBM_op_init(em, &bmop, op,
- "connect_verts verts=%hv faces_exclude=%hf check_degenerate=%b",
- BM_ELEM_SELECT, BM_ELEM_HIDDEN, true))
+ "connect_verts verts=%eb faces_exclude=%hf check_degenerate=%b",
+ verts, verts_len, BM_ELEM_HIDDEN, check_degenerate))
{
- return OPERATOR_CANCELLED;
+ goto finally;
}
}
@@ -908,15 +948,18 @@ static int edbm_vert_connect_exec(bContext *C, wmOperator *op)
}
if (!EDBM_op_finish(em, &bmop, op, true)) {
- return OPERATOR_CANCELLED;
+ len = 0;
}
else {
EDBM_selectmode_flush(em); /* so newly created edges get the selection state from the vertex */
EDBM_update_generic(em, true, true);
-
- return len ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
}
+
+
+finally:
+ MEM_freeN(verts);
+ return len ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
}
void MESH_OT_vert_connect(wmOperatorType *ot)
@@ -924,7 +967,7 @@ void MESH_OT_vert_connect(wmOperatorType *ot)
/* identifiers */
ot->name = "Vertex Connect";
ot->idname = "MESH_OT_vert_connect";
- ot->description = "Connect 2 vertices of a face by an edge, splitting the face in two";
+ ot->description = "Connect selected vertices of faces, splitting the face";
/* api callbacks */
ot->exec = edbm_vert_connect_exec;
@@ -935,6 +978,308 @@ void MESH_OT_vert_connect(wmOperatorType *ot)
}
+/**
+ * check that endpoints are verts and only have a single selected edge connected.
+ */
+static bool bm_vert_is_select_history_open(BMesh *bm)
+{
+ BMEditSelection *ele_a = bm->selected.first;
+ BMEditSelection *ele_b = bm->selected.last;
+ if ((ele_a->htype == BM_VERT) &&
+ (ele_b->htype == BM_VERT))
+ {
+ if ((BM_iter_elem_count_flag(BM_EDGES_OF_VERT, (BMVert *)ele_a->ele, BM_ELEM_SELECT, true) == 1) &&
+ (BM_iter_elem_count_flag(BM_EDGES_OF_VERT, (BMVert *)ele_b->ele, BM_ELEM_SELECT, true) == 1))
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+static bool bm_vert_connect_pair(BMesh *bm, BMVert *v_a, BMVert *v_b)
+{
+ BMOperator bmop;
+ BMVert **verts;
+ const int totedge_orig = bm->totedge;
+
+ BMO_op_init(bm, &bmop, BMO_FLAG_DEFAULTS, "connect_vert_pair");
+
+ verts = BMO_slot_buffer_alloc(&bmop, bmop.slots_in, "verts", 2);
+ verts[0] = v_a;
+ verts[1] = v_b;
+
+ BM_vert_normal_update(verts[0]);
+ BM_vert_normal_update(verts[1]);
+
+ BMO_op_exec(bm, &bmop);
+ BMO_slot_buffer_hflag_enable(bm, bmop.slots_out, "edges.out", BM_EDGE, BM_ELEM_SELECT, true);
+ BMO_op_finish(bm, &bmop);
+ return (bm->totedge != totedge_orig);
+}
+
+static bool bm_vert_connect_select_history(BMesh *bm)
+{
+ /* Logic is as follows:
+ *
+ * - If there are any isolated/wire verts - connect as edges.
+ * - Otherwise connect faces.
+ * - If all edges have been created already, closed the loop.
+ */
+ if (BLI_listbase_count_ex(&bm->selected, 2) == 2 && (bm->totvertsel > 2)) {
+ BMEditSelection *ese;
+ int tot = 0;
+ bool changed = false;
+ bool has_wire = false;
+ // bool all_verts;
+
+ /* ensure all verts have history */
+ for (ese = bm->selected.first; ese; ese = ese->next, tot++) {
+ BMVert *v;
+ if (ese->htype != BM_VERT) {
+ break;
+ }
+ v = (BMVert *)ese->ele;
+ if ((has_wire == false) && ((v->e == NULL) || BM_vert_is_wire(v))) {
+ has_wire = true;
+ }
+ }
+ // all_verts = (ese == NULL);
+
+ if (has_wire == false) {
+ /* all verts have faces , connect verts via faces! */
+ if (tot == bm->totvertsel) {
+ BMEditSelection *ese_last;
+ ese_last = bm->selected.first;
+ ese = ese_last->next;
+
+ do {
+
+ if (BM_edge_exists((BMVert *)ese_last->ele, (BMVert *)ese->ele)) {
+ /* pass, edge exists (and will be selected) */
+ }
+ else {
+ changed |= bm_vert_connect_pair(bm, (BMVert *)ese_last->ele, (BMVert *)ese->ele);
+ }
+ } while ((ese_last = ese),
+ (ese = ese->next));
+
+ if (changed) {
+ return true;
+ }
+ }
+
+ if (changed == false) {
+ /* existing loops: close the selection */
+ if (bm_vert_is_select_history_open(bm)) {
+ changed |= bm_vert_connect_pair(
+ bm,
+ (BMVert *)((BMEditSelection *)bm->selected.first)->ele,
+ (BMVert *)((BMEditSelection *)bm->selected.last)->ele);
+
+ if (changed) {
+ return true;
+ }
+ }
+ }
+ }
+
+ else {
+ /* no faces, simply connect the verts by edges */
+ BMEditSelection *ese_prev;
+ ese_prev = bm->selected.first;
+ ese = ese_prev->next;
+
+
+ do {
+ if (BM_edge_exists((BMVert *)ese_prev->ele, (BMVert *)ese->ele)) {
+ /* pass, edge exists (and will be selected) */
+ }
+ else {
+ BMEdge *e;
+ e = BM_edge_create(bm, (BMVert *)ese_prev->ele, (BMVert *)ese->ele, NULL, 0);
+ BM_edge_select_set(bm, e, true);
+ changed = true;
+ }
+ } while ((ese_prev = ese),
+ (ese = ese->next));
+
+ if (changed == false) {
+ /* existing loops: close the selection */
+ if (bm_vert_is_select_history_open(bm)) {
+ BMEdge *e;
+ ese_prev = bm->selected.first;
+ ese = bm->selected.last;
+ e = BM_edge_create(bm, (BMVert *)ese_prev->ele, (BMVert *)ese->ele, NULL, 0);
+ BM_edge_select_set(bm, e, true);
+ }
+ }
+
+ return true;
+ }
+ }
+
+ return false;
+}
+
+/**
+ * Convert an edge selection to a temp vertex selection
+ * (which must be cleared after use as a path to connect).
+ */
+static bool bm_vert_connect_select_history_edge_to_vert_path(BMesh *bm, ListBase *r_selected)
+{
+ ListBase selected_orig = {NULL, NULL};
+ BMEditSelection *ese;
+ int edges_len = 0;
+ bool side = false;
+
+ /* first check all edges are OK */
+ for (ese = bm->selected.first; ese; ese = ese->next) {
+ if (ese->htype == BM_EDGE) {
+ edges_len += 1;
+ }
+ else {
+ return false;
+ }
+ }
+ /* if this is a mixed selection, bail out! */
+ if (bm->totedgesel != edges_len) {
+ return false;
+ }
+
+ SWAP(ListBase, bm->selected, selected_orig);
+
+ /* convert edge selection into 2 ordered loops (where the first edge ends up in the middle) */
+ for (ese = selected_orig.first; ese; ese = ese->next) {
+ BMEdge *e_curr = (BMEdge *)ese->ele;
+ BMEdge *e_prev = ese->prev ? (BMEdge *)ese->prev->ele : NULL;
+ BMLoop *l_curr;
+ BMLoop *l_prev;
+ BMVert *v;
+
+ if (e_prev) {
+ BMFace *f = BM_edge_pair_share_face_by_len(e_curr, e_prev, &l_curr, &l_prev, true);
+ if (f) {
+ if ((e_curr->v1 != l_curr->v) == (e_prev->v1 != l_prev->v)) {
+ side = !side;
+ }
+ }
+ else if (is_quad_flip_v3(e_curr->v1->co, e_curr->v2->co, e_prev->v2->co, e_prev->v1->co)) {
+ side = !side;
+ }
+ }
+
+ v = (&e_curr->v1)[side];
+ if (!bm->selected.last || (BMVert *)((BMEditSelection *)bm->selected.last)->ele != v) {
+ BM_select_history_store_notest(bm, v);
+ }
+
+ v = (&e_curr->v1)[!side];
+ if (!bm->selected.first || (BMVert *)((BMEditSelection *)bm->selected.first)->ele != v) {
+ BM_select_history_store_head_notest(bm, v);
+ }
+
+ e_prev = e_curr;
+ }
+
+ *r_selected = bm->selected;
+ bm->selected = selected_orig;
+
+ return true;
+}
+
+static int edbm_vert_connect_path_exec(bContext *C, wmOperator *op)
+{
+ Object *obedit = CTX_data_edit_object(C);
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ BMesh *bm = em->bm;
+ bool is_pair = (em->bm->totvertsel == 2);
+ ListBase selected_orig = {NULL, NULL};
+ int retval;
+
+ /* when there is only 2 vertices, we can ignore selection order */
+ if (is_pair) {
+ return edbm_vert_connect_exec(C, op);
+ }
+
+ if (bm->selected.first) {
+ BMEditSelection *ese = bm->selected.first;
+ if (ese->htype == BM_EDGE) {
+ if (bm_vert_connect_select_history_edge_to_vert_path(bm, &selected_orig)) {
+ SWAP(ListBase, bm->selected, selected_orig);
+ }
+ }
+ }
+
+ if (bm_vert_connect_select_history(bm)) {
+ EDBM_selectmode_flush(em);
+ EDBM_update_generic(em, true, true);
+ retval = OPERATOR_FINISHED;
+ }
+ else {
+ BKE_report(op->reports, RPT_ERROR, "Invalid selection order");
+ retval = OPERATOR_CANCELLED;
+ }
+
+ if (!BLI_listbase_is_empty(&selected_orig)) {
+ BM_select_history_clear(bm);
+ bm->selected = selected_orig;
+ }
+
+ return retval;
+}
+
+void MESH_OT_vert_connect_path(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Vertex Connect Path";
+ ot->idname = "MESH_OT_vert_connect_path";
+ ot->description = "Connect vertices by their selection order, creating edges, splitting faces";
+
+ /* api callbacks */
+ ot->exec = edbm_vert_connect_path_exec;
+ ot->poll = ED_operator_editmesh;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+static int edbm_vert_connect_concave_exec(bContext *C, wmOperator *op)
+{
+ Object *obedit = CTX_data_edit_object(C);
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+
+ if (!EDBM_op_call_and_selectf(
+ em, op,
+ "faces.out", true,
+ "connect_verts_concave faces=%hf",
+ BM_ELEM_SELECT))
+ {
+ return OPERATOR_CANCELLED;
+ }
+
+
+ EDBM_update_generic(em, true, true);
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_vert_connect_concave(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Split Concave Faces";
+ ot->idname = "MESH_OT_vert_connect_concave";
+ ot->description = "Make all faces convex";
+
+ /* api callbacks */
+ ot->exec = edbm_vert_connect_concave_exec;
+ ot->poll = ED_operator_editmesh;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+
static int edbm_vert_connect_nonplaner_exec(bContext *C, wmOperator *op)
{
Object *obedit = CTX_data_edit_object(C);
@@ -978,6 +1323,43 @@ void MESH_OT_vert_connect_nonplanar(wmOperatorType *ot)
RNA_def_property_float_default(prop, DEG2RADF(5.0f));
}
+static int edbm_face_make_planar_exec(bContext *C, wmOperator *op)
+{
+ Object *obedit = CTX_data_edit_object(C);
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ const int repeat = RNA_int_get(op->ptr, "repeat");
+ const float fac = RNA_float_get(op->ptr, "factor");
+
+ if (!EDBM_op_callf(
+ em, op, "planar_faces faces=%hf iterations=%i factor=%f",
+ BM_ELEM_SELECT, repeat, fac))
+ {
+ return OPERATOR_CANCELLED;
+ }
+
+ EDBM_update_generic(em, true, true);
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_face_make_planar(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Make Planar Faces";
+ ot->idname = "MESH_OT_face_make_planar";
+ ot->description = "Flatten selected faces";
+
+ /* api callbacks */
+ ot->exec = edbm_face_make_planar_exec;
+ ot->poll = ED_operator_editmesh;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* props */
+ RNA_def_float(ot->srna, "factor", 1.0f, -10.0f, 10.0f, "Factor", "", 0.0f, 1.0f);
+ RNA_def_int(ot->srna, "repeat", 1, 1, 10000, "Iterations", "", 1, 200);
+}
+
static int edbm_edge_split_exec(bContext *C, wmOperator *op)
{
@@ -1212,7 +1594,7 @@ void MESH_OT_hide(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
/* props */
- RNA_def_boolean(ot->srna, "unselected", 0, "Unselected", "Hide unselected rather than selected");
+ RNA_def_boolean(ot->srna, "unselected", false, "Unselected", "Hide unselected rather than selected");
}
static int edbm_reveal_exec(bContext *C, wmOperator *UNUSED(op))
@@ -1274,7 +1656,7 @@ void MESH_OT_normals_make_consistent(wmOperatorType *ot)
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- RNA_def_boolean(ot->srna, "inside", 0, "Inside", "");
+ RNA_def_boolean(ot->srna, "inside", false, "Inside", "");
}
@@ -1288,7 +1670,8 @@ static int edbm_do_smooth_vertex_exec(bContext *C, wmOperator *op)
bool mirrx = false, mirry = false, mirrz = false;
int i, repeat;
float clip_dist = 0.0f;
- bool use_topology = (me->editflag & ME_EDIT_MIRROR_TOPO) != 0;
+ const float fac = RNA_float_get(op->ptr, "factor");
+ const bool use_topology = (me->editflag & ME_EDIT_MIRROR_TOPO) != 0;
const bool xaxis = RNA_boolean_get(op->ptr, "xaxis");
const bool yaxis = RNA_boolean_get(op->ptr, "yaxis");
@@ -1322,12 +1705,12 @@ static int edbm_do_smooth_vertex_exec(bContext *C, wmOperator *op)
repeat = RNA_int_get(op->ptr, "repeat");
if (!repeat)
repeat = 1;
-
+
for (i = 0; i < repeat; i++) {
if (!EDBM_op_callf(em, op,
- "smooth_vert verts=%hv mirror_clip_x=%b mirror_clip_y=%b mirror_clip_z=%b clip_dist=%f "
- "use_axis_x=%b use_axis_y=%b use_axis_z=%b",
- BM_ELEM_SELECT, mirrx, mirry, mirrz, clip_dist, xaxis, yaxis, zaxis))
+ "smooth_vert verts=%hv factor=%f mirror_clip_x=%b mirror_clip_y=%b mirror_clip_z=%b "
+ "clip_dist=%f use_axis_x=%b use_axis_y=%b use_axis_z=%b",
+ BM_ELEM_SELECT, fac, mirrx, mirry, mirrz, clip_dist, xaxis, yaxis, zaxis))
{
return OPERATOR_CANCELLED;
}
@@ -1358,10 +1741,11 @@ void MESH_OT_vertices_smooth(wmOperatorType *ot)
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- RNA_def_int(ot->srna, "repeat", 1, 1, 1000, "Number of times to smooth the mesh", "", 1, 100);
- RNA_def_boolean(ot->srna, "xaxis", 1, "X-Axis", "Smooth along the X axis");
- RNA_def_boolean(ot->srna, "yaxis", 1, "Y-Axis", "Smooth along the Y axis");
- RNA_def_boolean(ot->srna, "zaxis", 1, "Z-Axis", "Smooth along the Z axis");
+ RNA_def_float(ot->srna, "factor", 0.5f, -10.0f, 10.0f, "Smoothing", "Smoothing factor", 0.0f, 1.0f);
+ RNA_def_int(ot->srna, "repeat", 1, 1, 1000, "Repeat", "Number of times to smooth the mesh", 1, 100);
+ RNA_def_boolean(ot->srna, "xaxis", true, "X-Axis", "Smooth along the X axis");
+ RNA_def_boolean(ot->srna, "yaxis", true, "Y-Axis", "Smooth along the Y axis");
+ RNA_def_boolean(ot->srna, "zaxis", true, "Z-Axis", "Smooth along the Z axis");
}
static int edbm_do_smooth_laplacian_vertex_exec(bContext *C, wmOperator *op)
@@ -1436,16 +1820,16 @@ void MESH_OT_vertices_smooth_laplacian(wmOperatorType *ot)
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- RNA_def_int(ot->srna, "repeat", 1, 1, 200,
+ RNA_def_int(ot->srna, "repeat", 1, 1, 1000,
"Number of iterations to smooth the mesh", "", 1, 200);
- RNA_def_float(ot->srna, "lambda_factor", 0.00005f, 0.0000001f, 1000.0f,
- "Lambda factor", "", 0.0000001f, 1000.0f);
- RNA_def_float(ot->srna, "lambda_border", 0.00005f, 0.0000001f, 1000.0f,
- "Lambda factor in border", "", 0.0000001f, 1000.0f);
- RNA_def_boolean(ot->srna, "use_x", 1, "Smooth X Axis", "Smooth object along X axis");
- RNA_def_boolean(ot->srna, "use_y", 1, "Smooth Y Axis", "Smooth object along Y axis");
- RNA_def_boolean(ot->srna, "use_z", 1, "Smooth Z Axis", "Smooth object along Z axis");
- RNA_def_boolean(ot->srna, "preserve_volume", 1, "Preserve Volume", "Apply volume preservation after smooth");
+ RNA_def_float(ot->srna, "lambda_factor", 5e-5f, 1e-7f, 1000.0f,
+ "Lambda factor", "", 1e-7f, 1000.0f);
+ RNA_def_float(ot->srna, "lambda_border", 5e-5f, 1e-7f, 1000.0f,
+ "Lambda factor in border", "", 1e-7f, 1000.0f);
+ RNA_def_boolean(ot->srna, "use_x", true, "Smooth X Axis", "Smooth object along X axis");
+ RNA_def_boolean(ot->srna, "use_y", true, "Smooth Y Axis", "Smooth object along Y axis");
+ RNA_def_boolean(ot->srna, "use_z", true, "Smooth Z Axis", "Smooth object along Z axis");
+ RNA_def_boolean(ot->srna, "preserve_volume", true, "Preserve Volume", "Apply volume preservation after smooth");
}
/********************** Smooth/Solid Operators *************************/
@@ -1690,6 +2074,14 @@ void MESH_OT_colors_reverse(wmOperatorType *ot)
}
+enum {
+ MESH_MERGE_LAST = 1,
+ MESH_MERGE_CENTER = 3,
+ MESH_MERGE_CURSOR = 4,
+ MESH_MERGE_COLLAPSE = 5,
+ MESH_MERGE_FIRST = 6,
+};
+
static bool merge_firstlast(BMEditMesh *em, const bool use_first, const bool use_uvmerge, wmOperator *wmop)
{
BMVert *mergevert;
@@ -1786,22 +2178,20 @@ static int edbm_merge_exec(bContext *C, wmOperator *op)
bool ok = false;
switch (type) {
- case 3:
+ case MESH_MERGE_CENTER:
ok = merge_target(em, scene, v3d, obedit, false, uvs, op);
break;
- case 4:
+ case MESH_MERGE_CURSOR:
ok = merge_target(em, scene, v3d, obedit, true, uvs, op);
break;
- case 1:
+ case MESH_MERGE_LAST:
ok = merge_firstlast(em, false, uvs, op);
break;
- case 6:
+ case MESH_MERGE_FIRST:
ok = merge_firstlast(em, true, uvs, op);
break;
- case 5:
- ok = true;
- if (!EDBM_op_callf(em, op, "collapse edges=%he", BM_ELEM_SELECT))
- ok = false;
+ case MESH_MERGE_COLLAPSE:
+ ok = EDBM_op_callf(em, op, "collapse edges=%he uvs=%b", BM_ELEM_SELECT, uvs);
break;
default:
BLI_assert(0);
@@ -1814,15 +2204,20 @@ static int edbm_merge_exec(bContext *C, wmOperator *op)
EDBM_update_generic(em, true, true);
+ /* once collapsed, we can't have edge/face selection */
+ if ((em->selectmode & SCE_SELECT_VERTEX) == 0) {
+ EDBM_flag_disable_all(em, BM_ELEM_SELECT);
+ }
+
return OPERATOR_FINISHED;
}
static EnumPropertyItem merge_type_items[] = {
- {6, "FIRST", 0, "At First", ""},
- {1, "LAST", 0, "At Last", ""},
- {3, "CENTER", 0, "At Center", ""},
- {4, "CURSOR", 0, "At Cursor", ""},
- {5, "COLLAPSE", 0, "Collapse", ""},
+ {MESH_MERGE_FIRST, "FIRST", 0, "At First", ""},
+ {MESH_MERGE_LAST, "LAST", 0, "At Last", ""},
+ {MESH_MERGE_CENTER, "CENTER", 0, "At Center", ""},
+ {MESH_MERGE_CURSOR, "CURSOR", 0, "At Cursor", ""},
+ {MESH_MERGE_COLLAPSE, "COLLAPSE", 0, "Collapse", ""},
{0, NULL, 0, NULL, NULL}
};
@@ -1844,20 +2239,20 @@ static EnumPropertyItem *merge_type_itemf(bContext *C, PointerRNA *UNUSED(ptr),
((BMEditSelection *)em->bm->selected.first)->htype == BM_VERT &&
((BMEditSelection *)em->bm->selected.last)->htype == BM_VERT)
{
- RNA_enum_items_add_value(&item, &totitem, merge_type_items, 6);
- RNA_enum_items_add_value(&item, &totitem, merge_type_items, 1);
+ RNA_enum_items_add_value(&item, &totitem, merge_type_items, MESH_MERGE_FIRST);
+ RNA_enum_items_add_value(&item, &totitem, merge_type_items, MESH_MERGE_LAST);
}
else if (em->bm->selected.first && ((BMEditSelection *)em->bm->selected.first)->htype == BM_VERT) {
- RNA_enum_items_add_value(&item, &totitem, merge_type_items, 6);
+ RNA_enum_items_add_value(&item, &totitem, merge_type_items, MESH_MERGE_FIRST);
}
else if (em->bm->selected.last && ((BMEditSelection *)em->bm->selected.last)->htype == BM_VERT) {
- RNA_enum_items_add_value(&item, &totitem, merge_type_items, 1);
+ RNA_enum_items_add_value(&item, &totitem, merge_type_items, MESH_MERGE_LAST);
}
}
- RNA_enum_items_add_value(&item, &totitem, merge_type_items, 3);
- RNA_enum_items_add_value(&item, &totitem, merge_type_items, 4);
- RNA_enum_items_add_value(&item, &totitem, merge_type_items, 5);
+ RNA_enum_items_add_value(&item, &totitem, merge_type_items, MESH_MERGE_CENTER);
+ RNA_enum_items_add_value(&item, &totitem, merge_type_items, MESH_MERGE_CURSOR);
+ RNA_enum_items_add_value(&item, &totitem, merge_type_items, MESH_MERGE_COLLAPSE);
RNA_enum_item_end(&item, &totitem);
*r_free = true;
@@ -1884,9 +2279,9 @@ void MESH_OT_merge(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
/* properties */
- ot->prop = RNA_def_enum(ot->srna, "type", merge_type_items, 3, "Type", "Merge method to use");
+ ot->prop = RNA_def_enum(ot->srna, "type", merge_type_items, MESH_MERGE_CENTER, "Type", "Merge method to use");
RNA_def_enum_funcs(ot->prop, merge_type_itemf);
- RNA_def_boolean(ot->srna, "uvs", 0, "UVs", "Move UVs according to merge");
+ RNA_def_boolean(ot->srna, "uvs", false, "UVs", "Move UVs according to merge");
}
@@ -1962,9 +2357,9 @@ void MESH_OT_remove_doubles(wmOperatorType *ot)
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- RNA_def_float(ot->srna, "threshold", 0.0001f, 0.000001f, 50.0f, "Merge Distance",
- "Minimum distance between elements to merge", 0.00001, 10.0);
- RNA_def_boolean(ot->srna, "use_unselected", 0, "Unselected", "Merge selected to other unselected vertices");
+ RNA_def_float(ot->srna, "threshold", 1e-4f, 1e-6f, 50.0f, "Merge Distance",
+ "Minimum distance between elements to merge", 1e-5f, 10.0f);
+ RNA_def_boolean(ot->srna, "use_unselected", false, "Unselected", "Merge selected to other unselected vertices");
}
@@ -2158,9 +2553,9 @@ void MESH_OT_blend_from_shape(wmOperatorType *ot)
/* properties */
prop = RNA_def_enum(ot->srna, "shape", DummyRNA_NULL_items, 0, "Shape", "Shape key to use for blending");
RNA_def_enum_funcs(prop, shape_itemf);
- RNA_def_property_flag(prop, PROP_ENUM_NO_TRANSLATE);
- RNA_def_float(ot->srna, "blend", 1.0f, -FLT_MAX, FLT_MAX, "Blend", "Blending factor", -2.0f, 2.0f);
- RNA_def_boolean(ot->srna, "add", 1, "Add", "Add rather than blend between shapes");
+ RNA_def_property_flag(prop, PROP_ENUM_NO_TRANSLATE | PROP_NEVER_UNLINK);
+ RNA_def_float(ot->srna, "blend", 1.0f, -1e3f, 1e3f, "Blend", "Blending factor", -2.0f, 2.0f);
+ RNA_def_boolean(ot->srna, "add", true, "Add", "Add rather than blend between shapes");
}
static int edbm_solidify_exec(bContext *C, wmOperator *op)
@@ -2213,8 +2608,8 @@ void MESH_OT_solidify(wmOperatorType *ot)
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- prop = RNA_def_float(ot->srna, "thickness", 0.01f, -FLT_MAX, FLT_MAX, "thickness", "", -10.0f, 10.0f);
- RNA_def_property_ui_range(prop, -10, 10, 0.1, 4);
+ prop = RNA_def_float(ot->srna, "thickness", 0.01f, -1e4f, 1e4f, "Thickness", "", -10.0f, 10.0f);
+ RNA_def_property_ui_range(prop, -10.0, 10.0, 0.1, 4);
}
/* ******************************************************************** */
@@ -2507,7 +2902,7 @@ static int edbm_knife_cut_exec(bContext *C, wmOperator *op)
if (mode == KNIFE_MIDPOINT) numcuts = 1;
BMO_slot_int_set(bmop.slots_in, "cuts", numcuts);
- BMO_slot_int_set(bmop.slots_in, "quad_corner_type", SUBD_STRAIGHT_CUT);
+ BMO_slot_int_set(bmop.slots_in, "quad_corner_type", SUBD_CORNER_STRAIGHT_CUT);
BMO_slot_bool_set(bmop.slots_in, "use_single_edge", false);
BMO_slot_bool_set(bmop.slots_in, "use_grid_fill", false);
@@ -2547,9 +2942,18 @@ void MESH_OT_knife_cut(wmOperatorType *ot)
RNA_def_property_struct_runtime(prop, &RNA_OperatorMousePath);
/* internal */
- RNA_def_int(ot->srna, "cursor", BC_KNIFECURSOR, 0, INT_MAX, "Cursor", "", 0, INT_MAX);
+ RNA_def_int(ot->srna, "cursor", BC_KNIFECURSOR, 0, BC_NUMCURSORS, "Cursor", "", 0, BC_NUMCURSORS);
}
+
+/* *************** Operator: separate parts *************/
+
+enum {
+ MESH_SEPARATE_SELECTED = 0,
+ MESH_SEPARATE_MATERIAL = 1,
+ MESH_SEPARATE_LOOSE = 2,
+};
+
static Base *mesh_separate_tagged(Main *bmain, Scene *scene, Base *base_old, BMesh *bm_old)
{
Base *base_new;
@@ -2679,7 +3083,7 @@ static void mesh_separate_material_assign_mat_nr(Object *ob, const short mat_nr)
}
if (mat_nr < *totcolp) {
- ma_obdata = (*matarar)[mat_nr];
+ ma_obdata = (*matarar)[mat_nr];
}
else {
ma_obdata = NULL;
@@ -2833,17 +3237,27 @@ static int edbm_separate_exec(bContext *C, wmOperator *op)
}
/* editmode separate */
- if (type == 0) retval = mesh_separate_selected(bmain, scene, base, em->bm);
- else if (type == 1) retval = mesh_separate_material(bmain, scene, base, em->bm);
- else if (type == 2) retval = mesh_separate_loose(bmain, scene, base, em->bm);
- else BLI_assert(0);
+ switch (type) {
+ case MESH_SEPARATE_SELECTED:
+ retval = mesh_separate_selected(bmain, scene, base, em->bm);
+ break;
+ case MESH_SEPARATE_MATERIAL:
+ retval = mesh_separate_material(bmain, scene, base, em->bm);
+ break;
+ case MESH_SEPARATE_LOOSE:
+ retval = mesh_separate_loose(bmain, scene, base, em->bm);
+ break;
+ default:
+ BLI_assert(0);
+ break;
+ }
if (retval) {
EDBM_update_generic(em, true, true);
}
}
else {
- if (type == 0) {
+ if (type == MESH_SEPARATE_SELECTED) {
BKE_report(op->reports, RPT_ERROR, "Selection not supported in object mode");
return OPERATOR_CANCELLED;
}
@@ -2862,9 +3276,17 @@ static int edbm_separate_exec(bContext *C, wmOperator *op)
BM_mesh_bm_from_me(bm_old, me, false, false, 0);
- if (type == 1) retval_iter = mesh_separate_material(bmain, scene, base_iter, bm_old);
- else if (type == 2) retval_iter = mesh_separate_loose(bmain, scene, base_iter, bm_old);
- else BLI_assert(0);
+ switch (type) {
+ case MESH_SEPARATE_MATERIAL:
+ retval_iter = mesh_separate_material(bmain, scene, base_iter, bm_old);
+ break;
+ case MESH_SEPARATE_LOOSE:
+ retval_iter = mesh_separate_loose(bmain, scene, base_iter, bm_old);
+ break;
+ default:
+ BLI_assert(0);
+ break;
+ }
if (retval_iter) {
BM_mesh_bm_to_me(bm_old, me, false);
@@ -2893,17 +3315,15 @@ static int edbm_separate_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
-/* *************** Operator: separate parts *************/
-
-static EnumPropertyItem prop_separate_types[] = {
- {0, "SELECTED", 0, "Selection", ""},
- {1, "MATERIAL", 0, "By Material", ""},
- {2, "LOOSE", 0, "By loose parts", ""},
- {0, NULL, 0, NULL, NULL}
-};
-
void MESH_OT_separate(wmOperatorType *ot)
{
+ static EnumPropertyItem prop_separate_types[] = {
+ {MESH_SEPARATE_SELECTED, "SELECTED", 0, "Selection", ""},
+ {MESH_SEPARATE_MATERIAL, "MATERIAL", 0, "By Material", ""},
+ {MESH_SEPARATE_LOOSE, "LOOSE", 0, "By loose parts", ""},
+ {0, NULL, 0, NULL, NULL}
+ };
+
/* identifiers */
ot->name = "Separate";
ot->description = "Separate selected geometry into a new mesh";
@@ -2917,7 +3337,7 @@ void MESH_OT_separate(wmOperatorType *ot)
/* flags */
ot->flag = OPTYPE_UNDO;
- ot->prop = RNA_def_enum(ot->srna, "type", prop_separate_types, 0, "Type", "");
+ ot->prop = RNA_def_enum(ot->srna, "type", prop_separate_types, MESH_SEPARATE_SELECTED, "Type", "");
}
@@ -2927,7 +3347,14 @@ static int edbm_fill_exec(bContext *C, wmOperator *op)
BMEditMesh *em = BKE_editmesh_from_object(obedit);
const bool use_beauty = RNA_boolean_get(op->ptr, "use_beauty");
BMOperator bmop;
-
+ const int totface_orig = em->bm->totface;
+ int ret;
+
+ if (em->bm->totedgesel == 0) {
+ BKE_report(op->reports, RPT_WARNING, "No edges selected");
+ return OPERATOR_CANCELLED;
+ }
+
if (!EDBM_op_init(em, &bmop, op,
"triangle_fill edges=%he use_beauty=%b",
BM_ELEM_SELECT, use_beauty))
@@ -2937,17 +3364,24 @@ static int edbm_fill_exec(bContext *C, wmOperator *op)
BMO_op_exec(em->bm, &bmop);
- /* select new geometry */
- BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_out, "geom.out", BM_FACE | BM_EDGE, BM_ELEM_SELECT, true);
-
- if (!EDBM_op_finish(em, &bmop, op, true)) {
- return OPERATOR_CANCELLED;
+ if (totface_orig != em->bm->totface) {
+ /* select new geometry */
+ BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_out, "geom.out", BM_FACE | BM_EDGE, BM_ELEM_SELECT, true);
+
+ EDBM_update_generic(em, true, true);
+
+ ret = OPERATOR_FINISHED;
+ }
+ else {
+ BKE_report(op->reports, RPT_WARNING, "No faces filled");
+ ret = OPERATOR_CANCELLED;
}
- EDBM_update_generic(em, true, true);
-
- return OPERATOR_FINISHED;
+ if (!EDBM_op_finish(em, &bmop, op, true)) {
+ ret = OPERATOR_CANCELLED;
+ }
+ return ret;
}
void MESH_OT_fill(wmOperatorType *ot)
@@ -2997,6 +3431,9 @@ static float edbm_fill_grid_vert_tag_angle(BMVert *v)
*/
static void edbm_fill_grid_prepare(BMesh *bm, int offset, int *r_span, bool span_calc)
{
+ /* angle differences below this value are considered 'even'
+ * in that they shouldn't be used to calculate corners used for the 'span' */
+ const float eps_even = 1e-3f;
BMEdge *e;
BMIter iter;
int count;
@@ -3042,13 +3479,15 @@ static void edbm_fill_grid_prepare(BMesh *bm, int offset, int *r_span, bool span
v_act = v_act_link->data;
}
+ /* set this vertex first */
+ BLI_listbase_rotate_first(verts, v_act_link);
+
if (offset != 0) {
v_act_link = BLI_findlink(verts, offset);
v_act = v_act_link->data;
+ BLI_listbase_rotate_first(verts, v_act_link);
}
- /* set this vertex first */
- BLI_listbase_rotate_first(verts, v_act_link);
BM_edgeloop_edges_get(el_store, edges);
@@ -3073,18 +3512,23 @@ static void edbm_fill_grid_prepare(BMesh *bm, int offset, int *r_span, bool span
qsort(ele_sort, verts_len, sizeof(*ele_sort), BLI_sortutil_cmp_float_reverse);
- for (i = 0; i < 4; i++) {
- BMVert *v = ele_sort[i].data;
- BM_elem_flag_enable(v, BM_ELEM_TAG);
- }
+ /* check that we have at least 3 corners,
+ * if the angle on the 3rd angle is roughly the same as the last,
+ * then we can't calculate 3+ corners - fallback to the even span. */
+ if ((ele_sort[2].sort_value - ele_sort[verts_len - 1].sort_value) > eps_even) {
+ for (i = 0; i < 4; i++) {
+ BMVert *v = ele_sort[i].data;
+ BM_elem_flag_enable(v, BM_ELEM_TAG);
+ }
- /* now find the first... */
- for (v_link = verts->first, i = 0; i < verts_len / 2; v_link = v_link->next, i++) {
- BMVert *v = v_link->data;
- if (BM_elem_flag_test(v, BM_ELEM_TAG)) {
- if (v != v_act) {
- span = i;
- break;
+ /* now find the first... */
+ for (v_link = verts->first, i = 0; i < verts_len / 2; v_link = v_link->next, i++) {
+ BMVert *v = v_link->data;
+ if (BM_elem_flag_test(v, BM_ELEM_TAG)) {
+ if (v != v_act) {
+ span = i;
+ break;
+ }
}
}
}
@@ -3196,11 +3640,11 @@ void MESH_OT_fill_grid(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
/* properties */
- prop = RNA_def_int(ot->srna, "span", 1, 1, INT_MAX, "Span", "Number of sides (zero disables)", 1, 100);
+ prop = RNA_def_int(ot->srna, "span", 1, 1, 1000, "Span", "Number of sides (zero disables)", 1, 100);
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
- prop = RNA_def_int(ot->srna, "offset", 0, INT_MIN, INT_MAX, "Offset", "Number of sides (zero disables)", -100, 100);
+ prop = RNA_def_int(ot->srna, "offset", 0, -1000, 1000, "Offset", "Number of sides (zero disables)", -100, 100);
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
- RNA_def_boolean(ot->srna, "use_interp_simple", 0, "Simple Blending", "");
+ RNA_def_boolean(ot->srna, "use_interp_simple", false, "Simple Blending", "");
}
static int edbm_fill_holes_exec(bContext *C, wmOperator *op)
@@ -3238,7 +3682,8 @@ void MESH_OT_fill_holes(wmOperatorType *ot)
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- RNA_def_int(ot->srna, "sides", 4, 0, INT_MAX, "Sides", "Number of sides in hole required to fill (zero fills all holes)", 0, 100);
+ RNA_def_int(ot->srna, "sides", 4, 0, 1000,
+ "Sides", "Number of sides in hole required to fill (zero fills all holes)", 0, 100);
}
static int edbm_beautify_fill_exec(bContext *C, wmOperator *op)
@@ -3358,9 +3803,10 @@ void MESH_OT_poke(wmOperatorType *ot)
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- RNA_def_float(ot->srna, "offset", 0.0f, -FLT_MAX, FLT_MAX, "Poke Offset", "Poke Offset", -1.0f, 1.0f);
+ RNA_def_float(ot->srna, "offset", 0.0f, -1e3f, 1e3f, "Poke Offset", "Poke Offset", -1.0f, 1.0f);
RNA_def_boolean(ot->srna, "use_relative_offset", false, "Offset Relative", "Scale the offset by surrounding geometry");
- RNA_def_enum(ot->srna, "center_mode", poke_center_modes, BMOP_POKE_MEAN_WEIGHTED, "Poke Center", "Poke Face Center Calculation");
+ RNA_def_enum(ot->srna, "center_mode", poke_center_modes, BMOP_POKE_MEAN_WEIGHTED,
+ "Poke Center", "Poke Face Center Calculation");
}
/********************** Quad/Tri Operators *************************/
@@ -3414,19 +3860,45 @@ static int edbm_tris_convert_to_quads_exec(bContext *C, wmOperator *op)
{
Object *obedit = CTX_data_edit_object(C);
BMEditMesh *em = BKE_editmesh_from_object(obedit);
- int dosharp, douvs, dovcols, domaterials;
- const float limit = RNA_float_get(op->ptr, "limit");
+ bool do_seam, do_sharp, do_uvs, do_vcols, do_materials;
+ float angle_face_threshold, angle_shape_threshold;
+ PropertyRNA *prop;
- dosharp = RNA_boolean_get(op->ptr, "sharp");
- douvs = RNA_boolean_get(op->ptr, "uvs");
- dovcols = RNA_boolean_get(op->ptr, "vcols");
- domaterials = RNA_boolean_get(op->ptr, "materials");
+ /* When joining exactly 2 faces, no limit.
+ * this is useful for one off joins while editing. */
+ prop = RNA_struct_find_property(op->ptr, "face_threshold");
+ if ((em->bm->totfacesel == 2) &&
+ (RNA_property_is_set(op->ptr, prop) == false))
+ {
+ angle_face_threshold = DEG2RADF(180.0f);
+ }
+ else {
+ angle_face_threshold = RNA_property_float_get(op->ptr, prop);
+ }
+
+ prop = RNA_struct_find_property(op->ptr, "shape_threshold");
+ if ((em->bm->totfacesel == 2) &&
+ (RNA_property_is_set(op->ptr, prop) == false))
+ {
+ angle_shape_threshold = DEG2RADF(180.0f);
+ }
+ else {
+ angle_shape_threshold = RNA_property_float_get(op->ptr, prop);
+ }
+
+ do_seam = RNA_boolean_get(op->ptr, "seam");
+ do_sharp = RNA_boolean_get(op->ptr, "sharp");
+ do_uvs = RNA_boolean_get(op->ptr, "uvs");
+ do_vcols = RNA_boolean_get(op->ptr, "vcols");
+ do_materials = RNA_boolean_get(op->ptr, "materials");
if (!EDBM_op_call_and_selectf(
em, op,
"faces.out", true,
- "join_triangles faces=%hf limit=%f cmp_sharp=%b cmp_uvs=%b cmp_vcols=%b cmp_materials=%b",
- BM_ELEM_SELECT, limit, dosharp, douvs, dovcols, domaterials))
+ "join_triangles faces=%hf angle_face_threshold=%f angle_shape_threshold=%f "
+ "cmp_seam=%b cmp_sharp=%b cmp_uvs=%b cmp_vcols=%b cmp_materials=%b",
+ BM_ELEM_SELECT, angle_face_threshold, angle_shape_threshold,
+ do_seam, do_sharp, do_uvs, do_vcols, do_materials))
{
return OPERATOR_CANCELLED;
}
@@ -3440,14 +3912,21 @@ static void join_triangle_props(wmOperatorType *ot)
{
PropertyRNA *prop;
- prop = RNA_def_float_rotation(ot->srna, "limit", 0, NULL, 0.0f, DEG2RADF(180.0f),
- "Max Angle", "Angle Limit", 0.0f, DEG2RADF(180.0f));
+ prop = RNA_def_float_rotation(
+ ot->srna, "face_threshold", 0, NULL, 0.0f, DEG2RADF(180.0f),
+ "Max Face Angle", "Face angle limit", 0.0f, DEG2RADF(180.0f));
+ RNA_def_property_float_default(prop, DEG2RADF(40.0f));
+
+ prop = RNA_def_float_rotation(
+ ot->srna, "shape_threshold", 0, NULL, 0.0f, DEG2RADF(180.0f),
+ "Max Shape Angle", "Shape angle limit", 0.0f, DEG2RADF(180.0f));
RNA_def_property_float_default(prop, DEG2RADF(40.0f));
- RNA_def_boolean(ot->srna, "uvs", 0, "Compare UVs", "");
- RNA_def_boolean(ot->srna, "vcols", 0, "Compare VCols", "");
- RNA_def_boolean(ot->srna, "sharp", 0, "Compare Sharp", "");
- RNA_def_boolean(ot->srna, "materials", 0, "Compare Materials", "");
+ RNA_def_boolean(ot->srna, "uvs", false, "Compare UVs", "");
+ RNA_def_boolean(ot->srna, "vcols", false, "Compare VCols", "");
+ RNA_def_boolean(ot->srna, "seam", false, "Compare Seam", "");
+ RNA_def_boolean(ot->srna, "sharp", false, "Compare Sharp", "");
+ RNA_def_boolean(ot->srna, "materials", false, "Compare Materials", "");
}
void MESH_OT_tris_convert_to_quads(wmOperatorType *ot)
@@ -3470,19 +3949,25 @@ void MESH_OT_tris_convert_to_quads(wmOperatorType *ot)
/* -------------------------------------------------------------------- */
/* Dissolve */
-static void edbm_dissolve_prop__use_verts(wmOperatorType *ot)
+static void edbm_dissolve_prop__use_verts(wmOperatorType *ot, bool value, int flag)
{
- RNA_def_boolean(ot->srna, "use_verts", 0, "Dissolve Verts",
- "Dissolve remaining vertices");
+ PropertyRNA *prop;
+
+ prop = RNA_def_boolean(ot->srna, "use_verts", value, "Dissolve Verts",
+ "Dissolve remaining vertices");
+
+ if (flag) {
+ RNA_def_property_flag(prop, flag);
+ }
}
static void edbm_dissolve_prop__use_face_split(wmOperatorType *ot)
{
- RNA_def_boolean(ot->srna, "use_face_split", 0, "Face Split",
+ RNA_def_boolean(ot->srna, "use_face_split", false, "Face Split",
"Split off face corners to maintain surrounding geometry");
}
static void edbm_dissolve_prop__use_boundary_tear(wmOperatorType *ot)
{
- RNA_def_boolean(ot->srna, "use_boundary_tear", 0, "Tear Boundary",
+ RNA_def_boolean(ot->srna, "use_boundary_tear", false, "Tear Boundary",
"Split off face corners instead of merging faces");
}
@@ -3558,7 +4043,7 @@ void MESH_OT_dissolve_edges(wmOperatorType *ot)
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- edbm_dissolve_prop__use_verts(ot);
+ edbm_dissolve_prop__use_verts(ot, true, 0);
edbm_dissolve_prop__use_face_split(ot);
}
@@ -3597,7 +4082,7 @@ void MESH_OT_dissolve_faces(wmOperatorType *ot)
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- edbm_dissolve_prop__use_verts(ot);
+ edbm_dissolve_prop__use_verts(ot, false, 0);
}
@@ -3605,6 +4090,15 @@ static int edbm_dissolve_mode_exec(bContext *C, wmOperator *op)
{
Object *obedit = CTX_data_edit_object(C);
BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ PropertyRNA *prop;
+
+ prop = RNA_struct_find_property(op->ptr, "use_verts");
+ if (!RNA_property_is_set(op->ptr, prop)) {
+ /* always enable in edge-mode */
+ if ((em->selectmode & SCE_SELECT_FACE) == 0) {
+ RNA_property_boolean_set(op->ptr, prop, true);
+ }
+ }
if (em->selectmode & SCE_SELECT_VERTEX) {
return edbm_dissolve_verts_exec(C, op);
@@ -3631,7 +4125,7 @@ void MESH_OT_dissolve_mode(wmOperatorType *ot)
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- edbm_dissolve_prop__use_verts(ot);
+ edbm_dissolve_prop__use_verts(ot, false, PROP_SKIP_SAVE);
edbm_dissolve_prop__use_face_split(ot);
edbm_dissolve_prop__use_boundary_tear(ot);
}
@@ -3707,9 +4201,9 @@ void MESH_OT_dissolve_limited(wmOperatorType *ot)
prop = RNA_def_float_rotation(ot->srna, "angle_limit", 0, NULL, 0.0f, DEG2RADF(180.0f),
"Max Angle", "Angle limit", 0.0f, DEG2RADF(180.0f));
RNA_def_property_float_default(prop, DEG2RADF(5.0f));
- RNA_def_boolean(ot->srna, "use_dissolve_boundaries", 0, "All Boundaries",
+ RNA_def_boolean(ot->srna, "use_dissolve_boundaries", false, "All Boundaries",
"Dissolve all vertices inbetween face boundaries");
- RNA_def_enum_flag(ot->srna, "delimit", mesh_delimit_mode_items, 0, "Delimit",
+ RNA_def_enum_flag(ot->srna, "delimit", mesh_delimit_mode_items, BMO_DELIM_NORMAL, "Delimit",
"Delimit dissolve operation");
}
@@ -3753,8 +4247,8 @@ void MESH_OT_dissolve_degenerate(wmOperatorType *ot)
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- RNA_def_float(ot->srna, "threshold", 0.0001f, 0.000001f, 50.0f, "Merge Distance",
- "Minimum distance between elements to merge", 0.00001, 10.0);
+ RNA_def_float(ot->srna, "threshold", 1e-4f, 1e-6f, 50.0f, "Merge Distance",
+ "Minimum distance between elements to merge", 1e-5f, 10.0f);
}
@@ -3792,6 +4286,8 @@ static int edbm_delete_edgeloop_exec(bContext *C, wmOperator *op)
BM_mesh_elem_hflag_enable_test(em->bm, BM_FACE, BM_ELEM_SELECT, true, false, BM_ELEM_TAG);
+ EDBM_selectmode_flush_ex(em, SCE_SELECT_VERTEX);
+
EDBM_update_generic(em, true, true);
return OPERATOR_FINISHED;
@@ -4431,8 +4927,9 @@ void MESH_OT_sort_elements(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
/* properties */
- ot->prop = RNA_def_enum(ot->srna, "type", type_items, 0, "Type", "Type of re-ordering operation to apply");
- RNA_def_enum_flag(ot->srna, "elements", elem_items, 0, "Elements",
+ ot->prop = RNA_def_enum(ot->srna, "type", type_items, SRT_VIEW_ZAXIS,
+ "Type", "Type of re-ordering operation to apply");
+ RNA_def_enum_flag(ot->srna, "elements", elem_items, BM_VERT, "Elements",
"Which elements to affect (vertices, edges and/or faces)");
RNA_def_boolean(ot->srna, "reverse", false, "Reverse", "Reverse the sorting effect");
RNA_def_int(ot->srna, "seed", 0, 0, INT_MAX, "Seed", "Seed for random-based operations", 0, 255);
@@ -4480,7 +4977,7 @@ static int edbm_noise_exec(bContext *C, wmOperator *op)
BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
if (BM_elem_flag_test(eve, BM_ELEM_SELECT)) {
float tin, dum;
- externtex(ma->mtex[0], eve->co, &tin, &dum, &dum, &dum, &dum, 0, NULL);
+ externtex(ma->mtex[0], eve->co, &tin, &dum, &dum, &dum, &dum, 0, NULL, false);
eve->co[2] += fac * tin;
}
}
@@ -4507,10 +5004,16 @@ void MESH_OT_noise(wmOperatorType *ot)
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- RNA_def_float(ot->srna, "factor", 0.1f, -FLT_MAX, FLT_MAX, "Factor", "", 0.0f, 1.0f);
+ RNA_def_float(ot->srna, "factor", 0.1f, -1e4f, 1e4f, "Factor", "", 0.0f, 1.0f);
}
+enum {
+ MESH_BRIDGELOOP_SINGLE = 0,
+ MESH_BRIDGELOOP_CLOSED = 1,
+ MESH_BRIDGELOOP_PAIRS = 2,
+};
+
static int edbm_bridge_tag_boundary_edges(BMesh *bm)
{
/* tags boundary edges from a face selection */
@@ -4559,8 +5062,8 @@ static int edbm_bridge_edge_loops_exec(bContext *C, wmOperator *op)
Object *obedit = CTX_data_edit_object(C);
BMEditMesh *em = BKE_editmesh_from_object(obedit);
const int type = RNA_enum_get(op->ptr, "type");
- const bool use_pairs = (type == 2);
- const bool use_cyclic = (type == 1);
+ const bool use_pairs = (type == MESH_BRIDGELOOP_PAIRS);
+ const bool use_cyclic = (type == MESH_BRIDGELOOP_CLOSED);
const bool use_merge = RNA_boolean_get(op->ptr, "use_merge");
const float merge_factor = RNA_float_get(op->ptr, "merge_factor");
const int twist_offset = RNA_int_get(op->ptr, "twist_offset");
@@ -4658,9 +5161,9 @@ static int edbm_bridge_edge_loops_exec(bContext *C, wmOperator *op)
void MESH_OT_bridge_edge_loops(wmOperatorType *ot)
{
static EnumPropertyItem type_items[] = {
- {0, "SINGLE", 0, "Open Loop", ""},
- {1, "CLOSED", 0, "Closed Loop", ""},
- {2, "PAIRS", 0, "Loop Pairs", ""},
+ {MESH_BRIDGELOOP_SINGLE, "SINGLE", 0, "Open Loop", ""},
+ {MESH_BRIDGELOOP_CLOSED, "CLOSED", 0, "Closed Loop", ""},
+ {MESH_BRIDGELOOP_PAIRS, "PAIRS", 0, "Loop Pairs", ""},
{0, NULL, 0, NULL, NULL}
};
@@ -4676,7 +5179,7 @@ void MESH_OT_bridge_edge_loops(wmOperatorType *ot)
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- ot->prop = RNA_def_enum(ot->srna, "type", type_items, 0,
+ ot->prop = RNA_def_enum(ot->srna, "type", type_items, MESH_BRIDGELOOP_SINGLE,
"Connect Loops", "Method of bridging multiple loops");
RNA_def_boolean(ot->srna, "use_merge", false, "Merge", "Merge rather than creating faces");
@@ -4737,19 +5240,73 @@ void MESH_OT_wireframe(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
/* properties */
- RNA_def_boolean(ot->srna, "use_boundary", true, "Boundary", "Inset face boundaries");
- RNA_def_boolean(ot->srna, "use_even_offset", true, "Offset Even", "Scale the offset to give more even thickness");
+ RNA_def_boolean(ot->srna, "use_boundary", true, "Boundary", "Inset face boundaries");
+ RNA_def_boolean(ot->srna, "use_even_offset", true, "Offset Even", "Scale the offset to give more even thickness");
RNA_def_boolean(ot->srna, "use_relative_offset", false, "Offset Relative", "Scale the offset by surrounding geometry");
- RNA_def_boolean(ot->srna, "use_replace", true, "Replace", "Remove original faces");
- prop = RNA_def_float(ot->srna, "thickness", 0.01f, 0.0f, FLT_MAX, "Thickness", "", 0.0f, 10.0f);
+ RNA_def_boolean(ot->srna, "use_replace", true, "Replace", "Remove original faces");
+ prop = RNA_def_float(ot->srna, "thickness", 0.01f, 0.0f, 1e4f, "Thickness", "", 0.0f, 10.0f);
/* use 1 rather then 10 for max else dragging the button moves too far */
RNA_def_property_ui_range(prop, 0.0, 1.0, 0.01, 4);
- RNA_def_float(ot->srna, "offset", 0.01f, 0.0f, FLT_MAX, "Offset", "", 0.0f, 10.0f);
- RNA_def_boolean(ot->srna, "use_crease", false, "Crease", "Crease hub edges for improved subsurf");
- prop = RNA_def_float(ot->srna, "crease_weight", 0.01f, 0.0f, FLT_MAX, "Crease weight", "", 0.0f, 1.0f);
+ RNA_def_float(ot->srna, "offset", 0.01f, 0.0f, 1e4f, "Offset", "", 0.0f, 10.0f);
+ RNA_def_boolean(ot->srna, "use_crease", false, "Crease", "Crease hub edges for improved subsurf");
+ prop = RNA_def_float(ot->srna, "crease_weight", 0.01f, 0.0f, 1e3f, "Crease weight", "", 0.0f, 1.0f);
RNA_def_property_ui_range(prop, 0.0, 1.0, 0.1, 2);
}
+static int edbm_offset_edgeloop_exec(bContext *C, wmOperator *op)
+{
+ Object *obedit = CTX_data_edit_object(C);
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ BMOperator bmop;
+ const bool use_cap_endpoint = RNA_boolean_get(op->ptr, "use_cap_endpoint");
+
+ EDBM_op_init(
+ em, &bmop, op,
+ "offset_edgeloops edges=%he use_cap_endpoint=%b",
+ BM_ELEM_SELECT, use_cap_endpoint);
+
+ BMO_op_exec(em->bm, &bmop);
+
+ BM_mesh_elem_hflag_disable_all(em->bm, BM_VERT | BM_EDGE | BM_FACE, BM_ELEM_SELECT, false);
+
+ /* If in face-only select mode, switch to edge select mode so that
+ * an edge-only selection is not inconsistent state */
+ if (em->selectmode == SCE_SELECT_FACE) {
+ em->selectmode = SCE_SELECT_EDGE;
+ EDBM_selectmode_set(em);
+ EDBM_selectmode_to_scene(C);
+ }
+
+ BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_out, "edges.out", BM_EDGE, BM_ELEM_SELECT, true);
+
+ if (!EDBM_op_finish(em, &bmop, op, true)) {
+ return OPERATOR_CANCELLED;
+ }
+ else {
+ EDBM_update_generic(em, true, true);
+ return OPERATOR_FINISHED;
+ }
+}
+
+void MESH_OT_offset_edge_loops(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Offset Edge Loop";
+ ot->idname = "MESH_OT_offset_edge_loops";
+ ot->description = "Create offset edge loop from the current selection";
+
+ /* api callbacks */
+ ot->exec = edbm_offset_edgeloop_exec;
+ ot->poll = ED_operator_editmesh;
+
+ /* Keep internal, since this is only meant to be accessed via 'MESH_OT_offset_edge_loops_slide' */
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
+
+ RNA_def_boolean(ot->srna, "use_cap_endpoint", false, "Cap Endpoint", "Extend loop around end-points");
+}
+
#ifdef WITH_BULLET
static int edbm_convex_hull_exec(bContext *C, wmOperator *op)
{
@@ -4793,11 +5350,16 @@ static int edbm_convex_hull_exec(bContext *C, wmOperator *op)
/* Merge adjacent triangles */
if (RNA_boolean_get(op->ptr, "join_triangles")) {
- if (!EDBM_op_call_and_selectf(em, op,
- "faces.out", true,
- "join_triangles faces=%S limit=%f",
- &bmop, "geom.out",
- RNA_float_get(op->ptr, "limit")))
+ float angle_face_threshold = RNA_float_get(op->ptr, "face_threshold");
+ float angle_shape_threshold = RNA_float_get(op->ptr, "shape_threshold");
+
+ if (!EDBM_op_call_and_selectf(
+ em, op,
+ "faces.out", true,
+ "join_triangles faces=%S "
+ "angle_face_threshold=%f angle_shape_threshold=%f",
+ &bmop, "geom.out",
+ angle_face_threshold, angle_shape_threshold))
{
EDBM_op_finish(em, &bmop, op, true);
return OPERATOR_CANCELLED;
@@ -4893,7 +5455,7 @@ void MESH_OT_symmetrize(struct wmOperatorType *ot)
ot->prop = RNA_def_enum(ot->srna, "direction", symmetrize_direction_items,
BMO_SYMMETRIZE_NEGATIVE_X,
"Direction", "Which sides to copy from and to");
- RNA_def_float(ot->srna, "threshold", 0.0001, 0.0, 10.0, "Threshold", "", 0.00001, 0.1);
+ RNA_def_float(ot->srna, "threshold", 1e-4f, 0.0f, 10.0f, "Threshold", "", 1e-5f, 0.1f);
}
static int mesh_symmetry_snap_exec(bContext *C, wmOperator *op)
@@ -5017,8 +5579,8 @@ void MESH_OT_symmetry_snap(struct wmOperatorType *ot)
ot->prop = RNA_def_enum(ot->srna, "direction", symmetrize_direction_items,
BMO_SYMMETRIZE_NEGATIVE_X,
"Direction", "Which sides to copy from and to");
- RNA_def_float(ot->srna, "threshold", 0.05, 0.0, 10.0, "Threshold", "", 0.0001, 1.0);
- RNA_def_float(ot->srna, "factor", 0.5f, 0.0, 1.0, "Factor", "", 0.0, 1.0);
+ RNA_def_float(ot->srna, "threshold", 0.05f, 0.0f, 10.0f, "Threshold", "", 1e-4f, 1.0f);
+ RNA_def_float(ot->srna, "factor", 0.5f, 0.0f, 1.0f, "Factor", "", 0.0f, 1.0f);
RNA_def_boolean(ot->srna, "use_center", true, "Center", "Snap mid verts to the axis center");
}
@@ -5085,7 +5647,7 @@ void MESH_OT_mark_freestyle_edge(wmOperatorType *ot)
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- prop = RNA_def_boolean(ot->srna, "clear", 0, "Clear", "");
+ prop = RNA_def_boolean(ot->srna, "clear", false, "Clear", "");
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
@@ -5149,7 +5711,7 @@ void MESH_OT_mark_freestyle_face(wmOperatorType *ot)
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- prop = RNA_def_boolean(ot->srna, "clear", 0, "Clear", "");
+ prop = RNA_def_boolean(ot->srna, "clear", false, "Clear", "");
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
diff --git a/source/blender/editors/mesh/editmesh_utils.c b/source/blender/editors/mesh/editmesh_utils.c
index c7d1d883537..d521b2c01e5 100644
--- a/source/blender/editors/mesh/editmesh_utils.c
+++ b/source/blender/editors/mesh/editmesh_utils.c
@@ -33,9 +33,13 @@
#include "DNA_mesh_types.h"
#include "DNA_object_types.h"
+#include "DNA_key_types.h"
#include "BLI_math.h"
#include "BLI_alloca.h"
+#include "BLI_buffer.h"
+#include "BLI_kdtree.h"
+#include "BLI_listbase.h"
#include "BKE_DerivedMesh.h"
#include "BKE_context.h"
@@ -230,7 +234,7 @@ bool EDBM_op_finish(BMEditMesh *em, BMOperator *bmop, wmOperator *op, const bool
else {
em->emcopyusers--;
if (em->emcopyusers < 0) {
- printf("warning: em->emcopyusers was less then zero.\n");
+ printf("warning: em->emcopyusers was less than zero.\n");
}
if (em->emcopyusers <= 0) {
@@ -381,6 +385,12 @@ void EDBM_mesh_load(Object *ob)
Mesh *me = ob->data;
BMesh *bm = me->edit_btmesh->bm;
+ /* Workaround for T42360, 'ob->shapenr' should be 1 in this case.
+ * however this isn't synchronized between objects at the moment. */
+ if (UNLIKELY((ob->shapenr == 0) && (me->key && !BLI_listbase_is_empty(&me->key->block)))) {
+ bm->shapenr = 1;
+ }
+
BM_mesh_bm_to_me(bm, me, false);
#ifdef USE_TESSFACE_DEFAULT
@@ -432,14 +442,14 @@ void EDBM_select_flush(BMEditMesh *em)
BM_mesh_select_flush(em->bm);
}
-void EDBM_select_more(BMEditMesh *em)
+void EDBM_select_more(BMEditMesh *em, const bool use_face_step)
{
BMOperator bmop;
- int use_faces = em->selectmode == SCE_SELECT_FACE;
+ const bool use_faces = (em->selectmode == SCE_SELECT_FACE);
BMO_op_initf(em->bm, &bmop, BMO_FLAG_DEFAULTS,
- "region_extend geom=%hvef use_constrict=%b use_faces=%b",
- BM_ELEM_SELECT, false, use_faces);
+ "region_extend geom=%hvef use_contract=%b use_faces=%b use_face_step=%b",
+ BM_ELEM_SELECT, false, use_faces, use_face_step);
BMO_op_exec(em->bm, &bmop);
/* don't flush selection in edge/vertex mode */
BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_out, "geom.out", BM_ALL_NOLOOP, BM_ELEM_SELECT, use_faces ? true : false);
@@ -448,14 +458,14 @@ void EDBM_select_more(BMEditMesh *em)
EDBM_selectmode_flush(em);
}
-void EDBM_select_less(BMEditMesh *em)
+void EDBM_select_less(BMEditMesh *em, const bool use_face_step)
{
BMOperator bmop;
- int use_faces = em->selectmode == SCE_SELECT_FACE;
+ const bool use_faces = (em->selectmode == SCE_SELECT_FACE);
BMO_op_initf(em->bm, &bmop, BMO_FLAG_DEFAULTS,
- "region_extend geom=%hvef use_constrict=%b use_faces=%b",
- BM_ELEM_SELECT, true, use_faces);
+ "region_extend geom=%hvef use_contract=%b use_faces=%b use_face_step=%b",
+ BM_ELEM_SELECT, true, use_faces, use_face_step);
BMO_op_exec(em->bm, &bmop);
/* don't flush selection in edge/vertex mode */
BMO_slot_buffer_hflag_disable(em->bm, bmop.slots_out, "geom.out", BM_ALL_NOLOOP, BM_ELEM_SELECT, use_faces ? true : false);
@@ -524,30 +534,56 @@ static void *editbtMesh_to_undoMesh(void *emv, void *obdata)
return um;
}
-static void undoMesh_to_editbtMesh(void *umv, void *em_v, void *UNUSED(obdata))
+static void undoMesh_to_editbtMesh(void *umv, void *em_v, void *obdata)
{
BMEditMesh *em = em_v, *em_tmp;
Object *ob = em->ob;
UndoMesh *um = umv;
BMesh *bm;
+ Key *key = ((Mesh *) obdata)->key;
const BMAllocTemplate allocsize = BMALLOC_TEMPLATE_FROM_ME(&um->me);
- ob->shapenr = em->bm->shapenr = um->shapenr;
+ em->bm->shapenr = um->shapenr;
EDBM_mesh_free(em);
bm = BM_mesh_create(&allocsize);
- BM_mesh_bm_from_me(bm, &um->me, true, false, ob->shapenr);
+ BM_mesh_bm_from_me(bm, &um->me, true, false, um->shapenr);
em_tmp = BKE_editmesh_create(bm, true);
*em = *em_tmp;
-
+
em->selectmode = um->selectmode;
bm->selectmode = um->selectmode;
em->ob = ob;
+ /* T35170: Restore the active key on the RealMesh. Otherwise 'fake' offset propagation happens
+ * if the active is a basis for any other. */
+ if (key && (key->type == KEY_RELATIVE)) {
+ /* Since we can't add, remove or reorder keyblocks in editmode, it's safe to assume
+ * shapenr from restored bmesh and keyblock indices are in sync. */
+ const int kb_act_idx = ob->shapenr - 1;
+
+ /* If it is, let's patch the current mesh key block to its restored value.
+ * Else, the offsets won't be computed and it won't matter. */
+ if (BKE_keyblock_is_basis(key, kb_act_idx)) {
+ KeyBlock *kb_act = BLI_findlink(&key->block, kb_act_idx);
+
+ if (kb_act->totelem != um->me.totvert) {
+ /* The current mesh has some extra/missing verts compared to the undo, adjust. */
+ MEM_SAFE_FREE(kb_act->data);
+ kb_act->data = MEM_mallocN((size_t)(key->elemsize * bm->totvert), __func__);
+ kb_act->totelem = um->me.totvert;
+ }
+
+ BKE_keyblock_update_from_mesh(&um->me, kb_act);
+ }
+ }
+
+ ob->shapenr = um->shapenr;
+
MEM_freeN(em_tmp);
}
@@ -579,7 +615,9 @@ void undo_push_mesh(bContext *C, const char *name)
/**
* Return a new UVVertMap from the editmesh
*/
-UvVertMap *BM_uv_vert_map_create(BMesh *bm, bool use_select, const float limit[2])
+UvVertMap *BM_uv_vert_map_create(
+ BMesh *bm,
+ const float limit[2], const bool use_select, const bool use_winding)
{
BMVert *ev;
BMFace *efa;
@@ -591,11 +629,14 @@ UvVertMap *BM_uv_vert_map_create(BMesh *bm, bool use_select, const float limit[2
/* MTexPoly *tf; */ /* UNUSED */
MLoopUV *luv;
unsigned int a;
- int totverts, i, totuv;
+ int totverts, i, totuv, totfaces;
const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
+ bool *winding = NULL;
+ BLI_buffer_declare_static(vec2f, tf_uv_buf, BLI_BUFFER_NOP, BM_DEFAULT_NGON_STACK_SIZE);
BM_mesh_elem_index_ensure(bm, BM_VERT | BM_FACE);
+ totfaces = bm->totface;
totverts = bm->totvert;
totuv = 0;
@@ -616,35 +657,46 @@ UvVertMap *BM_uv_vert_map_create(BMesh *bm, bool use_select, const float limit[2
vmap->vert = (UvMapVert **)MEM_callocN(sizeof(*vmap->vert) * totverts, "UvMapVert_pt");
buf = vmap->buf = (UvMapVert *)MEM_callocN(sizeof(*vmap->buf) * totuv, "UvMapVert");
+ if (use_winding) {
+ winding = MEM_callocN(sizeof(*winding) * totfaces, "winding");
+ }
if (!vmap->vert || !vmap->buf) {
BKE_mesh_uv_vert_map_free(vmap);
return NULL;
}
- a = 0;
- BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
+ BM_ITER_MESH_INDEX (efa, &iter, bm, BM_FACES_OF_MESH, a) {
if ((use_select == false) || BM_elem_flag_test(efa, BM_ELEM_SELECT)) {
- i = 0;
- BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
+ float (*tf_uv)[2];
+
+ if (use_winding) {
+ tf_uv = (float (*)[2])BLI_buffer_resize_data(&tf_uv_buf, vec2f, efa->len);
+ }
+
+ BM_ITER_ELEM_INDEX(l, &liter, efa, BM_LOOPS_OF_FACE, i) {
buf->tfindex = i;
buf->f = a;
buf->separate = 0;
buf->next = vmap->vert[BM_elem_index_get(l->v)];
vmap->vert[BM_elem_index_get(l->v)] = buf;
-
buf++;
- i++;
+
+ if (use_winding) {
+ luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
+ copy_v2_v2(tf_uv[i], luv->uv);
+ }
}
- }
- a++;
+ if (use_winding) {
+ winding[a] = cross_poly_v2((const float (*)[2])tf_uv, efa->len) > 0;
+ }
+ }
}
/* sort individual uvs for each vert */
- a = 0;
- BM_ITER_MESH (ev, &iter, bm, BM_VERTS_OF_MESH) {
+ BM_ITER_MESH_INDEX (ev, &iter, bm, BM_VERTS_OF_MESH, a) {
UvMapVert *newvlist = NULL, *vlist = vmap->vert[a];
UvMapVert *iterv, *v, *lastv, *next;
float *uv, *uv2, uvdiff[2];
@@ -676,7 +728,9 @@ UvVertMap *BM_uv_vert_map_create(BMesh *bm, bool use_select, const float limit[2
sub_v2_v2v2(uvdiff, uv2, uv);
- if (fabsf(uvdiff[0]) < limit[0] && fabsf(uvdiff[1]) < limit[1]) {
+ if (fabsf(uvdiff[0]) < limit[0] && fabsf(uvdiff[1]) < limit[1] &&
+ (!use_winding || winding[iterv->f] == winding[v->f]))
+ {
if (lastv) lastv->next = next;
else vlist = next;
iterv->next = newvlist;
@@ -693,9 +747,14 @@ UvVertMap *BM_uv_vert_map_create(BMesh *bm, bool use_select, const float limit[2
}
vmap->vert[a] = newvlist;
- a++;
}
+ if (use_winding) {
+ MEM_freeN(winding);
+ }
+
+ BLI_buffer_free(&tf_uv_buf);
+
return vmap;
}
@@ -709,7 +768,9 @@ UvMapVert *BM_uv_vert_map_at_index(UvVertMap *vmap, unsigned int v)
/* A specialized vert map used by stitch operator */
-UvElementMap *BM_uv_element_map_create(BMesh *bm, const bool selected, const bool do_islands)
+UvElementMap *BM_uv_element_map_create(
+ BMesh *bm,
+ const bool selected, const bool use_winding, const bool do_islands)
{
BMVert *ev;
BMFace *efa;
@@ -718,29 +779,20 @@ UvElementMap *BM_uv_element_map_create(BMesh *bm, const bool selected, const boo
/* vars from original func */
UvElementMap *element_map;
UvElement *buf;
- UvElement *islandbuf;
- /* island number for faces */
- int *island_number;
+ bool *winding;
+ BLI_buffer_declare_static(vec2f, tf_uv_buf, BLI_BUFFER_NOP, BM_DEFAULT_NGON_STACK_SIZE);
MLoopUV *luv;
- int totverts, i, totuv, j, nislands = 0, islandbufsize = 0;
-
- unsigned int *map;
- BMFace **stack;
- int stacksize = 0;
+ int totverts, totfaces, i, totuv, j;
const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
BM_mesh_elem_index_ensure(bm, BM_VERT | BM_FACE);
+ totfaces = bm->totface;
totverts = bm->totvert;
totuv = 0;
- island_number = MEM_mallocN(sizeof(*stack) * bm->totface, "uv_island_number_face");
- if (!island_number) {
- return NULL;
- }
-
/* generate UvElement array */
BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
if (!selected || BM_elem_flag_test(efa, BM_ELEM_SELECT)) {
@@ -749,28 +801,31 @@ UvElementMap *BM_uv_element_map_create(BMesh *bm, const bool selected, const boo
}
if (totuv == 0) {
- MEM_freeN(island_number);
return NULL;
}
+
element_map = (UvElementMap *)MEM_callocN(sizeof(*element_map), "UvElementMap");
- if (!element_map) {
- MEM_freeN(island_number);
- return NULL;
- }
element_map->totalUVs = totuv;
element_map->vert = (UvElement **)MEM_callocN(sizeof(*element_map->vert) * totverts, "UvElementVerts");
buf = element_map->buf = (UvElement *)MEM_callocN(sizeof(*element_map->buf) * totuv, "UvElement");
- if (!element_map->vert || !element_map->buf) {
- BM_uv_element_map_free(element_map);
- MEM_freeN(island_number);
- return NULL;
+ if (use_winding) {
+ winding = MEM_mallocN(sizeof(*winding) * totfaces, "winding");
}
- j = 0;
- BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
- island_number[j++] = INVALID_ISLAND;
+ BM_ITER_MESH_INDEX (efa, &iter, bm, BM_FACES_OF_MESH, j) {
+
+ if (use_winding) {
+ winding[j] = false;
+ }
+
if (!selected || BM_elem_flag_test(efa, BM_ELEM_SELECT)) {
+ float (*tf_uv)[2];
+
+ if (use_winding) {
+ tf_uv = (float (*)[2])BLI_buffer_resize_data(&tf_uv_buf, vec2f, efa->len);
+ }
+
BM_ITER_ELEM_INDEX (l, &liter, efa, BM_LOOPS_OF_FACE, i) {
buf->l = l;
buf->separate = 0;
@@ -780,14 +835,22 @@ UvElementMap *BM_uv_element_map_create(BMesh *bm, const bool selected, const boo
buf->next = element_map->vert[BM_elem_index_get(l->v)];
element_map->vert[BM_elem_index_get(l->v)] = buf;
+ if (use_winding) {
+ luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
+ copy_v2_v2(tf_uv[i], luv->uv);
+ }
+
buf++;
}
+
+ if (use_winding) {
+ winding[j] = cross_poly_v2((const float (*)[2])tf_uv, efa->len) > 0;
+ }
}
}
/* sort individual uvs for each vert */
- i = 0;
- BM_ITER_MESH (ev, &iter, bm, BM_VERTS_OF_MESH) {
+ BM_ITER_MESH_INDEX (ev, &iter, bm, BM_VERTS_OF_MESH, i) {
UvElement *newvlist = NULL, *vlist = element_map->vert[i];
UvElement *iterv, *v, *lastv, *next;
float *uv, *uv2, uvdiff[2];
@@ -814,7 +877,9 @@ UvElementMap *BM_uv_element_map_create(BMesh *bm, const bool selected, const boo
sub_v2_v2v2(uvdiff, uv2, uv);
- if (fabsf(uvdiff[0]) < STD_UV_CONNECT_LIMIT && fabsf(uvdiff[1]) < STD_UV_CONNECT_LIMIT) {
+ if (fabsf(uvdiff[0]) < STD_UV_CONNECT_LIMIT && fabsf(uvdiff[1]) < STD_UV_CONNECT_LIMIT &&
+ (!use_winding || winding[BM_elem_index_get(iterv->l->f)] == winding[BM_elem_index_get(v->l->f)]))
+ {
if (lastv) lastv->next = next;
else vlist = next;
iterv->next = newvlist;
@@ -831,14 +896,28 @@ UvElementMap *BM_uv_element_map_create(BMesh *bm, const bool selected, const boo
}
element_map->vert[i] = newvlist;
- i++;
+ }
+
+ if (use_winding) {
+ MEM_freeN(winding);
}
if (do_islands) {
+ unsigned int *map;
+ BMFace **stack;
+ int stacksize = 0;
+ UvElement *islandbuf;
+ /* island number for faces */
+ int *island_number = NULL;
+
+ int nislands = 0, islandbufsize = 0;
+
/* map holds the map from current vmap->buf to the new, sorted map */
map = MEM_mallocN(sizeof(*map) * totuv, "uvelement_remap");
stack = MEM_mallocN(sizeof(*stack) * bm->totface, "uv_island_face_stack");
islandbuf = MEM_callocN(sizeof(*islandbuf) * totuv, "uvelement_island_buffer");
+ island_number = MEM_mallocN(sizeof(*island_number) * totfaces, "uv_island_number_face");
+ copy_vn_i(island_number, totfaces, INVALID_ISLAND);
/* at this point, every UvElement in vert points to a UvElement sharing the same vertex. Now we should sort uv's in islands. */
for (i = 0; i < totuv; i++) {
@@ -887,6 +966,8 @@ UvElementMap *BM_uv_element_map_create(BMesh *bm, const bool selected, const boo
}
}
+ MEM_freeN(island_number);
+
/* remap */
for (i = 0; i < bm->totvert; i++) {
/* important since we may do selection only. Some of these may be NULL */
@@ -895,14 +976,6 @@ UvElementMap *BM_uv_element_map_create(BMesh *bm, const bool selected, const boo
}
element_map->islandIndices = MEM_callocN(sizeof(*element_map->islandIndices) * nislands, "UvElementMap_island_indices");
- if (!element_map->islandIndices) {
- MEM_freeN(islandbuf);
- MEM_freeN(stack);
- MEM_freeN(map);
- BM_uv_element_map_free(element_map);
- MEM_freeN(island_number);
- }
-
j = 0;
for (i = 0; i < totuv; i++) {
UvElement *element = element_map->buf[i].next;
@@ -924,7 +997,8 @@ UvElementMap *BM_uv_element_map_create(BMesh *bm, const bool selected, const boo
MEM_freeN(stack);
MEM_freeN(map);
}
- MEM_freeN(island_number);
+
+ BLI_buffer_free(&tf_uv_buf);
return element_map;
}
@@ -1002,26 +1076,19 @@ static BMVert *cache_mirr_intptr_as_bmvert(intptr_t *index_lookup, int index)
}
/**
- * [note: I've decided to use ideasman's code for non-editmode stuff, but since
- * it has a big "not for editmode!" disclaimer, I'm going to keep what I have here
- * - joeedh]
+ * Mirror editing API, usage:
*
- * x-mirror editing api. usage:
+ * \code{.c}
+ * EDBM_verts_mirror_cache_begin(em, ...);
*
- * EDBM_verts_mirror_cache_begin(em);
- * ...
- * ...
- * BM_ITER_MESH (v, &iter, em->bm, BM_VERTS_OF_MESH) {
- * mirrorv = EDBM_verts_mirror_get(em, v);
- * }
- * ...
- * ...
- * EDBM_verts_mirror_cache_end(em);
+ * BM_ITER_MESH (v, &iter, em->bm, BM_VERTS_OF_MESH) {
+ * v_mirror = EDBM_verts_mirror_get(em, v);
+ * e_mirror = EDBM_verts_mirror_get_edge(em, e);
+ * f_mirror = EDBM_verts_mirror_get_face(em, f);
+ * }
*
- * \param use_self Allow a vertex to reference its self.
- * \param use_select Only cache selected verts.
- *
- * \note why do we only allow x axis mirror editing?
+ * EDBM_verts_mirror_cache_end(em);
+ * \endcode
*/
/* BM_SEARCH_MAXDIST is too big, copied from 2.6x MOC_THRESH, should become a
@@ -1046,9 +1113,10 @@ void EDBM_verts_mirror_cache_begin_ex(BMEditMesh *em, const int axis, const bool
BMVert *v;
int cd_vmirr_offset;
int i;
+ const float maxdist_sq = SQUARE(maxdist);
/* one or the other is used depending if topo is enabled */
- struct BMBVHTree *tree = NULL;
+ KDTree *tree = NULL;
MirrTopoStore_t mesh_topo_store = {NULL, -1, -1, -1};
BM_mesh_elem_table_ensure(bm, BM_VERT);
@@ -1073,7 +1141,11 @@ void EDBM_verts_mirror_cache_begin_ex(BMEditMesh *em, const int axis, const bool
ED_mesh_mirrtopo_init(me, -1, &mesh_topo_store, true);
}
else {
- tree = BKE_bmbvh_new_from_editmesh(em, 0, NULL, false);
+ tree = BLI_kdtree_new(bm->totvert);
+ BM_ITER_MESH_INDEX (v, &iter, bm, BM_VERTS_OF_MESH, i) {
+ BLI_kdtree_insert(tree, i, v->co);
+ }
+ BLI_kdtree_balance(tree);
}
#define VERT_INTPTR(_v, _i) r_index ? &r_index[_i] : BM_ELEM_CD_GET_VOID_P(_v, cd_vmirr_offset);
@@ -1093,10 +1165,19 @@ void EDBM_verts_mirror_cache_begin_ex(BMEditMesh *em, const int axis, const bool
v_mirr = cache_mirr_intptr_as_bmvert(mesh_topo_store.index_lookup, i);
}
else {
+ int i_mirr;
float co[3];
copy_v3_v3(co, v->co);
co[axis] *= -1.0f;
- v_mirr = BKE_bmbvh_find_vert_closest(tree, co, maxdist);
+
+ v_mirr = NULL;
+ i_mirr = BLI_kdtree_find_nearest(tree, co, NULL);
+ if (i_mirr != -1) {
+ BMVert *v_test = BM_vert_at_index(bm, i_mirr);
+ if (len_squared_v3v3(co, v_test->co) < maxdist_sq) {
+ v_mirr = v_test;
+ }
+ }
}
if (v_mirr && (use_self || (v_mirr != v))) {
@@ -1118,7 +1199,7 @@ void EDBM_verts_mirror_cache_begin_ex(BMEditMesh *em, const int axis, const bool
ED_mesh_mirrtopo_free(&mesh_topo_store);
}
else {
- BKE_bmbvh_free(tree);
+ BLI_kdtree_free(tree);
}
}
diff --git a/source/blender/editors/mesh/mesh_data.c b/source/blender/editors/mesh/mesh_data.c
index bf8559add6f..a2054a5f43c 100644
--- a/source/blender/editors/mesh/mesh_data.c
+++ b/source/blender/editors/mesh/mesh_data.c
@@ -43,14 +43,13 @@
#include "BKE_context.h"
#include "BKE_depsgraph.h"
-#include "BKE_image.h"
#include "BKE_library.h"
#include "BKE_main.h"
#include "BKE_mesh.h"
+#include "BKE_paint.h"
#include "BKE_report.h"
#include "BKE_editmesh.h"
-#include "RNA_access.h"
#include "RNA_define.h"
#include "WM_api.h"
@@ -58,6 +57,7 @@
#include "ED_mesh.h"
#include "ED_object.h"
+#include "ED_screen.h"
#include "ED_uvedit.h"
#include "ED_view3d.h"
@@ -335,6 +335,26 @@ int ED_mesh_uv_texture_add(Mesh *me, const char *name, const bool active_set)
return layernum_dst;
}
+void ED_mesh_uv_texture_ensure(struct Mesh *me, const char *name)
+{
+ BMEditMesh *em;
+ int layernum_dst;
+
+ if (me->edit_btmesh) {
+ em = me->edit_btmesh;
+
+ layernum_dst = CustomData_number_of_layers(&em->bm->pdata, CD_MTEXPOLY);
+ if (layernum_dst == 0)
+ ED_mesh_uv_texture_add(me, name, true);
+ }
+ else {
+ layernum_dst = CustomData_number_of_layers(&me->pdata, CD_MTEXPOLY);
+ if (layernum_dst == 0)
+ ED_mesh_uv_texture_add(me, name, true);
+ }
+}
+
+
bool ED_mesh_uv_texture_remove_index(Mesh *me, const int n)
{
CustomData *pdata = GET_CD_DATA(me, pdata), *ldata = GET_CD_DATA(me, ldata);
@@ -409,7 +429,7 @@ int ED_mesh_color_add(Mesh *me, const char *name, const bool active_set)
/* copy data from active vertex color layer */
if (layernum) {
const int layernum_dst = CustomData_get_active_layer(&em->bm->ldata, CD_MLOOPCOL);
- BM_data_layer_copy(em->bm, &em->bm->ldata, CD_MLOOPCOL, layernum, layernum_dst);
+ BM_data_layer_copy(em->bm, &em->bm->ldata, CD_MLOOPCOL, layernum_dst, layernum);
}
if (active_set || layernum == 0) {
CustomData_set_layer_active(&em->bm->ldata, CD_MLOOPCOL, layernum);
@@ -502,6 +522,12 @@ static int mesh_uv_texture_add_exec(bContext *C, wmOperator *UNUSED(op))
if (ED_mesh_uv_texture_add(me, NULL, true) == -1)
return OPERATOR_CANCELLED;
+ if (ob->mode & OB_MODE_TEXTURE_PAINT) {
+ Scene *scene = CTX_data_scene(C);
+ BKE_paint_proj_mesh_data_check(scene, ob, NULL, NULL, NULL, NULL);
+ WM_event_add_notifier(C, NC_SCENE | ND_TOOLSETTINGS, NULL);
+ }
+
return OPERATOR_FINISHED;
}
@@ -544,24 +570,13 @@ static int drop_named_image_invoke(bContext *C, wmOperator *op, const wmEvent *e
return OPERATOR_CANCELLED;
}
- /* check input variables */
- if (RNA_struct_property_is_set(op->ptr, "filepath")) {
- char path[FILE_MAX];
-
- RNA_string_get(op->ptr, "filepath", path);
- ima = BKE_image_load_exists(path);
- }
- else {
- char name[MAX_ID_NAME - 2];
- RNA_string_get(op->ptr, "name", name);
- ima = (Image *)BKE_libblock_find_name(ID_IM, name);
- }
-
+ ima = (Image *)WM_operator_drop_load_path(C, op, ID_IM);
if (!ima) {
- BKE_report(op->reports, RPT_ERROR, "Not an image");
return OPERATOR_CANCELLED;
}
-
+ /* handled below */
+ id_us_min((ID *)ima);
+
/* put mesh in editmode */
obedit = base->object;
@@ -612,6 +627,7 @@ void MESH_OT_drop_named_image(wmOperatorType *ot)
/* properties */
RNA_def_string(ot->srna, "name", "Image", MAX_ID_NAME - 2, "Name", "Image name to assign");
RNA_def_string(ot->srna, "filepath", "Path", FILE_MAX, "Filepath", "Path to image file");
+ RNA_def_boolean(ot->srna, "relative_path", true, "Relative Path", "Select the file relative to the blend file");
}
static int mesh_uv_texture_remove_exec(bContext *C, wmOperator *UNUSED(op))
@@ -622,6 +638,12 @@ static int mesh_uv_texture_remove_exec(bContext *C, wmOperator *UNUSED(op))
if (!ED_mesh_uv_texture_remove_active(me))
return OPERATOR_CANCELLED;
+ if (ob->mode & OB_MODE_TEXTURE_PAINT) {
+ Scene *scene = CTX_data_scene(C);
+ BKE_paint_proj_mesh_data_check(scene, ob, NULL, NULL, NULL, NULL);
+ WM_event_add_notifier(C, NC_SCENE | ND_TOOLSETTINGS, NULL);
+ }
+
return OPERATOR_FINISHED;
}
@@ -726,7 +748,7 @@ static int mesh_customdata_clear_exec__internal(bContext *C,
}
/* Clear Mask */
-static int mesh_customdata_clear_mask_poll(bContext *C)
+static int mesh_customdata_mask_clear_poll(bContext *C)
{
Object *ob = ED_object_context(C);
if (ob && ob->type == OB_MESH) {
@@ -750,7 +772,7 @@ static int mesh_customdata_clear_mask_poll(bContext *C)
}
return false;
}
-static int mesh_customdata_clear_mask_exec(bContext *C, wmOperator *UNUSED(op))
+static int mesh_customdata_mask_clear_exec(bContext *C, wmOperator *UNUSED(op))
{
int ret_a = mesh_customdata_clear_exec__internal(C, BM_VERT, CD_PAINT_MASK);
int ret_b = mesh_customdata_clear_exec__internal(C, BM_LOOP, CD_GRID_PAINT_MASK);
@@ -765,24 +787,27 @@ static int mesh_customdata_clear_mask_exec(bContext *C, wmOperator *UNUSED(op))
}
}
-void MESH_OT_customdata_clear_mask(wmOperatorType *ot)
+void MESH_OT_customdata_mask_clear(wmOperatorType *ot)
{
/* identifiers */
ot->name = "Clear Sculpt-Mask Data";
- ot->idname = "MESH_OT_customdata_clear_mask";
+ ot->idname = "MESH_OT_customdata_mask_clear";
ot->description = "Clear vertex sculpt masking data from the mesh";
/* api callbacks */
- ot->exec = mesh_customdata_clear_mask_exec;
- ot->poll = mesh_customdata_clear_mask_poll;
+ ot->exec = mesh_customdata_mask_clear_exec;
+ ot->poll = mesh_customdata_mask_clear_poll;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-/* Clear Skin */
-static int mesh_customdata_clear_skin_poll(bContext *C)
+/**
+ * Clear Skin
+ * \return -1 invalid state, 0 no skin, 1 has skin.
+ */
+static int mesh_customdata_skin_state(bContext *C)
{
Object *ob = ED_object_context(C);
@@ -790,28 +815,130 @@ static int mesh_customdata_clear_skin_poll(bContext *C)
Mesh *me = ob->data;
if (me->id.lib == NULL) {
CustomData *data = GET_CD_DATA(me, vdata);
- if (CustomData_has_layer(data, CD_MVERT_SKIN)) {
- return true;
- }
+ return CustomData_has_layer(data, CD_MVERT_SKIN);
}
}
- return false;
+ return -1;
+}
+
+static int mesh_customdata_skin_add_poll(bContext *C)
+{
+ return (mesh_customdata_skin_state(C) == 0);
+}
+
+static int mesh_customdata_skin_add_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ Object *ob = ED_object_context(C);
+ Mesh *me = ob->data;
+
+ BKE_mesh_ensure_skin_customdata(me);
+
+ DAG_id_tag_update(&me->id, 0);
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, me);
+
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_customdata_skin_add(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Add Skin Data";
+ ot->idname = "MESH_OT_customdata_skin_add";
+ ot->description = "Add a vertex skin layer";
+
+ /* api callbacks */
+ ot->exec = mesh_customdata_skin_add_exec;
+ ot->poll = mesh_customdata_skin_add_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-static int mesh_customdata_clear_skin_exec(bContext *C, wmOperator *UNUSED(op))
+
+static int mesh_customdata_skin_clear_poll(bContext *C)
+{
+ return (mesh_customdata_skin_state(C) == 1);
+}
+
+static int mesh_customdata_skin_clear_exec(bContext *C, wmOperator *UNUSED(op))
{
return mesh_customdata_clear_exec__internal(C, BM_VERT, CD_MVERT_SKIN);
}
-void MESH_OT_customdata_clear_skin(wmOperatorType *ot)
+void MESH_OT_customdata_skin_clear(wmOperatorType *ot)
{
/* identifiers */
ot->name = "Clear Skin Data";
- ot->idname = "MESH_OT_customdata_clear_skin";
+ ot->idname = "MESH_OT_customdata_skin_clear";
ot->description = "Clear vertex skin layer";
/* api callbacks */
- ot->exec = mesh_customdata_clear_skin_exec;
- ot->poll = mesh_customdata_clear_skin_poll;
+ ot->exec = mesh_customdata_skin_clear_exec;
+ ot->poll = mesh_customdata_skin_clear_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+/* Clear custom loop normals */
+static int mesh_customdata_custom_splitnormals_add_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ Object *ob = ED_object_context(C);
+ Mesh *me = ob->data;
+
+ if (!BKE_mesh_has_custom_loop_normals(me)) {
+ CustomData *data = GET_CD_DATA(me, ldata);
+
+ if (me->edit_btmesh) {
+ BM_data_layer_add(me->edit_btmesh->bm, data, CD_CUSTOMLOOPNORMAL);
+ }
+ else {
+ CustomData_add_layer(data, CD_CUSTOMLOOPNORMAL, CD_DEFAULT, NULL, me->totloop);
+ }
+
+ DAG_id_tag_update(&me->id, 0);
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, me);
+
+ return OPERATOR_FINISHED;
+ }
+ return OPERATOR_CANCELLED;
+}
+
+void MESH_OT_customdata_custom_splitnormals_add(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Add Custom Split Normals Data";
+ ot->idname = "MESH_OT_customdata_custom_splitnormals_add";
+ ot->description = "Add a custom split normals layer, if none exists yet";
+
+ /* api callbacks */
+ ot->exec = mesh_customdata_custom_splitnormals_add_exec;
+ ot->poll = ED_operator_object_active_editable_mesh;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+static int mesh_customdata_custom_splitnormals_clear_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ Object *ob = ED_object_context(C);
+ Mesh *me = ob->data;
+
+ if (BKE_mesh_has_custom_loop_normals(me)) {
+ return mesh_customdata_clear_exec__internal(C, BM_LOOP, CD_CUSTOMLOOPNORMAL);
+ }
+ return OPERATOR_CANCELLED;
+}
+
+void MESH_OT_customdata_custom_splitnormals_clear(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Clear Custom Split Normals Data";
+ ot->idname = "MESH_OT_customdata_custom_splitnormals_clear";
+ ot->description = "Remove the custom split normals layer, if it exists";
+
+ /* api callbacks */
+ ot->exec = mesh_customdata_custom_splitnormals_clear_exec;
+ ot->poll = ED_operator_object_active_editable_mesh;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
@@ -1148,7 +1275,7 @@ void ED_mesh_polys_add(Mesh *mesh, ReportList *reports, int count)
mesh_add_polys(mesh, count);
}
-void ED_mesh_calc_tessface(Mesh *mesh)
+void ED_mesh_calc_tessface(Mesh *mesh, bool free_mpoly)
{
if (mesh->edit_btmesh) {
BKE_editmesh_tessface_calc(mesh->edit_btmesh);
@@ -1156,6 +1283,17 @@ void ED_mesh_calc_tessface(Mesh *mesh)
else {
BKE_mesh_tessface_calc(mesh);
}
+ if (free_mpoly) {
+ CustomData_free(&mesh->ldata, mesh->totloop);
+ CustomData_free(&mesh->pdata, mesh->totpoly);
+ mesh->totloop = 0;
+ mesh->totpoly = 0;
+ mesh->mloop = NULL;
+ mesh->mloopcol = NULL;
+ mesh->mloopuv = NULL;
+ mesh->mpoly = NULL;
+ mesh->mtpoly = NULL;
+ }
}
void ED_mesh_report_mirror_ex(wmOperator *op, int totmirr, int totfail,
diff --git a/source/blender/editors/mesh/mesh_intern.h b/source/blender/editors/mesh/mesh_intern.h
index 76f6cb5ebb8..c56465f570a 100644
--- a/source/blender/editors/mesh/mesh_intern.h
+++ b/source/blender/editors/mesh/mesh_intern.h
@@ -34,14 +34,9 @@
#ifndef __MESH_INTERN_H__
#define __MESH_INTERN_H__
-struct BMEdge;
struct BMEditMesh;
-struct BMFace;
-struct BMHeader;
struct BMOperator;
-struct BMesh;
struct EnumPropertyItem;
-struct ViewContext;
struct bContext;
struct wmKeyConfig;
struct wmKeyMap;
@@ -137,6 +132,7 @@ void MESH_OT_rip_edge(struct wmOperatorType *ot);
/* *** editmesh_select.c *** */
void MESH_OT_select_similar(struct wmOperatorType *ot);
+void MESH_OT_select_similar_region(struct wmOperatorType *ot);
void MESH_OT_select_mode(struct wmOperatorType *ot);
void MESH_OT_loop_multi_select(struct wmOperatorType *ot);
void MESH_OT_loop_select(struct wmOperatorType *ot);
@@ -174,9 +170,13 @@ void MESH_OT_normals_make_consistent(struct wmOperatorType *ot);
void MESH_OT_vertices_smooth(struct wmOperatorType *ot);
void MESH_OT_vertices_smooth_laplacian(struct wmOperatorType *ot);
void MESH_OT_vert_connect(struct wmOperatorType *ot);
+void MESH_OT_vert_connect_path(struct wmOperatorType *ot);
+void MESH_OT_vert_connect_concave(struct wmOperatorType *ot);
void MESH_OT_vert_connect_nonplanar(struct wmOperatorType *ot);
+void MESH_OT_face_make_planar(struct wmOperatorType *ot);
void MESH_OT_edge_split(struct wmOperatorType *ot);
void MESH_OT_bridge_edge_loops(struct wmOperatorType *ot);
+void MESH_OT_offset_edge_loops(struct wmOperatorType *ot);
void MESH_OT_wireframe(struct wmOperatorType *ot);
void MESH_OT_convex_hull(struct wmOperatorType *ot);
void MESH_OT_symmetrize(struct wmOperatorType *ot);
@@ -234,8 +234,11 @@ void MESH_OT_uv_texture_remove(struct wmOperatorType *ot);
void MESH_OT_vertex_color_add(struct wmOperatorType *ot);
void MESH_OT_vertex_color_remove(struct wmOperatorType *ot);
/* no create_mask yet */
-void MESH_OT_customdata_clear_mask(struct wmOperatorType *ot);
-void MESH_OT_customdata_clear_skin(struct wmOperatorType *ot);
+void MESH_OT_customdata_mask_clear(struct wmOperatorType *ot);
+void MESH_OT_customdata_skin_add(struct wmOperatorType *ot);
+void MESH_OT_customdata_skin_clear(struct wmOperatorType *ot);
+void MESH_OT_customdata_custom_splitnormals_add(struct wmOperatorType *ot);
+void MESH_OT_customdata_custom_splitnormals_clear(struct wmOperatorType *ot);
void MESH_OT_drop_named_image(struct wmOperatorType *ot);
diff --git a/source/blender/editors/mesh/mesh_navmesh.c b/source/blender/editors/mesh/mesh_navmesh.c
index 440ab14dacd..1c36826b882 100644
--- a/source/blender/editors/mesh/mesh_navmesh.c
+++ b/source/blender/editors/mesh/mesh_navmesh.c
@@ -84,7 +84,7 @@ static void createVertsTrisData(bContext *C, LinkNode *obs,
for (oblink = obs; oblink; oblink = oblink->next) {
ob = (Object *) oblink->link;
dm = mesh_create_derived_no_virtual(scene, ob, NULL, CD_MASK_MESH);
- BLI_linklist_append(&dms, (void *)dm);
+ BLI_linklist_prepend(&dms, dm);
nverts += dm->getNumVerts(dm);
nfaces = dm->getNumTessFaces(dm);
@@ -325,7 +325,7 @@ static Object *createRepresentation(bContext *C, struct recast_polyMesh *pmesh,
if (createob) {
/* create new object */
- obedit = ED_object_add_type(C, OB_MESH, co, rot, false, lay);
+ obedit = ED_object_add_type(C, OB_MESH, "Navmesh", co, rot, false, lay);
}
else {
obedit = base->object;
@@ -429,7 +429,6 @@ static Object *createRepresentation(bContext *C, struct recast_polyMesh *pmesh,
obedit->gameflag &= ~OB_COLLISION;
obedit->gameflag |= OB_NAVMESH;
obedit->body_type = OB_BODY_TYPE_NAVMESH;
- rename_id((ID *)obedit, "Navmesh");
}
BKE_mesh_ensure_navmesh(obedit->data);
@@ -452,7 +451,7 @@ static int navmesh_create_exec(bContext *C, wmOperator *op)
}
}
else {
- BLI_linklist_append(&obs, (void *)base->object);
+ BLI_linklist_prepend(&obs, base->object);
}
}
}
diff --git a/source/blender/editors/mesh/mesh_ops.c b/source/blender/editors/mesh/mesh_ops.c
index 31653efa735..9718e63f012 100644
--- a/source/blender/editors/mesh/mesh_ops.c
+++ b/source/blender/editors/mesh/mesh_ops.c
@@ -130,6 +130,7 @@ void ED_operatortypes_mesh(void)
WM_operatortype_append(MESH_OT_edge_face_add);
WM_operatortype_append(MESH_OT_shortest_path_pick);
WM_operatortype_append(MESH_OT_select_similar);
+ WM_operatortype_append(MESH_OT_select_similar_region);
WM_operatortype_append(MESH_OT_select_mode);
WM_operatortype_append(MESH_OT_loop_multi_select);
WM_operatortype_append(MESH_OT_mark_seam);
@@ -150,8 +151,11 @@ void ED_operatortypes_mesh(void)
WM_operatortype_append(MESH_OT_uv_texture_remove);
WM_operatortype_append(MESH_OT_vertex_color_add);
WM_operatortype_append(MESH_OT_vertex_color_remove);
- WM_operatortype_append(MESH_OT_customdata_clear_mask);
- WM_operatortype_append(MESH_OT_customdata_clear_skin);
+ WM_operatortype_append(MESH_OT_customdata_mask_clear);
+ WM_operatortype_append(MESH_OT_customdata_skin_add);
+ WM_operatortype_append(MESH_OT_customdata_skin_clear);
+ WM_operatortype_append(MESH_OT_customdata_custom_splitnormals_add);
+ WM_operatortype_append(MESH_OT_customdata_custom_splitnormals_clear);
WM_operatortype_append(MESH_OT_drop_named_image);
WM_operatortype_append(MESH_OT_edgering_select);
@@ -160,7 +164,10 @@ void ED_operatortypes_mesh(void)
WM_operatortype_append(MESH_OT_solidify);
WM_operatortype_append(MESH_OT_select_nth);
WM_operatortype_append(MESH_OT_vert_connect);
+ WM_operatortype_append(MESH_OT_vert_connect_path);
+ WM_operatortype_append(MESH_OT_vert_connect_concave);
WM_operatortype_append(MESH_OT_vert_connect_nonplanar);
+ WM_operatortype_append(MESH_OT_face_make_planar);
WM_operatortype_append(MESH_OT_knife_tool);
WM_operatortype_append(MESH_OT_knife_project);
@@ -170,6 +177,7 @@ void ED_operatortypes_mesh(void)
WM_operatortype_append(MESH_OT_bridge_edge_loops);
WM_operatortype_append(MESH_OT_inset);
+ WM_operatortype_append(MESH_OT_offset_edge_loops);
WM_operatortype_append(MESH_OT_intersect);
WM_operatortype_append(MESH_OT_face_split_by_edges);
WM_operatortype_append(MESH_OT_poke);
@@ -218,6 +226,13 @@ void ED_operatormacros_mesh(void)
otmacro = WM_operatortype_macro_define(ot, "TRANSFORM_OT_edge_slide");
RNA_boolean_set(otmacro->ptr, "release_confirm", false);
+ ot = WM_operatortype_append_macro("MESH_OT_offset_edge_loops_slide", "Offset Edge Slide", "Offset edge loop slide",
+ OPTYPE_UNDO | OPTYPE_REGISTER);
+ WM_operatortype_macro_define(ot, "MESH_OT_offset_edge_loops");
+ otmacro = WM_operatortype_macro_define(ot, "TRANSFORM_OT_edge_slide");
+ RNA_boolean_set(otmacro->ptr, "release_confirm", false);
+ RNA_boolean_set(otmacro->ptr, "single_side", true);
+
ot = WM_operatortype_append_macro("MESH_OT_duplicate_move", "Add Duplicate", "Duplicate mesh and move",
OPTYPE_UNDO | OPTYPE_REGISTER);
WM_operatortype_macro_define(ot, "MESH_OT_duplicate");
@@ -295,7 +310,8 @@ void ED_keymap_mesh(wmKeyConfig *keyconf)
keymap = WM_keymap_find(keyconf, "Mesh", 0, 0);
keymap->poll = ED_operator_editmesh;
- WM_keymap_add_item(keymap, "MESH_OT_loopcut_slide", RKEY, KM_PRESS, KM_CTRL, 0);
+ WM_keymap_add_item(keymap, "MESH_OT_loopcut_slide", RKEY, KM_PRESS, KM_CTRL, 0);
+ WM_keymap_add_item(keymap, "MESH_OT_offset_edge_loops_slide", RKEY, KM_PRESS, KM_CTRL | KM_SHIFT, 0);
WM_keymap_add_item(keymap, "MESH_OT_inset", IKEY, KM_PRESS, 0, 0);
WM_keymap_add_item(keymap, "MESH_OT_poke", PKEY, KM_PRESS, KM_ALT, 0);
kmi = WM_keymap_add_item(keymap, "MESH_OT_bevel", BKEY, KM_PRESS, KM_CTRL, 0);
@@ -342,7 +358,7 @@ void ED_keymap_mesh(wmKeyConfig *keyconf)
WM_keymap_add_item(keymap, "MESH_OT_faces_select_linked_flat", FKEY, KM_PRESS, (KM_CTRL | KM_SHIFT | KM_ALT), 0);
- WM_keymap_add_item(keymap, "MESH_OT_select_similar", GKEY, KM_PRESS, KM_SHIFT, 0);
+ WM_keymap_add_menu(keymap, "VIEW3D_MT_edit_mesh_select_similar", GKEY, KM_PRESS, KM_SHIFT, 0);
/* selection mode */
WM_keymap_add_menu(keymap, "VIEW3D_MT_edit_mesh_select_mode", TABKEY, KM_PRESS, KM_CTRL, 0);
@@ -397,7 +413,7 @@ void ED_keymap_mesh(wmKeyConfig *keyconf)
WM_keymap_add_item(keymap, "MESH_OT_separate", PKEY, KM_PRESS, 0, 0);
WM_keymap_add_item(keymap, "MESH_OT_split", YKEY, KM_PRESS, 0, 0);
- WM_keymap_add_item(keymap, "MESH_OT_vert_connect", JKEY, KM_PRESS, 0, 0);
+ WM_keymap_add_item(keymap, "MESH_OT_vert_connect_path", JKEY, KM_PRESS, 0, 0);
/* Vertex Slide */
WM_keymap_add_item(keymap, "TRANSFORM_OT_vert_slide", VKEY, KM_PRESS, KM_SHIFT, 0);
diff --git a/source/blender/editors/mesh/meshtools.c b/source/blender/editors/mesh/meshtools.c
index 16f4f61f92b..2491685161c 100644
--- a/source/blender/editors/mesh/meshtools.c
+++ b/source/blender/editors/mesh/meshtools.c
@@ -329,7 +329,7 @@ int join_mesh_exec(bContext *C, wmOperator *op)
if (odg) {
/* Search for a match in the new object, and set new index */
for (dg = ob->defbase.first, index = 0; dg; dg = dg->next, index++) {
- if (!strcmp(dg->name, odg->name)) {
+ if (STREQ(dg->name, odg->name)) {
dvert[i].dw[j].def_nr = index;
break;
}
@@ -627,7 +627,7 @@ int join_mesh_shapes_exec(bContext *C, wmOperator *op)
/* first key added, so it was the basis. initialize it with the existing mesh */
kb = BKE_keyblock_add(key, NULL);
- BKE_key_convert_from_mesh(me, kb);
+ BKE_keyblock_convert_from_mesh(me, kb);
}
/* now ready to add new keys from selected meshes */
@@ -895,7 +895,7 @@ int ED_mesh_mirror_get_vert(Object *ob, int index)
index_mirr = eve_mirr ? BM_elem_index_get(eve_mirr) : -1;
}
else {
- index_mirr = mesh_get_x_mirror_vert(ob, index, use_topology);
+ index_mirr = mesh_get_x_mirror_vert(ob, index, use_topology);
}
return index_mirr;
@@ -1082,11 +1082,11 @@ bool ED_mesh_pick_face(bContext *C, Object *ob, const int mval[2], unsigned int
* on an edge in the backbuf, we can still select a face */
float dummy_dist;
- *index = view3d_sample_backbuf_rect(&vc, mval, size, 1, me->totpoly + 1, &dummy_dist, 0, NULL, NULL);
+ *index = ED_view3d_backbuf_sample_rect(&vc, mval, size, 1, me->totpoly + 1, &dummy_dist);
}
else {
/* sample only on the exact position */
- *index = view3d_sample_backbuf(&vc, mval[0], mval[1]);
+ *index = ED_view3d_backbuf_sample(&vc, mval[0], mval[1]);
}
if ((*index) == 0 || (*index) > (unsigned int)me->totpoly)
@@ -1248,11 +1248,11 @@ bool ED_mesh_pick_vert(bContext *C, Object *ob, const int mval[2], unsigned int
* on an face in the backbuf, we can still select a vert */
float dummy_dist;
- *index = view3d_sample_backbuf_rect(&vc, mval, size, 1, me->totvert + 1, &dummy_dist, 0, NULL, NULL);
+ *index = ED_view3d_backbuf_sample_rect(&vc, mval, size, 1, me->totvert + 1, &dummy_dist);
}
else {
/* sample only on the exact position */
- *index = view3d_sample_backbuf(&vc, mval[0], mval[1]);
+ *index = ED_view3d_backbuf_sample(&vc, mval[0], mval[1]);
}
if ((*index) == 0 || (*index) > (unsigned int)me->totvert)
diff --git a/source/blender/editors/metaball/mball_edit.c b/source/blender/editors/metaball/mball_edit.c
index f6a54beb8c8..42eda235276 100644
--- a/source/blender/editors/metaball/mball_edit.c
+++ b/source/blender/editors/metaball/mball_edit.c
@@ -47,7 +47,6 @@
#include "RNA_define.h"
#include "RNA_access.h"
-#include "RNA_enum_types.h"
#include "BKE_depsgraph.h"
#include "BKE_context.h"
@@ -405,7 +404,8 @@ void MBALL_OT_select_random_metaelems(struct wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
/* properties */
- RNA_def_float_percentage(ot->srna, "percent", 50.f, 0.0f, 100.0f, "Percent", "Percentage of elements to select randomly", 0.f, 100.0f);
+ RNA_def_float_percentage(ot->srna, "percent", 50.f, 0.0f, 100.0f,
+ "Percent", "Percentage of elements to select randomly", 0.0f, 100.0f);
WM_operator_properties_select_action_simple(ot, SEL_SELECT);
}
@@ -533,7 +533,7 @@ void MBALL_OT_hide_metaelems(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
/* props */
- RNA_def_boolean(ot->srna, "unselected", 0, "Unselected", "Hide unselected rather than selected");
+ RNA_def_boolean(ot->srna, "unselected", false, "Unselected", "Hide unselected rather than selected");
}
/***************************** Unhide operator *****************************/
@@ -584,7 +584,7 @@ bool mouse_mball(bContext *C, const int mval[2], bool extend, bool deselect, boo
MetaBall *mb = (MetaBall *)obedit->data;
MetaElem *ml, *ml_act = NULL;
int a, hits;
- unsigned int buffer[4 * MAXPICKBUF];
+ unsigned int buffer[MAXPICKBUF];
rcti rect;
view3d_set_viewcontext(C, &vc);
diff --git a/source/blender/editors/metaball/mball_ops.c b/source/blender/editors/metaball/mball_ops.c
index b7822200d98..3af85c33bcc 100644
--- a/source/blender/editors/metaball/mball_ops.c
+++ b/source/blender/editors/metaball/mball_ops.c
@@ -30,8 +30,6 @@
#include "DNA_scene_types.h"
-#include "BLI_utildefines.h"
-
#include "RNA_access.h"
#include "WM_api.h"
@@ -62,7 +60,7 @@ void ED_operatormacros_metaball(void)
wmOperatorTypeMacro *otmacro;
ot = WM_operatortype_append_macro("MBALL_OT_duplicate_move", "Duplicate",
- "Make copies of the selected bones within the same armature and move them",
+ "Make copies of the selected metaelements and move them",
OPTYPE_UNDO | OPTYPE_REGISTER);
WM_operatortype_macro_define(ot, "MBALL_OT_duplicate_metaelems");
otmacro = WM_operatortype_macro_define(ot, "TRANSFORM_OT_translate");
diff --git a/source/blender/editors/object/CMakeLists.txt b/source/blender/editors/object/CMakeLists.txt
index 1bb35b65918..b3d02d45e13 100644
--- a/source/blender/editors/object/CMakeLists.txt
+++ b/source/blender/editors/object/CMakeLists.txt
@@ -20,9 +20,9 @@
set(INC
../include
- ../../blenfont
../../blenkernel
../../blenlib
+ ../../blentranslation
../../bmesh
../../gpu
../../ikplugin
@@ -33,10 +33,11 @@ set(INC
../../render/extern/include
../../windowmanager
../../../../intern/guardedalloc
+ ../../../../intern/glew-mx
)
set(INC_SYS
-
+ ${GLEW_INCLUDE_PATH}
)
set(SRC
@@ -55,6 +56,7 @@ set(SRC
object_relations.c
object_select.c
object_shapekey.c
+ object_data_transfer.c
object_transform.c
object_warp.c
object_vgroup.c
@@ -62,6 +64,8 @@ set(SRC
object_intern.h
)
+add_definitions(${GL_DEFINITIONS})
+
if(WITH_PYTHON)
add_definitions(-DWITH_PYTHON)
endif()
diff --git a/source/blender/editors/object/SConscript b/source/blender/editors/object/SConscript
index db30fae1f84..914ffa3061c 100644
--- a/source/blender/editors/object/SConscript
+++ b/source/blender/editors/object/SConscript
@@ -33,9 +33,9 @@ incs = [
'#/extern/recastnavigation',
'#/intern/guardedalloc',
'../include',
- '../../blenfont',
'../../blenkernel',
'../../blenlib',
+ '../../blentranslation',
'../../bmesh',
'../../gpu',
'../../ikplugin',
diff --git a/source/blender/editors/object/object_add.c b/source/blender/editors/object/object_add.c
index 8972dd7cf08..615fbb527b3 100644
--- a/source/blender/editors/object/object_add.c
+++ b/source/blender/editors/object/object_add.c
@@ -55,8 +55,9 @@
#include "BLI_math.h"
#include "BLI_string.h"
-#include "BLF_translation.h"
+#include "BLT_translation.h"
+#include "BKE_action.h"
#include "BKE_anim.h"
#include "BKE_animsys.h"
#include "BKE_armature.h"
@@ -69,7 +70,6 @@
#include "BKE_effect.h"
#include "BKE_font.h"
#include "BKE_group.h"
-#include "BKE_image.h"
#include "BKE_lamp.h"
#include "BKE_lattice.h"
#include "BKE_library.h"
@@ -97,7 +97,6 @@
#include "ED_armature.h"
#include "ED_curve.h"
-#include "ED_lattice.h"
#include "ED_mball.h"
#include "ED_mesh.h"
#include "ED_node.h"
@@ -108,7 +107,6 @@
#include "ED_transform.h"
#include "ED_view3d.h"
-#include "UI_interface.h"
#include "UI_resources.h"
#include "GPU_material.h"
@@ -165,14 +163,13 @@ void ED_object_rotation_from_view(bContext *C, float rot[3], const char align_ax
BLI_assert(align_axis >= 'X' && align_axis <= 'Z');
if (rv3d) {
- const float pi_2 = (float)M_PI / 2.0f;
float quat[4];
switch (align_axis) {
case 'X':
{
float quat_y[4];
- axis_angle_to_quat(quat_y, rv3d->viewinv[1], -pi_2);
+ axis_angle_to_quat(quat_y, rv3d->viewinv[1], -M_PI_2);
mul_qt_qtqt(quat, rv3d->viewquat, quat_y);
quat[0] = -quat[0];
@@ -185,7 +182,7 @@ void ED_object_rotation_from_view(bContext *C, float rot[3], const char align_ax
quat[0] = -quat[0];
quat_to_eul(rot, quat);
- rot[0] -= pi_2;
+ rot[0] -= (float)M_PI_2;
break;
}
case 'Z':
@@ -222,9 +219,9 @@ void ED_object_base_init_transform(bContext *C, Base *base, const float loc[3],
/* Uses context to figure out transform for primitive.
* Returns standard diameter. */
-float ED_object_new_primitive_matrix(bContext *C, Object *obedit,
- const float loc[3], const float rot[3], float primmat[4][4],
- bool apply_diameter)
+float ED_object_new_primitive_matrix(
+ bContext *C, Object *obedit,
+ const float loc[3], const float rot[3], float primmat[4][4])
{
Scene *scene = CTX_data_scene(C);
View3D *v3d = CTX_wm_view3d(C);
@@ -249,13 +246,6 @@ float ED_object_new_primitive_matrix(bContext *C, Object *obedit,
{
const float dia = v3d ? ED_view3d_grid_scale(scene, v3d, NULL) : ED_scene_grid_scale(scene, NULL);
-
- if (apply_diameter) {
- primmat[0][0] *= dia;
- primmat[1][1] *= dia;
- primmat[2][2] *= dia;
- }
-
return dia;
}
@@ -273,7 +263,7 @@ void ED_object_add_unit_props(wmOperatorType *ot)
{
PropertyRNA *prop;
- prop = RNA_def_float(ot->srna, "radius", 1.0f, 0.0, FLT_MAX, "Radius", "", 0.001, 100.00);
+ prop = RNA_def_float(ot->srna, "radius", 1.0f, 0.0, OBJECT_ADD_SIZE_MAXF, "Radius", "", 0.001, 100.00);
RNA_def_property_subtype(prop, PROP_DISTANCE);
}
@@ -291,11 +281,12 @@ void ED_object_add_generic_props(wmOperatorType *ot, bool do_editmode)
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
}
- prop = RNA_def_float_vector_xyz(ot->srna, "location", 3, NULL, -FLT_MAX, FLT_MAX, "Location",
- "Location for the newly added object", -FLT_MAX, FLT_MAX);
+ prop = RNA_def_float_vector_xyz(ot->srna, "location", 3, NULL, -OBJECT_ADD_SIZE_MAXF, OBJECT_ADD_SIZE_MAXF,
+ "Location", "Location for the newly added object", -1000.0f, 1000.0f);
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
- prop = RNA_def_float_rotation(ot->srna, "rotation", 3, NULL, -FLT_MAX, FLT_MAX, "Rotation",
- "Rotation for the newly added object", (float)-M_PI * 2.0f, (float)M_PI * 2.0f);
+ prop = RNA_def_float_rotation(ot->srna, "rotation", 3, NULL, -OBJECT_ADD_SIZE_MAXF, OBJECT_ADD_SIZE_MAXF,
+ "Rotation", "Rotation for the newly added object",
+ DEG2RADF(-360.0f), DEG2RADF(360.0f));
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
prop = RNA_def_boolean_layer_member(ot->srna, "layers", 20, NULL, "Layer", "");
@@ -308,18 +299,19 @@ bool ED_object_add_generic_get_opts(bContext *C, wmOperator *op, const char view
{
View3D *v3d = CTX_wm_view3d(C);
unsigned int _layer;
+ PropertyRNA *prop;
- /* Switch to Edit mode? */
- if (RNA_struct_find_property(op->ptr, "enter_editmode")) { /* optional */
+ /* Switch to Edit mode? optional prop */
+ if ((prop = RNA_struct_find_property(op->ptr, "enter_editmode"))) {
bool _enter_editmode;
if (!enter_editmode)
enter_editmode = &_enter_editmode;
- if (RNA_struct_property_is_set(op->ptr, "enter_editmode") && enter_editmode)
- *enter_editmode = RNA_boolean_get(op->ptr, "enter_editmode");
+ if (RNA_property_is_set(op->ptr, prop) && enter_editmode)
+ *enter_editmode = RNA_property_boolean_get(op->ptr, prop);
else {
*enter_editmode = (U.flag & USER_ADD_EDITMODE) != 0;
- RNA_boolean_set(op->ptr, "enter_editmode", *enter_editmode);
+ RNA_property_boolean_set(op->ptr, prop, *enter_editmode);
}
}
@@ -329,8 +321,9 @@ bool ED_object_add_generic_get_opts(bContext *C, wmOperator *op, const char view
if (!layer)
layer = &_layer;
- if (RNA_struct_property_is_set(op->ptr, "layers")) {
- RNA_boolean_get_array(op->ptr, "layers", layer_values);
+ prop = RNA_struct_find_property(op->ptr, "layers");
+ if (RNA_property_is_set(op->ptr, prop)) {
+ RNA_property_boolean_get_array(op->ptr, prop, layer_values);
*layer = 0;
for (a = 0; a < 20; a++) {
if (layer_values[a])
@@ -341,9 +334,9 @@ bool ED_object_add_generic_get_opts(bContext *C, wmOperator *op, const char view
Scene *scene = CTX_data_scene(C);
*layer = BKE_screen_view3d_layer_active_ex(v3d, scene, false);
for (a = 0; a < 20; a++) {
- layer_values[a] = *layer & (1 << a);
+ layer_values[a] = (*layer & (1 << a)) != 0;
}
- RNA_boolean_set_array(op->ptr, "layers", layer_values);
+ RNA_property_boolean_set_array(op->ptr, prop, layer_values);
}
/* in local view we additionally add local view layers,
@@ -403,8 +396,11 @@ bool ED_object_add_generic_get_opts(bContext *C, wmOperator *op, const char view
/* For object add primitive operators.
* Do not call undo push in this function (users of this function have to). */
-Object *ED_object_add_type(bContext *C, int type, const float loc[3], const float rot[3],
- bool enter_editmode, unsigned int layer)
+Object *ED_object_add_type(
+ bContext *C,
+ int type, const char *name,
+ const float loc[3], const float rot[3],
+ bool enter_editmode, unsigned int layer)
{
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
@@ -415,7 +411,7 @@ Object *ED_object_add_type(bContext *C, int type, const float loc[3], const floa
ED_object_editmode_exit(C, EM_FREEDATA | EM_FREEUNDO | EM_WAITCURSOR | EM_DO_UNDO); /* freedata, and undo */
/* deselects all, sets scene->basact */
- ob = BKE_object_add(bmain, scene, type);
+ ob = BKE_object_add(bmain, scene, type, name);
BASACT->lay = ob->lay = layer;
/* editor level activate, notifiers */
ED_base_object_activate(C, BASACT);
@@ -449,14 +445,23 @@ static int object_add_exec(bContext *C, wmOperator *op)
Object *ob;
bool enter_editmode;
unsigned int layer;
- float loc[3], rot[3];
+ float loc[3], rot[3], radius;
WM_operator_view3d_unit_defaults(C, op);
if (!ED_object_add_generic_get_opts(C, op, 'Z', loc, rot, &enter_editmode, &layer, NULL))
return OPERATOR_CANCELLED;
- ob = ED_object_add_type(C, RNA_enum_get(op->ptr, "type"), loc, rot, enter_editmode, layer);
- BKE_object_obdata_size_init(ob, RNA_float_get(op->ptr, "radius"));
+ radius = RNA_float_get(op->ptr, "radius");
+ ob = ED_object_add_type(C, RNA_enum_get(op->ptr, "type"), NULL, loc, rot, enter_editmode, layer);
+
+ if (ob->type == OB_LATTICE) {
+ /* lattice is a special case!
+ * we never want to scale the obdata since that is the rest-state */
+ copy_v3_fl(ob->size, radius);
+ }
+ else {
+ BKE_object_obdata_size_init(ob, radius);
+ }
return OPERATOR_FINISHED;
}
@@ -504,21 +509,21 @@ static int effector_add_exec(bContext *C, wmOperator *op)
if (type == PFIELD_GUIDE) {
Curve *cu;
- ob = ED_object_add_type(C, OB_CURVE, loc, rot, false, layer);
+ const char *name = CTX_DATA_(BLT_I18NCONTEXT_ID_OBJECT, "CurveGuide");
+ ob = ED_object_add_type(C, OB_CURVE, name, loc, rot, false, layer);
- rename_id(&ob->id, CTX_DATA_(BLF_I18NCONTEXT_ID_OBJECT, "CurveGuide"));
cu = ob->data;
cu->flag |= CU_PATH | CU_3D;
ED_object_editmode_enter(C, 0);
- ED_object_new_primitive_matrix(C, ob, loc, rot, mat, false);
+ ED_object_new_primitive_matrix(C, ob, loc, rot, mat);
BLI_addtail(&cu->editnurb->nurbs, add_nurbs_primitive(C, ob, mat, CU_NURBS | CU_PRIM_PATH, dia));
if (!enter_editmode)
ED_object_editmode_exit(C, EM_FREEDATA);
}
else {
- ob = ED_object_add_type(C, OB_EMPTY, loc, rot, false, layer);
+ const char *name = CTX_DATA_(BLT_I18NCONTEXT_ID_OBJECT, "Field");
+ ob = ED_object_add_type(C, OB_EMPTY, name, loc, rot, false, layer);
BKE_object_obdata_size_init(ob, dia);
- rename_id(&ob->id, CTX_DATA_(BLF_I18NCONTEXT_ID_OBJECT, "Field"));
if (ELEM(type, PFIELD_WIND, PFIELD_VORTEX))
ob->empty_drawtype = OB_SINGLE_ARROW;
}
@@ -569,7 +574,7 @@ static int object_camera_add_exec(bContext *C, wmOperator *op)
if (!ED_object_add_generic_get_opts(C, op, 'Z', loc, rot, &enter_editmode, &layer, NULL))
return OPERATOR_CANCELLED;
- ob = ED_object_add_type(C, OB_CAMERA, loc, rot, false, layer);
+ ob = ED_object_add_type(C, OB_CAMERA, NULL, loc, rot, false, layer);
if (v3d) {
if (v3d->camera == NULL)
@@ -626,14 +631,14 @@ static int object_metaball_add_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
if (obedit == NULL || obedit->type != OB_MBALL) {
- obedit = ED_object_add_type(C, OB_MBALL, loc, rot, true, layer);
+ obedit = ED_object_add_type(C, OB_MBALL, NULL, loc, rot, true, layer);
newob = true;
}
else {
DAG_id_tag_update(&obedit->id, OB_RECALC_DATA);
}
- ED_object_new_primitive_matrix(C, obedit, loc, rot, mat, false);
+ ED_object_new_primitive_matrix(C, obedit, loc, rot, mat);
dia = RNA_float_get(op->ptr, "radius");
add_metaball_primitive(C, obedit, mat, dia, RNA_enum_get(op->ptr, "type"));
@@ -685,7 +690,7 @@ static int object_add_text_exec(bContext *C, wmOperator *op)
if (obedit && obedit->type == OB_FONT)
return OPERATOR_CANCELLED;
- obedit = ED_object_add_type(C, OB_FONT, loc, rot, enter_editmode, layer);
+ obedit = ED_object_add_type(C, OB_FONT, NULL, loc, rot, enter_editmode, layer);
BKE_object_obdata_size_init(obedit, RNA_float_get(op->ptr, "radius"));
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, obedit);
@@ -729,7 +734,7 @@ static int object_armature_add_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
if ((obedit == NULL) || (obedit->type != OB_ARMATURE)) {
- obedit = ED_object_add_type(C, OB_ARMATURE, loc, rot, true, layer);
+ obedit = ED_object_add_type(C, OB_ARMATURE, NULL, loc, rot, true, layer);
ED_object_editmode_enter(C, 0);
newob = true;
}
@@ -786,7 +791,7 @@ static int object_empty_add_exec(bContext *C, wmOperator *op)
if (!ED_object_add_generic_get_opts(C, op, 'Z', loc, rot, NULL, &layer, NULL))
return OPERATOR_CANCELLED;
- ob = ED_object_add_type(C, OB_EMPTY, loc, rot, false, layer);
+ ob = ED_object_add_type(C, OB_EMPTY, NULL, loc, rot, false, layer);
BKE_object_empty_draw_type_set(ob, type);
BKE_object_obdata_size_init(ob, RNA_float_get(op->ptr, "radius"));
@@ -824,24 +829,12 @@ static int empty_drop_named_image_invoke(bContext *C, wmOperator *op, const wmEv
Image *ima = NULL;
Object *ob = NULL;
- /* check image input variables */
- if (RNA_struct_property_is_set(op->ptr, "filepath")) {
- char path[FILE_MAX];
-
- RNA_string_get(op->ptr, "filepath", path);
- ima = BKE_image_load_exists(path);
- }
- else if (RNA_struct_property_is_set(op->ptr, "name")) {
- char name[MAX_ID_NAME - 2];
-
- RNA_string_get(op->ptr, "name", name);
- ima = (Image *)BKE_libblock_find_name(ID_IM, name);
- }
-
- if (ima == NULL) {
- BKE_report(op->reports, RPT_ERROR, "Not an image");
+ ima = (Image *)WM_operator_drop_load_path(C, op, ID_IM);
+ if (!ima) {
return OPERATOR_CANCELLED;
}
+ /* handled below */
+ id_us_min((ID *)ima);
base = ED_view3d_give_base_under_cursor(C, event->mval);
@@ -858,7 +851,7 @@ static int empty_drop_named_image_invoke(bContext *C, wmOperator *op, const wmEv
if (!ED_object_add_generic_get_opts(C, op, 'Z', NULL, rot, NULL, &layer, NULL))
return OPERATOR_CANCELLED;
- ob = ED_object_add_type(C, OB_EMPTY, NULL, rot, false, layer);
+ ob = ED_object_add_type(C, OB_EMPTY, NULL, NULL, rot, false, layer);
/* add under the mouse */
ED_object_location_from_view(C, ob->loc);
@@ -893,6 +886,8 @@ void OBJECT_OT_drop_named_image(wmOperatorType *ot)
/* properties */
prop = RNA_def_string(ot->srna, "filepath", NULL, FILE_MAX, "Filepath", "Path to image file");
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
+ RNA_def_boolean(ot->srna, "relative_path", true, "Relative Path", "Select the file relative to the blend file");
+ RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
prop = RNA_def_string(ot->srna, "name", NULL, MAX_ID_NAME - 2, "Name", "Image name to assign");
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
ED_object_add_generic_props(ot, false);
@@ -903,13 +898,13 @@ void OBJECT_OT_drop_named_image(wmOperatorType *ot)
static const char *get_lamp_defname(int type)
{
switch (type) {
- case LA_LOCAL: return CTX_DATA_(BLF_I18NCONTEXT_ID_LAMP, "Point");
- case LA_SUN: return CTX_DATA_(BLF_I18NCONTEXT_ID_LAMP, "Sun");
- case LA_SPOT: return CTX_DATA_(BLF_I18NCONTEXT_ID_LAMP, "Spot");
- case LA_HEMI: return CTX_DATA_(BLF_I18NCONTEXT_ID_LAMP, "Hemi");
- case LA_AREA: return CTX_DATA_(BLF_I18NCONTEXT_ID_LAMP, "Area");
+ case LA_LOCAL: return CTX_DATA_(BLT_I18NCONTEXT_ID_LAMP, "Point");
+ case LA_SUN: return CTX_DATA_(BLT_I18NCONTEXT_ID_LAMP, "Sun");
+ case LA_SPOT: return CTX_DATA_(BLT_I18NCONTEXT_ID_LAMP, "Spot");
+ case LA_HEMI: return CTX_DATA_(BLT_I18NCONTEXT_ID_LAMP, "Hemi");
+ case LA_AREA: return CTX_DATA_(BLT_I18NCONTEXT_ID_LAMP, "Area");
default:
- return CTX_DATA_(BLF_I18NCONTEXT_ID_LAMP, "Lamp");
+ return CTX_DATA_(BLT_I18NCONTEXT_ID_LAMP, "Lamp");
}
}
@@ -926,13 +921,11 @@ static int object_lamp_add_exec(bContext *C, wmOperator *op)
if (!ED_object_add_generic_get_opts(C, op, 'Z', loc, rot, NULL, &layer, NULL))
return OPERATOR_CANCELLED;
- ob = ED_object_add_type(C, OB_LAMP, loc, rot, false, layer);
+ ob = ED_object_add_type(C, OB_LAMP, get_lamp_defname(type), loc, rot, false, layer);
BKE_object_obdata_size_init(ob, RNA_float_get(op->ptr, "radius"));
la = (Lamp *)ob->data;
la->type = type;
- rename_id(&ob->id, get_lamp_defname(type));
- rename_id(&la->id, get_lamp_defname(type));
if (BKE_scene_use_new_shading_nodes(scene)) {
ED_node_shader_default(C, &la->id);
@@ -959,7 +952,7 @@ void OBJECT_OT_lamp_add(wmOperatorType *ot)
/* properties */
ot->prop = RNA_def_enum(ot->srna, "type", lamp_type_items, 0, "Type", "");
- RNA_def_property_translation_context(ot->prop, BLF_I18NCONTEXT_ID_LAMP);
+ RNA_def_property_translation_context(ot->prop, BLT_I18NCONTEXT_ID_LAMP);
ED_object_add_unit_props(ot);
ED_object_add_generic_props(ot, false);
@@ -981,8 +974,11 @@ static int group_instance_add_exec(bContext *C, wmOperator *op)
if (0 == RNA_struct_property_is_set(op->ptr, "location")) {
wmEvent *event = CTX_wm_window(C)->eventstate;
+ ARegion *ar = CTX_wm_region(C);
+ const int mval[2] = {event->x - ar->winrct.xmin,
+ event->y - ar->winrct.ymin};
ED_object_location_from_view(C, loc);
- ED_view3d_cursor3d_position(C, loc, event->mval);
+ ED_view3d_cursor3d_position(C, loc, mval);
RNA_float_set_array(op->ptr, "location", loc);
}
}
@@ -995,8 +991,7 @@ static int group_instance_add_exec(bContext *C, wmOperator *op)
if (group) {
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
- Object *ob = ED_object_add_type(C, OB_EMPTY, loc, rot, false, layer);
- rename_id(&ob->id, group->id.name + 2);
+ Object *ob = ED_object_add_type(C, OB_EMPTY, group->id.name + 2, loc, rot, false, layer);
ob->dup_group = group;
ob->transflag |= OB_DUPLIGROUP;
id_lib_extern(&group->id);
@@ -1051,14 +1046,14 @@ static int object_speaker_add_exec(bContext *C, wmOperator *op)
if (!ED_object_add_generic_get_opts(C, op, 'Z', loc, rot, NULL, &layer, NULL))
return OPERATOR_CANCELLED;
- ob = ED_object_add_type(C, OB_SPEAKER, loc, rot, false, layer);
+ ob = ED_object_add_type(C, OB_SPEAKER, NULL, loc, rot, false, layer);
/* to make it easier to start using this immediately in NLA, a default sound clip is created
* ready to be moved around to retime the sound and/or make new sound clips
*/
{
/* create new data for NLA hierarchy */
- AnimData *adt = BKE_id_add_animdata(&ob->id);
+ AnimData *adt = BKE_animdata_add_id(&ob->id);
NlaTrack *nlt = add_nlatrack(adt, NULL);
NlaStrip *strip = add_nla_soundstrip(scene, ob->data);
strip->start = CFRA;
@@ -1290,6 +1285,44 @@ static void copy_object_set_idnew(bContext *C, int dupflag)
/********************* Make Duplicates Real ************************/
+/**
+ * \note regarding hashing dupli-objects, skip the first member of #DupliObject.persistent_id
+ * since its a unique index and we only want to know if the group objects are from the same dupli-group instance.
+ */
+static unsigned int dupliobject_hash(const void *ptr)
+{
+ const DupliObject *dob = ptr;
+ unsigned int hash = BLI_ghashutil_ptrhash(dob->ob);
+ unsigned int i;
+ for (i = 1; (i < MAX_DUPLI_RECUR) && dob->persistent_id[i] != INT_MAX; i++) {
+ hash ^= (dob->persistent_id[i] ^ i);
+ }
+ return hash;
+}
+
+static bool dupliobject_cmp(const void *a_, const void *b_)
+{
+ const DupliObject *a = a_;
+ const DupliObject *b = b_;
+ unsigned int i;
+
+ if (a->ob != b->ob) {
+ return true;
+ }
+
+ for (i = 1; (i < MAX_DUPLI_RECUR); i++) {
+ if (a->persistent_id[i] != b->persistent_id[i]) {
+ return true;
+ }
+ else if (a->persistent_id[i] == INT_MAX) {
+ break;
+ }
+ }
+
+ /* matching */
+ return false;
+}
+
static void make_object_duplilist_real(bContext *C, Scene *scene, Base *base,
const bool use_base_parent,
const bool use_hierarchy)
@@ -1306,8 +1339,8 @@ static void make_object_duplilist_real(bContext *C, Scene *scene, Base *base,
lb = object_duplilist(bmain->eval_ctx, scene, base->object);
if (use_hierarchy || use_base_parent) {
- dupli_gh = BLI_ghash_ptr_new("make_object_duplilist_real dupli_gh");
- parent_gh = BLI_ghash_pair_new("make_object_duplilist_real parent_gh");
+ dupli_gh = BLI_ghash_ptr_new(__func__);
+ parent_gh = BLI_ghash_new(dupliobject_hash, dupliobject_cmp, __func__);
}
for (dob = lb->first; dob; dob = dob->next) {
@@ -1327,7 +1360,7 @@ static void make_object_duplilist_real(bContext *C, Scene *scene, Base *base,
basen->object = ob;
/* make sure apply works */
- BKE_free_animdata(&ob->id);
+ BKE_animdata_free(&ob->id);
ob->adt = NULL;
/* Proxies are not to be copied. */
@@ -1347,7 +1380,7 @@ static void make_object_duplilist_real(bContext *C, Scene *scene, Base *base,
if (dupli_gh)
BLI_ghash_insert(dupli_gh, dob, ob);
if (parent_gh)
- BLI_ghash_insert(parent_gh, BLI_ghashutil_pairalloc(dob->ob, SET_INT_IN_POINTER(dob->persistent_id[0])), ob);
+ BLI_ghash_insert(parent_gh, dob, ob);
DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
}
@@ -1363,9 +1396,14 @@ static void make_object_duplilist_real(bContext *C, Scene *scene, Base *base,
/* find parent that was also made real */
if (ob_src_par) {
- GHashPair *pair = BLI_ghashutil_pairalloc(ob_src_par, SET_INT_IN_POINTER(dob->persistent_id[0]));
- ob_dst_par = BLI_ghash_lookup(parent_gh, pair);
- BLI_ghashutil_pairfree(pair);
+ /* OK to keep most of the members uninitialized,
+ * they won't be read, this is simply for a hash lookup. */
+ DupliObject dob_key;
+ dob_key.ob = ob_src_par;
+ memcpy(&dob_key.persistent_id[1],
+ &dob->persistent_id[1],
+ sizeof(dob->persistent_id[1]) * (MAX_DUPLI_RECUR - 1));
+ ob_dst_par = BLI_ghash_lookup(parent_gh, &dob_key);
}
if (ob_dst_par) {
@@ -1428,7 +1466,7 @@ static void make_object_duplilist_real(bContext *C, Scene *scene, Base *base,
if (dupli_gh)
BLI_ghash_free(dupli_gh, NULL, NULL);
if (parent_gh)
- BLI_ghash_free(parent_gh, BLI_ghashutil_pairfree, NULL);
+ BLI_ghash_free(parent_gh, NULL, NULL);
copy_object_set_idnew(C, 0);
@@ -1569,18 +1607,30 @@ static int convert_exec(bContext *C, wmOperator *op)
/* don't forget multiple users! */
- /* reset flags */
- CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases)
{
- ob = base->object;
- ob->flag &= ~OB_DONE;
+ Base *base;
+
+ for (base = scene->base.first; base; base = base->next) {
+ ob = base->object;
+ ob->flag &= ~OB_DONE;
- /* flag data thats not been edited (only needed for !keep_original) */
- if (ob->data) {
- ((ID *)ob->data)->flag |= LIB_DOIT;
+ /* flag data thats not been edited (only needed for !keep_original) */
+ if (ob->data) {
+ ((ID *)ob->data)->flag |= LIB_DOIT;
+ }
+
+ /* possible metaball basis is not in this scene */
+ if (ob->type == OB_MBALL && target == OB_MESH) {
+ if (BKE_mball_is_basis(ob) == false) {
+ Object *ob_basis;
+ ob_basis = BKE_mball_basis_find(scene, ob);
+ if (ob_basis) {
+ ob_basis->flag &= ~OB_DONE;
+ }
+ }
+ }
}
}
- CTX_DATA_END;
CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases)
{
@@ -1652,11 +1702,10 @@ static int convert_exec(bContext *C, wmOperator *op)
dm = mesh_get_derived_final(scene, newob, CD_MASK_MESH);
// dm = mesh_create_derived_no_deform(ob1, NULL); /* this was called original (instead of get_derived). man o man why! (ton) */
- DM_to_mesh(dm, newob->data, newob, CD_MASK_MESH);
+ DM_to_mesh(dm, newob->data, newob, CD_MASK_MESH, true);
/* re-tessellation is called by DM_to_mesh */
- dm->release(dm);
BKE_object_free_modifiers(newob); /* after derivedmesh calls! */
}
else if (ob->type == OB_FONT) {
@@ -1820,14 +1869,21 @@ static int convert_exec(bContext *C, wmOperator *op)
if (!keep_original) {
if (mballConverted) {
- Base *base = scene->base.first, *tmpbase;
- while (base) {
- ob = base->object;
- tmpbase = base;
- base = base->next;
+ Base *base, *base_next;
+
+ for (base = scene->base.first; base; base = base_next) {
+ base_next = base->next;
+ ob = base->object;
if (ob->type == OB_MBALL) {
- ED_base_object_free_and_unlink(bmain, scene, tmpbase);
+ if (ob->flag & OB_DONE) {
+ Object *ob_basis = NULL;
+ if (BKE_mball_is_basis(ob) ||
+ ((ob_basis = BKE_mball_basis_find(scene, ob)) && (ob_basis->flag & OB_DONE)))
+ {
+ ED_base_object_free_and_unlink(bmain, scene, base);
+ }
+ }
}
}
}
@@ -1922,7 +1978,7 @@ static Base *object_add_duplicate_internal(Main *bmain, Scene *scene, Base *base
/* duplicates using userflags */
if (dupflag & USER_DUP_ACT) {
- BKE_copy_animdata_id_action(&obn->id);
+ BKE_animdata_copy_id_action(&obn->id);
}
if (dupflag & USER_DUP_MAT) {
@@ -1935,7 +1991,7 @@ static Base *object_add_duplicate_internal(Main *bmain, Scene *scene, Base *base
id->us--;
if (dupflag & USER_DUP_ACT) {
- BKE_copy_animdata_id_action(&obn->mat[a]->id);
+ BKE_animdata_copy_id_action(&obn->mat[a]->id);
}
}
}
@@ -1950,7 +2006,7 @@ static Base *object_add_duplicate_internal(Main *bmain, Scene *scene, Base *base
psys->part = BKE_particlesettings_copy(psys->part);
if (dupflag & USER_DUP_ACT) {
- BKE_copy_animdata_id_action(&psys->part->id);
+ BKE_animdata_copy_id_action(&psys->part->id);
}
id->us--;
@@ -2028,7 +2084,7 @@ static Base *object_add_duplicate_internal(Main *bmain, Scene *scene, Base *base
case OB_ARMATURE:
DAG_id_tag_update(&obn->id, OB_RECALC_DATA);
if (obn->pose)
- obn->pose->flag |= POSE_RECALC;
+ BKE_pose_tag_recalc(bmain, obn->pose);
if (dupflag & USER_DUP_ARM) {
ID_NEW_US2(obn->data)
else {
@@ -2078,9 +2134,9 @@ static Base *object_add_duplicate_internal(Main *bmain, Scene *scene, Base *base
if (dupflag & USER_DUP_ACT) {
bActuator *act;
- BKE_copy_animdata_id_action((ID *)obn->data);
+ BKE_animdata_copy_id_action((ID *)obn->data);
if (key) {
- BKE_copy_animdata_id_action((ID *)key);
+ BKE_animdata_copy_id_action((ID *)key);
}
/* Update the duplicated action in the action actuators */
@@ -2270,7 +2326,7 @@ static int add_named_exec(bContext *C, wmOperator *op)
MEM_freeN(base);
- WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
+ WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT | ND_OB_ACTIVE, scene);
return OPERATOR_FINISHED;
}
diff --git a/source/blender/editors/object/object_bake.c b/source/blender/editors/object/object_bake.c
index b8957514159..ecaa05ace99 100644
--- a/source/blender/editors/object/object_bake.c
+++ b/source/blender/editors/object/object_bake.c
@@ -45,8 +45,6 @@
#include "BLI_blenlib.h"
#include "BLI_threads.h"
#include "BLI_utildefines.h"
-#include "BLI_math.h"
-#include "BLI_math_geom.h"
#include "BKE_blender.h"
#include "BKE_screen.h"
@@ -71,7 +69,6 @@
#include "IMB_imbuf_types.h"
#include "IMB_imbuf.h"
-#include "IMB_colormanagement.h"
#include "GPU_draw.h" /* GPU_free_image */
@@ -218,7 +215,7 @@ static DerivedMesh *multiresbake_create_loresdm(Scene *scene, Object *ob, int *l
tmp_mmd.simple = true;
}
- DM_set_only_copy(cddm, CD_MASK_BAREMESH | CD_MASK_MTFACE);
+ DM_set_only_copy(cddm, CD_MASK_BAREMESH);
tmp_mmd.lvl = *lvl;
tmp_mmd.sculptlvl = *lvl;
@@ -286,23 +283,6 @@ static void clear_single_image(Image *image, ClearFlag flag)
}
}
-static void clear_images(MTFace *mtface, int totface, ClearFlag flag)
-{
- int a;
-
- for (a = 0; a < totface; a++) {
- mtface[a].tpage->id.flag &= ~LIB_DOIT;
- }
-
- for (a = 0; a < totface; a++) {
- clear_single_image(mtface[a].tpage, flag);
- }
-
- for (a = 0; a < totface; a++) {
- mtface[a].tpage->id.flag &= ~LIB_DOIT;
- }
-}
-
static void clear_images_poly(MTexPoly *mtpoly, int totpoly, ClearFlag flag)
{
int a;
@@ -345,7 +325,6 @@ static int multiresbake_image_exec_locked(bContext *C, wmOperator *op)
clear_flag = CLEAR_DISPLACEMENT;
}
- clear_images(me->mtface, me->totface, clear_flag);
clear_images_poly(me->mtpoly, me->totpoly, clear_flag);
}
CTX_DATA_END;
@@ -438,12 +417,12 @@ static void multiresbake_startjob(void *bkv, short *stop, short *do_update, floa
MultiresBakeJob *bkj = bkv;
int baked_objects = 0, tot_obj;
- tot_obj = BLI_countlist(&bkj->data);
+ tot_obj = BLI_listbase_count(&bkj->data);
if (bkj->bake_clear) { /* clear images */
for (data = bkj->data.first; data; data = data->next) {
DerivedMesh *dm = data->lores_dm;
- MTFace *mtface = CustomData_get_layer(&dm->faceData, CD_MTFACE);
+ MTexPoly *mtexpoly = CustomData_get_layer(&dm->polyData, CD_MTEXPOLY);
ClearFlag clear_flag = 0;
if (bkj->mode == RE_BAKE_NORMALS) {
@@ -453,7 +432,7 @@ static void multiresbake_startjob(void *bkv, short *stop, short *do_update, floa
clear_flag = CLEAR_DISPLACEMENT;
}
- clear_images(mtface, dm->getNumTessFaces(dm), clear_flag);
+ clear_images_poly(mtexpoly, dm->getNumPolys(dm), clear_flag);
}
}
diff --git a/source/blender/editors/object/object_bake_api.c b/source/blender/editors/object/object_bake_api.c
index 5746f9efd56..2c4f7a8e107 100644
--- a/source/blender/editors/object/object_bake_api.c
+++ b/source/blender/editors/object/object_bake_api.c
@@ -379,7 +379,10 @@ static bool bake_object_check(Object *ob, ReportList *reports)
if (node) {
if (BKE_node_is_connected_to_output(ntree, node)) {
- BKE_reportf(reports, RPT_ERROR,
+ /* we don't return false since this may be a false positive
+ * this can't be RPT_ERROR though, otherwise it prevents
+ * multiple highpoly objects to be baked at once */
+ BKE_reportf(reports, RPT_INFO,
"Circular dependency for image \"%s\" from object \"%s\"",
image->id.name + 2, ob->id.name + 2);
}
@@ -560,7 +563,7 @@ static int bake(
Object *ob_cage = NULL;
BakeHighPolyData *highpoly = NULL;
- int tot_highpoly;
+ int tot_highpoly = 0;
char restrict_flag_low = ob_low->restrictflag;
char restrict_flag_cage = 0;
@@ -571,6 +574,7 @@ static int bake(
float *result = NULL;
BakePixel *pixel_array_low = NULL;
+ BakePixel *pixel_array_high = NULL;
const bool is_save_internal = (save_mode == R_BAKE_SAVE_INTERNAL);
const bool is_noncolor = is_noncolor_pass(pass_type);
@@ -679,10 +683,13 @@ static int bake(
}
pixel_array_low = MEM_mallocN(sizeof(BakePixel) * num_pixels, "bake pixels low poly");
+ pixel_array_high = MEM_mallocN(sizeof(BakePixel) * num_pixels, "bake pixels high poly");
result = MEM_callocN(sizeof(float) * depth * num_pixels, "bake return pixels");
/* get the mesh as it arrives in the renderer */
- me_low = BKE_mesh_new_from_object(bmain, scene, ob_low, 1, 2, 1, 0);
+ me_low = BKE_mesh_new_from_object(bmain, scene, ob_low, 1, 2, 0, 0);
+ BKE_mesh_split_faces(me_low);
+ BKE_mesh_tessface_ensure(me_low);
/* populate the pixel array with the face data */
if ((is_selected_to_active && (ob_cage == NULL) && is_cage) == false)
@@ -697,7 +704,9 @@ static int bake(
/* prepare cage mesh */
if (ob_cage) {
- me_cage = BKE_mesh_new_from_object(bmain, scene, ob_cage, 1, 2, 1, 0);
+ me_cage = BKE_mesh_new_from_object(bmain, scene, ob_cage, 1, 2, 0, 0);
+ BKE_mesh_split_faces(me_cage);
+ BKE_mesh_tessface_ensure(me_cage);
if (me_low->totface != me_cage->totface) {
BKE_report(reports, RPT_ERROR,
"Invalid cage object, the cage mesh must have the same number "
@@ -729,7 +738,9 @@ static int bake(
ob_low->modifiers = modifiers_tmp;
/* get the cage mesh as it arrives in the renderer */
- me_cage = BKE_mesh_new_from_object(bmain, scene, ob_low, 1, 2, 1, 0);
+ me_cage = BKE_mesh_new_from_object(bmain, scene, ob_low, 1, 2, 0, 0);
+ BKE_mesh_split_faces(me_cage);
+ BKE_mesh_tessface_ensure(me_cage);
RE_bake_pixels_populate(me_cage, pixel_array_low, num_pixels, &bake_images, uv_layer);
}
@@ -746,8 +757,6 @@ static int bake(
/* initialize highpoly_data */
highpoly[i].ob = ob_iter;
highpoly[i].restrict_flag = ob_iter->restrictflag;
- highpoly[i].pixel_array = MEM_mallocN(sizeof(BakePixel) * num_pixels, "bake pixels high poly");
-
/* triangulating so BVH returns the primitive_id that will be used for rendering */
highpoly[i].tri_mod = ED_object_modifier_add(
@@ -757,18 +766,16 @@ static int bake(
tmd->quad_method = MOD_TRIANGULATE_QUAD_FIXED;
tmd->ngon_method = MOD_TRIANGULATE_NGON_EARCLIP;
- highpoly[i].me = BKE_mesh_new_from_object(bmain, scene, highpoly[i].ob, 1, 2, 1, 0);
+ highpoly[i].me = BKE_mesh_new_from_object(bmain, scene, highpoly[i].ob, 1, 2, 0, 0);
highpoly[i].ob->restrictflag &= ~OB_RESTRICT_RENDER;
+ BKE_mesh_split_faces(highpoly[i].me);
+ BKE_mesh_tessface_ensure(highpoly[i].me);
/* lowpoly to highpoly transformation matrix */
copy_m4_m4(highpoly[i].obmat, highpoly[i].ob->obmat);
invert_m4_m4(highpoly[i].imat, highpoly[i].obmat);
- /* rotation */
- normalize_m4_m4(highpoly[i].rotmat, highpoly[i].imat);
- zero_v3(highpoly[i].rotmat[3]);
- if (is_negative_m4(highpoly[i].rotmat))
- negate_m3(highpoly[i].rotmat);
+ highpoly[i].is_flip_object = is_negative_m4(highpoly[i].ob->obmat);
i++;
}
@@ -779,7 +786,7 @@ static int bake(
/* populate the pixel arrays with the corresponding face data for each high poly object */
if (!RE_bake_pixels_populate_from_objects(
- me_low, pixel_array_low, highpoly, tot_highpoly, num_pixels, ob_cage != NULL,
+ me_low, pixel_array_low, pixel_array_high, highpoly, tot_highpoly, num_pixels, ob_cage != NULL,
cage_extrusion, ob_low->obmat, (ob_cage ? ob_cage->obmat : ob_low->obmat), me_cage))
{
BKE_report(reports, RPT_ERROR, "Error handling selected objects");
@@ -788,8 +795,8 @@ static int bake(
/* the baking itself */
for (i = 0; i < tot_highpoly; i++) {
- ok = RE_bake_engine(re, highpoly[i].ob, highpoly[i].pixel_array, num_pixels,
- depth, pass_type, result);
+ ok = RE_bake_engine(re, highpoly[i].ob, i, pixel_array_high,
+ num_pixels, depth, pass_type, result);
if (!ok) {
BKE_reportf(reports, RPT_ERROR, "Error baking from object \"%s\"", highpoly[i].ob->id.name + 2);
goto cage_cleanup;
@@ -815,7 +822,7 @@ cage_cleanup:
ob_low->restrictflag &= ~OB_RESTRICT_RENDER;
if (RE_bake_has_engine(re)) {
- ok = RE_bake_engine(re, ob_low, pixel_array_low, num_pixels, depth, pass_type, result);
+ ok = RE_bake_engine(re, ob_low, 0, pixel_array_low, num_pixels, depth, pass_type, result);
}
else {
BKE_report(reports, RPT_ERROR, "Current render engine does not support baking");
@@ -864,7 +871,9 @@ cage_cleanup:
md->mode &= ~eModifierMode_Render;
}
- me_nores = BKE_mesh_new_from_object(bmain, scene, ob_low, 1, 2, 1, 0);
+ me_nores = BKE_mesh_new_from_object(bmain, scene, ob_low, 1, 2, 0, 0);
+ BKE_mesh_split_faces(me_nores);
+ BKE_mesh_tessface_ensure(me_nores);
RE_bake_pixels_populate(me_nores, pixel_array_low, num_pixels, &bake_images, uv_layer);
RE_bake_normal_world_to_tangent(pixel_array_low, num_pixels, depth, result, me_nores, normal_swizzle, ob_low->obmat);
@@ -916,7 +925,7 @@ cage_cleanup:
BakeData *bake = &scene->r.bake;
char name[FILE_MAX];
- BKE_makepicstring_from_type(name, filepath, bmain->name, 0, bake->im_format.imtype, true, false);
+ BKE_image_path_from_imtype(name, filepath, bmain->name, 0, bake->im_format.imtype, true, false, NULL);
if (is_automatic_name) {
BLI_path_suffix(name, FILE_MAX, ob_low->id.name + 2, "_");
@@ -977,9 +986,6 @@ cleanup:
for (i = 0; i < tot_highpoly; i++) {
highpoly[i].ob->restrictflag = highpoly[i].restrict_flag;
- if (highpoly[i].pixel_array)
- MEM_freeN(highpoly[i].pixel_array);
-
if (highpoly[i].tri_mod)
ED_object_modifier_remove(reports, bmain, highpoly[i].ob, highpoly[i].tri_mod);
@@ -997,6 +1003,9 @@ cleanup:
if (pixel_array_low)
MEM_freeN(pixel_array_low);
+ if (pixel_array_high)
+ MEM_freeN(pixel_array_high);
+
if (bake_images.data)
MEM_freeN(bake_images.data);
@@ -1081,8 +1090,9 @@ static int bake_exec(bContext *C, wmOperator *op)
/* setup new render */
RE_test_break_cb(re, NULL, bake_break);
- if (!bake_objects_check(bkr.main, bkr.ob, &bkr.selected_objects, bkr.reports, bkr.is_selected_to_active))
- return OPERATOR_CANCELLED;
+ if (!bake_objects_check(bkr.main, bkr.ob, &bkr.selected_objects, bkr.reports, bkr.is_selected_to_active)) {
+ goto finally;
+ }
if (bkr.is_clear) {
const bool is_tangent = ((bkr.pass_type == SCE_PASS_NORMAL) && (bkr.normal_space == R_BAKE_SPACE_TANGENT));
@@ -1117,6 +1127,8 @@ static int bake_exec(bContext *C, wmOperator *op)
RE_SetReports(re, NULL);
+
+finally:
BLI_freelistN(&bkr.selected_objects);
return result;
}
@@ -1208,7 +1220,7 @@ static void bake_set_props(wmOperator *op, Scene *scene)
prop = RNA_struct_find_property(op->ptr, "use_selected_to_active");
if (!RNA_property_is_set(op->ptr, prop)) {
- RNA_property_boolean_set(op->ptr, prop, (bake->flag & R_BAKE_TO_ACTIVE));
+ RNA_property_boolean_set(op->ptr, prop, (bake->flag & R_BAKE_TO_ACTIVE) != 0);
}
prop = RNA_struct_find_property(op->ptr, "cage_extrusion");
@@ -1248,22 +1260,22 @@ static void bake_set_props(wmOperator *op, Scene *scene)
prop = RNA_struct_find_property(op->ptr, "use_clear");
if (!RNA_property_is_set(op->ptr, prop)) {
- RNA_property_boolean_set(op->ptr, prop, (bake->flag & R_BAKE_CLEAR));
+ RNA_property_boolean_set(op->ptr, prop, (bake->flag & R_BAKE_CLEAR) != 0);
}
prop = RNA_struct_find_property(op->ptr, "use_cage");
if (!RNA_property_is_set(op->ptr, prop)) {
- RNA_property_boolean_set(op->ptr, prop, (bake->flag & R_BAKE_CAGE));
+ RNA_property_boolean_set(op->ptr, prop, (bake->flag & R_BAKE_CAGE) != 0);
}
prop = RNA_struct_find_property(op->ptr, "use_split_materials");
if (!RNA_property_is_set(op->ptr, prop)) {
- RNA_property_boolean_set(op->ptr, prop, (bake->flag & R_BAKE_SPLIT_MAT));
+ RNA_property_boolean_set(op->ptr, prop, (bake->flag & R_BAKE_SPLIT_MAT) != 0);
}
prop = RNA_struct_find_property(op->ptr, "use_automatic_name");
if (!RNA_property_is_set(op->ptr, prop)) {
- RNA_property_boolean_set(op->ptr, prop, (bake->flag & R_BAKE_AUTO_NAME));
+ RNA_property_boolean_set(op->ptr, prop, (bake->flag & R_BAKE_AUTO_NAME) != 0);
}
}
diff --git a/source/blender/editors/object/object_constraint.c b/source/blender/editors/object/object_constraint.c
index 92ed84b7f5e..2697a5e5fb1 100644
--- a/source/blender/editors/object/object_constraint.c
+++ b/source/blender/editors/object/object_constraint.c
@@ -40,7 +40,7 @@
#include "BLI_dynstr.h"
#include "BLI_utildefines.h"
-#include "BLF_translation.h"
+#include "BLT_translation.h"
#include "DNA_anim_types.h"
#include "DNA_constraint_types.h"
@@ -226,14 +226,14 @@ static void update_pyconstraint_cb(void *arg1, void *arg2)
/* helper function for add_constriant - sets the last target for the active constraint */
static void set_constraint_nth_target(bConstraint *con, Object *target, const char subtarget[], int index)
{
- bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
+ const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
ListBase targets = {NULL, NULL};
bConstraintTarget *ct;
int num_targets, i;
if (cti && cti->get_constraint_targets) {
cti->get_constraint_targets(con, &targets);
- num_targets = BLI_countlist(&targets);
+ num_targets = BLI_listbase_count(&targets);
if (index < 0) {
if (abs(index) < num_targets)
@@ -260,17 +260,221 @@ static void set_constraint_nth_target(bConstraint *con, Object *target, const ch
/* ------------- Constraint Sanity Testing ------------------- */
-/* checks validity of object pointers, and NULLs,
- * if Bone doesnt exist it sets the CONSTRAINT_DISABLE flag.
- */
-static void test_constraints(Object *owner, bPoseChannel *pchan)
+static void test_constraint(Object *owner, bPoseChannel *pchan, bConstraint *con, int type)
+{
+ const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
+ ListBase targets = {NULL, NULL};
+ bConstraintTarget *ct;
+ bool check_targets = true;
+
+ /* clear disabled-flag first */
+ con->flag &= ~CONSTRAINT_DISABLE;
+
+ if (con->type == CONSTRAINT_TYPE_KINEMATIC) {
+ bKinematicConstraint *data = con->data;
+
+ /* bad: we need a separate set of checks here as poletarget is
+ * optional... otherwise poletarget must exist too or else
+ * the constraint is deemed invalid
+ */
+ /* default IK check ... */
+ if (BKE_object_exists_check(data->tar) == 0) {
+ data->tar = NULL;
+ con->flag |= CONSTRAINT_DISABLE;
+ }
+ else if (data->tar == owner) {
+ if (!BKE_armature_find_bone_name(BKE_armature_from_object(owner), data->subtarget)) {
+ con->flag |= CONSTRAINT_DISABLE;
+ }
+ }
+
+ if (data->poletar) {
+ if (BKE_object_exists_check(data->poletar) == 0) {
+ data->poletar = NULL;
+ con->flag |= CONSTRAINT_DISABLE;
+ }
+ else if (data->poletar == owner) {
+ if (!BKE_armature_find_bone_name(BKE_armature_from_object(owner), data->polesubtarget)) {
+ con->flag |= CONSTRAINT_DISABLE;
+ }
+ }
+ }
+ /* ... can be overwritten here */
+ BIK_test_constraint(owner, con);
+ /* targets have already been checked for this */
+ check_targets = false;
+ }
+ else if (con->type == CONSTRAINT_TYPE_PIVOT) {
+ bPivotConstraint *data = con->data;
+
+ /* target doesn't have to exist, but if it is non-null, it must exist! */
+ if (data->tar && BKE_object_exists_check(data->tar) == 0) {
+ data->tar = NULL;
+ con->flag |= CONSTRAINT_DISABLE;
+ }
+ else if (data->tar == owner) {
+ if (!BKE_armature_find_bone_name(BKE_armature_from_object(owner), data->subtarget)) {
+ con->flag |= CONSTRAINT_DISABLE;
+ }
+ }
+
+ /* targets have already been checked for this */
+ check_targets = false;
+ }
+ else if (con->type == CONSTRAINT_TYPE_ACTION) {
+ bActionConstraint *data = con->data;
+
+ /* validate action */
+ if (data->act == NULL) {
+ /* must have action */
+ con->flag |= CONSTRAINT_DISABLE;
+ }
+ else if (data->act->idroot != ID_OB) {
+ /* only object-rooted actions can be used */
+ data->act = NULL;
+ con->flag |= CONSTRAINT_DISABLE;
+ }
+ }
+ else if (con->type == CONSTRAINT_TYPE_FOLLOWPATH) {
+ bFollowPathConstraint *data = con->data;
+
+ /* don't allow track/up axes to be the same */
+ if (data->upflag == data->trackflag)
+ con->flag |= CONSTRAINT_DISABLE;
+ if (data->upflag + 3 == data->trackflag)
+ con->flag |= CONSTRAINT_DISABLE;
+ }
+ else if (con->type == CONSTRAINT_TYPE_TRACKTO) {
+ bTrackToConstraint *data = con->data;
+
+ /* don't allow track/up axes to be the same */
+ if (data->reserved2 == data->reserved1)
+ con->flag |= CONSTRAINT_DISABLE;
+ if (data->reserved2 + 3 == data->reserved1)
+ con->flag |= CONSTRAINT_DISABLE;
+ }
+ else if (con->type == CONSTRAINT_TYPE_LOCKTRACK) {
+ bLockTrackConstraint *data = con->data;
+
+ if (data->lockflag == data->trackflag)
+ con->flag |= CONSTRAINT_DISABLE;
+ if (data->lockflag + 3 == data->trackflag)
+ con->flag |= CONSTRAINT_DISABLE;
+ }
+ else if (con->type == CONSTRAINT_TYPE_SPLINEIK) {
+ bSplineIKConstraint *data = con->data;
+
+ /* if the number of points does not match the amount required by the chain length,
+ * free the points array and request a rebind...
+ */
+ if ((data->points == NULL) || (data->numpoints != data->chainlen + 1)) {
+ /* free the points array */
+ if (data->points) {
+ MEM_freeN(data->points);
+ data->points = NULL;
+ }
+
+ /* clear the bound flag, forcing a rebind next time this is evaluated */
+ data->flag &= ~CONSTRAINT_SPLINEIK_BOUND;
+ }
+ }
+ else if (con->type == CONSTRAINT_TYPE_FOLLOWTRACK) {
+ bFollowTrackConstraint *data = con->data;
+
+ if ((data->flag & CAMERASOLVER_ACTIVECLIP) == 0) {
+ if (data->clip != NULL && data->track[0]) {
+ MovieTracking *tracking = &data->clip->tracking;
+ MovieTrackingObject *tracking_object;
+
+ if (data->object[0])
+ tracking_object = BKE_tracking_object_get_named(tracking, data->object);
+ else
+ tracking_object = BKE_tracking_object_get_camera(tracking);
+
+ if (!tracking_object) {
+ con->flag |= CONSTRAINT_DISABLE;
+ }
+ else {
+ if (!BKE_tracking_track_get_named(tracking, tracking_object, data->track))
+ con->flag |= CONSTRAINT_DISABLE;
+ }
+ }
+ else {
+ con->flag |= CONSTRAINT_DISABLE;
+ }
+ }
+ }
+ else if (con->type == CONSTRAINT_TYPE_CAMERASOLVER) {
+ bCameraSolverConstraint *data = con->data;
+
+ if ((data->flag & CAMERASOLVER_ACTIVECLIP) == 0 && (data->clip == NULL))
+ con->flag |= CONSTRAINT_DISABLE;
+ }
+ else if (con->type == CONSTRAINT_TYPE_OBJECTSOLVER) {
+ bObjectSolverConstraint *data = con->data;
+
+ if ((data->flag & CAMERASOLVER_ACTIVECLIP) == 0 && (data->clip == NULL))
+ con->flag |= CONSTRAINT_DISABLE;
+ }
+
+ /* Check targets for constraints */
+ if (check_targets && cti && cti->get_constraint_targets) {
+ cti->get_constraint_targets(con, &targets);
+
+ /* disable and clear constraints targets that are incorrect */
+ for (ct = targets.first; ct; ct = ct->next) {
+ /* general validity checks (for those constraints that need this) */
+ if (BKE_object_exists_check(ct->tar) == 0) {
+ /* object doesn't exist, but constraint requires target */
+ ct->tar = NULL;
+ con->flag |= CONSTRAINT_DISABLE;
+ }
+ else if (ct->tar == owner) {
+ if (type == CONSTRAINT_OBTYPE_BONE) {
+ if (!BKE_armature_find_bone_name(BKE_armature_from_object(owner), ct->subtarget)) {
+ /* bone must exist in armature... */
+ /* TODO: clear subtarget? */
+ con->flag |= CONSTRAINT_DISABLE;
+ }
+ else if (STREQ(pchan->name, ct->subtarget)) {
+ /* cannot target self */
+ ct->subtarget[0] = '\0';
+ con->flag |= CONSTRAINT_DISABLE;
+ }
+ }
+ else {
+ /* cannot use self as target */
+ ct->tar = NULL;
+ con->flag |= CONSTRAINT_DISABLE;
+ }
+ }
+
+ /* target checks for specific constraints */
+ if (ELEM(con->type, CONSTRAINT_TYPE_FOLLOWPATH, CONSTRAINT_TYPE_CLAMPTO, CONSTRAINT_TYPE_SPLINEIK)) {
+ if (ct->tar) {
+ if (ct->tar->type != OB_CURVE) {
+ ct->tar = NULL;
+ con->flag |= CONSTRAINT_DISABLE;
+ }
+ else {
+ Curve *cu = ct->tar->data;
+
+ /* auto-set 'Path' setting on curve so this works */
+ cu->flag |= CU_PATH;
+ }
+ }
+ }
+ }
+
+ /* free any temporary targets */
+ if (cti->flush_constraint_targets)
+ cti->flush_constraint_targets(con, &targets, 0);
+ }
+}
+
+static int constraint_type_get(Object *owner, bPoseChannel *pchan)
{
- bConstraint *curcon;
- ListBase *conlist = NULL;
int type;
-
- if (owner == NULL) return;
-
/* Check parents */
if (pchan) {
switch (owner->type) {
@@ -284,7 +488,22 @@ static void test_constraints(Object *owner, bPoseChannel *pchan)
}
else
type = CONSTRAINT_OBTYPE_OBJECT;
+ return type;
+}
+
+/* checks validity of object pointers, and NULLs,
+ * if Bone doesnt exist it sets the CONSTRAINT_DISABLE flag.
+ */
+static void test_constraints(Object *owner, bPoseChannel *pchan)
+{
+ bConstraint *curcon;
+ ListBase *conlist = NULL;
+ int type;
+ if (owner == NULL) return;
+
+ type = constraint_type_get(owner, pchan);
+
/* Get the constraint list for this object */
switch (type) {
case CONSTRAINT_OBTYPE_OBJECT:
@@ -298,213 +517,7 @@ static void test_constraints(Object *owner, bPoseChannel *pchan)
/* Check all constraints - is constraint valid? */
if (conlist) {
for (curcon = conlist->first; curcon; curcon = curcon->next) {
- bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(curcon);
- ListBase targets = {NULL, NULL};
- bConstraintTarget *ct;
-
- /* clear disabled-flag first */
- curcon->flag &= ~CONSTRAINT_DISABLE;
-
- if (curcon->type == CONSTRAINT_TYPE_KINEMATIC) {
- bKinematicConstraint *data = curcon->data;
-
- /* bad: we need a separate set of checks here as poletarget is
- * optional... otherwise poletarget must exist too or else
- * the constraint is deemed invalid
- */
- /* default IK check ... */
- if (BKE_object_exists_check(data->tar) == 0) {
- data->tar = NULL;
- curcon->flag |= CONSTRAINT_DISABLE;
- }
- else if (data->tar == owner) {
- if (!BKE_armature_find_bone_name(BKE_armature_from_object(owner), data->subtarget)) {
- curcon->flag |= CONSTRAINT_DISABLE;
- }
- }
-
- if (data->poletar) {
- if (BKE_object_exists_check(data->poletar) == 0) {
- data->poletar = NULL;
- curcon->flag |= CONSTRAINT_DISABLE;
- }
- else if (data->poletar == owner) {
- if (!BKE_armature_find_bone_name(BKE_armature_from_object(owner), data->polesubtarget)) {
- curcon->flag |= CONSTRAINT_DISABLE;
- }
- }
- }
- /* ... can be overwritten here */
- BIK_test_constraint(owner, curcon);
- /* targets have already been checked for this */
- continue;
- }
- else if (curcon->type == CONSTRAINT_TYPE_PIVOT) {
- bPivotConstraint *data = curcon->data;
-
- /* target doesn't have to exist, but if it is non-null, it must exist! */
- if (data->tar && BKE_object_exists_check(data->tar) == 0) {
- data->tar = NULL;
- curcon->flag |= CONSTRAINT_DISABLE;
- }
- else if (data->tar == owner) {
- if (!BKE_armature_find_bone_name(BKE_armature_from_object(owner), data->subtarget)) {
- curcon->flag |= CONSTRAINT_DISABLE;
- }
- }
-
- /* targets have already been checked for this */
- continue;
- }
- else if (curcon->type == CONSTRAINT_TYPE_ACTION) {
- bActionConstraint *data = curcon->data;
-
- /* validate action */
- if (data->act == NULL) {
- /* must have action */
- curcon->flag |= CONSTRAINT_DISABLE;
- }
- else if (data->act->idroot != ID_OB) {
- /* only object-rooted actions can be used */
- data->act = NULL;
- curcon->flag |= CONSTRAINT_DISABLE;
- }
- }
- else if (curcon->type == CONSTRAINT_TYPE_FOLLOWPATH) {
- bFollowPathConstraint *data = curcon->data;
-
- /* don't allow track/up axes to be the same */
- if (data->upflag == data->trackflag)
- curcon->flag |= CONSTRAINT_DISABLE;
- if (data->upflag + 3 == data->trackflag)
- curcon->flag |= CONSTRAINT_DISABLE;
- }
- else if (curcon->type == CONSTRAINT_TYPE_TRACKTO) {
- bTrackToConstraint *data = curcon->data;
-
- /* don't allow track/up axes to be the same */
- if (data->reserved2 == data->reserved1)
- curcon->flag |= CONSTRAINT_DISABLE;
- if (data->reserved2 + 3 == data->reserved1)
- curcon->flag |= CONSTRAINT_DISABLE;
- }
- else if (curcon->type == CONSTRAINT_TYPE_LOCKTRACK) {
- bLockTrackConstraint *data = curcon->data;
-
- if (data->lockflag == data->trackflag)
- curcon->flag |= CONSTRAINT_DISABLE;
- if (data->lockflag + 3 == data->trackflag)
- curcon->flag |= CONSTRAINT_DISABLE;
- }
- else if (curcon->type == CONSTRAINT_TYPE_SPLINEIK) {
- bSplineIKConstraint *data = curcon->data;
-
- /* if the number of points does not match the amount required by the chain length,
- * free the points array and request a rebind...
- */
- if ((data->points == NULL) || (data->numpoints != data->chainlen + 1)) {
- /* free the points array */
- if (data->points) {
- MEM_freeN(data->points);
- data->points = NULL;
- }
-
- /* clear the bound flag, forcing a rebind next time this is evaluated */
- data->flag &= ~CONSTRAINT_SPLINEIK_BOUND;
- }
- }
- else if (curcon->type == CONSTRAINT_TYPE_FOLLOWTRACK) {
- bFollowTrackConstraint *data = curcon->data;
-
- if ((data->flag & CAMERASOLVER_ACTIVECLIP) == 0) {
- if (data->clip != NULL && data->track[0]) {
- MovieTracking *tracking = &data->clip->tracking;
- MovieTrackingObject *tracking_object;
-
- if (data->object[0])
- tracking_object = BKE_tracking_object_get_named(tracking, data->object);
- else
- tracking_object = BKE_tracking_object_get_camera(tracking);
-
- if (!tracking_object) {
- curcon->flag |= CONSTRAINT_DISABLE;
- }
- else {
- if (!BKE_tracking_track_get_named(tracking, tracking_object, data->track))
- curcon->flag |= CONSTRAINT_DISABLE;
- }
- }
- else {
- curcon->flag |= CONSTRAINT_DISABLE;
- }
- }
- }
- else if (curcon->type == CONSTRAINT_TYPE_CAMERASOLVER) {
- bCameraSolverConstraint *data = curcon->data;
-
- if ((data->flag & CAMERASOLVER_ACTIVECLIP) == 0 && (data->clip == NULL))
- curcon->flag |= CONSTRAINT_DISABLE;
- }
- else if (curcon->type == CONSTRAINT_TYPE_OBJECTSOLVER) {
- bObjectSolverConstraint *data = curcon->data;
-
- if ((data->flag & CAMERASOLVER_ACTIVECLIP) == 0 && (data->clip == NULL))
- curcon->flag |= CONSTRAINT_DISABLE;
- }
-
- /* Check targets for constraints */
- if (cti && cti->get_constraint_targets) {
- cti->get_constraint_targets(curcon, &targets);
-
- /* disable and clear constraints targets that are incorrect */
- for (ct = targets.first; ct; ct = ct->next) {
- /* general validity checks (for those constraints that need this) */
- if (BKE_object_exists_check(ct->tar) == 0) {
- /* object doesn't exist, but constraint requires target */
- ct->tar = NULL;
- curcon->flag |= CONSTRAINT_DISABLE;
- }
- else if (ct->tar == owner) {
- if (type == CONSTRAINT_OBTYPE_BONE) {
- if (!BKE_armature_find_bone_name(BKE_armature_from_object(owner), ct->subtarget)) {
- /* bone must exist in armature... */
- /* TODO: clear subtarget? */
- curcon->flag |= CONSTRAINT_DISABLE;
- }
- else if (strcmp(pchan->name, ct->subtarget) == 0) {
- /* cannot target self */
- ct->subtarget[0] = '\0';
- curcon->flag |= CONSTRAINT_DISABLE;
- }
- }
- else {
- /* cannot use self as target */
- ct->tar = NULL;
- curcon->flag |= CONSTRAINT_DISABLE;
- }
- }
-
- /* target checks for specific constraints */
- if (ELEM(curcon->type, CONSTRAINT_TYPE_FOLLOWPATH, CONSTRAINT_TYPE_CLAMPTO, CONSTRAINT_TYPE_SPLINEIK)) {
- if (ct->tar) {
- if (ct->tar->type != OB_CURVE) {
- ct->tar = NULL;
- curcon->flag |= CONSTRAINT_DISABLE;
- }
- else {
- Curve *cu = ct->tar->data;
-
- /* auto-set 'Path' setting on curve so this works */
- cu->flag |= CU_PATH;
- }
- }
- }
- }
-
- /* free any temporary targets */
- if (cti->flush_constraint_targets)
- cti->flush_constraint_targets(curcon, &targets, 0);
- }
+ test_constraint(owner, pchan, curcon, type);
}
}
}
@@ -524,6 +537,26 @@ void object_test_constraints(Object *owner)
}
}
+static void object_test_constraint(Object *owner, bConstraint *con)
+{
+ if (owner->type == OB_ARMATURE && owner->pose) {
+ if (BLI_findindex(&owner->constraints, con) != -1) {
+ test_constraint(owner, NULL, con, CONSTRAINT_OBTYPE_OBJECT);
+ }
+ else {
+ bPoseChannel *pchan;
+ for (pchan = owner->pose->chanbase.first; pchan; pchan = pchan->next) {
+ if (BLI_findindex(&pchan->constraints, con) != -1) {
+ test_constraint(owner, pchan, con, CONSTRAINT_OBTYPE_BONE);
+ break;
+ }
+ }
+ }
+ }
+ else {
+ test_constraint(owner, NULL, con, CONSTRAINT_OBTYPE_OBJECT);
+ }
+}
/************************ generic functions for operators using constraint names and data context *********************/
@@ -1161,11 +1194,50 @@ void ED_object_constraint_update(Object *ob)
DAG_id_tag_update(&ob->id, OB_RECALC_OB);
}
+static void object_pose_tag_update(Main *bmain, Object *ob)
+{
+ BKE_pose_tag_recalc(bmain, ob->pose); /* Checks & sort pose channels. */
+ if (ob->proxy && ob->adt) {
+ /* We need to make use of ugly POSE_ANIMATION_WORKAROUND here too, else anim data are not reloaded
+ * after calling `BKE_pose_rebuild()`, which causes T43872.
+ * Note that this is a bit wide here, since we cannot be sure whether there are some locked proxy bones
+ * or not...
+ * XXX Temp hack until new depsgraph hopefully solves this. */
+ ob->adt->recalc |= ADT_RECALC_ANIM;
+ }
+}
+
void ED_object_constraint_dependency_update(Main *bmain, Object *ob)
{
ED_object_constraint_update(ob);
- if (ob->pose) ob->pose->flag |= POSE_RECALC; // checks & sorts pose channels
+ if (ob->pose) {
+ object_pose_tag_update(bmain, ob);
+ }
+ DAG_relations_tag_update(bmain);
+}
+
+void ED_object_constraint_tag_update(Object *ob, bConstraint *con)
+{
+ if (ob->pose) {
+ BKE_pose_tag_update_constraint_flags(ob->pose);
+ }
+
+ object_test_constraint(ob, con);
+
+ if (ob->type == OB_ARMATURE)
+ DAG_id_tag_update(&ob->id, OB_RECALC_DATA | OB_RECALC_OB);
+ else
+ DAG_id_tag_update(&ob->id, OB_RECALC_OB);
+}
+
+void ED_object_constraint_dependency_tag_update(Main *bmain, Object *ob, bConstraint *con)
+{
+ ED_object_constraint_tag_update(ob, con);
+
+ if (ob->pose) {
+ object_pose_tag_update(bmain, ob);
+ }
DAG_relations_tag_update(bmain);
}
@@ -1182,20 +1254,16 @@ static int constraint_delete_exec(bContext *C, wmOperator *UNUSED(op))
Object *ob = ptr.id.data;
bConstraint *con = ptr.data;
ListBase *lb = get_constraint_lb(ob, con, NULL);
- const bool is_ik = ELEM(con->type, CONSTRAINT_TYPE_KINEMATIC, CONSTRAINT_TYPE_SPLINEIK);
/* free the constraint */
- if (BKE_constraint_remove(lb, con)) {
+ if (BKE_constraint_remove_ex(lb, ob, con, true)) {
/* there's no active constraint now, so make sure this is the case */
- BKE_constraints_active_set(lb, NULL);
-
+ BKE_constraints_active_set(&ob->constraints, NULL);
ED_object_constraint_update(ob); /* needed to set the flags on posebones correctly */
-
- /* ITASC needs to be rebuilt once a constraint is removed [#26920] */
- if (is_ik) {
- BIK_clear_data(ob->pose);
- }
-
+
+ /* relatiols */
+ DAG_relations_tag_update(CTX_data_main(C));
+
/* notifiers */
WM_event_add_notifier(C, NC_OBJECT | ND_CONSTRAINT | NA_REMOVED, ob);
@@ -1399,6 +1467,8 @@ static int pose_constraint_copy_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
bPoseChannel *pchan = CTX_data_active_pose_bone(C);
+ ListBase lb;
+ CollectionPointerLink *link;
/* don't do anything if bone doesn't exist or doesn't have any constraints */
if (ELEM(NULL, pchan, pchan->constraints.first)) {
@@ -1407,16 +1477,22 @@ static int pose_constraint_copy_exec(bContext *C, wmOperator *op)
}
/* copy all constraints from active posebone to all selected posebones */
- CTX_DATA_BEGIN (C, bPoseChannel *, chan, selected_pose_bones)
- {
+ CTX_data_selected_pose_bones(C, &lb);
+ for (link = lb.first; link; link = link->next) {
+ Object *ob = link->ptr.id.data;
+ bPoseChannel *chan = link->ptr.data;
+
/* if we're not handling the object we're copying from, copy all constraints over */
if (pchan != chan) {
BKE_constraints_copy(&chan->constraints, &pchan->constraints, true);
/* update flags (need to add here, not just copy) */
chan->constflag |= pchan->constflag;
+
+ BKE_pose_tag_recalc(bmain, ob->pose);
+ DAG_id_tag_update((ID *)ob, OB_RECALC_DATA);
}
}
- CTX_DATA_END;
+ BLI_freelistN(&lb);
/* force depsgraph to get recalculated since new relationships added */
DAG_relations_tag_update(bmain);
@@ -1589,7 +1665,7 @@ static short get_new_constraint_target(bContext *C, int con_type, Object **tar_o
Object *obt;
/* add new target object */
- obt = BKE_object_add(bmain, scene, OB_EMPTY);
+ obt = BKE_object_add(bmain, scene, OB_EMPTY, NULL);
/* set layers OK */
newbase = BASACT;
@@ -1723,7 +1799,13 @@ static int constraint_add_exec(bContext *C, wmOperator *op, Object *ob, ListBase
DAG_relations_tag_update(bmain);
if ((ob->type == OB_ARMATURE) && (pchan)) {
- ob->pose->flag |= POSE_RECALC; /* sort pose channels */
+ BKE_pose_tag_recalc(bmain, ob->pose); /* sort pose channels */
+ if (BKE_constraints_proxylocked_owner(ob, pchan) && ob->adt) {
+ /* We need to make use of ugly POSE_ANIMATION_WORKAROUND here too, else anim data are not reloaded
+ * after calling `BKE_pose_rebuild()`, which causes T43872.
+ * XXX Temp hack until new depsgraph hopefully solves this. */
+ ob->adt->recalc |= ADT_RECALC_ANIM;
+ }
DAG_id_tag_update(&ob->id, OB_RECALC_DATA | OB_RECALC_OB);
}
else
@@ -1889,8 +1971,8 @@ static int pose_ik_add_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED
}
/* prepare popup menu to choose targetting options */
- pup = uiPupMenuBegin(C, IFACE_("Add IK"), ICON_NONE);
- layout = uiPupMenuLayout(pup);
+ pup = UI_popup_menu_begin(C, IFACE_("Add IK"), ICON_NONE);
+ layout = UI_popup_menu_layout(pup);
/* the type of targets we'll set determines the menu entries to show... */
if (get_new_constraint_target(C, CONSTRAINT_TYPE_KINEMATIC, &tar_ob, &tar_pchan, 0)) {
@@ -1909,9 +1991,9 @@ static int pose_ik_add_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED
}
/* finish building the menu, and process it (should result in calling self again) */
- uiPupMenuEnd(C, pup);
+ UI_popup_menu_end(C, pup);
- return OPERATOR_CANCELLED;
+ return OPERATOR_INTERFACE;
}
/* call constraint_add_exec() to add the IK constraint */
diff --git a/source/blender/editors/object/object_data_transfer.c b/source/blender/editors/object/object_data_transfer.c
new file mode 100644
index 00000000000..95e1204e122
--- /dev/null
+++ b/source/blender/editors/object/object_data_transfer.c
@@ -0,0 +1,729 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2014 by Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Bastien Montagne.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/editors/object/object_data_transfer.c
+ * \ingroup edobj
+ */
+
+#include "DNA_mesh_types.h"
+#include "DNA_modifier_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+
+#include "BLI_math.h"
+#include "BLI_blenlib.h"
+#include "BLI_utildefines.h"
+
+#include "BKE_context.h"
+#include "BKE_data_transfer.h"
+#include "BKE_depsgraph.h"
+#include "BKE_DerivedMesh.h"
+#include "BKE_mesh_mapping.h"
+#include "BKE_mesh_remap.h"
+#include "BKE_object.h"
+#include "BKE_report.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+#include "RNA_enum_types.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "ED_object.h"
+
+#include "UI_interface.h"
+
+#include "object_intern.h"
+
+/* All possible data to transfer.
+ * Note some are 'fake' ones, i.e. they are not hold by real CDLayers. */
+/* Not shared with modifier, since we use a usual enum here, not a multi-choice one. */
+static EnumPropertyItem DT_layer_items[] = {
+ {0, "", 0, "Vertex Data", ""},
+ {DT_TYPE_MDEFORMVERT, "VGROUP_WEIGHTS", 0, "Vertex Group(s)", "Transfer active or all vertex groups"},
+#if 0 /* XXX For now, would like to finish/merge work from 2014 gsoc first. */
+ {DT_TYPE_SHAPEKEY, "SHAPEKEYS", 0, "Shapekey(s)", "Transfer active or all shape keys"},
+#endif
+#if 0 /* XXX When SkinModifier is enabled, it seems to erase its own CD_MVERT_SKIN layer from final DM :( */
+ {DT_TYPE_SKIN, "SKIN", 0, "Skin Weight", "Transfer skin weights"},
+#endif
+ {DT_TYPE_BWEIGHT_VERT, "BEVEL_WEIGHT_VERT", 0, "Bevel Weight", "Transfer bevel weights"},
+ {0, "", 0, "Edge Data", ""},
+ {DT_TYPE_SHARP_EDGE, "SHARP_EDGE", 0, "Sharp", "Transfer sharp mark"},
+ {DT_TYPE_SEAM, "SEAM", 0, "UV Seam", "Transfer UV seam mark"},
+ {DT_TYPE_CREASE, "CREASE", 0, "Subsurf Crease", "Transfer crease values"},
+ {DT_TYPE_BWEIGHT_EDGE, "BEVEL_WEIGHT_EDGE", 0, "Bevel Weight", "Transfer bevel weights"},
+ {DT_TYPE_FREESTYLE_EDGE, "FREESTYLE_EDGE", 0, "Freestyle Mark", "Transfer Freestyle edge mark"},
+ {0, "", 0, "Face Corner Data", ""},
+ {DT_TYPE_LNOR, "CUSTOM_NORMAL", 0, "Custom Normals", "Transfer custom normals"},
+ {DT_TYPE_VCOL, "VCOL", 0, "VCol", "Vertex (face corners) colors"},
+ {DT_TYPE_UV, "UV", 0, "UVs", "Transfer UV layers"},
+ {0, "", 0, "Face Data", ""},
+ {DT_TYPE_SHARP_FACE, "SMOOTH", 0, "Smooth", "Transfer flat/smooth mark"},
+ {DT_TYPE_FREESTYLE_FACE, "FREESTYLE_FACE", 0, "Freestyle Mark", "Transfer Freestyle face mark"},
+ {0, NULL, 0, NULL, NULL}
+};
+
+/* Note: DT_layers_select_src_items enum is from rna_modifier.c */
+static EnumPropertyItem *dt_layers_select_src_itemf(
+ bContext *C, PointerRNA *ptr, PropertyRNA *UNUSED(prop), bool *r_free)
+{
+ EnumPropertyItem *item = NULL, tmp_item = {0};
+ int totitem = 0;
+
+ const int data_type = RNA_enum_get(ptr, "data_type");
+
+ if (!C) { /* needed for docs and i18n tools */
+ return DT_layers_select_src_items;
+ }
+
+ RNA_enum_items_add_value(&item, &totitem, DT_layers_select_src_items, DT_LAYERS_ACTIVE_SRC);
+ RNA_enum_items_add_value(&item, &totitem, DT_layers_select_src_items, DT_LAYERS_ALL_SRC);
+
+ if (data_type == DT_TYPE_MDEFORMVERT) {
+ Object *ob_src = CTX_data_active_object(C);
+
+ if (BKE_object_pose_armature_get(ob_src)) {
+ RNA_enum_items_add_value(&item, &totitem, DT_layers_select_src_items, DT_LAYERS_VGROUP_SRC_BONE_SELECT);
+ RNA_enum_items_add_value(&item, &totitem, DT_layers_select_src_items, DT_LAYERS_VGROUP_SRC_BONE_DEFORM);
+ }
+
+ if (ob_src) {
+ bDeformGroup *dg;
+ int i;
+
+ RNA_enum_item_add_separator(&item, &totitem);
+
+ for (i = 0, dg = ob_src->defbase.first; dg; i++, dg = dg->next) {
+ tmp_item.value = i;
+ tmp_item.identifier = tmp_item.name = dg->name;
+ RNA_enum_item_add(&item, &totitem, &tmp_item);
+ }
+ }
+ }
+ else if (data_type == DT_TYPE_SHAPEKEY) {
+ /* TODO */
+ }
+ else if (data_type == DT_TYPE_UV) {
+ Object *ob_src = CTX_data_active_object(C);
+ Scene *scene = CTX_data_scene(C);
+
+ if (ob_src) {
+ DerivedMesh *dm_src;
+ CustomData *pdata;
+ int num_data, i;
+
+ /* XXX Is this OK? */
+ dm_src = mesh_get_derived_final(scene, ob_src, CD_MASK_BAREMESH | CD_MTEXPOLY);
+ pdata = dm_src->getPolyDataLayout(dm_src);
+ num_data = CustomData_number_of_layers(pdata, CD_MTEXPOLY);
+
+ RNA_enum_item_add_separator(&item, &totitem);
+
+ for (i = 0; i < num_data; i++) {
+ tmp_item.value = i;
+ tmp_item.identifier = tmp_item.name = CustomData_get_layer_name(pdata, CD_MTEXPOLY, i);
+ RNA_enum_item_add(&item, &totitem, &tmp_item);
+ }
+ }
+ }
+ else if (data_type == DT_TYPE_VCOL) {
+ Object *ob_src = CTX_data_active_object(C);
+ Scene *scene = CTX_data_scene(C);
+
+ if (ob_src) {
+ DerivedMesh *dm_src;
+ CustomData *ldata;
+ int num_data, i;
+
+ /* XXX Is this OK? */
+ dm_src = mesh_get_derived_final(scene, ob_src, CD_MASK_BAREMESH | CD_MLOOPCOL);
+ ldata = dm_src->getLoopDataLayout(dm_src);
+ num_data = CustomData_number_of_layers(ldata, CD_MLOOPCOL);
+
+ RNA_enum_item_add_separator(&item, &totitem);
+
+ for (i = 0; i < num_data; i++) {
+ tmp_item.value = i;
+ tmp_item.identifier = tmp_item.name = CustomData_get_layer_name(ldata, CD_MLOOPCOL, i);
+ RNA_enum_item_add(&item, &totitem, &tmp_item);
+ }
+ }
+ }
+
+ RNA_enum_item_end(&item, &totitem);
+ *r_free = true;
+
+ return item;
+}
+
+/* Note: DT_layers_select_dst_items enum is from rna_modifier.c */
+static EnumPropertyItem *dt_layers_select_dst_itemf(
+ bContext *C, PointerRNA *ptr, PropertyRNA *UNUSED(prop), bool *r_free)
+{
+ EnumPropertyItem *item = NULL;
+ int totitem = 0;
+
+ const int layers_select_src = RNA_enum_get(ptr, "layers_select_src");
+
+ if (!C) { /* needed for docs and i18n tools */
+ return DT_layers_select_dst_items;
+ }
+
+ if (layers_select_src == DT_LAYERS_ACTIVE_SRC || layers_select_src >= 0) {
+ RNA_enum_items_add_value(&item, &totitem, DT_layers_select_dst_items, DT_LAYERS_ACTIVE_DST);
+ }
+ RNA_enum_items_add_value(&item, &totitem, DT_layers_select_dst_items, DT_LAYERS_NAME_DST);
+ RNA_enum_items_add_value(&item, &totitem, DT_layers_select_dst_items, DT_LAYERS_INDEX_DST);
+
+ /* No 'specific' to-layers here, since we may transfer to several objects at once! */
+
+ RNA_enum_item_end(&item, &totitem);
+ *r_free = true;
+
+ return item;
+}
+
+static EnumPropertyItem *dt_layers_select_itemf(bContext *C, PointerRNA *ptr, PropertyRNA *prop, bool *r_free)
+{
+ const bool reverse_transfer = RNA_boolean_get(ptr, "use_reverse_transfer");
+
+ if (STREQ(RNA_property_identifier(prop), "layers_select_dst")) {
+ if (reverse_transfer) {
+ return dt_layers_select_src_itemf(C, ptr, prop, r_free);
+ }
+ else {
+ return dt_layers_select_dst_itemf(C, ptr, prop, r_free);
+ }
+ }
+ else if (reverse_transfer) {
+ return dt_layers_select_dst_itemf(C, ptr, prop, r_free);
+ }
+ else {
+ return dt_layers_select_src_itemf(C, ptr, prop, r_free);
+ }
+}
+
+/* Note: DT_mix_mode_items enum is from rna_modifier.c */
+static EnumPropertyItem *dt_mix_mode_itemf(bContext *C, PointerRNA *ptr, PropertyRNA *UNUSED(prop), bool *r_free)
+{
+ EnumPropertyItem *item = NULL;
+ int totitem = 0;
+
+ const int dtdata_type = RNA_enum_get(ptr, "data_type");
+ bool support_advanced_mixing, support_threshold;
+
+ if (!C) { /* needed for docs and i18n tools */
+ return DT_mix_mode_items;
+ }
+
+ RNA_enum_items_add_value(&item, &totitem, DT_mix_mode_items, CDT_MIX_TRANSFER);
+
+ BKE_object_data_transfer_get_dttypes_capacity(dtdata_type, &support_advanced_mixing, &support_threshold);
+
+ if (support_threshold) {
+ RNA_enum_items_add_value(&item, &totitem, DT_mix_mode_items, CDT_MIX_REPLACE_ABOVE_THRESHOLD);
+ RNA_enum_items_add_value(&item, &totitem, DT_mix_mode_items, CDT_MIX_REPLACE_BELOW_THRESHOLD);
+ }
+
+ if (support_advanced_mixing) {
+ RNA_enum_item_add_separator(&item, &totitem);
+ RNA_enum_items_add_value(&item, &totitem, DT_mix_mode_items, CDT_MIX_MIX);
+ RNA_enum_items_add_value(&item, &totitem, DT_mix_mode_items, CDT_MIX_ADD);
+ RNA_enum_items_add_value(&item, &totitem, DT_mix_mode_items, CDT_MIX_SUB);
+ RNA_enum_items_add_value(&item, &totitem, DT_mix_mode_items, CDT_MIX_MUL);
+ }
+
+ RNA_enum_item_end(&item, &totitem);
+ *r_free = true;
+
+ return item;
+}
+
+static bool data_transfer_check(bContext *UNUSED(C), wmOperator *op)
+{
+ const int layers_select_src = RNA_enum_get(op->ptr, "layers_select_src");
+ PropertyRNA *prop = RNA_struct_find_property(op->ptr, "layers_select_dst");
+ const int layers_select_dst = RNA_property_enum_get(op->ptr, prop);
+
+ /* TODO: check for invalid layers_src select modes too! */
+
+ if ((layers_select_src != DT_LAYERS_ACTIVE_SRC) && (layers_select_dst == DT_LAYERS_ACTIVE_DST)) {
+ RNA_property_enum_set(op->ptr, prop, DT_LAYERS_NAME_DST);
+ return true;
+ }
+
+ return false;
+}
+
+/* Helper, used by both data_transfer_exec and datalayout_transfer_exec. */
+static void data_transfer_exec_preprocess_objects(
+ bContext *C, wmOperator *op, Object *ob_src, ListBase *ctx_objects, const bool reverse_transfer)
+{
+ CollectionPointerLink *ctx_ob;
+ CTX_data_selected_editable_objects(C, ctx_objects);
+
+ if (reverse_transfer) {
+ return; /* Nothing else to do in this case... */
+ }
+
+ for (ctx_ob = ctx_objects->first; ctx_ob; ctx_ob = ctx_ob->next) {
+ Object *ob = ctx_ob->ptr.data;
+ Mesh *me;
+ if ((ob == ob_src) || (ob->type != OB_MESH)) {
+ continue;
+ }
+
+ me = ob->data;
+ if (me->id.lib) {
+ /* Do not transfer to linked data, not supported. */
+ BKE_reportf(op->reports, RPT_WARNING, "Skipping object '%s', linked data '%s' cannot be modified",
+ ob->id.name + 2, me->id.name + 2);
+ me->id.flag &= ~LIB_DOIT;
+ continue;
+ }
+
+ me->id.flag |= LIB_DOIT;
+ }
+}
+
+/* Helper, used by both data_transfer_exec and datalayout_transfer_exec. */
+static bool data_transfer_exec_is_object_valid(
+ wmOperator *op, Object *ob_src, Object *ob_dst, const bool reverse_transfer)
+{
+ Mesh *me;
+ if ((ob_dst == ob_src) || (ob_src->type != OB_MESH) || (ob_dst->type != OB_MESH)) {
+ return false;
+ }
+
+ if (reverse_transfer) {
+ return true;
+ }
+
+ me = ob_dst->data;
+ if (me->id.flag & LIB_DOIT) {
+ me->id.flag &= ~LIB_DOIT;
+ return true;
+ }
+ else if (me->id.lib == NULL) {
+ /* Do not transfer apply operation more than once. */
+ /* XXX This is not nice regarding vgroups, which are half-Object data... :/ */
+ BKE_reportf(op->reports, RPT_WARNING,
+ "Skipping object '%s', data '%s' has already been processed with a previous object",
+ ob_dst->id.name + 2, me->id.name + 2);
+ }
+ return false;
+}
+
+static int data_transfer_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene = CTX_data_scene(C);
+ Object *ob_src = ED_object_active_context(C);
+
+ ListBase ctx_objects;
+ CollectionPointerLink *ctx_ob_dst;
+
+ bool changed = false;
+
+ const bool is_frozen = RNA_boolean_get(op->ptr, "use_freeze");
+
+ const bool reverse_transfer = RNA_boolean_get(op->ptr, "use_reverse_transfer");
+
+ const int data_type = RNA_enum_get(op->ptr, "data_type");
+ const bool use_create = RNA_boolean_get(op->ptr, "use_create");
+
+ const int map_vert_mode = RNA_enum_get(op->ptr, "vert_mapping");
+ const int map_edge_mode = RNA_enum_get(op->ptr, "edge_mapping");
+ const int map_loop_mode = RNA_enum_get(op->ptr, "loop_mapping");
+ const int map_poly_mode = RNA_enum_get(op->ptr, "poly_mapping");
+
+ const bool use_auto_transform = RNA_boolean_get(op->ptr, "use_auto_transform");
+ const bool use_object_transform = RNA_boolean_get(op->ptr, "use_object_transform");
+ const bool use_max_distance = RNA_boolean_get(op->ptr, "use_max_distance");
+ const float max_distance = use_max_distance ? RNA_float_get(op->ptr, "max_distance") : FLT_MAX;
+ const float ray_radius = RNA_float_get(op->ptr, "ray_radius");
+ const float islands_precision = RNA_float_get(op->ptr, "islands_precision");
+
+ const int layers_src = RNA_enum_get(op->ptr, "layers_select_src");
+ const int layers_dst = RNA_enum_get(op->ptr, "layers_select_dst");
+ int layers_select_src[DT_MULTILAYER_INDEX_MAX] = {0};
+ int layers_select_dst[DT_MULTILAYER_INDEX_MAX] = {0};
+ const int fromto_idx = BKE_object_data_transfer_dttype_to_srcdst_index(data_type);
+
+ const int mix_mode = RNA_enum_get(op->ptr, "mix_mode");
+ const float mix_factor = RNA_float_get(op->ptr, "mix_factor");
+
+ SpaceTransform space_transform_data;
+ SpaceTransform *space_transform = (use_object_transform && !use_auto_transform) ? &space_transform_data : NULL;
+
+ if (is_frozen) {
+ BKE_report(op->reports, RPT_INFO,
+ "Operator is frozen, changes to its settings won't take effect until you unfreeze it");
+ return OPERATOR_FINISHED;
+ }
+
+ if (reverse_transfer && ((ID *)(ob_src->data))->lib) {
+ /* Do not transfer to linked data, not supported. */
+ return OPERATOR_CANCELLED;
+ }
+
+ if (fromto_idx != DT_MULTILAYER_INDEX_INVALID) {
+ layers_select_src[fromto_idx] = layers_src;
+ layers_select_dst[fromto_idx] = layers_dst;
+ }
+
+ data_transfer_exec_preprocess_objects(C, op, ob_src, &ctx_objects, reverse_transfer);
+
+ for (ctx_ob_dst = ctx_objects.first; ctx_ob_dst; ctx_ob_dst = ctx_ob_dst->next) {
+ Object *ob_dst = ctx_ob_dst->ptr.data;
+
+ if (reverse_transfer) {
+ SWAP(Object *, ob_src, ob_dst);
+ }
+
+ if (data_transfer_exec_is_object_valid(op, ob_src, ob_dst, reverse_transfer)) {
+ if (space_transform) {
+ BLI_SPACE_TRANSFORM_SETUP(space_transform, ob_dst, ob_src);
+ }
+
+ if (BKE_object_data_transfer_mesh(
+ scene, ob_src, ob_dst, data_type, use_create,
+ map_vert_mode, map_edge_mode, map_loop_mode, map_poly_mode,
+ space_transform, use_auto_transform,
+ max_distance, ray_radius, islands_precision,
+ layers_select_src, layers_select_dst,
+ mix_mode, mix_factor, NULL, false, op->reports))
+ {
+ changed = true;
+ }
+ }
+
+ DAG_id_tag_update(&ob_dst->id, OB_RECALC_DATA);
+
+ if (reverse_transfer) {
+ SWAP(Object *, ob_src, ob_dst);
+ }
+ }
+
+ BLI_freelistN(&ctx_objects);
+
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, NULL);
+
+#if 0 /* TODO */
+ /* Note: issue with that is that if canceled, operator cannot be redone... Nasty in our case. */
+ return changed ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
+#else
+ (void)changed;
+ return OPERATOR_FINISHED;
+#endif
+}
+
+/* Used by both OBJECT_OT_data_transfer and OBJECT_OT_datalayout_transfer */
+/* Note this context poll is only really partial, it cannot check for all possible invalid cases. */
+static int data_transfer_poll(bContext *C)
+{
+ Object *ob = ED_object_active_context(C);
+ ID *data = (ob) ? ob->data : NULL;
+ return (ob && ob->type == OB_MESH && data);
+}
+
+/* Used by both OBJECT_OT_data_transfer and OBJECT_OT_datalayout_transfer */
+static bool data_transfer_draw_check_prop(PointerRNA *ptr, PropertyRNA *prop)
+{
+ PropertyRNA *prop_other;
+
+ const char *prop_id = RNA_property_identifier(prop);
+ const int data_type = RNA_enum_get(ptr, "data_type");
+ bool use_auto_transform = false;
+ bool use_max_distance = false;
+ bool use_modifier = false;
+
+ if ((prop_other = RNA_struct_find_property(ptr, "use_auto_transform"))) {
+ use_auto_transform = RNA_property_boolean_get(ptr, prop_other);
+ }
+ if ((prop_other = RNA_struct_find_property(ptr, "use_max_distance"))) {
+ use_max_distance = RNA_property_boolean_get(ptr, prop_other);
+ }
+ if ((prop_other = RNA_struct_find_property(ptr, "modifier"))) {
+ use_modifier = RNA_property_is_set(ptr, prop_other);
+ }
+
+ if (STREQ(prop_id, "modifier")) {
+ return use_modifier;
+ }
+
+ if (use_modifier) {
+ /* Hide everything but 'modifier' property, if set. */
+ return false;
+ }
+
+ if (STREQ(prop_id, "use_object_transform") && use_auto_transform) {
+ return false;
+ }
+ if (STREQ(prop_id, "max_distance") && !use_max_distance) {
+ return false;
+ }
+ if (STREQ(prop_id, "islands_precision") && !DT_DATATYPE_IS_LOOP(data_type)) {
+ return false;
+ }
+
+ if (STREQ(prop_id, "vert_mapping") && !DT_DATATYPE_IS_VERT(data_type)) {
+ return false;
+ }
+ if (STREQ(prop_id, "edge_mapping") && !DT_DATATYPE_IS_EDGE(data_type)) {
+ return false;
+ }
+ if (STREQ(prop_id, "loop_mapping") && !DT_DATATYPE_IS_LOOP(data_type)) {
+ return false;
+ }
+ if (STREQ(prop_id, "poly_mapping") && !DT_DATATYPE_IS_POLY(data_type)) {
+ return false;
+ }
+
+ if ((STREQ(prop_id, "layers_select_src") || STREQ(prop_id, "layers_select_dst")) &&
+ !DT_DATATYPE_IS_MULTILAYERS(data_type))
+ {
+ return false;
+ }
+
+ /* Else, show it! */
+ return true;
+}
+
+/* Used by both OBJECT_OT_data_transfer and OBJECT_OT_datalayout_transfer */
+static void data_transfer_ui(bContext *C, wmOperator *op)
+{
+ uiLayout *layout = op->layout;
+ wmWindowManager *wm = CTX_wm_manager(C);
+ PointerRNA ptr;
+
+ RNA_pointer_create(&wm->id, op->type->srna, op->properties, &ptr);
+
+ /* Main auto-draw call */
+ uiDefAutoButsRNA(layout, &ptr, data_transfer_draw_check_prop, '\0');
+}
+
+/* transfers weight from active to selected */
+void OBJECT_OT_data_transfer(wmOperatorType *ot)
+{
+ PropertyRNA *prop;
+
+ /* Identifiers.*/
+ ot->name = "Transfer Mesh Data";
+ ot->idname = "OBJECT_OT_data_transfer";
+ ot->description = "Transfer data layer(s) (weights, edge sharp, ...) from active to selected meshes";
+
+ /* API callbacks.*/
+ ot->poll = data_transfer_poll;
+ ot->invoke = WM_menu_invoke;
+ ot->exec = data_transfer_exec;
+ ot->check = data_transfer_check;
+ ot->ui = data_transfer_ui;
+
+ /* Flags.*/
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* Properties.*/
+ prop = RNA_def_boolean(ot->srna, "use_reverse_transfer", false, "Reverse Transfer",
+ "Transfer from selected objects to active one");
+ RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
+
+ RNA_def_boolean(ot->srna, "use_freeze", false, "Freeze Operator",
+ "Prevent changes to settings to re-run the operator, "
+ "handy to change several things at once with heavy geometry");
+
+ /* Data type to transfer. */
+ ot->prop = RNA_def_enum(ot->srna, "data_type", DT_layer_items, 0, "Data Type", "Which data to transfer");
+ RNA_def_boolean(ot->srna, "use_create", true, "Create Data", "Add data layers on destination meshes if needed");
+
+ /* Mapping methods. */
+ RNA_def_enum(ot->srna, "vert_mapping", DT_method_vertex_items, MREMAP_MODE_VERT_NEAREST, "Vertex Mapping",
+ "Method used to map source vertices to destination ones");
+ RNA_def_enum(ot->srna, "edge_mapping", DT_method_edge_items, MREMAP_MODE_EDGE_NEAREST, "Edge Mapping",
+ "Method used to map source edges to destination ones");
+ RNA_def_enum(ot->srna, "loop_mapping", DT_method_loop_items, MREMAP_MODE_LOOP_NEAREST_POLYNOR,
+ "Face Corner Mapping", "Method used to map source faces' corners to destination ones");
+ RNA_def_enum(ot->srna, "poly_mapping", DT_method_poly_items, MREMAP_MODE_POLY_NEAREST, "Face Mapping",
+ "Method used to map source faces to destination ones");
+
+ /* Mapping options and filtering. */
+ RNA_def_boolean(ot->srna, "use_auto_transform", false, "Auto Transform",
+ "Automatically compute transformation to get the best possible match between source and "
+ "destination meshes (WARNING: results will never be as good as manual matching of objects)");
+ RNA_def_boolean(ot->srna, "use_object_transform", true, "Object Transform",
+ "Evaluate source and destination meshes in global space");
+ RNA_def_boolean(ot->srna, "use_max_distance", false, "Only Neighbor Geometry",
+ "Source elements must be closer than given distance from destination one");
+ prop = RNA_def_float(ot->srna, "max_distance", 1.0f, 0.0f, FLT_MAX, "Max Distance",
+ "Maximum allowed distance between source and destination element, for non-topology mappings",
+ 0.0f, 100.0f);
+ RNA_def_property_subtype(prop, PROP_DISTANCE);
+ prop = RNA_def_float(ot->srna, "ray_radius", 0.0f, 0.0f, FLT_MAX, "Ray Radius",
+ "'Width' of rays (especially useful when raycasting against vertices or edges)",
+ 0.0f, 10.0f);
+ RNA_def_property_subtype(prop, PROP_DISTANCE);
+ prop = RNA_def_float(ot->srna, "islands_precision", 0.1f, 0.0f, 10.0f, "Islands Precision",
+ "Factor controlling precision of islands handling (the higher, the better the results)",
+ 0.0f, 1.0f);
+ RNA_def_property_subtype(prop, PROP_FACTOR);
+
+ /* How to handle multi-layers types of data. */
+ prop = RNA_def_enum(ot->srna, "layers_select_src", DT_layers_select_src_items, DT_LAYERS_ACTIVE_SRC,
+ "Source Layers Selection", "Which layers to transfer, in case of multi-layers types");
+ RNA_def_property_enum_funcs_runtime(prop, NULL, NULL, dt_layers_select_itemf);
+
+ prop = RNA_def_enum(ot->srna, "layers_select_dst", DT_layers_select_dst_items, DT_LAYERS_ACTIVE_DST,
+ "Destination Layers Matching", "How to match source and destination layers");
+ RNA_def_property_enum_funcs_runtime(prop, NULL, NULL, dt_layers_select_itemf);
+
+ prop = RNA_def_enum(ot->srna, "mix_mode", DT_mix_mode_items, CDT_MIX_TRANSFER, "Mix Mode",
+ "How to affect destination elements with source values");
+ RNA_def_property_enum_funcs_runtime(prop, NULL, NULL, dt_mix_mode_itemf);
+ RNA_def_float(ot->srna, "mix_factor", 1.0f, 0.0f, 1.0f, "Mix Factor",
+ "Factor to use when applying data to destination (exact behavior depends on mix mode)", 0.0f, 1.0f);
+}
+
+/******************************************************************************/
+/* Note: This operator is hybrid, it can work as a usual standalone Object operator,
+ * or as a DataTransfer modifier tool.
+ */
+
+static int datalayout_transfer_poll(bContext *C)
+{
+ return (edit_modifier_poll_generic(C, &RNA_DataTransferModifier, (1 << OB_MESH)) || data_transfer_poll(C));
+}
+
+static int datalayout_transfer_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene = CTX_data_scene(C);
+ Object *ob_act = ED_object_active_context(C);
+ DataTransferModifierData *dtmd;
+
+ dtmd = (DataTransferModifierData *)edit_modifier_property_get(op, ob_act, eModifierType_DataTransfer);
+
+ /* If we have a modifier, we transfer data layout from this modifier's source object to active one.
+ * Else, we transfer data layout from active object to all selected ones. */
+ if (dtmd) {
+ Object *ob_src = dtmd->ob_source;
+ Object *ob_dst = ob_act;
+
+ const bool use_delete = false; /* Never when used from modifier, for now. */
+
+ if (!ob_src) {
+ return OPERATOR_CANCELLED;
+ }
+
+ BKE_object_data_transfer_layout(scene, ob_src, ob_dst, dtmd->data_types, use_delete,
+ dtmd->layers_select_src, dtmd->layers_select_dst);
+
+ DAG_id_tag_update(&ob_dst->id, OB_RECALC_DATA);
+ }
+ else {
+ Object *ob_src = ob_act;
+
+ ListBase ctx_objects;
+ CollectionPointerLink *ctx_ob_dst;
+
+ const int data_type = RNA_enum_get(op->ptr, "data_type");
+ const bool use_delete = RNA_boolean_get(op->ptr, "use_delete");
+
+ const int layers_src = RNA_enum_get(op->ptr, "layers_select_src");
+ const int layers_dst = RNA_enum_get(op->ptr, "layers_select_dst");
+ int layers_select_src[DT_MULTILAYER_INDEX_MAX] = {0};
+ int layers_select_dst[DT_MULTILAYER_INDEX_MAX] = {0};
+ const int fromto_idx = BKE_object_data_transfer_dttype_to_srcdst_index(data_type);
+
+ if (fromto_idx != DT_MULTILAYER_INDEX_INVALID) {
+ layers_select_src[fromto_idx] = layers_src;
+ layers_select_dst[fromto_idx] = layers_dst;
+ }
+
+ data_transfer_exec_preprocess_objects(C, op, ob_src, &ctx_objects, false);
+
+ for (ctx_ob_dst = ctx_objects.first; ctx_ob_dst; ctx_ob_dst = ctx_ob_dst->next) {
+ Object *ob_dst = ctx_ob_dst->ptr.data;
+ if (data_transfer_exec_is_object_valid(op, ob_src, ob_dst, false)) {
+ BKE_object_data_transfer_layout(scene, ob_src, ob_dst, data_type, use_delete,
+ layers_select_src, layers_select_dst);
+ }
+
+ DAG_id_tag_update(&ob_dst->id, OB_RECALC_DATA);
+ }
+
+ BLI_freelistN(&ctx_objects);
+ }
+
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, NULL);
+
+ return OPERATOR_FINISHED;
+}
+
+static int datalayout_transfer_invoke(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ if (edit_modifier_invoke_properties(C, op)) {
+ return datalayout_transfer_exec(C, op);
+ }
+ else {
+ return WM_menu_invoke(C, op, event);
+ }
+}
+
+void OBJECT_OT_datalayout_transfer(wmOperatorType *ot)
+{
+ PropertyRNA *prop;
+
+ ot->name = "Transfer Mesh Data Layout";
+ ot->description = "Transfer layout of data layer(s) from active to selected meshes";
+ ot->idname = "OBJECT_OT_datalayout_transfer";
+
+ ot->poll = datalayout_transfer_poll;
+ ot->invoke = datalayout_transfer_invoke;
+ ot->exec = datalayout_transfer_exec;
+ ot->check = data_transfer_check;
+ ot->ui = data_transfer_ui;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* Properties.*/
+ edit_modifier_properties(ot);
+
+ /* Data type to transfer. */
+ ot->prop = RNA_def_enum(ot->srna, "data_type", DT_layer_items, 0, "Data Type", "Which data to transfer");
+ RNA_def_boolean(ot->srna, "use_delete", false, "Exact Match",
+ "Also delete some data layers from destination if necessary, so that it matches exactly source");
+
+ /* How to handle multi-layers types of data. */
+ prop = RNA_def_enum(ot->srna, "layers_select_src", DT_layers_select_src_items, DT_LAYERS_ACTIVE_SRC,
+ "Source Layers Selection", "Which layers to transfer, in case of multi-layers types");
+ RNA_def_property_enum_funcs_runtime(prop, NULL, NULL, dt_layers_select_src_itemf);
+
+ prop = RNA_def_enum(ot->srna, "layers_select_dst", DT_layers_select_dst_items, DT_LAYERS_ACTIVE_DST,
+ "Destination Layers Matching", "How to match source and destination layers");
+ RNA_def_property_enum_funcs_runtime(prop, NULL, NULL, dt_layers_select_dst_itemf);
+}
diff --git a/source/blender/editors/object/object_edit.c b/source/blender/editors/object/object_edit.c
index 93956128b84..c87eeaeb4a3 100644
--- a/source/blender/editors/object/object_edit.c
+++ b/source/blender/editors/object/object_edit.c
@@ -42,6 +42,8 @@
#include "BLI_utildefines.h"
#include "BLI_ghash.h"
+#include "BLT_translation.h"
+
#include "DNA_armature_types.h"
#include "DNA_curve_types.h"
#include "DNA_group_types.h"
@@ -63,7 +65,9 @@
#include "BKE_curve.h"
#include "BKE_effect.h"
#include "BKE_depsgraph.h"
+#include "BKE_global.h"
#include "BKE_image.h"
+#include "BKE_lattice.h"
#include "BKE_library.h"
#include "BKE_main.h"
#include "BKE_material.h"
@@ -315,7 +319,7 @@ void OBJECT_OT_hide_render_set(wmOperatorType *ot)
* Load EditMode data back into the object,
* optionally freeing the editmode data.
*/
-static bool ED_object_editmode_load_ex(Object *obedit, const bool freedata)
+static bool ED_object_editmode_load_ex(Main *bmain, Object *obedit, const bool freedata)
{
if (obedit == NULL) {
return false;
@@ -345,6 +349,11 @@ static bool ED_object_editmode_load_ex(Object *obedit, const bool freedata)
ED_armature_from_edit(obedit->data);
if (freedata)
ED_armature_edit_free(obedit->data);
+ /* TODO(sergey): Pose channels might have been changed, so need
+ * to inform dependency graph about this. But is it really the
+ * best place to do this?
+ */
+ DAG_relations_tag_update(bmain);
}
else if (ELEM(obedit->type, OB_CURVE, OB_SURF)) {
load_editNurb(obedit);
@@ -373,7 +382,8 @@ static bool ED_object_editmode_load_ex(Object *obedit, const bool freedata)
bool ED_object_editmode_load(Object *obedit)
{
- return ED_object_editmode_load_ex(obedit, false);
+ /* TODO(sergey): use proper main here? */
+ return ED_object_editmode_load_ex(G.main, obedit, false);
}
void ED_object_editmode_exit(bContext *C, int flag)
@@ -386,7 +396,7 @@ void ED_object_editmode_exit(bContext *C, int flag)
if (flag & EM_WAITCURSOR) waitcursor(1);
- if (ED_object_editmode_load_ex(obedit, freedata) == false) {
+ if (ED_object_editmode_load_ex(CTX_data_main(C), obedit, freedata) == false) {
/* in rare cases (background mode) its possible active object
* is flagged for editmode, without 'obedit' being set [#35489] */
if (UNLIKELY(scene->basact && (scene->basact->object->mode & OB_MODE_EDIT))) {
@@ -565,11 +575,11 @@ static int editmode_toggle_exec(bContext *C, wmOperator *op)
{
const int mode_flag = OB_MODE_EDIT;
const bool is_mode_set = (CTX_data_edit_object(C) != NULL);
- ToolSettings *toolsettings = CTX_data_tool_settings(C);
+ Scene *scene = CTX_data_scene(C);
if (!is_mode_set) {
- Scene *scene = CTX_data_scene(C);
- if (!ED_object_mode_compat_set(C, scene->basact->object, mode_flag, op->reports)) {
+ Object *ob = CTX_data_active_object(C);
+ if (!ED_object_mode_compat_set(C, ob, mode_flag, op->reports)) {
return OPERATOR_CANCELLED;
}
}
@@ -579,7 +589,7 @@ static int editmode_toggle_exec(bContext *C, wmOperator *op)
else
ED_object_editmode_exit(C, EM_FREEDATA | EM_FREEUNDO | EM_WAITCURSOR); /* had EM_DO_UNDO but op flag calls undo too [#24685] */
- ED_space_image_uv_sculpt_update(CTX_wm_manager(C), toolsettings);
+ ED_space_image_uv_sculpt_update(CTX_wm_manager(C), scene);
return OPERATOR_FINISHED;
}
@@ -895,6 +905,8 @@ static void copy_attr(Main *bmain, Scene *scene, View3D *v3d, short event)
base->object->rdamping = ob->rdamping;
base->object->min_vel = ob->min_vel;
base->object->max_vel = ob->max_vel;
+ base->object->min_angvel = ob->min_angvel;
+ base->object->max_angvel = ob->max_angvel;
if (ob->gameflag & OB_BOUNDS) {
base->object->collision_boundtype = ob->collision_boundtype;
}
@@ -1347,7 +1359,7 @@ static int shade_smooth_exec(bContext *C, wmOperator *op)
ID *data;
Curve *cu;
Nurb *nu;
- int clear = (strcmp(op->idname, "OBJECT_OT_shade_flat") == 0);
+ int clear = (STREQ(op->idname, "OBJECT_OT_shade_flat"));
bool done = false, linked_data = false;
CTX_DATA_BEGIN(C, Object *, ob, selected_editable_objects)
@@ -1701,7 +1713,7 @@ static int game_property_new_exec(bContext *C, wmOperator *op)
BLI_strncpy(prop->name, name, sizeof(prop->name));
}
- BKE_bproperty_unique(NULL, prop, 0); // make_unique_prop_names(prop->name);
+ BLI_uniquename(&ob->prop, prop, DATA_("Property"), '.', offsetof(bProperty, name), sizeof(prop->name));
WM_event_add_notifier(C, NC_LOGIC, NULL);
return OPERATOR_FINISHED;
@@ -1766,6 +1778,77 @@ void OBJECT_OT_game_property_remove(wmOperatorType *ot)
RNA_def_int(ot->srna, "index", 0, 0, INT_MAX, "Index", "Property index to remove ", 0, INT_MAX);
}
+#define GAME_PROPERTY_MOVE_UP 1
+#define GAME_PROPERTY_MOVE_DOWN -1
+
+static int game_property_move(bContext *C, wmOperator *op)
+{
+ Object *ob = CTX_data_active_object(C);
+ bProperty *prop;
+ bProperty *otherprop = NULL;
+ const int index = RNA_int_get(op->ptr, "index");
+ const int dir = RNA_enum_get(op->ptr, "direction");
+
+ if (ob == NULL)
+ return OPERATOR_CANCELLED;
+
+ prop = BLI_findlink(&ob->prop, index);
+ /* invalid index */
+ if (prop == NULL)
+ return OPERATOR_CANCELLED;
+
+ if (dir == GAME_PROPERTY_MOVE_UP) {
+ otherprop = prop->prev;
+ }
+ else if (dir == GAME_PROPERTY_MOVE_DOWN) {
+ otherprop = prop->next;
+ }
+ else {
+ BLI_assert(0);
+ }
+
+ if (prop && otherprop) {
+ BLI_listbase_swaplinks(&ob->prop, prop, otherprop);
+
+ WM_event_add_notifier(C, NC_LOGIC, NULL);
+ return OPERATOR_FINISHED;
+ }
+ else {
+ return OPERATOR_CANCELLED;
+ }
+}
+
+void OBJECT_OT_game_property_move(wmOperatorType *ot)
+{
+ static EnumPropertyItem direction_property_move[] = {
+ {GAME_PROPERTY_MOVE_UP, "UP", 0, "Up", ""},
+ {GAME_PROPERTY_MOVE_DOWN, "DOWN", 0, "Down", ""},
+ {0, NULL, 0, NULL, NULL}
+ };
+ PropertyRNA *prop;
+
+ /* identifiers */
+ ot->name = "Move Game Property";
+ ot->description = "Move game property";
+ ot->idname = "OBJECT_OT_game_property_move";
+
+ /* api callbacks */
+ ot->exec = game_property_move;
+ ot->poll = ED_operator_object_active_editable;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ prop = RNA_def_int(ot->srna, "index", 0, 0, INT_MAX, "Index", "Property index to move", 0, INT_MAX);
+ RNA_def_property_flag(prop, PROP_HIDDEN);
+ RNA_def_enum(ot->srna, "direction", direction_property_move, 0, "Direction",
+ "Direction for moving the property");
+}
+
+#undef GAME_PROPERTY_MOVE_UP
+#undef GAME_PROPERTY_MOVE_DOWN
+
#define COPY_PROPERTIES_REPLACE 1
#define COPY_PROPERTIES_MERGE 2
#define COPY_PROPERTIES_COPY 3
@@ -1963,6 +2046,8 @@ static int game_physics_copy_exec(bContext *C, wmOperator *UNUSED(op))
ob_iter->rdamping = ob->rdamping;
ob_iter->min_vel = ob->min_vel;
ob_iter->max_vel = ob->max_vel;
+ ob_iter->min_angvel = ob->min_angvel;
+ ob_iter->max_angvel = ob->max_angvel;
ob_iter->obstacleRad = ob->obstacleRad;
ob_iter->mass = ob->mass;
copy_v3_v3(ob_iter->anisotropicFriction, ob->anisotropicFriction);
@@ -1997,3 +2082,67 @@ void OBJECT_OT_game_physics_copy(struct wmOperatorType *ot)
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
+
+/* generic utility function */
+
+bool ED_object_editmode_calc_active_center(Object *obedit, const bool select_only, float r_center[3])
+{
+ switch (obedit->type) {
+ case OB_MESH:
+ {
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ BMEditSelection ese;
+
+ if (BM_select_history_active_get(em->bm, &ese)) {
+ BM_editselection_center(&ese, r_center);
+ return true;
+ }
+ break;
+ }
+ case OB_ARMATURE:
+ {
+ bArmature *arm = obedit->data;
+ EditBone *ebo = arm->act_edbone;
+
+ if (ebo && (!select_only || (ebo->flag & (BONE_SELECTED | BONE_ROOTSEL)))) {
+ copy_v3_v3(r_center, ebo->head);
+ return true;
+ }
+
+ break;
+ }
+ case OB_CURVE:
+ case OB_SURF:
+ {
+ Curve *cu = obedit->data;
+
+ if (ED_curve_active_center(cu, r_center)) {
+ return true;
+ }
+ break;
+ }
+ case OB_MBALL:
+ {
+ MetaBall *mb = obedit->data;
+ MetaElem *ml_act = mb->lastelem;
+
+ if (ml_act && (!select_only || (ml_act->flag & SELECT))) {
+ copy_v3_v3(r_center, &ml_act->x);
+ return true;
+ }
+ break;
+ }
+ case OB_LATTICE:
+ {
+ BPoint *actbp = BKE_lattice_active_point_get(obedit->data);
+
+ if (actbp) {
+ copy_v3_v3(r_center, actbp->vec);
+ return true;
+ }
+ break;
+ }
+ }
+
+ return false;
+}
diff --git a/source/blender/editors/object/object_group.c b/source/blender/editors/object/object_group.c
index 20e2e22cdf8..3c43f2729bd 100644
--- a/source/blender/editors/object/object_group.c
+++ b/source/blender/editors/object/object_group.c
@@ -61,47 +61,6 @@
/********************* 3d view operators ***********************/
-static bool group_link_early_exit_check(Group *group, Object *object)
-{
- GroupObject *group_object;
-
- for (group_object = group->gobject.first; group_object; group_object = group_object->next) {
- if (group_object->ob == object) {
- return true;
- }
- }
-
- return false;
-}
-
-static bool check_object_instances_group_recursive(Object *object, Group *group)
-{
- if (object->dup_group) {
- Group *dup_group = object->dup_group;
- if ((dup_group->id.flag & LIB_DOIT) == 0) {
- /* Cycle already exists in groups, let's prevent further crappyness */
- return true;
- }
- /* flag the object to identify cyclic dependencies in further dupli groups */
- dup_group->id.flag &= ~LIB_DOIT;
-
- if (dup_group == group)
- return true;
- else {
- GroupObject *gob;
- for (gob = dup_group->gobject.first; gob; gob = gob->next) {
- if (check_object_instances_group_recursive(gob->ob, group))
- return true;
- }
- }
-
- /* un-flag the object, it's allowed to have the same group multiple times in parallel */
- dup_group->id.flag |= LIB_DOIT;
- }
-
- return false;
-}
-
/* can be called with C == NULL */
static EnumPropertyItem *group_object_active_itemf(bContext *C, PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), bool *r_free)
{
@@ -185,15 +144,12 @@ static int objects_add_active_exec(bContext *C, wmOperator *op)
if (!BKE_group_object_exists(group, ob))
continue;
- /* for recursive check */
- BKE_main_id_tag_listbase(&bmain->group, true);
-
CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases)
{
- if (group_link_early_exit_check(group, base->object))
+ if (BKE_group_object_exists(group, base->object))
continue;
- if (!check_object_instances_group_recursive(base->object, group)) {
+ if (!BKE_group_object_cyclic_check(bmain, base->object, group)) {
BKE_group_object_add(group, base->object, scene, base);
updated = true;
}
@@ -486,7 +442,7 @@ static int group_link_exec(bContext *C, wmOperator *op)
* we could sckip all the dependency check and just consider
* operator is finished.
*/
- if (group_link_early_exit_check(group, ob)) {
+ if (BKE_group_object_exists(group, ob)) {
return OPERATOR_FINISHED;
}
@@ -495,8 +451,7 @@ static int group_link_exec(bContext *C, wmOperator *op)
* It is also bad idea to add object to group which is in group which
* contains our current object.
*/
- BKE_main_id_tag_listbase(&bmain->group, true);
- if (check_object_instances_group_recursive(ob, group)) {
+ if (BKE_group_object_cyclic_check(bmain, ob, group)) {
BKE_report(op->reports, RPT_ERROR, "Could not add the group because of dependency cycle detected");
return OPERATOR_CANCELLED;
}
diff --git a/source/blender/editors/object/object_hook.c b/source/blender/editors/object/object_hook.c
index 9f9a647c9f1..7b7f91b974d 100644
--- a/source/blender/editors/object/object_hook.c
+++ b/source/blender/editors/object/object_hook.c
@@ -254,7 +254,7 @@ static int return_editcurve_indexar(
}
if (totvert == 0) return 0;
- *r_indexar = index = MEM_mallocN(4 * totvert, "hook indexar");
+ *r_indexar = index = MEM_mallocN(sizeof(*index) * totvert, "hook indexar");
*r_tot = totvert;
nr = 0;
zero_v3(r_cent);
@@ -448,11 +448,12 @@ static Object *add_hook_object_new(Main *bmain, Scene *scene, Object *obedit)
Base *base, *basedit;
Object *ob;
- ob = BKE_object_add(bmain, scene, OB_EMPTY);
+ ob = BKE_object_add(bmain, scene, OB_EMPTY, NULL);
basedit = BKE_scene_base_find(scene, obedit);
- base = BKE_scene_base_find(scene, ob);
+ base = scene->basact;
base->lay = ob->lay = obedit->lay;
+ BLI_assert(scene->basact->object == ob);
/* icky, BKE_object_add sets new base as active.
* so set it back to the original edit object */
@@ -503,6 +504,15 @@ static int add_hook_object(Main *bmain, Scene *scene, Object *obedit, Object *ob
unit_m4(pose_mat);
+ invert_m4_m4(obedit->imat, obedit->obmat);
+ if (mode == OBJECT_ADDHOOK_NEWOB) {
+ /* pass */
+ }
+ else {
+ /* may overwrite with pose-bone location, below */
+ mul_v3_m4v3(cent, obedit->imat, ob->obmat[3]);
+ }
+
if (mode == OBJECT_ADDHOOK_SELOB_BONE) {
bArmature *arm = ob->data;
BLI_assert(ob->type == OB_ARMATURE);
@@ -514,6 +524,8 @@ static int add_hook_object(Main *bmain, Scene *scene, Object *obedit, Object *ob
pchan_act = BKE_pose_channel_active(ob);
if (LIKELY(pchan_act)) {
invert_m4_m4(pose_mat, pchan_act->pose_mat);
+ mul_v3_m4v3(cent, ob->obmat, pchan_act->pose_mat[3]);
+ mul_v3_m4v3(cent, obedit->imat, cent);
}
}
else {
@@ -521,6 +533,9 @@ static int add_hook_object(Main *bmain, Scene *scene, Object *obedit, Object *ob
}
}
+ copy_v3_v3(hmd->cent, cent);
+
+
/* matrix calculus */
/* vert x (obmat x hook->imat) x hook->obmat x ob->imat */
/* (parentinv ) */
diff --git a/source/blender/editors/object/object_intern.h b/source/blender/editors/object/object_intern.h
index 6fa3caa6172..6344e04ef1b 100644
--- a/source/blender/editors/object/object_intern.h
+++ b/source/blender/editors/object/object_intern.h
@@ -32,12 +32,12 @@
#define __OBJECT_INTERN_H__
struct wmOperatorType;
-struct KeyBlock;
-struct Lattice;
-struct Curve;
struct Object;
-struct Mesh;
-struct HookModifierData;
+struct bContext;
+struct StructRNA;
+struct wmOperator;
+
+struct ModifierData;
/* add hook menu */
enum eObject_Hook_Add_Mode {
@@ -94,6 +94,7 @@ void OBJECT_OT_game_property_new(struct wmOperatorType *ot);
void OBJECT_OT_game_property_remove(struct wmOperatorType *ot);
void OBJECT_OT_game_property_copy(struct wmOperatorType *ot);
void OBJECT_OT_game_property_clear(struct wmOperatorType *ot);
+void OBJECT_OT_game_property_move(struct wmOperatorType *ot);
void OBJECT_OT_logic_bricks_copy(struct wmOperatorType *ot);
void OBJECT_OT_game_physics_copy(struct wmOperatorType *ot);
@@ -155,6 +156,12 @@ void GROUP_OT_objects_add_active(struct wmOperatorType *ot);
void GROUP_OT_objects_remove_active(struct wmOperatorType *ot);
/* object_modifier.c */
+int edit_modifier_poll_generic(struct bContext *C, struct StructRNA *rna_type, int obtype_flag);
+int edit_modifier_poll(struct bContext *C);
+void edit_modifier_properties(struct wmOperatorType *ot);
+int edit_modifier_invoke_properties(struct bContext *C, struct wmOperator *op);
+struct ModifierData *edit_modifier_property_get(struct wmOperator *op, struct Object *ob, int type);
+
void OBJECT_OT_modifier_add(struct wmOperatorType *ot);
void OBJECT_OT_modifier_remove(struct wmOperatorType *ot);
void OBJECT_OT_modifier_move_up(struct wmOperatorType *ot);
@@ -168,6 +175,7 @@ void OBJECT_OT_multires_higher_levels_delete(struct wmOperatorType *ot);
void OBJECT_OT_multires_base_apply(struct wmOperatorType *ot);
void OBJECT_OT_multires_external_save(struct wmOperatorType *ot);
void OBJECT_OT_multires_external_pack(struct wmOperatorType *ot);
+void OBJECT_OT_correctivesmooth_bind(struct wmOperatorType *ot);
void OBJECT_OT_meshdeform_bind(struct wmOperatorType *ot);
void OBJECT_OT_explode_refresh(struct wmOperatorType *ot);
void OBJECT_OT_ocean_bake(struct wmOperatorType *ot);
@@ -214,7 +222,6 @@ void OBJECT_OT_vertex_group_remove_from(struct wmOperatorType *ot);
void OBJECT_OT_vertex_group_select(struct wmOperatorType *ot);
void OBJECT_OT_vertex_group_deselect(struct wmOperatorType *ot);
void OBJECT_OT_vertex_group_copy_to_linked(struct wmOperatorType *ot);
-void OBJECT_OT_vertex_group_transfer_weight(struct wmOperatorType *ot);
void OBJECT_OT_vertex_group_copy_to_selected(struct wmOperatorType *ot);
void OBJECT_OT_vertex_group_copy(struct wmOperatorType *ot);
void OBJECT_OT_vertex_group_normalize(struct wmOperatorType *ot);
@@ -223,7 +230,7 @@ void OBJECT_OT_vertex_group_levels(struct wmOperatorType *ot);
void OBJECT_OT_vertex_group_lock(struct wmOperatorType *ot);
void OBJECT_OT_vertex_group_fix(struct wmOperatorType *ot);
void OBJECT_OT_vertex_group_invert(struct wmOperatorType *ot);
-void OBJECT_OT_vertex_group_blend(struct wmOperatorType *ot);
+void OBJECT_OT_vertex_group_smooth(struct wmOperatorType *ot);
void OBJECT_OT_vertex_group_clean(struct wmOperatorType *ot);
void OBJECT_OT_vertex_group_quantize(struct wmOperatorType *ot);
void OBJECT_OT_vertex_group_limit_total(struct wmOperatorType *ot);
@@ -238,7 +245,7 @@ void OBJECT_OT_vertex_weight_normalize_active_vertex(struct wmOperatorType *ot);
void OBJECT_OT_vertex_weight_copy(struct wmOperatorType *ot);
/* object_warp.c */
-void OBJECT_OT_vertex_warp(struct wmOperatorType *ot);
+void TRANSFORM_OT_vertex_warp(struct wmOperatorType *ot);
/* object_shapekey.c */
void OBJECT_OT_shape_key_add(struct wmOperatorType *ot);
@@ -264,7 +271,11 @@ void OBJECT_OT_lod_add(struct wmOperatorType *ot);
void OBJECT_OT_lod_remove(struct wmOperatorType *ot);
/* object_random.c */
-void OBJECT_OT_vertex_random(struct wmOperatorType *ot);
+void TRANSFORM_OT_vertex_random(struct wmOperatorType *ot);
+
+/* object_transfer_data.c */
+void OBJECT_OT_data_transfer(struct wmOperatorType *ot);
+void OBJECT_OT_datalayout_transfer(struct wmOperatorType *ot);
#endif /* __OBJECT_INTERN_H__ */
diff --git a/source/blender/editors/object/object_lattice.c b/source/blender/editors/object/object_lattice.c
index c24a127ed8b..76d9facf701 100644
--- a/source/blender/editors/object/object_lattice.c
+++ b/source/blender/editors/object/object_lattice.c
@@ -100,7 +100,7 @@ void make_editLatt(Object *obedit)
actkey = BKE_keyblock_from_object(obedit);
if (actkey)
- BKE_key_convert_to_lattice(actkey, lt);
+ BKE_keyblock_convert_to_lattice(actkey, lt);
lt->editlatt = MEM_callocN(sizeof(EditLatt), "editlatt");
lt->editlatt->latt = MEM_dupallocN(lt);
@@ -713,7 +713,7 @@ static int lattice_flip_exec(bContext *C, wmOperator *op)
break;
default:
- printf("lattice_flip(): Unknown flipping axis (%d)\n", axis);
+ printf("lattice_flip(): Unknown flipping axis (%u)\n", axis);
return OPERATOR_CANCELLED;
}
diff --git a/source/blender/editors/object/object_lod.c b/source/blender/editors/object/object_lod.c
index 48e980015a7..ced306178b8 100644
--- a/source/blender/editors/object/object_lod.c
+++ b/source/blender/editors/object/object_lod.c
@@ -32,18 +32,22 @@
#include "DNA_object_types.h"
#include "BKE_context.h"
-#include "BKE_object.h"
#include "WM_api.h"
#include "WM_types.h"
#include "RNA_access.h"
#include "RNA_define.h"
-#include "RNA_enum_types.h"
#include "ED_screen.h"
#include "ED_object.h"
+#ifdef WITH_GAMEENGINE
+# include "BKE_object.h"
+
+# include "RNA_enum_types.h"
+#endif
+
#include "object_intern.h"
static int object_lod_add_exec(bContext *C, wmOperator *UNUSED(op))
diff --git a/source/blender/editors/object/object_modifier.c b/source/blender/editors/object/object_modifier.c
index b05840b5823..8ef2bd1b2af 100644
--- a/source/blender/editors/object/object_modifier.c
+++ b/source/blender/editors/object/object_modifier.c
@@ -68,6 +68,7 @@
#include "BKE_multires.h"
#include "BKE_report.h"
#include "BKE_object.h"
+#include "BKE_object_deform.h"
#include "BKE_ocean.h"
#include "BKE_paint.h"
#include "BKE_particle.h"
@@ -95,7 +96,7 @@ static void modifier_skin_customdata_delete(struct Object *ob);
ModifierData *ED_object_modifier_add(ReportList *reports, Main *bmain, Scene *scene, Object *ob, const char *name, int type)
{
ModifierData *md = NULL, *new_md = NULL;
- ModifierTypeInfo *mti = modifierType_getInfo(type);
+ const ModifierTypeInfo *mti = modifierType_getInfo(type);
/* only geometry objects should be able to get modifiers [#25291] */
if (!ELEM(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_LATTICE)) {
@@ -151,10 +152,10 @@ ModifierData *ED_object_modifier_add(ReportList *reports, Main *bmain, Scene *sc
ob->pd = object_add_collision_fields(0);
ob->pd->deflect = 1;
- DAG_relations_tag_update(bmain);
}
- else if (type == eModifierType_Surface)
- DAG_relations_tag_update(bmain);
+ else if (type == eModifierType_Surface) {
+ /* pass */
+ }
else if (type == eModifierType_Multires) {
/* set totlvl from existing MDISPS layer if object already had it */
multiresModifier_set_levels_from_disps((MultiresModifierData *)new_md, ob);
@@ -171,6 +172,7 @@ ModifierData *ED_object_modifier_add(ReportList *reports, Main *bmain, Scene *sc
}
DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ DAG_relations_tag_update(bmain);
return new_md;
}
@@ -246,7 +248,7 @@ static bool object_has_modifier_cb(Object *ob, void *data)
bool ED_object_multires_update_totlevels_cb(Object *ob, void *totlevel_v)
{
ModifierData *md;
- int totlevel = *((int *)totlevel_v);
+ int totlevel = *((char *)totlevel_v);
for (md = ob->modifiers.first; md; md = md->next) {
if (md->type == eModifierType_Multires) {
@@ -318,6 +320,8 @@ static bool object_modifier_remove(Main *bmain, Object *ob, ModifierData *md,
ob->mode &= ~OB_MODE_PARTICLE_EDIT;
}
+ DAG_relations_tag_update(bmain);
+
BLI_remlink(&ob->modifiers, md);
modifier_free(md);
@@ -367,10 +371,10 @@ void ED_object_modifier_clear(Main *bmain, Object *ob)
int ED_object_modifier_move_up(ReportList *reports, Object *ob, ModifierData *md)
{
if (md->prev) {
- ModifierTypeInfo *mti = modifierType_getInfo(md->type);
+ const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
if (mti->type != eModifierTypeType_OnlyDeform) {
- ModifierTypeInfo *nmti = modifierType_getInfo(md->prev->type);
+ const ModifierTypeInfo *nmti = modifierType_getInfo(md->prev->type);
if (nmti->flags & eModifierTypeFlag_RequiresOriginalData) {
BKE_report(reports, RPT_WARNING, "Cannot move above a modifier requiring original data");
@@ -388,10 +392,10 @@ int ED_object_modifier_move_up(ReportList *reports, Object *ob, ModifierData *md
int ED_object_modifier_move_down(ReportList *reports, Object *ob, ModifierData *md)
{
if (md->next) {
- ModifierTypeInfo *mti = modifierType_getInfo(md->type);
+ const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
if (mti->flags & eModifierTypeFlag_RequiresOriginalData) {
- ModifierTypeInfo *nmti = modifierType_getInfo(md->next->type);
+ const ModifierTypeInfo *nmti = modifierType_getInfo(md->next->type);
if (nmti->type != eModifierTypeType_OnlyDeform) {
BKE_report(reports, RPT_WARNING, "Cannot move beyond a non-deforming modifier");
@@ -439,9 +443,9 @@ int ED_object_modifier_convert(ReportList *UNUSED(reports), Main *bmain, Scene *
for (a = 0; a < totpart; a++) {
key = cache[a];
- if (key->steps > 0) {
- totvert += key->steps + 1;
- totedge += key->steps;
+ if (key->segments > 0) {
+ totvert += key->segments + 1;
+ totedge += key->segments;
}
}
@@ -449,16 +453,16 @@ int ED_object_modifier_convert(ReportList *UNUSED(reports), Main *bmain, Scene *
for (a = 0; a < totchild; a++) {
key = cache[a];
- if (key->steps > 0) {
- totvert += key->steps + 1;
- totedge += key->steps;
+ if (key->segments > 0) {
+ totvert += key->segments + 1;
+ totedge += key->segments;
}
}
if (totvert == 0) return 0;
/* add new mesh */
- obn = BKE_object_add(bmain, scene, OB_MESH);
+ obn = BKE_object_add(bmain, scene, OB_MESH, NULL);
me = obn->data;
me->totvert = totvert;
@@ -475,7 +479,7 @@ int ED_object_modifier_convert(ReportList *UNUSED(reports), Main *bmain, Scene *
cache = psys->pathcache;
for (a = 0; a < totpart; a++) {
key = cache[a];
- kmax = key->steps;
+ kmax = key->segments;
for (k = 0; k <= kmax; k++, key++, cvert++, mvert++) {
copy_v3_v3(mvert->co, key->co);
if (k) {
@@ -494,7 +498,7 @@ int ED_object_modifier_convert(ReportList *UNUSED(reports), Main *bmain, Scene *
cache = psys->childcache;
for (a = 0; a < totchild; a++) {
key = cache[a];
- kmax = key->steps;
+ kmax = key->segments;
for (k = 0; k <= kmax; k++, key++, cvert++, mvert++) {
copy_v3_v3(mvert->co, key->co);
if (k) {
@@ -517,7 +521,7 @@ int ED_object_modifier_convert(ReportList *UNUSED(reports), Main *bmain, Scene *
static int modifier_apply_shape(ReportList *reports, Scene *scene, Object *ob, ModifierData *md)
{
- ModifierTypeInfo *mti = modifierType_getInfo(md->type);
+ const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
md->scene = scene;
@@ -560,7 +564,7 @@ static int modifier_apply_shape(ReportList *reports, Scene *scene, Object *ob, M
/* if that was the first key block added, then it was the basis.
* Initialize it with the mesh, and add another for the modifier */
kb = BKE_keyblock_add(key, NULL);
- BKE_key_convert_from_mesh(me, kb);
+ BKE_keyblock_convert_from_mesh(me, kb);
}
kb = BKE_keyblock_add(key, md->name);
@@ -577,7 +581,7 @@ static int modifier_apply_shape(ReportList *reports, Scene *scene, Object *ob, M
static int modifier_apply_obdata(ReportList *reports, Scene *scene, Object *ob, ModifierData *md)
{
- ModifierTypeInfo *mti = modifierType_getInfo(md->type);
+ const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
md->scene = scene;
@@ -613,9 +617,7 @@ static int modifier_apply_obdata(ReportList *reports, Scene *scene, Object *ob,
return 0;
}
- DM_to_mesh(dm, me, ob, CD_MASK_MESH);
-
- dm->release(dm);
+ DM_to_mesh(dm, me, ob, CD_MASK_MESH, true);
if (md->type == eModifierType_Multires)
multires_customdata_delete(me);
@@ -743,7 +745,7 @@ static EnumPropertyItem *modifier_add_itemf(bContext *C, PointerRNA *UNUSED(ptr)
{
Object *ob = ED_object_active_context(C);
EnumPropertyItem *item = NULL, *md_item, *group_item = NULL;
- ModifierTypeInfo *mti;
+ const ModifierTypeInfo *mti;
int totitem = 0, a;
if (!ob)
@@ -807,7 +809,7 @@ void OBJECT_OT_modifier_add(wmOperatorType *ot)
/************************ generic functions for operators using mod names and data context *********************/
-static int edit_modifier_poll_generic(bContext *C, StructRNA *rna_type, int obtype_flag)
+int edit_modifier_poll_generic(bContext *C, StructRNA *rna_type, int obtype_flag)
{
PointerRNA ptr = CTX_data_pointer_get_type(C, "modifier", rna_type);
Object *ob = (ptr.id.data) ? ptr.id.data : ED_object_active_context(C);
@@ -819,17 +821,17 @@ static int edit_modifier_poll_generic(bContext *C, StructRNA *rna_type, int obty
return 1;
}
-static int edit_modifier_poll(bContext *C)
+int edit_modifier_poll(bContext *C)
{
return edit_modifier_poll_generic(C, &RNA_Modifier, 0);
}
-static void edit_modifier_properties(wmOperatorType *ot)
+void edit_modifier_properties(wmOperatorType *ot)
{
RNA_def_string(ot->srna, "modifier", NULL, MAX_NAME, "Modifier", "Name of the modifier to edit");
}
-static int edit_modifier_invoke_properties(bContext *C, wmOperator *op)
+int edit_modifier_invoke_properties(bContext *C, wmOperator *op)
{
ModifierData *md;
@@ -848,7 +850,7 @@ static int edit_modifier_invoke_properties(bContext *C, wmOperator *op)
return false;
}
-static ModifierData *edit_modifier_property_get(wmOperator *op, Object *ob, int type)
+ModifierData *edit_modifier_property_get(wmOperator *op, Object *ob, int type)
{
char modifier_name[MAX_NAME];
ModifierData *md;
@@ -1353,8 +1355,8 @@ void OBJECT_OT_multires_external_save(wmOperatorType *ot)
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
- WM_operator_properties_filesel(ot, FOLDERFILE | BTXFILE, FILE_SPECIAL, FILE_SAVE,
- WM_FILESEL_FILEPATH | WM_FILESEL_RELPATH, FILE_DEFAULTDISPLAY);
+ WM_operator_properties_filesel(ot, FILE_TYPE_FOLDER | FILE_TYPE_BTX, FILE_SPECIAL, FILE_SAVE,
+ WM_FILESEL_FILEPATH | WM_FILESEL_RELPATH, FILE_DEFAULTDISPLAY, FILE_SORT_ALPHA);
edit_modifier_properties(ot);
}
@@ -1667,7 +1669,7 @@ static void skin_armature_bone_create(Object *skin_ob,
BLI_snprintf(bone->name, sizeof(bone->name), "Bone.%.2d", endx);
/* add bDeformGroup */
- if ((dg = ED_vgroup_add_name(skin_ob, bone->name))) {
+ if ((dg = BKE_object_defgroup_add_name(skin_ob, bone->name))) {
ED_vgroup_vert_add(skin_ob, dg, parent_v, 1, WEIGHT_REPLACE);
ED_vgroup_vert_add(skin_ob, dg, v, 1, WEIGHT_REPLACE);
}
@@ -1705,7 +1707,7 @@ static Object *modifier_skin_armature_create(Main *bmain, Scene *scene, Object *
NULL,
me->totvert);
- arm_ob = BKE_object_add(bmain, scene, OB_ARMATURE);
+ arm_ob = BKE_object_add(bmain, scene, OB_ARMATURE, NULL);
BKE_object_transform_copy(arm_ob, skin_ob);
arm = arm_ob->data;
arm->layer = 1;
@@ -1816,6 +1818,73 @@ void OBJECT_OT_skin_armature_create(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
edit_modifier_properties(ot);
}
+/************************ delta mush bind operator *********************/
+
+static int correctivesmooth_poll(bContext *C)
+{
+ return edit_modifier_poll_generic(C, &RNA_CorrectiveSmoothModifier, 0);
+}
+
+static int correctivesmooth_bind_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene = CTX_data_scene(C);
+ Object *ob = ED_object_active_context(C);
+ CorrectiveSmoothModifierData *csmd = (CorrectiveSmoothModifierData *)edit_modifier_property_get(op, ob, eModifierType_CorrectiveSmooth);
+ bool is_bind;
+
+ if (!csmd) {
+ return OPERATOR_CANCELLED;
+ }
+
+ if (!modifier_isEnabled(scene, &csmd->modifier, eModifierMode_Realtime)) {
+ BKE_report(op->reports, RPT_ERROR, "Modifier is disabled");
+ return OPERATOR_CANCELLED;
+ }
+
+ is_bind = (csmd->bind_coords != NULL);
+
+ MEM_SAFE_FREE(csmd->bind_coords);
+ MEM_SAFE_FREE(csmd->delta_cache);
+
+ if (is_bind) {
+ /* toggle off */
+ csmd->bind_coords_num = 0;
+ }
+ else {
+ /* signal to modifier to recalculate */
+ csmd->bind_coords_num = (unsigned int)-1;
+ }
+
+ DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
+
+ return OPERATOR_FINISHED;
+}
+
+static int correctivesmooth_bind_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
+{
+ if (edit_modifier_invoke_properties(C, op))
+ return correctivesmooth_bind_exec(C, op);
+ else
+ return OPERATOR_CANCELLED;
+}
+
+void OBJECT_OT_correctivesmooth_bind(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Corrective Smooth Bind";
+ ot->description = "Bind base pose in Corrective Smooth modifier";
+ ot->idname = "OBJECT_OT_correctivesmooth_bind";
+
+ /* api callbacks */
+ ot->poll = correctivesmooth_poll;
+ ot->invoke = correctivesmooth_bind_invoke;
+ ot->exec = correctivesmooth_bind_exec;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
+ edit_modifier_properties(ot);
+}
/************************ mdef bind operator *********************/
@@ -1979,7 +2048,7 @@ static void init_ocean_modifier_bake(struct Ocean *oc, struct OceanModifierData
do_normals = (omd->flag & MOD_OCEAN_GENERATE_NORMALS);
do_jacobian = (omd->flag & MOD_OCEAN_GENERATE_FOAM);
- BKE_init_ocean(oc, omd->resolution * omd->resolution, omd->resolution * omd->resolution, omd->spatial_size, omd->spatial_size,
+ BKE_ocean_init(oc, omd->resolution * omd->resolution, omd->resolution * omd->resolution, omd->spatial_size, omd->spatial_size,
omd->wind_velocity, omd->smallest_wave, 1.0, omd->wave_direction, omd->damp, omd->wave_alignment,
omd->depth, omd->time,
do_heightfield, do_chop, do_normals, do_jacobian,
@@ -2037,7 +2106,7 @@ static void oceanbake_startjob(void *customdata, short *stop, short *do_update,
G.is_break = false; /* XXX shared with render - replace with job 'stop' switch */
- BKE_bake_ocean(oj->ocean, oj->och, oceanbake_update, (void *)oj);
+ BKE_ocean_bake(oj->ocean, oj->och, oceanbake_update, (void *)oj);
*do_update = true;
*stop = 0;
@@ -2048,7 +2117,7 @@ static void oceanbake_endjob(void *customdata)
OceanBakeJob *oj = customdata;
if (oj->ocean) {
- BKE_free_ocean(oj->ocean);
+ BKE_ocean_free(oj->ocean);
oj->ocean = NULL;
}
@@ -2079,7 +2148,7 @@ static int ocean_bake_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
- och = BKE_init_ocean_cache(omd->cachepath, modifier_path_relbase(ob),
+ och = BKE_ocean_init_cache(omd->cachepath, modifier_path_relbase(ob),
omd->bakestart, omd->bakeend, omd->wave_scale,
omd->chop_amount, omd->foam_coverage, omd->foam_fade, omd->resolution);
@@ -2113,11 +2182,11 @@ static int ocean_bake_exec(bContext *C, wmOperator *op)
}
/* make a copy of ocean to use for baking - threadsafety */
- ocean = BKE_add_ocean();
+ ocean = BKE_ocean_add();
init_ocean_modifier_bake(ocean, omd);
#if 0
- BKE_bake_ocean(ocean, och);
+ BKE_ocean_bake(ocean, och);
omd->oceancache = och;
omd->cached = true;
diff --git a/source/blender/editors/object/object_ops.c b/source/blender/editors/object/object_ops.c
index 7cf661de52c..22cac8638d9 100644
--- a/source/blender/editors/object/object_ops.c
+++ b/source/blender/editors/object/object_ops.c
@@ -40,7 +40,6 @@
#include "BKE_context.h"
#include "RNA_access.h"
-#include "RNA_define.h"
#include "WM_api.h"
#include "WM_types.h"
@@ -145,6 +144,7 @@ void ED_operatortypes_object(void)
WM_operatortype_append(OBJECT_OT_skin_radii_equalize);
WM_operatortype_append(OBJECT_OT_skin_armature_create);
+ WM_operatortype_append(OBJECT_OT_correctivesmooth_bind);
WM_operatortype_append(OBJECT_OT_meshdeform_bind);
WM_operatortype_append(OBJECT_OT_explode_refresh);
WM_operatortype_append(OBJECT_OT_ocean_bake);
@@ -178,7 +178,6 @@ void ED_operatortypes_object(void)
WM_operatortype_append(OBJECT_OT_vertex_group_select);
WM_operatortype_append(OBJECT_OT_vertex_group_deselect);
WM_operatortype_append(OBJECT_OT_vertex_group_copy_to_linked);
- WM_operatortype_append(OBJECT_OT_vertex_group_transfer_weight);
WM_operatortype_append(OBJECT_OT_vertex_group_copy_to_selected);
WM_operatortype_append(OBJECT_OT_vertex_group_copy);
WM_operatortype_append(OBJECT_OT_vertex_group_normalize);
@@ -187,7 +186,7 @@ void ED_operatortypes_object(void)
WM_operatortype_append(OBJECT_OT_vertex_group_fix);
WM_operatortype_append(OBJECT_OT_vertex_group_invert);
WM_operatortype_append(OBJECT_OT_vertex_group_levels);
- WM_operatortype_append(OBJECT_OT_vertex_group_blend);
+ WM_operatortype_append(OBJECT_OT_vertex_group_smooth);
WM_operatortype_append(OBJECT_OT_vertex_group_clean);
WM_operatortype_append(OBJECT_OT_vertex_group_quantize);
WM_operatortype_append(OBJECT_OT_vertex_group_limit_total);
@@ -201,12 +200,13 @@ void ED_operatortypes_object(void)
WM_operatortype_append(OBJECT_OT_vertex_weight_normalize_active_vertex);
WM_operatortype_append(OBJECT_OT_vertex_weight_copy);
- WM_operatortype_append(OBJECT_OT_vertex_warp);
+ WM_operatortype_append(TRANSFORM_OT_vertex_warp);
WM_operatortype_append(OBJECT_OT_game_property_new);
WM_operatortype_append(OBJECT_OT_game_property_remove);
WM_operatortype_append(OBJECT_OT_game_property_copy);
WM_operatortype_append(OBJECT_OT_game_property_clear);
+ WM_operatortype_append(OBJECT_OT_game_property_move);
WM_operatortype_append(OBJECT_OT_logic_bricks_copy);
WM_operatortype_append(OBJECT_OT_game_physics_copy);
@@ -249,7 +249,10 @@ void ED_operatortypes_object(void)
WM_operatortype_append(OBJECT_OT_lod_add);
WM_operatortype_append(OBJECT_OT_lod_remove);
- WM_operatortype_append(OBJECT_OT_vertex_random);
+ WM_operatortype_append(TRANSFORM_OT_vertex_random);
+
+ WM_operatortype_append(OBJECT_OT_data_transfer);
+ WM_operatortype_append(OBJECT_OT_datalayout_transfer);
}
void ED_operatormacros_object(void)
@@ -320,6 +323,7 @@ void ED_keymap_object(wmKeyConfig *keyconf)
ED_keymap_proportional_cycle(keyconf, keymap);
ED_keymap_proportional_obmode(keyconf, keymap);
+ /* game-engine only, leave free for users to define */
WM_keymap_add_item(keymap, "VIEW3D_OT_game_start", PKEY, KM_PRESS, 0, 0);
kmi = WM_keymap_add_item(keymap, "OBJECT_OT_select_all", AKEY, KM_PRESS, 0, 0);
@@ -420,6 +424,10 @@ void ED_keymap_object(wmKeyConfig *keyconf)
WM_keymap_add_menu(keymap, "VIEW3D_MT_object_specials", WKEY, KM_PRESS, 0, 0);
+ WM_keymap_verify_item(keymap, "OBJECT_OT_data_transfer", TKEY, KM_PRESS, KM_SHIFT | KM_CTRL, 0);
+ /* XXX No more available 'T' shortcuts... :/ */
+ /* WM_keymap_verify_item(keymap, "OBJECT_OT_datalayout_transfer", TKEY, KM_PRESS, KM_SHIFT | KM_CTRL, 0); */
+
for (i = 0; i <= 5; i++) {
kmi = WM_keymap_add_item(keymap, "OBJECT_OT_subdivision_set", ZEROKEY + i, KM_PRESS, KM_CTRL, 0);
RNA_int_set(kmi->ptr, "level", i);
diff --git a/source/blender/editors/object/object_random.c b/source/blender/editors/object/object_random.c
index 41b26b98047..a293f7a950e 100644
--- a/source/blender/editors/object/object_random.c
+++ b/source/blender/editors/object/object_random.c
@@ -124,12 +124,12 @@ static int object_rand_verts_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
-void OBJECT_OT_vertex_random(struct wmOperatorType *ot)
+void TRANSFORM_OT_vertex_random(struct wmOperatorType *ot)
{
/* identifiers */
ot->name = "Randomize";
ot->description = "Randomize vertices";
- ot->idname = "OBJECT_OT_vertex_random";
+ ot->idname = "TRANSFORM_OT_vertex_random";
/* api callbacks */
ot->exec = object_rand_verts_exec;
diff --git a/source/blender/editors/object/object_relations.c b/source/blender/editors/object/object_relations.c
index 0d58eaee5fa..e21f58d8a38 100644
--- a/source/blender/editors/object/object_relations.c
+++ b/source/blender/editors/object/object_relations.c
@@ -56,7 +56,7 @@
#include "BLI_kdtree.h"
#include "BLI_utildefines.h"
-#include "BLF_translation.h"
+#include "BLT_translation.h"
#include "BKE_action.h"
#include "BKE_animsys.h"
@@ -128,9 +128,9 @@ static int vertex_parent_set_exec(bContext *C, wmOperator *op)
BPoint *bp;
Object *par;
int a, v1 = 0, v2 = 0, v3 = 0, v4 = 0, nr = 1;
-
+
/* we need 1 to 3 selected vertices */
-
+
if (obedit->type == OB_MESH) {
Mesh *me = obedit->data;
BMEditMesh *em;
@@ -145,7 +145,7 @@ static int vertex_parent_set_exec(bContext *C, wmOperator *op)
/* derivedMesh might be needed for solving parenting,
* so re-create it here */
- makeDerivedMesh(scene, obedit, em, CD_MASK_BAREMESH | CD_MASK_ORIGINDEX, 0);
+ makeDerivedMesh(scene, obedit, em, CD_MASK_BAREMESH | CD_MASK_ORIGINDEX, false);
BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
if (BM_elem_flag_test(eve, BM_ELEM_SELECT)) {
@@ -160,7 +160,7 @@ static int vertex_parent_set_exec(bContext *C, wmOperator *op)
}
else if (ELEM(obedit->type, OB_SURF, OB_CURVE)) {
ListBase *editnurb = object_editcurve_get(obedit);
-
+
cu = obedit->data;
nu = editnurb->first;
@@ -169,7 +169,7 @@ static int vertex_parent_set_exec(bContext *C, wmOperator *op)
bezt = nu->bezt;
a = nu->pntsu;
while (a--) {
- if (BEZSELECTED_HIDDENHANDLES(cu, bezt)) {
+ if (BEZT_ISSEL_ANY_HIDDENHANDLES(cu, bezt)) {
if (v1 == 0) v1 = nr;
else if (v2 == 0) v2 = nr;
else if (v3 == 0) v3 = nr;
@@ -200,7 +200,7 @@ static int vertex_parent_set_exec(bContext *C, wmOperator *op)
}
else if (obedit->type == OB_LATTICE) {
Lattice *lt = obedit->data;
-
+
a = lt->editlatt->latt->pntsu * lt->editlatt->latt->pntsv * lt->editlatt->latt->pntsw;
bp = lt->editlatt->latt->def;
while (a--) {
@@ -215,28 +215,24 @@ static int vertex_parent_set_exec(bContext *C, wmOperator *op)
bp++;
}
}
-
+
if (v4 || !((v1 && v2 == 0 && v3 == 0) || (v1 && v2 && v3))) {
BKE_report(op->reports, RPT_ERROR, "Select either 1 or 3 vertices to parent to");
return OPERATOR_CANCELLED;
}
-
+
CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects)
{
if (ob != obedit) {
DAG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
par = obedit->parent;
-
- while (par) {
- if (par == ob) break;
- par = par->parent;
- }
- if (par) {
+
+ if (BKE_object_parent_loop_check(par, ob)) {
BKE_report(op->reports, RPT_ERROR, "Loop in parents");
}
else {
Object workob;
-
+
ob->parent = BASACT->object;
if (v3) {
ob->partype = PARVERT3;
@@ -260,7 +256,7 @@ static int vertex_parent_set_exec(bContext *C, wmOperator *op)
}
}
CTX_DATA_END;
-
+
DAG_relations_tag_update(bmain);
WM_event_add_notifier(C, NC_OBJECT, NULL);
@@ -274,12 +270,12 @@ void OBJECT_OT_vertex_parent_set(wmOperatorType *ot)
ot->name = "Make Vertex Parent";
ot->description = "Parent selected objects to the selected vertices";
ot->idname = "OBJECT_OT_vertex_parent_set";
-
+
/* api callbacks */
ot->invoke = WM_operator_confirm;
ot->poll = vertex_parent_set_poll;
ot->exec = vertex_parent_set_exec;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
@@ -291,36 +287,38 @@ static int make_proxy_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
Scene *scene = CTX_data_scene(C);
Object *ob = ED_object_active_context(C);
-
+
/* sanity checks */
if (!scene || scene->id.lib || !ob)
return OPERATOR_CANCELLED;
-
+
/* Get object to work on - use a menu if we need to... */
if (ob->dup_group && ob->dup_group->id.lib) {
/* gives menu with list of objects in group */
- //proxy_group_objects_menu(C, op, ob, ob->dup_group);
+ /* proxy_group_objects_menu(C, op, ob, ob->dup_group); */
WM_enum_search_invoke(C, op, event);
return OPERATOR_CANCELLED;
-
}
else if (ob->id.lib) {
- uiPopupMenu *pup = uiPupMenuBegin(C, IFACE_("OK?"), ICON_QUESTION);
- uiLayout *layout = uiPupMenuLayout(pup);
-
+ uiPopupMenu *pup = UI_popup_menu_begin(C, IFACE_("OK?"), ICON_QUESTION);
+ uiLayout *layout = UI_popup_menu_layout(pup);
+
/* create operator menu item with relevant properties filled in */
- uiItemFullO_ptr(layout, op->type, op->type->name, ICON_NONE, NULL, WM_OP_EXEC_REGION_WIN, UI_ITEM_O_RETURN_PROPS);
-
+ uiItemFullO_ptr(layout, op->type, op->type->name, ICON_NONE, NULL,
+ WM_OP_EXEC_REGION_WIN, UI_ITEM_O_RETURN_PROPS);
+
/* present the menu and be done... */
- uiPupMenuEnd(C, pup);
+ UI_popup_menu_end(C, pup);
+
+ /* this invoke just calls another instance of this operator... */
+ return OPERATOR_INTERFACE;
}
else {
/* error.. cannot continue */
BKE_report(op->reports, RPT_ERROR, "Can only make proxy for a referenced object or group");
+ return OPERATOR_CANCELLED;
}
-
- /* this invoke just calls another instance of this operator... */
- return OPERATOR_CANCELLED;
+
}
static int make_proxy_exec(bContext *C, wmOperator *op)
@@ -338,32 +336,30 @@ static int make_proxy_exec(bContext *C, wmOperator *op)
ob = gob;
gob = NULL;
}
-
+
if (ob) {
Object *newob;
Base *newbase, *oldbase = BASACT;
char name[MAX_ID_NAME + 4];
-
- /* Add new object for the proxy */
- newob = BKE_object_add(bmain, scene, OB_EMPTY);
BLI_snprintf(name, sizeof(name), "%s_proxy", ((ID *)(gob ? gob : ob))->name + 2);
- rename_id(&newob->id, name);
-
+ /* Add new object for the proxy */
+ newob = BKE_object_add(bmain, scene, OB_EMPTY, name);
+
/* set layers OK */
newbase = BASACT; /* BKE_object_add sets active... */
newbase->lay = oldbase->lay;
newob->lay = newbase->lay;
-
+
/* remove base, leave user count of object, it gets linked in BKE_object_make_proxy */
if (gob == NULL) {
BKE_scene_base_unlink(scene, oldbase);
MEM_freeN(oldbase);
}
-
+
BKE_object_make_proxy(newob, ob, gob);
-
+
/* depsgraph flushes are needed for the new data */
DAG_relations_tag_update(bmain);
DAG_id_tag_update(&newob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
@@ -373,12 +369,13 @@ static int make_proxy_exec(bContext *C, wmOperator *op)
BKE_report(op->reports, RPT_ERROR, "No object to make proxy for");
return OPERATOR_CANCELLED;
}
-
+
return OPERATOR_FINISHED;
}
/* Generic itemf's for operators that take library args */
-static EnumPropertyItem *proxy_group_object_itemf(bContext *C, PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), bool *r_free)
+static EnumPropertyItem *proxy_group_object_itemf(bContext *C, PointerRNA *UNUSED(ptr),
+ PropertyRNA *UNUSED(prop), bool *r_free)
{
EnumPropertyItem item_tmp = {0}, *item = NULL;
int totitem = 0;
@@ -410,17 +407,19 @@ void OBJECT_OT_proxy_make(wmOperatorType *ot)
ot->name = "Make Proxy";
ot->idname = "OBJECT_OT_proxy_make";
ot->description = "Add empty object to become local replacement data of a library-linked object";
-
+
/* callbacks */
ot->invoke = make_proxy_invoke;
ot->exec = make_proxy_exec;
ot->poll = ED_operator_object_active;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
+
/* properties */
- prop = RNA_def_enum(ot->srna, "object", DummyRNA_DEFAULT_items, 0, "Proxy Object", "Name of lib-linked/grouped object to make a proxy for"); /* XXX, relies on hard coded ID at the moment */
+ /* XXX, relies on hard coded ID at the moment */
+ prop = RNA_def_enum(ot->srna, "object", DummyRNA_DEFAULT_items, 0, "Proxy Object",
+ "Name of lib-linked/grouped object to make a proxy for");
RNA_def_enum_funcs(prop, proxy_group_object_itemf);
RNA_def_property_flag(prop, PROP_ENUM_NO_TRANSLATE);
ot->prop = prop;
@@ -435,9 +434,12 @@ typedef enum eObClearParentTypes {
} eObClearParentTypes;
EnumPropertyItem prop_clear_parent_types[] = {
- {CLEAR_PARENT_ALL, "CLEAR", 0, "Clear Parent", ""},
- {CLEAR_PARENT_KEEP_TRANSFORM, "CLEAR_KEEP_TRANSFORM", 0, "Clear and Keep Transformation", ""},
- {CLEAR_PARENT_INVERSE, "CLEAR_INVERSE", 0, "Clear Parent Inverse", ""},
+ {CLEAR_PARENT_ALL, "CLEAR", 0, "Clear Parent",
+ "Completely clear the parenting relationship, including involved modifiers is any"},
+ {CLEAR_PARENT_KEEP_TRANSFORM, "CLEAR_KEEP_TRANSFORM", 0, "Clear and Keep Transformation",
+ "As 'Clear Parent', but keep the current visual transformations of the object"},
+ {CLEAR_PARENT_INVERSE, "CLEAR_INVERSE", 0, "Clear Parent Inverse",
+ "Reset the transform corrections applied to the parenting relationship, does not remove parenting itself"},
{0, NULL, 0, NULL, NULL}
};
@@ -446,13 +448,13 @@ static void object_remove_parent_deform_modifiers(Object *ob, const Object *par)
{
if (ELEM(par->type, OB_ARMATURE, OB_LATTICE, OB_CURVE)) {
ModifierData *md, *mdn;
-
+
/* assume that we only need to remove the first instance of matching deform modifier here */
for (md = ob->modifiers.first; md; md = mdn) {
bool free = false;
-
+
mdn = md->next;
-
+
/* need to match types (modifier + parent) and references */
if ((md->type == eModifierType_Armature) && (par->type == OB_ARMATURE)) {
ArmatureModifierData *amd = (ArmatureModifierData *)md;
@@ -472,7 +474,7 @@ static void object_remove_parent_deform_modifiers(Object *ob, const Object *par)
free = true;
}
}
-
+
/* free modifier if match */
if (free) {
BLI_remlink(&ob->modifiers, md);
@@ -482,17 +484,17 @@ static void object_remove_parent_deform_modifiers(Object *ob, const Object *par)
}
}
-void ED_object_parent_clear(Object *ob, int type)
+void ED_object_parent_clear(Object *ob, const int type)
{
if (ob->parent == NULL)
return;
-
+
switch (type) {
case CLEAR_PARENT_ALL:
{
/* for deformers, remove corresponding modifiers to prevent a large number of modifiers building up */
object_remove_parent_deform_modifiers(ob, ob->parent);
-
+
/* clear parenting relationship completely */
ob->parent = NULL;
break;
@@ -506,12 +508,15 @@ void ED_object_parent_clear(Object *ob, int type)
}
case CLEAR_PARENT_INVERSE:
{
- /* object stays parented, but the parent inverse (i.e. offset from parent to retain binding state) is cleared */
- unit_m4(ob->parentinv);
+ /* object stays parented, but the parent inverse (i.e. offset from parent to retain binding state)
+ * is cleared. In other words: nothing to do here! */
break;
}
}
-
+
+ /* Always clear parentinv matrix for sake of consistency, see T41950. */
+ unit_m4(ob->parentinv);
+
DAG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
}
@@ -519,7 +524,7 @@ void ED_object_parent_clear(Object *ob, int type)
static int parent_clear_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
- int type = RNA_enum_get(op->ptr, "type");
+ const int type = RNA_enum_get(op->ptr, "type");
CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects)
{
@@ -539,23 +544,26 @@ void OBJECT_OT_parent_clear(wmOperatorType *ot)
ot->name = "Clear Parent";
ot->description = "Clear the object's parenting";
ot->idname = "OBJECT_OT_parent_clear";
-
+
/* api callbacks */
ot->invoke = WM_menu_invoke;
ot->exec = parent_clear_exec;
-
+
ot->poll = ED_operator_object_active_editable;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
+
ot->prop = RNA_def_enum(ot->srna, "type", prop_clear_parent_types, CLEAR_PARENT_ALL, "Type", "");
}
/* ******************** Make Parent Operator *********************** */
-void ED_object_parent(Object *ob, Object *par, int type, const char *substr)
+void ED_object_parent(Object *ob, Object *par, const int type, const char *substr)
{
+ /* Always clear parentinv matrix for sake of consistency, see T41950. */
+ unit_m4(ob->parentinv);
+
if (!par || BKE_object_parent_loop_check(par, ob)) {
ob->parent = NULL;
ob->partype = PAROBJECT;
@@ -563,6 +571,9 @@ void ED_object_parent(Object *ob, Object *par, int type, const char *substr)
return;
}
+ /* Other partypes are deprecated, do not use here! */
+ BLI_assert(ELEM(type & PARTYPE, PAROBJECT, PARSKEL, PARVERT1, PARVERT3, PARBONE));
+
/* this could use some more checks */
ob->parent = par;
@@ -589,21 +600,21 @@ EnumPropertyItem prop_make_parent_types[] = {
{0, NULL, 0, NULL, NULL}
};
-int ED_object_parent_set(ReportList *reports, Main *bmain, Scene *scene, Object *ob, Object *par,
- int partype, bool xmirror, bool keep_transform, const int vert_par[3])
+bool ED_object_parent_set(ReportList *reports, Main *bmain, Scene *scene, Object *ob, Object *par,
+ int partype, const bool xmirror, const bool keep_transform, const int vert_par[3])
{
bPoseChannel *pchan = NULL;
- int pararm = ELEM(partype, PAR_ARMATURE, PAR_ARMATURE_NAME, PAR_ARMATURE_ENVELOPE, PAR_ARMATURE_AUTO);
-
+ const bool pararm = ELEM(partype, PAR_ARMATURE, PAR_ARMATURE_NAME, PAR_ARMATURE_ENVELOPE, PAR_ARMATURE_AUTO);
+
DAG_id_tag_update(&par->id, OB_RECALC_OB);
-
+
/* preconditions */
if (partype == PAR_FOLLOW || partype == PAR_PATH_CONST) {
if (par->type != OB_CURVE)
return 0;
else {
Curve *cu = par->data;
-
+
if ((cu->flag & CU_PATH) == 0) {
cu->flag |= CU_PATH | CU_FOLLOW;
BKE_displist_make_curveTypes(scene, par, 0); /* force creation of path data */
@@ -617,12 +628,12 @@ int ED_object_parent_set(ReportList *reports, Main *bmain, Scene *scene, Object
/* get or create F-Curve */
bAction *act = verify_adt_action(&cu->id, 1);
FCurve *fcu = verify_fcurve(act, NULL, NULL, "eval_time", 0, 1);
-
+
/* setup dummy 'generator' modifier here to get 1-1 correspondence still working */
if (!fcu->bezt && !fcu->fpt && !fcu->modifiers.first)
add_fmodifier(&fcu->modifiers, FMODIFIER_TYPE_GENERATOR);
}
-
+
/* fall back on regular parenting now (for follow only) */
if (partype == PAR_FOLLOW)
partype = PAR_OBJECT;
@@ -630,17 +641,17 @@ int ED_object_parent_set(ReportList *reports, Main *bmain, Scene *scene, Object
}
else if (ELEM(partype, PAR_BONE, PAR_BONE_RELATIVE)) {
pchan = BKE_pose_channel_active(par);
-
+
if (pchan == NULL) {
BKE_report(reports, RPT_ERROR, "No active bone");
- return 0;
+ return false;
}
}
-
+
if (ob != par) {
if (BKE_object_parent_loop_check(par, ob)) {
BKE_report(reports, RPT_ERROR, "Loop in parents");
- return 0;
+ return false;
}
else {
Object workob;
@@ -655,14 +666,16 @@ int ED_object_parent_set(ReportList *reports, Main *bmain, Scene *scene, Object
/* set the parent (except for follow-path constraint option) */
if (partype != PAR_PATH_CONST) {
ob->parent = par;
+ /* Always clear parentinv matrix for sake of consistency, see T41950. */
+ unit_m4(ob->parentinv);
}
-
+
/* handle types */
if (pchan)
BLI_strncpy(ob->parsubstr, pchan->name, sizeof(ob->parsubstr));
else
ob->parsubstr[0] = 0;
-
+
if (partype == PAR_PATH_CONST) {
/* don't do anything here, since this is not technically "parenting" */
}
@@ -670,17 +683,18 @@ int ED_object_parent_set(ReportList *reports, Main *bmain, Scene *scene, Object
/* partype is now set to PAROBJECT so that invisible 'virtual' modifiers don't need to be created
* NOTE: the old (2.4x) method was to set ob->partype = PARSKEL, creating the virtual modifiers
*/
- ob->partype = PAROBJECT; /* note, dna define, not operator property */
- //ob->partype = PARSKEL; /* note, dna define, not operator property */
-
- /* BUT, to keep the deforms, we need a modifier, and then we need to set the object that it uses
+ ob->partype = PAROBJECT; /* note, dna define, not operator property */
+ /* ob->partype = PARSKEL; */ /* note, dna define, not operator property */
+
+ /* BUT, to keep the deforms, we need a modifier, and then we need to set the object that it uses
* - We need to ensure that the modifier we're adding doesn't already exist, so we check this by
* assuming that the parent is selected too...
*/
- // XXX currently this should only happen for meshes, curves, surfaces, and lattices - this stuff isn't available for metas yet
+ /* XXX currently this should only happen for meshes, curves, surfaces,
+ * and lattices - this stuff isn't available for metas yet */
if (ELEM(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_LATTICE)) {
ModifierData *md;
-
+
switch (partype) {
case PAR_CURVE: /* curve deform */
if (modifiers_isDeformedByCurve(ob) != par) {
@@ -688,6 +702,9 @@ int ED_object_parent_set(ReportList *reports, Main *bmain, Scene *scene, Object
if (md) {
((CurveModifierData *)md)->object = par;
}
+ if (par->curve_cache && par->curve_cache->path == NULL) {
+ DAG_id_tag_update(&par->id, OB_RECALC_DATA);
+ }
}
break;
case PAR_LATTICE: /* lattice deform */
@@ -730,21 +747,21 @@ int ED_object_parent_set(ReportList *reports, Main *bmain, Scene *scene, Object
else {
ob->partype = PAROBJECT; /* note, dna define, not operator property */
}
-
+
/* constraint */
if (partype == PAR_PATH_CONST) {
bConstraint *con;
bFollowPathConstraint *data;
float cmat[4][4], vec[3];
-
+
con = BKE_constraint_add_for_object(ob, "AutoPath", CONSTRAINT_TYPE_FOLLOWPATH);
-
+
data = con->data;
data->tar = par;
-
+
BKE_constraint_target_matrix_get(scene, con, 0, CONSTRAINT_OBTYPE_OBJECT, NULL, cmat, scene->r.cfra);
sub_v3_v3v3(vec, ob->obmat[3], cmat[3]);
-
+
copy_v3_v3(ob->loc, vec);
}
else if (pararm && (ob->type == OB_MESH) && (par->type == OB_ARMATURE)) {
@@ -760,7 +777,7 @@ int ED_object_parent_set(ReportList *reports, Main *bmain, Scene *scene, Object
/* get corrected inverse */
ob->partype = PAROBJECT;
BKE_object_workob_calc_parent(scene, ob, &workob);
-
+
invert_m4_m4(ob->parentinv, workob.obmat);
}
else {
@@ -768,12 +785,12 @@ int ED_object_parent_set(ReportList *reports, Main *bmain, Scene *scene, Object
BKE_object_workob_calc_parent(scene, ob, &workob);
invert_m4_m4(ob->parentinv, workob.obmat);
}
-
+
DAG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA);
}
}
- return 1;
+ return true;
}
@@ -787,6 +804,7 @@ static void parent_set_vert_find(KDTree *tree, Object *child, int vert_par[3], b
tot = BLI_kdtree_find_nearest_n(tree, co_find, nearest, 3);
BLI_assert(tot == 3);
+ UNUSED_VARS(tot);
vert_par[0] = nearest[0].index;
vert_par[1] = nearest[1].index;
@@ -808,8 +826,8 @@ static int parent_set_exec(bContext *C, wmOperator *op)
Scene *scene = CTX_data_scene(C);
Object *par = ED_object_active_context(C);
int partype = RNA_enum_get(op->ptr, "type");
- bool xmirror = RNA_boolean_get(op->ptr, "xmirror");
- bool keep_transform = RNA_boolean_get(op->ptr, "keep_transform");
+ const bool xmirror = RNA_boolean_get(op->ptr, "xmirror");
+ const bool keep_transform = RNA_boolean_get(op->ptr, "keep_transform");
bool ok = true;
/* vertex parent (kdtree) */
@@ -828,27 +846,25 @@ static int parent_set_exec(bContext *C, wmOperator *op)
if (tree_tot < (is_tri ? 3 : 1)) {
BKE_report(op->reports, RPT_ERROR, "Not enough vertices for vertex-parent");
ok = false;
- goto cleanup;
}
}
+ if (ok) {
+ /* Non vertex-parent */
+ CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects)
+ {
+ if (is_vert_par) {
+ parent_set_vert_find(tree, ob, vert_par, is_tri);
+ }
- /* Non vertex-parent */
- CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects)
- {
- if (is_vert_par) {
- parent_set_vert_find(tree, ob, vert_par, is_tri);
- }
-
- if (!ED_object_parent_set(op->reports, bmain, scene, ob, par, partype, xmirror, keep_transform, vert_par_p)) {
- ok = false;
- break;
+ if (!ED_object_parent_set(op->reports, bmain, scene, ob, par, partype, xmirror, keep_transform, vert_par_p)) {
+ ok = false;
+ break;
+ }
}
+ CTX_DATA_END;
}
- CTX_DATA_END;
-
-cleanup:
if (is_vert_par) {
BLI_kdtree_free(tree);
}
@@ -867,8 +883,8 @@ cleanup:
static int parent_set_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *UNUSED(event))
{
Object *ob = ED_object_active_context(C);
- uiPopupMenu *pup = uiPupMenuBegin(C, IFACE_("Set Parent To"), ICON_NONE);
- uiLayout *layout = uiPupMenuLayout(pup);
+ uiPopupMenu *pup = UI_popup_menu_begin(C, IFACE_("Set Parent To"), ICON_NONE);
+ uiLayout *layout = UI_popup_menu_layout(pup);
wmOperatorType *ot = WM_operatortype_find("OBJECT_OT_parent_set", true);
PointerRNA opptr;
@@ -902,22 +918,22 @@ static int parent_set_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent
else if (ob->type == OB_LATTICE) {
uiItemEnumO_ptr(layout, ot, NULL, 0, "type", PAR_LATTICE);
}
-
+
/* vertex parenting */
if (OB_TYPE_SUPPORT_PARVERT(ob->type)) {
uiItemEnumO_ptr(layout, ot, NULL, 0, "type", PAR_VERTEX);
uiItemEnumO_ptr(layout, ot, NULL, 0, "type", PAR_VERTEX_TRI);
}
- uiPupMenuEnd(C, pup);
-
- return OPERATOR_CANCELLED;
+ UI_popup_menu_end(C, pup);
+
+ return OPERATOR_INTERFACE;
}
static bool parent_set_draw_check_prop(PointerRNA *ptr, PropertyRNA *prop)
{
const char *prop_id = RNA_property_identifier(prop);
- int type = RNA_enum_get(ptr, "type");
+ const int type = RNA_enum_get(ptr, "type");
/* Only show XMirror for PAR_ARMATURE_ENVELOPE and PAR_ARMATURE_AUTO! */
if (STREQ(prop_id, "xmirror")) {
@@ -948,22 +964,21 @@ void OBJECT_OT_parent_set(wmOperatorType *ot)
ot->name = "Make Parent";
ot->description = "Set the object's parenting";
ot->idname = "OBJECT_OT_parent_set";
-
+
/* api callbacks */
ot->invoke = parent_set_invoke;
ot->exec = parent_set_exec;
ot->poll = ED_operator_object_active;
ot->ui = parent_set_ui;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- RNA_def_enum(ot->srna, "type", prop_make_parent_types, 0, "Type", "");
+
+ ot->prop = RNA_def_enum(ot->srna, "type", prop_make_parent_types, 0, "Type", "");
RNA_def_boolean(ot->srna, "xmirror", false, "X Mirror",
"Apply weights symmetrically along X axis, for Envelope/Automatic vertex groups creation");
RNA_def_boolean(ot->srna, "keep_transform", false, "Keep Transform",
"Apply transformation before parenting");
-
}
/* ************ Make Parent Without Inverse Operator ******************* */
@@ -972,9 +987,9 @@ static int parent_noinv_set_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
Object *par = ED_object_active_context(C);
-
+
DAG_id_tag_update(&par->id, OB_RECALC_OB);
-
+
/* context iterator */
CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects)
{
@@ -986,10 +1001,10 @@ static int parent_noinv_set_exec(bContext *C, wmOperator *op)
/* clear inverse matrix and also the object location */
unit_m4(ob->parentinv);
memset(ob->loc, 0, 3 * sizeof(float));
-
+
/* set recalc flags */
DAG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA);
-
+
/* set parenting type for object - object only... */
ob->parent = par;
ob->partype = PAROBJECT; /* note, dna define, not operator property */
@@ -997,10 +1012,10 @@ static int parent_noinv_set_exec(bContext *C, wmOperator *op)
}
}
CTX_DATA_END;
-
+
DAG_relations_tag_update(bmain);
WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
-
+
return OPERATOR_FINISHED;
}
@@ -1010,12 +1025,12 @@ void OBJECT_OT_parent_no_inverse_set(wmOperatorType *ot)
ot->name = "Make Parent without Inverse";
ot->description = "Set the object's parenting without setting the inverse parent correction";
ot->idname = "OBJECT_OT_parent_no_inverse_set";
-
+
/* api callbacks */
ot->invoke = WM_operator_confirm;
ot->exec = parent_noinv_set_exec;
ot->poll = ED_operator_object_active_editable;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
@@ -1040,23 +1055,22 @@ static int object_slow_parent_clear_exec(bContext *C, wmOperator *UNUSED(op))
CTX_DATA_END;
WM_event_add_notifier(C, NC_SCENE, scene);
-
+
return OPERATOR_FINISHED;
}
void OBJECT_OT_slow_parent_clear(wmOperatorType *ot)
{
-
/* identifiers */
ot->name = "Clear Slow Parent";
ot->description = "Clear the object's slow parent";
ot->idname = "OBJECT_OT_slow_parent_clear";
-
+
/* api callbacks */
ot->invoke = WM_operator_confirm;
ot->exec = object_slow_parent_clear_exec;
ot->poll = ED_operator_view3d_active;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
@@ -1073,37 +1087,40 @@ static int object_slow_parent_set_exec(bContext *C, wmOperator *UNUSED(op))
ob->partype |= PARSLOW;
DAG_id_tag_update(&ob->id, OB_RECALC_OB);
-
}
CTX_DATA_END;
WM_event_add_notifier(C, NC_SCENE, scene);
-
+
return OPERATOR_FINISHED;
}
void OBJECT_OT_slow_parent_set(wmOperatorType *ot)
{
-
/* identifiers */
ot->name = "Set Slow Parent";
ot->description = "Set the object's slow parent";
ot->idname = "OBJECT_OT_slow_parent_set";
-
+
/* api callbacks */
ot->invoke = WM_operator_confirm;
ot->exec = object_slow_parent_set_exec;
ot->poll = ED_operator_view3d_active;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/* ******************** Clear Track Operator ******************* */
+enum {
+ CLEAR_TRACK = 1,
+ CLEAR_TRACK_KEEP_TRANSFORM = 2,
+};
+
static EnumPropertyItem prop_clear_track_types[] = {
- {0, "CLEAR", 0, "Clear Track", ""},
- {1, "CLEAR_KEEP_TRANSFORM", 0, "Clear and Keep Transformation (Clear Track)", ""},
+ {CLEAR_TRACK, "CLEAR", 0, "Clear Track", ""},
+ {CLEAR_TRACK_KEEP_TRANSFORM, "CLEAR_KEEP_TRANSFORM", 0, "Clear and Keep Transformation (Clear Track)", ""},
{0, NULL, 0, NULL, NULL}
};
@@ -1111,7 +1128,7 @@ static EnumPropertyItem prop_clear_track_types[] = {
static int object_track_clear_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
- int type = RNA_enum_get(op->ptr, "type");
+ const int type = RNA_enum_get(op->ptr, "type");
if (CTX_data_edit_object(C)) {
BKE_report(op->reports, RPT_ERROR, "Operation cannot be performed in edit mode");
@@ -1120,19 +1137,19 @@ static int object_track_clear_exec(bContext *C, wmOperator *op)
CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects)
{
bConstraint *con, *pcon;
-
+
/* remove track-object for old track */
ob->track = NULL;
DAG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
-
+
/* also remove all tracking constraints */
for (con = ob->constraints.last; con; con = pcon) {
pcon = con->prev;
if (ELEM(con->type, CONSTRAINT_TYPE_TRACKTO, CONSTRAINT_TYPE_LOCKTRACK, CONSTRAINT_TYPE_DAMPTRACK))
BKE_constraint_remove(&ob->constraints, con);
}
-
- if (type == 1)
+
+ if (type == CLEAR_TRACK_KEEP_TRANSFORM)
BKE_object_apply_mat4(ob, ob->obmat, true, true);
}
CTX_DATA_END;
@@ -1149,25 +1166,31 @@ void OBJECT_OT_track_clear(wmOperatorType *ot)
ot->name = "Clear Track";
ot->description = "Clear tracking constraint or flag from object";
ot->idname = "OBJECT_OT_track_clear";
-
+
/* api callbacks */
ot->invoke = WM_menu_invoke;
ot->exec = object_track_clear_exec;
-
+
ot->poll = ED_operator_objectmode;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
+
ot->prop = RNA_def_enum(ot->srna, "type", prop_clear_track_types, 0, "Type", "");
}
/************************** Make Track Operator *****************************/
+enum {
+ CREATE_TRACK_DAMPTRACK = 1,
+ CREATE_TRACK_TRACKTO = 2,
+ CREATE_TRACK_LOCKTRACK = 3,
+};
+
static EnumPropertyItem prop_make_track_types[] = {
- {1, "DAMPTRACK", 0, "Damped Track Constraint", ""},
- {2, "TRACKTO", 0, "Track To Constraint", ""},
- {3, "LOCKTRACK", 0, "Lock Track Constraint", ""},
+ {CREATE_TRACK_DAMPTRACK, "DAMPTRACK", 0, "Damped Track Constraint", ""},
+ {CREATE_TRACK_TRACKTO, "TRACKTO", 0, "Track To Constraint", ""},
+ {CREATE_TRACK_LOCKTRACK, "LOCKTRACK", 0, "Lock Track Constraint", ""},
{0, NULL, 0, NULL, NULL}
};
@@ -1175,78 +1198,86 @@ static int track_set_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
Object *obact = ED_object_active_context(C);
-
- int type = RNA_enum_get(op->ptr, "type");
-
- if (type == 1) {
- bConstraint *con;
- bDampTrackConstraint *data;
- CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects)
+ const int type = RNA_enum_get(op->ptr, "type");
+
+ switch (type) {
+ case CREATE_TRACK_DAMPTRACK:
{
- if (ob != obact) {
- con = BKE_constraint_add_for_object(ob, "AutoTrack", CONSTRAINT_TYPE_DAMPTRACK);
+ bConstraint *con;
+ bDampTrackConstraint *data;
- data = con->data;
- data->tar = obact;
- DAG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
-
- /* Lamp, Camera and Speaker track differently by default */
- if (ELEM(ob->type, OB_LAMP, OB_CAMERA, OB_SPEAKER)) {
- data->trackflag = TRACK_nZ;
+ CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects)
+ {
+ if (ob != obact) {
+ con = BKE_constraint_add_for_object(ob, "AutoTrack", CONSTRAINT_TYPE_DAMPTRACK);
+
+ data = con->data;
+ data->tar = obact;
+ DAG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
+
+ /* Lamp, Camera and Speaker track differently by default */
+ if (ELEM(ob->type, OB_LAMP, OB_CAMERA, OB_SPEAKER)) {
+ data->trackflag = TRACK_nZ;
+ }
}
}
+ CTX_DATA_END;
+ break;
}
- CTX_DATA_END;
- }
- else if (type == 2) {
- bConstraint *con;
- bTrackToConstraint *data;
-
- CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects)
+ case CREATE_TRACK_TRACKTO:
{
- if (ob != obact) {
- con = BKE_constraint_add_for_object(ob, "AutoTrack", CONSTRAINT_TYPE_TRACKTO);
+ bConstraint *con;
+ bTrackToConstraint *data;
- data = con->data;
- data->tar = obact;
- DAG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
-
- /* Lamp, Camera and Speaker track differently by default */
- if (ELEM(ob->type, OB_LAMP, OB_CAMERA, OB_SPEAKER)) {
- data->reserved1 = TRACK_nZ;
- data->reserved2 = UP_Y;
+ CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects)
+ {
+ if (ob != obact) {
+ con = BKE_constraint_add_for_object(ob, "AutoTrack", CONSTRAINT_TYPE_TRACKTO);
+
+ data = con->data;
+ data->tar = obact;
+ DAG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
+
+ /* Lamp, Camera and Speaker track differently by default */
+ if (ELEM(ob->type, OB_LAMP, OB_CAMERA, OB_SPEAKER)) {
+ data->reserved1 = TRACK_nZ;
+ data->reserved2 = UP_Y;
+ }
}
}
+ CTX_DATA_END;
+ break;
}
- CTX_DATA_END;
- }
- else if (type == 3) {
- bConstraint *con;
- bLockTrackConstraint *data;
-
- CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects)
+ case CREATE_TRACK_LOCKTRACK:
{
- if (ob != obact) {
- con = BKE_constraint_add_for_object(ob, "AutoTrack", CONSTRAINT_TYPE_LOCKTRACK);
+ bConstraint *con;
+ bLockTrackConstraint *data;
- data = con->data;
- data->tar = obact;
- DAG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
-
- /* Lamp, Camera and Speaker track differently by default */
- if (ELEM(ob->type, OB_LAMP, OB_CAMERA, OB_SPEAKER)) {
- data->trackflag = TRACK_nZ;
- data->lockflag = LOCK_Y;
+ CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects)
+ {
+ if (ob != obact) {
+ con = BKE_constraint_add_for_object(ob, "AutoTrack", CONSTRAINT_TYPE_LOCKTRACK);
+
+ data = con->data;
+ data->tar = obact;
+ DAG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
+
+ /* Lamp, Camera and Speaker track differently by default */
+ if (ELEM(ob->type, OB_LAMP, OB_CAMERA, OB_SPEAKER)) {
+ data->trackflag = TRACK_nZ;
+ data->lockflag = LOCK_Y;
+ }
}
}
+ CTX_DATA_END;
+ break;
}
- CTX_DATA_END;
}
-
+
DAG_relations_tag_update(bmain);
WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
-
+
return OPERATOR_FINISHED;
}
@@ -1254,18 +1285,18 @@ void OBJECT_OT_track_set(wmOperatorType *ot)
{
/* identifiers */
ot->name = "Make Track";
- ot->description = "Make the object track another object, either by constraint or old way or locked track";
+ ot->description = "Make the object track another object, using various methods/constraints";
ot->idname = "OBJECT_OT_track_set";
-
+
/* api callbacks */
ot->invoke = WM_menu_invoke;
ot->exec = track_set_exec;
-
+
ot->poll = ED_operator_objectmode;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
+
/* properties */
ot->prop = RNA_def_enum(ot->srna, "type", prop_make_track_types, 0, "Type", "");
}
@@ -1286,8 +1317,8 @@ static unsigned int move_to_layer_init(bContext *C, wmOperator *op)
CTX_DATA_END;
for (a = 0; a < 20; a++)
- values[a] = (lay & (1 << a));
-
+ values[a] = (lay & (1 << a)) != 0;
+
RNA_boolean_set_array(op->ptr, "layers", values);
}
else {
@@ -1320,12 +1351,12 @@ static int move_to_layer_exec(bContext *C, wmOperator *op)
View3D *v3d = CTX_wm_view3d(C);
unsigned int lay, local;
/* bool is_lamp = false; */ /* UNUSED */
-
+
lay = move_to_layer_init(C, op);
lay &= 0xFFFFFF;
if (lay == 0) return OPERATOR_CANCELLED;
-
+
if (v3d && v3d->localvd) {
/* now we can move out of localview. */
/* note: layers are set in bases, library objects work for this */
@@ -1353,9 +1384,9 @@ static int move_to_layer_exec(bContext *C, wmOperator *op)
}
CTX_DATA_END;
}
-
+
/* warning, active object may be hidden now */
-
+
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, scene);
WM_event_add_notifier(C, NC_SCENE | ND_LAYER_CONTENT, scene);
@@ -1370,15 +1401,15 @@ void OBJECT_OT_move_to_layer(wmOperatorType *ot)
ot->name = "Move to Layer";
ot->description = "Move the object to different layers";
ot->idname = "OBJECT_OT_move_to_layer";
-
+
/* api callbacks */
ot->invoke = move_to_layer_invoke;
ot->exec = move_to_layer_exec;
ot->poll = ED_operator_objectmode;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
+
/* properties */
RNA_def_boolean_layer_member(ot->srna, "layers", 20, NULL, "Layer", "");
}
@@ -1390,13 +1421,12 @@ static void link_to_scene(Main *UNUSED(bmain), unsigned short UNUSED(nr))
{
Scene *sce = (Scene *) BLI_findlink(&bmain->scene, G.curscreen->scenenr - 1);
Base *base, *nbase;
-
- if (sce == 0) return;
+
+ if (sce == NULL) return;
if (sce->id.lib) return;
-
+
for (base = FIRSTBASE; base; base = base->next) {
if (TESTBASE(v3d, base)) {
-
nbase = MEM_mallocN(sizeof(Base), "newbase");
*nbase = *base;
BLI_addhead(&(sce->base), nbase);
@@ -1453,48 +1483,45 @@ static int make_links_scene_exec(bContext *C, wmOperator *op)
}
enum {
- MAKE_LINKS_OBDATA = 1,
- MAKE_LINKS_MATERIALS,
- MAKE_LINKS_ANIMDATA,
- MAKE_LINKS_GROUP,
- MAKE_LINKS_DUPLIGROUP,
- MAKE_LINKS_MODIFIERS,
- MAKE_LINKS_FONTS
+ MAKE_LINKS_OBDATA = 1,
+ MAKE_LINKS_MATERIALS = 2,
+ MAKE_LINKS_ANIMDATA = 3,
+ MAKE_LINKS_GROUP = 4,
+ MAKE_LINKS_DUPLIGROUP = 5,
+ MAKE_LINKS_MODIFIERS = 6,
+ MAKE_LINKS_FONTS = 7,
};
-/* Return 1 if make link data is allow, zero otherwise */
-static int allow_make_links_data(const int type, Object *ob_src, Object *ob_dst)
+/* Return true if make link data is allowed, false otherwise */
+static bool allow_make_links_data(const int type, Object *ob_src, Object *ob_dst)
{
switch (type) {
case MAKE_LINKS_OBDATA:
- if (ob_src->type == ob_dst->type && ob_src->type != OB_EMPTY)
- return 1;
+ if (ob_src->type == ob_dst->type && ob_src->type != OB_EMPTY) {
+ return true;
+ }
break;
case MAKE_LINKS_MATERIALS:
- if (OB_TYPE_SUPPORT_MATERIAL(ob_src->type) &&
- OB_TYPE_SUPPORT_MATERIAL(ob_dst->type))
- {
- return 1;
+ if (OB_TYPE_SUPPORT_MATERIAL(ob_src->type) && OB_TYPE_SUPPORT_MATERIAL(ob_dst->type)) {
+ return true;
}
break;
case MAKE_LINKS_ANIMDATA:
case MAKE_LINKS_GROUP:
case MAKE_LINKS_DUPLIGROUP:
- return 1;
+ return true;
case MAKE_LINKS_MODIFIERS:
- if (ob_src->type != OB_EMPTY && ob_dst->type != OB_EMPTY)
- return 1;
+ if (!ELEM(OB_EMPTY, ob_src->type, ob_dst->type)) {
+ return true;
+ }
break;
case MAKE_LINKS_FONTS:
- if ((ob_src->data != ob_dst->data) &&
- (ob_src->type == OB_FONT) &&
- (ob_dst->type == OB_FONT))
- {
- return 1;
+ if ((ob_src->data != ob_dst->data) && (ob_src->type == OB_FONT) && (ob_dst->type == OB_FONT)) {
+ return true;
}
break;
}
- return 0;
+ return false;
}
static int make_links_data_exec(bContext *C, wmOperator *op)
@@ -1548,13 +1575,13 @@ static int make_links_data_exec(bContext *C, wmOperator *op)
DAG_id_tag_update(&ob_dst->id, 0);
break;
case MAKE_LINKS_ANIMDATA:
- BKE_copy_animdata_id((ID *)ob_dst, (ID *)ob_src, false);
+ BKE_animdata_copy_id((ID *)ob_dst, (ID *)ob_src, false);
if (ob_dst->data && ob_src->data) {
if (obdata_id->lib) {
is_lib = true;
break;
}
- BKE_copy_animdata_id((ID *)ob_dst->data, (ID *)ob_src->data, false);
+ BKE_animdata_copy_id((ID *)ob_dst->data, (ID *)ob_src->data, false);
}
DAG_id_tag_update(&ob_dst->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
break;
@@ -1697,13 +1724,13 @@ void OBJECT_OT_make_links_data(wmOperatorType *ot)
/**************************** Make Single User ********************************/
-static void single_object_users(Main *bmain, Scene *scene, View3D *v3d, int flag, bool copy_groups)
+static void single_object_users(Main *bmain, Scene *scene, View3D *v3d, const int flag, const bool copy_groups)
{
Base *base;
Object *ob, *obn;
Group *group, *groupn;
GroupObject *go;
-
+
clear_sca_new_poins(); /* sensor/contr/act */
/* newid may still have some trash from Outliner tree building,
@@ -1714,7 +1741,7 @@ static void single_object_users(Main *bmain, Scene *scene, View3D *v3d, int flag
/* duplicate (must set newid) */
for (base = FIRSTBASE; base; base = base->next) {
ob = base->object;
-
+
if ((base->flag & flag) == flag) {
if (ob->id.lib == NULL && ob->id.us > 1) {
/* base gets copy of object */
@@ -1761,10 +1788,10 @@ static void single_object_users(Main *bmain, Scene *scene, View3D *v3d, int flag
/* group pointers in scene */
BKE_scene_groups_relink(scene);
-
+
ID_NEW(scene->camera);
if (v3d) ID_NEW(v3d->camera);
-
+
/* object and group pointers */
for (base = FIRSTBASE; base; base = base->next) {
BKE_object_relink(base->object);
@@ -1778,7 +1805,7 @@ static void single_object_users(Main *bmain, Scene *scene, View3D *v3d, int flag
void ED_object_single_user(Main *bmain, Scene *scene, Object *ob)
{
Base *base;
- bool copy_groups = false;
+ const bool copy_groups = false;
for (base = FIRSTBASE; base; base = base->next) {
if (base->object == ob) base->flag |= OB_DONE;
@@ -1788,11 +1815,11 @@ void ED_object_single_user(Main *bmain, Scene *scene, Object *ob)
single_object_users(bmain, scene, NULL, OB_DONE, copy_groups);
}
-static void new_id_matar(Material **matar, int totcol)
+static void new_id_matar(Material **matar, const int totcol)
{
ID *id;
int a;
-
+
for (a = 0; a < totcol; a++) {
id = (ID *)matar[a];
if (id && id->lib == NULL) {
@@ -1810,12 +1837,12 @@ static void new_id_matar(Material **matar, int totcol)
}
}
-static void single_obdata_users(Main *bmain, Scene *scene, int flag)
+static void single_obdata_users(Main *bmain, Scene *scene, const int flag)
{
Object *ob;
Lamp *la;
Curve *cu;
- //Camera *cam;
+ /* Camera *cam; */
Base *base;
Mesh *me;
Lattice *lat;
@@ -1826,7 +1853,7 @@ static void single_obdata_users(Main *bmain, Scene *scene, int flag)
ob = base->object;
if (ob->id.lib == NULL && (base->flag & flag) == flag) {
id = ob->data;
-
+
if (id && id->us > 1 && id->lib == NULL) {
DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
@@ -1845,7 +1872,7 @@ static void single_obdata_users(Main *bmain, Scene *scene, int flag)
case OB_MESH:
ob->data = me = BKE_mesh_copy(ob->data);
if (me->key)
- BKE_copy_animdata_id_action((ID *)me->key);
+ BKE_animdata_copy_id_action((ID *)me->key);
break;
case OB_MBALL:
ob->data = BKE_mball_copy(ob->data);
@@ -1857,12 +1884,12 @@ static void single_obdata_users(Main *bmain, Scene *scene, int flag)
ID_NEW(cu->bevobj);
ID_NEW(cu->taperobj);
if (cu->key)
- BKE_copy_animdata_id_action((ID *)cu->key);
+ BKE_animdata_copy_id_action((ID *)cu->key);
break;
case OB_LATTICE:
ob->data = lat = BKE_lattice_copy(ob->data);
if (lat->key)
- BKE_copy_animdata_id_action((ID *)lat->key);
+ BKE_animdata_copy_id_action((ID *)lat->key);
break;
case OB_ARMATURE:
DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
@@ -1883,16 +1910,14 @@ static void single_obdata_users(Main *bmain, Scene *scene, int flag)
* AnimData structure, which is not what we want.
* (sergey)
*/
- BKE_copy_animdata_id_action((ID *)ob->data);
+ BKE_animdata_copy_id_action((ID *)ob->data);
id->us--;
id->newid = ob->data;
-
}
-
}
}
-
+
me = bmain->mesh.first;
while (me) {
ID_NEW(me->texcomesh);
@@ -1900,41 +1925,40 @@ static void single_obdata_users(Main *bmain, Scene *scene, int flag)
}
}
-static void single_object_action_users(Scene *scene, int flag)
+static void single_object_action_users(Scene *scene, const int flag)
{
Object *ob;
Base *base;
-
+
for (base = FIRSTBASE; base; base = base->next) {
ob = base->object;
if (ob->id.lib == NULL && (flag == 0 || (base->flag & SELECT)) ) {
DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
- BKE_copy_animdata_id_action(&ob->id);
+ BKE_animdata_copy_id_action(&ob->id);
}
}
}
-static void single_mat_users(Scene *scene, int flag, int do_textures)
+static void single_mat_users(Scene *scene, const int flag, const bool do_textures)
{
Object *ob;
Base *base;
Material *ma, *man;
Tex *tex;
int a, b;
-
+
for (base = FIRSTBASE; base; base = base->next) {
ob = base->object;
if (ob->id.lib == NULL && (flag == 0 || (base->flag & SELECT)) ) {
-
for (a = 1; a <= ob->totcol; a++) {
ma = give_current_material(ob, a);
if (ma) {
/* do not test for LIB_NEW: this functions guaranteed delivers single_users! */
-
+
if (ma->id.us > 1) {
man = BKE_material_copy(ma);
- BKE_copy_animdata_id_action(&man->id);
-
+ BKE_animdata_copy_id_action(&man->id);
+
man->id.us = 0;
assign_material(ob, man, a, BKE_MAT_ASSIGN_USERPREF);
@@ -1944,7 +1968,7 @@ static void single_mat_users(Scene *scene, int flag, int do_textures)
if (tex->id.us > 1) {
tex->id.us--;
tex = BKE_texture_copy(tex);
- BKE_copy_animdata_id_action(&tex->id);
+ BKE_animdata_copy_id_action(&tex->id);
man->mtex[b]->tex = tex;
}
}
@@ -1960,10 +1984,10 @@ static void single_mat_users(Scene *scene, int flag, int do_textures)
static void do_single_tex_user(Tex **from)
{
Tex *tex, *texn;
-
+
tex = *from;
if (tex == NULL) return;
-
+
if (tex->id.newid) {
*from = (Tex *)tex->id.newid;
id_us_plus(tex->id.newid);
@@ -1971,7 +1995,7 @@ static void do_single_tex_user(Tex **from)
}
else if (tex->id.us > 1) {
texn = BKE_texture_copy(tex);
- BKE_copy_animdata_id_action(&texn->id);
+ BKE_animdata_copy_id_action(&texn->id);
tex->id.newid = (ID *)texn;
tex->id.us--;
*from = texn;
@@ -1985,7 +2009,7 @@ static void single_tex_users_expand(Main *bmain)
Lamp *la;
World *wo;
int b;
-
+
for (ma = bmain->mat.first; ma; ma = ma->id.next) {
if (ma->id.flag & LIB_NEW) {
for (b = 0; b < MAX_MTEX; b++) {
@@ -2026,7 +2050,7 @@ static void single_mat_users_expand(Main *bmain)
MetaBall *mb;
Material *ma;
int a;
-
+
for (ob = bmain->object.first; ob; ob = ob->id.next)
if (ob->id.flag & LIB_NEW)
new_id_matar(ob->mat, ob->totcol);
@@ -2052,7 +2076,7 @@ static void single_mat_users_expand(Main *bmain)
}
/* used for copying scenes */
-void ED_object_single_users(Main *bmain, Scene *scene, bool full, bool copy_groups)
+void ED_object_single_users(Main *bmain, Scene *scene, const bool full, const bool copy_groups)
{
single_object_users(bmain, scene, NULL, 0, copy_groups);
@@ -2073,13 +2097,13 @@ static void make_local_makelocalmaterial(Material *ma)
{
AnimData *adt;
int b;
-
+
id_make_local(&ma->id, false);
-
+
for (b = 0; b < MAX_MTEX; b++)
if (ma->mtex[b] && ma->mtex[b]->tex)
id_make_local(&ma->mtex[b]->tex->id, false);
-
+
adt = BKE_animdata_from_id(&ma->id);
if (adt) BKE_animdata_make_local(adt);
@@ -2087,13 +2111,13 @@ static void make_local_makelocalmaterial(Material *ma)
}
enum {
- MAKE_LOCAL_SELECT_OB,
- MAKE_LOCAL_SELECT_OBDATA,
- MAKE_LOCAL_SELECT_OBDATA_MATERIAL,
- MAKE_LOCAL_ALL
+ MAKE_LOCAL_SELECT_OB = 1,
+ MAKE_LOCAL_SELECT_OBDATA = 2,
+ MAKE_LOCAL_SELECT_OBDATA_MATERIAL = 3,
+ MAKE_LOCAL_ALL = 4,
};
-static bool tag_localizable_looper(void *UNUSED(user_data), ID **id_pointer, int UNUSED(cd_flag))
+static bool tag_localizable_looper(void *UNUSED(user_data), ID **id_pointer, const int UNUSED(cd_flag))
{
if (*id_pointer) {
(*id_pointer)->flag &= ~LIB_DOIT;
@@ -2101,7 +2125,7 @@ static bool tag_localizable_looper(void *UNUSED(user_data), ID **id_pointer, int
return true;
}
-static void tag_localizable_objects(bContext *C, int mode)
+static void tag_localizable_objects(bContext *C, const int mode)
{
Main *bmain = CTX_data_main(C);
Object *object;
@@ -2182,8 +2206,9 @@ static int make_local_exec(bContext *C, wmOperator *op)
Material *ma, ***matarar;
Lamp *la;
ID *id;
- int a, b, mode = RNA_enum_get(op->ptr, "type");
-
+ const int mode = RNA_enum_get(op->ptr, "type");
+ int a, b;
+
if (mode == MAKE_LOCAL_ALL) {
/* de-select so the user can differentiate newly instanced from existing objects */
BKE_scene_base_deselect_all(scene);
@@ -2200,7 +2225,7 @@ static int make_local_exec(bContext *C, wmOperator *op)
tag_localizable_objects(C, mode);
BKE_main_id_clear_newpoins(bmain);
-
+
CTX_DATA_BEGIN (C, Object *, ob, selected_objects)
{
if ((ob->id.flag & LIB_DOIT) == 0) {
@@ -2211,7 +2236,7 @@ static int make_local_exec(bContext *C, wmOperator *op)
id_make_local(&ob->id, false);
}
CTX_DATA_END;
-
+
/* maybe object pointers */
CTX_DATA_BEGIN (C, Object *, ob, selected_objects)
{
@@ -2228,12 +2253,12 @@ static int make_local_exec(bContext *C, wmOperator *op)
}
id = ob->data;
-
+
if (id && (ELEM(mode, MAKE_LOCAL_SELECT_OBDATA, MAKE_LOCAL_SELECT_OBDATA_MATERIAL))) {
id_make_local(id, false);
adt = BKE_animdata_from_id(id);
if (adt) BKE_animdata_make_local(adt);
-
+
/* tag indirect data direct */
matarar = give_matarar(ob);
if (matarar) {
@@ -2273,7 +2298,7 @@ static int make_local_exec(bContext *C, wmOperator *op)
if (ma)
make_local_makelocalmaterial(ma);
}
-
+
matarar = (Material ***)give_matarar(ob);
if (matarar) {
for (a = 0; a < ob->totcol; a++) {
@@ -2306,26 +2331,31 @@ void OBJECT_OT_make_local(wmOperatorType *ot)
ot->name = "Make Local";
ot->description = "Make library linked datablocks local to this file";
ot->idname = "OBJECT_OT_make_local";
-
+
/* api callbacks */
ot->invoke = WM_menu_invoke;
ot->exec = make_local_exec;
ot->poll = ED_operator_objectmode;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
+
/* properties */
ot->prop = RNA_def_enum(ot->srna, "type", type_items, 0, "Type", "");
}
+enum {
+ MAKE_SINGLE_USER_ALL = 1,
+ MAKE_SINGLE_USER_SELECTED = 2,
+};
+
static int make_single_user_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
View3D *v3d = CTX_wm_view3d(C); /* ok if this is NULL */
- int flag = RNA_enum_get(op->ptr, "type"); /* 0==ALL, SELECTED==selected objecs */
- bool copy_groups = false;
+ const int flag = (RNA_enum_get(op->ptr, "type") == MAKE_SINGLE_USER_SELECTED) ? SELECT : 0;
+ const bool copy_groups = false;
bool update_deps = false;
BKE_main_id_clear_newpoins(bmain);
@@ -2372,8 +2402,8 @@ static int make_single_user_exec(bContext *C, wmOperator *op)
void OBJECT_OT_make_single_user(wmOperatorType *ot)
{
static EnumPropertyItem type_items[] = {
- {SELECT, "SELECTED_OBJECTS", 0, "Selected Objects", ""},
- {0, "ALL", 0, "All", ""},
+ {MAKE_SINGLE_USER_SELECTED, "SELECTED_OBJECTS", 0, "Selected Objects", ""},
+ {MAKE_SINGLE_USER_ALL, "ALL", 0, "All", ""},
{0, NULL, 0, NULL, NULL}};
/* identifiers */
@@ -2390,12 +2420,13 @@ void OBJECT_OT_make_single_user(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
/* properties */
- ot->prop = RNA_def_enum(ot->srna, "type", type_items, SELECT, "Type", "");
+ ot->prop = RNA_def_enum(ot->srna, "type", type_items, MAKE_SINGLE_USER_SELECTED, "Type", "");
RNA_def_boolean(ot->srna, "object", 0, "Object", "Make single user objects");
RNA_def_boolean(ot->srna, "obdata", 0, "Object Data", "Make single user object data");
RNA_def_boolean(ot->srna, "material", 0, "Materials", "Make materials local to each datablock");
- RNA_def_boolean(ot->srna, "texture", 0, "Textures", "Make textures local to each material");
+ RNA_def_boolean(ot->srna, "texture", 0, "Textures",
+ "Make textures local to each material (needs 'Materials' to be set too)");
RNA_def_boolean(ot->srna, "animation", 0, "Object Animation", "Make animation data local to each object");
}
@@ -2404,17 +2435,20 @@ static int drop_named_material_invoke(bContext *C, wmOperator *op, const wmEvent
Base *base = ED_view3d_give_base_under_cursor(C, event->mval);
Material *ma;
char name[MAX_ID_NAME - 2];
-
+
RNA_string_get(op->ptr, "name", name);
ma = (Material *)BKE_libblock_find_name(ID_MA, name);
if (base == NULL || ma == NULL)
return OPERATOR_CANCELLED;
-
+
assign_material(base->object, ma, 1, BKE_MAT_ASSIGN_USERPREF);
-
+
+ DAG_id_tag_update(&base->object->id, OB_RECALC_OB);
+
+ WM_event_add_notifier(C, NC_OBJECT | ND_OB_SHADING, base->object);
WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, CTX_wm_view3d(C));
WM_event_add_notifier(C, NC_MATERIAL | ND_SHADING_LINKS, ma);
-
+
return OPERATOR_FINISHED;
}
@@ -2422,19 +2456,18 @@ static int drop_named_material_invoke(bContext *C, wmOperator *op, const wmEvent
/* assigns to object under cursor, only first material slot */
void OBJECT_OT_drop_named_material(wmOperatorType *ot)
{
-
/* identifiers */
ot->name = "Drop Named Material on Object";
ot->description = "";
ot->idname = "OBJECT_OT_drop_named_material";
-
+
/* api callbacks */
ot->invoke = drop_named_material_invoke;
ot->poll = ED_operator_objectmode;
-
+
/* flags */
ot->flag = OPTYPE_UNDO | OPTYPE_INTERNAL;
-
+
/* properties */
RNA_def_string(ot->srna, "name", "Material", MAX_ID_NAME - 2, "Name", "Material name to assign");
}
@@ -2444,7 +2477,7 @@ static int object_unlink_data_exec(bContext *C, wmOperator *op)
ID *id;
PropertyPointerRNA pprop;
- uiIDContextProperty(C, &pprop.ptr, &pprop.prop);
+ UI_context_active_but_prop_get_templateID(C, &pprop.ptr, &pprop.prop);
if (pprop.prop == NULL) {
BKE_report(op->reports, RPT_ERROR, "Incorrect context for running object data unlink");
diff --git a/source/blender/editors/object/object_select.c b/source/blender/editors/object/object_select.c
index e295a63848a..83334e4e6a3 100644
--- a/source/blender/editors/object/object_select.c
+++ b/source/blender/editors/object/object_select.c
@@ -47,7 +47,7 @@
#include "BLI_rand.h"
#include "BLI_utildefines.h"
-#include "BLF_translation.h"
+#include "BLT_translation.h"
#include "BKE_context.h"
#include "BKE_group.h"
@@ -618,15 +618,15 @@ static bool select_grouped_group(bContext *C, Object *ob) /* Select objects in
}
/* build the menu. */
- pup = uiPupMenuBegin(C, IFACE_("Select Group"), ICON_NONE);
- layout = uiPupMenuLayout(pup);
+ pup = UI_popup_menu_begin(C, IFACE_("Select Group"), ICON_NONE);
+ layout = UI_popup_menu_layout(pup);
for (i = 0; i < group_count; i++) {
group = ob_groups[i];
uiItemStringO(layout, group->id.name + 2, 0, "OBJECT_OT_select_same_group", "group", group->id.name + 2);
}
- uiPupMenuEnd(C, pup);
+ UI_popup_menu_end(C, pup);
return changed; /* The operator already handle this! */
}
@@ -929,11 +929,16 @@ void OBJECT_OT_select_grouped(wmOperatorType *ot)
}
/************************* Select by Layer **********************/
+enum {
+ OB_SEL_LAYERMATCH_EXACT = 1,
+ OB_SEL_LAYERMATCH_SHARED = 2,
+};
static int object_select_by_layer_exec(bContext *C, wmOperator *op)
{
unsigned int layernum;
- bool extend, match;
+ bool extend;
+ int match;
extend = RNA_boolean_get(op->ptr, "extend");
layernum = RNA_int_get(op->ptr, "layers");
@@ -951,13 +956,21 @@ static int object_select_by_layer_exec(bContext *C, wmOperator *op)
{
bool ok = false;
- if (match == true) /* exact */
- ok = (base->lay == (1 << (layernum - 1)));
- else /* shared layers */
- ok = (base->lay & (1 << (layernum - 1))) != 0;
+ switch (match) {
+ case OB_SEL_LAYERMATCH_EXACT:
+ /* Mask out bits used for local view, only work on real layer ones, see T45783. */
+ ok = ((base->lay & ((1 << 20) - 1)) == (1 << (layernum - 1)));
+ break;
+ case OB_SEL_LAYERMATCH_SHARED:
+ ok = (base->lay & (1 << (layernum - 1))) != 0;
+ break;
+ default:
+ break;
+ }
- if (ok)
+ if (ok) {
ED_base_object_select(base, BA_SELECT);
+ }
}
CTX_DATA_END;
@@ -970,8 +983,8 @@ static int object_select_by_layer_exec(bContext *C, wmOperator *op)
void OBJECT_OT_select_by_layer(wmOperatorType *ot)
{
static EnumPropertyItem match_items[] = {
- {1, "EXACT", 0, "Exact Match", ""},
- {2, "SHARED", 0, "Shared Layers", ""},
+ {OB_SEL_LAYERMATCH_EXACT, "EXACT", 0, "Exact Match", ""},
+ {OB_SEL_LAYERMATCH_SHARED, "SHARED", 0, "Shared Layers", ""},
{0, NULL, 0, NULL, NULL}
};
@@ -989,7 +1002,7 @@ void OBJECT_OT_select_by_layer(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
/* properties */
- RNA_def_enum(ot->srna, "match", match_items, 0, "Match", "");
+ RNA_def_enum(ot->srna, "match", match_items, OB_SEL_LAYERMATCH_EXACT, "Match", "");
RNA_def_boolean(ot->srna, "extend", false, "Extend", "Extend selection instead of deselecting everything first");
RNA_def_int(ot->srna, "layers", 1, 1, 20, "Layer", "", 1, 20);
}
diff --git a/source/blender/editors/object/object_shapekey.c b/source/blender/editors/object/object_shapekey.c
index 85104c14395..ed71af71ac9 100644
--- a/source/blender/editors/object/object_shapekey.c
+++ b/source/blender/editors/object/object_shapekey.c
@@ -48,7 +48,6 @@
#include "DNA_lattice_types.h"
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
-#include "DNA_scene_types.h"
#include "DNA_object_types.h"
#include "BKE_context.h"
@@ -75,10 +74,10 @@
/*********************** add shape key ***********************/
-static void ED_object_shape_key_add(bContext *C, Scene *scene, Object *ob, const bool from_mix)
+static void ED_object_shape_key_add(bContext *C, Object *ob, const bool from_mix)
{
KeyBlock *kb;
- if ((kb = BKE_object_insert_shape_key(scene, ob, NULL, from_mix))) {
+ if ((kb = BKE_object_shapekey_insert(ob, NULL, from_mix))) {
Key *key = BKE_key_from_object(ob);
/* for absolute shape keys, new keys may not be added last */
ob->shapenr = BLI_findindex(&key->block, kb) + 1;
@@ -89,82 +88,21 @@ static void ED_object_shape_key_add(bContext *C, Scene *scene, Object *ob, const
/*********************** remove shape key ***********************/
-static bool ED_object_shape_key_remove_all(Main *bmain, Object *ob)
+static bool object_shapekey_remove(Main *bmain, Object *ob)
{
- Key *key;
+ KeyBlock *kb;
+ Key *key = BKE_key_from_object(ob);
- key = BKE_key_from_object(ob);
- if (key == NULL)
+ if (key == NULL) {
return false;
-
- switch (GS(key->from->name)) {
- case ID_ME: ((Mesh *)key->from)->key = NULL; break;
- case ID_CU: ((Curve *)key->from)->key = NULL; break;
- case ID_LT: ((Lattice *)key->from)->key = NULL; break;
}
- BKE_libblock_free_us(bmain, key);
-
- return true;
-}
-
-static bool ED_object_shape_key_remove(Main *bmain, Object *ob)
-{
- KeyBlock *kb, *rkb;
- Key *key;
-
- key = BKE_key_from_object(ob);
- if (key == NULL)
- return false;
-
kb = BLI_findlink(&key->block, ob->shapenr - 1);
-
if (kb) {
- for (rkb = key->block.first; rkb; rkb = rkb->next)
- if (rkb->relative == ob->shapenr - 1)
- rkb->relative = 0;
-
- BLI_remlink(&key->block, kb);
- key->totkey--;
- if (key->refkey == kb) {
- key->refkey = key->block.first;
-
- if (key->refkey) {
- /* apply new basis key on original data */
- switch (ob->type) {
- case OB_MESH:
- BKE_key_convert_to_mesh(key->refkey, ob->data);
- break;
- case OB_CURVE:
- case OB_SURF:
- BKE_key_convert_to_curve(key->refkey, ob->data, BKE_curve_nurbs_get(ob->data));
- break;
- case OB_LATTICE:
- BKE_key_convert_to_lattice(key->refkey, ob->data);
- break;
- }
- }
- }
-
- if (kb->data) MEM_freeN(kb->data);
- MEM_freeN(kb);
-
- if (ob->shapenr > 1) {
- ob->shapenr--;
- }
- }
-
- if (key->totkey == 0) {
- switch (GS(key->from->name)) {
- case ID_ME: ((Mesh *)key->from)->key = NULL; break;
- case ID_CU: ((Curve *)key->from)->key = NULL; break;
- case ID_LT: ((Lattice *)key->from)->key = NULL; break;
- }
-
- BKE_libblock_free_us(bmain, key);
+ return BKE_object_shapekey_remove(bmain, ob, kb);
}
- return true;
+ return false;
}
static bool object_shape_key_mirror(bContext *C, Object *ob,
@@ -301,6 +239,16 @@ static int shape_key_mode_exists_poll(bContext *C)
(BKE_keyblock_from_object(ob) != NULL);
}
+static int shape_key_move_poll(bContext *C)
+{
+ /* Same as shape_key_mode_exists_poll above, but ensure we have at least two shapes! */
+ Object *ob = ED_object_context(C);
+ ID *data = (ob) ? ob->data : NULL;
+ Key *key = BKE_key_from_object(ob);
+
+ return (ob && !ob->id.lib && data && !data->lib && ob->mode != OB_MODE_EDIT && key && key->totkey > 1);
+}
+
static int shape_key_poll(bContext *C)
{
Object *ob = ED_object_context(C);
@@ -310,11 +258,13 @@ static int shape_key_poll(bContext *C)
static int shape_key_add_exec(bContext *C, wmOperator *op)
{
- Scene *scene = CTX_data_scene(C);
Object *ob = ED_object_context(C);
const bool from_mix = RNA_boolean_get(op->ptr, "from_mix");
- ED_object_shape_key_add(C, scene, ob, from_mix);
+ ED_object_shape_key_add(C, ob, from_mix);
+
+ DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ DAG_relations_tag_update(CTX_data_main(C));
return OPERATOR_FINISHED;
}
@@ -344,14 +294,15 @@ static int shape_key_remove_exec(bContext *C, wmOperator *op)
bool changed = false;
if (RNA_boolean_get(op->ptr, "all")) {
- changed = ED_object_shape_key_remove_all(bmain, ob);
+ changed = BKE_object_shapekey_free(bmain, ob);
}
else {
- changed = ED_object_shape_key_remove(bmain, ob);
+ changed = object_shapekey_remove(bmain, ob);
}
if (changed) {
DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ DAG_relations_tag_update(CTX_data_main(C));
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
return OPERATOR_FINISHED;
@@ -369,7 +320,6 @@ void OBJECT_OT_shape_key_remove(wmOperatorType *ot)
ot->description = "Remove shape key from the object";
/* api callbacks */
- ot->poll = shape_key_mode_poll;
ot->poll = shape_key_mode_exists_poll;
ot->exec = shape_key_remove_exec;
@@ -482,86 +432,40 @@ void OBJECT_OT_shape_key_mirror(wmOperatorType *ot)
}
+enum {
+ KB_MOVE_TOP = -2,
+ KB_MOVE_UP = -1,
+ KB_MOVE_DOWN = 1,
+ KB_MOVE_BOTTOM = 2,
+};
+
static int shape_key_move_exec(bContext *C, wmOperator *op)
{
Object *ob = ED_object_context(C);
- Key *key = BKE_key_from_object(ob);
- if (!key) {
- return OPERATOR_CANCELLED;
+ Key *key = BKE_key_from_object(ob);
+ const int type = RNA_enum_get(op->ptr, "type");
+ const int totkey = key->totkey;
+ const int act_index = ob->shapenr - 1;
+ int new_index;
+
+ switch (type) {
+ case KB_MOVE_TOP:
+ /* Replace the ref key only if we're at the top already (only for relative keys) */
+ new_index = (ELEM(act_index, 0, 1) || key->type == KEY_NORMAL) ? 0 : 1;
+ break;
+ case KB_MOVE_BOTTOM:
+ new_index = totkey - 1;
+ break;
+ case KB_MOVE_UP:
+ case KB_MOVE_DOWN:
+ default:
+ new_index = (totkey + act_index + type) % totkey;
+ break;
}
- {
- KeyBlock *kb, *kb_other, *kb_iter;
- const int type = RNA_enum_get(op->ptr, "type");
- const int shape_tot = key->totkey;
- const int shapenr_act = ob->shapenr - 1;
- const int shapenr_swap = (shape_tot + shapenr_act + type) % shape_tot;
-
- kb = BLI_findlink(&key->block, shapenr_act);
- if (!kb || shape_tot == 1) {
- return OPERATOR_CANCELLED;
- }
-
- if (type == -1) {
- /* move back */
- kb_other = kb->prev;
- BLI_remlink(&key->block, kb);
- BLI_insertlinkbefore(&key->block, kb_other, kb);
- }
- else {
- /* move next */
- kb_other = kb->next;
- BLI_remlink(&key->block, kb);
- BLI_insertlinkafter(&key->block, kb_other, kb);
- }
-
- ob->shapenr = shapenr_swap + 1;
-
- /* for relative shape keys */
- if (kb_other) {
- for (kb_iter = key->block.first; kb_iter; kb_iter = kb_iter->next) {
- if (kb_iter->relative == shapenr_act) {
- kb_iter->relative = shapenr_swap;
- }
- else if (kb_iter->relative == shapenr_swap) {
- kb_iter->relative = shapenr_act;
- }
- }
- }
- /* First key became last, or vice-versa, we have to change all keys' relative value. */
- else {
- for (kb_iter = key->block.first; kb_iter; kb_iter = kb_iter->next) {
- if (kb_iter->relative == shapenr_act) {
- kb_iter->relative = shapenr_swap;
- }
- else {
- kb_iter->relative += type;
- }
- }
- }
-
- /* for absolute shape keys */
- if (kb_other) {
- SWAP(float, kb_other->pos, kb->pos);
- }
- /* First key became last, or vice-versa, we have to change all keys' pos value. */
- else {
- float pos = kb->pos;
- if (type == -1) {
- for (kb_iter = key->block.first; kb_iter; kb_iter = kb_iter->next) {
- SWAP(float, kb_iter->pos, pos);
- }
- }
- else {
- for (kb_iter = key->block.last; kb_iter; kb_iter = kb_iter->prev) {
- SWAP(float, kb_iter->pos, pos);
- }
- }
- }
-
- /* First key is refkey, matches interface and BKE_key_sort */
- key->refkey = key->block.first;
+ if (!BKE_keyblock_move(ob, act_index, new_index)) {
+ return OPERATOR_CANCELLED;
}
DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
@@ -573,9 +477,11 @@ static int shape_key_move_exec(bContext *C, wmOperator *op)
void OBJECT_OT_shape_key_move(wmOperatorType *ot)
{
static EnumPropertyItem slot_move[] = {
- {-1, "UP", 0, "Up", ""},
- {1, "DOWN", 0, "Down", ""},
- {0, NULL, 0, NULL, NULL}
+ {KB_MOVE_TOP, "TOP", 0, "Top", "Top of the list"},
+ {KB_MOVE_UP, "UP", 0, "Up", ""},
+ {KB_MOVE_DOWN, "DOWN", 0, "Down", ""},
+ {KB_MOVE_BOTTOM, "BOTTOM", 0, "Bottom", "Bottom of the list"},
+ { 0, NULL, 0, NULL, NULL }
};
/* identifiers */
@@ -584,7 +490,7 @@ void OBJECT_OT_shape_key_move(wmOperatorType *ot)
ot->description = "Move the active shape key up/down in the list";
/* api callbacks */
- ot->poll = shape_key_mode_poll;
+ ot->poll = shape_key_move_poll;
ot->exec = shape_key_move_exec;
/* flags */
diff --git a/source/blender/editors/object/object_transform.c b/source/blender/editors/object/object_transform.c
index a1b8478a0e1..340b662c0ef 100644
--- a/source/blender/editors/object/object_transform.c
+++ b/source/blender/editors/object/object_transform.c
@@ -33,9 +33,7 @@
#include "DNA_anim_types.h"
#include "DNA_armature_types.h"
-#include "DNA_key_types.h"
#include "DNA_mesh_types.h"
-#include "DNA_meshdata_types.h"
#include "DNA_meta_types.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
@@ -69,7 +67,6 @@
#include "ED_armature.h"
#include "ED_keyframing.h"
-#include "ED_mball.h"
#include "ED_mesh.h"
#include "ED_screen.h"
#include "ED_view3d.h"
@@ -942,8 +939,7 @@ static int object_origin_set_exec(bContext *C, wmOperator *op)
/* convert the offset to parent space */
BKE_object_to_mat4(ob, obmat);
- copy_v3_v3(centn, cent);
- mul_mat3_m4_v3(obmat, centn); /* omit translation part */
+ mul_v3_mat3_m4v3(centn, obmat, cent); /* omit translation part */
add_v3_v3(ob->loc, centn);
@@ -973,8 +969,7 @@ static int object_origin_set_exec(bContext *C, wmOperator *op)
ob_other->flag |= OB_DONE;
DAG_id_tag_update(&ob_other->id, OB_RECALC_OB | OB_RECALC_DATA);
- copy_v3_v3(centn, cent);
- mul_mat3_m4_v3(ob_other->obmat, centn); /* ommit translation part */
+ mul_v3_mat3_m4v3(centn, ob_other->obmat, cent); /* omit translation part */
add_v3_v3(ob_other->loc, centn);
BKE_object_where_is_calc(scene, ob_other);
diff --git a/source/blender/editors/object/object_vgroup.c b/source/blender/editors/object/object_vgroup.c
index 777bbabb6e8..352c90e805a 100644
--- a/source/blender/editors/object/object_vgroup.c
+++ b/source/blender/editors/object/object_vgroup.c
@@ -36,16 +36,13 @@
#include "MEM_guardedalloc.h"
-#include "DNA_cloth_types.h"
#include "DNA_curve_types.h"
#include "DNA_lattice_types.h"
#include "DNA_meshdata_types.h"
#include "DNA_mesh_types.h"
#include "DNA_modifier_types.h"
#include "DNA_object_types.h"
-#include "DNA_object_force.h"
#include "DNA_scene_types.h"
-#include "DNA_particle_types.h"
#include "BLI_alloca.h"
#include "BLI_array.h"
@@ -53,8 +50,8 @@
#include "BLI_blenlib.h"
#include "BLI_utildefines.h"
#include "BLI_linklist_stack.h"
+#include "BLI_stackdefines.h"
-#include "BLF_translation.h"
#include "BKE_context.h"
#include "BKE_customdata.h"
@@ -85,11 +82,6 @@
#include "object_intern.h"
/************************ Exported Functions **********************/
-static void vgroup_remap_update_users(Object *ob, int *map);
-static void vgroup_delete_edit_mode(Object *ob, bDeformGroup *defgroup);
-static void vgroup_delete_object_mode(Object *ob, bDeformGroup *dg);
-static void vgroup_delete_all(Object *ob);
-
static bool vertex_group_use_vert_sel(Object *ob)
{
if (ob->mode == OB_MODE_EDIT) {
@@ -126,81 +118,6 @@ bool ED_vgroup_sync_from_pose(Object *ob)
return false;
}
-bool ED_vgroup_object_is_edit_mode(Object *ob)
-{
- if (ob->type == OB_MESH)
- return (BKE_editmesh_from_object(ob) != NULL);
- else if (ob->type == OB_LATTICE)
- return (((Lattice *)ob->data)->editlatt != NULL);
-
- return false;
-}
-
-bDeformGroup *ED_vgroup_add_name(Object *ob, const char *name)
-{
- bDeformGroup *defgroup;
-
- if (!ob || !OB_TYPE_SUPPORT_VGROUP(ob->type))
- return NULL;
-
- defgroup = BKE_defgroup_new(ob, name);
-
- ob->actdef = BLI_countlist(&ob->defbase);
-
- return defgroup;
-}
-
-bDeformGroup *ED_vgroup_add(Object *ob)
-{
- return ED_vgroup_add_name(ob, DATA_("Group"));
-}
-
-void ED_vgroup_delete(Object *ob, bDeformGroup *defgroup)
-{
- BLI_assert(BLI_findindex(&ob->defbase, defgroup) != -1);
-
- if (ED_vgroup_object_is_edit_mode(ob))
- vgroup_delete_edit_mode(ob, defgroup);
- else
- vgroup_delete_object_mode(ob, defgroup);
-}
-
-void ED_vgroup_clear(Object *ob)
-{
- bDeformGroup *dg = (bDeformGroup *)ob->defbase.first;
- int edit_mode = ED_vgroup_object_is_edit_mode(ob);
-
- while (dg) {
- bDeformGroup *next_dg = dg->next;
-
- if (edit_mode)
- vgroup_delete_edit_mode(ob, dg);
- else
- vgroup_delete_object_mode(ob, dg);
-
- dg = next_dg;
- }
-}
-
-bool ED_vgroup_data_create(ID *id)
-{
- /* create deform verts */
-
- if (GS(id->name) == ID_ME) {
- Mesh *me = (Mesh *)id;
- me->dvert = CustomData_add_layer(&me->vdata, CD_MDEFORMVERT, CD_CALLOC, NULL, me->totvert);
- return true;
- }
- else if (GS(id->name) == ID_LT) {
- Lattice *lt = (Lattice *)id;
- lt->dvert = MEM_callocN(sizeof(MDeformVert) * lt->pntsu * lt->pntsv * lt->pntsw, "lattice deformVert");
- return true;
- }
- else {
- return false;
- }
-}
-
/**
* Removes out of range MDeformWeights
*/
@@ -327,34 +244,9 @@ bool ED_vgroup_parray_alloc(ID *id, MDeformVert ***dvert_arr, int *dvert_tot, co
return false;
}
-static bool ed_vgroup_dm_parray_alloc(DerivedMesh *dm, MDeformVert ***dvert_arr, int *dvert_tot)
-{
- *dvert_tot = 0;
- *dvert_arr = NULL;
-
- if (dm) {
- MDeformVert *dvert = dm->getVertDataArray(dm, CD_MDEFORMVERT);
-
- if (dvert) {
- int i, totvert = dm->getNumVerts(dm);
-
- *dvert_tot = totvert;
- *dvert_arr = MEM_mallocN(sizeof(void *) * totvert, "vgroup parray from me");
-
- for (i = 0; i < totvert; i++) {
- (*dvert_arr)[i] = dvert + i;
- }
-
- return true;
- }
- }
-
- return false;
-}
-
/**
* For use with tools that use ED_vgroup_parray_alloc with \a use_vert_sel == true.
- * This finds the unselected mirror deform verts and copys the weights to them from the selected.
+ * This finds the unselected mirror deform verts and copies the weights to them from the selected.
*
* \note \a dvert_array has mirrored weights filled in, incase cleanup operations are needed on both.
*/
@@ -465,34 +357,6 @@ void ED_vgroup_parray_remove_zero(MDeformVert **dvert_array, const int dvert_tot
}
}
-/* returns true if the id type supports weights */
-bool ED_vgroup_array_get(ID *id, MDeformVert **dvert_arr, int *dvert_tot)
-{
- if (id) {
- switch (GS(id->name)) {
- case ID_ME:
- {
- Mesh *me = (Mesh *)id;
- *dvert_arr = me->dvert;
- *dvert_tot = me->totvert;
- return true;
- }
- case ID_LT:
- {
- Lattice *lt = (Lattice *)id;
- lt = (lt->editlatt) ? lt->editlatt->latt : lt;
- *dvert_arr = lt->dvert;
- *dvert_tot = lt->pntsu * lt->pntsv * lt->pntsw;
- return true;
- }
- }
- }
-
- *dvert_arr = NULL;
- *dvert_tot = 0;
- return false;
-}
-
/* matching index only */
bool ED_vgroup_array_copy(Object *ob, Object *ob_from)
{
@@ -501,8 +365,8 @@ bool ED_vgroup_array_copy(Object *ob, Object *ob_from)
int dvert_tot_from;
int dvert_tot;
int i;
- int defbase_tot_from = BLI_countlist(&ob_from->defbase);
- int defbase_tot = BLI_countlist(&ob->defbase);
+ int defbase_tot_from = BLI_listbase_count(&ob_from->defbase);
+ int defbase_tot = BLI_listbase_count(&ob->defbase);
bool new_vgroup = false;
if (ob == ob_from)
@@ -511,7 +375,7 @@ bool ED_vgroup_array_copy(Object *ob, Object *ob_from)
ED_vgroup_parray_alloc(ob_from->data, &dvert_array_from, &dvert_tot_from, false);
ED_vgroup_parray_alloc(ob->data, &dvert_array, &dvert_tot, false);
- if ((dvert_array == NULL) && (dvert_array_from != NULL) && ED_vgroup_data_create(ob->data)) {
+ if ((dvert_array == NULL) && (dvert_array_from != NULL) && BKE_object_defgroup_data_create(ob->data)) {
ED_vgroup_parray_alloc(ob->data, &dvert_array, &dvert_tot, false);
new_vgroup = true;
}
@@ -523,7 +387,7 @@ bool ED_vgroup_array_copy(Object *ob, Object *ob_from)
if (new_vgroup == true) {
/* free the newly added vgroup since it wasn't compatible */
- vgroup_delete_all(ob);
+ BKE_object_defgroup_remove_all(ob);
}
/* if true: both are 0 and nothing needs changing, consider this a success */
@@ -541,7 +405,7 @@ bool ED_vgroup_array_copy(Object *ob, Object *ob_from)
for (i = 0; i <= defbase_tot_from; i++) remap[i] = i;
for (; i <= defbase_tot; i++) remap[i] = 0; /* can't use these, so disable */
- vgroup_remap_update_users(ob, remap);
+ BKE_object_defgroup_remap_update_users(ob, remap);
MEM_freeN(remap);
}
@@ -564,6 +428,48 @@ bool ED_vgroup_array_copy(Object *ob, Object *ob_from)
return true;
}
+void ED_vgroup_parray_to_weight_array(
+ const MDeformVert **dvert_array, const int dvert_tot,
+ float *dvert_weights, const int def_nr)
+{
+ int i;
+
+ for (i = 0; i < dvert_tot; i++) {
+ const MDeformVert *dv = dvert_array[i];
+ dvert_weights[i] = dv ? defvert_find_weight(dv, def_nr) : 0.0f;
+ }
+}
+
+void ED_vgroup_parray_from_weight_array(
+ MDeformVert **dvert_array, const int dvert_tot,
+ const float *dvert_weights, const int def_nr, const bool remove_zero)
+{
+ int i;
+
+ for (i = 0; i < dvert_tot; i++) {
+ MDeformVert *dv = dvert_array[i];
+ if (dv) {
+ if (dvert_weights[i] > 0.0f) {
+ MDeformWeight *dw = defvert_verify_index(dv, def_nr);
+ BLI_assert(IN_RANGE_INCL(dvert_weights[i], 0.0f, 1.0f));
+ dw->weight = dvert_weights[i];
+ }
+ else {
+ MDeformWeight *dw = defvert_find_index(dv, def_nr);
+ if (dw) {
+ if (remove_zero) {
+ defvert_remove_group(dv, dw);
+ }
+ else {
+ dw->weight = 0.0f;
+ }
+ }
+ }
+ }
+ }
+}
+
+
/* TODO, cache flip data to speedup calls within a loop. */
static void mesh_defvert_mirror_update_internal(Object *ob,
MDeformVert *dvert_dst, MDeformVert *dvert_src,
@@ -682,7 +588,7 @@ static void vgroup_normalize_active(Object *ob, eVGroupSelect subset_type)
return;
}
- vgroup_validmap = ED_vgroup_subset_from_select_type(ob, subset_type, &vgroup_tot, &subset_count);
+ vgroup_validmap = BKE_object_defgroup_subset_from_select_type(ob, subset_type, &vgroup_tot, &subset_count);
defvert_normalize_subset(dvert_act, vgroup_validmap, vgroup_tot);
MEM_freeN((void *)vgroup_validmap);
@@ -703,7 +609,7 @@ static void vgroup_copy_active_to_sel(Object *ob, eVGroupSelect subset_type)
BMEditMesh *em = me->edit_btmesh;
MDeformVert *dvert_act;
int i, vgroup_tot, subset_count;
- const bool *vgroup_validmap = ED_vgroup_subset_from_select_type(ob, subset_type, &vgroup_tot, &subset_count);
+ const bool *vgroup_validmap = BKE_object_defgroup_subset_from_select_type(ob, subset_type, &vgroup_tot, &subset_count);
if (em) {
@@ -747,51 +653,6 @@ static void vgroup_copy_active_to_sel(Object *ob, eVGroupSelect subset_type)
/***********************Start weight transfer (WT)*********************************/
-typedef enum WT_VertexGroupMode {
- WT_REPLACE_ACTIVE_VERTEX_GROUP = 1,
- WT_REPLACE_ALL_VERTEX_GROUPS = 2
-} WT_VertexGroupMode;
-
-typedef enum WT_Method {
- WT_BY_INDEX = 1,
- WT_BY_NEAREST_VERTEX = 2,
- WT_BY_NEAREST_FACE = 3,
- WT_BY_NEAREST_VERTEX_IN_FACE = 4
-} WT_Method;
-
-typedef enum WT_ReplaceMode {
- WT_REPLACE_ALL_WEIGHTS = 1,
- WT_REPLACE_EMPTY_WEIGHTS = 2
-} WT_ReplaceMode;
-
-static EnumPropertyItem WT_vertex_group_mode_item[] = {
- {WT_REPLACE_ACTIVE_VERTEX_GROUP,
- "WT_REPLACE_ACTIVE_VERTEX_GROUP", 0, "Active", "Transfer active vertex group from selected to active mesh"},
- {WT_REPLACE_ALL_VERTEX_GROUPS,
- "WT_REPLACE_ALL_VERTEX_GROUPS", 0, "All", "Transfer all vertex groups from selected to active mesh"},
- {0, NULL, 0, NULL, NULL}
-};
-
-static EnumPropertyItem WT_method_item[] = {
- {WT_BY_INDEX,
- "WT_BY_INDEX", 0, "Vertex index", "Copy for identical meshes"},
- {WT_BY_NEAREST_VERTEX,
- "WT_BY_NEAREST_VERTEX", 0, "Nearest vertex", "Copy weight from closest vertex"},
- {WT_BY_NEAREST_FACE,
- "WT_BY_NEAREST_FACE", 0, "Nearest face", "Barycentric interpolation from nearest face"},
- {WT_BY_NEAREST_VERTEX_IN_FACE,
- "WT_BY_NEAREST_VERTEX_IN_FACE", 0, "Nearest vertex in face", "Copy weight from closest vertex in nearest face"},
- {0, NULL, 0, NULL, NULL}
-};
-
-static EnumPropertyItem WT_replace_mode_item[] = {
- {WT_REPLACE_ALL_WEIGHTS,
- "WT_REPLACE_ALL_WEIGHTS", 0, "All", "Overwrite all weights"},
- {WT_REPLACE_EMPTY_WEIGHTS,
- "WT_REPLACE_EMPTY_WEIGHTS", 0, "Empty", "Add weights to vertices with no weight"},
- {0, NULL, 0, NULL, NULL}
-};
-
static EnumPropertyItem WT_vertex_group_select_item[] = {
{WT_VGROUP_ACTIVE,
"ACTIVE", 0, "Active Group", "The active Vertex Group"},
@@ -867,298 +728,6 @@ static void vgroup_operator_subset_select_props(wmOperatorType *ot, bool use_act
ot->prop = prop;
}
-/* Copy weight.*/
-static void vgroup_transfer_weight(float *r_weight_dst, const float weight_src, const WT_ReplaceMode replace_mode)
-{
- switch (replace_mode) {
- case WT_REPLACE_ALL_WEIGHTS:
- *r_weight_dst = weight_src;
- break;
-
- case WT_REPLACE_EMPTY_WEIGHTS:
- if (*r_weight_dst == 0.0f) {
- *r_weight_dst = weight_src;
- }
- break;
-
- default:
- BLI_assert(0);
- break;
- }
-}
-
-/* Could be exposed externally by implementing it in header with the rest.
- * Simple refactoring will break something.
- * For now, naming is ed_ instead of ED_*/
-static bool ed_vgroup_transfer_weight(Object *ob_dst, Object *ob_src, bDeformGroup *dg_src, Scene *scene,
- WT_Method method, WT_ReplaceMode replace_mode, wmOperator *op)
-{
- bDeformGroup *dg_dst;
- Mesh *me_dst;
- DerivedMesh *dmesh_src;
- BVHTreeFromMesh tree_mesh_vertices_src, tree_mesh_faces_src = {NULL};
- MDeformVert **dv_array_src, **dv_array_dst, **dv_src, **dv_dst;
- MVert *mv_dst, *mv_src;
- MFace *mface_src, *mf;
- BVHTreeNearest nearest;
- MDeformWeight *dw_dst, *dw_src;
- int dv_tot_src, dv_tot_dst, i, v_index, index_dst, index_src, index_nearest, index_nearest_vertex;
- unsigned int f_index;
- float weight, tmp_weight[4], tmp_co[3], normal[3], tmp_mat[4][4], dist_v1, dist_v2, dist_v3, dist_v4;
- const int use_vert_sel = vertex_group_use_vert_sel(ob_dst);
- bool is_dg_dst_new = false;
-
- /* Ensure vertex group on target.*/
- if ((dg_dst = defgroup_find_name(ob_dst, dg_src->name)) == NULL) {
- dg_dst = BKE_defgroup_new(ob_dst, dg_src->name);
- is_dg_dst_new = true;
- }
-
- /* Get meshes.*/
- dmesh_src = mesh_get_derived_final(scene, ob_src, CD_MASK_BAREMESH | CD_MASK_MDEFORMVERT);
- me_dst = ob_dst->data;
-
- /* Get vertex group array from source mesh */
- if (!ed_vgroup_dm_parray_alloc(dmesh_src, &dv_array_src, &dv_tot_src)) {
- BKE_report(op->reports, RPT_ERROR, "Transfer failed (source mesh does not have any vertex groups)");
- return false;
- }
-
- /* Create data in memory when nothing there.*/
- if (!me_dst->dvert) ED_vgroup_data_create(&me_dst->id);
-
- /* Get vertex group for destination mesh */
- ED_vgroup_parray_alloc(&me_dst->id, &dv_array_dst, &dv_tot_dst, use_vert_sel);
-
- /* Get indexes of vertex groups.*/
- index_src = BLI_findindex(&ob_src->defbase, dg_src);
- index_dst = BLI_findindex(&ob_dst->defbase, dg_dst);
-
- /* Get vertices.*/
- mv_dst = me_dst->mvert;
- mv_src = dmesh_src->getVertArray(dmesh_src);
-
- /* Prepare transformation matrix.*/
- invert_m4_m4(ob_src->imat, ob_src->obmat);
- mul_m4_m4m4(tmp_mat, ob_src->imat, ob_dst->obmat);
-
- /* Clear weights.*/
- if (replace_mode == WT_REPLACE_ALL_WEIGHTS) {
- for (i = 0, dv_dst = dv_array_dst; i < me_dst->totvert; i++, dv_dst++) {
-
- if (*dv_dst == NULL) continue;
-
- dw_dst = defvert_find_index(*dv_dst, index_dst);
- /* Remove vertex from group.*/
- if (dw_dst) defvert_remove_group(*dv_dst, dw_dst);
- }
- }
-
- switch (method) {
-
- case WT_BY_INDEX:
- /* Check if indices are matching, delete and return if not.*/
- if (ob_dst == ob_src || dv_tot_dst == 0 || dv_tot_dst != dv_tot_src ||
- dv_array_src == NULL || dv_array_dst == NULL)
- {
- if (is_dg_dst_new) {
- ED_vgroup_delete(ob_dst, dg_dst);
- }
-
- if (dv_array_src) MEM_freeN(dv_array_src);
- if (dv_array_dst) MEM_freeN(dv_array_dst);
- dmesh_src->release(dmesh_src);
- BKE_report(op->reports, RPT_ERROR, "Transfer failed (indices are not matching)");
- return false;
- }
-
- /* Loop through the vertices.*/
- for (i = 0, dv_src = dv_array_src, dv_dst = dv_array_dst;
- i < me_dst->totvert;
- i++, dv_dst++, dv_src++, mv_src++, mv_dst++)
- {
-
- if (*dv_dst == NULL) {
- continue;
- }
-
- /* Copy weight.*/
- dw_src = defvert_find_index(*dv_src, index_src);
- if (dw_src && dw_src->weight) {
- dw_dst = defvert_verify_index(*dv_dst, index_dst);
- vgroup_transfer_weight(&dw_dst->weight, dw_src->weight, replace_mode);
- }
- }
- break;
-
- case WT_BY_NEAREST_VERTEX:
- /* Make node tree.*/
- bvhtree_from_mesh_verts(&tree_mesh_vertices_src, dmesh_src, FLT_EPSILON, 2, 6);
-
- /* Loop trough vertices.*/
- for (i = 0, dv_dst = dv_array_dst; i < me_dst->totvert; i++, dv_dst++, mv_dst++) {
-
- if (*dv_dst == NULL) {
- continue;
- }
-
- /* Reset nearest.*/
- nearest.dist_sq = FLT_MAX;
- /* It is faster to start searching at the top of the tree instead of previous search result.*/
- nearest.index = -1;
-
- /* Transform into target space.*/
- mul_v3_m4v3(tmp_co, tmp_mat, mv_dst->co);
-
- /* Node tree accelerated search for closest vetex.*/
- BLI_bvhtree_find_nearest(tree_mesh_vertices_src.tree, tmp_co,
- &nearest, tree_mesh_vertices_src.nearest_callback, &tree_mesh_vertices_src);
-
- /* Copy weight that are not NULL including weight value 0. In relevant cases, existing weights are
- * overwritten prior to this. See the "Clear weights." step above.*/
- dw_src = defvert_find_index(dv_array_src[nearest.index], index_src);
- if (dw_src && dw_src->weight) {
- dw_dst = defvert_verify_index(*dv_dst, index_dst);
- vgroup_transfer_weight(&dw_dst->weight, dw_src->weight, replace_mode);
- }
- }
-
- /* Free memory.*/
- free_bvhtree_from_mesh(&tree_mesh_vertices_src);
- break;
-
- case WT_BY_NEAREST_FACE:
- /* Get faces.*/
- DM_ensure_tessface(dmesh_src);
- mface_src = dmesh_src->getTessFaceArray(dmesh_src);
-
- /* Make node tree.*/
- bvhtree_from_mesh_faces(&tree_mesh_faces_src, dmesh_src, FLT_EPSILON, 2, 6);
-
- /* Loop through the vertices.*/
- for (i = 0, dv_dst = dv_array_dst; i < me_dst->totvert; i++, dv_dst++, mv_dst++) {
-
- if (*dv_dst == NULL) {
- continue;
- }
-
- /* Reset nearest.*/
- nearest.dist_sq = FLT_MAX;
- /* It is faster to start searching at the top of the tree instead of previous search result.*/
- nearest.index = -1;
-
- /* Transform into target space.*/
- mul_v3_m4v3(tmp_co, tmp_mat, mv_dst->co);
-
- /* Node tree accelerated search for closest face.*/
- BLI_bvhtree_find_nearest(tree_mesh_faces_src.tree, tmp_co,
- &nearest, tree_mesh_faces_src.nearest_callback, &tree_mesh_faces_src);
- index_nearest = nearest.index;
-
- /* Project onto face.*/
- mf = &mface_src[index_nearest];
- normal_tri_v3(normal, mv_src[mf->v1].co, mv_src[mf->v2].co, mv_src[mf->v3].co);
- project_v3_plane(tmp_co, normal, mv_src[mf->v1].co);
-
- /* Interpolate weights over face.*/
- interp_weights_face_v3(tmp_weight,
- mv_src[mf->v1].co,
- mv_src[mf->v2].co,
- mv_src[mf->v3].co,
- mf->v4 ? mv_src[mf->v4].co : NULL,
- tmp_co);
-
- /* Get weights from face.*/
- f_index = mf->v4 ? 3 : 2;
- weight = 0.0f;
- do {
- v_index = (&mf->v1)[f_index];
- weight += tmp_weight[f_index] * defvert_find_weight(dv_array_src[v_index], index_src);
- } while (f_index--);
-
- /* Copy weight that are not NULL including weight value 0. In relevant cases, existing weights are
- * overwritten prior to this. See the "Clear weights." step above.*/
- if (weight > 0.0f) {
- dw_dst = defvert_verify_index(*dv_dst, index_dst);
- vgroup_transfer_weight(&dw_dst->weight, weight, replace_mode);
- }
- }
-
- /* Free memory.*/
- free_bvhtree_from_mesh(&tree_mesh_faces_src);
- break;
-
- case WT_BY_NEAREST_VERTEX_IN_FACE:
- /* Get faces.*/
- DM_ensure_tessface(dmesh_src);
- mface_src = dmesh_src->getTessFaceArray(dmesh_src);
-
- /* Make node tree.*/
- bvhtree_from_mesh_faces(&tree_mesh_faces_src, dmesh_src, FLT_EPSILON, 2, 6);
-
- /* Loop through the vertices.*/
- for (i = 0, dv_dst = dv_array_dst; i < me_dst->totvert; i++, dv_dst++, mv_dst++) {
-
- if (*dv_dst == NULL) {
- continue;
- }
-
- /* Reset nearest.*/
- nearest.dist_sq = FLT_MAX;
- /* It is faster to start searching at the top of the tree instead of previous search result.*/
- nearest.index = -1;
-
- /* Transform into target space.*/
- mul_v3_m4v3(tmp_co, tmp_mat, mv_dst->co);
-
- /* Node tree accelerated search for closest face.*/
- BLI_bvhtree_find_nearest(tree_mesh_faces_src.tree, tmp_co,
- &nearest, tree_mesh_faces_src.nearest_callback, &tree_mesh_faces_src);
- index_nearest = nearest.index;
-
- /* Get distances.*/
- mf = &mface_src[index_nearest];
- dist_v1 = len_squared_v3v3(tmp_co, mv_src[mf->v1].co);
- dist_v2 = len_squared_v3v3(tmp_co, mv_src[mf->v2].co);
- dist_v3 = len_squared_v3v3(tmp_co, mv_src[mf->v3].co);
-
- /* Get closest vertex.*/
- f_index = mf->v4 ? 3 : 2;
- if (dist_v1 < dist_v2 && dist_v1 < dist_v3) index_nearest_vertex = mf->v1;
- else if (dist_v2 < dist_v3) index_nearest_vertex = mf->v2;
- else index_nearest_vertex = mf->v3;
- if (f_index == 3) {
- dist_v4 = len_squared_v3v3(tmp_co, mv_src[mf->v4].co);
- if (dist_v4 < dist_v1 && dist_v4 < dist_v2 && dist_v4 < dist_v3) {
- index_nearest_vertex = mf->v4;
- }
- }
-
- /* Copy weight that are not NULL including weight value 0. In relevant cases, existing weights are
- * overwritten prior to this. See the "Clear weights." step above.*/
- dw_src = defvert_find_index(dv_array_src[index_nearest_vertex], index_src);
- if (dw_src && dw_src->weight) {
- dw_dst = defvert_verify_index(*dv_dst, index_dst);
- vgroup_transfer_weight(&dw_dst->weight, dw_src->weight, replace_mode);
- }
- }
-
- /* Free memory.*/
- free_bvhtree_from_mesh(&tree_mesh_faces_src);
- break;
-
- default:
- BLI_assert(0);
- break;
- }
-
- /* Free memory.*/
- if (dv_array_src) MEM_freeN(dv_array_src);
- if (dv_array_dst) MEM_freeN(dv_array_dst);
- dmesh_src->release(dmesh_src);
-
- return true;
-}
/***********************End weight transfer (WT)***********************************/
@@ -1175,7 +744,7 @@ static void ED_vgroup_nr_vert_add(Object *ob,
int tot;
/* get the vert */
- ED_vgroup_array_get(ob->data, &dvert, &tot);
+ BKE_object_defgroup_array_get(ob->data, &dvert, &tot);
if (dvert == NULL)
return;
@@ -1208,7 +777,7 @@ static void ED_vgroup_nr_vert_add(Object *ob,
break;
case WEIGHT_SUBTRACT:
dw->weight -= weight;
- /* if the weight is zero or less then
+ /* if the weight is zero or less than
* remove the vert from the deform group
*/
if (dw->weight <= 0.0f) {
@@ -1261,8 +830,8 @@ void ED_vgroup_vert_add(Object *ob, bDeformGroup *dg, int vertnum, float weight,
/* if there's no deform verts then create some,
*/
- if (ED_vgroup_array_get(ob->data, &dv, &tot) && dv == NULL)
- ED_vgroup_data_create(ob->data);
+ if (BKE_object_defgroup_array_get(ob->data, &dv, &tot) && dv == NULL)
+ BKE_object_defgroup_data_create(ob->data);
/* call another function to do the work
*/
@@ -1287,7 +856,7 @@ void ED_vgroup_vert_remove(Object *ob, bDeformGroup *dg, int vertnum)
/* get the deform vertices corresponding to the
* vertnum
*/
- ED_vgroup_array_get(ob->data, &dvert, &tot);
+ BKE_object_defgroup_array_get(ob->data, &dvert, &tot);
if (dvert) {
MDeformVert *dv = &dvert[vertnum];
@@ -1476,7 +1045,7 @@ static void vgroup_duplicate(Object *ob)
BLI_addtail(&ob->defbase, cdg);
idg = (ob->actdef - 1);
- ob->actdef = BLI_countlist(&ob->defbase);
+ ob->actdef = BLI_listbase_count(&ob->defbase);
icdg = (ob->actdef - 1);
/* TODO, we might want to allow only copy selected verts here? - campbell */
@@ -1498,86 +1067,6 @@ static void vgroup_duplicate(Object *ob)
}
}
-/**
- * Return the subset type of the Vertex Group Selection
- */
-bool *ED_vgroup_subset_from_select_type(Object *ob, eVGroupSelect subset_type, int *r_vgroup_tot, int *r_subset_count)
-{
- bool *vgroup_validmap = NULL;
- *r_vgroup_tot = BLI_countlist(&ob->defbase);
-
- switch (subset_type) {
- case WT_VGROUP_ACTIVE:
- {
- const int def_nr_active = ob->actdef - 1;
- vgroup_validmap = MEM_mallocN(*r_vgroup_tot * sizeof(*vgroup_validmap), __func__);
- memset(vgroup_validmap, false, *r_vgroup_tot * sizeof(*vgroup_validmap));
- if ((def_nr_active >= 0) && (def_nr_active < *r_vgroup_tot)) {
- *r_subset_count = 1;
- vgroup_validmap[def_nr_active] = true;
- }
- else {
- *r_subset_count = 0;
- }
- break;
- }
- case WT_VGROUP_BONE_SELECT:
- {
- vgroup_validmap = BKE_objdef_selected_get(ob, *r_vgroup_tot, r_subset_count);
- break;
- }
- case WT_VGROUP_BONE_DEFORM:
- {
- int i;
- vgroup_validmap = BKE_objdef_validmap_get(ob, *r_vgroup_tot);
- *r_subset_count = 0;
- for (i = 0; i < *r_vgroup_tot; i++) {
- if (vgroup_validmap[i] == true) {
- *r_subset_count += 1;
- }
- }
- break;
- }
- case WT_VGROUP_BONE_DEFORM_OFF:
- {
- int i;
- vgroup_validmap = BKE_objdef_validmap_get(ob, *r_vgroup_tot);
- *r_subset_count = 0;
- for (i = 0; i < *r_vgroup_tot; i++) {
- vgroup_validmap[i] = !vgroup_validmap[i];
- if (vgroup_validmap[i] == true) {
- *r_subset_count += 1;
- }
- }
- break;
- }
- case WT_VGROUP_ALL:
- default:
- {
- vgroup_validmap = MEM_mallocN(*r_vgroup_tot * sizeof(*vgroup_validmap), __func__);
- memset(vgroup_validmap, true, *r_vgroup_tot * sizeof(*vgroup_validmap));
- *r_subset_count = *r_vgroup_tot;
- break;
- }
- }
-
- return vgroup_validmap;
-}
-
-/**
- * store indices from the vgroup_validmap (faster lookups in some cases)
- */
-void ED_vgroup_subset_to_index_array(const bool *vgroup_validmap, const int vgroup_tot,
- int *r_vgroup_subset_map)
-{
- int i, j = 0;
- for (i = 0; i < vgroup_tot; i++) {
- if (vgroup_validmap[i]) {
- r_vgroup_subset_map[j++] = i;
- }
- }
-}
-
static void vgroup_normalize(Object *ob)
{
MDeformWeight *dw;
@@ -1724,14 +1213,14 @@ static void getVerticalAndHorizontalChange(const float norm[3], float d, const f
plane_from_point_normal_v3(plane, coord, norm);
- closest_to_plane_v3(projA, plane, start);
- closest_to_plane_v3(projB, plane, end);
+ closest_to_plane_normalized_v3(projA, plane, start);
+ closest_to_plane_normalized_v3(projB, plane, end);
/* (vertical and horizontal refer to the plane's y and xz respectively)
* vertical distance */
dists[index] = dot_v3v3(norm, end) + d;
/* vertical change */
changes[index][0] = dists[index] - distToStart;
- //printf("vc %f %f\n", distance(end, projB, 3)-distance(start, projA, 3), changes[index][0]);
+ //printf("vc %f %f\n", distance(end, projB, 3) - distance(start, projA, 3), changes[index][0]);
/* horizontal change */
changes[index][1] = len_v3v3(projA, projB);
}
@@ -2051,8 +1540,8 @@ static void vgroup_normalize_all(Object *ob,
ED_vgroup_parray_alloc(ob->data, &dvert_array, &dvert_tot, use_vert_sel);
if (dvert_array) {
- const int defbase_tot = BLI_countlist(&ob->defbase);
- bool *lock_flags = BKE_objdef_lock_flags_get(ob, defbase_tot);
+ const int defbase_tot = BLI_listbase_count(&ob->defbase);
+ bool *lock_flags = BKE_object_defgroup_lock_flags_get(ob, defbase_tot);
if ((lock_active == true) &&
(lock_flags != NULL) &&
@@ -2185,9 +1674,17 @@ static void vgroup_invert_subset(Object *ob,
}
}
-static void vgroup_blend_subset(Object *ob, const bool *vgroup_validmap, const int vgroup_tot,
- const int subset_count,
- const float fac)
+enum {
+ WEIGHT_SMOOTH_ALL = -1,
+ WEIGHT_SMOOTH_DESELECT = false,
+ WEIGHT_SMOOTH_SELECT = true,
+};
+
+static void vgroup_smooth_subset(
+ Object *ob, const bool *vgroup_validmap, const int vgroup_tot,
+ const int subset_count,
+ const float fac, const int repeat,
+ const float fac_expand, const int source)
{
const float ifac = 1.0f - fac;
MDeformVert **dvert_array = NULL;
@@ -2196,102 +1693,186 @@ static void vgroup_blend_subset(Object *ob, const bool *vgroup_validmap, const i
float *vgroup_subset_weights = BLI_array_alloca(vgroup_subset_weights, subset_count);
const bool use_mirror = (ob->type == OB_MESH) ? (((Mesh *)ob->data)->editflag & ME_EDIT_MIRROR_X) != 0 : false;
+ const int expand_sign = signum_i(fac_expand);
+ const float expand = fabsf(fac_expand);
+ const float iexpand = 1.0f - expand;
+
BMEditMesh *em = BKE_editmesh_from_object(ob);
BMesh *bm = em ? em->bm : NULL;
Mesh *me = em ? NULL : ob->data;
- MeshElemMap *emap ;
+ MeshElemMap *emap;
int *emap_mem;
- BLI_SMALLSTACK_DECLARE(dv_stack, MDeformVert *);
+ float *weight_accum_prev;
+ float *weight_accum_curr;
+
+ unsigned int subset_index;
+
+ /* vertex indices that will be smoothed, (only to avoid iterating over verts that do nothing) */
+ unsigned int *verts_used;
+ STACK_DECLARE(verts_used);
- ED_vgroup_subset_to_index_array(vgroup_validmap, vgroup_tot, vgroup_subset_map);
+
+ BKE_object_defgroup_subset_to_index_array(vgroup_validmap, vgroup_tot, vgroup_subset_map);
ED_vgroup_parray_alloc(ob->data, &dvert_array, &dvert_tot, false);
memset(vgroup_subset_weights, 0, sizeof(*vgroup_subset_weights) * subset_count);
if (bm) {
BM_mesh_elem_table_ensure(bm, BM_VERT);
+ BM_mesh_elem_index_ensure(bm, BM_VERT);
emap = NULL;
emap_mem = NULL;
}
else {
- BKE_mesh_vert_edge_map_create(&emap, &emap_mem,
- me->medge, me->totvert, me->totedge);
+ BKE_mesh_vert_edge_map_create(&emap, &emap_mem, me->medge, me->totvert, me->totedge);
}
+ weight_accum_prev = MEM_mallocN(sizeof(*weight_accum_prev) * dvert_tot, __func__);
+ weight_accum_curr = MEM_mallocN(sizeof(*weight_accum_curr) * dvert_tot, __func__);
+
+ verts_used = MEM_mallocN(sizeof(*verts_used) * dvert_tot, __func__);
+ STACK_INIT(verts_used, dvert_tot);
- for (i = 0; i < dvert_tot; i++) {
- MDeformVert *dv;
- int dv_stack_tot = 0;
- int j;
- /* in case its not selected */
- if (bm) {
+ /* initialize used verts */
+ if (bm) {
+ for (i = 0; i < dvert_tot; i++) {
BMVert *v = BM_vert_at_index(bm, i);
if (BM_elem_flag_test(v, BM_ELEM_SELECT)) {
BMIter eiter;
BMEdge *e;
BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) {
BMVert *v_other = BM_edge_other_vert(e, v);
- const int i_other = BM_elem_index_get(v_other);
-
- if (BM_elem_flag_test(v_other, BM_ELEM_SELECT) == 0) {
- dv = dvert_array[i_other];
- BLI_SMALLSTACK_PUSH(dv_stack, dv);
- dv_stack_tot++;
+ if ((source == WEIGHT_SMOOTH_ALL) ||
+ (source == (BM_elem_flag_test(v_other, BM_ELEM_SELECT) != 0)))
+ {
+ STACK_PUSH(verts_used, i);
+ break;
}
}
}
}
- else {
+ }
+ else {
+ for (i = 0; i < dvert_tot; i++) {
MVert *v = &me->mvert[i];
if (v->flag & SELECT) {
+ int j;
for (j = 0; j < emap[i].count; j++) {
MEdge *e = &me->medge[emap[i].indices[j]];
const int i_other = (e->v1 == i ? e->v2 : e->v1);
MVert *v_other = &me->mvert[i_other];
-
- if ((v_other->flag & SELECT) == 0) {
- dv = dvert_array[i_other];
- BLI_SMALLSTACK_PUSH(dv_stack, dv);
- dv_stack_tot++;
+ if ((source == WEIGHT_SMOOTH_ALL) ||
+ (source == ((v_other->flag & SELECT) != 0)))
+ {
+ STACK_PUSH(verts_used, i);
+ break;
}
}
}
}
+ }
- if (dv_stack_tot) {
- const float dv_mul = 1.0f / (float)dv_stack_tot;
+ for (subset_index = 0; subset_index < subset_count; subset_index++) {
+ const int def_nr = vgroup_subset_map[subset_index];
+ int iter;
- /* vgroup_subset_weights is zero'd at this point */
- while ((dv = BLI_SMALLSTACK_POP(dv_stack))) {
- for (j = 0; j < subset_count; j++) {
- vgroup_subset_weights[j] += dv_mul * defvert_find_weight(dv, vgroup_subset_map[j]);
- }
- }
+ ED_vgroup_parray_to_weight_array((const MDeformVert **)dvert_array, dvert_tot, weight_accum_prev, def_nr);
+ memcpy(weight_accum_curr, weight_accum_prev, sizeof(*weight_accum_curr) * dvert_tot);
- dv = dvert_array[i];
- for (j = 0; j < subset_count; j++) {
- MDeformWeight *dw;
- if (vgroup_subset_weights[j] > 0.0f) {
- dw = defvert_verify_index(dv, vgroup_subset_map[j]);
+ for (iter = 0; iter < repeat; iter++) {
+ unsigned *vi_step, *vi_end = verts_used + STACK_SIZE(verts_used);
+
+ /* avoid looping over all verts */
+ // for (i = 0; i < dvert_tot; i++)
+ for (vi_step = verts_used; vi_step != vi_end; vi_step++) {
+ const unsigned int i = *vi_step;
+ float weight_tot = 0.0f;
+ float weight = 0.0f;
+
+#define WEIGHT_ACCUMULATE \
+ { \
+ float weight_other = weight_accum_prev[i_other]; \
+ float tot_factor = 1.0f; \
+ if (expand_sign == 1) { /* expand */ \
+ if (weight_other < weight_accum_prev[i]) { \
+ weight_other = (weight_accum_prev[i_other] * iexpand) + (weight_other * expand); \
+ tot_factor = iexpand; \
+ } \
+ } \
+ else if (expand_sign == -1) { /* contract */ \
+ if (weight_other > weight_accum_prev[i]) { \
+ weight_other = (weight_accum_prev[i_other] * iexpand) + (weight_other * expand); \
+ tot_factor = iexpand; \
+ } \
+ } \
+ weight += tot_factor * weight_other; \
+ weight_tot += tot_factor; \
+ } ((void)0)
+
+
+ if (bm) {
+ BMVert *v = BM_vert_at_index(bm, i);
+ BMIter eiter;
+ BMEdge *e;
+
+ /* checked already */
+ BLI_assert(BM_elem_flag_test(v, BM_ELEM_SELECT));
+
+ BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) {
+ BMVert *v_other = BM_edge_other_vert(e, v);
+ if ((source == WEIGHT_SMOOTH_ALL) ||
+ (source == (BM_elem_flag_test(v_other, BM_ELEM_SELECT) != 0)))
+ {
+ const int i_other = BM_elem_index_get(v_other);
+
+ WEIGHT_ACCUMULATE;
+ }
+ }
}
else {
- dw = defvert_find_index(dv, vgroup_subset_map[j]);
- }
+ int j;
- if (dw) {
- dw->weight = (fac * vgroup_subset_weights[j]) + (ifac * dw->weight);
- CLAMP(dw->weight, 0.0f, 1.0f);
+ /* checked already */
+ BLI_assert(me->mvert[i].flag & SELECT);
+
+ for (j = 0; j < emap[i].count; j++) {
+ MEdge *e = &me->medge[emap[i].indices[j]];
+ const int i_other = (e->v1 == i ? e->v2 : e->v1);
+ MVert *v_other = &me->mvert[i_other];
+
+ if ((source == WEIGHT_SMOOTH_ALL) ||
+ (source == ((v_other->flag & SELECT) != 0)))
+ {
+ WEIGHT_ACCUMULATE;
+ }
+ }
}
- /* zero for next iteration */
- vgroup_subset_weights[j] = 0.0f;
+#undef WEIGHT_ACCUMULATE
+
+ if (weight_tot != 0.0f) {
+ weight /= weight_tot;
+ weight = (weight_accum_prev[i] * ifac) + (weight * fac);
+
+ /* should be within range, just clamp because of float precision */
+ CLAMP(weight, 0.0f, 1.0f);
+ weight_accum_curr[i] = weight;
+ }
}
+
+ SWAP(float *, weight_accum_curr, weight_accum_prev);
}
+
+ ED_vgroup_parray_from_weight_array(dvert_array, dvert_tot, weight_accum_prev, def_nr, true);
}
+ MEM_freeN(weight_accum_curr);
+ MEM_freeN(weight_accum_prev);
+ MEM_freeN(verts_used);
+
if (bm) {
/* pass */
}
@@ -2616,7 +2197,7 @@ void ED_vgroup_mirror(Object *ob,
/* object mode / weight paint */
MVert *mv, *mv_mirr;
int vidx, vidx_mirr;
- const int use_vert_sel = (me->editflag & ME_EDIT_PAINT_VERT_SEL) != 0;
+ const bool use_vert_sel = (me->editflag & ME_EDIT_PAINT_VERT_SEL) != 0;
if (me->dvert == NULL) {
goto cleanup;
@@ -2725,298 +2306,13 @@ cleanup:
}
-static void vgroup_remap_update_users(Object *ob, int *map)
-{
- ExplodeModifierData *emd;
- ModifierData *md;
- ParticleSystem *psys;
- ClothModifierData *clmd;
- ClothSimSettings *clsim;
- int a;
-
- /* these cases don't use names to refer to vertex groups, so when
- * they get deleted the numbers get out of sync, this corrects that */
-
- if (ob->soft)
- ob->soft->vertgroup = map[ob->soft->vertgroup];
-
- for (md = ob->modifiers.first; md; md = md->next) {
- if (md->type == eModifierType_Explode) {
- emd = (ExplodeModifierData *)md;
- emd->vgroup = map[emd->vgroup];
- }
- else if (md->type == eModifierType_Cloth) {
- clmd = (ClothModifierData *)md;
- clsim = clmd->sim_parms;
-
- if (clsim) {
- clsim->vgroup_mass = map[clsim->vgroup_mass];
- clsim->vgroup_bend = map[clsim->vgroup_bend];
- clsim->vgroup_struct = map[clsim->vgroup_struct];
- }
- }
- }
-
- for (psys = ob->particlesystem.first; psys; psys = psys->next) {
- for (a = 0; a < PSYS_TOT_VG; a++)
- psys->vgroup[a] = map[psys->vgroup[a]];
- }
-}
-
-
-static void vgroup_delete_update_users(Object *ob, int id)
-{
- int i, defbase_tot = BLI_countlist(&ob->defbase) + 1;
- int *map = MEM_mallocN(sizeof(int) * defbase_tot, "vgroup del");
-
- map[id] = map[0] = 0;
- for (i = 1; i < id; i++) map[i] = i;
- for (i = id + 1; i < defbase_tot; i++) map[i] = i - 1;
-
- vgroup_remap_update_users(ob, map);
- MEM_freeN(map);
-}
-
-
-static void vgroup_delete_object_mode(Object *ob, bDeformGroup *dg)
-{
- MDeformVert *dvert_array = NULL;
- int dvert_tot = 0;
- const int def_nr = BLI_findindex(&ob->defbase, dg);
-
- BLI_assert(def_nr != -1);
-
- ED_vgroup_array_get(ob->data, &dvert_array, &dvert_tot);
-
- if (dvert_array) {
- int i, j;
- MDeformVert *dv;
- for (i = 0, dv = dvert_array; i < dvert_tot; i++, dv++) {
- MDeformWeight *dw;
-
- dw = defvert_find_index(dv, def_nr);
- defvert_remove_group(dv, dw); /* dw can be NULL */
-
- /* inline, make into a function if anything else needs to do this */
- for (j = 0; j < dv->totweight; j++) {
- if (dv->dw[j].def_nr > def_nr) {
- dv->dw[j].def_nr--;
- }
- }
- /* done */
- }
- }
-
- vgroup_delete_update_users(ob, def_nr + 1);
-
- /* Remove the group */
- BLI_freelinkN(&ob->defbase, dg);
-
- /* Update the active deform index if necessary */
- if (ob->actdef > def_nr)
- ob->actdef--;
- if (ob->actdef < 1 && ob->defbase.first)
- ob->actdef = 1;
-
- /* remove all dverts */
- if (BLI_listbase_is_empty(&ob->defbase)) {
- if (ob->type == OB_MESH) {
- Mesh *me = ob->data;
- CustomData_free_layer_active(&me->vdata, CD_MDEFORMVERT, me->totvert);
- me->dvert = NULL;
- }
- else if (ob->type == OB_LATTICE) {
- Lattice *lt = ob->data;
- if (lt->dvert) {
- MEM_freeN(lt->dvert);
- lt->dvert = NULL;
- }
- }
- }
-}
-
-/* only in editmode */
-/* removes from active defgroup, if allverts==0 only selected vertices */
-static bool vgroup_active_remove_verts(Object *ob, const bool allverts, bDeformGroup *dg)
-{
- MDeformVert *dv;
- const int def_nr = BLI_findindex(&ob->defbase, dg);
- bool changed = false;
-
- if (ob->type == OB_MESH) {
- Mesh *me = ob->data;
-
- if (me->edit_btmesh) {
- BMEditMesh *em = me->edit_btmesh;
- const int cd_dvert_offset = CustomData_get_offset(&em->bm->vdata, CD_MDEFORMVERT);
-
- if (cd_dvert_offset != -1) {
- BMVert *eve;
- BMIter iter;
-
- BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
- dv = BM_ELEM_CD_GET_VOID_P(eve, cd_dvert_offset);
-
- if (dv && dv->dw && (allverts || BM_elem_flag_test(eve, BM_ELEM_SELECT))) {
- MDeformWeight *dw = defvert_find_index(dv, def_nr);
- defvert_remove_group(dv, dw); /* dw can be NULL */
- changed = true;
- }
- }
- }
- }
- else {
- if (me->dvert) {
- MVert *mv;
- int i;
-
- mv = me->mvert;
- dv = me->dvert;
-
- for (i = 0; i < me->totvert; i++, mv++, dv++) {
- if (mv->flag & SELECT) {
- if (dv->dw && (allverts || (mv->flag & SELECT))) {
- MDeformWeight *dw = defvert_find_index(dv, def_nr);
- defvert_remove_group(dv, dw); /* dw can be NULL */
- changed = true;
- }
- }
- }
- }
- }
- }
- else if (ob->type == OB_LATTICE) {
- Lattice *lt = vgroup_edit_lattice(ob);
-
- if (lt->dvert) {
- BPoint *bp;
- int i, tot = lt->pntsu * lt->pntsv * lt->pntsw;
-
- for (i = 0, bp = lt->def; i < tot; i++, bp++) {
- if (allverts || (bp->f1 & SELECT)) {
- MDeformWeight *dw;
-
- dv = &lt->dvert[i];
-
- dw = defvert_find_index(dv, def_nr);
- defvert_remove_group(dv, dw); /* dw can be NULL */
- changed = true;
- }
- }
- }
- }
-
- return changed;
-}
-
-static void vgroup_delete_edit_mode(Object *ob, bDeformGroup *dg)
-{
- int i;
- const int dg_index = BLI_findindex(&ob->defbase, dg);
-
- BLI_assert(dg_index != -1);
-
- /* Make sure that no verts are using this group */
- if (vgroup_active_remove_verts(ob, true, dg) == false) {
- /* do nothing */
- }
- /* Make sure that any verts with higher indices are adjusted accordingly */
- else if (ob->type == OB_MESH) {
- Mesh *me = ob->data;
- BMEditMesh *em = me->edit_btmesh;
- const int cd_dvert_offset = CustomData_get_offset(&em->bm->vdata, CD_MDEFORMVERT);
-
- BMIter iter;
- BMVert *eve;
- MDeformVert *dvert;
-
- BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
- dvert = BM_ELEM_CD_GET_VOID_P(eve, cd_dvert_offset);
-
- if (dvert)
- for (i = 0; i < dvert->totweight; i++)
- if (dvert->dw[i].def_nr > dg_index)
- dvert->dw[i].def_nr--;
- }
- }
- else if (ob->type == OB_LATTICE) {
- Lattice *lt = vgroup_edit_lattice(ob);
- BPoint *bp;
- MDeformVert *dvert = lt->dvert;
- int a, tot;
-
- if (dvert) {
- tot = lt->pntsu * lt->pntsv * lt->pntsw;
- for (a = 0, bp = lt->def; a < tot; a++, bp++, dvert++) {
- for (i = 0; i < dvert->totweight; i++) {
- if (dvert->dw[i].def_nr > dg_index)
- dvert->dw[i].def_nr--;
- }
- }
- }
- }
-
- vgroup_delete_update_users(ob, dg_index + 1);
-
- /* Remove the group */
- BLI_freelinkN(&ob->defbase, dg);
-
- /* Update the active deform index if necessary */
- if (ob->actdef > dg_index)
- ob->actdef--;
- if (ob->actdef < 1 && ob->defbase.first)
- ob->actdef = 1;
-
- /* remove all dverts */
- if (BLI_listbase_is_empty(&ob->defbase)) {
- if (ob->type == OB_MESH) {
- Mesh *me = ob->data;
- CustomData_free_layer_active(&me->vdata, CD_MDEFORMVERT, me->totvert);
- me->dvert = NULL;
- }
- else if (ob->type == OB_LATTICE) {
- Lattice *lt = vgroup_edit_lattice(ob);
- if (lt->dvert) {
- MEM_freeN(lt->dvert);
- lt->dvert = NULL;
- }
- }
- }
-}
-
-static void vgroup_delete(Object *ob)
+static void vgroup_delete_active(Object *ob)
{
bDeformGroup *dg = BLI_findlink(&ob->defbase, ob->actdef - 1);
if (!dg)
return;
- if (BKE_object_is_in_editmode_vgroup(ob))
- vgroup_delete_edit_mode(ob, dg);
- else
- vgroup_delete_object_mode(ob, dg);
-}
-
-static void vgroup_delete_all(Object *ob)
-{
- /* Remove all DVerts */
- if (ob->type == OB_MESH) {
- Mesh *me = ob->data;
- CustomData_free_layer_active(&me->vdata, CD_MDEFORMVERT, me->totvert);
- me->dvert = NULL;
- }
- else if (ob->type == OB_LATTICE) {
- Lattice *lt = vgroup_edit_lattice(ob);
- if (lt->dvert) {
- MEM_freeN(lt->dvert);
- lt->dvert = NULL;
- }
- }
-
- /* Remove all DefGroups */
- BLI_freelistN(&ob->defbase);
-
- /* Fix counters/indices */
- ob->actdef = 0;
+ BKE_object_defgroup_remove(ob, dg);
}
/* only in editmode */
@@ -3061,7 +2357,7 @@ static void vgroup_assign_verts(Object *ob, const float weight)
int i;
if (!me->dvert) {
- ED_vgroup_data_create(&me->id);
+ BKE_object_defgroup_data_create(&me->id);
}
mv = me->mvert;
@@ -3085,7 +2381,7 @@ static void vgroup_assign_verts(Object *ob, const float weight)
int a, tot;
if (lt->dvert == NULL)
- ED_vgroup_data_create(&lt->id);
+ BKE_object_defgroup_data_create(&lt->id);
dv = lt->dvert;
@@ -3103,22 +2399,6 @@ static void vgroup_assign_verts(Object *ob, const float weight)
}
}
-/* only in editmode */
-/* removes from all defgroup, if allverts==0 only selected vertices */
-static bool vgroup_remove_verts(Object *ob, int allverts)
-{
- bool changed = false;
- /* To prevent code redundancy, we just use vgroup_active_remove_verts, but that
- * only operates on the active vgroup. So we iterate through all groups, by changing
- * active group index
- */
- bDeformGroup *dg;
- for (dg = ob->defbase.first; dg; dg = dg->next) {
- changed |= vgroup_active_remove_verts(ob, allverts, dg);
- }
- return changed;
-}
-
/********************** vertex group operators *********************/
static int vertex_group_poll(bContext *C)
@@ -3150,7 +2430,7 @@ static int vertex_group_mesh_poll(bContext *C)
ob->defbase.first);
}
-static int vertex_group_mesh_supported_poll(bContext *C)
+static int UNUSED_FUNCTION(vertex_group_mesh_supported_poll)(bContext *C)
{
Object *ob = ED_object_context(C);
ID *data = (ob) ? ob->data : NULL;
@@ -3170,16 +2450,43 @@ static int UNUSED_FUNCTION(vertex_group_poll_edit) (bContext *C)
}
/* editmode _or_ weight paint vertex sel */
-static int vertex_group_vert_select_poll(bContext *C)
+static int vertex_group_vert_select_poll_ex(bContext *C, const short ob_type_flag)
{
Object *ob = ED_object_context(C);
ID *data = (ob) ? ob->data : NULL;
if (!(ob && !ob->id.lib && data && !data->lib))
- return 0;
+ return false;
- return (BKE_object_is_in_editmode_vgroup(ob) ||
- BKE_object_is_in_wpaint_select_vert(ob));
+ if (ob_type_flag && (((1 << ob->type) & ob_type_flag)) == 0) {
+ return false;
+ }
+
+ if (BKE_object_is_in_editmode_vgroup(ob)) {
+ return true;
+ }
+ else if (ob->mode & OB_MODE_WEIGHT_PAINT) {
+ if (BKE_object_is_in_wpaint_select_vert(ob)) {
+ return true;
+ }
+ else {
+ CTX_wm_operator_poll_msg_set(C, "Vertex select needs to be enabled in weight paint mode");
+ return false;
+ }
+ }
+ else {
+ return false;
+ }
+}
+
+static int vertex_group_vert_select_poll(bContext *C)
+{
+ return vertex_group_vert_select_poll_ex(C, 0);
+}
+
+static int vertex_group_mesh_vert_select_poll(bContext *C)
+{
+ return vertex_group_vert_select_poll_ex(C, (1 << OB_MESH));
}
/* editmode _or_ weight paint vertex sel and active group unlocked */
@@ -3226,7 +2533,7 @@ static int vertex_group_add_exec(bContext *C, wmOperator *UNUSED(op))
{
Object *ob = ED_object_context(C);
- ED_vgroup_add(ob);
+ BKE_object_defgroup_add(ob);
DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_GEOM | ND_VERTEX_GROUP, ob->data);
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
@@ -3254,9 +2561,9 @@ static int vertex_group_remove_exec(bContext *C, wmOperator *op)
Object *ob = ED_object_context(C);
if (RNA_boolean_get(op->ptr, "all"))
- vgroup_delete_all(ob);
+ BKE_object_defgroup_remove_all(ob);
else
- vgroup_delete(ob);
+ vgroup_delete_active(ob);
DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_GEOM | ND_VERTEX_GROUP, ob->data);
@@ -3321,7 +2628,7 @@ static int vertex_group_assign_new_exec(bContext *C, wmOperator *op)
{
/* create new group... */
Object *ob = ED_object_context(C);
- ED_vgroup_add(ob);
+ BKE_object_defgroup_add(ob);
/* assign selection to new group */
return vertex_group_assign_exec(C, op);
@@ -3353,14 +2660,14 @@ static int vertex_group_remove_from_exec(bContext *C, wmOperator *op)
Object *ob = ED_object_context(C);
if (use_all_groups) {
- if (vgroup_remove_verts(ob, 0) == false) {
+ if (BKE_object_defgroup_clear_all(ob, true) == false) {
return OPERATOR_CANCELLED;
}
}
else {
bDeformGroup *dg = BLI_findlink(&ob->defbase, ob->actdef - 1);
- if ((dg == NULL) || (vgroup_active_remove_verts(ob, use_all_verts, dg) == false)) {
+ if ((dg == NULL) || (BKE_object_defgroup_clear(ob, dg, !use_all_verts) == false)) {
return OPERATOR_CANCELLED;
}
}
@@ -3486,7 +2793,7 @@ static int vertex_group_levels_exec(bContext *C, wmOperator *op)
int subset_count, vgroup_tot;
- const bool *vgroup_validmap = ED_vgroup_subset_from_select_type(ob, subset_type, &vgroup_tot, &subset_count);
+ const bool *vgroup_validmap = BKE_object_defgroup_subset_from_select_type(ob, subset_type, &vgroup_tot, &subset_count);
vgroup_levels_subset(ob, vgroup_validmap, vgroup_tot, subset_count, offset, gain);
MEM_freeN((void *)vgroup_validmap);
@@ -3552,7 +2859,7 @@ static int vertex_group_normalize_all_exec(bContext *C, wmOperator *op)
int subset_count, vgroup_tot;
- const bool *vgroup_validmap = ED_vgroup_subset_from_select_type(ob, subset_type, &vgroup_tot, &subset_count);
+ const bool *vgroup_validmap = BKE_object_defgroup_subset_from_select_type(ob, subset_type, &vgroup_tot, &subset_count);
vgroup_normalize_all(ob, vgroup_validmap, vgroup_tot, subset_count, lock_active);
MEM_freeN((void *)vgroup_validmap);
@@ -3674,7 +2981,7 @@ static int vertex_group_invert_exec(bContext *C, wmOperator *op)
int subset_count, vgroup_tot;
- const bool *vgroup_validmap = ED_vgroup_subset_from_select_type(ob, subset_type, &vgroup_tot, &subset_count);
+ const bool *vgroup_validmap = BKE_object_defgroup_subset_from_select_type(ob, subset_type, &vgroup_tot, &subset_count);
vgroup_invert_subset(ob, vgroup_validmap, vgroup_tot, subset_count, auto_assign, auto_remove);
MEM_freeN((void *)vgroup_validmap);
@@ -3706,17 +3013,19 @@ void OBJECT_OT_vertex_group_invert(wmOperatorType *ot)
"Remove verts from groups that have zero weight after inverting");
}
-
-static int vertex_group_blend_exec(bContext *C, wmOperator *op)
+static int vertex_group_smooth_exec(bContext *C, wmOperator *op)
{
Object *ob = ED_object_context(C);
- float fac = RNA_float_get(op->ptr, "factor");
+ const float fac = RNA_float_get(op->ptr, "factor");
+ const int repeat = RNA_int_get(op->ptr, "repeat");
eVGroupSelect subset_type = RNA_enum_get(op->ptr, "group_select_mode");
+ const int source = RNA_enum_get(op->ptr, "source");
+ const float fac_expand = RNA_float_get(op->ptr, "expand");
int subset_count, vgroup_tot;
- const bool *vgroup_validmap = ED_vgroup_subset_from_select_type(ob, subset_type, &vgroup_tot, &subset_count);
- vgroup_blend_subset(ob, vgroup_validmap, vgroup_tot, subset_count, fac);
+ const bool *vgroup_validmap = BKE_object_defgroup_subset_from_select_type(ob, subset_type, &vgroup_tot, &subset_count);
+ vgroup_smooth_subset(ob, vgroup_validmap, vgroup_tot, subset_count, fac, repeat, fac_expand, source);
MEM_freeN((void *)vgroup_validmap);
DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
@@ -3726,60 +3035,34 @@ static int vertex_group_blend_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
-/* check we have a vertex selection, either in weight paint or editmode */
-static int vertex_group_blend_poll(bContext *C)
+void OBJECT_OT_vertex_group_smooth(wmOperatorType *ot)
{
- Object *ob = ED_object_context(C);
- ID *data = (ob) ? ob->data : NULL;
-
- if (!(ob && !ob->id.lib && data && !data->lib))
- return false;
-
- if (ob->type != OB_MESH) {
- return false;
- }
-
- if (BKE_object_is_in_editmode_vgroup(ob)) {
- return true;
- }
- else if (ob->mode & OB_MODE_WEIGHT_PAINT) {
- if (ME_EDIT_PAINT_SEL_MODE(((Mesh *)data)) == SCE_SELECT_VERTEX) {
- return true;
- }
- else {
- CTX_wm_operator_poll_msg_set(C, "Vertex select needs to be enabled in weight paint mode");
- return false;
- }
-
- }
- else {
- return false;
- }
-}
-
-void OBJECT_OT_vertex_group_blend(wmOperatorType *ot)
-{
- PropertyRNA *prop;
+ static EnumPropertyItem smooth_source_item[] = {
+ {WEIGHT_SMOOTH_ALL, "ALL", 0, "All", ""},
+ {WEIGHT_SMOOTH_SELECT, "SELECT", 0, "Only Selected", ""},
+ {WEIGHT_SMOOTH_DESELECT, "DESELECT", 0, "Only Deselected", ""},
+ {0, NULL, 0, NULL, NULL}
+ };
/* identifiers */
- ot->name = "Blend Vertex Group";
- ot->idname = "OBJECT_OT_vertex_group_blend";
- ot->description = "Blend selected vertex weights with unselected for the active group";
+ ot->name = "Smooth Vertex Weights";
+ ot->idname = "OBJECT_OT_vertex_group_smooth";
+ ot->description = "Smooth weights for selected vertices";
/* api callbacks */
- ot->poll = vertex_group_blend_poll;
- ot->exec = vertex_group_blend_exec;
+ ot->poll = vertex_group_mesh_vert_select_poll;
+ ot->exec = vertex_group_smooth_exec;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
vgroup_operator_subset_select_props(ot, true);
- prop = RNA_def_property(ot->srna, "factor", PROP_FLOAT, PROP_FACTOR);
- RNA_def_property_ui_text(prop, "Factor", "");
- RNA_def_property_range(prop, 0.0f, 1.0f);
- RNA_def_property_float_default(prop, 1.0f);
-}
+ RNA_def_float(ot->srna, "factor", 0.5f, 0.0f, 1.0, "Factor", "", 0.0f, 1.0f);
+ RNA_def_int(ot->srna, "repeat", 1, 1, 10000, "Iterations", "", 1, 200);
+ RNA_def_float(ot->srna, "expand", 0.0f, -1.0f, 1.0, "Expand/Contract", "Expand/contract weights", -1.0f, 1.0f);
+ RNA_def_enum(ot->srna, "source", smooth_source_item, -1, "Source", "Vertices to mix with");
+}
static int vertex_group_clean_exec(bContext *C, wmOperator *op)
{
@@ -3791,7 +3074,7 @@ static int vertex_group_clean_exec(bContext *C, wmOperator *op)
int subset_count, vgroup_tot;
- const bool *vgroup_validmap = ED_vgroup_subset_from_select_type(ob, subset_type, &vgroup_tot, &subset_count);
+ const bool *vgroup_validmap = BKE_object_defgroup_subset_from_select_type(ob, subset_type, &vgroup_tot, &subset_count);
vgroup_clean_subset(ob, vgroup_validmap, vgroup_tot, subset_count, limit, keep_single);
MEM_freeN((void *)vgroup_validmap);
@@ -3832,7 +3115,7 @@ static int vertex_group_quantize_exec(bContext *C, wmOperator *op)
int subset_count, vgroup_tot;
- const bool *vgroup_validmap = ED_vgroup_subset_from_select_type(ob, subset_type, &vgroup_tot, &subset_count);
+ const bool *vgroup_validmap = BKE_object_defgroup_subset_from_select_type(ob, subset_type, &vgroup_tot, &subset_count);
vgroup_quantize_subset(ob, vgroup_validmap, vgroup_tot, subset_count, steps);
MEM_freeN((void *)vgroup_validmap);
@@ -3870,7 +3153,7 @@ static int vertex_group_limit_total_exec(bContext *C, wmOperator *op)
int subset_count, vgroup_tot;
- const bool *vgroup_validmap = ED_vgroup_subset_from_select_type(ob, subset_type, &vgroup_tot, &subset_count);
+ const bool *vgroup_validmap = BKE_object_defgroup_subset_from_select_type(ob, subset_type, &vgroup_tot, &subset_count);
int remove_tot = vgroup_limit_total_subset(ob, vgroup_validmap, vgroup_tot, subset_count, limit);
MEM_freeN((void *)vgroup_validmap);
@@ -3934,7 +3217,7 @@ void OBJECT_OT_vertex_group_mirror(wmOperatorType *ot)
/* identifiers */
ot->name = "Mirror Vertex Group";
ot->idname = "OBJECT_OT_vertex_group_mirror";
- ot->description = "Mirror all vertex groups, flip weights and/or names, editing only selected vertices, "
+ ot->description = "Mirror vertex group, flip weights and/or names, editing only selected vertices, "
"flipping when both sides are selected otherwise copy from unselected";
/* api callbacks */
@@ -3983,7 +3266,7 @@ void OBJECT_OT_vertex_group_copy_to_linked(wmOperatorType *ot)
/* identifiers */
ot->name = "Copy Vertex Groups to Linked";
ot->idname = "OBJECT_OT_vertex_group_copy_to_linked";
- ot->description = "Copy vertex groups to all users of the same geometry data";
+ ot->description = "Replace vertex groups of all users of the same geometry data by vertex groups of active object";
/* api callbacks */
ot->poll = vertex_group_poll;
@@ -4022,7 +3305,7 @@ void OBJECT_OT_vertex_group_copy_to_selected(wmOperatorType *ot)
/* identifiers */
ot->name = "Copy Vertex Group to Selected";
ot->idname = "OBJECT_OT_vertex_group_copy_to_selected";
- ot->description = "Copy vertex groups to other selected objects with matching indices";
+ ot->description = "Replace vertex groups of selected objects by vertex groups of active object";
/* api callbacks */
ot->poll = vertex_group_poll;
@@ -4032,143 +3315,6 @@ void OBJECT_OT_vertex_group_copy_to_selected(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-static int vertex_group_transfer_weight_exec(bContext *C, wmOperator *op)
-{
- Scene *scene = CTX_data_scene(C);
- Object *ob_act = CTX_data_active_object(C);
-
- bDeformGroup *dg_act = BLI_findlink(&ob_act->defbase, (ob_act->actdef - 1));
- char dg_act_name[MAX_VGROUP_NAME]; /* may be freed so copy */
-
- int fail = 0;
- bool changed = false;
-
- WT_VertexGroupMode vertex_group_mode = RNA_enum_get(op->ptr, "group_select_mode");
- WT_Method method = RNA_enum_get(op->ptr, "method");
- WT_ReplaceMode replace_mode = RNA_enum_get(op->ptr, "replace_mode");
-
- if (vertex_group_mode == WT_REPLACE_ACTIVE_VERTEX_GROUP) {
- if (!dg_act) {
- BKE_report(op->reports, RPT_WARNING, "Failed, active object has no active groups");
- return OPERATOR_FINISHED; /* to get the chance to make changes in the redo panel*/
- }
- }
-
- if (dg_act) {
- BLI_strncpy(dg_act_name, dg_act->name, sizeof(dg_act_name));
- }
-
- /* Macro to loop through selected objects and perform operation depending on function, option and method.*/
- CTX_DATA_BEGIN (C, Object *, ob_src, selected_editable_objects)
- {
- if (ob_act != ob_src) {
-
- if (BLI_listbase_is_empty(&ob_src->defbase)) {
- BKE_reportf(op->reports, RPT_WARNING,
- "Skipping object '%s' it has no vertex groups", ob_src->id.name + 2);
- continue;
- }
- else if (ob_src->type != OB_MESH) {
- /* armatures can be in pose mode so ignore them */
- if (ob_src->type != OB_ARMATURE) {
- BKE_reportf(op->reports, RPT_WARNING,
- "Skipping object '%s' only copying from meshes is supported", ob_src->id.name + 2);
- }
- continue;
- }
-
- switch (vertex_group_mode) {
-
- case WT_REPLACE_ACTIVE_VERTEX_GROUP:
- {
- bDeformGroup *dg_src;
- dg_src = defgroup_find_name(ob_src, dg_act_name);
-
- if (dg_src == NULL) {
- BKE_reportf(op->reports, RPT_WARNING,
- "Skipping object '%s' no group '%s' found", ob_src->id.name + 2, dg_act_name);
- continue;
- }
-
- if (ed_vgroup_transfer_weight(ob_act, ob_src, dg_src, scene, method, replace_mode, op)) {
- changed = true;
- }
- else {
- fail++;
- }
- break;
- }
- case WT_REPLACE_ALL_VERTEX_GROUPS:
- {
- bDeformGroup *dg_src;
- for (dg_src = ob_src->defbase.first; dg_src; dg_src = dg_src->next) {
- if (ed_vgroup_transfer_weight(ob_act, ob_src, dg_src, scene, method, replace_mode, op)) {
- changed = true;
- }
- else {
- fail++;
- }
- }
- break;
- }
- default:
- BLI_assert(0);
- break;
- }
- }
- }
- CTX_DATA_END;
-
- if (changed) {
-
- /* possible the active vertex group changed because of adding/removing */
- /* note!, dg_act may be realloc'd, only check its not NULL */
- if (dg_act) {
- ED_vgroup_select_by_name(ob_act, dg_act_name);
- }
- else {
- ED_vgroup_sync_from_pose(ob_act);
- }
-
- /* Event notifiers for correct display of data.*/
-
-
- DAG_id_tag_update(&ob_act->id, OB_RECALC_DATA);
- WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob_act); /* for buttons */
- WM_event_add_notifier(C, NC_GEOM | ND_VERTEX_GROUP, ob_act);
- return OPERATOR_FINISHED;
- }
- else {
- if (BLI_listbase_is_empty(&op->reports->list)) {
- BKE_report(op->reports, RPT_WARNING, "Failed, no other selected objects with vertex groups found");
- }
-
- return OPERATOR_FINISHED; /* to get the chance to make changes in the redo panel */
- }
-}
-
-/* transfers weight from active to selected */
-void OBJECT_OT_vertex_group_transfer_weight(wmOperatorType *ot)
-{
- /* Identifiers.*/
- ot->name = "Transfer Weights";
- ot->idname = "OBJECT_OT_vertex_group_transfer_weight";
- ot->description = "Transfer weight paint to active from selected mesh";
-
- /* API callbacks.*/
- ot->poll = vertex_group_mesh_supported_poll;
- ot->exec = vertex_group_transfer_weight_exec;
-
- /* Flags.*/
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* Properties.*/
- /* TODO, use vgroup_operator_subset_select_props for group_select_mode */
- ot->prop = RNA_def_enum(ot->srna, "group_select_mode", WT_vertex_group_mode_item, WT_REPLACE_ALL_VERTEX_GROUPS, "Group", "");
- ot->prop = RNA_def_enum(ot->srna, "method", WT_method_item, WT_BY_NEAREST_FACE, "Method", "");
- ot->prop = RNA_def_enum(ot->srna, "replace_mode", WT_replace_mode_item, WT_REPLACE_ALL_WEIGHTS, "Replace", "");
-}
-
static int set_active_group_exec(bContext *C, wmOperator *op)
{
Object *ob = ED_object_context(C);
@@ -4237,7 +3383,7 @@ void OBJECT_OT_vertex_group_set_active(wmOperatorType *ot)
static char *vgroup_init_remap(Object *ob)
{
bDeformGroup *def;
- int defbase_tot = BLI_countlist(&ob->defbase);
+ int defbase_tot = BLI_listbase_count(&ob->defbase);
char *name_array = MEM_mallocN(MAX_VGROUP_NAME * sizeof(char) * defbase_tot, "sort vgroups");
char *name;
@@ -4254,7 +3400,7 @@ static int vgroup_do_remap(Object *ob, const char *name_array, wmOperator *op)
{
MDeformVert *dvert = NULL;
bDeformGroup *def;
- int defbase_tot = BLI_countlist(&ob->defbase);
+ int defbase_tot = BLI_listbase_count(&ob->defbase);
/* needs a dummy index at the start*/
int *sort_map_update = MEM_mallocN(sizeof(int) * (defbase_tot + 1), "sort vgroups");
@@ -4297,7 +3443,7 @@ static int vgroup_do_remap(Object *ob, const char *name_array, wmOperator *op)
else {
int dvert_tot = 0;
- ED_vgroup_array_get(ob->data, &dvert, &dvert_tot);
+ BKE_object_defgroup_array_get(ob->data, &dvert, &dvert_tot);
/*create as necessary*/
if (dvert) {
@@ -4314,7 +3460,7 @@ static int vgroup_do_remap(Object *ob, const char *name_array, wmOperator *op)
sort_map[i]++;
sort_map_update[0] = 0;
- vgroup_remap_update_users(ob, sort_map_update);
+ BKE_object_defgroup_remap_update_users(ob, sort_map_update);
BLI_assert(sort_map_update[ob->actdef] >= 0);
ob->actdef = sort_map_update[ob->actdef];
@@ -4378,7 +3524,7 @@ static int vertex_group_sort_exec(bContext *C, wmOperator *op)
/*sort vgroup names*/
switch (sort_type) {
case SORT_TYPE_NAME:
- BLI_sortlist(&ob->defbase, vgroup_sort_name);
+ BLI_listbase_sort(&ob->defbase, vgroup_sort_name);
break;
case SORT_TYPE_BONEHIERARCHY:
vgroup_sort_bone_hierarchy(ob, NULL);
diff --git a/source/blender/editors/object/object_warp.c b/source/blender/editors/object/object_warp.c
index 8016dabf3a3..9f4da87903d 100644
--- a/source/blender/editors/object/object_warp.c
+++ b/source/blender/editors/object/object_warp.c
@@ -31,7 +31,6 @@
#include "BLI_math.h"
-#include "BKE_utildefines.h"
#include "BKE_context.h"
#include "RNA_access.h"
@@ -276,14 +275,14 @@ static int object_warp_verts_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
-void OBJECT_OT_vertex_warp(struct wmOperatorType *ot)
+void TRANSFORM_OT_vertex_warp(struct wmOperatorType *ot)
{
PropertyRNA *prop;
/* identifiers */
ot->name = "Warp";
ot->description = "Warp vertices around the cursor";
- ot->idname = "OBJECT_OT_vertex_warp";
+ ot->idname = "TRANSFORM_OT_vertex_warp";
/* api callbacks */
ot->exec = object_warp_verts_exec;
diff --git a/source/blender/editors/physics/CMakeLists.txt b/source/blender/editors/physics/CMakeLists.txt
index 892d71befb4..898422dac51 100644
--- a/source/blender/editors/physics/CMakeLists.txt
+++ b/source/blender/editors/physics/CMakeLists.txt
@@ -20,14 +20,16 @@
set(INC
../include
- ../../blenfont
../../blenkernel
../../blenlib
+ ../../blentranslation
+ ../../gpu
../../makesdna
../../makesrna
../../windowmanager
../../../../intern/elbeem/extern
../../../../intern/guardedalloc
+ ../../../../intern/glew-mx
)
set(INC_SYS
@@ -64,4 +66,6 @@ if(WITH_BULLET)
add_definitions(-DWITH_BULLET)
endif()
+add_definitions(${GL_DEFINITIONS})
+
blender_add_lib(bf_editor_physics "${SRC}" "${INC}" "${INC_SYS}")
diff --git a/source/blender/editors/physics/SConscript b/source/blender/editors/physics/SConscript
index 9436280de43..be399a58732 100644
--- a/source/blender/editors/physics/SConscript
+++ b/source/blender/editors/physics/SConscript
@@ -31,13 +31,15 @@ sources = env.Glob('*.c')
incs = [
'#/intern/guardedalloc',
+ env['BF_GLEW_INC'],
+ '#/intern/glew-mx',
'#/intern/rigidbody',
- '#/extern/glew/include',
'#/intern/elbeem/extern',
'../include',
- '../../blenfont',
'../../blenkernel',
'../../blenlib',
+ '../../blentranslation',
+ '../../gpu',
'../../makesdna',
'../../makesrna',
'../../windowmanager',
@@ -45,6 +47,7 @@ incs = [
incs = ' '.join(incs)
defs = []
+defs += env['BF_GL_DEFINITIONS']
if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'linuxcross', 'win64-vc', 'win64-mingw'):
incs += ' ' + env['BF_PTHREADS_INC']
diff --git a/source/blender/editors/physics/dynamicpaint_ops.c b/source/blender/editors/physics/dynamicpaint_ops.c
index 637af5d6536..93daa15e608 100644
--- a/source/blender/editors/physics/dynamicpaint_ops.c
+++ b/source/blender/editors/physics/dynamicpaint_ops.c
@@ -30,7 +30,7 @@
#include "BLI_string.h"
#include "BLI_utildefines.h"
-#include "BLF_translation.h"
+#include "BLT_translation.h"
#include "DNA_dynamicpaint_types.h"
#include "DNA_modifier_types.h"
@@ -40,6 +40,7 @@
#include "BKE_blender.h"
#include "BKE_context.h"
#include "BKE_deform.h"
+#include "BKE_object_deform.h"
#include "BKE_depsgraph.h"
#include "BKE_dynamicpaint.h"
#include "BKE_global.h"
@@ -235,11 +236,11 @@ static int output_toggle_exec(bContext *C, wmOperator *op)
/* Vertex Weight Layer */
else if (surface->type == MOD_DPAINT_SURFACE_T_WEIGHT) {
if (!exists) {
- ED_vgroup_add_name(ob, name);
+ BKE_object_defgroup_add_name(ob, name);
}
else {
bDeformGroup *defgroup = defgroup_find_name(ob, name);
- if (defgroup) ED_vgroup_delete(ob, defgroup);
+ if (defgroup) BKE_object_defgroup_remove(ob, defgroup);
}
}
}
@@ -395,13 +396,8 @@ static int dynamicPaint_initBake(struct bContext *C, struct wmOperator *op)
/* Bake was successful:
* Report for ended bake and how long it took */
if (status) {
- /* Format time string */
- char time_str[30];
- double time = PIL_check_seconds_timer() - timer;
- BLI_timestr(time, time_str, sizeof(time_str));
-
/* Show bake info */
- BKE_reportf(op->reports, RPT_INFO, "Bake complete! (%s)", time_str);
+ BKE_reportf(op->reports, RPT_INFO, "Bake complete! (%.2f)", PIL_check_seconds_timer() - timer);
}
else {
if (strlen(canvas->error)) { /* If an error occurred */
diff --git a/source/blender/editors/physics/particle_edit.c b/source/blender/editors/physics/particle_edit.c
index 76344b77dd3..892545a8efd 100644
--- a/source/blender/editors/physics/particle_edit.c
+++ b/source/blender/editors/physics/particle_edit.c
@@ -61,7 +61,7 @@
#include "BKE_modifier.h"
#include "BKE_particle.h"
#include "BKE_report.h"
-
+#include "BKE_bvhutils.h"
#include "BKE_pointcache.h"
#include "BIF_gl.h"
@@ -83,9 +83,11 @@
#include "physics_intern.h"
-static void PE_create_particle_edit(Scene *scene, Object *ob, PointCache *cache, ParticleSystem *psys);
-static void PTCacheUndo_clear(PTCacheEdit *edit);
-static void recalc_emitter_field(Object *ob, ParticleSystem *psys);
+void PE_create_particle_edit(Scene *scene, Object *ob, PointCache *cache, ParticleSystem *psys);
+void PTCacheUndo_clear(PTCacheEdit *edit);
+void recalc_lengths(PTCacheEdit *edit);
+void recalc_emitter_field(Object *ob, ParticleSystem *psys);
+void update_world_cos(Object *ob, PTCacheEdit *edit);
#define KEY_K PTCacheEditKey *key; int k
#define POINT_P PTCacheEditPoint *point; int p
@@ -355,6 +357,7 @@ typedef struct PEData {
Object *ob;
DerivedMesh *dm;
PTCacheEdit *edit;
+ BVHTreeFromMesh shape_bvh;
const int *mval;
rcti *rect;
@@ -397,12 +400,12 @@ static void PE_set_view3d_data(bContext *C, PEData *data)
/* note, the object argument means the modelview matrix does not account for the objects matrix, use viewmat rather than (obmat * viewmat) */
view3d_get_transformation(data->vc.ar, data->vc.rv3d, NULL, &data->mats);
- if ((data->vc.v3d->drawtype>OB_WIRE) && (data->vc.v3d->flag & V3D_ZBUF_SELECT)) {
+ if (V3D_IS_ZBUF(data->vc.v3d)) {
if (data->vc.v3d->flag & V3D_INVALID_BACKBUF) {
/* needed or else the draw matrix can be incorrect */
view3d_operator_needs_opengl(C);
- view3d_validate_backbuf(&data->vc);
+ ED_view3d_backbuf_validate(&data->vc);
/* we may need to force an update here by setting the rv3d as dirty
* for now it seems ok, but take care!:
* rv3d->depths->dirty = 1; */
@@ -411,6 +414,25 @@ static void PE_set_view3d_data(bContext *C, PEData *data)
}
}
+static bool PE_create_shape_tree(PEData *data, Object *shapeob)
+{
+ DerivedMesh *dm = shapeob->derivedFinal;
+
+ memset(&data->shape_bvh, 0, sizeof(data->shape_bvh));
+
+ if (!dm) {
+ return false;
+ }
+
+ DM_ensure_looptri(dm);
+ return (bvhtree_from_mesh_looptri(&data->shape_bvh, dm, 0.0f, 4, 8) != NULL);
+}
+
+static void PE_free_shape_tree(PEData *data)
+{
+ free_bvhtree_from_mesh(&data->shape_bvh);
+}
+
/*************************** selection utilities *******************************/
static bool key_test_depth(PEData *data, const float co[3], const int screen_co[2])
@@ -421,8 +443,8 @@ static bool key_test_depth(PEData *data, const float co[3], const int screen_co[
float depth;
/* nothing to do */
- if ((v3d->drawtype<=OB_WIRE) || (v3d->flag & V3D_ZBUF_SELECT)==0)
- return 1;
+ if (!V3D_IS_ZBUF(v3d))
+ return true;
/* used to calculate here but all callers have the screen_co already, so pass as arg */
#if 0
@@ -1055,7 +1077,7 @@ static void pe_iterate_lengths(Scene *scene, PTCacheEdit *edit)
}
}
/* set current distances to be kept between neighbouting keys */
-static void recalc_lengths(PTCacheEdit *edit)
+void recalc_lengths(PTCacheEdit *edit)
{
POINT_P; KEY_K;
@@ -1071,7 +1093,7 @@ static void recalc_lengths(PTCacheEdit *edit)
}
/* calculate a tree for finding nearest emitter's vertice */
-static void recalc_emitter_field(Object *ob, ParticleSystem *psys)
+void recalc_emitter_field(Object *ob, ParticleSystem *psys)
{
DerivedMesh *dm=psys_get_modifier(ob, psys)->dm;
PTCacheEdit *edit= psys->edit;
@@ -1159,7 +1181,7 @@ static void PE_update_selection(Scene *scene, Object *ob, int useflag)
point->flag &= ~PEP_EDIT_RECALC;
}
-static void update_world_cos(Object *ob, PTCacheEdit *edit)
+void update_world_cos(Object *ob, PTCacheEdit *edit)
{
ParticleSystem *psys = edit->psys;
ParticleSystemModifierData *psmd= psys_get_modifier(ob, psys);
@@ -1588,6 +1610,87 @@ void PARTICLE_OT_select_tips(wmOperatorType *ot)
WM_operator_properties_select_action(ot, SEL_SELECT);
}
+/*********************** select random operator ************************/
+
+enum { RAN_HAIR, RAN_POINTS };
+
+static EnumPropertyItem select_random_type_items[] = {
+ {RAN_HAIR, "HAIR", 0, "Hair", ""},
+ {RAN_POINTS, "POINTS", 0, "Points", ""},
+ {0, NULL, 0, NULL, NULL}
+};
+
+static int select_random_exec(bContext *C, wmOperator *op)
+{
+ PEData data;
+ int type;
+ Scene *scene;
+ Object *ob;
+
+ /* used by LOOP_VISIBLE_POINTS, LOOP_VISIBLE_KEYS and LOOP_KEYS */
+ PTCacheEdit *edit;
+ PTCacheEditPoint *point;
+ PTCacheEditKey *key;
+ int p;
+ int k;
+
+ const float randf = RNA_float_get (op->ptr, "percent") / 100.0f;
+
+ type = RNA_enum_get(op->ptr, "type");
+
+ PE_set_data(C, &data);
+ data.select_action = SEL_SELECT;
+ scene = CTX_data_scene(C);
+ ob = CTX_data_active_object(C);
+ edit = PE_get_current(scene, ob);
+
+ switch (type) {
+ case RAN_HAIR:
+ LOOP_VISIBLE_POINTS {
+ int flag = (BLI_frand() < randf) ? SEL_SELECT : SEL_DESELECT;
+ LOOP_KEYS {
+ select_action_apply (point, key, flag);
+ }
+ }
+ break;
+ case RAN_POINTS:
+ LOOP_VISIBLE_POINTS {
+ LOOP_VISIBLE_KEYS {
+ int flag = (BLI_frand() < randf) ? SEL_SELECT : SEL_DESELECT;
+ select_action_apply (point, key, flag);
+ }
+ }
+ break;
+ }
+
+ PE_update_selection(data.scene, data.ob, 1);
+ WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_SELECTED, data.ob);
+
+ return OPERATOR_FINISHED;
+}
+
+void PARTICLE_OT_select_random(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Select Random";
+ ot->idname = "PARTICLE_OT_select_random";
+ ot->description = "Select a randomly distributed set of hair or points";
+
+ /* api callbacks */
+ ot->exec = select_random_exec;
+ ot->poll = PE_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_float_percentage (ot->srna, "percent", 50.0f, 0.0f, 100.0f, "Percent",
+ "Percentage (mean) of elements in randomly selected set",
+ 0.0f, 100.0f);
+ ot->prop = RNA_def_enum (ot->srna, "type", select_random_type_items, RAN_HAIR,
+ "Type", "Select either hair or points");
+}
+
/************************ select linked operator ************************/
static int select_linked_exec(bContext *C, wmOperator *op)
@@ -3148,7 +3251,7 @@ static void brush_puff(PEData *data, int point_index)
static void BKE_brush_weight_get(PEData *data, float UNUSED(mat[4][4]), float UNUSED(imat[4][4]), int point_index, int key_index, PTCacheEditKey *UNUSED(key))
{
- /* roots have full weight allways */
+ /* roots have full weight always */
if (key_index) {
PTCacheEdit *edit = data->edit;
ParticleSystem *psys = edit->psys;
@@ -3382,7 +3485,7 @@ static int brush_add(PEData *data, short number)
if (psmd->dm->deformedOnly || psys->part->use_modifier_stack)
dm = psmd->dm;
else {
- dm = mesh_get_derived_deform(scene, ob, CD_MASK_BAREMESH);
+ dm = mesh_get_derived_deform(scene, ob, CD_MASK_BAREMESH | CD_MASK_MFACE);
release_dm = true;
}
@@ -3951,6 +4054,184 @@ void PARTICLE_OT_brush_edit(wmOperatorType *ot)
RNA_def_collection_runtime(ot->srna, "stroke", &RNA_OperatorStrokeElement, "Stroke", "");
}
+/*********************** cut shape ***************************/
+
+static int shape_cut_poll(bContext *C)
+{
+ if (PE_hair_poll(C)) {
+ Scene *scene = CTX_data_scene(C);
+ ParticleEditSettings *pset = PE_settings(scene);
+
+ if (pset->shape_object && (pset->shape_object->type == OB_MESH)) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+typedef struct PointInsideBVH {
+ BVHTreeFromMesh bvhdata;
+ int num_hits;
+} PointInsideBVH;
+
+static void point_inside_bvh_cb(void *userdata, int index, const BVHTreeRay *ray, BVHTreeRayHit *hit)
+{
+ PointInsideBVH *data = userdata;
+
+ data->bvhdata.raycast_callback(&data->bvhdata, index, ray, hit);
+
+ if (hit->index != -1)
+ ++data->num_hits;
+}
+
+/* true if the point is inside the shape mesh */
+static bool shape_cut_test_point(PEData *data, ParticleCacheKey *key)
+{
+ BVHTreeFromMesh *shape_bvh = &data->shape_bvh;
+ const float dir[3] = {1.0f, 0.0f, 0.0f};
+ PointInsideBVH userdata;
+
+ userdata.bvhdata = data->shape_bvh;
+ userdata.num_hits = 0;
+
+ BLI_bvhtree_ray_cast_all(shape_bvh->tree, key->co, dir, 0.0f, point_inside_bvh_cb, &userdata);
+
+ /* for any point inside a watertight mesh the number of hits is uneven */
+ return (userdata.num_hits % 2) == 1;
+}
+
+static void shape_cut(PEData *data, int pa_index)
+{
+ PTCacheEdit *edit = data->edit;
+ Object *ob = data->ob;
+ ParticleEditSettings *pset = PE_settings(data->scene);
+ ParticleCacheKey *key;
+
+ bool cut;
+ float cut_time = 1.0;
+ int k, totkeys = 1 << pset->draw_step;
+
+ /* don't cut hidden */
+ if (edit->points[pa_index].flag & PEP_HIDE)
+ return;
+
+ cut = false;
+
+ /* check if root is inside the cut shape */
+ key = edit->pathcache[pa_index];
+ if (!shape_cut_test_point(data, key)) {
+ cut_time = -1.0f;
+ cut = true;
+ }
+ else {
+ for (k = 0; k < totkeys; k++, key++) {
+ BVHTreeRayHit hit;
+ float dir[3];
+ float len;
+
+ sub_v3_v3v3(dir, (key+1)->co, key->co);
+ len = normalize_v3(dir);
+
+ memset(&hit, 0, sizeof(hit));
+ hit.index = -1;
+ hit.dist = len;
+ BLI_bvhtree_ray_cast(data->shape_bvh.tree, key->co, dir, 0.0f, &hit, data->shape_bvh.raycast_callback, &data->shape_bvh);
+ if (hit.index >= 0) {
+ if (hit.dist < len) {
+ cut_time = (hit.dist / len + (float)k) / (float)totkeys;
+ cut = true;
+ break;
+ }
+ }
+ }
+ }
+
+ if (cut) {
+ if (cut_time < 0.0f) {
+ edit->points[pa_index].flag |= PEP_TAG;
+ }
+ else {
+ rekey_particle_to_time(data->scene, ob, pa_index, cut_time);
+ edit->points[pa_index].flag |= PEP_EDIT_RECALC;
+ }
+ }
+}
+
+static int shape_cut_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ Scene *scene = CTX_data_scene(C);
+ Object *ob = CTX_data_active_object(C);
+ ParticleEditSettings *pset = PE_settings(scene);
+ PTCacheEdit *edit = PE_get_current(scene, ob);
+ Object *shapeob = pset->shape_object;
+ int selected = count_selected_keys(scene, edit);
+ int lock_root = pset->flag & PE_LOCK_FIRST;
+
+ if (!PE_start_edit(edit))
+ return OPERATOR_CANCELLED;
+
+ /* disable locking temporatily for disconnected hair */
+ if (edit->psys && edit->psys->flag & PSYS_GLOBAL_HAIR)
+ pset->flag &= ~PE_LOCK_FIRST;
+
+ if (edit->psys && edit->pathcache) {
+ PEData data;
+ int removed;
+
+ PE_set_data(C, &data);
+ if (!PE_create_shape_tree(&data, shapeob)) {
+ /* shapeob may not have faces... */
+ return OPERATOR_CANCELLED;
+ }
+
+ if (selected)
+ foreach_selected_point(&data, shape_cut);
+ else
+ foreach_point(&data, shape_cut);
+
+ removed = remove_tagged_particles(ob, edit->psys, pe_x_mirror(ob));
+ recalc_lengths(edit);
+
+ if (removed) {
+ update_world_cos(ob, edit);
+ psys_free_path_cache(NULL, edit);
+ DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ }
+ else
+ PE_update_object(scene, ob, 1);
+
+ if (edit->psys) {
+ WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_EDITED, ob);
+ }
+ else {
+ DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, ob);
+ }
+
+ PE_free_shape_tree(&data);
+ }
+
+ pset->flag |= lock_root;
+
+ return OPERATOR_FINISHED;
+}
+
+void PARTICLE_OT_shape_cut(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Shape Cut";
+ ot->idname = "PARTICLE_OT_shape_cut";
+ ot->description = "Cut hair to conform to the set shape object";
+
+ /* api callbacks */
+ ot->exec = shape_cut_exec;
+ ot->poll = shape_cut_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
/*********************** undo ***************************/
static void free_PTCacheUndo(PTCacheUndo *undo)
@@ -4168,7 +4449,7 @@ void PE_undo_step(Scene *scene, int step)
DAG_id_tag_update(&OBACT->id, OB_RECALC_DATA);
}
-int PE_undo_valid(Scene *scene)
+bool PE_undo_is_valid(Scene *scene)
{
PTCacheEdit *edit= PE_get_current(scene, OBACT);
@@ -4178,7 +4459,7 @@ int PE_undo_valid(Scene *scene)
return 0;
}
-static void PTCacheUndo_clear(PTCacheEdit *edit)
+void PTCacheUndo_clear(PTCacheEdit *edit)
{
PTCacheUndo *undo;
@@ -4219,18 +4500,19 @@ void PE_undo_number(Scene *scene, int nr)
/* get name of undo item, return null if no item with this index */
/* if active pointer, set it to 1 if true */
-const char *PE_undo_get_name(Scene *scene, int nr, int *active)
+const char *PE_undo_get_name(Scene *scene, int nr, bool *r_active)
{
PTCacheEdit *edit= PE_get_current(scene, OBACT);
PTCacheUndo *undo;
- if (active) *active= 0;
+ if (r_active) *r_active = false;
if (edit) {
undo= BLI_findlink(&edit->undo, nr);
if (undo) {
- if (active && undo==edit->curundo)
- *active= 1;
+ if (r_active && (undo == edit->curundo)) {
+ *r_active = true;
+ }
return undo->name;
}
}
@@ -4279,7 +4561,7 @@ int PE_minmax(Scene *scene, float min[3], float max[3])
/************************ particle edit toggle operator ************************/
/* initialize needed data for bake edit */
-static void PE_create_particle_edit(Scene *scene, Object *ob, PointCache *cache, ParticleSystem *psys)
+void PE_create_particle_edit(Scene *scene, Object *ob, PointCache *cache, ParticleSystem *psys)
{
PTCacheEdit *edit;
ParticleSystemModifierData *psmd = (psys) ? psys_get_modifier(ob, psys) : NULL;
diff --git a/source/blender/editors/physics/particle_object.c b/source/blender/editors/physics/particle_object.c
index 5a61f77e5a8..327ce060df9 100644
--- a/source/blender/editors/physics/particle_object.c
+++ b/source/blender/editors/physics/particle_object.c
@@ -40,18 +40,21 @@
#include "BLI_math.h"
#include "BLI_listbase.h"
#include "BLI_utildefines.h"
+#include "BLI_string.h"
#include "BKE_context.h"
#include "BKE_depsgraph.h"
#include "BKE_DerivedMesh.h"
#include "BKE_cdderivedmesh.h"
#include "BKE_global.h"
+#include "BKE_library.h"
#include "BKE_main.h"
+#include "BKE_modifier.h"
+#include "BKE_object.h"
#include "BKE_particle.h"
#include "BKE_pointcache.h"
#include "BKE_report.h"
-
#include "RNA_access.h"
#include "RNA_define.h"
@@ -62,8 +65,37 @@
#include "ED_screen.h"
#include "ED_object.h"
+#include "UI_resources.h"
+
#include "physics_intern.h"
+extern void PE_create_particle_edit(Scene *scene, Object *ob, PointCache *cache, ParticleSystem *psys);
+extern void PTCacheUndo_clear(PTCacheEdit *edit);
+extern void recalc_lengths(PTCacheEdit *edit);
+extern void recalc_emitter_field(Object *ob, ParticleSystem *psys);
+extern void update_world_cos(Object *ob, PTCacheEdit *edit);
+
+#define KEY_K PTCacheEditKey *key; int k
+#define POINT_P PTCacheEditPoint *point; int p
+#define LOOP_POINTS for (p=0, point=edit->points; p<edit->totpoint; p++, point++)
+#if 0
+#define LOOP_VISIBLE_POINTS for (p=0, point=edit->points; p<edit->totpoint; p++, point++) if (!(point->flag & PEP_HIDE))
+#define LOOP_SELECTED_POINTS for (p=0, point=edit->points; p<edit->totpoint; p++, point++) if (point_is_selected(point))
+#define LOOP_UNSELECTED_POINTS for (p=0, point=edit->points; p<edit->totpoint; p++, point++) if (!point_is_selected(point))
+#define LOOP_EDITED_POINTS for (p=0, point=edit->points; p<edit->totpoint; p++, point++) if (point->flag & PEP_EDIT_RECALC)
+#define LOOP_TAGGED_POINTS for (p=0, point=edit->points; p<edit->totpoint; p++, point++) if (point->flag & PEP_TAG)
+#endif
+#define LOOP_KEYS for (k=0, key=point->keys; k<point->totkey; k++, key++)
+#if 0
+#define LOOP_VISIBLE_KEYS for (k=0, key=point->keys; k<point->totkey; k++, key++) if (!(key->flag & PEK_HIDE))
+#define LOOP_SELECTED_KEYS for (k=0, key=point->keys; k<point->totkey; k++, key++) if ((key->flag & PEK_SELECT) && !(key->flag & PEK_HIDE))
+#define LOOP_TAGGED_KEYS for (k=0, key=point->keys; k<point->totkey; k++, key++) if (key->flag & PEK_TAG)
+
+#define KEY_WCO (key->flag & PEK_USE_WCO ? key->world_co : key->co)
+#endif
+
+static float I[4][4] = {{1.0f, 0.0f, 0.0f, 0.0f}, {0.0f, 1.0f, 0.0f, 0.0f}, {0.0f, 0.0f, 1.0f, 0.0f}, {0.0f, 0.0f, 0.0f, 1.0f}};
+
/********************** particle system slot operators *********************/
static int particle_system_add_exec(bContext *C, wmOperator *UNUSED(op))
@@ -623,38 +655,50 @@ void PARTICLE_OT_disconnect_hair(wmOperatorType *ot)
RNA_def_boolean(ot->srna, "all", 0, "All hair", "Disconnect all hair systems from the emitter mesh");
}
-static bool connect_hair(Scene *scene, Object *ob, ParticleSystem *psys)
+/* from/to_world_space : whether from/to particles are in world or hair space
+ * from/to_mat : additional transform for from/to particles (e.g. for using object space copying)
+ */
+static bool remap_hair_emitter(Scene *scene, Object *ob, ParticleSystem *psys,
+ Object *target_ob, ParticleSystem *target_psys, PTCacheEdit *target_edit,
+ float from_mat[4][4], float to_mat[4][4], bool from_global, bool to_global)
{
- ParticleSystemModifierData *psmd = psys_get_modifier(ob, psys);
- ParticleData *pa;
- PTCacheEdit *edit;
- PTCacheEditPoint *point;
- PTCacheEditKey *ekey = NULL;
- HairKey *key;
+ ParticleSystemModifierData *target_psmd = psys_get_modifier(target_ob, target_psys);
+ ParticleData *pa, *tpa;
+ PTCacheEditPoint *edit_point;
+ PTCacheEditKey *ekey;
BVHTreeFromMesh bvhtree= {NULL};
- BVHTreeNearest nearest;
MFace *mface = NULL, *mf;
MEdge *medge = NULL, *me;
MVert *mvert;
- DerivedMesh *dm = NULL;
+ DerivedMesh *dm, *target_dm;
int numverts;
int i, k;
- float hairmat[4][4], imat[4][4];
- float v[4][3], vec[3];
+ float from_ob_imat[4][4], to_ob_imat[4][4];
+ float from_imat[4][4], to_imat[4][4];
- if (!psys || !psys->part || psys->part->type != PART_HAIR || !psmd->dm)
+ if (!target_psmd->dm)
+ return false;
+ if (!psys->part || psys->part->type != PART_HAIR)
return false;
+ if (!target_psys->part || target_psys->part->type != PART_HAIR)
+ return false;
+
+ edit_point = target_edit ? target_edit->points : NULL;
- edit= psys->edit;
- point= edit ? edit->points : NULL;
+ invert_m4_m4(from_ob_imat, ob->obmat);
+ invert_m4_m4(to_ob_imat, target_ob->obmat);
+ invert_m4_m4(from_imat, from_mat);
+ invert_m4_m4(to_imat, to_mat);
- if (psmd->dm->deformedOnly) {
- /* we don't want to mess up psmd->dm when converting to global coordinates below */
- dm = psmd->dm;
+ if (target_psmd->dm->deformedOnly) {
+ /* we don't want to mess up target_psmd->dm when converting to global coordinates below */
+ dm = target_psmd->dm;
}
else {
- dm = mesh_get_derived_deform(scene, ob, CD_MASK_BAREMESH);
+ /* warning: this rebuilds target_psmd->dm! */
+ dm = mesh_get_derived_deform(scene, target_ob, CD_MASK_BAREMESH | CD_MASK_MFACE);
}
+ target_dm = target_psmd->dm;
/* don't modify the original vertices */
dm = CDDM_copy(dm);
@@ -662,12 +706,11 @@ static bool connect_hair(Scene *scene, Object *ob, ParticleSystem *psys)
DM_ensure_tessface(dm);
numverts = dm->getNumVerts(dm);
-
mvert = dm->getVertArray(dm);
/* convert to global coordinates */
for (i=0; i<numverts; i++)
- mul_m4_v3(ob->obmat, mvert[i].co);
+ mul_m4_v3(to_mat, mvert[i].co);
if (dm->getNumTessFaces(dm) != 0) {
mface = dm->getTessFaceArray(dm);
@@ -682,13 +725,23 @@ static bool connect_hair(Scene *scene, Object *ob, ParticleSystem *psys)
return false;
}
- for (i=0, pa= psys->particles; i<psys->totpart; i++, pa++) {
- key = pa->hair;
+ for (i = 0, tpa = target_psys->particles, pa = psys->particles;
+ i < target_psys->totpart;
+ i++, tpa++, pa++) {
+
+ float from_co[3];
+ BVHTreeNearest nearest;
+
+ if (from_global)
+ mul_v3_m4v3(from_co, from_ob_imat, pa->hair[0].co);
+ else
+ mul_v3_m4v3(from_co, from_ob_imat, pa->hair[0].world_co);
+ mul_m4_v3(from_mat, from_co);
nearest.index = -1;
nearest.dist_sq = FLT_MAX;
- BLI_bvhtree_find_nearest(bvhtree.tree, key->co, &nearest, bvhtree.nearest_callback, &bvhtree);
+ BLI_bvhtree_find_nearest(bvhtree.tree, from_co, &nearest, bvhtree.nearest_callback, &bvhtree);
if (nearest.index == -1) {
if (G.debug & G_DEBUG)
@@ -697,6 +750,8 @@ static bool connect_hair(Scene *scene, Object *ob, ParticleSystem *psys)
}
if (mface) {
+ float v[4][3];
+
mf = &mface[nearest.index];
copy_v3_v3(v[0], mvert[mf->v1].co);
@@ -704,44 +759,80 @@ static bool connect_hair(Scene *scene, Object *ob, ParticleSystem *psys)
copy_v3_v3(v[2], mvert[mf->v3].co);
if (mf->v4) {
copy_v3_v3(v[3], mvert[mf->v4].co);
- interp_weights_poly_v3(pa->fuv, v, 4, nearest.co);
+ interp_weights_poly_v3(tpa->fuv, v, 4, nearest.co);
}
else
- interp_weights_poly_v3(pa->fuv, v, 3, nearest.co);
+ interp_weights_poly_v3(tpa->fuv, v, 3, nearest.co);
+ tpa->foffset = 0.0f;
- pa->num = nearest.index;
- pa->num_dmcache = psys_particle_dm_face_lookup(ob, psmd->dm, pa->num, pa->fuv, NULL);
+ tpa->num = nearest.index;
+ tpa->num_dmcache = psys_particle_dm_face_lookup(target_ob, target_dm, tpa->num, tpa->fuv, NULL);
}
else {
me = &medge[nearest.index];
- pa->fuv[1] = line_point_factor_v3(nearest.co,
- mvert[me->v2].co,
- mvert[me->v2].co);
- pa->fuv[0] = 1.0f - pa->fuv[1];
- pa->fuv[2] = pa->fuv[3] = 0.0f;
+ tpa->fuv[1] = line_point_factor_v3(nearest.co,
+ mvert[me->v1].co,
+ mvert[me->v2].co);
+ tpa->fuv[0] = 1.0f - tpa->fuv[1];
+ tpa->fuv[2] = tpa->fuv[3] = 0.0f;
+ tpa->foffset = 0.0f;
- pa->num = nearest.index;
- pa->num_dmcache = -1;
+ tpa->num = nearest.index;
+ tpa->num_dmcache = -1;
}
- psys_mat_hair_to_global(ob, psmd->dm, psys->part->from, pa, hairmat);
- invert_m4_m4(imat, hairmat);
-
- sub_v3_v3v3(vec, nearest.co, key->co);
-
- if (point) {
- ekey = point->keys;
- point++;
- }
-
- for (k=0, key=pa->hair; k<pa->totkey; k++, key++) {
- add_v3_v3(key->co, vec);
- mul_m4_v3(imat, key->co);
-
- if (ekey) {
- ekey->flag |= PEK_USE_WCO;
- ekey++;
+ /* translate hair keys */
+ {
+ HairKey *key, *tkey;
+ float hairmat[4][4], imat[4][4];
+ float offset[3];
+
+ if (to_global)
+ copy_m4_m4(imat, target_ob->obmat);
+ else {
+ /* note: using target_dm here, which is in target_ob object space and has full modifiers */
+ psys_mat_hair_to_object(target_ob, target_dm, target_psys->part->from, tpa, hairmat);
+ invert_m4_m4(imat, hairmat);
+ }
+ mul_m4_m4m4(imat, imat, to_imat);
+
+ /* offset in world space */
+ sub_v3_v3v3(offset, nearest.co, from_co);
+
+ if (edit_point) {
+ for (k=0, key=pa->hair, tkey=tpa->hair, ekey = edit_point->keys; k<tpa->totkey; k++, key++, tkey++, ekey++) {
+ float co_orig[3];
+
+ if (from_global)
+ mul_v3_m4v3(co_orig, from_ob_imat, key->co);
+ else
+ mul_v3_m4v3(co_orig, from_ob_imat, key->world_co);
+ mul_m4_v3(from_mat, co_orig);
+
+ add_v3_v3v3(tkey->co, co_orig, offset);
+
+ mul_m4_v3(imat, tkey->co);
+
+ ekey->flag |= PEK_USE_WCO;
+ }
+
+ edit_point++;
+ }
+ else {
+ for (k=0, key=pa->hair, tkey=tpa->hair; k<tpa->totkey; k++, key++, tkey++) {
+ float co_orig[3];
+
+ if (from_global)
+ mul_v3_m4v3(co_orig, from_ob_imat, key->co);
+ else
+ mul_v3_m4v3(co_orig, from_ob_imat, key->world_co);
+ mul_m4_v3(from_mat, co_orig);
+
+ add_v3_v3v3(tkey->co, co_orig, offset);
+
+ mul_m4_v3(imat, tkey->co);
+ }
}
}
}
@@ -749,15 +840,26 @@ static bool connect_hair(Scene *scene, Object *ob, ParticleSystem *psys)
free_bvhtree_from_mesh(&bvhtree);
dm->release(dm);
- psys_free_path_cache(psys, psys->edit);
+ psys_free_path_cache(target_psys, target_edit);
- psys->flag &= ~PSYS_GLOBAL_HAIR;
-
- PE_update_object(scene, ob, 0);
+ PE_update_object(scene, target_ob, 0);
return true;
}
+static bool connect_hair(Scene *scene, Object *ob, ParticleSystem *psys)
+{
+ bool ok;
+
+ if (!psys)
+ return false;
+
+ ok = remap_hair_emitter(scene, ob, psys, ob, psys, psys->edit, ob->obmat, ob->obmat, psys->flag & PSYS_GLOBAL_HAIR, false);
+ psys->flag &= ~PSYS_GLOBAL_HAIR;
+
+ return ok;
+}
+
static int connect_hair_exec(bContext *C, wmOperator *op)
{
Scene *scene= CTX_data_scene(C);
@@ -805,3 +907,284 @@ void PARTICLE_OT_connect_hair(wmOperatorType *ot)
RNA_def_boolean(ot->srna, "all", 0, "All hair", "Connect all hair systems to the emitter mesh");
}
+/************************ particle system copy operator *********************/
+
+typedef enum eCopyParticlesSpace {
+ PAR_COPY_SPACE_OBJECT = 0,
+ PAR_COPY_SPACE_WORLD = 1,
+} eCopyParticlesSpace;
+
+static void copy_particle_edit(Scene *scene, Object *ob, ParticleSystem *psys, ParticleSystem *psys_from)
+{
+ PTCacheEdit *edit_from = psys_from->edit, *edit;
+ ParticleData *pa;
+ KEY_K;
+ POINT_P;
+
+ if (!edit_from)
+ return;
+
+ edit = MEM_dupallocN(edit_from);
+ edit->psys = psys;
+ psys->edit = edit;
+
+ edit->pathcache = NULL;
+ BLI_listbase_clear(&edit->pathcachebufs);
+
+ edit->emitter_field = NULL;
+ edit->emitter_cosnos = NULL;
+
+ BLI_listbase_clear(&edit->undo);
+ edit->curundo = NULL;
+
+ edit->points = MEM_dupallocN(edit_from->points);
+ pa = psys->particles;
+ LOOP_POINTS {
+ HairKey *hkey = pa->hair;
+
+ point->keys= MEM_dupallocN(point->keys);
+ LOOP_KEYS {
+ key->co = hkey->co;
+ key->time = &hkey->time;
+ key->flag = hkey->editflag;
+ if (!(psys->flag & PSYS_GLOBAL_HAIR)) {
+ key->flag |= PEK_USE_WCO;
+ hkey->editflag |= PEK_USE_WCO;
+ }
+
+ hkey++;
+ }
+
+ pa++;
+ }
+ update_world_cos(ob, edit);
+
+ UI_GetThemeColor3ubv(TH_EDGE_SELECT, edit->sel_col);
+ UI_GetThemeColor3ubv(TH_WIRE, edit->nosel_col);
+
+ recalc_lengths(edit);
+ recalc_emitter_field(ob, psys);
+ PE_update_object(scene, ob, true);
+
+ PTCacheUndo_clear(edit);
+ PE_undo_push(scene, "Original");
+}
+
+static void remove_particle_systems_from_object(Object *ob_to)
+{
+ ModifierData *md, *md_next;
+
+ if (ob_to->type != OB_MESH)
+ return;
+ if (!ob_to->data || ((ID *)ob_to->data)->lib)
+ return;
+
+ for (md = ob_to->modifiers.first; md; md = md_next) {
+ md_next = md->next;
+
+ /* remove all particle system modifiers as well,
+ * these need to sync to the particle system list
+ */
+ if (ELEM(md->type, eModifierType_ParticleSystem, eModifierType_DynamicPaint, eModifierType_Smoke)) {
+ BLI_remlink(&ob_to->modifiers, md);
+ modifier_free(md);
+ }
+ }
+
+ BKE_object_free_particlesystems(ob_to);
+}
+
+/* single_psys_from is optional, if NULL all psys of ob_from are copied */
+static bool copy_particle_systems_to_object(Scene *scene, Object *ob_from, ParticleSystem *single_psys_from, Object *ob_to, int space)
+{
+ ModifierData *md;
+ ParticleSystem *psys_start = NULL, *psys, *psys_from;
+ ParticleSystem **tmp_psys;
+ DerivedMesh *final_dm;
+ CustomDataMask cdmask;
+ int i, totpsys;
+
+ if (ob_to->type != OB_MESH)
+ return false;
+ if (!ob_to->data || ((ID *)ob_to->data)->lib)
+ return false;
+
+ /* For remapping we need a valid DM.
+ * Because the modifiers are appended at the end it's safe to use
+ * the final DM of the object without particles.
+ * However, when evaluating the DM all the particle modifiers must be valid,
+ * i.e. have the psys assigned already.
+ * To break this hen/egg problem we create all psys separately first (to collect required customdata masks),
+ * then create the DM, then add them to the object and make the psys modifiers ...
+ */
+ #define PSYS_FROM_FIRST (single_psys_from ? single_psys_from : ob_from->particlesystem.first)
+ #define PSYS_FROM_NEXT(cur) (single_psys_from ? NULL : (cur)->next)
+ totpsys = single_psys_from ? 1 : BLI_listbase_count(&ob_from->particlesystem);
+
+ tmp_psys = MEM_mallocN(sizeof(ParticleSystem*) * totpsys, "temporary particle system array");
+
+ cdmask = 0;
+ for (psys_from = PSYS_FROM_FIRST, i = 0;
+ psys_from;
+ psys_from = PSYS_FROM_NEXT(psys_from), ++i) {
+
+ psys = BKE_object_copy_particlesystem(psys_from);
+ tmp_psys[i] = psys;
+
+ if (psys_start == NULL)
+ psys_start = psys;
+
+ cdmask |= psys_emitter_customdata_mask(psys);
+ }
+ /* to iterate source and target psys in sync,
+ * we need to know where the newly added psys start
+ */
+ psys_start = totpsys > 0 ? tmp_psys[0] : NULL;
+
+ /* get the DM (psys and their modifiers have not been appended yet) */
+ final_dm = mesh_get_derived_final(scene, ob_to, cdmask);
+
+ /* now append psys to the object and make modifiers */
+ for (i = 0, psys_from = PSYS_FROM_FIRST;
+ i < totpsys;
+ ++i, psys_from = PSYS_FROM_NEXT(psys_from)) {
+
+ ParticleSystemModifierData *psmd;
+
+ psys = tmp_psys[i];
+
+ /* append to the object */
+ BLI_addtail(&ob_to->particlesystem, psys);
+
+ /* add a particle system modifier for each system */
+ md = modifier_new(eModifierType_ParticleSystem);
+ psmd = (ParticleSystemModifierData *)md;
+ /* push on top of the stack, no use trying to reproduce old stack order */
+ BLI_addtail(&ob_to->modifiers, md);
+
+ BLI_snprintf(md->name, sizeof(md->name), "ParticleSystem %i", i);
+ modifier_unique_name(&ob_to->modifiers, (ModifierData *)psmd);
+
+ psmd->psys = psys;
+ psmd->dm = CDDM_copy(final_dm);
+ CDDM_calc_normals(psmd->dm);
+ DM_ensure_tessface(psmd->dm);
+
+ if (psys_from->edit)
+ copy_particle_edit(scene, ob_to, psys, psys_from);
+ }
+ MEM_freeN(tmp_psys);
+
+ /* note: do this after creating DM copies for all the particle system modifiers,
+ * the remapping otherwise makes final_dm invalid!
+ */
+ for (psys = psys_start, psys_from = PSYS_FROM_FIRST, i = 0;
+ psys;
+ psys = psys->next, psys_from = PSYS_FROM_NEXT(psys_from), ++i) {
+
+ float (*from_mat)[4], (*to_mat)[4];
+
+ switch (space) {
+ case PAR_COPY_SPACE_OBJECT:
+ from_mat = I;
+ to_mat = I;
+ break;
+ case PAR_COPY_SPACE_WORLD:
+ from_mat = ob_from->obmat;
+ to_mat = ob_to->obmat;
+ break;
+ default:
+ /* should not happen */
+ BLI_assert(false);
+ break;
+ }
+
+ remap_hair_emitter(scene, ob_from, psys_from, ob_to, psys, psys->edit, from_mat, to_mat, psys_from->flag & PSYS_GLOBAL_HAIR, psys->flag & PSYS_GLOBAL_HAIR);
+
+ /* tag for recalc */
+// psys->recalc |= PSYS_RECALC_RESET;
+ }
+
+ #undef PSYS_FROM_FIRST
+ #undef PSYS_FROM_NEXT
+
+ DAG_id_tag_update(&ob_to->id, OB_RECALC_DATA);
+ WM_main_add_notifier(NC_OBJECT | ND_PARTICLE | NA_EDITED, ob_to);
+ return true;
+}
+
+static int copy_particle_systems_poll(bContext *C)
+{
+ Object *ob;
+ if (!ED_operator_object_active_editable(C))
+ return false;
+
+ ob = ED_object_active_context(C);
+ if (BLI_listbase_is_empty(&ob->particlesystem))
+ return false;
+
+ return true;
+}
+
+static int copy_particle_systems_exec(bContext *C, wmOperator *op)
+{
+ const int space = RNA_enum_get(op->ptr, "space");
+ const bool remove_target_particles = RNA_boolean_get(op->ptr, "remove_target_particles");
+ const bool use_active = RNA_boolean_get(op->ptr, "use_active");
+ Scene *scene = CTX_data_scene(C);
+ Object *ob_from = ED_object_active_context(C);
+ ParticleSystem *psys_from = use_active ? CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem).data : NULL;
+
+ int changed_tot = 0;
+ int fail = 0;
+
+ CTX_DATA_BEGIN (C, Object *, ob_to, selected_editable_objects)
+ {
+ if (ob_from != ob_to) {
+ bool changed = false;
+ if (remove_target_particles) {
+ remove_particle_systems_from_object(ob_to);
+ changed = true;
+ }
+ if (copy_particle_systems_to_object(scene, ob_from, psys_from, ob_to, space))
+ changed = true;
+ else
+ fail++;
+
+ if (changed)
+ changed_tot++;
+ }
+ }
+ CTX_DATA_END;
+
+ if ((changed_tot == 0 && fail == 0) || fail) {
+ BKE_reportf(op->reports, RPT_ERROR,
+ "Copy particle systems to selected: %d done, %d failed",
+ changed_tot, fail);
+ }
+
+ return OPERATOR_FINISHED;
+}
+
+void PARTICLE_OT_copy_particle_systems(wmOperatorType *ot)
+{
+ static EnumPropertyItem space_items[] = {
+ {PAR_COPY_SPACE_OBJECT, "OBJECT", 0, "Object", "Copy inside each object's local space"},
+ {PAR_COPY_SPACE_WORLD, "WORLD", 0, "World", "Copy in world space"},
+ {0, NULL, 0, NULL, NULL}
+ };
+
+ ot->name = "Copy Particle Systems";
+ ot->description = "Copy particle systems from the active object to selected objects";
+ ot->idname = "PARTICLE_OT_copy_particle_systems";
+
+ ot->poll = copy_particle_systems_poll;
+ ot->exec = copy_particle_systems_exec;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ RNA_def_enum(ot->srna, "space", space_items, PAR_COPY_SPACE_OBJECT, "Space", "Space transform for copying from one object to another");
+ RNA_def_boolean(ot->srna, "remove_target_particles", true, "Remove Target Particles", "Remove particle systems on the target objects");
+ RNA_def_boolean(ot->srna, "use_active", false, "Use Active", "Use the active particle system from the context");
+}
diff --git a/source/blender/editors/physics/physics_fluid.c b/source/blender/editors/physics/physics_fluid.c
index b53891f4880..b5adf38527b 100644
--- a/source/blender/editors/physics/physics_fluid.c
+++ b/source/blender/editors/physics/physics_fluid.c
@@ -72,8 +72,6 @@
#include "DNA_scene_types.h"
#include "DNA_mesh_types.h"
-#include "PIL_time.h"
-
static float get_fluid_viscosity(FluidsimSettings *settings)
{
diff --git a/source/blender/editors/physics/physics_intern.h b/source/blender/editors/physics/physics_intern.h
index 77ce5a334e6..666ed2397d2 100644
--- a/source/blender/editors/physics/physics_intern.h
+++ b/source/blender/editors/physics/physics_intern.h
@@ -39,6 +39,7 @@ struct wmOperatorType;
void PARTICLE_OT_select_all(struct wmOperatorType *ot);
void PARTICLE_OT_select_roots(struct wmOperatorType *ot);
void PARTICLE_OT_select_tips(struct wmOperatorType *ot);
+void PARTICLE_OT_select_random(struct wmOperatorType *ot);
void PARTICLE_OT_select_linked(struct wmOperatorType *ot);
void PARTICLE_OT_select_less(struct wmOperatorType *ot);
void PARTICLE_OT_select_more(struct wmOperatorType *ot);
@@ -55,6 +56,8 @@ void PARTICLE_OT_mirror(struct wmOperatorType *ot);
void PARTICLE_OT_brush_edit(struct wmOperatorType *ot);
+void PARTICLE_OT_shape_cut(struct wmOperatorType *ot);
+
void PARTICLE_OT_particle_edit_toggle(struct wmOperatorType *ot);
void PARTICLE_OT_edited_clear(struct wmOperatorType *ot);
@@ -69,6 +72,7 @@ void PARTICLE_OT_target_move_up(struct wmOperatorType *ot);
void PARTICLE_OT_target_move_down(struct wmOperatorType *ot);
void PARTICLE_OT_connect_hair(struct wmOperatorType *ot);
void PARTICLE_OT_disconnect_hair(struct wmOperatorType *ot);
+void PARTICLE_OT_copy_particle_systems(struct wmOperatorType *ot);
void PARTICLE_OT_dupliob_copy(struct wmOperatorType *ot);
void PARTICLE_OT_dupliob_remove(struct wmOperatorType *ot);
diff --git a/source/blender/editors/physics/physics_ops.c b/source/blender/editors/physics/physics_ops.c
index 48cc51ffb55..c765bff796e 100644
--- a/source/blender/editors/physics/physics_ops.c
+++ b/source/blender/editors/physics/physics_ops.c
@@ -29,10 +29,6 @@
#include <stdlib.h>
-#include "DNA_scene_types.h"
-
-#include "BLI_utildefines.h"
-
#include "RNA_access.h"
#include "WM_api.h"
@@ -51,6 +47,7 @@ static void operatortypes_particle(void)
WM_operatortype_append(PARTICLE_OT_select_all);
WM_operatortype_append(PARTICLE_OT_select_roots);
WM_operatortype_append(PARTICLE_OT_select_tips);
+ WM_operatortype_append(PARTICLE_OT_select_random);
WM_operatortype_append(PARTICLE_OT_select_linked);
WM_operatortype_append(PARTICLE_OT_select_less);
WM_operatortype_append(PARTICLE_OT_select_more);
@@ -67,6 +64,8 @@ static void operatortypes_particle(void)
WM_operatortype_append(PARTICLE_OT_brush_edit);
+ WM_operatortype_append(PARTICLE_OT_shape_cut);
+
WM_operatortype_append(PARTICLE_OT_particle_edit_toggle);
WM_operatortype_append(PARTICLE_OT_edited_clear);
@@ -81,6 +80,7 @@ static void operatortypes_particle(void)
WM_operatortype_append(PARTICLE_OT_target_move_down);
WM_operatortype_append(PARTICLE_OT_connect_hair);
WM_operatortype_append(PARTICLE_OT_disconnect_hair);
+ WM_operatortype_append(PARTICLE_OT_copy_particle_systems);
WM_operatortype_append(PARTICLE_OT_dupliob_copy);
WM_operatortype_append(PARTICLE_OT_dupliob_remove);
diff --git a/source/blender/editors/physics/rigidbody_constraint.c b/source/blender/editors/physics/rigidbody_constraint.c
index dd0816e509d..85b059d5574 100644
--- a/source/blender/editors/physics/rigidbody_constraint.c
+++ b/source/blender/editors/physics/rigidbody_constraint.c
@@ -37,8 +37,6 @@
#include "DNA_rigidbody_types.h"
#include "DNA_scene_types.h"
-#include "BLI_math.h"
-
#include "BKE_context.h"
#include "BKE_depsgraph.h"
#include "BKE_global.h"
diff --git a/source/blender/editors/physics/rigidbody_object.c b/source/blender/editors/physics/rigidbody_object.c
index 13a3d7a523f..949084973cf 100644
--- a/source/blender/editors/physics/rigidbody_object.c
+++ b/source/blender/editors/physics/rigidbody_object.c
@@ -33,24 +33,19 @@
#include <stdlib.h>
#include <string.h>
-#include "MEM_guardedalloc.h"
-#include "DNA_group_types.h"
#include "DNA_object_types.h"
-#include "DNA_mesh_types.h"
#include "DNA_rigidbody_types.h"
#include "DNA_scene_types.h"
#include "BLI_blenlib.h"
-#include "BLI_math.h"
-#include "BLF_translation.h"
+#include "BLT_translation.h"
#include "BKE_context.h"
#include "BKE_depsgraph.h"
#include "BKE_global.h"
#include "BKE_group.h"
-#include "BKE_object.h"
#include "BKE_report.h"
#include "BKE_rigidbody.h"
@@ -353,6 +348,7 @@ static int rigidbody_objects_shape_change_exec(bContext *C, wmOperator *op)
if (changed) {
/* send updates */
WM_event_add_notifier(C, NC_OBJECT | ND_POINTCACHE, NULL);
+ WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, NULL);
/* done */
return OPERATOR_FINISHED;
diff --git a/source/blender/editors/physics/rigidbody_world.c b/source/blender/editors/physics/rigidbody_world.c
index 1c893992cf2..0bd9ec5f4cd 100644
--- a/source/blender/editors/physics/rigidbody_world.c
+++ b/source/blender/editors/physics/rigidbody_world.c
@@ -37,8 +37,6 @@
#include "DNA_rigidbody_types.h"
#include "DNA_scene_types.h"
-#include "BLI_math.h"
-
#ifdef WITH_BULLET
# include "RBI_api.h"
#endif
@@ -48,8 +46,6 @@
#include "BKE_rigidbody.h"
#include "RNA_access.h"
-#include "RNA_define.h"
-#include "RNA_enum_types.h"
#include "WM_api.h"
#include "WM_types.h"
@@ -171,7 +167,7 @@ static int rigidbody_world_export_exec(bContext *C, wmOperator *op)
static int rigidbody_world_export_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
if (!RNA_struct_property_is_set(op->ptr, "relative_path"))
- RNA_boolean_set(op->ptr, "relative_path", (U.flag & USER_RELPATHS));
+ RNA_boolean_set(op->ptr, "relative_path", (U.flag & USER_RELPATHS) != 0);
if (RNA_struct_property_is_set(op->ptr, "filepath"))
return rigidbody_world_export_exec(C, op);
@@ -199,5 +195,5 @@ void RIGIDBODY_OT_world_export(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
/* properties */
- WM_operator_properties_filesel(ot, FOLDERFILE, FILE_SPECIAL, FILE_SAVE, FILE_RELPATH, FILE_DEFAULTDISPLAY);
+ WM_operator_properties_filesel(ot, FILE_TYPE_FOLDER, FILE_SPECIAL, FILE_SAVE, FILE_RELPATH, FILE_DEFAULTDISPLAY, FILE_SORT_ALPHA);
}
diff --git a/source/blender/editors/render/CMakeLists.txt b/source/blender/editors/render/CMakeLists.txt
index 24015bd4ea3..971ab9f3458 100644
--- a/source/blender/editors/render/CMakeLists.txt
+++ b/source/blender/editors/render/CMakeLists.txt
@@ -20,10 +20,10 @@
set(INC
../include
- ../../blenfont
../../blenkernel
../../blenlib
../../blenloader
+ ../../blentranslation
../../gpu
../../imbuf
../../bmesh
@@ -32,6 +32,7 @@ set(INC
../../render/extern/include
../../windowmanager
../../../../intern/guardedalloc
+ ../../../../intern/glew-mx
)
set(INC_SYS
@@ -64,6 +65,8 @@ if(WITH_HEADLESS)
add_definitions(-DWITH_HEADLESS)
endif()
+add_definitions(${GL_DEFINITIONS})
+
if(WITH_FREESTYLE)
list(APPEND INC
../../freestyle
diff --git a/source/blender/editors/render/SConscript b/source/blender/editors/render/SConscript
index 41576f9b485..24270ca2324 100644
--- a/source/blender/editors/render/SConscript
+++ b/source/blender/editors/render/SConscript
@@ -31,13 +31,15 @@ sources = env.Glob('*.c')
incs = [
'#/intern/guardedalloc',
- '#/extern/glew/include',
+ env['BF_GLEW_INC'],
+ '#/intern/glew-mx',
'#/intern/elbeem/extern',
'../include',
'../../blenfont',
'../../blenkernel',
'../../blenlib',
'../../blenloader',
+ '../../blentranslation',
'../../bmesh',
'../../gpu',
'../../imbuf',
@@ -49,6 +51,7 @@ incs = [
incs = ' '.join(incs)
defs = []
+defs += env['BF_GL_DEFINITIONS']
if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'linuxcross', 'win64-vc', 'win64-mingw'):
incs += ' ' + env['BF_PTHREADS_INC']
diff --git a/source/blender/editors/render/render_intern.h b/source/blender/editors/render/render_intern.h
index f9377d576bf..54429f9f066 100644
--- a/source/blender/editors/render/render_intern.h
+++ b/source/blender/editors/render/render_intern.h
@@ -32,9 +32,9 @@
#ifndef __RENDER_INTERN_H__
#define __RENDER_INTERN_H__
+struct bContext;
+struct RenderEngine;
struct wmOperatorType;
-struct RenderResult;
-struct Scene;
struct ScrArea;
/* render_shading.c */
@@ -44,6 +44,7 @@ void OBJECT_OT_material_slot_assign(struct wmOperatorType *ot);
void OBJECT_OT_material_slot_select(struct wmOperatorType *ot);
void OBJECT_OT_material_slot_deselect(struct wmOperatorType *ot);
void OBJECT_OT_material_slot_copy(struct wmOperatorType *ot);
+void OBJECT_OT_material_slot_move(struct wmOperatorType *ot);
void MATERIAL_OT_new(struct wmOperatorType *ot);
void TEXTURE_OT_new(struct wmOperatorType *ot);
@@ -55,6 +56,9 @@ void MATERIAL_OT_paste(struct wmOperatorType *ot);
void SCENE_OT_render_layer_add(struct wmOperatorType *ot);
void SCENE_OT_render_layer_remove(struct wmOperatorType *ot);
+void SCENE_OT_render_view_add(struct wmOperatorType *ot);
+void SCENE_OT_render_view_remove(struct wmOperatorType *ot);
+
#ifdef WITH_FREESTYLE
void SCENE_OT_freestyle_module_add(struct wmOperatorType *ot);
void SCENE_OT_freestyle_module_remove(struct wmOperatorType *ot);
diff --git a/source/blender/editors/render/render_internal.c b/source/blender/editors/render/render_internal.c
index baf25a49f7c..10de2d667ea 100644
--- a/source/blender/editors/render/render_internal.c
+++ b/source/blender/editors/render/render_internal.c
@@ -33,14 +33,16 @@
#include "MEM_guardedalloc.h"
-#include "BLI_blenlib.h"
+#include "BLI_listbase.h"
+#include "BLI_rect.h"
+#include "BLI_timecode.h"
#include "BLI_math.h"
#include "BLI_threads.h"
#include "BLI_utildefines.h"
#include "PIL_time.h"
-#include "BLF_translation.h"
+#include "BLT_translation.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
@@ -48,6 +50,7 @@
#include "DNA_userdef_types.h"
#include "BKE_blender.h"
+#include "BKE_camera.h"
#include "BKE_context.h"
#include "BKE_colortools.h"
#include "BKE_depsgraph.h"
@@ -75,10 +78,8 @@
#include "RE_engine.h"
#include "IMB_colormanagement.h"
-#include "IMB_imbuf.h"
#include "IMB_imbuf_types.h"
-#include "GPU_extensions.h"
#include "BIF_gl.h"
#include "BIF_glutil.h"
@@ -86,7 +87,6 @@
#include "RNA_access.h"
#include "RNA_define.h"
-#include "wm_window.h"
#include "render_intern.h"
@@ -119,7 +119,7 @@ typedef struct RenderJob {
} RenderJob;
/* called inside thread! */
-static void image_buffer_rect_update(RenderJob *rj, RenderResult *rr, ImBuf *ibuf, ImageUser *iuser, volatile rcti *renrect)
+static void image_buffer_rect_update(RenderJob *rj, RenderResult *rr, ImBuf *ibuf, ImageUser *iuser, volatile rcti *renrect, const char *viewname)
{
Scene *scene = rj->scene;
const float *rectf = NULL;
@@ -191,11 +191,15 @@ static void image_buffer_rect_update(RenderJob *rj, RenderResult *rr, ImBuf *ibu
*/
/* TODO(sergey): Need to check has_combined here? */
if (iuser->pass == 0) {
+ RenderView *rv;
+ size_t view_id = BKE_scene_multiview_view_id_get(&scene->r, viewname);
+ rv = RE_RenderViewGetById(rr, view_id);
+
/* find current float rect for display, first case is after composite... still weak */
- if (rr->rectf)
- rectf = rr->rectf;
+ if (rv->rectf)
+ rectf = rv->rectf;
else {
- if (rr->rect32) {
+ if (rv->rect32) {
/* special case, currently only happens with sequencer rendering,
* which updates the whole frame, so we can only mark display buffer
* as invalid here (sergey)
@@ -204,8 +208,8 @@ static void image_buffer_rect_update(RenderJob *rj, RenderResult *rr, ImBuf *ibu
return;
}
else {
- if (rr->renlay == NULL || rr->renlay->rectf == NULL) return;
- rectf = rr->renlay->rectf;
+ if (rr->renlay == NULL) return;
+ rectf = RE_RenderLayerGetPass(rr->renlay, SCE_PASS_COMBINED, viewname);
}
}
if (rectf == NULL) return;
@@ -343,7 +347,11 @@ static void render_freejob(void *rjv)
}
/* str is IMA_MAX_RENDER_TEXT in size */
-static void make_renderinfo_string(RenderStats *rs, Scene *scene, bool v3d_override, char *str)
+static void make_renderinfo_string(const RenderStats *rs,
+ const Scene *scene,
+ const bool v3d_override,
+ const char *error,
+ char *str)
{
char info_time_str[32]; // used to be extern to header_info.c
uintptr_t mem_in_use, mmap_in_use, peak_memory;
@@ -368,7 +376,7 @@ static void make_renderinfo_string(RenderStats *rs, Scene *scene, bool v3d_overr
spos += sprintf(spos, IFACE_("Frame:%d "), (scene->r.cfra));
/* previous and elapsed time */
- BLI_timestr(rs->lastframetime, info_time_str, sizeof(info_time_str));
+ BLI_timecode_string_from_time_simple(info_time_str, sizeof(info_time_str), rs->lastframetime);
if (rs->infostr && rs->infostr[0]) {
if (rs->lastframetime != 0.0)
@@ -376,7 +384,7 @@ static void make_renderinfo_string(RenderStats *rs, Scene *scene, bool v3d_overr
else
spos += sprintf(spos, "| ");
- BLI_timestr(PIL_check_seconds_timer() - rs->starttime, info_time_str, sizeof(info_time_str));
+ BLI_timecode_string_from_time_simple(info_time_str, sizeof(info_time_str), PIL_check_seconds_timer() - rs->starttime);
}
else
spos += sprintf(spos, "| ");
@@ -416,8 +424,12 @@ static void make_renderinfo_string(RenderStats *rs, Scene *scene, bool v3d_overr
spos += sprintf(spos, IFACE_("| Full Sample %d "), rs->curfsa);
/* extra info */
- if (rs->infostr && rs->infostr[0])
+ if (rs->infostr && rs->infostr[0]) {
spos += sprintf(spos, "| %s ", rs->infostr);
+ }
+ else if (error && error[0]) {
+ spos += sprintf(spos, "| %s ", error);
+ }
/* very weak... but 512 characters is quite safe */
if (spos >= str + IMA_MAX_RENDER_TEXT)
@@ -438,7 +450,8 @@ static void image_renderinfo_cb(void *rjv, RenderStats *rs)
if (rr->text == NULL)
rr->text = MEM_callocN(IMA_MAX_RENDER_TEXT, "rendertext");
- make_renderinfo_string(rs, rj->scene, rj->v3d_override, rr->text);
+ make_renderinfo_string(rs, rj->scene, rj->v3d_override,
+ rr->error, rr->text);
}
RE_ReleaseResult(rj->re);
@@ -525,6 +538,7 @@ static void image_rect_update(void *rjv, RenderResult *rr, volatile rcti *renrec
Image *ima = rj->image;
ImBuf *ibuf;
void *lock;
+ const char *viewname = RE_GetActiveRenderView(rj->re);
/* only update if we are displaying the slot being rendered */
if (ima->render_slot != ima->last_render_slot) {
@@ -557,7 +571,7 @@ static void image_rect_update(void *rjv, RenderResult *rr, volatile rcti *renrec
ibuf->channels == 1 ||
U.image_draw_method != IMAGE_DRAW_METHOD_GLSL)
{
- image_buffer_rect_update(rj, rr, ibuf, &rj->iuser, renrect);
+ image_buffer_rect_update(rj, rr, ibuf, &rj->iuser, renrect, viewname);
}
/* make jobs timer to send notifier */
@@ -779,13 +793,13 @@ static void clean_viewport_memory(Main *bmain, Scene *scene, int renderlay)
if ((base->lay & renderlay) == 0) {
continue;
}
-
if (RE_allow_render_generic_object(base->object)) {
base->object->id.flag &= ~LIB_DOIT;
}
}
- for (object = bmain->object.first; object; object = object->id.next) {
+ for (SETLOOPER(scene, sce_iter, base)) {
+ object = base->object;
if ((object->id.flag & LIB_DOIT) == 0) {
continue;
}
@@ -1121,7 +1135,7 @@ static void render_view3d_renderinfo_cb(void *rjp, RenderStats *rs)
*rp->stop = 1;
}
else {
- make_renderinfo_string(rs, rp->scene, false, rp->engine->text);
+ make_renderinfo_string(rs, rp->scene, false, NULL, rp->engine->text);
/* make jobs timer to send notifier */
*(rp->do_update) = true;
@@ -1140,8 +1154,8 @@ BLI_INLINE void rcti_scale_coords(rcti *scaled_rect, const rcti *rect,
static void render_update_resolution(Render *re, const RenderPreview *rp,
bool use_border, const rcti *clip_rect)
{
- int winx = rp->ar->winx / rp->resolution_divider,
- winy = rp->ar->winy / rp->resolution_divider;
+ int winx = rp->ar->winx / rp->resolution_divider;
+ int winy = rp->ar->winy / rp->resolution_divider;
if (use_border) {
rcti scaled_cliprct;
rcti_scale_coords(&scaled_cliprct, clip_rect,
@@ -1221,10 +1235,10 @@ static void render_view3d_startjob(void *customdata, short *stop, short *do_upda
if ((update_flag & (PR_UPDATE_RENDERSIZE | PR_UPDATE_DATABASE)) || rstats->convertdone == 0) {
RenderData rdata;
- /* no osa, blur, seq, layers, etc for preview render */
+ /* no osa, blur, seq, layers, savebuffer etc for preview render */
rdata = rp->scene->r;
rdata.mode &= ~(R_OSA | R_MBLUR | R_BORDER | R_PANORAMA);
- rdata.scemode &= ~(R_DOSEQ | R_DOCOMP | R_FREE_IMAGE);
+ rdata.scemode &= ~(R_DOSEQ | R_DOCOMP | R_FREE_IMAGE | R_EXR_TILE_FILE | R_FULL_SAMPLE);
rdata.scemode |= R_VIEWPORT_PREVIEW;
/* we do use layers, but only active */
@@ -1439,7 +1453,7 @@ static void render_view3d_do(RenderEngine *engine, const bContext *C)
rp->bmain = CTX_data_main(C);
rp->resolution_divider = divider;
rp->start_resolution_divider = divider;
- rp->has_freestyle = scene->r.mode & R_EDGE_FRS;
+ rp->has_freestyle = (scene->r.mode & R_EDGE_FRS) != 0;
copy_m4_m4(rp->viewmat, rp->rv3d->viewmat);
/* clear info text */
@@ -1455,7 +1469,7 @@ static void render_view3d_do(RenderEngine *engine, const bContext *C)
engine->flag &= ~RE_ENGINE_DO_UPDATE;
}
-/* callback for render engine , on changes */
+/* callback for render engine, on changes */
void render_view3d_update(RenderEngine *engine, const bContext *C)
{
/* this shouldn't be needed and causes too many database rebuilds, but we
@@ -1481,7 +1495,8 @@ void render_view3d_draw(RenderEngine *engine, const bContext *C)
if (re == NULL) return;
}
- RE_AcquireResultImage(re, &rres);
+ /* Viewport render preview doesn't support multiview, view hardcoded to 0 */
+ RE_AcquireResultImage(re, &rres, 0);
if (rres.rectf) {
RegionView3D *rv3d = CTX_wm_region_view3d(C);
@@ -1551,10 +1566,10 @@ void render_view3d_draw(RenderEngine *engine, const bContext *C)
RE_ReleaseResultImage(re);
}
-void ED_viewport_render_kill_jobs(const bContext *C, bool free_database)
+void ED_viewport_render_kill_jobs(wmWindowManager *wm,
+ Main *bmain,
+ bool free_database)
{
- wmWindowManager *wm = CTX_wm_manager(C);
- Main *bmain = CTX_data_main(C);
bScreen *sc;
ScrArea *sa;
ARegion *ar;
@@ -1611,7 +1626,17 @@ Scene *ED_render_job_get_scene(const bContext *C)
RenderJob *rj = (RenderJob *)WM_jobs_customdata_from_type(wm, WM_JOB_TYPE_RENDER);
if (rj)
- return rj->current_scene;
+ return rj->scene;
return NULL;
}
+
+Scene *ED_render_job_get_current_scene(const bContext *C)
+{
+ wmWindowManager *wm = CTX_wm_manager(C);
+ RenderJob *rj = (RenderJob *)WM_jobs_customdata_from_type(wm, WM_JOB_TYPE_RENDER);
+ if (rj) {
+ return rj->current_scene;
+ }
+ return NULL;
+}
diff --git a/source/blender/editors/render/render_opengl.c b/source/blender/editors/render/render_opengl.c
index ecf5e962c80..fe4022709de 100644
--- a/source/blender/editors/render/render_opengl.c
+++ b/source/blender/editors/render/render_opengl.c
@@ -31,19 +31,20 @@
#include <string.h>
#include <stddef.h>
-#include <GL/glew.h>
-
#include "MEM_guardedalloc.h"
+#include "DNA_camera_types.h"
#include "BLI_math.h"
#include "BLI_math_color_blend.h"
#include "BLI_blenlib.h"
#include "BLI_utildefines.h"
#include "BLI_jitter.h"
+#include "BLI_threads.h"
#include "DNA_scene_types.h"
#include "DNA_object_types.h"
+#include "BKE_camera.h"
#include "BKE_context.h"
#include "BKE_global.h"
#include "BKE_image.h"
@@ -69,8 +70,9 @@
#include "RNA_define.h"
#include "GPU_extensions.h"
+#include "GPU_glew.h"
+#include "GPU_compositing.h"
-#include "wm_window.h"
#include "render_intern.h"
@@ -94,6 +96,7 @@ typedef struct OGLRender {
ImageUser iuser;
GPUOffScreen *ofs;
+ GPUFX *fx;
int sizex, sizey;
int write_still;
@@ -101,11 +104,17 @@ typedef struct OGLRender {
bMovieHandle *mh;
int cfrao, nfra;
+ size_t totvideos;
+
+ /* quick lookup */
+ int view_id;
+
/* wm vars for timer and progress cursor */
wmWindowManager *wm;
wmWindow *win;
wmTimer *timer; /* use to check if running modal or not (invoke'd or exec'd)*/
+ void **movie_ctx_arr;
} OGLRender;
/* added because v3d is not always valid */
@@ -119,25 +128,144 @@ static unsigned int screen_opengl_layers(OGLRender *oglrender)
}
}
-static void screen_opengl_render_apply(OGLRender *oglrender)
+static bool screen_opengl_is_multiview(OGLRender *oglrender)
+{
+ View3D *v3d = oglrender->v3d;
+ RegionView3D *rv3d = oglrender->rv3d;
+ RenderData *rd = &oglrender->scene->r;
+
+ if ((rd == NULL) || ((!oglrender->is_sequencer) && ((rv3d == NULL) || (v3d == NULL))))
+ return false;
+
+ return (rd->scemode & R_MULTIVIEW) && ((oglrender->is_sequencer) || (rv3d->persp == RV3D_CAMOB && v3d->camera));
+}
+
+static void screen_opengl_views_setup(OGLRender *oglrender)
+{
+ RenderResult *rr;
+ RenderView *rv;
+ SceneRenderView *srv;
+ bool is_multiview;
+ Object *camera;
+ View3D *v3d = oglrender->v3d;
+
+ RenderData *rd = &oglrender->scene->r;
+
+ rr = RE_AcquireResultWrite(oglrender->re);
+
+ is_multiview = screen_opengl_is_multiview(oglrender);
+
+ if (!is_multiview) {
+ /* we only have one view when multiview is off */
+ rv = rr->views.first;
+
+ if (rv == NULL) {
+ rv = MEM_callocN(sizeof(RenderView), "new opengl render view");
+ BLI_addtail(&rr->views, rv);
+ }
+
+ while (rv->next) {
+ RenderView *rv_del = rv->next;
+ BLI_remlink(&rr->views, rv_del);
+
+ if (rv_del->rectf)
+ MEM_freeN(rv_del->rectf);
+
+ if (rv_del->rectz)
+ MEM_freeN(rv_del->rectz);
+
+ MEM_freeN(rv_del);
+ }
+ }
+ else {
+ if (!oglrender->is_sequencer)
+ RE_SetOverrideCamera(oglrender->re, V3D_CAMERA_SCENE(oglrender->scene, v3d));
+
+ /* remove all the views that are not needed */
+ rv = rr->views.last;
+ while (rv) {
+ srv = BLI_findstring(&rd->views, rv->name, offsetof(SceneRenderView, name));
+ if (BKE_scene_multiview_is_render_view_active(rd, srv)) {
+ if (rv->rectf == NULL)
+ rv->rectf = MEM_callocN(sizeof(float) * 4 * oglrender->sizex * oglrender->sizey, "screen_opengl_render_init rect");
+ rv = rv->prev;
+ }
+ else {
+ RenderView *rv_del = rv;
+ rv = rv_del->prev;
+
+ BLI_remlink(&rr->views, rv_del);
+
+ if (rv_del->rectf)
+ MEM_freeN(rv_del->rectf);
+
+ if (rv_del->rectz)
+ MEM_freeN(rv_del->rectz);
+
+ MEM_freeN(rv_del);
+ }
+ }
+
+ /* create all the views that are needed */
+ for (srv = rd->views.first; srv; srv = srv->next) {
+ if (BKE_scene_multiview_is_render_view_active(rd, srv) == false)
+ continue;
+
+ rv = BLI_findstring(&rr->views, srv->name, offsetof(SceneRenderView, name));
+
+ if (rv == NULL) {
+ rv = MEM_callocN(sizeof(RenderView), "new opengl render view");
+ BLI_strncpy(rv->name, srv->name, sizeof(rv->name));
+ BLI_addtail(&rr->views, rv);
+ }
+ }
+ }
+
+ for (rv = rr->views.first; rv; rv = rv->next) {
+ if (rv->rectf == NULL) {
+ rv->rectf = MEM_callocN(sizeof(float) * 4 * oglrender->sizex * oglrender->sizey, "screen_opengl_render_init rect");
+ }
+ }
+
+ BLI_lock_thread(LOCK_DRAW_IMAGE);
+ if (is_multiview && BKE_scene_multiview_is_stereo3d(rd)) {
+ oglrender->ima->flag |= IMA_IS_STEREO;
+ }
+ else {
+ oglrender->ima->flag &= ~IMA_IS_STEREO;
+ oglrender->iuser.flag &= ~IMA_SHOW_STEREO;
+ }
+ BLI_unlock_thread(LOCK_DRAW_IMAGE);
+
+ /* will only work for non multiview correctly */
+ if (v3d) {
+ camera = BKE_camera_multiview_render(oglrender->scene, v3d->camera, "new opengl render view");
+ BKE_render_result_stamp_info(oglrender->scene, camera, rr, false);
+ }
+ else {
+ BKE_render_result_stamp_info(oglrender->scene, oglrender->scene->camera, rr, false);
+ }
+
+ RE_ReleaseResult(oglrender->re);
+}
+
+static void screen_opengl_render_doit(OGLRender *oglrender, RenderResult *rr)
{
Scene *scene = oglrender->scene;
ARegion *ar = oglrender->ar;
View3D *v3d = oglrender->v3d;
RegionView3D *rv3d = oglrender->rv3d;
- RenderResult *rr;
Object *camera = NULL;
ImBuf *ibuf;
- void *lock;
float winmat[4][4];
+ float *rectf = RE_RenderViewGetById(rr, oglrender->view_id)->rectf;
int sizex = oglrender->sizex;
int sizey = oglrender->sizey;
const short view_context = (v3d != NULL);
bool draw_bgpic = true;
bool draw_sky = (scene->r.alphamode == R_ADDSKY);
unsigned char *rect = NULL;
-
- rr = RE_AcquireResultRead(oglrender->re);
+ const char *viewname = RE_GetActiveRenderView(oglrender->re);
if (oglrender->is_sequencer) {
SeqRenderData context;
@@ -145,9 +273,12 @@ static void screen_opengl_render_apply(OGLRender *oglrender)
int chanshown = sseq ? sseq->chanshown : 0;
struct bGPdata *gpd = (sseq && (sseq->flag & SEQ_SHOW_GPENCIL)) ? sseq->gpd : NULL;
- context = BKE_sequencer_new_render_data(oglrender->bmain->eval_ctx, oglrender->bmain,
- scene, oglrender->sizex, oglrender->sizey, 100.0f);
+ BKE_sequencer_new_render_data(
+ oglrender->bmain->eval_ctx, oglrender->bmain, scene,
+ oglrender->sizex, oglrender->sizey, 100.0f,
+ &context);
+ context.view_id = BKE_scene_multiview_view_id_get(&scene->r, viewname);
ibuf = BKE_sequencer_give_ibuf(&context, CFRA, chanshown);
if (ibuf) {
@@ -171,7 +302,7 @@ static void screen_opengl_render_apply(OGLRender *oglrender)
BKE_sequencer_imbuf_from_sequencer_space(scene, linear_ibuf);
}
- memcpy(rr->rectf, linear_ibuf->rect_float, sizeof(float) * 4 * oglrender->sizex * oglrender->sizey);
+ memcpy(rectf, linear_ibuf->rect_float, sizeof(float) * 4 * oglrender->sizex * oglrender->sizey);
IMB_freeImBuf(linear_ibuf);
}
@@ -180,7 +311,7 @@ static void screen_opengl_render_apply(OGLRender *oglrender)
int i;
unsigned char *gp_rect;
- GPU_offscreen_bind(oglrender->ofs);
+ GPU_offscreen_bind(oglrender->ofs, true);
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
@@ -188,32 +319,48 @@ static void screen_opengl_render_apply(OGLRender *oglrender)
wmOrtho2(0, sizex, 0, sizey);
glTranslatef(sizex / 2, sizey / 2, 0.0f);
- ED_gpencil_draw_ex(gpd, sizex, sizey, scene->r.cfra);
+ G.f |= G_RENDER_OGL;
+ ED_gpencil_draw_ex(scene, gpd, sizex, sizey, scene->r.cfra, SPACE_SEQ);
+ G.f &= ~G_RENDER_OGL;
gp_rect = MEM_mallocN(sizex * sizey * sizeof(unsigned char) * 4, "offscreen rect");
GPU_offscreen_read_pixels(oglrender->ofs, GL_UNSIGNED_BYTE, gp_rect);
+ BLI_assert(rectf != NULL);
+
for (i = 0; i < sizex * sizey * 4; i += 4) {
float col_src[4];
rgba_uchar_to_float(col_src, &gp_rect[i]);
- blend_color_mix_float(&rr->rectf[i], &rr->rectf[i], col_src);
+ blend_color_mix_float(&rectf[i], &rectf[i], col_src);
}
- GPU_offscreen_unbind(oglrender->ofs);
+ GPU_offscreen_unbind(oglrender->ofs, true);
MEM_freeN(gp_rect);
}
}
else if (view_context) {
+ bool is_persp;
+ /* full copy */
+ GPUFXSettings fx_settings = v3d->fx_settings;
+
ED_view3d_draw_offscreen_init(scene, v3d);
- GPU_offscreen_bind(oglrender->ofs); /* bind */
+ GPU_offscreen_bind(oglrender->ofs, true); /* bind */
/* render 3d view */
if (rv3d->persp == RV3D_CAMOB && v3d->camera) {
- /*int is_ortho = scene->r.mode & R_ORTHO;*/
- camera = v3d->camera;
+#if 0
+ const bool is_ortho = (scene->r.mode & R_ORTHO) != 0;
+#endif
+ camera = BKE_camera_multiview_render(oglrender->scene, v3d->camera, viewname);
RE_GetCameraWindow(oglrender->re, camera, scene->r.cfra, winmat);
-
+ if (camera->type == OB_CAMERA) {
+ Camera *cam = camera->data;
+ is_persp = cam->type == CAM_PERSP;
+ }
+ else
+ is_persp = true;
+ BKE_camera_to_gpu_dof(camera, &fx_settings);
}
else {
rctf viewplane;
@@ -222,12 +369,17 @@ static void screen_opengl_render_apply(OGLRender *oglrender)
bool is_ortho = ED_view3d_viewplane_get(v3d, rv3d, sizex, sizey, &viewplane, &clipsta, &clipend, NULL);
if (is_ortho) orthographic_m4(winmat, viewplane.xmin, viewplane.xmax, viewplane.ymin, viewplane.ymax, -clipend, clipend);
else perspective_m4(winmat, viewplane.xmin, viewplane.xmax, viewplane.ymin, viewplane.ymax, clipsta, clipend);
+
+ is_persp = !is_ortho;
}
rect = MEM_mallocN(sizex * sizey * sizeof(unsigned char) * 4, "offscreen rect");
if ((scene->r.mode & R_OSA) == 0) {
- ED_view3d_draw_offscreen(scene, v3d, ar, sizex, sizey, NULL, winmat, draw_bgpic, draw_sky);
+ ED_view3d_draw_offscreen(
+ scene, v3d, ar, sizex, sizey, NULL, winmat,
+ draw_bgpic, draw_sky, is_persp,
+ oglrender->ofs, oglrender->fx, &fx_settings, viewname);
GPU_offscreen_read_pixels(oglrender->ofs, GL_UNSIGNED_BYTE, rect);
}
else {
@@ -240,7 +392,10 @@ static void screen_opengl_render_apply(OGLRender *oglrender)
BLI_jitter_init(jit_ofs, scene->r.osa);
/* first sample buffer, also initializes 'rv3d->persmat' */
- ED_view3d_draw_offscreen(scene, v3d, ar, sizex, sizey, NULL, winmat, draw_bgpic, draw_sky);
+ ED_view3d_draw_offscreen(
+ scene, v3d, ar, sizex, sizey, NULL, winmat,
+ draw_bgpic, draw_sky, is_persp,
+ oglrender->ofs, oglrender->fx, &fx_settings, viewname);
GPU_offscreen_read_pixels(oglrender->ofs, GL_UNSIGNED_BYTE, rect);
for (i = 0; i < sizex * sizey * 4; i++)
@@ -253,7 +408,10 @@ static void screen_opengl_render_apply(OGLRender *oglrender)
(jit_ofs[j][0] * 2.0f) / sizex,
(jit_ofs[j][1] * 2.0f) / sizey);
- ED_view3d_draw_offscreen(scene, v3d, ar, sizex, sizey, NULL, winmat_jitter, draw_bgpic, draw_sky);
+ ED_view3d_draw_offscreen(
+ scene, v3d, ar, sizex, sizey, NULL, winmat_jitter,
+ draw_bgpic, draw_sky, is_persp,
+ oglrender->ofs, oglrender->fx, &fx_settings, viewname);
GPU_offscreen_read_pixels(oglrender->ofs, GL_UNSIGNED_BYTE, rect);
for (i = 0; i < sizex * sizey * 4; i++)
@@ -266,14 +424,14 @@ static void screen_opengl_render_apply(OGLRender *oglrender)
MEM_freeN(accum_buffer);
}
- GPU_offscreen_unbind(oglrender->ofs); /* unbind */
+ GPU_offscreen_unbind(oglrender->ofs, true); /* unbind */
}
else {
/* shouldnt suddenly give errors mid-render but possible */
char err_out[256] = "unknown";
ImBuf *ibuf_view = ED_view3d_draw_offscreen_imbuf_simple(scene, scene->camera, oglrender->sizex, oglrender->sizey,
- IB_rect, OB_SOLID, false, true,
- (draw_sky) ? R_ADDSKY : R_ALPHAPREMUL, err_out);
+ IB_rect, OB_SOLID, false, true, true,
+ (draw_sky) ? R_ADDSKY : R_ALPHAPREMUL, viewname, err_out);
camera = scene->camera;
if (ibuf_view) {
@@ -298,7 +456,8 @@ static void screen_opengl_render_apply(OGLRender *oglrender)
if (rect) {
int profile_to;
-
+ float *rectf = RE_RenderViewGetById(rr, oglrender->view_id)->rectf;
+
if (BKE_scene_check_color_management_enabled(scene))
profile_to = IB_PROFILE_LINEAR_RGB;
else
@@ -306,45 +465,68 @@ static void screen_opengl_render_apply(OGLRender *oglrender)
/* sequencer has got trickier conversion happened above
* also assume opengl's space matches byte buffer color space */
- IMB_buffer_float_from_byte(rr->rectf, rect,
+ IMB_buffer_float_from_byte(rectf, rect,
profile_to, IB_PROFILE_SRGB, true,
oglrender->sizex, oglrender->sizey, oglrender->sizex, oglrender->sizex);
+
+ /* rr->rectf is now filled with image data */
+
+ if ((scene->r.stamp & R_STAMP_ALL) && (scene->r.stamp & R_STAMP_DRAW))
+ BKE_image_stamp_buf(scene, camera, rect, rectf, rr->rectx, rr->recty, 4);
+
+ MEM_freeN(rect);
}
+}
- /* rr->rectf is now filled with image data */
+static void screen_opengl_render_write(OGLRender *oglrender)
+{
+ Scene *scene = oglrender->scene;
+ RenderResult *rr;
+ bool ok;
+ char name[FILE_MAX];
- if ((scene->r.stamp & R_STAMP_ALL) && (scene->r.stamp & R_STAMP_DRAW))
- BKE_stamp_buf(scene, camera, rect, rr->rectf, rr->rectx, rr->recty, 4);
+ rr = RE_AcquireResultRead(oglrender->re);
- RE_ReleaseResult(oglrender->re);
+ BKE_image_path_from_imformat(
+ name, scene->r.pic, oglrender->bmain->name, scene->r.cfra,
+ &scene->r.im_format, (scene->r.scemode & R_EXTENSION) != 0, false, NULL);
- /* update byte from float buffer */
- ibuf = BKE_image_acquire_ibuf(oglrender->ima, &oglrender->iuser, &lock);
+ /* write images as individual images or stereo */
+ BKE_render_result_stamp_info(scene, scene->camera, rr, false);
+ ok = RE_WriteRenderViewsImage(oglrender->reports, rr, scene, false, name);
- if (ibuf) {
- ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID;
+ RE_ReleaseResultImage(oglrender->re);
- /* write file for animation */
- if (oglrender->write_still) {
- char name[FILE_MAX];
- int ok;
+ if (ok) printf("OpenGL Render written to '%s'\n", name);
+ else printf("OpenGL Render failed to write '%s'\n", name);
+}
- if (scene->r.im_format.planes == R_IMF_CHAN_DEPTH_8) {
- IMB_color_to_bw(ibuf);
- }
+static void screen_opengl_render_apply(OGLRender *oglrender)
+{
+ RenderResult *rr;
+ RenderView *rv;
+ int view_id;
+ ImBuf *ibuf;
+ void *lock;
- BKE_makepicstring(name, scene->r.pic, oglrender->bmain->name, scene->r.cfra,
- &scene->r.im_format, (scene->r.scemode & R_EXTENSION) != 0, false);
- ok = BKE_imbuf_write_as(ibuf, name, &scene->r.im_format, true); /* no need to stamp here */
- if (ok) printf("OpenGL Render written to '%s'\n", name);
- else printf("OpenGL Render failed to write '%s'\n", name);
- }
+ rr = RE_AcquireResultRead(oglrender->re);
+ for (rv = rr->views.first, view_id = 0; rv; rv = rv->next, view_id++) {
+ RE_SetActiveRenderView(oglrender->re, rv->name);
+ oglrender->view_id = view_id;
+ screen_opengl_render_doit(oglrender, rr);
+ }
+
+ RE_ReleaseResult(oglrender->re);
+
+ ibuf = BKE_image_acquire_ibuf(oglrender->ima, &oglrender->iuser, &lock);
+ if (ibuf) {
+ ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID;
}
-
BKE_image_release_ibuf(oglrender->ima, ibuf, lock);
- if (rect)
- MEM_freeN(rect);
+ if (oglrender->write_still) {
+ screen_opengl_render_write(oglrender);
+ }
}
static bool screen_opengl_render_init(bContext *C, wmOperator *op)
@@ -356,7 +538,6 @@ static bool screen_opengl_render_init(bContext *C, wmOperator *op)
Scene *scene = CTX_data_scene(C);
ScrArea *prevsa = CTX_wm_area(C);
ARegion *prevar = CTX_wm_region(C);
- RenderResult *rr;
GPUOffScreen *ofs;
OGLRender *oglrender;
int sizex, sizey;
@@ -429,7 +610,6 @@ static bool screen_opengl_render_init(bContext *C, wmOperator *op)
oglrender->sseq = CTX_wm_space_seq(C);
}
-
oglrender->prevsa = prevsa;
oglrender->prevar = prevar;
@@ -444,6 +624,9 @@ static bool screen_opengl_render_init(bContext *C, wmOperator *op)
* running notifiers again will overwrite */
oglrender->scene->customdata_mask |= oglrender->scene->customdata_mask_modal;
+ if (oglrender->v3d->fx_settings.fx_flag & (GPU_FX_FLAG_DOF | GPU_FX_FLAG_SSAO)) {
+ oglrender->fx = GPU_fx_compositor_create();
+ }
}
/* create render */
@@ -460,15 +643,17 @@ static bool screen_opengl_render_init(bContext *C, wmOperator *op)
/* create render result */
RE_InitState(oglrender->re, NULL, &scene->r, NULL, sizex, sizey, NULL);
- rr = RE_AcquireResultWrite(oglrender->re);
- if (rr->rectf == NULL)
- rr->rectf = MEM_callocN(sizeof(float) * 4 * sizex * sizey, "screen_opengl_render_init rect");
- RE_ReleaseResult(oglrender->re);
+ /* create render views */
+ screen_opengl_views_setup(oglrender);
/* wm vars */
oglrender->wm = wm;
oglrender->win = win;
+ oglrender->totvideos = 0;
+ oglrender->mh = NULL;
+ oglrender->movie_ctx_arr = NULL;
+
return true;
}
@@ -476,10 +661,19 @@ static void screen_opengl_render_end(bContext *C, OGLRender *oglrender)
{
Main *bmain = CTX_data_main(C);
Scene *scene = oglrender->scene;
+ size_t i;
if (oglrender->mh) {
- if (BKE_imtype_is_movie(scene->r.im_format.imtype))
- oglrender->mh->end_movie();
+ if (BKE_imtype_is_movie(scene->r.im_format.imtype)) {
+ for (i = 0; i < oglrender->totvideos; i++) {
+ oglrender->mh->end_movie(oglrender->movie_ctx_arr[i]);
+ oglrender->mh->context_free(oglrender->movie_ctx_arr[i]);
+ }
+ }
+
+ if (oglrender->movie_ctx_arr) {
+ MEM_freeN(oglrender->movie_ctx_arr);
+ }
}
if (oglrender->timer) { /* exec will not have a timer */
@@ -493,6 +687,9 @@ static void screen_opengl_render_end(bContext *C, OGLRender *oglrender)
WM_event_add_notifier(C, NC_SCENE | ND_RENDER_RESULT, oglrender->scene);
+ if (oglrender->fx)
+ GPU_fx_compositor_destroy(oglrender->fx);
+
GPU_offscreen_free(oglrender->ofs);
oglrender->scene->customdata_mask_modal = 0;
@@ -509,7 +706,7 @@ static void screen_opengl_render_cancel(bContext *C, wmOperator *op)
}
/* share between invoke and exec */
-static int screen_opengl_render_anim_initialize(bContext *C, wmOperator *op)
+static bool screen_opengl_render_anim_initialize(bContext *C, wmOperator *op)
{
/* initialize animation */
OGLRender *oglrender;
@@ -517,13 +714,34 @@ static int screen_opengl_render_anim_initialize(bContext *C, wmOperator *op)
oglrender = op->customdata;
scene = oglrender->scene;
+ oglrender->totvideos = BKE_scene_multiview_num_videos_get(&scene->r);
oglrender->reports = op->reports;
- oglrender->mh = BKE_movie_handle_get(scene->r.im_format.imtype);
+
if (BKE_imtype_is_movie(scene->r.im_format.imtype)) {
- if (!oglrender->mh->start_movie(scene, &scene->r, oglrender->sizex, oglrender->sizey, oglrender->reports)) {
+ size_t i, width, height;
+
+ BKE_scene_multiview_videos_dimensions_get(&scene->r, oglrender->sizex, oglrender->sizey, &width, &height);
+ oglrender->mh = BKE_movie_handle_get(scene->r.im_format.imtype);
+
+ if (oglrender->mh == NULL) {
+ BKE_report(oglrender->reports, RPT_ERROR, "Movie format unsupported");
screen_opengl_render_end(C, oglrender);
- return 0;
+ return false;
+ }
+
+ oglrender->movie_ctx_arr = MEM_mallocN(sizeof(void *) * oglrender->totvideos, "Movies");
+
+ for (i = 0; i < oglrender->totvideos; i++) {
+ const char *suffix = BKE_scene_multiview_view_id_suffix_get(&scene->r, i);
+
+ oglrender->movie_ctx_arr[i] = oglrender->mh->context_create();
+ if (!oglrender->mh->start_movie(oglrender->movie_ctx_arr[i], scene, &scene->r, oglrender->sizex,
+ oglrender->sizey, oglrender->reports, PRVRANGEON != 0, suffix))
+ {
+ screen_opengl_render_end(C, oglrender);
+ return false;
+ }
}
}
@@ -531,20 +749,19 @@ static int screen_opengl_render_anim_initialize(bContext *C, wmOperator *op)
oglrender->nfra = PSFRA;
scene->r.cfra = PSFRA;
- return 1;
+ return true;
}
+
static bool screen_opengl_render_anim_step(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
OGLRender *oglrender = op->customdata;
Scene *scene = oglrender->scene;
- ImBuf *ibuf, *ibuf_save = NULL;
- void *lock;
char name[FILE_MAX];
bool ok = false;
const bool view_context = (oglrender->v3d != NULL);
- Object *camera = NULL;
bool is_movie;
+ RenderResult *rr;
/* go to next frame */
if (CFRA < oglrender->nfra)
@@ -562,8 +779,9 @@ static bool screen_opengl_render_anim_step(bContext *C, wmOperator *op)
is_movie = BKE_imtype_is_movie(scene->r.im_format.imtype);
if (!is_movie) {
- BKE_makepicstring(name, scene->r.pic, oglrender->bmain->name, scene->r.cfra,
- &scene->r.im_format, (scene->r.scemode & R_EXTENSION) != 0, true);
+ BKE_image_path_from_imformat(
+ name, scene->r.pic, oglrender->bmain->name, scene->r.cfra,
+ &scene->r.im_format, (scene->r.scemode & R_EXTENSION) != 0, true, NULL);
if ((scene->r.mode & R_NO_OVERWRITE) && BLI_exists(name)) {
BKE_reportf(op->reports, RPT_INFO, "Skipping existing frame \"%s\"", name);
@@ -583,89 +801,41 @@ static bool screen_opengl_render_anim_step(bContext *C, wmOperator *op)
if (BKE_scene_camera_switch_update(scene)) {
oglrender->v3d->camera = scene->camera;
}
-
- camera = oglrender->v3d->camera;
}
}
else {
BKE_scene_camera_switch_update(scene);
-
- camera = scene->camera;
}
/* render into offscreen buffer */
screen_opengl_render_apply(oglrender);
/* save to disk */
- ibuf = BKE_image_acquire_ibuf(oglrender->ima, &oglrender->iuser, &lock);
-
- if (ibuf) {
- bool needs_free = false;
-
- ibuf_save = ibuf;
-
- if (is_movie || !BKE_imtype_requires_linear_float(scene->r.im_format.imtype)) {
- ibuf_save = IMB_colormanagement_imbuf_for_write(ibuf, true, true, &scene->view_settings,
- &scene->display_settings, &scene->r.im_format);
-
- needs_free = true;
- }
-
- /* color -> grayscale */
- /* editing directly would alter the render view */
- if (scene->r.im_format.planes == R_IMF_PLANES_BW) {
- ImBuf *ibuf_bw = IMB_dupImBuf(ibuf_save);
- IMB_color_to_bw(ibuf_bw);
-
- if (needs_free)
- IMB_freeImBuf(ibuf_save);
-
- ibuf_save = ibuf_bw;
- }
- else {
- /* this is lightweight & doesnt re-alloc the buffers, only do this
- * to save the correct bit depth since the image is always RGBA */
- ImBuf *ibuf_cpy = IMB_allocImBuf(ibuf_save->x, ibuf_save->y, scene->r.im_format.planes, 0);
-
- ibuf_cpy->rect = ibuf_save->rect;
- ibuf_cpy->rect_float = ibuf_save->rect_float;
- ibuf_cpy->zbuf_float = ibuf_save->zbuf_float;
-
- if (needs_free) {
- ibuf_cpy->mall = ibuf_save->mall;
- ibuf_save->mall = 0;
- IMB_freeImBuf(ibuf_save);
- }
+ rr = RE_AcquireResultRead(oglrender->re);
- ibuf_save = ibuf_cpy;
+ if (is_movie) {
+ ok = RE_WriteRenderViewsMovie(oglrender->reports, rr, scene, &scene->r, oglrender->mh, oglrender->sizex,
+ oglrender->sizey, oglrender->movie_ctx_arr, oglrender->totvideos, PRVRANGEON != 0);
+ if (ok) {
+ printf("Append frame %d", scene->r.cfra);
+ BKE_reportf(op->reports, RPT_INFO, "Appended frame: %d", scene->r.cfra);
}
-
- if (is_movie) {
- ok = oglrender->mh->append_movie(&scene->r, PSFRA, CFRA, (int *)ibuf_save->rect,
- oglrender->sizex, oglrender->sizey, oglrender->reports);
- if (ok) {
- printf("Append frame %d", scene->r.cfra);
- BKE_reportf(op->reports, RPT_INFO, "Appended frame: %d", scene->r.cfra);
- }
+ }
+ else {
+ BKE_render_result_stamp_info(scene, scene->camera, rr, false);
+ ok = RE_WriteRenderViewsImage(op->reports, rr, scene, true, name);
+ if (ok) {
+ printf("Saved: %s", name);
+ BKE_reportf(op->reports, RPT_INFO, "Saved file: %s", name);
}
else {
- ok = BKE_imbuf_write_stamp(scene, camera, ibuf_save, name, &scene->r.im_format);
-
- if (ok == 0) {
- printf("Write error: cannot save %s\n", name);
- BKE_reportf(op->reports, RPT_ERROR, "Write error: cannot save %s", name);
- }
- else {
- printf("Saved: %s", name);
- BKE_reportf(op->reports, RPT_INFO, "Saved file: %s", name);
- }
+ printf("Write error: cannot save %s\n", name);
+ BKE_reportf(op->reports, RPT_ERROR, "Write error: cannot save %s", name);
}
-
- if (needs_free)
- IMB_freeImBuf(ibuf_save);
}
- BKE_image_release_ibuf(oglrender->ima, ibuf, lock);
+ RE_ReleaseResult(oglrender->re);
+
/* movie stats prints have no line break */
printf("\n");
diff --git a/source/blender/editors/render/render_ops.c b/source/blender/editors/render/render_ops.c
index 0d334082a2b..f98083f7e74 100644
--- a/source/blender/editors/render/render_ops.c
+++ b/source/blender/editors/render/render_ops.c
@@ -47,6 +47,7 @@ void ED_operatortypes_render(void)
WM_operatortype_append(OBJECT_OT_material_slot_select);
WM_operatortype_append(OBJECT_OT_material_slot_deselect);
WM_operatortype_append(OBJECT_OT_material_slot_copy);
+ WM_operatortype_append(OBJECT_OT_material_slot_move);
WM_operatortype_append(MATERIAL_OT_new);
WM_operatortype_append(TEXTURE_OT_new);
@@ -58,6 +59,9 @@ void ED_operatortypes_render(void)
WM_operatortype_append(SCENE_OT_render_layer_add);
WM_operatortype_append(SCENE_OT_render_layer_remove);
+ WM_operatortype_append(SCENE_OT_render_view_add);
+ WM_operatortype_append(SCENE_OT_render_view_remove);
+
#ifdef WITH_FREESTYLE
WM_operatortype_append(SCENE_OT_freestyle_module_add);
WM_operatortype_append(SCENE_OT_freestyle_module_remove);
diff --git a/source/blender/editors/render/render_preview.c b/source/blender/editors/render/render_preview.c
index 01f00a8458a..6dfd2b31d30 100644
--- a/source/blender/editors/render/render_preview.c
+++ b/source/blender/editors/render/render_preview.c
@@ -60,6 +60,7 @@
#include "DNA_brush_types.h"
#include "DNA_screen_types.h"
+#include "BKE_appdir.h"
#include "BKE_brush.h"
#include "BKE_context.h"
#include "BKE_colortools.h"
@@ -78,16 +79,14 @@
#include "IMB_imbuf.h"
#include "IMB_imbuf_types.h"
-#include "IMB_colormanagement.h"
-
-#include "GPU_extensions.h"
+#include "IMB_thumbs.h"
#include "BIF_gl.h"
#include "BIF_glutil.h"
-#include "PIL_time.h"
#include "RE_pipeline.h"
+#include "RE_engine.h"
#include "WM_api.h"
#include "WM_types.h"
@@ -95,9 +94,10 @@
#include "ED_datafiles.h"
#include "ED_render.h"
-#include "UI_interface.h"
-
-#include "render_intern.h"
+#ifndef NDEBUG
+/* Used for database init assert(). */
+# include "BLI_threads.h"
+#endif
ImBuf *get_brush_icon(Brush *brush)
{
@@ -120,7 +120,7 @@ ImBuf *get_brush_icon(Brush *brush)
// otherwise lets try to find it in other directories
if (!(brush->icon_imbuf)) {
- folder = BLI_get_folder(BLENDER_DATAFILES, "brushicons");
+ folder = BKE_appdir_folder_id(BLENDER_DATAFILES, "brushicons");
BLI_make_file_string(G.main->name, path, folder, brush->icon_filepath);
@@ -131,7 +131,7 @@ ImBuf *get_brush_icon(Brush *brush)
}
if (brush->icon_imbuf)
- BKE_icon_changed(BKE_icon_getid(&brush->id));
+ BKE_icon_changed(BKE_icon_id_ensure(&brush->id));
}
}
}
@@ -164,6 +164,7 @@ typedef struct ShaderPreview {
unsigned int *pr_rect;
int pr_method;
+ Main *bmain;
Main *pr_main;
} ShaderPreview;
@@ -174,6 +175,7 @@ typedef struct IconPreviewSize {
} IconPreviewSize;
typedef struct IconPreview {
+ Main *bmain;
Scene *scene;
void *owner;
ID *id;
@@ -205,14 +207,25 @@ static Main *load_main_from_memory(const void *blend, int blend_size)
}
#endif
-void ED_preview_init_dbase(void)
+void ED_preview_ensure_dbase(void)
{
#ifndef WITH_HEADLESS
- G_pr_main = load_main_from_memory(datatoc_preview_blend, datatoc_preview_blend_size);
- G_pr_main_cycles = load_main_from_memory(datatoc_preview_cycles_blend, datatoc_preview_cycles_blend_size);
+ static bool base_initialized = false;
+ BLI_assert(BLI_thread_is_main());
+ if (!base_initialized) {
+ G_pr_main = load_main_from_memory(datatoc_preview_blend, datatoc_preview_blend_size);
+ G_pr_main_cycles = load_main_from_memory(datatoc_preview_cycles_blend, datatoc_preview_cycles_blend_size);
+ base_initialized = true;
+ }
#endif
}
+static bool check_engine_supports_textures(Scene *scene)
+{
+ RenderEngineType *type = RE_engines_find(scene->r.engine);
+ return type->flag & RE_USE_TEXTURE_PREVIEW;
+}
+
void ED_preview_free_dbase(void)
{
if (G_pr_main)
@@ -258,12 +271,14 @@ static Scene *preview_get_scene(Main *pr_main)
/* call this with a pointer to initialize preview scene */
/* call this with NULL to restore assigned ID pointers in preview scene */
-static Scene *preview_prepare_scene(Scene *scene, ID *id, int id_type, ShaderPreview *sp)
+static Scene *preview_prepare_scene(Main *bmain, Scene *scene, ID *id, int id_type, ShaderPreview *sp)
{
Scene *sce;
Base *base;
Main *pr_main = sp->pr_main;
-
+
+ memcpy(pr_main->name, bmain->name, sizeof(pr_main->name));
+
sce = preview_get_scene(pr_main);
if (sce) {
@@ -299,12 +314,12 @@ static Scene *preview_prepare_scene(Scene *scene, ID *id, int id_type, ShaderPre
sce->r.cfra = scene->r.cfra;
- if (id_type == ID_TE) {
+ if (id_type == ID_TE && !check_engine_supports_textures(scene)) {
/* Force blender internal for texture icons and nodes render,
* seems commonly used render engines does not support
* such kind of rendering.
*/
- BLI_strncpy(sce->r.engine, "BLENDER_RENDER", sizeof(sce->r.engine));
+ BLI_strncpy(sce->r.engine, RE_engine_id_BLENDER_RENDER, sizeof(sce->r.engine));
}
else {
BLI_strncpy(sce->r.engine, scene->r.engine, sizeof(sce->r.engine));
@@ -356,7 +371,7 @@ static Scene *preview_prepare_scene(Scene *scene, ID *id, int id_type, ShaderPre
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 (!STREQ(base->object->id.name + 2, "Lamp.002")) {
if (mat->material_type == MA_TYPE_VOLUME)
base->object->restrictflag |= OB_RESTRICT_RENDER;
else
@@ -420,7 +435,7 @@ static Scene *preview_prepare_scene(Scene *scene, ID *id, int id_type, ShaderPre
Tex *tex = NULL, *origtex = (Tex *)id;
if (origtex) {
- tex = localize_texture(origtex);
+ tex = BKE_texture_localize(origtex);
sp->texcopy = tex;
BLI_addtail(&pr_main->tex, tex);
}
@@ -518,10 +533,11 @@ static Scene *preview_prepare_scene(Scene *scene, ID *id, int id_type, ShaderPre
}
/* new UI convention: draw is in pixel space already. */
-/* uses ROUNDBOX button in block to get the rect */
+/* uses UI_BTYPE_ROUNDBOX button in block to get the rect */
static bool ed_preview_draw_rect(ScrArea *sa, int split, int first, rcti *rect, rcti *newrect)
{
Render *re;
+ RenderView *rv;
RenderResult rres;
char name[32];
int offx = 0;
@@ -545,9 +561,22 @@ static bool ed_preview_draw_rect(ScrArea *sa, int split, int first, rcti *rect,
/* test if something rendered ok */
re = RE_GetRender(name);
- RE_AcquireResultImage(re, &rres);
- if (rres.rectf) {
+ if (re == NULL)
+ return false;
+
+ RE_AcquireResultImageViews(re, &rres);
+
+ if (!BLI_listbase_is_empty(&rres.views)) {
+ /* material preview only needs monoscopy (view 0) */
+ rv = RE_RenderViewGetById(&rres, 0);
+ }
+ else {
+ /* possible the job clears the views but we're still drawing T45496 */
+ rv = NULL;
+ }
+
+ if (rv && rv->rectf) {
if (ABS(rres.rectx - newx) < 2 && ABS(rres.recty - newy) < 2) {
@@ -558,8 +587,11 @@ static bool ed_preview_draw_rect(ScrArea *sa, int split, int first, rcti *rect,
unsigned char *rect_byte = MEM_mallocN(rres.rectx * rres.recty * sizeof(int), "ed_preview_draw_rect");
float fx = rect->xmin + offx;
float fy = rect->ymin;
-
- RE_AcquiredResultGet32(re, &rres, (unsigned int *)rect_byte);
+
+ /* material preview only needs monoscopy (view 0) */
+ if (re)
+ RE_AcquiredResultGet32(re, &rres, (unsigned int *)rect_byte, 0);
+
glaDrawPixelsSafe(fx, fy, rres.rectx, rres.recty, rres.rectx, GL_RGBA, GL_UNSIGNED_BYTE, rect_byte);
MEM_freeN(rect_byte);
@@ -569,7 +601,7 @@ static bool ed_preview_draw_rect(ScrArea *sa, int split, int first, rcti *rect,
}
}
- RE_ReleaseResultImage(re);
+ RE_ReleaseResultImageViews(re, &rres);
return ok;
}
@@ -698,7 +730,7 @@ static void shader_preview_render(ShaderPreview *sp, ID *id, int split, int firs
}
/* get the stuff from the builtin preview dbase */
- sce = preview_prepare_scene(sp->scene, id, idtype, sp);
+ sce = preview_prepare_scene(sp->bmain, sp->scene, id, idtype, sp);
if (sce == NULL) return;
if (!split || first) sprintf(name, "Preview %p", sp->owner);
@@ -751,15 +783,9 @@ static void shader_preview_render(ShaderPreview *sp, ID *id, int split, int firs
if (sp->pr_rect)
RE_ResultGet32(re, sp->pr_rect);
}
- else {
- /* validate owner */
- //if (ri->rect == NULL)
- // ri->rect= MEM_mallocN(sizeof(int) * ri->pr_rectx*ri->pr_recty, "BIF_previewrender");
- //RE_ResultGet32(re, ri->rect);
- }
/* unassign the pointers, reset vars */
- preview_prepare_scene(sp->scene, NULL, GS(id->name), sp);
+ preview_prepare_scene(sp->bmain, sp->scene, NULL, GS(id->name), sp);
/* XXX bad exception, end-exec is not being called in render, because it uses local main */
// if (idtype == ID_TE) {
@@ -927,65 +953,87 @@ static void set_alpha(char *cp, int sizex, int sizey, char alpha)
static void icon_preview_startjob(void *customdata, short *stop, short *do_update)
{
ShaderPreview *sp = customdata;
- ID *id = sp->id;
- short idtype = GS(id->name);
-
- if (idtype == ID_IM) {
- Image *ima = (Image *)id;
- ImBuf *ibuf = NULL;
- ImageUser iuser = {NULL};
- /* ima->ok is zero when Image cannot load */
- if (ima == NULL || ima->ok == 0)
- return;
+ if (sp->pr_method == PR_ICON_DEFERRED) {
+ PreviewImage *prv = sp->owner;
+ ImBuf *thumb;
+ char *deferred_data = PRV_DEFERRED_DATA(prv);
+ int source = deferred_data[0];
+ char *path = &deferred_data[1];
- /* setup dummy image user */
- iuser.ok = iuser.framenr = 1;
- iuser.scene = sp->scene;
-
- /* elubie: this needs to be changed: here image is always loaded if not
- * already there. Very expensive for large images. Need to find a way to
- * only get existing ibuf */
- ibuf = BKE_image_acquire_ibuf(ima, &iuser, NULL);
- if (ibuf == NULL || ibuf->rect == NULL) {
- BKE_image_release_ibuf(ima, ibuf, NULL);
- return;
- }
-
- icon_copy_rect(ibuf, sp->sizex, sp->sizey, sp->pr_rect);
+// printf("generating deferred %d×%d preview for %s\n", sp->sizex, sp->sizey, path);
- *do_update = true;
+ thumb = IMB_thumb_manage(path, THB_LARGE, source);
- BKE_image_release_ibuf(ima, ibuf, NULL);
+ if (thumb) {
+ /* PreviewImage assumes premultiplied alhpa... */
+ IMB_premultiply_alpha(thumb);
+
+ icon_copy_rect(thumb, sp->sizex, sp->sizey, sp->pr_rect);
+ IMB_freeImBuf(thumb);
+ }
}
- else if (idtype == ID_BR) {
- Brush *br = (Brush *)id;
+ else {
+ ID *id = sp->id;
+ short idtype = GS(id->name);
+
+ if (idtype == ID_IM) {
+ Image *ima = (Image *)id;
+ ImBuf *ibuf = NULL;
+ ImageUser iuser = {NULL};
+
+ /* ima->ok is zero when Image cannot load */
+ if (ima == NULL || ima->ok == 0)
+ return;
+
+ /* setup dummy image user */
+ iuser.ok = iuser.framenr = 1;
+ iuser.scene = sp->scene;
+
+ /* elubie: this needs to be changed: here image is always loaded if not
+ * already there. Very expensive for large images. Need to find a way to
+ * only get existing ibuf */
+ ibuf = BKE_image_acquire_ibuf(ima, &iuser, NULL);
+ if (ibuf == NULL || ibuf->rect == NULL) {
+ BKE_image_release_ibuf(ima, ibuf, NULL);
+ return;
+ }
- br->icon_imbuf = get_brush_icon(br);
+ icon_copy_rect(ibuf, sp->sizex, sp->sizey, sp->pr_rect);
- memset(sp->pr_rect, 0x88, sp->sizex * sp->sizey * sizeof(unsigned int));
+ *do_update = true;
- if (!(br->icon_imbuf) || !(br->icon_imbuf->rect))
- return;
+ BKE_image_release_ibuf(ima, ibuf, NULL);
+ }
+ else if (idtype == ID_BR) {
+ Brush *br = (Brush *)id;
- icon_copy_rect(br->icon_imbuf, sp->sizex, sp->sizey, sp->pr_rect);
+ br->icon_imbuf = get_brush_icon(br);
- *do_update = true;
- }
- else {
- /* re-use shader job */
- shader_preview_startjob(customdata, stop, do_update);
+ memset(sp->pr_rect, 0x88, sp->sizex * sp->sizey * sizeof(unsigned int));
+
+ if (!(br->icon_imbuf) || !(br->icon_imbuf->rect))
+ return;
- /* world is rendered with alpha=0, so it wasn't displayed
- * this could be render option for sky to, for later */
- if (idtype == ID_WO) {
- set_alpha((char *)sp->pr_rect, sp->sizex, sp->sizey, 255);
+ icon_copy_rect(br->icon_imbuf, sp->sizex, sp->sizey, sp->pr_rect);
+
+ *do_update = true;
}
- else if (idtype == ID_MA) {
- Material *ma = (Material *)id;
+ else {
+ /* re-use shader job */
+ shader_preview_startjob(customdata, stop, do_update);
- if (ma->material_type == MA_TYPE_HALO)
+ /* world is rendered with alpha=0, so it wasn't displayed
+ * this could be render option for sky to, for later */
+ if (idtype == ID_WO) {
set_alpha((char *)sp->pr_rect, sp->sizex, sp->sizey, 255);
+ }
+ else if (idtype == ID_MA) {
+ Material *ma = (Material *)id;
+
+ if (ma->material_type == MA_TYPE_HALO)
+ set_alpha((char *)sp->pr_rect, sp->sizex, sp->sizey, 255);
+ }
}
}
}
@@ -997,7 +1045,7 @@ static void common_preview_startjob(void *customdata, short *stop, short *do_upd
{
ShaderPreview *sp = customdata;
- if (sp->pr_method == PR_ICON_RENDER)
+ if (ELEM(sp->pr_method, PR_ICON_RENDER, PR_ICON_DEFERRED))
icon_preview_startjob(customdata, stop, do_update);
else
shader_preview_startjob(customdata, stop, do_update);
@@ -1033,29 +1081,35 @@ static void icon_preview_startjob_all_sizes(void *customdata, short *stop, short
const bool use_new_shading = BKE_scene_use_new_shading_nodes(ip->scene);
while (cur_size) {
+ PreviewImage *prv = ip->owner;
ShaderPreview *sp = MEM_callocN(sizeof(ShaderPreview), "Icon ShaderPreview");
+ const bool is_render = !prv->use_deferred;
/* construct shader preview from image size and previewcustomdata */
sp->scene = ip->scene;
sp->owner = ip->owner;
sp->sizex = cur_size->sizex;
sp->sizey = cur_size->sizey;
- sp->pr_method = PR_ICON_RENDER;
+ sp->pr_method = is_render ? PR_ICON_RENDER : PR_ICON_DEFERRED;
sp->pr_rect = cur_size->rect;
sp->id = ip->id;
-
- if (use_new_shading) {
- /* texture icon rendering is hardcoded to use BI,
- * so don't even think of using cycle's bmain for
- * texture icons
- */
- if (GS(ip->id->name) != ID_TE)
- sp->pr_main = G_pr_main_cycles;
- else
+ sp->bmain = ip->bmain;
+
+ if (is_render) {
+ BLI_assert(ip->id);
+ if (use_new_shading) {
+ /* texture icon rendering is hardcoded to use BI,
+ * so don't even think of using cycle's bmain for
+ * texture icons
+ */
+ if (GS(ip->id->name) != ID_TE)
+ sp->pr_main = G_pr_main_cycles;
+ else
+ sp->pr_main = G_pr_main;
+ }
+ else {
sp->pr_main = G_pr_main;
- }
- else {
- sp->pr_main = G_pr_main;
+ }
}
common_preview_startjob(sp, stop, do_update, progress);
@@ -1100,11 +1154,35 @@ static void icon_preview_free(void *customdata)
MEM_freeN(ip);
}
+void ED_preview_icon_render(Main *bmain, Scene *scene, ID *id, unsigned int *rect, int sizex, int sizey)
+{
+ IconPreview ip = {NULL};
+ short stop = false, update = false;
+ float progress = 0.0f;
+
+ ED_preview_ensure_dbase();
+
+ ip.bmain = bmain;
+ ip.scene = scene;
+ ip.owner = id;
+ ip.id = id;
+
+ icon_preview_add_size(&ip, rect, sizex, sizey);
+
+ icon_preview_startjob_all_sizes(&ip, &stop, &update, &progress);
+
+ icon_preview_endjob(&ip);
+
+ BLI_freelistN(&ip.sizes);
+}
+
void ED_preview_icon_job(const bContext *C, void *owner, ID *id, unsigned int *rect, int sizex, int sizey)
{
wmJob *wm_job;
IconPreview *ip, *old_ip;
-
+
+ ED_preview_ensure_dbase();
+
/* suspended start means it starts after 1 timer step, see WM_jobs_timer below */
wm_job = WM_jobs_get(CTX_wm_manager(C), CTX_wm_window(C), owner, "Icon Preview",
WM_JOB_EXCL_RENDER | WM_JOB_SUSPEND, WM_JOB_TYPE_RENDER_PREVIEW);
@@ -1117,8 +1195,9 @@ void ED_preview_icon_job(const bContext *C, void *owner, ID *id, unsigned int *r
BLI_movelisttolist(&ip->sizes, &old_ip->sizes);
/* customdata for preview thread */
+ ip->bmain = CTX_data_main(C);
ip->scene = CTX_data_scene(C);
- ip->owner = id;
+ ip->owner = owner;
ip->id = id;
icon_preview_add_size(ip, rect, sizex, sizey);
@@ -1145,6 +1224,8 @@ void ED_preview_shader_job(const bContext *C, void *owner, ID *id, ID *parent, M
return;
}
+ ED_preview_ensure_dbase();
+
wm_job = WM_jobs_get(CTX_wm_manager(C), CTX_wm_window(C), owner, "Shader Preview",
WM_JOB_EXCL_RENDER, WM_JOB_TYPE_RENDER_PREVIEW);
sp = MEM_callocN(sizeof(ShaderPreview), "shader preview");
@@ -1158,6 +1239,7 @@ void ED_preview_shader_job(const bContext *C, void *owner, ID *id, ID *parent, M
sp->id = id;
sp->parent = parent;
sp->slot = slot;
+ sp->bmain = CTX_data_main(C);
/* hardcoded preview .blend for cycles/internal, this should be solved
* once with custom preview .blend path for external engines */
@@ -1179,12 +1261,11 @@ void ED_preview_shader_job(const bContext *C, void *owner, ID *id, ID *parent, M
WM_jobs_start(CTX_wm_manager(C), wm_job);
}
-void ED_preview_kill_jobs(const struct bContext *C)
+void ED_preview_kill_jobs(wmWindowManager *wm, Main *bmain)
{
- wmWindowManager *wm = CTX_wm_manager(C);
if (wm)
WM_jobs_kill(wm, NULL, common_preview_startjob);
-
- ED_viewport_render_kill_jobs(C, false);
+
+ ED_viewport_render_kill_jobs(wm, bmain, false);
}
diff --git a/source/blender/editors/render/render_shading.c b/source/blender/editors/render/render_shading.c
index 72b4da64c3e..2e07e19e366 100644
--- a/source/blender/editors/render/render_shading.c
+++ b/source/blender/editors/render/render_shading.c
@@ -41,40 +41,39 @@
#include "DNA_space_types.h"
#include "DNA_world_types.h"
-#include "BLI_blenlib.h"
#include "BLI_utildefines.h"
+#include "BLI_listbase.h"
+#include "BLI_math_vector.h"
-#include "BLF_translation.h"
+#include "BLT_translation.h"
#include "BKE_animsys.h"
#include "BKE_context.h"
#include "BKE_curve.h"
#include "BKE_depsgraph.h"
#include "BKE_font.h"
-#include "BKE_freestyle.h"
#include "BKE_global.h"
#include "BKE_image.h"
#include "BKE_library.h"
#include "BKE_linestyle.h"
#include "BKE_main.h"
#include "BKE_material.h"
+#include "BKE_paint.h"
#include "BKE_report.h"
#include "BKE_scene.h"
#include "BKE_texture.h"
#include "BKE_world.h"
#include "BKE_editmesh.h"
-#include "IMB_imbuf.h"
-#include "IMB_imbuf_types.h"
-#include "GPU_material.h"
#ifdef WITH_FREESTYLE
+# include "BKE_freestyle.h"
# include "FRS_freestyle.h"
+# include "RNA_enum_types.h"
#endif
#include "RNA_access.h"
-#include "RNA_enum_types.h"
#include "WM_api.h"
#include "WM_types.h"
@@ -102,8 +101,15 @@ static int material_slot_add_exec(bContext *C, wmOperator *UNUSED(op))
if (!ob)
return OPERATOR_CANCELLED;
-
+
object_add_material_slot(ob);
+
+ if (ob->mode & OB_MODE_TEXTURE_PAINT) {
+ Scene *scene = CTX_data_scene(C);
+ BKE_paint_proj_mesh_data_check(scene, ob, NULL, NULL, NULL, NULL);
+ WM_event_add_notifier(C, NC_SCENE | ND_TOOLSETTINGS, NULL);
+ }
+
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
WM_event_add_notifier(C, NC_OBJECT | ND_OB_SHADING, ob);
WM_event_add_notifier(C, NC_MATERIAL | ND_SHADING_PREVIEW, ob);
@@ -138,8 +144,15 @@ static int material_slot_remove_exec(bContext *C, wmOperator *op)
BKE_report(op->reports, RPT_ERROR, "Unable to remove material slot in edit mode");
return OPERATOR_CANCELLED;
}
-
+
object_remove_material_slot(ob);
+
+ if (ob->mode & OB_MODE_TEXTURE_PAINT) {
+ Scene *scene = CTX_data_scene(C);
+ BKE_paint_proj_mesh_data_check(scene, ob, NULL, NULL, NULL, NULL);
+ WM_event_add_notifier(C, NC_SCENE | ND_TOOLSETTINGS, NULL);
+ }
+
DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
WM_event_add_notifier(C, NC_OBJECT | ND_OB_SHADING, ob);
@@ -188,9 +201,11 @@ static int material_slot_assign_exec(bContext *C, wmOperator *UNUSED(op))
ListBase *nurbs = BKE_curve_editNurbs_get((Curve *)ob->data);
if (nurbs) {
- for (nu = nurbs->first; nu; nu = nu->next)
- if (isNurbsel(nu))
- nu->mat_nr = nu->charidx = ob->actcol - 1;
+ for (nu = nurbs->first; nu; nu = nu->next) {
+ if (ED_curve_nurb_select_check(ob->data, nu)) {
+ nu->mat_nr = ob->actcol - 1;
+ }
+ }
}
}
else if (ob->type == OB_FONT) {
@@ -369,6 +384,74 @@ void OBJECT_OT_material_slot_copy(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
}
+static int material_slot_move_exec(bContext *C, wmOperator *op)
+{
+ Object *ob = ED_object_context(C);
+
+ unsigned int *slot_remap;
+ int index_pair[2];
+
+ int dir = RNA_enum_get(op->ptr, "direction");
+
+ if (!ob || ob->totcol < 2) {
+ return OPERATOR_CANCELLED;
+ }
+
+ /* up */
+ if (dir == 1 && ob->actcol > 1) {
+ index_pair[0] = ob->actcol - 2;
+ index_pair[1] = ob->actcol - 1;
+ ob->actcol--;
+ }
+ /* down */
+ else if (dir == -1 && ob->actcol < ob->totcol) {
+ index_pair[0] = ob->actcol - 1;
+ index_pair[1] = ob->actcol - 0;
+ ob->actcol++;
+ }
+ else {
+ return OPERATOR_CANCELLED;
+ }
+
+ slot_remap = MEM_mallocN(sizeof(unsigned int) * ob->totcol, __func__);
+
+ range_vn_u(slot_remap, ob->totcol, 0);
+
+ slot_remap[index_pair[0]] = index_pair[1];
+ slot_remap[index_pair[1]] = index_pair[0];
+
+ BKE_material_remap_object(ob, slot_remap);
+
+ MEM_freeN(slot_remap);
+
+ DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW | ND_DATA, ob);
+
+ return OPERATOR_FINISHED;
+}
+
+void OBJECT_OT_material_slot_move(wmOperatorType *ot)
+{
+ static EnumPropertyItem material_slot_move[] = {
+ {1, "UP", 0, "Up", ""},
+ {-1, "DOWN", 0, "Down", ""},
+ {0, NULL, 0, NULL, NULL}
+ };
+
+ /* identifiers */
+ ot->name = "Move Material";
+ ot->idname = "OBJECT_OT_material_slot_move";
+ ot->description = "Move the active material up/down in the list";
+
+ /* api callbacks */
+ ot->exec = material_slot_move_exec;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ RNA_def_enum(ot->srna, "direction", material_slot_move, 0, "Direction", "Direction to move, UP or DOWN");
+}
+
/********************** new material operator *********************/
static int new_material_exec(bContext *C, wmOperator *UNUSED(op))
@@ -393,11 +476,11 @@ static int new_material_exec(bContext *C, wmOperator *UNUSED(op))
}
/* hook into UI */
- uiIDContextProperty(C, &ptr, &prop);
+ UI_context_active_but_prop_get_templateID(C, &ptr, &prop);
if (prop) {
/* when creating new ID blocks, use is already 1, but RNA
- * pointer se also increases user, so this compensates it */
+ * pointer use also increases user, so this compensates it */
ma->id.us--;
RNA_id_pointer_create(&ma->id, &idptr);
@@ -438,11 +521,11 @@ static int new_texture_exec(bContext *C, wmOperator *UNUSED(op))
tex = BKE_texture_copy(tex);
}
else {
- tex = add_texture(bmain, DATA_("Texture"));
+ tex = BKE_texture_add(bmain, DATA_("Texture"));
}
/* hook into UI */
- uiIDContextProperty(C, &ptr, &prop);
+ UI_context_active_but_prop_get_templateID(C, &ptr, &prop);
if (prop) {
/* when creating new ID blocks, use is already 1, but RNA
@@ -505,7 +588,7 @@ static int new_world_exec(bContext *C, wmOperator *UNUSED(op))
}
/* hook into UI */
- uiIDContextProperty(C, &ptr, &prop);
+ UI_context_active_but_prop_get_templateID(C, &ptr, &prop);
if (prop) {
/* when creating new ID blocks, use is already 1, but RNA
@@ -543,7 +626,7 @@ static int render_layer_add_exec(bContext *C, wmOperator *UNUSED(op))
Scene *scene = CTX_data_scene(C);
BKE_scene_add_render_layer(scene, NULL);
- scene->r.actlay = BLI_countlist(&scene->r.layers) - 1;
+ scene->r.actlay = BLI_listbase_count(&scene->r.layers) - 1;
DAG_id_tag_update(&scene->id, 0);
WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, scene);
@@ -593,6 +676,70 @@ void SCENE_OT_render_layer_remove(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
}
+/********************** render view operators *********************/
+
+static int render_view_remove_poll(bContext *C)
+{
+ Scene *scene = CTX_data_scene(C);
+
+ /* don't allow user to remove "left" and "right" views */
+ return scene->r.actview > 1;
+}
+
+static int render_view_add_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ Scene *scene = CTX_data_scene(C);
+
+ BKE_scene_add_render_view(scene, NULL);
+ scene->r.actview = BLI_listbase_count(&scene->r.views) - 1;
+
+ WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, scene);
+
+ return OPERATOR_FINISHED;
+}
+
+void SCENE_OT_render_view_add(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Add Render View";
+ ot->idname = "SCENE_OT_render_view_add";
+ ot->description = "Add a render view";
+
+ /* api callbacks */
+ ot->exec = render_view_add_exec;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+static int render_view_remove_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ Scene *scene = CTX_data_scene(C);
+ SceneRenderView *rv = BLI_findlink(&scene->r.views, scene->r.actview);
+
+ if (!BKE_scene_remove_render_view(scene, rv))
+ return OPERATOR_CANCELLED;
+
+ WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, scene);
+
+ return OPERATOR_FINISHED;
+}
+
+void SCENE_OT_render_view_remove(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Remove Render View";
+ ot->idname = "SCENE_OT_render_view_remove";
+ ot->description = "Remove the selected render view";
+
+ /* api callbacks */
+ ot->exec = render_view_remove_exec;
+ ot->poll = render_view_remove_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
#ifdef WITH_FREESTYLE
static bool freestyle_linestyle_check_report(FreestyleLineSet *lineset, ReportList *reports)
@@ -719,10 +866,11 @@ void SCENE_OT_freestyle_module_move(wmOperatorType *ot)
static int freestyle_lineset_add_exec(bContext *C, wmOperator *UNUSED(op))
{
+ Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
SceneRenderLayer *srl = BLI_findlink(&scene->r.layers, scene->r.actlay);
- BKE_freestyle_lineset_add(&srl->freestyleConfig, NULL);
+ BKE_freestyle_lineset_add(bmain, &srl->freestyleConfig, NULL);
DAG_id_tag_update(&scene->id, 0);
WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, scene);
@@ -881,6 +1029,7 @@ void SCENE_OT_freestyle_lineset_move(wmOperatorType *ot)
static int freestyle_linestyle_new_exec(bContext *C, wmOperator *op)
{
+ Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
SceneRenderLayer *srl = BLI_findlink(&scene->r.layers, scene->r.actlay);
FreestyleLineSet *lineset = BKE_freestyle_lineset_get_active(&srl->freestyleConfig);
@@ -891,10 +1040,10 @@ static int freestyle_linestyle_new_exec(bContext *C, wmOperator *op)
}
if (lineset->linestyle) {
lineset->linestyle->id.us--;
- lineset->linestyle = BKE_linestyle_copy(lineset->linestyle);
+ lineset->linestyle = BKE_linestyle_copy(bmain, lineset->linestyle);
}
else {
- lineset->linestyle = BKE_linestyle_new("LineStyle", NULL);
+ lineset->linestyle = BKE_linestyle_new(bmain, "LineStyle");
}
DAG_id_tag_update(&lineset->linestyle->id, 0);
WM_event_add_notifier(C, NC_LINESTYLE, lineset->linestyle);
@@ -1374,11 +1523,15 @@ void TEXTURE_OT_slot_move(wmOperatorType *ot)
static int save_envmap(wmOperator *op, Scene *scene, EnvMap *env, char *path, const char imtype)
{
+ PropertyRNA *prop;
float layout[12];
- if (RNA_struct_find_property(op->ptr, "layout") )
- RNA_float_get_array(op->ptr, "layout", layout);
- else
+
+ if ((prop = RNA_struct_find_property(op->ptr, "layout"))) {
+ RNA_property_float_get_array(op->ptr, prop, layout);
+ }
+ else {
memcpy(layout, default_envmap_layout, sizeof(layout));
+ }
if (RE_WriteEnvmapResult(op->reports, scene, env, path, imtype, layout)) {
return OPERATOR_FINISHED;
@@ -1400,7 +1553,7 @@ static int envmap_save_exec(bContext *C, wmOperator *op)
RNA_string_get(op->ptr, "filepath", path);
if (scene->r.scemode & R_EXTENSION) {
- BKE_add_image_extension(path, &scene->r.im_format);
+ BKE_image_path_ensure_ext_from_imformat(path, &scene->r.im_format);
}
WM_cursor_wait(1);
@@ -1466,15 +1619,15 @@ void TEXTURE_OT_envmap_save(wmOperatorType *ot)
"(use -1 to skip a face)", 0.0f, 0.0f);
RNA_def_property_flag(prop, PROP_HIDDEN);
- WM_operator_properties_filesel(ot, FOLDERFILE | IMAGEFILE | MOVIEFILE, FILE_SPECIAL, FILE_SAVE,
- WM_FILESEL_FILEPATH, FILE_DEFAULTDISPLAY);
+ WM_operator_properties_filesel(ot, FILE_TYPE_FOLDER | FILE_TYPE_IMAGE | FILE_TYPE_MOVIE, FILE_SPECIAL, FILE_SAVE,
+ WM_FILESEL_FILEPATH, FILE_DEFAULTDISPLAY, FILE_SORT_ALPHA);
}
static int envmap_clear_exec(bContext *C, wmOperator *UNUSED(op))
{
Tex *tex = CTX_data_pointer_get_type(C, "texture", &RNA_Texture).data;
- BKE_free_envmapdata(tex->env);
+ BKE_texture_envmap_free_data(tex->env);
WM_event_add_notifier(C, NC_TEXTURE | NA_EDITED, tex);
@@ -1517,7 +1670,7 @@ static int envmap_clear_all_exec(bContext *C, wmOperator *UNUSED(op))
for (tex = bmain->tex.first; tex; tex = tex->id.next)
if (tex->env)
- BKE_free_envmapdata(tex->env);
+ BKE_texture_envmap_free_data(tex->env);
WM_event_add_notifier(C, NC_TEXTURE | NA_EDITED, tex);
diff --git a/source/blender/editors/render/render_update.c b/source/blender/editors/render/render_update.c
index 6b58d3d55aa..f11a8177bf8 100644
--- a/source/blender/editors/render/render_update.c
+++ b/source/blender/editors/render/render_update.c
@@ -41,17 +41,18 @@
#include "DNA_world_types.h"
#include "DNA_windowmanager_types.h"
+#include "BLI_listbase.h"
#include "BLI_threads.h"
#include "BLI_utildefines.h"
#include "BKE_context.h"
-#include "BKE_depsgraph.h"
#include "BKE_DerivedMesh.h"
#include "BKE_icons.h"
#include "BKE_main.h"
#include "BKE_material.h"
#include "BKE_node.h"
#include "BKE_paint.h"
+#include "BKE_scene.h"
#include "GPU_material.h"
#include "GPU_buffers.h"
@@ -61,6 +62,7 @@
#include "ED_node.h"
#include "ED_render.h"
+#include "ED_view3d.h"
#include "render_intern.h" // own include
@@ -85,7 +87,11 @@ void ED_render_scene_update(Main *bmain, Scene *scene, int updated)
/* don't call this recursively for frame updates */
if (recursive_check)
return;
-
+
+ /* Do not call if no WM available, see T42688. */
+ if (BLI_listbase_is_empty(&bmain->wm))
+ return;
+
recursive_check = true;
C = CTX_create();
@@ -137,26 +143,36 @@ void ED_render_scene_update(Main *bmain, Scene *scene, int updated)
recursive_check = false;
}
-void ED_render_engine_area_exit(ScrArea *sa)
+void ED_render_scene_update_pre(Main *bmain, Scene *scene, bool time)
+{
+ /* Blender internal might access to the data which is gonna to be freed
+ * by the scene update functions. This applies for example to simulation
+ * data like smoke and fire.
+ */
+ if (time && !BKE_scene_use_new_shading_nodes(scene)) {
+ bScreen *sc;
+ ScrArea *sa;
+ for (sc = bmain->screen.first; sc; sc = sc->id.next) {
+ for (sa = sc->areabase.first; sa; sa = sa->next) {
+ ED_render_engine_area_exit(bmain, sa);
+ }
+ }
+ }
+}
+
+void ED_render_engine_area_exit(Main *bmain, ScrArea *sa)
{
/* clear all render engines in this area */
ARegion *ar;
+ wmWindowManager *wm = bmain->wm.first;
if (sa->spacetype != SPACE_VIEW3D)
return;
for (ar = sa->regionbase.first; ar; ar = ar->next) {
- RegionView3D *rv3d;
-
if (ar->regiontype != RGN_TYPE_WINDOW || !(ar->regiondata))
continue;
-
- rv3d = ar->regiondata;
-
- if (rv3d->render_engine) {
- RE_engine_free(rv3d->render_engine);
- rv3d->render_engine = NULL;
- }
+ ED_view3d_stop_render_preview(wm, ar);
}
}
@@ -166,23 +182,15 @@ void ED_render_engine_changed(Main *bmain)
bScreen *sc;
ScrArea *sa;
Scene *scene;
- Material *ma;
for (sc = bmain->screen.first; sc; sc = sc->id.next)
for (sa = sc->areabase.first; sa; sa = sa->next)
- ED_render_engine_area_exit(sa);
+ ED_render_engine_area_exit(bmain, sa);
RE_FreePersistentData();
for (scene = bmain->scene.first; scene; scene = scene->id.next)
ED_render_id_flush_update(bmain, &scene->id);
-
- /* reset texture painting. Sending one dependency graph signal for any material should
- * refresh any texture slots */
- ma = bmain->mat.first;
- if (ma) {
- DAG_id_tag_update(&ma->id, 0);
- }
}
/***************************** Updates ***********************************
@@ -280,11 +288,11 @@ static void material_changed(Main *bmain, Material *ma)
int texture_draw = false;
/* icons */
- BKE_icon_changed(BKE_icon_getid(&ma->id));
+ BKE_icon_changed(BKE_icon_id_ensure(&ma->id));
/* glsl */
if (ma->gpumaterial.first)
- GPU_material_free(ma);
+ GPU_material_free(&ma->gpumaterial);
/* find node materials using this */
for (parent = bmain->mat.first; parent; parent = parent->id.next) {
@@ -295,10 +303,10 @@ static void material_changed(Main *bmain, Material *ma)
continue;
}
- BKE_icon_changed(BKE_icon_getid(&parent->id));
+ BKE_icon_changed(BKE_icon_id_ensure(&parent->id));
if (parent->gpumaterial.first)
- GPU_material_free(parent);
+ GPU_material_free(&parent->gpumaterial);
}
/* find if we have a scene with textured display */
@@ -310,7 +318,7 @@ static void material_changed(Main *bmain, Material *ma)
}
/* find textured objects */
- if (texture_draw && !(U.gameflags & USER_DISABLE_VBO)) {
+ if (texture_draw) {
for (ob = bmain->object.first; ob; ob = ob->id.next) {
DerivedMesh *dm = ob->derivedFinal;
Material ***material = give_matarar(ob);
@@ -335,7 +343,7 @@ static void lamp_changed(Main *bmain, Lamp *la)
Material *ma;
/* icons */
- BKE_icon_changed(BKE_icon_getid(&la->id));
+ BKE_icon_changed(BKE_icon_id_ensure(&la->id));
/* glsl */
for (ob = bmain->object.first; ob; ob = ob->id.next)
@@ -344,10 +352,10 @@ static void lamp_changed(Main *bmain, Lamp *la)
for (ma = bmain->mat.first; ma; ma = ma->id.next)
if (ma->gpumaterial.first)
- GPU_material_free(ma);
+ GPU_material_free(&ma->gpumaterial);
if (defmaterial.gpumaterial.first)
- GPU_material_free(&defmaterial);
+ GPU_material_free(&defmaterial.gpumaterial);
}
static int material_uses_texture(Material *ma, Tex *tex)
@@ -371,7 +379,7 @@ static void texture_changed(Main *bmain, Tex *tex)
bool texture_draw = false;
/* icons */
- BKE_icon_changed(BKE_icon_getid(&tex->id));
+ BKE_icon_changed(BKE_icon_id_ensure(&tex->id));
/* paint overlays */
for (scene = bmain->scene.first; scene; scene = scene->id.next)
@@ -382,10 +390,10 @@ static void texture_changed(Main *bmain, Tex *tex)
if (!material_uses_texture(ma, tex))
continue;
- BKE_icon_changed(BKE_icon_getid(&ma->id));
+ BKE_icon_changed(BKE_icon_id_ensure(&ma->id));
if (ma->gpumaterial.first)
- GPU_material_free(ma);
+ GPU_material_free(&ma->gpumaterial);
}
/* find lamps */
@@ -413,7 +421,10 @@ static void texture_changed(Main *bmain, Tex *tex)
continue;
}
- BKE_icon_changed(BKE_icon_getid(&wo->id));
+ BKE_icon_changed(BKE_icon_id_ensure(&wo->id));
+
+ if (wo->gpumaterial.first)
+ GPU_material_free(&wo->gpumaterial);
}
/* find compositing nodes */
@@ -430,7 +441,7 @@ static void texture_changed(Main *bmain, Tex *tex)
}
/* find textured objects */
- if (texture_draw && !(U.gameflags & USER_DISABLE_VBO)) {
+ if (texture_draw) {
for (ob = bmain->object.first; ob; ob = ob->id.next) {
DerivedMesh *dm = ob->derivedFinal;
Material ***material = give_matarar(ob);
@@ -458,15 +469,18 @@ static void world_changed(Main *bmain, World *wo)
Material *ma;
/* icons */
- BKE_icon_changed(BKE_icon_getid(&wo->id));
-
+ BKE_icon_changed(BKE_icon_id_ensure(&wo->id));
+
/* glsl */
for (ma = bmain->mat.first; ma; ma = ma->id.next)
if (ma->gpumaterial.first)
- GPU_material_free(ma);
+ GPU_material_free(&ma->gpumaterial);
if (defmaterial.gpumaterial.first)
- GPU_material_free(&defmaterial);
+ GPU_material_free(&defmaterial.gpumaterial);
+
+ if (wo->gpumaterial.first)
+ GPU_material_free(&wo->gpumaterial);
}
static void image_changed(Main *bmain, Image *ima)
@@ -474,7 +488,7 @@ static void image_changed(Main *bmain, Image *ima)
Tex *tex;
/* icons */
- BKE_icon_changed(BKE_icon_getid(&ima->id));
+ BKE_icon_changed(BKE_icon_id_ensure(&ima->id));
/* textures */
for (tex = bmain->tex.first; tex; tex = tex->id.next)
@@ -482,22 +496,34 @@ static void image_changed(Main *bmain, Image *ima)
texture_changed(bmain, tex);
}
-static void scene_changed(Main *bmain, Scene *UNUSED(scene))
+static void scene_changed(Main *bmain, Scene *scene)
{
Object *ob;
Material *ma;
+ World *wo;
/* glsl */
- for (ob = bmain->object.first; ob; ob = ob->id.next)
+ for (ob = bmain->object.first; ob; ob = ob->id.next) {
if (ob->gpulamp.first)
GPU_lamp_free(ob);
+
+ if (ob->mode & OB_MODE_TEXTURE_PAINT) {
+ BKE_texpaint_slots_refresh_object(scene, ob);
+ BKE_paint_proj_mesh_data_check(scene, ob, NULL, NULL, NULL, NULL);
+ GPU_drawobject_free(ob->derivedFinal);
+ }
+ }
for (ma = bmain->mat.first; ma; ma = ma->id.next)
if (ma->gpumaterial.first)
- GPU_material_free(ma);
+ GPU_material_free(&ma->gpumaterial);
+ for (wo = bmain->world.first; wo; wo = wo->id.next)
+ if (wo->gpumaterial.first)
+ GPU_material_free(&wo->gpumaterial);
+
if (defmaterial.gpumaterial.first)
- GPU_material_free(&defmaterial);
+ GPU_material_free(&defmaterial.gpumaterial);
}
void ED_render_id_flush_update(Main *bmain, ID *id)
@@ -539,7 +565,7 @@ void ED_render_id_flush_update(Main *bmain, ID *id)
void ED_render_internal_init(void)
{
- RenderEngineType *ret = RE_engines_find("BLENDER_RENDER");
+ RenderEngineType *ret = RE_engines_find(RE_engine_id_BLENDER_RENDER);
ret->view_update = render_view3d_update;
ret->view_draw = render_view3d_draw;
diff --git a/source/blender/editors/render/render_view.c b/source/blender/editors/render/render_view.c
index 0beb5737ec7..f6690296890 100644
--- a/source/blender/editors/render/render_view.c
+++ b/source/blender/editors/render/render_view.c
@@ -63,7 +63,7 @@ static ScrArea *biggest_non_image_area(bContext *C)
for (sa = sc->areabase.first; sa; sa = sa->next) {
if (sa->winx > 30 && sa->winy > 30) {
size = sa->winx * sa->winy;
- if (sa->spacetype == SPACE_BUTS) {
+ if (!sa->full && sa->spacetype == SPACE_BUTS) {
if (foundwin == 0 && size > bwmaxsize) {
bwmaxsize = size;
big = sa;
@@ -161,11 +161,19 @@ ScrArea *render_view_open(bContext *C, int mx, int my)
}
else if (scene->r.displaymode == R_OUTPUT_SCREEN) {
sa = CTX_wm_area(C);
- if (sa && sa->spacetype == SPACE_IMAGE)
- area_was_image = true;
- /* this function returns with changed context */
- sa = ED_screen_full_newspace(C, sa, SPACE_IMAGE);
+ /* if the active screen is already in fullscreen mode, skip this and
+ * unset the area, so that the fullscreen area is just changed later */
+ if (sa && sa->full) {
+ sa = NULL;
+ }
+ else {
+ if (sa && sa->spacetype == SPACE_IMAGE)
+ area_was_image = true;
+
+ /* this function returns with changed context */
+ sa = ED_screen_full_newspace(C, sa, SPACE_IMAGE);
+ }
}
if (!sa) {
@@ -186,10 +194,15 @@ ScrArea *render_view_open(bContext *C, int mx, int my)
/* makes ESC go back to prev space */
sima->flag |= SI_PREVSPACE;
+
+ /* we already had a fullscreen here -> mark new space as a stacked fullscreen */
+ if (sa->full) {
+ sa->flag |= (AREA_FLAG_STACKED_FULLSCREEN | AREA_FLAG_TEMP_TYPE);
+ }
}
else {
/* use any area of decent size */
- sa = BKE_screen_find_big_area(CTX_wm_screen(C), -1, 0);
+ sa = BKE_screen_find_big_area(CTX_wm_screen(C), SPACE_TYPE_ANY, 0);
if (sa->spacetype != SPACE_IMAGE) {
// XXX newspace(sa, SPACE_IMAGE);
sima = sa->spacedata.first;
@@ -232,6 +245,11 @@ static int render_view_cancel_exec(bContext *C, wmOperator *UNUSED(op))
ScrArea *sa = CTX_wm_area(C);
SpaceImage *sima = sa->spacedata.first;
+ /* ensure image editor fullscreen and area fullscreen states are in sync */
+ if ((sima->flag & SI_FULLWINDOW) && !sa->full) {
+ sima->flag &= ~SI_FULLWINDOW;
+ }
+
/* test if we have a temp screen in front */
if (win->screen->temp) {
wm_window_lower(win);
@@ -243,16 +261,17 @@ static int render_view_cancel_exec(bContext *C, wmOperator *UNUSED(op))
if (sima->flag & SI_FULLWINDOW) {
sima->flag &= ~SI_FULLWINDOW;
- ED_screen_full_prevspace(C, sa);
+ ED_screen_full_prevspace(C, sa, false);
}
- else
+ else {
ED_area_prevspace(C, sa);
+ }
return OPERATOR_FINISHED;
}
else if (sima->flag & SI_FULLWINDOW) {
sima->flag &= ~SI_FULLWINDOW;
- ED_screen_full_toggle(C, win, sa);
+ ED_screen_state_toggle(C, win, sa, SCREENMAXIMIZED);
return OPERATOR_FINISHED;
}
@@ -307,7 +326,7 @@ static int render_view_show_invoke(bContext *C, wmOperator *UNUSED(op), const wm
if (sima->flag & SI_FULLWINDOW) {
sima->flag &= ~SI_FULLWINDOW;
- ED_screen_full_prevspace(C, sa);
+ ED_screen_full_prevspace(C, sa, false);
}
else if (sima->next) {
/* workaround for case of double prevspace, render window
diff --git a/source/blender/editors/screen/CMakeLists.txt b/source/blender/editors/screen/CMakeLists.txt
index 4ff1767f582..ed86ffa5e16 100644
--- a/source/blender/editors/screen/CMakeLists.txt
+++ b/source/blender/editors/screen/CMakeLists.txt
@@ -23,6 +23,7 @@ set(INC
../../blenfont
../../blenkernel
../../blenlib
+ ../../blentranslation
../../bmesh
../../gpu
../../imbuf
@@ -30,6 +31,7 @@ set(INC
../../makesrna
../../windowmanager
../../../../intern/guardedalloc
+ ../../../../intern/glew-mx
)
set(INC_SYS
@@ -51,4 +53,6 @@ if(WITH_INTERNATIONAL)
add_definitions(-DWITH_INTERNATIONAL)
endif()
+add_definitions(${GL_DEFINITIONS})
+
blender_add_lib(bf_editor_screen "${SRC}" "${INC}" "${INC_SYS}")
diff --git a/source/blender/editors/screen/SConscript b/source/blender/editors/screen/SConscript
index 28a6cbb02e6..5f48894c3e7 100644
--- a/source/blender/editors/screen/SConscript
+++ b/source/blender/editors/screen/SConscript
@@ -31,11 +31,13 @@ sources = env.Glob('*.c')
incs = [
'#/intern/guardedalloc',
- '#/extern/glew/include',
+ env['BF_GLEW_INC'],
+ '#/intern/glew-mx',
'../include',
'../../blenfont',
'../../blenkernel',
'../../blenlib',
+ '../../blentranslation',
'../../bmesh',
'../../gpu',
'../../imbuf',
@@ -46,6 +48,7 @@ incs = [
incs = ' '.join(incs)
defs = []
+defs += env['BF_GL_DEFINITIONS']
if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'linuxcross', 'win64-vc', 'win64-mingw'):
incs += ' ' + env['BF_PTHREADS_INC']
diff --git a/source/blender/editors/screen/area.c b/source/blender/editors/screen/area.c
index 752f388c338..79d6b845361 100644
--- a/source/blender/editors/screen/area.c
+++ b/source/blender/editors/screen/area.c
@@ -41,7 +41,6 @@
#include "BLI_utildefines.h"
#include "BLI_linklist_stack.h"
-#include "BLF_translation.h"
#include "BKE_context.h"
#include "BKE_global.h"
@@ -62,7 +61,11 @@
#include "BIF_glutil.h"
#include "BLF_api.h"
+#include "IMB_imbuf.h"
+#include "IMB_imbuf_types.h"
+
#include "UI_interface.h"
+#include "UI_interface_icons.h"
#include "UI_resources.h"
#include "UI_view2d.h"
@@ -72,7 +75,7 @@ extern void ui_draw_anti_tria(float x1, float y1, float x2, float y2, float x3,
/* general area and region code */
-static void region_draw_emboss(ARegion *ar, rcti *scirct)
+static void region_draw_emboss(const ARegion *ar, const rcti *scirct)
{
rcti rect;
@@ -149,6 +152,73 @@ void ED_area_do_refresh(bContext *C, ScrArea *sa)
}
/**
+ * Action zones are only updated if the mouse is inside of them, but in some cases (currently only fullscreen icon)
+ * it might be needed to update their properties and redraw if the mouse isn't inside.
+ */
+void ED_area_azones_update(ScrArea *sa, const int mouse_xy[2])
+{
+ AZone *az;
+ bool changed = false;
+
+ for (az = sa->actionzones.first; az; az = az->next) {
+ if (az->type == AZONE_FULLSCREEN) {
+ /* only if mouse is not hovering the azone */
+ if (BLI_rcti_isect_pt_v(&az->rect, mouse_xy) == false) {
+ az->alpha = 0.0f;
+ changed = true;
+
+ /* can break since currently only this is handled here */
+ break;
+ }
+ }
+ }
+
+ if (changed) {
+ sa->flag &= ~AREA_FLAG_ACTIONZONES_UPDATE;
+ ED_area_tag_redraw(sa);
+ }
+}
+
+/**
+ * \brief Corner widget use for quitting fullscreen.
+ */
+static void area_draw_azone_fullscreen(short x1, short y1, short x2, short y2, float alpha)
+{
+ int x = x2 - ((float) x2 - x1) * 0.5f / UI_DPI_FAC;
+ int y = y2 - ((float) y2 - y1) * 0.5f / UI_DPI_FAC;
+
+ /* adjust the icon distance from the corner */
+ x += 36.0f / UI_DPI_FAC;
+ y += 36.0f / UI_DPI_FAC;
+
+ /* draws from the left bottom corner of the icon */
+ x -= UI_DPI_ICON_SIZE;
+ y -= UI_DPI_ICON_SIZE;
+
+ alpha = min_ff(alpha, 0.75f);
+
+ UI_icon_draw_aspect(x, y, ICON_FULLSCREEN_EXIT, 0.7f / UI_DPI_FAC, alpha);
+
+ /* debug drawing :
+ * The click_rect is the same as defined in fullscreen_click_rcti_init
+ * Keep them both in sync */
+
+ if (G.debug_value == 1) {
+ rcti click_rect;
+ float icon_size = UI_DPI_ICON_SIZE + 7 * UI_DPI_FAC;
+ char alpha_debug = 255 * alpha;
+
+ BLI_rcti_init(&click_rect, x, x + icon_size, y, y + icon_size);
+
+ glColor4ub(255, 0, 0, alpha_debug);
+ fdrawbox(click_rect.xmin, click_rect.ymin, click_rect.xmax, click_rect.ymax);
+ glColor4ub(0, 255, 255, alpha_debug);
+ fdrawline(click_rect.xmin, click_rect.ymin, click_rect.xmax, click_rect.ymax);
+ fdrawline(click_rect.xmin, click_rect.ymax, click_rect.xmax, click_rect.ymin);
+ }
+}
+
+/**
* \brief Corner widgets use for dragging and splitting the view.
*/
static void area_draw_azone(short x1, short y1, short x2, short y2)
@@ -231,21 +301,21 @@ static void region_draw_azone_tab_plus(AZone *az)
/* add code to draw region hidden as 'too small' */
switch (az->edge) {
case AE_TOP_TO_BOTTOMRIGHT:
- uiSetRoundBox(UI_CNR_TOP_LEFT | UI_CNR_TOP_RIGHT);
+ UI_draw_roundbox_corner_set(UI_CNR_TOP_LEFT | UI_CNR_TOP_RIGHT);
break;
case AE_BOTTOM_TO_TOPLEFT:
- uiSetRoundBox(UI_CNR_BOTTOM_RIGHT | UI_CNR_BOTTOM_LEFT);
+ UI_draw_roundbox_corner_set(UI_CNR_BOTTOM_RIGHT | UI_CNR_BOTTOM_LEFT);
break;
case AE_LEFT_TO_TOPRIGHT:
- uiSetRoundBox(UI_CNR_TOP_LEFT | UI_CNR_BOTTOM_LEFT);
+ UI_draw_roundbox_corner_set(UI_CNR_TOP_LEFT | UI_CNR_BOTTOM_LEFT);
break;
case AE_RIGHT_TO_TOPLEFT:
- uiSetRoundBox(UI_CNR_TOP_RIGHT | UI_CNR_BOTTOM_RIGHT);
+ UI_draw_roundbox_corner_set(UI_CNR_TOP_RIGHT | UI_CNR_BOTTOM_RIGHT);
break;
}
glColor4f(0.05f, 0.05f, 0.05f, 0.4f);
- uiRoundBox((float)az->x1, (float)az->y1, (float)az->x2, (float)az->y2, 4.0f);
+ UI_draw_roundbox((float)az->x1, (float)az->y1, (float)az->x2, (float)az->y2, 4.0f);
glEnable(GL_BLEND);
@@ -266,32 +336,32 @@ static void region_draw_azone_tab(AZone *az)
/* add code to draw region hidden as 'too small' */
switch (az->edge) {
case AE_TOP_TO_BOTTOMRIGHT:
- uiSetRoundBox(UI_CNR_TOP_LEFT | UI_CNR_TOP_RIGHT | UI_RB_ALPHA);
+ UI_draw_roundbox_corner_set(UI_CNR_TOP_LEFT | UI_CNR_TOP_RIGHT | UI_RB_ALPHA);
- uiDrawBoxShade(GL_POLYGON, (float)az->x1, (float)az->y1, (float)az->x2, (float)az->y2, 4.0f, -0.3f, 0.05f);
+ UI_draw_roundbox_shade_x(GL_POLYGON, (float)az->x1, (float)az->y1, (float)az->x2, (float)az->y2, 4.0f, -0.3f, 0.05f);
glColor4ub(0, 0, 0, 255);
- uiRoundRect((float)az->x1, 0.3f + (float)az->y1, (float)az->x2, 0.3f + (float)az->y2, 4.0f);
+ UI_draw_roundbox_unfilled((float)az->x1, 0.3f + (float)az->y1, (float)az->x2, 0.3f + (float)az->y2, 4.0f);
break;
case AE_BOTTOM_TO_TOPLEFT:
- uiSetRoundBox(UI_CNR_BOTTOM_RIGHT | UI_CNR_BOTTOM_LEFT | UI_RB_ALPHA);
+ UI_draw_roundbox_corner_set(UI_CNR_BOTTOM_RIGHT | UI_CNR_BOTTOM_LEFT | UI_RB_ALPHA);
- uiDrawBoxShade(GL_POLYGON, (float)az->x1, (float)az->y1, (float)az->x2, (float)az->y2, 4.0f, -0.3f, 0.05f);
+ UI_draw_roundbox_shade_x(GL_POLYGON, (float)az->x1, (float)az->y1, (float)az->x2, (float)az->y2, 4.0f, -0.3f, 0.05f);
glColor4ub(0, 0, 0, 255);
- uiRoundRect((float)az->x1, 0.3f + (float)az->y1, (float)az->x2, 0.3f + (float)az->y2, 4.0f);
+ UI_draw_roundbox_unfilled((float)az->x1, 0.3f + (float)az->y1, (float)az->x2, 0.3f + (float)az->y2, 4.0f);
break;
case AE_LEFT_TO_TOPRIGHT:
- uiSetRoundBox(UI_CNR_TOP_LEFT | UI_CNR_BOTTOM_LEFT | UI_RB_ALPHA);
+ UI_draw_roundbox_corner_set(UI_CNR_TOP_LEFT | UI_CNR_BOTTOM_LEFT | UI_RB_ALPHA);
- uiDrawBoxShade(GL_POLYGON, (float)az->x1, (float)az->y1, (float)az->x2, (float)az->y2, 4.0f, -0.3f, 0.05f);
+ UI_draw_roundbox_shade_x(GL_POLYGON, (float)az->x1, (float)az->y1, (float)az->x2, (float)az->y2, 4.0f, -0.3f, 0.05f);
glColor4ub(0, 0, 0, 255);
- uiRoundRect((float)az->x1, (float)az->y1, (float)az->x2, (float)az->y2, 4.0f);
+ UI_draw_roundbox_unfilled((float)az->x1, (float)az->y1, (float)az->x2, (float)az->y2, 4.0f);
break;
case AE_RIGHT_TO_TOPLEFT:
- uiSetRoundBox(UI_CNR_TOP_RIGHT | UI_CNR_BOTTOM_RIGHT | UI_RB_ALPHA);
+ UI_draw_roundbox_corner_set(UI_CNR_TOP_RIGHT | UI_CNR_BOTTOM_RIGHT | UI_RB_ALPHA);
- uiDrawBoxShade(GL_POLYGON, (float)az->x1, (float)az->y1, (float)az->x2, (float)az->y2, 4.0f, -0.3f, 0.05f);
+ UI_draw_roundbox_shade_x(GL_POLYGON, (float)az->x1, (float)az->y1, (float)az->x2, (float)az->y2, 4.0f, -0.3f, 0.05f);
glColor4ub(0, 0, 0, 255);
- uiRoundRect((float)az->x1, (float)az->y1, (float)az->x2, (float)az->y2, 4.0f);
+ UI_draw_roundbox_unfilled((float)az->x1, (float)az->y1, (float)az->x2, (float)az->y2, 4.0f);
break;
}
@@ -327,6 +397,11 @@ static void region_draw_azone_tria(AZone *az)
glDisable(GL_BLEND);
}
+static void area_azone_tag_update(ScrArea *sa)
+{
+ sa->flag |= AREA_FLAG_ACTIONZONES_UPDATE;
+}
+
static void region_draw_azones(ScrArea *sa, ARegion *ar)
{
AZone *az;
@@ -365,6 +440,13 @@ static void region_draw_azones(ScrArea *sa, ARegion *ar)
}
}
}
+ else if (az->type == AZONE_FULLSCREEN) {
+ area_draw_azone_fullscreen(az->x1, az->y1, az->x2, az->y2, az->alpha);
+
+ if (az->alpha != 0.0f) {
+ area_azone_tag_update(sa);
+ }
+ }
}
}
@@ -451,13 +533,17 @@ void ED_region_do_draw(bContext *C, ARegion *ar)
glDisable(GL_BLEND);
#endif
- ar->do_draw = 0;
memset(&ar->drawrct, 0, sizeof(ar->drawrct));
- uiFreeInactiveBlocks(C, &ar->uiblocks);
+ UI_blocklist_free_inactive(C, &ar->uiblocks);
- if (sa)
- region_draw_emboss(ar, &ar->winrct);
+ if (sa) {
+ /* disable emboss when the area is full,
+ * unless we need to see division between regions (quad-split for eg) */
+ if (((win->screen->state == SCREENFULL) && (ar->alignment == RGN_ALIGN_NONE)) == 0) {
+ region_draw_emboss(ar, &ar->winrct);
+ }
+ }
}
/* **********************************
@@ -490,7 +576,7 @@ void ED_region_tag_refresh_ui(ARegion *ar)
}
}
-void ED_region_tag_redraw_partial(ARegion *ar, rcti *rct)
+void ED_region_tag_redraw_partial(ARegion *ar, const rcti *rct)
{
if (ar && !(ar->do_draw & RGN_DRAWING)) {
if (!(ar->do_draw & RGN_DRAW)) {
@@ -567,10 +653,10 @@ static void area_azone_initialize(wmWindow *win, bScreen *screen, ScrArea *sa)
{
AZone *az;
- /* reinitalize entirely, regions add azones too */
+ /* reinitalize entirely, regions and fullscreen add azones too */
BLI_freelistN(&sa->actionzones);
- if (screen->full != SCREENNORMAL) {
+ if (screen->state != SCREENNORMAL) {
return;
}
@@ -602,6 +688,26 @@ static void area_azone_initialize(wmWindow *win, bScreen *screen, ScrArea *sa)
BLI_rcti_init(&az->rect, az->x1, az->x2, az->y1, az->y2);
}
+static void fullscreen_azone_initialize(ScrArea *sa, ARegion *ar)
+{
+ AZone *az;
+
+ if (ar->regiontype != RGN_TYPE_WINDOW)
+ return;
+
+ az = (AZone *)MEM_callocN(sizeof(AZone), "fullscreen action zone");
+ BLI_addtail(&(sa->actionzones), az);
+ az->type = AZONE_FULLSCREEN;
+ az->ar = ar;
+ az->alpha = 0.0f;
+
+ az->x1 = ar->winrct.xmax - (AZONEFADEOUT - 1);
+ az->y1 = ar->winrct.ymax - (AZONEFADEOUT - 1);
+ az->x2 = ar->winrct.xmax;
+ az->y2 = ar->winrct.ymax;
+ BLI_rcti_init(&az->rect, az->x1, az->x2, az->y1, az->y2);
+}
+
#define AZONEPAD_EDGE (0.1f * U.widget_unit)
#define AZONEPAD_ICON (0.45f * U.widget_unit)
static void region_azone_edge(AZone *az, ARegion *ar)
@@ -710,7 +816,7 @@ static void region_azone_tab_plus(ScrArea *sa, AZone *az, ARegion *ar)
switch (az->edge) {
case AE_TOP_TO_BOTTOMRIGHT:
- if (ar->winrct.ymax == sa->totrct.ymin) add = 1; else add = 0;
+ add = (ar->winrct.ymax == sa->totrct.ymin) ? 1 : 0;
az->x1 = ar->winrct.xmax - 2.5f * AZONEPAD_TAB_PLUSW;
az->y1 = ar->winrct.ymax - add;
az->x2 = ar->winrct.xmax - 1.5f * AZONEPAD_TAB_PLUSW;
@@ -755,7 +861,7 @@ static void region_azone_tab(ScrArea *sa, AZone *az, ARegion *ar)
switch (az->edge) {
case AE_TOP_TO_BOTTOMRIGHT:
- if (ar->winrct.ymax == sa->totrct.ymin) add = 1; else add = 0;
+ add = (ar->winrct.ymax == sa->totrct.ymin) ? 1 : 0;
az->x1 = ar->winrct.xmax - 2 * AZONEPAD_TABW;
az->y1 = ar->winrct.ymax - add;
az->x2 = ar->winrct.xmax - AZONEPAD_TABW;
@@ -800,7 +906,7 @@ static void region_azone_tria(ScrArea *sa, AZone *az, ARegion *ar)
switch (az->edge) {
case AE_TOP_TO_BOTTOMRIGHT:
- if (ar->winrct.ymax == sa->totrct.ymin) add = 1; else add = 0;
+ add = (ar->winrct.ymax == sa->totrct.ymin) ? 1 : 0;
az->x1 = ar->winrct.xmax - 2 * AZONEPAD_TRIAW;
az->y1 = ar->winrct.ymax - add;
az->x2 = ar->winrct.xmax - AZONEPAD_TRIAW;
@@ -830,25 +936,30 @@ static void region_azone_tria(ScrArea *sa, AZone *az, ARegion *ar)
}
-static void region_azone_initialize(ScrArea *sa, ARegion *ar, AZEdge edge)
+static void region_azone_initialize(ScrArea *sa, ARegion *ar, AZEdge edge, const bool is_fullscreen)
{
- AZone *az;
-
- az = (AZone *)MEM_callocN(sizeof(AZone), "actionzone");
- BLI_addtail(&(sa->actionzones), az);
- az->type = AZONE_REGION;
- az->ar = ar;
- az->edge = edge;
+ AZone *az = NULL;
+ const bool is_hidden = (ar->flag & (RGN_FLAG_HIDDEN | RGN_FLAG_TOO_SMALL)) == 0;
- if (ar->flag & (RGN_FLAG_HIDDEN | RGN_FLAG_TOO_SMALL)) {
- if (G.debug_value == 3)
- region_azone_icon(sa, az, ar);
- else if (G.debug_value == 2)
- region_azone_tria(sa, az, ar);
- else if (G.debug_value == 1)
- region_azone_tab(sa, az, ar);
- else
- region_azone_tab_plus(sa, az, ar);
+ if (is_hidden || !is_fullscreen) {
+ az = (AZone *)MEM_callocN(sizeof(AZone), "actionzone");
+ BLI_addtail(&(sa->actionzones), az);
+ az->type = AZONE_REGION;
+ az->ar = ar;
+ az->edge = edge;
+ }
+
+ if (!is_hidden) {
+ if (!is_fullscreen) {
+ if (G.debug_value == 3)
+ region_azone_icon(sa, az, ar);
+ else if (G.debug_value == 2)
+ region_azone_tria(sa, az, ar);
+ else if (G.debug_value == 1)
+ region_azone_tab(sa, az, ar);
+ else
+ region_azone_tab_plus(sa, az, ar);
+ }
}
else {
region_azone_edge(az, ar);
@@ -859,22 +970,22 @@ static void region_azone_initialize(ScrArea *sa, ARegion *ar, AZEdge edge)
/* *************************************************************** */
-static void region_azone_add(ScrArea *sa, ARegion *ar, int alignment)
+static void region_azone_add(ScrArea *sa, ARegion *ar, const int alignment, const bool is_fullscreen)
{
/* edge code (t b l r) is along which area edge azone will be drawn */
if (alignment == RGN_ALIGN_TOP)
- region_azone_initialize(sa, ar, AE_BOTTOM_TO_TOPLEFT);
+ region_azone_initialize(sa, ar, AE_BOTTOM_TO_TOPLEFT, is_fullscreen);
else if (alignment == RGN_ALIGN_BOTTOM)
- region_azone_initialize(sa, ar, AE_TOP_TO_BOTTOMRIGHT);
+ region_azone_initialize(sa, ar, AE_TOP_TO_BOTTOMRIGHT, is_fullscreen);
else if (alignment == RGN_ALIGN_RIGHT)
- region_azone_initialize(sa, ar, AE_LEFT_TO_TOPRIGHT);
+ region_azone_initialize(sa, ar, AE_LEFT_TO_TOPRIGHT, is_fullscreen);
else if (alignment == RGN_ALIGN_LEFT)
- region_azone_initialize(sa, ar, AE_RIGHT_TO_TOPLEFT);
+ region_azone_initialize(sa, ar, AE_RIGHT_TO_TOPLEFT, is_fullscreen);
}
/* dir is direction to check, not the splitting edge direction! */
-static int rct_fits(rcti *rect, char dir, int size)
+static int rct_fits(const rcti *rect, char dir, int size)
{
if (dir == 'h') {
return BLI_rcti_size_x(rect) + 1 - size;
@@ -1156,16 +1267,22 @@ static void region_rect_recursive(wmWindow *win, ScrArea *sa, ARegion *ar, rcti
if (ar->flag & (RGN_FLAG_HIDDEN | RGN_FLAG_TOO_SMALL)) {
ar->winrct = *remainder;
- if (alignment == RGN_ALIGN_TOP)
- ar->winrct.ymin = ar->winrct.ymax;
- else if (alignment == RGN_ALIGN_BOTTOM)
- ar->winrct.ymax = ar->winrct.ymin;
- else if (alignment == RGN_ALIGN_RIGHT)
- ar->winrct.xmin = ar->winrct.xmax;
- else if (alignment == RGN_ALIGN_LEFT)
- ar->winrct.xmax = ar->winrct.xmin;
- else /* prevent winrct to be valid */
- ar->winrct.xmax = ar->winrct.xmin;
+ switch (alignment) {
+ case RGN_ALIGN_TOP:
+ ar->winrct.ymin = ar->winrct.ymax;
+ break;
+ case RGN_ALIGN_BOTTOM:
+ ar->winrct.ymax = ar->winrct.ymin;
+ break;
+ case RGN_ALIGN_RIGHT:
+ ar->winrct.xmin = ar->winrct.xmax;
+ break;
+ case RGN_ALIGN_LEFT:
+ default:
+ /* prevent winrct to be valid */
+ ar->winrct.xmax = ar->winrct.xmin;
+ break;
+ }
}
/* restore prev-split exception */
@@ -1188,7 +1305,13 @@ static void region_rect_recursive(wmWindow *win, ScrArea *sa, ARegion *ar, rcti
* must be minimum '4' */
}
else {
- region_azone_add(sa, ar, alignment);
+ if (ELEM(win->screen->state, SCREENNORMAL, SCREENMAXIMIZED)) {
+ region_azone_add(sa, ar, alignment, false);
+ }
+ else {
+ region_azone_add(sa, ar, alignment, true);
+ fullscreen_azone_initialize(sa, ar);
+ }
}
region_rect_recursive(win, sa, ar->next, remainder, quad);
@@ -1240,7 +1363,7 @@ static void ed_default_handlers(wmWindowManager *wm, ScrArea *sa, ListBase *hand
/* XXX it would be good to have boundbox checks for some of these... */
if (flag & ED_KEYMAP_UI) {
/* user interface widgets */
- UI_add_region_handlers(handlers);
+ UI_region_handlers_add(handlers);
}
if (flag & ED_KEYMAP_VIEW2D) {
/* 2d-viewport handling+manipulation */
@@ -1256,7 +1379,7 @@ static void ed_default_handlers(wmWindowManager *wm, ScrArea *sa, ListBase *hand
ARegion *ar;
/* same local check for all areas */
static rcti rect = {0, 10000, 0, -1};
- rect.ymax = (30 * UI_DPI_FAC);
+ rect.ymax = UI_MARKER_MARGIN_Y;
ar = BKE_area_find_region_type(sa, RGN_TYPE_WINDOW);
if (ar) {
WM_event_add_keymap_handler_bb(handlers, keymap, &rect, &ar->winrct);
@@ -1277,8 +1400,18 @@ static void ed_default_handlers(wmWindowManager *wm, ScrArea *sa, ListBase *hand
}
if (flag & ED_KEYMAP_GPENCIL) {
/* grease pencil */
- wmKeyMap *keymap = WM_keymap_find(wm->defaultconf, "Grease Pencil", 0, 0);
- WM_event_add_keymap_handler(handlers, keymap);
+ /* NOTE: This is now 2 keymaps - One for basic functionality,
+ * and one that only applies when "Edit Mode" is enabled
+ * for strokes.
+ *
+ * For now, it's easier to just include both,
+ * since you hardly want one without the other.
+ */
+ wmKeyMap *keymap_general = WM_keymap_find(wm->defaultconf, "Grease Pencil", 0, 0);
+ wmKeyMap *keymap_edit = WM_keymap_find(wm->defaultconf, "Grease Pencil Stroke Edit Mode", 0, 0);
+
+ WM_event_add_keymap_handler(handlers, keymap_general);
+ WM_event_add_keymap_handler(handlers, keymap_edit);
}
if (flag & ED_KEYMAP_HEADER) {
/* standard keymap for headers regions */
@@ -1334,7 +1467,7 @@ void ED_area_initialize(wmWindowManager *wm, wmWindow *win, ScrArea *sa)
}
else {
/* prevent uiblocks to run */
- uiFreeBlocks(NULL, &ar->uiblocks);
+ UI_blocklist_free(NULL, &ar->uiblocks);
}
}
}
@@ -1394,7 +1527,7 @@ void region_toggle_hidden(bContext *C, ARegion *ar, const bool do_fade)
/* exported to all editors, uses fading default */
void ED_region_toggle_hidden(bContext *C, ARegion *ar)
{
- region_toggle_hidden(C, ar, 1);
+ region_toggle_hidden(C, ar, true);
}
/**
@@ -1438,10 +1571,10 @@ void ED_area_data_copy(ScrArea *sa_dst, ScrArea *sa_src, const bool do_free)
void ED_area_data_swap(ScrArea *sa_dst, ScrArea *sa_src)
{
- sa_dst->headertype = sa_src->headertype;
- sa_dst->spacetype = sa_src->spacetype;
- sa_dst->type = sa_src->type;
- sa_dst->butspacetype = sa_src->butspacetype;
+ SWAP(short, sa_dst->headertype, sa_src->headertype);
+ SWAP(char, sa_dst->spacetype, sa_src->spacetype);
+ SWAP(SpaceType *, sa_dst->type, sa_src->type);
+ SWAP(char, sa_dst->butspacetype, sa_src->butspacetype);
SWAP(ListBase, sa_dst->spacedata, sa_src->spacedata);
@@ -1547,7 +1680,7 @@ void ED_area_newspace(bContext *C, ScrArea *sa, int type)
void ED_area_prevspace(bContext *C, ScrArea *sa)
{
- SpaceLink *sl = (sa) ? sa->spacedata.first : CTX_wm_space_data(C);
+ SpaceLink *sl = sa->spacedata.first;
if (sl && sl->next) {
/* workaround for case of double prevspace, render window
@@ -1561,6 +1694,8 @@ void ED_area_prevspace(bContext *C, ScrArea *sa)
/* no change */
return;
}
+ sa->flag &= ~AREA_FLAG_STACKED_FULLSCREEN;
+
ED_area_tag_redraw(sa);
/* send space change notifier */
@@ -1577,7 +1712,7 @@ int ED_area_header_switchbutton(const bContext *C, uiBlock *block, int yco)
RNA_pointer_create(&(scr->id), &RNA_Area, sa, &areaptr);
- uiDefButR(block, MENU, 0, "", xco, yco, 1.5 * U.widget_unit, U.widget_unit,
+ uiDefButR(block, UI_BTYPE_MENU, 0, "", xco, yco, 1.5 * U.widget_unit, U.widget_unit,
&areaptr, "type", 0, 0.0f, 0.0f, 0.0f, 0.0f, "");
return xco + 1.7 * U.widget_unit;
@@ -1585,10 +1720,10 @@ int ED_area_header_switchbutton(const bContext *C, uiBlock *block, int yco)
/************************ standard UI regions ************************/
-void ED_region_panels(const bContext *C, ARegion *ar, int vertical, const char *context, int contextnr)
+void ED_region_panels(const bContext *C, ARegion *ar, const char *context, int contextnr, const bool vertical)
{
ScrArea *sa = CTX_wm_area(C);
- uiStyle *style = UI_GetStyleDraw();
+ uiStyle *style = UI_style_get_dpi();
uiBlock *block;
PanelType *pt;
Panel *panel;
@@ -1686,16 +1821,16 @@ void ED_region_panels(const bContext *C, ARegion *ar, int vertical, const char *
w -= margin_x;
/* create panels */
- uiBeginPanels(C, ar);
+ UI_panels_begin(C, ar);
- /* set view2d view matrix - uiBeginBlock() stores it */
+ /* set view2d view matrix - UI_block_begin() stores it */
UI_view2d_view_ortho(v2d);
BLI_SMALLSTACK_ITER_BEGIN(pt_stack, pt)
{
bool open;
- panel = uiPanelFindByType(ar, pt);
+ panel = UI_panel_find_by_type(ar, pt);
if (use_category_tabs && pt->category[0] && !STREQ(category, pt->category)) {
if ((panel == NULL) || ((panel->flag & PNL_PIN) == 0)) {
@@ -1704,20 +1839,21 @@ void ED_region_panels(const bContext *C, ARegion *ar, int vertical, const char *
}
/* draw panel */
- block = uiBeginBlock(C, ar, pt->idname, UI_EMBOSS);
- panel = uiBeginPanel(sa, ar, block, pt, panel, &open);
+ block = UI_block_begin(C, ar, pt->idname, UI_EMBOSS);
+ panel = UI_panel_begin(sa, ar, block, pt, panel, &open);
/* 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, 0, style);
+ panel->layout = UI_block_layout(
+ block, UI_LAYOUT_HORIZONTAL, UI_LAYOUT_HEADER,
+ triangle, (UI_UNIT_Y * 1.1f) + style->panelspace, UI_UNIT_Y, 1, 0, style);
pt->draw_header(C, panel);
- uiBlockLayoutResolve(block, &xco, &yco);
+ UI_block_layout_resolve(block, &xco, &yco);
panel->labelofs = xco - triangle;
panel->layout = NULL;
}
@@ -1734,28 +1870,29 @@ void ED_region_panels(const bContext *C, ARegion *ar, int vertical, const char *
else
panelContext = UI_LAYOUT_PANEL;
- panel->layout = uiBlockLayout(block, UI_LAYOUT_VERTICAL, panelContext,
- style->panelspace, 0, w - 2 * style->panelspace, em, 0, style);
+ panel->layout = UI_block_layout(
+ block, UI_LAYOUT_VERTICAL, panelContext,
+ style->panelspace, 0, w - 2 * style->panelspace, em, 0, style);
pt->draw(C, panel);
- uiBlockLayoutResolve(block, &xco, &yco);
+ UI_block_layout_resolve(block, &xco, &yco);
panel->layout = NULL;
yco -= 2 * style->panelspace;
- uiEndPanel(block, w, -yco);
+ UI_panel_end(block, w, -yco);
}
else {
yco = 0;
- uiEndPanel(block, w, 0);
+ UI_panel_end(block, w, 0);
}
- uiEndBlock(C, block);
+ UI_block_end(C, block);
}
BLI_SMALLSTACK_ITER_END;
/* align panels and return size */
- uiEndPanels(C, ar, &x, &y);
+ UI_panels_end(C, ar, &x, &y);
/* before setting the view */
if (vertical) {
@@ -1780,7 +1917,7 @@ void ED_region_panels(const bContext *C, ARegion *ar, int vertical, const char *
* flip +1 or -1 pixel compared to redoing the entire layout again.
* Leaving in commented code for future tests */
#if 0
- uiScalePanels(ar, BLI_rctf_size_x(&v2d->cur));
+ UI_panels_scale(ar, BLI_rctf_size_x(&v2d->cur));
break;
#endif
}
@@ -1795,7 +1932,7 @@ void ED_region_panels(const bContext *C, ARegion *ar, int vertical, const char *
UI_view2d_view_restore(C);
glEnable(GL_BLEND);
UI_ThemeColor4((ar->type->regionid == RGN_TYPE_PREVIEW) ? TH_PREVIEW_BACK : TH_BACK);
- glRecti(0, 0, BLI_rcti_size_x(&ar->winrct), BLI_rcti_size_y(&ar->winrct));
+ glRecti(0, 0, BLI_rcti_size_x(&ar->winrct), BLI_rcti_size_y(&ar->winrct) + 1);
glDisable(GL_BLEND);
}
else {
@@ -1808,7 +1945,7 @@ void ED_region_panels(const bContext *C, ARegion *ar, int vertical, const char *
UI_view2d_view_ortho(v2d);
/* draw panels */
- uiDrawPanels(C, ar);
+ UI_panels_draw(C, ar);
/* restore view matrix */
UI_view2d_view_restore(C);
@@ -1835,7 +1972,7 @@ void ED_region_panels_init(wmWindowManager *wm, ARegion *ar)
void ED_region_header(const bContext *C, ARegion *ar)
{
- uiStyle *style = UI_GetStyleDraw();
+ uiStyle *style = UI_style_get_dpi();
uiBlock *block;
uiLayout *layout;
HeaderType *ht;
@@ -1855,8 +1992,8 @@ void ED_region_header(const bContext *C, ARegion *ar)
/* draw all headers types */
for (ht = ar->type->headertypes.first; ht; ht = ht->next) {
- block = uiBeginBlock(C, ar, ht->idname, UI_EMBOSS);
- layout = uiBlockLayout(block, UI_LAYOUT_HORIZONTAL, UI_LAYOUT_HEADER, xco, yco, UI_UNIT_Y, 1, 0, style);
+ block = UI_block_begin(C, ar, ht->idname, UI_EMBOSS);
+ layout = UI_block_layout(block, UI_LAYOUT_HORIZONTAL, UI_LAYOUT_HEADER, xco, yco, UI_UNIT_Y, 1, 0, style);
if (ht->draw) {
header.type = ht;
@@ -1869,14 +2006,14 @@ void ED_region_header(const bContext *C, ARegion *ar)
maxco = xco;
}
- uiBlockLayoutResolve(block, &xco, &yco);
+ UI_block_layout_resolve(block, &xco, &yco);
/* for view2d */
if (xco > maxco)
maxco = xco;
- uiEndBlock(C, block);
- uiDrawBlock(C, block);
+ UI_block_end(C, block);
+ UI_block_draw(C, block);
}
/* always as last */
@@ -1897,10 +2034,10 @@ int ED_area_headersize(void)
return (int)(HEADERY * UI_DPI_FAC);
}
-void ED_region_info_draw(ARegion *ar, const char *text, int block, float fill_color[4])
+void ED_region_info_draw(ARegion *ar, const char *text, float fill_color[4], const bool full_redraw)
{
const int header_height = UI_UNIT_Y;
- uiStyle *style = UI_GetStyleDraw();
+ uiStyle *style = UI_style_get_dpi();
int fontid = style->widget.uifont_id;
GLint scissor[4];
rcti rect;
@@ -1910,7 +2047,7 @@ void ED_region_info_draw(ARegion *ar, const char *text, int block, float fill_co
rect.ymin = BLI_rcti_size_y(&ar->winrct) - header_height;
/* box fill entire width or just around text */
- if (!block)
+ if (!full_redraw)
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);
@@ -1940,6 +2077,196 @@ void ED_region_info_draw(ARegion *ar, const char *text, int block, float fill_co
glScissor(scissor[0], scissor[1], scissor[2], scissor[3]);
}
+#define MAX_METADATA_STR 1024
+
+static const char *meta_data_list[] =
+{
+ "File",
+ "Strip",
+ "Note",
+ "Date",
+ "RenderTime",
+ "Marker",
+ "Time",
+ "Frame",
+ "Camera",
+ "Scene"
+};
+
+BLI_INLINE bool metadata_is_valid(ImBuf *ibuf, char *r_str, short index, int offset)
+{
+ return (IMB_metadata_get_field(ibuf, meta_data_list[index], r_str + offset, MAX_METADATA_STR - offset) && r_str[0]);
+}
+
+static void metadata_draw_imbuf(ImBuf *ibuf, const rctf *rect, int fontid, const bool is_top)
+{
+ char temp_str[MAX_METADATA_STR];
+ int line_width;
+ int ofs_y = 0;
+ short i;
+ int len;
+ const float height = BLF_height_max(fontid);
+ const float vertical_offset = height + (0.1f * U.widget_unit);
+
+ if (is_top) {
+ for (i = 0; i < 4; i++) {
+ /* first line */
+ if (i == 0) {
+ bool do_newline = false;
+ len = BLI_snprintf_rlen(temp_str, MAX_METADATA_STR, "%s: ", meta_data_list[0]);
+ if (metadata_is_valid(ibuf, temp_str, 0, len)) {
+ BLF_position(fontid, rect->xmin + (0.2f * U.widget_unit),
+ rect->ymax - vertical_offset, 0.0f);
+ BLF_draw(fontid, temp_str, BLF_DRAW_STR_DUMMY_MAX);
+ do_newline = true;
+ }
+
+ len = BLI_snprintf_rlen(temp_str, MAX_METADATA_STR, "%s: ", meta_data_list[1]);
+ if (metadata_is_valid(ibuf, temp_str, 1, len)) {
+ line_width = BLF_width(fontid, temp_str, BLF_DRAW_STR_DUMMY_MAX);
+ BLF_position(fontid, rect->xmax - line_width - (0.2f * U.widget_unit),
+ rect->ymax - vertical_offset, 0.0f);
+ BLF_draw(fontid, temp_str, BLF_DRAW_STR_DUMMY_MAX);
+ do_newline = true;
+ }
+
+ if (do_newline)
+ ofs_y += vertical_offset;
+ }
+ else if (i == 1) {
+ len = BLI_snprintf_rlen(temp_str, MAX_METADATA_STR, "%s: ", meta_data_list[i + 1]);
+ if (metadata_is_valid(ibuf, temp_str, i + 1, len)) {
+ BLF_position(fontid, rect->xmin + (0.2f * U.widget_unit),
+ rect->ymax - vertical_offset - ofs_y, 0.0f);
+ BLF_draw(fontid, temp_str, BLF_DRAW_STR_DUMMY_MAX);
+ ofs_y += vertical_offset;
+ }
+ }
+ else {
+ len = BLI_snprintf_rlen(temp_str, MAX_METADATA_STR, "%s: ", meta_data_list[i + 1]);
+ if (metadata_is_valid(ibuf, temp_str, i + 1, len)) {
+ line_width = BLF_width(fontid, temp_str, BLF_DRAW_STR_DUMMY_MAX);
+ BLF_position(fontid, rect->xmax - line_width - (0.2f * U.widget_unit),
+ rect->ymax - vertical_offset - ofs_y, 0.0f);
+ BLF_draw(fontid, temp_str, BLF_DRAW_STR_DUMMY_MAX);
+ ofs_y += vertical_offset;
+ }
+ }
+ }
+ }
+ else {
+ int ofs_x = 0;
+ for (i = 5; i < 10; i++) {
+ len = BLI_snprintf_rlen(temp_str, MAX_METADATA_STR, "%s: ", meta_data_list[i]);
+ if (metadata_is_valid(ibuf, temp_str, i, len)) {
+ BLF_position(fontid, rect->xmin + (0.2f * U.widget_unit) + ofs_x,
+ rect->ymin + (0.3f * U.widget_unit), 0.0f);
+ BLF_draw(fontid, temp_str, BLF_DRAW_STR_DUMMY_MAX);
+
+ ofs_x += BLF_width(fontid, temp_str, BLF_DRAW_STR_DUMMY_MAX) + UI_UNIT_X;
+ }
+ }
+ }
+}
+
+static float metadata_box_height_get(ImBuf *ibuf, int fontid, const bool is_top)
+{
+ char str[MAX_METADATA_STR] = "";
+ short i, count = 0;
+ const float height = BLF_height_max(fontid) + 0.1f * U.widget_unit;
+
+ if (is_top) {
+ if (metadata_is_valid(ibuf, str, 0, 0) || metadata_is_valid(ibuf, str, 1, 0)) {
+ count++;
+ }
+ for (i = 2; i < 5; i++) {
+ if (metadata_is_valid(ibuf, str, i, 0)) {
+ count++;
+ }
+ }
+ }
+ else {
+ for (i = 5; i < 10; i++) {
+ if (metadata_is_valid(ibuf, str, i, 0)) {
+ count = 1;
+ }
+ }
+ }
+
+ if (count) {
+ return (height * count + (0.1f * U.widget_unit));
+ }
+
+ return 0;
+}
+
+#undef MAX_METADATA_STR
+
+void ED_region_image_metadata_draw(int x, int y, ImBuf *ibuf, rctf frame, float zoomx, float zoomy)
+{
+ float box_y;
+ rctf rect;
+ uiStyle *style = UI_style_get_dpi();
+
+ if (!ibuf->metadata)
+ return;
+
+ /* find window pixel coordinates of origin */
+ glPushMatrix();
+
+ /* offset and zoom using ogl */
+ glTranslatef(x, y, 0.0f);
+ glScalef(zoomx, zoomy, 1.0f);
+
+ BLF_size(blf_mono_font, style->widgetlabel.points * 1.5f, U.dpi);
+
+ /* *** upper box*** */
+
+ /* get needed box height */
+ box_y = metadata_box_height_get(ibuf, blf_mono_font, true);
+
+ if (box_y) {
+ UI_ThemeColor(TH_METADATA_BG);
+
+ /* set up rect */
+ BLI_rctf_init(&rect, frame.xmin, frame.xmax, frame.ymax, frame.ymax + box_y);
+ /* draw top box */
+ glRectf(rect.xmin, rect.ymin, rect.xmax, rect.ymax);
+
+ BLF_clipping(blf_mono_font, rect.xmin, rect.ymin, rect.xmax, rect.ymax);
+ BLF_enable(blf_mono_font, BLF_CLIPPING);
+
+ UI_ThemeColor(TH_METADATA_TEXT);
+ metadata_draw_imbuf(ibuf, &rect, blf_mono_font, true);
+
+ BLF_disable(blf_mono_font, BLF_CLIPPING);
+ }
+
+
+ /* *** lower box*** */
+
+ box_y = metadata_box_height_get(ibuf, blf_mono_font, false);
+
+ if (box_y) {
+ UI_ThemeColor(TH_METADATA_BG);
+
+ /* set up box rect */
+ BLI_rctf_init(&rect, frame.xmin, frame.xmax, frame.ymin - box_y, frame.ymin);
+ /* draw top box */
+ glRectf(rect.xmin, rect.ymin, rect.xmax, rect.ymax);
+
+ BLF_clipping(blf_mono_font, rect.xmin, rect.ymin, rect.xmax, rect.ymax);
+ BLF_enable(blf_mono_font, BLF_CLIPPING);
+
+ UI_ThemeColor(TH_METADATA_TEXT);
+ metadata_draw_imbuf(ibuf, &rect, blf_mono_font, false);
+
+ BLF_disable(blf_mono_font, BLF_CLIPPING);
+ }
+
+ glPopMatrix();
+}
+
void ED_region_grid_draw(ARegion *ar, float zoomx, float zoomy)
{
float gridsize, gridstep = 1.0f / 32.0f;
@@ -2040,7 +2367,7 @@ void ED_region_cache_draw_background(const ARegion *ar)
void ED_region_cache_draw_curfra_label(const int framenr, const float x, const float y)
{
- uiStyle *style = UI_GetStyle();
+ uiStyle *style = UI_style_get();
int fontid = style->widget.uifont_id;
char numstr[32];
float font_dims[2] = {0.0f, 0.0f};
@@ -2075,4 +2402,3 @@ void ED_region_cache_draw_cached_segments(const ARegion *ar, const int num_segme
}
}
}
-
diff --git a/source/blender/editors/screen/glutil.c b/source/blender/editors/screen/glutil.c
index 0edde66ffff..fd65d81baad 100644
--- a/source/blender/editors/screen/glutil.c
+++ b/source/blender/editors/screen/glutil.c
@@ -45,7 +45,6 @@
#include "BIF_gl.h"
#include "BIF_glutil.h"
-#include "GPU_extensions.h"
#include "IMB_colormanagement.h"
#include "IMB_imbuf_types.h"
@@ -224,15 +223,15 @@ void fdrawcheckerboard(float x1, float y1, float x2, float y2)
glDisable(GL_POLYGON_STIPPLE);
}
-void sdrawline(short x1, short y1, short x2, short y2)
+void sdrawline(int x1, int y1, int x2, int y2)
{
- short v[2];
+ int v[2];
glBegin(GL_LINE_STRIP);
v[0] = x1; v[1] = y1;
- glVertex2sv(v);
+ glVertex2iv(v);
v[0] = x2; v[1] = y2;
- glVertex2sv(v);
+ glVertex2iv(v);
glEnd();
}
@@ -246,25 +245,25 @@ void sdrawline(short x1, short y1, short x2, short y2)
* x1,y1-- x2,y1
*/
-static void sdrawtripoints(short x1, short y1, short x2, short y2)
+static void sdrawtripoints(int x1, int y1, int x2, int y2)
{
- short v[2];
+ int v[2];
v[0] = x1; v[1] = y1;
- glVertex2sv(v);
+ glVertex2iv(v);
v[0] = x1; v[1] = y2;
- glVertex2sv(v);
+ glVertex2iv(v);
v[0] = x2; v[1] = y1;
- glVertex2sv(v);
+ glVertex2iv(v);
}
-void sdrawtri(short x1, short y1, short x2, short y2)
+void sdrawtri(int x1, int y1, int x2, int y2)
{
glBegin(GL_LINE_STRIP);
sdrawtripoints(x1, y1, x2, y2);
glEnd();
}
-void sdrawtrifill(short x1, short y1, short x2, short y2)
+void sdrawtrifill(int x1, int y1, int x2, int y2)
{
glBegin(GL_TRIANGLES);
sdrawtripoints(x1, y1, x2, y2);
@@ -272,22 +271,22 @@ void sdrawtrifill(short x1, short y1, short x2, short y2)
}
#endif
-void sdrawbox(short x1, short y1, short x2, short y2)
+void sdrawbox(int x1, int y1, int x2, int y2)
{
- short v[2];
+ int v[2];
glBegin(GL_LINE_STRIP);
v[0] = x1; v[1] = y1;
- glVertex2sv(v);
+ glVertex2iv(v);
v[0] = x1; v[1] = y2;
- glVertex2sv(v);
+ glVertex2iv(v);
v[0] = x2; v[1] = y2;
- glVertex2sv(v);
+ glVertex2iv(v);
v[0] = x2; v[1] = y1;
- glVertex2sv(v);
+ glVertex2iv(v);
v[0] = x1; v[1] = y1;
- glVertex2sv(v);
+ glVertex2iv(v);
glEnd();
}
@@ -339,7 +338,7 @@ void sdrawXORline(int x0, int y0, int x1, int y1)
void sdrawXORline4(int nr, int x0, int y0, int x1, int y1)
{
- static short old[4][2][2];
+ static int old[4][2][2];
static char flags[4] = {0, 0, 0, 0};
/* with builtin memory, max 4 lines */
@@ -350,8 +349,8 @@ void sdrawXORline4(int nr, int x0, int y0, int x1, int y1)
if (nr == -1) { /* flush */
for (nr = 0; nr < 4; nr++) {
if (flags[nr]) {
- glVertex2sv(old[nr][0]);
- glVertex2sv(old[nr][1]);
+ glVertex2iv(old[nr][0]);
+ glVertex2iv(old[nr][1]);
flags[nr] = 0;
}
}
@@ -359,8 +358,8 @@ void sdrawXORline4(int nr, int x0, int y0, int x1, int y1)
else {
if (nr >= 0 && nr < 4) {
if (flags[nr]) {
- glVertex2sv(old[nr][0]);
- glVertex2sv(old[nr][1]);
+ glVertex2iv(old[nr][0]);
+ glVertex2iv(old[nr][1]);
}
old[nr][0][0] = x0;
@@ -580,25 +579,25 @@ void glaDrawPixelsTexScaled(float x, float y, int img_w, int img_h, int format,
continue;
if (type == GL_FLOAT) {
- glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, subpart_w, subpart_h, format, GL_FLOAT, &f_rect[subpart_y * offset_y * img_w * components + subpart_x * offset_x * components]);
+ glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, subpart_w, subpart_h, format, GL_FLOAT, &f_rect[((size_t)subpart_y) * offset_y * img_w * components + subpart_x * offset_x * components]);
/* add an extra border of pixels so linear looks ok at edges of full image. */
if (subpart_w < tex_w)
- glTexSubImage2D(GL_TEXTURE_2D, 0, subpart_w, 0, 1, subpart_h, format, GL_FLOAT, &f_rect[subpart_y * offset_y * img_w * components + (subpart_x * offset_x + subpart_w - 1) * components]);
+ glTexSubImage2D(GL_TEXTURE_2D, 0, subpart_w, 0, 1, subpart_h, format, GL_FLOAT, &f_rect[((size_t)subpart_y) * offset_y * img_w * components + (subpart_x * offset_x + subpart_w - 1) * components]);
if (subpart_h < tex_h)
- glTexSubImage2D(GL_TEXTURE_2D, 0, 0, subpart_h, subpart_w, 1, format, GL_FLOAT, &f_rect[(subpart_y * offset_y + subpart_h - 1) * img_w * components + subpart_x * offset_x * components]);
+ glTexSubImage2D(GL_TEXTURE_2D, 0, 0, subpart_h, subpart_w, 1, format, GL_FLOAT, &f_rect[(((size_t)subpart_y) * offset_y + subpart_h - 1) * img_w * components + subpart_x * offset_x * components]);
if (subpart_w < tex_w && subpart_h < tex_h)
- glTexSubImage2D(GL_TEXTURE_2D, 0, subpart_w, subpart_h, 1, 1, format, GL_FLOAT, &f_rect[(subpart_y * offset_y + subpart_h - 1) * img_w * components + (subpart_x * offset_x + subpart_w - 1) * components]);
+ glTexSubImage2D(GL_TEXTURE_2D, 0, subpart_w, subpart_h, 1, 1, format, GL_FLOAT, &f_rect[(((size_t)subpart_y) * offset_y + subpart_h - 1) * img_w * components + (subpart_x * offset_x + subpart_w - 1) * components]);
}
else {
- glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, subpart_w, subpart_h, format, GL_UNSIGNED_BYTE, &uc_rect[subpart_y * offset_y * img_w * components + subpart_x * offset_x * components]);
+ glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, subpart_w, subpart_h, format, GL_UNSIGNED_BYTE, &uc_rect[((size_t)subpart_y) * offset_y * img_w * components + subpart_x * offset_x * components]);
if (subpart_w < tex_w)
- glTexSubImage2D(GL_TEXTURE_2D, 0, subpart_w, 0, 1, subpart_h, format, GL_UNSIGNED_BYTE, &uc_rect[subpart_y * offset_y * img_w * components + (subpart_x * offset_x + subpart_w - 1) * components]);
+ glTexSubImage2D(GL_TEXTURE_2D, 0, subpart_w, 0, 1, subpart_h, format, GL_UNSIGNED_BYTE, &uc_rect[((size_t)subpart_y) * offset_y * img_w * components + (subpart_x * offset_x + subpart_w - 1) * components]);
if (subpart_h < tex_h)
- glTexSubImage2D(GL_TEXTURE_2D, 0, 0, subpart_h, subpart_w, 1, format, GL_UNSIGNED_BYTE, &uc_rect[(subpart_y * offset_y + subpart_h - 1) * img_w * components + subpart_x * offset_x * components]);
+ glTexSubImage2D(GL_TEXTURE_2D, 0, 0, subpart_h, subpart_w, 1, format, GL_UNSIGNED_BYTE, &uc_rect[(((size_t)subpart_y) * offset_y + subpart_h - 1) * img_w * components + subpart_x * offset_x * components]);
if (subpart_w < tex_w && subpart_h < tex_h)
- glTexSubImage2D(GL_TEXTURE_2D, 0, subpart_w, subpart_h, 1, 1, format, GL_UNSIGNED_BYTE, &uc_rect[(subpart_y * offset_y + subpart_h - 1) * img_w * components + (subpart_x * offset_x + subpart_w - 1) * components]);
+ glTexSubImage2D(GL_TEXTURE_2D, 0, subpart_w, subpart_h, 1, 1, format, GL_UNSIGNED_BYTE, &uc_rect[(((size_t)subpart_y) * offset_y + subpart_h - 1) * img_w * components + (subpart_x * offset_x + subpart_w - 1) * components]);
}
glEnable(GL_TEXTURE_2D);
@@ -840,16 +839,16 @@ void gla2DDrawTranslatePt(gla2DDrawInfo *di, float wo_x, float wo_y, int *r_sc_x
}
/**
- * Translate the \a world point from world coordiantes into screen space.
+ * Translate the \a world point from world coordinates into screen space.
*/
-void gla2DDrawTranslatePtv(gla2DDrawInfo *di, float world[2], int screen_r[2])
+void gla2DDrawTranslatePtv(gla2DDrawInfo *di, float world[2], int r_screen[2])
{
screen_r[0] = (world[0] - di->world_rect.xmin) * di->wo_to_sc[0];
screen_r[1] = (world[1] - di->world_rect.ymin) * di->wo_to_sc[1];
}
/**
- * Restores the previous OpenGL state and free's the auxilary gla data.
+ * Restores the previous OpenGL state and frees the auxiliary gla data.
*/
void glaEnd2DDraw(gla2DDrawInfo *di)
{
@@ -992,7 +991,7 @@ void bgl_get_mats(bglMats *mats)
/**
* \note \a viewdist is only for ortho at the moment.
*/
-void bglPolygonOffset(float viewdist, float dist)
+void bglPolygonOffset(float viewdist, float dist)
{
static float winmat[16], offset = 0.0;
@@ -1008,8 +1007,25 @@ void bglPolygonOffset(float viewdist, float dist)
/* dist is from camera to center point */
- if (winmat[15] > 0.5f) offs = 0.00001f * dist * viewdist; // ortho tweaking
- else offs = 0.0005f * dist; // should be clipping value or so...
+ if (winmat[15] > 0.5f) {
+#if 1
+ offs = 0.00001f * dist * viewdist; // ortho tweaking
+#else
+ static float depth_fac = 0.0f;
+ if (depth_fac == 0.0f) {
+ int depthbits;
+ glGetIntegerv(GL_DEPTH_BITS, &depthbits);
+ depth_fac = 1.0f / (float)((1 << depthbits) - 1);
+ }
+ offs = (-1.0 / winmat[10]) * dist * depth_fac;
+
+ UNUSED_VARS(viewdist);
+#endif
+ }
+ else {
+ /* should be clipping value or so... */
+ offs = 0.0005f * dist;
+ }
winmat[14] -= offs;
offset += offs;
@@ -1137,9 +1153,9 @@ void glaDrawImBuf_glsl_ctx(const bContext *C, ImBuf *ibuf, float x, float y, int
void cpack(unsigned int x)
{
- glColor3ub( ( (x) & 0xFF),
- (((x) >> 8) & 0xFF),
- (((x) >> 16) & 0xFF) );
+ glColor3ub(( (x) & 0xFF),
+ (((x) >> 8) & 0xFF),
+ (((x) >> 16) & 0xFF));
}
void glaDrawBorderCorners(const rcti *border, float zoomx, float zoomy)
diff --git a/source/blender/editors/screen/screen_context.c b/source/blender/editors/screen/screen_context.c
index 7c8987ae778..87c0ce398e5 100644
--- a/source/blender/editors/screen/screen_context.c
+++ b/source/blender/editors/screen/screen_context.c
@@ -26,12 +26,13 @@
* \ingroup edscr
*/
-
+#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "DNA_object_types.h"
#include "DNA_armature_types.h"
+#include "DNA_gpencil_types.h"
#include "DNA_sequence_types.h"
#include "DNA_scene_types.h"
#include "DNA_screen_types.h"
@@ -45,17 +46,32 @@
#include "BKE_object.h"
#include "BKE_action.h"
#include "BKE_armature.h"
+#include "BKE_gpencil.h"
+#include "BKE_screen.h"
#include "BKE_sequencer.h"
#include "RNA_access.h"
#include "ED_armature.h"
+#include "ED_gpencil.h"
#include "WM_api.h"
#include "UI_interface.h"
#include "screen_intern.h"
+static unsigned int context_layers(bScreen *sc, Scene *scene, ScrArea *sa_ctx)
+{
+ /* needed for 'USE_ALLSELECT' define, otherwise we end up editing off-screen layers. */
+ if (sc && sa_ctx && (sa_ctx->spacetype == SPACE_BUTS)) {
+ const unsigned int lay = BKE_screen_view3d_layer_all(sc);
+ if (lay) {
+ return lay;
+ }
+ }
+ return scene->lay;
+}
+
const char *screen_context_dir[] = {
"scene", "visible_objects", "visible_bases", "selectable_objects", "selectable_bases",
"selected_objects", "selected_bases",
@@ -66,15 +82,18 @@ const char *screen_context_dir[] = {
"sculpt_object", "vertex_paint_object", "weight_paint_object",
"image_paint_object", "particle_edit_object",
"sequences", "selected_sequences", "selected_editable_sequences", /* sequencer */
+ "gpencil_data", "gpencil_data_owner", /* grease pencil data */
+ "visible_gpencil_layers", "editable_gpencil_layers", "editable_gpencil_strokes",
+ "active_gpencil_layer", "active_gpencil_frame",
"active_operator",
NULL};
int ed_screen_context(const bContext *C, const char *member, bContextDataResult *result)
{
bScreen *sc = CTX_wm_screen(C);
+ ScrArea *sa = CTX_wm_area(C);
Scene *scene = sc->scene;
Base *base;
- unsigned int lay = scene->lay;
#if 0 /* Using the context breaks adding objects in the UI. Need to find out why - campbell */
Object *obact = CTX_data_active_object(C);
@@ -95,10 +114,11 @@ int ed_screen_context(const bContext *C, const char *member, bContextDataResult
return 1;
}
else if (CTX_data_equals(member, "visible_objects") || CTX_data_equals(member, "visible_bases")) {
+ const unsigned int lay = context_layers(sc, scene, sa);
int visible_objects = CTX_data_equals(member, "visible_objects");
for (base = scene->base.first; base; base = base->next) {
- if (((base->object->restrictflag & OB_RESTRICT_VIEW) == 0) && (base->lay & scene->lay)) {
+ if (((base->object->restrictflag & OB_RESTRICT_VIEW) == 0) && (base->lay & lay)) {
if (visible_objects)
CTX_data_id_list_add(result, &base->object->id);
else
@@ -109,6 +129,7 @@ int ed_screen_context(const bContext *C, const char *member, bContextDataResult
return 1;
}
else if (CTX_data_equals(member, "selectable_objects") || CTX_data_equals(member, "selectable_bases")) {
+ const unsigned int lay = context_layers(sc, scene, sa);
int selectable_objects = CTX_data_equals(member, "selectable_objects");
for (base = scene->base.first; base; base = base->next) {
@@ -125,10 +146,11 @@ int ed_screen_context(const bContext *C, const char *member, bContextDataResult
return 1;
}
else if (CTX_data_equals(member, "selected_objects") || CTX_data_equals(member, "selected_bases")) {
+ const unsigned int lay = context_layers(sc, scene, sa);
int selected_objects = CTX_data_equals(member, "selected_objects");
for (base = scene->base.first; base; base = base->next) {
- if ((base->flag & SELECT) && (base->lay & scene->lay)) {
+ if ((base->flag & SELECT) && (base->lay & lay)) {
if (selected_objects)
CTX_data_id_list_add(result, &base->object->id);
else
@@ -139,10 +161,11 @@ int ed_screen_context(const bContext *C, const char *member, bContextDataResult
return 1;
}
else if (CTX_data_equals(member, "selected_editable_objects") || CTX_data_equals(member, "selected_editable_bases")) {
+ const unsigned int lay = context_layers(sc, scene, sa);
int selected_editable_objects = CTX_data_equals(member, "selected_editable_objects");
for (base = scene->base.first; base; base = base->next) {
- if ((base->flag & SELECT) && (base->lay & scene->lay)) {
+ if ((base->flag & SELECT) && (base->lay & lay)) {
if ((base->object->restrictflag & OB_RESTRICT_VIEW) == 0) {
if (0 == BKE_object_is_libdata(base->object)) {
if (selected_editable_objects)
@@ -392,6 +415,114 @@ int ed_screen_context(const bContext *C, const char *member, bContextDataResult
return 1;
}
}
+ else if (CTX_data_equals(member, "gpencil_data")) {
+ /* FIXME: for some reason, CTX_data_active_object(C) returns NULL when called from these situations
+ * (as outlined above - see Campbell's #ifdefs). That causes the get_active function to fail when
+ * called from context. For that reason, we end up using an alternative where we pass everything in!
+ */
+ bGPdata *gpd = ED_gpencil_data_get_active_direct((ID *)sc, scene, sa, obact);
+
+ if (gpd) {
+ CTX_data_id_pointer_set(result, &gpd->id);
+ return 1;
+ }
+ }
+ else if (CTX_data_equals(member, "gpencil_data_owner")) {
+ /* pointer to which data/datablock owns the reference to the Grease Pencil data being used (as gpencil_data)
+ * XXX: see comment for gpencil_data case...
+ */
+ bGPdata **gpd_ptr = NULL;
+ PointerRNA ptr;
+
+ /* get pointer to Grease Pencil Data */
+ gpd_ptr = ED_gpencil_data_get_pointers_direct((ID *)sc, scene, sa, obact, &ptr);
+
+ if (gpd_ptr) {
+ CTX_data_pointer_set(result, ptr.id.data, ptr.type, ptr.data);
+ return 1;
+ }
+ }
+ else if (CTX_data_equals(member, "active_gpencil_layer")) {
+ /* XXX: see comment for gpencil_data case... */
+ bGPdata *gpd = ED_gpencil_data_get_active_direct((ID *)sc, scene, sa, obact);
+
+ if (gpd) {
+ bGPDlayer *gpl = gpencil_layer_getactive(gpd);
+
+ if (gpl) {
+ CTX_data_pointer_set(result, &gpd->id, &RNA_GPencilLayer, gpl);
+ return 1;
+ }
+ }
+ }
+ else if (CTX_data_equals(member, "active_gpencil_frame")) {
+ /* XXX: see comment for gpencil_data case... */
+ bGPdata *gpd = ED_gpencil_data_get_active_direct((ID *)sc, scene, sa, obact);
+
+ if (gpd) {
+ bGPDlayer *gpl = gpencil_layer_getactive(gpd);
+
+ if (gpl) {
+ CTX_data_pointer_set(result, &gpd->id, &RNA_GPencilLayer, gpl->actframe);
+ return 1;
+ }
+ }
+ }
+ else if (CTX_data_equals(member, "visible_gpencil_layers")) {
+ /* XXX: see comment for gpencil_data case... */
+ bGPdata *gpd = ED_gpencil_data_get_active_direct((ID *)sc, scene, sa, obact);
+
+ if (gpd) {
+ bGPDlayer *gpl;
+
+ for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ if ((gpl->flag & GP_LAYER_HIDE) == 0) {
+ CTX_data_list_add(result, &gpd->id, &RNA_GPencilLayer, gpl);
+ }
+ }
+ CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION);
+ return 1;
+ }
+ }
+ else if (CTX_data_equals(member, "editable_gpencil_layers")) {
+ /* XXX: see comment for gpencil_data case... */
+ bGPdata *gpd = ED_gpencil_data_get_active_direct((ID *)sc, scene, sa, obact);
+
+ if (gpd) {
+ bGPDlayer *gpl;
+
+ for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ if ((gpl->flag & (GP_LAYER_HIDE | GP_LAYER_LOCKED)) == 0) {
+ CTX_data_list_add(result, &gpd->id, &RNA_GPencilLayer, gpl);
+ }
+ }
+ CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION);
+ return 1;
+ }
+ }
+ else if (CTX_data_equals(member, "editable_gpencil_strokes")) {
+ /* XXX: see comment for gpencil_data case... */
+ bGPdata *gpd = ED_gpencil_data_get_active_direct((ID *)sc, scene, sa, obact);
+
+ if (gpd) {
+ bGPDlayer *gpl;
+
+ for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ if ((gpl->flag & (GP_LAYER_HIDE | GP_LAYER_LOCKED)) == 0 && (gpl->actframe)) {
+ bGPDframe *gpf = gpl->actframe;
+ bGPDstroke *gps;
+
+ for (gps = gpf->strokes.first; gps; gps = gps->next) {
+ if (ED_gpencil_stroke_can_use_direct(sa, gps)) {
+ CTX_data_list_add(result, &gpd->id, &RNA_GPencilStroke, gps);
+ }
+ }
+ }
+ }
+ CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION);
+ return 1;
+ }
+ }
else if (CTX_data_equals(member, "active_operator")) {
wmOperator *op = NULL;
@@ -399,8 +530,8 @@ int ed_screen_context(const bContext *C, const char *member, bContextDataResult
if (sfile) {
op = sfile->op;
}
- else if ((op = uiContextActiveOperator(C))) {
- /* do nothign */
+ else if ((op = UI_context_active_operator_get(C))) {
+ /* do nothing */
}
else {
/* note, this checks poll, could be a problem, but this also
diff --git a/source/blender/editors/screen/screen_edit.c b/source/blender/editors/screen/screen_edit.c
index 5beab9fcc14..1a1cc8894e6 100644
--- a/source/blender/editors/screen/screen_edit.c
+++ b/source/blender/editors/screen/screen_edit.c
@@ -59,6 +59,7 @@
#include "ED_screen.h"
#include "ED_screen_types.h"
#include "ED_clip.h"
+#include "ED_node.h"
#include "ED_render.h"
#include "UI_interface.h"
@@ -1009,7 +1010,7 @@ static void scrarea_draw_shape_light(ScrArea *sa, char UNUSED(dir))
glDisable(GL_BLEND);
}
-static void drawscredge_area_draw(int sizex, int sizey, short x1, short y1, short x2, short y2, short a)
+static void drawscredge_area_draw(int sizex, int sizey, int x1, int y1, int x2, int y2, int a)
{
/* right border area */
if (x2 < sizex - 1)
@@ -1058,7 +1059,7 @@ bScreen *ED_screen_duplicate(wmWindow *win, bScreen *sc)
{
bScreen *newsc;
- if (sc->full != SCREENNORMAL) return NULL; /* XXX handle this case! */
+ if (sc->state != SCREENNORMAL) return NULL; /* XXX handle this case! */
/* make new empty screen: */
newsc = ED_screen_add(win, sc->scene, sc->id.name + 2);
@@ -1313,7 +1314,8 @@ void ED_screen_exit(bContext *C, wmWindow *window, bScreen *screen)
if (screen->animtimer)
WM_event_remove_timer(wm, window, screen->animtimer);
screen->animtimer = NULL;
-
+ screen->scrubbing = false;
+
if (screen->mainwin)
wm_subwindow_close(window, screen->mainwin);
screen->mainwin = 0;
@@ -1439,7 +1441,7 @@ void ED_screen_set_subwinactive(bContext *C, wmEvent *event)
/* this used to be a notifier, but needs to be done immediate
* because it can undo setting the right button as active due
* to delayed notifier handling */
- uiFreeActiveButtons(C, win->screen);
+ UI_screen_free_active_but(C, win->screen);
}
else
region_cursor_set(win, scr->subwinactive, false);
@@ -1467,25 +1469,26 @@ int ED_screen_area_active(const bContext *C)
return 0;
}
-/* operator call, WM + Window + screen already existed before */
-/* Do NOT call in area/region queues! */
-void ED_screen_set(bContext *C, bScreen *sc)
+/**
+ * operator call, WM + Window + screen already existed before
+ *
+ * \warning Do NOT call in area/region queues!
+ * \returns success.
+ */
+bool ED_screen_set(bContext *C, bScreen *sc)
{
Main *bmain = CTX_data_main(C);
wmWindowManager *wm = CTX_wm_manager(C);
wmWindow *win = CTX_wm_window(C);
bScreen *oldscreen = CTX_wm_screen(C);
- ID *id;
/* validate screen, it's called with notifier reference */
- for (id = bmain->screen.first; id; id = id->next)
- if (sc == (bScreen *)id)
- break;
- if (id == NULL)
- return;
-
+ if (BLI_findindex(&bmain->screen, sc) == -1) {
+ return true;
+ }
- if (sc->full) { /* find associated full */
+ if (ELEM(sc->state, SCREENMAXIMIZED, SCREENFULL)) {
+ /* find associated full */
bScreen *sc1;
for (sc1 = bmain->screen.first; sc1; sc1 = sc1->id.next) {
ScrArea *sa = sc1->areabase.first;
@@ -1497,8 +1500,9 @@ void ED_screen_set(bContext *C, bScreen *sc)
}
/* check for valid winid */
- if (sc->winid != 0 && sc->winid != win->winid)
- return;
+ if (sc->winid != 0 && sc->winid != win->winid) {
+ return false;
+ }
if (oldscreen != sc) {
wmTimer *wt = oldscreen->animtimer;
@@ -1558,60 +1562,75 @@ void ED_screen_set(bContext *C, bScreen *sc)
}
/* Always do visible update since it's possible new screen will
- * have different layers visible in 3D viewpots. This is possible
- * because of view3d.lock_camera_and_layers option.
+ * have different layers visible in 3D view-ports.
+ * This is possible because of view3d.lock_camera_and_layers option.
*/
DAG_on_visible_update(bmain, false);
}
+
+ return true;
}
-static int ed_screen_used(wmWindowManager *wm, bScreen *sc)
+static bool ed_screen_used(wmWindowManager *wm, bScreen *sc)
{
wmWindow *win;
- for (win = wm->windows.first; win; win = win->next)
- if (win->screen == sc)
- return 1;
-
- return 0;
+ for (win = wm->windows.first; win; win = win->next) {
+ if (win->screen == sc) {
+ return true;
+ }
+
+ if (ELEM(win->screen->state, SCREENMAXIMIZED, SCREENFULL)) {
+ ScrArea *sa = win->screen->areabase.first;
+ if (sa->full == sc) {
+ return true;
+ }
+ }
+ }
+
+ return false;
}
/* only call outside of area/region loops */
-void ED_screen_delete(bContext *C, bScreen *sc)
+bool ED_screen_delete(bContext *C, bScreen *sc)
{
Main *bmain = CTX_data_main(C);
wmWindowManager *wm = CTX_wm_manager(C);
wmWindow *win = CTX_wm_window(C);
bScreen *newsc;
- int delete = 1;
/* don't allow deleting temp fullscreens for now */
- if (sc->full == SCREENFULL) {
- return;
+ if (ELEM(sc->state, SCREENMAXIMIZED, SCREENFULL)) {
+ return false;
}
-
-
+
/* screen can only be in use by one window at a time, so as
* long as we are able to find a screen that is unused, we
* can safely assume ours is not in use anywhere an delete it */
for (newsc = sc->id.prev; newsc; newsc = newsc->id.prev)
- if (!ed_screen_used(wm, newsc))
+ if (!ed_screen_used(wm, newsc) && !newsc->temp)
break;
if (!newsc) {
for (newsc = sc->id.next; newsc; newsc = newsc->id.next)
- if (!ed_screen_used(wm, newsc))
+ if (!ed_screen_used(wm, newsc) && !newsc->temp)
break;
}
- if (!newsc)
- return;
+ if (!newsc) {
+ return false;
+ }
ED_screen_set(C, newsc);
- if (delete && win->screen != sc)
+ if (win->screen != sc) {
BKE_libblock_free(bmain, sc);
+ return true;
+ }
+ else {
+ return false;
+ }
}
static void ed_screen_set_3dview_camera(Scene *scene, bScreen *sc, ScrArea *sa, View3D *v3d)
@@ -1705,8 +1724,11 @@ void ED_screen_set_scene(bContext *C, bScreen *screen, Scene *scene)
}
-/* only call outside of area/region loops */
-void ED_screen_delete_scene(bContext *C, Scene *scene)
+/**
+ * \note Only call outside of area/region loops
+ * \return true if successful
+ */
+bool ED_screen_delete_scene(bContext *C, Scene *scene)
{
Main *bmain = CTX_data_main(C);
Scene *newscene;
@@ -1716,11 +1738,13 @@ void ED_screen_delete_scene(bContext *C, Scene *scene)
else if (scene->id.next)
newscene = scene->id.next;
else
- return;
+ return false;
ED_screen_set_scene(C, CTX_wm_screen(C), newscene);
BKE_scene_unlink(bmain, scene, newscene);
+
+ return true;
}
ScrArea *ED_screen_full_newspace(bContext *C, ScrArea *sa, int type)
@@ -1730,11 +1754,11 @@ ScrArea *ED_screen_full_newspace(bContext *C, ScrArea *sa, int type)
ScrArea *newsa = NULL;
if (!sa || sa->full == NULL) {
- newsa = ED_screen_full_toggle(C, win, sa);
+ newsa = ED_screen_state_toggle(C, win, sa, SCREENMAXIMIZED);
}
if (!newsa) {
- if (sa->full) {
+ if (sa->full && (screen->state == SCREENMAXIMIZED)) {
/* if this has been called from the temporary info header generated in
* temp fullscreen layouts, find the correct fullscreen area to change
* to create a new space inside */
@@ -1747,20 +1771,54 @@ ScrArea *ED_screen_full_newspace(bContext *C, ScrArea *sa, int type)
newsa = sa;
}
}
-
+
+ BLI_assert(newsa);
+
+ if (sa && (sa->spacetype != type)) {
+ newsa->flag |= AREA_FLAG_TEMP_TYPE;
+ }
+ else {
+ newsa->flag &= ~AREA_FLAG_TEMP_TYPE;
+ }
+
ED_area_newspace(C, newsa, type);
return newsa;
}
-void ED_screen_full_prevspace(bContext *C, ScrArea *sa)
+/**
+ * \a was_prev_temp for the case previous space was a temporary fullscreen as well
+ */
+void ED_screen_full_prevspace(bContext *C, ScrArea *sa, const bool was_prev_temp)
{
- wmWindow *win = CTX_wm_window(C);
+ BLI_assert(sa->full);
+
+ if (sa->flag & AREA_FLAG_STACKED_FULLSCREEN) {
+ /* stacked fullscreen -> only go back to previous screen and don't toggle out of fullscreen */
+ ED_area_prevspace(C, sa);
+ /* only clear if previous space wasn't a temp fullscreen as well */
+ if (!was_prev_temp) {
+ sa->flag &= ~AREA_FLAG_TEMP_TYPE;
+ }
+ }
+ else {
+ ED_screen_restore_temp_type(C, sa);
+ }
+}
- ED_area_prevspace(C, sa);
-
- if (sa->full)
- ED_screen_full_toggle(C, win, sa);
+void ED_screen_restore_temp_type(bContext *C, ScrArea *sa)
+{
+ /* incase nether functions below run */
+ ED_area_tag_redraw(sa);
+
+ if (sa->flag & AREA_FLAG_TEMP_TYPE) {
+ ED_area_prevspace(C, sa);
+ sa->flag &= ~AREA_FLAG_TEMP_TYPE;
+ }
+
+ if (sa->full) {
+ ED_screen_state_toggle(C, CTX_wm_window(C), sa, SCREENMAXIMIZED);
+ }
}
/* restore a screen / area back to default operation, after temp fullscreen modes */
@@ -1768,40 +1826,33 @@ void ED_screen_full_restore(bContext *C, ScrArea *sa)
{
wmWindow *win = CTX_wm_window(C);
SpaceLink *sl = sa->spacedata.first;
+ bScreen *screen = CTX_wm_screen(C);
+ short state = (screen ? screen->state : SCREENMAXIMIZED);
- /* if fullscreen area has a secondary space (such as a file browser or fullscreen render
- * overlaid on top of a existing setup) then return to the previous space */
+ /* if fullscreen area has a temporary space (such as a file browser or fullscreen render
+ * overlaid on top of an existing setup) then return to the previous space */
if (sl->next) {
- /* specific checks for space types */
-
- /* Special check added for non-render image window (back from fullscreen through "Back to Previous" button) */
- if (sl->spacetype == SPACE_IMAGE) {
- SpaceImage *sima = sa->spacedata.first;
-
- if (sima->flag & (SI_PREVSPACE | SI_FULLWINDOW)) {
- sima->flag &= ~SI_PREVSPACE;
- sima->flag &= ~SI_FULLWINDOW;
- ED_screen_full_prevspace(C, sa);
- }
- else
- ED_screen_full_toggle(C, win, sa);
- }
- else if (sl->spacetype == SPACE_FILE) {
- ED_screen_full_prevspace(C, sa);
+ if (sa->flag & AREA_FLAG_TEMP_TYPE) {
+ ED_screen_full_prevspace(C, sa, false);
}
else {
- ED_screen_full_toggle(C, win, sa);
+ ED_screen_state_toggle(C, win, sa, state);
}
+ /* warning: 'sa' may be freed */
}
/* otherwise just tile the area again */
else {
- ED_screen_full_toggle(C, win, sa);
+ ED_screen_state_toggle(C, win, sa, state);
}
}
-/* this function toggles: if area is full then the parent will be restored */
-ScrArea *ED_screen_full_toggle(bContext *C, wmWindow *win, ScrArea *sa)
+/**
+ * this function toggles: if area is maximized/full then the parent will be restored
+ *
+ * \warning \a sa may be freed.
+ */
+ScrArea *ED_screen_state_toggle(bContext *C, wmWindow *win, ScrArea *sa, const short state)
{
bScreen *sc, *oldscreen;
ARegion *ar;
@@ -1811,24 +1862,21 @@ ScrArea *ED_screen_full_toggle(bContext *C, wmWindow *win, ScrArea *sa)
* switching screens with tooltip open because region and tooltip
* are no longer in the same screen */
for (ar = sa->regionbase.first; ar; ar = ar->next)
- uiFreeBlocks(C, &ar->uiblocks);
-
+ UI_blocklist_free(C, &ar->uiblocks);
+
/* prevent hanging header prints */
ED_area_headerprint(sa, NULL);
}
if (sa && sa->full) {
+ /* restoring back to SCREENNORMAL */
ScrArea *old;
- /*short fulltype;*/ /*UNUSED*/
sc = sa->full; /* the old screen to restore */
oldscreen = win->screen; /* the one disappearing */
- /*fulltype = sc->full;*/
- sc->full = 0;
+ sc->state = SCREENNORMAL;
- /* removed: SCREENAUTOPLAY exception here */
-
/* find old area */
for (old = sc->areabase.first; old; old = old->next)
if (old->full) break;
@@ -1838,6 +1886,13 @@ ScrArea *ED_screen_full_toggle(bContext *C, wmWindow *win, ScrArea *sa)
return NULL;
}
+ if (state == SCREENFULL) {
+ /* restore the old side panels/header visibility */
+ for (ar = sa->regionbase.first; ar; ar = ar->next) {
+ ar->flag = ar->flagfullscreen;
+ }
+ }
+
ED_area_data_swap(old, sa);
if (sa->flag & AREA_TEMP_INFO) sa->flag &= ~AREA_TEMP_INFO;
old->full = NULL;
@@ -1851,46 +1906,74 @@ ScrArea *ED_screen_full_toggle(bContext *C, wmWindow *win, ScrArea *sa)
BKE_screen_free(oldscreen);
BKE_libblock_free(CTX_data_main(C), oldscreen);
+ /* After we've restored back to SCREENNORMAL, we have to wait with
+ * screen handling as it uses the area coords which aren't updated yet.
+ * Without doing so, the screen handling gets wrong area coords,
+ * which in worst case can lead to crashes (see T43139) */
+ sc->skip_handling = true;
}
else {
+ /* change from SCREENNORMAL to new state */
ScrArea *newa;
char newname[MAX_ID_NAME - 2];
oldscreen = win->screen;
- /* nothing wrong with having only 1 area, as far as I can see...
- * is there only 1 area? */
-#if 0
- if (oldscreen->areabase.first == oldscreen->areabase.last)
- return NULL;
-#endif
-
- oldscreen->full = SCREENFULL;
- BLI_snprintf(newname, sizeof(newname), "%s-%s", oldscreen->id.name + 2, "full");
+ oldscreen->state = state;
+ BLI_snprintf(newname, sizeof(newname), "%s-%s", oldscreen->id.name + 2, "nonnormal");
sc = ED_screen_add(win, oldscreen->scene, newname);
- sc->full = SCREENFULL; // XXX
+ sc->state = state;
+ sc->redraws_flag = oldscreen->redraws_flag;
/* timer */
sc->animtimer = oldscreen->animtimer;
oldscreen->animtimer = NULL;
- /* returns the top small area */
- newa = area_split(sc, (ScrArea *)sc->areabase.first, 'h', 0.99f, 1);
- ED_area_newspace(C, newa, SPACE_INFO);
-
/* use random area when we have no active one, e.g. when the
* mouse is outside of the window and we open a file browser */
if (!sa)
sa = oldscreen->areabase.first;
- /* copy area */
- newa = newa->prev;
- ED_area_data_swap(newa, sa);
- sa->flag |= AREA_TEMP_INFO;
+ if (state == SCREENMAXIMIZED) {
+ /* returns the top small area */
+ newa = area_split(sc, (ScrArea *)sc->areabase.first, 'h', 0.99f, 1);
+ ED_area_newspace(C, newa, SPACE_INFO);
+
+ /* copy area */
+ newa = newa->prev;
+ ED_area_data_swap(newa, sa);
+ sa->flag |= AREA_TEMP_INFO;
+
+ sa->full = oldscreen;
+ newa->full = oldscreen;
+ newa->next->full = oldscreen; // XXX
+ }
+ else if (state == SCREENFULL) {
+ newa = (ScrArea *)sc->areabase.first;
+
+ /* copy area */
+ ED_area_data_swap(newa, sa);
+ newa->flag = sa->flag; /* mostly for AREA_FLAG_WASFULLSCREEN */
+
+ /* temporarily hide the side panels/header */
+ for (ar = newa->regionbase.first; ar; ar = ar->next) {
+ ar->flagfullscreen = ar->flag;
+
+ if (ELEM(ar->regiontype,
+ RGN_TYPE_UI,
+ RGN_TYPE_HEADER,
+ RGN_TYPE_TOOLS))
+ {
+ ar->flag |= RGN_FLAG_HIDDEN;
+ }
+ }
- sa->full = oldscreen;
- newa->full = oldscreen;
- newa->next->full = oldscreen; // XXX
+ sa->full = oldscreen;
+ newa->full = oldscreen;
+ }
+ else {
+ BLI_assert(false);
+ }
ED_screen_set(C, sc);
}
@@ -2049,7 +2132,7 @@ void ED_update_for_newframe(Main *bmain, Scene *scene, int UNUSED(mute))
/* this function applies the changes too */
BKE_scene_update_for_newframe(bmain->eval_ctx, bmain, scene, layers);
- //if ( (CFRA>1) && (!mute) && (scene->r.audio.flag & AUDIO_SCRUB))
+ //if ((CFRA > 1) && (!mute) && (scene->r.audio.flag & AUDIO_SCRUB))
// audiostream_scrub( CFRA );
/* 3d window, preview */
@@ -2073,4 +2156,85 @@ void ED_update_for_newframe(Main *bmain, Scene *scene, int UNUSED(mute))
}
+/*
+ * return true if any active area requires to see in 3D
+ */
+bool ED_screen_stereo3d_required(bScreen *screen)
+{
+ ScrArea *sa;
+ Scene *sce = screen->scene;
+ const bool is_multiview = (sce->r.scemode & R_MULTIVIEW) != 0;
+
+ for (sa = screen->areabase.first; sa; sa = sa->next) {
+ switch (sa->spacetype) {
+ case SPACE_VIEW3D:
+ {
+ View3D *v3d;
+
+ if (!is_multiview)
+ continue;
+
+ v3d = sa->spacedata.first;
+ if (v3d->camera && v3d->stereo3d_camera == STEREO_3D_ID) {
+ ARegion *ar;
+ for (ar = sa->regionbase.first; ar; ar = ar->next) {
+ if (ar->regiondata && ar->regiontype == RGN_TYPE_WINDOW) {
+ RegionView3D *rv3d = ar->regiondata;
+ if (rv3d->persp == RV3D_CAMOB) {
+ return true;
+ }
+ }
+ }
+ }
+ break;
+ }
+ case SPACE_IMAGE:
+ {
+ SpaceImage *sima;
+
+ /* images should always show in stereo, even if
+ * the file doesn't have views enabled */
+ sima = sa->spacedata.first;
+ if (sima->image && (sima->image->flag & IMA_IS_STEREO) &&
+ (sima->iuser.flag & IMA_SHOW_STEREO))
+ {
+ return true;
+ }
+ break;
+ }
+ case SPACE_NODE:
+ {
+ SpaceNode *snode;
+
+ if (!is_multiview)
+ continue;
+
+ snode = sa->spacedata.first;
+ if ((snode->flag & SNODE_BACKDRAW) && ED_node_is_compositor(snode)) {
+ return true;
+ }
+ break;
+ }
+ case SPACE_SEQ:
+ {
+ SpaceSeq *sseq;
+
+ if (!is_multiview)
+ continue;
+
+ sseq = sa->spacedata.first;
+ if (ELEM(sseq->view, SEQ_VIEW_PREVIEW, SEQ_VIEW_SEQUENCE_PREVIEW)) {
+ return true;
+ }
+
+ if (sseq->draw_flag & SEQ_DRAW_BACKDROP) {
+ return true;
+ }
+ break;
+ }
+ }
+ }
+
+ return false;
+}
diff --git a/source/blender/editors/screen/screen_intern.h b/source/blender/editors/screen/screen_intern.h
index 9e0421b6e99..ccb6d5a6dca 100644
--- a/source/blender/editors/screen/screen_intern.h
+++ b/source/blender/editors/screen/screen_intern.h
@@ -32,10 +32,10 @@
#define __SCREEN_INTERN_H__
/* internal exports only */
-struct wmWindow;
-struct Scene;
#define AZONESPOT (0.6f * U.widget_unit)
+#define AZONEFADEIN (5.0f * U.widget_unit) /* when azone is totally visible */
+#define AZONEFADEOUT (6.5f * U.widget_unit) /* when we start seeing the azone */
/* area.c */
void ED_area_data_copy(ScrArea *sa_dst, ScrArea *sa_src, const bool do_free);
diff --git a/source/blender/editors/screen/screen_ops.c b/source/blender/editors/screen/screen_ops.c
index 7c7574b3af3..4a1c1e34414 100644
--- a/source/blender/editors/screen/screen_ops.c
+++ b/source/blender/editors/screen/screen_ops.c
@@ -37,12 +37,13 @@
#include "BLI_dlrbTree.h"
#include "BLI_utildefines.h"
-#include "BLF_translation.h"
+#include "BLT_translation.h"
#include "DNA_armature_types.h"
#include "DNA_lattice_types.h"
#include "DNA_object_types.h"
#include "DNA_curve_types.h"
+#include "DNA_gpencil_types.h"
#include "DNA_scene_types.h"
#include "DNA_meta_types.h"
#include "DNA_mask_types.h"
@@ -80,8 +81,7 @@
#include "UI_interface.h"
#include "UI_resources.h"
-
-#include "wm_window.h"
+#include "UI_view2d.h"
#include "screen_intern.h" /* own module include */
@@ -129,13 +129,31 @@ static int screen_active_editable(bContext *C)
{
if (ED_operator_screenactive(C)) {
/* no full window splitting allowed */
- if (CTX_wm_screen(C)->full != SCREENNORMAL)
+ if (CTX_wm_screen(C)->state != SCREENNORMAL)
return 0;
return 1;
}
return 0;
}
+static ARegion *screen_find_region_type(bContext *C, int type)
+{
+ ARegion *ar = CTX_wm_region(C);
+
+ /* find the header region
+ * - try context first, but upon failing, search all regions in area...
+ */
+ if ((ar == NULL) || (ar->regiontype != type)) {
+ ScrArea *sa = CTX_wm_area(C);
+ ar = BKE_area_find_region_type(sa, type);
+ }
+ else {
+ ar = NULL;
+ }
+
+ return ar;
+}
+
/* when mouse is over area-edge */
int ED_operator_screen_mainwinactive(bContext *C)
{
@@ -374,7 +392,7 @@ int ED_operator_editarmature(bContext *C)
* \brief check for pose mode (no mixed modes)
*
* We want to enable most pose operations in weight paint mode,
- * when it comes to transforming bones, but managing bomes layers/groups
+ * when it comes to transforming bones, but managing bones layers/groups
* can be left for pose mode only. (not weight paint mode)
*/
int ED_operator_posemode_exclusive(bContext *C)
@@ -394,7 +412,7 @@ int ED_operator_posemode_exclusive(bContext *C)
}
/* allows for pinned pose objects to be used in the object buttons
- * and the the non-active pose object to be used in the 3D view */
+ * and the non-active pose object to be used in the 3D view */
int ED_operator_posemode_context(bContext *C)
{
Object *obpose = ED_pose_object_from_context(C);
@@ -581,19 +599,6 @@ typedef struct sActionzoneData {
int x, y, gesture_dir, modifier;
} sActionzoneData;
-/* used by other operators too */
-static ScrArea *screen_areahascursor(bScreen *scr, int x, int y)
-{
- ScrArea *sa = NULL;
- sa = scr->areabase.first;
- while (sa) {
- if (BLI_rcti_isect_pt(&sa->totrct, x, y)) break;
- sa = sa->next;
- }
-
- return sa;
-}
-
/* quick poll to save operators to be created and handled */
static int actionzone_area_poll(bContext *C)
{
@@ -611,6 +616,24 @@ static int actionzone_area_poll(bContext *C)
return 0;
}
+/* the debug drawing of the click_rect is in area_draw_azone_fullscreen, keep both in sync */
+static void fullscreen_click_rcti_init(rcti *rect, const short x1, const short y1, const short x2, const short y2)
+{
+ int x = x2 - ((float) x2 - x1) * 0.5f / UI_DPI_FAC;
+ int y = y2 - ((float) y2 - y1) * 0.5f / UI_DPI_FAC;
+ float icon_size = UI_DPI_ICON_SIZE + 7 * UI_DPI_FAC;
+
+ /* adjust the icon distance from the corner */
+ x += 36.0f / UI_DPI_FAC;
+ y += 36.0f / UI_DPI_FAC;
+
+ /* draws from the left bottom corner of the icon */
+ x -= UI_DPI_ICON_SIZE;
+ y -= UI_DPI_ICON_SIZE;
+
+ BLI_rcti_init(rect, x, x + icon_size, y, y + icon_size);
+}
+
AZone *is_in_area_actionzone(ScrArea *sa, const int xy[2])
{
AZone *az = NULL;
@@ -627,6 +650,42 @@ AZone *is_in_area_actionzone(ScrArea *sa, const int xy[2])
else if (az->type == AZONE_REGION) {
break;
}
+ else if (az->type == AZONE_FULLSCREEN) {
+ int mouse_radius, spot_radius, fadein_radius, fadeout_radius;
+ rcti click_rect;
+
+ fullscreen_click_rcti_init(&click_rect, az->x1, az->y1, az->x2, az->y2);
+
+ if (BLI_rcti_isect_pt_v(&click_rect, xy)) {
+ az->alpha = 1.0f;
+ }
+ else {
+ mouse_radius = (xy[0] - az->x2) * (xy[0] - az->x2) + (xy[1] - az->y2) * (xy[1] - az->y2);
+ spot_radius = AZONESPOT * AZONESPOT;
+ fadein_radius = AZONEFADEIN * AZONEFADEIN;
+ fadeout_radius = AZONEFADEOUT * AZONEFADEOUT;
+
+ if (mouse_radius < spot_radius) {
+ az->alpha = 1.0f;
+ }
+ else if (mouse_radius < fadein_radius) {
+ az->alpha = 1.0f;
+ }
+ else if (mouse_radius < fadeout_radius) {
+ az->alpha = 1.0f - ((float)(mouse_radius - fadein_radius)) / ((float)(fadeout_radius - fadein_radius));
+ }
+ else {
+ az->alpha = 0.0f;
+ }
+
+ /* fade in/out but no click */
+ az = NULL;
+ }
+
+ /* XXX force redraw to show/hide the action zone */
+ ED_area_tag_redraw(sa);
+ break;
+ }
}
}
@@ -654,9 +713,12 @@ static void actionzone_apply(bContext *C, wmOperator *op, int type)
if (type == AZONE_AREA)
event.type = EVT_ACTIONZONE_AREA;
+ else if (type == AZONE_FULLSCREEN)
+ event.type = EVT_ACTIONZONE_FULLSCREEN;
else
event.type = EVT_ACTIONZONE_REGION;
- event.val = 0;
+
+ event.val = KM_NOTHING;
event.customdata = op->customdata;
event.customdatafree = true;
op->customdata = NULL;
@@ -666,7 +728,8 @@ static void actionzone_apply(bContext *C, wmOperator *op, int type)
static int actionzone_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- AZone *az = is_in_area_actionzone(CTX_wm_area(C), &event->x);
+ ScrArea *sa = CTX_wm_area(C);
+ AZone *az = is_in_area_actionzone(sa, &event->x);
sActionzoneData *sad;
/* quick escape */
@@ -675,13 +738,13 @@ static int actionzone_invoke(bContext *C, wmOperator *op, const wmEvent *event)
/* ok we do the actionzone */
sad = op->customdata = MEM_callocN(sizeof(sActionzoneData), "sActionzoneData");
- sad->sa1 = CTX_wm_area(C);
+ sad->sa1 = sa;
sad->az = az;
sad->x = event->x; sad->y = event->y;
/* region azone directly reacts on mouse clicks */
- if (sad->az->type == AZONE_REGION) {
- actionzone_apply(C, op, AZONE_REGION);
+ if (ELEM(sad->az->type, AZONE_REGION, AZONE_FULLSCREEN)) {
+ actionzone_apply(C, op, sad->az->type);
actionzone_exit(op);
return OPERATOR_FINISHED;
}
@@ -734,7 +797,7 @@ static int actionzone_modal(bContext *C, wmOperator *op, const wmEvent *event)
/* gesture is large enough? */
if (is_gesture) {
/* second area, for join when (sa1 != sa2) */
- sad->sa2 = screen_areahascursor(sc, event->x, event->y);
+ sad->sa2 = BKE_screen_find_area_xy(sc, SPACE_TYPE_ANY, event->x, event->y);
/* apply sends event */
actionzone_apply(C, op, sad->az->type);
actionzone_exit(op);
@@ -855,7 +918,7 @@ static int area_swap_modal(bContext *C, wmOperator *op, const wmEvent *event)
switch (event->type) {
case MOUSEMOVE:
/* second area, for join */
- sad->sa2 = screen_areahascursor(CTX_wm_screen(C), event->x, event->y);
+ sad->sa2 = BKE_screen_find_area_xy(CTX_wm_screen(C), SPACE_TYPE_ANY, event->x, event->y);
break;
case LEFTMOUSE: /* release LMB */
if (event->val == KM_RELEASE) {
@@ -929,6 +992,7 @@ static int area_dupli_invoke(bContext *C, wmOperator *op, const wmEvent *event)
rect.ymax = rect.ymin + BLI_rcti_size_y(&rect) / U.pixelsize;
newwin = WM_window_open(C, &rect);
+ *newwin->stereo3d_format = *win->stereo3d_format;
/* allocs new screen and adds to newly created window, using window size */
newsc = ED_screen_add(newwin, CTX_data_scene(C), sc->id.name + 2);
@@ -1462,7 +1526,7 @@ static int area_split_invoke(bContext *C, wmOperator *op, const wmEvent *event)
int dir;
/* no full window splitting allowed */
- if (sc->full != SCREENNORMAL)
+ if (sc->state != SCREENNORMAL)
return OPERATOR_CANCELLED;
if (event->type == EVT_ACTIONZONE_AREA) {
@@ -1605,7 +1669,8 @@ static int area_split_modal(bContext *C, wmOperator *op, const wmEvent *event)
sd->sarea->flag &= ~(AREA_FLAG_DRAWSPLIT_H | AREA_FLAG_DRAWSPLIT_V);
ED_area_tag_redraw(sd->sarea);
}
- sd->sarea = screen_areahascursor(CTX_wm_screen(C), event->x, event->y); /* area context not set */
+ /* area context not set */
+ sd->sarea = BKE_screen_find_area_xy(CTX_wm_screen(C), SPACE_TYPE_ANY, event->x, event->y);
if (sd->sarea) {
ED_area_tag_redraw(sd->sarea);
@@ -1866,6 +1931,12 @@ static void region_scale_validate_size(RegionMoveData *rmd)
static void region_scale_toggle_hidden(bContext *C, RegionMoveData *rmd)
{
+ /* hidden areas may have bad 'View2D.cur' value,
+ * correct before displaying. see T45156 */
+ if (rmd->ar->flag & RGN_FLAG_HIDDEN) {
+ UI_view2d_curRect_validate(&rmd->ar->v2d);
+ }
+
region_toggle_hidden(C, rmd->ar, 0);
region_scale_validate_size(rmd);
}
@@ -1980,6 +2051,48 @@ static void SCREEN_OT_region_scale(wmOperatorType *ot)
/* ************** frame change operator ***************************** */
+static void areas_do_frame_follow(bContext *C, bool middle)
+{
+ bScreen *scr = CTX_wm_screen(C);
+ Scene *scene = CTX_data_scene(C);
+ wmWindowManager *wm = CTX_wm_manager(C);
+ wmWindow *window;
+ for (window = wm->windows.first; window; window = window->next) {
+ ScrArea *sa;
+ for (sa = window->screen->areabase.first; sa; sa = sa->next) {
+ ARegion *ar;
+ for (ar = sa->regionbase.first; ar; ar = ar->next) {
+ /* do follow here if editor type supports it */
+ if ((scr->redraws_flag & TIME_FOLLOW)) {
+ if ((ar->regiontype == RGN_TYPE_WINDOW &&
+ ELEM(sa->spacetype, SPACE_SEQ, SPACE_TIME, SPACE_IPO, SPACE_ACTION, SPACE_NLA)) ||
+ (sa->spacetype == SPACE_CLIP && ar->regiontype == RGN_TYPE_PREVIEW))
+ {
+ float w = BLI_rctf_size_x(&ar->v2d.cur);
+
+ if (middle) {
+ if ((scene->r.cfra < ar->v2d.cur.xmin) || (scene->r.cfra > ar->v2d.cur.xmax)) {
+ ar->v2d.cur.xmax = scene->r.cfra + (w / 2);
+ ar->v2d.cur.xmin = scene->r.cfra - (w / 2);
+ }
+ }
+ else {
+ if (scene->r.cfra < ar->v2d.cur.xmin) {
+ ar->v2d.cur.xmax = scene->r.cfra;
+ ar->v2d.cur.xmin = ar->v2d.cur.xmax - w;
+ }
+ else if (scene->r.cfra > ar->v2d.cur.xmax) {
+ ar->v2d.cur.xmin = scene->r.cfra;
+ ar->v2d.cur.xmax = ar->v2d.cur.xmin + w;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
/* function to be called outside UI context, or for redo */
static int frame_offset_exec(bContext *C, wmOperator *op)
{
@@ -1993,7 +2106,9 @@ static int frame_offset_exec(bContext *C, wmOperator *op)
FRAMENUMBER_MIN_CLAMP(CFRA);
SUBFRA = 0.f;
- sound_seek_scene(bmain, scene);
+ areas_do_frame_follow(C, false);
+
+ BKE_sound_seek_scene(bmain, scene);
WM_event_add_notifier(C, NC_SCENE | ND_FRAME, scene);
@@ -2043,7 +2158,9 @@ static int frame_jump_exec(bContext *C, wmOperator *op)
else
CFRA = PSFRA;
- sound_seek_scene(bmain, scene);
+ areas_do_frame_follow(C, true);
+
+ BKE_sound_seek_scene(bmain, scene);
WM_event_add_notifier(C, NC_SCENE | ND_FRAME, scene);
}
@@ -2075,6 +2192,7 @@ static int keyframe_jump_exec(bContext *C, wmOperator *op)
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
Object *ob = CTX_data_active_object(C);
+ bGPdata *gpd = CTX_data_gpencil_data(C);
bDopeSheet ads = {NULL};
DLRBT_Tree keys;
ActKeyColumn *ak;
@@ -2102,7 +2220,9 @@ static int keyframe_jump_exec(bContext *C, wmOperator *op)
if (ob)
ob_to_keylist(&ads, ob, &keys, NULL);
-
+
+ gpencil_to_keylist(&ads, gpd, &keys);
+
{
Mask *mask = CTX_data_edit_mask(C);
if (mask) {
@@ -2144,7 +2264,9 @@ static int keyframe_jump_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
else {
- sound_seek_scene(bmain, scene);
+ areas_do_frame_follow(C, true);
+
+ BKE_sound_seek_scene(bmain, scene);
WM_event_add_notifier(C, NC_SCENE | ND_FRAME, scene);
@@ -2204,7 +2326,9 @@ static int marker_jump_exec(bContext *C, wmOperator *op)
else {
CFRA = closest;
- sound_seek_scene(bmain, scene);
+ areas_do_frame_follow(C, true);
+
+ BKE_sound_seek_scene(bmain, scene);
WM_event_add_notifier(C, NC_SCENE | ND_FRAME, scene);
@@ -2231,8 +2355,11 @@ static void SCREEN_OT_marker_jump(wmOperatorType *ot)
static bool screen_set_is_ok(bScreen *screen, bScreen *screen_prev)
{
- return ((screen->winid == 0) &&
- (screen->full == 0) &&
+ return ((screen->winid == 0) &&
+ /* in typical usage these should have a nonzero winid
+ * (all temp screens should be used, or closed & freed). */
+ (screen->temp == false) &&
+ (screen->state == SCREENNORMAL) &&
(screen != screen_prev) &&
(screen->id.name[2] != '.' || !(U.uiflag & USER_HIDE_DOT)));
}
@@ -2245,12 +2372,13 @@ static int screen_set_exec(bContext *C, wmOperator *op)
bScreen *screen_prev = screen;
ScrArea *sa = CTX_wm_area(C);
- int tot = BLI_countlist(&bmain->screen);
+ int tot = BLI_listbase_count(&bmain->screen);
int delta = RNA_int_get(op->ptr, "delta");
/* temp screens are for userpref or render display */
- if (screen->temp)
+ if (screen->temp || (sa && sa->full && sa->full->temp)) {
return OPERATOR_CANCELLED;
+ }
if (delta == 1) {
while (tot--) {
@@ -2303,10 +2431,11 @@ static void SCREEN_OT_screen_set(wmOperatorType *ot)
/* function to be called outside UI context, or for redo */
-static int screen_full_area_exec(bContext *C, wmOperator *UNUSED(op))
+static int screen_maximize_area_exec(bContext *C, wmOperator *op)
{
bScreen *screen = CTX_wm_screen(C);
ScrArea *sa = NULL;
+ const bool hide_panels = RNA_boolean_get(op->ptr, "use_hide_panels");
/* search current screen for 'fullscreen' areas */
/* prevents restoring info header, when mouse is over it */
@@ -2314,25 +2443,41 @@ static int screen_full_area_exec(bContext *C, wmOperator *UNUSED(op))
if (sa->full) break;
}
- if (sa == NULL) sa = CTX_wm_area(C);
+ if (sa == NULL) {
+ sa = CTX_wm_area(C);
+ }
- ED_screen_full_toggle(C, CTX_wm_window(C), sa);
+ if (hide_panels) {
+ if (!ELEM(screen->state, SCREENNORMAL, SCREENFULL)) {
+ return OPERATOR_CANCELLED;
+ }
+ ED_screen_state_toggle(C, CTX_wm_window(C), sa, SCREENFULL);
+ }
+ else {
+ if (!ELEM(screen->state, SCREENNORMAL, SCREENMAXIMIZED)) {
+ return OPERATOR_CANCELLED;
+ }
+ ED_screen_state_toggle(C, CTX_wm_window(C), sa, SCREENMAXIMIZED);
+ }
+
return OPERATOR_FINISHED;
}
static void SCREEN_OT_screen_full_area(wmOperatorType *ot)
{
- ot->name = "Toggle Full Screen";
- ot->description = "Toggle display selected area as fullscreen";
+ PropertyRNA *prop;
+
+ ot->name = "Toggle Fullscreen Area";
+ ot->description = "Toggle display selected area as fullscreen/maximized";
ot->idname = "SCREEN_OT_screen_full_area";
- ot->exec = screen_full_area_exec;
+ ot->exec = screen_maximize_area_exec;
ot->poll = ED_operator_areaactive;
ot->flag = 0;
-
-}
-
+ prop = RNA_def_boolean(ot->srna, "use_hide_panels", false, "Hide Panels", "Hide all the panels");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+}
/* ************** join area operator ********************************************** */
@@ -2388,8 +2533,8 @@ static int area_join_init(bContext *C, wmOperator *op)
x2 = RNA_int_get(op->ptr, "max_x");
y2 = RNA_int_get(op->ptr, "max_y");
- sa1 = screen_areahascursor(CTX_wm_screen(C), x1, y1);
- sa2 = screen_areahascursor(CTX_wm_screen(C), x2, y2);
+ sa1 = BKE_screen_find_area_xy(CTX_wm_screen(C), SPACE_TYPE_ANY, x1, y1);
+ sa2 = BKE_screen_find_area_xy(CTX_wm_screen(C), SPACE_TYPE_ANY, x2, y2);
if (sa1 == NULL || sa2 == NULL || sa1 == sa2)
return 0;
@@ -2522,7 +2667,7 @@ static int area_join_modal(bContext *C, wmOperator *op, const wmEvent *event)
case MOUSEMOVE:
{
- ScrArea *sa = screen_areahascursor(sc, event->x, event->y);
+ ScrArea *sa = BKE_screen_find_area_xy(sc, SPACE_TYPE_ANY, event->x, event->y);
int dir;
if (sa) {
@@ -2645,8 +2790,8 @@ static int screen_area_options_invoke(bContext *C, wmOperator *op, const wmEvent
if (actedge == NULL) return OPERATOR_CANCELLED;
- pup = uiPupMenuBegin(C, RNA_struct_ui_name(op->type->srna), ICON_NONE);
- layout = uiPupMenuLayout(pup);
+ pup = UI_popup_menu_begin(C, RNA_struct_ui_name(op->type->srna), ICON_NONE);
+ layout = UI_popup_menu_layout(pup);
WM_operator_properties_create(&ptr1, "SCREEN_OT_area_join");
@@ -2665,9 +2810,9 @@ static int screen_area_options_invoke(bContext *C, wmOperator *op, const wmEvent
uiItemFullO(layout, "SCREEN_OT_area_split", NULL, ICON_NONE, ptr2.data, WM_OP_INVOKE_DEFAULT, 0);
uiItemFullO(layout, "SCREEN_OT_area_join", NULL, ICON_NONE, ptr1.data, WM_OP_INVOKE_DEFAULT, 0);
- uiPupMenuEnd(C, pup);
+ UI_popup_menu_end(C, pup);
- return OPERATOR_CANCELLED;
+ return OPERATOR_INTERFACE;
}
static void SCREEN_OT_area_options(wmOperatorType *ot)
@@ -2703,7 +2848,7 @@ static int spacedata_cleanup_exec(bContext *C, wmOperator *op)
SpaceLink *sl = sa->spacedata.first;
BLI_remlink(&sa->spacedata, sl);
- tot += BLI_countlist(&sa->spacedata);
+ tot += BLI_listbase_count(&sa->spacedata);
BKE_spacedata_freelist(&sa->spacedata);
BLI_addtail(&sa->spacedata, sl);
}
@@ -2761,20 +2906,20 @@ static int repeat_history_invoke(bContext *C, wmOperator *op, const wmEvent *UNU
uiLayout *layout;
int items, i;
- items = BLI_countlist(&wm->operators);
+ items = BLI_listbase_count(&wm->operators);
if (items == 0)
return OPERATOR_CANCELLED;
- pup = uiPupMenuBegin(C, RNA_struct_ui_name(op->type->srna), ICON_NONE);
- layout = uiPupMenuLayout(pup);
+ pup = UI_popup_menu_begin(C, RNA_struct_ui_name(op->type->srna), ICON_NONE);
+ layout = UI_popup_menu_layout(pup);
for (i = items - 1, lastop = wm->operators.last; lastop; lastop = lastop->prev, i--)
if (WM_operator_repeat_check(C, lastop))
uiItemIntO(layout, RNA_struct_ui_name(lastop->type->srna), ICON_NONE, op->type->idname, "index", i);
- uiPupMenuEnd(C, pup);
+ UI_popup_menu_end(C, pup);
- return OPERATOR_CANCELLED;
+ return OPERATOR_INTERFACE;
}
static int repeat_history_exec(bContext *C, wmOperator *op)
@@ -3027,23 +3172,44 @@ static void SCREEN_OT_region_flip(wmOperatorType *ot)
ot->flag = 0;
}
+/* ************** header operator ***************************** */
+static int header_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ ARegion *ar = screen_find_region_type(C, RGN_TYPE_HEADER);
+
+ if (ar == NULL) {
+ return OPERATOR_CANCELLED;
+ }
+
+ ar->flag ^= RGN_FLAG_HIDDEN;
+
+ ED_area_tag_redraw(CTX_wm_area(C));
+
+ WM_event_add_notifier(C, NC_SCREEN | NA_EDITED, NULL);
+
+ return OPERATOR_FINISHED;
+}
+
+static void SCREEN_OT_header(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Header";
+ ot->description = "Display header";
+ ot->idname = "SCREEN_OT_header";
+
+ /* api callbacks */
+ ot->exec = header_exec;
+}
+
/* ************** header flip operator ***************************** */
/* flip a header region alignment */
static int header_flip_exec(bContext *C, wmOperator *UNUSED(op))
{
- ARegion *ar = CTX_wm_region(C);
-
- /* find the header region
- * - try context first, but upon failing, search all regions in area...
- */
- if ((ar == NULL) || (ar->regiontype != RGN_TYPE_HEADER)) {
- ScrArea *sa = CTX_wm_area(C);
- ar = BKE_area_find_region_type(sa, RGN_TYPE_HEADER);
+ ARegion *ar = screen_find_region_type(C, RGN_TYPE_HEADER);
- /* don't do anything if no region */
- if (ar == NULL)
- return OPERATOR_CANCELLED;
+ if (ar == NULL) {
+ return OPERATOR_CANCELLED;
}
/* copied from SCREEN_OT_region_flip */
@@ -3142,14 +3308,14 @@ static int header_toolbox_invoke(bContext *C, wmOperator *UNUSED(op), const wmEv
uiPopupMenu *pup;
uiLayout *layout;
- pup = uiPupMenuBegin(C, IFACE_("Header"), ICON_NONE);
- layout = uiPupMenuLayout(pup);
+ pup = UI_popup_menu_begin(C, IFACE_("Header"), ICON_NONE);
+ layout = UI_popup_menu_layout(pup);
ED_screens_header_tools_menu_create(C, layout, NULL);
- uiPupMenuEnd(C, pup);
+ UI_popup_menu_end(C, pup);
- return OPERATOR_CANCELLED;
+ return OPERATOR_INTERFACE;
}
static void SCREEN_OT_header_toolbox(wmOperatorType *ot)
@@ -3260,10 +3426,17 @@ static int match_region_with_redraws(int spacetype, int regiontype, int redraws)
return 0;
}
+//#define PROFILE_AUDIO_SYNCH
+
static int screen_animation_step(bContext *C, wmOperator *UNUSED(op), const wmEvent *event)
{
bScreen *screen = CTX_wm_screen(C);
+#ifdef PROFILE_AUDIO_SYNCH
+ static int old_frame = 0;
+ int newfra_int;
+#endif
+
if (screen->animtimer && screen->animtimer == event->customdata) {
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
@@ -3282,9 +3455,27 @@ static int screen_animation_step(bContext *C, wmOperator *UNUSED(op), const wmEv
if ((scene->audio.flag & AUDIO_SYNC) &&
(sad->flag & ANIMPLAY_FLAG_REVERSE) == false &&
- finite(time = sound_sync_scene(scene)))
+ finite(time = BKE_sound_sync_scene(scene)))
{
- scene->r.cfra = (double)time * FPS + 0.5;
+ double newfra = (double)time * FPS;
+
+ /* give some space here to avoid jumps */
+ if (newfra + 0.5 > scene->r.cfra && newfra - 0.5 < scene->r.cfra)
+ scene->r.cfra++;
+ else
+ scene->r.cfra = newfra + 0.5;
+
+#ifdef PROFILE_AUDIO_SYNCH
+ newfra_int = scene->r.cfra;
+ if (newfra_int < old_frame) {
+ printf("back jump detected, frame %d!\n", newfra_int);
+ }
+ else if (newfra_int > old_frame + 1) {
+ printf("forward jump detected, frame %d!\n", newfra_int);
+ }
+ fflush(stdout);
+ old_frame = newfra_int;
+#endif
}
else {
if (sync) {
@@ -3351,8 +3542,12 @@ static int screen_animation_step(bContext *C, wmOperator *UNUSED(op), const wmEv
sad->flag |= ANIMPLAY_FLAG_JUMPED;
}
- if (sad->flag & ANIMPLAY_FLAG_JUMPED)
- sound_seek_scene(bmain, scene);
+ if (sad->flag & ANIMPLAY_FLAG_JUMPED) {
+ BKE_sound_seek_scene(bmain, scene);
+#ifdef PROFILE_AUDIO_SYNCH
+ old_frame = CFRA;
+#endif
+ }
/* since we follow drawflags, we can't send notifier but tag regions ourselves */
ED_update_for_newframe(bmain, scene, 1);
@@ -3361,11 +3556,33 @@ static int screen_animation_step(bContext *C, wmOperator *UNUSED(op), const wmEv
for (sa = window->screen->areabase.first; sa; sa = sa->next) {
ARegion *ar;
for (ar = sa->regionbase.first; ar; ar = ar->next) {
+ bool redraw = false;
if (ar == sad->ar) {
- ED_region_tag_redraw(ar);
+ redraw = true;
}
else if (match_region_with_redraws(sa->spacetype, ar->regiontype, sad->redraws)) {
+ redraw = true;
+ }
+
+ if (redraw) {
ED_region_tag_redraw(ar);
+ /* do follow here if editor type supports it */
+ if ((sad->redraws & TIME_FOLLOW)) {
+ if ((ar->regiontype == RGN_TYPE_WINDOW &&
+ ELEM(sa->spacetype, SPACE_SEQ, SPACE_TIME, SPACE_IPO, SPACE_ACTION, SPACE_NLA)) ||
+ (sa->spacetype == SPACE_CLIP && ar->regiontype == RGN_TYPE_PREVIEW))
+ {
+ float w = BLI_rctf_size_x(&ar->v2d.cur);
+ if (scene->r.cfra < ar->v2d.cur.xmin) {
+ ar->v2d.cur.xmax = scene->r.cfra;
+ ar->v2d.cur.xmin = ar->v2d.cur.xmax - w;
+ }
+ else if (scene->r.cfra > ar->v2d.cur.xmax) {
+ ar->v2d.cur.xmin = scene->r.cfra;
+ ar->v2d.cur.xmax = ar->v2d.cur.xmin + w;
+ }
+ }
+ }
}
}
@@ -3410,15 +3627,31 @@ static void SCREEN_OT_animation_step(wmOperatorType *ot)
/* find window that owns the animation timer */
bScreen *ED_screen_animation_playing(const wmWindowManager *wm)
{
- wmWindow *window;
+ wmWindow *win;
+
+ for (win = wm->windows.first; win; win = win->next) {
+ if (win->screen->animtimer || win->screen->scrubbing) {
+ return win->screen;
+ }
+ }
- for (window = wm->windows.first; window; window = window->next)
- if (window->screen->animtimer)
- return window->screen;
-
return NULL;
}
+bScreen *ED_screen_animation_no_scrub(const wmWindowManager *wm)
+{
+ wmWindow *win;
+
+ for (win = wm->windows.first; win; win = win->next) {
+ if (win->screen->animtimer) {
+ return win->screen;
+ }
+ }
+
+ return NULL;
+}
+
+
/* toggle operator */
int ED_screen_animation_play(bContext *C, int sync, int mode)
{
@@ -3428,13 +3661,15 @@ int ED_screen_animation_play(bContext *C, int sync, int mode)
if (ED_screen_animation_playing(CTX_wm_manager(C))) {
/* stop playback now */
ED_screen_animation_timer(C, 0, 0, 0, 0);
- sound_stop_scene(scene);
+ BKE_sound_stop_scene(scene);
+
+ WM_event_add_notifier(C, NC_SCENE | ND_FRAME, scene);
}
else {
int refresh = SPACE_TIME; /* these settings are currently only available from a menu in the TimeLine */
if (mode == 1) /* XXX only play audio forwards!? */
- sound_play_scene(scene);
+ BKE_sound_play_scene(scene);
ED_screen_animation_timer(C, screen->redraws_flag, refresh, sync, mode);
@@ -3590,9 +3825,9 @@ static int fullscreen_back_exec(bContext *C, wmOperator *op)
BKE_report(op->reports, RPT_ERROR, "No fullscreen areas were found");
return OPERATOR_CANCELLED;
}
-
- ED_screen_full_restore(C, sa);
-
+
+ ED_screen_full_prevspace(C, sa, false);
+
return OPERATOR_FINISHED;
}
@@ -3755,7 +3990,9 @@ static int scene_delete_exec(bContext *C, wmOperator *UNUSED(op))
{
Scene *scene = CTX_data_scene(C);
- ED_screen_delete_scene(C, scene);
+ if (ED_screen_delete_scene(C, scene) == false) {
+ return OPERATOR_CANCELLED;
+ }
if (G.debug & G_DEBUG)
printf("scene delete %p\n", scene);
@@ -3945,6 +4182,7 @@ void ED_operatortypes_screen(void)
WM_operatortype_append(SCREEN_OT_region_scale);
WM_operatortype_append(SCREEN_OT_region_flip);
WM_operatortype_append(SCREEN_OT_header_flip);
+ WM_operatortype_append(SCREEN_OT_header);
WM_operatortype_append(SCREEN_OT_header_toggle_menus);
WM_operatortype_append(SCREEN_OT_header_toolbox);
WM_operatortype_append(SCREEN_OT_screen_set);
@@ -4042,11 +4280,14 @@ void ED_keymap_screen(wmKeyConfig *keyconf)
WM_keymap_verify_item(keymap, "SCREEN_OT_area_dupli", EVT_ACTIONZONE_AREA, 0, KM_SHIFT, 0);
WM_keymap_verify_item(keymap, "SCREEN_OT_area_swap", EVT_ACTIONZONE_AREA, 0, KM_CTRL, 0);
WM_keymap_verify_item(keymap, "SCREEN_OT_region_scale", EVT_ACTIONZONE_REGION, 0, 0, 0);
+ kmi = WM_keymap_add_item(keymap, "SCREEN_OT_screen_full_area", EVT_ACTIONZONE_FULLSCREEN, 0, 0, 0);
+ RNA_boolean_set(kmi->ptr, "use_hide_panels", true);
/* area move after action zones */
WM_keymap_verify_item(keymap, "SCREEN_OT_area_move", LEFTMOUSE, KM_PRESS, 0, 0);
WM_keymap_verify_item(keymap, "SCREEN_OT_area_options", RIGHTMOUSE, KM_PRESS, 0, 0);
+ WM_keymap_add_item(keymap, "SCREEN_OT_header", F9KEY, KM_PRESS, KM_ALT, 0);
/* Header Editing ------------------------------------------------ */
keymap = WM_keymap_find(keyconf, "Header", 0, 0);
@@ -4066,6 +4307,9 @@ void ED_keymap_screen(wmKeyConfig *keyconf)
WM_keymap_add_item(keymap, "SCREEN_OT_screen_full_area", UPARROWKEY, KM_PRESS, KM_CTRL, 0);
WM_keymap_add_item(keymap, "SCREEN_OT_screen_full_area", DOWNARROWKEY, KM_PRESS, KM_CTRL, 0);
WM_keymap_add_item(keymap, "SCREEN_OT_screen_full_area", SPACEKEY, KM_PRESS, KM_SHIFT, 0);
+ kmi = WM_keymap_add_item(keymap, "SCREEN_OT_screen_full_area", F10KEY, KM_PRESS, KM_ALT, 0);
+ RNA_boolean_set(kmi->ptr, "use_hide_panels", true);
+
WM_keymap_add_item(keymap, "SCREEN_OT_screenshot", F3KEY, KM_PRESS, KM_CTRL, 0);
WM_keymap_add_item(keymap, "SCREEN_OT_screencast", F3KEY, KM_PRESS, KM_ALT, 0);
diff --git a/source/blender/editors/screen/screendump.c b/source/blender/editors/screen/screendump.c
index be5fd48b41a..a701fc9ccb7 100644
--- a/source/blender/editors/screen/screendump.c
+++ b/source/blender/editors/screen/screendump.c
@@ -65,7 +65,6 @@
#include "PIL_time.h"
-#include "ED_screen_types.h"
#include "screen_intern.h"
@@ -287,8 +286,8 @@ void SCREEN_OT_screenshot(wmOperatorType *ot)
ot->flag = 0;
- WM_operator_properties_filesel(ot, FOLDERFILE | IMAGEFILE, FILE_SPECIAL, FILE_SAVE,
- WM_FILESEL_FILEPATH, FILE_DEFAULTDISPLAY);
+ WM_operator_properties_filesel(ot, FILE_TYPE_FOLDER | FILE_TYPE_IMAGE, FILE_SPECIAL, FILE_SAVE,
+ WM_FILESEL_FILEPATH, FILE_DEFAULTDISPLAY, FILE_SORT_ALPHA);
RNA_def_boolean(ot->srna, "full", 1, "Full Screen",
"Capture the whole window (otherwise only capture the active area)");
}
@@ -304,6 +303,9 @@ typedef struct ScreenshotJob {
const short *stop;
const short *do_update;
ReportList reports;
+
+ bMovieHandle *movie_handle;
+ void *movie_ctx;
} ScreenshotJob;
@@ -313,7 +315,13 @@ static void screenshot_freejob(void *sjv)
if (sj->dumprect)
MEM_freeN(sj->dumprect);
-
+
+ if (sj->movie_handle) {
+ bMovieHandle *mh = sj->movie_handle;
+ mh->end_movie(sj->movie_ctx);
+ mh->context_free(sj->movie_ctx);
+ }
+
MEM_freeN(sj);
}
@@ -338,20 +346,26 @@ static void screenshot_startjob(void *sjv, short *stop, short *do_update, float
{
ScreenshotJob *sj = sjv;
RenderData rd = sj->scene->r;
- bMovieHandle *mh = BKE_movie_handle_get(sj->scene->r.im_format.imtype);
-
+ bMovieHandle *mh = NULL;
+
/* we need this as local variables for renderdata */
rd.frs_sec = U.scrcastfps;
rd.frs_sec_base = 1.0f;
if (BKE_imtype_is_movie(rd.im_format.imtype)) {
- if (!mh->start_movie(sj->scene, &rd, sj->dumpsx, sj->dumpsy, &sj->reports)) {
+ mh = BKE_movie_handle_get(sj->scene->r.im_format.imtype);
+ if (mh == NULL) {
+ printf("Movie format unsupported\n");
+ return;
+ }
+ sj->movie_ctx = mh->context_create();
+ sj->movie_handle = mh;
+
+ if (!mh->start_movie(sj->movie_ctx, sj->scene, &rd, sj->dumpsx, sj->dumpsy, &sj->reports, false, "")) {
printf("screencast job stopped\n");
return;
}
}
- else
- mh = NULL;
sj->stop = stop;
sj->do_update = do_update;
@@ -363,8 +377,8 @@ static void screenshot_startjob(void *sjv, short *stop, short *do_update, float
if (sj->dumprect) {
if (mh) {
- if (mh->append_movie(&rd, rd.sfra, rd.cfra, (int *)sj->dumprect,
- sj->dumpsx, sj->dumpsy, &sj->reports))
+ if (mh->append_movie(sj->movie_ctx, &rd, rd.sfra, rd.cfra, (int *)sj->dumprect,
+ sj->dumpsx, sj->dumpsy, "", &sj->reports))
{
BKE_reportf(&sj->reports, RPT_INFO, "Appended frame: %d", rd.cfra);
printf("Appended frame %d\n", rd.cfra);
@@ -378,8 +392,9 @@ static void screenshot_startjob(void *sjv, short *stop, short *do_update, float
char name[FILE_MAX];
int ok;
- BKE_makepicstring(name, rd.pic, sj->bmain->name, rd.cfra,
- &rd.im_format, (rd.scemode & R_EXTENSION) != 0, true);
+ BKE_image_path_from_imformat(
+ name, rd.pic, sj->bmain->name, rd.cfra,
+ &rd.im_format, (rd.scemode & R_EXTENSION) != 0, true, NULL);
ibuf->rect = sj->dumprect;
ok = BKE_imbuf_write(ibuf, name, &rd.im_format);
@@ -410,8 +425,11 @@ static void screenshot_startjob(void *sjv, short *stop, short *do_update, float
PIL_sleep_ms(U.scrcastwait);
}
- if (mh)
- mh->end_movie();
+ if (mh) {
+ mh->end_movie(sj->movie_ctx);
+ mh->context_free(sj->movie_ctx);
+ sj->movie_handle = NULL;
+ }
BKE_report(&sj->reports, RPT_INFO, "Screencast job stopped");
}
diff --git a/source/blender/editors/sculpt_paint/CMakeLists.txt b/source/blender/editors/sculpt_paint/CMakeLists.txt
index 18db57c9f21..46753df4e13 100644
--- a/source/blender/editors/sculpt_paint/CMakeLists.txt
+++ b/source/blender/editors/sculpt_paint/CMakeLists.txt
@@ -23,7 +23,7 @@ set(INC
../uvedit
../../blenkernel
../../blenlib
- ../../blenfont
+ ../../blentranslation
../../bmesh
../../gpu
../../imbuf
@@ -32,6 +32,7 @@ set(INC
../../render/extern/include
../../windowmanager
../../../../intern/guardedalloc
+ ../../../../intern/glew-mx
)
set(INC_SYS
@@ -64,4 +65,6 @@ if(WITH_INTERNATIONAL)
add_definitions(-DWITH_INTERNATIONAL)
endif()
+add_definitions(${GL_DEFINITIONS})
+
blender_add_lib(bf_editor_sculpt_paint "${SRC}" "${INC}" "${INC_SYS}")
diff --git a/source/blender/editors/sculpt_paint/SConscript b/source/blender/editors/sculpt_paint/SConscript
index b0118fbbf53..52fab472189 100644
--- a/source/blender/editors/sculpt_paint/SConscript
+++ b/source/blender/editors/sculpt_paint/SConscript
@@ -30,15 +30,17 @@ Import ('env')
sources = env.Glob('*.c')
defs = []
+defs += env['BF_GL_DEFINITIONS']
incs = [
'#/intern/guardedalloc',
- '#/extern/glew/include',
+ env['BF_GLEW_INC'],
+ '#/intern/glew-mx',
'../include',
'../uvedit',
- '../../blenfont',
'../../blenkernel',
'../../blenlib',
+ '../../blentranslation',
'../../bmesh',
'../../gpu',
'../../imbuf',
diff --git a/source/blender/editors/sculpt_paint/paint_cursor.c b/source/blender/editors/sculpt_paint/paint_cursor.c
index 7b9ede38b39..e19756c6a35 100644
--- a/source/blender/editors/sculpt_paint/paint_cursor.c
+++ b/source/blender/editors/sculpt_paint/paint_cursor.c
@@ -426,7 +426,7 @@ static int load_tex_cursor(Brush *br, ViewContext *vc, float zoom)
len = sqrtf(x * x + y * y);
if (len <= 1) {
- float avg = BKE_brush_curve_strength_clamp(br, len, 1.0f); /* Falloff curve */
+ float avg = BKE_brush_curve_strength_clamped(br, len, 1.0f); /* Falloff curve */
buffer[index] = 255 - (GLubyte)(255 * avg);
@@ -521,14 +521,15 @@ static int project_brush_radius(ViewContext *vc,
}
}
-static int sculpt_get_brush_geometry(bContext *C, ViewContext *vc,
- int x, int y, int *pixel_radius,
- float location[3])
+static bool sculpt_get_brush_geometry(
+ bContext *C, ViewContext *vc,
+ int x, int y, int *pixel_radius,
+ float location[3])
{
Scene *scene = CTX_data_scene(C);
Paint *paint = BKE_paint_get_active_from_context(C);
float mouse[2];
- int hit;
+ bool hit;
mouse[0] = x;
mouse[1] = y;
@@ -594,7 +595,7 @@ static void paint_draw_tex_overlay(UnifiedPaintSettings *ups, Brush *brush,
if (mtex->brush_map_mode == MTEX_MAP_MODE_VIEW) {
/* brush rotation */
glTranslatef(0.5, 0.5, 0);
- glRotatef((double)RAD2DEGF(ups->brush_rotation),
+ glRotatef((double)RAD2DEGF((primary) ? ups->brush_rotation : ups->brush_rotation_sec),
0.0, 0.0, 1.0);
glTranslatef(-0.5f, -0.5f, 0);
@@ -643,24 +644,20 @@ static void paint_draw_tex_overlay(UnifiedPaintSettings *ups, Brush *brush,
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
if (primary)
- glTranslatef(brush->stencil_pos[0], brush->stencil_pos[1], 0);
+ glTranslate2fv(brush->stencil_pos);
else
- glTranslatef(brush->mask_stencil_pos[0], brush->mask_stencil_pos[1], 0);
+ glTranslate2fv(brush->mask_stencil_pos);
glRotatef(RAD2DEGF(mtex->rot), 0, 0, 1);
glMatrixMode(GL_TEXTURE);
}
/* set quad color. Colored overlay does not get blending */
- if (col)
- glColor4f(1.0,
- 1.0,
- 1.0,
- overlay_alpha / 100.0f);
- else
- glColor4f(U.sculpt_paint_overlay_col[0],
- U.sculpt_paint_overlay_col[1],
- U.sculpt_paint_overlay_col[2],
- overlay_alpha / 100.0f);
+ if (col) {
+ glColor4f(1.0, 1.0, 1.0, overlay_alpha / 100.0f);
+ }
+ else {
+ glColor4f(UNPACK3(U.sculpt_paint_overlay_col), overlay_alpha / 100.0f);
+ }
/* draw textured quad */
glBegin(GL_QUADS);
@@ -728,7 +725,7 @@ static void paint_draw_cursor_overlay(UnifiedPaintSettings *ups, Brush *brush,
do_pop = true;
glPushMatrix();
glLoadIdentity();
- glTranslatef(center[0], center[1], 0);
+ glTranslate2fv(center);
glScalef(ups->size_pressure_value, ups->size_pressure_value, 1);
glTranslatef(-center[0], -center[1], 0);
}
@@ -759,7 +756,7 @@ static void paint_draw_alpha_overlay(UnifiedPaintSettings *ups, Brush *brush,
ViewContext *vc, int x, int y, float zoom, PaintMode mode)
{
/* color means that primary brush texture is colured and secondary is used for alpha/mask control */
- bool col = ELEM(mode, PAINT_TEXTURE_PROJECTIVE, PAINT_TEXTURE_2D, PAINT_VERTEX) ? true : false;
+ bool col = ELEM(mode, ePaintTextureProjective, ePaintTexture2D, ePaintVertex) ? true : false;
OverlayControlFlags flags = BKE_paint_get_overlay_flags();
/* save lots of GL state
* TODO: check on whether all of these are needed? */
@@ -785,7 +782,7 @@ static void paint_draw_alpha_overlay(UnifiedPaintSettings *ups, Brush *brush,
paint_draw_cursor_overlay(ups, brush, vc, x, y, zoom);
}
else {
- if (!(flags & PAINT_OVERLAY_OVERRIDE_PRIMARY))
+ if (!(flags & PAINT_OVERLAY_OVERRIDE_PRIMARY) && (mode != ePaintWeight))
paint_draw_tex_overlay(ups, brush, vc, x, y, zoom, false, true);
if (!(flags & PAINT_OVERLAY_OVERRIDE_CURSOR))
paint_draw_cursor_overlay(ups, brush, vc, x, y, zoom);
@@ -958,21 +955,32 @@ static void paint_cursor_on_hit(UnifiedPaintSettings *ups, Brush *brush, ViewCon
}
}
+static bool ommit_cursor_drawing(Paint *paint, PaintMode mode, Brush *brush)
+{
+ if (paint->flags & PAINT_SHOW_BRUSH) {
+ if (ELEM(mode, ePaintTexture2D, ePaintTextureProjective) && brush->imagepaint_tool == PAINT_TOOL_FILL) {
+ return true;
+ }
+ return false;
+ }
+ return true;
+}
+
static void paint_draw_cursor(bContext *C, int x, int y, void *UNUSED(unused))
{
Scene *scene = CTX_data_scene(C);
UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings;
Paint *paint = BKE_paint_get_active_from_context(C);
Brush *brush = BKE_paint_brush(paint);
+ PaintMode mode = BKE_paintmode_get_active_from_context(C);
ViewContext vc;
- PaintMode mode;
float final_radius;
float translation[2];
float outline_alpha, *outline_col;
float zoomx, zoomy;
-
+
/* check that brush drawing is enabled */
- if (!(paint->flags & PAINT_SHOW_BRUSH))
+ if (ommit_cursor_drawing(paint, mode, brush))
return;
/* can't use stroke vc here because this will be called during
@@ -981,7 +989,6 @@ static void paint_draw_cursor(bContext *C, int x, int y, void *UNUSED(unused))
get_imapaint_zoom(C, &zoomx, &zoomy);
zoomx = max_ff(zoomx, zoomy);
- mode = BKE_paintmode_get_active_from_context(C);
/* skip everything and draw brush here */
if (brush->flag & BRUSH_CURVE) {
@@ -999,9 +1006,7 @@ static void paint_draw_cursor(bContext *C, int x, int y, void *UNUSED(unused))
/* don't calculate rake angles while a stroke is active because the rake variables are global and
* we may get interference with the stroke itself. For line strokes, such interference is visible */
if (!ups->stroke_active) {
- if (brush->flag & BRUSH_RAKE)
- /* here, translation contains the mouse coordinates. */
- paint_calculate_rake_rotation(ups, translation);
+ paint_calculate_rake_rotation(ups, brush, translation);
}
/* draw overlay */
@@ -1009,9 +1014,10 @@ static void paint_draw_cursor(bContext *C, int x, int y, void *UNUSED(unused))
/* TODO: as sculpt and other paint modes are unified, this
* special mode of drawing will go away */
- if ((mode == PAINT_SCULPT) && vc.obact->sculpt) {
+ if ((mode == ePaintSculpt) && vc.obact->sculpt) {
float location[3];
- int pixel_radius, hit;
+ int pixel_radius;
+ bool hit;
/* test if brush is over the mesh */
hit = sculpt_get_brush_geometry(C, &vc, x, y, &pixel_radius, location);
@@ -1022,8 +1028,8 @@ static void paint_draw_cursor(bContext *C, int x, int y, void *UNUSED(unused))
/* check if brush is subtracting, use different color then */
/* TODO: no way currently to know state of pen flip or
* invert key modifier without starting a stroke */
- if ((!(ups->draw_inverted) ^
- !(brush->flag & BRUSH_DIR_IN)) &&
+ if (((ups->draw_inverted == 0) ^
+ ((brush->flag & BRUSH_DIR_IN) == 0)) &&
ELEM(brush->sculpt_tool, SCULPT_TOOL_DRAW,
SCULPT_TOOL_INFLATE, SCULPT_TOOL_CLAY,
SCULPT_TOOL_PINCH, SCULPT_TOOL_CREASE))
@@ -1050,7 +1056,7 @@ static void paint_draw_cursor(bContext *C, int x, int y, void *UNUSED(unused))
glColor4f(outline_col[0], outline_col[1], outline_col[2], outline_alpha);
/* draw brush outline */
- glTranslatef(translation[0], translation[1], 0);
+ glTranslate2fv(translation);
/* draw an inner brush */
if (ups->stroke_active && BKE_brush_use_size_pressure(scene, brush)) {
diff --git a/source/blender/editors/sculpt_paint/paint_curve.c b/source/blender/editors/sculpt_paint/paint_curve.c
index 8c7c3b102e3..2f27db835f5 100644
--- a/source/blender/editors/sculpt_paint/paint_curve.c
+++ b/source/blender/editors/sculpt_paint/paint_curve.c
@@ -108,7 +108,7 @@ static void paintcurve_undo_restore(bContext *C, ListBase *lb)
uc = (UndoCurve *)lb->first;
- if (strncmp(uc->idname, pc->id.name, BLI_strnlen(uc->idname, sizeof(uc->idname))) == 0) {
+ if (STREQLEN(uc->idname, pc->id.name, BLI_strnlen(uc->idname, sizeof(uc->idname)))) {
SWAP(PaintCurvePoint *, pc->points, uc->points);
SWAP(int, pc->tot_points, uc->tot_points);
SWAP(int, pc->add_index, uc->active_point);
@@ -134,12 +134,12 @@ static void paintcurve_undo_begin(bContext *C, wmOperator *op, PaintCurve *pc)
UndoCurve *uc;
switch (mode) {
- case PAINT_TEXTURE_2D:
- case PAINT_TEXTURE_PROJECTIVE:
+ case ePaintTexture2D:
+ case ePaintTextureProjective:
undo_stack_id = UNDO_PAINT_IMAGE;
break;
- case PAINT_SCULPT:
+ case ePaintSculpt:
undo_stack_id = UNDO_PAINT_MESH;
break;
@@ -222,6 +222,28 @@ static int paintcurve_point_co_index(char sel)
return i;
}
+static char paintcurve_point_side_index(const BezTriple *bezt, const bool is_first, const char fallback)
+{
+ /* when matching, guess based on endpoint side */
+ if (BEZT_ISSEL_ANY(bezt)) {
+ if ((bezt->f1 & SELECT) == (bezt->f3 & SELECT)) {
+ return is_first ? SEL_F1 : SEL_F3;
+ }
+ else if (bezt->f1 & SELECT) {
+ return SEL_F1;
+ }
+ else if (bezt->f3 & SELECT) {
+ return SEL_F3;
+ }
+ else {
+ return fallback;
+ }
+ }
+ else {
+ return 0;
+ }
+}
+
/******************* Operators *********************************/
static int paintcurve_new_exec(bContext *C, wmOperator *UNUSED(op))
@@ -295,10 +317,17 @@ static void paintcurve_point_add(bContext *C, wmOperator *op, const int loc[2])
for (i = 0; i < pc->tot_points; i++) {
pcp[i].bez.f1 = pcp[i].bez.f2 = pcp[i].bez.f3 = 0;
}
- pcp[add_index].bez.f3 = SELECT;
- pcp[add_index].bez.h2 = HD_ALIGN;
- pc->add_index = add_index + 1;
+ BKE_paint_curve_clamp_endpoint_add_index(pc, add_index);
+
+ if (pc->add_index != 0) {
+ pcp[add_index].bez.f3 = SELECT;
+ pcp[add_index].bez.h2 = HD_ALIGN;
+ }
+ else {
+ pcp[add_index].bez.f1 = SELECT;
+ pcp[add_index].bez.h1 = HD_ALIGN;
+ }
WM_paint_cursor_tag_redraw(window, ar);
}
@@ -329,7 +358,7 @@ void PAINTCURVE_OT_add_point(wmOperatorType *ot)
{
/* identifiers */
ot->name = "Add New Paint Curve Point";
- ot->description = "Add new paint curve point";
+ ot->description = ot->name;
ot->idname = "PAINTCURVE_OT_add_point";
/* api callbacks */
@@ -366,7 +395,7 @@ static int paintcurve_delete_point_exec(bContext *C, wmOperator *op)
#define DELETE_TAG 2
for (i = 0, pcp = pc->points; i < pc->tot_points; i++, pcp++) {
- if ((pcp->bez.f1 & SELECT) || (pcp->bez.f2 & SELECT) || (pcp->bez.f3 & SELECT)) {
+ if (BEZT_ISSEL_ANY(&pcp->bez)) {
pcp->bez.f2 |= DELETE_TAG;
tot_del++;
}
@@ -384,7 +413,7 @@ static int paintcurve_delete_point_exec(bContext *C, wmOperator *op)
points_new[j] = pc->points[i];
if ((i + 1) == pc->add_index) {
- pc->add_index = j + 1;
+ BKE_paint_curve_clamp_endpoint_add_index(pc, j);
}
j++;
}
@@ -410,8 +439,8 @@ static int paintcurve_delete_point_exec(bContext *C, wmOperator *op)
void PAINTCURVE_OT_delete_point(wmOperatorType *ot)
{
/* identifiers */
- ot->name = "Add New Paint Curve Point";
- ot->description = "Add new paint curve point";
+ ot->name = "Remove Paint Curve Point";
+ ot->description = ot->name;
ot->idname = "PAINTCURVE_OT_delete_point";
/* api callbacks */
@@ -469,7 +498,7 @@ static bool paintcurve_point_select(bContext *C, wmOperator *op, const int loc[2
pcp = paintcurve_point_get_closest(pc, loc_fl, false, PAINT_CURVE_SELECT_THRESHOLD, &selflag);
if (pcp) {
- pc->add_index = (pcp - pc->points) + 1;
+ BKE_paint_curve_clamp_endpoint_add_index(pc, pcp - pc->points);
if (selflag == SEL_F2) {
if (extend)
@@ -599,9 +628,8 @@ static int paintcurve_slide_invoke(bContext *C, wmOperator *op, const wmEvent *e
pcp = NULL;
/* just find first selected point */
for (i = 0; i < pc->tot_points; i++) {
- if (pc->points[i].bez.f1 || pc->points[i].bez.f2 || pc->points[i].bez.f3) {
+ if ((select = paintcurve_point_side_index(&pc->points[i].bez, i == 0, SEL_F3))) {
pcp = &pc->points[i];
- select = SEL_F3;
break;
}
}
@@ -631,7 +659,7 @@ static int paintcurve_slide_invoke(bContext *C, wmOperator *op, const wmEvent *e
/* only select the active point */
PAINT_CURVE_POINT_SELECT(pcp, psd->select);
- pc->add_index = (pcp - pc->points) + 1;
+ BKE_paint_curve_clamp_endpoint_add_index(pc, pcp - pc->points);
WM_event_add_modal_handler(C, op);
WM_paint_cursor_tag_redraw(window, ar);
@@ -709,17 +737,17 @@ static int paintcurve_draw_exec(bContext *C, wmOperator *UNUSED(op))
const char *name;
switch (mode) {
- case PAINT_TEXTURE_2D:
- case PAINT_TEXTURE_PROJECTIVE:
+ case ePaintTexture2D:
+ case ePaintTextureProjective:
name = "PAINT_OT_image_paint";
break;
- case PAINT_WEIGHT:
+ case ePaintWeight:
name = "PAINT_OT_weight_paint";
break;
- case PAINT_VERTEX:
+ case ePaintVertex:
name = "PAINT_OT_vertex_paint";
break;
- case PAINT_SCULPT:
+ case ePaintSculpt:
name = "SCULPT_OT_brush_stroke";
break;
default:
@@ -749,7 +777,7 @@ static int paintcurve_cursor_invoke(bContext *C, wmOperator *UNUSED(op), const w
PaintMode mode = BKE_paintmode_get_active_from_context(C);
switch (mode) {
- case PAINT_TEXTURE_2D:
+ case ePaintTexture2D:
{
ARegion *ar = CTX_wm_region(C);
SpaceImage *sima = CTX_wm_space_image(C);
diff --git a/source/blender/editors/sculpt_paint/paint_hide.c b/source/blender/editors/sculpt_paint/paint_hide.c
index f1c91d0fcb5..2f1d4cd4194 100644
--- a/source/blender/editors/sculpt_paint/paint_hide.c
+++ b/source/blender/editors/sculpt_paint/paint_hide.c
@@ -98,7 +98,7 @@ static void partialvis_update_mesh(Object *ob,
Mesh *me = ob->data;
MVert *mvert;
const float *paint_mask;
- int *vert_indices;
+ const int *vert_indices;
int totvert, i;
bool any_changed = false, any_visible = false;
@@ -150,7 +150,7 @@ static void partialvis_update_grids(Object *ob,
/* get PBVH data */
BKE_pbvh_node_get_grids(pbvh, node,
&grid_indices, &totgrid, NULL, NULL,
- &grids, NULL);
+ &grids);
grid_hidden = BKE_pbvh_grid_hidden(pbvh);
BKE_pbvh_get_grid_key(pbvh, &key);
diff --git a/source/blender/editors/sculpt_paint/paint_image.c b/source/blender/editors/sculpt_paint/paint_image.c
index 0e3592f59ee..f0c9c023876 100644
--- a/source/blender/editors/sculpt_paint/paint_image.c
+++ b/source/blender/editors/sculpt_paint/paint_image.c
@@ -45,31 +45,24 @@
#include "BLI_utildefines.h"
#include "BLI_threads.h"
-#include "PIL_time.h"
#include "IMB_imbuf.h"
#include "IMB_imbuf_types.h"
#include "DNA_brush_types.h"
-#include "DNA_mesh_types.h"
#include "DNA_node_types.h"
#include "DNA_object_types.h"
#include "BKE_context.h"
#include "BKE_depsgraph.h"
+#include "BKE_DerivedMesh.h"
#include "BKE_brush.h"
#include "BKE_image.h"
#include "BKE_main.h"
#include "BKE_material.h"
-#include "BKE_mesh.h"
#include "BKE_node.h"
#include "BKE_paint.h"
-#include "BKE_report.h"
-#include "BKE_scene.h"
#include "BKE_texture.h"
-#include "BKE_colortools.h"
-
-#include "BKE_editmesh.h"
#include "UI_view2d.h"
@@ -84,9 +77,9 @@
#include "RNA_access.h"
#include "RNA_define.h"
-#include "RNA_enum_types.h"
#include "GPU_draw.h"
+#include "GPU_buffers.h"
#include "BIF_gl.h"
#include "BIF_glutil.h"
@@ -99,7 +92,7 @@ typedef struct UndoImageTile {
struct UndoImageTile *next, *prev;
char idname[MAX_ID_NAME]; /* name instead of pointer*/
- char ibufname[IB_FILENAME_SIZE];
+ char ibufname[IMB_FILENAME_SIZE];
union {
float *fp;
@@ -165,9 +158,10 @@ static void undo_copy_tile(UndoImageTile *tile, ImBuf *tmpibuf, ImBuf *ibuf, Cop
}
}
else {
- if (mode == RESTORE_COPY)
+ if (mode == RESTORE_COPY) {
IMB_rectcpy(tmpibuf, ibuf, 0, 0, tile->x * IMAPAINT_TILE_SIZE,
- tile->y * IMAPAINT_TILE_SIZE, IMAPAINT_TILE_SIZE, IMAPAINT_TILE_SIZE);
+ tile->y * IMAPAINT_TILE_SIZE, IMAPAINT_TILE_SIZE, IMAPAINT_TILE_SIZE);
+ }
/* swap to the tmpbuf for easy copying */
if (ibuf->rect_float) {
SWAP(float *, tmpibuf->rect_float, tile->rect.fp);
@@ -199,7 +193,7 @@ void *image_undo_find_tile(Image *ima, ImBuf *ibuf, int x_tile, int y_tile, unsi
for (tile = lb->first; tile; tile = tile->next) {
if (tile->x == x_tile && tile->y == y_tile && ima->gen_type == tile->gen_type && ima->source == tile->source) {
if (tile->use_float == use_float) {
- if (strcmp(tile->idname, ima->id.name) == 0 && strcmp(tile->ibufname, ibuf->name) == 0) {
+ if (STREQ(tile->idname, ima->id.name) && STREQ(tile->ibufname, ibuf->name)) {
if (mask) {
/* allocate mask if requested */
if (!tile->mask) {
@@ -221,7 +215,7 @@ void *image_undo_find_tile(Image *ima, ImBuf *ibuf, int x_tile, int y_tile, unsi
return NULL;
}
-void *image_undo_push_tile(Image *ima, ImBuf *ibuf, ImBuf **tmpibuf, int x_tile, int y_tile, unsigned short **mask, bool **valid, bool proj)
+void *image_undo_push_tile(Image *ima, ImBuf *ibuf, ImBuf **tmpibuf, int x_tile, int y_tile, unsigned short **mask, bool **valid, bool proj, bool find_prev)
{
ListBase *lb = undo_paint_push_get_list(UNDO_PAINT_IMAGE);
UndoImageTile *tile;
@@ -232,7 +226,7 @@ void *image_undo_push_tile(Image *ima, ImBuf *ibuf, ImBuf **tmpibuf, int x_tile,
/* check if tile is already pushed */
/* in projective painting we keep accounting of tiles, so if we need one pushed, just push! */
- if (!proj) {
+ if (find_prev) {
data = image_undo_find_tile(ima, ibuf, x_tile, y_tile, mask, true);
if (data)
return data;
@@ -334,7 +328,7 @@ void ED_image_undo_restore(bContext *C, ListBase *lb)
short use_float;
/* find image based on name, pointer becomes invalid with global undo */
- if (ima && strcmp(tile->idname, ima->id.name) == 0) {
+ if (ima && STREQ(tile->idname, ima->id.name)) {
/* ima is valid */
}
else {
@@ -343,7 +337,7 @@ void ED_image_undo_restore(bContext *C, ListBase *lb)
ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL);
- if (ima && ibuf && strcmp(tile->ibufname, ibuf->name) != 0) {
+ if (ima && ibuf && !STREQ(tile->ibufname, ibuf->name)) {
/* current ImBuf filename was changed, probably current frame
* was changed when painting on image sequence, rather than storing
* full image user (which isn't so obvious, btw) try to find ImBuf with
@@ -451,7 +445,7 @@ void imapaint_region_tiles(ImBuf *ibuf, int x, int y, int w, int h, int *tx, int
*ty = (y >> IMAPAINT_TILE_BITS);
}
-void ED_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, bool find_old)
{
ImBuf *tmpibuf = NULL;
int tilex, tiley, tilew, tileh, tx, ty;
@@ -480,7 +474,7 @@ void ED_imapaint_dirty_region(Image *ima, ImBuf *ibuf, int x, int y, int w, int
for (ty = tiley; ty <= tileh; ty++)
for (tx = tilex; tx <= tilew; tx++)
- image_undo_push_tile(ima, ibuf, &tmpibuf, tx, ty, NULL, NULL, false);
+ image_undo_push_tile(ima, ibuf, &tmpibuf, tx, ty, NULL, NULL, false, find_old);
ibuf->userflags |= IB_BITMAPDIRTY;
@@ -505,7 +499,7 @@ void imapaint_image_update(SpaceImage *sima, Image *image, ImBuf *ibuf, short te
int w = imapaintpartial.x2 - imapaintpartial.x1;
int h = imapaintpartial.y2 - imapaintpartial.y1;
/* Testing with partial update in uv editor too */
- GPU_paint_update_image(image, imapaintpartial.x1, imapaintpartial.y1, w, h); //!texpaint);
+ GPU_paint_update_image(image, (sima ? &sima->iuser : NULL), imapaintpartial.x1, imapaintpartial.y1, w, h); //!texpaint);
}
}
@@ -527,8 +521,11 @@ BlurKernel *paint_new_blur_kernel(Brush *br, bool proj)
kernel->pixel_len = radius;
}
else {
- radius = br->blur_kernel_radius;
+ if (br->blur_kernel_radius <= 0)
+ br->blur_kernel_radius = 1;
+ radius = br->blur_kernel_radius;
+
side = kernel->side = radius * 2 + 1;
kernel->side_squared = kernel->side * kernel->side;
kernel->wdata = MEM_mallocN(sizeof(float) * kernel->side_squared, "blur kernel data");
@@ -543,11 +540,11 @@ BlurKernel *paint_new_blur_kernel(Brush *br, bool proj)
case KERNEL_GAUSSIAN:
{
- /* at standard deviation of 3.0 kernel is at about zero */
+ /* at 3.0 standard deviations distance, kernel is about zero */
float standard_dev = radius / 3.0f;
/* make the necessary adjustment to the value for use in the normal distribution formula */
- standard_dev = standard_dev * standard_dev * 2;
+ standard_dev = -standard_dev * standard_dev * 2;
for (i = 0; i < side; i++) {
for (j = 0; j < side; j++) {
@@ -666,22 +663,24 @@ void paint_brush_color_get(struct Scene *scene, struct Brush *br, bool color_cor
copy_v3_v3(color, BKE_brush_secondary_color_get(scene, br));
else {
if (br->flag & BRUSH_USE_GRADIENT) {
+ float color_gr[4];
switch (br->gradient_stroke_mode) {
case BRUSH_GRADIENT_PRESSURE:
- do_colorband(br->gradient, pressure, color);
+ do_colorband(br->gradient, pressure, color_gr);
break;
case BRUSH_GRADIENT_SPACING_REPEAT:
{
float coord = fmod(distance / br->gradient_spacing, 1.0);
- do_colorband(br->gradient, coord, color);
+ do_colorband(br->gradient, coord, color_gr);
break;
}
case BRUSH_GRADIENT_SPACING_CLAMP:
{
- do_colorband(br->gradient, distance / br->gradient_spacing, color);
+ do_colorband(br->gradient, distance / br->gradient_spacing, color_gr);
break;
}
}
+ copy_v3_v3(color, color_gr);
}
else
copy_v3_v3(color, BKE_brush_color_get(scene, br));
@@ -749,14 +748,16 @@ static PaintOperation *texture_paint_init(bContext *C, wmOperator *op, const flo
copy_v2_v2(pop->prevmouse, mouse);
copy_v2_v2(pop->startmouse, mouse);
- if ((brush->imagepaint_tool == PAINT_TOOL_FILL) && (brush->flag & BRUSH_USE_GRADIENT)) {
- pop->cursor = WM_paint_cursor_activate(CTX_wm_manager(C), image_paint_poll, gradient_draw_line, pop);
- }
-
/* initialize from context */
if (CTX_wm_region_view3d(C)) {
Object *ob = OBACT;
- paint_proj_mesh_data_ensure(C, ob, op);
+ bool uvs, mat, tex, stencil;
+ if (!BKE_paint_proj_mesh_data_check(scene, ob, &uvs, &mat, &tex, &stencil)) {
+ BKE_paint_data_warning(op->reports, uvs, mat, tex, stencil);
+ MEM_freeN(pop);
+ WM_event_add_notifier(C, NC_SCENE | ND_TOOLSETTINGS, NULL);
+ return NULL;
+ }
pop->mode = PAINT_MODE_3D_PROJECT;
pop->custom_paint = paint_proj_new_stroke(C, ob, mouse, mode);
}
@@ -770,6 +771,10 @@ static PaintOperation *texture_paint_init(bContext *C, wmOperator *op, const flo
return NULL;
}
+ if ((brush->imagepaint_tool == PAINT_TOOL_FILL) && (brush->flag & BRUSH_USE_GRADIENT)) {
+ pop->cursor = WM_paint_cursor_activate(CTX_wm_manager(C), image_paint_poll, gradient_draw_line, pop);
+ }
+
settings->imapaint.flag |= IMAGEPAINT_DRAWING;
ED_undo_paint_push_begin(UNDO_PAINT_IMAGE, op->type->name,
ED_image_undo_restore, ED_image_undo_free, NULL);
@@ -1040,8 +1045,9 @@ static void toggle_paint_cursor(bContext *C, int enable)
* purpose is to make sure the paint cursor is shown if paint
* mode is enabled in the image editor. the paint poll will
* ensure that the cursor is hidden when not in paint mode */
-void ED_space_image_paint_update(wmWindowManager *wm, ToolSettings *settings)
+void ED_space_image_paint_update(wmWindowManager *wm, Scene *scene)
{
+ ToolSettings *settings = scene->toolsettings;
wmWindow *win;
ScrArea *sa;
ImagePaintSettings *imapaint = &settings->imapaint;
@@ -1054,7 +1060,7 @@ void ED_space_image_paint_update(wmWindowManager *wm, ToolSettings *settings)
enabled = true;
if (enabled) {
- BKE_paint_init(&imapaint->paint, PAINT_CURSOR_TEXTURE_PAINT);
+ BKE_paint_init(scene, ePaintTexture2D, PAINT_CURSOR_TEXTURE_PAINT);
paint_cursor_start_explicit(&imapaint->paint, wm, image_paint_poll);
}
@@ -1207,7 +1213,7 @@ static int sample_color_exec(bContext *C, wmOperator *op)
RNA_int_get_array(op->ptr, "location", location);
use_palette = RNA_boolean_get(op->ptr, "palette");
- paint_sample_color(C, ar, location[0], location[1], mode == PAINT_TEXTURE_PROJECTIVE, use_palette);
+ paint_sample_color(C, ar, location[0], location[1], mode == ePaintTextureProjective, use_palette);
if (show_cursor) {
paint->flags |= PAINT_SHOW_BRUSH;
@@ -1245,7 +1251,7 @@ static int sample_color_invoke(bContext *C, wmOperator *op, const wmEvent *event
RNA_int_set_array(op->ptr, "location", event->mval);
- paint_sample_color(C, ar, event->mval[0], event->mval[1], mode == PAINT_TEXTURE_PROJECTIVE, false);
+ paint_sample_color(C, ar, event->mval[0], event->mval[1], mode == ePaintTextureProjective, false);
WM_cursor_modal_set(win, BC_EYEDROPPER_CURSOR);
WM_event_add_notifier(C, NC_BRUSH | NA_EDITED, brush);
@@ -1284,7 +1290,7 @@ static int sample_color_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
ARegion *ar = CTX_wm_region(C);
RNA_int_set_array(op->ptr, "location", event->mval);
- paint_sample_color(C, ar, event->mval[0], event->mval[1], mode == PAINT_TEXTURE_PROJECTIVE, false);
+ paint_sample_color(C, ar, event->mval[0], event->mval[1], mode == ePaintTextureProjective, false);
WM_event_add_notifier(C, NC_BRUSH | NA_EDITED, brush);
break;
}
@@ -1293,11 +1299,12 @@ static int sample_color_modal(bContext *C, wmOperator *op, const wmEvent *event)
if (event->val == KM_PRESS) {
ARegion *ar = CTX_wm_region(C);
RNA_int_set_array(op->ptr, "location", event->mval);
- paint_sample_color(C, ar, event->mval[0], event->mval[1], mode == PAINT_TEXTURE_PROJECTIVE, true);
+ paint_sample_color(C, ar, event->mval[0], event->mval[1], mode == ePaintTextureProjective, true);
if (!data->sample_palette) {
data->sample_palette = true;
sample_color_update_header(data, C);
}
+ WM_event_add_notifier(C, NC_BRUSH | NA_EDITED, brush);
}
break;
}
@@ -1378,29 +1385,31 @@ static int texture_paint_toggle_exec(bContext *C, wmOperator *op)
* cache in case we are loading a file */
BKE_texpaint_slots_refresh_object(scene, ob);
- paint_proj_mesh_data_ensure(C, ob, op);
-
+ BKE_paint_proj_mesh_data_check(scene, ob, NULL, NULL, NULL, NULL);
+
/* entering paint mode also sets image to editors */
if (imapaint->mode == IMAGEPAINT_MODE_MATERIAL) {
Material *ma = give_current_material(ob, ob->actcol); /* set the current material active paint slot on image editor */
- if (ma->texpaintslot)
+ if (ma && ma->texpaintslot)
ima = ma->texpaintslot[ma->paint_active_slot].ima;
}
- else if (imapaint->mode == IMAGEPAINT_MODE_MATERIAL) {
+ else if (imapaint->mode == IMAGEPAINT_MODE_IMAGE) {
ima = imapaint->canvas;
}
- for (sc = bmain->screen.first; sc; sc = sc->id.next) {
- ScrArea *sa;
- for (sa = sc->areabase.first; sa; sa = sa->next) {
- SpaceLink *sl;
- for (sl = sa->spacedata.first; sl; sl = sl->next) {
- if (sl->spacetype == SPACE_IMAGE) {
- SpaceImage *sima = (SpaceImage *)sl;
-
- if (!sima->pin)
- ED_space_image_set(sima, scene, scene->obedit, ima);
+ if (ima) {
+ for (sc = bmain->screen.first; sc; sc = sc->id.next) {
+ ScrArea *sa;
+ for (sa = sc->areabase.first; sa; sa = sa->next) {
+ SpaceLink *sl;
+ for (sl = sa->spacedata.first; sl; sl = sl->next) {
+ if (sl->spacetype == SPACE_IMAGE) {
+ SpaceImage *sima = (SpaceImage *)sl;
+
+ if (!sima->pin)
+ ED_space_image_set(sima, scene, scene->obedit, ima);
+ }
}
}
}
@@ -1408,7 +1417,7 @@ static int texture_paint_toggle_exec(bContext *C, wmOperator *op)
ob->mode |= mode_flag;
- BKE_paint_init(&scene->toolsettings->imapaint.paint, PAINT_CURSOR_TEXTURE_PAINT);
+ BKE_paint_init(scene, ePaintTextureProjective, PAINT_CURSOR_TEXTURE_PAINT);
if (U.glreslimit != 0)
GPU_free_images();
@@ -1417,7 +1426,7 @@ static int texture_paint_toggle_exec(bContext *C, wmOperator *op)
toggle_paint_cursor(C, 1);
}
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ GPU_drawobject_free(ob->derivedFinal);
WM_event_add_notifier(C, NC_SCENE | ND_MODE, scene);
return OPERATOR_FINISHED;
diff --git a/source/blender/editors/sculpt_paint/paint_image_2d.c b/source/blender/editors/sculpt_paint/paint_image_2d.c
index 5530f947b8c..c5a066e9b14 100644
--- a/source/blender/editors/sculpt_paint/paint_image_2d.c
+++ b/source/blender/editors/sculpt_paint/paint_image_2d.c
@@ -38,9 +38,7 @@
#include "DNA_space_types.h"
#include "DNA_object_types.h"
-#include "BLI_math.h"
-#include "BLI_rect.h"
#include "BLI_math_color_blend.h"
#include "BLI_stack.h"
#include "BLI_bitmap.h"
@@ -65,7 +63,6 @@
#include "UI_view2d.h"
-#include "RE_shader_ext.h"
#include "GPU_draw.h"
@@ -142,6 +139,7 @@ typedef struct ImagePaintState {
int faceindex;
float uv[2];
int do_facesel;
+ int symmetry;
bool need_redraw;
@@ -348,8 +346,8 @@ static unsigned short *brush_painter_curve_mask_new(BrushPainter *painter, int d
{
Brush *brush = painter->brush;
- int xoff = -diameter * 0.5f + 0.5f;
- int yoff = -diameter * 0.5f + 0.5f;
+ int xoff = -radius;
+ int yoff = -radius;
unsigned short *mask, *m;
int x, y;
@@ -362,7 +360,7 @@ static unsigned short *brush_painter_curve_mask_new(BrushPainter *painter, int d
float xy[2] = {x + xoff, y + yoff};
float len = len_v2(xy);
- *m = (unsigned short)(65535.0f * BKE_brush_curve_strength_clamp(brush, len, radius));
+ *m = (unsigned short)(65535.0f * BKE_brush_curve_strength_clamped(brush, len, radius));
}
}
@@ -411,11 +409,11 @@ static ImBuf *brush_painter_imbuf_new(BrushPainter *painter, int size, float pre
if (is_texbrush) {
brush_imbuf_tex_co(&tex_mapping, x, y, texco);
BKE_brush_sample_tex_3D(scene, brush, texco, rgba, thread, pool);
- mul_v3_v3(rgba, brush_rgb);
/* TODO(sergey): Support texture paint color space. */
if (!use_float) {
IMB_colormanagement_scene_linear_to_display_v3(rgba, display);
}
+ mul_v3_v3(rgba, brush_rgb);
}
else {
copy_v3_v3(rgba, brush_rgb);
@@ -485,11 +483,11 @@ static void brush_painter_imbuf_update(BrushPainter *painter, ImBuf *oldtexibuf,
if (is_texbrush) {
brush_imbuf_tex_co(&tex_mapping, x, y, texco);
BKE_brush_sample_tex_3D(scene, brush, texco, rgba, thread, pool);
- mul_v3_v3(rgba, brush_rgb);
/* TODO(sergey): Support texture paint color space. */
if (!use_float) {
IMB_colormanagement_scene_linear_to_display_v3(rgba, display);
}
+ mul_v3_v3(rgba, brush_rgb);
}
else {
copy_v3_v3(rgba, brush_rgb);
@@ -689,7 +687,7 @@ static void brush_painter_2d_refresh_cache(ImagePaintState *s, BrushPainter *pai
bool do_partial_update_mask = false;
/* invalidate case for all mapping modes */
if (brush->mask_mtex.brush_map_mode == MTEX_MAP_MODE_VIEW) {
- mask_rotation += ups->brush_rotation;
+ mask_rotation += ups->brush_rotation_sec;
}
else if (brush->mask_mtex.brush_map_mode == MTEX_MAP_MODE_RANDOM) {
renew_maxmask = true;
@@ -773,15 +771,8 @@ static void brush_painter_2d_refresh_cache(ImagePaintState *s, BrushPainter *pai
}
/* keep these functions in sync */
-static void paint_2d_ibuf_rgb_get(ImBuf *ibuf, int x, int y, const bool is_torus, float r_rgb[4])
+static void paint_2d_ibuf_rgb_get(ImBuf *ibuf, int x, int y, float r_rgb[4])
{
- if (is_torus) {
- x %= ibuf->x;
- if (x < 0) x += ibuf->x;
- y %= ibuf->y;
- if (y < 0) y += ibuf->y;
- }
-
if (ibuf->rect_float) {
const float *rrgbf = ibuf->rect_float + (ibuf->x * y + x) * 4;
copy_v4_v4(r_rgb, rrgbf);
@@ -817,18 +808,30 @@ static void paint_2d_ibuf_rgb_set(ImBuf *ibuf, int x, int y, const bool is_torus
}
}
-static float paint_2d_ibuf_add_if(ImBuf *ibuf, unsigned int x, unsigned int y, float *outrgb, short torus, float w)
+static void paint_2d_ibuf_tile_convert(ImBuf *ibuf, int *x, int *y, short tile)
+{
+ if (tile & PAINT_TILE_X) {
+ *x %= ibuf->x;
+ if (*x < 0) *x += ibuf->x;
+ }
+ if (tile & PAINT_TILE_Y) {
+ *y %= ibuf->y;
+ if (*y < 0) *y += ibuf->y;
+ }
+}
+
+
+static float paint_2d_ibuf_add_if(ImBuf *ibuf, int x, int y, float *outrgb, short tile, float w)
{
float inrgb[4];
- // XXX: signed unsigned mismatch
- if ((x >= (unsigned int)(ibuf->x)) || (y >= (unsigned int)(ibuf->y))) {
- if (torus) paint_2d_ibuf_rgb_get(ibuf, x, y, 1, inrgb);
- else return 0;
- }
- else {
- paint_2d_ibuf_rgb_get(ibuf, x, y, 0, inrgb);
+ if (tile) paint_2d_ibuf_tile_convert(ibuf, &x, &y, tile);
+ /* need to also do clipping here always since tiled coordinates
+ * are not always within bounds */
+ if (x < ibuf->x && x >= 0 && y < ibuf->y && y >= 0) {
+ paint_2d_ibuf_rgb_get(ibuf, x, y, inrgb);
}
+ else return 0;
mul_v4_fl(inrgb, w);
add_v4_v4(outrgb, inrgb);
@@ -836,7 +839,7 @@ static float paint_2d_ibuf_add_if(ImBuf *ibuf, unsigned int x, unsigned int y, f
return w;
}
-static void paint_2d_lift_soften(ImagePaintState *s, ImBuf *ibuf, ImBuf *ibufb, int *pos, const short is_torus)
+static void paint_2d_lift_soften(ImagePaintState *s, ImBuf *ibuf, ImBuf *ibufb, int *pos, const short tile)
{
bool sharpen = (s->painter->cache.invert ^ ((s->brush->flag & BRUSH_DIR_IN) != 0));
float threshold = s->brush->sharp_threshold;
@@ -854,7 +857,7 @@ static void paint_2d_lift_soften(ImagePaintState *s, ImBuf *ibuf, ImBuf *ibufb,
in_off[1] = pos[1];
out_off[0] = out_off[1] = 0;
- if (!is_torus) {
+ if (!tile) {
IMB_rectclip(ibuf, ibufb, &in_off[0], &in_off[1], &out_off[0],
&out_off[1], &dim[0], &dim[1]);
@@ -872,13 +875,23 @@ static void paint_2d_lift_soften(ImagePaintState *s, ImBuf *ibuf, ImBuf *ibufb,
yi = in_off[1] + y;
count = 0.0;
- paint_2d_ibuf_rgb_get(ibuf, xi, yi, is_torus, rgba);
+ if (tile) {
+ paint_2d_ibuf_tile_convert(ibuf, &xi, &yi, tile);
+ if (xi < ibuf->x && xi >= 0 && yi < ibuf->y && yi >= 0)
+ paint_2d_ibuf_rgb_get(ibuf, xi, yi, rgba);
+ else
+ zero_v4(rgba);
+ }
+ else {
+ /* coordinates have been clipped properly here, it should be safe to do this */
+ paint_2d_ibuf_rgb_get(ibuf, xi, yi, rgba);
+ }
zero_v4(outrgb);
for (yk = 0; yk < kernel->side; yk++) {
for (xk = 0; xk < kernel->side; xk++) {
count += paint_2d_ibuf_add_if(ibuf, xi + xk - kernel->pixel_len,
- yi + yk - kernel->pixel_len, outrgb, is_torus,
+ yi + yk - kernel->pixel_len, outrgb, tile,
kernel->wdata[xk + yk * kernel->side]);
}
}
@@ -892,7 +905,7 @@ static void paint_2d_lift_soften(ImagePaintState *s, ImBuf *ibuf, ImBuf *ibufb,
/* now rgba_ub contains the edge result, but this should be converted to luminance to avoid
* colored speckles appearing in final image, and also to check for threshold */
- outrgb[0] = outrgb[1] = outrgb[2] = rgb_to_grayscale(outrgb);
+ outrgb[0] = outrgb[1] = outrgb[2] = IMB_colormanagement_get_luminance(outrgb);
if (fabsf(outrgb[0]) > threshold) {
float mask = BKE_brush_alpha_get(s->scene, s->brush);
float alpha = rgba[3];
@@ -926,7 +939,7 @@ static void paint_2d_set_region(ImagePaintRegion *region, int destx, int desty,
region->height = height;
}
-static int paint_2d_torus_split_region(ImagePaintRegion region[4], ImBuf *dbuf, ImBuf *sbuf)
+static int paint_2d_torus_split_region(ImagePaintRegion region[4], ImBuf *dbuf, ImBuf *sbuf, short tile)
{
int destx = region->destx;
int desty = region->desty;
@@ -937,15 +950,18 @@ static int paint_2d_torus_split_region(ImagePaintRegion region[4], ImBuf *dbuf,
int origw, origh, w, h, tot = 0;
/* convert destination and source coordinates to be within image */
- destx = destx % dbuf->x;
- if (destx < 0) destx += dbuf->x;
- desty = desty % dbuf->y;
- if (desty < 0) desty += dbuf->y;
- srcx = srcx % sbuf->x;
- if (srcx < 0) srcx += sbuf->x;
- srcy = srcy % sbuf->y;
- if (srcy < 0) srcy += sbuf->y;
-
+ if (tile & PAINT_TILE_X) {
+ destx = destx % dbuf->x;
+ if (destx < 0) destx += dbuf->x;
+ srcx = srcx % sbuf->x;
+ if (srcx < 0) srcx += sbuf->x;
+ }
+ if (tile & PAINT_TILE_Y) {
+ desty = desty % dbuf->y;
+ if (desty < 0) desty += dbuf->y;
+ srcy = srcy % sbuf->y;
+ if (srcy < 0) srcy += sbuf->y;
+ }
/* clip width of blending area to destination imbuf, to avoid writing the
* same pixel twice */
origw = w = (width > dbuf->x) ? dbuf->x : width;
@@ -956,23 +972,23 @@ static int paint_2d_torus_split_region(ImagePaintRegion region[4], ImBuf *dbuf,
paint_2d_set_region(&region[tot++], destx, desty, srcx, srcy, w, h);
/* do 3 other rects if needed */
- if (w < origw)
+ if ((tile & PAINT_TILE_X) && w < origw)
paint_2d_set_region(&region[tot++], (destx + w) % dbuf->x, desty, (srcx + w) % sbuf->x, srcy, origw - w, h);
- if (h < origh)
+ if ((tile & PAINT_TILE_Y) && h < origh)
paint_2d_set_region(&region[tot++], destx, (desty + h) % dbuf->y, srcx, (srcy + h) % sbuf->y, w, origh - h);
- if ((w < origw) && (h < origh))
+ if ((tile & PAINT_TILE_X) && (tile & PAINT_TILE_Y) && (w < origw) && (h < origh))
paint_2d_set_region(&region[tot++], (destx + w) % dbuf->x, (desty + h) % dbuf->y, (srcx + w) % sbuf->x, (srcy + h) % sbuf->y, origw - w, origh - h);
return tot;
}
-static void paint_2d_lift_smear(ImBuf *ibuf, ImBuf *ibufb, int *pos)
+static void paint_2d_lift_smear(ImBuf *ibuf, ImBuf *ibufb, int *pos, short tile)
{
ImagePaintRegion region[4];
int a, tot;
paint_2d_set_region(region, 0, 0, pos[0], pos[1], ibufb->x, ibufb->y);
- tot = paint_2d_torus_split_region(region, ibufb, ibuf);
+ tot = paint_2d_torus_split_region(region, ibufb, ibuf, tile);
for (a = 0; a < tot; a++)
IMB_rectblend(ibufb, ibufb, ibuf, NULL, NULL, NULL, 0, region[a].destx, region[a].desty,
@@ -999,8 +1015,8 @@ static ImBuf *paint_2d_lift_clone(ImBuf *ibuf, ImBuf *ibufb, int *pos)
static void paint_2d_convert_brushco(ImBuf *ibufb, const float pos[2], int ipos[2])
{
- ipos[0] = (int)floorf((pos[0] - ibufb->x / 2) + 1.0f);
- ipos[1] = (int)floorf((pos[1] - ibufb->y / 2) + 1.0f);
+ ipos[0] = (int)floorf((pos[0] - ibufb->x / 2));
+ ipos[1] = (int)floorf((pos[1] - ibufb->y / 2));
}
static int paint_2d_op(void *state, ImBuf *ibufb, unsigned short *curveb, unsigned short *texmaskb, const float lastpos[2], const float pos[2])
@@ -1008,7 +1024,7 @@ static int paint_2d_op(void *state, ImBuf *ibufb, unsigned short *curveb, unsign
ImagePaintState *s = ((ImagePaintState *)state);
ImBuf *clonebuf = NULL, *frombuf;
ImagePaintRegion region[4];
- short torus = s->brush->flag & BRUSH_TORUS;
+ short tile = s->symmetry & (PAINT_TILE_X | PAINT_TILE_Y);
short blend = s->blend;
const float *offset = s->brush->clone.offset;
float liftpos[2];
@@ -1020,14 +1036,14 @@ static int paint_2d_op(void *state, ImBuf *ibufb, unsigned short *curveb, unsign
/* lift from canvas */
if (s->tool == PAINT_TOOL_SOFTEN) {
- paint_2d_lift_soften(s, s->canvas, ibufb, bpos, torus);
+ paint_2d_lift_soften(s, s->canvas, ibufb, bpos, tile);
}
else if (s->tool == PAINT_TOOL_SMEAR) {
if (lastpos[0] == pos[0] && lastpos[1] == pos[1])
return 0;
paint_2d_convert_brushco(ibufb, lastpos, blastpos);
- paint_2d_lift_smear(s->canvas, ibufb, blastpos);
+ paint_2d_lift_smear(s->canvas, ibufb, blastpos, tile);
}
else if (s->tool == PAINT_TOOL_CLONE && s->clonecanvas) {
liftpos[0] = pos[0] - offset[0] * s->canvas->x;
@@ -1039,9 +1055,9 @@ static int paint_2d_op(void *state, ImBuf *ibufb, unsigned short *curveb, unsign
frombuf = (clonebuf) ? clonebuf : ibufb;
- if (torus) {
+ if (tile) {
paint_2d_set_region(region, bpos[0], bpos[1], 0, 0, frombuf->x, frombuf->y);
- tot = paint_2d_torus_split_region(region, s->canvas, frombuf);
+ tot = paint_2d_torus_split_region(region, s->canvas, frombuf, tile);
}
else {
paint_2d_set_region(region, bpos[0], bpos[1], 0, 0, frombuf->x, frombuf->y);
@@ -1052,7 +1068,7 @@ static int paint_2d_op(void *state, ImBuf *ibufb, unsigned short *curveb, unsign
for (a = 0; a < tot; a++) {
ED_imapaint_dirty_region(s->image, s->canvas,
region[a].destx, region[a].desty,
- region[a].width, region[a].height);
+ region[a].width, region[a].height, true);
if (s->do_masking) {
/* masking, find original pixels tiles from undo buffer to composite over */
@@ -1112,7 +1128,7 @@ static int paint_2d_canvas_set(ImagePaintState *s, Image *ima)
if (ima == NULL) {
return 0;
}
- else if (ima->packedfile && ima->rr) {
+ else if (BKE_image_has_packedfile(ima) && ima->rr) {
s->warnpackedfile = ima->id.name + 2;
return 0;
}
@@ -1237,6 +1253,7 @@ void *paint_2d_new_stroke(bContext *C, wmOperator *op, int mode)
s->blend = brush->blend;
s->image = s->sima->image;
+ s->symmetry = settings->imapaint.paint.symmetry_flags;
if (!paint_2d_canvas_set(s, s->image)) {
if (s->warnmultifile)
@@ -1309,12 +1326,12 @@ static void paint_2d_fill_add_pixel_byte(
const int x_px, const int y_px, ImBuf *ibuf, BLI_Stack *stack, BLI_bitmap *touched,
const float color[4], float threshold_sq)
{
- int coordinate;
+ size_t coordinate;
if (x_px >= ibuf->x || x_px < 0 || y_px >= ibuf->y || y_px < 0)
return;
- coordinate = y_px * ibuf->x + x_px;
+ coordinate = ((size_t)y_px) * ibuf->x + x_px;
if (!BLI_BITMAP_TEST(touched, coordinate)) {
float color_f[4];
@@ -1332,12 +1349,12 @@ static void paint_2d_fill_add_pixel_float(
const int x_px, const int y_px, ImBuf *ibuf, BLI_Stack *stack, BLI_bitmap *touched,
const float color[4], float threshold_sq)
{
- int coordinate;
+ size_t coordinate;
if (x_px >= ibuf->x || x_px < 0 || y_px >= ibuf->y || y_px < 0)
return;
- coordinate = y_px * ibuf->x + x_px;
+ coordinate = ((size_t)y_px) * ibuf->x + x_px;
if (!BLI_BITMAP_TEST(touched, coordinate)) {
if (compare_len_squared_v3v3(ibuf->rect_float + 4 * coordinate, color, threshold_sq)) {
@@ -1389,21 +1406,21 @@ void paint_2d_bucket_fill(
if (!mouse_init || !br) {
/* first case, no image UV, fill the whole image */
- ED_imapaint_dirty_region(ima, ibuf, 0, 0, ibuf->x, ibuf->y);
+ ED_imapaint_dirty_region(ima, ibuf, 0, 0, ibuf->x, ibuf->y, false);
if (do_float) {
for (x_px = 0; x_px < ibuf->x; x_px++) {
for (y_px = 0; y_px < ibuf->y; y_px++) {
- blend_color_mix_float(ibuf->rect_float + 4 * (y_px * ibuf->x + x_px),
- ibuf->rect_float + 4 * (y_px * ibuf->x + x_px), color_f);
+ blend_color_mix_float(ibuf->rect_float + 4 * (((size_t)y_px) * ibuf->x + x_px),
+ ibuf->rect_float + 4 * (((size_t)y_px) * ibuf->x + x_px), color_f);
}
}
}
else {
for (x_px = 0; x_px < ibuf->x; x_px++) {
for (y_px = 0; y_px < ibuf->y; y_px++) {
- blend_color_mix_byte((unsigned char *)(ibuf->rect + y_px * ibuf->x + x_px),
- (unsigned char *)(ibuf->rect + y_px * ibuf->x + x_px), (unsigned char *)&color_b);
+ blend_color_mix_byte((unsigned char *)(ibuf->rect + ((size_t)y_px) * ibuf->x + x_px),
+ (unsigned char *)(ibuf->rect + ((size_t)y_px) * ibuf->x + x_px), (unsigned char *)&color_b);
}
}
}
@@ -1413,7 +1430,7 @@ void paint_2d_bucket_fill(
* value is within the brush fill threshold from the fill color */
BLI_Stack *stack;
BLI_bitmap *touched;
- int coordinate;
+ size_t coordinate;
int width = ibuf->x;
float image_init[2];
int minx = ibuf->x, miny = ibuf->y, maxx = 0, maxy = 0;
@@ -1431,12 +1448,12 @@ void paint_2d_bucket_fill(
}
/* change image invalidation method later */
- ED_imapaint_dirty_region(ima, ibuf, 0, 0, ibuf->x, ibuf->y);
+ ED_imapaint_dirty_region(ima, ibuf, 0, 0, ibuf->x, ibuf->y, false);
- stack = BLI_stack_new(sizeof(int), __func__);
- touched = BLI_BITMAP_NEW(ibuf->x * ibuf->y, "bucket_fill_bitmap");
+ stack = BLI_stack_new(sizeof(size_t), __func__);
+ touched = BLI_BITMAP_NEW(((size_t)ibuf->x) * ibuf->y, "bucket_fill_bitmap");
- coordinate = (y_px * ibuf->x + x_px);
+ coordinate = (((size_t)y_px) * ibuf->x + x_px);
if (do_float) {
copy_v4_v4(pixel_color, ibuf->rect_float + 4 * coordinate);
@@ -1569,7 +1586,7 @@ void paint_2d_gradient_fill(
do_float = (ibuf->rect_float != NULL);
/* this will be substituted by something else when selection is available */
- ED_imapaint_dirty_region(ima, ibuf, 0, 0, ibuf->x, ibuf->y);
+ ED_imapaint_dirty_region(ima, ibuf, 0, 0, ibuf->x, ibuf->y, false);
if (do_float) {
for (x_px = 0; x_px < ibuf->x; x_px++) {
@@ -1584,6 +1601,7 @@ void paint_2d_gradient_fill(
break;
}
case BRUSH_GRADIENT_RADIAL:
+ default:
{
f = len_v2(p) / line_len;
break;
@@ -1593,8 +1611,8 @@ void paint_2d_gradient_fill(
/* convert to premultiplied */
mul_v3_fl(color_f, color_f[3]);
color_f[3] *= br->alpha;
- IMB_blend_color_float(ibuf->rect_float + 4 * (y_px * ibuf->x + x_px),
- ibuf->rect_float + 4 * (y_px * ibuf->x + x_px),
+ IMB_blend_color_float(ibuf->rect_float + 4 * (((size_t)y_px) * ibuf->x + x_px),
+ ibuf->rect_float + 4 * (((size_t)y_px) * ibuf->x + x_px),
color_f, br->blend);
}
}
@@ -1612,6 +1630,7 @@ void paint_2d_gradient_fill(
break;
}
case BRUSH_GRADIENT_RADIAL:
+ default:
{
f = len_v2(p) / line_len;
break;
@@ -1619,10 +1638,11 @@ void paint_2d_gradient_fill(
}
do_colorband(br->gradient, f, color_f);
+ linearrgb_to_srgb_v3_v3(color_f, color_f);
rgba_float_to_uchar((unsigned char *)&color_b, color_f);
((unsigned char *)&color_b)[3] *= br->alpha;
- IMB_blend_color_byte((unsigned char *)(ibuf->rect + y_px * ibuf->x + x_px),
- (unsigned char *)(ibuf->rect + y_px * ibuf->x + x_px),
+ IMB_blend_color_byte((unsigned char *)(ibuf->rect + ((size_t)y_px) * ibuf->x + x_px),
+ (unsigned char *)(ibuf->rect + ((size_t)y_px) * ibuf->x + x_px),
(unsigned char *)&color_b, br->blend);
}
}
diff --git a/source/blender/editors/sculpt_paint/paint_image_proj.c b/source/blender/editors/sculpt_paint/paint_image_proj.c
index ee9181b7d3f..f1489f2fd10 100644
--- a/source/blender/editors/sculpt_paint/paint_image_proj.c
+++ b/source/blender/editors/sculpt_paint/paint_image_proj.c
@@ -43,14 +43,14 @@
#include "BLI_blenlib.h"
#include "BLI_linklist.h"
#include "BLI_math.h"
+#include "BLI_math_bits.h"
#include "BLI_math_color_blend.h"
#include "BLI_memarena.h"
#include "BLI_threads.h"
#include "BLI_utildefines.h"
-#include "BLF_translation.h"
+#include "BLT_translation.h"
-#include "PIL_time.h"
#include "IMB_imbuf.h"
#include "IMB_imbuf_types.h"
@@ -62,8 +62,8 @@
#include "DNA_object_types.h"
#include "BKE_camera.h"
-#include "BKE_colortools.h"
#include "BKE_context.h"
+#include "BKE_colortools.h"
#include "BKE_depsgraph.h"
#include "BKE_DerivedMesh.h"
#include "BKE_idprop.h"
@@ -74,16 +74,16 @@
#include "BKE_material.h"
#include "BKE_mesh.h"
#include "BKE_mesh_mapping.h"
+#include "BKE_node.h"
#include "BKE_paint.h"
#include "BKE_report.h"
#include "BKE_scene.h"
#include "BKE_texture.h"
-#include "UI_view2d.h"
#include "UI_interface.h"
-#include "ED_image.h"
#include "ED_mesh.h"
+#include "ED_node.h"
#include "ED_paint.h"
#include "ED_screen.h"
#include "ED_uvedit.h"
@@ -99,10 +99,12 @@
#include "RNA_enum_types.h"
#include "GPU_draw.h"
-#include "GPU_buffers.h"
#include "IMB_colormanagement.h"
+#include "bmesh.h"
+//#include "bmesh_tools.h"
+
#include "paint_intern.h"
/* Defines and Structs */
@@ -133,23 +135,30 @@ BLI_INLINE unsigned char f_to_char(const float val)
//#define PROJ_DEBUG_PRINT_CLIP 1
#define PROJ_DEBUG_WINCLIP 1
+
+#ifndef PROJ_DEBUG_NOSEAMBLEED
/* projectFaceSeamFlags options */
//#define PROJ_FACE_IGNORE (1<<0) /* When the face is hidden, backfacing or occluded */
//#define PROJ_FACE_INIT (1<<1) /* When we have initialized the faces data */
#define PROJ_FACE_SEAM1 (1 << 0) /* If this face has a seam on any of its edges */
#define PROJ_FACE_SEAM2 (1 << 1)
#define PROJ_FACE_SEAM3 (1 << 2)
-#define PROJ_FACE_SEAM4 (1 << 3)
#define PROJ_FACE_NOSEAM1 (1 << 4)
#define PROJ_FACE_NOSEAM2 (1 << 5)
#define PROJ_FACE_NOSEAM3 (1 << 6)
-#define PROJ_FACE_NOSEAM4 (1 << 7)
/* face winding */
#define PROJ_FACE_WINDING_INIT 1
#define PROJ_FACE_WINDING_CW 2
+/* a slightly scaled down face is used to get fake 3D location for edge pixels in the seams
+ * as this number approaches 1.0f the likelihood increases of float precision errors where
+ * it is occluded by an adjacent face */
+#define PROJ_FACE_SCALE_SEAM 0.99f
+#endif /* PROJ_DEBUG_NOSEAMBLEED */
+
+
#define PROJ_SRC_VIEW 1
#define PROJ_SRC_IMAGE_CAM 2
#define PROJ_SRC_IMAGE_VIEW 3
@@ -158,12 +167,6 @@ BLI_INLINE unsigned char f_to_char(const float val)
#define PROJ_VIEW_DATA_ID "view_data"
#define PROJ_VIEW_DATA_SIZE (4 * 4 + 4 * 4 + 3) /* viewmat + winmat + clipsta + clipend + is_ortho */
-
-/* a slightly scaled down face is used to get fake 3D location for edge pixels in the seams
- * as this number approaches 1.0f the likelihood increases of float precision errors where
- * it is occluded by an adjacent face */
-#define PROJ_FACE_SCALE_SEAM 0.99f
-
#define PROJ_BUCKET_NULL 0
#define PROJ_BUCKET_INIT (1 << 0)
// #define PROJ_BUCKET_CLONE_INIT (1<<1)
@@ -187,11 +190,34 @@ typedef struct ProjPaintImage {
ImagePaintPartialRedraw *partRedrawRect;
volatile void **undoRect; /* only used to build undo tiles during painting */
unsigned short **maskRect; /* the mask accumulation must happen on canvas, not on space screen bucket.
- * Here we store the mask rectangle */
+ * Here we store the mask rectangle */
bool **valid; /* store flag to enforce validation of undo rectangle */
- int touch;
+ bool touch;
} ProjPaintImage;
+/**
+ * Handle for stroke (operator customdata)
+ */
+typedef struct ProjStrokeHandle {
+ /* Support for painting from multiple views at once,
+ * currently used to impliment summetry painting,
+ * we can assume at least the first is set while painting. */
+ struct ProjPaintState *ps_views[8];
+ int ps_views_tot;
+ int symmetry_flags;
+
+ int orig_brush_size;
+
+ bool need_redraw;
+
+ /* trick to bypass regular paint and allow clone picking */
+ bool is_clone_cursor_pick;
+
+ /* In ProjPaintState, only here for convenience */
+ Scene *scene;
+ Brush *brush;
+} ProjStrokeHandle;
+
/* Main projection painting struct passed to all projection painting functions */
typedef struct ProjPaintState {
View3D *v3d;
@@ -203,25 +229,18 @@ typedef struct ProjPaintState {
/* the paint color. It can change depending of inverted mode or not */
float paint_color[3];
float paint_color_linear[3];
+ float dither;
Brush *brush;
short tool, blend, mode;
- int orig_brush_size;
+
float brush_size;
Object *ob;
+ /* for symmetry, we need to store modified object matrix */
+ float obmat[4][4];
+ float obmat_imat[4][4];
/* end similarities with ImagePaintState */
- DerivedMesh *dm;
- int dm_totface;
- int dm_totvert;
- int dm_release;
-
- MVert *dm_mvert;
- MFace *dm_mface;
- MTFace **dm_mtface;
- MTFace **dm_mtface_clone; /* other UV map, use for cloning between layers */
- MTFace *dm_mtface_stencil;
-
Image *stencil_ima;
Image *canvas_ima;
Image *clone_ima;
@@ -232,24 +251,16 @@ typedef struct ProjPaintState {
LinkNode **bucketRect; /* screen sized 2D array, each pixel has a linked list of ProjPixel's */
LinkNode **bucketFaces; /* bucketRect aligned array linkList of faces overlapping each bucket */
unsigned char *bucketFlags; /* store if the bucks have been initialized */
-#ifndef PROJ_DEBUG_NOSEAMBLEED
- char *faceSeamFlags; /* store info about faces, if they are initialized etc*/
- char *faceWindingFlags; /* save the winding of the face in uv space, helps as an extra validation step for seam detection */
- float (*faceSeamUVs)[4][2]; /* expanded UVs for faces to use as seams */
- LinkNode **vertFaces; /* Only needed for when seam_bleed_px is enabled, use to find UV seams */
-#endif
+
char *vertFlags; /* store options per vert, now only store if the vert is pointing away from the view */
int buckets_x; /* The size of the bucket grid, the grid span's screenMin/screenMax so you can paint outsize the screen or with 2 brushes at once */
int buckets_y;
- ProjPaintImage *projImages;
-
int pixel_sizeof; /* result of project_paint_pixel_sizeof(), constant per stroke */
int image_tot; /* size of projectImages array */
float (*screenCoords)[4]; /* verts projected into floating point screen space */
-
float screenMin[2]; /* 2D bounds for mesh verts on the screen's plane (screenspace) */
float screenMax[2];
float screen_width; /* Calculated from screenMin & screenMax */
@@ -266,13 +277,17 @@ typedef struct ProjPaintState {
bool do_occlude; /* Use raytraced occlusion? - ortherwise will paint right through to the back*/
bool do_backfacecull; /* ignore faces with normals pointing away, skips a lot of raycasts if your normals are correctly flipped */
bool do_mask_normal; /* mask out pixels based on their normals */
+ bool do_mask_cavity; /* mask out pixels based on cavity */
bool do_new_shading_nodes; /* cache BKE_scene_use_new_shading_nodes value */
- float normal_angle; /* what angle to mask at*/
+ float normal_angle; /* what angle to mask at */
+ float normal_angle__cos; /* cos(normal_angle), faster to compare */
float normal_angle_inner;
+ float normal_angle_inner__cos;
float normal_angle_range; /* difference between normal_angle and normal_angle_inner, for easy access */
bool do_face_sel; /* quick access to (me->editflag & ME_EDIT_PAINT_FACE_SEL) */
bool is_ortho;
+ bool is_flip_object; /* the object is negative scaled */
bool do_masking; /* use masking during painting. Some operations such as airbrush may disable */
bool is_texbrush; /* only to avoid running */
bool is_maskbrush; /* mask brush is applied before masking */
@@ -283,6 +298,7 @@ typedef struct ProjPaintState {
float cloneOffset[2];
float projectMat[4][4]; /* Projection matrix, use for getting screen coords */
+ float projectMatInv[4][4]; /* inverse of projectMat */
float viewDir[3]; /* View vector, use for do_backfacecull and for ray casting with an ortho viewport */
float viewPos[3]; /* View location in object relative 3D space, so can compare to verts */
float clipsta, clipend;
@@ -297,12 +313,60 @@ typedef struct ProjPaintState {
int bucketMax[2];
int context_bucket_x, context_bucket_y; /* must lock threads while accessing these */
- /* redraw */
- bool need_redraw;
-
+ struct CurveMapping *cavity_curve;
BlurKernel *blurkernel;
+
+
+ /* -------------------------------------------------------------------- */
+ /* Vars shared between multiple views (keep last) */
+ /**
+ * This data is owned by ``ProjStrokeHandle.ps_views[0]``,
+ * all other views re-use the data.
+ */
+
+#define PROJ_PAINT_STATE_SHARED_MEMCPY(ps_dst, ps_src) \
+ MEMCPY_STRUCT_OFS(ps_dst, ps_src, is_shared_user)
+
+#define PROJ_PAINT_STATE_SHARED_CLEAR(ps) \
+ MEMSET_STRUCT_OFS(ps, 0, is_shared_user)
+
+ bool is_shared_user;
+
+ ProjPaintImage *projImages;
+ float *cavities; /* cavity amount for vertices */
+
+#ifndef PROJ_DEBUG_NOSEAMBLEED
+ char *faceSeamFlags; /* store info about faces, if they are initialized etc*/
+ char *faceWindingFlags; /* save the winding of the face in uv space, helps as an extra validation step for seam detection */
+ float (*faceSeamUVs)[3][2]; /* expanded UVs for faces to use as seams */
+ LinkNode **vertFaces; /* Only needed for when seam_bleed_px is enabled, use to find UV seams */
+#endif
+
SpinLock *tile_lock;
+
+ DerivedMesh *dm;
+ int dm_totlooptri;
+ int dm_totpoly;
+ int dm_totedge;
+ int dm_totvert;
+ bool dm_release;
+
+ const MVert *dm_mvert;
+ const MEdge *dm_medge;
+ const MPoly *dm_mpoly;
+ const MLoop *dm_mloop;
+ const MLoopTri *dm_mlooptri;
+
+ const MLoopUV *dm_mloopuv_stencil;
+
+ /**
+ * \note These UV layers are aligned to \a dm_mpoly
+ * but each pointer references the start of the layer,
+ * so a loop indirection is needed as well.
+ */
+ const MLoopUV **dm_mloopuv;
+ const MLoopUV **dm_mloopuv_clone; /* other UV map, use for cloning between layers */
} ProjPaintState;
typedef union pixelPointer {
@@ -320,25 +384,27 @@ typedef union pixelStore {
typedef struct ProjPixel {
float projCoSS[2]; /* the floating point screen projection of this pixel */
float worldCoSS[3];
+
+ short x_px, y_px;
+
+ unsigned short image_index; /* if anyone wants to paint onto more than 65535 images they can bite me */
+ unsigned char bb_cell_index;
+
+ /* for various reasons we may want to mask out painting onto this pixel */
+ unsigned short mask;
+
/* Only used when the airbrush is disabled.
* Store the max mask value to avoid painting over an area with a lower opacity
* with an advantage that we can avoid touching the pixel at all, if the
* new mask value is lower then mask_accum */
unsigned short *mask_accum;
- /* for various reasons we may want to mask out painting onto this pixel */
- unsigned short mask;
-
- short x_px, y_px;
/* horrible hack, store tile valid flag pointer here to re-validate tiles used for anchored and drag-dot strokes */
bool *valid;
PixelPointer origColor;
PixelStore newColor;
PixelPointer pixel;
-
- short image_index; /* if anyone wants to paint onto more than 32768 images they can bite me */
- unsigned char bb_cell_index;
} ProjPixel;
typedef struct ProjPixelClone {
@@ -356,40 +422,71 @@ typedef struct {
} TileInfo;
+
+/* -------------------------------------------------------------------- */
+
+/** \name MLoopTri accessor functions.
+ * \{ */
+
+BLI_INLINE const MPoly *ps_tri_index_to_mpoly(const ProjPaintState *ps, int tri_index)
+{
+ return &ps->dm_mpoly[ps->dm_mlooptri[tri_index].poly];
+}
+
+#define PS_LOOPTRI_AS_VERT_INDEX_3(ps, lt) \
+ ps->dm_mloop[lt->tri[0]].v, \
+ ps->dm_mloop[lt->tri[1]].v, \
+ ps->dm_mloop[lt->tri[2]].v,
+
+#define PS_LOOPTRI_AS_UV_3(uvlayer, lt) \
+ uvlayer[lt->poly][lt->tri[0]].uv, \
+ uvlayer[lt->poly][lt->tri[1]].uv, \
+ uvlayer[lt->poly][lt->tri[2]].uv,
+
+#define PS_LOOPTRI_ASSIGN_UV_3(uv_tri, uvlayer, lt) { \
+ (uv_tri)[0] = uvlayer[lt->poly][lt->tri[0]].uv; \
+ (uv_tri)[1] = uvlayer[lt->poly][lt->tri[1]].uv; \
+ (uv_tri)[2] = uvlayer[lt->poly][lt->tri[2]].uv; \
+} ((void)0)
+
+/** \} */
+
+
+
/* Finish projection painting structs */
-static TexPaintSlot *project_paint_face_paint_slot(const ProjPaintState *ps, int face_index)
+static TexPaintSlot *project_paint_face_paint_slot(const ProjPaintState *ps, int tri_index)
{
- MFace *mf = ps->dm_mface + face_index;
- Material *ma = ps->dm->mat[mf->mat_nr];
- return ma->texpaintslot + ma->paint_active_slot;
+ const MPoly *mp = ps_tri_index_to_mpoly(ps, tri_index);
+ Material *ma = ps->dm->mat[mp->mat_nr];
+ return ma ? ma->texpaintslot + ma->paint_active_slot : NULL;
}
-static Image *project_paint_face_paint_image(const ProjPaintState *ps, int face_index)
+static Image *project_paint_face_paint_image(const ProjPaintState *ps, int tri_index)
{
if (ps->do_stencil_brush) {
return ps->stencil_ima;
}
else {
- MFace *mf = ps->dm_mface + face_index;
- Material *ma = ps->dm->mat[mf->mat_nr];
- TexPaintSlot *slot = ma->texpaintslot + ma->paint_active_slot;
+ const MPoly *mp = ps_tri_index_to_mpoly(ps, tri_index);
+ Material *ma = ps->dm->mat[mp->mat_nr];
+ TexPaintSlot *slot = ma ? ma->texpaintslot + ma->paint_active_slot : NULL;
return slot ? slot->ima : ps->canvas_ima;
}
}
-static TexPaintSlot *project_paint_face_clone_slot(const ProjPaintState *ps, int face_index)
+static TexPaintSlot *project_paint_face_clone_slot(const ProjPaintState *ps, int tri_index)
{
- MFace *mf = ps->dm_mface + face_index;
- Material *ma = ps->dm->mat[mf->mat_nr];
- return ma->texpaintslot + ma->paint_clone_slot;
+ const MPoly *mp = ps_tri_index_to_mpoly(ps, tri_index);
+ Material *ma = ps->dm->mat[mp->mat_nr];
+ return ma ? ma->texpaintslot + ma->paint_clone_slot : NULL;
}
-static Image *project_paint_face_clone_image(const ProjPaintState *ps, int face_index)
+static Image *project_paint_face_clone_image(const ProjPaintState *ps, int tri_index)
{
- MFace *mf = ps->dm_mface + face_index;
- Material *ma = ps->dm->mat[mf->mat_nr];
- TexPaintSlot *slot = ma->texpaintslot + ma->paint_clone_slot;
+ const MPoly *mp = ps_tri_index_to_mpoly(ps, tri_index);
+ Material *ma = ps->dm->mat[mp->mat_nr];
+ TexPaintSlot *slot = ma ? ma->texpaintslot + ma->paint_clone_slot : NULL;
return slot ? slot->ima : ps->clone_ima;
}
@@ -422,17 +519,19 @@ static int project_bucket_offset_safe(const ProjPaintState *ps, const float proj
}
}
-static float VecZDepthOrtho(const float pt[2],
- const float v1[3], const float v2[3], const float v3[3],
- float w[3])
+static float VecZDepthOrtho(
+ const float pt[2],
+ const float v1[3], const float v2[3], const float v3[3],
+ float w[3])
{
barycentric_weights_v2(v1, v2, v3, pt, w);
return (v1[2] * w[0]) + (v2[2] * w[1]) + (v3[2] * w[2]);
}
-static float VecZDepthPersp(const float pt[2],
- const float v1[4], const float v2[4], const float v3[4],
- float w[3])
+static float VecZDepthPersp(
+ const float pt[2],
+ const float v1[4], const float v2[4], const float v3[4],
+ float w[3])
{
float wtot_inv, wtot;
float w_tmp[3];
@@ -466,17 +565,15 @@ static float VecZDepthPersp(const float pt[2],
/* Return the top-most face index that the screen space coord 'pt' touches (or -1) */
-static int project_paint_PickFace(const ProjPaintState *ps, const float pt[2], float w[3], int *side)
+static int project_paint_PickFace(
+ const ProjPaintState *ps, const float pt[2],
+ float w[3])
{
LinkNode *node;
float w_tmp[3];
- const float *v1, *v2, *v3, *v4;
int bucket_index;
- int face_index;
- int best_side = -1;
- int best_face_index = -1;
+ int best_tri_index = -1;
float z_depth_best = FLT_MAX, z_depth;
- MFace *mf;
bucket_index = project_bucket_offset_safe(ps, pt);
if (bucket_index == -1)
@@ -488,43 +585,32 @@ static int project_paint_PickFace(const ProjPaintState *ps, const float pt[2], f
* that the point its testing is only every originated from an existing face */
for (node = ps->bucketFaces[bucket_index]; node; node = node->next) {
- face_index = GET_INT_FROM_POINTER(node->link);
- mf = ps->dm_mface + face_index;
+ const int tri_index = GET_INT_FROM_POINTER(node->link);
+ const MLoopTri *lt = &ps->dm_mlooptri[tri_index];
+ const float *vtri_ss[3] = {
+ ps->screenCoords[ps->dm_mloop[lt->tri[0]].v],
+ ps->screenCoords[ps->dm_mloop[lt->tri[1]].v],
+ ps->screenCoords[ps->dm_mloop[lt->tri[2]].v],
+ };
- v1 = ps->screenCoords[mf->v1];
- v2 = ps->screenCoords[mf->v2];
- v3 = ps->screenCoords[mf->v3];
- if (isect_point_tri_v2(pt, v1, v2, v3)) {
- if (ps->is_ortho) z_depth = VecZDepthOrtho(pt, v1, v2, v3, w_tmp);
- else z_depth = VecZDepthPersp(pt, v1, v2, v3, w_tmp);
+ if (isect_point_tri_v2(pt, UNPACK3(vtri_ss))) {
+ if (ps->is_ortho) {
+ z_depth = VecZDepthOrtho(pt, UNPACK3(vtri_ss), w_tmp);
+ }
+ else {
+ z_depth = VecZDepthPersp(pt, UNPACK3(vtri_ss), w_tmp);
+ }
if (z_depth < z_depth_best) {
- best_face_index = face_index;
- best_side = 0;
+ best_tri_index = tri_index;
z_depth_best = z_depth;
copy_v3_v3(w, w_tmp);
}
}
- else if (mf->v4) {
- v4 = ps->screenCoords[mf->v4];
-
- if (isect_point_tri_v2(pt, v1, v3, v4)) {
- if (ps->is_ortho) z_depth = VecZDepthOrtho(pt, v1, v3, v4, w_tmp);
- else z_depth = VecZDepthPersp(pt, v1, v3, v4, w_tmp);
-
- if (z_depth < z_depth_best) {
- best_face_index = face_index;
- best_side = 1;
- z_depth_best = z_depth;
- copy_v3_v3(w, w_tmp);
- }
- }
- }
}
- *side = best_side;
- return best_face_index; /* will be -1 or a valid face */
+ return best_tri_index; /* will be -1 or a valid face */
}
/* Converts a uv coord into a pixel location wrapping if the uv is outside 0-1 range */
@@ -542,33 +628,29 @@ static void uvco_to_wrapped_pxco(const float uv[2], int ibuf_x, int ibuf_y, floa
}
/* Set the top-most face color that the screen space coord 'pt' touches (or return 0 if none touch) */
-static bool project_paint_PickColor(const ProjPaintState *ps, const float pt[2],
- float *rgba_fp, unsigned char *rgba, const bool interp)
+static bool project_paint_PickColor(
+ const ProjPaintState *ps, const float pt[2],
+ float *rgba_fp, unsigned char *rgba, const bool interp)
{
+ const MLoopTri *lt;
+ const float *lt_tri_uv[3];
float w[3], uv[2];
- int side;
- int face_index;
- MTFace *tf;
+ int tri_index;
Image *ima;
ImBuf *ibuf;
int xi, yi;
+ tri_index = project_paint_PickFace(ps, pt, w);
- face_index = project_paint_PickFace(ps, pt, w, &side);
-
- if (face_index == -1)
+ if (tri_index == -1)
return 0;
- tf = *(ps->dm_mtface + face_index);
+ lt = &ps->dm_mlooptri[tri_index];
+ PS_LOOPTRI_ASSIGN_UV_3(lt_tri_uv, ps->dm_mloopuv, lt);
- if (side == 0) {
- interp_v2_v2v2v2(uv, tf->uv[0], tf->uv[1], tf->uv[2], w);
- }
- else { /* QUAD */
- interp_v2_v2v2v2(uv, tf->uv[0], tf->uv[2], tf->uv[3], w);
- }
+ interp_v2_v2v2v2(uv, UNPACK3(lt_tri_uv), w);
- ima = project_paint_face_paint_image(ps, face_index);
+ ima = project_paint_face_paint_image(ps, tri_index);
ibuf = BKE_image_get_first_ibuf(ima); /* we must have got the imbuf before getting here */
if (!ibuf) return 0;
@@ -630,16 +712,18 @@ static bool project_paint_PickColor(const ProjPaintState *ps, const float pt[2],
return 1;
}
-/* Check if 'pt' is infront of the 3 verts on the Z axis (used for screenspace occlusuion test)
- * return...
- * 0 : no occlusion
- * -1 : no occlusion but 2D intersection is true (avoid testing the other half of a quad)
- * 1 : occluded
- * 2 : occluded with w[3] weights set (need to know in some cases) */
-
-static int project_paint_occlude_ptv(const float pt[3],
- const float v1[4], const float v2[4], const float v3[4],
- float w[3], const bool is_ortho)
+/**
+ * Check if 'pt' is infront of the 3 verts on the Z axis (used for screenspace occlusuion test)
+ * \return
+ * - `0`: no occlusion
+ * - `-1`: no occlusion but 2D intersection is true
+ * - `1`: occluded
+ * - `2`: occluded with `w[3]` weights set (need to know in some cases)
+ */
+static int project_paint_occlude_ptv(
+ const float pt[3],
+ const float v1[4], const float v2[4], const float v3[4],
+ float w[3], const bool is_ortho)
{
/* if all are behind us, return false */
if (v1[2] > pt[2] && v2[2] > pt[2] && v3[2] > pt[2])
@@ -669,26 +753,31 @@ static int project_paint_occlude_ptv(const float pt[3],
}
-static int project_paint_occlude_ptv_clip(const ProjPaintState *ps, const MFace *mf,
- const float pt[3], const float v1[4], const float v2[4], const float v3[4],
- const int side)
+static int project_paint_occlude_ptv_clip(
+ const float pt[3],
+ const float v1[4], const float v2[4], const float v3[4],
+ const float v1_3d[3], const float v2_3d[3], const float v3_3d[3],
+ float w[3], const bool is_ortho, RegionView3D *rv3d)
{
- float w[3], wco[3];
- int ret = project_paint_occlude_ptv(pt, v1, v2, v3, w, ps->is_ortho);
+ float wco[3];
+ int ret = project_paint_occlude_ptv(pt, v1, v2, v3, w, is_ortho);
if (ret <= 0)
return ret;
if (ret == 1) { /* weights not calculated */
- if (ps->is_ortho) barycentric_weights_v2(v1, v2, v3, pt, w);
- else barycentric_weights_v2_persp(v1, v2, v3, pt, w);
+ if (is_ortho) {
+ barycentric_weights_v2(v1, v2, v3, pt, w);
+ }
+ else {
+ barycentric_weights_v2_persp(v1, v2, v3, pt, w);
+ }
}
/* Test if we're in the clipped area, */
- if (side) interp_v3_v3v3v3(wco, ps->dm_mvert[mf->v1].co, ps->dm_mvert[mf->v3].co, ps->dm_mvert[mf->v4].co, w);
- else interp_v3_v3v3v3(wco, ps->dm_mvert[mf->v1].co, ps->dm_mvert[mf->v2].co, ps->dm_mvert[mf->v3].co, w);
+ interp_v3_v3v3v3(wco, v1_3d, v2_3d, v3_3d, w);
- if (!ED_view3d_clipping_test(ps->rv3d, wco, true)) {
+ if (!ED_view3d_clipping_test(rv3d, wco, true)) {
return 1;
}
@@ -699,35 +788,44 @@ static int project_paint_occlude_ptv_clip(const ProjPaintState *ps, const MFace
/* Check if a screenspace location is occluded by any other faces
* check, pixelScreenCo must be in screenspace, its Z-Depth only needs to be used for comparison
* and doesn't need to be correct in relation to X and Y coords (this is the case in perspective view) */
-static bool project_bucket_point_occluded(const ProjPaintState *ps, LinkNode *bucketFace,
- const int orig_face, const float pixelScreenCo[4])
+static bool project_bucket_point_occluded(
+ const ProjPaintState *ps, LinkNode *bucketFace,
+ const int orig_face, const float pixelScreenCo[4])
{
- MFace *mf;
- int face_index;
int isect_ret;
- float w[3]; /* not needed when clipping */
- const short do_clip = ps->rv3d ? ps->rv3d->rflag & RV3D_CLIPPING : 0;
+ const bool do_clip = ps->rv3d ? (ps->rv3d->rflag & RV3D_CLIPPING) != 0 : 0;
/* we could return 0 for 1 face buckets, as long as this function assumes
* that the point its testing is only every originated from an existing face */
for (; bucketFace; bucketFace = bucketFace->next) {
- face_index = GET_INT_FROM_POINTER(bucketFace->link);
-
- if (orig_face != face_index) {
- mf = ps->dm_mface + face_index;
- if (do_clip)
- isect_ret = project_paint_occlude_ptv_clip(ps, mf, pixelScreenCo, ps->screenCoords[mf->v1], ps->screenCoords[mf->v2], ps->screenCoords[mf->v3], 0);
- else
- isect_ret = project_paint_occlude_ptv(pixelScreenCo, ps->screenCoords[mf->v1], ps->screenCoords[mf->v2], ps->screenCoords[mf->v3], w, ps->is_ortho);
-
- /* Note, if (isect_ret == -1) then we don't want to test the other side of the quad */
- if (isect_ret == 0 && mf->v4) {
- if (do_clip)
- isect_ret = project_paint_occlude_ptv_clip(ps, mf, pixelScreenCo, ps->screenCoords[mf->v1], ps->screenCoords[mf->v3], ps->screenCoords[mf->v4], 1);
- else
- isect_ret = project_paint_occlude_ptv(pixelScreenCo, ps->screenCoords[mf->v1], ps->screenCoords[mf->v3], ps->screenCoords[mf->v4], w, ps->is_ortho);
+ const int tri_index = GET_INT_FROM_POINTER(bucketFace->link);
+
+ if (orig_face != tri_index) {
+ const MLoopTri *lt = &ps->dm_mlooptri[tri_index];
+ const float *vtri_ss[3] = {
+ ps->screenCoords[ps->dm_mloop[lt->tri[0]].v],
+ ps->screenCoords[ps->dm_mloop[lt->tri[1]].v],
+ ps->screenCoords[ps->dm_mloop[lt->tri[2]].v],
+ };
+ float w[3];
+
+ if (do_clip) {
+ const float *vtri_co[3] = {
+ ps->dm_mvert[ps->dm_mloop[lt->tri[0]].v].co,
+ ps->dm_mvert[ps->dm_mloop[lt->tri[1]].v].co,
+ ps->dm_mvert[ps->dm_mloop[lt->tri[2]].v].co,
+ };
+ isect_ret = project_paint_occlude_ptv_clip(
+ pixelScreenCo, UNPACK3(vtri_ss), UNPACK3(vtri_co),
+ w, ps->is_ortho, ps->rv3d);
+ }
+ else {
+ isect_ret = project_paint_occlude_ptv(
+ pixelScreenCo, UNPACK3(vtri_ss),
+ w, ps->is_ortho);
}
+
if (isect_ret >= 1) {
/* TODO - we may want to cache the first hit,
* it is not possible to swap the face order in the list anymore */
@@ -764,11 +862,11 @@ static int line_isect_y(const float p1[2], const float p2[2], const float y_leve
}
if (p1[1] > y_level && p2[1] < y_level) {
- *x_isect = (p2[0] * (p1[1] - y_level) + p1[0] * (y_level - p2[1])) / y_diff; /*(p1[1]-p2[1]);*/
+ *x_isect = (p2[0] * (p1[1] - y_level) + p1[0] * (y_level - p2[1])) / y_diff; /* (p1[1] - p2[1]); */
return ISECT_TRUE;
}
else if (p1[1] < y_level && p2[1] > y_level) {
- *x_isect = (p2[0] * (y_level - p1[1]) + p1[0] * (p2[1] - y_level)) / y_diff; /*(p2[1]-p1[1]);*/
+ *x_isect = (p2[0] * (y_level - p1[1]) + p1[0] * (p2[1] - y_level)) / y_diff; /* (p2[1] - p1[1]); */
return ISECT_TRUE;
}
else {
@@ -797,11 +895,11 @@ static int line_isect_x(const float p1[2], const float p2[2], const float x_leve
}
if (p1[0] > x_level && p2[0] < x_level) {
- *y_isect = (p2[1] * (p1[0] - x_level) + p1[1] * (x_level - p2[0])) / x_diff; /*(p1[0]-p2[0]);*/
+ *y_isect = (p2[1] * (p1[0] - x_level) + p1[1] * (x_level - p2[0])) / x_diff; /* (p1[0] - p2[0]); */
return ISECT_TRUE;
}
else if (p1[0] < x_level && p2[0] > x_level) {
- *y_isect = (p2[1] * (x_level - p1[0]) + p1[1] * (p2[0] - x_level)) / x_diff; /*(p2[0]-p1[0]);*/
+ *y_isect = (p2[1] * (x_level - p1[0]) + p1[1] * (p2[0] - x_level)) / x_diff; /* (p2[0] - p1[0]); */
return ISECT_TRUE;
}
else {
@@ -837,21 +935,19 @@ static bool cmp_uv(const float vec2a[2], const float vec2b[2])
* return zero if there is no area in the returned rectangle */
#ifndef PROJ_DEBUG_NOSEAMBLEED
static bool pixel_bounds_uv(
- const float uv1[2], const float uv2[2], const float uv3[2], const float uv4[2],
+ const float uv_quad[4][2],
rcti *bounds_px,
- const int ibuf_x, const int ibuf_y,
- const bool is_quad
+ const int ibuf_x, const int ibuf_y
)
{
float min_uv[2], max_uv[2]; /* UV bounds */
INIT_MINMAX2(min_uv, max_uv);
- minmax_v2v2_v2(min_uv, max_uv, uv1);
- minmax_v2v2_v2(min_uv, max_uv, uv2);
- minmax_v2v2_v2(min_uv, max_uv, uv3);
- if (is_quad)
- minmax_v2v2_v2(min_uv, max_uv, uv4);
+ minmax_v2v2_v2(min_uv, max_uv, uv_quad[0]);
+ minmax_v2v2_v2(min_uv, max_uv, uv_quad[1]);
+ minmax_v2v2_v2(min_uv, max_uv, uv_quad[2]);
+ minmax_v2v2_v2(min_uv, max_uv, uv_quad[3]);
bounds_px->xmin = (int)(ibuf_x * min_uv[0]);
bounds_px->ymin = (int)(ibuf_y * min_uv[1]);
@@ -895,82 +991,77 @@ static bool pixel_bounds_array(float (*uv)[2], rcti *bounds_px, const int ibuf_x
#ifndef PROJ_DEBUG_NOSEAMBLEED
-static void project_face_winding_init(const ProjPaintState *ps, const int face_index)
+static void project_face_winding_init(const ProjPaintState *ps, const int tri_index)
{
/* detect the winding of faces in uv space */
- MTFace *tf = ps->dm_mtface[face_index];
- float winding = cross_tri_v2(tf->uv[0], tf->uv[1], tf->uv[2]);
-
- if (ps->dm_mface[face_index].v4)
- winding += cross_tri_v2(tf->uv[2], tf->uv[3], tf->uv[0]);
+ const MLoopTri *lt = &ps->dm_mlooptri[tri_index];
+ const float *lt_tri_uv[3] = { PS_LOOPTRI_AS_UV_3(ps->dm_mloopuv, lt) };
+ float winding = cross_tri_v2(lt_tri_uv[0], lt_tri_uv[1], lt_tri_uv[2]);
if (winding > 0)
- ps->faceWindingFlags[face_index] |= PROJ_FACE_WINDING_CW;
+ ps->faceWindingFlags[tri_index] |= PROJ_FACE_WINDING_CW;
- ps->faceWindingFlags[face_index] |= PROJ_FACE_WINDING_INIT;
+ ps->faceWindingFlags[tri_index] |= PROJ_FACE_WINDING_INIT;
}
/* This function returns 1 if this face has a seam along the 2 face-vert indices
* 'orig_i1_fidx' and 'orig_i2_fidx' */
-static bool check_seam(const ProjPaintState *ps,
- const int orig_face, const int orig_i1_fidx, const int orig_i2_fidx,
- int *other_face, int *orig_fidx)
+static bool check_seam(
+ const ProjPaintState *ps,
+ const int orig_face, const int orig_i1_fidx, const int orig_i2_fidx,
+ int *other_face, int *orig_fidx)
{
+ const MLoopTri *orig_lt = &ps->dm_mlooptri[orig_face];
+ const float *orig_lt_tri_uv[3] = { PS_LOOPTRI_AS_UV_3(ps->dm_mloopuv, orig_lt) };
+ /* vert indices from face vert order indices */
+ const unsigned int i1 = ps->dm_mloop[orig_lt->tri[orig_i1_fidx]].v;
+ const unsigned int i2 = ps->dm_mloop[orig_lt->tri[orig_i2_fidx]].v;
LinkNode *node;
- int face_index;
- unsigned int i1, i2;
int i1_fidx = -1, i2_fidx = -1; /* index in face */
- MFace *mf;
- MTFace *tf;
- const MFace *orig_mf = ps->dm_mface + orig_face;
- const MTFace *orig_tf = ps->dm_mtface[orig_face];
-
- /* vert indices from face vert order indices */
- i1 = (*(&orig_mf->v1 + orig_i1_fidx));
- i2 = (*(&orig_mf->v1 + orig_i2_fidx));
for (node = ps->vertFaces[i1]; node; node = node->next) {
- face_index = GET_INT_FROM_POINTER(node->link);
+ const int tri_index = GET_INT_FROM_POINTER(node->link);
- if (face_index != orig_face) {
- mf = ps->dm_mface + face_index;
+ if (tri_index != orig_face) {
+ const MLoopTri *lt = &ps->dm_mlooptri[tri_index];
+ const int lt_vtri[3] = { PS_LOOPTRI_AS_VERT_INDEX_3(ps, lt) };
/* could check if the 2 faces images match here,
* but then there wouldn't be a way to return the opposite face's info */
/* We need to know the order of the verts in the adjacent face
* set the i1_fidx and i2_fidx to (0,1,2,3) */
- i1_fidx = BKE_MESH_TESSFACE_VINDEX_ORDER(mf, i1);
- i2_fidx = BKE_MESH_TESSFACE_VINDEX_ORDER(mf, i2);
+ i1_fidx = BKE_MESH_TESSTRI_VINDEX_ORDER(lt_vtri, i1);
+ i2_fidx = BKE_MESH_TESSTRI_VINDEX_ORDER(lt_vtri, i2);
/* Only need to check if 'i2_fidx' is valid because we know i1_fidx is the same vert on both faces */
if (i2_fidx != -1) {
- Image *tpage = project_paint_face_paint_image(ps, face_index);
+ const float *lt_tri_uv[3] = { PS_LOOPTRI_AS_UV_3(ps->dm_mloopuv, lt) };
+ Image *tpage = project_paint_face_paint_image(ps, tri_index);
Image *orig_tpage = project_paint_face_paint_image(ps, orig_face);
BLI_assert(i1_fidx != -1);
/* This IS an adjacent face!, now lets check if the UVs are ok */
- tf = ps->dm_mtface[face_index];
/* set up the other face */
- *other_face = face_index;
+ *other_face = tri_index;
- /* we check if difference is 1 here, else we might have a case of edge 2-0 or 3-0 for quads */
+ /* we check if difference is 1 here, else we might have a case of edge 2-0 for a tri */
*orig_fidx = (i1_fidx < i2_fidx && (i2_fidx - i1_fidx == 1)) ? i1_fidx : i2_fidx;
/* initialize face winding if needed */
- if ((ps->faceWindingFlags[face_index] & PROJ_FACE_WINDING_INIT) == 0)
- project_face_winding_init(ps, face_index);
+ if ((ps->faceWindingFlags[tri_index] & PROJ_FACE_WINDING_INIT) == 0)
+ project_face_winding_init(ps, tri_index);
/* first test if they have the same image */
if ((orig_tpage == tpage) &&
- cmp_uv(orig_tf->uv[orig_i1_fidx], tf->uv[i1_fidx]) &&
- cmp_uv(orig_tf->uv[orig_i2_fidx], tf->uv[i2_fidx]))
+ cmp_uv(orig_lt_tri_uv[orig_i1_fidx], lt_tri_uv[i1_fidx]) &&
+ cmp_uv(orig_lt_tri_uv[orig_i2_fidx], lt_tri_uv[i2_fidx]))
{
/* if faces don't have the same winding in uv space,
* they are on the same side so edge is boundary */
- if ((ps->faceWindingFlags[face_index] & PROJ_FACE_WINDING_CW) !=
+ if ((ps->faceWindingFlags[tri_index] & PROJ_FACE_WINDING_CW) !=
(ps->faceWindingFlags[orig_face] & PROJ_FACE_WINDING_CW))
{
return 1;
@@ -992,16 +1083,25 @@ static bool check_seam(const ProjPaintState *ps,
return 1;
}
+#define SMALL_NUMBER 1.e-6f
+BLI_INLINE float shell_v2v2_normal_dir_to_dist(float n[2], float d[2])
+{
+ const float angle_cos = (normalize_v2(n) < SMALL_NUMBER) ? fabsf(dot_v2v2(d, n)) : 0.0f;
+ return (UNLIKELY(angle_cos < SMALL_NUMBER)) ? 1.0f : (1.0f / angle_cos);
+}
+#undef SMALL_NUMBER
+
/* Calculate outset UV's, this is not the same as simply scaling the UVs,
* since the outset coords are a margin that keep an even distance from the original UV's,
* note that the image aspect is taken into account */
-static void uv_image_outset(float (*orig_uv)[2], float (*outset_uv)[2], const float scaler,
- const int ibuf_x, const int ibuf_y, const bool is_quad)
+static void uv_image_outset(
+ float (*orig_uv)[2], float (*outset_uv)[2], const float scaler,
+ const int ibuf_x, const int ibuf_y, const bool cw)
{
- float a1, a2, a3, a4 = 0.0f;
- float puv[4][2]; /* pixelspace uv's */
- float no1[2], no2[2], no3[2], no4[2]; /* normals */
- float dir1[2], dir2[2], dir3[2], dir4[2];
+ float a1, a2, a3;
+ float puv[3][2]; /* pixelspace uv's */
+ float no1[2], no2[2], no3[2]; /* normals */
+ float dir1[2], dir2[2], dir3[2];
float ibuf_inv[2];
ibuf_inv[0] = 1.0f / (float)ibuf_x;
@@ -1017,80 +1117,47 @@ static void uv_image_outset(float (*orig_uv)[2], float (*outset_uv)[2], const fl
puv[2][0] = orig_uv[2][0] * ibuf_x;
puv[2][1] = orig_uv[2][1] * ibuf_y;
- if (is_quad) {
- puv[3][0] = orig_uv[3][0] * ibuf_x;
- puv[3][1] = orig_uv[3][1] * ibuf_y;
- }
-
/* face edge directions */
sub_v2_v2v2(dir1, puv[1], puv[0]);
sub_v2_v2v2(dir2, puv[2], puv[1]);
+ sub_v2_v2v2(dir3, puv[0], puv[2]);
normalize_v2(dir1);
normalize_v2(dir2);
-
- if (is_quad) {
- sub_v2_v2v2(dir3, puv[3], puv[2]);
- sub_v2_v2v2(dir4, puv[0], puv[3]);
- normalize_v2(dir3);
- normalize_v2(dir4);
- }
- else {
- sub_v2_v2v2(dir3, puv[0], puv[2]);
- normalize_v2(dir3);
- }
-
- if (is_quad) {
- a1 = shell_v2v2_mid_normalized_to_dist(dir4, dir1);
- a2 = shell_v2v2_mid_normalized_to_dist(dir1, dir2);
- a3 = shell_v2v2_mid_normalized_to_dist(dir2, dir3);
- a4 = shell_v2v2_mid_normalized_to_dist(dir3, dir4);
- }
- else {
- a1 = shell_v2v2_mid_normalized_to_dist(dir3, dir1);
- a2 = shell_v2v2_mid_normalized_to_dist(dir1, dir2);
- a3 = shell_v2v2_mid_normalized_to_dist(dir2, dir3);
- }
-
- if (is_quad) {
- sub_v2_v2v2(no1, dir4, dir1);
- sub_v2_v2v2(no2, dir1, dir2);
- sub_v2_v2v2(no3, dir2, dir3);
- sub_v2_v2v2(no4, dir3, dir4);
- normalize_v2(no1);
- normalize_v2(no2);
- normalize_v2(no3);
- normalize_v2(no4);
- mul_v2_fl(no1, a1 * scaler);
- mul_v2_fl(no2, a2 * scaler);
- mul_v2_fl(no3, a3 * scaler);
- mul_v2_fl(no4, a4 * scaler);
- add_v2_v2v2(outset_uv[0], puv[0], no1);
- add_v2_v2v2(outset_uv[1], puv[1], no2);
- add_v2_v2v2(outset_uv[2], puv[2], no3);
- add_v2_v2v2(outset_uv[3], puv[3], no4);
- mul_v2_v2(outset_uv[0], ibuf_inv);
- mul_v2_v2(outset_uv[1], ibuf_inv);
- mul_v2_v2(outset_uv[2], ibuf_inv);
- mul_v2_v2(outset_uv[3], ibuf_inv);
+ normalize_v2(dir3);
+
+ /* here we just use the orthonormality property (a1, a2) dot (a2, -a1) = 0
+ * to get normals from the edge directions based on the winding */
+ if (cw) {
+ no1[0] = -dir3[1] - dir1[1];
+ no1[1] = dir3[0] + dir1[0];
+ no2[0] = -dir1[1] - dir2[1];
+ no2[1] = dir1[0] + dir2[0];
+ no3[0] = -dir2[1] - dir3[1];
+ no3[1] = dir2[0] + dir3[0];
}
else {
- sub_v2_v2v2(no1, dir3, dir1);
- sub_v2_v2v2(no2, dir1, dir2);
- sub_v2_v2v2(no3, dir2, dir3);
- normalize_v2(no1);
- normalize_v2(no2);
- normalize_v2(no3);
- mul_v2_fl(no1, a1 * scaler);
- mul_v2_fl(no2, a2 * scaler);
- mul_v2_fl(no3, a3 * scaler);
- add_v2_v2v2(outset_uv[0], puv[0], no1);
- add_v2_v2v2(outset_uv[1], puv[1], no2);
- add_v2_v2v2(outset_uv[2], puv[2], no3);
-
- mul_v2_v2(outset_uv[0], ibuf_inv);
- mul_v2_v2(outset_uv[1], ibuf_inv);
- mul_v2_v2(outset_uv[2], ibuf_inv);
- }
+ no1[0] = dir3[1] + dir1[1];
+ no1[1] = -dir3[0] - dir1[0];
+ no2[0] = dir1[1] + dir2[1];
+ no2[1] = -dir1[0] - dir2[0];
+ no3[0] = dir2[1] + dir3[1];
+ no3[1] = -dir2[0] - dir3[0];
+ }
+
+ a1 = shell_v2v2_normal_dir_to_dist(no1, dir3);
+ a2 = shell_v2v2_normal_dir_to_dist(no2, dir1);
+ a3 = shell_v2v2_normal_dir_to_dist(no3, dir2);
+
+ mul_v2_fl(no1, a1 * scaler);
+ mul_v2_fl(no2, a2 * scaler);
+ mul_v2_fl(no3, a3 * scaler);
+ add_v2_v2v2(outset_uv[0], puv[0], no1);
+ add_v2_v2v2(outset_uv[1], puv[1], no2);
+ add_v2_v2v2(outset_uv[2], puv[2], no3);
+
+ mul_v2_v2(outset_uv[0], ibuf_inv);
+ mul_v2_v2(outset_uv[1], ibuf_inv);
+ mul_v2_v2(outset_uv[2], ibuf_inv);
}
/*
@@ -1099,25 +1166,25 @@ static void uv_image_outset(float (*orig_uv)[2], float (*outset_uv)[2], const fl
*
* If we're multithreadng, make sure threads are locked when this is called
*/
-static void project_face_seams_init(const ProjPaintState *ps, const int face_index, const int is_quad)
+static void project_face_seams_init(const ProjPaintState *ps, const int tri_index)
{
int other_face, other_fidx; /* vars for the other face, we also set its flag */
- int fidx1 = is_quad ? 3 : 2;
+ int fidx1 = 2;
int fidx2 = 0; /* next fidx in the face (0,1,2,3) -> (1,2,3,0) or (0,1,2) -> (1,2,0) for a tri */
/* initialize face winding if needed */
- if ((ps->faceWindingFlags[face_index] & PROJ_FACE_WINDING_INIT) == 0)
- project_face_winding_init(ps, face_index);
+ if ((ps->faceWindingFlags[tri_index] & PROJ_FACE_WINDING_INIT) == 0)
+ project_face_winding_init(ps, tri_index);
do {
- if ((ps->faceSeamFlags[face_index] & (1 << fidx1 | 16 << fidx1)) == 0) {
- if (check_seam(ps, face_index, fidx1, fidx2, &other_face, &other_fidx)) {
- ps->faceSeamFlags[face_index] |= 1 << fidx1;
+ if ((ps->faceSeamFlags[tri_index] & (1 << fidx1 | 16 << fidx1)) == 0) {
+ if (check_seam(ps, tri_index, fidx1, fidx2, &other_face, &other_fidx)) {
+ ps->faceSeamFlags[tri_index] |= 1 << fidx1;
if (other_face != -1)
ps->faceSeamFlags[other_face] |= 1 << other_fidx;
}
else {
- ps->faceSeamFlags[face_index] |= 16 << fidx1;
+ ps->faceSeamFlags[tri_index] |= 16 << fidx1;
if (other_face != -1)
ps->faceSeamFlags[other_face] |= 16 << other_fidx; /* second 4 bits for disabled */
}
@@ -1181,28 +1248,66 @@ static void screen_px_from_persp(
}
-static void project_face_pixel(const MTFace *tf_other, ImBuf *ibuf_other, const float w[3],
- int side, unsigned char rgba_ub[4], float rgba_f[4])
+/**
+ * Set a direction vector based on a screen location.
+ * (use for perspective view, else we can simply use `ps->viewDir`)
+ *
+ * Similar functionality to #ED_view3d_win_to_vector
+ *
+ * \param r_dir: Resulting direction (length is undefined).
+ */
+static void screen_px_to_vector_persp(
+ int winx, int winy, const float projmat_inv[4][4], const float view_pos[3],
+ const float co_px[2],
+ float r_dir[3])
{
- const float *uvCo1, *uvCo2, *uvCo3;
- float uv_other[2], x, y;
+ r_dir[0] = 2.0f * (co_px[0] / winx) - 1.0f;
+ r_dir[1] = 2.0f * (co_px[1] / winy) - 1.0f;
+ r_dir[2] = -0.5f;
+ mul_project_m4_v3((float(*)[4])projmat_inv, r_dir);
+ sub_v3_v3(r_dir, view_pos);
+}
- uvCo1 = (float *)tf_other->uv[0];
- if (side == 1) {
- uvCo2 = (float *)tf_other->uv[2];
- uvCo3 = (float *)tf_other->uv[3];
- }
- else {
- uvCo2 = (float *)tf_other->uv[1];
- uvCo3 = (float *)tf_other->uv[2];
- }
+/**
+ * Special function to return the factor to a point along a line in pixel space.
+ *
+ * This is needed since we can't use #line_point_factor_v2 for perspective screen-space coords.
+ *
+ * \param p: 2D screen-space location.
+ * \param v1, v2: 3D object-space locations.
+ */
+static float screen_px_line_point_factor_v2_persp(
+ const ProjPaintState *ps,
+ const float p[2],
+ const float v1[3], const float v2[3])
+{
+ const float zero[3] = {0};
+ float v1_proj[3], v2_proj[3];
+ float dir[3];
+
+ screen_px_to_vector_persp(ps->winx, ps->winy, ps->projectMatInv, ps->viewPos, p, dir);
- interp_v2_v2v2v2(uv_other, uvCo1, uvCo2, uvCo3, (float *)w);
+ sub_v3_v3v3(v1_proj, v1, ps->viewPos);
+ sub_v3_v3v3(v2_proj, v2, ps->viewPos);
+
+ project_plane_v3_v3v3(v1_proj, v1_proj, dir);
+ project_plane_v3_v3v3(v2_proj, v2_proj, dir);
+
+ return line_point_factor_v2(zero, v1_proj, v2_proj);
+}
+
+
+static void project_face_pixel(
+ const float *lt_tri_uv[3], ImBuf *ibuf_other, const float w[3],
+ unsigned char rgba_ub[4], float rgba_f[4])
+{
+ float uv_other[2], x, y;
+
+ interp_v2_v2v2v2(uv_other, UNPACK3(lt_tri_uv), w);
/* use */
uvco_to_wrapped_pxco(uv_other, ibuf_other->x, ibuf_other->y, &x, &y);
-
if (ibuf_other->rect_float) { /* from float to float */
bilinear_interpolation_color_wrap(ibuf_other, NULL, rgba_f, x, y);
}
@@ -1215,8 +1320,7 @@ static void project_face_pixel(const MTFace *tf_other, ImBuf *ibuf_other, const
/* run this outside project_paint_uvpixel_init since pixels with mask 0 don't need init */
static float project_paint_uvpixel_mask(
const ProjPaintState *ps,
- const int face_index,
- const int side,
+ const int tri_index,
const float w[3])
{
float mask;
@@ -1226,14 +1330,16 @@ static float project_paint_uvpixel_mask(
/* another UV maps image is masking this one's */
ImBuf *ibuf_other;
Image *other_tpage = ps->stencil_ima;
- const MTFace *tf_other = ps->dm_mtface_stencil + face_index;
if (other_tpage && (ibuf_other = BKE_image_acquire_ibuf(other_tpage, NULL, NULL))) {
+ const MLoopTri *lt_other = &ps->dm_mlooptri[tri_index];
+ const float *lt_other_tri_uv[3] = { PS_LOOPTRI_AS_UV_3(ps->dm_mloopuv, lt_other) };
+
/* BKE_image_acquire_ibuf - TODO - this may be slow */
unsigned char rgba_ub[4];
float rgba_f[4];
- project_face_pixel(tf_other, ibuf_other, w, side, rgba_ub, rgba_f);
+ project_face_pixel(lt_other_tri_uv, ibuf_other, w, rgba_ub, rgba_f);
if (ibuf_other->rect_float) { /* from float to float */
mask = ((rgba_f[0] + rgba_f[1] + rgba_f[2]) * (1.0f / 3.0f)) * rgba_f[3];
@@ -1259,21 +1365,32 @@ static float project_paint_uvpixel_mask(
mask = 1.0f;
}
+ if (ps->do_mask_cavity) {
+ const MLoopTri *lt = &ps->dm_mlooptri[tri_index];
+ const int lt_vtri[3] = { PS_LOOPTRI_AS_VERT_INDEX_3(ps, lt) };
+ float ca1, ca2, ca3, ca_mask;
+ ca1 = ps->cavities[lt_vtri[0]];
+ ca2 = ps->cavities[lt_vtri[1]];
+ ca3 = ps->cavities[lt_vtri[2]];
+
+ ca_mask = w[0] * ca1 + w[1] * ca2 + w[2] * ca3;
+ ca_mask = curvemapping_evaluateF(ps->cavity_curve, 0, ca_mask);
+ CLAMP(ca_mask, 0.0f, 1.0f);
+ mask *= ca_mask;
+ }
+
/* calculate mask */
if (ps->do_mask_normal) {
- MFace *mf = &ps->dm_mface[face_index];
- float no[3], angle;
- if (mf->flag & ME_SMOOTH) {
+ const MLoopTri *lt = &ps->dm_mlooptri[tri_index];
+ const int lt_vtri[3] = { PS_LOOPTRI_AS_VERT_INDEX_3(ps, lt) };
+ const MPoly *mp = &ps->dm_mpoly[lt->poly];
+ float no[3], angle_cos;
+
+ if (mp->flag & ME_SMOOTH) {
const short *no1, *no2, *no3;
- no1 = ps->dm_mvert[mf->v1].no;
- if (side == 1) {
- no2 = ps->dm_mvert[mf->v3].no;
- no3 = ps->dm_mvert[mf->v4].no;
- }
- else {
- no2 = ps->dm_mvert[mf->v2].no;
- no3 = ps->dm_mvert[mf->v3].no;
- }
+ no1 = ps->dm_mvert[lt_vtri[0]].no;
+ no2 = ps->dm_mvert[lt_vtri[1]].no;
+ no3 = ps->dm_mvert[lt_vtri[2]].no;
no[0] = w[0] * no1[0] + w[1] * no2[0] + w[2] * no3[0];
no[1] = w[0] * no1[1] + w[1] * no2[1] + w[2] * no3[1];
@@ -1284,55 +1401,49 @@ static float project_paint_uvpixel_mask(
/* incase the */
#if 1
/* normalizing per pixel isn't optimal, we could cache or check ps->*/
- if (mf->v4)
- normal_quad_v3(no,
- ps->dm_mvert[mf->v1].co,
- ps->dm_mvert[mf->v2].co,
- ps->dm_mvert[mf->v3].co,
- ps->dm_mvert[mf->v4].co);
- else
- normal_tri_v3(no,
- ps->dm_mvert[mf->v1].co,
- ps->dm_mvert[mf->v2].co,
- ps->dm_mvert[mf->v3].co);
+ normal_tri_v3(no,
+ ps->dm_mvert[lt_vtri[0]].co,
+ ps->dm_mvert[lt_vtri[1]].co,
+ ps->dm_mvert[lt_vtri[2]].co);
#else
/* don't use because some modifiers dont have normal data (subsurf for eg) */
- copy_v3_v3(no, (float *)ps->dm->getTessFaceData(ps->dm, face_index, CD_NORMAL));
+ copy_v3_v3(no, (float *)ps->dm->getTessFaceData(ps->dm, tri_index, CD_NORMAL));
#endif
}
+ if (UNLIKELY(ps->is_flip_object)) {
+ negate_v3(no);
+ }
+
/* now we can use the normal as a mask */
if (ps->is_ortho) {
- angle = angle_normalized_v3v3((float *)ps->viewDir, no);
+ angle_cos = dot_v3v3(ps->viewDir, no);
}
else {
/* Annoying but for the perspective view we need to get the pixels location in 3D space :/ */
float viewDirPersp[3];
const float *co1, *co2, *co3;
- co1 = ps->dm_mvert[mf->v1].co;
- if (side == 1) {
- co2 = ps->dm_mvert[mf->v3].co;
- co3 = ps->dm_mvert[mf->v4].co;
- }
- else {
- co2 = ps->dm_mvert[mf->v2].co;
- co3 = ps->dm_mvert[mf->v3].co;
- }
+ co1 = ps->dm_mvert[lt_vtri[0]].co;
+ co2 = ps->dm_mvert[lt_vtri[1]].co;
+ co3 = ps->dm_mvert[lt_vtri[2]].co;
/* Get the direction from the viewPoint to the pixel and normalize */
viewDirPersp[0] = (ps->viewPos[0] - (w[0] * co1[0] + w[1] * co2[0] + w[2] * co3[0]));
viewDirPersp[1] = (ps->viewPos[1] - (w[0] * co1[1] + w[1] * co2[1] + w[2] * co3[1]));
viewDirPersp[2] = (ps->viewPos[2] - (w[0] * co1[2] + w[1] * co2[2] + w[2] * co3[2]));
normalize_v3(viewDirPersp);
+ if (UNLIKELY(ps->is_flip_object)) {
+ negate_v3(viewDirPersp);
+ }
- angle = angle_normalized_v3v3(viewDirPersp, no);
+ angle_cos = dot_v3v3(viewDirPersp, no);
}
- if (angle >= ps->normal_angle) {
+ if (angle_cos <= ps->normal_angle__cos) {
return 0.0f; /* outsize the normal limit*/
}
- else if (angle > ps->normal_angle_inner) {
- mask *= (ps->normal_angle - angle) / ps->normal_angle_range;
+ else if (angle_cos < ps->normal_angle_inner__cos) {
+ mask *= (ps->normal_angle - acosf(angle_cos)) / ps->normal_angle_range;
} /* otherwise no mask normal is needed, were within the limit */
}
@@ -1375,10 +1486,14 @@ static int project_paint_undo_subtiles(const TileInfo *tinf, int tx, int ty)
if (generate_tile) {
volatile void *undorect;
if (tinf->masked) {
- undorect = image_undo_push_tile(pjIma->ima, pjIma->ibuf, tinf->tmpibuf, tx, ty, &pjIma->maskRect[tile_index], &pjIma->valid[tile_index], true);
+ undorect = image_undo_push_tile(
+ pjIma->ima, pjIma->ibuf, tinf->tmpibuf,
+ tx, ty, &pjIma->maskRect[tile_index], &pjIma->valid[tile_index], true, false);
}
else {
- undorect = image_undo_push_tile(pjIma->ima, pjIma->ibuf, tinf->tmpibuf, tx, ty, NULL, &pjIma->valid[tile_index], true);
+ undorect = image_undo_push_tile(
+ pjIma->ima, pjIma->ibuf, tinf->tmpibuf,
+ tx, ty, NULL, &pjIma->valid[tile_index], true, false);
}
pjIma->ibuf->userflags |= IB_BITMAPDIRTY;
@@ -1402,10 +1517,9 @@ static ProjPixel *project_paint_uvpixel_init(
const TileInfo *tinf,
int x_px, int y_px,
const float mask,
- const int face_index,
+ const int tri_index,
const float pixelScreenCo[4],
const float world_spaceCo[3],
- const int side,
const float w[3])
{
ProjPixel *projPixel;
@@ -1423,7 +1537,7 @@ static ProjPixel *project_paint_uvpixel_init(
y_px = mod_i(y_px, ibuf->y);
BLI_assert(ps->pixel_sizeof == project_paint_pixel_sizeof(ps->tool));
- projPixel = (ProjPixel *)BLI_memarena_alloc(arena, ps->pixel_sizeof);
+ projPixel = BLI_memarena_alloc(arena, ps->pixel_sizeof);
/* calculate the undo tile offset of the pixel, used to store the original
* pixel color and accumulated mask if any */
@@ -1479,22 +1593,24 @@ static ProjPixel *project_paint_uvpixel_init(
/* done with view3d_project_float inline */
if (ps->tool == PAINT_TOOL_CLONE) {
- if (ps->dm_mtface_clone) {
+ if (ps->dm_mloopuv_clone) {
ImBuf *ibuf_other;
- Image *other_tpage = project_paint_face_clone_image(ps, face_index);
- const MTFace *tf_other = ps->dm_mtface_clone[face_index];
+ Image *other_tpage = project_paint_face_clone_image(ps, tri_index);
if (other_tpage && (ibuf_other = BKE_image_acquire_ibuf(other_tpage, NULL, NULL))) {
+ const MLoopTri *lt_other = &ps->dm_mlooptri[tri_index];
+ const float *lt_other_tri_uv[3] = { PS_LOOPTRI_AS_UV_3(ps->dm_mloopuv_clone, lt_other) };
+
/* BKE_image_acquire_ibuf - TODO - this may be slow */
if (ibuf->rect_float) {
if (ibuf_other->rect_float) { /* from float to float */
- project_face_pixel(tf_other, ibuf_other, w, side, NULL, ((ProjPixelClone *)projPixel)->clonepx.f);
+ project_face_pixel(lt_other_tri_uv, ibuf_other, w, NULL, ((ProjPixelClone *)projPixel)->clonepx.f);
}
else { /* from char to float */
unsigned char rgba_ub[4];
float rgba[4];
- project_face_pixel(tf_other, ibuf_other, w, side, rgba_ub, NULL);
+ project_face_pixel(lt_other_tri_uv, ibuf_other, w, rgba_ub, NULL);
srgb_to_linearrgb_uchar4(rgba, rgba_ub);
straight_to_premul_v4_v4(((ProjPixelClone *)projPixel)->clonepx.f, rgba);
}
@@ -1502,12 +1618,13 @@ static ProjPixel *project_paint_uvpixel_init(
else {
if (ibuf_other->rect_float) { /* float to char */
float rgba[4];
- project_face_pixel(tf_other, ibuf_other, w, side, NULL, rgba);
+ project_face_pixel(lt_other_tri_uv, ibuf_other, w, NULL, rgba);
premul_to_straight_v4(rgba);
linearrgb_to_srgb_uchar3(((ProjPixelClone *)projPixel)->clonepx.ch, rgba);
+ ((ProjPixelClone *)projPixel)->clonepx.ch[3] = rgba[3] * 255;
}
else { /* char to char */
- project_face_pixel(tf_other, ibuf_other, w, side, ((ProjPixelClone *)projPixel)->clonepx.ch, NULL);
+ project_face_pixel(lt_other_tri_uv, ibuf_other, w, ((ProjPixelClone *)projPixel)->clonepx.ch, NULL);
}
}
@@ -1525,7 +1642,7 @@ static ProjPixel *project_paint_uvpixel_init(
}
else {
float co[2];
- sub_v2_v2v2(co, projPixel->projCoSS, (float *)ps->cloneOffset);
+ sub_v2_v2v2(co, projPixel->projCoSS, ps->cloneOffset);
/* no need to initialize the bucket, we're only checking buckets faces and for this
* the faces are already initialized in project_paint_delayed_face_init(...) */
@@ -1553,13 +1670,14 @@ static ProjPixel *project_paint_uvpixel_init(
}
static bool line_clip_rect2f(
- rctf *rect,
+ const rctf *cliprect,
+ const rctf *rect,
const float l1[2], const float l2[2],
float l1_clip[2], float l2_clip[2])
{
/* first account for horizontal, then vertical lines */
/* horiz */
- if (fabsf(l1[1] - l2[1]) < PROJ_GEOM_TOLERANCE) {
+ if (fabsf(l1[1] - l2[1]) < PROJ_PIXEL_TOLERANCE) {
/* is the line out of range on its Y axis? */
if (l1[1] < rect->ymin || l1[1] > rect->ymax) {
return 0;
@@ -1570,7 +1688,7 @@ static bool line_clip_rect2f(
}
- if (fabsf(l1[0] - l2[0]) < PROJ_GEOM_TOLERANCE) { /* this is a single point (or close to)*/
+ if (fabsf(l1[0] - l2[0]) < PROJ_PIXEL_TOLERANCE) { /* this is a single point (or close to)*/
if (BLI_rctf_isect_pt_v(rect, l1)) {
copy_v2_v2(l1_clip, l1);
copy_v2_v2(l2_clip, l2);
@@ -1587,7 +1705,7 @@ static bool line_clip_rect2f(
CLAMP(l2_clip[0], rect->xmin, rect->xmax);
return 1;
}
- else if (fabsf(l1[0] - l2[0]) < PROJ_GEOM_TOLERANCE) {
+ else if (fabsf(l1[0] - l2[0]) < PROJ_PIXEL_TOLERANCE) {
/* is the line out of range on its X axis? */
if (l1[0] < rect->xmin || l1[0] > rect->xmax) {
return 0;
@@ -1598,7 +1716,7 @@ static bool line_clip_rect2f(
return 0;
}
- if (fabsf(l1[1] - l2[1]) < PROJ_GEOM_TOLERANCE) { /* this is a single point (or close to)*/
+ if (fabsf(l1[1] - l2[1]) < PROJ_PIXEL_TOLERANCE) { /* this is a single point (or close to)*/
if (BLI_rctf_isect_pt_v(rect, l1)) {
copy_v2_v2(l1_clip, l1);
copy_v2_v2(l2_clip, l2);
@@ -1637,7 +1755,7 @@ static bool line_clip_rect2f(
if (ok1 && ok2) return 1;
/* top/bottom */
- if (line_isect_y(l1, l2, rect->ymin, &isect) && (isect >= rect->xmin) && (isect <= rect->xmax)) {
+ if (line_isect_y(l1, l2, rect->ymin, &isect) && (isect >= cliprect->xmin) && (isect <= cliprect->xmax)) {
if (l1[1] < l2[1]) { /* line 1 is outside */
l1_clip[0] = isect;
l1_clip[1] = rect->ymin;
@@ -1652,7 +1770,7 @@ static bool line_clip_rect2f(
if (ok1 && ok2) return 1;
- if (line_isect_y(l1, l2, rect->ymax, &isect) && (isect >= rect->xmin) && (isect <= rect->xmax)) {
+ if (line_isect_y(l1, l2, rect->ymax, &isect) && (isect >= cliprect->xmin) && (isect <= cliprect->xmax)) {
if (l1[1] > l2[1]) { /* line 1 is outside */
l1_clip[0] = isect;
l1_clip[1] = rect->ymax;
@@ -1668,7 +1786,7 @@ static bool line_clip_rect2f(
if (ok1 && ok2) return 1;
/* left/right */
- if (line_isect_x(l1, l2, rect->xmin, &isect) && (isect >= rect->ymin) && (isect <= rect->ymax)) {
+ if (line_isect_x(l1, l2, rect->xmin, &isect) && (isect >= cliprect->ymin) && (isect <= cliprect->ymax)) {
if (l1[0] < l2[0]) { /* line 1 is outside */
l1_clip[0] = rect->xmin;
l1_clip[1] = isect;
@@ -1683,7 +1801,7 @@ static bool line_clip_rect2f(
if (ok1 && ok2) return 1;
- if (line_isect_x(l1, l2, rect->xmax, &isect) && (isect >= rect->ymin) && (isect <= rect->ymax)) {
+ if (line_isect_x(l1, l2, rect->xmax, &isect) && (isect >= cliprect->ymin) && (isect <= cliprect->ymax)) {
if (l1[0] > l2[0]) { /* line 1 is outside */
l1_clip[0] = rect->xmax;
l1_clip[1] = isect;
@@ -1707,35 +1825,14 @@ static bool line_clip_rect2f(
-/* scale the quad & tri about its center
- * scaling by PROJ_FACE_SCALE_SEAM (0.99x) is used for getting fake UV pixel coords that are on the
- * edge of the face but slightly inside it occlusion tests don't return hits on adjacent faces */
+/**
+ * Scale the tri about its center
+ * scaling by #PROJ_FACE_SCALE_SEAM (0.99x) is used for getting fake UV pixel coords that are on the
+ * edge of the face but slightly inside it occlusion tests don't return hits on adjacent faces
+ */
#ifndef PROJ_DEBUG_NOSEAMBLEED
-static void scale_quad(float insetCos[4][3], float *origCos[4], const float inset)
-{
- float cent[3];
- cent[0] = (origCos[0][0] + origCos[1][0] + origCos[2][0] + origCos[3][0]) * (1.0f / 4.0f);
- cent[1] = (origCos[0][1] + origCos[1][1] + origCos[2][1] + origCos[3][1]) * (1.0f / 4.0f);
- cent[2] = (origCos[0][2] + origCos[1][2] + origCos[2][2] + origCos[3][2]) * (1.0f / 4.0f);
-
- sub_v3_v3v3(insetCos[0], origCos[0], cent);
- sub_v3_v3v3(insetCos[1], origCos[1], cent);
- sub_v3_v3v3(insetCos[2], origCos[2], cent);
- sub_v3_v3v3(insetCos[3], origCos[3], cent);
-
- mul_v3_fl(insetCos[0], inset);
- mul_v3_fl(insetCos[1], inset);
- mul_v3_fl(insetCos[2], inset);
- mul_v3_fl(insetCos[3], inset);
-
- add_v3_v3(insetCos[0], cent);
- add_v3_v3(insetCos[1], cent);
- add_v3_v3(insetCos[2], cent);
- add_v3_v3(insetCos[3], cent);
-}
-
-static void scale_tri(float insetCos[4][3], float *origCos[4], const float inset)
+static void scale_tri(float insetCos[3][3], const float *origCos[4], const float inset)
{
float cent[3];
cent[0] = (origCos[0][0] + origCos[1][0] + origCos[2][0]) * (1.0f / 3.0f);
@@ -1768,7 +1865,7 @@ static float len_squared_v2v2_alt(const float v1[2], const float v2_1, const flo
/* note, use a squared value so we can use len_squared_v2v2
* be sure that you have done a bounds check first or this may fail */
/* only give bucket_bounds as an arg because we need it elsewhere */
-static bool project_bucket_isect_circle(const float cent[2], const float radius_squared, rctf *bucket_bounds)
+static bool project_bucket_isect_circle(const float cent[2], const float radius_squared, const rctf *bucket_bounds)
{
/* Would normally to a simple intersection test, however we know the bounds of these 2 already intersect
@@ -1823,7 +1920,7 @@ static bool project_bucket_isect_circle(const float cent[2], const float radius_
* however switching back to this for ortho is always an option */
static void rect_to_uvspace_ortho(
- rctf *bucket_bounds,
+ const rctf *bucket_bounds,
const float *v1coSS, const float *v2coSS, const float *v3coSS,
const float *uv1co, const float *uv2co, const float *uv3co,
float bucket_bounds_uv[4][2],
@@ -1856,7 +1953,7 @@ static void rect_to_uvspace_ortho(
/* same as above but use barycentric_weights_v2_persp */
static void rect_to_uvspace_persp(
- rctf *bucket_bounds,
+ const rctf *bucket_bounds,
const float *v1coSS, const float *v2coSS, const float *v3coSS,
const float *uv1co, const float *uv2co, const float *uv3co,
float bucket_bounds_uv[4][2],
@@ -1898,7 +1995,7 @@ static float angle_2d_clockwise(const float p1[2], const float p2[2], const floa
v1[0] = p1[0] - p2[0]; v1[1] = p1[1] - p2[1];
v2[0] = p3[0] - p2[0]; v2[1] = p3[1] - p2[1];
- return -atan2(v1[0] * v2[1] - v1[1] * v2[0], v1[0] * v2[0] + v1[1] * v2[1]);
+ return -atan2f(v1[0] * v2[1] - v1[1] * v2[0], v1[0] * v2[0] + v1[1] * v2[1]);
}
#endif
@@ -1910,7 +2007,10 @@ static float angle_2d_clockwise(const float p1[2], const float p2[2], const floa
#define ISECT_ALL4 ((1 << 4) - 1)
/* limit must be a fraction over 1.0f */
-static bool IsectPT2Df_limit(float pt[2], float v1[2], float v2[2], float v3[2], float limit)
+static bool IsectPT2Df_limit(
+ const float pt[2],
+ const float v1[2], const float v2[2], const float v3[2],
+ const float limit)
{
return ((area_tri_v2(pt, v1, v2) +
area_tri_v2(pt, v2, v3) +
@@ -1930,27 +2030,88 @@ static int float_z_sort(const void *p1, const void *p2)
return (((float *)p1)[2] < ((float *)p2)[2] ? -1 : 1);
}
+/* assumes one point is within the rectangle */
+static bool line_rect_clip(
+ const rctf *rect,
+ const float l1[4], const float l2[4],
+ const float uv1[2], const float uv2[2],
+ float uv[2], bool is_ortho)
+{
+ float min = FLT_MAX, tmp;
+ float xlen = l2[0] - l1[0];
+ float ylen = l2[1] - l1[1];
+
+ /* 0.1 might seem too much, but remember, this is pixels! */
+ if (xlen > 0.1f) {
+ if ((l1[0] - rect->xmin) * (l2[0] - rect->xmin) <= 0) {
+ tmp = rect->xmin;
+ min = min_ff((tmp - l1[0]) / xlen, min);
+ }
+ else if ((l1[0] - rect->xmax) * (l2[0] - rect->xmax) < 0) {
+ tmp = rect->xmax;
+ min = min_ff((tmp - l1[0]) / xlen, min);
+ }
+ }
+
+ if (ylen > 0.1f) {
+ if ((l1[1] - rect->ymin) * (l2[1] - rect->ymin) <= 0) {
+ tmp = rect->ymin;
+ min = min_ff((tmp - l1[1]) / ylen, min);
+ }
+ else if ((l1[1] - rect->ymax) * (l2[1] - rect->ymax) < 0) {
+ tmp = rect->ymax;
+ min = min_ff((tmp - l1[1]) / ylen, min);
+ }
+ }
+
+ if (min == FLT_MAX)
+ return false;
+
+ tmp = (is_ortho) ? 1.0f : (l1[3] + min * (l2[3] - l1[3]));
+
+ uv[0] = (uv1[0] + min / tmp * (uv2[0] - uv1[0]));
+ uv[1] = (uv1[1] + min / tmp * (uv2[1] - uv1[1]));
+
+ return true;
+}
+
+
static void project_bucket_clip_face(
- const bool is_ortho,
- rctf *bucket_bounds,
- float *v1coSS, float *v2coSS, float *v3coSS,
+ const bool is_ortho, const bool is_flip_object,
+ const rctf *cliprect,
+ const rctf *bucket_bounds,
+ const float *v1coSS, const float *v2coSS, const float *v3coSS,
const float *uv1co, const float *uv2co, const float *uv3co,
float bucket_bounds_uv[8][2],
- int *tot)
+ int *tot, bool cull)
{
int inside_bucket_flag = 0;
int inside_face_flag = 0;
- const int flip = ((line_point_side_v2(v1coSS, v2coSS, v3coSS) > 0.0f) != (line_point_side_v2(uv1co, uv2co, uv3co) > 0.0f));
-
+ int flip;
+ bool collinear = false;
+
float bucket_bounds_ss[4][2];
+ /* detect pathological case where face the three vertices are almost collinear in screen space.
+ * mostly those will be culled but when flood filling or with smooth shading it's a possibility */
+ if (dist_squared_to_line_v2(v1coSS, v2coSS, v3coSS) < 0.5f ||
+ dist_squared_to_line_v2(v2coSS, v3coSS, v1coSS) < 0.5f)
+ {
+ collinear = true;
+ }
+
/* get the UV space bounding box */
inside_bucket_flag |= BLI_rctf_isect_pt_v(bucket_bounds, v1coSS);
inside_bucket_flag |= BLI_rctf_isect_pt_v(bucket_bounds, v2coSS) << 1;
inside_bucket_flag |= BLI_rctf_isect_pt_v(bucket_bounds, v3coSS) << 2;
-
+
if (inside_bucket_flag == ISECT_ALL3) {
- /* all screenspace points are inside the bucket bounding box, this means we don't need to clip and can simply return the UVs */
+ /* is_flip_object is used here because we use the face winding */
+ flip = (((line_point_side_v2(v1coSS, v2coSS, v3coSS) > 0.0f) != is_flip_object) !=
+ (line_point_side_v2(uv1co, uv2co, uv3co) > 0.0f));
+
+ /* all screenspace points are inside the bucket bounding box,
+ * this means we don't need to clip and can simply return the UVs */
if (flip) { /* facing the back? */
copy_v2_v2(bucket_bounds_uv[0], uv3co);
copy_v2_v2(bucket_bounds_uv[1], uv2co);
@@ -1960,9 +2121,55 @@ static void project_bucket_clip_face(
copy_v2_v2(bucket_bounds_uv[0], uv1co);
copy_v2_v2(bucket_bounds_uv[1], uv2co);
copy_v2_v2(bucket_bounds_uv[2], uv3co);
+ }
+
+ *tot = 3;
+ return;
+ }
+ /* handle pathological case here, no need for further intersections below since tringle area is almost zero */
+ if (collinear) {
+ int flag;
+
+ (*tot) = 0;
+
+ if (cull)
+ return;
+
+ if (inside_bucket_flag & ISECT_1) { copy_v2_v2(bucket_bounds_uv[*tot], uv1co); (*tot)++; }
+
+ flag = inside_bucket_flag & (ISECT_1 | ISECT_2);
+ if (flag && flag != (ISECT_1 | ISECT_2)) {
+ if (line_rect_clip(bucket_bounds, v1coSS, v2coSS, uv1co, uv2co, bucket_bounds_uv[*tot], is_ortho))
+ (*tot)++;
+ }
+
+ if (inside_bucket_flag & ISECT_2) { copy_v2_v2(bucket_bounds_uv[*tot], uv2co); (*tot)++; }
+
+ flag = inside_bucket_flag & (ISECT_2 | ISECT_3);
+ if (flag && flag != (ISECT_2 | ISECT_3)) {
+ if (line_rect_clip(bucket_bounds, v2coSS, v3coSS, uv2co, uv3co, bucket_bounds_uv[*tot], is_ortho))
+ (*tot)++;
+ }
+
+ if (inside_bucket_flag & ISECT_3) { copy_v2_v2(bucket_bounds_uv[*tot], uv3co); (*tot)++; }
+
+ flag = inside_bucket_flag & (ISECT_3 | ISECT_1);
+ if (flag && flag != (ISECT_3 | ISECT_1)) {
+ if (line_rect_clip(bucket_bounds, v3coSS, v1coSS, uv3co, uv1co, bucket_bounds_uv[*tot], is_ortho))
+ (*tot)++;
+ }
+
+ if ((*tot) < 3) {
+ /* no intersections to speak of, but more probable is that all face is just outside the
+ * rectangle and culled due to float precision issues. Since above teste have failed,
+ * just dump triangle as is for painting */
+ *tot = 0;
+ copy_v2_v2(bucket_bounds_uv[*tot], uv1co); (*tot)++;
+ copy_v2_v2(bucket_bounds_uv[*tot], uv2co); (*tot)++;
+ copy_v2_v2(bucket_bounds_uv[*tot], uv3co); (*tot)++;
+ return;
}
- *tot = 3;
return;
}
@@ -1984,11 +2191,18 @@ static void project_bucket_clip_face(
bucket_bounds_ss[3][1] = bucket_bounds->ymin;
inside_face_flag |= (IsectPT2Df_limit(bucket_bounds_ss[3], v1coSS, v2coSS, v3coSS, 1 + PROJ_GEOM_TOLERANCE) ? ISECT_4 : 0);
+ flip = ((line_point_side_v2(v1coSS, v2coSS, v3coSS) > 0.0f) !=
+ (line_point_side_v2(uv1co, uv2co, uv3co) > 0.0f));
+
if (inside_face_flag == ISECT_ALL4) {
/* bucket is totally inside the screenspace face, we can safely use weights */
- if (is_ortho) rect_to_uvspace_ortho(bucket_bounds, v1coSS, v2coSS, v3coSS, uv1co, uv2co, uv3co, bucket_bounds_uv, flip);
- else rect_to_uvspace_persp(bucket_bounds, v1coSS, v2coSS, v3coSS, uv1co, uv2co, uv3co, bucket_bounds_uv, flip);
+ if (is_ortho) {
+ rect_to_uvspace_ortho(bucket_bounds, v1coSS, v2coSS, v3coSS, uv1co, uv2co, uv3co, bucket_bounds_uv, flip);
+ }
+ else {
+ rect_to_uvspace_persp(bucket_bounds, v1coSS, v2coSS, v3coSS, uv1co, uv2co, uv3co, bucket_bounds_uv, flip);
+ }
*tot = 4;
return;
@@ -2019,7 +2233,7 @@ static void project_bucket_clip_face(
float cent[2] = {0.0f, 0.0f};
/*float up[2] = {0.0f, 1.0f};*/
int i;
- short doubles;
+ bool doubles;
(*tot) = 0;
@@ -2033,21 +2247,21 @@ static void project_bucket_clip_face(
if (inside_bucket_flag & ISECT_3) { copy_v2_v2(isectVCosSS[*tot], v3coSS); (*tot)++; }
if ((inside_bucket_flag & (ISECT_1 | ISECT_2)) != (ISECT_1 | ISECT_2)) {
- if (line_clip_rect2f(bucket_bounds, v1coSS, v2coSS, v1_clipSS, v2_clipSS)) {
+ if (line_clip_rect2f(cliprect, bucket_bounds, v1coSS, v2coSS, v1_clipSS, v2_clipSS)) {
if ((inside_bucket_flag & ISECT_1) == 0) { copy_v2_v2(isectVCosSS[*tot], v1_clipSS); (*tot)++; }
if ((inside_bucket_flag & ISECT_2) == 0) { copy_v2_v2(isectVCosSS[*tot], v2_clipSS); (*tot)++; }
}
}
if ((inside_bucket_flag & (ISECT_2 | ISECT_3)) != (ISECT_2 | ISECT_3)) {
- if (line_clip_rect2f(bucket_bounds, v2coSS, v3coSS, v1_clipSS, v2_clipSS)) {
+ if (line_clip_rect2f(cliprect, bucket_bounds, v2coSS, v3coSS, v1_clipSS, v2_clipSS)) {
if ((inside_bucket_flag & ISECT_2) == 0) { copy_v2_v2(isectVCosSS[*tot], v1_clipSS); (*tot)++; }
if ((inside_bucket_flag & ISECT_3) == 0) { copy_v2_v2(isectVCosSS[*tot], v2_clipSS); (*tot)++; }
}
}
if ((inside_bucket_flag & (ISECT_3 | ISECT_1)) != (ISECT_3 | ISECT_1)) {
- if (line_clip_rect2f(bucket_bounds, v3coSS, v1coSS, v1_clipSS, v2_clipSS)) {
+ if (line_clip_rect2f(cliprect, bucket_bounds, v3coSS, v1coSS, v1_clipSS, v2_clipSS)) {
if ((inside_bucket_flag & ISECT_3) == 0) { copy_v2_v2(isectVCosSS[*tot], v1_clipSS); (*tot)++; }
if ((inside_bucket_flag & ISECT_1) == 0) { copy_v2_v2(isectVCosSS[*tot], v2_clipSS); (*tot)++; }
}
@@ -2085,53 +2299,39 @@ static void project_bucket_clip_face(
for (i = 0; i < (*tot); i++) {
v2_clipSS[0] = isectVCosSS[i][0] - cent[0];
v2_clipSS[1] = isectVCosSS[i][1] - cent[1];
- isectVCosSS[i][2] = atan2f(v1_clipSS[0] * v2_clipSS[1] - v1_clipSS[1] * v2_clipSS[0], v1_clipSS[0] * v2_clipSS[0] + v1_clipSS[1] * v2_clipSS[1]);
+ isectVCosSS[i][2] = atan2f(v1_clipSS[0] * v2_clipSS[1] - v1_clipSS[1] * v2_clipSS[0],
+ v1_clipSS[0] * v2_clipSS[0] + v1_clipSS[1] * v2_clipSS[1]);
}
if (flip) qsort(isectVCosSS, *tot, sizeof(float) * 3, float_z_sort_flip);
else qsort(isectVCosSS, *tot, sizeof(float) * 3, float_z_sort);
- /* remove doubles */
- /* first/last check */
- if (fabsf(isectVCosSS[0][0] - isectVCosSS[(*tot) - 1][0]) < PROJ_PIXEL_TOLERANCE &&
- fabsf(isectVCosSS[0][1] - isectVCosSS[(*tot) - 1][1]) < PROJ_PIXEL_TOLERANCE)
- {
- (*tot)--;
- }
-
- /* its possible there is only a few left after remove doubles */
- if ((*tot) < 3) {
- // printf("removed too many doubles A\n");
- *tot = 0;
- return;
- }
-
doubles = true;
while (doubles == true) {
doubles = false;
- for (i = 1; i < (*tot); i++) {
- if (fabsf(isectVCosSS[i - 1][0] - isectVCosSS[i][0]) < PROJ_PIXEL_TOLERANCE &&
- fabsf(isectVCosSS[i - 1][1] - isectVCosSS[i][1]) < PROJ_PIXEL_TOLERANCE)
+
+ for (i = 0; i < (*tot); i++) {
+ if (fabsf(isectVCosSS[(i + 1) % *tot][0] - isectVCosSS[i][0]) < PROJ_PIXEL_TOLERANCE &&
+ fabsf(isectVCosSS[(i + 1) % *tot][1] - isectVCosSS[i][1]) < PROJ_PIXEL_TOLERANCE)
{
int j;
- for (j = i + 1; j < (*tot); j++) {
- isectVCosSS[j - 1][0] = isectVCosSS[j][0];
- isectVCosSS[j - 1][1] = isectVCosSS[j][1];
+ for (j = i; j < (*tot) - 1; j++) {
+ isectVCosSS[j][0] = isectVCosSS[j + 1][0];
+ isectVCosSS[j][1] = isectVCosSS[j + 1][1];
}
doubles = true; /* keep looking for more doubles */
(*tot)--;
}
}
+
+ /* its possible there is only a few left after remove doubles */
+ if ((*tot) < 3) {
+ // printf("removed too many doubles B\n");
+ *tot = 0;
+ return;
+ }
}
- /* its possible there is only a few left after remove doubles */
- if ((*tot) < 3) {
- // printf("removed too many doubles B\n");
- *tot = 0;
- return;
- }
-
-
if (is_ortho) {
for (i = 0; i < (*tot); i++) {
barycentric_weights_v2(v1coSS, v2coSS, v3coSS, isectVCosSS[i], w);
@@ -2155,7 +2355,9 @@ static void project_bucket_clip_face(
int i;
if (is_ortho) rect_to_uvspace_ortho(bucket_bounds, v1coSS, v2coSS, v3coSS, uv1co, uv2co, uv3co, test_uv, flip);
else rect_to_uvspace_persp(bucket_bounds, v1coSS, v2coSS, v3coSS, uv1co, uv2co, uv3co, test_uv, flip);
- printf("( [(%f,%f), (%f,%f), (%f,%f), (%f,%f)], ", test_uv[0][0], test_uv[0][1], test_uv[1][0], test_uv[1][1], test_uv[2][0], test_uv[2][1], test_uv[3][0], test_uv[3][1]);
+ printf("( [(%f,%f), (%f,%f), (%f,%f), (%f,%f)], ",
+ test_uv[0][0], test_uv[0][1], test_uv[1][0], test_uv[1][1],
+ test_uv[2][0], test_uv[2][1], test_uv[3][0], test_uv[3][1]);
printf(" [(%f,%f), (%f,%f), (%f,%f)], ", uv1co[0], uv1co[1], uv2co[0], uv2co[1], uv3co[0], uv3co[1]);
@@ -2242,7 +2444,7 @@ static bool IsectPoly2Df(const float pt[2], float uv[][2], const int tot)
static bool IsectPoly2Df_twoside(const float pt[2], float uv[][2], const int tot)
{
int i;
- int side = (line_point_side_v2(uv[tot - 1], uv[0], pt) > 0.0f);
+ bool side = (line_point_side_v2(uv[tot - 1], uv[0], pt) > 0.0f);
for (i = 1; i < tot; i++) {
if ((line_point_side_v2(uv[i - 1], uv[i], pt) > 0.0f) != side)
@@ -2253,9 +2455,16 @@ static bool IsectPoly2Df_twoside(const float pt[2], float uv[][2], const int tot
return 1;
}
-/* One of the most important function for projection painting, since it selects the pixels to be added into each bucket.
- * initialize pixels from this face where it intersects with the bucket_index, optionally initialize pixels for removing seams */
-static void project_paint_face_init(const ProjPaintState *ps, const int thread_index, const int bucket_index, const int face_index, const int image_index, rctf *bucket_bounds, ImBuf *ibuf, ImBuf **tmpibuf, const short clamp_u, const short clamp_v)
+/* One of the most important function for projection painting,
+ * since it selects the pixels to be added into each bucket.
+ *
+ * initialize pixels from this face where it intersects with the bucket_index,
+ * optionally initialize pixels for removing seams */
+static void project_paint_face_init(
+ const ProjPaintState *ps,
+ const int thread_index, const int bucket_index, const int tri_index, const int image_index,
+ const rctf *clip_rect, const rctf *bucket_bounds, ImBuf *ibuf, ImBuf **tmpibuf,
+ const bool clamp_u, const bool clamp_v)
{
/* Projection vars, to get the 3D locations into screen space */
MemArena *arena = ps->arena_mt[thread_index];
@@ -2271,8 +2480,9 @@ static void project_paint_face_init(const ProjPaintState *ps, const int thread_i
ps->projImages + image_index
};
- const MFace *mf = ps->dm_mface + face_index;
- const MTFace *tf = ps->dm_mtface[face_index];
+ const MLoopTri *lt = &ps->dm_mlooptri[tri_index];
+ const int lt_vtri[3] = { PS_LOOPTRI_AS_VERT_INDEX_3(ps, lt) };
+ const float *lt_tri_uv[3] = { PS_LOOPTRI_AS_UV_3(ps->dm_mloopuv, lt) };
/* UV/pixel seeking data */
int x; /* Image X-Pixel */
@@ -2280,40 +2490,38 @@ static void project_paint_face_init(const ProjPaintState *ps, const int thread_i
float mask;
float uv[2]; /* Image floating point UV - same as x, y but from 0.0-1.0 */
- int side;
- float *v1coSS, *v2coSS, *v3coSS; /* vert co screen-space, these will be assigned to mf->v1,2,3 or mf->v1,3,4 */
+ const float *v1coSS, *v2coSS, *v3coSS; /* vert co screen-space, these will be assigned to lt_vtri[0-2] */
- float *vCo[4]; /* vertex screenspace coords */
+ const float *vCo[3]; /* vertex screenspace coords */
float w[3], wco[3];
- float *uv1co, *uv2co, *uv3co; /* for convenience only, these will be assigned to tf->uv[0],1,2 or tf->uv[0],2,3 */
+ float *uv1co, *uv2co, *uv3co; /* for convenience only, these will be assigned to lt_tri_uv[0],1,2 or lt_tri_uv[0],2,3 */
float pixelScreenCo[4];
bool do_3d_mapping = ps->brush->mtex.brush_map_mode == MTEX_MAP_MODE_3D;
rcti bounds_px; /* ispace bounds */
/* vars for getting uvspace bounds */
- float tf_uv_pxoffset[4][2]; /* bucket bounds in UV space so we can init pixels only for this face, */
+ float lt_uv_pxoffset[3][2]; /* bucket bounds in UV space so we can init pixels only for this face, */
float xhalfpx, yhalfpx;
const float ibuf_xf = (float)ibuf->x, ibuf_yf = (float)ibuf->y;
int has_x_isect = 0, has_isect = 0; /* for early loop exit */
- int i1, i2, i3;
-
float uv_clip[8][2];
int uv_clip_tot;
const bool is_ortho = ps->is_ortho;
+ const bool is_flip_object = ps->is_flip_object;
const bool do_backfacecull = ps->do_backfacecull;
const bool do_clip = ps->rv3d ? ps->rv3d->rflag & RV3D_CLIPPING : 0;
- vCo[0] = ps->dm_mvert[mf->v1].co;
- vCo[1] = ps->dm_mvert[mf->v2].co;
- vCo[2] = ps->dm_mvert[mf->v3].co;
+ vCo[0] = ps->dm_mvert[lt_vtri[0]].co;
+ vCo[1] = ps->dm_mvert[lt_vtri[1]].co;
+ vCo[2] = ps->dm_mvert[lt_vtri[2]].co;
- /* Use tf_uv_pxoffset instead of tf->uv so we can offset the UV half a pixel
+ /* Use lt_uv_pxoffset instead of lt_tri_uv so we can offset the UV half a pixel
* this is done so we can avoid offsetting all the pixels by 0.5 which causes
* problems when wrapping negative coords */
xhalfpx = (0.5f + (PROJ_PIXEL_TOLERANCE * (1.0f / 3.0f))) / ibuf_xf;
@@ -2328,49 +2536,32 @@ static void project_paint_face_init(const ProjPaintState *ps, const int thread_i
* but since the first thing most people try is painting onto a quad- better make it work.
*/
- tf_uv_pxoffset[0][0] = tf->uv[0][0] - xhalfpx;
- tf_uv_pxoffset[0][1] = tf->uv[0][1] - yhalfpx;
-
- tf_uv_pxoffset[1][0] = tf->uv[1][0] - xhalfpx;
- tf_uv_pxoffset[1][1] = tf->uv[1][1] - yhalfpx;
+ lt_uv_pxoffset[0][0] = lt_tri_uv[0][0] - xhalfpx;
+ lt_uv_pxoffset[0][1] = lt_tri_uv[0][1] - yhalfpx;
- tf_uv_pxoffset[2][0] = tf->uv[2][0] - xhalfpx;
- tf_uv_pxoffset[2][1] = tf->uv[2][1] - yhalfpx;
+ lt_uv_pxoffset[1][0] = lt_tri_uv[1][0] - xhalfpx;
+ lt_uv_pxoffset[1][1] = lt_tri_uv[1][1] - yhalfpx;
- if (mf->v4) {
- vCo[3] = ps->dm_mvert[mf->v4].co;
+ lt_uv_pxoffset[2][0] = lt_tri_uv[2][0] - xhalfpx;
+ lt_uv_pxoffset[2][1] = lt_tri_uv[2][1] - yhalfpx;
- tf_uv_pxoffset[3][0] = tf->uv[3][0] - xhalfpx;
- tf_uv_pxoffset[3][1] = tf->uv[3][1] - yhalfpx;
- side = 1;
- }
- else {
- side = 0;
- }
-
- do {
- if (side == 1) {
- i1 = 0; i2 = 2; i3 = 3;
- }
- else {
- i1 = 0; i2 = 1; i3 = 2;
- }
-
- uv1co = tf_uv_pxoffset[i1]; // was tf->uv[i1];
- uv2co = tf_uv_pxoffset[i2]; // was tf->uv[i2];
- uv3co = tf_uv_pxoffset[i3]; // was tf->uv[i3];
+ {
+ uv1co = lt_uv_pxoffset[0]; // was lt_tri_uv[i1];
+ uv2co = lt_uv_pxoffset[1]; // was lt_tri_uv[i2];
+ uv3co = lt_uv_pxoffset[2]; // was lt_tri_uv[i3];
- v1coSS = ps->screenCoords[(*(&mf->v1 + i1))];
- v2coSS = ps->screenCoords[(*(&mf->v1 + i2))];
- v3coSS = ps->screenCoords[(*(&mf->v1 + i3))];
+ v1coSS = ps->screenCoords[lt_vtri[0]];
+ v2coSS = ps->screenCoords[lt_vtri[1]];
+ v3coSS = ps->screenCoords[lt_vtri[2]];
- /* This funtion gives is a concave polyline in UV space from the clipped quad and tri*/
+ /* This funtion gives is a concave polyline in UV space from the clipped tri*/
project_bucket_clip_face(
- is_ortho, bucket_bounds,
+ is_ortho, is_flip_object,
+ clip_rect, bucket_bounds,
v1coSS, v2coSS, v3coSS,
uv1co, uv2co, uv3co,
- uv_clip, &uv_clip_tot
- );
+ uv_clip, &uv_clip_tot,
+ do_backfacecull || ps->do_occlude);
/* sometimes this happens, better just allow for 8 intersectiosn even though there should be max 6 */
#if 0
@@ -2391,10 +2582,10 @@ static void project_paint_face_init(const ProjPaintState *ps, const int thread_i
CLAMP(bounds_px.ymax, 0, ibuf->y);
}
- /*
+#if 0
project_paint_undo_tiles_init(&bounds_px, ps->projImages + image_index, tmpibuf,
tile_width, threaded, ps->do_masking);
- */
+#endif
/* clip face and */
has_isect = 0;
@@ -2420,7 +2611,12 @@ static void project_paint_face_init(const ProjPaintState *ps, const int thread_i
/* a pity we need to get the worldspace pixel location here */
if (do_clip || do_3d_mapping) {
- interp_v3_v3v3v3(wco, ps->dm_mvert[(*(&mf->v1 + i1))].co, ps->dm_mvert[(*(&mf->v1 + i2))].co, ps->dm_mvert[(*(&mf->v1 + i3))].co, w);
+ interp_v3_v3v3v3(
+ wco,
+ ps->dm_mvert[lt_vtri[0]].co,
+ ps->dm_mvert[lt_vtri[1]].co,
+ ps->dm_mvert[lt_vtri[2]].co,
+ w);
if (do_clip && ED_view3d_clipping_test(ps->rv3d, wco, true)) {
continue; /* Watch out that no code below this needs to run */
}
@@ -2428,17 +2624,17 @@ static void project_paint_face_init(const ProjPaintState *ps, const int thread_i
/* Is this UV visible from the view? - raytrace */
/* project_paint_PickFace is less complex, use for testing */
- //if (project_paint_PickFace(ps, pixelScreenCo, w, &side) == face_index) {
+ //if (project_paint_PickFace(ps, pixelScreenCo, w, &side) == tri_index) {
if ((ps->do_occlude == false) ||
- !project_bucket_point_occluded(ps, bucketFaceNodes, face_index, pixelScreenCo))
+ !project_bucket_point_occluded(ps, bucketFaceNodes, tri_index, pixelScreenCo))
{
- mask = project_paint_uvpixel_mask(ps, face_index, side, w);
+ mask = project_paint_uvpixel_mask(ps, tri_index, w);
if (mask > 0.0f) {
BLI_linklist_prepend_arena(
bucketPixelNodes,
- project_paint_uvpixel_init(ps, arena, &tinf, x, y, mask, face_index,
- pixelScreenCo, wco, side, w),
+ project_paint_uvpixel_init(ps, arena, &tinf, x, y, mask, tri_index,
+ pixelScreenCo, wco, w),
arena
);
}
@@ -2462,8 +2658,7 @@ static void project_paint_face_init(const ProjPaintState *ps, const int thread_i
#endif
}
}
- } while (side--);
-
+ }
#ifndef PROJ_DEBUG_NOSEAMBLEED
@@ -2473,20 +2668,19 @@ static void project_paint_face_init(const ProjPaintState *ps, const int thread_i
if (threaded)
BLI_lock_thread(LOCK_CUSTOM1); /* Other threads could be modifying these vars */
- face_seam_flag = ps->faceSeamFlags[face_index];
+ face_seam_flag = ps->faceSeamFlags[tri_index];
/* are any of our edges un-initialized? */
if ((face_seam_flag & (PROJ_FACE_SEAM1 | PROJ_FACE_NOSEAM1)) == 0 ||
(face_seam_flag & (PROJ_FACE_SEAM2 | PROJ_FACE_NOSEAM2)) == 0 ||
- (face_seam_flag & (PROJ_FACE_SEAM3 | PROJ_FACE_NOSEAM3)) == 0 ||
- (face_seam_flag & (PROJ_FACE_SEAM4 | PROJ_FACE_NOSEAM4)) == 0)
+ (face_seam_flag & (PROJ_FACE_SEAM3 | PROJ_FACE_NOSEAM3)) == 0)
{
- project_face_seams_init(ps, face_index, mf->v4);
- face_seam_flag = ps->faceSeamFlags[face_index];
- //printf("seams - %d %d %d %d\n", flag&PROJ_FACE_SEAM1, flag&PROJ_FACE_SEAM2, flag&PROJ_FACE_SEAM3, flag&PROJ_FACE_SEAM4);
+ project_face_seams_init(ps, tri_index);
+ face_seam_flag = ps->faceSeamFlags[tri_index];
+ //printf("seams - %d %d %d %d\n", flag&PROJ_FACE_SEAM1, flag&PROJ_FACE_SEAM2, flag&PROJ_FACE_SEAM3);
}
- if ((face_seam_flag & (PROJ_FACE_SEAM1 | PROJ_FACE_SEAM2 | PROJ_FACE_SEAM3 | PROJ_FACE_SEAM4)) == 0) {
+ if ((face_seam_flag & (PROJ_FACE_SEAM1 | PROJ_FACE_SEAM2 | PROJ_FACE_SEAM3)) == 0) {
if (threaded)
BLI_unlock_thread(LOCK_CUSTOM1); /* Other threads could be modifying these vars */
@@ -2496,65 +2690,58 @@ static void project_paint_face_init(const ProjPaintState *ps, const int thread_i
/* we have a seam - deal with it! */
/* Now create new UV's for the seam face */
- float (*outset_uv)[2] = ps->faceSeamUVs[face_index];
- float insetCos[4][3]; /* inset face coords. NOTE!!! ScreenSace for ortho, Worldspace in prespective view */
+ float (*outset_uv)[2] = ps->faceSeamUVs[tri_index];
+ float insetCos[3][3]; /* inset face coords. NOTE!!! ScreenSace for ortho, Worldspace in prespective view */
- float *vCoSS[4]; /* vertex screenspace coords */
+ const float *vCoSS[3]; /* vertex screenspace coords */
float bucket_clip_edges[2][2]; /* store the screenspace coords of the face, clipped by the bucket's screen aligned rectangle */
float edge_verts_inset_clip[2][3];
int fidx1, fidx2; /* face edge pairs - loop throuh these ((0,1), (1,2), (2,3), (3,0)) or ((0,1), (1,2), (2,0)) for a tri */
float seam_subsection[4][2];
- float fac1, fac2, ftot;
-
+ float fac1, fac2;
if (outset_uv[0][0] == FLT_MAX) /* first time initialize */
- uv_image_outset(tf_uv_pxoffset, outset_uv, ps->seam_bleed_px, ibuf->x, ibuf->y, mf->v4 != 0);
+ uv_image_outset(
+ lt_uv_pxoffset, outset_uv, ps->seam_bleed_px,
+ ibuf->x, ibuf->y, (ps->faceWindingFlags[tri_index] & PROJ_FACE_WINDING_CW) == 0);
/* ps->faceSeamUVs cant be modified when threading, now this is done we can unlock */
if (threaded)
BLI_unlock_thread(LOCK_CUSTOM1); /* Other threads could be modifying these vars */
- vCoSS[0] = ps->screenCoords[mf->v1];
- vCoSS[1] = ps->screenCoords[mf->v2];
- vCoSS[2] = ps->screenCoords[mf->v3];
- if (mf->v4)
- vCoSS[3] = ps->screenCoords[mf->v4];
+ vCoSS[0] = ps->screenCoords[lt_vtri[0]];
+ vCoSS[1] = ps->screenCoords[lt_vtri[1]];
+ vCoSS[2] = ps->screenCoords[lt_vtri[2]];
/* PROJ_FACE_SCALE_SEAM must be slightly less then 1.0f */
if (is_ortho) {
- if (mf->v4) scale_quad(insetCos, vCoSS, PROJ_FACE_SCALE_SEAM);
- else scale_tri(insetCos, vCoSS, PROJ_FACE_SCALE_SEAM);
+ scale_tri(insetCos, vCoSS, PROJ_FACE_SCALE_SEAM);
}
else {
- if (mf->v4) scale_quad(insetCos, vCo, PROJ_FACE_SCALE_SEAM);
- else scale_tri(insetCos, vCo, PROJ_FACE_SCALE_SEAM);
+ scale_tri(insetCos, vCo, PROJ_FACE_SCALE_SEAM);
}
- side = 0; /* for triangles this wont need to change */
-
- for (fidx1 = 0; fidx1 < (mf->v4 ? 4 : 3); fidx1++) {
- if (mf->v4) fidx2 = (fidx1 == 3) ? 0 : fidx1 + 1; /* next fidx in the face (0,1,2,3) -> (1,2,3,0) */
- else fidx2 = (fidx1 == 2) ? 0 : fidx1 + 1; /* next fidx in the face (0,1,2) -> (1,2,0) */
+ for (fidx1 = 0; fidx1 < 3; fidx1++) {
+ fidx2 = (fidx1 == 2) ? 0 : fidx1 + 1; /* next fidx in the face (0,1,2) -> (1,2,0) */
if ((face_seam_flag & (1 << fidx1)) && /* 1<<fidx1 -> PROJ_FACE_SEAM# */
- line_clip_rect2f(bucket_bounds, vCoSS[fidx1], vCoSS[fidx2], bucket_clip_edges[0], bucket_clip_edges[1]))
+ line_clip_rect2f(clip_rect, bucket_bounds, vCoSS[fidx1], vCoSS[fidx2], bucket_clip_edges[0], bucket_clip_edges[1]))
{
+ if (len_squared_v2v2(vCoSS[fidx1], vCoSS[fidx2]) > FLT_EPSILON) { /* avoid div by zero */
- ftot = len_v2v2(vCoSS[fidx1], vCoSS[fidx2]); /* screenspace edge length */
-
- if (ftot > 0.0f) { /* avoid div by zero */
- if (mf->v4) {
- if (fidx1 == 2 || fidx2 == 2) side = 1;
- else side = 0;
+ if (is_ortho) {
+ fac1 = line_point_factor_v2(bucket_clip_edges[0], vCoSS[fidx1], vCoSS[fidx2]);
+ fac2 = line_point_factor_v2(bucket_clip_edges[1], vCoSS[fidx1], vCoSS[fidx2]);
+ }
+ else {
+ fac1 = screen_px_line_point_factor_v2_persp(ps, bucket_clip_edges[0], vCo[fidx1], vCo[fidx2]);
+ fac2 = screen_px_line_point_factor_v2_persp(ps, bucket_clip_edges[1], vCo[fidx1], vCo[fidx2]);
}
- fac1 = len_v2v2(vCoSS[fidx1], bucket_clip_edges[0]) / ftot;
- fac2 = len_v2v2(vCoSS[fidx1], bucket_clip_edges[1]) / ftot;
-
- interp_v2_v2v2(seam_subsection[0], tf_uv_pxoffset[fidx1], tf_uv_pxoffset[fidx2], fac1);
- interp_v2_v2v2(seam_subsection[1], tf_uv_pxoffset[fidx1], tf_uv_pxoffset[fidx2], fac2);
+ interp_v2_v2v2(seam_subsection[0], lt_uv_pxoffset[fidx1], lt_uv_pxoffset[fidx2], fac1);
+ interp_v2_v2v2(seam_subsection[1], lt_uv_pxoffset[fidx1], lt_uv_pxoffset[fidx2], fac2);
interp_v2_v2v2(seam_subsection[2], outset_uv[fidx1], outset_uv[fidx2], fac2);
interp_v2_v2v2(seam_subsection[3], outset_uv[fidx1], outset_uv[fidx2], fac1);
@@ -2565,7 +2752,7 @@ static void project_paint_face_init(const ProjPaintState *ps, const int thread_i
interp_v3_v3v3(edge_verts_inset_clip[1], insetCos[fidx1], insetCos[fidx2], fac2);
- if (pixel_bounds_uv(seam_subsection[0], seam_subsection[1], seam_subsection[2], seam_subsection[3], &bounds_px, ibuf->x, ibuf->y, true)) {
+ if (pixel_bounds_uv((const float (*)[2])seam_subsection, &bounds_px, ibuf->x, ibuf->y)) {
/* bounds between the seam rect and the uvspace bucket pixels */
has_isect = 0;
@@ -2579,7 +2766,7 @@ static void project_paint_face_init(const ProjPaintState *ps, const int thread_i
uv[0] = (float)x / ibuf_xf; /* use offset uvs instead */
/* test we're inside uvspace bucket and triangle bounds */
- if (isect_point_quad_v2(uv, seam_subsection[0], seam_subsection[1], seam_subsection[2], seam_subsection[3])) {
+ if (isect_point_quad_v2(uv, UNPACK4(seam_subsection))) {
float fac;
/* We need to find the closest point along the face edge,
@@ -2593,11 +2780,8 @@ static void project_paint_face_init(const ProjPaintState *ps, const int thread_i
/* Since this is a seam we need to work out where on the line this pixel is */
//fac = line_point_factor_v2(uv, uv_seam_quad[0], uv_seam_quad[1]);
-
- fac = line_point_factor_v2(uv, seam_subsection[0], seam_subsection[1]);
- if (fac < 0.0f) { copy_v3_v3(pixelScreenCo, edge_verts_inset_clip[0]); }
- else if (fac > 1.0f) { copy_v3_v3(pixelScreenCo, edge_verts_inset_clip[1]); }
- else { interp_v3_v3v3(pixelScreenCo, edge_verts_inset_clip[0], edge_verts_inset_clip[1], fac); }
+ fac = resolve_quad_u_v2(uv, UNPACK4(seam_subsection));
+ interp_v3_v3v3(pixelScreenCo, edge_verts_inset_clip[0], edge_verts_inset_clip[1], fac);
if (!is_ortho) {
pixelScreenCo[3] = 1.0f;
@@ -2608,57 +2792,41 @@ static void project_paint_face_init(const ProjPaintState *ps, const int thread_i
}
if ((ps->do_occlude == false) ||
- !project_bucket_point_occluded(ps, bucketFaceNodes, face_index, pixelScreenCo))
+ !project_bucket_point_occluded(ps, bucketFaceNodes, tri_index, pixelScreenCo))
{
/* Only bother calculating the weights if we intersect */
- if (ps->do_mask_normal || ps->dm_mtface_clone) {
-#if 1
+ if (ps->do_mask_normal || ps->dm_mloopuv_clone) {
+ const float uv_fac = fac1 + (fac * (fac2 - fac1));
+#if 0
/* get the UV on the line since we want to copy the pixels from there for bleeding */
float uv_close[2];
- float uv_fac = closest_to_line_v2(uv_close, uv, tf_uv_pxoffset[fidx1], tf_uv_pxoffset[fidx2]);
- if (uv_fac < 0.0f) copy_v2_v2(uv_close, tf_uv_pxoffset[fidx1]);
- else if (uv_fac > 1.0f) copy_v2_v2(uv_close, tf_uv_pxoffset[fidx2]);
-
- if (side) {
- barycentric_weights_v2(tf_uv_pxoffset[0], tf_uv_pxoffset[2], tf_uv_pxoffset[3], uv_close, w);
- }
- else {
- barycentric_weights_v2(tf_uv_pxoffset[0], tf_uv_pxoffset[1], tf_uv_pxoffset[2], uv_close, w);
- }
-#else /* this is buggy with quads, don't use for now */
+ interp_v2_v2v2(uv_close, lt_uv_pxoffset[fidx1], lt_uv_pxoffset[fidx2], uv_fac);
+ barycentric_weights_v2(lt_uv_pxoffset[0], lt_uv_pxoffset[1], lt_uv_pxoffset[2], uv_close, w);
+#else
/* Cheat, we know where we are along the edge so work out the weights from that */
- uv_fac = fac1 + (uv_fac * (fac2 - fac1));
-
w[0] = w[1] = w[2] = 0.0;
- if (side) {
- w[fidx1 ? fidx1 - 1 : 0] = 1.0f - uv_fac;
- w[fidx2 ? fidx2 - 1 : 0] = uv_fac;
- }
- else {
- w[fidx1] = 1.0f - uv_fac;
- w[fidx2] = uv_fac;
- }
+ w[fidx1] = 1.0f - uv_fac;
+ w[fidx2] = uv_fac;
#endif
}
/* a pity we need to get the worldspace pixel location here */
if (do_clip || do_3d_mapping) {
- if (side) interp_v3_v3v3v3(wco, ps->dm_mvert[mf->v1].co, ps->dm_mvert[mf->v3].co, ps->dm_mvert[mf->v4].co, w);
- else interp_v3_v3v3v3(wco, ps->dm_mvert[mf->v1].co, ps->dm_mvert[mf->v2].co, ps->dm_mvert[mf->v3].co, w);
+ interp_v3_v3v3v3(wco, vCo[0], vCo[1], vCo[2], w);
if (do_clip && ED_view3d_clipping_test(ps->rv3d, wco, true)) {
continue; /* Watch out that no code below this needs to run */
}
}
- mask = project_paint_uvpixel_mask(ps, face_index, side, w);
+ mask = project_paint_uvpixel_mask(ps, tri_index, w);
if (mask > 0.0f) {
BLI_linklist_prepend_arena(
bucketPixelNodes,
- project_paint_uvpixel_init(ps, arena, &tinf, x, y, mask, face_index,
- pixelScreenCo, wco, side, w),
+ project_paint_uvpixel_init(ps, arena, &tinf, x, y, mask, tri_index,
+ pixelScreenCo, wco, w),
arena
);
}
@@ -2684,6 +2852,8 @@ static void project_paint_face_init(const ProjPaintState *ps, const int thread_i
}
}
}
+#else
+ UNUSED_VARS(vCo, threaded);
#endif // PROJ_DEBUG_NOSEAMBLEED
}
@@ -2720,10 +2890,12 @@ static void project_bucket_bounds(const ProjPaintState *ps, const int bucket_x,
/* Fill this bucket with pixels from the faces that intersect it.
*
* have bucket_bounds as an argument so we don't need to give bucket_x/y the rect function needs */
-static void project_bucket_init(const ProjPaintState *ps, const int thread_index, const int bucket_index, rctf *bucket_bounds)
+static void project_bucket_init(
+ const ProjPaintState *ps, const int thread_index, const int bucket_index,
+ const rctf *clip_rect, const rctf *bucket_bounds)
{
LinkNode *node;
- int face_index, image_index = 0;
+ int tri_index, image_index = 0;
ImBuf *ibuf = NULL;
Image *tpage_last = NULL, *tpage;
Image *ima = NULL;
@@ -2735,17 +2907,20 @@ static void project_bucket_init(const ProjPaintState *ps, const int thread_index
ima = ps->projImages[0].ima;
for (node = ps->bucketFaces[bucket_index]; node; node = node->next) {
- project_paint_face_init(ps, thread_index, bucket_index, GET_INT_FROM_POINTER(node->link), 0, bucket_bounds, ibuf, &tmpibuf, ima->tpageflag & IMA_CLAMP_U, ima->tpageflag & IMA_CLAMP_V);
+ project_paint_face_init(
+ ps, thread_index, bucket_index, GET_INT_FROM_POINTER(node->link), 0,
+ clip_rect, bucket_bounds, ibuf, &tmpibuf,
+ (ima->tpageflag & IMA_CLAMP_U) != 0, (ima->tpageflag & IMA_CLAMP_V) != 0);
}
}
else {
/* More complicated loop, switch between images */
for (node = ps->bucketFaces[bucket_index]; node; node = node->next) {
- face_index = GET_INT_FROM_POINTER(node->link);
+ tri_index = GET_INT_FROM_POINTER(node->link);
/* Image context switching */
- tpage = project_paint_face_paint_image(ps, face_index);
+ tpage = project_paint_face_paint_image(ps, tri_index);
if (tpage_last != tpage) {
tpage_last = tpage;
@@ -2759,7 +2934,10 @@ static void project_bucket_init(const ProjPaintState *ps, const int thread_index
}
/* context switching done */
- project_paint_face_init(ps, thread_index, bucket_index, face_index, image_index, bucket_bounds, ibuf, &tmpibuf, ima->tpageflag & IMA_CLAMP_U, ima->tpageflag & IMA_CLAMP_V);
+ project_paint_face_init(
+ ps, thread_index, bucket_index, tri_index, image_index,
+ clip_rect, bucket_bounds, ibuf, &tmpibuf,
+ (ima->tpageflag & IMA_CLAMP_U) != 0, (ima->tpageflag & IMA_CLAMP_V) != 0);
}
}
@@ -2776,66 +2954,47 @@ static void project_bucket_init(const ProjPaintState *ps, const int thread_index
* calculated when it might not be needed later, (at the moment at least)
* obviously it shouldn't have bugs though */
-static bool project_bucket_face_isect(ProjPaintState *ps, int bucket_x, int bucket_y, const MFace *mf)
+static bool project_bucket_face_isect(ProjPaintState *ps, int bucket_x, int bucket_y, const MLoopTri *lt)
{
/* TODO - replace this with a tricker method that uses sideofline for all screenCoords's edges against the closest bucket corner */
+ const int lt_vtri[3] = { PS_LOOPTRI_AS_VERT_INDEX_3(ps, lt) };
rctf bucket_bounds;
float p1[2], p2[2], p3[2], p4[2];
- const float *v, *v1, *v2, *v3, *v4 = NULL;
+ const float *v, *v1, *v2, *v3;
int fidx;
project_bucket_bounds(ps, bucket_x, bucket_y, &bucket_bounds);
-
+
/* Is one of the faces verts in the bucket bounds? */
- fidx = mf->v4 ? 3 : 2;
+ fidx = 2;
do {
- v = ps->screenCoords[(*(&mf->v1 + fidx))];
+ v = ps->screenCoords[lt_vtri[fidx]];
if (BLI_rctf_isect_pt_v(&bucket_bounds, v)) {
return 1;
}
} while (fidx--);
- v1 = ps->screenCoords[mf->v1];
- v2 = ps->screenCoords[mf->v2];
- v3 = ps->screenCoords[mf->v3];
- if (mf->v4) {
- v4 = ps->screenCoords[mf->v4];
- }
+ v1 = ps->screenCoords[lt_vtri[0]];
+ v2 = ps->screenCoords[lt_vtri[1]];
+ v3 = ps->screenCoords[lt_vtri[2]];
p1[0] = bucket_bounds.xmin; p1[1] = bucket_bounds.ymin;
p2[0] = bucket_bounds.xmin; p2[1] = bucket_bounds.ymax;
p3[0] = bucket_bounds.xmax; p3[1] = bucket_bounds.ymax;
p4[0] = bucket_bounds.xmax; p4[1] = bucket_bounds.ymin;
- if (mf->v4) {
- if (isect_point_quad_v2(p1, v1, v2, v3, v4) ||
- isect_point_quad_v2(p2, v1, v2, v3, v4) ||
- isect_point_quad_v2(p3, v1, v2, v3, v4) ||
- isect_point_quad_v2(p4, v1, v2, v3, v4) ||
-
- /* we can avoid testing v3,v1 because another intersection MUST exist if this intersects */
- (isect_line_line_v2(p1, p2, v1, v2) || isect_line_line_v2(p1, p2, v2, v3) || isect_line_line_v2(p1, p2, v3, v4)) ||
- (isect_line_line_v2(p2, p3, v1, v2) || isect_line_line_v2(p2, p3, v2, v3) || isect_line_line_v2(p2, p3, v3, v4)) ||
- (isect_line_line_v2(p3, p4, v1, v2) || isect_line_line_v2(p3, p4, v2, v3) || isect_line_line_v2(p3, p4, v3, v4)) ||
- (isect_line_line_v2(p4, p1, v1, v2) || isect_line_line_v2(p4, p1, v2, v3) || isect_line_line_v2(p4, p1, v3, v4)))
- {
- return 1;
- }
- }
- else {
- if (isect_point_tri_v2(p1, v1, v2, v3) ||
- isect_point_tri_v2(p2, v1, v2, v3) ||
- isect_point_tri_v2(p3, v1, v2, v3) ||
- isect_point_tri_v2(p4, v1, v2, v3) ||
- /* we can avoid testing v3,v1 because another intersection MUST exist if this intersects */
- (isect_line_line_v2(p1, p2, v1, v2) || isect_line_line_v2(p1, p2, v2, v3)) ||
- (isect_line_line_v2(p2, p3, v1, v2) || isect_line_line_v2(p2, p3, v2, v3)) ||
- (isect_line_line_v2(p3, p4, v1, v2) || isect_line_line_v2(p3, p4, v2, v3)) ||
- (isect_line_line_v2(p4, p1, v1, v2) || isect_line_line_v2(p4, p1, v2, v3)))
- {
- return 1;
- }
+ if (isect_point_tri_v2(p1, v1, v2, v3) ||
+ isect_point_tri_v2(p2, v1, v2, v3) ||
+ isect_point_tri_v2(p3, v1, v2, v3) ||
+ isect_point_tri_v2(p4, v1, v2, v3) ||
+ /* we can avoid testing v3,v1 because another intersection MUST exist if this intersects */
+ (isect_line_line_v2(p1, p2, v1, v2) || isect_line_line_v2(p1, p2, v2, v3)) ||
+ (isect_line_line_v2(p2, p3, v1, v2) || isect_line_line_v2(p2, p3, v2, v3)) ||
+ (isect_line_line_v2(p3, p4, v1, v2) || isect_line_line_v2(p3, p4, v2, v3)) ||
+ (isect_line_line_v2(p4, p1, v1, v2) || isect_line_line_v2(p4, p1, v2, v3)))
+ {
+ return 1;
}
return 0;
@@ -2843,8 +3002,9 @@ static bool project_bucket_face_isect(ProjPaintState *ps, int bucket_x, int buck
/* Add faces to the bucket but don't initialize its pixels
* TODO - when painting occluded, sort the faces on their min-Z and only add faces that faces that are not occluded */
-static void project_paint_delayed_face_init(ProjPaintState *ps, const MFace *mf, const int face_index)
+static void project_paint_delayed_face_init(ProjPaintState *ps, const MLoopTri *lt, const int tri_index)
{
+ const int lt_vtri[3] = { PS_LOOPTRI_AS_VERT_INDEX_3(ps, lt) };
float min[2], max[2], *vCoSS;
int bucketMin[2], bucketMax[2]; /* for ps->bucketRect indexing */
int fidx, bucket_x, bucket_y;
@@ -2853,9 +3013,9 @@ static void project_paint_delayed_face_init(ProjPaintState *ps, const MFace *mf,
INIT_MINMAX2(min, max);
- fidx = mf->v4 ? 3 : 2;
+ fidx = 2;
do {
- vCoSS = ps->screenCoords[*(&mf->v1 + fidx)];
+ vCoSS = ps->screenCoords[lt_vtri[fidx]];
minmax_v2v2_v2(min, max, vCoSS);
} while (fidx--);
@@ -2864,11 +3024,11 @@ static void project_paint_delayed_face_init(ProjPaintState *ps, const MFace *mf,
for (bucket_y = bucketMin[1]; bucket_y < bucketMax[1]; bucket_y++) {
has_x_isect = 0;
for (bucket_x = bucketMin[0]; bucket_x < bucketMax[0]; bucket_x++) {
- if (project_bucket_face_isect(ps, bucket_x, bucket_y, mf)) {
+ if (project_bucket_face_isect(ps, bucket_x, bucket_y, lt)) {
int bucket_index = bucket_x + (bucket_y * ps->buckets_x);
BLI_linklist_prepend_arena(
&ps->bucketFaces[bucket_index],
- SET_INT_IN_POINTER(face_index), /* cast to a pointer to shut up the compiler */
+ SET_INT_IN_POINTER(tri_index), /* cast to a pointer to shut up the compiler */
arena
);
@@ -2888,254 +3048,146 @@ static void project_paint_delayed_face_init(ProjPaintState *ps, const MFace *mf,
#ifndef PROJ_DEBUG_NOSEAMBLEED
if (ps->seam_bleed_px > 0.0f) {
- if (!mf->v4) {
- ps->faceSeamFlags[face_index] |= PROJ_FACE_NOSEAM4; /* so this wont show up as an untagged edge */
- }
- **ps->faceSeamUVs[face_index] = FLT_MAX; /* set as uninitialized */
+ **ps->faceSeamUVs[tri_index] = FLT_MAX; /* set as uninitialized */
}
#endif
}
-/* run once per stroke before projection painting */
-static void project_paint_begin(ProjPaintState *ps)
+/**
+ * \note when using subsurf or multires, some arrays are thrown away, we need to keep a copy
+ */
+static void proj_paint_state_non_cddm_init(ProjPaintState *ps)
{
- /* Viewport vars */
- float mat[3][3];
-
- float no[3];
-
- float *projScreenCo; /* Note, we could have 4D vectors are only needed for */
- float projMargin;
-
- /* Image Vars - keep track of images we have used */
- LinkNode *image_LinkList = NULL;
- LinkNode *node;
-
- ProjPaintImage *projIma;
- Image *tpage_last = NULL, *tpage;
- TexPaintSlot *slot_last = NULL, *slot = NULL;
- TexPaintSlot *slot_last_clone = NULL, *slot_clone;
-
- /* Face vars */
- MPoly *mpoly_orig;
- MFace *mf;
- MTFace **tf;
- MTFace *tf_base;
-
- MTFace **tf_clone;
- MTFace *tf_clone_base = NULL;
-
- int a, i; /* generic looping vars */
- int image_index = -1, face_index;
-
- /* double lookup */
- const int *index_mf_to_mpoly = NULL;
- const int *index_mp_to_orig = NULL;
-
- MVert *mv;
-
- MemArena *arena; /* at the moment this is just ps->arena_mt[0], but use this to show were not multithreading */
-
- const int diameter = 2 * BKE_brush_size_get(ps->scene, ps->brush);
-
- bool reset_threads = false;
-
- /* ---- end defines ---- */
-
- if (ps->source == PROJ_SRC_VIEW)
- ED_view3d_clipping_local(ps->rv3d, ps->ob->obmat); /* faster clipping lookups */
-
- ps->do_face_sel = ((((Mesh *)ps->ob->data)->editflag & ME_EDIT_PAINT_FACE_SEL) != 0);
-
- /* paint onto the derived mesh */
-
- /* Workaround for subsurf selection, try the display mesh first */
- if (ps->source == PROJ_SRC_IMAGE_CAM) {
- /* using render mesh, assume only camera was rendered from */
- ps->dm = mesh_create_derived_render(ps->scene, ps->ob, ps->scene->customdata_mask | CD_MASK_MTFACE);
- ps->dm_release = true;
- }
- else if (ps->ob->derivedFinal &&
- CustomData_has_layer(&ps->ob->derivedFinal->faceData, CD_MTFACE) &&
- (ps->do_face_sel == false || CustomData_has_layer(&ps->ob->derivedFinal->polyData, CD_ORIGINDEX)))
- {
- ps->dm = ps->ob->derivedFinal;
- ps->dm_release = false;
- }
- else {
- ps->dm = mesh_get_derived_final(
- ps->scene, ps->ob,
- ps->scene->customdata_mask | CD_MASK_MTFACE | (ps->do_face_sel ? CD_ORIGINDEX : 0));
- ps->dm_release = true;
- }
-
- if (!CustomData_has_layer(&ps->dm->faceData, CD_MTFACE)) {
-
- if (ps->dm_release)
- ps->dm->release(ps->dm);
-
- ps->dm = NULL;
- return;
- }
-
- DM_update_materials(ps->dm, ps->ob);
-
- ps->dm_totvert = ps->dm->getNumVerts(ps->dm);
- ps->dm_totface = ps->dm->getNumTessFaces(ps->dm);
-
- ps->dm_mvert = ps->dm->getVertArray(ps->dm);
- ps->dm_mface = ps->dm->getTessFaceArray(ps->dm);
- ps->dm_mtface = MEM_mallocN(ps->dm_totface * sizeof(MTFace *), "proj_paint_mtfaces");
-
- if (ps->do_face_sel) {
- index_mf_to_mpoly = ps->dm->getTessFaceDataArray(ps->dm, CD_ORIGINDEX);
- index_mp_to_orig = ps->dm->getPolyDataArray(ps->dm, CD_ORIGINDEX);
- if (index_mf_to_mpoly == NULL) {
- index_mp_to_orig = NULL;
- }
- else {
- mpoly_orig = ((Mesh *)ps->ob->data)->mpoly;
- }
- }
- else {
- mpoly_orig = NULL;
- }
-
- /* use clone mtface? */
- if (ps->do_layer_clone) {
- ps->dm_mtface_clone = MEM_mallocN(ps->dm_totface * sizeof(MTFace *), "proj_paint_mtfaces");
- }
-
- if (ps->do_layer_stencil || ps->do_stencil_brush) {
- //int layer_num = CustomData_get_stencil_layer(&ps->dm->faceData, CD_MTFACE);
- int layer_num = CustomData_get_stencil_layer(&((Mesh *)ps->ob->data)->pdata, CD_MTEXPOLY);
- if (layer_num != -1)
- ps->dm_mtface_stencil = CustomData_get_layer_n(&ps->dm->faceData, CD_MTFACE, layer_num);
-
- if (ps->dm_mtface_stencil == NULL) {
- /* get active instead */
- ps->dm_mtface_stencil = CustomData_get_layer(&ps->dm->faceData, CD_MTFACE);
- }
-
- if (ps->do_stencil_brush)
- tf_base = ps->dm_mtface_stencil;
- }
-
- if (ps->do_layer_clone) {
- int layer_num = CustomData_get_clone_layer(&((Mesh *)ps->ob->data)->pdata, CD_MTEXPOLY);
-
- if (layer_num != -1)
- tf_clone_base = CustomData_get_layer_n(&ps->dm->faceData, CD_MTFACE, layer_num);
-
- if (tf_clone_base == NULL) {
- /* get active instead */
- tf_clone_base = CustomData_get_layer(&ps->dm->faceData, CD_MTFACE);
- }
-
- }
-
- /* when using subsurf or multires, mface arrays are thrown away, we need to keep a copy */
if (ps->dm->type != DM_TYPE_CDDM) {
ps->dm_mvert = MEM_dupallocN(ps->dm_mvert);
- ps->dm_mface = MEM_dupallocN(ps->dm_mface);
+ ps->dm_mpoly = MEM_dupallocN(ps->dm_mpoly);
+ ps->dm_mloop = MEM_dupallocN(ps->dm_mloop);
/* looks like these are ok for now.*/
#if 0
- ps->dm_mtface = MEM_dupallocN(ps->dm_mtface);
- ps->dm_mtface_clone = MEM_dupallocN(ps->dm_mtface_clone);
- ps->dm_mtface_stencil = MEM_dupallocN(ps->dm_mtface_stencil);
+ ps->dm_mloopuv = MEM_dupallocN(ps->dm_mloopuv);
+ ps->dm_mloopuv_clone = MEM_dupallocN(ps->dm_mloopuv_clone);
+ ps->dm_mloopuv_stencil = MEM_dupallocN(ps->dm_mloopuv_stencil);
#endif
}
+}
+
+static void proj_paint_state_viewport_init(
+ ProjPaintState *ps, const char symmetry_flag)
+{
+ float mat[3][3];
+ float viewmat[4][4];
+ float viewinv[4][4];
ps->viewDir[0] = 0.0f;
ps->viewDir[1] = 0.0f;
ps->viewDir[2] = 1.0f;
- {
- float viewmat[4][4];
- float viewinv[4][4];
+ copy_m4_m4(ps->obmat, ps->ob->obmat);
- invert_m4_m4(ps->ob->imat, ps->ob->obmat);
+ if (symmetry_flag) {
+ int i;
+ for (i = 0; i < 3; i++) {
+ if ((symmetry_flag >> i) & 1) {
+ negate_v3(ps->obmat[i]);
+ ps->is_flip_object = !ps->is_flip_object;
+ }
+ }
+ }
- if (ps->source == PROJ_SRC_VIEW) {
- /* normal drawing */
- ps->winx = ps->ar->winx;
- ps->winy = ps->ar->winy;
+ invert_m4_m4(ps->obmat_imat, ps->obmat);
- copy_m4_m4(viewmat, ps->rv3d->viewmat);
- copy_m4_m4(viewinv, ps->rv3d->viewinv);
+ if (ELEM(ps->source, PROJ_SRC_VIEW, PROJ_SRC_VIEW_FILL)) {
+ /* normal drawing */
+ ps->winx = ps->ar->winx;
+ ps->winy = ps->ar->winy;
- ED_view3d_ob_project_mat_get(ps->rv3d, ps->ob, ps->projectMat);
+ copy_m4_m4(viewmat, ps->rv3d->viewmat);
+ copy_m4_m4(viewinv, ps->rv3d->viewinv);
- ps->is_ortho = ED_view3d_clip_range_get(ps->v3d, ps->rv3d, &ps->clipsta, &ps->clipend, true);
- }
- else {
- /* re-projection */
- float winmat[4][4];
- float vmat[4][4];
+ ED_view3d_ob_project_mat_get_from_obmat(ps->rv3d, ps->obmat, ps->projectMat);
- ps->winx = ps->reproject_ibuf->x;
- ps->winy = ps->reproject_ibuf->y;
+ ps->is_ortho = ED_view3d_clip_range_get(ps->v3d, ps->rv3d, &ps->clipsta, &ps->clipend, true);
+ }
+ else {
+ /* re-projection */
+ float winmat[4][4];
+ float vmat[4][4];
- if (ps->source == PROJ_SRC_IMAGE_VIEW) {
- /* image stores camera data, tricky */
- IDProperty *idgroup = IDP_GetProperties(&ps->reproject_image->id, 0);
- IDProperty *view_data = IDP_GetPropertyFromGroup(idgroup, PROJ_VIEW_DATA_ID);
+ ps->winx = ps->reproject_ibuf->x;
+ ps->winy = ps->reproject_ibuf->y;
- const float *array = (float *)IDP_Array(view_data);
+ if (ps->source == PROJ_SRC_IMAGE_VIEW) {
+ /* image stores camera data, tricky */
+ IDProperty *idgroup = IDP_GetProperties(&ps->reproject_image->id, 0);
+ IDProperty *view_data = IDP_GetPropertyFromGroup(idgroup, PROJ_VIEW_DATA_ID);
- /* use image array, written when creating image */
- memcpy(winmat, array, sizeof(winmat)); array += sizeof(winmat) / sizeof(float);
- memcpy(viewmat, array, sizeof(viewmat)); array += sizeof(viewmat) / sizeof(float);
- ps->clipsta = array[0];
- ps->clipend = array[1];
- ps->is_ortho = array[2] ? 1 : 0;
+ const float *array = (float *)IDP_Array(view_data);
- invert_m4_m4(viewinv, viewmat);
- }
- else if (ps->source == PROJ_SRC_IMAGE_CAM) {
- Object *cam_ob = ps->scene->camera;
- CameraParams params;
-
- /* viewmat & viewinv */
- copy_m4_m4(viewinv, cam_ob->obmat);
- normalize_m4(viewinv);
- invert_m4_m4(viewmat, viewinv);
-
- /* window matrix, clipping and ortho */
- BKE_camera_params_init(&params);
- BKE_camera_params_from_object(&params, cam_ob);
- BKE_camera_params_compute_viewplane(&params, ps->winx, ps->winy, 1.0f, 1.0f);
- BKE_camera_params_compute_matrix(&params);
-
- copy_m4_m4(winmat, params.winmat);
- ps->clipsta = params.clipsta;
- ps->clipend = params.clipend;
- ps->is_ortho = params.is_ortho;
- }
+ /* use image array, written when creating image */
+ memcpy(winmat, array, sizeof(winmat)); array += sizeof(winmat) / sizeof(float);
+ memcpy(viewmat, array, sizeof(viewmat)); array += sizeof(viewmat) / sizeof(float);
+ ps->clipsta = array[0];
+ ps->clipend = array[1];
+ ps->is_ortho = array[2] ? 1 : 0;
- /* same as #ED_view3d_ob_project_mat_get */
- mul_m4_m4m4(vmat, viewmat, ps->ob->obmat);
- mul_m4_m4m4(ps->projectMat, winmat, vmat);
+ invert_m4_m4(viewinv, viewmat);
+ }
+ else if (ps->source == PROJ_SRC_IMAGE_CAM) {
+ Object *cam_ob = ps->scene->camera;
+ CameraParams params;
+
+ /* viewmat & viewinv */
+ copy_m4_m4(viewinv, cam_ob->obmat);
+ normalize_m4(viewinv);
+ invert_m4_m4(viewmat, viewinv);
+
+ /* window matrix, clipping and ortho */
+ BKE_camera_params_init(&params);
+ BKE_camera_params_from_object(&params, cam_ob);
+ BKE_camera_params_compute_viewplane(&params, ps->winx, ps->winy, 1.0f, 1.0f);
+ BKE_camera_params_compute_matrix(&params);
+
+ copy_m4_m4(winmat, params.winmat);
+ ps->clipsta = params.clipsta;
+ ps->clipend = params.clipend;
+ ps->is_ortho = params.is_ortho;
+ }
+ else {
+ BLI_assert(0);
}
+ /* same as #ED_view3d_ob_project_mat_get */
+ mul_m4_m4m4(vmat, viewmat, ps->obmat);
+ mul_m4_m4m4(ps->projectMat, winmat, vmat);
+ }
+
+ invert_m4_m4(ps->projectMatInv, ps->projectMat);
- /* viewDir - object relative */
- invert_m4_m4(ps->ob->imat, ps->ob->obmat);
- copy_m3_m4(mat, viewinv);
- mul_m3_v3(mat, ps->viewDir);
- copy_m3_m4(mat, ps->ob->imat);
- mul_m3_v3(mat, ps->viewDir);
- normalize_v3(ps->viewDir);
+ /* viewDir - object relative */
+ copy_m3_m4(mat, viewinv);
+ mul_m3_v3(mat, ps->viewDir);
+ copy_m3_m4(mat, ps->obmat_imat);
+ mul_m3_v3(mat, ps->viewDir);
+ normalize_v3(ps->viewDir);
- /* viewPos - object relative */
- copy_v3_v3(ps->viewPos, viewinv[3]);
- copy_m3_m4(mat, ps->ob->imat);
- mul_m3_v3(mat, ps->viewPos);
- add_v3_v3(ps->viewPos, ps->ob->imat[3]);
+ if (UNLIKELY(ps->is_flip_object)) {
+ negate_v3(ps->viewDir);
}
- /* calculate vert screen coords
- * run this early so we can calculate the x/y resolution of our bucket rect */
+ /* viewPos - object relative */
+ copy_v3_v3(ps->viewPos, viewinv[3]);
+ copy_m3_m4(mat, ps->obmat_imat);
+ mul_m3_v3(mat, ps->viewPos);
+ add_v3_v3(ps->viewPos, ps->obmat_imat[3]);
+}
+
+static void proj_paint_state_screen_coords_init(ProjPaintState *ps, const int diameter)
+{
+ const MVert *mv;
+ float *projScreenCo;
+ float projMargin;
+ int a;
+
INIT_MINMAX2(ps->screenMin, ps->screenMax);
ps->screenCoords = MEM_mallocN(sizeof(float) * ps->dm_totvert * 4, "ProjectPaint ScreenVerts");
@@ -3176,7 +3228,7 @@ static void project_paint_begin(ProjPaintState *ps)
}
/* If this border is not added we get artifacts for faces that
- * have a parallel edge and at the bounds of the the 2D projected verts eg
+ * have a parallel edge and at the bounds of the 2D projected verts eg
* - a single screen aligned quad */
projMargin = (ps->screenMax[0] - ps->screenMin[0]) * 0.000001f;
ps->screenMax[0] += projMargin;
@@ -3192,47 +3244,74 @@ static void project_paint_begin(ProjPaintState *ps)
CLAMP(ps->screenMin[1], (float)(-diameter), (float)(ps->winy + diameter));
CLAMP(ps->screenMax[1], (float)(-diameter), (float)(ps->winy + diameter));
+#else
+ UNUSED_VARS(diameter);
#endif
}
- else { /* re-projection, use bounds */
+ else if (ps->source != PROJ_SRC_VIEW_FILL) { /* re-projection, use bounds */
ps->screenMin[0] = 0;
ps->screenMax[0] = (float)(ps->winx);
ps->screenMin[1] = 0;
ps->screenMax[1] = (float)(ps->winy);
}
+}
- /* only for convenience */
- ps->screen_width = ps->screenMax[0] - ps->screenMin[0];
- ps->screen_height = ps->screenMax[1] - ps->screenMin[1];
-
- ps->buckets_x = (int)(ps->screen_width / (((float)diameter) / PROJ_BUCKET_BRUSH_DIV));
- ps->buckets_y = (int)(ps->screen_height / (((float)diameter) / PROJ_BUCKET_BRUSH_DIV));
+static void proj_paint_state_cavity_init(ProjPaintState *ps)
+{
+ const MVert *mv;
+ const MEdge *me;
+ float *cavities;
+ int a;
- /* printf("\tscreenspace bucket division x:%d y:%d\n", ps->buckets_x, ps->buckets_y); */
+ if (ps->do_mask_cavity) {
+ int *counter = MEM_callocN(sizeof(int) * ps->dm_totvert, "counter");
+ float (*edges)[3] = MEM_callocN(sizeof(float) * 3 * ps->dm_totvert, "edges");
+ ps->cavities = MEM_mallocN(sizeof(float) * ps->dm_totvert, "ProjectPaint Cavities");
+ cavities = ps->cavities;
+
+ for (a = 0, me = ps->dm_medge; a < ps->dm_totedge; a++, me++) {
+ float e[3];
+ sub_v3_v3v3(e, ps->dm_mvert[me->v1].co, ps->dm_mvert[me->v2].co);
+ normalize_v3(e);
+ add_v3_v3(edges[me->v2], e);
+ counter[me->v2]++;
+ sub_v3_v3(edges[me->v1], e);
+ counter[me->v1]++;
+ }
+ for (a = 0, mv = ps->dm_mvert; a < ps->dm_totvert; a++, mv++) {
+ if (counter[a] > 0) {
+ float no[3];
+ mul_v3_fl(edges[a], 1.0f / counter[a]);
+ normal_short_to_float_v3(no, mv->no);
+ /* augment the diffe*/
+ cavities[a] = saacos(10.0f * dot_v3v3(no, edges[a])) * (float)M_1_PI;
+ }
+ else
+ cavities[a] = 0.0;
+ }
- if (ps->buckets_x > PROJ_BUCKET_RECT_MAX || ps->buckets_y > PROJ_BUCKET_RECT_MAX) {
- reset_threads = true;
+ MEM_freeN(counter);
+ MEM_freeN(edges);
}
+}
- /* really high values could cause problems since it has to allocate a few
- * (ps->buckets_x*ps->buckets_y) sized arrays */
- CLAMP(ps->buckets_x, PROJ_BUCKET_RECT_MIN, PROJ_BUCKET_RECT_MAX);
- CLAMP(ps->buckets_y, PROJ_BUCKET_RECT_MIN, PROJ_BUCKET_RECT_MAX);
-
- ps->bucketRect = (LinkNode **)MEM_callocN(sizeof(LinkNode *) * ps->buckets_x * ps->buckets_y, "paint-bucketRect");
- ps->bucketFaces = (LinkNode **)MEM_callocN(sizeof(LinkNode *) * ps->buckets_x * ps->buckets_y, "paint-bucketFaces");
-
- ps->bucketFlags = (unsigned char *)MEM_callocN(sizeof(char) * ps->buckets_x * ps->buckets_y, "paint-bucketFaces");
#ifndef PROJ_DEBUG_NOSEAMBLEED
+static void proj_paint_state_seam_bleed_init(ProjPaintState *ps)
+{
if (ps->seam_bleed_px > 0.0f) {
- ps->vertFaces = (LinkNode **)MEM_callocN(sizeof(LinkNode *) * ps->dm_totvert, "paint-vertFaces");
- ps->faceSeamFlags = (char *)MEM_callocN(sizeof(char) * ps->dm_totface, "paint-faceSeamFlags");
- ps->faceWindingFlags = (char *)MEM_callocN(sizeof(char) * ps->dm_totface, "paint-faceWindindFlags");
- ps->faceSeamUVs = MEM_mallocN(sizeof(float) * ps->dm_totface * 8, "paint-faceSeamUVs");
+ ps->vertFaces = MEM_callocN(sizeof(LinkNode *) * ps->dm_totvert, "paint-vertFaces");
+ ps->faceSeamFlags = MEM_callocN(sizeof(char) * ps->dm_totlooptri, "paint-faceSeamFlags");
+ ps->faceWindingFlags = MEM_callocN(sizeof(char) * ps->dm_totlooptri, "paint-faceWindindFlags");
+ ps->faceSeamUVs = MEM_mallocN(sizeof(float[3][2]) * ps->dm_totlooptri, "paint-faceSeamUVs");
}
+}
#endif
+static void proj_paint_state_thread_init(ProjPaintState *ps, const bool reset_threads)
+{
+ int a;
+
/* Thread stuff
*
* very small brushes run a lot slower multithreaded since the advantage with
@@ -3246,85 +3325,364 @@ static void project_paint_begin(ProjPaintState *ps)
if (reset_threads)
ps->thread_tot = 1;
- if (ps->thread_tot > 1) {
- ps->tile_lock = MEM_mallocN(sizeof(SpinLock), "projpaint_tile_lock");
- BLI_spin_init(ps->tile_lock);
- }
+ if (ps->is_shared_user == false) {
+ if (ps->thread_tot > 1) {
+ ps->tile_lock = MEM_mallocN(sizeof(SpinLock), "projpaint_tile_lock");
+ BLI_spin_init(ps->tile_lock);
+ }
- image_undo_init_locks();
+ image_undo_init_locks();
+ }
for (a = 0; a < ps->thread_tot; a++) {
ps->arena_mt[a] = BLI_memarena_new(MEM_SIZE_OPTIMAL(1 << 16), "project paint arena");
}
+}
- arena = ps->arena_mt[0];
-
+static void proj_paint_state_vert_flags_init(ProjPaintState *ps)
+{
if (ps->do_backfacecull && ps->do_mask_normal) {
float viewDirPersp[3];
+ const MVert *mv;
+ float no[3];
+ int a;
ps->vertFlags = MEM_callocN(sizeof(char) * ps->dm_totvert, "paint-vertFlags");
for (a = 0, mv = ps->dm_mvert; a < ps->dm_totvert; a++, mv++) {
normal_short_to_float_v3(no, mv->no);
+ if (UNLIKELY(ps->is_flip_object)) {
+ negate_v3(no);
+ }
if (ps->is_ortho) {
- if (angle_normalized_v3v3(ps->viewDir, no) >= ps->normal_angle) { /* 1 vert of this face is towards us */
+ if (dot_v3v3(ps->viewDir, no) <= ps->normal_angle__cos) { /* 1 vert of this face is towards us */
ps->vertFlags[a] |= PROJ_VERT_CULL;
}
}
else {
sub_v3_v3v3(viewDirPersp, ps->viewPos, mv->co);
normalize_v3(viewDirPersp);
- if (angle_normalized_v3v3(viewDirPersp, no) >= ps->normal_angle) { /* 1 vert of this face is towards us */
+ if (UNLIKELY(ps->is_flip_object)) {
+ negate_v3(viewDirPersp);
+ }
+ if (dot_v3v3(viewDirPersp, no) <= ps->normal_angle__cos) { /* 1 vert of this face is towards us */
ps->vertFlags[a] |= PROJ_VERT_CULL;
}
}
}
}
-
- for (face_index = 0, tf = ps->dm_mtface, mf = ps->dm_mface; face_index < ps->dm_totface; mf++, tf++, face_index++) {
- bool is_face_sel;
+ else {
+ ps->vertFlags = NULL;
+ }
+}
#ifndef PROJ_DEBUG_NOSEAMBLEED
- /* add face user if we have bleed enabled, set the UV seam flags later */
- /* annoying but we need to add all faces even ones we never use elsewhere */
- if (ps->seam_bleed_px > 0.0f) {
- BLI_linklist_prepend_arena(&ps->vertFaces[mf->v1], SET_INT_IN_POINTER(face_index), arena);
- BLI_linklist_prepend_arena(&ps->vertFaces[mf->v2], SET_INT_IN_POINTER(face_index), arena);
- BLI_linklist_prepend_arena(&ps->vertFaces[mf->v3], SET_INT_IN_POINTER(face_index), arena);
- if (mf->v4) {
- BLI_linklist_prepend_arena(&ps->vertFaces[mf->v4], SET_INT_IN_POINTER(face_index), arena);
- }
- }
+static void project_paint_bleed_add_face_user(
+ const ProjPaintState *ps, MemArena *arena,
+ const MLoopTri *lt, const int tri_index)
+{
+ /* add face user if we have bleed enabled, set the UV seam flags later */
+ /* annoying but we need to add all faces even ones we never use elsewhere */
+ if (ps->seam_bleed_px > 0.0f) {
+ const int lt_vtri[3] = { PS_LOOPTRI_AS_VERT_INDEX_3(ps, lt) };
+ void *tri_index_p = SET_INT_IN_POINTER(tri_index);
+ BLI_linklist_prepend_arena(&ps->vertFaces[lt_vtri[0]], tri_index_p, arena);
+ BLI_linklist_prepend_arena(&ps->vertFaces[lt_vtri[1]], tri_index_p, arena);
+ BLI_linklist_prepend_arena(&ps->vertFaces[lt_vtri[2]], tri_index_p, arena);
+ }
+}
#endif
- if (ps->do_face_sel) {
- int orig_index;
- if (index_mp_to_orig && ((orig_index = DM_origindex_mface_mpoly(index_mf_to_mpoly, index_mp_to_orig,
- face_index))) != ORIGINDEX_NONE)
- {
- MPoly *mp = &mpoly_orig[orig_index];
- is_face_sel = ((mp->flag & ME_FACE_SEL) != 0);
- }
- else {
- is_face_sel = ((mf->flag & ME_FACE_SEL) != 0);
+/* Return true if DM can be painted on, false otherwise */
+static bool proj_paint_state_dm_init(ProjPaintState *ps)
+{
+ /* Workaround for subsurf selection, try the display mesh first */
+ if (ps->source == PROJ_SRC_IMAGE_CAM) {
+ /* using render mesh, assume only camera was rendered from */
+ ps->dm = mesh_create_derived_render(ps->scene, ps->ob, ps->scene->customdata_mask | CD_MASK_MTFACE);
+ ps->dm_release = true;
+ }
+ else if (ps->ob->derivedFinal &&
+ CustomData_has_layer(&ps->ob->derivedFinal->loopData, CD_MLOOPUV) &&
+ (ps->do_face_sel == false || CustomData_has_layer(&ps->ob->derivedFinal->polyData, CD_ORIGINDEX)))
+ {
+ ps->dm = ps->ob->derivedFinal;
+ ps->dm_release = false;
+ }
+ else {
+ ps->dm = mesh_get_derived_final(
+ ps->scene, ps->ob,
+ ps->scene->customdata_mask | CD_MASK_MTFACE | (ps->do_face_sel ? CD_ORIGINDEX : 0));
+ ps->dm_release = true;
+ }
+
+ if (!CustomData_has_layer(&ps->dm->loopData, CD_MLOOPUV)) {
+
+ if (ps->dm_release)
+ ps->dm->release(ps->dm);
+
+ ps->dm = NULL;
+ return false;
+ }
+
+ DM_update_materials(ps->dm, ps->ob);
+
+ ps->dm_mvert = ps->dm->getVertArray(ps->dm);
+
+ if (ps->do_mask_cavity)
+ ps->dm_medge = ps->dm->getEdgeArray(ps->dm);
+
+ ps->dm_mloop = ps->dm->getLoopArray(ps->dm);
+ ps->dm_mpoly = ps->dm->getPolyArray(ps->dm);
+
+ ps->dm_mlooptri = ps->dm->getLoopTriArray(ps->dm);
+
+ ps->dm_totvert = ps->dm->getNumVerts(ps->dm);
+ ps->dm_totedge = ps->dm->getNumEdges(ps->dm);
+ ps->dm_totpoly = ps->dm->getNumPolys(ps->dm);
+ ps->dm_totlooptri = ps->dm->getNumLoopTri(ps->dm);
+
+ ps->dm_mloopuv = MEM_mallocN(ps->dm_totpoly * sizeof(MLoopUV *), "proj_paint_mtfaces");
+
+ return true;
+}
+
+typedef struct {
+ const MLoopUV *mloopuv_clone_base;
+ const TexPaintSlot *slot_last_clone;
+ const TexPaintSlot *slot_clone;
+} ProjPaintLayerClone;
+
+static void proj_paint_layer_clone_init(
+ ProjPaintState *ps,
+ ProjPaintLayerClone *layer_clone)
+{
+ MLoopUV *mloopuv_clone_base = NULL;
+
+ /* use clone mtface? */
+ if (ps->do_layer_clone) {
+ const int layer_num = CustomData_get_clone_layer(&((Mesh *)ps->ob->data)->pdata, CD_MTEXPOLY);
+
+ ps->dm_mloopuv_clone = MEM_mallocN(ps->dm_totpoly * sizeof(MLoopUV *), "proj_paint_mtfaces");
+
+ if (layer_num != -1)
+ mloopuv_clone_base = CustomData_get_layer_n(&ps->dm->loopData, CD_MLOOPUV, layer_num);
+
+ if (mloopuv_clone_base == NULL) {
+ /* get active instead */
+ mloopuv_clone_base = CustomData_get_layer(&ps->dm->loopData, CD_MLOOPUV);
+ }
+
+ }
+
+ memset(layer_clone, 0, sizeof(*layer_clone));
+ layer_clone->mloopuv_clone_base = mloopuv_clone_base;
+}
+
+/* Return true if face should be skipped, false otherwise */
+static bool project_paint_clone_face_skip(
+ ProjPaintState *ps,
+ ProjPaintLayerClone *lc,
+ const TexPaintSlot *slot,
+ const int tri_index)
+{
+ if (ps->do_layer_clone) {
+ if (ps->do_material_slots) {
+ lc->slot_clone = project_paint_face_clone_slot(ps, tri_index);
+ /* all faces should have a valid slot, reassert here */
+ if (ELEM(lc->slot_clone, NULL, slot))
+ return true;
+ }
+ else if (ps->clone_ima == ps->canvas_ima)
+ return true;
+
+ if (ps->do_material_slots) {
+ if (lc->slot_clone != lc->slot_last_clone) {
+ if (!slot->uvname ||
+ !(lc->mloopuv_clone_base = CustomData_get_layer_named(
+ &ps->dm->loopData, CD_MLOOPUV,
+ lc->slot_clone->uvname)))
+ {
+ lc->mloopuv_clone_base = CustomData_get_layer(&ps->dm->loopData, CD_MLOOPUV);
+ }
+ lc->slot_last_clone = lc->slot_clone;
}
}
+
+ /* will set multiple times for 4+ sided poly */
+ ps->dm_mloopuv_clone[ps->dm_mlooptri[tri_index].poly] = lc->mloopuv_clone_base;
+ }
+ return false;
+}
+
+typedef struct {
+ const MPoly *mpoly_orig;
+
+ const int *index_mp_to_orig;
+} ProjPaintFaceLookup;
+
+static void proj_paint_face_lookup_init(
+ const ProjPaintState *ps,
+ ProjPaintFaceLookup *face_lookup)
+{
+ memset(face_lookup, 0, sizeof(*face_lookup));
+ if (ps->do_face_sel) {
+ face_lookup->index_mp_to_orig = ps->dm->getPolyDataArray(ps->dm, CD_ORIGINDEX);
+ face_lookup->mpoly_orig = ((Mesh *)ps->ob->data)->mpoly;
+ }
+}
+
+/* Return true if face should be considered selected, false otherwise */
+static bool project_paint_check_face_sel(
+ const ProjPaintState *ps,
+ const ProjPaintFaceLookup *face_lookup,
+ const MLoopTri *lt)
+{
+ if (ps->do_face_sel) {
+ int orig_index;
+ const MPoly *mp;
+
+ if ((face_lookup->index_mp_to_orig != NULL) &&
+ (((orig_index = (face_lookup->index_mp_to_orig[lt->poly]))) != ORIGINDEX_NONE))
+ {
+ mp = &face_lookup->mpoly_orig[orig_index];
+ }
else {
- is_face_sel = true;
+ mp = &ps->dm_mpoly[lt->poly];
}
+ return ((mp->flag & ME_FACE_SEL) != 0);
+ }
+ else {
+ return true;
+ }
+}
+
+typedef struct {
+ const float *v1;
+ const float *v2;
+ const float *v3;
+} ProjPaintFaceCoSS;
+
+static void proj_paint_face_coSS_init(
+ const ProjPaintState *ps, const MLoopTri *lt,
+ ProjPaintFaceCoSS *coSS)
+{
+ const int lt_vtri[3] = { PS_LOOPTRI_AS_VERT_INDEX_3(ps, lt) };
+ coSS->v1 = ps->screenCoords[lt_vtri[0]];
+ coSS->v2 = ps->screenCoords[lt_vtri[1]];
+ coSS->v3 = ps->screenCoords[lt_vtri[2]];
+}
+
+/* Return true if face should be culled, false otherwise */
+static bool project_paint_flt_max_cull(
+ const ProjPaintState *ps,
+ const ProjPaintFaceCoSS *coSS)
+{
+ if (!ps->is_ortho) {
+ if (coSS->v1[0] == FLT_MAX ||
+ coSS->v2[0] == FLT_MAX ||
+ coSS->v3[0] == FLT_MAX)
+ {
+ return true;
+ }
+ }
+ return false;
+}
+
+#ifdef PROJ_DEBUG_WINCLIP
+/* Return true if face should be culled, false otherwise */
+static bool project_paint_winclip(
+ const ProjPaintState *ps,
+ const ProjPaintFaceCoSS *coSS)
+{
+ /* ignore faces outside the view */
+ return ((ps->source != PROJ_SRC_VIEW_FILL) &&
+ ((coSS->v1[0] < ps->screenMin[0] &&
+ coSS->v2[0] < ps->screenMin[0] &&
+ coSS->v3[0] < ps->screenMin[0]) ||
+
+ (coSS->v1[0] > ps->screenMax[0] &&
+ coSS->v2[0] > ps->screenMax[0] &&
+ coSS->v3[0] > ps->screenMax[0]) ||
+
+ (coSS->v1[1] < ps->screenMin[1] &&
+ coSS->v2[1] < ps->screenMin[1] &&
+ coSS->v3[1] < ps->screenMin[1]) ||
+
+ (coSS->v1[1] > ps->screenMax[1] &&
+ coSS->v2[1] > ps->screenMax[1] &&
+ coSS->v3[1] > ps->screenMax[1])));
+}
+#endif //PROJ_DEBUG_WINCLIP
+
+
+static void project_paint_build_proj_ima(
+ ProjPaintState *ps, MemArena *arena,
+ LinkNode *image_LinkList)
+{
+ ProjPaintImage *projIma;
+ LinkNode *node;
+ int i;
+
+ /* build an array of images we use */
+ projIma = ps->projImages = BLI_memarena_alloc(arena, sizeof(ProjPaintImage) * ps->image_tot);
+
+ for (node = image_LinkList, i = 0; node; node = node->next, i++, projIma++) {
+ int size;
+ projIma->ima = node->link;
+ projIma->touch = 0;
+ projIma->ibuf = BKE_image_acquire_ibuf(projIma->ima, NULL, NULL);
+ size = sizeof(void **) * IMAPAINT_TILE_NUMBER(projIma->ibuf->x) * IMAPAINT_TILE_NUMBER(projIma->ibuf->y);
+ projIma->partRedrawRect = BLI_memarena_alloc(arena, sizeof(ImagePaintPartialRedraw) * PROJ_BOUNDBOX_SQUARED);
+ memset(projIma->partRedrawRect, 0, sizeof(ImagePaintPartialRedraw) * PROJ_BOUNDBOX_SQUARED);
+ projIma->undoRect = (volatile void **) BLI_memarena_alloc(arena, size);
+ memset(projIma->undoRect, 0, size);
+ projIma->maskRect = BLI_memarena_alloc(arena, size);
+ memset(projIma->maskRect, 0, size);
+ projIma->valid = BLI_memarena_alloc(arena, size);
+ memset(projIma->valid, 0, size);
+ }
+}
+
+static void project_paint_prepare_all_faces(
+ ProjPaintState *ps, MemArena *arena,
+ const ProjPaintFaceLookup *face_lookup,
+ ProjPaintLayerClone *layer_clone,
+ const MLoopUV *mloopuv_base,
+ const bool is_multi_view)
+{
+ /* Image Vars - keep track of images we have used */
+ LinkNodePair image_LinkList = {NULL, NULL};
+
+ Image *tpage_last = NULL, *tpage;
+ TexPaintSlot *slot_last = NULL;
+ TexPaintSlot *slot = NULL;
+ const MLoopTri *lt;
+ int image_index = -1, tri_index;
+ int prev_poly = -1;
+
+ for (tri_index = 0, lt = ps->dm_mlooptri; tri_index < ps->dm_totlooptri; tri_index++, lt++) {
+ bool is_face_sel;
+
+#ifndef PROJ_DEBUG_NOSEAMBLEED
+ project_paint_bleed_add_face_user(ps, arena, lt, tri_index);
+#endif
+
+ is_face_sel = project_paint_check_face_sel(ps, face_lookup, lt);
+
if (!ps->do_stencil_brush) {
- slot = project_paint_face_paint_slot(ps, face_index);
+ slot = project_paint_face_paint_slot(ps, tri_index);
/* all faces should have a valid slot, reassert here */
if (slot == NULL) {
- tf_base = CustomData_get_layer(&ps->dm->faceData, CD_MTFACE);
+ mloopuv_base = CustomData_get_layer(&ps->dm->loopData, CD_MLOOPUV);
tpage = ps->canvas_ima;
}
else {
if (slot != slot_last) {
- if (!slot->uvname || !(tf_base = CustomData_get_layer_named(&ps->dm->faceData, CD_MTFACE, slot->uvname)))
- tf_base = CustomData_get_layer(&ps->dm->faceData, CD_MTFACE);
+ if (!slot->uvname || !(mloopuv_base = CustomData_get_layer_named(&ps->dm->loopData, CD_MLOOPUV, slot->uvname)))
+ mloopuv_base = CustomData_get_layer(&ps->dm->loopData, CD_MLOOPUV);
slot_last = slot;
}
@@ -3339,110 +3697,68 @@ static void project_paint_begin(ProjPaintState *ps)
tpage = ps->stencil_ima;
}
- *tf = tf_base + face_index;
+ ps->dm_mloopuv[lt->poly] = mloopuv_base;
- if (ps->do_layer_clone) {
- if (ps->do_material_slots) {
- slot_clone = project_paint_face_clone_slot(ps, face_index);
- /* all faces should have a valid slot, reassert here */
- if (ELEM(slot_clone, NULL, slot))
- continue;
- }
- else if (ps->clone_ima == ps->canvas_ima)
- continue;
-
- tf_clone = ps->dm_mtface_clone + face_index;
-
- if (ps->do_material_slots) {
- if (slot_clone != slot_last_clone) {
- if (!slot->uvname || !(tf_clone_base = CustomData_get_layer_named(&ps->dm->faceData, CD_MTFACE, slot_clone->uvname)))
- tf_clone_base = CustomData_get_layer(&ps->dm->faceData, CD_MTFACE);
- slot_last_clone = slot_clone;
- }
- }
-
- *tf_clone = tf_clone_base + face_index;
+ if (project_paint_clone_face_skip(ps, layer_clone, slot, tri_index)) {
+ continue;
}
/* tfbase here should be non-null! */
- BLI_assert (tf_base != NULL);
+ BLI_assert (mloopuv_base != NULL);
if (is_face_sel && tpage) {
- const float *v1coSS, *v2coSS, *v3coSS, *v4coSS = NULL;
+ ProjPaintFaceCoSS coSS;
+ proj_paint_face_coSS_init(ps, lt, &coSS);
- v1coSS = ps->screenCoords[mf->v1];
- v2coSS = ps->screenCoords[mf->v2];
- v3coSS = ps->screenCoords[mf->v3];
- if (mf->v4) {
- v4coSS = ps->screenCoords[mf->v4];
- }
-
-
- if (!ps->is_ortho) {
- if (v1coSS[0] == FLT_MAX ||
- v2coSS[0] == FLT_MAX ||
- v3coSS[0] == FLT_MAX ||
- (mf->v4 && v4coSS[0] == FLT_MAX))
- {
+ if (is_multi_view == false) {
+ if (project_paint_flt_max_cull(ps, &coSS)) {
continue;
}
- }
#ifdef PROJ_DEBUG_WINCLIP
- /* ignore faces outside the view */
- if (
- (v1coSS[0] < ps->screenMin[0] &&
- v2coSS[0] < ps->screenMin[0] &&
- v3coSS[0] < ps->screenMin[0] &&
- (mf->v4 && v4coSS[0] < ps->screenMin[0])) ||
-
- (v1coSS[0] > ps->screenMax[0] &&
- v2coSS[0] > ps->screenMax[0] &&
- v3coSS[0] > ps->screenMax[0] &&
- (mf->v4 && v4coSS[0] > ps->screenMax[0])) ||
-
- (v1coSS[1] < ps->screenMin[1] &&
- v2coSS[1] < ps->screenMin[1] &&
- v3coSS[1] < ps->screenMin[1] &&
- (mf->v4 && v4coSS[1] < ps->screenMin[1])) ||
-
- (v1coSS[1] > ps->screenMax[1] &&
- v2coSS[1] > ps->screenMax[1] &&
- v3coSS[1] > ps->screenMax[1] &&
- (mf->v4 && v4coSS[1] > ps->screenMax[1]))
- )
- {
- continue;
- }
+ if (project_paint_winclip(ps, &coSS)) {
+ continue;
+ }
#endif //PROJ_DEBUG_WINCLIP
+ /* backface culls individual triangles but mask normal will use polygon */
+ if (ps->do_backfacecull) {
+ if (ps->do_mask_normal) {
+ if (prev_poly != lt->poly) {
+ int iloop;
+ bool culled = true;
+ const MPoly *poly = ps->dm_mpoly + lt->poly;
+ int poly_loops = poly->totloop;
+ prev_poly = lt->poly;
+ for (iloop = 0; iloop < poly_loops; iloop++) {
+ if (!(ps->vertFlags[ps->dm_mloop[poly->loopstart + iloop].v] & PROJ_VERT_CULL)) {
+ culled = false;
+ break;
+ }
+ }
- if (ps->do_backfacecull) {
- if (ps->do_mask_normal) {
- /* Since we are interpolating the normals of faces, we want to make
- * sure all the verts are pointing away from the view,
- * not just the face */
- if ((ps->vertFlags[mf->v1] & PROJ_VERT_CULL) &&
- (ps->vertFlags[mf->v2] & PROJ_VERT_CULL) &&
- (ps->vertFlags[mf->v3] & PROJ_VERT_CULL) &&
- (mf->v4 == 0 || ps->vertFlags[mf->v4] & PROJ_VERT_CULL)
- )
- {
- continue;
+ if (culled) {
+ /* poly loops - 2 is number of triangles for poly,
+ * but counter gets incremented when continuing, so decrease by 3 */
+ int poly_tri = poly_loops - 3;
+ tri_index += poly_tri;
+ lt += poly_tri;
+ continue;
+ }
+ }
}
- }
- else {
- if (line_point_side_v2(v1coSS, v2coSS, v3coSS) < 0.0f) {
- continue;
+ else {
+ if ((line_point_side_v2(coSS.v1, coSS.v2, coSS.v3) < 0.0f) != ps->is_flip_object) {
+ continue;
+ }
}
-
}
}
if (tpage_last != tpage) {
- image_index = BLI_linklist_index(image_LinkList, tpage);
+ image_index = BLI_linklist_index(image_LinkList.list, tpage);
if (image_index == -1 && BKE_image_has_ibuf(tpage, NULL)) { /* MemArena dosnt have an append func */
BLI_linklist_append(&image_LinkList, tpage);
@@ -3456,32 +3772,115 @@ static void project_paint_begin(ProjPaintState *ps)
if (image_index != -1) {
/* Initialize the faces screen pixels */
/* Add this to a list to initialize later */
- project_paint_delayed_face_init(ps, mf, face_index);
+ project_paint_delayed_face_init(ps, lt, tri_index);
}
}
}
/* build an array of images we use*/
- projIma = ps->projImages = (ProjPaintImage *)BLI_memarena_alloc(arena, sizeof(ProjPaintImage) * ps->image_tot);
-
- for (node = image_LinkList, i = 0; node; node = node->next, i++, projIma++) {
- int size;
- projIma->ima = node->link;
- projIma->touch = 0;
- projIma->ibuf = BKE_image_acquire_ibuf(projIma->ima, NULL, NULL);
- size = sizeof(void **) * IMAPAINT_TILE_NUMBER(projIma->ibuf->x) * IMAPAINT_TILE_NUMBER(projIma->ibuf->y);
- projIma->partRedrawRect = BLI_memarena_alloc(arena, sizeof(ImagePaintPartialRedraw) * PROJ_BOUNDBOX_SQUARED);
- memset(projIma->partRedrawRect, 0, sizeof(ImagePaintPartialRedraw) * PROJ_BOUNDBOX_SQUARED);
- projIma->undoRect = (volatile void **) BLI_memarena_alloc(arena, size);
- memset(projIma->undoRect, 0, size);
- projIma->maskRect = (unsigned short **) BLI_memarena_alloc(arena, size);
- memset(projIma->maskRect, 0, size);
- projIma->valid = (bool **) BLI_memarena_alloc(arena, size);
- memset(projIma->valid, 0, size);
+ if (ps->is_shared_user == false) {
+ project_paint_build_proj_ima(ps, arena, image_LinkList.list);
}
/* we have built the array, discard the linked list */
- BLI_linklist_free(image_LinkList, NULL);
+ BLI_linklist_free(image_LinkList.list, NULL);
+}
+
+/* run once per stroke before projection painting */
+static void project_paint_begin(
+ ProjPaintState *ps,
+ const bool is_multi_view, const char symmetry_flag)
+{
+ ProjPaintLayerClone layer_clone;
+ ProjPaintFaceLookup face_lookup;
+ const MLoopUV *mloopuv_base = NULL;
+
+ MemArena *arena; /* at the moment this is just ps->arena_mt[0], but use this to show were not multithreading */
+
+ const int diameter = 2 * BKE_brush_size_get(ps->scene, ps->brush);
+
+ bool reset_threads = false;
+
+ /* ---- end defines ---- */
+
+ if (ps->source == PROJ_SRC_VIEW)
+ ED_view3d_clipping_local(ps->rv3d, ps->ob->obmat); /* faster clipping lookups */
+
+ ps->do_face_sel = ((((Mesh *)ps->ob->data)->editflag & ME_EDIT_PAINT_FACE_SEL) != 0);
+ ps->is_flip_object = (ps->ob->transflag & OB_NEG_SCALE) != 0;
+
+ /* paint onto the derived mesh */
+ if (ps->is_shared_user == false) {
+ if (!proj_paint_state_dm_init(ps)) {
+ return;
+ }
+ }
+
+ proj_paint_face_lookup_init(ps, &face_lookup);
+ proj_paint_layer_clone_init(ps, &layer_clone);
+
+ if (ps->do_layer_stencil || ps->do_stencil_brush) {
+ //int layer_num = CustomData_get_stencil_layer(&ps->dm->loopData, CD_MLOOPUV);
+ int layer_num = CustomData_get_stencil_layer(&((Mesh *)ps->ob->data)->pdata, CD_MTEXPOLY);
+ if (layer_num != -1)
+ ps->dm_mloopuv_stencil = CustomData_get_layer_n(&ps->dm->loopData, CD_MLOOPUV, layer_num);
+
+ if (ps->dm_mloopuv_stencil == NULL) {
+ /* get active instead */
+ ps->dm_mloopuv_stencil = CustomData_get_layer(&ps->dm->loopData, CD_MLOOPUV);
+ }
+
+ if (ps->do_stencil_brush)
+ mloopuv_base = ps->dm_mloopuv_stencil;
+ }
+
+ /* when using subsurf or multires, mface arrays are thrown away, we need to keep a copy */
+ if (ps->is_shared_user == false) {
+ proj_paint_state_non_cddm_init(ps);
+
+ proj_paint_state_cavity_init(ps);
+ }
+
+ proj_paint_state_viewport_init(ps, symmetry_flag);
+
+ /* calculate vert screen coords
+ * run this early so we can calculate the x/y resolution of our bucket rect */
+ proj_paint_state_screen_coords_init(ps, diameter);
+
+ /* only for convenience */
+ ps->screen_width = ps->screenMax[0] - ps->screenMin[0];
+ ps->screen_height = ps->screenMax[1] - ps->screenMin[1];
+
+ ps->buckets_x = (int)(ps->screen_width / (((float)diameter) / PROJ_BUCKET_BRUSH_DIV));
+ ps->buckets_y = (int)(ps->screen_height / (((float)diameter) / PROJ_BUCKET_BRUSH_DIV));
+
+ /* printf("\tscreenspace bucket division x:%d y:%d\n", ps->buckets_x, ps->buckets_y); */
+
+ if (ps->buckets_x > PROJ_BUCKET_RECT_MAX || ps->buckets_y > PROJ_BUCKET_RECT_MAX) {
+ reset_threads = true;
+ }
+
+ /* really high values could cause problems since it has to allocate a few
+ * (ps->buckets_x*ps->buckets_y) sized arrays */
+ CLAMP(ps->buckets_x, PROJ_BUCKET_RECT_MIN, PROJ_BUCKET_RECT_MAX);
+ CLAMP(ps->buckets_y, PROJ_BUCKET_RECT_MIN, PROJ_BUCKET_RECT_MAX);
+
+ ps->bucketRect = MEM_callocN(sizeof(LinkNode *) * ps->buckets_x * ps->buckets_y, "paint-bucketRect");
+ ps->bucketFaces = MEM_callocN(sizeof(LinkNode *) * ps->buckets_x * ps->buckets_y, "paint-bucketFaces");
+
+ ps->bucketFlags = MEM_callocN(sizeof(char) * ps->buckets_x * ps->buckets_y, "paint-bucketFaces");
+#ifndef PROJ_DEBUG_NOSEAMBLEED
+ if (ps->is_shared_user == false) {
+ proj_paint_state_seam_bleed_init(ps);
+ }
+#endif
+
+ proj_paint_state_thread_init(ps, reset_threads);
+ arena = ps->arena_mt[0];
+
+ proj_paint_state_vert_flags_init(ps);
+
+ project_paint_prepare_all_faces(ps, arena, &face_lookup, &layer_clone, mloopuv_base, is_multi_view);
}
static void paint_proj_begin_clone(ProjPaintState *ps, const float mouse[2])
@@ -3490,7 +3889,7 @@ static void paint_proj_begin_clone(ProjPaintState *ps, const float mouse[2])
if (ps->tool == PAINT_TOOL_CLONE) {
float projCo[4];
copy_v3_v3(projCo, ED_view3d_cursor3d_get(ps->scene, ps->v3d));
- mul_m4_v3(ps->ob->imat, projCo);
+ mul_m4_v3(ps->obmat_imat, projCo);
projCo[3] = 1.0f;
mul_m4_v4(ps->projectMat, projCo);
@@ -3502,14 +3901,16 @@ static void paint_proj_begin_clone(ProjPaintState *ps, const float mouse[2])
static void project_paint_end(ProjPaintState *ps)
{
int a;
- ProjPaintImage *projIma;
image_undo_remove_masks();
/* dereference used image buffers */
- for (a = 0, projIma = ps->projImages; a < ps->image_tot; a++, projIma++) {
- BKE_image_release_ibuf(projIma->ima, projIma->ibuf, NULL);
- DAG_id_tag_update(&projIma->ima->id, 0);
+ if (ps->is_shared_user == false) {
+ ProjPaintImage *projIma;
+ for (a = 0, projIma = ps->projImages; a < ps->image_tot; a++, projIma++) {
+ BKE_image_release_ibuf(projIma->ima, projIma->ibuf, NULL);
+ DAG_id_tag_update(&projIma->ima->id, 0);
+ }
}
BKE_image_release_ibuf(ps->reproject_image, ps->reproject_ibuf, NULL);
@@ -3518,23 +3919,52 @@ static void project_paint_end(ProjPaintState *ps)
MEM_freeN(ps->bucketRect);
MEM_freeN(ps->bucketFaces);
MEM_freeN(ps->bucketFlags);
- MEM_freeN(ps->dm_mtface);
- if (ps->do_layer_clone)
- MEM_freeN(ps->dm_mtface_clone);
- if (ps->thread_tot > 1) {
- BLI_spin_end(ps->tile_lock);
- MEM_freeN((void *)ps->tile_lock);
- }
- image_undo_end_locks();
+
+ if (ps->is_shared_user == false) {
+
+ /* must be set for non-shared */
+ BLI_assert(ps->dm_mloopuv || ps->is_shared_user);
+ if (ps->dm_mloopuv)
+ MEM_freeN(ps->dm_mloopuv);
+
+ if (ps->do_layer_clone)
+ MEM_freeN(ps->dm_mloopuv_clone);
+ if (ps->thread_tot > 1) {
+ BLI_spin_end(ps->tile_lock);
+ MEM_freeN((void *)ps->tile_lock);
+ }
+
+ image_undo_end_locks();
#ifndef PROJ_DEBUG_NOSEAMBLEED
- if (ps->seam_bleed_px > 0.0f) {
- MEM_freeN(ps->vertFaces);
- MEM_freeN(ps->faceSeamFlags);
- MEM_freeN(ps->faceWindingFlags);
- MEM_freeN(ps->faceSeamUVs);
- }
+ if (ps->seam_bleed_px > 0.0f) {
+ MEM_freeN(ps->vertFaces);
+ MEM_freeN(ps->faceSeamFlags);
+ MEM_freeN(ps->faceWindingFlags);
+ MEM_freeN(ps->faceSeamUVs);
+ }
+#endif
+
+ if (ps->do_mask_cavity) {
+ MEM_freeN(ps->cavities);
+ }
+
+ /* copy for subsurf/multires, so throw away */
+ if (ps->dm->type != DM_TYPE_CDDM) {
+ if (ps->dm_mvert) MEM_freeN((void *)ps->dm_mvert);
+ if (ps->dm_mpoly) MEM_freeN((void *)ps->dm_mpoly);
+ if (ps->dm_mloop) MEM_freeN((void *)ps->dm_mloop);
+ /* looks like these don't need copying */
+#if 0
+ if (ps->dm_mloopuv) MEM_freeN(ps->dm_mloopuv);
+ if (ps->dm_mloopuv_clone) MEM_freeN(ps->dm_mloopuv_clone);
+ if (ps->dm_mloopuv_stencil) MEM_freeN(ps->dm_mloopuv_stencil);
#endif
+ }
+
+ if (ps->dm_release)
+ ps->dm->release(ps->dm);
+ }
if (ps->blurkernel) {
paint_delete_blur_kernel(ps->blurkernel);
@@ -3546,36 +3976,25 @@ static void project_paint_end(ProjPaintState *ps)
for (a = 0; a < ps->thread_tot; a++) {
BLI_memarena_free(ps->arena_mt[a]);
}
+}
- /* copy for subsurf/multires, so throw away */
- if (ps->dm->type != DM_TYPE_CDDM) {
- if (ps->dm_mvert) MEM_freeN(ps->dm_mvert);
- if (ps->dm_mface) MEM_freeN(ps->dm_mface);
- /* looks like these don't need copying */
-#if 0
- if (ps->dm_mtface) MEM_freeN(ps->dm_mtface);
- if (ps->dm_mtface_clone) MEM_freeN(ps->dm_mtface_clone);
- if (ps->dm_mtface_stencil) MEM_freeN(ps->dm_mtface_stencil);
-#endif
- }
+/* 1 = an undo, -1 is a redo. */
+static void partial_redraw_single_init(ImagePaintPartialRedraw *pr)
+{
+ pr->x1 = 10000000;
+ pr->y1 = 10000000;
- if (ps->dm_release)
- ps->dm->release(ps->dm);
+ pr->x2 = -1;
+ pr->y2 = -1;
+
+ pr->enabled = 1;
}
-/* 1 = an undo, -1 is a redo. */
static void partial_redraw_array_init(ImagePaintPartialRedraw *pr)
{
int tot = PROJ_BOUNDBOX_SQUARED;
while (tot--) {
- pr->x1 = 10000000;
- pr->y1 = 10000000;
-
- pr->x2 = -1;
- pr->y2 = -1;
-
- pr->enabled = 1;
-
+ partial_redraw_single_init(pr);
pr++;
}
}
@@ -3619,6 +4038,8 @@ static bool project_image_refresh_tagged(ProjPaintState *ps)
imapaint_image_update(NULL, projIma->ima, projIma->ibuf, true);
redraw = 1;
}
+
+ partial_redraw_single_init(pr);
}
projIma->touch = 0; /* clear for reuse */
@@ -3669,7 +4090,9 @@ static bool project_bucket_iter_init(ProjPaintState *ps, const float mval_f[2])
}
-static bool project_bucket_iter_next(ProjPaintState *ps, int *bucket_index, rctf *bucket_bounds, const float mval[2])
+static bool project_bucket_iter_next(
+ ProjPaintState *ps, int *bucket_index,
+ rctf *bucket_bounds, const float mval[2])
{
const int diameter = 2 * ps->brush_size;
@@ -3759,10 +4182,9 @@ static void do_projectpaint_clone_f(ProjPaintState *ps, ProjPixel *projPixel, fl
}
}
-/* do_projectpaint_smear*
- *
- * note, mask is used to modify the alpha here, this is not correct since it allows
- * accumulation of color greater then 'projPixel->mask' however in the case of smear its not
+/**
+ * \note mask is used to modify the alpha here, this is not correct since it allows
+ * accumulation of color greater than 'projPixel->mask' however in the case of smear its not
* really that important to be correct as it is with clone and painting
*/
static void do_projectpaint_smear(ProjPaintState *ps, ProjPixel *projPixel, float mask,
@@ -3825,7 +4247,7 @@ static void do_projectpaint_soften_f(ProjPaintState *ps, ProjPixel *projPixel, f
/* now rgba_ub contains the edge result, but this should be converted to luminance to avoid
* colored speckles appearing in final image, and also to check for threshold */
- rgba[0] = rgba[1] = rgba[2] = rgb_to_grayscale(rgba);
+ rgba[0] = rgba[1] = rgba[2] = IMB_colormanagement_get_luminance(rgba);
if (fabsf(rgba[0]) > ps->brush->sharp_threshold) {
float alpha = projPixel->pixel.f_pt[3];
projPixel->pixel.f_pt[3] = rgba[3] = mask;
@@ -3886,7 +4308,7 @@ static void do_projectpaint_soften(ProjPaintState *ps, ProjPixel *projPixel, flo
sub_v3_v3v3(rgba, rgba_pixel, rgba);
/* now rgba_ub contains the edge result, but this should be converted to luminance to avoid
* colored speckles appearing in final image, and also to check for threshold */
- rgba[0] = rgba[1] = rgba[2] = rgb_to_grayscale(rgba);
+ rgba[0] = rgba[1] = rgba[2] = IMB_colormanagement_get_luminance(rgba);
if (fabsf(rgba[0]) > ps->brush->sharp_threshold) {
float alpha = rgba_pixel[3];
rgba[3] = rgba_pixel[3] = mask;
@@ -3908,20 +4330,28 @@ static void do_projectpaint_soften(ProjPaintState *ps, ProjPixel *projPixel, flo
}
}
-static void do_projectpaint_draw(ProjPaintState *ps, ProjPixel *projPixel, const float texrgb[3], float mask)
+static void do_projectpaint_draw(
+ ProjPaintState *ps, ProjPixel *projPixel, const float texrgb[3], float mask,
+ float dither, float u, float v)
{
float rgb[3];
unsigned char rgba_ub[4];
- copy_v3_v3(rgb, ps->paint_color);
-
if (ps->is_texbrush) {
- mul_v3_v3(rgb, texrgb);
+ mul_v3_v3v3(rgb, texrgb, ps->paint_color_linear);
/* TODO(sergey): Support texture paint color space. */
linearrgb_to_srgb_v3_v3(rgb, rgb);
}
+ else {
+ copy_v3_v3(rgb, ps->paint_color);
+ }
- rgb_float_to_uchar(rgba_ub, rgb);
+ if (dither > 0.0f) {
+ float_to_byte_dither_v3(rgba_ub, rgb, dither, u, v);
+ }
+ else {
+ F3TOCHAR3(rgb, rgba_ub);
+ }
rgba_ub[3] = f_to_char(mask);
if (ps->do_masking) {
@@ -3980,6 +4410,16 @@ static void do_projectpaint_mask_f(ProjPaintState *ps, ProjPixel *projPixel, flo
}
}
+static void image_paint_partial_redraw_expand(
+ ImagePaintPartialRedraw *cell,
+ const ProjPixel *projPixel)
+{
+ cell->x1 = min_ii(cell->x1, (int)projPixel->x_px);
+ cell->y1 = min_ii(cell->y1, (int)projPixel->y_px);
+
+ cell->x2 = max_ii(cell->x2, (int)projPixel->x_px + 1);
+ cell->y2 = max_ii(cell->y2, (int)projPixel->y_px + 1);
+}
/* run this for single and multithreaded painting */
static void *do_projectpaint_thread(void *ph_v)
@@ -4017,7 +4457,8 @@ static void *do_projectpaint_thread(void *ph_v)
const float brush_radius = ps->brush_size;
const float brush_radius_sq = brush_radius * brush_radius; /* avoid a square root with every dist comparison */
- short lock_alpha = ELEM(brush->blend, IMB_BLEND_ERASE_ALPHA, IMB_BLEND_ADD_ALPHA) ? 0 : brush->flag & BRUSH_LOCK_ALPHA;
+ const bool lock_alpha = ELEM(brush->blend, IMB_BLEND_ERASE_ALPHA, IMB_BLEND_ADD_ALPHA) ?
+ 0 : (brush->flag & BRUSH_LOCK_ALPHA) != 0;
LinkNode *smearPixels = NULL;
LinkNode *smearPixels_f = NULL;
@@ -4043,8 +4484,13 @@ static void *do_projectpaint_thread(void *ph_v)
/* Check this bucket and its faces are initialized */
if (ps->bucketFlags[bucket_index] == PROJ_BUCKET_NULL) {
+ rctf clip_rect = bucket_bounds;
+ clip_rect.xmin -= PROJ_PIXEL_TOLERANCE;
+ clip_rect.xmax += PROJ_PIXEL_TOLERANCE;
+ clip_rect.ymin -= PROJ_PIXEL_TOLERANCE;
+ clip_rect.ymax += PROJ_PIXEL_TOLERANCE;
/* No pixels initialized */
- project_bucket_init(ps, thread_index, bucket_index, &bucket_bounds);
+ project_bucket_init(ps, thread_index, bucket_index, &clip_rect, &bucket_bounds);
}
if (ps->source != PROJ_SRC_VIEW) {
@@ -4086,6 +4532,7 @@ static void *do_projectpaint_thread(void *ph_v)
break;
}
case BRUSH_GRADIENT_RADIAL:
+ default:
{
f = len_v2(p) / line_len;
break;
@@ -4101,7 +4548,15 @@ static void *do_projectpaint_thread(void *ph_v)
color_f, ps->blend);
}
else {
- rgba_float_to_uchar(projPixel->newColor.ch, color_f);
+ linearrgb_to_srgb_v3_v3(color_f, color_f);
+
+ if (ps->dither > 0.0f) {
+ float_to_byte_dither_v3(projPixel->newColor.ch, color_f, ps->dither, projPixel->x_px, projPixel->y_px);
+ }
+ else {
+ F3TOCHAR3(color_f, projPixel->newColor.ch);
+ }
+ projPixel->newColor.ch[3] = FTOCHAR(color_f[3]);
IMB_blend_color_byte(projPixel->pixel.ch_pt, projPixel->origColor.ch_pt,
projPixel->newColor.ch, ps->blend);
}
@@ -4126,16 +4581,21 @@ static void *do_projectpaint_thread(void *ph_v)
}
if (lock_alpha) {
- if (is_floatbuf) projPixel->pixel.f_pt[3] = projPixel->origColor.f_pt[3];
- else projPixel->pixel.ch_pt[3] = projPixel->origColor.ch_pt[3];
+ if (is_floatbuf) {
+ /* slightly more involved case since floats are in premultiplied space we need
+ * to make sure alpha is consistent, see T44627 */
+ float rgb_straight[4];
+ premul_to_straight_v4_v4(rgb_straight, projPixel->pixel.f_pt);
+ rgb_straight[3] = projPixel->origColor.f_pt[3];
+ straight_to_premul_v4_v4(projPixel->pixel.f_pt, rgb_straight);
+ }
+ else {
+ projPixel->pixel.ch_pt[3] = projPixel->origColor.ch_pt[3];
+ }
}
last_partial_redraw_cell = last_projIma->partRedrawRect + projPixel->bb_cell_index;
- last_partial_redraw_cell->x1 = min_ii(last_partial_redraw_cell->x1, (int)projPixel->x_px);
- last_partial_redraw_cell->y1 = min_ii(last_partial_redraw_cell->y1, (int)projPixel->y_px);
-
- last_partial_redraw_cell->x2 = max_ii(last_partial_redraw_cell->x2, (int)projPixel->x_px + 1);
- last_partial_redraw_cell->y2 = max_ii(last_partial_redraw_cell->y2, (int)projPixel->y_px + 1);
+ image_paint_partial_redraw_expand(last_partial_redraw_cell, projPixel);
}
else {
if (is_floatbuf) {
@@ -4182,7 +4642,7 @@ static void *do_projectpaint_thread(void *ph_v)
if (dist_sq <= brush_radius_sq) {
dist = sqrtf(dist_sq);
- falloff = BKE_brush_curve_strength_clamp(ps->brush, dist, brush_radius);
+ falloff = BKE_brush_curve_strength_clamped(ps->brush, dist, brush_radius);
if (falloff > 0.0f) {
float texrgb[3];
@@ -4269,11 +4729,7 @@ static void *do_projectpaint_thread(void *ph_v)
*projPixel->valid = true;
last_partial_redraw_cell = last_projIma->partRedrawRect + projPixel->bb_cell_index;
- last_partial_redraw_cell->x1 = min_ii(last_partial_redraw_cell->x1, (int)projPixel->x_px);
- last_partial_redraw_cell->y1 = min_ii(last_partial_redraw_cell->y1, (int)projPixel->y_px);
-
- last_partial_redraw_cell->x2 = max_ii(last_partial_redraw_cell->x2, (int)projPixel->x_px + 1);
- last_partial_redraw_cell->y2 = max_ii(last_partial_redraw_cell->y2, (int)projPixel->y_px + 1);
+ image_paint_partial_redraw_expand(last_partial_redraw_cell, projPixel);
/* texrgb is not used for clone, smear or soften */
switch (tool) {
@@ -4297,14 +4753,23 @@ static void *do_projectpaint_thread(void *ph_v)
break;
default:
if (is_floatbuf) do_projectpaint_draw_f(ps, projPixel, texrgb, mask);
- else do_projectpaint_draw(ps, projPixel, texrgb, mask);
+ else do_projectpaint_draw(ps, projPixel, texrgb, mask, ps->dither, projPixel->x_px, projPixel->y_px);
break;
}
- }
- if (lock_alpha) {
- if (is_floatbuf) projPixel->pixel.f_pt[3] = projPixel->origColor.f_pt[3];
- else projPixel->pixel.ch_pt[3] = projPixel->origColor.ch_pt[3];
+ if (lock_alpha) {
+ if (is_floatbuf) {
+ /* slightly more involved case since floats are in premultiplied space we need
+ * to make sure alpha is consistent, see T44627 */
+ float rgb_straight[4];
+ premul_to_straight_v4_v4(rgb_straight, projPixel->pixel.f_pt);
+ rgb_straight[3] = projPixel->origColor.f_pt[3];
+ straight_to_premul_v4_v4(projPixel->pixel.f_pt, rgb_straight);
+ }
+ else {
+ projPixel->pixel.ch_pt[3] = projPixel->origColor.ch_pt[3];
+ }
+ }
}
/* done painting */
@@ -4381,13 +4846,13 @@ static bool project_paint_op(void *state, const float lastpos[2], const float po
/* thread specific */
handles[a].thread_index = a;
- handles[a].projImages = (ProjPaintImage *)BLI_memarena_alloc(ps->arena_mt[a], ps->image_tot * sizeof(ProjPaintImage));
+ handles[a].projImages = BLI_memarena_alloc(ps->arena_mt[a], ps->image_tot * sizeof(ProjPaintImage));
memcpy(handles[a].projImages, ps->projImages, ps->image_tot * sizeof(ProjPaintImage));
/* image bounds */
for (i = 0; i < ps->image_tot; i++) {
- handles[a].projImages[i].partRedrawRect = (ImagePaintPartialRedraw *)BLI_memarena_alloc(ps->arena_mt[a], sizeof(ImagePaintPartialRedraw) * PROJ_BOUNDBOX_SQUARED);
+ handles[a].projImages[i].partRedrawRect = BLI_memarena_alloc(ps->arena_mt[a], sizeof(ImagePaintPartialRedraw) * PROJ_BOUNDBOX_SQUARED);
memcpy(handles[a].projImages[i].partRedrawRect, ps->projImages[i].partRedrawRect, sizeof(ImagePaintPartialRedraw) * PROJ_BOUNDBOX_SQUARED);
}
@@ -4417,38 +4882,53 @@ static bool project_paint_op(void *state, const float lastpos[2], const float po
touch_any = 1;
}
}
-
+
+ /* calculate pivot for rotation around seletion if needed */
+ if (U.uiflag & USER_ORBIT_SELECTION) {
+ float w[3];
+ int tri_index;
+
+ tri_index = project_paint_PickFace(ps, pos, w);
+
+ if (tri_index != -1) {
+ const MLoopTri *lt = &ps->dm_mlooptri[tri_index];
+ const int lt_vtri[3] = { PS_LOOPTRI_AS_VERT_INDEX_3(ps, lt) };
+ float world[3];
+ UnifiedPaintSettings *ups = &ps->scene->toolsettings->unified_paint_settings;
+
+ interp_v3_v3v3v3(
+ world,
+ ps->dm_mvert[lt_vtri[0]].co,
+ ps->dm_mvert[lt_vtri[1]].co,
+ ps->dm_mvert[lt_vtri[2]].co,
+ w);
+
+ ups->average_stroke_counter++;
+ mul_m4_v3(ps->obmat, world);
+ add_v3_v3(ups->average_stroke_accum, world);
+ ups->last_stroke_valid = true;
+ }
+ }
+
return touch_any;
}
-void paint_proj_stroke(const bContext *C, void *pps, const float prev_pos[2], const float pos[2], const bool eraser, float pressure, float distance, float size)
+static void paint_proj_stroke_ps(
+ const bContext *UNUSED(C), void *ps_handle_p, const float prev_pos[2], const float pos[2],
+ const bool eraser, float pressure, float distance, float size,
+ /* extra view */
+ ProjPaintState *ps
+ )
{
- ProjPaintState *ps = pps;
+ ProjStrokeHandle *ps_handle = ps_handle_p;
Brush *brush = ps->brush;
Scene *scene = ps->scene;
- int a;
ps->brush_size = size;
ps->blend = brush->blend;
if (eraser)
ps->blend = IMB_BLEND_ERASE_ALPHA;
-
- /* clone gets special treatment here to avoid going through image initialization */
- if (ps->tool == PAINT_TOOL_CLONE && ps->mode == BRUSH_STROKE_INVERT) {
- View3D *v3d = ps->v3d;
- float *cursor = ED_view3d_cursor3d_get(scene, v3d);
- int mval_i[2] = {(int)pos[0], (int)pos[1]};
-
- view3d_operator_needs_opengl(C);
-
- if (!ED_view3d_autodist(scene, ps->ar, v3d, mval_i, cursor, false, NULL))
- return;
-
- ED_region_tag_redraw(ps->ar);
-
- return;
- }
/* handle gradient and inverted stroke color here */
if (ps->tool == PAINT_TOOL_DRAW) {
@@ -4469,14 +4949,42 @@ void paint_proj_stroke(const bContext *C, void *pps, const float prev_pos[2], co
}
}
- /* continue adding to existing partial redraw rects until redraw */
- if (!ps->need_redraw) {
- for (a = 0; a < ps->image_tot; a++)
- partial_redraw_array_init(ps->projImages[a].partRedrawRect);
+ if (project_paint_op(ps, prev_pos, pos)) {
+ ps_handle->need_redraw = true;
+ project_image_refresh_tagged(ps);
}
+}
+
- if (project_paint_op(ps, prev_pos, pos))
- ps->need_redraw = true;
+void paint_proj_stroke(
+ const bContext *C, void *ps_handle_p, const float prev_pos[2], const float pos[2],
+ const bool eraser, float pressure, float distance, float size)
+{
+ int i;
+ ProjStrokeHandle *ps_handle = ps_handle_p;
+
+ /* clone gets special treatment here to avoid going through image initialization */
+ if (ps_handle->is_clone_cursor_pick) {
+ Scene *scene = ps_handle->scene;
+ View3D *v3d = CTX_wm_view3d(C);
+ ARegion *ar = CTX_wm_region(C);
+ float *cursor = ED_view3d_cursor3d_get(scene, v3d);
+ int mval_i[2] = {(int)pos[0], (int)pos[1]};
+
+ view3d_operator_needs_opengl(C);
+
+ if (!ED_view3d_autodist(scene, ar, v3d, mval_i, cursor, false, NULL))
+ return;
+
+ ED_region_tag_redraw(ar);
+
+ return;
+ }
+
+ for (i = 0; i < ps_handle->ps_views_tot; i++) {
+ ProjPaintState *ps = ps_handle->ps_views[i];
+ paint_proj_stroke_ps(C, ps_handle_p, prev_pos, pos, eraser, pressure, distance, size, ps);
+ }
}
@@ -4495,7 +5003,7 @@ static void project_state_init(bContext *C, Object *ob, ProjPaintState *ps, int
ps->blend = brush->blend;
/* only check for inversion for the soften tool, elsewhere, a resident brush inversion flag can cause issues */
if (brush->imagepaint_tool == PAINT_TOOL_SOFTEN) {
- ps->mode = ((ps->mode == BRUSH_STROKE_INVERT) ^ ((brush->flag & BRUSH_DIR_IN) != 0) ?
+ ps->mode = (((ps->mode == BRUSH_STROKE_INVERT) ^ ((brush->flag & BRUSH_DIR_IN) != 0)) ?
BRUSH_STROKE_INVERT : BRUSH_STROKE_NORMAL);
ps->blurkernel = paint_new_blur_kernel(brush, true);
@@ -4532,11 +5040,14 @@ static void project_state_init(bContext *C, Object *ob, ProjPaintState *ps, int
ps->clone_ima = (!ps->do_material_slots) ?
settings->imapaint.clone : NULL;
+ ps->do_mask_cavity = (settings->imapaint.paint.flags & PAINT_USE_CAVITY_MASK) ? true : false;
+ ps->cavity_curve = settings->imapaint.paint.cavity_curve;
+
/* setup projection painting data */
if (ps->tool != PAINT_TOOL_FILL) {
- ps->do_backfacecull = (settings->imapaint.flag & IMAGEPAINT_PROJECT_BACKFACE) ? 0 : 1;
- ps->do_occlude = (settings->imapaint.flag & IMAGEPAINT_PROJECT_XRAY) ? 0 : 1;
- ps->do_mask_normal = (settings->imapaint.flag & IMAGEPAINT_PROJECT_FLAT) ? 0 : 1;
+ ps->do_backfacecull = (settings->imapaint.flag & IMAGEPAINT_PROJECT_BACKFACE) ? false : true;
+ ps->do_occlude = (settings->imapaint.flag & IMAGEPAINT_PROJECT_XRAY) ? false : true;
+ ps->do_mask_normal = (settings->imapaint.flag & IMAGEPAINT_PROJECT_FLAT) ? false : true;
}
else {
ps->do_backfacecull = ps->do_occlude = ps->do_mask_normal = 0;
@@ -4573,60 +5084,126 @@ static void project_state_init(bContext *C, Object *ob, ProjPaintState *ps, int
if (ps->normal_angle_range <= 0.0f)
ps->do_mask_normal = false; /* no need to do blending */
+ ps->normal_angle__cos = cosf(ps->normal_angle);
+ ps->normal_angle_inner__cos = cosf(ps->normal_angle_inner);
+
+ ps->dither = settings->imapaint.dither;
+
return;
}
void *paint_proj_new_stroke(bContext *C, Object *ob, const float mouse[2], int mode)
{
- ProjPaintState *ps = MEM_callocN(sizeof(ProjPaintState), "ProjectionPaintState");
+ ProjStrokeHandle *ps_handle;
+ Scene *scene = CTX_data_scene(C);
+ ToolSettings *settings = scene->toolsettings;
+ int i;
+ bool is_multi_view;
+ char symmetry_flag_views[ARRAY_SIZE(ps_handle->ps_views)] = {0};
- project_state_init(C, ob, ps, mode);
+ ps_handle = MEM_callocN(sizeof(ProjStrokeHandle), "ProjStrokeHandle");
+ ps_handle->scene = scene;
+ ps_handle->brush = BKE_paint_brush(&settings->imapaint.paint);
- if (ps->tool == PAINT_TOOL_CLONE && mode == BRUSH_STROKE_INVERT) {
+ /* bypass regular stroke logic */
+ if ((ps_handle->brush->imagepaint_tool == PAINT_TOOL_CLONE) &&
+ (mode == BRUSH_STROKE_INVERT))
+ {
view3d_operator_needs_opengl(C);
- return ps;
+ ps_handle->is_clone_cursor_pick = true;
+ return ps_handle;
}
- paint_brush_init_tex(ps->brush);
+ ps_handle->orig_brush_size = BKE_brush_size_get(scene, ps_handle->brush);
- ps->source = PROJ_SRC_VIEW;
+ ps_handle->symmetry_flags = settings->imapaint.paint.symmetry_flags & PAINT_SYMM_AXIS_ALL;
+ ps_handle->ps_views_tot = 1 + (pow_i(2, count_bits_i(ps_handle->symmetry_flags)) - 1);
+ is_multi_view = (ps_handle->ps_views_tot != 1);
- if (ps->ob == NULL || !(ps->ob->lay & ps->v3d->lay)) {
- MEM_freeN(ps);
- return NULL;
+ for (i = 0; i < ps_handle->ps_views_tot; i++) {
+ ProjPaintState *ps = MEM_callocN(sizeof(ProjPaintState), "ProjectionPaintState");
+ ps_handle->ps_views[i] = ps;
}
- ps->orig_brush_size = BKE_brush_size_get(ps->scene, ps->brush);
+ if (ps_handle->symmetry_flags) {
+ int index = 0;
+
+ int x = 0;
+ do {
+ int y = 0;
+ do {
+ int z = 0;
+ do {
+ symmetry_flag_views[index++] = (
+ (x ? PAINT_SYMM_X : 0) |
+ (y ? PAINT_SYMM_Y : 0) |
+ (z ? PAINT_SYMM_Z : 0));
+ BLI_assert(index <= ps_handle->ps_views_tot);
+ } while ((z++ == 0) && (ps_handle->symmetry_flags & PAINT_SYMM_Z));
+ } while ((y++ == 0) && (ps_handle->symmetry_flags & PAINT_SYMM_Y));
+ } while ((x++ == 0) && (ps_handle->symmetry_flags & PAINT_SYMM_X));
+ BLI_assert(index == ps_handle->ps_views_tot);
+ }
+
+ for (i = 0; i < ps_handle->ps_views_tot; i++) {
+ ProjPaintState *ps = ps_handle->ps_views[i];
+
+ project_state_init(C, ob, ps, mode);
+
+ if (ps->ob == NULL || !(ps->ob->lay & ps->v3d->lay)) {
+ ps_handle->ps_views_tot = i + 1;
+ goto fail;
+ }
+ }
/* Don't allow brush size below 2 */
- if (BKE_brush_size_get(ps->scene, ps->brush) < 2)
- BKE_brush_size_set(ps->scene, ps->brush, 2);
+ if (BKE_brush_size_get(scene, ps_handle->brush) < 2)
+ BKE_brush_size_set(scene, ps_handle->brush, 2 * U.pixelsize);
/* allocate and initialize spatial data structures */
- project_paint_begin(ps);
- if (ps->dm == NULL) {
- MEM_freeN(ps);
- return NULL;
+ for (i = 0; i < ps_handle->ps_views_tot; i++) {
+ ProjPaintState *ps = ps_handle->ps_views[i];
+
+ ps->source = (ps->tool == PAINT_TOOL_FILL) ? PROJ_SRC_VIEW_FILL : PROJ_SRC_VIEW;
+ project_image_refresh_tagged(ps);
+
+ /* re-use! */
+ if (i != 0) {
+ ps->is_shared_user = true;
+ PROJ_PAINT_STATE_SHARED_MEMCPY(ps, ps_handle->ps_views[0]);
+ }
+
+ project_paint_begin(ps, is_multi_view, symmetry_flag_views[i]);
+
+ paint_proj_begin_clone(ps, mouse);
+
+ if (ps->dm == NULL) {
+ goto fail;
+ return NULL;
+ }
}
- paint_proj_begin_clone(ps, mouse);
+ paint_brush_init_tex(ps_handle->brush);
- /* special full screen draw mode for fill tool */
- if (ps->tool == PAINT_TOOL_FILL)
- ps->source = PROJ_SRC_VIEW_FILL;
+ return ps_handle;
- return ps;
+
+fail:
+ for (i = 0; i < ps_handle->ps_views_tot; i++) {
+ ProjPaintState *ps = ps_handle->ps_views[i];
+ MEM_freeN(ps);
+ }
+ MEM_freeN(ps_handle);
+ return NULL;
}
-void paint_proj_redraw(const bContext *C, void *pps, bool final)
+void paint_proj_redraw(const bContext *C, void *ps_handle_p, bool final)
{
- ProjPaintState *ps = pps;
+ ProjStrokeHandle *ps_handle = ps_handle_p;
- if (ps->need_redraw) {
- project_image_refresh_tagged(ps);
-
- ps->need_redraw = false;
+ if (ps_handle->need_redraw) {
+ ps_handle->need_redraw = false;
}
else if (!final) {
return;
@@ -4641,19 +5218,34 @@ void paint_proj_redraw(const bContext *C, void *pps, bool final)
}
}
-void paint_proj_stroke_done(void *pps)
+void paint_proj_stroke_done(void *ps_handle_p)
{
- ProjPaintState *ps = pps;
- if (ps->tool == PAINT_TOOL_CLONE && ps->mode == BRUSH_STROKE_INVERT) {
- MEM_freeN(ps);
+ ProjStrokeHandle *ps_handle = ps_handle_p;
+ Scene *scene = ps_handle->scene;
+ int i;
+
+ if (ps_handle->is_clone_cursor_pick) {
+ MEM_freeN(ps_handle);
return;
}
- BKE_brush_size_set(ps->scene, ps->brush, ps->orig_brush_size);
- paint_brush_exit_tex(ps->brush);
+ for (i = 1; i < ps_handle->ps_views_tot; i++) {
+ PROJ_PAINT_STATE_SHARED_CLEAR(ps_handle->ps_views[i]);
+ }
+
+ BKE_brush_size_set(scene, ps_handle->brush, ps_handle->orig_brush_size);
+
+ paint_brush_exit_tex(ps_handle->brush);
+
+ for (i = 0; i < ps_handle->ps_views_tot; i++) {
+ ProjPaintState *ps;
+ ps = ps_handle->ps_views[i];
+ project_paint_end(ps);
+ MEM_freeN(ps);
+
+ }
- project_paint_end(ps);
- MEM_freeN(ps);
+ MEM_freeN(ps_handle);
}
/* use project paint to re-apply an image */
static int texture_paint_camera_project_exec(bContext *C, wmOperator *op)
@@ -4665,13 +5257,18 @@ static int texture_paint_camera_project_exec(bContext *C, wmOperator *op)
IDProperty *idgroup;
IDProperty *view_data = NULL;
Object *ob = OBACT;
+ bool uvs, mat, tex;
if (ob == NULL || ob->type != OB_MESH) {
BKE_report(op->reports, RPT_ERROR, "No active mesh object");
return OPERATOR_CANCELLED;
}
- paint_proj_mesh_data_ensure(C, ob, op);
+ if (!BKE_paint_proj_mesh_data_check(scene, ob, &uvs, &mat, &tex, NULL)) {
+ BKE_paint_data_warning(op->reports, uvs, mat, tex, true);
+ WM_event_add_notifier(C, NC_SCENE | ND_TOOLSETTINGS, NULL);
+ return OPERATOR_CANCELLED;
+ }
project_state_init(C, ob, &ps, BRUSH_STROKE_NORMAL);
@@ -4718,7 +5315,7 @@ static int texture_paint_camera_project_exec(bContext *C, wmOperator *op)
ps.is_maskbrush = false;
ps.do_masking = false;
orig_brush_size = BKE_brush_size_get(scene, ps.brush);
- BKE_brush_size_set(scene, ps.brush, 32); /* cover the whole image */
+ BKE_brush_size_set(scene, ps.brush, 32 * U.pixelsize); /* cover the whole image */
ps.tool = PAINT_TOOL_DRAW; /* so pixels are initialized with minimal info */
@@ -4728,7 +5325,7 @@ static int texture_paint_camera_project_exec(bContext *C, wmOperator *op)
ED_image_undo_restore, ED_image_undo_free, NULL);
/* allocate and initialize spatial data structures */
- project_paint_begin(&ps);
+ project_paint_begin(&ps, false, 0);
if (ps.dm == NULL) {
BKE_brush_size_set(scene, ps.brush, orig_brush_size);
@@ -4802,7 +5399,7 @@ static int texture_paint_image_from_view_exec(bContext *C, wmOperator *op)
if (w > maxsize) w = maxsize;
if (h > maxsize) h = maxsize;
- ibuf = ED_view3d_draw_offscreen_imbuf(scene, CTX_wm_view3d(C), CTX_wm_region(C), w, h, IB_rect, false, R_ALPHAPREMUL, err_out);
+ ibuf = ED_view3d_draw_offscreen_imbuf(scene, CTX_wm_view3d(C), CTX_wm_region(C), w, h, IB_rect, false, R_ALPHAPREMUL, NULL, err_out);
if (!ibuf) {
/* Mostly happens when OpenGL offscreen buffer was failed to create, */
/* but could be other reasons. Should be handled in the future. nazgul */
@@ -4810,10 +5407,13 @@ static int texture_paint_image_from_view_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
- image = BKE_image_add_from_imbuf(ibuf);
+ image = BKE_image_add_from_imbuf(ibuf, "image_view");
+
+ /* Drop reference to ibuf so that the image owns it */
+ IMB_freeImBuf(ibuf);
if (image) {
- /* now for the trickyness. store the view projection here!
+ /* now for the trickiness. store the view projection here!
* re-projection will reuse this */
View3D *v3d = CTX_wm_view3d(C);
RegionView3D *rv3d = CTX_wm_region_view3d(C);
@@ -4832,11 +5432,11 @@ static int texture_paint_image_from_view_exec(bContext *C, wmOperator *op)
memcpy(array, rv3d->winmat, sizeof(rv3d->winmat)); array += sizeof(rv3d->winmat) / sizeof(float);
memcpy(array, rv3d->viewmat, sizeof(rv3d->viewmat)); array += sizeof(rv3d->viewmat) / sizeof(float);
is_ortho = ED_view3d_clip_range_get(v3d, rv3d, &array[0], &array[1], true);
- array[2] = is_ortho ? 1.0f : 0.0f; /* using float for a bool is dodgy but since its an extra member in the array... easier then adding a single bool prop */
+ /* using float for a bool is dodgy but since its an extra member in the array...
+ * easier then adding a single bool prop */
+ array[2] = is_ortho ? 1.0f : 0.0f;
IDP_AddToGroup(idgroup, view_data);
-
- rename_id(&image->id, "image_view");
}
return OPERATOR_FINISHED;
@@ -4863,110 +5463,78 @@ void PAINT_OT_image_from_view(wmOperatorType *ot)
* Data generation for projective texturing *
* *******************************************/
+void BKE_paint_data_warning(struct ReportList *reports, bool uvs, bool mat, bool tex, bool stencil)
+{
+ BKE_reportf(reports, RPT_WARNING, "Missing%s%s%s%s detected!",
+ !uvs ? " UVs," : "",
+ !mat ? " Materials," : "",
+ !tex ? " Textures," : "",
+ !stencil ? " Stencil," : ""
+ );
+}
/* Make sure that active object has a material, and assign UVs and image layers if they do not exist */
-void paint_proj_mesh_data_ensure(bContext *C, Object *ob, wmOperator *op)
+bool BKE_paint_proj_mesh_data_check(Scene *scene, Object *ob, bool *uvs, bool *mat, bool *tex, bool *stencil)
{
Mesh *me;
int layernum;
- ImagePaintSettings *imapaint = &(CTX_data_tool_settings(C)->imapaint);
- bScreen *sc;
- Scene *scene = CTX_data_scene(C);
- Main *bmain = CTX_data_main(C);
+ ImagePaintSettings *imapaint = &scene->toolsettings->imapaint;
Brush *br = BKE_paint_brush(&imapaint->paint);
+ bool hasmat = true;
+ bool hastex = true;
+ bool hasstencil = true;
+ bool hasuvs = true;
+ imapaint->missing_data = 0;
+
BLI_assert(ob->type == OB_MESH);
- /* no material, add one */
- if (ob->totcol == 0) {
- Material *ma = BKE_material_add(CTX_data_main(C), "Material");
- /* no material found, just assign to first slot */
- assign_material(ob, ma, 1, BKE_MAT_ASSIGN_USERPREF);
- proj_paint_add_slot(C, ma, NULL);
- }
- else {
- /* there may be material slots but they may be empty, check */
- int i;
-
- for (i = 1; i < ob->totcol + 1; i++) {
- Material *ma = give_current_material(ob, i);
-
- if (ma) {
- if (imapaint->mode == IMAGEPAINT_MODE_MATERIAL) {
+ if (imapaint->mode == IMAGEPAINT_MODE_MATERIAL) {
+ /* no material, add one */
+ if (ob->totcol == 0) {
+ hasmat = false;
+ hastex = false;
+ }
+ else {
+ /* there may be material slots but they may be empty, check */
+ int i;
+ hasmat = false;
+ hastex = false;
+
+ for (i = 1; i < ob->totcol + 1; i++) {
+ Material *ma = give_current_material(ob, i);
+
+ if (ma) {
+ hasmat = true;
if (!ma->texpaintslot) {
/* refresh here just in case */
- BKE_texpaint_slot_refresh_cache(scene, ma);
+ BKE_texpaint_slot_refresh_cache(scene, ma);
/* if still no slots, we have to add */
- if (!ma->texpaintslot) {
- proj_paint_add_slot(C, ma, NULL);
-
- if (ma->texpaintslot) {
- for (sc = bmain->screen.first; sc; sc = sc->id.next) {
- ScrArea *sa;
- for (sa = sc->areabase.first; sa; sa = sa->next) {
- SpaceLink *sl;
- for (sl = sa->spacedata.first; sl; sl = sl->next) {
- if (sl->spacetype == SPACE_IMAGE) {
- SpaceImage *sima = (SpaceImage *)sl;
-
- if (!sima->pin)
- ED_space_image_set(sima, scene, scene->obedit, ma->texpaintslot[0].ima);
- }
- }
- }
- }
- }
+ if (ma->texpaintslot) {
+ hastex = true;
+ break;
}
}
+ else {
+ hastex = true;
+ break;
+ }
}
}
- else {
- Material *ma = BKE_material_add(CTX_data_main(C), "Material");
- /* no material found, just assign to first slot */
- assign_material(ob, ma, i, BKE_MAT_ASSIGN_USERPREF);
- proj_paint_add_slot(C, ma, NULL);
- }
}
}
-
- if (imapaint->mode == IMAGEPAINT_MODE_IMAGE) {
+ else if (imapaint->mode == IMAGEPAINT_MODE_IMAGE) {
if (imapaint->canvas == NULL) {
- int width;
- int height;
- Main *bmain = CTX_data_main(C);
- float color[4] = {0.0, 0.0, 0.0, 1.0};
-
- width = 1024;
- height = 1024;
- imapaint->canvas = BKE_image_add_generated(bmain, width, height, "Canvas", 32, false, IMA_GENTYPE_BLANK, color);
-
- GPU_drawobject_free(ob->derivedFinal);
-
- for (sc = bmain->screen.first; sc; sc = sc->id.next) {
- ScrArea *sa;
- for (sa = sc->areabase.first; sa; sa = sa->next) {
- SpaceLink *sl;
- for (sl = sa->spacedata.first; sl; sl = sl->next) {
- if (sl->spacetype == SPACE_IMAGE) {
- SpaceImage *sima = (SpaceImage *)sl;
-
- if (!sima->pin)
- ED_space_image_set(sima, scene, scene->obedit, imapaint->canvas);
- }
- }
- }
- }
- }
+ hastex = false;
+ }
}
-
+
me = BKE_mesh_from_object(ob);
layernum = CustomData_number_of_layers(&me->pdata, CD_MTEXPOLY);
if (layernum == 0) {
- BKE_reportf(op->reports, RPT_WARNING, "Object did not have UV map, manual unwrap recommended");
-
- ED_mesh_uv_texture_add(me, "UVMap", true);
+ hasuvs = false;
}
/* Make sure we have a stencil to paint on! */
@@ -4974,16 +5542,29 @@ void paint_proj_mesh_data_ensure(bContext *C, Object *ob, wmOperator *op)
imapaint->flag |= IMAGEPAINT_PROJECT_LAYER_STENCIL;
if (imapaint->stencil == NULL) {
- int width;
- int height;
- Main *bmain = CTX_data_main(C);
- float color[4] = {0.0, 0.0, 0.0, 1.0};
-
- width = 1024;
- height = 1024;
- imapaint->stencil = BKE_image_add_generated(bmain, width, height, "Stencil", 32, false, IMA_GENTYPE_BLANK, color);
+ hasstencil = false;
}
}
+
+ if (!hasuvs) imapaint->missing_data |= IMAGEPAINT_MISSING_UVS;
+ if (!hasmat) imapaint->missing_data |= IMAGEPAINT_MISSING_MATERIAL;
+ if (!hastex) imapaint->missing_data |= IMAGEPAINT_MISSING_TEX;
+ if (!hasstencil) imapaint->missing_data |= IMAGEPAINT_MISSING_STENCIL;
+
+ if (uvs) {
+ *uvs = hasuvs;
+ }
+ if (mat) {
+ *mat = hasmat;
+ }
+ if (tex) {
+ *tex = hastex;
+ }
+ if (stencil) {
+ *stencil = hasstencil;
+ }
+
+ return hasuvs && hasmat && hastex && hasstencil;
}
/* Add layer operator */
@@ -4997,7 +5578,7 @@ static EnumPropertyItem layer_type_items[] = {
{MAP_SPEC, "SPECULAR_INTENSITY", 0, "Specular Intensity", ""},
{MAP_HAR, "SPECULAR_HARDNESS", 0, "Specular Hardness", ""},
{MAP_AMB, "AMBIENT", 0, "Ambient", ""},
- {MAP_EMIT, "EMMIT", 0, "Emmit", ""},
+ {MAP_EMIT, "EMIT", 0, "Emit", ""},
{MAP_COLMIR, "MIRROR_COLOR", 0, "Mirror Color", ""},
{MAP_RAYMIRR, "RAYMIRROR", 0, "Ray Mirror", ""},
{MAP_NORM, "NORMAL", 0, "Normal", ""},
@@ -5006,30 +5587,74 @@ static EnumPropertyItem layer_type_items[] = {
{0, NULL, 0, NULL, NULL}
};
-bool proj_paint_add_slot(bContext *C, Material *ma, wmOperator *op)
+static Image *proj_paint_image_create(wmOperator *op, Main *bmain)
+{
+ Image *ima;
+ float color[4] = {0.0f, 0.0f, 0.0f, 1.0f};
+ char imagename[MAX_ID_NAME - 2] = "Material Diffuse Color";
+ int width = 1024;
+ int height = 1024;
+ bool use_float = false;
+ short gen_type = IMA_GENTYPE_BLANK;
+ bool alpha = false;
+
+ if (op) {
+ width = RNA_int_get(op->ptr, "width");
+ height = RNA_int_get(op->ptr, "height");
+ use_float = RNA_boolean_get(op->ptr, "float");
+ gen_type = RNA_enum_get(op->ptr, "generated_type");
+ RNA_float_get_array(op->ptr, "color", color);
+ alpha = RNA_boolean_get(op->ptr, "alpha");
+ RNA_string_get(op->ptr, "name", imagename);
+ }
+ ima = BKE_image_add_generated(bmain, width, height, imagename, alpha ? 32 : 24, use_float,
+ gen_type, color, false);
+
+ return ima;
+}
+
+static bool proj_paint_add_slot(bContext *C, wmOperator *op)
{
Object *ob = CTX_data_active_object(C);
Scene *scene = CTX_data_scene(C);
- bool is_bi = BKE_scene_uses_blender_internal(scene);
+ Material *ma;
+ bool is_bi = BKE_scene_uses_blender_internal(scene) || BKE_scene_uses_blender_game(scene);
+ Image *ima = NULL;
if (!ob)
return false;
- if (!ma)
- ma = give_current_material(ob, ob->actcol);
+ ma = give_current_material(ob, ob->actcol);
if (ma) {
+ Main *bmain = CTX_data_main(C);
+
+ if (!is_bi && BKE_scene_use_new_shading_nodes(scene)) {
+ bNode *imanode;
+ bNodeTree *ntree = ma->nodetree;
- if (!is_bi || ma->use_nodes) {
- /* not supported for now */
+ if (!ntree) {
+ ED_node_shader_default(C, &ma->id);
+ ntree = ma->nodetree;
+ }
+
+ ma->use_nodes = true;
+
+ /* try to add an image node */
+ imanode = nodeAddStaticNode(C, ntree, SH_NODE_TEX_IMAGE);
+
+ ima = proj_paint_image_create(op, bmain);
+ imanode->id = &ima->id;
+
+ nodeSetActive(ntree, imanode);
+
+ ntreeUpdateTree(CTX_data_main(C), ntree);
}
else {
- MTex *mtex = add_mtex_id(&ma->id, -1);
+ MTex *mtex = BKE_texture_mtex_add_id(&ma->id, -1);
/* successful creation of mtex layer, now create set */
if (mtex) {
- Main *bmain = CTX_data_main(C);
- Image *ima;
int type = MAP_COL;
int type_id = 0;
@@ -5045,51 +5670,41 @@ bool proj_paint_add_slot(bContext *C, Material *ma, wmOperator *op)
}
}
- mtex->tex = add_texture(bmain, DATA_(layer_type_items[type_id].name));
+ mtex->tex = BKE_texture_add(bmain, DATA_(layer_type_items[type_id].name));
mtex->mapto = type;
if (mtex->tex) {
- float color[4] = {0.0f, 0.0f, 0.0f, 1.0f};
- char imagename[MAX_ID_NAME - 2] = "Material Diffuse Color";
- int width = 1024;
- int height = 1024;
- bool use_float = false;
- short gen_type = IMA_GENTYPE_BLANK;
- bool alpha = false;
-
- if (op) {
- width = RNA_int_get(op->ptr, "width");
- height = RNA_int_get(op->ptr, "height");
- use_float = RNA_boolean_get(op->ptr, "float");
- gen_type = RNA_enum_get(op->ptr, "generated_type");
- RNA_float_get_array(op->ptr, "color", color);
- alpha = RNA_boolean_get(op->ptr, "alpha");
- RNA_string_get(op->ptr, "name", imagename);
- }
-
- ima = mtex->tex->ima = BKE_image_add_generated(bmain, width, height, imagename, alpha ? 32 : 24, use_float,
- gen_type, color);
-
- BKE_texpaint_slot_refresh_cache(scene, ma);
- BKE_image_signal(ima, NULL, IMA_SIGNAL_USER_NEW_IMAGE);
- WM_event_add_notifier(C, NC_TEXTURE | NA_ADDED, mtex->tex);
- WM_event_add_notifier(C, NC_IMAGE | NA_ADDED, ima);
- DAG_id_tag_update(&ma->id, 0);
- ED_area_tag_redraw(CTX_wm_area(C));
+ ima = mtex->tex->ima = proj_paint_image_create(op, bmain);
}
- WM_event_add_notifier(C, NC_TEXTURE, CTX_data_scene(C));
- return true;
+ WM_event_add_notifier(C, NC_TEXTURE | NA_ADDED, mtex->tex);
}
}
+
+ if (ima) {
+ BKE_texpaint_slot_refresh_cache(scene, ma);
+ BKE_image_signal(ima, NULL, IMA_SIGNAL_USER_NEW_IMAGE);
+ WM_event_add_notifier(C, NC_IMAGE | NA_ADDED, ima);
+ DAG_id_tag_update(&ma->id, 0);
+ ED_area_tag_redraw(CTX_wm_area(C));
+
+ BKE_paint_proj_mesh_data_check(scene, ob, NULL, NULL, NULL, NULL);
+
+ return true;
+ }
}
-
+
return false;
}
static int texture_paint_add_texture_paint_slot_exec(bContext *C, wmOperator *op)
{
- return proj_paint_add_slot(C, NULL, op);
+ if (proj_paint_add_slot(C, op)) {
+ return OPERATOR_FINISHED;
+ }
+ else {
+ return OPERATOR_CANCELLED;
+ }
}
@@ -5100,6 +5715,12 @@ static int texture_paint_add_texture_paint_slot_invoke(bContext *C, wmOperator *
Material *ma = give_current_material(ob, ob->actcol);
int type = RNA_enum_get(op->ptr, "type");
+ if (!ma) {
+ ma = BKE_material_add(CTX_data_main(C), "Material");
+ /* no material found, just assign to first slot */
+ assign_material(ob, ma, ob->actcol, BKE_MAT_ASSIGN_USERPREF);
+ }
+
type = RNA_enum_from_value(layer_type_items, type);
/* get the name of the texture layer type */
@@ -5131,7 +5752,7 @@ void PAINT_OT_add_texture_paint_slot(wmOperatorType *ot)
ot->poll = ED_operator_region_view3d_active;
/* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ ot->flag = OPTYPE_UNDO;
/* properties */
prop = RNA_def_enum(ot->srna, "type", layer_type_items, 0, "Type", "Merge method to use");
@@ -5155,7 +5776,7 @@ static int texture_paint_delete_texture_paint_slot_exec(bContext *C, wmOperator
Object *ob = CTX_data_active_object(C);
Scene *scene = CTX_data_scene(C);
Material *ma;
- bool is_bi = BKE_scene_uses_blender_internal(scene);
+ bool is_bi = BKE_scene_uses_blender_internal(scene) || BKE_scene_uses_blender_game(scene);
TexPaintSlot *slot;
/* not supported for node-based engines */
@@ -5169,16 +5790,21 @@ static int texture_paint_delete_texture_paint_slot_exec(bContext *C, wmOperator
slot = ma->texpaintslot + ma->paint_active_slot;
- if (ma->mtex[slot->index]->tex)
+ if (ma->mtex[slot->index]->tex) {
id_us_min(&ma->mtex[slot->index]->tex->id);
+
+ if (ma->mtex[slot->index]->tex->ima) {
+ id_us_min(&ma->mtex[slot->index]->tex->ima->id);
+ }
+ }
MEM_freeN(ma->mtex[slot->index]);
ma->mtex[slot->index] = NULL;
BKE_texpaint_slot_refresh_cache(scene, ma);
DAG_id_tag_update(&ma->id, 0);
- WM_event_add_notifier(C, NC_MATERIAL, CTX_data_scene(C));
+ WM_event_add_notifier(C, NC_MATERIAL, ma);
/* we need a notifier for data change since we change the displayed modifier uvs */
- WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
return OPERATOR_FINISHED;
}
@@ -5187,7 +5813,7 @@ void PAINT_OT_delete_texture_paint_slot(wmOperatorType *ot)
{
/* identifiers */
ot->name = "Delete Texture Paint Slot";
- ot->description = "Add a texture paint slot";
+ ot->description = "Delete selected texture paint slot";
ot->idname = "PAINT_OT_delete_texture_paint_slot";
/* api callbacks */
@@ -5197,3 +5823,66 @@ void PAINT_OT_delete_texture_paint_slot(wmOperatorType *ot)
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
+
+static int add_simple_uvs_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ /* no checks here, poll function does them for us */
+ Object *ob = CTX_data_active_object(C);
+ Scene *scene = CTX_data_scene(C);
+ Mesh *me = ob->data;
+ bool synch_selection = (scene->toolsettings->uv_flag & UV_SYNC_SELECTION) != 0;
+
+ BMesh *bm = BM_mesh_create(&bm_mesh_allocsize_default);
+
+ /* turn synch selection off, since we are not in edit mode we need to ensure only the uv flags are tested */
+ scene->toolsettings->uv_flag &= ~UV_SYNC_SELECTION;
+
+ ED_mesh_uv_texture_ensure(me, NULL);
+
+ BM_mesh_bm_from_me(bm, me, true, false, 0);
+
+ /* select all uv loops first - pack parameters needs this to make sure charts are registered */
+ ED_uvedit_select_all(bm);
+ ED_uvedit_unwrap_cube_project(ob, bm, 1.0, false);
+ /* set the margin really quickly before the packing operation*/
+ scene->toolsettings->uvcalc_margin = 0.001f;
+ ED_uvedit_pack_islands(scene, ob, bm, false, false, true);
+ BM_mesh_bm_to_me(bm, me, false);
+ BM_mesh_free(bm);
+
+ if (synch_selection)
+ scene->toolsettings->uv_flag |= UV_SYNC_SELECTION;
+
+ BKE_paint_proj_mesh_data_check(scene, ob, NULL, NULL, NULL, NULL);
+
+ DAG_id_tag_update(ob->data, 0);
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
+ WM_event_add_notifier(C, NC_SCENE | ND_TOOLSETTINGS, scene);
+ return OPERATOR_FINISHED;
+}
+
+static int add_simple_uvs_poll(bContext *C)
+{
+ Object *ob = CTX_data_active_object(C);
+
+ if (!ob || ob->type != OB_MESH || ob->mode != OB_MODE_TEXTURE_PAINT)
+ return false;
+
+ return true;
+}
+
+void PAINT_OT_add_simple_uvs(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Add simple UVs";
+ ot->description = "Add cube map uvs on mesh";
+ ot->idname = "PAINT_OT_add_simple_uvs";
+
+ /* api callbacks */
+ ot->exec = add_simple_uvs_exec;
+ ot->poll = add_simple_uvs_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
diff --git a/source/blender/editors/sculpt_paint/paint_intern.h b/source/blender/editors/sculpt_paint/paint_intern.h
index 5e1ac0cf8a8..fd7e053fea3 100644
--- a/source/blender/editors/sculpt_paint/paint_intern.h
+++ b/source/blender/editors/sculpt_paint/paint_intern.h
@@ -34,14 +34,11 @@
struct ARegion;
struct bContext;
-struct bglMats;
struct Brush;
struct ImagePool;
struct ColorSpace;
struct ColorManagedDisplay;
struct ListBase;
-struct Material;
-struct Mesh;
struct MTex;
struct Object;
struct PaintStroke;
@@ -55,7 +52,6 @@ struct ViewContext;
struct wmEvent;
struct wmOperator;
struct wmOperatorType;
-struct ImagePaintState;
struct wmWindowManager;
struct DMCoNo;
enum PaintMode;
@@ -149,7 +145,7 @@ typedef struct ImagePaintPartialRedraw {
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, bool validate);
-void *image_undo_push_tile(struct Image *ima, struct ImBuf *ibuf, struct ImBuf **tmpibuf, int x_tile, int y_tile, unsigned short **, bool **valid, bool proj);
+void *image_undo_push_tile(struct Image *ima, struct ImBuf *ibuf, struct ImBuf **tmpibuf, int x_tile, int y_tile, unsigned short **, bool **valid, bool proj, bool find_prev);
void image_undo_remove_masks(void);
void image_undo_init_locks(void);
void image_undo_end_locks(void);
@@ -164,13 +160,11 @@ void paint_2d_redraw(const bContext *C, void *ps, bool final);
void paint_2d_stroke_done(void *ps);
void paint_2d_stroke(void *ps, const float prev_mval[2], const float mval[2], const bool eraser, float pressure, float distance, float size);
void paint_2d_bucket_fill(const struct bContext *C, const float color[3], struct Brush *br, const float mouse_init[2], void *ps);
-void paint_2d_gradient_fill (const struct bContext *C, struct Brush *br, const float mouse_init[2], const float mouse_final[2], void *ps);
+void paint_2d_gradient_fill(const struct bContext *C, struct Brush *br, const float mouse_init[2], const float mouse_final[2], void *ps);
void *paint_proj_new_stroke(struct bContext *C, struct Object *ob, const float mouse[2], int mode);
void paint_proj_stroke(const struct bContext *C, void *ps, const float prevmval_i[2], const float mval_i[2], const bool eraser, float pressure, float distance, float size);
void paint_proj_redraw(const struct bContext *C, void *pps, bool final);
void paint_proj_stroke_done(void *ps);
-void paint_proj_mesh_data_ensure(bContext *C, struct Object *ob, struct wmOperator *op);
-bool proj_paint_add_slot(bContext *C, struct Material *ma, struct wmOperator *op);
void paint_brush_color_get(struct Scene *scene, struct Brush *br, bool color_correction, bool invert, float distance, float pressure, float color[3], struct ColorManagedDisplay *display);
bool paint_use_opacity_masking(struct Brush *brush);
@@ -186,6 +180,7 @@ void PAINT_OT_image_from_view(struct wmOperatorType *ot);
void PAINT_OT_add_texture_paint_slot(struct wmOperatorType *ot);
void PAINT_OT_delete_texture_paint_slot(struct wmOperatorType *ot);
void PAINT_OT_image_paint(struct wmOperatorType *ot);
+void PAINT_OT_add_simple_uvs(struct wmOperatorType *ot);
/* uv sculpting */
int uv_sculpt_poll(struct bContext *C);
@@ -246,6 +241,18 @@ typedef enum BrushStrokeMode {
BRUSH_STROKE_SMOOTH
} BrushStrokeMode;
+/* paint_ops.c */
+typedef enum {
+ RC_COLOR = 1,
+ RC_ROTATION = 2,
+ RC_ZOOM = 4,
+ RC_WEIGHT = 8,
+ RC_SECONDARY_ROTATION = 16
+} RCFlags;
+
+void set_brush_rc_props(struct PointerRNA *ptr, const char *paint, const char *prop, const char *secondary_prop,
+ RCFlags flags);
+
/* paint_undo.c */
struct ListBase *undo_paint_push_get_list(int type);
void undo_paint_push_count_alloc(int type, int size);
diff --git a/source/blender/editors/sculpt_paint/paint_mask.c b/source/blender/editors/sculpt_paint/paint_mask.c
index 8faa4cfaf33..118f3a7571f 100644
--- a/source/blender/editors/sculpt_paint/paint_mask.c
+++ b/source/blender/editors/sculpt_paint/paint_mask.c
@@ -69,7 +69,7 @@
static EnumPropertyItem mode_items[] = {
{PAINT_MASK_FLOOD_VALUE, "VALUE", 0, "Value", "Set mask to the level specified by the 'value' property"},
- {PAINT_MASK_FLOOD_VALUE_INVERSE, "VALUE_INVERSE", 0, "Value Inverted", "Set mask to the level specified by the inverted 'value' property"},
+ {PAINT_MASK_FLOOD_VALUE_INVERSE, "VALUE_INVERSE", 0, "Value Inverted", "Set mask to the level specified by the inverted 'value' property"},
{PAINT_MASK_INVERT, "INVERT", 0, "Invert", "Invert the mask"},
{0}};
@@ -277,7 +277,7 @@ int ED_sculpt_mask_box_select(struct bContext *C, ViewContext *vc, const rcti *r
typedef struct LassoMaskData {
struct ViewContext *vc;
float projviewobjmat[4][4];
- bool *px;
+ BLI_bitmap *px;
int width;
rcti rect; /* bounding box for scanfilling */
int symmpass;
@@ -290,7 +290,7 @@ typedef struct LassoMaskData {
static bool is_effected_lasso(LassoMaskData *data, float co[3])
{
float scr_co_f[2];
- short scr_co_s[2];
+ int scr_co_s[2];
float co_final[3];
flip_v3_v3(co_final, co, data->symmpass);
@@ -301,25 +301,30 @@ static bool is_effected_lasso(LassoMaskData *data, float co[3])
scr_co_s[1] = scr_co_f[1];
/* clip against screen, because lasso is limited to screen only */
- if (scr_co_s[0] < data->rect.xmin || scr_co_s[1] < data->rect.ymin || scr_co_s[0] >= data->rect.xmax || scr_co_s[1] >= data->rect.ymax)
+ if ((scr_co_s[0] < data->rect.xmin) ||
+ (scr_co_s[1] < data->rect.ymin) ||
+ (scr_co_s[0] >= data->rect.xmax) ||
+ (scr_co_s[1] >= data->rect.ymax))
+ {
return false;
+ }
scr_co_s[0] -= data->rect.xmin;
scr_co_s[1] -= data->rect.ymin;
- return data->px[scr_co_s[1] * data->width + scr_co_s[0]];
+ return BLI_BITMAP_TEST_BOOL(data->px, scr_co_s[1] * data->width + scr_co_s[0]);
}
static void mask_lasso_px_cb(int x, int y, void *user_data)
{
struct LassoMaskData *data = user_data;
- data->px[(y * data->width) + x] = true;
+ BLI_BITMAP_ENABLE(data->px, (y * data->width) + x);
}
static int paint_mask_gesture_lasso_exec(bContext *C, wmOperator *op)
{
int mcords_tot;
- int (*mcords)[2] = (int (*)[2])WM_gesture_lasso_path_to_array(C, op, &mcords_tot);
+ const int (*mcords)[2] = WM_gesture_lasso_path_to_array(C, op, &mcords_tot);
if (mcords) {
float clip_planes[4][4], clip_planes_final[4][4];
@@ -349,13 +354,13 @@ static int paint_mask_gesture_lasso_exec(bContext *C, wmOperator *op)
ob = vc.obact;
ED_view3d_ob_project_mat_get(vc.rv3d, ob, data.projviewobjmat);
- BLI_lasso_boundbox(&data.rect, (const int (*)[2])mcords, mcords_tot);
+ BLI_lasso_boundbox(&data.rect, mcords, mcords_tot);
data.width = data.rect.xmax - data.rect.xmin;
- data.px = MEM_callocN(sizeof(*data.px) * data.width * (data.rect.ymax - data.rect.ymin), "lasso_mask_pixel_buffer");
+ data.px = BLI_BITMAP_NEW(data.width * (data.rect.ymax - data.rect.ymin), __func__);
fill_poly_v2i_n(
data.rect.xmin, data.rect.ymin, data.rect.xmax, data.rect.ymax,
- (const int (*)[2])mcords, mcords_tot,
+ mcords, mcords_tot,
mask_lasso_px_cb, &data);
ED_view3d_clipping_calc(&bb, clip_planes, &mats, &data.rect);
diff --git a/source/blender/editors/sculpt_paint/paint_ops.c b/source/blender/editors/sculpt_paint/paint_ops.c
index dc6be9caa53..05eda4da63b 100644
--- a/source/blender/editors/sculpt_paint/paint_ops.c
+++ b/source/blender/editors/sculpt_paint/paint_ops.c
@@ -66,11 +66,12 @@ static int brush_add_exec(bContext *C, wmOperator *UNUSED(op))
Paint *paint = BKE_paint_get_active_from_context(C);
Brush *br = BKE_paint_brush(paint);
Main *bmain = CTX_data_main(C);
+ PaintMode mode = BKE_paintmode_get_active_from_context(C);
if (br)
br = BKE_brush_copy(br);
else
- br = BKE_brush_add(bmain, "Brush");
+ br = BKE_brush_add(bmain, "Brush", BKE_paint_object_mode_from_paint_mode(mode));
BKE_paint_brush_set(paint, br);
@@ -106,15 +107,14 @@ static int brush_scale_size_exec(bContext *C, wmOperator *op)
const int old_size = BKE_brush_size_get(scene, brush);
int size = (int)(scalar * old_size);
- if (old_size == size) {
+ if (abs(old_size - size) < U.pixelsize) {
if (scalar > 1) {
- size++;
+ size += U.pixelsize;
}
else if (scalar < 1) {
- size--;
+ size -= U.pixelsize;
}
}
- CLAMP(size, 1, 2000); // XXX magic number
BKE_brush_size_set(scene, brush, size);
}
@@ -128,6 +128,8 @@ static int brush_scale_size_exec(bContext *C, wmOperator *op)
BKE_brush_unprojected_radius_set(scene, brush, unprojected_radius);
}
+
+ WM_main_add_notifier(NC_BRUSH | NA_EDITED, brush);
}
return OPERATOR_FINISHED;
@@ -195,13 +197,16 @@ static int palette_color_add_exec(bContext *C, wmOperator *UNUSED(op))
Brush *brush = paint->brush;
PaintMode mode = BKE_paintmode_get_active_from_context(C);
Palette *palette = paint->palette;
- PaletteColor *color = BKE_palette_color_add(palette);
+ PaletteColor *color;
+
+ color = BKE_palette_color_add(palette);
+ palette->active_color = BLI_listbase_count(&palette->colors) - 1;
- if (ELEM(mode, PAINT_TEXTURE_PROJECTIVE, PAINT_TEXTURE_2D, PAINT_VERTEX)) {
+ if (ELEM(mode, ePaintTextureProjective, ePaintTexture2D, ePaintVertex)) {
copy_v3_v3(color->rgb, BKE_brush_color_get(scene, brush));
color->value = 0.0;
}
- else if (mode == PAINT_WEIGHT) {
+ else if (mode == ePaintWeight) {
zero_v3(color->rgb);
color->value = brush->weight;
}
@@ -230,7 +235,9 @@ static int palette_color_delete_exec(bContext *C, wmOperator *UNUSED(op))
Palette *palette = paint->palette;
PaletteColor *color = BLI_findlink(&palette->colors, palette->active_color);
- BKE_palette_color_remove(palette, color);
+ if (color) {
+ BKE_palette_color_remove(palette, color);
+ }
return OPERATOR_FINISHED;
}
@@ -425,9 +432,8 @@ static int brush_generic_tool_set(Main *bmain, Paint *paint, const int tool,
brush = brush_tool_cycle(bmain, brush_orig, tool, tool_offset, ob_mode);
if (!brush && brush_tool(brush_orig, tool_offset) != tool && create_missing) {
- brush = BKE_brush_add(bmain, tool_name);
+ brush = BKE_brush_add(bmain, tool_name, ob_mode);
brush_tool_set(brush, tool_offset, tool);
- brush->ob_mode = ob_mode;
brush->toggle_brush = brush_orig;
}
@@ -1085,6 +1091,7 @@ void ED_operatortypes_paint(void)
WM_operatortype_append(PAINT_OT_brush_colors_flip);
WM_operatortype_append(PAINT_OT_add_texture_paint_slot);
WM_operatortype_append(PAINT_OT_delete_texture_paint_slot);
+ WM_operatortype_append(PAINT_OT_add_simple_uvs);
/* weight */
WM_operatortype_append(PAINT_OT_weight_paint_toggle);
@@ -1148,14 +1155,6 @@ static void ed_keymap_paint_brush_size(wmKeyMap *keymap, const char *UNUSED(path
RNA_float_set(kmi->ptr, "scalar", 10.0 / 9.0); // 1.1111....
}
-typedef enum {
- RC_COLOR = 1,
- RC_ROTATION = 2,
- RC_ZOOM = 4,
- RC_WEIGHT = 8,
- RC_SECONDARY_ROTATION = 16
-} RCFlags;
-
static void set_brush_rc_path(PointerRNA *ptr, const char *brush_path,
const char *output_name, const char *input_name)
{
@@ -1166,9 +1165,9 @@ static void set_brush_rc_path(PointerRNA *ptr, const char *brush_path,
MEM_freeN(path);
}
-static void set_brush_rc_props(PointerRNA *ptr, const char *paint,
- const char *prop, const char *secondary_prop,
- RCFlags flags)
+void set_brush_rc_props(PointerRNA *ptr, const char *paint,
+ const char *prop, const char *secondary_prop,
+ RCFlags flags)
{
const char *ups_path = "tool_settings.unified_paint_settings";
char *brush_path;
@@ -1324,9 +1323,7 @@ void ED_keymap_paint(wmKeyConfig *keyconf)
*
* This should be improved further, perhaps by showing a triangle
* grid rather than brush alpha */
- kmi = WM_keymap_add_item(keymap, "WM_OT_radial_control", DKEY, KM_PRESS, KM_SHIFT, 0);
- set_brush_rc_props(kmi->ptr, "sculpt", "detail_size", NULL, 0);
- RNA_string_set(kmi->ptr, "data_path_primary", "tool_settings.sculpt.detail_size");
+ kmi = WM_keymap_add_item(keymap, "SCULPT_OT_set_detail_size", DKEY, KM_PRESS, KM_SHIFT, 0);
/* multires switch */
kmi = WM_keymap_add_item(keymap, "OBJECT_OT_subdivision_set", PAGEUPKEY, KM_PRESS, 0, 0);
@@ -1364,8 +1361,7 @@ void ED_keymap_paint(wmKeyConfig *keyconf)
kmi = WM_keymap_add_item(keymap, "WM_OT_context_toggle", SKEY, KM_PRESS, KM_SHIFT, 0);
RNA_string_set(kmi->ptr, "data_path", "tool_settings.sculpt.brush.use_smooth_stroke");
- kmi = WM_keymap_add_item(keymap, "WM_OT_context_menu_enum", RKEY, KM_PRESS, 0, 0);
- RNA_string_set(kmi->ptr, "data_path", "tool_settings.sculpt.brush.texture_angle_source_random");
+ WM_keymap_add_menu(keymap, "VIEW3D_MT_angle_control", RKEY, KM_PRESS, 0, 0);
/* Vertex Paint mode */
keymap = WM_keymap_find(keyconf, "Vertex Paint", 0, 0);
@@ -1389,8 +1385,7 @@ void ED_keymap_paint(wmKeyConfig *keyconf)
kmi = WM_keymap_add_item(keymap, "WM_OT_context_toggle", SKEY, KM_PRESS, KM_SHIFT, 0);
RNA_string_set(kmi->ptr, "data_path", "tool_settings.vertex_paint.brush.use_smooth_stroke");
- kmi = WM_keymap_add_item(keymap, "WM_OT_context_menu_enum", RKEY, KM_PRESS, 0, 0);
- RNA_string_set(kmi->ptr, "data_path", "tool_settings.vertex_paint.brush.texture_angle_source_random");
+ WM_keymap_add_menu(keymap, "VIEW3D_MT_angle_control", RKEY, KM_PRESS, 0, 0);
kmi = WM_keymap_add_item(keymap, "WM_OT_context_menu_enum", EKEY, KM_PRESS, 0, 0);
RNA_string_set(kmi->ptr, "data_path", "tool_settings.vertex_paint.brush.stroke_method");
@@ -1466,8 +1461,7 @@ void ED_keymap_paint(wmKeyConfig *keyconf)
kmi = WM_keymap_add_item(keymap, "WM_OT_context_toggle", SKEY, KM_PRESS, KM_SHIFT, 0);
RNA_string_set(kmi->ptr, "data_path", "tool_settings.image_paint.brush.use_smooth_stroke");
- kmi = WM_keymap_add_item(keymap, "WM_OT_context_menu_enum", RKEY, KM_PRESS, 0, 0);
- RNA_string_set(kmi->ptr, "data_path", "tool_settings.image_paint.brush.texture_angle_source_random");
+ WM_keymap_add_menu(keymap, "VIEW3D_MT_angle_control", RKEY, KM_PRESS, 0, 0);
kmi = WM_keymap_add_item(keymap, "WM_OT_context_menu_enum", EKEY, KM_PRESS, 0, 0);
RNA_string_set(kmi->ptr, "data_path", "tool_settings.image_paint.brush.stroke_method");
diff --git a/source/blender/editors/sculpt_paint/paint_stroke.c b/source/blender/editors/sculpt_paint/paint_stroke.c
index 1ed5ad8160c..b1ddf1172c8 100644
--- a/source/blender/editors/sculpt_paint/paint_stroke.c
+++ b/source/blender/editors/sculpt_paint/paint_stroke.c
@@ -68,6 +68,12 @@
#include <float.h>
#include <math.h>
+#define DEBUG_TIME
+
+#ifdef DEBUG_TIME
+# include "PIL_time_utildefines.h"
+#endif
+
typedef struct PaintSample {
float mouse[2];
float pressure;
@@ -116,6 +122,10 @@ typedef struct PaintStroke {
float zoom_2d;
int pen_flip;
+
+ /* line constraint */
+ bool constrain_line;
+ float constrained_pos[2];
StrokeGetLocation get_location;
StrokeTestStart test_start;
@@ -155,13 +165,25 @@ static void paint_draw_line_cursor(bContext *C, int x, int y, void *customdata)
glColor4ub(0, 0, 0, paint->paint_cursor_col[3]);
glLineWidth(3.0);
- sdrawline((int)stroke->last_mouse_position[0], (int)stroke->last_mouse_position[1],
- x, y);
+ if (stroke->constrain_line) {
+ sdrawline((int)stroke->last_mouse_position[0], (int)stroke->last_mouse_position[1],
+ stroke->constrained_pos[0], stroke->constrained_pos[1]);
+ }
+ else {
+ sdrawline((int)stroke->last_mouse_position[0], (int)stroke->last_mouse_position[1],
+ x, y);
+ }
glColor4ub(255, 255, 255, paint->paint_cursor_col[3]);
glLineWidth(1.0);
- sdrawline((int)stroke->last_mouse_position[0], (int)stroke->last_mouse_position[1],
- x, y);
+ if (stroke->constrain_line) {
+ sdrawline((int)stroke->last_mouse_position[0], (int)stroke->last_mouse_position[1],
+ stroke->constrained_pos[0], stroke->constrained_pos[1]);
+ }
+ else {
+ sdrawline((int)stroke->last_mouse_position[0], (int)stroke->last_mouse_position[1],
+ x, y);
+ }
glDisable(GL_LINE_STIPPLE);
@@ -172,7 +194,7 @@ static void paint_draw_line_cursor(bContext *C, int x, int y, void *customdata)
static bool paint_tool_require_location(Brush *brush, PaintMode mode)
{
switch (mode) {
- case PAINT_SCULPT:
+ case ePaintSculpt:
if (ELEM(brush->sculpt_tool, SCULPT_TOOL_GRAB, SCULPT_TOOL_ROTATE,
SCULPT_TOOL_SNAKE_HOOK, SCULPT_TOOL_THUMB))
{
@@ -201,6 +223,8 @@ static bool paint_brush_update(bContext *C,
UnifiedPaintSettings *ups = stroke->ups;
bool location_sampled = false;
bool location_success = false;
+ bool do_random = false;
+ bool do_random_mask = false;
/* XXX: Use pressure value from first brush step for brushes which don't
* support strokes (grab, thumb). They depends on initial state and
* brush coord/pressure/etc.
@@ -248,27 +272,34 @@ static bool paint_brush_update(bContext *C,
}
if (paint_supports_dynamic_tex_coords(brush, mode)) {
- if (((brush->mtex.brush_map_mode == MTEX_MAP_MODE_VIEW) ||
- (brush->mtex.brush_map_mode == MTEX_MAP_MODE_AREA) ||
- (brush->mtex.brush_map_mode == MTEX_MAP_MODE_RANDOM)) &&
- !(brush->flag & BRUSH_RAKE))
+
+ if (ELEM(brush->mtex.brush_map_mode,
+ MTEX_MAP_MODE_VIEW,
+ MTEX_MAP_MODE_AREA,
+ MTEX_MAP_MODE_RANDOM))
{
- if (brush->flag & BRUSH_RANDOM_ROTATION)
- ups->brush_rotation = 2.0f * (float)M_PI * BLI_frand();
- else
- ups->brush_rotation = 0.0f;
+ do_random = true;
}
if (brush->mtex.brush_map_mode == MTEX_MAP_MODE_RANDOM)
- BKE_brush_randomize_texture_coordinates(ups, false);
+ BKE_brush_randomize_texture_coords(ups, false);
else {
copy_v2_v2(ups->tex_mouse, mouse);
}
/* take care of mask texture, if any */
if (brush->mask_mtex.tex) {
+
+ if (ELEM(brush->mask_mtex.brush_map_mode,
+ MTEX_MAP_MODE_VIEW,
+ MTEX_MAP_MODE_AREA,
+ MTEX_MAP_MODE_RANDOM))
+ {
+ do_random_mask = true;
+ }
+
if (brush->mask_mtex.brush_map_mode == MTEX_MAP_MODE_RANDOM)
- BKE_brush_randomize_texture_coordinates(ups, true);
+ BKE_brush_randomize_texture_coords(ups, true);
else {
copy_v2_v2(ups->mask_tex_mouse, mouse);
}
@@ -285,7 +316,7 @@ static bool paint_brush_update(bContext *C,
ups->anchored_size = ups->pixel_radius = sqrtf(dx * dx + dy * dy);
- ups->brush_rotation = atan2f(dx, dy) + M_PI;
+ ups->brush_rotation = ups->brush_rotation_sec = atan2f(dx, dy) + (float)M_PI;
if (brush->flag & BRUSH_EDGE_TO_EDGE) {
halfway[0] = dx * 0.5f + stroke->initial_mouse[0];
@@ -322,13 +353,30 @@ static bool paint_brush_update(bContext *C,
ups->pixel_radius /= stroke->zoom_2d;
ups->draw_anchored = true;
}
- else if (brush->flag & BRUSH_RAKE) {
+ else {
/* here we are using the initial mouse coordinate because we do not want the rake
* result to depend on jittering */
- if (!stroke->brush_init)
+ if (!stroke->brush_init) {
copy_v2_v2(ups->last_rake, mouse_init);
- else
- paint_calculate_rake_rotation(ups, mouse_init);
+ }
+ /* curve strokes do their own rake calculation */
+ else if (!(brush->flag & BRUSH_CURVE)) {
+ paint_calculate_rake_rotation(ups, brush, mouse_init);
+ }
+ }
+
+ if (do_random) {
+ if (brush->mtex.brush_angle_mode & MTEX_ANGLE_RANDOM) {
+ ups->brush_rotation += -brush->mtex.random_angle / 2.0f +
+ brush->mtex.random_angle * BLI_frand();
+ }
+ }
+
+ if (do_random_mask) {
+ if (brush->mask_mtex.brush_angle_mode & MTEX_ANGLE_RANDOM) {
+ ups->brush_rotation_sec += -brush->mask_mtex.random_angle / 2.0f +
+ brush->mask_mtex.random_angle * BLI_frand();
+ }
}
if (!location_sampled) {
@@ -355,7 +403,7 @@ static bool paint_stroke_use_jitter(PaintMode mode, Brush *brush, bool invert)
/* jitter-ed brush gives weird and unpredictable result for this
* kinds of stroke, so manually disable jitter usage (sergey) */
use_jitter &= (brush->flag & (BRUSH_DRAG_DOT | BRUSH_ANCHORED)) == 0;
- use_jitter &= (!ELEM(mode, PAINT_TEXTURE_2D, PAINT_TEXTURE_PROJECTIVE) ||
+ use_jitter &= (!ELEM(mode, ePaintTexture2D, ePaintTextureProjective) ||
!(invert && brush->imagepaint_tool == PAINT_TOOL_CLONE));
@@ -523,7 +571,7 @@ static float paint_stroke_integrate_overlap(Brush *br, float factor)
g = 1.0f / m;
max = 0;
for (i = 0; i < m; i++) {
- float overlap = paint_stroke_overlapped_curve(br, i * g, spacing);
+ float overlap = fabs(paint_stroke_overlapped_curve(br, i * g, spacing));
if (overlap > max)
max = overlap;
@@ -618,7 +666,8 @@ PaintStroke *paint_stroke_new(bContext *C,
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));
+ Paint *p = BKE_paint_get_active_from_context(C);
+ Brush *br = stroke->brush = BKE_paint_brush(p);
float zoomx, zoomy;
view3d_set_viewcontext(C, &stroke->vc);
@@ -637,18 +686,23 @@ PaintStroke *paint_stroke_new(bContext *C,
get_imapaint_zoom(C, &zoomx, &zoomy);
stroke->zoom_2d = max_ff(zoomx, zoomy);
- if ((br->flag & BRUSH_CURVE) &&
- RNA_struct_property_is_set(op->ptr, "mode"))
- {
- RNA_enum_set(op->ptr, "mode", BRUSH_STROKE_NORMAL);
+ if (stroke->stroke_mode == BRUSH_STROKE_INVERT) {
+ if (br->flag & (BRUSH_CURVE)) {
+ RNA_enum_set(op->ptr, "mode", BRUSH_STROKE_NORMAL);
+ }
}
/* initialize here */
ups->overlap_factor = 1.0;
ups->stroke_active = true;
-
+
+ zero_v3(ups->average_stroke_accum);
+ ups->average_stroke_counter = 0;
+
/* initialize here to avoid initialization conflict with threaded strokes */
curvemapping_initialize(br->curve);
-
+ if (p->flags & PAINT_USE_CAVITY_MASK)
+ curvemapping_initialize(p->cavity_curve);
+
BKE_paint_set_overlay_override(br->overlay_flags);
return stroke;
@@ -669,9 +723,12 @@ static void stroke_done(struct bContext *C, struct wmOperator *op)
ups->stroke_active = false;
/* reset rotation here to avoid doing so in cursor display */
- if (!(stroke->brush->flag & BRUSH_RAKE))
+ if (!(stroke->brush->mtex.brush_angle_mode & MTEX_ANGLE_RAKE))
ups->brush_rotation = 0.0f;
+ if (!(stroke->brush->mask_mtex.brush_angle_mode & MTEX_ANGLE_RAKE))
+ ups->brush_rotation_sec = 0.0f;
+
if (stroke->stroke_started) {
if (stroke->redraw)
stroke->redraw(C, stroke, true);
@@ -717,13 +774,13 @@ bool paint_supports_dynamic_size(Brush *br, PaintMode mode)
return false;
switch (mode) {
- case PAINT_SCULPT:
+ case ePaintSculpt:
if (sculpt_is_grab_tool(br))
return false;
break;
- case PAINT_TEXTURE_2D: /* fall through */
- case PAINT_TEXTURE_PROJECTIVE:
+ case ePaintTexture2D: /* fall through */
+ case ePaintTextureProjective:
if ((br->imagepaint_tool == PAINT_TOOL_FILL) &&
(br->flag & BRUSH_USE_GRADIENT))
{
@@ -746,7 +803,7 @@ bool paint_supports_smooth_stroke(Brush *br, PaintMode mode)
}
switch (mode) {
- case PAINT_SCULPT:
+ case ePaintSculpt:
if (sculpt_is_grab_tool(br))
return false;
break;
@@ -758,8 +815,8 @@ bool paint_supports_smooth_stroke(Brush *br, PaintMode mode)
bool paint_supports_texture(PaintMode mode)
{
- /* ommit: PAINT_WEIGHT, PAINT_SCULPT_UV, PAINT_INVALID */
- return ELEM(mode, PAINT_SCULPT, PAINT_VERTEX, PAINT_TEXTURE_PROJECTIVE, PAINT_TEXTURE_2D);
+ /* omit: PAINT_WEIGHT, PAINT_SCULPT_UV, PAINT_INVALID */
+ return ELEM(mode, ePaintSculpt, ePaintVertex, ePaintTextureProjective, ePaintTexture2D);
}
/* return true if the brush size can change during paint (normally used for pressure) */
@@ -769,7 +826,7 @@ bool paint_supports_dynamic_tex_coords(Brush *br, PaintMode mode)
return false;
switch (mode) {
- case PAINT_SCULPT:
+ case ePaintSculpt:
if (sculpt_is_grab_tool(br))
return false;
break;
@@ -910,7 +967,9 @@ static void paint_stroke_line_end(bContext *C, wmOperator *op, PaintStroke *stro
static bool paint_stroke_curve_end(bContext *C, wmOperator *op, PaintStroke *stroke)
{
Brush *br = stroke->brush;
+
if (br->flag & BRUSH_CURVE) {
+ UnifiedPaintSettings *ups = &CTX_data_tool_settings(C)->unified_paint_settings;
const Scene *scene = CTX_data_scene(C);
const float spacing = paint_space_stroke_spacing(scene, stroke, 1.0f, 1.0f);
PaintCurve *pc = br->paint_curve;
@@ -921,24 +980,49 @@ static bool paint_stroke_curve_end(bContext *C, wmOperator *op, PaintStroke *str
if (!pc)
return true;
+#ifdef DEBUG_TIME
+ TIMEIT_START(stroke);
+#endif
+
pcp = pc->points;
stroke->ups->overlap_factor = paint_stroke_integrate_overlap(br, 1.0);
for (i = 0; i < pc->tot_points - 1; i++, pcp++) {
int j;
float data[(PAINT_CURVE_NUM_SEGMENTS + 1) * 2];
+ float tangents[(PAINT_CURVE_NUM_SEGMENTS + 1) * 2];
PaintCurvePoint *pcp_next = pcp + 1;
+ bool do_rake = false;
- for (j = 0; j < 2; j++)
+ for (j = 0; j < 2; j++) {
BKE_curve_forward_diff_bezier(
pcp->bez.vec[1][j],
pcp->bez.vec[2][j],
pcp_next->bez.vec[0][j],
pcp_next->bez.vec[1][j],
data + j, PAINT_CURVE_NUM_SEGMENTS, sizeof(float[2]));
+ }
+ if ((br->mtex.brush_angle_mode & MTEX_ANGLE_RAKE) ||
+ (br->mask_mtex.brush_angle_mode & MTEX_ANGLE_RAKE))
+ {
+ do_rake = true;
+ for (j = 0; j < 2; j++) {
+ BKE_curve_forward_diff_tangent_bezier(
+ pcp->bez.vec[1][j],
+ pcp->bez.vec[2][j],
+ pcp_next->bez.vec[0][j],
+ pcp_next->bez.vec[1][j],
+ tangents + j, PAINT_CURVE_NUM_SEGMENTS, sizeof(float[2]));
+ }
+ }
for (j = 0; j < PAINT_CURVE_NUM_SEGMENTS; j++) {
+ if (do_rake) {
+ float rotation = atan2f(tangents[2 * j], tangents[2 * j + 1]);
+ paint_update_brush_rake_rotation(ups, br, rotation);
+ }
+
if (!stroke->stroke_started) {
stroke->last_pressure = 1.0;
copy_v2_v2(stroke->last_mouse_position, data + 2 * j);
@@ -956,12 +1040,45 @@ static bool paint_stroke_curve_end(bContext *C, wmOperator *op, PaintStroke *str
}
stroke_done(C, op);
+
+#ifdef DEBUG_TIME
+ TIMEIT_END(stroke);
+#endif
+
return true;
}
return false;
}
+static void paint_stroke_line_constrain(PaintStroke *stroke, float mouse[2])
+{
+ if (stroke->constrain_line) {
+ float line[2];
+ float angle, len, res;
+
+ sub_v2_v2v2(line, mouse, stroke->last_mouse_position);
+ angle = atan2f(line[1], line[0]);
+ len = len_v2(line);
+
+ /* divide angle by PI/4 */
+ angle = 4.0f * angle / (float)M_PI;
+
+ /* now take residue */
+ res = angle - floorf(angle);
+
+ /* residue decides how close we are at a certain angle */
+ if (res <= 0.5f) {
+ angle = floorf(angle) * (float)M_PI_4;
+ }
+ else {
+ angle = (floorf(angle) + 1.0f) * (float)M_PI_4;
+ }
+
+ mouse[0] = stroke->constrained_pos[0] = len * cosf(angle) + stroke->last_mouse_position[0];
+ mouse[1] = stroke->constrained_pos[1] = len * sinf(angle) + stroke->last_mouse_position[1];
+ }
+}
int paint_stroke_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
@@ -1035,7 +1152,9 @@ int paint_stroke_modal(bContext *C, wmOperator *op, const wmEvent *event)
if (event->type == stroke->event_type && !first_modal) {
if (event->val == KM_RELEASE) {
- paint_stroke_line_end (C, op, stroke, sample_average.mouse);
+ copy_v2_fl2(mouse, event->mval[0], event->mval[1]);
+ paint_stroke_line_constrain(stroke, mouse);
+ paint_stroke_line_end (C, op, stroke, mouse);
stroke_done(C, op);
return OPERATOR_FINISHED;
}
@@ -1045,12 +1164,20 @@ int paint_stroke_modal(bContext *C, wmOperator *op, const wmEvent *event)
stroke_done(C, op);
return OPERATOR_FINISHED;
}
- else if ((br->flag & BRUSH_LINE) && stroke->stroke_started &&
- (first_modal || (ELEM(event->type, MOUSEMOVE, INBETWEEN_MOUSEMOVE))))
- {
- if (br->flag & BRUSH_RAKE) {
- copy_v2_v2(stroke->ups->last_rake, stroke->last_mouse_position);
- paint_calculate_rake_rotation(stroke->ups, sample_average.mouse);
+ else if (br->flag & BRUSH_LINE) {
+ if (event->alt)
+ stroke->constrain_line = true;
+ else
+ stroke->constrain_line = false;
+
+ copy_v2_fl2(mouse, event->mval[0], event->mval[1]);
+ paint_stroke_line_constrain(stroke, mouse);
+
+ if (stroke->stroke_started && (first_modal || (ELEM(event->type, MOUSEMOVE, INBETWEEN_MOUSEMOVE)))) {
+ if ((br->mtex.brush_angle_mode & MTEX_ANGLE_RAKE) || (br->mask_mtex.brush_angle_mode & MTEX_ANGLE_RAKE)) {
+ copy_v2_v2(stroke->ups->last_rake, stroke->last_mouse_position);
+ }
+ paint_calculate_rake_rotation(stroke->ups, br, mouse);
}
}
else if (first_modal ||
diff --git a/source/blender/editors/sculpt_paint/paint_undo.c b/source/blender/editors/sculpt_paint/paint_undo.c
index 20e3155c01d..42f0aaab173 100644
--- a/source/blender/editors/sculpt_paint/paint_undo.c
+++ b/source/blender/editors/sculpt_paint/paint_undo.c
@@ -210,7 +210,7 @@ static int undo_stack_step(bContext *C, UndoStack *stack, int step, const char *
/* pass */
}
else {
- if (!name || strcmp(stack->current->name, name) == 0) {
+ if (!name || STREQ(stack->current->name, name)) {
if (G.debug & G_DEBUG_WM) {
printf("%s: undo '%s'\n", __func__, stack->current->name);
}
@@ -225,7 +225,7 @@ static int undo_stack_step(bContext *C, UndoStack *stack, int step, const char *
/* pass */
}
else {
- if (!name || strcmp(stack->current->name, name) == 0) {
+ if (!name || STREQ(stack->current->name, name)) {
undo = (stack->current && stack->current->next) ? stack->current->next : stack->elems.first;
undo_restore(C, stack, undo);
stack->current = undo;
@@ -331,32 +331,33 @@ void ED_undo_paint_step_num(bContext *C, int type, int step)
undo_step_num(C, &MeshUndoStack, step);
}
-static char *undo_stack_get_name(UndoStack *stack, int nr, int *active)
+static char *undo_stack_get_name(UndoStack *stack, int nr, bool *r_active)
{
UndoElem *uel;
- if (active) *active = 0;
+ if (r_active) *r_active = false;
uel = BLI_findlink(&stack->elems, nr);
if (uel) {
- if (active && uel == stack->current)
- *active = 1;
+ if (r_active && (uel == stack->current)) {
+ *r_active = true;
+ }
return uel->name;
}
return NULL;
}
-const char *ED_undo_paint_get_name(bContext *C, int type, int nr, int *active)
+const char *ED_undo_paint_get_name(bContext *C, int type, int nr, bool *r_active)
{
if (type == UNDO_PAINT_IMAGE) {
undo_stack_cleanup(&ImageUndoStack, C);
- return undo_stack_get_name(&ImageUndoStack, nr, active);
+ return undo_stack_get_name(&ImageUndoStack, nr, r_active);
}
else if (type == UNDO_PAINT_MESH) {
undo_stack_cleanup(&MeshUndoStack, C);
- return undo_stack_get_name(&MeshUndoStack, nr, active);
+ return undo_stack_get_name(&MeshUndoStack, nr, r_active);
}
return NULL;
}
@@ -379,7 +380,7 @@ bool ED_undo_paint_empty(int type)
return false;
}
-int ED_undo_paint_valid(int type, const char *name)
+bool ED_undo_paint_is_valid(int type, const char *name)
{
UndoStack *stack;
@@ -394,7 +395,7 @@ int ED_undo_paint_valid(int type, const char *name)
/* pass */
}
else {
- if (name && strcmp(stack->current->name, name) == 0)
+ if (name && STREQ(stack->current->name, name))
return 1;
else
return stack->elems.first != stack->elems.last;
diff --git a/source/blender/editors/sculpt_paint/paint_utils.c b/source/blender/editors/sculpt_paint/paint_utils.c
index f34d0ff3f7b..7b66632fa42 100644
--- a/source/blender/editors/sculpt_paint/paint_utils.c
+++ b/source/blender/editors/sculpt_paint/paint_utils.c
@@ -46,17 +46,15 @@
#include "BLI_listbase.h"
#include "BLI_rect.h"
-#include "BLF_translation.h"
+#include "BLT_translation.h"
-#include "BKE_scene.h"
#include "BKE_brush.h"
#include "BKE_context.h"
#include "BKE_DerivedMesh.h"
-#include "BKE_material.h"
#include "BKE_image.h"
+#include "BKE_material.h"
#include "BKE_paint.h"
#include "BKE_report.h"
-#include "BKE_image.h"
#include "RNA_access.h"
#include "RNA_define.h"
@@ -66,16 +64,12 @@
#include "IMB_colormanagement.h"
#include "IMB_imbuf_types.h"
+#include "IMB_imbuf.h"
-#include "RE_shader_ext.h"
#include "RE_render_ext.h"
#include "ED_view3d.h"
#include "ED_screen.h"
-#include "ED_uvedit.h"
-
-#include "IMB_imbuf_types.h"
-#include "IMB_imbuf.h"
#include "BLI_sys_types.h"
#include "ED_mesh.h" /* for face mask functions */
@@ -183,7 +177,7 @@ float paint_get_tex_pixel(MTex *mtex, float u, float v, struct ImagePool *pool,
float co[3] = {u, v, 0.0f};
externtex(mtex, co, &intensity,
- rgba, rgba + 1, rgba + 2, rgba + 3, thread, pool);
+ rgba, rgba + 1, rgba + 2, rgba + 3, thread, pool, false);
return intensity;
}
@@ -195,7 +189,7 @@ void paint_get_tex_pixel_col(MTex *mtex, float u, float v, float rgba[4], struct
float intensity;
hasrgb = externtex(mtex, co, &intensity,
- rgba, rgba + 1, rgba + 2, rgba + 3, thread, pool);
+ rgba, rgba + 1, rgba + 2, rgba + 3, thread, pool, false);
if (!hasrgb) {
rgba[0] = intensity;
rgba[1] = intensity;
@@ -283,24 +277,16 @@ static void imapaint_tri_weights(float matrix[4][4], GLint view[4],
static void imapaint_pick_uv(Scene *scene, Object *ob, unsigned int faceindex, const int xy[2], float uv[2])
{
DerivedMesh *dm = mesh_get_derived_final(scene, ob, CD_MASK_BAREMESH);
- MTFace *tf_base, *tf;
- Material *ma;
- TexPaintSlot *slot;
- int numfaces = dm->getNumTessFaces(dm), a, findex;
+ const int tottri = dm->getNumLoopTri(dm);
+ int i, findex;
float p[2], w[3], absw, minabsw;
- MFace mf;
- MVert mv[4];
float matrix[4][4], proj[4][4];
GLint view[4];
-
- /* compute barycentric coordinates */
-
- /* double lookup */
- const int *index_mf_to_mpoly = dm->getTessFaceDataArray(dm, CD_ORIGINDEX);
+ const ImagePaintMode mode = scene->toolsettings->imapaint.mode;
+ const MLoopTri *lt = dm->getLoopTriArray(dm);
+ const MPoly *mpoly = dm->getPolyArray(dm);
+ const MLoop *mloop = dm->getLoopArray(dm);
const int *index_mp_to_orig = dm->getPolyDataArray(dm, CD_ORIGINDEX);
- if (index_mf_to_mpoly == NULL) {
- index_mp_to_orig = NULL;
- }
/* get the needed opengl matrices */
glGetIntegerv(GL_VIEWPORT, view);
@@ -314,56 +300,50 @@ static void imapaint_pick_uv(Scene *scene, Object *ob, unsigned int faceindex, c
uv[0] = uv[1] = 0.0;
/* test all faces in the derivedmesh with the original index of the picked face */
- for (a = 0; a < numfaces; a++) {
- findex = index_mf_to_mpoly ? DM_origindex_mface_mpoly(index_mf_to_mpoly, index_mp_to_orig, a) : a;
+ /* face means poly here, not triangle, indeed */
+ for (i = 0; i < tottri; i++, lt++) {
+ findex = index_mp_to_orig ? index_mp_to_orig[lt->poly] : lt->poly;
if (findex == faceindex) {
- dm->getTessFace(dm, a, &mf);
-
- ma = dm->mat[mf.mat_nr];
- slot = &ma->texpaintslot[ma->paint_active_slot];
-
- dm->getVert(dm, mf.v1, &mv[0]);
- dm->getVert(dm, mf.v2, &mv[1]);
- dm->getVert(dm, mf.v3, &mv[2]);
- if (mf.v4)
- dm->getVert(dm, mf.v4, &mv[3]);
-
- if (!(slot && slot->uvname && (tf_base = CustomData_get_layer_named(&dm->faceData, CD_MTFACE, slot->uvname))))
- tf_base = CustomData_get_layer(&dm->faceData, CD_MTFACE);
+ const MLoopUV *mloopuv;
+ const MPoly *mp = &mpoly[lt->poly];
+ const MLoopUV *tri_uv[3];
+ float tri_co[3][3];
+
+ dm->getVertCo(dm, mloop[lt->tri[0]].v, tri_co[0]);
+ dm->getVertCo(dm, mloop[lt->tri[1]].v, tri_co[1]);
+ dm->getVertCo(dm, mloop[lt->tri[2]].v, tri_co[2]);
+
+ if (mode == IMAGEPAINT_MODE_MATERIAL) {
+ const Material *ma;
+ const TexPaintSlot *slot;
+
+ ma = dm->mat[mp->mat_nr];
+ slot = &ma->texpaintslot[ma->paint_active_slot];
+
+ if (!(slot && slot->uvname &&
+ (mloopuv = CustomData_get_layer_named(&dm->loopData, CD_MLOOPUV, slot->uvname))))
+ {
+ mloopuv = CustomData_get_layer(&dm->loopData, CD_MLOOPUV);
+ }
+ }
+ else {
+ mloopuv = CustomData_get_layer(&dm->loopData, CD_MLOOPUV);
+ }
- tf = &tf_base[a];
+ tri_uv[0] = &mloopuv[lt->tri[0]];
+ tri_uv[1] = &mloopuv[lt->tri[1]];
+ tri_uv[2] = &mloopuv[lt->tri[2]];
p[0] = xy[0];
p[1] = xy[1];
- if (mf.v4) {
- /* the triangle with the largest absolute values is the one
- * with the most negative weights */
- imapaint_tri_weights(matrix, view, mv[0].co, mv[1].co, mv[3].co, p, w);
- absw = fabsf(w[0]) + fabsf(w[1]) + fabsf(w[2]);
- if (absw < minabsw) {
- uv[0] = tf->uv[0][0] * w[0] + tf->uv[1][0] * w[1] + tf->uv[3][0] * w[2];
- uv[1] = tf->uv[0][1] * w[0] + tf->uv[1][1] * w[1] + tf->uv[3][1] * w[2];
- minabsw = absw;
- }
-
- imapaint_tri_weights(matrix, view, mv[1].co, mv[2].co, mv[3].co, p, w);
- absw = fabsf(w[0]) + fabsf(w[1]) + fabsf(w[2]);
- if (absw < minabsw) {
- uv[0] = tf->uv[1][0] * w[0] + tf->uv[2][0] * w[1] + tf->uv[3][0] * w[2];
- uv[1] = tf->uv[1][1] * w[0] + tf->uv[2][1] * w[1] + tf->uv[3][1] * w[2];
- minabsw = absw;
- }
- }
- else {
- imapaint_tri_weights(matrix, view, mv[0].co, mv[1].co, mv[2].co, p, w);
- absw = fabsf(w[0]) + fabsf(w[1]) + fabsf(w[2]);
- if (absw < minabsw) {
- uv[0] = tf->uv[0][0] * w[0] + tf->uv[1][0] * w[1] + tf->uv[2][0] * w[2];
- uv[1] = tf->uv[0][1] * w[0] + tf->uv[1][1] * w[1] + tf->uv[2][1] * w[2];
- minabsw = absw;
- }
+ imapaint_tri_weights(matrix, view, UNPACK3(tri_co), p, w);
+ absw = fabsf(w[0]) + fabsf(w[1]) + fabsf(w[2]);
+ if (absw < minabsw) {
+ uv[0] = tri_uv[0]->uv[0] * w[0] + tri_uv[1]->uv[0] * w[1] + tri_uv[2]->uv[0] * w[2];
+ uv[1] = tri_uv[0]->uv[1] * w[0] + tri_uv[1]->uv[1] * w[1] + tri_uv[2]->uv[1] * w[2];
+ minabsw = absw;
}
}
}
@@ -372,15 +352,15 @@ static void imapaint_pick_uv(Scene *scene, Object *ob, unsigned int faceindex, c
}
/* returns 0 if not found, otherwise 1 */
-static int imapaint_pick_face(ViewContext *vc, const int mval[2], unsigned int *r_index, unsigned int totface)
+static int imapaint_pick_face(ViewContext *vc, const int mval[2], unsigned int *r_index, unsigned int totpoly)
{
- if (totface == 0)
+ if (totpoly == 0)
return 0;
/* sample only on the exact position */
- *r_index = view3d_sample_backbuf(vc, mval[0], mval[1]);
+ *r_index = ED_view3d_backbuf_sample(vc, mval[0], mval[1]);
- if ((*r_index) == 0 || (*r_index) > (unsigned int)totface) {
+ if ((*r_index) == 0 || (*r_index) > (unsigned int)totpoly) {
return 0;
}
@@ -390,12 +370,12 @@ static int imapaint_pick_face(ViewContext *vc, const int mval[2], unsigned int *
}
-static Image *imapaint_face_image(DerivedMesh *dm, int face_index)
+static Image *imapaint_face_image(Object *ob, Mesh *me, int face_index)
{
Image *ima;
- MFace *mf = dm->getTessFaceArray(dm) + face_index;
- Material *ma = dm->mat[mf->mat_nr];
- ima = ma->texpaintslot[ma->paint_active_slot].ima;
+ MPoly *mp = me->mpoly + face_index;
+ Material *ma = give_current_material(ob, mp->mat_nr + 1);
+ ima = ma && ma->texpaintslot ? ma->texpaintslot[ma->paint_active_slot].ima : NULL;
return ima;
}
@@ -438,6 +418,7 @@ void paint_sample_color(bContext *C, ARegion *ar, int x, int y, bool texpaint_pr
}
color = BKE_palette_color_add(palette);
+ palette->active_color = BLI_listbase_count(&palette->colors) - 1;
}
@@ -449,26 +430,24 @@ void paint_sample_color(bContext *C, ARegion *ar, int x, int y, bool texpaint_pr
bool use_material = (imapaint->mode == IMAGEPAINT_MODE_MATERIAL);
if (ob) {
+ Mesh *me = (Mesh *)ob->data;
DerivedMesh *dm = mesh_get_derived_final(scene, ob, CD_MASK_BAREMESH);
ViewContext vc;
const int mval[2] = {x, y};
unsigned int faceindex;
- unsigned int totface = dm->getNumTessFaces(dm);
- MTFace *dm_mtface = dm->getTessFaceDataArray(dm, CD_MTFACE);
-
- DM_update_materials(dm, ob);
+ unsigned int totpoly = me->totpoly;
- if (dm_mtface) {
+ if (dm->getLoopDataArray(dm, CD_MLOOPUV)) {
view3d_set_viewcontext(C, &vc);
view3d_operator_needs_opengl(C);
- if (imapaint_pick_face(&vc, mval, &faceindex, totface)) {
+ if (imapaint_pick_face(&vc, mval, &faceindex, totpoly)) {
Image *image;
if (use_material)
- image = imapaint_face_image(dm, faceindex);
+ image = imapaint_face_image(ob, me, faceindex);
else
image = imapaint->canvas;
@@ -486,12 +465,15 @@ void paint_sample_color(bContext *C, ARegion *ar, int x, int y, bool texpaint_pr
if (u < 0.0f) u += 1.0f;
if (v < 0.0f) v += 1.0f;
- u = u * ibuf->x - 0.5f;
- v = v * ibuf->y - 0.5f;
+ u = u * ibuf->x;
+ v = v * ibuf->y;
if (ibuf->rect_float) {
float rgba_f[4];
- bilinear_interpolation_color_wrap(ibuf, NULL, rgba_f, u, v);
+ if (U.gameflags & USER_DISABLE_MIPMAP)
+ nearest_interpolation_color_wrap(ibuf, NULL, rgba_f, u, v);
+ else
+ bilinear_interpolation_color_wrap(ibuf, NULL, rgba_f, u, v);
straight_to_premul_v4(rgba_f);
if (use_palette) {
linearrgb_to_srgb_v3_v3(color->rgb, rgba_f);
@@ -503,7 +485,10 @@ void paint_sample_color(bContext *C, ARegion *ar, int x, int y, bool texpaint_pr
}
else {
unsigned char rgba[4];
- bilinear_interpolation_color_wrap(ibuf, rgba, NULL, u, v);
+ if (U.gameflags & USER_DISABLE_MIPMAP)
+ nearest_interpolation_color_wrap(ibuf, rgba, NULL, u, v);
+ else
+ bilinear_interpolation_color_wrap(ibuf, rgba, NULL, u, v);
if (use_palette) {
rgb_uchar_to_float(color->rgb, rgba);
}
@@ -587,7 +572,7 @@ void BRUSH_OT_curve_preset(wmOperatorType *ot)
ot->poll = brush_curve_preset_poll;
prop = RNA_def_enum(ot->srna, "shape", prop_shape_items, CURVE_PRESET_SMOOTH, "Mode", "");
- RNA_def_property_translation_context(prop, BLF_I18NCONTEXT_ID_CURVE); /* Abusing id_curve :/ */
+ RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_CURVE); /* Abusing id_curve :/ */
}
diff --git a/source/blender/editors/sculpt_paint/paint_vertex.c b/source/blender/editors/sculpt_paint/paint_vertex.c
index 509a7f31f5b..8daad9deea9 100644
--- a/source/blender/editors/sculpt_paint/paint_vertex.c
+++ b/source/blender/editors/sculpt_paint/paint_vertex.c
@@ -37,6 +37,7 @@
#include "IMB_imbuf.h"
#include "IMB_imbuf_types.h"
+#include "IMB_colormanagement.h"
#include "DNA_armature_types.h"
#include "DNA_mesh_types.h"
@@ -66,8 +67,6 @@
#include "WM_api.h"
#include "WM_types.h"
-#include "GPU_buffers.h"
-
#include "ED_armature.h"
#include "ED_object.h"
#include "ED_mesh.h"
@@ -84,53 +83,14 @@ static bool vertex_paint_use_fast_update_check(Object *ob)
if (dm) {
Mesh *me = BKE_mesh_from_object(ob);
- if (me && me->mcol) {
- return (me->mcol == CustomData_get_layer(&dm->faceData, CD_MCOL));
+ if (me && me->mloopcol) {
+ return (me->mloopcol == CustomData_get_layer(&dm->loopData, CD_MLOOPCOL));
}
}
return false;
}
-/* if the polygons from the mesh and the 'derivedFinal' match
- * we can assume that no modifiers are applied and that its worth adding tessellated faces
- * so 'vertex_paint_use_fast_update_check()' returns true */
-static bool vertex_paint_use_tessface_check(Object *ob, Mesh *me)
-{
- DerivedMesh *dm = ob->derivedFinal;
-
- if (me && dm) {
- return (me->mpoly == CustomData_get_layer(&dm->polyData, CD_MPOLY));
- }
-
- return false;
-}
-
-static void update_tessface_data(Object *ob, Mesh *me)
-{
- if (vertex_paint_use_tessface_check(ob, me)) {
- /* assume if these exist, that they are up to date & valid */
- if (!me->mcol || !me->mface) {
- /* should always be true */
- /* XXX Why this clearing? tessface_calc will reset it anyway! */
-#if 0
- if (me->mcol) {
- memset(me->mcol, 255, 4 * sizeof(MCol) * me->totface);
- }
-#endif
-
- /* create tessfaces because they will be used for drawing & fast updates */
- BKE_mesh_tessface_calc(me); /* does own call to update pointers */
- }
- }
- else {
- if (me->totface) {
- /* this wont be used, theres no need to keep it */
- BKE_mesh_tessface_clear(me);
- }
- }
-
-}
/* polling - retrieve whether cursor should be set or operator should be done */
/* Returns true if vertex paint mode is active */
@@ -206,82 +166,9 @@ unsigned int vpaint_get_current_col(Scene *scene, VPaint *vp)
return *(unsigned int *)col;
}
-static void do_shared_vertex_tesscol(Mesh *me, bool *mfacetag)
-{
- /* if no mcol: do not do */
- /* if tface: only the involved faces, otherwise all */
- const int use_face_sel = (me->editflag & ME_EDIT_PAINT_FACE_SEL);
- MFace *mface;
- int a;
- short *scolmain, *scol;
- char *mcol;
- const bool *mftag;
-
- if (me->mcol == NULL || me->totvert == 0 || me->totface == 0) return;
-
- scolmain = MEM_callocN(4 * sizeof(short) * me->totvert, "colmain");
-
- mface = me->mface;
- mcol = (char *)me->mcol;
- for (a = me->totface; a > 0; a--, mface++, mcol += 16) {
- if ((use_face_sel == false) || (mface->flag & ME_FACE_SEL)) {
- scol = scolmain + 4 * mface->v1;
- scol[0]++; scol[1] += mcol[1]; scol[2] += mcol[2]; scol[3] += mcol[3];
- scol = scolmain + 4 * mface->v2;
- scol[0]++; scol[1] += mcol[5]; scol[2] += mcol[6]; scol[3] += mcol[7];
- scol = scolmain + 4 * mface->v3;
- scol[0]++; scol[1] += mcol[9]; scol[2] += mcol[10]; scol[3] += mcol[11];
- if (mface->v4) {
- scol = scolmain + 4 * mface->v4;
- scol[0]++; scol[1] += mcol[13]; scol[2] += mcol[14]; scol[3] += mcol[15];
- }
- }
- }
-
- a = me->totvert;
- scol = scolmain;
- while (a--) {
- if (scol[0] > 1) {
- scol[1] = divide_round_i(scol[1], scol[0]);
- scol[2] = divide_round_i(scol[2], scol[0]);
- scol[3] = divide_round_i(scol[3], scol[0]);
- }
- scol += 4;
- }
-
- mface = me->mface;
- mcol = (char *)me->mcol;
- mftag = mfacetag;
- for (a = me->totface; a > 0; a--, mface++, mcol += 16, mftag += 4) {
- if ((use_face_sel == false) || (mface->flag & ME_FACE_SEL)) {
- if (mftag[0]) {
- scol = scolmain + 4 * mface->v1;
- mcol[1] = scol[1]; mcol[2] = scol[2]; mcol[3] = scol[3];
- }
-
- if (mftag[1]) {
- scol = scolmain + 4 * mface->v2;
- mcol[5] = scol[1]; mcol[6] = scol[2]; mcol[7] = scol[3];
- }
-
- if (mftag[2]) {
- scol = scolmain + 4 * mface->v3;
- mcol[9] = scol[1]; mcol[10] = scol[2]; mcol[11] = scol[3];
- }
-
- if (mface->v4 && mftag[3]) {
- scol = scolmain + 4 * mface->v4;
- mcol[13] = scol[1]; mcol[14] = scol[2]; mcol[15] = scol[3];
- }
- }
- }
-
- MEM_freeN(scolmain);
-}
-
-static void do_shared_vertexcol(Mesh *me, bool *mlooptag, bool *mfacetag, const bool do_tessface)
+static void do_shared_vertexcol(Mesh *me, bool *mlooptag)
{
- const int use_face_sel = (me->editflag & ME_EDIT_PAINT_FACE_SEL);
+ const bool use_face_sel = (me->editflag & ME_EDIT_PAINT_FACE_SEL) != 0;
MPoly *mp;
int (*scol)[4];
int i, j;
@@ -333,10 +220,6 @@ static void do_shared_vertexcol(Mesh *me, bool *mlooptag, bool *mfacetag, const
}
MEM_freeN(scol);
-
- if (has_shared && do_tessface) {
- do_shared_vertex_tesscol(me, mfacetag);
- }
}
static bool make_vertexcol(Object *ob) /* single ob */
@@ -353,17 +236,12 @@ static bool make_vertexcol(Object *ob) /* single ob */
/* copies from shadedisplist to mcol */
if (!me->mloopcol && me->totloop) {
- if (!me->mcol) {
- CustomData_add_layer(&me->fdata, CD_MCOL, CD_DEFAULT, NULL, me->totface);
- }
if (!me->mloopcol) {
CustomData_add_layer(&me->ldata, CD_MLOOPCOL, CD_DEFAULT, NULL, me->totloop);
}
BKE_mesh_update_customdata_pointers(me, true);
}
- update_tessface_data(ob, me);
-
DAG_id_tag_update(&me->id, 0);
return (me->mloopcol != NULL);
@@ -382,12 +260,12 @@ static int wpaint_mirror_vgroup_ensure(Object *ob, const int vgroup_active)
mirrdef = defgroup_name_index(ob, name_flip);
if (mirrdef == -1) {
if (BKE_defgroup_new(ob, name_flip)) {
- mirrdef = BLI_countlist(&ob->defbase) - 1;
+ mirrdef = BLI_listbase_count(&ob->defbase) - 1;
}
}
/* curdef should never be NULL unless this is
- * a lamp and ED_vgroup_add_name fails */
+ * a lamp and BKE_object_defgroup_add_name fails */
return mirrdef;
}
@@ -594,7 +472,7 @@ bool ED_vpaint_smooth(Object *ob)
/* remove stale me->mcol, will be added later */
BKE_mesh_tessface_clear(me);
- do_shared_vertexcol(me, mlooptag, NULL, false);
+ do_shared_vertexcol(me, mlooptag);
MEM_freeN(mlooptag);
@@ -770,7 +648,7 @@ BLI_INLINE unsigned int mcol_lighten(unsigned int col1, unsigned int col2, int f
/* See if are lighter, if so mix, else don't do anything.
* if the paint col is darker then the original, then ignore */
- if (rgb_to_grayscale_byte(cp1) > rgb_to_grayscale_byte(cp2)) {
+ if (IMB_colormanagement_get_luminance_byte(cp1) > IMB_colormanagement_get_luminance_byte(cp2)) {
return col1;
}
@@ -803,7 +681,7 @@ BLI_INLINE unsigned int mcol_darken(unsigned int col1, unsigned int col2, int fa
/* See if were darker, if so mix, else don't do anything.
* if the paint col is brighter then the original, then ignore */
- if (rgb_to_grayscale_byte(cp1) < rgb_to_grayscale_byte(cp2)) {
+ if (IMB_colormanagement_get_luminance_byte(cp1) < IMB_colormanagement_get_luminance_byte(cp2)) {
return col1;
}
@@ -870,7 +748,7 @@ static unsigned int vpaint_blend(VPaint *vp, unsigned int col, unsigned int colo
}
-static int sample_backbuf_area(ViewContext *vc, int *indexar, int totface, int x, int y, float size)
+static int sample_backbuf_area(ViewContext *vc, int *indexar, int totpoly, int x, int y, float size)
{
struct ImBuf *ibuf;
int a, tot = 0, index;
@@ -879,26 +757,29 @@ static int sample_backbuf_area(ViewContext *vc, int *indexar, int totface, int x
* brushes with size > 64, why is this here? */
/*if (size > 64.0) size = 64.0;*/
- ibuf = view3d_read_backbuf(vc, x - size, y - size, x + size, y + size);
+ ibuf = ED_view3d_backbuf_read(vc, x - size, y - size, x + size, y + size);
if (ibuf) {
unsigned int *rt = ibuf->rect;
- memset(indexar, 0, sizeof(int) * (totface + 1));
+ memset(indexar, 0, sizeof(int) * (totpoly + 1));
size = ibuf->x * ibuf->y;
while (size--) {
if (*rt) {
- index = WM_framebuffer_to_index(*rt);
- if (index > 0 && index <= totface)
+ index = *rt;
+ if (index > 0 && index <= totpoly) {
indexar[index] = 1;
+ }
}
rt++;
}
- for (a = 1; a <= totface; a++) {
- if (indexar[a]) indexar[tot++] = a;
+ for (a = 1; a <= totpoly; a++) {
+ if (indexar[a]) {
+ indexar[tot++] = a;
+ }
}
IMB_freeImBuf(ibuf);
@@ -919,7 +800,7 @@ static float calc_vp_strength_col_dl(VPaint *vp, ViewContext *vc, const float co
{
const float dist_sq = len_squared_v2v2(mval, co_ss);
- if (dist_sq <= brush_size_pressure * brush_size_pressure) {
+ if (dist_sq <= SQUARE(brush_size_pressure)) {
Brush *brush = BKE_paint_brush(&vp->paint);
const float dist = sqrtf(dist_sq);
float factor;
@@ -937,7 +818,7 @@ static float calc_vp_strength_col_dl(VPaint *vp, ViewContext *vc, const float co
else {
factor = 1.0f;
}
- return factor * BKE_brush_curve_strength_clamp(brush, dist, brush_size_pressure);
+ return factor * BKE_brush_curve_strength_clamped(brush, dist, brush_size_pressure);
}
}
if (rgba)
@@ -1092,7 +973,7 @@ static int weight_sample_invoke(bContext *C, wmOperator *op, const wmEvent *even
me = BKE_mesh_from_object(vc.obact);
if (me && me->dvert && vc.v3d && vc.rv3d) {
- const int use_vert_sel = (me->editflag & ME_EDIT_PAINT_VERT_SEL) != 0;
+ const bool use_vert_sel = (me->editflag & ME_EDIT_PAINT_VERT_SEL) != 0;
int v_idx_best = -1;
unsigned int index;
@@ -1177,8 +1058,8 @@ static EnumPropertyItem *weight_paint_sample_enum_itemf(bContext *C, PointerRNA
me = BKE_mesh_from_object(vc.obact);
if (me && me->dvert && vc.v3d && vc.rv3d && vc.obact->defbase.first) {
- const int defbase_tot = BLI_countlist(&vc.obact->defbase);
- const int use_vert_sel = (me->editflag & ME_EDIT_PAINT_VERT_SEL) != 0;
+ const int defbase_tot = BLI_listbase_count(&vc.obact->defbase);
+ const bool use_vert_sel = (me->editflag & ME_EDIT_PAINT_VERT_SEL) != 0;
int *groups = MEM_callocN(defbase_tot * sizeof(int), "groups");
bool found = false;
unsigned int index;
@@ -1577,8 +1458,8 @@ static void enforce_locks(MDeformVert *odv, MDeformVert *ndv,
change_status[i] = 1; /* can be altered while redistributing */
}
}
- /* if there was any change, redistribute it */
- if (total_changed) {
+ /* if there was any change, and somewhere to redistribute it, do it */
+ if (total_changed && total_valid) {
/* auto normalize will allow weights to temporarily go above 1 in redistribution */
if (vgroup_validmap && total_changed < 0 && total_valid) {
totchange_allowed = total_valid;
@@ -1742,7 +1623,8 @@ static int apply_mp_locks_normalize(Mesh *me, const WeightPaintInfo *wpi,
}
clamp_weights(dv);
- enforce_locks(&dv_test, dv, wpi->defbase_tot, wpi->defbase_sel, wpi->lock_flags, wpi->vgroup_validmap, wpi->do_auto_normalize, wpi->do_multipaint);
+ enforce_locks(&dv_test, dv, wpi->defbase_tot, wpi->defbase_sel, wpi->lock_flags, wpi->vgroup_validmap,
+ wpi->do_auto_normalize, wpi->do_multipaint);
if (wpi->do_auto_normalize) {
/* XXX - should we pass the active group? - currently '-1' */
@@ -2074,7 +1956,7 @@ static int wpaint_mode_toggle_exec(bContext *C, wmOperator *op)
paint_cursor_start(C, weight_paint_poll);
- BKE_paint_init(&wp->paint, PAINT_CURSOR_WEIGHT_PAINT);
+ BKE_paint_init(scene, ePaintWeight, PAINT_CURSOR_WEIGHT_PAINT);
/* weight paint specific */
ED_mesh_mirror_spatial_table(ob, NULL, NULL, 's');
@@ -2159,7 +2041,7 @@ static bool wpaint_ensure_data(bContext *C, wmOperator *op)
/* if nothing was added yet, we make dverts and a vertex deform group */
if (!me->dvert) {
- ED_vgroup_data_create(&me->id);
+ BKE_object_defgroup_data_create(&me->id);
WM_event_add_notifier(C, NC_GEOM | ND_DATA, me);
}
@@ -2174,7 +2056,7 @@ static bool wpaint_ensure_data(bContext *C, wmOperator *op)
if (pchan) {
bDeformGroup *dg = defgroup_find_name(ob, pchan->name);
if (dg == NULL) {
- dg = ED_vgroup_add_name(ob, pchan->name); /* sets actdef */
+ dg = BKE_object_defgroup_add_name(ob, pchan->name); /* sets actdef */
}
else {
int actdef = 1 + BLI_findindex(&ob->defbase, dg);
@@ -2186,7 +2068,7 @@ static bool wpaint_ensure_data(bContext *C, wmOperator *op)
}
}
if (BLI_listbase_is_empty(&ob->defbase)) {
- ED_vgroup_add(ob);
+ BKE_object_defgroup_add(ob);
}
/* ensure we don't try paint onto an invalid group */
@@ -2235,10 +2117,10 @@ static bool wpaint_stroke_test_start(bContext *C, wmOperator *op, const float UN
/* set up auto-normalize, and generate map for detecting which
* vgroups affect deform bones */
- wpd->defbase_tot = BLI_countlist(&ob->defbase);
- wpd->lock_flags = BKE_objdef_lock_flags_get(ob, wpd->defbase_tot);
+ wpd->defbase_tot = BLI_listbase_count(&ob->defbase);
+ wpd->lock_flags = BKE_object_defgroup_lock_flags_get(ob, wpd->defbase_tot);
if (ts->auto_normalize || ts->multipaint || wpd->lock_flags) {
- wpd->vgroup_validmap = BKE_objdef_validmap_get(ob, wpd->defbase_tot);
+ wpd->vgroup_validmap = BKE_object_defgroup_validmap_get(ob, wpd->defbase_tot);
}
/* painting on subsurfs should give correct points too, this returns me->totvert amount */
@@ -2318,7 +2200,7 @@ static void wpaint_stroke_update_step(bContext *C, struct PaintStroke *stroke, P
/* *** setup WeightPaintInfo - pass onto do_weight_paint_vertex *** */
wpi.defbase_tot = wpd->defbase_tot;
- wpi.defbase_sel = BKE_objdef_selected_get(ob, wpi.defbase_tot, &wpi.defbase_tot_sel);
+ wpi.defbase_sel = BKE_object_defgroup_selected_get(ob, wpi.defbase_tot, &wpi.defbase_tot_sel);
if (wpi.defbase_tot_sel == 0 && ob->actdef > 0) {
wpi.defbase_tot_sel = 1;
}
@@ -2682,7 +2564,7 @@ static int vpaint_mode_toggle_exec(bContext *C, wmOperator *op)
paint_cursor_start(C, vertex_paint_poll);
- BKE_paint_init(&vp->paint, PAINT_CURSOR_VERTEX_PAINT);
+ BKE_paint_init(scene, ePaintVertex, PAINT_CURSOR_VERTEX_PAINT);
}
/* update modifier stack for mapping requirements */
@@ -2750,35 +2632,13 @@ typedef struct VPaintData {
* array, otherwise we need to refresh the modifier stack */
bool use_fast_update;
- /* mpoly -> mface mapping */
- MeshElemMap *polyfacemap;
- void *polyfacemap_mem;
-
/* loops tagged as having been painted, to apply shared vertex color
* blending only to modified loops */
bool *mlooptag;
- bool *mfacetag;
bool is_texbrush;
} VPaintData;
-static void vpaint_build_poly_facemap(struct VPaintData *vd, Mesh *me)
-{
- const int *tessface_origindex;
-
- vd->polyfacemap = NULL;
- vd->polyfacemap_mem = NULL;
-
- tessface_origindex = CustomData_get_layer(&me->fdata, CD_ORIGINDEX);
-
- if (!tessface_origindex)
- return;
-
- BKE_mesh_origindex_map_create(&vd->polyfacemap, (int **)&vd->polyfacemap_mem,
- me->totpoly,
- tessface_origindex, me->totface);
-}
-
static bool vpaint_stroke_test_start(bContext *C, struct wmOperator *op, const float UNUSED(mouse[2]))
{
Scene *scene = CTX_data_scene(C);
@@ -2801,11 +2661,6 @@ static bool vpaint_stroke_test_start(bContext *C, struct wmOperator *op, const f
if (me->mloopcol == NULL)
return false;
- /* Update tessface data if needed
- * Added here too because e.g. switching to/from edit mode would remove tessface data,
- * yet "fast_update" could still be used! */
- update_tessface_data(ob, me);
-
/* make mode data storage */
vpd = MEM_callocN(sizeof(struct VPaintData), "VPaintData");
paint_stroke_set_mode_data(stroke, vpd);
@@ -2820,9 +2675,8 @@ static bool vpaint_stroke_test_start(bContext *C, struct wmOperator *op, const f
brush->mtex.tex;
/* are we painting onto a modified mesh?,
- * if not we can skip face map trickyness */
+ * if not we can skip face map trickiness */
if (vertex_paint_use_fast_update_check(ob)) {
- vpaint_build_poly_facemap(vpd, me);
vpd->use_fast_update = true;
/* printf("Fast update!\n");*/
}
@@ -2834,8 +2688,6 @@ static bool vpaint_stroke_test_start(bContext *C, struct wmOperator *op, const f
/* to keep tracked of modified loops for shared vertex color blending */
if (brush->vertexpaint_tool == PAINT_BLEND_BLUR) {
vpd->mlooptag = MEM_mallocN(sizeof(bool) * me->totloop, "VPaintData mlooptag");
- if (vpd->use_fast_update)
- vpd->mfacetag = MEM_mallocN(sizeof(bool) * me->totface * 4, "VPaintData mfacetag");
}
/* for filtering */
@@ -2856,14 +2708,10 @@ static void vpaint_paint_poly(VPaint *vp, VPaintData *vpd, Mesh *me,
ViewContext *vc = &vpd->vc;
Brush *brush = BKE_paint_brush(&vp->paint);
MPoly *mpoly = &me->mpoly[index];
- MFace *mf;
- MCol *mc;
MLoop *ml;
- MLoopCol *mlc;
unsigned int *lcol = ((unsigned int *)me->mloopcol) + mpoly->loopstart;
unsigned int *lcolorig = ((unsigned int *)vp->vpaint_prev) + mpoly->loopstart;
bool *mlooptag = (vpd->mlooptag) ? vpd->mlooptag + mpoly->loopstart : NULL;
- bool *mftag;
float alpha;
int i, j;
int totloop = mpoly->totloop;
@@ -2920,35 +2768,6 @@ static void vpaint_paint_poly(VPaint *vp, VPaintData *vpd, Mesh *me,
if (mlooptag) mlooptag[i] = 1;
}
}
-
- if (vpd->use_fast_update) {
- const MeshElemMap *map = &vpd->polyfacemap[index];
-
- /* update vertex colors for tessellations incrementally,
- * rather then regenerating the tessellation altogether */
- for (i = 0; i < map->count; i++) {
- const int index_tessface = map->indices[i];
-
- mf = &me->mface[index_tessface];
- mc = &me->mcol[index_tessface * 4];
- mftag = &vpd->mfacetag[index_tessface * 4];
-
- ml = me->mloop + mpoly->loopstart;
- mlc = me->mloopcol + mpoly->loopstart;
-
- for (j = 0; j < totloop; j++, ml++, mlc++) {
- /* search for the loop vertex within the tessface */
- const int fidx = BKE_MESH_TESSFACE_VINDEX_ORDER(mf, ml->v);
- if (fidx != -1) {
- MESH_MLOOPCOL_TO_MCOL(mlc, mc + fidx);
- if (mlooptag) {
- mftag[fidx] = mlooptag[j];
- }
- }
- }
- }
- }
-
}
static void vpaint_stroke_update_step(bContext *C, struct PaintStroke *stroke, PointerRNA *itemptr)
@@ -2984,8 +2803,8 @@ static void vpaint_stroke_update_step(bContext *C, struct PaintStroke *stroke, P
if ((me->editflag & ME_EDIT_PAINT_FACE_SEL) && me->mpoly) {
for (index = 0; index < totindex; index++) {
if (indexar[index] && indexar[index] <= me->totpoly) {
- MPoly *mpoly = ((MPoly *)me->mpoly) + (indexar[index] - 1);
-
+ const MPoly *mpoly = &me->mpoly[indexar[index] - 1];
+
if ((mpoly->flag & ME_FACE_SEL) == 0)
indexar[index] = 0;
}
@@ -3000,8 +2819,6 @@ static void vpaint_stroke_update_step(bContext *C, struct PaintStroke *stroke, P
/* clear modified tag for blur tool */
if (vpd->mlooptag)
memset(vpd->mlooptag, 0, sizeof(bool) * me->totloop);
- if (vpd->mfacetag)
- memset(vpd->mfacetag, 0, sizeof(bool) * me->totface * 4);
for (index = 0; index < totindex; index++) {
if (indexar[index] && indexar[index] <= me->totpoly) {
@@ -3013,8 +2830,7 @@ static void vpaint_stroke_update_step(bContext *C, struct PaintStroke *stroke, P
/* was disabled because it is slow, but necessary for blur */
if (brush->vertexpaint_tool == PAINT_BLEND_BLUR) {
- int do_tessface = vpd->use_fast_update;
- do_shared_vertexcol(me, vpd->mlooptag, vpd->mfacetag, do_tessface);
+ do_shared_vertexcol(me, vpd->mlooptag);
}
ED_region_tag_redraw(vc->ar);
@@ -3024,7 +2840,7 @@ static void vpaint_stroke_update_step(bContext *C, struct PaintStroke *stroke, P
* avoid this if we can! */
DAG_id_tag_update(ob->data, 0);
}
- else if (!GPU_buffer_legacy(ob->derivedFinal)) {
+ else {
/* If using new VBO drawing, mark mcol as dirty to force colors gpu buffer refresh! */
ob->derivedFinal->dirty |= DM_DIRTY_MCOL_UPDATE_DRAW;
}
@@ -3043,20 +2859,9 @@ static void vpaint_stroke_done(const bContext *C, struct PaintStroke *stroke)
/* frees prev buffer */
copy_vpaint_prev(ts->vpaint, NULL, 0);
- if (vpd->polyfacemap) {
- MEM_freeN(vpd->polyfacemap);
- }
-
- if (vpd->polyfacemap_mem) {
- MEM_freeN(vpd->polyfacemap_mem);
- }
-
if (vpd->mlooptag)
MEM_freeN(vpd->mlooptag);
- if (vpd->mfacetag)
- MEM_freeN(vpd->mfacetag);
-
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
MEM_freeN(vpd);
@@ -3217,7 +3022,7 @@ static void gradientVert_update(DMGradient_userData *grad_data, int index)
/* no need to clamp 'alpha' yet */
/* adjust weight */
- alpha = BKE_brush_curve_strength_clamp(grad_data->brush, alpha, 1.0f);
+ alpha = BKE_brush_curve_strength_clamped(grad_data->brush, alpha, 1.0f);
if (alpha != 0.0f) {
MDeformVert *dv = &me->dvert[index];
diff --git a/source/blender/editors/sculpt_paint/paint_vertex_proj.c b/source/blender/editors/sculpt_paint/paint_vertex_proj.c
index ae729248f7e..c939eb6df35 100644
--- a/source/blender/editors/sculpt_paint/paint_vertex_proj.c
+++ b/source/blender/editors/sculpt_paint/paint_vertex_proj.c
@@ -186,7 +186,7 @@ static void vpaint_proj_dm_map_cosnos_update(struct VertProjHandle *vp_handle,
/* highly unlikely this will become unavailable once painting starts (perhaps with animated modifiers) */
if (LIKELY(dm->foreachMappedVert)) {
- fill_vn_fl(vp_handle->dists_sq, me->totvert, FLT_MAX);
+ copy_vn_fl(vp_handle->dists_sq, me->totvert, FLT_MAX);
dm->foreachMappedVert(dm, vpaint_proj_dm_map_cosnos_update__map_cb, &vp_update, DM_FOREACH_USE_NORMAL);
}
diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c
index 7e518242b00..07511e1924e 100644
--- a/source/blender/editors/sculpt_paint/sculpt.c
+++ b/source/blender/editors/sculpt_paint/sculpt.c
@@ -40,9 +40,8 @@
#include "BLI_dial.h"
#include "BLI_utildefines.h"
#include "BLI_ghash.h"
-#include "BLI_threads.h"
-#include "BLF_translation.h"
+#include "BLT_translation.h"
#include "DNA_customdata_types.h"
#include "DNA_mesh_types.h"
@@ -56,8 +55,8 @@
#include "BKE_brush.h"
#include "BKE_ccg.h"
#include "BKE_context.h"
-#include "BKE_crazyspace.h"
#include "BKE_depsgraph.h"
+#include "BKE_global.h"
#include "BKE_image.h"
#include "BKE_key.h"
#include "BKE_library.h"
@@ -85,9 +84,8 @@
#include "RNA_access.h"
#include "RNA_define.h"
-#include "RE_render_ext.h"
-
#include "GPU_buffers.h"
+#include "GPU_extensions.h"
#include "UI_interface.h"
#include "UI_resources.h"
@@ -106,6 +104,8 @@
#if defined(__APPLE__) && defined _OPENMP
#include <sys/sysctl.h>
+#include "BLI_threads.h"
+
/* Query how many cores not counting HT aka physical cores we've got. */
static int system_physical_thread_count(void)
{
@@ -116,32 +116,12 @@ static int system_physical_thread_count(void)
}
#endif /* __APPLE__ */
-void ED_sculpt_stroke_get_average(Object *ob, float stroke[3])
-{
- if (ob->sculpt->last_stroke_valid && ob->sculpt->average_stroke_counter > 0) {
- float fac = 1.0f / ob->sculpt->average_stroke_counter;
- mul_v3_v3fl(stroke, ob->sculpt->average_stroke_accum, fac);
- }
- else {
- copy_v3_v3(stroke, ob->obmat[3]);
- }
-}
-
-bool ED_sculpt_minmax(bContext *C, float min[3], float max[3])
-{
- Object *ob = CTX_data_active_object(C);
-
- if (ob && ob->sculpt && ob->sculpt->last_stroke_valid) {
- copy_v3_v3(min, ob->sculpt->last_stroke);
- copy_v3_v3(max, ob->sculpt->last_stroke);
-
- return 1;
- }
- else {
- return 0;
- }
-}
-
+/** \name Tool Capabilities
+ *
+ * Avoid duplicate checks, internal logic only,
+ * share logic with #rna_def_sculpt_capabilities where possible.
+ *
+ * \{ */
/* Check if there are any active modifiers in stack (used for flushing updates at enter/exit sculpt mode) */
static bool sculpt_has_active_modifiers(Scene *scene, Object *ob)
@@ -160,6 +140,43 @@ static bool sculpt_has_active_modifiers(Scene *scene, Object *ob)
return 0;
}
+static bool sculpt_tool_needs_original(const char sculpt_tool)
+{
+ return ELEM(sculpt_tool,
+ SCULPT_TOOL_GRAB,
+ SCULPT_TOOL_ROTATE,
+ SCULPT_TOOL_THUMB,
+ SCULPT_TOOL_LAYER);
+}
+
+static bool sculpt_tool_is_proxy_used(const char sculpt_tool)
+{
+ return ELEM(sculpt_tool,
+ SCULPT_TOOL_SMOOTH,
+ SCULPT_TOOL_LAYER);
+}
+
+/**
+ * Test whether the #StrokeCache.sculpt_normal needs update in #do_brush_action
+ */
+static int sculpt_brush_needs_normal(const Brush *brush)
+{
+ return ((SCULPT_TOOL_HAS_NORMAL_WEIGHT(brush->sculpt_tool) &&
+ (brush->normal_weight > 0)) ||
+
+ ELEM(brush->sculpt_tool,
+ SCULPT_TOOL_BLOB,
+ SCULPT_TOOL_CREASE,
+ SCULPT_TOOL_DRAW,
+ SCULPT_TOOL_LAYER,
+ SCULPT_TOOL_NUDGE,
+ SCULPT_TOOL_ROTATE,
+ SCULPT_TOOL_THUMB) ||
+
+ (brush->mtex.brush_map_mode == MTEX_MAP_MODE_AREA));
+}
+
+/** \} */
typedef enum StrokeFlags {
@@ -192,8 +209,8 @@ typedef struct StrokeCache {
float true_location[3];
float location[3];
- float pen_flip;
- float invert;
+ bool pen_flip;
+ bool invert;
float pressure;
float mouse[2];
float bstrength;
@@ -209,8 +226,6 @@ typedef struct StrokeCache {
ViewContext *vc;
Brush *brush;
- float (*face_norms)[3]; /* Copy of the mesh faces' normals */
-
float special_rotation;
float grab_delta[3], grab_delta_symmetry[3];
float old_grab_location[3], orig_grab_location[3];
@@ -231,6 +246,9 @@ typedef struct StrokeCache {
* calc_brush_local_mat() and used in tex_strength(). */
float brush_local_mat[4][4];
+ float plane_offset[3]; /* used to shift the plane around when doing tiled strokes */
+ int tile_pass;
+
float last_center[3];
int radial_symmetry_pass;
float symm_rot_mat[4][4];
@@ -268,8 +286,8 @@ typedef struct {
/* Original coordinate, normal, and mask */
const float *co;
- float mask;
const short *no;
+ float mask;
} SculptOrigVertData;
@@ -312,30 +330,70 @@ static void sculpt_orig_vert_data_update(SculptOrigVertData *orig_data,
PBVHVertexIter *iter)
{
if (orig_data->unode->type == SCULPT_UNDO_COORDS) {
- if (orig_data->coords) {
- orig_data->co = orig_data->coords[iter->i];
+ if (orig_data->bm_log) {
+ BM_log_original_vert_data(
+ orig_data->bm_log, iter->bm_vert,
+ &orig_data->co, &orig_data->no);
}
else {
- orig_data->co = BM_log_original_vert_co(orig_data->bm_log, iter->bm_vert);
- }
-
- if (orig_data->normals) {
+ orig_data->co = orig_data->coords[iter->i];
orig_data->no = orig_data->normals[iter->i];
}
- else {
- orig_data->no = BM_log_original_vert_no(orig_data->bm_log, iter->bm_vert);
- }
}
else if (orig_data->unode->type == SCULPT_UNDO_MASK) {
- if (orig_data->vmasks) {
- orig_data->mask = orig_data->vmasks[iter->i];
+ if (orig_data->bm_log) {
+ orig_data->mask = BM_log_original_mask(orig_data->bm_log, iter->bm_vert);
}
else {
- orig_data->mask = BM_log_original_mask(orig_data->bm_log, iter->bm_vert);
+ orig_data->mask = orig_data->vmasks[iter->i];
}
}
}
+/** \name SculptProjectVector
+ *
+ * Fast-path for #project_plane_v3_v3v3
+ *
+ * \{ */
+
+typedef struct SculptProjectVector {
+ float plane[3];
+ float len_sq;
+ float len_sq_inv_neg;
+ bool is_valid;
+
+} SculptProjectVector;
+
+/**
+ * \param plane Direction, can be any length.
+ */
+static void sculpt_project_v3_cache_init(
+ SculptProjectVector *spvc, const float plane[3])
+{
+ copy_v3_v3(spvc->plane, plane);
+ spvc->len_sq = len_squared_v3(spvc->plane);
+ spvc->is_valid = (spvc->len_sq > FLT_EPSILON);
+ spvc->len_sq_inv_neg = (spvc->is_valid) ? -1.0f / spvc->len_sq : 0.0f;
+}
+
+/**
+ * Calculate the projection.
+ */
+static void sculpt_project_v3(
+ const SculptProjectVector *spvc, const float vec[3],
+ float r_vec[3])
+{
+#if 0
+ project_plane_v3_v3v3(r_vec, vec, spvc->plane);
+#else
+ /* inline the projection, cache `-1.0 / dot_v3_v3(v_proj, v_proj)` */
+ madd_v3_v3fl(r_vec, spvc->plane, dot_v3v3(vec, spvc->plane) * spvc->len_sq_inv_neg);
+#endif
+}
+
+/** \} */
+
+
/**********************************************************************/
/* Returns true if the stroke will use dynamic topology, false
@@ -344,8 +402,8 @@ static void sculpt_orig_vert_data_update(SculptOrigVertData *orig_data,
* Factors: some brushes like grab cannot do dynamic topology.
* Others, like smooth, are better without. Same goes for alt-
* key smoothing. */
-static int sculpt_stroke_dynamic_topology(const SculptSession *ss,
- const Brush *brush)
+static bool sculpt_stroke_is_dynamic_topology(
+ const SculptSession *ss, const Brush *brush)
{
return ((BKE_pbvh_type(ss->pbvh) == PBVH_BMESH) &&
@@ -355,20 +413,8 @@ static int sculpt_stroke_dynamic_topology(const SculptSession *ss,
* dynamic-topology */
!(brush->flag & BRUSH_ANCHORED) &&
!(brush->flag & BRUSH_DRAG_DOT) &&
-
- (!ELEM(brush->sculpt_tool,
- /* These brushes, as currently coded, cannot
- * support dynamic topology */
- SCULPT_TOOL_GRAB,
- SCULPT_TOOL_ROTATE,
- SCULPT_TOOL_THUMB,
- SCULPT_TOOL_LAYER,
-
- /* These brushes could handle dynamic topology,
- * but user feedback indicates it's better not
- * to */
- SCULPT_TOOL_SMOOTH,
- SCULPT_TOOL_MASK)));
+
+ SCULPT_TOOL_HAS_DYNTOPO(brush->sculpt_tool));
}
/*** paint mesh ***/
@@ -376,17 +422,11 @@ static int sculpt_stroke_dynamic_topology(const SculptSession *ss,
static void paint_mesh_restore_co(Sculpt *sd, Object *ob)
{
SculptSession *ss = ob->sculpt;
- StrokeCache *cache = ss->cache;
const Brush *brush = BKE_paint_brush(&sd->paint);
- int i;
PBVHNode **nodes;
int n, totnode;
-#ifndef _OPENMP
- (void)sd; /* quied unused warning */
-#endif
-
BKE_pbvh_search_gather(ss->pbvh, NULL, NULL, &nodes, &totnode);
/* Disable OpenMP when dynamic-topology is enabled. Otherwise, new
@@ -431,12 +471,6 @@ static void paint_mesh_restore_co(Sculpt *sd, Object *ob)
}
}
- if (ss->face_normals) {
- for (i = 0; i < ss->totpoly; i++) {
- copy_v3_v3(ss->face_normals[i], cache->face_norms[i]);
- }
- }
-
if (nodes)
MEM_freeN(nodes);
}
@@ -536,7 +570,7 @@ static void sculpt_brush_test_init(SculptSession *ss, SculptBrushTest *test)
}
}
-BLI_INLINE bool sculpt_brush_test_clipping(SculptBrushTest *test, const float co[3])
+BLI_INLINE bool sculpt_brush_test_clipping(const SculptBrushTest *test, const float co[3])
{
RegionView3D *rv3d = test->clip_rv3d;
return (rv3d && (ED_view3d_clipping_test(rv3d, co, true)));
@@ -574,7 +608,7 @@ static bool sculpt_brush_test_sq(SculptBrushTest *test, const float co[3])
}
}
-static bool sculpt_brush_test_fast(SculptBrushTest *test, float co[3])
+static bool sculpt_brush_test_fast(const SculptBrushTest *test, const float co[3])
{
if (sculpt_brush_test_clipping(test, co)) {
return 0;
@@ -582,7 +616,7 @@ static bool sculpt_brush_test_fast(SculptBrushTest *test, float co[3])
return len_squared_v3v3(co, test->location) <= test->radius_squared;
}
-static bool sculpt_brush_test_cube(SculptBrushTest *test, float co[3], float local[4][4])
+static bool sculpt_brush_test_cube(SculptBrushTest *test, const float co[3], float local[4][4])
{
float side = M_SQRT1_2;
float local_co[3];
@@ -635,7 +669,7 @@ static float frontface(Brush *br, const float sculpt_normal[3],
#if 0
-static bool sculpt_brush_test_cyl(SculptBrushTest *test, float co[3], float location[3], float an[3])
+static bool sculpt_brush_test_cyl(SculptBrushTest *test, float co[3], float location[3], const float area_no[3])
{
if (sculpt_brush_test_fast(test, co)) {
float t1[3], t2[3], t3[3], dist;
@@ -643,7 +677,7 @@ static bool sculpt_brush_test_cyl(SculptBrushTest *test, float co[3], float loca
sub_v3_v3v3(t1, location, co);
sub_v3_v3v3(t2, x2, location);
- cross_v3_v3v3(t3, an, t1);
+ cross_v3_v3v3(t3, area_no, t1);
dist = len_v3(t3) / len_v3(t2);
@@ -729,18 +763,447 @@ static float calc_symmetry_feather(Sculpt *sd, StrokeCache *cache)
}
}
+/** \name Calculate Normal and Center
+ *
+ * Calculate geometry surrounding the brush center.
+ * (optionally using original coordinates).
+ *
+ * Functions are:
+ * - #calc_area_center
+ * - #calc_area_normal
+ * - #calc_area_normal_and_center
+ *
+ * \note These are all _very_ similar, when changing one, check others.
+ * \{ */
+
+static void calc_area_center(
+ Sculpt *sd, Object *ob,
+ PBVHNode **nodes, int totnode,
+ float r_area_co[3])
+{
+ const Brush *brush = BKE_paint_brush(&sd->paint);
+ SculptSession *ss = ob->sculpt;
+ const bool has_bm_orco = ss->bm && sculpt_stroke_is_dynamic_topology(ss, brush);
+ int n;
+
+ /* 0=towards view, 1=flipped */
+ float area_co[2][3] = {{0.0f}};
+
+ int count[2] = {0};
+
+#pragma omp parallel for schedule(guided) if ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_OMP_LIMIT)
+ for (n = 0; n < totnode; n++) {
+ PBVHVertexIter vd;
+ SculptBrushTest test;
+ SculptUndoNode *unode;
+ float private_co[2][3] = {{0.0f}};
+ int private_count[2] = {0};
+ bool use_original;
+
+ unode = sculpt_undo_push_node(ob, nodes[n], SCULPT_UNDO_COORDS);
+ sculpt_brush_test_init(ss, &test);
+
+ use_original = (ss->cache->original && (unode->co || unode->bm_entry));
+
+ /* when the mesh is edited we can't rely on original coords
+ * (original mesh may not even have verts in brush radius) */
+ if (use_original && has_bm_orco) {
+ float (*orco_coords)[3];
+ int (*orco_tris)[3];
+ int orco_tris_num;
+ int i;
+
+ BKE_pbvh_node_get_bm_orco_data(
+ nodes[n],
+ &orco_tris, &orco_tris_num, &orco_coords);
+
+ for (i = 0; i < orco_tris_num; i++) {
+ const float *co_tri[3] = {
+ orco_coords[orco_tris[i][0]],
+ orco_coords[orco_tris[i][1]],
+ orco_coords[orco_tris[i][2]],
+ };
+ float co[3];
+
+ closest_on_tri_to_point_v3(co, test.location, UNPACK3(co_tri));
+
+ if (sculpt_brush_test_fast(&test, co)) {
+ float no[3];
+ int flip_index;
+
+ cross_tri_v3(no, UNPACK3(co_tri));
+
+ flip_index = (dot_v3v3(ss->cache->view_normal, no) <= 0.0f);
+ add_v3_v3(private_co[flip_index], co);
+ private_count[flip_index] += 1;
+ }
+ }
+ }
+ else {
+ BKE_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE)
+ {
+ const float *co;
+ const short *no_s; /* bm_vert only */
+
+ if (use_original) {
+ if (unode->bm_entry) {
+ BM_log_original_vert_data(ss->bm_log, vd.bm_vert, &co, &no_s);
+ }
+ else {
+ co = unode->co[vd.i];
+ no_s = unode->no[vd.i];
+ }
+ }
+ else {
+ co = vd.co;
+ }
+
+ if (sculpt_brush_test_fast(&test, co)) {
+ float no_buf[3];
+ const float *no;
+ int flip_index;
+
+ if (use_original) {
+ normal_short_to_float_v3(no_buf, no_s);
+ no = no_buf;
+ }
+ else {
+ if (vd.no) {
+ normal_short_to_float_v3(no_buf, vd.no);
+ no = no_buf;
+ }
+ else {
+ no = vd.fno;
+ }
+ }
+
+ flip_index = (dot_v3v3(ss->cache->view_normal, no) <= 0.0f);
+ add_v3_v3(private_co[flip_index], co);
+ private_count[flip_index] += 1;
+ }
+ }
+ BKE_pbvh_vertex_iter_end;
+ }
+
+#pragma omp critical
+ {
+ /* for flatten center */
+ add_v3_v3(area_co[0], private_co[0]);
+ add_v3_v3(area_co[1], private_co[1]);
+
+ /* weights */
+ count[0] += private_count[0];
+ count[1] += private_count[1];
+ }
+ }
+
+ /* for flatten center */
+ for (n = 0; n < ARRAY_SIZE(area_co); n++) {
+ if (count[n] != 0) {
+ mul_v3_v3fl(r_area_co, area_co[n], 1.0f / count[n]);
+ break;
+ }
+ }
+ if (n == 2) {
+ zero_v3(r_area_co);
+ }
+}
+
+
+static void calc_area_normal(
+ Sculpt *sd, Object *ob,
+ PBVHNode **nodes, int totnode,
+ float r_area_no[3])
+{
+ const Brush *brush = BKE_paint_brush(&sd->paint);
+ SculptSession *ss = ob->sculpt;
+ const bool has_bm_orco = ss->bm && sculpt_stroke_is_dynamic_topology(ss, brush);
+ int n;
+
+ /* 0=towards view, 1=flipped */
+ float area_no[2][3] = {{0.0f}};
+
+ int count[2] = {0};
+
+#pragma omp parallel for schedule(guided) if ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_OMP_LIMIT)
+ for (n = 0; n < totnode; n++) {
+ PBVHVertexIter vd;
+ SculptBrushTest test;
+ SculptUndoNode *unode;
+ float private_no[2][3] = {{0.0f}};
+ int private_count[2] = {0};
+ bool use_original;
+
+ unode = sculpt_undo_push_node(ob, nodes[n], SCULPT_UNDO_COORDS);
+ sculpt_brush_test_init(ss, &test);
+
+ use_original = (ss->cache->original && (unode->co || unode->bm_entry));
+
+ /* when the mesh is edited we can't rely on original coords
+ * (original mesh may not even have verts in brush radius) */
+ if (use_original && has_bm_orco) {
+ float (*orco_coords)[3];
+ int (*orco_tris)[3];
+ int orco_tris_num;
+ int i;
+
+ BKE_pbvh_node_get_bm_orco_data(
+ nodes[n],
+ &orco_tris, &orco_tris_num, &orco_coords);
+
+ for (i = 0; i < orco_tris_num; i++) {
+ const float *co_tri[3] = {
+ orco_coords[orco_tris[i][0]],
+ orco_coords[orco_tris[i][1]],
+ orco_coords[orco_tris[i][2]],
+ };
+ float co[3];
+
+ closest_on_tri_to_point_v3(co, test.location, UNPACK3(co_tri));
+
+ if (sculpt_brush_test_fast(&test, co)) {
+ float no[3];
+ int flip_index;
+
+ normal_tri_v3(no, UNPACK3(co_tri));
+
+ flip_index = (dot_v3v3(ss->cache->view_normal, no) <= 0.0f);
+ add_v3_v3(private_no[flip_index], no);
+ private_count[flip_index] += 1;
+ }
+ }
+ }
+ else {
+ BKE_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE)
+ {
+ const float *co;
+ const short *no_s; /* bm_vert only */
+
+ if (use_original) {
+ if (unode->bm_entry) {
+ BM_log_original_vert_data(ss->bm_log, vd.bm_vert, &co, &no_s);
+ }
+ else {
+ co = unode->co[vd.i];
+ no_s = unode->no[vd.i];
+ }
+ }
+ else {
+ co = vd.co;
+ }
+
+ if (sculpt_brush_test_fast(&test, co)) {
+ float no_buf[3];
+ const float *no;
+ int flip_index;
+
+ if (use_original) {
+ normal_short_to_float_v3(no_buf, no_s);
+ no = no_buf;
+ }
+ else {
+ if (vd.no) {
+ normal_short_to_float_v3(no_buf, vd.no);
+ no = no_buf;
+ }
+ else {
+ no = vd.fno;
+ }
+ }
+
+ flip_index = (dot_v3v3(ss->cache->view_normal, no) <= 0.0f);
+ add_v3_v3(private_no[flip_index], no);
+ private_count[flip_index] += 1;
+ }
+ }
+ BKE_pbvh_vertex_iter_end;
+ }
+
+#pragma omp critical
+ {
+ /* for area normal */
+ add_v3_v3(area_no[0], private_no[0]);
+ add_v3_v3(area_no[1], private_no[1]);
+
+ /* weights */
+ count[0] += private_count[0];
+ count[1] += private_count[1];
+ }
+ }
+
+ /* for area normal */
+ for (n = 0; n < ARRAY_SIZE(area_no); n++) {
+ if (normalize_v3_v3(r_area_no, area_no[n]) != 0.0f) {
+ break;
+ }
+ }
+}
+
+/* this calculates flatten center and area normal together,
+ * amortizing the memory bandwidth and loop overhead to calculate both at the same time */
+static void calc_area_normal_and_center(
+ Sculpt *sd, Object *ob,
+ PBVHNode **nodes, int totnode,
+ float r_area_no[3], float r_area_co[3])
+{
+ const Brush *brush = BKE_paint_brush(&sd->paint);
+ SculptSession *ss = ob->sculpt;
+ const bool has_bm_orco = ss->bm && sculpt_stroke_is_dynamic_topology(ss, brush);
+ int n;
+
+ /* 0=towards view, 1=flipped */
+ float area_co[2][3] = {{0.0f}};
+ float area_no[2][3] = {{0.0f}};
+
+ int count[2] = {0};
+
+#pragma omp parallel for schedule(guided) if ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_OMP_LIMIT)
+ for (n = 0; n < totnode; n++) {
+ PBVHVertexIter vd;
+ SculptBrushTest test;
+ SculptUndoNode *unode;
+ float private_co[2][3] = {{0.0f}};
+ float private_no[2][3] = {{0.0f}};
+ int private_count[2] = {0};
+ bool use_original;
+
+ unode = sculpt_undo_push_node(ob, nodes[n], SCULPT_UNDO_COORDS);
+ sculpt_brush_test_init(ss, &test);
+
+ use_original = (ss->cache->original && (unode->co || unode->bm_entry));
+
+ /* when the mesh is edited we can't rely on original coords
+ * (original mesh may not even have verts in brush radius) */
+ if (use_original && has_bm_orco) {
+ float (*orco_coords)[3];
+ int (*orco_tris)[3];
+ int orco_tris_num;
+ int i;
+
+ BKE_pbvh_node_get_bm_orco_data(
+ nodes[n],
+ &orco_tris, &orco_tris_num, &orco_coords);
+
+ for (i = 0; i < orco_tris_num; i++) {
+ const float *co_tri[3] = {
+ orco_coords[orco_tris[i][0]],
+ orco_coords[orco_tris[i][1]],
+ orco_coords[orco_tris[i][2]],
+ };
+ float co[3];
+
+ closest_on_tri_to_point_v3(co, test.location, UNPACK3(co_tri));
+
+ if (sculpt_brush_test_fast(&test, co)) {
+ float no[3];
+ int flip_index;
+
+ normal_tri_v3(no, UNPACK3(co_tri));
+
+ flip_index = (dot_v3v3(ss->cache->view_normal, no) <= 0.0f);
+ add_v3_v3(private_co[flip_index], co);
+ add_v3_v3(private_no[flip_index], no);
+ private_count[flip_index] += 1;
+ }
+ }
+ }
+ else {
+ BKE_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE)
+ {
+ const float *co;
+ const short *no_s; /* bm_vert only */
+
+ if (use_original) {
+ if (unode->bm_entry) {
+ BM_log_original_vert_data(ss->bm_log, vd.bm_vert, &co, &no_s);
+ }
+ else {
+ co = unode->co[vd.i];
+ no_s = unode->no[vd.i];
+ }
+ }
+ else {
+ co = vd.co;
+ }
+
+ if (sculpt_brush_test_fast(&test, co)) {
+ float no_buf[3];
+ const float *no;
+ int flip_index;
+
+ if (use_original) {
+ normal_short_to_float_v3(no_buf, no_s);
+ no = no_buf;
+ }
+ else {
+ if (vd.no) {
+ normal_short_to_float_v3(no_buf, vd.no);
+ no = no_buf;
+ }
+ else {
+ no = vd.fno;
+ }
+ }
+
+ flip_index = (dot_v3v3(ss->cache->view_normal, no) <= 0.0f);
+ add_v3_v3(private_co[flip_index], co);
+ add_v3_v3(private_no[flip_index], no);
+ private_count[flip_index] += 1;
+ }
+ }
+ BKE_pbvh_vertex_iter_end;
+ }
+
+#pragma omp critical
+ {
+ /* for flatten center */
+ add_v3_v3(area_co[0], private_co[0]);
+ add_v3_v3(area_co[1], private_co[1]);
+
+ /* for area normal */
+ add_v3_v3(area_no[0], private_no[0]);
+ add_v3_v3(area_no[1], private_no[1]);
+
+ /* weights */
+ count[0] += private_count[0];
+ count[1] += private_count[1];
+ }
+ }
+
+ /* for flatten center */
+ for (n = 0; n < ARRAY_SIZE(area_co); n++) {
+ if (count[n] != 0) {
+ mul_v3_v3fl(r_area_co, area_co[n], 1.0f / count[n]);
+ break;
+ }
+ }
+ if (n == 2) {
+ zero_v3(r_area_co);
+ }
+
+ /* for area normal */
+ for (n = 0; n < ARRAY_SIZE(area_no); n++) {
+ if (normalize_v3_v3(r_area_no, area_no[n]) != 0.0f) {
+ break;
+ }
+ }
+}
+
+/** \} */
+
+
/* Return modified brush strength. Includes the direction of the brush, positive
* values pull vertices, negative values push. Uses tablet pressure and a
* special multiplier found experimentally to scale the strength factor. */
-static float brush_strength(Sculpt *sd, StrokeCache *cache, float feather, UnifiedPaintSettings *ups)
+static float brush_strength(const Sculpt *sd, const StrokeCache *cache, const float feather, const UnifiedPaintSettings *ups)
{
const Scene *scene = cache->vc->scene;
- Brush *brush = BKE_paint_brush(&sd->paint);
+ const Brush *brush = BKE_paint_brush((Paint *)&sd->paint);
/* Primary strength input; square it to make lower values more sensitive */
const float root_alpha = BKE_brush_alpha_get(scene, brush);
float alpha = root_alpha * root_alpha;
- float dir = brush->flag & BRUSH_DIR_IN ? -1 : 1;
+ float dir = (brush->flag & BRUSH_DIR_IN) ? -1 : 1;
float pressure = BKE_brush_use_alpha_pressure(scene, brush) ? cache->pressure : 1;
float pen_flip = cache->pen_flip ? -1 : 1;
float invert = cache->invert ? -1 : 1;
@@ -809,10 +1272,10 @@ static float brush_strength(Sculpt *sd, StrokeCache *cache, float feather, Unifi
return alpha * pressure * feather;
case SCULPT_TOOL_SNAKE_HOOK:
- return feather;
+ return root_alpha * feather;
case SCULPT_TOOL_GRAB:
- return feather;
+ return root_alpha * feather;
case SCULPT_TOOL_ROTATE:
return alpha * pressure * feather;
@@ -954,132 +1417,34 @@ static void sculpt_clip(Sculpt *sd, SculptSession *ss, float co[3], const float
}
}
-static void add_norm_if(float view_vec[3], float out[3], float out_flip[3], float fno[3])
-{
- if ((dot_v3v3(view_vec, fno)) > 0) {
- add_v3_v3(out, fno);
- }
- else {
- add_v3_v3(out_flip, fno); /* out_flip is used when out is {0,0,0} */
- }
-}
-
-static void calc_area_normal(Sculpt *sd, Object *ob, float an[3], PBVHNode **nodes, int totnode)
-{
- float out_flip[3] = {0.0f, 0.0f, 0.0f};
-
- SculptSession *ss = ob->sculpt;
- const Brush *brush = BKE_paint_brush(&sd->paint);
- int n;
- bool original;
-
- /* Grab brush requires to test on original data (see r33888 and
- * bug #25371) */
- original = (BKE_paint_brush(&sd->paint)->sculpt_tool == SCULPT_TOOL_GRAB ?
- true : ss->cache->original);
-
- /* In general the original coords are not available with dynamic
- * topology
- *
- * Mask tool could not use undo nodes to get coordinates from
- * since the coordinates are not stored in those odes.
- * And mask tool is not gonna to modify vertex coordinates,
- * so we don't actually need to use modified coords.
- */
- if (ss->bm || brush->sculpt_tool == SCULPT_TOOL_MASK)
- original = false;
-
- (void)sd; /* unused w/o openmp */
-
- zero_v3(an);
-
-#pragma omp parallel for schedule(guided) if ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_OMP_LIMIT)
- for (n = 0; n < totnode; n++) {
- PBVHVertexIter vd;
- SculptBrushTest test;
- SculptUndoNode *unode;
- float private_an[3] = {0.0f, 0.0f, 0.0f};
- float private_out_flip[3] = {0.0f, 0.0f, 0.0f};
-
- unode = sculpt_undo_push_node(ob, nodes[n], SCULPT_UNDO_COORDS);
- sculpt_brush_test_init(ss, &test);
-
- if (original) {
- BKE_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE)
- {
- if (sculpt_brush_test_fast(&test, unode->co[vd.i])) {
- float fno[3];
-
- normal_short_to_float_v3(fno, unode->no[vd.i]);
- add_norm_if(ss->cache->view_normal, private_an, private_out_flip, fno);
- }
- }
- BKE_pbvh_vertex_iter_end;
- }
- else {
- BKE_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE)
- {
- if (sculpt_brush_test_fast(&test, vd.co)) {
- if (vd.no) {
- float fno[3];
-
- normal_short_to_float_v3(fno, vd.no);
- add_norm_if(ss->cache->view_normal, private_an, private_out_flip, fno);
- }
- else {
- add_norm_if(ss->cache->view_normal, private_an, private_out_flip, vd.fno);
- }
- }
- }
- BKE_pbvh_vertex_iter_end;
- }
-
-#pragma omp critical
- {
- add_v3_v3(an, private_an);
- add_v3_v3(out_flip, private_out_flip);
- }
- }
-
- if (is_zero_v3(an))
- copy_v3_v3(an, out_flip);
-
- normalize_v3(an);
-}
-
/* Calculate primary direction of movement for many brushes */
-static void calc_sculpt_normal(Sculpt *sd, Object *ob,
- PBVHNode **nodes, int totnode,
- float an[3])
+static void calc_sculpt_normal(
+ Sculpt *sd, Object *ob,
+ PBVHNode **nodes, int totnode,
+ float r_area_no[3])
{
const Brush *brush = BKE_paint_brush(&sd->paint);
const SculptSession *ss = ob->sculpt;
switch (brush->sculpt_plane) {
case SCULPT_DISP_DIR_VIEW:
- copy_v3_v3(an, ss->cache->true_view_normal);
+ copy_v3_v3(r_area_no, ss->cache->true_view_normal);
break;
case SCULPT_DISP_DIR_X:
- an[1] = 0.0;
- an[2] = 0.0;
- an[0] = 1.0;
+ ARRAY_SET_ITEMS(r_area_no, 1, 0, 0);
break;
case SCULPT_DISP_DIR_Y:
- an[0] = 0.0;
- an[2] = 0.0;
- an[1] = 1.0;
+ ARRAY_SET_ITEMS(r_area_no, 0, 1, 0);
break;
case SCULPT_DISP_DIR_Z:
- an[0] = 0.0;
- an[1] = 0.0;
- an[2] = 1.0;
+ ARRAY_SET_ITEMS(r_area_no, 0, 0, 1);
break;
case SCULPT_DISP_DIR_AREA:
- calc_area_normal(sd, ob, an, nodes, totnode);
+ calc_area_normal(sd, ob, nodes, totnode, r_area_no);
break;
default:
@@ -1180,27 +1545,6 @@ static void update_brush_local_mat(Sculpt *sd, Object *ob)
}
}
-/* Test whether the StrokeCache.sculpt_normal needs update in
- * do_brush_action() */
-static int brush_needs_sculpt_normal(const Brush *brush)
-{
- return ((ELEM(brush->sculpt_tool,
- SCULPT_TOOL_GRAB,
- SCULPT_TOOL_SNAKE_HOOK) &&
- (brush->normal_weight > 0)) ||
-
- ELEM(brush->sculpt_tool,
- SCULPT_TOOL_BLOB,
- SCULPT_TOOL_CREASE,
- SCULPT_TOOL_DRAW,
- SCULPT_TOOL_LAYER,
- SCULPT_TOOL_NUDGE,
- SCULPT_TOOL_ROTATE,
- SCULPT_TOOL_THUMB) ||
-
- (brush->mtex.brush_map_mode == MTEX_MAP_MODE_AREA));
-}
-
/* For the smooth brush, uses the neighboring vertices around vert to calculate
* a smoothed location for vert. Skips corner vertices (used by only one
* polygon.) */
@@ -1210,20 +1554,19 @@ static void neighbor_average(SculptSession *ss, float avg[3], unsigned vert)
const MVert *mvert = ss->mvert;
float (*deform_co)[3] = ss->deform_cos;
- zero_v3(avg);
-
/* Don't modify corner vertices */
if (vert_map->count > 1) {
int i, total = 0;
+ zero_v3(avg);
+
for (i = 0; i < vert_map->count; i++) {
const MPoly *p = &ss->mpoly[vert_map->indices[i]];
- unsigned f_adj_v[3];
+ unsigned f_adj_v[2];
- if (poly_get_adj_loops_from_vert(f_adj_v, p, ss->mloop, vert) != -1) {
+ if (poly_get_adj_loops_from_vert(p, ss->mloop, vert, f_adj_v) != -1) {
int j;
-
- for (j = 0; j < 3; j++) {
+ for (j = 0; j < ARRAY_SIZE(f_adj_v); j += 1) {
if (vert_map->count != 2 || ss->pmap[f_adj_v[j]].count <= 2) {
add_v3_v3(avg, deform_co ? deform_co[f_adj_v[j]] :
mvert[f_adj_v[j]].co);
@@ -1254,12 +1597,11 @@ static float neighbor_average_mask(SculptSession *ss, unsigned vert)
for (i = 0; i < ss->pmap[vert].count; i++) {
const MPoly *p = &ss->mpoly[ss->pmap[vert].indices[i]];
- unsigned f_adj_v[3];
+ unsigned f_adj_v[2];
- if (poly_get_adj_loops_from_vert(f_adj_v, p, ss->mloop, vert) != -1) {
+ if (poly_get_adj_loops_from_vert(p, ss->mloop, vert, f_adj_v) != -1) {
int j;
-
- for (j = 0; j < 3; j++) {
+ for (j = 0; j < ARRAY_SIZE(f_adj_v); j += 1) {
avg += vmask[f_adj_v[j]];
total++;
}
@@ -1275,22 +1617,24 @@ static float neighbor_average_mask(SculptSession *ss, unsigned vert)
/* Same logic as neighbor_average(), but for bmesh rather than mesh */
static void bmesh_neighbor_average(float avg[3], BMVert *v)
{
- const int vfcount = BM_vert_face_count(v);
+ /* logic for 3 or more is identical */
+ const int vfcount = BM_vert_face_count_ex(v, 3);
- zero_v3(avg);
-
/* Don't modify corner vertices */
if (vfcount > 1) {
BMIter liter;
BMLoop *l;
int i, total = 0;
+ zero_v3(avg);
+
BM_ITER_ELEM (l, &liter, v, BM_LOOPS_OF_VERT) {
- BMVert *adj_v[3] = {l->prev->v, v, l->next->v};
+ const BMVert *adj_v[2] = {l->prev->v, l->next->v};
- for (i = 0; i < 3; i++) {
- if (vfcount != 2 || BM_vert_face_count(adj_v[i]) <= 2) {
- add_v3_v3(avg, adj_v[i]->co);
+ for (i = 0; i < ARRAY_SIZE(adj_v); i++) {
+ const BMVert *v_other = adj_v[i];
+ if (vfcount != 2 || BM_vert_face_count_ex(v_other, 2) <= 2) {
+ add_v3_v3(avg, v_other->co);
total++;
}
}
@@ -1306,7 +1650,7 @@ static void bmesh_neighbor_average(float avg[3], BMVert *v)
}
/* Same logic as neighbor_average_mask(), but for bmesh rather than mesh */
-static float bmesh_neighbor_average_mask(BMesh *bm, BMVert *v)
+static float bmesh_neighbor_average_mask(BMVert *v, const int cd_vert_mask_offset)
{
BMIter liter;
BMLoop *l;
@@ -1314,13 +1658,12 @@ static float bmesh_neighbor_average_mask(BMesh *bm, BMVert *v)
int i, total = 0;
BM_ITER_ELEM (l, &liter, v, BM_LOOPS_OF_VERT) {
- BMVert *adj_v[3] = {l->prev->v, v, l->next->v};
+ /* skip this vertex */
+ const BMVert *adj_v[2] = {l->prev->v, l->next->v};
- for (i = 0; i < 3; i++) {
- BMVert *v2 = adj_v[i];
- float *vmask = CustomData_bmesh_get(&bm->vdata,
- v2->head.data,
- CD_PAINT_MASK);
+ for (i = 0; i < ARRAY_SIZE(adj_v); i++) {
+ const BMVert *v_other = adj_v[i];
+ const float *vmask = BM_ELEM_CD_GET_VOID_P(v_other, cd_vert_mask_offset);
avg += (*vmask);
total++;
}
@@ -1330,9 +1673,7 @@ static float bmesh_neighbor_average_mask(BMesh *bm, BMVert *v)
return avg / (float)total;
}
else {
- float *vmask = CustomData_bmesh_get(&bm->vdata,
- v->head.data,
- CD_PAINT_MASK);
+ const float *vmask = BM_ELEM_CD_GET_VOID_P(v, cd_vert_mask_offset);
return (*vmask);
}
}
@@ -1395,7 +1736,7 @@ static void do_bmesh_smooth_brush(Sculpt *sd, SculptSession *ss, PBVHNode *node,
vd.no, vd.fno,
smooth_mask ? 0 : *vd.mask);
if (smooth_mask) {
- float val = bmesh_neighbor_average_mask(ss->bm, vd.bm_vert) - *vd.mask;
+ float val = bmesh_neighbor_average_mask(vd.bm_vert, vd.cd_vert_mask_offset) - *vd.mask;
val *= fade * bstrength;
*vd.mask += val;
CLAMP(*vd.mask, 0, 1);
@@ -1426,12 +1767,11 @@ static void do_multires_smooth_brush(Sculpt *sd, SculptSession *ss, PBVHNode *no
SculptBrushTest test;
CCGElem **griddata, *data;
CCGKey key;
- DMGridAdjacency *gridadj, *adj;
float (*tmpgrid_co)[3], (*tmprow_co)[3];
float *tmpgrid_mask, *tmprow_mask;
int v1, v2, v3, v4;
int thread_num;
- BLI_bitmap **grid_hidden;
+ BLI_bitmap * const *grid_hidden;
int *grid_indices, totgrid, gridsize, i, x, y;
sculpt_brush_test_init(ss, &test);
@@ -1439,7 +1779,7 @@ static void do_multires_smooth_brush(Sculpt *sd, SculptSession *ss, PBVHNode *no
CLAMP(bstrength, 0.0f, 1.0f);
BKE_pbvh_node_get_grids(ss->pbvh, node, &grid_indices, &totgrid,
- NULL, &gridsize, &griddata, &gridadj);
+ NULL, &gridsize, &griddata);
BKE_pbvh_get_grid_key(ss->pbvh, &key);
grid_hidden = BKE_pbvh_grid_hidden(ss->pbvh);
@@ -1456,9 +1796,8 @@ static void do_multires_smooth_brush(Sculpt *sd, SculptSession *ss, PBVHNode *no
for (i = 0; i < totgrid; ++i) {
int gi = grid_indices[i];
- BLI_bitmap *gh = grid_hidden[gi];
+ const BLI_bitmap *gh = grid_hidden[gi];
data = griddata[gi];
- adj = &gridadj[gi];
if (smooth_mask)
memset(tmpgrid_mask, 0, sizeof(float) * gridsize * gridsize);
@@ -1524,18 +1863,6 @@ static void do_multires_smooth_brush(Sculpt *sd, SculptSession *ss, PBVHNode *no
continue;
}
- if (x == 0 && adj->index[0] == -1)
- continue;
-
- if (x == gridsize - 1 && adj->index[2] == -1)
- continue;
-
- if (y == 0 && adj->index[3] == -1)
- continue;
-
- if (y == gridsize - 1 && adj->index[1] == -1)
- continue;
-
index = x + y * gridsize;
co = CCG_elem_offset_co(&key, data, index);
fno = CCG_elem_offset_no(&key, data, index);
@@ -1726,6 +2053,8 @@ static void do_crease_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnod
float brush_alpha;
int n;
+ SculptProjectVector spvc;
+
/* offset with as much as possible factored in already */
mul_v3_v3fl(offset, ss->cache->sculpt_normal_symm, ss->cache->radius);
mul_v3_v3(offset, ss->cache->scale);
@@ -1742,6 +2071,10 @@ static void do_crease_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnod
if (brush->sculpt_tool == SCULPT_TOOL_BLOB) flippedbstrength *= -1.0f;
+ /* Use surface normal for 'spvc', so the vertices are pinched towards a line instead of a single point.
+ * Without this we get a 'flat' surface surrounding the pinch */
+ sculpt_project_v3_cache_init(&spvc, ss->cache->sculpt_normal_symm);
+
/* threaded loop over nodes */
#pragma omp parallel for schedule(guided) if ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_OMP_LIMIT)
for (n = 0; n < totnode; n++) {
@@ -1766,6 +2099,8 @@ static void do_crease_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnod
sub_v3_v3v3(val1, test.location, vd.co);
mul_v3_fl(val1, fade * flippedbstrength);
+ sculpt_project_v3(&spvc, val1, val1);
+
/* then we draw */
mul_v3_v3fl(val2, offset, fade);
@@ -2159,266 +2494,38 @@ static void do_inflate_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totno
}
}
-static void calc_flatten_center(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode, float fc[3])
-{
- SculptSession *ss = ob->sculpt;
- int n;
-
- int count = 0;
- int count_flip = 0;
-
- float fc_flip[3] = {0.0, 0.0, 0.0};
-
- (void)sd; /* unused w/o openmp */
-
- zero_v3(fc);
-
-#pragma omp parallel for schedule(guided) if ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_OMP_LIMIT)
- for (n = 0; n < totnode; n++) {
- PBVHVertexIter vd;
- SculptBrushTest test;
- SculptUndoNode *unode;
- float private_fc[3] = {0.0f, 0.0f, 0.0f};
- float private_fc_flip[3] = {0.0f, 0.0f, 0.0f};
- int private_count = 0;
- int private_count_flip = 0;
-
- unode = sculpt_undo_push_node(ob, nodes[n], SCULPT_UNDO_COORDS);
- sculpt_brush_test_init(ss, &test);
-
- if (ss->cache->original && unode->co) {
- BKE_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE)
- {
- if (sculpt_brush_test_fast(&test, unode->co[vd.i])) {
- float fno[3];
-
- normal_short_to_float_v3(fno, unode->no[vd.i]);
- if (dot_v3v3(ss->cache->view_normal, fno) > 0) {
- add_v3_v3(private_fc, unode->co[vd.i]);
- private_count++;
- }
- else {
- add_v3_v3(private_fc_flip, unode->co[vd.i]);
- private_count_flip++;
- }
- }
- }
- BKE_pbvh_vertex_iter_end;
- }
- else {
- BKE_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE)
- {
- if (sculpt_brush_test_fast(&test, vd.co)) {
- /* for area normal */
- if (vd.no) {
- float fno[3];
-
- normal_short_to_float_v3(fno, vd.no);
-
- if (dot_v3v3(ss->cache->view_normal, fno) > 0) {
- add_v3_v3(private_fc, vd.co);
- private_count++;
- }
- else {
- add_v3_v3(private_fc_flip, vd.co);
- private_count_flip++;
- }
- }
- else {
- if (dot_v3v3(ss->cache->view_normal, vd.fno) > 0) {
- add_v3_v3(private_fc, vd.co);
- private_count++;
- }
- else {
- add_v3_v3(private_fc_flip, vd.co);
- private_count_flip++;
- }
- }
- }
- }
- BKE_pbvh_vertex_iter_end;
- }
-
-#pragma omp critical
- {
- add_v3_v3(fc, private_fc);
- add_v3_v3(fc_flip, private_fc_flip);
- count += private_count;
- count_flip += private_count_flip;
- }
- }
- if (count != 0)
- mul_v3_fl(fc, 1.0f / count);
- else if (count_flip != 0)
- mul_v3_v3fl(fc, fc_flip, 1.0f / count_flip);
- else
- zero_v3(fc);
-}
-
-/* this calculates flatten center and area normal together,
- * amortizing the memory bandwidth and loop overhead to calculate both at the same time */
-static void calc_area_normal_and_flatten_center(Sculpt *sd, Object *ob,
- PBVHNode **nodes, int totnode,
- float an[3], float fc[3])
-{
- SculptSession *ss = ob->sculpt;
- int n;
-
- /* for area normal */
- float out_flip[3] = {0.0f, 0.0f, 0.0f};
- float fc_flip[3] = {0.0f, 0.0f, 0.0f};
-
- /* for flatten center */
- int count = 0;
- int count_flipped = 0;
-
- (void)sd; /* unused w/o openmp */
-
- /* for area normal */
- zero_v3(an);
-
- /* for flatten center */
- zero_v3(fc);
-
-#pragma omp parallel for schedule(guided) if ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_OMP_LIMIT)
- for (n = 0; n < totnode; n++) {
- PBVHVertexIter vd;
- SculptBrushTest test;
- SculptUndoNode *unode;
- float private_an[3] = {0.0f, 0.0f, 0.0f};
- float private_out_flip[3] = {0.0f, 0.0f, 0.0f};
- float private_fc[3] = {0.0f, 0.0f, 0.0f};
- float private_fc_flip[3] = {0.0f, 0.0f, 0.0f};
- int private_count = 0;
- int private_count_flip = 0;
-
- unode = sculpt_undo_push_node(ob, nodes[n], SCULPT_UNDO_COORDS);
- sculpt_brush_test_init(ss, &test);
-
- if (ss->cache->original && unode->co) {
- BKE_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE)
- {
- if (sculpt_brush_test_fast(&test, unode->co[vd.i])) {
- /* for area normal */
- float fno[3];
-
- normal_short_to_float_v3(fno, unode->no[vd.i]);
-
- if (dot_v3v3(ss->cache->view_normal, fno) > 0) {
- add_v3_v3(private_an, fno);
- add_v3_v3(private_fc, unode->co[vd.i]);
- private_count++;
- }
- else {
- add_v3_v3(private_out_flip, fno);
- add_v3_v3(private_fc_flip, unode->co[vd.i]);
- private_count_flip++;
- }
- }
- }
- BKE_pbvh_vertex_iter_end;
- }
- else {
- BKE_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE)
- {
- if (sculpt_brush_test_fast(&test, vd.co)) {
- /* for area normal */
- if (vd.no) {
- float fno[3];
-
- normal_short_to_float_v3(fno, vd.no);
-
- if (dot_v3v3(ss->cache->view_normal, fno) > 0) {
- add_v3_v3(private_an, fno);
- add_v3_v3(private_fc, vd.co);
- private_count++;
- }
- else {
- add_v3_v3(private_out_flip, fno);
- add_v3_v3(private_fc_flip, vd.co);
- private_count_flip++;
- }
- }
- else {
- if (dot_v3v3(ss->cache->view_normal, vd.fno) > 0) {
- add_v3_v3(private_an, vd.fno);
- add_v3_v3(private_fc, vd.co);
- private_count++;
- }
- else {
- add_v3_v3(private_out_flip, vd.fno);
- add_v3_v3(private_fc_flip, vd.co);
- private_count_flip++;
- }
- }
- }
- }
- BKE_pbvh_vertex_iter_end;
- }
-
-#pragma omp critical
- {
- /* for area normal */
- add_v3_v3(an, private_an);
- add_v3_v3(out_flip, private_out_flip);
-
- /* for flatten center */
- add_v3_v3(fc, private_fc);
- add_v3_v3(fc_flip, private_fc_flip);
- count += private_count;
- count_flipped += private_count_flip;
- }
- }
-
- /* for area normal */
- if (is_zero_v3(an))
- copy_v3_v3(an, out_flip);
-
- normalize_v3(an);
-
- /* for flatten center */
- if (count != 0)
- mul_v3_fl(fc, 1.0f / count);
- else if (count_flipped != 0)
- mul_v3_v3fl(fc, fc_flip, 1.0f / count_flipped);
- else
- zero_v3(fc);
-}
-
-static void calc_sculpt_plane(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode, float an[3], float fc[3])
+static void calc_sculpt_plane(
+ Sculpt *sd, Object *ob,
+ PBVHNode **nodes, int totnode,
+ float r_area_no[3], float r_area_co[3])
{
SculptSession *ss = ob->sculpt;
Brush *brush = BKE_paint_brush(&sd->paint);
if (ss->cache->mirror_symmetry_pass == 0 &&
ss->cache->radial_symmetry_pass == 0 &&
+ ss->cache->tile_pass == 0 &&
(ss->cache->first_time || !(brush->flag & BRUSH_ORIGINAL_NORMAL)))
{
switch (brush->sculpt_plane) {
case SCULPT_DISP_DIR_VIEW:
- copy_v3_v3(an, ss->cache->true_view_normal);
+ copy_v3_v3(r_area_no, ss->cache->true_view_normal);
break;
case SCULPT_DISP_DIR_X:
- an[1] = 0.0;
- an[2] = 0.0;
- an[0] = 1.0;
+ ARRAY_SET_ITEMS(r_area_no, 1, 0, 0);
break;
case SCULPT_DISP_DIR_Y:
- an[0] = 0.0;
- an[2] = 0.0;
- an[1] = 1.0;
+ ARRAY_SET_ITEMS(r_area_no, 0, 1, 0);
break;
case SCULPT_DISP_DIR_Z:
- an[0] = 0.0;
- an[1] = 0.0;
- an[2] = 1.0;
+ ARRAY_SET_ITEMS(r_area_no, 0, 0, 1);
break;
case SCULPT_DISP_DIR_AREA:
- calc_area_normal_and_flatten_center(sd, ob, nodes, totnode, an, fc);
+ calc_area_normal_and_center(sd, ob, nodes, totnode, r_area_no, r_area_co);
break;
default:
@@ -2428,50 +2535,57 @@ static void calc_sculpt_plane(Sculpt *sd, Object *ob, PBVHNode **nodes, int totn
/* for flatten center */
/* flatten center has not been calculated yet if we are not using the area normal */
if (brush->sculpt_plane != SCULPT_DISP_DIR_AREA)
- calc_flatten_center(sd, ob, nodes, totnode, fc);
+ calc_area_center(sd, ob, nodes, totnode, r_area_co);
/* for area normal */
- copy_v3_v3(ss->cache->sculpt_normal, an);
+ copy_v3_v3(ss->cache->sculpt_normal, r_area_no);
/* for flatten center */
- copy_v3_v3(ss->cache->last_center, fc);
+ copy_v3_v3(ss->cache->last_center, r_area_co);
}
else {
/* for area normal */
- copy_v3_v3(an, ss->cache->sculpt_normal);
+ copy_v3_v3(r_area_no, ss->cache->sculpt_normal);
/* for flatten center */
- copy_v3_v3(fc, ss->cache->last_center);
+ copy_v3_v3(r_area_co, ss->cache->last_center);
/* for area normal */
- flip_v3(an, ss->cache->mirror_symmetry_pass);
+ flip_v3(r_area_no, ss->cache->mirror_symmetry_pass);
/* for flatten center */
- flip_v3(fc, ss->cache->mirror_symmetry_pass);
+ flip_v3(r_area_co, ss->cache->mirror_symmetry_pass);
/* for area normal */
- mul_m4_v3(ss->cache->symm_rot_mat, an);
+ mul_m4_v3(ss->cache->symm_rot_mat, r_area_no);
/* for flatten center */
- mul_m4_v3(ss->cache->symm_rot_mat, fc);
+ mul_m4_v3(ss->cache->symm_rot_mat, r_area_co);
+
+ /* shift the plane for the current tile */
+ add_v3_v3(r_area_co, ss->cache->plane_offset);
}
}
/* Projects a point onto a plane along the plane's normal */
-static void point_plane_project(float intr[3], float co[3], float plane_normal[3], float plane_center[3])
+static void point_plane_project(
+ float intr[3],
+ const float co[3], const float plane_normal[3], const float plane_center[3])
{
sub_v3_v3v3(intr, co, plane_center);
mul_v3_v3fl(intr, plane_normal, dot_v3v3(plane_normal, intr));
sub_v3_v3v3(intr, co, intr);
}
-static int plane_trim(StrokeCache *cache, Brush *brush, float val[3])
+static int plane_trim(const StrokeCache *cache, const Brush *brush, const float val[3])
{
return (!(brush->flag & BRUSH_PLANE_TRIM) ||
((dot_v3v3(val, val) <= cache->radius_squared * cache->plane_trim_squared)));
}
-static int plane_point_side_flip(float co[3], float plane_normal[3], float plane_center[3], int flip)
+static bool plane_point_side_flip(
+ const float co[3], const float plane_normal[3], const float plane_center[3],
+ const bool flip)
{
float delta[3];
float d;
@@ -2484,7 +2598,7 @@ static int plane_point_side_flip(float co[3], float plane_normal[3], float plane
return d <= 0.0f;
}
-static int plane_point_side(float co[3], float plane_normal[3], float plane_center[3])
+static int plane_point_side(const float co[3], const float plane_normal[3], const float plane_center[3])
{
float delta[3];
@@ -2513,8 +2627,8 @@ static void do_flatten_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totno
float bstrength = ss->cache->bstrength;
const float radius = ss->cache->radius;
- float an[3];
- float fc[3];
+ float area_no[3];
+ float area_co[3];
float offset = get_offset(sd, ss);
@@ -2524,13 +2638,13 @@ static void do_flatten_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totno
float temp[3];
- calc_sculpt_plane(sd, ob, nodes, totnode, an, fc);
+ calc_sculpt_plane(sd, ob, nodes, totnode, area_no, area_co);
displace = radius * offset;
- mul_v3_v3v3(temp, an, ss->cache->scale);
+ mul_v3_v3v3(temp, area_no, ss->cache->scale);
mul_v3_fl(temp, displace);
- add_v3_v3(fc, temp);
+ add_v3_v3(area_co, temp);
#pragma omp parallel for schedule(guided) if ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_OMP_LIMIT)
for (n = 0; n < totnode; n++) {
@@ -2548,7 +2662,7 @@ static void do_flatten_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totno
float intr[3];
float val[3];
- point_plane_project(intr, vd.co, an, fc);
+ point_plane_project(intr, vd.co, area_no, area_co);
sub_v3_v3v3(val, intr, vd.co);
@@ -2578,16 +2692,16 @@ static void do_clay_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
float displace;
- float an[3];
- float fc[3];
+ float area_no[3];
+ float area_co[3];
int n;
float temp[3];
- int flip;
+ bool flip;
- calc_sculpt_plane(sd, ob, nodes, totnode, an, fc);
+ calc_sculpt_plane(sd, ob, nodes, totnode, area_no, area_co);
flip = bstrength < 0;
@@ -2598,11 +2712,11 @@ static void do_clay_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
displace = radius * (0.25f + offset);
- mul_v3_v3v3(temp, an, ss->cache->scale);
+ mul_v3_v3v3(temp, area_no, ss->cache->scale);
mul_v3_fl(temp, displace);
- add_v3_v3(fc, temp);
+ add_v3_v3(area_co, temp);
- /* add_v3_v3v3(p, ss->cache->location, an); */
+ /* add_v3_v3v3(p, ss->cache->location, area_no); */
#pragma omp parallel for schedule(guided) if ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_OMP_LIMIT)
for (n = 0; n < totnode; n++) {
@@ -2617,15 +2731,17 @@ static void do_clay_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
BKE_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE)
{
if (sculpt_brush_test_sq(&test, vd.co)) {
- if (plane_point_side_flip(vd.co, an, fc, flip)) {
+ if (plane_point_side_flip(vd.co, area_no, area_co, flip)) {
float intr[3];
float val[3];
- point_plane_project(intr, vd.co, an, fc);
+ point_plane_project(intr, vd.co, area_no, area_co);
sub_v3_v3v3(val, intr, vd.co);
if (plane_trim(ss->cache, brush, val)) {
+ /* note, the normal from the vertices is ignored,
+ * causes glitch with planes, see: T44390 */
const float fade = bstrength * tex_strength(ss, brush, vd.co, sqrtf(test.dist),
vd.no, vd.fno, vd.mask ? *vd.mask : 0.0f);
@@ -2652,9 +2768,9 @@ static void do_clay_strips_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int t
float displace;
- float sn[3];
- float an[3];
- float fc[3];
+ float area_no_sp[3]; /* the sculpt-plane normal (whatever its set to) */
+ float area_no[3]; /* geometry normal */
+ float area_co[3];
int n;
@@ -2663,14 +2779,14 @@ static void do_clay_strips_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int t
float scale[4][4];
float tmat[4][4];
- int flip;
+ bool flip;
- calc_sculpt_plane(sd, ob, nodes, totnode, sn, fc);
+ calc_sculpt_plane(sd, ob, nodes, totnode, area_no_sp, area_co);
if (brush->sculpt_plane != SCULPT_DISP_DIR_AREA || (brush->flag & BRUSH_ORIGINAL_NORMAL))
- calc_area_normal(sd, ob, an, nodes, totnode);
+ calc_area_normal(sd, ob, nodes, totnode, area_no);
else
- copy_v3_v3(an, sn);
+ copy_v3_v3(area_no, area_no_sp);
/* delay the first daub because grab delta is not setup */
if (ss->cache->first_time)
@@ -2685,16 +2801,16 @@ static void do_clay_strips_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int t
displace = radius * (0.25f + offset);
- mul_v3_v3v3(temp, sn, ss->cache->scale);
+ mul_v3_v3v3(temp, area_no_sp, ss->cache->scale);
mul_v3_fl(temp, displace);
- add_v3_v3(fc, temp);
+ add_v3_v3(area_co, temp);
/* init mat */
- cross_v3_v3v3(mat[0], an, ss->cache->grab_delta_symmetry);
+ cross_v3_v3v3(mat[0], area_no, ss->cache->grab_delta_symmetry);
mat[0][3] = 0;
- cross_v3_v3v3(mat[1], an, mat[0]);
+ cross_v3_v3v3(mat[1], area_no, mat[0]);
mat[1][3] = 0;
- copy_v3_v3(mat[2], an);
+ copy_v3_v3(mat[2], area_no);
mat[2][3] = 0;
copy_v3_v3(mat[3], ss->cache->location);
mat[3][3] = 1;
@@ -2718,15 +2834,17 @@ static void do_clay_strips_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int t
BKE_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE)
{
if (sculpt_brush_test_cube(&test, vd.co, mat)) {
- if (plane_point_side_flip(vd.co, sn, fc, flip)) {
+ if (plane_point_side_flip(vd.co, area_no_sp, area_co, flip)) {
float intr[3];
float val[3];
- point_plane_project(intr, vd.co, sn, fc);
+ point_plane_project(intr, vd.co, area_no_sp, area_co);
sub_v3_v3v3(val, intr, vd.co);
if (plane_trim(ss->cache, brush, val)) {
+ /* note, the normal from the vertices is ignored,
+ * causes glitch with planes, see: T44390 */
const float fade = bstrength * tex_strength(ss, brush, vd.co,
ss->cache->radius * test.dist,
vd.no, vd.fno, vd.mask ? *vd.mask : 0.0f);
@@ -2751,8 +2869,8 @@ static void do_fill_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
float bstrength = ss->cache->bstrength;
const float radius = ss->cache->radius;
- float an[3];
- float fc[3];
+ float area_no[3];
+ float area_co[3];
float offset = get_offset(sd, ss);
float displace;
@@ -2761,13 +2879,13 @@ static void do_fill_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
float temp[3];
- calc_sculpt_plane(sd, ob, nodes, totnode, an, fc);
+ calc_sculpt_plane(sd, ob, nodes, totnode, area_no, area_co);
displace = radius * offset;
- mul_v3_v3v3(temp, an, ss->cache->scale);
+ mul_v3_v3v3(temp, area_no, ss->cache->scale);
mul_v3_fl(temp, displace);
- add_v3_v3(fc, temp);
+ add_v3_v3(area_co, temp);
#pragma omp parallel for schedule(guided) if ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_OMP_LIMIT)
for (n = 0; n < totnode; n++) {
@@ -2782,11 +2900,11 @@ static void do_fill_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
BKE_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE)
{
if (sculpt_brush_test_sq(&test, vd.co)) {
- if (plane_point_side(vd.co, an, fc)) {
+ if (plane_point_side(vd.co, area_no, area_co)) {
float intr[3];
float val[3];
- point_plane_project(intr, vd.co, an, fc);
+ point_plane_project(intr, vd.co, area_no, area_co);
sub_v3_v3v3(val, intr, vd.co);
@@ -2815,8 +2933,8 @@ static void do_scrape_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnod
float bstrength = ss->cache->bstrength;
const float radius = ss->cache->radius;
- float an[3];
- float fc[3];
+ float area_no[3];
+ float area_co[3];
float offset = get_offset(sd, ss);
float displace;
@@ -2825,13 +2943,13 @@ static void do_scrape_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnod
float temp[3];
- calc_sculpt_plane(sd, ob, nodes, totnode, an, fc);
+ calc_sculpt_plane(sd, ob, nodes, totnode, area_no, area_co);
displace = -radius * offset;
- mul_v3_v3v3(temp, an, ss->cache->scale);
+ mul_v3_v3v3(temp, area_no, ss->cache->scale);
mul_v3_fl(temp, displace);
- add_v3_v3(fc, temp);
+ add_v3_v3(area_co, temp);
#pragma omp parallel for schedule(guided) if ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_OMP_LIMIT)
for (n = 0; n < totnode; n++) {
@@ -2846,11 +2964,11 @@ static void do_scrape_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnod
BKE_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE)
{
if (sculpt_brush_test_sq(&test, vd.co)) {
- if (!plane_point_side(vd.co, an, fc)) {
+ if (!plane_point_side(vd.co, area_no, area_co)) {
float intr[3];
float val[3];
- point_plane_project(intr, vd.co, an, fc);
+ point_plane_project(intr, vd.co, area_no, area_co);
sub_v3_v3v3(val, intr, vd.co);
@@ -2876,7 +2994,7 @@ static void do_gravity(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode, fl
SculptSession *ss = ob->sculpt;
Brush *brush = BKE_paint_brush(&sd->paint);
- float offset[3]/*, an[3]*/;
+ float offset[3]/*, area_no[3]*/;
int n;
float gravity_vector[3];
@@ -2917,19 +3035,13 @@ void sculpt_vertcos_to_key(Object *ob, KeyBlock *kb, float (*vertCos)[3])
{
Mesh *me = (Mesh *)ob->data;
float (*ofs)[3] = NULL;
- int a, is_basis = 0;
+ int a;
+ const int kb_act_idx = ob->shapenr - 1;
KeyBlock *currkey;
/* for relative keys editing of base should update other keys */
- if (me->key->type == KEY_RELATIVE)
- for (currkey = me->key->block.first; currkey; currkey = currkey->next)
- if (ob->shapenr - 1 == currkey->relative) {
- is_basis = 1;
- break;
- }
-
- if (is_basis) {
- ofs = BKE_key_convert_to_vertcos(ob, kb);
+ if (BKE_keyblock_is_basis(me->key, kb_act_idx)) {
+ ofs = BKE_keyblock_convert_to_vertcos(ob, kb);
/* calculate key coord offsets (from previous location) */
for (a = 0; a < me->totvert; a++) {
@@ -2937,14 +3049,10 @@ void sculpt_vertcos_to_key(Object *ob, KeyBlock *kb, float (*vertCos)[3])
}
/* apply offsets on other keys */
- currkey = me->key->block.first;
- while (currkey) {
- int apply_offset = ((currkey != kb) && (ob->shapenr - 1 == currkey->relative));
-
- if (apply_offset)
- BKE_key_convert_from_offset(ob, currkey, ofs);
-
- currkey = currkey->next;
+ for (currkey = me->key->block.first; currkey; currkey = currkey->next) {
+ if ((currkey != kb) && (currkey->relative == kb_act_idx)) {
+ BKE_keyblock_update_from_offset(ob, currkey, ofs);
+ }
}
MEM_freeN(ofs);
@@ -2960,14 +3068,14 @@ void sculpt_vertcos_to_key(Object *ob, KeyBlock *kb, float (*vertCos)[3])
BKE_mesh_calc_normals(me);
}
- /* apply new coords on active key block */
- BKE_key_convert_from_vertcos(ob, kb, vertCos);
+ /* apply new coords on active key block, no need to re-allocate kb->data here! */
+ BKE_keyblock_update_from_vertcos(ob, kb, vertCos);
}
/* Note: we do the topology update before any brush actions to avoid
* issues with the proxies. The size of the proxy can't change, so
* topology must be updated first. */
-static void sculpt_topology_update(Sculpt *sd, Object *ob, Brush *brush)
+static void sculpt_topology_update(Sculpt *sd, Object *ob, Brush *brush, UnifiedPaintSettings *UNUSED(ups))
{
SculptSession *ss = ob->sculpt;
SculptSearchSphereData data;
@@ -2983,11 +3091,7 @@ static void sculpt_topology_update(Sculpt *sd, Object *ob, Brush *brush)
radius = ss->cache->radius * 1.25f;
data.radius_squared = radius * radius;
- data.original = ELEM(brush->sculpt_tool,
- SCULPT_TOOL_GRAB,
- SCULPT_TOOL_ROTATE,
- SCULPT_TOOL_THUMB,
- SCULPT_TOOL_LAYER) ? true : ss->cache->original;
+ data.original = sculpt_tool_needs_original(brush->sculpt_tool) ? true : ss->cache->original;
BKE_pbvh_search_gather(ss->pbvh, sculpt_search_sphere_cb, &data, &nodes, &totnode);
@@ -3018,9 +3122,11 @@ static void sculpt_topology_update(Sculpt *sd, Object *ob, Brush *brush)
}
if (BKE_pbvh_type(ss->pbvh) == PBVH_BMESH) {
- BKE_pbvh_bmesh_update_topology(ss->pbvh, mode,
- ss->cache->location,
- ss->cache->radius);
+ BKE_pbvh_bmesh_update_topology(
+ ss->pbvh, mode,
+ ss->cache->location,
+ (brush->flag & BRUSH_FRONTFACE) ? ss->cache->view_normal : NULL,
+ ss->cache->radius);
}
MEM_freeN(nodes);
@@ -3028,13 +3134,10 @@ static void sculpt_topology_update(Sculpt *sd, Object *ob, Brush *brush)
/* update average stroke position */
copy_v3_v3(location, ss->cache->true_location);
mul_m4_v3(ob->obmat, location);
-
- add_v3_v3(ob->sculpt->average_stroke_accum, location);
- ob->sculpt->average_stroke_counter++;
}
}
-static void do_brush_action(Sculpt *sd, Object *ob, Brush *brush)
+static void do_brush_action(Sculpt *sd, Object *ob, Brush *brush, UnifiedPaintSettings *ups)
{
SculptSession *ss = ob->sculpt;
SculptSearchSphereData data;
@@ -3045,11 +3148,7 @@ static void do_brush_action(Sculpt *sd, Object *ob, Brush *brush)
data.ss = ss;
data.sd = sd;
data.radius_squared = ss->cache->radius_squared;
- data.original = ELEM(brush->sculpt_tool,
- SCULPT_TOOL_GRAB,
- SCULPT_TOOL_ROTATE,
- SCULPT_TOOL_THUMB,
- SCULPT_TOOL_LAYER) ? true : ss->cache->original;
+ data.original = sculpt_tool_needs_original(brush->sculpt_tool) ? true : ss->cache->original;
BKE_pbvh_search_gather(ss->pbvh, sculpt_search_sphere_cb, &data, &nodes, &totnode);
/* Only act if some verts are inside the brush area */
@@ -3064,7 +3163,7 @@ static void do_brush_action(Sculpt *sd, Object *ob, Brush *brush)
BKE_pbvh_node_mark_update(nodes[n]);
}
- if (brush_needs_sculpt_normal(brush))
+ if (sculpt_brush_needs_normal(brush))
update_sculpt_normal(sd, ob, nodes, totnode);
if (brush->mtex.brush_map_mode == MTEX_MAP_MODE_AREA)
@@ -3148,8 +3247,10 @@ static void do_brush_action(Sculpt *sd, Object *ob, Brush *brush)
copy_v3_v3(location, ss->cache->true_location);
mul_m4_v3(ob->obmat, location);
- add_v3_v3(ob->sculpt->average_stroke_accum, location);
- ob->sculpt->average_stroke_counter++;
+ add_v3_v3(ups->average_stroke_accum, location);
+ ups->average_stroke_counter++;
+ /* update last stroke position */
+ ups->last_stroke_valid = true;
}
}
@@ -3182,8 +3283,8 @@ static void sculpt_combine_proxies(Sculpt *sd, Object *ob)
BKE_pbvh_gather_proxies(ss->pbvh, &nodes, &totnode);
/* first line is tools that don't support proxies */
- if (!ELEM(brush->sculpt_tool, SCULPT_TOOL_SMOOTH, SCULPT_TOOL_LAYER) ||
- ss->cache->supports_gravity)
+ if (ss->cache->supports_gravity ||
+ (sculpt_tool_is_proxy_used(brush->sculpt_tool) == false))
{
/* these brushes start from original coordinates */
const bool use_orco = ELEM(brush->sculpt_tool, SCULPT_TOOL_GRAB,
@@ -3261,7 +3362,7 @@ static void sculpt_flush_stroke_deform(Sculpt *sd, Object *ob)
SculptSession *ss = ob->sculpt;
Brush *brush = BKE_paint_brush(&sd->paint);
- if (ELEM(brush->sculpt_tool, SCULPT_TOOL_SMOOTH, SCULPT_TOOL_LAYER)) {
+ if (sculpt_tool_is_proxy_used(brush->sculpt_tool)) {
/* this brushes aren't using proxies, so sculpt_combine_proxies() wouldn't
* propagate needed deformation to original base */
@@ -3343,6 +3444,7 @@ static void calc_brushdata_symm(Sculpt *sd, StrokeCache *cache, const char symm,
unit_m4(cache->symm_rot_mat);
unit_m4(cache->symm_rot_mat_inv);
+ zero_v3(cache->plane_offset);
if (axis) { /* expects XYZ */
rotate_m4(cache->symm_rot_mat, axis, angle);
@@ -3358,9 +3460,61 @@ static void calc_brushdata_symm(Sculpt *sd, StrokeCache *cache, const char symm,
}
}
-typedef void (*BrushActionFunc)(Sculpt *sd, Object *ob, Brush *brush);
+typedef void (*BrushActionFunc)(Sculpt *sd, Object *ob, Brush *brush, UnifiedPaintSettings *ups);
+
+static void do_tiled(Sculpt *sd, Object *ob, Brush *brush, UnifiedPaintSettings *ups, BrushActionFunc action)
+{
+ SculptSession *ss = ob->sculpt;
+ StrokeCache *cache = ss->cache;
+ const float radius = cache->radius;
+ const float *bbMin = ob->bb->vec[0];
+ const float *bbMax = ob->bb->vec[6];
+ const float *step = sd->paint.tile_offset;
+ int dim;
+
+ /* These are integer locations, for real location: multiply with step and add orgLoc. So 0,0,0 is at orgLoc. */
+ int start[3];
+ int end[3];
+ int cur[3];
+
+ float orgLoc[3]; /* position of the "prototype" stroke for tiling */
+ copy_v3_v3(orgLoc, cache->location);
+
+ for (dim = 0; dim < 3; ++dim) {
+ if ((sd->paint.symmetry_flags & (PAINT_TILE_X << dim)) && step[dim] > 0) {
+ start[dim] = (bbMin[dim] - orgLoc[dim] - radius) / step[dim];
+ end[dim] = (bbMax[dim] - orgLoc[dim] + radius) / step[dim];
+ }
+ else
+ start[dim] = end[dim] = 0;
+ }
-static void do_radial_symmetry(Sculpt *sd, Object *ob, Brush *brush,
+ /* first do the "untiled" position to initialize the stroke for this location */
+ cache->tile_pass = 0;
+ action(sd, ob, brush, ups);
+
+ /* now do it for all the tiles */
+ copy_v3_v3_int(cur, start);
+ for (cur[0] = start[0]; cur[0] <= end[0]; ++cur[0]) {
+ for (cur[1] = start[1]; cur[1] <= end[1]; ++cur[1]) {
+ for (cur[2] = start[2]; cur[2] <= end[2]; ++cur[2]) {
+ if (!cur[0] && !cur[1] && !cur[2])
+ continue; /* skip tile at orgLoc, this was already handled before all others */
+
+ ++cache->tile_pass;
+
+ for (dim = 0; dim < 3; ++dim) {
+ cache->location[dim] = cur[dim] * step[dim] + orgLoc[dim];
+ cache->plane_offset[dim] = cur[dim] * step[dim];
+ }
+ action(sd, ob, brush, ups);
+ }
+ }
+ }
+}
+
+
+static void do_radial_symmetry(Sculpt *sd, Object *ob, Brush *brush, UnifiedPaintSettings *ups,
BrushActionFunc action,
const char symm, const int axis,
const float feather)
@@ -3372,7 +3526,7 @@ static void do_radial_symmetry(Sculpt *sd, Object *ob, Brush *brush,
const float angle = 2 * M_PI * i / sd->radial_symm[axis - 'X'];
ss->cache->radial_symmetry_pass = i;
calc_brushdata_symm(sd, ss->cache, symm, axis, angle, feather);
- action(sd, ob, brush);
+ do_tiled(sd, ob, brush, ups, action);
}
}
@@ -3410,11 +3564,11 @@ static void do_symmetrical_brush_actions(Sculpt *sd, Object *ob,
cache->radial_symmetry_pass = 0;
calc_brushdata_symm(sd, cache, i, 0, 0, feather);
- action(sd, ob, brush);
+ do_tiled(sd, ob, brush, ups, action);
- do_radial_symmetry(sd, ob, brush, action, i, 'X', feather);
- do_radial_symmetry(sd, ob, brush, action, i, 'Y', feather);
- do_radial_symmetry(sd, ob, brush, action, i, 'Z', feather);
+ do_radial_symmetry(sd, ob, brush, ups, action, i, 'X', feather);
+ do_radial_symmetry(sd, ob, brush, ups, action, i, 'Y', feather);
+ do_radial_symmetry(sd, ob, brush, ups, action, i, 'Z', feather);
}
}
}
@@ -3522,8 +3676,6 @@ static const char *sculpt_tool_name(Sculpt *sd)
static void sculpt_cache_free(StrokeCache *cache)
{
- if (cache->face_norms)
- MEM_freeN(cache->face_norms);
if (cache->dial)
MEM_freeN(cache->dial);
MEM_freeN(cache);
@@ -3595,7 +3747,7 @@ static void sculpt_omp_start(Sculpt *sd, SculptSession *ss)
if (ss->multires) {
int i, gridsize, array_mem_size;
BKE_pbvh_node_get_grids(ss->pbvh, NULL, NULL, NULL, NULL,
- &gridsize, NULL, NULL);
+ &gridsize, NULL);
array_mem_size = cache->num_threads * sizeof(void *);
@@ -3783,21 +3935,10 @@ static void sculpt_update_cache_invariants(bContext *C, Sculpt *sd, SculptSessio
/* Make copies of the mesh vertex locations and normals for some tools */
if (brush->flag & BRUSH_ANCHORED) {
- if (ss->face_normals) {
- cache->face_norms = MEM_mallocN(sizeof(float) * 3 * ss->totpoly, "Sculpt face norms");
- for (i = 0; i < ss->totpoly; ++i) {
- copy_v3_v3(cache->face_norms[i], ss->face_normals[i]);
- }
- }
-
cache->original = 1;
}
- if (ELEM(brush->sculpt_tool,
- SCULPT_TOOL_DRAW, SCULPT_TOOL_CREASE, SCULPT_TOOL_BLOB,
- SCULPT_TOOL_LAYER, SCULPT_TOOL_INFLATE, SCULPT_TOOL_CLAY,
- SCULPT_TOOL_CLAY_STRIPS, SCULPT_TOOL_ROTATE, SCULPT_TOOL_FLATTEN))
- {
+ if (SCULPT_TOOL_HAS_ACCUMULATE(brush->sculpt_tool)) {
if (!(brush->flag & BRUSH_ACCUMULATE)) {
cache->original = 1;
}
@@ -3921,7 +4062,7 @@ static void sculpt_update_cache_variants(bContext *C, Sculpt *sd, Object *ob,
* brush coord/pressure/etc.
* It's more an events design issue, which doesn't split coordinate/pressure/angle
* changing events. We should avoid this after events system re-design */
- if (paint_supports_dynamic_size(brush, PAINT_SCULPT) || cache->first_time) {
+ if (paint_supports_dynamic_size(brush, ePaintSculpt) || cache->first_time) {
cache->pressure = RNA_float_get(ptr, "pressure");
}
@@ -3938,7 +4079,7 @@ static void sculpt_update_cache_variants(bContext *C, Sculpt *sd, Object *ob,
}
}
- if (BKE_brush_use_size_pressure(scene, brush) && paint_supports_dynamic_size(brush, PAINT_SCULPT)) {
+ if (BKE_brush_use_size_pressure(scene, brush) && paint_supports_dynamic_size(brush, ePaintSculpt)) {
cache->radius = cache->initial_radius * cache->pressure;
}
else {
@@ -4006,14 +4147,14 @@ static void sculpt_stroke_modifiers_check(const bContext *C, Object *ob)
typedef struct {
SculptSession *ss;
const float *ray_start, *ray_normal;
- int hit;
+ bool hit;
float dist;
- int original;
+ bool original;
} SculptRaycastData;
typedef struct {
const float *ray_start, *ray_normal;
- int hit;
+ bool hit;
float dist;
float detail;
} SculptDetailRaycastData;
@@ -4051,7 +4192,7 @@ static void sculpt_raycast_detail_cb(PBVHNode *node, void *data_v, float *tmin)
if (BKE_pbvh_node_get_tmin(node) < *tmin) {
SculptDetailRaycastData *srd = data_v;
if (BKE_pbvh_bmesh_node_raycast_detail(node, srd->ray_start, srd->ray_normal,
- &srd->detail, &srd->dist))
+ &srd->dist, &srd->detail))
{
srd->hit = 1;
*tmin = srd->dist;
@@ -4076,7 +4217,10 @@ static float sculpt_raycast_init(ViewContext *vc, const float mouse[2], float ra
sub_v3_v3v3(ray_normal, ray_end, ray_start);
dist = normalize_v3(ray_normal);
- if (!rv3d->is_persp) {
+ if ((rv3d->is_persp == false) &&
+ /* if the ray is clipped, don't adjust its start/end */
+ ((rv3d->rflag & RV3D_CLIPPING) == 0))
+ {
BKE_pbvh_raycast_project_ray_root(ob->sculpt->pbvh, original, ray_start, ray_end, ray_normal);
/* recalculate the normal */
@@ -4145,7 +4289,7 @@ static void sculpt_brush_init_tex(const Scene *scene, Sculpt *sd, SculptSession
sculpt_update_tex(scene, sd, ss);
}
-static int sculpt_brush_stroke_init(bContext *C, wmOperator *op)
+static bool sculpt_brush_stroke_init(bContext *C, wmOperator *op)
{
Scene *scene = CTX_data_scene(C);
Object *ob = CTX_data_active_object(C);
@@ -4166,9 +4310,6 @@ static int sculpt_brush_stroke_init(bContext *C, wmOperator *op)
is_smooth = sculpt_any_smooth_mode(brush, NULL, mode);
BKE_sculpt_update_mesh_elements(scene, sd, ob, is_smooth, need_mask);
- zero_v3(ob->sculpt->average_stroke_accum);
- ob->sculpt->average_stroke_counter = 0;
-
return 1;
}
@@ -4290,17 +4431,20 @@ static void sculpt_stroke_update_step(bContext *C, struct PaintStroke *UNUSED(st
sculpt_restore_mesh(sd, ob);
if (sd->flags & SCULPT_DYNTOPO_DETAIL_CONSTANT) {
- BKE_pbvh_bmesh_detail_size_set(ss->pbvh,
- sd->constant_detail / 100.0f);
+ BKE_pbvh_bmesh_detail_size_set(ss->pbvh, sd->constant_detail / 100.0f);
+ }
+ else if (sd->flags & SCULPT_DYNTOPO_DETAIL_BRUSH) {
+ BKE_pbvh_bmesh_detail_size_set(ss->pbvh, ss->cache->radius * sd->detail_percent / 100.0f);
}
else {
- BKE_pbvh_bmesh_detail_size_set(ss->pbvh,
- (ss->cache->radius /
- (float)ups->pixel_radius) *
- (float)sd->detail_size / 0.4f);
+ BKE_pbvh_bmesh_detail_size_set(
+ ss->pbvh,
+ (ss->cache->radius /
+ (float)ups->pixel_radius) *
+ (float)(sd->detail_size * U.pixelsize) / 0.4f);
}
- if (sculpt_stroke_dynamic_topology(ss, brush)) {
+ if (sculpt_stroke_is_dynamic_topology(ss, brush)) {
do_symmetrical_brush_actions(sd, ob, sculpt_topology_update, ups);
}
@@ -4375,10 +4519,6 @@ static void sculpt_stroke_done(const bContext *C, struct PaintStroke *UNUSED(str
}
}
- /* update last stroke position */
- ob->sculpt->last_stroke_valid = 1;
- ED_sculpt_stroke_get_average(ob, ob->sculpt->last_stroke);
-
sculpt_cache_free(ss->cache);
ss->cache = NULL;
@@ -4714,8 +4854,8 @@ static int sculpt_dynamic_topology_toggle_exec(bContext *C, wmOperator *UNUSED(o
static int dyntopo_warning_popup(bContext *C, wmOperatorType *ot, bool vdata, bool modifiers)
{
- uiPopupMenu *pup = uiPupMenuBegin(C, IFACE_("Warning!"), ICON_ERROR);
- uiLayout *layout = uiPupMenuLayout(pup);
+ uiPopupMenu *pup = UI_popup_menu_begin(C, IFACE_("Warning!"), ICON_ERROR);
+ uiLayout *layout = UI_popup_menu_layout(pup);
if (vdata) {
const char *msg_error = TIP_("Vertex Data Detected!");
@@ -4736,9 +4876,9 @@ static int dyntopo_warning_popup(bContext *C, wmOperatorType *ot, bool vdata, bo
uiItemFullO_ptr(layout, ot, IFACE_("OK"), ICON_NONE, NULL, WM_OP_EXEC_DEFAULT, 0);
- uiPupMenuEnd(C, pup);
+ UI_popup_menu_end(C, pup);
- return OPERATOR_CANCELLED;
+ return OPERATOR_INTERFACE;
}
@@ -4760,7 +4900,7 @@ static int sculpt_dynamic_topology_toggle_invoke(bContext *C, wmOperator *op, co
if (!ELEM(i, CD_MVERT, CD_MEDGE, CD_MFACE, CD_MLOOP, CD_MPOLY, CD_PAINT_MASK, CD_ORIGINDEX) &&
(CustomData_has_layer(&me->vdata, i) ||
CustomData_has_layer(&me->edata, i) ||
- CustomData_has_layer(&me->fdata, i)))
+ CustomData_has_layer(&me->ldata, i)))
{
vdata = true;
break;
@@ -4771,7 +4911,7 @@ static int sculpt_dynamic_topology_toggle_invoke(bContext *C, wmOperator *op, co
/* exception for shape keys because we can edit those */
for (; md; md = md->next) {
- ModifierTypeInfo *mti = modifierType_getInfo(md->type);
+ const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
if (!modifier_isEnabled(scene, md, eModifierMode_Realtime)) continue;
if (mti->type == eModifierTypeType_Constructive) {
@@ -4863,6 +5003,9 @@ static int sculpt_symmetrize_exec(bContext *C, wmOperator *UNUSED(op))
sd->symmetrize_direction, 0.00001f);
sculpt_dynamic_topology_triangulate(ss->bm);
+ /* bisect operator flags edges (keep tags clean for edge queue) */
+ BM_mesh_elem_hflag_disable_all(ss->bm, BM_EDGE, BM_ELEM_TAG, false);
+
/* Finish undo */
BM_log_all_added(ss->bm, ss->bm_log);
sculpt_undo_push_end();
@@ -4937,7 +5080,7 @@ static int sculpt_mode_toggle_exec(bContext *C, wmOperator *op)
/* Leave sculptmode */
ob->mode &= ~mode_flag;
- BKE_free_sculptsession(ob);
+ BKE_sculptsession_free(ob);
paint_cursor_delete_textures();
}
@@ -4966,16 +5109,22 @@ static int sculpt_mode_toggle_exec(bContext *C, wmOperator *op)
ts->sculpt->flags |= SCULPT_DYNTOPO_SUBDIVIDE | SCULPT_DYNTOPO_COLLAPSE;
}
- if (!ts->sculpt->detail_size) {
+ if (!ts->sculpt->detail_size)
ts->sculpt->detail_size = 12;
- }
-
+ if (!ts->sculpt->detail_percent)
+ ts->sculpt->detail_percent = 25;
if (ts->sculpt->constant_detail == 0.0f)
ts->sculpt->constant_detail = 30.0f;
+ /* Set sane default tiling offsets */
+ if (!ts->sculpt->paint.tile_offset[0]) ts->sculpt->paint.tile_offset[0] = 1.0f;
+ if (!ts->sculpt->paint.tile_offset[1]) ts->sculpt->paint.tile_offset[1] = 1.0f;
+ if (!ts->sculpt->paint.tile_offset[2]) ts->sculpt->paint.tile_offset[2] = 1.0f;
+
+
/* Create sculpt mode session data */
if (ob->sculpt)
- BKE_free_sculptsession(ob);
+ BKE_sculptsession_free(ob);
sculpt_init_session(scene, ob);
@@ -4995,7 +5144,7 @@ static int sculpt_mode_toggle_exec(bContext *C, wmOperator *op)
"Object has negative scale, sculpting may be unpredictable");
}
- BKE_paint_init(&ts->sculpt->paint, PAINT_CURSOR_SCULPT);
+ BKE_paint_init(scene, ePaintSculpt, PAINT_CURSOR_SCULPT);
paint_cursor_start(C, sculpt_poll_view3d);
}
@@ -5058,7 +5207,10 @@ static int sculpt_detail_flood_fill_exec(bContext *C, wmOperator *UNUSED(op))
sculpt_undo_push_begin("Dynamic topology flood fill");
sculpt_undo_push_node(ob, NULL, SCULPT_UNDO_COORDS);
- while (BKE_pbvh_bmesh_update_topology(ss->pbvh, PBVH_Collapse | PBVH_Subdivide, bb_min, size)) {
+ while (BKE_pbvh_bmesh_update_topology(
+ ss->pbvh, PBVH_Collapse | PBVH_Subdivide,
+ bb_min, NULL, size))
+ {
for (i = 0; i < totnodes; i++)
BKE_pbvh_node_mark_topology_update(nodes[i]);
}
@@ -5188,6 +5340,50 @@ static void SCULPT_OT_sample_detail_size(wmOperatorType *ot)
RNA_def_int_array(ot->srna, "location", 2, NULL, 0, SHRT_MAX, "Location", "Screen Coordinates of sampling", 0, SHRT_MAX);
}
+
+static int sculpt_set_detail_size_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ Sculpt *sd = CTX_data_tool_settings(C)->sculpt;
+
+ PointerRNA props_ptr;
+ wmOperatorType *ot = WM_operatortype_find("WM_OT_radial_control", true);
+
+ WM_operator_properties_create_ptr(&props_ptr, ot);
+
+ if (sd->flags & SCULPT_DYNTOPO_DETAIL_CONSTANT) {
+ set_brush_rc_props(&props_ptr, "sculpt", "constant_detail", NULL, 0);
+ RNA_string_set(&props_ptr, "data_path_primary", "tool_settings.sculpt.constant_detail");
+ }
+ else if (sd->flags & SCULPT_DYNTOPO_DETAIL_BRUSH) {
+ set_brush_rc_props(&props_ptr, "sculpt", "constant_detail", NULL, 0);
+ RNA_string_set(&props_ptr, "data_path_primary", "tool_settings.sculpt.detail_percent");
+ }
+ else {
+ set_brush_rc_props(&props_ptr, "sculpt", "detail_size", NULL, 0);
+ RNA_string_set(&props_ptr, "data_path_primary", "tool_settings.sculpt.detail_size");
+ }
+
+ WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &props_ptr);
+
+ WM_operator_properties_free(&props_ptr);
+
+ return OPERATOR_FINISHED;
+}
+
+static void SCULPT_OT_set_detail_size(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Set Detail Size";
+ ot->idname = "SCULPT_OT_set_detail_size";
+ ot->description = "Set the mesh detail (either relative or constant one, depending on current dyntopo mode)";
+
+ /* api callbacks */
+ ot->exec = sculpt_set_detail_size_exec;
+ ot->poll = sculpt_and_dynamic_topology_poll;
+
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
void ED_operatortypes_sculpt(void)
{
WM_operatortype_append(SCULPT_OT_brush_stroke);
@@ -5198,4 +5394,5 @@ void ED_operatortypes_sculpt(void)
WM_operatortype_append(SCULPT_OT_symmetrize);
WM_operatortype_append(SCULPT_OT_detail_flood_fill);
WM_operatortype_append(SCULPT_OT_sample_detail_size);
+ WM_operatortype_append(SCULPT_OT_set_detail_size);
}
diff --git a/source/blender/editors/sculpt_paint/sculpt_intern.h b/source/blender/editors/sculpt_paint/sculpt_intern.h
index a61f571fdf6..8f1a4655c37 100644
--- a/source/blender/editors/sculpt_paint/sculpt_intern.h
+++ b/source/blender/editors/sculpt_paint/sculpt_intern.h
@@ -41,14 +41,8 @@
#include "BKE_pbvh.h"
struct bContext;
-struct Brush;
struct KeyBlock;
-struct Mesh;
-struct MultiresModifierData;
struct Object;
-struct Scene;
-struct Sculpt;
-struct SculptStroke;
struct SculptUndoNode;
int sculpt_mode_poll(struct bContext *C);
diff --git a/source/blender/editors/sculpt_paint/sculpt_undo.c b/source/blender/editors/sculpt_paint/sculpt_undo.c
index 91f80a4fc40..1f1be51b9a6 100644
--- a/source/blender/editors/sculpt_paint/sculpt_undo.c
+++ b/source/blender/editors/sculpt_paint/sculpt_undo.c
@@ -104,7 +104,7 @@ static int sculpt_undo_restore_coords(bContext *C, DerivedMesh *dm, SculptUndoNo
if (unode->maxvert) {
/* regular mesh restore */
- if (ss->kb && strcmp(ss->kb->name, unode->shapeName)) {
+ if (ss->kb && !STREQ(ss->kb->name, unode->shapeName)) {
/* shape key has been changed before calling undo operator */
Key *key = BKE_key_from_object(ob);
@@ -127,7 +127,7 @@ static int sculpt_undo_restore_coords(bContext *C, DerivedMesh *dm, SculptUndoNo
if (ss->kb) {
float (*vertCos)[3];
- vertCos = BKE_key_convert_to_vertcos(ob, ss->kb);
+ vertCos = BKE_keyblock_convert_to_vertcos(ob, ss->kb);
for (i = 0; i < unode->totvert; i++) {
if (ss->modifiers_active) {
@@ -279,7 +279,7 @@ static void sculpt_undo_bmesh_restore_generic(bContext *C,
unode->applied = true;
}
- if (ELEM(unode->type, SCULPT_UNDO_MASK, SCULPT_UNDO_MASK)) {
+ if (unode->type == SCULPT_UNDO_MASK) {
int i, totnode;
PBVHNode **nodes;
@@ -404,7 +404,7 @@ static void sculpt_undo_restore(bContext *C, ListBase *lb)
bool need_mask = false;
for (unode = lb->first; unode; unode = unode->next) {
- if (strcmp(unode->idname, ob->id.name) == 0) {
+ if (STREQ(unode->idname, ob->id.name)) {
if (unode->type == SCULPT_UNDO_MASK) {
/* is possible that we can't do the mask undo (below)
* because of the vertex count */
@@ -423,7 +423,7 @@ static void sculpt_undo_restore(bContext *C, ListBase *lb)
return;
for (unode = lb->first; unode; unode = unode->next) {
- if (!(strcmp(unode->idname, ob->id.name) == 0))
+ if (!STREQ(unode->idname, ob->id.name))
continue;
/* check if undo data matches current data well enough to
@@ -484,7 +484,7 @@ static void sculpt_undo_restore(bContext *C, ListBase *lb)
BKE_mesh_calc_normals_tessface(mesh->mvert, mesh->totvert,
mesh->mface, mesh->totface, NULL);
- BKE_free_sculptsession_deformMats(ss);
+ BKE_sculptsession_free_deformMats(ss);
tag_update |= true;
}
@@ -550,7 +550,7 @@ static bool sculpt_undo_cleanup(bContext *C, ListBase *lb)
unode = lb->first;
- if (unode && strcmp(unode->idname, ob->id.name) != 0) {
+ if (unode && !STREQ(unode->idname, ob->id.name)) {
if (unode->bm_entry)
BM_log_cleanup_entry(unode->bm_entry);
@@ -581,7 +581,7 @@ static void sculpt_undo_alloc_and_store_hidden(PBVH *pbvh,
grid_hidden = BKE_pbvh_grid_hidden(pbvh);
BKE_pbvh_node_get_grids(pbvh, node, &grid_indices, &totgrid,
- NULL, NULL, NULL, NULL);
+ NULL, NULL, NULL);
unode->grid_hidden = MEM_mapallocN(sizeof(*unode->grid_hidden) * totgrid,
"unode->grid_hidden");
@@ -610,7 +610,7 @@ static SculptUndoNode *sculpt_undo_alloc_node(Object *ob, PBVHNode *node,
if (node) {
BKE_pbvh_node_num_verts(ss->pbvh, node, &totvert, &allvert);
BKE_pbvh_node_get_grids(ss->pbvh, node, &grids, &totgrid,
- &maxgrid, &gridsize, NULL, NULL);
+ &maxgrid, &gridsize, NULL);
unode->totvert = totvert;
}
@@ -695,7 +695,8 @@ static void sculpt_undo_store_hidden(Object *ob, SculptUndoNode *unode)
}
else {
MVert *mvert;
- int *vert_indices, allvert;
+ const int *vert_indices;
+ int allvert;
int i;
BKE_pbvh_node_num_verts(pbvh, node, NULL, &allvert);
@@ -842,11 +843,12 @@ SculptUndoNode *sculpt_undo_push_node(Object *ob, PBVHNode *node,
if (unode->grids) {
int totgrid, *grids;
BKE_pbvh_node_get_grids(ss->pbvh, node, &grids, &totgrid,
- NULL, NULL, NULL, NULL);
+ NULL, NULL, NULL);
memcpy(unode->grids, grids, sizeof(int) * totgrid);
}
else {
- int *vert_indices, allvert;
+ const int *vert_indices;
+ int allvert;
BKE_pbvh_node_num_verts(ss->pbvh, node, NULL, &allvert);
BKE_pbvh_node_get_verts(ss->pbvh, node, &vert_indices, NULL);
memcpy(unode->index, vert_indices, sizeof(int) * unode->totvert);
diff --git a/source/blender/editors/sculpt_paint/sculpt_uv.c b/source/blender/editors/sculpt_paint/sculpt_uv.c
index d90eaafa379..405ac3f6808 100644
--- a/source/blender/editors/sculpt_paint/sculpt_uv.c
+++ b/source/blender/editors/sculpt_paint/sculpt_uv.c
@@ -60,7 +60,6 @@
#include "RNA_access.h"
#include "RNA_define.h"
-#include "RNA_enum_types.h"
#include "paint_intern.h"
#include "uvedit_intern.h"
@@ -225,8 +224,9 @@ static void brush_drawcursor_uvsculpt(bContext *C, int x, int y, void *UNUSED(cu
}
-void ED_space_image_uv_sculpt_update(wmWindowManager *wm, ToolSettings *settings)
+void ED_space_image_uv_sculpt_update(wmWindowManager *wm, Scene *scene)
{
+ ToolSettings *settings = scene->toolsettings;
if (settings->use_uv_sculpt) {
if (!settings->uvsculpt) {
settings->uvsculpt = MEM_callocN(sizeof(*settings->uvsculpt), "UV Smooth paint");
@@ -237,7 +237,7 @@ void ED_space_image_uv_sculpt_update(wmWindowManager *wm, ToolSettings *settings
settings->uvsculpt->paint.flags |= PAINT_SHOW_BRUSH;
}
- BKE_paint_init(&settings->uvsculpt->paint, PAINT_CURSOR_SCULPT);
+ BKE_paint_init(scene, ePaintSculptUV, PAINT_CURSOR_SCULPT);
settings->uvsculpt->paint.paint_cursor = WM_paint_cursor_activate(wm, uv_sculpt_brush_poll,
brush_drawcursor_uvsculpt, NULL);
@@ -316,7 +316,7 @@ static void HC_relaxation_iteration_uv(BMEditMesh *em, UvSculptData *sculptdata,
if ((dist = dot_v2v2(diff, diff)) <= radius) {
UvElement *element;
float strength;
- strength = alpha * BKE_brush_curve_strength(brush, sqrtf(dist), radius_root);
+ strength = alpha * BKE_brush_curve_strength_clamped(brush, sqrtf(dist), radius_root);
sculptdata->uv[i].uv[0] = (1.0f - strength) * sculptdata->uv[i].uv[0] + strength * (tmp_uvdata[i].p[0] - 0.5f * (tmp_uvdata[i].b[0] + tmp_uvdata[i].sum_b[0] / tmp_uvdata[i].ncounter));
sculptdata->uv[i].uv[1] = (1.0f - strength) * sculptdata->uv[i].uv[1] + strength * (tmp_uvdata[i].p[1] - 0.5f * (tmp_uvdata[i].b[1] + tmp_uvdata[i].sum_b[1] / tmp_uvdata[i].ncounter));
@@ -380,7 +380,7 @@ static void laplacian_relaxation_iteration_uv(BMEditMesh *em, UvSculptData *scul
if ((dist = dot_v2v2(diff, diff)) <= radius) {
UvElement *element;
float strength;
- strength = alpha * BKE_brush_curve_strength(brush, sqrtf(dist), radius_root);
+ strength = alpha * BKE_brush_curve_strength_clamped(brush, sqrtf(dist), radius_root);
sculptdata->uv[i].uv[0] = (1.0f - strength) * sculptdata->uv[i].uv[0] + strength * tmp_uvdata[i].p[0];
sculptdata->uv[i].uv[1] = (1.0f - strength) * sculptdata->uv[i].uv[1] + strength * tmp_uvdata[i].p[1];
@@ -455,7 +455,7 @@ static void uv_sculpt_stroke_apply(bContext *C, wmOperator *op, const wmEvent *e
if ((dist = dot_v2v2(diff, diff)) <= radius) {
UvElement *element;
float strength;
- strength = alpha * BKE_brush_curve_strength(brush, sqrtf(dist), radius_root);
+ strength = alpha * BKE_brush_curve_strength_clamped(brush, sqrtf(dist), radius_root);
normalize_v2(diff);
sculptdata->uv[i].uv[0] -= strength * diff[0] * 0.001f;
@@ -558,15 +558,15 @@ static int uv_element_offset_from_face_get(UvElementMap *map, BMFace *efa, BMLoo
static unsigned int uv_edge_hash(const void *key)
{
- UvEdge *edge = (UvEdge *)key;
+ const UvEdge *edge = key;
return (BLI_ghashutil_uinthash(edge->uv2) +
BLI_ghashutil_uinthash(edge->uv1));
}
static bool uv_edge_compare(const void *a, const void *b)
{
- UvEdge *edge1 = (UvEdge *)a;
- UvEdge *edge2 = (UvEdge *)b;
+ const UvEdge *edge1 = a;
+ const UvEdge *edge2 = b;
if ((edge1->uv1 == edge2->uv1) && (edge1->uv2 == edge2->uv2)) {
return 0;
@@ -599,7 +599,7 @@ static UvSculptData *uv_sculpt_stroke_init(bContext *C, wmOperator *op, const wm
UvEdge *edges;
GHash *edgeHash;
- GHashIterator *ghi;
+ GHashIterator gh_iter;
bool do_island_optimization = !(ts->uv_sculpt_settings & UV_SCULPT_ALL_ISLANDS);
int island_index = 0;
@@ -613,18 +613,18 @@ static UvSculptData *uv_sculpt_stroke_init(bContext *C, wmOperator *op, const wm
if (do_island_optimization) {
/* We will need island information */
if (ts->uv_flag & UV_SYNC_SELECTION) {
- data->elementMap = BM_uv_element_map_create(bm, false, true);
+ data->elementMap = BM_uv_element_map_create(bm, false, true, true);
}
else {
- data->elementMap = BM_uv_element_map_create(bm, true, true);
+ data->elementMap = BM_uv_element_map_create(bm, true, true, true);
}
}
else {
if (ts->uv_flag & UV_SYNC_SELECTION) {
- data->elementMap = BM_uv_element_map_create(bm, false, false);
+ data->elementMap = BM_uv_element_map_create(bm, false, true, false);
}
else {
- data->elementMap = BM_uv_element_map_create(bm, true, false);
+ data->elementMap = BM_uv_element_map_create(bm, true, true, false);
}
}
@@ -755,21 +755,15 @@ static UvSculptData *uv_sculpt_stroke_init(bContext *C, wmOperator *op, const wm
uv_sculpt_stroke_exit(C, op);
return NULL;
}
- ghi = BLI_ghashIterator_new(edgeHash);
- if (!ghi) {
- BLI_ghash_free(edgeHash, NULL, NULL);
- MEM_freeN(edges);
- uv_sculpt_stroke_exit(C, op);
- return NULL;
- }
+
/* fill the edges with data */
- for (i = 0; !BLI_ghashIterator_done(ghi); BLI_ghashIterator_step(ghi)) {
- data->uvedges[i++] = *((UvEdge *)BLI_ghashIterator_getKey(ghi));
+ i = 0;
+ GHASH_ITER (gh_iter, edgeHash) {
+ data->uvedges[i++] = *((UvEdge *)BLI_ghashIterator_getKey(&gh_iter));
}
data->totalUvEdges = BLI_ghash_size(edgeHash);
/* cleanup temporary stuff */
- BLI_ghashIterator_free(ghi);
BLI_ghash_free(edgeHash, NULL, NULL);
MEM_freeN(edges);
@@ -829,7 +823,7 @@ static UvSculptData *uv_sculpt_stroke_init(bContext *C, wmOperator *op, const wm
diff[1] /= aspectRatio;
if ((dist = dot_v2v2(diff, diff)) <= radius) {
float strength;
- strength = alpha * BKE_brush_curve_strength(brush, sqrtf(dist), radius_root);
+ strength = alpha * BKE_brush_curve_strength_clamped(brush, sqrtf(dist), radius_root);
data->initial_stroke->initialSelection[counter].uv = i;
data->initial_stroke->initialSelection[counter].strength = strength;
diff --git a/source/blender/editors/sound/CMakeLists.txt b/source/blender/editors/sound/CMakeLists.txt
index 245ee657bc3..535cd579030 100644
--- a/source/blender/editors/sound/CMakeLists.txt
+++ b/source/blender/editors/sound/CMakeLists.txt
@@ -39,10 +39,11 @@ set(SRC
)
if(WITH_AUDASPACE)
- list(APPEND INC
- ../../../../intern/audaspace/intern
+ add_definitions(${AUDASPACE_DEFINITIONS})
+
+ list(APPEND INC_SYS
+ ${AUDASPACE_C_INCLUDE_DIRS}
)
- add_definitions(-DWITH_AUDASPACE)
endif()
if(WITH_CODEC_FFMPEG)
diff --git a/source/blender/editors/sound/SConscript b/source/blender/editors/sound/SConscript
index 33feedf51cc..fad52c64df1 100644
--- a/source/blender/editors/sound/SConscript
+++ b/source/blender/editors/sound/SConscript
@@ -31,7 +31,6 @@ sources = env.Glob('*.c')
incs = [
'#/intern/guardedalloc',
- '#/intern/audaspace/intern',
'../include',
'../../blenkernel',
'../../blenlib',
@@ -44,6 +43,10 @@ incs = ' '.join(incs)
defs = []
+if env['WITH_BF_AUDASPACE']:
+ defs += env['BF_AUDASPACE_DEF']
+ incs += ' ' + env['BF_AUDASPACE_C_INC']
+
if env['WITH_BF_FFMPEG']:
defs.append('WITH_FFMPEG')
diff --git a/source/blender/editors/sound/sound_intern.h b/source/blender/editors/sound/sound_intern.h
index e8a8ec55ab5..ace173abdee 100644
--- a/source/blender/editors/sound/sound_intern.h
+++ b/source/blender/editors/sound/sound_intern.h
@@ -32,7 +32,6 @@
#ifndef __SOUND_INTERN_H__
#define __SOUND_INTERN_H__
-struct wmOperatorType;
#endif /* __SOUND_INTERN_H__ */
diff --git a/source/blender/editors/sound/sound_ops.c b/source/blender/editors/sound/sound_ops.c
index 619fbd7f4c8..f8d84cc0276 100644
--- a/source/blender/editors/sound/sound_ops.c
+++ b/source/blender/editors/sound/sound_ops.c
@@ -51,6 +51,7 @@
#include "BKE_global.h"
#include "BKE_main.h"
#include "BKE_report.h"
+#include "BKE_library.h"
#include "BKE_packedFile.h"
#include "BKE_scene.h"
#include "BKE_sound.h"
@@ -66,13 +67,12 @@
#include "WM_types.h"
#ifdef WITH_AUDASPACE
-# include "AUD_C-API.h"
+# include AUD_SPECIAL_H
#endif
#include "ED_sound.h"
#include "ED_util.h"
-#include "sound_intern.h"
/******************** open sound operator ********************/
@@ -87,7 +87,7 @@ static void sound_open_init(bContext *C, wmOperator *op)
PropertyPointerRNA *pprop;
op->customdata = pprop = MEM_callocN(sizeof(PropertyPointerRNA), "OpenPropertyPointerRNA");
- uiIDContextProperty(C, &pprop->ptr, &pprop->prop);
+ UI_context_active_but_prop_get_templateID(C, &pprop->ptr, &pprop->prop);
}
#ifdef WITH_AUDASPACE
@@ -101,13 +101,14 @@ static int sound_open_exec(bContext *C, wmOperator *op)
Main *bmain = CTX_data_main(C);
RNA_string_get(op->ptr, "filepath", path);
- sound = sound_new_file(bmain, path);
+ sound = BKE_sound_new_file(bmain, path);
if (!op->customdata)
sound_open_init(C, op);
- if (sound == NULL || sound->playback_handle == NULL) {
+ if (sound->playback_handle == NULL) {
if (op->customdata) MEM_freeN(op->customdata);
+ BKE_libblock_free(bmain, sound);
BKE_report(op->reports, RPT_ERROR, "Unsupported audio format");
return OPERATOR_CANCELLED;
}
@@ -115,7 +116,7 @@ static int sound_open_exec(bContext *C, wmOperator *op)
info = AUD_getInfo(sound->playback_handle);
if (info.specs.channels == AUD_CHANNELS_INVALID) {
- sound_delete(bmain, sound);
+ BKE_sound_delete(bmain, sound);
if (op->customdata) MEM_freeN(op->customdata);
BKE_report(op->reports, RPT_ERROR, "Unsupported audio format");
return OPERATOR_CANCELLED;
@@ -123,11 +124,11 @@ static int sound_open_exec(bContext *C, wmOperator *op)
if (RNA_boolean_get(op->ptr, "mono")) {
sound->flags |= SOUND_FLAGS_MONO;
- sound_load(bmain, sound);
+ BKE_sound_load(bmain, sound);
}
if (RNA_boolean_get(op->ptr, "cache")) {
- sound_cache(sound);
+ BKE_sound_cache(sound);
}
/* hook into UI */
@@ -143,7 +144,7 @@ static int sound_open_exec(bContext *C, wmOperator *op)
RNA_property_update(C, &pprop->ptr, pprop->prop);
}
- if (op->customdata) MEM_freeN(op->customdata);
+ MEM_freeN(op->customdata);
return OPERATOR_FINISHED;
}
@@ -184,8 +185,8 @@ static void SOUND_OT_open(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
/* properties */
- WM_operator_properties_filesel(ot, FOLDERFILE | SOUNDFILE | MOVIEFILE, FILE_SPECIAL, FILE_OPENFILE,
- WM_FILESEL_FILEPATH | WM_FILESEL_RELPATH, FILE_DEFAULTDISPLAY);
+ WM_operator_properties_filesel(ot, FILE_TYPE_FOLDER | FILE_TYPE_SOUND | FILE_TYPE_MOVIE, FILE_SPECIAL, FILE_OPENFILE,
+ WM_FILESEL_FILEPATH | WM_FILESEL_RELPATH, FILE_DEFAULTDISPLAY, FILE_SORT_ALPHA);
RNA_def_boolean(ot->srna, "cache", false, "Cache", "Cache the sound in memory");
RNA_def_boolean(ot->srna, "mono", false, "Mono", "Mixdown the sound to mono");
}
@@ -206,8 +207,8 @@ static void SOUND_OT_open_mono(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
/* properties */
- WM_operator_properties_filesel(ot, FOLDERFILE | SOUNDFILE | MOVIEFILE, FILE_SPECIAL, FILE_OPENFILE,
- WM_FILESEL_FILEPATH | WM_FILESEL_RELPATH, FILE_DEFAULTDISPLAY);
+ WM_operator_properties_filesel(ot, FILE_TYPE_FOLDER | FILE_TYPE_SOUND | FILE_TYPE_MOVIE, FILE_SPECIAL, FILE_OPENFILE,
+ WM_FILESEL_FILEPATH | WM_FILESEL_RELPATH, FILE_DEFAULTDISPLAY, FILE_SORT_ALPHA);
RNA_def_boolean(ot->srna, "cache", false, "Cache", "Cache the sound in memory");
RNA_def_boolean(ot->srna, "mono", true, "Mono", "Mixdown the sound to mono");
}
@@ -243,7 +244,7 @@ static int sound_update_animation_flags_exec(bContext *C, wmOperator *UNUSED(op)
}
SEQ_END
- fcu = id_data_find_fcurve(&scene->id, scene, &RNA_Scene, "audio_volume", 0, &driven);
+ fcu = id_data_find_fcurve(&scene->id, scene, &RNA_Scene, "audio_volume", 0, &driven);
if (fcu || driven)
scene->audio.flag |= AUDIO_VOLUME_ANIMATED;
else
@@ -400,7 +401,7 @@ static bool sound_mixdown_check(bContext *UNUSED(C), wmOperator *op)
if (item->value == container) {
const char **ext = snd_ext_sound;
while (*ext != NULL) {
- if (!strcmp(*ext + 1, item->name)) {
+ if (STREQ(*ext + 1, item->name)) {
extension = *ext;
break;
}
@@ -450,9 +451,9 @@ static int sound_mixdown_invoke(bContext *C, wmOperator *op, const wmEvent *even
static bool sound_mixdown_draw_check_prop(PointerRNA *UNUSED(ptr), PropertyRNA *prop)
{
const char *prop_id = RNA_property_identifier(prop);
- return !(strcmp(prop_id, "filepath") == 0 ||
- strcmp(prop_id, "directory") == 0 ||
- strcmp(prop_id, "filename") == 0);
+ return !(STREQ(prop_id, "filepath") ||
+ STREQ(prop_id, "directory") ||
+ STREQ(prop_id, "filename"));
}
static void sound_mixdown_draw(bContext *C, wmOperator *op)
@@ -651,8 +652,8 @@ static void SOUND_OT_mixdown(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER;
/* properties */
- WM_operator_properties_filesel(ot, FOLDERFILE | SOUNDFILE, FILE_SPECIAL, FILE_SAVE,
- WM_FILESEL_FILEPATH | WM_FILESEL_RELPATH, FILE_DEFAULTDISPLAY);
+ WM_operator_properties_filesel(ot, FILE_TYPE_FOLDER | FILE_TYPE_SOUND, FILE_SPECIAL, FILE_SAVE,
+ WM_FILESEL_FILEPATH | WM_FILESEL_RELPATH, FILE_DEFAULTDISPLAY, FILE_SORT_ALPHA);
#ifdef WITH_AUDASPACE
RNA_def_int(ot->srna, "accuracy", 1024, 1, 16777216, "Accuracy", "Sample accuracy, important for animation data (the lower the value, the more accurate)", 1, 16777216);
RNA_def_enum(ot->srna, "container", container_items, AUD_CONTAINER_FLAC, "Container", "File format");
@@ -691,7 +692,7 @@ static int sound_pack_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
sound->packedfile = newPackedFile(op->reports, sound->name, ID_BLEND_PATH(bmain, &sound->id));
- sound_load(bmain, sound);
+ BKE_sound_load(bmain, sound);
return OPERATOR_FINISHED;
}
diff --git a/source/blender/editors/space_action/CMakeLists.txt b/source/blender/editors/space_action/CMakeLists.txt
index e0dc2709cf3..839071d1330 100644
--- a/source/blender/editors/space_action/CMakeLists.txt
+++ b/source/blender/editors/space_action/CMakeLists.txt
@@ -22,10 +22,13 @@ set(INC
../include
../../blenkernel
../../blenlib
+ ../../blentranslation
+ ../../gpu
../../makesdna
../../makesrna
../../windowmanager
../../../../intern/guardedalloc
+ ../../../../intern/glew-mx
)
set(INC_SYS
@@ -33,6 +36,7 @@ set(INC_SYS
)
set(SRC
+ action_data.c
action_draw.c
action_edit.c
action_ops.c
@@ -42,4 +46,6 @@ set(SRC
action_intern.h
)
+add_definitions(${GL_DEFINITIONS})
+
blender_add_lib(bf_editor_space_action "${SRC}" "${INC}" "${INC_SYS}")
diff --git a/source/blender/editors/space_action/SConscript b/source/blender/editors/space_action/SConscript
index 2776bd2989a..346324e129d 100644
--- a/source/blender/editors/space_action/SConscript
+++ b/source/blender/editors/space_action/SConscript
@@ -29,16 +29,22 @@ Import ('env')
sources = env.Glob('*.c')
+defs = []
+defs += env['BF_GL_DEFINITIONS']
+
incs = [
'#/intern/guardedalloc',
- '#/extern/glew/include',
+ env['BF_GLEW_INC'],
+ '#/intern/glew-mx',
'../include',
'../../blenkernel',
'../../blenlib',
+ '../../blentranslation',
+ '../../gpu',
'../../makesdna',
'../../makesrna',
'../../windowmanager',
]
incs = ' '.join(incs)
-env.BlenderLib ( 'bf_editors_space_action', sources, Split(incs), [], libtype=['core'], priority=[40] )
+env.BlenderLib ( 'bf_editors_space_action', sources, Split(incs), defs, libtype=['core'], priority=[40] )
diff --git a/source/blender/editors/space_action/action_data.c b/source/blender/editors/space_action/action_data.c
new file mode 100644
index 00000000000..c3519423773
--- /dev/null
+++ b/source/blender/editors/space_action/action_data.c
@@ -0,0 +1,963 @@
+/*
+ * ***** 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) 2015 Blender Foundation
+ * This is a new part of Blender
+ *
+ * Contributor(s): Joshua Leung
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/editors/space_action/action_data.c
+ * \ingroup spaction
+ */
+
+
+#include <math.h>
+#include <stdlib.h>
+#include <string.h>
+#include <float.h>
+
+
+#include "BLI_blenlib.h"
+#include "BLI_math.h"
+#include "BLI_utildefines.h"
+
+#include "BLT_translation.h"
+
+#include "DNA_anim_types.h"
+#include "DNA_gpencil_types.h"
+#include "DNA_key_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_mask_types.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+#include "RNA_enum_types.h"
+
+#include "BKE_animsys.h"
+#include "BKE_action.h"
+#include "BKE_fcurve.h"
+#include "BKE_global.h"
+#include "BKE_library.h"
+#include "BKE_key.h"
+#include "BKE_main.h"
+#include "BKE_nla.h"
+#include "BKE_scene.h"
+#include "BKE_context.h"
+#include "BKE_report.h"
+
+#include "UI_view2d.h"
+
+#include "ED_anim_api.h"
+#include "ED_gpencil.h"
+#include "ED_keyframing.h"
+#include "ED_keyframes_edit.h"
+#include "ED_screen.h"
+#include "ED_markers.h"
+#include "ED_mask.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "UI_interface.h"
+
+#include "action_intern.h"
+
+/* ************************************************************************** */
+/* ACTION CREATION */
+
+/* Helper function to find the active AnimData block from the Action Editor context */
+AnimData *ED_actedit_animdata_from_context(bContext *C)
+{
+ SpaceAction *saction = (SpaceAction *)CTX_wm_space_data(C);
+ Object *ob = CTX_data_active_object(C);
+ AnimData *adt = NULL;
+
+ /* Get AnimData block to use */
+ if (saction->mode == SACTCONT_ACTION) {
+ /* Currently, "Action Editor" means object-level only... */
+ if (ob) {
+ adt = ob->adt;
+ }
+ }
+ else if (saction->mode == SACTCONT_SHAPEKEY) {
+ Key *key = BKE_key_from_object(ob);
+ if (key) {
+ adt = key->adt;
+ }
+ }
+
+ return adt;
+}
+
+/* -------------------------------------------------------------------- */
+
+/* Create new action */
+static bAction *action_create_new(bContext *C, bAction *oldact)
+{
+ ScrArea *sa = CTX_wm_area(C);
+ bAction *action;
+
+ /* create action - the way to do this depends on whether we've got an
+ * existing one there already, in which case we make a copy of it
+ * (which is useful for "versioning" actions within the same file)
+ */
+ if (oldact && GS(oldact->id.name) == ID_AC) {
+ /* make a copy of the existing action */
+ action = BKE_action_copy(oldact);
+ }
+ else {
+ /* just make a new (empty) action */
+ action = add_empty_action(CTX_data_main(C), "Action");
+ }
+
+ /* when creating new ID blocks, there is already 1 user (as for all new datablocks),
+ * but the RNA pointer code will assign all the proper users instead, so we compensate
+ * for that here
+ */
+ BLI_assert(action->id.us == 1);
+ action->id.us--;
+
+ /* set ID-Root type */
+ if (sa->spacetype == SPACE_ACTION) {
+ SpaceAction *saction = (SpaceAction *)sa->spacedata.first;
+
+ if (saction->mode == SACTCONT_SHAPEKEY)
+ action->idroot = ID_KE;
+ else
+ action->idroot = ID_OB;
+ }
+
+ return action;
+}
+
+/* Change the active action used by the action editor */
+static void actedit_change_action(bContext *C, bAction *act)
+{
+ bScreen *screen = CTX_wm_screen(C);
+ SpaceAction *saction = (SpaceAction *)CTX_wm_space_data(C);
+
+ PointerRNA ptr, idptr;
+ PropertyRNA *prop;
+
+ /* create RNA pointers and get the property */
+ RNA_pointer_create(&screen->id, &RNA_SpaceDopeSheetEditor, saction, &ptr);
+ prop = RNA_struct_find_property(&ptr, "action");
+
+ /* NOTE: act may be NULL here, so better to just use a cast here */
+ RNA_id_pointer_create((ID *)act, &idptr);
+
+ /* set the new pointer, and force a refresh */
+ RNA_property_pointer_set(&ptr, prop, idptr);
+ RNA_property_update(C, &ptr, prop);
+}
+
+/* ******************** New Action Operator *********************** */
+
+/* Criteria:
+ * 1) There must be an dopesheet/action editor, and it must be in a mode which uses actions...
+ * OR
+ * The NLA Editor is active (i.e. Animation Data panel -> new action)
+ * 2) The associated AnimData block must not be in tweakmode
+ */
+static int action_new_poll(bContext *C)
+{
+ Scene *scene = CTX_data_scene(C);
+
+ /* Check tweakmode is off (as you don't want to be tampering with the action in that case) */
+ /* NOTE: unlike for pushdown, this operator needs to be run when creating an action from nothing... */
+ if (ED_operator_action_active(C)) {
+ SpaceAction *saction = (SpaceAction *)CTX_wm_space_data(C);
+ Object *ob = CTX_data_active_object(C);
+
+ /* For now, actions are only for the active object, and on object and shapekey levels... */
+ if (saction->mode == SACTCONT_ACTION) {
+ /* XXX: This assumes that actions are assigned to the active object in this mode */
+ if (ob) {
+ if ((ob->adt == NULL) || (ob->adt->flag & ADT_NLA_EDIT_ON) == 0)
+ return true;
+ }
+ }
+ else if (saction->mode == SACTCONT_SHAPEKEY) {
+ Key *key = BKE_key_from_object(ob);
+ if (key) {
+ if ((key->adt == NULL) || (key->adt->flag & ADT_NLA_EDIT_ON) == 0)
+ return true;
+ }
+ }
+ }
+ else if (ED_operator_nla_active(C)) {
+ if (!(scene->flag & SCE_NLA_EDIT_ON)) {
+ return true;
+ }
+ }
+
+ /* something failed... */
+ return false;
+}
+
+static int action_new_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ PointerRNA ptr, idptr;
+ PropertyRNA *prop;
+
+ /* hook into UI */
+ UI_context_active_but_prop_get_templateID(C, &ptr, &prop);
+
+ if (prop) {
+ bAction *action = NULL, *oldact = NULL;
+ AnimData *adt = NULL;
+ PointerRNA oldptr;
+
+ oldptr = RNA_property_pointer_get(&ptr, prop);
+ oldact = (bAction *)oldptr.id.data;
+
+ /* stash the old action to prevent it from being lost */
+ if (ptr.type == &RNA_AnimData) {
+ adt = ptr.data;
+ }
+ else if (ptr.type == &RNA_SpaceDopeSheetEditor) {
+ adt = ED_actedit_animdata_from_context(C);
+ }
+
+ /* Perform stashing operation - But only if there is an action */
+ if (adt && oldact) {
+ /* stash the action */
+ if (BKE_nla_action_stash(adt)) {
+ /* The stash operation will remove the user already
+ * (and unlink the action from the AnimData action slot).
+ * Hence, we must unset the ref to the action in the
+ * action editor too (if this is where we're being called from)
+ * first before setting the new action once it is created,
+ * or else the user gets decremented twice!
+ */
+ if (ptr.type == &RNA_SpaceDopeSheetEditor) {
+ SpaceAction *saction = (SpaceAction *)ptr.data;
+ saction->action = NULL;
+ }
+ }
+ else {
+ //printf("WARNING: Failed to stash %s. It may already exist in the NLA stack though\n", oldact->id.name);
+ }
+ }
+
+ /* create action */
+ action = action_create_new(C, oldact);
+
+ /* set this new action
+ * NOTE: we can't use actedit_change_action, as this function is also called from the NLA
+ */
+ RNA_id_pointer_create(&action->id, &idptr);
+ RNA_property_pointer_set(&ptr, prop, idptr);
+ RNA_property_update(C, &ptr, prop);
+ }
+
+ /* set notifier that keyframes have changed */
+ WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_ADDED, NULL);
+
+ return OPERATOR_FINISHED;
+}
+
+void ACTION_OT_new(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "New Action";
+ ot->idname = "ACTION_OT_new";
+ ot->description = "Create new action";
+
+ /* api callbacks */
+ ot->exec = action_new_exec;
+ ot->poll = action_new_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+/* ******************* Action Push-Down Operator ******************** */
+
+/* Criteria:
+ * 1) There must be an dopesheet/action editor, and it must be in a mode which uses actions
+ * 2) There must be an action active
+ * 3) The associated AnimData block must not be in tweakmode
+ */
+static int action_pushdown_poll(bContext *C)
+{
+ if (ED_operator_action_active(C)) {
+ SpaceAction *saction = (SpaceAction *)CTX_wm_space_data(C);
+ AnimData *adt = ED_actedit_animdata_from_context(C);
+
+ /* Check for AnimData, Actions, and that tweakmode is off */
+ if (adt && saction->action) {
+ /* NOTE: We check this for the AnimData block in question and not the global flag,
+ * as the global flag may be left dirty by some of the browsing ops here.
+ */
+ if (!(adt->flag & ADT_NLA_EDIT_ON))
+ return true;
+ }
+ }
+
+ /* something failed... */
+ return false;
+}
+
+static int action_pushdown_exec(bContext *C, wmOperator *op)
+{
+ SpaceAction *saction = (SpaceAction *)CTX_wm_space_data(C);
+ AnimData *adt = ED_actedit_animdata_from_context(C);
+
+ /* Do the deed... */
+ if (adt) {
+ /* Perform the pushdown operation
+ * - This will deal with all the AnimData-side usercounts
+ */
+ if (action_has_motion(adt->action) == 0) {
+ /* action may not be suitable... */
+ BKE_report(op->reports, RPT_WARNING, "Action must have at least one keyframe or F-Modifier");
+ return OPERATOR_CANCELLED;
+ }
+ else {
+ /* action can be safely added */
+ BKE_nla_action_pushdown(adt);
+ }
+
+ /* Stop displaying this action in this editor
+ * NOTE: The editor itself doesn't set a user...
+ */
+ saction->action = NULL;
+ }
+
+ /* Send notifiers that stuff has changed */
+ WM_event_add_notifier(C, NC_ANIMATION | ND_NLA_ACTCHANGE, NULL);
+ return OPERATOR_FINISHED;
+}
+
+void ACTION_OT_push_down(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Push Down Action";
+ ot->idname = "ACTION_OT_push_down";
+ ot->description = "Push action down on to the NLA stack as a new strip";
+
+ /* callbacks */
+ ot->exec = action_pushdown_exec;
+ ot->poll = action_pushdown_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+/* ******************* Action Stash Operator ******************** */
+
+static int action_stash_exec(bContext *C, wmOperator *op)
+{
+ SpaceAction *saction = (SpaceAction *)CTX_wm_space_data(C);
+ AnimData *adt = ED_actedit_animdata_from_context(C);
+
+ /* Perform stashing operation */
+ if (adt) {
+ /* don't do anything if this action is empty... */
+ if (action_has_motion(adt->action) == 0) {
+ /* action may not be suitable... */
+ BKE_report(op->reports, RPT_WARNING, "Action must have at least one keyframe or F-Modifier");
+ return OPERATOR_CANCELLED;
+ }
+ else {
+ /* stash the action */
+ if (BKE_nla_action_stash(adt)) {
+ /* The stash operation will remove the user already,
+ * so the flushing step later shouldn't double up
+ * the usercount fixes. Hence, we must unset this ref
+ * first before setting the new action.
+ */
+ saction->action = NULL;
+ }
+ else {
+ /* action has already been added - simply warn about this, and clear */
+ BKE_report(op->reports, RPT_ERROR, "Action has already been stashed");
+ }
+
+ /* clear action refs from editor, and then also the backing data (not necessary) */
+ actedit_change_action(C, NULL);
+ }
+ }
+
+ /* Send notifiers that stuff has changed */
+ WM_event_add_notifier(C, NC_ANIMATION | ND_NLA_ACTCHANGE, NULL);
+ return OPERATOR_FINISHED;
+}
+
+void ACTION_OT_stash(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Stash Action";
+ ot->idname = "ACTION_OT_stash";
+ ot->description = "Store this action in the NLA stack as a non-contributing strip for later use";
+
+ /* callbacks */
+ ot->exec = action_stash_exec;
+ ot->poll = action_pushdown_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ ot->prop = RNA_def_boolean(ot->srna, "create_new", true, "Create New Action",
+ "Create a new action once the existing one has been safely stored");
+}
+
+/* ----------------- */
+
+/* Criteria:
+ * 1) There must be an dopesheet/action editor, and it must be in a mode which uses actions
+ * 2) The associated AnimData block must not be in tweakmode
+ */
+static int action_stash_create_poll(bContext *C)
+{
+ if (ED_operator_action_active(C)) {
+ AnimData *adt = ED_actedit_animdata_from_context(C);
+
+ /* Check tweakmode is off (as you don't want to be tampering with the action in that case) */
+ /* NOTE: unlike for pushdown, this operator needs to be run when creating an action from nothing... */
+ if (adt) {
+ if (!(adt->flag & ADT_NLA_EDIT_ON))
+ return true;
+ }
+ else {
+ /* There may not be any action/animdata yet, so, just fallback to the global setting
+ * (which may not be totally valid yet if the action editor was used and things are
+ * now in an inconsistent state)
+ */
+ SpaceAction *saction = (SpaceAction *)CTX_wm_space_data(C);
+ Scene *scene = CTX_data_scene(C);
+
+ if (!(scene->flag & SCE_NLA_EDIT_ON)) {
+ /* For now, actions are only for the active object, and on object and shapekey levels... */
+ return ELEM(saction->mode, SACTCONT_ACTION, SACTCONT_SHAPEKEY);
+ }
+ }
+ }
+
+ /* something failed... */
+ return false;
+}
+
+static int action_stash_create_exec(bContext *C, wmOperator *op)
+{
+ SpaceAction *saction = (SpaceAction *)CTX_wm_space_data(C);
+ AnimData *adt = ED_actedit_animdata_from_context(C);
+
+ /* Check for no action... */
+ if (saction->action == NULL) {
+ /* just create a new action */
+ bAction *action = action_create_new(C, NULL);
+ actedit_change_action(C, action);
+ }
+ else if (adt) {
+ /* Perform stashing operation */
+ if (action_has_motion(adt->action) == 0) {
+ /* don't do anything if this action is empty... */
+ BKE_report(op->reports, RPT_WARNING, "Action must have at least one keyframe or F-Modifier");
+ return OPERATOR_CANCELLED;
+ }
+ else {
+ /* stash the action */
+ if (BKE_nla_action_stash(adt)) {
+ bAction *new_action = NULL;
+
+ /* create new action not based on the old one (since the "new" operator already does that) */
+ new_action = action_create_new(C, NULL);
+
+ /* The stash operation will remove the user already,
+ * so the flushing step later shouldn't double up
+ * the usercount fixes. Hence, we must unset this ref
+ * first before setting the new action.
+ */
+ saction->action = NULL;
+ actedit_change_action(C, new_action);
+ }
+ else {
+ /* action has already been added - simply warn about this, and clear */
+ BKE_report(op->reports, RPT_ERROR, "Action has already been stashed");
+ actedit_change_action(C, NULL);
+ }
+ }
+ }
+
+ /* Send notifiers that stuff has changed */
+ WM_event_add_notifier(C, NC_ANIMATION | ND_NLA_ACTCHANGE, NULL);
+ return OPERATOR_FINISHED;
+}
+
+void ACTION_OT_stash_and_create(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Stash Action";
+ ot->idname = "ACTION_OT_stash_and_create";
+ ot->description = "Store this action in the NLA stack as a non-contributing strip for later use, and create a new action";
+
+ /* callbacks */
+ ot->exec = action_stash_create_exec;
+ ot->poll = action_stash_create_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+/* ************************************************************************** */
+/* ACTION UNLINK */
+
+/* ******************* Action Unlink Operator ******************** */
+/* We use a custom unlink operator here, as there are some technicalities which need special care:
+ * 1) When in Tweak Mode, it shouldn't be possible to unlink the active action,
+ * or else, everything turns to custard.
+ * 2) If the Action doesn't have any other users, the user should at least get
+ * a warning that it is going to get lost.
+ * 3) We need a convenient way to exit Tweak Mode from the Action Editor
+ */
+
+void ED_animedit_unlink_action(bContext *C, ID *id, AnimData *adt, bAction *act, ReportList *reports, bool force_delete)
+{
+ ScrArea *sa = CTX_wm_area(C);
+
+ /* If the old action only has a single user (that it's about to lose),
+ * warn user about it
+ *
+ * TODO: Maybe we should just save it for them? But then, there's the problem of
+ * trying to get rid of stuff that's actually unwanted!
+ */
+ if (act->id.us == 1) {
+ BKE_reportf(reports, RPT_WARNING,
+ "Action '%s' will not be saved, create Fake User or Stash in NLA Stack to retain",
+ act->id.name + 2);
+ }
+
+ /* Clear Fake User and remove action stashing strip (if present) */
+ if (force_delete) {
+ /* Remove stashed strip binding this action to this datablock */
+ /* XXX: we cannot unlink it from *OTHER* datablocks that may also be stashing it,
+ * but GE users only seem to use/care about single-object binding for now so this
+ * should be fine
+ */
+ if (adt) {
+ NlaTrack *nlt, *nlt_next;
+ NlaStrip *strip, *nstrip;
+
+ for (nlt = adt->nla_tracks.first; nlt; nlt = nlt_next) {
+ nlt_next = nlt->next;
+
+ if (strstr(nlt->name, DATA_("[Action Stash]"))) {
+ for (strip = nlt->strips.first; strip; strip = nstrip) {
+ nstrip = strip->next;
+
+ if (strip->act == act) {
+ /* Remove this strip, and the track too if it doesn't have anything else */
+ free_nlastrip(&nlt->strips, strip);
+
+ if (nlt->strips.first == NULL) {
+ BLI_assert(nstrip == NULL);
+ free_nlatrack(&adt->nla_tracks, nlt);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /* Clear Fake User */
+ if (act->id.flag & LIB_FAKEUSER) {
+ act->id.flag &= ~LIB_FAKEUSER;
+ act->id.us--;
+ }
+ }
+
+ /* If in Tweak Mode, don't unlink. Instead, this
+ * becomes a shortcut to exit Tweak Mode instead
+ */
+ if ((adt) && (adt->flag & ADT_NLA_EDIT_ON)) {
+ /* Exit Tweak Mode */
+ BKE_nla_tweakmode_exit(adt);
+
+ /* Flush this to the Action Editor (if that's where this change was initiated) */
+ if (sa->spacetype == SPACE_ACTION) {
+ actedit_change_action(C, NULL);
+ }
+ }
+ else {
+ /* Unlink normally - Setting it to NULL should be enough to get the old one unlinked */
+ if (sa->spacetype == SPACE_ACTION) {
+ /* clear action editor -> action */
+ actedit_change_action(C, NULL);
+ }
+ else {
+ /* clear AnimData -> action */
+ PointerRNA ptr;
+ PropertyRNA *prop;
+
+ /* create AnimData RNA pointers */
+ RNA_pointer_create(id, &RNA_AnimData, adt, &ptr);
+ prop = RNA_struct_find_property(&ptr, "action");
+
+ /* clear... */
+ RNA_property_pointer_set(&ptr, prop, PointerRNA_NULL);
+ RNA_property_update(C, &ptr, prop);
+ }
+ }
+}
+
+/* -------------------------- */
+
+static int action_unlink_poll(bContext *C)
+{
+ if (ED_operator_action_active(C)) {
+ SpaceAction *saction = (SpaceAction *)CTX_wm_space_data(C);
+ AnimData *adt = ED_actedit_animdata_from_context(C);
+
+ /* Only when there's an active action, in the right modes... */
+ if (saction->action && adt)
+ return true;
+ }
+
+ /* something failed... */
+ return false;
+}
+
+static int action_unlink_exec(bContext *C, wmOperator *op)
+{
+ AnimData *adt = ED_actedit_animdata_from_context(C);
+ bool force_delete = RNA_boolean_get(op->ptr, "force_delete");
+
+ if (adt && adt->action) {
+ ED_animedit_unlink_action(C, NULL, adt, adt->action, op->reports, force_delete);
+ }
+
+ return OPERATOR_FINISHED;
+}
+
+static int action_unlink_invoke(bContext *C, wmOperator *op, const wmEvent *evt)
+{
+ /* NOTE: this is hardcoded to match the behaviour for the unlink button (in interface_templates.c) */
+ RNA_boolean_set(op->ptr, "force_delete", evt->shift != 0);
+ return action_unlink_exec(C, op);
+}
+
+void ACTION_OT_unlink(wmOperatorType *ot)
+{
+ PropertyRNA *prop;
+
+ /* identifiers */
+ ot->name = "Unlink Action";
+ ot->idname = "ACTION_OT_unlink";
+ ot->description = "Unlink this action from the active action slot (and/or exit Tweak Mode)";
+
+ /* callbacks */
+ ot->invoke = action_unlink_invoke;
+ ot->exec = action_unlink_exec;
+ ot->poll = action_unlink_poll;
+
+ /* properties */
+ prop = RNA_def_boolean(ot->srna, "force_delete", false, "Force Delete",
+ "Clear Fake User and remove copy stashed in this datablock's NLA stack");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+}
+
+/* ************************************************************************** */
+/* ACTION BROWSING */
+
+/* Try to find NLA Strip to use for action layer up/down tool */
+static NlaStrip *action_layer_get_nlastrip(ListBase *strips, float ctime)
+{
+ NlaStrip *strip;
+
+ for (strip = strips->first; strip; strip = strip->next) {
+ /* Can we use this? */
+ if (IN_RANGE_INCL(ctime, strip->start, strip->end)) {
+ /* in range - use this one */
+ return strip;
+ }
+ else if ((ctime < strip->start) && (strip->prev == NULL)) {
+ /* before first - use this one */
+ return strip;
+ }
+ else if ((ctime > strip->end) && (strip->next == NULL)) {
+ /* after last - use this one */
+ return strip;
+ }
+ }
+
+ /* nothing suitable found... */
+ return NULL;
+}
+
+/* Switch NLA Strips/Actions */
+static void action_layer_switch_strip(AnimData *adt,
+ NlaTrack *old_track, NlaStrip *old_strip,
+ NlaTrack *nlt, NlaStrip *strip)
+{
+ /* Exit tweakmode on old strip
+ * NOTE: We need to manually clear this stuff ourselves, as tweakmode exit doesn't do it
+ */
+ BKE_nla_tweakmode_exit(adt);
+
+ if (old_strip) {
+ old_strip->flag &= ~(NLASTRIP_FLAG_ACTIVE | NLASTRIP_FLAG_SELECT);
+ }
+ if (old_track) {
+ old_track->flag &= ~(NLATRACK_ACTIVE | NLATRACK_SELECTED);
+ }
+
+ /* Make this one the active one instead */
+ strip->flag |= (NLASTRIP_FLAG_ACTIVE | NLASTRIP_FLAG_SELECT);
+ nlt->flag |= NLATRACK_ACTIVE;
+
+ /* Copy over "solo" flag - This is useful for stashed actions... */
+ if (old_track) {
+ if (old_track->flag & NLATRACK_SOLO) {
+ old_track->flag &= ~NLATRACK_SOLO;
+ nlt->flag |= NLATRACK_SOLO;
+ }
+ }
+ else {
+ /* NLA muting <==> Solo Tracks */
+ if (adt->flag & ADT_NLA_EVAL_OFF) {
+ /* disable NLA muting */
+ adt->flag &= ~ADT_NLA_EVAL_OFF;
+
+ /* mark this track as being solo */
+ adt->flag |= ADT_NLA_SOLO_TRACK;
+ nlt->flag |= NLATRACK_SOLO;
+
+ // TODO: Needs restpose flushing (when we get reference track)
+ }
+ }
+
+ /* Enter tweakmode again - hopefully we're now "it" */
+ BKE_nla_tweakmode_enter(adt);
+ BLI_assert(adt->actstrip == strip);
+}
+
+/* ********************** One Layer Up Operator ************************** */
+
+static int action_layer_next_poll(bContext *C)
+{
+ /* Action Editor's action editing modes only */
+ if (ED_operator_action_active(C)) {
+ AnimData *adt = ED_actedit_animdata_from_context(C);
+ if (adt) {
+ /* only allow if we're in tweakmode, and there's something above us... */
+ if (adt->flag & ADT_NLA_EDIT_ON) {
+ /* We need to check if there are any tracks above the active one
+ * since the track the action comes from is not stored in AnimData
+ */
+ if (adt->nla_tracks.last) {
+ NlaTrack *nlt = (NlaTrack *)adt->nla_tracks.last;
+
+ if (nlt->flag & NLATRACK_DISABLED) {
+ /* A disabled track will either be the track itself,
+ * or one of the ones above it.
+ *
+ * If this is the top-most one, there is the possibility
+ * that there is no active action. For now, we let this
+ * case return true too, so that there is a natural way
+ * to "move to an empty layer", even though this means
+ * that we won't actually have an action.
+ */
+ // return (adt->tmpact != NULL);
+ return true;
+ }
+ }
+ }
+ }
+ }
+
+ /* something failed... */
+ return false;
+}
+
+static int action_layer_next_exec(bContext *C, wmOperator *op)
+{
+ AnimData *adt = ED_actedit_animdata_from_context(C);
+ NlaTrack *act_track;
+
+ Scene *scene = CTX_data_scene(C);
+ float ctime = BKE_scene_frame_get(scene);
+
+ /* Get active track */
+ act_track = BKE_nlatrack_find_tweaked(adt);
+
+ if (act_track == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "Could not find current NLA Track");
+ return OPERATOR_CANCELLED;
+ }
+
+ /* Find next action, and hook it up */
+ if (act_track->next) {
+ NlaTrack *nlt;
+
+ /* Find next action to use */
+ for (nlt = act_track->next; nlt; nlt = nlt->next) {
+ NlaStrip *strip = action_layer_get_nlastrip(&nlt->strips, ctime);
+
+ if (strip) {
+ action_layer_switch_strip(adt, act_track, adt->actstrip, nlt, strip);
+ break;
+ }
+ }
+ }
+ else {
+ /* No more actions (strips) - Go back to editing the original active action
+ * NOTE: This will mean exiting tweakmode...
+ */
+ BKE_nla_tweakmode_exit(adt);
+
+ /* Deal with solo flags...
+ * Assume: Solo Track == NLA Muting
+ */
+ if (adt->flag & ADT_NLA_SOLO_TRACK) {
+ /* turn off solo flags on tracks */
+ act_track->flag &= ~NLATRACK_SOLO;
+ adt->flag &= ~ADT_NLA_SOLO_TRACK;
+
+ /* turn on NLA muting (to keep same effect) */
+ adt->flag |= ADT_NLA_EVAL_OFF;
+
+ // TODO: Needs restpose flushing (when we get reference track)
+ }
+ }
+
+ /* Update the action that this editor now uses
+ * NOTE: The calls above have already handled the usercount/animdata side of things
+ */
+ actedit_change_action(C, adt->action);
+ return OPERATOR_FINISHED;
+}
+
+void ACTION_OT_layer_next(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Next Layer";
+ ot->idname = "ACTION_OT_layer_next";
+ ot->description = "Switch to editing action in animation layer above the current action in the NLA Stack";
+
+ /* callbacks */
+ ot->exec = action_layer_next_exec;
+ ot->poll = action_layer_next_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+/* ********************* One Layer Down Operator ************************* */
+
+static int action_layer_prev_poll(bContext *C)
+{
+ /* Action Editor's action editing modes only */
+ if (ED_operator_action_active(C)) {
+ AnimData *adt = ED_actedit_animdata_from_context(C);
+ if (adt) {
+ if (adt->flag & ADT_NLA_EDIT_ON) {
+ /* Tweak Mode: We need to check if there are any tracks below the active one that we can move to */
+ if (adt->nla_tracks.first) {
+ NlaTrack *nlt = (NlaTrack *)adt->nla_tracks.first;
+
+ /* Since the first disabled track is the track being tweaked/edited,
+ * we can simplify things by only checking the first track:
+ * - If it is disabled, this is the track being tweaked,
+ * so there can't be anything below it
+ * - Otherwise, there is at least 1 track below the tweaking
+ * track that we can descend to
+ */
+ if ((nlt->flag & NLATRACK_DISABLED) == 0) {
+ /* not disabled = there are actions below the one being tweaked */
+ return true;
+ }
+ }
+ }
+ else {
+ /* Normal Mode: If there are any tracks, we can try moving to those */
+ return (adt->nla_tracks.first != NULL);
+ }
+ }
+ }
+
+ /* something failed... */
+ return false;
+}
+
+static int action_layer_prev_exec(bContext *C, wmOperator *op)
+{
+ AnimData *adt = ED_actedit_animdata_from_context(C);
+ NlaTrack *act_track;
+ NlaTrack *nlt;
+
+ Scene *scene = CTX_data_scene(C);
+ float ctime = BKE_scene_frame_get(scene);
+
+ /* Sanity Check */
+ if (adt == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "Internal Error: Could not find Animation Data/NLA Stack to use");
+ return OPERATOR_CANCELLED;
+ }
+
+ /* Get active track */
+ act_track = BKE_nlatrack_find_tweaked(adt);
+
+ /* If there is no active track, that means we are using the active action... */
+ if (act_track) {
+ /* Active Track - Start from the one below it */
+ nlt = act_track->prev;
+ }
+ else {
+ /* Active Action - Use the top-most track */
+ nlt = adt->nla_tracks.last;
+ }
+
+ /* Find previous action and hook it up */
+ for (; nlt; nlt = nlt->prev) {
+ NlaStrip *strip = action_layer_get_nlastrip(&nlt->strips, ctime);
+
+ if (strip) {
+ action_layer_switch_strip(adt, act_track, adt->actstrip, nlt, strip);
+ break;
+ }
+ }
+
+ /* Update the action that this editor now uses
+ * NOTE: The calls above have already handled the usercount/animdata side of things
+ */
+ actedit_change_action(C, adt->action);
+ return OPERATOR_FINISHED;
+}
+
+void ACTION_OT_layer_prev(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Previous Layer";
+ ot->idname = "ACTION_OT_layer_prev";
+ ot->description = "Switch to editing action in animation layer below the current action in the NLA Stack";
+
+ /* callbacks */
+ ot->exec = action_layer_prev_exec;
+ ot->poll = action_layer_prev_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+/* ************************************************************************** */
diff --git a/source/blender/editors/space_action/action_draw.c b/source/blender/editors/space_action/action_draw.c
index 335949e8495..10748c2fe15 100644
--- a/source/blender/editors/space_action/action_draw.c
+++ b/source/blender/editors/space_action/action_draw.c
@@ -93,6 +93,8 @@ void draw_channel_names(bContext *C, bAnimContext *ac, ARegion *ar)
/* loop through channels, and set up drawing depending on their type */
{ /* first pass: just the standard GL-drawing for backdrop + text */
+ size_t channel_index = 0;
+
y = (float)ACHANNEL_FIRST;
for (ale = anim_data.first; ale; ale = ale->next) {
@@ -104,15 +106,16 @@ void draw_channel_names(bContext *C, bAnimContext *ac, ARegion *ar)
IN_RANGE(ymaxc, v2d->cur.ymin, v2d->cur.ymax) )
{
/* draw all channels using standard channel-drawing API */
- ANIM_channel_draw(ac, ale, yminc, ymaxc);
+ ANIM_channel_draw(ac, ale, yminc, ymaxc, channel_index);
}
/* adjust y-position for next one */
y -= ACHANNEL_STEP;
+ channel_index++;
}
}
{ /* second pass: widgets */
- uiBlock *block = uiBeginBlock(C, ar, __func__, UI_EMBOSS);
+ uiBlock *block = UI_block_begin(C, ar, __func__, UI_EMBOSS);
size_t channel_index = 0;
y = (float)ACHANNEL_FIRST;
@@ -134,8 +137,8 @@ void draw_channel_names(bContext *C, bAnimContext *ac, ARegion *ar)
channel_index++;
}
- uiEndBlock(C, block);
- uiDrawBlock(C, block);
+ UI_block_end(C, block);
+ UI_block_draw(C, block);
}
/* free tempolary channels */
@@ -210,7 +213,7 @@ void draw_channel_strips(bAnimContext *ac, SpaceAction *saction, ARegion *ar)
if (IN_RANGE(yminc, v2d->cur.ymin, v2d->cur.ymax) ||
IN_RANGE(ymaxc, v2d->cur.ymin, v2d->cur.ymax) )
{
- bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale);
+ const bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale);
int sel = 0;
/* determine if any need to draw channel */
diff --git a/source/blender/editors/space_action/action_edit.c b/source/blender/editors/space_action/action_edit.c
index 091d3fe56b4..e351fb57d9a 100644
--- a/source/blender/editors/space_action/action_edit.c
+++ b/source/blender/editors/space_action/action_edit.c
@@ -40,8 +40,12 @@
#include "BLI_math.h"
#include "BLI_utildefines.h"
+#include "BLT_translation.h"
+
#include "DNA_anim_types.h"
#include "DNA_gpencil_types.h"
+#include "DNA_key_types.h"
+#include "DNA_object_types.h"
#include "DNA_scene_types.h"
#include "DNA_mask_types.h"
@@ -52,6 +56,8 @@
#include "BKE_action.h"
#include "BKE_fcurve.h"
#include "BKE_global.h"
+#include "BKE_library.h"
+#include "BKE_key.h"
#include "BKE_main.h"
#include "BKE_nla.h"
#include "BKE_context.h"
@@ -74,72 +80,6 @@
#include "action_intern.h"
-/* ************************************************************************** */
-/* ACTION MANAGEMENT */
-
-/* ******************** New Action Operator *********************** */
-
-static int act_new_exec(bContext *C, wmOperator *UNUSED(op))
-{
- PointerRNA ptr, idptr;
- PropertyRNA *prop;
-
- /* hook into UI */
- uiIDContextProperty(C, &ptr, &prop);
-
- if (prop) {
- bAction *action = NULL, *oldact = NULL;
- PointerRNA oldptr;
-
- /* create action - the way to do this depends on whether we've got an
- * existing one there already, in which case we make a copy of it
- * (which is useful for "versioning" actions within the same file)
- */
- oldptr = RNA_property_pointer_get(&ptr, prop);
- oldact = (bAction *)oldptr.id.data;
-
- if (oldact && GS(oldact->id.name) == ID_AC) {
- /* make a copy of the existing action */
- action = BKE_action_copy(oldact);
- }
- else {
- Main *bmain = CTX_data_main(C);
-
- /* just make a new (empty) action */
- action = add_empty_action(bmain, "Action");
- }
-
- /* when creating new ID blocks, use is already 1 (fake user),
- * but RNA pointer use also increases user, so this compensates it
- */
- action->id.us--;
-
- RNA_id_pointer_create(&action->id, &idptr);
- RNA_property_pointer_set(&ptr, prop, idptr);
- RNA_property_update(C, &ptr, prop);
- }
-
- /* set notifier that keyframes have changed */
- WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_ADDED, NULL);
-
- return OPERATOR_FINISHED;
-}
-
-void ACTION_OT_new(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "New Action";
- ot->idname = "ACTION_OT_new";
- ot->description = "Create new action";
-
- /* api callbacks */
- ot->exec = act_new_exec;
- /* NOTE: this is used in the NLA too... */
- //ot->poll = ED_operator_action_active;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-}
/* ************************************************************************** */
/* POSE MARKERS STUFF */
@@ -283,7 +223,7 @@ static bool get_keyframe_extents(bAnimContext *ac, float *min, float *max, const
float tmin, tmax;
/* get range and apply necessary scaling before processing */
- if (calc_fcurve_range(fcu, &tmin, &tmax, onlySel, true)) {
+ if (calc_fcurve_range(fcu, &tmin, &tmax, onlySel, false)) {
if (adt) {
tmin = BKE_nla_tweakedit_remap(adt, tmin, NLATIME_CONVERT_MAP);
@@ -297,7 +237,7 @@ static bool get_keyframe_extents(bAnimContext *ac, float *min, float *max, const
}
}
}
-
+
/* free memory */
ANIM_animdata_freelist(&anim_data);
}
@@ -335,8 +275,12 @@ static int actkeys_previewrange_exec(bContext *C, wmOperator *UNUSED(op))
/* set the range directly */
get_keyframe_extents(&ac, &min, &max, false);
scene->r.flag |= SCER_PRV_RANGE;
- scene->r.psfra = iroundf(min);
- scene->r.pefra = iroundf(max);
+ scene->r.psfra = floorf(min);
+ scene->r.pefra = ceilf(max);
+
+ if (scene->r.psfra == scene->r.pefra) {
+ scene->r.pefra = scene->r.psfra + 1;
+ }
/* set notifier that things have changed */
// XXX err... there's nothing for frame ranges yet, but this should do fine too
@@ -386,7 +330,7 @@ static bool actkeys_channels_get_selected_extents(bAnimContext *ac, float *min,
y = (float)ACHANNEL_FIRST;
for (ale = anim_data.first; ale; ale = ale->next) {
- bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale);
+ const bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale);
/* must be selected... */
if (acf && acf->has_setting(ac, ale, ACHANNEL_SETTING_SELECT) &&
@@ -485,7 +429,15 @@ static int actkeys_viewsel_exec(bContext *C, wmOperator *UNUSED(op))
/* only selected */
return actkeys_viewall(C, true);
}
-
+
+static int actkeys_view_frame_exec(bContext *C, wmOperator *op)
+{
+ const int smooth_viewtx = WM_operator_smooth_viewtx_get(op);
+ ANIM_center_frame(C, smooth_viewtx);
+
+ return OPERATOR_FINISHED;
+}
+
void ACTION_OT_view_all(wmOperatorType *ot)
{
/* identifiers */
@@ -516,6 +468,21 @@ void ACTION_OT_view_selected(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
+void ACTION_OT_view_frame(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "View Frame";
+ ot->idname = "ACTION_OT_view_frame";
+ ot->description = "Reset viewable area to show range around current frame";
+
+ /* api callbacks */
+ ot->exec = actkeys_view_frame_exec;
+ ot->poll = ED_operator_action_active; /* XXX: unchecked poll to get fsamples working too, but makes modifier damage trickier... */
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
/* ************************************************************************** */
/* GENERAL STUFF */
@@ -545,7 +512,7 @@ static short copy_action_keys(bAnimContext *ac)
static short paste_action_keys(bAnimContext *ac,
- const eKeyPasteOffset offset_mode, const eKeyMergeMode merge_mode)
+ const eKeyPasteOffset offset_mode, const eKeyMergeMode merge_mode, bool flip)
{
ListBase anim_data = {NULL, NULL};
int filter, ok = 0;
@@ -562,7 +529,7 @@ static short paste_action_keys(bAnimContext *ac,
ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
/* paste keyframes */
- ok = paste_animedit_keys(ac, &anim_data, offset_mode, merge_mode);
+ ok = paste_animedit_keys(ac, &anim_data, offset_mode, merge_mode, flip);
/* clean up */
ANIM_animdata_freelist(&anim_data);
@@ -622,6 +589,7 @@ static int actkeys_paste_exec(bContext *C, wmOperator *op)
const eKeyPasteOffset offset_mode = RNA_enum_get(op->ptr, "offset");
const eKeyMergeMode merge_mode = RNA_enum_get(op->ptr, "merge");
+ const bool flipped = RNA_boolean_get(op->ptr, "flipped");
/* get editor data */
if (ANIM_animdata_get_context(C, &ac) == 0)
@@ -638,7 +606,7 @@ static int actkeys_paste_exec(bContext *C, wmOperator *op)
}
else {
/* non-zero return means an error occurred while trying to paste */
- if (paste_action_keys(&ac, offset_mode, merge_mode)) {
+ if (paste_action_keys(&ac, offset_mode, merge_mode, flipped)) {
return OPERATOR_CANCELLED;
}
}
@@ -651,6 +619,7 @@ static int actkeys_paste_exec(bContext *C, wmOperator *op)
void ACTION_OT_paste(wmOperatorType *ot)
{
+ PropertyRNA *prop;
/* identifiers */
ot->name = "Paste Keyframes";
ot->idname = "ACTION_OT_paste";
@@ -667,6 +636,8 @@ void ACTION_OT_paste(wmOperatorType *ot)
/* props */
RNA_def_enum(ot->srna, "offset", keyframe_paste_offset_items, KEYFRAME_PASTE_OFFSET_CFRA_START, "Offset", "Paste time offset of keys");
RNA_def_enum(ot->srna, "merge", keyframe_paste_merge_items, KEYFRAME_PASTE_MERGE_MIX, "Type", "Method of merging pasted keys and existing");
+ prop = RNA_def_boolean(ot->srna, "flipped", false, "Flipped", "Paste keyframes from mirrored bones if they exist");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
/* ******************** Insert Keyframes Operator ************************* */
@@ -712,8 +683,13 @@ static void insert_action_keys(bAnimContext *ac, short mode)
else
cfra = (float)CFRA;
- /* if there's an id */
- if (ale->id)
+ /* read value from property the F-Curve represents, or from the curve only?
+ * - ale->id != NULL: Typically, this means that we have enough info to try resolving the path
+ * - ale->owner != NULL: If this is set, then the path may not be resolvable from the ID alone,
+ * so it's easier for now to just read the F-Curve directly.
+ * (TODO: add the full-blown PointerRNA relative parsing case here...)
+ */
+ if (ale->id && !ale->owner)
insert_keyframe(reports, ale->id, NULL, ((fcu->grp) ? (fcu->grp->name) : (NULL)), fcu->rna_path, fcu->array_index, cfra, flag);
else
insert_vert_fcurve(fcu, cfra, fcu->curval, 0);
@@ -786,7 +762,7 @@ static void duplicate_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_FCURVE)
+ if (ELEM(ale->type, ANIMTYPE_FCURVE, ANIMTYPE_NLACURVE))
duplicate_fcurve_keys((FCurve *)ale->key_data);
else if (ale->type == ANIMTYPE_GPLAYER)
ED_gplayer_frames_duplicate((bGPDlayer *)ale->data);
@@ -820,13 +796,6 @@ static int actkeys_duplicate_exec(bContext *C, wmOperator *UNUSED(op))
return OPERATOR_FINISHED;
}
-
-static int actkeys_duplicate_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
-{
- actkeys_duplicate_exec(C, op);
-
- return OPERATOR_FINISHED;
-}
void ACTION_OT_duplicate(wmOperatorType *ot)
{
@@ -836,7 +805,6 @@ void ACTION_OT_duplicate(wmOperatorType *ot)
ot->description = "Make a copy of all selected keyframes";
/* api callbacks */
- ot->invoke = actkeys_duplicate_invoke;
ot->exec = actkeys_duplicate_exec;
ot->poll = ED_operator_action_active;
@@ -934,7 +902,7 @@ void ACTION_OT_delete(wmOperatorType *ot)
/* ******************** Clean Keyframes Operator ************************* */
-static void clean_action_keys(bAnimContext *ac, float thresh)
+static void clean_action_keys(bAnimContext *ac, float thresh, bool clean_chan)
{
ListBase anim_data = {NULL, NULL};
bAnimListElem *ale;
@@ -946,7 +914,7 @@ static void clean_action_keys(bAnimContext *ac, float thresh)
/* loop through filtered data and clean curves */
for (ale = anim_data.first; ale; ale = ale->next) {
- clean_fcurve((FCurve *)ale->key_data, thresh);
+ clean_fcurve(ac, ale, thresh, clean_chan);
ale->update |= ANIM_UPDATE_DEFAULT;
}
@@ -961,18 +929,23 @@ static int actkeys_clean_exec(bContext *C, wmOperator *op)
{
bAnimContext ac;
float thresh;
+ bool clean_chan;
/* get editor data */
if (ANIM_animdata_get_context(C, &ac) == 0)
return OPERATOR_CANCELLED;
- if (ELEM(ac.datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK))
+
+ if (ELEM(ac.datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK)) {
+ BKE_report(op->reports, RPT_ERROR, "Not implemented");
return OPERATOR_PASS_THROUGH;
+ }
/* get cleaning threshold */
thresh = RNA_float_get(op->ptr, "threshold");
+ clean_chan = RNA_boolean_get(op->ptr, "channels");
/* clean keyframes */
- clean_action_keys(&ac, thresh);
+ clean_action_keys(&ac, thresh, clean_chan);
/* set notifier that keyframes have changed */
WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL);
@@ -997,6 +970,7 @@ void ACTION_OT_clean(wmOperatorType *ot)
/* properties */
ot->prop = RNA_def_float(ot->srna, "threshold", 0.001f, 0.0f, FLT_MAX, "Threshold", "", 0.0f, 1000.0f);
+ RNA_def_boolean(ot->srna, "channels", false, "Channels", "");
}
/* ******************** Sample Keyframes Operator *********************** */
@@ -1025,15 +999,18 @@ static void sample_action_keys(bAnimContext *ac)
/* ------------------- */
-static int actkeys_sample_exec(bContext *C, wmOperator *UNUSED(op))
+static int actkeys_sample_exec(bContext *C, wmOperator *op)
{
bAnimContext ac;
/* get editor data */
if (ANIM_animdata_get_context(C, &ac) == 0)
return OPERATOR_CANCELLED;
- if (ELEM(ac.datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK))
+
+ if (ELEM(ac.datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK)) {
+ BKE_report(op->reports, RPT_ERROR, "Not implemented");
return OPERATOR_PASS_THROUGH;
+ }
/* sample keyframes */
sample_action_keys(&ac);
@@ -1138,8 +1115,11 @@ static int actkeys_expo_exec(bContext *C, wmOperator *op)
/* get editor data */
if (ANIM_animdata_get_context(C, &ac) == 0)
return OPERATOR_CANCELLED;
- if (ELEM(ac.datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK))
+
+ if (ELEM(ac.datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK)) {
+ BKE_report(op->reports, RPT_ERROR, "Not implemented");
return OPERATOR_PASS_THROUGH;
+ }
/* get handle setting mode */
mode = RNA_enum_get(op->ptr, "type");
@@ -1209,8 +1189,11 @@ static int actkeys_ipo_exec(bContext *C, wmOperator *op)
/* get editor data */
if (ANIM_animdata_get_context(C, &ac) == 0)
return OPERATOR_CANCELLED;
- if (ELEM(ac.datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK))
+
+ if (ELEM(ac.datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK)) {
+ BKE_report(op->reports, RPT_ERROR, "Not implemented");
return OPERATOR_PASS_THROUGH;
+ }
/* get handle setting mode */
mode = RNA_enum_get(op->ptr, "type");
@@ -1288,8 +1271,11 @@ static int actkeys_handletype_exec(bContext *C, wmOperator *op)
/* get editor data */
if (ANIM_animdata_get_context(C, &ac) == 0)
return OPERATOR_CANCELLED;
- if (ELEM(ac.datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK))
+
+ if (ELEM(ac.datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK)) {
+ BKE_report(op->reports, RPT_ERROR, "Not implemented");
return OPERATOR_PASS_THROUGH;
+ }
/* get handle setting mode */
mode = RNA_enum_get(op->ptr, "type");
@@ -1324,7 +1310,7 @@ void ACTION_OT_handle_type(wmOperatorType *ot)
/* ******************** Set Keyframe-Type Operator *********************** */
-/* this function is responsible for setting interpolation mode for keyframes */
+/* this function is responsible for setting keyframe type for keyframes */
static void setkeytype_action_keys(bAnimContext *ac, short mode)
{
ListBase anim_data = {NULL, NULL};
@@ -1349,6 +1335,29 @@ static void setkeytype_action_keys(bAnimContext *ac, short mode)
ANIM_animdata_freelist(&anim_data);
}
+/* this function is responsible for setting the keyframe type for Grease Pencil frames */
+static void setkeytype_gpencil_keys(bAnimContext *ac, short mode)
+{
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+
+ /* filter data */
+ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_NODUPLIS);
+ ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+
+ /* loop through each layer */
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ if (ale->type == ANIMTYPE_GPLAYER) {
+ ED_gplayer_frames_keytype_set(ale->data, mode);
+ ale->update |= ANIM_UPDATE_DEPS;
+ }
+ }
+
+ ANIM_animdata_update(ac, &anim_data);
+ ANIM_animdata_freelist(&anim_data);
+}
+
/* ------------------- */
static int actkeys_keytype_exec(bContext *C, wmOperator *op)
@@ -1359,14 +1368,22 @@ static int actkeys_keytype_exec(bContext *C, wmOperator *op)
/* get editor data */
if (ANIM_animdata_get_context(C, &ac) == 0)
return OPERATOR_CANCELLED;
- if (ELEM(ac.datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK))
+
+ if (ac.datatype == ANIMCONT_MASK) {
+ BKE_report(op->reports, RPT_ERROR, "Not implemented for Masks");
return OPERATOR_PASS_THROUGH;
+ }
/* get handle setting mode */
mode = RNA_enum_get(op->ptr, "type");
/* set handle type */
- setkeytype_action_keys(&ac, mode);
+ if (ac.datatype == ANIMCONT_GPENCIL) {
+ setkeytype_gpencil_keys(&ac, mode);
+ }
+ else {
+ setkeytype_action_keys(&ac, mode);
+ }
/* set notifier that keyframe properties have changed */
WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME_PROP, NULL);
diff --git a/source/blender/editors/space_action/action_intern.h b/source/blender/editors/space_action/action_intern.h
index 8f39a38157a..17f1f404225 100644
--- a/source/blender/editors/space_action/action_intern.h
+++ b/source/blender/editors/space_action/action_intern.h
@@ -35,10 +35,7 @@ struct bContext;
struct bAnimContext;
struct SpaceAction;
struct ARegion;
-struct wmWindowManager;
struct wmOperatorType;
-struct ActKeysInc;
-struct bAnimListElem;
/* internal exports only */
@@ -80,6 +77,7 @@ enum eActKeys_ColumnSelect_Mode {
void ACTION_OT_previewrange_set(struct wmOperatorType *ot);
void ACTION_OT_view_all(struct wmOperatorType *ot);
void ACTION_OT_view_selected(struct wmOperatorType *ot);
+void ACTION_OT_view_frame(struct wmOperatorType *ot);
void ACTION_OT_copy(struct wmOperatorType *ot);
void ACTION_OT_paste(struct wmOperatorType *ot);
@@ -101,6 +99,14 @@ void ACTION_OT_snap(struct wmOperatorType *ot);
void ACTION_OT_mirror(struct wmOperatorType *ot);
void ACTION_OT_new(struct wmOperatorType *ot);
+void ACTION_OT_unlink(struct wmOperatorType *ot);
+
+void ACTION_OT_push_down(struct wmOperatorType *ot);
+void ACTION_OT_stash(struct wmOperatorType *ot);
+void ACTION_OT_stash_and_create(struct wmOperatorType *ot);
+
+void ACTION_OT_layer_next(struct wmOperatorType *ot);
+void ACTION_OT_layer_prev(struct wmOperatorType *ot);
void ACTION_OT_markers_make_local(struct wmOperatorType *ot);
diff --git a/source/blender/editors/space_action/action_ops.c b/source/blender/editors/space_action/action_ops.c
index b99419dec20..59b147c6f6c 100644
--- a/source/blender/editors/space_action/action_ops.c
+++ b/source/blender/editors/space_action/action_ops.c
@@ -35,7 +35,6 @@
#include "DNA_space_types.h"
-#include "BLI_utildefines.h"
#include "ED_anim_api.h"
#include "ED_markers.h"
@@ -44,7 +43,6 @@
#include "action_intern.h"
#include "RNA_access.h"
-#include "RNA_define.h"
#include "WM_api.h"
#include "WM_types.h"
@@ -79,12 +77,22 @@ void action_operatortypes(void)
WM_operatortype_append(ACTION_OT_keyframe_insert);
WM_operatortype_append(ACTION_OT_copy);
WM_operatortype_append(ACTION_OT_paste);
+
WM_operatortype_append(ACTION_OT_new);
+ WM_operatortype_append(ACTION_OT_unlink);
+
+ WM_operatortype_append(ACTION_OT_push_down);
+ WM_operatortype_append(ACTION_OT_stash);
+ WM_operatortype_append(ACTION_OT_stash_and_create);
+
+ WM_operatortype_append(ACTION_OT_layer_next);
+ WM_operatortype_append(ACTION_OT_layer_prev);
WM_operatortype_append(ACTION_OT_previewrange_set);
WM_operatortype_append(ACTION_OT_view_all);
WM_operatortype_append(ACTION_OT_view_selected);
-
+ WM_operatortype_append(ACTION_OT_view_frame);
+
WM_operatortype_append(ACTION_OT_markers_make_local);
}
@@ -99,6 +107,7 @@ void ED_operatormacros_action(void)
WM_operatortype_macro_define(ot, "ACTION_OT_duplicate");
otmacro = WM_operatortype_macro_define(ot, "TRANSFORM_OT_transform");
RNA_enum_set(otmacro->ptr, "mode", TFM_TIME_DUPLICATE);
+ RNA_enum_set(otmacro->ptr, "proportional", PROP_EDIT_OFF);
}
/* ************************** registration - keymaps **********************************/
@@ -195,11 +204,10 @@ static void action_keymap_keyframes(wmKeyConfig *keyconf, wmKeyMap *keymap)
WM_keymap_add_item(keymap, "ACTION_OT_keyframe_type", RKEY, KM_PRESS, 0, 0);
/* destructive */
- WM_keymap_add_item(keymap, "ACTION_OT_clean", OKEY, KM_PRESS, 0, 0);
WM_keymap_add_item(keymap, "ACTION_OT_sample", OKEY, KM_PRESS, KM_SHIFT, 0);
- WM_keymap_add_item(keymap, "ACTION_OT_delete", XKEY, KM_PRESS, 0, 0);
- WM_keymap_add_item(keymap, "ACTION_OT_delete", DELKEY, KM_PRESS, 0, 0);
+ WM_keymap_add_menu(keymap, "DOPESHEET_MT_delete", XKEY, KM_PRESS, 0, 0);
+ WM_keymap_add_menu(keymap, "DOPESHEET_MT_delete", DELKEY, KM_PRESS, 0, 0);
WM_keymap_add_item(keymap, "ACTION_OT_duplicate_move", DKEY, KM_PRESS, KM_SHIFT, 0);
WM_keymap_add_item(keymap, "ACTION_OT_keyframe_insert", IKEY, KM_PRESS, 0, 0);
@@ -207,9 +215,13 @@ static void action_keymap_keyframes(wmKeyConfig *keyconf, wmKeyMap *keymap)
/* copy/paste */
WM_keymap_add_item(keymap, "ACTION_OT_copy", CKEY, KM_PRESS, KM_CTRL, 0);
WM_keymap_add_item(keymap, "ACTION_OT_paste", VKEY, KM_PRESS, KM_CTRL, 0);
+ kmi = WM_keymap_add_item(keymap, "ACTION_OT_paste", VKEY, KM_PRESS, KM_CTRL | KM_SHIFT, 0);
+ RNA_boolean_set(kmi->ptr, "flipped", true);
#ifdef __APPLE__
WM_keymap_add_item(keymap, "ACTION_OT_copy", CKEY, KM_PRESS, KM_OSKEY, 0);
WM_keymap_add_item(keymap, "ACTION_OT_paste", VKEY, KM_PRESS, KM_OSKEY, 0);
+ kmi = WM_keymap_add_item(keymap, "ACTION_OT_paste", VKEY, KM_PRESS, KM_OSKEY | KM_SHIFT, 0);
+ RNA_boolean_set(kmi->ptr, "flipped", true);
#endif
/* auto-set range */
@@ -217,6 +229,8 @@ static void action_keymap_keyframes(wmKeyConfig *keyconf, wmKeyMap *keymap)
WM_keymap_add_item(keymap, "ACTION_OT_view_all", HOMEKEY, KM_PRESS, 0, 0);
WM_keymap_add_item(keymap, "ACTION_OT_view_all", NDOF_BUTTON_FIT, KM_PRESS, 0, 0);
WM_keymap_add_item(keymap, "ACTION_OT_view_selected", PADPERIOD, KM_PRESS, 0, 0);
+ WM_keymap_add_item(keymap, "ACTION_OT_view_frame", PAD0, KM_PRESS, 0, 0);
+
/* animation module */
/* channels list
@@ -230,6 +244,9 @@ static void action_keymap_keyframes(wmKeyConfig *keyconf, wmKeyMap *keymap)
/* transform system */
transform_keymap_for_space(keyconf, keymap, SPACE_ACTION);
+ kmi = WM_keymap_add_item(keymap, "WM_OT_context_toggle", OKEY, KM_PRESS, 0, 0);
+ RNA_string_set(kmi->ptr, "data_path", "tool_settings.use_proportional_action");
+
/* special markers hotkeys for anim editors: see note in definition of this function */
ED_marker_keymap_animedit_conflictfree(keymap);
}
diff --git a/source/blender/editors/space_action/action_select.c b/source/blender/editors/space_action/action_select.c
index ddfca98a119..3c9c88a0ae6 100644
--- a/source/blender/editors/space_action/action_select.c
+++ b/source/blender/editors/space_action/action_select.c
@@ -632,7 +632,7 @@ void ACTION_OT_select_linked(wmOperatorType *ot)
ot->poll = ED_operator_action_active;
/* flags */
- ot->flag = OPTYPE_REGISTER /*|OPTYPE_UNDO*/;
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/* ******************** Select More/Less Operators *********************** */
@@ -709,7 +709,7 @@ void ACTION_OT_select_more(wmOperatorType *ot)
ot->poll = ED_operator_action_active;
/* flags */
- ot->flag = OPTYPE_REGISTER /*|OPTYPE_UNDO*/;
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/* ----------------- */
@@ -743,7 +743,7 @@ void ACTION_OT_select_less(wmOperatorType *ot)
ot->poll = ED_operator_action_active;
/* flags */
- ot->flag = OPTYPE_REGISTER /*|OPTYPE_UNDO*/;
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/* ******************** Select Left/Right Operator ************************* */
@@ -1221,11 +1221,11 @@ static void mouse_action_keys(bAnimContext *ac, const int mval[2], short select_
agrp->flag |= AGRP_SELECTED;
ANIM_set_active_channel(ac, ac->data, ac->datatype, filter, agrp, ANIMTYPE_GROUP);
}
- else if (ale->type == ANIMTYPE_FCURVE) {
+ else if (ELEM(ale->type, ANIMTYPE_FCURVE, ANIMTYPE_NLACURVE)) {
FCurve *fcu = ale->data;
fcu->flag |= FCURVE_SELECTED;
- ANIM_set_active_channel(ac, ac->data, ac->datatype, filter, fcu, ANIMTYPE_FCURVE);
+ ANIM_set_active_channel(ac, ac->data, ac->datatype, filter, fcu, ale->type);
}
}
}
diff --git a/source/blender/editors/space_action/space_action.c b/source/blender/editors/space_action/space_action.c
index 7ca8968a705..5d0b34a2e0c 100644
--- a/source/blender/editors/space_action/space_action.c
+++ b/source/blender/editors/space_action/space_action.c
@@ -197,8 +197,8 @@ static void action_main_area_draw(const bContext *C, ARegion *ar)
/* markers */
UI_view2d_view_orthoSpecial(ar, v2d, 1);
- flag = (ac.markers && (ac.markers != &ac.scene->markers)) ? DRAW_MARKERS_LOCAL : 0;
- draw_markers_time(C, flag);
+ flag = ((ac.markers && (ac.markers != &ac.scene->markers)) ? DRAW_MARKERS_LOCAL : 0) | DRAW_MARKERS_MARGIN;
+ ED_markers_draw(C, flag);
/* preview range */
UI_view2d_view_ortho(v2d);
diff --git a/source/blender/editors/space_api/spacetypes.c b/source/blender/editors/space_api/spacetypes.c
index c8431d58bf5..01f0d1ae54f 100644
--- a/source/blender/editors/space_api/spacetypes.c
+++ b/source/blender/editors/space_api/spacetypes.c
@@ -32,7 +32,6 @@
#include "BLI_blenlib.h"
#include "BLI_utildefines.h"
-#include "DNA_object_types.h"
#include "DNA_scene_types.h"
#include "DNA_windowmanager_types.h"
@@ -61,7 +60,6 @@
#include "ED_space_api.h"
#include "ED_sound.h"
#include "ED_uvedit.h"
-#include "ED_view3d.h"
#include "ED_mball.h"
#include "ED_logic.h"
#include "ED_clip.h"
@@ -122,7 +120,7 @@ void ED_spacetypes_init(void)
ED_operatortypes_io();
ED_operatortypes_view2d();
- UI_buttons_operatortypes();
+ ED_button_operatortypes();
/* register operators */
spacetypes = BKE_spacetypes_list();
@@ -155,6 +153,7 @@ void ED_spacemacros_init(void)
ED_operatormacros_mask();
ED_operatormacros_sequencer();
ED_operatormacros_paint();
+ ED_operatormacros_gpencil();
/* register dropboxes (can use macros) */
spacetypes = BKE_spacetypes_list();
@@ -318,7 +317,3 @@ void ED_spacetype_xxx(void)
}
/* ****************************** end template *********************** */
-
-
-
-
diff --git a/source/blender/editors/space_buttons/CMakeLists.txt b/source/blender/editors/space_buttons/CMakeLists.txt
index 9e045a39a0c..397d79e1dbe 100644
--- a/source/blender/editors/space_buttons/CMakeLists.txt
+++ b/source/blender/editors/space_buttons/CMakeLists.txt
@@ -20,13 +20,15 @@
set(INC
../include
- ../../blenfont
../../blenkernel
../../blenlib
+ ../../blentranslation
+ ../../gpu
../../makesdna
../../makesrna
../../windowmanager
../../../../intern/guardedalloc
+ ../../../../intern/glew-mx
)
set(INC_SYS
@@ -46,6 +48,8 @@ if(WITH_INTERNATIONAL)
add_definitions(-DWITH_INTERNATIONAL)
endif()
+add_definitions(${GL_DEFINITIONS})
+
if(WITH_FREESTYLE)
add_definitions(-DWITH_FREESTYLE)
endif()
diff --git a/source/blender/editors/space_buttons/SConscript b/source/blender/editors/space_buttons/SConscript
index 61f9b6f496e..c39df449647 100644
--- a/source/blender/editors/space_buttons/SConscript
+++ b/source/blender/editors/space_buttons/SConscript
@@ -31,12 +31,14 @@ sources = env.Glob('*.c')
incs = [
'#/intern/guardedalloc',
- '#/extern/glew/include',
+ env['BF_GLEW_INC'],
+ '#/intern/glew-mx',
'../include',
- '../../blenfont',
'../../blenkernel',
'../../blenlib',
+ '../../blentranslation',
'../../bmesh',
+ '../../gpu',
'../../imbuf',
'../../makesdna',
'../../makesrna',
@@ -44,7 +46,9 @@ incs = [
'../../windowmanager',
]
incs = ' '.join(incs)
+
defs = []
+defs += env['BF_GL_DEFINITIONS']
if env['WITH_BF_INTERNATIONAL']:
defs.append('WITH_INTERNATIONAL')
diff --git a/source/blender/editors/space_buttons/buttons_context.c b/source/blender/editors/space_buttons/buttons_context.c
index 524a42ba388..42e2d6b90f0 100644
--- a/source/blender/editors/space_buttons/buttons_context.c
+++ b/source/blender/editors/space_buttons/buttons_context.c
@@ -36,7 +36,7 @@
#include "BLI_listbase.h"
#include "BLI_utildefines.h"
-#include "BLF_translation.h"
+#include "BLT_translation.h"
#include "DNA_armature_types.h"
#include "DNA_lamp_types.h"
@@ -59,6 +59,7 @@
#include "RNA_access.h"
+#include "ED_buttons.h"
#include "ED_armature.h"
#include "ED_screen.h"
#include "ED_physics.h"
@@ -1103,11 +1104,11 @@ void buttons_context_draw(const bContext *C, uiLayout *layout)
uiLayoutSetAlignment(row, UI_LAYOUT_ALIGN_LEFT);
block = uiLayoutGetBlock(row);
- uiBlockSetEmboss(block, UI_EMBOSSN);
- but = uiDefIconButBitC(block, ICONTOG, SB_PIN_CONTEXT, 0, ICON_UNPINNED, 0, 0, UI_UNIT_X, UI_UNIT_Y, &sbuts->flag,
+ UI_block_emboss_set(block, UI_EMBOSS_NONE);
+ but = uiDefIconButBitC(block, UI_BTYPE_ICON_TOGGLE, SB_PIN_CONTEXT, 0, ICON_UNPINNED, 0, 0, UI_UNIT_X, UI_UNIT_Y, &sbuts->flag,
0, 0, 0, 0, TIP_("Follow context or keep fixed datablock displayed"));
- uiButClearFlag(but, UI_BUT_UNDO); /* skip undo on screen buttons */
- uiButSetFunc(but, pin_cb, NULL, NULL);
+ UI_but_flag_disable(but, UI_BUT_UNDO); /* skip undo on screen buttons */
+ UI_but_func_set(but, pin_cb, NULL, NULL);
for (a = 0; a < path->len; a++) {
ptr = &path->ptr[a];
@@ -1146,7 +1147,7 @@ void buttons_context_register(ARegionType *art)
pt = MEM_callocN(sizeof(PanelType), "spacetype buttons panel context");
strcpy(pt->idname, "BUTTONS_PT_context");
strcpy(pt->label, N_("Context")); /* XXX C panels are not available through RNA (bpy.types)! */
- strcpy(pt->translation_context, BLF_I18NCONTEXT_DEFAULT_BPYRNA);
+ strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
pt->draw = buttons_panel_context;
pt->flag = PNL_NO_HEADER;
BLI_addtail(&art->paneltypes, pt);
@@ -1179,3 +1180,33 @@ ID *buttons_context_id_path(const bContext *C)
return NULL;
}
+
+void ED_buttons_id_unref(SpaceButs *sbuts, const ID *id)
+{
+ if (sbuts->pinid == id) {
+ sbuts->pinid = NULL;
+ sbuts->flag &= ~SB_PIN_CONTEXT;
+ }
+
+ if (sbuts->path) {
+ ButsContextPath *path = sbuts->path;
+ int i;
+
+ for (i = 0; i < path->len; i++) {
+ if (path->ptr[i].id.data == id) {
+ break;
+ }
+ }
+
+ if (i == path->len) {
+ /* pass */
+ }
+ else if (i == 0) {
+ MEM_SAFE_FREE(sbuts->path);
+ }
+ else {
+ memset(&path->ptr[i], 0, sizeof(path->ptr[i]) * (path->len - i));
+ path->len = i;
+ }
+ }
+}
diff --git a/source/blender/editors/space_buttons/buttons_intern.h b/source/blender/editors/space_buttons/buttons_intern.h
index f294729ae97..7fc35a6b1e7 100644
--- a/source/blender/editors/space_buttons/buttons_intern.h
+++ b/source/blender/editors/space_buttons/buttons_intern.h
@@ -34,7 +34,6 @@
#include "DNA_listBase.h"
#include "RNA_types.h"
-struct ARegion;
struct ARegionType;
struct ID;
struct SpaceButs;
diff --git a/source/blender/editors/space_buttons/buttons_ops.c b/source/blender/editors/space_buttons/buttons_ops.c
index b651d684bf6..b8b56f8f848 100644
--- a/source/blender/editors/space_buttons/buttons_ops.c
+++ b/source/blender/editors/space_buttons/buttons_ops.c
@@ -40,7 +40,7 @@
#include "BLI_path_util.h"
#include "BLI_string.h"
-#include "BLF_translation.h"
+#include "BLT_translation.h"
#include "BKE_context.h"
#include "BKE_global.h"
@@ -72,12 +72,12 @@ static int toolbox_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *UN
RNA_pointer_create(&sc->id, &RNA_SpaceProperties, sbuts, &ptr);
- pup = uiPupMenuBegin(C, IFACE_("Align"), ICON_NONE);
- layout = uiPupMenuLayout(pup);
+ pup = UI_popup_menu_begin(C, IFACE_("Align"), ICON_NONE);
+ layout = UI_popup_menu_layout(pup);
uiItemsEnumR(layout, &ptr, "align");
- uiPupMenuEnd(C, pup);
+ UI_popup_menu_end(C, pup);
- return OPERATOR_CANCELLED;
+ return OPERATOR_INTERFACE;
}
void BUTTONS_OT_toolbox(wmOperatorType *ot)
@@ -97,6 +97,7 @@ void BUTTONS_OT_toolbox(wmOperatorType *ot)
typedef struct FileBrowseOp {
PointerRNA ptr;
PropertyRNA *prop;
+ bool is_undo;
} FileBrowseOp;
static int file_browse_exec(bContext *C, wmOperator *op)
@@ -142,6 +143,10 @@ static int file_browse_exec(bContext *C, wmOperator *op)
RNA_property_update(C, &fbo->ptr, fbo->prop);
MEM_freeN(str);
+ if (fbo->is_undo) {
+ const char *undostr = RNA_property_identifier(fbo->prop);
+ ED_undo_push(C, undostr);
+ }
/* special, annoying exception, filesel on redo panel [#26618] */
{
@@ -168,6 +173,7 @@ static int file_browse_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
PointerRNA ptr;
PropertyRNA *prop;
+ bool is_undo;
FileBrowseOp *fbo;
char *str;
@@ -176,7 +182,7 @@ static int file_browse_invoke(bContext *C, wmOperator *op, const wmEvent *event)
return OPERATOR_CANCELLED;
}
- uiFileBrowseContextProperty(C, &ptr, &prop);
+ UI_context_active_but_prop_get_filebrowser(C, &ptr, &prop, &is_undo);
if (!prop)
return OPERATOR_CANCELLED;
@@ -186,6 +192,7 @@ static int file_browse_invoke(bContext *C, wmOperator *op, const wmEvent *event)
/* useful yet irritating feature, Shift+Click to open the file
* Alt+Click to browse a folder in the OS's browser */
if (event->shift || event->alt) {
+ wmOperatorType *ot = WM_operatortype_find("WM_OT_path_open", true);
PointerRNA props_ptr;
if (event->alt) {
@@ -195,19 +202,21 @@ static int file_browse_invoke(bContext *C, wmOperator *op, const wmEvent *event)
}
- WM_operator_properties_create(&props_ptr, "WM_OT_path_open");
+ WM_operator_properties_create_ptr(&props_ptr, ot);
RNA_string_set(&props_ptr, "filepath", str);
- WM_operator_name_call(C, "WM_OT_path_open", WM_OP_EXEC_DEFAULT, &props_ptr);
+ WM_operator_name_call_ptr(C, ot, WM_OP_EXEC_DEFAULT, &props_ptr);
WM_operator_properties_free(&props_ptr);
MEM_freeN(str);
return OPERATOR_CANCELLED;
}
else {
+ PropertyRNA *prop_relpath;
const char *path_prop = RNA_struct_find_property(op->ptr, "directory") ? "directory" : "filepath";
fbo = MEM_callocN(sizeof(FileBrowseOp), "FileBrowseOp");
fbo->ptr = ptr;
fbo->prop = prop;
+ fbo->is_undo = is_undo;
op->customdata = fbo;
RNA_string_set(op->ptr, path_prop, str);
@@ -215,10 +224,10 @@ static int file_browse_invoke(bContext *C, wmOperator *op, const wmEvent *event)
/* normally ED_fileselect_get_params would handle this but we need to because of stupid
* user-prefs exception - campbell */
- if (RNA_struct_find_property(op->ptr, "relative_path")) {
- if (!RNA_struct_property_is_set(op->ptr, "relative_path")) {
+ if ((prop_relpath = RNA_struct_find_property(op->ptr, "relative_path"))) {
+ if (!RNA_property_is_set(op->ptr, prop_relpath)) {
/* annoying exception!, if were dealing with the user prefs, default relative to be off */
- RNA_boolean_set(op->ptr, "relative_path", U.flag & USER_RELPATHS && (ptr.data != &U));
+ RNA_property_boolean_set(op->ptr, prop_relpath, U.flag & USER_RELPATHS && (ptr.data != &U));
}
}
WM_event_add_fileselect(C, op);
@@ -239,11 +248,12 @@ void BUTTONS_OT_file_browse(wmOperatorType *ot)
ot->exec = file_browse_exec;
ot->cancel = file_browse_cancel;
- ot->flag |= OPTYPE_UNDO;
+ /* conditional undo based on button flag */
+ ot->flag = 0;
/* properties */
WM_operator_properties_filesel(ot, 0, FILE_SPECIAL, FILE_OPENFILE,
- WM_FILESEL_FILEPATH | WM_FILESEL_RELPATH, FILE_DEFAULTDISPLAY);
+ WM_FILESEL_FILEPATH | WM_FILESEL_RELPATH, FILE_DEFAULTDISPLAY, FILE_SORT_ALPHA);
}
/* second operator, only difference from BUTTONS_OT_file_browse is WM_FILESEL_DIRECTORY */
@@ -259,9 +269,10 @@ void BUTTONS_OT_directory_browse(wmOperatorType *ot)
ot->exec = file_browse_exec;
ot->cancel = file_browse_cancel;
- ot->flag |= OPTYPE_UNDO;
+ /* conditional undo based on button flag */
+ ot->flag = 0;
/* properties */
WM_operator_properties_filesel(ot, 0, FILE_SPECIAL, FILE_OPENFILE,
- WM_FILESEL_DIRECTORY | WM_FILESEL_RELPATH, FILE_DEFAULTDISPLAY);
+ WM_FILESEL_DIRECTORY | WM_FILESEL_RELPATH, FILE_DEFAULTDISPLAY, FILE_SORT_ALPHA);
}
diff --git a/source/blender/editors/space_buttons/buttons_texture.c b/source/blender/editors/space_buttons/buttons_texture.c
index 020d477fc39..b56ff850c35 100644
--- a/source/blender/editors/space_buttons/buttons_texture.c
+++ b/source/blender/editors/space_buttons/buttons_texture.c
@@ -37,7 +37,7 @@
#include "BLI_string.h"
#include "BLI_utildefines.h"
-#include "BLF_translation.h"
+#include "BLT_translation.h"
#include "DNA_brush_types.h"
#include "DNA_ID.h"
@@ -61,7 +61,9 @@
#include "BKE_paint.h"
#include "BKE_particle.h"
#include "BKE_scene.h"
-#include "BKE_freestyle.h"
+#ifdef WITH_FREESTYLE
+# include "BKE_freestyle.h"
+#endif
#include "RNA_access.h"
@@ -256,7 +258,7 @@ static void buttons_texture_user_property_add(ListBase *users, ID *id,
user->category = category;
user->icon = icon;
user->name = name;
- user->index = BLI_countlist(users);
+ user->index = BLI_listbase_count(users);
BLI_addtail(users, user);
}
@@ -273,7 +275,7 @@ static void buttons_texture_user_node_add(ListBase *users, ID *id,
user->category = category;
user->icon = icon;
user->name = name;
- user->index = BLI_countlist(users);
+ user->index = BLI_listbase_count(users);
BLI_addtail(users, user);
}
@@ -468,7 +470,7 @@ void buttons_texture_context_compute(const bContext *C, SpaceButs *sbuts)
}
else {
/* set one user as active based on active index */
- if (ct->index >= BLI_countlist(&ct->users))
+ if (ct->index == BLI_listbase_count_ex(&ct->users, ct->index + 1))
ct->index = 0;
ct->user = BLI_findlink(&ct->users, ct->index);
@@ -557,7 +559,7 @@ static void template_texture_user_menu(bContext *C, uiLayout *layout, void *UNUS
char name[UI_MAX_NAME_STR];
/* add label per category */
- if (!last_category || strcmp(last_category, user->category) != 0) {
+ if (!last_category || !STREQ(last_category, user->category)) {
uiItemL(layout, user->category, ICON_NONE);
but = block->buttons.last;
but->drawflag = UI_BUT_TEXT_LEFT;
@@ -576,9 +578,9 @@ static void template_texture_user_menu(bContext *C, uiLayout *layout, void *UNUS
else
BLI_snprintf(name, UI_MAX_NAME_STR, " %s", user->name);
- but = uiDefIconTextBut(block, BUT, 0, user->icon, name, 0, 0, UI_UNIT_X * 4, UI_UNIT_Y,
+ but = uiDefIconTextBut(block, UI_BTYPE_BUT, 0, user->icon, name, 0, 0, UI_UNIT_X * 4, UI_UNIT_Y,
NULL, 0.0, 0.0, 0.0, 0.0, "");
- uiButSetNFunc(but, template_texture_select, MEM_dupallocN(user), NULL);
+ UI_but_funcN_set(but, template_texture_select, MEM_dupallocN(user), NULL);
last_category = user->category;
}
@@ -620,9 +622,9 @@ void uiTemplateTextureUser(uiLayout *layout, bContext *C)
}
/* some cosmetic tweaks */
- uiButSetMenuFromPulldown(but);
+ UI_but_type_set_menu_from_pulldown(but);
- but->flag &= ~UI_ICON_SUBMENU;
+ but->flag &= ~UI_BUT_ICON_SUBMENU;
}
/************************* Texture Show **************************/
@@ -675,9 +677,9 @@ void uiTemplateTextureShow(uiLayout *layout, bContext *C, PointerRNA *ptr, Prope
uiBlock *block = uiLayoutGetBlock(layout);
uiBut *but;
- but = uiDefIconBut(block, BUT, 0, ICON_BUTS, 0, 0, UI_UNIT_X, UI_UNIT_Y,
+ but = uiDefIconBut(block, UI_BTYPE_BUT, 0, ICON_BUTS, 0, 0, UI_UNIT_X, UI_UNIT_Y,
NULL, 0.0, 0.0, 0.0, 0.0, "Show texture in texture tab");
- uiButSetFunc(but, template_texture_show, user->ptr.data, user->prop);
+ UI_but_func_set(but, template_texture_show, user->ptr.data, user->prop);
}
}
diff --git a/source/blender/editors/space_buttons/space_buttons.c b/source/blender/editors/space_buttons/space_buttons.c
index 4d62f528915..e28ad686d2a 100644
--- a/source/blender/editors/space_buttons/space_buttons.c
+++ b/source/blender/editors/space_buttons/space_buttons.c
@@ -28,7 +28,6 @@
* \ingroup spbuttons
*/
-
#include <string.h>
#include <stdio.h>
@@ -46,10 +45,6 @@
#include "WM_api.h"
#include "WM_types.h"
-#include "UI_resources.h"
-#include "UI_view2d.h"
-
-
#include "buttons_intern.h" /* own include */
/* ******************** default callbacks for buttons space ***************** */
@@ -142,38 +137,38 @@ static void buttons_main_area_draw(const bContext *C, ARegion *ar)
{
/* draw entirely, view changes should be handled here */
SpaceButs *sbuts = CTX_wm_space_buts(C);
- int vertical = (sbuts->align == BUT_VERTICAL);
+ const bool vertical = (sbuts->align == BUT_VERTICAL);
buttons_context_compute(C, sbuts);
if (sbuts->mainb == BCONTEXT_SCENE)
- ED_region_panels(C, ar, vertical, "scene", sbuts->mainb);
+ ED_region_panels(C, ar, "scene", sbuts->mainb, vertical);
else if (sbuts->mainb == BCONTEXT_RENDER)
- ED_region_panels(C, ar, vertical, "render", sbuts->mainb);
+ ED_region_panels(C, ar, "render", sbuts->mainb, vertical);
else if (sbuts->mainb == BCONTEXT_RENDER_LAYER)
- ED_region_panels(C, ar, vertical, "render_layer", sbuts->mainb);
+ ED_region_panels(C, ar, "render_layer", sbuts->mainb, vertical);
else if (sbuts->mainb == BCONTEXT_WORLD)
- ED_region_panels(C, ar, vertical, "world", sbuts->mainb);
+ ED_region_panels(C, ar, "world", sbuts->mainb, vertical);
else if (sbuts->mainb == BCONTEXT_OBJECT)
- ED_region_panels(C, ar, vertical, "object", sbuts->mainb);
+ ED_region_panels(C, ar, "object", sbuts->mainb, vertical);
else if (sbuts->mainb == BCONTEXT_DATA)
- ED_region_panels(C, ar, vertical, "data", sbuts->mainb);
+ ED_region_panels(C, ar, "data", sbuts->mainb, vertical);
else if (sbuts->mainb == BCONTEXT_MATERIAL)
- ED_region_panels(C, ar, vertical, "material", sbuts->mainb);
+ ED_region_panels(C, ar, "material", sbuts->mainb, vertical);
else if (sbuts->mainb == BCONTEXT_TEXTURE)
- ED_region_panels(C, ar, vertical, "texture", sbuts->mainb);
+ ED_region_panels(C, ar, "texture", sbuts->mainb, vertical);
else if (sbuts->mainb == BCONTEXT_PARTICLE)
- ED_region_panels(C, ar, vertical, "particle", sbuts->mainb);
+ ED_region_panels(C, ar, "particle", sbuts->mainb, vertical);
else if (sbuts->mainb == BCONTEXT_PHYSICS)
- ED_region_panels(C, ar, vertical, "physics", sbuts->mainb);
+ ED_region_panels(C, ar, "physics", sbuts->mainb, vertical);
else if (sbuts->mainb == BCONTEXT_BONE)
- ED_region_panels(C, ar, vertical, "bone", sbuts->mainb);
+ ED_region_panels(C, ar, "bone", sbuts->mainb, vertical);
else if (sbuts->mainb == BCONTEXT_MODIFIER)
- ED_region_panels(C, ar, vertical, "modifier", sbuts->mainb);
+ ED_region_panels(C, ar, "modifier", sbuts->mainb, vertical);
else if (sbuts->mainb == BCONTEXT_CONSTRAINT)
- ED_region_panels(C, ar, vertical, "constraint", sbuts->mainb);
+ ED_region_panels(C, ar, "constraint", sbuts->mainb, vertical);
else if (sbuts->mainb == BCONTEXT_BONE_CONSTRAINT)
- ED_region_panels(C, ar, vertical, "bone_constraint", sbuts->mainb);
+ ED_region_panels(C, ar, "bone_constraint", sbuts->mainb, vertical);
sbuts->re_align = 0;
sbuts->mainbo = sbuts->mainb;
@@ -376,9 +371,11 @@ static void buttons_area_listener(bScreen *UNUSED(sc), ScrArea *sa, wmNotifier *
}
break;
/* Listener for preview render, when doing an global undo. */
- case NC_WINDOW:
- ED_area_tag_redraw(sa);
- sbuts->preview = 1;
+ case NC_WM:
+ if (wmn->data == ND_UNDO) {
+ ED_area_tag_redraw(sa);
+ sbuts->preview = 1;
+ }
break;
#ifdef WITH_FREESTYLE
case NC_LINESTYLE:
diff --git a/source/blender/editors/space_clip/CMakeLists.txt b/source/blender/editors/space_clip/CMakeLists.txt
index 7689aa28169..d17d1856502 100644
--- a/source/blender/editors/space_clip/CMakeLists.txt
+++ b/source/blender/editors/space_clip/CMakeLists.txt
@@ -23,15 +23,17 @@
set(INC
../include
- ../../blenkernel
../../blenfont
+ ../../blenkernel
../../blenlib
+ ../../blentranslation
../../imbuf
+ ../../gpu
../../makesdna
../../makesrna
../../windowmanager
- ../../gpu
../../../../intern/guardedalloc
+ ../../../../intern/glew-mx
)
set(INC_SYS
@@ -56,6 +58,8 @@ set(SRC
clip_intern.h
)
+add_definitions(${GL_DEFINITIONS})
+
if(WITH_INTERNATIONAL)
add_definitions(-DWITH_INTERNATIONAL)
endif()
diff --git a/source/blender/editors/space_clip/SConscript b/source/blender/editors/space_clip/SConscript
index d4483eda6e3..37b83946e93 100644
--- a/source/blender/editors/space_clip/SConscript
+++ b/source/blender/editors/space_clip/SConscript
@@ -28,14 +28,19 @@
Import ('env')
sources = env.Glob('*.c')
+
defs = []
+defs += env['BF_GL_DEFINITIONS']
+
incs = [
'#/intern/guardedalloc',
- '#/extern/glew/include',
+ env['BF_GLEW_INC'],
+ '#/intern/glew-mx',
'../include',
'../../blenfont',
'../../blenkernel',
'../../blenlib',
+ '../../blentranslation',
'../../gpu',
'../../imbuf',
'../../makesdna',
diff --git a/source/blender/editors/space_clip/clip_buttons.c b/source/blender/editors/space_clip/clip_buttons.c
index 889613b5d13..0378c68d12c 100644
--- a/source/blender/editors/space_clip/clip_buttons.c
+++ b/source/blender/editors/space_clip/clip_buttons.c
@@ -44,7 +44,7 @@
#include "BLI_path_util.h"
#include "BLI_string.h"
-#include "BLF_translation.h"
+#include "BLT_translation.h"
#include "BKE_context.h"
#include "BKE_depsgraph.h"
@@ -69,26 +69,9 @@
/* Panels */
-static int clip_grease_pencil_panel_poll(const bContext *C, PanelType *UNUSED(pt))
+void ED_clip_buttons_register(ARegionType *UNUSED(art))
{
- SpaceClip *sc = CTX_wm_space_clip(C);
- return sc->view == SC_VIEW_CLIP;
-}
-
-void ED_clip_buttons_register(ARegionType *art)
-{
- PanelType *pt;
-
- pt = MEM_callocN(sizeof(PanelType), "spacetype clip panel gpencil");
- strcpy(pt->idname, "CLIP_PT_gpencil");
- strcpy(pt->label, N_("Grease Pencil"));
- strcpy(pt->translation_context, BLF_I18NCONTEXT_DEFAULT_BPYRNA);
- pt->draw_header = ED_gpencil_panel_standard_header;
- pt->draw = ED_gpencil_panel_standard;
- pt->flag |= PNL_DEFAULT_CLOSED;
- pt->poll = clip_grease_pencil_panel_poll;
- BLI_addtail(&art->paneltypes, pt);
}
/********************* MovieClip Template ************************/
@@ -130,7 +113,7 @@ void uiTemplateMovieClip(uiLayout *layout, bContext *C, PointerRNA *ptr, const c
row = uiLayoutRow(layout, false);
block = uiLayoutGetBlock(row);
- uiDefBut(block, LABEL, 0, IFACE_("File Path:"), 0, 19, 145, 19, NULL, 0, 0, 0, 0, "");
+ uiDefBut(block, UI_BTYPE_LABEL, 0, IFACE_("File Path:"), 0, 19, 145, 19, NULL, 0, 0, 0, 0, "");
row = uiLayoutRow(layout, false);
split = uiLayoutSplit(row, 0.0f, false);
@@ -183,10 +166,10 @@ void uiTemplateTrack(uiLayout *layout, PointerRNA *ptr, const char *propname)
col = uiLayoutColumn(layout, true);
block = uiLayoutGetBlock(col);
- uiDefBut(block, TRACKPREVIEW, 0, "", 0, 0, UI_UNIT_X * 10, scopes->track_preview_height, scopes, 0, 0, 0, 0, "");
+ uiDefBut(block, UI_BTYPE_TRACK_PREVIEW, 0, "", 0, 0, UI_UNIT_X * 10, scopes->track_preview_height, scopes, 0, 0, 0, 0, "");
/* Resize grip. */
- uiDefIconButI(block, GRIP, 0, ICON_GRIP, 0, 0, UI_UNIT_X * 10, (short)(UI_UNIT_Y * 0.8f),
+ uiDefIconButI(block, UI_BTYPE_GRIP, 0, ICON_GRIP, 0, 0, UI_UNIT_X * 10, (short)(UI_UNIT_Y * 0.8f),
&scopes->track_preview_height, UI_UNIT_Y, UI_UNIT_Y * 20.0f, 0.0f, 0.0f, "");
}
@@ -403,9 +386,9 @@ void uiTemplateMarker(uiLayout *layout, PointerRNA *ptr, const char *propname, P
else
tip = TIP_("Marker is enabled at current frame");
- bt = uiDefIconButBitI(block, TOGN, MARKER_DISABLED, 0, ICON_RESTRICT_VIEW_OFF, 0, 0, UI_UNIT_X, UI_UNIT_Y,
+ bt = uiDefIconButBitI(block, UI_BTYPE_TOGGLE_N, MARKER_DISABLED, 0, ICON_RESTRICT_VIEW_OFF, 0, 0, UI_UNIT_X, UI_UNIT_Y,
&cb->marker_flag, 0, 0, 1, 0, tip);
- uiButSetNFunc(bt, marker_update_cb, cb, NULL);
+ UI_but_funcN_set(bt, marker_update_cb, cb, NULL);
}
else {
int width, height, step, digits;
@@ -417,7 +400,7 @@ void uiTemplateMarker(uiLayout *layout, PointerRNA *ptr, const char *propname, P
if (track->flag & TRACK_LOCKED) {
uiLayoutSetActive(layout, false);
block = uiLayoutAbsoluteBlock(layout);
- uiDefBut(block, LABEL, 0, IFACE_("Track is locked"), 0, 0, UI_UNIT_X * 15.0f, UI_UNIT_Y, NULL, 0, 0, 0, 0, "");
+ uiDefBut(block, UI_BTYPE_LABEL, 0, IFACE_("Track is locked"), 0, 0, UI_UNIT_X * 15.0f, UI_UNIT_Y, NULL, 0, 0, 0, 0, "");
return;
}
@@ -442,53 +425,53 @@ void uiTemplateMarker(uiLayout *layout, PointerRNA *ptr, const char *propname, P
cb->marker_flag = marker->flag;
block = uiLayoutAbsoluteBlock(layout);
- uiBlockSetHandleFunc(block, marker_block_handler, cb);
- uiBlockSetNFunc(block, marker_update_cb, cb, NULL);
+ UI_block_func_handle_set(block, marker_block_handler, cb);
+ UI_block_funcN_set(block, marker_update_cb, cb, NULL);
if (cb->marker_flag & MARKER_DISABLED)
tip = TIP_("Marker is disabled at current frame");
else
tip = TIP_("Marker is enabled at current frame");
- uiDefButBitI(block, OPTIONN, MARKER_DISABLED, B_MARKER_FLAG, IFACE_("Enabled"), 0.5 * UI_UNIT_X, 9.5 * UI_UNIT_Y, 7.25 * UI_UNIT_X, UI_UNIT_Y,
+ uiDefButBitI(block, UI_BTYPE_CHECKBOX_N, MARKER_DISABLED, B_MARKER_FLAG, IFACE_("Enabled"), 0.5 * UI_UNIT_X, 9.5 * UI_UNIT_Y, 7.25 * UI_UNIT_X, UI_UNIT_Y,
&cb->marker_flag, 0, 0, 0, 0, tip);
col = uiLayoutColumn(layout, true);
uiLayoutSetActive(col, (cb->marker_flag & MARKER_DISABLED) == 0);
block = uiLayoutAbsoluteBlock(col);
- uiBlockBeginAlign(block);
+ UI_block_align_begin(block);
- uiDefBut(block, LABEL, 0, IFACE_("Position:"), 0, 10 * UI_UNIT_Y, 15 * UI_UNIT_X, UI_UNIT_Y, NULL, 0, 0, 0, 0, "");
- uiDefButF(block, NUM, B_MARKER_POS, IFACE_("X:"), 0.5 * UI_UNIT_X, 9 * UI_UNIT_Y, 7.25 * UI_UNIT_X, UI_UNIT_Y, &cb->marker_pos[0],
+ uiDefBut(block, UI_BTYPE_LABEL, 0, IFACE_("Position:"), 0, 10 * UI_UNIT_Y, 15 * UI_UNIT_X, UI_UNIT_Y, NULL, 0, 0, 0, 0, "");
+ uiDefButF(block, UI_BTYPE_NUM, B_MARKER_POS, IFACE_("X:"), 0.5 * UI_UNIT_X, 9 * UI_UNIT_Y, 7.25 * UI_UNIT_X, UI_UNIT_Y, &cb->marker_pos[0],
-10 * width, 10.0 * width, step, digits, TIP_("X-position of marker at frame in screen coordinates"));
- uiDefButF(block, NUM, B_MARKER_POS, IFACE_("Y:"), 8.25 * UI_UNIT_X, 9 * UI_UNIT_Y, 7.25 * UI_UNIT_X, UI_UNIT_Y, &cb->marker_pos[1],
+ uiDefButF(block, UI_BTYPE_NUM, B_MARKER_POS, IFACE_("Y:"), 8.25 * UI_UNIT_X, 9 * UI_UNIT_Y, 7.25 * UI_UNIT_X, UI_UNIT_Y, &cb->marker_pos[1],
-10 * height, 10.0 * height, step, digits,
TIP_("Y-position of marker at frame in screen coordinates"));
- uiDefBut(block, LABEL, 0, IFACE_("Offset:"), 0, 8 * UI_UNIT_Y, 15 * UI_UNIT_X, UI_UNIT_Y, NULL, 0, 0, 0, 0, "");
- uiDefButF(block, NUM, B_MARKER_OFFSET, IFACE_("X:"), 0.5 * UI_UNIT_X, 7 * UI_UNIT_Y, 7.25 * UI_UNIT_X, UI_UNIT_Y, &cb->track_offset[0],
+ uiDefBut(block, UI_BTYPE_LABEL, 0, IFACE_("Offset:"), 0, 8 * UI_UNIT_Y, 15 * UI_UNIT_X, UI_UNIT_Y, NULL, 0, 0, 0, 0, "");
+ uiDefButF(block, UI_BTYPE_NUM, B_MARKER_OFFSET, IFACE_("X:"), 0.5 * UI_UNIT_X, 7 * UI_UNIT_Y, 7.25 * UI_UNIT_X, UI_UNIT_Y, &cb->track_offset[0],
-10 * width, 10.0 * width, step, digits, TIP_("X-offset to parenting point"));
- uiDefButF(block, NUM, B_MARKER_OFFSET, IFACE_("Y:"), 8.25 * UI_UNIT_X, 7 * UI_UNIT_Y, 7.25 * UI_UNIT_X, UI_UNIT_Y, &cb->track_offset[1],
+ uiDefButF(block, UI_BTYPE_NUM, B_MARKER_OFFSET, IFACE_("Y:"), 8.25 * UI_UNIT_X, 7 * UI_UNIT_Y, 7.25 * UI_UNIT_X, UI_UNIT_Y, &cb->track_offset[1],
-10 * height, 10.0 * height, step, digits, TIP_("Y-offset to parenting point"));
- uiDefBut(block, LABEL, 0, IFACE_("Pattern Area:"), 0, 6 * UI_UNIT_Y, 15 * UI_UNIT_X, UI_UNIT_Y, NULL, 0, 0, 0, 0, "");
- uiDefButF(block, NUM, B_MARKER_PAT_DIM, IFACE_("Width:"), 0.5 * UI_UNIT_X, 5 * UI_UNIT_Y, 15 * UI_UNIT_X, UI_UNIT_Y, &cb->marker_pat[0], 3.0f,
+ uiDefBut(block, UI_BTYPE_LABEL, 0, IFACE_("Pattern Area:"), 0, 6 * UI_UNIT_Y, 15 * UI_UNIT_X, UI_UNIT_Y, NULL, 0, 0, 0, 0, "");
+ uiDefButF(block, UI_BTYPE_NUM, B_MARKER_PAT_DIM, IFACE_("Width:"), 0.5 * UI_UNIT_X, 5 * UI_UNIT_Y, 15 * UI_UNIT_X, UI_UNIT_Y, &cb->marker_pat[0], 3.0f,
10.0 * width, step, digits, TIP_("Width of marker's pattern in screen coordinates"));
- uiDefButF(block, NUM, B_MARKER_PAT_DIM, IFACE_("Height:"), 0.5 * UI_UNIT_X, 4 * UI_UNIT_Y, 15 * UI_UNIT_X, UI_UNIT_Y, &cb->marker_pat[1], 3.0f,
+ uiDefButF(block, UI_BTYPE_NUM, B_MARKER_PAT_DIM, IFACE_("Height:"), 0.5 * UI_UNIT_X, 4 * UI_UNIT_Y, 15 * UI_UNIT_X, UI_UNIT_Y, &cb->marker_pat[1], 3.0f,
10.0 * height, step, digits, TIP_("Height of marker's pattern in screen coordinates"));
- uiDefBut(block, LABEL, 0, IFACE_("Search Area:"), 0, 3 * UI_UNIT_Y, 15 * UI_UNIT_X, UI_UNIT_Y, NULL, 0, 0, 0, 0, "");
- uiDefButF(block, NUM, B_MARKER_SEARCH_POS, IFACE_("X:"), 0.5 * UI_UNIT_X, 2 * UI_UNIT_Y, 7.25 * UI_UNIT_X, UI_UNIT_Y, &cb->marker_search_pos[0],
+ uiDefBut(block, UI_BTYPE_LABEL, 0, IFACE_("Search Area:"), 0, 3 * UI_UNIT_Y, 15 * UI_UNIT_X, UI_UNIT_Y, NULL, 0, 0, 0, 0, "");
+ uiDefButF(block, UI_BTYPE_NUM, B_MARKER_SEARCH_POS, IFACE_("X:"), 0.5 * UI_UNIT_X, 2 * UI_UNIT_Y, 7.25 * UI_UNIT_X, UI_UNIT_Y, &cb->marker_search_pos[0],
-width, width, step, digits, TIP_("X-position of search at frame relative to marker's position"));
- uiDefButF(block, NUM, B_MARKER_SEARCH_POS, IFACE_("Y:"), 8.25 * UI_UNIT_X, 2 * UI_UNIT_Y, 7.25 * UI_UNIT_X, UI_UNIT_Y, &cb->marker_search_pos[1],
+ uiDefButF(block, UI_BTYPE_NUM, B_MARKER_SEARCH_POS, IFACE_("Y:"), 8.25 * UI_UNIT_X, 2 * UI_UNIT_Y, 7.25 * UI_UNIT_X, UI_UNIT_Y, &cb->marker_search_pos[1],
-height, height, step, digits, TIP_("Y-position of search at frame relative to marker's position"));
- uiDefButF(block, NUM, B_MARKER_SEARCH_DIM, IFACE_("Width:"), 0.5 * UI_UNIT_X, 1 * UI_UNIT_Y, 15 * UI_UNIT_X, UI_UNIT_Y, &cb->marker_search[0], 3.0f,
+ uiDefButF(block, UI_BTYPE_NUM, B_MARKER_SEARCH_DIM, IFACE_("Width:"), 0.5 * UI_UNIT_X, 1 * UI_UNIT_Y, 15 * UI_UNIT_X, UI_UNIT_Y, &cb->marker_search[0], 3.0f,
10.0 * width, step, digits, TIP_("Width of marker's search in screen coordinates"));
- uiDefButF(block, NUM, B_MARKER_SEARCH_DIM, IFACE_("Height:"), 0.5 * UI_UNIT_X, 0 * UI_UNIT_Y, 15 * UI_UNIT_X, UI_UNIT_Y, &cb->marker_search[1], 3.0f,
+ uiDefButF(block, UI_BTYPE_NUM, B_MARKER_SEARCH_DIM, IFACE_("Height:"), 0.5 * UI_UNIT_X, 0 * UI_UNIT_Y, 15 * UI_UNIT_X, UI_UNIT_Y, &cb->marker_search[1], 3.0f,
10.0 * height, step, digits, TIP_("Height of marker's search in screen coordinates"));
- uiBlockEndAlign(block);
+ UI_block_align_end(block);
}
}
@@ -557,7 +540,7 @@ void uiTemplateMovieclipInformation(uiLayout *layout, PointerRNA *ptr, const cha
uiItemL(col, str, ICON_NONE);
/* Display current frame number. */
- framenr = BKE_movieclip_remap_scene_to_clip_frame(clip, user->framenr) ;
+ framenr = BKE_movieclip_remap_scene_to_clip_frame(clip, user->framenr);
if (framenr <= clip->len)
BLI_snprintf(str, sizeof(str), IFACE_("Frame: %d / %d"), framenr, clip->len);
else
diff --git a/source/blender/editors/space_clip/clip_dopesheet_draw.c b/source/blender/editors/space_clip/clip_dopesheet_draw.c
index 2a457bf503f..4bf4c1e7baa 100644
--- a/source/blender/editors/space_clip/clip_dopesheet_draw.c
+++ b/source/blender/editors/space_clip/clip_dopesheet_draw.c
@@ -30,7 +30,6 @@
*/
#include "DNA_movieclip_types.h"
-#include "DNA_object_types.h" /* SELECT */
#include "DNA_scene_types.h"
#include "BLI_utildefines.h"
@@ -283,7 +282,7 @@ void clip_draw_dopesheet_channels(const bContext *C, ARegion *ar)
MovieTracking *tracking;
MovieTrackingDopesheet *dopesheet;
MovieTrackingDopesheetChannel *channel;
- uiStyle *style = UI_GetStyle();
+ uiStyle *style = UI_style_get();
uiBlock *block;
int fontid = style->widget.uifont_id;
int height;
@@ -348,7 +347,7 @@ void clip_draw_dopesheet_channels(const bContext *C, ARegion *ar)
}
/* second pass: widgets */
- block = uiBeginBlock(C, ar, __func__, UI_EMBOSS);
+ block = UI_block_begin(C, ar, __func__, UI_EMBOSS);
y = (float) CHANNEL_FIRST;
/* get RNA properties (once) */
@@ -370,11 +369,11 @@ void clip_draw_dopesheet_channels(const bContext *C, ARegion *ar)
RNA_pointer_create(&clip->id, &RNA_MovieTrackingTrack, track, &ptr);
- uiBlockSetEmboss(block, UI_EMBOSSN);
- uiDefIconButR_prop(block, ICONTOG, 1, icon,
+ UI_block_emboss_set(block, UI_EMBOSS_NONE);
+ uiDefIconButR_prop(block, UI_BTYPE_ICON_TOGGLE, 1, icon,
v2d->cur.xmax - UI_UNIT_X - CHANNEL_PAD, y - UI_UNIT_Y / 2.0f,
UI_UNIT_X, UI_UNIT_Y, &ptr, chan_prop_lock, 0, 0, 0, 0, 0, NULL);
- uiBlockSetEmboss(block, UI_EMBOSS);
+ UI_block_emboss_set(block, UI_EMBOSS);
}
/* adjust y-position for next one */
@@ -382,6 +381,6 @@ void clip_draw_dopesheet_channels(const bContext *C, ARegion *ar)
}
glDisable(GL_BLEND);
- uiEndBlock(C, block);
- uiDrawBlock(C, block);
+ UI_block_end(C, block);
+ UI_block_draw(C, block);
}
diff --git a/source/blender/editors/space_clip/clip_dopesheet_ops.c b/source/blender/editors/space_clip/clip_dopesheet_ops.c
index 7ae5eda7139..d2f2fdd0b46 100644
--- a/source/blender/editors/space_clip/clip_dopesheet_ops.c
+++ b/source/blender/editors/space_clip/clip_dopesheet_ops.c
@@ -29,7 +29,6 @@
* \ingroup spclip
*/
-#include "DNA_object_types.h" /* SELECT */
#include "DNA_scene_types.h"
#include "BLI_utildefines.h"
diff --git a/source/blender/editors/space_clip/clip_draw.c b/source/blender/editors/space_clip/clip_draw.c
index a35251e71ef..62bb372514b 100644
--- a/source/blender/editors/space_clip/clip_draw.c
+++ b/source/blender/editors/space_clip/clip_draw.c
@@ -43,6 +43,7 @@
#include "BLI_math.h"
#include "BLI_string.h"
#include "BLI_math_base.h"
+#include "BLI_rect.h"
#include "BKE_context.h"
#include "BKE_image.h"
@@ -63,7 +64,6 @@
#include "UI_resources.h"
#include "UI_view2d.h"
-#include "RNA_access.h"
#include "BLF_api.h"
@@ -252,11 +252,11 @@ static void draw_movieclip_notes(SpaceClip *sc, ARegion *ar)
MovieClip *clip = ED_space_clip_get_clip(sc);
MovieTracking *tracking = &clip->tracking;
char str[256] = {0};
- bool block = false;
+ bool full_redraw = false;
if (tracking->stats) {
BLI_strncpy(str, tracking->stats->message, sizeof(str));
- block = true;
+ full_redraw = true;
}
else {
if (sc->flag & SC_LOCK_SELECTION)
@@ -265,7 +265,7 @@ static void draw_movieclip_notes(SpaceClip *sc, ARegion *ar)
if (str[0]) {
float fill_color[4] = {0.0f, 0.0f, 0.0f, 0.6f};
- ED_region_info_draw(ar, str, block, fill_color);
+ ED_region_info_draw(ar, str, fill_color, full_redraw);
}
}
@@ -286,6 +286,7 @@ static void draw_movieclip_buffer(const bContext *C, SpaceClip *sc, ARegion *ar,
MovieClip *clip = ED_space_clip_get_clip(sc);
int filter = GL_LINEAR;
int x, y;
+ rctf frame;
/* find window pixel coordinates of origin */
UI_view2d_view_to_region(&ar->v2d, 0.0f, 0.0f, &x, &y);
@@ -309,10 +310,14 @@ static void draw_movieclip_buffer(const bContext *C, SpaceClip *sc, ARegion *ar,
glPixelZoom(zoomx * width / ibuf->x, zoomy * height / ibuf->y);
glaDrawImBuf_glsl_ctx(C, ibuf, x, y, filter);
-
/* reset zoom */
glPixelZoom(1.0f, 1.0f);
+ BLI_rctf_init(&frame, 0.0f, ibuf->x, 0.0f, ibuf->y);
+
+ if (sc->flag & SC_SHOW_METADATA)
+ ED_region_image_metadata_draw(x, y, ibuf, frame, zoomx * width / ibuf->x, zoomy * height / ibuf->y);
+
if (ibuf->planes == 32)
glDisable(GL_BLEND);
}
@@ -515,7 +520,7 @@ static void draw_marker_outline(SpaceClip *sc, MovieTrackingTrack *track, MovieT
/* pattern and search outline */
glPushMatrix();
- glTranslatef(marker_pos[0], marker_pos[1], 0);
+ glTranslate2fv(marker_pos);
if (!tiny)
glLineWidth(3.0f);
@@ -647,7 +652,7 @@ static void draw_marker_areas(SpaceClip *sc, MovieTrackingTrack *track, MovieTra
/* pattern */
glPushMatrix();
- glTranslatef(marker_pos[0], marker_pos[1], 0);
+ glTranslate2fv(marker_pos);
if (tiny) {
glLineStipple(3, 0xaaaa);
@@ -800,7 +805,7 @@ static void draw_marker_slide_zones(SpaceClip *sc, MovieTrackingTrack *track, Mo
}
glPushMatrix();
- glTranslatef(marker_pos[0], marker_pos[1], 0);
+ glTranslate2fv(marker_pos);
dx = 6.0f / width / sc->zoom;
dy = 6.0f / height / sc->zoom;
@@ -1123,8 +1128,10 @@ static void draw_plane_marker_ex(SpaceClip *sc, Scene *scene, MovieTrackingPlane
bool draw_outline, int width, int height)
{
bool tiny = (sc->flag & SC_SHOW_TINY_MARKER) != 0;
- bool is_selected_track = plane_track->flag & SELECT;
- bool draw_plane_quad = plane_track->image == NULL || plane_track->image_opacity == 0.0f;
+ bool is_selected_track = (plane_track->flag & SELECT) != 0;
+ const bool has_image = plane_track->image != NULL &&
+ BKE_image_has_ibuf(plane_track->image, NULL);
+ const bool draw_plane_quad = !has_image || plane_track->image_opacity == 0.0f;
float px[2];
if (draw_outline) {
@@ -1693,29 +1700,29 @@ void clip_draw_main(const bContext *C, SpaceClip *sc, ARegion *ar)
}
if (sc->flag & SC_SHOW_STABLE) {
+ float translation[2];
+ float aspect = clip->tracking.camera.pixel_aspect;
float smat[4][4], ismat[4][4];
- ibuf = ED_space_clip_get_stable_buffer(sc, sc->loc, &sc->scale, &sc->angle);
-
- if (ibuf) {
- float translation[2];
- float aspect = clip->tracking.camera.pixel_aspect;
+ if ((sc->flag & SC_MUTE_FOOTAGE) == 0) {
+ ibuf = ED_space_clip_get_stable_buffer(sc, sc->loc,
+ &sc->scale, &sc->angle);
+ }
- if (width != ibuf->x)
- mul_v2_v2fl(translation, sc->loc, (float)width / ibuf->x);
- else
- copy_v2_v2(translation, sc->loc);
+ if (ibuf != NULL && width != ibuf->x)
+ mul_v2_v2fl(translation, sc->loc, (float)width / ibuf->x);
+ else
+ copy_v2_v2(translation, sc->loc);
- BKE_tracking_stabilization_data_to_mat4(width, height, aspect,
- translation, sc->scale, sc->angle, sc->stabmat);
+ BKE_tracking_stabilization_data_to_mat4(width, height, aspect, translation,
+ sc->scale, sc->angle, sc->stabmat);
- unit_m4(smat);
- smat[0][0] = 1.0f / width;
- smat[1][1] = 1.0f / height;
- invert_m4_m4(ismat, smat);
+ unit_m4(smat);
+ smat[0][0] = 1.0f / width;
+ smat[1][1] = 1.0f / height;
+ invert_m4_m4(ismat, smat);
- mul_m4_series(sc->unistabmat, smat, sc->stabmat, ismat);
- }
+ mul_m4_series(sc->unistabmat, smat, sc->stabmat, ismat);
}
else if ((sc->flag & SC_MUTE_FOOTAGE) == 0) {
ibuf = ED_space_clip_get_buffer(sc);
@@ -1779,7 +1786,7 @@ void clip_draw_grease_pencil(bContext *C, int onlyv2d)
int framenr = ED_space_clip_get_clip_frame_number(sc);
MovieTrackingMarker *marker = BKE_tracking_marker_get(track, framenr);
- glTranslatef(marker->pos[0], marker->pos[1], 0.0f);
+ glTranslate2fv(marker->pos);
}
}
diff --git a/source/blender/editors/space_clip/clip_editor.c b/source/blender/editors/space_clip/clip_editor.c
index b7860643e1a..dbedfaa1de4 100644
--- a/source/blender/editors/space_clip/clip_editor.c
+++ b/source/blender/editors/space_clip/clip_editor.c
@@ -48,16 +48,16 @@
#include "BLI_fileops.h"
#include "BLI_math.h"
#include "BLI_rect.h"
-#include "BLI_threads.h"
+#include "BLI_task.h"
#include "BKE_global.h"
#include "BKE_main.h"
+#include "BKE_mask.h"
#include "BKE_movieclip.h"
#include "BKE_context.h"
#include "BKE_tracking.h"
#include "BKE_library.h"
-#include "GPU_extensions.h"
#include "IMB_colormanagement.h"
#include "IMB_imbuf_types.h"
@@ -65,6 +65,7 @@
#include "ED_screen.h"
#include "ED_clip.h"
+#include "ED_mask.h"
#include "WM_api.h"
#include "WM_types.h"
@@ -220,6 +221,7 @@ int ED_space_clip_get_clip_frame_number(SpaceClip *sc)
{
MovieClip *clip = ED_space_clip_get_clip(sc);
+ /* Caller must ensure space does have a valid clip, otherwise it will crash, see T45017. */
return BKE_movieclip_remap_scene_to_clip_frame(clip, sc->user.framenr);
}
@@ -330,7 +332,7 @@ void ED_clip_update_frame(const Main *mainp, int cfra)
}
}
-static bool selected_boundbox(SpaceClip *sc, float min[2], float max[2])
+static bool selected_tracking_boundbox(SpaceClip *sc, float min[2], float max[2])
{
MovieClip *clip = ED_space_clip_get_clip(sc);
MovieTrackingTrack *track;
@@ -378,6 +380,29 @@ static bool selected_boundbox(SpaceClip *sc, float min[2], float max[2])
return ok;
}
+static bool selected_boundbox(const bContext *C, float min[2], float max[2])
+{
+ SpaceClip *sc = CTX_wm_space_clip(C);
+ if (sc->mode == SC_MODE_TRACKING) {
+ return selected_tracking_boundbox(sc, min, max);
+ }
+ else {
+ if (ED_mask_selected_minmax(C, min, max)) {
+ MovieClip *clip = ED_space_clip_get_clip(sc);
+ int width, height;
+ ED_space_clip_get_size(sc, &width, &height);
+ BKE_mask_coord_to_movieclip(clip, &sc->user, min, min);
+ BKE_mask_coord_to_movieclip(clip, &sc->user, max, max);
+ min[0] *= width;
+ min[1] *= height;
+ max[0] *= width;
+ max[1] *= height;
+ return true;
+ }
+ return false;
+ }
+}
+
bool ED_clip_view_selection(const bContext *C, ARegion *ar, bool fit)
{
SpaceClip *sc = CTX_wm_space_clip(C);
@@ -389,7 +414,7 @@ bool ED_clip_view_selection(const bContext *C, ARegion *ar, bool fit)
if ((frame_width == 0) || (frame_height == 0) || (sc->clip == NULL))
return false;
- if (!selected_boundbox(sc, min, max))
+ if (!selected_boundbox(C, min, max))
return false;
/* center view */
@@ -620,11 +645,6 @@ typedef struct PrefetchQueue {
float *progress;
} PrefetchQueue;
-typedef struct PrefetchThread {
- MovieClip *clip;
- PrefetchQueue *queue;
-} PrefetchThread;
-
/* check whether pre-fetching is allowed */
static bool check_prefetch_break(void)
{
@@ -632,8 +652,9 @@ static bool check_prefetch_break(void)
}
/* read file for specified frame number to the memory */
-static unsigned char *prefetch_read_file_to_memory(MovieClip *clip, int current_frame, short render_size,
- short render_flag, size_t *size_r)
+static unsigned char *prefetch_read_file_to_memory(
+ MovieClip *clip, int current_frame, short render_size, short render_flag,
+ size_t *r_size)
{
MovieClipUser user = {0};
char name[FILE_MAX];
@@ -666,7 +687,7 @@ static unsigned char *prefetch_read_file_to_memory(MovieClip *clip, int current_
return NULL;
}
- *size_r = size;
+ *r_size = size;
close(file);
@@ -704,8 +725,9 @@ static int prefetch_find_uncached_frame(MovieClip *clip, int from_frame, int end
}
/* get memory buffer for first uncached frame within prefetch frame range */
-static unsigned char *prefetch_thread_next_frame(PrefetchQueue *queue, MovieClip *clip,
- size_t *size_r, int *current_frame_r)
+static unsigned char *prefetch_thread_next_frame(
+ PrefetchQueue *queue, MovieClip *clip,
+ size_t *r_size, int *r_current_frame)
{
unsigned char *mem = NULL;
@@ -734,9 +756,9 @@ static unsigned char *prefetch_thread_next_frame(PrefetchQueue *queue, MovieClip
int frames_processed;
mem = prefetch_read_file_to_memory(clip, current_frame, queue->render_size,
- queue->render_flag, size_r);
+ queue->render_flag, r_size);
- *current_frame_r = current_frame;
+ *r_current_frame = current_frame;
queue->current_frame = current_frame;
@@ -757,33 +779,35 @@ static unsigned char *prefetch_thread_next_frame(PrefetchQueue *queue, MovieClip
return mem;
}
-static void *do_prefetch_thread(void *data_v)
+static void prefetch_task_func(TaskPool *pool, void *task_data, int UNUSED(threadid))
{
- PrefetchThread *data = (PrefetchThread *) data_v;
- MovieClip *clip = data->clip;
+ PrefetchQueue *queue = (PrefetchQueue *)BLI_task_pool_userdata(pool);
+ MovieClip *clip = (MovieClip *)task_data;
unsigned char *mem;
size_t size;
int current_frame;
- while ((mem = prefetch_thread_next_frame(data->queue, data->clip, &size, &current_frame))) {
+ while ((mem = prefetch_thread_next_frame(queue, clip, &size, &current_frame))) {
ImBuf *ibuf;
MovieClipUser user = {0};
int flag = IB_rect | IB_alphamode_detect;
int result;
char *colorspace_name = NULL;
+ const bool use_proxy = (clip->flag & MCLIP_USE_PROXY) &&
+ (queue->render_size != MCLIP_PROXY_RENDER_SIZE_FULL);
user.framenr = current_frame;
- user.render_size = data->queue->render_size;
- user.render_flag = data->queue->render_flag;
+ user.render_size = queue->render_size;
+ user.render_flag = queue->render_flag;
/* Proxies are stored in the display space. */
- if (data->queue->render_flag & MCLIP_USE_PROXY) {
+ if (!use_proxy) {
colorspace_name = clip->colorspace_settings.name;
}
ibuf = IMB_ibImageFromMemory(mem, size, flag, colorspace_name, "prefetch frame");
- result = BKE_movieclip_put_frame_if_possible(data->clip, &user, ibuf);
+ result = BKE_movieclip_put_frame_if_possible(clip, &user, ibuf);
IMB_freeImBuf(ibuf);
@@ -791,27 +815,20 @@ static void *do_prefetch_thread(void *data_v)
if (!result) {
/* no more space in the cache, stop reading frames */
- *data->queue->stop = 1;
+ *queue->stop = 1;
break;
}
}
-
- return NULL;
}
static void start_prefetch_threads(MovieClip *clip, int start_frame, int current_frame, int end_frame,
short render_size, short render_flag, short *stop, short *do_update,
float *progress)
{
- ListBase threads;
PrefetchQueue queue;
- PrefetchThread *handles;
- int tot_thread = BLI_system_thread_count();
- int i;
-
- /* reserve one thread for the interface */
- if (tot_thread > 1)
- tot_thread--;
+ TaskScheduler *task_scheduler = BLI_task_scheduler_get();
+ TaskPool *task_pool;
+ int i, tot_thread = BLI_task_scheduler_num_threads(task_scheduler);
/* initialize queue */
BLI_spin_init(&queue.spin);
@@ -828,29 +845,18 @@ static void start_prefetch_threads(MovieClip *clip, int start_frame, int current
queue.do_update = do_update;
queue.progress = progress;
- /* fill in thread handles */
- handles = MEM_callocN(sizeof(PrefetchThread) * tot_thread, "prefetch threaded handles");
-
- if (tot_thread > 1)
- BLI_init_threads(&threads, do_prefetch_thread, tot_thread);
-
+ task_pool = BLI_task_pool_create(task_scheduler, &queue);
for (i = 0; i < tot_thread; i++) {
- PrefetchThread *handle = &handles[i];
-
- handle->clip = clip;
- handle->queue = &queue;
-
- if (tot_thread > 1)
- BLI_insert_thread(&threads, handle);
+ BLI_task_pool_push(task_pool,
+ prefetch_task_func,
+ clip,
+ false,
+ TASK_PRIORITY_LOW);
}
+ BLI_task_pool_work_and_wait(task_pool);
+ BLI_task_pool_free(task_pool);
- /* run the threads */
- if (tot_thread > 1)
- BLI_end_threads(&threads);
- else
- do_prefetch_thread(handles);
-
- MEM_freeN(handles);
+ BLI_spin_end(&queue.spin);
}
static bool prefetch_movie_frame(MovieClip *clip, int frame, short render_size,
diff --git a/source/blender/editors/space_clip/clip_graph_draw.c b/source/blender/editors/space_clip/clip_graph_draw.c
index 723c8bd144a..2c3b8acf672 100644
--- a/source/blender/editors/space_clip/clip_graph_draw.c
+++ b/source/blender/editors/space_clip/clip_graph_draw.c
@@ -50,7 +50,6 @@
#include "UI_resources.h"
#include "UI_view2d.h"
-#include "BLF_api.h"
#include "clip_intern.h" // own include
diff --git a/source/blender/editors/space_clip/clip_graph_ops.c b/source/blender/editors/space_clip/clip_graph_ops.c
index d1e2c770ade..e781d199d35 100644
--- a/source/blender/editors/space_clip/clip_graph_ops.c
+++ b/source/blender/editors/space_clip/clip_graph_ops.c
@@ -45,8 +45,6 @@
#include "ED_screen.h"
#include "ED_clip.h"
-#include "UI_interface.h"
-
#include "RNA_access.h"
#include "RNA_define.h"
@@ -202,10 +200,18 @@ static bool mouse_select_knot(bContext *C, float co[2], bool extend)
toggle_selection_cb);
}
- if (userdata.coord == 0)
- userdata.marker->flag |= MARKER_GRAPH_SEL_X;
- else
- userdata.marker->flag |= MARKER_GRAPH_SEL_Y;
+ if (userdata.coord == 0) {
+ if (extend && (userdata.marker->flag & MARKER_GRAPH_SEL_X) != 0)
+ userdata.marker->flag &= ~MARKER_GRAPH_SEL_X;
+ else
+ userdata.marker->flag |= MARKER_GRAPH_SEL_X;
+ }
+ else {
+ if (extend && (userdata.marker->flag & MARKER_GRAPH_SEL_Y) != 0)
+ userdata.marker->flag &= ~MARKER_GRAPH_SEL_Y;
+ else
+ userdata.marker->flag |= MARKER_GRAPH_SEL_Y;
+ }
return true;
}
@@ -240,10 +246,12 @@ static bool mouse_select_curve(bContext *C, float co[2], bool extend)
else if (act_track != userdata.track) {
SelectUserData selectdata = {SEL_DESELECT};
MovieTrackingObject *object = BKE_tracking_object_get_active(tracking);
- ListBase *tracksbase = BKE_tracking_object_get_tracks(tracking, object);
tracking->act_track = userdata.track;
- BKE_tracking_track_select(tracksbase, userdata.track, TRACK_AREA_ALL, true);
+ if ((sc->flag & SC_SHOW_GRAPH_SEL_ONLY) == 0) {
+ ListBase *tracksbase = BKE_tracking_object_get_tracks(tracking, object);
+ BKE_tracking_track_select(tracksbase, userdata.track, TRACK_AREA_ALL, false);
+ }
/* deselect all knots on newly selected curve */
clip_graph_tracking_iterate(sc,
diff --git a/source/blender/editors/space_clip/clip_ops.c b/source/blender/editors/space_clip/clip_ops.c
index 87efaa615ee..55805e0b907 100644
--- a/source/blender/editors/space_clip/clip_ops.c
+++ b/source/blender/editors/space_clip/clip_ops.c
@@ -49,10 +49,10 @@
#include "BLI_path_util.h"
#include "BLI_math.h"
#include "BLI_rect.h"
-#include "BLI_threads.h"
+#include "BLI_task.h"
#include "BLI_string.h"
-#include "BLF_translation.h"
+#include "BLT_translation.h"
#include "BKE_context.h"
#include "BKE_global.h"
@@ -79,6 +79,8 @@
#include "UI_view2d.h"
+#include "PIL_time.h"
+
#include "clip_intern.h" // own include
/******************** view navigation utilities *********************/
@@ -166,7 +168,7 @@ static void open_init(bContext *C, wmOperator *op)
PropertyPointerRNA *pprop;
op->customdata = pprop = MEM_callocN(sizeof(PropertyPointerRNA), "OpenPropertyPointerRNA");
- uiIDContextProperty(C, &pprop->ptr, &pprop->prop);
+ UI_context_active_but_prop_get_templateID(C, &pprop->ptr, &pprop->prop);
}
static void open_cancel(bContext *UNUSED(C), wmOperator *op)
@@ -272,7 +274,7 @@ static int open_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)
return open_exec(C, op);
if (!RNA_struct_property_is_set(op->ptr, "relative_path"))
- RNA_boolean_set(op->ptr, "relative_path", U.flag & USER_RELPATHS);
+ RNA_boolean_set(op->ptr, "relative_path", (U.flag & USER_RELPATHS) != 0);
open_init(C, op);
@@ -297,8 +299,8 @@ void CLIP_OT_open(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
/* properties */
- WM_operator_properties_filesel(ot, FOLDERFILE | IMAGEFILE | MOVIEFILE, FILE_SPECIAL, FILE_OPENFILE,
- WM_FILESEL_RELPATH | WM_FILESEL_FILES | WM_FILESEL_DIRECTORY, FILE_DEFAULTDISPLAY);
+ WM_operator_properties_filesel(ot, FILE_TYPE_FOLDER | FILE_TYPE_IMAGE | FILE_TYPE_MOVIE, FILE_SPECIAL, FILE_OPENFILE,
+ WM_FILESEL_RELPATH | WM_FILESEL_FILES | WM_FILESEL_DIRECTORY, FILE_DEFAULTDISPLAY, FILE_SORT_ALPHA);
}
/******************* reload clip operator *********************/
@@ -486,18 +488,25 @@ typedef struct ViewZoomData {
float zoom;
int event_type;
float location[2];
+ wmTimer *timer;
+ double timer_lastdraw;
} ViewZoomData;
static void view_zoom_init(bContext *C, wmOperator *op, const wmEvent *event)
{
SpaceClip *sc = CTX_wm_space_clip(C);
ARegion *ar = CTX_wm_region(C);
-
ViewZoomData *vpd;
op->customdata = vpd = MEM_callocN(sizeof(ViewZoomData), "ClipViewZoomData");
WM_cursor_modal_set(CTX_wm_window(C), BC_NSEW_SCROLLCURSOR);
+ if (U.viewzoom == USER_ZOOM_CONT) {
+ /* needs a timer to continue redrawing */
+ vpd->timer = WM_event_add_timer(CTX_wm_manager(C), CTX_wm_window(C), TIMER, 0.01f);
+ vpd->timer_lastdraw = PIL_check_seconds_timer();
+ }
+
vpd->x = event->x;
vpd->y = event->y;
vpd->zoom = sc->zoom;
@@ -518,6 +527,10 @@ static void view_zoom_exit(bContext *C, wmOperator *op, bool cancel)
ED_region_tag_redraw(CTX_wm_region(C));
}
+ if (vpd->timer) {
+ WM_event_remove_timer(CTX_wm_manager(C), vpd->timer->win, vpd->timer);
+ }
+
WM_cursor_modal_restore(CTX_wm_window(C));
MEM_freeN(op->customdata);
}
@@ -555,22 +568,61 @@ static int view_zoom_invoke(bContext *C, wmOperator *op, const wmEvent *event)
}
}
+static void view_zoom_apply(bContext *C,
+ ViewZoomData *vpd,
+ wmOperator *op,
+ const wmEvent *event)
+{
+ float factor;
+
+ if (U.viewzoom == USER_ZOOM_CONT) {
+ SpaceClip *sclip = CTX_wm_space_clip(C);
+ double time = PIL_check_seconds_timer();
+ float time_step = (float)(time - vpd->timer_lastdraw);
+ float fac;
+ float zfac;
+
+ if (U.uiflag & USER_ZOOM_HORIZ) {
+ fac = (float)(event->x - vpd->x);
+ }
+ else {
+ fac = (float)(event->y - vpd->y);
+ }
+
+ if (U.uiflag & USER_ZOOM_INVERT) {
+ fac = -fac;
+ }
+
+ zfac = 1.0f + ((fac / 20.0f) * time_step);
+ vpd->timer_lastdraw = time;
+ factor = (sclip->zoom * zfac) / vpd->zoom;
+ }
+ else {
+ float delta = event->x - vpd->x + event->y - vpd->y;
+
+ if (U.uiflag & USER_ZOOM_INVERT) {
+ delta *= -1;
+ }
+
+ factor = 1.0f + delta / 300.0f;
+ }
+
+ RNA_float_set(op->ptr, "factor", factor);
+ sclip_zoom_set(C, vpd->zoom * factor, vpd->location);
+ ED_region_tag_redraw(CTX_wm_region(C));
+}
+
static int view_zoom_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
ViewZoomData *vpd = op->customdata;
- float delta, factor;
-
switch (event->type) {
+ case TIMER:
+ if (event->customdata == vpd->timer) {
+ view_zoom_apply(C, vpd, op, event);
+ }
+ break;
case MOUSEMOVE:
- delta = event->x - vpd->x + event->y - vpd->y;
-
- if (U.uiflag & USER_ZOOM_INVERT)
- delta *= -1;
-
- factor = 1.0f + delta / 300.0f;
- RNA_float_set(op->ptr, "factor", factor);
- sclip_zoom_set(C, vpd->zoom * factor, vpd->location);
- ED_region_tag_redraw(CTX_wm_region(C));
+ view_zoom_apply(C, vpd, op, event);
break;
default:
if (event->type == vpd->event_type && event->val == KM_RELEASE) {
@@ -606,7 +658,7 @@ void CLIP_OT_view_zoom(wmOperatorType *ot)
ot->poll = ED_space_clip_view_clip_poll;
/* flags */
- ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_POINTER;
+ ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_CURSOR;
/* properties */
prop = RNA_def_float(ot->srna, "factor", 0.0f, -FLT_MAX, FLT_MAX, "Factor",
@@ -860,7 +912,7 @@ static void change_frame_apply(bContext *C, wmOperator *op)
SUBFRA = 0.0f;
/* do updates */
- sound_seek_scene(CTX_data_main(C), scene);
+ BKE_sound_seek_scene(CTX_data_main(C), scene);
WM_event_add_notifier(C, NC_SCENE | ND_FRAME, scene);
}
@@ -1071,10 +1123,7 @@ typedef struct ProxyQueue {
typedef struct ProxyThread {
MovieClip *clip;
- ProxyQueue *queue;
-
struct MovieDistortion *distortion;
-
int *build_sizes, build_count;
int *build_undistort_sizes, build_undistort_count;
} ProxyThread;
@@ -1130,14 +1179,15 @@ static unsigned char *proxy_thread_next_frame(ProxyQueue *queue, MovieClip *clip
return mem;
}
-static void *do_proxy_thread(void *data_v)
+static void proxy_task_func(TaskPool *pool, void *task_data, int UNUSED(threadid))
{
- ProxyThread *data = (ProxyThread *) data_v;
+ ProxyThread *data = (ProxyThread *)task_data;
+ ProxyQueue *queue = (ProxyQueue *)BLI_task_pool_userdata(pool);
unsigned char *mem;
size_t size;
int cfra;
- while ((mem = proxy_thread_next_frame(data->queue, data->clip, &size, &cfra))) {
+ while ((mem = proxy_thread_next_frame(queue, data->clip, &size, &cfra))) {
ImBuf *ibuf;
ibuf = IMB_ibImageFromMemory(mem, size, IB_rect | IB_multilayer | IB_alphamode_detect,
@@ -1153,8 +1203,6 @@ static void *do_proxy_thread(void *data_v)
MEM_freeN(mem);
}
-
- return NULL;
}
static void do_sequence_proxy(void *pjv, int *build_sizes, int build_count,
@@ -1164,12 +1212,18 @@ static void do_sequence_proxy(void *pjv, int *build_sizes, int build_count,
ProxyJob *pj = pjv;
MovieClip *clip = pj->clip;
Scene *scene = pj->scene;
+ TaskScheduler *task_scheduler = BLI_task_scheduler_get();
+ TaskPool *task_pool;
int sfra = SFRA, efra = EFRA;
ProxyThread *handles;
- ListBase threads;
- int i, tot_thread = BLI_system_thread_count();
+ int i, tot_thread = BLI_task_scheduler_num_threads(task_scheduler);
+ int width, height;
ProxyQueue queue;
+ if (build_undistort_count) {
+ BKE_movieclip_get_size(clip, NULL, &width, &height);
+ }
+
BLI_spin_init(&queue.spin);
queue.cfra = sfra;
@@ -1179,16 +1233,13 @@ static void do_sequence_proxy(void *pjv, int *build_sizes, int build_count,
queue.do_update = do_update;
queue.progress = progress;
- handles = MEM_callocN(sizeof(ProxyThread) * tot_thread, "proxy threaded handles");
-
- if (tot_thread > 1)
- BLI_init_threads(&threads, do_proxy_thread, tot_thread);
-
+ task_pool = BLI_task_pool_create(task_scheduler, &queue);
+ handles = MEM_callocN(sizeof(ProxyThread) * tot_thread,
+ "proxy threaded handles");
for (i = 0; i < tot_thread; i++) {
ProxyThread *handle = &handles[i];
handle->clip = clip;
- handle->queue = &queue;
handle->build_count = build_count;
handle->build_sizes = build_sizes;
@@ -1197,29 +1248,29 @@ static void do_sequence_proxy(void *pjv, int *build_sizes, int build_count,
handle->build_undistort_sizes = build_undistort_sizes;
if (build_undistort_count) {
- int width, height;
- BKE_movieclip_get_size(clip, NULL, &width, &height);
- handle->distortion = BKE_tracking_distortion_new(&clip->tracking, width, height);
+ handle->distortion = BKE_tracking_distortion_new(&clip->tracking,
+ width, height);
}
- if (tot_thread > 1)
- BLI_insert_thread(&threads, handle);
+ BLI_task_pool_push(task_pool,
+ proxy_task_func,
+ handle,
+ false,
+ TASK_PRIORITY_LOW);
}
- if (tot_thread > 1)
- BLI_end_threads(&threads);
- else
- do_proxy_thread(handles);
-
- MEM_freeN(handles);
+ BLI_task_pool_work_and_wait(task_pool);
+ BLI_task_pool_free(task_pool);
if (build_undistort_count) {
for (i = 0; i < tot_thread; i++) {
ProxyThread *handle = &handles[i];
-
BKE_tracking_distortion_free(handle->distortion);
}
}
+
+ BLI_spin_end(&queue.spin);
+ MEM_freeN(handles);
}
static void proxy_startjob(void *pjv, short *stop, short *do_update, float *progress)
@@ -1256,7 +1307,14 @@ static void proxy_endjob(void *pjv)
if (pj->index_context)
IMB_anim_index_rebuild_finish(pj->index_context, pj->stop);
- BKE_movieclip_reload(pj->clip);
+ if (pj->clip->source == MCLIP_SRC_MOVIE) {
+ /* Timecode might have changed, so do a full reload to deal with this. */
+ BKE_movieclip_reload(pj->clip);
+ }
+ else {
+ /* For image sequences we'll preserve original cache. */
+ BKE_movieclip_clear_proxy_cache(pj->clip);
+ }
WM_main_add_notifier(NC_MOVIECLIP | ND_DISPLAY, pj->clip);
}
@@ -1284,7 +1342,8 @@ static int clip_rebuild_proxy_exec(bContext *C, wmOperator *UNUSED(op))
if (clip->anim) {
pj->index_context = IMB_anim_index_rebuild_context(clip->anim, clip->proxy.build_tc_flag,
- clip->proxy.build_size_flag, clip->proxy.quality);
+ clip->proxy.build_size_flag, clip->proxy.quality,
+ true, NULL);
}
WM_jobs_customdata_set(wm_job, pj, proxy_freejob);
diff --git a/source/blender/editors/space_clip/clip_toolbar.c b/source/blender/editors/space_clip/clip_toolbar.c
index 55b78219770..d31d7f53b30 100644
--- a/source/blender/editors/space_clip/clip_toolbar.c
+++ b/source/blender/editors/space_clip/clip_toolbar.c
@@ -38,7 +38,7 @@
#include "BLI_blenlib.h"
#include "BLI_utildefines.h"
-#include "BLF_translation.h"
+#include "BLT_translation.h"
#include "BKE_context.h"
#include "BKE_screen.h"
@@ -242,7 +242,7 @@ static void clip_panel_operator_redo(const bContext *C, Panel *pa)
uiLayoutSetEnabled(pa->layout, false);
/* note, blockfunc is a default but->func, use Handle func to allow button callbacks too */
- uiBlockSetHandleFunc(block, ED_undo_operator_repeat_cb_evt, op);
+ UI_block_func_handle_set(block, ED_undo_operator_repeat_cb_evt, op);
clip_panel_operator_redo_operator(C, pa, op);
}
@@ -258,7 +258,7 @@ void ED_clip_tool_props_register(ARegionType *art)
pt = MEM_callocN(sizeof(PanelType), "spacetype clip panel last operator");
strcpy(pt->idname, "CLIP_PT_last_operator");
strcpy(pt->label, N_("Operator"));
- strcpy(pt->translation_context, BLF_I18NCONTEXT_DEFAULT_BPYRNA);
+ strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
pt->draw_header = clip_panel_operator_redo_header;
pt->draw = clip_panel_operator_redo;
BLI_addtail(&art->paneltypes, pt);
diff --git a/source/blender/editors/space_clip/clip_utils.c b/source/blender/editors/space_clip/clip_utils.c
index a79ac1f7b82..48f8f587106 100644
--- a/source/blender/editors/space_clip/clip_utils.c
+++ b/source/blender/editors/space_clip/clip_utils.c
@@ -30,12 +30,10 @@
*/
#include "DNA_scene_types.h"
-#include "DNA_object_types.h" /* SELECT */
#include "MEM_guardedalloc.h"
#include "BLI_utildefines.h"
-#include "BLI_math.h"
#include "BLI_listbase.h"
#include "BLI_string.h"
@@ -54,8 +52,6 @@
#include "ED_screen.h"
#include "ED_clip.h"
-#include "RNA_access.h"
-#include "RNA_define.h"
#include "UI_interface.h"
#include "UI_resources.h"
@@ -181,9 +177,7 @@ void clip_delete_track(bContext *C, MovieClip *clip, MovieTrackingTrack *track)
MovieTracking *tracking = &clip->tracking;
MovieTrackingStabilization *stab = &tracking->stabilization;
MovieTrackingTrack *act_track = BKE_tracking_track_get_active(tracking);
- MovieTrackingPlaneTrack *plane_track, *next_plane_track;
ListBase *tracksbase = BKE_tracking_get_active_tracks(tracking);
- ListBase *plane_tracks_base = BKE_tracking_get_active_plane_tracks(tracking);
bool has_bundle = false, update_stab = false;
char track_name_escaped[MAX_NAME], prefix[MAX_NAME * 2];
@@ -201,49 +195,7 @@ void clip_delete_track(bContext *C, MovieClip *clip, MovieTrackingTrack *track)
has_bundle = true;
/* Make sure no plane will use freed track */
- for (plane_track = plane_tracks_base->first;
- plane_track;
- plane_track = next_plane_track)
- {
- bool found = false;
- int i;
-
- next_plane_track = plane_track->next;
-
- for (i = 0; i < plane_track->point_tracksnr; i++) {
- if (plane_track->point_tracks[i] == track) {
- found = true;
- break;
- }
- }
-
- if (!found) {
- continue;
- }
-
- if (plane_track->point_tracksnr > 4) {
- int track_index;
- MovieTrackingTrack **new_point_tracks;
-
- new_point_tracks = MEM_mallocN(sizeof(*new_point_tracks) * plane_track->point_tracksnr,
- "new point tracks array");
-
- for (i = 0, track_index = 0; i < plane_track->point_tracksnr; i++) {
- if (plane_track->point_tracks[i] != track) {
- new_point_tracks[track_index++] = plane_track->point_tracks[i];
- }
- }
-
- MEM_freeN(plane_track->point_tracks);
- plane_track->point_tracks = new_point_tracks;
- plane_track->point_tracksnr--;
- }
- else {
- /* Delete planes with less than 3 point tracks in it. */
- BKE_tracking_plane_track_free(plane_track);
- BLI_freelinkN(plane_tracks_base, plane_track);
- }
- }
+ BKE_tracking_plane_tracks_remove_point_track(tracking, track);
/* Delete f-curves associated with the track (such as weight, i.e.) */
BLI_strescape(track_name_escaped, track->name, sizeof(track_name_escaped));
diff --git a/source/blender/editors/space_clip/space_clip.c b/source/blender/editors/space_clip/space_clip.c
index a797a60f74c..f119fe23c12 100644
--- a/source/blender/editors/space_clip/space_clip.c
+++ b/source/blender/editors/space_clip/space_clip.c
@@ -55,7 +55,7 @@
#include "ED_screen.h"
#include "ED_clip.h"
#include "ED_transform.h"
-#include "ED_uvedit.h" /* just for draw_image_cursor */
+#include "ED_uvedit.h" /* just for ED_image_draw_cursor */
#include "IMB_imbuf.h"
@@ -206,7 +206,7 @@ static void clip_scopes_tag_refresh(ScrArea *sa)
if (sc->mode != SC_MODE_TRACKING)
return;
- /* only while proeprties are visible */
+ /* only while properties are visible */
for (ar = sa->regionbase.first; ar; ar = ar->next) {
if (ar->regiontype == RGN_TYPE_UI && ar->flag & RGN_FLAG_HIDDEN)
return;
@@ -420,6 +420,9 @@ static void clip_listener(bScreen *UNUSED(sc), ScrArea *sa, wmNotifier *wmn)
clip_scopes_check_gpencil_change(sa);
ED_area_tag_redraw(sa);
}
+ else if (wmn->data & ND_GPENCIL_EDITMODE) {
+ ED_area_tag_redraw(sa);
+ }
break;
}
}
@@ -1159,7 +1162,7 @@ static void clip_main_area_draw(const bContext *C, ARegion *ar)
/* if tracking is in progress, we should synchronize framenr from clipuser
* so latest tracked frame would be shown */
if (clip && clip->tracking_context)
- BKE_tracking_context_sync_user(clip->tracking_context, &sc->user);
+ BKE_autotrack_context_sync_user(clip->tracking_context, &sc->user);
if (sc->flag & SC_LOCK_SELECTION) {
ImBuf *tmpibuf = NULL;
@@ -1218,7 +1221,7 @@ static void clip_main_area_draw(const bContext *C, ARegion *ar)
glScalef(zoomx, zoomy, 0);
glMultMatrixf(sc->stabmat);
glScalef(width, height, 0);
- draw_image_cursor(ar, sc->cursor);
+ ED_image_draw_cursor(ar, sc->cursor);
glPopMatrix();
}
@@ -1245,6 +1248,8 @@ static void clip_main_area_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), AR
case NC_GPENCIL:
if (wmn->action == NA_EDITED)
ED_region_tag_redraw(ar);
+ else if (wmn->data & ND_GPENCIL_EDITMODE)
+ ED_region_tag_redraw(ar);
break;
}
}
@@ -1440,7 +1445,7 @@ static void clip_tools_area_init(wmWindowManager *wm, ARegion *ar)
static void clip_tools_area_draw(const bContext *C, ARegion *ar)
{
- ED_region_panels(C, ar, 1, NULL, -1);
+ ED_region_panels(C, ar, NULL, -1, true);
}
/****************** tool properties region ******************/
@@ -1487,7 +1492,7 @@ static void clip_properties_area_draw(const bContext *C, ARegion *ar)
BKE_movieclip_update_scopes(sc->clip, &sc->user, &sc->scopes);
- ED_region_panels(C, ar, 1, NULL, -1);
+ ED_region_panels(C, ar, NULL, -1, true);
}
static void clip_properties_area_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn)
@@ -1495,7 +1500,7 @@ static void clip_properties_area_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(s
/* context changes */
switch (wmn->category) {
case NC_GPENCIL:
- if (wmn->data == ND_DATA)
+ if (ELEM(wmn->data, ND_DATA, ND_GPENCIL_EDITMODE))
ED_region_tag_redraw(ar);
break;
case NC_BRUSH:
diff --git a/source/blender/editors/space_clip/tracking_ops.c b/source/blender/editors/space_clip/tracking_ops.c
index fb6b1a0033c..a19fa97965a 100644
--- a/source/blender/editors/space_clip/tracking_ops.c
+++ b/source/blender/editors/space_clip/tracking_ops.c
@@ -41,7 +41,6 @@
#include "BLI_utildefines.h"
#include "BLI_math.h"
#include "BLI_listbase.h"
-#include "BLI_rect.h"
#include "BLI_blenlib.h"
#include "BKE_main.h"
@@ -65,16 +64,14 @@
#include "IMB_imbuf_types.h"
#include "IMB_imbuf.h"
-#include "UI_interface.h"
#include "RNA_access.h"
#include "RNA_define.h"
-#include "BLF_translation.h"
+#include "BLT_translation.h"
#include "PIL_time.h"
-#include "UI_view2d.h"
#include "clip_intern.h" // own include
@@ -828,12 +825,8 @@ static void apply_mouse_slide(bContext *C, SlideMarkerData *data)
plane_track = plane_track->next)
{
if ((plane_track->flag & PLANE_TRACK_AUTOKEY) == 0) {
- int i;
- for (i = 0; i < plane_track->point_tracksnr; i++) {
- if (plane_track->point_tracks[i] == data->track) {
- BKE_tracking_track_plane_from_existing_motion(plane_track, framenr);
- break;
- }
+ if (BKE_tracking_plane_track_has_point_track(plane_track, data->track)) {
+ BKE_tracking_track_plane_from_existing_motion(plane_track, framenr);
}
}
}
@@ -1073,7 +1066,7 @@ void CLIP_OT_slide_marker(wmOperatorType *ot)
ot->modal = slide_marker_modal;
/* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_GRAB_POINTER | OPTYPE_BLOCKING;
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_GRAB_CURSOR | OPTYPE_BLOCKING;
/* properties */
RNA_def_float_vector(ot->srna, "offset", 2, NULL, -FLT_MAX, FLT_MAX,
@@ -1083,7 +1076,7 @@ void CLIP_OT_slide_marker(wmOperatorType *ot)
/********************** track operator *********************/
typedef struct TrackMarkersJob {
- struct MovieTrackingContext *context; /* tracking context */
+ struct AutoTrackContext *context; /* tracking context */
int sfra, efra, lastfra; /* Start, end and recently tracked frames */
int backwards; /* Backwards tracking flag */
MovieClip *clip; /* Clip which is tracking */
@@ -1231,7 +1224,7 @@ static int track_markers_initjob(bContext *C, TrackMarkersJob *tmj, int backward
tmj->delay /= 2;
}
- tmj->context = BKE_tracking_context_new(clip, &sc->user, backwards, 1);
+ tmj->context = BKE_autotrack_context_new(clip, &sc->user, backwards, 1);
clip->tracking_context = tmj->context;
@@ -1265,14 +1258,14 @@ static void track_markers_startjob(void *tmv, short *stop, short *do_update, flo
double start_time = PIL_check_seconds_timer(), exec_time;
- if (!BKE_tracking_context_step(tmj->context))
+ if (!BKE_autotrack_context_step(tmj->context))
break;
exec_time = PIL_check_seconds_timer() - start_time;
if (tmj->delay > (float)exec_time)
PIL_sleep_ms(tmj->delay - (float)exec_time);
}
- else if (!BKE_tracking_context_step(tmj->context))
+ else if (!BKE_autotrack_context_step(tmj->context))
break;
*do_update = true;
@@ -1296,7 +1289,7 @@ static void track_markers_updatejob(void *tmv)
{
TrackMarkersJob *tmj = (TrackMarkersJob *)tmv;
- BKE_tracking_context_sync(tmj->context);
+ BKE_autotrack_context_sync(tmj->context);
}
static void track_markers_endjob(void *tmv)
@@ -1310,8 +1303,8 @@ static void track_markers_endjob(void *tmv)
ED_update_for_newframe(tmj->main, tmj->scene, 0);
}
- BKE_tracking_context_sync(tmj->context);
- BKE_tracking_context_finish(tmj->context);
+ BKE_autotrack_context_sync(tmj->context);
+ BKE_autotrack_context_finish(tmj->context);
WM_main_add_notifier(NC_SCENE | ND_FRAME, tmj->scene);
}
@@ -1319,7 +1312,7 @@ static void track_markers_endjob(void *tmv)
static void track_markers_freejob(void *tmv)
{
TrackMarkersJob *tmj = (TrackMarkersJob *)tmv;
- BKE_tracking_context_free(tmj->context);
+ BKE_autotrack_context_free(tmj->context);
MEM_freeN(tmj);
}
@@ -1328,7 +1321,7 @@ static int track_markers_exec(bContext *C, wmOperator *op)
SpaceClip *sc;
MovieClip *clip;
Scene *scene = CTX_data_scene(C);
- struct MovieTrackingContext *context;
+ struct AutoTrackContext *context;
MovieClipUser *user, fake_user = {0};
int framenr, sfra, efra;
const bool backwards = RNA_boolean_get(op->ptr, "backwards");
@@ -1388,10 +1381,10 @@ static int track_markers_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
/* do not disable tracks due to threshold when tracking frame-by-frame */
- context = BKE_tracking_context_new(clip, user, backwards, sequence);
+ context = BKE_autotrack_context_new(clip, user, backwards, sequence);
while (framenr != efra) {
- if (!BKE_tracking_context_step(context))
+ if (!BKE_autotrack_context_step(context))
break;
if (backwards) framenr--;
@@ -1401,9 +1394,9 @@ static int track_markers_exec(bContext *C, wmOperator *op)
break;
}
- BKE_tracking_context_sync(context);
- BKE_tracking_context_finish(context);
- BKE_tracking_context_free(context);
+ BKE_autotrack_context_sync(context);
+ BKE_autotrack_context_finish(context);
+ BKE_autotrack_context_free(context);
/* update scene current frame to the lastes tracked frame */
scene->r.cfra = BKE_movieclip_remap_clip_to_scene_frame(clip, framenr);
@@ -1433,6 +1426,7 @@ static int track_markers_invoke(bContext *C, wmOperator *op, const wmEvent *UNUS
}
clip = ED_space_clip_get_clip(sc);
+ BLI_assert(clip != NULL);
framenr = ED_space_clip_get_clip_frame_number(sc);
if (WM_jobs_test(CTX_wm_manager(C), sa, WM_JOB_TYPE_ANY)) {
@@ -1511,6 +1505,7 @@ void CLIP_OT_track_markers(wmOperatorType *ot)
ot->exec = track_markers_exec;
ot->invoke = track_markers_invoke;
ot->modal = track_markers_modal;
+ ot->poll = ED_space_clip_tracking_poll;
/* flags */
ot->flag = OPTYPE_UNDO;
@@ -1886,7 +1881,7 @@ void CLIP_OT_clear_track_path(wmOperatorType *ot)
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* proeprties */
+ /* properties */
RNA_def_enum(ot->srna, "action", clear_path_actions, TRACK_CLEAR_REMAINED, "Action", "Clear action to execute");
RNA_def_boolean(ot->srna, "clear_active", 0, "Clear Active", "Clear active track only instead of all selected tracks");
}
@@ -2045,7 +2040,7 @@ static void object_solver_inverted_matrix(Scene *scene, Object *ob, float invmat
bool found = false;
for (con = ob->constraints.first; con; con = con->next) {
- bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
+ const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
if (!cti)
continue;
@@ -2076,7 +2071,7 @@ static Object *object_solver_camera(Scene *scene, Object *ob)
bConstraint *con;
for (con = ob->constraints.first; con; con = con->next) {
- bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
+ const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
if (!cti)
continue;
@@ -3057,7 +3052,7 @@ static int frame_jump_exec(bContext *C, wmOperator *op)
if (CFRA != sc->user.framenr) {
CFRA = sc->user.framenr;
- sound_seek_scene(CTX_data_main(C), scene);
+ BKE_sound_seek_scene(CTX_data_main(C), scene);
WM_event_add_notifier(C, NC_SCENE | ND_FRAME, scene);
}
@@ -3120,6 +3115,12 @@ static int join_tracks_exec(bContext *C, wmOperator *op)
if (tracking->stabilization.rot_track == track)
tracking->stabilization.rot_track = act_track;
+ /* TODO(sergey): Re-evaluate planes with auto-key. */
+ BKE_tracking_plane_tracks_replace_point_track(tracking,
+ track,
+ act_track);
+
+
BKE_tracking_track_free(track);
BLI_freelinkN(tracksbase, track);
}
@@ -4184,7 +4185,7 @@ void CLIP_OT_slide_plane_marker(wmOperatorType *ot)
ot->modal = slide_plane_marker_modal;
/* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_GRAB_POINTER | OPTYPE_BLOCKING;
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_GRAB_CURSOR | OPTYPE_BLOCKING;
}
/********************** Insert track keyframe operator *********************/
diff --git a/source/blender/editors/space_clip/tracking_select.c b/source/blender/editors/space_clip/tracking_select.c
index 860d9dc6b3c..8a2bf17c667 100644
--- a/source/blender/editors/space_clip/tracking_select.c
+++ b/source/blender/editors/space_clip/tracking_select.c
@@ -36,7 +36,6 @@
#include "BLI_utildefines.h"
#include "BLI_math.h"
-#include "BLI_listbase.h"
#include "BLI_rect.h"
#include "BLI_lasso.h"
@@ -49,16 +48,9 @@
#include "ED_screen.h"
#include "ED_clip.h"
-#include "IMB_imbuf_types.h"
-#include "IMB_imbuf.h"
-
-#include "UI_interface.h"
-
#include "RNA_access.h"
#include "RNA_define.h"
-#include "PIL_time.h"
-
#include "UI_view2d.h"
#include "clip_intern.h" // own include
@@ -70,7 +62,6 @@ static float dist_to_crns(float co[2], float pos[2], float crns[4][2]);
static int mouse_on_side(float co[2], float x1, float y1, float x2, float y2, float epsx, float epsy)
{
if (x1 > x2)
-
SWAP(float, x1, x2);
if (y1 > y2)
@@ -1006,6 +997,6 @@ void CLIP_OT_select_grouped(wmOperatorType *ot)
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* proeprties */
+ /* properties */
RNA_def_enum(ot->srna, "group", select_group_items, TRACK_CLEAR_REMAINED, "Action", "Clear action to execute");
}
diff --git a/source/blender/editors/space_console/CMakeLists.txt b/source/blender/editors/space_console/CMakeLists.txt
index 241a48c1e2d..ecfb1f0e0df 100644
--- a/source/blender/editors/space_console/CMakeLists.txt
+++ b/source/blender/editors/space_console/CMakeLists.txt
@@ -23,10 +23,12 @@ set(INC
../../blenfont
../../blenkernel
../../blenlib
+ ../../gpu
../../makesdna
../../makesrna
../../windowmanager
../../../../intern/guardedalloc
+ ../../../../intern/glew-mx
)
set(INC_SYS
@@ -45,4 +47,6 @@ if(WITH_PYTHON)
add_definitions(-DWITH_PYTHON)
endif()
+add_definitions(${GL_DEFINITIONS})
+
blender_add_lib(bf_editor_space_console "${SRC}" "${INC}" "${INC_SYS}")
diff --git a/source/blender/editors/space_console/SConscript b/source/blender/editors/space_console/SConscript
index 0395a33cd97..f189cd3920a 100644
--- a/source/blender/editors/space_console/SConscript
+++ b/source/blender/editors/space_console/SConscript
@@ -28,16 +28,20 @@
Import ('env')
sources = env.Glob('*.c')
+
defs = []
+defs += env['BF_GL_DEFINITIONS']
incs = [
'../include',
- '#/extern/glew/include',
'#/intern/guardedalloc',
+ env['BF_GLEW_INC'],
+ '#/intern/glew-mx',
'../../makesdna',
'../../makesrna',
'../../blenkernel',
'../../blenlib',
+ '../../gpu',
'../../windowmanager',
'../../blenfont',
]
diff --git a/source/blender/editors/space_console/console_draw.c b/source/blender/editors/space_console/console_draw.c
index 635d5ea07fd..d206ce4699e 100644
--- a/source/blender/editors/space_console/console_draw.c
+++ b/source/blender/editors/space_console/console_draw.c
@@ -30,7 +30,6 @@
#include <sys/stat.h>
#include <limits.h>
-#include "BLF_api.h"
#include "BLI_blenlib.h"
#include "BLI_utildefines.h"
diff --git a/source/blender/editors/space_console/console_intern.h b/source/blender/editors/space_console/console_intern.h
index 00f1f8c21c9..d8a4a6fd2bb 100644
--- a/source/blender/editors/space_console/console_intern.h
+++ b/source/blender/editors/space_console/console_intern.h
@@ -31,7 +31,6 @@
struct ConsoleLine;
struct wmOperatorType;
-struct ReportList;
struct bContext;
/* console_draw.c */
@@ -66,6 +65,7 @@ void CONSOLE_OT_history_cycle(struct wmOperatorType *ot);
void CONSOLE_OT_copy(struct wmOperatorType *ot);
void CONSOLE_OT_paste(struct wmOperatorType *ot);
void CONSOLE_OT_select_set(struct wmOperatorType *ot);
+void CONSOLE_OT_select_word(struct wmOperatorType *ot);
enum { LINE_BEGIN, LINE_END, PREV_CHAR, NEXT_CHAR, PREV_WORD, NEXT_WORD };
enum { DEL_ALL, DEL_NEXT_CHAR, DEL_PREV_CHAR, DEL_NEXT_WORD, DEL_PREV_WORD, DEL_SELECTION, DEL_NEXT_SEL, DEL_PREV_SEL };
diff --git a/source/blender/editors/space_console/console_ops.c b/source/blender/editors/space_console/console_ops.c
index b44e942527c..92731c2f135 100644
--- a/source/blender/editors/space_console/console_ops.c
+++ b/source/blender/editors/space_console/console_ops.c
@@ -95,7 +95,7 @@ static void console_scrollback_limit(SpaceConsole *sc)
if (U.scrollback < 32) U.scrollback = 256; // XXX - save in user defaults
- for (tot = BLI_countlist(&sc->scrollback); tot > U.scrollback; tot--)
+ for (tot = BLI_listbase_count(&sc->scrollback); tot > U.scrollback; tot--)
console_scrollback_free(sc, sc->scrollback.first);
}
@@ -107,7 +107,7 @@ static ConsoleLine *console_history_find(SpaceConsole *sc, const char *str, Cons
if (cl == cl_ignore)
continue;
- if (strcmp(str, cl->line) == 0)
+ if (STREQ(str, cl->line))
return cl;
}
@@ -136,7 +136,7 @@ static void console_lb_debug__internal(ListBase *lb)
{
ConsoleLine *cl;
- printf("%d: ", BLI_countlist(lb));
+ printf("%d: ", BLI_listbase_count(lb));
for (cl = lb->first; cl; cl = cl->next)
printf("<%s> ", cl->line);
printf("\n");
@@ -262,6 +262,40 @@ static int console_line_insert(ConsoleLine *ci, char *str)
return len;
}
+/**
+ * Take an absolute index and give the line/column info.
+ *
+ * \note be sure to call console_scrollback_prompt_begin first
+ */
+static bool console_line_column_from_index(
+ SpaceConsole *sc, const int pos,
+ ConsoleLine **r_cl, int *r_cl_offset, int *r_col)
+{
+ ConsoleLine *cl;
+ int offset = 0;
+
+ for (cl = sc->scrollback.last; cl; cl = cl->prev) {
+ offset += cl->len + 1;
+ if (offset >= pos) {
+ break;
+ }
+ }
+
+ if (cl) {
+ offset -= 1;
+ *r_cl = cl;
+ *r_cl_offset = offset;
+ *r_col = offset - pos;
+ return true;
+ }
+ else {
+ *r_cl = NULL;
+ *r_cl_offset = -1;
+ *r_col = -1;
+ return false;
+ }
+}
+
/* static funcs for text editing */
/* similar to the text editor, with some not used. keep compatible */
@@ -722,7 +756,7 @@ static int console_history_cycle_exec(bContext *C, wmOperator *op)
if (ci->prev) {
ConsoleLine *ci_prev = (ConsoleLine *)ci->prev;
- if (strcmp(ci->line, ci_prev->line) == 0)
+ if (STREQ(ci->line, ci_prev->line))
console_history_free(sc, ci_prev);
}
@@ -791,7 +825,7 @@ static int console_history_append_exec(bContext *C, wmOperator *op)
while ((cl = console_history_find(sc, ci->line, ci)))
console_history_free(sc, cl);
- if (strcmp(str, ci->line) == 0) {
+ if (STREQ(str, ci->line)) {
MEM_freeN(str);
return OPERATOR_FINISHED;
}
@@ -1134,3 +1168,57 @@ void CONSOLE_OT_select_set(wmOperatorType *ot)
ot->cancel = console_modal_select_cancel;
ot->poll = ED_operator_console_active;
}
+
+static int console_selectword_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *event)
+{
+ SpaceConsole *sc = CTX_wm_space_console(C);
+ ARegion *ar = CTX_wm_region(C);
+
+ ConsoleLine cl_dummy = {NULL};
+ ConsoleLine *cl;
+ int ret = OPERATOR_CANCELLED;
+ int pos, offset, n;
+
+ pos = console_char_pick(sc, ar, event->mval);
+
+ console_scrollback_prompt_begin(sc, &cl_dummy);
+
+ if (console_line_column_from_index(sc, pos, &cl, &offset, &n)) {
+ int sel[2] = {n, n};
+
+ BLI_str_cursor_step_utf8(
+ cl->line, cl->len,
+ &sel[0], STRCUR_DIR_NEXT,
+ STRCUR_JUMP_DELIM, true);
+
+ BLI_str_cursor_step_utf8(
+ cl->line, cl->len,
+ &sel[1], STRCUR_DIR_PREV,
+ STRCUR_JUMP_DELIM, true);
+
+ sel[0] = offset - sel[0];
+ sel[1] = offset - sel[1];
+
+ if ((sel[0] != sc->sel_start) || (sel[1] != sc->sel_end)) {
+ sc->sel_start = sel[0];
+ sc->sel_end = sel[1];
+ ED_area_tag_redraw(CTX_wm_area(C));
+ ret = OPERATOR_FINISHED;
+ }
+ }
+
+ console_scrollback_prompt_end(sc, &cl_dummy);
+ return ret;
+}
+
+void CONSOLE_OT_select_word(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Select Word";
+ ot->description = "Select word at cursor position";
+ ot->idname = "CONSOLE_OT_select_word";
+
+ /* api callbacks */
+ ot->invoke = console_selectword_invoke;
+ ot->poll = ED_operator_console_active;
+}
diff --git a/source/blender/editors/space_console/space_console.c b/source/blender/editors/space_console/space_console.c
index e4a61a8f06e..a592f35f629 100644
--- a/source/blender/editors/space_console/space_console.c
+++ b/source/blender/editors/space_console/space_console.c
@@ -270,6 +270,7 @@ static void console_operatortypes(void)
WM_operatortype_append(CONSOLE_OT_copy);
WM_operatortype_append(CONSOLE_OT_paste);
WM_operatortype_append(CONSOLE_OT_select_set);
+ WM_operatortype_append(CONSOLE_OT_select_word);
}
static void console_keymap(struct wmKeyConfig *keyconf)
@@ -348,6 +349,7 @@ static void console_keymap(struct wmKeyConfig *keyconf)
#endif
WM_keymap_add_item(keymap, "CONSOLE_OT_select_set", LEFTMOUSE, KM_PRESS, 0, 0);
+ WM_keymap_add_item(keymap, "CONSOLE_OT_select_word", LEFTMOUSE, KM_DBL_CLICK, 0, 0);
RNA_string_set(WM_keymap_add_item(keymap, "CONSOLE_OT_insert", TABKEY, KM_PRESS, KM_CTRL, 0)->ptr, "text", "\t"); /* fake tabs */
diff --git a/source/blender/editors/space_file/CMakeLists.txt b/source/blender/editors/space_file/CMakeLists.txt
index 3b2db3ee7bc..fd701a8be4c 100644
--- a/source/blender/editors/space_file/CMakeLists.txt
+++ b/source/blender/editors/space_file/CMakeLists.txt
@@ -24,12 +24,16 @@ set(INC
../../blenkernel
../../blenlib
../../blenloader
+ ../../blentranslation
../../imbuf
+ ../../gpu
../../makesdna
../../makesrna
../../render/extern/include
../../windowmanager
+ ../../../../intern/atomic
../../../../intern/guardedalloc
+ ../../../../intern/glew-mx
)
set(INC_SYS
@@ -40,6 +44,7 @@ set(SRC
file_draw.c
file_ops.c
file_panels.c
+ file_utils.c
filelist.c
filesel.c
fsmenu.c
@@ -86,6 +91,8 @@ if(WITH_INTERNATIONAL)
add_definitions(-DWITH_INTERNATIONAL)
endif()
+add_definitions(${GL_DEFINITIONS})
+
if(WITH_FREESTYLE)
add_definitions(-DWITH_FREESTYLE)
endif()
diff --git a/source/blender/editors/space_file/SConscript b/source/blender/editors/space_file/SConscript
index d42394454eb..a66a14a32de 100644
--- a/source/blender/editors/space_file/SConscript
+++ b/source/blender/editors/space_file/SConscript
@@ -29,13 +29,17 @@ Import ('env')
sources = env.Glob('*.c')
incs = [
+ '#/intern/atomic',
'#/intern/guardedalloc',
- '#/extern/glew/include',
+ env['BF_GLEW_INC'],
+ '#/intern/glew-mx',
'../include',
'../../blenfont',
'../../blenkernel',
'../../blenlib',
'../../blenloader',
+ '../../blentranslation',
+ '../../gpu',
'../../imbuf',
'../../makesdna',
'../../makesrna',
@@ -45,6 +49,7 @@ incs = [
incs = ' '.join(incs)
defs = []
+defs += env['BF_GL_DEFINITIONS']
if env['WITH_BF_OPENJPEG']:
defs.append('WITH_OPENJPEG')
diff --git a/source/blender/editors/space_file/file_draw.c b/source/blender/editors/space_file/file_draw.c
index 3e099b43a4b..2d9ecbdf415 100644
--- a/source/blender/editors/space_file/file_draw.c
+++ b/source/blender/editors/space_file/file_draw.c
@@ -35,6 +35,7 @@
#include "BLI_blenlib.h"
#include "BLI_utildefines.h"
#include "BLI_fileops_types.h"
+#include "BLI_math.h"
#ifdef WIN32
# include "BLI_winstuff.h"
@@ -47,8 +48,9 @@
#include "BKE_global.h"
#include "BKE_main.h"
-#include "BLF_api.h"
-#include "BLF_translation.h"
+#include "BLO_readfile.h"
+
+#include "BLT_translation.h"
#include "IMB_imbuf_types.h"
@@ -65,13 +67,20 @@
#include "UI_resources.h"
#include "UI_view2d.h"
+#include "WM_api.h"
#include "WM_types.h"
-#include "fsmenu.h"
#include "filelist.h"
#include "file_intern.h" // own include
+/* Dummy helper - we need dynamic tooltips here. */
+static char *file_draw_tooltip_func(bContext *UNUSED(C), void *argN, const char *UNUSED(tip))
+{
+ char *dyn_tooltip = argN;
+ return BLI_strdup(dyn_tooltip);
+}
+
/* Note: This function uses pixelspace (0, 0, winx, winy), not view2d.
* The controls are laid out as follows:
*
@@ -113,31 +122,37 @@ void file_draw_buttons(const bContext *C, ARegion *ar)
SpaceFile *sfile = CTX_wm_space_file(C);
FileSelectParams *params = ED_fileselect_get_params(sfile);
ARegion *artmp;
+ const bool is_browse_only = (sfile->op == NULL);
/* Initialize UI block. */
BLI_snprintf(uiblockstr, sizeof(uiblockstr), "win %p", (void *)ar);
- block = uiBeginBlock(C, ar, uiblockstr, UI_EMBOSS);
+ block = UI_block_begin(C, ar, uiblockstr, UI_EMBOSS);
/* exception to make space for collapsed region icon */
for (artmp = CTX_wm_area(C)->regionbase.first; artmp; artmp = artmp->next) {
- if (artmp->regiontype == RGN_TYPE_CHANNELS && artmp->flag & RGN_FLAG_HIDDEN) {
+ if (artmp->regiontype == RGN_TYPE_TOOLS && artmp->flag & RGN_FLAG_HIDDEN) {
chan_offs = 16;
min_x += chan_offs;
available_w -= chan_offs;
}
}
-
+
/* Is there enough space for the execute / cancel buttons? */
- loadbutton = UI_GetStringWidth(sfile->params->title) + btn_margin;
- if (loadbutton < btn_minw) {
- loadbutton = MAX2(btn_minw,
- btn_margin + UI_GetStringWidth(params->title));
- }
-
- if (available_w <= loadbutton + separator + input_minw || params->title[0] == 0) {
+
+
+ if (is_browse_only) {
loadbutton = 0;
}
else {
+ const uiFontStyle *fstyle = UI_FSTYLE_WIDGET;
+ loadbutton = UI_fontstyle_string_width(fstyle, params->title) + btn_margin;
+ CLAMP_MIN(loadbutton, btn_minw);
+ if (available_w <= loadbutton + separator + input_minw) {
+ loadbutton = 0;
+ }
+ }
+
+ if (loadbutton) {
line1_w -= (loadbutton + separator);
line2_w = line1_w;
}
@@ -150,127 +165,105 @@ void file_draw_buttons(const bContext *C, ARegion *ar)
else {
line2_w -= (fnumbuttons + separator);
}
-
+
/* Text input fields for directory and file. */
if (available_w > 0) {
+ const struct FileDirEntry *file = sfile->files ? filelist_file(sfile->files, params->active_file) : NULL;
int overwrite_alert = file_draw_check_exists(sfile);
+ const bool is_active_dir = file && (file->typeflag & FILE_TYPE_FOLDER);
+
/* callbacks for operator check functions */
- uiBlockSetFunc(block, file_draw_check_cb, NULL, NULL);
+ UI_block_func_set(block, file_draw_check_cb, NULL, NULL);
- but = uiDefBut(block, TEX, -1, "",
+ but = uiDefBut(block, UI_BTYPE_TEXT, -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);
+ UI_but_func_complete_set(but, autocomplete_directory, NULL);
+ UI_but_flag_enable(but, UI_BUT_NO_UTF8);
+ UI_but_flag_disable(but, UI_BUT_UNDO);
+ UI_but_funcN_set(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);
+ UI_but_flag_enable(but, UI_BUT_DISABLED);
if ((params->flag & FILE_DIRSEL_ONLY) == 0) {
- but = uiDefBut(block, TEX, -1, "",
+ but = uiDefBut(block, UI_BTYPE_TEXT, -1, "",
min_x, line2_y, line2_w - chan_offs, btn_h,
- params->file, 0.0, (float)FILE_MAXFILE, 0, 0,
+ is_active_dir ? (char *)"" : 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);
+ UI_but_func_complete_set(but, autocomplete_file, NULL);
+ UI_but_flag_enable(but, UI_BUT_NO_UTF8);
+ UI_but_flag_disable(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);
+ UI_but_funcN_set(but, file_filename_enter_handle, NULL, but);
/* check if this overrides a file and if the operator option is used */
if (overwrite_alert) {
- uiButSetFlag(but, UI_BUT_REDALERT);
+ UI_but_flag_enable(but, UI_BUT_REDALERT);
}
}
/* clear func */
- uiBlockSetFunc(block, NULL, NULL, NULL);
+ UI_block_func_set(block, NULL, NULL, NULL);
}
/* Filename number increment / decrement buttons. */
if (fnumbuttons && (params->flag & FILE_DIRSEL_ONLY) == 0) {
- uiBlockBeginAlign(block);
- but = uiDefIconButO(block, BUT, "FILE_OT_filenum", 0, ICON_ZOOMOUT,
+ UI_block_align_begin(block);
+ but = uiDefIconButO(block, UI_BTYPE_BUT, "FILE_OT_filenum", 0, ICON_ZOOMOUT,
min_x + line2_w + separator - chan_offs, line2_y,
btn_fn_w, btn_h,
TIP_("Decrement the filename number"));
- RNA_int_set(uiButGetOperatorPtrRNA(but), "increment", -1);
+ RNA_int_set(UI_but_operator_ptr_get(but), "increment", -1);
- but = uiDefIconButO(block, BUT, "FILE_OT_filenum", 0, ICON_ZOOMIN,
+ but = uiDefIconButO(block, UI_BTYPE_BUT, "FILE_OT_filenum", 0, ICON_ZOOMIN,
min_x + line2_w + separator + btn_fn_w - chan_offs, line2_y,
btn_fn_w, btn_h,
TIP_("Increment the filename number"));
- RNA_int_set(uiButGetOperatorPtrRNA(but), "increment", 1);
- uiBlockEndAlign(block);
+ RNA_int_set(UI_but_operator_ptr_get(but), "increment", 1);
+ UI_block_align_end(block);
}
/* Execute / cancel buttons. */
if (loadbutton) {
- /* params->title is already translated! */
- uiDefButO(block, BUT, "FILE_OT_execute", WM_OP_EXEC_REGION_WIN, params->title,
+ const struct FileDirEntry *file = sfile->files ? filelist_file(sfile->files, params->active_file) : NULL;
+ char const *str_exec;
+
+ if (file && FILENAME_IS_PARENT(file->relpath)) {
+ str_exec = IFACE_("Parent Directory");
+ }
+ else if (file && file->typeflag & FILE_TYPE_DIR) {
+ str_exec = IFACE_("Open Directory");
+ }
+ else {
+ str_exec = params->title; /* params->title is already translated! */
+ }
+
+ uiDefButO(block, UI_BTYPE_BUT, "FILE_OT_execute", WM_OP_EXEC_REGION_WIN, str_exec,
max_x - loadbutton, line1_y, loadbutton, btn_h, "");
- uiDefButO(block, BUT, "FILE_OT_cancel", WM_OP_EXEC_REGION_WIN, IFACE_("Cancel"),
+ uiDefButO(block, UI_BTYPE_BUT, "FILE_OT_cancel", WM_OP_EXEC_REGION_WIN, IFACE_("Cancel"),
max_x - loadbutton, line2_y, loadbutton, btn_h, "");
}
- uiEndBlock(C, block);
- uiDrawBlock(C, block);
+ UI_block_end(C, block);
+ UI_block_draw(C, block);
}
static void draw_tile(int sx, int sy, int width, int height, int colorid, int shade)
{
UI_ThemeColorShade(colorid, shade);
- uiSetRoundBox(UI_CNR_ALL);
- uiRoundBox((float)sx, (float)(sy - height), (float)(sx + width), (float)sy, 5.0f);
+ UI_draw_roundbox_corner_set(UI_CNR_ALL);
+ UI_draw_roundbox((float)sx, (float)(sy - height), (float)(sx + width), (float)sy, 5.0f);
}
-static int get_file_icon(struct direntry *file)
-{
- if (file->type & S_IFDIR) {
- if (strcmp(file->relname, "..") == 0) {
- return ICON_FILE_PARENT;
- }
- if (file->flags & APPLICATIONBUNDLE) {
- return ICON_UGLYPACKAGE;
- }
- if (file->flags & BLENDERFILE) {
- return ICON_FILE_BLEND;
- }
- return ICON_FILE_FOLDER;
- }
- else if (file->flags & BLENDERFILE)
- return ICON_FILE_BLEND;
- else if (file->flags & BLENDERFILE_BACKUP)
- return ICON_FILE_BACKUP;
- else if (file->flags & IMAGEFILE)
- return ICON_FILE_IMAGE;
- else if (file->flags & MOVIEFILE)
- return ICON_FILE_MOVIE;
- else if (file->flags & PYSCRIPTFILE)
- return ICON_FILE_SCRIPT;
- else if (file->flags & SOUNDFILE)
- return ICON_FILE_SOUND;
- else if (file->flags & FTFONTFILE)
- return ICON_FILE_FONT;
- else if (file->flags & BTXFILE)
- return ICON_FILE_BLANK;
- else if (file->flags & COLLADAFILE)
- return ICON_FILE_BLANK;
- else if (file->flags & TEXTFILE)
- return ICON_FILE_TEXT;
- else
- return ICON_FILE_BLANK;
-}
-
-static void file_draw_icon(uiBlock *block, char *path, int sx, int sy, int icon, int width, int height, bool drag)
+static void file_draw_icon(uiBlock *block, const char *path, int sx, int sy, int icon, int width, int height, bool drag)
{
uiBut *but;
int x, y;
@@ -281,32 +274,42 @@ static void file_draw_icon(uiBlock *block, char *path, int sx, int sy, int icon,
/*if (icon == ICON_FILE_BLANK) alpha = 0.375f;*/
- but = uiDefIconBut(block, LABEL, 0, icon, x, y, width, height, NULL, 0.0f, 0.0f, 0.0f, 0.0f, "");
+ but = uiDefIconBut(block, UI_BTYPE_LABEL, 0, icon, x, y, width, height, NULL, 0.0f, 0.0f, 0.0f, 0.0f, NULL);
+ UI_but_func_tooltip_set(but, file_draw_tooltip_func, BLI_strdup(path));
- if (drag)
- uiButSetDragPath(but, path);
+ if (drag) {
+ /* path is no more static, cannot give it directly to but... */
+ UI_but_drag_set_path(but, BLI_strdup(path), true);
+ }
}
static void file_draw_string(int sx, int sy, const char *string, float width, int height, short align)
{
- uiStyle *style = UI_GetStyle();
- uiFontStyle fs = style->widgetlabel;
+ uiStyle *style;
+ uiFontStyle fs;
rcti rect;
char fname[FILE_MAXFILE];
+ if (string[0] == '\0') {
+ return;
+ }
+
+ style = UI_style_get();
+ fs = style->widgetlabel;
+
fs.align = align;
BLI_strncpy(fname, string, FILE_MAXFILE);
- file_shorten_string(fname, width + 1.0f, 0);
+ UI_text_clip_middle_ex(&fs, fname, width, UI_DPI_ICON_SIZE, sizeof(fname), '\0');
- /* no text clipping needed, uiStyleFontDraw does it but is a bit too strict (for buttons it works) */
+ /* no text clipping needed, UI_fontstyle_draw does it but is a bit too strict (for buttons it works) */
rect.xmin = sx;
- rect.xmax = (int)(sx + ceil(width + 4.0f));
+ rect.xmax = (int)(sx + ceil(width + 5.0f / UI_DPI_FAC));
rect.ymin = sy - height;
rect.ymax = sy;
-
- uiStyleFontDraw(&fs, &rect, fname);
+
+ UI_fontstyle_draw(&fs, &rect, fname);
}
void file_calc_previews(const bContext *C, ARegion *ar)
@@ -318,72 +321,92 @@ void file_calc_previews(const bContext *C, ARegion *ar)
UI_view2d_totRect_set(v2d, sfile->layout->width, sfile->layout->height);
}
-static void file_draw_preview(uiBlock *block, struct direntry *file, int sx, int sy, ImBuf *imb, FileLayout *layout, bool dropshadow, bool drag)
+static void file_draw_preview(
+ uiBlock *block, const char *path, int sx, int sy, const float icon_aspect,
+ ImBuf *imb, const int icon, FileLayout *layout, const bool is_icon, const int typeflags, const bool drag)
{
- if (imb) {
- uiBut *but;
- float fx, fy;
- float dx, dy;
- int xco, yco;
- float scaledx, scaledy;
- float scale;
- int ex, ey;
-
- if ((imb->x * UI_DPI_FAC > layout->prv_w) ||
- (imb->y * UI_DPI_FAC > layout->prv_h))
- {
- if (imb->x > imb->y) {
- scaledx = (float)layout->prv_w;
- scaledy = ( (float)imb->y / (float)imb->x) * layout->prv_w;
- scale = scaledx / imb->x;
- }
- else {
- scaledy = (float)layout->prv_h;
- scaledx = ( (float)imb->x / (float)imb->y) * layout->prv_h;
- scale = scaledy / imb->y;
- }
+ uiBut *but;
+ float fx, fy;
+ float dx, dy;
+ int xco, yco;
+ float ui_imbx, ui_imby;
+ float scaledx, scaledy;
+ float scale;
+ int ex, ey;
+ bool use_dropshadow = !is_icon && (typeflags & FILE_TYPE_IMAGE);
+
+ BLI_assert(imb != NULL);
+
+ ui_imbx = imb->x * UI_DPI_FAC;
+ ui_imby = imb->y * UI_DPI_FAC;
+ /* Unlike thumbnails, icons are not scaled up. */
+ if (((ui_imbx > layout->prv_w) || (ui_imby > layout->prv_h)) ||
+ (!is_icon && ((ui_imbx < layout->prv_w) || (ui_imby < layout->prv_h))))
+ {
+ if (imb->x > imb->y) {
+ scaledx = (float)layout->prv_w;
+ scaledy = ((float)imb->y / (float)imb->x) * layout->prv_w;
+ scale = scaledx / imb->x;
}
else {
- scaledx = (float)imb->x * UI_DPI_FAC;
- scaledy = (float)imb->y * UI_DPI_FAC;
- scale = UI_DPI_FAC;
+ scaledy = (float)layout->prv_h;
+ scaledx = ((float)imb->x / (float)imb->y) * layout->prv_h;
+ scale = scaledy / imb->y;
}
+ }
+ else {
+ scaledx = ui_imbx;
+ scaledy = ui_imby;
+ scale = UI_DPI_FAC;
+ }
- ex = (int)scaledx;
- ey = (int)scaledy;
- fx = ((float)layout->prv_w - (float)ex) / 2.0f;
- fy = ((float)layout->prv_h - (float)ey) / 2.0f;
- dx = (fx + 0.5f + layout->prv_border_x);
- dy = (fy + 0.5f - layout->prv_border_y);
- xco = sx + (int)dx;
- yco = sy - layout->prv_h + (int)dy;
-
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-
- /* shadow */
- if (dropshadow)
- uiDrawBoxShadow(220, (float)xco, (float)yco, (float)(xco + ex), (float)(yco + ey));
+ ex = (int)scaledx;
+ ey = (int)scaledy;
+ fx = ((float)layout->prv_w - (float)ex) / 2.0f;
+ fy = ((float)layout->prv_h - (float)ey) / 2.0f;
+ dx = (fx + 0.5f + layout->prv_border_x);
+ dy = (fy + 0.5f - layout->prv_border_y);
+ xco = sx + (int)dx;
+ yco = sy - layout->prv_h + (int)dy;
- glEnable(GL_BLEND);
-
- /* the image */
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+ /* shadow */
+ if (use_dropshadow) {
+ UI_draw_box_shadow(220, (float)xco, (float)yco, (float)(xco + ex), (float)(yco + ey));
+ }
+
+ glEnable(GL_BLEND);
+
+ /* the image */
+ if (!is_icon && typeflags & FILE_TYPE_FTFONT) {
+ UI_ThemeColor(TH_TEXT);
+ }
+ else {
glColor4f(1.0, 1.0, 1.0, 1.0);
- glaDrawPixelsTexScaled((float)xco, (float)yco, imb->x, imb->y, GL_RGBA, GL_UNSIGNED_BYTE, GL_NEAREST, imb->rect, scale, scale);
-
- /* border */
- if (dropshadow) {
- glColor4f(0.0f, 0.0f, 0.0f, 0.4f);
- fdrawbox((float)xco, (float)yco, (float)(xco + ex), (float)(yco + ey));
- }
-
- /* dragregion */
- if (drag) {
- but = uiDefBut(block, LABEL, 0, "", xco, yco, ex, ey, NULL, 0.0, 0.0, 0, 0, "");
- uiButSetDragImage(but, file->path, get_file_icon(file), imb, scale);
- }
-
- glDisable(GL_BLEND);
}
+ glaDrawPixelsTexScaled((float)xco, (float)yco, imb->x, imb->y, GL_RGBA, GL_UNSIGNED_BYTE, GL_NEAREST, imb->rect, scale, scale);
+
+ if (icon) {
+ UI_icon_draw_aspect((float)xco, (float)yco, icon, icon_aspect, 1.0f);
+ }
+
+ /* border */
+ if (use_dropshadow) {
+ glColor4f(0.0f, 0.0f, 0.0f, 0.4f);
+ fdrawbox((float)xco, (float)yco, (float)(xco + ex), (float)(yco + ey));
+ }
+
+ but = uiDefBut(block, UI_BTYPE_LABEL, 0, "", xco, yco, ex, ey, NULL, 0.0, 0.0, 0, 0, NULL);
+ UI_but_func_tooltip_set(but, file_draw_tooltip_func, BLI_strdup(path));
+
+ /* dragregion */
+ if (drag) {
+ /* path is no more static, cannot give it directly to but... */
+ UI_but_drag_set_image(but, BLI_strdup(path), icon, imb, scale, true);
+ }
+
+ glDisable(GL_BLEND);
}
static void renamebutton_cb(bContext *C, void *UNUSED(arg1), char *oldname)
@@ -393,17 +416,19 @@ static void renamebutton_cb(bContext *C, void *UNUSED(arg1), char *oldname)
char filename[FILE_MAX + 12];
wmWindowManager *wm = CTX_wm_manager(C);
SpaceFile *sfile = (SpaceFile *)CTX_wm_space_data(C);
+ ScrArea *sa = CTX_wm_area(C);
ARegion *ar = CTX_wm_region(C);
BLI_make_file_string(G.main->name, orgname, sfile->params->dir, oldname);
BLI_strncpy(filename, sfile->params->renameedit, sizeof(filename));
+ BLI_filename_make_safe(filename);
BLI_make_file_string(G.main->name, newname, sfile->params->dir, filename);
- if (strcmp(orgname, newname) != 0) {
+ if (!STREQ(orgname, newname)) {
if (!BLI_exists(newname)) {
BLI_rename(orgname, newname);
/* to make sure we show what is on disk */
- ED_fileselect_clear(wm, sfile);
+ ED_fileselect_clear(wm, sa, sfile);
}
ED_region_tag_redraw(ar);
@@ -468,9 +493,10 @@ void file_draw_list(const bContext *C, ARegion *ar)
FileLayout *layout = ED_fileselect_get_layout(sfile, ar);
View2D *v2d = &ar->v2d;
struct FileList *files = sfile->files;
- struct direntry *file;
+ struct FileDirEntry *file;
+ const char *root = filelist_dir(files);
ImBuf *imb;
- uiBlock *block = uiBeginBlock(C, ar, __func__, UI_EMBOSS);
+ uiBlock *block = UI_block_begin(C, ar, __func__, UI_EMBOSS);
int numfiles;
int numfiles_layout;
int sx, sy;
@@ -481,8 +507,11 @@ void file_draw_list(const bContext *C, ARegion *ar)
short align;
bool do_drag;
int column_space = 0.6f * UI_UNIT_X;
+ const bool small_size = SMALL_SIZE_CHECK(params->thumbnail_size);
+ const bool update_stat_strings = small_size != SMALL_SIZE_CHECK(layout->curr_size);
+ const float thumb_icon_aspect = sqrtf(64.0f / (float)(params->thumbnail_size));
- numfiles = filelist_numfiles(files);
+ numfiles = filelist_files_ensure(files);
if (params->display != FILE_IMGDISPLAY) {
@@ -504,105 +533,168 @@ void file_draw_list(const bContext *C, ARegion *ar)
numfiles_layout += layout->columns;
}
+ filelist_file_cache_slidingwindow_set(files, numfiles_layout);
+
textwidth = (FILE_IMGDISPLAY == params->display) ? layout->tile_w : (int)layout->column_widths[COLUMN_NAME];
textheight = (int)(layout->textheight * 3.0 / 2.0 + 0.5);
align = (FILE_IMGDISPLAY == params->display) ? UI_STYLE_TEXT_CENTER : UI_STYLE_TEXT_LEFT;
+ if (numfiles > 0) {
+ const bool success = filelist_file_cache_block(files, min_ii(offset + (numfiles_layout / 2), numfiles - 1));
+ BLI_assert(success);
+ UNUSED_VARS_NDEBUG(success);
+
+ filelist_cache_previews_update(files);
+
+ /* Handle preview timer here, since it's filelist_file_cache_block() and filelist_cache_previews_update()
+ * which controlls previews task. */
+ {
+ const bool previews_running = filelist_cache_previews_running(files);
+// printf("%s: preview task: %d\n", __func__, previews_running);
+ if (previews_running && !sfile->previews_timer) {
+ sfile->previews_timer = WM_event_add_timer_notifier(CTX_wm_manager(C), CTX_wm_window(C),
+ NC_SPACE | ND_SPACE_FILE_PREVIEW, 0.01);
+ }
+ if (!previews_running && sfile->previews_timer) {
+ /* Preview is not running, no need to keep generating update events! */
+// printf("%s: Inactive preview task, sleeping!\n", __func__);
+ WM_event_remove_timer_notifier(CTX_wm_manager(C), CTX_wm_window(C), sfile->previews_timer);
+ sfile->previews_timer = NULL;
+ }
+ }
+ }
+
for (i = offset; (i < numfiles) && (i < offset + numfiles_layout); i++) {
+ unsigned int file_selflag;
+ char path[FILE_MAX_LIBEXTRA];
ED_fileselect_layout_tilepos(layout, i, &sx, &sy);
sx += (int)(v2d->tot.xmin + 0.1f * UI_UNIT_X);
sy = (int)(v2d->tot.ymax - sy);
file = filelist_file(files, i);
-
+ file_selflag = filelist_entry_select_get(sfile->files, file, CHECK_ALL);
+
+ BLI_join_dirfile(path, sizeof(path), root, file->relpath);
+
UI_ThemeColor4(TH_TEXT);
- if (!(file->selflag & EDITING_FILE)) {
- if ((params->active_file == i) || (file->selflag & HILITED_FILE) || (file->selflag & SELECTED_FILE)) {
- int colorid = (file->selflag & SELECTED_FILE) ? TH_HILITE : TH_BACK;
- int shade = (params->active_file == i) || (file->selflag & HILITED_FILE) ? 20 : 0;
+ if (!(file_selflag & FILE_SEL_EDITING)) {
+ if ((params->highlight_file == i) || (file_selflag & FILE_SEL_HIGHLIGHTED) ||
+ (file_selflag & FILE_SEL_SELECTED))
+ {
+ int colorid = (file_selflag & FILE_SEL_SELECTED) ? TH_HILITE : TH_BACK;
+ int shade = (params->highlight_file == i) || (file_selflag & FILE_SEL_HIGHLIGHTED) ? 35 : 0;
+
+ BLI_assert(i > 0 || FILENAME_IS_CURRPAR(file->relpath));
+
draw_tile(sx, sy - 1, layout->tile_w + 4, sfile->layout->tile_h + layout->tile_border_y, colorid, shade);
}
}
- uiSetRoundBox(UI_CNR_NONE);
+ UI_draw_roundbox_corner_set(UI_CNR_NONE);
/* don't drag parent or refresh items */
- do_drag = !(STREQ(file->relname, "..") || STREQ(file->relname, "."));
+ do_drag = !(FILENAME_IS_CURRPAR(file->relpath));
if (FILE_IMGDISPLAY == params->display) {
+ const int icon = filelist_geticon(files, i, false);
is_icon = 0;
imb = filelist_getimage(files, i);
if (!imb) {
- imb = filelist_geticon(files, i);
+ imb = filelist_geticon_image(files, i);
is_icon = 1;
}
-
- file_draw_preview(block, file, sx, sy, imb, layout, !is_icon && (file->flags & IMAGEFILE), do_drag);
+
+ file_draw_preview(block, path, sx, sy, thumb_icon_aspect,
+ imb, icon, layout, is_icon, file->typeflag, do_drag);
}
else {
- file_draw_icon(block, file->path, sx, sy - (UI_UNIT_Y / 6), get_file_icon(file), ICON_DEFAULT_WIDTH_SCALE, ICON_DEFAULT_HEIGHT_SCALE, do_drag);
+ file_draw_icon(block, path, sx, sy - (UI_UNIT_Y / 6), filelist_geticon(files, i, true),
+ ICON_DEFAULT_WIDTH_SCALE, ICON_DEFAULT_HEIGHT_SCALE, do_drag);
sx += ICON_DEFAULT_WIDTH_SCALE + 0.2f * UI_UNIT_X;
}
UI_ThemeColor4(TH_TEXT);
- if (file->selflag & EDITING_FILE) {
- uiBut *but = uiDefBut(block, TEX, 1, "", sx, sy - layout->tile_h - 0.15f * UI_UNIT_X,
- textwidth, textheight, sfile->params->renameedit, 1.0f, (float)sizeof(sfile->params->renameedit), 0, 0, "");
- uiButSetRenameFunc(but, renamebutton_cb, file);
- uiButSetFlag(but, UI_BUT_NO_UTF8); /* allow non utf8 names */
- uiButClearFlag(but, UI_BUT_UNDO);
- if (false == uiButActiveOnly(C, ar, block, but)) {
- file->selflag &= ~EDITING_FILE;
+ if (file_selflag & FILE_SEL_EDITING) {
+ uiBut *but;
+ short width;
+
+ if (params->display == FILE_SHORTDISPLAY) {
+ width = layout->tile_w - (ICON_DEFAULT_WIDTH_SCALE + 0.2f * UI_UNIT_X);
+ }
+ else if (params->display == FILE_LONGDISPLAY) {
+ width = layout->column_widths[COLUMN_NAME] + (column_space * 3.5f);
+ }
+ else {
+ BLI_assert(params->display == FILE_IMGDISPLAY);
+ width = textwidth;
+ }
+
+ but = uiDefBut(block, UI_BTYPE_TEXT, 1, "", sx, sy - layout->tile_h - 0.15f * UI_UNIT_X,
+ width, textheight, sfile->params->renameedit, 1.0f,
+ (float)sizeof(sfile->params->renameedit), 0, 0, "");
+ UI_but_func_rename_set(but, renamebutton_cb, file);
+ UI_but_flag_enable(but, UI_BUT_NO_UTF8); /* allow non utf8 names */
+ UI_but_flag_disable(but, UI_BUT_UNDO);
+ if (false == UI_but_active_only(C, ar, block, but)) {
+ file_selflag = filelist_entry_select_set(
+ sfile->files, file, FILE_SEL_REMOVE, FILE_SEL_EDITING, CHECK_ALL);
}
}
- if (!(file->selflag & EDITING_FILE)) {
+ if (!(file_selflag& FILE_SEL_EDITING)) {
int tpos = (FILE_IMGDISPLAY == params->display) ? sy - layout->tile_h + layout->textheight : sy;
- file_draw_string(sx + 1, tpos, file->relname, (float)textwidth, textheight, align);
+ file_draw_string(sx + 1, tpos, file->name, (float)textwidth, textheight, align);
}
+ sx += (int)layout->column_widths[COLUMN_NAME] + column_space;
if (params->display == FILE_SHORTDISPLAY) {
- sx += (int)layout->column_widths[COLUMN_NAME] + column_space;
- if (!(file->type & S_IFDIR)) {
- file_draw_string(sx, sy, file->size, layout->column_widths[COLUMN_SIZE], layout->tile_h, align);
- sx += (int)layout->column_widths[COLUMN_SIZE] + column_space;
+ if ((file->typeflag & (FILE_TYPE_BLENDER | FILE_TYPE_BLENDER_BACKUP)) ||
+ !(file->typeflag & (FILE_TYPE_DIR | FILE_TYPE_BLENDERLIB)))
+ {
+ if ((file->entry->size_str[0] == '\0') || update_stat_strings) {
+ BLI_filelist_entry_size_to_string(NULL, file->entry->size, small_size, file->entry->size_str);
+ }
+ file_draw_string(
+ sx, sy, file->entry->size_str, layout->column_widths[COLUMN_SIZE], layout->tile_h, align);
}
+ sx += (int)layout->column_widths[COLUMN_SIZE] + column_space;
}
else if (params->display == FILE_LONGDISPLAY) {
- sx += (int)layout->column_widths[COLUMN_NAME] + column_space;
-
-#ifndef WIN32
- /* rwx rwx rwx */
- file_draw_string(sx, sy, file->mode1, layout->column_widths[COLUMN_MODE1], layout->tile_h, align);
- sx += layout->column_widths[COLUMN_MODE1] + column_space;
-
- file_draw_string(sx, sy, file->mode2, layout->column_widths[COLUMN_MODE2], layout->tile_h, align);
- sx += layout->column_widths[COLUMN_MODE2] + column_space;
-
- file_draw_string(sx, sy, file->mode3, layout->column_widths[COLUMN_MODE3], layout->tile_h, align);
- sx += layout->column_widths[COLUMN_MODE3] + column_space;
-
- file_draw_string(sx, sy, file->owner, layout->column_widths[COLUMN_OWNER], layout->tile_h, align);
- sx += layout->column_widths[COLUMN_OWNER] + column_space;
-#endif
-
- file_draw_string(sx, sy, file->date, layout->column_widths[COLUMN_DATE], layout->tile_h, align);
- sx += (int)layout->column_widths[COLUMN_DATE] + column_space;
-
- file_draw_string(sx, sy, file->time, layout->column_widths[COLUMN_TIME], layout->tile_h, align);
- sx += (int)layout->column_widths[COLUMN_TIME] + column_space;
+ if (!(file->typeflag & FILE_TYPE_BLENDERLIB) && !FILENAME_IS_CURRPAR(file->relpath)) {
+ if ((file->entry->date_str[0] == '\0') || update_stat_strings) {
+ BLI_filelist_entry_datetime_to_string(
+ NULL, file->entry->time, small_size, file->entry->time_str, file->entry->date_str);
+ }
+ file_draw_string(
+ sx, sy, file->entry->date_str, layout->column_widths[COLUMN_DATE], layout->tile_h, align);
+ sx += (int)layout->column_widths[COLUMN_DATE] + column_space;
+ file_draw_string(
+ sx, sy, file->entry->time_str, layout->column_widths[COLUMN_TIME], layout->tile_h, align);
+ sx += (int)layout->column_widths[COLUMN_TIME] + column_space;
+ }
+ else {
+ sx += (int)layout->column_widths[COLUMN_DATE] + column_space;
+ sx += (int)layout->column_widths[COLUMN_TIME] + column_space;
+ }
- if (!(file->type & S_IFDIR)) {
- file_draw_string(sx, sy, file->size, layout->column_widths[COLUMN_SIZE], layout->tile_h, align);
- sx += (int)layout->column_widths[COLUMN_SIZE] + column_space;
+ if ((file->typeflag & (FILE_TYPE_BLENDER | FILE_TYPE_BLENDER_BACKUP)) ||
+ !(file->typeflag & (FILE_TYPE_DIR | FILE_TYPE_BLENDERLIB)))
+ {
+ if ((file->entry->size_str[0] == '\0') || update_stat_strings) {
+ BLI_filelist_entry_size_to_string(NULL, file->entry->size, small_size, file->entry->size_str);
+ }
+ file_draw_string(
+ sx, sy, file->entry->size_str, layout->column_widths[COLUMN_SIZE], layout->tile_h, align);
}
+ sx += (int)layout->column_widths[COLUMN_SIZE] + column_space;
}
}
- uiEndBlock(C, block);
- uiDrawBlock(C, block);
+ UI_block_end(C, block);
+ UI_block_draw(C, block);
+ layout->curr_size = params->thumbnail_size;
}
diff --git a/source/blender/editors/space_file/file_intern.h b/source/blender/editors/space_file/file_intern.h
index 7147353b3f1..baafefab1f6 100644
--- a/source/blender/editors/space_file/file_intern.h
+++ b/source/blender/editors/space_file/file_intern.h
@@ -38,7 +38,7 @@ struct ARegionType;
struct SpaceFile;
/* file_ops.c */
-struct ARegion *file_buttons_region(struct ScrArea *sa);
+struct ARegion *file_tools_region(struct ScrArea *sa);
/* file_draw.c */
#define TILE_BORDER_X (UI_UNIT_X / 4)
@@ -48,24 +48,37 @@ struct ARegion *file_buttons_region(struct ScrArea *sa);
#define IMASEL_BUTTONS_HEIGHT (UI_UNIT_Y * 2)
#define IMASEL_BUTTONS_MARGIN (UI_UNIT_Y / 6)
+#define SMALL_SIZE_CHECK(_size) ((_size) < 64) /* Related to FileSelectParams.thumbnail_size. */
+
void file_draw_buttons(const bContext *C, ARegion *ar);
void file_calc_previews(const bContext *C, ARegion *ar);
void file_draw_list(const bContext *C, ARegion *ar);
+void file_draw_check(bContext *C);
void file_draw_check_cb(bContext *C, void *arg1, void *arg2);
bool file_draw_check_exists(SpaceFile *sfile);
/* file_ops.h */
struct wmOperatorType;
struct wmOperator;
-struct wmEvent;
+
+typedef enum WalkSelectDirection {
+ FILE_SELECT_WALK_UP,
+ FILE_SELECT_WALK_DOWN,
+ FILE_SELECT_WALK_LEFT,
+ FILE_SELECT_WALK_RIGHT,
+} WalkSelectDirections;
+
void FILE_OT_highlight(struct wmOperatorType *ot);
void FILE_OT_select(struct wmOperatorType *ot);
+void FILE_OT_select_walk(struct wmOperatorType *ot);
void FILE_OT_select_all_toggle(struct wmOperatorType *ot);
void FILE_OT_select_border(struct wmOperatorType *ot);
void FILE_OT_select_bookmark(struct wmOperatorType *ot);
void FILE_OT_bookmark_add(struct wmOperatorType *ot);
void FILE_OT_bookmark_delete(struct wmOperatorType *ot);
+void FILE_OT_bookmark_cleanup(struct wmOperatorType *ot);
+void FILE_OT_bookmark_move(struct wmOperatorType *ot);
void FILE_OT_reset_recent(wmOperatorType *ot);
void FILE_OT_hidedot(struct wmOperatorType *ot);
void FILE_OT_execute(struct wmOperatorType *ot);
@@ -99,11 +112,10 @@ void file_operator_to_sfile(struct SpaceFile *sfile, struct wmOperator *op);
/* filesel.c */
-float file_shorten_string(char *string, float w, int front);
+void fileselect_file_set(SpaceFile *sfile, const int index);
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);
int autocomplete_directory(struct bContext *C, char *str, void *arg_v);
int autocomplete_file(struct bContext *C, char *str, void *arg_v);
@@ -111,5 +123,8 @@ int autocomplete_file(struct bContext *C, char *str, void *arg_v);
/* file_panels.c */
void file_panels_register(struct ARegionType *art);
+/* file_utils.c */
+void file_tile_boundbox(const ARegion *ar, FileLayout *layout, const int file, rcti *r_bounds);
+
#endif /* __FILE_INTERN_H__ */
diff --git a/source/blender/editors/space_file/file_ops.c b/source/blender/editors/space_file/file_ops.c
index 27d6fabba4e..8347ad87258 100644
--- a/source/blender/editors/space_file/file_ops.c
+++ b/source/blender/editors/space_file/file_ops.c
@@ -31,9 +31,11 @@
#include "BLI_blenlib.h"
#include "BLI_utildefines.h"
#include "BLI_fileops_types.h"
+#include "BLI_linklist.h"
#include "BLO_readfile.h"
+#include "BKE_appdir.h"
#include "BKE_context.h"
#include "BKE_screen.h"
#include "BKE_global.h"
@@ -97,9 +99,9 @@ static void file_deselect_all(SpaceFile *sfile, unsigned int flag)
{
FileSelection sel;
sel.first = 0;
- sel.last = filelist_numfiles(sfile->files) - 1;
+ sel.last = filelist_files_ensure(sfile->files) - 1;
- filelist_select(sfile->files, &sel, FILE_SEL_REMOVE, flag, CHECK_ALL);
+ filelist_entries_select_index_range_set(sfile->files, &sel, FILE_SEL_REMOVE, flag, CHECK_ALL);
}
typedef enum FileSelect {
@@ -137,7 +139,7 @@ static FileSelection file_selection_get(bContext *C, const rcti *rect, bool fill
{
ARegion *ar = CTX_wm_region(C);
SpaceFile *sfile = CTX_wm_space_file(C);
- int numfiles = filelist_numfiles(sfile->files);
+ int numfiles = filelist_files_ensure(sfile->files);
FileSelection sel;
sel = find_file_mouse_rect(sfile, ar, rect);
@@ -150,7 +152,7 @@ static FileSelection file_selection_get(bContext *C, const rcti *rect, bool fill
if (fill && (sel.last >= 0) && (sel.last < numfiles) ) {
int f = sel.last;
while (f >= 0) {
- if (filelist_is_selected(sfile->files, f, CHECK_ALL) )
+ if (filelist_entry_select_index_get(sfile->files, f, CHECK_ALL) )
break;
f--;
}
@@ -166,50 +168,118 @@ static FileSelect file_select_do(bContext *C, int selected_idx, bool do_diropen)
FileSelect retval = FILE_SELECT_NOTHING;
SpaceFile *sfile = CTX_wm_space_file(C);
FileSelectParams *params = ED_fileselect_get_params(sfile);
- int numfiles = filelist_numfiles(sfile->files);
- struct direntry *file;
+ int numfiles = filelist_files_ensure(sfile->files);
+ const FileDirEntry *file;
/* make the selected file active */
if ((selected_idx >= 0) &&
(selected_idx < numfiles) &&
(file = filelist_file(sfile->files, selected_idx)))
{
+ params->highlight_file = selected_idx;
params->active_file = selected_idx;
- if (S_ISDIR(file->type)) {
+ if (file->typeflag & FILE_TYPE_DIR) {
+ const bool is_parent_dir = FILENAME_IS_PARENT(file->relpath);
+
if (do_diropen == false) {
params->file[0] = '\0';
retval = FILE_SELECT_DIR;
}
/* the path is too long and we are not going up! */
- else if (strcmp(file->relname, "..") && strlen(params->dir) + strlen(file->relname) >= FILE_MAX) {
+ else if (!is_parent_dir && strlen(params->dir) + strlen(file->relpath) >= FILE_MAX) {
// XXX error("Path too long, cannot enter this directory");
}
else {
- if (strcmp(file->relname, "..") == 0) {
+ if (is_parent_dir) {
/* avoids /../../ */
BLI_parent_dir(params->dir);
+
+ if (params->recursion_level > 1) {
+ /* Disable 'dirtree' recursion when going up in tree. */
+ params->recursion_level = 0;
+ filelist_setrecursion(sfile->files, params->recursion_level);
+ }
}
else {
BLI_cleanup_dir(G.main->name, params->dir);
- strcat(params->dir, file->relname);
+ strcat(params->dir, file->relpath);
BLI_add_slash(params->dir);
}
- file_change_dir(C, 0);
+ ED_file_change_dir(C, false);
retval = FILE_SELECT_DIR;
}
}
else {
- if (file->relname) {
- BLI_strncpy(params->file, file->relname, FILE_MAXFILE);
- }
retval = FILE_SELECT_FILE;
}
+ fileselect_file_set(sfile, selected_idx);
}
return retval;
}
+/**
+ * \warning: loops over all files so better use cautiously
+ */
+static bool file_is_any_selected(struct FileList *files)
+{
+ const int numfiles = filelist_files_ensure(files);
+ int i;
+
+ /* Is any file selected ? */
+ for (i = 0; i < numfiles; ++i) {
+ if (filelist_entry_select_index_get(files, i, CHECK_ALL)) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+/**
+ * If \a file is outside viewbounds, this adjusts view to make sure it's inside
+ */
+static void file_ensure_inside_viewbounds(ARegion *ar, SpaceFile *sfile, const int file)
+{
+ FileLayout *layout = ED_fileselect_get_layout(sfile, ar);
+ rctf *cur = &ar->v2d.cur;
+ rcti rect;
+ bool changed = true;
+
+ file_tile_boundbox(ar, layout, file, &rect);
+
+ /* down - also use if tile is higher than viewbounds so view is aligned to file name */
+ if (cur->ymin > rect.ymin || layout->tile_h > ar->winy) {
+ cur->ymin = rect.ymin - (2 * layout->tile_border_y);
+ cur->ymax = cur->ymin + ar->winy;
+ }
+ /* up */
+ else if (cur->ymax < rect.ymax) {
+ cur->ymax = rect.ymax + layout->tile_border_y;
+ cur->ymin = cur->ymax - ar->winy;
+ }
+ /* left - also use if tile is wider than viewbounds so view is aligned to file name */
+ else if (cur->xmin > rect.xmin || layout->tile_w > ar->winx) {
+ cur->xmin = rect.xmin - layout->tile_border_x;
+ cur->xmax = cur->xmin + ar->winx;
+ }
+ /* right */
+ else if (cur->xmax < rect.xmax) {
+ cur->xmax = rect.xmax + (2 * layout->tile_border_x);
+ cur->xmin = cur->xmax - ar->winx;
+ }
+ else {
+ BLI_assert(cur->xmin <= rect.xmin && cur->xmax >= rect.xmax &&
+ cur->ymin <= rect.ymin && cur->ymax >= rect.ymax);
+ changed = false;
+ }
+
+ if (changed) {
+ UI_view2d_curRect_validate(&ar->v2d);
+ }
+}
+
static FileSelect file_select(bContext *C, const rcti *rect, FileSelType select, bool fill, bool do_diropen)
{
@@ -219,25 +289,76 @@ static FileSelect file_select(bContext *C, const rcti *rect, FileSelType select,
const FileCheckType check_type = (sfile->params->flag & FILE_DIRSEL_ONLY) ? CHECK_DIRS : CHECK_ALL;
/* flag the files as selected in the filelist */
- filelist_select(sfile->files, &sel, select, SELECTED_FILE, check_type);
+ filelist_entries_select_index_range_set(sfile->files, &sel, select, FILE_SEL_SELECTED, check_type);
/* Don't act on multiple selected files */
if (sel.first != sel.last) select = 0;
/* Do we have a valid selection and are we actually selecting */
- if ((sel.last >= 0) && ((select == FILE_SEL_ADD) || (select == FILE_SEL_TOGGLE))) {
+ if ((sel.last >= 0) && (select != FILE_SEL_REMOVE)) {
/* Check last selection, if selected, act on the file or dir */
- if (filelist_is_selected(sfile->files, sel.last, check_type)) {
+ if (filelist_entry_select_index_get(sfile->files, sel.last, check_type)) {
retval = file_select_do(C, sel.last, do_diropen);
}
}
+ if (select != FILE_SEL_ADD && !file_is_any_selected(sfile->files)) {
+ sfile->params->active_file = -1;
+ }
+ else {
+ ARegion *ar = CTX_wm_region(C);
+ const FileLayout *layout = ED_fileselect_get_layout(sfile, ar);
+
+ /* Adjust view to display selection. Doing iterations for first and last
+ * selected item makes view showing as much of the selection possible.
+ * Not really useful if tiles are (almost) bigger than viewbounds though. */
+ if (((layout->flag & FILE_LAYOUT_HOR) && ar->winx > (1.2f * layout->tile_w)) ||
+ ((layout->flag & FILE_LAYOUT_VER) && ar->winy > (2.0f * layout->tile_h)))
+ {
+ file_ensure_inside_viewbounds(ar, sfile, sel.last);
+ file_ensure_inside_viewbounds(ar, sfile, sel.first);
+ }
+ }
+
/* update operator for name change event */
- file_draw_check_cb(C, NULL, NULL);
+ file_draw_check(C);
return retval;
}
+static int file_border_select_find_last_selected(
+ SpaceFile *sfile, ARegion *ar, const FileSelection *sel,
+ const int mouse_xy[2])
+{
+ FileLayout *layout = ED_fileselect_get_layout(sfile, ar);
+ rcti bounds_first, bounds_last;
+ int dist_first, dist_last;
+ float mouseco_view[2];
+
+ UI_view2d_region_to_view(&ar->v2d, UNPACK2(mouse_xy), &mouseco_view[0], &mouseco_view[1]);
+
+ file_tile_boundbox(ar, layout, sel->first, &bounds_first);
+ file_tile_boundbox(ar, layout, sel->last, &bounds_last);
+
+ /* are first and last in the same column (horizontal layout)/row (vertical layout)? */
+ if ((layout->flag & FILE_LAYOUT_HOR && bounds_first.xmin == bounds_last.xmin) ||
+ (layout->flag & FILE_LAYOUT_VER && bounds_first.ymin != bounds_last.ymin))
+ {
+ /* use vertical distance */
+ const int my_loc = (int)mouseco_view[1];
+ dist_first = BLI_rcti_length_y(&bounds_first, my_loc);
+ dist_last = BLI_rcti_length_y(&bounds_last, my_loc);
+ }
+ else {
+ /* use horizontal distance */
+ const int mx_loc = (int)mouseco_view[0];
+ dist_first = BLI_rcti_length_x(&bounds_first, mx_loc);
+ dist_last = BLI_rcti_length_x(&bounds_last, mx_loc);
+ }
+
+ return (dist_first < dist_last) ? sel->first : sel->last;
+}
+
static int file_border_select_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
ARegion *ar = CTX_wm_region(C);
@@ -251,24 +372,40 @@ static int file_border_select_modal(bContext *C, wmOperator *op, const wmEvent *
result = WM_border_select_modal(C, op, event);
if (result == OPERATOR_RUNNING_MODAL) {
-
WM_operator_properties_border_to_rcti(op, &rect);
BLI_rcti_isect(&(ar->v2d.mask), &rect, &rect);
sel = file_selection_get(C, &rect, 0);
- if ( (sel.first != params->sel_first) || (sel.last != params->sel_last) ) {
- file_deselect_all(sfile, HILITED_FILE);
- filelist_select(sfile->files, &sel, FILE_SEL_ADD, HILITED_FILE, CHECK_ALL);
+ if ((sel.first != params->sel_first) || (sel.last != params->sel_last)) {
+ int idx;
+
+ file_deselect_all(sfile, FILE_SEL_HIGHLIGHTED);
+ filelist_entries_select_index_range_set(sfile->files, &sel, FILE_SEL_ADD, FILE_SEL_HIGHLIGHTED, CHECK_ALL);
WM_event_add_notifier(C, NC_SPACE | ND_SPACE_FILE_PARAMS, NULL);
+
+ for (idx = sel.last; idx >= 0; idx--) {
+ const FileDirEntry *file = filelist_file(sfile->files, idx);
+
+ /* dont highlight readonly file (".." or ".") on border select */
+ if (FILENAME_IS_CURRPAR(file->relpath)) {
+ filelist_entry_select_set(sfile->files, file, FILE_SEL_REMOVE, FILE_SEL_HIGHLIGHTED, CHECK_ALL);
+ }
+
+ /* make sure highlight_file is no readonly file */
+ if (sel.last == idx) {
+ params->highlight_file = idx;
+ }
+ }
}
params->sel_first = sel.first; params->sel_last = sel.last;
-
+ params->active_file = file_border_select_find_last_selected(sfile, ar, &sel, event->mval);
}
else {
- params->active_file = -1;
+ params->highlight_file = -1;
params->sel_first = params->sel_last = -1;
- file_deselect_all(sfile, HILITED_FILE);
+ fileselect_file_set(sfile, params->active_file);
+ file_deselect_all(sfile, FILE_SEL_HIGHLIGHTED);
WM_event_add_notifier(C, NC_SPACE | ND_SPACE_FILE_PARAMS, NULL);
}
@@ -278,6 +415,7 @@ static int file_border_select_modal(bContext *C, wmOperator *op, const wmEvent *
static int file_border_select_exec(bContext *C, wmOperator *op)
{
ARegion *ar = CTX_wm_region(C);
+ SpaceFile *sfile = CTX_wm_space_file(C);
rcti rect;
FileSelect ret;
const bool select = (RNA_int_get(op->ptr, "gesture_mode") == GESTURE_MODAL_SELECT);
@@ -286,14 +424,16 @@ static int file_border_select_exec(bContext *C, wmOperator *op)
WM_operator_properties_border_to_rcti(op, &rect);
if (!extend) {
- SpaceFile *sfile = CTX_wm_space_file(C);
-
- file_deselect_all(sfile, SELECTED_FILE);
+ file_deselect_all(sfile, FILE_SEL_SELECTED);
}
BLI_rcti_isect(&(ar->v2d.mask), &rect, &rect);
ret = file_select(C, &rect, select ? FILE_SEL_ADD : FILE_SEL_REMOVE, false, false);
+
+ /* unselect '..' parent entry - it's not supposed to be selected if more than one file is selected */
+ filelist_entry_select_index_set(sfile->files, 0, FILE_SEL_REMOVE, FILE_SEL_SELECTED, CHECK_ALL);
+
if (FILE_SELECT_DIR == ret) {
WM_event_add_notifier(C, NC_SPACE | ND_SPACE_FILE_LIST, NULL);
}
@@ -340,10 +480,25 @@ static int file_select_invoke(bContext *C, wmOperator *op, const wmEvent *event)
if (!BLI_rcti_isect_pt(&ar->v2d.mask, rect.xmin, rect.ymin))
return OPERATOR_CANCELLED;
- /* single select, deselect all selected first */
- if (!extend) file_deselect_all(sfile, SELECTED_FILE);
+ if (sfile && sfile->params) {
+ int idx = sfile->params->highlight_file;
+ int numfiles = filelist_files_ensure(sfile->files);
+
+ if ((idx >= 0) && (idx < numfiles)) {
+ /* single select, deselect all selected first */
+ if (!extend) {
+ file_deselect_all(sfile, FILE_SEL_SELECTED);
+ }
+ }
+ }
ret = file_select(C, &rect, extend ? FILE_SEL_TOGGLE : FILE_SEL_ADD, fill, do_diropen);
+
+ if (extend) {
+ /* unselect '..' parent entry - it's not supposed to be selected if more than one file is selected */
+ filelist_entry_select_index_set(sfile->files, 0, FILE_SEL_REMOVE, FILE_SEL_SELECTED, CHECK_ALL);
+ }
+
if (FILE_SELECT_DIR == ret)
WM_event_add_notifier(C, NC_SPACE | ND_SPACE_FILE_LIST, NULL);
else if (FILE_SELECT_FILE == ret)
@@ -377,34 +532,267 @@ void FILE_OT_select(wmOperatorType *ot)
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
+/**
+ * \returns true if selection has changed
+ */
+static bool file_walk_select_selection_set(
+ bContext *C, SpaceFile *sfile,
+ const int direction, const int numfiles,
+ const int active_old, const int active_new, const int other_site,
+ const bool has_selection, const bool extend, const bool fill)
+{
+ FileSelectParams *params = sfile->params;
+ struct FileList *files = sfile->files;
+ const int last_sel = params->active_file; /* store old value */
+ int active = active_old; /* could use active_old instead, just for readability */
+ bool deselect = false;
+
+ BLI_assert(params);
+
+ if (has_selection) {
+ if (extend &&
+ filelist_entry_select_index_get(files, active_old, CHECK_ALL) &&
+ filelist_entry_select_index_get(files, active_new, CHECK_ALL))
+ {
+ /* conditions for deselecting: initial file is selected, new file is
+ * selected and either other_side isn't selected/found or we use fill */
+ deselect = (fill || other_site == -1 ||
+ !filelist_entry_select_index_get(files, other_site, CHECK_ALL));
+
+ /* don't change highlight_file here since we either want to deselect active or we want to
+ * walk through a block of selected files without selecting/deselecting anything */
+ params->active_file = active_new;
+ /* but we want to change active if we use fill (needed to get correct selection bounds) */
+ if (deselect && fill) {
+ active = active_new;
+ }
+ }
+ else {
+ /* regular selection change */
+ params->active_file = active = active_new;
+ }
+ }
+ else {
+ /* select last file */
+ if (ELEM(direction, FILE_SELECT_WALK_UP, FILE_SELECT_WALK_LEFT)) {
+ params->active_file = active = numfiles - 1;
+ }
+ /* select first file */
+ else if (ELEM(direction, FILE_SELECT_WALK_DOWN, FILE_SELECT_WALK_RIGHT)) {
+ params->active_file = active = extend ? 1 : 0;
+ }
+ else {
+ BLI_assert(0);
+ }
+ }
+
+ if (active < 0) {
+ return false;
+ }
+
+ if (extend) {
+ /* highlight the active walker file for extended selection for better visual feedback */
+ params->highlight_file = params->active_file;
+
+ /* unselect '..' parent entry - it's not supposed to be selected if more than one file is selected */
+ filelist_entry_select_index_set(files, 0, FILE_SEL_REMOVE, FILE_SEL_SELECTED, CHECK_ALL);
+ }
+ else {
+ /* deselect all first */
+ file_deselect_all(sfile, FILE_SEL_SELECTED);
+
+ /* highlight file under mouse pos */
+ params->highlight_file = -1;
+ WM_event_add_mousemove(C);
+ }
+
+ /* do the actual selection */
+ if (fill) {
+ FileSelection sel = { MIN2(active, last_sel), MAX2(active, last_sel) };
+
+ /* clamping selection to not include '..' parent entry */
+ if (sel.first == 0) {
+ sel.first = 1;
+ }
+
+ /* fill selection between last and first selected file */
+ filelist_entries_select_index_range_set(
+ files, &sel, deselect ? FILE_SEL_REMOVE : FILE_SEL_ADD, FILE_SEL_SELECTED, CHECK_ALL);
+ /* entire sel is cleared here, so select active again */
+ if (deselect) {
+ filelist_entry_select_index_set(files, active, FILE_SEL_ADD, FILE_SEL_SELECTED, CHECK_ALL);
+ }
+ }
+ else {
+ filelist_entry_select_index_set(
+ files, active, deselect ? FILE_SEL_REMOVE : FILE_SEL_ADD, FILE_SEL_SELECTED, CHECK_ALL);
+ }
+
+ BLI_assert(IN_RANGE(active, -1, numfiles));
+ fileselect_file_set(sfile, params->active_file);
+
+ /* ensure newly selected file is inside viewbounds */
+ file_ensure_inside_viewbounds(CTX_wm_region(C), sfile, params->active_file);
+
+ /* selection changed */
+ return true;
+}
+
+/**
+ * \returns true if selection has changed
+ */
+static bool file_walk_select_do(
+ bContext *C, SpaceFile *sfile,
+ FileSelectParams *params, const int direction,
+ const bool extend, const bool fill)
+{
+ struct FileList *files = sfile->files;
+ const int numfiles = filelist_files_ensure(files);
+ const bool has_selection = file_is_any_selected(files);
+ const int active_old = params->active_file;
+ int active_new = -1;
+ int other_site = -1; /* file on the other site of active_old */
+
+
+ /* *** get all needed files for handling selection *** */
+
+ if (has_selection) {
+ ARegion *ar = CTX_wm_region(C);
+ FileLayout *layout = ED_fileselect_get_layout(sfile, ar);
+ const int idx_shift = (layout->flag & FILE_LAYOUT_HOR) ? layout->rows : layout->columns;
+
+ if ((layout->flag & FILE_LAYOUT_HOR && direction == FILE_SELECT_WALK_UP) ||
+ (layout->flag & FILE_LAYOUT_VER && direction == FILE_SELECT_WALK_LEFT))
+ {
+ active_new = active_old - 1;
+ other_site = active_old + 1;
+ }
+ else if ((layout->flag & FILE_LAYOUT_HOR && direction == FILE_SELECT_WALK_DOWN) ||
+ (layout->flag & FILE_LAYOUT_VER && direction == FILE_SELECT_WALK_RIGHT))
+ {
+ active_new = active_old + 1;
+ other_site = active_old - 1;
+ }
+ else if ((layout->flag & FILE_LAYOUT_HOR && direction == FILE_SELECT_WALK_LEFT) ||
+ (layout->flag & FILE_LAYOUT_VER && direction == FILE_SELECT_WALK_UP))
+ {
+ active_new = active_old - idx_shift;
+ other_site = active_old + idx_shift;
+ }
+ else if ((layout->flag & FILE_LAYOUT_HOR && direction == FILE_SELECT_WALK_RIGHT) ||
+ (layout->flag & FILE_LAYOUT_VER && direction == FILE_SELECT_WALK_DOWN))
+ {
+
+ active_new = active_old + idx_shift;
+ other_site = active_old - idx_shift;
+ }
+ else {
+ BLI_assert(0);
+ }
+
+ if (!IN_RANGE(active_new, 0, numfiles)) {
+ if (extend) {
+ /* extend to invalid file -> abort */
+ return false;
+ }
+ /* if we don't extend, selecting '..' (index == 0) is allowed so
+ * using key selection to go to parent directory is possible */
+ else if (active_new != 0) {
+ /* select initial file */
+ active_new = active_old;
+ }
+ }
+ if (!IN_RANGE(other_site, 0, numfiles)) {
+ other_site = -1;
+ }
+ }
+
+ return file_walk_select_selection_set(
+ C, sfile, direction, numfiles, active_old, active_new, other_site, has_selection, extend, fill);
+}
+
+static int file_walk_select_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
+{
+ SpaceFile *sfile = (SpaceFile *)CTX_wm_space_data(C);
+ FileSelectParams *params = sfile->params;
+ const int direction = RNA_enum_get(op->ptr, "direction");
+ const bool extend = RNA_boolean_get(op->ptr, "extend");
+ const bool fill = RNA_boolean_get(op->ptr, "fill");
+
+ if (file_walk_select_do(C, sfile, params, direction, extend, fill)) {
+ WM_event_add_notifier(C, NC_SPACE | ND_SPACE_FILE_PARAMS, NULL);
+ return OPERATOR_FINISHED;
+ }
+
+ return OPERATOR_CANCELLED;
+}
+
+void FILE_OT_select_walk(wmOperatorType *ot)
+{
+ static EnumPropertyItem direction_items[] = {
+ {FILE_SELECT_WALK_UP, "UP", 0, "Prev", ""},
+ {FILE_SELECT_WALK_DOWN, "DOWN", 0, "Next", ""},
+ {FILE_SELECT_WALK_LEFT, "LEFT", 0, "Left", ""},
+ {FILE_SELECT_WALK_RIGHT, "RIGHT", 0, "Right", ""},
+ {0, NULL, 0, NULL, NULL}
+ };
+ PropertyRNA *prop;
+
+ /* identifiers */
+ ot->name = "Walk Select/Deselect File";
+ ot->description = "Select/Deselect files by walking through them";
+ ot->idname = "FILE_OT_select_walk";
+
+ /* api callbacks */
+ ot->invoke = file_walk_select_invoke;
+ ot->poll = ED_operator_file_active;
+
+ /* properties */
+ prop = RNA_def_enum(ot->srna, "direction", direction_items, 0, "Walk Direction",
+ "Select/Deselect file in this direction");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+ prop = RNA_def_boolean(ot->srna, "extend", false, "Extend",
+ "Extend selection instead of deselecting everything first");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+ prop = RNA_def_boolean(ot->srna, "fill", false, "Fill", "Select everything beginning with the last selection");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+}
+
static int file_select_all_exec(bContext *C, wmOperator *UNUSED(op))
{
ScrArea *sa = CTX_wm_area(C);
SpaceFile *sfile = CTX_wm_space_file(C);
FileSelection sel;
- int numfiles = filelist_numfiles(sfile->files);
- int i;
- bool is_selected = false;
+ const int numfiles = filelist_files_ensure(sfile->files);
+ const bool has_selection = file_is_any_selected(sfile->files);
sel.first = 0;
sel.last = numfiles - 1;
- /* Is any file selected ? */
- for (i = 0; i < numfiles; ++i) {
- if (filelist_is_selected(sfile->files, i, CHECK_ALL)) {
- is_selected = true;
- break;
- }
- }
/* select all only if previously no file was selected */
- if (is_selected) {
- filelist_select(sfile->files, &sel, FILE_SEL_REMOVE, SELECTED_FILE, CHECK_ALL);
+ if (has_selection) {
+ filelist_entries_select_index_range_set(sfile->files, &sel, FILE_SEL_REMOVE, FILE_SEL_SELECTED, CHECK_ALL);
+ sfile->params->active_file = -1;
}
else {
const FileCheckType check_type = (sfile->params->flag & FILE_DIRSEL_ONLY) ? CHECK_DIRS : CHECK_FILES;
- filelist_select(sfile->files, &sel, FILE_SEL_ADD, SELECTED_FILE, check_type);
+ int i;
+
+ filelist_entries_select_index_range_set(sfile->files, &sel, FILE_SEL_ADD, FILE_SEL_SELECTED, check_type);
+
+ /* set active_file to first selected */
+ for (i = 0; i < numfiles; i++) {
+ if (filelist_entry_select_index_get(sfile->files, i, check_type)) {
+ sfile->params->active_file = i;
+ break;
+ }
+ }
}
+
+ file_draw_check(C);
+ WM_event_add_mousemove(C);
ED_area_tag_redraw(sa);
+
return OPERATOR_FINISHED;
}
@@ -424,18 +812,20 @@ void FILE_OT_select_all_toggle(wmOperatorType *ot)
/* ---------- BOOKMARKS ----------- */
+/* Note we could get rid of this one, but it's used by some addon so... Does not hurt keeping it around for now. */
static int bookmark_select_exec(bContext *C, wmOperator *op)
{
SpaceFile *sfile = CTX_wm_space_file(C);
+ PropertyRNA *prop;
- if (RNA_struct_find_property(op->ptr, "dir")) {
+ if ((prop = RNA_struct_find_property(op->ptr, "dir"))) {
char entry[256];
FileSelectParams *params = sfile->params;
- RNA_string_get(op->ptr, "dir", entry);
+ RNA_property_string_get(op->ptr, prop, entry);
BLI_strncpy(params->dir, entry, sizeof(params->dir));
BLI_cleanup_dir(G.main->name, params->dir);
- file_change_dir(C, 1);
+ ED_file_change_dir(C, true);
WM_event_add_notifier(C, NC_SPACE | ND_SPACE_FILE_LIST, NULL);
}
@@ -465,17 +855,18 @@ static int bookmark_add_exec(bContext *C, wmOperator *UNUSED(op))
{
ScrArea *sa = CTX_wm_area(C);
SpaceFile *sfile = CTX_wm_space_file(C);
- struct FSMenu *fsmenu = fsmenu_get();
+ struct FSMenu *fsmenu = ED_fsmenu_get();
struct FileSelectParams *params = ED_fileselect_get_params(sfile);
if (params->dir[0] != '\0') {
char name[FILE_MAX];
- fsmenu_insert_entry(fsmenu, FS_CATEGORY_BOOKMARKS, params->dir, FS_INSERT_SAVE);
- BLI_make_file_string("/", name, BLI_get_folder_create(BLENDER_USER_CONFIG, NULL), BLENDER_BOOKMARK_FILE);
+ fsmenu_insert_entry(fsmenu, FS_CATEGORY_BOOKMARKS, params->dir, NULL, FS_INSERT_SAVE);
+ BLI_make_file_string("/", name, BKE_appdir_folder_id_create(BLENDER_USER_CONFIG, NULL), BLENDER_BOOKMARK_FILE);
fsmenu_write_file(fsmenu, name);
}
+ ED_area_tag_refresh(sa);
ED_area_tag_redraw(sa);
return OPERATOR_FINISHED;
}
@@ -495,17 +886,27 @@ void FILE_OT_bookmark_add(wmOperatorType *ot)
static int bookmark_delete_exec(bContext *C, wmOperator *op)
{
ScrArea *sa = CTX_wm_area(C);
- struct FSMenu *fsmenu = fsmenu_get();
- int nentries = fsmenu_get_nentries(fsmenu, FS_CATEGORY_BOOKMARKS);
-
- if (RNA_struct_find_property(op->ptr, "index")) {
- int index = RNA_int_get(op->ptr, "index");
+ SpaceFile *sfile = CTX_wm_space_file(C);
+ struct FSMenu *fsmenu = ED_fsmenu_get();
+ int nentries = ED_fsmenu_get_nentries(fsmenu, FS_CATEGORY_BOOKMARKS);
+
+ PropertyRNA *prop = RNA_struct_find_property(op->ptr, "index");
+
+ if (prop) {
+ int index;
+ if (RNA_property_is_set(op->ptr, prop)) {
+ index = RNA_property_int_get(op->ptr, prop);
+ }
+ else { /* if index unset, use active bookmark... */
+ index = sfile->bookmarknr;
+ }
if ((index > -1) && (index < nentries)) {
char name[FILE_MAX];
fsmenu_remove_entry(fsmenu, FS_CATEGORY_BOOKMARKS, index);
- BLI_make_file_string("/", name, BLI_get_folder_create(BLENDER_USER_CONFIG, NULL), BLENDER_BOOKMARK_FILE);
+ BLI_make_file_string("/", name, BKE_appdir_folder_id_create(BLENDER_USER_CONFIG, NULL), BLENDER_BOOKMARK_FILE);
fsmenu_write_file(fsmenu, name);
+ ED_area_tag_refresh(sa);
ED_area_tag_redraw(sa);
}
}
@@ -531,19 +932,150 @@ void FILE_OT_bookmark_delete(wmOperatorType *ot)
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
+static int bookmark_cleanup_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ ScrArea *sa = CTX_wm_area(C);
+ struct FSMenu *fsmenu = ED_fsmenu_get();
+ struct FSMenuEntry *fsme_next, *fsme = ED_fsmenu_get_category(fsmenu, FS_CATEGORY_BOOKMARKS);
+ int index;
+ bool changed = false;
+
+ for (index = 0; fsme; fsme = fsme_next) {
+ fsme_next = fsme->next;
+
+ if (!BLI_is_dir(fsme->path)) {
+ fsmenu_remove_entry(fsmenu, FS_CATEGORY_BOOKMARKS, index);
+ changed = true;
+ }
+ else {
+ index++;
+ }
+ }
+
+ if (changed) {
+ char name[FILE_MAX];
+
+ BLI_make_file_string("/", name, BKE_appdir_folder_id_create(BLENDER_USER_CONFIG, NULL), BLENDER_BOOKMARK_FILE);
+ fsmenu_write_file(fsmenu, name);
+ fsmenu_refresh_bookmarks_status(fsmenu);
+ ED_area_tag_refresh(sa);
+ ED_area_tag_redraw(sa);
+ }
+
+ return OPERATOR_FINISHED;
+}
+
+void FILE_OT_bookmark_cleanup(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Cleanup Bookmarks";
+ ot->description = "Delete all invalid bookmarks";
+ ot->idname = "FILE_OT_bookmark_cleanup";
+
+ /* api callbacks */
+ ot->exec = bookmark_cleanup_exec;
+ ot->poll = ED_operator_file_active;
+
+ /* properties */
+}
+
+enum {
+ FILE_BOOKMARK_MOVE_TOP = -2,
+ FILE_BOOKMARK_MOVE_UP = -1,
+ FILE_BOOKMARK_MOVE_DOWN = 1,
+ FILE_BOOKMARK_MOVE_BOTTOM = 2,
+};
+
+static int bookmark_move_exec(bContext *C, wmOperator *op)
+{
+ ScrArea *sa = CTX_wm_area(C);
+ SpaceFile *sfile = CTX_wm_space_file(C);
+ struct FSMenu *fsmenu = ED_fsmenu_get();
+ struct FSMenuEntry *fsmentry = ED_fsmenu_get_category(fsmenu, FS_CATEGORY_BOOKMARKS);
+ const struct FSMenuEntry *fsmentry_org = fsmentry;
+
+ char fname[FILE_MAX];
+
+ const int direction = RNA_enum_get(op->ptr, "direction");
+ const int totitems = ED_fsmenu_get_nentries(fsmenu, FS_CATEGORY_BOOKMARKS);
+ const int act_index = sfile->bookmarknr;
+ int new_index;
+
+ if (totitems < 2) {
+ return OPERATOR_CANCELLED;
+ }
+
+ switch (direction) {
+ case FILE_BOOKMARK_MOVE_TOP:
+ new_index = 0;
+ break;
+ case FILE_BOOKMARK_MOVE_BOTTOM:
+ new_index = totitems - 1;
+ break;
+ case FILE_BOOKMARK_MOVE_UP:
+ case FILE_BOOKMARK_MOVE_DOWN:
+ default:
+ new_index = (totitems + act_index + direction) % totitems;
+ break;
+ }
+
+ if (new_index == act_index) {
+ return OPERATOR_CANCELLED;
+ }
+
+ BLI_linklist_move_item((LinkNode **)&fsmentry, act_index, new_index);
+ if (fsmentry != fsmentry_org) {
+ ED_fsmenu_set_category(fsmenu, FS_CATEGORY_BOOKMARKS, fsmentry);
+ }
+
+ /* Need to update active bookmark number. */
+ sfile->bookmarknr = new_index;
+
+ BLI_make_file_string("/", fname, BKE_appdir_folder_id_create(BLENDER_USER_CONFIG, NULL), BLENDER_BOOKMARK_FILE);
+ fsmenu_write_file(fsmenu, fname);
+
+ ED_area_tag_redraw(sa);
+ return OPERATOR_FINISHED;
+}
+
+void FILE_OT_bookmark_move(wmOperatorType *ot)
+{
+ static EnumPropertyItem slot_move[] = {
+ {FILE_BOOKMARK_MOVE_TOP, "TOP", 0, "Top", "Top of the list"},
+ {FILE_BOOKMARK_MOVE_UP, "UP", 0, "Up", ""},
+ {FILE_BOOKMARK_MOVE_DOWN, "DOWN", 0, "Down", ""},
+ {FILE_BOOKMARK_MOVE_BOTTOM, "BOTTOM", 0, "Bottom", "Bottom of the list"},
+ { 0, NULL, 0, NULL, NULL }
+ };
+
+ /* identifiers */
+ ot->name = "Move Bookmark";
+ ot->idname = "FILE_OT_bookmark_move";
+ ot->description = "Move the active bookmark up/down in the list";
+
+ /* api callbacks */
+ ot->poll = ED_operator_file_active;
+ ot->exec = bookmark_move_exec;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER; /* No undo! */
+
+ RNA_def_enum(ot->srna, "direction", slot_move, 0, "Direction", "Direction to move, UP or DOWN");
+}
+
static int reset_recent_exec(bContext *C, wmOperator *UNUSED(op))
{
ScrArea *sa = CTX_wm_area(C);
char name[FILE_MAX];
- struct FSMenu *fsmenu = fsmenu_get();
+ struct FSMenu *fsmenu = ED_fsmenu_get();
- while (fsmenu_get_entry(fsmenu, FS_CATEGORY_RECENT, 0) != NULL) {
+ while (ED_fsmenu_get_entry(fsmenu, FS_CATEGORY_RECENT, 0) != NULL) {
fsmenu_remove_entry(fsmenu, FS_CATEGORY_RECENT, 0);
}
- BLI_make_file_string("/", name, BLI_get_folder_create(BLENDER_USER_CONFIG, NULL), BLENDER_BOOKMARK_FILE);
+ BLI_make_file_string("/", name, BKE_appdir_folder_id_create(BLENDER_USER_CONFIG, NULL), BLENDER_BOOKMARK_FILE);
fsmenu_write_file(fsmenu, name);
ED_area_tag_redraw(sa);
-
+
return OPERATOR_FINISHED;
}
@@ -568,31 +1100,31 @@ int file_highlight_set(SpaceFile *sfile, ARegion *ar, int mx, int my)
if (sfile == NULL || sfile->files == NULL) return 0;
- numfiles = filelist_numfiles(sfile->files);
+ numfiles = filelist_files_ensure(sfile->files);
params = ED_fileselect_get_params(sfile);
- origfile = params->active_file;
+ origfile = params->highlight_file;
mx -= ar->winrct.xmin;
my -= ar->winrct.ymin;
if (BLI_rcti_isect_pt(&ar->v2d.mask, mx, my)) {
float fx, fy;
- int active_file;
+ int highlight_file;
UI_view2d_region_to_view(v2d, mx, my, &fx, &fy);
- active_file = ED_fileselect_layout_offset(sfile->layout, (int)(v2d->tot.xmin + fx), (int)(v2d->tot.ymax - fy));
+ highlight_file = ED_fileselect_layout_offset(sfile->layout, (int)(v2d->tot.xmin + fx), (int)(v2d->tot.ymax - fy));
- if ((active_file >= 0) && (active_file < numfiles))
- params->active_file = active_file;
+ if ((highlight_file >= 0) && (highlight_file < numfiles))
+ params->highlight_file = highlight_file;
else
- params->active_file = -1;
+ params->highlight_file = -1;
}
else
- params->active_file = -1;
+ params->highlight_file = -1;
- return (params->active_file != origfile);
+ return (params->highlight_file != origfile);
}
static int file_highlight_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *event)
@@ -658,65 +1190,67 @@ void FILE_OT_cancel(struct wmOperatorType *ot)
void file_sfile_to_operator(wmOperator *op, SpaceFile *sfile, char *filepath)
{
+ PropertyRNA *prop;
+
BLI_join_dirfile(filepath, FILE_MAX, sfile->params->dir, sfile->params->file); /* XXX, not real length */
- if (RNA_struct_find_property(op->ptr, "relative_path")) {
- if (RNA_boolean_get(op->ptr, "relative_path")) {
+
+ if ((prop = RNA_struct_find_property(op->ptr, "relative_path"))) {
+ if (RNA_property_boolean_get(op->ptr, prop)) {
BLI_path_rel(filepath, G.main->name);
}
}
- if (RNA_struct_find_property(op->ptr, "filename")) {
- RNA_string_set(op->ptr, "filename", sfile->params->file);
+ if ((prop = RNA_struct_find_property(op->ptr, "filename"))) {
+ RNA_property_string_set(op->ptr, prop, sfile->params->file);
}
- if (RNA_struct_find_property(op->ptr, "directory")) {
- RNA_string_set(op->ptr, "directory", sfile->params->dir);
+ if ((prop = RNA_struct_find_property(op->ptr, "directory"))) {
+ RNA_property_string_set(op->ptr, prop, sfile->params->dir);
}
- if (RNA_struct_find_property(op->ptr, "filepath")) {
- RNA_string_set(op->ptr, "filepath", filepath);
+ if ((prop = RNA_struct_find_property(op->ptr, "filepath"))) {
+ RNA_property_string_set(op->ptr, prop, filepath);
}
/* some ops have multiple files to select */
/* this is called on operators check() so clear collections first since
* they may be already set. */
{
- PointerRNA itemptr;
- PropertyRNA *prop_files = RNA_struct_find_property(op->ptr, "files");
- PropertyRNA *prop_dirs = RNA_struct_find_property(op->ptr, "dirs");
- int i, numfiles = filelist_numfiles(sfile->files);
+ int i, numfiles = filelist_files_ensure(sfile->files);
- if (prop_files) {
+ if ((prop = RNA_struct_find_property(op->ptr, "files"))) {
+ PointerRNA itemptr;
int num_files = 0;
- RNA_property_collection_clear(op->ptr, prop_files);
+ RNA_property_collection_clear(op->ptr, prop);
for (i = 0; i < numfiles; i++) {
- if (filelist_is_selected(sfile->files, i, CHECK_FILES)) {
- struct direntry *file = filelist_file(sfile->files, i);
- RNA_property_collection_add(op->ptr, prop_files, &itemptr);
- RNA_string_set(&itemptr, "name", file->relname);
+ if (filelist_entry_select_index_get(sfile->files, i, CHECK_FILES)) {
+ FileDirEntry *file = filelist_file(sfile->files, i);
+ RNA_property_collection_add(op->ptr, prop, &itemptr);
+ RNA_string_set(&itemptr, "name", file->relpath);
num_files++;
}
}
/* make sure the file specified in the filename button is added even if no files selected */
if (0 == num_files) {
- RNA_property_collection_add(op->ptr, prop_files, &itemptr);
+ RNA_property_collection_add(op->ptr, prop, &itemptr);
RNA_string_set(&itemptr, "name", sfile->params->file);
}
}
- if (prop_dirs) {
+ if ((prop = RNA_struct_find_property(op->ptr, "dirs"))) {
+ PointerRNA itemptr;
int num_dirs = 0;
- RNA_property_collection_clear(op->ptr, prop_dirs);
+ RNA_property_collection_clear(op->ptr, prop);
for (i = 0; i < numfiles; i++) {
- if (filelist_is_selected(sfile->files, i, CHECK_DIRS)) {
- struct direntry *file = filelist_file(sfile->files, i);
- RNA_property_collection_add(op->ptr, prop_dirs, &itemptr);
- RNA_string_set(&itemptr, "name", file->relname);
+ if (filelist_entry_select_index_get(sfile->files, i, CHECK_DIRS)) {
+ FileDirEntry *file = filelist_file(sfile->files, i);
+ RNA_property_collection_add(op->ptr, prop, &itemptr);
+ RNA_string_set(&itemptr, "name", file->relpath);
num_dirs++;
}
}
/* make sure the directory specified in the button is added even if no directory selected */
if (0 == num_dirs) {
- RNA_property_collection_add(op->ptr, prop_dirs, &itemptr);
+ RNA_property_collection_add(op->ptr, prop, &itemptr);
RNA_string_set(&itemptr, "name", sfile->params->dir);
}
}
@@ -751,7 +1285,7 @@ void file_operator_to_sfile(SpaceFile *sfile, wmOperator *op)
/* XXX, files and dirs updates missing, not really so important though */
}
-void file_draw_check_cb(bContext *C, void *UNUSED(arg1), void *UNUSED(arg2))
+void file_draw_check(bContext *C)
{
SpaceFile *sfile = CTX_wm_space_file(C);
wmOperator *op = sfile->op;
@@ -771,11 +1305,18 @@ void file_draw_check_cb(bContext *C, void *UNUSED(arg1), void *UNUSED(arg2))
}
}
+/* for use with; UI_block_func_set */
+void file_draw_check_cb(bContext *C, void *UNUSED(arg1), void *UNUSED(arg2))
+{
+ file_draw_check(C);
+}
+
bool file_draw_check_exists(SpaceFile *sfile)
{
if (sfile->op) { /* fails on reload */
- if (RNA_struct_find_property(sfile->op->ptr, "check_existing")) {
- if (RNA_boolean_get(sfile->op->ptr, "check_existing")) {
+ PropertyRNA *prop;
+ if ((prop = RNA_struct_find_property(sfile->op->ptr, "check_existing"))) {
+ if (RNA_property_boolean_get(sfile->op->ptr, prop)) {
char filepath[FILE_MAX];
BLI_join_dirfile(filepath, sizeof(filepath), sfile->params->dir, sfile->params->file);
if (BLI_is_file(filepath)) {
@@ -788,23 +1329,42 @@ bool file_draw_check_exists(SpaceFile *sfile)
return false;
}
-/* sends events now, so things get handled on windowqueue level */
int file_exec(bContext *C, wmOperator *exec_op)
{
wmWindowManager *wm = CTX_wm_manager(C);
SpaceFile *sfile = CTX_wm_space_file(C);
+ const struct FileDirEntry *file = filelist_file(sfile->files, sfile->params->active_file);
char filepath[FILE_MAX];
-
- if (sfile->op) {
+
+ /* directory change */
+ if (file && (file->typeflag & FILE_TYPE_DIR)) {
+ if (!file->relpath) {
+ return OPERATOR_CANCELLED;
+ }
+
+ if (FILENAME_IS_PARENT(file->relpath)) {
+ BLI_parent_dir(sfile->params->dir);
+ }
+ else {
+ BLI_cleanup_dir(G.main->name, sfile->params->dir);
+ strcat(sfile->params->dir, file->relpath);
+ BLI_add_slash(sfile->params->dir);
+ }
+
+ ED_file_change_dir(C, false);
+ }
+ /* opening file - sends events now, so things get handled on windowqueue level */
+ else if (sfile->op) {
wmOperator *op = sfile->op;
/* when used as a macro, for doubleclick,
* to prevent closing when doubleclicking on .. item */
if (RNA_boolean_get(exec_op->ptr, "need_active")) {
+ const int numfiles = filelist_files_ensure(sfile->files);
int i, active = 0;
- for (i = 0; i < filelist_numfiles(sfile->files); i++) {
- if (filelist_is_selected(sfile->files, i, CHECK_ALL)) {
+ for (i = 0; i < numfiles; i++) {
+ if (filelist_entry_select_index_get(sfile->files, i, CHECK_ALL)) {
active = 1;
break;
}
@@ -818,15 +1378,17 @@ int file_exec(bContext *C, wmOperator *exec_op)
file_sfile_to_operator(op, sfile, filepath);
if (BLI_exists(sfile->params->dir)) {
- fsmenu_insert_entry(fsmenu_get(), FS_CATEGORY_RECENT, sfile->params->dir, FS_INSERT_SAVE | FS_INSERT_FIRST);
+ fsmenu_insert_entry(ED_fsmenu_get(), FS_CATEGORY_RECENT, sfile->params->dir, NULL,
+ FS_INSERT_SAVE | FS_INSERT_FIRST);
}
- BLI_make_file_string(G.main->name, filepath, BLI_get_folder_create(BLENDER_USER_CONFIG, NULL), BLENDER_BOOKMARK_FILE);
- fsmenu_write_file(fsmenu_get(), filepath);
+ BLI_make_file_string(G.main->name, filepath, BKE_appdir_folder_id_create(BLENDER_USER_CONFIG, NULL),
+ BLENDER_BOOKMARK_FILE);
+ fsmenu_write_file(ED_fsmenu_get(), filepath);
WM_event_fileselect_event(wm, op, EVT_FILESELECT_EXEC);
}
-
+
return OPERATOR_FINISHED;
}
@@ -859,16 +1421,21 @@ int file_parent_exec(bContext *C, wmOperator *UNUSED(unused))
BLI_cleanup_dir(G.main->name, sfile->params->dir);
/* if not browsing in .blend file, we still want to check whether the path is a directory */
if (sfile->params->type == FILE_LOADLIB) {
- char tdir[FILE_MAX], tgroup[FILE_MAX];
- if (BLO_is_a_library(sfile->params->dir, tdir, tgroup)) {
- file_change_dir(C, 0);
+ char tdir[FILE_MAX];
+ if (BLO_library_path_explode(sfile->params->dir, tdir, NULL, NULL)) {
+ ED_file_change_dir(C, false);
}
else {
- file_change_dir(C, 1);
+ ED_file_change_dir(C, true);
}
}
else {
- file_change_dir(C, 1);
+ ED_file_change_dir(C, true);
+ }
+ if (sfile->params->recursion_level > 1) {
+ /* Disable 'dirtree' recursion when going up in tree. */
+ sfile->params->recursion_level = 0;
+ filelist_setrecursion(sfile->files, sfile->params->recursion_level);
}
WM_event_add_notifier(C, NC_SPACE | ND_SPACE_FILE_LIST, NULL);
}
@@ -896,9 +1463,10 @@ static int file_refresh_exec(bContext *C, wmOperator *UNUSED(unused))
{
wmWindowManager *wm = CTX_wm_manager(C);
SpaceFile *sfile = CTX_wm_space_file(C);
- struct FSMenu *fsmenu = fsmenu_get();
+ ScrArea *sa = CTX_wm_area(C);
+ struct FSMenu *fsmenu = ED_fsmenu_get();
- ED_fileselect_clear(wm, sfile);
+ ED_fileselect_clear(wm, sa, sfile);
/* refresh system directory menu */
fsmenu_refresh_system_category(fsmenu);
@@ -933,7 +1501,7 @@ int file_previous_exec(bContext *C, wmOperator *UNUSED(unused))
folderlist_popdir(sfile->folders_prev, sfile->params->dir);
folderlist_pushdir(sfile->folders_next, sfile->params->dir);
- file_change_dir(C, 1);
+ ED_file_change_dir(C, true);
}
WM_event_add_notifier(C, NC_SPACE | ND_SPACE_FILE_LIST, NULL);
@@ -965,7 +1533,7 @@ int file_next_exec(bContext *C, wmOperator *UNUSED(unused))
// update folders_prev so we can check for it in folderlist_clear_next()
folderlist_pushdir(sfile->folders_prev, sfile->params->dir);
- file_change_dir(C, 1);
+ ED_file_change_dir(C, true);
}
WM_event_add_notifier(C, NC_SPACE | ND_SPACE_FILE_LIST, NULL);
@@ -988,11 +1556,11 @@ static int file_smoothscroll_invoke(bContext *C, wmOperator *UNUSED(op), const w
if (sfile->smoothscroll_timer == NULL || sfile->smoothscroll_timer != event->customdata)
return OPERATOR_PASS_THROUGH;
- numfiles = filelist_numfiles(sfile->files);
+ numfiles = filelist_files_ensure(sfile->files);
/* check if we are editing a name */
for (i = 0; i < numfiles; ++i) {
- if (filelist_is_selected(sfile->files, i, CHECK_ALL) ) {
+ if (filelist_entry_select_index_get(sfile->files, i, CHECK_ALL) ) {
edit_idx = i;
break;
}
@@ -1110,10 +1678,12 @@ int file_directory_new_exec(bContext *C, wmOperator *op)
{
char name[FILE_MAXFILE];
char path[FILE_MAX];
- int generate_name = 1;
+ bool generate_name = true;
+ PropertyRNA *prop;
wmWindowManager *wm = CTX_wm_manager(C);
SpaceFile *sfile = CTX_wm_space_file(C);
+ ScrArea *sa = CTX_wm_area(C);
if (!sfile->params) {
BKE_report(op->reports, RPT_WARNING, "No parent directory given");
@@ -1122,9 +1692,11 @@ int file_directory_new_exec(bContext *C, wmOperator *op)
path[0] = '\0';
- if (RNA_struct_find_property(op->ptr, "directory")) {
- RNA_string_get(op->ptr, "directory", path);
- if (path[0] != '\0') generate_name = 0;
+ if ((prop = RNA_struct_find_property(op->ptr, "directory"))) {
+ RNA_property_string_get(op->ptr, prop, path);
+ if (path[0] != '\0') {
+ generate_name = false;
+ }
}
if (generate_name) {
@@ -1134,10 +1706,23 @@ int file_directory_new_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
}
+ else { /* We assume we are able to generate a valid name! */
+ char org_path[FILE_MAX];
+
+ BLI_strncpy(org_path, path, sizeof(org_path));
+ if (BLI_path_make_safe(path)) {
+ BKE_reportf(op->reports, RPT_WARNING, "'%s' given path is OS-invalid, creating '%s' path instead",
+ org_path, path);
+ }
+ }
/* create the file */
- BLI_dir_create_recursive(path);
+ if (!BLI_dir_create_recursive(path)) {
+ BKE_report(op->reports, RPT_ERROR, "Could not create new folder");
+ return OPERATOR_CANCELLED;
+ }
+ /* Should no more be needed, now that BLI_dir_create_recursive returns a success state - but kept just in case. */
if (!BLI_exists(path)) {
BKE_report(op->reports, RPT_ERROR, "Could not create new folder");
return OPERATOR_CANCELLED;
@@ -1151,11 +1736,11 @@ int file_directory_new_exec(bContext *C, wmOperator *op)
sfile->scroll_offset = 0;
/* reload dir to make sure we're seeing what's in the directory */
- ED_fileselect_clear(wm, sfile);
+ ED_fileselect_clear(wm, sa, sfile);
if (RNA_boolean_get(op->ptr, "open")) {
BLI_strncpy(sfile->params->dir, path, sizeof(sfile->params->dir));
- file_change_dir(C, 1);
+ ED_file_change_dir(C, true);
}
WM_event_add_notifier(C, NC_SPACE | ND_SPACE_FILE_LIST, NULL);
@@ -1185,6 +1770,7 @@ void FILE_OT_directory_new(struct wmOperatorType *ot)
}
+/* TODO This should go to BLI_path_utils. */
static void file_expand_directory(bContext *C)
{
SpaceFile *sfile = CTX_wm_space_file(C);
@@ -1197,7 +1783,7 @@ static void file_expand_directory(bContext *C)
else if (sfile->params->dir[0] == '~') {
char tmpstr[sizeof(sfile->params->dir) - 1];
BLI_strncpy(tmpstr, sfile->params->dir + 1, sizeof(tmpstr));
- BLI_join_dirfile(sfile->params->dir, sizeof(sfile->params->dir), BLI_getDefaultDocumentFolder(), tmpstr);
+ BLI_join_dirfile(sfile->params->dir, sizeof(sfile->params->dir), BKE_appdir_folder_default(), tmpstr);
}
else if (sfile->params->dir[0] == '\0')
@@ -1225,6 +1811,7 @@ static void file_expand_directory(bContext *C)
}
}
+/* TODO check we still need this, it's annoying to have OS-specific code here... :/ */
#if defined(WIN32)
static bool can_create_dir(const char *dir)
{
@@ -1260,7 +1847,7 @@ void file_directory_enter_handle(bContext *C, void *UNUSED(arg_unused), void *UN
if (BLI_exists(sfile->params->dir)) {
/* if directory exists, enter it immediately */
- file_change_dir(C, 1);
+ ED_file_change_dir(C, true);
/* don't do for now because it selects entire text instead of
* placing cursor at the end */
@@ -1311,6 +1898,9 @@ void file_filename_enter_handle(bContext *C, void *UNUSED(arg_unused), void *arg
matches = file_select_match(sfile, sfile->params->file, matched_file);
+ /* *After* file_select_match! */
+ BLI_filename_make_safe(sfile->params->file);
+
if (matches) {
/* int i, numfiles = filelist_numfiles(sfile->files); */ /* XXX UNUSED */
sfile->params->file[0] = '\0';
@@ -1329,23 +1919,26 @@ void file_filename_enter_handle(bContext *C, void *UNUSED(arg_unused), void *arg
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);
+ ED_file_change_dir(C, true);
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];
+ char tdir[FILE_MAX];
BLI_add_slash(filepath);
- if (BLO_is_a_library(filepath, tdir, tgroup)) {
+ if (BLO_library_path_explode(filepath, tdir, NULL, NULL)) {
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);
+ ED_file_change_dir(C, false);
UI_textbutton_activate_but(C, but);
WM_event_add_notifier(C, NC_SPACE | ND_SPACE_FILE_LIST, NULL);
}
}
}
+ else if (matches > 1) {
+ file_draw_check(C);
+ }
}
}
@@ -1365,10 +1958,11 @@ static int file_hidedot_exec(bContext *C, wmOperator *UNUSED(unused))
{
wmWindowManager *wm = CTX_wm_manager(C);
SpaceFile *sfile = CTX_wm_space_file(C);
+ ScrArea *sa = CTX_wm_area(C);
if (sfile->params) {
sfile->params->flag ^= FILE_HIDE_DOT;
- ED_fileselect_clear(wm, sfile);
+ ED_fileselect_clear(wm, sa, sfile);
WM_event_add_notifier(C, NC_SPACE | ND_SPACE_FILE_LIST, NULL);
}
@@ -1388,37 +1982,37 @@ void FILE_OT_hidedot(struct wmOperatorType *ot)
ot->poll = ED_operator_file_active; /* <- important, handler is on window level */
}
-ARegion *file_buttons_region(ScrArea *sa)
+ARegion *file_tools_region(ScrArea *sa)
{
ARegion *ar, *arnew;
-
- for (ar = sa->regionbase.first; ar; ar = ar->next)
- if (ar->regiontype == RGN_TYPE_CHANNELS)
- return ar;
+
+ if ((ar = BKE_area_find_region_type(sa, RGN_TYPE_TOOLS)) != NULL)
+ return ar;
/* add subdiv level; after header */
- for (ar = sa->regionbase.first; ar; ar = ar->next)
- if (ar->regiontype == RGN_TYPE_HEADER)
- break;
+ ar = BKE_area_find_region_type(sa, RGN_TYPE_HEADER);
/* is error! */
- if (ar == NULL) return NULL;
-
- arnew = MEM_callocN(sizeof(ARegion), "buttons for file panels");
+ if (ar == NULL)
+ return NULL;
+ arnew = MEM_callocN(sizeof(ARegion), "tools for file");
BLI_insertlinkafter(&sa->regionbase, ar, arnew);
- arnew->regiontype = RGN_TYPE_CHANNELS;
+ arnew->regiontype = RGN_TYPE_TOOLS;
arnew->alignment = RGN_ALIGN_LEFT;
-
- arnew->flag = RGN_FLAG_HIDDEN;
-
+
+ ar = MEM_callocN(sizeof(ARegion), "tool props for file");
+ BLI_insertlinkafter(&sa->regionbase, arnew, ar);
+ ar->regiontype = RGN_TYPE_TOOL_PROPS;
+ ar->alignment = RGN_ALIGN_BOTTOM | RGN_SPLIT_PREV;
+
return arnew;
}
static int file_bookmark_toggle_exec(bContext *C, wmOperator *UNUSED(unused))
{
ScrArea *sa = CTX_wm_area(C);
- ARegion *ar = file_buttons_region(sa);
+ ARegion *ar = file_tools_region(sa);
if (ar)
ED_region_toggle_hidden(C, ar);
@@ -1448,7 +2042,7 @@ static int file_filenum_exec(bContext *C, wmOperator *op)
if (sfile->params && (inc != 0)) {
BLI_newname(sfile->params->file, inc);
ED_area_tag_redraw(sa);
- file_draw_check_cb(C, NULL, NULL);
+ file_draw_check(C);
// WM_event_add_notifier(C, NC_WINDOW, NULL);
}
@@ -1477,12 +2071,12 @@ static int file_rename_exec(bContext *C, wmOperator *UNUSED(op))
SpaceFile *sfile = (SpaceFile *)CTX_wm_space_data(C);
if (sfile->params) {
- int idx = sfile->params->active_file;
- int numfiles = filelist_numfiles(sfile->files);
- if ( (0 <= idx) && (idx < numfiles) ) {
- struct direntry *file = filelist_file(sfile->files, idx);
- filelist_select_file(sfile->files, idx, FILE_SEL_ADD, EDITING_FILE, CHECK_ALL);
- BLI_strncpy(sfile->params->renameedit, file->relname, FILE_MAXFILE);
+ int idx = sfile->params->highlight_file;
+ int numfiles = filelist_files_ensure(sfile->files);
+ if ((0 <= idx) && (idx < numfiles)) {
+ FileDirEntry *file = filelist_file(sfile->files, idx);
+ filelist_entry_select_index_set(sfile->files, idx, FILE_SEL_ADD, FILE_SEL_EDITING, CHECK_ALL);
+ BLI_strncpy(sfile->params->renameedit, file->relpath, FILE_MAXFILE);
sfile->params->renamefile[0] = '\0';
}
ED_area_tag_redraw(sa);
@@ -1494,20 +2088,34 @@ static int file_rename_exec(bContext *C, wmOperator *UNUSED(op))
static int file_rename_poll(bContext *C)
{
- int poll = ED_operator_file_active(C);
+ bool poll = ED_operator_file_active(C);
SpaceFile *sfile = CTX_wm_space_file(C);
if (sfile && sfile->params) {
- if (sfile->params->active_file < 0) {
- poll = 0;
+ int idx = sfile->params->highlight_file;
+ int numfiles = filelist_files_ensure(sfile->files);
+
+ if ((0 <= idx) && (idx < numfiles)) {
+ FileDirEntry *file = filelist_file(sfile->files, idx);
+ if (FILENAME_IS_CURRPAR(file->relpath)) {
+ poll = false;
+ }
+ }
+
+ if (sfile->params->highlight_file < 0) {
+ poll = false;
}
else {
- char dir[FILE_MAX], group[FILE_MAX];
- if (filelist_islibrary(sfile->files, dir, group)) poll = 0;
+ char dir[FILE_MAX];
+ if (filelist_islibrary(sfile->files, dir, NULL)) {
+ poll = false;
+ }
}
}
- else
- poll = 0;
+ else {
+ poll = false;
+ }
+
return poll;
}
@@ -1530,14 +2138,14 @@ static int file_delete_poll(bContext *C)
SpaceFile *sfile = CTX_wm_space_file(C);
if (sfile && sfile->params) {
- char dir[FILE_MAX], group[FILE_MAX];
- int numfiles = filelist_numfiles(sfile->files);
+ char dir[FILE_MAX];
+ int numfiles = filelist_files_ensure(sfile->files);
int i;
int num_selected = 0;
- if (filelist_islibrary(sfile->files, dir, group)) poll = 0;
+ if (filelist_islibrary(sfile->files, dir, NULL)) poll = 0;
for (i = 0; i < numfiles; i++) {
- if (filelist_is_selected(sfile->files, i, CHECK_FILES)) {
+ if (filelist_entry_select_index_get(sfile->files, i, CHECK_FILES)) {
num_selected++;
}
}
@@ -1556,19 +2164,20 @@ int file_delete_exec(bContext *C, wmOperator *UNUSED(op))
char str[FILE_MAX];
wmWindowManager *wm = CTX_wm_manager(C);
SpaceFile *sfile = CTX_wm_space_file(C);
- struct direntry *file;
- int numfiles = filelist_numfiles(sfile->files);
+ ScrArea *sa = CTX_wm_area(C);
+ FileDirEntry *file;
+ int numfiles = filelist_files_ensure(sfile->files);
int i;
for (i = 0; i < numfiles; i++) {
- if (filelist_is_selected(sfile->files, i, CHECK_FILES)) {
+ if (filelist_entry_select_index_get(sfile->files, i, CHECK_FILES)) {
file = filelist_file(sfile->files, i);
- BLI_make_file_string(G.main->name, str, sfile->params->dir, file->relname);
+ BLI_make_file_string(G.main->name, str, sfile->params->dir, file->relpath);
BLI_delete(str, false, false);
}
}
- ED_fileselect_clear(wm, sfile);
+ ED_fileselect_clear(wm, sa, sfile);
WM_event_add_notifier(C, NC_SPACE | ND_SPACE_FILE_LIST, NULL);
return OPERATOR_FINISHED;
diff --git a/source/blender/editors/space_file/file_panels.c b/source/blender/editors/space_file/file_panels.c
index 8fad17e1210..7acf2564fb2 100644
--- a/source/blender/editors/space_file/file_panels.c
+++ b/source/blender/editors/space_file/file_panels.c
@@ -34,7 +34,7 @@
#include "BKE_context.h"
#include "BKE_screen.h"
-#include "BLF_translation.h"
+#include "BLT_translation.h"
#include "DNA_screen_types.h"
#include "DNA_space_types.h"
@@ -44,6 +44,8 @@
#include "RNA_access.h"
+#include "ED_fileselect.h"
+
#include "UI_interface.h"
#include "UI_resources.h"
@@ -55,140 +57,6 @@
#include <string.h>
-static void file_panel_cb(bContext *C, void *arg_entry, void *UNUSED(arg_v))
-{
- wmOperatorType *ot = WM_operatortype_find("FILE_OT_select_bookmark", false);
- PointerRNA ptr;
- const char *entry = (char *)arg_entry;
-
- WM_operator_properties_create_ptr(&ptr, ot);
- RNA_string_set(&ptr, "dir", entry);
- WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_REGION_WIN, &ptr);
- WM_operator_properties_free(&ptr);
-}
-
-static void file_panel_category(const bContext *C, Panel *pa, FSMenuCategory category, short *nr, int icon, int allow_delete)
-{
- SpaceFile *sfile = CTX_wm_space_file(C);
- uiBlock *block;
- uiBut *but;
- uiLayout *box, *col;
- struct FSMenu *fsmenu = fsmenu_get();
- int i, nentries = fsmenu_get_nentries(fsmenu, category);
-
- /* reset each time */
- *nr = -1;
-
- /* hide if no entries */
- if (nentries == 0)
- return;
-
- /* layout */
- uiLayoutSetAlignment(pa->layout, UI_LAYOUT_ALIGN_LEFT);
- block = uiLayoutGetBlock(pa->layout);
- box = uiLayoutBox(pa->layout);
- col = uiLayoutColumn(box, true);
-
- for (i = 0; i < nentries; ++i) {
- char dir[FILE_MAX];
- char temp[FILE_MAX];
- uiLayout *layout = uiLayoutRow(col, false);
- char *entry;
-
- entry = fsmenu_get_entry(fsmenu, category, i);
-
- /* set this list item as active if we have a match */
- if (sfile->params) {
- if (BLI_path_cmp(sfile->params->dir, entry) == 0) {
- *nr = i;
- }
- }
-
- /* create nice bookmark name, shows last directory in the full path currently */
- BLI_strncpy(temp, entry, FILE_MAX);
- BLI_add_slash(temp);
- BLI_getlastdir(temp, dir, FILE_MAX);
- BLI_del_slash(dir);
-
- if (dir[0] == 0)
- BLI_strncpy(dir, entry, FILE_MAX);
-
- /* create list item */
- 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 */
- uiButSetDrawFlag(but, UI_BUT_ICON_LEFT | UI_BUT_TEXT_LEFT);
-
- /* create delete button */
- if (allow_delete && fsmenu_can_save(fsmenu, category, i)) {
- uiBlockSetEmboss(block, UI_EMBOSSN);
- uiItemIntO(layout, "", ICON_X, "FILE_OT_bookmark_delete", "index", i);
- uiBlockSetEmboss(block, UI_EMBOSS);
- }
- }
-}
-
-static void file_panel_system(const bContext *C, Panel *pa)
-{
- SpaceFile *sfile = CTX_wm_space_file(C);
-
- if (sfile)
- file_panel_category(C, pa, FS_CATEGORY_SYSTEM, &sfile->systemnr, ICON_DISK_DRIVE, 0);
-}
-
-static int file_panel_system_bookmarks_poll(const bContext *C, PanelType *UNUSED(pt))
-{
- SpaceFile *sfile = CTX_wm_space_file(C);
- return (sfile && !(U.uiflag & USER_HIDE_SYSTEM_BOOKMARKS));
-}
-
-static void file_panel_system_bookmarks(const bContext *C, Panel *pa)
-{
- SpaceFile *sfile = CTX_wm_space_file(C);
-
- if (sfile && !(U.uiflag & USER_HIDE_SYSTEM_BOOKMARKS)) {
- file_panel_category(C, pa, FS_CATEGORY_SYSTEM_BOOKMARKS, &sfile->systemnr, ICON_BOOKMARKS, 0);
- }
-
-}
-
-static void file_panel_bookmarks(const bContext *C, Panel *pa)
-{
- SpaceFile *sfile = CTX_wm_space_file(C);
- uiLayout *row;
-
- if (sfile) {
- row = uiLayoutRow(pa->layout, false);
- uiItemO(row, IFACE_("Add"), ICON_ZOOMIN, "file.bookmark_add");
- uiItemL(row, NULL, ICON_NONE);
-
- file_panel_category(C, pa, FS_CATEGORY_BOOKMARKS, &sfile->bookmarknr, ICON_BOOKMARKS, 1);
- }
-}
-
-static int file_panel_recent_poll(const bContext *C, PanelType *UNUSED(pt))
-{
- SpaceFile *sfile = CTX_wm_space_file(C);
- return (sfile && !(U.uiflag & USER_HIDE_RECENT));
-}
-
-static void file_panel_recent(const bContext *C, Panel *pa)
-{
- SpaceFile *sfile = CTX_wm_space_file(C);
- uiLayout *row;
-
- if (sfile) {
- if (!(U.uiflag & USER_HIDE_RECENT)) {
- row = uiLayoutRow(pa->layout, false);
- uiItemO(row, IFACE_("Reset"), ICON_X, "file.reset_recent");
- uiItemL(row, NULL, ICON_NONE);
-
- file_panel_category(C, pa, FS_CATEGORY_RECENT, &sfile->recentnr, ICON_FILE_FOLDER, 0);
- }
- }
-}
-
-
static int file_panel_operator_poll(const bContext *C, PanelType *UNUSED(pt))
{
SpaceFile *sfile = CTX_wm_space_file(C);
@@ -217,52 +85,22 @@ static void file_panel_operator(const bContext *C, Panel *pa)
SpaceFile *sfile = CTX_wm_space_file(C);
wmOperator *op = sfile->op;
// int empty = 1, flag;
-
- uiBlockSetFunc(uiLayoutGetBlock(pa->layout), file_draw_check_cb, NULL, NULL);
+
+ UI_block_func_set(uiLayoutGetBlock(pa->layout), file_draw_check_cb, NULL, NULL);
uiLayoutOperatorButs(C, pa->layout, op, file_panel_check_prop, '\0', UI_LAYOUT_OP_SHOW_EMPTY);
- uiBlockSetFunc(uiLayoutGetBlock(pa->layout), NULL, NULL, NULL);
+ UI_block_func_set(uiLayoutGetBlock(pa->layout), NULL, NULL, NULL);
}
void file_panels_register(ARegionType *art)
{
PanelType *pt;
- pt = MEM_callocN(sizeof(PanelType), "spacetype file system directories");
- strcpy(pt->idname, "FILE_PT_system");
- strcpy(pt->label, N_("System"));
- strcpy(pt->translation_context, BLF_I18NCONTEXT_DEFAULT_BPYRNA);
- pt->draw = file_panel_system;
- BLI_addtail(&art->paneltypes, pt);
-
- pt = MEM_callocN(sizeof(PanelType), "spacetype file system bookmarks");
- strcpy(pt->idname, "FILE_PT_system_bookmarks");
- strcpy(pt->label, N_("System Bookmarks"));
- strcpy(pt->translation_context, BLF_I18NCONTEXT_DEFAULT_BPYRNA);
- pt->draw = file_panel_system_bookmarks;
- pt->poll = file_panel_system_bookmarks_poll;
- BLI_addtail(&art->paneltypes, pt);
-
- pt = MEM_callocN(sizeof(PanelType), "spacetype file bookmarks");
- strcpy(pt->idname, "FILE_PT_bookmarks");
- strcpy(pt->label, N_("Bookmarks"));
- strcpy(pt->translation_context, BLF_I18NCONTEXT_DEFAULT_BPYRNA);
- pt->draw = file_panel_bookmarks;
- BLI_addtail(&art->paneltypes, pt);
-
- pt = MEM_callocN(sizeof(PanelType), "spacetype file recent directories");
- strcpy(pt->idname, "FILE_PT_recent");
- strcpy(pt->label, N_("Recent"));
- strcpy(pt->translation_context, BLF_I18NCONTEXT_DEFAULT_BPYRNA);
- pt->draw = file_panel_recent;
- pt->poll = file_panel_recent_poll;
- BLI_addtail(&art->paneltypes, pt);
-
pt = MEM_callocN(sizeof(PanelType), "spacetype file operator properties");
strcpy(pt->idname, "FILE_PT_operator");
strcpy(pt->label, N_("Operator"));
- strcpy(pt->translation_context, BLF_I18NCONTEXT_DEFAULT_BPYRNA);
+ strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
pt->poll = file_panel_operator_poll;
pt->draw_header = file_panel_operator_header;
pt->draw = file_panel_operator;
diff --git a/source/blender/editors/space_file/file_utils.c b/source/blender/editors/space_file/file_utils.c
new file mode 100644
index 00000000000..3c007f25da3
--- /dev/null
+++ b/source/blender/editors/space_file/file_utils.c
@@ -0,0 +1,47 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/editors/space_file/file_utils.c
+ * \ingroup spfile
+ */
+
+#include "BLI_rect.h"
+
+#include "BKE_context.h"
+
+#include "ED_screen.h"
+#include "ED_fileselect.h"
+
+#include "WM_types.h"
+
+#include "file_intern.h"
+
+
+void file_tile_boundbox(const ARegion *ar, FileLayout *layout, const int file, rcti *r_bounds)
+{
+ int xmin, ymax;
+
+ ED_fileselect_layout_tilepos(layout, file, &xmin, &ymax);
+ ymax = (int)ar->v2d.tot.ymax - ymax; /* real, view space ymax */
+ BLI_rcti_init(r_bounds, xmin, xmin + layout->tile_w + layout->tile_border_x,
+ ymax - layout->tile_h - layout->tile_border_y, ymax);
+}
diff --git a/source/blender/editors/space_file/filelist.c b/source/blender/editors/space_file/filelist.c
index 871abbda48a..0d1aff09e9c 100644
--- a/source/blender/editors/space_file/filelist.c
+++ b/source/blender/editors/space_file/filelist.c
@@ -35,19 +35,29 @@
#include <stdlib.h>
#include <math.h>
#include <string.h>
+#include <sys/stat.h>
+#include <time.h>
#ifndef WIN32
-#include <unistd.h>
+# include <unistd.h>
#else
-#include <io.h>
-#include <direct.h>
+# include <io.h>
+# include <direct.h>
#endif
#include "MEM_guardedalloc.h"
#include "BLI_blenlib.h"
+#include "BLI_fileops.h"
+#include "BLI_fileops_types.h"
+#include "BLI_fnmatch.h"
+#include "BLI_ghash.h"
+#include "BLI_hash_md5.h"
#include "BLI_linklist.h"
+#include "BLI_math.h"
+#include "BLI_stack.h"
+#include "BLI_task.h"
+#include "BLI_threads.h"
#include "BLI_utildefines.h"
-#include "BLI_fileops_types.h"
#ifdef WIN32
# include "BLI_winstuff.h"
@@ -57,15 +67,15 @@
#include "BKE_global.h"
#include "BKE_library.h"
#include "BKE_icons.h"
+#include "BKE_idcode.h"
#include "BKE_main.h"
-#include "BKE_report.h"
#include "BLO_readfile.h"
-#include "BKE_idcode.h"
#include "DNA_space_types.h"
-#include "ED_fileselect.h"
#include "ED_datafiles.h"
+#include "ED_fileselect.h"
+#include "ED_screen.h"
#include "IMB_imbuf.h"
#include "IMB_imbuf_types.h"
@@ -77,315 +87,687 @@
#include "WM_types.h"
#include "UI_resources.h"
+#include "UI_interface_icons.h"
+
+#include "atomic_ops.h"
#include "filelist.h"
-struct FileList;
-typedef struct FileImage {
- struct FileImage *next, *prev;
+/* ----------------- FOLDERLIST (previous/next) -------------- */
+
+typedef struct FolderList {
+ struct FolderList *next, *prev;
+ char *foldername;
+} FolderList;
+
+ListBase *folderlist_new(void)
+{
+ ListBase *p = MEM_callocN(sizeof(*p), __func__);
+ return p;
+}
+
+void folderlist_popdir(struct ListBase *folderlist, char *dir)
+{
+ const char *prev_dir;
+ struct FolderList *folder;
+ folder = folderlist->last;
+
+ if (folder) {
+ /* remove the current directory */
+ MEM_freeN(folder->foldername);
+ BLI_freelinkN(folderlist, folder);
+
+ folder = folderlist->last;
+ if (folder) {
+ prev_dir = folder->foldername;
+ BLI_strncpy(dir, prev_dir, FILE_MAXDIR);
+ }
+ }
+ /* delete the folder next or use setdir directly before PREVIOUS OP */
+}
+
+void folderlist_pushdir(ListBase *folderlist, const char *dir)
+{
+ struct FolderList *folder, *previous_folder;
+ previous_folder = folderlist->last;
+
+ /* check if already exists */
+ if (previous_folder && previous_folder->foldername) {
+ if (BLI_path_cmp(previous_folder->foldername, dir) == 0) {
+ return;
+ }
+ }
+
+ /* create next folder element */
+ folder = MEM_mallocN(sizeof(*folder), __func__);
+ folder->foldername = BLI_strdup(dir);
+
+ /* add it to the end of the list */
+ BLI_addtail(folderlist, folder);
+}
+
+const char *folderlist_peeklastdir(ListBase *folderlist)
+{
+ struct FolderList *folder;
+
+ if (!folderlist->last)
+ return NULL;
+
+ folder = folderlist->last;
+ return folder->foldername;
+}
+
+int folderlist_clear_next(struct SpaceFile *sfile)
+{
+ struct FolderList *folder;
+
+ /* if there is no folder_next there is nothing we can clear */
+ if (!sfile->folders_next)
+ return 0;
+
+ /* if previous_folder, next_folder or refresh_folder operators are executed it doesn't clear folder_next */
+ folder = sfile->folders_prev->last;
+ if ((!folder) || (BLI_path_cmp(folder->foldername, sfile->params->dir) == 0))
+ return 0;
+
+ /* eventually clear flist->folders_next */
+ return 1;
+}
+
+/* not listbase itself */
+void folderlist_free(ListBase *folderlist)
+{
+ if (folderlist) {
+ FolderList *folder;
+ for (folder = folderlist->first; folder; folder = folder->next)
+ MEM_freeN(folder->foldername);
+ BLI_freelistN(folderlist);
+ }
+}
+
+ListBase *folderlist_duplicate(ListBase *folderlist)
+{
+
+ if (folderlist) {
+ ListBase *folderlistn = MEM_callocN(sizeof(*folderlistn), __func__);
+ FolderList *folder;
+
+ BLI_duplicatelist(folderlistn, folderlist);
+
+ for (folder = folderlistn->first; folder; folder = folder->next) {
+ folder->foldername = MEM_dupallocN(folder->foldername);
+ }
+ return folderlistn;
+ }
+ return NULL;
+}
+
+
+/* ------------------FILELIST------------------------ */
+
+typedef struct FileListInternEntry {
+ struct FileListInternEntry *next, *prev;
+
+ char uuid[16]; /* ASSET_UUID_LENGTH */
+
+ int typeflag; /* eFileSel_File_Types */
+ int blentype; /* ID type, in case typeflag has FILE_TYPE_BLENDERLIB set. */
+
+ char *relpath;
+ char *name; /* not striclty needed, but used during sorting, avoids to have to recompute it there... */
+
+ BLI_stat_t st;
+} FileListInternEntry;
+
+typedef struct FileListIntern {
+ ListBase entries; /* FileListInternEntry items. */
+ FileListInternEntry **filtered;
+
+ char curr_uuid[16]; /* Used to generate uuid during internal listing. */
+} FileListIntern;
+
+#define FILELIST_ENTRYCACHESIZE_DEFAULT 1024 /* Keep it a power of two! */
+typedef struct FileListEntryCache {
+ size_t size; /* The size of the cache... */
+
+ int flags;
+
+ /* This one gathers all entries from both block and misc caches. Used for easy bulk-freing. */
+ ListBase cached_entries;
+
+ /* Block cache: all entries between start and end index. used for part of the list on diplay. */
+ FileDirEntry **block_entries;
+ int block_start_index, block_end_index, block_center_index, block_cursor;
+
+ /* Misc cache: random indices, FIFO behavior.
+ * Note: Not 100% sure we actually need that, time will say. */
+ int misc_cursor;
+ int *misc_entries_indices;
+ GHash *misc_entries;
+
+ /* Allows to quickly get a cached entry from its UUID. */
+ GHash *uuids;
+
+ /* Previews handling. */
+ TaskScheduler *previews_scheduler;
+ TaskPool *previews_pool;
+ ThreadQueue *previews_todo;
+ ThreadQueue *previews_done;
+ double previews_timestamp;
+ int previews_pending;
+} FileListEntryCache;
+
+/* FileListCache.flags */
+enum {
+ FLC_IS_INIT = 1 << 0,
+ FLC_PREVIEWS_ACTIVE = 1 << 1,
+};
+
+typedef struct FileListEntryPreview {
char path[FILE_MAX];
unsigned int flags;
int index;
- short done;
ImBuf *img;
-} FileImage;
+} FileListEntryPreview;
-typedef struct ThumbnailJob {
- ListBase loadimages;
- const short *stop;
- const short *do_update;
- struct FileList *filelist;
- ReportList reports;
-} ThumbnailJob;
+typedef struct FileListFilter {
+ unsigned int filter;
+ unsigned int filter_id;
+ char filter_glob[64];
+ char filter_search[66]; /* + 2 for heading/trailing implicit '*' wildcards. */
+ short flags;
+} FileListFilter;
+
+/* FileListFilter.flags */
+enum {
+ FLF_HIDE_DOT = 1 << 0,
+ FLF_HIDE_PARENT = 1 << 1,
+ FLF_HIDE_LIB_DIR = 1 << 2,
+};
typedef struct FileList {
- struct direntry *filelist;
- int *fidx;
- int numfiles;
- int numfiltered;
- char dir[FILE_MAX];
+ FileDirEntryArr filelist;
+
short prv_w;
short prv_h;
- short hide_dot;
- unsigned int filter;
- char filter_glob[64];
- short changed;
+
+ short flags;
+
+ short sort;
+
+ FileListFilter filter_data;
+
+ struct FileListIntern filelist_intern;
+
+ struct FileListEntryCache filelist_cache;
+
+ /* We need to keep those info outside of actual filelist items, because those are no more persistent
+ * (only generated on demand, and freed as soon as possible).
+ * Persistent part (mere list of paths + stat info) is kept as small as possible, and filebrowser-agnostic.
+ */
+ GHash *selection_state;
+
+ short max_recursion;
+ short recursion_level;
struct BlendHandle *libfiledata;
- short hide_parent;
- void (*readf)(struct FileList *);
- bool (*filterf)(struct direntry *file, const char *dir, unsigned int filter, short hide_dot);
+ /* Set given path as root directory, may change given string in place to a valid value. */
+ void (*checkdirf)(struct FileList *, char *);
+
+ /* Fill filelist (to be called by read job). */
+ void (*read_jobf)(struct FileList *, const char *, short *, short *, float *, ThreadMutex *);
+ /* Filter an entry of current filelist. */
+ bool (*filterf)(struct FileListInternEntry *, const char *, FileListFilter *);
} FileList;
-typedef struct FolderList {
- struct FolderList *next, *prev;
- char *foldername;
-} FolderList;
+/* FileList.flags */
+enum {
+ FL_FORCE_RESET = 1 << 0,
+ FL_IS_READY = 1 << 1,
+ FL_IS_PENDING = 1 << 2,
+ FL_NEED_SORTING = 1 << 3,
+ FL_NEED_FILTERING = 1 << 4,
+};
#define SPECIAL_IMG_SIZE 48
#define SPECIAL_IMG_ROWS 4
#define SPECIAL_IMG_COLS 4
-#define SPECIAL_IMG_FOLDER 0
-#define SPECIAL_IMG_PARENT 1
-#define SPECIAL_IMG_REFRESH 2
-#define SPECIAL_IMG_BLENDFILE 3
-#define SPECIAL_IMG_SOUNDFILE 4
-#define SPECIAL_IMG_MOVIEFILE 5
-#define SPECIAL_IMG_PYTHONFILE 6
-#define SPECIAL_IMG_TEXTFILE 7
-#define SPECIAL_IMG_FONTFILE 8
-#define SPECIAL_IMG_UNKNOWNFILE 9
-#define SPECIAL_IMG_LOADING 10
-#define SPECIAL_IMG_BACKUP 11
-#define SPECIAL_IMG_MAX SPECIAL_IMG_BACKUP + 1
+enum {
+ SPECIAL_IMG_FOLDER = 0,
+ SPECIAL_IMG_PARENT = 1,
+ SPECIAL_IMG_REFRESH = 2,
+ SPECIAL_IMG_BLENDFILE = 3,
+ SPECIAL_IMG_SOUNDFILE = 4,
+ SPECIAL_IMG_MOVIEFILE = 5,
+ SPECIAL_IMG_PYTHONFILE = 6,
+ SPECIAL_IMG_TEXTFILE = 7,
+ SPECIAL_IMG_FONTFILE = 8,
+ SPECIAL_IMG_UNKNOWNFILE = 9,
+ SPECIAL_IMG_LOADING = 10,
+ SPECIAL_IMG_BACKUP = 11,
+ SPECIAL_IMG_MAX
+};
static ImBuf *gSpecialFileImages[SPECIAL_IMG_MAX];
-/* ******************* SORT ******************* */
+static void filelist_readjob_main(struct FileList *, const char *, short *, short *, float *, ThreadMutex *);
+static void filelist_readjob_lib(struct FileList *, const char *, short *, short *, float *, ThreadMutex *);
+static void filelist_readjob_dir(struct FileList *, const char *, short *, short *, float *, ThreadMutex *);
-static bool compare_is_directory(const struct direntry *entry)
-{
- /* for library browse .blend files may be treated as directories, but
- * for sorting purposes they should be considered regular files */
- if (S_ISDIR(entry->type))
- return !(entry->flags & (BLENDERFILE | BLENDERFILE_BACKUP));
-
- return false;
-}
+/* helper, could probably go in BKE actually? */
+static int groupname_to_code(const char *group);
+static unsigned int groupname_to_filter_id(const char *group);
-static int compare_name(const void *a1, const void *a2)
-{
- const struct direntry *entry1 = a1, *entry2 = a2;
+static void filelist_filter_clear(FileList *filelist);
+static void filelist_cache_clear(FileListEntryCache *cache, size_t new_size);
+/* ********** Sort helpers ********** */
+
+static int compare_direntry_generic(const FileListInternEntry *entry1, const FileListInternEntry *entry2)
+{
/* type is equal to stat.st_mode */
- if (compare_is_directory(entry1)) {
- if (compare_is_directory(entry2) == 0) return (-1);
- }
- else {
- if (compare_is_directory(entry2)) return (1);
- }
- if (S_ISREG(entry1->type)) {
- if (S_ISREG(entry2->type) == 0) return (-1);
+ if (entry1->typeflag & FILE_TYPE_DIR) {
+ if (entry2->typeflag & FILE_TYPE_DIR) {
+ /* If both entries are tagged as dirs, we make a 'sub filter' that shows first the real dirs,
+ * then libs (.blend files), then categories in libs. */
+ if (entry1->typeflag & FILE_TYPE_BLENDERLIB) {
+ if (!(entry2->typeflag & FILE_TYPE_BLENDERLIB)) {
+ return 1;
+ }
+ }
+ else if (entry2->typeflag & FILE_TYPE_BLENDERLIB) {
+ return -1;
+ }
+ else if (entry1->typeflag & (FILE_TYPE_BLENDER | FILE_TYPE_BLENDER_BACKUP)) {
+ if (!(entry2->typeflag & (FILE_TYPE_BLENDER | FILE_TYPE_BLENDER_BACKUP))) {
+ return 1;
+ }
+ }
+ else if (entry2->typeflag & (FILE_TYPE_BLENDER | FILE_TYPE_BLENDER_BACKUP)) {
+ return -1;
+ }
+ }
+ else {
+ return -1;
+ }
}
- else {
- if (S_ISREG(entry2->type)) return (1);
+ else if (entry2->typeflag & FILE_TYPE_DIR) {
+ return 1;
}
- if ((entry1->type & S_IFMT) < (entry2->type & S_IFMT)) return (-1);
- if ((entry1->type & S_IFMT) > (entry2->type & S_IFMT)) return (1);
-
+
/* make sure "." and ".." are always first */
- if (strcmp(entry1->relname, ".") == 0) return (-1);
- if (strcmp(entry2->relname, ".") == 0) return (1);
- if (strcmp(entry1->relname, "..") == 0) return (-1);
- if (strcmp(entry2->relname, "..") == 0) return (1);
+ if (FILENAME_IS_CURRENT(entry1->relpath)) return -1;
+ if (FILENAME_IS_CURRENT(entry2->relpath)) return 1;
+ if (FILENAME_IS_PARENT(entry1->relpath)) return -1;
+ if (FILENAME_IS_PARENT(entry2->relpath)) return 1;
- return (BLI_natstrcmp(entry1->relname, entry2->relname));
+ return 0;
}
-static int compare_date(const void *a1, const void *a2)
+static int compare_name(void *UNUSED(user_data), const void *a1, const void *a2)
{
- const struct direntry *entry1 = a1, *entry2 = a2;
-
- /* type is equal to stat.st_mode */
+ const FileListInternEntry *entry1 = a1;
+ const FileListInternEntry *entry2 = a2;
+ char *name1, *name2;
+ int ret;
- if (compare_is_directory(entry1)) {
- if (compare_is_directory(entry2) == 0) return (-1);
+ if ((ret = compare_direntry_generic(entry1, entry2))) {
+ return ret;
}
- else {
- if (compare_is_directory(entry2)) return (1);
- }
- if (S_ISREG(entry1->type)) {
- if (S_ISREG(entry2->type) == 0) return (-1);
- }
- else {
- if (S_ISREG(entry2->type)) return (1);
- }
- if ((entry1->type & S_IFMT) < (entry2->type & S_IFMT)) return (-1);
- if ((entry1->type & S_IFMT) > (entry2->type & S_IFMT)) return (1);
- /* make sure "." and ".." are always first */
- if (strcmp(entry1->relname, ".") == 0) return (-1);
- if (strcmp(entry2->relname, ".") == 0) return (1);
- if (strcmp(entry1->relname, "..") == 0) return (-1);
- if (strcmp(entry2->relname, "..") == 0) return (1);
-
- if (entry1->s.st_mtime < entry2->s.st_mtime) return 1;
- if (entry1->s.st_mtime > entry2->s.st_mtime) return -1;
-
- else return BLI_natstrcmp(entry1->relname, entry2->relname);
+ name1 = entry1->name;
+ name2 = entry2->name;
+
+ return BLI_natstrcmp(name1, name2);
}
-static int compare_size(const void *a1, const void *a2)
+static int compare_date(void *UNUSED(user_data), const void *a1, const void *a2)
{
- const struct direntry *entry1 = a1, *entry2 = a2;
-
- /* type is equal to stat.st_mode */
+ const FileListInternEntry *entry1 = a1;
+ const FileListInternEntry *entry2 = a2;
+ char *name1, *name2;
+ int64_t time1, time2;
+ int ret;
- if (compare_is_directory(entry1)) {
- if (compare_is_directory(entry2) == 0) return (-1);
- }
- else {
- if (compare_is_directory(entry2)) return (1);
- }
- if (S_ISREG(entry1->type)) {
- if (S_ISREG(entry2->type) == 0) return (-1);
- }
- else {
- if (S_ISREG(entry2->type)) return (1);
+ if ((ret = compare_direntry_generic(entry1, entry2))) {
+ return ret;
}
- if ((entry1->type & S_IFMT) < (entry2->type & S_IFMT)) return (-1);
- if ((entry1->type & S_IFMT) > (entry2->type & S_IFMT)) return (1);
-
- /* make sure "." and ".." are always first */
- if (strcmp(entry1->relname, ".") == 0) return (-1);
- if (strcmp(entry2->relname, ".") == 0) return (1);
- if (strcmp(entry1->relname, "..") == 0) return (-1);
- if (strcmp(entry2->relname, "..") == 0) return (1);
- if (entry1->s.st_size < entry2->s.st_size) return 1;
- if (entry1->s.st_size > entry2->s.st_size) return -1;
- else return BLI_natstrcmp(entry1->relname, entry2->relname);
+ time1 = (int64_t)entry1->st.st_mtime;
+ time2 = (int64_t)entry2->st.st_mtime;
+ if (time1 < time2) return 1;
+ if (time1 > time2) return -1;
+
+ name1 = entry1->name;
+ name2 = entry2->name;
+
+ return BLI_natstrcmp(name1, name2);
}
-static int compare_extension(const void *a1, const void *a2)
+static int compare_size(void *UNUSED(user_data), const void *a1, const void *a2)
{
- const struct direntry *entry1 = a1, *entry2 = a2;
- const char *sufix1, *sufix2;
- const char *nil = "";
+ const FileListInternEntry *entry1 = a1;
+ const FileListInternEntry *entry2 = a2;
+ char *name1, *name2;
+ uint64_t size1, size2;
+ int ret;
- if (!(sufix1 = strstr(entry1->relname, ".blend.gz")))
- sufix1 = strrchr(entry1->relname, '.');
- if (!(sufix2 = strstr(entry2->relname, ".blend.gz")))
- sufix2 = strrchr(entry2->relname, '.');
- if (!sufix1) sufix1 = nil;
- if (!sufix2) sufix2 = nil;
+ if ((ret = compare_direntry_generic(entry1, entry2))) {
+ return ret;
+ }
+
+ size1 = entry1->st.st_size;
+ size2 = entry2->st.st_size;
+ if (size1 < size2) return 1;
+ if (size1 > size2) return -1;
- /* type is equal to stat.st_mode */
+ name1 = entry1->name;
+ name2 = entry2->name;
- if (compare_is_directory(entry1)) {
- if (compare_is_directory(entry2) == 0) return (-1);
+ return BLI_natstrcmp(name1, name2);
+}
+
+static int compare_extension(void *UNUSED(user_data), const void *a1, const void *a2)
+{
+ const FileListInternEntry *entry1 = a1;
+ const FileListInternEntry *entry2 = a2;
+ char *name1, *name2;
+ int ret;
+
+ if ((ret = compare_direntry_generic(entry1, entry2))) {
+ return ret;
+ }
+
+ if ((entry1->typeflag & FILE_TYPE_BLENDERLIB) && !(entry2->typeflag & FILE_TYPE_BLENDERLIB)) return -1;
+ if (!(entry1->typeflag & FILE_TYPE_BLENDERLIB) && (entry2->typeflag & FILE_TYPE_BLENDERLIB)) return 1;
+ if ((entry1->typeflag & FILE_TYPE_BLENDERLIB) && (entry2->typeflag & FILE_TYPE_BLENDERLIB)) {
+ if ((entry1->typeflag & FILE_TYPE_DIR) && !(entry2->typeflag & FILE_TYPE_DIR)) return 1;
+ if (!(entry1->typeflag & FILE_TYPE_DIR) && (entry2->typeflag & FILE_TYPE_DIR)) return -1;
+ if (entry1->blentype < entry2->blentype) return -1;
+ if (entry1->blentype > entry2->blentype) return 1;
}
else {
- if (compare_is_directory(entry2)) return (1);
+ const char *sufix1, *sufix2;
+
+ if (!(sufix1 = strstr(entry1->relpath, ".blend.gz")))
+ sufix1 = strrchr(entry1->relpath, '.');
+ if (!(sufix2 = strstr(entry2->relpath, ".blend.gz")))
+ sufix2 = strrchr(entry2->relpath, '.');
+ if (!sufix1) sufix1 = "";
+ if (!sufix2) sufix2 = "";
+
+ if ((ret = BLI_strcasecmp(sufix1, sufix2))) {
+ return ret;
+ }
}
- if (S_ISREG(entry1->type)) {
- if (S_ISREG(entry2->type) == 0) return (-1);
+
+ name1 = entry1->name;
+ name2 = entry2->name;
+
+ return BLI_natstrcmp(name1, name2);
+}
+
+void filelist_sort(struct FileList *filelist)
+{
+ if ((filelist->flags & FL_NEED_SORTING) && (filelist->sort != FILE_SORT_NONE)) {
+ switch (filelist->sort) {
+ case FILE_SORT_ALPHA:
+ BLI_listbase_sort_r(&filelist->filelist_intern.entries, compare_name, NULL);
+ break;
+ case FILE_SORT_TIME:
+ BLI_listbase_sort_r(&filelist->filelist_intern.entries, compare_date, NULL);
+ break;
+ case FILE_SORT_SIZE:
+ BLI_listbase_sort_r(&filelist->filelist_intern.entries, compare_size, NULL);
+ break;
+ case FILE_SORT_EXTENSION:
+ BLI_listbase_sort_r(&filelist->filelist_intern.entries, compare_extension, NULL);
+ break;
+ case FILE_SORT_NONE: /* Should never reach this point! */
+ default:
+ BLI_assert(0);
+ }
+
+ filelist_filter_clear(filelist);
+ filelist->flags &= ~FL_NEED_SORTING;
}
- else {
- if (S_ISREG(entry2->type)) return (1);
+}
+
+void filelist_setsorting(struct FileList *filelist, const short sort)
+{
+ if (filelist->sort != sort) {
+ filelist->sort = sort;
+ filelist->flags |= FL_NEED_SORTING;
}
- if ((entry1->type & S_IFMT) < (entry2->type & S_IFMT)) return (-1);
- if ((entry1->type & S_IFMT) > (entry2->type & S_IFMT)) return (1);
-
- /* make sure "." and ".." are always first */
- if (strcmp(entry1->relname, ".") == 0) return (-1);
- if (strcmp(entry2->relname, ".") == 0) return (1);
- if (strcmp(entry1->relname, "..") == 0) return (-1);
- if (strcmp(entry2->relname, "..") == 0) return (1);
-
- return (BLI_strcasecmp(sufix1, sufix2));
}
-static bool is_hidden_file(const char *filename, short hide_dot)
+/* ********** Filter helpers ********** */
+
+static bool is_hidden_file(const char *filename, FileListFilter *filter)
{
+ char *sep = (char *)BLI_last_slash(filename);
bool is_hidden = false;
- if (hide_dot) {
- if (filename[0] == '.' && filename[1] != '.' && filename[1] != 0) {
- is_hidden = 1; /* ignore .file */
- }
- else if (((filename[0] == '.') && (filename[1] == 0))) {
- is_hidden = 1; /* ignore . */
+ if (filter->flags & FLF_HIDE_DOT) {
+ if (filename[0] == '.' && filename[1] != '.' && filename[1] != '\0') {
+ is_hidden = true; /* ignore .file */
}
else {
int len = strlen(filename);
if ((len > 0) && (filename[len - 1] == '~')) {
- is_hidden = 1; /* ignore file~ */
+ is_hidden = true; /* ignore file~ */
}
}
}
- else {
- if (((filename[0] == '.') && (filename[1] == 0))) {
- is_hidden = 1; /* ignore . */
+ if (!is_hidden && (filter->flags & FLF_HIDE_PARENT)) {
+ if (filename[0] == '.' && filename[1] == '.' && filename[2] == '\0') {
+ is_hidden = true; /* ignore .. */
+ }
+ }
+ if (!is_hidden && ((filename[0] == '.') && (filename[1] == '\0'))) {
+ is_hidden = true; /* ignore . */
+ }
+ /* filename might actually be a piece of path, in which case we have to check all its parts. */
+ if (!is_hidden && sep) {
+ char tmp_filename[FILE_MAX_LIBEXTRA];
+
+ BLI_strncpy(tmp_filename, filename, sizeof(tmp_filename));
+ sep = tmp_filename + (sep - filename);
+ while (sep) {
+ BLI_assert(sep[1] != '\0');
+ if (is_hidden_file(sep + 1, filter)) {
+ is_hidden = true;
+ break;
+ }
+ *sep = '\0';
+ sep = (char *)BLI_last_slash(tmp_filename);
}
}
return is_hidden;
}
-static bool is_filtered_file(struct direntry *file, const char *UNUSED(dir), unsigned int filter, short hide_dot)
+static bool is_filtered_file(FileListInternEntry *file, const char *UNUSED(root), FileListFilter *filter)
{
- bool is_filtered = false;
- if (filter) {
- if (file->flags & filter) {
- is_filtered = 1;
+ bool is_filtered = !is_hidden_file(file->relpath, filter);
+
+ if (is_filtered && filter->filter && !FILENAME_IS_CURRPAR(file->relpath)) {
+ if (file->typeflag & FILE_TYPE_DIR) {
+ if (file->typeflag & (FILE_TYPE_BLENDERLIB | FILE_TYPE_BLENDER | FILE_TYPE_BLENDER_BACKUP)) {
+ if (!(filter->filter & (FILE_TYPE_BLENDER | FILE_TYPE_BLENDER_BACKUP))) {
+ is_filtered = false;
+ }
+ }
+ else {
+ if (!(filter->filter & FILE_TYPE_FOLDER)) {
+ is_filtered = false;
+ }
+ }
}
- else if (file->type & S_IFDIR) {
- if (filter & FOLDERFILE) {
- is_filtered = 1;
+ else {
+ if (!(file->typeflag & filter->filter)) {
+ is_filtered = false;
+ }
+ }
+ if (is_filtered && (filter->filter_search[0] != '\0')) {
+ if (fnmatch(filter->filter_search, file->relpath, FNM_CASEFOLD) != 0) {
+ is_filtered = false;
}
}
}
- else {
- is_filtered = 1;
- }
- return is_filtered && !is_hidden_file(file->relname, hide_dot);
+
+ return is_filtered;
}
-static bool is_filtered_lib(struct direntry *file, const char *dir, unsigned int filter, short hide_dot)
+static bool is_filtered_lib(FileListInternEntry *file, const char *root, FileListFilter *filter)
{
- bool is_filtered = false;
- char tdir[FILE_MAX], tgroup[BLO_GROUP_MAX];
- if (BLO_is_a_library(dir, tdir, tgroup)) {
- is_filtered = !is_hidden_file(file->relname, hide_dot);
+ bool is_filtered;
+ char path[FILE_MAX_LIBEXTRA], dir[FILE_MAXDIR], *group, *name;
+
+ BLI_join_dirfile(path, sizeof(path), root, file->relpath);
+
+ if (BLO_library_path_explode(path, dir, &group, &name)) {
+ is_filtered = !is_hidden_file(file->relpath, filter);
+ if (is_filtered && filter->filter && !FILENAME_IS_CURRPAR(file->relpath)) {
+ if (file->typeflag & FILE_TYPE_DIR) {
+ if (file->typeflag & (FILE_TYPE_BLENDERLIB | FILE_TYPE_BLENDER | FILE_TYPE_BLENDER_BACKUP)) {
+ if (!(filter->filter & (FILE_TYPE_BLENDER | FILE_TYPE_BLENDER_BACKUP))) {
+ is_filtered = false;
+ }
+ }
+ else {
+ if (!(filter->filter & FILE_TYPE_FOLDER)) {
+ is_filtered = false;
+ }
+ }
+ }
+ if (is_filtered && group) {
+ if (!name && (filter->flags & FLF_HIDE_LIB_DIR)) {
+ is_filtered = false;
+ }
+ else {
+ unsigned int filter_id = groupname_to_filter_id(group);
+ if (!(filter_id & filter->filter_id)) {
+ is_filtered = false;
+ }
+ }
+ }
+ if (is_filtered && (filter->filter_search[0] != '\0')) {
+ if (fnmatch(filter->filter_search, file->relpath, FNM_CASEFOLD) != 0) {
+ is_filtered = false;
+ }
+ }
+ }
}
else {
- is_filtered = is_filtered_file(file, dir, filter, hide_dot);
+ is_filtered = is_filtered_file(file, root, filter);
}
+
return is_filtered;
}
-static bool is_filtered_main(struct direntry *file, const char *UNUSED(dir), unsigned int UNUSED(filter), short hide_dot)
+static bool is_filtered_main(FileListInternEntry *file, const char *UNUSED(dir), FileListFilter *filter)
+{
+ return !is_hidden_file(file->relpath, filter);
+}
+
+static void filelist_filter_clear(FileList *filelist)
{
- return !is_hidden_file(file->relname, hide_dot);
+ filelist->flags |= FL_NEED_FILTERING;
}
void filelist_filter(FileList *filelist)
{
int num_filtered = 0;
- int i, j;
+ const int num_files = filelist->filelist.nbr_entries;
+ FileListInternEntry **filtered_tmp, *file;
- if (!filelist->filelist)
+ if (filelist->filelist.nbr_entries == 0) {
return;
+ }
- /* How many files are left after filter ? */
- for (i = 0; i < filelist->numfiles; ++i) {
- struct direntry *file = &filelist->filelist[i];
- if (filelist->filterf(file, filelist->dir, filelist->filter, filelist->hide_dot)) {
- num_filtered++;
- }
+ if (!(filelist->flags & FL_NEED_FILTERING)) {
+ /* Assume it has already been filtered, nothing else to do! */
+ return;
}
-
- if (filelist->fidx) {
- MEM_freeN(filelist->fidx);
- filelist->fidx = NULL;
+
+ filelist->filter_data.flags &= ~FLF_HIDE_LIB_DIR;
+ if (filelist->max_recursion) {
+ /* Never show lib ID 'categories' directories when we are in 'flat' mode, unless
+ * root path is a blend file. */
+ char dir[FILE_MAXDIR];
+ if (!filelist_islibrary(filelist, dir, NULL)) {
+ filelist->filter_data.flags |= FLF_HIDE_LIB_DIR;
+ }
}
- filelist->fidx = (int *)MEM_callocN(num_filtered * sizeof(int), "filteridx");
- filelist->numfiltered = num_filtered;
- for (i = 0, j = 0; i < filelist->numfiles; ++i) {
- struct direntry *file = &filelist->filelist[i];
- if (filelist->filterf(file, filelist->dir, filelist->filter, filelist->hide_dot)) {
- filelist->fidx[j++] = i;
+ filtered_tmp = MEM_mallocN(sizeof(*filtered_tmp) * (size_t)num_files, __func__);
+
+ /* Filter remap & count how many files are left after filter in a single loop. */
+ for (file = filelist->filelist_intern.entries.first; file; file = file->next) {
+ if (filelist->filterf(file, filelist->filelist.root, &filelist->filter_data)) {
+ filtered_tmp[num_filtered++] = file;
}
}
+
+ if (filelist->filelist_intern.filtered) {
+ MEM_freeN(filelist->filelist_intern.filtered);
+ }
+ filelist->filelist_intern.filtered = MEM_mallocN(sizeof(*filelist->filelist_intern.filtered) * (size_t)num_filtered,
+ __func__);
+ memcpy(filelist->filelist_intern.filtered, filtered_tmp,
+ sizeof(*filelist->filelist_intern.filtered) * (size_t)num_filtered);
+ filelist->filelist.nbr_entries_filtered = num_filtered;
+// printf("Filetered: %d over %d entries\n", num_filtered, filelist->filelist.nbr_entries);
+
+ filelist_cache_clear(&filelist->filelist_cache, filelist->filelist_cache.size);
+ filelist->flags &= ~FL_NEED_FILTERING;
+
+ MEM_freeN(filtered_tmp);
}
+void filelist_setfilter_options(FileList *filelist, const bool hide_dot, const bool hide_parent,
+ const unsigned int filter, const unsigned int filter_id,
+ const char *filter_glob, const char *filter_search)
+{
+ bool update = false;
+
+ if (((filelist->filter_data.flags & FLF_HIDE_DOT) != 0) != (hide_dot != 0)) {
+ filelist->filter_data.flags ^= FLF_HIDE_DOT;
+ update = true;
+ }
+ if (((filelist->filter_data.flags & FLF_HIDE_PARENT) != 0) != (hide_parent != 0)) {
+ filelist->filter_data.flags ^= FLF_HIDE_PARENT;
+ update = true;
+ }
+ if ((filelist->filter_data.filter != filter) || (filelist->filter_data.filter_id != filter_id)) {
+ filelist->filter_data.filter = filter;
+ filelist->filter_data.filter_id = filter_id;
+ update = true;
+ }
+ if (!STREQ(filelist->filter_data.filter_glob, filter_glob)) {
+ BLI_strncpy(filelist->filter_data.filter_glob, filter_glob, sizeof(filelist->filter_data.filter_glob));
+ update = true;
+ }
+ if ((BLI_strcmp_ignore_pad(filelist->filter_data.filter_search, filter_search, '*') != 0)) {
+ BLI_strncpy_ensure_pad(filelist->filter_data.filter_search, filter_search, '*',
+ sizeof(filelist->filter_data.filter_search));
+ update = true;
+ }
+
+ if (update) {
+ /* And now, free filtered data so that we know we have to filter again. */
+ filelist_filter_clear(filelist);
+ }
+}
+
+/* ********** Icon/image helpers ********** */
+
void filelist_init_icons(void)
{
short x, y, k;
@@ -428,136 +810,517 @@ void filelist_free_icons(void)
}
}
-/* -----------------FOLDERLIST (previous/next) -------------- */
-ListBase *folderlist_new(void)
+void filelist_imgsize(struct FileList *filelist, short w, short h)
{
- ListBase *p = MEM_callocN(sizeof(ListBase), "folderlist");
- return p;
+ filelist->prv_w = w;
+ filelist->prv_h = h;
}
-void folderlist_popdir(struct ListBase *folderlist, char *dir)
+static FileDirEntry *filelist_geticon_get_file(struct FileList *filelist, const int index)
{
- const char *prev_dir;
- struct FolderList *folder;
- folder = folderlist->last;
+ BLI_assert(G.background == false);
- if (folder) {
- /* remove the current directory */
- MEM_freeN(folder->foldername);
- BLI_freelinkN(folderlist, folder);
+ return filelist_file(filelist, index);
+}
- folder = folderlist->last;
- if (folder) {
- prev_dir = folder->foldername;
- BLI_strncpy(dir, prev_dir, FILE_MAXDIR);
+ImBuf *filelist_getimage(struct FileList *filelist, const int index)
+{
+ FileDirEntry *file = filelist_geticon_get_file(filelist, index);
+
+ return file->image;
+}
+
+static ImBuf *filelist_geticon_image_ex(const unsigned int typeflag, const char *relpath)
+{
+ ImBuf *ibuf = NULL;
+
+ if (typeflag & FILE_TYPE_DIR) {
+ if (FILENAME_IS_PARENT(relpath)) {
+ ibuf = gSpecialFileImages[SPECIAL_IMG_PARENT];
+ }
+ else if (FILENAME_IS_CURRENT(relpath)) {
+ ibuf = gSpecialFileImages[SPECIAL_IMG_REFRESH];
+ }
+ else {
+ ibuf = gSpecialFileImages[SPECIAL_IMG_FOLDER];
}
}
- /* delete the folder next or use setdir directly before PREVIOUS OP */
+ else if (typeflag & FILE_TYPE_BLENDER) {
+ ibuf = gSpecialFileImages[SPECIAL_IMG_BLENDFILE];
+ }
+ else if (typeflag & FILE_TYPE_BLENDERLIB) {
+ ibuf = gSpecialFileImages[SPECIAL_IMG_UNKNOWNFILE];
+ }
+ else if (typeflag & (FILE_TYPE_MOVIE)) {
+ ibuf = gSpecialFileImages[SPECIAL_IMG_MOVIEFILE];
+ }
+ else if (typeflag & FILE_TYPE_SOUND) {
+ ibuf = gSpecialFileImages[SPECIAL_IMG_SOUNDFILE];
+ }
+ else if (typeflag & FILE_TYPE_PYSCRIPT) {
+ ibuf = gSpecialFileImages[SPECIAL_IMG_PYTHONFILE];
+ }
+ else if (typeflag & FILE_TYPE_FTFONT) {
+ ibuf = gSpecialFileImages[SPECIAL_IMG_FONTFILE];
+ }
+ else if (typeflag & FILE_TYPE_TEXT) {
+ ibuf = gSpecialFileImages[SPECIAL_IMG_TEXTFILE];
+ }
+ else if (typeflag & FILE_TYPE_IMAGE) {
+ ibuf = gSpecialFileImages[SPECIAL_IMG_LOADING];
+ }
+ else if (typeflag & FILE_TYPE_BLENDER_BACKUP) {
+ ibuf = gSpecialFileImages[SPECIAL_IMG_BACKUP];
+ }
+ else {
+ ibuf = gSpecialFileImages[SPECIAL_IMG_UNKNOWNFILE];
+ }
+
+ return ibuf;
}
-void folderlist_pushdir(ListBase *folderlist, const char *dir)
+ImBuf *filelist_geticon_image(struct FileList *filelist, const int index)
{
- struct FolderList *folder, *previous_folder;
- previous_folder = folderlist->last;
+ FileDirEntry *file = filelist_geticon_get_file(filelist, index);
- /* check if already exists */
- if (previous_folder && previous_folder->foldername) {
- if (BLI_path_cmp(previous_folder->foldername, dir) == 0) {
- return;
+ return filelist_geticon_image_ex(file->typeflag, file->relpath);
+}
+
+static int filelist_geticon_ex(
+ const int typeflag, const int blentype, const char *relpath, const bool is_main, const bool ignore_libdir)
+{
+ if ((typeflag & FILE_TYPE_DIR) && !(ignore_libdir && (typeflag & (FILE_TYPE_BLENDERLIB | FILE_TYPE_BLENDER)))) {
+ if (FILENAME_IS_PARENT(relpath)) {
+ return is_main ? ICON_FILE_PARENT : ICON_NONE;
+ }
+ else if (typeflag & FILE_TYPE_APPLICATIONBUNDLE) {
+ return ICON_UGLYPACKAGE;
+ }
+ else if (typeflag & FILE_TYPE_BLENDER) {
+ return ICON_FILE_BLEND;
+ }
+ else if (is_main) {
+ /* Do not return icon for folders if icons are not 'main' draw type (e.g. when used over previews). */
+ return ICON_FILE_FOLDER;
}
}
- /* create next folder element */
- folder = (FolderList *)MEM_mallocN(sizeof(FolderList), "FolderList");
- folder->foldername = BLI_strdup(dir);
+ if (typeflag & FILE_TYPE_BLENDER)
+ return ICON_FILE_BLEND;
+ else if (typeflag & FILE_TYPE_BLENDER_BACKUP)
+ return ICON_FILE_BACKUP;
+ else if (typeflag & FILE_TYPE_IMAGE)
+ return ICON_FILE_IMAGE;
+ else if (typeflag & FILE_TYPE_MOVIE)
+ return ICON_FILE_MOVIE;
+ else if (typeflag & FILE_TYPE_PYSCRIPT)
+ return ICON_FILE_SCRIPT;
+ else if (typeflag & FILE_TYPE_SOUND)
+ return ICON_FILE_SOUND;
+ else if (typeflag & FILE_TYPE_FTFONT)
+ return ICON_FILE_FONT;
+ else if (typeflag & FILE_TYPE_BTX)
+ return ICON_FILE_BLANK;
+ else if (typeflag & FILE_TYPE_COLLADA)
+ return ICON_FILE_BLANK;
+ else if (typeflag & FILE_TYPE_TEXT)
+ return ICON_FILE_TEXT;
+ else if (typeflag & FILE_TYPE_BLENDERLIB) {
+ const int ret = UI_idcode_icon_get(blentype);
+ if (ret != ICON_NONE) {
+ return ret;
+ }
+ }
+ return is_main ? ICON_FILE_BLANK : ICON_NONE;
+}
- /* add it to the end of the list */
- BLI_addtail(folderlist, folder);
+int filelist_geticon(struct FileList *filelist, const int index, const bool is_main)
+{
+ FileDirEntry *file = filelist_geticon_get_file(filelist, index);
+
+ return filelist_geticon_ex(file->typeflag, file->blentype, file->relpath, is_main, false);
}
-const char *folderlist_peeklastdir(ListBase *folderlist)
+/* ********** Main ********** */
+
+static void filelist_checkdir_dir(struct FileList *UNUSED(filelist), char *r_dir)
{
- struct FolderList *folder;
+ BLI_make_exist(r_dir);
+}
- if (!folderlist->last)
- return NULL;
+static void filelist_checkdir_lib(struct FileList *UNUSED(filelist), char *r_dir)
+{
+ char dir[FILE_MAXDIR];
+ if (!BLO_library_path_explode(r_dir, dir, NULL, NULL)) {
+ /* if not a valid library, we need it to be a valid directory! */
+ BLI_make_exist(r_dir);
+ }
+}
- folder = folderlist->last;
- return folder->foldername;
+static void filelist_checkdir_main(struct FileList *filelist, char *r_dir)
+{
+ /* TODO */
+ filelist_checkdir_lib(filelist, r_dir);
}
-int folderlist_clear_next(struct SpaceFile *sfile)
+static void filelist_entry_clear(FileDirEntry *entry)
{
- struct FolderList *folder;
+ if (entry->name) {
+ MEM_freeN(entry->name);
+ }
+ if (entry->description) {
+ MEM_freeN(entry->description);
+ }
+ if (entry->relpath) {
+ MEM_freeN(entry->relpath);
+ }
+ if (entry->image) {
+ IMB_freeImBuf(entry->image);
+ }
+ /* For now, consider FileDirEntryRevision::poin as not owned here, so no need to do anything about it */
- /* if there is no folder_next there is nothing we can clear */
- if (!sfile->folders_next)
- return 0;
+ if (!BLI_listbase_is_empty(&entry->variants)) {
+ FileDirEntryVariant *var;
- /* if previous_folder, next_folder or refresh_folder operators are executed it doesn't clear folder_next */
- folder = sfile->folders_prev->last;
- if ((!folder) || (BLI_path_cmp(folder->foldername, sfile->params->dir) == 0))
- return 0;
+ for (var = entry->variants.first; var; var = var->next) {
+ if (var->name) {
+ MEM_freeN(var->name);
+ }
+ if (var->description) {
+ MEM_freeN(var->description);
+ }
- /* eventually clear flist->folders_next */
- return 1;
+ if (!BLI_listbase_is_empty(&var->revisions)) {
+ FileDirEntryRevision *rev;
+
+ for (rev = var->revisions.first; rev; rev = rev->next) {
+ if (rev->comment) {
+ MEM_freeN(rev->comment);
+ }
+ }
+
+ BLI_freelistN(&var->revisions);
+ }
+ }
+
+ /* TODO: tags! */
+
+ BLI_freelistN(&entry->variants);
+ }
+ else if (entry->entry) {
+ MEM_freeN(entry->entry);
+ }
}
-/* not listbase itself */
-void folderlist_free(ListBase *folderlist)
+static void filelist_entry_free(FileDirEntry *entry)
{
- if (folderlist) {
- FolderList *folder;
- for (folder = folderlist->first; folder; folder = folder->next)
- MEM_freeN(folder->foldername);
- BLI_freelistN(folderlist);
+ filelist_entry_clear(entry);
+ MEM_freeN(entry);
+}
+
+static void filelist_direntryarr_free(FileDirEntryArr *array)
+{
+#if 0
+ FileDirEntry *entry, *entry_next;
+
+ for (entry = array->entries.first; entry; entry = entry_next) {
+ entry_next = entry->next;
+ filelist_entry_free(entry);
}
+ BLI_listbase_clear(&array->entries);
+#else
+ BLI_assert(BLI_listbase_is_empty(&array->entries));
+#endif
+ array->nbr_entries = 0;
+ array->nbr_entries_filtered = -1;
+ array->entry_idx_start = -1;
+ array->entry_idx_end = -1;
}
-ListBase *folderlist_duplicate(ListBase *folderlist)
+static void filelist_intern_entry_free(FileListInternEntry *entry)
{
-
- if (folderlist) {
- ListBase *folderlistn = MEM_callocN(sizeof(ListBase), "copy folderlist");
- FolderList *folder;
-
- BLI_duplicatelist(folderlistn, folderlist);
-
- for (folder = folderlistn->first; folder; folder = folder->next) {
- folder->foldername = MEM_dupallocN(folder->foldername);
+ if (entry->relpath) {
+ MEM_freeN(entry->relpath);
+ }
+ if (entry->name) {
+ MEM_freeN(entry->name);
+ }
+ MEM_freeN(entry);
+}
+
+static void filelist_intern_free(FileListIntern *filelist_intern)
+{
+ FileListInternEntry *entry, *entry_next;
+
+ for (entry = filelist_intern->entries.first; entry; entry = entry_next) {
+ entry_next = entry->next;
+ filelist_intern_entry_free(entry);
+ }
+ BLI_listbase_clear(&filelist_intern->entries);
+
+ MEM_SAFE_FREE(filelist_intern->filtered);
+}
+
+static void filelist_cache_previewf(TaskPool *pool, void *taskdata, int UNUSED(threadid))
+{
+ FileListEntryCache *cache = taskdata;
+ FileListEntryPreview *preview;
+
+// printf("%s: Start (%d)...\n", __func__, threadid);
+
+ /* Note we wait on queue here. */
+ while (!BLI_task_pool_canceled(pool) && (preview = BLI_thread_queue_pop(cache->previews_todo))) {
+ ThumbSource source = 0;
+
+// printf("%s: %d - %s - %p\n", __func__, preview->index, preview->path, preview->img);
+ BLI_assert(preview->flags & (FILE_TYPE_IMAGE | FILE_TYPE_MOVIE | FILE_TYPE_FTFONT |
+ FILE_TYPE_BLENDER | FILE_TYPE_BLENDER_BACKUP | FILE_TYPE_BLENDERLIB));
+ if (preview->flags & FILE_TYPE_IMAGE) {
+ source = THB_SOURCE_IMAGE;
}
- return folderlistn;
+ else if (preview->flags & (FILE_TYPE_BLENDER | FILE_TYPE_BLENDER_BACKUP | FILE_TYPE_BLENDERLIB)) {
+ source = THB_SOURCE_BLEND;
+ }
+ else if (preview->flags & FILE_TYPE_MOVIE) {
+ source = THB_SOURCE_MOVIE;
+ }
+ else if (preview->flags & FILE_TYPE_FTFONT) {
+ source = THB_SOURCE_FONT;
+ }
+
+ IMB_thumb_path_lock(preview->path);
+ preview->img = IMB_thumb_manage(preview->path, THB_LARGE, source);
+ IMB_thumb_path_unlock(preview->path);
+
+ BLI_thread_queue_push(cache->previews_done, preview);
}
- return NULL;
+
+// printf("%s: End (%d)...\n", __func__, threadid);
}
+static void filelist_cache_preview_ensure_running(FileListEntryCache *cache)
+{
+ if (!cache->previews_pool) {
+ TaskScheduler *scheduler;
+ TaskPool *pool;
+ int num_tasks = max_ii(1, (BLI_system_thread_count() / 2) + 1);
+
+ scheduler = cache->previews_scheduler = BLI_task_scheduler_create(num_tasks + 1);
+ pool = cache->previews_pool = BLI_task_pool_create(scheduler, NULL);
+ cache->previews_todo = BLI_thread_queue_init();
+ cache->previews_done = BLI_thread_queue_init();
+
+ while (num_tasks--) {
+ BLI_task_pool_push(pool, filelist_cache_previewf, cache, false, TASK_PRIORITY_HIGH);
+ }
+ IMB_thumb_locks_acquire();
+ }
+ cache->previews_timestamp = 0.0;
+}
-static void filelist_read_main(struct FileList *filelist);
-static void filelist_read_library(struct FileList *filelist);
-static void filelist_read_dir(struct FileList *filelist);
+static void filelist_cache_previews_clear(FileListEntryCache *cache)
+{
+ FileListEntryPreview *preview;
+
+ if (cache->previews_pool) {
+ while ((preview = BLI_thread_queue_pop_timeout(cache->previews_todo, 0))) {
+// printf("%s: TODO %d - %s - %p\n", __func__, preview->index, preview->path, preview->img);
+ MEM_freeN(preview);
+ cache->previews_pending--;
+ }
+ while ((preview = BLI_thread_queue_pop_timeout(cache->previews_done, 0))) {
+// printf("%s: DONE %d - %s - %p\n", __func__, preview->index, preview->path, preview->img);
+ if (preview->img) {
+ IMB_freeImBuf(preview->img);
+ }
+ MEM_freeN(preview);
+ cache->previews_pending--;
+ }
+ }
+// printf("%s: remaining pending previews: %d\n", __func__, cache->previews_pending);
+}
+
+static void filelist_cache_previews_free(FileListEntryCache *cache, const bool set_inactive)
+{
+ if (cache->previews_pool) {
+ BLI_thread_queue_nowait(cache->previews_todo);
+ BLI_thread_queue_nowait(cache->previews_done);
+ BLI_task_pool_cancel(cache->previews_pool);
+
+ filelist_cache_previews_clear(cache);
+
+ BLI_thread_queue_free(cache->previews_done);
+ BLI_thread_queue_free(cache->previews_todo);
+ BLI_task_pool_free(cache->previews_pool);
+ BLI_task_scheduler_free(cache->previews_scheduler);
+ cache->previews_scheduler = NULL;
+ cache->previews_pool = NULL;
+ cache->previews_todo = NULL;
+ cache->previews_done = NULL;
+
+ IMB_thumb_locks_release();
+ }
+ if (set_inactive) {
+ cache->flags &= ~FLC_PREVIEWS_ACTIVE;
+ }
+ BLI_assert(cache->previews_pending == 0);
+ cache->previews_timestamp = 0.0;
+}
+
+static void filelist_cache_previews_push(FileList *filelist, FileDirEntry *entry, const int index)
+{
+ FileListEntryCache *cache = &filelist->filelist_cache;
+
+ BLI_assert(cache->flags & FLC_PREVIEWS_ACTIVE);
+
+ if (!entry->image &&
+ !(entry->flags & FILE_ENTRY_INVALID_PREVIEW) &&
+ (entry->typeflag & (FILE_TYPE_IMAGE | FILE_TYPE_MOVIE | FILE_TYPE_FTFONT |
+ FILE_TYPE_BLENDER | FILE_TYPE_BLENDER_BACKUP | FILE_TYPE_BLENDERLIB)))
+ {
+ FileListEntryPreview *preview = MEM_mallocN(sizeof(*preview), __func__);
+ BLI_join_dirfile(preview->path, sizeof(preview->path), filelist->filelist.root, entry->relpath);
+ preview->index = index;
+ preview->flags = entry->typeflag;
+ preview->img = NULL;
+// printf("%s: %d - %s - %p\n", __func__, preview->index, preview->path, preview->img);
+
+ filelist_cache_preview_ensure_running(cache);
+ BLI_thread_queue_push(cache->previews_todo, preview);
+ cache->previews_pending++;
+ }
+}
+
+static void filelist_cache_init(FileListEntryCache *cache, size_t cache_size)
+{
+ BLI_listbase_clear(&cache->cached_entries);
+
+ cache->block_cursor = cache->block_start_index = cache->block_center_index = cache->block_end_index = 0;
+ cache->block_entries = MEM_mallocN(sizeof(*cache->block_entries) * cache_size, __func__);
+
+ cache->misc_entries = BLI_ghash_ptr_new_ex(__func__, cache_size);
+ cache->misc_entries_indices = MEM_mallocN(sizeof(*cache->misc_entries_indices) * cache_size, __func__);
+ copy_vn_i(cache->misc_entries_indices, cache_size, -1);
+ cache->misc_cursor = 0;
+
+ /* XXX This assumes uint is 32 bits and uuid is 128 bits (char[16]), be careful! */
+ cache->uuids = BLI_ghash_new_ex(
+ BLI_ghashutil_uinthash_v4_p, BLI_ghashutil_uinthash_v4_cmp, __func__, cache_size * 2);
+
+ cache->size = cache_size;
+ cache->flags = FLC_IS_INIT;
+}
+
+static void filelist_cache_free(FileListEntryCache *cache)
+{
+ FileDirEntry *entry, *entry_next;
+
+ if (!(cache->flags & FLC_IS_INIT)) {
+ return;
+ }
+
+ filelist_cache_previews_free(cache, true);
+
+ MEM_freeN(cache->block_entries);
+
+ BLI_ghash_free(cache->misc_entries, NULL, NULL);
+ MEM_freeN(cache->misc_entries_indices);
+
+ BLI_ghash_free(cache->uuids, NULL, NULL);
+
+ for (entry = cache->cached_entries.first; entry; entry = entry_next) {
+ entry_next = entry->next;
+ filelist_entry_free(entry);
+ }
+ BLI_listbase_clear(&cache->cached_entries);
+}
+
+static void filelist_cache_clear(FileListEntryCache *cache, size_t new_size)
+{
+ FileDirEntry *entry, *entry_next;
+
+ if (!(cache->flags & FLC_IS_INIT)) {
+ return;
+ }
+
+ filelist_cache_previews_clear(cache);
+
+ cache->block_cursor = cache->block_start_index = cache->block_center_index = cache->block_end_index = 0;
+ if (new_size != cache->size) {
+ cache->block_entries = MEM_reallocN(cache->block_entries, sizeof(*cache->block_entries) * new_size);
+ }
+
+ BLI_ghash_clear_ex(cache->misc_entries, NULL, NULL, new_size);
+ if (new_size != cache->size) {
+ cache->misc_entries_indices = MEM_reallocN(cache->misc_entries_indices,
+ sizeof(*cache->misc_entries_indices) * new_size);
+ }
+ copy_vn_i(cache->misc_entries_indices, new_size, -1);
+
+ BLI_ghash_clear_ex(cache->uuids, NULL, NULL, new_size * 2);
+
+ cache->size = new_size;
+
+ for (entry = cache->cached_entries.first; entry; entry = entry_next) {
+ entry_next = entry->next;
+ filelist_entry_free(entry);
+ }
+ BLI_listbase_clear(&cache->cached_entries);
+}
-/* ------------------FILELIST------------------------ */
FileList *filelist_new(short type)
{
- FileList *p = MEM_callocN(sizeof(FileList), "filelist");
+ FileList *p = MEM_callocN(sizeof(*p), __func__);
+
+ filelist_cache_init(&p->filelist_cache, FILELIST_ENTRYCACHESIZE_DEFAULT);
+
+ p->selection_state = BLI_ghash_new(BLI_ghashutil_uinthash_v4_p, BLI_ghashutil_uinthash_v4_cmp, __func__);
+
switch (type) {
case FILE_MAIN:
- p->readf = filelist_read_main;
+ p->checkdirf = filelist_checkdir_main;
+ p->read_jobf = filelist_readjob_main;
p->filterf = is_filtered_main;
break;
case FILE_LOADLIB:
- p->readf = filelist_read_library;
+ p->checkdirf = filelist_checkdir_lib;
+ p->read_jobf = filelist_readjob_lib;
p->filterf = is_filtered_lib;
break;
default:
- p->readf = filelist_read_dir;
+ p->checkdirf = filelist_checkdir_dir;
+ p->read_jobf = filelist_readjob_dir;
p->filterf = is_filtered_file;
break;
-
}
return p;
}
+void filelist_clear_ex(struct FileList *filelist, const bool do_cache, const bool do_selection)
+{
+ if (!filelist) {
+ return;
+ }
+
+ filelist_filter_clear(filelist);
+
+ if (do_cache) {
+ filelist_cache_clear(&filelist->filelist_cache, filelist->filelist_cache.size);
+ }
+
+ filelist_intern_free(&filelist->filelist_intern);
+
+ filelist_direntryarr_free(&filelist->filelist);
+
+ if (do_selection && filelist->selection_state) {
+ BLI_ghash_clear(filelist->selection_state, MEM_freeN, NULL);
+ }
+}
+
+void filelist_clear(struct FileList *filelist)
+{
+ filelist_clear_ex(filelist, true, true);
+}
void filelist_free(struct FileList *filelist)
{
@@ -566,18 +1329,18 @@ void filelist_free(struct FileList *filelist)
return;
}
- if (filelist->fidx) {
- MEM_freeN(filelist->fidx);
- filelist->fidx = NULL;
+ filelist_clear_ex(filelist, false, false); /* No need to clear cache & selection_state, we free them anyway. */
+ filelist_cache_free(&filelist->filelist_cache);
+
+ if (filelist->selection_state) {
+ BLI_ghash_free(filelist->selection_state, MEM_freeN, NULL);
+ filelist->selection_state = NULL;
}
- BLI_free_filelist(filelist->filelist, filelist->numfiles);
- filelist->numfiles = 0;
- filelist->filelist = NULL;
- filelist->filter = 0;
- filelist->filter_glob[0] = '\0';
- filelist->numfiltered = 0;
- filelist->hide_dot = 0;
+ memset(&filelist->filter_data, 0, sizeof(filelist->filter_data));
+
+ filelist->flags &= ~(FL_NEED_SORTING | FL_NEED_FILTERING);
+ filelist->sort = FILE_SORT_NONE;
}
void filelist_freelib(struct FileList *filelist)
@@ -592,155 +1355,575 @@ BlendHandle *filelist_lib(struct FileList *filelist)
return filelist->libfiledata;
}
-int filelist_numfiles(struct FileList *filelist)
+static const char *fileentry_uiname(const char *root, const char *relpath, const int typeflag, char *buff)
{
- return filelist->numfiltered;
+ char *name = NULL;
+
+ if (typeflag & FILE_TYPE_BLENDERLIB) {
+ char abspath[FILE_MAX_LIBEXTRA];
+ char *group;
+
+ BLI_join_dirfile(abspath, sizeof(abspath), root, relpath);
+ BLO_library_path_explode(abspath, buff, &group, &name);
+ if (!name) {
+ name = group;
+ }
+ }
+ /* Depending on platforms, 'my_file.blend/..' might be viewed as dir or not... */
+ if (!name) {
+ if (typeflag & FILE_TYPE_DIR) {
+ name = (char *)relpath;
+ }
+ else {
+ name = (char *)BLI_path_basename(relpath);
+ }
+ }
+ BLI_assert(name);
+
+ return name;
}
const char *filelist_dir(struct FileList *filelist)
{
- return filelist->dir;
+ return filelist->filelist.root;
}
-void filelist_setdir(struct FileList *filelist, const char *dir)
+/**
+ * May modify in place given r_dir, which is expected to be FILE_MAX_LIBEXTRA length.
+ */
+void filelist_setdir(struct FileList *filelist, char *r_dir)
{
- BLI_strncpy(filelist->dir, dir, sizeof(filelist->dir));
+ BLI_assert(strlen(r_dir) < FILE_MAX_LIBEXTRA);
+
+ BLI_cleanup_dir(G.main->name, r_dir);
+ filelist->checkdirf(filelist, r_dir);
+
+ if (!STREQ(filelist->filelist.root, r_dir)) {
+ BLI_strncpy(filelist->filelist.root, r_dir, sizeof(filelist->filelist.root));
+ filelist->flags |= FL_FORCE_RESET;
+ }
}
-void filelist_imgsize(struct FileList *filelist, short w, short h)
+void filelist_setrecursion(struct FileList *filelist, const int recursion_level)
{
- filelist->prv_w = w;
- filelist->prv_h = h;
+ if (filelist->max_recursion != recursion_level) {
+ filelist->max_recursion = recursion_level;
+ filelist->flags |= FL_FORCE_RESET;
+ }
}
-short filelist_changed(struct FileList *filelist)
+bool filelist_force_reset(struct FileList *filelist)
{
- return filelist->changed;
+ return (filelist->flags & FL_FORCE_RESET) != 0;
}
-ImBuf *filelist_getimage(struct FileList *filelist, int index)
+bool filelist_is_ready(struct FileList *filelist)
{
- ImBuf *ibuf = NULL;
- int fidx = 0;
+ return (filelist->flags & FL_IS_READY) != 0;
+}
- BLI_assert(G.background == false);
+bool filelist_pending(struct FileList *filelist)
+{
+ return (filelist->flags & FL_IS_PENDING) != 0;
+}
- if ((index < 0) || (index >= filelist->numfiltered)) {
- return NULL;
+/**
+ * Limited version of full update done by space_file's file_refresh(), to be used by operators and such.
+ * Ensures given filelist is ready to be used (i.e. it is filtered and sorted), unless it is tagged for a full refresh.
+ */
+int filelist_files_ensure(FileList *filelist)
+{
+ if (!filelist_force_reset(filelist) || !filelist_empty(filelist)) {
+ filelist_sort(filelist);
+ filelist_filter(filelist);
}
- fidx = filelist->fidx[index];
- ibuf = filelist->filelist[fidx].image;
- return ibuf;
+ return filelist->filelist.nbr_entries_filtered;;
}
-ImBuf *filelist_geticon(struct FileList *filelist, int index)
+static FileDirEntry *filelist_file_create_entry(FileList *filelist, const int index)
{
- ImBuf *ibuf = NULL;
- struct direntry *file = NULL;
- int fidx = 0;
+ FileListInternEntry *entry = filelist->filelist_intern.filtered[index];
+ FileListEntryCache *cache = &filelist->filelist_cache;
+ FileDirEntry *ret;
+ FileDirEntryRevision *rev;
- BLI_assert(G.background == false);
+ ret = MEM_callocN(sizeof(*ret), __func__);
+ rev = MEM_callocN(sizeof(*rev), __func__);
- if ((index < 0) || (index >= filelist->numfiltered)) {
- return NULL;
+ rev->size = (uint64_t)entry->st.st_size;
+
+ rev->time = (int64_t)entry->st.st_mtime;
+
+ ret->entry = rev;
+ ret->relpath = BLI_strdup(entry->relpath);
+ ret->name = BLI_strdup(entry->name);
+ ret->description = BLI_strdupcat(filelist->filelist.root, entry->relpath);
+ memcpy(ret->uuid, entry->uuid, sizeof(ret->uuid));
+ ret->blentype = entry->blentype;
+ ret->typeflag = entry->typeflag;
+
+ BLI_addtail(&cache->cached_entries, ret);
+ return ret;
+}
+
+static void filelist_file_release_entry(FileList *filelist, FileDirEntry *entry)
+{
+ BLI_remlink(&filelist->filelist_cache.cached_entries, entry);
+ filelist_entry_free(entry);
+}
+
+static FileDirEntry *filelist_file_ex(struct FileList *filelist, const int index, const bool use_request)
+{
+ FileDirEntry *ret = NULL, *old;
+ FileListEntryCache *cache = &filelist->filelist_cache;
+ const size_t cache_size = cache->size;
+ int old_index;
+
+ if ((index < 0) || (index >= filelist->filelist.nbr_entries_filtered)) {
+ return ret;
}
- fidx = filelist->fidx[index];
- file = &filelist->filelist[fidx];
- if (file->type & S_IFDIR) {
- if (strcmp(filelist->filelist[fidx].relname, "..") == 0) {
- ibuf = gSpecialFileImages[SPECIAL_IMG_PARENT];
- }
- else if (strcmp(filelist->filelist[fidx].relname, ".") == 0) {
- ibuf = gSpecialFileImages[SPECIAL_IMG_REFRESH];
- }
- else {
- ibuf = gSpecialFileImages[SPECIAL_IMG_FOLDER];
- }
+
+ if (index >= cache->block_start_index && index < cache->block_end_index) {
+ const int idx = (index - cache->block_start_index + cache->block_cursor) % cache_size;
+ return cache->block_entries[idx];
}
- else {
- ibuf = gSpecialFileImages[SPECIAL_IMG_UNKNOWNFILE];
+
+ if ((ret = BLI_ghash_lookup(cache->misc_entries, SET_INT_IN_POINTER(index)))) {
+ return ret;
}
- if (file->flags & BLENDERFILE) {
- ibuf = gSpecialFileImages[SPECIAL_IMG_BLENDFILE];
+ if (!use_request) {
+ return NULL;
}
- else if ((file->flags & MOVIEFILE) || (file->flags & MOVIEFILE_ICON)) {
- ibuf = gSpecialFileImages[SPECIAL_IMG_MOVIEFILE];
+
+// printf("requesting file %d (not yet cached)\n", index);
+
+ /* Else, we have to add new entry to 'misc' cache - and possibly make room for it first! */
+ ret = filelist_file_create_entry(filelist, index);
+ old_index = cache->misc_entries_indices[cache->misc_cursor];
+ if ((old = BLI_ghash_popkey(cache->misc_entries, SET_INT_IN_POINTER(old_index), NULL))) {
+ BLI_ghash_remove(cache->uuids, old->uuid, NULL, NULL);
+ filelist_file_release_entry(filelist, old);
}
- else if (file->flags & SOUNDFILE) {
- ibuf = gSpecialFileImages[SPECIAL_IMG_SOUNDFILE];
+ BLI_ghash_insert(cache->misc_entries, SET_INT_IN_POINTER(index), ret);
+ BLI_ghash_insert(cache->uuids, ret->uuid, ret);
+
+ cache->misc_entries_indices[cache->misc_cursor] = index;
+ cache->misc_cursor = (cache->misc_cursor + 1) % cache_size;
+
+#if 0 /* Actually no, only block cached entries should have preview imho. */
+ if (cache->previews_pool) {
+ filelist_cache_previews_push(filelist, ret, index);
}
- else if (file->flags & PYSCRIPTFILE) {
- ibuf = gSpecialFileImages[SPECIAL_IMG_PYTHONFILE];
+#endif
+
+ return ret;
+}
+
+FileDirEntry *filelist_file(struct FileList *filelist, int index)
+{
+ return filelist_file_ex(filelist, index, true);
+}
+
+int filelist_file_findpath(struct FileList *filelist, const char *filename)
+{
+ int fidx = -1;
+
+ if (filelist->filelist.nbr_entries_filtered < 0) {
+ return fidx;
}
- else if (file->flags & FTFONTFILE) {
- ibuf = gSpecialFileImages[SPECIAL_IMG_FONTFILE];
+
+ /* XXX TODO Cache could probably use a ghash on paths too? Not really urgent though.
+ * This is only used to find again renamed entry, annoying but looks hairy to get rid of it currently. */
+
+ for (fidx = 0; fidx < filelist->filelist.nbr_entries_filtered; fidx++) {
+ FileListInternEntry *entry = filelist->filelist_intern.filtered[fidx];
+ if (STREQ(entry->relpath, filename)) {
+ return fidx;
+ }
}
- else if (file->flags & TEXTFILE) {
- ibuf = gSpecialFileImages[SPECIAL_IMG_TEXTFILE];
+
+ return -1;
+}
+
+FileDirEntry *filelist_entry_find_uuid(struct FileList *filelist, const int uuid[4])
+{
+ if (filelist->filelist.nbr_entries_filtered < 0) {
+ return NULL;
}
- else if (file->flags & IMAGEFILE) {
- ibuf = gSpecialFileImages[SPECIAL_IMG_LOADING];
+
+ if (filelist->filelist_cache.uuids) {
+ FileDirEntry *entry = BLI_ghash_lookup(filelist->filelist_cache.uuids, uuid);
+ if (entry) {
+ return entry;
+ }
}
- else if (file->flags & BLENDERFILE_BACKUP) {
- ibuf = gSpecialFileImages[SPECIAL_IMG_BACKUP];
+
+ {
+ int fidx;
+
+ for (fidx = 0; fidx < filelist->filelist.nbr_entries_filtered; fidx++) {
+ FileListInternEntry *entry = filelist->filelist_intern.filtered[fidx];
+ if (memcmp(entry->uuid, uuid, sizeof(entry->uuid)) == 0) {
+ return filelist_file(filelist, fidx);
+ }
+ }
}
- return ibuf;
+ return NULL;
}
-struct direntry *filelist_file(struct FileList *filelist, int index)
+void filelist_file_cache_slidingwindow_set(FileList *filelist, size_t window_size)
{
- int fidx = 0;
-
- if ((index < 0) || (index >= filelist->numfiltered)) {
- return NULL;
+ /* Always keep it power of 2, in [256, 8192] range for now, cache being app. twice bigger than requested window. */
+ size_t size = 256;
+ window_size *= 2;
+
+ while (size < window_size && size < 8192) {
+ size *= 2;
}
- fidx = filelist->fidx[index];
- return &filelist->filelist[fidx];
+ if (size != filelist->filelist_cache.size) {
+ filelist_cache_clear(&filelist->filelist_cache, size);
+ }
}
-int filelist_find(struct FileList *filelist, const char *filename)
+/* Helpers, low-level, they assume cursor + size <= cache_size */
+static bool filelist_file_cache_block_create(FileList *filelist, const int start_index, const int size, int cursor)
{
- int index = -1;
+ FileListEntryCache *cache = &filelist->filelist_cache;
+
+ {
+ int i, idx;
+
+ for (i = 0, idx = start_index; i < size; i++, idx++, cursor++) {
+ FileDirEntry *entry;
+
+ /* That entry might have already been requested and stored in misc cache... */
+ if ((entry = BLI_ghash_popkey(cache->misc_entries, SET_INT_IN_POINTER(idx), NULL)) == NULL) {
+ entry = filelist_file_create_entry(filelist, idx);
+ BLI_ghash_insert(cache->uuids, entry->uuid, entry);
+ }
+ cache->block_entries[cursor] = entry;
+ }
+ return true;
+ }
+
+ return false;
+}
+
+static void filelist_file_cache_block_release(struct FileList *filelist, const int size, int cursor)
+{
+ FileListEntryCache *cache = &filelist->filelist_cache;
+
+ {
+ int i;
+
+ for (i = 0; i < size; i++, cursor++) {
+ FileDirEntry *entry = cache->block_entries[cursor];
+// printf("%s: release cacheidx %d (%%p %%s)\n", __func__, cursor/*, cache->block_entries[cursor], cache->block_entries[cursor]->relpath*/);
+ BLI_ghash_remove(cache->uuids, entry->uuid, NULL, NULL);
+ filelist_file_release_entry(filelist, entry);
+#ifndef NDEBUG
+ cache->block_entries[cursor] = NULL;
+#endif
+ }
+ }
+}
+
+/* Load in cache all entries "around" given index (as much as block cache may hold). */
+bool filelist_file_cache_block(struct FileList *filelist, const int index)
+{
+ FileListEntryCache *cache = &filelist->filelist_cache;
+ const size_t cache_size = cache->size;
+
+ const int nbr_entries = filelist->filelist.nbr_entries_filtered;
+ int start_index = max_ii(0, index - (cache_size / 2));
+ int end_index = min_ii(nbr_entries, index + (cache_size / 2));
int i;
- int fidx = -1;
-
- if (!filelist->fidx)
- return fidx;
-
- for (i = 0; i < filelist->numfiles; ++i) {
- if (strcmp(filelist->filelist[i].relname, filename) == 0) { /* not dealing with user input so don't need BLI_path_cmp */
- index = i;
- break;
+ if ((index < 0) || (index >= nbr_entries)) {
+// printf("Wrong index %d ([%d:%d])", index, 0, nbr_entries);
+ return false;
+ }
+
+ /* Maximize cached range! */
+ if ((end_index - start_index) < cache_size) {
+ if (start_index == 0) {
+ end_index = min_ii(nbr_entries, start_index + cache_size);
+ }
+ else if (end_index == nbr_entries) {
+ start_index = max_ii(0, end_index - cache_size);
}
}
- for (i = 0; i < filelist->numfiltered; ++i) {
- if (filelist->fidx[i] == index) {
- fidx = i;
- break;
+ BLI_assert((end_index - start_index) <= cache_size) ;
+
+// printf("%s: [%d:%d] around index %d (current cache: [%d:%d])\n", __func__,
+// start_index, end_index, index, cache->block_start_index, cache->block_end_index);
+
+ /* If we have something to (re)cache... */
+ if ((start_index != cache->block_start_index) || (end_index != cache->block_end_index)) {
+ if ((start_index >= cache->block_end_index) || (end_index <= cache->block_start_index)) {
+ int size1 = cache->block_end_index - cache->block_start_index;
+ int size2 = 0;
+ int idx1 = cache->block_cursor, idx2 = 0;
+
+// printf("Full Recaching!\n");
+
+ if (cache->flags & FLC_PREVIEWS_ACTIVE) {
+ filelist_cache_previews_clear(cache);
+ }
+
+ if (idx1 + size1 > cache_size) {
+ size2 = idx1 + size1 - cache_size;
+ size1 -= size2;
+ filelist_file_cache_block_release(filelist, size2, idx2);
+ }
+ filelist_file_cache_block_release(filelist, size1, idx1);
+
+ cache->block_start_index = cache->block_end_index = cache->block_cursor = 0;
+
+ /* New cached block does not overlap existing one, simple. */
+ if (!filelist_file_cache_block_create(filelist, start_index, end_index - start_index, 0)) {
+ return false;
+ }
+
+ cache->block_start_index = start_index;
+ cache->block_end_index = end_index;
+ }
+ else {
+// printf("Partial Recaching!\n");
+
+ /* At this point, we know we keep part of currently cached entries, so update previews if needed,
+ * and remove everything from working queue - we'll add all newly needed entries at the end. */
+ if (cache->flags & FLC_PREVIEWS_ACTIVE) {
+ filelist_cache_previews_update(filelist);
+ filelist_cache_previews_clear(cache);
+ }
+
+// printf("\tpreview cleaned up...\n");
+
+ if (start_index > cache->block_start_index) {
+ int size1 = start_index - cache->block_start_index;
+ int size2 = 0;
+ int idx1 = cache->block_cursor, idx2 = 0;
+
+// printf("\tcache releasing: [%d:%d] (%d, %d)\n", cache->block_start_index, cache->block_start_index + size1, cache->block_cursor, size1);
+
+ if (idx1 + size1 > cache_size) {
+ size2 = idx1 + size1 - cache_size;
+ size1 -= size2;
+ filelist_file_cache_block_release(filelist, size2, idx2);
+ }
+ filelist_file_cache_block_release(filelist, size1, idx1);
+
+ cache->block_cursor = (idx1 + size1 + size2) % cache_size;
+ cache->block_start_index = start_index;
+ }
+ if (end_index < cache->block_end_index) {
+ int size1 = cache->block_end_index - end_index;
+ int size2 = 0;
+ int idx1, idx2 = 0;
+
+// printf("\tcache releasing: [%d:%d] (%d)\n", cache->block_end_index - size1, cache->block_end_index, cache->block_cursor);
+
+ idx1 = (cache->block_cursor + end_index - cache->block_start_index) % cache_size;
+ if (idx1 + size1 > cache_size) {
+ size2 = idx1 + size1 - cache_size;
+ size1 -= size2;
+ filelist_file_cache_block_release(filelist, size2, idx2);
+ }
+ filelist_file_cache_block_release(filelist, size1, idx1);
+
+ cache->block_end_index = end_index;
+ }
+
+// printf("\tcache cleaned up...\n");
+
+ if (start_index < cache->block_start_index) {
+ /* Add (request) needed entries before already cached ones. */
+ /* Note: We need some index black magic to wrap around (cycle) inside our cache_size array... */
+ int size1 = cache->block_start_index - start_index;
+ int size2 = 0;
+ int idx1, idx2;
+
+ if (size1 > cache->block_cursor) {
+ size2 = size1;
+ size1 -= cache->block_cursor;
+ size2 -= size1;
+ idx2 = 0;
+ idx1 = cache_size - size1;
+ }
+ else {
+ idx1 = cache->block_cursor - size1;
+ }
+
+ if (size2) {
+ if (!filelist_file_cache_block_create(filelist, start_index + size1, size2, idx2)) {
+ return false;
+ }
+ }
+ if (!filelist_file_cache_block_create(filelist, start_index, size1, idx1)) {
+ return false;
+ }
+
+ cache->block_cursor = idx1;
+ cache->block_start_index = start_index;
+ }
+// printf("\tstart-extended...\n");
+ if (end_index > cache->block_end_index) {
+ /* Add (request) needed entries after already cached ones. */
+ /* Note: We need some index black magic to wrap around (cycle) inside our cache_size array... */
+ int size1 = end_index - cache->block_end_index;
+ int size2 = 0;
+ int idx1, idx2;
+
+ idx1 = (cache->block_cursor + end_index - cache->block_start_index - size1) % cache_size;
+ if ((idx1 + size1) > cache_size) {
+ size2 = size1;
+ size1 = cache_size - idx1;
+ size2 -= size1;
+ idx2 = 0;
+ }
+
+ if (size2) {
+ if (!filelist_file_cache_block_create(filelist, end_index - size2, size2, idx2)) {
+ return false;
+ }
+ }
+ if (!filelist_file_cache_block_create(filelist, end_index - size1 - size2, size1, idx1)) {
+ return false;
+ }
+
+ cache->block_end_index = end_index;
+ }
+
+// printf("\tend-extended...\n");
+ }
+ }
+ else if ((cache->block_center_index != index) && (cache->flags & FLC_PREVIEWS_ACTIVE)) {
+ /* We try to always preview visible entries first, so 'restart' preview background task. */
+ filelist_cache_previews_update(filelist);
+ filelist_cache_previews_clear(cache);
+ }
+
+// printf("Re-queueing previews...\n");
+
+ /* Note we try to preview first images around given index - i.e. assumed visible ones. */
+ if (cache->flags & FLC_PREVIEWS_ACTIVE) {
+ for (i = 0; ((index + i) < end_index) || ((index - i) >= start_index); i++) {
+ if ((index - i) >= start_index) {
+ const int idx = (cache->block_cursor + (index - start_index) - i) % cache_size;
+ filelist_cache_previews_push(filelist, cache->block_entries[idx], index - i);
+ }
+ if ((index + i) < end_index) {
+ const int idx = (cache->block_cursor + (index - start_index) + i) % cache_size;
+ filelist_cache_previews_push(filelist, cache->block_entries[idx], index + i);
+ }
}
}
- return fidx;
+
+ cache->block_center_index = index;
+
+// printf("%s Finished!\n", __func__);
+
+ return true;
}
-void filelist_hidedot(struct FileList *filelist, short hide)
+void filelist_cache_previews_set(FileList *filelist, const bool use_previews)
{
- filelist->hide_dot = hide;
+ FileListEntryCache *cache = &filelist->filelist_cache;
+
+ if (use_previews == ((cache->flags & FLC_PREVIEWS_ACTIVE) != 0)) {
+ return;
+ }
+ /* Do not start preview work while listing, gives nasty flickering! */
+ else if (use_previews && (filelist->flags & FL_IS_READY)) {
+ cache->flags |= FLC_PREVIEWS_ACTIVE;
+
+ BLI_assert((cache->previews_pool == NULL) && (cache->previews_todo == NULL) && (cache->previews_done == NULL));
+
+// printf("%s: Init Previews...\n", __func__);
+
+ /* No need to populate preview queue here, filelist_file_cache_block() handles this. */
+ }
+ else {
+// printf("%s: Clear Previews...\n", __func__);
+
+ filelist_cache_previews_free(cache, true);
+ }
}
-void filelist_setfilter(struct FileList *filelist, unsigned int filter)
+bool filelist_cache_previews_update(FileList *filelist)
{
- filelist->filter = filter;
+ FileListEntryCache *cache = &filelist->filelist_cache;
+ TaskPool *pool = cache->previews_pool;
+ bool changed = false;
+
+ if (!pool) {
+ return changed;
+ }
+
+// printf("%s: Update Previews...\n", __func__);
+
+ while (!BLI_thread_queue_is_empty(cache->previews_done)) {
+ FileListEntryPreview *preview = BLI_thread_queue_pop(cache->previews_done);
+ FileDirEntry *entry;
+
+ /* Paranoid (should never happen currently since we consume this queue from a single thread), but... */
+ if (!preview) {
+ continue;
+ }
+ /* entry might have been removed from cache in the mean while, we do not want to cache it again here. */
+ entry = filelist_file_ex(filelist, preview->index, false);
+
+// printf("%s: %d - %s - %p\n", __func__, preview->index, preview->path, preview->img);
+
+ if (preview->img) {
+ /* Due to asynchronous process, a preview for a given image may be generated several times, i.e.
+ * entry->image may already be set at this point. */
+ if (entry && !entry->image) {
+ entry->image = preview->img;
+ changed = true;
+ }
+ else {
+ IMB_freeImBuf(preview->img);
+ }
+ }
+ else if (entry) {
+ /* We want to avoid re-processing this entry continuously!
+ * Note that, since entries only live in cache, preview will be retried quite often anyway. */
+ entry->flags |= FILE_ENTRY_INVALID_PREVIEW;
+ }
+
+ MEM_freeN(preview);
+ cache->previews_pending--;
+ BLI_assert(cache->previews_pending >= 0);
+ }
+
+// printf("%s: Previews pending: %d\n", __func__, cache->previews_pending);
+ if (cache->previews_pending == 0) {
+ if (cache->previews_timestamp == 0.0) {
+ cache->previews_timestamp = PIL_check_seconds_timer();
+ }
+ else if (PIL_check_seconds_timer() - cache->previews_timestamp > 1.0) {
+ /* Preview task is IDLE since more than (approximatively) 1000ms,
+ * kill workers & task for now - they will be automatically restarted when needed. */
+// printf("%s: Inactive preview task, sleeping (%f vs %f)!\n", __func__, PIL_check_seconds_timer(), cache->previews_timestamp);
+ filelist_cache_previews_free(cache, false);
+ }
+ }
+
+ return changed;
}
-void filelist_setfilter_types(struct FileList *filelist, const char *filter_glob)
+bool filelist_cache_previews_running(FileList *filelist)
{
- BLI_strncpy(filelist->filter_glob, filter_glob, sizeof(filelist->filter_glob));
+ FileListEntryCache *cache = &filelist->filelist_cache;
+
+ return (cache->previews_pool != NULL);
}
/* would recognize .blend as well */
@@ -772,55 +1955,55 @@ static bool file_is_blend_backup(const char *str)
static int path_extension_type(const char *path)
{
if (BLO_has_bfile_extension(path)) {
- return BLENDERFILE;
+ return FILE_TYPE_BLENDER;
}
else if (file_is_blend_backup(path)) {
- return BLENDERFILE_BACKUP;
+ return FILE_TYPE_BLENDER_BACKUP;
}
else if (BLI_testextensie(path, ".app")) {
- return APPLICATIONBUNDLE;
+ return FILE_TYPE_APPLICATIONBUNDLE;
}
else if (BLI_testextensie(path, ".py")) {
- return PYSCRIPTFILE;
+ return FILE_TYPE_PYSCRIPT;
}
else if (BLI_testextensie_n(path, ".txt", ".glsl", ".osl", ".data", NULL)) {
- return TEXTFILE;
+ return FILE_TYPE_TEXT;
}
else if (BLI_testextensie_n(path, ".ttf", ".ttc", ".pfb", ".otf", ".otc", NULL)) {
- return FTFONTFILE;
+ return FILE_TYPE_FTFONT;
}
else if (BLI_testextensie(path, ".btx")) {
- return BTXFILE;
+ return FILE_TYPE_BTX;
}
else if (BLI_testextensie(path, ".dae")) {
- return COLLADAFILE;
+ return FILE_TYPE_COLLADA;
}
else if (BLI_testextensie_array(path, imb_ext_image) ||
(G.have_quicktime && BLI_testextensie_array(path, imb_ext_image_qt)))
{
- return IMAGEFILE;
+ return FILE_TYPE_IMAGE;
}
else if (BLI_testextensie(path, ".ogg")) {
if (IMB_isanim(path)) {
- return MOVIEFILE;
+ return FILE_TYPE_MOVIE;
}
else {
- return SOUNDFILE;
+ return FILE_TYPE_SOUND;
}
}
else if (BLI_testextensie_array(path, imb_ext_movie)) {
- return MOVIEFILE;
+ return FILE_TYPE_MOVIE;
}
else if (BLI_testextensie_array(path, imb_ext_audio)) {
- return SOUNDFILE;
+ return FILE_TYPE_SOUND;
}
return 0;
}
-static int file_extension_type(const char *dir, const char *relname)
+static int file_extension_type(const char *dir, const char *relpath)
{
char path[FILE_MAX];
- BLI_join_dirfile(path, sizeof(path), dir, relname);
+ BLI_join_dirfile(path, sizeof(path), dir, relpath);
return path_extension_type(path);
}
@@ -828,213 +2011,146 @@ int ED_file_extension_icon(const char *path)
{
int type = path_extension_type(path);
- if (type == BLENDERFILE)
- return ICON_FILE_BLEND;
- else if (type == BLENDERFILE_BACKUP)
- return ICON_FILE_BACKUP;
- else if (type == IMAGEFILE)
- return ICON_FILE_IMAGE;
- else if (type == MOVIEFILE)
- return ICON_FILE_MOVIE;
- else if (type == PYSCRIPTFILE)
- return ICON_FILE_SCRIPT;
- else if (type == SOUNDFILE)
- return ICON_FILE_SOUND;
- else if (type == FTFONTFILE)
- return ICON_FILE_FONT;
- else if (type == BTXFILE)
- return ICON_FILE_BLANK;
- else if (type == COLLADAFILE)
- return ICON_FILE_BLANK;
- else if (type == TEXTFILE)
- return ICON_FILE_TEXT;
-
- return ICON_FILE_BLANK;
-}
-
-static void filelist_setfiletypes(struct FileList *filelist)
-{
- struct direntry *file;
- int num;
-
- file = filelist->filelist;
-
- for (num = 0; num < filelist->numfiles; num++, file++) {
- file->type = file->s.st_mode; /* restore the mess below */
-#ifndef __APPLE__
- /* Don't check extensions for directories, allow in OSX cause bundles have extensions*/
- if (file->type & S_IFDIR) {
- continue;
- }
-#endif
- file->flags = file_extension_type(filelist->dir, file->relname);
-
- if (filelist->filter_glob[0] &&
- BLI_testextensie_glob(file->relname, filelist->filter_glob))
- {
- file->flags = OPERATORFILE;
- }
-
+ switch (type) {
+ case FILE_TYPE_BLENDER:
+ return ICON_FILE_BLEND;
+ case FILE_TYPE_BLENDER_BACKUP:
+ return ICON_FILE_BACKUP;
+ case FILE_TYPE_IMAGE:
+ return ICON_FILE_IMAGE;
+ case FILE_TYPE_MOVIE:
+ return ICON_FILE_MOVIE;
+ case FILE_TYPE_PYSCRIPT:
+ return ICON_FILE_SCRIPT;
+ case FILE_TYPE_SOUND:
+ return ICON_FILE_SOUND;
+ case FILE_TYPE_FTFONT:
+ return ICON_FILE_FONT;
+ case FILE_TYPE_BTX:
+ return ICON_FILE_BLANK;
+ case FILE_TYPE_COLLADA:
+ return ICON_FILE_BLANK;
+ case FILE_TYPE_TEXT:
+ return ICON_FILE_TEXT;
+ default:
+ return ICON_FILE_BLANK;
}
}
-static void filelist_read_dir(struct FileList *filelist)
-{
- if (!filelist) return;
-
- filelist->fidx = NULL;
- filelist->filelist = NULL;
-
- BLI_cleanup_dir(G.main->name, filelist->dir);
- filelist->numfiles = BLI_dir_contents(filelist->dir, &(filelist->filelist));
-
- filelist_setfiletypes(filelist);
- filelist_filter(filelist);
-}
-
-static void filelist_read_main(struct FileList *filelist)
+int filelist_empty(struct FileList *filelist)
{
- if (!filelist) return;
- filelist_from_main(filelist);
+ return (filelist->filelist.nbr_entries == 0);
}
-static void filelist_read_library(struct FileList *filelist)
+unsigned int filelist_entry_select_set(
+ const FileList *filelist, const FileDirEntry *entry, FileSelType select, unsigned int flag, FileCheckType check)
{
- if (!filelist) return;
- BLI_cleanup_dir(G.main->name, filelist->dir);
- filelist_from_library(filelist);
- if (!filelist->libfiledata) {
- int num;
- struct direntry *file;
+ /* Default NULL pointer if not found is fine here! */
+ void **es_p = BLI_ghash_lookup_p(filelist->selection_state, entry->uuid);
+ unsigned int entry_flag = es_p ? GET_UINT_FROM_POINTER(*es_p) : 0;
+ const unsigned int org_entry_flag = entry_flag;
- BLI_make_exist(filelist->dir);
- filelist_read_dir(filelist);
- file = filelist->filelist;
- for (num = 0; num < filelist->numfiles; num++, file++) {
- if (BLO_has_bfile_extension(file->relname)) {
- char name[FILE_MAX];
+ BLI_assert(entry);
+ BLI_assert(ELEM(check, CHECK_DIRS, CHECK_FILES, CHECK_ALL));
- BLI_join_dirfile(name, sizeof(name), filelist->dir, file->relname);
+ if (((check == CHECK_ALL)) ||
+ ((check == CHECK_DIRS) && (entry->typeflag & FILE_TYPE_DIR)) ||
+ ((check == CHECK_FILES) && !(entry->typeflag & FILE_TYPE_DIR)))
+ {
+ switch (select) {
+ case FILE_SEL_REMOVE:
+ entry_flag &= ~flag;
+ break;
+ case FILE_SEL_ADD:
+ entry_flag |= flag;
+ break;
+ case FILE_SEL_TOGGLE:
+ entry_flag ^= flag;
+ break;
+ }
+ }
- /* prevent current file being used as acceptable dir */
- if (BLI_path_cmp(G.main->name, name) != 0) {
- file->type &= ~S_IFMT;
- file->type |= S_IFDIR;
- }
+ if (entry_flag != org_entry_flag) {
+ if (es_p) {
+ if (entry_flag) {
+ *es_p = SET_UINT_IN_POINTER(entry_flag);
+ }
+ else {
+ BLI_ghash_remove(filelist->selection_state, entry->uuid, MEM_freeN, NULL);
}
}
+ else if (entry_flag) {
+ void *key = MEM_mallocN(sizeof(entry->uuid), __func__);
+ memcpy(key, entry->uuid, sizeof(entry->uuid));
+ BLI_ghash_insert(filelist->selection_state, key, SET_UINT_IN_POINTER(entry_flag));
+ }
}
-}
-void filelist_readdir(struct FileList *filelist)
-{
- filelist->readf(filelist);
-}
-
-int filelist_empty(struct FileList *filelist)
-{
- return filelist->filelist == NULL;
+ return entry_flag;
}
-void filelist_parent(struct FileList *filelist)
+void filelist_entry_select_index_set(FileList *filelist, const int index, FileSelType select, unsigned int flag, FileCheckType check)
{
- BLI_parent_dir(filelist->dir);
- BLI_make_exist(filelist->dir);
- filelist_readdir(filelist);
-}
+ FileDirEntry *entry = filelist_file(filelist, index);
-void filelist_select_file(struct FileList *filelist, int index, FileSelType select, unsigned int flag, FileCheckType check)
-{
- struct direntry *file = filelist_file(filelist, index);
- if (file != NULL) {
- int check_ok = 0;
- switch (check) {
- case CHECK_DIRS:
- check_ok = S_ISDIR(file->type);
- break;
- case CHECK_ALL:
- check_ok = 1;
- break;
- case CHECK_FILES:
- default:
- check_ok = !S_ISDIR(file->type);
- break;
- }
- if (check_ok) {
- switch (select) {
- case FILE_SEL_REMOVE:
- file->selflag &= ~flag;
- break;
- case FILE_SEL_ADD:
- file->selflag |= flag;
- break;
- case FILE_SEL_TOGGLE:
- file->selflag ^= flag;
- break;
- }
- }
+ if (entry) {
+ filelist_entry_select_set(filelist, entry, select, flag, check);
}
}
-void filelist_select(struct FileList *filelist, FileSelection *sel, FileSelType select, unsigned int flag, FileCheckType check)
+void filelist_entries_select_index_range_set(
+ FileList *filelist, FileSelection *sel, FileSelType select, unsigned int flag, FileCheckType check)
{
/* select all valid files between first and last indicated */
- if ((sel->first >= 0) && (sel->first < filelist->numfiltered) && (sel->last >= 0) && (sel->last < filelist->numfiltered)) {
+ if ((sel->first >= 0) && (sel->first < filelist->filelist.nbr_entries_filtered) &&
+ (sel->last >= 0) && (sel->last < filelist->filelist.nbr_entries_filtered))
+ {
int current_file;
for (current_file = sel->first; current_file <= sel->last; current_file++) {
- filelist_select_file(filelist, current_file, select, flag, check);
+ filelist_entry_select_index_set(filelist, current_file, select, flag, check);
}
}
}
-bool filelist_is_selected(struct FileList *filelist, int index, FileCheckType check)
+unsigned int filelist_entry_select_get(FileList *filelist, FileDirEntry *entry, FileCheckType check)
{
- struct direntry *file = filelist_file(filelist, index);
- if (!file) {
- return 0;
- }
- switch (check) {
- case CHECK_DIRS:
- return S_ISDIR(file->type) && (file->selflag & SELECTED_FILE);
- case CHECK_FILES:
- return S_ISREG(file->type) && (file->selflag & SELECTED_FILE);
- case CHECK_ALL:
- default:
- return (file->selflag & SELECTED_FILE) != 0;
+ BLI_assert(entry);
+ BLI_assert(ELEM(check, CHECK_DIRS, CHECK_FILES, CHECK_ALL));
+
+ if (((check == CHECK_ALL)) ||
+ ((check == CHECK_DIRS) && (entry->typeflag & FILE_TYPE_DIR)) ||
+ ((check == CHECK_FILES) && !(entry->typeflag & FILE_TYPE_DIR)))
+ {
+ /* Default NULL pointer if not found is fine here! */
+ return GET_UINT_FROM_POINTER(BLI_ghash_lookup(filelist->selection_state, entry->uuid));
}
+
+ return 0;
}
-void filelist_sort(struct FileList *filelist, short sort)
+unsigned int filelist_entry_select_index_get(FileList *filelist, const int index, FileCheckType check)
{
- switch (sort) {
- case FILE_SORT_ALPHA:
- qsort(filelist->filelist, filelist->numfiles, sizeof(struct direntry), compare_name);
- break;
- case FILE_SORT_TIME:
- qsort(filelist->filelist, filelist->numfiles, sizeof(struct direntry), compare_date);
- break;
- case FILE_SORT_SIZE:
- qsort(filelist->filelist, filelist->numfiles, sizeof(struct direntry), compare_size);
- break;
- case FILE_SORT_EXTENSION:
- qsort(filelist->filelist, filelist->numfiles, sizeof(struct direntry), compare_extension);
- break;
+ FileDirEntry *entry = filelist_file(filelist, index);
+
+ if (entry) {
+ return filelist_entry_select_get(filelist, entry, check);
}
- filelist_filter(filelist);
+ return 0;
}
-
-bool filelist_islibrary(struct FileList *filelist, char *dir, char *group)
+bool filelist_islibrary(struct FileList *filelist, char *dir, char **group)
{
- return BLO_is_a_library(filelist->dir, dir, group);
+ return BLO_library_path_explode(filelist->filelist.root, dir, group, NULL);
}
static int groupname_to_code(const char *group)
{
char buf[BLO_GROUP_MAX];
char *lslash;
-
+
+ BLI_assert(group);
+
BLI_strncpy(buf, group, sizeof(buf));
lslash = (char *)BLI_last_slash(buf);
if (lslash)
@@ -1042,371 +2158,556 @@ static int groupname_to_code(const char *group)
return buf[0] ? BKE_idcode_from_name(buf) : 0;
}
-
-void filelist_from_library(struct FileList *filelist)
+
+static unsigned int groupname_to_filter_id(const char *group)
{
- LinkNode *l, *names, *previews;
- struct ImBuf *ima;
- int ok, i, nprevs, nnames, idcode;
- char filename[FILE_MAX];
- char dir[FILE_MAX], group[BLO_GROUP_MAX];
-
+ int id_code = groupname_to_code(group);
+
+ return BKE_idcode_to_idfilter(id_code);
+}
+
+/**
+ * From here, we are in 'Job Context', i.e. have to be careful about sharing stuff between background working thread
+ * and main one (used by UI among other things).
+ */
+typedef struct TodoDir {
+ int level;
+ char *dir;
+} TodoDir;
+
+static int filelist_readjob_list_dir(
+ const char *root, ListBase *entries, const char *filter_glob,
+ const bool do_lib, const char *main_name, const bool skip_currpar)
+{
+ struct direntry *files;
+ int nbr_files, nbr_entries = 0;
+
+ nbr_files = BLI_filelist_dir_contents(root, &files);
+ if (files) {
+ int i = nbr_files;
+ while (i--) {
+ FileListInternEntry *entry;
+
+ if (skip_currpar && FILENAME_IS_CURRPAR(files[i].relname)) {
+ continue;
+ }
+
+ entry = MEM_callocN(sizeof(*entry), __func__);
+ entry->relpath = MEM_dupallocN(files[i].relname);
+ entry->st = files[i].s;
+
+ /* Set file type. */
+ if (S_ISDIR(files[i].s.st_mode)) {
+ entry->typeflag = FILE_TYPE_DIR;
+ }
+ else if (do_lib && BLO_has_bfile_extension(entry->relpath)) {
+ /* If we are considering .blend files as libs, promote them to directory status. */
+ char name[FILE_MAX];
+
+ entry->typeflag = FILE_TYPE_BLENDER;
+
+ BLI_join_dirfile(name, sizeof(name), root, entry->relpath);
+
+ /* prevent current file being used as acceptable dir */
+ if (BLI_path_cmp(main_name, name) != 0) {
+ entry->typeflag |= FILE_TYPE_DIR;
+ }
+ }
+ /* Otherwise, do not check extensions for directories! */
+ else if (!(entry->typeflag & FILE_TYPE_DIR)) {
+ if (filter_glob[0] && BLI_testextensie_glob(entry->relpath, filter_glob)) {
+ entry->typeflag = FILE_TYPE_OPERATOR;
+ }
+ else {
+ entry->typeflag = file_extension_type(root, entry->relpath);
+ }
+ }
+
+ BLI_addtail(entries, entry);
+ nbr_entries++;
+ }
+ BLI_filelist_free(files, nbr_files);
+ }
+ return nbr_entries;
+}
+
+static int filelist_readjob_list_lib(const char *root, ListBase *entries, const bool skip_currpar)
+{
+ FileListInternEntry *entry;
+ LinkNode *ln, *names;
+ int i, nnames, idcode = 0, nbr_entries = 0;
+ char dir[FILE_MAX], *group;
+ bool ok;
+
+ struct BlendHandle *libfiledata = NULL;
+
/* name test */
- ok = filelist_islibrary(filelist, dir, group);
+ ok = BLO_library_path_explode(root, dir, &group, NULL);
if (!ok) {
- /* free */
- if (filelist->libfiledata) BLO_blendhandle_close(filelist->libfiledata);
- filelist->libfiledata = NULL;
- return;
+ return nbr_entries;
}
-
- BLI_strncpy(filename, G.main->name, sizeof(filename));
/* there we go */
- /* for the time being only read filedata when libfiledata==0 */
- if (filelist->libfiledata == NULL) {
- filelist->libfiledata = BLO_blendhandle_from_file(dir, NULL);
- if (filelist->libfiledata == NULL) return;
+ libfiledata = BLO_blendhandle_from_file(dir, NULL);
+ if (libfiledata == NULL) {
+ return nbr_entries;
}
-
- idcode = groupname_to_code(group);
-
- /* memory for strings is passed into filelist[i].relname
- * and freed in freefilelist */
- if (idcode) {
- previews = BLO_blendhandle_get_previews(filelist->libfiledata, idcode, &nprevs);
- names = BLO_blendhandle_get_datablock_names(filelist->libfiledata, idcode, &nnames);
- /* ugh, no rewind, need to reopen */
- BLO_blendhandle_close(filelist->libfiledata);
- filelist->libfiledata = BLO_blendhandle_from_file(dir, NULL);
-
+
+ /* memory for strings is passed into filelist[i].entry->relpath and freed in filelist_entry_free. */
+ if (group) {
+ idcode = groupname_to_code(group);
+ names = BLO_blendhandle_get_datablock_names(libfiledata, idcode, &nnames);
}
else {
- previews = NULL;
- nprevs = 0;
- names = BLO_blendhandle_get_linkable_groups(filelist->libfiledata);
- nnames = BLI_linklist_length(names);
+ names = BLO_blendhandle_get_linkable_groups(libfiledata);
+ nnames = BLI_linklist_count(names);
}
- filelist->numfiles = nnames + 1;
- filelist->filelist = malloc(filelist->numfiles * sizeof(*filelist->filelist));
- memset(filelist->filelist, 0, filelist->numfiles * sizeof(*filelist->filelist));
+ BLO_blendhandle_close(libfiledata);
- filelist->filelist[0].relname = BLI_strdup("..");
- filelist->filelist[0].type |= S_IFDIR;
-
- for (i = 0, l = names; i < nnames; i++, l = l->next) {
- const char *blockname = l->link;
+ if (!skip_currpar) {
+ entry = MEM_callocN(sizeof(*entry), __func__);
+ entry->relpath = BLI_strdup(FILENAME_PARENT);
+ entry->typeflag |= (FILE_TYPE_BLENDERLIB | FILE_TYPE_DIR);
+ BLI_addtail(entries, entry);
+ nbr_entries++;
+ }
+
+ for (i = 0, ln = names; i < nnames; i++, ln = ln->next) {
+ const char *blockname = ln->link;
- filelist->filelist[i + 1].relname = BLI_strdup(blockname);
- if (idcode) {
- filelist->filelist[i + 1].type |= S_IFREG;
+ entry = MEM_callocN(sizeof(*entry), __func__);
+ entry->relpath = BLI_strdup(blockname);
+ entry->typeflag |= FILE_TYPE_BLENDERLIB;
+ if (!(group && idcode)) {
+ entry->typeflag |= FILE_TYPE_DIR;
+ entry->blentype = groupname_to_code(blockname);
}
else {
- filelist->filelist[i + 1].type |= S_IFDIR;
- }
- }
-
- if (previews && (nnames != nprevs)) {
- printf("filelist_from_library: error, found %d items, %d previews\n", nnames, nprevs);
- }
- else if (previews) {
- for (i = 0, l = previews; i < nnames; i++, l = l->next) {
- PreviewImage *img = l->link;
-
- if (img) {
- unsigned int w = img->w[ICON_SIZE_PREVIEW];
- unsigned int h = img->h[ICON_SIZE_PREVIEW];
- unsigned int *rect = img->rect[ICON_SIZE_PREVIEW];
-
- /* first allocate imbuf for copying preview into it */
- if (w > 0 && h > 0 && rect) {
- ima = IMB_allocImBuf(w, h, 32, IB_rect);
- memcpy(ima->rect, rect, w * h * sizeof(unsigned int));
- filelist->filelist[i + 1].image = ima;
- filelist->filelist[i + 1].flags = IMAGEFILE;
- }
- }
+ entry->blentype = idcode;
}
+ BLI_addtail(entries, entry);
+ nbr_entries++;
}
BLI_linklist_free(names, free);
- if (previews) BLI_linklist_free(previews, BKE_previewimg_freefunc);
-
- filelist_sort(filelist, FILE_SORT_ALPHA);
- BLI_strncpy(G.main->name, filename, sizeof(filename)); /* prevent G.main->name to change */
-
- filelist->filter = 0;
- filelist_filter(filelist);
+ return nbr_entries;
}
-void filelist_hideparent(struct FileList *filelist, short hide)
-{
- filelist->hide_parent = hide;
-}
-
-void filelist_from_main(struct FileList *filelist)
+#if 0
+/* Kept for reference here, in case we want to add back that feature later. We do not need it currently. */
+/* Code ***NOT*** updated for job stuff! */
+static void filelist_readjob_main_rec(struct FileList *filelist)
{
ID *id;
- struct direntry *files, *firstlib = NULL;
+ FileDirEntry *files, *firstlib = NULL;
ListBase *lb;
int a, fake, idcode, ok, totlib, totbl;
- // filelist->type = FILE_MAIN; // XXXXX TODO: add modes to filebrowser
+ // filelist->type = FILE_MAIN; // XXX TODO: add modes to filebrowser
- if (filelist->dir[0] == '/') filelist->dir[0] = 0;
-
- if (filelist->dir[0]) {
- idcode = groupname_to_code(filelist->dir);
- if (idcode == 0) filelist->dir[0] = 0;
+ BLI_assert(filelist->filelist.entries == NULL);
+
+ if (filelist->filelist.root[0] == '/') filelist->filelist.root[0] = '\0';
+
+ if (filelist->filelist.root[0]) {
+ idcode = groupname_to_code(filelist->filelist.root);
+ if (idcode == 0) filelist->filelist.root[0] = '\0';
}
-
+
if (filelist->dir[0] == 0) {
-
/* make directories */
#ifdef WITH_FREESTYLE
- filelist->numfiles = 25;
+ filelist->filelist.nbr_entries = 24;
#else
- filelist->numfiles = 24;
+ filelist->filelist.nbr_entries = 23;
#endif
- filelist->filelist = (struct direntry *)malloc(filelist->numfiles * sizeof(struct direntry));
-
- for (a = 0; a < filelist->numfiles; a++) {
- memset(&(filelist->filelist[a]), 0, sizeof(struct direntry));
- filelist->filelist[a].type |= S_IFDIR;
+ filelist_resize(filelist, filelist->filelist.nbr_entries);
+
+ for (a = 0; a < filelist->filelist.nbr_entries; a++) {
+ filelist->filelist.entries[a].typeflag |= FILE_TYPE_DIR;
}
-
- filelist->filelist[0].relname = BLI_strdup("..");
- filelist->filelist[2].relname = BLI_strdup("Scene");
- filelist->filelist[3].relname = BLI_strdup("Object");
- filelist->filelist[4].relname = BLI_strdup("Mesh");
- filelist->filelist[5].relname = BLI_strdup("Curve");
- filelist->filelist[6].relname = BLI_strdup("Metaball");
- filelist->filelist[7].relname = BLI_strdup("Material");
- filelist->filelist[8].relname = BLI_strdup("Texture");
- filelist->filelist[9].relname = BLI_strdup("Image");
- filelist->filelist[10].relname = BLI_strdup("Ika");
- filelist->filelist[11].relname = BLI_strdup("Wave");
- filelist->filelist[12].relname = BLI_strdup("Lattice");
- filelist->filelist[13].relname = BLI_strdup("Lamp");
- filelist->filelist[14].relname = BLI_strdup("Camera");
- filelist->filelist[15].relname = BLI_strdup("Ipo");
- filelist->filelist[16].relname = BLI_strdup("World");
- filelist->filelist[17].relname = BLI_strdup("Screen");
- filelist->filelist[18].relname = BLI_strdup("VFont");
- filelist->filelist[19].relname = BLI_strdup("Text");
- filelist->filelist[20].relname = BLI_strdup("Armature");
- filelist->filelist[21].relname = BLI_strdup("Action");
- filelist->filelist[22].relname = BLI_strdup("NodeTree");
- filelist->filelist[23].relname = BLI_strdup("Speaker");
+
+ filelist->filelist.entries[0].entry->relpath = BLI_strdup(FILENAME_PARENT);
+ filelist->filelist.entries[1].entry->relpath = BLI_strdup("Scene");
+ filelist->filelist.entries[2].entry->relpath = BLI_strdup("Object");
+ filelist->filelist.entries[3].entry->relpath = BLI_strdup("Mesh");
+ filelist->filelist.entries[4].entry->relpath = BLI_strdup("Curve");
+ filelist->filelist.entries[5].entry->relpath = BLI_strdup("Metaball");
+ filelist->filelist.entries[6].entry->relpath = BLI_strdup("Material");
+ filelist->filelist.entries[7].entry->relpath = BLI_strdup("Texture");
+ filelist->filelist.entries[8].entry->relpath = BLI_strdup("Image");
+ filelist->filelist.entries[9].entry->relpath = BLI_strdup("Ika");
+ filelist->filelist.entries[10].entry->relpath = BLI_strdup("Wave");
+ filelist->filelist.entries[11].entry->relpath = BLI_strdup("Lattice");
+ filelist->filelist.entries[12].entry->relpath = BLI_strdup("Lamp");
+ filelist->filelist.entries[13].entry->relpath = BLI_strdup("Camera");
+ filelist->filelist.entries[14].entry->relpath = BLI_strdup("Ipo");
+ filelist->filelist.entries[15].entry->relpath = BLI_strdup("World");
+ filelist->filelist.entries[16].entry->relpath = BLI_strdup("Screen");
+ filelist->filelist.entries[17].entry->relpath = BLI_strdup("VFont");
+ filelist->filelist.entries[18].entry->relpath = BLI_strdup("Text");
+ filelist->filelist.entries[19].entry->relpath = BLI_strdup("Armature");
+ filelist->filelist.entries[20].entry->relpath = BLI_strdup("Action");
+ filelist->filelist.entries[21].entry->relpath = BLI_strdup("NodeTree");
+ filelist->filelist.entries[22].entry->relpath = BLI_strdup("Speaker");
#ifdef WITH_FREESTYLE
- filelist->filelist[24].relname = BLI_strdup("FreestyleLineStyle");
+ filelist->filelist.entries[23].entry->relpath = BLI_strdup("FreestyleLineStyle");
#endif
- filelist_sort(filelist, FILE_SORT_ALPHA);
}
else {
-
/* make files */
- idcode = groupname_to_code(filelist->dir);
-
+ idcode = groupname_to_code(filelist->filelist.root);
+
lb = which_libbase(G.main, idcode);
if (lb == NULL) return;
-
- id = lb->first;
- filelist->numfiles = 0;
- while (id) {
- if (!filelist->hide_dot || id->name[2] != '.') {
- filelist->numfiles++;
+
+ filelist->filelist.nbr_entries = 0;
+ for (id = lb->first; id; id = id->next) {
+ if (!(filelist->filter_data.flags & FLF_HIDE_DOT) || id->name[2] != '.') {
+ filelist->filelist.nbr_entries++;
}
-
- id = id->next;
}
-
- /* XXXXX TODO: if databrowse F4 or append/link filelist->hide_parent has to be set */
- if (!filelist->hide_parent) filelist->numfiles += 1;
- filelist->filelist = filelist->numfiles > 0 ? (struct direntry *)malloc(filelist->numfiles * sizeof(struct direntry)) : NULL;
- files = filelist->filelist;
-
- if (!filelist->hide_parent) {
- memset(&(filelist->filelist[0]), 0, sizeof(struct direntry));
- filelist->filelist[0].relname = BLI_strdup("..");
- filelist->filelist[0].type |= S_IFDIR;
+ /* XXX TODO: if databrowse F4 or append/link filelist->flags & FLF_HIDE_PARENT has to be set */
+ if (!(filelist->filter_data.flags & FLF_HIDE_PARENT))
+ filelist->filelist.nbr_entries++;
+
+ if (filelist->filelist.nbr_entries > 0) {
+ filelist_resize(filelist, filelist->filelist.nbr_entries);
+ }
+
+ files = filelist->filelist.entries;
+ if (!(filelist->filter_data.flags & FLF_HIDE_PARENT)) {
+ files->entry->relpath = BLI_strdup(FILENAME_PARENT);
+ files->typeflag |= FILE_TYPE_DIR;
+
files++;
}
-
- id = lb->first;
+
totlib = totbl = 0;
-
- while (id) {
+ for (id = lb->first; id; id = id->next) {
ok = 1;
if (ok) {
- if (!filelist->hide_dot || id->name[2] != '.') {
- memset(files, 0, sizeof(struct direntry));
+ if (!(filelist->filter_data.flags & FLF_HIDE_DOT) || id->name[2] != '.') {
if (id->lib == NULL) {
- files->relname = BLI_strdup(id->name + 2);
+ files->entry->relpath = BLI_strdup(id->name + 2);
}
else {
- files->relname = MEM_mallocN(FILE_MAX + (MAX_ID_NAME - 2), "filename for lib");
- BLI_snprintf(files->relname, FILE_MAX + (MAX_ID_NAME - 2) + 3, "%s | %s", id->lib->name, id->name + 2);
+ char relname[FILE_MAX + (MAX_ID_NAME - 2) + 3];
+ BLI_snprintf(relname, sizeof(relname), "%s | %s", id->lib->name, id->name + 2);
+ files->entry->relpath = BLI_strdup(relname);
}
- files->type |= S_IFREG;
-#if 0 /* XXXXX TODO show the selection status of the objects */
+// files->type |= S_IFREG;
+#if 0 /* XXX TODO show the selection status of the objects */
if (!filelist->has_func) { /* F4 DATA BROWSE */
if (idcode == ID_OB) {
- if ( ((Object *)id)->flag & SELECT) files->selflag |= SELECTED_FILE;
+ if ( ((Object *)id)->flag & SELECT) files->entry->selflag |= FILE_SEL_SELECTED;
}
else if (idcode == ID_SCE) {
- if ( ((Scene *)id)->r.scemode & R_BG_RENDER) files->selflag |= SELECTED_FILE;
+ if ( ((Scene *)id)->r.scemode & R_BG_RENDER) files->entry->selflag |= FILE_SEL_SELECTED;
}
}
#endif
- files->nr = totbl + 1;
- files->poin = id;
+// files->entry->nr = totbl + 1;
+ files->entry->poin = id;
fake = id->flag & LIB_FAKEUSER;
if (idcode == ID_MA || idcode == ID_TE || idcode == ID_LA || idcode == ID_WO || idcode == ID_IM) {
- files->flags |= IMAGEFILE;
+ files->typeflag |= FILE_TYPE_IMAGE;
}
- if (id->lib && fake) BLI_snprintf(files->extra, sizeof(files->extra), "LF %d", id->us);
- else if (id->lib) BLI_snprintf(files->extra, sizeof(files->extra), "L %d", id->us);
- else if (fake) BLI_snprintf(files->extra, sizeof(files->extra), "F %d", id->us);
- else BLI_snprintf(files->extra, sizeof(files->extra), " %d", id->us);
-
+// if (id->lib && fake) BLI_snprintf(files->extra, sizeof(files->entry->extra), "LF %d", id->us);
+// else if (id->lib) BLI_snprintf(files->extra, sizeof(files->entry->extra), "L %d", id->us);
+// else if (fake) BLI_snprintf(files->extra, sizeof(files->entry->extra), "F %d", id->us);
+// else BLI_snprintf(files->extra, sizeof(files->entry->extra), " %d", id->us);
+
if (id->lib) {
if (totlib == 0) firstlib = files;
totlib++;
}
-
+
files++;
}
totbl++;
}
-
- id = id->next;
}
-
+
/* only qsort of library blocks */
if (totlib > 1) {
- qsort(firstlib, totlib, sizeof(struct direntry), compare_name);
+ qsort(firstlib, totlib, sizeof(*files), compare_name);
}
}
- filelist->filter = 0;
- filelist_filter(filelist);
}
+#endif
-static void thumbnail_joblist_free(ThumbnailJob *tj)
+static void filelist_readjob_do(
+ const bool do_lib,
+ FileList *filelist, const char *main_name, short *stop, short *do_update, float *progress, ThreadMutex *lock)
{
- FileImage *limg = tj->loadimages.first;
-
- /* free the images not yet copied to the filelist -> these will get freed with the filelist */
- for (; limg; limg = limg->next) {
- if ((limg->img) && (!limg->done)) {
- IMB_freeImBuf(limg->img);
+ ListBase entries = {0};
+ BLI_Stack *todo_dirs;
+ TodoDir *td_dir;
+ char dir[FILE_MAX_LIBEXTRA];
+ char filter_glob[64]; /* TODO should be define! */
+ const char *root = filelist->filelist.root;
+ const int max_recursion = filelist->max_recursion;
+ int nbr_done_dirs = 0, nbr_todo_dirs = 1;
+
+// BLI_assert(filelist->filtered == NULL);
+ BLI_assert(BLI_listbase_is_empty(&filelist->filelist.entries) && (filelist->filelist.nbr_entries == 0));
+
+ todo_dirs = BLI_stack_new(sizeof(*td_dir), __func__);
+ td_dir = BLI_stack_push_r(todo_dirs);
+ td_dir->level = 1;
+
+ BLI_strncpy(dir, filelist->filelist.root, sizeof(dir));
+ BLI_strncpy(filter_glob, filelist->filter_data.filter_glob, sizeof(filter_glob));
+
+ BLI_cleanup_dir(main_name, dir);
+ td_dir->dir = BLI_strdup(dir);
+
+ while (!BLI_stack_is_empty(todo_dirs) && !(*stop)) {
+ FileListInternEntry *entry;
+ int nbr_entries = 0;
+ bool is_lib = do_lib;
+
+ char *subdir;
+ int recursion_level;
+ bool skip_currpar;
+
+ td_dir = BLI_stack_peek(todo_dirs);
+ subdir = td_dir->dir;
+ recursion_level = td_dir->level;
+ skip_currpar = (recursion_level > 1);
+
+ BLI_stack_discard(todo_dirs);
+
+ if (do_lib) {
+ nbr_entries = filelist_readjob_list_lib(subdir, &entries, skip_currpar);
+ }
+ if (!nbr_entries) {
+ is_lib = false;
+ nbr_entries = filelist_readjob_list_dir(subdir, &entries, filter_glob, do_lib, main_name, skip_currpar);
+ }
+
+ for (entry = entries.first; entry; entry = entry->next) {
+ BLI_join_dirfile(dir, sizeof(dir), subdir, entry->relpath);
+ BLI_cleanup_file(root, dir);
+
+ /* Generate our entry uuid. Abusing uuid as an uint32, shall be more than enough here,
+ * things would crash way before we overflow that counter!
+ * Using an atomic operation to avoid having to lock thread...
+ * Note that we do not really need this here currently, since there is a single listing thread, but better
+ * remain consistent about threading! */
+ *((uint32_t *)entry->uuid) = atomic_add_uint32((uint32_t *)filelist->filelist_intern.curr_uuid, 1);
+
+ BLI_path_rel(dir, root);
+ /* Only thing we change in direntry here, so we need to free it first. */
+ MEM_freeN(entry->relpath);
+ entry->relpath = BLI_strdup(dir + 2); /* + 2 to remove '//' added by BLI_path_rel */
+ entry->name = BLI_strdup(fileentry_uiname(root, entry->relpath, entry->typeflag, dir));
+
+ /* Here we decide whether current filedirentry is to be listed too, or not. */
+ if (max_recursion && (is_lib || (recursion_level <= max_recursion))) {
+ if (((entry->typeflag & FILE_TYPE_DIR) == 0) || FILENAME_IS_CURRPAR(entry->relpath)) {
+ /* Skip... */
+ }
+ else if (!is_lib && (recursion_level >= max_recursion) &&
+ ((entry->typeflag & (FILE_TYPE_BLENDER | FILE_TYPE_BLENDER_BACKUP)) == 0))
+ {
+ /* Do not recurse in real directories in this case, only in .blend libs. */
+ }
+ else {
+ /* We have a directory we want to list, add it to todo list! */
+ BLI_join_dirfile(dir, sizeof(dir), root, entry->relpath);
+ BLI_cleanup_dir(main_name, dir);
+ td_dir = BLI_stack_push_r(todo_dirs);
+ td_dir->level = recursion_level + 1;
+ td_dir->dir = BLI_strdup(dir);
+ nbr_todo_dirs++;
+ }
+ }
+ }
+
+ if (nbr_entries) {
+ BLI_mutex_lock(lock);
+
+ *do_update = true;
+
+ BLI_movelisttolist(&filelist->filelist.entries, &entries);
+ filelist->filelist.nbr_entries += nbr_entries;
+
+ BLI_mutex_unlock(lock);
}
+
+ nbr_done_dirs++;
+ *progress = (float)nbr_done_dirs / (float)nbr_todo_dirs;
+ MEM_freeN(subdir);
}
- BLI_freelistN(&tj->loadimages);
+
+ /* If we were interrupted by stop, stack may not be empty and we need to free pending dir paths. */
+ while (!BLI_stack_is_empty(todo_dirs)) {
+ td_dir = BLI_stack_peek(todo_dirs);
+ MEM_freeN(td_dir->dir);
+ BLI_stack_discard(todo_dirs);
+ }
+ BLI_stack_free(todo_dirs);
}
-static void thumbnails_startjob(void *tjv, short *stop, short *do_update, float *UNUSED(progress))
+static void filelist_readjob_dir(
+ FileList *filelist, const char *main_name, short *stop, short *do_update, float *progress, ThreadMutex *lock)
{
- ThumbnailJob *tj = tjv;
- FileImage *limg = tj->loadimages.first;
+ filelist_readjob_do(false, filelist, main_name, stop, do_update, progress, lock);
+}
- tj->stop = stop;
- tj->do_update = do_update;
+static void filelist_readjob_lib(
+ FileList *filelist, const char *main_name, short *stop, short *do_update, float *progress, ThreadMutex *lock)
+{
+ filelist_readjob_do(true, filelist, main_name, stop, do_update, progress, lock);
+}
- while ((*stop == 0) && (limg)) {
- if (limg->flags & IMAGEFILE) {
- limg->img = IMB_thumb_manage(limg->path, THB_NORMAL, THB_SOURCE_IMAGE);
- }
- else if (limg->flags & (BLENDERFILE | BLENDERFILE_BACKUP)) {
- limg->img = IMB_thumb_manage(limg->path, THB_NORMAL, THB_SOURCE_BLEND);
- }
- else if (limg->flags & MOVIEFILE) {
- limg->img = IMB_thumb_manage(limg->path, THB_NORMAL, THB_SOURCE_MOVIE);
- if (!limg->img) {
- /* remember that file can't be loaded via IMB_open_anim */
- limg->flags &= ~MOVIEFILE;
- limg->flags |= MOVIEFILE_ICON;
- }
- }
- *do_update = true;
- PIL_sleep_ms(10);
- limg = limg->next;
- }
+static void filelist_readjob_main(
+ FileList *filelist, const char *main_name, short *stop, short *do_update, float *progress, ThreadMutex *lock)
+{
+ /* TODO! */
+ filelist_readjob_dir(filelist, main_name, stop, do_update, progress, lock);
}
-static void thumbnails_update(void *tjv)
+
+typedef struct FileListReadJob {
+ ThreadMutex lock;
+ char main_name[FILE_MAX];
+ struct FileList *filelist;
+ struct FileList *tmp_filelist; /* XXX We may use a simpler struct here... just a linked list and root path? */
+} FileListReadJob;
+
+static void filelist_readjob_startjob(void *flrjv, short *stop, short *do_update, float *progress)
{
- ThumbnailJob *tj = tjv;
+ FileListReadJob *flrj = flrjv;
- if (tj->filelist && tj->filelist->filelist) {
- FileImage *limg = tj->loadimages.first;
- while (limg) {
- if (!limg->done && limg->img) {
- tj->filelist->filelist[limg->index].image = limg->img;
- /* update flag for movie files where thumbnail can't be created */
- if (limg->flags & MOVIEFILE_ICON) {
- tj->filelist->filelist[limg->index].flags &= ~MOVIEFILE;
- tj->filelist->filelist[limg->index].flags |= MOVIEFILE_ICON;
- }
- limg->done = true;
- }
- limg = limg->next;
- }
+// printf("START filelist reading (%d files, main thread: %d)\n",
+// flrj->filelist->filelist.nbr_entries, BLI_thread_is_main());
+
+ BLI_mutex_lock(&flrj->lock);
+
+ BLI_assert((flrj->tmp_filelist == NULL) && flrj->filelist);
+
+ flrj->tmp_filelist = MEM_dupallocN(flrj->filelist);
+
+ BLI_listbase_clear(&flrj->tmp_filelist->filelist.entries);
+ flrj->tmp_filelist->filelist.nbr_entries = 0;
+
+ flrj->tmp_filelist->filelist_intern.filtered = NULL;
+ BLI_listbase_clear(&flrj->tmp_filelist->filelist_intern.entries);
+ memset(flrj->tmp_filelist->filelist_intern.curr_uuid, 0, sizeof(flrj->tmp_filelist->filelist_intern.curr_uuid));
+
+ flrj->tmp_filelist->libfiledata = NULL;
+ memset(&flrj->tmp_filelist->filelist_cache, 0, sizeof(flrj->tmp_filelist->filelist_cache));
+ flrj->tmp_filelist->selection_state = NULL;
+
+ BLI_mutex_unlock(&flrj->lock);
+
+ flrj->tmp_filelist->read_jobf(flrj->tmp_filelist, flrj->main_name, stop, do_update, progress, &flrj->lock);
+}
+
+static void filelist_readjob_update(void *flrjv)
+{
+ FileListReadJob *flrj = flrjv;
+ FileListIntern *fl_intern = &flrj->filelist->filelist_intern;
+ ListBase new_entries = {NULL};
+ int nbr_entries, new_nbr_entries = 0;
+
+ BLI_movelisttolist(&new_entries, &fl_intern->entries);
+ nbr_entries = flrj->filelist->filelist.nbr_entries;
+
+ BLI_mutex_lock(&flrj->lock);
+
+ if (flrj->tmp_filelist->filelist.nbr_entries) {
+ /* We just move everything out of 'thread context' into final list. */
+ new_nbr_entries = flrj->tmp_filelist->filelist.nbr_entries;
+ BLI_movelisttolist(&new_entries, &flrj->tmp_filelist->filelist.entries);
+ flrj->tmp_filelist->filelist.nbr_entries = 0;
}
+
+ BLI_mutex_unlock(&flrj->lock);
+
+ if (new_nbr_entries) {
+ /* Do not clear selection cache, we can assume already 'selected' uuids are still valid! */
+ filelist_clear_ex(flrj->filelist, true, false);
+
+ flrj->filelist->flags |= (FL_NEED_SORTING | FL_NEED_FILTERING);
+ }
+
+ /* if no new_nbr_entries, this is NOP */
+ BLI_movelisttolist(&fl_intern->entries, &new_entries);
+ flrj->filelist->filelist.nbr_entries = nbr_entries + new_nbr_entries;
}
-static void thumbnails_free(void *tjv)
+static void filelist_readjob_endjob(void *flrjv)
{
- ThumbnailJob *tj = tjv;
- thumbnail_joblist_free(tj);
- MEM_freeN(tj);
+ FileListReadJob *flrj = flrjv;
+
+ /* In case there would be some dangling update... */
+ filelist_readjob_update(flrjv);
+
+ flrj->filelist->flags &= ~FL_IS_PENDING;
+ flrj->filelist->flags |= FL_IS_READY;
}
+static void filelist_readjob_free(void *flrjv)
+{
+ FileListReadJob *flrj = flrjv;
+
+// printf("END filelist reading (%d files)\n", flrj->filelist->filelist.nbr_entries);
+
+ if (flrj->tmp_filelist) {
+ /* tmp_filelist shall never ever be filtered! */
+ BLI_assert(flrj->tmp_filelist->filelist.nbr_entries == 0);
+ BLI_assert(BLI_listbase_is_empty(&flrj->tmp_filelist->filelist.entries));
-void thumbnails_start(FileList *filelist, const bContext *C)
+ filelist_freelib(flrj->tmp_filelist);
+ filelist_free(flrj->tmp_filelist);
+ MEM_freeN(flrj->tmp_filelist);
+ }
+
+ BLI_mutex_end(&flrj->lock);
+
+ MEM_freeN(flrj);
+}
+
+void filelist_readjob_start(FileList *filelist, const bContext *C)
{
wmJob *wm_job;
- ThumbnailJob *tj;
- int idx;
-
+ FileListReadJob *flrj;
+
/* prepare job data */
- tj = MEM_callocN(sizeof(ThumbnailJob), "thumbnails\n");
- tj->filelist = filelist;
- for (idx = 0; idx < filelist->numfiles; idx++) {
- if (!filelist->filelist[idx].image) {
- if ((filelist->filelist[idx].flags & (IMAGEFILE | MOVIEFILE | BLENDERFILE | BLENDERFILE_BACKUP))) {
- FileImage *limg = MEM_callocN(sizeof(FileImage), "loadimage");
- BLI_strncpy(limg->path, filelist->filelist[idx].path, FILE_MAX);
- limg->index = idx;
- limg->flags = filelist->filelist[idx].flags;
- BLI_addtail(&tj->loadimages, limg);
- }
- }
- }
+ flrj = MEM_callocN(sizeof(*flrj), __func__);
+ flrj->filelist = filelist;
+ BLI_strncpy(flrj->main_name, G.main->name, sizeof(flrj->main_name));
+
+ filelist->flags &= ~(FL_FORCE_RESET | FL_IS_READY);
+ filelist->flags |= FL_IS_PENDING;
- BKE_reports_init(&tj->reports, RPT_PRINT);
+ BLI_mutex_init(&flrj->lock);
/* setup job */
- wm_job = WM_jobs_get(CTX_wm_manager(C), CTX_wm_window(C), filelist, "Thumbnails",
- 0, WM_JOB_TYPE_FILESEL_THUMBNAIL);
- WM_jobs_customdata_set(wm_job, tj, thumbnails_free);
- WM_jobs_timer(wm_job, 0.5, NC_WINDOW, NC_WINDOW);
- WM_jobs_callbacks(wm_job, thumbnails_startjob, NULL, thumbnails_update, NULL);
+ wm_job = WM_jobs_get(CTX_wm_manager(C), CTX_wm_window(C), CTX_wm_area(C), "Listing Dirs...",
+ WM_JOB_PROGRESS, WM_JOB_TYPE_FILESEL_READDIR);
+ WM_jobs_customdata_set(wm_job, flrj, filelist_readjob_free);
+ WM_jobs_timer(wm_job, 0.01, NC_SPACE | ND_SPACE_FILE_LIST, NC_SPACE | ND_SPACE_FILE_LIST);
+ WM_jobs_callbacks(wm_job, filelist_readjob_startjob, NULL, filelist_readjob_update, filelist_readjob_endjob);
/* start the job */
WM_jobs_start(CTX_wm_manager(C), wm_job);
}
-void thumbnails_stop(wmWindowManager *wm, FileList *filelist)
+void filelist_readjob_stop(wmWindowManager *wm, ScrArea *sa)
{
- WM_jobs_kill(wm, filelist, NULL);
+ WM_jobs_kill_type(wm, sa, WM_JOB_TYPE_FILESEL_READDIR);
}
-int thumbnails_running(wmWindowManager *wm, FileList *filelist)
+int filelist_readjob_running(wmWindowManager *wm, ScrArea *sa)
{
- return WM_jobs_test(wm, filelist, WM_JOB_TYPE_FILESEL_THUMBNAIL);
+ return WM_jobs_test(wm, sa, WM_JOB_TYPE_FILESEL_READDIR);
}
diff --git a/source/blender/editors/space_file/filelist.h b/source/blender/editors/space_file/filelist.h
index c37bb882168..d70faab1d6a 100644
--- a/source/blender/editors/space_file/filelist.h
+++ b/source/blender/editors/space_file/filelist.h
@@ -40,14 +40,10 @@ extern "C" {
struct BlendHandle;
struct FileList;
struct FileSelection;
-struct FolderList;
-struct Main;
-struct ReportList;
-struct Scene;
-struct direntry;
-struct rcti;
struct wmWindowManager;
+struct FileDirEntry;
+
typedef enum FileSelType {
FILE_SEL_REMOVE = 0,
FILE_SEL_ADD = 1,
@@ -60,50 +56,69 @@ typedef enum FileCheckType {
CHECK_ALL = 3
} FileCheckType;
-struct FileList * filelist_new(short type);
+struct ListBase * folderlist_new(void);
+void folderlist_free(struct ListBase *folderlist);
+struct ListBase * folderlist_duplicate(ListBase *folderlist);
+void folderlist_popdir(struct ListBase *folderlist, char *dir);
+void folderlist_pushdir(struct ListBase *folderlist, const char *dir);
+const char * folderlist_peeklastdir(struct ListBase *folderdist);
+int folderlist_clear_next(struct SpaceFile *sfile);
+
+
+void filelist_setsorting(struct FileList *filelist, const short sort);
+void filelist_sort(struct FileList *filelist);
+
+void filelist_setfilter_options(struct FileList *filelist, const bool hide_dot, const bool hide_parent,
+ const unsigned int filter, const unsigned int filter_id,
+ const char *filter_glob, const char *filter_search);
+void filelist_filter(struct FileList *filelist);
+
void filelist_init_icons(void);
void filelist_free_icons(void);
-int filelist_find(struct FileList *filelist, const char *file);
+void filelist_imgsize(struct FileList *filelist, short w, short h);
+struct ImBuf * filelist_getimage(struct FileList *filelist, const int index);
+struct ImBuf * filelist_geticon_image(struct FileList *filelist, const int index);
+int filelist_geticon(struct FileList *filelist, const int index, const bool is_main);
+
+struct FileList * filelist_new(short type);
+void filelist_clear(struct FileList *filelist);
+void filelist_clear_ex(struct FileList *filelist, const bool do_cache, const bool do_selection);
void filelist_free(struct FileList *filelist);
-void filelist_sort(struct FileList *filelist, short sort);
-int filelist_numfiles(struct FileList *filelist);
+
const char * filelist_dir(struct FileList *filelist);
-void filelist_setdir(struct FileList *filelist, const char *dir);
-struct direntry * filelist_file(struct FileList *filelist, int index);
-void filelist_select(struct FileList *filelist, FileSelection *sel, FileSelType select, unsigned int flag, FileCheckType check);
-void filelist_select_file(struct FileList *filelist, int index, FileSelType select, unsigned int flag, FileCheckType check);
-bool filelist_is_selected(struct FileList *filelist, int index, FileCheckType check);
-void filelist_hidedot(struct FileList *filelist, short hide);
-void filelist_setfilter(struct FileList *filelist, unsigned int filter);
-void filelist_setfilter_types(struct FileList *filelist, const char *filter_glob);
-void filelist_filter(struct FileList *filelist);
-void filelist_imgsize(struct FileList *filelist, short w, short h);
-struct ImBuf * filelist_getimage(struct FileList *filelist, int index);
-struct ImBuf * filelist_geticon(struct FileList *filelist, int index);
-short filelist_changed(struct FileList *filelist);
-void filelist_readdir(struct FileList *filelist);
+void filelist_setdir(struct FileList *filelist, char *r_dir);
+int filelist_files_ensure(struct FileList *filelist);
int filelist_empty(struct FileList *filelist);
-void filelist_parent(struct FileList *filelist);
+FileDirEntry * filelist_file(struct FileList *filelist, int index);
+int filelist_file_findpath(struct FileList *filelist, const char *file);
+FileDirEntry * filelist_entry_find_uuid(struct FileList *filelist, const int uuid[4]);
+void filelist_file_cache_slidingwindow_set(struct FileList *filelist, size_t window_size);
+bool filelist_file_cache_block(struct FileList *filelist, const int index);
+
+bool filelist_force_reset(struct FileList *filelist);
+bool filelist_pending(struct FileList *filelist);
+bool filelist_is_ready(struct FileList *filelist);
+
+unsigned int filelist_entry_select_set(const struct FileList *filelist, const struct FileDirEntry *entry, FileSelType select, unsigned int flag, FileCheckType check);
+void filelist_entry_select_index_set(struct FileList *filelist, const int index, FileSelType select, unsigned int flag, FileCheckType check);
+void filelist_entries_select_index_range_set(struct FileList *filelist, FileSelection *sel, FileSelType select, unsigned int flag, FileCheckType check);
+unsigned int filelist_entry_select_get(struct FileList *filelist, struct FileDirEntry *entry, FileCheckType check);
+unsigned int filelist_entry_select_index_get(struct FileList *filelist, const int index, FileCheckType check);
+
+void filelist_setrecursion(struct FileList *filelist, const int recursion_level);
struct BlendHandle *filelist_lib(struct FileList *filelist);
-bool filelist_islibrary(struct FileList *filelist, char *dir, char *group);
-void filelist_from_main(struct FileList *filelist);
-void filelist_from_library(struct FileList *filelist);
+bool filelist_islibrary(struct FileList *filelist, char *dir, char **group);
void filelist_freelib(struct FileList *filelist);
-void filelist_hideparent(struct FileList *filelist, short hide);
-struct ListBase * folderlist_new(void);
-void folderlist_free(struct ListBase *folderlist);
-struct ListBase * folderlist_duplicate(ListBase *folderlist);
-void folderlist_popdir(struct ListBase *folderlist, char *dir);
-void folderlist_pushdir(struct ListBase *folderlist, const char *dir);
-const char * folderlist_peeklastdir(struct ListBase *folderdist);
-int folderlist_clear_next(struct SpaceFile *sfile);
+void filelist_readjob_start(struct FileList *filelist, const struct bContext *C);
+void filelist_readjob_stop(struct wmWindowManager *wm, struct ScrArea *sa);
+int filelist_readjob_running(struct wmWindowManager *wm, struct ScrArea *sa);
-void thumbnails_start(struct FileList *filelist, const struct bContext *C);
-void thumbnails_stop(struct wmWindowManager *wm, struct FileList *filelist);
-int thumbnails_running(struct wmWindowManager *wm, struct FileList *filelist);
+bool filelist_cache_previews_update(struct FileList *filelist);
+void filelist_cache_previews_set(struct FileList *filelist, const bool use_previews);
+bool filelist_cache_previews_running(struct FileList *filelist);
#ifdef __cplusplus
}
diff --git a/source/blender/editors/space_file/filesel.c b/source/blender/editors/space_file/filesel.c
index afe3f29e9bc..da24f1ce95d 100644
--- a/source/blender/editors/space_file/filesel.c
+++ b/source/blender/editors/space_file/filesel.c
@@ -58,6 +58,7 @@
#include "BLI_fileops_types.h"
#include "BLI_fnmatch.h"
+#include "BKE_appdir.h"
#include "BKE_context.h"
#include "BKE_global.h"
#include "BKE_main.h"
@@ -101,6 +102,8 @@ short ED_fileselect_set_params(SpaceFile *sfile)
/* set path to most recently opened .blend */
BLI_split_dirfile(G.main->name, sfile->params->dir, sfile->params->file, sizeof(sfile->params->dir), sizeof(sfile->params->file));
sfile->params->filter_glob[0] = '\0';
+ /* set the default thumbnails size */
+ sfile->params->thumbnail_size = 128;
}
params = sfile->params;
@@ -116,10 +119,12 @@ short ED_fileselect_set_params(SpaceFile *sfile)
BLI_strncpy_utf8(params->title, RNA_struct_ui_name(op->type->srna), sizeof(params->title));
- if (RNA_struct_find_property(op->ptr, "filemode"))
- params->type = RNA_int_get(op->ptr, "filemode");
- else
+ if ((prop = RNA_struct_find_property(op->ptr, "filemode"))) {
+ params->type = RNA_property_int_get(op->ptr, prop);
+ }
+ else {
params->type = FILE_SPECIAL;
+ }
if (is_filepath && RNA_struct_property_is_set_ex(op->ptr, "filepath", false)) {
char name[FILE_MAX];
@@ -157,30 +162,32 @@ short ED_fileselect_set_params(SpaceFile *sfile)
params->filter = 0;
if ((prop = RNA_struct_find_property(op->ptr, "filter_blender")))
- params->filter |= RNA_property_boolean_get(op->ptr, prop) ? BLENDERFILE : 0;
+ params->filter |= RNA_property_boolean_get(op->ptr, prop) ? FILE_TYPE_BLENDER : 0;
+ if ((prop = RNA_struct_find_property(op->ptr, "filter_blenlib")))
+ params->filter |= RNA_property_boolean_get(op->ptr, prop) ? FILE_TYPE_BLENDERLIB : 0;
if ((prop = RNA_struct_find_property(op->ptr, "filter_backup")))
- params->filter |= RNA_property_boolean_get(op->ptr, prop) ? BLENDERFILE_BACKUP : 0;
+ params->filter |= RNA_property_boolean_get(op->ptr, prop) ? FILE_TYPE_BLENDER_BACKUP : 0;
if ((prop = RNA_struct_find_property(op->ptr, "filter_image")))
- params->filter |= RNA_property_boolean_get(op->ptr, prop) ? IMAGEFILE : 0;
+ params->filter |= RNA_property_boolean_get(op->ptr, prop) ? FILE_TYPE_IMAGE : 0;
if ((prop = RNA_struct_find_property(op->ptr, "filter_movie")))
- params->filter |= RNA_property_boolean_get(op->ptr, prop) ? MOVIEFILE : 0;
+ params->filter |= RNA_property_boolean_get(op->ptr, prop) ? FILE_TYPE_MOVIE : 0;
if ((prop = RNA_struct_find_property(op->ptr, "filter_python")))
- params->filter |= RNA_property_boolean_get(op->ptr, prop) ? PYSCRIPTFILE : 0;
+ params->filter |= RNA_property_boolean_get(op->ptr, prop) ? FILE_TYPE_PYSCRIPT : 0;
if ((prop = RNA_struct_find_property(op->ptr, "filter_font")))
- params->filter |= RNA_property_boolean_get(op->ptr, prop) ? FTFONTFILE : 0;
+ params->filter |= RNA_property_boolean_get(op->ptr, prop) ? FILE_TYPE_FTFONT : 0;
if ((prop = RNA_struct_find_property(op->ptr, "filter_sound")))
- params->filter |= RNA_property_boolean_get(op->ptr, prop) ? SOUNDFILE : 0;
+ params->filter |= RNA_property_boolean_get(op->ptr, prop) ? FILE_TYPE_SOUND : 0;
if ((prop = RNA_struct_find_property(op->ptr, "filter_text")))
- params->filter |= RNA_property_boolean_get(op->ptr, prop) ? TEXTFILE : 0;
+ params->filter |= RNA_property_boolean_get(op->ptr, prop) ? FILE_TYPE_TEXT : 0;
if ((prop = RNA_struct_find_property(op->ptr, "filter_folder")))
- params->filter |= RNA_property_boolean_get(op->ptr, prop) ? FOLDERFILE : 0;
+ params->filter |= RNA_property_boolean_get(op->ptr, prop) ? FILE_TYPE_FOLDER : 0;
if ((prop = RNA_struct_find_property(op->ptr, "filter_btx")))
- params->filter |= RNA_property_boolean_get(op->ptr, prop) ? BTXFILE : 0;
+ params->filter |= RNA_property_boolean_get(op->ptr, prop) ? FILE_TYPE_BTX : 0;
if ((prop = RNA_struct_find_property(op->ptr, "filter_collada")))
- params->filter |= RNA_property_boolean_get(op->ptr, prop) ? COLLADAFILE : 0;
+ params->filter |= RNA_property_boolean_get(op->ptr, prop) ? FILE_TYPE_COLLADA : 0;
if ((prop = RNA_struct_find_property(op->ptr, "filter_glob"))) {
RNA_property_string_get(op->ptr, prop, params->filter_glob);
- params->filter |= (OPERATORFILE | FOLDERFILE);
+ params->filter |= (FILE_TYPE_OPERATOR | FILE_TYPE_FOLDER);
}
else {
params->filter_glob[0] = '\0';
@@ -195,6 +202,13 @@ short ED_fileselect_set_params(SpaceFile *sfile)
}
}
+ /* For now, always init filterid to 'all true' */
+ params->filter_id = FILTER_ID_AC | FILTER_ID_AR | FILTER_ID_BR | FILTER_ID_CA | FILTER_ID_CU | FILTER_ID_GD |
+ FILTER_ID_GR | FILTER_ID_IM | FILTER_ID_LA | FILTER_ID_LS | FILTER_ID_LT | FILTER_ID_MA |
+ FILTER_ID_MB | FILTER_ID_MC | FILTER_ID_ME | FILTER_ID_MSK | FILTER_ID_NT | FILTER_ID_OB |
+ FILTER_ID_PA | FILTER_ID_PAL | FILTER_ID_PC | FILTER_ID_SCE | FILTER_ID_SPK | FILTER_ID_SO |
+ FILTER_ID_TE | FILTER_ID_TXT | FILTER_ID_VF | FILTER_ID_WO;
+
if (U.uiflag & USER_HIDE_DOT) {
params->flag |= FILE_HIDE_DOT;
}
@@ -209,12 +223,20 @@ short ED_fileselect_set_params(SpaceFile *sfile)
params->flag |= RNA_boolean_get(op->ptr, "active_layer") ? FILE_ACTIVELAY : 0;
}
- if (RNA_struct_find_property(op->ptr, "display_type"))
- params->display = RNA_enum_get(op->ptr, "display_type");
+ if ((prop = RNA_struct_find_property(op->ptr, "display_type"))) {
+ params->display = RNA_property_enum_get(op->ptr, prop);
+ }
+
+ if ((prop = RNA_struct_find_property(op->ptr, "sort_method"))) {
+ params->sort = RNA_property_enum_get(op->ptr, prop);
+ }
+ else {
+ params->sort = FILE_SORT_ALPHA;
+ }
if (params->display == FILE_DEFAULTDISPLAY) {
if (U.uiflag & USER_SHOW_THUMBNAILS) {
- if (params->filter & (IMAGEFILE | MOVIEFILE))
+ if (params->filter & (FILE_TYPE_IMAGE | FILE_TYPE_MOVIE))
params->display = FILE_IMGDISPLAY;
else
params->display = FILE_SHORTDISPLAY;
@@ -225,8 +247,10 @@ short ED_fileselect_set_params(SpaceFile *sfile)
}
if (is_relative_path) {
- if (!RNA_struct_property_is_set_ex(op->ptr, "relative_path", false)) {
- RNA_boolean_set(op->ptr, "relative_path", U.flag & USER_RELPATHS);
+ if ((prop = RNA_struct_find_property(op->ptr, "relative_path"))) {
+ if (!RNA_property_is_set_ex(op->ptr, prop, false)) {
+ RNA_property_boolean_set(op->ptr, prop, (U.flag & USER_RELPATHS) != 0);
+ }
}
}
}
@@ -241,7 +265,7 @@ short ED_fileselect_set_params(SpaceFile *sfile)
}
/* operator has no setting for this */
- params->sort = FILE_SORT_ALPHA;
+ params->active_file = -1;
/* initialize the list with previous folders */
@@ -253,7 +277,7 @@ short ED_fileselect_set_params(SpaceFile *sfile)
BLI_split_dir_part(G.main->name, sfile->params->dir, sizeof(sfile->params->dir));
}
else {
- const char *doc_path = BLI_getDefaultDocumentFolder();
+ const char *doc_path = BKE_appdir_folder_default();
if (doc_path) {
BLI_strncpy(sfile->params->dir, doc_path, sizeof(sfile->params->dir));
}
@@ -275,6 +299,18 @@ void ED_fileselect_reset_params(SpaceFile *sfile)
sfile->params->type = FILE_UNIX;
sfile->params->flag = 0;
sfile->params->title[0] = '\0';
+ sfile->params->active_file = -1;
+}
+
+/**
+ * Sets FileSelectParams->file (name of selected file)
+ */
+void fileselect_file_set(SpaceFile *sfile, const int index)
+{
+ const struct FileDirEntry *file = filelist_file(sfile->files, index);
+ if (file && file->relpath && file->relpath[0] && !(file->typeflag & FILE_TYPE_FOLDER)) {
+ BLI_strncpy(sfile->params->file, file->relpath, FILE_MAXFILE);
+ }
}
int ED_fileselect_layout_numfiles(FileLayout *layout, ARegion *ar)
@@ -390,63 +426,23 @@ void ED_fileselect_layout_tilepos(FileLayout *layout, int tile, int *x, int *y)
}
}
-/* Shorten a string to a given width w.
- * If front is set, shorten from the front,
- * otherwise shorten from the end. */
-float file_shorten_string(char *string, float w, int front)
-{
- char temp[FILE_MAX];
- short shortened = 0;
- float sw = 0;
- float pad = 0;
-
- if (w <= 0) {
- *string = '\0';
- return 0.0;
- }
+float file_string_width(const char *str)
+{
+ uiStyle *style = UI_style_get();
+ float width;
- sw = file_string_width(string);
- if (front == 1) {
- const char *s = string;
- BLI_strncpy(temp, "...", 4);
- pad = file_string_width(temp);
- while ((*s) && (sw + pad > w)) {
- s++;
- sw = file_string_width(s);
- shortened = 1;
- }
- if (shortened) {
- int slen = strlen(s);
- BLI_strncpy(temp + 3, s, slen + 1);
- temp[slen + 4] = '\0';
- BLI_strncpy(string, temp, slen + 4);
- }
+ UI_fontstyle_set(&style->widget);
+ if (style->widget.kerning == 1) { /* for BLF_width */
+ BLF_enable(style->widget.uifont_id, BLF_KERNING_DEFAULT);
}
- else {
- const char *s = string;
- while (sw > w) {
- int slen = strlen(string);
- string[slen - 1] = '\0';
- sw = file_string_width(s);
- shortened = 1;
- }
- if (shortened) {
- int slen = strlen(string);
- if (slen > 3) {
- BLI_strncpy(string + slen - 3, "...", 4);
- }
- }
+ width = BLF_width(style->widget.uifont_id, str, BLF_DRAW_STR_DUMMY_MAX);
+
+ if (style->widget.kerning == 1) {
+ BLF_disable(style->widget.uifont_id, BLF_KERNING_DEFAULT);
}
-
- return sw;
-}
-float file_string_width(const char *str)
-{
- uiStyle *style = UI_GetStyle();
- uiStyleFontSet(&style->widget);
- return BLF_width(style->widget.uifont_id, str, BLF_DRAW_STR_DUMMY_MAX);
+ return width;
}
float file_font_pointsize(void)
@@ -454,48 +450,31 @@ float file_font_pointsize(void)
#if 0
float s;
char tmp[2] = "X";
- uiStyle *style = UI_GetStyle();
- uiStyleFontSet(&style->widget);
+ uiStyle *style = UI_style_get();
+ UI_fontstyle_set(&style->widget);
s = BLF_height(style->widget.uifont_id, tmp);
return style->widget.points;
#else
- uiStyle *style = UI_GetStyle();
- uiStyleFontSet(&style->widget);
+ uiStyle *style = UI_style_get();
+ UI_fontstyle_set(&style->widget);
return style->widget.points * UI_DPI_FAC;
#endif
}
-static void column_widths(struct FileList *files, struct FileLayout *layout)
+static void column_widths(FileSelectParams *params, struct FileLayout *layout)
{
int i;
- int numfiles = filelist_numfiles(files);
+ const bool small_size = SMALL_SIZE_CHECK(params->thumbnail_size);
for (i = 0; i < MAX_FILE_COLUMN; ++i) {
layout->column_widths[i] = 0;
}
- for (i = 0; (i < numfiles); ++i) {
- struct direntry *file = filelist_file(files, i);
- if (file) {
- float len;
- len = file_string_width(file->relname);
- if (len > layout->column_widths[COLUMN_NAME]) layout->column_widths[COLUMN_NAME] = len;
- len = file_string_width(file->date);
- if (len > layout->column_widths[COLUMN_DATE]) layout->column_widths[COLUMN_DATE] = len;
- len = file_string_width(file->time);
- if (len > layout->column_widths[COLUMN_TIME]) layout->column_widths[COLUMN_TIME] = len;
- len = file_string_width(file->size);
- if (len > layout->column_widths[COLUMN_SIZE]) layout->column_widths[COLUMN_SIZE] = len;
- len = file_string_width(file->mode1);
- if (len > layout->column_widths[COLUMN_MODE1]) layout->column_widths[COLUMN_MODE1] = len;
- len = file_string_width(file->mode2);
- if (len > layout->column_widths[COLUMN_MODE2]) layout->column_widths[COLUMN_MODE2] = len;
- len = file_string_width(file->mode3);
- if (len > layout->column_widths[COLUMN_MODE3]) layout->column_widths[COLUMN_MODE3] = len;
- len = file_string_width(file->owner);
- if (len > layout->column_widths[COLUMN_OWNER]) layout->column_widths[COLUMN_OWNER] = len;
- }
- }
+ layout->column_widths[COLUMN_NAME] = ((float)params->thumbnail_size / 8.0f) * UI_UNIT_X;;
+ /* Biggest possible reasonable values... */
+ layout->column_widths[COLUMN_DATE] = file_string_width(small_size ? "23/08/89" : "23-Dec-89");
+ layout->column_widths[COLUMN_TIME] = file_string_width("23:59");
+ layout->column_widths[COLUMN_SIZE] = file_string_width(small_size ? "98.7 M" : "98.7 MiB");
}
void ED_fileselect_init_layout(struct SpaceFile *sfile, ARegion *ar)
@@ -515,14 +494,14 @@ void ED_fileselect_init_layout(struct SpaceFile *sfile, ARegion *ar)
return;
}
- numfiles = filelist_numfiles(sfile->files);
+ numfiles = filelist_files_ensure(sfile->files);
textheight = (int)file_font_pointsize();
layout = sfile->layout;
layout->textheight = textheight;
if (params->display == FILE_IMGDISPLAY) {
- layout->prv_w = 4.8f * UI_UNIT_X;
- layout->prv_h = 4.8f * UI_UNIT_Y;
+ layout->prv_w = ((float)params->thumbnail_size / 20.0f) * UI_UNIT_X;
+ layout->prv_h = ((float)params->thumbnail_size / 20.0f) * UI_UNIT_Y;
layout->tile_border_x = 0.3f * UI_UNIT_X;
layout->tile_border_y = 0.3f * UI_UNIT_X;
layout->prv_border_x = 0.3f * UI_UNIT_X;
@@ -554,7 +533,7 @@ void ED_fileselect_init_layout(struct SpaceFile *sfile, ARegion *ar)
layout->height = (int)(BLI_rctf_size_y(&v2d->cur) - 2 * layout->tile_border_y);
layout->rows = layout->height / (layout->tile_h + 2 * layout->tile_border_y);
- column_widths(sfile->files, layout);
+ column_widths(params, layout);
if (params->display == FILE_SHORTDISPLAY) {
maxlen = ICON_DEFAULT_WIDTH_SCALE + column_icon_space +
@@ -564,12 +543,6 @@ void ED_fileselect_init_layout(struct SpaceFile *sfile, ARegion *ar)
else {
maxlen = ICON_DEFAULT_WIDTH_SCALE + column_icon_space +
(int)layout->column_widths[COLUMN_NAME] + column_space +
-#ifndef WIN32
- (int)layout->column_widths[COLUMN_MODE1] + column_space +
- (int)layout->column_widths[COLUMN_MODE2] + column_space +
- (int)layout->column_widths[COLUMN_MODE3] + column_space +
- (int)layout->column_widths[COLUMN_OWNER] + column_space +
-#endif
(int)layout->column_widths[COLUMN_DATE] + column_space +
(int)layout->column_widths[COLUMN_TIME] + column_space +
(int)layout->column_widths[COLUMN_SIZE] + column_space;
@@ -596,27 +569,32 @@ FileLayout *ED_fileselect_get_layout(struct SpaceFile *sfile, ARegion *ar)
return sfile->layout;
}
-void file_change_dir(bContext *C, int checkdir)
+void ED_file_change_dir(bContext *C, const bool checkdir)
{
wmWindowManager *wm = CTX_wm_manager(C);
SpaceFile *sfile = CTX_wm_space_file(C);
+ ScrArea *sa = CTX_wm_area(C);
if (sfile->params) {
+ ED_fileselect_clear(wm, sa, sfile);
- ED_fileselect_clear(wm, sfile);
+ /* Clear search string, it is very rare to want to keep that filter while changing dir,
+ * and usually very annoying to keep it actually! */
+ sfile->params->filter_search[0] = '\0';
+ sfile->params->active_file = -1;
if (checkdir && !BLI_is_dir(sfile->params->dir)) {
BLI_strncpy(sfile->params->dir, filelist_dir(sfile->files), sizeof(sfile->params->dir));
/* could return but just refresh the current dir */
}
filelist_setdir(sfile->files, sfile->params->dir);
-
+
if (folderlist_clear_next(sfile))
folderlist_free(sfile->folders_next);
folderlist_pushdir(sfile->folders_prev, sfile->params->dir);
- file_draw_check_cb(C, NULL, NULL);
+ file_draw_check(C);
}
}
@@ -625,18 +603,19 @@ int file_select_match(struct SpaceFile *sfile, const char *pattern, char *matche
int match = 0;
int i;
- struct direntry *file;
- int n = filelist_numfiles(sfile->files);
+ FileDirEntry *file;
+ int n = filelist_files_ensure(sfile->files);
/* select any file that matches the pattern, this includes exact match
* if the user selects a single file by entering the filename
*/
for (i = 0; i < n; i++) {
file = filelist_file(sfile->files, i);
- if (fnmatch(pattern, file->relname, 0) == 0) {
- file->selflag |= SELECTED_FILE;
+ /* Do not check wether file is a file or dir here! Causes T44243 (we do accept dirs at this stage). */
+ if (fnmatch(pattern, file->relpath, 0) == 0) {
+ filelist_entry_select_set(sfile->files, file, FILE_SEL_ADD, FILE_SEL_SELECTED, CHECK_ALL);
if (!match) {
- BLI_strncpy(matched_file, file->relname, FILE_MAX);
+ BLI_strncpy(matched_file, file->relpath, FILE_MAX);
}
match++;
}
@@ -662,10 +641,10 @@ int autocomplete_directory(struct bContext *C, char *str, void *UNUSED(arg_v))
dir = opendir(dirname);
if (dir) {
- AutoComplete *autocpl = autocomplete_begin(str, FILE_MAX);
+ AutoComplete *autocpl = UI_autocomplete_begin(str, FILE_MAX);
while ((de = readdir(dir)) != NULL) {
- if (strcmp(".", de->d_name) == 0 || strcmp("..", de->d_name) == 0) {
+ if (FILENAME_IS_CURRPAR(de->d_name)) {
/* pass */
}
else {
@@ -676,21 +655,16 @@ int autocomplete_directory(struct bContext *C, char *str, void *UNUSED(arg_v))
if (BLI_stat(path, &status) == 0) {
if (S_ISDIR(status.st_mode)) { /* is subdir */
- autocomplete_do_name(autocpl, path);
+ UI_autocomplete_update_name(autocpl, path);
}
}
}
}
closedir(dir);
- match = autocomplete_end(autocpl, str);
- if (match) {
- if (match == AUTOCOMPLETE_FULL_MATCH) {
- BLI_add_slash(str);
- }
- else {
- BLI_strncpy(sfile->params->dir, str, sizeof(sfile->params->dir));
- }
+ match = UI_autocomplete_end(autocpl, str);
+ if (match == AUTOCOMPLETE_FULL_MATCH) {
+ BLI_add_slash(str);
}
}
}
@@ -705,36 +679,34 @@ int autocomplete_file(struct bContext *C, char *str, void *UNUSED(arg_v))
/* search if str matches the beginning of name */
if (str[0] && sfile->files) {
- AutoComplete *autocpl = autocomplete_begin(str, FILE_MAX);
- int nentries = filelist_numfiles(sfile->files);
+ AutoComplete *autocpl = UI_autocomplete_begin(str, FILE_MAX);
+ int nentries = filelist_files_ensure(sfile->files);
int i;
for (i = 0; i < nentries; ++i) {
- struct direntry *file = filelist_file(sfile->files, i);
- if (file && (S_ISREG(file->type) || S_ISDIR(file->type))) {
- autocomplete_do_name(autocpl, file->relname);
- }
+ FileDirEntry *file = filelist_file(sfile->files, i);
+ UI_autocomplete_update_name(autocpl, file->relpath);
}
- match = autocomplete_end(autocpl, str);
+ match = UI_autocomplete_end(autocpl, str);
}
return match;
}
-void ED_fileselect_clear(struct wmWindowManager *wm, struct SpaceFile *sfile)
+void ED_fileselect_clear(wmWindowManager *wm, ScrArea *sa, SpaceFile *sfile)
{
/* only NULL in rare cases - [#29734] */
if (sfile->files) {
- thumbnails_stop(wm, sfile->files);
+ filelist_readjob_stop(wm, sa);
filelist_freelib(sfile->files);
- filelist_free(sfile->files);
+ filelist_clear(sfile->files);
}
- sfile->params->active_file = -1;
+ sfile->params->highlight_file = -1;
WM_main_add_notifier(NC_SPACE | ND_SPACE_FILE_LIST, NULL);
}
-void ED_fileselect_exit(struct wmWindowManager *wm, struct SpaceFile *sfile)
+void ED_fileselect_exit(wmWindowManager *wm, ScrArea *sa, SpaceFile *sfile)
{
if (!sfile) return;
if (sfile->op) {
@@ -746,7 +718,8 @@ void ED_fileselect_exit(struct wmWindowManager *wm, struct SpaceFile *sfile)
folderlist_free(sfile->folders_next);
if (sfile->files) {
- ED_fileselect_clear(wm, sfile);
+ ED_fileselect_clear(wm, sa, sfile);
+ filelist_free(sfile->files);
MEM_freeN(sfile->files);
sfile->files = NULL;
}
diff --git a/source/blender/editors/space_file/fsmenu.c b/source/blender/editors/space_file/fsmenu.c
index d049a45fd90..2142368f758 100644
--- a/source/blender/editors/space_file/fsmenu.c
+++ b/source/blender/editors/space_file/fsmenu.c
@@ -40,6 +40,12 @@
#include "BLI_utildefines.h"
#include "BLI_blenlib.h"
+#include "BKE_appdir.h"
+
+#include "DNA_space_types.h"
+
+#include "ED_fileselect.h"
+
#ifdef WIN32
# include <windows.h> /* need to include windows.h so _WIN32_IE is defined */
# ifndef _WIN32_IE
@@ -63,15 +69,6 @@
/* FSMENU HANDLING */
-/* FSMenuEntry's without paths indicate seperators */
-typedef struct _FSMenuEntry FSMenuEntry;
-struct _FSMenuEntry {
- FSMenuEntry *next;
-
- char *path;
- short save;
-};
-
typedef struct FSMenu {
FSMenuEntry *fsmenu_system;
FSMenuEntry *fsmenu_system_bookmarks;
@@ -81,7 +78,7 @@ typedef struct FSMenu {
static FSMenu *g_fsmenu = NULL;
-FSMenu *fsmenu_get(void)
+FSMenu *ED_fsmenu_get(void)
{
if (!g_fsmenu) {
g_fsmenu = MEM_callocN(sizeof(struct FSMenu), "fsmenu");
@@ -89,7 +86,7 @@ FSMenu *fsmenu_get(void)
return g_fsmenu;
}
-static FSMenuEntry *fsmenu_get_category(struct FSMenu *fsmenu, FSMenuCategory category)
+struct FSMenuEntry *ED_fsmenu_get_category(struct FSMenu *fsmenu, FSMenuCategory category)
{
FSMenuEntry *fsm_head = NULL;
@@ -110,7 +107,7 @@ static FSMenuEntry *fsmenu_get_category(struct FSMenu *fsmenu, FSMenuCategory ca
return fsm_head;
}
-static void fsmenu_set_category(struct FSMenu *fsmenu, FSMenuCategory category, FSMenuEntry *fsm_head)
+void ED_fsmenu_set_category(struct FSMenu *fsmenu, FSMenuCategory category, FSMenuEntry *fsm_head)
{
switch (category) {
case FS_CATEGORY_SYSTEM:
@@ -128,47 +125,141 @@ static void fsmenu_set_category(struct FSMenu *fsmenu, FSMenuCategory category,
}
}
-int fsmenu_get_nentries(struct FSMenu *fsmenu, FSMenuCategory category)
+int ED_fsmenu_get_nentries(struct FSMenu *fsmenu, FSMenuCategory category)
{
FSMenuEntry *fsm_iter;
int count = 0;
- for (fsm_iter = fsmenu_get_category(fsmenu, category); fsm_iter; fsm_iter = fsm_iter->next) {
+ for (fsm_iter = ED_fsmenu_get_category(fsmenu, category); fsm_iter; fsm_iter = fsm_iter->next) {
count++;
}
return count;
}
-char *fsmenu_get_entry(struct FSMenu *fsmenu, FSMenuCategory category, int idx)
+FSMenuEntry *ED_fsmenu_get_entry(struct FSMenu *fsmenu, FSMenuCategory category, int index)
{
FSMenuEntry *fsm_iter;
- for (fsm_iter = fsmenu_get_category(fsmenu, category); fsm_iter && idx; fsm_iter = fsm_iter->next) {
- idx--;
+ for (fsm_iter = ED_fsmenu_get_category(fsmenu, category); fsm_iter && index; fsm_iter = fsm_iter->next) {
+ index--;
+ }
+
+ return fsm_iter;
+}
+
+char *ED_fsmenu_entry_get_path(struct FSMenuEntry *fsentry)
+{
+ return fsentry->path;
+}
+
+void ED_fsmenu_entry_set_path(struct FSMenuEntry *fsentry, const char *path)
+{
+ if ((!fsentry->path || !path || !STREQ(path, fsentry->path)) && (fsentry->path != path)) {
+ char tmp_name[FILE_MAXFILE];
+
+ MEM_SAFE_FREE(fsentry->path);
+
+ fsentry->path = (path && path[0]) ? BLI_strdup(path) : NULL;
+
+ BLI_make_file_string("/", tmp_name, BKE_appdir_folder_id_create(BLENDER_USER_CONFIG, NULL), BLENDER_BOOKMARK_FILE);
+ fsmenu_write_file(ED_fsmenu_get(), tmp_name);
+ }
+}
+
+static void fsmenu_entry_generate_name(struct FSMenuEntry *fsentry, char *name, size_t name_size)
+{
+ char temp[FILE_MAX];
+
+ BLI_strncpy(temp, fsentry->path, FILE_MAX);
+ BLI_add_slash(temp);
+ BLI_getlastdir(temp, name, name_size);
+ BLI_del_slash(name);
+ if (!name[0]) {
+ name[0] = '/';
+ name[1] = '\0';
+ }
+}
+
+char *ED_fsmenu_entry_get_name(struct FSMenuEntry *fsentry)
+{
+ if (fsentry->name[0]) {
+ return fsentry->name;
}
+ else {
+ /* Here we abuse fsm_iter->name, keeping first char NULL. */
+ char *name = fsentry->name + 1;
+ size_t name_size = sizeof(fsentry->name) - 1;
- return fsm_iter ? fsm_iter->path : NULL;
+ fsmenu_entry_generate_name(fsentry, name, name_size);
+ return name;
+ }
+}
+
+void ED_fsmenu_entry_set_name(struct FSMenuEntry *fsentry, const char *name)
+{
+ if (!STREQ(name, fsentry->name)) {
+ char tmp_name[FILE_MAXFILE];
+ size_t tmp_name_size = sizeof(tmp_name);
+
+ fsmenu_entry_generate_name(fsentry, tmp_name, tmp_name_size);
+ if (!name[0] || STREQ(tmp_name, name)) {
+ /* reset name to default behavior. */
+ fsentry->name[0] = '\0';
+ }
+ else {
+ BLI_strncpy(fsentry->name, name, sizeof(fsentry->name));
+ }
+
+ BLI_make_file_string("/", tmp_name, BKE_appdir_folder_id_create(BLENDER_USER_CONFIG, NULL), BLENDER_BOOKMARK_FILE);
+ fsmenu_write_file(ED_fsmenu_get(), tmp_name);
+ }
+}
+
+void fsmenu_entry_refresh_valid(struct FSMenuEntry *fsentry)
+{
+ if (fsentry->path && fsentry->path[0]) {
+#ifdef WIN32
+ /* XXX Special case, always consider those as valid.
+ * Thanks to Windows, which can spend five seconds to perform a mere stat() call on those paths...
+ * See T43684.
+ */
+ const char *exceptions[] = {"A:\\", "B:\\", NULL};
+ const size_t exceptions_len[] = {strlen(exceptions[0]), strlen(exceptions[1]), 0};
+ int i;
+
+ for (i = 0; exceptions[i]; i++) {
+ if (STRCASEEQLEN(fsentry->path, exceptions[i], exceptions_len[i])) {
+ fsentry->valid = true;
+ return;
+ }
+ }
+#endif
+ fsentry->valid = BLI_is_dir(fsentry->path);
+ }
+ else {
+ fsentry->valid = false;
+ }
}
short fsmenu_can_save(struct FSMenu *fsmenu, FSMenuCategory category, int idx)
{
FSMenuEntry *fsm_iter;
- for (fsm_iter = fsmenu_get_category(fsmenu, category); fsm_iter && idx; fsm_iter = fsm_iter->next) {
+ for (fsm_iter = ED_fsmenu_get_category(fsmenu, category); fsm_iter && idx; fsm_iter = fsm_iter->next) {
idx--;
}
return fsm_iter ? fsm_iter->save : 0;
}
-void fsmenu_insert_entry(struct FSMenu *fsmenu, FSMenuCategory category, const char *path, FSMenuInsert flag)
+void fsmenu_insert_entry(struct FSMenu *fsmenu, FSMenuCategory category, const char *path, const char *name, FSMenuInsert flag)
{
FSMenuEntry *fsm_prev;
FSMenuEntry *fsm_iter;
FSMenuEntry *fsm_head;
- fsm_head = fsmenu_get_category(fsmenu, category);
+ fsm_head = ED_fsmenu_get_category(fsmenu, category);
fsm_prev = fsm_head; /* this is odd and not really correct? */
for (fsm_iter = fsm_head; fsm_iter; fsm_prev = fsm_iter, fsm_iter = fsm_iter->next) {
@@ -179,7 +270,7 @@ void fsmenu_insert_entry(struct FSMenu *fsmenu, FSMenuCategory category, const c
if (fsm_iter != fsm_head) {
fsm_prev->next = fsm_iter->next;
fsm_iter->next = fsm_head;
- fsmenu_set_category(fsmenu, category, fsm_iter);
+ ED_fsmenu_set_category(fsmenu, category, fsm_iter);
}
}
return;
@@ -202,10 +293,41 @@ void fsmenu_insert_entry(struct FSMenu *fsmenu, FSMenuCategory category, const c
fsm_iter->path = BLI_strdup(path);
fsm_iter->save = (flag & FS_INSERT_SAVE) != 0;
+ if ((category == FS_CATEGORY_RECENT) && (!name || !name[0])) {
+ /* Special handling when adding new recent entry - check if dir exists in some other categories,
+ * and try to use name from there if so. */
+ FSMenuCategory cats[] = {FS_CATEGORY_SYSTEM, FS_CATEGORY_SYSTEM_BOOKMARKS, FS_CATEGORY_BOOKMARKS};
+ int i = ARRAY_SIZE(cats);
+
+ while (i--) {
+ FSMenuEntry *tfsm = ED_fsmenu_get_category(fsmenu, cats[i]);
+
+ for (; tfsm; tfsm = tfsm->next) {
+ if (STREQ(tfsm->path, fsm_iter->path)) {
+ if (tfsm->name && tfsm->name[0]) {
+ name = tfsm->name;
+ }
+ break;
+ }
+ }
+ if (tfsm) {
+ break;
+ }
+ }
+ }
+
+ if (name && name[0]) {
+ BLI_strncpy(fsm_iter->name, name, sizeof(fsm_iter->name));
+ }
+ else {
+ fsm_iter->name[0] = '\0';
+ }
+ fsmenu_entry_refresh_valid(fsm_iter);
+
if (fsm_prev) {
if (flag & FS_INSERT_FIRST) {
fsm_iter->next = fsm_head;
- fsmenu_set_category(fsmenu, category, fsm_iter);
+ ED_fsmenu_set_category(fsmenu, category, fsm_iter);
}
else {
fsm_iter->next = fsm_prev->next;
@@ -214,7 +336,7 @@ void fsmenu_insert_entry(struct FSMenu *fsmenu, FSMenuCategory category, const c
}
else {
fsm_iter->next = fsm_head;
- fsmenu_set_category(fsmenu, category, fsm_iter);
+ ED_fsmenu_set_category(fsmenu, category, fsm_iter);
}
}
@@ -224,7 +346,7 @@ void fsmenu_remove_entry(struct FSMenu *fsmenu, FSMenuCategory category, int idx
FSMenuEntry *fsm_iter;
FSMenuEntry *fsm_head;
- fsm_head = fsmenu_get_category(fsmenu, category);
+ fsm_head = ED_fsmenu_get_category(fsmenu, category);
for (fsm_iter = fsm_head; fsm_iter && idx; fsm_prev = fsm_iter, fsm_iter = fsm_iter->next)
idx--;
@@ -241,7 +363,7 @@ void fsmenu_remove_entry(struct FSMenu *fsmenu, FSMenuCategory category, int idx
}
else {
fsm_head = fsm_iter->next;
- fsmenu_set_category(fsmenu, category, fsm_head);
+ ED_fsmenu_set_category(fsmenu, category, fsm_head);
}
/* free entry */
MEM_freeN(fsm_iter->path);
@@ -253,20 +375,29 @@ void fsmenu_remove_entry(struct FSMenu *fsmenu, FSMenuCategory category, int idx
void fsmenu_write_file(struct FSMenu *fsmenu, const char *filename)
{
FSMenuEntry *fsm_iter = NULL;
+ char fsm_name[FILE_MAX];
int nwritten = 0;
FILE *fp = BLI_fopen(filename, "w");
if (!fp) return;
-
+
fprintf(fp, "[Bookmarks]\n");
- for (fsm_iter = fsmenu_get_category(fsmenu, FS_CATEGORY_BOOKMARKS); fsm_iter; fsm_iter = fsm_iter->next) {
+ for (fsm_iter = ED_fsmenu_get_category(fsmenu, FS_CATEGORY_BOOKMARKS); fsm_iter; fsm_iter = fsm_iter->next) {
if (fsm_iter->path && fsm_iter->save) {
+ fsmenu_entry_generate_name(fsm_iter, fsm_name, sizeof(fsm_name));
+ if (fsm_iter->name[0] && !STREQ(fsm_iter->name, fsm_name)) {
+ fprintf(fp, "!%s\n", fsm_iter->name);
+ }
fprintf(fp, "%s\n", fsm_iter->path);
}
}
fprintf(fp, "[Recent]\n");
- for (fsm_iter = fsmenu_get_category(fsmenu, FS_CATEGORY_RECENT); fsm_iter && (nwritten < FSMENU_RECENT_MAX); fsm_iter = fsm_iter->next, ++nwritten) {
+ for (fsm_iter = ED_fsmenu_get_category(fsmenu, FS_CATEGORY_RECENT); fsm_iter && (nwritten < FSMENU_RECENT_MAX); fsm_iter = fsm_iter->next, ++nwritten) {
if (fsm_iter->path && fsm_iter->save) {
+ fsmenu_entry_generate_name(fsm_iter, fsm_name, sizeof(fsm_name));
+ if (fsm_iter->name[0] && !STREQ(fsm_iter->name, fsm_name)) {
+ fprintf(fp, "!%s\n", fsm_iter->name);
+ }
fprintf(fp, "%s\n", fsm_iter->path);
}
}
@@ -276,19 +407,31 @@ void fsmenu_write_file(struct FSMenu *fsmenu, const char *filename)
void fsmenu_read_bookmarks(struct FSMenu *fsmenu, const char *filename)
{
char line[FILE_MAXDIR];
+ char name[FILE_MAXFILE];
FSMenuCategory category = FS_CATEGORY_BOOKMARKS;
FILE *fp;
fp = BLI_fopen(filename, "r");
if (!fp) return;
+ name[0] = '\0';
+
while (fgets(line, sizeof(line), fp) != NULL) { /* read a line */
- if (strncmp(line, "[Bookmarks]", 11) == 0) {
+ if (STREQLEN(line, "[Bookmarks]", 11)) {
category = FS_CATEGORY_BOOKMARKS;
}
- else if (strncmp(line, "[Recent]", 8) == 0) {
+ else if (STREQLEN(line, "[Recent]", 8)) {
category = FS_CATEGORY_RECENT;
}
+ else if (line[0] == '!') {
+ int len = strlen(line);
+ if (len > 0) {
+ if (line[len - 1] == '\n') {
+ line[len - 1] = '\0';
+ }
+ BLI_strncpy(name, line + 1, sizeof(name));
+ }
+ }
else {
int len = strlen(line);
if (len > 0) {
@@ -302,9 +445,11 @@ void fsmenu_read_bookmarks(struct FSMenu *fsmenu, const char *filename)
if (BLI_exists(line))
#endif
{
- fsmenu_insert_entry(fsmenu, category, line, FS_INSERT_SAVE);
+ fsmenu_insert_entry(fsmenu, category, line, name, FS_INSERT_SAVE);
}
}
+ /* always reset name. */
+ name[0] = '\0';
}
}
fclose(fp);
@@ -316,29 +461,49 @@ void fsmenu_read_system(struct FSMenu *fsmenu, int read_bookmarks)
#ifdef WIN32
/* Add the drive names to the listing */
{
+ wchar_t wline[FILE_MAXDIR];
__int64 tmp;
- char tmps[4];
+ char tmps[4], *name;
int i;
-
+
tmp = GetLogicalDrives();
-
+
for (i = 0; i < 26; i++) {
if ((tmp >> i) & 1) {
tmps[0] = 'A' + i;
tmps[1] = ':';
tmps[2] = '\\';
- tmps[3] = 0;
-
- fsmenu_insert_entry(fsmenu, FS_CATEGORY_SYSTEM, tmps, FS_INSERT_SORTED);
+ tmps[3] = '\0';
+ name = NULL;
+
+ /* Flee from horrible win querying hover floppy drives! */
+ if (i > 1) {
+ /* Try to get volume label as well... */
+ BLI_strncpy_wchar_from_utf8(wline, tmps, 4);
+ if (GetVolumeInformationW(wline, wline + 4, FILE_MAXDIR - 4, NULL, NULL, NULL, NULL, 0)) {
+ size_t label_len;
+
+ BLI_strncpy_wchar_as_utf8(line, wline + 4, FILE_MAXDIR - 4);
+
+ label_len = MIN2(strlen(line), FILE_MAXDIR - 6);
+ BLI_snprintf(line + label_len, 6, " (%.2s)", tmps);
+
+ name = line;
+ }
+ }
+
+ fsmenu_insert_entry(fsmenu, FS_CATEGORY_SYSTEM, tmps, name, FS_INSERT_SORTED);
}
}
/* Adding Desktop and My Documents */
if (read_bookmarks) {
- SHGetSpecialFolderPath(0, line, CSIDL_PERSONAL, 0);
- fsmenu_insert_entry(fsmenu, FS_CATEGORY_SYSTEM_BOOKMARKS, line, FS_INSERT_SORTED);
- SHGetSpecialFolderPath(0, line, CSIDL_DESKTOPDIRECTORY, 0);
- fsmenu_insert_entry(fsmenu, FS_CATEGORY_SYSTEM_BOOKMARKS, line, FS_INSERT_SORTED);
+ SHGetSpecialFolderPathW(0, wline, CSIDL_PERSONAL, 0);
+ BLI_strncpy_wchar_as_utf8(line, wline, FILE_MAXDIR);
+ fsmenu_insert_entry(fsmenu, FS_CATEGORY_SYSTEM_BOOKMARKS, line, NULL, FS_INSERT_SORTED);
+ SHGetSpecialFolderPathW(0, wline, CSIDL_DESKTOPDIRECTORY, 0);
+ BLI_strncpy_wchar_as_utf8(line, wline, FILE_MAXDIR);
+ fsmenu_insert_entry(fsmenu, FS_CATEGORY_SYSTEM_BOOKMARKS, line, NULL, FS_INSERT_SORTED);
}
}
#else
@@ -359,38 +524,38 @@ void fsmenu_read_system(struct FSMenu *fsmenu, int read_bookmarks)
continue;
FSRefMakePath(&dir, path, FILE_MAX);
- if (strcmp((char *)path, "/home") && strcmp((char *)path, "/net")) {
+ if (!STREQ((char *)path, "/home") && !STREQ((char *)path, "/net")) {
/* /net and /home are meaningless on OSX, home folders are stored in /Users */
- fsmenu_insert_entry(fsmenu, FS_CATEGORY_SYSTEM, (char *)path, FS_INSERT_SORTED);
+ fsmenu_insert_entry(fsmenu, FS_CATEGORY_SYSTEM, (char *)path, NULL, FS_INSERT_SORTED);
}
}
/* As 10.4 doesn't provide proper API to retrieve the favorite places,
* assume they are the standard ones
- * TODO : replace hardcoded paths with proper BLI_get_folder calls */
+ * TODO : replace hardcoded paths with proper BKE_appdir_folder_id calls */
home = getenv("HOME");
if (read_bookmarks && home) {
BLI_snprintf(line, sizeof(line), "%s/", home);
- fsmenu_insert_entry(fsmenu, FS_CATEGORY_SYSTEM_BOOKMARKS, line, FS_INSERT_SORTED);
+ fsmenu_insert_entry(fsmenu, FS_CATEGORY_SYSTEM_BOOKMARKS, line, NULL, FS_INSERT_SORTED);
BLI_snprintf(line, sizeof(line), "%s/Desktop/", home);
if (BLI_exists(line)) {
- fsmenu_insert_entry(fsmenu, FS_CATEGORY_SYSTEM_BOOKMARKS, line, FS_INSERT_SORTED);
+ fsmenu_insert_entry(fsmenu, FS_CATEGORY_SYSTEM_BOOKMARKS, line, NULL, FS_INSERT_SORTED);
}
BLI_snprintf(line, sizeof(line), "%s/Documents/", home);
if (BLI_exists(line)) {
- fsmenu_insert_entry(fsmenu, FS_CATEGORY_SYSTEM_BOOKMARKS, line, FS_INSERT_SORTED);
+ fsmenu_insert_entry(fsmenu, FS_CATEGORY_SYSTEM_BOOKMARKS, line, NULL, FS_INSERT_SORTED);
}
BLI_snprintf(line, sizeof(line), "%s/Pictures/", home);
if (BLI_exists(line)) {
- fsmenu_insert_entry(fsmenu, FS_CATEGORY_SYSTEM_BOOKMARKS, line, FS_INSERT_SORTED);
+ fsmenu_insert_entry(fsmenu, FS_CATEGORY_SYSTEM_BOOKMARKS, line, NULL, FS_INSERT_SORTED);
}
BLI_snprintf(line, sizeof(line), "%s/Music/", home);
if (BLI_exists(line)) {
- fsmenu_insert_entry(fsmenu, FS_CATEGORY_SYSTEM_BOOKMARKS, line, FS_INSERT_SORTED);
+ fsmenu_insert_entry(fsmenu, FS_CATEGORY_SYSTEM_BOOKMARKS, line, NULL, FS_INSERT_SORTED);
}
BLI_snprintf(line, sizeof(line), "%s/Movies/", home);
if (BLI_exists(line)) {
- fsmenu_insert_entry(fsmenu, FS_CATEGORY_SYSTEM_BOOKMARKS, line, FS_INSERT_SORTED);
+ fsmenu_insert_entry(fsmenu, FS_CATEGORY_SYSTEM_BOOKMARKS, line, NULL, FS_INSERT_SORTED);
}
}
#else /* OSX 10.6+ */
@@ -410,7 +575,7 @@ void fsmenu_read_system(struct FSMenu *fsmenu, int read_bookmarks)
continue;
CFURLGetFileSystemRepresentation(cfURL, false, (UInt8 *)defPath, FILE_MAX);
- fsmenu_insert_entry(fsmenu, FS_CATEGORY_SYSTEM, (char *)defPath, FS_INSERT_SORTED);
+ fsmenu_insert_entry(fsmenu, FS_CATEGORY_SYSTEM, (char *)defPath, NULL, FS_INSERT_SORTED);
}
CFRelease(volEnum);
@@ -441,9 +606,14 @@ void fsmenu_read_system(struct FSMenu *fsmenu, int read_bookmarks)
pathString = CFURLCopyFileSystemPath(cfURL, kCFURLPOSIXPathStyle);
- if (pathString == NULL || !CFStringGetCString(pathString, line, sizeof(line), kCFStringEncodingASCII))
+ if (pathString == NULL || !CFStringGetCString(pathString, line, sizeof(line), kCFStringEncodingUTF8))
continue;
- fsmenu_insert_entry(fsmenu, FS_CATEGORY_SYSTEM_BOOKMARKS, line, FS_INSERT_SORTED);
+
+ /* Exclude "all my files" as it makes no sense in blender fileselector */
+ /* Exclude "airdrop" if wlan not active as it would show "" ) */
+ if (!strstr(line, "myDocuments.cannedSearch") && (*line != '\0')) {
+ fsmenu_insert_entry(fsmenu, FS_CATEGORY_SYSTEM_BOOKMARKS, line, NULL, FS_INSERT_LAST);
+ }
CFRelease(pathString);
CFRelease(cfURL);
@@ -461,10 +631,10 @@ void fsmenu_read_system(struct FSMenu *fsmenu, int read_bookmarks)
if (read_bookmarks && home) {
BLI_snprintf(line, sizeof(line), "%s/", home);
- fsmenu_insert_entry(fsmenu, FS_CATEGORY_SYSTEM_BOOKMARKS, line, FS_INSERT_SORTED);
+ fsmenu_insert_entry(fsmenu, FS_CATEGORY_SYSTEM_BOOKMARKS, line, NULL, FS_INSERT_SORTED);
BLI_snprintf(line, sizeof(line), "%s/Desktop/", home);
if (BLI_exists(line)) {
- fsmenu_insert_entry(fsmenu, FS_CATEGORY_SYSTEM_BOOKMARKS, line, FS_INSERT_SORTED);
+ fsmenu_insert_entry(fsmenu, FS_CATEGORY_SYSTEM_BOOKMARKS, line, NULL, FS_INSERT_SORTED);
}
}
@@ -483,16 +653,16 @@ void fsmenu_read_system(struct FSMenu *fsmenu, int read_bookmarks)
else {
while ((mnt = getmntent(fp))) {
/* not sure if this is right, but seems to give the relevant mnts */
- if (strncmp(mnt->mnt_fsname, "/dev", 4))
+ if (!STREQLEN(mnt->mnt_fsname, "/dev", 4))
continue;
len = strlen(mnt->mnt_dir);
if (len && mnt->mnt_dir[len - 1] != '/') {
BLI_snprintf(line, sizeof(line), "%s/", mnt->mnt_dir);
- fsmenu_insert_entry(fsmenu, FS_CATEGORY_SYSTEM, line, FS_INSERT_SORTED);
+ fsmenu_insert_entry(fsmenu, FS_CATEGORY_SYSTEM, line, NULL, FS_INSERT_SORTED);
}
else {
- fsmenu_insert_entry(fsmenu, FS_CATEGORY_SYSTEM, mnt->mnt_dir, FS_INSERT_SORTED);
+ fsmenu_insert_entry(fsmenu, FS_CATEGORY_SYSTEM, mnt->mnt_dir, NULL, FS_INSERT_SORTED);
}
found = 1;
@@ -505,7 +675,7 @@ void fsmenu_read_system(struct FSMenu *fsmenu, int read_bookmarks)
/* fallback */
if (!found)
- fsmenu_insert_entry(fsmenu, FS_CATEGORY_SYSTEM, "/", FS_INSERT_SORTED);
+ fsmenu_insert_entry(fsmenu, FS_CATEGORY_SYSTEM, "/", NULL, FS_INSERT_SORTED);
}
}
#endif
@@ -515,7 +685,7 @@ void fsmenu_read_system(struct FSMenu *fsmenu, int read_bookmarks)
static void fsmenu_free_category(struct FSMenu *fsmenu, FSMenuCategory category)
{
- FSMenuEntry *fsm_iter = fsmenu_get_category(fsmenu, category);
+ FSMenuEntry *fsm_iter = ED_fsmenu_get_category(fsmenu, category);
while (fsm_iter) {
FSMenuEntry *fsm_next = fsm_iter->next;
@@ -532,15 +702,28 @@ static void fsmenu_free_category(struct FSMenu *fsmenu, FSMenuCategory category)
void fsmenu_refresh_system_category(struct FSMenu *fsmenu)
{
fsmenu_free_category(fsmenu, FS_CATEGORY_SYSTEM);
- fsmenu_set_category(fsmenu, FS_CATEGORY_SYSTEM, NULL);
+ ED_fsmenu_set_category(fsmenu, FS_CATEGORY_SYSTEM, NULL);
fsmenu_free_category(fsmenu, FS_CATEGORY_SYSTEM_BOOKMARKS);
- fsmenu_set_category(fsmenu, FS_CATEGORY_SYSTEM_BOOKMARKS, NULL);
+ ED_fsmenu_set_category(fsmenu, FS_CATEGORY_SYSTEM_BOOKMARKS, NULL);
/* Add all entries to system category */
fsmenu_read_system(fsmenu, true);
}
+void fsmenu_refresh_bookmarks_status(struct FSMenu *fsmenu)
+{
+ int categories[] = {FS_CATEGORY_SYSTEM, FS_CATEGORY_SYSTEM_BOOKMARKS, FS_CATEGORY_BOOKMARKS, FS_CATEGORY_RECENT};
+ int i;
+
+ for (i = sizeof(categories) / sizeof(*categories); i--; ) {
+ FSMenuEntry *fsm_iter = ED_fsmenu_get_category(fsmenu, categories[i]);
+ for ( ; fsm_iter; fsm_iter = fsm_iter->next) {
+ fsmenu_entry_refresh_valid(fsm_iter);
+ }
+ }
+}
+
void fsmenu_free(void)
{
if (g_fsmenu) {
@@ -554,3 +737,16 @@ void fsmenu_free(void)
g_fsmenu = NULL;
}
+int fsmenu_get_active_indices(struct FSMenu *fsmenu, enum FSMenuCategory category, const char *dir)
+{
+ FSMenuEntry *fsm_iter = ED_fsmenu_get_category(fsmenu, category);
+ int i;
+
+ for (i = 0; fsm_iter; fsm_iter = fsm_iter->next, i++) {
+ if (BLI_path_cmp(dir, fsm_iter->path) == 0) {
+ return i;
+ }
+ }
+
+ return -1;
+}
diff --git a/source/blender/editors/space_file/fsmenu.h b/source/blender/editors/space_file/fsmenu.h
index 01bd4e95afa..81014874fb5 100644
--- a/source/blender/editors/space_file/fsmenu.h
+++ b/source/blender/editors/space_file/fsmenu.h
@@ -37,42 +37,26 @@
/* XXX could become UserPref */
#define FSMENU_RECENT_MAX 10
-typedef enum FSMenuCategory {
- FS_CATEGORY_SYSTEM,
- FS_CATEGORY_SYSTEM_BOOKMARKS,
- FS_CATEGORY_BOOKMARKS,
- FS_CATEGORY_RECENT
-} FSMenuCategory;
-
-typedef enum FSMenuInsert {
- FS_INSERT_SORTED = (1 << 0),
- FS_INSERT_SAVE = (1 << 1),
- FS_INSERT_FIRST = (1 << 2) /* moves the item to the front of the list when its not already there */
-} FSMenuInsert;
+enum FSMenuCategory;
+enum FSMenuInsert;
struct FSMenu;
-
-struct FSMenu *fsmenu_get(void);
-
-/** Returns the number of entries in the Fileselect Menu */
-int fsmenu_get_nentries(struct FSMenu *fsmenu, FSMenuCategory category);
-
-/** Returns the fsmenu entry at \a index (or NULL if a bad index)
- * or a separator.
- */
-char *fsmenu_get_entry(struct FSMenu *fsmenu, FSMenuCategory category, int index);
+struct FSMenuEntry;
/** Inserts a new fsmenu entry with the given \a path.
* Duplicate entries are not added.
* \param flag Options for inserting the entry.
*/
-void fsmenu_insert_entry(struct FSMenu *fsmenu, FSMenuCategory category, const char *path, const FSMenuInsert flag);
+void fsmenu_insert_entry(struct FSMenu *fsmenu, enum FSMenuCategory category, const char *path, const char *name, const enum FSMenuInsert flag);
+
+/** Refresh 'valid' status of given menu entry */
+void fsmenu_entry_refresh_valid(struct FSMenuEntry *fsentry);
/** Return whether the entry was created by the user and can be saved and deleted */
-short fsmenu_can_save(struct FSMenu *fsmenu, FSMenuCategory category, int index);
+short fsmenu_can_save(struct FSMenu *fsmenu, enum FSMenuCategory category, int index);
/** Removes the fsmenu entry at the given \a index. */
-void fsmenu_remove_entry(struct FSMenu *fsmenu, FSMenuCategory category, int index);
+void fsmenu_remove_entry(struct FSMenu *fsmenu, enum FSMenuCategory category, int index);
/** saves the 'bookmarks' to the specified file */
void fsmenu_write_file(struct FSMenu *fsmenu, const char *filename);
@@ -89,5 +73,11 @@ void fsmenu_free(void);
/** Refresh system directory menu */
void fsmenu_refresh_system_category(struct FSMenu *fsmenu);
+/** Refresh 'valid' status of all menu entries */
+void fsmenu_refresh_bookmarks_status(struct FSMenu *fsmenu);
+
+/** Get active index based on given directory. */
+int fsmenu_get_active_indices(struct FSMenu *fsmenu, enum FSMenuCategory category, const char *dir);
+
#endif
diff --git a/source/blender/editors/space_file/space_file.c b/source/blender/editors/space_file/space_file.c
index d5be04cff20..97c2d75e469 100644
--- a/source/blender/editors/space_file/space_file.c
+++ b/source/blender/editors/space_file/space_file.c
@@ -39,8 +39,8 @@
#include "BLI_utildefines.h"
#include "BLI_fileops_types.h"
-#include "BLO_readfile.h"
+#include "BKE_appdir.h"
#include "BKE_context.h"
#include "BKE_screen.h"
#include "BKE_global.h"
@@ -71,7 +71,7 @@ static SpaceLink *file_new(const bContext *UNUSED(C))
{
ARegion *ar;
SpaceFile *sfile;
-
+
sfile = MEM_callocN(sizeof(SpaceFile), "initfile");
sfile->spacetype = SPACE_FILE;
@@ -81,12 +81,18 @@ static SpaceLink *file_new(const bContext *UNUSED(C))
ar->regiontype = RGN_TYPE_HEADER;
ar->alignment = RGN_ALIGN_TOP;
- /* channel list region */
- ar = MEM_callocN(sizeof(ARegion), "channel area for file");
+ /* Tools region */
+ ar = MEM_callocN(sizeof(ARegion), "tools area for file");
BLI_addtail(&sfile->regionbase, ar);
- ar->regiontype = RGN_TYPE_CHANNELS;
+ ar->regiontype = RGN_TYPE_TOOLS;
ar->alignment = RGN_ALIGN_LEFT;
+ /* Tool props (aka operator) region */
+ ar = MEM_callocN(sizeof(ARegion), "tool props area for file");
+ BLI_addtail(&sfile->regionbase, ar);
+ ar->regiontype = RGN_TYPE_TOOL_PROPS;
+ ar->alignment = RGN_ALIGN_BOTTOM | RGN_SPLIT_PREV;
+
/* ui list region */
ar = MEM_callocN(sizeof(ARegion), "ui area for file");
BLI_addtail(&sfile->regionbase, ar);
@@ -111,6 +117,8 @@ static void file_free(SpaceLink *sl)
{
SpaceFile *sfile = (SpaceFile *) sl;
+ BLI_assert(sfile->previews_timer == NULL);
+
if (sfile->files) {
// XXXXX would need to do thumbnails_stop here, but no context available
filelist_freelib(sfile->files);
@@ -149,7 +157,13 @@ static void file_init(wmWindowManager *UNUSED(wm), ScrArea *sa)
SpaceFile *sfile = (SpaceFile *)sa->spacedata.first;
/* refresh system directory list */
- fsmenu_refresh_system_category(fsmenu_get());
+ fsmenu_refresh_system_category(ED_fsmenu_get());
+
+ /* Update bookmarks 'valid' state.
+ * Done here, because it seems BLI_is_dir() can have huge impact on performances
+ * in some cases, on win systems... See T43684.
+ */
+ fsmenu_refresh_bookmarks_status(ED_fsmenu_get());
if (sfile->layout) sfile->layout->dirty = true;
}
@@ -158,7 +172,12 @@ static void file_exit(wmWindowManager *wm, ScrArea *sa)
{
SpaceFile *sfile = (SpaceFile *)sa->spacedata.first;
- ED_fileselect_exit(wm, sfile);
+ if (sfile->previews_timer) {
+ WM_event_remove_timer_notifier(wm, NULL, sfile->previews_timer);
+ sfile->previews_timer = NULL;
+ }
+
+ ED_fileselect_exit(wm, sa, sfile);
}
static SpaceLink *file_duplicate(SpaceLink *sl)
@@ -187,75 +206,94 @@ static SpaceLink *file_duplicate(SpaceLink *sl)
return (SpaceLink *)sfilen;
}
-static void file_refresh(const bContext *C, ScrArea *UNUSED(sa))
+static void file_refresh(const bContext *C, ScrArea *sa)
{
wmWindowManager *wm = CTX_wm_manager(C);
SpaceFile *sfile = CTX_wm_space_file(C);
FileSelectParams *params = ED_fileselect_get_params(sfile);
+ struct FSMenu *fsmenu = ED_fsmenu_get();
- if (!sfile->folders_prev)
+ if (!sfile->folders_prev) {
sfile->folders_prev = folderlist_new();
+ }
if (!sfile->files) {
sfile->files = filelist_new(params->type);
- filelist_setdir(sfile->files, params->dir);
- params->active_file = -1; // added this so it opens nicer (ton)
+ params->highlight_file = -1; /* added this so it opens nicer (ton) */
+ }
+ filelist_setdir(sfile->files, params->dir);
+ filelist_setrecursion(sfile->files, params->recursion_level);
+ filelist_setsorting(sfile->files, params->sort);
+ filelist_setfilter_options(sfile->files, (params->flag & FILE_HIDE_DOT) != 0,
+ false, /* TODO hide_parent, should be controllable? */
+ params->flag & FILE_FILTER ? params->filter : 0,
+ params->filter_id,
+ params->filter_glob,
+ params->filter_search);
+
+ /* Update the active indices of bookmarks & co. */
+ sfile->systemnr = fsmenu_get_active_indices(fsmenu, FS_CATEGORY_SYSTEM, params->dir);
+ sfile->system_bookmarknr = fsmenu_get_active_indices(fsmenu, FS_CATEGORY_SYSTEM_BOOKMARKS, params->dir);
+ sfile->bookmarknr = fsmenu_get_active_indices(fsmenu, FS_CATEGORY_BOOKMARKS, params->dir);
+ sfile->recentnr = fsmenu_get_active_indices(fsmenu, FS_CATEGORY_RECENT, params->dir);
+
+ if (filelist_force_reset(sfile->files)) {
+ filelist_readjob_stop(wm, sa);
+ filelist_clear(sfile->files);
}
- filelist_hidedot(sfile->files, params->flag & FILE_HIDE_DOT);
- filelist_setfilter(sfile->files, params->flag & FILE_FILTER ? params->filter : 0);
- filelist_setfilter_types(sfile->files, params->filter_glob);
if (filelist_empty(sfile->files)) {
- thumbnails_stop(wm, sfile->files);
- filelist_readdir(sfile->files);
- if (params->sort != FILE_SORT_NONE) {
- filelist_sort(sfile->files, params->sort);
- }
- BLI_strncpy(params->dir, filelist_dir(sfile->files), FILE_MAX);
- if (params->display == FILE_IMGDISPLAY) {
- thumbnails_start(sfile->files, C);
+ if (!filelist_pending(sfile->files)) {
+ filelist_readjob_start(sfile->files, C);
}
}
+
+ filelist_sort(sfile->files);
+ filelist_filter(sfile->files);
+
+ if (params->display == FILE_IMGDISPLAY) {
+ filelist_cache_previews_set(sfile->files, true);
+ }
else {
- if (params->sort != FILE_SORT_NONE) {
- thumbnails_stop(wm, sfile->files);
- filelist_sort(sfile->files, params->sort);
- if (params->display == FILE_IMGDISPLAY) {
- thumbnails_start(sfile->files, C);
- }
- }
- else {
- if (params->display == FILE_IMGDISPLAY) {
- if (!thumbnails_running(wm, sfile->files)) {
- thumbnails_start(sfile->files, C);
- }
- }
- else {
- /* stop any running thumbnail jobs if we're not
- * displaying them - speedup for NFS */
- thumbnails_stop(wm, sfile->files);
- }
- filelist_filter(sfile->files);
+ filelist_cache_previews_set(sfile->files, false);
+ if (sfile->previews_timer) {
+ WM_event_remove_timer_notifier(wm, CTX_wm_window(C), sfile->previews_timer);
+ sfile->previews_timer = NULL;
}
}
-
+
if (params->renamefile[0] != '\0') {
- int idx = filelist_find(sfile->files, params->renamefile);
+ int idx = filelist_file_findpath(sfile->files, params->renamefile);
if (idx >= 0) {
- struct direntry *file = filelist_file(sfile->files, idx);
+ FileDirEntry *file = filelist_file(sfile->files, idx);
if (file) {
- file->selflag |= EDITING_FILE;
+ filelist_entry_select_set(sfile->files, file, FILE_SEL_ADD, FILE_SEL_EDITING, CHECK_ALL);
}
}
BLI_strncpy(sfile->params->renameedit, sfile->params->renamefile, sizeof(sfile->params->renameedit));
- params->renamefile[0] = '\0';
+ /* File listing is now async, do not clear renamefile if matching entry not found
+ * and dirlist is not finished! */
+ if (idx >= 0 || filelist_is_ready(sfile->files)) {
+ params->renamefile[0] = '\0';
+ }
+ }
+
+ if (sfile->layout) {
+ sfile->layout->dirty = true;
}
- if (sfile->layout) sfile->layout->dirty = true;
+ /* Might be called with NULL sa, see file_main_area_draw() below. */
+ if (sa && BKE_area_find_region_type(sa, RGN_TYPE_TOOLS) == NULL) {
+ /* Create TOOLS/TOOL_PROPS regions. */
+ file_tools_region(sa);
+
+ ED_area_initialize(wm, CTX_wm_window(C), sa);
+ ED_area_tag_redraw(sa);
+ }
}
static void file_listener(bScreen *UNUSED(sc), ScrArea *sa, wmNotifier *wmn)
{
- /* SpaceFile *sfile = (SpaceFile *)sa->spacedata.first; */
+ SpaceFile *sfile = (SpaceFile *)sa->spacedata.first;
/* context changes */
switch (wmn->category) {
@@ -269,6 +307,12 @@ static void file_listener(bScreen *UNUSED(sc), ScrArea *sa, wmNotifier *wmn)
ED_area_tag_refresh(sa);
ED_area_tag_redraw(sa);
break;
+ case ND_SPACE_FILE_PREVIEW:
+ if (sfile->files && filelist_cache_previews_update(sfile->files)) {
+ ED_area_tag_refresh(sa);
+ ED_area_tag_redraw(sa);
+ }
+ break;
}
break;
}
@@ -354,7 +398,7 @@ static void file_main_area_draw(const bContext *C, ARegion *ar)
UI_view2d_view_ortho(v2d);
/* on first read, find active file */
- if (params->active_file == -1) {
+ if (params->highlight_file == -1) {
wmEvent *event = CTX_wm_window(C)->eventstate;
file_highlight_set(sfile, ar, event->x, event->y);
}
@@ -374,6 +418,7 @@ static void file_main_area_draw(const bContext *C, ARegion *ar)
static void file_operatortypes(void)
{
WM_operatortype_append(FILE_OT_select);
+ WM_operatortype_append(FILE_OT_select_walk);
WM_operatortype_append(FILE_OT_select_all_toggle);
WM_operatortype_append(FILE_OT_select_border);
WM_operatortype_append(FILE_OT_select_bookmark);
@@ -387,6 +432,8 @@ static void file_operatortypes(void)
WM_operatortype_append(FILE_OT_bookmark_toggle);
WM_operatortype_append(FILE_OT_bookmark_add);
WM_operatortype_append(FILE_OT_bookmark_delete);
+ WM_operatortype_append(FILE_OT_bookmark_cleanup);
+ WM_operatortype_append(FILE_OT_bookmark_move);
WM_operatortype_append(FILE_OT_reset_recent);
WM_operatortype_append(FILE_OT_hidedot);
WM_operatortype_append(FILE_OT_filenum);
@@ -437,6 +484,49 @@ static void file_keymap(struct wmKeyConfig *keyconf)
RNA_boolean_set(kmi->ptr, "fill", true);
RNA_boolean_set(kmi->ptr, "open", false);
+
+ /* arrow keys navigation (walk selecting) */
+ kmi = WM_keymap_add_item(keymap, "FILE_OT_select_walk", UPARROWKEY, KM_PRESS, 0, 0);
+ RNA_enum_set(kmi->ptr, "direction", FILE_SELECT_WALK_UP);
+ kmi = WM_keymap_add_item(keymap, "FILE_OT_select_walk", UPARROWKEY, KM_PRESS, KM_SHIFT, 0);
+ RNA_enum_set(kmi->ptr, "direction", FILE_SELECT_WALK_UP);
+ RNA_boolean_set(kmi->ptr, "extend", true);
+ kmi = WM_keymap_add_item(keymap, "FILE_OT_select_walk", UPARROWKEY, KM_PRESS, KM_SHIFT | KM_CTRL, 0);
+ RNA_enum_set(kmi->ptr, "direction", FILE_SELECT_WALK_UP);
+ RNA_boolean_set(kmi->ptr, "extend", true);
+ RNA_boolean_set(kmi->ptr, "fill", true);
+
+ kmi = WM_keymap_add_item(keymap, "FILE_OT_select_walk", DOWNARROWKEY, KM_PRESS, 0, 0);
+ RNA_enum_set(kmi->ptr, "direction", FILE_SELECT_WALK_DOWN);
+ kmi = WM_keymap_add_item(keymap, "FILE_OT_select_walk", DOWNARROWKEY, KM_PRESS, KM_SHIFT, 0);
+ RNA_enum_set(kmi->ptr, "direction", FILE_SELECT_WALK_DOWN);
+ RNA_boolean_set(kmi->ptr, "extend", true);
+ kmi = WM_keymap_add_item(keymap, "FILE_OT_select_walk", DOWNARROWKEY, KM_PRESS, KM_SHIFT | KM_CTRL, 0);
+ RNA_enum_set(kmi->ptr, "direction", FILE_SELECT_WALK_DOWN);
+ RNA_boolean_set(kmi->ptr, "extend", true);
+ RNA_boolean_set(kmi->ptr, "fill", true);
+
+ kmi = WM_keymap_add_item(keymap, "FILE_OT_select_walk", LEFTARROWKEY, KM_PRESS, 0, 0);
+ RNA_enum_set(kmi->ptr, "direction", FILE_SELECT_WALK_LEFT);
+ kmi = WM_keymap_add_item(keymap, "FILE_OT_select_walk", LEFTARROWKEY, KM_PRESS, KM_SHIFT, 0);
+ RNA_enum_set(kmi->ptr, "direction", FILE_SELECT_WALK_LEFT);
+ RNA_boolean_set(kmi->ptr, "extend", true);
+ kmi = WM_keymap_add_item(keymap, "FILE_OT_select_walk", LEFTARROWKEY, KM_PRESS, KM_SHIFT | KM_CTRL, 0);
+ RNA_enum_set(kmi->ptr, "direction", FILE_SELECT_WALK_LEFT);
+ RNA_boolean_set(kmi->ptr, "extend", true);
+ RNA_boolean_set(kmi->ptr, "fill", true);
+
+ kmi = WM_keymap_add_item(keymap, "FILE_OT_select_walk", RIGHTARROWKEY, KM_PRESS, 0, 0);
+ RNA_enum_set(kmi->ptr, "direction", FILE_SELECT_WALK_RIGHT);
+ kmi = WM_keymap_add_item(keymap, "FILE_OT_select_walk", RIGHTARROWKEY, KM_PRESS, KM_SHIFT, 0);
+ RNA_enum_set(kmi->ptr, "direction", FILE_SELECT_WALK_RIGHT);
+ RNA_boolean_set(kmi->ptr, "extend", true);
+ kmi = WM_keymap_add_item(keymap, "FILE_OT_select_walk", RIGHTARROWKEY, KM_PRESS, KM_SHIFT | KM_CTRL, 0);
+ RNA_enum_set(kmi->ptr, "direction", FILE_SELECT_WALK_RIGHT);
+ RNA_boolean_set(kmi->ptr, "extend", true);
+ RNA_boolean_set(kmi->ptr, "fill", true);
+
+
/* front and back mouse folder navigation */
WM_keymap_add_item(keymap, "FILE_OT_previous", BUTTON4MOUSE, KM_CLICK, 0, 0);
WM_keymap_add_item(keymap, "FILE_OT_next", BUTTON5MOUSE, KM_CLICK, 0, 0);
@@ -478,7 +568,7 @@ static void file_keymap(struct wmKeyConfig *keyconf)
}
-static void file_channel_area_init(wmWindowManager *wm, ARegion *ar)
+static void file_tools_area_init(wmWindowManager *wm, ARegion *ar)
{
wmKeyMap *keymap;
@@ -490,12 +580,12 @@ static void file_channel_area_init(wmWindowManager *wm, ARegion *ar)
WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
}
-static void file_channel_area_draw(const bContext *C, ARegion *ar)
+static void file_tools_area_draw(const bContext *C, ARegion *ar)
{
- ED_region_panels(C, ar, 1, NULL, -1);
+ ED_region_panels(C, ar, NULL, -1, true);
}
-static void file_channel_area_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *UNUSED(ar), wmNotifier *UNUSED(wmn))
+static void file_tools_area_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *UNUSED(ar), wmNotifier *UNUSED(wmn))
{
#if 0
/* context changes */
@@ -621,12 +711,24 @@ void ED_spacetype_file(void)
/* regions: channels (directories) */
art = MEM_callocN(sizeof(ARegionType), "spacetype file region");
- art->regionid = RGN_TYPE_CHANNELS;
+ art->regionid = RGN_TYPE_TOOLS;
art->prefsizex = 240;
+ art->prefsizey = 60;
+ art->keymapflag = ED_KEYMAP_UI;
+ art->listener = file_tools_area_listener;
+ art->init = file_tools_area_init;
+ art->draw = file_tools_area_draw;
+ BLI_addhead(&st->regiontypes, art);
+
+ /* regions: tool properties */
+ art = MEM_callocN(sizeof(ARegionType), "spacetype file operator region");
+ art->regionid = RGN_TYPE_TOOL_PROPS;
+ art->prefsizex = 0;
+ art->prefsizey = 360;
art->keymapflag = ED_KEYMAP_UI;
- art->listener = file_channel_area_listener;
- art->init = file_channel_area_init;
- art->draw = file_channel_area_draw;
+ art->listener = file_tools_area_listener;
+ art->init = file_tools_area_init;
+ art->draw = file_tools_area_draw;
BLI_addhead(&st->regiontypes, art);
file_panels_register(art);
@@ -656,16 +758,16 @@ void ED_file_exit(void)
void ED_file_read_bookmarks(void)
{
- const char * const cfgdir = BLI_get_folder(BLENDER_USER_CONFIG, NULL);
+ const char * const cfgdir = BKE_appdir_folder_id(BLENDER_USER_CONFIG, NULL);
fsmenu_free();
- fsmenu_read_system(fsmenu_get(), true);
+ fsmenu_read_system(ED_fsmenu_get(), true);
if (cfgdir) {
char name[FILE_MAX];
BLI_make_file_string("/", name, cfgdir, BLENDER_BOOKMARK_FILE);
- fsmenu_read_bookmarks(fsmenu_get(), name);
+ fsmenu_read_bookmarks(ED_fsmenu_get(), name);
}
}
diff --git a/source/blender/editors/space_graph/CMakeLists.txt b/source/blender/editors/space_graph/CMakeLists.txt
index d3fb87204fb..40a196fa95b 100644
--- a/source/blender/editors/space_graph/CMakeLists.txt
+++ b/source/blender/editors/space_graph/CMakeLists.txt
@@ -20,13 +20,15 @@
set(INC
../include
- ../../blenfont
../../blenkernel
../../blenlib
+ ../../blentranslation
+ ../../gpu
../../makesdna
../../makesrna
../../windowmanager
../../../../intern/guardedalloc
+ ../../../../intern/glew-mx
)
set(INC_SYS
@@ -46,14 +48,17 @@ set(SRC
)
if(WITH_AUDASPACE)
- list(APPEND INC
- ../../../../intern/audaspace/intern
+ add_definitions(${AUDASPACE_DEFINITIONS})
+
+ list(APPEND INC_SYS
+ ${AUDASPACE_C_INCLUDE_DIRS}
)
- add_definitions(-DWITH_AUDASPACE)
endif()
if(WITH_INTERNATIONAL)
add_definitions(-DWITH_INTERNATIONAL)
endif()
+add_definitions(${GL_DEFINITIONS})
+
blender_add_lib(bf_editor_space_graph "${SRC}" "${INC}" "${INC_SYS}")
diff --git a/source/blender/editors/space_graph/SConscript b/source/blender/editors/space_graph/SConscript
index 8ddeb0ccfe8..af17853556e 100644
--- a/source/blender/editors/space_graph/SConscript
+++ b/source/blender/editors/space_graph/SConscript
@@ -31,12 +31,13 @@ sources = env.Glob('*.c')
incs = [
'#/intern/guardedalloc',
- '#/extern/glew/include',
- '#/intern/audaspace/intern',
+ env['BF_GLEW_INC'],
+ '#/intern/glew-mx',
'../include',
- '../../blenfont',
'../../blenkernel',
'../../blenlib',
+ '../../blentranslation',
+ '../../gpu',
'../../imbuf',
'../../makesdna',
'../../makesrna',
@@ -44,6 +45,11 @@ incs = [
]
defs = []
+defs += env['BF_GL_DEFINITIONS']
+
+if env['WITH_BF_AUDASPACE']:
+ defs += env['BF_AUDASPACE_DEF']
+ incs.append(env['BF_AUDASPACE_C_INC'])
if env['WITH_BF_INTERNATIONAL']:
defs.append('WITH_INTERNATIONAL')
diff --git a/source/blender/editors/space_graph/graph_buttons.c b/source/blender/editors/space_graph/graph_buttons.c
index b59030d3c12..8e471ceca95 100644
--- a/source/blender/editors/space_graph/graph_buttons.c
+++ b/source/blender/editors/space_graph/graph_buttons.c
@@ -44,7 +44,7 @@
#include "BLI_blenlib.h"
#include "BLI_utildefines.h"
-#include "BLF_translation.h"
+#include "BLT_translation.h"
#include "BKE_context.h"
#include "BKE_curve.h"
@@ -159,15 +159,34 @@ static void graph_panel_properties(const bContext *C, Panel *pa)
// UNUSED
// block = uiLayoutGetBlock(layout);
- // uiBlockSetHandleFunc(block, do_graph_region_buttons, NULL);
+ // UI_block_func_handle_set(block, do_graph_region_buttons, NULL);
/* F-Curve pointer */
RNA_pointer_create(ale->id, &RNA_FCurve, fcu, &fcu_ptr);
/* user-friendly 'name' for F-Curve */
- /* TODO: only show the path if this is invalid? */
col = uiLayoutColumn(layout, false);
- icon = getname_anim_fcurve(name, ale->id, fcu);
+ if (ale->type == ANIMTYPE_FCURVE) {
+ /* get user-friendly name for F-Curve */
+ icon = getname_anim_fcurve(name, ale->id, fcu);
+ }
+ else {
+ /* NLA Control Curve, etc. */
+ const bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale);
+
+ /* get name */
+ if (acf && acf->name) {
+ acf->name(ale, name);
+ }
+ else {
+ strcpy(name, IFACE_("<invalid>"));
+ icon = ICON_ERROR;
+ }
+
+ /* icon */
+ if (ale->type == ANIMTYPE_NLACURVE)
+ icon = ICON_NLA;
+ }
uiItemL(col, name, icon);
/* RNA-Path Editing - only really should be enabled when things aren't working */
@@ -210,7 +229,7 @@ static short get_active_fcurve_keyframe_edit(FCurve *fcu, BezTriple **bezt, BezT
* wants to edit numerically, there is likely to only be 1 vert selected
*/
for (i = 0, b = fcu->bezt; i < fcu->totvert; i++, b++) {
- if (BEZSELECTED(b)) {
+ if (BEZT_ISSEL_ANY(b)) {
/* found
* - 'previous' is either the one before, of the keyframe itself (which is still fine)
* XXX: we can just make this null instead if needed
@@ -315,7 +334,7 @@ static void graph_panel_key_properties(const bContext *C, Panel *pa)
return;
block = uiLayoutGetBlock(layout);
- /* uiBlockSetHandleFunc(block, do_graph_region_buttons, NULL); */
+ /* UI_block_func_handle_set(block, do_graph_region_buttons, NULL); */
/* only show this info if there are keyframes to edit */
if (get_active_fcurve_keyframe_edit(fcu, &bezt, &prevbezt)) {
@@ -366,33 +385,33 @@ 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, UI_BTYPE_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);
+ UI_but_func_set(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, UI_BTYPE_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);
+ UI_but_func_set(but, graphedit_activekey_update_cb, fcu, bezt);
+ UI_but_unit_type_set(but, unit);
}
/* previous handle - only if previous was Bezier interpolation */
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, UI_BTYPE_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_left_handle_coord_cb, fcu, bezt);
+ UI_but_func_set(but, graphedit_activekey_left_handle_coord_cb, fcu, bezt);
- but = uiDefButR(block, NUM, B_REDR, "Y:", 0, 0, UI_UNIT_X, UI_UNIT_Y,
+ but = uiDefButR(block, UI_BTYPE_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_left_handle_coord_cb, fcu, bezt);
- uiButSetUnitType(but, unit);
+ UI_but_func_set(but, graphedit_activekey_left_handle_coord_cb, fcu, bezt);
+ UI_but_unit_type_set(but, unit);
/* XXX: with label? */
- but = uiDefButR(block, MENU, B_REDR, NULL, 0, 0, UI_UNIT_X, UI_UNIT_Y,
+ but = uiDefButR(block, UI_BTYPE_MENU, B_REDR, NULL, 0, 0, UI_UNIT_X, UI_UNIT_Y,
&bezt_ptr, "handle_left_type", 0, 0, 0, -1, -1, "Type of left handle");
- uiButSetFunc(but, graphedit_activekey_handles_cb, fcu, bezt);
+ UI_but_func_set(but, graphedit_activekey_handles_cb, fcu, bezt);
}
/* next handle - only if current is Bezier interpolation */
@@ -400,19 +419,19 @@ static void graph_panel_key_properties(const bContext *C, Panel *pa)
/* NOTE: special update callbacks are needed on the coords here due to T39911 */
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, UI_BTYPE_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_right_handle_coord_cb, fcu, bezt);
+ UI_but_func_set(but, graphedit_activekey_right_handle_coord_cb, fcu, bezt);
- but = uiDefButR(block, NUM, B_REDR, "Y:", 0, 0, UI_UNIT_X, UI_UNIT_Y,
+ but = uiDefButR(block, UI_BTYPE_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_right_handle_coord_cb, fcu, bezt);
- uiButSetUnitType(but, unit);
+ UI_but_func_set(but, graphedit_activekey_right_handle_coord_cb, fcu, bezt);
+ UI_but_unit_type_set(but, unit);
/* XXX: with label? */
- but = uiDefButR(block, MENU, B_REDR, NULL, 0, 0, UI_UNIT_X, UI_UNIT_Y,
+ but = uiDefButR(block, UI_BTYPE_MENU, B_REDR, NULL, 0, 0, UI_UNIT_X, UI_UNIT_Y,
&bezt_ptr, "handle_right_type", 0, 0, 0, -1, -1, "Type of right handle");
- uiButSetFunc(but, graphedit_activekey_handles_cb, fcu, bezt);
+ UI_but_func_set(but, graphedit_activekey_handles_cb, fcu, bezt);
}
}
else {
@@ -671,22 +690,22 @@ static void graph_panel_drivers(const bContext *C, Panel *pa)
/* set event handler for panel */
block = uiLayoutGetBlock(pa->layout); // xxx?
- uiBlockSetHandleFunc(block, do_graph_region_driver_buttons, NULL);
+ UI_block_func_handle_set(block, do_graph_region_driver_buttons, NULL);
/* general actions - management */
col = uiLayoutColumn(pa->layout, false);
block = uiLayoutGetBlock(col);
- but = uiDefIconTextBut(block, BUT, B_IPO_DEPCHANGE, ICON_FILE_REFRESH, IFACE_("Update Dependencies"),
- 0, 0, 10 * UI_UNIT_X, 22,
+ but = uiDefIconTextBut(block, UI_BTYPE_BUT, B_IPO_DEPCHANGE, ICON_FILE_REFRESH, IFACE_("Update Dependencies"),
+ 0, 0, 10 * UI_UNIT_X, UI_UNIT_Y,
NULL, 0.0, 0.0, 0, 0,
TIP_("Force updates of dependencies"));
- uiButSetFunc(but, driver_update_flags_cb, fcu, NULL);
+ UI_but_func_set(but, driver_update_flags_cb, fcu, NULL);
- but = uiDefIconTextBut(block, BUT, B_IPO_DEPCHANGE, ICON_ZOOMOUT, IFACE_("Remove Driver"),
- 0, 0, 10 * UI_UNIT_X, 18,
+ but = uiDefIconTextBut(block, UI_BTYPE_BUT, B_IPO_DEPCHANGE, ICON_ZOOMOUT, IFACE_("Remove Driver"),
+ 0, 0, 10 * UI_UNIT_X, UI_UNIT_Y,
NULL, 0.0, 0.0, 0, 0,
TIP_("Remove this driver"));
- uiButSetNFunc(but, driver_remove_cb, MEM_dupallocN(ale), NULL);
+ UI_but_funcN_set(but, driver_remove_cb, MEM_dupallocN(ale), NULL);
/* driver-level settings - type, expressions, and errors */
RNA_pointer_create(ale->id, &RNA_Driver, driver, &driver_ptr);
@@ -763,11 +782,11 @@ static void graph_panel_drivers(const bContext *C, Panel *pa)
/* add driver variables */
col = uiLayoutColumn(pa->layout, false);
block = uiLayoutGetBlock(col);
- but = uiDefIconTextBut(block, BUT, B_IPO_DEPCHANGE, ICON_ZOOMIN, IFACE_("Add Variable"),
+ but = uiDefIconTextBut(block, UI_BTYPE_BUT, B_IPO_DEPCHANGE, ICON_ZOOMIN, IFACE_("Add Variable"),
0, 0, 10 * UI_UNIT_X, UI_UNIT_Y,
NULL, 0.0, 0.0, 0, 0,
TIP_("Driver variables ensure that all dependencies will be accounted for and that drivers will update correctly"));
- uiButSetFunc(but, driver_add_var_cb, driver, NULL);
+ UI_but_func_set(but, driver_add_var_cb, driver, NULL);
/* loop over targets, drawing them */
for (dvar = driver->variables.first; dvar; dvar = dvar->next) {
@@ -788,11 +807,11 @@ static void graph_panel_drivers(const bContext *C, Panel *pa)
uiItemR(row, &dvar_ptr, "name", 0, "", ICON_NONE);
/* remove button */
- uiBlockSetEmboss(block, UI_EMBOSSN);
- but = uiDefIconBut(block, BUT, B_IPO_DEPCHANGE, ICON_X, 290, 0, UI_UNIT_X, UI_UNIT_Y,
+ UI_block_emboss_set(block, UI_EMBOSS_NONE);
+ but = uiDefIconBut(block, UI_BTYPE_BUT, B_IPO_DEPCHANGE, ICON_X, 290, 0, UI_UNIT_X, UI_UNIT_Y,
NULL, 0.0, 0.0, 0.0, 0.0, IFACE_("Delete target variable"));
- uiButSetFunc(but, driver_delete_var_cb, driver, dvar);
- uiBlockSetEmboss(block, UI_EMBOSS);
+ UI_but_func_set(but, driver_delete_var_cb, driver, dvar);
+ UI_block_emboss_set(block, UI_EMBOSS);
/* variable type */
row = uiLayoutRow(box, false);
@@ -864,12 +883,13 @@ static void graph_panel_modifiers(const bContext *C, Panel *pa)
FModifier *fcm;
uiLayout *col, *row;
uiBlock *block;
+ bool active;
if (!graph_panel_context(C, &ale, &fcu))
return;
block = uiLayoutGetBlock(pa->layout);
- uiBlockSetHandleFunc(block, do_graph_region_modifier_buttons, NULL);
+ UI_block_func_handle_set(block, do_graph_region_modifier_buttons, NULL);
/* 'add modifier' button at top of panel */
{
@@ -879,7 +899,7 @@ static void graph_panel_modifiers(const bContext *C, Panel *pa)
/* this is an operator button which calls a 'add modifier' operator...
* a menu might be nicer but would be tricky as we need some custom filtering
*/
- uiDefButO(block, BUT, "GRAPH_OT_fmodifier_add", WM_OP_INVOKE_REGION_WIN, IFACE_("Add Modifier"),
+ uiDefButO(block, UI_BTYPE_BUT, "GRAPH_OT_fmodifier_add", WM_OP_INVOKE_REGION_WIN, IFACE_("Add Modifier"),
0.5 * UI_UNIT_X, 0, 7.5 * UI_UNIT_X, UI_UNIT_Y, TIP_("Adds a new F-Curve Modifier for the active F-Curve"));
/* copy/paste (as sub-row)*/
@@ -888,9 +908,11 @@ static void graph_panel_modifiers(const bContext *C, Panel *pa)
uiItemO(row, "", ICON_PASTEDOWN, "GRAPH_OT_fmodifier_paste");
}
+ active = !(fcu->flag & FCURVE_MOD_OFF);
/* draw each modifier */
for (fcm = fcu->modifiers.first; fcm; fcm = fcm->next) {
col = uiLayoutColumn(pa->layout, true);
+ uiLayoutSetActive(col, active);
ANIM_uiTemplate_fmodifier_draw(col, ale->id, &fcu->modifiers, fcm);
}
@@ -907,7 +929,7 @@ void graph_buttons_register(ARegionType *art)
pt = MEM_callocN(sizeof(PanelType), "spacetype graph panel view");
strcpy(pt->idname, "GRAPH_PT_view");
strcpy(pt->label, N_("View Properties"));
- strcpy(pt->translation_context, BLF_I18NCONTEXT_DEFAULT_BPYRNA);
+ strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
pt->draw = graph_panel_view;
pt->flag |= PNL_DEFAULT_CLOSED;
BLI_addtail(&art->paneltypes, pt);
@@ -915,7 +937,7 @@ void graph_buttons_register(ARegionType *art)
pt = MEM_callocN(sizeof(PanelType), "spacetype graph panel properties");
strcpy(pt->idname, "GRAPH_PT_properties");
strcpy(pt->label, N_("Active F-Curve"));
- strcpy(pt->translation_context, BLF_I18NCONTEXT_DEFAULT_BPYRNA);
+ strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
pt->draw = graph_panel_properties;
pt->poll = graph_panel_poll;
BLI_addtail(&art->paneltypes, pt);
@@ -923,7 +945,7 @@ void graph_buttons_register(ARegionType *art)
pt = MEM_callocN(sizeof(PanelType), "spacetype graph panel properties");
strcpy(pt->idname, "GRAPH_PT_key_properties");
strcpy(pt->label, N_("Active Keyframe"));
- strcpy(pt->translation_context, BLF_I18NCONTEXT_DEFAULT_BPYRNA);
+ strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
pt->draw = graph_panel_key_properties;
pt->poll = graph_panel_poll;
BLI_addtail(&art->paneltypes, pt);
@@ -932,7 +954,7 @@ void graph_buttons_register(ARegionType *art)
pt = MEM_callocN(sizeof(PanelType), "spacetype graph panel drivers");
strcpy(pt->idname, "GRAPH_PT_drivers");
strcpy(pt->label, N_("Drivers"));
- strcpy(pt->translation_context, BLF_I18NCONTEXT_DEFAULT_BPYRNA);
+ strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
pt->draw = graph_panel_drivers;
pt->poll = graph_panel_drivers_poll;
BLI_addtail(&art->paneltypes, pt);
@@ -940,7 +962,7 @@ void graph_buttons_register(ARegionType *art)
pt = MEM_callocN(sizeof(PanelType), "spacetype graph panel modifiers");
strcpy(pt->idname, "GRAPH_PT_modifiers");
strcpy(pt->label, N_("Modifiers"));
- strcpy(pt->translation_context, BLF_I18NCONTEXT_DEFAULT_BPYRNA);
+ strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
pt->draw = graph_panel_modifiers;
pt->poll = graph_panel_poll;
BLI_addtail(&art->paneltypes, pt);
diff --git a/source/blender/editors/space_graph/graph_draw.c b/source/blender/editors/space_graph/graph_draw.c
index ed7cfe7da99..91e11ac4b1e 100644
--- a/source/blender/editors/space_graph/graph_draw.c
+++ b/source/blender/editors/space_graph/graph_draw.c
@@ -33,6 +33,7 @@
#include <float.h>
#include "BLI_blenlib.h"
+#include "BLI_math.h"
#include "BLI_utildefines.h"
#include "DNA_anim_types.h"
@@ -42,6 +43,7 @@
#include "DNA_userdef_types.h"
#include "BKE_context.h"
+#include "BKE_curve.h"
#include "BKE_fcurve.h"
@@ -227,7 +229,7 @@ static void draw_fcurve_vertices_handles(FCurve *fcu, SpaceIpo *sipo, View2D *v2
* Also, need to take into account whether the keyframe was selected
* if a Graph Editor option to only show handles of selected keys is on.
*/
- if (!sel_handle_only || BEZSELECTED(bezt)) {
+ if (!sel_handle_only || BEZT_ISSEL_ANY(bezt)) {
if ((!prevbezt && (bezt->ipo == BEZT_IPO_BEZ)) || (prevbezt && (prevbezt->ipo == BEZT_IPO_BEZ))) {
if ((bezt->f1 & SELECT) == sel) /* && v2d->cur.xmin < bezt->vec[0][0] < v2d->cur.xmax)*/
draw_fcurve_handle_control(bezt->vec[0][0], bezt->vec[0][1], xscale, yscale, hsize);
@@ -343,7 +345,7 @@ static void draw_fcurve_handles(SpaceIpo *sipo, FCurve *fcu)
* check that keyframe is selected
*/
if (sipo->flag & SIPO_SELVHANDLESONLY) {
- if (BEZSELECTED(bezt) == 0)
+ if (BEZT_ISSEL_ANY(bezt) == 0)
continue;
}
@@ -475,10 +477,11 @@ static void draw_fcurve_samples(SpaceIpo *sipo, ARegion *ar, FCurve *fcu)
/* helper func - just draw the F-Curve by sampling the visible region (for drawing curves with modifiers) */
static void draw_fcurve_curve(bAnimContext *ac, ID *id, FCurve *fcu, View2D *v2d, View2DGrid *grid)
{
+ SpaceIpo *sipo = (SpaceIpo *)ac->sl;
ChannelDriver *driver;
float samplefreq;
float stime, etime;
- float unitFac;
+ float unitFac, offset;
float dx, dy;
short mapping_flag = ANIM_get_normalization_flags(ac);
int i, n;
@@ -495,14 +498,14 @@ static void draw_fcurve_curve(bAnimContext *ac, ID *id, FCurve *fcu, View2D *v2d
fcu->driver = NULL;
/* compute unit correction factor */
- unitFac = ANIM_unit_mapping_get_factor(ac->scene, id, fcu, mapping_flag);
+ unitFac = ANIM_unit_mapping_get_factor(ac->scene, id, fcu, mapping_flag, &offset);
/* Note about sampling frequency:
* Ideally, this is chosen such that we have 1-2 pixels = 1 segment
* which means that our curves can be as smooth as possible. However,
* this does mean that curves may not be fully accurate (i.e. if they have
* sudden spikes which happen at the sampling point, we may have problems).
- * Also, this may introduce lower performance on less densely detailed curves,'
+ * Also, this may introduce lower performance on less densely detailed curves,
* though it is impossible to predict this from the modifiers!
*
* If the automatically determined sampling frequency is likely to cause an infinite
@@ -512,7 +515,25 @@ static void draw_fcurve_curve(bAnimContext *ac, ID *id, FCurve *fcu, View2D *v2d
/* grid->dx represents the number of 'frames' between gridlines, but we divide by U.v2d_min_gridsize to get pixels-steps */
/* TODO: perhaps we should have 1.0 frames as upper limit so that curves don't get too distorted? */
samplefreq = dx / (U.v2d_min_gridsize * U.pixelsize);
- if (samplefreq < 0.00001f) samplefreq = 0.00001f;
+
+ if (sipo->flag & SIPO_BEAUTYDRAW_OFF) {
+ /* Low Precision = coarse lower-bound clamping
+ *
+ * Although the "Beauty Draw" flag was originally for AA'd
+ * line drawing, the sampling rate here has a much greater
+ * impact on performance (e.g. for T40372)!
+ *
+ * This one still amounts to 10 sample-frames for each 1-frame interval
+ * which should be quite a decent approximation in many situations.
+ */
+ if (samplefreq < 0.1f)
+ samplefreq = 0.1f;
+ }
+ else {
+ /* "Higher Precision" but slower - especially on larger windows (e.g. T40372) */
+ if (samplefreq < 0.00001f)
+ samplefreq = 0.00001f;
+ }
/* the start/end times are simply the horizontal extents of the 'cur' rect */
@@ -525,12 +546,13 @@ static void draw_fcurve_curve(bAnimContext *ac, ID *id, FCurve *fcu, View2D *v2d
* the displayed values appear correctly in the viewport
*/
glBegin(GL_LINE_STRIP);
-
- for (i = 0, n = (etime - stime) / samplefreq + 0.5f; i < n; ++i) {
+
+ n = (etime - stime) / samplefreq + 0.5f;
+ for (i = 0; i <= n; i++) {
float ctime = stime + i * samplefreq;
- glVertex2f(ctime, evaluate_fcurve(fcu, ctime) * unitFac);
+ glVertex2f(ctime, (evaluate_fcurve(fcu, ctime) + offset) * unitFac);
}
-
+
glEnd();
/* restore driver */
@@ -544,13 +566,14 @@ static void draw_fcurve_curve_samples(bAnimContext *ac, ID *id, FCurve *fcu, Vie
FPoint *fpt = prevfpt + 1;
float fac, v[2];
int b = fcu->totvert - 1;
- float unit_scale;
+ float unit_scale, offset;
short mapping_flag = ANIM_get_normalization_flags(ac);
/* apply unit mapping */
glPushMatrix();
- unit_scale = ANIM_unit_mapping_get_factor(ac->scene, id, fcu, mapping_flag);
+ unit_scale = ANIM_unit_mapping_get_factor(ac->scene, id, fcu, mapping_flag, &offset);
glScalef(1.0f, unit_scale, 1.0f);
+ glTranslatef(0.0f, offset, 0.0f);
glBegin(GL_LINE_STRIP);
@@ -616,8 +639,24 @@ static void draw_fcurve_curve_samples(bAnimContext *ac, ID *id, FCurve *fcu, Vie
glPopMatrix();
}
-#if 0
-/* helper func - draw one repeat of an F-Curve */
+/* helper func - check if the F-Curve only contains easily drawable segments
+ * (i.e. no easing equation interpolations)
+ */
+static bool fcurve_can_use_simple_bezt_drawing(FCurve *fcu)
+{
+ BezTriple *bezt;
+ int i;
+
+ for (i = 0, bezt = fcu->bezt; i < fcu->totvert; i++, bezt++) {
+ if (ELEM(bezt->ipo, BEZT_IPO_CONST, BEZT_IPO_LIN, BEZT_IPO_BEZ) == false) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+/* helper func - draw one repeat of an F-Curve (using Bezier curve approximations) */
static void draw_fcurve_curve_bezts(bAnimContext *ac, ID *id, FCurve *fcu, View2D *v2d)
{
BezTriple *prevbezt = fcu->bezt;
@@ -627,13 +666,14 @@ static void draw_fcurve_curve_bezts(bAnimContext *ac, ID *id, FCurve *fcu, View2
float fac = 0.0f;
int b = fcu->totvert - 1;
int resol;
- float unit_scale;
+ float unit_scale, offset;
short mapping_flag = ANIM_get_normalization_flags(ac);
-
+
/* apply unit mapping */
glPushMatrix();
- unit_scale = ANIM_unit_mapping_get_factor(ac->scene, id, fcu, mapping_flag);
+ unit_scale = ANIM_unit_mapping_get_factor(ac->scene, id, fcu, mapping_flag, &offset);
glScalef(1.0f, unit_scale, 1.0f);
+ glTranslatef(0.0f, offset, 0.0f);
glBegin(GL_LINE_STRIP);
@@ -689,17 +729,19 @@ static void draw_fcurve_curve_bezts(bAnimContext *ac, ID *id, FCurve *fcu, View2
v1[1] = prevbezt->vec[1][1];
glVertex2fv(v1);
}
- else {
+ else if (prevbezt->ipo == BEZT_IPO_BEZ) {
/* Bezier-Interpolation: draw curve as series of segments between keyframes
* - resol determines number of points to sample in between keyframes
*/
/* resol depends on distance between points (not just horizontal) OR is a fixed high res */
/* TODO: view scale should factor into this someday too... */
- if (fcu->driver)
+ if (fcu->driver) {
resol = 32;
- else
+ }
+ else {
resol = (int)(5.0f * len_v2v2(bezt->vec[1], prevbezt->vec[1]));
+ }
if (resol < 2) {
/* only draw one */
@@ -773,7 +815,6 @@ static void draw_fcurve_curve_bezts(bAnimContext *ac, ID *id, FCurve *fcu, View2
glEnd();
glPopMatrix();
}
-#endif
/* Debugging -------------------------------- */
@@ -787,7 +828,8 @@ static void graph_draw_driver_debug(bAnimContext *ac, ID *id, FCurve *fcu)
ChannelDriver *driver = fcu->driver;
View2D *v2d = &ac->ar->v2d;
short mapping_flag = ANIM_get_normalization_flags(ac);
- float unitfac = ANIM_unit_mapping_get_factor(ac->scene, id, fcu, mapping_flag);
+ float offset;
+ float unitfac = ANIM_unit_mapping_get_factor(ac->scene, id, fcu, mapping_flag, &offset);
/* for now, only show when debugging driver... */
//if ((driver->flag & DRIVER_FLAG_SHOWDEBUG) == 0)
@@ -809,11 +851,13 @@ static void graph_draw_driver_debug(bAnimContext *ac, ID *id, FCurve *fcu)
* NOTE: we need to scale the y-values to be valid for the units
*/
glBegin(GL_LINES);
+ {
t = v2d->cur.xmin;
- glVertex2f(t, t * unitfac);
+ glVertex2f(t, (t + offset) * unitfac);
t = v2d->cur.xmax;
- glVertex2f(t, t * unitfac);
+ glVertex2f(t, (t + offset) * unitfac);
+ }
glEnd();
/* cleanup line drawing */
@@ -836,6 +880,7 @@ static void graph_draw_driver_debug(bAnimContext *ac, ID *id, FCurve *fcu)
setlinestyle(5);
glBegin(GL_LINES);
+ {
/* x-axis lookup */
co[0] = x;
@@ -855,6 +900,7 @@ static void graph_draw_driver_debug(bAnimContext *ac, ID *id, FCurve *fcu)
co[0] = x;
glVertex2fv(co);
+ }
glEnd();
setlinestyle(0);
@@ -865,7 +911,7 @@ static void graph_draw_driver_debug(bAnimContext *ac, ID *id, FCurve *fcu)
glPointSize(7.0);
glBegin(GL_POINTS);
- glVertex2f(x, y);
+ glVertex2f(x, y);
glEnd();
/* inner frame */
@@ -873,7 +919,7 @@ static void graph_draw_driver_debug(bAnimContext *ac, ID *id, FCurve *fcu)
glPointSize(3.0);
glBegin(GL_POINTS);
- glVertex2f(x, y);
+ glVertex2f(x, y);
glEnd();
glPointSize(1.0f);
@@ -989,11 +1035,15 @@ void graph_draw_curves(bAnimContext *ac, SpaceIpo *sipo, ARegion *ar, View2DGrid
}
else if (((fcu->bezt) || (fcu->fpt)) && (fcu->totvert)) {
/* just draw curve based on defined data (i.e. no modifiers) */
- if (fcu->bezt)
- //draw_fcurve_curve_bezts(ac, ale->id, fcu, &ar->v2d);
- draw_fcurve_curve(ac, ale->id, fcu, &ar->v2d, grid); // XXX: better to do an optimised integration here instead, but for now, this works
- else if (fcu->fpt)
+ if (fcu->bezt) {
+ if (fcurve_can_use_simple_bezt_drawing(fcu))
+ draw_fcurve_curve_bezts(ac, ale->id, fcu, &ar->v2d);
+ else
+ draw_fcurve_curve(ac, ale->id, fcu, &ar->v2d, grid);
+ }
+ else if (fcu->fpt) {
draw_fcurve_curve_samples(ac, ale->id, fcu, &ar->v2d);
+ }
}
/* restore settings */
@@ -1020,10 +1070,12 @@ void graph_draw_curves(bAnimContext *ac, SpaceIpo *sipo, ARegion *ar, View2DGrid
}
else if (((fcu->bezt) || (fcu->fpt)) && (fcu->totvert)) {
short mapping_flag = ANIM_get_normalization_flags(ac);
- float unit_scale = ANIM_unit_mapping_get_factor(ac->scene, ale->id, fcu, mapping_flag);
+ float offset;
+ float unit_scale = ANIM_unit_mapping_get_factor(ac->scene, ale->id, fcu, mapping_flag, &offset);
glPushMatrix();
glScalef(1.0f, unit_scale, 1.0f);
+ glTranslatef(0.0f, offset, 0.0f);
if (fcu->bezt) {
bool do_handles = draw_fcurve_handles_check(sipo, fcu);
@@ -1090,6 +1142,8 @@ void graph_draw_channel_names(bContext *C, bAnimContext *ac, ARegion *ar)
/* loop through channels, and set up drawing depending on their type */
{ /* first pass: just the standard GL-drawing for backdrop + text */
+ size_t channel_index = 0;
+
y = (float)ACHANNEL_FIRST;
for (ale = anim_data.first, i = 0; ale; ale = ale->next, i++) {
@@ -1101,15 +1155,16 @@ void graph_draw_channel_names(bContext *C, bAnimContext *ac, ARegion *ar)
IN_RANGE(ymaxc, v2d->cur.ymin, v2d->cur.ymax) )
{
/* draw all channels using standard channel-drawing API */
- ANIM_channel_draw(ac, ale, yminc, ymaxc);
+ ANIM_channel_draw(ac, ale, yminc, ymaxc, channel_index);
}
/* adjust y-position for next one */
y -= ACHANNEL_STEP;
+ channel_index++;
}
}
{ /* second pass: widgets */
- uiBlock *block = uiBeginBlock(C, ar, __func__, UI_EMBOSS);
+ uiBlock *block = UI_block_begin(C, ar, __func__, UI_EMBOSS);
size_t channel_index = 0;
y = (float)ACHANNEL_FIRST;
@@ -1135,8 +1190,8 @@ void graph_draw_channel_names(bContext *C, bAnimContext *ac, ARegion *ar)
channel_index++;
}
- uiEndBlock(C, block);
- uiDrawBlock(C, block);
+ UI_block_end(C, block);
+ UI_block_draw(C, block);
glDisable(GL_BLEND);
}
diff --git a/source/blender/editors/space_graph/graph_edit.c b/source/blender/editors/space_graph/graph_edit.c
index c8298927f7d..ca5d2db80e7 100644
--- a/source/blender/editors/space_graph/graph_edit.c
+++ b/source/blender/editors/space_graph/graph_edit.c
@@ -36,7 +36,7 @@
#include <float.h>
#ifdef WITH_AUDASPACE
-# include "AUD_C-API.h"
+# include AUD_SPECIAL_H
#endif
#include "MEM_guardedalloc.h"
@@ -52,7 +52,7 @@
#include "RNA_define.h"
#include "RNA_enum_types.h"
-#include "BLF_translation.h"
+#include "BLT_translation.h"
#include "BKE_fcurve.h"
#include "BKE_global.h"
@@ -60,8 +60,6 @@
#include "BKE_context.h"
#include "BKE_report.h"
-#include "UI_interface.h"
-#include "UI_resources.h"
#include "UI_view2d.h"
#include "ED_anim_api.h"
@@ -111,7 +109,7 @@ void get_graph_keyframe_extents(bAnimContext *ac, float *xmin, float *xmax, floa
AnimData *adt = ANIM_nla_mapping_get(ac, ale);
FCurve *fcu = (FCurve *)ale->key_data;
float txmin, txmax, tymin, tymax;
- float unitFac;
+ float unitFac, offset;
/* get range */
if (calc_fcurve_bounds(fcu, &txmin, &txmax, &tymin, &tymax, do_sel_only, include_handles)) {
@@ -124,7 +122,9 @@ void get_graph_keyframe_extents(bAnimContext *ac, float *xmin, float *xmax, floa
}
/* apply unit corrections */
- unitFac = ANIM_unit_mapping_get_factor(ac->scene, ale->id, fcu, mapping_flag);
+ unitFac = ANIM_unit_mapping_get_factor(ac->scene, ale->id, fcu, mapping_flag, &offset);
+ tymin += offset;
+ tymax += offset;
tymin *= unitFac;
tymax *= unitFac;
@@ -258,6 +258,14 @@ static int graphkeys_view_selected_exec(bContext *C, wmOperator *op)
return graphkeys_viewall(C, true, include_handles, smooth_viewtx);
}
+static int graphkeys_view_frame_exec(bContext *C, wmOperator *op)
+{
+ const int smooth_viewtx = WM_operator_smooth_viewtx_get(op);
+ ANIM_center_frame(C, smooth_viewtx);
+ return OPERATOR_FINISHED;
+}
+
+
void GRAPH_OT_view_all(wmOperatorType *ot)
{
/* identifiers */
@@ -296,6 +304,21 @@ void GRAPH_OT_view_selected(wmOperatorType *ot)
"Include handles of keyframes when calculating extents");
}
+void GRAPH_OT_view_frame(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "View Frame";
+ ot->idname = "GRAPH_OT_view_frame";
+ ot->description = "Reset viewable area to show range around current frame";
+
+ /* api callbacks */
+ ot->exec = graphkeys_view_frame_exec;
+ ot->poll = ED_operator_graphedit_active; /* XXX: unchecked poll to get fsamples working too, but makes modifier damage trickier... */
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
/* ******************** Create Ghost-Curves Operator *********************** */
/* This operator samples the data of the selected F-Curves to F-Points, storing them
* as 'ghost curves' in the active Graph Editor
@@ -329,7 +352,7 @@ static void create_ghost_curves(bAnimContext *ac, int start, int end)
AnimData *adt = ANIM_nla_mapping_get(ac, ale);
ChannelDriver *driver = fcu->driver;
FPoint *fpt;
- float unitFac;
+ float unitFac, offset;
int cfra;
SpaceIpo *sipo = (SpaceIpo *) ac->sl;
short mapping_flag = ANIM_get_normalization_flags(ac);
@@ -338,7 +361,7 @@ static void create_ghost_curves(bAnimContext *ac, int start, int end)
fcu->driver = NULL;
/* calculate unit-mapping factor */
- unitFac = ANIM_unit_mapping_get_factor(ac->scene, ale->id, fcu, mapping_flag);
+ unitFac = ANIM_unit_mapping_get_factor(ac->scene, ale->id, fcu, mapping_flag, &offset);
/* create samples, but store them in a new curve
* - we cannot use fcurve_store_samples() as that will only overwrite the original curve
@@ -351,7 +374,7 @@ static void create_ghost_curves(bAnimContext *ac, int start, int end)
float cfrae = BKE_nla_tweakedit_remap(adt, cfra, NLATIME_CONVERT_UNMAP);
fpt->vec[0] = cfrae;
- fpt->vec[1] = fcurve_samplingcb_evalcurve(fcu, NULL, cfrae) * unitFac;
+ fpt->vec[1] = (fcurve_samplingcb_evalcurve(fcu, NULL, cfrae) + offset) * unitFac;
}
/* set color of ghost curve
@@ -500,12 +523,17 @@ static void insert_graph_keys(bAnimContext *ac, short mode)
else
cfra = (float)CFRA;
- /* if there's an id */
- if (ale->id)
+ /* read value from property the F-Curve represents, or from the curve only?
+ * - ale->id != NULL: Typically, this means that we have enough info to try resolving the path
+ * - ale->owner != NULL: If this is set, then the path may not be resolvable from the ID alone,
+ * so it's easier for now to just read the F-Curve directly.
+ * (TODO: add the full-blown PointerRNA relative parsing case here...)
+ */
+ if (ale->id && !ale->owner)
insert_keyframe(reports, ale->id, NULL, ((fcu->grp) ? (fcu->grp->name) : (NULL)), fcu->rna_path, fcu->array_index, cfra, flag);
else
insert_vert_fcurve(fcu, cfra, fcu->curval, 0);
-
+
ale->update |= ANIM_UPDATE_DEFAULT;
}
@@ -584,7 +612,7 @@ static int graphkeys_click_insert_exec(bContext *C, wmOperator *op)
ListBase anim_data;
short mapping_flag = ANIM_get_normalization_flags(&ac);
-
+ float scale, offset;
/* get frame and value from props */
frame = RNA_float_get(op->ptr, "frame");
val = RNA_float_get(op->ptr, "value");
@@ -594,16 +622,18 @@ static int graphkeys_click_insert_exec(bContext *C, wmOperator *op)
frame = BKE_nla_tweakedit_remap(adt, frame, NLATIME_CONVERT_UNMAP);
/* apply inverse unit-mapping to value to get correct value for F-Curves */
- val *= ANIM_unit_mapping_get_factor(ac.scene, ale->id, fcu, mapping_flag | ANIM_UNITCONV_RESTORE);
-
+ scale = ANIM_unit_mapping_get_factor(ac.scene, ale->id, fcu, mapping_flag | ANIM_UNITCONV_RESTORE, &offset);
+
+ val = val * scale - offset;
+
/* insert keyframe on the specified frame + value */
insert_vert_fcurve(fcu, frame, val, 0);
-
+
ale->update |= ANIM_UPDATE_DEPS;
-
+
BLI_listbase_clear(&anim_data);
BLI_addtail(&anim_data, ale);
-
+
ANIM_animdata_update(&ac, &anim_data);
}
else {
@@ -699,7 +729,7 @@ static short copy_graph_keys(bAnimContext *ac)
}
static short paste_graph_keys(bAnimContext *ac,
- const eKeyPasteOffset offset_mode, const eKeyMergeMode merge_mode)
+ const eKeyPasteOffset offset_mode, const eKeyMergeMode merge_mode, bool flip)
{
ListBase anim_data = {NULL, NULL};
int filter, ok = 0;
@@ -716,7 +746,7 @@ static short paste_graph_keys(bAnimContext *ac,
ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
/* paste keyframes */
- ok = paste_animedit_keys(ac, &anim_data, offset_mode, merge_mode);
+ ok = paste_animedit_keys(ac, &anim_data, offset_mode, merge_mode, flip);
/* clean up */
ANIM_animdata_freelist(&anim_data);
@@ -767,6 +797,7 @@ static int graphkeys_paste_exec(bContext *C, wmOperator *op)
const eKeyPasteOffset offset_mode = RNA_enum_get(op->ptr, "offset");
const eKeyMergeMode merge_mode = RNA_enum_get(op->ptr, "merge");
+ const bool flipped = RNA_boolean_get(op->ptr, "flipped");
/* get editor data */
if (ANIM_animdata_get_context(C, &ac) == 0)
@@ -776,7 +807,7 @@ static int graphkeys_paste_exec(bContext *C, wmOperator *op)
ac.reports = op->reports;
/* paste keyframes - non-zero return means an error occurred while trying to paste */
- if (paste_graph_keys(&ac, offset_mode, merge_mode)) {
+ if (paste_graph_keys(&ac, offset_mode, merge_mode, flipped)) {
return OPERATOR_CANCELLED;
}
@@ -788,6 +819,8 @@ static int graphkeys_paste_exec(bContext *C, wmOperator *op)
void GRAPH_OT_paste(wmOperatorType *ot)
{
+ PropertyRNA *prop;
+
/* identifiers */
ot->name = "Paste Keyframes";
ot->idname = "GRAPH_OT_paste";
@@ -804,6 +837,8 @@ void GRAPH_OT_paste(wmOperatorType *ot)
/* props */
RNA_def_enum(ot->srna, "offset", keyframe_paste_offset_items, KEYFRAME_PASTE_OFFSET_CFRA_START, "Offset", "Paste time offset of keys");
RNA_def_enum(ot->srna, "merge", keyframe_paste_merge_items, KEYFRAME_PASTE_MERGE_MIX, "Type", "Method of merging pasted keys and existing");
+ prop = RNA_def_boolean(ot->srna, "flipped", false, "Flipped", "Paste keyframes from mirrored bones if they exist");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
/* ******************** Duplicate Keyframes Operator ************************* */
@@ -848,13 +883,6 @@ static int graphkeys_duplicate_exec(bContext *C, wmOperator *UNUSED(op))
return OPERATOR_FINISHED;
}
-static int graphkeys_duplicate_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
-{
- graphkeys_duplicate_exec(C, op);
-
- return OPERATOR_FINISHED;
-}
-
void GRAPH_OT_duplicate(wmOperatorType *ot)
{
/* identifiers */
@@ -863,7 +891,6 @@ void GRAPH_OT_duplicate(wmOperatorType *ot)
ot->description = "Make a copy of all selected keyframes";
/* api callbacks */
- ot->invoke = graphkeys_duplicate_invoke;
ot->exec = graphkeys_duplicate_exec;
ot->poll = graphop_editable_keyframes_poll;
@@ -955,7 +982,7 @@ void GRAPH_OT_delete(wmOperatorType *ot)
/* ******************** Clean Keyframes Operator ************************* */
-static void clean_graph_keys(bAnimContext *ac, float thresh)
+static void clean_graph_keys(bAnimContext *ac, float thresh, bool clean_chan)
{
ListBase anim_data = {NULL, NULL};
bAnimListElem *ale;
@@ -967,7 +994,7 @@ static void clean_graph_keys(bAnimContext *ac, float thresh)
/* loop through filtered data and clean curves */
for (ale = anim_data.first; ale; ale = ale->next) {
- clean_fcurve((FCurve *)ale->key_data, thresh);
+ clean_fcurve(ac, ale, thresh, clean_chan);
ale->update |= ANIM_UPDATE_DEFAULT;
}
@@ -982,6 +1009,7 @@ static int graphkeys_clean_exec(bContext *C, wmOperator *op)
{
bAnimContext ac;
float thresh;
+ bool clean_chan;
/* get editor data */
if (ANIM_animdata_get_context(C, &ac) == 0)
@@ -989,9 +1017,9 @@ static int graphkeys_clean_exec(bContext *C, wmOperator *op)
/* get cleaning threshold */
thresh = RNA_float_get(op->ptr, "threshold");
-
+ clean_chan = RNA_boolean_get(op->ptr, "channels");
/* clean keyframes */
- clean_graph_keys(&ac, thresh);
+ clean_graph_keys(&ac, thresh, clean_chan);
/* set notifier that keyframes have changed */
WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL);
@@ -1016,6 +1044,7 @@ void GRAPH_OT_clean(wmOperatorType *ot)
/* properties */
ot->prop = RNA_def_float(ot->srna, "threshold", 0.001f, 0.0f, FLT_MAX, "Threshold", "", 0.0f, 1000.0f);
+ RNA_def_boolean(ot->srna, "channels", false, "Channels", "");
}
/* ******************** Bake F-Curve Operator *********************** */
@@ -1152,6 +1181,11 @@ static int graphkeys_sound_bake_exec(bContext *C, wmOperator *op)
RNA_string_get(op->ptr, "filepath", path);
+ if (!BLI_is_file(path)) {
+ BKE_reportf(op->reports, RPT_ERROR, "File not found '%s'", path);
+ return OPERATOR_CANCELLED;
+ }
+
scene = ac.scene; /* current scene */
/* store necessary data for the baking steps */
@@ -1241,8 +1275,8 @@ void GRAPH_OT_sound_bake(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
/* properties */
- WM_operator_properties_filesel(ot, FOLDERFILE | SOUNDFILE | MOVIEFILE, FILE_SPECIAL, FILE_OPENFILE,
- WM_FILESEL_FILEPATH, FILE_DEFAULTDISPLAY);
+ WM_operator_properties_filesel(ot, FILE_TYPE_FOLDER | FILE_TYPE_SOUND | FILE_TYPE_MOVIE, FILE_SPECIAL, FILE_OPENFILE,
+ WM_FILESEL_FILEPATH, FILE_DEFAULTDISPLAY, FILE_SORT_ALPHA);
RNA_def_float(ot->srna, "low", 0.0f, 0.0, 100000.0, "Lowest frequency",
"Cutoff frequency of a high-pass filter that is applied to the audio data", 0.1, 1000.00);
RNA_def_float(ot->srna, "high", 100000.0, 0.0, 100000.0, "Highest frequency",
@@ -1718,7 +1752,7 @@ static int graphkeys_euler_filter_exec(bContext *C, wmOperator *op)
* so if the paths or the ID's don't match up, then a curve needs to be added
* to a new group
*/
- if ((euf) && (euf->id == ale->id) && (strcmp(euf->rna_path, fcu->rna_path) == 0)) {
+ if ((euf) && (euf->id == ale->id) && (STREQ(euf->rna_path, fcu->rna_path))) {
/* this should be fine to add to the existing group then */
euf->fcurves[fcu->array_index] = fcu;
}
@@ -1874,7 +1908,8 @@ static int graphkeys_framejump_exec(bContext *C, wmOperator *UNUSED(op))
AnimData *adt = ANIM_nla_mapping_get(&ac, ale);
short mapping_flag = ANIM_get_normalization_flags(&ac);
KeyframeEditData current_ked;
- float unit_scale = ANIM_unit_mapping_get_factor(ac.scene, ale->id, ale->key_data, mapping_flag | ANIM_UNITCONV_ONLYKEYS);
+ float offset;
+ float unit_scale = ANIM_unit_mapping_get_factor(ac.scene, ale->id, ale->key_data, mapping_flag | ANIM_UNITCONV_ONLYKEYS, &offset);
memset(&current_ked, 0, sizeof(current_ked));
@@ -1888,7 +1923,7 @@ static int graphkeys_framejump_exec(bContext *C, wmOperator *UNUSED(op))
ked.f1 += current_ked.f1;
ked.i1 += current_ked.i1;
- ked.f2 += current_ked.f2 / unit_scale;
+ ked.f2 += (current_ked.f2 + offset) * unit_scale;
ked.i2 += current_ked.i2;
}
@@ -1981,9 +2016,10 @@ static void snap_graph_keys(bAnimContext *ac, short mode)
/* normalise cursor value (for normalised F-Curves display) */
if (mode == GRAPHKEYS_SNAP_VALUE) {
short mapping_flag = ANIM_get_normalization_flags(ac);
- float unit_scale = ANIM_unit_mapping_get_factor(ac->scene, ale->id, ale->key_data, mapping_flag);
+ float offset;
+ float unit_scale = ANIM_unit_mapping_get_factor(ac->scene, ale->id, ale->key_data, mapping_flag, &offset);
- ked.f1 = cursor_value / unit_scale;
+ ked.f1 = (cursor_value / unit_scale) - offset;
}
/* perform snapping */
@@ -2108,9 +2144,10 @@ static void mirror_graph_keys(bAnimContext *ac, short mode)
/* apply unit corrections */
if (mode == GRAPHKEYS_MIRROR_VALUE) {
short mapping_flag = ANIM_get_normalization_flags(ac);
- float unit_scale = ANIM_unit_mapping_get_factor(ac->scene, ale->id, ale->key_data, mapping_flag | ANIM_UNITCONV_ONLYKEYS);
+ float offset;
+ float unit_scale = ANIM_unit_mapping_get_factor(ac->scene, ale->id, ale->key_data, mapping_flag | ANIM_UNITCONV_ONLYKEYS, &offset);
- ked.f1 = cursor_value * unit_scale;
+ ked.f1 = (cursor_value + offset) * unit_scale;
}
/* perform actual mirroring */
@@ -2240,7 +2277,7 @@ static EnumPropertyItem *graph_fmodifier_itemf(bContext *C, PointerRNA *UNUSED(p
/* start from 1 to skip the 'Invalid' modifier type */
for (i = 1; i < FMODIFIER_NUM_TYPES; i++) {
- FModifierTypeInfo *fmi = get_fmodifier_typeinfo(i);
+ const FModifierTypeInfo *fmi = get_fmodifier_typeinfo(i);
int index;
/* check if modifier is valid for this context */
diff --git a/source/blender/editors/space_graph/graph_intern.h b/source/blender/editors/space_graph/graph_intern.h
index 408c78d194e..a478a86a5e2 100644
--- a/source/blender/editors/space_graph/graph_intern.h
+++ b/source/blender/editors/space_graph/graph_intern.h
@@ -32,11 +32,8 @@
#define __GRAPH_INTERN_H__
struct bContext;
-struct wmWindowManager;
struct bAnimContext;
struct bAnimListElem;
-struct FCurve;
-struct FModifier;
struct SpaceIpo;
struct ScrArea;
struct ARegion;
@@ -62,6 +59,7 @@ void graph_draw_ghost_curves(struct bAnimContext *ac, struct SpaceIpo *sipo, str
void GRAPH_OT_select_all_toggle(struct wmOperatorType *ot);
void GRAPH_OT_select_border(struct wmOperatorType *ot);
void GRAPH_OT_select_lasso(struct wmOperatorType *ot);
+void GRAPH_OT_select_circle(struct wmOperatorType *ot);
void GRAPH_OT_select_column(struct wmOperatorType *ot);
void GRAPH_OT_select_linked(struct wmOperatorType *ot);
void GRAPH_OT_select_more(struct wmOperatorType *ot);
@@ -93,6 +91,7 @@ void get_graph_keyframe_extents(struct bAnimContext *ac, float *xmin, float *xma
void GRAPH_OT_previewrange_set(struct wmOperatorType *ot);
void GRAPH_OT_view_all(struct wmOperatorType *ot);
void GRAPH_OT_view_selected(struct wmOperatorType *ot);
+void GRAPH_OT_view_frame(struct wmOperatorType *ot);
void GRAPH_OT_click_insert(struct wmOperatorType *ot);
void GRAPH_OT_keyframe_insert(struct wmOperatorType *ot);
diff --git a/source/blender/editors/space_graph/graph_ops.c b/source/blender/editors/space_graph/graph_ops.c
index 62b6b59df29..8e5c85d2c38 100644
--- a/source/blender/editors/space_graph/graph_ops.c
+++ b/source/blender/editors/space_graph/graph_ops.c
@@ -34,6 +34,7 @@
#include "DNA_scene_types.h"
+#include "BLI_blenlib.h"
#include "BLI_utildefines.h"
#include "BLI_math_base.h"
@@ -86,8 +87,9 @@ static void graphview_cursor_apply(bContext *C, wmOperator *op)
* NOTE: sync this part of the code with ANIM_OT_change_frame
*/
CFRA = RNA_int_get(op->ptr, "frame");
+ FRAMENUMBER_MIN_CLAMP(CFRA);
SUBFRA = 0.f;
- sound_seek_scene(bmain, scene);
+ BKE_sound_seek_scene(bmain, scene);
/* set the cursor value */
sipo->cursorVal = RNA_float_get(op->ptr, "value");
@@ -137,6 +139,7 @@ static void graphview_cursor_setprops(bContext *C, wmOperator *op, const wmEvent
/* Modal Operator init */
static int graphview_cursor_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
+ bScreen *screen = CTX_wm_screen(C);
/* Change to frame that mouse is over before adding modal handler,
* as user could click on a single frame (jump to frame) as well as
* click-dragging over a range (modal scrubbing).
@@ -146,6 +149,9 @@ static int graphview_cursor_invoke(bContext *C, wmOperator *op, const wmEvent *e
/* apply these changes first */
graphview_cursor_apply(C, op);
+ if (screen)
+ screen->scrubbing = true;
+
/* add temp handler */
WM_event_add_modal_handler(C, op);
return OPERATOR_RUNNING_MODAL;
@@ -154,9 +160,12 @@ static int graphview_cursor_invoke(bContext *C, wmOperator *op, const wmEvent *e
/* Modal event handling of cursor changing */
static int graphview_cursor_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
+ bScreen *screen = CTX_wm_screen(C);
/* execute the events */
switch (event->type) {
case ESCKEY:
+ if (screen)
+ screen->scrubbing = false;
return OPERATOR_FINISHED;
case MOUSEMOVE:
@@ -171,8 +180,11 @@ static int graphview_cursor_modal(bContext *C, wmOperator *op, const wmEvent *ev
/* we check for either mouse-button to end, as checking for ACTIONMOUSE (which is used to init
* the modal op) doesn't work for some reason
*/
- if (event->val == KM_RELEASE)
+ if (event->val == KM_RELEASE) {
+ if (screen)
+ screen->scrubbing = false;
return OPERATOR_FINISHED;
+ }
break;
}
@@ -200,6 +212,174 @@ static void GRAPH_OT_cursor_set(wmOperatorType *ot)
RNA_def_float(ot->srna, "value", 0, -FLT_MAX, FLT_MAX, "Value", "", -100.0f, 100.0f);
}
+/* Hide/Reveal ------------------------------------------------------------ */
+
+static int graphview_curves_hide_exec(bContext *C, wmOperator *op)
+{
+ bAnimContext ac;
+ ListBase anim_data = {NULL, NULL};
+ ListBase all_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+ const bool unselected = RNA_boolean_get(op->ptr, "unselected");
+
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
+
+ /* get list of all channels that selection may need to be flushed to
+ * - hierarchy must not affect what we have access to here...
+ */
+ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_CHANNELS | ANIMFILTER_NODUPLIS);
+ ANIM_animdata_filter(&ac, &all_data, filter, ac.data, ac.datatype);
+
+ /* filter data
+ * - of the remaining visible curves, we want to hide the ones that are
+ * selected/unselected (depending on "unselected" prop)
+ */
+ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_NODUPLIS);
+ if (unselected)
+ filter |= ANIMFILTER_UNSEL;
+ else
+ filter |= ANIMFILTER_SEL;
+
+ ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
+
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ /* hack: skip object channels for now, since flushing those will always flush everything, but they are always included */
+ /* TODO: find out why this is the case, and fix that */
+ if (ale->type == ANIMTYPE_OBJECT)
+ continue;
+
+ /* change the hide setting, and unselect it... */
+ ANIM_channel_setting_set(&ac, ale, ACHANNEL_SETTING_VISIBLE, ACHANNEL_SETFLAG_CLEAR);
+ ANIM_channel_setting_set(&ac, ale, ACHANNEL_SETTING_SELECT, ACHANNEL_SETFLAG_CLEAR);
+
+ /* now, also flush selection status up/down as appropriate */
+ ANIM_flush_setting_anim_channels(&ac, &all_data, ale, ACHANNEL_SETTING_VISIBLE, ACHANNEL_SETFLAG_CLEAR);
+ }
+
+ /* cleanup */
+ ANIM_animdata_freelist(&anim_data);
+ BLI_freelistN(&all_data);
+
+ /* unhide selected */
+ if (unselected) {
+ /* turn off requirement for visible */
+ filter = ANIMFILTER_SEL | ANIMFILTER_NODUPLIS | ANIMFILTER_LIST_CHANNELS;
+
+ /* flushing has been done */
+ ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
+
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ /* hack: skip object channels for now, since flushing those will always flush everything, but they are always included */
+ /* TODO: find out why this is the case, and fix that */
+ if (ale->type == ANIMTYPE_OBJECT)
+ continue;
+
+ /* change the hide setting, and unselect it... */
+ ANIM_channel_setting_set(&ac, ale, ACHANNEL_SETTING_VISIBLE, ACHANNEL_SETFLAG_ADD);
+ ANIM_channel_setting_set(&ac, ale, ACHANNEL_SETTING_SELECT, ACHANNEL_SETFLAG_ADD);
+
+ /* now, also flush selection status up/down as appropriate */
+ ANIM_flush_setting_anim_channels(&ac, &anim_data, ale, ACHANNEL_SETTING_VISIBLE, ACHANNEL_SETFLAG_ADD);
+ }
+ ANIM_animdata_freelist(&anim_data);
+ }
+
+
+ /* send notifier that things have changed */
+ WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL);
+
+ return OPERATOR_FINISHED;
+}
+
+static void GRAPH_OT_hide(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Hide Curves";
+ ot->idname = "GRAPH_OT_hide";
+ ot->description = "Hide selected curves from Graph Editor view";
+
+ /* api callbacks */
+ ot->exec = graphview_curves_hide_exec;
+ ot->poll = ED_operator_graphedit_active;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* props */
+ RNA_def_boolean(ot->srna, "unselected", 0, "Unselected", "Hide unselected rather than selected curves");
+}
+
+/* ........ */
+
+static int graphview_curves_reveal_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ bAnimContext ac;
+ ListBase anim_data = {NULL, NULL};
+ ListBase all_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
+
+ /* get list of all channels that selection may need to be flushed to
+ * - hierarchy must not affect what we have access to here...
+ */
+ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_CHANNELS | ANIMFILTER_NODUPLIS);
+ ANIM_animdata_filter(&ac, &all_data, filter, ac.data, ac.datatype);
+
+ /* filter data
+ * - just go through all visible channels, ensuring that everything is set to be curve-visible
+ */
+ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_NODUPLIS);
+ ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
+
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ /* hack: skip object channels for now, since flushing those will always flush everything, but they are always included */
+ /* TODO: find out why this is the case, and fix that */
+ if (ale->type == ANIMTYPE_OBJECT)
+ continue;
+
+ /* select if it is not visible */
+ if (ANIM_channel_setting_get(&ac, ale, ACHANNEL_SETTING_VISIBLE) == 0)
+ ANIM_channel_setting_set(&ac, ale, ACHANNEL_SETTING_SELECT, ACHANNEL_SETFLAG_ADD);
+
+ /* change the visibility setting */
+ ANIM_channel_setting_set(&ac, ale, ACHANNEL_SETTING_VISIBLE, ACHANNEL_SETFLAG_ADD);
+
+ /* now, also flush selection status up/down as appropriate */
+ ANIM_flush_setting_anim_channels(&ac, &all_data, ale, ACHANNEL_SETTING_VISIBLE, true);
+ }
+
+ /* cleanup */
+ ANIM_animdata_freelist(&anim_data);
+ BLI_freelistN(&all_data);
+
+ /* send notifier that things have changed */
+ WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL);
+
+ return OPERATOR_FINISHED;
+}
+
+static void GRAPH_OT_reveal(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Reveal Curves";
+ ot->idname = "GRAPH_OT_reveal";
+ ot->description = "Make previously hidden curves visible again in Graph Editor view";
+
+ /* api callbacks */
+ ot->exec = graphview_curves_reveal_exec;
+ ot->poll = ED_operator_graphedit_active;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
/* ************************** registration - operator types **********************************/
void graphedit_operatortypes(void)
@@ -211,16 +391,21 @@ void graphedit_operatortypes(void)
WM_operatortype_append(GRAPH_OT_view_all);
WM_operatortype_append(GRAPH_OT_view_selected);
WM_operatortype_append(GRAPH_OT_properties);
+ WM_operatortype_append(GRAPH_OT_view_frame);
WM_operatortype_append(GRAPH_OT_ghost_curves_create);
WM_operatortype_append(GRAPH_OT_ghost_curves_clear);
+ WM_operatortype_append(GRAPH_OT_hide);
+ WM_operatortype_append(GRAPH_OT_reveal);
+
/* keyframes */
/* selection */
WM_operatortype_append(GRAPH_OT_clickselect);
WM_operatortype_append(GRAPH_OT_select_all_toggle);
WM_operatortype_append(GRAPH_OT_select_border);
WM_operatortype_append(GRAPH_OT_select_lasso);
+ WM_operatortype_append(GRAPH_OT_select_circle);
WM_operatortype_append(GRAPH_OT_select_column);
WM_operatortype_append(GRAPH_OT_select_linked);
WM_operatortype_append(GRAPH_OT_select_more);
@@ -267,6 +452,7 @@ void ED_operatormacros_graph(void)
WM_operatortype_macro_define(ot, "GRAPH_OT_duplicate");
otmacro = WM_operatortype_macro_define(ot, "TRANSFORM_OT_transform");
RNA_enum_set(otmacro->ptr, "mode", TFM_TIME_DUPLICATE);
+ RNA_enum_set(otmacro->ptr, "proportional", PROP_EDIT_OFF);
}
@@ -359,6 +545,8 @@ static void graphedit_keymap_keyframes(wmKeyConfig *keyconf, wmKeyMap *keymap)
kmi = WM_keymap_add_item(keymap, "GRAPH_OT_select_lasso", EVT_TWEAK_A, KM_ANY, KM_CTRL | KM_SHIFT, 0);
RNA_boolean_set(kmi->ptr, "deselect", true);
+ WM_keymap_add_item(keymap, "GRAPH_OT_select_circle", CKEY, KM_PRESS, 0, 0);
+
/* column select */
RNA_enum_set(WM_keymap_add_item(keymap, "GRAPH_OT_select_column", KKEY, KM_PRESS, 0, 0)->ptr, "mode", GRAPHKEYS_COLUMNSEL_KEYS);
RNA_enum_set(WM_keymap_add_item(keymap, "GRAPH_OT_select_column", KKEY, KM_PRESS, KM_CTRL, 0)->ptr, "mode", GRAPHKEYS_COLUMNSEL_CFRA);
@@ -387,15 +575,14 @@ static void graphedit_keymap_keyframes(wmKeyConfig *keyconf, wmKeyMap *keymap)
WM_keymap_add_item(keymap, "GRAPH_OT_easing_type", EKEY, KM_PRESS, KM_CTRL, 0);
/* destructive */
- WM_keymap_add_item(keymap, "GRAPH_OT_clean", OKEY, KM_PRESS, 0, 0);
WM_keymap_add_item(keymap, "GRAPH_OT_smooth", OKEY, KM_PRESS, KM_ALT, 0);
WM_keymap_add_item(keymap, "GRAPH_OT_sample", OKEY, KM_PRESS, KM_SHIFT, 0);
WM_keymap_add_item(keymap, "GRAPH_OT_bake", CKEY, KM_PRESS, KM_ALT, 0);
- WM_keymap_add_item(keymap, "GRAPH_OT_delete", XKEY, KM_PRESS, 0, 0);
- WM_keymap_add_item(keymap, "GRAPH_OT_delete", DELKEY, KM_PRESS, 0, 0);
-
+ WM_keymap_add_menu(keymap, "GRAPH_MT_delete", XKEY, KM_PRESS, 0, 0);
+ WM_keymap_add_menu(keymap, "GRAPH_MT_delete", DELKEY, KM_PRESS, 0, 0);
+
WM_keymap_add_item(keymap, "GRAPH_OT_duplicate_move", DKEY, KM_PRESS, KM_SHIFT, 0);
/* insertkey */
@@ -405,9 +592,13 @@ static void graphedit_keymap_keyframes(wmKeyConfig *keyconf, wmKeyMap *keymap)
/* copy/paste */
WM_keymap_add_item(keymap, "GRAPH_OT_copy", CKEY, KM_PRESS, KM_CTRL, 0);
WM_keymap_add_item(keymap, "GRAPH_OT_paste", VKEY, KM_PRESS, KM_CTRL, 0);
+ kmi = WM_keymap_add_item(keymap, "GRAPH_OT_paste", VKEY, KM_PRESS, KM_CTRL | KM_SHIFT, 0);
+ RNA_boolean_set(kmi->ptr, "flipped", true);
#ifdef __APPLE__
WM_keymap_add_item(keymap, "GRAPH_OT_copy", CKEY, KM_PRESS, KM_OSKEY, 0);
WM_keymap_add_item(keymap, "GRAPH_OT_paste", VKEY, KM_PRESS, KM_OSKEY, 0);
+ kmi = WM_keymap_add_item(keymap, "GRAPH_OT_paste", VKEY, KM_PRESS, KM_OSKEY | KM_SHIFT, 0);
+ RNA_boolean_set(kmi->ptr, "flipped", true);
#endif
/* auto-set range */
@@ -415,7 +606,8 @@ static void graphedit_keymap_keyframes(wmKeyConfig *keyconf, wmKeyMap *keymap)
WM_keymap_add_item(keymap, "GRAPH_OT_view_all", HOMEKEY, KM_PRESS, 0, 0);
WM_keymap_add_item(keymap, "GRAPH_OT_view_all", NDOF_BUTTON_FIT, KM_PRESS, 0, 0);
WM_keymap_add_item(keymap, "GRAPH_OT_view_selected", PADPERIOD, KM_PRESS, 0, 0);
-
+ WM_keymap_add_item(keymap, "GRAPH_OT_view_frame", PAD0, KM_PRESS, 0, 0);
+
/* F-Modifiers */
kmi = WM_keymap_add_item(keymap, "GRAPH_OT_fmodifier_add", MKEY, KM_PRESS, KM_CTRL | KM_SHIFT, 0);
RNA_boolean_set(kmi->ptr, "only_active", false);
@@ -429,6 +621,22 @@ static void graphedit_keymap_keyframes(wmKeyConfig *keyconf, wmKeyMap *keymap)
/* transform system */
transform_keymap_for_space(keyconf, keymap, SPACE_IPO);
+ kmi = WM_keymap_add_item(keymap, "WM_OT_context_toggle", OKEY, KM_PRESS, 0, 0);
+ RNA_string_set(kmi->ptr, "data_path", "tool_settings.use_proportional_fcurve");
+
+ /* pivot point settings */
+ kmi = WM_keymap_add_item(keymap, "WM_OT_context_set_enum", COMMAKEY, KM_PRESS, 0, 0);
+ RNA_string_set(kmi->ptr, "data_path", "space_data.pivot_point");
+ RNA_string_set(kmi->ptr, "value", "BOUNDING_BOX_CENTER");
+
+ kmi = WM_keymap_add_item(keymap, "WM_OT_context_set_enum", PERIODKEY, KM_PRESS, 0, 0);
+ RNA_string_set(kmi->ptr, "data_path", "space_data.pivot_point");
+ RNA_string_set(kmi->ptr, "value", "CURSOR");
+
+ kmi = WM_keymap_add_item(keymap, "WM_OT_context_set_enum", PERIODKEY, KM_PRESS, KM_CTRL, 0);
+ RNA_string_set(kmi->ptr, "data_path", "space_data.pivot_point");
+ RNA_string_set(kmi->ptr, "value", "INDIVIDUAL_ORIGINS");
+
/* special markers hotkeys for anim editors: see note in definition of this function */
ED_marker_keymap_animedit_conflictfree(keymap);
}
@@ -438,6 +646,7 @@ static void graphedit_keymap_keyframes(wmKeyConfig *keyconf, wmKeyMap *keymap)
void graphedit_keymap(wmKeyConfig *keyconf)
{
wmKeyMap *keymap;
+ wmKeyMapItem *kmi;
/* keymap for all regions */
keymap = WM_keymap_find(keyconf, "Graph Editor Generic", SPACE_IPO, 0);
@@ -448,7 +657,17 @@ void graphedit_keymap(wmKeyConfig *keyconf)
/* find (i.e. a shortcut for setting the name filter) */
WM_keymap_add_item(keymap, "ANIM_OT_channels_find", FKEY, KM_PRESS, KM_CTRL, 0);
-
+
+ /* hide/reveal selected curves */
+ kmi = WM_keymap_add_item(keymap, "GRAPH_OT_hide", HKEY, KM_PRESS, 0, 0);
+ RNA_boolean_set(kmi->ptr, "unselected", false);
+
+ kmi = WM_keymap_add_item(keymap, "GRAPH_OT_hide", HKEY, KM_PRESS, KM_SHIFT, 0);
+ RNA_boolean_set(kmi->ptr, "unselected", true);
+
+ WM_keymap_add_item(keymap, "GRAPH_OT_reveal", HKEY, KM_PRESS, KM_ALT, 0);
+
+
/* channels */
/* Channels are not directly handled by the Graph Editor module, but are inherited from the Animation module.
* All the relevant operations, keymaps, drawing, etc. can therefore all be found in that module instead, as these
diff --git a/source/blender/editors/space_graph/graph_select.c b/source/blender/editors/space_graph/graph_select.c
index 378139accbc..67274100312 100644
--- a/source/blender/editors/space_graph/graph_select.c
+++ b/source/blender/editors/space_graph/graph_select.c
@@ -198,7 +198,7 @@ void GRAPH_OT_select_all_toggle(wmOperatorType *ot)
ot->poll = graphop_visible_keyframes_poll;
/* flags */
- ot->flag = OPTYPE_REGISTER /*|OPTYPE_UNDO*/;
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
/* props */
ot->prop = RNA_def_boolean(ot->srna, "invert", 0, "Invert", "");
@@ -219,7 +219,7 @@ void GRAPH_OT_select_all_toggle(wmOperatorType *ot)
*/
static void borderselect_graphkeys(
bAnimContext *ac, const rctf *rectf_view, short mode, short selectmode, bool incl_handles,
- struct KeyframeEdit_LassoData *data_lasso)
+ void *data)
{
ListBase anim_data = {NULL, NULL};
bAnimListElem *ale;
@@ -244,10 +244,16 @@ static void borderselect_graphkeys(
/* init editing data */
memset(&ked, 0, sizeof(KeyframeEditData));
- if (data_lasso) {
+ if (mode == BEZT_OK_REGION_LASSO) {
+ struct KeyframeEdit_LassoData *data_lasso = data;
data_lasso->rectf_scaled = &scaled_rectf;
ked.data = data_lasso;
}
+ else if (mode == BEZT_OK_REGION_CIRCLE) {
+ struct KeyframeEdit_CircleData *data_circle = data;
+ data_circle->rectf_scaled = &scaled_rectf;
+ ked.data = data;
+ }
else {
ked.data = &scaled_rectf;
}
@@ -266,7 +272,8 @@ static void borderselect_graphkeys(
for (ale = anim_data.first; ale; ale = ale->next) {
AnimData *adt = ANIM_nla_mapping_get(ac, ale);
FCurve *fcu = (FCurve *)ale->key_data;
- float unit_scale = ANIM_unit_mapping_get_factor(ac->scene, ale->id, fcu, mapping_flag);
+ float offset;
+ float unit_scale = ANIM_unit_mapping_get_factor(ac->scene, ale->id, fcu, mapping_flag, &offset);
/* apply NLA mapping to all the keyframes, since it's easier than trying to
* guess when a callback might use something different
@@ -276,8 +283,8 @@ static void borderselect_graphkeys(
scaled_rectf.xmin = rectf.xmin;
scaled_rectf.xmax = rectf.xmax;
- scaled_rectf.ymin = rectf.ymin / unit_scale;
- scaled_rectf.ymax = rectf.ymax / unit_scale;
+ scaled_rectf.ymin = rectf.ymin / unit_scale - offset;
+ scaled_rectf.ymax = rectf.ymax / unit_scale - offset;
/* set horizontal range (if applicable)
* NOTE: these values are only used for x-range and y-range but not region
@@ -390,7 +397,7 @@ void GRAPH_OT_select_border(wmOperatorType *ot)
ot->poll = graphop_visible_keyframes_poll;
/* flags */
- ot->flag = OPTYPE_REGISTER /*|OPTYPE_UNDO*/;
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
/* rna */
WM_operator_properties_gesture_border(ot, true);
@@ -485,6 +492,81 @@ void GRAPH_OT_select_lasso(wmOperatorType *ot)
RNA_def_boolean(ot->srna, "extend", true, "Extend", "Extend selection instead of deselecting everything first");
}
+static int graph_circle_select_exec(bContext *C, wmOperator *op)
+{
+ bAnimContext ac;
+ const int gesture_mode = RNA_int_get(op->ptr, "gesture_mode");
+ short selectmode;
+ bool incl_handles;
+ rctf rect_fl;
+ struct KeyframeEdit_CircleData data;
+ float x = RNA_int_get(op->ptr, "x");
+ float y = RNA_int_get(op->ptr, "y");
+ float radius = RNA_int_get(op->ptr, "radius");
+
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
+
+ data.mval[0] = x;
+ data.mval[1] = y;
+ data.radius_squared = radius * radius;
+ data.rectf_view = &rect_fl;
+
+ if (gesture_mode == GESTURE_MODAL_SELECT)
+ selectmode = SELECT_ADD;
+ else
+ selectmode = SELECT_SUBTRACT;
+
+ rect_fl.xmin = x - radius;
+ rect_fl.xmax = x + radius;
+ rect_fl.ymin = y - radius;
+ rect_fl.ymax = y + radius;
+
+ if (ac.spacetype == SPACE_IPO) {
+ SpaceIpo *sipo = (SpaceIpo *)ac.sl;
+ if (selectmode == SELECT_ADD) {
+ incl_handles = ((sipo->flag & SIPO_SELVHANDLESONLY) ||
+ (sipo->flag & SIPO_NOHANDLES)) == 0;
+ }
+ else {
+ incl_handles = (sipo->flag & SIPO_NOHANDLES) == 0;
+ }
+ }
+ else {
+ incl_handles = false;
+ }
+
+ /* apply borderselect action */
+ borderselect_graphkeys(&ac, &rect_fl, BEZT_OK_REGION_CIRCLE, selectmode, incl_handles, &data);
+
+ /* send notifier that keyframe selection has changed */
+ WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_SELECTED, NULL);
+
+ return OPERATOR_FINISHED;
+}
+
+void GRAPH_OT_select_circle(wmOperatorType *ot)
+{
+ ot->name = "Circle Select";
+ ot->description = "Select keyframe points using circle selection";
+ ot->idname = "GRAPH_OT_select_circle";
+
+ ot->invoke = WM_gesture_circle_invoke;
+ ot->modal = WM_gesture_circle_modal;
+ ot->exec = graph_circle_select_exec;
+ ot->poll = graphop_visible_keyframes_poll;
+ ot->cancel = WM_gesture_circle_cancel;
+
+ /* flags */
+ ot->flag = OPTYPE_UNDO;
+
+ RNA_def_int(ot->srna, "x", 0, INT_MIN, INT_MAX, "X", "", INT_MIN, INT_MAX);
+ RNA_def_int(ot->srna, "y", 0, INT_MIN, INT_MAX, "Y", "", INT_MIN, INT_MAX);
+ RNA_def_int(ot->srna, "radius", 1, 1, INT_MAX, "Radius", "", 1, INT_MAX);
+ RNA_def_int(ot->srna, "gesture_mode", 0, INT_MIN, INT_MAX, "Event Type", "", INT_MIN, INT_MAX);
+}
+
/* ******************** Column Select Operator **************************** */
/* This operator works in one of four ways:
* - 1) select all keyframes in the same frame as a selected one (KKEY)
@@ -662,7 +744,7 @@ void GRAPH_OT_select_column(wmOperatorType *ot)
ot->poll = graphop_visible_keyframes_poll;
/* flags */
- ot->flag = OPTYPE_REGISTER /*|OPTYPE_UNDO*/;
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
/* props */
ot->prop = RNA_def_enum(ot->srna, "mode", prop_column_select_types, 0, "Mode", "");
@@ -720,7 +802,7 @@ void GRAPH_OT_select_linked(wmOperatorType *ot)
ot->poll = graphop_visible_keyframes_poll;
/* flags */
- ot->flag = OPTYPE_REGISTER /*|OPTYPE_UNDO*/;
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/* ******************** Select More/Less Operators *********************** */
@@ -798,7 +880,7 @@ void GRAPH_OT_select_more(wmOperatorType *ot)
ot->poll = graphop_visible_keyframes_poll;
/* flags */
- ot->flag = OPTYPE_REGISTER /*|OPTYPE_UNDO*/;
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/* ----------------- */
@@ -832,7 +914,7 @@ void GRAPH_OT_select_less(wmOperatorType *ot)
ot->poll = graphop_visible_keyframes_poll;
/* flags */
- ot->flag = OPTYPE_REGISTER /*|OPTYPE_UNDO*/;
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/* ******************** Select Left/Right Operator ************************* */
@@ -1008,6 +1090,8 @@ typedef struct tNearestVertInfo {
short hpoint; /* the handle index that we hit (eHandleIndex) */
short sel; /* whether the handle is selected or not */
int dist; /* distance from mouse to vert */
+
+ eAnim_ChannelType ctype; /* type of animation channel this FCurve comes from */
} tNearestVertInfo;
/* Tags for the type of graph vert that we have */
@@ -1028,15 +1112,15 @@ typedef enum eGraphVertIndex {
static bool fcurve_handle_sel_check(SpaceIpo *sipo, BezTriple *bezt)
{
if (sipo->flag & SIPO_NOHANDLES) return 0;
- if ((sipo->flag & SIPO_SELVHANDLESONLY) && BEZSELECTED(bezt) == 0) return 0;
+ if ((sipo->flag & SIPO_SELVHANDLESONLY) && BEZT_ISSEL_ANY(bezt) == 0) return 0;
return 1;
}
/* check if the given vertex is within bounds or not */
// TODO: should we return if we hit something?
static void nearest_fcurve_vert_store(
- ListBase *matches, View2D *v2d, FCurve *fcu,
- BezTriple *bezt, FPoint *fpt, short hpoint, const int mval[2], float unit_scale)
+ ListBase *matches, View2D *v2d, FCurve *fcu, eAnim_ChannelType ctype,
+ BezTriple *bezt, FPoint *fpt, short hpoint, const int mval[2], float unit_scale, float offset)
{
/* Keyframes or Samples? */
if (bezt) {
@@ -1048,7 +1132,7 @@ static void nearest_fcurve_vert_store(
* 'vec' matrix
*/
if (UI_view2d_view_to_region_clip(v2d,
- bezt->vec[hpoint + 1][0], bezt->vec[hpoint + 1][1] * unit_scale,
+ bezt->vec[hpoint + 1][0], (bezt->vec[hpoint + 1][1] + offset) * unit_scale,
&screen_co[0], &screen_co[1]) &&
/* check if distance from mouse cursor to vert in screen space is within tolerance */
((dist = len_v2v2_int(mval, screen_co)) <= GVERTSEL_TOL))
@@ -1059,7 +1143,7 @@ static void nearest_fcurve_vert_store(
/* if there is already a point for the F-Curve, check if this point is closer than that was */
if ((nvi) && (nvi->fcu == fcu)) {
/* replace if we are closer, or if equal and that one wasn't selected but we are... */
- if ((nvi->dist > dist) || ((nvi->sel == 0) && BEZSELECTED(bezt)))
+ if ((nvi->dist > dist) || ((nvi->sel == 0) && BEZT_ISSEL_ANY(bezt)))
replace = 1;
}
/* add new if not replacing... */
@@ -1068,11 +1152,13 @@ static void nearest_fcurve_vert_store(
/* store values */
nvi->fcu = fcu;
+ nvi->ctype = ctype;
+
nvi->bezt = bezt;
nvi->hpoint = hpoint;
nvi->dist = dist;
- nvi->sel = BEZSELECTED(bezt); // XXX... should this use the individual verts instead?
+ nvi->sel = BEZT_ISSEL_ANY(bezt); // XXX... should this use the individual verts instead?
/* add to list of matches if appropriate... */
if (replace == 0)
@@ -1108,30 +1194,31 @@ static void get_nearest_fcurve_verts_list(bAnimContext *ac, const int mval[2], L
for (ale = anim_data.first; ale; ale = ale->next) {
FCurve *fcu = (FCurve *)ale->key_data;
AnimData *adt = ANIM_nla_mapping_get(ac, ale);
- float unit_scale = ANIM_unit_mapping_get_factor(ac->scene, ale->id, fcu, mapping_flag);
-
+ float offset;
+ float unit_scale = ANIM_unit_mapping_get_factor(ac->scene, ale->id, fcu, mapping_flag, &offset);
+
/* apply NLA mapping to all the keyframes */
if (adt)
ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 0, 0);
-
+
if (fcu->bezt) {
BezTriple *bezt1 = fcu->bezt, *prevbezt = NULL;
int i;
for (i = 0; i < fcu->totvert; i++, prevbezt = bezt1, bezt1++) {
/* keyframe */
- nearest_fcurve_vert_store(matches, v2d, fcu, bezt1, NULL, NEAREST_HANDLE_KEY, mval, unit_scale);
+ nearest_fcurve_vert_store(matches, v2d, fcu, ale->type, bezt1, NULL, NEAREST_HANDLE_KEY, mval, unit_scale, offset);
/* handles - only do them if they're visible */
if (fcurve_handle_sel_check(sipo, bezt1) && (fcu->totvert > 1)) {
/* first handle only visible if previous segment had handles */
if ((!prevbezt && (bezt1->ipo == BEZT_IPO_BEZ)) || (prevbezt && (prevbezt->ipo == BEZT_IPO_BEZ))) {
- nearest_fcurve_vert_store(matches, v2d, fcu, bezt1, NULL, NEAREST_HANDLE_LEFT, mval, unit_scale);
+ nearest_fcurve_vert_store(matches, v2d, fcu, ale->type, bezt1, NULL, NEAREST_HANDLE_LEFT, mval, unit_scale, offset);
}
/* second handle only visible if this segment is bezier */
if (bezt1->ipo == BEZT_IPO_BEZ) {
- nearest_fcurve_vert_store(matches, v2d, fcu, bezt1, NULL, NEAREST_HANDLE_RIGHT, mval, unit_scale);
+ nearest_fcurve_vert_store(matches, v2d, fcu, ale->type, bezt1, NULL, NEAREST_HANDLE_RIGHT, mval, unit_scale, offset);
}
}
}
@@ -1251,11 +1338,11 @@ static void mouse_graph_keys(bAnimContext *ac, const int mval[2], short select_m
if (select_mode == SELECT_INVERT) {
/* keyframe - invert select of all */
if (nvi->hpoint == NEAREST_HANDLE_KEY) {
- if (BEZSELECTED(bezt)) {
- BEZ_DESEL(bezt);
+ if (BEZT_ISSEL_ANY(bezt)) {
+ BEZT_DESEL_ALL(bezt);
}
else {
- BEZ_SEL(bezt);
+ BEZT_SEL_ALL(bezt);
}
}
@@ -1272,7 +1359,7 @@ static void mouse_graph_keys(bAnimContext *ac, const int mval[2], short select_m
else {
/* if the keyframe was clicked on, select all verts of given beztriple */
if (nvi->hpoint == NEAREST_HANDLE_KEY) {
- BEZ_SEL(bezt);
+ BEZT_SEL_ALL(bezt);
}
/* otherwise, select the handle that applied */
else if (nvi->hpoint == NEAREST_HANDLE_LEFT)
@@ -1306,7 +1393,7 @@ static void mouse_graph_keys(bAnimContext *ac, const int mval[2], short select_m
/* take selection status from item that got hit, to prevent flip/flop on channel
* selection status when shift-selecting (i.e. "SELECT_INVERT") points
*/
- if (BEZSELECTED(bezt))
+ if (BEZT_ISSEL_ANY(bezt))
nvi->fcu->flag |= FCURVE_SELECTED;
else
nvi->fcu->flag &= ~FCURVE_SELECTED;
@@ -1324,7 +1411,7 @@ static void mouse_graph_keys(bAnimContext *ac, const int mval[2], short select_m
/* needs to be called with (sipo->flag & SIPO_SELCUVERTSONLY) otherwise the active flag won't be set [#26452] */
if (nvi->fcu->flag & FCURVE_SELECTED) {
int filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_NODUPLIS);
- ANIM_set_active_channel(ac, ac->data, ac->datatype, filter, nvi->fcu, ANIMTYPE_FCURVE);
+ ANIM_set_active_channel(ac, ac->data, ac->datatype, filter, nvi->fcu, nvi->ctype);
}
/* free temp sample data for filtering */
diff --git a/source/blender/editors/space_graph/graph_utils.c b/source/blender/editors/space_graph/graph_utils.c
index e9c8ae95acd..0e56dc817e4 100644
--- a/source/blender/editors/space_graph/graph_utils.c
+++ b/source/blender/editors/space_graph/graph_utils.c
@@ -40,7 +40,6 @@
#include "MEM_guardedalloc.h"
-#include "BLI_math.h"
#include "BLI_blenlib.h"
#include "BKE_context.h"
@@ -211,13 +210,18 @@ int graphop_active_fcurve_poll(bContext *C)
if (ale == NULL)
return 0;
- /* free temp data... */
- has_fcurve = ((ale->data) && (ale->type == ANIMTYPE_FCURVE));
+ /* do we have a suitable F-Curves?
+ * - For most cases, NLA Control Curves are sufficiently similar to NLA curves to serve this role too.
+ * Under the hood, they are F-Curves too. The only problems which will arise here are if these need to be
+ * in an Action too (but drivers would then also be affected!)
+ */
+ has_fcurve = ((ale->data) && ELEM(ale->type, ANIMTYPE_FCURVE, ANIMTYPE_NLACURVE));
if (has_fcurve) {
FCurve *fcu = (FCurve *)ale->data;
has_fcurve = (fcu->flag & FCURVE_VISIBLE) != 0;
}
+ /* free temp data... */
MEM_freeN(ale);
/* return success */
diff --git a/source/blender/editors/space_graph/space_graph.c b/source/blender/editors/space_graph/space_graph.c
index 6dba706b241..4c7ac532411 100644
--- a/source/blender/editors/space_graph/space_graph.c
+++ b/source/blender/editors/space_graph/space_graph.c
@@ -182,7 +182,7 @@ static void graph_init(struct wmWindowManager *UNUSED(wm), ScrArea *sa)
{
SpaceIpo *sipo = (SpaceIpo *)sa->spacedata.first;
- /* init dopesheet data if non-existant (i.e. for old files) */
+ /* init dopesheet data if non-existent (i.e. for old files) */
if (sipo->ads == NULL) {
sipo->ads = MEM_callocN(sizeof(bDopeSheet), "GraphEdit DopeSheet");
sipo->ads->source = (ID *)(G.main->scene.first); // FIXME: this is a really nasty hack here for now...
@@ -293,7 +293,7 @@ static void graph_main_area_draw(const bContext *C, ARegion *ar)
/* markers */
UI_view2d_view_orthoSpecial(ar, v2d, 1);
- draw_markers_time(C, 0);
+ ED_markers_draw(C, DRAW_MARKERS_MARGIN);
/* preview range */
UI_view2d_view_ortho(v2d);
@@ -384,7 +384,7 @@ static void graph_buttons_area_init(wmWindowManager *wm, ARegion *ar)
static void graph_buttons_area_draw(const bContext *C, ARegion *ar)
{
- ED_region_panels(C, ar, 1, NULL, -1);
+ ED_region_panels(C, ar, NULL, -1, true);
}
static void graph_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn)
diff --git a/source/blender/editors/space_image/CMakeLists.txt b/source/blender/editors/space_image/CMakeLists.txt
index 62ac3c2d985..c60d194b620 100644
--- a/source/blender/editors/space_image/CMakeLists.txt
+++ b/source/blender/editors/space_image/CMakeLists.txt
@@ -23,14 +23,16 @@ set(INC
../../blenfont
../../blenkernel
../../blenlib
- ../../imbuf
+ ../../blentranslation
../../bmesh
+ ../../imbuf
+ ../../gpu
../../makesdna
../../makesrna
../../render/extern/include
../../windowmanager
../../../../intern/guardedalloc
- ../../gpu
+ ../../../../intern/glew-mx
)
set(INC_SYS
@@ -71,4 +73,6 @@ if(WITH_IMAGE_CINEON)
add_definitions(-DWITH_CINEON)
endif()
+add_definitions(${GL_DEFINITIONS})
+
blender_add_lib(bf_editor_space_image "${SRC}" "${INC}" "${INC_SYS}")
diff --git a/source/blender/editors/space_image/SConscript b/source/blender/editors/space_image/SConscript
index d878a726b55..95d23d177e7 100644
--- a/source/blender/editors/space_image/SConscript
+++ b/source/blender/editors/space_image/SConscript
@@ -31,12 +31,15 @@ sources = env.Glob('*.c')
incs = [
'#/intern/guardedalloc',
- '#/extern/glew/include',
+ env['BF_GLEW_INC'],
+ '#/intern/glew-mx',
'../include',
'../../blenfont',
'../../blenkernel',
'../../blenlib',
+ '../../blentranslation',
'../../bmesh',
+ '../../gpu',
'../../imbuf',
'../../makesdna',
'../../makesrna',
@@ -47,6 +50,7 @@ incs = [
incs = ' '.join(incs)
defs = []
+defs += env['BF_GL_DEFINITIONS']
if env['WITH_BF_INTERNATIONAL']:
defs.append('WITH_INTERNATIONAL')
diff --git a/source/blender/editors/space_image/image_buttons.c b/source/blender/editors/space_image/image_buttons.c
index 7e90008d8d2..6b5cc38595b 100644
--- a/source/blender/editors/space_image/image_buttons.c
+++ b/source/blender/editors/space_image/image_buttons.c
@@ -38,12 +38,13 @@
#include "BLI_blenlib.h"
#include "BLI_utildefines.h"
-#include "BLF_translation.h"
+#include "BLT_translation.h"
#include "BKE_context.h"
#include "BKE_image.h"
#include "BKE_node.h"
#include "BKE_screen.h"
+#include "BKE_scene.h"
#include "RE_pipeline.h"
@@ -64,6 +65,7 @@
#include "image_intern.h"
#define B_NOP -1
+#define MAX_IMAGE_INFO_LEN 128
/* proto */
@@ -81,9 +83,9 @@ static void image_info(Scene *scene, ImageUser *iuser, Image *ima, ImBuf *ibuf,
else {
if (ima->source == IMA_SRC_MOVIE) {
ofs += BLI_strncpy_rlen(str + ofs, IFACE_("Movie"), len - ofs);
- if (ima->anim)
+ if (BKE_image_has_anim(ima))
ofs += BLI_snprintf(str + ofs, len - ofs, IFACE_(" %d frs"),
- IMB_anim_get_duration(ima->anim, IMB_TC_RECORD_RUN));
+ IMB_anim_get_duration(((ImageAnim *)ima->anims.first)->anim, IMB_TC_RECORD_RUN));
}
else {
ofs += BLI_strncpy_rlen(str, IFACE_("Image"), len - ofs);
@@ -268,7 +270,7 @@ static void image_panel_preview(ScrArea *sa, short cntrl) // IMAGE_HANDLER_PRE
return;
}
- block = uiBeginBlock(C, ar, __func__, UI_EMBOSS);
+ block = UI_block_begin(C, ar, __func__, UI_EMBOSS);
uiPanelControl(UI_PNL_SOLID | UI_PNL_CLOSE | UI_PNL_SCALE | cntrl);
uiSetPanelHandler(IMAGE_HANDLER_PREVIEW); // for close and esc
@@ -276,7 +278,7 @@ static void image_panel_preview(ScrArea *sa, short cntrl) // IMAGE_HANDLER_PRE
ofsy = -100 + (sa->winy / 2) / sima->blockscale;
if (uiNewPanel(C, ar, block, "Preview", "Image", ofsx, ofsy, 300, 200) == 0) return;
- uiBlockSetDrawExtraFunc(block, preview_cb);
+ UI_but_func_drawextra_set(block, preview_cb);
}
#endif
@@ -284,31 +286,37 @@ static void image_panel_preview(ScrArea *sa, short cntrl) // IMAGE_HANDLER_PRE
/* ********************* callbacks for standard image buttons *************** */
-static void ui_imageuser_slot_menu(bContext *UNUSED(C), uiLayout *layout, void *render_slot_p)
+static void ui_imageuser_slot_menu(bContext *UNUSED(C), uiLayout *layout, void *image_p)
{
uiBlock *block = uiLayoutGetBlock(layout);
- short *render_slot = render_slot_p;
+ Image *image = image_p;
int slot;
- uiDefBut(block, LABEL, 0, IFACE_("Slot"),
+ uiDefBut(block, UI_BTYPE_LABEL, 0, IFACE_("Slot"),
0, 0, UI_UNIT_X * 5, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
uiItemS(layout);
slot = IMA_MAX_RENDER_SLOT;
while (slot--) {
- char str[32];
- BLI_snprintf(str, sizeof(str), IFACE_("Slot %d"), slot + 1);
- uiDefButS(block, BUTM, B_NOP, str, 0, 0,
- UI_UNIT_X * 5, UI_UNIT_X, render_slot, (float) slot, 0.0, 0, -1, "");
+ char str[64];
+ if (image->render_slots[slot].name[0] != '\0') {
+ BLI_strncpy(str, image->render_slots[slot].name, sizeof(str));
+ }
+ else {
+ BLI_snprintf(str, sizeof(str), IFACE_("Slot %d"), slot + 1);
+ }
+ uiDefButS(block, UI_BTYPE_BUT_MENU, B_NOP, str, 0, 0,
+ UI_UNIT_X * 5, UI_UNIT_X, &image->render_slot, (float) slot, 0.0, 0, -1, "");
}
}
static const char *ui_imageuser_layer_fake_name(RenderResult *rr)
{
- if (rr->rectf) {
+ RenderView *rv = RE_RenderViewGetById(rr, 0);
+ if (rv->rectf) {
return IFACE_("Composite");
}
- else if (rr->rect32) {
+ else if (rv->rect32) {
return IFACE_("Sequence");
}
else {
@@ -320,21 +328,29 @@ static void ui_imageuser_layer_menu(bContext *UNUSED(C), uiLayout *layout, void
{
void **rnd_data = rnd_pt;
uiBlock *block = uiLayoutGetBlock(layout);
- RenderResult *rr = rnd_data[0];
+ Image *image = rnd_data[0];
ImageUser *iuser = rnd_data[1];
+ Scene *scene = iuser->scene;
+ RenderResult *rr;
RenderLayer *rl;
RenderLayer rl_fake = {NULL};
const char *fake_name;
int nr;
- uiBlockSetCurLayout(block, layout);
+ /* may have been freed since drawing */
+ rr = BKE_image_acquire_renderresult(scene, image);
+ if (UNLIKELY(rr == NULL)) {
+ return;
+ }
+
+ UI_block_layout_set_current(block, layout);
uiLayoutColumn(layout, false);
- uiDefBut(block, LABEL, 0, IFACE_("Layer"),
+ uiDefBut(block, UI_BTYPE_LABEL, 0, IFACE_("Layer"),
0, 0, UI_UNIT_X * 5, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
uiItemS(layout);
- nr = BLI_countlist(&rr->layers) - 1;
+ nr = BLI_listbase_count(&rr->layers) - 1;
fake_name = ui_imageuser_layer_fake_name(rr);
if (fake_name) {
@@ -344,7 +360,7 @@ static void ui_imageuser_layer_menu(bContext *UNUSED(C), uiLayout *layout, void
for (rl = rr->layers.last; rl; rl = rl->prev, nr--) {
final:
- uiDefButS(block, BUTM, B_NOP, IFACE_(rl->name), 0, 0,
+ uiDefButS(block, UI_BTYPE_BUT_MENU, B_NOP, rl->name, 0, 0,
UI_UNIT_X * 5, UI_UNIT_X, &iuser->layer, (float) nr, 0.0, 0, -1, "");
}
@@ -355,11 +371,13 @@ final:
}
BLI_assert(nr == -1);
+
+ BKE_image_release_renderresult(scene, image);
}
static const char *ui_imageuser_pass_fake_name(RenderLayer *rl)
{
- if (rl == NULL || rl->rectf) {
+ if (rl == NULL) {
return IFACE_("Combined");
}
else {
@@ -367,49 +385,129 @@ static const char *ui_imageuser_pass_fake_name(RenderLayer *rl)
}
}
-static void ui_imageuser_pass_menu(bContext *UNUSED(C), uiLayout *layout, void *ptrpair_p)
+static void ui_imageuser_pass_menu(bContext *UNUSED(C), uiLayout *layout, void *rnd_pt)
{
- void **ptrpair = ptrpair_p;
+ void **rnd_data = rnd_pt;
uiBlock *block = uiLayoutGetBlock(layout);
- // RenderResult *rr = ptrpair[0];
- ImageUser *iuser = ptrpair[1];
- /* rl==NULL means composite result */
- RenderLayer *rl = ptrpair[2];
+ Image *image = rnd_data[0];
+ ImageUser *iuser = rnd_data[1];
+ /* (rpass_index == -1) means composite result */
+ const int rpass_index = GET_INT_FROM_POINTER(rnd_data[2]);
+ Scene *scene = iuser->scene;
+ RenderResult *rr;
+ RenderLayer *rl;
RenderPass rpass_fake = {NULL};
RenderPass *rpass;
const char *fake_name;
int nr;
+ int passflag = 0;
+
+ /* may have been freed since drawing */
+ rr = BKE_image_acquire_renderresult(scene, image);
+ if (UNLIKELY(rr == NULL)) {
+ return;
+ }
+
+ rl = BLI_findlink(&rr->layers, rpass_index);
- uiBlockSetCurLayout(block, layout);
+ UI_block_layout_set_current(block, layout);
uiLayoutColumn(layout, false);
- uiDefBut(block, LABEL, 0, IFACE_("Pass"),
+ uiDefBut(block, UI_BTYPE_LABEL, 0, IFACE_("Pass"),
0, 0, UI_UNIT_X * 5, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
uiItemS(layout);
- nr = (rl ? BLI_countlist(&rl->passes) : 0) - 1;
+ nr = 0;
fake_name = ui_imageuser_pass_fake_name(rl);
if (fake_name) {
- BLI_strncpy(rpass_fake.name, fake_name, sizeof(rpass_fake.name));
+ BLI_strncpy(rpass_fake.internal_name, fake_name, sizeof(rpass_fake.internal_name));
nr += 1;
}
/* rendered results don't have a Combined pass */
- for (rpass = rl ? rl->passes.last : NULL; rpass; rpass = rpass->prev, nr--) {
+ /* multiview: the ordering must be ascending, so the left-most pass is always the one picked */
+ for (rpass = rl ? rl->passes.first : NULL; rpass; rpass = rpass->next, nr++) {
+
+ /* just show one pass of each kind */
+ if (passflag & rpass->passtype)
+ continue;
+
+ passflag |= rpass->passtype;
+
final:
- uiDefButS(block, BUTM, B_NOP, IFACE_(rpass->name), 0, 0,
+ uiDefButS(block, UI_BTYPE_BUT_MENU, B_NOP, IFACE_(rpass->internal_name), 0, 0,
UI_UNIT_X * 5, UI_UNIT_X, &iuser->pass, (float) nr, 0.0, 0, -1, "");
}
if (fake_name) {
fake_name = NULL;
rpass = &rpass_fake;
+ nr = 0;
goto final;
}
- BLI_assert(nr == -1);
+ BKE_image_release_renderresult(scene, image);
+}
+
+/**************************** view menus *****************************/
+static void ui_imageuser_view_menu_rr(bContext *UNUSED(C), uiLayout *layout, void *rnd_pt)
+{
+ void **rnd_data = rnd_pt;
+ uiBlock *block = uiLayoutGetBlock(layout);
+ Image *image = rnd_data[0];
+ ImageUser *iuser = rnd_data[1];
+ RenderResult *rr;
+ RenderView *rview;
+ int nr;
+ Scene *scene = iuser->scene;
+
+ /* may have been freed since drawing */
+ rr = BKE_image_acquire_renderresult(scene, image);
+ if (UNLIKELY(rr == NULL)) {
+ return;
+ }
+
+ UI_block_layout_set_current(block, layout);
+ uiLayoutColumn(layout, false);
+
+ uiDefBut(block, UI_BTYPE_LABEL, 0, IFACE_("View"),
+ 0, 0, UI_UNIT_X * 5, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
+
+ uiItemS(layout);
+
+ nr = (rr ? BLI_listbase_count(&rr->views) : 0) - 1;
+ for (rview = rr ? rr->views.last : NULL; rview; rview = rview->prev, nr--) {
+ uiDefButS(block, UI_BTYPE_BUT_MENU, B_NOP, IFACE_(rview->name), 0, 0,
+ UI_UNIT_X * 5, UI_UNIT_X, &iuser->view, (float) nr, 0.0, 0, -1, "");
+ }
+
+ BKE_image_release_renderresult(scene, image);
+}
+
+static void ui_imageuser_view_menu_multiview(bContext *UNUSED(C), uiLayout *layout, void *rnd_pt)
+{
+ void **rnd_data = rnd_pt;
+ uiBlock *block = uiLayoutGetBlock(layout);
+ Image *image = rnd_data[0];
+ ImageUser *iuser = rnd_data[1];
+ int nr;
+ ImageView *iv;
+
+ UI_block_layout_set_current(block, layout);
+ uiLayoutColumn(layout, false);
+
+ uiDefBut(block, UI_BTYPE_LABEL, 0, IFACE_("View"),
+ 0, 0, UI_UNIT_X * 5, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
+
+ uiItemS(layout);
+
+ nr = BLI_listbase_count(&image->views) - 1;
+ for (iv = image->views.last; iv; iv = iv->prev, nr--) {
+ uiDefButS(block, UI_BTYPE_BUT_MENU, B_NOP, IFACE_(iv->name), 0, 0,
+ UI_UNIT_X * 5, UI_UNIT_X, &iuser->view, (float) nr, 0.0, 0, -1, "");
+ }
}
/* 5 layer button callbacks... */
@@ -417,16 +515,17 @@ static void image_multi_cb(bContext *C, void *rr_v, void *iuser_v)
{
ImageUser *iuser = iuser_v;
- BKE_image_multilayer_index(rr_v, iuser);
+ BKE_image_multilayer_index(rr_v, iuser);
WM_event_add_notifier(C, NC_IMAGE | ND_DRAW, NULL);
}
+
static void image_multi_inclay_cb(bContext *C, void *rr_v, void *iuser_v)
{
RenderResult *rr = rr_v;
ImageUser *iuser = iuser_v;
- int tot = BLI_countlist(&rr->layers);
+ int tot = BLI_listbase_count(&rr->layers);
- if (rr->rectf || rr->rect32)
+ if (RE_HasFakeLayer(rr))
tot++; /* fake compo/sequencer layer */
if (iuser->layer < tot - 1) {
@@ -449,32 +548,76 @@ static void image_multi_incpass_cb(bContext *C, void *rr_v, void *iuser_v)
{
RenderResult *rr = rr_v;
ImageUser *iuser = iuser_v;
- RenderLayer *rl = BLI_findlink(&rr->layers, iuser->layer);
+ RenderLayer *rl;
+ RenderPass *rp;
+ int layer = iuser->layer;
- if (rl) {
- int tot = BLI_countlist(&rl->passes);
+ if (RE_HasFakeLayer(rr))
+ layer -= 1;
- if (rr->rectf || rr->rect32)
- tot++; /* fake compo/sequencer layer */
+ rl = BLI_findlink(&rr->layers, layer);
- if (iuser->pass < tot - 1) {
- iuser->pass++;
- BKE_image_multilayer_index(rr, iuser);
- WM_event_add_notifier(C, NC_IMAGE | ND_DRAW, NULL);
+ if (rl) {
+ RenderPass *rpass = BLI_findlink(&rl->passes, iuser->pass);
+ int rp_index = iuser->pass + 1;
+
+ if (rpass == NULL)
+ return;
+
+ for (rp = rpass->next; rp; rp = rp->next, rp_index++) {
+ if (rp->passtype != rpass->passtype) {
+ iuser->pass = rp_index;
+ BKE_image_multilayer_index(rr, iuser);
+ WM_event_add_notifier(C, NC_IMAGE | ND_DRAW, NULL);
+ break;
+ }
}
}
}
static void image_multi_decpass_cb(bContext *C, void *rr_v, void *iuser_v)
{
+ RenderResult *rr = rr_v;
ImageUser *iuser = iuser_v;
+ RenderLayer *rl;
+ RenderPass *rp;
+ int layer = iuser->layer;
- if (iuser->pass > 0) {
- iuser->pass--;
- BKE_image_multilayer_index(rr_v, iuser);
- WM_event_add_notifier(C, NC_IMAGE | ND_DRAW, NULL);
+ if (iuser->pass == 0)
+ return;
+
+ if (RE_HasFakeLayer(rr))
+ layer -= 1;
+
+ rl = BLI_findlink(&rr->layers, layer);
+
+ if (rl) {
+ RenderPass *rpass = BLI_findlink(&rl->passes, iuser->pass);
+ int rp_index = 0;
+
+ if (rpass == NULL)
+ return;
+
+ for (rp = rl->passes.first; rp; rp = rp->next, rp_index++) {
+ if (rp->passtype == rpass->passtype) {
+ iuser->pass = rp_index - 1;
+ BKE_image_multilayer_index(rr, iuser);
+ WM_event_add_notifier(C, NC_IMAGE | ND_DRAW, NULL);
+ break;
+ }
+ }
}
}
+/* 5 view button callbacks... */
+static void image_multiview_cb(bContext *C, void *ima_v, void *iuser_v)
+{
+ Image *ima = ima_v;
+ ImageUser *iuser = iuser_v;
+
+ BKE_image_multiview_index(ima, iuser);
+ WM_event_add_notifier(C, NC_IMAGE | ND_DRAW, NULL);
+}
+
#if 0
static void image_freecache_cb(bContext *C, void *ima_v, void *unused)
{
@@ -492,15 +635,16 @@ static void image_user_change(bContext *C, void *iuser_v, void *unused)
}
#endif
-static void uiblock_layer_pass_buttons(uiLayout *layout, RenderResult *rr, ImageUser *iuser, int w, short *render_slot)
+static void uiblock_layer_pass_buttons(uiLayout *layout, Image *image, RenderResult *rr, ImageUser *iuser, int w, short *render_slot)
{
- static void *rnd_pt[3]; /* XXX, workaround */
+ static void *rnd_pt[4]; /* XXX, workaround */
uiBlock *block = uiLayoutGetBlock(layout);
uiBut *but;
RenderLayer *rl = NULL;
- int wmenu1, wmenu2, wmenu3;
+ int wmenu1, wmenu2, wmenu3, wmenu4;
const char *fake_name;
- const char *display_name;
+ const char *display_name = "";
+ const bool show_stereo = (iuser->flag & IMA_SHOW_STEREO) != 0;
uiLayoutRow(layout, true);
@@ -508,51 +652,94 @@ static void uiblock_layer_pass_buttons(uiLayout *layout, RenderResult *rr, Image
wmenu1 = (2 * w) / 5;
wmenu2 = (3 * w) / 5;
wmenu3 = (3 * w) / 6;
+ wmenu4 = (3 * w) / 6;
- rnd_pt[0] = rr;
+ rnd_pt[0] = image;
rnd_pt[1] = iuser;
rnd_pt[2] = NULL;
/* menu buts */
if (render_slot) {
char str[64];
- BLI_snprintf(str, sizeof(str), IFACE_("Slot %d"), *render_slot + 1);
- but = uiDefMenuBut(block, ui_imageuser_slot_menu, render_slot, str, 0, 0, wmenu1, UI_UNIT_Y, TIP_("Select Slot"));
- uiButSetFunc(but, image_multi_cb, rr, iuser);
- uiButSetMenuFromPulldown(but);
+ if (image->render_slots[*render_slot].name[0] != '\0') {
+ BLI_strncpy(str, image->render_slots[*render_slot].name, sizeof(str));
+ }
+ else {
+ BLI_snprintf(str, sizeof(str), IFACE_("Slot %d"), *render_slot + 1);
+ }
+ but = uiDefMenuBut(block, ui_imageuser_slot_menu, image, str, 0, 0, wmenu1, UI_UNIT_Y, TIP_("Select Slot"));
+ UI_but_func_set(but, image_multi_cb, rr, iuser);
+ UI_but_type_set_menu_from_pulldown(but);
}
if (rr) {
RenderPass *rpass;
+ RenderView *rview;
+ int rpass_index;
/* layer */
fake_name = ui_imageuser_layer_fake_name(rr);
- rl = BLI_findlink(&rr->layers, iuser->layer - (fake_name ? 1 : 0));
- rnd_pt[2] = rl;
-
- display_name = rl ? rl->name : (fake_name ? fake_name : "");
- but = uiDefMenuBut(block, ui_imageuser_layer_menu, rnd_pt, display_name, 0, 0, wmenu2, UI_UNIT_Y, TIP_("Select Layer"));
- uiButSetFunc(but, image_multi_cb, rr, iuser);
- uiButSetMenuFromPulldown(but);
-
+ rpass_index = iuser->layer - (fake_name ? 1 : 0);
+ rl = BLI_findlink(&rr->layers, rpass_index);
+ rnd_pt[2] = SET_INT_IN_POINTER(rpass_index);
+
+ if (RE_layers_have_name(rr)) {
+ display_name = rl ? rl->name : (fake_name ? fake_name : "");
+ but = uiDefMenuBut(block, ui_imageuser_layer_menu, rnd_pt, display_name,
+ 0, 0, wmenu2, UI_UNIT_Y, TIP_("Select Layer"));
+ UI_but_func_set(but, image_multi_cb, rr, iuser);
+ UI_but_type_set_menu_from_pulldown(but);
+ }
/* pass */
fake_name = ui_imageuser_pass_fake_name(rl);
rpass = (rl ? BLI_findlink(&rl->passes, iuser->pass - (fake_name ? 1 : 0)) : NULL);
- display_name = rpass ? rpass->name : (fake_name ? fake_name : "");
- but = uiDefMenuBut(block, ui_imageuser_pass_menu, rnd_pt, display_name, 0, 0, wmenu3, UI_UNIT_Y, TIP_("Select Pass"));
- uiButSetFunc(but, image_multi_cb, rr, iuser);
- uiButSetMenuFromPulldown(but);
+ display_name = rpass ? rpass->internal_name : (fake_name ? fake_name : "");
+ but = uiDefMenuBut(block, ui_imageuser_pass_menu, rnd_pt, IFACE_(display_name),
+ 0, 0, wmenu3, UI_UNIT_Y, TIP_("Select Pass"));
+ UI_but_func_set(but, image_multi_cb, rr, iuser);
+ UI_but_type_set_menu_from_pulldown(but);
+
+ /* view */
+ if (BLI_listbase_count_ex(&rr->views, 2) > 1 &&
+ ((!show_stereo) || (!RE_RenderResult_is_stereo(rr))))
+ {
+ rview = BLI_findlink(&rr->views, iuser->view);
+ display_name = rview ? rview->name : "";
+
+ but = uiDefMenuBut(block, ui_imageuser_view_menu_rr, rnd_pt, display_name, 0, 0, wmenu4, UI_UNIT_Y, TIP_("Select View"));
+ UI_but_func_set(but, image_multi_cb, rr, iuser);
+ UI_but_type_set_menu_from_pulldown(but);
+ }
+ }
+
+ /* stereo image */
+ else if (((image->flag & IMA_IS_STEREO) && (!show_stereo)) ||
+ ((image->flag & IMA_IS_MULTIVIEW) && ((image->flag & IMA_IS_STEREO) == 0)))
+ {
+ ImageView *iv;
+ int nr = 0;
+
+ for (iv = image->views.first; iv; iv = iv->next) {
+ if (nr++ == iuser->view) {
+ display_name = iv->name;
+ break;
+ }
+ }
+
+ but = uiDefMenuBut(block, ui_imageuser_view_menu_multiview, rnd_pt, display_name, 0, 0, wmenu1, UI_UNIT_Y, TIP_("Select View"));
+ UI_but_func_set(but, image_multiview_cb, image, iuser);
+ UI_but_type_set_menu_from_pulldown(but);
}
}
-static void uiblock_layer_pass_arrow_buttons(uiLayout *layout, RenderResult *rr, ImageUser *iuser, short *render_slot)
+static void uiblock_layer_pass_arrow_buttons(uiLayout *layout, Image *image, RenderResult *rr, ImageUser *iuser,
+ int menus_width, short *render_slot)
{
uiBlock *block = uiLayoutGetBlock(layout);
uiLayout *row;
uiBut *but;
- const float dpi_fac = UI_DPI_FAC;
row = uiLayoutRow(layout, true);
@@ -564,20 +751,20 @@ static void uiblock_layer_pass_arrow_buttons(uiLayout *layout, RenderResult *rr,
}
/* decrease, increase arrows */
- but = uiDefIconBut(block, BUT, 0, ICON_TRIA_LEFT, 0, 0, 0.85f * UI_UNIT_X, UI_UNIT_Y, NULL, 0, 0, 0, 0, TIP_("Previous Layer"));
- uiButSetFunc(but, image_multi_declay_cb, rr, iuser);
- but = uiDefIconBut(block, BUT, 0, ICON_TRIA_RIGHT, 0, 0, 0.90f * UI_UNIT_X, UI_UNIT_Y, NULL, 0, 0, 0, 0, TIP_("Next Layer"));
- uiButSetFunc(but, image_multi_inclay_cb, rr, iuser);
+ but = uiDefIconBut(block, UI_BTYPE_BUT, 0, ICON_TRIA_LEFT, 0, 0, 0.85f * UI_UNIT_X, UI_UNIT_Y, NULL, 0, 0, 0, 0, TIP_("Previous Layer"));
+ UI_but_func_set(but, image_multi_declay_cb, rr, iuser);
+ but = uiDefIconBut(block, UI_BTYPE_BUT, 0, ICON_TRIA_RIGHT, 0, 0, 0.90f * UI_UNIT_X, UI_UNIT_Y, NULL, 0, 0, 0, 0, TIP_("Next Layer"));
+ UI_but_func_set(but, image_multi_inclay_cb, rr, iuser);
- uiblock_layer_pass_buttons(row, rr, iuser, 230 * dpi_fac, render_slot);
+ uiblock_layer_pass_buttons(row, image, rr, iuser, menus_width, render_slot);
/* decrease, increase arrows */
- but = uiDefIconBut(block, BUT, 0, ICON_TRIA_LEFT, 0, 0, 0.85f * UI_UNIT_X, UI_UNIT_Y, NULL, 0, 0, 0, 0, TIP_("Previous Pass"));
- uiButSetFunc(but, image_multi_decpass_cb, rr, iuser);
- but = uiDefIconBut(block, BUT, 0, ICON_TRIA_RIGHT, 0, 0, 0.90f * UI_UNIT_X, UI_UNIT_Y, NULL, 0, 0, 0, 0, TIP_("Next Pass"));
- uiButSetFunc(but, image_multi_incpass_cb, rr, iuser);
+ but = uiDefIconBut(block, UI_BTYPE_BUT, 0, ICON_TRIA_LEFT, 0, 0, 0.85f * UI_UNIT_X, UI_UNIT_Y, NULL, 0, 0, 0, 0, TIP_("Previous Pass"));
+ UI_but_func_set(but, image_multi_decpass_cb, rr, iuser);
+ but = uiDefIconBut(block, UI_BTYPE_BUT, 0, ICON_TRIA_RIGHT, 0, 0, 0.90f * UI_UNIT_X, UI_UNIT_Y, NULL, 0, 0, 0, 0, TIP_("Next Pass"));
+ UI_but_func_set(but, image_multi_incpass_cb, rr, iuser);
- uiBlockEndAlign(block);
+ UI_block_align_end(block);
}
// XXX HACK!
@@ -603,10 +790,8 @@ static void rna_update_cb(bContext *C, void *arg_cb, void *UNUSED(arg))
RNA_property_update(C, &cb->ptr, cb->prop);
}
-void uiTemplateImage(uiLayout *layout, bContext *C, PointerRNA *ptr, const char *propname, PointerRNA *userptr, int compact)
+void uiTemplateImage(uiLayout *layout, bContext *C, PointerRNA *ptr, const char *propname, PointerRNA *userptr, int compact, int multiview)
{
-#define MAX_INFO_LEN 128
-
PropertyRNA *prop;
PointerRNA imaptr;
RNAUpdateCb *cb;
@@ -615,7 +800,7 @@ void uiTemplateImage(uiLayout *layout, bContext *C, PointerRNA *ptr, const char
Scene *scene = CTX_data_scene(C);
uiLayout *row, *split, *col;
uiBlock *block;
- char str[MAX_INFO_LEN];
+ char str[MAX_IMAGE_INFO_LEN];
void *lock;
@@ -652,14 +837,14 @@ void uiTemplateImage(uiLayout *layout, bContext *C, PointerRNA *ptr, const char
uiLayoutSetContextPointer(layout, "edit_image_user", userptr);
if (!compact)
- uiTemplateID(layout, C, ptr, propname, "IMAGE_OT_new", "IMAGE_OT_open", NULL);
+ uiTemplateID(layout, C, ptr, propname, ima ? NULL : "IMAGE_OT_new", "IMAGE_OT_open", NULL);
if (ima) {
- uiBlockSetNFunc(block, rna_update_cb, MEM_dupallocN(cb), NULL);
+ UI_block_funcN_set(block, rna_update_cb, MEM_dupallocN(cb), NULL);
if (ima->source == IMA_SRC_VIEWER) {
ImBuf *ibuf = BKE_image_acquire_ibuf(ima, iuser, &lock);
- image_info(scene, iuser, ima, ibuf, str, MAX_INFO_LEN);
+ image_info(scene, iuser, ima, ibuf, str, MAX_IMAGE_INFO_LEN);
BKE_image_release_ibuf(ima, ibuf, lock);
uiItemL(layout, ima->id.name + 2, ICON_NONE);
@@ -670,28 +855,35 @@ void uiTemplateImage(uiLayout *layout, bContext *C, PointerRNA *ptr, const char
#if 0
iuser = ntree_get_active_iuser(scene->nodetree);
if (iuser) {
- uiBlockBeginAlign(block);
- uiDefIconTextBut(block, BUT, B_SIMA_RECORD, ICON_REC, "Record", 10, 120, 100, 20, 0, 0, 0, 0, 0, "");
- uiDefIconTextBut(block, BUT, B_SIMA_PLAY, ICON_PLAY, "Play", 110, 120, 100, 20, 0, 0, 0, 0, 0, "");
- but = uiDefBut(block, BUT, B_NOP, "Free Cache", 210, 120, 100, 20, 0, 0, 0, 0, 0, "");
- uiButSetFunc(but, image_freecache_cb, ima, NULL);
+ UI_block_align_begin(block);
+ uiDefIconTextBut(block, UI_BTYPE_BUT, B_SIMA_RECORD, ICON_REC, "Record", 10, 120, 100, 20, 0, 0, 0, 0, 0, "");
+ uiDefIconTextBut(block, UI_BTYPE_BUT, B_SIMA_PLAY, ICON_PLAY, "Play", 110, 120, 100, 20, 0, 0, 0, 0, 0, "");
+ but = uiDefBut(block, UI_BTYPE_BUT, B_NOP, "Free Cache", 210, 120, 100, 20, 0, 0, 0, 0, 0, "");
+ UI_but_func_set(but, image_freecache_cb, ima, NULL);
if (iuser->frames)
BLI_snprintf(str, sizeof(str), "(%d) Frames:", iuser->framenr);
else strcpy(str, "Frames:");
- uiBlockBeginAlign(block);
- uiDefButI(block, NUM, imagechanged, str, 10, 90, 150, 20, &iuser->frames, 0.0, MAXFRAMEF, 0, 0, "Number of images of a movie to use");
- uiDefButI(block, NUM, imagechanged, "StartFr:", 160, 90, 150, 20, &iuser->sfra, 1.0, MAXFRAMEF, 0, 0, "Global starting frame of the movie");
+ UI_block_align_begin(block);
+ uiDefButI(block, UI_BTYPE_NUM, imagechanged, str, 10, 90, 150, 20, &iuser->frames, 0.0, MAXFRAMEF, 0, 0, "Number of images of a movie to use");
+ uiDefButI(block, UI_BTYPE_NUM, imagechanged, "StartFr:", 160, 90, 150, 20, &iuser->sfra, 1.0, MAXFRAMEF, 0, 0, "Global starting frame of the movie");
}
#endif
}
else if (ima->type == IMA_TYPE_R_RESULT) {
/* browse layer/passes */
RenderResult *rr;
+ const float dpi_fac = UI_DPI_FAC;
+ const int menus_width = 230 * dpi_fac;
/* use BKE_image_acquire_renderresult so we get the correct slot in the menu */
rr = BKE_image_acquire_renderresult(scene, ima);
- uiblock_layer_pass_arrow_buttons(layout, rr, iuser, &ima->render_slot);
+ if (rr) {
+ uiblock_layer_pass_arrow_buttons(layout, ima, rr, iuser, menus_width, &ima->render_slot);
+ }
+ else {
+ uiblock_layer_pass_buttons(layout, ima, rr, iuser, menus_width, &ima->render_slot);
+ }
BKE_image_release_renderresult(scene, ima);
}
}
@@ -700,13 +892,13 @@ void uiTemplateImage(uiLayout *layout, bContext *C, PointerRNA *ptr, const char
if (ima->source != IMA_SRC_GENERATED) {
row = uiLayoutRow(layout, true);
- if (ima->packedfile)
+ if (BKE_image_has_packedfile(ima))
uiItemO(row, "", ICON_PACKAGE, "image.unpack");
else
uiItemO(row, "", ICON_UGLYPACKAGE, "image.pack");
row = uiLayoutRow(row, true);
- uiLayoutSetEnabled(row, ima->packedfile == NULL);
+ uiLayoutSetEnabled(row, BKE_image_has_packedfile(ima) == false);
uiItemR(row, &imaptr, "filepath", 0, "", ICON_NONE);
uiItemO(row, "", ICON_FILE_REFRESH, "image.reload");
}
@@ -724,14 +916,12 @@ void uiTemplateImage(uiLayout *layout, bContext *C, PointerRNA *ptr, const char
/* multilayer? */
if (ima->type == IMA_TYPE_MULTILAYER && ima->rr) {
- uiblock_layer_pass_arrow_buttons(layout, ima->rr, iuser, NULL);
+ const float dpi_fac = UI_DPI_FAC;
+ uiblock_layer_pass_arrow_buttons(layout, ima, ima->rr, iuser, 230 * dpi_fac, NULL);
}
else if (ima->source != IMA_SRC_GENERATED) {
if (compact == 0) {
- ImBuf *ibuf = BKE_image_acquire_ibuf(ima, iuser, &lock);
- image_info(scene, iuser, ima, ibuf, str, MAX_INFO_LEN);
- BKE_image_release_ibuf(ima, ibuf, lock);
- uiItemL(layout, str, ICON_NONE);
+ uiTemplateImageInfo(layout, C, ima, iuser);
}
}
@@ -745,7 +935,7 @@ void uiTemplateImage(uiLayout *layout, bContext *C, PointerRNA *ptr, const char
bool has_alpha = true;
if (ibuf) {
- int imtype = BKE_ftype_to_imtype(ibuf->ftype);
+ int imtype = BKE_image_ftype_to_imtype(ibuf->ftype, &ibuf->foptions);
char valid_channels = BKE_imtype_valid_channels(imtype, false);
has_alpha = (valid_channels & IMA_CHAN_FLAG_ALPHA) != 0;
@@ -753,13 +943,28 @@ void uiTemplateImage(uiLayout *layout, bContext *C, PointerRNA *ptr, const char
BKE_image_release_ibuf(ima, ibuf, NULL);
}
+ if (multiview) {
+ if ((scene->r.scemode & R_MULTIVIEW) != 0) {
+ uiItemR(layout, &imaptr, "use_multiview", 0, NULL, ICON_NONE);
+
+ if (RNA_boolean_get(&imaptr, "use_multiview")) {
+ uiTemplateImageViews(layout, &imaptr);
+ }
+ }
+ }
+
if (has_alpha) {
col = uiLayoutColumn(layout, false);
uiItemR(col, &imaptr, "use_alpha", 0, NULL, ICON_NONE);
- uiItemR(col, &imaptr, "alpha_mode", 0, IFACE_("Alpha"), ICON_NONE);
+ row = uiLayoutRow(col, false);
+ uiLayoutSetActive(row, RNA_boolean_get(&imaptr, "use_alpha"));
+ uiItemR(row, &imaptr, "alpha_mode", 0, IFACE_("Alpha"), ICON_NONE);
}
- uiItemS(layout);
+ if (ima->source == IMA_SRC_MOVIE) {
+ col = uiLayoutColumn(layout, false);
+ uiItemR(col, &imaptr, "use_deinterlace", 0, IFACE_("Deinterlace"), ICON_NONE);
+ }
split = uiLayoutSplit(layout, 0.0f, false);
@@ -809,16 +1014,18 @@ void uiTemplateImage(uiLayout *layout, bContext *C, PointerRNA *ptr, const char
uiItemR(col, &imaptr, "use_generated_float", 0, NULL, ICON_NONE);
uiItemR(split, &imaptr, "generated_type", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
+
+ if (ima->gen_type == IMA_GENTYPE_BLANK) {
+ uiItemR(layout, &imaptr, "generated_color", 0, NULL, ICON_NONE);
+ }
}
}
- uiBlockSetNFunc(block, NULL, NULL, NULL);
+ UI_block_funcN_set(block, NULL, NULL, NULL);
}
MEM_freeN(cb);
-
-#undef MAX_INFO_LEN
}
void uiTemplateImageSettings(uiLayout *layout, PointerRNA *imfptr, int color_management)
@@ -922,35 +1129,143 @@ void uiTemplateImageSettings(uiLayout *layout, PointerRNA *imfptr, int color_man
}
}
+void uiTemplateImageStereo3d(uiLayout *layout, PointerRNA *stereo3d_format_ptr)
+{
+ Stereo3dFormat *stereo3d_format = stereo3d_format_ptr->data;
+ uiLayout *col;
+
+ col = uiLayoutColumn(layout, false);
+ uiItemR(col, stereo3d_format_ptr, "display_mode", 0, NULL, ICON_NONE);
+
+ switch (stereo3d_format->display_mode) {
+ case S3D_DISPLAY_ANAGLYPH:
+ {
+ uiItemR(col, stereo3d_format_ptr, "anaglyph_type", 0, NULL, ICON_NONE);
+ break;
+ }
+ case S3D_DISPLAY_INTERLACE:
+ {
+ uiItemR(col, stereo3d_format_ptr, "interlace_type", 0, NULL, ICON_NONE);
+ uiItemR(col, stereo3d_format_ptr, "use_interlace_swap", 0, NULL, ICON_NONE);
+ break;
+ }
+ case S3D_DISPLAY_SIDEBYSIDE:
+ {
+ uiItemR(col, stereo3d_format_ptr, "use_sidebyside_crosseyed", 0, NULL, ICON_NONE);
+ /* fall-through */
+ }
+ case S3D_DISPLAY_TOPBOTTOM:
+ {
+ uiItemR(col, stereo3d_format_ptr, "use_squeezed_frame", 0, NULL, ICON_NONE);
+ break;
+ }
+ }
+}
+
+static void uiTemplateViewsFormat(uiLayout *layout, PointerRNA *ptr, PointerRNA *stereo3d_format_ptr)
+{
+ uiLayout *col, *box;
+
+ col = uiLayoutColumn(layout, false);
+
+ uiItemL(col, IFACE_("Views Format:"), ICON_NONE);
+ uiItemR(uiLayoutRow(col, false), ptr, "views_format", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
+
+ if (stereo3d_format_ptr) {
+ box = uiLayoutBox(col);
+ uiLayoutSetActive(box, RNA_enum_get(ptr, "views_format") == R_IMF_VIEWS_STEREO_3D);
+ uiTemplateImageStereo3d(box, stereo3d_format_ptr);
+ }
+}
+
+void uiTemplateImageViews(uiLayout *layout, PointerRNA *imaptr)
+{
+ Image *ima = imaptr->data;
+
+ if (ima->type != IMA_TYPE_MULTILAYER) {
+ PropertyRNA *prop;
+ PointerRNA stereo3d_format_ptr;
+
+ prop = RNA_struct_find_property(imaptr, "stereo_3d_format");
+ stereo3d_format_ptr = RNA_property_pointer_get(imaptr, prop);
+
+ uiTemplateViewsFormat(layout, imaptr, &stereo3d_format_ptr);
+ }
+ else {
+ uiTemplateViewsFormat(layout, imaptr, NULL);
+ }
+}
+
+void uiTemplateImageFormatViews(uiLayout *layout, PointerRNA *imfptr, PointerRNA *ptr)
+{
+ ImageFormatData *imf = imfptr->data;
+
+ if (ptr == NULL)
+ return;
+
+ uiItemR(layout, ptr, "use_multiview", 0, NULL, ICON_NONE);
+
+ if (RNA_boolean_get(ptr, "use_multiview")) {
+ if (imf->imtype != R_IMF_IMTYPE_MULTILAYER) {
+ PropertyRNA *prop;
+ PointerRNA stereo3d_format_ptr;
+
+ prop = RNA_struct_find_property(imfptr, "stereo_3d_format");
+ stereo3d_format_ptr = RNA_property_pointer_get(imfptr, prop);
+
+ uiTemplateViewsFormat(layout, imfptr, &stereo3d_format_ptr);
+ }
+ else {
+ uiTemplateViewsFormat(layout, imfptr, NULL);
+ }
+ }
+}
+
void uiTemplateImageLayers(uiLayout *layout, bContext *C, Image *ima, ImageUser *iuser)
{
Scene *scene = CTX_data_scene(C);
/* render layers and passes */
if (ima && iuser) {
- const float dpi_fac = UI_DPI_FAC;
RenderResult *rr;
+ const float dpi_fac = UI_DPI_FAC;
+ const int menus_width = 160 * dpi_fac;
+ const bool is_render_result = (ima->type == IMA_TYPE_R_RESULT);
/* use BKE_image_acquire_renderresult so we get the correct slot in the menu */
rr = BKE_image_acquire_renderresult(scene, ima);
- uiblock_layer_pass_buttons(layout, rr, iuser, 160 * dpi_fac, (ima->type == IMA_TYPE_R_RESULT) ? &ima->render_slot : NULL);
+ if (rr && is_render_result) {
+ uiblock_layer_pass_arrow_buttons(layout, ima, rr, iuser, menus_width, &ima->render_slot);
+ }
+ else {
+ uiblock_layer_pass_buttons(layout, ima, rr, iuser, menus_width,
+ is_render_result ? &ima->render_slot : NULL);
+ }
BKE_image_release_renderresult(scene, ima);
}
}
-void image_buttons_register(ARegionType *art)
+void uiTemplateImageInfo(uiLayout *layout, bContext *C, Image *ima, ImageUser *iuser)
{
- PanelType *pt;
- const char *category = "Grease Pencil";
+ ImBuf *ibuf;
+ char str[MAX_IMAGE_INFO_LEN];
+ void *lock;
+
+ if (!ima || !iuser)
+ return;
- pt = MEM_callocN(sizeof(PanelType), "spacetype image panel gpencil");
- strcpy(pt->idname, "IMAGE_PT_gpencil");
- strcpy(pt->label, N_("Grease Pencil"));
- strcpy(pt->translation_context, BLF_I18NCONTEXT_DEFAULT_BPYRNA);
- pt->draw_header = ED_gpencil_panel_standard_header;
- pt->draw = ED_gpencil_panel_standard;
- BLI_strncpy(pt->category, category, BLI_strlen_utf8(category));
- BLI_addtail(&art->paneltypes, pt);
+ ibuf = BKE_image_acquire_ibuf(ima, iuser, &lock);
+
+ image_info(CTX_data_scene(C), iuser, ima, ibuf, str, MAX_IMAGE_INFO_LEN);
+ BKE_image_release_ibuf(ima, ibuf, lock);
+ uiItemL(layout, str, ICON_NONE);
+}
+
+#undef MAX_IMAGE_INFO_LEN
+
+void image_buttons_register(ARegionType *UNUSED(art))
+{
+
}
static int image_properties_toggle_exec(bContext *C, wmOperator *UNUSED(op))
diff --git a/source/blender/editors/space_image/image_draw.c b/source/blender/editors/space_image/image_draw.c
index 79c21bab01c..3a178ed0277 100644
--- a/source/blender/editors/space_image/image_draw.c
+++ b/source/blender/editors/space_image/image_draw.c
@@ -68,6 +68,7 @@
#include "ED_gpencil.h"
#include "ED_image.h"
#include "ED_mask.h"
+#include "ED_render.h"
#include "ED_screen.h"
#include "UI_interface.h"
@@ -79,25 +80,36 @@
#include "image_intern.h"
-static void draw_render_info(Scene *scene, Image *ima, ARegion *ar, float zoomx, float zoomy)
+static void draw_render_info(const bContext *C,
+ Scene *scene,
+ Image *ima,
+ ARegion *ar,
+ float zoomx,
+ float zoomy)
{
RenderResult *rr;
Render *re = RE_GetRender(scene->id.name);
+ RenderData *rd = RE_engine_get_render_data(re);
+ Scene *stats_scene = ED_render_job_get_scene(C);
+ if (stats_scene == NULL) {
+ stats_scene = CTX_data_scene(C);
+ }
- rr = BKE_image_acquire_renderresult(scene, ima);
+ rr = BKE_image_acquire_renderresult(stats_scene, ima);
if (rr && rr->text) {
float fill_color[4] = {0.0f, 0.0f, 0.0f, 0.25f};
- ED_region_info_draw(ar, rr->text, 1, fill_color);
+ ED_region_info_draw(ar, rr->text, fill_color, true);
}
- BKE_image_release_renderresult(scene, ima);
+ BKE_image_release_renderresult(stats_scene, ima);
if (re) {
int total_tiles;
+ bool need_free_tiles;
rcti *tiles;
- RE_engine_get_current_tiles(re, &total_tiles, &tiles);
+ tiles = RE_engine_get_current_tiles(re, &total_tiles, &need_free_tiles);
if (total_tiles) {
int i, x, y;
@@ -110,9 +122,9 @@ static void draw_render_info(Scene *scene, Image *ima, ARegion *ar, float zoomx,
glTranslatef(x, y, 0.0f);
glScalef(zoomx, zoomy, 1.0f);
- if (scene->r.mode & R_BORDER) {
- glTranslatef((int)(-scene->r.border.xmin * scene->r.xsch * scene->r.size / 100.0f),
- (int)(-scene->r.border.ymin * scene->r.ysch * scene->r.size / 100.0f),
+ if (rd->mode & R_BORDER) {
+ glTranslatef((int)(-rd->border.xmin * rd->xsch * rd->size / 100.0f),
+ (int)(-rd->border.ymin * rd->ysch * rd->size / 100.0f),
0.0f);
}
@@ -122,7 +134,9 @@ static void draw_render_info(Scene *scene, Image *ima, ARegion *ar, float zoomx,
glaDrawBorderCorners(tile, zoomx, zoomy);
}
- MEM_freeN(tiles);
+ if (need_free_tiles) {
+ MEM_freeN(tiles);
+ }
glPopMatrix();
}
@@ -769,7 +783,7 @@ void draw_image_main(const bContext *C, ARegion *ar)
Image *ima;
ImBuf *ibuf;
float zoomx, zoomy;
- bool show_viewer, show_render, show_paint;
+ bool show_viewer, show_render, show_paint, show_stereo3d, show_multilayer;
void *lock;
/* XXX can we do this in refresh? */
@@ -799,6 +813,8 @@ void draw_image_main(const bContext *C, ARegion *ar)
show_viewer = (ima && ima->source == IMA_SRC_VIEWER) != 0;
show_render = (show_viewer && ima->type == IMA_TYPE_R_RESULT) != 0;
show_paint = (ima && (sima->mode == SI_MODE_PAINT) && (show_viewer == false) && (show_render == false));
+ show_stereo3d = (ima && (ima->flag & IMA_IS_STEREO) && (sima->iuser.flag & IMA_SHOW_STEREO));
+ show_multilayer = ima && BKE_image_is_multilayer(ima);
if (show_viewer) {
/* use locked draw for drawing viewer image buffer since the compositor
@@ -809,17 +825,41 @@ void draw_image_main(const bContext *C, ARegion *ar)
BLI_lock_thread(LOCK_DRAW_IMAGE);
}
+ if (show_stereo3d) {
+ if (show_multilayer)
+ /* update multiindex and pass for the current eye */
+ BKE_image_multilayer_index(ima->rr, &sima->iuser);
+ else
+ BKE_image_multiview_index(ima, &sima->iuser);
+ }
+
ibuf = ED_space_image_acquire_buffer(sima, &lock);
/* draw the image or grid */
- if (ibuf == NULL)
+ if (ibuf == NULL) {
ED_region_grid_draw(ar, zoomx, zoomy);
- else if (sima->flag & SI_DRAW_TILE)
- draw_image_buffer_repeated(C, sima, ar, scene, ima, ibuf, zoomx, zoomy);
- else if (ima && (ima->tpageflag & IMA_TILES))
- draw_image_buffer_tiled(sima, ar, scene, ima, ibuf, 0.0f, 0.0, zoomx, zoomy);
- else
- draw_image_buffer(C, sima, ar, scene, ibuf, 0.0f, 0.0f, zoomx, zoomy);
+ }
+ else {
+
+ if (sima->flag & SI_DRAW_TILE)
+ draw_image_buffer_repeated(C, sima, ar, scene, ima, ibuf, zoomx, zoomy);
+ else if (ima && (ima->tpageflag & IMA_TILES))
+ draw_image_buffer_tiled(sima, ar, scene, ima, ibuf, 0.0f, 0.0, zoomx, zoomy);
+ else
+ draw_image_buffer(C, sima, ar, scene, ibuf, 0.0f, 0.0f, zoomx, zoomy);
+
+ if (sima->flag & SI_DRAW_METADATA) {
+ int x, y;
+ rctf frame;
+
+ BLI_rctf_init(&frame, 0.0f, ibuf->x, 0.0f, ibuf->y);
+ UI_view2d_view_to_region(&ar->v2d, 0.0f, 0.0f, &x, &y);
+
+ ED_region_image_metadata_draw(x, y, ibuf, frame, zoomx, zoomy);
+ }
+ }
+
+ ED_space_image_release_buffer(sima, ibuf, lock);
/* paint helpers */
if (show_paint)
@@ -842,19 +882,22 @@ void draw_image_main(const bContext *C, ARegion *ar)
}
#endif
- ED_space_image_release_buffer(sima, ibuf, lock);
-
if (show_viewer) {
BLI_unlock_thread(LOCK_DRAW_IMAGE);
}
/* render info */
if (ima && show_render)
- draw_render_info(sima->iuser.scene, ima, ar, zoomx, zoomy);
+ draw_render_info(C, sima->iuser.scene, ima, ar, zoomx, zoomy);
}
-static bool show_image_cache(Image *image, Mask *mask)
+bool ED_space_image_show_cache(SpaceImage *sima)
{
+ Image *image = ED_space_image(sima);
+ Mask *mask = NULL;
+ if (sima->mode == SI_MODE_MASK) {
+ mask = ED_space_image_get_mask(sima);
+ }
if (image == NULL && mask == NULL) {
return false;
}
@@ -872,12 +915,12 @@ void draw_image_cache(const bContext *C, ARegion *ar)
float x, cfra = CFRA, sfra = SFRA, efra = EFRA, framelen = ar->winx / (efra - sfra + 1);
Mask *mask = NULL;
- if (sima->mode == SI_MODE_MASK) {
- mask = ED_space_image_get_mask(sima);
+ if (!ED_space_image_show_cache(sima)) {
+ return;
}
- if (!show_image_cache(image, mask)) {
- return;
+ if (sima->mode == SI_MODE_MASK) {
+ mask = ED_space_image_get_mask(sima);
}
glEnable(GL_BLEND);
diff --git a/source/blender/editors/space_image/image_edit.c b/source/blender/editors/space_image/image_edit.c
index 24b1c54dd9f..38c9604d14b 100644
--- a/source/blender/editors/space_image/image_edit.c
+++ b/source/blender/editors/space_image/image_edit.c
@@ -35,6 +35,7 @@
#include "BLI_rect.h"
+#include "BKE_colortools.h"
#include "BKE_context.h"
#include "BKE_global.h"
#include "BKE_image.h"
@@ -103,7 +104,7 @@ void ED_space_image_set_mask(bContext *C, SpaceImage *sima, Mask *mask)
}
}
-ImBuf *ED_space_image_acquire_buffer(SpaceImage *sima, void **lock_r)
+ImBuf *ED_space_image_acquire_buffer(SpaceImage *sima, void **r_lock)
{
ImBuf *ibuf;
@@ -113,7 +114,7 @@ ImBuf *ED_space_image_acquire_buffer(SpaceImage *sima, void **lock_r)
return BIF_render_spare_imbuf();
else
#endif
- ibuf = BKE_image_acquire_ibuf(sima->image, &sima->iuser, lock_r);
+ ibuf = BKE_image_acquire_ibuf(sima->image, &sima->iuser, r_lock);
if (ibuf) {
if (ibuf->rect || ibuf->rect_float)
@@ -123,7 +124,7 @@ ImBuf *ED_space_image_acquire_buffer(SpaceImage *sima, void **lock_r)
}
}
else
- *lock_r = NULL;
+ *r_lock = NULL;
return NULL;
}
@@ -290,6 +291,20 @@ void ED_image_point_pos__reverse(SpaceImage *sima, ARegion *ar, const float co[2
r_co[1] = (co[1] * height * zoomy) + (float)sy;
}
+void ED_space_image_scopes_update(const struct bContext *C, struct SpaceImage *sima, struct ImBuf *ibuf, bool use_view_settings)
+{
+ Scene *scene = CTX_data_scene(C);
+ Object *ob = CTX_data_active_object(C);
+
+ /* scope update can be expensive, don't update during paint modes */
+ if (sima->mode == SI_MODE_PAINT)
+ return;
+ if (ob && ((ob->mode & (OB_MODE_TEXTURE_PAINT | OB_MODE_EDIT)) != 0))
+ return;
+
+ scopes_update(&sima->scopes, ibuf, use_view_settings ? &scene->view_settings : NULL, &scene->display_settings);
+}
+
bool ED_space_image_show_render(SpaceImage *sima)
{
return (sima->image && ELEM(sima->image->type, IMA_TYPE_R_RESULT, IMA_TYPE_COMPOSITE));
@@ -303,13 +318,6 @@ bool ED_space_image_show_paint(SpaceImage *sima)
return (sima->mode == SI_MODE_PAINT);
}
-bool ED_space_image_show_texpaint(SpaceImage *sima, Object *ob)
-{
- return (ob && ob->type == OB_MESH &&
- ob->mode == OB_MODE_TEXTURE_PAINT &&
- !(sima->flag & SI_NO_DRAW_TEXPAINT));
-}
-
bool ED_space_image_show_uvedit(SpaceImage *sima, Object *obedit)
{
if (sima && (ED_space_image_show_render(sima) || ED_space_image_show_paint(sima)))
@@ -327,24 +335,6 @@ bool ED_space_image_show_uvedit(SpaceImage *sima, Object *obedit)
return false;
}
-bool ED_space_image_show_uvshadow(SpaceImage *sima, Object *obedit)
-{
- if (ED_space_image_show_render(sima))
- return false;
-
- if (ED_space_image_show_paint(sima))
- if (obedit && obedit->type == OB_MESH) {
- struct BMEditMesh *em = BKE_editmesh_from_object(obedit);
- bool ret;
-
- ret = EDBM_mtexpoly_check(em);
-
- return ret && !(sima->flag & SI_NO_DRAW_TEXPAINT);
- }
-
- return false;
-}
-
/* matches clip function */
bool ED_space_image_check_show_maskedit(Scene *scene, SpaceImage *sima)
{
diff --git a/source/blender/editors/space_image/image_intern.h b/source/blender/editors/space_image/image_intern.h
index 74a0a18b0c8..6eaad302180 100644
--- a/source/blender/editors/space_image/image_intern.h
+++ b/source/blender/editors/space_image/image_intern.h
@@ -38,11 +38,7 @@ struct ARegion;
struct ARegionType;
struct ScrArea;
struct SpaceImage;
-struct Object;
-struct Image;
-struct ImBuf;
struct wmOperatorType;
-struct Scene;
struct bNodeTree;
/* space_image.c */
@@ -92,6 +88,8 @@ void IMAGE_OT_curves_point_set(struct wmOperatorType *ot);
void IMAGE_OT_change_frame(struct wmOperatorType *ot);
void IMAGE_OT_read_renderlayers(struct wmOperatorType *ot);
+void IMAGE_OT_render_border(struct wmOperatorType *ot);
+void IMAGE_OT_clear_render_border(struct wmOperatorType *ot);
/* image_panels.c */
struct ImageUser *ntree_get_active_iuser(struct bNodeTree *ntree);
diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c
index cd95e67f070..3c5aff4d698 100644
--- a/source/blender/editors/space_image/image_ops.c
+++ b/source/blender/editors/space_image/image_ops.c
@@ -30,16 +30,23 @@
#include <stddef.h>
#include <string.h>
+#include <fcntl.h>
#include <stdlib.h>
#include <errno.h>
+#ifndef WIN32
+# include <unistd.h>
+#else
+# include <io.h>
+#endif
#include "MEM_guardedalloc.h"
#include "BLI_math.h"
#include "BLI_blenlib.h"
#include "BLI_utildefines.h"
+#include "BLI_string_utf8.h"
-#include "BLF_translation.h"
+#include "BLT_translation.h"
#include "DNA_object_types.h"
#include "DNA_node_types.h"
@@ -49,22 +56,27 @@
#include "BKE_colortools.h"
#include "BKE_context.h"
#include "BKE_depsgraph.h"
+#include "BKE_DerivedMesh.h"
#include "BKE_icons.h"
#include "BKE_image.h"
#include "BKE_global.h"
#include "BKE_library.h"
#include "BKE_main.h"
#include "BKE_packedFile.h"
+#include "BKE_paint.h"
#include "BKE_report.h"
#include "BKE_screen.h"
#include "BKE_sound.h"
+#include "BKE_scene.h"
#include "GPU_draw.h"
+#include "GPU_buffers.h"
#include "IMB_colormanagement.h"
#include "IMB_imbuf.h"
#include "IMB_imbuf_types.h"
#include "IMB_moviecache.h"
+#include "intern/openexr/openexr_multi.h"
#include "RE_pipeline.h"
@@ -73,6 +85,7 @@
#include "RNA_enum_types.h"
#include "ED_image.h"
+#include "ED_mask.h"
#include "ED_paint.h"
#include "ED_render.h"
#include "ED_screen.h"
@@ -89,6 +102,8 @@
#include "PIL_time.h"
+#include "RE_engine.h"
+
#include "image_intern.h"
/******************** view navigation utilities *********************/
@@ -144,10 +159,29 @@ static int image_poll(bContext *C)
static int space_image_buffer_exists_poll(bContext *C)
{
SpaceImage *sima = CTX_wm_space_image(C);
- if (sima && sima->spacetype == SPACE_IMAGE)
- if (ED_space_image_has_buffer(sima))
- return 1;
- return 0;
+ if (sima && ED_space_image_has_buffer(sima)) {
+ return true;
+ }
+ return false;
+}
+
+static int image_not_packed_poll(bContext *C)
+{
+ SpaceImage *sima = CTX_wm_space_image(C);
+
+ /* Do not run 'replace' on packed images, it does not give user expected results at all. */
+ if (sima && sima->image && BLI_listbase_is_empty(&sima->image->packedfiles)) {
+ return true;
+ }
+ return false;
+}
+
+static bool imbuf_format_writeable(const ImBuf *ibuf)
+{
+ ImageFormatData im_format;
+ ImbFormatOptions options_dummy;
+ BKE_imbuf_to_image_format(&im_format, ibuf);
+ return (BKE_image_imtype_to_ftype(im_format.imtype, &options_dummy) == ibuf->ftype);
}
static int space_image_file_exists_poll(bContext *C)
@@ -171,6 +205,9 @@ static int space_image_file_exists_poll(bContext *C)
else if (!BLI_file_is_writable(name)) {
CTX_wm_operator_poll_msg_set(C, "image path can't be written to");
}
+ else if (!imbuf_format_writeable(ibuf)) {
+ CTX_wm_operator_poll_msg_set(C, "image format is read-only");
+ }
else {
ret = true;
}
@@ -179,26 +216,29 @@ static int space_image_file_exists_poll(bContext *C)
return ret;
}
- return 0;
+ return false;
}
+#if 0 /* UNUSED */
static int space_image_poll(bContext *C)
{
SpaceImage *sima = CTX_wm_space_image(C);
- if (sima && sima->spacetype == SPACE_IMAGE && sima->image)
- return 1;
- return 0;
+ if (sima && sima->image) {
+ return true;
+ }
+ return false;
}
+#endif
int space_image_main_area_poll(bContext *C)
{
SpaceImage *sima = CTX_wm_space_image(C);
- // XXX ARegion *ar = CTX_wm_region(C);
+ /* XXX ARegion *ar = CTX_wm_region(C); */
- if (sima)
- return 1; // XXX (ar && ar->type->regionid == RGN_TYPE_WINDOW);
-
- return 0;
+ if (sima) {
+ return true; /* XXX (ar && ar->type->regionid == RGN_TYPE_WINDOW); */
+ }
+ return false;
}
/* For IMAGE_OT_curves_point_set to avoid sampling when in uv smooth mode or editmode */
@@ -364,7 +404,7 @@ void IMAGE_OT_view_pan(wmOperatorType *ot)
ot->poll = space_image_main_area_poll;
/* flags */
- ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_POINTER | OPTYPE_LOCK_BYPASS;
+ ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_CURSOR | OPTYPE_LOCK_BYPASS;
/* properties */
RNA_def_float_vector(ot->srna, "offset", 2, NULL, -FLT_MAX, FLT_MAX,
@@ -580,7 +620,7 @@ void IMAGE_OT_view_zoom(wmOperatorType *ot)
ot->poll = space_image_main_area_poll;
/* flags */
- ot->flag = OPTYPE_BLOCKING | OPTYPE_LOCK_BYPASS;
+ ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_CURSOR | OPTYPE_LOCK_BYPASS;
/* properties */
prop = RNA_def_float(ot->srna, "factor", 0.0f, -FLT_MAX, FLT_MAX, "Factor",
@@ -706,6 +746,9 @@ void IMAGE_OT_view_all(wmOperatorType *ot)
ot->exec = image_view_all_exec;
ot->poll = space_image_main_area_poll;
+ /* flags */
+ ot->flag = OPTYPE_LOCK_BYPASS;
+
/* properties */
prop = RNA_def_boolean(ot->srna, "fit_view", 0, "Fit View", "Fit frame to the viewport");
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
@@ -737,8 +780,15 @@ static int image_view_selected_exec(bContext *C, wmOperator *UNUSED(op))
height = height * aspy;
/* get bounds */
- if (!ED_uvedit_minmax(scene, ima, obedit, min, max))
- return OPERATOR_CANCELLED;
+ if (ED_space_image_show_uvedit(sima, obedit)) {
+ if (!ED_uvedit_minmax(scene, ima, obedit, min, max))
+ return OPERATOR_CANCELLED;
+ }
+ else if (ED_space_image_check_show_maskedit(scene, sima)) {
+ if (!ED_mask_selected_minmax(C, min, max)) {
+ return OPERATOR_CANCELLED;
+ }
+ }
/* adjust offset and zoom */
sima->xof = (int)(((min[0] + max[0]) * 0.5f - 0.5f) * width);
@@ -758,7 +808,7 @@ static int image_view_selected_exec(bContext *C, wmOperator *UNUSED(op))
static int image_view_selected_poll(bContext *C)
{
- return (space_image_main_area_poll(C) && ED_operator_uvedit(C));
+ return (space_image_main_area_poll(C) && (ED_operator_uvedit(C) || ED_operator_mask(C)));
}
void IMAGE_OT_view_selected(wmOperatorType *ot)
@@ -931,6 +981,7 @@ static void image_filesel(bContext *C, wmOperator *op, const char *path)
typedef struct ImageOpenData {
PropertyPointerRNA pprop;
ImageUser *iuser;
+ ImageFormatData im_format;
} ImageOpenData;
typedef struct ImageFrame {
@@ -941,10 +992,9 @@ typedef struct ImageFrame {
static void image_open_init(bContext *C, wmOperator *op)
{
ImageOpenData *iod;
-
op->customdata = iod = MEM_callocN(sizeof(ImageOpenData), __func__);
iod->iuser = CTX_data_pointer_get_type(C, "image_user", &RNA_ImageUser).data;
- uiIDContextProperty(C, &iod->pprop.ptr, &iod->pprop.prop);
+ UI_context_active_but_prop_get_templateID(C, &iod->pprop.ptr, &iod->pprop.prop);
}
static void image_open_cancel(bContext *UNUSED(C), wmOperator *op)
@@ -991,6 +1041,7 @@ static void image_sequence_get_frames(PointerRNA *ptr, ListBase *frames, char *p
}
else {
/* different file base name found, is ignored */
+ MEM_freeN(filename);
MEM_freeN(frame);
break;
}
@@ -1021,7 +1072,7 @@ static int image_sequence_get_len(ListBase *frames, int *ofs)
{
ImageFrame *frame;
- BLI_sortlist(frames, image_cmp_frame);
+ BLI_listbase_sort(frames, image_cmp_frame);
frame = frames->first;
if (frame) {
@@ -1043,31 +1094,44 @@ static int image_open_exec(bContext *C, wmOperator *op)
Scene *scene = CTX_data_scene(C);
Object *obedit = CTX_data_edit_object(C);
ImageUser *iuser = NULL;
- ImageOpenData *iod;
+ ImageOpenData *iod = op->customdata;
PointerRNA idptr;
Image *ima = NULL;
char path[FILE_MAX];
int frame_seq_len = 0;
int frame_ofs = 1;
+ bool exists = false;
const bool is_relative_path = RNA_boolean_get(op->ptr, "relative_path");
RNA_string_get(op->ptr, "filepath", path);
- if (!IMB_isanim(path) && RNA_struct_property_is_set(op->ptr, "files") &&
- RNA_struct_property_is_set(op->ptr, "directory"))
+ if (RNA_struct_property_is_set(op->ptr, "directory") &&
+ RNA_struct_property_is_set(op->ptr, "files"))
{
- ListBase frames;
-
- BLI_listbase_clear(&frames);
- image_sequence_get_frames(op->ptr, &frames, path, sizeof(path));
- frame_seq_len = image_sequence_get_len(&frames, &frame_ofs);
- BLI_freelistN(&frames);
+ /* only to pass to imbuf */
+ char path_full[FILE_MAX];
+ BLI_strncpy(path_full, path, sizeof(path_full));
+ BLI_path_abs(path_full, G.main->name);
+
+ if (!IMB_isanim(path_full)) {
+ bool was_relative = BLI_path_is_rel(path);
+ ListBase frames;
+
+ BLI_listbase_clear(&frames);
+ image_sequence_get_frames(op->ptr, &frames, path, sizeof(path));
+ frame_seq_len = image_sequence_get_len(&frames, &frame_ofs);
+ BLI_freelistN(&frames);
+
+ if (was_relative) {
+ BLI_path_rel(path, G.main->name);
+ }
+ }
}
errno = 0;
- ima = BKE_image_load_exists(path);
+ ima = BKE_image_load_exists_ex(path, &exists);
if (!ima) {
if (op->customdata) MEM_freeN(op->customdata);
@@ -1079,10 +1143,26 @@ static int image_open_exec(bContext *C, wmOperator *op)
if (!op->customdata)
image_open_init(C, op);
+ /* handle multiview images */
+ if (RNA_boolean_get(op->ptr, "use_multiview")) {
+ ImageFormatData *imf = &iod->im_format;
+
+ ima->flag |= IMA_USE_VIEWS;
+ ima->views_format = imf->views_format;
+ *ima->stereo3d_format = imf->stereo3d_format;
+ }
+ else {
+ ima->flag &= ~IMA_USE_VIEWS;
+ ima->flag &= ~IMA_IS_STEREO;
+ ima->flag &= ~IMA_IS_MULTIVIEW;
+ BKE_image_free_views(ima);
+ }
+
/* only image path after save, never ibuf */
if (is_relative_path) {
- const char *relbase = ID_BLEND_PATH(bmain, &ima->id);
- BLI_path_rel(ima->name, relbase);
+ if (!exists) {
+ BLI_path_rel(ima->name, bmain->name);
+ }
}
/* hook into UI */
@@ -1121,10 +1201,12 @@ static int image_open_exec(bContext *C, wmOperator *op)
iuser->framenr = 1;
iuser->offset = frame_ofs - 1;
iuser->fie_ima = 2;
+ iuser->scene = scene;
+ BKE_image_init_imageuser(ima, iuser);
}
/* XXX unpackImage frees image buffers */
- ED_preview_kill_jobs(C);
+ ED_preview_kill_jobs(CTX_wm_manager(C), bmain);
BKE_image_signal(ima, iuser, IMA_SIGNAL_RELOAD);
WM_event_add_notifier(C, NC_IMAGE | NA_EDITED, ima);
@@ -1139,7 +1221,8 @@ static int image_open_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(
SpaceImage *sima = CTX_wm_space_image(C); /* XXX other space types can call */
const char *path = U.textudir;
Image *ima = NULL;
-
+ Scene *scene = CTX_data_scene(C);
+ PropertyRNA *prop;
if (sima) {
ima = sima->image;
}
@@ -1155,7 +1238,7 @@ static int image_open_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(
PropertyRNA *prop;
/* hook into UI */
- uiIDContextProperty(C, &ptr, &prop);
+ UI_context_active_but_prop_get_templateID(C, &ptr, &prop);
if (prop) {
PointerRNA oldptr;
@@ -1178,11 +1261,44 @@ static int image_open_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(
image_open_init(C, op);
+ /* show multiview save options only if scene has multiviews */
+ prop = RNA_struct_find_property(op->ptr, "show_multiview");
+ RNA_property_boolean_set(op->ptr, prop, (scene->r.scemode & R_MULTIVIEW) != 0);
+
image_filesel(C, op, path);
return OPERATOR_RUNNING_MODAL;
}
+static bool image_open_draw_check_prop(PointerRNA *UNUSED(ptr), PropertyRNA *prop)
+{
+ const char *prop_id = RNA_property_identifier(prop);
+
+ return !(STREQ(prop_id, "filepath") ||
+ STREQ(prop_id, "directory") ||
+ STREQ(prop_id, "filename")
+ );
+}
+
+static void image_open_draw(bContext *UNUSED(C), wmOperator *op)
+{
+ uiLayout *layout = op->layout;
+ ImageOpenData *iod = op->customdata;
+ ImageFormatData *imf = &iod->im_format;
+ PointerRNA imf_ptr, ptr;
+
+ /* main draw call */
+ RNA_pointer_create(NULL, op->type->srna, op->properties, &ptr);
+ uiDefAutoButsRNA(layout, &ptr, image_open_draw_check_prop, '\0');
+
+ /* image template */
+ RNA_pointer_create(NULL, &RNA_ImageFormatSettings, imf, &imf_ptr);
+
+ /* multiview template */
+ if (RNA_boolean_get(op->ptr, "show_multiview"))
+ uiTemplateImageFormatViews(layout, &imf_ptr, op->ptr);
+}
+
/* called by other space types too */
void IMAGE_OT_open(wmOperatorType *ot)
{
@@ -1195,13 +1311,14 @@ void IMAGE_OT_open(wmOperatorType *ot)
ot->exec = image_open_exec;
ot->invoke = image_open_invoke;
ot->cancel = image_open_cancel;
+ ot->ui = image_open_draw;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
/* properties */
- WM_operator_properties_filesel(ot, FOLDERFILE | IMAGEFILE | MOVIEFILE, FILE_SPECIAL, FILE_OPENFILE,
- WM_FILESEL_FILEPATH | WM_FILESEL_DIRECTORY | WM_FILESEL_FILES | WM_FILESEL_RELPATH, FILE_DEFAULTDISPLAY);
+ WM_operator_properties_filesel(ot, FILE_TYPE_FOLDER | FILE_TYPE_IMAGE | FILE_TYPE_MOVIE, FILE_SPECIAL, FILE_OPENFILE,
+ WM_FILESEL_FILEPATH | WM_FILESEL_DIRECTORY | WM_FILESEL_FILES | WM_FILESEL_RELPATH, FILE_DEFAULTDISPLAY, FILE_SORT_ALPHA);
}
/******************** Match movie length operator ********************/
@@ -1226,10 +1343,10 @@ static int image_match_len_exec(bContext *C, wmOperator *UNUSED(op))
}
- if (!ima || !iuser || !ima->anim)
+ if (!ima || !iuser || !BKE_image_has_anim(ima))
return OPERATOR_CANCELLED;
- iuser->frames = IMB_anim_get_duration(ima->anim, IMB_TC_RECORD_RUN);
+ iuser->frames = IMB_anim_get_duration(((ImageAnim *) ima->anims.first)->anim, IMB_TC_RECORD_RUN);
BKE_image_user_frame_calc(iuser, scene->r.cfra, 0);
return OPERATOR_FINISHED;
@@ -1276,9 +1393,9 @@ static int image_replace_exec(bContext *C, wmOperator *op)
sima->image->source = IMA_SRC_FILE;
/* XXX unpackImage frees image buffers */
- ED_preview_kill_jobs(C);
+ ED_preview_kill_jobs(CTX_wm_manager(C), CTX_data_main(C));
- BKE_icon_changed(BKE_icon_getid(&sima->image->id));
+ BKE_icon_changed(BKE_icon_id_ensure(&sima->image->id));
BKE_image_signal(sima->image, &sima->iuser, IMA_SIGNAL_RELOAD);
WM_event_add_notifier(C, NC_IMAGE | NA_EDITED, sima->image);
@@ -1313,14 +1430,14 @@ void IMAGE_OT_replace(wmOperatorType *ot)
/* api callbacks */
ot->exec = image_replace_exec;
ot->invoke = image_replace_invoke;
- ot->poll = space_image_poll;
+ ot->poll = image_not_packed_poll;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
/* properties */
- WM_operator_properties_filesel(ot, FOLDERFILE | IMAGEFILE | MOVIEFILE, FILE_SPECIAL, FILE_OPENFILE,
- WM_FILESEL_FILEPATH | WM_FILESEL_RELPATH, FILE_DEFAULTDISPLAY);
+ WM_operator_properties_filesel(ot, FILE_TYPE_FOLDER | FILE_TYPE_IMAGE | FILE_TYPE_MOVIE, FILE_SPECIAL, FILE_OPENFILE,
+ WM_FILESEL_FILEPATH | WM_FILESEL_RELPATH, FILE_DEFAULTDISPLAY, FILE_SORT_ALPHA);
}
/******************** save image as operator ********************/
@@ -1377,12 +1494,11 @@ static int save_image_options_init(SaveImageOptions *simopts, SpaceImage *sima,
else {
if (ima->source == IMA_SRC_GENERATED) {
simopts->im_format.imtype = R_IMF_IMTYPE_PNG;
+ simopts->im_format.compress = ibuf->foptions.quality;
}
else {
BKE_imbuf_to_image_format(&simopts->im_format, ibuf);
- simopts->im_format.quality = ibuf->ftype & 0xff;
}
- simopts->im_format.quality = ibuf->ftype & 0xff;
}
simopts->im_format.planes = ibuf->planes;
@@ -1426,6 +1542,10 @@ static int save_image_options_init(SaveImageOptions *simopts, SpaceImage *sima,
}
}
+ /* use the multiview image settings as the default */
+ simopts->im_format.stereo3d_format = *ima->stereo3d_format;
+ simopts->im_format.views_format = ima->views_format;
+
/* color management */
BKE_color_managed_display_settings_copy(&simopts->im_format.display_settings, &scene->display_settings);
BKE_color_managed_view_settings_copy(&simopts->im_format.view_settings, &scene->view_settings);
@@ -1461,30 +1581,105 @@ static void save_image_options_to_op(SaveImageOptions *simopts, wmOperator *op)
RNA_string_set(op->ptr, "filepath", simopts->filepath);
}
+static void save_image_post(wmOperator *op, ImBuf *ibuf, Image *ima, int ok, int save_copy, const char *relbase, int relative, int do_newpath, const char *filepath)
+{
+ if (ok) {
+ if (!save_copy) {
+ ColorManagedColorspaceSettings old_colorspace_settings;
+
+ if (do_newpath) {
+ BLI_strncpy(ibuf->name, filepath, sizeof(ibuf->name));
+ BLI_strncpy(ima->name, filepath, sizeof(ima->name));
+ }
+
+ ibuf->userflags &= ~IB_BITMAPDIRTY;
+
+ /* change type? */
+ if (ima->type == IMA_TYPE_R_RESULT) {
+ ima->type = IMA_TYPE_IMAGE;
+
+ /* workaround to ensure the render result buffer is no longer used
+ * by this image, otherwise can crash when a new render result is
+ * created. */
+ if (ibuf->rect && !(ibuf->mall & IB_rect))
+ imb_freerectImBuf(ibuf);
+ if (ibuf->rect_float && !(ibuf->mall & IB_rectfloat))
+ imb_freerectfloatImBuf(ibuf);
+ if (ibuf->zbuf && !(ibuf->mall & IB_zbuf))
+ IMB_freezbufImBuf(ibuf);
+ if (ibuf->zbuf_float && !(ibuf->mall & IB_zbuffloat))
+ IMB_freezbuffloatImBuf(ibuf);
+ }
+ if (ELEM(ima->source, IMA_SRC_GENERATED, IMA_SRC_VIEWER)) {
+ ima->source = IMA_SRC_FILE;
+ ima->type = IMA_TYPE_IMAGE;
+ }
+
+ /* only image path, never ibuf */
+ if (relative) {
+ BLI_path_rel(ima->name, relbase); /* only after saving */
+ }
+
+ BKE_color_managed_colorspace_settings_copy(&old_colorspace_settings,
+ &ima->colorspace_settings);
+ IMB_colormanagment_colorspace_from_ibuf_ftype(&ima->colorspace_settings, ibuf);
+ if (!BKE_color_managed_colorspace_settings_equals(&old_colorspace_settings,
+ &ima->colorspace_settings))
+ {
+ BKE_image_signal(ima, NULL, IMA_SIGNAL_COLORMANAGE);
+ }
+ }
+ }
+ else {
+ BKE_reportf(op->reports, RPT_ERROR, "Could not write image %s", filepath);
+ }
+}
+
+static void save_imbuf_post(ImBuf *ibuf, ImBuf *colormanaged_ibuf)
+{
+ if (colormanaged_ibuf != ibuf) {
+ /* This guys might be modified by image buffer write functions,
+ * need to copy them back from color managed image buffer to an
+ * original one, so file type of image is being properly updated.
+ */
+ ibuf->ftype = colormanaged_ibuf->ftype;
+ ibuf->foptions = colormanaged_ibuf->foptions;
+ ibuf->planes = colormanaged_ibuf->planes;
+
+ IMB_freeImBuf(colormanaged_ibuf);
+ }
+}
+
/**
* \return success.
* \note ``ima->name`` and ``ibuf->name`` should end up the same.
+ * \note for multiview the first ``ibuf`` is important to get the settings.
*/
static bool save_image_doit(bContext *C, SpaceImage *sima, wmOperator *op, SaveImageOptions *simopts, bool do_newpath)
{
Image *ima = ED_space_image(sima);
void *lock;
ImBuf *ibuf = ED_space_image_acquire_buffer(sima, &lock);
+ Scene *scene;
+ RenderResult *rr = NULL;
bool ok = false;
+ WM_cursor_wait(1);
+
if (ibuf) {
- ImBuf *colormanaged_ibuf;
+ ImBuf *colormanaged_ibuf = NULL;
const char *relbase = ID_BLEND_PATH(CTX_data_main(C), &ima->id);
const bool relative = (RNA_struct_find_property(op->ptr, "relative_path") && RNA_boolean_get(op->ptr, "relative_path"));
const bool save_copy = (RNA_struct_find_property(op->ptr, "copy") && RNA_boolean_get(op->ptr, "copy"));
const bool save_as_render = (RNA_struct_find_property(op->ptr, "save_as_render") && RNA_boolean_get(op->ptr, "save_as_render"));
ImageFormatData *imf = &simopts->im_format;
+ const bool is_multilayer = imf->imtype == R_IMF_IMTYPE_MULTILAYER;
+ bool is_mono;
+
/* old global to ensure a 2nd save goes to same dir */
BLI_strncpy(G.ima, simopts->filepath, sizeof(G.ima));
- WM_cursor_wait(1);
-
if (ima->type == IMA_TYPE_R_RESULT) {
/* enforce user setting for RGB or RGBA, but skip BW */
if (simopts->im_format.planes == R_IMF_PLANES_RGBA) {
@@ -1505,83 +1700,194 @@ static bool save_image_doit(bContext *C, SpaceImage *sima, wmOperator *op, SaveI
}
}
- colormanaged_ibuf = IMB_colormanagement_imbuf_for_write(ibuf, save_as_render, true, &imf->view_settings, &imf->display_settings, imf);
+ /* we need renderresult for exr and rendered multiview */
+ scene = CTX_data_scene(C);
+ rr = BKE_image_acquire_renderresult(scene, ima);
+ is_mono = rr ? BLI_listbase_count_ex(&rr->views, 2) < 2 : (ima->flag & IMA_IS_MULTIVIEW) == 0;
- if (simopts->im_format.imtype == R_IMF_IMTYPE_MULTILAYER) {
- Scene *scene = CTX_data_scene(C);
- RenderResult *rr = BKE_image_acquire_renderresult(scene, ima);
- if (rr) {
- ok = RE_WriteRenderResult(op->reports, rr, simopts->filepath, simopts->im_format.exr_codec);
- }
- else {
+ /* error handling */
+ if (!rr) {
+ if (imf->imtype == R_IMF_IMTYPE_MULTILAYER) {
BKE_report(op->reports, RPT_ERROR, "Did not write, no Multilayer Image");
+ goto cleanup;
}
- BKE_image_release_renderresult(scene, ima);
}
else {
- ok = BKE_imbuf_write_as(colormanaged_ibuf, simopts->filepath, &simopts->im_format, save_copy);
- }
-
- if (ok) {
- if (!save_copy) {
- if (do_newpath) {
- BLI_strncpy(ibuf->name, simopts->filepath, sizeof(ibuf->name));
- BLI_strncpy(ima->name, simopts->filepath, sizeof(ima->name));
+ if (imf->views_format == R_IMF_VIEWS_STEREO_3D) {
+ if ((ima->flag & IMA_IS_STEREO) == 0) {
+ BKE_reportf(op->reports, RPT_ERROR, "Did not write, the image doesn't have a \"%s\" and \"%s\" views",
+ STEREO_LEFT_NAME, STEREO_RIGHT_NAME);
+ goto cleanup;
}
- ibuf->userflags &= ~IB_BITMAPDIRTY;
-
- /* change type? */
- if (ima->type == IMA_TYPE_R_RESULT) {
- ima->type = IMA_TYPE_IMAGE;
-
- /* workaround to ensure the render result buffer is no longer used
- * by this image, otherwise can crash when a new render result is
- * created. */
- if (ibuf->rect && !(ibuf->mall & IB_rect))
- imb_freerectImBuf(ibuf);
- if (ibuf->rect_float && !(ibuf->mall & IB_rectfloat))
- imb_freerectfloatImBuf(ibuf);
- if (ibuf->zbuf && !(ibuf->mall & IB_zbuf))
- IMB_freezbufImBuf(ibuf);
- if (ibuf->zbuf_float && !(ibuf->mall & IB_zbuffloat))
- IMB_freezbuffloatImBuf(ibuf);
- }
- if (ELEM(ima->source, IMA_SRC_GENERATED, IMA_SRC_VIEWER)) {
- ima->source = IMA_SRC_FILE;
- ima->type = IMA_TYPE_IMAGE;
+ /* it shouldn't ever happen*/
+ if ((BLI_findstring(&rr->views, STEREO_LEFT_NAME, offsetof(RenderView, name)) == NULL) ||
+ (BLI_findstring(&rr->views, STEREO_RIGHT_NAME, offsetof(RenderView, name)) == NULL))
+ {
+ BKE_reportf(op->reports, RPT_ERROR, "Did not write, the image doesn't have a \"%s\" and \"%s\" views",
+ STEREO_LEFT_NAME, STEREO_RIGHT_NAME);
+ goto cleanup;
}
+ }
+ BKE_imbuf_stamp_info(rr, ibuf);
+ }
- /* only image path, never ibuf */
- if (relative) {
- BLI_path_rel(ima->name, relbase); /* only after saving */
+ /* fancy multiview OpenEXR */
+ if ((imf->imtype == R_IMF_IMTYPE_MULTILAYER) && (imf->views_format == R_IMF_VIEWS_MULTIVIEW)) {
+ ok = RE_WriteRenderResult(op->reports, rr, simopts->filepath, imf, true, NULL);
+ save_image_post(op, ibuf, ima, ok, true, relbase, relative, do_newpath, simopts->filepath);
+ ED_space_image_release_buffer(sima, ibuf, lock);
+ }
+ else if ((imf->imtype == R_IMF_IMTYPE_OPENEXR) && (imf->views_format == R_IMF_VIEWS_MULTIVIEW)) {
+ /* treat special Openexr case separetely (this is the singlelayer multiview OpenEXR */
+ BKE_imbuf_write_prepare(ibuf, imf);
+ ok = BKE_image_save_openexr_multiview(ima, ibuf, simopts->filepath, (IB_rect | IB_zbuf | IB_zbuffloat | IB_multiview));
+ ED_space_image_release_buffer(sima, ibuf, lock);
+ }
+ /* regular mono pipeline */
+ else if (is_mono) {
+ if (is_multilayer) {
+ ok = RE_WriteRenderResult(op->reports, rr, simopts->filepath, imf, false, NULL);
+ }
+ else {
+ colormanaged_ibuf = IMB_colormanagement_imbuf_for_write(ibuf, save_as_render, true, &imf->view_settings, &imf->display_settings, imf);
+ IMB_metadata_copy(colormanaged_ibuf, ibuf);
+ ok = BKE_imbuf_write_as(colormanaged_ibuf, simopts->filepath, imf, save_copy);
+ save_imbuf_post(ibuf, colormanaged_ibuf);
+ }
+ save_image_post(op, ibuf, ima, ok, (is_multilayer ? true : save_copy), relbase, relative, do_newpath, simopts->filepath);
+ ED_space_image_release_buffer(sima, ibuf, lock);
+ }
+ /* individual multiview images */
+ else if (imf->views_format == R_IMF_VIEWS_INDIVIDUAL) {
+ size_t i;
+ unsigned char planes = ibuf->planes;
+ const size_t totviews = (rr ? BLI_listbase_count(&rr->views) : BLI_listbase_count(&ima->views));
+
+ if (!is_multilayer) {
+ ED_space_image_release_buffer(sima, ibuf, lock);
+ }
+
+ for (i = 0; i < totviews; i++) {
+ char filepath[FILE_MAX];
+ bool ok_view = false;
+ const char *view = rr ? ((RenderView *) BLI_findlink(&rr->views, i))->name :
+ ((ImageView *) BLI_findlink(&ima->views, i))->name;
+
+ if (is_multilayer) {
+ BKE_scene_multiview_view_filepath_get(&scene->r, simopts->filepath, view, filepath);
+ ok_view = RE_WriteRenderResult(op->reports, rr, filepath, imf, false, view);
+ save_image_post(op, ibuf, ima, ok_view, true, relbase, relative, do_newpath, filepath);
+ }
+ else {
+ /* copy iuser to get the correct ibuf for this view */
+ ImageUser iuser = sima->iuser;
+ iuser.view = i;
+ iuser.flag &= ~IMA_SHOW_STEREO;
+
+ if (rr)
+ BKE_image_multilayer_index(rr, &iuser);
+ else
+ BKE_image_multiview_index(ima, &iuser);
+
+ ibuf = BKE_image_acquire_ibuf(sima->image, &iuser, &lock);
+ ibuf->planes = planes;
+
+ BKE_scene_multiview_view_filepath_get(&scene->r, simopts->filepath, view, filepath);
+
+ colormanaged_ibuf = IMB_colormanagement_imbuf_for_write(ibuf, save_as_render, true, &imf->view_settings, &imf->display_settings, imf);
+ ok_view = BKE_imbuf_write_as(colormanaged_ibuf, filepath, &simopts->im_format, save_copy);
+ save_imbuf_post(ibuf, colormanaged_ibuf);
+ save_image_post(op, ibuf, ima, ok_view, true, relbase, relative, do_newpath, filepath);
+ BKE_image_release_ibuf(sima->image, ibuf, lock);
}
+ ok &= ok_view;
+ }
- IMB_colormanagment_colorspace_from_ibuf_ftype(&ima->colorspace_settings, ibuf);
+ if (is_multilayer) {
+ ED_space_image_release_buffer(sima, ibuf, lock);
}
}
- else {
- BKE_reportf(op->reports, RPT_ERROR, "Could not write image %s", simopts->filepath);
- }
+ /* stereo (multiview) images */
+ else if (simopts->im_format.views_format == R_IMF_VIEWS_STEREO_3D) {
+ if (imf->imtype == R_IMF_IMTYPE_MULTILAYER) {
+ ok = RE_WriteRenderResult(op->reports, rr, simopts->filepath, imf, false, NULL);
+ save_image_post(op, ibuf, ima, ok, true, relbase, relative, do_newpath, simopts->filepath);
+ ED_space_image_release_buffer(sima, ibuf, lock);
+ }
+ else {
+ ImBuf *ibuf_stereo[2] = {NULL};
+ unsigned char planes = ibuf->planes;
+ const char *names[2] = {STEREO_LEFT_NAME, STEREO_RIGHT_NAME};
+ int i;
- WM_event_add_notifier(C, NC_IMAGE | NA_EDITED, sima->image);
+ /* we need to get the specific per-view buffers */
+ ED_space_image_release_buffer(sima, ibuf, lock);
+
+ for (i = 0; i < 2; i ++) {
+ ImageUser iuser = sima->iuser;
+ iuser.flag &= ~IMA_SHOW_STEREO;
+
+ if (rr) {
+ int id = BLI_findstringindex(&rr->views, names[i], offsetof(RenderView, name));
+ iuser.view = id;
+ BKE_image_multilayer_index(rr, &iuser);
+ }
+ else {
+ iuser.view = i;
+ BKE_image_multiview_index(ima, &iuser);
+ }
+
+ ibuf = BKE_image_acquire_ibuf(sima->image, &iuser, &lock);
+
+ if (ibuf == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "Did not write, unexpected error when saving stereo image");
+ goto cleanup;
+ }
+
+ ibuf->planes = planes;
+
+ /* color manage the ImBuf leaving it ready for saving */
+ colormanaged_ibuf = IMB_colormanagement_imbuf_for_write(ibuf, save_as_render, true,
+ &imf->view_settings, &imf->display_settings, imf);
- WM_cursor_wait(0);
+ BKE_imbuf_write_prepare(colormanaged_ibuf, imf);
+ IMB_prepare_write_ImBuf(IMB_isfloat(colormanaged_ibuf), colormanaged_ibuf);
- if (colormanaged_ibuf != ibuf) {
- /* This guys might be modified by image buffer write functions,
- * need to copy them back from color managed image buffer to an
- * original one, so file type of image is being properly updated.
- */
- ibuf->ftype = colormanaged_ibuf->ftype;
- ibuf->planes = colormanaged_ibuf->planes;
+ /* duplicate buffer to prevent locker issue when using render result */
+ ibuf_stereo[i] = IMB_dupImBuf(colormanaged_ibuf);
- IMB_freeImBuf(colormanaged_ibuf);
+ save_imbuf_post(ibuf, colormanaged_ibuf);
+ BKE_image_release_ibuf(sima->image, ibuf, lock);
+ }
+
+ ibuf = IMB_stereo3d_ImBuf(imf, ibuf_stereo[0], ibuf_stereo[1]);
+
+ /* save via traditional path */
+ ok = BKE_imbuf_write_as(ibuf, simopts->filepath, imf, save_copy);
+
+ IMB_freeImBuf(ibuf);
+
+ for (i = 0; i < 2; i ++) {
+ IMB_freeImBuf(ibuf_stereo[i]);
+ }
+ }
}
+
+ WM_event_add_notifier(C, NC_IMAGE | NA_EDITED, sima->image);
+
+ }
+ else {
+cleanup:
+ ED_space_image_release_buffer(sima, ibuf, lock);
}
- ED_space_image_release_buffer(sima, ibuf, lock);
+ if (rr) {
+ BKE_image_release_renderresult(scene, ima);
+ }
+
+ WM_cursor_wait(0);
return ok;
}
@@ -1629,6 +1935,7 @@ static int image_save_as_invoke(bContext *C, wmOperator *op, const wmEvent *UNUS
Image *ima = ED_space_image(sima);
Scene *scene = CTX_data_scene(C);
SaveImageOptions simopts;
+ PropertyRNA *prop;
const bool save_as_render = ((ima->source == IMA_SRC_VIEWER) || (ima->flag & IMA_VIEW_AS_RENDER));
if (RNA_struct_property_is_set(op->ptr, "filepath"))
@@ -1650,6 +1957,12 @@ static int image_save_as_invoke(bContext *C, wmOperator *op, const wmEvent *UNUS
op->customdata = MEM_mallocN(sizeof(simopts.im_format), __func__);
memcpy(op->customdata, &simopts.im_format, sizeof(simopts.im_format));
+ /* show multiview save options only if image has multiviews */
+ prop = RNA_struct_find_property(op->ptr, "show_multiview");
+ RNA_property_boolean_set(op->ptr, prop, (ima->flag & IMA_IS_MULTIVIEW) != 0);
+ prop = RNA_struct_find_property(op->ptr, "use_multiview");
+ RNA_property_boolean_set(op->ptr, prop, (ima->flag & IMA_IS_MULTIVIEW) != 0);
+
image_filesel(C, op, simopts.filepath);
return OPERATOR_RUNNING_MODAL;
@@ -1676,15 +1989,20 @@ static void image_save_as_draw(bContext *UNUSED(C), wmOperator *op)
{
uiLayout *layout = op->layout;
ImageFormatData *imf = op->customdata;
- PointerRNA ptr;
+ PointerRNA imf_ptr, ptr;
+ const bool is_multiview = RNA_boolean_get(op->ptr, "show_multiview");
/* image template */
- RNA_pointer_create(NULL, &RNA_ImageFormatSettings, imf, &ptr);
- uiTemplateImageSettings(layout, &ptr, false);
+ RNA_pointer_create(NULL, &RNA_ImageFormatSettings, imf, &imf_ptr);
+ uiTemplateImageSettings(layout, &imf_ptr, false);
/* main draw call */
RNA_pointer_create(NULL, op->type->srna, op->properties, &ptr);
uiDefAutoButsRNA(layout, &ptr, image_save_as_draw_check_prop, '\0');
+
+ /* multiview template */
+ if (is_multiview)
+ uiTemplateImageFormatViews(layout, &imf_ptr, op->ptr);
}
static int image_save_as_poll(bContext *C)
@@ -1707,8 +2025,6 @@ static int image_save_as_poll(bContext *C)
void IMAGE_OT_save_as(wmOperatorType *ot)
{
-// PropertyRNA *prop;
-
/* identifiers */
ot->name = "Save As Image";
ot->idname = "IMAGE_OT_save_as";
@@ -1729,8 +2045,8 @@ void IMAGE_OT_save_as(wmOperatorType *ot)
RNA_def_boolean(ot->srna, "save_as_render", 0, "Save As Render", "Apply render part of display transform when saving byte image");
RNA_def_boolean(ot->srna, "copy", 0, "Copy", "Create a new image file without modifying the current image in blender");
- WM_operator_properties_filesel(ot, FOLDERFILE | IMAGEFILE | MOVIEFILE, FILE_SPECIAL, FILE_SAVE,
- WM_FILESEL_FILEPATH | WM_FILESEL_RELPATH, FILE_DEFAULTDISPLAY);
+ WM_operator_properties_filesel(ot, FILE_TYPE_FOLDER | FILE_TYPE_IMAGE | FILE_TYPE_MOVIE, FILE_SPECIAL, FILE_SAVE,
+ WM_FILESEL_FILEPATH | WM_FILESEL_RELPATH, FILE_DEFAULTDISPLAY, FILE_SORT_ALPHA);
}
/******************** save image operator ********************/
@@ -1877,7 +2193,7 @@ static int image_reload_exec(bContext *C, wmOperator *UNUSED(op))
return OPERATOR_CANCELLED;
/* XXX unpackImage frees image buffers */
- ED_preview_kill_jobs(C);
+ ED_preview_kill_jobs(CTX_wm_manager(C), CTX_data_main(C));
// XXX other users?
BKE_image_signal(ima, (sima) ? &sima->iuser : NULL, IMA_SIGNAL_RELOAD);
@@ -1905,6 +2221,12 @@ void IMAGE_OT_reload(wmOperatorType *ot)
/********************** new image operator *********************/
#define IMA_DEF_NAME N_("Untitled")
+enum {
+ GEN_CONTEXT_NONE = 0,
+ GEN_CONTEXT_PAINT_CANVAS = 1,
+ GEN_CONTEXT_PAINT_STENCIL = 2
+};
+
static int image_new_exec(bContext *C, wmOperator *op)
{
SpaceImage *sima;
@@ -1918,6 +2240,8 @@ static int image_new_exec(bContext *C, wmOperator *op)
char *name = _name;
float color[4];
int width, height, floatbuf, gen_type, alpha;
+ int gen_context;
+ int stereo3d;
/* retrieve state */
sima = CTX_wm_space_image(C);
@@ -1937,17 +2261,19 @@ static int image_new_exec(bContext *C, wmOperator *op)
gen_type = RNA_enum_get(op->ptr, "generated_type");
RNA_float_get_array(op->ptr, "color", color);
alpha = RNA_boolean_get(op->ptr, "alpha");
+ gen_context = RNA_enum_get(op->ptr, "gen_context");
+ stereo3d = RNA_boolean_get(op->ptr, "use_stereo_3d");
if (!alpha)
color[3] = 1.0f;
- ima = BKE_image_add_generated(bmain, width, height, name, alpha ? 32 : 24, floatbuf, gen_type, color);
+ ima = BKE_image_add_generated(bmain, width, height, name, alpha ? 32 : 24, floatbuf, gen_type, color, stereo3d);
if (!ima)
return OPERATOR_CANCELLED;
/* hook into UI */
- uiIDContextProperty(C, &ptr, &prop);
+ UI_context_active_but_prop_get_templateID(C, &ptr, &prop);
if (prop) {
/* when creating new ID blocks, use is already 1, but RNA
@@ -1961,6 +2287,40 @@ static int image_new_exec(bContext *C, wmOperator *op)
else if (sima) {
ED_space_image_set(sima, scene, obedit, ima);
}
+ else if (gen_context == GEN_CONTEXT_PAINT_CANVAS) {
+ bScreen *sc;
+ Object *ob = CTX_data_active_object(C);
+
+ GPU_drawobject_free(ob->derivedFinal);
+ if (scene->toolsettings->imapaint.canvas)
+ id_us_min(&scene->toolsettings->imapaint.canvas->id);
+ scene->toolsettings->imapaint.canvas = ima;
+
+ for (sc = bmain->screen.first; sc; sc = sc->id.next) {
+ ScrArea *sa;
+ for (sa = sc->areabase.first; sa; sa = sa->next) {
+ SpaceLink *sl;
+ for (sl = sa->spacedata.first; sl; sl = sl->next) {
+ if (sl->spacetype == SPACE_IMAGE) {
+ SpaceImage *sima = (SpaceImage *)sl;
+
+ if (!sima->pin)
+ ED_space_image_set(sima, scene, scene->obedit, ima);
+ }
+ }
+ }
+ }
+ BKE_paint_proj_mesh_data_check(scene, ob, NULL, NULL, NULL, NULL);
+ WM_event_add_notifier(C, NC_SCENE | ND_TOOLSETTINGS, NULL);
+ }
+ else if (gen_context == GEN_CONTEXT_PAINT_STENCIL) {
+ Object *ob = CTX_data_active_object(C);
+ if (scene->toolsettings->imapaint.stencil)
+ id_us_min(&scene->toolsettings->imapaint.stencil->id);
+ scene->toolsettings->imapaint.stencil = ima;
+ BKE_paint_proj_mesh_data_check(scene, ob, NULL, NULL, NULL, NULL);
+ WM_event_add_notifier(C, NC_SCENE | ND_TOOLSETTINGS, NULL);
+ }
else {
Tex *tex = CTX_data_pointer_get_type(C, "texture", &RNA_Texture).data;
if (tex && tex->type == TEX_IMAGE) {
@@ -1979,7 +2339,7 @@ static int image_new_exec(bContext *C, wmOperator *op)
}
/* XXX, Ton is not a fan of OK buttons but using this function to avoid undo/redo bug while in mesh-editmode, - campbell */
-/* XXX Note: the WM_operator_props_dialog_popup() doesn't work for uiIDContextProperty(), image is not being that way */
+/* XXX Note: the WM_operator_props_dialog_popup() doesn't work for UI_context_active_but_prop_get_templateID(), image is not being that way */
static int image_new_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
/* Better for user feedback. */
@@ -1987,10 +2347,64 @@ static int image_new_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(e
return WM_operator_props_dialog_popup(C, op, 15 * UI_UNIT_X, 5 * UI_UNIT_Y);
}
+static void image_new_draw(bContext *UNUSED(C), wmOperator *op)
+{
+ uiLayout *split, *col[2];
+ uiLayout *layout = op->layout;
+ PointerRNA ptr;
+#if 0
+ Scene *scene = CTX_data_scene(C);
+ const bool is_multiview = (scene->r.scemode & R_MULTIVIEW) != 0;
+#endif
+
+ RNA_pointer_create(NULL, op->type->srna, op->properties, &ptr);
+
+ /* copy of WM_operator_props_dialog_popup() layout */
+
+ split = uiLayoutSplit(layout, 0.5f, false);
+ col[0] = uiLayoutColumn(split, false);
+ col[1] = uiLayoutColumn(split, false);
+
+ uiItemL(col[0], IFACE_("Name"), ICON_NONE);
+ uiItemR(col[1], &ptr, "name", 0, "", ICON_NONE);
+
+ uiItemL(col[0], IFACE_("Width"), ICON_NONE);
+ uiItemR(col[1], &ptr, "width", 0, "", ICON_NONE);
+
+ uiItemL(col[0], IFACE_("Height"), ICON_NONE);
+ uiItemR(col[1], &ptr, "height", 0, "", ICON_NONE);
+
+ uiItemL(col[0], IFACE_("Color"), ICON_NONE);
+ uiItemR(col[1], &ptr, "color", 0, "", ICON_NONE);
+
+ uiItemL(col[0], "", ICON_NONE);
+ uiItemR(col[1], &ptr, "alpha", 0, NULL, ICON_NONE);
+
+ uiItemL(col[0], IFACE_("Generated Type"), ICON_NONE);
+ uiItemR(col[1], &ptr, "generated_type", 0, "", ICON_NONE);
+
+ uiItemL(col[0], "", ICON_NONE);
+ uiItemR(col[1], &ptr, "float", 0, NULL, ICON_NONE);
+
+#if 0
+ if (is_multiview) {
+ uiItemL(col[0], "", ICON_NONE);
+ uiItemR(col[1], &ptr, "use_stereo_3d", 0, NULL, ICON_NONE);
+ }
+#endif
+}
+
void IMAGE_OT_new(wmOperatorType *ot)
{
PropertyRNA *prop;
static float default_color[4] = {0.0f, 0.0f, 0.0f, 1.0f};
+
+ static EnumPropertyItem gen_context_items[] = {
+ {GEN_CONTEXT_NONE, "NONE", 0, "None", ""},
+ {GEN_CONTEXT_PAINT_CANVAS, "PAINT_CANVAS", 0, "Paint Canvas", ""},
+ {GEN_CONTEXT_PAINT_STENCIL, "PAINT_STENCIL", 0, "Paint Stencil", ""},
+ {0, NULL, 0, NULL, NULL}
+ };
/* identifiers */
ot->name = "New Image";
@@ -2000,6 +2414,7 @@ void IMAGE_OT_new(wmOperatorType *ot)
/* api callbacks */
ot->exec = image_new_exec;
ot->invoke = image_new_invoke;
+ ot->ui = image_new_draw;
/* flags */
ot->flag = OPTYPE_UNDO;
@@ -2017,9 +2432,10 @@ void IMAGE_OT_new(wmOperatorType *ot)
RNA_def_enum(ot->srna, "generated_type", image_generated_type_items, IMA_GENTYPE_BLANK,
"Generated Type", "Fill the image with a grid for UV map testing");
RNA_def_boolean(ot->srna, "float", 0, "32 bit Float", "Create image with 32 bit floating point bit depth");
- prop = RNA_def_boolean(ot->srna, "texstencil", 0, "Stencil", "Set Image as stencil");
+ prop = RNA_def_enum(ot->srna, "gen_context", gen_context_items, 0, "Gen Context", "Generation context");
RNA_def_property_flag(prop, PROP_HIDDEN);
-
+ prop = RNA_def_boolean(ot->srna, "use_stereo_3d", 0, "Stereo 3D", "Create an image with left and right views");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE | PROP_HIDDEN);
}
#undef IMA_DEF_NAME
@@ -2047,7 +2463,7 @@ static int image_invert_exec(bContext *C, wmOperator *op)
const bool b = RNA_boolean_get(op->ptr, "invert_b");
const bool a = RNA_boolean_get(op->ptr, "invert_a");
- int i;
+ size_t i;
if (ibuf == NULL) /* TODO: this should actually never happen, but does for render-results -> cleanup */
return OPERATOR_CANCELLED;
@@ -2058,13 +2474,13 @@ static int image_invert_exec(bContext *C, wmOperator *op)
/* 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);
+ ED_imapaint_dirty_region(ima, ibuf, 0, 0, ibuf->x, ibuf->y, false);
}
/* TODO: make this into an IMB_invert_channels(ibuf,r,g,b,a) method!? */
if (ibuf->rect_float) {
float *fp = (float *) ibuf->rect_float;
- for (i = ibuf->x * ibuf->y; i > 0; i--, fp += 4) {
+ for (i = ((size_t)ibuf->x) * ibuf->y; i > 0; i--, fp += 4) {
if (r) fp[0] = 1.0f - fp[0];
if (g) fp[1] = 1.0f - fp[1];
if (b) fp[2] = 1.0f - fp[2];
@@ -2078,7 +2494,7 @@ static int image_invert_exec(bContext *C, wmOperator *op)
else if (ibuf->rect) {
char *cp = (char *) ibuf->rect;
- for (i = ibuf->x * ibuf->y; i > 0; i--, cp += 4) {
+ for (i = ((size_t)ibuf->x) * ibuf->y; i > 0; i--, cp += 4) {
if (r) cp[0] = 255 - cp[0];
if (g) cp[1] = 255 - cp[1];
if (b) cp[2] = 255 - cp[2];
@@ -2144,7 +2560,7 @@ static bool image_pack_test(bContext *C, wmOperator *op)
if (!ima)
return 0;
- if (!as_png && ima->packedfile)
+ if (!as_png && BKE_image_has_packedfile(ima))
return 0;
if (ima->source == IMA_SRC_SEQUENCE || ima->source == IMA_SRC_MOVIE) {
@@ -2173,7 +2589,7 @@ static int image_pack_exec(bContext *C, wmOperator *op)
if (as_png)
BKE_image_memorypack(ima);
else
- ima->packedfile = newPackedFile(op->reports, ima->name, ID_BLEND_PATH(bmain, &ima->id));
+ BKE_image_packfiles(op->reports, ima, ID_BLEND_PATH(bmain, &ima->id));
WM_event_add_notifier(C, NC_IMAGE | NA_EDITED, ima);
@@ -2196,15 +2612,15 @@ static int image_pack_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(
ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL);
if (!as_png && (ibuf && (ibuf->userflags & IB_BITMAPDIRTY))) {
- pup = uiPupMenuBegin(C, IFACE_("OK"), ICON_QUESTION);
- layout = uiPupMenuLayout(pup);
+ pup = UI_popup_menu_begin(C, IFACE_("OK"), ICON_QUESTION);
+ layout = UI_popup_menu_layout(pup);
uiItemBooleanO(layout, IFACE_("Can't pack edited image from disk, pack as internal PNG?"), ICON_NONE,
op->idname, "as_png", 1);
- uiPupMenuEnd(C, pup);
+ UI_popup_menu_end(C, pup);
BKE_image_release_ibuf(ima, ibuf, NULL);
- return OPERATOR_CANCELLED;
+ return OPERATOR_INTERFACE;
}
BKE_image_release_ibuf(ima, ibuf, NULL);
@@ -2245,7 +2661,7 @@ static int image_unpack_exec(bContext *C, wmOperator *op)
if (!ima) ima = CTX_data_edit_image(C);
}
- if (!ima || !ima->packedfile)
+ if (!ima || !BKE_image_has_packedfile(ima))
return OPERATOR_CANCELLED;
if (ima->source == IMA_SRC_SEQUENCE || ima->source == IMA_SRC_MOVIE) {
@@ -2257,7 +2673,7 @@ static int image_unpack_exec(bContext *C, wmOperator *op)
BKE_report(op->reports, RPT_WARNING, "AutoPack is enabled, so image will be packed again on file save");
/* XXX unpackImage frees image buffers */
- ED_preview_kill_jobs(C);
+ ED_preview_kill_jobs(CTX_wm_manager(C), CTX_data_main(C));
unpackImage(op->reports, ima, method);
@@ -2273,7 +2689,7 @@ static int image_unpack_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSE
if (RNA_struct_property_is_set(op->ptr, "id"))
return image_unpack_exec(C, op);
- if (!ima || !ima->packedfile)
+ if (!ima || !BKE_image_has_packedfile(ima))
return OPERATOR_CANCELLED;
if (ima->source == IMA_SRC_SEQUENCE || ima->source == IMA_SRC_MOVIE) {
@@ -2284,7 +2700,7 @@ static int image_unpack_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSE
if (G.fileflags & G_AUTOPACK)
BKE_report(op->reports, RPT_WARNING, "AutoPack is enabled, so image will be packed again on file save");
- unpack_menu(C, "IMAGE_OT_unpack", ima->id.name + 2, ima->name, "textures", ima->packedfile);
+ unpack_menu(C, "IMAGE_OT_unpack", ima->id.name + 2, ima->name, "textures", BKE_image_has_packedfile(ima) ? ((ImagePackedFile *)ima->packedfiles.first)->packedfile : NULL);
return OPERATOR_FINISHED;
}
@@ -2528,8 +2944,9 @@ static int image_sample_invoke(bContext *C, wmOperator *op, const wmEvent *event
ImageSampleInfo *info;
if (ar->regiontype == RGN_TYPE_WINDOW) {
- if (event->mval[1] <= 16)
+ if (event->mval[1] <= 16 && ED_space_image_show_cache(sima)) {
return OPERATOR_PASS_THROUGH;
+ }
}
if (!ED_space_image_has_buffer(sima))
@@ -2552,8 +2969,11 @@ static int image_sample_modal(bContext *C, wmOperator *op, const wmEvent *event)
switch (event->type) {
case LEFTMOUSE:
case RIGHTMOUSE: // XXX hardcoded
- image_sample_exit(C, op);
- return OPERATOR_CANCELLED;
+ if (event->val == KM_RELEASE) {
+ image_sample_exit(C, op);
+ return OPERATOR_CANCELLED;
+ }
+ break;
case MOUSEMOVE:
image_sample_apply(C, op, event);
break;
@@ -2925,7 +3345,7 @@ static void change_frame_apply(bContext *C, wmOperator *op)
SUBFRA = 0.0f;
/* do updates */
- sound_seek_scene(CTX_data_main(C), scene);
+ BKE_sound_seek_scene(CTX_data_main(C), scene);
WM_event_add_notifier(C, NC_SCENE | ND_FRAME, scene);
}
@@ -2963,8 +3383,10 @@ static int change_frame_invoke(bContext *C, wmOperator *op, const wmEvent *event
ARegion *ar = CTX_wm_region(C);
if (ar->regiontype == RGN_TYPE_WINDOW) {
- if (event->mval[1] > 16)
+ SpaceImage *sima = CTX_wm_space_image(C);
+ if (event->mval[1] > 16 || !ED_space_image_show_cache(sima)) {
return OPERATOR_PASS_THROUGH;
+ }
}
RNA_int_set(op->ptr, "frame", frame_from_event(C, event));
@@ -3049,3 +3471,101 @@ void IMAGE_OT_read_renderlayers(wmOperatorType *ot)
/* flags */
ot->flag = 0;
}
+
+/* ********************* Render border operator ****************** */
+
+static int render_border_exec(bContext *C, wmOperator *op)
+{
+ ARegion *ar = CTX_wm_region(C);
+ Scene *scene = CTX_data_scene(C);
+ Render *re = RE_GetRender(scene->id.name);
+ RenderData *rd;
+ rctf border;
+
+ if (re == NULL) {
+ /* Shouldn't happen, but better be safe close to the release. */
+ return OPERATOR_CANCELLED;
+ }
+
+ rd = RE_engine_get_render_data(re);
+ if ((rd->mode & (R_BORDER | R_CROP)) == (R_BORDER | R_CROP)) {
+ BKE_report(op->reports, RPT_INFO, "Can not set border from a cropped render");
+ return OPERATOR_CANCELLED;
+ }
+
+ /* get rectangle from operator */
+ WM_operator_properties_border_to_rctf(op, &border);
+ UI_view2d_region_to_view_rctf(&ar->v2d, &border, &border);
+
+ /* actually set border */
+ CLAMP(border.xmin, 0.0f, 1.0f);
+ CLAMP(border.ymin, 0.0f, 1.0f);
+ CLAMP(border.xmax, 0.0f, 1.0f);
+ CLAMP(border.ymax, 0.0f, 1.0f);
+ scene->r.border = border;
+
+ /* drawing a border surrounding the entire camera view switches off border rendering
+ * or the border covers no pixels */
+ if ((border.xmin <= 0.0f && border.xmax >= 1.0f &&
+ border.ymin <= 0.0f && border.ymax >= 1.0f) ||
+ (border.xmin == border.xmax || border.ymin == border.ymax))
+ {
+ scene->r.mode &= ~R_BORDER;
+ }
+ else {
+ scene->r.mode |= R_BORDER;
+ }
+
+ WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, NULL);
+
+ return OPERATOR_FINISHED;
+
+}
+
+void IMAGE_OT_render_border(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Render Border";
+ ot->description = "Set the boundaries of the border render and enable border render";
+ ot->idname = "IMAGE_OT_render_border";
+
+ /* api callbacks */
+ ot->invoke = WM_border_select_invoke;
+ ot->exec = render_border_exec;
+ ot->modal = WM_border_select_modal;
+ ot->cancel = WM_border_select_cancel;
+ ot->poll = image_cycle_render_slot_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* rna */
+ WM_operator_properties_border(ot);
+}
+
+/* ********************* Clear render border operator ****************** */
+
+static int clear_render_border_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ Scene *scene = CTX_data_scene(C);
+ scene->r.mode &= ~R_BORDER;
+ WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, NULL);
+ BLI_rctf_init(&scene->r.border, 0.0f, 1.0f, 0.0f, 1.0f);
+ return OPERATOR_FINISHED;
+
+}
+
+void IMAGE_OT_clear_render_border(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Render Border";
+ ot->description = "Clear the boundaries of the border render and disable border render";
+ ot->idname = "IMAGE_OT_clear_render_border";
+
+ /* api callbacks */
+ ot->exec = clear_render_border_exec;
+ ot->poll = image_cycle_render_slot_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
diff --git a/source/blender/editors/space_image/space_image.c b/source/blender/editors/space_image/space_image.c
index ab616bf592f..97e3390f142 100644
--- a/source/blender/editors/space_image/space_image.c
+++ b/source/blender/editors/space_image/space_image.c
@@ -33,6 +33,7 @@
#include "DNA_meshdata_types.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
+#include "DNA_image_types.h"
#include "MEM_guardedalloc.h"
@@ -155,7 +156,8 @@ static SpaceLink *image_new(const bContext *UNUSED(C))
simage->iuser.ok = true;
simage->iuser.fie_ima = 2;
simage->iuser.frames = 100;
-
+ simage->iuser.flag = IMA_SHOW_STEREO;
+
scopes_new(&simage->scopes);
simage->sample_line_hist.height = 100;
@@ -257,6 +259,8 @@ static void image_operatortypes(void)
WM_operatortype_append(IMAGE_OT_change_frame);
WM_operatortype_append(IMAGE_OT_read_renderlayers);
+ WM_operatortype_append(IMAGE_OT_render_border);
+ WM_operatortype_append(IMAGE_OT_clear_render_border);
}
static void image_keymap(struct wmKeyConfig *keyconf)
@@ -325,9 +329,9 @@ static void image_keymap(struct wmKeyConfig *keyconf)
RNA_boolean_set(kmi->ptr, "toggle", true);
/* fast switch to render slots */
- for (i = 0; i < MAX2(IMA_MAX_RENDER_SLOT, 9); i++) {
+ for (i = 0; i < MIN2(IMA_MAX_RENDER_SLOT, 9); i++) {
kmi = WM_keymap_add_item(keymap, "WM_OT_context_set_int", ONEKEY + i, KM_PRESS, 0, 0);
- RNA_string_set(kmi->ptr, "data_path", "space_data.image.render_slot");
+ RNA_string_set(kmi->ptr, "data_path", "space_data.image.render_slots.active_index");
RNA_int_set(kmi->ptr, "value", i);
}
@@ -343,13 +347,17 @@ static void image_keymap(struct wmKeyConfig *keyconf)
kmi = WM_keymap_add_item(keymap, "WM_OT_context_set_enum", PERIODKEY, KM_PRESS, 0, 0);
RNA_string_set(kmi->ptr, "data_path", "space_data.pivot_point");
RNA_string_set(kmi->ptr, "value", "CURSOR");
+
+ /* render border */
+ WM_keymap_add_item(keymap, "IMAGE_OT_render_border", BKEY, KM_PRESS, KM_CTRL, 0);
+ WM_keymap_add_item(keymap, "IMAGE_OT_clear_render_border", BKEY, KM_PRESS, KM_CTRL | KM_ALT, 0);
}
/* dropboxes */
static int image_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent *UNUSED(event))
{
if (drag->type == WM_DRAG_PATH)
- if (ELEM(drag->icon, 0, ICON_FILE_IMAGE, ICON_FILE_BLANK)) /* rule might not work? */
+ if (ELEM(drag->icon, 0, ICON_FILE_IMAGE, ICON_FILE_MOVIE, ICON_FILE_BLANK)) /* rule might not work? */
return 1;
return 0;
}
@@ -674,7 +682,7 @@ static void image_main_area_draw(const bContext *C, ARegion *ar)
View2D *v2d = &ar->v2d;
//View2DScrollers *scrollers;
float col[3];
-
+
/* XXX not supported yet, disabling for now */
scene->r.scemode &= ~R_COMP_CROP;
@@ -686,7 +694,7 @@ static void image_main_area_draw(const bContext *C, ARegion *ar)
/* put scene context variable in iuser */
if (sima->image && sima->image->type == IMA_TYPE_R_RESULT) {
/* for render result, try to use the currently rendering scene */
- Scene *render_scene = ED_render_job_get_scene(C);
+ Scene *render_scene = ED_render_job_get_current_scene(C);
if (render_scene)
sima->iuser.scene = render_scene;
else
@@ -706,7 +714,7 @@ static void image_main_area_draw(const bContext *C, ARegion *ar)
ED_region_draw_cb_draw(C, ar, REGION_DRAW_PRE_VIEW);
- draw_uvedit_main(sima, ar, scene, obedit, obact);
+ ED_uvedit_draw_main(sima, ar, scene, obedit, obact);
/* check for mask (delay draw) */
if (ED_space_image_show_uvedit(sima, obedit)) {
@@ -766,12 +774,12 @@ static void image_main_area_draw(const bContext *C, ARegion *ar)
NULL, C);
UI_view2d_view_ortho(v2d);
- draw_image_cursor(ar, sima->cursor);
+ ED_image_draw_cursor(ar, sima->cursor);
UI_view2d_view_restore(C);
}
else if (curve) {
UI_view2d_view_ortho(v2d);
- draw_image_cursor(ar, sima->cursor);
+ ED_image_draw_cursor(ar, sima->cursor);
UI_view2d_view_restore(C);
}
@@ -785,18 +793,28 @@ static void image_main_area_draw(const bContext *C, ARegion *ar)
#endif
}
-static void image_main_area_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn)
+static void image_main_area_listener(bScreen *UNUSED(sc), ScrArea *sa, ARegion *ar, wmNotifier *wmn)
{
/* context changes */
switch (wmn->category) {
case NC_GPENCIL:
- if (wmn->action == NA_EDITED)
+ if (ELEM(wmn->action, NA_EDITED, NA_SELECTED))
+ ED_region_tag_redraw(ar);
+ else if (wmn->data & ND_GPENCIL_EDITMODE)
ED_region_tag_redraw(ar);
break;
case NC_IMAGE:
if (wmn->action == NA_PAINTING)
ED_region_tag_redraw(ar);
break;
+ case NC_MATERIAL:
+ if (wmn->data == ND_SHADING_LINKS) {
+ SpaceImage *sima = sa->spacedata.first;
+
+ if (sima->iuser.scene && (sima->iuser.scene->toolsettings->uv_flag & UV_SHOW_SAME_IMAGE))
+ ED_region_tag_redraw(ar);
+ }
+ break;
}
}
@@ -816,7 +834,7 @@ static void image_buttons_area_init(wmWindowManager *wm, ARegion *ar)
static void image_buttons_area_draw(const bContext *C, ARegion *ar)
{
- ED_region_panels(C, ar, 1, NULL, -1);
+ ED_region_panels(C, ar, NULL, -1, true);
}
static void image_buttons_area_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn)
@@ -845,6 +863,10 @@ static void image_buttons_area_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa)
case NC_NODE:
ED_region_tag_redraw(ar);
break;
+ case NC_GPENCIL:
+ if (ELEM(wmn->action, NA_EDITED, NA_SELECTED))
+ ED_region_tag_redraw(ar);
+ break;
}
}
@@ -878,14 +900,14 @@ static void image_tools_area_draw(const bContext *C, ARegion *ar)
BKE_histogram_update_sample_line(&sima->sample_line_hist, ibuf, &scene->view_settings, &scene->display_settings);
}
if (sima->image->flag & IMA_VIEW_AS_RENDER)
- scopes_update(&sima->scopes, ibuf, &scene->view_settings, &scene->display_settings);
+ ED_space_image_scopes_update(C, sima, ibuf, true);
else
- scopes_update(&sima->scopes, ibuf, NULL, &scene->display_settings);
+ ED_space_image_scopes_update(C, sima, ibuf, false);
}
}
ED_space_image_release_buffer(sima, ibuf, lock);
- ED_region_panels(C, ar, 1, NULL, -1);
+ ED_region_panels(C, ar, NULL, -1, true);
}
static void image_tools_area_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn)
@@ -893,11 +915,12 @@ static void image_tools_area_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa),
/* context changes */
switch (wmn->category) {
case NC_GPENCIL:
- if (wmn->data == ND_DATA)
+ if (wmn->data == ND_DATA || ELEM(wmn->action, NA_EDITED, NA_SELECTED))
ED_region_tag_redraw(ar);
break;
case NC_BRUSH:
- if (wmn->action == NA_EDITED)
+ /* NA_SELECTED is used on brush changes */
+ if (ELEM(wmn->action, NA_EDITED, NA_SELECTED))
ED_region_tag_redraw(ar);
break;
case NC_SCENE:
diff --git a/source/blender/editors/space_info/CMakeLists.txt b/source/blender/editors/space_info/CMakeLists.txt
index 94b40a9f40a..96fe9322b97 100644
--- a/source/blender/editors/space_info/CMakeLists.txt
+++ b/source/blender/editors/space_info/CMakeLists.txt
@@ -24,12 +24,15 @@ set(INC
../../blenkernel
../../blenlib
../../blenloader
+ ../../blentranslation
../../imbuf
../../bmesh
+ ../../gpu
../../makesdna
../../makesrna
../../windowmanager
../../../../intern/guardedalloc
+ ../../../../intern/glew-mx
)
set(INC_SYS
@@ -52,4 +55,6 @@ if(WITH_INTERNATIONAL)
add_definitions(-DWITH_INTERNATIONAL)
endif()
+add_definitions(${GL_DEFINITIONS})
+
blender_add_lib(bf_editor_space_info "${SRC}" "${INC}" "${INC_SYS}")
diff --git a/source/blender/editors/space_info/SConscript b/source/blender/editors/space_info/SConscript
index 2a1419984c6..e17c39f7e38 100644
--- a/source/blender/editors/space_info/SConscript
+++ b/source/blender/editors/space_info/SConscript
@@ -31,13 +31,16 @@ sources = env.Glob('*.c')
incs = [
'#/intern/guardedalloc',
- '#/extern/glew/include',
+ env['BF_GLEW_INC'],
+ '#/intern/glew-mx',
'../include',
'../../blenfont',
'../../blenkernel',
'../../blenlib',
'../../blenloader',
+ '../../blentranslation',
'../../bmesh',
+ '../../gpu',
'../../imbuf',
'../../makesdna',
'../../makesrna',
@@ -46,6 +49,7 @@ incs = [
incs = ' '.join(incs)
defs = []
+defs += env['BF_GL_DEFINITIONS']
if env['WITH_BF_INTERNATIONAL']:
defs.append('WITH_INTERNATIONAL')
diff --git a/source/blender/editors/space_info/info_draw.c b/source/blender/editors/space_info/info_draw.c
index 86af89bd6a9..cd424f45842 100644
--- a/source/blender/editors/space_info/info_draw.c
+++ b/source/blender/editors/space_info/info_draw.c
@@ -33,7 +33,6 @@
#include <sys/stat.h>
#include <limits.h>
-#include "BLF_api.h"
#include "BLI_utildefines.h"
@@ -45,15 +44,13 @@
#include "BIF_gl.h"
-#include "ED_datafiles.h"
-#include "ED_types.h"
#include "UI_resources.h"
#include "UI_interface.h"
#include "UI_view2d.h"
#include "info_intern.h"
-#include "../space_info/textview.h"
+#include "textview.h"
/* complicates things a bit, so leaving in old simple code */
#define USE_INFO_NEWLINE
diff --git a/source/blender/editors/space_info/info_ops.c b/source/blender/editors/space_info/info_ops.c
index 25fa31407ff..2bcd56a3ced 100644
--- a/source/blender/editors/space_info/info_ops.c
+++ b/source/blender/editors/space_info/info_ops.c
@@ -42,7 +42,7 @@
#include "BLI_math.h"
#include "BLI_utildefines.h"
-#include "BLF_translation.h"
+#include "BLT_translation.h"
#include "BKE_bpath.h"
#include "BKE_context.h"
@@ -134,7 +134,7 @@ static int autopack_toggle_exec(bContext *C, wmOperator *op)
G.fileflags &= ~G_AUTOPACK;
}
else {
- packAll(bmain, op->reports);
+ packAll(bmain, op->reports, true);
G.fileflags |= G_AUTOPACK;
}
@@ -161,7 +161,7 @@ static int pack_all_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
- packAll(bmain, op->reports);
+ packAll(bmain, op->reports, true);
G.fileflags |= G_AUTOPACK;
return OPERATOR_FINISHED;
@@ -253,15 +253,15 @@ static int unpack_all_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(
else
BLI_snprintf(title, sizeof(title), IFACE_("Unpack %d Files"), count);
- pup = uiPupMenuBegin(C, title, ICON_NONE);
- layout = uiPupMenuLayout(pup);
+ pup = UI_popup_menu_begin(C, title, ICON_NONE);
+ layout = UI_popup_menu_layout(pup);
uiLayoutSetOperatorContext(layout, WM_OP_EXEC_DEFAULT);
uiItemsEnumO(layout, "FILE_OT_unpack_all", "method");
- uiPupMenuEnd(C, pup);
+ UI_popup_menu_end(C, pup);
- return OPERATOR_CANCELLED;
+ return OPERATOR_INTERFACE;
}
void FILE_OT_unpack_all(wmOperatorType *ot)
@@ -322,15 +322,15 @@ static int unpack_item_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED
uiPopupMenu *pup;
uiLayout *layout;
- pup = uiPupMenuBegin(C, IFACE_("Unpack"), ICON_NONE);
- layout = uiPupMenuLayout(pup);
+ pup = UI_popup_menu_begin(C, IFACE_("Unpack"), ICON_NONE);
+ layout = UI_popup_menu_layout(pup);
uiLayoutSetOperatorContext(layout, WM_OP_EXEC_DEFAULT);
uiItemsFullEnumO(layout, op->type->idname, "method", op->ptr->data, WM_OP_EXEC_REGION_WIN, 0);
- uiPupMenuEnd(C, pup);
+ UI_popup_menu_end(C, pup);
- return OPERATOR_CANCELLED;
+ return OPERATOR_INTERFACE;
}
void FILE_OT_unpack_item(wmOperatorType *ot)
@@ -485,7 +485,7 @@ void FILE_OT_find_missing_files(wmOperatorType *ot)
RNA_def_boolean(ot->srna, "find_all", false, "Find All", "Find all files in the search path (not just missing)");
WM_operator_properties_filesel(ot, 0, FILE_SPECIAL, FILE_OPENFILE,
- WM_FILESEL_DIRECTORY, FILE_DEFAULTDISPLAY);
+ WM_FILESEL_DIRECTORY, FILE_DEFAULTDISPLAY, FILE_SORT_ALPHA);
}
/********************* report box operator *********************/
diff --git a/source/blender/editors/space_info/info_stats.c b/source/blender/editors/space_info/info_stats.c
index a0dfb285a1c..dafb71b4480 100644
--- a/source/blender/editors/space_info/info_stats.c
+++ b/source/blender/editors/space_info/info_stats.c
@@ -41,7 +41,7 @@
#include "BLI_string.h"
#include "BLI_utildefines.h"
-#include "BLF_translation.h"
+#include "BLT_translation.h"
#include "BKE_anim.h"
#include "BKE_blender.h"
@@ -56,6 +56,8 @@
#include "ED_info.h"
#include "ED_armature.h"
+#include "GPU_extensions.h"
+
#define MAX_INFO_LEN 512
#define MAX_INFO_NUM_LEN 16
@@ -381,6 +383,7 @@ static void stats_string(Scene *scene)
Object *ob = (scene->basact) ? scene->basact->object : NULL;
uintptr_t mem_in_use, mmap_in_use;
char memstr[MAX_INFO_MEM_LEN];
+ char gpumemstr[MAX_INFO_MEM_LEN] = "";
char *s;
size_t ofs = 0;
@@ -416,11 +419,22 @@ static void stats_string(Scene *scene)
/* get memory statistics */
- s = memstr;
- ofs += BLI_snprintf(s + ofs, MAX_INFO_MEM_LEN - ofs, IFACE_(" | Mem:%.2fM"),
+ ofs = BLI_snprintf(memstr, MAX_INFO_MEM_LEN, IFACE_(" | Mem:%.2fM"),
(double)((mem_in_use - mmap_in_use) >> 10) / 1024.0);
if (mmap_in_use)
- BLI_snprintf(s + ofs, MAX_INFO_MEM_LEN - ofs, IFACE_(" (%.2fM)"), (double)((mmap_in_use) >> 10) / 1024.0);
+ BLI_snprintf(memstr + ofs, MAX_INFO_MEM_LEN - ofs, IFACE_(" (%.2fM)"), (double)((mmap_in_use) >> 10) / 1024.0);
+
+ if (GPU_mem_stats_supported()) {
+ int gpu_free_mem, gpu_tot_memory;
+
+ GPU_mem_stats_get(&gpu_tot_memory, &gpu_free_mem);
+
+ ofs = BLI_snprintf(gpumemstr, MAX_INFO_MEM_LEN, IFACE_(" | Free GPU Mem:%.2fM"), (double)((gpu_free_mem)) / 1024.0);
+
+ if (gpu_tot_memory) {
+ BLI_snprintf(gpumemstr + ofs, MAX_INFO_MEM_LEN - ofs, IFACE_("/%.2fM"), (double)((gpu_tot_memory)) / 1024.0);
+ }
+ }
s = stats->infostr;
ofs = 0;
@@ -447,22 +461,23 @@ static void stats_string(Scene *scene)
}
ofs += BLI_strncpy_rlen(s + ofs, memstr, MAX_INFO_LEN - ofs);
+ ofs += BLI_strncpy_rlen(s + ofs, gpumemstr, MAX_INFO_LEN - ofs);
}
else if (ob && (ob->mode & OB_MODE_POSE)) {
- ofs += BLI_snprintf(s + ofs, MAX_INFO_LEN - ofs, IFACE_("Bones:%s/%s %s"),
- stats_fmt.totbonesel, stats_fmt.totbone, memstr);
+ ofs += BLI_snprintf(s + ofs, MAX_INFO_LEN - ofs, IFACE_("Bones:%s/%s %s%s"),
+ stats_fmt.totbonesel, stats_fmt.totbone, memstr, gpumemstr);
}
else if (stats_is_object_dynamic_topology_sculpt(ob)) {
- ofs += BLI_snprintf(s + ofs, MAX_INFO_LEN - ofs, IFACE_("Verts:%s | Tris:%s"), stats_fmt.totvert,
- stats_fmt.tottri);
+ ofs += BLI_snprintf(s + ofs, MAX_INFO_LEN - ofs, IFACE_("Verts:%s | Tris:%s%s"), stats_fmt.totvert,
+ stats_fmt.tottri, gpumemstr);
}
else {
ofs += BLI_snprintf(s + ofs, MAX_INFO_LEN - ofs,
- IFACE_("Verts:%s | Faces:%s | Tris:%s | Objects:%s/%s | Lamps:%s/%s%s"),
+ IFACE_("Verts:%s | Faces:%s | Tris:%s | Objects:%s/%s | Lamps:%s/%s%s%s"),
stats_fmt.totvert, stats_fmt.totface,
stats_fmt.tottri, stats_fmt.totobjsel,
stats_fmt.totobj, stats_fmt.totlampsel,
- stats_fmt.totlamp, memstr);
+ stats_fmt.totlamp, memstr, gpumemstr);
}
if (ob)
diff --git a/source/blender/editors/space_info/space_info.c b/source/blender/editors/space_info/space_info.c
index 062fc0cd42e..aeab87e6cb5 100644
--- a/source/blender/editors/space_info/space_info.c
+++ b/source/blender/editors/space_info/space_info.c
@@ -37,7 +37,7 @@
#include "BLI_blenlib.h"
#include "BLI_utildefines.h"
-#include "BLF_translation.h"
+#include "BLT_translation.h"
#include "BKE_context.h"
#include "BKE_global.h"
@@ -282,16 +282,13 @@ static void info_header_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegi
static void recent_files_menu_draw(const bContext *UNUSED(C), Menu *menu)
{
struct RecentFile *recent;
- char file[FILE_MAX];
uiLayout *layout = menu->layout;
uiLayoutSetOperatorContext(layout, WM_OP_EXEC_REGION_WIN);
- if (G.recent_files.first) {
+ if (!BLI_listbase_is_empty(&G.recent_files)) {
for (recent = G.recent_files.first; (recent); recent = recent->next) {
- BLI_split_file_part(recent->filepath, file, sizeof(file));
- if (BLO_has_bfile_extension(file))
- uiItemStringO(layout, BLI_path_basename(recent->filepath), ICON_FILE_BLEND, "WM_OT_open_mainfile", "filepath", recent->filepath);
- else
- uiItemStringO(layout, BLI_path_basename(recent->filepath), ICON_FILE_BACKUP, "WM_OT_open_mainfile", "filepath", recent->filepath);
+ const char *file = BLI_path_basename(recent->filepath);
+ const int icon = BLO_has_bfile_extension(file) ? ICON_FILE_BLEND : ICON_FILE_BACKUP;
+ uiItemStringO(layout, file, icon, "WM_OT_open_mainfile", "filepath", recent->filepath);
}
}
else {
@@ -306,7 +303,7 @@ static void recent_files_menu_register(void)
mt = MEM_callocN(sizeof(MenuType), "spacetype info menu recent files");
strcpy(mt->idname, "INFO_MT_file_open_recent");
strcpy(mt->label, N_("Open Recent..."));
- strcpy(mt->translation_context, BLF_I18NCONTEXT_DEFAULT_BPYRNA);
+ strcpy(mt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
mt->draw = recent_files_menu_draw;
WM_menutype_add(mt);
}
diff --git a/source/blender/editors/space_info/textview.c b/source/blender/editors/space_info/textview.c
index 33333e4c992..ebce13389c9 100644
--- a/source/blender/editors/space_info/textview.c
+++ b/source/blender/editors/space_info/textview.c
@@ -155,7 +155,7 @@ static int console_draw_string(ConsoleDrawContext *cdc, const char *str, int str
MEM_freeN(offsets);
return 1;
}
- else if (y_next - cdc->lheight < cdc->ymin) {
+ else if (y_next < cdc->ymin) {
/* have not reached the drawable area so don't break */
cdc->xy[1] = y_next;
diff --git a/source/blender/editors/space_logic/CMakeLists.txt b/source/blender/editors/space_logic/CMakeLists.txt
index af2e8476511..349c003cf56 100644
--- a/source/blender/editors/space_logic/CMakeLists.txt
+++ b/source/blender/editors/space_logic/CMakeLists.txt
@@ -21,13 +21,15 @@
set(INC
../include
../interface
- ../../blenfont
../../blenkernel
../../blenlib
+ ../../blentranslation
+ ../../gpu
../../makesdna
../../makesrna
../../windowmanager
../../../../intern/guardedalloc
+ ../../../../intern/glew-mx
)
set(INC_SYS
@@ -47,6 +49,8 @@ if(WITH_GAMEENGINE)
add_definitions(-DWITH_GAMEENGINE)
endif()
+add_definitions(${GL_DEFINITIONS})
+
if(WITH_INTERNATIONAL)
add_definitions(-DWITH_INTERNATIONAL)
endif()
diff --git a/source/blender/editors/space_logic/SConscript b/source/blender/editors/space_logic/SConscript
index ae8e929a684..4b618710d1f 100644
--- a/source/blender/editors/space_logic/SConscript
+++ b/source/blender/editors/space_logic/SConscript
@@ -31,12 +31,14 @@ sources = env.Glob('*.c')
incs = [
'#/intern/guardedalloc',
- '#/extern/glew/include',
+ env['BF_GLEW_INC'],
+ '#/intern/glew-mx',
'../include',
'../interface',
- '../../blenfont',
'../../blenkernel',
'../../blenlib',
+ '../../blentranslation',
+ '../../gpu',
'../../imbuf',
'../../makesdna',
'../../makesrna',
@@ -45,6 +47,7 @@ incs = [
incs = ' '.join(incs)
defs = []
+defs += env['BF_GL_DEFINITIONS']
if env['WITH_BF_GAMEENGINE']:
defs.append('WITH_GAMEENGINE')
diff --git a/source/blender/editors/space_logic/logic_buttons.c b/source/blender/editors/space_logic/logic_buttons.c
index 2c521532484..e0cbc1c9539 100644
--- a/source/blender/editors/space_logic/logic_buttons.c
+++ b/source/blender/editors/space_logic/logic_buttons.c
@@ -34,7 +34,6 @@
#include "BLI_utildefines.h"
#include "BKE_context.h"
-#include "BKE_screen.h"
#include "ED_screen.h"
@@ -124,12 +123,12 @@ static int cut_links_exec(bContext *C, wmOperator *op)
for (block = ar->uiblocks.first; block; block = block->next) {
but = block->buttons.first;
while (but) {
- if (but->type==LINK && but->link) {
+ if (but->type==UI_BTYPE_LINK && but->link) {
for (line = but->link->lines.first; line; line = nline) {
nline = line->next;
if (cut_links_intersect(line, mcoords, i)) {
- ui_delete_linkline(line, but);
+ ui_linkline_remove(line, but);
}
}
}
diff --git a/source/blender/editors/space_logic/logic_intern.h b/source/blender/editors/space_logic/logic_intern.h
index 38b122f64b6..13146621d1b 100644
--- a/source/blender/editors/space_logic/logic_intern.h
+++ b/source/blender/editors/space_logic/logic_intern.h
@@ -35,12 +35,8 @@
/* internal exports only */
struct bContext;
struct ARegion;
-struct ARegionType;
struct ScrArea;
-struct SpaceLogic;
-struct Object;
struct wmOperatorType;
-struct Scene;
/* space_logic.c */
struct ARegion *logic_has_buttons_region(struct ScrArea *sa);
diff --git a/source/blender/editors/space_logic/logic_ops.c b/source/blender/editors/space_logic/logic_ops.c
index 62703ba517e..abcb767958f 100644
--- a/source/blender/editors/space_logic/logic_ops.c
+++ b/source/blender/editors/space_logic/logic_ops.c
@@ -39,6 +39,8 @@
#include "BLI_blenlib.h"
#include "BLI_utildefines.h"
+#include "BLT_translation.h"
+
#include "BKE_context.h"
#include "BKE_main.h"
#include "BKE_sca.h"
@@ -298,7 +300,7 @@ static int sensor_add_exec(bContext *C, wmOperator *op)
BLI_strncpy(sens->name, sens_name, sizeof(sens->name));
}
- make_unique_prop_names(C, sens->name);
+ BLI_uniquename(&ob->sensors, sens, DATA_("Sensor"), '.', offsetof(bSensor, name), sizeof(sens->name));
ob->scaflag |= OB_SHOWSENS;
WM_event_add_notifier(C, NC_LOGIC, NULL);
@@ -405,7 +407,8 @@ static int controller_add_exec(bContext *C, wmOperator *op)
BLI_strncpy(cont->name, cont_name, sizeof(cont->name));
}
- make_unique_prop_names(C, cont->name);
+ BLI_uniquename(&ob->controllers, cont, DATA_("Controller"), '.', offsetof(bController, name), sizeof(cont->name));
+
/* set the controller state mask from the current object state.
* A controller is always in a single state, so select the lowest bit set
* from the object state */
@@ -523,7 +526,7 @@ static int actuator_add_exec(bContext *C, wmOperator *op)
BLI_strncpy(act->name, act_name, sizeof(act->name));
}
- make_unique_prop_names(C, act->name);
+ BLI_uniquename(&ob->actuators, act, DATA_("Actuator"), '.', offsetof(bActuator, name), sizeof(act->name));
ob->scaflag |= OB_SHOWACT;
WM_event_add_notifier(C, NC_LOGIC, NULL);
diff --git a/source/blender/editors/space_logic/logic_window.c b/source/blender/editors/space_logic/logic_window.c
index dd152022762..ccf8460e9a3 100644
--- a/source/blender/editors/space_logic/logic_window.c
+++ b/source/blender/editors/space_logic/logic_window.c
@@ -48,6 +48,7 @@
#include "BLI_blenlib.h"
#include "BLI_utildefines.h"
+#include "BLI_path_util.h"
#include "BKE_action.h"
#include "BKE_context.h"
@@ -56,7 +57,7 @@
#include "ED_util.h"
-#include "BLF_translation.h"
+#include "BLT_translation.h"
#include "UI_interface.h"
#include "UI_view2d.h"
@@ -94,91 +95,6 @@
/* proto */
static ID **get_selected_and_linked_obs(bContext *C, short *count, short scavisflag);
-static int vergname(const void *v1, const void *v2)
-{
- char **x1, **x2;
-
- x1 = (char **)v1;
- x2 = (char **)v2;
-
- return BLI_natstrcmp(*x1, *x2);
-}
-
-void make_unique_prop_names(bContext *C, char *str)
-{
- Object *ob;
- bProperty *prop;
- bSensor *sens;
- bController *cont;
- bActuator *act;
- ID **idar;
- short a, obcount, propcount=0, nr;
- const char **names;
-
- /* this function is called by a Button, and gives the current
- * stringpointer as an argument, this is the one that can change
- */
-
- idar= get_selected_and_linked_obs(C, &obcount, BUTS_SENS_SEL|BUTS_SENS_ACT|BUTS_ACT_SEL|BUTS_ACT_ACT|BUTS_CONT_SEL|BUTS_CONT_ACT);
-
- /* for each object, make properties and sca names unique */
-
- /* count total names */
- for (a=0; a<obcount; a++) {
- ob= (Object *)idar[a];
- propcount+= BLI_countlist(&ob->prop);
- propcount+= BLI_countlist(&ob->sensors);
- propcount+= BLI_countlist(&ob->controllers);
- propcount+= BLI_countlist(&ob->actuators);
- }
- if (propcount==0) {
- if (idar) MEM_freeN(idar);
- return;
- }
-
- /* make names array for sorting */
- names= MEM_callocN(propcount*sizeof(void *), "names");
-
- /* count total names */
- nr= 0;
- for (a=0; a<obcount; a++) {
- ob= (Object *)idar[a];
- prop= ob->prop.first;
- while (prop) {
- names[nr++] = prop->name;
- prop= prop->next;
- }
- sens= ob->sensors.first;
- while (sens) {
- names[nr++] = sens->name;
- sens= sens->next;
- }
- cont= ob->controllers.first;
- while (cont) {
- names[nr++] = cont->name;
- cont= cont->next;
- }
- act= ob->actuators.first;
- while (act) {
- names[nr++] = act->name;
- act= act->next;
- }
- }
-
- qsort(names, propcount, sizeof(void *), vergname);
-
- /* now we check for double names, and change them */
-
- for (nr=0; nr<propcount; nr++) {
- if (names[nr]!=str && strcmp( names[nr], str )==0 ) {
- BLI_newname(str, +1);
- }
- }
-
- MEM_freeN(idar);
- MEM_freeN(names);
-}
-
static void do_logic_buts(bContext *C, void *UNUSED(arg), int event)
{
Main *bmain= CTX_data_main(C);
@@ -210,7 +126,7 @@ static void do_logic_buts(bContext *C, void *UNUSED(arg), int event)
ob->scaflag &= ~OB_ADDSENS;
sens= new_sensor(SENS_ALWAYS);
BLI_addtail(&(ob->sensors), sens);
- make_unique_prop_names(C, sens->name);
+ BLI_uniquename(&ob->sensors, sens, DATA_("Sensor"), '.', offsetof(bSensor, name), sizeof(sens->name));
ob->scaflag |= OB_SHOWSENS;
}
}
@@ -252,7 +168,7 @@ static void do_logic_buts(bContext *C, void *UNUSED(arg), int event)
if (ob->scaflag & OB_ADDCONT) {
ob->scaflag &= ~OB_ADDCONT;
cont= new_controller(CONT_LOGIC_AND);
- make_unique_prop_names(C, cont->name);
+ BLI_uniquename(&ob->controllers, cont, DATA_("Controller"), '.', offsetof(bController, name), sizeof(cont->name));
ob->scaflag |= OB_SHOWCONT;
BLI_addtail(&(ob->controllers), cont);
/* set the controller state mask from the current object state.
@@ -328,7 +244,7 @@ static void do_logic_buts(bContext *C, void *UNUSED(arg), int event)
if (ob->scaflag & OB_ADDACT) {
ob->scaflag &= ~OB_ADDACT;
act= new_actuator(ACT_OBJECT);
- make_unique_prop_names(C, act->name);
+ BLI_uniquename(&ob->actuators, act, DATA_("Actuator"), '.', offsetof(bActuator, name), sizeof(act->name));
BLI_addtail(&(ob->actuators), act);
ob->scaflag |= OB_SHOWACT;
}
@@ -761,17 +677,17 @@ static uiBlock *sensor_menu(bContext *C, ARegion *ar, void *UNUSED(arg))
uiBlock *block;
int yco=0;
- block= uiBeginBlock(C, ar, __func__, UI_EMBOSSP);
- uiBlockSetButmFunc(block, do_sensor_menu, NULL);
+ block= UI_block_begin(C, ar, __func__, UI_EMBOSS_PULLDOWN);
+ UI_block_func_butmenu_set(block, do_sensor_menu, NULL);
- uiDefBut(block, BUTM, 1, IFACE_("Show Objects"), 0, (short)(yco-=20), 160, 19, NULL, 0.0, 0.0, 1, 0, "");
- uiDefBut(block, BUTM, 1, IFACE_("Hide Objects"), 0, (short)(yco-=20), 160, 19, NULL, 0.0, 0.0, 1, 1, "");
- uiDefBut(block, SEPRLINE, 0, "", 0, (short)(yco-=6), 160, 6, NULL, 0.0, 0.0, 0, 0, "");
- uiDefBut(block, BUTM, 1, IFACE_("Show Sensors"), 0, (short)(yco-=20), 160, 19, NULL, 0.0, 0.0, 1, 2, "");
- uiDefBut(block, BUTM, 1, IFACE_("Hide Sensors"), 0, (short)(yco-=20), 160, 19, NULL, 0.0, 0.0, 1, 3, "");
+ uiDefBut(block, UI_BTYPE_BUT_MENU, 1, IFACE_("Show Objects"), 0, (short)(yco-=20), 160, 19, NULL, 0.0, 0.0, 1, 0, "");
+ uiDefBut(block, UI_BTYPE_BUT_MENU, 1, IFACE_("Hide Objects"), 0, (short)(yco-=20), 160, 19, NULL, 0.0, 0.0, 1, 1, "");
+ uiDefBut(block, UI_BTYPE_SEPR_LINE, 0, "", 0, (short)(yco-=6), 160, 6, NULL, 0.0, 0.0, 0, 0, "");
+ uiDefBut(block, UI_BTYPE_BUT_MENU, 1, IFACE_("Show Sensors"), 0, (short)(yco-=20), 160, 19, NULL, 0.0, 0.0, 1, 2, "");
+ uiDefBut(block, UI_BTYPE_BUT_MENU, 1, IFACE_("Hide Sensors"), 0, (short)(yco-=20), 160, 19, NULL, 0.0, 0.0, 1, 3, "");
- uiBlockSetDirection(block, UI_TOP);
- uiEndBlock(C, block);
+ UI_block_direction_set(block, UI_DIR_UP);
+ UI_block_end(C, block);
return block;
}
@@ -810,17 +726,17 @@ static uiBlock *controller_menu(bContext *C, ARegion *ar, void *UNUSED(arg))
uiBlock *block;
int yco=0;
- block= uiBeginBlock(C, ar, __func__, UI_EMBOSSP);
- uiBlockSetButmFunc(block, do_controller_menu, NULL);
+ block= UI_block_begin(C, ar, __func__, UI_EMBOSS_PULLDOWN);
+ UI_block_func_butmenu_set(block, do_controller_menu, NULL);
- uiDefBut(block, BUTM, 1, IFACE_("Show Objects"), 0, (short)(yco-=20), 160, 19, NULL, 0.0, 0.0, 1, 0, "");
- uiDefBut(block, BUTM, 1, IFACE_("Hide Objects"), 0, (short)(yco-=20), 160, 19, NULL, 0.0, 0.0, 1, 1, "");
- uiDefBut(block, SEPRLINE, 0, "", 0, (short)(yco-=6), 160, 6, NULL, 0.0, 0.0, 0, 0, "");
- uiDefBut(block, BUTM, 1, IFACE_("Show Controllers"), 0, (short)(yco-=20), 160, 19, NULL, 0.0, 0.0, 2, 2, "");
- uiDefBut(block, BUTM, 1, IFACE_("Hide Controllers"), 0, (short)(yco-=20), 160, 19, NULL, 0.0, 0.0, 3, 3, "");
+ uiDefBut(block, UI_BTYPE_BUT_MENU, 1, IFACE_("Show Objects"), 0, (short)(yco-=20), 160, 19, NULL, 0.0, 0.0, 1, 0, "");
+ uiDefBut(block, UI_BTYPE_BUT_MENU, 1, IFACE_("Hide Objects"), 0, (short)(yco-=20), 160, 19, NULL, 0.0, 0.0, 1, 1, "");
+ uiDefBut(block, UI_BTYPE_SEPR_LINE, 0, "", 0, (short)(yco-=6), 160, 6, NULL, 0.0, 0.0, 0, 0, "");
+ uiDefBut(block, UI_BTYPE_BUT_MENU, 1, IFACE_("Show Controllers"), 0, (short)(yco-=20), 160, 19, NULL, 0.0, 0.0, 2, 2, "");
+ uiDefBut(block, UI_BTYPE_BUT_MENU, 1, IFACE_("Hide Controllers"), 0, (short)(yco-=20), 160, 19, NULL, 0.0, 0.0, 3, 3, "");
- uiBlockSetDirection(block, UI_TOP);
- uiEndBlock(C, block);
+ UI_block_direction_set(block, UI_DIR_UP);
+ UI_block_end(C, block);
return block;
}
@@ -859,17 +775,17 @@ static uiBlock *actuator_menu(bContext *C, ARegion *ar, void *UNUSED(arg))
uiBlock *block;
int xco=0;
- block= uiBeginBlock(C, ar, __func__, UI_EMBOSSP);
- uiBlockSetButmFunc(block, do_actuator_menu, NULL);
+ block= UI_block_begin(C, ar, __func__, UI_EMBOSS_PULLDOWN);
+ UI_block_func_butmenu_set(block, do_actuator_menu, NULL);
- uiDefBut(block, BUTM, 1, IFACE_("Show Objects"), 0, (short)(xco-=20), 160, 19, NULL, 0.0, 0.0, 1, 0, "");
- uiDefBut(block, BUTM, 1, IFACE_("Hide Objects"), 0, (short)(xco-=20), 160, 19, NULL, 0.0, 0.0, 1, 1, "");
- uiDefBut(block, SEPRLINE, 0, "", 0, (short)(xco-=6), 160, 6, NULL, 0.0, 0.0, 0, 0, "");
- uiDefBut(block, BUTM, 1, IFACE_("Show Actuators"), 0, (short)(xco-=20), 160, 19, NULL, 0.0, 0.0, 1, 2, "");
- uiDefBut(block, BUTM, 1, IFACE_("Hide Actuators"), 0, (short)(xco-=20), 160, 19, NULL, 0.0, 0.0, 1, 3, "");
+ uiDefBut(block, UI_BTYPE_BUT_MENU, 1, IFACE_("Show Objects"), 0, (short)(xco-=20), 160, 19, NULL, 0.0, 0.0, 1, 0, "");
+ uiDefBut(block, UI_BTYPE_BUT_MENU, 1, IFACE_("Hide Objects"), 0, (short)(xco-=20), 160, 19, NULL, 0.0, 0.0, 1, 1, "");
+ uiDefBut(block, UI_BTYPE_SEPR_LINE, 0, "", 0, (short)(xco-=6), 160, 6, NULL, 0.0, 0.0, 0, 0, "");
+ uiDefBut(block, UI_BTYPE_BUT_MENU, 1, IFACE_("Show Actuators"), 0, (short)(xco-=20), 160, 19, NULL, 0.0, 0.0, 1, 2, "");
+ uiDefBut(block, UI_BTYPE_BUT_MENU, 1, IFACE_("Hide Actuators"), 0, (short)(xco-=20), 160, 19, NULL, 0.0, 0.0, 1, 3, "");
- uiBlockSetDirection(block, UI_TOP);
- uiEndBlock(C, block);
+ UI_block_direction_set(block, UI_DIR_UP);
+ UI_block_end(C, block);
return block;
}
@@ -892,26 +808,26 @@ static uiBlock *controller_state_mask_menu(bContext *C, ARegion *ar, void *arg_c
short yco = 12, xco = 0, stbit, offset;
- block= uiBeginBlock(C, ar, __func__, UI_EMBOSS);
+ block= UI_block_begin(C, ar, __func__, UI_EMBOSS);
/* use this for a fake extra empy space around the buttons */
- uiDefBut(block, LABEL, 0, "", -5, -5, 200, 34, NULL, 0, 0, 0, 0, "");
+ uiDefBut(block, UI_BTYPE_LABEL, 0, "", -5, -5, 200, 34, NULL, 0, 0, 0, 0, "");
for (offset=0; offset<15; offset += 5) {
- uiBlockBeginAlign(block);
+ UI_block_align_begin(block);
for (stbit=0; stbit<5; stbit++) {
- but = uiDefButBitI(block, TOG, (1<<(stbit+offset)), (stbit+offset), "", (short)(xco+12*stbit+13*offset), yco, 12, 12, (int *)&(cont->state_mask), 0, 0, 0, 0, "");
- uiButSetFunc(but, check_controller_state_mask, but, &(cont->state_mask));
+ but = uiDefButBitI(block, UI_BTYPE_TOGGLE, (1<<(stbit+offset)), (stbit+offset), "", (short)(xco+12*stbit+13*offset), yco, 12, 12, (int *)&(cont->state_mask), 0, 0, 0, 0, "");
+ UI_but_func_set(but, check_controller_state_mask, but, &(cont->state_mask));
}
for (stbit=0; stbit<5; stbit++) {
- but = uiDefButBitI(block, TOG, (1<<(stbit+offset+15)), (stbit+offset+15), "", (short)(xco+12*stbit+13*offset), yco-12, 12, 12, (int *)&(cont->state_mask), 0, 0, 0, 0, "");
- uiButSetFunc(but, check_controller_state_mask, but, &(cont->state_mask));
+ but = uiDefButBitI(block, UI_BTYPE_TOGGLE, (1<<(stbit+offset+15)), (stbit+offset+15), "", (short)(xco+12*stbit+13*offset), yco-12, 12, 12, (int *)&(cont->state_mask), 0, 0, 0, 0, "");
+ UI_but_func_set(but, check_controller_state_mask, but, &(cont->state_mask));
}
}
- uiBlockEndAlign(block);
+ UI_block_align_end(block);
- uiBlockSetDirection(block, UI_TOP);
- uiEndBlock(C, block);
+ UI_block_direction_set(block, UI_DIR_UP);
+ UI_block_end(C, block);
return block;
}
@@ -923,7 +839,7 @@ static bool is_sensor_linked(uiBlock *block, bSensor *sens)
for (i=0; i<sens->totlinks; i++) {
cont = sens->links[i];
- if (uiFindInlink(block, cont) != NULL)
+ if (UI_block_links_find_inlink(block, cont) != NULL)
return 1;
}
return 0;
@@ -987,7 +903,7 @@ static void draw_sensor_internal_header(uiLayout *layout, PointerRNA *ptr)
sub = uiLayoutRow(row, false);
uiLayoutSetActive(sub, (RNA_boolean_get(ptr, "use_pulse_true_level") ||
RNA_boolean_get(ptr, "use_pulse_false_level")));
- uiItemR(sub, ptr, "frequency", 0, IFACE_("Freq"), ICON_NONE);
+ uiItemR(sub, ptr, "tick_skip", 0, IFACE_("Skip"), ICON_NONE);
row = uiLayoutRow(split, true);
uiItemR(row, ptr, "use_level", UI_ITEM_R_TOGGLE, NULL, ICON_NONE);
@@ -1117,7 +1033,7 @@ static void draw_sensor_keyboard(uiLayout *layout, PointerRNA *ptr)
uiLayout *row, *col;
row = uiLayoutRow(layout, false);
- uiItemL(row, CTX_IFACE_(BLF_I18NCONTEXT_ID_WINDOWMANAGER, "Key:"), ICON_NONE);
+ uiItemL(row, CTX_IFACE_(BLT_I18NCONTEXT_ID_WINDOWMANAGER, "Key:"), ICON_NONE);
col = uiLayoutColumn(row, false);
uiLayoutSetActive(col, RNA_boolean_get(ptr, "use_all_keys") == false);
uiItemR(col, ptr, "key", UI_ITEM_R_EVENT, "", ICON_NONE);
@@ -2189,12 +2105,15 @@ static void draw_actuator_steering(uiLayout *layout, PointerRNA *ptr)
}
row = uiLayoutRow(layout, false);
- uiItemR(row, ptr, "self_terminated", 0, NULL, ICON_NONE);
+ col = uiLayoutColumn(row, false);
+ uiItemR(col, ptr, "self_terminated", 0, NULL, ICON_NONE);
if (RNA_enum_get(ptr, "mode")==ACT_STEERING_PATHFOLLOWING) {
- uiItemR(row, ptr, "update_period", 0, NULL, ICON_NONE);
- row = uiLayoutRow(layout, false);
+ col = uiLayoutColumn(row, false);
+ uiItemR(col, ptr, "update_period", 0, NULL, ICON_NONE);
}
row = uiLayoutRow(layout, false);
+ uiItemR(row, ptr, "lock_z_velocity", 1, NULL, ICON_NONE);
+ row = uiLayoutRow(layout, false);
uiItemR(row, ptr, "show_visualization", 0, NULL, ICON_NONE);
if (RNA_enum_get(ptr, "mode") != ACT_STEERING_PATHFOLLOWING) {
uiLayoutSetActive(row, false);
@@ -2353,9 +2272,9 @@ void logic_buttons(bContext *C, ARegion *ar)
idar= get_selected_and_linked_obs(C, &count, slogic->scaflag);
BLI_snprintf(uiblockstr, sizeof(uiblockstr), "buttonswin %p", (void *)ar);
- block= uiBeginBlock(C, ar, uiblockstr, UI_EMBOSS);
- uiBlockSetHandleFunc(block, do_logic_buts, NULL);
- uiBoundsBlock(block, U.widget_unit/2);
+ block= UI_block_begin(C, ar, uiblockstr, UI_EMBOSS);
+ UI_block_func_handle_set(block, do_logic_buts, NULL);
+ UI_block_bounds_set_normal(block, U.widget_unit/2);
/* loop over all objects and set visible/linked flags for the logic bricks */
for (a=0; a<count; a++) {
@@ -2401,7 +2320,7 @@ void logic_buttons(bContext *C, ARegion *ar)
/* ****************** Controllers ****************** */
xco= 21 * U.widget_unit; yco= - U.widget_unit / 2; width= 15 * U.widget_unit;
- layout= uiBlockLayout(block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, xco, yco, width, 20, 0, UI_GetStyle());
+ layout= UI_block_layout(block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, xco, yco, width, 20, 0, UI_style_get());
row = uiLayoutRow(layout, true);
uiDefBlockBut(block, controller_menu, NULL, IFACE_("Controllers"), xco - U.widget_unit / 2, yco, width, UI_UNIT_Y, ""); /* replace this with uiLayout stuff later */
@@ -2431,7 +2350,7 @@ void logic_buttons(bContext *C, ARegion *ar)
uiItemR(split, &settings_ptr, "show_state_panel", UI_ITEM_R_NO_BG, "", ICON_DISCLOSURE_TRI_RIGHT);
row = uiLayoutRow(split, true);
- uiDefButBitS(block, TOG, OB_SHOWCONT, B_REDR, ob->id.name + 2, (short)(xco - U.widget_unit / 2), yco, (short)(width - 1.5f * U.widget_unit), UI_UNIT_Y, &ob->scaflag, 0, 31, 0, 0, TIP_("Object name, click to show/hide controllers"));
+ uiDefButBitS(block, UI_BTYPE_TOGGLE, OB_SHOWCONT, B_REDR, ob->id.name + 2, (short)(xco - U.widget_unit / 2), yco, (short)(width - 1.5f * U.widget_unit), UI_UNIT_Y, &ob->scaflag, 0, 31, 0, 0, TIP_("Object name, click to show/hide controllers"));
RNA_pointer_create((ID *)ob, &RNA_Object, ob, &object_ptr);
uiLayoutSetContextPointer(row, "object", &object_ptr);
@@ -2479,9 +2398,9 @@ void logic_buttons(bContext *C, ARegion *ar)
col = uiLayoutColumn(split, false);
uiLayoutSetActive(col, RNA_boolean_get(&ptr, "active"));
uiLayoutSetAlignment(col, UI_LAYOUT_ALIGN_LEFT);
- but = uiDefIconBut(block, INLINK, 0, ICON_INLINK, 0, 0, UI_UNIT_X, UI_UNIT_Y, cont, LINK_CONTROLLER, 0, 0, 0, "");
+ but = uiDefIconBut(block, UI_BTYPE_INLINK, 0, ICON_INLINK, 0, 0, UI_UNIT_X, UI_UNIT_Y, cont, LINK_CONTROLLER, 0, 0, 0, "");
if (!RNA_boolean_get(&ptr, "active")) {
- uiButSetFlag(but, UI_BUT_SCA_LINK_GREY);
+ UI_but_flag_enable(but, UI_BUT_SCA_LINK_GREY);
}
//col = uiLayoutColumn(split, true);
@@ -2502,22 +2421,22 @@ void logic_buttons(bContext *C, ARegion *ar)
col = uiLayoutColumn(subsplit, false);
uiLayoutSetActive(col, RNA_boolean_get(&ptr, "active"));
uiLayoutSetAlignment(col, UI_LAYOUT_ALIGN_LEFT);
- but = uiDefIconBut(block, LINK, 0, ICON_LINK, 0, 0, UI_UNIT_X, UI_UNIT_Y, NULL, 0, 0, 0, 0, "");
+ but = uiDefIconBut(block, UI_BTYPE_LINK, 0, ICON_LINK, 0, 0, UI_UNIT_X, UI_UNIT_Y, NULL, 0, 0, 0, 0, "");
if (!RNA_boolean_get(&ptr, "active")) {
- uiButSetFlag(but, UI_BUT_SCA_LINK_GREY);
+ UI_but_flag_enable(but, UI_BUT_SCA_LINK_GREY);
}
- uiSetButLink(but, NULL, (void ***)&(cont->links), &cont->totlinks, LINK_CONTROLLER, LINK_ACTUATOR);
+ UI_but_link_set(but, NULL, (void ***)&(cont->links), &cont->totlinks, LINK_CONTROLLER, LINK_ACTUATOR);
}
}
- uiBlockLayoutResolve(block, NULL, &yco); /* stores final height in yco */
+ UI_block_layout_resolve(block, NULL, &yco); /* stores final height in yco */
height = yco;
/* ****************** Sensors ****************** */
xco= U.widget_unit / 2; yco= -U.widget_unit / 2; width= 17 * U.widget_unit;
- layout= uiBlockLayout(block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, xco, yco, width, 20, 0, UI_GetStyle());
+ layout= UI_block_layout(block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, xco, yco, width, 20, 0, UI_style_get());
row = uiLayoutRow(layout, true);
uiDefBlockBut(block, sensor_menu, NULL, IFACE_("Sensors"), xco - U.widget_unit / 2, yco, 15 * U.widget_unit, UI_UNIT_Y, ""); /* replace this with uiLayout stuff later */
@@ -2537,7 +2456,7 @@ void logic_buttons(bContext *C, ARegion *ar)
if ((ob->scavisflag & OB_VIS_SENS) == 0) continue;
row = uiLayoutRow(layout, true);
- uiDefButBitS(block, TOG, OB_SHOWSENS, B_REDR, ob->id.name + 2, (short)(xco - U.widget_unit / 2), yco, (short)(width - 1.5f * U.widget_unit), UI_UNIT_Y, &ob->scaflag, 0, 31, 0, 0, TIP_("Object name, click to show/hide sensors"));
+ uiDefButBitS(block, UI_BTYPE_TOGGLE, OB_SHOWSENS, B_REDR, ob->id.name + 2, (short)(xco - U.widget_unit / 2), yco, (short)(width - 1.5f * U.widget_unit), UI_UNIT_Y, &ob->scaflag, 0, 31, 0, 0, TIP_("Object name, click to show/hide sensors"));
RNA_pointer_create((ID *)ob, &RNA_Object, ob, &object_ptr);
uiLayoutSetContextPointer(row, "object", &object_ptr);
@@ -2575,23 +2494,23 @@ void logic_buttons(bContext *C, ARegion *ar)
/* put link button to the right */
col = uiLayoutColumn(split, false);
uiLayoutSetActive(col, RNA_boolean_get(&ptr, "active"));
- but = uiDefIconBut(block, LINK, 0, ICON_LINK, 0, 0, UI_UNIT_X, UI_UNIT_Y, NULL, 0, 0, 0, 0, "");
+ but = uiDefIconBut(block, UI_BTYPE_LINK, 0, ICON_LINK, 0, 0, UI_UNIT_X, UI_UNIT_Y, NULL, 0, 0, 0, 0, "");
if (!RNA_boolean_get(&ptr, "active")) {
- uiButSetFlag(but, UI_BUT_SCA_LINK_GREY);
+ UI_but_flag_enable(but, UI_BUT_SCA_LINK_GREY);
}
/* use old-school uiButtons for links for now */
- uiSetButLink(but, NULL, (void ***)&sens->links, &sens->totlinks, LINK_SENSOR, LINK_CONTROLLER);
+ UI_but_link_set(but, NULL, (void ***)&sens->links, &sens->totlinks, LINK_SENSOR, LINK_CONTROLLER);
}
}
}
- uiBlockLayoutResolve(block, NULL, &yco); /* stores final height in yco */
+ UI_block_layout_resolve(block, NULL, &yco); /* stores final height in yco */
height = MIN2(height, yco);
/* ****************** Actuators ****************** */
xco= 40 * U.widget_unit; yco= -U.widget_unit / 2; width= 17 * U.widget_unit;
- layout= uiBlockLayout(block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, xco, yco, width, 20, 0, UI_GetStyle());
+ layout= UI_block_layout(block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, xco, yco, width, 20, 0, UI_style_get());
row = uiLayoutRow(layout, true);
uiDefBlockBut(block, actuator_menu, NULL, IFACE_("Actuators"), xco - U.widget_unit / 2, yco, 15 * U.widget_unit, UI_UNIT_Y, ""); /* replace this with uiLayout stuff later */
@@ -2613,7 +2532,7 @@ void logic_buttons(bContext *C, ARegion *ar)
}
row = uiLayoutRow(layout, true);
- uiDefButBitS(block, TOG, OB_SHOWACT, B_REDR, ob->id.name + 2, (short)(xco - U.widget_unit / 2), yco, (short)(width - 1.5f * U.widget_unit), UI_UNIT_Y, &ob->scaflag, 0, 31, 0, 0, TIP_("Object name, click to show/hide actuators"));
+ uiDefButBitS(block, UI_BTYPE_TOGGLE, OB_SHOWACT, B_REDR, ob->id.name + 2, (short)(xco - U.widget_unit / 2), yco, (short)(width - 1.5f * U.widget_unit), UI_UNIT_Y, &ob->scaflag, 0, 31, 0, 0, TIP_("Object name, click to show/hide actuators"));
RNA_pointer_create((ID *)ob, &RNA_Object, ob, &object_ptr);
uiLayoutSetContextPointer(row, "object", &object_ptr);
@@ -2644,9 +2563,9 @@ void logic_buttons(bContext *C, ARegion *ar)
/* put inlink button to the left */
col = uiLayoutColumn(split, false);
uiLayoutSetActive(col, RNA_boolean_get(&ptr, "active"));
- but = uiDefIconBut(block, INLINK, 0, ICON_INLINK, 0, 0, UI_UNIT_X, UI_UNIT_Y, act, LINK_ACTUATOR, 0, 0, 0, "");
+ but = uiDefIconBut(block, UI_BTYPE_INLINK, 0, ICON_INLINK, 0, 0, UI_UNIT_X, UI_UNIT_Y, act, LINK_ACTUATOR, 0, 0, 0, "");
if (!RNA_boolean_get(&ptr, "active")) {
- uiButSetFlag(but, UI_BUT_SCA_LINK_GREY);
+ UI_but_flag_enable(but, UI_BUT_SCA_LINK_GREY);
}
col = uiLayoutColumn(split, true);
@@ -2661,7 +2580,7 @@ void logic_buttons(bContext *C, ARegion *ar)
}
}
}
- uiBlockLayoutResolve(block, NULL, &yco); /* stores final height in yco */
+ UI_block_layout_resolve(block, NULL, &yco); /* stores final height in yco */
height = MIN2(height, yco);
UI_view2d_totRect_set(&ar->v2d, 57.5f * U.widget_unit, height - U.widget_unit);
@@ -2669,10 +2588,10 @@ void logic_buttons(bContext *C, ARegion *ar)
/* set the view */
UI_view2d_view_ortho(&ar->v2d);
- uiComposeLinks(block);
+ UI_block_links_compose(block);
- uiEndBlock(C, block);
- uiDrawBlock(C, block);
+ UI_block_end(C, block);
+ UI_block_draw(C, block);
/* restore view matrix */
UI_view2d_view_restore(C);
diff --git a/source/blender/editors/space_logic/space_logic.c b/source/blender/editors/space_logic/space_logic.c
index 733cac7794e..34a5fee88eb 100644
--- a/source/blender/editors/space_logic/space_logic.c
+++ b/source/blender/editors/space_logic/space_logic.c
@@ -282,7 +282,7 @@ static void logic_buttons_area_init(wmWindowManager *wm, ARegion *ar)
static void logic_buttons_area_draw(const bContext *C, ARegion *ar)
{
- ED_region_panels(C, ar, 1, NULL, -1);
+ ED_region_panels(C, ar, NULL, -1, true);
}
/************************* header region **************************/
diff --git a/source/blender/editors/space_nla/CMakeLists.txt b/source/blender/editors/space_nla/CMakeLists.txt
index a74fc3191b7..c8c64a79945 100644
--- a/source/blender/editors/space_nla/CMakeLists.txt
+++ b/source/blender/editors/space_nla/CMakeLists.txt
@@ -20,13 +20,15 @@
set(INC
../include
- ../../blenfont
../../blenkernel
../../blenlib
+ ../../blentranslation
+ ../../gpu
../../makesdna
../../makesrna
../../windowmanager
../../../../intern/guardedalloc
+ ../../../../intern/glew-mx
)
set(INC_SYS
@@ -49,4 +51,6 @@ if(WITH_INTERNATIONAL)
add_definitions(-DWITH_INTERNATIONAL)
endif()
+add_definitions(${GL_DEFINITIONS})
+
blender_add_lib(bf_editor_space_nla "${SRC}" "${INC}" "${INC_SYS}")
diff --git a/source/blender/editors/space_nla/SConscript b/source/blender/editors/space_nla/SConscript
index a00337e0b58..5bfa8d6c4c2 100644
--- a/source/blender/editors/space_nla/SConscript
+++ b/source/blender/editors/space_nla/SConscript
@@ -31,11 +31,13 @@ sources = env.Glob('*.c')
incs = [
'#/intern/guardedalloc',
- '#/extern/glew/include',
+ env['BF_GLEW_INC'],
+ '#/intern/glew-mx',
'../include',
- '../../blenfont',
'../../blenkernel',
'../../blenlib',
+ '../../blentranslation',
+ '../../gpu',
'../../makesdna',
'../../makesrna',
'../../windowmanager',
@@ -43,6 +45,7 @@ incs = [
incs = ' '.join(incs)
defs = []
+defs += env['BF_GL_DEFINITIONS']
if env['WITH_BF_INTERNATIONAL']:
defs.append('WITH_INTERNATIONAL')
diff --git a/source/blender/editors/space_nla/nla_buttons.c b/source/blender/editors/space_nla/nla_buttons.c
index 1090106d79f..8eead9b8e44 100644
--- a/source/blender/editors/space_nla/nla_buttons.c
+++ b/source/blender/editors/space_nla/nla_buttons.c
@@ -42,7 +42,7 @@
#include "BLI_blenlib.h"
-#include "BLF_translation.h"
+#include "BLT_translation.h"
#include "BKE_nla.h"
#include "BKE_context.h"
@@ -143,6 +143,7 @@ bool nla_panel_context(const bContext *C, PointerRNA *adt_ptr, PointerRNA *nlt_p
case ANIMTYPE_DSLAT:
case ANIMTYPE_DSLINESTYLE:
case ANIMTYPE_DSSPK:
+ case ANIMTYPE_DSGPENCIL:
{
/* for these channels, we only do AnimData */
if (ale->adt && adt_ptr) {
@@ -158,7 +159,9 @@ bool nla_panel_context(const bContext *C, PointerRNA *adt_ptr, PointerRNA *nlt_p
}
/* AnimData pointer */
- RNA_pointer_create(id, &RNA_AnimData, ale->adt, adt_ptr);
+ if (adt_ptr) {
+ RNA_pointer_create(id, &RNA_AnimData, ale->adt, adt_ptr);
+ }
/* set found status to -1, since setting to 1 would break the loop
* and potentially skip an active NLA-Track in some cases...
@@ -254,7 +257,7 @@ static void nla_panel_animdata(const bContext *C, Panel *pa)
/* adt = adt_ptr.data; */
block = uiLayoutGetBlock(layout);
- uiBlockSetHandleFunc(block, do_nla_region_buttons, NULL);
+ UI_block_func_handle_set(block, do_nla_region_buttons, NULL);
/* AnimData Source Properties ----------------------------------- */
@@ -281,7 +284,7 @@ static void nla_panel_animdata(const bContext *C, Panel *pa)
/* Active Action Properties ------------------------------------- */
/* action */
row = uiLayoutRow(layout, true);
- uiTemplateID(row, (bContext *)C, &adt_ptr, "action", "ACTION_OT_new", NULL, NULL /*"ACTION_OT_unlink"*/); // XXX: need to make these operators
+ uiTemplateID(row, (bContext *)C, &adt_ptr, "action", "ACTION_OT_new", NULL, "NLA_OT_action_unlink");
/* extrapolation */
row = uiLayoutRow(layout, true);
@@ -309,7 +312,7 @@ static void nla_panel_track(const bContext *C, Panel *pa)
return;
block = uiLayoutGetBlock(layout);
- uiBlockSetHandleFunc(block, do_nla_region_buttons, NULL);
+ UI_block_func_handle_set(block, do_nla_region_buttons, NULL);
/* Info - Active NLA-Context:Track ---------------------- */
row = uiLayoutRow(layout, true);
@@ -329,7 +332,7 @@ static void nla_panel_properties(const bContext *C, Panel *pa)
return;
block = uiLayoutGetBlock(layout);
- uiBlockSetHandleFunc(block, do_nla_region_buttons, NULL);
+ UI_block_func_handle_set(block, do_nla_region_buttons, NULL);
/* Strip Properties ------------------------------------- */
/* strip type */
@@ -394,7 +397,7 @@ static void nla_panel_actclip(const bContext *C, Panel *pa)
return;
block = uiLayoutGetBlock(layout);
- uiBlockSetHandleFunc(block, do_nla_region_buttons, NULL);
+ UI_block_func_handle_set(block, do_nla_region_buttons, NULL);
/* Strip Properties ------------------------------------- */
/* action pointer */
@@ -434,7 +437,7 @@ static void nla_panel_evaluation(const bContext *C, Panel *pa)
return;
block = uiLayoutGetBlock(layout);
- uiBlockSetHandleFunc(block, do_nla_region_buttons, NULL);
+ UI_block_func_handle_set(block, do_nla_region_buttons, NULL);
col = uiLayoutColumn(layout, true);
uiItemR(col, &strip_ptr, "use_animated_influence", 0, NULL, ICON_NONE);
@@ -468,7 +471,7 @@ static void nla_panel_modifiers(const bContext *C, Panel *pa)
strip = strip_ptr.data;
block = uiLayoutGetBlock(pa->layout);
- uiBlockSetHandleFunc(block, do_nla_region_buttons, NULL);
+ UI_block_func_handle_set(block, do_nla_region_buttons, NULL);
/* 'add modifier' button at top of panel */
{
@@ -477,7 +480,7 @@ static void nla_panel_modifiers(const bContext *C, Panel *pa)
// XXX for now, this will be a operator button which calls a temporary 'add modifier' operator
// FIXME: we need to set the only-active property so that this will only add modifiers for the active strip (not all selected)
- uiDefButO(block, BUT, "NLA_OT_fmodifier_add", WM_OP_INVOKE_REGION_WIN, IFACE_("Add Modifier"), 10, 0, 150, 20,
+ uiDefButO(block, UI_BTYPE_BUT, "NLA_OT_fmodifier_add", WM_OP_INVOKE_REGION_WIN, IFACE_("Add Modifier"), 10, 0, 150, 20,
TIP_("Adds a new F-Modifier for the active NLA Strip"));
/* copy/paste (as sub-row)*/
@@ -504,7 +507,7 @@ void nla_buttons_register(ARegionType *art)
pt = MEM_callocN(sizeof(PanelType), "spacetype nla panel animdata");
strcpy(pt->idname, "NLA_PT_animdata");
strcpy(pt->label, N_("Animation Data"));
- strcpy(pt->translation_context, BLF_I18NCONTEXT_DEFAULT_BPYRNA);
+ strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
pt->draw = nla_panel_animdata;
pt->poll = nla_animdata_panel_poll;
pt->flag = PNL_DEFAULT_CLOSED;
@@ -513,7 +516,7 @@ void nla_buttons_register(ARegionType *art)
pt = MEM_callocN(sizeof(PanelType), "spacetype nla panel track");
strcpy(pt->idname, "NLA_PT_track");
strcpy(pt->label, N_("Active Track"));
- strcpy(pt->translation_context, BLF_I18NCONTEXT_DEFAULT_BPYRNA);
+ strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
pt->draw = nla_panel_track;
pt->poll = nla_track_panel_poll;
BLI_addtail(&art->paneltypes, pt);
@@ -521,7 +524,7 @@ void nla_buttons_register(ARegionType *art)
pt = MEM_callocN(sizeof(PanelType), "spacetype nla panel properties");
strcpy(pt->idname, "NLA_PT_properties");
strcpy(pt->label, N_("Active Strip"));
- strcpy(pt->translation_context, BLF_I18NCONTEXT_DEFAULT_BPYRNA);
+ strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
pt->draw = nla_panel_properties;
pt->poll = nla_strip_panel_poll;
BLI_addtail(&art->paneltypes, pt);
@@ -529,7 +532,7 @@ void nla_buttons_register(ARegionType *art)
pt = MEM_callocN(sizeof(PanelType), "spacetype nla panel properties");
strcpy(pt->idname, "NLA_PT_actionclip");
strcpy(pt->label, N_("Action Clip"));
- strcpy(pt->translation_context, BLF_I18NCONTEXT_DEFAULT_BPYRNA);
+ strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
pt->draw = nla_panel_actclip;
pt->poll = nla_strip_actclip_panel_poll;
BLI_addtail(&art->paneltypes, pt);
@@ -537,7 +540,7 @@ void nla_buttons_register(ARegionType *art)
pt = MEM_callocN(sizeof(PanelType), "spacetype nla panel evaluation");
strcpy(pt->idname, "NLA_PT_evaluation");
strcpy(pt->label, N_("Evaluation"));
- strcpy(pt->translation_context, BLF_I18NCONTEXT_DEFAULT_BPYRNA);
+ strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
pt->draw = nla_panel_evaluation;
pt->poll = nla_strip_eval_panel_poll;
BLI_addtail(&art->paneltypes, pt);
@@ -545,7 +548,7 @@ void nla_buttons_register(ARegionType *art)
pt = MEM_callocN(sizeof(PanelType), "spacetype nla panel modifiers");
strcpy(pt->idname, "NLA_PT_modifiers");
strcpy(pt->label, N_("Modifiers"));
- strcpy(pt->translation_context, BLF_I18NCONTEXT_DEFAULT_BPYRNA);
+ strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
pt->draw = nla_panel_modifiers;
pt->poll = nla_strip_eval_panel_poll;
BLI_addtail(&art->paneltypes, pt);
diff --git a/source/blender/editors/space_nla/nla_channels.c b/source/blender/editors/space_nla/nla_channels.c
index fbb4d273626..a0ea12b8aa0 100644
--- a/source/blender/editors/space_nla/nla_channels.c
+++ b/source/blender/editors/space_nla/nla_channels.c
@@ -182,6 +182,7 @@ static int mouse_nla_channels(bContext *C, bAnimContext *ac, float x, int channe
case ANIMTYPE_DSLAT:
case ANIMTYPE_DSLINESTYLE:
case ANIMTYPE_DSSPK:
+ case ANIMTYPE_DSGPENCIL:
{
/* sanity checking... */
if (ale->adt) {
@@ -290,10 +291,12 @@ static int mouse_nla_channels(bContext *C, bAnimContext *ac, float x, int channe
* the case of users trying to use this to change actions
* - in tweakmode, clicking here gets us out of tweakmode, as changing selection
* while in tweakmode is really evil!
+ * - we disable "solo" flags too, to make it easier to work with stashed actions
+ * with less trouble
*/
if (nlaedit_is_tweakmode_on(ac)) {
/* exit tweakmode immediately */
- nlaedit_disable_tweakmode(ac);
+ nlaedit_disable_tweakmode(ac, true);
/* changes to NLA-Action occurred */
notifierFlags |= ND_NLA_ACTCHANGE;
@@ -503,6 +506,68 @@ void NLA_OT_action_pushdown(wmOperatorType *ot)
RNA_def_property_flag(ot->prop, PROP_SKIP_SAVE);
}
+/* ******************** Action Unlink ******************************** */
+
+static int nla_action_unlink_poll(bContext *C)
+{
+ if (ED_operator_nla_active(C)) {
+ return nla_panel_context(C, NULL, NULL, NULL);
+ }
+
+ /* something failed... */
+ return false;
+}
+
+static int nla_action_unlink_exec(bContext *C, wmOperator *op)
+{
+ PointerRNA adt_ptr;
+ AnimData *adt;
+
+ /* check context and also validity of pointer */
+ if (!nla_panel_context(C, &adt_ptr, NULL, NULL))
+ return OPERATOR_CANCELLED;
+
+ /* get animdata */
+ adt = adt_ptr.data;
+ if (adt == NULL)
+ return OPERATOR_CANCELLED;
+
+ /* do unlinking */
+ if (adt && adt->action) {
+ bool force_delete = RNA_boolean_get(op->ptr, "force_delete");
+ ED_animedit_unlink_action(C, adt_ptr.id.data, adt, adt->action, op->reports, force_delete);
+ }
+
+ return OPERATOR_FINISHED;
+}
+
+static int nla_action_unlink_invoke(bContext *C, wmOperator *op, const wmEvent *evt)
+{
+ /* NOTE: this is hardcoded to match the behaviour for the unlink button (in interface_templates.c) */
+ RNA_boolean_set(op->ptr, "force_delete", evt->shift != 0);
+ return nla_action_unlink_exec(C, op);
+}
+
+void NLA_OT_action_unlink(wmOperatorType *ot)
+{
+ PropertyRNA *prop;
+
+ /* identifiers */
+ ot->name = "Unlink Action";
+ ot->idname = "NLA_OT_action_unlink";
+ ot->description = "Unlink this action from the active action slot (and/or exit Tweak Mode)";
+
+ /* callbacks */
+ ot->invoke = nla_action_unlink_invoke;
+ ot->exec = nla_action_unlink_exec;
+ ot->poll = nla_action_unlink_poll;
+
+ /* properties */
+ prop = RNA_def_boolean(ot->srna, "force_delete", false, "Force Delete",
+ "Clear Fake User and remove copy stashed in this datablock's NLA stack");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+}
+
/* ******************** Add Tracks Operator ***************************** */
/* Add NLA Tracks to the same AnimData block as a selected track, or above the selected tracks */
@@ -649,7 +714,7 @@ static int nlaedit_delete_tracks_exec(bContext *C, wmOperator *UNUSED(op))
return OPERATOR_CANCELLED;
/* get a list of the AnimData blocks being shown in the NLA */
- filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_SEL);
+ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_SEL | ANIMFILTER_NODUPLIS);
ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
/* delete tracks */
@@ -724,7 +789,7 @@ static int nlaedit_objects_add_exec(bContext *C, wmOperator *UNUSED(op))
CTX_DATA_BEGIN (C, Object *, ob, selected_objects)
{
/* ensure that object has AnimData... that's all */
- BKE_id_add_animdata(&ob->id);
+ BKE_animdata_add_id(&ob->id);
}
CTX_DATA_END;
diff --git a/source/blender/editors/space_nla/nla_draw.c b/source/blender/editors/space_nla/nla_draw.c
index ac8dca6e83a..b0adabe4d1d 100644
--- a/source/blender/editors/space_nla/nla_draw.c
+++ b/source/blender/editors/space_nla/nla_draw.c
@@ -59,7 +59,6 @@
#include "WM_types.h"
#include "UI_interface.h"
-#include "UI_interface_icons.h"
#include "UI_resources.h"
#include "UI_view2d.h"
@@ -187,7 +186,7 @@ static void nla_strip_get_color_inside(AnimData *adt, NlaStrip *strip, float col
}
else {
/* Action Clip (default/normal type of strip) */
- if ((strip->flag & NLASTRIP_FLAG_ACTIVE) && (adt && (adt->flag & ADT_NLA_EDIT_ON))) {
+ if (adt && (adt->flag & ADT_NLA_EDIT_ON) && (adt->actstrip == strip)) {
/* active strip should be drawn green when it is acting as the tweaking strip.
* however, this case should be skipped for when not in EditMode...
*/
@@ -274,7 +273,7 @@ static void nla_draw_strip_curves(NlaStrip *strip, float yminc, float ymaxc)
/* main call for drawing a single NLA-strip */
static void nla_draw_strip(SpaceNla *snla, AnimData *adt, NlaTrack *nlt, NlaStrip *strip, View2D *v2d, float yminc, float ymaxc)
{
- short nonSolo = ((adt && (adt->flag & ADT_NLA_SOLO_TRACK)) && (nlt->flag & NLATRACK_SOLO) == 0);
+ const bool non_solo = ((adt && (adt->flag & ADT_NLA_SOLO_TRACK)) && (nlt->flag & NLATRACK_SOLO) == 0);
float color[3];
/* get color of strip */
@@ -283,7 +282,7 @@ static void nla_draw_strip(SpaceNla *snla, AnimData *adt, NlaTrack *nlt, NlaStri
/* draw extrapolation info first (as backdrop)
* - but this should only be drawn if track has some contribution
*/
- if ((strip->extendmode != NLASTRIP_EXTEND_NOTHING) && (nonSolo == 0)) {
+ if ((strip->extendmode != NLASTRIP_EXTEND_NOTHING) && (non_solo == 0)) {
/* enable transparency... */
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_BLEND);
@@ -338,12 +337,12 @@ static void nla_draw_strip(SpaceNla *snla, AnimData *adt, NlaTrack *nlt, NlaStri
/* draw 'inside' of strip itself */
- if (nonSolo == 0) {
+ if (non_solo == 0) {
/* strip is in normal track */
glColor3fv(color);
- uiSetRoundBox(UI_CNR_ALL); /* all corners rounded */
+ UI_draw_roundbox_corner_set(UI_CNR_ALL); /* all corners rounded */
- uiDrawBoxShade(GL_POLYGON, strip->start, yminc, strip->end, ymaxc, 0.0, 0.5, 0.1);
+ UI_draw_roundbox_shade_x(GL_POLYGON, strip->start, yminc, strip->end, ymaxc, 0.0, 0.5, 0.1);
}
else {
/* strip is in disabled track - make less visible */
@@ -375,11 +374,11 @@ static void nla_draw_strip(SpaceNla *snla, AnimData *adt, NlaTrack *nlt, NlaStri
}
/* - line style: dotted for muted */
- if (strip->flag & NLASTRIP_FLAG_MUTED)
+ if ((nlt->flag & NLATRACK_MUTED) || (strip->flag & NLASTRIP_FLAG_MUTED))
setlinestyle(4);
/* draw outline */
- uiDrawBoxShade(GL_LINE_LOOP, strip->start, yminc, strip->end, ymaxc, 0.0, 0.0, 0.1);
+ UI_draw_roundbox_shade_x(GL_LINE_LOOP, strip->start, yminc, strip->end, ymaxc, 0.0, 0.0, 0.1);
/* if action-clip strip, draw lines delimiting repeats too (in the same color as outline) */
if ((strip->type == NLASTRIP_TYPE_CLIP) && IS_EQF(strip->repeat, 1.0f) == 0) {
@@ -423,18 +422,19 @@ static void nla_draw_strip(SpaceNla *snla, AnimData *adt, NlaTrack *nlt, NlaStri
}
/* add the relevant text to the cache of text-strings to draw in pixelspace */
-static void nla_draw_strip_text(AnimData *adt, NlaTrack *nlt, NlaStrip *strip, int index, View2D *v2d, float yminc, float ymaxc)
+static void nla_draw_strip_text(
+ AnimData *adt, NlaTrack *nlt, NlaStrip *strip, int index, View2D *v2d,
+ float xminc, float xmaxc, float yminc, float ymaxc)
{
- short notSolo = ((adt && (adt->flag & ADT_NLA_SOLO_TRACK)) && (nlt->flag & NLATRACK_SOLO) == 0);
+ const bool non_solo = ((adt && (adt->flag & ADT_NLA_SOLO_TRACK)) && (nlt->flag & NLATRACK_SOLO) == 0);
char str[256];
size_t str_len;
char col[4];
- float xofs;
rctf rect;
/* just print the name and the range */
if (strip->flag & NLASTRIP_FLAG_TEMP_META) {
- str_len = BLI_snprintf(str, sizeof(str), "%d) Temp-Meta", index);
+ str_len = BLI_snprintf_rlen(str, sizeof(str), "%d) Temp-Meta", index);
}
else {
str_len = BLI_strncpy_rlen(str, strip->name, sizeof(str));
@@ -449,24 +449,18 @@ static void nla_draw_strip_text(AnimData *adt, NlaTrack *nlt, NlaStrip *strip, i
}
/* text opacity depends on whether if there's a solo'd track, this isn't it */
- if (notSolo == 0)
+ if (non_solo == 0)
col[3] = 255;
else
col[3] = 128;
-
- /* determine the amount of padding required - cannot be constant otherwise looks weird in some cases */
- if ((strip->end - strip->start) <= 5.0f)
- xofs = 0.5f;
- else
- xofs = 1.0f;
-
+
/* set bounding-box for text
* - padding of 2 'units' on either side
*/
// TODO: make this centered?
- rect.xmin = strip->start + xofs;
+ rect.xmin = xminc;
rect.ymin = yminc;
- rect.xmax = strip->end - xofs;
+ rect.xmax = xmaxc;
rect.ymax = ymaxc;
/* add this string to the cache of texts to draw */
@@ -491,11 +485,11 @@ static void nla_draw_strip_frames_text(NlaTrack *UNUSED(nlt), NlaStrip *strip, V
* while also preserving some accuracy, since we do use floats
*/
/* start frame */
- numstr_len = BLI_snprintf(numstr, sizeof(numstr), "%.1f", strip->start);
+ numstr_len = BLI_snprintf_rlen(numstr, sizeof(numstr), "%.1f", strip->start);
UI_view2d_text_cache_add(v2d, strip->start - 1.0f, ymaxc + ytol, numstr, numstr_len, col);
/* end frame */
- numstr_len = BLI_snprintf(numstr, sizeof(numstr), "%.1f", strip->end);
+ numstr_len = BLI_snprintf_rlen(numstr, sizeof(numstr), "%.1f", strip->end);
UI_view2d_text_cache_add(v2d, strip->end, ymaxc + ytol, numstr, numstr_len, col);
}
@@ -511,6 +505,8 @@ void draw_nla_main_data(bAnimContext *ac, SpaceNla *snla, ARegion *ar)
float y = 0.0f;
size_t items;
int height;
+ const float pixelx = BLI_rctf_size_x(&v2d->cur) / BLI_rcti_size_x(&v2d->mask);
+ const float text_margin_x = (8 * UI_DPI_FAC) * pixelx;
/* build list of channels to draw */
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS);
@@ -551,11 +547,16 @@ void draw_nla_main_data(bAnimContext *ac, SpaceNla *snla, ARegion *ar)
/* draw each strip in the track (if visible) */
for (strip = nlt->strips.first, index = 1; strip; strip = strip->next, index++) {
if (BKE_nlastrip_within_bounds(strip, v2d->cur.xmin, v2d->cur.xmax)) {
+ const float xminc = strip->start + text_margin_x;
+ const float xmaxc = strip->end + text_margin_x;
+
/* draw the visualization of the strip */
nla_draw_strip(snla, adt, nlt, strip, v2d, yminc, ymaxc);
/* add the text for this strip to the cache */
- nla_draw_strip_text(adt, nlt, strip, index, v2d, yminc, ymaxc);
+ if (xminc < xmaxc) {
+ nla_draw_strip_text(adt, nlt, strip, index, v2d, xminc, xmaxc, yminc, ymaxc);
+ }
/* if transforming strips (only real reason for temp-metas currently),
* add to the cache the frame numbers of the strip's extents
@@ -619,7 +620,7 @@ void draw_nla_main_data(bAnimContext *ac, SpaceNla *snla, ARegion *ar)
/* *********************************************** */
/* Channel List */
-void draw_nla_channel_list(bContext *C, bAnimContext *ac, ARegion *ar)
+void draw_nla_channel_list(const bContext *C, bAnimContext *ac, ARegion *ar)
{
ListBase anim_data = {NULL, NULL};
bAnimListElem *ale;
@@ -651,6 +652,8 @@ void draw_nla_channel_list(bContext *C, bAnimContext *ac, ARegion *ar)
/* draw channels */
{ /* first pass: just the standard GL-drawing for backdrop + text */
+ size_t channel_index = 0;
+
y = (float)(-NLACHANNEL_HEIGHT(snla));
for (ale = anim_data.first; ale; ale = ale->next) {
@@ -662,15 +665,16 @@ void draw_nla_channel_list(bContext *C, bAnimContext *ac, ARegion *ar)
IN_RANGE(ymaxc, v2d->cur.ymin, v2d->cur.ymax) )
{
/* draw all channels using standard channel-drawing API */
- ANIM_channel_draw(ac, ale, yminc, ymaxc);
+ ANIM_channel_draw(ac, ale, yminc, ymaxc, channel_index);
}
/* adjust y-position for next one */
y -= NLACHANNEL_STEP(snla);
+ channel_index++;
}
}
{ /* second pass: UI widgets */
- uiBlock *block = uiBeginBlock(C, ar, __func__, UI_EMBOSS);
+ uiBlock *block = UI_block_begin(C, ar, __func__, UI_EMBOSS);
size_t channel_index = 0;
y = (float)(-NLACHANNEL_HEIGHT(snla));
@@ -697,8 +701,8 @@ void draw_nla_channel_list(bContext *C, bAnimContext *ac, ARegion *ar)
channel_index++;
}
- uiEndBlock(C, block);
- uiDrawBlock(C, block);
+ UI_block_end(C, block);
+ UI_block_draw(C, block);
glDisable(GL_BLEND);
}
diff --git a/source/blender/editors/space_nla/nla_edit.c b/source/blender/editors/space_nla/nla_edit.c
index c787177a62a..f7673d86f94 100644
--- a/source/blender/editors/space_nla/nla_edit.c
+++ b/source/blender/editors/space_nla/nla_edit.c
@@ -43,7 +43,7 @@
#include "BLI_math.h"
#include "BLI_utildefines.h"
-#include "BLF_translation.h"
+#include "BLT_translation.h"
#include "BKE_action.h"
#include "BKE_fcurve.h"
@@ -111,6 +111,8 @@ static int nlaedit_enable_tweakmode_exec(bContext *C, wmOperator *op)
ListBase anim_data = {NULL, NULL};
bAnimListElem *ale;
int filter;
+
+ const bool do_solo = RNA_boolean_get(op->ptr, "isolate_action");
bool ok = false;
/* get editor data */
@@ -133,6 +135,15 @@ static int nlaedit_enable_tweakmode_exec(bContext *C, wmOperator *op)
/* try entering tweakmode if valid */
ok |= BKE_nla_tweakmode_enter(adt);
+
+ /* mark the active track as being "solo"? */
+ if (do_solo && adt->actstrip) {
+ NlaTrack *nlt = BKE_nlatrack_find_tweaked(adt);
+
+ if (nlt && !(nlt->flag & NLATRACK_SOLO)) {
+ BKE_nlatrack_solo_toggle(adt, nlt);
+ }
+ }
}
/* free temp data */
@@ -159,6 +170,8 @@ static int nlaedit_enable_tweakmode_exec(bContext *C, wmOperator *op)
void NLA_OT_tweakmode_enter(wmOperatorType *ot)
{
+ PropertyRNA *prop;
+
/* identifiers */
ot->name = "Enter Tweak Mode";
ot->idname = "NLA_OT_tweakmode_enter";
@@ -170,16 +183,22 @@ void NLA_OT_tweakmode_enter(wmOperatorType *ot)
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ prop = RNA_def_boolean(ot->srna, "isolate_action", 0, "Isolate Action",
+ "Enable 'solo' on the NLA Track containing the active strip, "
+ "to edit it without seeing the effects of the NLA stack");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
/* ------------- */
/* NLA Editor internal API function for exiting tweakmode */
-bool nlaedit_disable_tweakmode(bAnimContext *ac)
+bool nlaedit_disable_tweakmode(bAnimContext *ac, bool do_solo)
{
ListBase anim_data = {NULL, NULL};
bAnimListElem *ale;
- int filter;
+ int filter;
/* get a list of the AnimData blocks being shown in the NLA */
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_ANIMDATA);
@@ -195,7 +214,14 @@ bool nlaedit_disable_tweakmode(bAnimContext *ac)
for (ale = anim_data.first; ale; ale = ale->next) {
AnimData *adt = ale->data;
- /* to be sure, just exit tweakmode... */
+ /* clear solo flags */
+ if ((do_solo) & (adt->flag & ADT_NLA_SOLO_TRACK) &&
+ (adt->flag & ADT_NLA_EDIT_ON))
+ {
+ BKE_nlatrack_solo_toggle(adt, NULL);
+ }
+
+ /* to be sure that we're doing everything right, just exit tweakmode... */
BKE_nla_tweakmode_exit(adt);
}
@@ -218,9 +244,11 @@ bool nlaedit_disable_tweakmode(bAnimContext *ac)
}
/* exit tweakmode operator callback */
-static int nlaedit_disable_tweakmode_exec(bContext *C, wmOperator *UNUSED(op))
+static int nlaedit_disable_tweakmode_exec(bContext *C, wmOperator *op)
{
bAnimContext ac;
+
+ const bool do_solo = RNA_boolean_get(op->ptr, "isolate_action");
bool ok = false;
/* get editor data */
@@ -228,7 +256,7 @@ static int nlaedit_disable_tweakmode_exec(bContext *C, wmOperator *UNUSED(op))
return OPERATOR_CANCELLED;
/* perform operation */
- ok = nlaedit_disable_tweakmode(&ac);
+ ok = nlaedit_disable_tweakmode(&ac, do_solo);
/* success? */
if (ok)
@@ -239,6 +267,8 @@ static int nlaedit_disable_tweakmode_exec(bContext *C, wmOperator *UNUSED(op))
void NLA_OT_tweakmode_exit(wmOperatorType *ot)
{
+ PropertyRNA *prop;
+
/* identifiers */
ot->name = "Exit Tweak Mode";
ot->idname = "NLA_OT_tweakmode_exit";
@@ -250,6 +280,12 @@ void NLA_OT_tweakmode_exit(wmOperatorType *ot)
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ prop = RNA_def_boolean(ot->srna, "isolate_action", 0, "Isolate Action",
+ "Disable 'solo' on any of the NLA Tracks after exiting tweak mode "
+ "to get things back to normal");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
/* *********************************************** */
@@ -382,7 +418,7 @@ static bool nla_channels_get_selected_extents(bAnimContext *ac, float *min, floa
y = (float)NLACHANNEL_FIRST;
for (ale = anim_data.first; ale; ale = ale->next) {
- bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale);
+ const bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale);
/* must be selected... */
if (acf && acf->has_setting(ac, ale, ACHANNEL_SETTING_SELECT) &&
@@ -1372,11 +1408,15 @@ static int nlaedit_toggle_mute_exec(bContext *C, wmOperator *UNUSED(op))
/* just flip the mute flag for now */
// TODO: have a pre-pass to check if mute all or unmute all?
strip->flag ^= NLASTRIP_FLAG_MUTED;
+
+ /* tag AnimData to get recalculated */
+ ale->update |= ANIM_UPDATE_DEPS;
}
}
}
- /* free temp data */
+ /* cleanup */
+ ANIM_animdata_update(&ac, &anim_data);
ANIM_animdata_freelist(&anim_data);
/* set notifier that things have changed */
@@ -1436,7 +1476,9 @@ static int nlaedit_swap_exec(bContext *C, wmOperator *op)
if (BLI_listbase_is_empty(&nlt->strips) == false) {
NlaStrip *mstrip = (NlaStrip *)nlt->strips.first;
- if ((mstrip->flag & NLASTRIP_FLAG_TEMP_META) && (BLI_countlist(&mstrip->strips) == 2)) {
+ if ((mstrip->flag & NLASTRIP_FLAG_TEMP_META) &&
+ (BLI_listbase_count_ex(&mstrip->strips, 3) == 2))
+ {
/* remove this temp meta, so that we can see the strips inside */
BKE_nlastrips_clear_metas(&nlt->strips, 0, 1);
}
@@ -2128,9 +2170,13 @@ static int nlaedit_snap_exec(bContext *C, wmOperator *op)
/* remove the meta-strips now that we're done */
BKE_nlastrips_clear_metas(&nlt->strips, 0, 1);
+
+ /* tag for recalculating the animation */
+ ale->update |= ANIM_UPDATE_DEPS;
}
- /* free temp data */
+ /* cleanup */
+ ANIM_animdata_update(&ac, &anim_data);
ANIM_animdata_freelist(&anim_data);
/* refresh auto strip properties */
@@ -2174,12 +2220,12 @@ static int nla_fmodifier_add_invoke(bContext *C, wmOperator *UNUSED(op), const w
uiLayout *layout;
int i;
- pup = uiPupMenuBegin(C, IFACE_("Add F-Modifier"), ICON_NONE);
- layout = uiPupMenuLayout(pup);
+ pup = UI_popup_menu_begin(C, IFACE_("Add F-Modifier"), ICON_NONE);
+ layout = UI_popup_menu_layout(pup);
/* start from 1 to skip the 'Invalid' modifier type */
for (i = 1; i < FMODIFIER_NUM_TYPES; i++) {
- FModifierTypeInfo *fmi = get_fmodifier_typeinfo(i);
+ const FModifierTypeInfo *fmi = get_fmodifier_typeinfo(i);
/* check if modifier is valid for this context */
if (fmi == NULL)
@@ -2192,9 +2238,9 @@ static int nla_fmodifier_add_invoke(bContext *C, wmOperator *UNUSED(op), const w
}
uiItemS(layout);
- uiPupMenuEnd(C, pup);
+ UI_popup_menu_end(C, pup);
- return OPERATOR_CANCELLED;
+ return OPERATOR_INTERFACE;
}
static int nla_fmodifier_add_exec(bContext *C, wmOperator *op)
@@ -2244,6 +2290,7 @@ static int nla_fmodifier_add_exec(bContext *C, wmOperator *op)
if (fcm) {
set_active_fmodifier(&strip->modifiers, fcm);
+ ale->update |= ANIM_UPDATE_DEPS;
}
else {
BKE_reportf(op->reports, RPT_ERROR,
@@ -2254,6 +2301,7 @@ static int nla_fmodifier_add_exec(bContext *C, wmOperator *op)
}
/* free temp data */
+ ANIM_animdata_update(&ac, &anim_data);
ANIM_animdata_freelist(&anim_data);
/* set notifier that things have changed */
@@ -2319,6 +2367,9 @@ static int nla_fmodifier_copy_exec(bContext *C, wmOperator *op)
}
}
+ /* free temp data */
+ ANIM_animdata_freelist(&anim_data);
+
/* successful or not? */
if (ok == 0) {
BKE_report(op->reports, RPT_ERROR, "No F-Modifiers available to be copied");
@@ -2373,10 +2424,12 @@ static int nla_fmodifier_paste_exec(bContext *C, wmOperator *op)
for (strip = nlt->strips.first; strip; strip = strip->next) {
// TODO: do we want to replace existing modifiers? add user pref for that!
ok += ANIM_fmodifiers_paste_from_buf(&strip->modifiers, 0);
+ ale->update |= ANIM_UPDATE_DEPS;
}
}
/* clean up */
+ ANIM_animdata_update(&ac, &anim_data);
ANIM_animdata_freelist(&anim_data);
/* successful or not? */
diff --git a/source/blender/editors/space_nla/nla_intern.h b/source/blender/editors/space_nla/nla_intern.h
index 766ae28da6f..344580c0d15 100644
--- a/source/blender/editors/space_nla/nla_intern.h
+++ b/source/blender/editors/space_nla/nla_intern.h
@@ -50,7 +50,7 @@ void NLA_OT_properties(wmOperatorType *ot);
/* nla_draw.c */
void draw_nla_main_data(bAnimContext *ac, SpaceNla *snla, ARegion *ar);
-void draw_nla_channel_list(bContext *C, bAnimContext *ac, ARegion *ar);
+void draw_nla_channel_list(const bContext *C, bAnimContext *ac, ARegion *ar);
/* **************************************** */
/* nla_select.c */
@@ -83,7 +83,7 @@ enum eNlaEdit_Snap_Mode {
/* --- */
-bool nlaedit_disable_tweakmode(bAnimContext *ac);
+bool nlaedit_disable_tweakmode(bAnimContext *ac, bool do_solo);
void NLA_OT_tweakmode_enter(wmOperatorType *ot);
void NLA_OT_tweakmode_exit(wmOperatorType *ot);
@@ -137,6 +137,7 @@ bool nlaedit_add_tracks_empty(bAnimContext *ac);
void NLA_OT_channels_click(wmOperatorType *ot);
void NLA_OT_action_pushdown(wmOperatorType *ot);
+void NLA_OT_action_unlink(wmOperatorType *ot);
void NLA_OT_tracks_add(wmOperatorType *ot);
void NLA_OT_tracks_delete(wmOperatorType *ot);
diff --git a/source/blender/editors/space_nla/nla_ops.c b/source/blender/editors/space_nla/nla_ops.c
index 5e1381db696..98da10470f8 100644
--- a/source/blender/editors/space_nla/nla_ops.c
+++ b/source/blender/editors/space_nla/nla_ops.c
@@ -28,15 +28,11 @@
* \ingroup spnla
*/
-
#include <string.h>
#include <stdio.h>
#include "DNA_scene_types.h"
-
-#include "BLI_blenlib.h"
-
#include "BKE_context.h"
#include "BKE_screen.h"
@@ -118,6 +114,7 @@ void nla_operatortypes(void)
WM_operatortype_append(NLA_OT_channels_click);
WM_operatortype_append(NLA_OT_action_pushdown);
+ WM_operatortype_append(NLA_OT_action_unlink);
WM_operatortype_append(NLA_OT_tracks_add);
WM_operatortype_append(NLA_OT_tracks_delete);
@@ -309,6 +306,7 @@ static void nla_keymap_main(wmKeyConfig *keyconf, wmKeyMap *keymap)
void nla_keymap(wmKeyConfig *keyconf)
{
wmKeyMap *keymap;
+ wmKeyMapItem *kmi;
/* keymap for all regions ------------------------------------------- */
keymap = WM_keymap_find(keyconf, "NLA Generic", SPACE_NLA, 0);
@@ -323,6 +321,16 @@ void nla_keymap(wmKeyConfig *keyconf)
WM_keymap_add_item(keymap, "NLA_OT_tweakmode_enter", TABKEY, KM_PRESS, 0, 0);
WM_keymap_add_item(keymap, "NLA_OT_tweakmode_exit", TABKEY, KM_PRESS, 0, 0);
+ /* tweakmode for stashed actions
+ * - similar to normal tweakmode, except we mark the tracks as being "solo"
+ * too so that the action can be edited in isolation
+ */
+ kmi = WM_keymap_add_item(keymap, "NLA_OT_tweakmode_enter", TABKEY, KM_PRESS, KM_SHIFT, 0);
+ RNA_boolean_set(kmi->ptr, "isolate_action", true);
+
+ kmi = WM_keymap_add_item(keymap, "NLA_OT_tweakmode_exit", TABKEY, KM_PRESS, KM_SHIFT, 0);
+ RNA_boolean_set(kmi->ptr, "isolate_action", true);
+
/* find (i.e. a shortcut for setting the name filter) */
WM_keymap_add_item(keymap, "ANIM_OT_channels_find", FKEY, KM_PRESS, KM_CTRL, 0);
diff --git a/source/blender/editors/space_nla/space_nla.c b/source/blender/editors/space_nla/space_nla.c
index 134e5dd80a2..9fc7b5d6f8f 100644
--- a/source/blender/editors/space_nla/space_nla.c
+++ b/source/blender/editors/space_nla/space_nla.c
@@ -180,7 +180,7 @@ static void nla_init(struct wmWindowManager *UNUSED(wm), ScrArea *sa)
{
SpaceNla *snla = (SpaceNla *)sa->spacedata.first;
- /* init dopesheet data if non-existant (i.e. for old files) */
+ /* init dopesheet data if non-existent (i.e. for old files) */
if (snla->ads == NULL) {
snla->ads = MEM_callocN(sizeof(bDopeSheet), "NlaEdit DopeSheet");
snla->ads->source = (ID *)G.main->scene.first; // XXX this is bad, but we need this to be set correct
@@ -236,7 +236,7 @@ static void nla_channel_area_draw(const bContext *C, ARegion *ar)
/* data */
if (ANIM_animdata_get_context(C, &ac)) {
- draw_nla_channel_list((bContext *)C, &ac, ar);
+ draw_nla_channel_list(C, &ac, ar);
}
/* reset view matrix */
@@ -305,7 +305,7 @@ static void nla_main_area_draw(const bContext *C, ARegion *ar)
/* markers */
UI_view2d_view_orthoSpecial(ar, v2d, 1);
- draw_markers_time(C, 0);
+ ED_markers_draw(C, DRAW_MARKERS_MARGIN);
/* preview range */
UI_view2d_view_ortho(v2d);
@@ -349,7 +349,7 @@ static void nla_buttons_area_init(wmWindowManager *wm, ARegion *ar)
static void nla_buttons_area_draw(const bContext *C, ARegion *ar)
{
- ED_region_panels(C, ar, 1, NULL, -1);
+ ED_region_panels(C, ar, NULL, -1, true);
}
static void nla_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn)
diff --git a/source/blender/editors/space_node/CMakeLists.txt b/source/blender/editors/space_node/CMakeLists.txt
index 6b0460ce5cd..cde818333e4 100644
--- a/source/blender/editors/space_node/CMakeLists.txt
+++ b/source/blender/editors/space_node/CMakeLists.txt
@@ -23,6 +23,7 @@ set(INC
../../blenfont
../../blenkernel
../../blenlib
+ ../../blentranslation
../../imbuf
../../gpu
../../makesdna
@@ -32,6 +33,7 @@ set(INC
../../windowmanager
../../compositor
../../../../intern/guardedalloc
+ ../../../../intern/glew-mx
)
set(INC_SYS
@@ -64,4 +66,6 @@ if(WITH_COMPOSITOR)
add_definitions(-DWITH_COMPOSITOR)
endif()
+add_definitions(${GL_DEFINITIONS})
+
blender_add_lib(bf_editor_space_node "${SRC}" "${INC}" "${INC_SYS}")
diff --git a/source/blender/editors/space_node/SConscript b/source/blender/editors/space_node/SConscript
index 94756b96035..b559b61cf5a 100644
--- a/source/blender/editors/space_node/SConscript
+++ b/source/blender/editors/space_node/SConscript
@@ -1,3 +1,4 @@
+
#!/usr/bin/env python
#
# ***** BEGIN GPL LICENSE BLOCK *****
@@ -31,11 +32,13 @@ sources = env.Glob('*.c')
incs = [
'#/intern/guardedalloc',
- '#/extern/glew/include',
+ env['BF_GLEW_INC'],
+ '#/intern/glew-mx',
'../include',
'../../blenfont',
'../../blenkernel',
'../../blenlib',
+ '../../blentranslation',
'../../compositor',
'../../gpu',
'../../imbuf',
@@ -48,6 +51,8 @@ incs = [
incs = ' '.join(incs)
defs = []
+defs += env['BF_GL_DEFINITIONS']
+
cf = []
if env['OURPLATFORM'] in ('win32-vc', 'win64-vc'):
#cf.append('/WX')
diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c
index 0358c1abce2..ab5874682da 100644
--- a/source/blender/editors/space_node/drawnode.c
+++ b/source/blender/editors/space_node/drawnode.c
@@ -38,6 +38,7 @@
#include "DNA_space_types.h"
#include "DNA_screen_types.h"
#include "DNA_userdef_types.h"
+#include "DNA_text_types.h"
#include "BKE_context.h"
#include "BKE_curve.h"
@@ -47,14 +48,13 @@
#include "BKE_tracking.h"
#include "BLF_api.h"
-#include "BLF_translation.h"
+#include "BLT_translation.h"
#include "BIF_gl.h"
#include "BIF_glutil.h"
#include "RNA_access.h"
#include "RNA_define.h"
-#include "RNA_enum_types.h"
#include "ED_node.h"
@@ -64,7 +64,6 @@
#include "UI_resources.h"
#include "IMB_colormanagement.h"
-#include "IMB_imbuf.h"
#include "IMB_imbuf_types.h"
#include "node_intern.h" /* own include */
@@ -382,7 +381,7 @@ static void node_draw_frame_prepare(const bContext *UNUSED(C), bNodeTree *ntree,
static void node_draw_frame_label(bNodeTree *ntree, bNode *node, const float aspect)
{
/* XXX font id is crap design */
- const int fontid = UI_GetStyle()->widgetlabel.uifont_id;
+ const int fontid = UI_style_get()->widgetlabel.uifont_id;
NodeFrame *data = (NodeFrame *)node->storage;
rctf *rct = &node->totr;
int color_id = node_get_colorid(node);
@@ -391,6 +390,8 @@ static void node_draw_frame_label(bNodeTree *ntree, bNode *node, const float asp
float width, ascender;
float x, y;
const int font_size = data->label_size / aspect;
+ const float margin = (float)(NODE_DY / 4);
+ int label_height;
nodeLabel(ntree, node, label, sizeof(label));
@@ -403,14 +404,54 @@ static void node_draw_frame_label(bNodeTree *ntree, bNode *node, const float asp
width = BLF_width(fontid, label, sizeof(label));
ascender = BLF_ascender(fontid);
+ label_height = ((margin / aspect) + (ascender * aspect));
/* 'x' doesn't need aspect correction */
x = BLI_rctf_cent_x(rct) - (0.5f * width);
- y = rct->ymax - (((NODE_DY / 4) / aspect) + (ascender * aspect));
+ y = rct->ymax - label_height;
BLF_position(fontid, x, y, 0);
BLF_draw(fontid, label, BLF_DRAW_STR_DUMMY_MAX);
+ /* draw text body */
+ if (node->id) {
+ Text *text = (Text *)node->id;
+ TextLine *line;
+ const int line_height_max = BLF_height_max(fontid);
+ const float line_spacing = (line_height_max * aspect);
+ const float line_width = (BLI_rctf_size_x(rct) - margin) / aspect;
+ int y_min;
+
+ /* 'x' doesn't need aspect correction */
+ x = rct->xmin + margin;
+ y = rct->ymax - (label_height + line_spacing);
+ /* early exit */
+ y_min = y + ((margin * 2) - (y - rct->ymin));
+
+ BLF_enable(fontid, BLF_CLIPPING | BLF_WORD_WRAP);
+ BLF_clipping(
+ fontid,
+ rct->xmin,
+ /* round to avoid clipping half-way through a line */
+ y - (floorf(((y - rct->ymin) - (margin * 2)) / line_spacing) * line_spacing),
+ rct->xmin + line_width,
+ rct->ymax);
+
+ BLF_wordwrap(fontid, line_width);
+
+ for (line = text->lines.first; line; line = line->next) {
+ struct ResultBLF info;
+ BLF_position(fontid, x, y, 0);
+ BLF_draw_ex(fontid, line->line, line->len, &info);
+ y -= line_spacing * info.lines;
+ if (y < y_min) {
+ break;
+ }
+ }
+
+ BLF_disable(fontid, BLF_CLIPPING | BLF_WORD_WRAP);
+ }
+
BLF_disable(fontid, BLF_ASPECT);
}
@@ -424,7 +465,7 @@ static void node_draw_frame(const bContext *C, ARegion *ar, SpaceNode *snode,
/* skip if out of view */
if (BLI_rctf_isect(&node->totr, &ar->v2d.cur, NULL) == false) {
- uiEndBlock(C, node->block);
+ UI_block_end(C, node->block);
node->block = NULL;
return;
}
@@ -441,8 +482,8 @@ static void node_draw_frame(const bContext *C, ARegion *ar, SpaceNode *snode,
else
UI_ThemeColor4(TH_NODE_FRAME);
glEnable(GL_BLEND);
- uiSetRoundBox(UI_CNR_ALL);
- uiRoundBox(rct->xmin, rct->ymin, rct->xmax, rct->ymax, BASIS_RAD);
+ UI_draw_roundbox_corner_set(UI_CNR_ALL);
+ UI_draw_roundbox(rct->xmin, rct->ymin, rct->xmax, rct->ymax, BASIS_RAD);
glDisable(GL_BLEND);
/* outline active and selected emphasis */
@@ -454,8 +495,8 @@ static void node_draw_frame(const bContext *C, ARegion *ar, SpaceNode *snode,
UI_ThemeColorShadeAlpha(TH_ACTIVE, 0, -40);
else
UI_ThemeColorShadeAlpha(TH_SELECT, 0, -40);
- uiSetRoundBox(UI_CNR_ALL);
- uiDrawBox(GL_LINE_LOOP,
+ UI_draw_roundbox_corner_set(UI_CNR_ALL);
+ UI_draw_roundbox_gl_mode(GL_LINE_LOOP,
rct->xmin, rct->ymin,
rct->xmax, rct->ymax, BASIS_RAD);
@@ -468,8 +509,8 @@ static void node_draw_frame(const bContext *C, ARegion *ar, SpaceNode *snode,
UI_ThemeClearColor(color_id);
- uiEndBlock(C, node->block);
- uiDrawBlock(C, node->block);
+ UI_block_end(C, node->block);
+ UI_block_draw(C, node->block);
node->block = NULL;
}
@@ -500,6 +541,7 @@ static void node_buts_frame_ex(uiLayout *layout, bContext *UNUSED(C), PointerRNA
{
uiItemR(layout, ptr, "label_size", 0, IFACE_("Label Size"), ICON_NONE);
uiItemR(layout, ptr, "shrink", 0, IFACE_("Shrink"), ICON_NONE);
+ uiItemR(layout, ptr, "text", 0, NULL, ICON_NONE);
}
@@ -546,7 +588,7 @@ static void node_draw_reroute(const bContext *C, ARegion *ar, SpaceNode *UNUSED(
if (node->totr.xmax < ar->v2d.cur.xmin || node->totr.xmin > ar->v2d.cur.xmax ||
node->totr.ymax < ar->v2d.cur.ymin || node->totr.ymin > ar->v2d.cur.ymax)
{
- uiEndBlock(C, node->block);
+ UI_block_end(C, node->block);
node->block = NULL;
return;
}
@@ -556,10 +598,10 @@ static void node_draw_reroute(const bContext *C, ARegion *ar, SpaceNode *UNUSED(
*/
#if 0
/* body */
- uiSetRoundBox(UI_CNR_ALL);
+ UI_draw_roundbox_corner_set(UI_CNR_ALL);
UI_ThemeColor4(TH_NODE);
glEnable(GL_BLEND);
- uiRoundBox(rct->xmin, rct->ymin, rct->xmax, rct->ymax, size);
+ UI_draw_roundbox(rct->xmin, rct->ymin, rct->xmax, rct->ymax, size);
glDisable(GL_BLEND);
/* outline active and selected emphasis */
@@ -571,7 +613,7 @@ static void node_draw_reroute(const bContext *C, ARegion *ar, SpaceNode *UNUSED(
UI_ThemeColorShadeAlpha(TH_TEXT_HI, 0, -40);
else
UI_ThemeColorShadeAlpha(TH_TEXT_HI, -20, -120);
- uiDrawBox(GL_LINE_LOOP, rct->xmin, rct->ymin, rct->xmax, rct->ymax, size);
+ UI_draw_roundbox_gl_mode(GL_LINE_LOOP, rct->xmin, rct->ymin, rct->xmax, rct->ymax, size);
glDisable(GL_LINE_SMOOTH);
glDisable(GL_BLEND);
@@ -581,7 +623,7 @@ static void node_draw_reroute(const bContext *C, ARegion *ar, SpaceNode *UNUSED(
if (node->label[0] != '\0') {
/* draw title (node label) */
BLI_strncpy(showname, node->label, sizeof(showname));
- uiDefBut(node->block, LABEL, 0, showname,
+ uiDefBut(node->block, UI_BTYPE_LABEL, 0, showname,
(int)(rct->xmin - NODE_DYS), (int)(rct->ymax),
(short)512, (short)NODE_DY,
NULL, 0, 0, 0, 0, NULL);
@@ -594,8 +636,8 @@ static void node_draw_reroute(const bContext *C, ARegion *ar, SpaceNode *UNUSED(
node_socket_circle_draw(C, ntree, node, sock, socket_size, (sock->flag & SELECT) || (node->flag & SELECT));
}
- uiEndBlock(C, node->block);
- uiDrawBlock(C, node->block);
+ UI_block_end(C, node->block);
+ UI_block_draw(C, node->block);
node->block = NULL;
}
@@ -605,7 +647,7 @@ static void node_draw_reroute(const bContext *C, ARegion *ar, SpaceNode *UNUSED(
static int node_tweak_area_reroute(bNode *node, int x, int y)
{
/* square of tweak radius */
- static const float tweak_radius_sq = 576; /* 24 * 24 */
+ const float tweak_radius_sq = SQUARE(24);
bNodeSocket *sock = node->inputs.first;
float dx = sock->locx - x;
@@ -671,10 +713,12 @@ static void node_buts_image_user(uiLayout *layout, bContext *C, PointerRNA *ptr,
uiItemR(col, ptr, "use_auto_refresh", 0, NULL, ICON_NONE);
}
- col = uiLayoutColumn(layout, false);
-
- if (RNA_enum_get(imaptr, "type") == IMA_TYPE_MULTILAYER)
+ if (RNA_enum_get(imaptr, "type") == IMA_TYPE_MULTILAYER &&
+ RNA_boolean_get(ptr, "has_layers"))
+ {
+ col = uiLayoutColumn(layout, false);
uiItemR(col, ptr, "layer", 0, NULL, ICON_NONE);
+ }
}
static void node_shader_buts_material(uiLayout *layout, bContext *C, PointerRNA *ptr)
@@ -781,13 +825,15 @@ static void node_shader_buts_tex_image(uiLayout *layout, bContext *C, PointerRNA
uiLayoutSetContextPointer(layout, "image_user", &iuserptr);
uiTemplateID(layout, C, ptr, "image", NULL, "IMAGE_OT_open", NULL);
uiItemR(layout, ptr, "color_space", 0, "", ICON_NONE);
- uiItemR(layout, ptr, "projection", 0, "", ICON_NONE);
uiItemR(layout, ptr, "interpolation", 0, "", ICON_NONE);
+ uiItemR(layout, ptr, "projection", 0, "", ICON_NONE);
if (RNA_enum_get(ptr, "projection") == SHD_PROJ_BOX) {
uiItemR(layout, ptr, "projection_blend", 0, "Blend", ICON_NONE);
}
+ uiItemR(layout, ptr, "extension", 0, "", ICON_NONE);
+
/* note: image user properties used directly here, unlike compositor image node,
* which redefines them in the node struct RNA to get proper updates.
*/
@@ -797,7 +843,7 @@ static void node_shader_buts_tex_image(uiLayout *layout, bContext *C, PointerRNA
static void node_shader_buts_tex_image_ex(uiLayout *layout, bContext *C, PointerRNA *ptr)
{
PointerRNA iuserptr = RNA_pointer_get(ptr, "image_user");
- uiTemplateImage(layout, C, ptr, "image", &iuserptr, 0);
+ uiTemplateImage(layout, C, ptr, "image", &iuserptr, 0, 0);
}
static void node_shader_buts_tex_environment(uiLayout *layout, bContext *C, PointerRNA *ptr)
@@ -807,10 +853,52 @@ static void node_shader_buts_tex_environment(uiLayout *layout, bContext *C, Poin
uiLayoutSetContextPointer(layout, "image_user", &iuserptr);
uiTemplateID(layout, C, ptr, "image", NULL, "IMAGE_OT_open", NULL);
+
+ node_buts_image_user(layout, C, &iuserptr, &imaptr, &iuserptr);
+
uiItemR(layout, ptr, "color_space", 0, "", ICON_NONE);
uiItemR(layout, ptr, "projection", 0, "", ICON_NONE);
+}
- node_buts_image_user(layout, C, &iuserptr, &imaptr, &iuserptr);
+static void node_shader_buts_tex_environment_ex(uiLayout *layout, bContext *C, PointerRNA *ptr)
+{
+ PointerRNA imaptr = RNA_pointer_get(ptr, "image");
+ PointerRNA iuserptr = RNA_pointer_get(ptr, "image_user");
+ Image *ima = imaptr.data;
+
+ uiLayoutSetContextPointer(layout, "image_user", &iuserptr);
+ uiTemplateID(layout, C, ptr, "image", ima ? NULL : "IMAGE_OT_new", "IMAGE_OT_open", NULL);
+
+ if (!ima)
+ return;
+
+ uiItemR(layout, &imaptr, "source", 0, IFACE_("Source"), ICON_NONE);
+
+ if (!(ELEM(ima->source, IMA_SRC_GENERATED, IMA_SRC_VIEWER))) {
+ uiLayout *row = uiLayoutRow(layout, true);
+ const bool is_packed = BKE_image_has_packedfile(ima);
+
+ if (is_packed)
+ uiItemO(row, "", ICON_PACKAGE, "image.unpack");
+ else
+ uiItemO(row, "", ICON_UGLYPACKAGE, "image.pack");
+
+ row = uiLayoutRow(row, true);
+ uiLayoutSetEnabled(row, !is_packed);
+ uiItemR(row, &imaptr, "filepath", 0, "", ICON_NONE);
+ uiItemO(row, "", ICON_FILE_REFRESH, "image.reload");
+ }
+
+ /* multilayer? */
+ if (ima->type == IMA_TYPE_MULTILAYER && ima->rr) {
+ uiTemplateImageLayers(layout, C, ima, iuserptr.data);
+ }
+ else if (ima->source != IMA_SRC_GENERATED) {
+ uiTemplateImageInfo(layout, C, ima, iuserptr.data);
+ }
+
+ uiItemR(layout, ptr, "color_space", 0, IFACE_("Color Space"), ICON_NONE);
+ uiItemR(layout, ptr, "projection", 0, IFACE_("Projection"), ICON_NONE);
}
static void node_shader_buts_tex_sky(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
@@ -861,8 +949,32 @@ static void node_shader_buts_tex_voronoi(uiLayout *layout, bContext *UNUSED(C),
uiItemR(layout, ptr, "coloring", 0, "", ICON_NONE);
}
+static void node_shader_buts_tex_pointdensity(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
+{
+ bNode *node = ptr->data;
+ NodeShaderTexPointDensity *shader_point_density = node->storage;
+
+ uiItemR(layout, ptr, "point_source", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
+ uiItemR(layout, ptr, "object", 0, NULL, ICON_NONE);
+
+ if (node->id && shader_point_density->point_source == SHD_POINTDENSITY_SOURCE_PSYS) {
+ PointerRNA dataptr;
+ RNA_id_pointer_create((ID *)node->id, &dataptr);
+ uiItemPointerR(layout, ptr, "particle_system", &dataptr, "particle_systems", NULL, ICON_NONE);
+ }
+
+ uiItemR(layout, ptr, "space", 0, NULL, ICON_NONE);
+ uiItemR(layout, ptr, "radius", 0, NULL, ICON_NONE);
+ uiItemR(layout, ptr, "interpolation", 0, NULL, ICON_NONE);
+ uiItemR(layout, ptr, "resolution", 0, NULL, ICON_NONE);
+ if (shader_point_density->point_source == SHD_POINTDENSITY_SOURCE_PSYS) {
+ uiItemR(layout, ptr, "color_source", 0, NULL, ICON_NONE);
+ }
+}
+
static void node_shader_buts_tex_coord(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
+ uiItemR(layout, ptr, "object", 0, NULL, 0);
uiItemR(layout, ptr, "from_dupli", 0, NULL, 0);
}
@@ -1073,6 +1185,7 @@ static void node_shader_set_butfunc(bNodeType *ntype)
break;
case SH_NODE_TEX_ENVIRONMENT:
ntype->draw_buttons = node_shader_buts_tex_environment;
+ ntype->draw_buttons_ex = node_shader_buts_tex_environment_ex;
break;
case SH_NODE_TEX_GRADIENT:
ntype->draw_buttons = node_shader_buts_tex_gradient;
@@ -1092,6 +1205,9 @@ static void node_shader_set_butfunc(bNodeType *ntype)
case SH_NODE_TEX_VORONOI:
ntype->draw_buttons = node_shader_buts_tex_voronoi;
break;
+ case SH_NODE_TEX_POINTDENSITY:
+ ntype->draw_buttons = node_shader_buts_tex_pointdensity;
+ break;
case SH_NODE_TEX_COORD:
ntype->draw_buttons = node_shader_buts_tex_coord;
break;
@@ -1139,6 +1255,24 @@ static void node_shader_set_butfunc(bNodeType *ntype)
/* ****************** BUTTON CALLBACKS FOR COMPOSITE NODES ***************** */
+static void node_buts_image_views(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr,
+ PointerRNA *imaptr)
+{
+ uiLayout *col;
+
+ if (!imaptr->data)
+ return;
+
+ col = uiLayoutColumn(layout, false);
+
+ if (RNA_boolean_get(ptr, "has_views")) {
+ if (RNA_enum_get(ptr, "view") == 0)
+ uiItemR(col, ptr, "view", 0, NULL, ICON_CAMERA_STEREO);
+ else
+ uiItemR(col, ptr, "view", 0, NULL, ICON_SCENE);
+ }
+}
+
static void node_composit_buts_image(uiLayout *layout, bContext *C, PointerRNA *ptr)
{
bNode *node = ptr->data;
@@ -1152,6 +1286,8 @@ static void node_composit_buts_image(uiLayout *layout, bContext *C, PointerRNA *
imaptr = RNA_pointer_get(ptr, "image");
node_buts_image_user(layout, C, ptr, &imaptr, &iuserptr);
+
+ node_buts_image_views(layout, C, ptr, &imaptr);
}
static void node_composit_buts_image_ex(uiLayout *layout, bContext *C, PointerRNA *ptr)
@@ -1161,7 +1297,7 @@ static void node_composit_buts_image_ex(uiLayout *layout, bContext *C, PointerRN
RNA_pointer_create((ID *)ptr->id.data, &RNA_ImageUser, node->storage, &iuserptr);
uiLayoutSetContextPointer(layout, "image_user", &iuserptr);
- uiTemplateImage(layout, C, ptr, "image", &iuserptr, 0);
+ uiTemplateImage(layout, C, ptr, "image", &iuserptr, 0, 1);
}
static void node_composit_buts_renderlayers(uiLayout *layout, bContext *C, PointerRNA *ptr)
@@ -1642,8 +1778,8 @@ static void node_composit_buts_id_mask(uiLayout *layout, bContext *UNUSED(C), Po
static void node_composit_buts_file_output(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
PointerRNA imfptr = RNA_pointer_get(ptr, "format");
- int multilayer = (RNA_enum_get(&imfptr, "file_format") == R_IMF_IMTYPE_MULTILAYER);
-
+ const bool multilayer = RNA_enum_get(&imfptr, "file_format") == R_IMF_IMTYPE_MULTILAYER;
+
if (multilayer)
uiItemL(layout, IFACE_("Path:"), ICON_NONE);
else
@@ -1652,15 +1788,22 @@ static void node_composit_buts_file_output(uiLayout *layout, bContext *UNUSED(C)
}
static void node_composit_buts_file_output_ex(uiLayout *layout, bContext *C, PointerRNA *ptr)
{
+ Scene *scene = CTX_data_scene(C);
PointerRNA imfptr = RNA_pointer_get(ptr, "format");
PointerRNA active_input_ptr, op_ptr;
uiLayout *row, *col;
int active_index;
- int multilayer = (RNA_enum_get(&imfptr, "file_format") == R_IMF_IMTYPE_MULTILAYER);
+ const bool multilayer = RNA_enum_get(&imfptr, "file_format") == R_IMF_IMTYPE_MULTILAYER;
+ const bool is_multiview = (scene->r.scemode & R_MULTIVIEW) != 0;
node_composit_buts_file_output(layout, C, ptr);
uiTemplateImageSettings(layout, &imfptr, false);
+ /* disable stereo output for multilayer, too much work for something that no one will use */
+ /* if someone asks for that we can implement it */
+ if (is_multiview)
+ uiTemplateImageFormatViews(layout, &imfptr, NULL);
+
uiItemS(layout);
uiItemO(layout, IFACE_("Add Input"), ICON_ZOOMIN, "NODE_OT_output_file_add_socket");
@@ -1672,13 +1815,13 @@ static void node_composit_buts_file_output_ex(uiLayout *layout, bContext *C, Poi
/* using different collection properties if multilayer format is enabled */
if (multilayer) {
uiTemplateList(col, C, "UI_UL_list", "file_output_node", ptr, "layer_slots", ptr, "active_input_index",
- 0, 0, 0, 0);
+ NULL, 0, 0, 0, 0);
RNA_property_collection_lookup_int(ptr, RNA_struct_find_property(ptr, "layer_slots"),
active_index, &active_input_ptr);
}
else {
uiTemplateList(col, C, "UI_UL_list", "file_output_node", ptr, "file_slots", ptr, "active_input_index",
- 0, 0, 0, 0);
+ NULL, 0, 0, 0, 0);
RNA_property_collection_lookup_int(ptr, RNA_struct_find_property(ptr, "file_slots"),
active_index, &active_input_ptr);
}
@@ -1722,6 +1865,9 @@ static void node_composit_buts_file_output_ex(uiLayout *layout, bContext *C, Poi
col = uiLayoutColumn(layout, false);
uiLayoutSetActive(col, RNA_boolean_get(&active_input_ptr, "use_node_format") == false);
uiTemplateImageSettings(col, &imfptr, false);
+
+ if (is_multiview)
+ uiTemplateImageFormatViews(layout, &imfptr, NULL);
}
}
}
@@ -2015,6 +2161,18 @@ static void node_composit_buts_switch(uiLayout *layout, bContext *UNUSED(C), Poi
uiItemR(layout, ptr, "check", 0, NULL, ICON_NONE);
}
+static void node_composit_buts_switch_view_ex(uiLayout *layout, bContext *UNUSED(C), PointerRNA *UNUSED(ptr))
+{
+ PointerRNA op_ptr;
+ wmOperatorType *ot = WM_operatortype_find("NODE_OT_switch_view_update", 1);
+
+ BLI_assert(ot != 0);
+
+ WM_operator_properties_create_ptr(&op_ptr, ot);
+
+ uiItemFullO_ptr(layout, ot, "Update Views", ICON_FILE_REFRESH, op_ptr.data, WM_OP_INVOKE_DEFAULT, 0);
+}
+
static void node_composit_buts_boxmask(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
uiLayout *row;
@@ -2281,6 +2439,7 @@ static void node_composit_buts_trackpos(uiLayout *layout, bContext *C, PointerRN
static void node_composit_buts_planetrackdeform(uiLayout *layout, bContext *C, PointerRNA *ptr)
{
bNode *node = ptr->data;
+ NodePlaneTrackDeformData *data = node->storage;
uiTemplateID(layout, C, ptr, "clip", NULL, "CLIP_OT_open", NULL);
@@ -2309,6 +2468,12 @@ static void node_composit_buts_planetrackdeform(uiLayout *layout, bContext *C, P
uiItemR(layout, ptr, "plane_track_name", 0, "", ICON_ANIM_DATA);
}
}
+
+ uiItemR(layout, ptr, "use_motion_blur", 0, NULL, ICON_NONE);
+ if (data->flag & CMP_NODEFLAG_PLANETRACKDEFORM_MOTION_BLUR) {
+ uiItemR(layout, ptr, "motion_blur_samples", 0, NULL, ICON_NONE);
+ uiItemR(layout, ptr, "motion_blur_shutter", 0, NULL, ICON_NONE);
+ }
}
static void node_composit_buts_cornerpin(uiLayout *UNUSED(layout), bContext *UNUSED(C), PointerRNA *UNUSED(ptr))
@@ -2505,6 +2670,9 @@ static void node_composit_set_butfunc(bNodeType *ntype)
case CMP_NODE_SWITCH:
ntype->draw_buttons = node_composit_buts_switch;
break;
+ case CMP_NODE_SWITCH_VIEW:
+ ntype->draw_buttons_ex = node_composit_buts_switch_view_ex;
+ break;
case CMP_NODE_MASK_BOX:
ntype->draw_buttons = node_composit_buts_boxmask;
ntype->draw_backdrop = node_composit_backdrop_boxmask;
@@ -2657,7 +2825,7 @@ static void node_texture_buts_image_ex(uiLayout *layout, bContext *C, PointerRNA
PointerRNA iuserptr;
RNA_pointer_create((ID *)ptr->id.data, &RNA_ImageUser, node->storage, &iuserptr);
- uiTemplateImage(layout, C, ptr, "image", &iuserptr, 0);
+ uiTemplateImage(layout, C, ptr, "image", &iuserptr, 0, 0);
}
static void node_texture_buts_output(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
@@ -2877,6 +3045,7 @@ static void node_file_output_socket_draw(bContext *C, uiLayout *layout, PointerR
imfptr = RNA_pointer_get(node_ptr, "format");
imtype = RNA_enum_get(&imfptr, "file_format");
+
if (imtype == R_IMF_IMTYPE_MULTILAYER) {
NodeImageMultiFileSocket *input = sock->storage;
RNA_pointer_create(&ntree->id, &RNA_NodeOutputFileSlotLayer, input, &inputptr);
@@ -2899,9 +3068,9 @@ static void node_file_output_socket_draw(bContext *C, uiLayout *layout, PointerR
RNA_property_enum_name((bContext *)C, &imfptr, imtype_prop,
RNA_property_enum_get(&imfptr, imtype_prop), &imtype_name);
block = uiLayoutGetBlock(row);
- uiBlockSetEmboss(block, UI_EMBOSSP);
+ UI_block_emboss_set(block, UI_EMBOSS_PULLDOWN);
uiItemL(row, imtype_name, ICON_NONE);
- uiBlockSetEmboss(block, UI_EMBOSSN);
+ UI_block_emboss_set(block, UI_EMBOSS_NONE);
}
}
@@ -3055,9 +3224,7 @@ void draw_nodespace_back_pix(const bContext *C, ARegion *ar, SpaceNode *snode, b
/* somehow the offset has to be calculated inverse */
glaDefine2DArea(&ar->winrct);
- /* ortho at pixel level curarea */
- /* almost #wmOrtho2_region_pixelspace, but no +1 px */
- wmOrtho2_pixelspace(ar->winx, ar->winy);
+ wmOrtho2_region_pixelspace(ar);
x = (ar->winx - snode->zoom * ibuf->x) / 2 + snode->xof;
y = (ar->winy - snode->zoom * ibuf->y) / 2 + snode->yof;
@@ -3254,7 +3421,7 @@ int node_link_bezier_points(View2D *v2d, SpaceNode *snode, bNodeLink *link, floa
#define LINK_RESOL 24
#define LINK_ARROW 12 /* position of arrow on the link, LINK_RESOL/2 */
-#define ARROW_SIZE 7
+#define ARROW_SIZE (7 * UI_DPI_FAC)
void node_draw_link_bezier(View2D *v2d, SpaceNode *snode, bNodeLink *link,
int th_col1, bool do_shaded, int th_col2, bool do_triple, int th_col3)
{
@@ -3267,6 +3434,7 @@ void node_draw_link_bezier(View2D *v2d, SpaceNode *snode, bNodeLink *link,
/* store current linewidth */
float linew;
float arrow[2], arrow1[2], arrow2[2];
+ const float px_fac = UI_DPI_WINDOW_FAC;
glGetFloatv(GL_LINE_WIDTH, &linew);
/* we can reuse the dist variable here to increment the GL curve eval amount*/
@@ -3293,7 +3461,7 @@ void node_draw_link_bezier(View2D *v2d, SpaceNode *snode, bNodeLink *link,
}
if (do_triple) {
UI_ThemeColorShadeAlpha(th_col3, -80, -120);
- glLineWidth(4.0f);
+ glLineWidth(4.0f * px_fac);
glBegin(GL_LINE_STRIP);
for (i = 0; i <= LINK_RESOL; i++) {
@@ -3314,7 +3482,7 @@ void node_draw_link_bezier(View2D *v2d, SpaceNode *snode, bNodeLink *link,
* for Intel hardware, this breaks with GL_LINE_STRIP and
* changing color in begin/end blocks.
*/
- glLineWidth(1.5f);
+ glLineWidth(1.5f * px_fac);
if (do_shaded) {
glBegin(GL_LINES);
for (i = 0; i < LINK_RESOL; i++) {
@@ -3444,7 +3612,7 @@ void node_draw_link(View2D *v2d, SpaceNode *snode, bNodeLink *link)
{
bool do_shaded = false;
bool do_triple = false;
- int th_col1 = TH_HEADER, th_col2 = TH_HEADER, th_col3 = TH_WIRE;
+ int th_col1 = TH_WIRE_INNER, th_col2 = TH_WIRE_INNER, th_col3 = TH_WIRE;
if (link->fromsock == NULL && link->tosock == NULL)
return;
diff --git a/source/blender/editors/space_node/node_add.c b/source/blender/editors/space_node/node_add.c
index 02e6f9b69f3..ab7fa51856a 100644
--- a/source/blender/editors/space_node/node_add.c
+++ b/source/blender/editors/space_node/node_add.c
@@ -29,8 +29,6 @@
* \ingroup spnode
*/
-#include <errno.h>
-
#include "MEM_guardedalloc.h"
#include "DNA_node_types.h"
@@ -38,7 +36,7 @@
#include "BLI_listbase.h"
#include "BLI_math.h"
-#include "BLF_translation.h"
+#include "BLT_translation.h"
#include "BKE_context.h"
#include "BKE_image.h"
@@ -227,7 +225,7 @@ static int add_reroute_exec(bContext *C, wmOperator *op)
float insert_point[2];
/* always first */
- ED_preview_kill_jobs(C);
+ ED_preview_kill_jobs(CTX_wm_manager(C), CTX_data_main(C));
node_deselect_all(snode);
@@ -304,33 +302,12 @@ static int node_add_file_exec(bContext *C, wmOperator *op)
{
SpaceNode *snode = CTX_wm_space_node(C);
bNode *node;
- Image *ima = NULL;
+ Image *ima;
int type = 0;
- /* check input variables */
- if (RNA_struct_property_is_set(op->ptr, "filepath")) {
- char path[FILE_MAX];
- RNA_string_get(op->ptr, "filepath", path);
-
- errno = 0;
-
- ima = BKE_image_load_exists(path);
-
- if (!ima) {
- BKE_reportf(op->reports, RPT_ERROR, "Cannot read image '%s': %s",
- path, errno ? strerror(errno) : TIP_("unsupported format"));
- return OPERATOR_CANCELLED;
- }
- }
- else if (RNA_struct_property_is_set(op->ptr, "name")) {
- char name[MAX_ID_NAME - 2];
- RNA_string_get(op->ptr, "name", name);
- ima = (Image *)BKE_libblock_find_name(ID_IM, name);
-
- if (!ima) {
- BKE_reportf(op->reports, RPT_ERROR, "Image '%s' not found", name);
- return OPERATOR_CANCELLED;
- }
+ ima = (Image *)WM_operator_drop_load_path(C, op, ID_IM);
+ if (!ima) {
+ return OPERATOR_CANCELLED;
}
switch (snode->nodetree->type) {
@@ -347,7 +324,7 @@ static int node_add_file_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
- ED_preview_kill_jobs(C);
+ ED_preview_kill_jobs(CTX_wm_manager(C), CTX_data_main(C));
node = node_add_node(C, NULL, type, snode->cursor[0], snode->cursor[1]);
@@ -357,9 +334,14 @@ static int node_add_file_exec(bContext *C, wmOperator *op)
}
node->id = (ID *)ima;
-
- BKE_image_signal(ima, NULL, IMA_SIGNAL_RELOAD);
- WM_event_add_notifier(C, NC_IMAGE | NA_EDITED, ima);
+
+ /* When adding new image file via drag-drop we need to load imbuf in order
+ * to get proper image source.
+ */
+ if (RNA_struct_property_is_set(op->ptr, "filepath")) {
+ BKE_image_signal(ima, NULL, IMA_SIGNAL_RELOAD);
+ WM_event_add_notifier(C, NC_IMAGE | NA_EDITED, ima);
+ }
snode_notify(C, snode);
snode_dag_update(C, snode);
@@ -397,8 +379,8 @@ void NODE_OT_add_file(wmOperatorType *ot)
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- WM_operator_properties_filesel(ot, FOLDERFILE | IMAGEFILE, FILE_SPECIAL, FILE_OPENFILE,
- WM_FILESEL_FILEPATH, FILE_DEFAULTDISPLAY); //XXX TODO, relative_path
+ WM_operator_properties_filesel(ot, FILE_TYPE_FOLDER | FILE_TYPE_IMAGE | FILE_TYPE_MOVIE, FILE_SPECIAL, FILE_OPENFILE,
+ WM_FILESEL_FILEPATH | WM_FILESEL_RELPATH, FILE_DEFAULTDISPLAY, FILE_SORT_ALPHA);
RNA_def_string(ot->srna, "name", "Image", MAX_ID_NAME - 2, "Name", "Datablock name to assign");
}
@@ -426,7 +408,7 @@ static int node_add_mask_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
- ED_preview_kill_jobs(C);
+ ED_preview_kill_jobs(CTX_wm_manager(C), CTX_data_main(C));
node = node_add_node(C, NULL, CMP_NODE_MASK, snode->cursor[0], snode->cursor[1]);
@@ -471,8 +453,8 @@ static int new_node_tree_exec(bContext *C, wmOperator *op)
PointerRNA ptr, idptr;
PropertyRNA *prop;
const char *idname;
- char _treename[MAX_ID_NAME - 2];
- char *treename = _treename;
+ char treename_buf[MAX_ID_NAME - 2];
+ const char *treename;
if (RNA_struct_property_is_set(op->ptr, "type")) {
prop = RNA_struct_find_property(op->ptr, "type");
@@ -484,10 +466,11 @@ static int new_node_tree_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
if (RNA_struct_property_is_set(op->ptr, "name")) {
- RNA_string_get(op->ptr, "name", treename);
+ RNA_string_get(op->ptr, "name", treename_buf);
+ treename = treename_buf;
}
else {
- treename = (char *)DATA_("NodeTree");
+ treename = DATA_("NodeTree");
}
if (!ntreeTypeFind(idname)) {
@@ -498,7 +481,7 @@ static int new_node_tree_exec(bContext *C, wmOperator *op)
ntree = ntreeAddTree(bmain, treename, idname);
/* hook into UI */
- uiIDContextProperty(C, &ptr, &prop);
+ UI_context_active_but_prop_get_templateID(C, &ptr, &prop);
if (prop) {
/* RNA_property_pointer_set increases the user count,
diff --git a/source/blender/editors/space_node/node_buttons.c b/source/blender/editors/space_node/node_buttons.c
index 58d94a28226..52b0292b9a3 100644
--- a/source/blender/editors/space_node/node_buttons.c
+++ b/source/blender/editors/space_node/node_buttons.c
@@ -35,7 +35,7 @@
#include "BLI_math.h"
#include "BLI_blenlib.h"
-#include "BLF_translation.h"
+#include "BLT_translation.h"
#include "BKE_context.h"
#include "BKE_global.h"
@@ -57,6 +57,7 @@
/* ******************* node space & buttons ************** */
+#if 0
/* poll for active nodetree */
static int active_nodetree_poll(const bContext *C, PanelType *UNUSED(pt))
{
@@ -64,6 +65,7 @@ static int active_nodetree_poll(const bContext *C, PanelType *UNUSED(pt))
return (snode && snode->nodetree);
}
+#endif
static int node_sockets_poll(const bContext *C, PanelType *UNUSED(pt))
{
@@ -146,14 +148,14 @@ static void node_tree_interface_panel(const bContext *C, Panel *pa)
col = uiLayoutColumn(split, true);
uiItemL(col, IFACE_("Inputs:"), ICON_NONE);
uiTemplateList(col, (bContext *)C, "NODE_UL_interface_sockets", "inputs", &ptr, "inputs", &ptr, "active_input",
- 0, 0, 0, 0);
+ NULL, 0, 0, 0, 0);
opptr = uiItemFullO(col, "NODE_OT_tree_socket_add", "", ICON_PLUS, NULL, WM_OP_EXEC_DEFAULT, UI_ITEM_O_RETURN_PROPS);
RNA_enum_set(&opptr, "in_out", SOCK_IN);
col = uiLayoutColumn(split, true);
uiItemL(col, IFACE_("Outputs:"), ICON_NONE);
uiTemplateList(col, (bContext *)C, "NODE_UL_interface_sockets", "outputs", &ptr, "outputs", &ptr, "active_output",
- 0, 0, 0, 0);
+ NULL, 0, 0, 0, 0);
opptr = uiItemFullO(col, "NODE_OT_tree_socket_add", "", ICON_PLUS, NULL, WM_OP_EXEC_DEFAULT, UI_ITEM_O_RETURN_PROPS);
RNA_enum_set(&opptr, "in_out", SOCK_OUT);
@@ -184,7 +186,7 @@ void node_buttons_register(ARegionType *art)
pt = MEM_callocN(sizeof(PanelType), "spacetype node panel node sockets");
strcpy(pt->idname, "NODE_PT_sockets");
strcpy(pt->label, N_("Sockets"));
- strcpy(pt->translation_context, BLF_I18NCONTEXT_DEFAULT_BPYRNA);
+ strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
pt->draw = node_sockets_panel;
pt->poll = node_sockets_poll;
pt->flag |= PNL_DEFAULT_CLOSED;
@@ -193,19 +195,10 @@ void node_buttons_register(ARegionType *art)
pt = MEM_callocN(sizeof(PanelType), "spacetype node panel tree interface");
strcpy(pt->idname, "NODE_PT_node_tree_interface");
strcpy(pt->label, N_("Interface"));
- strcpy(pt->translation_context, BLF_I18NCONTEXT_DEFAULT_BPYRNA);
+ strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
pt->draw = node_tree_interface_panel;
pt->poll = node_tree_interface_poll;
BLI_addtail(&art->paneltypes, pt);
-
- pt = MEM_callocN(sizeof(PanelType), "spacetype node panel gpencil");
- strcpy(pt->idname, "NODE_PT_gpencil");
- strcpy(pt->label, N_("Grease Pencil"));
- strcpy(pt->translation_context, BLF_I18NCONTEXT_DEFAULT_BPYRNA);
- pt->draw_header = ED_gpencil_panel_standard_header;
- pt->draw = ED_gpencil_panel_standard;
- pt->poll = active_nodetree_poll;
- BLI_addtail(&art->paneltypes, pt);
}
static int node_properties_toggle_exec(bContext *C, wmOperator *UNUSED(op))
diff --git a/source/blender/editors/space_node/node_draw.c b/source/blender/editors/space_node/node_draw.c
index 7b5ec38f4c6..283457d1fc6 100644
--- a/source/blender/editors/space_node/node_draw.c
+++ b/source/blender/editors/space_node/node_draw.c
@@ -41,7 +41,7 @@
#include "BLI_math.h"
#include "BLI_blenlib.h"
-#include "BLF_translation.h"
+#include "BLT_translation.h"
#include "BKE_context.h"
#include "BKE_depsgraph.h"
@@ -66,10 +66,13 @@
#include "RNA_access.h"
#include "node_intern.h" /* own include */
-#include "COM_compositor.h"
+
+#ifdef WITH_COMPOSITOR
+# include "COM_compositor.h"
+#endif
/* XXX interface.h */
-extern void ui_dropshadow(const rctf *rct, float radius, float aspect, float alpha, int select);
+extern void ui_draw_dropshadow(const rctf *rct, float radius, float aspect, float alpha, int select);
float ED_node_grid_size(void)
{
@@ -120,7 +123,14 @@ void ED_node_tag_update_id(ID *id)
bNodeTree *ntree = node_tree_from_ID(id);
if (id == NULL || ntree == NULL)
return;
-
+
+ /* TODO(sergey): With the new dependency graph it
+ * should be just enough to only tag ntree itself,
+ * all the users of this tree will have update
+ * flushed from the tree,
+ */
+ DAG_id_tag_update(&ntree->id, 0);
+
if (ntree->type == NTREE_SHADER) {
DAG_id_tag_update(id, 0);
@@ -160,14 +170,14 @@ void ED_node_tag_update_nodetree(Main *bmain, bNodeTree *ntree)
ntreeTexCheckCyclics(ntree);
}
-static int compare_nodes(bNode *a, bNode *b)
+static bool compare_nodes(const bNode *a, const bNode *b)
{
bNode *parent;
/* These tell if either the node or any of the parent nodes is selected.
* A selected parent means an unselected node is also in foreground!
*/
- int a_select = (a->flag & NODE_SELECT), b_select = (b->flag & NODE_SELECT);
- int a_active = (a->flag & NODE_ACTIVE), b_active = (b->flag & NODE_ACTIVE);
+ bool a_select = (a->flag & NODE_SELECT) != 0, b_select = (b->flag & NODE_SELECT) != 0;
+ bool a_active = (a->flag & NODE_ACTIVE) != 0, b_active = (b->flag & NODE_ACTIVE) != 0;
/* if one is an ancestor of the other */
/* XXX there might be a better sorting algorithm for stable topological sort, this is O(n^2) worst case */
@@ -214,7 +224,7 @@ void ED_node_sort(bNodeTree *ntree)
{
/* merge sort is the algorithm of choice here */
bNode *first_a, *first_b, *node_a, *node_b, *tmp;
- int totnodes = BLI_countlist(&ntree->nodes);
+ int totnodes = BLI_listbase_count(&ntree->nodes);
int k, a, b;
k = 1;
@@ -283,11 +293,11 @@ static void node_uiblocks_init(const bContext *C, bNodeTree *ntree)
for (node = ntree->nodes.first; node; node = node->next) {
/* ui block */
BLI_snprintf(uiblockstr, sizeof(uiblockstr), "node buttons %p", (void *)node);
- node->block = uiBeginBlock(C, CTX_wm_region(C), uiblockstr, UI_EMBOSS);
- uiBlockSetHandleFunc(node->block, do_node_internal_buttons, node);
+ node->block = UI_block_begin(C, CTX_wm_region(C), uiblockstr, UI_EMBOSS);
+ UI_block_func_handle_set(node->block, do_node_internal_buttons, node);
/* this cancels events for background nodes */
- uiBlockSetFlag(node->block, UI_BLOCK_CLIP_EVENTS);
+ UI_block_flag_enable(node->block, UI_BLOCK_CLIP_EVENTS);
}
}
@@ -298,6 +308,12 @@ void node_to_view(struct bNode *node, float x, float y, float *rx, float *ry)
*ry *= UI_DPI_FAC;
}
+void node_to_updated_rect(struct bNode *node, rctf *r_rect)
+{
+ node_to_view(node, node->offsetx, node->offsety, &r_rect->xmin, &r_rect->ymax);
+ node_to_view(node, node->offsetx + node->width, node->offsety - node->height, &r_rect->xmax, &r_rect->ymin);
+}
+
void node_from_view(struct bNode *node, float x, float y, float *rx, float *ry)
{
x /= UI_DPI_FAC;
@@ -336,8 +352,9 @@ static void node_update_basis(const bContext *C, bNodeTree *ntree, bNode *node)
RNA_pointer_create(&ntree->id, &RNA_NodeSocket, nsock, &sockptr);
- layout = uiBlockLayout(node->block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL,
- locx + NODE_DYS, dy, NODE_WIDTH(node) - NODE_DY, NODE_DY, 0, UI_GetStyle());
+ layout = UI_block_layout(
+ node->block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL,
+ locx + NODE_DYS, dy, NODE_WIDTH(node) - NODE_DY, NODE_DY, 0, UI_style_get());
/* context pointers for current node and socket */
uiLayoutSetContextPointer(layout, "node", &nodeptr);
uiLayoutSetContextPointer(layout, "socket", &sockptr);
@@ -348,8 +365,8 @@ static void node_update_basis(const bContext *C, bNodeTree *ntree, bNode *node)
nsock->typeinfo->draw((bContext *)C, row, &sockptr, &nodeptr, IFACE_(nsock->name));
- uiBlockEndAlign(node->block);
- uiBlockLayoutResolve(node->block, NULL, &buty);
+ UI_block_align_end(node->block);
+ UI_block_layout_resolve(node->block, NULL, &buty);
/* ensure minimum socket height in case layout is empty */
buty = min_ii(buty, dy - NODE_DY);
@@ -407,14 +424,15 @@ static void node_update_basis(const bContext *C, bNodeTree *ntree, bNode *node)
node->butr.ymax = 0;
- layout = uiBlockLayout(node->block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL,
- locx + NODE_DYS, dy, node->butr.xmax, 0, 0, UI_GetStyle());
+ layout = UI_block_layout(
+ node->block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL,
+ locx + NODE_DYS, dy, node->butr.xmax, 0, 0, UI_style_get());
uiLayoutSetContextPointer(layout, "node", &nodeptr);
node->typeinfo->draw_buttons(layout, (bContext *)C, &nodeptr);
- uiBlockEndAlign(node->block);
- uiBlockLayoutResolve(node->block, NULL, &buty);
+ UI_block_align_end(node->block);
+ UI_block_layout_resolve(node->block, NULL, &buty);
dy = buty - NODE_DYS / 2;
}
@@ -426,8 +444,9 @@ static void node_update_basis(const bContext *C, bNodeTree *ntree, bNode *node)
RNA_pointer_create(&ntree->id, &RNA_NodeSocket, nsock, &sockptr);
- layout = uiBlockLayout(node->block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL,
- locx + NODE_DYS, dy, NODE_WIDTH(node) - NODE_DY, NODE_DY, 0, UI_GetStyle());
+ layout = UI_block_layout(
+ node->block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL,
+ locx + NODE_DYS, dy, NODE_WIDTH(node) - NODE_DY, NODE_DY, 0, UI_style_get());
/* context pointers for current node and socket */
uiLayoutSetContextPointer(layout, "node", &nodeptr);
uiLayoutSetContextPointer(layout, "socket", &sockptr);
@@ -436,8 +455,8 @@ static void node_update_basis(const bContext *C, bNodeTree *ntree, bNode *node)
nsock->typeinfo->draw((bContext *)C, row, &sockptr, &nodeptr, IFACE_(nsock->name));
- uiBlockEndAlign(node->block);
- uiBlockLayoutResolve(node->block, NULL, &buty);
+ UI_block_align_end(node->block);
+ UI_block_layout_resolve(node->block, NULL, &buty);
/* ensure minimum socket height in case layout is empty */
buty = min_ii(buty, dy - NODE_DY);
@@ -463,11 +482,12 @@ static void node_update_basis(const bContext *C, bNodeTree *ntree, bNode *node)
/* Set the block bounds to clip mouse events from underlying nodes.
* Add a margin for sockets on each side.
*/
- uiExplicitBoundsBlock(node->block,
- node->totr.xmin - NODE_SOCKSIZE,
- node->totr.ymin,
- node->totr.xmax + NODE_SOCKSIZE,
- node->totr.ymax);
+ UI_block_bounds_set_explicit(
+ node->block,
+ node->totr.xmin - NODE_SOCKSIZE,
+ node->totr.ymin,
+ node->totr.xmax + NODE_SOCKSIZE,
+ node->totr.ymax);
}
/* based on settings in node, sets drawing rect info. each redraw! */
@@ -524,11 +544,12 @@ static void node_update_hidden(bNode *node)
/* Set the block bounds to clip mouse events from underlying nodes.
* Add a margin for sockets on each side.
*/
- uiExplicitBoundsBlock(node->block,
- node->totr.xmin - NODE_SOCKSIZE,
- node->totr.ymin,
- node->totr.xmax + NODE_SOCKSIZE,
- node->totr.ymax);
+ UI_block_bounds_set_explicit(
+ node->block,
+ node->totr.xmin - NODE_SOCKSIZE,
+ node->totr.ymin,
+ node->totr.xmax + NODE_SOCKSIZE,
+ node->totr.ymax);
}
void node_update_default(const bContext *C, bNodeTree *ntree, bNode *node)
@@ -739,16 +760,16 @@ void node_draw_shadow(SpaceNode *snode, bNode *node, float radius, float alpha)
{
rctf *rct = &node->totr;
- uiSetRoundBox(UI_CNR_ALL);
+ UI_draw_roundbox_corner_set(UI_CNR_ALL);
if (node->parent == NULL)
- ui_dropshadow(rct, radius, snode->aspect, alpha, node->flag & SELECT);
+ ui_draw_dropshadow(rct, radius, snode->aspect, alpha, node->flag & SELECT);
else {
const float margin = 3.0f;
glColor4f(0.0f, 0.0f, 0.0f, 0.33f);
glEnable(GL_BLEND);
- uiRoundBox(rct->xmin - margin, rct->ymin - margin,
- rct->xmax + margin, rct->ymax + margin, radius + margin);
+ UI_draw_roundbox(rct->xmin - margin, rct->ymin - margin,
+ rct->xmax + margin, rct->ymax + margin, radius + margin);
glDisable(GL_BLEND);
}
}
@@ -771,7 +792,7 @@ static void node_draw_basis(const bContext *C, ARegion *ar, SpaceNode *snode, bN
/* skip if out of view */
if (BLI_rctf_isect(&node->totr, &ar->v2d.cur, NULL) == false) {
- uiEndBlock(C, node->block);
+ UI_block_end(C, node->block);
node->block = NULL;
return;
}
@@ -800,8 +821,8 @@ static void node_draw_basis(const bContext *C, ARegion *ar, SpaceNode *snode, bN
}
#endif
- uiSetRoundBox(UI_CNR_TOP_LEFT | UI_CNR_TOP_RIGHT);
- uiRoundBox(rct->xmin, rct->ymax - NODE_DY, rct->xmax, rct->ymax, BASIS_RAD);
+ UI_draw_roundbox_corner_set(UI_CNR_TOP_LEFT | UI_CNR_TOP_RIGHT);
+ UI_draw_roundbox(rct->xmin, rct->ymax - NODE_DY, rct->xmax, rct->ymax, BASIS_RAD);
/* show/hide icons */
iconofs = rct->xmax - 0.35f * U.widget_unit;
@@ -810,27 +831,27 @@ static void node_draw_basis(const bContext *C, ARegion *ar, SpaceNode *snode, bN
if (node->typeinfo->flag & NODE_PREVIEW) {
uiBut *but;
iconofs -= iconbutw;
- uiBlockSetEmboss(node->block, UI_EMBOSSN);
- but = uiDefIconBut(node->block, TOGBUT, B_REDR, ICON_MATERIAL,
+ UI_block_emboss_set(node->block, UI_EMBOSS_NONE);
+ but = uiDefIconBut(node->block, UI_BTYPE_BUT_TOGGLE, B_REDR, ICON_MATERIAL,
iconofs, rct->ymax - NODE_DY, iconbutw, UI_UNIT_Y, NULL, 0, 0, 0, 0, "");
- uiButSetFunc(but, node_toggle_button_cb, node, (void *)"NODE_OT_preview_toggle");
+ UI_but_func_set(but, node_toggle_button_cb, node, (void *)"NODE_OT_preview_toggle");
/* XXX this does not work when node is activated and the operator called right afterwards,
* since active ID is not updated yet (needs to process the notifier).
* This can only work as visual indicator!
*/
// if (!(node->flag & (NODE_ACTIVE_ID|NODE_DO_OUTPUT)))
-// uiButSetFlag(but, UI_BUT_DISABLED);
- uiBlockSetEmboss(node->block, UI_EMBOSS);
+// UI_but_flag_enable(but, UI_BUT_DISABLED);
+ UI_block_emboss_set(node->block, UI_EMBOSS);
}
/* group edit */
if (node->type == NODE_GROUP) {
uiBut *but;
iconofs -= iconbutw;
- uiBlockSetEmboss(node->block, UI_EMBOSSN);
- but = uiDefIconBut(node->block, TOGBUT, B_REDR, ICON_NODETREE,
+ UI_block_emboss_set(node->block, UI_EMBOSS_NONE);
+ but = uiDefIconBut(node->block, UI_BTYPE_BUT_TOGGLE, B_REDR, ICON_NODETREE,
iconofs, rct->ymax - NODE_DY, iconbutw, UI_UNIT_Y, NULL, 0, 0, 0, 0, "");
- uiButSetFunc(but, node_toggle_button_cb, node, (void *)"NODE_OT_group_edit");
- uiBlockSetEmboss(node->block, UI_EMBOSS);
+ UI_but_func_set(but, node_toggle_button_cb, node, (void *)"NODE_OT_group_edit");
+ UI_block_emboss_set(node->block, UI_EMBOSS);
}
/* title */
@@ -844,15 +865,15 @@ static void node_draw_basis(const bContext *C, ARegion *ar, SpaceNode *snode, bN
uiBut *but;
int but_size = UI_UNIT_X * 0.6f;
/* XXX button uses a custom triangle draw below, so make it invisible without icon */
- uiBlockSetEmboss(node->block, UI_EMBOSSN);
- but = uiDefBut(node->block, TOGBUT, B_REDR, "",
+ UI_block_emboss_set(node->block, UI_EMBOSS_NONE);
+ but = uiDefBut(node->block, UI_BTYPE_BUT_TOGGLE, B_REDR, "",
rct->xmin + 0.5f * U.widget_unit - but_size / 2, rct->ymax - NODE_DY / 2.0f - but_size / 2,
but_size, but_size, NULL, 0, 0, 0, 0, "");
- uiButSetFunc(but, node_toggle_button_cb, node, (void *)"NODE_OT_hide_toggle");
- uiBlockSetEmboss(node->block, UI_EMBOSS);
+ UI_but_func_set(but, node_toggle_button_cb, node, (void *)"NODE_OT_hide_toggle");
+ UI_block_emboss_set(node->block, UI_EMBOSS);
/* custom draw function for this button */
- UI_DrawTriIcon(rct->xmin + 0.5f * U.widget_unit, rct->ymax - NODE_DY / 2.0f, 'v');
+ UI_draw_icon_tri(rct->xmin + 0.5f * U.widget_unit, rct->ymax - NODE_DY / 2.0f, 'v');
}
/* this isn't doing anything for the label, so commenting out */
@@ -868,7 +889,7 @@ static void node_draw_basis(const bContext *C, ARegion *ar, SpaceNode *snode, bN
//if (node->flag & NODE_MUTED)
// BLI_snprintf(showname, sizeof(showname), "[%s]", showname); /* XXX - don't print into self! */
- uiDefBut(node->block, LABEL, 0, showname,
+ uiDefBut(node->block, UI_BTYPE_LABEL, 0, showname,
(int)(rct->xmin + (NODE_MARGIN_X)), (int)(rct->ymax - NODE_DY),
(short)(iconofs - rct->xmin - 18.0f), (short)NODE_DY,
NULL, 0, 0, 0, 0, "");
@@ -881,8 +902,8 @@ static void node_draw_basis(const bContext *C, ARegion *ar, SpaceNode *snode, bN
else
UI_ThemeColor4(TH_NODE);
glEnable(GL_BLEND);
- uiSetRoundBox(UI_CNR_BOTTOM_LEFT | UI_CNR_BOTTOM_RIGHT);
- uiRoundBox(rct->xmin, rct->ymin, rct->xmax, rct->ymax - NODE_DY, BASIS_RAD);
+ UI_draw_roundbox_corner_set(UI_CNR_BOTTOM_LEFT | UI_CNR_BOTTOM_RIGHT);
+ UI_draw_roundbox(rct->xmin, rct->ymin, rct->xmax, rct->ymax - NODE_DY, BASIS_RAD);
glDisable(GL_BLEND);
/* outline active and selected emphasis */
@@ -896,8 +917,8 @@ static void node_draw_basis(const bContext *C, ARegion *ar, SpaceNode *snode, bN
else
UI_ThemeColorShadeAlpha(TH_SELECT, 0, -40);
- uiSetRoundBox(UI_CNR_ALL);
- uiDrawBox(GL_LINE_LOOP, rct->xmin, rct->ymin, rct->xmax, rct->ymax, BASIS_RAD);
+ UI_draw_roundbox_corner_set(UI_CNR_ALL);
+ UI_draw_roundbox_gl_mode(GL_LINE_LOOP, rct->xmin, rct->ymin, rct->xmax, rct->ymax, BASIS_RAD);
glDisable(GL_LINE_SMOOTH);
glDisable(GL_BLEND);
@@ -936,8 +957,8 @@ static void node_draw_basis(const bContext *C, ARegion *ar, SpaceNode *snode, bN
UI_ThemeClearColor(color_id);
- uiEndBlock(C, node->block);
- uiDrawBlock(C, node->block);
+ UI_block_end(C, node->block);
+ UI_block_draw(C, node->block);
node->block = NULL;
}
@@ -969,7 +990,7 @@ static void node_draw_hidden(const bContext *C, ARegion *ar, SpaceNode *snode, b
(void)ntree;
#endif
- uiRoundBox(rct->xmin, rct->ymin, rct->xmax, rct->ymax, hiddenrad);
+ UI_draw_roundbox(rct->xmin, rct->ymin, rct->xmax, rct->ymax, hiddenrad);
/* outline active and selected emphasis */
if (node->flag & SELECT) {
@@ -980,7 +1001,7 @@ static void node_draw_hidden(const bContext *C, ARegion *ar, SpaceNode *snode, b
UI_ThemeColorShadeAlpha(TH_ACTIVE, 0, -40);
else
UI_ThemeColorShadeAlpha(TH_SELECT, 0, -40);
- uiDrawBox(GL_LINE_LOOP, rct->xmin, rct->ymin, rct->xmax, rct->ymax, hiddenrad);
+ UI_draw_roundbox_gl_mode(GL_LINE_LOOP, rct->xmin, rct->ymin, rct->xmax, rct->ymax, hiddenrad);
glDisable(GL_LINE_SMOOTH);
glDisable(GL_BLEND);
@@ -992,7 +1013,7 @@ static void node_draw_hidden(const bContext *C, ARegion *ar, SpaceNode *snode, b
glEnable(GL_LINE_SMOOTH);
glColor3fv(node->color);
- uiDrawBox(GL_LINE_LOOP, rct->xmin + 1, rct->ymin + 1, rct->xmax -1, rct->ymax - 1, hiddenrad);
+ UI_draw_roundbox_gl_mode(GL_LINE_LOOP, rct->xmin + 1, rct->ymin + 1, rct->xmax -1, rct->ymax - 1, hiddenrad);
glDisable(GL_LINE_SMOOTH);
glDisable(GL_BLEND);
@@ -1009,15 +1030,15 @@ static void node_draw_hidden(const bContext *C, ARegion *ar, SpaceNode *snode, b
uiBut *but;
int but_size = UI_UNIT_X * 0.6f;
/* XXX button uses a custom triangle draw below, so make it invisible without icon */
- uiBlockSetEmboss(node->block, UI_EMBOSSN);
- but = uiDefBut(node->block, TOGBUT, B_REDR, "",
+ UI_block_emboss_set(node->block, UI_EMBOSS_NONE);
+ but = uiDefBut(node->block, UI_BTYPE_BUT_TOGGLE, B_REDR, "",
rct->xmin + 10.0f - but_size / 2, centy - but_size / 2,
but_size, but_size, NULL, 0, 0, 0, 0, "");
- uiButSetFunc(but, node_toggle_button_cb, node, (void *)"NODE_OT_hide_toggle");
- uiBlockSetEmboss(node->block, UI_EMBOSS);
+ UI_but_func_set(but, node_toggle_button_cb, node, (void *)"NODE_OT_hide_toggle");
+ UI_block_emboss_set(node->block, UI_EMBOSS);
/* custom draw function for this button */
- UI_DrawTriIcon(rct->xmin + 10.0f, centy, 'h');
+ UI_draw_icon_tri(rct->xmin + 10.0f, centy, 'h');
}
/* disable lines */
@@ -1035,7 +1056,7 @@ static void node_draw_hidden(const bContext *C, ARegion *ar, SpaceNode *snode, b
//if (node->flag & NODE_MUTED)
// BLI_snprintf(showname, sizeof(showname), "[%s]", showname); /* XXX - don't print into self! */
- uiDefBut(node->block, LABEL, 0, showname,
+ uiDefBut(node->block, UI_BTYPE_LABEL, 0, showname,
(int)(rct->xmin + (NODE_MARGIN_X)), (int)(centy - 10),
(short)(BLI_rctf_size_x(rct) - 18.0f - 12.0f), (short)NODE_DY,
NULL, 0, 0, 0, 0, "");
@@ -1063,8 +1084,8 @@ static void node_draw_hidden(const bContext *C, ARegion *ar, SpaceNode *snode, b
node_socket_circle_draw(C, ntree, node, sock, socket_size, sock->flag & SELECT);
}
- uiEndBlock(C, node->block);
- uiDrawBlock(C, node->block);
+ UI_block_end(C, node->block);
+ UI_block_draw(C, node->block);
node->block = NULL;
}
@@ -1125,6 +1146,9 @@ void node_update_nodetree(const bContext *C, bNodeTree *ntree)
{
bNode *node;
+ /* make sure socket "used" tags are correct, for displaying value buttons */
+ ntreeTagUsedSockets(ntree);
+
/* update nodes front to back, so children sizes get updated before parents */
for (node = ntree->nodes.last; node; node = node->prev) {
node_update(C, ntree, node);
@@ -1243,15 +1267,15 @@ static void draw_group_overlay(const bContext *C, ARegion *ar)
/* shade node groups to separate them visually */
UI_ThemeColorShadeAlpha(TH_NODE_GROUP, 0, -70);
glEnable(GL_BLEND);
- uiSetRoundBox(UI_CNR_NONE);
- uiDrawBox(GL_POLYGON, rect.xmin, rect.ymin, rect.xmax, rect.ymax, 0);
+ UI_draw_roundbox_corner_set(UI_CNR_NONE);
+ UI_draw_roundbox_gl_mode(GL_POLYGON, rect.xmin, rect.ymin, rect.xmax, rect.ymax, 0);
glDisable(GL_BLEND);
/* set the block bounds to clip mouse events from underlying nodes */
- block = uiBeginBlock(C, ar, "node tree bounds block", UI_EMBOSS);
- uiExplicitBoundsBlock(block, rect.xmin, rect.ymin, rect.xmax, rect.ymax);
- uiBlockSetFlag(block, UI_BLOCK_CLIP_EVENTS);
- uiEndBlock(C, block);
+ block = UI_block_begin(C, ar, "node tree bounds block", UI_EMBOSS);
+ UI_block_bounds_set_explicit(block, rect.xmin, rect.ymin, rect.xmax, rect.ymax);
+ UI_block_flag_enable(block, UI_BLOCK_CLIP_EVENTS);
+ UI_block_end(C, block);
}
void drawnodespace(const bContext *C, ARegion *ar)
@@ -1293,6 +1317,11 @@ void drawnodespace(const bContext *C, ARegion *ar)
path = snode->treepath.last;
+ /* update tree path name (drawn in the bottom left) */
+ if (snode->id && UNLIKELY(!STREQ(path->node_name, snode->id->name + 2))) {
+ BLI_strncpy(path->node_name, snode->id->name + 2, sizeof(path->node_name));
+ }
+
/* current View2D center, will be set temporarily for parent node trees */
UI_view2d_center_get(v2d, &center[0], &center[1]);
diff --git a/source/blender/editors/space_node/node_edit.c b/source/blender/editors/space_node/node_edit.c
index ca13d87d632..ffd51bcc44e 100644
--- a/source/blender/editors/space_node/node_edit.c
+++ b/source/blender/editors/space_node/node_edit.c
@@ -31,7 +31,6 @@
#include "MEM_guardedalloc.h"
-#include "DNA_action_types.h"
#include "DNA_lamp_types.h"
#include "DNA_material_types.h"
#include "DNA_node_types.h"
@@ -73,8 +72,6 @@
#include "IMB_imbuf_types.h"
#include "node_intern.h" /* own include */
-#include "NOD_common.h"
-#include "NOD_socket.h"
#include "NOD_composite.h"
#include "NOD_shader.h"
#include "NOD_texture.h"
@@ -96,7 +93,6 @@ typedef struct CompoJob {
const short *stop;
short *do_update;
float *progress;
- short need_sync;
int recalc_flags;
} CompoJob;
@@ -165,13 +161,12 @@ static int compo_breakjob(void *cjv)
);
}
-/* called by compo, wmJob sends notifier, old compositor system only */
-static void compo_statsdrawjob(void *cjv, char *UNUSED(str))
+/* called by compo, wmJob sends notifier */
+static void compo_statsdrawjob(void *cjv, const char *UNUSED(str))
{
CompoJob *cj = cjv;
*(cj->do_update) = true;
- cj->need_sync = true;
}
/* called by compo, wmJob sends notifier */
@@ -205,17 +200,8 @@ static void compo_initjob(void *cjv)
}
/* called before redraw notifiers, it moves finished previews over */
-static void compo_updatejob(void *cjv)
+static void compo_updatejob(void *UNUSED(cjv))
{
- CompoJob *cj = cjv;
-
- if (cj->need_sync) {
- /* was used by old compositor system only */
- ntreeLocalSync(cj->localtree, cj->ntree);
-
- cj->need_sync = false;
- }
-
WM_main_add_notifier(NC_SCENE | ND_COMPO_RESULT, NULL);
}
@@ -226,13 +212,13 @@ static void compo_progressjob(void *cjv, float progress)
*(cj->progress) = progress;
}
-
/* only this runs inside thread */
static void compo_startjob(void *cjv, short *stop, short *do_update, float *progress)
{
CompoJob *cj = cjv;
bNodeTree *ntree = cj->localtree;
Scene *scene = cj->scene;
+ SceneRenderView *srv;
if (scene->use_nodes == false)
return;
@@ -252,7 +238,16 @@ static void compo_startjob(void *cjv, short *stop, short *do_update, float *prog
// XXX BIF_store_spare();
/* 1 is do_previews */
- ntreeCompositExecTree(cj->scene, ntree, &cj->scene->r, false, true, &scene->view_settings, &scene->display_settings);
+
+ if ((cj->scene->r.scemode & R_MULTIVIEW) == 0) {
+ ntreeCompositExecTree(cj->scene, ntree, &cj->scene->r, false, true, &scene->view_settings, &scene->display_settings, "");
+ }
+ else {
+ for (srv = scene->r.views.first; srv; srv = srv->next) {
+ if (BKE_scene_multiview_is_render_view_active(&scene->r, srv) == false) continue;
+ ntreeCompositExecTree(cj->scene, ntree, &cj->scene->r, false, true, &scene->view_settings, &scene->display_settings, srv->name);
+ }
+ }
ntree->test_break = NULL;
ntree->stats_draw = NULL;
@@ -342,14 +337,22 @@ void snode_dag_update(bContext *C, SpaceNode *snode)
void snode_notify(bContext *C, SpaceNode *snode)
{
+ ID *id = snode->id;
+
WM_event_add_notifier(C, NC_NODE | NA_EDITED, NULL);
- if (ED_node_is_shader(snode))
- WM_event_add_notifier(C, NC_MATERIAL | ND_NODES, snode->id);
+ if (ED_node_is_shader(snode)) {
+ if (GS(id->name) == ID_MA)
+ WM_main_add_notifier(NC_MATERIAL | ND_SHADING, id);
+ else if (GS(id->name) == ID_LA)
+ WM_main_add_notifier(NC_LAMP | ND_LIGHTING, id);
+ else if (GS(id->name) == ID_WO)
+ WM_main_add_notifier(NC_WORLD | ND_WORLD, id);
+ }
else if (ED_node_is_compositor(snode))
- WM_event_add_notifier(C, NC_SCENE | ND_NODES, snode->id);
+ WM_event_add_notifier(C, NC_SCENE | ND_NODES, id);
else if (ED_node_is_texture(snode))
- WM_event_add_notifier(C, NC_TEXTURE | ND_NODES, snode->id);
+ WM_event_add_notifier(C, NC_TEXTURE | ND_NODES, id);
}
void ED_node_set_tree_type(SpaceNode *snode, bNodeTreeType *typeinfo)
@@ -561,7 +564,7 @@ void snode_set_context(const bContext *C)
return;
}
- if (snode->nodetree && strcmp(snode->nodetree->idname, snode->tree_idname) != 0) {
+ if (snode->nodetree && !STREQ(snode->nodetree->idname, snode->tree_idname)) {
/* current tree does not match selected type, clear tree path */
ntree = NULL;
id = NULL;
@@ -662,11 +665,16 @@ void ED_node_set_active(Main *bmain, bNodeTree *ntree, bNode *node)
/* if active texture changed, free glsl materials */
if ((node->flag & NODE_ACTIVE_TEXTURE) && !was_active_texture) {
Material *ma;
+ World *wo;
for (ma = bmain->mat.first; ma; ma = ma->id.next)
if (ma->nodetree && ma->use_nodes && ntreeHasTree(ma->nodetree, ntree))
- GPU_material_free(ma);
+ GPU_material_free(&ma->gpumaterial);
+ for (wo = bmain->world.first; wo; wo = wo->id.next)
+ if (wo->nodetree && wo->use_nodes && ntreeHasTree(wo->nodetree, ntree))
+ GPU_material_free(&wo->gpumaterial);
+
WM_main_add_notifier(NC_IMAGE, NULL);
}
@@ -695,7 +703,7 @@ void ED_node_set_active(Main *bmain, bNodeTree *ntree, bNode *node)
for (scene = bmain->scene.first; scene; scene = scene->id.next) {
if (scene->nodetree && scene->use_nodes && ntreeHasTree(scene->nodetree, ntree)) {
if (node->id == NULL || node->id == (ID *)scene) {
- int num_layers = BLI_countlist(&scene->r.layers);
+ int num_layers = BLI_listbase_count(&scene->r.layers);
scene->r.actlay = node->custom1;
/* Clamp the value, because it might have come from a different
* scene which could have more render layers than new one.
@@ -732,6 +740,34 @@ void ED_node_set_active(Main *bmain, bNodeTree *ntree, bNode *node)
}
}
+void ED_node_id_unref(SpaceNode *snode, const ID *id)
+{
+ if (GS(id->name) == ID_SCE) {
+ if (snode->id == id) {
+ /* nasty DNA logic for SpaceNode:
+ * ideally should be handled by editor code, but would be bad level call
+ */
+ bNodeTreePath *path, *path_next;
+ for (path = snode->treepath.first; path; path = path_next) {
+ path_next = path->next;
+ MEM_freeN(path);
+ }
+ BLI_listbase_clear(&snode->treepath);
+
+ snode->id = NULL;
+ snode->from = NULL;
+ snode->nodetree = NULL;
+ snode->edittree = NULL;
+ }
+ }
+ else if (GS(id->name) == ID_OB) {
+ if (snode->from == id) {
+ snode->flag &= ~SNODE_PIN;
+ snode->from = NULL;
+ }
+ }
+}
+
void ED_node_post_apply_transform(bContext *UNUSED(C), bNodeTree *UNUSED(ntree))
{
/* XXX This does not work due to layout functions relying on node->block,
@@ -1142,7 +1178,7 @@ static int node_duplicate_exec(bContext *C, wmOperator *op)
bNodeLink *link, *newlink, *lastlink;
const bool keep_inputs = RNA_boolean_get(op->ptr, "keep_inputs");
- ED_preview_kill_jobs(C);
+ ED_preview_kill_jobs(CTX_wm_manager(C), CTX_data_main(C));
lastnode = ntree->nodes.last;
for (node = ntree->nodes.first; node; node = node->next) {
@@ -1277,7 +1313,7 @@ static int node_read_renderlayers_exec(bContext *C, wmOperator *UNUSED(op))
Scene *curscene = CTX_data_scene(C), *scene;
bNode *node;
- ED_preview_kill_jobs(C);
+ ED_preview_kill_jobs(CTX_wm_manager(C), bmain);
/* first tag scenes unread */
for (scene = bmain->scene.first; scene; scene = scene->id.next)
@@ -1476,7 +1512,7 @@ static int node_preview_toggle_exec(bContext *C, wmOperator *UNUSED(op))
if ((snode == NULL) || (snode->edittree == NULL))
return OPERATOR_CANCELLED;
- ED_preview_kill_jobs(C);
+ ED_preview_kill_jobs(CTX_wm_manager(C), CTX_data_main(C));
node_flag_toggle_exec(snode, NODE_PREVIEW);
@@ -1540,7 +1576,7 @@ static int node_socket_toggle_exec(bContext *C, wmOperator *UNUSED(op))
if ((snode == NULL) || (snode->edittree == NULL))
return OPERATOR_CANCELLED;
- ED_preview_kill_jobs(C);
+ ED_preview_kill_jobs(CTX_wm_manager(C), CTX_data_main(C));
/* Toggle for all selected nodes */
hidden = 0;
@@ -1588,7 +1624,7 @@ static int node_mute_exec(bContext *C, wmOperator *UNUSED(op))
SpaceNode *snode = CTX_wm_space_node(C);
bNode *node;
- ED_preview_kill_jobs(C);
+ ED_preview_kill_jobs(CTX_wm_manager(C), CTX_data_main(C));
for (node = snode->edittree->nodes.first; node; node = node->next) {
/* Only allow muting of nodes having a mute func! */
@@ -1626,7 +1662,7 @@ static int node_delete_exec(bContext *C, wmOperator *UNUSED(op))
SpaceNode *snode = CTX_wm_space_node(C);
bNode *node, *next;
- ED_preview_kill_jobs(C);
+ ED_preview_kill_jobs(CTX_wm_manager(C), CTX_data_main(C));
for (node = snode->edittree->nodes.first; node; node = next) {
next = node->next;
@@ -1661,13 +1697,61 @@ void NODE_OT_delete(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
+/* ****************** Switch View ******************* */
+
+static int node_switch_view_poll(bContext *C)
+{
+ SpaceNode *snode = CTX_wm_space_node(C);
+
+ if (snode && snode->edittree)
+ return true;
+
+ return false;
+}
+
+static int node_switch_view_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ SpaceNode *snode = CTX_wm_space_node(C);
+ bNode *node, *next;
+
+ for (node = snode->edittree->nodes.first; node; node = next) {
+ next = node->next;
+ if (node->flag & SELECT) {
+ /* call the update function from the Switch View node */
+ node->update = NODE_UPDATE_OPERATOR;
+ }
+ }
+
+ ntreeUpdateTree(CTX_data_main(C), snode->edittree);
+
+ snode_notify(C, snode);
+ snode_dag_update(C, snode);
+
+ return OPERATOR_FINISHED;
+}
+
+void NODE_OT_switch_view_update(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Update Views";
+ ot->description = "Update views of selected node";
+ ot->idname = "NODE_OT_switch_view_update";
+
+ /* api callbacks */
+ ot->exec = node_switch_view_exec;
+ ot->poll = node_switch_view_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
/* ****************** Delete with reconnect ******************* */
static int node_delete_reconnect_exec(bContext *C, wmOperator *UNUSED(op))
{
SpaceNode *snode = CTX_wm_space_node(C);
bNode *node, *next;
- ED_preview_kill_jobs(C);
+ ED_preview_kill_jobs(CTX_wm_manager(C), CTX_data_main(C));
for (node = snode->edittree->nodes.first; node; node = next) {
next = node->next;
@@ -1924,7 +2008,7 @@ static int node_clipboard_copy_exec(bContext *C, wmOperator *UNUSED(op))
bNode *node;
bNodeLink *link, *newlink;
- ED_preview_kill_jobs(C);
+ ED_preview_kill_jobs(CTX_wm_manager(C), CTX_data_main(C));
/* clear current clipboard */
BKE_node_clipboard_clear();
@@ -2037,7 +2121,7 @@ static int node_clipboard_paste_exec(bContext *C, wmOperator *op)
if (!all_nodes_valid)
return OPERATOR_CANCELLED;
- ED_preview_kill_jobs(C);
+ ED_preview_kill_jobs(CTX_wm_manager(C), CTX_data_main(C));
/* deselect old nodes */
node_deselect_all(snode);
@@ -2445,7 +2529,7 @@ static int viewer_border_exec(bContext *C, wmOperator *op)
void *lock;
ImBuf *ibuf;
- ED_preview_kill_jobs(C);
+ ED_preview_kill_jobs(CTX_wm_manager(C), CTX_data_main(C));
ima = BKE_image_verify_viewer(IMA_TYPE_COMPOSITE, "Viewer Node");
ibuf = BKE_image_acquire_ibuf(ima, NULL, &lock);
diff --git a/source/blender/editors/space_node/node_group.c b/source/blender/editors/space_node/node_group.c
index 96cc7fb4407..b57f95db4e6 100644
--- a/source/blender/editors/space_node/node_group.c
+++ b/source/blender/editors/space_node/node_group.c
@@ -39,7 +39,7 @@
#include "BLI_listbase.h"
#include "BLI_math.h"
-#include "BLF_translation.h"
+#include "BLT_translation.h"
#include "BKE_action.h"
#include "BKE_animsys.h"
@@ -55,7 +55,6 @@
#include "RNA_access.h"
#include "RNA_define.h"
-#include "RNA_enum_types.h"
#include "WM_api.h"
#include "WM_types.h"
@@ -64,7 +63,6 @@
#include "node_intern.h" /* own include */
#include "NOD_common.h"
-#include "NOD_socket.h"
static int node_group_operator_active(bContext *C)
{
@@ -144,7 +142,7 @@ static int node_group_edit_exec(bContext *C, wmOperator *op)
bNode *gnode;
const bool exit = RNA_boolean_get(op->ptr, "exit");
- ED_preview_kill_jobs(C);
+ ED_preview_kill_jobs(CTX_wm_manager(C), CTX_data_main(C));
gnode = node_group_get_active(C, node_idname);
@@ -352,7 +350,7 @@ static int node_group_ungroup_exec(bContext *C, wmOperator *op)
const char *node_idname = group_node_idname(C);
bNode *gnode;
- ED_preview_kill_jobs(C);
+ ED_preview_kill_jobs(CTX_wm_manager(C), CTX_data_main(C));
gnode = node_group_get_active(C, node_idname);
if (!gnode)
@@ -458,8 +456,8 @@ static int node_group_separate_selected(bNodeTree *ntree, bNodeTree *ngroup, flo
/* add internal links to the ntree */
for (link = ngroup->links.first; link; link = link_next) {
- int fromselect = (link->fromnode && (link->fromnode->flag & NODE_SELECT));
- int toselect = (link->tonode && (link->tonode->flag & NODE_SELECT));
+ const bool fromselect = (link->fromnode && (link->fromnode->flag & NODE_SELECT));
+ const bool toselect = (link->tonode && (link->tonode->flag & NODE_SELECT));
link_next = link->next;
if (make_copy) {
@@ -522,7 +520,7 @@ static int node_group_separate_exec(bContext *C, wmOperator *op)
int type = RNA_enum_get(op->ptr, "type");
float offx, offy;
- ED_preview_kill_jobs(C);
+ ED_preview_kill_jobs(CTX_wm_manager(C), CTX_data_main(C));
/* are we inside of a group? */
ngroup = snode->edittree;
@@ -562,16 +560,16 @@ static int node_group_separate_exec(bContext *C, wmOperator *op)
static int node_group_separate_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *UNUSED(event))
{
- uiPopupMenu *pup = uiPupMenuBegin(C, CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Separate"), ICON_NONE);
- uiLayout *layout = uiPupMenuLayout(pup);
+ uiPopupMenu *pup = UI_popup_menu_begin(C, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Separate"), ICON_NONE);
+ uiLayout *layout = UI_popup_menu_layout(pup);
uiLayoutSetOperatorContext(layout, WM_OP_EXEC_DEFAULT);
uiItemEnumO(layout, "NODE_OT_group_separate", NULL, 0, "type", NODE_GS_COPY);
uiItemEnumO(layout, "NODE_OT_group_separate", NULL, 0, "type", NODE_GS_MOVE);
- uiPupMenuEnd(C, pup);
+ UI_popup_menu_end(C, pup);
- return OPERATOR_CANCELLED;
+ return OPERATOR_INTERFACE;
}
void NODE_OT_group_separate(wmOperatorType *ot)
@@ -915,7 +913,7 @@ static int node_group_make_exec(bContext *C, wmOperator *op)
bNode *gnode;
Main *bmain = CTX_data_main(C);
- ED_preview_kill_jobs(C);
+ ED_preview_kill_jobs(CTX_wm_manager(C), CTX_data_main(C));
if (!node_group_make_test_selected(ntree, NULL, ntree_idname, op->reports))
return OPERATOR_CANCELLED;
@@ -966,7 +964,7 @@ static int node_group_insert_exec(bContext *C, wmOperator *op)
bNode *gnode;
Main *bmain = CTX_data_main(C);
- ED_preview_kill_jobs(C);
+ ED_preview_kill_jobs(CTX_wm_manager(C), CTX_data_main(C));
gnode = node_group_get_active(C, node_idname);
diff --git a/source/blender/editors/space_node/node_intern.h b/source/blender/editors/space_node/node_intern.h
index 9598ff190c0..b08c9b10eeb 100644
--- a/source/blender/editors/space_node/node_intern.h
+++ b/source/blender/editors/space_node/node_intern.h
@@ -42,12 +42,9 @@ struct ARegionType;
struct View2D;
struct bContext;
struct wmWindow;
-struct wmWindowManager;
-struct wmEvent;
struct bNode;
struct bNodeSocket;
struct bNodeLink;
-struct Main;
struct wmKeyConfig;
/* temp data to pass on to modal */
@@ -87,6 +84,7 @@ void drawnodespace(const bContext *C, ARegion *ar);
void node_set_cursor(struct wmWindow *win, struct SpaceNode *snode, float cursor[2]);
/* DPI scaled coords */
void node_to_view(struct bNode *node, float x, float y, float *rx, float *ry);
+void node_to_updated_rect(struct bNode *node, rctf *r_rect);
void node_from_view(struct bNode *node, float x, float y, float *rx, float *ry);
/* node_buttons.c */
@@ -163,13 +161,14 @@ void NODE_OT_links_cut(struct wmOperatorType *ot);
void NODE_OT_links_detach(struct wmOperatorType *ot);
void NODE_OT_parent_set(struct wmOperatorType *ot);
-void NODE_OT_parent_clear(struct wmOperatorType *ot);
void NODE_OT_join(struct wmOperatorType *ot);
void NODE_OT_attach(struct wmOperatorType *ot);
void NODE_OT_detach(struct wmOperatorType *ot);
void NODE_OT_link_viewer(struct wmOperatorType *ot);
+void NODE_OT_insert_offset(wmOperatorType *ot);
+
/* node_edit.c */
void snode_notify(struct bContext *C, struct SpaceNode *snode);
void snode_dag_update(struct bContext *C, struct SpaceNode *snode);
@@ -204,6 +203,8 @@ void NODE_OT_output_file_add_socket(struct wmOperatorType *ot);
void NODE_OT_output_file_remove_active_socket(struct wmOperatorType *ot);
void NODE_OT_output_file_move_active_socket(struct wmOperatorType *ot);
+void NODE_OT_switch_view_update (struct wmOperatorType *ot);
+
/* Note: clipboard_cut is a simple macro of copy + delete */
void NODE_OT_clipboard_copy(struct wmOperatorType *ot);
void NODE_OT_clipboard_paste(struct wmOperatorType *ot);
@@ -227,7 +228,8 @@ extern const char *node_context_dir[];
#define NODE_DYS (U.widget_unit / 2)
#define NODE_DY U.widget_unit
#define NODE_SOCKDY (0.08f * U.widget_unit)
-#define NODE_WIDTH(node) (node->width * UI_DPI_FAC)
+#define NODE_WIDTH(node) (node->width * UI_DPI_FAC)
+#define NODE_HEIGHT(node) (node->height * UI_DPI_FAC)
#define NODE_MARGIN_X (0.75f * U.widget_unit)
#define NODE_SOCKSIZE (0.25f * U.widget_unit)
#define NODE_LINK_RESOL 12
diff --git a/source/blender/editors/space_node/node_ops.c b/source/blender/editors/space_node/node_ops.c
index 7dcbeae4627..96f0e69ca71 100644
--- a/source/blender/editors/space_node/node_ops.c
+++ b/source/blender/editors/space_node/node_ops.c
@@ -92,6 +92,8 @@ void node_operatortypes(void)
WM_operatortype_append(NODE_OT_link_viewer);
+ WM_operatortype_append(NODE_OT_insert_offset);
+
WM_operatortype_append(NODE_OT_read_renderlayers);
WM_operatortype_append(NODE_OT_read_fullsamplelayers);
WM_operatortype_append(NODE_OT_render_changed);
@@ -111,7 +113,6 @@ void node_operatortypes(void)
WM_operatortype_append(NODE_OT_output_file_move_active_socket);
WM_operatortype_append(NODE_OT_parent_set);
- WM_operatortype_append(NODE_OT_parent_clear);
WM_operatortype_append(NODE_OT_join);
WM_operatortype_append(NODE_OT_attach);
WM_operatortype_append(NODE_OT_detach);
@@ -124,6 +125,8 @@ void node_operatortypes(void)
WM_operatortype_append(NODE_OT_viewer_border);
WM_operatortype_append(NODE_OT_clear_viewer_border);
+ WM_operatortype_append(NODE_OT_switch_view_update);
+
WM_operatortype_append(NODE_OT_tree_socket_add);
WM_operatortype_append(NODE_OT_tree_socket_remove);
WM_operatortype_append(NODE_OT_tree_socket_move);
@@ -146,7 +149,22 @@ void ED_operatormacros_node(void)
mot = WM_operatortype_macro_define(ot, "TRANSFORM_OT_translate");
RNA_boolean_set(mot->ptr, "release_confirm", true);
WM_operatortype_macro_define(ot, "NODE_OT_attach");
+ WM_operatortype_macro_define(ot, "NODE_OT_insert_offset");
+
+ /* NODE_OT_translate_attach with remove_on_canel set to true */
+ ot = WM_operatortype_append_macro("NODE_OT_translate_attach_remove_on_cancel", "Move and Attach",
+ "Move nodes and attach to frame",
+ OPTYPE_UNDO | OPTYPE_REGISTER);
+ mot = WM_operatortype_macro_define(ot, "TRANSFORM_OT_translate");
+ RNA_boolean_set(mot->ptr, "release_confirm", true);
+ RNA_boolean_set(mot->ptr, "remove_on_cancel", true);
+ WM_operatortype_macro_define(ot, "NODE_OT_attach");
+ WM_operatortype_macro_define(ot, "NODE_OT_insert_offset");
+ /* Note: Currently not in a default keymap or menu due to messy keymaps
+ * and tricky invoke functionality.
+ * Kept around in case users want to make own shortcuts.
+ */
ot = WM_operatortype_append_macro("NODE_OT_detach_translate_attach", "Detach and Move",
"Detach nodes, move and attach to frame",
OPTYPE_UNDO | OPTYPE_REGISTER);
@@ -173,6 +191,7 @@ void ED_operatormacros_node(void)
OPTYPE_UNDO | OPTYPE_REGISTER);
WM_operatortype_macro_define(ot, "NODE_OT_links_detach");
WM_operatortype_macro_define(ot, "TRANSFORM_OT_translate");
+ WM_operatortype_macro_define(ot, "NODE_OT_insert_offset");
ot = WM_operatortype_append_macro("NODE_OT_move_detach_links_release", "Detach", "Move a node to detach links",
OPTYPE_UNDO | OPTYPE_REGISTER);
@@ -267,7 +286,7 @@ void node_keymap(struct wmKeyConfig *keyconf)
WM_keymap_add_item(keymap, "NODE_OT_duplicate_move_keep_inputs", DKEY, KM_PRESS, KM_SHIFT | KM_CTRL, 0);
WM_keymap_add_item(keymap, "NODE_OT_parent_set", PKEY, KM_PRESS, KM_CTRL, 0);
- WM_keymap_add_item(keymap, "NODE_OT_parent_clear", PKEY, KM_PRESS, KM_ALT, 0);
+ WM_keymap_add_item(keymap, "NODE_OT_detach", PKEY, KM_PRESS, KM_ALT, 0);
WM_keymap_add_item(keymap, "NODE_OT_join", JKEY, KM_PRESS, KM_CTRL, 0);
WM_keymap_add_item(keymap, "NODE_OT_hide_toggle", HKEY, KM_PRESS, 0, 0);
@@ -311,7 +330,7 @@ void node_keymap(struct wmKeyConfig *keyconf)
WM_keymap_add_item(keymap, "NODE_OT_group_separate", PKEY, KM_PRESS, 0, 0);
kmi = WM_keymap_add_item(keymap, "NODE_OT_group_edit", TABKEY, KM_PRESS, 0, 0);
RNA_boolean_set(kmi->ptr, "exit", false);
- kmi = WM_keymap_add_item(keymap, "NODE_OT_group_edit", TABKEY, KM_PRESS, KM_SHIFT, 0);
+ kmi = WM_keymap_add_item(keymap, "NODE_OT_group_edit", TABKEY, KM_PRESS, KM_CTRL, 0);
RNA_boolean_set(kmi->ptr, "exit", true);
WM_keymap_add_item(keymap, "NODE_OT_read_renderlayers", RKEY, KM_PRESS, KM_CTRL, 0);
diff --git a/source/blender/editors/space_node/node_relationships.c b/source/blender/editors/space_node/node_relationships.c
index 973ce56857c..a9f126a75e2 100644
--- a/source/blender/editors/space_node/node_relationships.c
+++ b/source/blender/editors/space_node/node_relationships.c
@@ -37,6 +37,7 @@
#include "BLI_math.h"
#include "BLI_blenlib.h"
+#include "BLI_easing.h"
#include "BKE_context.h"
#include "BKE_global.h"
@@ -45,6 +46,7 @@
#include "ED_node.h" /* own include */
#include "ED_screen.h"
#include "ED_render.h"
+#include "ED_util.h"
#include "RNA_access.h"
#include "RNA_define.h"
@@ -53,11 +55,11 @@
#include "WM_types.h"
#include "UI_view2d.h"
+#include "UI_resources.h"
-#include "BLF_translation.h"
+#include "BLT_translation.h"
#include "node_intern.h" /* own include */
-#include "NOD_common.h"
/* ****************** Add *********************** */
@@ -67,6 +69,17 @@ typedef struct bNodeListItem {
struct bNode *node;
} bNodeListItem;
+typedef struct NodeInsertOfsData {
+ bNodeTree *ntree;
+ bNode *insert; /* inserted node */
+ bNode *prev, *next; /* prev/next node in the chain */
+ bNode *insert_parent;
+
+ wmTimer *anim_timer;
+
+ float offset_x; /* offset to apply to node chain */
+} NodeInsertOfsData;
+
static int sort_nodes_locx(const void *a, const void *b)
{
const bNodeListItem *nli1 = a;
@@ -203,7 +216,7 @@ static void snode_autoconnect(SpaceNode *snode, const bool allow_multiple, const
}
/* sort nodes left to right */
- BLI_sortlist(nodelist, sort_nodes_locx);
+ BLI_listbase_sort(nodelist, sort_nodes_locx);
for (nli = nodelist->first; nli; nli = nli->next) {
bNode *node_fr, *node_to;
@@ -236,7 +249,7 @@ static void snode_autoconnect(SpaceNode *snode, const bool allow_multiple, const
if (!has_selected_inputs) {
/* no selected inputs, connect by finding suitable match */
- int num_inputs = BLI_countlist(&node_to->inputs);
+ int num_inputs = BLI_listbase_count(&node_to->inputs);
for (i = 0; i < num_inputs; i++) {
@@ -368,7 +381,7 @@ static int node_active_link_viewer_exec(bContext *C, wmOperator *UNUSED(op))
if (!node)
return OPERATOR_CANCELLED;
- ED_preview_kill_jobs(C);
+ ED_preview_kill_jobs(CTX_wm_manager(C), CTX_data_main(C));
if (node_link_viewer(C, node) == OPERATOR_CANCELLED)
return OPERATOR_CANCELLED;
@@ -747,7 +760,7 @@ static int node_link_invoke(bContext *C, wmOperator *op, const wmEvent *event)
UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1],
&cursor[0], &cursor[1]);
- ED_preview_kill_jobs(C);
+ ED_preview_kill_jobs(CTX_wm_manager(C), CTX_data_main(C));
nldrag = node_link_init(snode, cursor, detach);
@@ -803,7 +816,7 @@ static int node_make_link_exec(bContext *C, wmOperator *op)
SpaceNode *snode = CTX_wm_space_node(C);
const bool replace = RNA_boolean_get(op->ptr, "replace");
- ED_preview_kill_jobs(C);
+ ED_preview_kill_jobs(CTX_wm_manager(C), CTX_data_main(C));
snode_autoconnect(snode, 1, replace);
@@ -874,7 +887,7 @@ static int cut_links_exec(bContext *C, wmOperator *op)
bool found = false;
bNodeLink *link, *next;
- ED_preview_kill_jobs(C);
+ ED_preview_kill_jobs(CTX_wm_manager(C), CTX_data_main(C));
for (link = snode->edittree->links.first; link; link = next) {
next = link->next;
@@ -884,7 +897,8 @@ static int cut_links_exec(bContext *C, wmOperator *op)
if (cut_links_intersect(link, mcoords, i)) {
if (found == false) {
- ED_preview_kill_jobs(C);
+ /* TODO(sergey): Why did we kill jobs twice? */
+ ED_preview_kill_jobs(CTX_wm_manager(C), CTX_data_main(C));
found = true;
}
@@ -941,7 +955,7 @@ static int detach_links_exec(bContext *C, wmOperator *UNUSED(op))
bNodeTree *ntree = snode->edittree;
bNode *node;
- ED_preview_kill_jobs(C);
+ ED_preview_kill_jobs(CTX_wm_manager(C), CTX_data_main(C));
for (node = ntree->nodes.first; node; node = node->next) {
if (node->flag & SELECT) {
@@ -1011,40 +1025,6 @@ void NODE_OT_parent_set(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-/* ****************** Clear Parent ******************* */
-
-static int node_parent_clear_exec(bContext *C, wmOperator *UNUSED(op))
-{
- SpaceNode *snode = CTX_wm_space_node(C);
- bNodeTree *ntree = snode->edittree;
- bNode *node;
-
- for (node = ntree->nodes.first; node; node = node->next) {
- if (node->flag & NODE_SELECT) {
- nodeDetachNode(node);
- }
- }
-
- WM_event_add_notifier(C, NC_NODE | ND_DISPLAY, NULL);
-
- return OPERATOR_FINISHED;
-}
-
-void NODE_OT_parent_clear(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Clear Parent";
- ot->description = "Detach selected nodes";
- ot->idname = "NODE_OT_parent_clear";
-
- /* api callbacks */
- ot->exec = node_parent_clear_exec;
- ot->poll = ED_operator_node_editable;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-}
-
/* ****************** Join Nodes ******************* */
/* tags for depth-first search */
@@ -1133,25 +1113,33 @@ void NODE_OT_join(wmOperatorType *ot)
/* ****************** Attach ******************* */
-static int node_attach_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *event)
+static bNode *node_find_frame_to_attach(ARegion *ar, const bNodeTree *ntree, const int mouse_xy[2])
{
- ARegion *ar = CTX_wm_region(C);
- SpaceNode *snode = CTX_wm_space_node(C);
- bNodeTree *ntree = snode->edittree;
bNode *frame;
float cursor[2];
-
+
/* convert mouse coordinates to v2d space */
- UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &cursor[0], &cursor[1]);
+ UI_view2d_region_to_view(&ar->v2d, UNPACK2(mouse_xy), &cursor[0], &cursor[1]);
/* check nodes front to back */
for (frame = ntree->nodes.last; frame; frame = frame->prev) {
/* skip selected, those are the nodes we want to attach */
if ((frame->type != NODE_FRAME) || (frame->flag & NODE_SELECT))
continue;
- if (BLI_rctf_isect_pt(&frame->totr, cursor[0], cursor[1]))
- break;
+ if (BLI_rctf_isect_pt_v(&frame->totr, cursor))
+ return frame;
}
+
+ return NULL;
+}
+
+static int node_attach_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *event)
+{
+ ARegion *ar = CTX_wm_region(C);
+ SpaceNode *snode = CTX_wm_space_node(C);
+ bNodeTree *ntree = snode->edittree;
+ bNode *frame = node_find_frame_to_attach(ar, ntree, event->mval);
+
if (frame) {
bNode *node, *parent;
for (node = ntree->nodes.last; node; node = node->prev) {
@@ -1332,7 +1320,7 @@ void ED_node_link_intersect_test(ScrArea *sa, int test)
bNode *select;
SpaceNode *snode;
bNodeLink *link, *selink = NULL;
- float mcoords[6][2];
+ float dist_best = FLT_MAX;
if (!ed_node_link_conditions(sa, test, &snode, &select)) return;
@@ -1342,34 +1330,40 @@ void ED_node_link_intersect_test(ScrArea *sa, int test)
if (test == 0) return;
- /* okay, there's 1 node, without links, now intersect */
- mcoords[0][0] = select->totr.xmin;
- mcoords[0][1] = select->totr.ymin;
- mcoords[1][0] = select->totr.xmax;
- mcoords[1][1] = select->totr.ymin;
- mcoords[2][0] = select->totr.xmax;
- mcoords[2][1] = select->totr.ymax;
- mcoords[3][0] = select->totr.xmin;
- mcoords[3][1] = select->totr.ymax;
- mcoords[4][0] = select->totr.xmin;
- mcoords[4][1] = select->totr.ymin;
- mcoords[5][0] = select->totr.xmax;
- mcoords[5][1] = select->totr.ymax;
-
- /* we only tag a single link for intersect now */
- /* idea; use header dist when more? */
+ /* find link to select/highlight */
for (link = snode->edittree->links.first; link; link = link->next) {
+ float coord_array[NODE_LINK_RESOL + 1][2];
+
if (nodeLinkIsHidden(link))
continue;
-
- if (cut_links_intersect(link, mcoords, 5)) { /* intersect code wants edges */
- if (selink)
- break;
- selink = link;
+
+ if (node_link_bezier_points(NULL, NULL, link, coord_array, NODE_LINK_RESOL)) {
+ float dist = FLT_MAX;
+ int i;
+
+ /* loop over link coords to find shortest dist to upper left node edge of a intersected line segment */
+ for (i = 0; i < NODE_LINK_RESOL; i++) {
+ /* check if the node rect intersetcts the line from this point to next one */
+ if (BLI_rctf_isect_segment(&select->totr, coord_array[i], coord_array[i + 1])) {
+ /* store the shortest distance to the upper left edge of all intersetctions found so far */
+ const float node_xy[] = {select->totr.xmin, select->totr.ymax};
+
+ /* to be precise coord_array should be clipped by select->totr,
+ * but not done since there's no real noticeable difference */
+ dist = min_ff(dist_squared_to_line_segment_v2(node_xy, coord_array[i], coord_array[i + 1]),
+ dist);
+ }
+ }
+
+ /* we want the link with the shortest distance to node center */
+ if (dist < dist_best) {
+ dist_best = dist;
+ selink = link;
+ }
}
}
- if (link == NULL && selink)
+ if (selink)
selink->flag |= NODE_LINKFLAG_HILITE;
}
@@ -1405,6 +1399,323 @@ static bNodeSocket *socket_best_match(ListBase *sockets)
return NULL;
}
+static bool node_parents_offset_flag_enable_cb(bNode *parent, void *UNUSED(userdata))
+{
+ /* NODE_TEST is used to flag nodes that shouldn't be offset (again) */
+ parent->flag |= NODE_TEST;
+
+ return true;
+}
+
+static void node_offset_apply(bNode *node, const float offset_x)
+{
+ /* NODE_TEST is used to flag nodes that shouldn't be offset (again) */
+ if ((node->flag & NODE_TEST) == 0) {
+ node->anim_init_locx = node->locx;
+ node->anim_ofsx = (offset_x / UI_DPI_FAC);
+ node->flag |= NODE_TEST;
+ }
+}
+
+static void node_parent_offset_apply(NodeInsertOfsData *data, bNode *parent, const float offset_x)
+{
+ bNode *node;
+
+ node_offset_apply(parent, offset_x);
+
+ /* flag all childs as offset to prevent them from being offset
+ * separately (they've already moved with the parent) */
+ for (node = data->ntree->nodes.first; node; node = node->next) {
+ if (nodeIsChildOf(parent, node)) {
+ /* NODE_TEST is used to flag nodes that shouldn't be offset (again) */
+ node->flag |= NODE_TEST;
+ }
+ }
+}
+
+#define NODE_INSOFS_ANIM_DURATION 0.25f
+
+/**
+ * Callback that applies NodeInsertOfsData.offset_x to a node or its parent, similar
+ * to node_link_insert_offset_output_chain_cb below, but with slightly different logic
+ */
+static bool node_link_insert_offset_frame_chain_cb(
+ bNode *fromnode, bNode *tonode,
+ void *userdata,
+ const bool reversed)
+{
+ NodeInsertOfsData *data = userdata;
+ bNode *ofs_node = reversed ? fromnode : tonode;
+
+ if (ofs_node->parent && ofs_node->parent != data->insert_parent) {
+ node_offset_apply(ofs_node->parent, data->offset_x);
+ }
+ else {
+ node_offset_apply(ofs_node, data->offset_x);
+ }
+
+ return true;
+}
+
+/**
+ * Applies NodeInsertOfsData.offset_x to all childs of \a parent
+ */
+static void node_link_insert_offset_frame_chains(
+ const bNodeTree *ntree, const bNode *parent,
+ NodeInsertOfsData *data,
+ const bool reversed)
+{
+ bNode *node;
+
+ for (node = ntree->nodes.first; node; node = node->next) {
+ if (nodeIsChildOf(parent, node)) {
+ nodeChainIter(ntree, node, node_link_insert_offset_frame_chain_cb, data, reversed);
+ }
+ }
+}
+
+/**
+ * Callback that applies NodeInsertOfsData.offset_x to a node or its parent,
+ * considering the logic needed for offseting nodes after link insert
+ */
+static bool node_link_insert_offset_chain_cb(
+ bNode *fromnode, bNode *tonode,
+ void *userdata,
+ const bool reversed)
+{
+ NodeInsertOfsData *data = userdata;
+ bNode *ofs_node = reversed ? fromnode : tonode;
+
+ if (data->insert_parent) {
+ if (ofs_node->parent && (ofs_node->parent->flag & NODE_TEST) == 0) {
+ node_parent_offset_apply(data, ofs_node->parent, data->offset_x);
+ node_link_insert_offset_frame_chains(data->ntree, ofs_node->parent, data, reversed);
+ }
+ else {
+ node_offset_apply(ofs_node, data->offset_x);
+ }
+
+ if (nodeIsChildOf(data->insert_parent, ofs_node) == false) {
+ data->insert_parent = NULL;
+ }
+ }
+ else if (ofs_node->parent) {
+ bNode *node = nodeFindRootParent(ofs_node);
+ node_offset_apply(node, data->offset_x);
+ }
+ else {
+ node_offset_apply(ofs_node, data->offset_x);
+ }
+
+ return true;
+}
+
+static void node_link_insert_offset_ntree(
+ NodeInsertOfsData *iofsd, ARegion *ar,
+ const int mouse_xy[2], const bool right_alignment)
+{
+ bNodeTree *ntree = iofsd->ntree;
+ bNode *insert = iofsd->insert;
+ bNode *prev = iofsd->prev, *next = iofsd->next;
+ bNode *init_parent = insert->parent; /* store old insert->parent for restoring later */
+ rctf totr_insert;
+
+ const float min_margin = U.node_margin * UI_DPI_FAC;
+ const float width = NODE_WIDTH(insert);
+ const bool needs_alignment = (next->totr.xmin - prev->totr.xmax) < (width + (min_margin * 2.0f));
+
+ float margin = width;
+ float dist, addval;
+
+
+ /* NODE_TEST will be used later, so disable for all nodes */
+ ntreeNodeFlagSet(ntree, NODE_TEST, false);
+
+ /* insert->totr isn't updated yet, so totr_insert is used to get the correct worldspace coords */
+ node_to_updated_rect(insert, &totr_insert);
+
+ /* frame attachement was't handled yet so we search the frame that the node will be attached to later */
+ insert->parent = node_find_frame_to_attach(ar, ntree, mouse_xy);
+
+ /* this makes sure nodes are also correctly offset when inserting a node on top of a frame
+ * without actually making it a part of the frame (because mouse isn't intersecting it)
+ * - logic here is similar to node_find_frame_to_attach */
+ if (!insert->parent ||
+ (prev->parent && (prev->parent == next->parent) && (prev->parent != insert->parent)))
+ {
+ bNode *frame;
+ rctf totr_frame;
+
+ /* check nodes front to back */
+ for (frame = ntree->nodes.last; frame; frame = frame->prev) {
+ /* skip selected, those are the nodes we want to attach */
+ if ((frame->type != NODE_FRAME) || (frame->flag & NODE_SELECT))
+ continue;
+
+ /* for some reason frame y coords aren't correct yet */
+ node_to_updated_rect(frame, &totr_frame);
+
+ if (BLI_rctf_isect_x(&totr_frame, totr_insert.xmin) &&
+ BLI_rctf_isect_x(&totr_frame, totr_insert.xmax))
+ {
+ if (BLI_rctf_isect_y(&totr_frame, totr_insert.ymin) ||
+ BLI_rctf_isect_y(&totr_frame, totr_insert.ymax))
+ {
+ /* frame isn't insert->parent actually, but this is needed to make offsetting
+ * nodes work correctly for above checked cases (it is restored later) */
+ insert->parent = frame;
+ break;
+ }
+ }
+ }
+ }
+
+
+ /* *** ensure offset at the left (or right for right_alignment case) of insert_node *** */
+
+ dist = right_alignment ? totr_insert.xmin - prev->totr.xmax : next->totr.xmin - totr_insert.xmax;
+ /* distance between insert_node and prev is smaller than min margin */
+ if (dist < min_margin) {
+ addval = (min_margin - dist) * (right_alignment ? 1.0f : -1.0f);
+
+ node_offset_apply(insert, addval);
+
+ totr_insert.xmin += addval;
+ totr_insert.xmax += addval;
+ margin += min_margin;
+ }
+
+ /* *** ensure offset at the right (or left for right_alignment case) of insert_node *** */
+
+ dist = right_alignment ? next->totr.xmin - totr_insert.xmax : totr_insert.xmin - prev->totr.xmax;
+ /* distance between insert_node and next is smaller than min margin */
+ if (dist < min_margin) {
+ addval = (min_margin - dist) * (right_alignment ? 1.0f : -1.0f);
+ if (needs_alignment) {
+ bNode *offs_node = right_alignment ? next : prev;
+ if (!offs_node->parent ||
+ offs_node->parent == insert->parent ||
+ nodeIsChildOf(offs_node->parent, insert))
+ {
+ node_offset_apply(offs_node, addval);
+ }
+ else if (!insert->parent && offs_node->parent) {
+ node_offset_apply(nodeFindRootParent(offs_node), addval);
+ }
+ margin = addval;
+ }
+ /* enough room is available, but we want to ensure the min margin at the right */
+ else {
+ /* offset inserted node so that min margin is kept at the right */
+ node_offset_apply(insert, -addval);
+ }
+ }
+
+
+ if (needs_alignment) {
+ iofsd->insert_parent = insert->parent;
+ iofsd->offset_x = margin;
+
+ /* flag all parents of insert as offset to prevent them from being offset */
+ nodeParentsIter(insert, node_parents_offset_flag_enable_cb, NULL);
+ /* iterate over entire chain and apply offsets */
+ nodeChainIter(ntree, right_alignment ? next : prev, node_link_insert_offset_chain_cb, iofsd, !right_alignment);
+ }
+
+ insert->parent = init_parent;
+}
+
+/**
+ * Modal handler for insert offset animation
+ */
+static int node_insert_offset_modal(bContext *C, wmOperator *UNUSED(op), const wmEvent *event)
+{
+ SpaceNode *snode = CTX_wm_space_node(C);
+ NodeInsertOfsData *iofsd = snode->iofsd;
+ bNode *node;
+ float duration;
+ bool redraw = false;
+
+ if (!snode || event->type != TIMER || iofsd->anim_timer != event->customdata)
+ return OPERATOR_PASS_THROUGH;
+
+ duration = (float)iofsd->anim_timer->duration;
+
+ /* handle animation - do this before possibly aborting due to duration, since
+ * main thread might be so busy that node hasn't reached final position yet */
+ for (node = snode->edittree->nodes.first; node; node = node->next) {
+ if (UNLIKELY(node->anim_ofsx)) {
+ const float endval = node->anim_init_locx + node->anim_ofsx;
+ if (node->locx < endval) {
+ node->locx = BLI_easing_cubic_ease_in_out(duration, node->anim_init_locx, node->anim_ofsx,
+ NODE_INSOFS_ANIM_DURATION);
+ CLAMP_MAX(node->locx, endval);
+ redraw = true;
+ }
+ }
+ }
+ if (redraw) {
+ ED_region_tag_redraw(CTX_wm_region(C));
+ }
+
+ /* end timer + free insert offset data */
+ if (duration > NODE_INSOFS_ANIM_DURATION) {
+ WM_event_remove_timer(CTX_wm_manager(C), NULL, iofsd->anim_timer);
+
+ for (node = snode->edittree->nodes.first; node; node = node->next) {
+ node->anim_init_locx = node->anim_ofsx = 0.0f;
+ }
+
+ snode->iofsd = NULL;
+ MEM_freeN(iofsd);
+
+ return (OPERATOR_FINISHED | OPERATOR_PASS_THROUGH);
+ }
+
+ return OPERATOR_RUNNING_MODAL;
+}
+
+#undef NODE_INSOFS_ANIM_DURATION
+
+static int node_insert_offset_invoke(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ const SpaceNode *snode = CTX_wm_space_node(C);
+ NodeInsertOfsData *iofsd = snode->iofsd;
+
+ if (!iofsd || !iofsd->insert)
+ return OPERATOR_CANCELLED;
+
+ BLI_assert((snode->flag & SNODE_SKIP_INSOFFSET) == 0);
+
+ iofsd->ntree = snode->edittree;
+ iofsd->anim_timer = WM_event_add_timer(CTX_wm_manager(C), CTX_wm_window(C), TIMER, 0.02);
+
+ node_link_insert_offset_ntree(
+ iofsd, CTX_wm_region(C),
+ event->mval, (snode->insert_ofs_dir == SNODE_INSERTOFS_DIR_RIGHT));
+
+ /* add temp handler */
+ WM_event_add_modal_handler(C, op);
+
+ return OPERATOR_RUNNING_MODAL;
+}
+
+void NODE_OT_insert_offset(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Insert Offset";
+ ot->description = "Automatically offset nodes on insertion";
+ ot->idname = "NODE_OT_insert_offset";
+
+ /* callbacks */
+ ot->invoke = node_insert_offset_invoke;
+ ot->modal = node_insert_offset_modal;
+ ot->poll = ED_operator_node_editable;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING;
+}
+
/* assumes link with NODE_LINKFLAG_HILITE set */
void ED_node_link_insert(ScrArea *sa)
{
@@ -1435,6 +1746,17 @@ void ED_node_link_insert(ScrArea *sa)
nodeAddLink(snode->edittree, select, best_output, node, sockto);
+ /* set up insert offset data, it needs stuff from here */
+ if ((snode->flag & SNODE_SKIP_INSOFFSET) == 0) {
+ NodeInsertOfsData *iofsd = MEM_callocN(sizeof(NodeInsertOfsData), __func__);
+
+ iofsd->insert = select;
+ iofsd->prev = link->fromnode;
+ iofsd->next = node;
+
+ snode->iofsd = iofsd;
+ }
+
ntreeUpdateTree(G.main, snode->edittree); /* needed for pointers */
snode_update(snode, select);
ED_node_tag_update_id(snode->id);
diff --git a/source/blender/editors/space_node/node_select.c b/source/blender/editors/space_node/node_select.c
index de580f612a0..78302fedd97 100644
--- a/source/blender/editors/space_node/node_select.c
+++ b/source/blender/editors/space_node/node_select.c
@@ -249,9 +249,9 @@ static bool node_select_grouped_name(SpaceNode *snode, bNode *node_act, const bo
bool changed = false;
const unsigned int delims[] = {'.', '-', '_', '\0'};
size_t pref_len_act, pref_len_curr;
- char *sep, *suf_act, *suf_curr;
+ const char *sep, *suf_act, *suf_curr;
- pref_len_act = BLI_str_partition_ex_utf8(node_act->name, delims, &sep, &suf_act, from_right);
+ pref_len_act = BLI_str_partition_ex_utf8(node_act->name, NULL, delims, &sep, &suf_act, from_right);
/* Note: in case we are searching for suffix, and found none, use whole name as suffix. */
if (from_right && !(sep && suf_act)) {
@@ -263,7 +263,7 @@ static bool node_select_grouped_name(SpaceNode *snode, bNode *node_act, const bo
if (node->flag & SELECT) {
continue;
}
- pref_len_curr = BLI_str_partition_ex_utf8(node->name, delims, &sep, &suf_curr, from_right);
+ pref_len_curr = BLI_str_partition_ex_utf8(node->name, NULL, delims, &sep, &suf_curr, from_right);
/* Same as with active node name! */
if (from_right && !(sep && suf_curr)) {
@@ -972,7 +972,7 @@ static void node_find_cb(const struct bContext *C, void *UNUSED(arg), const char
BLI_snprintf(name, 256, "%s (%s)", node->name, node->label);
else
BLI_strncpy(name, node->name, 256);
- if (false == uiSearchItemAdd(items, name, node, 0))
+ if (false == UI_search_item_add(items, name, node, 0))
break;
}
}
@@ -1006,18 +1006,18 @@ static uiBlock *node_find_menu(bContext *C, ARegion *ar, void *arg_op)
uiBut *but;
wmOperator *op = (wmOperator *)arg_op;
- block = uiBeginBlock(C, ar, "_popup", UI_EMBOSS);
- uiBlockSetFlag(block, UI_BLOCK_LOOP | UI_BLOCK_MOVEMOUSE_QUIT | UI_BLOCK_SEARCH_MENU);
+ block = UI_block_begin(C, ar, "_popup", UI_EMBOSS);
+ UI_block_flag_enable(block, UI_BLOCK_LOOP | UI_BLOCK_MOVEMOUSE_QUIT | UI_BLOCK_SEARCH_MENU);
but = uiDefSearchBut(block, search, 0, ICON_VIEWZOOM, sizeof(search), 10, 10, 9 * UI_UNIT_X, UI_UNIT_Y, 0, 0, "");
- uiButSetSearchFunc(but, node_find_cb, op->type, node_find_call_cb, NULL);
+ UI_but_func_search_set(but, node_find_cb, op->type, node_find_call_cb, NULL);
/* fake button, it holds space for search items */
- uiDefBut(block, LABEL, 0, "", 10, 10 - uiSearchBoxHeight(), uiSearchBoxWidth(), uiSearchBoxHeight(), NULL, 0, 0, 0, 0, NULL);
+ uiDefBut(block, UI_BTYPE_LABEL, 0, "", 10, 10 - UI_searchbox_size_y(), UI_searchbox_size_x(), UI_searchbox_size_y(), NULL, 0, 0, 0, 0, NULL);
- uiPopupBoundsBlock(block, 6, 0, -UI_UNIT_Y); /* move it downwards, mouse over button */
+ UI_block_bounds_set_popup(block, 6, 0, -UI_UNIT_Y); /* move it downwards, mouse over button */
- // uiButActiveOnly(C, ar, block, but); XXX using this here makes Blender hang - investigate
+ // UI_but_active_only(C, ar, block, but); XXX using this here makes Blender hang - investigate
wm_event_init_from_window(win, &event);
event.type = EVT_BUT_OPEN;
event.val = KM_PRESS;
@@ -1031,7 +1031,7 @@ static uiBlock *node_find_menu(bContext *C, ARegion *ar, void *arg_op)
static int node_find_node_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- uiPupBlock(C, node_find_menu, op);
+ UI_popup_block_invoke(C, node_find_menu, op);
return OPERATOR_CANCELLED;
}
diff --git a/source/blender/editors/space_node/node_templates.c b/source/blender/editors/space_node/node_templates.c
index 99a481e5d82..f2293754608 100644
--- a/source/blender/editors/space_node/node_templates.c
+++ b/source/blender/editors/space_node/node_templates.c
@@ -24,18 +24,18 @@
* \ingroup edinterface
*/
+#include <stdlib.h>
#include <string.h>
#include "MEM_guardedalloc.h"
#include "DNA_node_types.h"
#include "DNA_screen_types.h"
-#include "DNA_space_types.h"
#include "BLI_listbase.h"
#include "BLI_string.h"
-#include "BLF_translation.h"
+#include "BLT_translation.h"
#include "BKE_context.h"
#include "BKE_global.h"
@@ -54,7 +54,6 @@
#include "ED_util.h"
-#include "node_intern.h"
/************************* Node Socket Manipulation **************************/
@@ -216,8 +215,22 @@ static void node_socket_add_replace(const bContext *C, bNodeTree *ntree, bNode *
}
else if (!node_from) {
node_from = nodeAddStaticNode(C, ntree, type);
- node_from->locx = node_to->locx - (node_from->typeinfo->width + 50);
- node_from->locy = node_to->locy;
+ if (node_prev != NULL) {
+ /* If we're replacing existing node, use it's location. */
+ node_from->locx = node_prev->locx;
+ node_from->locy = node_prev->locy;
+ node_from->offsetx = node_prev->offsetx;
+ node_from->offsety = node_prev->offsety;
+ }
+ else {
+ /* Avoid exact intersection of nodes.
+ * TODO(sergey): Still not ideal, but better than nothing.
+ */
+ int index = BLI_findindex(&node_to->inputs, sock_to);
+ BLI_assert(index != -1);
+ node_from->locx = node_to->locx - (node_from->typeinfo->width + 50);
+ node_from->locy = node_to->locy - (node_from->typeinfo->height * index);
+ }
node_link_item_apply(node_from, item);
}
@@ -300,7 +313,7 @@ static void ui_node_link_items(NodeLinkArg *arg, int in_out, NodeLinkItem **r_it
for (ngroup = arg->bmain->nodetree.first; ngroup; ngroup = ngroup->id.next) {
ListBase *lb = ((in_out == SOCK_IN) ? &ngroup->inputs : &ngroup->outputs);
- totitems += BLI_countlist(lb);
+ totitems += BLI_listbase_count(lb);
}
if (totitems > 0) {
@@ -454,7 +467,7 @@ static void ui_node_menu_column(NodeLinkArg *arg, int nclass, const char *cname)
if (first) {
column = uiLayoutColumn(layout, 0);
- uiBlockSetCurLayout(block, column);
+ UI_block_layout_set_current(block, column);
uiItemL(column, IFACE_(cname), ICON_NODE);
but = block->buttons.last;
@@ -466,7 +479,7 @@ static void ui_node_menu_column(NodeLinkArg *arg, int nclass, const char *cname)
if (!cur_node_name || !STREQ(cur_node_name, items[i].node_name)) {
cur_node_name = items[i].node_name;
/* 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,
+ uiDefBut(block, UI_BTYPE_LABEL, 0, IFACE_(cur_node_name), 0, 0, UI_UNIT_X * 4, UI_UNIT_Y,
NULL, 0.0, 0.0, 0.0, 0.0, "");
}
@@ -478,12 +491,12 @@ static void ui_node_menu_column(NodeLinkArg *arg, int nclass, const char *cname)
icon = ICON_NONE;
}
- but = uiDefIconTextBut(block, BUT, 0, icon, name, 0, 0, UI_UNIT_X * 4, UI_UNIT_Y,
+ but = uiDefIconTextBut(block, UI_BTYPE_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];
- uiButSetNFunc(but, ui_node_link, argN, NULL);
+ UI_but_funcN_set(but, ui_node_link, argN, NULL);
}
if (items)
@@ -511,8 +524,8 @@ static void ui_template_node_link_menu(bContext *C, uiLayout *layout, void *but_
bNodeSocket *sock = arg->sock;
bNodeTreeType *ntreetype = arg->ntree->typeinfo;
- uiBlockSetFlag(block, UI_BLOCK_NO_FLIP);
- uiBlockSetCurLayout(block, layout);
+ UI_block_flag_enable(block, UI_BLOCK_NO_FLIP);
+ UI_block_layout_set_current(block, layout);
split = uiLayoutSplit(layout, 0.0f, false);
arg->bmain = bmain;
@@ -523,20 +536,20 @@ static void ui_template_node_link_menu(bContext *C, uiLayout *layout, void *but_
ntreetype->foreach_nodeclass(scene, arg, node_menu_column_foreach_cb);
column = uiLayoutColumn(split, false);
- uiBlockSetCurLayout(block, column);
+ UI_block_layout_set_current(block, column);
if (sock->link) {
uiItemL(column, IFACE_("Link"), ICON_NONE);
but = block->buttons.last;
but->drawflag = UI_BUT_TEXT_LEFT;
- but = uiDefBut(block, BUT, 0, IFACE_("Remove"), 0, 0, UI_UNIT_X * 4, UI_UNIT_Y,
+ but = uiDefBut(block, UI_BTYPE_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"));
- uiButSetNFunc(but, ui_node_link, MEM_dupallocN(arg), SET_INT_IN_POINTER(UI_NODE_LINK_REMOVE));
+ UI_but_funcN_set(but, ui_node_link, MEM_dupallocN(arg), SET_INT_IN_POINTER(UI_NODE_LINK_REMOVE));
- but = uiDefBut(block, BUT, 0, IFACE_("Disconnect"), 0, 0, UI_UNIT_X * 4, UI_UNIT_Y,
+ but = uiDefBut(block, UI_BTYPE_BUT, 0, IFACE_("Disconnect"), 0, 0, UI_UNIT_X * 4, UI_UNIT_Y,
NULL, 0.0, 0.0, 0.0, 0.0, TIP_("Disconnect nodes connected to the input"));
- uiButSetNFunc(but, ui_node_link, MEM_dupallocN(arg), SET_INT_IN_POINTER(UI_NODE_LINK_DISCONNECT));
+ UI_but_funcN_set(but, ui_node_link, MEM_dupallocN(arg), SET_INT_IN_POINTER(UI_NODE_LINK_DISCONNECT));
}
ui_node_menu_column(arg, NODE_CLASS_GROUP, N_("Group"));
@@ -553,7 +566,7 @@ void uiTemplateNodeLink(uiLayout *layout, bNodeTree *ntree, bNode *node, bNodeSo
arg->node = node;
arg->sock = sock;
- uiBlockSetCurLayout(block, layout);
+ UI_block_layout_set_current(block, layout);
if (sock->link || sock->type == SOCK_SHADER || (sock->flag & SOCK_HIDE_VALUE)) {
char name[UI_MAX_NAME_STR];
@@ -563,7 +576,7 @@ void uiTemplateNodeLink(uiLayout *layout, bNodeTree *ntree, bNode *node, bNodeSo
else
but = uiDefIconMenuBut(block, ui_template_node_link_menu, NULL, ICON_NONE, 0, 0, UI_UNIT_X, UI_UNIT_Y, "");
- uiButSetMenuFromPulldown(but);
+ UI_but_type_set_menu_from_pulldown(but);
but->flag |= UI_BUT_NODE_LINK;
but->poin = (char *)but;
@@ -609,7 +622,7 @@ static void ui_node_draw_input(uiLayout *layout, bContext *C, bNodeTree *ntree,
uiLayout *split, *row, *col;
bNode *lnode;
char label[UI_MAX_NAME_STR];
- int indent = (depth > 1) ? 2 * (depth - 1) : 0;
+ int i, indent = (depth > 1) ? 2 * (depth - 1) : 0;
int dependency_loop;
if (input->flag & SOCK_UNAVAIL)
@@ -628,7 +641,8 @@ static void ui_node_draw_input(uiLayout *layout, bContext *C, bNodeTree *ntree,
RNA_pointer_create(&ntree->id, &RNA_Node, node, &nodeptr);
/* indented label */
- memset(label, ' ', indent);
+ for (i = 0; i < indent; i++)
+ label[i] = ' ';
label[indent] = '\0';
BLI_snprintf(label, UI_MAX_NAME_STR, "%s%s:", label, IFACE_(input->name));
@@ -638,7 +652,7 @@ static void ui_node_draw_input(uiLayout *layout, bContext *C, bNodeTree *ntree,
row = uiLayoutRow(split, true);
if (depth > 0) {
- uiBlockSetEmboss(block, UI_EMBOSSN);
+ UI_block_emboss_set(block, UI_EMBOSS_NONE);
if (lnode && (lnode->inputs.first || (lnode->typeinfo->draw_buttons && lnode->type != NODE_GROUP))) {
int icon = (input->flag & SOCK_COLLAPSED) ? ICON_DISCLOSURE_TRI_RIGHT : ICON_DISCLOSURE_TRI_DOWN;
@@ -650,7 +664,7 @@ static void ui_node_draw_input(uiLayout *layout, bContext *C, bNodeTree *ntree,
bt = block->buttons.last;
bt->rect.xmax = UI_UNIT_X / 2;
- uiBlockSetEmboss(block, UI_EMBOSS);
+ UI_block_emboss_set(block, UI_EMBOSS);
}
uiItemL(row, label, ICON_NONE);
diff --git a/source/blender/editors/space_node/node_toolbar.c b/source/blender/editors/space_node/node_toolbar.c
index dd5bad3f8ad..e3e263f2e44 100644
--- a/source/blender/editors/space_node/node_toolbar.c
+++ b/source/blender/editors/space_node/node_toolbar.c
@@ -28,27 +28,18 @@
* \ingroup nodes
*/
-
-#include "MEM_guardedalloc.h"
-
#include "BLI_utildefines.h"
#include "DNA_node_types.h"
#include "BKE_context.h"
-#include "BKE_node.h"
#include "BKE_screen.h"
#include "WM_api.h"
#include "WM_types.h"
-#include "RNA_access.h"
-
#include "ED_screen.h"
-#include "UI_interface.h"
-#include "UI_resources.h"
-
#include "node_intern.h" /* own include */
diff --git a/source/blender/editors/space_node/node_view.c b/source/blender/editors/space_node/node_view.c
index 3491ecc86af..8c5d2d82468 100644
--- a/source/blender/editors/space_node/node_view.c
+++ b/source/blender/editors/space_node/node_view.c
@@ -292,7 +292,7 @@ void NODE_OT_backimage_move(wmOperatorType *ot)
ot->cancel = snode_bg_viewmove_cancel;
/* flags */
- ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_POINTER;
+ ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_CURSOR;
}
static int backimage_zoom_exec(bContext *C, wmOperator *op)
@@ -609,8 +609,11 @@ static int sample_modal(bContext *C, wmOperator *op, const wmEvent *event)
switch (event->type) {
case LEFTMOUSE:
case RIGHTMOUSE: // XXX hardcoded
- sample_exit(C, op);
- return OPERATOR_CANCELLED;
+ if (event->val == KM_RELEASE) {
+ sample_exit(C, op);
+ return OPERATOR_CANCELLED;
+ }
+ break;
case MOUSEMOVE:
sample_apply(C, op, event);
break;
diff --git a/source/blender/editors/space_node/space_node.c b/source/blender/editors/space_node/space_node.c
index ccaeae34927..b9b925f1829 100644
--- a/source/blender/editors/space_node/space_node.c
+++ b/source/blender/editors/space_node/space_node.c
@@ -28,8 +28,6 @@
* \ingroup spnode
*/
-
-
#include "DNA_lamp_types.h"
#include "DNA_material_types.h"
#include "DNA_node_types.h"
@@ -152,7 +150,7 @@ void ED_node_tree_pop(SpaceNode *snode)
int ED_node_tree_depth(SpaceNode *snode)
{
- return BLI_countlist(&snode->treepath);
+ return BLI_listbase_count(&snode->treepath);
}
bNodeTree *ED_node_tree_get(SpaceNode *snode, int level)
@@ -205,12 +203,10 @@ void ED_node_tree_path_get_fixedbuf(SpaceNode *snode, char *value, int max_lengt
value[0] = '\0';
for (path = snode->treepath.first, i = 0; path; path = path->next, ++i) {
if (i == 0) {
- BLI_strncpy(value, path->node_name, max_length);
- size = strlen(path->node_name);
+ size = BLI_strncpy_rlen(value, path->node_name, max_length);
}
else {
- BLI_snprintf(value, max_length, "/%s", path->node_name);
- size = strlen(path->node_name) + 1;
+ size = BLI_snprintf_rlen(value, max_length, "/%s", path->node_name);
}
max_length -= size;
if (max_length <= 0)
@@ -515,6 +511,11 @@ static void node_area_listener(bScreen *sc, ScrArea *sa, wmNotifier *wmn)
ED_area_tag_refresh(sa);
}
break;
+ case NC_GPENCIL:
+ if (ELEM(wmn->action, NA_EDITED, NA_SELECTED)) {
+ ED_area_tag_redraw(sa);
+ }
+ break;
}
}
@@ -597,7 +598,7 @@ static void node_buttons_area_init(wmWindowManager *wm, ARegion *ar)
static void node_buttons_area_draw(const bContext *C, ARegion *ar)
{
- ED_region_panels(C, ar, 1, NULL, -1);
+ ED_region_panels(C, ar, NULL, -1, true);
}
/* add handlers, stuff you only do once or on area/region changes */
@@ -613,7 +614,7 @@ static void node_toolbar_area_init(wmWindowManager *wm, ARegion *ar)
static void node_toolbar_area_draw(const bContext *C, ARegion *ar)
{
- ED_region_panels(C, ar, 1, NULL, -1);
+ ED_region_panels(C, ar, NULL, -1, true);
}
static void node_cursor(wmWindow *win, ScrArea *sa, ARegion *ar)
@@ -665,12 +666,12 @@ static void node_main_area_draw(const bContext *C, ARegion *ar)
static int node_ima_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent *UNUSED(event))
{
if (drag->type == WM_DRAG_ID) {
- ID *id = (ID *)drag->poin;
+ ID *id = drag->poin;
if (GS(id->name) == ID_IM)
return 1;
}
else if (drag->type == WM_DRAG_PATH) {
- if (ELEM(drag->icon, 0, ICON_FILE_IMAGE)) /* rule might not work? */
+ if (ELEM(drag->icon, 0, ICON_FILE_IMAGE, ICON_FILE_MOVIE)) /* rule might not work? */
return 1;
}
return 0;
@@ -679,7 +680,7 @@ static int node_ima_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent *
static int node_mask_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent *UNUSED(event))
{
if (drag->type == WM_DRAG_ID) {
- ID *id = (ID *)drag->poin;
+ ID *id = drag->poin;
if (GS(id->name) == ID_MSK)
return 1;
}
@@ -688,20 +689,22 @@ static int node_mask_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent
static void node_id_drop_copy(wmDrag *drag, wmDropBox *drop)
{
- ID *id = (ID *)drag->poin;
+ ID *id = drag->poin;
RNA_string_set(drop->ptr, "name", id->name + 2);
}
static void node_id_path_drop_copy(wmDrag *drag, wmDropBox *drop)
{
- ID *id = (ID *)drag->poin;
+ ID *id = drag->poin;
if (id) {
RNA_string_set(drop->ptr, "name", id->name + 2);
+ RNA_struct_property_unset(drop->ptr, "filepath");
}
- if (drag->path[0]) {
+ else if (drag->path[0]) {
RNA_string_set(drop->ptr, "filepath", drag->path);
+ RNA_struct_property_unset(drop->ptr, "name");
}
}
@@ -768,6 +771,8 @@ static void node_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegi
case NC_GPENCIL:
if (wmn->action == NA_EDITED)
ED_region_tag_redraw(ar);
+ else if (wmn->data & ND_GPENCIL_EDITMODE)
+ ED_region_tag_redraw(ar);
break;
}
}
diff --git a/source/blender/editors/space_outliner/CMakeLists.txt b/source/blender/editors/space_outliner/CMakeLists.txt
index 4db47b75502..289d6e715e1 100644
--- a/source/blender/editors/space_outliner/CMakeLists.txt
+++ b/source/blender/editors/space_outliner/CMakeLists.txt
@@ -22,12 +22,14 @@ set(INC
../include
../../blenkernel
../../blenlib
- ../../blenfont
+ ../../blentranslation
../../imbuf
+ ../../gpu
../../makesdna
../../makesrna
../../windowmanager
../../../../intern/guardedalloc
+ ../../../../intern/glew-mx
)
set(INC_SYS
@@ -50,4 +52,6 @@ if(WITH_INTERNATIONAL)
add_definitions(-DWITH_INTERNATIONAL)
endif()
+add_definitions(${GL_DEFINITIONS})
+
blender_add_lib(bf_editor_space_outliner "${SRC}" "${INC}" "${INC_SYS}")
diff --git a/source/blender/editors/space_outliner/SConscript b/source/blender/editors/space_outliner/SConscript
index db8041f0235..dce559a21df 100644
--- a/source/blender/editors/space_outliner/SConscript
+++ b/source/blender/editors/space_outliner/SConscript
@@ -28,15 +28,19 @@
Import ('env')
sources = env.Glob('*.c')
+
defs = []
+defs == env['BF_GL_DEFINITIONS']
incs = [
'#/intern/guardedalloc',
- '#/extern/glew/include',
+ env['BF_GLEW_INC'],
+ '#/intern/glew-mx',
'../include',
- '../../blenfont',
'../../blenkernel',
'../../blenlib',
+ '../../blentranslation',
+ '../../gpu',
'../../imbuf',
'../../makesdna',
'../../makesrna',
diff --git a/source/blender/editors/space_outliner/outliner_draw.c b/source/blender/editors/space_outliner/outliner_draw.c
index 7eb90953df4..ac9e2e36ded 100644
--- a/source/blender/editors/space_outliner/outliner_draw.c
+++ b/source/blender/editors/space_outliner/outliner_draw.c
@@ -29,7 +29,9 @@
* \ingroup spoutliner
*/
+#include "DNA_anim_types.h"
#include "DNA_armature_types.h"
+#include "DNA_gpencil_types.h"
#include "DNA_group_types.h"
#include "DNA_lamp_types.h"
#include "DNA_object_types.h"
@@ -41,11 +43,12 @@
#include "BLI_utildefines.h"
#include "BLI_mempool.h"
-#include "BLF_translation.h"
+#include "BLT_translation.h"
#include "BKE_context.h"
#include "BKE_deform.h"
#include "BKE_depsgraph.h"
+#include "BKE_fcurve.h"
#include "BKE_global.h"
#include "BKE_library.h"
#include "BKE_main.h"
@@ -55,6 +58,7 @@
#include "BKE_object.h"
#include "ED_armature.h"
+#include "ED_keyframing.h"
#include "ED_object.h"
#include "ED_screen.h"
@@ -168,20 +172,51 @@ static void restrictbutton_recursive_bone(bContext *C, bArmature *arm, Bone *bon
}
static void restrictbutton_recursive_child(bContext *C, Scene *scene, Object *ob_parent, char flag,
- bool state, bool deselect)
+ bool state, bool deselect, const char *rnapropname)
{
Main *bmain = CTX_data_main(C);
Object *ob;
+
for (ob = bmain->object.first; ob; ob = ob->id.next) {
if (BKE_object_is_child_recursive(ob_parent, ob)) {
- if (state) {
- ob->restrictflag |= flag;
- if (deselect) {
- ED_base_object_select(BKE_scene_base_find(scene, ob), BA_DESELECT);
+ /* only do if child object is selectable */
+ if ((flag == OB_RESTRICT_SELECT) || (ob->restrictflag & OB_RESTRICT_SELECT) == 0) {
+ if (state) {
+ ob->restrictflag |= flag;
+ if (deselect) {
+ ED_base_object_select(BKE_scene_base_find(scene, ob), BA_DESELECT);
+ }
+ }
+ else {
+ ob->restrictflag &= ~flag;
}
}
- else {
- ob->restrictflag &= ~flag;
+
+ if (rnapropname) {
+ PointerRNA ptr;
+ PropertyRNA *prop;
+ ID *id;
+ bAction *action;
+ FCurve *fcu;
+ bool driven, special;
+
+ RNA_id_pointer_create(&ob->id, &ptr);
+ prop = RNA_struct_find_property(&ptr, rnapropname);
+ fcu = rna_get_fcurve_context_ui(C, &ptr, prop, 0, NULL, &action, &driven, &special);
+
+ if (fcu && !driven) {
+ id = ptr.id.data;
+ if (autokeyframe_cfra_can_key(scene, id)) {
+ ReportList *reports = CTX_wm_reports(C);
+ short flag = ANIM_get_keyframing_flags(scene, 1);
+
+ fcu->flag &= ~FCURVE_SELECTED;
+ insert_keyframe(reports, id, action, ((fcu->grp) ? (fcu->grp->name) : (NULL)),
+ fcu->rna_path, fcu->array_index, CFRA, flag);
+ /* Assuming this is not necessary here, since 'ancestor' object button will do it anyway. */
+ /* WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL); */
+ }
+ }
}
}
}
@@ -203,7 +238,7 @@ static void restrictbutton_view_cb(bContext *C, void *poin, void *poin2)
if (CTX_wm_window(C)->eventstate->ctrl) {
restrictbutton_recursive_child(C, scene, ob, OB_RESTRICT_VIEW,
- (ob->restrictflag & OB_RESTRICT_VIEW) != 0, true);
+ (ob->restrictflag & OB_RESTRICT_VIEW) != 0, true, "hide");
}
WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
@@ -226,7 +261,7 @@ static void restrictbutton_sel_cb(bContext *C, void *poin, void *poin2)
if (CTX_wm_window(C)->eventstate->ctrl) {
restrictbutton_recursive_child(C, scene, ob, OB_RESTRICT_SELECT,
- (ob->restrictflag & OB_RESTRICT_SELECT) != 0, true);
+ (ob->restrictflag & OB_RESTRICT_SELECT) != 0, true, NULL);
}
WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
@@ -239,7 +274,7 @@ static void restrictbutton_rend_cb(bContext *C, void *poin, void *poin2)
if (CTX_wm_window(C)->eventstate->ctrl) {
restrictbutton_recursive_child(C, (Scene *)poin, ob, OB_RESTRICT_RENDER,
- (ob->restrictflag & OB_RESTRICT_RENDER) != 0, false);
+ (ob->restrictflag & OB_RESTRICT_RENDER) != 0, false, "hide_render");
}
WM_event_add_notifier(C, NC_SCENE | ND_OB_RENDER, poin);
@@ -255,8 +290,7 @@ static void restrictbutton_modifier_cb(bContext *C, void *UNUSED(poin), void *po
Object *ob = (Object *)poin2;
DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
-
- WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
+ WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
}
static void restrictbutton_bone_visibility_cb(bContext *C, void *poin, void *poin2)
@@ -316,6 +350,11 @@ static void restrictbutton_ebone_visibility_cb(bContext *C, void *UNUSED(poin),
WM_event_add_notifier(C, NC_OBJECT | ND_POSE, NULL);
}
+static void restrictbutton_gp_layer_flag_cb(bContext *C, void *UNUSED(poin), void *UNUSED(poin2))
+{
+ WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
+}
+
static int group_restrict_flag(Group *gr, int flag)
{
GroupObject *gob;
@@ -407,6 +446,20 @@ static void restrictbutton_gr_restrict_render(bContext *C, void *poin, void *poi
WM_event_add_notifier(C, NC_GROUP, NULL);
}
+static void restrictbutton_id_user_toggle(bContext *UNUSED(C), void *poin, void *UNUSED(poin2))
+{
+ ID *id = (ID *)poin;
+
+ BLI_assert(id != NULL);
+
+ if (id->flag & LIB_FAKEUSER) {
+ id_us_plus(id);
+ }
+ else {
+ id_us_min(id);
+ }
+}
+
static void namebutton_cb(bContext *C, void *tsep, char *oldname)
{
@@ -417,7 +470,7 @@ static void namebutton_cb(bContext *C, void *tsep, char *oldname)
TreeStoreElem *tselem = tsep;
if (ts && tselem) {
- TreeElement *te = outliner_find_tse(soops, tselem);
+ TreeElement *te = outliner_find_tree_element(&soops->tree, tselem);
if (tselem->type == 0) {
test_idbutton(tselem->id->name); // library.c, unique name and alpha sort
@@ -514,11 +567,22 @@ static void namebutton_cb(bContext *C, void *tsep, char *oldname)
Object *ob = (Object *)tselem->id; // id = object
bActionGroup *grp = te->directdata;
- BLI_uniquename(&ob->pose->agroups, grp, CTX_DATA_(BLF_I18NCONTEXT_ID_ACTION, "Group"), '.',
+ BLI_uniquename(&ob->pose->agroups, grp, CTX_DATA_(BLT_I18NCONTEXT_ID_ACTION, "Group"), '.',
offsetof(bActionGroup, name), sizeof(grp->name));
WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
break;
}
+ case TSE_GP_LAYER:
+ {
+ bGPdata *gpd = (bGPdata *)tselem->id; // id = GP Datablock
+ bGPDlayer *gpl = te->directdata;
+
+ // XXX: name needs translation stuff
+ BLI_uniquename(&gpd->layers, gpl, "GP Layer", '.',
+ offsetof(bGPDlayer, info), sizeof(gpl->info));
+ WM_event_add_notifier(C, NC_GPENCIL | ND_DATA, gpd);
+ break;
+ }
case TSE_R_LAYER:
break;
}
@@ -554,29 +618,29 @@ static void outliner_draw_restrictbuts(uiBlock *block, Scene *scene, ARegion *ar
ob = (Object *)tselem->id;
RNA_pointer_create((ID *)ob, &RNA_Object, ob, &ptr);
- uiBlockSetEmboss(block, UI_EMBOSSN);
- bt = uiDefIconButR_prop(block, ICONTOG, 0, ICON_RESTRICT_VIEW_OFF,
+ UI_block_emboss_set(block, UI_EMBOSS_NONE);
+ bt = uiDefIconButR_prop(block, UI_BTYPE_ICON_TOGGLE, 0, ICON_RESTRICT_VIEW_OFF,
(int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX), te->ys, UI_UNIT_X, UI_UNIT_Y,
&ptr, object_prop_hide, -1, 0, 0, -1, -1,
TIP_("Restrict viewport visibility (Ctrl - Recursive)"));
- uiButSetFunc(bt, restrictbutton_view_cb, scene, ob);
- uiButSetFlag(bt, UI_BUT_DRAG_LOCK);
+ UI_but_func_set(bt, restrictbutton_view_cb, scene, ob);
+ UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
- bt = uiDefIconButR_prop(block, ICONTOG, 0, ICON_RESTRICT_SELECT_OFF,
+ bt = uiDefIconButR_prop(block, UI_BTYPE_ICON_TOGGLE, 0, ICON_RESTRICT_SELECT_OFF,
(int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_SELECTX), te->ys, UI_UNIT_X, UI_UNIT_Y,
&ptr, object_prop_hide_select, -1, 0, 0, -1, -1,
TIP_("Restrict viewport selection (Ctrl - Recursive)"));
- uiButSetFunc(bt, restrictbutton_sel_cb, scene, ob);
- uiButSetFlag(bt, UI_BUT_DRAG_LOCK);
+ UI_but_func_set(bt, restrictbutton_sel_cb, scene, ob);
+ UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
- bt = uiDefIconButR_prop(block, ICONTOG, 0, ICON_RESTRICT_RENDER_OFF,
+ bt = uiDefIconButR_prop(block, UI_BTYPE_ICON_TOGGLE, 0, ICON_RESTRICT_RENDER_OFF,
(int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_RENDERX), te->ys, UI_UNIT_X, UI_UNIT_Y,
&ptr, object_prop_hide_render, -1, 0, 0, -1, -1,
TIP_("Restrict rendering (Ctrl - Recursive)"));
- uiButSetFunc(bt, restrictbutton_rend_cb, scene, ob);
- uiButSetFlag(bt, UI_BUT_DRAG_LOCK);
+ UI_but_func_set(bt, restrictbutton_rend_cb, scene, ob);
+ UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
- uiBlockSetEmboss(block, UI_EMBOSS);
+ UI_block_emboss_set(block, UI_EMBOSS);
}
if (tselem->type == 0 && te->idcode == ID_GR) {
@@ -587,130 +651,153 @@ static void outliner_draw_restrictbuts(uiBlock *block, Scene *scene, ARegion *ar
if (gr->id.lib)
but_flag |= UI_BUT_DISABLED;
- uiBlockSetEmboss(block, UI_EMBOSSN);
+ UI_block_emboss_set(block, UI_EMBOSS_NONE);
restrict_bool = group_restrict_flag(gr, OB_RESTRICT_VIEW);
- bt = uiDefIconBut(block, ICONTOG, 0, restrict_bool ? ICON_RESTRICT_VIEW_ON : ICON_RESTRICT_VIEW_OFF,
+ bt = uiDefIconBut(block, UI_BTYPE_ICON_TOGGLE, 0, restrict_bool ? ICON_RESTRICT_VIEW_ON : ICON_RESTRICT_VIEW_OFF,
(int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX), te->ys, UI_UNIT_X, UI_UNIT_Y,
NULL, 0, 0, 0, 0, TIP_("Restrict/Allow visibility in the 3D View"));
- uiButSetFunc(bt, restrictbutton_gr_restrict_view, scene, gr);
- uiButSetFlag(bt, but_flag);
+ UI_but_func_set(bt, restrictbutton_gr_restrict_view, scene, gr);
+ UI_but_flag_enable(bt, but_flag);
restrict_bool = group_restrict_flag(gr, OB_RESTRICT_SELECT);
- bt = uiDefIconBut(block, ICONTOG, 0, restrict_bool ? ICON_RESTRICT_SELECT_ON : ICON_RESTRICT_SELECT_OFF,
+ bt = uiDefIconBut(block, UI_BTYPE_ICON_TOGGLE, 0, restrict_bool ? ICON_RESTRICT_SELECT_ON : ICON_RESTRICT_SELECT_OFF,
(int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_SELECTX), te->ys, UI_UNIT_X, UI_UNIT_Y,
NULL, 0, 0, 0, 0, TIP_("Restrict/Allow selection in the 3D View"));
- uiButSetFunc(bt, restrictbutton_gr_restrict_select, scene, gr);
- uiButSetFlag(bt, but_flag);
+ UI_but_func_set(bt, restrictbutton_gr_restrict_select, scene, gr);
+ UI_but_flag_enable(bt, but_flag);
restrict_bool = group_restrict_flag(gr, OB_RESTRICT_RENDER);
- bt = uiDefIconBut(block, ICONTOG, 0, restrict_bool ? ICON_RESTRICT_RENDER_ON : ICON_RESTRICT_RENDER_OFF,
+ bt = uiDefIconBut(block, UI_BTYPE_ICON_TOGGLE, 0, restrict_bool ? ICON_RESTRICT_RENDER_ON : ICON_RESTRICT_RENDER_OFF,
(int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_RENDERX), te->ys, UI_UNIT_X, UI_UNIT_Y,
NULL, 0, 0, 0, 0, TIP_("Restrict/Allow renderability"));
- uiButSetFunc(bt, restrictbutton_gr_restrict_render, scene, gr);
- uiButSetFlag(bt, but_flag);
+ UI_but_func_set(bt, restrictbutton_gr_restrict_render, scene, gr);
+ UI_but_flag_enable(bt, but_flag);
- uiBlockSetEmboss(block, UI_EMBOSS);
+ UI_block_emboss_set(block, UI_EMBOSS);
}
/* scene render layers and passes have toggle-able flags too! */
else if (tselem->type == TSE_R_LAYER) {
- uiBlockSetEmboss(block, UI_EMBOSSN);
+ UI_block_emboss_set(block, UI_EMBOSS_NONE);
- bt = uiDefIconButBitI(block, ICONTOGN, SCE_LAY_DISABLE, 0, ICON_CHECKBOX_HLT - 1,
+ bt = uiDefIconButBitI(block, UI_BTYPE_ICON_TOGGLE_N, SCE_LAY_DISABLE, 0, ICON_CHECKBOX_HLT - 1,
(int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX), te->ys, UI_UNIT_X,
UI_UNIT_Y, te->directdata, 0, 0, 0, 0, TIP_("Render this RenderLayer"));
- uiButSetFunc(bt, restrictbutton_r_lay_cb, tselem->id, NULL);
- uiButSetFlag(bt, UI_BUT_DRAG_LOCK);
+ UI_but_func_set(bt, restrictbutton_r_lay_cb, tselem->id, NULL);
+ UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
- uiBlockSetEmboss(block, UI_EMBOSS);
+ UI_block_emboss_set(block, UI_EMBOSS);
}
else if (tselem->type == TSE_R_PASS) {
int *layflag = te->directdata;
int passflag = 1 << tselem->nr;
- uiBlockSetEmboss(block, UI_EMBOSSN);
+ UI_block_emboss_set(block, UI_EMBOSS_NONE);
- bt = uiDefIconButBitI(block, ICONTOG, passflag, 0, ICON_CHECKBOX_HLT - 1,
+ bt = uiDefIconButBitI(block, UI_BTYPE_ICON_TOGGLE, passflag, 0, ICON_CHECKBOX_HLT - 1,
(int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX), te->ys, UI_UNIT_X,
UI_UNIT_Y, layflag, 0, 0, 0, 0, TIP_("Render this Pass"));
- uiButSetFunc(bt, restrictbutton_r_lay_cb, tselem->id, NULL);
- uiButSetFlag(bt, UI_BUT_DRAG_LOCK);
+ UI_but_func_set(bt, restrictbutton_r_lay_cb, tselem->id, NULL);
+ UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
layflag++; /* is lay_xor */
if (ELEM(passflag, SCE_PASS_SPEC, SCE_PASS_SHADOW, SCE_PASS_AO, SCE_PASS_REFLECT, SCE_PASS_REFRACT,
SCE_PASS_INDIRECT, SCE_PASS_EMIT, SCE_PASS_ENVIRONMENT))
{
- bt = uiDefIconButBitI(block, TOG, passflag, 0, (*layflag & passflag) ? ICON_DOT : ICON_BLANK1,
+ bt = uiDefIconButBitI(block, UI_BTYPE_TOGGLE, passflag, 0, (*layflag & passflag) ? ICON_DOT : ICON_BLANK1,
(int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_SELECTX), te->ys, UI_UNIT_X,
UI_UNIT_Y, layflag, 0, 0, 0, 0, TIP_("Exclude this Pass from Combined"));
- uiButSetFunc(bt, restrictbutton_r_lay_cb, tselem->id, NULL);
- uiButSetFlag(bt, UI_BUT_DRAG_LOCK);
+ UI_but_func_set(bt, restrictbutton_r_lay_cb, tselem->id, NULL);
+ UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
}
- uiBlockSetEmboss(block, UI_EMBOSS);
+ UI_block_emboss_set(block, UI_EMBOSS);
}
else if (tselem->type == TSE_MODIFIER) {
ModifierData *md = (ModifierData *)te->directdata;
ob = (Object *)tselem->id;
- uiBlockSetEmboss(block, UI_EMBOSSN);
- bt = uiDefIconButBitI(block, ICONTOGN, eModifierMode_Realtime, 0, ICON_RESTRICT_VIEW_OFF,
+ UI_block_emboss_set(block, UI_EMBOSS_NONE);
+ bt = uiDefIconButBitI(block, UI_BTYPE_ICON_TOGGLE_N, eModifierMode_Realtime, 0, ICON_RESTRICT_VIEW_OFF,
(int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX), te->ys, UI_UNIT_X,
UI_UNIT_Y, &(md->mode), 0, 0, 0, 0,
TIP_("Restrict/Allow visibility in the 3D View"));
- uiButSetFunc(bt, restrictbutton_modifier_cb, scene, ob);
- uiButSetFlag(bt, UI_BUT_DRAG_LOCK);
+ UI_but_func_set(bt, restrictbutton_modifier_cb, scene, ob);
+ UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
- bt = uiDefIconButBitI(block, ICONTOGN, eModifierMode_Render, 0, ICON_RESTRICT_RENDER_OFF,
+ bt = uiDefIconButBitI(block, UI_BTYPE_ICON_TOGGLE_N, eModifierMode_Render, 0, ICON_RESTRICT_RENDER_OFF,
(int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_RENDERX), te->ys, UI_UNIT_X,
UI_UNIT_Y, &(md->mode), 0, 0, 0, 0, TIP_("Restrict/Allow renderability"));
- uiButSetFunc(bt, restrictbutton_modifier_cb, scene, ob);
- uiButSetFlag(bt, UI_BUT_DRAG_LOCK);
+ UI_but_func_set(bt, restrictbutton_modifier_cb, scene, ob);
+ UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
- uiBlockSetEmboss(block, UI_EMBOSS);
+ UI_block_emboss_set(block, UI_EMBOSS);
}
else if (tselem->type == TSE_POSE_CHANNEL) {
bPoseChannel *pchan = (bPoseChannel *)te->directdata;
Bone *bone = pchan->bone;
ob = (Object *)tselem->id;
- uiBlockSetEmboss(block, UI_EMBOSSN);
- bt = uiDefIconButBitI(block, ICONTOG, BONE_HIDDEN_P, 0, ICON_RESTRICT_VIEW_OFF,
+ UI_block_emboss_set(block, UI_EMBOSS_NONE);
+ bt = uiDefIconButBitI(block, UI_BTYPE_ICON_TOGGLE, BONE_HIDDEN_P, 0, ICON_RESTRICT_VIEW_OFF,
(int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX), te->ys, UI_UNIT_X,
UI_UNIT_Y, &(bone->flag), 0, 0, 0, 0,
TIP_("Restrict/Allow visibility in the 3D View"));
- uiButSetFunc(bt, restrictbutton_bone_visibility_cb, ob->data, bone);
- uiButSetFlag(bt, UI_BUT_DRAG_LOCK);
+ UI_but_func_set(bt, restrictbutton_bone_visibility_cb, ob->data, bone);
+ UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
- bt = uiDefIconButBitI(block, ICONTOG, BONE_UNSELECTABLE, 0, ICON_RESTRICT_SELECT_OFF,
+ bt = uiDefIconButBitI(block, UI_BTYPE_ICON_TOGGLE, BONE_UNSELECTABLE, 0, ICON_RESTRICT_SELECT_OFF,
(int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_SELECTX), te->ys, UI_UNIT_X,
UI_UNIT_Y, &(bone->flag), 0, 0, 0, 0,
TIP_("Restrict/Allow selection in the 3D View"));
- uiButSetFunc(bt, restrictbutton_bone_select_cb, ob->data, bone);
- uiButSetFlag(bt, UI_BUT_DRAG_LOCK);
+ UI_but_func_set(bt, restrictbutton_bone_select_cb, ob->data, bone);
+ UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
- uiBlockSetEmboss(block, UI_EMBOSS);
+ UI_block_emboss_set(block, UI_EMBOSS);
}
else if (tselem->type == TSE_EBONE) {
EditBone *ebone = (EditBone *)te->directdata;
- uiBlockSetEmboss(block, UI_EMBOSSN);
- bt = uiDefIconButBitI(block, ICONTOG, BONE_HIDDEN_A, 0, ICON_RESTRICT_VIEW_OFF,
+ UI_block_emboss_set(block, UI_EMBOSS_NONE);
+ bt = uiDefIconButBitI(block, UI_BTYPE_ICON_TOGGLE, BONE_HIDDEN_A, 0, ICON_RESTRICT_VIEW_OFF,
(int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX), te->ys, UI_UNIT_X,
UI_UNIT_Y, &(ebone->flag), 0, 0, 0, 0,
TIP_("Restrict/Allow visibility in the 3D View"));
- uiButSetFunc(bt, restrictbutton_ebone_visibility_cb, NULL, ebone);
- uiButSetFlag(bt, UI_BUT_DRAG_LOCK);
+ UI_but_func_set(bt, restrictbutton_ebone_visibility_cb, NULL, ebone);
+ UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
- bt = uiDefIconButBitI(block, ICONTOG, BONE_UNSELECTABLE, 0, ICON_RESTRICT_SELECT_OFF,
+ bt = uiDefIconButBitI(block, UI_BTYPE_ICON_TOGGLE, BONE_UNSELECTABLE, 0, ICON_RESTRICT_SELECT_OFF,
(int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_SELECTX), te->ys, UI_UNIT_X,
UI_UNIT_Y, &(ebone->flag), 0, 0, 0, 0,
TIP_("Restrict/Allow selection in the 3D View"));
- uiButSetFunc(bt, restrictbutton_ebone_select_cb, NULL, ebone);
- uiButSetFlag(bt, UI_BUT_DRAG_LOCK);
+ UI_but_func_set(bt, restrictbutton_ebone_select_cb, NULL, ebone);
+ UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
- uiBlockSetEmboss(block, UI_EMBOSS);
+ UI_block_emboss_set(block, UI_EMBOSS);
+ }
+ else if (tselem->type == TSE_GP_LAYER) {
+ bGPDlayer *gpl = (bGPDlayer *)te->directdata;
+
+ UI_block_emboss_set(block, UI_EMBOSS_NONE);
+
+ bt = uiDefIconButBitS(block, UI_BTYPE_ICON_TOGGLE, GP_LAYER_HIDE, 0, ICON_RESTRICT_VIEW_OFF,
+ (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX), te->ys, UI_UNIT_X,
+ UI_UNIT_Y, &gpl->flag, 0, 0, 0, 0,
+ TIP_("Restrict/Allow visibility in the 3D View"));
+ UI_but_func_set(bt, restrictbutton_gp_layer_flag_cb, NULL, gpl);
+ UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
+
+ bt = uiDefIconButBitS(block, UI_BTYPE_ICON_TOGGLE, GP_LAYER_LOCKED, 0, ICON_UNLOCKED,
+ (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_SELECTX), te->ys, UI_UNIT_X,
+ UI_UNIT_Y, &gpl->flag, 0, 0, 0, 0,
+ TIP_("Restrict/Allow editing of strokes and keyframes in this layer"));
+ UI_but_func_set(bt, restrictbutton_gp_layer_flag_cb, NULL, gpl);
+ UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
+
+ /* TODO: visibility in renders */
+
+ UI_block_emboss_set(block, UI_EMBOSS);
}
}
@@ -718,6 +805,66 @@ static void outliner_draw_restrictbuts(uiBlock *block, Scene *scene, ARegion *ar
}
}
+static void outliner_draw_userbuts(uiBlock *block, ARegion *ar, SpaceOops *soops, ListBase *lb)
+{
+ uiBut *bt;
+ TreeElement *te;
+ TreeStoreElem *tselem;
+
+ for (te = lb->first; te; te = te->next) {
+ tselem = TREESTORE(te);
+ if (te->ys + 2 * UI_UNIT_Y >= ar->v2d.cur.ymin && te->ys <= ar->v2d.cur.ymax) {
+ if (tselem->type == 0) {
+ ID *id = tselem->id;
+ const char *tip = NULL;
+ int icon = ICON_NONE;
+ char buf[16] = "";
+ int but_flag = UI_BUT_DRAG_LOCK;
+
+ if (id->lib)
+ but_flag |= UI_BUT_DISABLED;
+
+ UI_block_emboss_set(block, UI_EMBOSS_NONE);
+
+ if (id->flag & LIB_FAKEUSER) {
+ icon = ICON_FILE_TICK;
+ tip = TIP_("Datablock will be retained using a fake user");
+ }
+ else {
+ icon = ICON_X;
+ tip = TIP_("Datablock has no users and will be deleted");
+ }
+ bt = uiDefIconButBitS(block, UI_BTYPE_TOGGLE, LIB_FAKEUSER, 1, icon,
+ (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX), te->ys, UI_UNIT_X, UI_UNIT_Y,
+ &id->flag, 0, 0, 0, 0, tip);
+ UI_but_func_set(bt, restrictbutton_id_user_toggle, id, NULL);
+ UI_but_flag_enable(bt, but_flag);
+
+
+ BLI_str_format_int_grouped(buf, id->us);
+ bt = uiDefBut(block, UI_BTYPE_BUT, 1, buf,
+ (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_SELECTX), te->ys,
+ UI_UNIT_X, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0,
+ TIP_("Number of users of this datablock"));
+ UI_but_flag_enable(bt, but_flag);
+
+
+ bt = uiDefButBitS(block, UI_BTYPE_TOGGLE, LIB_FAKEUSER, 1, (id->flag & LIB_FAKEUSER) ? "F" : " ",
+ (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_RENDERX), te->ys, UI_UNIT_X, UI_UNIT_Y,
+ &id->flag, 0, 0, 0, 0,
+ TIP_("Datablock has a 'fake' user which will keep it in the file "
+ "even if nothing else uses it"));
+ UI_but_func_set(bt, restrictbutton_id_user_toggle, id, NULL);
+ UI_but_flag_enable(bt, but_flag);
+
+ UI_block_emboss_set(block, UI_EMBOSS);
+ }
+ }
+
+ if (TSELEM_OPEN(tselem, soops)) outliner_draw_userbuts(block, ar, soops, &te->subtree);
+ }
+}
+
static void outliner_draw_rnacols(ARegion *ar, int sizex)
{
View2D *v2d = &ar->v2d;
@@ -745,8 +892,6 @@ static void outliner_draw_rnabuts(uiBlock *block, Scene *scene, ARegion *ar, Spa
TreeStoreElem *tselem;
PointerRNA *ptr;
PropertyRNA *prop;
-
- uiBlockSetEmboss(block, UI_EMBOSST);
for (te = lb->first; te; te = te->next) {
tselem = TREESTORE(te);
@@ -759,7 +904,7 @@ static void outliner_draw_rnabuts(uiBlock *block, Scene *scene, ARegion *ar, Spa
if (RNA_property_type(prop) == PROP_POINTER) {
uiBut *but = uiDefAutoButR(block, ptr, prop, -1, "", ICON_NONE, sizex, te->ys,
OL_RNA_COL_SIZEX, UI_UNIT_Y - 1);
- uiButSetFlag(but, UI_BUT_DISABLED);
+ UI_but_flag_enable(but, UI_BUT_DISABLED);
}
else if (RNA_property_type(prop) == PROP_ENUM) {
uiDefAutoButR(block, ptr, prop, -1, NULL, ICON_NONE, sizex, te->ys, OL_RNA_COL_SIZEX,
@@ -783,7 +928,7 @@ static void outliner_draw_rnabuts(uiBlock *block, Scene *scene, ARegion *ar, Spa
if (TSELEM_OPEN(tselem, soops)) outliner_draw_rnabuts(block, scene, ar, soops, sizex, &te->subtree);
}
- uiBlockSetEmboss(block, UI_EMBOSS);
+ UI_block_emboss_set(block, UI_EMBOSS);
}
static void outliner_buttons(const bContext *C, uiBlock *block, ARegion *ar, TreeElement *te)
@@ -807,12 +952,12 @@ static void outliner_buttons(const bContext *C, uiBlock *block, ARegion *ar, Tre
spx = te->xs + 1.8f * UI_UNIT_X;
dx = ar->v2d.cur.xmax - (spx + 3.2f * UI_UNIT_X);
- bt = uiDefBut(block, TEX, OL_NAMEBUTTON, "", spx, te->ys, dx, UI_UNIT_Y - 1, (void *)te->name,
+ bt = uiDefBut(block, UI_BTYPE_TEXT, OL_NAMEBUTTON, "", spx, te->ys, dx, UI_UNIT_Y - 1, (void *)te->name,
1.0, (float)len, 0, 0, "");
- uiButSetRenameFunc(bt, namebutton_cb, tselem);
+ UI_but_func_rename_set(bt, namebutton_cb, tselem);
/* returns false if button got removed */
- if (false == uiButActiveOnly(C, ar, block, bt)) {
+ if (false == UI_but_active_only(C, ar, block, bt)) {
tselem->flag &= ~TSE_TEXTBUT;
/* bad! (notifier within draw) without this, we don't get a refesh */
@@ -840,13 +985,46 @@ static void tselem_draw_icon_uibut(struct DrawIconArg *arg, int icon)
glDisable(GL_BLEND);
}
else {
- uiBut *but = uiDefIconBut(arg->block, LABEL, 0, icon, arg->xb, arg->yb, UI_UNIT_X, UI_UNIT_Y, NULL,
+ uiBut *but = uiDefIconBut(arg->block, UI_BTYPE_LABEL, 0, icon, arg->xb, arg->yb, UI_UNIT_X, UI_UNIT_Y, NULL,
0.0, 0.0, 1.0, arg->alpha, (arg->id && arg->id->lib) ? arg->id->lib->name : "");
if (arg->id)
- uiButSetDragID(but, arg->id);
+ UI_but_drag_set_id(but, arg->id);
+ }
+
+}
+
+static void tselem_draw_gp_icon_uibut(struct DrawIconArg *arg, ID *id, bGPDlayer *gpl)
+{
+ /* restrict column clip - skip it for now... */
+ if (arg->x >= arg->xmax) {
+ /* pass */
}
+ else {
+ PointerRNA ptr;
+ const float eps = 0.001f;
+ const bool is_stroke_visible = (gpl->color[3] > eps);
+ const bool is_fill_visible = (gpl->fill[3] > eps);
+ float w = 0.5f * UI_UNIT_X;
+ float h = 0.85f * UI_UNIT_Y;
+ RNA_pointer_create(id, &RNA_GPencilLayer, gpl, &ptr);
+
+ UI_block_align_begin(arg->block);
+
+ UI_block_emboss_set(arg->block, is_stroke_visible ? UI_EMBOSS : UI_EMBOSS_NONE);
+ uiDefButR(arg->block, UI_BTYPE_COLOR, 1, "", arg->xb, arg->yb, w, h,
+ &ptr, "color", -1,
+ 0, 0, 0, 0, NULL);
+
+ UI_block_emboss_set(arg->block, is_fill_visible ? UI_EMBOSS : UI_EMBOSS_NONE);
+ uiDefButR(arg->block, UI_BTYPE_COLOR, 1, "", arg->xb + w, arg->yb, w, h,
+ &ptr, "fill_color", -1,
+ 0, 0, 0, 0, NULL);
+
+ UI_block_emboss_set(arg->block, UI_EMBOSS_NONE);
+ UI_block_align_end(arg->block);
+ }
}
static void tselem_draw_icon(uiBlock *block, int xmax, float x, float y, TreeStoreElem *tselem, TreeElement *te,
@@ -946,6 +1124,7 @@ static void tselem_draw_icon(uiBlock *block, int xmax, float x, float y, TreeSto
UI_icon_draw(x, y, ICON_MOD_BEVEL); break;
case eModifierType_Smooth:
case eModifierType_LaplacianSmooth:
+ case eModifierType_CorrectiveSmooth:
UI_icon_draw(x, y, ICON_MOD_SMOOTH); break;
case eModifierType_SimpleDeform:
UI_icon_draw(x, y, ICON_MOD_SIMPLEDEFORM); break;
@@ -990,6 +1169,10 @@ static void tselem_draw_icon(uiBlock *block, int xmax, float x, float y, TreeSto
UI_icon_draw(x, y, ICON_MOD_WIREFRAME); break;
case eModifierType_LaplacianDeform:
UI_icon_draw(x, y, ICON_MOD_MESHDEFORM); break; /* XXX, needs own icon */
+ case eModifierType_DataTransfer:
+ UI_icon_draw(x, y, ICON_MOD_DATA_TRANSFER); break;
+ case eModifierType_NormalEdit:
+ UI_icon_draw(x, y, ICON_MOD_NORMALEDIT); break;
/* Default */
case eModifierType_None:
case eModifierType_ShapeKey:
@@ -1042,6 +1225,9 @@ static void tselem_draw_icon(uiBlock *block, int xmax, float x, float y, TreeSto
else
UI_icon_draw(x, y, RNA_struct_ui_icon(te->rnaptr.type));
break;
+ case TSE_GP_LAYER:
+ tselem_draw_gp_icon_uibut(&arg, tselem->id, te->directdata);
+ break;
default:
UI_icon_draw(x, y, ICON_DOT); break;
}
@@ -1135,6 +1321,8 @@ static void tselem_draw_icon(uiBlock *block, int xmax, float x, float y, TreeSto
tselem_draw_icon_uibut(&arg, ICON_LIBRARY_DATA_DIRECT); break;
case ID_LS:
tselem_draw_icon_uibut(&arg, ICON_LINE_DATA); break;
+ case ID_GD:
+ tselem_draw_icon_uibut(&arg, ICON_GREASEPENCIL); break;
}
}
}
@@ -1176,13 +1364,14 @@ static void outliner_draw_iconrow(bContext *C, uiBlock *block, Scene *scene, Spa
if (active != OL_DRAWSEL_NONE) {
float ufac = UI_UNIT_X / 20.0f;
- uiSetRoundBox(UI_CNR_ALL);
+ UI_draw_roundbox_corner_set(UI_CNR_ALL);
glColor4ub(255, 255, 255, 100);
- uiRoundBox((float) *offsx - 1.0f * ufac,
- (float)ys + 1.0f * ufac,
- (float)*offsx + UI_UNIT_X - 2.0f * ufac,
- (float)ys + UI_UNIT_Y - ufac,
- (float)UI_UNIT_Y / 2.0f - ufac);
+ UI_draw_roundbox(
+ (float) *offsx - 1.0f * ufac,
+ (float)ys + 1.0f * ufac,
+ (float)*offsx + UI_UNIT_X - 2.0f * ufac,
+ (float)ys + UI_UNIT_Y - ufac,
+ (float)UI_UNIT_Y / 2.0f - ufac);
glEnable(GL_BLEND); /* roundbox disables */
}
@@ -1217,8 +1406,9 @@ static void outliner_set_coord_tree_element(SpaceOops *soops, TreeElement *te, i
}
-static void outliner_draw_tree_element(bContext *C, uiBlock *block, Scene *scene, ARegion *ar, SpaceOops *soops,
- TreeElement *te, int startx, int *starty, TreeElement **te_edit)
+static void outliner_draw_tree_element(
+ bContext *C, uiBlock *block, const uiFontStyle *fstyle, Scene *scene, ARegion *ar, SpaceOops *soops,
+ TreeElement *te, int startx, int *starty, TreeElement **te_edit)
{
TreeElement *ten;
TreeStoreElem *tselem;
@@ -1322,12 +1512,13 @@ static void outliner_draw_tree_element(bContext *C, uiBlock *block, Scene *scene
/* active circle */
if (active != OL_DRAWSEL_NONE) {
- uiSetRoundBox(UI_CNR_ALL);
- uiRoundBox((float)startx + UI_UNIT_X,
- (float)*starty + 1.0f * ufac,
- (float)startx + 2.0f * UI_UNIT_X - 2.0f * ufac,
- (float)*starty + UI_UNIT_Y - 1.0f * ufac,
- UI_UNIT_Y / 2.0f - 1.0f * ufac);
+ UI_draw_roundbox_corner_set(UI_CNR_ALL);
+ UI_draw_roundbox(
+ (float)startx + UI_UNIT_X,
+ (float)*starty + 1.0f * ufac,
+ (float)startx + 2.0f * UI_UNIT_X - 2.0f * ufac,
+ (float)*starty + UI_UNIT_Y - 1.0f * ufac,
+ UI_UNIT_Y / 2.0f - 1.0f * ufac);
glEnable(GL_BLEND); /* roundbox disables it */
te->flag |= TE_ACTIVE; // for lookup in display hierarchies
@@ -1376,9 +1567,9 @@ static void outliner_draw_tree_element(bContext *C, uiBlock *block, Scene *scene
else if (ELEM(tselem->type, TSE_RNA_PROPERTY, TSE_RNA_ARRAY_ELEM)) UI_ThemeColorBlend(TH_BACK, TH_TEXT, 0.75f);
else UI_ThemeColor(TH_TEXT);
- UI_DrawString(startx + offsx, *starty + 5 * ufac, te->name);
+ UI_fontstyle_draw_simple(fstyle, startx + offsx, *starty + 5 * ufac, te->name);
- offsx += (int)(UI_UNIT_X + UI_GetStringWidth(te->name));
+ offsx += (int)(UI_UNIT_X + UI_fontstyle_string_width(fstyle, te->name));
/* closed item, we draw the icons, not when it's a scene, or master-server list though */
if (!TSELEM_OPEN(tselem, soops)) {
@@ -1416,13 +1607,15 @@ static void outliner_draw_tree_element(bContext *C, uiBlock *block, Scene *scene
if (TSELEM_OPEN(tselem, soops)) {
*starty -= UI_UNIT_Y;
-
- for (ten = te->subtree.first; ten; ten = ten->next)
- outliner_draw_tree_element(C, block, scene, ar, soops, ten, startx + UI_UNIT_X, starty, te_edit);
+
+ for (ten = te->subtree.first; ten; ten = ten->next) {
+ outliner_draw_tree_element(C, block, fstyle, scene, ar, soops, ten, startx + UI_UNIT_X, starty, te_edit);
+ }
}
else {
- for (ten = te->subtree.first; ten; ten = ten->next)
+ for (ten = te->subtree.first; ten; ten = ten->next) {
outliner_set_coord_tree_element(soops, ten, startx, *starty);
+ }
*starty -= UI_UNIT_Y;
}
@@ -1505,6 +1698,7 @@ static void outliner_draw_selection(ARegion *ar, SpaceOops *soops, ListBase *lb,
static void outliner_draw_tree(bContext *C, uiBlock *block, Scene *scene, ARegion *ar,
SpaceOops *soops, TreeElement **te_edit)
{
+ const uiFontStyle *fstyle = UI_FSTYLE_WIDGET;
TreeElement *te;
int starty, startx;
float col[3];
@@ -1535,7 +1729,7 @@ static void outliner_draw_tree(bContext *C, uiBlock *block, Scene *scene, ARegio
starty = (int)ar->v2d.tot.ymax - UI_UNIT_Y - OL_Y_OFFSET;
startx = 0;
for (te = soops->tree.first; te; te = te->next) {
- outliner_draw_tree_element(C, block, scene, ar, soops, te, startx, &starty, te_edit);
+ outliner_draw_tree_element(C, block, fstyle, scene, ar, soops, te, startx, &starty, te_edit);
}
}
@@ -1654,7 +1848,7 @@ void draw_outliner(const bContext *C)
/* draw outliner stuff (background, hierarchy lines and names) */
outliner_back(ar);
- block = uiBeginBlock(C, ar, __func__, UI_EMBOSS);
+ block = UI_block_begin(C, ar, __func__, UI_EMBOSS);
outliner_draw_tree((bContext *)C, block, scene, ar, soops, &te_edit);
if (ELEM(soops->outlinevis, SO_DATABLOCKS, SO_USERDEF)) {
@@ -1662,6 +1856,11 @@ void draw_outliner(const bContext *C)
outliner_draw_rnacols(ar, sizex_rna);
outliner_draw_rnabuts(block, scene, ar, soops, sizex_rna, &soops->tree);
}
+ else if ((soops->outlinevis == SO_ID_ORPHANS) && !(soops->flag & SO_HIDE_RESTRICTCOLS)) {
+ /* draw user toggle columns */
+ outliner_draw_restrictcols(ar);
+ outliner_draw_userbuts(block, ar, soops, &soops->tree);
+ }
else if (!(soops->flag & SO_HIDE_RESTRICTCOLS)) {
/* draw restriction columns */
outliner_draw_restrictcols(ar);
@@ -1673,8 +1872,8 @@ void draw_outliner(const bContext *C)
outliner_buttons(C, block, ar, te_edit);
}
- uiEndBlock(C, block);
- uiDrawBlock(C, block);
+ UI_block_end(C, block);
+ UI_block_draw(C, block);
/* clear flag that allows quick redraws */
soops->storeflag &= ~SO_TREESTORE_REDRAW;
diff --git a/source/blender/editors/space_outliner/outliner_edit.c b/source/blender/editors/space_outliner/outliner_edit.c
index ef621407abd..6d420674f3e 100644
--- a/source/blender/editors/space_outliner/outliner_edit.c
+++ b/source/blender/editors/space_outliner/outliner_edit.c
@@ -39,19 +39,24 @@
#include "BLI_blenlib.h"
#include "BLI_utildefines.h"
+#include "BLI_mempool.h"
-#include "BLF_translation.h"
+#include "BLT_translation.h"
#include "BKE_animsys.h"
#include "BKE_context.h"
#include "BKE_depsgraph.h"
+#include "BKE_global.h"
#include "BKE_library.h"
#include "BKE_main.h"
+#include "BKE_outliner_treehash.h"
#include "BKE_report.h"
#include "BKE_scene.h"
#include "BKE_material.h"
+#include "BKE_group.h"
#include "ED_object.h"
+#include "ED_outliner.h"
#include "ED_screen.h"
#include "ED_keyframing.h"
@@ -73,22 +78,6 @@
/* This is not used anywhere at the moment */
#if 0
-/* return 1 when levels were opened */
-static int outliner_open_back(SpaceOops *soops, TreeElement *te)
-{
- TreeStoreElem *tselem;
- int retval = 0;
-
- for (te = te->parent; te; te = te->parent) {
- tselem = TREESTORE(te);
- if (tselem->flag & TSE_CLOSED) {
- tselem->flag &= ~TSE_CLOSED;
- retval = 1;
- }
- }
- return retval;
-}
-
static void outliner_open_reveal(SpaceOops *soops, ListBase *lb, TreeElement *teFind, int *found)
{
TreeElement *te;
@@ -113,7 +102,9 @@ static void outliner_open_reveal(SpaceOops *soops, ListBase *lb, TreeElement *te
}
#endif
-static TreeElement *outliner_dropzone_element(const SpaceOops *soops, TreeElement *te, const float fmval[2], const int children)
+static TreeElement *outliner_dropzone_element(
+ const SpaceOops *soops, TreeElement *te,
+ const float fmval[2], const bool children)
{
if ((fmval[1] > te->ys) && (fmval[1] < (te->ys + UI_UNIT_Y))) {
/* name and first icon */
@@ -132,7 +123,7 @@ static TreeElement *outliner_dropzone_element(const SpaceOops *soops, TreeElemen
}
/* Used for drag and drop parenting */
-TreeElement *outliner_dropzone_find(const SpaceOops *soops, const float fmval[2], const int children)
+TreeElement *outliner_dropzone_find(const SpaceOops *soops, const float fmval[2], const bool children)
{
TreeElement *te;
@@ -229,7 +220,7 @@ static void do_item_rename(ARegion *ar, TreeElement *te, TreeStoreElem *tselem,
else if (tselem->id->lib) {
BKE_report(reports, RPT_WARNING, "Cannot edit external libdata");
}
- else if (te->idcode == ID_LI && te->parent) {
+ else if (te->idcode == ID_LI && ((Library *)tselem->id)->parent) {
BKE_report(reports, RPT_WARNING, "Cannot edit the path of an indirectly linked library");
}
else {
@@ -601,6 +592,50 @@ void OUTLINER_OT_selected_toggle(wmOperatorType *ot)
/* Show Active --------------------------------------------------- */
+static void outliner_set_coordinates_element_recursive(SpaceOops *soops, TreeElement *te, int startx, int *starty)
+{
+ TreeStoreElem *tselem = TREESTORE(te);
+
+ /* store coord and continue, we need coordinates for elements outside view too */
+ te->xs = (float)startx;
+ te->ys = (float)(*starty);
+ *starty -= UI_UNIT_Y;
+
+ if (TSELEM_OPEN(tselem, soops)) {
+ TreeElement *ten;
+ for (ten = te->subtree.first; ten; ten = ten->next) {
+ outliner_set_coordinates_element_recursive(soops, ten, startx + UI_UNIT_X, starty);
+ }
+ }
+}
+
+/* to retrieve coordinates with redrawing the entire tree */
+static void outliner_set_coordinates(ARegion *ar, SpaceOops *soops)
+{
+ TreeElement *te;
+ int starty = (int)(ar->v2d.tot.ymax) - UI_UNIT_Y;
+
+ for (te = soops->tree.first; te; te = te->next) {
+ outliner_set_coordinates_element_recursive(soops, te, 0, &starty);
+ }
+}
+
+/* return 1 when levels were opened */
+static int outliner_open_back(TreeElement *te)
+{
+ TreeStoreElem *tselem;
+ int retval = 0;
+
+ for (te = te->parent; te; te = te->parent) {
+ tselem = TREESTORE(te);
+ if (tselem->flag & TSE_CLOSED) {
+ tselem->flag &= ~TSE_CLOSED;
+ retval = 1;
+ }
+ }
+ return retval;
+}
+
static int outliner_show_active_exec(bContext *C, wmOperator *UNUSED(op))
{
SpaceOops *so = CTX_wm_space_outliner(C);
@@ -617,6 +652,11 @@ static int outliner_show_active_exec(bContext *C, wmOperator *UNUSED(op))
te = outliner_find_id(so, &so->tree, (ID *)OBACT);
if (te) {
+ /* open up tree to active object */
+ if (outliner_open_back(te)) {
+ outliner_set_coordinates(ar, so);
+ }
+
/* make te->ys center of view */
ytop = te->ys + BLI_rcti_size_y(&v2d->mask) / 2;
if (ytop > 0) ytop = 0;
@@ -642,7 +682,7 @@ void OUTLINER_OT_show_active(wmOperatorType *ot)
/* identifiers */
ot->name = "Show Active";
ot->idname = "OUTLINER_OT_show_active";
- ot->description = "Adjust the view so that the active Object is shown centered";
+ ot->description = "Open up the tree and adjust the view so that the active Object is shown centered";
/* callbacks */
ot->exec = outliner_show_active_exec;
@@ -690,37 +730,6 @@ void OUTLINER_OT_scroll_page(wmOperatorType *ot)
#if 0
-/* recursive helper for function below */
-static void outliner_set_coordinates_element(SpaceOops *soops, TreeElement *te, int startx, int *starty)
-{
- TreeStoreElem *tselem = TREESTORE(te);
-
- /* store coord and continue, we need coordinates for elements outside view too */
- te->xs = (float)startx;
- te->ys = (float)(*starty);
- *starty -= UI_UNIT_Y;
-
- if (TSELEM_OPEN(tselem, soops)) {
- TreeElement *ten;
- for (ten = te->subtree.first; ten; ten = ten->next) {
- outliner_set_coordinates_element(soops, ten, startx + UI_UNIT_X, starty);
- }
- }
-
-}
-
-/* to retrieve coordinates with redrawing the entire tree */
-static void outliner_set_coordinates(ARegion *ar, SpaceOops *soops)
-{
- TreeElement *te;
- int starty = (int)(ar->v2d.tot.ymax) - UI_UNIT_Y;
- int startx = 0;
-
- for (te = soops->tree.first; te; te = te->next) {
- outliner_set_coordinates_element(soops, te, startx, &starty);
- }
-}
-
/* find next element that has this name */
static TreeElement *outliner_find_name(SpaceOops *soops, ListBase *lb, char *name, int flags,
TreeElement *prev, int *prevFound)
@@ -780,7 +789,7 @@ static void outliner_find_panel(Scene *UNUSED(scene), ARegion *ar, SpaceOops *so
else {
/* pop up panel - no previous, or user didn't want search after previous */
name[0] = '\0';
-// XXX if (sbutton(name, 0, sizeof(name)-1, "Find: ") && name[0]) {
+// XXX if (sbutton(name, 0, sizeof(name) - 1, "Find: ") && name[0]) {
// te = outliner_find_name(soops, &soops->tree, name, flags, NULL, &prevFound);
// }
// else return; /* XXX RETURN! XXX */
@@ -1305,7 +1314,7 @@ static KeyingSet *verify_active_keyingset(Scene *scene, short add)
// XXX the default settings have yet to evolve
if ((add) && (ks == NULL)) {
ks = BKE_keyingset_add(&scene->keyingsets, NULL, NULL, KEYINGSET_ABSOLUTE, 0);
- scene->active_keyingset = BLI_countlist(&scene->keyingsets);
+ scene->active_keyingset = BLI_listbase_count(&scene->keyingsets);
}
return ks;
@@ -1347,7 +1356,7 @@ static void do_outliner_keyingset_editop(SpaceOops *soops, KeyingSet *ks, ListBa
/* TODO: what do we do with group name?
* for now, we don't supply one, and just let this use the KeyingSet name */
BKE_keyingset_add_path(ks, id, NULL, path, array_index, flag, groupmode);
- ks->active_path = BLI_countlist(&ks->paths);
+ ks->active_path = BLI_listbase_count(&ks->paths);
break;
}
case KEYINGSET_EDITMODE_REMOVE:
@@ -1453,6 +1462,62 @@ void OUTLINER_OT_keyingset_remove_selected(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
+
+/* ************************************************************** */
+/* ORPHANED DATABLOCKS */
+
+static int ed_operator_outliner_id_orphans_active(bContext *C)
+{
+ ScrArea *sa = CTX_wm_area(C);
+ if ((sa) && (sa->spacetype == SPACE_OUTLINER)) {
+ SpaceOops *so = CTX_wm_space_outliner(C);
+ return (so->outlinevis == SO_ID_ORPHANS);
+ }
+ return 0;
+}
+
+/* Purge Orphans Operator --------------------------------------- */
+
+static int outliner_orphans_purge_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(evt))
+{
+ /* present a prompt to informing users that this change is irreversible */
+ return WM_operator_confirm_message(C, op,
+ "Purging unused datablocks cannot be undone. "
+ "Click here to proceed...");
+}
+
+static int outliner_orphans_purge_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ /* Firstly, ensure that the file has been saved,
+ * so that the latest changes since the last save
+ * are retained...
+ */
+ WM_operator_name_call(C, "WM_OT_save_mainfile", WM_OP_EXEC_DEFAULT, NULL);
+
+ /* Now, reload the file to get rid of the orphans... */
+ WM_operator_name_call(C, "WM_OT_revert_mainfile", WM_OP_EXEC_DEFAULT, NULL);
+ return OPERATOR_FINISHED;
+}
+
+void OUTLINER_OT_orphans_purge(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->idname = "OUTLINER_OT_orphans_purge";
+ ot->name = "Purge All";
+ ot->description = "Clear all orphaned datablocks without any users from the file (cannot be undone)";
+
+ /* callbacks */
+ ot->invoke = outliner_orphans_purge_invoke;
+ ot->exec = outliner_orphans_purge_exec;
+ ot->poll = ed_operator_outliner_id_orphans_active;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+/* ************************************************************** */
+/* DRAG AND DROP OPERATORS */
+
/* ******************** Parent Drop Operator *********************** */
static int parent_drop_exec(bContext *C, wmOperator *op)
@@ -1500,7 +1565,7 @@ static int parent_drop_invoke(bContext *C, wmOperator *op, const wmEvent *event)
UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &fmval[0], &fmval[1]);
/* Find object hovered over */
- te = outliner_dropzone_find(soops, fmval, 1);
+ te = outliner_dropzone_find(soops, fmval, true);
if (te) {
RNA_string_set(op->ptr, "parent", te->name);
@@ -1543,8 +1608,8 @@ static int parent_drop_invoke(bContext *C, wmOperator *op, const wmEvent *event)
else {
/* Menu creation */
wmOperatorType *ot = WM_operatortype_find("OUTLINER_OT_parent_drop", false);
- uiPopupMenu *pup = uiPupMenuBegin(C, IFACE_("Set Parent To"), ICON_NONE);
- uiLayout *layout = uiPupMenuLayout(pup);
+ uiPopupMenu *pup = UI_popup_menu_begin(C, IFACE_("Set Parent To"), ICON_NONE);
+ uiLayout *layout = UI_popup_menu_layout(pup);
PointerRNA ptr;
@@ -1615,9 +1680,9 @@ static int parent_drop_invoke(bContext *C, wmOperator *op, const wmEvent *event)
uiItemFullO_ptr(layout, ot, IFACE_("Lattice Deform"), 0, ptr.data, WM_OP_EXEC_DEFAULT, 0);
}
- uiPupMenuEnd(C, pup);
+ UI_popup_menu_end(C, pup);
- return OPERATOR_CANCELLED;
+ return OPERATOR_INTERFACE;
}
}
else {
@@ -1715,7 +1780,7 @@ static int scene_drop_invoke(bContext *C, wmOperator *op, const wmEvent *event)
UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &fmval[0], &fmval[1]);
/* Find object hovered over */
- te = outliner_dropzone_find(soops, fmval, 0);
+ te = outliner_dropzone_find(soops, fmval, false);
if (te) {
Base *base;
@@ -1785,7 +1850,7 @@ static int material_drop_invoke(bContext *C, wmOperator *op, const wmEvent *even
UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &fmval[0], &fmval[1]);
/* Find object hovered over */
- te = outliner_dropzone_find(soops, fmval, 1);
+ te = outliner_dropzone_find(soops, fmval, true);
if (te) {
RNA_string_set(op->ptr, "object", te->name);
@@ -1829,3 +1894,98 @@ void OUTLINER_OT_material_drop(wmOperatorType *ot)
RNA_def_string(ot->srna, "material", "Material", MAX_ID_NAME, "Material", "Target Material");
}
+static int group_link_invoke(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ Main *bmain = CTX_data_main(C);
+ Group *group = NULL;
+ Object *ob = NULL;
+ Scene *scene = CTX_data_scene(C);
+ SpaceOops *soops = CTX_wm_space_outliner(C);
+ ARegion *ar = CTX_wm_region(C);
+ TreeElement *te = NULL;
+ char ob_name[MAX_ID_NAME - 2];
+ float fmval[2];
+
+ UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &fmval[0], &fmval[1]);
+
+ /* Find object hovered over */
+ te = outliner_dropzone_find(soops, fmval, true);
+
+ if (te) {
+ group = (Group *)BKE_libblock_find_name(ID_GR, te->name);
+
+ RNA_string_get(op->ptr, "object", ob_name);
+ ob = (Object *)BKE_libblock_find_name(ID_OB, ob_name);
+
+ if (ELEM(NULL, group, ob)) {
+ return OPERATOR_CANCELLED;
+ }
+ if (BKE_group_object_exists(group, ob)) {
+ return OPERATOR_FINISHED;
+ }
+
+ if (BKE_group_object_cyclic_check(bmain, ob, group)) {
+ BKE_report(op->reports, RPT_ERROR, "Could not add the group because of dependency cycle detected");
+ return OPERATOR_CANCELLED;
+ }
+
+ BKE_group_object_add(group, ob, scene, NULL);
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
+
+ return OPERATOR_FINISHED;
+ }
+
+ return OPERATOR_CANCELLED;
+}
+
+void OUTLINER_OT_group_link(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Link Object to Group";
+ ot->description = "Link Object to Group in Outliner";
+ ot->idname = "OUTLINER_OT_group_link";
+
+ /* api callbacks */
+ ot->invoke = group_link_invoke;
+
+ ot->poll = ED_operator_outliner_active;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
+
+ /* properties */
+ RNA_def_string(ot->srna, "object", "Object", MAX_ID_NAME, "Object", "Target Object");
+}
+
+/******** Utils to clear any ref to freed ID... **********/
+
+void ED_outliner_id_unref(SpaceOops *so, const ID *id)
+{
+ /* Some early out checks. */
+ if (!TREESTORE_ID_TYPE(id)) {
+ return; /* ID type is not used by outilner... */
+ }
+
+ if (so->search_tse.id == id) {
+ so->search_tse.id = NULL;
+ }
+
+ if (so->treestore) {
+ TreeStoreElem *tselem;
+ BLI_mempool_iter iter;
+ bool changed = false;
+
+ BLI_mempool_iternew(so->treestore, &iter);
+ while ((tselem = BLI_mempool_iterstep(&iter))) {
+ if (tselem->id == id) {
+ tselem->id = NULL;
+ changed = true;
+ }
+ }
+ if (so->treehash && changed) {
+ /* rebuild hash table, because it depends on ids too */
+ /* postpone a full rebuild because this can be called many times on-free */
+ so->storeflag |= SO_TREESTORE_REBUILD;
+ }
+ }
+}
diff --git a/source/blender/editors/space_outliner/outliner_intern.h b/source/blender/editors/space_outliner/outliner_intern.h
index 317d33dd3e2..c89a1bb1b9f 100644
--- a/source/blender/editors/space_outliner/outliner_intern.h
+++ b/source/blender/editors/space_outliner/outliner_intern.h
@@ -36,12 +36,10 @@
/* internal exports only */
-struct wmWindowManager;
struct wmOperatorType;
struct TreeStoreElem;
struct bContext;
struct Scene;
-struct ARegion;
struct ID;
struct Object;
@@ -59,52 +57,17 @@ typedef struct TreeElement {
PointerRNA rnaptr; // RNA Pointer
} TreeElement;
+#define TREESTORE_ID_TYPE(_id) \
+ (ELEM(GS((_id)->name), ID_SCE, ID_LI, ID_OB, ID_ME, ID_CU, ID_MB, ID_NT, ID_MA, ID_TE, ID_IM, ID_LT, ID_LA, ID_CA) || \
+ ELEM(GS((_id)->name), ID_KE, ID_WO, ID_SPK, ID_GR, ID_AR, ID_AC, ID_BR, ID_PA, ID_GD, ID_LS) || \
+ ELEM(GS((_id)->name), ID_SCR, ID_WM, ID_TXT, ID_VF)) /* Only in 'blendfile' mode ... :/ */
+
/* TreeElement->flag */
#define TE_ACTIVE 1
#define TE_ICONROW 2
#define TE_LAZY_CLOSED 4
#define TE_FREE_NAME 8
-/* TreeStoreElem types */
-#define TSE_NLA 1
-#define TSE_NLA_ACTION 2
-#define TSE_DEFGROUP_BASE 3
-#define TSE_DEFGROUP 4
-#define TSE_BONE 5
-#define TSE_EBONE 6
-#define TSE_CONSTRAINT_BASE 7
-#define TSE_CONSTRAINT 8
-#define TSE_MODIFIER_BASE 9
-#define TSE_MODIFIER 10
-#define TSE_LINKED_OB 11
-// #define TSE_SCRIPT_BASE 12 // UNUSED
-#define TSE_POSE_BASE 13
-#define TSE_POSE_CHANNEL 14
-#define TSE_ANIM_DATA 15
-#define TSE_DRIVER_BASE 16
-#define TSE_DRIVER 17
-
-#define TSE_PROXY 18
-#define TSE_R_LAYER_BASE 19
-#define TSE_R_LAYER 20
-#define TSE_R_PASS 21
-#define TSE_LINKED_MAT 22
-/* NOTE, is used for light group */
-#define TSE_LINKED_LAMP 23
-#define TSE_POSEGRP_BASE 24
-#define TSE_POSEGRP 25
-#define TSE_SEQUENCE 26
-#define TSE_SEQ_STRIP 27
-#define TSE_SEQUENCE_DUP 28
-#define TSE_LINKED_PSYS 29
-#define TSE_RNA_STRUCT 30
-#define TSE_RNA_PROPERTY 31
-#define TSE_RNA_ARRAY_ELEM 32
-#define TSE_NLA_TRACK 33
-#define TSE_KEYMAP 34
-#define TSE_KEYMAP_ITEM 35
-#define TSE_ID_BASE 36
-
/* button events */
#define OL_NAMEBUTTON 1
@@ -166,6 +129,7 @@ void outliner_free_tree(ListBase *lb);
void outliner_cleanup_tree(struct SpaceOops *soops);
TreeElement *outliner_find_tse(struct SpaceOops *soops, TreeStoreElem *tse);
+TreeElement *outliner_find_tree_element(ListBase *lb, TreeStoreElem *store_elem);
TreeElement *outliner_find_id(struct SpaceOops *soops, ListBase *lb, struct ID *id);
struct ID *outliner_search_back(SpaceOops *soops, TreeElement *te, short idcode);
@@ -205,7 +169,7 @@ void group_toggle_renderability_cb(struct bContext *C, struct Scene *scene, Tree
void item_rename_cb(struct bContext *C, struct Scene *scene, TreeElement *te, struct TreeStoreElem *tsep, struct TreeStoreElem *tselem);
-TreeElement *outliner_dropzone_find(const struct SpaceOops *soops, const float fmval[2], const int children);
+TreeElement *outliner_dropzone_find(const struct SpaceOops *soops, const float fmval[2], const bool children);
/* ...................................................... */
void OUTLINER_OT_item_activate(struct wmOperatorType *ot);
@@ -233,21 +197,26 @@ void OUTLINER_OT_keyingset_remove_selected(struct wmOperatorType *ot);
void OUTLINER_OT_drivers_add_selected(struct wmOperatorType *ot);
void OUTLINER_OT_drivers_delete_selected(struct wmOperatorType *ot);
+void OUTLINER_OT_orphans_purge(struct wmOperatorType *ot);
+
void OUTLINER_OT_parent_drop(struct wmOperatorType *ot);
void OUTLINER_OT_parent_clear(struct wmOperatorType *ot);
void OUTLINER_OT_scene_drop(struct wmOperatorType *ot);
void OUTLINER_OT_material_drop(struct wmOperatorType *ot);
+void OUTLINER_OT_group_link(struct wmOperatorType *ot);
/* outliner_tools.c ---------------------------------------------- */
void OUTLINER_OT_operation(struct wmOperatorType *ot);
+void OUTLINER_OT_scene_operation(struct wmOperatorType *ot);
void OUTLINER_OT_object_operation(struct wmOperatorType *ot);
void OUTLINER_OT_group_operation(struct wmOperatorType *ot);
void OUTLINER_OT_id_operation(struct wmOperatorType *ot);
void OUTLINER_OT_data_operation(struct wmOperatorType *ot);
void OUTLINER_OT_animdata_operation(struct wmOperatorType *ot);
void OUTLINER_OT_action_set(struct wmOperatorType *ot);
-
+void OUTLINER_OT_constraint_operation(struct wmOperatorType *ot);
+void OUTLINER_OT_modifier_operation(struct wmOperatorType *ot);
/* ---------------------------------------------------------------- */
/* outliner_ops.c */
diff --git a/source/blender/editors/space_outliner/outliner_ops.c b/source/blender/editors/space_outliner/outliner_ops.c
index d735b5e75cf..839d44df25d 100644
--- a/source/blender/editors/space_outliner/outliner_ops.c
+++ b/source/blender/editors/space_outliner/outliner_ops.c
@@ -30,7 +30,6 @@
#include "DNA_space_types.h"
-#include "BLI_utildefines.h"
#include "RNA_access.h"
@@ -49,12 +48,15 @@ void outliner_operatortypes(void)
WM_operatortype_append(OUTLINER_OT_item_openclose);
WM_operatortype_append(OUTLINER_OT_item_rename);
WM_operatortype_append(OUTLINER_OT_operation);
+ WM_operatortype_append(OUTLINER_OT_scene_operation);
WM_operatortype_append(OUTLINER_OT_object_operation);
WM_operatortype_append(OUTLINER_OT_group_operation);
WM_operatortype_append(OUTLINER_OT_id_operation);
WM_operatortype_append(OUTLINER_OT_data_operation);
WM_operatortype_append(OUTLINER_OT_animdata_operation);
WM_operatortype_append(OUTLINER_OT_action_set);
+ WM_operatortype_append(OUTLINER_OT_constraint_operation);
+ WM_operatortype_append(OUTLINER_OT_modifier_operation);
WM_operatortype_append(OUTLINER_OT_show_one_level);
WM_operatortype_append(OUTLINER_OT_show_active);
@@ -73,11 +75,14 @@ void outliner_operatortypes(void)
WM_operatortype_append(OUTLINER_OT_drivers_add_selected);
WM_operatortype_append(OUTLINER_OT_drivers_delete_selected);
+
+ WM_operatortype_append(OUTLINER_OT_orphans_purge);
WM_operatortype_append(OUTLINER_OT_parent_drop);
WM_operatortype_append(OUTLINER_OT_parent_clear);
WM_operatortype_append(OUTLINER_OT_scene_drop);
WM_operatortype_append(OUTLINER_OT_material_drop);
+ WM_operatortype_append(OUTLINER_OT_group_link);
}
void outliner_keymap(wmKeyConfig *keyconf)
diff --git a/source/blender/editors/space_outliner/outliner_select.c b/source/blender/editors/space_outliner/outliner_select.c
index 6f5bf712d55..e52c68b57e9 100644
--- a/source/blender/editors/space_outliner/outliner_select.c
+++ b/source/blender/editors/space_outliner/outliner_select.c
@@ -290,6 +290,10 @@ static eOLDrawState tree_element_active_material(
}
}
if (set != OL_SETSEL_NONE) {
+ /* Tagging object for update seems a bit stupid here, but looks like we have to do it
+ * for render views to update. See T42973.
+ * Note that RNA material update does it too, see e.g. rna_MaterialSlot_update(). */
+ DAG_id_tag_update((ID *)ob, OB_RECALC_OB);
WM_event_add_notifier(C, NC_MATERIAL | ND_SHADING_LINKS, NULL);
}
return OL_DRAWSEL_NONE;
@@ -550,10 +554,12 @@ static eOLDrawState tree_element_active_bone(
Object *ob = OBACT;
if (ob) {
if (set != OL_SETSEL_EXTEND) {
- bPoseChannel *pchannel;
/* single select forces all other bones to get unselected */
- for (pchannel = ob->pose->chanbase.first; pchannel; pchannel = pchannel->next)
- pchannel->bone->flag &= ~(BONE_TIPSEL | BONE_SELECTED | BONE_ROOTSEL);
+ Bone *bone;
+ for (bone = arm->bonebase.first; bone != NULL; bone = bone->next) {
+ bone->flag &= ~(BONE_TIPSEL | BONE_SELECTED | BONE_ROOTSEL);
+ do_outliner_bone_select_recursive(arm, bone, false);
+ }
}
}
@@ -614,7 +620,7 @@ static eOLDrawState tree_element_active_ebone(
if (set != OL_SETSEL_NONE) {
if (set == OL_SETSEL_NORMAL) {
if (!(ebone->flag & BONE_HIDDEN_A)) {
- ED_armature_deselect_all(scene->obedit, 0); // deselect
+ ED_armature_deselect_all(scene->obedit);
tree_element_active_ebone__sel(C, scene, arm, ebone, true);
status = OL_DRAWSEL_NORMAL;
}
@@ -771,7 +777,7 @@ static eOLDrawState tree_element_active_sequence_dup(
continue;
}
-// if (!strcmp(p->strip->stripdata->name, seq->strip->stripdata->name))
+// if (STREQ(p->strip->stripdata->name, seq->strip->stripdata->name))
// XXX select_single_seq(p, 0);
p = p->next;
}
@@ -869,6 +875,9 @@ eOLDrawState tree_element_type_active(
return tree_element_active_sequence_dup(scene, te, tselem, set);
case TSE_KEYMAP_ITEM:
return tree_element_active_keymap_item(C, te, tselem, set);
+ case TSE_GP_LAYER:
+ //return tree_element_active_gplayer(C, scene, te, tselem, set);
+ break;
}
return OL_DRAWSEL_NONE;
@@ -911,7 +920,7 @@ static bool do_outliner_item_activate(bContext *C, Scene *scene, ARegion *ar, Sp
if (tselem->type != TSE_SEQUENCE && tselem->type != TSE_SEQ_STRIP && tselem->type != TSE_SEQUENCE_DUP)
tree_element_set_active_object(C, scene, soops, te,
(extend && tselem->type == 0) ? OL_SETSEL_EXTEND : OL_SETSEL_NORMAL,
- recursive && tselem->type == 0 );
+ recursive && tselem->type == 0);
if (tselem->type == 0) { // the lib blocks
/* editmode? */
diff --git a/source/blender/editors/space_outliner/outliner_tools.c b/source/blender/editors/space_outliner/outliner_tools.c
index d09ed1a100e..50171d7f032 100644
--- a/source/blender/editors/space_outliner/outliner_tools.c
+++ b/source/blender/editors/space_outliner/outliner_tools.c
@@ -33,6 +33,7 @@
#include "DNA_anim_types.h"
#include "DNA_armature_types.h"
+#include "DNA_gpencil_types.h"
#include "DNA_group_types.h"
#include "DNA_lamp_types.h"
#include "DNA_linestyle_types.h"
@@ -43,12 +44,15 @@
#include "DNA_sequence_types.h"
#include "DNA_world_types.h"
#include "DNA_object_types.h"
+#include "DNA_constraint_types.h"
+#include "DNA_modifier_types.h"
#include "BLI_blenlib.h"
#include "BLI_utildefines.h"
#include "BKE_animsys.h"
#include "BKE_context.h"
+#include "BKE_constraint.h"
#include "BKE_depsgraph.h"
#include "BKE_fcurve.h"
#include "BKE_group.h"
@@ -69,6 +73,7 @@
#include "UI_interface.h"
#include "UI_view2d.h"
+#include "UI_resources.h"
#include "RNA_access.h"
#include "RNA_define.h"
@@ -258,7 +263,90 @@ static void outliner_do_libdata_operation(bContext *C, Scene *scene, SpaceOops *
}
}
-/* */
+/* ******************************************** */
+typedef enum eOutliner_PropSceneOps {
+ OL_SCENE_OP_DELETE = 1
+} eOutliner_PropSceneOps;
+
+static EnumPropertyItem prop_scene_op_types[] = {
+ {OL_SCENE_OP_DELETE, "DELETE", ICON_X, "Delete", ""},
+ {0, NULL, 0, NULL, NULL}
+};
+
+static bool outliner_do_scene_operation(
+ bContext *C, eOutliner_PropSceneOps event, ListBase *lb,
+ bool (*operation_cb)(bContext *, eOutliner_PropSceneOps, TreeElement *, TreeStoreElem *))
+{
+ TreeElement *te;
+ TreeStoreElem *tselem;
+ bool success = false;
+
+ for (te = lb->first; te; te = te->next) {
+ tselem = TREESTORE(te);
+ if (tselem->flag & TSE_SELECTED) {
+ if (operation_cb(C, event, te, tselem)) {
+ success = true;
+ }
+ }
+ }
+
+ return success;
+}
+
+static bool scene_cb(bContext *C, eOutliner_PropSceneOps event, TreeElement *UNUSED(te), TreeStoreElem *tselem)
+{
+ Scene *scene = (Scene *)tselem->id;
+
+ if (event == OL_SCENE_OP_DELETE) {
+ if (ED_screen_delete_scene(C, scene)) {
+ WM_event_add_notifier(C, NC_SCENE | NA_REMOVED, scene);
+ }
+ else {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+static int outliner_scene_operation_exec(bContext *C, wmOperator *op)
+{
+ SpaceOops *soops = CTX_wm_space_outliner(C);
+ const eOutliner_PropSceneOps event = RNA_enum_get(op->ptr, "type");
+
+ if (outliner_do_scene_operation(C, event, &soops->tree, scene_cb) == false) {
+ return OPERATOR_CANCELLED;
+ }
+
+ if (event == OL_SCENE_OP_DELETE) {
+ outliner_cleanup_tree(soops);
+ ED_undo_push(C, "Delete Scene(s)");
+ }
+ else {
+ BLI_assert(0);
+ return OPERATOR_CANCELLED;
+ }
+
+ return OPERATOR_FINISHED;
+}
+
+void OUTLINER_OT_scene_operation(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Outliner Scene Operation";
+ ot->idname = "OUTLINER_OT_scene_operation";
+ ot->description = "Context menu for scene operations";
+
+ /* callbacks */
+ ot->invoke = WM_menu_invoke;
+ ot->exec = outliner_scene_operation_exec;
+ ot->poll = ED_operator_outliner_active;
+
+ ot->flag = 0;
+
+ ot->prop = RNA_def_enum(ot->srna, "type", prop_scene_op_types, 0, "Scene Operation", "");
+}
+/* ******************************************** */
static void object_select_cb(bContext *UNUSED(C), Scene *scene, TreeElement *te,
TreeStoreElem *UNUSED(tsep), TreeStoreElem *tselem)
@@ -422,8 +510,7 @@ static void group_instance_cb(bContext *C, Scene *scene, TreeElement *UNUSED(te)
{
Group *group = (Group *)tselem->id;
- Object *ob = ED_object_add_type(C, OB_EMPTY, scene->cursor, NULL, false, scene->layact);
- rename_id(&ob->id, group->id.name + 2);
+ Object *ob = ED_object_add_type(C, OB_EMPTY, group->id.name + 2, scene->cursor, NULL, false, scene->layact);
ob->dup_group = group;
ob->transflag |= OB_DUPLIGROUP;
id_lib_extern(&group->id);
@@ -462,7 +549,7 @@ void outliner_do_object_operation(bContext *C, Scene *scene_act, SpaceOops *soop
static void clear_animdata_cb(int UNUSED(event), TreeElement *UNUSED(te),
TreeStoreElem *tselem, void *UNUSED(arg))
{
- BKE_free_animdata(tselem->id);
+ BKE_animdata_free(tselem->id);
}
@@ -499,19 +586,39 @@ static void refreshdrivers_animdata_cb(int UNUSED(event), TreeElement *UNUSED(te
/* --------------------------------- */
+typedef enum eOutliner_PropDataOps {
+ OL_DOP_SELECT = 1,
+ OL_DOP_DESELECT,
+ OL_DOP_HIDE,
+ OL_DOP_UNHIDE,
+ OL_DOP_SELECT_LINKED,
+} eOutliner_PropDataOps;
+
+typedef enum eOutliner_PropConstraintOps {
+ OL_CONSTRAINTOP_ENABLE = 1,
+ OL_CONSTRAINTOP_DISABLE,
+ OL_CONSTRAINTOP_DELETE
+} eOutliner_PropConstraintOps;
+
+typedef enum eOutliner_PropModifierOps {
+ OL_MODIFIER_OP_TOGVIS = 1,
+ OL_MODIFIER_OP_TOGREN,
+ OL_MODIFIER_OP_DELETE
+} eOutliner_PropModifierOps;
+
static void pchan_cb(int event, TreeElement *te, TreeStoreElem *UNUSED(tselem), void *UNUSED(arg))
{
bPoseChannel *pchan = (bPoseChannel *)te->directdata;
- if (event == 1)
+ if (event == OL_DOP_SELECT)
pchan->bone->flag |= BONE_SELECTED;
- else if (event == 2)
+ else if (event == OL_DOP_DESELECT)
pchan->bone->flag &= ~BONE_SELECTED;
- else if (event == 3) {
+ else if (event == OL_DOP_HIDE) {
pchan->bone->flag |= BONE_HIDDEN_P;
pchan->bone->flag &= ~BONE_SELECTED;
}
- else if (event == 4)
+ else if (event == OL_DOP_UNHIDE)
pchan->bone->flag &= ~BONE_HIDDEN_P;
}
@@ -519,15 +626,15 @@ static void bone_cb(int event, TreeElement *te, TreeStoreElem *UNUSED(tselem), v
{
Bone *bone = (Bone *)te->directdata;
- if (event == 1)
+ if (event == OL_DOP_SELECT)
bone->flag |= BONE_SELECTED;
- else if (event == 2)
+ else if (event == OL_DOP_DESELECT)
bone->flag &= ~BONE_SELECTED;
- else if (event == 3) {
+ else if (event == OL_DOP_HIDE) {
bone->flag |= BONE_HIDDEN_P;
bone->flag &= ~BONE_SELECTED;
}
- else if (event == 4)
+ else if (event == OL_DOP_UNHIDE)
bone->flag &= ~BONE_HIDDEN_P;
}
@@ -535,22 +642,22 @@ static void ebone_cb(int event, TreeElement *te, TreeStoreElem *UNUSED(tselem),
{
EditBone *ebone = (EditBone *)te->directdata;
- if (event == 1)
+ if (event == OL_DOP_SELECT)
ebone->flag |= BONE_SELECTED;
- else if (event == 2)
+ else if (event == OL_DOP_DESELECT)
ebone->flag &= ~BONE_SELECTED;
- else if (event == 3) {
+ else if (event == OL_DOP_HIDE) {
ebone->flag |= BONE_HIDDEN_A;
ebone->flag &= ~BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL;
}
- else if (event == 4)
+ else if (event == OL_DOP_UNHIDE)
ebone->flag &= ~BONE_HIDDEN_A;
}
static void sequence_cb(int event, TreeElement *te, TreeStoreElem *tselem, void *scene_ptr)
{
Sequence *seq = (Sequence *)te->directdata;
- if (event == 1) {
+ if (event == OL_DOP_SELECT) {
Scene *scene = (Scene *)scene_ptr;
Editing *ed = BKE_sequencer_editing_get(scene, false);
if (BLI_findindex(ed->seqbasep, seq) != -1) {
@@ -561,9 +668,23 @@ static void sequence_cb(int event, TreeElement *te, TreeStoreElem *tselem, void
(void)tselem;
}
+static void gp_layer_cb(int event, TreeElement *te, TreeStoreElem *UNUSED(tselem), void *UNUSED(arg))
+{
+ bGPDlayer *gpl = (bGPDlayer *)te->directdata;
+
+ if (event == OL_DOP_SELECT)
+ gpl->flag |= GP_LAYER_SELECT;
+ else if (event == OL_DOP_DESELECT)
+ gpl->flag &= ~GP_LAYER_SELECT;
+ else if (event == OL_DOP_HIDE)
+ gpl->flag |= GP_LAYER_HIDE;
+ else if (event == OL_DOP_UNHIDE)
+ gpl->flag &= ~GP_LAYER_HIDE;
+}
+
static void data_select_linked_cb(int event, TreeElement *te, TreeStoreElem *UNUSED(tselem), void *C_v)
{
- if (event == 5) {
+ if (event == OL_DOP_SELECT_LINKED) {
if (RNA_struct_is_ID(te->rnaptr.type)) {
bContext *C = (bContext *) C_v;
ID *id = te->rnaptr.data;
@@ -573,6 +694,68 @@ static void data_select_linked_cb(int event, TreeElement *te, TreeStoreElem *UNU
}
}
+static void constraint_cb(int event, TreeElement *te, TreeStoreElem *UNUSED(tselem), void *C_v)
+{
+ bContext *C = C_v;
+ SpaceOops *soops = CTX_wm_space_outliner(C);
+ bConstraint *constraint = (bConstraint *)te->directdata;
+ Object *ob = (Object *)outliner_search_back(soops, te, ID_OB);
+
+ if (event == OL_CONSTRAINTOP_ENABLE) {
+ constraint->flag &= ~CONSTRAINT_OFF;
+ ED_object_constraint_update(ob);
+ WM_event_add_notifier(C, NC_OBJECT | ND_CONSTRAINT, ob);
+ }
+ else if (event == OL_CONSTRAINTOP_DISABLE) {
+ constraint->flag = CONSTRAINT_OFF;
+ ED_object_constraint_update(ob);
+ WM_event_add_notifier(C, NC_OBJECT | ND_CONSTRAINT, ob);
+ }
+ else if (event == OL_CONSTRAINTOP_DELETE) {
+ ListBase *lb = NULL;
+
+ if (TREESTORE(te->parent->parent)->type == TSE_POSE_CHANNEL) {
+ lb = &((bPoseChannel *)te->parent->parent->directdata)->constraints;
+ }
+ else {
+ lb = &ob->constraints;
+ }
+
+ if (BKE_constraint_remove_ex(lb, ob, constraint, true)) {
+ /* there's no active constraint now, so make sure this is the case */
+ BKE_constraints_active_set(&ob->constraints, NULL);
+ ED_object_constraint_update(ob); /* needed to set the flags on posebones correctly */
+ WM_event_add_notifier(C, NC_OBJECT | ND_CONSTRAINT | NA_REMOVED, ob);
+ te->store_elem->flag &= ~TSE_SELECTED;
+ }
+ }
+}
+
+static void modifier_cb(int event, TreeElement *te, TreeStoreElem *UNUSED(tselem), void *Carg)
+{
+ bContext *C = (bContext *)Carg;
+ Main *bmain = CTX_data_main(C);
+ SpaceOops *soops = CTX_wm_space_outliner(C);
+ ModifierData *md = (ModifierData *)te->directdata;
+ Object *ob = (Object *)outliner_search_back(soops, te, ID_OB);
+
+ if (event == OL_MODIFIER_OP_TOGVIS) {
+ md->mode ^= eModifierMode_Realtime;
+ DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
+ }
+ else if (event == OL_MODIFIER_OP_TOGREN) {
+ md->mode ^= eModifierMode_Render;
+ DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
+ }
+ else if (event == OL_MODIFIER_OP_DELETE) {
+ ED_object_modifier_remove(NULL, bmain, ob, md);
+ WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER | NA_REMOVED, ob);
+ te->store_elem->flag &= ~TSE_SELECTED;
+ }
+}
+
static void outliner_do_data_operation(SpaceOops *soops, int type, int event, ListBase *lb,
void (*operation_cb)(int, TreeElement *, TreeStoreElem *, void *),
void *arg)
@@ -593,14 +776,60 @@ static void outliner_do_data_operation(SpaceOops *soops, int type, int event, Li
}
}
+static Base *outline_delete_hierarchy(bContext *C, Scene *scene, Base *base)
+{
+ Base *child_base, *base_next;
+ Object *parent;
+
+ if (!base) {
+ return NULL;
+ }
+
+ for (child_base = scene->base.first; child_base; child_base = base_next) {
+ base_next = child_base->next;
+ for (parent = child_base->object->parent; parent && (parent != base->object); parent = parent->parent);
+ if (parent) {
+ base_next = outline_delete_hierarchy(C, scene, child_base);
+ }
+ }
+
+ base_next = base->next;
+ ED_base_object_free_and_unlink(CTX_data_main(C), scene, base);
+ return base_next;
+}
+
+static void object_delete_hierarchy_cb(
+ bContext *C, Scene *scene, TreeElement *te, TreeStoreElem *UNUSED(tsep), TreeStoreElem *tselem)
+{
+ Base *base = (Base *)te->directdata;
+ Object *obedit = scene->obedit;
+
+ if (!base) {
+ base = BKE_scene_base_find(scene, (Object *)tselem->id);
+ }
+ if (base) {
+ /* Check also library later. */
+ for (; obedit && (obedit != base->object); obedit = obedit->parent);
+ if (obedit == base->object) {
+ ED_object_editmode_exit(C, EM_FREEDATA | EM_FREEUNDO | EM_WAITCURSOR | EM_DO_UNDO);
+ }
+
+ outline_delete_hierarchy(C, scene, base);
+ te->directdata = NULL;
+ tselem->id = NULL;
+ }
+
+ WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene);
+}
+
/* **************************************** */
enum {
- OL_OP_ENDMARKER = 0,
- OL_OP_SELECT,
+ OL_OP_SELECT = 1,
OL_OP_DESELECT,
OL_OP_SELECT_HIERARCHY,
OL_OP_DELETE,
+ OL_OP_DELETE_HIERARCHY,
OL_OP_LOCALIZED, /* disabled, see below */
OL_OP_TOGVIS,
OL_OP_TOGSEL,
@@ -613,11 +842,12 @@ static EnumPropertyItem prop_object_op_types[] = {
{OL_OP_DESELECT, "DESELECT", 0, "Deselect", ""},
{OL_OP_SELECT_HIERARCHY, "SELECT_HIERARCHY", 0, "Select Hierarchy", ""},
{OL_OP_DELETE, "DELETE", 0, "Delete", ""},
+ {OL_OP_DELETE_HIERARCHY, "DELETE_HIERARCHY", 0, "Delete Hierarchy", ""},
{OL_OP_TOGVIS, "TOGVIS", 0, "Toggle Visible", ""},
{OL_OP_TOGSEL, "TOGSEL", 0, "Toggle Selectable", ""},
{OL_OP_TOGREN, "TOGREN", 0, "Toggle Renderable", ""},
{OL_OP_RENAME, "RENAME", 0, "Rename", ""},
- {OL_OP_ENDMARKER, NULL, 0, NULL, NULL}
+ {0, NULL, 0, NULL, NULL}
};
static int outliner_object_operation_exec(bContext *C, wmOperator *op)
@@ -672,6 +902,16 @@ static int outliner_object_operation_exec(bContext *C, wmOperator *op)
str = "Delete Objects";
WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene);
}
+ else if (event == OL_OP_DELETE_HIERARCHY) {
+ outliner_do_object_operation(C, scene, soops, &soops->tree, object_delete_hierarchy_cb);
+
+ /* XXX: See OL_OP_DELETE comment above. */
+ outliner_cleanup_tree(soops);
+
+ DAG_relations_tag_update(bmain);
+ str = "Delete Object Hierarchy";
+ WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene);
+ }
else if (event == OL_OP_LOCALIZED) { /* disabled, see above enum (ton) */
outliner_do_object_operation(C, scene, soops, &soops->tree, id_local_cb);
str = "Localized Objects";
@@ -725,15 +965,26 @@ void OUTLINER_OT_object_operation(wmOperatorType *ot)
/* **************************************** */
+typedef enum eOutliner_PropGroupOps {
+ OL_GROUPOP_UNLINK = 1,
+ OL_GROUPOP_LOCAL,
+ OL_GROUPOP_LINK,
+ OL_GROUPOP_INSTANCE,
+ OL_GROUPOP_TOGVIS,
+ OL_GROUPOP_TOGSEL,
+ OL_GROUPOP_TOGREN,
+ OL_GROUPOP_RENAME,
+} eOutliner_PropGroupOps;
+
static EnumPropertyItem prop_group_op_types[] = {
- {0, "UNLINK", 0, "Unlink Group", ""},
- {1, "LOCAL", 0, "Make Local Group", ""},
- {2, "LINK", 0, "Link Group Objects to Scene", ""},
- {3, "INSTANCE", 0, "Instance Groups in Scene", ""},
- {4, "TOGVIS", 0, "Toggle Visible Group", ""},
- {5, "TOGSEL", 0, "Toggle Selectable", ""},
- {6, "TOGREN", 0, "Toggle Renderable", ""},
- {7, "RENAME", 0, "Rename", ""},
+ {OL_GROUPOP_UNLINK, "UNLINK", 0, "Unlink Group", ""},
+ {OL_GROUPOP_LOCAL, "LOCAL", 0, "Make Local Group", ""},
+ {OL_GROUPOP_LINK, "LINK", 0, "Link Group Objects to Scene", ""},
+ {OL_GROUPOP_INSTANCE, "INSTANCE", 0, "Instance Groups in Scene", ""},
+ {OL_GROUPOP_TOGVIS, "TOGVIS", 0, "Toggle Visible Group", ""},
+ {OL_GROUPOP_TOGSEL, "TOGSEL", 0, "Toggle Selectable", ""},
+ {OL_GROUPOP_TOGREN, "TOGREN", 0, "Toggle Renderable", ""},
+ {OL_GROUPOP_RENAME, "RENAME", 0, "Rename", ""},
{0, NULL, 0, NULL, NULL}
};
@@ -750,28 +1001,42 @@ static int outliner_group_operation_exec(bContext *C, wmOperator *op)
event = RNA_enum_get(op->ptr, "type");
switch (event) {
- case 0: outliner_do_libdata_operation(C, scene, soops, &soops->tree, unlink_group_cb); break;
- case 1: outliner_do_libdata_operation(C, scene, soops, &soops->tree, id_local_cb); break;
- case 2: outliner_do_libdata_operation(C, scene, soops, &soops->tree, group_linkobs2scene_cb); break;
- case 3: outliner_do_libdata_operation(C, scene, soops, &soops->tree, group_instance_cb); break;
- case 4: outliner_do_libdata_operation(C, scene, soops, &soops->tree, group_toggle_visibility_cb); break;
- case 5: outliner_do_libdata_operation(C, scene, soops, &soops->tree, group_toggle_selectability_cb); break;
- case 6: outliner_do_libdata_operation(C, scene, soops, &soops->tree, group_toggle_renderability_cb); break;
- case 7: outliner_do_libdata_operation(C, scene, soops, &soops->tree, item_rename_cb); break;
+ case OL_GROUPOP_UNLINK:
+ outliner_do_libdata_operation(C, scene, soops, &soops->tree, unlink_group_cb);
+ break;
+ case OL_GROUPOP_LOCAL:
+ outliner_do_libdata_operation(C, scene, soops, &soops->tree, id_local_cb);
+ break;
+ case OL_GROUPOP_LINK:
+ outliner_do_libdata_operation(C, scene, soops, &soops->tree, group_linkobs2scene_cb);
+ break;
+ case OL_GROUPOP_INSTANCE:
+ outliner_do_libdata_operation(C, scene, soops, &soops->tree, group_instance_cb);
+ break;
+ case OL_GROUPOP_TOGVIS:
+ outliner_do_libdata_operation(C, scene, soops, &soops->tree, group_toggle_visibility_cb);
+ break;
+ case OL_GROUPOP_TOGSEL:
+ outliner_do_libdata_operation(C, scene, soops, &soops->tree, group_toggle_selectability_cb);
+ break;
+ case OL_GROUPOP_TOGREN:
+ outliner_do_libdata_operation(C, scene, soops, &soops->tree, group_toggle_renderability_cb);
+ break;
+ case OL_GROUPOP_RENAME:
+ outliner_do_libdata_operation(C, scene, soops, &soops->tree, item_rename_cb);
+ break;
default:
BLI_assert(0);
- return OPERATOR_CANCELLED;
}
-
if (event == 3) { /* instance */
/* works without this except if you try render right after, see: 22027 */
DAG_relations_tag_update(CTX_data_main(C));
}
-
- ED_undo_push(C, prop_group_op_types[event].name);
+
+ ED_undo_push(C, prop_group_op_types[event - 1].name);
WM_event_add_notifier(C, NC_GROUP, NULL);
-
+
return OPERATOR_FINISHED;
}
@@ -1195,12 +1460,105 @@ void OUTLINER_OT_animdata_operation(wmOperatorType *ot)
/* **************************************** */
+static EnumPropertyItem prop_constraint_op_types[] = {
+ {OL_CONSTRAINTOP_ENABLE, "ENABLE", ICON_RESTRICT_VIEW_OFF, "Enable", ""},
+ {OL_CONSTRAINTOP_DISABLE, "DISABLE", ICON_RESTRICT_VIEW_ON, "Disable", ""},
+ {OL_CONSTRAINTOP_DELETE, "DELETE", ICON_X, "Delete", ""},
+ {0, NULL, 0, NULL, NULL}
+};
+
+static int outliner_constraint_operation_exec(bContext *C, wmOperator *op)
+{
+ SpaceOops *soops = CTX_wm_space_outliner(C);
+ int scenelevel = 0, objectlevel = 0, idlevel = 0, datalevel = 0;
+ eOutliner_PropConstraintOps event;
+
+ event = RNA_enum_get(op->ptr, "type");
+ set_operation_types(soops, &soops->tree, &scenelevel, &objectlevel, &idlevel, &datalevel);
+
+ outliner_do_data_operation(soops, datalevel, event, &soops->tree, constraint_cb, C);
+
+ if (event == OL_CONSTRAINTOP_DELETE) {
+ outliner_cleanup_tree(soops);
+ }
+
+ ED_undo_push(C, "Constraint operation");
+
+ return OPERATOR_FINISHED;
+}
+
+void OUTLINER_OT_constraint_operation(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Outliner Constraint Operation";
+ ot->idname = "OUTLINER_OT_constraint_operation";
+ ot->description = "";
+
+ /* callbacks */
+ ot->invoke = WM_menu_invoke;
+ ot->exec = outliner_constraint_operation_exec;
+ ot->poll = ED_operator_outliner_active;
+
+ ot->flag = 0;
+
+ ot->prop = RNA_def_enum(ot->srna, "type", prop_constraint_op_types, 0, "Constraint Operation", "");
+}
+
+/* ******************** */
+
+static EnumPropertyItem prop_modifier_op_types[] = {
+ {OL_MODIFIER_OP_TOGVIS, "TOGVIS", ICON_RESTRICT_VIEW_OFF, "Toggle viewport use", ""},
+ {OL_MODIFIER_OP_TOGREN, "TOGREN", ICON_RESTRICT_RENDER_OFF, "Toggle render use", ""},
+ {OL_MODIFIER_OP_DELETE, "DELETE", ICON_X, "Delete", ""},
+ {0, NULL, 0, NULL, NULL}
+};
+
+static int outliner_modifier_operation_exec(bContext *C, wmOperator *op)
+{
+ SpaceOops *soops = CTX_wm_space_outliner(C);
+ int scenelevel = 0, objectlevel = 0, idlevel = 0, datalevel = 0;
+ eOutliner_PropModifierOps event;
+
+ event = RNA_enum_get(op->ptr, "type");
+ set_operation_types(soops, &soops->tree, &scenelevel, &objectlevel, &idlevel, &datalevel);
+
+ outliner_do_data_operation(soops, datalevel, event, &soops->tree, modifier_cb, C);
+
+ if (event == OL_MODIFIER_OP_DELETE) {
+ outliner_cleanup_tree(soops);
+ }
+
+ ED_undo_push(C, "Modifier operation");
+
+ return OPERATOR_FINISHED;
+}
+
+void OUTLINER_OT_modifier_operation(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Outliner Modifier Operation";
+ ot->idname = "OUTLINER_OT_modifier_operation";
+ ot->description = "";
+
+ /* callbacks */
+ ot->invoke = WM_menu_invoke;
+ ot->exec = outliner_modifier_operation_exec;
+ ot->poll = ED_operator_outliner_active;
+
+ ot->flag = 0;
+
+ ot->prop = RNA_def_enum(ot->srna, "type", prop_modifier_op_types, 0, "Modifier Operation", "");
+}
+
+/* ******************** */
+
+// XXX: select linked is for RNA structs only
static EnumPropertyItem prop_data_op_types[] = {
- {1, "SELECT", 0, "Select", ""},
- {2, "DESELECT", 0, "Deselect", ""},
- {3, "HIDE", 0, "Hide", ""},
- {4, "UNHIDE", 0, "Unhide", ""},
- {5, "SELECT_LINKED", 0, "Select Linked", ""},
+ {OL_DOP_SELECT, "SELECT", 0, "Select", ""},
+ {OL_DOP_DESELECT, "DESELECT", 0, "Deselect", ""},
+ {OL_DOP_HIDE, "HIDE", 0, "Hide", ""},
+ {OL_DOP_UNHIDE, "UNHIDE", 0, "Unhide", ""},
+ {OL_DOP_SELECT_LINKED, "SELECT_LINKED", 0, "Select Linked", ""},
{0, NULL, 0, NULL, NULL}
};
@@ -1208,7 +1566,7 @@ static int outliner_data_operation_exec(bContext *C, wmOperator *op)
{
SpaceOops *soops = CTX_wm_space_outliner(C);
int scenelevel = 0, objectlevel = 0, idlevel = 0, datalevel = 0;
- int event;
+ eOutliner_PropDataOps event;
/* check for invalid states */
if (soops == NULL)
@@ -1217,47 +1575,53 @@ static int outliner_data_operation_exec(bContext *C, wmOperator *op)
event = RNA_enum_get(op->ptr, "type");
set_operation_types(soops, &soops->tree, &scenelevel, &objectlevel, &idlevel, &datalevel);
- if (event <= 0)
- return OPERATOR_CANCELLED;
-
switch (datalevel) {
case TSE_POSE_CHANNEL:
{
outliner_do_data_operation(soops, datalevel, event, &soops->tree, pchan_cb, NULL);
WM_event_add_notifier(C, NC_OBJECT | ND_POSE, NULL);
ED_undo_push(C, "PoseChannel operation");
- }
+
break;
-
+ }
case TSE_BONE:
{
outliner_do_data_operation(soops, datalevel, event, &soops->tree, bone_cb, NULL);
WM_event_add_notifier(C, NC_OBJECT | ND_POSE, NULL);
ED_undo_push(C, "Bone operation");
- }
+
break;
-
+ }
case TSE_EBONE:
{
outliner_do_data_operation(soops, datalevel, event, &soops->tree, ebone_cb, NULL);
WM_event_add_notifier(C, NC_OBJECT | ND_POSE, NULL);
ED_undo_push(C, "EditBone operation");
- }
+
break;
-
+ }
case TSE_SEQUENCE:
{
Scene *scene = CTX_data_scene(C);
outliner_do_data_operation(soops, datalevel, event, &soops->tree, sequence_cb, scene);
+
+ break;
}
+ case TSE_GP_LAYER:
+ {
+ outliner_do_data_operation(soops, datalevel, event, &soops->tree, gp_layer_cb, NULL);
+ WM_event_add_notifier(C, NC_GPENCIL | ND_DATA, NULL);
+ ED_undo_push(C, "Grease Pencil Layer operation");
+
break;
-
+ }
case TSE_RNA_STRUCT:
- if (event == 5) {
+ if (event == OL_DOP_SELECT_LINKED) {
outliner_do_data_operation(soops, datalevel, event, &soops->tree, data_select_linked_cb, C);
}
+
break;
-
+
default:
BKE_report(op->reports, RPT_WARNING, "Not yet implemented");
break;
@@ -1312,8 +1676,12 @@ static int do_outliner_operation_event(bContext *C, Scene *scene, ARegion *ar, S
set_operation_types(soops, &soops->tree, &scenelevel, &objectlevel, &idlevel, &datalevel);
if (scenelevel) {
- //if (objectlevel || datalevel || idlevel) error("Mixed selection");
- //else pupmenu("Scene Operations%t|Delete");
+ if (objectlevel || datalevel || idlevel) {
+ BKE_report(reports, RPT_WARNING, "Mixed selection");
+ }
+ else {
+ WM_operator_name_call(C, "OUTLINER_OT_scene_operation", WM_OP_INVOKE_REGION_WIN, NULL);
+ }
}
else if (objectlevel) {
WM_operator_name_call(C, "OUTLINER_OT_object_operation", WM_OP_INVOKE_REGION_WIN, NULL);
@@ -1342,6 +1710,15 @@ static int do_outliner_operation_event(bContext *C, Scene *scene, ARegion *ar, S
else if (ELEM(datalevel, TSE_R_LAYER_BASE, TSE_R_LAYER, TSE_R_PASS)) {
/*WM_operator_name_call(C, "OUTLINER_OT_renderdata_operation", WM_OP_INVOKE_REGION_WIN, NULL)*/
}
+ else if (datalevel == TSE_ID_BASE) {
+ /* do nothing... there are no ops needed here yet */
+ }
+ else if (datalevel == TSE_CONSTRAINT) {
+ WM_operator_name_call(C, "OUTLINER_OT_constraint_operation", WM_OP_INVOKE_REGION_WIN, NULL);
+ }
+ else if (datalevel == TSE_MODIFIER) {
+ WM_operator_name_call(C, "OUTLINER_OT_modifier_operation", WM_OP_INVOKE_REGION_WIN, NULL);
+ }
else {
WM_operator_name_call(C, "OUTLINER_OT_data_operation", WM_OP_INVOKE_REGION_WIN, NULL);
}
@@ -1364,9 +1741,14 @@ static int outliner_operation(bContext *C, wmOperator *UNUSED(op), const wmEvent
Scene *scene = CTX_data_scene(C);
ARegion *ar = CTX_wm_region(C);
SpaceOops *soops = CTX_wm_space_outliner(C);
+ uiBut *but = UI_context_active_but_get(C);
TreeElement *te;
float fmval[2];
+ if (but) {
+ UI_but_tooltip_timer_remove(C, but);
+ }
+
UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &fmval[0], &fmval[1]);
for (te = soops->tree.first; te; te = te->next) {
diff --git a/source/blender/editors/space_outliner/outliner_tree.c b/source/blender/editors/space_outliner/outliner_tree.c
index 5801dd126e3..aaca61ed5cf 100644
--- a/source/blender/editors/space_outliner/outliner_tree.c
+++ b/source/blender/editors/space_outliner/outliner_tree.c
@@ -38,6 +38,7 @@
#include "DNA_armature_types.h"
#include "DNA_constraint_types.h"
#include "DNA_camera_types.h"
+#include "DNA_gpencil_types.h"
#include "DNA_group_types.h"
#include "DNA_key_types.h"
#include "DNA_lamp_types.h"
@@ -57,7 +58,7 @@
#include "BLI_mempool.h"
#include "BLI_fnmatch.h"
-#include "BLF_translation.h"
+#include "BLT_translation.h"
#include "BKE_fcurve.h"
#include "BKE_main.h"
@@ -65,7 +66,7 @@
#include "BKE_modifier.h"
#include "BKE_sequencer.h"
#include "BKE_idcode.h"
-#include "BKE_treehash.h"
+#include "BKE_outliner_treehash.h"
#include "ED_armature.h"
#include "ED_screen.h"
@@ -103,6 +104,8 @@ static void outliner_storage_cleanup(SpaceOops *soops)
/* cleanup only after reading file or undo step, and always for
* RNA datablocks view in order to save memory */
if (soops->storeflag & SO_TREESTORE_CLEANUP) {
+ soops->storeflag &= ~SO_TREESTORE_CLEANUP;
+
BLI_mempool_iternew(ts, &iter);
while ((tselem = BLI_mempool_iterstep(&iter))) {
if (tselem->id == NULL) unused++;
@@ -113,7 +116,7 @@ static void outliner_storage_cleanup(SpaceOops *soops)
BLI_mempool_destroy(ts);
soops->treestore = NULL;
if (soops->treehash) {
- BKE_treehash_free(soops->treehash);
+ BKE_outliner_treehash_free(soops->treehash);
soops->treehash = NULL;
}
}
@@ -132,7 +135,7 @@ static void outliner_storage_cleanup(SpaceOops *soops)
soops->treestore = new_ts;
if (soops->treehash) {
/* update hash table to fix broken pointers */
- BKE_treehash_rebuild_from_treestore(soops->treehash, soops->treestore);
+ BKE_outliner_treehash_rebuild_from_treestore(soops->treehash, soops->treestore);
}
}
}
@@ -150,12 +153,12 @@ static void check_persistent(SpaceOops *soops, TreeElement *te, ID *id, short ty
}
if (soops->treehash == NULL) {
- soops->treehash = BKE_treehash_create_from_treestore(soops->treestore);
+ soops->treehash = BKE_outliner_treehash_create_from_treestore(soops->treestore);
}
/* find any unused tree element in treestore and mark it as used
* (note that there may be multiple unused elements in case of linked objects) */
- tselem = BKE_treehash_lookup_unused(soops->treehash, type, nr, id);
+ tselem = BKE_outliner_treehash_lookup_unused(soops->treehash, type, nr, id);
if (tselem) {
te->store_elem = tselem;
tselem->used = 1;
@@ -170,7 +173,7 @@ static void check_persistent(SpaceOops *soops, TreeElement *te, ID *id, short ty
tselem->used = 0;
tselem->flag = TSE_CLOSED;
te->store_elem = tselem;
- BKE_treehash_add_element(soops->treehash, tselem);
+ BKE_outliner_treehash_add_element(soops->treehash, tselem);
}
/* ********************************************************* */
@@ -196,7 +199,7 @@ void outliner_cleanup_tree(SpaceOops *soops)
}
/* Find specific item from the treestore */
-static TreeElement *outliner_find_tree_element(ListBase *lb, TreeStoreElem *store_elem)
+TreeElement *outliner_find_tree_element(ListBase *lb, TreeStoreElem *store_elem)
{
TreeElement *te, *tes;
for (te = lb->first; te; te = te->next) {
@@ -215,7 +218,7 @@ TreeElement *outliner_find_tse(SpaceOops *soops, TreeStoreElem *tse)
if (tse->id == NULL) return NULL;
/* check if 'tse' is in treestore */
- tselem = BKE_treehash_lookup_any(soops->treehash, tse->type, tse->nr, tse->id);
+ tselem = BKE_outliner_treehash_lookup_any(soops->treehash, tse->type, tse->nr, tse->id);
if (tselem)
return outliner_find_tree_element(&soops->tree, tselem);
@@ -430,11 +433,13 @@ static void outliner_add_scene_contents(SpaceOops *soops, ListBase *lb, Scene *s
// TODO: move this to the front?
if (outliner_animdata_test(sce->adt))
outliner_add_element(soops, lb, sce, te, TSE_ANIM_DATA, 0);
+
+ outliner_add_element(soops, lb, sce->gpd, te, 0, 0);
outliner_add_element(soops, lb, sce->world, te, 0, 0);
#ifdef WITH_FREESTYLE
- if (STREQ(sce->r.engine, "BLENDER_RENDER") && (sce->r.mode & R_EDGE_FRS))
+ if (STREQ(sce->r.engine, RE_engine_id_BLENDER_RENDER) && (sce->r.mode & R_EDGE_FRS))
outliner_add_line_styles(soops, lb, sce, te);
#endif
}
@@ -451,6 +456,8 @@ static void outliner_add_object_contents(SpaceOops *soops, TreeElement *te, Tree
if (ob->proxy && ob->id.lib == NULL)
outliner_add_element(soops, &te->subtree, ob->proxy, te, TSE_PROXY, 0);
+
+ outliner_add_element(soops, &te->subtree, ob->gpd, te, 0, 0);
outliner_add_element(soops, &te->subtree, ob->data, te, 0, 0);
@@ -764,16 +771,16 @@ static void outliner_add_id_contents(SpaceOops *soops, TreeElement *te, TreeStor
ten = outliner_add_element(soops, &te->subtree, id, te, TSE_EBONE, a);
ten->directdata = ebone;
ten->name = ebone->name;
- ebone->temp = ten;
+ ebone->temp.p = ten;
}
/* make hierarchy */
- ten = arm->edbo->first ? ((EditBone *)arm->edbo->first)->temp : NULL;
+ ten = arm->edbo->first ? ((EditBone *)arm->edbo->first)->temp.p : NULL;
while (ten) {
TreeElement *nten = ten->next, *par;
ebone = (EditBone *)ten->directdata;
if (ebone->parent) {
BLI_remlink(&te->subtree, ten);
- par = ebone->parent->temp;
+ par = ebone->parent->temp.p;
BLI_addtail(&par->subtree, ten);
ten->parent = par;
}
@@ -809,6 +816,22 @@ static void outliner_add_id_contents(SpaceOops *soops, TreeElement *te, TreeStor
}
break;
}
+ case ID_GD:
+ {
+ bGPdata *gpd = (bGPdata *)id;
+ bGPDlayer *gpl;
+ int a = 0;
+
+ if (outliner_animdata_test(gpd->adt))
+ outliner_add_element(soops, &te->subtree, gpd, te, TSE_ANIM_DATA, 0);
+
+ // TODO: base element for layers?
+ for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ outliner_add_element(soops, &te->subtree, gpl, te, TSE_GP_LAYER, a);
+ a++;
+ }
+ break;
+ }
}
}
@@ -825,6 +848,10 @@ static TreeElement *outliner_add_element(SpaceOops *soops, ListBase *lb, void *i
id = ((PointerRNA *)idv)->id.data;
if (!id) id = ((PointerRNA *)idv)->data;
}
+ else if (type == TSE_GP_LAYER) {
+ /* idv is the layer its self */
+ id = TREESTORE(parent)->id;
+ }
/* One exception */
if (type == TSE_ID_BASE) {
@@ -834,6 +861,11 @@ static TreeElement *outliner_add_element(SpaceOops *soops, ListBase *lb, void *i
return NULL;
}
+ if (type == 0) {
+ /* Zero type means real ID, ensure we do not get non-outliner ID types here... */
+ BLI_assert(TREESTORE_ID_TYPE(id));
+ }
+
te = MEM_callocN(sizeof(TreeElement), "tree elem");
/* add to the visual tree */
BLI_addtail(lb, te);
@@ -856,6 +888,9 @@ static TreeElement *outliner_add_element(SpaceOops *soops, ListBase *lb, void *i
else if (type == TSE_ANIM_DATA) {
/* pass */
}
+ else if (type == TSE_GP_LAYER) {
+ /* pass */
+ }
else if (type == TSE_ID_BASE) {
/* pass */
}
@@ -938,6 +973,12 @@ static TreeElement *outliner_add_element(SpaceOops *soops, ListBase *lb, void *i
}
}
}
+ else if (type == TSE_GP_LAYER) {
+ bGPDlayer *gpl = (bGPDlayer *)idv;
+
+ te->name = gpl->info;
+ te->directdata = gpl;
+ }
else if (type == TSE_SEQUENCE) {
Sequence *seq = (Sequence *) idv;
Sequence *p;
@@ -951,7 +992,7 @@ static TreeElement *outliner_add_element(SpaceOops *soops, ListBase *lb, void *i
te->directdata = seq;
te->name = seq->name + 2;
- if (seq->type < SEQ_TYPE_EFFECT) {
+ if (!(seq->type & SEQ_TYPE_EFFECT)) {
/*
* This work like the sequence.
* If the sequence have a name (not default name)
@@ -1102,7 +1143,7 @@ static TreeElement *outliner_add_element(SpaceOops *soops, ListBase *lb, void *i
int a = 0;
for (kmi = km->items.first; kmi; kmi = kmi->next, a++) {
- const char *key = WM_key_event_string(kmi->type);
+ const char *key = WM_key_event_string(kmi->type, false);
if (key[0]) {
wmOperatorType *ot = NULL;
@@ -1160,7 +1201,7 @@ static int need_add_seq_dup(Sequence *seq)
continue;
}
- if (!strcmp(p->strip->stripdata->name, seq->strip->stripdata->name))
+ if (STREQ(p->strip->stripdata->name, seq->strip->stripdata->name))
return(2);
p = p->prev;
}
@@ -1172,7 +1213,7 @@ static int need_add_seq_dup(Sequence *seq)
continue;
}
- if (!strcmp(p->strip->stripdata->name, seq->strip->stripdata->name))
+ if (STREQ(p->strip->stripdata->name, seq->strip->stripdata->name))
return(0);
p = p->next;
}
@@ -1191,12 +1232,90 @@ static void outliner_add_seq_dup(SpaceOops *soops, Sequence *seq, TreeElement *t
continue;
}
- if (!strcmp(p->strip->stripdata->name, seq->strip->stripdata->name))
+ if (STREQ(p->strip->stripdata->name, seq->strip->stripdata->name))
/* ch = */ /* UNUSED */ outliner_add_element(soops, &te->subtree, (void *)p, te, TSE_SEQUENCE, index);
p = p->next;
}
}
+
+/* ----------------------------------------------- */
+
+
+static void outliner_add_library_contents(Main *mainvar, SpaceOops *soops, TreeElement *te, Library *lib)
+{
+ TreeElement *ten;
+ ListBase *lbarray[MAX_LIBARRAY];
+ int a, tot;
+
+ tot = set_listbasepointers(mainvar, lbarray);
+ for (a = 0; a < tot; a++) {
+ if (lbarray[a]->first) {
+ ID *id = lbarray[a]->first;
+
+ /* check if there's data in current lib */
+ for (; id; id = id->next)
+ if (id->lib == lib)
+ break;
+
+ if (id) {
+ ten = outliner_add_element(soops, &te->subtree, lbarray[a], NULL, TSE_ID_BASE, 0);
+ ten->directdata = lbarray[a];
+
+ ten->name = (char *)BKE_idcode_to_name_plural(GS(id->name));
+ if (ten->name == NULL)
+ ten->name = "UNKNOWN";
+
+ for (id = lbarray[a]->first; id; id = id->next) {
+ if (id->lib == lib)
+ outliner_add_element(soops, &ten->subtree, id, ten, 0, 0);
+ }
+ }
+ }
+ }
+
+}
+
+static void outliner_add_orphaned_datablocks(Main *mainvar, SpaceOops *soops)
+{
+ TreeElement *ten;
+ ListBase *lbarray[MAX_LIBARRAY];
+ int a, tot;
+
+ tot = set_listbasepointers(mainvar, lbarray);
+ for (a = 0; a < tot; a++) {
+ if (lbarray[a]->first) {
+ ID *id = lbarray[a]->first;
+
+ /* check if there are any datablocks of this type which are orphans */
+ for (; id; id = id->next) {
+ if (ID_REAL_USERS(id) <= 0)
+ break;
+ }
+
+ if (id) {
+ /* header for this type of datablock */
+ /* TODO's:
+ * - Add a parameter to BKE_idcode_to_name_plural to get a sane "user-visible" name instead?
+ * - Ensure that this uses nice icons for the datablock type involved instead of the dot?
+ */
+ ten = outliner_add_element(soops, &soops->tree, lbarray[a], NULL, TSE_ID_BASE, 0);
+ ten->directdata = lbarray[a];
+
+ ten->name = (char *)BKE_idcode_to_name_plural(GS(id->name));
+ if (ten->name == NULL)
+ ten->name = "UNKNOWN";
+
+ /* add the orphaned datablocks - these will not be added with any subtrees attached */
+ for (id = lbarray[a]->first; id; id = id->next) {
+ if (ID_REAL_USERS(id) <= 0)
+ outliner_add_element(soops, &ten->subtree, id, ten, 0, 0);
+ }
+ }
+ }
+ }
+}
+
/* ======================================================= */
/* Generic Tree Building helpers - order these are called is top to bottom */
@@ -1311,7 +1430,10 @@ static void outliner_sort(SpaceOops *soops, ListBase *lb)
TreeElement *te;
TreeStoreElem *tselem;
int totelem = 0;
-
+
+ if (soops->flag & SO_SKIP_SORT_ALPHA)
+ return;
+
te = lb->last;
if (te == NULL) return;
tselem = TREESTORE(te);
@@ -1371,59 +1493,42 @@ static void outliner_sort(SpaceOops *soops, ListBase *lb)
/* Filtering ----------------------------------------------- */
-static int outliner_filter_has_name(TreeElement *te, const char *name, int flags)
+static bool outliner_filter_has_name(TreeElement *te, const char *name, int flags)
{
-#if 0
- int found = 0;
-
- /* determine if match */
- if (flags & SO_FIND_CASE_SENSITIVE) {
- if (flags & SO_FIND_COMPLETE)
- found = strcmp(te->name, name) == 0;
- else
- found = strstr(te->name, name) != NULL;
- }
- else {
- if (flags & SO_FIND_COMPLETE)
- found = BLI_strcasecmp(te->name, name) == 0;
- else
- found = BLI_strcasestr(te->name, name) != NULL;
- }
-#else
-
int fn_flag = 0;
- int found = 0;
-
+
if ((flags & SO_FIND_CASE_SENSITIVE) == 0)
fn_flag |= FNM_CASEFOLD;
- if (flags & SO_FIND_COMPLETE) {
- found = fnmatch(name, te->name, fn_flag) == 0;
- }
- else {
- char fn_name[sizeof(((struct SpaceOops *)NULL)->search_string) + 2];
- BLI_snprintf(fn_name, sizeof(fn_name), "*%s*", name);
- found = fnmatch(fn_name, te->name, fn_flag) == 0;
- }
- return found;
-#endif
+ return fnmatch(name, te->name, fn_flag) == 0;
}
static int outliner_filter_tree(SpaceOops *soops, ListBase *lb)
{
TreeElement *te, *ten;
TreeStoreElem *tselem;
-
+ char search_buff[sizeof(((struct SpaceOops *)NULL)->search_string) + 2];
+ char *search_string;
+
/* although we don't have any search string, we return true
* since the entire tree is ok then...
*/
if (soops->search_string[0] == 0)
return 1;
+ if (soops->search_flags & SO_FIND_COMPLETE) {
+ search_string = soops->search_string;
+ }
+ else {
+ /* Implicitly add heading/trailing wildcards if needed. */
+ BLI_strncpy_ensure_pad(search_buff, soops->search_string, '*', sizeof(search_buff));
+ search_string = search_buff;
+ }
+
for (te = lb->first; te; te = ten) {
ten = te->next;
- if (0 == outliner_filter_has_name(te, soops->search_string, soops->search_flags)) {
+ if (!outliner_filter_has_name(te, search_string, soops->search_flags)) {
/* item isn't something we're looking for, but...
* - if the subtree is expanded, check if there are any matches that can be easily found
* so that searching for "cu" in the default scene will still match the Cube
@@ -1458,42 +1563,6 @@ static int outliner_filter_tree(SpaceOops *soops, ListBase *lb)
return (BLI_listbase_is_empty(lb) == false);
}
-static void outliner_add_library_contents(Main *mainvar, SpaceOops *soops, TreeElement *te, Library *lib)
-{
- TreeElement *ten;
- ListBase *lbarray[MAX_LIBARRAY];
- int a, tot;
-
- tot = set_listbasepointers(mainvar, lbarray);
- for (a = 0; a < tot; a++) {
- if (lbarray[a]->first) {
- ID *id = lbarray[a]->first;
-
- /* check if there's data in current lib */
- for (; id; id = id->next)
- if (id->lib == lib)
- break;
-
- if (id) {
-
- ten = outliner_add_element(soops, &te->subtree, (void *)lbarray[a], NULL, TSE_ID_BASE, 0);
- ten->directdata = lbarray[a];
-
- ten->name = (char *)BKE_idcode_to_name_plural(GS(id->name));
- if (ten->name == NULL)
- ten->name = "UNKNOWN";
-
- for (id = lbarray[a]->first; id; id = id->next) {
- if (id->lib == lib)
- outliner_add_element(soops, &ten->subtree, id, ten, 0, 0);
- }
- }
- }
- }
-
-}
-
-
/* ======================================================= */
/* Main Tree Building API */
@@ -1515,6 +1584,11 @@ void outliner_build_tree(Main *mainvar, Scene *scene, SpaceOops *soops)
else
soops->search_flags &= ~SO_SEARCH_RECURSIVE;
+ if (soops->treehash && (soops->storeflag & SO_TREESTORE_REBUILD)) {
+ soops->storeflag &= ~SO_TREESTORE_REBUILD;
+ BKE_outliner_treehash_rebuild_from_treestore(soops->treehash, soops->treestore);
+ }
+
if (soops->tree.first && (soops->storeflag & SO_TREESTORE_REDRAW))
return;
@@ -1553,10 +1627,19 @@ void outliner_build_tree(Main *mainvar, Scene *scene, SpaceOops *soops)
tselem = TREESTORE(ten);
lib = (Library *)tselem->id;
if (lib && lib->parent) {
- BLI_remlink(&soops->tree, ten);
par = (TreeElement *)lib->parent->id.newid;
- BLI_addtail(&par->subtree, ten);
- ten->parent = par;
+ if (tselem->id->flag & LIB_INDIRECT) {
+ /* Only remove from 'first level' if lib is not also directly used. */
+ BLI_remlink(&soops->tree, ten);
+ BLI_addtail(&par->subtree, ten);
+ ten->parent = par;
+ }
+ else {
+ /* Else, make a new copy of the libtree for our parent. */
+ TreeElement *dupten = outliner_add_element(soops, &par->subtree, lib, NULL, 0, 0);
+ outliner_add_library_contents(mainvar, soops, dupten, lib);
+ dupten->parent = par;
+ }
}
ten = nten;
}
@@ -1688,6 +1771,9 @@ void outliner_build_tree(Main *mainvar, Scene *scene, SpaceOops *soops)
tselem->flag &= ~TSE_CLOSED;
}
}
+ else if (soops->outlinevis == SO_ID_ORPHANS) {
+ outliner_add_orphaned_datablocks(mainvar, soops);
+ }
else {
ten = outliner_add_element(soops, &soops->tree, OBACT, NULL, 0, 0);
if (ten) ten->directdata = BASACT;
diff --git a/source/blender/editors/space_outliner/space_outliner.c b/source/blender/editors/space_outliner/space_outliner.c
index 504d9628d98..7b1ec174a6b 100644
--- a/source/blender/editors/space_outliner/space_outliner.c
+++ b/source/blender/editors/space_outliner/space_outliner.c
@@ -41,7 +41,7 @@
#include "BKE_context.h"
#include "BKE_screen.h"
#include "BKE_scene.h"
-#include "BKE_treehash.h"
+#include "BKE_outliner_treehash.h"
#include "ED_space_api.h"
#include "ED_screen.h"
@@ -98,10 +98,10 @@ static int outliner_parent_drop_poll(bContext *C, wmDrag *drag, const wmEvent *e
UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &fmval[0], &fmval[1]);
if (drag->type == WM_DRAG_ID) {
- ID *id = (ID *)drag->poin;
+ ID *id = drag->poin;
if (GS(id->name) == ID_OB) {
/* Ensure item under cursor is valid drop target */
- TreeElement *te = outliner_dropzone_find(soops, fmval, 1);
+ TreeElement *te = outliner_dropzone_find(soops, fmval, true);
if (te && te->idcode == ID_OB && TREESTORE(te)->type == 0) {
Scene *scene;
@@ -129,7 +129,7 @@ static int outliner_parent_drop_poll(bContext *C, wmDrag *drag, const wmEvent *e
static void outliner_parent_drop_copy(wmDrag *drag, wmDropBox *drop)
{
- ID *id = (ID *)drag->poin;
+ ID *id = drag->poin;
RNA_string_set(drop->ptr, "child", id->name + 2);
}
@@ -148,10 +148,10 @@ static int outliner_parent_clear_poll(bContext *C, wmDrag *drag, const wmEvent *
}
if (drag->type == WM_DRAG_ID) {
- ID *id = (ID *)drag->poin;
+ ID *id = drag->poin;
if (GS(id->name) == ID_OB) {
if (((Object *)id)->parent) {
- if ((te = outliner_dropzone_find(soops, fmval, 1))) {
+ if ((te = outliner_dropzone_find(soops, fmval, true))) {
TreeStoreElem *tselem = TREESTORE(te);
switch (te->idcode) {
@@ -171,7 +171,7 @@ static int outliner_parent_clear_poll(bContext *C, wmDrag *drag, const wmEvent *
static void outliner_parent_clear_copy(wmDrag *drag, wmDropBox *drop)
{
- ID *id = (ID *)drag->poin;
+ ID *id = drag->poin;
RNA_string_set(drop->ptr, "dragged_obj", id->name + 2);
/* Set to simple parent clear type. Avoid menus for drag and drop if possible.
@@ -188,10 +188,10 @@ static int outliner_scene_drop_poll(bContext *C, wmDrag *drag, const wmEvent *ev
UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &fmval[0], &fmval[1]);
if (drag->type == WM_DRAG_ID) {
- ID *id = (ID *)drag->poin;
+ ID *id = drag->poin;
if (GS(id->name) == ID_OB) {
/* Ensure item under cursor is valid drop target */
- TreeElement *te = outliner_dropzone_find(soops, fmval, 0);
+ TreeElement *te = outliner_dropzone_find(soops, fmval, false);
return (te && te->idcode == ID_SCE && TREESTORE(te)->type == 0);
}
}
@@ -200,7 +200,7 @@ static int outliner_scene_drop_poll(bContext *C, wmDrag *drag, const wmEvent *ev
static void outliner_scene_drop_copy(wmDrag *drag, wmDropBox *drop)
{
- ID *id = (ID *)drag->poin;
+ ID *id = drag->poin;
RNA_string_set(drop->ptr, "object", id->name + 2);
}
@@ -213,10 +213,10 @@ static int outliner_material_drop_poll(bContext *C, wmDrag *drag, const wmEvent
UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &fmval[0], &fmval[1]);
if (drag->type == WM_DRAG_ID) {
- ID *id = (ID *)drag->poin;
+ ID *id = drag->poin;
if (GS(id->name) == ID_MA) {
/* Ensure item under cursor is valid drop target */
- TreeElement *te = outliner_dropzone_find(soops, fmval, 1);
+ TreeElement *te = outliner_dropzone_find(soops, fmval, true);
return (te && te->idcode == ID_OB && TREESTORE(te)->type == 0);
}
}
@@ -225,11 +225,35 @@ static int outliner_material_drop_poll(bContext *C, wmDrag *drag, const wmEvent
static void outliner_material_drop_copy(wmDrag *drag, wmDropBox *drop)
{
- ID *id = (ID *)drag->poin;
+ ID *id = drag->poin;
RNA_string_set(drop->ptr, "material", id->name + 2);
}
+static int outliner_group_link_poll(bContext *C, wmDrag *drag, const wmEvent *event)
+{
+ ARegion *ar = CTX_wm_region(C);
+ SpaceOops *soops = CTX_wm_space_outliner(C);
+ float fmval[2];
+ UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &fmval[0], &fmval[1]);
+
+ if (drag->type == WM_DRAG_ID) {
+ ID *id = drag->poin;
+ if (GS(id->name) == ID_OB) {
+ /* Ensure item under cursor is valid drop target */
+ TreeElement *te = outliner_dropzone_find(soops, fmval, true);
+ return (te && te->idcode == ID_GR && TREESTORE(te)->type == 0);
+ }
+ }
+ return 0;
+}
+
+static void outliner_group_link_copy(wmDrag *drag, wmDropBox *drop)
+{
+ ID *id = drag->poin;
+ RNA_string_set(drop->ptr, "object", id->name + 2);
+}
+
/* region dropbox definition */
static void outliner_dropboxes(void)
{
@@ -239,6 +263,7 @@ static void outliner_dropboxes(void)
WM_dropbox_add(lb, "OUTLINER_OT_parent_clear", outliner_parent_clear_poll, outliner_parent_clear_copy);
WM_dropbox_add(lb, "OUTLINER_OT_scene_drop", outliner_scene_drop_poll, outliner_scene_drop_copy);
WM_dropbox_add(lb, "OUTLINER_OT_material_drop", outliner_material_drop_poll, outliner_material_drop_copy);
+ WM_dropbox_add(lb, "OUTLINER_OT_group_link", outliner_group_link_poll, outliner_group_link_copy);
}
static void outliner_main_area_draw(const bContext *C, ARegion *ar)
@@ -362,6 +387,10 @@ static void outliner_main_area_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa)
break;
}
break;
+ case NC_GPENCIL:
+ if (ELEM(wmn->action, NA_EDITED, NA_SELECTED))
+ ED_region_tag_redraw(ar);
+ break;
}
}
@@ -435,7 +464,7 @@ static void outliner_free(SpaceLink *sl)
BLI_mempool_destroy(soutliner->treestore);
}
if (soutliner->treehash) {
- BKE_treehash_free(soutliner->treehash);
+ BKE_outliner_treehash_free(soutliner->treehash);
}
}
diff --git a/source/blender/editors/space_script/CMakeLists.txt b/source/blender/editors/space_script/CMakeLists.txt
index 26c4183f7df..2eb31576c57 100644
--- a/source/blender/editors/space_script/CMakeLists.txt
+++ b/source/blender/editors/space_script/CMakeLists.txt
@@ -22,10 +22,12 @@ set(INC
../include
../../blenkernel
../../blenlib
+ ../../gpu
../../makesdna
../../makesrna
../../windowmanager
../../../../intern/guardedalloc
+ ../../../../intern/glew-mx
)
set(INC_SYS
@@ -47,4 +49,6 @@ if(WITH_PYTHON)
add_definitions(-DWITH_PYTHON)
endif()
+add_definitions(${GL_DEFINITIONS})
+
blender_add_lib(bf_editor_space_script "${SRC}" "${INC}" "${INC_SYS}")
diff --git a/source/blender/editors/space_script/SConscript b/source/blender/editors/space_script/SConscript
index acb0bf9f20b..c03a61ec197 100644
--- a/source/blender/editors/space_script/SConscript
+++ b/source/blender/editors/space_script/SConscript
@@ -31,10 +31,12 @@ sources = env.Glob('*.c')
incs = [
'#/intern/guardedalloc',
- '#/extern/glew/include',
+ env['BF_GLEW_INC'],
+ '#/intern/glew-mx',
'../include',
'../../blenkernel',
'../../blenlib',
+ '../../gpu',
'../../imbuf',
'../../makesdna',
'../../makesrna',
@@ -43,6 +45,7 @@ incs = [
]
defs = []
+defs += env['BF_GL_DEFINITIONS']
if env['WITH_BF_PYTHON']:
defs.append('WITH_PYTHON')
diff --git a/source/blender/editors/space_script/script_edit.c b/source/blender/editors/space_script/script_edit.c
index 9077d0cf8ed..d265ae62db6 100644
--- a/source/blender/editors/space_script/script_edit.c
+++ b/source/blender/editors/space_script/script_edit.c
@@ -32,7 +32,6 @@
#include <string.h>
#include <stdio.h>
-#include "BLI_blenlib.h"
#include "BLI_utildefines.h"
#include "BKE_context.h"
@@ -131,7 +130,7 @@ static int script_reload_exec(bContext *C, wmOperator *op)
WM_event_add_notifier(C, NC_WINDOW, NULL);
return OPERATOR_FINISHED;
#else
- (void)C, (void)op; /* unused */
+ UNUSED_VARS(C, op);
return OPERATOR_CANCELLED;
#endif
}
diff --git a/source/blender/editors/space_script/script_ops.c b/source/blender/editors/space_script/script_ops.c
index 045df87d8db..41c07596a3b 100644
--- a/source/blender/editors/space_script/script_ops.c
+++ b/source/blender/editors/space_script/script_ops.c
@@ -32,19 +32,7 @@
#include <stdlib.h>
#include <math.h>
-
-#include "DNA_screen_types.h"
-#include "DNA_space_types.h"
-
-#include "BLI_math.h"
-#include "BLI_blenlib.h"
-
-#include "BKE_context.h"
-
-#include "RNA_access.h"
-
#include "WM_api.h"
-#include "WM_types.h"
#include "script_intern.h"
@@ -63,4 +51,3 @@ void script_keymap(wmKeyConfig *UNUSED(keyconf))
{
/* Script space is deprecated, and doesn't need a keymap */
}
-
diff --git a/source/blender/editors/space_script/space_script.c b/source/blender/editors/space_script/space_script.c
index fd2cd268a27..759dcd3d0a4 100644
--- a/source/blender/editors/space_script/space_script.c
+++ b/source/blender/editors/space_script/space_script.c
@@ -35,7 +35,6 @@
#include "MEM_guardedalloc.h"
#include "BLI_blenlib.h"
-#include "BLI_math.h"
#include "BLI_utildefines.h"
#include "BKE_context.h"
@@ -53,7 +52,6 @@
#include "UI_view2d.h"
#ifdef WITH_PYTHON
-#include "BPY_extern.h"
#endif
#include "script_intern.h" // own include
diff --git a/source/blender/editors/space_sequencer/CMakeLists.txt b/source/blender/editors/space_sequencer/CMakeLists.txt
index db5729a5762..778ccf902d1 100644
--- a/source/blender/editors/space_sequencer/CMakeLists.txt
+++ b/source/blender/editors/space_sequencer/CMakeLists.txt
@@ -20,14 +20,16 @@
set(INC
../include
- ../../blenfont
../../blenkernel
../../blenlib
+ ../../blentranslation
../../imbuf
+ ../../gpu
../../makesdna
../../makesrna
../../windowmanager
../../../../intern/guardedalloc
+ ../../../../intern/glew-mx
)
set(INC_SYS
@@ -41,6 +43,7 @@ set(SRC
sequencer_edit.c
sequencer_modifier.c
sequencer_ops.c
+ sequencer_preview.c
sequencer_scopes.c
sequencer_select.c
sequencer_view.c
@@ -50,14 +53,17 @@ set(SRC
)
if(WITH_AUDASPACE)
- list(APPEND INC
- ../../../../intern/audaspace/intern
+ add_definitions(${AUDASPACE_DEFINITIONS})
+
+ list(APPEND INC_SYS
+ ${AUDASPACE_C_INCLUDE_DIRS}
)
- add_definitions(-DWITH_AUDASPACE)
endif()
if(WITH_INTERNATIONAL)
add_definitions(-DWITH_INTERNATIONAL)
endif()
+add_definitions(${GL_DEFINITIONS})
+
blender_add_lib(bf_editor_space_sequencer "${SRC}" "${INC}" "${INC_SYS}")
diff --git a/source/blender/editors/space_sequencer/SConscript b/source/blender/editors/space_sequencer/SConscript
index 5aae30244a7..9c654d7a1e5 100644
--- a/source/blender/editors/space_sequencer/SConscript
+++ b/source/blender/editors/space_sequencer/SConscript
@@ -31,12 +31,13 @@ sources = env.Glob('*.c')
incs = [
'#/intern/guardedalloc',
- '#/extern/glew/include',
- '#/intern/audaspace/intern',
+ env['BF_GLEW_INC'],
+ '#/intern/glew-mx',
'../include',
- '../../blenfont',
'../../blenkernel',
'../../blenlib',
+ '../../blentranslation',
+ '../../gpu',
'../../imbuf',
'../../makesdna',
'../../makesrna',
@@ -44,6 +45,11 @@ incs = [
]
defs = []
+defs += env['BF_GL_DEFINITIONS']
+
+if env['WITH_BF_AUDASPACE']:
+ defs += env['BF_AUDASPACE_DEF']
+ incs.append(env['BF_AUDASPACE_C_INC'])
if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'linuxcross', 'win64-vc', 'win64-mingw'):
incs.append(env['BF_PTHREADS_INC'])
diff --git a/source/blender/editors/space_sequencer/sequencer_add.c b/source/blender/editors/space_sequencer/sequencer_add.c
index 345988c1d5c..ce03c24e2ab 100644
--- a/source/blender/editors/space_sequencer/sequencer_add.c
+++ b/source/blender/editors/space_sequencer/sequencer_add.c
@@ -30,6 +30,7 @@
#include <stdlib.h>
#include <math.h>
#include <string.h>
+#include <ctype.h>
#include "MEM_guardedalloc.h"
@@ -40,7 +41,6 @@
#include "DNA_scene_types.h"
#include "DNA_mask_types.h"
-#include "BLF_translation.h"
#include "BKE_context.h"
#include "BKE_global.h"
@@ -61,17 +61,21 @@
#include "ED_screen.h"
#include "ED_sequencer.h"
-#include "UI_view2d.h"
+#include "UI_interface.h"
#include "BKE_sound.h"
#ifdef WITH_AUDASPACE
-# include "AUD_C-API.h"
+# include AUD_SEQUENCE_H
#endif
/* own include */
#include "sequencer_intern.h"
+typedef struct SequencerAddData {
+ ImageFormatData im_format;
+} SequencerAddData;
+
/* Generic functions, reused by add strip operators */
/* avoid passing multiple args and be more verbose */
@@ -224,6 +228,19 @@ static void seq_load_operator_info(SeqLoadInfo *seq_load, wmOperator *op)
}
RNA_PROP_END;
}
+
+ if ((prop = RNA_struct_find_property(op->ptr, "use_multiview")) && RNA_property_boolean_get(op->ptr, prop)) {
+ if (op->customdata) {
+ SequencerAddData *sad = op->customdata;
+ ImageFormatData *imf = &sad->im_format;
+
+ seq_load->views_format = imf->views_format;
+ seq_load->flag |= SEQ_USE_VIEWS;
+
+ /* operator custom data is always released after the SeqLoadInfo, no need to handle the memory here */
+ seq_load->stereo3d_format = &imf->stereo3d_format;
+ }
+ }
}
/**
@@ -289,7 +306,7 @@ static int sequencer_add_scene_strip_exec(bContext *C, wmOperator *op)
BLI_strncpy(seq->name + 2, sce_seq->id.name + 2, sizeof(seq->name) - 2);
BKE_sequence_base_unique_name_recursive(&ed->seqbase, seq);
- seq->scene_sound = sound_scene_add_scene_sound(scene, seq, start_frame, start_frame + seq->len, 0);
+ seq->scene_sound = BKE_sound_scene_add_scene_sound(scene, seq, start_frame, start_frame + seq->len, 0);
BKE_sequence_calc_disp(scene, seq);
BKE_sequencer_sort(scene);
@@ -575,6 +592,9 @@ static int sequencer_add_generic_strip_exec(bContext *C, wmOperator *op, SeqLoad
return OPERATOR_CANCELLED;
}
+ if (op->customdata)
+ MEM_freeN(op->customdata);
+
BKE_sequencer_sort(scene);
BKE_sequencer_update_muting(ed);
@@ -583,15 +603,40 @@ static int sequencer_add_generic_strip_exec(bContext *C, wmOperator *op, SeqLoad
return OPERATOR_FINISHED;
}
+/* add sequencer operators */
+static void sequencer_add_init(bContext *UNUSED(C), wmOperator *op)
+{
+ op->customdata = MEM_callocN(sizeof(SequencerAddData), __func__);
+}
+
+static void sequencer_add_cancel(bContext *UNUSED(C), wmOperator *op)
+{
+ if (op->customdata)
+ MEM_freeN(op->customdata);
+ op->customdata = NULL;
+}
+
+static bool sequencer_add_draw_check_prop(PointerRNA *UNUSED(ptr), PropertyRNA *prop)
+{
+ const char *prop_id = RNA_property_identifier(prop);
+
+ return !(STREQ(prop_id, "filepath") ||
+ STREQ(prop_id, "directory") ||
+ STREQ(prop_id, "filename")
+ );
+}
+
/* add movie operator */
static int sequencer_add_movie_strip_exec(bContext *C, wmOperator *op)
{
return sequencer_add_generic_strip_exec(C, op, BKE_sequencer_add_movie_strip);
}
-
static int sequencer_add_movie_strip_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
+ PropertyRNA *prop;
+ Scene *scene = CTX_data_scene(C);
+
/* This is for drag and drop */
if ((RNA_struct_property_is_set(op->ptr, "files") && RNA_collection_length(op->ptr, "files")) ||
RNA_struct_property_is_set(op->ptr, "filepath"))
@@ -601,13 +646,37 @@ static int sequencer_add_movie_strip_invoke(bContext *C, wmOperator *op, const w
}
sequencer_generic_invoke_xy__internal(C, op, 0, SEQ_TYPE_MOVIE);
-
+
+ sequencer_add_init(C, op);
+
+ /* show multiview save options only if scene has multiviews */
+ prop = RNA_struct_find_property(op->ptr, "show_multiview");
+ RNA_property_boolean_set(op->ptr, prop, (scene->r.scemode & R_MULTIVIEW) != 0);
+
WM_event_add_fileselect(C, op);
return OPERATOR_RUNNING_MODAL;
//return sequencer_add_movie_strip_exec(C, op);
}
+static void sequencer_add_draw(bContext *UNUSED(C), wmOperator *op)
+{
+ uiLayout *layout = op->layout;
+ SequencerAddData *sad = op->customdata;
+ ImageFormatData *imf = &sad->im_format;
+ PointerRNA imf_ptr, ptr;
+
+ /* main draw call */
+ RNA_pointer_create(NULL, op->type->srna, op->properties, &ptr);
+ uiDefAutoButsRNA(layout, &ptr, sequencer_add_draw_check_prop, '\0');
+
+ /* image template */
+ RNA_pointer_create(NULL, &RNA_ImageFormatSettings, imf, &imf_ptr);
+
+ /* multiview template */
+ if (RNA_boolean_get(op->ptr, "show_multiview"))
+ uiTemplateImageFormatViews(layout, &imf_ptr, op->ptr);
+}
void SEQUENCER_OT_movie_strip_add(struct wmOperatorType *ot)
{
@@ -620,14 +689,16 @@ void SEQUENCER_OT_movie_strip_add(struct wmOperatorType *ot)
/* api callbacks */
ot->invoke = sequencer_add_movie_strip_invoke;
ot->exec = sequencer_add_movie_strip_exec;
+ ot->cancel = sequencer_add_cancel;
+ ot->ui = sequencer_add_draw;
ot->poll = ED_operator_sequencer_active_editable;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- WM_operator_properties_filesel(ot, FOLDERFILE | MOVIEFILE, FILE_SPECIAL, FILE_OPENFILE,
- WM_FILESEL_FILEPATH | WM_FILESEL_RELPATH | WM_FILESEL_FILES, FILE_DEFAULTDISPLAY);
+ WM_operator_properties_filesel(ot, FILE_TYPE_FOLDER | FILE_TYPE_MOVIE, FILE_SPECIAL, FILE_OPENFILE,
+ WM_FILESEL_FILEPATH | WM_FILESEL_RELPATH | WM_FILESEL_FILES, FILE_DEFAULTDISPLAY, FILE_SORT_ALPHA);
sequencer_generic_props__internal(ot, SEQPROP_STARTFRAME);
RNA_def_boolean(ot->srna, "sound", true, "Sound", "Load sound with the movie");
}
@@ -675,17 +746,80 @@ void SEQUENCER_OT_sound_strip_add(struct wmOperatorType *ot)
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- WM_operator_properties_filesel(ot, FOLDERFILE | SOUNDFILE, FILE_SPECIAL, FILE_OPENFILE,
- WM_FILESEL_FILEPATH | WM_FILESEL_RELPATH | WM_FILESEL_FILES, FILE_DEFAULTDISPLAY);
+ WM_operator_properties_filesel(ot, FILE_TYPE_FOLDER | FILE_TYPE_SOUND, FILE_SPECIAL, FILE_OPENFILE,
+ WM_FILESEL_FILEPATH | WM_FILESEL_RELPATH | WM_FILESEL_FILES, FILE_DEFAULTDISPLAY, FILE_SORT_ALPHA);
sequencer_generic_props__internal(ot, SEQPROP_STARTFRAME);
RNA_def_boolean(ot->srna, "cache", false, "Cache", "Cache the sound in memory");
}
+int sequencer_image_seq_get_minmax_frame(wmOperator *op, int sfra, int *r_minframe, int *r_numdigits)
+{
+ int minframe = INT32_MAX, maxframe = INT32_MIN;
+ int numdigits = 0;
+
+ RNA_BEGIN (op->ptr, itemptr, "files")
+ {
+ char *filename;
+ int frame;
+ /* just get the first filename */
+ filename = RNA_string_get_alloc(&itemptr, "name", NULL, 0);
+
+ if (filename) {
+ if (BLI_path_frame_get(filename, &frame, &numdigits)) {
+ minframe = min_ii(minframe, frame);
+ maxframe = max_ii(maxframe, frame);
+ }
+
+ MEM_freeN(filename);
+ }
+ }
+ RNA_END;
+
+ if (minframe == INT32_MAX) {
+ minframe = sfra;
+ maxframe = minframe + 1;
+ }
+
+ *r_minframe = minframe;
+ *r_numdigits = numdigits;
+
+ return maxframe - minframe + 1;
+}
+
+void sequencer_image_seq_reserve_frames(wmOperator *op, StripElem *se, int len, int minframe, int numdigits)
+{
+ int i;
+ char *filename = NULL;
+ RNA_BEGIN (op->ptr, itemptr, "files")
+ {
+ /* just get the first filename */
+ filename = RNA_string_get_alloc(&itemptr, "name", NULL, 0);
+ break;
+ }
+ RNA_END;
+
+ if (filename) {
+ char ext[PATH_MAX];
+ char filename_stripped[PATH_MAX];
+ /* strip the frame from filename and substitute with # */
+ BLI_path_frame_strip(filename, true, ext);
+
+ for (i = 0; i < len; i++, se++) {
+ BLI_strncpy(filename_stripped, filename, sizeof(filename_stripped));
+ BLI_path_frame(filename_stripped, minframe + i, numdigits);
+ BLI_snprintf(se->name, sizeof(se->name), "%s%s", filename_stripped, ext);
+ }
+
+ MEM_freeN(filename);
+ }
+}
+
+
/* add image operator */
static int sequencer_add_image_strip_exec(bContext *C, wmOperator *op)
{
+ int minframe, numdigits;
/* cant use the generic function for this */
-
Scene *scene = CTX_data_scene(C); /* only for sound */
Editing *ed = BKE_sequencer_editing_get(scene, true);
SeqLoadInfo seq_load;
@@ -693,11 +827,17 @@ static int sequencer_add_image_strip_exec(bContext *C, wmOperator *op)
Strip *strip;
StripElem *se;
+ const bool use_placeholders = RNA_boolean_get(op->ptr, "use_placeholders");
seq_load_operator_info(&seq_load, op);
/* images are unique in how they handle this - 1 per strip elem */
- seq_load.len = RNA_property_collection_length(op->ptr, RNA_struct_find_property(op->ptr, "files"));
+ if (use_placeholders) {
+ seq_load.len = sequencer_image_seq_get_minmax_frame(op, seq_load.start_frame, &minframe, &numdigits);
+ }
+ else {
+ seq_load.len = RNA_property_collection_length(op->ptr, RNA_struct_find_property(op->ptr, "files"));
+ }
if (seq_load.len == 0)
return OPERATOR_CANCELLED;
@@ -705,20 +845,24 @@ static int sequencer_add_image_strip_exec(bContext *C, wmOperator *op)
if (seq_load.flag & SEQ_LOAD_REPLACE_SEL)
ED_sequencer_deselect_all(scene);
-
/* main adding function */
seq = BKE_sequencer_add_image_strip(C, ed->seqbasep, &seq_load);
strip = seq->strip;
se = strip->stripdata;
- RNA_BEGIN (op->ptr, itemptr, "files")
- {
- char *filename = RNA_string_get_alloc(&itemptr, "name", NULL, 0);
- BLI_strncpy(se->name, filename, sizeof(se->name));
- MEM_freeN(filename);
- se++;
+ if (use_placeholders) {
+ sequencer_image_seq_reserve_frames(op, se, seq_load.len, minframe, numdigits);
+ }
+ else {
+ RNA_BEGIN (op->ptr, itemptr, "files")
+ {
+ char *filename = RNA_string_get_alloc(&itemptr, "name", NULL, 0);
+ BLI_strncpy(se->name, filename, sizeof(se->name));
+ MEM_freeN(filename);
+ se++;
+ }
+ RNA_END;
}
- RNA_END;
if (seq_load.len == 1) {
if (seq_load.start_frame < seq_load.end_frame) {
@@ -737,6 +881,9 @@ static int sequencer_add_image_strip_exec(bContext *C, wmOperator *op)
sequencer_add_apply_overlap(C, op, seq);
+ if (op->customdata)
+ MEM_freeN(op->customdata);
+
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
return OPERATOR_FINISHED;
@@ -744,6 +891,9 @@ static int sequencer_add_image_strip_exec(bContext *C, wmOperator *op)
static int sequencer_add_image_strip_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
+ PropertyRNA *prop;
+ Scene *scene = CTX_data_scene(C);
+
/* drag drop has set the names */
if (RNA_struct_property_is_set(op->ptr, "files") && RNA_collection_length(op->ptr, "files")) {
sequencer_generic_invoke_xy__internal(C, op, SEQPROP_ENDFRAME | SEQPROP_NOPATHS, SEQ_TYPE_IMAGE);
@@ -752,6 +902,12 @@ static int sequencer_add_image_strip_invoke(bContext *C, wmOperator *op, const w
sequencer_generic_invoke_xy__internal(C, op, SEQPROP_ENDFRAME, SEQ_TYPE_IMAGE);
+ sequencer_add_init(C, op);
+
+ /* show multiview save options only if scene has multiviews */
+ prop = RNA_struct_find_property(op->ptr, "show_multiview");
+ RNA_property_boolean_set(op->ptr, prop, (scene->r.scemode & R_MULTIVIEW) != 0);
+
WM_event_add_fileselect(C, op);
return OPERATOR_RUNNING_MODAL;
}
@@ -768,15 +924,19 @@ void SEQUENCER_OT_image_strip_add(struct wmOperatorType *ot)
/* api callbacks */
ot->invoke = sequencer_add_image_strip_invoke;
ot->exec = sequencer_add_image_strip_exec;
+ ot->cancel = sequencer_add_cancel;
+ ot->ui = sequencer_add_draw;
ot->poll = ED_operator_sequencer_active_editable;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- WM_operator_properties_filesel(ot, FOLDERFILE | IMAGEFILE, FILE_SPECIAL, FILE_OPENFILE,
- WM_FILESEL_DIRECTORY | WM_FILESEL_RELPATH | WM_FILESEL_FILES, FILE_DEFAULTDISPLAY);
+ WM_operator_properties_filesel(ot, FILE_TYPE_FOLDER | FILE_TYPE_IMAGE, FILE_SPECIAL, FILE_OPENFILE,
+ WM_FILESEL_DIRECTORY | WM_FILESEL_RELPATH | WM_FILESEL_FILES, FILE_DEFAULTDISPLAY, FILE_SORT_ALPHA);
sequencer_generic_props__internal(ot, SEQPROP_STARTFRAME | SEQPROP_ENDFRAME);
+
+ RNA_def_boolean(ot->srna, "use_placeholders", false, "Use Placeholders", "Use placeholders for missing frames of the strip");
}
@@ -850,6 +1010,9 @@ static int sequencer_add_effect_strip_exec(bContext *C, wmOperator *op)
else if (seq->type == SEQ_TYPE_ADJUSTMENT) {
seq->blend_mode = SEQ_TYPE_CROSS;
}
+ else if (seq->type == SEQ_TYPE_TEXT) {
+ seq->blend_mode = SEQ_TYPE_ALPHAOVER;
+ }
/* an unset channel is a special case where we automatically go above
* the other strips. */
@@ -920,8 +1083,9 @@ void SEQUENCER_OT_effect_strip_add(struct wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
WM_operator_properties_filesel(ot, 0, FILE_SPECIAL, FILE_OPENFILE,
- WM_FILESEL_FILEPATH | WM_FILESEL_RELPATH, FILE_DEFAULTDISPLAY);
+ WM_FILESEL_FILEPATH | WM_FILESEL_RELPATH, FILE_DEFAULTDISPLAY, FILE_SORT_ALPHA);
sequencer_generic_props__internal(ot, SEQPROP_STARTFRAME | SEQPROP_ENDFRAME);
RNA_def_enum(ot->srna, "type", sequencer_prop_effect_types, SEQ_TYPE_CROSS, "Type", "Sequencer effect type");
- RNA_def_float_vector(ot->srna, "color", 3, NULL, 0.0f, 1.0f, "Color", "Initialize the strip with this color (only used when type='COLOR')", 0.0f, 1.0f);
+ RNA_def_float_vector(ot->srna, "color", 3, NULL, 0.0f, 1.0f, "Color",
+ "Initialize the strip with this color (only used when type='COLOR')", 0.0f, 1.0f);
}
diff --git a/source/blender/editors/space_sequencer/sequencer_buttons.c b/source/blender/editors/space_sequencer/sequencer_buttons.c
index d75eeca2c67..86d3fcbe1ac 100644
--- a/source/blender/editors/space_sequencer/sequencer_buttons.c
+++ b/source/blender/editors/space_sequencer/sequencer_buttons.c
@@ -34,7 +34,7 @@
#include "BLI_blenlib.h"
#include "BLI_utildefines.h"
-#include "BLF_translation.h"
+#include "BLT_translation.h"
#include "BKE_context.h"
#include "BKE_screen.h"
@@ -46,12 +46,12 @@
#include "WM_api.h"
#include "WM_types.h"
-#include "UI_interface.h"
#include "sequencer_intern.h"
/* **************************** buttons ********************************* */
+#if 0
static int sequencer_grease_pencil_panel_poll(const bContext *C, PanelType *UNUSED(pt))
{
SpaceSeq *sseq = CTX_wm_space_seq(C);
@@ -59,19 +59,22 @@ static int sequencer_grease_pencil_panel_poll(const bContext *C, PanelType *UNUS
/* don't show the gpencil if we are not showing the image */
return ED_space_sequencer_check_show_imbuf(sseq);
}
+#endif
-void sequencer_buttons_register(ARegionType *art)
+void sequencer_buttons_register(ARegionType *UNUSED(art))
{
+#if 0
PanelType *pt;
pt = MEM_callocN(sizeof(PanelType), "spacetype sequencer panel gpencil");
strcpy(pt->idname, "SEQUENCER_PT_gpencil");
strcpy(pt->label, N_("Grease Pencil"));
- strcpy(pt->translation_context, BLF_I18NCONTEXT_DEFAULT_BPYRNA);
+ strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
pt->draw_header = ED_gpencil_panel_standard_header;
pt->draw = ED_gpencil_panel_standard;
pt->poll = sequencer_grease_pencil_panel_poll;
BLI_addtail(&art->paneltypes, pt);
+#endif
}
/* **************** operator to open/close properties view ************* */
diff --git a/source/blender/editors/space_sequencer/sequencer_draw.c b/source/blender/editors/space_sequencer/sequencer_draw.c
index dab51f752b4..afa59876647 100644
--- a/source/blender/editors/space_sequencer/sequencer_draw.c
+++ b/source/blender/editors/space_sequencer/sequencer_draw.c
@@ -34,6 +34,7 @@
#include "BLI_blenlib.h"
#include "BLI_math.h"
#include "BLI_utildefines.h"
+#include "BLI_threads.h"
#include "IMB_imbuf_types.h"
@@ -49,6 +50,7 @@
#include "BKE_main.h"
#include "BKE_sequencer.h"
#include "BKE_sound.h"
+#include "BKE_scene.h"
#include "IMB_colormanagement.h"
#include "IMB_imbuf.h"
@@ -61,6 +63,7 @@
#include "ED_markers.h"
#include "ED_mask.h"
#include "ED_sequencer.h"
+#include "ED_screen.h"
#include "ED_space_api.h"
#include "UI_interface.h"
@@ -69,6 +72,8 @@
#include "WM_api.h"
+#include "MEM_guardedalloc.h"
+
/* own include */
#include "sequencer_intern.h"
@@ -82,9 +87,13 @@
/* Note, Don't use SEQ_BEGIN/SEQ_END while drawing!
* it messes up transform, - Campbell */
-static void draw_shadedstrip(Sequence *seq, unsigned char col[3], float x1, float y1, float x2, float y2);
+#undef SEQ_BEGIN
+#undef SEQP_BEGIN
+#undef SEQ_END
+
+static Sequence *special_seq_update = NULL;
-static void get_seq_color3ubv(Scene *curscene, Sequence *seq, unsigned char col[3])
+void color3ubv_from_seq(Scene *curscene, Sequence *seq, unsigned char col[3])
{
unsigned char blendcol[3];
SolidColorVars *colvars = (SolidColorVars *)seq->effectdata;
@@ -175,14 +184,14 @@ static void get_seq_color3ubv(Scene *curscene, Sequence *seq, unsigned char col[
}
}
-static void drawseqwave(Scene *scene, Sequence *seq, float x1, float y1, float x2, float y2, float stepsize)
+static void drawseqwave(const bContext *C, SpaceSeq *sseq, Scene *scene, Sequence *seq, float x1, float y1, float x2, float y2, float stepsize)
{
/*
* x1 is the starting x value to draw the wave,
* x2 the end x value, same for y1 and y2
* stepsize is width of a pixel.
*/
- if (seq->flag & SEQ_AUDIO_DRAW_WAVEFORM) {
+ if ((sseq->flag & SEQ_ALL_WAVEFORMS) || (seq->flag & SEQ_AUDIO_DRAW_WAVEFORM)) {
int i, j, pos;
int length = floor((x2 - x1) / stepsize) + 1;
float ymid = (y1 + y2) / 2;
@@ -190,19 +199,37 @@ static void drawseqwave(Scene *scene, Sequence *seq, float x1, float y1, float x
float samplestep;
float startsample, endsample;
float value;
-
+ bSound *sound = seq->sound;
+
SoundWaveform *waveform;
-
- if (!seq->sound->waveform)
- sound_read_waveform(seq->sound);
-
- if (!seq->sound->waveform)
- return; /* zero length sound */
-
+
+ if (!sound->spinlock) {
+ sound->spinlock = MEM_mallocN(sizeof(SpinLock), "sound_spinlock");
+ BLI_spin_init(sound->spinlock);
+ }
+
+ BLI_spin_lock(sound->spinlock);
+ if (!seq->sound->waveform) {
+ if (!(sound->flags & SOUND_FLAGS_WAVEFORM_LOADING)) {
+ /* prevent sounds from reloading */
+ seq->sound->flags |= SOUND_FLAGS_WAVEFORM_LOADING;
+ BLI_spin_unlock(sound->spinlock);
+ sequencer_preview_add_sound(C, seq);
+ }
+ else {
+ BLI_spin_unlock(sound->spinlock);
+ }
+ return; /* nothing to draw */
+ }
+ BLI_spin_unlock(sound->spinlock);
+
waveform = seq->sound->waveform;
- if (!waveform)
+ if (waveform->length == 0) {
+ /* BKE_sound_read_waveform() set an empty SoundWaveform data in case it cannot generate a valid one...
+ * See T45726. */
return;
+ }
startsample = floor((seq->startofs + seq->anim_startofs) / FPS * SOUND_WAVE_SAMPLES_PER_SECOND);
endsample = ceil((seq->startofs + seq->anim_startofs + seq->enddisp - seq->startdisp) / FPS * SOUND_WAVE_SAMPLES_PER_SECOND);
@@ -299,7 +326,7 @@ static void drawmeta_contents(Scene *scene, Sequence *seqm, float x1, float y1,
if ((seqm->flag & SEQ_MUTE) == 0 && (seq->flag & SEQ_MUTE))
drawmeta_stipple(1);
- get_seq_color3ubv(scene, seq, col);
+ color3ubv_from_seq(scene, seq, col);
glColor4ubv(col);
@@ -332,7 +359,10 @@ static float draw_seq_handle_size_get_clamped(Sequence *seq, const float pixelx)
{
const float minhandle = pixelx * SEQ_HANDLE_SIZE_MIN;
const float maxhandle = pixelx * SEQ_HANDLE_SIZE_MAX;
- return CLAMPIS(seq->handsize, minhandle, maxhandle);
+ float size = CLAMPIS(seq->handsize, minhandle, maxhandle);
+
+ /* ensure we're not greater than half width */
+ return min_ff(size, ((float)(seq->enddisp - seq->startdisp) / 2.0f) / pixelx);
}
/* draw a handle, for each end of a sequence strip */
@@ -371,7 +401,7 @@ static void draw_seq_handle(View2D *v2d, Sequence *seq, const float handsize_cla
}
/* draw! */
- if (seq->type < SEQ_TYPE_EFFECT ||
+ if (!(seq->type & SEQ_TYPE_EFFECT) ||
BKE_sequence_effect_get_num_inputs(seq->type) == 0)
{
glEnable(GL_BLEND);
@@ -402,12 +432,12 @@ static void draw_seq_handle(View2D *v2d, Sequence *seq, const float handsize_cla
size_t numstr_len;
if (direction == SEQ_LEFTHANDLE) {
- numstr_len = BLI_snprintf(numstr, sizeof(numstr), "%d", seq->startdisp);
+ numstr_len = BLI_snprintf_rlen(numstr, sizeof(numstr), "%d", seq->startdisp);
x1 = rx1;
y1 -= 0.45f;
}
else {
- numstr_len = BLI_snprintf(numstr, sizeof(numstr), "%d", seq->enddisp - 1);
+ numstr_len = BLI_snprintf_rlen(numstr, sizeof(numstr), "%d", seq->enddisp - 1);
x1 = x2 - handsize_clamped * 0.75f;
y1 = y2 + 0.05f;
}
@@ -415,112 +445,6 @@ static void draw_seq_handle(View2D *v2d, Sequence *seq, const float handsize_cla
}
}
-static void draw_seq_extensions(Scene *scene, ARegion *ar, Sequence *seq)
-{
- float x1, x2, y1, y2, pixely, a;
- unsigned char col[3], blendcol[3];
- View2D *v2d = &ar->v2d;
-
- if (seq->type >= SEQ_TYPE_EFFECT) return;
-
- x1 = seq->startdisp;
- x2 = seq->enddisp;
-
- y1 = seq->machine + SEQ_STRIP_OFSBOTTOM;
- y2 = seq->machine + SEQ_STRIP_OFSTOP;
-
- pixely = BLI_rctf_size_y(&v2d->cur) / BLI_rcti_size_y(&v2d->mask);
-
- if (pixely <= 0) return; /* can happen when the view is split/resized */
-
- blendcol[0] = blendcol[1] = blendcol[2] = 120;
-
- if (seq->startofs) {
- glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-
- get_seq_color3ubv(scene, seq, col);
-
- if (seq->flag & SELECT) {
- UI_GetColorPtrBlendShade3ubv(col, blendcol, col, 0.3, -40);
- glColor4ub(col[0], col[1], col[2], 170);
- }
- else {
- UI_GetColorPtrBlendShade3ubv(col, blendcol, col, 0.6, 0);
- glColor4ub(col[0], col[1], col[2], 110);
- }
-
- glRectf((float)(seq->start), y1 - SEQ_STRIP_OFSBOTTOM, x1, y1);
-
- if (seq->flag & SELECT) glColor4ub(col[0], col[1], col[2], 255);
- else glColor4ub(col[0], col[1], col[2], 160);
-
- fdrawbox((float)(seq->start), y1 - SEQ_STRIP_OFSBOTTOM, x1, y1); //outline
-
- glDisable(GL_BLEND);
- }
- if (seq->endofs) {
- glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-
- get_seq_color3ubv(scene, seq, col);
-
- if (seq->flag & SELECT) {
- UI_GetColorPtrBlendShade3ubv(col, blendcol, col, 0.3, -40);
- glColor4ub(col[0], col[1], col[2], 170);
- }
- else {
- UI_GetColorPtrBlendShade3ubv(col, blendcol, col, 0.6, 0);
- glColor4ub(col[0], col[1], col[2], 110);
- }
-
- glRectf(x2, y2, (float)(seq->start + seq->len), y2 + SEQ_STRIP_OFSBOTTOM);
-
- if (seq->flag & SELECT) glColor4ub(col[0], col[1], col[2], 255);
- else glColor4ub(col[0], col[1], col[2], 160);
-
- fdrawbox(x2, y2, (float)(seq->start + seq->len), y2 + SEQ_STRIP_OFSBOTTOM); //outline
-
- glDisable(GL_BLEND);
- }
- if (seq->startstill) {
- get_seq_color3ubv(scene, seq, col);
- UI_GetColorPtrBlendShade3ubv(col, blendcol, col, 0.75, 40);
- glColor3ubv((GLubyte *)col);
-
- draw_shadedstrip(seq, col, x1, y1, (float)(seq->start), y2);
-
- /* feint pinstripes, helps see exactly which is extended and which isn't,
- * especially when the extension is very small */
- if (seq->flag & SELECT) UI_GetColorPtrBlendShade3ubv(col, col, col, 0.0, 24);
- else UI_GetColorPtrShade3ubv(col, col, -16);
-
- glColor3ubv((GLubyte *)col);
-
- for (a = y1; a < y2; a += pixely * 2.0f) {
- fdrawline(x1, a, (float)(seq->start), a);
- }
- }
- if (seq->endstill) {
- get_seq_color3ubv(scene, seq, col);
- UI_GetColorPtrBlendShade3ubv(col, blendcol, col, 0.75, 40);
- glColor3ubv((GLubyte *)col);
-
- draw_shadedstrip(seq, col, (float)(seq->start + seq->len), y1, x2, y2);
-
- /* feint pinstripes, helps see exactly which is extended and which isn't,
- * especially when the extension is very small */
- if (seq->flag & SELECT) UI_GetColorPtrShade3ubv(col, col, 24);
- else UI_GetColorPtrShade3ubv(col, col, -16);
-
- glColor3ubv((GLubyte *)col);
-
- for (a = y1; a < y2; a += pixely * 2.0f) {
- fdrawline((float)(seq->start + seq->len), a, x2, a);
- }
- }
-}
-
/* draw info text on a sequence strip */
static void draw_seq_text(View2D *v2d, Sequence *seq, float x1, float x2, float y1, float y2, const unsigned char background_col[3])
{
@@ -554,7 +478,7 @@ static void draw_seq_text(View2D *v2d, Sequence *seq, float x1, float x2, float
}
}
else if (seq->type == SEQ_TYPE_MOVIECLIP) {
- if (seq->clip && strcmp(name, seq->clip->id.name + 2) != 0) {
+ if (seq->clip && !STREQ(name, seq->clip->id.name + 2)) {
str_len = BLI_snprintf(str, sizeof(str), "%s: %s | %d",
name, seq->clip->id.name + 2, seq->len);
}
@@ -564,7 +488,7 @@ static void draw_seq_text(View2D *v2d, Sequence *seq, float x1, float x2, float
}
}
else if (seq->type == SEQ_TYPE_MASK) {
- if (seq->mask && strcmp(name, seq->mask->id.name + 2) != 0) {
+ if (seq->mask && !STREQ(name, seq->mask->id.name + 2)) {
str_len = BLI_snprintf(str, sizeof(str), "%s: %s | %d",
name, seq->mask->id.name + 2, seq->len);
}
@@ -581,6 +505,11 @@ static void draw_seq_text(View2D *v2d, Sequence *seq, float x1, float x2, float
str_len = BLI_snprintf(str, sizeof(str), "%s: %s%s | %d",
name, seq->strip->dir, seq->strip->stripdata->name, seq->len);
}
+ else if (seq->type == SEQ_TYPE_TEXT) {
+ TextVars *textdata = seq->effectdata;
+ str_len = BLI_snprintf(str, sizeof(str), "%s | %d",
+ textdata->text, seq->startdisp);
+ }
else if (seq->type & SEQ_TYPE_EFFECT) {
str_len = BLI_snprintf(str, sizeof(str), "%s | %d",
name, seq->len);
@@ -627,7 +556,7 @@ static void draw_seq_text(View2D *v2d, Sequence *seq, float x1, float x2, float
}
/* draws a shaded strip, made from gradient + flat color + gradient */
-static void draw_shadedstrip(Sequence *seq, unsigned char col[3], float x1, float y1, float x2, float y2)
+void draw_shadedstrip(Sequence *seq, unsigned char col[3], float x1, float y1, float x2, float y2)
{
float ymid1, ymid2;
@@ -684,12 +613,117 @@ static void draw_shadedstrip(Sequence *seq, unsigned char col[3], float x1, floa
}
}
+void draw_sequence_extensions(Scene *scene, ARegion *ar, Sequence *seq)
+{
+ float x1, x2, y1, y2, pixely, a;
+ unsigned char col[3], blendcol[3];
+ View2D *v2d = &ar->v2d;
+
+ x1 = seq->startdisp;
+ x2 = seq->enddisp;
+
+ y1 = seq->machine + SEQ_STRIP_OFSBOTTOM;
+ y2 = seq->machine + SEQ_STRIP_OFSTOP;
+
+ pixely = BLI_rctf_size_y(&v2d->cur) / BLI_rcti_size_y(&v2d->mask);
+
+ if (pixely <= 0) return; /* can happen when the view is split/resized */
+
+ blendcol[0] = blendcol[1] = blendcol[2] = 120;
+
+ if (seq->startofs) {
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+ color3ubv_from_seq(scene, seq, col);
+
+ if (seq->flag & SELECT) {
+ UI_GetColorPtrBlendShade3ubv(col, blendcol, col, 0.3, -40);
+ glColor4ub(col[0], col[1], col[2], 170);
+ }
+ else {
+ UI_GetColorPtrBlendShade3ubv(col, blendcol, col, 0.6, 0);
+ glColor4ub(col[0], col[1], col[2], 110);
+ }
+
+ glRectf((float)(seq->start), y1 - SEQ_STRIP_OFSBOTTOM, x1, y1);
+
+ if (seq->flag & SELECT) glColor4ub(col[0], col[1], col[2], 255);
+ else glColor4ub(col[0], col[1], col[2], 160);
+
+ fdrawbox((float)(seq->start), y1 - SEQ_STRIP_OFSBOTTOM, x1, y1); //outline
+
+ glDisable(GL_BLEND);
+ }
+ if (seq->endofs) {
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+ color3ubv_from_seq(scene, seq, col);
+
+ if (seq->flag & SELECT) {
+ UI_GetColorPtrBlendShade3ubv(col, blendcol, col, 0.3, -40);
+ glColor4ub(col[0], col[1], col[2], 170);
+ }
+ else {
+ UI_GetColorPtrBlendShade3ubv(col, blendcol, col, 0.6, 0);
+ glColor4ub(col[0], col[1], col[2], 110);
+ }
+
+ glRectf(x2, y2, (float)(seq->start + seq->len), y2 + SEQ_STRIP_OFSBOTTOM);
+
+ if (seq->flag & SELECT) glColor4ub(col[0], col[1], col[2], 255);
+ else glColor4ub(col[0], col[1], col[2], 160);
+
+ fdrawbox(x2, y2, (float)(seq->start + seq->len), y2 + SEQ_STRIP_OFSBOTTOM); //outline
+
+ glDisable(GL_BLEND);
+ }
+ if (seq->startstill) {
+ color3ubv_from_seq(scene, seq, col);
+ UI_GetColorPtrBlendShade3ubv(col, blendcol, col, 0.75, 40);
+ glColor3ubv((GLubyte *)col);
+
+ draw_shadedstrip(seq, col, x1, y1, (float)(seq->start), y2);
+
+ /* feint pinstripes, helps see exactly which is extended and which isn't,
+ * especially when the extension is very small */
+ if (seq->flag & SELECT) UI_GetColorPtrBlendShade3ubv(col, col, col, 0.0, 24);
+ else UI_GetColorPtrShade3ubv(col, col, -16);
+
+ glColor3ubv((GLubyte *)col);
+
+ for (a = y1; a < y2; a += pixely * 2.0f) {
+ fdrawline(x1, a, (float)(seq->start), a);
+ }
+ }
+ if (seq->endstill) {
+ color3ubv_from_seq(scene, seq, col);
+ UI_GetColorPtrBlendShade3ubv(col, blendcol, col, 0.75, 40);
+ glColor3ubv((GLubyte *)col);
+
+ draw_shadedstrip(seq, col, (float)(seq->start + seq->len), y1, x2, y2);
+
+ /* feint pinstripes, helps see exactly which is extended and which isn't,
+ * especially when the extension is very small */
+ if (seq->flag & SELECT) UI_GetColorPtrShade3ubv(col, col, 24);
+ else UI_GetColorPtrShade3ubv(col, col, -16);
+
+ glColor3ubv((GLubyte *)col);
+
+ for (a = y1; a < y2; a += pixely * 2.0f) {
+ fdrawline((float)(seq->start + seq->len), a, x2, a);
+ }
+ }
+}
+
+
/*
* Draw a sequence strip, bounds check already made
* ARegion is currently only used to get the windows width in pixels
* so wave file sample drawing precision is zoom adjusted
*/
-static void draw_seq_strip(Scene *scene, ARegion *ar, Sequence *seq, int outline_tint, float pixelx)
+static void draw_seq_strip(const bContext *C, SpaceSeq *sseq, Scene *scene, ARegion *ar, Sequence *seq, int outline_tint, float pixelx)
{
View2D *v2d = &ar->v2d;
float x1, x2, y1, y2;
@@ -707,8 +741,8 @@ static void draw_seq_strip(Scene *scene, ARegion *ar, Sequence *seq, int outline
/* get the correct color per strip type*/
- //get_seq_color3ubv(scene, seq, col);
- get_seq_color3ubv(scene, seq, background_col);
+ //color3ubv_from_seq(scene, seq, col);
+ color3ubv_from_seq(scene, seq, background_col);
/* draw the main strip body */
if (is_single_image) { /* single image */
@@ -719,11 +753,13 @@ static void draw_seq_strip(Scene *scene, ARegion *ar, Sequence *seq, int outline
else { /* normal operation */
draw_shadedstrip(seq, background_col, x1, y1, x2, y2);
}
-
- /* draw additional info and controls */
- if (!is_single_image)
- draw_seq_extensions(scene, ar, seq);
-
+
+ if (!is_single_image) {
+ if ((sseq->draw_flag & SEQ_DRAW_OFFSET_EXT) || (seq == special_seq_update)) {
+ draw_sequence_extensions(scene, ar, seq);
+ }
+ }
+
draw_seq_handle(v2d, seq, handsize_clamped, SEQ_LEFTHANDLE);
draw_seq_handle(v2d, seq, handsize_clamped, SEQ_RIGHTHANDLE);
@@ -733,7 +769,9 @@ static void draw_seq_strip(Scene *scene, ARegion *ar, Sequence *seq, int outline
/* draw sound wave */
if (seq->type == SEQ_TYPE_SOUND_RAM) {
- drawseqwave(scene, seq, x1, y1, x2, y2, BLI_rctf_size_x(&ar->v2d.cur) / ar->winx);
+ if (!(sseq->flag & SEQ_NO_WAVEFORMS)) {
+ drawseqwave(C, sseq, scene, seq, x1, y1, x2, y2, BLI_rctf_size_x(&ar->v2d.cur) / ar->winx);
+ }
}
/* draw lock */
@@ -766,7 +804,7 @@ static void draw_seq_strip(Scene *scene, ARegion *ar, Sequence *seq, int outline
glDisable(GL_POLYGON_STIPPLE);
}
- get_seq_color3ubv(scene, seq, col);
+ color3ubv_from_seq(scene, seq, col);
if ((G.moving & G_TRANSFORM_SEQ) && (seq->flag & SELECT)) {
if (seq->flag & SEQ_OVERLAP) {
col[0] = 255; col[1] = col[2] = 40;
@@ -784,7 +822,7 @@ static void draw_seq_strip(Scene *scene, ARegion *ar, Sequence *seq, int outline
glLineStipple(1, 0x8888);
}
- uiDrawBoxShade(GL_LINE_LOOP, x1, y1, x2, y2, 0.0, 0.1, 0.0);
+ UI_draw_roundbox_shade_x(GL_LINE_LOOP, x1, y1, x2, y2, 0.0, 0.1, 0.0);
if (seq->flag & SEQ_MUTE) {
glDisable(GL_LINE_STIPPLE);
@@ -810,22 +848,32 @@ static void draw_seq_strip(Scene *scene, ARegion *ar, Sequence *seq, int outline
}
}
-static Sequence *special_seq_update = NULL;
+void sequencer_special_update_set(Sequence *seq)
+{
+ special_seq_update = seq;
+}
-static void UNUSED_FUNCTION(set_special_seq_update) (int val)
+Sequence *ED_sequencer_special_preview_get(void)
{
-// int x;
+ return special_seq_update;
+}
- /* if mouse over a sequence && LEFTMOUSE */
- if (val) {
-// XXX special_seq_update = find_nearest_seq(&x);
- }
- else {
- special_seq_update = NULL;
- }
+void ED_sequencer_special_preview_set(bContext *C, const int mval[2])
+{
+ Scene *scene = CTX_data_scene(C);
+ ARegion *ar = CTX_wm_region(C);
+ int hand;
+ Sequence *seq;
+ seq = find_nearest_seq(scene, &ar->v2d, &hand, mval);
+ sequencer_special_update_set(seq);
+}
+
+void ED_sequencer_special_preview_clear(void)
+{
+ sequencer_special_update_set(NULL);
}
-ImBuf *sequencer_ibuf_get(struct Main *bmain, Scene *scene, SpaceSeq *sseq, int cfra, int frame_ofs)
+ImBuf *sequencer_ibuf_get(struct Main *bmain, Scene *scene, SpaceSeq *sseq, int cfra, int frame_ofs, const char *viewname)
{
SeqRenderData context;
ImBuf *ibuf;
@@ -835,9 +883,6 @@ ImBuf *sequencer_ibuf_get(struct Main *bmain, Scene *scene, SpaceSeq *sseq, int
short is_break = G.is_break;
render_size = sseq->render_size;
- if (render_size == 99) {
- render_size = 100;
- }
if (render_size == 0) {
render_size = scene->r.size;
}
@@ -852,7 +897,11 @@ ImBuf *sequencer_ibuf_get(struct Main *bmain, Scene *scene, SpaceSeq *sseq, int
rectx = (render_size * (float)scene->r.xsch) / 100.0f + 0.5f;
recty = (render_size * (float)scene->r.ysch) / 100.0f + 0.5f;
- context = BKE_sequencer_new_render_data(bmain->eval_ctx, bmain, scene, rectx, recty, proxy_size);
+ BKE_sequencer_new_render_data(
+ bmain->eval_ctx, bmain, scene,
+ rectx, recty, proxy_size,
+ &context);
+ context.view_id = BKE_scene_multiview_view_id_get(&scene->r, viewname);
/* sequencer could start rendering, in this case we need to be sure it wouldn't be canceled
* by Esc pressed somewhere in the past
@@ -917,16 +966,110 @@ static ImBuf *sequencer_make_scope(Scene *scene, ImBuf *ibuf, ImBuf *(*make_scop
return scope;
}
-void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq, int cfra, int frame_ofs, bool draw_overlay)
+static void sequencer_display_size(Scene *scene, SpaceSeq *sseq, float r_viewrect[2])
+{
+ float render_size, proxy_size;
+
+ if (sseq->render_size == SEQ_PROXY_RENDER_SIZE_SCENE) {
+ render_size = (float)scene->r.size / 100.0f;
+ proxy_size = 1.0f;
+ }
+ else {
+ render_size = (float)sseq->render_size / 100.0f;
+ proxy_size = render_size;
+ }
+
+ r_viewrect[0] = (render_size * (float)scene->r.xsch);
+ r_viewrect[1] = (render_size * (float)scene->r.ysch);
+
+ /* rectx = viewrectx + 0.5f; */ /* UNUSED */
+ /* recty = viewrecty + 0.5f; */ /* UNUSED */
+
+ if (sseq->mainb == SEQ_DRAW_IMG_IMBUF) {
+ r_viewrect[0] *= scene->r.xasp / scene->r.yasp;
+ r_viewrect[0] /= proxy_size;
+ r_viewrect[1] /= proxy_size;
+ }
+}
+
+static void sequencer_draw_gpencil(const bContext *C)
+{
+ /* draw grease-pencil (image aligned) */
+ ED_gpencil_draw_2dimage(C);
+
+ /* ortho at pixel level */
+ UI_view2d_view_restore(C);
+
+ /* draw grease-pencil (screen aligned) */
+ ED_gpencil_draw_view2d(C, 0);
+}
+
+/* draws content borders plus safety borders if needed */
+static void sequencer_draw_borders(const SpaceSeq *sseq, const View2D *v2d, const Scene *scene)
+{
+ float x1 = v2d->tot.xmin;
+ float y1 = v2d->tot.ymin;
+ float x2 = v2d->tot.xmax;
+ float y2 = v2d->tot.ymax;
+
+ /* border */
+ setlinestyle(3);
+
+ UI_ThemeColorBlendShade(TH_WIRE, TH_BACK, 1.0, 0);
+
+ glBegin(GL_LINE_LOOP);
+ glVertex2f(x1 - 0.5f, y1 - 0.5f);
+ glVertex2f(x1 - 0.5f, y2 + 0.5f);
+ glVertex2f(x2 + 0.5f, y2 + 0.5f);
+ glVertex2f(x2 + 0.5f, y1 - 0.5f);
+ glEnd();
+
+ /* safety border */
+ if (sseq->flag & SEQ_SHOW_SAFE_MARGINS) {
+ UI_draw_safe_areas(
+ x1, x2, y1, y2,
+ scene->safe_areas.title,
+ scene->safe_areas.action);
+
+ if (sseq->flag & SEQ_SHOW_SAFE_CENTER) {
+ UI_draw_safe_areas(
+ x1, x2, y1, y2,
+ scene->safe_areas.title_center,
+ scene->safe_areas.action_center);
+ }
+ }
+
+ setlinestyle(0);
+}
+
+/* draws checkerboard background for transparent content */
+static void sequencer_draw_background(const SpaceSeq *sseq, View2D *v2d, const float viewrect[2])
+{
+ /* setting up the view */
+ UI_view2d_totRect_set(v2d, viewrect[0] + 0.5f, viewrect[1] + 0.5f);
+ UI_view2d_curRect_validate(v2d);
+ UI_view2d_view_ortho(v2d);
+
+ /* only draw alpha for main buffer */
+ if (sseq->mainb == SEQ_DRAW_IMG_IMBUF) {
+ if (sseq->flag & SEQ_USE_ALPHA) {
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+ fdrawcheckerboard(v2d->tot.xmin, v2d->tot.ymin, v2d->tot.xmax, v2d->tot.ymax);
+ glColor4f(1.0, 1.0, 1.0, 1.0);
+ }
+ }
+}
+
+void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq, int cfra, int frame_ofs, bool draw_overlay, bool draw_backdrop)
{
struct Main *bmain = CTX_data_main(C);
struct ImBuf *ibuf = NULL;
struct ImBuf *scope = NULL;
struct View2D *v2d = &ar->v2d;
/* int rectx, recty; */ /* UNUSED */
- float viewrectx, viewrecty;
- float render_size = 0.0;
- float proxy_size = 100.0;
+ float viewrect[2];
float col[3];
GLuint texid;
GLuint last_texid;
@@ -935,6 +1078,9 @@ void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq
const bool is_imbuf = ED_space_sequencer_check_show_imbuf(sseq);
int format, type;
bool glsl_used = false;
+ const bool draw_gpencil = ((sseq->flag & SEQ_SHOW_GPENCIL) && sseq->gpd);
+ const char *names[2] = {STEREO_LEFT_NAME, STEREO_RIGHT_NAME};
+ bool draw_metadata = false;
if (G.is_rendering == false && (scene->r.seq_flag & R_SEQ_GL_PREV) == 0) {
/* stop all running jobs, except screen one. currently previews frustrate Render
@@ -950,48 +1096,44 @@ void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq
}
}
- render_size = sseq->render_size;
- if (render_size == 0) {
- render_size = scene->r.size;
- }
- else {
- proxy_size = render_size;
- }
- if (render_size < 0) {
- return;
- }
-
- viewrectx = (render_size * (float)scene->r.xsch) / 100.0f;
- viewrecty = (render_size * (float)scene->r.ysch) / 100.0f;
-
- /* rectx = viewrectx + 0.5f; */ /* UNUSED */
- /* recty = viewrecty + 0.5f; */ /* UNUSED */
-
- if (sseq->mainb == SEQ_DRAW_IMG_IMBUF) {
- viewrectx *= scene->r.xasp / scene->r.yasp;
- viewrectx /= proxy_size / 100.0f;
- viewrecty /= proxy_size / 100.0f;
- }
-
- if (!draw_overlay || sseq->overlay_type == SEQ_DRAW_OVERLAY_REFERENCE) {
+ if ((!draw_overlay || sseq->overlay_type == SEQ_DRAW_OVERLAY_REFERENCE) && !draw_backdrop) {
UI_GetThemeColor3fv(TH_SEQ_PREVIEW, col);
glClearColor(col[0], col[1], col[2], 0.0);
glClear(GL_COLOR_BUFFER_BIT);
}
+ /* without this colors can flicker from previous opengl state */
+ glColor4ub(255, 255, 255, 255);
+
/* only initialize the preview if a render is in progress */
if (G.is_rendering)
return;
- ibuf = sequencer_ibuf_get(bmain, scene, sseq, cfra, frame_ofs);
-
- if (ibuf == NULL)
+ if (sseq->render_size == SEQ_PROXY_RENDER_SIZE_NONE) {
return;
+ }
- if (ibuf->rect == NULL && ibuf->rect_float == NULL)
+ /* for now we only support Left/Right */
+ ibuf = sequencer_ibuf_get(bmain, scene, sseq, cfra, frame_ofs, names[sseq->multiview_eye]);
+
+ if ((ibuf == NULL) ||
+ (ibuf->rect == NULL && ibuf->rect_float == NULL))
+ {
+ /* gpencil can also be drawn without a valid imbuf */
+ if (draw_gpencil && is_imbuf) {
+ sequencer_display_size(scene, sseq, viewrect);
+
+ sequencer_draw_background(sseq, v2d, viewrect);
+ sequencer_draw_borders(sseq, v2d, scene);
+
+ sequencer_draw_gpencil(C);
+ }
return;
+ }
- if (sseq->mainb != SEQ_DRAW_IMG_IMBUF || sseq->zebra != 0) {
+ sequencer_display_size(scene, sseq, viewrect);
+
+ if (!draw_backdrop && (sseq->mainb != SEQ_DRAW_IMG_IMBUF || sseq->zebra != 0)) {
SequencerScopes *scopes = &sseq->scopes;
sequencer_check_scopes(scopes, ibuf);
@@ -1037,32 +1179,21 @@ void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq
/* future files may have new scopes we don't catch above */
if (scope) {
scopes->reference_ibuf = ibuf;
- viewrectx = scope->x;
- viewrecty = scope->y;
+ if (sseq->mainb == SEQ_DRAW_IMG_IMBUF) {
+ /* scopes drawn in image preview use viewrect from orig ibuf - currently that's only zebra */
+ }
+ else {
+ viewrect[0] = scope->x;
+ viewrect[1] = scope->y;
+ }
}
else {
scopes->reference_ibuf = NULL;
}
}
- /* without this colors can flicker from previous opengl state */
- glColor4ub(255, 255, 255, 255);
-
- UI_view2d_totRect_set(v2d, viewrectx + 0.5f, viewrecty + 0.5f);
- UI_view2d_curRect_validate(v2d);
-
- /* setting up the view - actual drawing starts here */
- UI_view2d_view_ortho(v2d);
-
- /* only draw alpha for main buffer */
- if (sseq->mainb == SEQ_DRAW_IMG_IMBUF) {
- if (sseq->flag & SEQ_USE_ALPHA) {
- glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-
- fdrawcheckerboard(v2d->tot.xmin, v2d->tot.ymin, v2d->tot.xmax, v2d->tot.ymax);
- glColor4f(1.0, 1.0, 1.0, 1.0);
- }
+ if (!draw_backdrop) {
+ sequencer_draw_background(sseq, v2d, viewrect);
}
if (scope) {
@@ -1154,6 +1285,14 @@ void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq
else
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, ibuf->x, ibuf->y, 0, format, type, display_buffer);
+ if (draw_backdrop) {
+ glMatrixMode(GL_PROJECTION);
+ glPushMatrix();
+ glLoadIdentity();
+ glMatrixMode(GL_MODELVIEW);
+ glPushMatrix();
+ glLoadIdentity();
+ }
glBegin(GL_QUADS);
if (draw_overlay) {
@@ -1176,13 +1315,37 @@ void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq
glTexCoord2f(1.0f, 0.0f); glVertex2f(v2d->tot.xmax, v2d->tot.ymin);
}
}
+ else if (draw_backdrop) {
+ float aspect;
+ float image_aspect = viewrect[0] / viewrect[1];
+ float imagex, imagey;
+
+ aspect = BLI_rcti_size_x(&ar->winrct) / (float)BLI_rcti_size_y(&ar->winrct);
+
+ if (aspect >= image_aspect) {
+ imagex = image_aspect / aspect;
+ imagey = 1.0f;
+ }
+ else {
+ imagex = 1.0f;
+ imagey = aspect / image_aspect;
+ }
+
+ glTexCoord2f(0.0f, 0.0f); glVertex2f(-imagex, -imagey);
+ glTexCoord2f(0.0f, 1.0f); glVertex2f(-imagex, imagey);
+ glTexCoord2f(1.0f, 1.0f); glVertex2f(imagex, imagey);
+ glTexCoord2f(1.0f, 0.0f); glVertex2f(imagex, -imagey);
+ }
else {
+ draw_metadata = ((sseq->flag & SEQ_SHOW_METADATA) != 0);
+
glTexCoord2f(0.0f, 0.0f); glVertex2f(v2d->tot.xmin, v2d->tot.ymin);
glTexCoord2f(0.0f, 1.0f); glVertex2f(v2d->tot.xmin, v2d->tot.ymax);
glTexCoord2f(1.0f, 1.0f); glVertex2f(v2d->tot.xmax, v2d->tot.ymax);
glTexCoord2f(1.0f, 0.0f); glVertex2f(v2d->tot.xmax, v2d->tot.ymin);
}
glEnd();
+
glBindTexture(GL_TEXTURE_2D, last_texid);
glDisable(GL_TEXTURE_2D);
if (sseq->mainb == SEQ_DRAW_IMG_IMBUF && sseq->flag & SEQ_USE_ALPHA)
@@ -1192,67 +1355,34 @@ void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq
if (glsl_used)
IMB_colormanagement_finish_glsl_draw();
- if (sseq->mainb == SEQ_DRAW_IMG_IMBUF) {
-
- float x1 = v2d->tot.xmin;
- float y1 = v2d->tot.ymin;
- float x2 = v2d->tot.xmax;
- float y2 = v2d->tot.ymax;
-
- /* border */
- setlinestyle(3);
-
- UI_ThemeColorBlendShade(TH_WIRE, TH_BACK, 1.0, 0);
-
- glBegin(GL_LINE_LOOP);
- glVertex2f(x1 - 0.5f, y1 - 0.5f);
- glVertex2f(x1 - 0.5f, y2 + 0.5f);
- glVertex2f(x2 + 0.5f, y2 + 0.5f);
- glVertex2f(x2 + 0.5f, y1 - 0.5f);
- glEnd();
-
- /* safety border */
- if ((sseq->flag & SEQ_DRAW_SAFE_MARGINS) != 0) {
- float fac = 0.1;
-
- float a = fac * (x2 - x1);
- x1 += a;
- x2 -= a;
-
- a = fac * (y2 - y1);
- y1 += a;
- y2 -= a;
-
- glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
-
- uiSetRoundBox(UI_CNR_ALL);
- uiDrawBox(GL_LINE_LOOP, x1, y1, x2, y2, 12.0);
+ if (cache_handle)
+ IMB_display_buffer_release(cache_handle);
- glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
+ if (!scope)
+ IMB_freeImBuf(ibuf);
- }
+ if (draw_metadata) {
+ ED_region_image_metadata_draw(0.0, 0.0, ibuf, v2d->tot, 1.0, 1.0);
+ }
- setlinestyle(0);
+ if (draw_backdrop) {
+ glPopMatrix();
+ glMatrixMode(GL_PROJECTION);
+ glPopMatrix();
+ glMatrixMode(GL_MODELVIEW);
+ return;
}
-
- if (sseq->flag & SEQ_SHOW_GPENCIL) {
- if (is_imbuf) {
- /* draw grease-pencil (image aligned) */
- ED_gpencil_draw_2dimage(C);
- }
+
+ if (sseq->mainb == SEQ_DRAW_IMG_IMBUF) {
+ sequencer_draw_borders(sseq, v2d, scene);
}
- if (!scope)
- IMB_freeImBuf(ibuf);
-
- /* ortho at pixel level */
- UI_view2d_view_restore(C);
-
- if (sseq->flag & SEQ_SHOW_GPENCIL) {
- if (is_imbuf) {
- /* draw grease-pencil (screen aligned) */
- ED_gpencil_draw_view2d(C, 0);
- }
+ if (draw_gpencil && is_imbuf) {
+ sequencer_draw_gpencil(C);
+ }
+ else {
+ /* ortho at pixel level */
+ UI_view2d_view_restore(C);
}
@@ -1280,9 +1410,6 @@ void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq
NULL, C);
}
}
-
- if (cache_handle)
- IMB_display_buffer_release(cache_handle);
}
#if 0
@@ -1359,6 +1486,7 @@ static void draw_seq_strips(const bContext *C, Editing *ed, ARegion *ar)
{
Scene *scene = CTX_data_scene(C);
View2D *v2d = &ar->v2d;
+ SpaceSeq *sseq = CTX_wm_space_seq(C);
Sequence *last_seq = BKE_sequencer_active_get(scene);
int sel = 0, j;
float pixelx = BLI_rctf_size_x(&v2d->cur) / BLI_rcti_size_x(&v2d->mask);
@@ -1379,7 +1507,7 @@ static void draw_seq_strips(const bContext *C, Editing *ed, ARegion *ar)
else if (seq->machine > v2d->cur.ymax) continue;
/* strip passed all tests unscathed... so draw it now */
- draw_seq_strip(scene, ar, seq, outline_tint, pixelx);
+ draw_seq_strip(C, sseq, scene, ar, seq, outline_tint, pixelx);
}
/* draw selected next time round */
@@ -1388,20 +1516,33 @@ static void draw_seq_strips(const bContext *C, Editing *ed, ARegion *ar)
/* draw the last selected last (i.e. 'active' in other parts of Blender), removes some overlapping error */
if (last_seq)
- draw_seq_strip(scene, ar, last_seq, 120, pixelx);
+ draw_seq_strip(C, sseq, scene, ar, last_seq, 120, pixelx);
+
+ /* draw highlight when previewing a single strip */
+ if (special_seq_update) {
+ const Sequence *seq = special_seq_update;
+ glEnable(GL_BLEND);
+ glColor4ub(255, 255, 255, 48);
+ glRectf(seq->startdisp, seq->machine + SEQ_STRIP_OFSBOTTOM, seq->enddisp, seq->machine + SEQ_STRIP_OFSTOP);
+ glDisable(GL_BLEND);
+ }
}
static void seq_draw_sfra_efra(Scene *scene, View2D *v2d)
-{
+{
+ const Editing *ed = BKE_sequencer_editing_get(scene, false);
+ const int frame_sta = PSFRA;
+ const int frame_end = PEFRA + 1;
+
glEnable(GL_BLEND);
/* draw darkened area outside of active timeline
* frame range used is preview range or scene range */
UI_ThemeColorShadeAlpha(TH_BACK, -25, -100);
- if (PSFRA < PEFRA + 1) {
- glRectf(v2d->cur.xmin, v2d->cur.ymin, (float)PSFRA, v2d->cur.ymax);
- glRectf((float)(PEFRA + 1), v2d->cur.ymin, v2d->cur.xmax, v2d->cur.ymax);
+ if (frame_sta < frame_end) {
+ glRectf(v2d->cur.xmin, v2d->cur.ymin, (float)frame_sta, v2d->cur.ymax);
+ glRectf((float)frame_end, v2d->cur.ymin, v2d->cur.xmax, v2d->cur.ymax);
}
else {
glRectf(v2d->cur.xmin, v2d->cur.ymin, v2d->cur.xmax, v2d->cur.ymax);
@@ -1409,9 +1550,21 @@ static void seq_draw_sfra_efra(Scene *scene, View2D *v2d)
UI_ThemeColorShade(TH_BACK, -60);
/* thin lines where the actual frames are */
- fdrawline((float)PSFRA, v2d->cur.ymin, (float)PSFRA, v2d->cur.ymax);
- fdrawline((float)(PEFRA + 1), v2d->cur.ymin, (float)(PEFRA + 1), v2d->cur.ymax);
-
+ fdrawline(frame_sta, v2d->cur.ymin, frame_sta, v2d->cur.ymax);
+ fdrawline(frame_end, v2d->cur.ymin, frame_end, v2d->cur.ymax);
+
+ if (ed && !BLI_listbase_is_empty(&ed->metastack)) {
+ MetaStack *ms = ed->metastack.last;
+
+ glColor4ub(255, 255, 255, 8);
+ glRectf(ms->disp_range[0], v2d->cur.ymin, ms->disp_range[1], v2d->cur.ymax);
+
+ UI_ThemeColorShade(TH_BACK, -40);
+
+ fdrawline(ms->disp_range[0], v2d->cur.ymin, ms->disp_range[0], v2d->cur.ymax);
+ fdrawline(ms->disp_range[1], v2d->cur.ymin, ms->disp_range[1], v2d->cur.ymax);
+ }
+
glDisable(GL_BLEND);
}
@@ -1450,6 +1603,11 @@ void draw_timeline_seq(const bContext *C, ARegion *ar)
// NOTE: the gridlines are currently spaced every 25 frames, which is only fine for 25 fps, but maybe not for 30...
UI_view2d_constant_grid_draw(v2d);
+ if (sseq->draw_flag & SEQ_DRAW_BACKDROP) {
+ draw_image_seq(C, scene, ar, sseq, scene->r.cfra, 0, false, true);
+ UI_view2d_view_ortho(v2d);
+ }
+
ED_region_draw_cb_draw(C, ar, REGION_DRAW_PRE_VIEW);
seq_draw_sfra_efra(scene, v2d);
@@ -1471,7 +1629,7 @@ void draw_timeline_seq(const bContext *C, ARegion *ar)
/* markers */
UI_view2d_view_orthoSpecial(ar, v2d, 1);
- draw_markers_time(C, DRAW_MARKERS_LINES);
+ ED_markers_draw(C, DRAW_MARKERS_LINES | DRAW_MARKERS_MARGIN);
/* preview range */
UI_view2d_view_ortho(v2d);
diff --git a/source/blender/editors/space_sequencer/sequencer_edit.c b/source/blender/editors/space_sequencer/sequencer_edit.c
index 9c43d22ae2f..3cc0276104e 100644
--- a/source/blender/editors/space_sequencer/sequencer_edit.c
+++ b/source/blender/editors/space_sequencer/sequencer_edit.c
@@ -35,10 +35,13 @@
#include "MEM_guardedalloc.h"
#include "BLI_blenlib.h"
+#include "BLI_fileops.h"
+#include "BLI_ghash.h"
#include "BLI_math.h"
+#include "BLI_timecode.h"
#include "BLI_utildefines.h"
-#include "BLF_translation.h"
+#include "BLT_translation.h"
#include "DNA_scene_types.h"
@@ -49,7 +52,6 @@
#include "BKE_report.h"
#include "BKE_sound.h"
-#include "IMB_imbuf.h"
#include "WM_api.h"
#include "WM_types.h"
@@ -59,11 +61,15 @@
/* for menu/popup icons etc etc*/
+#include "ED_numinput.h"
#include "ED_screen.h"
#include "ED_transform.h"
#include "ED_sequencer.h"
+#include "ED_space_api.h"
#include "UI_view2d.h"
+#include "UI_interface.h"
+
/* own include */
#include "sequencer_intern.h"
@@ -87,6 +93,7 @@ EnumPropertyItem sequencer_prop_effect_types[] = {
{SEQ_TYPE_MULTICAM, "MULTICAM", 0, "Multicam Selector", ""},
{SEQ_TYPE_ADJUSTMENT, "ADJUSTMENT", 0, "Adjustment Layer", ""},
{SEQ_TYPE_GAUSSIAN_BLUR, "GAUSSIAN_BLUR", 0, "Gaussian Blur", ""},
+ {SEQ_TYPE_TEXT, "TEXT", 0, "Text", ""},
{0, NULL, 0, NULL, NULL}
};
@@ -145,11 +152,12 @@ static void proxy_startjob(void *pjv, short *stop, short *do_update, float *prog
struct SeqIndexBuildContext *context = link->data;
BKE_sequencer_proxy_rebuild(context, stop, do_update, progress);
- }
-
- if (*stop) {
- pj->stop = 1;
- fprintf(stderr, "Canceling proxy rebuild on users request...\n");
+
+ if (*stop) {
+ pj->stop = 1;
+ fprintf(stderr, "Canceling proxy rebuild on users request...\n");
+ break;
+ }
}
}
@@ -175,9 +183,12 @@ static void seq_proxy_build_job(const bContext *C)
Scene *scene = CTX_data_scene(C);
Editing *ed = BKE_sequencer_editing_get(scene, false);
ScrArea *sa = CTX_wm_area(C);
- struct SeqIndexBuildContext *context;
- LinkData *link;
Sequence *seq;
+ GSet *file_list;
+
+ if (ed == NULL) {
+ return;
+ }
wm_job = WM_jobs_get(CTX_wm_manager(C), CTX_wm_window(C), sa, "Building Proxies",
WM_JOB_PROGRESS, WM_JOB_TYPE_SEQ_BUILD_PROXY);
@@ -195,16 +206,17 @@ static void seq_proxy_build_job(const bContext *C)
WM_jobs_callbacks(wm_job, proxy_startjob, NULL, NULL, proxy_endjob);
}
+ file_list = BLI_gset_new(BLI_ghashutil_strhash_p, BLI_ghashutil_strcmp, "file list");
SEQP_BEGIN (ed, seq)
{
if ((seq->flag & SELECT)) {
- context = BKE_sequencer_proxy_rebuild_context(pj->main, pj->scene, seq);
- link = BLI_genericNodeN(context);
- BLI_addtail(&pj->queue, link);
+ BKE_sequencer_proxy_rebuild_context(pj->main, pj->scene, seq, file_list, &pj->queue);
}
}
SEQ_END
+ BLI_gset_free(file_list, MEM_freeN);
+
if (!WM_jobs_is_running(wm_job)) {
G.is_break = false;
WM_jobs_start(CTX_wm_manager(C), wm_job);
@@ -385,7 +397,7 @@ Sequence *find_nearest_seq(Scene *scene, View2D *v2d, int *hand, const int mval[
displen = (float)abs(seq->startdisp - seq->enddisp);
if (displen / pixelx > 16) { /* don't even try to grab the handles of small strips */
- /* Set the max value to handle to 1/3 of the total len when its less then 28.
+ /* Set the max value to handle to 1/3 of the total len when its less than 28.
* This is important because otherwise selecting handles happens even when you click in the middle */
if ((displen / 3) < 30 * pixelx) {
@@ -494,6 +506,13 @@ bool ED_space_sequencer_check_show_imbuf(SpaceSeq *sseq)
ELEM(sseq->mainb, SEQ_DRAW_SEQUENCE, SEQ_DRAW_IMG_IMBUF));
}
+bool ED_space_sequencer_check_show_strip(SpaceSeq *sseq)
+{
+ return (ELEM(sseq->view, SEQ_VIEW_SEQUENCE, SEQ_VIEW_SEQUENCE_PREVIEW) &&
+ ELEM(sseq->mainb, SEQ_DRAW_SEQUENCE, SEQ_DRAW_IMG_IMBUF));
+}
+
+
int seq_effect_find_selected(Scene *scene, Sequence *activeseq, int type, Sequence **selseq1, Sequence **selseq2, Sequence **selseq3, const char **error_str)
{
Editing *ed = BKE_sequencer_editing_get(scene, false);
@@ -884,6 +903,7 @@ static bool sequence_offset_after_frame(Scene *scene, const int delta, const int
Sequence *seq;
Editing *ed = BKE_sequencer_editing_get(scene, false);
bool done = false;
+ TimeMarker *marker;
/* all strips >= cfra are shifted */
@@ -897,6 +917,14 @@ static bool sequence_offset_after_frame(Scene *scene, const int delta, const int
}
}
+ if (!scene->toolsettings->lock_markers) {
+ for (marker = scene->markers.first; marker; marker = marker->next) {
+ if (marker->frame >= cfra) {
+ marker->frame += delta;
+ }
+ }
+ }
+
return done;
}
@@ -968,20 +996,20 @@ static void UNUSED_FUNCTION(seq_remap_paths) (Scene *scene)
return;
BLI_strncpy(from, last_seq->strip->dir, sizeof(from));
-// XXX if (0 == sbutton(from, 0, sizeof(from)-1, "From: "))
+// XXX if (0 == sbutton(from, 0, sizeof(from) - 1, "From: "))
// return;
BLI_strncpy(to, from, sizeof(to));
-// XXX if (0 == sbutton(to, 0, sizeof(to)-1, "To: "))
+// XXX if (0 == sbutton(to, 0, sizeof(to) - 1, "To: "))
// return;
- if (strcmp(to, from) == 0)
+ if (STREQ(to, from))
return;
SEQP_BEGIN (ed, seq)
{
if (seq->flag & SELECT) {
- if (strncmp(seq->strip->dir, from, strlen(from)) == 0) {
+ if (STREQLEN(seq->strip->dir, from, strlen(from))) {
printf("found %s\n", seq->strip->dir);
/* strip off the beginning */
@@ -1019,7 +1047,7 @@ static int sequencer_gap_remove_exec(bContext *C, wmOperator *op)
break;
}
}
-
+
for ( ; cfra < efra; cfra++) {
/* first == 0 means there's still no strip to remove a gap for */
if (first == false) {
@@ -1129,7 +1157,7 @@ int sequencer_strip_has_path_poll(bContext *C)
return (((ed = BKE_sequencer_editing_get(CTX_data_scene(C), false)) != NULL) && ((seq = ed->act_seq) != NULL) && (SEQ_HAS_PATH(seq)));
}
-int sequencer_view_poll(bContext *C)
+int sequencer_view_preview_poll(bContext *C)
{
SpaceSeq *sseq = CTX_wm_space_seq(C);
Editing *ed = BKE_sequencer_editing_get(CTX_data_scene(C), false);
@@ -1139,6 +1167,15 @@ int sequencer_view_poll(bContext *C)
return 0;
}
+int sequencer_view_strips_poll(bContext *C)
+{
+ SpaceSeq *sseq = CTX_wm_space_seq(C);
+ if (sseq && ED_space_sequencer_check_show_strip(sseq))
+ return 1;
+
+ return 0;
+}
+
/* snap operator*/
static int sequencer_snap_exec(bContext *C, wmOperator *op)
{
@@ -1231,6 +1268,450 @@ void SEQUENCER_OT_snap(struct wmOperatorType *ot)
RNA_def_int(ot->srna, "frame", 0, INT_MIN, INT_MAX, "Frame", "Frame where selected strips will be snapped", INT_MIN, INT_MAX);
}
+typedef struct SlipData {
+ int init_mouse[2];
+ float init_mouseloc[2];
+ TransSeq *ts;
+ Sequence **seq_array;
+ bool *trim;
+ int num_seq;
+ bool slow;
+ int slow_offset; /* offset at the point where offset was turned on */
+ void *draw_handle;
+ NumInput num_input;
+} SlipData;
+
+static void transseq_backup(TransSeq *ts, Sequence *seq)
+{
+ ts->start = seq->start;
+ ts->machine = seq->machine;
+ ts->startstill = seq->startstill;
+ ts->endstill = seq->endstill;
+ ts->startdisp = seq->startdisp;
+ ts->enddisp = seq->enddisp;
+ ts->startofs = seq->startofs;
+ ts->endofs = seq->endofs;
+ ts->anim_startofs = seq->anim_startofs;
+ ts->anim_endofs = seq->anim_endofs;
+ ts->len = seq->len;
+}
+
+
+static void transseq_restore(TransSeq *ts, Sequence *seq)
+{
+ seq->start = ts->start;
+ seq->machine = ts->machine;
+ seq->startstill = ts->startstill;
+ seq->endstill = ts->endstill;
+ seq->startdisp = ts->startdisp;
+ seq->enddisp = ts->enddisp;
+ seq->startofs = ts->startofs;
+ seq->endofs = ts->endofs;
+ seq->anim_startofs = ts->anim_startofs;
+ seq->anim_endofs = ts->anim_endofs;
+ seq->len = ts->len;
+}
+
+static void draw_slip_extensions(const bContext *C, ARegion *ar, void *data)
+{
+ Scene *scene = CTX_data_scene(C);
+ SlipData *td = data;
+ int i;
+
+ for (i = 0; i < td->num_seq; i++) {
+ Sequence *seq = td->seq_array[i];
+
+ if ((seq->type != SEQ_TYPE_META) && td->trim[i]) {
+ draw_sequence_extensions(scene, ar, seq);
+ }
+ }
+}
+
+static int slip_add_sequences_rec(ListBase *seqbasep, Sequence **seq_array, bool *trim, int offset, bool do_trim)
+{
+ Sequence *seq;
+ int num_items = 0;
+
+ for (seq = seqbasep->first; seq; seq = seq->next) {
+ if (!do_trim || (!(seq->type & SEQ_TYPE_EFFECT) && (seq->flag & SELECT))) {
+ seq_array[offset + num_items] = seq;
+ trim[offset + num_items] = do_trim;
+ num_items++;
+
+ if (seq->type == SEQ_TYPE_META) {
+ /* trim the sub-sequences */
+ num_items += slip_add_sequences_rec(&seq->seqbase, seq_array, trim, num_items + offset, false);
+ }
+ else if (seq->type & SEQ_TYPE_EFFECT) {
+ trim[offset + num_items] = false;
+ }
+ }
+ }
+
+ return num_items;
+}
+
+static int slip_count_sequences_rec(ListBase *seqbasep, bool first_level)
+{
+ Sequence *seq;
+ int trimmed_sequences = 0;
+
+ for (seq = seqbasep->first; seq; seq = seq->next) {
+ if (!first_level || (!(seq->type & SEQ_TYPE_EFFECT) && (seq->flag & SELECT))) {
+ trimmed_sequences++;
+
+ if (seq->type == SEQ_TYPE_META) {
+ /* trim the sub-sequences */
+ trimmed_sequences += slip_count_sequences_rec(&seq->seqbase, false);
+ }
+ }
+ }
+
+ return trimmed_sequences;
+}
+
+static int sequencer_slip_invoke(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ SlipData *data;
+ Scene *scene = CTX_data_scene(C);
+ Editing *ed = BKE_sequencer_editing_get(scene, false);
+ ARegion *ar = CTX_wm_region(C);
+ float mouseloc[2];
+ int num_seq, i;
+ View2D *v2d = UI_view2d_fromcontext(C);
+
+ /* first recursively cound the trimmed elements */
+ num_seq = slip_count_sequences_rec(ed->seqbasep, true);
+
+ if (num_seq == 0)
+ return OPERATOR_CANCELLED;
+
+ data = op->customdata = MEM_mallocN(sizeof(SlipData), "trimdata");
+ data->ts = MEM_mallocN(num_seq * sizeof(TransSeq), "trimdata_transform");
+ data->seq_array = MEM_mallocN(num_seq * sizeof(Sequence *), "trimdata_sequences");
+ data->trim = MEM_mallocN(num_seq * sizeof(bool), "trimdata_trim");
+ data->num_seq = num_seq;
+
+ initNumInput(&data->num_input);
+ data->num_input.idx_max = 0;
+ data->num_input.val_flag[0] |= NUM_NO_FRACTION;
+ data->num_input.unit_sys = USER_UNIT_NONE;
+ data->num_input.unit_type[0] = 0;
+
+
+ slip_add_sequences_rec(ed->seqbasep, data->seq_array, data->trim, 0, true);
+
+ for (i = 0; i < num_seq; i++) {
+ transseq_backup(data->ts + i, data->seq_array[i]);
+ }
+
+ data->draw_handle = ED_region_draw_cb_activate(ar->type, draw_slip_extensions, data, REGION_DRAW_POST_VIEW);
+
+ UI_view2d_region_to_view(v2d, event->mval[0], event->mval[1], &mouseloc[0], &mouseloc[1]);
+
+ copy_v2_v2_int(data->init_mouse, event->mval);
+ copy_v2_v2(data->init_mouseloc, mouseloc);
+
+ data->slow = false;
+
+ WM_event_add_modal_handler(C, op);
+
+ /* notify so we draw extensions immediately */
+ WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
+
+ return OPERATOR_RUNNING_MODAL;
+}
+
+static bool sequencer_slip_recursively(Scene *scene, SlipData *data, int offset)
+{
+
+ /* only data types supported for now */
+ if (offset != 0) {
+ Editing *ed = BKE_sequencer_editing_get(scene, false);
+ int i;
+
+ /* we iterate in reverse so metastrips are iterated after their children */
+ for (i = data->num_seq - 1; i >= 0; i--) {
+ Sequence *seq = data->seq_array[i];
+ int endframe;
+ /* we have the offset, do the terrible math */
+
+ /* first, do the offset */
+ seq->start = data->ts[i].start + offset;
+
+ if (data->trim[i]) {
+ /* find the endframe */
+ endframe = seq->start + seq->len;
+
+ /* now compute the terrible offsets */
+ if (endframe > seq->enddisp) {
+ seq->endstill = 0;
+ seq->endofs = endframe - seq->enddisp;
+ }
+ else if (endframe <= seq->enddisp) {
+ seq->endstill = seq->enddisp - endframe;
+ seq->endofs = 0;
+ }
+
+ if (seq->start > seq->startdisp) {
+ seq->startstill = seq->start - seq->startdisp;
+ seq->startofs = 0;
+ }
+ else if (seq->start <= seq->startdisp) {
+ seq->startstill = 0;
+ seq->startofs = seq->startdisp - seq->start;
+ }
+ }
+ else {
+ /* if no real trim, don't change the data, rather transform the strips themselves */
+ seq->startdisp = data->ts[i].startdisp + offset;
+ seq->enddisp = data->ts[i].enddisp + offset;
+ }
+
+ /* effects are only added if we they are in a metastrip. In this case, dependent strips will just be transformed and we can skip calculating for effects
+ * This way we can avoid an extra loop just for effects*/
+ if (!(seq->type & SEQ_TYPE_EFFECT))
+ BKE_sequence_calc(scene, seq);
+ }
+ BKE_sequencer_free_imbuf(scene, &ed->seqbase, false);
+
+ return true;
+ }
+
+ return false;
+}
+
+static int sequencer_slip_exec(bContext *C, wmOperator *op)
+{
+ SlipData *data;
+ Scene *scene = CTX_data_scene(C);
+ Editing *ed = BKE_sequencer_editing_get(scene, false);
+ int num_seq, i;
+ int offset = RNA_int_get(op->ptr, "offset");
+ bool success = false;
+
+ /* first recursively cound the trimmed elements */
+ num_seq = slip_count_sequences_rec(ed->seqbasep, true);
+
+ if (num_seq == 0)
+ return OPERATOR_CANCELLED;
+
+ data = op->customdata = MEM_mallocN(sizeof(SlipData), "trimdata");
+ data->ts = MEM_mallocN(num_seq * sizeof(TransSeq), "trimdata_transform");
+ data->seq_array = MEM_mallocN(num_seq * sizeof(Sequence *), "trimdata_sequences");
+ data->trim = MEM_mallocN(num_seq * sizeof(bool), "trimdata_trim");
+ data->num_seq = num_seq;
+
+ slip_add_sequences_rec(ed->seqbasep, data->seq_array, data->trim, 0, true);
+
+ for (i = 0; i < num_seq; i++) {
+ transseq_backup(data->ts + i, data->seq_array[i]);
+ }
+
+ success = sequencer_slip_recursively(scene, data, offset);
+
+ MEM_freeN(data->seq_array);
+ MEM_freeN(data->trim);
+ MEM_freeN(data->ts);
+ MEM_freeN(data);
+
+ if (success) {
+ WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
+ return OPERATOR_FINISHED;
+ }
+ else {
+ return OPERATOR_CANCELLED;
+ }
+}
+
+
+static void sequencer_slip_update_header(Scene *scene, ScrArea *sa, SlipData *data, int offset)
+{
+#define HEADER_LENGTH 40
+ char msg[HEADER_LENGTH];
+
+ if (sa) {
+ if (hasNumInput(&data->num_input)) {
+ char num_str[NUM_STR_REP_LEN];
+ outputNumInput(&data->num_input, num_str, &scene->unit);
+ BLI_snprintf(msg, HEADER_LENGTH, "Trim offset: %s", num_str);
+ }
+ else {
+ BLI_snprintf(msg, HEADER_LENGTH, "Trim offset: %d", offset);
+ }
+ }
+
+ ED_area_headerprint(sa, msg);
+
+#undef HEADER_LENGTH
+}
+
+static int sequencer_slip_modal(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ Scene *scene = CTX_data_scene(C);
+ SlipData *data = (SlipData *)op->customdata;
+ ScrArea *sa = CTX_wm_area(C);
+ ARegion *ar = CTX_wm_region(C);
+ const bool has_numInput = hasNumInput(&data->num_input);
+ bool handled = true;
+
+ /* Modal numinput active, try to handle numeric inputs first... */
+ if (event->val == KM_PRESS && has_numInput && handleNumInput(C, &data->num_input, event)) {
+ float offset;
+ applyNumInput(&data->num_input, &offset);
+
+ sequencer_slip_update_header(scene, sa, data, (int)offset);
+
+ RNA_int_set(op->ptr, "offset", offset);
+
+ if (sequencer_slip_recursively(scene, data, offset)) {
+ WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
+ }
+
+ return OPERATOR_RUNNING_MODAL;
+ }
+
+ switch (event->type) {
+ case MOUSEMOVE:
+ {
+ if (!has_numInput) {
+ float mouseloc[2];
+ int offset;
+ int mouse_x;
+ View2D *v2d = UI_view2d_fromcontext(C);
+
+ if (data->slow) {
+ mouse_x = event->mval[0] - data->slow_offset;
+ mouse_x *= 0.1f;
+ mouse_x += data->slow_offset;
+ }
+ else {
+ mouse_x = event->mval[0];
+ }
+
+
+ /* choose the side based on which side of the playhead the mouse is on */
+ UI_view2d_region_to_view(v2d, mouse_x, 0, &mouseloc[0], &mouseloc[1]);
+ offset = mouseloc[0] - data->init_mouseloc[0];
+
+ sequencer_slip_update_header(scene, sa, data, offset);
+
+ RNA_int_set(op->ptr, "offset", offset);
+
+ if (sequencer_slip_recursively(scene, data, offset)) {
+ WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
+ }
+ }
+ break;
+ }
+
+ case LEFTMOUSE:
+ case RETKEY:
+ case SPACEKEY:
+ {
+ ED_region_draw_cb_exit(ar->type, data->draw_handle);
+ MEM_freeN(data->seq_array);
+ MEM_freeN(data->trim);
+ MEM_freeN(data->ts);
+ MEM_freeN(data);
+ op->customdata = NULL;
+ if (sa) {
+ ED_area_headerprint(sa, NULL);
+ }
+ WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
+ return OPERATOR_FINISHED;
+ }
+
+ case ESCKEY:
+ case RIGHTMOUSE:
+ {
+ int i;
+ Editing *ed = BKE_sequencer_editing_get(scene, false);
+
+ for (i = 0; i < data->num_seq; i++) {
+ transseq_restore(data->ts + i, data->seq_array[i]);
+ }
+
+ for (i = 0; i < data->num_seq; i++) {
+ Sequence *seq = data->seq_array[i];
+ BKE_sequence_reload_new_file(scene, seq, false);
+ BKE_sequence_calc(scene, seq);
+ }
+
+ ED_region_draw_cb_exit(ar->type, data->draw_handle);
+
+ MEM_freeN(data->seq_array);
+ MEM_freeN(data->ts);
+ MEM_freeN(data->trim);
+ MEM_freeN(data);
+ op->customdata = NULL;
+
+ WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
+
+ BKE_sequencer_free_imbuf(scene, &ed->seqbase, false);
+
+ if (sa) {
+ ED_area_headerprint(sa, NULL);
+ }
+
+ return OPERATOR_CANCELLED;
+ }
+
+ case RIGHTSHIFTKEY:
+ case LEFTSHIFTKEY:
+ if (!has_numInput) {
+ if (event->val == KM_PRESS) {
+ data->slow = true;
+ data->slow_offset = event->mval[0];
+ }
+ else if (event->val == KM_RELEASE) {
+ data->slow = false;
+ }
+ }
+ break;
+
+ default:
+ handled = false;
+ break;
+ }
+
+ /* Modal numinput inactive, try to handle numeric inputs last... */
+ if (!handled && event->val == KM_PRESS && handleNumInput(C, &data->num_input, event)) {
+ float offset;
+ applyNumInput(&data->num_input, &offset);
+
+ sequencer_slip_update_header(scene, sa, data, (int)offset);
+
+ RNA_int_set(op->ptr, "offset", offset);
+
+ if (sequencer_slip_recursively(scene, data, offset)) {
+ WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
+ }
+ }
+
+ return OPERATOR_RUNNING_MODAL;
+}
+
+void SEQUENCER_OT_slip(struct wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Trim Strips";
+ ot->idname = "SEQUENCER_OT_slip";
+ ot->description = "Trim the contents of the active strip";
+
+ /* api callbacks */
+ ot->invoke = sequencer_slip_invoke;
+ ot->modal = sequencer_slip_modal;
+ ot->exec = sequencer_slip_exec;
+ ot->poll = sequencer_edit_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ RNA_def_int(ot->srna, "offset", 0, INT32_MIN, INT32_MAX, "Offset", "Offset to the data of the strip",
+ INT32_MIN, INT32_MAX);
+}
+
/* mute operator */
static int sequencer_mute_exec(bContext *C, wmOperator *op)
{
@@ -1269,7 +1750,7 @@ void SEQUENCER_OT_mute(struct wmOperatorType *ot)
/* identifiers */
ot->name = "Mute Strips";
ot->idname = "SEQUENCER_OT_mute";
- ot->description = "Mute selected strips";
+ ot->description = "Mute (un)selected strips";
/* api callbacks */
ot->exec = sequencer_mute_exec;
@@ -1320,7 +1801,7 @@ void SEQUENCER_OT_unmute(struct wmOperatorType *ot)
/* identifiers */
ot->name = "Un-Mute Strips";
ot->idname = "SEQUENCER_OT_unmute";
- ot->description = "Un-Mute unselected rather than selected strips";
+ ot->description = "Unmute (un)selected strips";
/* api callbacks */
ot->exec = sequencer_unmute_exec;
@@ -1329,7 +1810,7 @@ void SEQUENCER_OT_unmute(struct wmOperatorType *ot)
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- RNA_def_boolean(ot->srna, "unselected", 0, "Unselected", "UnMute unselected rather than selected strips");
+ RNA_def_boolean(ot->srna, "unselected", 0, "Unselected", "Unmute unselected rather than selected strips");
}
@@ -1446,6 +1927,14 @@ void SEQUENCER_OT_reload(struct wmOperatorType *ot)
}
/* reload operator */
+static int sequencer_refresh_all_poll(bContext *C)
+{
+ if (G.is_rendering) {
+ return 0;
+ }
+ return sequencer_edit_poll(C);
+}
+
static int sequencer_refresh_all_exec(bContext *C, wmOperator *UNUSED(op))
{
Scene *scene = CTX_data_scene(C);
@@ -1467,7 +1956,7 @@ void SEQUENCER_OT_refresh_all(struct wmOperatorType *ot)
/* api callbacks */
ot->exec = sequencer_refresh_all_exec;
- ot->poll = sequencer_edit_poll;
+ ot->poll = sequencer_refresh_all_poll;
}
static int sequencer_reassign_inputs_exec(bContext *C, wmOperator *op)
@@ -1993,6 +2482,7 @@ static int sequencer_meta_toggle_exec(bContext *C, wmOperator *UNUSED(op))
BLI_addtail(&ed->metastack, ms);
ms->parseq = last_seq;
ms->oldbasep = ed->seqbasep;
+ copy_v2_v2_int(ms->disp_range, &ms->parseq->startdisp);
ed->seqbasep = &last_seq->seqbase;
@@ -2012,12 +2502,25 @@ static int sequencer_meta_toggle_exec(bContext *C, wmOperator *UNUSED(op))
ed->seqbasep = ms->oldbasep;
+ /* for old files, update from meta */
+ if (ms->disp_range[0] == ms->disp_range[1]) {
+ copy_v2_v2_int(ms->disp_range, &ms->parseq->startdisp);
+ }
+
/* recalc all: the meta can have effects connected to it */
for (seq = ed->seqbasep->first; seq; seq = seq->next)
BKE_sequence_calc(scene, seq);
+ /* 2.73+, keeping endpoings is important!
+ * moving them around means you can't usefully use metas in a complex edit */
+#if 1
+ BKE_sequence_tx_set_final_left(ms->parseq, ms->disp_range[0]);
+ BKE_sequence_tx_set_final_right(ms->parseq, ms->disp_range[1]);
+ BKE_sequence_calc(scene, ms->parseq);
+#else
if (BKE_sequence_test_overlap(ed->seqbasep, ms->parseq))
BKE_sequence_base_shuffle(ed->seqbasep, ms->parseq, scene);
+#endif
BKE_sequencer_active_set(scene, ms->parseq);
@@ -2059,8 +2562,8 @@ static int sequencer_meta_make_exec(bContext *C, wmOperator *op)
Sequence *seq, *seqm, *next, *last_seq = BKE_sequencer_active_get(scene);
int channel_max = 1;
- if (BKE_sequence_base_isolated_sel_check(ed->seqbasep, false) == false) {
- BKE_report(op->reports, RPT_ERROR, "Please select more than one or all related strips");
+ if (BKE_sequence_base_isolated_sel_check(ed->seqbasep) == false) {
+ BKE_report(op->reports, RPT_ERROR, "Please select all related strips");
return OPERATOR_CANCELLED;
}
@@ -2439,88 +2942,13 @@ void SEQUENCER_OT_view_selected(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER;
}
-
-static int find_next_prev_edit(Scene *scene, int cfra,
- const short side,
- const bool do_skip_mute, const bool do_center)
-{
- Editing *ed = BKE_sequencer_editing_get(scene, false);
- Sequence *seq, *best_seq = NULL, *frame_seq = NULL;
-
- int dist, best_dist;
- best_dist = MAXFRAME * 2;
-
- if (ed == NULL) return cfra;
-
- for (seq = ed->seqbasep->first; seq; seq = seq->next) {
- int seq_frame;
-
- if (do_skip_mute && (seq->flag & SEQ_MUTE)) {
- continue;
- }
-
- if (do_center) {
- seq_frame = (seq->startdisp + seq->enddisp) / 2;
- }
- else {
- seq_frame = seq->startdisp;
- }
-
- dist = MAXFRAME * 2;
-
- switch (side) {
- case SEQ_SIDE_LEFT:
- if (seq_frame < cfra) {
- dist = cfra - seq_frame;
- }
- break;
- case SEQ_SIDE_RIGHT:
- if (seq_frame > cfra) {
- dist = seq_frame - cfra;
- }
- else if (seq_frame == cfra) {
- frame_seq = seq;
- }
- break;
- }
-
- if (dist < best_dist) {
- best_dist = dist;
- best_seq = seq;
- }
- }
-
- /* if no sequence to the right is found and the
- * frame is on the start of the last sequence,
- * move to the end of the last sequence */
- if (frame_seq) {
- if (do_center) {
- cfra = (frame_seq->startdisp + frame_seq->enddisp) / 2;
- }
- else {
- cfra = frame_seq->enddisp;
- }
- }
-
- if (best_seq) {
- if (do_center) {
- cfra = (best_seq->startdisp + best_seq->enddisp) / 2;
- }
- else {
- cfra = best_seq->startdisp;
- }
- }
-
- return cfra;
-}
-
static bool strip_jump_internal(Scene *scene,
const short side,
const bool do_skip_mute, const bool do_center)
{
bool changed = false;
int cfra = CFRA;
- int nfra = find_next_prev_edit(scene, cfra, side, do_skip_mute, do_center);
+ int nfra = BKE_sequencer_find_next_prev_edit(scene, cfra, side, do_skip_mute, do_center, false);
if (nfra != cfra) {
CFRA = nfra;
@@ -2753,7 +3181,7 @@ static void seq_copy_del_sound(Scene *scene, Sequence *seq)
}
}
else if (seq->scene_sound) {
- sound_remove_scene_sound(scene, seq->scene_sound);
+ BKE_sound_remove_scene_sound(scene, seq->scene_sound);
seq->scene_sound = NULL;
}
}
@@ -2767,7 +3195,7 @@ static int sequencer_copy_exec(bContext *C, wmOperator *op)
BKE_sequencer_free_clipboard();
- if (BKE_sequence_base_isolated_sel_check(ed->seqbasep, true) == false) {
+ if (BKE_sequence_base_isolated_sel_check(ed->seqbasep) == false) {
BKE_report(op->reports, RPT_ERROR, "Please select all related strips");
return OPERATOR_CANCELLED;
}
@@ -2804,9 +3232,7 @@ static int sequencer_copy_exec(bContext *C, wmOperator *op)
}
/* duplicate pointers */
- for (seq = seqbase_clipboard.first; seq; seq = seq->next) {
- BKE_sequence_clipboard_pointers_store(seq);
- }
+ BKE_sequencer_base_clipboard_pointers_store(&seqbase_clipboard);
}
return OPERATOR_FINISHED;
@@ -2850,9 +3276,7 @@ static int sequencer_paste_exec(bContext *C, wmOperator *UNUSED(op))
}
}
- for (iseq = nseqbase.first; iseq; iseq = iseq->next) {
- BKE_sequence_clipboard_pointers_restore(iseq, bmain);
- }
+ BKE_sequencer_base_clipboard_pointers_restore(&nseqbase, bmain);
for (iseq = nseqbase.first; iseq; iseq = iseq->next) {
BKE_sequence_sound_init(scene, iseq);
@@ -2914,10 +3338,10 @@ static int sequencer_swap_data_exec(bContext *C, wmOperator *op)
}
if (seq_act->scene_sound)
- sound_remove_scene_sound(scene, seq_act->scene_sound);
+ BKE_sound_remove_scene_sound(scene, seq_act->scene_sound);
if (seq_other->scene_sound)
- sound_remove_scene_sound(scene, seq_other->scene_sound);
+ BKE_sound_remove_scene_sound(scene, seq_other->scene_sound);
seq_act->scene_sound = NULL;
seq_other->scene_sound = NULL;
@@ -2925,8 +3349,8 @@ static int sequencer_swap_data_exec(bContext *C, wmOperator *op)
BKE_sequence_calc(scene, seq_act);
BKE_sequence_calc(scene, seq_other);
- if (seq_act->sound) sound_add_scene_sound_defaults(scene, seq_act);
- if (seq_other->sound) sound_add_scene_sound_defaults(scene, seq_other);
+ if (seq_act->sound) BKE_sound_add_scene_sound_defaults(scene, seq_act);
+ if (seq_other->sound) BKE_sound_add_scene_sound_defaults(scene, seq_other);
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
@@ -2997,7 +3421,7 @@ void SEQUENCER_OT_view_ghost_border(wmOperatorType *ot)
ot->invoke = WM_border_select_invoke;
ot->exec = view_ghost_border_exec;
ot->modal = WM_border_select_modal;
- ot->poll = sequencer_view_poll;
+ ot->poll = sequencer_view_preview_poll;
ot->cancel = WM_border_select_cancel;
/* flags */
@@ -3008,13 +3432,54 @@ void SEQUENCER_OT_view_ghost_border(wmOperatorType *ot)
}
/* rebuild_proxy operator */
-static int sequencer_rebuild_proxy_exec(bContext *C, wmOperator *UNUSED(op))
+
+static int sequencer_rebuild_proxy_invoke(bContext *C, wmOperator *UNUSED(op),
+ const wmEvent *UNUSED(event))
{
seq_proxy_build_job(C);
return OPERATOR_FINISHED;
}
+static int sequencer_rebuild_proxy_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+ Editing *ed = BKE_sequencer_editing_get(scene, false);
+ Sequence *seq;
+ GSet *file_list;
+
+ if (ed == NULL) {
+ return OPERATOR_CANCELLED;
+ }
+
+ file_list = BLI_gset_new(BLI_ghashutil_strhash_p, BLI_ghashutil_strcmp, "file list");
+
+ SEQP_BEGIN(ed, seq)
+ {
+ if ((seq->flag & SELECT)) {
+ ListBase queue = {NULL, NULL};
+ LinkData *link;
+ short stop = 0, do_update;
+ float progress;
+
+ BKE_sequencer_proxy_rebuild_context(bmain, scene, seq, file_list, &queue);
+
+ for (link = queue.first; link; link = link->next) {
+ struct SeqIndexBuildContext *context = link->data;
+ BKE_sequencer_proxy_rebuild(context, &stop, &do_update, &progress);
+ BKE_sequencer_proxy_rebuild_finish(context, 0);
+ }
+ BKE_sequencer_free_imbuf(scene, &ed->seqbase, false);
+ }
+ }
+ SEQ_END
+
+ BLI_gset_free(file_list, MEM_freeN);
+
+ return OPERATOR_FINISHED;
+}
+
void SEQUENCER_OT_rebuild_proxy(wmOperatorType *ot)
{
/* identifiers */
@@ -3023,13 +3488,98 @@ void SEQUENCER_OT_rebuild_proxy(wmOperatorType *ot)
ot->description = "Rebuild all selected proxies and timecode indices using the job system";
/* api callbacks */
+ ot->invoke = sequencer_rebuild_proxy_invoke;
ot->exec = sequencer_rebuild_proxy_exec;
- ot->poll = ED_operator_sequencer_active;
/* flags */
ot->flag = OPTYPE_REGISTER;
}
+static int sequencer_enable_proxies_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
+{
+ return WM_operator_props_dialog_popup(C, op, 10 * UI_UNIT_X, 5 * UI_UNIT_Y);
+}
+
+static int sequencer_enable_proxies_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene = CTX_data_scene(C);
+ Editing *ed = BKE_sequencer_editing_get(scene, false);
+ Sequence *seq;
+ bool proxy_25 = RNA_boolean_get(op->ptr, "proxy_25");
+ bool proxy_50 = RNA_boolean_get(op->ptr, "proxy_50");
+ bool proxy_75 = RNA_boolean_get(op->ptr, "proxy_75");
+ bool proxy_100 = RNA_boolean_get(op->ptr, "proxy_100");
+ bool override = RNA_boolean_get(op->ptr, "override");
+ bool turnon = true;
+
+ if (ed == NULL || !(proxy_25 || proxy_50 || proxy_75 || proxy_100)) {
+ turnon = false;
+ }
+
+ SEQP_BEGIN(ed, seq)
+ {
+ if ((seq->flag & SELECT)) {
+ if (ELEM(seq->type, SEQ_TYPE_MOVIE, SEQ_TYPE_IMAGE, SEQ_TYPE_META, SEQ_TYPE_SCENE, SEQ_TYPE_MULTICAM)) {
+ BKE_sequencer_proxy_set(seq, turnon);
+ if (seq->strip->proxy == NULL) {
+ continue;
+ }
+
+ if (proxy_25)
+ seq->strip->proxy->build_size_flags |= SEQ_PROXY_IMAGE_SIZE_25;
+ else
+ seq->strip->proxy->build_size_flags &= ~SEQ_PROXY_IMAGE_SIZE_25;
+
+ if (proxy_50)
+ seq->strip->proxy->build_size_flags |= SEQ_PROXY_IMAGE_SIZE_50;
+ else
+ seq->strip->proxy->build_size_flags &= ~SEQ_PROXY_IMAGE_SIZE_50;
+
+ if (proxy_75)
+ seq->strip->proxy->build_size_flags |= SEQ_PROXY_IMAGE_SIZE_75;
+ else
+ seq->strip->proxy->build_size_flags &= ~SEQ_PROXY_IMAGE_SIZE_75;
+
+ if (proxy_100)
+ seq->strip->proxy->build_size_flags |= SEQ_PROXY_IMAGE_SIZE_100;
+ else
+ seq->strip->proxy->build_size_flags &= ~SEQ_PROXY_IMAGE_SIZE_100;
+
+ if (!override)
+ seq->strip->proxy->build_flags |= SEQ_PROXY_SKIP_EXISTING;
+ else
+ seq->strip->proxy->build_flags &= ~SEQ_PROXY_SKIP_EXISTING;
+ }
+ }
+ }
+ SEQ_END
+
+ WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
+
+ return OPERATOR_FINISHED;
+}
+
+void SEQUENCER_OT_enable_proxies(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Set Selected Strip Proxies";
+ ot->idname = "SEQUENCER_OT_enable_proxies";
+ ot->description = "Enable selected proxies on all selected Movie strips";
+
+ /* api callbacks */
+ ot->invoke = sequencer_enable_proxies_invoke;
+ ot->exec = sequencer_enable_proxies_exec;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER;
+
+ RNA_def_boolean(ot->srna, "proxy_25", false, "25%", "");
+ RNA_def_boolean(ot->srna, "proxy_50", false, "50%", "");
+ RNA_def_boolean(ot->srna, "proxy_75", false, "75%", "");
+ RNA_def_boolean(ot->srna, "proxy_100", false, "100%", "");
+ RNA_def_boolean(ot->srna, "override", false, "Override", "");
+}
+
/* change ops */
static EnumPropertyItem prop_change_effect_input_types[] = {
@@ -3164,12 +3714,21 @@ static int sequencer_change_path_exec(bContext *C, wmOperator *op)
Editing *ed = BKE_sequencer_editing_get(scene, false);
Sequence *seq = BKE_sequencer_active_get(scene);
const bool is_relative_path = RNA_boolean_get(op->ptr, "relative_path");
+ const bool use_placeholders = RNA_boolean_get(op->ptr, "use_placeholders");
+ int minframe, numdigits;
if (seq->type == SEQ_TYPE_IMAGE) {
char directory[FILE_MAX];
- const int len = RNA_property_collection_length(op->ptr, RNA_struct_find_property(op->ptr, "files"));
+ int len;
StripElem *se;
+ /* need to find min/max frame for placeholders */
+ if (use_placeholders) {
+ len = sequencer_image_seq_get_minmax_frame(op, seq->sfra, &minframe, &numdigits);
+ }
+ else {
+ len = RNA_property_collection_length(op->ptr, RNA_struct_find_property(op->ptr, "files"));
+ }
if (len == 0)
return OPERATOR_CANCELLED;
@@ -3187,14 +3746,19 @@ static int sequencer_change_path_exec(bContext *C, wmOperator *op)
}
seq->strip->stripdata = se = MEM_callocN(len * sizeof(StripElem), "stripelem");
- RNA_BEGIN (op->ptr, itemptr, "files")
- {
- char *filename = RNA_string_get_alloc(&itemptr, "name", NULL, 0);
- BLI_strncpy(se->name, filename, sizeof(se->name));
- MEM_freeN(filename);
- se++;
+ if (use_placeholders) {
+ sequencer_image_seq_reserve_frames(op, se, len, minframe, numdigits);
+ }
+ else {
+ RNA_BEGIN (op->ptr, itemptr, "files")
+ {
+ char *filename = RNA_string_get_alloc(&itemptr, "name", NULL, 0);
+ BLI_strncpy(se->name, filename, sizeof(se->name));
+ MEM_freeN(filename);
+ se++;
+ }
+ RNA_END;
}
- RNA_END;
/* reset these else we wont see all the images */
seq->anim_startofs = seq->anim_endofs = 0;
@@ -3266,8 +3830,117 @@ void SEQUENCER_OT_change_path(struct wmOperatorType *ot)
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- WM_operator_properties_filesel(ot, FOLDERFILE | IMAGEFILE | MOVIEFILE, FILE_SPECIAL, FILE_OPENFILE,
+ WM_operator_properties_filesel(ot, FILE_TYPE_FOLDER | FILE_TYPE_IMAGE | FILE_TYPE_MOVIE, FILE_SPECIAL, FILE_OPENFILE,
WM_FILESEL_DIRECTORY | WM_FILESEL_RELPATH | WM_FILESEL_FILEPATH | WM_FILESEL_FILES,
- FILE_DEFAULTDISPLAY);
+ FILE_DEFAULTDISPLAY, FILE_SORT_ALPHA);
+ RNA_def_boolean(ot->srna, "use_placeholders", false, "Use Placeholders", "Use placeholders for missing frames of the strip");
}
+static int sequencer_export_subtitles_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
+{
+ if (!RNA_struct_property_is_set(op->ptr, "filepath")) {
+ char filepath[FILE_MAX];
+
+ if (G.main->name[0] == 0)
+ BLI_strncpy(filepath, "untitled", sizeof(filepath));
+ else
+ BLI_strncpy(filepath, G.main->name, sizeof(filepath));
+
+ BLI_replace_extension(filepath, sizeof(filepath), ".srt");
+ RNA_string_set(op->ptr, "filepath", filepath);
+ }
+
+ WM_event_add_fileselect(C, op);
+
+ return OPERATOR_RUNNING_MODAL;
+}
+
+static int sequencer_export_subtitles_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene = CTX_data_scene(C);
+ Sequence *seq = BKE_sequencer_active_get(scene);
+ Editing *ed = BKE_sequencer_editing_get(scene, false);
+ int iter = 0;
+ FILE *file;
+ char filepath[FILE_MAX];
+
+ if (!RNA_struct_property_is_set(op->ptr, "filepath")) {
+ BKE_report(op->reports, RPT_ERROR, "No filename given");
+ return OPERATOR_CANCELLED;
+ }
+
+ RNA_string_get(op->ptr, "filepath", filepath);
+ BLI_ensure_extension(filepath, sizeof(filepath), ".srt");
+
+ /* Avoid File write exceptions */
+ if (!BLI_exists(filepath)) {
+ BLI_make_existing_file(filepath);
+ if (!BLI_file_touch(filepath)) {
+ BKE_report(op->reports, RPT_ERROR, "Can't create subtitle file");
+ return OPERATOR_CANCELLED;
+ }
+ }
+ else if (!BLI_file_is_writable(filepath)) {
+ BKE_report(op->reports, RPT_ERROR, "Can't overwrite export file");
+ return OPERATOR_CANCELLED;
+ }
+
+ /* time to open and write! */
+ file = BLI_fopen(filepath, "w");
+
+ SEQ_BEGIN(ed, seq)
+ {
+ if (seq->type == SEQ_TYPE_TEXT) {
+ TextVars *data = seq->effectdata;
+ char timecode_str[32];
+ double sec;
+ int frac;
+ int len;
+ fprintf(file, "%d\n", iter++);
+ sec = FRA2TIME(seq->startdisp);
+ frac = 1000 * (sec - floor(sec));
+ sec = floor(sec);
+ BLI_timecode_string_from_time(timecode_str, sizeof(timecode_str), 1, sec, FPS, USER_TIMECODE_SMPTE_FULL);
+ len = strlen(timecode_str);
+ timecode_str[len - 3] = 0;
+ fprintf(file, "%s,%d", timecode_str, frac);
+ sec = FRA2TIME(seq->enddisp);
+ BLI_timecode_string_from_time(timecode_str, sizeof(timecode_str), 1, sec, FPS, USER_TIMECODE_SMPTE_FULL);
+ len = strlen(timecode_str);
+ timecode_str[len - 3] = 0;
+ fprintf(file, " --> %s,%d\n", timecode_str, frac);
+ fprintf(file, "%s\n\n", data->text);
+ }
+ }
+ SEQ_END
+
+ fclose(file);
+
+ return OPERATOR_FINISHED;
+}
+
+static int sequencer_strip_is_text_poll(bContext *C)
+{
+ Editing *ed;
+ Sequence *seq;
+ return (((ed = BKE_sequencer_editing_get(CTX_data_scene(C), false)) != NULL) && ((seq = ed->act_seq) != NULL) && (seq->type == SEQ_TYPE_TEXT));
+}
+
+void SEQUENCER_OT_export_subtitles(struct wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Export Subtitles";
+ ot->idname = "SEQUENCER_OT_export_subtitles";
+ ot->description = "Export .srt file containing text strips";
+
+ /* api callbacks */
+ ot->exec = sequencer_export_subtitles_exec;
+ ot->invoke = sequencer_export_subtitles_invoke;
+ ot->poll = sequencer_strip_is_text_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ WM_operator_properties_filesel(ot, FILE_TYPE_FOLDER, FILE_BLENDER, FILE_SAVE,
+ WM_FILESEL_FILEPATH, FILE_DEFAULTDISPLAY, FILE_SORT_ALPHA);
+}
diff --git a/source/blender/editors/space_sequencer/sequencer_intern.h b/source/blender/editors/space_sequencer/sequencer_intern.h
index df266b0f546..3e228fd0b31 100644
--- a/source/blender/editors/space_sequencer/sequencer_intern.h
+++ b/source/blender/editors/space_sequencer/sequencer_intern.h
@@ -45,6 +45,8 @@ struct ARegion;
struct ARegionType;
struct Scene;
struct Main;
+struct wmOperator;
+struct StripElem;
/* space_sequencer.c */
struct ARegion *sequencer_has_buttons_region(struct ScrArea *sa);
@@ -52,12 +54,17 @@ struct ARegion *sequencer_has_buttons_region(struct ScrArea *sa);
/* sequencer_draw.c */
void draw_timeline_seq(const struct bContext *C, struct ARegion *ar);
-void draw_image_seq(const struct bContext *C, struct Scene *scene, struct ARegion *ar, struct SpaceSeq *sseq, int cfra, int offset, bool draw_overlay);
+void draw_image_seq(const struct bContext *C, struct Scene *scene, struct ARegion *ar, struct SpaceSeq *sseq, int cfra, int offset, bool draw_overlay, bool draw_backdrop);
+void color3ubv_from_seq(struct Scene *curscene, struct Sequence *seq, unsigned char col[3]);
+void draw_shadedstrip(struct Sequence *seq, unsigned char col[3], float x1, float y1, float x2, float y2);
+void draw_sequence_extensions(struct Scene *scene, struct ARegion *ar, struct Sequence *seq);
+
+void sequencer_special_update_set(Sequence *seq);
/* UNUSED */
// void seq_reset_imageofs(struct SpaceSeq *sseq);
-struct ImBuf *sequencer_ibuf_get(struct Main *bmain, struct Scene *scene, struct SpaceSeq *sseq, int cfra, int frame_ofs);
+struct ImBuf *sequencer_ibuf_get(struct Main *bmain, struct Scene *scene, struct SpaceSeq *sseq, int cfra, int frame_ofs, const char *viewname);
/* sequencer_edit.c */
struct View2D;
@@ -73,7 +80,8 @@ int sequencer_edit_poll(struct bContext *C);
/* UNUSED */
//int sequencer_strip_poll(struct bContext *C);
int sequencer_strip_has_path_poll(struct bContext *C);
-int sequencer_view_poll(struct bContext *C);
+int sequencer_view_preview_poll(struct bContext *C);
+int sequencer_view_strips_poll(struct bContext *C);
/* externs */
extern EnumPropertyItem sequencer_prop_effect_types[];
@@ -84,6 +92,7 @@ struct wmOperatorType;
struct wmKeyConfig;
void SEQUENCER_OT_cut(struct wmOperatorType *ot);
+void SEQUENCER_OT_slip(struct wmOperatorType *ot);
void SEQUENCER_OT_mute(struct wmOperatorType *ot);
void SEQUENCER_OT_unmute(struct wmOperatorType *ot);
void SEQUENCER_OT_lock(struct wmOperatorType *ot);
@@ -123,6 +132,9 @@ void SEQUENCER_OT_copy(struct wmOperatorType *ot);
void SEQUENCER_OT_paste(struct wmOperatorType *ot);
void SEQUENCER_OT_rebuild_proxy(struct wmOperatorType *ot);
+void SEQUENCER_OT_enable_proxies(struct wmOperatorType *ot);
+
+void SEQUENCER_OT_export_subtitles(struct wmOperatorType *ot);
/* preview specific operators */
void SEQUENCER_OT_view_all_preview(struct wmOperatorType *ot);
@@ -149,13 +161,6 @@ void SEQUENCER_OT_sound_strip_add(struct wmOperatorType *ot);
void SEQUENCER_OT_image_strip_add(struct wmOperatorType *ot);
void SEQUENCER_OT_effect_strip_add(struct wmOperatorType *ot);
-/* RNA enums, just to be more readable */
-enum {
- SEQ_SIDE_NONE = 0,
- SEQ_SIDE_LEFT,
- SEQ_SIDE_RIGHT,
- SEQ_SIDE_BOTH
-};
enum {
SEQ_CUT_SOFT,
SEQ_CUT_HARD
@@ -194,9 +199,17 @@ void SEQUENCER_OT_properties(struct wmOperatorType *ot);
void SEQUENCER_OT_strip_modifier_add(struct wmOperatorType *ot);
void SEQUENCER_OT_strip_modifier_remove(struct wmOperatorType *ot);
void SEQUENCER_OT_strip_modifier_move(struct wmOperatorType *ot);
+void SEQUENCER_OT_strip_modifier_copy(struct wmOperatorType *ot);
/* sequencer_view.c */
void SEQUENCER_OT_sample(struct wmOperatorType *ot);
+/* sequencer_preview.c */
+void sequencer_preview_add_sound(const struct bContext *C, struct Sequence *seq);
+
+/* sequencer_add */
+int sequencer_image_seq_get_minmax_frame(struct wmOperator *op, int sfra, int *r_minframe, int *r_numdigits);
+void sequencer_image_seq_reserve_frames(struct wmOperator *op, struct StripElem *se, int len, int minframe, int numdigits);
+
#endif /* __SEQUENCER_INTERN_H__ */
diff --git a/source/blender/editors/space_sequencer/sequencer_modifier.c b/source/blender/editors/space_sequencer/sequencer_modifier.c
index ff40bf1e638..fad317fdd4e 100644
--- a/source/blender/editors/space_sequencer/sequencer_modifier.c
+++ b/source/blender/editors/space_sequencer/sequencer_modifier.c
@@ -29,24 +29,14 @@
* \ingroup spseq
*/
-#include "MEM_guardedalloc.h"
#include "BLI_blenlib.h"
-#include "BLI_math.h"
#include "BLI_utildefines.h"
#include "DNA_scene_types.h"
-#include "DNA_mask_types.h"
-#include "DNA_userdef_types.h"
#include "BKE_context.h"
-#include "BKE_global.h"
-#include "BKE_library.h"
-#include "BKE_main.h"
#include "BKE_sequencer.h"
-#include "BKE_movieclip.h"
-#include "BKE_mask.h"
-#include "BKE_report.h"
#include "WM_api.h"
#include "WM_types.h"
@@ -54,8 +44,6 @@
#include "RNA_define.h"
#include "RNA_enum_types.h"
-#include "UI_interface.h"
-#include "UI_resources.h"
/* own include */
#include "sequencer_intern.h"
@@ -219,3 +207,58 @@ void SEQUENCER_OT_strip_modifier_move(wmOperatorType *ot)
RNA_def_string(ot->srna, "name", "Name", MAX_NAME, "Name", "Name of modifier to remove");
RNA_def_enum(ot->srna, "direction", direction_items, SEQ_MODIFIER_MOVE_UP, "Type", "");
}
+
+static int strip_modifier_copy_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ Scene *scene = CTX_data_scene(C);
+ Editing *ed = scene->ed;
+ Sequence *seq = BKE_sequencer_active_get(scene);
+ Sequence *seq_iter;
+
+ if (!seq || !seq->modifiers.first)
+ return OPERATOR_CANCELLED;
+
+ SEQP_BEGIN(ed, seq_iter)
+ {
+ if (seq_iter->flag & SELECT) {
+ if (seq_iter == seq)
+ continue;
+
+ if (seq_iter->modifiers.first) {
+ SequenceModifierData *smd_tmp, *smd = seq_iter->modifiers.first;
+
+ while (smd) {
+ smd_tmp = smd->next;
+ BLI_remlink(&seq_iter->modifiers, smd);
+ BKE_sequence_modifier_free(smd);
+ smd = smd_tmp;
+ }
+ BLI_listbase_clear(&seq_iter->modifiers);
+ }
+
+ BKE_sequence_modifier_list_copy(seq_iter, seq);
+ }
+ }
+ SEQ_END
+
+ BKE_sequence_invalidate_cache(scene, seq);
+ WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
+
+ return OPERATOR_FINISHED;
+}
+
+void SEQUENCER_OT_strip_modifier_copy(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Copy to Selected Strips";
+ ot->idname = "SEQUENCER_OT_strip_modifier_copy";
+ ot->description = "Copy modifiers of the active strip to all selected strips";
+
+ /* api callbacks */
+ ot->exec = strip_modifier_copy_exec;
+ ot->poll = strip_modifier_active_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
diff --git a/source/blender/editors/space_sequencer/sequencer_ops.c b/source/blender/editors/space_sequencer/sequencer_ops.c
index c5e47c3aa3e..3d08e0c5ed8 100644
--- a/source/blender/editors/space_sequencer/sequencer_ops.c
+++ b/source/blender/editors/space_sequencer/sequencer_ops.c
@@ -40,6 +40,8 @@
#include "ED_markers.h"
#include "ED_transform.h" /* transform keymap */
+#include "BKE_sequencer.h"
+
#include "sequencer_intern.h"
@@ -50,6 +52,7 @@ void sequencer_operatortypes(void)
{
/* sequencer_edit.c */
WM_operatortype_append(SEQUENCER_OT_cut);
+ WM_operatortype_append(SEQUENCER_OT_slip);
WM_operatortype_append(SEQUENCER_OT_mute);
WM_operatortype_append(SEQUENCER_OT_unmute);
WM_operatortype_append(SEQUENCER_OT_lock);
@@ -74,6 +77,8 @@ void sequencer_operatortypes(void)
WM_operatortype_append(SEQUENCER_OT_swap_data);
WM_operatortype_append(SEQUENCER_OT_rendersize);
+ WM_operatortype_append(SEQUENCER_OT_export_subtitles);
+
WM_operatortype_append(SEQUENCER_OT_copy);
WM_operatortype_append(SEQUENCER_OT_paste);
@@ -85,6 +90,7 @@ void sequencer_operatortypes(void)
WM_operatortype_append(SEQUENCER_OT_view_ghost_border);
WM_operatortype_append(SEQUENCER_OT_rebuild_proxy);
+ WM_operatortype_append(SEQUENCER_OT_enable_proxies);
WM_operatortype_append(SEQUENCER_OT_change_effect_input);
WM_operatortype_append(SEQUENCER_OT_change_effect_type);
WM_operatortype_append(SEQUENCER_OT_change_path);
@@ -117,6 +123,7 @@ void sequencer_operatortypes(void)
WM_operatortype_append(SEQUENCER_OT_strip_modifier_add);
WM_operatortype_append(SEQUENCER_OT_strip_modifier_remove);
WM_operatortype_append(SEQUENCER_OT_strip_modifier_move);
+ WM_operatortype_append(SEQUENCER_OT_strip_modifier_copy);
/* sequencer_view.h */
WM_operatortype_append(SEQUENCER_OT_sample);
@@ -316,6 +323,8 @@ void sequencer_keymap(wmKeyConfig *keyconf)
WM_keymap_add_menu(keymap, "SEQUENCER_MT_change", CKEY, KM_PRESS, 0, 0);
+ WM_keymap_add_item(keymap, "SEQUENCER_OT_slip", SKEY, KM_PRESS, 0, 0);
+
kmi = WM_keymap_add_item(keymap, "WM_OT_context_set_int", OKEY, KM_PRESS, 0, 0);
RNA_string_set(kmi->ptr, "data_path", "scene.sequence_editor.overlay_frame");
RNA_int_set(kmi->ptr, "value", 0);
@@ -359,5 +368,5 @@ void ED_operatormacros_sequencer(void)
"Duplicate selected strips and move them", OPTYPE_UNDO | OPTYPE_REGISTER);
WM_operatortype_macro_define(ot, "SEQUENCER_OT_duplicate");
- WM_operatortype_macro_define(ot, "TRANSFORM_OT_translate");
+ WM_operatortype_macro_define(ot, "TRANSFORM_OT_seq_slide");
}
diff --git a/source/blender/editors/space_sequencer/sequencer_preview.c b/source/blender/editors/space_sequencer/sequencer_preview.c
new file mode 100644
index 00000000000..3f908dc7096
--- /dev/null
+++ b/source/blender/editors/space_sequencer/sequencer_preview.c
@@ -0,0 +1,172 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * Contributor(s): Blender Foundation, 2003-2009, Antony Riakiotakis
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/editors/space_sequencer/sequencer_preview.c
+ * \ingroup spseq
+ */
+
+#include "DNA_sequence_types.h"
+#include "DNA_sound_types.h"
+
+#include "BLI_listbase.h"
+#include "BLI_threads.h"
+
+#include "BKE_sound.h"
+#include "BKE_context.h"
+#include "BKE_global.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "ED_screen.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "sequencer_intern.h"
+
+typedef struct PreviewJob {
+ ListBase previews;
+ ThreadMutex *mutex;
+ Scene *scene;
+ int total;
+ int processed;
+} PreviewJob;
+
+typedef struct PreviewJobAudio {
+ struct PreviewJobAudio *next, *prev;
+ bSound *sound;
+ int lr; /* sample left or right */
+ int startframe;
+ bool waveform; /* reload sound or waveform */
+} PreviewJobAudio;
+
+static void free_preview_job(void *data)
+{
+ PreviewJob *pj = (PreviewJob *)data;
+
+ BLI_mutex_free(pj->mutex);
+ BLI_freelistN(&pj->previews);
+ MEM_freeN(pj);
+}
+
+/* only this runs inside thread */
+static void preview_startjob(void *data, short *stop, short *do_update, float *progress)
+{
+ PreviewJob *pj = data;
+ PreviewJobAudio *previewjb;
+
+ BLI_mutex_lock(pj->mutex);
+ previewjb = pj->previews.first;
+ BLI_mutex_unlock(pj->mutex);
+
+ while (previewjb) {
+ PreviewJobAudio *preview_next;
+ bSound *sound = previewjb->sound;
+
+ BKE_sound_read_waveform(sound, stop);
+
+ if (*stop || G.is_break) {
+ BLI_mutex_lock(pj->mutex);
+ previewjb = previewjb->next;
+ BLI_mutex_unlock(pj->mutex);
+ while (previewjb) {
+ sound = previewjb->sound;
+
+ /* make sure we cleanup the loading flag! */
+ BLI_spin_lock(sound->spinlock);
+ sound->flags &= ~SOUND_FLAGS_WAVEFORM_LOADING;
+ BLI_spin_unlock(sound->spinlock);
+
+ BLI_mutex_lock(pj->mutex);
+ previewjb = previewjb->next;
+ BLI_mutex_unlock(pj->mutex);
+ }
+
+ BLI_mutex_lock(pj->mutex);
+ BLI_freelistN(&pj->previews);
+ pj->total = 0;
+ pj->processed = 0;
+ BLI_mutex_unlock(pj->mutex);
+ break;
+ }
+
+ BLI_mutex_lock(pj->mutex);
+ preview_next = previewjb->next;
+ BLI_freelinkN(&pj->previews, previewjb);
+ previewjb = preview_next;
+ pj->processed++;
+ *progress = (pj->total > 0) ? (float)pj->processed / (float)pj->total : 1.0f;
+ *do_update = true;
+ BLI_mutex_unlock(pj->mutex);
+ }
+}
+
+static void preview_endjob(void *data)
+{
+ PreviewJob *pj = data;
+
+ WM_main_add_notifier(NC_SCENE | ND_SEQUENCER, pj->scene);
+}
+
+
+void sequencer_preview_add_sound(const bContext *C, Sequence *seq)
+{
+ /* first, get the preview job, if it exists */
+ wmJob *wm_job;
+ PreviewJob *pj;
+ ScrArea *sa = CTX_wm_area(C);
+ PreviewJobAudio *audiojob = MEM_callocN(sizeof(PreviewJobAudio), "preview_audio");
+ wm_job = WM_jobs_get(CTX_wm_manager(C), CTX_wm_window(C), sa, "Strip Previews",
+ WM_JOB_PROGRESS, WM_JOB_TYPE_SEQ_BUILD_PREVIEW);
+
+ pj = WM_jobs_customdata_get(wm_job);
+
+ if (!pj) {
+ pj = MEM_callocN(sizeof(PreviewJob), "preview rebuild job");
+
+ pj->mutex = BLI_mutex_alloc();
+ pj->scene = CTX_data_scene(C);
+
+ WM_jobs_customdata_set(wm_job, pj, free_preview_job);
+ WM_jobs_timer(wm_job, 0.1, NC_SCENE | ND_SEQUENCER, NC_SCENE | ND_SEQUENCER);
+ WM_jobs_callbacks(wm_job, preview_startjob, NULL, NULL, preview_endjob);
+ }
+
+ /* attempt to lock mutex of job here */
+
+ audiojob->sound = seq->sound;
+
+ BLI_mutex_lock(pj->mutex);
+ BLI_addtail(&pj->previews, audiojob);
+ pj->total++;
+ BLI_mutex_unlock(pj->mutex);
+
+ if (!WM_jobs_is_running(wm_job)) {
+ G.is_break = false;
+ WM_jobs_start(CTX_wm_manager(C), wm_job);
+ }
+
+ ED_area_tag_redraw(sa);
+}
diff --git a/source/blender/editors/space_sequencer/sequencer_scopes.c b/source/blender/editors/space_sequencer/sequencer_scopes.c
index 9b3b9f23036..c197aabedfd 100644
--- a/source/blender/editors/space_sequencer/sequencer_scopes.c
+++ b/source/blender/editors/space_sequencer/sequencer_scopes.c
@@ -29,9 +29,9 @@
#include <math.h>
#include <string.h>
-#include "BLI_math_color.h"
#include "BLI_utildefines.h"
+#include "IMB_colormanagement.h"
#include "IMB_imbuf_types.h"
#include "IMB_imbuf.h"
@@ -55,7 +55,7 @@ static void rgb_to_yuv_normalized(const float rgb[3], float yuv[3])
static void scope_put_pixel(unsigned char *table, unsigned char *pos)
{
- char newval = table[*pos];
+ unsigned char newval = table[*pos];
pos[0] = pos[1] = pos[2] = newval;
pos[3] = 255;
}
@@ -148,8 +148,8 @@ static ImBuf *make_waveform_view_from_ibuf_byte(ImBuf *ibuf)
{
ImBuf *rval = IMB_allocImBuf(ibuf->x + 3, 515, 32, IB_rect);
int x, y;
- unsigned char *src = (unsigned char *) ibuf->rect;
- unsigned char *tgt = (unsigned char *) rval->rect;
+ const unsigned char *src = (unsigned char *)ibuf->rect;
+ unsigned char *tgt = (unsigned char *)rval->rect;
int w = ibuf->x + 3;
int h = 515;
float waveform_gamma = 0.2;
@@ -166,8 +166,8 @@ static ImBuf *make_waveform_view_from_ibuf_byte(ImBuf *ibuf)
unsigned char *last_p = NULL;
for (x = 0; x < ibuf->x; x++) {
- unsigned char *rgb = src + 4 * (ibuf->x * y + x);
- float v = (float)rgb_to_luma_byte(rgb) / 255.0f;
+ const unsigned char *rgb = src + 4 * (ibuf->x * y + x);
+ float v = (float)IMB_colormanagement_get_luminance_byte(rgb) / 255.0f;
unsigned char *p = tgt;
p += 4 * (w * ((int) (v * (h - 3)) + 1) + x + 1);
@@ -189,7 +189,7 @@ static ImBuf *make_waveform_view_from_ibuf_float(ImBuf *ibuf)
{
ImBuf *rval = IMB_allocImBuf(ibuf->x + 3, 515, 32, IB_rect);
int x, y;
- float *src = ibuf->rect_float;
+ const float *src = ibuf->rect_float;
unsigned char *tgt = (unsigned char *) rval->rect;
int w = ibuf->x + 3;
int h = 515;
@@ -207,7 +207,7 @@ static ImBuf *make_waveform_view_from_ibuf_float(ImBuf *ibuf)
for (x = 0; x < ibuf->x; x++) {
const float *rgb = src + 4 * (ibuf->x * y + x);
- float v = rgb_to_luma(rgb);
+ float v = IMB_colormanagement_get_luminance(rgb);
unsigned char *p = tgt;
CLAMP(v, 0.0f, 1.0f);
@@ -245,8 +245,8 @@ static ImBuf *make_sep_waveform_view_from_ibuf_byte(ImBuf *ibuf)
{
ImBuf *rval = IMB_allocImBuf(ibuf->x + 3, 515, 32, IB_rect);
int x, y;
- unsigned char *src = (unsigned char *) ibuf->rect;
- unsigned char *tgt = (unsigned char *) rval->rect;
+ const unsigned char *src = (const unsigned char *)ibuf->rect;
+ unsigned char *tgt = (unsigned char *)rval->rect;
int w = ibuf->x + 3;
int sw = ibuf->x / 3;
int h = 515;
@@ -264,7 +264,7 @@ static ImBuf *make_sep_waveform_view_from_ibuf_byte(ImBuf *ibuf)
for (x = 0; x < ibuf->x; x++) {
int c;
- unsigned char *rgb = src + 4 * (ibuf->x * y + x);
+ const unsigned char *rgb = src + 4 * (ibuf->x * y + x);
for (c = 0; c < 3; c++) {
unsigned char *p = tgt;
p += 4 * (w * ((rgb[c] * (h - 3)) / 255 + 1) + c * sw + x / 3 + 1);
@@ -290,8 +290,8 @@ static ImBuf *make_sep_waveform_view_from_ibuf_float(ImBuf *ibuf)
{
ImBuf *rval = IMB_allocImBuf(ibuf->x + 3, 515, 32, IB_rect);
int x, y;
- float *src = ibuf->rect_float;
- unsigned char *tgt = (unsigned char *) rval->rect;
+ const float *src = ibuf->rect_float;
+ unsigned char *tgt = (unsigned char *)rval->rect;
int w = ibuf->x + 3;
int sw = ibuf->x / 3;
int h = 515;
@@ -455,7 +455,7 @@ static ImBuf *make_histogram_view_from_ibuf_byte(ImBuf *ibuf)
ImBuf *rval = IMB_allocImBuf(515, 128, 32, IB_rect);
int x, y;
unsigned int nr, ng, nb;
- unsigned char *src = (unsigned char *) ibuf->rect;
+ const unsigned char *src = (unsigned char *)ibuf->rect;
unsigned int bins[3][HIS_STEPS];
@@ -468,7 +468,7 @@ static ImBuf *make_histogram_view_from_ibuf_byte(ImBuf *ibuf)
memset(cur_bins, 0, sizeof(cur_bins));
for (x = 0; x < ibuf->x; x++) {
- unsigned char *pixel = src + (y * ibuf->x + x) * 4;
+ const unsigned char *pixel = src + (y * ibuf->x + x) * 4;
cur_bins[0][pixel[0]]++;
cur_bins[1][pixel[1]]++;
@@ -532,7 +532,7 @@ static ImBuf *make_histogram_view_from_ibuf_float(ImBuf *ibuf)
{
ImBuf *rval = IMB_allocImBuf(515, 128, 32, IB_rect);
int nr, ng, nb, x, y;
- float *src = ibuf->rect_float;
+ const float *src = ibuf->rect_float;
unsigned int bins[3][HIS_STEPS];
@@ -635,7 +635,7 @@ static ImBuf *make_vectorscope_view_from_ibuf_byte(ImBuf *ibuf)
{
ImBuf *rval = IMB_allocImBuf(515, 515, 32, IB_rect);
int x, y;
- char *src = (char *) ibuf->rect;
+ const char *src = (const char *) ibuf->rect;
char *tgt = (char *) rval->rect;
float rgb[3], yuv[3];
int w = 515;
@@ -647,19 +647,19 @@ static ImBuf *make_vectorscope_view_from_ibuf_byte(ImBuf *ibuf)
wtable[x] = (unsigned char) (pow(((float) x + 1) / 256, scope_gamma) * 255);
}
- for (x = 0; x <= 255; x++) {
- vectorscope_put_cross(255, 0, 255 - x, tgt, w, h, 1);
- vectorscope_put_cross(255, x, 0, tgt, w, h, 1);
- vectorscope_put_cross(255 - x, 255, 0, tgt, w, h, 1);
- vectorscope_put_cross(0, 255, x, tgt, w, h, 1);
- vectorscope_put_cross(0, 255 - x, 255, tgt, w, h, 1);
- vectorscope_put_cross(x, 0, 255, tgt, w, h, 1);
+ for (x = 0; x < 256; x++) {
+ vectorscope_put_cross(255, 0, 255 - x, tgt, w, h, 1);
+ vectorscope_put_cross(255, x, 0, tgt, w, h, 1);
+ vectorscope_put_cross(255 - x, 255, 0, tgt, w, h, 1);
+ vectorscope_put_cross(0, 255, x, tgt, w, h, 1);
+ vectorscope_put_cross(0, 255 - x, 255, tgt, w, h, 1);
+ vectorscope_put_cross(x, 0, 255, tgt, w, h, 1);
}
for (y = 0; y < ibuf->y; y++) {
for (x = 0; x < ibuf->x; x++) {
const char *src1 = src + 4 * (ibuf->x * y + x);
- const char *p;
+ char *p;
rgb[0] = (float)src1[0] / 255.0f;
rgb[1] = (float)src1[1] / 255.0f;
@@ -681,7 +681,7 @@ static ImBuf *make_vectorscope_view_from_ibuf_float(ImBuf *ibuf)
{
ImBuf *rval = IMB_allocImBuf(515, 515, 32, IB_rect);
int x, y;
- float *src = ibuf->rect_float;
+ const float *src = ibuf->rect_float;
char *tgt = (char *) rval->rect;
float rgb[3], yuv[3];
int w = 515;
@@ -694,12 +694,12 @@ static ImBuf *make_vectorscope_view_from_ibuf_float(ImBuf *ibuf)
}
for (x = 0; x <= 255; x++) {
- vectorscope_put_cross(255, 0, 255 - x, tgt, w, h, 1);
- vectorscope_put_cross(255, x, 0, tgt, w, h, 1);
- vectorscope_put_cross(255 - x, 255, 0, tgt, w, h, 1);
- vectorscope_put_cross(0, 255, x, tgt, w, h, 1);
- vectorscope_put_cross(0, 255 - x, 255, tgt, w, h, 1);
- vectorscope_put_cross(x, 0, 255, tgt, w, h, 1);
+ vectorscope_put_cross(255, 0, 255 - x, tgt, w, h, 1);
+ vectorscope_put_cross(255, x, 0, tgt, w, h, 1);
+ vectorscope_put_cross(255 - x, 255, 0, tgt, w, h, 1);
+ vectorscope_put_cross(0, 255, x, tgt, w, h, 1);
+ vectorscope_put_cross(0, 255 - x, 255, tgt, w, h, 1);
+ vectorscope_put_cross(x, 0, 255, tgt, w, h, 1);
}
for (y = 0; y < ibuf->y; y++) {
diff --git a/source/blender/editors/space_sequencer/sequencer_select.c b/source/blender/editors/space_sequencer/sequencer_select.c
index 933daf4adee..3dff2442f45 100644
--- a/source/blender/editors/space_sequencer/sequencer_select.c
+++ b/source/blender/editors/space_sequencer/sequencer_select.c
@@ -66,17 +66,23 @@ static void select_surrounding_handles(Scene *scene, Sequence *test) /* XXX BRIN
neighbor = find_neighboring_sequence(scene, test, SEQ_SIDE_LEFT, -1);
if (neighbor) {
+ /* Only select neighbor handle if matching handle from test seq is also selected, or if neighbor
+ * was not selected at all up till now.
+ * Otherwise, we get odd mismatch when shift-alt-rmb selecting neighbor strips... */
+ if (!(neighbor->flag & SELECT) || (test->flag & SEQ_LEFTSEL)) {
+ neighbor->flag |= SEQ_RIGHTSEL;
+ }
neighbor->flag |= SELECT;
recurs_sel_seq(neighbor);
- neighbor->flag |= SEQ_RIGHTSEL;
}
neighbor = find_neighboring_sequence(scene, test, SEQ_SIDE_RIGHT, -1);
if (neighbor) {
+ if (!(neighbor->flag & SELECT) || (test->flag & SEQ_RIGHTSEL)) { /* See comment above. */
+ neighbor->flag |= SEQ_LEFTSEL;
+ }
neighbor->flag |= SELECT;
recurs_sel_seq(neighbor);
- neighbor->flag |= SEQ_LEFTSEL;
}
- test->flag |= SELECT;
}
/* used for mouse selection and for SEQUENCER_OT_select_active_side() */
@@ -357,40 +363,33 @@ static int sequencer_select_invoke(bContext *C, wmOperator *op, const wmEvent *e
case SEQ_SELECT_LR_MOUSE:
x = UI_view2d_region_to_view_x(v2d, event->mval[0]);
break;
-
case SEQ_SELECT_LR_LEFT:
- x = CFRA - 1;
+ x = CFRA - 1.0f;
break;
case SEQ_SELECT_LR_RIGHT:
- x = CFRA + 1;
+ default:
+ x = CFRA;
break;
}
SEQP_BEGIN (ed, seq)
{
- if (x < CFRA) {
- if (seq->enddisp < CFRA) {
- seq->flag |= SELECT;
- recurs_sel_seq(seq);
- }
- }
- else {
- if (seq->startdisp > CFRA) {
- seq->flag |= SELECT;
- recurs_sel_seq(seq);
- }
+ if (((x < CFRA) && (seq->enddisp <= CFRA)) ||
+ ((x >= CFRA) && (seq->startdisp >= CFRA)))
+ {
+ seq->flag |= SELECT;
+ recurs_sel_seq(seq);
}
}
SEQ_END
-
{
SpaceSeq *sseq = CTX_wm_space_seq(C);
if (sseq && sseq->flag & SEQ_MARKER_TRANS) {
TimeMarker *tmarker;
for (tmarker = scene->markers.first; tmarker; tmarker = tmarker->next) {
- if (((x < CFRA) && tmarker->frame < CFRA) ||
- ((x >= CFRA) && tmarker->frame >= CFRA))
+ if (((x < CFRA) && (tmarker->frame <= CFRA)) ||
+ ((x >= CFRA) && (tmarker->frame >= CFRA)))
{
tmarker->flag |= SELECT;
}
@@ -423,83 +422,94 @@ static int sequencer_select_invoke(bContext *C, wmOperator *op, const wmEvent *e
}
}
- if (extend && (seq->flag & SELECT) && ed->act_seq == act_orig) {
- switch (hand) {
- case SEQ_SIDE_NONE:
- if (linked_handle == 0)
- seq->flag &= ~SEQ_ALLSEL;
- break;
- case SEQ_SIDE_LEFT:
- seq->flag ^= SEQ_LEFTSEL;
- break;
- case SEQ_SIDE_RIGHT:
- seq->flag ^= SEQ_RIGHTSEL;
- break;
+ /* On Alt selection, select the strip and bordering handles */
+ if (linked_handle) {
+ if (!ELEM(hand, SEQ_SIDE_LEFT, SEQ_SIDE_RIGHT)) {
+ /* First click selects the strip and its adjacent handles (if valid).
+ * Second click selects the strip, both of its handles and its adjacent handles (if valid).
+ */
+ const bool is_striponly_selected = ((seq->flag & SEQ_ALLSEL) == SELECT);
+
+ if (!extend) {
+ ED_sequencer_deselect_all(scene);
+ }
+ seq->flag &= ~SEQ_ALLSEL;
+ seq->flag |= is_striponly_selected ? SEQ_ALLSEL : SELECT;
+ select_surrounding_handles(scene, seq);
+ }
+ else if (seq->flag & SELECT) {
+ /* First click selects adjacent handles on that side.
+ * Second click selects all strips in that direction.
+ * If there are no adjacent strips, it just selects all in that direction.
+ */
+ sel_side = hand;
+ neighbor = find_neighboring_sequence(scene, seq, sel_side, -1);
+ if (neighbor) {
+ switch (sel_side) {
+ case SEQ_SIDE_LEFT:
+ if ((seq->flag & SEQ_LEFTSEL) && (neighbor->flag & SEQ_RIGHTSEL)) {
+ if (extend == 0) ED_sequencer_deselect_all(scene);
+ seq->flag |= SELECT;
+
+ select_active_side(ed->seqbasep, SEQ_SIDE_LEFT, seq->machine, seq->startdisp);
+ }
+ else {
+ if (extend == 0) ED_sequencer_deselect_all(scene);
+ seq->flag |= SELECT;
+
+ neighbor->flag |= SELECT;
+ recurs_sel_seq(neighbor);
+ neighbor->flag |= SEQ_RIGHTSEL;
+ seq->flag |= SEQ_LEFTSEL;
+ }
+ break;
+ case SEQ_SIDE_RIGHT:
+ if ((seq->flag & SEQ_RIGHTSEL) && (neighbor->flag & SEQ_LEFTSEL)) {
+ if (extend == 0) ED_sequencer_deselect_all(scene);
+ seq->flag |= SELECT;
+
+ select_active_side(ed->seqbasep, SEQ_SIDE_RIGHT, seq->machine, seq->startdisp);
+ }
+ else {
+ if (extend == 0) ED_sequencer_deselect_all(scene);
+ seq->flag |= SELECT;
+
+ neighbor->flag |= SELECT;
+ recurs_sel_seq(neighbor);
+ neighbor->flag |= SEQ_LEFTSEL;
+ seq->flag |= SEQ_RIGHTSEL;
+ }
+ break;
+ }
+ }
+ else {
+ if (extend == 0) ED_sequencer_deselect_all(scene);
+ select_active_side(ed->seqbasep, sel_side, seq->machine, seq->startdisp);
+ }
}
}
else {
- seq->flag |= SELECT;
- if (hand == SEQ_SIDE_LEFT) seq->flag |= SEQ_LEFTSEL;
- if (hand == SEQ_SIDE_RIGHT) seq->flag |= SEQ_RIGHTSEL;
- }
-
- /* On Alt selection, select the strip and bordering handles */
- if (linked_handle && !ELEM(hand, SEQ_SIDE_LEFT, SEQ_SIDE_RIGHT)) {
- if (extend == 0) ED_sequencer_deselect_all(scene);
- seq->flag |= SELECT;
- select_surrounding_handles(scene, seq);
- }
- else if (linked_handle && ELEM(hand, SEQ_SIDE_LEFT, SEQ_SIDE_RIGHT) && (seq->flag & SELECT)) {
- /*
- * First click selects adjacent handles on that side.
- * Second click selects all strips in that direction.
- * If there are no adjacent strips, it just selects all in that direction.
- */
- sel_side = hand;
- neighbor = find_neighboring_sequence(scene, seq, sel_side, -1);
- if (neighbor) {
- switch (sel_side) {
+ if (extend && (seq->flag & SELECT) && ed->act_seq == act_orig) {
+ switch (hand) {
+ case SEQ_SIDE_NONE:
+ if (linked_handle == 0)
+ seq->flag &= ~SEQ_ALLSEL;
+ break;
case SEQ_SIDE_LEFT:
- if ((seq->flag & SEQ_LEFTSEL) && (neighbor->flag & SEQ_RIGHTSEL)) {
- if (extend == 0) ED_sequencer_deselect_all(scene);
- seq->flag |= SELECT;
-
- select_active_side(ed->seqbasep, SEQ_SIDE_LEFT, seq->machine, seq->startdisp);
- }
- else {
- if (extend == 0) ED_sequencer_deselect_all(scene);
- seq->flag |= SELECT;
-
- neighbor->flag |= SELECT;
- recurs_sel_seq(neighbor);
- neighbor->flag |= SEQ_RIGHTSEL;
- seq->flag |= SEQ_LEFTSEL;
- }
+ seq->flag ^= SEQ_LEFTSEL;
break;
case SEQ_SIDE_RIGHT:
- if ((seq->flag & SEQ_RIGHTSEL) && (neighbor->flag & SEQ_LEFTSEL)) {
- if (extend == 0) ED_sequencer_deselect_all(scene);
- seq->flag |= SELECT;
-
- select_active_side(ed->seqbasep, SEQ_SIDE_RIGHT, seq->machine, seq->startdisp);
- }
- else {
- if (extend == 0) ED_sequencer_deselect_all(scene);
- seq->flag |= SELECT;
-
- neighbor->flag |= SELECT;
- recurs_sel_seq(neighbor);
- neighbor->flag |= SEQ_LEFTSEL;
- seq->flag |= SEQ_RIGHTSEL;
- }
+ seq->flag ^= SEQ_RIGHTSEL;
break;
}
}
else {
- if (extend == 0) ED_sequencer_deselect_all(scene);
- select_active_side(ed->seqbasep, sel_side, seq->machine, seq->startdisp);
+ seq->flag |= SELECT;
+ if (hand == SEQ_SIDE_LEFT) seq->flag |= SEQ_LEFTSEL;
+ if (hand == SEQ_SIDE_RIGHT) seq->flag |= SEQ_RIGHTSEL;
}
}
+
recurs_sel_seq(seq);
if (linked_time) {
@@ -591,21 +601,35 @@ static bool select_more_less_seq__internal(Scene *scene, bool sel, const bool li
}
for (seq = ed->seqbasep->first; seq; seq = seq->next) {
- if ((int)(seq->flag & SELECT) == sel) {
- if ((linked == 0 && seq->tmp) == 0) {
- /* only get unselected nabours */
+ if ((seq->flag & SELECT) == sel) {
+ if (linked || (seq->tmp == NULL)) {
+ /* only get unselected neighbors */
neighbor = find_neighboring_sequence(scene, seq, SEQ_SIDE_LEFT, isel);
if (neighbor) {
- if (sel) { neighbor->flag |= SELECT; recurs_sel_seq(neighbor); }
- else neighbor->flag &= ~SELECT;
- if (linked == 0) neighbor->tmp = (Sequence *)1;
+ if (sel) {
+ neighbor->flag |= SELECT;
+ recurs_sel_seq(neighbor);
+ }
+ else {
+ neighbor->flag &= ~SELECT;
+ }
+ if (!linked) {
+ neighbor->tmp = (Sequence *)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;
+ if (sel) {
+ neighbor->flag |= SELECT;
+ recurs_sel_seq(neighbor);
+ }
+ else {
+ neighbor->flag &= ~SELECT;
+ }
+ if (!linked) {
+ neighbor->tmp = (Sequence *)1;
+ }
changed = true;
}
}
@@ -622,7 +646,7 @@ static int sequencer_select_more_exec(bContext *C, wmOperator *UNUSED(op))
{
Scene *scene = CTX_data_scene(C);
- if (!select_more_less_seq__internal(scene, 0, 0))
+ if (!select_more_less_seq__internal(scene, true, false))
return OPERATOR_CANCELLED;
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER | NA_SELECTED, scene);
@@ -653,7 +677,7 @@ static int sequencer_select_less_exec(bContext *C, wmOperator *UNUSED(op))
{
Scene *scene = CTX_data_scene(C);
- if (!select_more_less_seq__internal(scene, 1, 0))
+ if (!select_more_less_seq__internal(scene, false, false))
return OPERATOR_CANCELLED;
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER | NA_SELECTED, scene);
@@ -999,7 +1023,7 @@ static bool select_grouped_data(Editing *ed, Sequence *actseq)
if (SEQ_HAS_PATH(actseq) && dir) {
SEQP_BEGIN (ed, seq)
{
- if (SEQ_HAS_PATH(seq) && seq->strip && strcmp(seq->strip->dir, dir) == 0) {
+ if (SEQ_HAS_PATH(seq) && seq->strip && STREQ(seq->strip->dir, dir)) {
seq->flag |= SELECT;
changed = true;
}
@@ -1047,15 +1071,15 @@ static bool select_grouped_effect(Editing *ed, Sequence *actseq)
{
Sequence *seq;
bool changed = false;
- bool effects[SEQ_TYPE_EFFECT_MAX + 1];
+ bool effects[SEQ_TYPE_MAX + 1];
int i;
- for (i = 0; i <= SEQ_TYPE_EFFECT_MAX; i++)
+ for (i = 0; i <= SEQ_TYPE_MAX; i++)
effects[i] = false;
SEQP_BEGIN (ed, seq)
{
- if (ELEM(actseq, seq->seq1, seq->seq2, seq->seq3)) {
+ if ((seq->type & SEQ_TYPE_EFFECT) && ELEM(actseq, seq->seq1, seq->seq2, seq->seq3)) {
effects[seq->type] = true;
}
}
diff --git a/source/blender/editors/space_sequencer/sequencer_view.c b/source/blender/editors/space_sequencer/sequencer_view.c
index 7fdbc9cc7de..4d6ea865b40 100644
--- a/source/blender/editors/space_sequencer/sequencer_view.c
+++ b/source/blender/editors/space_sequencer/sequencer_view.c
@@ -94,7 +94,7 @@ static void sample_apply(bContext *C, wmOperator *op, const wmEvent *event)
Scene *scene = CTX_data_scene(C);
SpaceSeq *sseq = (SpaceSeq *) CTX_wm_space_data(C);
ARegion *ar = CTX_wm_region(C);
- ImBuf *ibuf = sequencer_ibuf_get(bmain, scene, sseq, CFRA, 0);
+ ImBuf *ibuf = sequencer_ibuf_get(bmain, scene, sseq, CFRA, 0, NULL);
ImageSampleInfo *info = op->customdata;
float fx, fy;
@@ -201,8 +201,11 @@ static int sample_modal(bContext *C, wmOperator *op, const wmEvent *event)
switch (event->type) {
case LEFTMOUSE:
case RIGHTMOUSE: /* XXX hardcoded */
- sample_exit(C, op);
- return OPERATOR_CANCELLED;
+ if (event->val == KM_RELEASE) {
+ sample_exit(C, op);
+ return OPERATOR_CANCELLED;
+ }
+ break;
case MOUSEMOVE:
sample_apply(C, op, event);
break;
diff --git a/source/blender/editors/space_sequencer/space_sequencer.c b/source/blender/editors/space_sequencer/space_sequencer.c
index c0cfaed7867..5b3061bd513 100644
--- a/source/blender/editors/space_sequencer/space_sequencer.c
+++ b/source/blender/editors/space_sequencer/space_sequencer.c
@@ -144,9 +144,9 @@ static SpaceLink *sequencer_new(const bContext *C)
ar->alignment = RGN_ALIGN_TOP;
ar->flag |= RGN_FLAG_HIDDEN;
/* for now, aspect ratio should be maintained, and zoom is clamped within sane default limits */
- ar->v2d.keepzoom = V2D_KEEPASPECT | V2D_KEEPZOOM;
- ar->v2d.minzoom = 0.00001f;
- ar->v2d.maxzoom = 100000.0f;
+ ar->v2d.keepzoom = V2D_KEEPASPECT | V2D_KEEPZOOM | V2D_LIMITZOOM;
+ ar->v2d.minzoom = 0.001f;
+ ar->v2d.maxzoom = 1000.0f;
ar->v2d.tot.xmin = -960.0f; /* 1920 width centered */
ar->v2d.tot.ymin = -540.0f; /* 1080 height centered */
ar->v2d.tot.xmax = 960.0f;
@@ -328,7 +328,7 @@ static SpaceLink *sequencer_duplicate(SpaceLink *sl)
SpaceSeq *sseqn = MEM_dupallocN(sl);
/* clear or remove stuff from old */
-// XXX sseq->gpd = gpencil_data_duplicate(sseq->gpd);
+// XXX sseq->gpd = gpencil_data_duplicate(sseq->gpd, false);
memset(&sseqn->scopes, 0, sizeof(sseqn->scopes));
@@ -352,6 +352,10 @@ static void sequencer_listener(bScreen *UNUSED(sc), ScrArea *sa, wmNotifier *wmn
if (wmn->data == ND_SPACE_SEQUENCER)
sequencer_scopes_tag_refresh(sa);
break;
+ case NC_GPENCIL:
+ if (wmn->data & ND_GPENCIL_EDITMODE)
+ ED_area_tag_redraw(sa);
+ break;
}
}
@@ -500,6 +504,13 @@ static void sequencer_main_area_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa
break;
}
break;
+ case NC_ANIMATION:
+ switch (wmn->data) {
+ case ND_KEYFRAME:
+ ED_region_tag_redraw(ar);
+ break;
+ }
+ break;
case NC_SPACE:
if (wmn->data == ND_SPACE_SEQUENCER)
ED_region_tag_redraw(ar);
@@ -553,13 +564,16 @@ static void sequencer_preview_area_draw(const bContext *C, ARegion *ar)
SpaceSeq *sseq = sa->spacedata.first;
Scene *scene = CTX_data_scene(C);
wmWindowManager *wm = CTX_wm_manager(C);
- int show_split = scene->ed && scene->ed->over_flag & SEQ_EDIT_OVERLAY_SHOW && sseq->mainb == SEQ_DRAW_IMG_IMBUF;
+ const bool show_split = (
+ scene->ed &&
+ (scene->ed->over_flag & SEQ_EDIT_OVERLAY_SHOW) &&
+ (sseq->mainb == SEQ_DRAW_IMG_IMBUF));
/* XXX temp fix for wrong setting in sseq->mainb */
if (sseq->mainb == SEQ_DRAW_SEQUENCE) sseq->mainb = SEQ_DRAW_IMG_IMBUF;
if (!show_split || sseq->overlay_type != SEQ_DRAW_OVERLAY_REFERENCE)
- draw_image_seq(C, scene, ar, sseq, scene->r.cfra, 0, false);
+ draw_image_seq(C, scene, ar, sseq, scene->r.cfra, 0, false, false);
if (show_split && sseq->overlay_type != SEQ_DRAW_OVERLAY_CURRENT) {
int over_cfra;
@@ -570,10 +584,10 @@ static void sequencer_preview_area_draw(const bContext *C, ARegion *ar)
over_cfra = scene->r.cfra + scene->ed->over_ofs;
if (over_cfra != scene->r.cfra || sseq->overlay_type != SEQ_DRAW_OVERLAY_RECT)
- draw_image_seq(C, scene, ar, sseq, scene->r.cfra, over_cfra - scene->r.cfra, true);
+ draw_image_seq(C, scene, ar, sseq, scene->r.cfra, over_cfra - scene->r.cfra, true, false);
}
- if ((U.uiflag & USER_SHOW_FPS) && ED_screen_animation_playing(wm)) {
+ if ((U.uiflag & USER_SHOW_FPS) && ED_screen_animation_no_scrub(wm)) {
rcti rect;
ED_region_visible_rect(ar, &rect);
ED_scene_draw_fps(scene, &rect);
@@ -585,7 +599,7 @@ static void sequencer_preview_area_listener(bScreen *UNUSED(sc), ScrArea *UNUSED
/* context changes */
switch (wmn->category) {
case NC_GPENCIL:
- if (wmn->action == NA_EDITED) {
+ if (ELEM(wmn->action, NA_EDITED, NA_SELECTED)) {
ED_region_tag_redraw(ar);
}
break;
@@ -595,6 +609,16 @@ static void sequencer_preview_area_listener(bScreen *UNUSED(sc), ScrArea *UNUSED
case ND_MARKERS:
case ND_SEQUENCER:
case ND_RENDER_OPTIONS:
+ case ND_DRAW_RENDER_VIEWPORT:
+ ED_region_tag_redraw(ar);
+ break;
+ }
+ break;
+ case NC_ANIMATION:
+ switch (wmn->data) {
+ case ND_KEYFRAME:
+ /* Otherwise, often prevents seing immediately effects of keyframe editing... */
+ BKE_sequencer_cache_cleanup();
ED_region_tag_redraw(ar);
break;
}
@@ -633,7 +657,7 @@ static void sequencer_buttons_area_init(wmWindowManager *wm, ARegion *ar)
static void sequencer_buttons_area_draw(const bContext *C, ARegion *ar)
{
- ED_region_panels(C, ar, 1, NULL, -1);
+ ED_region_panels(C, ar, NULL, -1, true);
}
static void sequencer_buttons_area_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn)
@@ -641,7 +665,7 @@ static void sequencer_buttons_area_listener(bScreen *UNUSED(sc), ScrArea *UNUSED
/* context changes */
switch (wmn->category) {
case NC_GPENCIL:
- if (wmn->data == ND_DATA) {
+ if (ELEM(wmn->action, NA_EDITED, NA_SELECTED)) {
ED_region_tag_redraw(ar);
}
break;
diff --git a/source/blender/editors/space_text/CMakeLists.txt b/source/blender/editors/space_text/CMakeLists.txt
index bfeeb93372a..de85ddc40ab 100644
--- a/source/blender/editors/space_text/CMakeLists.txt
+++ b/source/blender/editors/space_text/CMakeLists.txt
@@ -23,10 +23,13 @@ set(INC
../../blenfont
../../blenkernel
../../blenlib
+ ../../blentranslation
+ ../../gpu
../../makesdna
../../makesrna
../../windowmanager
../../../../intern/guardedalloc
+ ../../../../intern/glew-mx
)
set(INC_SYS
@@ -48,6 +51,8 @@ set(SRC
text_intern.h
)
+add_definitions(${GL_DEFINITIONS})
+
if(WITH_PYTHON)
list(APPEND INC
../../python
diff --git a/source/blender/editors/space_text/SConscript b/source/blender/editors/space_text/SConscript
index 3f617f95c58..d11671fe743 100644
--- a/source/blender/editors/space_text/SConscript
+++ b/source/blender/editors/space_text/SConscript
@@ -28,14 +28,20 @@
Import ('env')
sources = env.Glob('*.c')
+
defs = []
+defs += env['BF_GL_DEFINITIONS']
+
incs = [
'#/intern/guardedalloc',
- '#/extern/glew/include',
+ env['BF_GLEW_INC'],
+ '#/intern/glew-mx',
'../include',
'../../blenfont',
'../../blenkernel',
'../../blenlib',
+ '../../blentranslation',
+ '../../gpu',
'../../imbuf',
'../../makesdna',
'../../makesrna',
diff --git a/source/blender/editors/space_text/space_text.c b/source/blender/editors/space_text/space_text.c
index 1e710b88cad..ff53d306e69 100644
--- a/source/blender/editors/space_text/space_text.c
+++ b/source/blender/editors/space_text/space_text.c
@@ -135,7 +135,7 @@ static void text_listener(bScreen *UNUSED(sc), ScrArea *sa, wmNotifier *wmn)
break;
case ND_CURSOR:
if (st->text && st->text == wmn->reference)
- text_scroll_to_cursor(st, sa);
+ text_scroll_to_cursor__area(st, sa, true);
ED_area_tag_redraw(sa);
break;
@@ -156,7 +156,7 @@ static void text_listener(bScreen *UNUSED(sc), ScrArea *sa, wmNotifier *wmn)
break;
case NA_SELECTED:
if (st->text && st->text == wmn->reference)
- text_scroll_to_cursor(st, sa);
+ text_scroll_to_cursor__area(st, sa, true);
break;
}
@@ -541,7 +541,7 @@ static void text_properties_area_draw(const bContext *C, ARegion *ar)
{
SpaceText *st = CTX_wm_space_text(C);
- ED_region_panels(C, ar, 1, NULL, -1);
+ ED_region_panels(C, ar, NULL, -1, true);
/* this flag trick is make sure buttons have been added already */
if (st->flags & ST_FIND_ACTIVATE) {
diff --git a/source/blender/editors/space_text/text_autocomplete.c b/source/blender/editors/space_text/text_autocomplete.c
index 99e1606c9bd..1637ae14892 100644
--- a/source/blender/editors/space_text/text_autocomplete.c
+++ b/source/blender/editors/space_text/text_autocomplete.c
@@ -183,7 +183,7 @@ static GHash *text_autocomplete_build(Text *text)
const int choice_len = i_end - i_start;
if ((choice_len > seek_len) &&
- (seek_len == 0 || strncmp(seek, str_sub, seek_len) == 0) &&
+ (seek_len == 0 || STREQLEN(seek, str_sub, seek_len)) &&
(seek != str_sub))
{
// printf("Adding: %s\n", s);
@@ -207,18 +207,16 @@ static GHash *text_autocomplete_build(Text *text)
}
{
- GHashIterator *iter = BLI_ghashIterator_new(gh);
+ GHashIterator gh_iter;
/* get the formatter for highlighting */
TextFormatType *tft;
tft = ED_text_format_get(text);
- for (; !BLI_ghashIterator_done(iter); BLI_ghashIterator_step(iter)) {
- const char *s = BLI_ghashIterator_getValue(iter);
+ GHASH_ITER (gh_iter, gh) {
+ const char *s = BLI_ghashIterator_getValue(&gh_iter);
texttool_suggest_add(s, tft->format_identifier(s));
}
- BLI_ghashIterator_free(iter);
-
}
}
diff --git a/source/blender/editors/space_text/text_draw.c b/source/blender/editors/space_text/text_draw.c
index af827d6dc5a..462b619f497 100644
--- a/source/blender/editors/space_text/text_draw.c
+++ b/source/blender/editors/space_text/text_draw.c
@@ -28,8 +28,6 @@
* \ingroup sptext
*/
-
-
#include "MEM_guardedalloc.h"
#include "BLF_api.h"
@@ -44,6 +42,9 @@
#include "BKE_context.h"
#include "BKE_suggestions.h"
#include "BKE_text.h"
+#include "BKE_screen.h"
+
+#include "ED_text.h"
#include "BIF_gl.h"
@@ -381,7 +382,9 @@ static int text_draw_wrapped(SpaceText *st, const char *str, int x, int y, int w
int a, fstart, fpos; /* utf8 chars */
int mi, ma, mstart, mend; /* mem */
char fmt_prev = 0xff;
-
+ /* don't draw lines below this */
+ const int clip_min_y = -(int)(st->lheight_dpi - 1);
+
flatten_string(st, &fs, str);
str = fs.buf;
max = w / st->cwidth;
@@ -424,7 +427,8 @@ static int text_draw_wrapped(SpaceText *st, const char *str, int x, int y, int w
mend = txt_utf8_forward_columns(str + mend, max, &padding) - str;
end = (wrap += max - padding);
- if (y <= 0) break;
+ if (y <= clip_min_y)
+ break;
}
else if (str[mi] == ' ' || str[mi] == '-') {
wrap = i + 1; mend = mi + 1;
@@ -432,7 +436,7 @@ static int text_draw_wrapped(SpaceText *st, const char *str, int x, int y, int w
}
/* Draw the remaining text */
- for (a = fstart, ma = mstart; str[ma] && y > 0; a++, ma += BLI_str_utf8_size_safe(str + ma)) {
+ for (a = fstart, ma = mstart; str[ma] && y > clip_min_y; a++, ma += BLI_str_utf8_size_safe(str + ma)) {
if (use_syntax) {
if (fmt_prev != format[a]) format_draw_color(fmt_prev = format[a]);
}
@@ -519,7 +523,7 @@ static void text_drawcache_init(SpaceText *st)
DrawCache *drawcache = MEM_callocN(sizeof(DrawCache), "text draw cache");
drawcache->winx = -1;
- drawcache->nlines = BLI_countlist(&st->text->lines);
+ drawcache->nlines = BLI_listbase_count(&st->text->lines);
drawcache->text_id[0] = '\0';
st->drawcache = drawcache;
@@ -545,7 +549,7 @@ static void text_update_drawcache(SpaceText *st, ARegion *ar)
full_update |= drawcache->tabnumber != st->tabnumber; /* word-wrapping option was toggled */
full_update |= drawcache->lheight != st->lheight_dpi; /* word-wrapping option was toggled */
full_update |= drawcache->cwidth != st->cwidth; /* word-wrapping option was toggled */
- full_update |= strncmp(drawcache->text_id, txt->id.name, MAX_ID_NAME); /* text datablock was changed */
+ full_update |= !STREQLEN(drawcache->text_id, txt->id.name, MAX_ID_NAME); /* text datablock was changed */
if (st->wordwrap) {
/* update line heights */
@@ -560,7 +564,7 @@ static void text_update_drawcache(SpaceText *st, ARegion *ar)
int lineno = 0, size, lines_count;
int *fp = drawcache->line_height, *new_tail, *old_tail;
- nlines = BLI_countlist(&txt->lines);
+ nlines = BLI_listbase_count(&txt->lines);
size = sizeof(int) * nlines;
if (fp) fp = MEM_reallocN(fp, size);
@@ -605,7 +609,7 @@ static void text_update_drawcache(SpaceText *st, ARegion *ar)
}
if (full_update || drawcache->update_flag) {
- nlines = BLI_countlist(&txt->lines);
+ nlines = BLI_listbase_count(&txt->lines);
if (st->showlinenrs)
st->linenrs_tot = (int)floor(log10((float)nlines)) + 1;
@@ -892,15 +896,15 @@ static void draw_textscroll(SpaceText *st, rcti *scroll, rcti *back)
UI_ThemeColor(TH_BACK);
glRecti(back->xmin, back->ymin, back->xmax, back->ymax);
- uiWidgetScrollDraw(&wcol, scroll, &st->txtbar, (st->flags & ST_SCROLL_SELECT) ? UI_SCROLL_PRESSED : 0);
+ UI_draw_widget_scroll(&wcol, scroll, &st->txtbar, (st->flags & ST_SCROLL_SELECT) ? UI_SCROLL_PRESSED : 0);
- uiSetRoundBox(UI_CNR_ALL);
+ UI_draw_roundbox_corner_set(UI_CNR_ALL);
rad = 0.4f * min_ii(BLI_rcti_size_x(&st->txtscroll), BLI_rcti_size_y(&st->txtscroll));
UI_GetThemeColor3ubv(TH_HILITE, col);
col[3] = 48;
glColor4ubv(col);
glEnable(GL_BLEND);
- uiRoundBox(st->txtscroll.xmin + 1, st->txtscroll.ymin, st->txtscroll.xmax - 1, st->txtscroll.ymax, rad);
+ UI_draw_roundbox(st->txtscroll.xmin + 1, st->txtscroll.ymin, st->txtscroll.xmax - 1, st->txtscroll.ymax, rad);
glDisable(GL_BLEND);
}
@@ -1034,7 +1038,7 @@ static void draw_suggestion_list(SpaceText *st, ARegion *ar)
x = MAX2(0, ar->winx - boxw);
/* not needed but stands out nicer */
- uiDrawBoxShadow(220, x, y - boxh, x + boxw, y);
+ UI_draw_box_shadow(220, x, y - boxh, x + boxw, y);
UI_ThemeColor(TH_SHADE1);
glRecti(x - 1, y + 1, x + boxw + 1, y - boxh - 1);
@@ -1323,6 +1327,8 @@ void draw_text_main(SpaceText *st, ARegion *ar)
int i, x, y, winx, linecount = 0, lineno = 0;
int wraplinecount = 0, wrap_skip = 0;
int margin_column_x;
+ /* don't draw lines below this */
+ const int clip_min_y = -(int)(st->lheight_dpi - 1);
/* if no text, nothing to do */
if (!text)
@@ -1330,7 +1336,7 @@ void draw_text_main(SpaceText *st, ARegion *ar)
/* dpi controlled line height and font size */
st->lheight_dpi = (U.widget_unit * st->lheight) / 20;
- st->viewlines = (st->lheight_dpi) ? (int)ar->winy / (st->lheight_dpi + TXT_LINE_SPACING) : 0;
+ st->viewlines = (st->lheight_dpi) ? (int)(ar->winy - clip_min_y) / (st->lheight_dpi + TXT_LINE_SPACING) : 0;
text_update_drawcache(st, ar);
@@ -1394,7 +1400,7 @@ void draw_text_main(SpaceText *st, ARegion *ar)
/* draw the text */
UI_ThemeColor(TH_TEXT);
- for (i = 0; y > 0 && i < st->viewlines && tmp; i++, tmp = tmp->next) {
+ for (i = 0; y > clip_min_y && i < st->viewlines && tmp; i++, tmp = tmp->next) {
if (st->showsyntax && !tmp->format)
tft->format_line(st, tmp, false);
@@ -1441,7 +1447,6 @@ void draw_text_main(SpaceText *st, ARegion *ar)
/* draw other stuff */
draw_brackets(st, ar);
- glTranslatef(GLA_PIXEL_OFS, GLA_PIXEL_OFS, 0.0f); /* XXX scroll requires exact pixel space */
draw_textscroll(st, &scroll, &back);
draw_documentation(st, ar);
draw_suggestion_list(st, ar);
@@ -1461,22 +1466,15 @@ void text_update_character_width(SpaceText *st)
/* Moves the view to the cursor location,
* also used to make sure the view isn't outside the file */
-void text_scroll_to_cursor(SpaceText *st, ScrArea *sa)
+void text_scroll_to_cursor(SpaceText *st, ARegion *ar, const bool center)
{
Text *text;
- ARegion *ar = NULL;
- int i, x, winx = 0;
+ int i, x, winx = ar->winx;
if (ELEM(NULL, st, st->text, st->text->curl)) return;
text = st->text;
- for (ar = sa->regionbase.first; ar; ar = ar->next)
- if (ar->regiontype == RGN_TYPE_WINDOW) {
- winx = ar->winx;
- break;
- }
-
text_update_character_width(st);
i = txt_get_span(text->lines.first, text->sell);
@@ -1486,8 +1484,19 @@ void text_scroll_to_cursor(SpaceText *st, ScrArea *sa)
i += offl;
}
- if (st->top + st->viewlines <= i || st->top > i)
- st->top = i - st->viewlines / 2;
+ if (center) {
+ if (st->top + st->viewlines <= i || st->top > i) {
+ st->top = i - st->viewlines / 2;
+ }
+ }
+ else {
+ if (st->top + st->viewlines <= i) {
+ st->top = i - (st->viewlines - 1);
+ }
+ else if (st->top > i) {
+ st->top = i;
+ }
+ }
if (st->wordwrap) {
st->left = 0;
@@ -1496,8 +1505,19 @@ void text_scroll_to_cursor(SpaceText *st, ScrArea *sa)
x = st->cwidth * (text_get_char_pos(st, text->sell->line, text->selc) - st->left);
winx -= TXT_OFFSET + (st->showlinenrs ? TEXTXLOC : 0) + TXT_SCROLL_WIDTH;
- if (x <= 0 || x > winx)
- st->left += (x - winx / 2) / st->cwidth;
+ if (center) {
+ if (x <= 0 || x > winx) {
+ st->left += (x - winx / 2) / st->cwidth;
+ }
+ }
+ else {
+ if (x <= 0) {
+ st->left += ((x + 1) / st->cwidth) - 1;
+ }
+ else if (x > winx) {
+ st->left += ((x - (winx + 1)) / st->cwidth) + 1;
+ }
+ }
}
if (st->top < 0) st->top = 0;
@@ -1507,10 +1527,58 @@ void text_scroll_to_cursor(SpaceText *st, ScrArea *sa)
st->scroll_accum[1] = 0.0f;
}
+/* takes an area instead of a region, use for listeners */
+void text_scroll_to_cursor__area(SpaceText *st, ScrArea *sa, const bool center)
+{
+ ARegion *ar;
+
+ if (ELEM(NULL, st, st->text, st->text->curl)) return;
+
+ ar = BKE_area_find_region_type(sa, RGN_TYPE_WINDOW);
+
+ if (ar) {
+ text_scroll_to_cursor(st, ar, center);
+ }
+}
+
void text_update_cursor_moved(bContext *C)
{
ScrArea *sa = CTX_wm_area(C);
SpaceText *st = CTX_wm_space_text(C);
- text_scroll_to_cursor(st, sa);
+ text_scroll_to_cursor__area(st, sa, true);
+}
+
+/**
+ * Takes a cursor (row, character) and returns x,y pixel coords.
+ */
+bool ED_text_region_location_from_cursor(SpaceText *st, ARegion *ar, const int cursor_co[2], int r_pixel_co[2])
+{
+ TextLine *line = NULL;
+
+ if (!st->text) {
+ goto error;
+ }
+
+ line = BLI_findlink(&st->text->lines, cursor_co[0]);
+ if (!line || (cursor_co[1] < 0) || (cursor_co[1] > line->len)) {
+ goto error;
+ }
+ else {
+ int offl, offc;
+ int linenr_offset = st->showlinenrs ? TXT_OFFSET + TEXTXLOC : TXT_OFFSET;
+ /* handle tabs as well! */
+ int char_pos = text_get_char_pos(st, line->line, cursor_co[1]);
+
+ wrap_offset(st, ar, line, cursor_co[1], &offl, &offc);
+ r_pixel_co[0] = (char_pos + offc - st->left) * st->cwidth + linenr_offset;
+ r_pixel_co[1] = (cursor_co[0] + offl - st->top) * (st->lheight_dpi + TXT_LINE_SPACING);
+ r_pixel_co[1] = (ar->winy - (r_pixel_co[1] + TXT_OFFSET)) - st->lheight_dpi;
+ }
+ return true;
+
+
+error:
+ r_pixel_co[0] = r_pixel_co[1] = -1;
+ return false;
}
diff --git a/source/blender/editors/space_text/text_header.c b/source/blender/editors/space_text/text_header.c
index b1d57f5a75e..91665f1a598 100644
--- a/source/blender/editors/space_text/text_header.c
+++ b/source/blender/editors/space_text/text_header.c
@@ -34,7 +34,6 @@
#include "BLI_blenlib.h"
-#include "BLF_translation.h"
#include "BKE_context.h"
#include "BKE_screen.h"
@@ -142,7 +141,7 @@ void TEXT_OT_start_find(wmOperatorType *ot)
uiPopupMenu *pup;
if (text) {
- pup = uiPupMenuBegin(C, IFACE_("Text"), ICON_NONE);
+ pup = UI_popup_menu_begin(C, IFACE_("Text"), ICON_NONE);
if (txt_has_sel(text)) {
uiItemO(layout, NULL, ICON_NONE, "TEXT_OT_cut");
uiItemO(layout, NULL, ICON_NONE, "TEXT_OT_copy");
@@ -153,13 +152,13 @@ void TEXT_OT_start_find(wmOperatorType *ot)
uiItemO(layout, NULL, ICON_NONE, "TEXT_OT_save");
uiItemO(layout, NULL, ICON_NONE, "TEXT_OT_save_as");
uiItemO(layout, NULL, ICON_NONE, "TEXT_OT_run_script");
- uiPupMenuEnd(C, pup);
+ UI_popup_menu_end(C, pup);
}
else {
- pup = uiPupMenuBegin(C, IFACE_("File"), ICON_NONE);
+ pup = UI_popup_menu_begin(C, IFACE_("File"), ICON_NONE);
uiItemO(layout, NULL, ICON_NONE, "TEXT_OT_new");
uiItemO(layout, NULL, ICON_NONE, "TEXT_OT_open");
- uiPupMenuEnd(C, pup);
+ UI_popup_menu_end(C, pup);
}
}
@@ -168,11 +167,11 @@ void TEXT_OT_start_find(wmOperatorType *ot)
uiPopupMenu *pup;
- pup = uiPupMenuBegin(C, IFACE_("Edit"), ICON_NONE);
+ pup = UI_popup_menu_begin(C, IFACE_("Edit"), ICON_NONE);
uiItemO(layout, NULL, ICON_NONE, "TEXT_OT_cut");
uiItemO(layout, NULL, ICON_NONE, "TEXT_OT_copy");
uiItemO(layout, NULL, ICON_NONE, "TEXT_OT_paste");
- uiPupMenuEnd(C, pup);
+ UI_popup_menu_end(C, pup);
}
{
@@ -181,19 +180,19 @@ void TEXT_OT_start_find(wmOperatorType *ot)
uiPopupMenu *pup;
if (text) {
- pup = uiPupMenuBegin(C, IFACE_("Text"), ICON_NONE);
+ pup = UI_popup_menu_begin(C, IFACE_("Text"), ICON_NONE);
uiItemO(layout, NULL, ICON_NONE, "TEXT_OT_new");
uiItemO(layout, NULL, ICON_NONE, "TEXT_OT_open");
uiItemO(layout, NULL, ICON_NONE, "TEXT_OT_save");
uiItemO(layout, NULL, ICON_NONE, "TEXT_OT_save_as");
uiItemO(layout, NULL, ICON_NONE, "TEXT_OT_run_script");
- uiPupMenuEnd(C, pup);
+ UI_popup_menu_end(C, pup);
}
else {
- pup = uiPupMenuBegin(C, IFACE_("File"), ICON_NONE);
+ pup = UI_popup_menu_begin(C, IFACE_("File"), ICON_NONE);
uiItemO(layout, NULL, ICON_NONE, "TEXT_OT_new");
uiItemO(layout, NULL, ICON_NONE, "TEXT_OT_open");
- uiPupMenuEnd(C, pup);
+ UI_popup_menu_end(C, pup);
}
}
@@ -202,15 +201,15 @@ void TEXT_OT_start_find(wmOperatorType *ot)
uiPopupMenu *pup;
- pup = uiPupMenuBegin(C, IFACE_("Text"), ICON_NONE);
- uiItemEnumO(layout, "TEXT_OT_move", CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Top of File"),
+ pup = UI_popup_menu_begin(C, IFACE_("Text"), ICON_NONE);
+ uiItemEnumO(layout, "TEXT_OT_move", CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Top of File"),
0, "type", FILE_TOP);
- uiItemEnumO(layout, "TEXT_OT_move", CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Bottom of File"),
+ uiItemEnumO(layout, "TEXT_OT_move", CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Bottom of File"),
0, "type", FILE_BOTTOM);
- uiItemEnumO(layout, "TEXT_OT_move", CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Page Up"), 0, "type", PREV_PAGE);
- uiItemEnumO(layout, "TEXT_OT_move", CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Page Down"),
+ uiItemEnumO(layout, "TEXT_OT_move", CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Page Up"), 0, "type", PREV_PAGE);
+ uiItemEnumO(layout, "TEXT_OT_move", CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Page Down"),
0, "type", NEXT_PAGE);
- uiPupMenuEnd(C, pup);
+ UI_popup_menu_end(C, pup);
}
#endif
diff --git a/source/blender/editors/space_text/text_intern.h b/source/blender/editors/space_text/text_intern.h
index d4cd029dac0..7ae2617f375 100644
--- a/source/blender/editors/space_text/text_intern.h
+++ b/source/blender/editors/space_text/text_intern.h
@@ -34,15 +34,12 @@
/* internal exports only */
struct ARegion;
-struct ARegionType;
struct bContext;
-struct ReportList;
struct ScrArea;
struct SpaceText;
struct Text;
struct TextLine;
struct wmOperatorType;
-struct wmWindowManager;
/* text_draw.c */
void draw_text_main(struct SpaceText *st, struct ARegion *ar);
@@ -50,7 +47,8 @@ void draw_text_main(struct SpaceText *st, struct ARegion *ar);
void text_update_line_edited(struct TextLine *line);
void text_update_edited(struct Text *text);
void text_update_character_width(struct SpaceText *st);
-void text_scroll_to_cursor(struct SpaceText *st, struct ScrArea *sa);
+void text_scroll_to_cursor(struct SpaceText *st, struct ARegion *ar, const bool center);
+void text_scroll_to_cursor__area(struct SpaceText *st, struct ScrArea *sa, const bool center);
void text_update_cursor_moved(struct bContext *C);
#define TXT_OFFSET ((int)(0.5f * U.widget_unit))
diff --git a/source/blender/editors/space_text/text_ops.c b/source/blender/editors/space_text/text_ops.c
index 852edaac7dc..a2fae2d5667 100644
--- a/source/blender/editors/space_text/text_ops.c
+++ b/source/blender/editors/space_text/text_ops.c
@@ -39,7 +39,7 @@
#include "BLI_blenlib.h"
-#include "BLF_translation.h"
+#include "BLT_translation.h"
#include "PIL_time.h"
@@ -171,7 +171,7 @@ static int text_new_exec(bContext *C, wmOperator *UNUSED(op))
text = BKE_text_add(bmain, "Text");
/* hook into UI */
- uiIDContextProperty(C, &ptr, &prop);
+ UI_context_active_but_prop_get_templateID(C, &ptr, &prop);
if (prop) {
RNA_id_pointer_create(&text->id, &idptr);
@@ -214,7 +214,7 @@ static void text_open_init(bContext *C, wmOperator *op)
PropertyPointerRNA *pprop;
op->customdata = pprop = MEM_callocN(sizeof(PropertyPointerRNA), "OpenPropertyPointerRNA");
- uiIDContextProperty(C, &pprop->ptr, &pprop->prop);
+ UI_context_active_but_prop_get_templateID(C, &pprop->ptr, &pprop->prop);
}
static void text_open_cancel(bContext *UNUSED(C), wmOperator *op)
@@ -300,8 +300,8 @@ void TEXT_OT_open(wmOperatorType *ot)
ot->flag = OPTYPE_UNDO;
/* properties */
- WM_operator_properties_filesel(ot, FOLDERFILE | TEXTFILE | PYSCRIPTFILE, FILE_SPECIAL, FILE_OPENFILE,
- WM_FILESEL_FILEPATH, FILE_DEFAULTDISPLAY); //XXX TODO, relative_path
+ WM_operator_properties_filesel(ot, FILE_TYPE_FOLDER | FILE_TYPE_TEXT | FILE_TYPE_PYSCRIPT, FILE_SPECIAL, FILE_OPENFILE,
+ WM_FILESEL_FILEPATH, FILE_DEFAULTDISPLAY, FILE_SORT_ALPHA); //XXX TODO, relative_path
RNA_def_boolean(ot->srna, "internal", 0, "Make internal", "Make text file internal after loading");
}
@@ -577,8 +577,8 @@ void TEXT_OT_save_as(wmOperatorType *ot)
ot->poll = text_edit_poll;
/* properties */
- WM_operator_properties_filesel(ot, FOLDERFILE | TEXTFILE | PYSCRIPTFILE, FILE_SPECIAL, FILE_SAVE,
- WM_FILESEL_FILEPATH, FILE_DEFAULTDISPLAY); //XXX TODO, relative_path
+ WM_operator_properties_filesel(ot, FILE_TYPE_FOLDER | FILE_TYPE_TEXT | FILE_TYPE_PYSCRIPT, FILE_SPECIAL, FILE_SAVE,
+ WM_FILESEL_FILEPATH, FILE_DEFAULTDISPLAY, FILE_SORT_ALPHA); //XXX TODO, relative_path
}
/******************* run script operator *********************/
@@ -714,88 +714,6 @@ void TEXT_OT_refresh_pyconstraints(wmOperatorType *ot)
/******************* paste operator *********************/
-static char *txt_copy_selected(Text *text)
-{
- TextLine *tmp, *linef, *linel;
- char *buf = NULL;
- int charf, charl, length = 0;
-
- if (!text) return NULL;
- if (!text->curl) return NULL;
- if (!text->sell) return NULL;
-
- if (!txt_has_sel(text)) return NULL;
-
- if (text->curl == text->sell) {
- linef = linel = text->curl;
-
- if (text->curc < text->selc) {
- charf = text->curc;
- charl = text->selc;
- }
- else {
- charf = text->selc;
- charl = text->curc;
- }
- }
- else if (txt_get_span(text->curl, text->sell) < 0) {
- linef = text->sell;
- linel = text->curl;
-
- charf = text->selc;
- charl = text->curc;
- }
- else {
- linef = text->curl;
- linel = text->sell;
-
- charf = text->curc;
- charl = text->selc;
- }
-
- if (linef == linel) {
- length = charl - charf;
-
- buf = MEM_callocN(length + 1, "cut buffera");
-
- BLI_strncpy(buf, linef->line + charf, length + 1);
- }
- else {
- length += linef->len - charf;
- length += charl;
- length++; /* For the '\n' */
-
- tmp = linef->next;
- while (tmp && tmp != linel) {
- length += tmp->len + 1;
- tmp = tmp->next;
- }
-
- buf = MEM_callocN(length + 1, "cut bufferb");
-
- strncpy(buf, linef->line + charf, linef->len - charf);
- length = linef->len - charf;
-
- buf[length++] = '\n';
-
- tmp = linef->next;
- while (tmp && tmp != linel) {
- strncpy(buf + length, tmp->line, tmp->len);
- length += tmp->len;
-
- buf[length++] = '\n';
-
- tmp = tmp->next;
- }
- strncpy(buf + length, linel->line, charl);
- length += charl;
-
- buf[length] = 0;
- }
-
- return buf;
-}
-
static int text_paste_exec(bContext *C, wmOperator *op)
{
const bool selection = RNA_boolean_get(op->ptr, "selection");
@@ -876,7 +794,10 @@ static void txt_copy_clipboard(Text *text)
{
char *buf;
- buf = txt_copy_selected(text);
+ if (!txt_has_sel(text))
+ return;
+
+ buf = txt_sel_to_buf(text);
if (buf) {
WM_clipboard_text_set(buf, 0);
@@ -2000,7 +1921,7 @@ void TEXT_OT_jump(wmOperatorType *ot)
/* properties */
prop = RNA_def_int(ot->srna, "line", 1, 1, INT_MAX, "Line", "Line number to jump to", 1, 10000);
- RNA_def_property_translation_context(prop, BLF_I18NCONTEXT_ID_TEXT);
+ RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_TEXT);
}
/******************* delete operator **********************/
@@ -2312,7 +2233,7 @@ void TEXT_OT_scroll(wmOperatorType *ot)
ot->poll = text_scroll_poll;
/* flags */
- ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_POINTER | OPTYPE_INTERNAL;
+ ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_CURSOR | OPTYPE_INTERNAL;
/* properties */
RNA_def_int(ot->srna, "lines", 1, INT_MIN, INT_MAX, "Lines", "Number of lines to scroll", -100, 100);
@@ -2415,6 +2336,7 @@ typedef struct SetSelection {
int selecting;
int selc, sell;
short old[2];
+ wmTimer *timer; /* needed for scrolling when mouse at region bounds */
} SetSelection;
static int flatten_width(SpaceText *st, const char *str)
@@ -2615,10 +2537,14 @@ static void text_cursor_set_to_pos(SpaceText *st, ARegion *ar, int x, int y, con
y -= txt_get_span(text->lines.first, *linep) - st->top;
if (y > 0) {
- while (y-- != 0) if ((*linep)->next) *linep = (*linep)->next;
+ while (y-- != 0) {
+ if ((*linep)->next) *linep = (*linep)->next;
+ }
}
else if (y < 0) {
- while (y++ != 0) if ((*linep)->prev) *linep = (*linep)->prev;
+ while (y++ != 0) {
+ if ((*linep)->prev) *linep = (*linep)->prev;
+ }
}
@@ -2629,6 +2555,29 @@ static void text_cursor_set_to_pos(SpaceText *st, ARegion *ar, int x, int y, con
if (!sel) txt_pop_sel(text);
}
+static void text_cursor_timer_ensure(bContext *C, SetSelection *ssel)
+{
+ if (ssel->timer == NULL) {
+ wmWindowManager *wm = CTX_wm_manager(C);
+ wmWindow *win = CTX_wm_window(C);
+
+ ssel->timer = WM_event_add_timer(wm, win, TIMER, 0.02f);
+ }
+}
+
+static void text_cursor_timer_remove(bContext *C, SetSelection *ssel)
+{
+ if (ssel->timer) {
+ wmWindowManager *wm = CTX_wm_manager(C);
+ wmWindow *win = CTX_wm_window(C);
+
+ WM_event_remove_timer(wm, win, ssel->timer);
+ }
+ ssel->timer = NULL;
+}
+
+
+
static void text_cursor_set_apply(bContext *C, wmOperator *op, const wmEvent *event)
{
SpaceText *st = CTX_wm_space_text(C);
@@ -2636,32 +2585,34 @@ static void text_cursor_set_apply(bContext *C, wmOperator *op, const wmEvent *ev
SetSelection *ssel = op->customdata;
if (event->mval[1] < 0 || event->mval[1] > ar->winy) {
- int d = (ssel->old[1] - event->mval[1]) * st->pix_per_line;
- if (d) txt_screen_skip(st, ar, d);
-
- text_cursor_set_to_pos(st, ar, event->mval[0], event->mval[1] < 0 ? 0 : ar->winy, 1);
+ text_cursor_timer_ensure(C, ssel);
- text_update_cursor_moved(C);
- WM_event_add_notifier(C, NC_TEXT | ND_CURSOR, st->text);
+ if (event->type == TIMER) {
+ text_cursor_set_to_pos(st, ar, event->mval[0], event->mval[1], 1);
+ text_scroll_to_cursor(st, ar, false);
+ WM_event_add_notifier(C, NC_TEXT | ND_CURSOR, st->text);
+ }
}
else if (!st->wordwrap && (event->mval[0] < 0 || event->mval[0] > ar->winx)) {
- if (event->mval[0] > ar->winx) st->left++;
- else if (event->mval[0] < 0 && st->left > 0) st->left--;
-
- text_cursor_set_to_pos(st, ar, event->mval[0], event->mval[1], 1);
+ text_cursor_timer_ensure(C, ssel);
- text_update_cursor_moved(C);
- WM_event_add_notifier(C, NC_TEXT | ND_CURSOR, st->text);
- // XXX PIL_sleep_ms(10);
+ if (event->type == TIMER) {
+ text_cursor_set_to_pos(st, ar, CLAMPIS(event->mval[0], 0, ar->winx), event->mval[1], 1);
+ text_scroll_to_cursor(st, ar, false);
+ WM_event_add_notifier(C, NC_TEXT | ND_CURSOR, st->text);
+ }
}
else {
- text_cursor_set_to_pos(st, ar, event->mval[0], event->mval[1], 1);
+ text_cursor_timer_remove(C, ssel);
- text_update_cursor_moved(C);
- WM_event_add_notifier(C, NC_TEXT | ND_CURSOR, st->text);
+ if (event->type != TIMER) {
+ text_cursor_set_to_pos(st, ar, event->mval[0], event->mval[1], 1);
+ text_scroll_to_cursor(st, ar, false);
+ WM_event_add_notifier(C, NC_TEXT | ND_CURSOR, st->text);
- ssel->old[0] = event->mval[0];
- ssel->old[1] = event->mval[1];
+ ssel->old[0] = event->mval[0];
+ ssel->old[1] = event->mval[1];
+ }
}
}
@@ -2681,6 +2632,7 @@ static void text_cursor_set_exit(bContext *C, wmOperator *op)
text_update_cursor_moved(C);
WM_event_add_notifier(C, NC_TEXT | ND_CURSOR, st->text);
+ text_cursor_timer_remove(C, ssel);
MEM_freeN(ssel);
}
@@ -2717,6 +2669,7 @@ static int text_set_selection_modal(bContext *C, wmOperator *op, const wmEvent *
case RIGHTMOUSE:
text_cursor_set_exit(C, op);
return OPERATOR_FINISHED;
+ case TIMER:
case MOUSEMOVE:
text_cursor_set_apply(C, op, event);
break;
@@ -2970,7 +2923,7 @@ static int text_find_and_replace(bContext *C, wmOperator *op, short mode)
if (mode != TEXT_FIND && txt_has_sel(text)) {
tmp = txt_sel_to_buf(text);
- if (flags & ST_MATCH_CASE) found = strcmp(st->findstr, tmp) == 0;
+ if (flags & ST_MATCH_CASE) found = STREQ(st->findstr, tmp);
else found = BLI_strcasecmp(st->findstr, tmp) == 0;
if (found) {
@@ -3144,36 +3097,36 @@ static int text_resolve_conflict_invoke(bContext *C, wmOperator *op, const wmEve
case 1:
if (text->flags & TXT_ISDIRTY) {
/* modified locally and externally, ahhh. offer more possibilites. */
- pup = uiPupMenuBegin(C, IFACE_("File Modified Outside and Inside Blender"), ICON_NONE);
- layout = uiPupMenuLayout(pup);
+ pup = UI_popup_menu_begin(C, IFACE_("File Modified Outside and Inside Blender"), ICON_NONE);
+ layout = UI_popup_menu_layout(pup);
uiItemEnumO_ptr(layout, op->type, IFACE_("Reload from disk (ignore local changes)"),
0, "resolution", RESOLVE_RELOAD);
uiItemEnumO_ptr(layout, op->type, IFACE_("Save to disk (ignore outside changes)"),
0, "resolution", RESOLVE_SAVE);
uiItemEnumO_ptr(layout, op->type, IFACE_("Make text internal (separate copy)"),
0, "resolution", RESOLVE_MAKE_INTERNAL);
- uiPupMenuEnd(C, pup);
+ UI_popup_menu_end(C, pup);
}
else {
- pup = uiPupMenuBegin(C, IFACE_("File Modified Outside Blender"), ICON_NONE);
- layout = uiPupMenuLayout(pup);
+ pup = UI_popup_menu_begin(C, IFACE_("File Modified Outside Blender"), ICON_NONE);
+ layout = UI_popup_menu_layout(pup);
uiItemEnumO_ptr(layout, op->type, IFACE_("Reload from disk"), 0, "resolution", RESOLVE_RELOAD);
uiItemEnumO_ptr(layout, op->type, IFACE_("Make text internal (separate copy)"),
0, "resolution", RESOLVE_MAKE_INTERNAL);
uiItemEnumO_ptr(layout, op->type, IFACE_("Ignore"), 0, "resolution", RESOLVE_IGNORE);
- uiPupMenuEnd(C, pup);
+ UI_popup_menu_end(C, pup);
}
break;
case 2:
- pup = uiPupMenuBegin(C, IFACE_("File Deleted Outside Blender"), ICON_NONE);
- layout = uiPupMenuLayout(pup);
+ pup = UI_popup_menu_begin(C, IFACE_("File Deleted Outside Blender"), ICON_NONE);
+ layout = UI_popup_menu_layout(pup);
uiItemEnumO_ptr(layout, op->type, IFACE_("Make text internal"), 0, "resolution", RESOLVE_MAKE_INTERNAL);
uiItemEnumO_ptr(layout, op->type, IFACE_("Recreate file"), 0, "resolution", RESOLVE_SAVE);
- uiPupMenuEnd(C, pup);
+ UI_popup_menu_end(C, pup);
break;
}
- return OPERATOR_CANCELLED;
+ return OPERATOR_INTERFACE;
}
void TEXT_OT_resolve_conflict(wmOperatorType *ot)
diff --git a/source/blender/editors/space_time/CMakeLists.txt b/source/blender/editors/space_time/CMakeLists.txt
index b42ae3ab725..90af405eaa8 100644
--- a/source/blender/editors/space_time/CMakeLists.txt
+++ b/source/blender/editors/space_time/CMakeLists.txt
@@ -22,10 +22,12 @@ set(INC
../include
../../blenkernel
../../blenlib
+ ../../gpu
../../makesdna
../../makesrna
../../windowmanager
../../../../intern/guardedalloc
+ ../../../../intern/glew-mx
)
set(INC_SYS
@@ -39,4 +41,6 @@ set(SRC
time_intern.h
)
+add_definitions(${GL_DEFINITIONS})
+
blender_add_lib(bf_editor_space_time "${SRC}" "${INC}" "${INC_SYS}")
diff --git a/source/blender/editors/space_time/SConscript b/source/blender/editors/space_time/SConscript
index bf1b918f4f1..86437b9c258 100644
--- a/source/blender/editors/space_time/SConscript
+++ b/source/blender/editors/space_time/SConscript
@@ -31,15 +31,18 @@ sources = env.Glob('*.c')
incs = [
'#/intern/guardedalloc',
- '#/extern/glew/include',
+ env['BF_GLEW_INC'],
+ '#/intern/glew-mx',
'../include',
'../../blenkernel',
'../../blenlib',
+ '../../gpu',
'../../makesdna',
'../../makesrna',
'../../windowmanager',
]
defs = []
+defs += env['BF_GL_DEFINITIONS']
env.BlenderLib('bf_editors_space_time', sources, incs, defs, libtype=['core'], priority=[65])
diff --git a/source/blender/editors/space_time/space_time.c b/source/blender/editors/space_time/space_time.c
index 88c57d45b79..9ecea7462ff 100644
--- a/source/blender/editors/space_time/space_time.c
+++ b/source/blender/editors/space_time/space_time.c
@@ -32,6 +32,7 @@
#include <string.h>
#include <stdio.h>
+#include "DNA_gpencil_types.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
@@ -57,6 +58,7 @@
#include "UI_resources.h"
#include "UI_view2d.h"
+#include "UI_interface.h"
#include "ED_space_api.h"
#include "ED_markers.h"
@@ -89,13 +91,12 @@ static void time_draw_sfra_efra(Scene *scene, View2D *v2d)
fdrawline((float)PEFRA, v2d->cur.ymin, (float)PEFRA, v2d->cur.ymax);
}
-#define CACHE_DRAW_HEIGHT 3.0f
-
static void time_draw_cache(SpaceTime *stime, Object *ob, Scene *scene)
{
PTCacheID *pid;
ListBase pidlist;
SpaceTimeCache *stc = stime->caches.first;
+ const float cache_draw_height = (4.0f * UI_DPI_FAC * U.pixelsize);
float yoffs = 0.f;
if (!(stime->cache_display & TIME_CACHE_DISPLAY) || (!ob))
@@ -171,7 +172,7 @@ static void time_draw_cache(SpaceTime *stime, Object *ob, Scene *scene)
glPushMatrix();
glTranslatef(0.0, (float)V2D_SCROLL_HEIGHT + yoffs, 0.0);
- glScalef(1.0, CACHE_DRAW_HEIGHT, 0.0);
+ glScalef(1.0, cache_draw_height, 0.0);
switch (pid->type) {
case PTCACHE_TYPE_SOFTBODY:
@@ -229,7 +230,7 @@ static void time_draw_cache(SpaceTime *stime, Object *ob, Scene *scene)
glPopMatrix();
- yoffs += CACHE_DRAW_HEIGHT;
+ yoffs += cache_draw_height;
stc = stc->next;
}
@@ -295,13 +296,19 @@ static void time_draw_idblock_keyframes(View2D *v2d, ID *id, short onlysel)
DLRBT_Tree keys;
ActKeyColumn *ak;
+ float fac1 = (GS(id->name) == ID_GD) ? 0.8f : 0.6f; /* draw GPencil keys taller, to help distinguish them */
+ float fac2 = 1.0f - fac1;
+
+ float ymin = v2d->tot.ymin;
+ float ymax = v2d->tot.ymax * fac1 + ymin * fac2;
+
/* init binarytree-list for getting keyframes */
BLI_dlrbTree_init(&keys);
/* init dopesheet settings */
if (onlysel)
ads.filterflag |= ADS_FILTER_ONLYSEL;
-
+
/* populate tree with keyframe nodes */
switch (GS(id->name)) {
case ID_SCE:
@@ -310,6 +317,9 @@ static void time_draw_idblock_keyframes(View2D *v2d, ID *id, short onlysel)
case ID_OB:
ob_to_keylist(&ads, (Object *)id, &keys, NULL);
break;
+ case ID_GD:
+ gpencil_to_keylist(&ads, (bGPdata *)id, &keys);
+ break;
}
/* build linked-list for searching */
@@ -325,8 +335,8 @@ static void time_draw_idblock_keyframes(View2D *v2d, ID *id, short onlysel)
(ak) && (ak->cfra <= v2d->cur.xmax);
ak = ak->next)
{
- glVertex2f(ak->cfra, v2d->tot.ymin);
- glVertex2f(ak->cfra, v2d->tot.ymax);
+ glVertex2f(ak->cfra, ymin);
+ glVertex2f(ak->cfra, ymax);
}
glEnd(); // GL_LINES
@@ -339,16 +349,23 @@ static void time_draw_keyframes(const bContext *C, ARegion *ar)
{
Scene *scene = CTX_data_scene(C);
Object *ob = CTX_data_active_object(C);
+ bGPdata *gpd = CTX_data_gpencil_data(C);
View2D *v2d = &ar->v2d;
bool onlysel = ((scene->flag & SCE_KEYS_NO_SELONLY) == 0);
+ /* draw grease pencil keyframes (if available) */
+ if (gpd) {
+ UI_ThemeColor(TH_TIME_GP_KEYFRAME);
+ time_draw_idblock_keyframes(v2d, (ID *)gpd, onlysel);
+ }
+
/* draw scene keyframes first
* - don't try to do this when only drawing active/selected data keyframes,
* since this can become quite slow
*/
if (onlysel == 0) {
/* set draw color */
- glColor3ub(0xDD, 0xA7, 0x00);
+ UI_ThemeColorShade(TH_TIME_KEYFRAME, -50);
time_draw_idblock_keyframes(v2d, (ID *)scene, onlysel);
}
@@ -357,7 +374,7 @@ static void time_draw_keyframes(const bContext *C, ARegion *ar)
* OR the onlysel flag was set, which means that only active object's keyframes should
* be considered
*/
- glColor3ub(0xDD, 0xD7, 0x00);
+ UI_ThemeColor(TH_TIME_KEYFRAME);
if (ob && ((ob->mode == OB_MODE_POSE) || onlysel)) {
/* draw keyframes for active object only */
@@ -520,7 +537,7 @@ static void time_main_area_draw(const bContext *C, ARegion *ar)
/* markers */
UI_view2d_view_orthoSpecial(ar, v2d, 1);
- draw_markers_time(C, 0);
+ ED_markers_draw(C, 0);
/* caches */
time_draw_cache(stime, obact, scene);
diff --git a/source/blender/editors/space_time/time_intern.h b/source/blender/editors/space_time/time_intern.h
index ce52cbbd65e..ced36b2ac2d 100644
--- a/source/blender/editors/space_time/time_intern.h
+++ b/source/blender/editors/space_time/time_intern.h
@@ -34,7 +34,6 @@
/* internal exports only */
-struct wmWindowManager;
/* time_ops.c */
void time_operatortypes(void);
diff --git a/source/blender/editors/space_userpref/space_userpref.c b/source/blender/editors/space_userpref/space_userpref.c
index 0bd094b6a33..b5a6821d147 100644
--- a/source/blender/editors/space_userpref/space_userpref.c
+++ b/source/blender/editors/space_userpref/space_userpref.c
@@ -47,9 +47,7 @@
#include "WM_api.h"
#include "WM_types.h"
-#include "UI_view2d.h"
-#include "userpref_intern.h" // own include
/* ******************** default callbacks for userpref space ***************** */
@@ -115,7 +113,7 @@ static void userpref_main_area_init(wmWindowManager *wm, ARegion *ar)
static void userpref_main_area_draw(const bContext *C, ARegion *ar)
{
- ED_region_panels(C, ar, 1, NULL, -1);
+ ED_region_panels(C, ar, NULL, -1, true);
}
static void userpref_operatortypes(void)
diff --git a/source/blender/editors/space_userpref/userpref_ops.c b/source/blender/editors/space_userpref/userpref_ops.c
index 8dd6c3c0271..0783eacc65c 100644
--- a/source/blender/editors/space_userpref/userpref_ops.c
+++ b/source/blender/editors/space_userpref/userpref_ops.c
@@ -32,5 +32,4 @@
#include <string.h>
#include <stdio.h>
-#include "userpref_intern.h"
diff --git a/source/blender/editors/space_view3d/CMakeLists.txt b/source/blender/editors/space_view3d/CMakeLists.txt
index 97c328dbac2..059b384a9e2 100644
--- a/source/blender/editors/space_view3d/CMakeLists.txt
+++ b/source/blender/editors/space_view3d/CMakeLists.txt
@@ -23,6 +23,7 @@ set(INC
../../blenfont
../../blenkernel
../../blenlib
+ ../../blentranslation
../../bmesh
../../gpu
../../imbuf
@@ -30,7 +31,9 @@ set(INC
../../makesrna
../../render/extern/include
../../windowmanager
+ ../../depsgraph
../../../../intern/guardedalloc
+ ../../../../intern/glew-mx
../../../../intern/smoke/extern
)
@@ -43,6 +46,7 @@ set(SRC
drawarmature.c
drawmesh.c
drawobject.c
+ drawsimdebug.c
drawvolume.c
space_view3d.c
view3d_buttons.c
@@ -76,7 +80,7 @@ if(WITH_GAMEENGINE)
add_definitions(-DWITH_GAMEENGINE)
endif()
-add_definitions(-DGLEW_STATIC)
+add_definitions(${GL_DEFINITIONS})
if(WITH_INTERNATIONAL)
add_definitions(-DWITH_INTERNATIONAL)
@@ -86,4 +90,8 @@ if(WITH_FREESTYLE)
add_definitions(-DWITH_FREESTYLE)
endif()
+if(WITH_LEGACY_DEPSGRAPH)
+ add_definitions(-DWITH_LEGACY_DEPSGRAPH)
+endif()
+
blender_add_lib(bf_editor_space_view3d "${SRC}" "${INC}" "${INC_SYS}")
diff --git a/source/blender/editors/space_view3d/SConscript b/source/blender/editors/space_view3d/SConscript
index e6658ab3c49..7fdccce1c0e 100644
--- a/source/blender/editors/space_view3d/SConscript
+++ b/source/blender/editors/space_view3d/SConscript
@@ -28,17 +28,21 @@
Import ('env')
sources = env.Glob('*.c')
-defs = [ 'GLEW_STATIC' ]
+
+defs = []
+defs += env['BF_GL_DEFINITIONS']
incs = [
'#/intern/guardedalloc',
- '#/extern/glew/include',
+ env['BF_GLEW_INC'],
+ '#/intern/glew-mx',
'#/intern/smoke/extern',
'#/source/gameengine/BlenderRoutines',
'../include',
'../../blenfont',
'../../blenkernel',
'../../blenlib',
+ '../../blentranslation',
'../../bmesh',
'../../gpu',
'../../imbuf',
@@ -46,6 +50,7 @@ incs = [
'../../makesrna',
'../../render/extern/include',
'../../windowmanager',
+ '../../depsgraph',
]
if env['WITH_BF_PYTHON']:
@@ -63,4 +68,7 @@ if env['WITH_BF_INTERNATIONAL']:
if env['WITH_BF_FREESTYLE']:
defs.append('WITH_FREESTYLE')
+if env['WITH_BF_LEGACY_DEPSGRAPH']:
+ defs.append('WITH_LEGACY_DEPSGRAPH')
+
env.BlenderLib ( 'bf_editors_space_view3d', sources, incs, defines = defs, libtype=['core'], priority=[40] )
diff --git a/source/blender/editors/space_view3d/drawanimviz.c b/source/blender/editors/space_view3d/drawanimviz.c
index 17f90fc54e3..d753ad68fcc 100644
--- a/source/blender/editors/space_view3d/drawanimviz.c
+++ b/source/blender/editors/space_view3d/drawanimviz.c
@@ -51,10 +51,8 @@
#include "BIF_gl.h"
-#include "ED_armature.h"
#include "ED_keyframes_draw.h"
-#include "BLF_api.h"
#include "UI_resources.h"
diff --git a/source/blender/editors/space_view3d/drawarmature.c b/source/blender/editors/space_view3d/drawarmature.c
index dfa373f111f..f7698b0e9f3 100644
--- a/source/blender/editors/space_view3d/drawarmature.c
+++ b/source/blender/editors/space_view3d/drawarmature.c
@@ -61,7 +61,6 @@
#include "ED_armature.h"
#include "ED_keyframes_draw.h"
-#include "BLF_api.h"
#include "UI_resources.h"
@@ -1548,7 +1547,7 @@ static void draw_pose_dofs(Object *ob)
glPushMatrix();
copy_v3_v3(posetrans, pchan->pose_mat[3]);
- glTranslatef(posetrans[0], posetrans[1], posetrans[2]);
+ glTranslate3fv(posetrans);
if (pchan->parent) {
copy_m4_m4(mat, pchan->parent->pose_mat);
@@ -1620,7 +1619,7 @@ static void draw_pose_dofs(Object *ob)
for (a = -16; a <= 16; a++) {
/* *0.5f here comes from M_PI/360.0f when rotations were still in degrees */
float fac = ((float)a) / 16.0f * 0.5f;
- phi = (float)(0.5 * M_PI) + fac * (pchan->limitmax[0] - pchan->limitmin[0]);
+ phi = (float)M_PI_2 + fac * (pchan->limitmax[0] - pchan->limitmin[0]);
i = (a == -16) ? 2 : 3;
corner[i][0] = 0.0f;
@@ -1779,7 +1778,7 @@ static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, Base *base,
}
draw_custom_bone(scene, v3d, rv3d, pchan->custom,
- OB_SOLID, arm->flag, flag, index, bone->length);
+ OB_SOLID, arm->flag, flag, index, PCHAN_CUSTOM_DRAW_SIZE(pchan));
}
}
else {
@@ -1870,7 +1869,7 @@ static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, Base *base,
flag |= BONE_DRAW_ACTIVE;
draw_custom_bone(scene, v3d, rv3d, pchan->custom,
- OB_WIRE, arm->flag, flag, index, bone->length);
+ OB_WIRE, arm->flag, flag, index, PCHAN_CUSTOM_DRAW_SIZE(pchan));
glPopMatrix();
}
@@ -2088,6 +2087,10 @@ static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, Base *base,
if (v3d->zbuf) glEnable(GL_DEPTH_TEST);
}
}
+
+ if (index != -1) {
+ GPU_select_load_id(-1);
+ }
}
/* in editmode, we don't store the bone matrix... */
@@ -2363,7 +2366,7 @@ static void draw_ghost_poses_range(Scene *scene, View3D *v3d, ARegion *ar, Base
bArmature *arm = ob->data;
bPose *posen, *poseo;
float start, end, stepsize, range, colfac;
- int cfrao, flago, ipoflago;
+ int cfrao, flago;
start = (float)arm->ghostsf;
end = (float)arm->ghostef;
@@ -2378,8 +2381,6 @@ static void draw_ghost_poses_range(Scene *scene, View3D *v3d, ARegion *ar, Base
cfrao = CFRA;
flago = arm->flag;
arm->flag &= ~(ARM_DRAWNAMES | ARM_DRAWAXES);
- ipoflago = ob->ipoflag;
- ob->ipoflag |= OB_DISABLE_PATH;
/* copy the pose */
poseo = ob->pose;
@@ -2392,7 +2393,7 @@ static void draw_ghost_poses_range(Scene *scene, View3D *v3d, ARegion *ar, Base
if (v3d->zbuf) glDisable(GL_DEPTH_TEST);
/* draw from first frame of range to last */
- for (CFRA = (int)start; CFRA < end; CFRA += (int)stepsize) {
+ for (CFRA = (int)start; CFRA <= end; CFRA += (int)stepsize) {
colfac = (end - (float)CFRA) / range;
UI_ThemeColorShadeAlpha(TH_WIRE, 0, -128 - (int)(120.0f * sqrtf(colfac)));
@@ -2415,7 +2416,6 @@ static void draw_ghost_poses_range(Scene *scene, View3D *v3d, ARegion *ar, Base
ob->pose = poseo;
arm->flag = flago;
ob->mode |= OB_MODE_POSE;
- ob->ipoflag = ipoflago;
}
/* draw ghosts on keyframes in action within range
@@ -2459,8 +2459,7 @@ static void draw_ghost_poses_keys(Scene *scene, View3D *v3d, ARegion *ar, Base *
cfrao = CFRA;
flago = arm->flag;
arm->flag &= ~(ARM_DRAWNAMES | ARM_DRAWAXES);
- ob->ipoflag |= OB_DISABLE_PATH;
-
+
/* copy the pose */
poseo = ob->pose;
BKE_pose_copy_data(&posen, ob->pose, 1);
diff --git a/source/blender/editors/space_view3d/drawmesh.c b/source/blender/editors/space_view3d/drawmesh.c
index fb97a6ac9f4..d806dfa015a 100644
--- a/source/blender/editors/space_view3d/drawmesh.c
+++ b/source/blender/editors/space_view3d/drawmesh.c
@@ -60,7 +60,6 @@
#include "UI_resources.h"
-#include "GPU_buffers.h"
#include "GPU_extensions.h"
#include "GPU_draw.h"
#include "GPU_material.h"
@@ -80,15 +79,15 @@ typedef struct drawMeshFaceSelect_userData {
typedef struct drawEMTFMapped_userData {
BMEditMesh *em;
bool has_mcol;
- bool has_mtface;
- MFace *mf;
- MTFace *tf;
+ int cd_poly_tex_offset;
+ const MPoly *mpoly;
+ const MTexPoly *mtexpoly;
} drawEMTFMapped_userData;
typedef struct drawTFace_userData {
- Mesh *me;
- MFace *mf;
- MTFace *tf;
+ const Mesh *me;
+ const MPoly *mpoly;
+ const MTexPoly *mtexpoly;
} drawTFace_userData;
/**************************** Face Select Mode *******************************/
@@ -97,7 +96,7 @@ typedef struct drawTFace_userData {
BLI_INLINE int edge_vis_index(const int index) { return index * 2; }
BLI_INLINE int edge_sel_index(const int index) { return index * 2 + 1; }
-static BLI_bitmap *get_tface_mesh_marked_edge_info(Mesh *me)
+static BLI_bitmap *get_tface_mesh_marked_edge_info(Mesh *me, bool draw_select_edges)
{
BLI_bitmap *bitmap_edge_flags = BLI_BITMAP_NEW(me->totedge * 2, __func__);
MPoly *mp;
@@ -113,8 +112,17 @@ static BLI_bitmap *get_tface_mesh_marked_edge_info(Mesh *me)
ml = me->mloop + mp->loopstart;
for (j = 0; j < mp->totloop; j++, ml++) {
- BLI_BITMAP_ENABLE(bitmap_edge_flags, edge_vis_index(ml->e));
- if (select_set) BLI_BITMAP_ENABLE(bitmap_edge_flags, edge_sel_index(ml->e));
+ if ((draw_select_edges == false) &&
+ (select_set && BLI_BITMAP_TEST(bitmap_edge_flags, edge_sel_index(ml->e))))
+ {
+ BLI_BITMAP_DISABLE(bitmap_edge_flags, edge_vis_index(ml->e));
+ }
+ else {
+ BLI_BITMAP_ENABLE(bitmap_edge_flags, edge_vis_index(ml->e));
+ if (select_set) {
+ BLI_BITMAP_ENABLE(bitmap_edge_flags, edge_sel_index(ml->e));
+ }
+ }
}
}
}
@@ -129,21 +137,26 @@ static DMDrawOption draw_mesh_face_select__setHiddenOpts(void *userData, int ind
Mesh *me = data->me;
if (me->drawflag & ME_DRAWEDGES) {
- if ((me->drawflag & ME_HIDDENEDGES) || (BLI_BITMAP_TEST(data->edge_flags, edge_vis_index(index))))
+ if ((BLI_BITMAP_TEST(data->edge_flags, edge_vis_index(index))))
return DM_DRAW_OPTION_NORMAL;
else
return DM_DRAW_OPTION_SKIP;
}
- else if (BLI_BITMAP_TEST(data->edge_flags, edge_sel_index(index)))
+ else if (BLI_BITMAP_TEST(data->edge_flags, edge_sel_index(index)) &&
+ BLI_BITMAP_TEST(data->edge_flags, edge_vis_index(index)))
+ {
return DM_DRAW_OPTION_NORMAL;
- else
+ }
+ else {
return DM_DRAW_OPTION_SKIP;
+ }
}
static DMDrawOption draw_mesh_face_select__setSelectOpts(void *userData, int index)
{
drawMeshFaceSelect_userData *data = userData;
- return (BLI_BITMAP_TEST(data->edge_flags, edge_sel_index(index))) ? DM_DRAW_OPTION_NORMAL : DM_DRAW_OPTION_SKIP;
+ return (BLI_BITMAP_TEST(data->edge_flags, edge_sel_index(index)) &&
+ BLI_BITMAP_TEST(data->edge_flags, edge_vis_index(index))) ? DM_DRAW_OPTION_NORMAL : DM_DRAW_OPTION_SKIP;
}
/* draws unselected */
@@ -158,12 +171,12 @@ static DMDrawOption draw_mesh_face_select__drawFaceOptsInv(void *userData, int i
return DM_DRAW_OPTION_SKIP;
}
-void draw_mesh_face_select(RegionView3D *rv3d, Mesh *me, DerivedMesh *dm)
+void draw_mesh_face_select(RegionView3D *rv3d, Mesh *me, DerivedMesh *dm, bool draw_select_edges)
{
drawMeshFaceSelect_userData data;
data.me = me;
- data.edge_flags = get_tface_mesh_marked_edge_info(me);
+ data.edge_flags = get_tface_mesh_marked_edge_info(me, draw_select_edges);
glEnable(GL_DEPTH_TEST);
glDisable(GL_LIGHTING);
@@ -181,7 +194,7 @@ void draw_mesh_face_select(RegionView3D *rv3d, Mesh *me, DerivedMesh *dm)
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
/* dull unselected faces so as not to get in the way of seeing color */
glColor4ub(96, 96, 96, 64);
- dm->drawMappedFaces(dm, draw_mesh_face_select__drawFaceOptsInv, NULL, NULL, (void *)me, 0);
+ dm->drawMappedFaces(dm, draw_mesh_face_select__drawFaceOptsInv, NULL, NULL, (void *)me, DM_DRAW_SKIP_HIDDEN);
glDisable(GL_BLEND);
}
@@ -223,11 +236,11 @@ static struct TextureDrawState {
bool texpaint_material; /* use material slots for texture painting */
} Gtexdraw = {NULL, NULL, NULL, false, 0, 0, 0, false, {0, 0, 0, 0}, false, false};
-static bool set_draw_settings_cached(int clearcache, MTFace *texface, Material *ma, struct TextureDrawState gtexdraw)
+static bool set_draw_settings_cached(int clearcache, MTexPoly *texface, Material *ma, struct TextureDrawState gtexdraw)
{
static Material *c_ma;
static int c_textured;
- static MTFace c_texface;
+ static MTexPoly c_texface;
static int c_backculled;
static bool c_badtex;
static int c_lit;
@@ -251,7 +264,7 @@ static bool set_draw_settings_cached(int clearcache, MTFace *texface, Material *
if (clearcache) {
c_textured = c_lit = c_backculled = -1;
- memset(&c_texface, 0, sizeof(MTFace));
+ memset(&c_texface, 0, sizeof(c_texface));
c_badtex = false;
c_has_texface = -1;
c_ma = NULL;
@@ -279,10 +292,10 @@ static bool set_draw_settings_cached(int clearcache, MTFace *texface, Material *
if (!ma && BKE_image_has_alpha(texface->tpage))
alphablend = GPU_BLEND_ALPHA;
}
- else if (texpaint && ma) {
+ else if (texpaint) {
if (gtexdraw.texpaint_material)
- ima = ma->texpaintslot ? ma->texpaintslot[ma->paint_active_slot].ima : NULL;
- else
+ ima = ma && ma->texpaintslot ? ma->texpaintslot[ma->paint_active_slot].ima : NULL;
+ else
ima = gtexdraw.canvas;
}
else
@@ -315,6 +328,14 @@ static bool set_draw_settings_cached(int clearcache, MTFace *texface, Material *
glActiveTexture(GL_TEXTURE1);
glEnable(GL_TEXTURE_2D);
+ glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
+ glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_INTERPOLATE);
+ glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_RGB, GL_PREVIOUS);
+ glTexEnvi(GL_TEXTURE_ENV, GL_SRC1_RGB, GL_PRIMARY_COLOR);
+ glTexEnvi(GL_TEXTURE_ENV, GL_SRC2_RGB, GL_PREVIOUS);
+ glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB, GL_SRC_ALPHA);
+ glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_REPLACE);
+ glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_ALPHA, GL_PREVIOUS);
glBindTexture(GL_TEXTURE_2D, ima->bindcode);
glActiveTexture(GL_TEXTURE0);
}
@@ -513,7 +534,7 @@ static void draw_textured_end(void)
glPopMatrix();
}
-static DMDrawOption draw_tface__set_draw_legacy(MTFace *tface, const bool has_mcol, int matnr)
+static DMDrawOption draw_tface__set_draw_legacy(MTexPoly *mtexpoly, const bool has_mcol, int matnr)
{
Material *ma = give_current_material(Gtexdraw.ob, matnr + 1);
bool invalidtexture = false;
@@ -521,9 +542,9 @@ static DMDrawOption draw_tface__set_draw_legacy(MTFace *tface, const bool has_mc
if (ma && (ma->game.flag & GEMAT_INVISIBLE))
return DM_DRAW_OPTION_SKIP;
- invalidtexture = set_draw_settings_cached(0, tface, ma, Gtexdraw);
+ invalidtexture = set_draw_settings_cached(0, mtexpoly, ma, Gtexdraw);
- if (tface && invalidtexture) {
+ if (mtexpoly && invalidtexture) {
glColor3ub(0xFF, 0x00, 0xFF);
return DM_DRAW_OPTION_NO_MCOL; /* Don't set color */
}
@@ -532,7 +553,7 @@ static DMDrawOption draw_tface__set_draw_legacy(MTFace *tface, const bool has_mc
return DM_DRAW_OPTION_NO_MCOL; /* Don't set color */
}
else if (!has_mcol) {
- if (tface) {
+ if (mtexpoly) {
glColor3f(1.0, 1.0, 1.0);
}
else {
@@ -554,162 +575,173 @@ static DMDrawOption draw_tface__set_draw_legacy(MTFace *tface, const bool has_mc
}
}
-static DMDrawOption draw_mcol__set_draw_legacy(MTFace *UNUSED(tface), const bool has_mcol, int UNUSED(matnr))
-{
- if (has_mcol)
- return DM_DRAW_OPTION_NORMAL;
- else
- return DM_DRAW_OPTION_NO_MCOL;
-}
-
-static DMDrawOption draw_tface__set_draw(MTFace *tface, const bool UNUSED(has_mcol), int matnr)
+static DMDrawOption draw_tface__set_draw(MTexPoly *mtexpoly, const bool UNUSED(has_mcol), int matnr)
{
Material *ma = give_current_material(Gtexdraw.ob, matnr + 1);
- if (ma && (ma->game.flag & GEMAT_INVISIBLE)) return 0;
+ if (ma && (ma->game.flag & GEMAT_INVISIBLE)) return DM_DRAW_OPTION_SKIP;
- if (tface || Gtexdraw.is_texpaint)
- set_draw_settings_cached(0, tface, ma, Gtexdraw);
+ if (mtexpoly || Gtexdraw.is_texpaint)
+ set_draw_settings_cached(0, mtexpoly, ma, Gtexdraw);
/* always use color from mcol, as set in update_tface_color_layer */
return DM_DRAW_OPTION_NORMAL;
}
-static void update_tface_color_layer(DerivedMesh *dm)
+static void update_tface_color_layer(DerivedMesh *dm, bool use_mcol)
{
- MTFace *tface = DM_get_tessface_data_layer(dm, CD_MTFACE);
- MFace *mface = dm->getTessFaceArray(dm);
- MCol *finalCol;
+ const MPoly *mp = dm->getPolyArray(dm);
+ const int mpoly_num = dm->getNumPolys(dm);
+ MTexPoly *mtexpoly = DM_get_poly_data_layer(dm, CD_MTEXPOLY);
+ MLoopCol *finalCol;
int i, j;
- MCol *mcol = dm->getTessFaceDataArray(dm, CD_PREVIEW_MCOL);
- if (!mcol)
- mcol = dm->getTessFaceDataArray(dm, CD_MCOL);
+ MLoopCol *mloopcol = NULL;
+
+ /* cache material values to avoid a lot of lookups */
+ Material *ma = NULL;
+ short mat_nr_prev = -1;
+ enum {
+ COPY_CALC,
+ COPY_ORIG,
+ COPY_PREV,
+ } copy_mode = COPY_CALC;
+
+ if (use_mcol) {
+ mloopcol = dm->getLoopDataArray(dm, CD_PREVIEW_MLOOPCOL);
+ if (!mloopcol)
+ mloopcol = dm->getLoopDataArray(dm, CD_MLOOPCOL);
+ }
- if (CustomData_has_layer(&dm->faceData, CD_TEXTURE_MCOL)) {
- finalCol = CustomData_get_layer(&dm->faceData, CD_TEXTURE_MCOL);
+ if (CustomData_has_layer(&dm->loopData, CD_TEXTURE_MLOOPCOL)) {
+ finalCol = CustomData_get_layer(&dm->loopData, CD_TEXTURE_MLOOPCOL);
}
else {
- finalCol = MEM_mallocN(sizeof(MCol) * 4 * dm->getNumTessFaces(dm), "add_tface_color_layer");
-
- CustomData_add_layer(&dm->faceData, CD_TEXTURE_MCOL, CD_ASSIGN, finalCol, dm->numTessFaceData);
+ finalCol = MEM_mallocN(sizeof(MLoopCol) * dm->numLoopData, "add_tface_color_layer");
+ CustomData_add_layer(&dm->loopData, CD_TEXTURE_MLOOPCOL, CD_ASSIGN, finalCol, dm->numLoopData);
}
- for (i = 0; i < dm->getNumTessFaces(dm); i++) {
- Material *ma = give_current_material(Gtexdraw.ob, mface[i].mat_nr + 1);
-
- if (ma && (ma->game.flag & GEMAT_INVISIBLE)) {
- if (mcol)
- memcpy(&finalCol[i * 4], &mcol[i * 4], sizeof(MCol) * 4);
- else
- for (j = 0; j < 4; j++) {
- finalCol[i * 4 + j].b = 255;
- finalCol[i * 4 + j].g = 255;
- finalCol[i * 4 + j].r = 255;
- }
+ for (i = mpoly_num; i--; mp++) {
+ const short mat_nr = mp->mat_nr;
+
+ if (UNLIKELY(mat_nr_prev != mat_nr)) {
+ ma = give_current_material(Gtexdraw.ob, mat_nr + 1);
+ copy_mode = COPY_CALC;
+ mat_nr_prev = mat_nr;
+ }
+
+ /* avoid lookups */
+ if (copy_mode == COPY_ORIG) {
+ memcpy(&finalCol[mp->loopstart], &mloopcol[mp->loopstart], sizeof(*finalCol) * mp->totloop);
}
- else if (tface && set_draw_settings_cached(0, tface, ma, Gtexdraw)) {
- for (j = 0; j < 4; j++) {
- finalCol[i * 4 + j].b = 255;
- finalCol[i * 4 + j].g = 0;
- finalCol[i * 4 + j].r = 255;
+ else if (copy_mode == COPY_PREV) {
+ int loop_index = mp->loopstart;
+ const MLoopCol *lcol_prev = &finalCol[(mp - 1)->loopstart];
+ for (j = 0; j < mp->totloop; j++, loop_index++) {
+ finalCol[loop_index] = *lcol_prev;
}
}
+
+ /* (copy_mode == COPY_CALC) */
+ else if (ma && (ma->game.flag & GEMAT_INVISIBLE)) {
+ if (mloopcol) {
+ memcpy(&finalCol[mp->loopstart], &mloopcol[mp->loopstart], sizeof(*finalCol) * mp->totloop);
+ copy_mode = COPY_ORIG;
+ }
+ else {
+ memset(&finalCol[mp->loopstart], 0xff, sizeof(*finalCol) * mp->totloop);
+ copy_mode = COPY_PREV;
+ }
+ }
+ else if (mtexpoly && set_draw_settings_cached(0, mtexpoly, ma, Gtexdraw)) {
+ int loop_index = mp->loopstart;
+ for (j = 0; j < mp->totloop; j++, loop_index++) {
+ finalCol[loop_index].r = 255;
+ finalCol[loop_index].g = 0;
+ finalCol[loop_index].b = 255;
+ }
+ copy_mode = COPY_PREV;
+ }
else if (ma && (ma->shade_flag & MA_OBCOLOR)) {
- for (j = 0; j < 4; j++) {
- finalCol[i * 4 + j].b = Gtexdraw.obcol[0];
- finalCol[i * 4 + j].g = Gtexdraw.obcol[1];
- finalCol[i * 4 + j].r = Gtexdraw.obcol[2];
+ int loop_index = mp->loopstart;
+ for (j = 0; j < mp->totloop; j++, loop_index++) {
+ copy_v3_v3_char(&finalCol[loop_index].r, (char *)Gtexdraw.obcol);
}
+ copy_mode = COPY_PREV;
}
- else if (!mcol) {
- if (tface) {
- for (j = 0; j < 4; j++) {
- finalCol[i * 4 + j].b = 255;
- finalCol[i * 4 + j].g = 255;
- finalCol[i * 4 + j].r = 255;
- }
+ else {
+ if (mloopcol) {
+ memcpy(&finalCol[mp->loopstart], &mloopcol[mp->loopstart], sizeof(*finalCol) * mp->totloop);
+ copy_mode = COPY_ORIG;
+ }
+ else if (mtexpoly) {
+ memset(&finalCol[mp->loopstart], 0xff, sizeof(*finalCol) * mp->totloop);
+ copy_mode = COPY_PREV;
}
else {
float col[3];
if (ma) {
+ int loop_index = mp->loopstart;
+ MLoopCol lcol;
+
if (Gtexdraw.color_profile) linearrgb_to_srgb_v3_v3(col, &ma->r);
else copy_v3_v3(col, &ma->r);
+ rgb_float_to_uchar((unsigned char *)&lcol.r, col);
+ lcol.a = 255;
- for (j = 0; j < 4; j++) {
- finalCol[i * 4 + j].b = FTOCHAR(col[0]);
- finalCol[i * 4 + j].g = FTOCHAR(col[1]);
- finalCol[i * 4 + j].r = FTOCHAR(col[2]);
+ for (j = 0; j < mp->totloop; j++, loop_index++) {
+ finalCol[loop_index] = lcol;
}
}
- else
- for (j = 0; j < 4; j++) {
- finalCol[i * 4 + j].b = 255;
- finalCol[i * 4 + j].g = 255;
- finalCol[i * 4 + j].r = 255;
- }
- }
- }
- else {
- for (j = 0; j < 4; j++) {
- finalCol[i * 4 + j].r = mcol[i * 4 + j].r;
- finalCol[i * 4 + j].g = mcol[i * 4 + j].g;
- finalCol[i * 4 + j].b = mcol[i * 4 + j].b;
+ else {
+ memset(&finalCol[mp->loopstart], 0xff, sizeof(*finalCol) * mp->totloop);
+ }
+ copy_mode = COPY_PREV;
}
}
}
}
-static DMDrawOption draw_tface_mapped__set_draw(void *userData, int index)
+static DMDrawOption draw_tface_mapped__set_draw(void *userData, int origindex, int UNUSED(mat_nr))
{
- Mesh *me = ((drawTFace_userData *)userData)->me;
+ const Mesh *me = ((drawTFace_userData *)userData)->me;
/* array checked for NULL before calling */
- MPoly *mpoly = &me->mpoly[index];
+ MPoly *mpoly = &me->mpoly[origindex];
- BLI_assert(index >= 0 && index < me->totpoly);
+ BLI_assert(origindex >= 0 && origindex < me->totpoly);
if (mpoly->flag & ME_HIDE) {
return DM_DRAW_OPTION_SKIP;
}
else {
- MTexPoly *tpoly = (me->mtpoly) ? &me->mtpoly[index] : NULL;
- MTFace mtf = {{{0}}};
+ MTexPoly *tpoly = (me->mtpoly) ? &me->mtpoly[origindex] : NULL;
int matnr = mpoly->mat_nr;
-
- if (tpoly) {
- ME_MTEXFACE_CPY(&mtf, tpoly);
- }
-
- return draw_tface__set_draw(&mtf, (me->mloopcol != NULL), matnr);
+
+ return draw_tface__set_draw(tpoly, (me->mloopcol != NULL), matnr);
}
}
-static DMDrawOption draw_em_tf_mapped__set_draw(void *userData, int index)
+static DMDrawOption draw_em_tf_mapped__set_draw(void *userData, int origindex, int mat_nr)
{
drawEMTFMapped_userData *data = userData;
BMEditMesh *em = data->em;
BMFace *efa;
- if (UNLIKELY(index >= em->bm->totface))
+ if (UNLIKELY(origindex >= em->bm->totface))
return DM_DRAW_OPTION_NORMAL;
- efa = BM_face_at_index(em->bm, index);
+ efa = BM_face_at_index(em->bm, origindex);
if (BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) {
return DM_DRAW_OPTION_SKIP;
}
else {
- MTFace mtf = {{{0}}};
- int matnr = efa->mat_nr;
+ MTexPoly *mtexpoly = (data->cd_poly_tex_offset != -1) ?
+ BM_ELEM_CD_GET_VOID_P(efa, data->cd_poly_tex_offset) : NULL;
+ int matnr = (mat_nr != -1) ? mat_nr : efa->mat_nr;
- if (data->has_mtface) {
- MTexPoly *tpoly = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
- ME_MTEXFACE_CPY(&mtf, tpoly);
- }
-
- return draw_tface__set_draw_legacy(data->has_mtface ? &mtf : NULL,
- data->has_mcol, matnr);
+ return draw_tface__set_draw_legacy(mtexpoly, data->has_mcol, matnr);
}
}
@@ -741,7 +773,6 @@ static void draw_mesh_text(Scene *scene, Object *ob, int glsl)
/* fake values to pass to GPU_render_text() */
MCol tmp_mcol[4] = {{0}};
MCol *tmp_mcol_pt = mloopcol ? tmp_mcol : NULL;
- MTFace tmp_tf = {{{0}}};
/* don't draw without tfaces */
if (!mtpoly || !mloopuv)
@@ -758,7 +789,7 @@ static void draw_mesh_text(Scene *scene, Object *ob, int glsl)
for (a = 0, mp = mface; a < totpoly; a++, mtpoly++, mp++) {
short matnr = mp->mat_nr;
- int mf_smooth = mp->flag & ME_SMOOTH;
+ const bool mf_smooth = (mp->flag & ME_SMOOTH) != 0;
Material *mat = (me->mat) ? me->mat[matnr] : NULL;
int mode = mat ? mat->game.flag : GEMAT_INVISIBLE;
@@ -766,14 +797,14 @@ static void draw_mesh_text(Scene *scene, Object *ob, int glsl)
if (!(mode & GEMAT_INVISIBLE) && (mode & GEMAT_TEXT) && mp->totloop >= 3) {
/* get the polygon as a tri/quad */
int mp_vi[4];
- float v1[3], v2[3], v3[3], v4[3];
+ float v_quad_data[4][3];
+ const float *v_quad[4];
+ const float *uv_quad[4];
char string[MAX_PROPSTRING];
int characters, i, glattrib = -1, badtex = 0;
/* TEXFACE */
- ME_MTEXFACE_CPY(&tmp_tf, mtpoly);
-
if (glsl) {
GPU_enable_material(matnr + 1, &gattribs);
@@ -785,7 +816,7 @@ static void draw_mesh_text(Scene *scene, Object *ob, int glsl)
}
}
else {
- badtex = set_draw_settings_cached(0, &tmp_tf, mat, Gtexdraw);
+ badtex = set_draw_settings_cached(0, mtpoly, mat, Gtexdraw);
if (badtex) {
continue;
}
@@ -798,13 +829,17 @@ static void draw_mesh_text(Scene *scene, Object *ob, int glsl)
/* UV */
luv = &mloopuv[mp->loopstart];
- copy_v2_v2(tmp_tf.uv[0], luv->uv); luv++;
- copy_v2_v2(tmp_tf.uv[1], luv->uv); luv++;
- copy_v2_v2(tmp_tf.uv[2], luv->uv); luv++;
+ uv_quad[0] = luv->uv; luv++;
+ uv_quad[1] = luv->uv; luv++;
+ uv_quad[2] = luv->uv; luv++;
if (mp->totloop >= 4) {
- copy_v2_v2(tmp_tf.uv[3], luv->uv);
+ uv_quad[3] = luv->uv;
+ }
+ else {
+ uv_quad[3] = NULL;
}
+
/* COLOR */
if (mloopcol) {
unsigned int totloop_clamp = min_ii(4, mp->totloop);
@@ -817,13 +852,22 @@ static void draw_mesh_text(Scene *scene, Object *ob, int glsl)
}
/* LOCATION */
- ddm->getVertCo(ddm, mp_vi[0], v1);
- ddm->getVertCo(ddm, mp_vi[1], v2);
- ddm->getVertCo(ddm, mp_vi[2], v3);
+ ddm->getVertCo(ddm, mp_vi[0], v_quad_data[0]);
+ ddm->getVertCo(ddm, mp_vi[1], v_quad_data[1]);
+ ddm->getVertCo(ddm, mp_vi[2], v_quad_data[2]);
if (mp->totloop >= 4) {
- ddm->getVertCo(ddm, mp_vi[3], v4);
+ ddm->getVertCo(ddm, mp_vi[3], v_quad_data[3]);
}
+ v_quad[0] = v_quad_data[0];
+ v_quad[1] = v_quad_data[1];
+ v_quad[2] = v_quad_data[2];
+ if (mp->totloop >= 4) {
+ v_quad[3] = v_quad_data[2];
+ }
+ else {
+ v_quad[3] = NULL;
+ }
/* The BM_FONT handling is in the gpu module, shared with the
@@ -838,13 +882,16 @@ static void draw_mesh_text(Scene *scene, Object *ob, int glsl)
if (!mf_smooth) {
float nor[3];
- normal_tri_v3(nor, v1, v2, v3);
+ normal_tri_v3(nor, v_quad[0], v_quad[1], v_quad[2]);
glNormal3fv(nor);
}
- GPU_render_text(&tmp_tf, mode, string, characters,
- (unsigned int *)tmp_mcol_pt, v1, v2, v3, (mp->totloop >= 4 ? v4 : NULL), glattrib);
+ GPU_render_text(
+ mtpoly, mode, string, characters,
+ (unsigned int *)tmp_mcol_pt,
+ v_quad, uv_quad,
+ glattrib);
}
}
@@ -855,10 +902,10 @@ static int compareDrawOptions(void *userData, int cur_index, int next_index)
{
drawTFace_userData *data = userData;
- if (data->mf && data->mf[cur_index].mat_nr != data->mf[next_index].mat_nr)
+ if (data->mpoly && data->mpoly[cur_index].mat_nr != data->mpoly[next_index].mat_nr)
return 0;
- if (data->tf && data->tf[cur_index].tpage != data->tf[next_index].tpage)
+ if (data->mtexpoly && data->mtexpoly[cur_index].tpage != data->mtexpoly[next_index].tpage)
return 0;
return 1;
@@ -869,10 +916,10 @@ static int compareDrawOptionsEm(void *userData, int cur_index, int next_index)
{
drawEMTFMapped_userData *data = userData;
- if (data->mf && data->mf[cur_index].mat_nr != data->mf[next_index].mat_nr)
+ if (data->mpoly && data->mpoly[cur_index].mat_nr != data->mpoly[next_index].mat_nr)
return 0;
- if (data->tf && data->tf[cur_index].tpage != data->tf[next_index].tpage)
+ if (data->mtexpoly && data->mtexpoly[cur_index].tpage != data->mtexpoly[next_index].tpage)
return 0;
return 1;
@@ -902,43 +949,36 @@ static void draw_mesh_textured_old(Scene *scene, View3D *v3d, RegionView3D *rv3d
data.em = me->edit_btmesh;
data.has_mcol = CustomData_has_layer(&me->edit_btmesh->bm->ldata, CD_MLOOPCOL);
- data.has_mtface = CustomData_has_layer(&me->edit_btmesh->bm->pdata, CD_MTEXPOLY);
- data.mf = DM_get_tessface_data_layer(dm, CD_MFACE);
- data.tf = DM_get_tessface_data_layer(dm, CD_MTFACE);
+ data.cd_poly_tex_offset = CustomData_get_offset(&me->edit_btmesh->bm->pdata, CD_MTEXPOLY);
+
+ data.mpoly = DM_get_poly_data_layer(dm, CD_MPOLY);
+ data.mtexpoly = DM_get_poly_data_layer(dm, CD_MTEXPOLY);
dm->drawMappedFacesTex(dm, draw_em_tf_mapped__set_draw, compareDrawOptionsEm, &data, 0);
}
else if (draw_flags & DRAW_FACE_SELECT) {
if (ob->mode & OB_MODE_WEIGHT_PAINT)
dm->drawMappedFaces(dm, wpaint__setSolidDrawOptions_facemask, GPU_enable_material, NULL, me,
- DM_DRAW_USE_COLORS | DM_DRAW_ALWAYS_SMOOTH);
+ DM_DRAW_USE_COLORS | DM_DRAW_ALWAYS_SMOOTH | DM_DRAW_SKIP_HIDDEN);
else {
drawTFace_userData userData;
- userData.mf = DM_get_tessface_data_layer(dm, CD_MFACE);
- userData.tf = DM_get_tessface_data_layer(dm, CD_MTFACE);
+ userData.mpoly = DM_get_poly_data_layer(dm, CD_MPOLY);
+ userData.mtexpoly = DM_get_poly_data_layer(dm, CD_MTEXPOLY);
userData.me = me;
dm->drawMappedFacesTex(dm, me->mpoly ? draw_tface_mapped__set_draw : NULL, compareDrawOptions, &userData, uvflag);
}
}
- else {
- if (GPU_buffer_legacy(dm)) {
- if (draw_flags & DRAW_MODIFIERS_PREVIEW)
- dm->drawFacesTex(dm, draw_mcol__set_draw_legacy, NULL, NULL, uvflag);
- else
- dm->drawFacesTex(dm, draw_tface__set_draw_legacy, NULL, NULL, uvflag);
- }
- else {
- drawTFace_userData userData;
-
- update_tface_color_layer(dm);
-
- userData.mf = DM_get_tessface_data_layer(dm, CD_MFACE);
- userData.tf = DM_get_tessface_data_layer(dm, CD_MTFACE);
- userData.me = NULL;
-
- dm->drawFacesTex(dm, draw_tface__set_draw, compareDrawOptions, &userData, uvflag);
- }
+ else {
+ drawTFace_userData userData;
+
+ update_tface_color_layer(dm, !(ob->mode & OB_MODE_TEXTURE_PAINT));
+
+ userData.mpoly = DM_get_poly_data_layer(dm, CD_MPOLY);
+ userData.mtexpoly = DM_get_poly_data_layer(dm, CD_MTEXPOLY);
+ userData.me = NULL;
+
+ dm->drawFacesTex(dm, draw_tface__set_draw, compareDrawOptions, &userData, uvflag);
}
/* draw game engine text hack */
@@ -948,8 +988,10 @@ static void draw_mesh_textured_old(Scene *scene, View3D *v3d, RegionView3D *rv3d
draw_textured_end();
/* draw edges and selected faces over textured mesh */
- if (!(ob == scene->obedit) && (draw_flags & DRAW_FACE_SELECT))
- draw_mesh_face_select(rv3d, me, dm);
+ if (!(ob == scene->obedit) && (draw_flags & DRAW_FACE_SELECT)) {
+ bool draw_select_edges = (ob->mode & OB_MODE_TEXTURE_PAINT) == 0;
+ draw_mesh_face_select(rv3d, me, dm, draw_select_edges);
+ }
/* reset from negative scale correction */
glFrontFace(GL_CCW);
@@ -1096,7 +1138,7 @@ void draw_mesh_textured(Scene *scene, View3D *v3d, RegionView3D *rv3d,
Mesh *me = ob->data;
TexMatCallback data = {scene, ob, me, dm};
bool (*set_face_cb)(void *, int);
- int glsl, picking = (G.f & G_PICKSEL);
+ bool glsl, picking = (G.f & G_PICKSEL) != 0;
/* face hiding callback depending on mode */
if (ob == scene->obedit)
@@ -1145,8 +1187,10 @@ void draw_mesh_textured(Scene *scene, View3D *v3d, RegionView3D *rv3d,
glMatrixMode(GL_MODELVIEW);
/* faceselect mode drawing over textured mesh */
- if (!(ob == scene->obedit) && (draw_flags & DRAW_FACE_SELECT))
- draw_mesh_face_select(rv3d, ob->data, dm);
+ if (!(ob == scene->obedit) && (draw_flags & DRAW_FACE_SELECT)) {
+ bool draw_select_edges = (ob->mode & OB_MODE_TEXTURE_PAINT) == 0;
+ draw_mesh_face_select(rv3d, ob->data, dm, draw_select_edges);
+ }
}
/* Vertex Paint and Weight Paint */
@@ -1176,12 +1220,14 @@ static void draw_mesh_paint_light_end(void)
void draw_mesh_paint_weight_faces(DerivedMesh *dm, const bool use_light,
void *facemask_cb, void *user_data)
{
+ DMSetMaterial setMaterial = GPU_object_materials_check() ? GPU_enable_material : NULL;
+
if (use_light) {
draw_mesh_paint_light_begin();
}
- dm->drawMappedFaces(dm, (DMSetDrawOptions)facemask_cb, GPU_enable_material, NULL, user_data,
- DM_DRAW_USE_COLORS | DM_DRAW_ALWAYS_SMOOTH);
+ dm->drawMappedFaces(dm, (DMSetDrawOptions)facemask_cb, setMaterial, NULL, user_data,
+ DM_DRAW_USE_COLORS);
if (use_light) {
draw_mesh_paint_light_end();
@@ -1192,18 +1238,18 @@ void draw_mesh_paint_vcolor_faces(DerivedMesh *dm, const bool use_light,
void *facemask_cb, void *user_data,
const Mesh *me)
{
+ DMSetMaterial setMaterial = GPU_object_materials_check() ? GPU_enable_material : NULL;
+
if (use_light) {
draw_mesh_paint_light_begin();
}
if (me->mloopcol) {
- dm->drawMappedFaces(dm, facemask_cb, GPU_enable_material, NULL, user_data,
- DM_DRAW_USE_COLORS | DM_DRAW_ALWAYS_SMOOTH);
+ dm->drawMappedFaces(dm, facemask_cb, setMaterial, NULL, user_data, DM_DRAW_USE_COLORS);
}
else {
glColor3f(1.0f, 1.0f, 1.0f);
- dm->drawMappedFaces(dm, facemask_cb, GPU_enable_material, NULL, user_data,
- DM_DRAW_ALWAYS_SMOOTH);
+ dm->drawMappedFaces(dm, facemask_cb, setMaterial, NULL, user_data, 0);
}
if (use_light) {
@@ -1271,7 +1317,8 @@ void draw_mesh_paint(View3D *v3d, RegionView3D *rv3d,
/* draw face selection on top */
if (draw_flags & DRAW_FACE_SELECT) {
- draw_mesh_face_select(rv3d, me, dm);
+ bool draw_select_edges = (ob->mode & OB_MODE_TEXTURE_PAINT) == 0;
+ draw_mesh_face_select(rv3d, me, dm, draw_select_edges);
}
else if ((use_light == false) || (ob->dtx & OB_DRAWWIRE)) {
const bool use_depth = (v3d->flag & V3D_ZBUF_SELECT) || !(ob->mode & OB_MODE_WEIGHT_PAINT);
diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c
index 2f0f6d59b8c..4e9818deb72 100644
--- a/source/blender/editors/space_view3d/drawobject.c
+++ b/source/blender/editors/space_view3d/drawobject.c
@@ -52,6 +52,7 @@
#include "BKE_anim.h" /* for the where_on_path function */
#include "BKE_armature.h"
#include "BKE_camera.h"
+#include "BKE_colortools.h"
#include "BKE_constraint.h" /* for the get_constraint_target function */
#include "BKE_curve.h"
#include "BKE_DerivedMesh.h"
@@ -73,6 +74,7 @@
#include "BKE_particle.h"
#include "BKE_pointcache.h"
#include "BKE_scene.h"
+#include "BKE_subsurf.h"
#include "BKE_unit.h"
#include "BKE_tracking.h"
@@ -175,7 +177,6 @@ typedef struct drawDMFacesSel_userData {
BMesh *bm;
BMFace *efa_act;
- const int *orig_index_mf_to_mpoly;
const int *orig_index_mp_to_orig;
} drawDMFacesSel_userData;
@@ -213,6 +214,7 @@ static void drawcube_size(float size);
static void drawcircle_size(float size);
static void draw_empty_sphere(float size);
static void draw_empty_cone(float size);
+static void draw_box(float vec[8][3], bool solid);
static void ob_wire_color_blend_theme_id(const unsigned char ob_wire_col[4], const int theme_id, float fac)
{
@@ -299,11 +301,12 @@ bool draw_glsl_material(Scene *scene, Object *ob, View3D *v3d, const char dt)
if (v3d->flag2 & V3D_SHOW_SOLID_MATCAP)
return true;
- if (BKE_scene_use_new_shading_nodes(scene))
+ if (v3d->drawtype == OB_TEXTURE)
+ return (scene->gm.matmode == GAME_MAT_GLSL && !BKE_scene_use_new_shading_nodes(scene));
+ else if (v3d->drawtype == OB_MATERIAL && dt > OB_SOLID)
+ return true;
+ else
return false;
-
- return ((scene->gm.matmode == GAME_MAT_GLSL && v3d->drawtype == OB_TEXTURE) ||
- (v3d->drawtype == OB_MATERIAL)) && (dt > OB_SOLID);
}
static bool check_alpha_pass(Base *base)
@@ -402,13 +405,13 @@ static const float cosval[CIRCLE_RESOL] = {
static void draw_xyz_wire(const float c[3], float size, int axis)
{
- float v1[3] = {0.f, 0.f, 0.f}, v2[3] = {0.f, 0.f, 0.f};
+ float v1[3] = {0.0f, 0.0f, 0.0f}, v2[3] = {0.0f, 0.0f, 0.0f};
float dim = size * 0.1f;
float dx[3], dy[3], dz[3];
- dx[0] = dim; dx[1] = 0.f; dx[2] = 0.f;
- dy[0] = 0.f; dy[1] = dim; dy[2] = 0.f;
- dz[0] = 0.f; dz[1] = 0.f; dz[2] = dim;
+ dx[0] = dim; dx[1] = 0.0f; dx[2] = 0.0f;
+ dy[0] = 0.0f; dy[1] = dim; dy[2] = 0.0f;
+ dz[0] = 0.0f; dz[1] = 0.0f; dz[2] = dim;
switch (axis) {
case 0: /* x axis */
@@ -424,7 +427,7 @@ static void draw_xyz_wire(const float c[3], float size, int axis)
glVertex3fv(v2);
/* top left to bottom right */
- mul_v3_fl(dy, 2.f);
+ mul_v3_fl(dy, 2.0f);
add_v3_v3(v1, dy);
sub_v3_v3(v2, dy);
@@ -447,7 +450,7 @@ static void draw_xyz_wire(const float c[3], float size, int axis)
glVertex3fv(v2);
/* top left to center */
- mul_v3_fl(dy, 2.f);
+ mul_v3_fl(dy, 2.0f);
add_v3_v3(v1, dy);
copy_v3_v3(v2, c);
@@ -465,12 +468,12 @@ static void draw_xyz_wire(const float c[3], float size, int axis)
glVertex3fv(v1);
- mul_v3_fl(dx, 2.f);
+ mul_v3_fl(dx, 2.0f);
add_v3_v3(v1, dx);
glVertex3fv(v1);
- mul_v3_fl(dz, 2.f);
+ mul_v3_fl(dz, 2.0f);
sub_v3_v3(v1, dx);
sub_v3_v3(v1, dz);
@@ -483,7 +486,6 @@ static void draw_xyz_wire(const float c[3], float size, int axis)
glEnd();
break;
}
-
}
void drawaxes(float size, char drawtype)
@@ -597,10 +599,10 @@ void drawaxes(float size, char drawtype)
}
-/* Function to draw an Image on a empty Object */
+/* Function to draw an Image on an empty Object */
static void draw_empty_image(Object *ob, const short dflag, const unsigned char ob_wire_col[4])
{
- Image *ima = (Image *)ob->data;
+ Image *ima = ob->data;
ImBuf *ibuf = BKE_image_acquire_ibuf(ima, ob->iuser, NULL);
float scale, ofs_x, ofs_y, sca_x, sca_y;
@@ -640,16 +642,13 @@ static void draw_empty_image(Object *ob, const short dflag, const unsigned char
sca_y = 1.0f;
}
- /* Calculate the scale center based on objects origin */
+ /* Calculate the scale center based on object's origin */
ofs_x = ob->ima_ofs[0] * ima_x;
ofs_y = ob->ima_ofs[1] * ima_y;
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
- /* Make sure we are drawing at the origin */
- glTranslatef(0.0f, 0.0f, 0.0f);
-
/* Calculate Image scale */
scale = (ob->empty_drawsize / max_ff((float)ima_x * sca_x, (float)ima_y * sca_y));
@@ -732,7 +731,7 @@ void drawcircball(int mode, const float cent[3], float rad, float tmat[4][4])
}
/* circle for object centers, special_color is for library or ob users */
-static void drawcentercircle(View3D *v3d, RegionView3D *rv3d, const float co[3], int selstate, int special_color)
+static void drawcentercircle(View3D *v3d, RegionView3D *rv3d, const float co[3], int selstate, bool special_color)
{
const float size = ED_view3d_pixel_size(rv3d, co) * (float)U.obcenter_dia * 0.5f;
float verts[CIRCLE_RESOL][3];
@@ -740,6 +739,8 @@ static void drawcentercircle(View3D *v3d, RegionView3D *rv3d, const float co[3],
/* using gldepthfunc guarantees that it does write z values,
* but not checks for it, so centers remain visible independent order of drawing */
if (v3d->zbuf) glDepthFunc(GL_ALWAYS);
+ /* write to near buffer always */
+ glDepthRange(0.0, 0.0);
glEnable(GL_BLEND);
if (special_color) {
@@ -769,6 +770,7 @@ static void drawcentercircle(View3D *v3d, RegionView3D *rv3d, const float co[3],
/* finish up */
glDisableClientState(GL_VERTEX_ARRAY);
+ glDepthRange(0.0, 1.0);
glDisable(GL_BLEND);
if (v3d->zbuf) glDepthFunc(GL_LEQUAL);
@@ -940,7 +942,7 @@ void view3d_cached_text_draw_end(View3D *v3d, ARegion *ar, bool depth_write, flo
/* ******************** primitive drawing ******************* */
-/* draws a cube on given the scaling of the cube, assuming that
+/* draws a cube given the scaling of the cube, assuming that
* all required matrices have been set (used for drawing empties)
*/
static void drawcube_size(float size)
@@ -974,7 +976,7 @@ static void drawcube_size(const float size[3])
{
glPushMatrix();
- glScalef(size[0], size[1], size[2]);
+ glScale3fv(size);
glBegin(GL_LINE_STRIP);
@@ -1022,8 +1024,6 @@ static void drawshadbuflimits(Lamp *la, float mat[4][4])
glPointSize(1.0);
}
-
-
static void spotvolume(float lvec[3], float vvec[3], const float inp)
{
/* camera is at 0,0,0 */
@@ -1032,8 +1032,8 @@ static void spotvolume(float lvec[3], float vvec[3], const float inp)
normalize_v3(lvec);
normalize_v3(vvec); /* is this the correct vector ? */
- cross_v3_v3v3(temp, vvec, lvec); /* equation for a plane through vvec en lvec */
- cross_v3_v3v3(plane, lvec, temp); /* a plane perpendicular to this, parrallel with lvec */
+ cross_v3_v3v3(temp, vvec, lvec); /* equation for a plane through vvec and lvec */
+ cross_v3_v3v3(plane, lvec, temp); /* a plane perpendicular to this, parallel with lvec */
/* vectors are exactly aligned, use the X axis, this is arbitrary */
if (normalize_v3(plane) == 0.0f)
@@ -1146,6 +1146,52 @@ static void draw_transp_spot_volume(Lamp *la, float x, float z)
glCullFace(GL_BACK);
}
+#ifdef WITH_GAMEENGINE
+static void draw_transp_sun_volume(Lamp *la)
+{
+ float box[8][3];
+
+ /* construct box */
+ box[0][0] = box[1][0] = box[2][0] = box[3][0] = -la->shadow_frustum_size;
+ box[4][0] = box[5][0] = box[6][0] = box[7][0] = +la->shadow_frustum_size;
+ box[0][1] = box[1][1] = box[4][1] = box[5][1] = -la->shadow_frustum_size;
+ box[2][1] = box[3][1] = box[6][1] = box[7][1] = +la->shadow_frustum_size;
+ box[0][2] = box[3][2] = box[4][2] = box[7][2] = -la->clipend;
+ box[1][2] = box[2][2] = box[5][2] = box[6][2] = -la->clipsta;
+
+ /* draw edges */
+ draw_box(box, false);
+
+ /* draw faces */
+ glEnable(GL_CULL_FACE);
+ glEnable(GL_BLEND);
+ glDepthMask(0);
+
+ /* draw backside darkening */
+ glCullFace(GL_FRONT);
+
+ glBlendFunc(GL_ZERO, GL_SRC_ALPHA);
+ glColor4f(0.0f, 0.0f, 0.0f, 0.4f);
+
+ draw_box(box, true);
+
+ /* draw front side lighting */
+ glCullFace(GL_BACK);
+
+ glBlendFunc(GL_ONE, GL_ONE);
+ glColor4f(0.2f, 0.2f, 0.2f, 1.0f);
+
+ draw_box(box, true);
+
+ /* restore state */
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glDisable(GL_BLEND);
+ glDepthMask(1);
+ glDisable(GL_CULL_FACE);
+ glCullFace(GL_BACK);
+}
+#endif
+
static void drawlamp(View3D *v3d, RegionView3D *rv3d, Base *base,
const char dt, const short dflag, const unsigned char ob_wire_col[4], const bool is_obact)
{
@@ -1158,7 +1204,7 @@ static void drawlamp(View3D *v3d, RegionView3D *rv3d, Base *base,
unsigned char curcol[4];
unsigned char col[4];
- /* cone can't be drawn for duplicated lamps, because duplilist would be freed to */
+ /* cone can't be drawn for duplicated lamps, because duplilist would be freed */
/* the moment of view3d_draw_transp() call */
const bool is_view = (rv3d->persp == RV3D_CAMOB && v3d->camera == base->object);
const bool drawcone = ((dt > OB_WIRE) &&
@@ -1168,7 +1214,22 @@ static void drawlamp(View3D *v3d, RegionView3D *rv3d, Base *base,
!(base->flag & OB_FROMDUPLI) &&
!is_view);
- if (drawcone && !v3d->transp) {
+#ifdef WITH_GAMEENGINE
+ const bool drawshadowbox = (
+ (rv3d->rflag & RV3D_IS_GAME_ENGINE) &&
+ (dt > OB_WIRE) &&
+ !(G.f & G_PICKSEL) &&
+ (la->type == LA_SUN) &&
+ ((la->mode & LA_SHAD_BUF) ||
+ (la->mode & LA_SHAD_RAY)) &&
+ (la->mode & LA_SHOW_SHADOW_BOX) &&
+ !(base->flag & OB_FROMDUPLI) &&
+ !is_view);
+#else
+ const bool drawshadowbox = false;
+#endif
+
+ if ((drawcone || drawshadowbox) && !v3d->transp) {
/* in this case we need to draw delayed */
ED_view3d_after_add(&v3d->afterdraw_transp, base, dflag);
return;
@@ -1254,7 +1315,7 @@ static void drawlamp(View3D *v3d, RegionView3D *rv3d, Base *base,
mul_v3_v3fl(v2, imat[0], circrad * 2.5f);
/* center */
- glTranslatef(vec[0], vec[1], vec[2]);
+ glTranslate3fv(vec);
setlinestyle(3);
@@ -1307,7 +1368,7 @@ static void drawlamp(View3D *v3d, RegionView3D *rv3d, Base *base,
x *= y;
/* draw the circle/square at the end of the cone */
- glTranslatef(0.0, 0.0, x);
+ glTranslatef(0.0, 0.0, x);
if (la->mode & LA_SQUARE) {
float tvec[3];
float z_abs = fabsf(z);
@@ -1331,7 +1392,7 @@ static void drawlamp(View3D *v3d, RegionView3D *rv3d, Base *base,
/* draw the circle/square representing spotbl */
if (la->type == LA_SPOT) {
- float spotblcirc = fabsf(z) * (1.0f - powf(la->spotblend, 2));
+ float spotblcirc = fabsf(z) * (1.0f - pow2f(la->spotblend));
/* hide line if it is zero size or overlaps with outer border,
* previously it adjusted to always to show it but that seems
* confusing because it doesn't show the actual blend size */
@@ -1413,6 +1474,13 @@ static void drawlamp(View3D *v3d, RegionView3D *rv3d, Base *base,
dir = -dir;
}
}
+
+#ifdef WITH_GAMEENGINE
+ if (drawshadowbox) {
+ draw_transp_sun_volume(la);
+ }
+#endif
+
}
else if (la->type == LA_AREA) {
setlinestyle(3);
@@ -1496,10 +1564,10 @@ static void draw_limit_line(float sta, float end, const short dflag, unsigned in
static void draw_focus_cross(float dist, float size)
{
glBegin(GL_LINES);
- glVertex3f(-size, 0.f, -dist);
- glVertex3f(size, 0.f, -dist);
- glVertex3f(0.f, -size, -dist);
- glVertex3f(0.f, size, -dist);
+ glVertex3f(-size, 0.0f, -dist);
+ glVertex3f(size, 0.0f, -dist);
+ glVertex3f(0.0f, -size, -dist);
+ glVertex3f(0.0f, size, -dist);
glEnd();
}
@@ -1552,8 +1620,7 @@ static void draw_viewport_object_reconstruction(Scene *scene, Base *base, View3D
BKE_tracking_get_camera_object_matrix(scene, base->object, mat);
/* we're compensating camera size for bundles size,
- * to make it so bundles are always displayed with the same size
- */
+ * to make it so bundles are always displayed with the same size */
copy_v3_v3(camera_size, base->object->size);
if ((tracking_object->flag & TRACKING_OBJECT_CAMERA) == 0)
mul_v3_fl(camera_size, tracking_object->scale);
@@ -1592,7 +1659,7 @@ static void draw_viewport_object_reconstruction(Scene *scene, Base *base, View3D
GPU_select_load_id(base->selcol + (tracknr << 16));
glPushMatrix();
- glTranslatef(track->bundle_pos[0], track->bundle_pos[1], track->bundle_pos[2]);
+ glTranslate3fv(track->bundle_pos);
glScalef(v3d->bundle_size / 0.05f / camera_size[0],
v3d->bundle_size / 0.05f / camera_size[1],
v3d->bundle_size / 0.05f / camera_size[2]);
@@ -1621,7 +1688,7 @@ static void draw_viewport_object_reconstruction(Scene *scene, Base *base, View3D
glColor3ubv(ob_wire_col);
}
- glLineWidth(2.f);
+ glLineWidth(2.0f);
glDisable(GL_LIGHTING);
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
@@ -1629,7 +1696,7 @@ static void draw_viewport_object_reconstruction(Scene *scene, Base *base, View3D
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
glEnable(GL_LIGHTING);
- glLineWidth(1.f);
+ glLineWidth(1.0f);
}
if ((dflag & DRAW_CONSTCOLOR) == 0) {
@@ -1743,6 +1810,238 @@ static void draw_viewport_reconstruction(Scene *scene, Base *base, View3D *v3d,
GPU_select_load_id(base->selcol);
}
+static void drawcamera_volume(float near_plane[4][3], float far_plane[4][3], const GLenum mode)
+{
+ glBegin(mode);
+ glVertex3fv(near_plane[0]);
+ glVertex3fv(far_plane[0]);
+ glVertex3fv(far_plane[1]);
+ glVertex3fv(near_plane[1]);
+ glEnd();
+
+ glBegin(mode);
+ glVertex3fv(near_plane[1]);
+ glVertex3fv(far_plane[1]);
+ glVertex3fv(far_plane[2]);
+ glVertex3fv(near_plane[2]);
+ glEnd();
+
+ glBegin(mode);
+ glVertex3fv(near_plane[2]);
+ glVertex3fv(near_plane[1]);
+ glVertex3fv(far_plane[1]);
+ glVertex3fv(far_plane[2]);
+ glEnd();
+
+ glBegin(mode);
+ glVertex3fv(far_plane[0]);
+ glVertex3fv(near_plane[0]);
+ glVertex3fv(near_plane[3]);
+ glVertex3fv(far_plane[3]);
+ glEnd();
+}
+
+/* camera frame */
+static void drawcamera_frame(float vec[4][3], const GLenum mode)
+{
+ glBegin(mode);
+ glVertex3fv(vec[0]);
+ glVertex3fv(vec[1]);
+ glVertex3fv(vec[2]);
+ glVertex3fv(vec[3]);
+ glEnd();
+}
+
+/* center point to camera frame */
+static void drawcamera_framelines(float vec[4][3], float origin[3])
+{
+ glBegin(GL_LINE_STRIP);
+ glVertex3fv(vec[1]);
+ glVertex3fv(origin);
+ glVertex3fv(vec[0]);
+ glVertex3fv(vec[3]);
+ glVertex3fv(origin);
+ glVertex3fv(vec[2]);
+ glEnd();
+}
+
+static bool drawcamera_is_stereo3d(Scene *scene, View3D *v3d, Object *ob)
+{
+ return (ob == v3d->camera) &&
+ (scene->r.scemode & R_MULTIVIEW) != 0 &&
+ (v3d->stereo3d_flag);
+}
+
+static void drawcamera_stereo3d(
+ Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *ob, const Camera *cam,
+ float vec[4][3], float drawsize, const float scale[3])
+{
+ int i, j;
+ float obmat[4][4];
+ float vec_lr[2][4][3];
+ const float fac = (cam->stereo.pivot == CAM_S3D_PIVOT_CENTER) ? 2.0f : 1.0f;
+ float origin[2][3] = {{0}};
+ float tvec[3];
+ const Camera *cam_lr[2];
+ const char *names[2] = {STEREO_LEFT_NAME, STEREO_RIGHT_NAME};
+
+ const bool is_stereo3d_cameras = (v3d->stereo3d_flag & V3D_S3D_DISPCAMERAS) && (scene->r.views_format == SCE_VIEWS_FORMAT_STEREO_3D);
+ const bool is_stereo3d_plane = (v3d->stereo3d_flag & V3D_S3D_DISPPLANE) && (scene->r.views_format == SCE_VIEWS_FORMAT_STEREO_3D);
+ const bool is_stereo3d_volume = (v3d->stereo3d_flag & V3D_S3D_DISPVOLUME);
+
+ zero_v3(tvec);
+
+ glPushMatrix();
+
+ for (i = 0; i < 2; i++) {
+ ob = BKE_camera_multiview_render(scene, ob, names[i]);
+ cam_lr[i] = ob->data;
+
+ glLoadMatrixf(rv3d->viewmat);
+ BKE_camera_multiview_model_matrix(&scene->r, ob, names[i], obmat);
+ glMultMatrixf(obmat);
+
+ copy_m3_m3(vec_lr[i], vec);
+ copy_v3_v3(vec_lr[i][3], vec[3]);
+
+ if (cam->stereo.convergence_mode == CAM_S3D_OFFAXIS) {
+ const float shift_x =
+ ((BKE_camera_multiview_shift_x(&scene->r, ob, names[i]) - cam->shiftx) *
+ (drawsize * scale[0] * fac));
+
+ for (j = 0; j < 4; j++) {
+ vec_lr[i][j][0] += shift_x;
+ }
+ }
+
+ if (is_stereo3d_cameras) {
+ /* camera frame */
+ drawcamera_frame(vec_lr[i], GL_LINE_LOOP);
+
+ /* center point to camera frame */
+ drawcamera_framelines(vec_lr[i], tvec);
+ }
+
+ /* connecting line */
+ mul_m4_v3(obmat, origin[i]);
+
+ /* convergence plane */
+ if (is_stereo3d_plane || is_stereo3d_volume) {
+ for (j = 0; j < 4; j++) {
+ mul_m4_v3(obmat, vec_lr[i][j]);
+ }
+ }
+ }
+
+
+ /* the remaining drawing takes place in the view space */
+ glLoadMatrixf(rv3d->viewmat);
+
+ if (is_stereo3d_cameras) {
+ /* draw connecting lines */
+ glPushAttrib(GL_ENABLE_BIT);
+
+ glLineStipple(2, 0xAAAA);
+ glEnable(GL_LINE_STIPPLE);
+
+ glBegin(GL_LINES);
+ glVertex3fv(origin[0]);
+ glVertex3fv(origin[1]);
+ glEnd();
+ glPopAttrib();
+ }
+
+ /* draw convergence plane*/
+ if (is_stereo3d_plane) {
+ float axis_center[3], screen_center[3];
+ float world_plane[4][3];
+ float local_plane[4][3];
+ float offset;
+
+ mid_v3_v3v3(axis_center, origin[0], origin[1]);
+
+ for (i = 0; i < 4; i++) {
+ mid_v3_v3v3(world_plane[i], vec_lr[0][i], vec_lr[1][i]);
+ sub_v3_v3v3(local_plane[i], world_plane[i], axis_center);
+ }
+
+ mid_v3_v3v3(screen_center, world_plane[0], world_plane[2]);
+ offset = cam->stereo.convergence_distance / len_v3v3(screen_center, axis_center);
+
+ for (i = 0; i < 4; i++) {
+ mul_v3_fl(local_plane[i], offset);
+ add_v3_v3(local_plane[i], axis_center);
+ }
+
+ glColor3f(0.0f, 0.0f, 0.0f);
+
+ /* camera frame */
+ drawcamera_frame(local_plane, GL_LINE_LOOP);
+
+ if (v3d->stereo3d_convergence_alpha > 0.0f) {
+ glEnable(GL_BLEND);
+ glDepthMask(0); /* disable write in zbuffer, needed for nice transp */
+
+ glColor4f(0.0f, 0.0f, 0.0f, v3d->stereo3d_convergence_alpha);
+
+ drawcamera_frame(local_plane, GL_QUADS);
+
+ glDisable(GL_BLEND);
+ glDepthMask(1); /* restore write in zbuffer */
+ }
+ }
+
+ /* draw convergence plane*/
+ if (is_stereo3d_volume) {
+ float screen_center[3];
+ float near_plane[4][3], far_plane[4][3];
+ float offset;
+ int j;
+
+ for (i = 0; i < 2; i++) {
+ mid_v3_v3v3(screen_center, vec_lr[i][0], vec_lr[i][2]);
+
+ offset = len_v3v3(screen_center, origin[i]);
+
+ for (j = 0; j < 4; j++) {
+ sub_v3_v3v3(near_plane[j], vec_lr[i][j], origin[i]);
+ mul_v3_fl(near_plane[j], cam_lr[i]->clipsta / offset);
+ add_v3_v3(near_plane[j], origin[i]);
+
+ sub_v3_v3v3(far_plane[j], vec_lr[i][j], origin[i]);
+ mul_v3_fl(far_plane[j], cam_lr[i]->clipend / offset);
+ add_v3_v3(far_plane[j], origin[i]);
+ }
+
+ /* camera frame */
+ glColor3f(0.0f, 0.0f, 0.0f);
+
+ drawcamera_frame(near_plane, GL_LINE_LOOP);
+ drawcamera_frame(far_plane, GL_LINE_LOOP);
+ drawcamera_volume(near_plane, far_plane, GL_LINE_LOOP);
+
+ if (v3d->stereo3d_volume_alpha > 0.0f) {
+ glEnable(GL_BLEND);
+ glDepthMask(0); /* disable write in zbuffer, needed for nice transp */
+
+ if (i == 0)
+ glColor4f(0.0f, 1.0f, 1.0f, v3d->stereo3d_volume_alpha);
+ else
+ glColor4f(1.0f, 0.0f, 0.0f, v3d->stereo3d_volume_alpha);
+
+ drawcamera_frame(near_plane, GL_QUADS);
+ drawcamera_frame(far_plane, GL_QUADS);
+ drawcamera_volume(near_plane, far_plane, GL_QUADS);
+
+ glDisable(GL_BLEND);
+ glDepthMask(1); /* restore write in zbuffer */
+ }
+ }
+ }
+
+ glPopMatrix();
+}
+
/* flag similar to draw_object() */
static void drawcamera(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base,
const short dflag, const unsigned char ob_wire_col[4])
@@ -1754,9 +2053,20 @@ static void drawcamera(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base
float vec[4][3], asp[2], shift[2], scale[3];
int i;
float drawsize;
- const bool is_view = (rv3d->persp == RV3D_CAMOB && ob == v3d->camera);
MovieClip *clip = BKE_object_movieclip_get(scene, base->object, false);
+ const bool is_view = (rv3d->persp == RV3D_CAMOB && ob == v3d->camera);
+ const bool is_multiview = (scene->r.scemode & R_MULTIVIEW) != 0;
+ const bool is_stereo3d = drawcamera_is_stereo3d(scene, v3d, ob);
+ const bool is_stereo3d_view = (scene->r.views_format == SCE_VIEWS_FORMAT_STEREO_3D);
+ const bool is_stereo3d_cameras = (ob == scene->camera) &&
+ is_multiview &&
+ is_stereo3d_view &&
+ (v3d->stereo3d_flag & V3D_S3D_DISPCAMERAS);
+ const bool is_selection_camera_stereo = (G.f & G_PICKSEL) &&
+ is_view && is_multiview &&
+ is_stereo3d_view;
+
/* draw data for movie clip set as active for scene */
if (clip) {
draw_viewport_reconstruction(scene, base, v3d, clip, dflag, ob_wire_col, false);
@@ -1782,9 +2092,17 @@ static void drawcamera(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base
cam = ob->data;
- scale[0] = 1.0f / len_v3(ob->obmat[0]);
- scale[1] = 1.0f / len_v3(ob->obmat[1]);
- scale[2] = 1.0f / len_v3(ob->obmat[2]);
+ /* BKE_camera_multiview_model_matrix already accounts for scale, don't do it here */
+ if (is_selection_camera_stereo) {
+ scale[0] = 1.0f;
+ scale[1] = 1.0f;
+ scale[2] = 1.0f;
+ }
+ else {
+ scale[0] = 1.0f / len_v3(ob->obmat[0]);
+ scale[1] = 1.0f / len_v3(ob->obmat[1]);
+ scale[2] = 1.0f / len_v3(ob->obmat[2]);
+ }
BKE_camera_view_frame_ex(scene, cam, cam->drawsize, is_view, scale,
asp, shift, &drawsize, vec);
@@ -1793,12 +2111,24 @@ static void drawcamera(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base
glDisable(GL_CULL_FACE);
/* camera frame */
- glBegin(GL_LINE_LOOP);
- glVertex3fv(vec[0]);
- glVertex3fv(vec[1]);
- glVertex3fv(vec[2]);
- glVertex3fv(vec[3]);
- glEnd();
+ if (!is_stereo3d_cameras) {
+ /* make sure selection uses the same matrix for camera as the one used while viewing */
+ if (is_selection_camera_stereo) {
+ float obmat[4][4];
+ bool is_left = v3d->multiview_eye == STEREO_LEFT_ID;
+
+ glPushMatrix();
+ glLoadMatrixf(rv3d->viewmat);
+ BKE_camera_multiview_model_matrix(&scene->r, ob, is_left ? STEREO_LEFT_NAME : STEREO_RIGHT_NAME, obmat);
+ glMultMatrixf(obmat);
+
+ drawcamera_frame(vec, GL_LINE_LOOP);
+ glPopMatrix();
+ }
+ else {
+ drawcamera_frame(vec, GL_LINE_LOOP);
+ }
+ }
if (is_view)
return;
@@ -1806,20 +2136,12 @@ static void drawcamera(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base
zero_v3(tvec);
/* center point to camera frame */
- glBegin(GL_LINE_STRIP);
- glVertex3fv(vec[1]);
- glVertex3fv(tvec);
- glVertex3fv(vec[0]);
- glVertex3fv(vec[3]);
- glVertex3fv(tvec);
- glVertex3fv(vec[2]);
- glEnd();
-
+ if (!is_stereo3d_cameras)
+ drawcamera_framelines(vec, tvec);
/* arrow on top */
tvec[2] = vec[1][2]; /* copy the depth */
-
/* draw an outline arrow for inactive cameras and filled
* for active cameras. We actually draw both outline+filled
* for active cameras so the wire can be seen side-on */
@@ -1869,14 +2191,17 @@ static void drawcamera(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base
glPopMatrix();
}
}
+
+ /* stereo cameras drawing */
+ if (is_stereo3d) {
+ drawcamera_stereo3d(scene, v3d, rv3d, ob, cam, vec, drawsize, scale);
+ }
}
/* flag similar to draw_object() */
static void drawspeaker(Scene *UNUSED(scene), View3D *UNUSED(v3d), RegionView3D *UNUSED(rv3d),
Object *UNUSED(ob), int UNUSED(flag))
{
- //Speaker *spk = ob->data;
-
float vec[3];
int i, j;
@@ -1948,8 +2273,8 @@ static void lattice_draw_verts(Lattice *lt, DispList *dl, BPoint *actbp, short s
}
}
- glPointSize(1.0);
bglEnd();
+ glPointSize(1.0);
}
static void drawlattice__point(Lattice *lt, DispList *dl, int u, int v, int w, int actdef_wcol)
@@ -1987,9 +2312,9 @@ static void ensure_curve_cache(Scene *scene, Object *object)
* here, we also need to check whether display list is
* empty or not.
*
- * The trick below tries to optimie calls to displist
+ * The trick below tries to optimize calls to displist
* creation for cases curve is empty. Meaning, if the curve
- * is empty (without splies) bevel list would also be empty.
+ * is empty (without splines) bevel list would also be empty.
* And the thing is, render thread always leaves bevel list
* in a proper state. So if bevel list is here and display
* list is not we need to make display list.
@@ -2153,8 +2478,7 @@ static void calcDrawDMNormalScale(Object *ob, drawDMNormal_userData *data)
invert_m3_m3(data->imat, obmat);
/* transposed inverted matrix */
- copy_m3_m3(data->tmat, data->imat);
- transpose_m3(data->tmat);
+ transpose_m3_m3(data->tmat, data->imat);
}
}
@@ -2268,8 +2592,7 @@ static void draw_dm_verts__mapFunc(void *userData, int index, const float co[3],
BMVert *eve = BM_vert_at_index(data->bm, index);
if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN) && BM_elem_flag_test(eve, BM_ELEM_SELECT) == data->sel) {
- /* skin nodes: draw a red circle around the root
- * node(s) */
+ /* skin nodes: draw a red circle around the root node(s) */
if (data->cd_vskin_offset != -1) {
const MVertSkin *vs = BM_ELEM_CD_GET_VOID_P(eve, data->cd_vskin_offset);
if (vs->flag & MVERT_SKIN_ROOT) {
@@ -2335,7 +2658,6 @@ static void draw_dm_verts(BMEditMesh *em, DerivedMesh *dm, const char sel, BMVer
static DMDrawOption draw_dm_edges_sel__setDrawOptions(void *userData, int index)
{
BMEdge *eed;
- //unsigned char **cols = userData, *col;
drawDMEdgesSel_userData *data = userData;
unsigned char *col;
@@ -2352,7 +2674,7 @@ static DMDrawOption draw_dm_edges_sel__setDrawOptions(void *userData, int index)
else {
col = data->baseCol;
}
- /* no alpha, this is used so a transparent color can disable drawing unselected edges in editmode */
+ /* no alpha, this is used so a transparent color can disable drawing unselected edges in editmode */
if (col[3] == 0)
return DM_DRAW_OPTION_SKIP;
@@ -2497,7 +2819,7 @@ static void draw_dm_edges_weight_interp(BMEditMesh *em, DerivedMesh *dm, const c
data.bm = em->bm;
data.cd_dvert_offset = CustomData_get_offset(&em->bm->vdata, CD_MDEFORMVERT);
- data.defgroup_tot = BLI_countlist(&ob->defbase);
+ data.defgroup_tot = BLI_listbase_count(&ob->defbase);
data.vgroup_index = ob->actdef - 1;
data.weight_user = weight_user;
UI_GetThemeColor3fv(TH_VERTEX_UNREFERENCED, data.alert_color);
@@ -2692,12 +3014,9 @@ static int draw_dm_faces_sel__compareDrawOptions(void *userData, int index, int
unsigned char *col, *next_col;
- if (!data->orig_index_mf_to_mpoly)
- return 0;
-
- i = DM_origindex_mface_mpoly(data->orig_index_mf_to_mpoly, data->orig_index_mp_to_orig, index);
+ i = data->orig_index_mp_to_orig ? data->orig_index_mp_to_orig[index] : index;
efa = (i != ORIGINDEX_NONE) ? BM_face_at_index(data->bm, i) : NULL;
- i = DM_origindex_mface_mpoly(data->orig_index_mf_to_mpoly, data->orig_index_mp_to_orig, next_index);
+ i = data->orig_index_mp_to_orig ? data->orig_index_mp_to_orig[next_index] : next_index;
next_efa = (i != ORIGINDEX_NONE) ? BM_face_at_index(data->bm, i) : NULL;
if (ELEM(NULL, efa, next_efa))
@@ -2743,13 +3062,9 @@ static void draw_dm_faces_sel(BMEditMesh *em, DerivedMesh *dm, unsigned char *ba
#endif
data.efa_act = efa_act;
/* double lookup */
- data.orig_index_mf_to_mpoly = DM_get_tessface_data_layer(dm, CD_ORIGINDEX);
data.orig_index_mp_to_orig = DM_get_poly_data_layer(dm, CD_ORIGINDEX);
- if ((data.orig_index_mf_to_mpoly && data.orig_index_mp_to_orig) == false) {
- data.orig_index_mf_to_mpoly = data.orig_index_mp_to_orig = NULL;
- }
- dm->drawMappedFaces(dm, draw_dm_faces_sel__setDrawOptions, GPU_enable_material, draw_dm_faces_sel__compareDrawOptions, &data, 0);
+ dm->drawMappedFaces(dm, draw_dm_faces_sel__setDrawOptions, NULL, draw_dm_faces_sel__compareDrawOptions, &data, DM_DRAW_SKIP_HIDDEN);
}
static DMDrawOption draw_dm_creases__setDrawOptions(void *userData, int index)
@@ -2842,11 +3157,6 @@ static void draw_dm_bweights(BMEditMesh *em, Scene *scene, DerivedMesh *dm)
}
}
-static int draw_dm_override_material_color(int UNUSED(nr), void *UNUSED(attribs))
-{
- return 1;
-}
-
/* Second section of routines: Combine first sets to form fancy
* drawing routines (for example rendering twice to get overlays).
*
@@ -2953,21 +3263,23 @@ static void draw_em_fancy_edges(BMEditMesh *em, Scene *scene, View3D *v3d,
if (!sel_only) wireCol[3] = 255;
}
- if (ts->selectmode == SCE_SELECT_FACE) {
- draw_dm_edges_sel(em, cageDM, wireCol, selCol, actCol, eed_act);
- }
- else if ((me->drawflag & ME_DRAWEDGES) || (ts->selectmode & SCE_SELECT_EDGE)) {
+ if ((me->drawflag & ME_DRAWEDGES) || (ts->selectmode & SCE_SELECT_EDGE)) {
if (cageDM->drawMappedEdgesInterp &&
((ts->selectmode & SCE_SELECT_VERTEX) || (me->drawflag & ME_DRAWEIGHT)))
{
- glShadeModel(GL_SMOOTH);
if (draw_dm_edges_weight_check(me, v3d)) {
+ glShadeModel(GL_SMOOTH);
draw_dm_edges_weight_interp(em, cageDM, ts->weightuser);
+ glShadeModel(GL_FLAT);
+ }
+ else if (ts->selectmode == SCE_SELECT_FACE) {
+ draw_dm_edges_sel(em, cageDM, wireCol, selCol, actCol, eed_act);
}
else {
+ glShadeModel(GL_SMOOTH);
draw_dm_edges_sel_interp(em, cageDM, wireCol, selCol);
+ glShadeModel(GL_FLAT);
}
- glShadeModel(GL_FLAT);
}
else {
draw_dm_edges_sel(em, cageDM, wireCol, selCol, actCol, eed_act);
@@ -3040,7 +3352,7 @@ static void draw_em_measure_stats(ARegion *ar, View3D *v3d, Object *ob, BMEditMe
}
BM_ITER_MESH (eed, &iter, em->bm, BM_EDGES_OF_MESH) {
- /* draw selected edges, or edges next to selected verts while draging */
+ /* draw selected edges, or edges next to selected verts while dragging */
if (BM_elem_flag_test(eed, BM_ELEM_SELECT) ||
(do_moving && (BM_elem_flag_test(eed->v1, BM_ELEM_SELECT) ||
BM_elem_flag_test(eed->v2, BM_ELEM_SELECT))))
@@ -3078,7 +3390,7 @@ static void draw_em_measure_stats(ARegion *ar, View3D *v3d, Object *ob, BMEditMe
unit->system, B_UNIT_LENGTH, do_split, false);
}
else {
- numstr_len = BLI_snprintf(numstr, sizeof(numstr), conv_float, len_v3v3(v1, v2));
+ numstr_len = BLI_snprintf_rlen(numstr, sizeof(numstr), conv_float, len_v3v3(v1, v2));
}
view3d_cached_text_draw_add(vmid, numstr, numstr_len, 0, txt_flag, col);
@@ -3097,17 +3409,15 @@ static void draw_em_measure_stats(ARegion *ar, View3D *v3d, Object *ob, BMEditMe
BM_mesh_elem_index_ensure(em->bm, BM_VERT | BM_FACE);
}
- // invert_m4_m4(ob->imat, ob->obmat); // this is already called
-
BM_ITER_MESH (eed, &iter, em->bm, BM_EDGES_OF_MESH) {
BMLoop *l_a, *l_b;
if (BM_edge_loop_pair(eed, &l_a, &l_b)) {
- /* draw selected edges, or edges next to selected verts while draging */
+ /* draw selected edges, or edges next to selected verts while dragging */
if (BM_elem_flag_test(eed, BM_ELEM_SELECT) ||
(do_moving && (BM_elem_flag_test(eed->v1, BM_ELEM_SELECT) ||
BM_elem_flag_test(eed->v2, BM_ELEM_SELECT) ||
- /* special case, this is useful to show when vertes connected to this edge via a
- * face are being transformed */
+ /* special case, this is useful to show when verts connected to
+ * this edge via a face are being transformed */
BM_elem_flag_test(l_a->next->next->v, BM_ELEM_SELECT) ||
BM_elem_flag_test(l_a->prev->v, BM_ELEM_SELECT) ||
BM_elem_flag_test(l_b->next->next->v, BM_ELEM_SELECT) ||
@@ -3157,7 +3467,7 @@ static void draw_em_measure_stats(ARegion *ar, View3D *v3d, Object *ob, BMEditMe
angle = angle_normalized_v3v3(no_a, no_b);
- numstr_len = BLI_snprintf(numstr, sizeof(numstr), "%.3f", is_rad ? angle : RAD2DEGF(angle));
+ numstr_len = BLI_snprintf_rlen(numstr, sizeof(numstr), "%.3f", is_rad ? angle : RAD2DEGF(angle));
view3d_cached_text_draw_add(vmid, numstr, numstr_len, 0, txt_flag, col);
}
@@ -3182,7 +3492,7 @@ static void draw_em_measure_stats(ARegion *ar, View3D *v3d, Object *ob, BMEditMe
3, unit->system, B_UNIT_AREA, do_split, false); \
} \
else { \
- numstr_len = BLI_snprintf(numstr, sizeof(numstr), conv_float, area); \
+ numstr_len = BLI_snprintf_rlen(numstr, sizeof(numstr), conv_float, area); \
} \
view3d_cached_text_draw_add(vmid, numstr, numstr_len, 0, txt_flag, col); \
} (void)0
@@ -3256,7 +3566,12 @@ static void draw_em_measure_stats(ARegion *ar, View3D *v3d, Object *ob, BMEditMe
bool is_first = true;
BM_ITER_ELEM (loop, &liter, efa, BM_LOOPS_OF_FACE) {
- if (is_face_sel || (do_moving && BM_elem_flag_test(loop->v, BM_ELEM_SELECT))) {
+ if (is_face_sel ||
+ (do_moving &&
+ (BM_elem_flag_test(loop->v, BM_ELEM_SELECT) ||
+ BM_elem_flag_test(loop->prev->v, BM_ELEM_SELECT) ||
+ BM_elem_flag_test(loop->next->v, BM_ELEM_SELECT))))
+ {
float angle;
float v2_local[3];
@@ -3300,7 +3615,7 @@ static void draw_em_measure_stats(ARegion *ar, View3D *v3d, Object *ob, BMEditMe
angle = angle_v3v3v3(v1, v2, v3);
- numstr_len = BLI_snprintf(numstr, sizeof(numstr), "%.3f", is_rad ? angle : RAD2DEGF(angle));
+ numstr_len = BLI_snprintf_rlen(numstr, sizeof(numstr), "%.3f", is_rad ? angle : RAD2DEGF(angle));
interp_v3_v3v3(fvec, vmid, v2_local, 0.8f);
view3d_cached_text_draw_add(fvec, numstr, numstr_len, 0, txt_flag, col);
}
@@ -3331,7 +3646,7 @@ static void draw_em_indices(BMEditMesh *em)
UI_GetThemeColor3ubv(TH_DRAWEXTRA_FACEANG, col);
BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
if (BM_elem_flag_test(v, BM_ELEM_SELECT)) {
- numstr_len = BLI_snprintf(numstr, sizeof(numstr), "%d", i);
+ numstr_len = BLI_snprintf_rlen(numstr, sizeof(numstr), "%d", i);
view3d_cached_text_draw_add(v->co, numstr, numstr_len, 0, txt_flag, col);
}
i++;
@@ -3343,7 +3658,7 @@ static void draw_em_indices(BMEditMesh *em)
UI_GetThemeColor3ubv(TH_DRAWEXTRA_EDGELEN, col);
BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
if (BM_elem_flag_test(e, BM_ELEM_SELECT)) {
- numstr_len = BLI_snprintf(numstr, sizeof(numstr), "%d", i);
+ numstr_len = BLI_snprintf_rlen(numstr, sizeof(numstr), "%d", i);
mid_v3_v3v3(pos, e->v1->co, e->v2->co);
view3d_cached_text_draw_add(pos, numstr, numstr_len, 0, txt_flag, col);
}
@@ -3357,7 +3672,7 @@ static void draw_em_indices(BMEditMesh *em)
BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
if (BM_elem_flag_test(f, BM_ELEM_SELECT)) {
BM_face_calc_center_mean(f, pos);
- numstr_len = BLI_snprintf(numstr, sizeof(numstr), "%d", i);
+ numstr_len = BLI_snprintf_rlen(numstr, sizeof(numstr), "%d", i);
view3d_cached_text_draw_add(pos, numstr, numstr_len, 0, txt_flag, col);
}
i++;
@@ -3375,7 +3690,6 @@ static DMDrawOption draw_em_fancy__setFaceOpts(void *userData, int index)
efa = BM_face_at_index(em->bm, index);
if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) {
- GPU_enable_material(efa->mat_nr + 1, NULL);
return DM_DRAW_OPTION_NORMAL;
}
else {
@@ -3414,7 +3728,7 @@ static void draw_em_fancy(Scene *scene, ARegion *ar, View3D *v3d,
if (em->bm->selected.last) {
BMEditSelection *ese = em->bm->selected.last;
- /* face is handeled above */
+ /* face is handled above */
#if 0
if (ese->type == BM_FACE) {
efa_act = (BMFace *)ese->data;
@@ -3450,7 +3764,7 @@ static void draw_em_fancy(Scene *scene, ARegion *ar, View3D *v3d,
/* use the cageDM since it always overlaps the editmesh faces */
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
cageDM->drawMappedFaces(cageDM, draw_em_fancy__setFaceOpts,
- GPU_enable_material, NULL, me->edit_btmesh, 0);
+ GPU_enable_material, NULL, me->edit_btmesh, DM_DRAW_SKIP_HIDDEN);
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
}
else if (check_object_draw_texture(scene, v3d, dt)) {
@@ -3474,7 +3788,7 @@ static void draw_em_fancy(Scene *scene, ARegion *ar, View3D *v3d,
glEnable(GL_LIGHTING);
glFrontFace((ob->transflag & OB_NEG_SCALE) ? GL_CW : GL_CCW);
- finalDM->drawMappedFaces(finalDM, draw_em_fancy__setFaceOpts, GPU_enable_material, NULL, me->edit_btmesh, 0);
+ finalDM->drawMappedFaces(finalDM, draw_em_fancy__setFaceOpts, GPU_enable_material, NULL, me->edit_btmesh, DM_DRAW_SKIP_HIDDEN);
glFrontFace(GL_CCW);
glDisable(GL_LIGHTING);
@@ -3529,11 +3843,14 @@ static void draw_em_fancy(Scene *scene, ARegion *ar, View3D *v3d,
}
else if (efa_act) {
/* even if draw faces is off it would be nice to draw the stipple face
- * Make all other faces zero alpha except for the active
- * */
- /* col4 is only used by WITH_FREESTYLE, but keeping it here spares some #ifdef's... */
- unsigned char col1[4], col2[4], col3[4], col4[4];
- col1[3] = col2[3] = col4[3] = 0; /* don't draw */
+ * Make all other faces zero alpha except for the active */
+ unsigned char col1[4], col2[4], col3[4];
+#ifdef WITH_FREESTYLE
+ unsigned char col4[4];
+ col4[3] = 0; /* don't draw */
+#endif
+ col1[3] = col2[3] = 0; /* don't draw */
+
UI_GetThemeColor4ubv(TH_EDITMESH_ACTIVE, col3);
glEnable(GL_BLEND);
@@ -3547,7 +3864,6 @@ static void draw_em_fancy(Scene *scene, ARegion *ar, View3D *v3d,
glDisable(GL_BLEND);
glDepthMask(1); /* restore write in zbuffer */
-
}
/* here starts all fancy draw-extra over */
@@ -3672,6 +3988,12 @@ static void draw_mesh_object_outline(View3D *v3d, Object *ob, DerivedMesh *dm)
}
}
+static bool object_is_halo(Scene *scene, Object *ob)
+{
+ const Material *ma = give_current_material(ob, 1);
+ return (ma && (ma->material_type == MA_TYPE_HALO) && !BKE_scene_use_new_shading_nodes(scene));
+}
+
static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D *rv3d, Base *base,
const char dt, const unsigned char ob_wire_col[4], const short dflag)
{
@@ -3681,10 +4003,8 @@ static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D
Object *ob = base->object;
#endif
Mesh *me = ob->data;
- Material *ma = give_current_material(ob, 1);
- const bool hasHaloMat = (ma && (ma->material_type == MA_TYPE_HALO) && !BKE_scene_use_new_shading_nodes(scene));
eWireDrawMode draw_wire = OBDRAW_WIRE_OFF;
- int /* totvert,*/ totedge, totface;
+ bool /* no_verts,*/ no_edges, no_faces;
DerivedMesh *dm = mesh_get_derived_final(scene, ob, scene->customdata_mask);
const bool is_obact = (ob == OBACT);
int draw_flags = (is_obact && BKE_paint_select_face_test(ob)) ? DRAW_FACE_SELECT : 0;
@@ -3696,7 +4016,7 @@ static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D
/* Check to draw dynamic paint colors (or weights from WeightVG modifiers).
* Note: Last "preview-active" modifier in stack will win! */
- if (DM_get_tessface_data_layer(dm, CD_PREVIEW_MCOL) && modifiers_isPreview(ob))
+ if (DM_get_loop_data_layer(dm, CD_PREVIEW_MLOOPCOL) && modifiers_isPreview(ob))
draw_flags |= DRAW_MODIFIERS_PREVIEW;
/* Unwanted combination */
@@ -3707,10 +4027,16 @@ static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D
draw_wire = OBDRAW_WIRE_ON_DEPTH; /* draw wire after solid using zoffset and depth buffer adjusment */
}
- /* totvert = dm->getNumVerts(dm); */ /*UNUSED*/
- totedge = dm->getNumEdges(dm);
- totface = dm->getNumTessFaces(dm);
-
+ /* check polys instead of tessfaces because of dyntopo where tessfaces don't exist */
+ if (dm->type == DM_TYPE_CCGDM) {
+ no_edges = !subsurf_has_edges(dm);
+ no_faces = !subsurf_has_faces(dm);
+ }
+ else {
+ no_edges = (dm->getNumEdges(dm) == 0);
+ no_faces = (dm->getNumPolys(dm) == 0);
+ }
+
/* vertexpaint, faceselect wants this, but it doesnt work for shaded? */
glFrontFace((ob->transflag & OB_NEG_SCALE) ? GL_CW : GL_CCW);
@@ -3718,13 +4044,15 @@ static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D
if (((v3d->flag2 & V3D_RENDER_OVERRIDE) && v3d->drawtype >= OB_WIRE) == 0)
draw_bounding_volume(ob, ob->boundtype);
}
- else if (hasHaloMat || (totface == 0 && totedge == 0)) {
+ else if ((no_faces && no_edges) ||
+ ((!is_obact || (ob->mode == OB_MODE_OBJECT)) && object_is_halo(scene, ob)))
+ {
glPointSize(1.5);
dm->drawVerts(dm);
glPointSize(1.0);
}
- else if (dt == OB_WIRE || totface == 0) {
- draw_wire = OBDRAW_WIRE_ON; /* draw wire only, no depth buffer stuff */
+ else if ((dt == OB_WIRE) || no_faces) {
+ draw_wire = OBDRAW_WIRE_ON; /* draw wire only, no depth buffer stuff */
}
else if (((is_obact && ob->mode & OB_MODE_TEXTURE_PAINT)) ||
check_object_draw_texture(scene, v3d, dt))
@@ -3766,14 +4094,16 @@ static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D
else
dm->drawFacesGLSL(dm, GPU_enable_material);
-// if (BKE_bproperty_object_get(ob, "Text"))
-// XXX draw_mesh_text(ob, 1);
+#if 0 /* XXX */
+ if (BKE_bproperty_object_get(ob, "Text"))
+ draw_mesh_text(ob, 1);
+#endif
GPU_disable_material();
glFrontFace(GL_CCW);
if (draw_flags & DRAW_FACE_SELECT)
- draw_mesh_face_select(rv3d, me, dm);
+ draw_mesh_face_select(rv3d, me, dm, false);
}
else {
draw_mesh_textured(scene, v3d, rv3d, ob, dm, draw_flags);
@@ -3820,7 +4150,7 @@ static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D
glEnable(GL_LIGHTING);
glEnable(GL_COLOR_MATERIAL);
- dm->drawMappedFaces(dm, NULL, draw_dm_override_material_color, NULL, NULL, DM_DRAW_USE_COLORS);
+ dm->drawMappedFaces(dm, NULL, NULL, NULL, NULL, DM_DRAW_USE_COLORS);
glDisable(GL_COLOR_MATERIAL);
glDisable(GL_LIGHTING);
@@ -3885,7 +4215,7 @@ static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D
}
if ((draw_wire != OBDRAW_WIRE_OFF) && /* draw extra wire */
- /* when overriding with render only, don't bother */
+ /* when overriding with render only, don't bother */
(((v3d->flag2 & V3D_RENDER_OVERRIDE) && v3d->drawtype >= OB_SOLID) == 0))
{
/* When using wireframe object draw in particle edit mode
@@ -3915,7 +4245,7 @@ static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D
glDepthMask(0); /* disable write in zbuffer, selected edge wires show better */
}
- dm->drawEdges(dm, (dt == OB_WIRE || totface == 0), (ob->dtx & OB_DRAW_ALL_EDGES) != 0);
+ dm->drawEdges(dm, ((dt == OB_WIRE) || no_faces), (ob->dtx & OB_DRAW_ALL_EDGES) != 0);
if (dt != OB_WIRE && (draw_wire == OBDRAW_WIRE_ON_DEPTH)) {
glDepthMask(1);
@@ -3924,7 +4254,7 @@ static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D
}
if (is_obact && BKE_paint_select_vert_test(ob)) {
- const int use_depth = (v3d->flag & V3D_ZBUF_SELECT);
+ const bool use_depth = (v3d->flag & V3D_ZBUF_SELECT) != 0;
glColor3f(0.0f, 0.0f, 0.0f);
glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE));
@@ -3939,7 +4269,7 @@ static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D
dm->release(dm);
}
-/* returns 1 if nothing was drawn, for detecting to draw an object center */
+/* returns true if nothing was drawn, for detecting to draw an object center */
static bool draw_mesh_object(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D *rv3d, Base *base,
const char dt, const unsigned char ob_wire_col[4], const short dflag)
{
@@ -3979,11 +4309,14 @@ static bool draw_mesh_object(Scene *scene, ARegion *ar, View3D *v3d, RegionView3
if (obedit != ob)
finalDM = cageDM = editbmesh_get_derived_base(ob, em);
else
- cageDM = editbmesh_get_derived_cage_and_final(scene, ob, em, &finalDM,
- scene->customdata_mask);
+ cageDM = editbmesh_get_derived_cage_and_final(
+ scene, ob, em, scene->customdata_mask,
+ &finalDM);
DM_update_materials(finalDM, ob);
- DM_update_materials(cageDM, ob);
+ if (cageDM != finalDM) {
+ DM_update_materials(cageDM, ob);
+ }
if (dt > OB_WIRE) {
const bool glsl = draw_glsl_material(scene, ob, v3d, dt);
@@ -4295,7 +4628,7 @@ static bool drawCurveDerivedMesh(Scene *scene, View3D *v3d, RegionView3D *rv3d,
glFrontFace((ob->transflag & OB_NEG_SCALE) ? GL_CW : GL_CCW);
- if (dt > OB_WIRE && dm->getNumTessFaces(dm)) {
+ if (dt > OB_WIRE && dm->getNumPolys(dm)) {
int glsl = draw_glsl_material(scene, ob, v3d, dt);
GPU_begin_object_materials(v3d, rv3d, scene, ob, glsl, NULL);
@@ -4319,7 +4652,7 @@ static bool drawCurveDerivedMesh(Scene *scene, View3D *v3d, RegionView3D *rv3d,
/**
* Only called by #drawDispList
- * \return 1 when nothing was drawn
+ * \return true when nothing was drawn
*/
static bool drawDispList_nobackface(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base,
const char dt, const short dflag, const unsigned char ob_wire_col[4])
@@ -4328,19 +4661,8 @@ static bool drawDispList_nobackface(Scene *scene, View3D *v3d, RegionView3D *rv3
ListBase *lb = NULL;
DispList *dl;
Curve *cu;
- const short render_only = (v3d->flag2 & V3D_RENDER_OVERRIDE);
- const short solid = (dt > OB_WIRE);
-
- if (drawCurveDerivedMesh(scene, v3d, rv3d, base, dt) == false) {
- return false;
- }
-
- if (ob->type == OB_MBALL) {
- glFrontFace((ob->transflag & OB_NEG_SCALE) ? GL_CW : GL_CCW);
- }
- else {
- glFrontFace((ob->transflag & OB_NEG_SCALE) ? GL_CCW : GL_CW);
- }
+ const bool render_only = (v3d->flag2 & V3D_RENDER_OVERRIDE) != 0;
+ const bool solid = (dt > OB_WIRE);
switch (ob->type) {
case OB_FONT:
@@ -4469,7 +4791,28 @@ static bool drawDispList(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *ba
ensure_curve_cache(scene, base->object);
#endif
- retval = drawDispList_nobackface(scene, v3d, rv3d, base, dt, dflag, ob_wire_col);
+ if (drawCurveDerivedMesh(scene, v3d, rv3d, base, dt) == false) {
+ retval = false;
+ }
+ else {
+ Object *ob = base->object;
+ GLenum mode;
+
+ if (ob->type == OB_MBALL) {
+ mode = (ob->transflag & OB_NEG_SCALE) ? GL_CW : GL_CCW;
+ }
+ else {
+ mode = (ob->transflag & OB_NEG_SCALE) ? GL_CCW : GL_CW;
+ }
+
+ glFrontFace(mode);
+
+ retval = drawDispList_nobackface(scene, v3d, rv3d, base, dt, dflag, ob_wire_col);
+
+ if (mode != GL_CCW) {
+ glFrontFace(GL_CCW);
+ }
+ }
if (v3d->flag2 & V3D_BACKFACE_CULLING) {
glDisable(GL_CULL_FACE);
@@ -4581,7 +4924,7 @@ static void draw_particle(ParticleKey *state, int draw_as, short draw, float pix
copy_v3_v3(pdd->vd, vec2); pdd->vd += 3;
vec[2] = 2.0f * pixsize;
- vec[0] = vec[1] = 0.0;
+ vec[0] = vec[1] = 0.0f;
mul_qt_v3(state->rot, vec);
if (draw_as == PART_DRAW_AXIS) {
copy_v3_v3(vec2, state->co);
@@ -4664,7 +5007,7 @@ static void draw_particle_data(ParticleSystem *psys, RegionView3D *rv3d,
if (psys->parent)
mul_m4_v3(psys->parent->obmat, state->co);
- /* create actiual particle data */
+ /* create actual particle data */
if (draw_as == PART_DRAW_BB) {
bb->offset[0] = part->bb_offset[0];
bb->offset[1] = part->bb_offset[1];
@@ -4689,16 +5032,17 @@ static void draw_particle_data(ParticleSystem *psys, RegionView3D *rv3d,
draw_particle(state, draw_as, part->draw, pixsize, imat, part->draw_line, bb, pdd);
}
-/* unified drawing of all new particle systems draw types except dupli ob & group */
-/* mostly tries to use vertex arrays for speed */
-
-/* 1. check that everything is ok & updated */
-/* 2. start initializing things */
-/* 3. initialize according to draw type */
-/* 4. allocate drawing data arrays */
-/* 5. start filling the arrays */
-/* 6. draw the arrays */
-/* 7. clean up */
+/* unified drawing of all new particle systems draw types except dupli ob & group
+ * mostly tries to use vertex arrays for speed
+ *
+ * 1. check that everything is ok & updated
+ * 2. start initializing things
+ * 3. initialize according to draw type
+ * 4. allocate drawing data arrays
+ * 5. start filling the arrays
+ * 6. draw the arrays
+ * 7. clean up
+ */
static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv3d,
Base *base, ParticleSystem *psys,
const char ob_dt, const short dflag)
@@ -4743,6 +5087,12 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv
if (draw_as == PART_DRAW_NOT)
return;
+ /* prepare curvemapping tables */
+ if ((psys->part->child_flag & PART_CHILD_USE_CLUMP_CURVE) && psys->part->clumpcurve)
+ curvemapping_changed_all(psys->part->clumpcurve);
+ if ((psys->part->child_flag & PART_CHILD_USE_ROUGH_CURVE) && psys->part->roughcurve)
+ curvemapping_changed_all(psys->part->roughcurve);
+
/* 2. */
sim.scene = scene;
sim.ob = ob;
@@ -4888,7 +5238,7 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv
int create_ndata = 0;
if (!pdd)
- pdd = psys->pdd = MEM_callocN(sizeof(ParticleDrawData), "ParticlDrawData");
+ pdd = psys->pdd = MEM_callocN(sizeof(ParticleDrawData), "ParticleDrawData");
if (part->draw_as == PART_DRAW_REND && part->trail_count > 1) {
tot_vec_size *= part->trail_count;
@@ -4991,7 +5341,7 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv
BLI_assert(0);
break;
}
- CLAMP(intensity, 0.f, 1.f);
+ CLAMP(intensity, 0.0f, 1.0f);
weight_to_rgb(ma_col, intensity);
}
}
@@ -5050,8 +5400,8 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv
}
if (drawn) {
- /* additional things to draw for each particle */
- /* (velocity, size and number) */
+ /* additional things to draw for each particle
+ * (velocity, size and number) */
if ((part->draw & PART_DRAW_VEL) && pdd && pdd->vedata) {
copy_v3_v3(pdd->ved, state.co);
pdd->ved += 3;
@@ -5079,21 +5429,21 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv
if (part->draw & PART_DRAW_NUM) {
if (a < totpart && (part->draw & PART_DRAW_HEALTH) && (part->phystype == PART_PHYS_BOIDS)) {
- numstr_len = BLI_snprintf(val_pos, sizeof(numstr), "%d:%.2f", a, pa_health);
+ numstr_len = BLI_snprintf_rlen(val_pos, sizeof(numstr), "%d:%.2f", a, pa_health);
}
else {
- numstr_len = BLI_snprintf(val_pos, sizeof(numstr), "%d", a);
+ numstr_len = BLI_snprintf_rlen(val_pos, sizeof(numstr), "%d", a);
}
}
else {
if (a < totpart && (part->draw & PART_DRAW_HEALTH) && (part->phystype == PART_PHYS_BOIDS)) {
- numstr_len = BLI_snprintf(val_pos, sizeof(numstr), "%.2f", pa_health);
+ numstr_len = BLI_snprintf_rlen(val_pos, sizeof(numstr), "%.2f", pa_health);
}
}
if (numstr[0]) {
- /* in path drawing state.co is the end point */
- /* use worldspace beause object matrix is already applied */
+ /* in path drawing state.co is the end point
+ * use worldspace because object matrix is already applied */
mul_v3_m4v3(vec_txt, ob->imat, state.co);
view3d_cached_text_draw_add(vec_txt, numstr, numstr_len,
10, V3D_CACHE_TEXT_WORLDSPACE | V3D_CACHE_TEXT_ASCII, tcol);
@@ -5110,7 +5460,7 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv
if (draw_as == PART_DRAW_PATH) {
ParticleCacheKey **cache, *path;
- float /* *cd2=NULL, */ /* UNUSED */ *cdata2 = NULL;
+ float *cdata2 = NULL;
/* setup gl flags */
if (1) { //ob_dt > OB_WIRE) {
@@ -5144,7 +5494,7 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv
cache = psys->pathcache;
for (a = 0, pa = psys->particles; a < totpart; a++, pa++) {
path = cache[a];
- if (path->steps > 0) {
+ if (path->segments > 0) {
glVertexPointer(3, GL_FLOAT, sizeof(ParticleCacheKey), path->co);
if (1) { //ob_dt > OB_WIRE) {
@@ -5156,7 +5506,138 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv
}
}
- glDrawArrays(GL_LINE_STRIP, 0, path->steps + 1);
+ glDrawArrays(GL_LINE_STRIP, 0, path->segments + 1);
+ }
+ }
+
+ if (part->type == PART_HAIR) {
+ if (part->draw & PART_DRAW_GUIDE_HAIRS) {
+ DerivedMesh *hair_dm = psys->hair_out_dm;
+
+ glDisable(GL_LIGHTING);
+ glDisable(GL_COLOR_MATERIAL);
+ glDisableClientState(GL_NORMAL_ARRAY);
+ glDisableClientState(GL_COLOR_ARRAY);
+
+ for (a = 0, pa = psys->particles; a < totpart; a++, pa++) {
+ if (pa->totkey > 1) {
+ HairKey *hkey = pa->hair;
+
+ glVertexPointer(3, GL_FLOAT, sizeof(HairKey), hkey->world_co);
+
+#if 0 /* XXX use proper theme color here */
+ UI_ThemeColor(TH_NORMAL);
+#else
+ glColor3f(0.58f, 0.67f, 1.0f);
+#endif
+
+ glDrawArrays(GL_LINE_STRIP, 0, pa->totkey);
+ }
+ }
+
+ if (hair_dm) {
+ MVert *mvert = hair_dm->getVertArray(hair_dm);
+ int i;
+
+ glColor3f(0.9f, 0.4f, 0.4f);
+
+ glBegin(GL_LINES);
+ for (a = 0, pa = psys->particles; a < totpart; a++, pa++) {
+ for (i = 1; i < pa->totkey; ++i) {
+ float v1[3], v2[3];
+
+ copy_v3_v3(v1, mvert[pa->hair_index + i - 1].co);
+ copy_v3_v3(v2, mvert[pa->hair_index + i].co);
+
+ mul_m4_v3(ob->obmat, v1);
+ mul_m4_v3(ob->obmat, v2);
+
+ glVertex3fv(v1);
+ glVertex3fv(v2);
+ }
+ }
+ glEnd();
+ }
+
+ glEnable(GL_LIGHTING);
+ glEnable(GL_COLOR_MATERIAL);
+ glEnableClientState(GL_NORMAL_ARRAY);
+ if ((dflag & DRAW_CONSTCOLOR) == 0)
+ if (part->draw_col == PART_DRAW_COL_MAT)
+ glEnableClientState(GL_COLOR_ARRAY);
+ }
+
+ if (part->draw & PART_DRAW_HAIR_GRID) {
+ ClothModifierData *clmd = psys->clmd;
+ if (clmd) {
+ float *a = clmd->hair_grid_min;
+ float *b = clmd->hair_grid_max;
+ int *res = clmd->hair_grid_res;
+ int i;
+
+ glDisable(GL_LIGHTING);
+ glDisable(GL_COLOR_MATERIAL);
+ glDisableClientState(GL_NORMAL_ARRAY);
+ glDisableClientState(GL_COLOR_ARRAY);
+
+ if (select)
+ UI_ThemeColor(TH_ACTIVE);
+ else
+ UI_ThemeColor(TH_WIRE);
+ glBegin(GL_LINES);
+ glVertex3f(a[0], a[1], a[2]); glVertex3f(b[0], a[1], a[2]);
+ glVertex3f(b[0], a[1], a[2]); glVertex3f(b[0], b[1], a[2]);
+ glVertex3f(b[0], b[1], a[2]); glVertex3f(a[0], b[1], a[2]);
+ glVertex3f(a[0], b[1], a[2]); glVertex3f(a[0], a[1], a[2]);
+
+ glVertex3f(a[0], a[1], b[2]); glVertex3f(b[0], a[1], b[2]);
+ glVertex3f(b[0], a[1], b[2]); glVertex3f(b[0], b[1], b[2]);
+ glVertex3f(b[0], b[1], b[2]); glVertex3f(a[0], b[1], b[2]);
+ glVertex3f(a[0], b[1], b[2]); glVertex3f(a[0], a[1], b[2]);
+
+ glVertex3f(a[0], a[1], a[2]); glVertex3f(a[0], a[1], b[2]);
+ glVertex3f(b[0], a[1], a[2]); glVertex3f(b[0], a[1], b[2]);
+ glVertex3f(a[0], b[1], a[2]); glVertex3f(a[0], b[1], b[2]);
+ glVertex3f(b[0], b[1], a[2]); glVertex3f(b[0], b[1], b[2]);
+ glEnd();
+
+ if (select)
+ UI_ThemeColorShadeAlpha(TH_ACTIVE, 0, -100);
+ else
+ UI_ThemeColorShadeAlpha(TH_WIRE, 0, -100);
+ glEnable(GL_BLEND);
+ glBegin(GL_LINES);
+ for (i = 1; i < res[0] - 1; ++i) {
+ float f = interpf(b[0], a[0], (float)i / (float)(res[0] - 1));
+ glVertex3f(f, a[1], a[2]); glVertex3f(f, b[1], a[2]);
+ glVertex3f(f, b[1], a[2]); glVertex3f(f, b[1], b[2]);
+ glVertex3f(f, b[1], b[2]); glVertex3f(f, a[1], b[2]);
+ glVertex3f(f, a[1], b[2]); glVertex3f(f, a[1], a[2]);
+ }
+ for (i = 1; i < res[1] - 1; ++i) {
+ float f = interpf(b[1], a[1], (float)i / (float)(res[1] - 1));
+ glVertex3f(a[0], f, a[2]); glVertex3f(b[0], f, a[2]);
+ glVertex3f(b[0], f, a[2]); glVertex3f(b[0], f, b[2]);
+ glVertex3f(b[0], f, b[2]); glVertex3f(a[0], f, b[2]);
+ glVertex3f(a[0], f, b[2]); glVertex3f(a[0], f, a[2]);
+ }
+ for (i = 1; i < res[2] - 1; ++i) {
+ float f = interpf(b[2], a[2], (float)i / (float)(res[2] - 1));
+ glVertex3f(a[0], a[1], f); glVertex3f(b[0], a[1], f);
+ glVertex3f(b[0], a[1], f); glVertex3f(b[0], b[1], f);
+ glVertex3f(b[0], b[1], f); glVertex3f(a[0], b[1], f);
+ glVertex3f(a[0], b[1], f); glVertex3f(a[0], a[1], f);
+ }
+ glEnd();
+ glDisable(GL_BLEND);
+
+ glEnable(GL_LIGHTING);
+ glEnable(GL_COLOR_MATERIAL);
+ glEnableClientState(GL_NORMAL_ARRAY);
+ if ((dflag & DRAW_CONSTCOLOR) == 0)
+ if (part->draw_col == PART_DRAW_COL_MAT)
+ glEnableClientState(GL_COLOR_ARRAY);
+ }
}
}
@@ -5175,10 +5656,9 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv
}
}
- glDrawArrays(GL_LINE_STRIP, 0, path->steps + 1);
+ glDrawArrays(GL_LINE_STRIP, 0, path->segments + 1);
}
-
/* restore & clean up */
if (1) { //ob_dt > OB_WIRE) {
if (part->draw_col == PART_DRAW_COL_MAT)
@@ -5186,9 +5666,10 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv
glDisable(GL_COLOR_MATERIAL);
}
- if (cdata2)
+ if (cdata2) {
MEM_freeN(cdata2);
- /* cd2 = */ /* UNUSED */ cdata2 = NULL;
+ cdata2 = NULL;
+ }
glLineWidth(1.0f);
@@ -5197,8 +5678,8 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv
for (a = 0, pa = psys->particles; a < totpart; a++, pa++) {
float vec_txt[3];
- numstr_len = BLI_snprintf(numstr, sizeof(numstr), "%i", a);
- /* use worldspace beause object matrix is already applied */
+ numstr_len = BLI_snprintf_rlen(numstr, sizeof(numstr), "%i", a);
+ /* use worldspace because object matrix is already applied */
mul_v3_m4v3(vec_txt, ob->imat, cache[a]->co);
view3d_cached_text_draw_add(vec_txt, numstr, numstr_len,
10, V3D_CACHE_TEXT_WORLDSPACE | V3D_CACHE_TEXT_ASCII, tcol);
@@ -5326,8 +5807,8 @@ static void draw_ptcache_edit(Scene *scene, View3D *v3d, PTCacheEdit *edit)
PTCacheEditPoint *point;
PTCacheEditKey *key;
ParticleEditSettings *pset = PE_settings(scene);
- int i, k, totpoint = edit->totpoint, timed = pset->flag & PE_FADE_TIME ? pset->fade_frames : 0;
- int steps = 1;
+ int i, k, totpoint = edit->totpoint, timed = (pset->flag & PE_FADE_TIME) ? pset->fade_frames : 0;
+ int totkeys = 1;
float sel_col[3];
float nosel_col[3];
float *pathcol = NULL, *pcol;
@@ -5346,10 +5827,10 @@ static void draw_ptcache_edit(Scene *scene, View3D *v3d, PTCacheEdit *edit)
UI_GetThemeColor3fv(TH_VERTEX, nosel_col);
/* draw paths */
- steps = (*edit->pathcache)->steps + 1;
+ totkeys = (*edit->pathcache)->segments + 1;
glEnable(GL_BLEND);
- pathcol = MEM_callocN(steps * 4 * sizeof(float), "particle path color data");
+ pathcol = MEM_callocN(totkeys * 4 * sizeof(float), "particle path color data");
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);
@@ -5369,7 +5850,7 @@ static void draw_ptcache_edit(Scene *scene, View3D *v3d, PTCacheEdit *edit)
glVertexPointer(3, GL_FLOAT, sizeof(ParticleCacheKey), path->co);
if (point->flag & PEP_HIDE) {
- for (k = 0, pcol = pathcol; k < steps; k++, pcol += 4) {
+ for (k = 0, pcol = pathcol; k < totkeys; k++, pcol += 4) {
copy_v3_v3(pcol, path->col);
pcol[3] = 0.25f;
}
@@ -5377,7 +5858,7 @@ static void draw_ptcache_edit(Scene *scene, View3D *v3d, PTCacheEdit *edit)
glColorPointer(4, GL_FLOAT, 4 * sizeof(float), pathcol);
}
else if (timed) {
- for (k = 0, pcol = pathcol, pkey = path; k < steps; k++, pkey++, pcol += 4) {
+ for (k = 0, pcol = pathcol, pkey = path; k < totkeys; k++, pkey++, pcol += 4) {
copy_v3_v3(pcol, pkey->col);
pcol[3] = 1.0f - fabsf((float)(CFRA) -pkey->time) / (float)pset->fade_frames;
}
@@ -5387,7 +5868,7 @@ static void draw_ptcache_edit(Scene *scene, View3D *v3d, PTCacheEdit *edit)
else
glColorPointer(3, GL_FLOAT, sizeof(ParticleCacheKey), path->col);
- glDrawArrays(GL_LINE_STRIP, 0, path->steps + 1);
+ glDrawArrays(GL_LINE_STRIP, 0, path->segments + 1);
}
if (pathcol) { MEM_freeN(pathcol); pathcol = pcol = NULL; }
@@ -5466,7 +5947,7 @@ static void draw_ptcache_edit(Scene *scene, View3D *v3d, PTCacheEdit *edit)
glColor3fv(nosel_col);
/* has to be like this.. otherwise selection won't work, have try glArrayElement later..*/
glBegin(GL_POINTS);
- glVertex3fv(key->flag & PEK_USE_WCO ? key->world_co : key->co);
+ glVertex3fv((key->flag & PEK_USE_WCO) ? key->world_co : key->co);
glEnd();
}
}
@@ -5482,9 +5963,9 @@ static void draw_ptcache_edit(Scene *scene, View3D *v3d, PTCacheEdit *edit)
glShadeModel(GL_FLAT);
if (v3d->zbuf) glEnable(GL_DEPTH_TEST);
glLineWidth(1.0f);
- glPointSize(1.0);
+ glPointSize(1.0f);
}
-//static void ob_draw_RE_motion(float com[3],float rotscale[3][3],float tw,float th)
+
static void ob_draw_RE_motion(float com[3], float rotscale[3][3], float itw, float ith, float drw_size)
{
float tr[3][3];
@@ -5771,8 +6252,8 @@ static void drawvertsN(Nurb *nu, const char sel, const bool hide_handles, const
if (bezt->hide == 0) {
if (sel == 1 && bezt == vert) {
UI_ThemeColor(TH_ACTIVE_VERT);
- bglVertex3fv(bezt->vec[1]);
+ if (bezt->f2 & SELECT) bglVertex3fv(bezt->vec[1]);
if (!hide_handles) {
if (bezt->f1 & SELECT) bglVertex3fv(bezt->vec[0]);
if (bezt->f3 & SELECT) bglVertex3fv(bezt->vec[2]);
@@ -5888,7 +6369,7 @@ static void draw_editnurb_splines(Object *ob, Nurb *nurb, const bool sel)
Nurb *nu;
BPoint *bp, *bp1;
int a, b, ofs, index;
- Curve *cu = (Curve *)ob->data;
+ Curve *cu = ob->data;
index = 0;
nu = nurb;
@@ -6248,7 +6729,7 @@ static void draw_empty_sphere(float size)
static GLuint displist = 0;
if (displist == 0) {
- GLUquadricObj *qobj;
+ GLUquadricObj *qobj;
displist = glGenLists(1);
glNewList(displist, GL_COMPILE);
@@ -6279,16 +6760,13 @@ static void draw_empty_sphere(float size)
/* draw a cone for use as an empty drawtype */
static void draw_empty_cone(float size)
{
- float cent = 0;
- float radius;
+ const float radius = size;
+
GLUquadricObj *qobj = gluNewQuadric();
gluQuadricDrawStyle(qobj, GLU_SILHOUETTE);
-
glPushMatrix();
- radius = size;
- glTranslatef(cent, cent, cent);
glScalef(radius, size * 2.0f, radius);
glRotatef(-90.0, 1.0, 0.0, 0.0);
gluCylinder(qobj, 1.0, 0.0, 1.0, 8, 1);
@@ -6301,7 +6779,7 @@ static void draw_empty_cone(float size)
static void drawspiral(const float cent[3], float rad, float tmat[4][4], int start)
{
float vec[3], vx[3], vy[3];
- const float tot_inv = (1.0f / (float)CIRCLE_RESOL);
+ const float tot_inv = 1.0f / (float)CIRCLE_RESOL;
int a;
bool inverse = false;
float x, y, fac;
@@ -6365,8 +6843,7 @@ static void drawspiral(const float cent[3], float rad, float tmat[4][4], int sta
}
/* draws a circle on x-z plane given the scaling of the circle, assuming that
- * all required matrices have been set (used for drawing empties)
- */
+ * all required matrices have been set (used for drawing empties) */
static void drawcircle_size(float size)
{
float x, y;
@@ -6374,7 +6851,7 @@ static void drawcircle_size(float size)
glBegin(GL_LINE_LOOP);
- /* coordinates are: cos(degrees * 11.25) = x, sin(degrees*11.25) = y, 0.0f = z */
+ /* coordinates are: cos(degrees * 11.25) = x, sin(degrees * 11.25) = y, 0.0f = z */
for (degrees = 0; degrees < CIRCLE_RESOL; degrees++) {
x = cosval[degrees];
y = sinval[degrees];
@@ -6518,31 +6995,23 @@ static void draw_forcefield(Object *ob, RegionView3D *rv3d,
PartDeflect *pd = ob->pd;
float imat[4][4], tmat[4][4];
float vec[3] = {0.0, 0.0, 0.0};
- float size;
-
/* scale size of circle etc with the empty drawsize */
- if (ob->type == OB_EMPTY) size = ob->empty_drawsize;
- else size = 1.0;
+ const float size = (ob->type == OB_EMPTY) ? ob->empty_drawsize : 1.0f;
/* calculus here, is reused in PFIELD_FORCE */
invert_m4_m4(imat, rv3d->viewmatob);
-// normalize_v3(imat[0]); /* we don't do this because field doesnt scale either... apart from wind! */
-// normalize_v3(imat[1]);
+#if 0
+ normalize_v3(imat[0]); /* we don't do this because field doesnt scale either... apart from wind! */
+ normalize_v3(imat[1]);
+#endif
if (pd->forcefield == PFIELD_WIND) {
- float force_val;
+ float force_val = pd->f_strength;
if ((dflag & DRAW_CONSTCOLOR) == 0) {
ob_wire_color_blend_theme_id(ob_wire_col, TH_BACK, 0.5f);
}
- //if (has_ipo_code(ob->ipo, OB_PD_FSTR))
- // force_val = IPO_GetFloatValue(ob->ipo, OB_PD_FSTR, scene->r.cfra);
- //else
- {
- force_val = pd->f_strength;
- }
-
unit_m4(tmat);
force_val *= 0.1f;
drawcircball(GL_LINE_LOOP, vec, size, tmat);
@@ -6556,14 +7025,7 @@ static void draw_forcefield(Object *ob, RegionView3D *rv3d,
}
else if (pd->forcefield == PFIELD_FORCE) {
- float ffall_val;
-
- //if (has_ipo_code(ob->ipo, OB_PD_FFALL))
- // ffall_val = IPO_GetFloatValue(ob->ipo, OB_PD_FFALL, scene->r.cfra);
- //else
- {
- ffall_val = pd->f_power;
- }
+ float ffall_val = pd->f_power;
if ((dflag & DRAW_CONSTCOLOR) == 0) ob_wire_color_blend_theme_id(ob_wire_col, TH_BACK, 0.5f);
drawcircball(GL_LINE_LOOP, vec, size, imat);
@@ -6573,20 +7035,9 @@ static void draw_forcefield(Object *ob, RegionView3D *rv3d,
drawcircball(GL_LINE_LOOP, vec, size * 2.0f, imat);
}
else if (pd->forcefield == PFIELD_VORTEX) {
- float /*ffall_val,*/ force_val;
+ float force_val = pd->f_strength;
unit_m4(tmat);
- //if (has_ipo_code(ob->ipo, OB_PD_FFALL))
- // ffall_val = IPO_GetFloatValue(ob->ipo, OB_PD_FFALL, scene->r.cfra);
- //else
- // ffall_val = pd->f_power;
-
- //if (has_ipo_code(ob->ipo, OB_PD_FSTR))
- // force_val = IPO_GetFloatValue(ob->ipo, OB_PD_FSTR, scene->r.cfra);
- //else
- {
- force_val = pd->f_strength;
- }
if ((dflag & DRAW_CONSTCOLOR) == 0) {
ob_wire_color_blend_theme_id(ob_wire_col, TH_BACK, 0.7f);
@@ -6604,25 +7055,19 @@ static void draw_forcefield(Object *ob, RegionView3D *rv3d,
else if (pd->forcefield == PFIELD_GUIDE && ob->type == OB_CURVE) {
Curve *cu = ob->data;
if ((cu->flag & CU_PATH) && ob->curve_cache->path && ob->curve_cache->path->data) {
- float mindist, guidevec1[4], guidevec2[3];
-
- //if (has_ipo_code(ob->ipo, OB_PD_FSTR))
- // mindist = IPO_GetFloatValue(ob->ipo, OB_PD_FSTR, scene->r.cfra);
- //else
- {
- mindist = pd->f_strength;
- }
+ float guidevec1[4], guidevec2[3];
+ float mindist = pd->f_strength;
if ((dflag & DRAW_CONSTCOLOR) == 0) {
ob_wire_color_blend_theme_id(ob_wire_col, TH_BACK, 0.5f);
}
- /*path end*/
+ /* path end */
setlinestyle(3);
where_on_path(ob, 1.0f, guidevec1, guidevec2, NULL, NULL, NULL);
drawcircball(GL_LINE_LOOP, guidevec1, mindist, imat);
- /*path beginning*/
+ /* path beginning */
setlinestyle(0);
where_on_path(ob, 0.0f, guidevec1, guidevec2, NULL, NULL, NULL);
drawcircball(GL_LINE_LOOP, guidevec1, mindist, imat);
@@ -6693,19 +7138,31 @@ static void draw_forcefield(Object *ob, RegionView3D *rv3d,
setlinestyle(0);
}
-static void draw_box(float vec[8][3])
+static void draw_box(float vec[8][3], bool solid)
{
- glBegin(GL_LINE_STRIP);
- glVertex3fv(vec[0]); glVertex3fv(vec[1]); glVertex3fv(vec[2]); glVertex3fv(vec[3]);
- glVertex3fv(vec[0]); glVertex3fv(vec[4]); glVertex3fv(vec[5]); glVertex3fv(vec[6]);
- glVertex3fv(vec[7]); glVertex3fv(vec[4]);
- glEnd();
+ if (!solid) {
+ glBegin(GL_LINE_STRIP);
+ glVertex3fv(vec[0]); glVertex3fv(vec[1]); glVertex3fv(vec[2]); glVertex3fv(vec[3]);
+ glVertex3fv(vec[0]); glVertex3fv(vec[4]); glVertex3fv(vec[5]); glVertex3fv(vec[6]);
+ glVertex3fv(vec[7]); glVertex3fv(vec[4]);
+ glEnd();
- glBegin(GL_LINES);
- glVertex3fv(vec[1]); glVertex3fv(vec[5]);
- glVertex3fv(vec[2]); glVertex3fv(vec[6]);
- glVertex3fv(vec[3]); glVertex3fv(vec[7]);
- glEnd();
+ glBegin(GL_LINES);
+ glVertex3fv(vec[1]); glVertex3fv(vec[5]);
+ glVertex3fv(vec[2]); glVertex3fv(vec[6]);
+ glVertex3fv(vec[3]); glVertex3fv(vec[7]);
+ glEnd();
+ }
+ else {
+ glBegin(GL_QUADS);
+ glVertex3fv(vec[0]); glVertex3fv(vec[1]); glVertex3fv(vec[2]); glVertex3fv(vec[3]);
+ glVertex3fv(vec[7]); glVertex3fv(vec[6]); glVertex3fv(vec[5]); glVertex3fv(vec[4]);
+ glVertex3fv(vec[4]); glVertex3fv(vec[5]); glVertex3fv(vec[1]); glVertex3fv(vec[0]);
+ glVertex3fv(vec[3]); glVertex3fv(vec[2]); glVertex3fv(vec[6]); glVertex3fv(vec[7]);
+ glVertex3fv(vec[3]); glVertex3fv(vec[7]); glVertex3fv(vec[4]); glVertex3fv(vec[0]);
+ glVertex3fv(vec[1]); glVertex3fv(vec[5]); glVertex3fv(vec[6]); glVertex3fv(vec[2]);
+ glEnd();
+ }
}
static void draw_bb_quadric(BoundBox *bb, char type, bool around_origin)
@@ -6727,7 +7184,7 @@ static void draw_bb_quadric(BoundBox *bb, char type, bool around_origin)
glPushMatrix();
if (type == OB_BOUND_SPHERE) {
float scale = MAX3(size[0], size[1], size[2]);
- glTranslatef(cent[0], cent[1], cent[2]);
+ glTranslate3fv(cent);
glScalef(scale, scale, scale);
gluSphere(qobj, 1.0, 8, 5);
}
@@ -6776,6 +7233,9 @@ static void draw_bounding_volume(Object *ob, char type)
else if (ob->type == OB_ARMATURE) {
bb = BKE_armature_boundbox_get(ob);
}
+ else if (ob->type == OB_LATTICE) {
+ bb = BKE_lattice_boundbox_get(ob);
+ }
else {
const float min[3] = {-1.0f, -1.0f, -1.0f}, max[3] = {1.0f, 1.0f, 1.0f};
bb = &bb_local;
@@ -6799,7 +7259,7 @@ static void draw_bounding_volume(Object *ob, char type)
vec[0][2] = vec[3][2] = vec[4][2] = vec[7][2] = -size[2];
vec[1][2] = vec[2][2] = vec[5][2] = vec[6][2] = +size[2];
- draw_box(vec);
+ draw_box(vec, false);
}
else {
draw_bb_quadric(bb, type, true);
@@ -6807,7 +7267,7 @@ static void draw_bounding_volume(Object *ob, char type)
}
else {
if (type == OB_BOUND_BOX)
- draw_box(bb->vec);
+ draw_box(bb->vec, false);
else
draw_bb_quadric(bb, type, false);
}
@@ -6843,7 +7303,7 @@ static void drawtexspace(Object *ob)
setlinestyle(2);
- draw_box(vec);
+ draw_box(vec, false);
setlinestyle(0);
}
@@ -6859,17 +7319,20 @@ static void drawObjectSelect(Scene *scene, View3D *v3d, ARegion *ar, Base *base,
glDepthMask(0);
if (ELEM(ob->type, OB_FONT, OB_CURVE, OB_SURF)) {
- DerivedMesh *dm = ob->derivedFinal;
+ DerivedMesh *dm;
bool has_faces = false;
- if (dm)
- DM_update_materials(dm, ob);
#ifdef SEQUENCER_DAG_WORKAROUND
ensure_curve_cache(scene, ob);
#endif
+ dm = ob->derivedFinal;
if (dm) {
- has_faces = dm->getNumTessFaces(dm) > 0;
+ DM_update_materials(dm, ob);
+ }
+
+ if (dm) {
+ has_faces = (dm->getNumPolys(dm) != 0);
}
else {
has_faces = BKE_displist_has_faces(&ob->curve_cache->disp);
@@ -7027,7 +7490,7 @@ static void draw_object_wire_color(Scene *scene, Base *base, unsigned char r_ob_
else {
if (ob->flag & OB_FROMGROUP) {
if (base->flag & (SELECT + BA_WAS_SEL)) {
- /* uses darker active color for non-active + selected*/
+ /* uses darker active color for non-active + selected */
theme_id = TH_GROUP_ACTIVE;
if (scene->basact != base) {
@@ -7081,8 +7544,11 @@ static void draw_object_matcap_check(View3D *v3d, Object *ob)
v3d->defmaterial->preview = NULL;
}
/* first time users */
- if (v3d->matcap_icon == 0)
+ if (v3d->matcap_icon < ICON_MATCAP_01 ||
+ v3d->matcap_icon > ICON_MATCAP_24)
+ {
v3d->matcap_icon = ICON_MATCAP_01;
+ }
if (v3d->defmaterial->preview == NULL)
v3d->defmaterial->preview = UI_icon_to_preview(v3d->matcap_icon);
@@ -7114,7 +7580,7 @@ static void draw_rigidbody_shape(Object *ob)
vec[0][2] = vec[3][2] = vec[4][2] = vec[7][2] = -size[2];
vec[1][2] = vec[2][2] = vec[5][2] = vec[6][2] = +size[2];
- draw_box(vec);
+ draw_box(vec, false);
break;
case RB_SHAPE_SPHERE:
draw_bb_quadric(bb, OB_BOUND_SPHERE, true);
@@ -7151,7 +7617,8 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short
const bool render_override = (v3d->flag2 & V3D_RENDER_OVERRIDE) != 0;
const bool is_picking = (G.f & G_PICKSEL) != 0;
const bool has_particles = (ob->particlesystem.first != NULL);
- bool particle_skip_object = false; /* Draw particles but not their emitter object. */
+ bool skip_object = false; /* Draw particles but not their emitter object. */
+ SmokeModifierData *smd = NULL;
if (ob != scene->obedit) {
if (ob->restrictflag & OB_RESTRICT_VIEW)
@@ -7175,17 +7642,37 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short
if (ob->mode == OB_MODE_OBJECT) {
ParticleSystem *psys;
- particle_skip_object = render_override;
+ skip_object = render_override;
for (psys = ob->particlesystem.first; psys; psys = psys->next) {
/* Once we have found a psys which renders its emitter object, we are done. */
if (psys->part->draw & PART_DRAW_EMITTER) {
- particle_skip_object = false;
+ skip_object = false;
break;
}
}
}
}
+ if ((md = modifiers_findByType(ob, eModifierType_Smoke)) && (modifier_isEnabled(scene, md, eModifierMode_Realtime))) {
+ smd = (SmokeModifierData *)md;
+
+ if (smd->domain) {
+ if (!v3d->transp && (dflag & DRAW_PICKING) == 0) {
+ if (!v3d->xray && !(ob->dtx & OB_DRAWXRAY)) {
+ /* object has already been drawn so skip drawing it */
+ ED_view3d_after_add(&v3d->afterdraw_transp, base, dflag);
+ return;
+ }
+ else if (v3d->xray) {
+ /* object has already been drawn so skip drawing it */
+ ED_view3d_after_add(&v3d->afterdraw_xraytransp, base, dflag);
+ return;
+ }
+ }
+ }
+ }
+
+
/* xray delay? */
if ((dflag & DRAW_PICKING) == 0 && (base->flag & OB_FROMDUPLI) == 0 && (v3d->flag2 & V3D_RENDER_SHADOW) == 0) {
/* don't do xray in particle mode, need the z-buffer */
@@ -7257,7 +7744,7 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short
if (ob->mode & (OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT | OB_MODE_TEXTURE_PAINT)) {
if (ob->type == OB_MESH) {
if (dt < OB_SOLID) {
- zbufoff = 1;
+ zbufoff = true;
dt = OB_SOLID;
}
@@ -7284,13 +7771,12 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short
if (dt >= OB_BOUNDBOX) {
dtx = ob->dtx;
if (ob->mode & OB_MODE_EDIT) {
- // the only 2 extra drawtypes alowed in editmode
+ /* the only 2 extra drawtypes alowed in editmode */
dtx = dtx & (OB_DRAWWIRE | OB_TEXSPACE);
}
-
}
- if (!particle_skip_object) {
+ if (!skip_object) {
/* draw outline for selected objects, mesh does itself */
if ((v3d->flag & V3D_SELECT_OUTLINE) && !render_override && ob->type != OB_MESH) {
if (dt > OB_WIRE && (ob->mode & OB_MODE_EDIT) == 0 && (dflag & DRAW_SCENESET) == 0) {
@@ -7345,9 +7831,6 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short
}
else if (ED_view3d_boundbox_clip(rv3d, ob->bb)) {
empty_object = drawDispList(scene, v3d, rv3d, base, dt, dflag, ob_wire_col);
-
-//XXX old animsys if (cu->path)
-// curve_draw_speed(scene, ob);
}
break;
case OB_MBALL:
@@ -7512,12 +7995,10 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short
}
/* draw code for smoke */
- if ((md = modifiers_findByType(ob, eModifierType_Smoke))) {
- SmokeModifierData *smd = (SmokeModifierData *)md;
-
- // draw collision objects
- if ((smd->type & MOD_SMOKE_TYPE_COLL) && smd->coll) {
+ if (smd) {
#if 0
+ /* draw collision objects */
+ if ((smd->type & MOD_SMOKE_TYPE_COLL) && smd->coll) {
SmokeCollSettings *scs = smd->coll;
if (scs->points) {
size_t i;
@@ -7544,30 +8025,30 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short
glDisable(GL_BLEND);
glDepthMask(GL_TRUE);
if (col) cpack(col);
-
}
-#endif
}
+#endif
/* only draw domains */
if (smd->domain) {
SmokeDomainSettings *sds = smd->domain;
- float p0[3], p1[3], viewnormal[3];
- BoundBox bb;
+ float viewnormal[3];
glLoadMatrixf(rv3d->viewmat);
glMultMatrixf(ob->obmat);
/* draw adaptive domain bounds */
- if (sds->flags & MOD_SMOKE_ADAPTIVE_DOMAIN) {
+ if ((sds->flags & MOD_SMOKE_ADAPTIVE_DOMAIN) && !render_override) {
+ float p0[3], p1[3];
+ BoundBox bb;
/* draw domain max bounds */
VECSUBFAC(p0, sds->p0, sds->cell_size, sds->adapt_res);
VECADDFAC(p1, sds->p1, sds->cell_size, sds->adapt_res);
BKE_boundbox_init_from_minmax(&bb, p0, p1);
- draw_box(bb.vec);
+ draw_box(bb.vec, false);
- /* draw base resolution bounds */
#if 0
+ /* draw base resolution bounds */
BKE_boundbox_init_from_minmax(&bb, sds->p0, sds->p1);
draw_box(bb.vec);
#endif
@@ -7575,16 +8056,16 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short
/* don't show smoke before simulation starts, this could be made an option in the future */
if (smd->domain->fluid && CFRA >= smd->domain->point_cache[0]->startframe) {
+ float p0[3], p1[3];
- // get view vector
- copy_v3_v3(viewnormal, rv3d->viewinv[2]);
+ /* get view vector */
invert_m4_m4(ob->imat, ob->obmat);
- mul_mat3_m4_v3(ob->imat, viewnormal);
+ mul_v3_mat3_m4v3(viewnormal, ob->imat, rv3d->viewinv[2]);
normalize_v3(viewnormal);
/* set dynamic boundaries to draw the volume
- * also scale cube to global space to equalize volume slicing on all axises
- * (its scaled back before drawing) */
+ * also scale cube to global space to equalize volume slicing on all axes
+ * (it's scaled back before drawing) */
p0[0] = (sds->p0[0] + sds->cell_size[0] * sds->res_min[0] + sds->obj_shift_f[0]) * fabsf(ob->size[0]);
p0[1] = (sds->p0[1] + sds->cell_size[1] * sds->res_min[1] + sds->obj_shift_f[1]) * fabsf(ob->size[1]);
p0[2] = (sds->p0[2] + sds->cell_size[2] * sds->res_min[2] + sds->obj_shift_f[2]) * fabsf(ob->size[2]);
@@ -7668,7 +8149,6 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short
view3d_cached_text_draw_add(zero, ob->id.name + 2, strlen(ob->id.name + 2), 10, 0, ob_wire_col);
}
}
- /*if (dtx & OB_DRAWIMAGE) drawDispListwire(&ob->disp);*/
if ((dtx & OB_DRAWWIRE) && dt >= OB_SOLID) {
if ((dflag & DRAW_CONSTCOLOR) == 0) {
draw_wire_extra(scene, rv3d, ob, ob_wire_col);
@@ -7679,10 +8159,10 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short
if ((dt <= OB_SOLID) && !render_override) {
if (((ob->gameflag & OB_DYNAMIC) &&
- !ELEM(ob->collision_boundtype, OB_BOUND_TRIANGLE_MESH, OB_BOUND_CONVEX_HULL)) ||
+ ((ob->gameflag & OB_BOUNDS) == 0)) ||
((ob->gameflag & OB_BOUNDS) &&
- (ob->boundtype == OB_BOUND_SPHERE)))
+ (ob->collision_boundtype == OB_BOUND_SPHERE)))
{
float imat[4][4], vec[3] = {0.0f, 0.0f, 0.0f};
@@ -7723,7 +8203,7 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short
if (render_override) {
/* don't draw */
}
- else if ((scene->basact) == base)
+ else if (is_obact)
do_draw_center = ACTIVE;
else if (base->flag & SELECT)
do_draw_center = SELECT;
@@ -7784,7 +8264,7 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short
if (ELEM(curcon->type, CONSTRAINT_TYPE_FOLLOWTRACK, CONSTRAINT_TYPE_OBJECTSOLVER)) {
/* special case for object solver and follow track constraints because they don't fill
* constraint targets properly (design limitation -- scene is needed for their target
- * but it can't be accessed from get_targets callvack) */
+ * but it can't be accessed from get_targets callback) */
Object *camob = NULL;
@@ -7809,7 +8289,7 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short
}
}
else {
- bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(curcon);
+ const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(curcon);
if ((cti && cti->get_constraint_targets) && (curcon->flag & CONSTRAINT_EXPAND)) {
ListBase targets = {NULL, NULL};
@@ -7975,7 +8455,7 @@ static void bbs_mesh_solid_EM(BMEditMesh *em, Scene *scene, View3D *v3d,
cpack(0);
if (use_faceselect) {
- dm->drawMappedFaces(dm, bbs_mesh_solid__setSolidDrawOptions, GPU_enable_material, NULL, em->bm, 0);
+ dm->drawMappedFaces(dm, bbs_mesh_solid__setSolidDrawOptions, NULL, NULL, em->bm, DM_DRAW_SKIP_HIDDEN | DM_DRAW_SELECT_USE_EDITMODE);
if (check_ob_drawface_dot(scene, v3d, ob->dt)) {
glPointSize(UI_GetThemeValuef(TH_FACEDOT_SIZE));
@@ -7987,7 +8467,7 @@ static void bbs_mesh_solid_EM(BMEditMesh *em, Scene *scene, View3D *v3d,
}
else {
- dm->drawMappedFaces(dm, bbs_mesh_mask__setSolidDrawOptions, GPU_enable_material, NULL, em->bm, 0);
+ dm->drawMappedFaces(dm, bbs_mesh_mask__setSolidDrawOptions, NULL, NULL, em->bm, DM_DRAW_SKIP_SELECT | DM_DRAW_SKIP_HIDDEN | DM_DRAW_SELECT_USE_EDITMODE);
}
}
@@ -8031,7 +8511,7 @@ static void bbs_mesh_solid_verts(Scene *scene, Object *ob)
DM_update_materials(dm, ob);
- dm->drawMappedFaces(dm, bbs_mesh_solid_hide2__setDrawOpts, GPU_enable_material, NULL, me, 0);
+ dm->drawMappedFaces(dm, bbs_mesh_solid_hide2__setDrawOpts, GPU_enable_material, NULL, me, DM_DRAW_SKIP_HIDDEN);
bbs_obmode_mesh_verts(ob, dm, 1);
bm_vertoffs = me->totvert + 1;
@@ -8041,16 +8521,16 @@ static void bbs_mesh_solid_verts(Scene *scene, Object *ob)
static void bbs_mesh_solid_faces(Scene *scene, Object *ob)
{
DerivedMesh *dm = mesh_get_derived_final(scene, ob, scene->customdata_mask);
- Mesh *me = (Mesh *)ob->data;
+ Mesh *me = ob->data;
glColor3ub(0, 0, 0);
DM_update_materials(dm, ob);
if ((me->editflag & ME_EDIT_PAINT_FACE_SEL))
- dm->drawMappedFaces(dm, bbs_mesh_solid_hide__setDrawOpts, GPU_enable_material, NULL, me, 0);
+ dm->drawMappedFaces(dm, bbs_mesh_solid_hide__setDrawOpts, NULL, NULL, me, DM_DRAW_SKIP_HIDDEN);
else
- dm->drawMappedFaces(dm, bbs_mesh_solid__setDrawOpts, GPU_enable_material, NULL, me, 0);
+ dm->drawMappedFaces(dm, bbs_mesh_solid__setDrawOpts, NULL, NULL, me, 0);
dm->release(dm);
}
diff --git a/source/blender/editors/space_view3d/drawsimdebug.c b/source/blender/editors/space_view3d/drawsimdebug.c
new file mode 100644
index 00000000000..46320ba6763
--- /dev/null
+++ b/source/blender/editors/space_view3d/drawsimdebug.c
@@ -0,0 +1,166 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2014 by the Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Lukas Toenne
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/editors/space_view3d/drawsimdebug.c
+ * \ingroup spview3d
+ */
+
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_view3d_types.h"
+#include "DNA_object_types.h"
+
+#include "BLI_math.h"
+#include "BLI_utildefines.h"
+#include "BLI_ghash.h"
+
+#include "BKE_effect.h"
+
+#include "view3d_intern.h"
+
+#include "BIF_gl.h"
+
+
+static void draw_sim_debug_elements(SimDebugData *debug_data, float imat[4][4])
+{
+ GHashIterator iter;
+
+ /**** dots ****/
+
+ glPointSize(3.0f);
+ glBegin(GL_POINTS);
+ for (BLI_ghashIterator_init(&iter, debug_data->gh); !BLI_ghashIterator_done(&iter); BLI_ghashIterator_step(&iter)) {
+ SimDebugElement *elem = BLI_ghashIterator_getValue(&iter);
+ if (elem->type != SIM_DEBUG_ELEM_DOT)
+ continue;
+
+ glColor3f(elem->color[0], elem->color[1], elem->color[2]);
+ glVertex3f(elem->v1[0], elem->v1[1], elem->v1[2]);
+ }
+ glEnd();
+ glPointSize(1.0f);
+
+ /**** circles ****/
+
+ {
+ float circle[16][2] = {
+ {0.000000, 1.000000}, {0.382683, 0.923880}, {0.707107, 0.707107}, {0.923880, 0.382683},
+ {1.000000, -0.000000}, {0.923880, -0.382683}, {0.707107, -0.707107}, {0.382683, -0.923880},
+ {-0.000000, -1.000000}, {-0.382683, -0.923880}, {-0.707107, -0.707107}, {-0.923879, -0.382684},
+ {-1.000000, 0.000000}, {-0.923879, 0.382684}, {-0.707107, 0.707107}, {-0.382683, 0.923880} };
+ for (BLI_ghashIterator_init(&iter, debug_data->gh); !BLI_ghashIterator_done(&iter); BLI_ghashIterator_step(&iter)) {
+ SimDebugElement *elem = BLI_ghashIterator_getValue(&iter);
+ float radius = elem->v2[0];
+ float co[3];
+ int i;
+
+ if (elem->type != SIM_DEBUG_ELEM_CIRCLE)
+ continue;
+
+ glColor3f(elem->color[0], elem->color[1], elem->color[2]);
+ glBegin(GL_LINE_LOOP);
+ for (i = 0; i < 16; ++i) {
+ co[0] = radius * circle[i][0];
+ co[1] = radius * circle[i][1];
+ co[2] = 0.0f;
+ mul_mat3_m4_v3(imat, co);
+ add_v3_v3(co, elem->v1);
+
+ glVertex3f(co[0], co[1], co[2]);
+ }
+ glEnd();
+ }
+ }
+
+ /**** lines ****/
+
+ glBegin(GL_LINES);
+ for (BLI_ghashIterator_init(&iter, debug_data->gh); !BLI_ghashIterator_done(&iter); BLI_ghashIterator_step(&iter)) {
+ SimDebugElement *elem = BLI_ghashIterator_getValue(&iter);
+ if (elem->type != SIM_DEBUG_ELEM_LINE)
+ continue;
+
+ glColor3f(elem->color[0], elem->color[1], elem->color[2]);
+ glVertex3f(elem->v1[0], elem->v1[1], elem->v1[2]);
+ glVertex3f(elem->v2[0], elem->v2[1], elem->v2[2]);
+ }
+ glEnd();
+
+ /**** vectors ****/
+
+ glPointSize(2.0f);
+ glBegin(GL_POINTS);
+ for (BLI_ghashIterator_init(&iter, debug_data->gh); !BLI_ghashIterator_done(&iter); BLI_ghashIterator_step(&iter)) {
+ SimDebugElement *elem = BLI_ghashIterator_getValue(&iter);
+ if (elem->type != SIM_DEBUG_ELEM_VECTOR)
+ continue;
+
+ glColor3f(elem->color[0], elem->color[1], elem->color[2]);
+ glVertex3f(elem->v1[0], elem->v1[1], elem->v1[2]);
+ }
+ glEnd();
+ glPointSize(1.0f);
+
+ glBegin(GL_LINES);
+ for (BLI_ghashIterator_init(&iter, debug_data->gh); !BLI_ghashIterator_done(&iter); BLI_ghashIterator_step(&iter)) {
+ SimDebugElement *elem = BLI_ghashIterator_getValue(&iter);
+ float t[3];
+ if (elem->type != SIM_DEBUG_ELEM_VECTOR)
+ continue;
+
+ glColor3f(elem->color[0], elem->color[1], elem->color[2]);
+ glVertex3f(elem->v1[0], elem->v1[1], elem->v1[2]);
+ add_v3_v3v3(t, elem->v1, elem->v2);
+ glVertex3f(t[0], t[1], t[2]);
+ }
+ glEnd();
+}
+
+void draw_sim_debug_data(Scene *UNUSED(scene), View3D *UNUSED(v3d), ARegion *ar)
+{
+ RegionView3D *rv3d = ar->regiondata;
+ /*Object *ob = base->object;*/
+ float imat[4][4];
+
+ if (!_sim_debug_data)
+ return;
+
+ invert_m4_m4(imat, rv3d->viewmatob);
+
+// glDepthMask(GL_FALSE);
+// glEnable(GL_BLEND);
+
+ glPushMatrix();
+
+ glLoadMatrixf(rv3d->viewmat);
+ draw_sim_debug_elements(_sim_debug_data, imat);
+
+ glPopMatrix();
+
+// glDepthMask(GL_TRUE);
+// glDisable(GL_BLEND);
+}
diff --git a/source/blender/editors/space_view3d/drawvolume.c b/source/blender/editors/space_view3d/drawvolume.c
index 59798f97d93..d6691f431dd 100644
--- a/source/blender/editors/space_view3d/drawvolume.c
+++ b/source/blender/editors/space_view3d/drawvolume.c
@@ -27,8 +27,6 @@
* \ingroup spview3d
*/
-
-
#include <string.h>
#include <math.h>
@@ -38,7 +36,6 @@
#include "DNA_screen_types.h"
#include "DNA_smoke_types.h"
#include "DNA_view3d_types.h"
-#include "DNA_property_types.h"
#include "BLI_utildefines.h"
#include "BLI_math.h"
@@ -51,10 +48,6 @@
#include "GPU_extensions.h"
-#include "ED_mesh.h"
-
-#include "BLF_api.h"
-
#include "view3d_intern.h" // own include
struct GPUTexture;
@@ -112,7 +105,7 @@ void draw_smoke_volume(SmokeDomainSettings *sds, Object *ob,
float cor[3] = {1.0f, 1.0f, 1.0f};
int gl_depth = 0, gl_blend = 0;
- int use_fire = (sds->active_fields & SM_ACTIVE_FIRE);
+ const bool use_fire = (sds->active_fields & SM_ACTIVE_FIRE) != 0;
/* draw slices of smoke is adapted from c++ code authored
* by: Johannes Schmid and Ingemar Rask, 2006, johnny@grob.org */
@@ -142,76 +135,8 @@ void draw_smoke_volume(SmokeDomainSettings *sds, Object *ob,
unsigned char *spec_data;
float *spec_pixels;
GPUTexture *tex_spec;
-
- /* Fragment program to calculate the view3d of smoke */
- /* using 4 textures, density, shadow, flame and flame spectrum */
- const char *shader_basic =
- "!!ARBfp1.0\n"
- "PARAM dx = program.local[0];\n"
- "PARAM darkness = program.local[1];\n"
- "PARAM render = program.local[2];\n"
- "PARAM f = {1.442695041, 1.442695041, 1.442695041, 0.01};\n"
- "TEMP temp, shadow, flame, spec, value;\n"
- "TEX temp, fragment.texcoord[0], texture[0], 3D;\n"
- "TEX shadow, fragment.texcoord[0], texture[1], 3D;\n"
- "TEX flame, fragment.texcoord[0], texture[2], 3D;\n"
- "TEX spec, flame.r, texture[3], 1D;\n"
- /* calculate shading factor from density */
- "MUL value.r, temp.a, darkness.a;\n"
- "MUL value.r, value.r, dx.r;\n"
- "MUL value.r, value.r, f.r;\n"
- "EX2 temp, -value.r;\n"
- /* alpha */
- "SUB temp.a, 1.0, temp.r;\n"
- /* shade colors */
- "MUL temp.r, temp.r, shadow.r;\n"
- "MUL temp.g, temp.g, shadow.r;\n"
- "MUL temp.b, temp.b, shadow.r;\n"
- "MUL temp.r, temp.r, darkness.r;\n"
- "MUL temp.g, temp.g, darkness.g;\n"
- "MUL temp.b, temp.b, darkness.b;\n"
- /* for now this just replace smoke shading if rendering fire */
- "CMP result.color, render.r, temp, spec;\n"
- "END\n";
-
- /* color shader */
- const char *shader_color =
- "!!ARBfp1.0\n"
- "PARAM dx = program.local[0];\n"
- "PARAM darkness = program.local[1];\n"
- "PARAM render = program.local[2];\n"
- "PARAM f = {1.442695041, 1.442695041, 1.442695041, 1.442695041};\n"
- "TEMP temp, shadow, flame, spec, value;\n"
- "TEX temp, fragment.texcoord[0], texture[0], 3D;\n"
- "TEX shadow, fragment.texcoord[0], texture[1], 3D;\n"
- "TEX flame, fragment.texcoord[0], texture[2], 3D;\n"
- "TEX spec, flame.r, texture[3], 1D;\n"
- /* unpremultiply volume texture */
- "RCP value.r, temp.a;\n"
- "MUL temp.r, temp.r, value.r;\n"
- "MUL temp.g, temp.g, value.r;\n"
- "MUL temp.b, temp.b, value.r;\n"
- /* calculate shading factor from density */
- "MUL value.r, temp.a, darkness.a;\n"
- "MUL value.r, value.r, dx.r;\n"
- "MUL value.r, value.r, f.r;\n"
- "EX2 value.r, -value.r;\n"
- /* alpha */
- "SUB temp.a, 1.0, value.r;\n"
- /* shade colors */
- "MUL temp.r, temp.r, shadow.r;\n"
- "MUL temp.g, temp.g, shadow.r;\n"
- "MUL temp.b, temp.b, shadow.r;\n"
- "MUL temp.r, temp.r, value.r;\n"
- "MUL temp.g, temp.g, value.r;\n"
- "MUL temp.b, temp.b, value.r;\n"
- /* for now this just replace smoke shading if rendering fire */
- "CMP result.color, render.r, temp, spec;\n"
- "END\n";
-
- GLuint prog;
-
-
+ GPUProgram *smoke_program;
+ int progtype = (sds->active_fields & SM_ACTIVE_COLORS) ? GPU_PROGRAM_SMOKE_COLORED : GPU_PROGRAM_SMOKE;
float size[3];
if (!tex) {
@@ -328,8 +253,7 @@ void draw_smoke_volume(SmokeDomainSettings *sds, Object *ob,
glGetBooleanv(GL_BLEND, (GLboolean *)&gl_blend);
glGetBooleanv(GL_DEPTH_TEST, (GLboolean *)&gl_depth);
- glDepthMask(GL_FALSE);
- glDisable(GL_DEPTH_TEST);
+ glEnable(GL_DEPTH_TEST);
glEnable(GL_BLEND);
/* find cube vertex that is closest to the viewer */
@@ -356,24 +280,17 @@ void draw_smoke_volume(SmokeDomainSettings *sds, Object *ob,
// printf("i: %d\n", i);
// printf("point %f, %f, %f\n", cv[i][0], cv[i][1], cv[i][2]);
- if (GL_TRUE == glewIsSupported("GL_ARB_fragment_program")) {
- glEnable(GL_FRAGMENT_PROGRAM_ARB);
- glGenProgramsARB(1, &prog);
-
- glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, prog);
- /* set shader */
- if (sds->active_fields & SM_ACTIVE_COLORS)
- glProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, (GLsizei)strlen(shader_color), shader_color);
- else
- glProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, (GLsizei)strlen(shader_basic), shader_basic);
+ smoke_program = GPU_shader_get_builtin_program(progtype);
+ if (smoke_program) {
+ GPU_program_bind(smoke_program);
/* cell spacing */
- glProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 0, dx, dx, dx, 1.0);
+ GPU_program_parameter_4f(smoke_program, 0, dx, dx, dx, 1.0);
/* custom parameter for smoke style (higher = thicker) */
if (sds->active_fields & SM_ACTIVE_COLORS)
- glProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 1, 1.0, 1.0, 1.0, 10.0);
+ GPU_program_parameter_4f(smoke_program, 1, 1.0, 1.0, 1.0, 10.0);
else
- glProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 1, sds->active_color[0], sds->active_color[1], sds->active_color[2], 10.0);
+ GPU_program_parameter_4f(smoke_program, 1, sds->active_color[0], sds->active_color[1], sds->active_color[2], 10.0);
}
else
printf("Your gfx card does not support 3D View smoke drawing.\n");
@@ -453,7 +370,7 @@ void draw_smoke_volume(SmokeDomainSettings *sds, Object *ob,
else
glBlendFunc(GL_SRC_ALPHA, GL_ONE);
- glProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 2, 1.0, 0.0, 0.0, 0.0);
+ GPU_program_parameter_4f(smoke_program, 2, 1.0, 0.0, 0.0, 0.0);
glBegin(GL_POLYGON);
glColor3f(1.0, 1.0, 1.0);
for (i = 0; i < numpoints; i++) {
@@ -473,7 +390,7 @@ void draw_smoke_volume(SmokeDomainSettings *sds, Object *ob,
else
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- glProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 2, -1.0, 0.0, 0.0, 0.0);
+ GPU_program_parameter_4f(smoke_program, 2, -1.0, 0.0, 0.0, 0.0);
glBegin(GL_POLYGON);
glColor3f(1.0, 1.0, 1.0);
for (i = 0; i < numpoints; i++) {
@@ -506,10 +423,8 @@ void draw_smoke_volume(SmokeDomainSettings *sds, Object *ob,
free(spec_data);
free(spec_pixels);
- if (GLEW_ARB_fragment_program) {
- glDisable(GL_FRAGMENT_PROGRAM_ARB);
- glDeleteProgramsARB(1, &prog);
- }
+ if (smoke_program)
+ GPU_program_unbind(smoke_program);
MEM_freeN(points);
@@ -521,8 +436,6 @@ void draw_smoke_volume(SmokeDomainSettings *sds, Object *ob,
if (gl_depth) {
glEnable(GL_DEPTH_TEST);
}
-
- glDepthMask(GL_TRUE);
}
#ifdef SMOKE_DEBUG_VELOCITY
diff --git a/source/blender/editors/space_view3d/space_view3d.c b/source/blender/editors/space_view3d/space_view3d.c
index 8b76ec3a56d..7869522e8fb 100644
--- a/source/blender/editors/space_view3d/space_view3d.c
+++ b/source/blender/editors/space_view3d/space_view3d.c
@@ -56,6 +56,7 @@
#include "GPU_extensions.h"
#include "GPU_material.h"
+#include "GPU_compositing.h"
#include "BIF_gl.h"
@@ -73,6 +74,8 @@
# include "BPY_extern.h"
#endif
+#include "DEG_depsgraph.h"
+
#include "view3d_intern.h" /* own include */
/* ******************** manage regions ********************* */
@@ -265,7 +268,7 @@ void ED_view3d_check_mats_rv3d(struct RegionView3D *rv3d)
}
#endif
-static void view3d_stop_render_preview(wmWindowManager *wm, ARegion *ar)
+void ED_view3d_stop_render_preview(wmWindowManager *wm, ARegion *ar)
{
RegionView3D *rv3d = ar->regiondata;
@@ -296,7 +299,7 @@ void ED_view3d_shade_update(Main *bmain, Scene *scene, View3D *v3d, ScrArea *sa)
for (ar = sa->regionbase.first; ar; ar = ar->next) {
if (ar->regiondata)
- view3d_stop_render_preview(wm, ar);
+ ED_view3d_stop_render_preview(wm, ar);
}
}
else if (scene->obedit != NULL && scene->obedit->type == OB_MESH) {
@@ -343,7 +346,13 @@ static SpaceLink *view3d_new(const bContext *C)
v3d->bundle_size = 0.2f;
v3d->bundle_drawtype = OB_PLAINAXES;
-
+
+ /* stereo */
+ v3d->stereo3d_camera = STEREO_3D_ID;
+ v3d->stereo3d_flag |= V3D_S3D_DISPPLANE;
+ v3d->stereo3d_convergence_alpha = 0.15f;
+ v3d->stereo3d_volume_alpha = 0.05f;
+
/* header */
ar = MEM_callocN(sizeof(ARegion), "header for view3d");
@@ -414,10 +423,15 @@ static void view3d_free(SpaceLink *sl)
/* matcap material, its preview rect gets freed via icons */
if (vd->defmaterial) {
if (vd->defmaterial->gpumaterial.first)
- GPU_material_free(vd->defmaterial);
+ GPU_material_free(&vd->defmaterial->gpumaterial);
BKE_previewimg_free(&vd->defmaterial->preview);
MEM_freeN(vd->defmaterial);
}
+
+ if (vd->fx_settings.ssao)
+ MEM_freeN(vd->fx_settings.ssao);
+ if (vd->fx_settings.dof)
+ MEM_freeN(vd->fx_settings.dof);
}
@@ -434,9 +448,7 @@ static SpaceLink *view3d_duplicate(SpaceLink *sl)
BGpic *bgpic;
/* clear or remove stuff from old */
-
-// XXX BIF_view3d_previewrender_free(v3do);
-
+
if (v3dn->localvd) {
v3dn->localvd = NULL;
v3dn->properties_storage = NULL;
@@ -461,7 +473,11 @@ static SpaceLink *view3d_duplicate(SpaceLink *sl)
}
v3dn->properties_storage = NULL;
-
+ if (v3dn->fx_settings.dof)
+ v3dn->fx_settings.dof = MEM_dupallocN(v3do->fx_settings.dof);
+ if (v3dn->fx_settings.ssao)
+ v3dn->fx_settings.ssao = MEM_dupallocN(v3do->fx_settings.ssao);
+
return (SpaceLink *)v3dn;
}
@@ -555,18 +571,23 @@ static void view3d_main_area_exit(wmWindowManager *wm, ARegion *ar)
{
RegionView3D *rv3d = ar->regiondata;
- view3d_stop_render_preview(wm, ar);
+ ED_view3d_stop_render_preview(wm, ar);
if (rv3d->gpuoffscreen) {
GPU_offscreen_free(rv3d->gpuoffscreen);
rv3d->gpuoffscreen = NULL;
}
+
+ if (rv3d->compositor) {
+ GPU_fx_compositor_destroy(rv3d->compositor);
+ rv3d->compositor = NULL;
+ }
}
static int view3d_ob_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent *UNUSED(event))
{
if (drag->type == WM_DRAG_ID) {
- ID *id = (ID *)drag->poin;
+ ID *id = drag->poin;
if (GS(id->name) == ID_OB)
return 1;
}
@@ -576,7 +597,7 @@ static int view3d_ob_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent
static int view3d_group_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent *UNUSED(event))
{
if (drag->type == WM_DRAG_ID) {
- ID *id = (ID *)drag->poin;
+ ID *id = drag->poin;
if (GS(id->name) == ID_GR)
return 1;
}
@@ -586,7 +607,7 @@ static int view3d_group_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEve
static int view3d_mat_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent *UNUSED(event))
{
if (drag->type == WM_DRAG_ID) {
- ID *id = (ID *)drag->poin;
+ ID *id = drag->poin;
if (GS(id->name) == ID_MA)
return 1;
}
@@ -596,12 +617,12 @@ static int view3d_mat_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent
static int view3d_ima_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent *UNUSED(event))
{
if (drag->type == WM_DRAG_ID) {
- ID *id = (ID *)drag->poin;
+ ID *id = drag->poin;
if (GS(id->name) == ID_IM)
return 1;
}
else if (drag->type == WM_DRAG_PATH) {
- if (ELEM(drag->icon, 0, ICON_FILE_IMAGE)) /* rule might not work? */
+ if (ELEM(drag->icon, 0, ICON_FILE_IMAGE, ICON_FILE_MOVIE)) /* rule might not work? */
return 1;
}
return 0;
@@ -643,14 +664,14 @@ static int view3d_ima_mesh_drop_poll(bContext *C, wmDrag *drag, const wmEvent *e
static void view3d_ob_drop_copy(wmDrag *drag, wmDropBox *drop)
{
- ID *id = (ID *)drag->poin;
+ ID *id = drag->poin;
RNA_string_set(drop->ptr, "name", id->name + 2);
}
static void view3d_group_drop_copy(wmDrag *drag, wmDropBox *drop)
{
- ID *id = (ID *)drag->poin;
+ ID *id = drag->poin;
drop->opcontext = WM_OP_EXEC_DEFAULT;
RNA_string_set(drop->ptr, "name", id->name + 2);
@@ -658,19 +679,23 @@ static void view3d_group_drop_copy(wmDrag *drag, wmDropBox *drop)
static void view3d_id_drop_copy(wmDrag *drag, wmDropBox *drop)
{
- ID *id = (ID *)drag->poin;
+ ID *id = drag->poin;
RNA_string_set(drop->ptr, "name", id->name + 2);
}
static void view3d_id_path_drop_copy(wmDrag *drag, wmDropBox *drop)
{
- ID *id = (ID *)drag->poin;
+ ID *id = drag->poin;
- if (id)
+ if (id) {
RNA_string_set(drop->ptr, "name", id->name + 2);
- if (drag->path[0])
+ RNA_struct_property_unset(drop->ptr, "filepath");
+ }
+ else if (drag->path[0]) {
RNA_string_set(drop->ptr, "filepath", drag->path);
+ RNA_struct_property_unset(drop->ptr, "image");
+ }
}
@@ -698,10 +723,6 @@ static void view3d_main_area_free(ARegion *ar)
if (rv3d->localvd) MEM_freeN(rv3d->localvd);
if (rv3d->clipbb) MEM_freeN(rv3d->clipbb);
- if (rv3d->ri) {
- // XXX BIF_view3d_previewrender_free(rv3d);
- }
-
if (rv3d->render_engine)
RE_engine_free(rv3d->render_engine);
@@ -715,6 +736,9 @@ static void view3d_main_area_free(ARegion *ar)
if (rv3d->gpuoffscreen) {
GPU_offscreen_free(rv3d->gpuoffscreen);
}
+ if (rv3d->compositor) {
+ GPU_fx_compositor_destroy(rv3d->compositor);
+ }
MEM_freeN(rv3d);
ar->regiondata = NULL;
@@ -735,10 +759,10 @@ static void *view3d_main_area_duplicate(void *poin)
new->depths = NULL;
new->gpuoffscreen = NULL;
- new->ri = NULL;
new->render_engine = NULL;
new->sms = NULL;
new->smooth_timer = NULL;
+ new->compositor = NULL;
return new;
}
@@ -820,6 +844,16 @@ static void view3d_main_area_listener(bScreen *sc, ScrArea *sa, ARegion *ar, wmN
case ND_WORLD:
/* handled by space_view3d_listener() for v3d access */
break;
+ case ND_DRAW_RENDER_VIEWPORT:
+ {
+ if (v3d->camera && (scene == wmn->reference)) {
+ RegionView3D *rv3d = ar->regiondata;
+ if (rv3d->persp == RV3D_CAMOB) {
+ ED_region_tag_redraw(ar);
+ }
+ }
+ break;
+ }
}
if (wmn->action == NA_EDITED)
ED_region_tag_redraw(ar);
@@ -859,25 +893,50 @@ static void view3d_main_area_listener(bScreen *sc, ScrArea *sa, ARegion *ar, wmN
break;
}
break;
+ case NC_CAMERA:
+ switch (wmn->data) {
+ case ND_DRAW_RENDER_VIEWPORT:
+ {
+ if (v3d->camera && (v3d->camera->data == wmn->reference)) {
+ RegionView3D *rv3d = ar->regiondata;
+ if (rv3d->persp == RV3D_CAMOB) {
+ ED_region_tag_redraw(ar);
+ }
+ }
+ break;
+ }
+ }
+ break;
case NC_GROUP:
/* all group ops for now */
ED_region_tag_redraw(ar);
break;
case NC_BRUSH:
- if (wmn->action == NA_EDITED)
- ED_region_tag_redraw_overlay(ar);
+ switch (wmn->action) {
+ case NA_EDITED:
+ ED_region_tag_redraw_overlay(ar);
+ break;
+ case NA_SELECTED:
+ /* used on brush changes - needed because 3d cursor
+ * has to be drawn if clone brush is selected */
+ ED_region_tag_redraw(ar);
+ break;
+ }
break;
case NC_MATERIAL:
switch (wmn->data) {
case ND_SHADING:
case ND_NODES:
{
+#ifdef WITH_LEGACY_DEPSGRAPH
Object *ob = OBACT;
if ((v3d->drawtype == OB_MATERIAL) ||
(ob && (ob->mode == OB_MODE_TEXTURE_PAINT)) ||
(v3d->drawtype == OB_TEXTURE &&
(scene->gm.matmode == GAME_MAT_GLSL ||
- BKE_scene_use_new_shading_nodes(scene))))
+ BKE_scene_use_new_shading_nodes(scene))) ||
+ !DEG_depsgraph_use_legacy())
+#endif
{
ED_region_tag_redraw(ar);
}
@@ -900,7 +959,8 @@ static void view3d_main_area_listener(bScreen *sc, ScrArea *sa, ARegion *ar, wmN
switch (wmn->data) {
case ND_LIGHTING:
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)) ||
+ !DEG_depsgraph_use_legacy())
{
ED_region_tag_redraw(ar);
}
@@ -957,8 +1017,9 @@ static void view3d_main_area_listener(bScreen *sc, ScrArea *sa, ARegion *ar, wmN
break;
case NC_GPENCIL:
- if (wmn->action == NA_EDITED)
+ if (wmn->data == ND_DATA || ELEM(wmn->action, NA_EDITED, NA_SELECTED)) {
ED_region_tag_redraw(ar);
+ }
break;
}
}
@@ -1014,6 +1075,10 @@ static void view3d_header_area_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa)
if (wmn->data == ND_SPACE_VIEW3D)
ED_region_tag_redraw(ar);
break;
+ case NC_GPENCIL:
+ if (wmn->data & ND_GPENCIL_EDITMODE)
+ ED_region_tag_redraw(ar);
+ break;
}
}
@@ -1030,7 +1095,7 @@ static void view3d_buttons_area_init(wmWindowManager *wm, ARegion *ar)
static void view3d_buttons_area_draw(const bContext *C, ARegion *ar)
{
- ED_region_panels(C, ar, 1, NULL, -1);
+ ED_region_panels(C, ar, NULL, -1, true);
}
static void view3d_buttons_area_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn)
@@ -1099,7 +1164,8 @@ static void view3d_buttons_area_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa
ED_region_tag_redraw(ar);
break;
case NC_BRUSH:
- if (wmn->action == NA_EDITED)
+ /* NA_SELECTED is used on brush changes */
+ if (ELEM(wmn->action, NA_EDITED, NA_SELECTED))
ED_region_tag_redraw(ar);
break;
case NC_SPACE:
@@ -1111,7 +1177,7 @@ static void view3d_buttons_area_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa
ED_region_tag_redraw(ar);
break;
case NC_GPENCIL:
- if (wmn->data == ND_DATA || wmn->action == NA_EDITED)
+ if ((wmn->data & (ND_DATA | ND_GPENCIL_EDITMODE)) || (wmn->action == NA_EDITED))
ED_region_tag_redraw(ar);
break;
case NC_IMAGE:
@@ -1135,7 +1201,7 @@ static void view3d_tools_area_init(wmWindowManager *wm, ARegion *ar)
static void view3d_tools_area_draw(const bContext *C, ARegion *ar)
{
- ED_region_panels(C, ar, 1, CTX_data_mode_string(C), -1);
+ ED_region_panels(C, ar, CTX_data_mode_string(C), -1, true);
}
static void view3d_props_area_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn)
@@ -1175,7 +1241,8 @@ static void space_view3d_listener(bScreen *UNUSED(sc), ScrArea *sa, struct wmNot
case NC_WORLD:
switch (wmn->data) {
case ND_WORLD_DRAW:
- if (v3d->flag2 & V3D_RENDER_OVERRIDE)
+ case ND_WORLD:
+ if (v3d->flag3 & V3D_SHOW_WORLD)
ED_area_tag_redraw_regiontype(sa, RGN_TYPE_WINDOW);
break;
}
diff --git a/source/blender/editors/space_view3d/view3d_buttons.c b/source/blender/editors/space_view3d/view3d_buttons.c
index cf589cdd946..d5fd18a77db 100644
--- a/source/blender/editors/space_view3d/view3d_buttons.c
+++ b/source/blender/editors/space_view3d/view3d_buttons.c
@@ -45,7 +45,7 @@
#include "MEM_guardedalloc.h"
-#include "BLF_translation.h"
+#include "BLT_translation.h"
#include "BLI_math.h"
#include "BLI_blenlib.h"
@@ -60,6 +60,7 @@
#include "BKE_editmesh.h"
#include "BKE_deform.h"
#include "BKE_object.h"
+#include "BKE_object_deform.h"
#include "WM_api.h"
#include "WM_types.h"
@@ -67,8 +68,6 @@
#include "RNA_access.h"
#include "ED_armature.h"
-#include "ED_gpencil.h"
-#include "ED_object.h"
#include "ED_mesh.h"
#include "ED_screen.h"
@@ -82,7 +81,7 @@
#define B_REDR 2
#define B_OBJECTPANELMEDIAN 1008
-#define NBR_TRANSFORM_PROPERTIES 7
+#define NBR_TRANSFORM_PROPERTIES 8
/* temporary struct for storing transform properties */
typedef struct {
@@ -124,38 +123,84 @@ static float compute_scale_factor(const float ve_median, const float median)
}
}
+/* Apply helpers.
+ * Note: In case we only have one element, copy directly the value instead of applying the diff or scale factor.
+ * Avoids some glitches when going e.g. from 3 to 0.0001 (see T37327).
+ */
+static void apply_raw_diff(float *val, const int tot, const float ve_median, const float median)
+{
+ *val = (tot == 1) ? ve_median : (*val + median);
+}
+
+static void apply_raw_diff_v3(float val[3], const int tot, const float ve_median[3], const float median[3])
+{
+ if (tot == 1) {
+ copy_v3_v3(val, ve_median);
+ }
+ else {
+ add_v3_v3(val, median);
+ }
+}
+
+static void apply_scale_factor(float *val, const int tot, const float ve_median, const float median, const float sca)
+{
+ if (tot == 1 || ve_median == median) {
+ *val = ve_median;
+ }
+ else {
+ *val *= sca;
+ }
+}
+
+static void apply_scale_factor_clamp(float *val, const int tot, const float ve_median, const float sca)
+{
+ if (tot == 1) {
+ *val = ve_median;
+ CLAMP(*val, 0.0f, 1.0f);
+ }
+ else if (ELEM(sca, 0.0f, 1.0f)) {
+ *val = sca;
+ }
+ else {
+ *val = (sca > 0.0f) ? (*val * sca) : (1.0f + ((1.0f - *val) * sca));
+ CLAMP(*val, 0.0f, 1.0f);
+ }
+}
+
/* is used for both read and write... */
static void v3d_editvertex_buts(uiLayout *layout, View3D *v3d, Object *ob, float lim)
{
/* Get rid of those ugly magic numbers, even in a single func they become confusing! */
/* Location, common to all. */
-/* XXX Those two *must* remain contiguous (used as array)! */
-#define LOC_X 0
-#define LOC_Y 1
-#define LOC_Z 2
+/* Next three *must* remain contiguous (used as array)! */
+#define LOC_X 0
+#define LOC_Y 1
+#define LOC_Z 2
/* Meshes... */
-#define M_CREASE 3
-#define M_WEIGHT 4
-/* XXX Those two *must* remain contiguous (used as array)! */
-#define M_SKIN_X 5
-#define M_SKIN_Y 6
+#define M_BV_WEIGHT 3
+/* Next two *must* remain contiguous (used as array)! */
+#define M_SKIN_X 4
+#define M_SKIN_Y 5
+#define M_BE_WEIGHT 6
+#define M_CREASE 7
/* Curves... */
-#define C_BWEIGHT 3
-#define C_WEIGHT 4
-#define C_RADIUS 5
-#define C_TILT 6
+#define C_BWEIGHT 3
+#define C_WEIGHT 4
+#define C_RADIUS 5
+#define C_TILT 6
/*Lattice... */
-#define L_WEIGHT 4
+#define L_WEIGHT 4
uiBlock *block = (layout) ? uiLayoutAbsoluteBlock(layout) : NULL;
TransformProperties *tfp;
float median[NBR_TRANSFORM_PROPERTIES], ve_median[NBR_TRANSFORM_PROPERTIES];
- int tot, totedgedata, totcurvedata, totlattdata, totskinradius, totcurvebweight;
+ int tot, totedgedata, totcurvedata, totlattdata, totcurvebweight;
bool has_meshdata = false;
+ bool has_skinradius = false;
PointerRNA data_ptr;
- fill_vn_fl(median, NBR_TRANSFORM_PROPERTIES, 0.0f);
- tot = totedgedata = totcurvedata = totlattdata = totskinradius = totcurvebweight = 0;
+ copy_vn_fl(median, NBR_TRANSFORM_PROPERTIES, 0.0f);
+ tot = totedgedata = totcurvedata = totlattdata = totcurvebweight = 0;
/* make sure we got storage */
if (v3d->properties_storage == NULL)
@@ -170,37 +215,37 @@ static void v3d_editvertex_buts(uiLayout *layout, View3D *v3d, Object *ob, float
BMEdge *eed;
BMIter iter;
- const int cd_vert_skin_offset = CustomData_get_offset(&bm->vdata, CD_MVERT_SKIN);
const int cd_vert_bweight_offset = CustomData_get_offset(&bm->vdata, CD_BWEIGHT);
+ const int cd_vert_skin_offset = CustomData_get_offset(&bm->vdata, CD_MVERT_SKIN);
const int cd_edge_bweight_offset = CustomData_get_offset(&bm->edata, CD_BWEIGHT);
const int cd_edge_crease_offset = CustomData_get_offset(&bm->edata, CD_CREASE);
+ has_skinradius = (cd_vert_skin_offset != -1);
+
if (bm->totvertsel) {
BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) {
if (BM_elem_flag_test(eve, BM_ELEM_SELECT)) {
tot++;
add_v3_v3(&median[LOC_X], eve->co);
- /* TODO cd_vert_bweight_offset */
- (void)cd_vert_bweight_offset;
+ if (cd_vert_bweight_offset != -1) {
+ median[M_BV_WEIGHT] += BM_ELEM_CD_GET_FLOAT(eve, cd_vert_bweight_offset);
+ }
- if (cd_vert_skin_offset != -1) {
+ if (has_skinradius) {
MVertSkin *vs = BM_ELEM_CD_GET_VOID_P(eve, cd_vert_skin_offset);
add_v2_v2(&median[M_SKIN_X], vs->radius); /* Third val not used currently. */
- totskinradius++;
}
}
}
}
- if ((cd_edge_bweight_offset != -1) ||
- (cd_edge_crease_offset != -1))
- {
+ if ((cd_edge_bweight_offset != -1) || (cd_edge_crease_offset != -1)) {
if (bm->totedgesel) {
BM_ITER_MESH (eed, &iter, bm, BM_EDGES_OF_MESH) {
if (BM_elem_flag_test(eed, BM_ELEM_SELECT)) {
if (cd_edge_bweight_offset != -1) {
- median[M_WEIGHT] += BM_ELEM_CD_GET_FLOAT(eed, cd_edge_bweight_offset);
+ median[M_BE_WEIGHT] += BM_ELEM_CD_GET_FLOAT(eed, cd_edge_bweight_offset);
}
if (cd_edge_crease_offset != -1) {
@@ -216,7 +261,7 @@ static void v3d_editvertex_buts(uiLayout *layout, View3D *v3d, Object *ob, float
totedgedata = bm->totedgesel;
}
- has_meshdata = (totedgedata || totskinradius);
+ has_meshdata = (tot || totedgedata);
}
else if (ob->type == OB_CURVE || ob->type == OB_SURF) {
Curve *cu = ob->data;
@@ -314,7 +359,7 @@ static void v3d_editvertex_buts(uiLayout *layout, View3D *v3d, Object *ob, float
}
if (tot == 0) {
- uiDefBut(block, LABEL, 0, IFACE_("Nothing selected"), 0, 130, 200, 20, NULL, 0, 0, 0, 0, "");
+ uiDefBut(block, UI_BTYPE_LABEL, 0, IFACE_("Nothing selected"), 0, 130, 200, 20, NULL, 0, 0, 0, 0, "");
return;
}
@@ -326,22 +371,27 @@ static void v3d_editvertex_buts(uiLayout *layout, View3D *v3d, Object *ob, float
if (has_meshdata) {
if (totedgedata) {
median[M_CREASE] /= (float)totedgedata;
- median[M_WEIGHT] /= (float)totedgedata;
+ median[M_BE_WEIGHT] /= (float)totedgedata;
}
- if (totskinradius) {
- median[M_SKIN_X] /= (float)totskinradius;
- median[M_SKIN_Y] /= (float)totskinradius;
+ if (tot) {
+ median[M_BV_WEIGHT] /= (float)tot;
+ if (has_skinradius) {
+ median[M_SKIN_X] /= (float)tot;
+ median[M_SKIN_Y] /= (float)tot;
+ }
}
}
else if (totcurvedata) {
+ if (totcurvebweight) {
+ median[C_BWEIGHT] /= (float)totcurvebweight;
+ }
median[C_WEIGHT] /= (float)totcurvedata;
median[C_RADIUS] /= (float)totcurvedata;
median[C_TILT] /= (float)totcurvedata;
- if (totcurvebweight)
- median[C_BWEIGHT] /= (float)totcurvebweight;
}
- else if (totlattdata)
+ else if (totlattdata) {
median[L_WEIGHT] /= (float)totlattdata;
+ }
if (block) { /* buttons */
uiBut *but;
@@ -353,7 +403,7 @@ static void v3d_editvertex_buts(uiLayout *layout, View3D *v3d, Object *ob, float
memcpy(tfp->ve_median, median, sizeof(tfp->ve_median));
- uiBlockBeginAlign(block);
+ UI_block_align_begin(block);
if (tot == 1) {
if (totcurvedata) /* Curve */
c = IFACE_("Control Point:");
@@ -362,98 +412,111 @@ static void v3d_editvertex_buts(uiLayout *layout, View3D *v3d, Object *ob, float
}
else
c = IFACE_("Median:");
- uiDefBut(block, LABEL, 0, c, 0, yi -= buth, 200, buth, NULL, 0, 0, 0, 0, "");
+ uiDefBut(block, UI_BTYPE_LABEL, 0, c, 0, yi -= buth, 200, buth, NULL, 0, 0, 0, 0, "");
- uiBlockBeginAlign(block);
+ UI_block_align_begin(block);
/* Should be no need to translate these. */
- but = uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, IFACE_("X:"), 0, yi -= buth, 200, buth,
+ but = uiDefButF(block, UI_BTYPE_NUM, B_OBJECTPANELMEDIAN, IFACE_("X:"), 0, yi -= buth, 200, buth,
&(tfp->ve_median[LOC_X]), -lim, lim, 10, RNA_TRANSLATION_PREC_DEFAULT, "");
- uiButSetUnitType(but, PROP_UNIT_LENGTH);
- but = uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, IFACE_("Y:"), 0, yi -= buth, 200, buth,
+ UI_but_unit_type_set(but, PROP_UNIT_LENGTH);
+ but = uiDefButF(block, UI_BTYPE_NUM, B_OBJECTPANELMEDIAN, IFACE_("Y:"), 0, yi -= buth, 200, buth,
&(tfp->ve_median[LOC_Y]), -lim, lim, 10, RNA_TRANSLATION_PREC_DEFAULT, "");
- uiButSetUnitType(but, PROP_UNIT_LENGTH);
- but = uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, IFACE_("Z:"), 0, yi -= buth, 200, buth,
+ UI_but_unit_type_set(but, PROP_UNIT_LENGTH);
+ but = uiDefButF(block, UI_BTYPE_NUM, B_OBJECTPANELMEDIAN, IFACE_("Z:"), 0, yi -= buth, 200, buth,
&(tfp->ve_median[LOC_Z]), -lim, lim, 10, RNA_TRANSLATION_PREC_DEFAULT, "");
- uiButSetUnitType(but, PROP_UNIT_LENGTH);
+ UI_but_unit_type_set(but, PROP_UNIT_LENGTH);
if (totcurvebweight == tot) {
- uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, IFACE_("W:"), 0, yi -= buth, 200, buth,
+ uiDefButF(block, UI_BTYPE_NUM, B_OBJECTPANELMEDIAN, IFACE_("W:"), 0, yi -= buth, 200, buth,
&(tfp->ve_median[C_BWEIGHT]), 0.01, 100.0, 1, 3, "");
}
- uiBlockBeginAlign(block);
- uiDefButBitS(block, TOG, V3D_GLOBAL_STATS, B_REDR, IFACE_("Global"),
+ UI_block_align_begin(block);
+ uiDefButBitS(block, UI_BTYPE_TOGGLE, V3D_GLOBAL_STATS, B_REDR, IFACE_("Global"),
0, yi -= buth + but_margin, 100, buth,
&v3d->flag, 0, 0, 0, 0, TIP_("Displays global values"));
- uiDefButBitS(block, TOGN, V3D_GLOBAL_STATS, B_REDR, IFACE_("Local"),
+ uiDefButBitS(block, UI_BTYPE_TOGGLE_N, V3D_GLOBAL_STATS, B_REDR, IFACE_("Local"),
100, yi, 100, buth,
&v3d->flag, 0, 0, 0, 0, TIP_("Displays local values"));
- uiBlockEndAlign(block);
+ UI_block_align_end(block);
/* Meshes... */
if (has_meshdata) {
- if (totedgedata) {
- /* customdata layer added on demand */
- uiDefButF(block, NUM, B_OBJECTPANELMEDIAN,
- totedgedata == 1 ? IFACE_("Crease:") : IFACE_("Mean Crease:"),
- 0, yi -= buth + but_margin, 200, buth,
- &(tfp->ve_median[M_CREASE]), 0.0, 1.0, 1, 2, TIP_("Weight used by SubSurf modifier"));
+ if (tot) {
+ uiDefBut(block, UI_BTYPE_LABEL, 0, tot == 1 ? IFACE_("Vertex Data:") : IFACE_("Vertices Data:"),
+ 0, yi -= buth + but_margin, 200, buth, NULL, 0.0, 0.0, 0, 0, "");
/* customdata layer added on demand */
- uiDefButF(block, NUM, B_OBJECTPANELMEDIAN,
- totedgedata == 1 ? IFACE_("Bevel Weight:") : IFACE_("Mean Bevel Weight:"),
+ uiDefButF(block, UI_BTYPE_NUM, B_OBJECTPANELMEDIAN,
+ tot == 1 ? IFACE_("Bevel Weight:") : IFACE_("Mean Bevel Weight:"),
0, yi -= buth + but_margin, 200, buth,
- &(tfp->ve_median[M_WEIGHT]), 0.0, 1.0, 1, 2, TIP_("Weight used by Bevel modifier"));
+ &(tfp->ve_median[M_BV_WEIGHT]), 0.0, 1.0, 1, 2, TIP_("Vertex weight used by Bevel modifier"));
}
- if (totskinradius) {
- uiDefButF(block, NUM, B_OBJECTPANELMEDIAN,
- totskinradius == 1 ? IFACE_("Radius X:") : IFACE_("Mean Radius X:"),
+ if (has_skinradius) {
+ UI_block_align_begin(block);
+ uiDefButF(block, UI_BTYPE_NUM, B_OBJECTPANELMEDIAN,
+ tot == 1 ? IFACE_("Radius X:") : IFACE_("Mean Radius X:"),
0, yi -= buth + but_margin, 200, buth,
&(tfp->ve_median[M_SKIN_X]), 0.0, 100.0, 1, 3, TIP_("X radius used by Skin modifier"));
- uiDefButF(block, NUM, B_OBJECTPANELMEDIAN,
- totskinradius == 1 ? IFACE_("Radius Y:") : IFACE_("Mean Radius Y:"),
+ uiDefButF(block, UI_BTYPE_NUM, B_OBJECTPANELMEDIAN,
+ tot == 1 ? IFACE_("Radius Y:") : IFACE_("Mean Radius Y:"),
0, yi -= buth + but_margin, 200, buth,
&(tfp->ve_median[M_SKIN_Y]), 0.0, 100.0, 1, 3, TIP_("Y radius used by Skin modifier"));
+ UI_block_align_end(block);
+ }
+ if (totedgedata) {
+ uiDefBut(block, UI_BTYPE_LABEL, 0, totedgedata == 1 ? IFACE_("Edge Data:") : IFACE_("Edges Data:"),
+ 0, yi -= buth + but_margin, 200, buth, NULL, 0.0, 0.0, 0, 0, "");
+ /* customdata layer added on demand */
+ uiDefButF(block, UI_BTYPE_NUM, B_OBJECTPANELMEDIAN,
+ totedgedata == 1 ? IFACE_("Bevel Weight:") : IFACE_("Mean Bevel Weight:"),
+ 0, yi -= buth + but_margin, 200, buth,
+ &(tfp->ve_median[M_BE_WEIGHT]), 0.0, 1.0, 1, 2, TIP_("Edge weight used by Bevel modifier"));
+ /* customdata layer added on demand */
+ uiDefButF(block, UI_BTYPE_NUM, B_OBJECTPANELMEDIAN,
+ totedgedata == 1 ? IFACE_("Crease:") : IFACE_("Mean Crease:"),
+ 0, yi -= buth + but_margin, 200, buth,
+ &(tfp->ve_median[M_CREASE]), 0.0, 1.0, 1, 2, TIP_("Weight used by SubSurf modifier"));
}
}
/* Curve... */
else if (totcurvedata == 1) {
- uiDefButR(block, NUM, 0, IFACE_("Weight:"), 0, yi -= buth + but_margin, 200, buth,
+ uiDefButR(block, UI_BTYPE_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, UI_BTYPE_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, UI_BTYPE_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) {
- uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, IFACE_("Mean Weight:"),
+ uiDefButF(block, UI_BTYPE_NUM, B_OBJECTPANELMEDIAN, IFACE_("Mean Weight:"),
0, yi -= buth + but_margin, 200, buth,
&(tfp->ve_median[C_WEIGHT]), 0.0, 1.0, 1, 3, TIP_("Weight used for SoftBody Goal"));
- uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, IFACE_("Mean Radius:"),
+ uiDefButF(block, UI_BTYPE_NUM, B_OBJECTPANELMEDIAN, IFACE_("Mean Radius:"),
0, yi -= buth + but_margin, 200, buth,
&(tfp->ve_median[C_RADIUS]), 0.0, 100.0, 1, 3, TIP_("Radius of curve control points"));
- but = uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, IFACE_("Mean Tilt:"),
+ but = uiDefButF(block, UI_BTYPE_NUM, B_OBJECTPANELMEDIAN, IFACE_("Mean Tilt:"),
0, yi -= buth + but_margin, 200, buth,
&(tfp->ve_median[C_TILT]), -tilt_limit, tilt_limit, 1, 3,
TIP_("Tilt of curve control points"));
- uiButSetUnitType(but, PROP_UNIT_ROTATION);
+ UI_but_unit_type_set(but, PROP_UNIT_ROTATION);
}
/* Lattice... */
else if (totlattdata == 1) {
- uiDefButR(block, NUM, 0, IFACE_("Weight:"), 0, yi -= buth + but_margin, 200, buth,
+ uiDefButR(block, UI_BTYPE_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) {
- uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, IFACE_("Mean Weight:"),
+ uiDefButF(block, UI_BTYPE_NUM, B_OBJECTPANELMEDIAN, IFACE_("Mean Weight:"),
0, yi -= buth + but_margin, 200, buth,
&(tfp->ve_median[L_WEIGHT]), 0.0, 1.0, 1, 3, TIP_("Weight used for SoftBody Goal"));
}
- uiBlockEndAlign(block);
-
+ UI_block_align_end(block);
}
else { /* apply */
int i;
+ bool apply_vcos;
memcpy(ve_median, tfp->ve_median, sizeof(tfp->ve_median));
@@ -466,155 +529,130 @@ static void v3d_editvertex_buts(uiLayout *layout, View3D *v3d, Object *ob, float
while (i--)
median[i] = ve_median[i] - median[i];
- if (ob->type == OB_MESH) {
+ /* Note with a single element selected, we always do. */
+ apply_vcos = (tot == 1) || (len_squared_v3(&median[LOC_X]) != 0.0f);
+
+ if ((ob->type == OB_MESH) &&
+ (apply_vcos || median[M_BV_WEIGHT] || median[M_SKIN_X] || median[M_SKIN_Y] ||
+ median[M_BE_WEIGHT] || median[M_CREASE]))
+ {
Mesh *me = ob->data;
BMEditMesh *em = me->edit_btmesh;
BMesh *bm = em->bm;
BMIter iter;
+ BMVert *eve;
+ BMEdge *eed;
- if (tot == 1 || len_v3(&median[LOC_X]) != 0.0f) {
- BMVert *eve;
+ int cd_vert_bweight_offset = -1;
+ int cd_vert_skin_offset = -1;
+ int cd_edge_bweight_offset = -1;
+ int cd_edge_crease_offset = -1;
- BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) {
- if (BM_elem_flag_test(eve, BM_ELEM_SELECT)) {
- if (tot == 1) {
- /* In case we only have one element selected, copy directly the value instead of applying
- * the diff. Avoids some glitches when going e.g. from 3 to 0.0001 (see [#37327]).
- */
- copy_v3_v3(eve->co, &ve_median[LOC_X]);
- }
- else {
- add_v3_v3(eve->co, &median[LOC_X]);
- }
- }
- }
+ float scale_bv_weight = 1.0f;
+ float scale_skin_x = 1.0f;
+ float scale_skin_y = 1.0f;
+ float scale_be_weight = 1.0f;
+ float scale_crease = 1.0f;
- EDBM_mesh_normals_update(em);
- }
+ /* Vertices */
- if (median[M_CREASE] != 0.0f) {
- const int cd_edge_crease_offset = (BM_mesh_cd_flag_ensure(bm, me, ME_CDFLAG_EDGE_CREASE),
- CustomData_get_offset(&bm->edata, CD_CREASE));
- const float sca = compute_scale_factor(ve_median[M_CREASE], median[M_CREASE]);
- BMEdge *eed;
+ if (apply_vcos || median[M_BV_WEIGHT] || median[M_SKIN_X] || median[M_SKIN_Y]) {
+ if (median[M_BV_WEIGHT]) {
+ BM_mesh_cd_flag_ensure(bm, me, ME_CDFLAG_VERT_BWEIGHT);
+ cd_vert_bweight_offset = CustomData_get_offset(&bm->vdata, CD_BWEIGHT);
+ BLI_assert(cd_vert_bweight_offset != -1);
- if (ELEM(sca, 0.0f, 1.0f)) {
- BM_ITER_MESH (eed, &iter, bm, BM_EDGES_OF_MESH) {
- if (BM_elem_flag_test(eed, BM_ELEM_SELECT)) {
- BM_ELEM_CD_SET_FLOAT(eed, cd_edge_crease_offset, sca);
- }
- }
- }
- else if (sca > 0.0f) {
- BM_ITER_MESH (eed, &iter, bm, BM_EDGES_OF_MESH) {
- if (BM_elem_flag_test(eed, BM_ELEM_SELECT) && !BM_elem_flag_test(eed, BM_ELEM_HIDDEN)) {
- float *crease = BM_ELEM_CD_GET_VOID_P(eed, cd_edge_crease_offset);
- *crease *= sca;
- CLAMP(*crease, 0.0f, 1.0f);
- }
- }
+ scale_bv_weight = compute_scale_factor(ve_median[M_BV_WEIGHT], median[M_BV_WEIGHT]);
}
- else {
- BM_ITER_MESH (eed, &iter, bm, BM_EDGES_OF_MESH) {
- if (BM_elem_flag_test(eed, BM_ELEM_SELECT) && !BM_elem_flag_test(eed, BM_ELEM_HIDDEN)) {
- float *crease = BM_ELEM_CD_GET_VOID_P(eed, cd_edge_crease_offset);
- *crease = 1.0f + ((1.0f - *crease) * sca);
- CLAMP(*crease, 0.0f, 1.0f);
- }
- }
- }
- }
-
- if (median[M_WEIGHT] != 0.0f) {
- const int cd_edge_bweight_offset = (BM_mesh_cd_flag_ensure(bm, me, ME_CDFLAG_EDGE_BWEIGHT),
- CustomData_get_offset(&bm->edata, CD_BWEIGHT));
- const float sca = compute_scale_factor(ve_median[M_WEIGHT], median[M_WEIGHT]);
- BMEdge *eed;
- BLI_assert(cd_edge_bweight_offset != -1);
+ if (median[M_SKIN_X]) {
+ cd_vert_skin_offset = CustomData_get_offset(&bm->vdata, CD_MVERT_SKIN);
+ BLI_assert(cd_vert_skin_offset != -1);
- if (ELEM(sca, 0.0f, 1.0f)) {
- BM_ITER_MESH (eed, &iter, bm, BM_EDGES_OF_MESH) {
- if (BM_elem_flag_test(eed, BM_ELEM_SELECT)) {
- float *bweight = BM_ELEM_CD_GET_VOID_P(eed, cd_edge_bweight_offset);
- *bweight = sca;
- }
+ if (ve_median[M_SKIN_X] != median[M_SKIN_X]) {
+ scale_skin_x = ve_median[M_SKIN_X] / (ve_median[M_SKIN_X] - median[M_SKIN_X]);
}
}
- else if (sca > 0.0f) {
- BM_ITER_MESH (eed, &iter, bm, BM_EDGES_OF_MESH) {
- if (BM_elem_flag_test(eed, BM_ELEM_SELECT) && !BM_elem_flag_test(eed, BM_ELEM_HIDDEN)) {
- float *bweight = BM_ELEM_CD_GET_VOID_P(eed, cd_edge_bweight_offset);
- *bweight *= sca;
- CLAMP(*bweight, 0.0f, 1.0f);
- }
+ if (median[M_SKIN_Y]) {
+ if (cd_vert_skin_offset == -1) {
+ cd_vert_skin_offset = CustomData_get_offset(&bm->vdata, CD_MVERT_SKIN);
+ BLI_assert(cd_vert_skin_offset != -1);
}
- }
- else {
- BM_ITER_MESH (eed, &iter, bm, BM_EDGES_OF_MESH) {
- if (BM_elem_flag_test(eed, BM_ELEM_SELECT) && !BM_elem_flag_test(eed, BM_ELEM_HIDDEN)) {
- float *bweight = BM_ELEM_CD_GET_VOID_P(eed, cd_edge_bweight_offset);
- *bweight = 1.0f + ((1.0f - *bweight) * sca);
- CLAMP(*bweight, 0.0f, 1.0f);
- }
+
+ if (ve_median[M_SKIN_Y] != median[M_SKIN_Y]) {
+ scale_skin_y = ve_median[M_SKIN_Y] / (ve_median[M_SKIN_Y] - median[M_SKIN_Y]);
}
}
- }
- if (median[M_SKIN_X] != 0.0f) {
- const int cd_vert_skin_offset = CustomData_get_offset(&bm->vdata, CD_MVERT_SKIN);
- /* That one is not clamped to [0.0, 1.0]. */
- float sca = ve_median[M_SKIN_X];
- BMVert *eve;
-
- BLI_assert(cd_vert_skin_offset != -1);
+ BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) {
+ if (BM_elem_flag_test(eve, BM_ELEM_SELECT)) {
+ if (apply_vcos) {
+ apply_raw_diff_v3(eve->co, tot, &ve_median[LOC_X], &median[LOC_X]);
+ }
- if (ve_median[M_SKIN_X] - median[M_SKIN_X] == 0.0f) {
- BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) {
- if (BM_elem_flag_test(eve, BM_ELEM_SELECT)) {
- MVertSkin *vs = BM_ELEM_CD_GET_VOID_P(eve, cd_vert_skin_offset);
- vs->radius[0] = sca;
+ if (cd_vert_bweight_offset != -1) {
+ float *bweight = BM_ELEM_CD_GET_VOID_P(eve, cd_vert_bweight_offset);
+ apply_scale_factor_clamp(bweight, tot, ve_median[M_BV_WEIGHT], scale_bv_weight);
}
- }
- }
- else {
- sca /= (ve_median[M_SKIN_X] - median[M_SKIN_X]);
- BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) {
- if (BM_elem_flag_test(eve, BM_ELEM_SELECT)) {
+
+ if (cd_vert_skin_offset != -1) {
MVertSkin *vs = BM_ELEM_CD_GET_VOID_P(eve, cd_vert_skin_offset);
- vs->radius[0] *= sca;
+
+ /* That one is not clamped to [0.0, 1.0]. */
+ if (median[M_SKIN_X] != 0.0f) {
+ apply_scale_factor(&vs->radius[0], tot, ve_median[M_SKIN_X], median[M_SKIN_X],
+ scale_skin_x);
+ }
+ if (median[M_SKIN_Y] != 0.0f) {
+ apply_scale_factor(&vs->radius[1], tot, ve_median[M_SKIN_Y], median[M_SKIN_Y],
+ scale_skin_y);
+ }
}
}
}
}
- if (median[M_SKIN_Y] != 0.0f) {
- const int cd_vert_skin_offset = CustomData_get_offset(&bm->vdata, CD_MVERT_SKIN);
- /* That one is not clamped to [0.0, 1.0]. */
- float sca = ve_median[M_SKIN_Y];
- BMVert *eve;
- BLI_assert(cd_vert_skin_offset != -1);
+ if (apply_vcos) {
+ EDBM_mesh_normals_update(em);
+ }
- if (ve_median[M_SKIN_Y] - median[M_SKIN_Y] == 0.0f) {
- BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) {
- if (BM_elem_flag_test(eve, BM_ELEM_SELECT)) {
- MVertSkin *vs = BM_ELEM_CD_GET_VOID_P(eve, cd_vert_skin_offset);
- vs->radius[1] = sca;
- }
- }
+ /* Edges */
+
+ if (median[M_BE_WEIGHT] || median[M_CREASE]) {
+ if (median[M_BE_WEIGHT]) {
+ BM_mesh_cd_flag_ensure(bm, me, ME_CDFLAG_EDGE_BWEIGHT);
+ cd_edge_bweight_offset = CustomData_get_offset(&bm->edata, CD_BWEIGHT);
+ BLI_assert(cd_edge_bweight_offset != -1);
+
+ scale_be_weight = compute_scale_factor(ve_median[M_BE_WEIGHT], median[M_BE_WEIGHT]);
}
- else {
- sca /= (ve_median[M_SKIN_Y] - median[M_SKIN_Y]);
- BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) {
- if (BM_elem_flag_test(eve, BM_ELEM_SELECT)) {
- MVertSkin *vs = BM_ELEM_CD_GET_VOID_P(eve, cd_vert_skin_offset);
- vs->radius[1] *= sca;
+
+ if (median[M_CREASE]) {
+ BM_mesh_cd_flag_ensure(bm, me, ME_CDFLAG_EDGE_CREASE);
+ cd_edge_crease_offset = CustomData_get_offset(&bm->edata, CD_CREASE);
+ BLI_assert(cd_edge_crease_offset != -1);
+
+ scale_crease = compute_scale_factor(ve_median[M_CREASE], median[M_CREASE]);
+ }
+
+ BM_ITER_MESH (eed, &iter, bm, BM_EDGES_OF_MESH) {
+ if (BM_elem_flag_test(eed, BM_ELEM_SELECT)) {
+ if (median[M_BE_WEIGHT] != 0.0f) {
+ float *bweight = BM_ELEM_CD_GET_VOID_P(eed, cd_edge_bweight_offset);
+ apply_scale_factor_clamp(bweight, tot, ve_median[M_BE_WEIGHT], scale_be_weight);
+ }
+
+ if (median[M_CREASE] != 0.0f) {
+ float *crease = BM_ELEM_CD_GET_VOID_P(eed, cd_edge_crease_offset);
+ apply_scale_factor_clamp(crease, tot, ve_median[M_CREASE], scale_crease);
}
}
}
}
}
- else if (ELEM(ob->type, OB_CURVE, OB_SURF)) {
+ else if (ELEM(ob->type, OB_CURVE, OB_SURF) &&
+ (apply_vcos || median[C_BWEIGHT] || median[C_WEIGHT] || median[C_RADIUS] || median[C_TILT]))
+ {
Curve *cu = ob->data;
Nurb *nu;
BPoint *bp;
@@ -628,44 +666,31 @@ static void v3d_editvertex_buts(uiLayout *layout, View3D *v3d, Object *ob, float
if (nu->type == CU_BEZIER) {
for (a = nu->pntsu, bezt = nu->bezt; a--; bezt++) {
if (bezt->f2 & SELECT) {
- /* Here we always have to use the diff... :/
- * Cannot avoid some glitches when going e.g. from 3 to 0.0001 (see [#37327]),
- * unless we use doubles.
- */
- add_v3_v3(bezt->vec[0], &median[LOC_X]);
- add_v3_v3(bezt->vec[1], &median[LOC_X]);
- add_v3_v3(bezt->vec[2], &median[LOC_X]);
-
- if (median[C_WEIGHT] != 0.0f) {
- if (ELEM(scale_w, 0.0f, 1.0f)) {
- bezt->weight = scale_w;
- }
- else {
- bezt->weight = scale_w > 0.0f ? bezt->weight * scale_w :
- 1.0f + ((1.0f - bezt->weight) * scale_w);
- CLAMP(bezt->weight, 0.0f, 1.0f);
- }
+ if (apply_vcos) {
+ /* Here we always have to use the diff... :/
+ * Cannot avoid some glitches when going e.g. from 3 to 0.0001 (see T37327),
+ * unless we use doubles.
+ */
+ add_v3_v3(bezt->vec[0], &median[LOC_X]);
+ add_v3_v3(bezt->vec[1], &median[LOC_X]);
+ add_v3_v3(bezt->vec[2], &median[LOC_X]);
+ }
+ if (median[C_WEIGHT]) {
+ apply_scale_factor_clamp(&bezt->weight, tot, ve_median[C_WEIGHT], scale_w);
+ }
+ if (median[C_RADIUS]) {
+ apply_raw_diff(&bezt->radius, tot, ve_median[C_RADIUS], median[C_RADIUS]);
+ }
+ if (median[C_TILT]) {
+ apply_raw_diff(&bezt->alfa, tot, ve_median[C_TILT], median[C_TILT]);
}
-
- bezt->radius += median[C_RADIUS];
- bezt->alfa += median[C_TILT];
}
- else {
+ else if (apply_vcos) { /* Handles can only have their coordinates changed here. */
if (bezt->f1 & SELECT) {
- if (tot == 1) {
- copy_v3_v3(bezt->vec[0], &ve_median[LOC_X]);
- }
- else {
- add_v3_v3(bezt->vec[0], &median[LOC_X]);
- }
+ apply_raw_diff_v3(bezt->vec[0], tot, &ve_median[LOC_X], &median[LOC_X]);
}
if (bezt->f3 & SELECT) {
- if (tot == 1) {
- copy_v3_v3(bezt->vec[2], &ve_median[LOC_X]);
- }
- else {
- add_v3_v3(bezt->vec[2], &median[LOC_X]);
- }
+ apply_raw_diff_v3(bezt->vec[2], tot, &ve_median[LOC_X], &median[LOC_X]);
}
}
}
@@ -673,28 +698,20 @@ static void v3d_editvertex_buts(uiLayout *layout, View3D *v3d, Object *ob, float
else {
for (a = nu->pntsu * nu->pntsv, bp = nu->bp; a--; bp++) {
if (bp->f1 & SELECT) {
- if (tot == 1) {
- copy_v3_v3(bp->vec, &ve_median[LOC_X]);
- bp->vec[3] = ve_median[C_BWEIGHT];
- bp->radius = ve_median[C_RADIUS];
- bp->alfa = ve_median[C_TILT];
+ if (apply_vcos) {
+ apply_raw_diff_v3(bp->vec, tot, &ve_median[LOC_X], &median[LOC_X]);
}
- else {
- add_v3_v3(bp->vec, &median[LOC_X]);
- bp->vec[3] += median[C_BWEIGHT];
- bp->radius += median[C_RADIUS];
- bp->alfa += median[C_TILT];
+ if (median[C_BWEIGHT]) {
+ apply_raw_diff(&bp->vec[3], tot, ve_median[C_BWEIGHT], median[C_BWEIGHT]);
}
-
- if (median[C_WEIGHT] != 0.0f) {
- if (ELEM(scale_w, 0.0f, 1.0f)) {
- bp->weight = scale_w;
- }
- else {
- bp->weight = scale_w > 0.0f ? bp->weight * scale_w :
- 1.0f + ((1.0f - bp->weight) * scale_w);
- CLAMP(bp->weight, 0.0f, 1.0f);
- }
+ if (median[C_WEIGHT]) {
+ apply_scale_factor_clamp(&bp->weight, tot, ve_median[C_WEIGHT], scale_w);
+ }
+ if (median[C_RADIUS]) {
+ apply_raw_diff(&bp->radius, tot, ve_median[C_RADIUS], median[C_RADIUS]);
+ }
+ if (median[C_TILT]) {
+ apply_raw_diff(&bp->alfa, tot, ve_median[C_TILT], median[C_TILT]);
}
}
}
@@ -705,7 +722,7 @@ static void v3d_editvertex_buts(uiLayout *layout, View3D *v3d, Object *ob, float
nu = nu->next;
}
}
- else if (ob->type == OB_LATTICE) {
+ else if ((ob->type == OB_LATTICE) && (apply_vcos || median[L_WEIGHT])) {
Lattice *lt = ob->data;
BPoint *bp;
int a;
@@ -715,22 +732,11 @@ static void v3d_editvertex_buts(uiLayout *layout, View3D *v3d, Object *ob, float
bp = lt->editlatt->latt->def;
while (a--) {
if (bp->f1 & SELECT) {
- if (tot == 1) {
- copy_v3_v3(bp->vec, &ve_median[LOC_X]);
- }
- else {
- add_v3_v3(bp->vec, &median[LOC_X]);
+ if (apply_vcos) {
+ apply_raw_diff_v3(bp->vec, tot, &ve_median[LOC_X], &median[LOC_X]);
}
-
- if (median[L_WEIGHT] != 0.0f) {
- if (ELEM(scale_w, 0.0f, 1.0f)) {
- bp->weight = scale_w;
- }
- else {
- bp->weight = scale_w > 0.0f ? bp->weight * scale_w :
- 1.0f + ((1.0f - bp->weight) * scale_w);
- CLAMP(bp->weight, 0.0f, 1.0f);
- }
+ if (median[L_WEIGHT]) {
+ apply_scale_factor_clamp(&bp->weight, tot, ve_median[L_WEIGHT], scale_w);
}
}
bp++;
@@ -746,10 +752,11 @@ static void v3d_editvertex_buts(uiLayout *layout, View3D *v3d, Object *ob, float
#undef LOC_Y
#undef LOC_Z
/* Meshes (and lattice)... */
-#undef M_CREASE
-#undef M_WEIGHT
+#undef M_BV_WEIGHT
#undef M_SKIN_X
#undef M_SKIN_Y
+#undef M_BE_WEIGHT
+#undef M_CREASE
/* Curves... */
#undef C_BWEIGHT
#undef C_WEIGHT
@@ -826,7 +833,7 @@ static void view3d_panel_vgroup(const bContext *C, Panel *pa)
int yco = 0;
int lock_count = 0;
- uiBlockSetHandleFunc(block, do_view3d_vgroup_buttons, NULL);
+ UI_block_func_handle_set(block, do_view3d_vgroup_buttons, NULL);
bcol = uiLayoutColumn(pa->layout, true);
row = uiLayoutRow(bcol, true); /* The filter button row */
@@ -836,9 +843,9 @@ static void view3d_panel_vgroup(const bContext *C, Panel *pa)
col = uiLayoutColumn(bcol, true);
- vgroup_validmap = ED_vgroup_subset_from_select_type(ob, subset_type, &vgroup_tot, &subset_count);
+ vgroup_validmap = BKE_object_defgroup_subset_from_select_type(ob, subset_type, &vgroup_tot, &subset_count);
for (i = 0, dg = ob->defbase.first; dg; i++, dg = dg->next) {
- bool locked = dg->flag & DG_LOCK_WEIGHT;
+ bool locked = (dg->flag & DG_LOCK_WEIGHT) != 0;
if (vgroup_validmap[i]) {
MDeformWeight *dw = defvert_find_index(dv, i);
if (dw) {
@@ -850,13 +857,13 @@ static void view3d_panel_vgroup(const bContext *C, Panel *pa)
/* The Weight Group Name */
ot = ot_weight_set_active;
- but = uiDefButO_ptr(block, BUT, ot, WM_OP_EXEC_DEFAULT, dg->name,
+ but = uiDefButO_ptr(block, UI_BTYPE_BUT, ot, WM_OP_EXEC_DEFAULT, dg->name,
xco, yco, (x = UI_UNIT_X * 5), UI_UNIT_Y, "");
- but_ptr = uiButGetOperatorPtrRNA(but);
+ but_ptr = UI_but_operator_ptr_get(but);
RNA_int_set(but_ptr, "weight_group", i);
- uiButSetDrawFlag(but, UI_BUT_TEXT_RIGHT);
+ UI_but_drawflag_enable(but, UI_BUT_TEXT_RIGHT);
if (ob->actdef != i + 1) {
- uiButSetFlag(but, UI_BUT_INACTIVE);
+ UI_but_flag_enable(but, UI_BUT_INACTIVE);
}
xco += x;
@@ -865,10 +872,10 @@ static void view3d_panel_vgroup(const bContext *C, Panel *pa)
/* The weight group value */
/* To be reworked still */
- but = uiDefButF(block, NUM, B_VGRP_PNL_EDIT_SINGLE + i, "",
+ but = uiDefButF(block, UI_BTYPE_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, "");
- uiButSetDrawFlag(but, UI_BUT_TEXT_LEFT);
+ UI_but_drawflag_enable(but, UI_BUT_TEXT_LEFT);
if (locked) {
lock_count++;
}
@@ -903,19 +910,19 @@ static void view3d_panel_vgroup(const bContext *C, Panel *pa)
row = uiLayoutRow(col, true);
ot = WM_operatortype_find("OBJECT_OT_vertex_weight_normalize_active_vertex", 1);
- but = uiDefButO_ptr(block, BUT, ot, WM_OP_EXEC_DEFAULT, "Normalize",
+ but = uiDefButO_ptr(block, UI_BTYPE_BUT, ot, WM_OP_EXEC_DEFAULT, "Normalize",
0, yco, UI_UNIT_X * 5, UI_UNIT_Y,
TIP_("Normalize weights of active vertex (if affected groups are unlocked)"));
if (lock_count) {
- uiButSetFlag(but, UI_BUT_DISABLED);
+ UI_but_flag_enable(but, UI_BUT_DISABLED);
}
ot = WM_operatortype_find("OBJECT_OT_vertex_weight_copy", 1);
- but = uiDefButO_ptr(block, BUT, ot, WM_OP_EXEC_DEFAULT, "Copy",
+ but = uiDefButO_ptr(block, UI_BTYPE_BUT, ot, WM_OP_EXEC_DEFAULT, "Copy",
UI_UNIT_X * 5, yco, UI_UNIT_X * 5, UI_UNIT_Y,
TIP_("Copy active vertex to other selected vertices (if affected groups are unlocked)"));
if (lock_count) {
- uiButSetFlag(but, UI_BUT_DISABLED);
+ UI_but_flag_enable(but, UI_BUT_DISABLED);
}
}
@@ -985,9 +992,8 @@ static void v3d_transform_butsR(uiLayout *layout, PointerRNA *ptr)
if (ptr->type == &RNA_Object) {
Object *ob = ptr->data;
- /* dimensions and material support just happen to be the same checks
- * later we may want to add dimensions for lattice, armature etc too */
- if (OB_TYPE_SUPPORT_MATERIAL(ob->type)) {
+ /* dimensions and editmode just happen to be the same checks */
+ if (OB_TYPE_SUPPORT_EDITMODE(ob->type)) {
uiItemR(layout, ptr, "dimensions", 0, NULL, ICON_NONE);
}
}
@@ -1137,7 +1143,7 @@ static void view3d_panel_transform(const bContext *C, Panel *pa)
uiLayout *col;
block = uiLayoutGetBlock(pa->layout);
- uiBlockSetHandleFunc(block, do_view3d_region_buttons, NULL);
+ UI_block_func_handle_set(block, do_view3d_region_buttons, NULL);
col = uiLayoutColumn(pa->layout, false);
@@ -1172,23 +1178,15 @@ void view3d_buttons_register(ARegionType *art)
pt = MEM_callocN(sizeof(PanelType), "spacetype view3d panel object");
strcpy(pt->idname, "VIEW3D_PT_transform");
strcpy(pt->label, N_("Transform")); /* XXX C panels not available through RNA (bpy.types)! */
- strcpy(pt->translation_context, BLF_I18NCONTEXT_DEFAULT_BPYRNA);
+ strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
pt->draw = view3d_panel_transform;
pt->poll = view3d_panel_transform_poll;
BLI_addtail(&art->paneltypes, pt);
- pt = MEM_callocN(sizeof(PanelType), "spacetype view3d panel gpencil");
- strcpy(pt->idname, "VIEW3D_PT_gpencil");
- strcpy(pt->label, N_("Grease Pencil")); /* XXX C panels are not available through RNA (bpy.types)! */
- strcpy(pt->translation_context, BLF_I18NCONTEXT_DEFAULT_BPYRNA);
- pt->draw_header = ED_gpencil_panel_standard_header;
- pt->draw = ED_gpencil_panel_standard;
- BLI_addtail(&art->paneltypes, pt);
-
pt = MEM_callocN(sizeof(PanelType), "spacetype view3d panel vgroup");
strcpy(pt->idname, "VIEW3D_PT_vgroup");
strcpy(pt->label, N_("Vertex Weights")); /* XXX C panels are not available through RNA (bpy.types)! */
- strcpy(pt->translation_context, BLF_I18NCONTEXT_DEFAULT_BPYRNA);
+ strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
pt->draw = view3d_panel_vgroup;
pt->poll = view3d_panel_vgroup_poll;
BLI_addtail(&art->paneltypes, pt);
diff --git a/source/blender/editors/space_view3d/view3d_camera_control.c b/source/blender/editors/space_view3d/view3d_camera_control.c
index ee0f3da18b4..f717f1c0a43 100644
--- a/source/blender/editors/space_view3d/view3d_camera_control.c
+++ b/source/blender/editors/space_view3d/view3d_camera_control.c
@@ -51,14 +51,12 @@
#include "MEM_guardedalloc.h"
#include "BLI_math.h"
-#include "BLI_blenlib.h"
#include "BLI_utildefines.h"
#include "BKE_object.h"
#include "BKE_depsgraph.h" /* for object updating */
-#include "ED_keyframing.h"
#include "ED_screen.h"
#include "view3d_intern.h" /* own include */
@@ -135,7 +133,7 @@ Object *ED_view3d_cameracontrol_object_get(View3DCameraControl *vctrl)
/**
- * Creates a #View3DControl handle and sets up
+ * Creates a #View3DCameraControl handle and sets up
* the view for first-person style navigation.
*/
struct View3DCameraControl *ED_view3d_cameracontrol_acquire(
@@ -266,6 +264,8 @@ void ED_view3d_cameracontrol_update(
BKE_object_apply_mat4(v3d->camera, view_mat, true, true);
+ DAG_id_tag_update(&v3d->camera->id, OB_RECALC_OB);
+
copy_v3_v3(v3d->camera->size, size_back);
id_key = &v3d->camera->id;
diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c
index 2629d9f33d0..d9ad481ab33 100644
--- a/source/blender/editors/space_view3d/view3d_draw.c
+++ b/source/blender/editors/space_view3d/view3d_draw.c
@@ -42,6 +42,7 @@
#include "DNA_lamp_types.h"
#include "DNA_scene_types.h"
#include "DNA_world_types.h"
+#include "DNA_brush_types.h"
#include "MEM_guardedalloc.h"
@@ -49,11 +50,13 @@
#include "BLI_math.h"
#include "BLI_utildefines.h"
#include "BLI_endian_switch.h"
+#include "BLI_threads.h"
#include "BKE_anim.h"
#include "BKE_camera.h"
#include "BKE_context.h"
#include "BKE_customdata.h"
+#include "BKE_DerivedMesh.h"
#include "BKE_image.h"
#include "BKE_key.h"
#include "BKE_main.h"
@@ -77,7 +80,7 @@
#include "WM_api.h"
#include "BLF_api.h"
-#include "BLF_translation.h"
+#include "BLT_translation.h"
#include "ED_armature.h"
#include "ED_keyframing.h"
@@ -94,9 +97,15 @@
#include "GPU_draw.h"
#include "GPU_material.h"
#include "GPU_extensions.h"
+#include "GPU_compositing.h"
#include "view3d_intern.h" /* own include */
+/* prototypes */
+static void view3d_stereo3d_setup(Scene *scene, View3D *v3d, ARegion *ar);
+static void view3d_stereo3d_setup_offscreen(Scene *scene, View3D *v3d, ARegion *ar,
+ float winmat[4][4], const char *viewname);
+
/* handy utility for drawing shapes in the viewport for arbitrary code.
* could add lines and points too */
// #define DEBUG_DRAW
@@ -162,15 +171,15 @@ static void view3d_draw_clipping(RegionView3D *rv3d)
/* fill in zero alpha for rendering & re-projection [#31530] */
unsigned char col[4];
- UI_GetThemeColorShade3ubv(TH_BACK, -8, col);
- col[3] = 0;
+ UI_GetThemeColor4ubv(TH_V3D_CLIPPING_BORDER, col);
glColor4ubv(col);
+ glEnable(GL_BLEND);
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3, GL_FLOAT, 0, bb->vec);
glDrawElements(GL_QUADS, sizeof(clipping_index) / sizeof(unsigned int), GL_UNSIGNED_INT, clipping_index);
glDisableClientState(GL_VERTEX_ARRAY);
-
+ glDisable(GL_BLEND);
}
}
@@ -205,7 +214,7 @@ void ED_view3d_clipping_enable(void)
}
}
-static bool view3d_clipping_test(const float co[3], float clip[6][4])
+static bool view3d_clipping_test(const float co[3], const float clip[6][4])
{
if (plane_point_side_v3(clip[0], co) > 0.0f)
if (plane_point_side_v3(clip[1], co) > 0.0f)
@@ -218,7 +227,7 @@ static bool view3d_clipping_test(const float co[3], float clip[6][4])
/* for 'local' ED_view3d_clipping_local must run first
* then all comparisons can be done in localspace */
-bool ED_view3d_clipping_test(RegionView3D *rv3d, const float co[3], const bool is_local)
+bool ED_view3d_clipping_test(const RegionView3D *rv3d, const float co[3], const bool is_local)
{
return view3d_clipping_test(co, is_local ? rv3d->clip_local : rv3d->clip);
}
@@ -294,7 +303,7 @@ static void drawgrid(UnitSettings *unit, ARegion *ar, View3D *v3d, const char **
dx = fabs(x - (wx) * fx / fw);
if (dx == 0) dx = fabs(y - (wy) * fy / fw);
- glDepthMask(0); /* disable write in zbuffer */
+ glDepthMask(GL_FALSE); /* disable write in zbuffer */
/* check zoom out */
UI_ThemeColor(TH_GRID);
@@ -433,7 +442,7 @@ static void drawgrid(UnitSettings *unit, ARegion *ar, View3D *v3d, const char **
fdrawline(x, 0.0, x, (float)ar->winy);
- glDepthMask(1); /* enable write in zbuffer */
+ glDepthMask(GL_TRUE); /* enable write in zbuffer */
}
#undef GRID_MIN_PX
@@ -463,7 +472,7 @@ float ED_view3d_grid_scale(Scene *scene, View3D *v3d, const char **grid_unit)
return v3d->grid * ED_scene_grid_scale(scene, grid_unit);
}
-static void drawfloor(Scene *scene, View3D *v3d, const char **grid_unit)
+static void drawfloor(Scene *scene, View3D *v3d, const char **grid_unit, bool write_depth)
{
float grid, grid_scale;
unsigned char col_grid[3];
@@ -475,8 +484,8 @@ static void drawfloor(Scene *scene, View3D *v3d, const char **grid_unit)
grid_scale = ED_view3d_grid_scale(scene, v3d, grid_unit);
grid = gridlines * grid_scale;
- if (v3d->zbuf && scene->obedit)
- glDepthMask(0); /* for zbuffer-select */
+ if (!write_depth)
+ glDepthMask(GL_FALSE);
UI_GetThemeColor3ubv(TH_GRID, col_grid);
@@ -545,7 +554,7 @@ static void drawfloor(Scene *scene, View3D *v3d, const char **grid_unit)
}
}
- if (v3d->zbuf && scene->obedit) glDepthMask(1);
+ glDepthMask(GL_TRUE);
}
@@ -586,20 +595,26 @@ 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;
-
+
+ int axis_order[3] = {0, 1, 2};
+ int axis_i;
+
startx += rect->xmin;
starty += rect->ymin;
-
+
+ axis_sort_v3(rv3d->viewinv[2], axis_order);
+
/* thickness of lines is proportional to k */
glLineWidth(2);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- for (i = 0; i < 3; i++) {
+ for (axis_i = 0; axis_i < 3; axis_i++) {
+ int i = axis_order[axis_i];
+ const char axis_text[2] = {'x' + i, '\0'};
+
zero_v3(vec);
vec[i] = 1.0f;
mul_qt_v3(rv3d->viewquat, vec);
@@ -616,8 +631,6 @@ static void draw_view_axis(RegionView3D *rv3d, rcti *rect)
BLF_draw_default_ascii(startx + dx + 2, starty + dy + ydisp + 2, 0.0f, axis_text, 1);
}
- axis_text[0]++;
-
/* BLF_draw_default disables blending */
glEnable(GL_BLEND);
}
@@ -645,7 +658,7 @@ static void draw_rotation_guide(RegionView3D *rv3d)
glEnable(GL_POINT_SMOOTH);
glDepthMask(0); /* don't overwrite zbuf */
- if (rv3d->rot_angle != 0.f) {
+ if (rv3d->rot_angle != 0.0f) {
/* -- draw rotation axis -- */
float scaled_axis[3];
const float scale = rv3d->dist;
@@ -653,19 +666,21 @@ static void draw_rotation_guide(RegionView3D *rv3d)
glBegin(GL_LINE_STRIP);
- color[3] = 0.f; /* more transparent toward the ends */
+ color[3] = 0.0f; /* more transparent toward the ends */
glColor4fv(color);
add_v3_v3v3(end, o, scaled_axis);
glVertex3fv(end);
- // color[3] = 0.2f + fabsf(rv3d->rot_angle); /* modulate opacity with angle */
- // ^^ neat idea, but angle is frame-rate dependent, so it's usually close to 0.2
+#if 0
+ color[3] = 0.2f + fabsf(rv3d->rot_angle); /* modulate opacity with angle */
+ /* ^^ neat idea, but angle is frame-rate dependent, so it's usually close to 0.2 */
+#endif
color[3] = 0.5f; /* more opaque toward the center */
glColor4fv(color);
glVertex3fv(o);
- color[3] = 0.f;
+ color[3] = 0.0f;
glColor4fv(color);
sub_v3_v3v3(end, o, scaled_axis);
glVertex3fv(end);
@@ -676,14 +691,14 @@ static void draw_rotation_guide(RegionView3D *rv3d)
#define ROT_AXIS_DETAIL 13
const float s = 0.05f * scale;
- const float step = 2.f * (float)(M_PI / ROT_AXIS_DETAIL);
+ const float step = 2.0f * (float)(M_PI / ROT_AXIS_DETAIL);
float angle;
int i;
float q[4]; /* rotate ring so it's perpendicular to axis */
const int upright = fabsf(rv3d->rot_axis[2]) >= 0.95f;
if (!upright) {
- const float up[3] = {0.f, 0.f, 1.f};
+ const float up[3] = {0.0f, 0.0f, 1.0f};
float vis_angle, vis_axis[3];
cross_v3_v3v3(vis_axis, up, rv3d->rot_axis);
@@ -694,7 +709,7 @@ static void draw_rotation_guide(RegionView3D *rv3d)
color[3] = 0.25f; /* somewhat faint */
glColor4fv(color);
glBegin(GL_LINE_LOOP);
- for (i = 0, angle = 0.f; i < ROT_AXIS_DETAIL; ++i, angle += step) {
+ for (i = 0, angle = 0.0f; i < ROT_AXIS_DETAIL; ++i, angle += step) {
float p[3] = {s * cosf(angle), s * sinf(angle), 0.0f};
if (!upright) {
@@ -720,12 +735,12 @@ static void draw_rotation_guide(RegionView3D *rv3d)
glVertex3fv(o);
glEnd();
- /* find screen coordinates for rotation center, then draw pretty icon */
#if 0
+ /* find screen coordinates for rotation center, then draw pretty icon */
mul_m4_v3(rv3d->persinv, rot_center);
UI_icon_draw(rot_center[0], rot_center[1], ICON_NDOF_TURN);
-#endif
/* ^^ just playing around, does not work */
+#endif
glDisable(GL_BLEND);
glDisable(GL_POINT_SMOOTH);
@@ -787,7 +802,16 @@ static const char *view3d_get_name(View3D *v3d, RegionView3D *rv3d)
if ((v3d->camera) && (v3d->camera->type == OB_CAMERA)) {
Camera *cam;
cam = v3d->camera->data;
- name = (cam->type != CAM_ORTHO) ? IFACE_("Camera Persp") : IFACE_("Camera Ortho");
+ if (cam->type == CAM_PERSP) {
+ name = IFACE_("Camera Persp");
+ }
+ else if (cam->type == CAM_ORTHO) {
+ name = IFACE_("Camera Ortho");
+ }
+ else {
+ BLI_assert(cam->type == CAM_PANO);
+ name = IFACE_("Camera Pano");
+ }
}
else {
name = IFACE_("Object as Camera");
@@ -935,8 +959,9 @@ static void draw_selected_name(Scene *scene, Object *ob, rcti *rect)
BLF_draw_default(offset, 0.5f * U.widget_unit, 0.0f, info, sizeof(info));
}
-static void view3d_camera_border(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D *rv3d,
- rctf *r_viewborder, const bool no_shift, const bool no_zoom)
+static void view3d_camera_border(
+ const Scene *scene, const ARegion *ar, const View3D *v3d, const RegionView3D *rv3d,
+ rctf *r_viewborder, const bool no_shift, const bool no_zoom)
{
CameraParams params;
rctf rect_view, rect_camera;
@@ -969,7 +994,9 @@ static void view3d_camera_border(Scene *scene, ARegion *ar, View3D *v3d, RegionV
r_viewborder->ymax = ((rect_camera.ymax - rect_view.ymin) / BLI_rctf_size_y(&rect_view)) * ar->winy;
}
-void ED_view3d_calc_camera_border_size(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D *rv3d, float r_size[2])
+void ED_view3d_calc_camera_border_size(
+ const Scene *scene, const ARegion *ar, const View3D *v3d, const RegionView3D *rv3d,
+ float r_size[2])
{
rctf viewborder;
@@ -978,8 +1005,9 @@ void ED_view3d_calc_camera_border_size(Scene *scene, ARegion *ar, View3D *v3d, R
r_size[1] = BLI_rctf_size_y(&viewborder);
}
-void ED_view3d_calc_camera_border(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D *rv3d,
- rctf *r_viewborder, const bool no_shift)
+void ED_view3d_calc_camera_border(
+ const Scene *scene, const ARegion *ar, const View3D *v3d, const RegionView3D *rv3d,
+ rctf *r_viewborder, const bool no_shift)
{
view3d_camera_border(scene, ar, v3d, rv3d, r_viewborder, no_shift, false);
}
@@ -1057,14 +1085,13 @@ static void drawviewborder_triangle(float x1, float x2, float y1, float y2, cons
static void drawviewborder(Scene *scene, ARegion *ar, View3D *v3d)
{
- float hmargin, vmargin;
float x1, x2, y1, y2;
float x1i, x2i, y1i, y2i;
rctf viewborder;
Camera *ca = NULL;
RegionView3D *rv3d = ar->regiondata;
-
+
if (v3d->camera == NULL)
return;
if (v3d->camera->type == OB_CAMERA)
@@ -1091,6 +1118,9 @@ static void drawviewborder(Scene *scene, ARegion *ar, View3D *v3d)
/* passepartout, specified in camera edit buttons */
if (ca && (ca->flag & CAM_SHOWPASSEPARTOUT) && ca->passepartalpha > 0.000001f) {
+ const float winx = (ar->winx + 1);
+ const float winy = (ar->winy + 1);
+
if (ca->passepartalpha == 1.0f) {
glColor3f(0, 0, 0);
}
@@ -1100,11 +1130,11 @@ static void drawviewborder(Scene *scene, ARegion *ar, View3D *v3d)
glColor4f(0, 0, 0, ca->passepartalpha);
}
if (x1i > 0.0f)
- glRectf(0.0, (float)ar->winy, x1i, 0.0);
- if (x2i < (float)ar->winx)
- glRectf(x2i, (float)ar->winy, (float)ar->winx, 0.0);
- if (y2i < (float)ar->winy)
- glRectf(x1i, (float)ar->winy, x2i, y2i);
+ glRectf(0.0, winy, x1i, 0.0);
+ if (x2i < winx)
+ glRectf(x2i, winy, winx, 0.0);
+ if (y2i < winy)
+ glRectf(x1i, winy, x2i, y2i);
if (y2i > 0.0f)
glRectf(x1i, y1i, x2i, 0.0);
@@ -1143,10 +1173,10 @@ static void drawviewborder(Scene *scene, ARegion *ar, View3D *v3d)
if (scene->r.mode & R_BORDER) {
float x3, y3, x4, y4;
- x3 = x1 + scene->r.border.xmin * (x2 - x1);
- y3 = y1 + scene->r.border.ymin * (y2 - y1);
- x4 = x1 + scene->r.border.xmax * (x2 - x1);
- y4 = y1 + scene->r.border.ymax * (y2 - y1);
+ x3 = x1i + 1 + roundf(scene->r.border.xmin * (x2 - x1));
+ y3 = y1i + 1 + roundf(scene->r.border.ymin * (y2 - y1));
+ x4 = x1i + 1 + roundf(scene->r.border.xmax * (x2 - x1));
+ y4 = y1i + 1 + roundf(scene->r.border.ymax * (y2 - y1));
cpack(0x4040FF);
glRecti(x3, y3, x4, y4);
@@ -1213,17 +1243,20 @@ static void drawviewborder(Scene *scene, ARegion *ar, View3D *v3d)
drawviewborder_triangle(x1, x2, y1, y2, 1, 'B');
}
- if (ca->flag & CAM_SHOWTITLESAFE) {
- UI_ThemeColorBlendShade(TH_VIEW_OVERLAY, TH_BACK, 0.25, 0);
-
- hmargin = 0.1f * (x2 - x1);
- vmargin = 0.05f * (y2 - y1);
- uiDrawBox(GL_LINE_LOOP, x1 + hmargin, y1 + vmargin, x2 - hmargin, y2 - vmargin, 2.0f);
+ if (ca->flag & CAM_SHOW_SAFE_MARGINS) {
+ UI_draw_safe_areas(
+ x1, x2, y1, y2,
+ scene->safe_areas.title,
+ scene->safe_areas.action);
- hmargin = 0.035f * (x2 - x1);
- vmargin = 0.035f * (y2 - y1);
- uiDrawBox(GL_LINE_LOOP, x1 + hmargin, y1 + vmargin, x2 - hmargin, y2 - vmargin, 2.0f);
+ if (ca->flag & CAM_SHOW_SAFE_CENTER) {
+ UI_draw_safe_areas(
+ x1, x2, y1, y2,
+ scene->safe_areas.title_center,
+ scene->safe_areas.action_center);
+ }
}
+
if (ca->flag & CAM_SHOWSENSOR) {
/* determine sensor fit, and get sensor x/y, for auto fit we
* assume and square sensor and only use sensor_x */
@@ -1257,7 +1290,7 @@ static void drawviewborder(Scene *scene, ARegion *ar, View3D *v3d)
/* draw */
UI_ThemeColorShade(TH_VIEW_OVERLAY, 100);
- uiDrawBox(GL_LINE_LOOP, rect.xmin, rect.ymin, rect.xmax, rect.ymax, 2.0f);
+ UI_draw_roundbox_gl_mode(GL_LINE_LOOP, rect.xmin, rect.ymin, rect.xmax, rect.ymax, 2.0f);
}
}
@@ -1267,8 +1300,9 @@ static void drawviewborder(Scene *scene, ARegion *ar, View3D *v3d)
/* camera name - draw in highlighted text color */
if (ca && (ca->flag & CAM_SHOWNAME)) {
UI_ThemeColor(TH_TEXT_HI);
- BLF_draw_default(x1i, y1i - 15, 0.0f, v3d->camera->id.name + 2, sizeof(v3d->camera->id.name) - 2);
- UI_ThemeColor(TH_WIRE);
+ BLF_draw_default(
+ x1i, y1i - (0.7f * U.widget_unit), 0.0f,
+ v3d->camera->id.name + 2, sizeof(v3d->camera->id.name) - 2);
}
}
@@ -1294,12 +1328,12 @@ static void backdrawview3d(Scene *scene, ARegion *ar, View3D *v3d)
/* do nothing */
}
else if ((base && (base->object->mode & OB_MODE_PARTICLE_EDIT)) &&
- v3d->drawtype > OB_WIRE && (v3d->flag & V3D_ZBUF_SELECT))
+ V3D_IS_ZBUF(v3d))
{
/* do nothing */
}
- else if (scene->obedit && v3d->drawtype > OB_WIRE &&
- (v3d->flag & V3D_ZBUF_SELECT))
+ else if (scene->obedit &&
+ V3D_IS_ZBUF(v3d))
{
/* do nothing */
}
@@ -1355,11 +1389,11 @@ static void backdrawview3d(Scene *scene, ARegion *ar, View3D *v3d)
}
if (rv3d->gpuoffscreen)
- GPU_offscreen_bind(rv3d->gpuoffscreen);
+ GPU_offscreen_bind(rv3d->gpuoffscreen, true);
else
glScissor(ar->winrct.xmin, ar->winrct.ymin, BLI_rcti_size_x(&ar->winrct), BLI_rcti_size_y(&ar->winrct));
- glClearColor(0.0, 0.0, 0.0, 0.0);
+ glClearColor(0.0, 0.0, 0.0, 0.0);
if (v3d->zbuf) {
glEnable(GL_DEPTH_TEST);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
@@ -1378,7 +1412,7 @@ static void backdrawview3d(Scene *scene, ARegion *ar, View3D *v3d)
draw_object_backbufsel(scene, v3d, rv3d, base->object);
if (rv3d->gpuoffscreen)
- GPU_offscreen_unbind(rv3d->gpuoffscreen);
+ GPU_offscreen_unbind(rv3d->gpuoffscreen, true);
else
ar->swap = 0; /* mark invalid backbuf for wm draw */
@@ -1404,10 +1438,10 @@ void view3d_opengl_read_pixels(ARegion *ar, int x, int y, int w, int h, int form
RegionView3D *rv3d = ar->regiondata;
if (rv3d->gpuoffscreen) {
- GPU_offscreen_bind(rv3d->gpuoffscreen);
+ GPU_offscreen_bind(rv3d->gpuoffscreen, true);
glReadBuffer(GL_COLOR_ATTACHMENT0_EXT);
glReadPixels(x, y, w, h, format, type, data);
- GPU_offscreen_unbind(rv3d->gpuoffscreen);
+ GPU_offscreen_unbind(rv3d->gpuoffscreen, true);
}
else {
glReadPixels(ar->winrct.xmin + x, ar->winrct.ymin + y, w, h, format, type, data);
@@ -1421,14 +1455,23 @@ static void view3d_opengl_read_Z_pixels(ARegion *ar, int x, int y, int w, int h,
glReadPixels(ar->winrct.xmin + x, ar->winrct.ymin + y, w, h, format, type, data);
}
-void view3d_validate_backbuf(ViewContext *vc)
+void ED_view3d_backbuf_validate(ViewContext *vc)
{
if (vc->v3d->flag & V3D_INVALID_BACKBUF)
backdrawview3d(vc->scene, vc->ar, vc->v3d);
}
+/**
+ * allow for small values [0.5 - 2.5],
+ * and large values, FLT_MAX by clamping by the area size
+ */
+int ED_view3d_backbuf_sample_size_clamp(ARegion *ar, const float dist)
+{
+ return (int)min_ff(ceilf(dist), (float)max_ii(ar->winx, ar->winx));
+}
+
/* samples a single pixel (copied from vpaint) */
-unsigned int view3d_sample_backbuf(ViewContext *vc, int x, int y)
+unsigned int ED_view3d_backbuf_sample(ViewContext *vc, int x, int y)
{
unsigned int col;
@@ -1436,7 +1479,7 @@ unsigned int view3d_sample_backbuf(ViewContext *vc, int x, int y)
return 0;
}
- view3d_validate_backbuf(vc);
+ ED_view3d_backbuf_validate(vc);
view3d_opengl_read_pixels(vc->ar, x, y, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &col);
glReadBuffer(GL_BACK);
@@ -1449,81 +1492,79 @@ unsigned int view3d_sample_backbuf(ViewContext *vc, int x, int y)
}
/* reads full rect, converts indices */
-ImBuf *view3d_read_backbuf(ViewContext *vc, short xmin, short ymin, short xmax, short ymax)
+ImBuf *ED_view3d_backbuf_read(ViewContext *vc, int xmin, int ymin, int xmax, int ymax)
{
- unsigned int *dr, *rd;
- struct ImBuf *ibuf, *ibuf1;
- int a;
- short xminc, yminc, xmaxc, ymaxc, xs, ys;
-
+ struct ImBuf *ibuf_clip;
/* clip */
- if (xmin < 0) xminc = 0; else xminc = xmin;
- if (xmax >= vc->ar->winx) xmaxc = vc->ar->winx - 1; else xmaxc = xmax;
- if (xminc > xmaxc) return NULL;
+ const rcti clip = {
+ max_ii(xmin, 0), min_ii(xmax, vc->ar->winx - 1),
+ max_ii(ymin, 0), min_ii(ymax, vc->ar->winy - 1)};
+ const int size_clip[2] = {
+ BLI_rcti_size_x(&clip) + 1,
+ BLI_rcti_size_y(&clip) + 1};
+
+ if (UNLIKELY((clip.xmin > clip.xmax) ||
+ (clip.ymin > clip.ymax)))
+ {
+ return NULL;
+ }
- if (ymin < 0) yminc = 0; else yminc = ymin;
- if (ymax >= vc->ar->winy) ymaxc = vc->ar->winy - 1; else ymaxc = ymax;
- if (yminc > ymaxc) return NULL;
-
- ibuf = IMB_allocImBuf((xmaxc - xminc + 1), (ymaxc - yminc + 1), 32, IB_rect);
+ ibuf_clip = IMB_allocImBuf(size_clip[0], size_clip[1], 32, IB_rect);
- view3d_validate_backbuf(vc);
+ ED_view3d_backbuf_validate(vc);
- view3d_opengl_read_pixels(vc->ar,
- xminc, yminc,
- (xmaxc - xminc + 1),
- (ymaxc - yminc + 1),
- GL_RGBA, GL_UNSIGNED_BYTE, ibuf->rect);
+ view3d_opengl_read_pixels(vc->ar, clip.xmin, clip.ymin, size_clip[0], size_clip[1], GL_RGBA, GL_UNSIGNED_BYTE, ibuf_clip->rect);
glReadBuffer(GL_BACK);
- if (ENDIAN_ORDER == B_ENDIAN) IMB_convert_rgba_to_abgr(ibuf);
-
- a = (xmaxc - xminc + 1) * (ymaxc - yminc + 1);
- dr = ibuf->rect;
- while (a--) {
- if (*dr) *dr = WM_framebuffer_to_index(*dr);
- dr++;
+ if (ENDIAN_ORDER == B_ENDIAN) {
+ IMB_convert_rgba_to_abgr(ibuf_clip);
}
+
+ WM_framebuffer_to_index_array(ibuf_clip->rect, size_clip[0] * size_clip[1]);
- /* put clipped result back, if needed */
- if (xminc == xmin && xmaxc == xmax && yminc == ymin && ymaxc == ymax)
- return ibuf;
-
- ibuf1 = IMB_allocImBuf( (xmax - xmin + 1), (ymax - ymin + 1), 32, IB_rect);
- rd = ibuf->rect;
- dr = ibuf1->rect;
+ if ((clip.xmin == xmin) &&
+ (clip.xmax == xmax) &&
+ (clip.ymin == ymin) &&
+ (clip.ymax == ymax))
+ {
+ return ibuf_clip;
+ }
+ else {
+ /* put clipped result into a non-clipped buffer */
+ struct ImBuf *ibuf_full;
+ const int size[2] = {
+ (xmax - xmin + 1),
+ (ymax - ymin + 1)};
- for (ys = ymin; ys <= ymax; ys++) {
- for (xs = xmin; xs <= xmax; xs++, dr++) {
- if (xs >= xminc && xs <= xmaxc && ys >= yminc && ys <= ymaxc) {
- *dr = *rd;
- rd++;
- }
- }
+ ibuf_full = IMB_allocImBuf(size[0], size[1], 32, IB_rect);
+
+ IMB_rectcpy(
+ ibuf_full, ibuf_clip,
+ clip.xmin - xmin, clip.ymin - ymin,
+ 0, 0,
+ size_clip[0], size_clip[1]);
+ IMB_freeImBuf(ibuf_clip);
+ return ibuf_full;
}
- IMB_freeImBuf(ibuf);
- return ibuf1;
}
/* smart function to sample a rect spiralling outside, nice for backbuf selection */
-unsigned int view3d_sample_backbuf_rect(ViewContext *vc, const int mval[2], int size,
- unsigned int min, unsigned int max, float *r_dist, short strict,
- void *handle, bool (*indextest)(void *handle, unsigned int index))
+unsigned int ED_view3d_backbuf_sample_rect(
+ ViewContext *vc, const int mval[2], int size,
+ unsigned int min, unsigned int max, float *r_dist)
{
struct ImBuf *buf;
- unsigned int *bufmin, *bufmax, *tbuf;
+ const unsigned int *bufmin, *bufmax, *tbuf;
int minx, miny;
int a, b, rc, nr, amount, dirvec[4][2];
- int distance = 0;
unsigned int index = 0;
- bool indexok = false;
amount = (size - 1) / 2;
minx = mval[0] - (amount + 1);
miny = mval[1] - (amount + 1);
- buf = view3d_read_backbuf(vc, minx, miny, minx + size - 1, miny + size - 1);
+ buf = ED_view3d_backbuf_read(vc, minx, miny, minx + size - 1, miny + size - 1);
if (!buf) return 0;
rc = 0;
@@ -1541,21 +1582,19 @@ unsigned int view3d_sample_backbuf_rect(ViewContext *vc, const int mval[2], int
for (nr = 1; nr <= size; nr++) {
for (a = 0; a < 2; a++) {
- for (b = 0; b < nr; b++, distance++) {
- if (*tbuf && *tbuf >= min && *tbuf < max) { /* we got a hit */
- if (strict) {
- indexok = indextest(handle, *tbuf - min + 1);
- if (indexok) {
- *r_dist = sqrtf((float)distance);
- index = *tbuf - min + 1;
- goto exit;
- }
- }
- else {
- *r_dist = sqrtf((float)distance); /* XXX, this distance is wrong - */
- index = *tbuf - min + 1; /* messy yah, but indices start at 1 */
- goto exit;
- }
+ for (b = 0; b < nr; b++) {
+ if (*tbuf && *tbuf >= min && *tbuf < max) {
+ /* we got a hit */
+
+ /* get x,y pixel coords from the offset
+ * (manhatten distance in keeping with other screen-based selection) */
+ *r_dist = (float)(
+ abs(((int)(tbuf - buf->rect) % size) - (size / 2)) +
+ abs(((int)(tbuf - buf->rect) / size) - (size / 2)));
+
+ /* indices start at 1 here */
+ index = (*tbuf - min) + 1;
+ goto exit;
}
tbuf += (dirvec[rc][0] + dirvec[rc][1]);
@@ -1577,6 +1616,26 @@ exit:
/* ************************************************************* */
+static void view3d_stereo_bgpic_setup(Scene *scene, View3D *v3d, Image *ima, ImageUser *iuser)
+{
+ if ((ima->flag & IMA_IS_STEREO)) {
+ iuser->flag |= IMA_SHOW_STEREO;
+
+ if ((scene->r.scemode & R_MULTIVIEW) == 0) {
+ iuser->multiview_eye = STEREO_LEFT_ID;
+ }
+ else if (v3d->stereo3d_camera != STEREO_3D_ID) {
+ /* show only left or right camera */
+ iuser->multiview_eye = v3d->stereo3d_camera;
+ }
+
+ BKE_image_multiview_index(ima, iuser);
+ }
+ else {
+ iuser->flag &= ~IMA_SHOW_STEREO;
+ }
+}
+
static void view3d_draw_bgpic(Scene *scene, ARegion *ar, View3D *v3d,
const bool do_foreground, const bool do_camera_frame)
{
@@ -1585,6 +1644,7 @@ static void view3d_draw_bgpic(Scene *scene, ARegion *ar, View3D *v3d,
int fg_flag = do_foreground ? V3D_BGPIC_FOREGROUND : 0;
for (bgpic = v3d->bgpicbase.first; bgpic; bgpic = bgpic->next) {
+ bgpic->iuser.scene = scene; /* Needed for render results. */
if ((bgpic->flag & V3D_BGPIC_FOREGROUND) != fg_flag)
continue;
@@ -1595,12 +1655,14 @@ static void view3d_draw_bgpic(Scene *scene, ARegion *ar, View3D *v3d,
{
float image_aspect[2];
float fac, asp, zoomx, zoomy;
- float x1, y1, x2, y2;
+ float x1, y1, x2, y2, centx, centy;
ImBuf *ibuf = NULL, *freeibuf, *releaseibuf;
+ void *lock;
+ rctf clip_rect;
- Image *ima;
- MovieClip *clip;
+ Image *ima = NULL;
+ MovieClip *clip = NULL;
/* disable individual images */
if ((bgpic->flag & V3D_BGPIC_DISABLED))
@@ -1617,16 +1679,15 @@ static void view3d_draw_bgpic(Scene *scene, ARegion *ar, View3D *v3d,
ibuf = NULL; /* frame is out of range, dont show */
}
else {
- ibuf = BKE_image_acquire_ibuf(ima, &bgpic->iuser, NULL);
+ view3d_stereo_bgpic_setup(scene, v3d, ima, &bgpic->iuser);
+ ibuf = BKE_image_acquire_ibuf(ima, &bgpic->iuser, &lock);
releaseibuf = ibuf;
}
image_aspect[0] = ima->aspx;
- image_aspect[1] = ima->aspx;
+ image_aspect[1] = ima->aspy;
}
else if (bgpic->source == V3D_BGPIC_MOVIE) {
- clip = NULL;
-
/* TODO: skip drawing when out of frame range (as image sequences do above) */
if (bgpic->flag & V3D_BGPIC_CAMERACLIP) {
@@ -1664,7 +1725,7 @@ static void view3d_draw_bgpic(Scene *scene, ARegion *ar, View3D *v3d,
if (freeibuf)
IMB_freeImBuf(freeibuf);
if (releaseibuf)
- BKE_image_release_ibuf(ima, releaseibuf, NULL);
+ BKE_image_release_ibuf(ima, releaseibuf, lock);
continue;
}
@@ -1702,6 +1763,9 @@ static void view3d_draw_bgpic(Scene *scene, ARegion *ar, View3D *v3d,
y2 += yof_scale;
}
+ centx = (x1 + x2) / 2.0f;
+ centy = (y1 + y2) / 2.0f;
+
/* aspect correction */
if (bgpic->flag & V3D_BGPIC_CAMERA_ASPECT) {
/* apply aspect from clip */
@@ -1719,16 +1783,14 @@ static void view3d_draw_bgpic(Scene *scene, ARegion *ar, View3D *v3d,
if ((asp_src > asp_dst) == ((bgpic->flag & V3D_BGPIC_CAMERA_CROP) != 0)) {
/* fit X */
const float div = asp_src / asp_dst;
- const float cent = (x1 + x2) / 2.0f;
- x1 = ((x1 - cent) * div) + cent;
- x2 = ((x2 - cent) * div) + cent;
+ x1 = ((x1 - centx) * div) + centx;
+ x2 = ((x2 - centx) * div) + centx;
}
else {
/* fit Y */
const float div = asp_dst / asp_src;
- const float cent = (y1 + y2) / 2.0f;
- y1 = ((y1 - cent) * div) + cent;
- y2 = ((y2 - cent) * div) + cent;
+ y1 = ((y1 - centy) * div) + centy;
+ y2 = ((y2 - centy) * div) + centy;
}
}
}
@@ -1755,15 +1817,22 @@ static void view3d_draw_bgpic(Scene *scene, ARegion *ar, View3D *v3d,
y1 = sco[1] + asp * fac * (bgpic->yof - bgpic->size);
x2 = sco[0] + fac * (bgpic->xof + bgpic->size);
y2 = sco[1] + asp * fac * (bgpic->yof + bgpic->size);
+
+ centx = (x1 + x2) / 2.0f;
+ centy = (y1 + y2) / 2.0f;
}
/* complete clip? */
+ BLI_rctf_init(&clip_rect, x1, x2, y1, y2);
+ if (bgpic->rotation) {
+ BLI_rctf_rotate_expand(&clip_rect, &clip_rect, bgpic->rotation);
+ }
- if (x2 < 0 || y2 < 0 || x1 > ar->winx || y1 > ar->winy) {
+ if (clip_rect.xmax < 0 || clip_rect.ymax < 0 || clip_rect.xmin > ar->winx || clip_rect.ymin > ar->winy) {
if (freeibuf)
IMB_freeImBuf(freeibuf);
if (releaseibuf)
- BKE_image_release_ibuf(ima, releaseibuf, NULL);
+ BKE_image_release_ibuf(ima, releaseibuf, lock);
continue;
}
@@ -1805,6 +1874,17 @@ static void view3d_draw_bgpic(Scene *scene, ARegion *ar, View3D *v3d,
glPushMatrix();
ED_region_pixelspace(ar);
+ glTranslatef(centx, centy, 0.0);
+ glRotatef(RAD2DEGF(-bgpic->rotation), 0.0f, 0.0f, 1.0f);
+
+ if (bgpic->flag & V3D_BGPIC_FLIP_X) {
+ zoomx *= -1.0f;
+ x1 = x2;
+ }
+ if (bgpic->flag & V3D_BGPIC_FLIP_Y) {
+ zoomy *= -1.0f;
+ y1 = y2;
+ }
glPixelZoom(zoomx, zoomy);
glColor4f(1.0f, 1.0f, 1.0f, 1.0f - bgpic->blend);
@@ -1812,7 +1892,7 @@ static void view3d_draw_bgpic(Scene *scene, ARegion *ar, View3D *v3d,
* glaDrawPixelsSafe in some cases, which will end up in missing
* alpha transparency for the background image (sergey)
*/
- glaDrawPixelsTex(x1, y1, ibuf->x, ibuf->y, GL_RGBA, GL_UNSIGNED_BYTE, GL_LINEAR, ibuf->rect);
+ glaDrawPixelsTex(x1 - centx, y1 - centy, ibuf->x, ibuf->y, GL_RGBA, GL_UNSIGNED_BYTE, GL_LINEAR, ibuf->rect);
glPixelZoom(1.0, 1.0);
glPixelTransferf(GL_ALPHA_SCALE, 1.0f);
@@ -1830,7 +1910,7 @@ static void view3d_draw_bgpic(Scene *scene, ARegion *ar, View3D *v3d,
if (freeibuf)
IMB_freeImBuf(freeibuf);
if (releaseibuf)
- BKE_image_release_ibuf(ima, releaseibuf, NULL);
+ BKE_image_release_ibuf(ima, releaseibuf, lock);
}
}
}
@@ -1883,7 +1963,7 @@ static void view3d_draw_transp(Scene *scene, ARegion *ar, View3D *v3d)
{
View3DAfter *v3da, *next;
- glDepthMask(0);
+ glDepthMask(GL_FALSE);
v3d->transp = true;
for (v3da = v3d->afterdraw_transp.first; v3da; v3da = next) {
@@ -1894,17 +1974,19 @@ static void view3d_draw_transp(Scene *scene, ARegion *ar, View3D *v3d)
}
v3d->transp = false;
- glDepthMask(1);
+ glDepthMask(GL_TRUE);
}
/* clears zbuffer and draws it over */
-static void view3d_draw_xray(Scene *scene, ARegion *ar, View3D *v3d, const bool clear)
+static void view3d_draw_xray(Scene *scene, ARegion *ar, View3D *v3d, bool *clear)
{
View3DAfter *v3da, *next;
- if (clear && v3d->zbuf)
+ if (*clear && v3d->zbuf) {
glClear(GL_DEPTH_BUFFER_BIT);
+ *clear = false;
+ }
v3d->xray = true;
for (v3da = v3d->afterdraw_xray.first; v3da; v3da = next) {
@@ -1928,6 +2010,8 @@ static void view3d_draw_xraytransp(Scene *scene, ARegion *ar, View3D *v3d, const
v3d->xray = true;
v3d->transp = true;
+ glDepthMask(GL_FALSE);
+
for (v3da = v3d->afterdraw_xraytransp.first; v3da; v3da = next) {
next = v3da->next;
draw_object(scene, ar, v3d, v3da->base, v3da->dflag);
@@ -1938,6 +2022,7 @@ static void view3d_draw_xraytransp(Scene *scene, ARegion *ar, View3D *v3d, const
v3d->transp = false;
v3d->xray = false;
+ glDepthMask(GL_TRUE);
}
/* *********************** */
@@ -2000,9 +2085,9 @@ static void draw_dupli_objects_color(
tbase.flag = OB_FROMDUPLI | base->flag;
lb = object_duplilist(G.main->eval_ctx, scene, base->object);
- // BLI_sortlist(lb, dupli_ob_sort); /* might be nice to have if we have a dupli list with mixed objects. */
+ // BLI_listbase_sort(lb, dupli_ob_sort); /* might be nice to have if we have a dupli list with mixed objects. */
- apply_data = duplilist_apply(base->object, lb);
+ apply_data = duplilist_apply(base->object, scene, lb);
dob = dupli_step(lb->first);
if (dob) dob_next = dupli_step(dob->next);
@@ -2068,14 +2153,14 @@ static void draw_dupli_objects_color(
* so for now it should be ok to - campbell */
if ( /* if this is the last no need to make a displist */
- (dob_next == NULL || dob_next->ob != dob->ob) ||
- /* 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 ||
- draw_glsl_material(scene, dob->ob, v3d, dt) ||
- check_object_draw_texture(scene, v3d, dt) ||
- (base->object == OBACT && v3d->flag2 & V3D_SOLID_MATCAP))
+ (dob_next == NULL || dob_next->ob != dob->ob) ||
+ /* 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 ||
+ draw_glsl_material(scene, dob->ob, v3d, dt) ||
+ check_object_draw_texture(scene, v3d, dt) ||
+ (v3d->flag2 & V3D_SOLID_MATCAP) != 0)
{
// printf("draw_dupli_objects_color: skipping displist for %s\n", dob->ob->id.name + 2);
use_displist = false;
@@ -2106,7 +2191,9 @@ static void draw_dupli_objects_color(
}
else {
copy_m4_m4(dob->ob->obmat, dob->mat);
+ GPU_begin_dupli_object(dob);
draw_object(scene, ar, v3d, &tbase, dflag_dupli);
+ GPU_end_dupli_object();
}
}
@@ -2310,7 +2397,9 @@ void ED_view3d_draw_depth(Scene *scene, ARegion *ar, View3D *v3d, bool alphaover
if (rv3d->rflag & RV3D_CLIPPING) {
ED_view3d_clipping_set(rv3d);
}
-
+ /* get surface depth without bias */
+ rv3d->rflag |= RV3D_ZOFFSET_DISABLED;
+
v3d->zbuf = true;
glEnable(GL_DEPTH_TEST);
@@ -2395,8 +2484,10 @@ void ED_view3d_draw_depth(Scene *scene, ARegion *ar, View3D *v3d, bool alphaover
glDepthMask(mask_orig);
}
- if (rv3d->rflag & RV3D_CLIPPING)
+ if (rv3d->rflag & RV3D_CLIPPING) {
ED_view3d_clipping_disable();
+ }
+ rv3d->rflag &= ~RV3D_ZOFFSET_DISABLED;
v3d->zbuf = zbuf;
if (!v3d->zbuf) glDisable(GL_DEPTH_TEST);
@@ -2411,8 +2502,10 @@ typedef struct View3DShadow {
GPULamp *lamp;
} View3DShadow;
-static void gpu_render_lamp_update(Scene *scene, View3D *v3d, Object *ob, Object *par,
- float obmat[4][4], ListBase *shadows, SceneRenderLayer *srl)
+static void gpu_render_lamp_update(Scene *scene, View3D *v3d,
+ Object *ob, Object *par,
+ float obmat[4][4], unsigned int lay,
+ ListBase *shadows, SceneRenderLayer *srl)
{
GPULamp *lamp;
Lamp *la = (Lamp *)ob->data;
@@ -2422,10 +2515,10 @@ static void gpu_render_lamp_update(Scene *scene, View3D *v3d, Object *ob, Object
lamp = GPU_lamp_from_blender(scene, ob, par);
if (lamp) {
- GPU_lamp_update(lamp, ob->lay, (ob->restrictflag & OB_RESTRICT_RENDER), obmat);
+ GPU_lamp_update(lamp, lay, (ob->restrictflag & OB_RESTRICT_RENDER), obmat);
GPU_lamp_update_colors(lamp, la->r, la->g, la->b, la->energy);
- layers = ob->lay & v3d->lay;
+ layers = lay & v3d->lay;
if (srl)
layers &= srl->lay;
@@ -2437,13 +2530,14 @@ static void gpu_render_lamp_update(Scene *scene, View3D *v3d, Object *ob, Object
}
}
-static void gpu_update_lamps_shadows(Scene *scene, View3D *v3d)
+static void gpu_update_lamps_shadows_world(Scene *scene, View3D *v3d)
{
ListBase shadows;
View3DShadow *shadow;
Scene *sce_iter;
Base *base;
Object *ob;
+ World *world = scene->world;
SceneRenderLayer *srl = v3d->scenelock ? BLI_findlink(&scene->r.layers, scene->r.actlay) : NULL;
BLI_listbase_clear(&shadows);
@@ -2453,7 +2547,7 @@ static void gpu_update_lamps_shadows(Scene *scene, View3D *v3d)
ob = base->object;
if (ob->type == OB_LAMP)
- gpu_render_lamp_update(scene, v3d, ob, NULL, ob->obmat, &shadows, srl);
+ gpu_render_lamp_update(scene, v3d, ob, NULL, ob->obmat, ob->lay, &shadows, srl);
if (ob->transflag & OB_DUPLI) {
DupliObject *dob;
@@ -2461,7 +2555,7 @@ static void gpu_update_lamps_shadows(Scene *scene, View3D *v3d)
for (dob = lb->first; dob; dob = dob->next)
if (dob->ob->type == OB_LAMP)
- gpu_render_lamp_update(scene, v3d, dob->ob, ob, dob->mat, &shadows, srl);
+ gpu_render_lamp_update(scene, v3d, dob->ob, ob, dob->mat, ob->lay, &shadows, srl);
free_object_duplilist(lb);
}
@@ -2481,7 +2575,7 @@ static void gpu_update_lamps_shadows(Scene *scene, View3D *v3d)
v3d->drawtype = OB_SOLID;
v3d->lay &= GPU_lamp_shadow_layer(shadow->lamp);
- v3d->flag2 &= ~V3D_SOLID_TEX | V3D_SHOW_SOLID_MATCAP;
+ v3d->flag2 &= ~(V3D_SOLID_TEX | V3D_SHOW_SOLID_MATCAP);
v3d->flag2 |= V3D_RENDER_OVERRIDE | V3D_RENDER_SHADOW;
GPU_lamp_shadow_buffer_bind(shadow->lamp, viewmat, &winsize, winmat);
@@ -2496,7 +2590,10 @@ static void gpu_update_lamps_shadows(Scene *scene, View3D *v3d)
invert_m4_m4(rv3d.persinv, rv3d.viewinv);
/* no need to call ED_view3d_draw_offscreen_init since shadow buffers were already updated */
- ED_view3d_draw_offscreen(scene, v3d, &ar, winsize, winsize, viewmat, winmat, false, false);
+ ED_view3d_draw_offscreen(
+ scene, v3d, &ar, winsize, winsize, viewmat, winmat,
+ false, false, true,
+ NULL, NULL, NULL, NULL);
GPU_lamp_shadow_buffer_unbind(shadow->lamp);
v3d->drawtype = drawtype;
@@ -2505,18 +2602,26 @@ static void gpu_update_lamps_shadows(Scene *scene, View3D *v3d)
}
BLI_freelistN(&shadows);
+
+ /* update world values */
+ if (world) {
+ GPU_mist_update_enable(world->mode & WO_MIST);
+ GPU_mist_update_values(world->mistype, world->miststa, world->mistdist, world->misi, &world->horr);
+ GPU_horizon_update_color(&world->horr);
+ GPU_ambient_update_color(&world->ambr);
+ }
}
/* *********************** customdata **************** */
-CustomDataMask ED_view3d_datamask(Scene *scene, View3D *v3d)
+CustomDataMask ED_view3d_datamask(const Scene *scene, const View3D *v3d)
{
CustomDataMask mask = 0;
if (ELEM(v3d->drawtype, OB_TEXTURE, OB_MATERIAL) ||
((v3d->drawtype == OB_SOLID) && (v3d->flag2 & V3D_SOLID_TEX)))
{
- mask |= CD_MASK_MTFACE | CD_MASK_MCOL;
+ mask |= CD_MASK_MTEXPOLY | CD_MASK_MLOOPUV | CD_MASK_MLOOPCOL;
if (BKE_scene_use_new_shading_nodes(scene)) {
if (v3d->drawtype == OB_MATERIAL)
@@ -2524,8 +2629,10 @@ CustomDataMask ED_view3d_datamask(Scene *scene, View3D *v3d)
}
else {
if ((scene->gm.matmode == GAME_MAT_GLSL && v3d->drawtype == OB_TEXTURE) ||
- (v3d->drawtype == OB_MATERIAL))
+ (v3d->drawtype == OB_MATERIAL))
+ {
mask |= CD_MASK_ORCO;
+ }
}
}
@@ -2533,16 +2640,16 @@ CustomDataMask ED_view3d_datamask(Scene *scene, View3D *v3d)
}
/* goes over all modes and view3d settings */
-CustomDataMask ED_view3d_screen_datamask(bScreen *screen)
+CustomDataMask ED_view3d_screen_datamask(const bScreen *screen)
{
- Scene *scene = screen->scene;
+ const Scene *scene = screen->scene;
CustomDataMask mask = CD_MASK_BAREMESH;
- ScrArea *sa;
+ const ScrArea *sa;
/* check if we need tfaces & mcols due to view mode */
for (sa = screen->areabase.first; sa; sa = sa->next) {
if (sa->spacetype == SPACE_VIEW3D) {
- mask |= ED_view3d_datamask(scene, (View3D *)sa->spacedata.first);
+ mask |= ED_view3d_datamask(scene, sa->spacedata.first);
}
}
@@ -2552,6 +2659,7 @@ CustomDataMask ED_view3d_screen_datamask(bScreen *screen)
void ED_view3d_update_viewmat(Scene *scene, View3D *v3d, ARegion *ar, float viewmat[4][4], float winmat[4][4])
{
RegionView3D *rv3d = ar->regiondata;
+ rctf cameraborder;
/* setup window matrices */
if (winmat)
@@ -2569,7 +2677,23 @@ void ED_view3d_update_viewmat(Scene *scene, View3D *v3d, ARegion *ar, float view
mul_m4_m4m4(rv3d->persmat, rv3d->winmat, rv3d->viewmat);
invert_m4_m4(rv3d->persinv, rv3d->persmat);
invert_m4_m4(rv3d->viewinv, rv3d->viewmat);
+
+ /* calculate GLSL view dependent values */
+ /* store window coordinates scaling/offset */
+ if (rv3d->persp == RV3D_CAMOB && v3d->camera) {
+ ED_view3d_calc_camera_border(scene, ar, v3d, rv3d, &cameraborder, false);
+ rv3d->viewcamtexcofac[0] = (float)ar->winx / BLI_rctf_size_x(&cameraborder);
+ rv3d->viewcamtexcofac[1] = (float)ar->winy / BLI_rctf_size_y(&cameraborder);
+
+ rv3d->viewcamtexcofac[2] = -rv3d->viewcamtexcofac[0] * cameraborder.xmin / (float)ar->winx;
+ rv3d->viewcamtexcofac[3] = -rv3d->viewcamtexcofac[1] * cameraborder.ymin / (float)ar->winy;
+ }
+ else {
+ rv3d->viewcamtexcofac[0] = rv3d->viewcamtexcofac[1] = 1.0f;
+ rv3d->viewcamtexcofac[2] = rv3d->viewcamtexcofac[3] = 0.0f;
+ }
+
/* calculate pixelsize factor once, is used for lamps and obcenters */
{
/* note: '1.0f / len_v3(v1)' replaced 'len_v3(rv3d->viewmat[0])'
@@ -2592,8 +2716,6 @@ void ED_view3d_update_viewmat(Scene *scene, View3D *v3d, ARegion *ar, float view
}
}
-
-
/**
* Shared by #ED_view3d_draw_offscreen and #view3d_main_area_draw_objects
*
@@ -2604,11 +2726,17 @@ static void view3d_draw_objects(
const bContext *C,
Scene *scene, View3D *v3d, ARegion *ar,
const char **grid_unit,
- const bool do_bgpic, const bool draw_offscreen)
+ const bool do_bgpic, const bool draw_offscreen, GPUFX *fx)
{
RegionView3D *rv3d = ar->regiondata;
Base *base;
const bool do_camera_frame = !draw_offscreen;
+ const bool draw_grids = !draw_offscreen && (v3d->flag2 & V3D_RENDER_OVERRIDE) == 0;
+ const bool draw_floor = (rv3d->view == RV3D_VIEW_USER) || (rv3d->persp != RV3D_ORTHO);
+ /* only draw grids after in solid modes, else it hovers over mesh wires */
+ const bool draw_grids_after = draw_grids && draw_floor && (v3d->drawtype > OB_WIRE) && fx;
+ bool do_composite_xray = false;
+ bool xrayclear = true;
if (!draw_offscreen) {
ED_region_draw_cb_draw(C, ar, REGION_DRAW_PRE_VIEW);
@@ -2639,28 +2767,24 @@ static void view3d_draw_objects(
glEnable(GL_DEPTH_TEST);
}
- if (!draw_offscreen) {
+ /* ortho grid goes first, does not write to depth buffer and doesn't need depth test so it will override
+ * objects if done last */
+ if (draw_grids) {
/* needs to be done always, gridview is adjusted in drawgrid() now, but only for ortho views. */
- rv3d->gridview = v3d->grid;
- if (scene->unit.system) {
- rv3d->gridview /= scene->unit.scale_length;
- }
+ rv3d->gridview = ED_view3d_grid_scale(scene, v3d, grid_unit);
- if ((rv3d->view == RV3D_VIEW_USER) || (rv3d->persp != RV3D_ORTHO)) {
- if ((v3d->flag2 & V3D_RENDER_OVERRIDE) == 0) {
- drawfloor(scene, v3d, grid_unit);
- }
+ if (!draw_floor) {
+ ED_region_pixelspace(ar);
+ *grid_unit = NULL; /* drawgrid need this to detect/affect smallest valid unit... */
+ drawgrid(&scene->unit, ar, v3d, grid_unit);
+ /* XXX make function? replaces persp(1) */
+ glMatrixMode(GL_PROJECTION);
+ glLoadMatrixf(rv3d->winmat);
+ glMatrixMode(GL_MODELVIEW);
+ glLoadMatrixf(rv3d->viewmat);
}
- else {
- if ((v3d->flag2 & V3D_RENDER_OVERRIDE) == 0) {
- ED_region_pixelspace(ar);
- drawgrid(&scene->unit, ar, v3d, grid_unit);
- /* XXX make function? replaces persp(1) */
- glMatrixMode(GL_PROJECTION);
- glLoadMatrixf(rv3d->winmat);
- glMatrixMode(GL_MODELVIEW);
- glLoadMatrixf(rv3d->viewmat);
- }
+ else if (!draw_grids_after) {
+ drawfloor(scene, v3d, grid_unit, true);
}
}
@@ -2736,6 +2860,11 @@ static void view3d_draw_objects(
}
}
+ /* perspective floor goes last to use scene depth and avoid writing to depth buffer */
+ if (draw_grids_after) {
+ drawfloor(scene, v3d, grid_unit, false);
+ }
+
/* must be before xray draw which clears the depth buffer */
if (v3d->flag2 & V3D_SHOW_GPENCIL) {
/* must be before xray draw which clears the depth buffer */
@@ -2746,8 +2875,19 @@ static void view3d_draw_objects(
/* transp and X-ray afterdraw stuff */
if (v3d->afterdraw_transp.first) view3d_draw_transp(scene, ar, v3d);
- if (v3d->afterdraw_xray.first) view3d_draw_xray(scene, ar, v3d, true);
- if (v3d->afterdraw_xraytransp.first) view3d_draw_xraytransp(scene, ar, v3d, true);
+
+ /* always do that here to cleanup depth buffers if none needed */
+ if (fx) {
+ do_composite_xray = v3d->zbuf && (v3d->afterdraw_xray.first || v3d->afterdraw_xraytransp.first);
+ GPU_fx_compositor_setup_XRay_pass(fx, do_composite_xray);
+ }
+
+ if (v3d->afterdraw_xray.first) view3d_draw_xray(scene, ar, v3d, &xrayclear);
+ if (v3d->afterdraw_xraytransp.first) view3d_draw_xraytransp(scene, ar, v3d, xrayclear);
+
+ if (fx && do_composite_xray) {
+ GPU_fx_compositor_XRay_resolve(fx);
+ }
if (!draw_offscreen) {
ED_region_draw_cb_draw(C, ar, REGION_DRAW_POST_VIEW);
@@ -2793,18 +2933,240 @@ void ED_view3d_draw_offscreen_init(Scene *scene, View3D *v3d)
{
/* shadow buffers, before we setup matrices */
if (draw_glsl_material(scene, NULL, v3d, v3d->drawtype))
- gpu_update_lamps_shadows(scene, v3d);
+ gpu_update_lamps_shadows_world(scene, v3d);
+}
+
+/*
+ * Function to clear the view
+ */
+static void view3d_main_area_clear(Scene *scene, View3D *v3d, ARegion *ar)
+{
+ if (scene->world && (v3d->flag3 & V3D_SHOW_WORLD)) {
+ bool glsl = GPU_glsl_support() && BKE_scene_use_new_shading_nodes(scene) && scene->world->nodetree && scene->world->use_nodes;
+
+ if (glsl) {
+ RegionView3D *rv3d = ar->regiondata;
+ GPUMaterial *gpumat = GPU_material_world(scene, scene->world);
+ bool material_not_bound;
+
+ /* calculate full shader for background */
+ GPU_material_bind(gpumat, 1, 1, 1.0, false, rv3d->viewmat, rv3d->viewinv, rv3d->viewcamtexcofac, (v3d->scenelock != 0));
+
+ material_not_bound = !GPU_material_bound(gpumat);
+
+ if (material_not_bound) {
+ glMatrixMode(GL_PROJECTION);
+ glPushMatrix();
+ glLoadIdentity();
+ glMatrixMode(GL_MODELVIEW);
+ glPushMatrix();
+ glLoadIdentity();
+ glColor4f(0.0f, 0.0f, 0.0f, 1.0f);
+ }
+
+ glEnable(GL_DEPTH_TEST);
+ glDepthFunc(GL_ALWAYS);
+ glShadeModel(GL_SMOOTH);
+ glBegin(GL_TRIANGLE_STRIP);
+ glVertex3f(-1.0, -1.0, 1.0);
+ glVertex3f(1.0, -1.0, 1.0);
+ glVertex3f(-1.0, 1.0, 1.0);
+ glVertex3f(1.0, 1.0, 1.0);
+ glEnd();
+ glShadeModel(GL_FLAT);
+
+ if (material_not_bound) {
+ glMatrixMode(GL_PROJECTION);
+ glPopMatrix();
+ glMatrixMode(GL_MODELVIEW);
+ glPopMatrix();
+ }
+
+ GPU_material_unbind(gpumat);
+
+ glDepthFunc(GL_LEQUAL);
+ glDisable(GL_DEPTH_TEST);
+ }
+ else if (scene->world->skytype & WO_SKYBLEND) { /* blend sky */
+ int x, y;
+ float col_hor[3];
+ float col_zen[3];
+
+#define VIEWGRAD_RES_X 16
+#define VIEWGRAD_RES_Y 16
+
+ GLubyte grid_col[VIEWGRAD_RES_X][VIEWGRAD_RES_Y][4];
+ static float grid_pos[VIEWGRAD_RES_X][VIEWGRAD_RES_Y][3];
+ static GLushort indices[VIEWGRAD_RES_X - 1][VIEWGRAD_RES_X - 1][4];
+ static bool buf_calculated = false;
+
+ IMB_colormanagement_pixel_to_display_space_v3(col_hor, &scene->world->horr, &scene->view_settings,
+ &scene->display_settings);
+ IMB_colormanagement_pixel_to_display_space_v3(col_zen, &scene->world->zenr, &scene->view_settings,
+ &scene->display_settings);
+
+ glMatrixMode(GL_PROJECTION);
+ glPushMatrix();
+ glLoadIdentity();
+ glMatrixMode(GL_MODELVIEW);
+ glPushMatrix();
+ glLoadIdentity();
+
+ glShadeModel(GL_SMOOTH);
+
+ /* calculate buffers the first time only */
+ if (!buf_calculated) {
+ for (x = 0; x < VIEWGRAD_RES_X; x++) {
+ for (y = 0; y < VIEWGRAD_RES_Y; y++) {
+ const float xf = (float)x / (float)(VIEWGRAD_RES_X - 1);
+ const float yf = (float)y / (float)(VIEWGRAD_RES_Y - 1);
+
+ /* -1..1 range */
+ grid_pos[x][y][0] = (xf - 0.5f) * 2.0f;
+ grid_pos[x][y][1] = (yf - 0.5f) * 2.0f;
+ grid_pos[x][y][2] = 1.0;
+ }
+ }
+
+ for (x = 0; x < VIEWGRAD_RES_X - 1; x++) {
+ for (y = 0; y < VIEWGRAD_RES_Y - 1; y++) {
+ indices[x][y][0] = x * VIEWGRAD_RES_X + y;
+ indices[x][y][1] = x * VIEWGRAD_RES_X + y + 1;
+ indices[x][y][2] = (x + 1) * VIEWGRAD_RES_X + y + 1;
+ indices[x][y][3] = (x + 1) * VIEWGRAD_RES_X + y;
+ }
+ }
+
+ buf_calculated = true;
+ }
+
+ for (x = 0; x < VIEWGRAD_RES_X; x++) {
+ for (y = 0; y < VIEWGRAD_RES_Y; y++) {
+ const float xf = (float)x / (float)(VIEWGRAD_RES_X - 1);
+ const float yf = (float)y / (float)(VIEWGRAD_RES_Y - 1);
+ const float mval[2] = {xf * (float)ar->winx, yf * ar->winy};
+ const float z_up[3] = {0.0f, 0.0f, 1.0f};
+ float out[3];
+ GLubyte *col_ub = grid_col[x][y];
+
+ float col_fac;
+ float col_fl[3];
+
+ ED_view3d_win_to_vector(ar, mval, out);
+
+ if (scene->world->skytype & WO_SKYPAPER) {
+ if (scene->world->skytype & WO_SKYREAL) {
+ col_fac = fabsf(((float)y / (float)VIEWGRAD_RES_Y) - 0.5f) * 2.0f;
+ }
+ else {
+ col_fac = (float)y / (float)VIEWGRAD_RES_Y;
+ }
+ }
+ else {
+ if (scene->world->skytype & WO_SKYREAL) {
+ col_fac = fabsf((angle_normalized_v3v3(z_up, out) / (float)M_PI) - 0.5f) * 2.0f;
+ }
+ else {
+ col_fac = 1.0f - (angle_normalized_v3v3(z_up, out) / (float)M_PI);
+ }
+ }
+
+ interp_v3_v3v3(col_fl, col_hor, col_zen, col_fac);
+
+ rgb_float_to_uchar(col_ub, col_fl);
+ col_ub[3] = 255;
+ }
+ }
+
+ glEnable(GL_DEPTH_TEST);
+ glDepthFunc(GL_ALWAYS);
+
+ glEnableClientState(GL_VERTEX_ARRAY);
+ glEnableClientState(GL_COLOR_ARRAY);
+ glVertexPointer(3, GL_FLOAT, 0, grid_pos);
+ glColorPointer(4, GL_UNSIGNED_BYTE, 0, grid_col);
+
+ glDrawElements(GL_QUADS, (VIEWGRAD_RES_X - 1) * (VIEWGRAD_RES_Y - 1) * 4, GL_UNSIGNED_SHORT, indices);
+
+ glDisableClientState(GL_VERTEX_ARRAY);
+ glDisableClientState(GL_COLOR_ARRAY);
+
+ glDepthFunc(GL_LEQUAL);
+ glDisable(GL_DEPTH_TEST);
+
+ glMatrixMode(GL_PROJECTION);
+ glPopMatrix();
+ glMatrixMode(GL_MODELVIEW);
+ glPopMatrix();
+
+ glShadeModel(GL_FLAT);
+
+#undef VIEWGRAD_RES_X
+#undef VIEWGRAD_RES_Y
+ }
+ else { /* solid sky */
+ float col_hor[3];
+ IMB_colormanagement_pixel_to_display_space_v3(col_hor, &scene->world->horr, &scene->view_settings,
+ &scene->display_settings);
+
+ glClearColor(col_hor[0], col_hor[1], col_hor[2], 1.0);
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+ }
+ }
+ else {
+ if (UI_GetThemeValue(TH_SHOW_BACK_GRAD)) {
+ glMatrixMode(GL_PROJECTION);
+ glPushMatrix();
+ glLoadIdentity();
+ glMatrixMode(GL_MODELVIEW);
+ glPushMatrix();
+ glLoadIdentity();
+
+ glEnable(GL_DEPTH_TEST);
+ glDepthFunc(GL_ALWAYS);
+ glShadeModel(GL_SMOOTH);
+ glBegin(GL_QUADS);
+ UI_ThemeColor(TH_LOW_GRAD);
+ glVertex3f(-1.0, -1.0, 1.0);
+ glVertex3f(1.0, -1.0, 1.0);
+ UI_ThemeColor(TH_HIGH_GRAD);
+ glVertex3f(1.0, 1.0, 1.0);
+ glVertex3f(-1.0, 1.0, 1.0);
+ glEnd();
+ glShadeModel(GL_FLAT);
+
+ glDepthFunc(GL_LEQUAL);
+ glDisable(GL_DEPTH_TEST);
+
+ glMatrixMode(GL_PROJECTION);
+ glPopMatrix();
+
+ glMatrixMode(GL_MODELVIEW);
+ glPopMatrix();
+ }
+ else {
+ UI_ThemeClearColorAlpha(TH_HIGH_GRAD, 1.0f);
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+ }
+ }
}
/* ED_view3d_draw_offscreen_init should be called before this to initialize
* stuff like shadow buffers
*/
-void ED_view3d_draw_offscreen(Scene *scene, View3D *v3d, ARegion *ar, int winx, int winy,
- float viewmat[4][4], float winmat[4][4],
- bool do_bgpic, bool do_sky)
-{
+void ED_view3d_draw_offscreen(
+ Scene *scene, View3D *v3d, ARegion *ar, int winx, int winy,
+ float viewmat[4][4], float winmat[4][4],
+ bool do_bgpic, bool do_sky, bool is_persp,
+ GPUOffScreen *ofs,
+ GPUFX *fx, GPUFXSettings *fx_settings,
+ const char *viewname)
+{
+ struct bThemeState theme_state;
int bwinx, bwiny;
rcti brect;
+ bool do_compositing = false;
+ RegionView3D *rv3d = ar->regiondata;
glPushMatrix();
@@ -2820,7 +3182,7 @@ void ED_view3d_draw_offscreen(Scene *scene, View3D *v3d, ARegion *ar, int winx,
ar->winrct.xmax = winx;
ar->winrct.ymax = winy;
- /* set theme */
+ UI_Theme_Store(&theme_state);
UI_SetTheme(SPACE_VIEW3D, RGN_TYPE_WINDOW);
/* set flags */
@@ -2832,26 +3194,45 @@ void ED_view3d_draw_offscreen(Scene *scene, View3D *v3d, ARegion *ar, int winx,
GPU_free_images_anim();
}
+ /* setup view matrices before fx or unbinding the offscreen buffers will cause issues */
+ if ((viewname != NULL && viewname[0] != '\0') && (viewmat == NULL) && rv3d->persp == RV3D_CAMOB && v3d->camera)
+ view3d_stereo3d_setup_offscreen(scene, v3d, ar, winmat, viewname);
+ else
+ view3d_main_area_setup_view(scene, v3d, ar, viewmat, winmat);
+
+ /* framebuffer fx needed, we need to draw offscreen first */
+ if (v3d->fx_settings.fx_flag && fx) {
+ GPUSSAOSettings *ssao = NULL;
+
+ if (v3d->drawtype < OB_SOLID) {
+ ssao = v3d->fx_settings.ssao;
+ v3d->fx_settings.ssao = NULL;
+ }
+
+ do_compositing = GPU_fx_compositor_initialize_passes(fx, &ar->winrct, NULL, fx_settings);
+
+ if (ssao)
+ v3d->fx_settings.ssao = ssao;
+ }
+
/* clear opengl buffers */
if (do_sky) {
- float sky_color[3];
-
- ED_view3d_offscreen_sky_color_get(scene, sky_color);
- glClearColor(sky_color[0], sky_color[1], sky_color[2], 1.0f);
+ view3d_main_area_clear(scene, v3d, ar);
}
else {
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
}
- glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
-
-
- /* setup view matrices */
- view3d_main_area_setup_view(scene, v3d, ar, viewmat, winmat);
-
-
/* main drawing call */
- view3d_draw_objects(NULL, scene, v3d, ar, NULL, do_bgpic, true);
+ view3d_draw_objects(NULL, scene, v3d, ar, NULL, do_bgpic, true, do_compositing ? fx : NULL);
+
+ /* post process */
+ if (do_compositing) {
+ if (!winmat)
+ is_persp = rv3d->is_persp;
+ GPU_fx_do_composite_pass(fx, winmat, is_persp, scene, ofs);
+ }
if ((v3d->flag2 & V3D_RENDER_SHADOW) == 0) {
/* draw grease-pencil stuff */
@@ -2874,30 +3255,23 @@ void ED_view3d_draw_offscreen(Scene *scene, View3D *v3d, ARegion *ar, int winx,
glPopMatrix();
- /* XXX, without this the sequencer flickers with opengl draw enabled, need to find out why - campbell */
- glColor4ub(255, 255, 255, 255);
+ UI_Theme_Restore(&theme_state);
G.f &= ~G_RENDER_OGL;
}
-/* get a color used for offscreen sky, returns color in sRGB space */
-void ED_view3d_offscreen_sky_color_get(Scene *scene, float sky_color[3])
-{
- if (scene->world)
- linearrgb_to_srgb_v3_v3(sky_color, &scene->world->horr);
- else
- UI_GetThemeColor3fv(TH_BACK, sky_color);
-}
-
/* utility func for ED_view3d_draw_offscreen */
ImBuf *ED_view3d_draw_offscreen_imbuf(Scene *scene, View3D *v3d, ARegion *ar, int sizex, int sizey, unsigned int flag,
- bool draw_background, int alpha_mode, char err_out[256])
+ bool draw_background, int alpha_mode, const char *viewname, char err_out[256])
{
RegionView3D *rv3d = ar->regiondata;
ImBuf *ibuf;
GPUOffScreen *ofs;
- bool draw_sky = (alpha_mode == R_ADDSKY);
-
+ bool draw_sky = (alpha_mode == R_ADDSKY) && v3d && (v3d->flag3 & V3D_SHOW_WORLD);
+
+ if (UNLIKELY(v3d == NULL))
+ return NULL;
+
/* state changes make normal drawing go weird otherwise */
glPushAttrib(GL_LIGHTING_BIT);
@@ -2910,24 +3284,35 @@ ImBuf *ED_view3d_draw_offscreen_imbuf(Scene *scene, View3D *v3d, ARegion *ar, in
ED_view3d_draw_offscreen_init(scene, v3d);
- GPU_offscreen_bind(ofs);
+ GPU_offscreen_bind(ofs, true);
/* render 3d view */
if (rv3d->persp == RV3D_CAMOB && v3d->camera) {
CameraParams params;
+ GPUFXSettings fx_settings = {NULL};
+ Object *camera = BKE_camera_multiview_render(scene, v3d->camera, viewname);
BKE_camera_params_init(&params);
/* fallback for non camera objects */
params.clipsta = v3d->near;
params.clipend = v3d->far;
- BKE_camera_params_from_object(&params, v3d->camera);
+ BKE_camera_params_from_object(&params, camera);
+ BKE_camera_multiview_params(&scene->r, &params, camera, viewname);
BKE_camera_params_compute_viewplane(&params, sizex, sizey, scene->r.xasp, scene->r.yasp);
BKE_camera_params_compute_matrix(&params);
- ED_view3d_draw_offscreen(scene, v3d, ar, sizex, sizey, NULL, params.winmat, draw_background, draw_sky);
+ BKE_camera_to_gpu_dof(camera, &fx_settings);
+
+ ED_view3d_draw_offscreen(
+ scene, v3d, ar, sizex, sizey, NULL, params.winmat,
+ draw_background, draw_sky, !params.is_ortho,
+ ofs, NULL, &fx_settings, viewname);
}
else {
- ED_view3d_draw_offscreen(scene, v3d, ar, sizex, sizey, NULL, NULL, draw_background, draw_sky);
+ ED_view3d_draw_offscreen(
+ scene, v3d, ar, sizex, sizey, NULL, NULL,
+ draw_background, draw_sky, true,
+ ofs, NULL, NULL, viewname);
}
/* read in pixels & stamp */
@@ -2939,20 +3324,21 @@ ImBuf *ED_view3d_draw_offscreen_imbuf(Scene *scene, View3D *v3d, ARegion *ar, in
GPU_offscreen_read_pixels(ofs, GL_UNSIGNED_BYTE, ibuf->rect);
/* unbind */
- GPU_offscreen_unbind(ofs);
+ GPU_offscreen_unbind(ofs, true);
GPU_offscreen_free(ofs);
glPopAttrib();
if (ibuf->rect_float && ibuf->rect)
IMB_rect_from_float(ibuf);
-
+
return ibuf;
}
/* creates own 3d views, used by the sequencer */
ImBuf *ED_view3d_draw_offscreen_imbuf_simple(Scene *scene, Object *camera, int width, int height, unsigned int flag, int drawtype,
- bool use_solid_tex, bool draw_background, int alpha_mode, char err_out[256])
+ bool use_solid_tex, bool use_gpencil, bool draw_background, int alpha_mode,
+ const char *viewname, char err_out[256])
{
View3D v3d = {NULL};
ARegion ar = {NULL};
@@ -2967,6 +3353,9 @@ ImBuf *ED_view3d_draw_offscreen_imbuf_simple(Scene *scene, Object *camera, int w
v3d.lay = scene->lay;
v3d.drawtype = drawtype;
v3d.flag2 = V3D_RENDER_OVERRIDE;
+
+ if (use_gpencil)
+ v3d.flag2 |= V3D_SHOW_GPENCIL;
if (use_solid_tex)
v3d.flag2 |= V3D_SOLID_TEX;
@@ -2979,9 +3368,11 @@ ImBuf *ED_view3d_draw_offscreen_imbuf_simple(Scene *scene, Object *camera, int w
{
CameraParams params;
+ Object *camera = BKE_camera_multiview_render(scene, v3d.camera, viewname);
BKE_camera_params_init(&params);
- BKE_camera_params_from_object(&params, v3d.camera);
+ BKE_camera_params_from_object(&params, camera);
+ BKE_camera_multiview_params(&scene->r, &params, camera, viewname);
BKE_camera_params_compute_viewplane(&params, width, height, scene->r.xasp, scene->r.yasp);
BKE_camera_params_compute_matrix(&params);
@@ -2995,7 +3386,7 @@ ImBuf *ED_view3d_draw_offscreen_imbuf_simple(Scene *scene, Object *camera, int w
invert_m4_m4(rv3d.persinv, rv3d.viewinv);
return ED_view3d_draw_offscreen_imbuf(scene, &v3d, &ar, width, height, flag,
- draw_background, alpha_mode, err_out);
+ draw_background, alpha_mode, viewname, err_out);
// seq_view3d_cb(scene, cfra, render_size, seqrectx, seqrecty);
}
@@ -3197,181 +3588,107 @@ static void view3d_main_area_draw_engine_info(View3D *v3d, RegionView3D *rv3d, A
fill_color[3] = 1.0f;
}
- ED_region_info_draw(ar, rv3d->render_engine->text, 1, fill_color);
+ ED_region_info_draw(ar, rv3d->render_engine->text, fill_color, true);
}
-/*
- * Function to clear the view
- */
-static void view3d_main_area_clear(Scene *scene, View3D *v3d, ARegion *ar)
+static bool view3d_stereo3d_active(const bContext *C, Scene *scene, View3D *v3d, RegionView3D *rv3d)
{
- /* clear background */
- if (scene->world && (v3d->flag2 & V3D_RENDER_OVERRIDE)) { /* clear with solid color */
- if (scene->world->skytype & WO_SKYBLEND) { /* blend sky */
- int x, y;
- float col_hor[3];
- float col_zen[3];
-
-#define VIEWGRAD_RES_X 16
-#define VIEWGRAD_RES_Y 16
-
- GLubyte grid_col[VIEWGRAD_RES_X][VIEWGRAD_RES_Y][4];
- static float grid_pos[VIEWGRAD_RES_X][VIEWGRAD_RES_Y][3];
- static GLushort indices[VIEWGRAD_RES_X - 1][VIEWGRAD_RES_X - 1][4];
- static bool buf_calculated = false;
-
- IMB_colormanagement_pixel_to_display_space_v3(col_hor, &scene->world->horr, &scene->view_settings,
- &scene->display_settings);
- IMB_colormanagement_pixel_to_display_space_v3(col_zen, &scene->world->zenr, &scene->view_settings,
- &scene->display_settings);
-
- glMatrixMode(GL_PROJECTION);
- glPushMatrix();
- glLoadIdentity();
- glMatrixMode(GL_MODELVIEW);
- glPushMatrix();
- glLoadIdentity();
-
- glShadeModel(GL_SMOOTH);
-
- /* calculate buffers the first time only */
- if (!buf_calculated) {
- for (x = 0; x < VIEWGRAD_RES_X; x++) {
- for (y = 0; y < VIEWGRAD_RES_Y; y++) {
- const float xf = (float)x / (float)(VIEWGRAD_RES_X - 1);
- const float yf = (float)y / (float)(VIEWGRAD_RES_Y - 1);
-
- /* -1..1 range */
- grid_pos[x][y][0] = (xf - 0.5f) * 2.0f;
- grid_pos[x][y][1] = (yf - 0.5f) * 2.0f;
- grid_pos[x][y][2] = 1.0;
- }
- }
+ wmWindow *win = CTX_wm_window(C);
- for (x = 0; x < VIEWGRAD_RES_X - 1; x++) {
- for (y = 0; y < VIEWGRAD_RES_Y - 1; y++) {
- indices[x][y][0] = x * VIEWGRAD_RES_X + y;
- indices[x][y][1] = x * VIEWGRAD_RES_X + y + 1;
- indices[x][y][2] = (x + 1) * VIEWGRAD_RES_X + y + 1;
- indices[x][y][3] = (x + 1) * VIEWGRAD_RES_X + y;
- }
- }
+ if ((scene->r.scemode & R_MULTIVIEW) == 0)
+ return false;
- buf_calculated = true;
- }
+ if (WM_stereo3d_enabled(win, true) == false)
+ return false;
- for (x = 0; x < VIEWGRAD_RES_X; x++) {
- for (y = 0; y < VIEWGRAD_RES_Y; y++) {
- const float xf = (float)x / (float)(VIEWGRAD_RES_X - 1);
- const float yf = (float)y / (float)(VIEWGRAD_RES_Y - 1);
- const float mval[2] = {xf * (float)ar->winx, yf * ar->winy};
- const float z_up[3] = {0.0f, 0.0f, 1.0f};
- float out[3];
- GLubyte *col_ub = grid_col[x][y];
+ if ((v3d->camera == NULL) || (v3d->camera->type != OB_CAMERA) || rv3d->persp != RV3D_CAMOB)
+ return false;
- float col_fac;
- float col_fl[3];
+ if (scene->r.views_format & SCE_VIEWS_FORMAT_MULTIVIEW) {
+ if (v3d->stereo3d_camera == STEREO_MONO_ID)
+ return false;
- ED_view3d_win_to_vector(ar, mval, out);
+ return BKE_scene_multiview_is_stereo3d(&scene->r);
+ }
- if (scene->world->skytype & WO_SKYPAPER) {
- if (scene->world->skytype & WO_SKYREAL) {
- col_fac = fabsf(((float)y / (float)VIEWGRAD_RES_Y) - 0.5f) * 2.0f;
- }
- else {
- col_fac = (float)y / (float)VIEWGRAD_RES_Y;
- }
- }
- else {
- if (scene->world->skytype & WO_SKYREAL) {
- col_fac = fabsf((angle_normalized_v3v3(z_up, out) / (float)M_PI) - 0.5f) * 2.0f;
- }
- else {
- col_fac = 1.0f - (angle_normalized_v3v3(z_up, out) / (float)M_PI);
- }
- }
+ return true;
+}
- interp_v3_v3v3(col_fl, col_hor, col_zen, col_fac);
+/* setup the view and win matrices for the multiview cameras
+ *
+ * unlike view3d_stereo3d_setup_offscreen, when view3d_stereo3d_setup is called
+ * we have no winmatrix (i.e., projection matrix) defined at that time.
+ * Since the camera and the camera shift are needed for the winmat calculation
+ * we do a small hack to replace it temporarily so we don't need to change the
+ * view3d)main_area_setup_view() code to account for that.
+ */
+static void view3d_stereo3d_setup(Scene *scene, View3D *v3d, ARegion *ar)
+{
+ bool is_left;
+ const char *names[2] = {STEREO_LEFT_NAME, STEREO_RIGHT_NAME};
+ const char *viewname;
- rgb_float_to_uchar(col_ub, col_fl);
- col_ub[3] = 0;
- }
- }
+ /* show only left or right camera */
+ if (v3d->stereo3d_camera != STEREO_3D_ID)
+ v3d->multiview_eye = v3d->stereo3d_camera;
- glEnable(GL_DEPTH_TEST);
- glDepthFunc(GL_ALWAYS);
+ is_left = v3d->multiview_eye == STEREO_LEFT_ID;
+ viewname = names[is_left ? STEREO_LEFT_ID : STEREO_RIGHT_ID];
- glEnableClientState(GL_VERTEX_ARRAY);
- glEnableClientState(GL_COLOR_ARRAY);
- glVertexPointer(3, GL_FLOAT, 0, grid_pos);
- glColorPointer(4, GL_UNSIGNED_BYTE, 0, grid_col);
+ /* update the viewport matrices with the new camera */
+ if (scene->r.views_format == SCE_VIEWS_FORMAT_STEREO_3D) {
+ Camera *data;
+ float viewmat[4][4];
+ float shiftx;
- glDrawElements(GL_QUADS, (VIEWGRAD_RES_X - 1) * (VIEWGRAD_RES_Y - 1) * 4, GL_UNSIGNED_SHORT, indices);
+ data = (Camera *)v3d->camera->data;
+ shiftx = data->shiftx;
- glDisableClientState(GL_VERTEX_ARRAY);
- glDisableClientState(GL_COLOR_ARRAY);
+ BLI_lock_thread(LOCK_VIEW3D);
+ data->shiftx = BKE_camera_multiview_shift_x(&scene->r, v3d->camera, viewname);
- glDepthFunc(GL_LEQUAL);
- glDisable(GL_DEPTH_TEST);
+ BKE_camera_multiview_view_matrix(&scene->r, v3d->camera, is_left, viewmat);
+ view3d_main_area_setup_view(scene, v3d, ar, viewmat, NULL);
- glMatrixMode(GL_PROJECTION);
- glPopMatrix();
- glMatrixMode(GL_MODELVIEW);
- glPopMatrix();
+ data->shiftx = shiftx;
+ BLI_unlock_thread(LOCK_VIEW3D);
+ }
+ else { /* SCE_VIEWS_FORMAT_MULTIVIEW */
+ float viewmat[4][4];
+ Object *view_ob = v3d->camera;
+ Object *camera = BKE_camera_multiview_render(scene, v3d->camera, viewname);
- glShadeModel(GL_FLAT);
+ BLI_lock_thread(LOCK_VIEW3D);
+ v3d->camera = camera;
-#undef VIEWGRAD_RES_X
-#undef VIEWGRAD_RES_Y
- }
- else { /* solid sky */
- float col_hor[3];
- IMB_colormanagement_pixel_to_display_space_v3(col_hor, &scene->world->horr, &scene->view_settings,
- &scene->display_settings);
+ BKE_camera_multiview_view_matrix(&scene->r, camera, false, viewmat);
+ view3d_main_area_setup_view(scene, v3d, ar, viewmat, NULL);
- glClearColor(col_hor[0], col_hor[1], col_hor[2], 0.0f);
- glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
- }
+ v3d->camera = view_ob;
+ BLI_unlock_thread(LOCK_VIEW3D);
}
- else {
- if (UI_GetThemeValue(TH_SHOW_BACK_GRAD)) {
- glMatrixMode(GL_PROJECTION);
- glPushMatrix();
- glLoadIdentity();
- glMatrixMode(GL_MODELVIEW);
- glPushMatrix();
- glLoadIdentity();
-
- glEnable(GL_DEPTH_TEST);
- glDepthFunc(GL_ALWAYS);
- glShadeModel(GL_SMOOTH);
- glBegin(GL_QUADS);
- UI_ThemeColor(TH_LOW_GRAD);
- glVertex3f(-1.0, -1.0, 1.0);
- glVertex3f(1.0, -1.0, 1.0);
- UI_ThemeColor(TH_HIGH_GRAD);
- glVertex3f(1.0, 1.0, 1.0);
- glVertex3f(-1.0, 1.0, 1.0);
- glEnd();
- glShadeModel(GL_FLAT);
+}
- glDepthFunc(GL_LEQUAL);
- glDisable(GL_DEPTH_TEST);
+static void view3d_stereo3d_setup_offscreen(Scene *scene, View3D *v3d, ARegion *ar,
+ float winmat[4][4], const char *viewname)
+{
+ /* update the viewport matrices with the new camera */
+ if (scene->r.views_format == SCE_VIEWS_FORMAT_STEREO_3D) {
+ float viewmat[4][4];
+ const bool is_left = STREQ(viewname, STEREO_LEFT_NAME);
- glMatrixMode(GL_PROJECTION);
- glPopMatrix();
+ BKE_camera_multiview_view_matrix(&scene->r, v3d->camera, is_left, viewmat);
+ view3d_main_area_setup_view(scene, v3d, ar, viewmat, winmat);
+ }
+ else { /* SCE_VIEWS_FORMAT_MULTIVIEW */
+ float viewmat[4][4];
+ Object *camera = BKE_camera_multiview_render(scene, v3d->camera, viewname);
- glMatrixMode(GL_MODELVIEW);
- glPopMatrix();
- }
- else {
- UI_ThemeClearColor(TH_HIGH_GRAD);
- glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
- }
+ BKE_camera_multiview_view_matrix(&scene->r, camera, false, viewmat);
+ view3d_main_area_setup_view(scene, v3d, ar, viewmat, winmat);
}
}
-
#ifdef WITH_GAMEENGINE
static void update_lods(Scene *scene, float camera_pos[3])
{
@@ -3386,29 +3703,34 @@ static void update_lods(Scene *scene, float camera_pos[3])
}
#endif
-
static void view3d_main_area_draw_objects(const bContext *C, Scene *scene, View3D *v3d,
ARegion *ar, const char **grid_unit)
{
RegionView3D *rv3d = ar->regiondata;
unsigned int lay_used = v3d->lay_used;
-
+
+ /* post processing */
+ bool do_compositing = false;
+
/* shadow buffers, before we setup matrices */
if (draw_glsl_material(scene, NULL, v3d, v3d->drawtype))
- gpu_update_lamps_shadows(scene, v3d);
-
+ gpu_update_lamps_shadows_world(scene, v3d);
+
/* reset default OpenGL lights if needed (i.e. after preferences have been altered) */
if (rv3d->rflag & RV3D_GPULIGHT_UPDATE) {
rv3d->rflag &= ~RV3D_GPULIGHT_UPDATE;
GPU_default_lights();
}
- /* setup view matrices */
- view3d_main_area_setup_view(scene, v3d, ar, NULL, NULL);
+ /* setup the view matrix */
+ if (view3d_stereo3d_active(C, scene, v3d, rv3d))
+ view3d_stereo3d_setup(scene, v3d, ar);
+ else
+ view3d_main_area_setup_view(scene, v3d, ar, NULL, NULL);
rv3d->rflag &= ~RV3D_IS_GAME_ENGINE;
#ifdef WITH_GAMEENGINE
- if (STREQ(scene->r.engine, "BLENDER_GAME")) {
+ if (STREQ(scene->r.engine, RE_engine_id_BLENDER_GAME)) {
rv3d->rflag |= RV3D_IS_GAME_ENGINE;
/* Make sure LoDs are up to date */
@@ -3416,6 +3738,23 @@ static void view3d_main_area_draw_objects(const bContext *C, Scene *scene, View3
}
#endif
+ /* framebuffer fx needed, we need to draw offscreen first */
+ if (v3d->fx_settings.fx_flag && v3d->drawtype >= OB_SOLID) {
+ GPUFXSettings fx_settings;
+ BKE_screen_gpu_fx_validate(&v3d->fx_settings);
+ fx_settings = v3d->fx_settings;
+ if (!rv3d->compositor)
+ rv3d->compositor = GPU_fx_compositor_create();
+
+ if (rv3d->persp == RV3D_CAMOB && v3d->camera)
+ BKE_camera_to_gpu_dof(v3d->camera, &fx_settings);
+ else {
+ fx_settings.dof = NULL;
+ }
+
+ do_compositing = GPU_fx_compositor_initialize_passes(rv3d->compositor, &ar->winrct, &ar->drawrct, &fx_settings);
+ }
+
/* clear the background */
view3d_main_area_clear(scene, v3d, ar);
@@ -3425,7 +3764,12 @@ static void view3d_main_area_draw_objects(const bContext *C, Scene *scene, View3
}
/* main drawing call */
- view3d_draw_objects(C, scene, v3d, ar, grid_unit, true, false);
+ view3d_draw_objects(C, scene, v3d, ar, grid_unit, true, false, do_compositing ? rv3d->compositor : NULL);
+
+ /* post process */
+ if (do_compositing) {
+ GPU_fx_do_composite_pass(rv3d->compositor, rv3d->winmat, rv3d->is_persp, scene, NULL);
+ }
/* Disable back anti-aliasing */
if (U.ogl_multisamples != USER_MULTISAMPLE_NONE) {
@@ -3449,6 +3793,36 @@ static void view3d_main_area_draw_objects(const bContext *C, Scene *scene, View3
}
+static bool is_cursor_visible(Scene *scene)
+{
+ Object *ob = OBACT;
+
+ /* don't draw cursor in paint modes, but with a few exceptions */
+ if (ob && ob->mode & OB_MODE_ALL_PAINT) {
+ /* exception: object is in weight paint and has deforming armature in pose mode */
+ if (ob->mode & OB_MODE_WEIGHT_PAINT) {
+ if (BKE_object_pose_armature_get(ob) != NULL) {
+ return true;
+ }
+ }
+ /* exception: object in texture paint mode, clone brush, use_clone_layer disabled */
+ else if (ob->mode & OB_MODE_TEXTURE_PAINT) {
+ const Paint *p = BKE_paint_get_active(scene);
+
+ if (p && p->brush && p->brush->imagepaint_tool == PAINT_TOOL_CLONE) {
+ if ((scene->toolsettings->imapaint.flag & IMAGEPAINT_PROJECT_LAYER_CLONE) == 0) {
+ return true;
+ }
+ }
+ }
+
+ /* no exception met? then don't draw cursor! */
+ return false;
+ }
+
+ return true;
+}
+
static void view3d_main_area_draw_info(const bContext *C, Scene *scene,
ARegion *ar, View3D *v3d,
const char *grid_unit, bool render_border)
@@ -3482,7 +3856,10 @@ static void view3d_main_area_draw_info(const bContext *C, Scene *scene,
if ((v3d->flag2 & V3D_RENDER_OVERRIDE) == 0) {
Object *ob;
- drawcursor(scene, ar, v3d);
+ /* 3d cursor */
+ if (is_cursor_visible(scene)) {
+ drawcursor(scene, ar, v3d);
+ }
if (U.uiflag & USER_SHOW_ROTVIEWICON)
draw_view_axis(rv3d, &rect);
@@ -3502,7 +3879,7 @@ static void view3d_main_area_draw_info(const bContext *C, Scene *scene,
if ((v3d->flag2 & V3D_RENDER_OVERRIDE) == 0) {
wmWindowManager *wm = CTX_wm_manager(C);
- if ((U.uiflag & USER_SHOW_FPS) && ED_screen_animation_playing(wm)) {
+ if ((U.uiflag & USER_SHOW_FPS) && ED_screen_animation_no_scrub(wm)) {
ED_scene_draw_fps(scene, &rect);
}
else if (U.uiflag & USER_SHOW_VIEWPORTNAME) {
@@ -3540,9 +3917,13 @@ void view3d_main_area_draw(const bContext *C, ARegion *ar)
/* draw viewport using opengl */
if (v3d->drawtype != OB_RENDER || !view3d_main_area_do_render_draw(scene) || clip_border) {
view3d_main_area_draw_objects(C, scene, v3d, ar, &grid_unit);
+
#ifdef DEBUG_DRAW
bl_debug_draw();
#endif
+ if (G.debug & G_DEBUG_SIMDATA)
+ draw_sim_debug_data(scene, v3d, ar);
+
ED_region_pixelspace(ar);
}
diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c
index cff6761d628..2295986faf0 100644
--- a/source/blender/editors/space_view3d/view3d_edit.c
+++ b/source/blender/editors/space_view3d/view3d_edit.c
@@ -28,7 +28,6 @@
* \ingroup spview3d
*/
-
#include <string.h>
#include <stdio.h>
#include <math.h>
@@ -38,7 +37,6 @@
#include "DNA_curve_types.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
-#include "DNA_camera_types.h"
#include "MEM_guardedalloc.h"
@@ -46,10 +44,10 @@
#include "BLI_math.h"
#include "BLI_utildefines.h"
+#include "BKE_armature.h"
#include "BKE_camera.h"
#include "BKE_context.h"
#include "BKE_font.h"
-#include "BKE_image.h"
#include "BKE_library.h"
#include "BKE_object.h"
#include "BKE_paint.h"
@@ -76,7 +74,6 @@
#include "ED_transform.h"
#include "ED_mesh.h"
#include "ED_view3d.h"
-#include "ED_sculpt.h"
#include "UI_resources.h"
@@ -84,7 +81,7 @@
#include "view3d_intern.h" /* own include */
-bool ED_view3d_offset_lock_check(struct View3D *v3d, struct RegionView3D *rv3d)
+bool ED_view3d_offset_lock_check(const View3D *v3d, const RegionView3D *rv3d)
{
return (rv3d->persp != RV3D_CAMOB) && (v3d->ob_centre_cursor || v3d->ob_centre);
}
@@ -104,7 +101,10 @@ static bool view3d_operator_offset_lock_check(bContext *C, wmOperator *op)
/* ********************** view3d_edit: view manipulations ********************* */
-bool ED_view3d_camera_lock_check(View3D *v3d, RegionView3D *rv3d)
+/**
+ * \return true when the view-port is locked to its camera.
+ */
+bool ED_view3d_camera_lock_check(const View3D *v3d, const RegionView3D *rv3d)
{
return ((v3d->camera) &&
(v3d->camera->id.lib == NULL) &&
@@ -112,6 +112,10 @@ bool ED_view3d_camera_lock_check(View3D *v3d, RegionView3D *rv3d)
(rv3d->persp == RV3D_CAMOB));
}
+/**
+ * Apply the camera object transformation to the view-port.
+ * (needed so we can use regular view-port manipulation operators, that sync back to the camera).
+ */
void ED_view3d_camera_lock_init_ex(View3D *v3d, RegionView3D *rv3d, const bool calc_dist)
{
if (ED_view3d_camera_lock_check(v3d, rv3d)) {
@@ -128,7 +132,11 @@ void ED_view3d_camera_lock_init(View3D *v3d, RegionView3D *rv3d)
ED_view3d_camera_lock_init_ex(v3d, rv3d, true);
}
-/* return true if the camera is moved */
+/**
+ * Apply the view-port transformation back to the camera object.
+ *
+ * \return true if the camera is moved.
+ */
bool ED_view3d_camera_lock_sync(View3D *v3d, RegionView3D *rv3d)
{
if (ED_view3d_camera_lock_check(v3d, rv3d)) {
@@ -190,6 +198,7 @@ bool ED_view3d_camera_autokey(
struct bContext *C, const bool do_rotate, const bool do_translate)
{
if (autokeyframe_cfra_can_key(scene, id_key)) {
+ const float cfra = (float)CFRA;
ListBase dsources = {NULL, NULL};
/* add data-source override for the camera object */
@@ -201,12 +210,12 @@ bool ED_view3d_camera_autokey(
* 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);
+ struct KeyingSet *ks = ANIM_get_keyingset_for_autokeying(scene, ANIM_KS_ROTATION_ID);
+ ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, 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);
+ struct KeyingSet *ks = ANIM_get_keyingset_for_autokeying(scene, ANIM_KS_LOCATION_ID);
+ ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, cfra);
}
/* free temp data */
@@ -520,6 +529,7 @@ void ED_view3d_quadview_update(ScrArea *sa, ARegion *ar, bool do_clip)
typedef struct ViewOpsData {
/* context pointers (assigned by viewops_data_alloc) */
+ Scene *scene;
ScrArea *sa;
ARegion *ar;
View3D *v3d;
@@ -592,6 +602,7 @@ static void viewops_data_alloc(bContext *C, wmOperator *op)
/* store data */
op->customdata = vod;
+ vod->scene = CTX_data_scene(C);
vod->sa = CTX_wm_area(C);
vod->ar = CTX_wm_region(C);
vod->v3d = vod->sa->spacedata.first;
@@ -621,14 +632,17 @@ static bool view3d_orbit_calc_center(bContext *C, float r_dyn_ofs[3])
Scene *scene = CTX_data_scene(C);
Object *ob = OBACT;
- if (ob && (ob->mode & OB_MODE_ALL_PAINT) && (BKE_object_pose_armature_get(ob) == NULL)) {
+ if (ob && (ob->mode & OB_MODE_ALL_PAINT) &&
+ /* with weight-paint + pose-mode, fall through to using calculateTransformCenter */
+ ((ob->mode & OB_MODE_WEIGHT_PAINT) && BKE_object_pose_armature_get(ob)) == 0)
+ {
/* in case of sculpting use last average stroke position as a rotation
* center, in other cases it's not clear what rotation center shall be
* so just rotate around object origin
*/
- if (ob->mode & OB_MODE_SCULPT) {
+ if (ob->mode & (OB_MODE_SCULPT | OB_MODE_TEXTURE_PAINT)) {
float stroke[3];
- ED_sculpt_stroke_get_average(ob, stroke);
+ BKE_paint_stroke_get_average(scene, ob, stroke);
copy_v3_v3(lastofs, stroke);
}
else {
@@ -1035,7 +1049,7 @@ static void viewrotate_apply(ViewOpsData *vod, int x, int y)
* - of rotation is linearly proportional
* - to the distance that the mouse is
* - dragged. */
- phi = si * (float)(M_PI / 2.0);
+ phi = si * (float)M_PI_2;
q1[0] = cosf(phi);
mul_v3_fl(q1 + 1, sinf(phi));
@@ -1119,6 +1133,8 @@ static int viewrotate_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
ViewOpsData *vod = op->customdata;
short event_code = VIEW_PASS;
+ bool use_autokey = false;
+ int ret = OPERATOR_RUNNING_MODAL;
/* execute the events */
if (event->type == MOUSEMOVE) {
@@ -1153,17 +1169,25 @@ static int viewrotate_modal(bContext *C, wmOperator *op, const wmEvent *event)
if (event_code == VIEW_APPLY) {
viewrotate_apply(vod, event->x, event->y);
+ if (ED_screen_animation_playing(CTX_wm_manager(C))) {
+ use_autokey = true;
+ }
}
else if (event_code == VIEW_CONFIRM) {
- ED_view3d_camera_lock_autokey(vod->v3d, vod->rv3d, C, true, true);
ED_view3d_depth_tag_update(vod->rv3d);
+ use_autokey = true;
+ ret = OPERATOR_FINISHED;
+ }
- viewops_data_free(C, op);
+ if (use_autokey) {
+ ED_view3d_camera_lock_autokey(vod->v3d, vod->rv3d, C, true, true);
+ }
- return OPERATOR_FINISHED;
+ if (ret & OPERATOR_FINISHED) {
+ viewops_data_free(C, op);
}
- return OPERATOR_RUNNING_MODAL;
+ return ret;
}
/**
@@ -1221,26 +1245,31 @@ static int viewrotate_invoke(bContext *C, wmOperator *op, const wmEvent *event)
ED_region_tag_redraw(vod->ar);
}
- if (event->type == MOUSEPAN) {
+ if (ELEM(event->type, MOUSEPAN, MOUSEROTATE)) {
/* Rotate direction we keep always same */
- if (U.uiflag2 & USER_TRACKPAD_NATURAL)
- viewrotate_apply(vod, 2 * event->x - event->prevx, 2 * event->y - event->prevy);
- else
- viewrotate_apply(vod, event->prevx, event->prevy);
-
- ED_view3d_depth_tag_update(vod->rv3d);
-
- viewops_data_free(C, op);
-
- return OPERATOR_FINISHED;
- }
- else if (event->type == MOUSEROTATE) {
- /* MOUSEROTATE performs orbital rotation, so y axis delta is set to 0 */
- viewrotate_apply(vod, event->prevx, event->y);
+ int x, y;
+
+ if (event->type == MOUSEPAN) {
+ if (U.uiflag2 & USER_TRACKPAD_NATURAL) {
+ x = 2 * event->x - event->prevx;
+ y = 2 * event->y - event->prevy;
+ }
+ else {
+ x = event->prevx;
+ y = event->prevy;
+ }
+ }
+ else {
+ /* MOUSEROTATE performs orbital rotation, so y axis delta is set to 0 */
+ x = event->prevx;
+ y = event->y;
+ }
+
+ viewrotate_apply(vod, x, y);
ED_view3d_depth_tag_update(vod->rv3d);
-
+
viewops_data_free(C, op);
-
+
return OPERATOR_FINISHED;
}
else {
@@ -1298,7 +1327,7 @@ void VIEW3D_OT_rotate(wmOperatorType *ot)
ot->cancel = viewrotate_cancel;
/* flags */
- ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_POINTER;
+ ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_CURSOR;
}
/** \name NDOF Utility Functions
@@ -1912,7 +1941,7 @@ static void viewmove_apply(ViewOpsData *vod, int x, int y)
vod->rv3d->ofs_lock[1] -= ((vod->oldy - y) * 2.0f) / (float)vod->ar->winy;
}
else if ((vod->rv3d->persp == RV3D_CAMOB) && !ED_view3d_camera_lock_check(vod->v3d, vod->rv3d)) {
- const float zoomfac = BKE_screen_view3d_zoom_to_fac((float)vod->rv3d->camzoom) * 2.0f;
+ const float zoomfac = BKE_screen_view3d_zoom_to_fac(vod->rv3d->camzoom) * 2.0f;
vod->rv3d->camdx += (vod->oldx - x) / (vod->ar->winx * zoomfac);
vod->rv3d->camdy += (vod->oldy - y) / (vod->ar->winy * zoomfac);
CLAMP(vod->rv3d->camdx, -1.0f, 1.0f);
@@ -1946,6 +1975,8 @@ static int viewmove_modal(bContext *C, wmOperator *op, const wmEvent *event)
ViewOpsData *vod = op->customdata;
short event_code = VIEW_PASS;
+ bool use_autokey = false;
+ int ret = OPERATOR_RUNNING_MODAL;
/* execute the events */
if (event->type == MOUSEMOVE) {
@@ -1972,17 +2003,25 @@ static int viewmove_modal(bContext *C, wmOperator *op, const wmEvent *event)
if (event_code == VIEW_APPLY) {
viewmove_apply(vod, event->x, event->y);
+ if (ED_screen_animation_playing(CTX_wm_manager(C))) {
+ use_autokey = true;
+ }
}
else if (event_code == VIEW_CONFIRM) {
- ED_view3d_camera_lock_autokey(vod->v3d, vod->rv3d, C, false, true);
ED_view3d_depth_tag_update(vod->rv3d);
+ use_autokey = true;
+ ret = OPERATOR_FINISHED;
+ }
- viewops_data_free(C, op);
+ if (use_autokey) {
+ ED_view3d_camera_lock_autokey(vod->v3d, vod->rv3d, C, false, true);
+ }
- return OPERATOR_FINISHED;
+ if (ret & OPERATOR_FINISHED) {
+ viewops_data_free(C, op);
}
- return OPERATOR_RUNNING_MODAL;
+ return ret;
}
static int viewmove_invoke(bContext *C, wmOperator *op, const wmEvent *event)
@@ -2031,7 +2070,7 @@ void VIEW3D_OT_move(wmOperatorType *ot)
ot->cancel = viewmove_cancel;
/* flags */
- ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_POINTER;
+ ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_CURSOR;
}
/* ************************ viewzoom ******************************** */
@@ -2071,16 +2110,63 @@ void viewzoom_modal_keymap(wmKeyConfig *keyconf)
WM_modalkeymap_assign(keymap, "VIEW3D_OT_zoom");
}
-static void view_zoom_mouseloc(ARegion *ar, float dfac, int mx, int my)
+static void view_zoom_mouseloc_camera(
+ Scene *scene, View3D *v3d,
+ ARegion *ar, float dfac, int mx, int my)
{
RegionView3D *rv3d = ar->regiondata;
+ const float zoomfac = BKE_screen_view3d_zoom_to_fac(rv3d->camzoom);
+ const float zoomfac_new = CLAMPIS(zoomfac * (1.0f / dfac), RV3D_CAMZOOM_MIN_FACTOR, RV3D_CAMZOOM_MAX_FACTOR);
+ const float camzoom_new = BKE_screen_view3d_zoom_from_fac(zoomfac_new);
+
+
+ if (U.uiflag & USER_ZOOM_TO_MOUSEPOS) {
+ float zoomfac_px;
+ rctf camera_frame_old;
+ rctf camera_frame_new;
+
+ const float pt_src[2] = {mx, my};
+ float pt_dst[2];
+ float delta_px[2];
+
+ ED_view3d_calc_camera_border(scene, ar, v3d, rv3d, &camera_frame_old, false);
+ BLI_rctf_translate(&camera_frame_old, ar->winrct.xmin, ar->winrct.ymin);
+
+ rv3d->camzoom = camzoom_new;
+ CLAMP(rv3d->camzoom, RV3D_CAMZOOM_MIN, RV3D_CAMZOOM_MAX);
+
+ ED_view3d_calc_camera_border(scene, ar, v3d, rv3d, &camera_frame_new, false);
+ BLI_rctf_translate(&camera_frame_new, ar->winrct.xmin, ar->winrct.ymin);
+
+ BLI_rctf_transform_pt_v(&camera_frame_new, &camera_frame_old, pt_dst, pt_src);
+ sub_v2_v2v2(delta_px, pt_dst, pt_src);
+
+ /* translate the camera offset using pixel space delta
+ * mapped back to the camera (same logic as panning in camera view) */
+ zoomfac_px = BKE_screen_view3d_zoom_to_fac(rv3d->camzoom) * 2.0f;
+
+ rv3d->camdx += delta_px[0] / (ar->winx * zoomfac_px);
+ rv3d->camdy += delta_px[1] / (ar->winy * zoomfac_px);
+ CLAMP(rv3d->camdx, -1.0f, 1.0f);
+ CLAMP(rv3d->camdy, -1.0f, 1.0f);
+ }
+ else {
+ rv3d->camzoom = camzoom_new;
+ CLAMP(rv3d->camzoom, RV3D_CAMZOOM_MIN, RV3D_CAMZOOM_MAX);
+ }
+}
+
+static void view_zoom_mouseloc_3d(ARegion *ar, float dfac, int mx, int my)
+{
+ RegionView3D *rv3d = ar->regiondata;
+ const float dist_new = rv3d->dist * dfac;
if (U.uiflag & USER_ZOOM_TO_MOUSEPOS) {
float dvec[3];
float tvec[3];
float tpos[3];
float mval_f[2];
- float new_dist;
+
float zfac;
negate_v3_v3(tpos, rv3d->ofs);
@@ -2097,105 +2183,133 @@ static void view_zoom_mouseloc(ARegion *ar, float dfac, int mx, int my)
negate_v3(tvec);
/* Offset to target position and dolly */
- new_dist = rv3d->dist * dfac;
-
copy_v3_v3(rv3d->ofs, tvec);
- rv3d->dist = new_dist;
+ rv3d->dist = dist_new;
/* Calculate final offset */
madd_v3_v3v3fl(rv3d->ofs, tvec, dvec, dfac);
}
else {
- rv3d->dist *= dfac;
+ rv3d->dist = dist_new;
}
}
-
-static void viewzoom_apply(ViewOpsData *vod, const int xy[2], const short viewzoom, const short zoom_invert)
+static float viewzoom_scale_value(
+ const rcti *winrct,
+ const short viewzoom,
+ const bool zoom_invert, const bool zoom_invert_force,
+ const int xy[2], const int xy_orig[2],
+ const float val, const float val_orig,
+ double *r_timer_lastdraw)
{
- float zfac = 1.0;
- bool use_cam_zoom;
- float dist_range[2];
-
- use_cam_zoom = (vod->rv3d->persp == RV3D_CAMOB) && !(vod->rv3d->is_persp && ED_view3d_camera_lock_check(vod->v3d, vod->rv3d));
-
- ED_view3d_dist_range_get(vod->v3d, dist_range);
-
- if (use_cam_zoom) {
- float delta;
- delta = (xy[0] - vod->origx + xy[1] - vod->origy) / 10.0f;
- vod->rv3d->camzoom = vod->camzoom_prev + (zoom_invert ? -delta : delta);
-
- CLAMP(vod->rv3d->camzoom, RV3D_CAMZOOM_MIN, RV3D_CAMZOOM_MAX);
- }
+ float zfac;
if (viewzoom == USER_ZOOM_CONT) {
double time = PIL_check_seconds_timer();
- float time_step = (float)(time - vod->timer_lastdraw);
+ float time_step = (float)(time - *r_timer_lastdraw);
float fac;
if (U.uiflag & USER_ZOOM_HORIZ) {
- fac = (float)(vod->origx - xy[0]);
+ fac = (float)(xy_orig[0] - xy[0]);
}
else {
- fac = (float)(vod->origy - xy[1]);
+ fac = (float)(xy_orig[1] - xy[1]);
}
- if (zoom_invert) {
+ if (zoom_invert != zoom_invert_force) {
fac = -fac;
}
/* oldstyle zoom */
zfac = 1.0f + ((fac / 20.0f) * time_step);
- vod->timer_lastdraw = time;
+ *r_timer_lastdraw = time;
}
else if (viewzoom == USER_ZOOM_SCALE) {
/* method which zooms based on how far you move the mouse */
const int ctr[2] = {
- BLI_rcti_cent_x(&vod->ar->winrct),
- BLI_rcti_cent_y(&vod->ar->winrct),
+ BLI_rcti_cent_x(winrct),
+ BLI_rcti_cent_y(winrct),
};
- const float len_new = 5 + len_v2v2_int(ctr, xy);
- const float len_old = 5 + len_v2v2_int(ctr, &vod->origx);
- zfac = vod->dist_prev * ((len_old + 5) / (len_new + 5)) / vod->rv3d->dist;
+ float len_new = 5 + len_v2v2_int(ctr, xy);
+ float len_old = 5 + len_v2v2_int(ctr, xy_orig);
+
+ /* intentionally ignore 'zoom_invert' for scale */
+ if (zoom_invert_force) {
+ SWAP(float, len_new, len_old);
+ }
+
+ zfac = val_orig * (len_old / max_ff(len_new, 1.0f)) / val;
}
else { /* USER_ZOOM_DOLLY */
- float len1, len2;
-
+ float len_new = 5;
+ float len_old = 5;
+
if (U.uiflag & USER_ZOOM_HORIZ) {
- len1 = (vod->ar->winrct.xmax - xy[0]) + 5;
- len2 = (vod->ar->winrct.xmax - vod->origx) + 5;
+ len_new += (winrct->xmax - xy[0]);
+ len_old += (winrct->xmax - xy_orig[0]);
}
else {
- len1 = (vod->ar->winrct.ymax - xy[1]) + 5;
- len2 = (vod->ar->winrct.ymax - vod->origy) + 5;
+ len_new += (winrct->ymax - xy[1]);
+ len_old += (winrct->ymax - xy_orig[1]);
}
- if (zoom_invert) {
- SWAP(float, len1, len2);
- }
-
- if (use_cam_zoom) {
- /* zfac is ignored in this case, see below */
-#if 0
- zfac = vod->camzoom_prev * (2.0f * ((len1 / len2) - 1.0f) + 1.0f) / vod->rv3d->camzoom;
-#endif
- }
- else {
- zfac = vod->dist_prev * (2.0f * ((len1 / len2) - 1.0f) + 1.0f) / vod->rv3d->dist;
+
+ if (zoom_invert != zoom_invert_force) {
+ SWAP(float, len_new, len_old);
}
+
+ zfac = val_orig * (2.0f * ((len_new / max_ff(len_old, 1.0f)) - 1.0f) + 1.0f) / val;
}
- if (!use_cam_zoom) {
- if (zfac != 1.0f) {
- const float zfac_min = dist_range[0] / vod->rv3d->dist;
- const float zfac_max = dist_range[1] / vod->rv3d->dist;
- CLAMP(zfac, zfac_min, zfac_max);
- if (zfac != 1.0f) {
- view_zoom_mouseloc(vod->ar, zfac, vod->oldx, vod->oldy);
- }
- }
+ return zfac;
+}
+
+static void viewzoom_apply_camera(
+ ViewOpsData *vod, const int xy[2],
+ const short viewzoom, const bool zoom_invert)
+{
+ float zfac;
+ float zoomfac_prev = BKE_screen_view3d_zoom_to_fac(vod->camzoom_prev) * 2.0f;
+ float zoomfac = BKE_screen_view3d_zoom_to_fac(vod->rv3d->camzoom) * 2.0f;
+
+ zfac = viewzoom_scale_value(
+ &vod->ar->winrct, viewzoom, zoom_invert, true, xy, &vod->origx,
+ zoomfac, zoomfac_prev,
+ &vod->timer_lastdraw);
+
+ if (zfac != 1.0f && zfac != 0.0f) {
+ /* calculate inverted, then invert again (needed because of camera zoom scaling) */
+ zfac = 1.0f / zfac;
+ view_zoom_mouseloc_camera(
+ vod->scene, vod->v3d,
+ vod->ar, zfac, vod->oldx, vod->oldy);
+ }
+
+ ED_region_tag_redraw(vod->ar);
+}
+
+static void viewzoom_apply_3d(
+ ViewOpsData *vod, const int xy[2],
+ const short viewzoom, const bool zoom_invert)
+{
+ float zfac;
+ float dist_range[2];
+
+ ED_view3d_dist_range_get(vod->v3d, dist_range);
+
+ zfac = viewzoom_scale_value(
+ &vod->ar->winrct, viewzoom, zoom_invert, false, xy, &vod->origx,
+ vod->rv3d->dist, vod->dist_prev,
+ &vod->timer_lastdraw);
+
+ if (zfac != 1.0f) {
+ const float zfac_min = dist_range[0] / vod->rv3d->dist;
+ const float zfac_max = dist_range[1] / vod->rv3d->dist;
+ CLAMP(zfac, zfac_min, zfac_max);
+
+ view_zoom_mouseloc_3d(
+ vod->ar, zfac, vod->oldx, vod->oldy);
}
/* these limits were in old code too */
@@ -2209,11 +2323,26 @@ static void viewzoom_apply(ViewOpsData *vod, const int xy[2], const short viewzo
ED_region_tag_redraw(vod->ar);
}
+static void viewzoom_apply(
+ ViewOpsData *vod, const int xy[2],
+ const short viewzoom, const bool zoom_invert)
+{
+ if ((vod->rv3d->persp == RV3D_CAMOB) &&
+ (vod->rv3d->is_persp && ED_view3d_camera_lock_check(vod->v3d, vod->rv3d)) == 0)
+ {
+ viewzoom_apply_camera(vod, xy, viewzoom, zoom_invert);
+ }
+ else {
+ viewzoom_apply_3d(vod, xy, viewzoom, zoom_invert);
+ }
+}
static int viewzoom_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
ViewOpsData *vod = op->customdata;
short event_code = VIEW_PASS;
+ bool use_autokey = false;
+ int ret = OPERATOR_RUNNING_MODAL;
/* execute the events */
if (event->type == TIMER && event->customdata == vod->timer) {
@@ -2244,20 +2373,30 @@ static int viewzoom_modal(bContext *C, wmOperator *op, const wmEvent *event)
if (event_code == VIEW_APPLY) {
viewzoom_apply(vod, &event->x, U.viewzoom, (U.uiflag & USER_ZOOM_INVERT) != 0);
+ if (ED_screen_animation_playing(CTX_wm_manager(C))) {
+ use_autokey = true;
+ }
}
else if (event_code == VIEW_CONFIRM) {
- ED_view3d_camera_lock_autokey(vod->v3d, vod->rv3d, C, false, true);
ED_view3d_depth_tag_update(vod->rv3d);
- viewops_data_free(C, op);
+ use_autokey = true;
+ ret = OPERATOR_FINISHED;
+ }
- return OPERATOR_FINISHED;
+ if (use_autokey) {
+ ED_view3d_camera_lock_autokey(vod->v3d, vod->rv3d, C, false, true);
+ }
+
+ if (ret & OPERATOR_FINISHED) {
+ viewops_data_free(C, op);
}
- return OPERATOR_RUNNING_MODAL;
+ return ret;
}
static int viewzoom_exec(bContext *C, wmOperator *op)
{
+ Scene *scene = CTX_data_scene(C);
View3D *v3d;
RegionView3D *rv3d;
ScrArea *sa;
@@ -2290,22 +2429,26 @@ static int viewzoom_exec(bContext *C, wmOperator *op)
ED_view3d_dist_range_get(v3d, dist_range);
if (delta < 0) {
+ const float step = 1.2f;
/* this min and max is also in viewmove() */
if (use_cam_zoom) {
- rv3d->camzoom -= 10.0f;
- if (rv3d->camzoom < RV3D_CAMZOOM_MIN) rv3d->camzoom = RV3D_CAMZOOM_MIN;
+ view_zoom_mouseloc_camera(scene, v3d, ar, step, mx, my);
}
- else if (rv3d->dist < dist_range[1]) {
- view_zoom_mouseloc(ar, 1.2f, mx, my);
+ else {
+ if (rv3d->dist < dist_range[1]) {
+ view_zoom_mouseloc_3d(ar, step, mx, my);
+ }
}
}
else {
+ const float step = 1.0f / 1.2f;
if (use_cam_zoom) {
- rv3d->camzoom += 10.0f;
- if (rv3d->camzoom > RV3D_CAMZOOM_MAX) rv3d->camzoom = RV3D_CAMZOOM_MAX;
+ view_zoom_mouseloc_camera(scene, v3d, ar, step, mx, my);
}
- else if (rv3d->dist > dist_range[0]) {
- view_zoom_mouseloc(ar, 0.83333f, mx, my);
+ else {
+ if (rv3d->dist > dist_range[0]) {
+ view_zoom_mouseloc_3d(ar, step, mx, my);
+ }
}
}
@@ -2315,6 +2458,7 @@ static int viewzoom_exec(bContext *C, wmOperator *op)
ED_view3d_depth_tag_update(rv3d);
ED_view3d_camera_lock_sync(v3d, rv3d);
+ ED_view3d_camera_lock_autokey(v3d, rv3d, C, false, true);
ED_region_tag_redraw(ar);
@@ -2389,8 +2533,10 @@ static int viewzoom_invoke(bContext *C, wmOperator *op, const wmEvent *event)
vod->origy = vod->oldy = vod->origy + event->x - event->prevx;
viewzoom_apply(vod, &event->prevx, USER_ZOOM_DOLLY, (U.uiflag & USER_ZOOM_INVERT) != 0);
}
+ ED_view3d_camera_lock_autokey(vod->v3d, vod->rv3d, C, false, true);
+
ED_view3d_depth_tag_update(vod->rv3d);
-
+
viewops_data_free(C, op);
return OPERATOR_FINISHED;
}
@@ -2432,7 +2578,7 @@ void VIEW3D_OT_zoom(wmOperatorType *ot)
ot->cancel = viewzoom_cancel;
/* flags */
- ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_POINTER;
+ ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_CURSOR;
RNA_def_int(ot->srna, "delta", 0, INT_MIN, INT_MAX, "Delta", "", INT_MIN, INT_MAX);
prop = RNA_def_int(ot->srna, "mx", 0, 0, INT_MAX, "Zoom Position X", "", 0, INT_MAX);
@@ -2486,6 +2632,8 @@ static int viewdolly_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
ViewOpsData *vod = op->customdata;
short event_code = VIEW_PASS;
+ bool use_autokey = false;
+ int ret = OPERATOR_RUNNING_MODAL;
/* execute the events */
if (event->type == MOUSEMOVE) {
@@ -2512,16 +2660,25 @@ static int viewdolly_modal(bContext *C, wmOperator *op, const wmEvent *event)
if (event_code == VIEW_APPLY) {
viewdolly_apply(vod, event->x, event->y, (U.uiflag & USER_ZOOM_INVERT) != 0);
+ if (ED_screen_animation_playing(CTX_wm_manager(C))) {
+ use_autokey = true;
+ }
}
else if (event_code == VIEW_CONFIRM) {
- ED_view3d_camera_lock_autokey(vod->v3d, vod->rv3d, C, false, true);
ED_view3d_depth_tag_update(vod->rv3d);
- viewops_data_free(C, op);
+ use_autokey = true;
+ ret = OPERATOR_FINISHED;
+ }
- return OPERATOR_FINISHED;
+ if (use_autokey) {
+ ED_view3d_camera_lock_autokey(vod->v3d, vod->rv3d, C, false, true);
}
- return OPERATOR_RUNNING_MODAL;
+ if (ret & OPERATOR_FINISHED) {
+ viewops_data_free(C, op);
+ }
+
+ return ret;
}
static int viewdolly_exec(bContext *C, wmOperator *op)
@@ -2675,7 +2832,7 @@ void VIEW3D_OT_dolly(wmOperatorType *ot)
ot->cancel = viewdolly_cancel;
/* flags */
- ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_POINTER;
+ ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_CURSOR;
RNA_def_int(ot->srna, "delta", 0, INT_MIN, INT_MAX, "Delta", "", INT_MIN, INT_MAX);
RNA_def_int(ot->srna, "mx", 0, 0, INT_MAX, "Zoom Position X", "", 0, INT_MAX);
@@ -2698,29 +2855,15 @@ static void view3d_from_minmax(bContext *C, View3D *v3d, ARegion *ar,
size = max_fff(afm[0], afm[1], afm[2]);
if (ok_dist) {
- /* fix up zoom distance if needed */
+ char persp;
if (rv3d->is_persp) {
- float lens, sensor_size;
- /* offset the view based on the lens */
if (rv3d->persp == RV3D_CAMOB && ED_view3d_camera_lock_check(v3d, rv3d)) {
- CameraParams params;
- BKE_camera_params_init(&params);
- params.clipsta = v3d->near;
- params.clipend = v3d->far;
- BKE_camera_params_from_object(&params, v3d->camera);
-
- lens = params.lens;
- sensor_size = BKE_camera_sensor_size(params.sensor_fit, params.sensor_x, params.sensor_y);
+ persp = RV3D_CAMOB;
}
else {
- lens = v3d->lens;
- sensor_size = DEFAULT_SENSOR_WIDTH;
+ persp = RV3D_PERSP;
}
- size = ED_view3d_radius_to_persp_dist(focallength_to_fov(lens, sensor_size), size / 2.0f) * VIEW3D_MARGIN;
-
- /* do not zoom closer than the near clipping plane */
- size = max_ff(size, v3d->near * 1.5f);
}
else { /* ortho */
if (size < 0.0001f) {
@@ -2729,7 +2872,15 @@ static void view3d_from_minmax(bContext *C, View3D *v3d, ARegion *ar,
}
else {
/* adjust zoom so it looks nicer */
- size = ED_view3d_radius_to_ortho_dist(v3d->lens, size / 2.0f) * VIEW3D_MARGIN;
+ persp = RV3D_ORTHO;
+ }
+ }
+
+ if (ok_dist) {
+ new_dist = ED_view3d_radius_to_dist(v3d, ar, persp, true, (size / 2) * VIEW3D_MARGIN);
+ if (rv3d->is_persp) {
+ /* don't zoom closer than the near clipping plane */
+ new_dist = max_ff(new_dist, v3d->near * 1.5f);
}
}
}
@@ -2737,15 +2888,6 @@ static void view3d_from_minmax(bContext *C, View3D *v3d, ARegion *ar,
mid_v3_v3v3(new_ofs, min, max);
negate_v3(new_ofs);
- new_dist = size;
-
- /* correction for window aspect ratio */
- if (ar->winy > 2 && ar->winx > 2) {
- size = (float)ar->winx / (float)ar->winy;
- if (size < 1.0f) size = 1.0f / size;
- new_dist *= size;
- }
-
if (rv3d->persp == RV3D_CAMOB && !ED_view3d_camera_lock_check(v3d, rv3d)) {
rv3d->persp = RV3D_PERSP;
ED_view3d_smooth_view(C, v3d, ar, v3d->camera, NULL,
@@ -2901,24 +3043,7 @@ static int viewselected_exec(bContext *C, wmOperator *op)
ok = ED_view3d_minmax_verts(obedit, min, max); /* only selected */
}
else if (ob && (ob->mode & OB_MODE_POSE)) {
- if (ob->pose) {
- bArmature *arm = ob->data;
- bPoseChannel *pchan;
- float vec[3];
-
- for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
- if (pchan->bone->flag & BONE_SELECTED) {
- if (pchan->bone->layer & arm->layer) {
- bPoseChannel *pchan_tx = pchan->custom_tx ? pchan->custom_tx : pchan;
- ok = 1;
- mul_v3_m4v3(vec, ob->obmat, pchan_tx->pose_head);
- minmax_v3v3_v3(min, max, vec);
- mul_v3_m4v3(vec, ob->obmat, pchan_tx->pose_tail);
- minmax_v3v3_v3(min, max, vec);
- }
- }
- }
- }
+ ok = BKE_pose_minmax(ob, min, max, true, true);
}
else if (BKE_paint_select_face_test(ob)) {
ok = paintface_minmax(ob, min, max);
@@ -2926,8 +3051,10 @@ static int viewselected_exec(bContext *C, wmOperator *op)
else if (ob && (ob->mode & OB_MODE_PARTICLE_EDIT)) {
ok = PE_minmax(scene, min, max);
}
- else if (ob && (ob->mode & OB_MODE_SCULPT)) {
- ok = ED_sculpt_minmax(C, min, max);
+ else if (ob && (ob->mode & (OB_MODE_SCULPT | OB_MODE_TEXTURE_PAINT))) {
+ BKE_paint_stroke_get_average(scene, ob, min);
+ copy_v3_v3(max, min);
+ ok = true;
ok_dist = 0; /* don't zoom */
}
else {
@@ -3322,7 +3449,8 @@ void VIEW3D_OT_render_border(wmOperatorType *ot)
/* rna */
WM_operator_properties_border(ot);
- prop = RNA_def_boolean(ot->srna, "camera_only", 0, "Camera Only", "Set render border for camera view and final render only");
+ prop = RNA_def_boolean(ot->srna, "camera_only", false, "Camera Only",
+ "Set render border for camera view and final render only");
RNA_def_property_flag(prop, PROP_HIDDEN);
}
@@ -3423,7 +3551,7 @@ static int view3d_zoom_border_exec(bContext *C, wmOperator *op)
/* find the closest Z pixel */
depth_close = view3d_depth_near(&depth_temp);
- MEM_freeN(depth_temp.depths);
+ MEM_SAFE_FREE(depth_temp.depths);
}
cent[0] = (((double)rect.xmin) + ((double)rect.xmax)) / 2;
@@ -3624,6 +3752,8 @@ static void axis_set_view(bContext *C, View3D *v3d, ARegion *ar,
{
RegionView3D *rv3d = ar->regiondata; /* no NULL check is needed, poll checks */
float quat[4];
+ const short orig_persp = rv3d->persp;
+
normalize_qt_qt(quat, quat_);
@@ -3639,7 +3769,7 @@ static void axis_set_view(bContext *C, View3D *v3d, ARegion *ar,
float twmat[3][3];
/* same as transform manipulator when normal is set */
- ED_getTransformOrientationMatrix(C, twmat, true);
+ ED_getTransformOrientationMatrix(C, twmat, V3D_ACTIVE);
mat3_to_quat(obact_quat, twmat);
invert_qt(obact_quat);
@@ -3650,22 +3780,6 @@ static void axis_set_view(bContext *C, View3D *v3d, ARegion *ar,
}
if (align_active == false) {
- /* normal operation */
- if (rv3d->viewlock & RV3D_LOCKED) {
- /* only pass on if */
-
- /* nice confusing if-block */
- if (!((rv3d->view == RV3D_VIEW_FRONT && view == RV3D_VIEW_BACK) ||
- (rv3d->view == RV3D_VIEW_BACK && view == RV3D_VIEW_FRONT) ||
- (rv3d->view == RV3D_VIEW_RIGHT && view == RV3D_VIEW_LEFT) ||
- (rv3d->view == RV3D_VIEW_LEFT && view == RV3D_VIEW_RIGHT) ||
- (rv3d->view == RV3D_VIEW_BOTTOM && view == RV3D_VIEW_TOP) ||
- (rv3d->view == RV3D_VIEW_TOP && view == RV3D_VIEW_BOTTOM)))
- {
- return;
- }
- }
-
rv3d->view = view;
}
@@ -3682,16 +3796,31 @@ static void axis_set_view(bContext *C, View3D *v3d, ARegion *ar,
}
if (rv3d->persp == RV3D_CAMOB && v3d->camera) {
+ /* to camera */
ED_view3d_smooth_view(C, v3d, ar, v3d->camera, NULL,
rv3d->ofs, quat, NULL, NULL,
smooth_viewtx);
}
+ else if (orig_persp == RV3D_CAMOB && v3d->camera) {
+ /* from camera */
+ float ofs[3], dist;
+
+ copy_v3_v3(ofs, rv3d->ofs);
+ dist = rv3d->dist;
+
+ /* so we animate _from_ the camera location */
+ ED_view3d_from_object(v3d->camera, rv3d->ofs, NULL, &rv3d->dist, NULL);
+
+ ED_view3d_smooth_view(C, v3d, ar, NULL, NULL,
+ ofs, quat, &dist, NULL,
+ smooth_viewtx);
+ }
else {
+ /* no camera involved */
ED_view3d_smooth_view(C, v3d, ar, NULL, NULL,
NULL, quat, NULL, NULL,
smooth_viewtx);
}
-
}
static int viewnumpad_exec(bContext *C, wmOperator *op)
@@ -3712,10 +3841,6 @@ static int viewnumpad_exec(bContext *C, wmOperator *op)
viewnum = RNA_enum_get(op->ptr, "type");
align_active = RNA_boolean_get(op->ptr, "align_active");
- /* set this to zero, gets handled in axis_set_view */
- if (rv3d->viewlock & RV3D_LOCKED)
- align_active = false;
-
/* Use this to test if we started out with a camera */
if (rv3d->persp == RV3D_CAMOB) {
@@ -3841,23 +3966,37 @@ static int vieworbit_exec(bContext *C, wmOperator *op)
ARegion *ar;
RegionView3D *rv3d;
int orbitdir;
+ char view_opposite;
+ PropertyRNA *prop_angle = RNA_struct_find_property(op->ptr, "angle");
+ float angle = RNA_property_is_set(op->ptr, prop_angle) ?
+ RNA_property_float_get(op->ptr, prop_angle) : DEG2RADF(U.pad_rot_angle);
/* no NULL check is needed, poll checks */
- ED_view3d_context_user_region(C, &v3d, &ar);
+ v3d = CTX_wm_view3d(C);
+ ar = CTX_wm_region(C);
rv3d = ar->regiondata;
+ /* support for switching to the opposite view (even when in locked views) */
+ view_opposite = (fabsf(angle) == (float)M_PI) ? ED_view3d_axis_view_opposite(rv3d->view) : RV3D_VIEW_USER;
orbitdir = RNA_enum_get(op->ptr, "type");
- if ((rv3d->viewlock & RV3D_LOCKED) == 0) {
+ if ((rv3d->viewlock & RV3D_LOCKED) && (view_opposite == RV3D_VIEW_USER)) {
+ /* no NULL check is needed, poll checks */
+ ED_view3d_context_user_region(C, &v3d, &ar);
+ rv3d = ar->regiondata;
+ }
+
+ if ((rv3d->viewlock & RV3D_LOCKED) == 0 || (view_opposite != RV3D_VIEW_USER)) {
if ((rv3d->persp != RV3D_CAMOB) || ED_view3d_camera_lock_check(v3d, rv3d)) {
int smooth_viewtx = WM_operator_smooth_viewtx_get(op);
- float angle = DEG2RADF((float)U.pad_rot_angle);
float quat_mul[4];
float quat_new[4];
float ofs_new[3];
float *ofs_new_pt = NULL;
- view3d_ensure_persp(v3d, ar);
+ if (view_opposite == RV3D_VIEW_USER) {
+ view3d_ensure_persp(v3d, ar);
+ }
if (ELEM(orbitdir, V3D_VIEW_STEPLEFT, V3D_VIEW_STEPRIGHT)) {
const float zvec[3] = {0.0f, 0.0f, 1.0f};
@@ -3880,7 +4019,15 @@ static int vieworbit_exec(bContext *C, wmOperator *op)
}
mul_qt_qtqt(quat_new, rv3d->viewquat, quat_mul);
- rv3d->view = RV3D_VIEW_USER;
+
+ if (view_opposite != RV3D_VIEW_USER) {
+ rv3d->view = view_opposite;
+ /* avoid float in-precision, just get a new orientation */
+ ED_view3d_quat_from_axis_view(view_opposite, quat_new);
+ }
+ else {
+ rv3d->view = RV3D_VIEW_USER;
+ }
if (U.uiflag & USER_ORBIT_SELECTION) {
float dyn_ofs[3];
@@ -3911,6 +4058,8 @@ static int vieworbit_exec(bContext *C, wmOperator *op)
void VIEW3D_OT_view_orbit(wmOperatorType *ot)
{
+ PropertyRNA *prop;
+
/* identifiers */
ot->name = "View Orbit";
ot->description = "Orbit the view";
@@ -3924,7 +4073,11 @@ void VIEW3D_OT_view_orbit(wmOperatorType *ot)
ot->flag = 0;
/* properties */
+ prop = RNA_def_float(ot->srna, "angle", 0, -FLT_MAX, FLT_MAX, "Roll", "", -FLT_MAX, FLT_MAX);
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+
ot->prop = RNA_def_enum(ot->srna, "type", prop_view_orbit_items, 0, "Orbit", "Direction of View Orbit");
+
}
@@ -3970,6 +4123,8 @@ static int viewroll_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
ViewOpsData *vod = op->customdata;
short event_code = VIEW_PASS;
+ bool use_autokey = false;
+ int ret = OPERATOR_RUNNING_MODAL;
/* execute the events */
if (event->type == MOUSEMOVE) {
@@ -3996,18 +4151,35 @@ static int viewroll_modal(bContext *C, wmOperator *op, const wmEvent *event)
if (event_code == VIEW_APPLY) {
viewroll_apply(vod, event->x, event->y);
+ if (ED_screen_animation_playing(CTX_wm_manager(C))) {
+ use_autokey = true;
+ }
}
else if (event_code == VIEW_CONFIRM) {
- ED_view3d_camera_lock_autokey(vod->v3d, vod->rv3d, C, true, false);
ED_view3d_depth_tag_update(vod->rv3d);
- viewops_data_free(C, op);
+ use_autokey = true;
+ ret = OPERATOR_FINISHED;
+ }
- return OPERATOR_FINISHED;
+ if (use_autokey) {
+ ED_view3d_camera_lock_autokey(vod->v3d, vod->rv3d, C, true, false);
+ }
+
+ if (ret & OPERATOR_FINISHED) {
+ viewops_data_free(C, op);
}
- return OPERATOR_RUNNING_MODAL;
+ return ret;
}
+static EnumPropertyItem prop_view_roll_items[] = {
+ {0, "ROLLANGLE", 0, "Roll Angle", "Roll the view using an angle value"},
+ {V3D_VIEW_STEPLEFT, "ROLLLEFT", 0, "Roll Left", "Roll the view around to the Left"},
+ {V3D_VIEW_STEPRIGHT, "ROLLTRIGHT", 0, "Roll Right", "Roll the view around to the Right"},
+ {0, NULL, 0, NULL, NULL}
+};
+
+
static int viewroll_exec(bContext *C, wmOperator *op)
{
View3D *v3d;
@@ -4025,12 +4197,17 @@ static int viewroll_exec(bContext *C, wmOperator *op)
rv3d = ar->regiondata;
if ((rv3d->persp != RV3D_CAMOB) || ED_view3d_camera_lock_check(v3d, rv3d)) {
- const float angle = RNA_float_get(op->ptr, "angle");
+ int type = RNA_enum_get(op->ptr, "type");
+ float angle = (type == 0) ? RNA_float_get(op->ptr, "angle") : DEG2RADF(U.pad_rot_angle);
float mousevec[3];
float quat_new[4];
const int smooth_viewtx = WM_operator_smooth_viewtx_get(op);
+ if (type == V3D_VIEW_STEPLEFT) {
+ angle = -angle;
+ }
+
normalize_v3_v3(mousevec, rv3d->viewinv[2]);
negate_v3(mousevec);
view_roll_angle(ar, quat_new, rv3d->viewquat, mousevec, angle);
@@ -4052,7 +4229,9 @@ static int viewroll_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
ViewOpsData *vod;
- if (RNA_struct_property_is_set(op->ptr, "angle")) {
+ bool use_angle = RNA_enum_get(op->ptr, "type") != 0;
+
+ if (use_angle || RNA_struct_property_is_set(op->ptr, "angle")) {
viewroll_exec(C, op);
}
else {
@@ -4090,6 +4269,8 @@ static void viewroll_cancel(bContext *C, wmOperator *op)
void VIEW3D_OT_view_roll(wmOperatorType *ot)
{
+ PropertyRNA *prop;
+
/* identifiers */
ot->name = "View Roll";
ot->description = "Roll the view";
@@ -4106,7 +4287,10 @@ void VIEW3D_OT_view_roll(wmOperatorType *ot)
ot->flag = 0;
/* properties */
- ot->prop = RNA_def_float(ot->srna, "angle", 0, -FLT_MAX, FLT_MAX, "Roll", "", -FLT_MAX, FLT_MAX);
+ ot->prop = prop = RNA_def_float(ot->srna, "angle", 0, -FLT_MAX, FLT_MAX, "Roll", "", -FLT_MAX, FLT_MAX);
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+ prop = RNA_def_enum(ot->srna, "type", prop_view_roll_items, 0, "Roll Angle Source", "How roll angle is calculated");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
static EnumPropertyItem prop_view_pan_items[] = {
@@ -4259,32 +4443,16 @@ static int background_image_add_exec(bContext *C, wmOperator *UNUSED(op))
static int background_image_add_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
View3D *v3d = CTX_wm_view3d(C);
- Image *ima = NULL;
+ Image *ima;
BGpic *bgpic;
- char name[MAX_ID_NAME - 2];
-
- /* check input variables */
- if (RNA_struct_property_is_set(op->ptr, "filepath")) {
- char path[FILE_MAX];
-
- RNA_string_get(op->ptr, "filepath", path);
- ima = BKE_image_load_exists(path);
- }
- else if (RNA_struct_property_is_set(op->ptr, "name")) {
- RNA_string_get(op->ptr, "name", name);
- ima = (Image *)BKE_libblock_find_name(ID_IM, name);
- }
+ ima = (Image *)WM_operator_drop_load_path(C, op, ID_IM);
+ /* may be NULL, continue anyway */
+
bgpic = background_image_add(C);
-
- if (ima) {
- bgpic->ima = ima;
-
- id_us_plus(&ima->id);
-
- if (!(v3d->flag & V3D_DISPBGPICS))
- v3d->flag |= V3D_DISPBGPICS;
- }
+ bgpic->ima = ima;
+
+ v3d->flag |= V3D_DISPBGPICS;
WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, v3d);
@@ -4310,7 +4478,8 @@ void VIEW3D_OT_background_image_add(wmOperatorType *ot)
/* properties */
RNA_def_string(ot->srna, "name", "Image", MAX_ID_NAME - 2, "Name", "Image name to assign");
- RNA_def_string(ot->srna, "filepath", "Path", FILE_MAX, "Filepath", "Path to image file");
+ WM_operator_properties_filesel(ot, FILE_TYPE_FOLDER | FILE_TYPE_IMAGE | FILE_TYPE_MOVIE, FILE_SPECIAL, FILE_OPENFILE,
+ WM_FILESEL_FILEPATH | WM_FILESEL_RELPATH, FILE_DEFAULTDISPLAY, FILE_SORT_ALPHA);
}
@@ -4360,16 +4529,6 @@ void VIEW3D_OT_background_image_remove(wmOperatorType *ot)
/* ********************* set clipping operator ****************** */
-static void calc_clipping_plane(float clip[6][4], const BoundBox *clipbb)
-{
- int val;
-
- for (val = 0; val < 4; val++) {
- normal_tri_v3(clip[val], clipbb->vec[val], clipbb->vec[val == 3 ? 0 : val + 1], clipbb->vec[val + 4]);
- clip[val][3] = -dot_v3v3(clip[val], clipbb->vec[val]);
- }
-}
-
static void calc_local_clipping(float clip_local[6][4], BoundBox *clipbb, float mat[4][4])
{
BoundBox clipbb_local;
@@ -4382,7 +4541,7 @@ static void calc_local_clipping(float clip_local[6][4], BoundBox *clipbb, float
mul_v3_m4v3(clipbb_local.vec[i], imat, clipbb->vec[i]);
}
- calc_clipping_plane(clip_local, &clipbb_local);
+ ED_view3d_clipping_calc_from_boundbox(clip_local, &clipbb_local, is_negative_m4(mat));
}
void ED_view3d_clipping_local(RegionView3D *rv3d, float mat[4][4])
@@ -4463,7 +4622,7 @@ void ED_view3d_cursor3d_position(bContext *C, float fp[3], const int mval[2])
Scene *scene = CTX_data_scene(C);
ARegion *ar = CTX_wm_region(C);
View3D *v3d = CTX_wm_view3d(C);
- RegionView3D *rv3d = CTX_wm_region_view3d(C);
+ RegionView3D *rv3d = ar->regiondata;
bool flip;
bool depth_used = false;
@@ -4498,11 +4657,30 @@ void ED_view3d_cursor3d_update(bContext *C, const int mval[2])
{
Scene *scene = CTX_data_scene(C);
View3D *v3d = CTX_wm_view3d(C);
- float *fp = ED_view3d_cursor3d_get(scene, v3d);
- ED_view3d_cursor3d_position(C, fp, mval);
+ float *fp_curr = ED_view3d_cursor3d_get(scene, v3d);
+ float fp_prev[3];
+
+ copy_v3_v3(fp_prev, fp_curr);
+
+ ED_view3d_cursor3d_position(C, fp_curr, mval);
- if (v3d && v3d->localvd)
+ /* offset the cursor lock to avoid jumping to new offset */
+ if (v3d->ob_centre_cursor) {
+ ARegion *ar = CTX_wm_region(C);
+ RegionView3D *rv3d = ar->regiondata;
+
+ float co_curr[2], co_prev[2];
+
+ if ((ED_view3d_project_float_global(ar, fp_prev, co_prev, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) &&
+ (ED_view3d_project_float_global(ar, fp_curr, co_curr, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK))
+ {
+ rv3d->ofs_lock[0] += (co_curr[0] - co_prev[0]) / (ar->winx * 0.5f);
+ rv3d->ofs_lock[1] += (co_curr[1] - co_prev[1]) / (ar->winy * 0.5f);
+ }
+ }
+
+ if (v3d->localvd)
WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, v3d);
else
WM_event_add_notifier(C, NC_SCENE | NA_EDITED, scene);
@@ -4512,7 +4690,7 @@ static int view3d_cursor3d_invoke(bContext *C, wmOperator *UNUSED(op), const wmE
{
ED_view3d_cursor3d_update(C, event->mval);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void VIEW3D_OT_cursor3d(wmOperatorType *ot)
@@ -4526,7 +4704,7 @@ void VIEW3D_OT_cursor3d(wmOperatorType *ot)
/* api callbacks */
ot->invoke = view3d_cursor3d_invoke;
- ot->poll = ED_operator_view3d_active;
+ ot->poll = ED_operator_region_view3d_active;
/* flags */
// ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
@@ -4640,28 +4818,43 @@ static float view_autodist_depth_margin(ARegion *ar, const int mval[2], int marg
view3d_update_depths_rect(ar, &depth_temp, &rect);
depth_close = view3d_depth_near(&depth_temp);
- if (depth_temp.depths) MEM_freeN(depth_temp.depths);
+ MEM_SAFE_FREE(depth_temp.depths);
return depth_close;
}
-/* XXX todo Zooms in on a border drawn by the user */
-bool ED_view3d_autodist(Scene *scene, ARegion *ar, View3D *v3d,
- const int mval[2], float mouse_worldloc[3],
- const bool alphaoverride, const float fallback_depth_pt[3])
+/**
+ * Get the world-space 3d location from a screen-space 2d point.
+ *
+ * \param mval: Input screen-space pixel location.
+ * \param mouse_worldloc: Output world-space loction.
+ * \param fallback_depth_pt: Use this points depth when no depth can be found.
+ */
+bool ED_view3d_autodist(
+ Scene *scene, ARegion *ar, View3D *v3d,
+ const int mval[2], float mouse_worldloc[3],
+ const bool alphaoverride, const float fallback_depth_pt[3])
{
bglMats mats; /* ZBuffer depth vars */
float depth_close;
double cent[2], p[3];
+ int margin_arr[] = {0, 2, 4};
+ int i;
+ bool depth_ok = false;
/* Get Z Depths, needed for perspective, nice for ortho */
bgl_get_mats(&mats);
ED_view3d_draw_depth(scene, ar, v3d, alphaoverride);
- depth_close = view_autodist_depth_margin(ar, mval, 4);
+ /* Attempt with low margin's first */
+ i = 0;
+ do {
+ depth_close = view_autodist_depth_margin(ar, mval, margin_arr[i++] * U.pixelsize);
+ depth_ok = (depth_close != FLT_MAX);
+ } while ((depth_ok == false) && (i < ARRAY_SIZE(margin_arr)));
- if (depth_close != FLT_MAX) {
- cent[0] = (double)mval[0];
- cent[1] = (double)mval[1];
+ if (depth_ok) {
+ cent[0] = (double)mval[0] + 0.5;
+ cent[1] = (double)mval[1] + 0.5;
if (gluUnProject(cent[0], cent[1], depth_close,
mats.modelview, mats.projection, (GLint *)mats.viewport, &p[0], &p[1], &p[2]))
@@ -4712,8 +4905,8 @@ bool ED_view3d_autodist_simple(ARegion *ar, const int mval[2], float mouse_world
if (depth == FLT_MAX)
return false;
- cent[0] = (double)mval[0];
- cent[1] = (double)mval[1];
+ cent[0] = (double)mval[0] + 0.5;
+ cent[1] = (double)mval[1] + 0.5;
bgl_get_mats(&mats);
@@ -4932,8 +5125,9 @@ BGpic *ED_view3D_background_image_new(View3D *v3d)
{
BGpic *bgpic = MEM_callocN(sizeof(BGpic), "Background Image");
- bgpic->size = 5.0;
- bgpic->blend = 0.5;
+ bgpic->rotation = 0.0f;
+ bgpic->size = 5.0f;
+ bgpic->blend = 0.5f;
bgpic->iuser.fie_ima = 2;
bgpic->iuser.ok = 1;
bgpic->view = 0; /* 0 for all */
diff --git a/source/blender/editors/space_view3d/view3d_fly.c b/source/blender/editors/space_view3d/view3d_fly.c
index da77c4f75f7..e6910cf9303 100644
--- a/source/blender/editors/space_view3d/view3d_fly.c
+++ b/source/blender/editors/space_view3d/view3d_fly.c
@@ -39,7 +39,7 @@
#include "BKE_context.h"
#include "BKE_report.h"
-#include "BLF_translation.h"
+#include "BLT_translation.h"
#include "BIF_gl.h"
@@ -51,6 +51,7 @@
#include "PIL_time.h" /* smoothview */
+#include "UI_interface.h"
#include "UI_resources.h"
#include "view3d_intern.h" /* own include */
@@ -283,26 +284,37 @@ static void drawFlyPixel(const struct bContext *UNUSED(C), ARegion *UNUSED(ar),
glEnd();
}
-static void fly_update_header(bContext *C, FlyInfo *fly)
+static void fly_update_header(bContext *C, wmOperator *op, FlyInfo *fly)
{
-#define HEADER_LENGTH 256
- char header[HEADER_LENGTH];
-
- BLI_snprintf(header, HEADER_LENGTH, IFACE_("LMB/Return: confirm, "
- "RMB/Esc: cancel, "
- "MMB: pan, "
- "WASDQE: direction, "
- "Alt: slow, "
- "Ctrl: free look, "
- "X: Upright x axis (%s), "
- "Z: Upright z axis (%s), "
- "(+/- | Wheel): speed"),
-
- WM_bool_as_string(fly->xlock != FLY_AXISLOCK_STATE_OFF),
- WM_bool_as_string(fly->zlock != FLY_AXISLOCK_STATE_OFF));
+ char header[UI_MAX_DRAW_STR];
+ char buf[UI_MAX_DRAW_STR];
+
+ char *p = buf;
+ int available_len = sizeof(buf);
+
+#define WM_MODALKEY(_id) \
+ WM_modalkeymap_operator_items_to_string_buf(op->type, (_id), true, UI_MAX_SHORTCUT_STR, &available_len, &p)
+
+ BLI_snprintf(header, sizeof(header), IFACE_("%s: confirm, %s: cancel, "
+ "%s: pan enable, "
+ "%s|%s|%s|%s|%s|%s: direction, "
+ "%s: slow, %s: free look, "
+ "%s: Upright x axis (%s), "
+ "%s: Upright z axis (%s), "
+ "%s: increase speed, %s: decrease speed"),
+ WM_MODALKEY(FLY_MODAL_CONFIRM), WM_MODALKEY(FLY_MODAL_CANCEL),
+ WM_MODALKEY(FLY_MODAL_PAN_ENABLE),
+ WM_MODALKEY(FLY_MODAL_DIR_FORWARD), WM_MODALKEY(FLY_MODAL_DIR_LEFT),
+ WM_MODALKEY(FLY_MODAL_DIR_BACKWARD), WM_MODALKEY(FLY_MODAL_DIR_RIGHT),
+ WM_MODALKEY(FLY_MODAL_DIR_UP), WM_MODALKEY(FLY_MODAL_DIR_DOWN),
+ WM_MODALKEY(FLY_MODAL_PRECISION_ENABLE), WM_MODALKEY(FLY_MODAL_FREELOOK_ENABLE),
+ WM_MODALKEY(FLY_MODAL_AXIS_LOCK_X), WM_bool_as_string(fly->xlock != FLY_AXISLOCK_STATE_OFF),
+ WM_MODALKEY(FLY_MODAL_AXIS_LOCK_Z), WM_bool_as_string(fly->zlock != FLY_AXISLOCK_STATE_OFF),
+ WM_MODALKEY(FLY_MODAL_ACCELERATE), WM_MODALKEY(FLY_MODAL_DECELERATE));
+
+#undef WM_MODALKEY
ED_area_headerprint(CTX_wm_area(C), header);
-#undef HEADER_LENGTH
}
/* FlyInfo->state */
@@ -410,7 +422,7 @@ static bool initFlyInfo(bContext *C, FlyInfo *fly, wmOperator *op, const wmEvent
/* center the mouse, probably the UI mafia are against this but without its quite annoying */
WM_cursor_warp(win, fly->ar->winrct.xmin + fly->center_mval[0], fly->ar->winrct.ymin + fly->center_mval[1]);
- fly_update_header(C, fly);
+ fly_update_header(C, op, fly);
return 1;
}
@@ -449,7 +461,7 @@ static int flyEnd(bContext *C, FlyInfo *fly)
return OPERATOR_CANCELLED;
}
-static void flyEvent(bContext *C, FlyInfo *fly, const wmEvent *event)
+static void flyEvent(bContext *C, wmOperator *op, FlyInfo *fly, const wmEvent *event)
{
if (event->type == TIMER && event->customdata == fly->timer) {
fly->redraw = 1;
@@ -657,7 +669,7 @@ static void flyEvent(bContext *C, FlyInfo *fly, const wmEvent *event)
fly->xlock = FLY_AXISLOCK_STATE_ACTIVE;
fly->xlock_momentum = 0.0;
}
- fly_update_header(C, fly);
+ fly_update_header(C, op, fly);
break;
case FLY_MODAL_AXIS_LOCK_Z:
if (fly->zlock != FLY_AXISLOCK_STATE_OFF)
@@ -666,7 +678,7 @@ static void flyEvent(bContext *C, FlyInfo *fly, const wmEvent *event)
fly->zlock = FLY_AXISLOCK_STATE_ACTIVE;
fly->zlock_momentum = 0.0;
}
- fly_update_header(C, fly);
+ fly_update_header(C, op, fly);
break;
case FLY_MODAL_PRECISION_ENABLE:
@@ -806,7 +818,7 @@ static int flyApply(bContext *C, FlyInfo *fly)
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);
+ axis_angle_to_quat(tmp_quat, upvec, moffset[1] * time_redraw * -FLY_ROTATE_FAC);
mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, tmp_quat);
if (fly->xlock != FLY_AXISLOCK_STATE_OFF)
@@ -836,7 +848,7 @@ static int flyApply(bContext *C, FlyInfo *fly)
}
/* Rotate about the relative up vec */
- axis_angle_to_quat(tmp_quat, upvec, (float)moffset[0] * time_redraw * FLY_ROTATE_FAC);
+ axis_angle_to_quat(tmp_quat, upvec, moffset[0] * time_redraw * FLY_ROTATE_FAC);
mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, tmp_quat);
if (fly->xlock != FLY_AXISLOCK_STATE_OFF)
@@ -982,7 +994,7 @@ static int fly_invoke(bContext *C, wmOperator *op, const wmEvent *event)
return OPERATOR_CANCELLED;
}
- flyEvent(C, fly, event);
+ flyEvent(C, op, fly, event);
WM_event_add_modal_handler(C, op);
@@ -1008,7 +1020,7 @@ static int fly_modal(bContext *C, wmOperator *op, const wmEvent *event)
fly->redraw = 0;
- flyEvent(C, fly, event);
+ flyEvent(C, op, fly, event);
if (fly->ndof) { /* 3D mouse overrules [2D mouse + timer] */
if (event->type == NDOF_MOTION) {
diff --git a/source/blender/editors/space_view3d/view3d_header.c b/source/blender/editors/space_view3d/view3d_header.c
index a88724a1cdd..42895a7530b 100644
--- a/source/blender/editors/space_view3d/view3d_header.c
+++ b/source/blender/editors/space_view3d/view3d_header.c
@@ -32,21 +32,16 @@
#include <stdio.h>
#include <stdlib.h>
-#include "DNA_brush_types.h"
#include "DNA_scene_types.h"
#include "DNA_object_types.h"
-#include "BLI_math.h"
-#include "BLI_blenlib.h"
#include "BLI_utildefines.h"
-#include "BLF_translation.h"
+#include "BLT_translation.h"
#include "BKE_context.h"
#include "BKE_depsgraph.h"
#include "BKE_main.h"
-#include "BKE_modifier.h"
-#include "BKE_paint.h"
#include "BKE_screen.h"
#include "BKE_editmesh.h"
@@ -110,8 +105,8 @@ static void view3d_layers_editmode_ensure(Scene *scene, View3D *v3d)
if (scene->obedit && (scene->obedit->lay & v3d->lay) == 0) {
int bit;
for (bit = 0; bit < 32; bit++) {
- if (scene->obedit->lay & (1 << bit)) {
- v3d->lay |= 1 << bit;
+ if (scene->obedit->lay & (1u << bit)) {
+ v3d->lay |= (1u << bit);
break;
}
}
@@ -166,8 +161,8 @@ static int view3d_layers_exec(bContext *C, wmOperator *op)
v3d->layact = 1 << nr;
else if ((v3d->lay & v3d->layact) == 0) {
for (bit = 0; bit < 32; bit++) {
- if (v3d->lay & (1 << bit)) {
- v3d->layact = 1 << bit;
+ if (v3d->lay & (1u << bit)) {
+ v3d->layact = (1u << bit);
break;
}
}
@@ -262,7 +257,7 @@ void uiTemplateEditModeSelection(uiLayout *layout, struct bContext *C)
Object *obedit = CTX_data_edit_object(C);
uiBlock *block = uiLayoutGetBlock(layout);
- uiBlockSetHandleFunc(block, do_view3d_header_buttons, NULL);
+ UI_block_func_handle_set(block, do_view3d_header_buttons, NULL);
if (obedit && (obedit->type == OB_MESH)) {
BMEditMesh *em = BKE_editmesh_from_object(obedit);
@@ -270,13 +265,13 @@ void uiTemplateEditModeSelection(uiLayout *layout, struct bContext *C)
row = uiLayoutRow(layout, true);
block = uiLayoutGetBlock(row);
- uiDefIconButBitS(block, TOG, SCE_SELECT_VERTEX, B_SEL_VERT, ICON_VERTEXSEL,
+ uiDefIconButBitS(block, UI_BTYPE_TOGGLE, SCE_SELECT_VERTEX, B_SEL_VERT, ICON_VERTEXSEL,
0, 0, UI_UNIT_X, UI_UNIT_Y, &em->selectmode, 1.0, 0.0, 0, 0,
TIP_("Vertex select - Shift-Click for multiple modes, Ctrl-Click contracts selection"));
- uiDefIconButBitS(block, TOG, SCE_SELECT_EDGE, B_SEL_EDGE, ICON_EDGESEL,
+ uiDefIconButBitS(block, UI_BTYPE_TOGGLE, SCE_SELECT_EDGE, B_SEL_EDGE, ICON_EDGESEL,
0, 0, UI_UNIT_X, UI_UNIT_Y, &em->selectmode, 1.0, 0.0, 0, 0,
TIP_("Edge select - Shift-Click for multiple modes, Ctrl-Click expands/contracts selection"));
- uiDefIconButBitS(block, TOG, SCE_SELECT_FACE, B_SEL_FACE, ICON_FACESEL,
+ uiDefIconButBitS(block, UI_BTYPE_TOGGLE, SCE_SELECT_FACE, B_SEL_FACE, ICON_FACESEL,
0, 0, UI_UNIT_X, UI_UNIT_Y, &em->selectmode, 1.0, 0.0, 0, 0,
TIP_("Face select - Shift-Click for multiple modes, Ctrl-Click expands selection"));
}
@@ -302,10 +297,10 @@ void uiTemplateHeader3D(uiLayout *layout, struct bContext *C)
RNA_pointer_create(&scene->id, &RNA_Scene, scene, &sceneptr);
block = uiLayoutGetBlock(layout);
- uiBlockSetHandleFunc(block, do_view3d_header_buttons, NULL);
+ UI_block_func_handle_set(block, do_view3d_header_buttons, NULL);
/* other buttons: */
- uiBlockSetEmboss(block, UI_EMBOSS);
+ UI_block_emboss_set(block, UI_EMBOSS);
/* mode */
if (ob) {
diff --git a/source/blender/editors/space_view3d/view3d_intern.h b/source/blender/editors/space_view3d/view3d_intern.h
index 84ac4f7d02d..95c0ef92680 100644
--- a/source/blender/editors/space_view3d/view3d_intern.h
+++ b/source/blender/editors/space_view3d/view3d_intern.h
@@ -41,16 +41,15 @@ struct BoundBox;
struct DerivedMesh;
struct Object;
struct SmokeDomainSettings;
-struct ViewContext;
struct bAnimVizSettings;
struct bContext;
struct bMotionPath;
struct bPoseChannel;
-struct bScreen;
struct Mesh;
struct wmNDOFMotionData;
struct wmOperatorType;
struct wmWindowManager;
+struct wmKeyConfig;
/* drawing flags: */
enum {
@@ -163,7 +162,9 @@ bool draw_armature(Scene *scene, View3D *v3d, ARegion *ar, Base *base,
/* drawmesh.c */
void draw_mesh_textured(Scene *scene, View3D *v3d, RegionView3D *rv3d,
struct Object *ob, struct DerivedMesh *dm, const int draw_flags);
-void draw_mesh_face_select(struct RegionView3D *rv3d, struct Mesh *me, struct DerivedMesh *dm);
+void draw_mesh_face_select(
+ struct RegionView3D *rv3d, struct Mesh *me, struct DerivedMesh *dm,
+ bool draw_select_edges);
void draw_mesh_paint_weight_faces(struct DerivedMesh *dm, const bool do_light,
void *facemask_cb, void *user_data);
void draw_mesh_paint_vcolor_faces(struct DerivedMesh *dm, const bool use_light,
@@ -175,6 +176,9 @@ void draw_mesh_paint_weight_edges(RegionView3D *rv3d, struct DerivedMesh *dm,
void draw_mesh_paint(View3D *v3d, RegionView3D *rv3d,
struct Object *ob, struct DerivedMesh *dm, const int draw_flags);
+/* drawsimdebug.c */
+void draw_sim_debug_data(Scene *scene, View3D *v3d, ARegion *ar);
+
/* view3d_draw.c */
void view3d_main_area_draw(const struct bContext *C, struct ARegion *ar);
void ED_view3d_draw_depth(Scene *scene, struct ARegion *ar, View3D *v3d, bool alphaoverride);
@@ -201,7 +205,7 @@ void VIEW3D_OT_localview(struct wmOperatorType *ot);
void VIEW3D_OT_game_start(struct wmOperatorType *ot);
-bool ED_view3d_boundbox_clip_ex(RegionView3D *rv3d, const struct BoundBox *bb, float obmat[4][4]);
+bool ED_view3d_boundbox_clip_ex(const RegionView3D *rv3d, const struct BoundBox *bb, float obmat[4][4]);
bool ED_view3d_boundbox_clip(RegionView3D *rv3d, const struct BoundBox *bb);
void ED_view3d_smooth_view_ex(
@@ -218,8 +222,8 @@ void ED_view3d_smooth_view(
const float *ofs, const float *quat, const float *dist, const float *lens,
const int smooth_viewtx);
-void view3d_winmatrix_set(ARegion *ar, View3D *v3d, const rctf *rect);
-void view3d_viewmatrix_set(Scene *scene, View3D *v3d, RegionView3D *rv3d);
+void view3d_winmatrix_set(ARegion *ar, const View3D *v3d, const rctf *rect);
+void view3d_viewmatrix_set(Scene *scene, const View3D *v3d, RegionView3D *rv3d);
void fly_modal_keymap(struct wmKeyConfig *keyconf);
void walk_modal_keymap(struct wmKeyConfig *keyconf);
diff --git a/source/blender/editors/space_view3d/view3d_ops.c b/source/blender/editors/space_view3d/view3d_ops.c
index 7e101fea138..8c668b2b8e0 100644
--- a/source/blender/editors/space_view3d/view3d_ops.c
+++ b/source/blender/editors/space_view3d/view3d_ops.c
@@ -42,6 +42,7 @@
#include "BLI_blenlib.h"
#include "BLI_utildefines.h"
+#include "BKE_appdir.h"
#include "BKE_blender.h"
#include "BKE_context.h"
#include "BKE_main.h"
@@ -77,7 +78,7 @@ static int view3d_copybuffer_exec(bContext *C, wmOperator *op)
}
CTX_DATA_END;
- BLI_make_file_string("/", str, BLI_temp_dir_base(), "copybuffer.blend");
+ BLI_make_file_string("/", str, BKE_tempdir_base(), "copybuffer.blend");
BKE_copybuffer_save(str, op->reports);
BKE_report(op->reports, RPT_INFO, "Copied selected objects to buffer");
@@ -102,7 +103,7 @@ static int view3d_pastebuffer_exec(bContext *C, wmOperator *op)
{
char str[FILE_MAX];
- BLI_make_file_string("/", str, BLI_temp_dir_base(), "copybuffer.blend");
+ BLI_make_file_string("/", str, BKE_tempdir_base(), "copybuffer.blend");
if (BKE_copybuffer_paste(C, str, op->reports)) {
WM_event_add_notifier(C, NC_WINDOW, NULL);
@@ -296,8 +297,11 @@ void view3d_keymap(wmKeyConfig *keyconf)
RNA_enum_set(WM_keymap_add_item(keymap, "VIEW3D_OT_view_pan", PAD4, KM_PRESS, KM_CTRL, 0)->ptr, "type", V3D_VIEW_PANLEFT);
RNA_enum_set(WM_keymap_add_item(keymap, "VIEW3D_OT_view_pan", PAD6, KM_PRESS, KM_CTRL, 0)->ptr, "type", V3D_VIEW_PANRIGHT);
RNA_enum_set(WM_keymap_add_item(keymap, "VIEW3D_OT_view_pan", PAD8, KM_PRESS, KM_CTRL, 0)->ptr, "type", V3D_VIEW_PANUP);
- RNA_float_set(WM_keymap_add_item(keymap, "VIEW3D_OT_view_roll", PAD4, KM_PRESS, KM_SHIFT, 0)->ptr, "angle", M_PI / -12);
- RNA_float_set(WM_keymap_add_item(keymap, "VIEW3D_OT_view_roll", PAD6, KM_PRESS, KM_SHIFT, 0)->ptr, "angle", M_PI / 12);
+ RNA_enum_set(WM_keymap_add_item(keymap, "VIEW3D_OT_view_roll", PAD4, KM_PRESS, KM_SHIFT, 0)->ptr, "type", V3D_VIEW_STEPLEFT);
+ RNA_enum_set(WM_keymap_add_item(keymap, "VIEW3D_OT_view_roll", PAD6, KM_PRESS, KM_SHIFT, 0)->ptr, "type", V3D_VIEW_STEPRIGHT);
+ kmi = WM_keymap_add_item(keymap, "VIEW3D_OT_view_orbit", PAD9, KM_PRESS, 0, 0);
+ RNA_enum_set(kmi->ptr, "type", V3D_VIEW_STEPRIGHT);
+ RNA_float_set(kmi->ptr, "angle", (float)M_PI);
RNA_enum_set(WM_keymap_add_item(keymap, "VIEW3D_OT_view_pan", WHEELUPMOUSE, KM_PRESS, KM_CTRL, 0)->ptr, "type", V3D_VIEW_PANRIGHT);
RNA_enum_set(WM_keymap_add_item(keymap, "VIEW3D_OT_view_pan", WHEELDOWNMOUSE, KM_PRESS, KM_CTRL, 0)->ptr, "type", V3D_VIEW_PANLEFT);
@@ -309,8 +313,8 @@ void view3d_keymap(wmKeyConfig *keyconf)
RNA_enum_set(WM_keymap_add_item(keymap, "VIEW3D_OT_view_orbit", WHEELUPMOUSE, KM_PRESS, KM_SHIFT | KM_ALT, 0)->ptr, "type", V3D_VIEW_STEPUP);
RNA_enum_set(WM_keymap_add_item(keymap, "VIEW3D_OT_view_orbit", WHEELDOWNMOUSE, KM_PRESS, KM_SHIFT | KM_ALT, 0)->ptr, "type", V3D_VIEW_STEPDOWN);
- RNA_float_set(WM_keymap_add_item(keymap, "VIEW3D_OT_view_roll", WHEELUPMOUSE, KM_PRESS, KM_CTRL | KM_SHIFT, 0)->ptr, "angle", M_PI / -12);
- RNA_float_set(WM_keymap_add_item(keymap, "VIEW3D_OT_view_roll", WHEELDOWNMOUSE, KM_PRESS, KM_CTRL | KM_SHIFT, 0)->ptr, "angle", M_PI / 12);
+ RNA_enum_set(WM_keymap_add_item(keymap, "VIEW3D_OT_view_roll", WHEELUPMOUSE, KM_PRESS, KM_CTRL | KM_SHIFT, 0)->ptr, "type", V3D_VIEW_STEPLEFT);
+ RNA_enum_set(WM_keymap_add_item(keymap, "VIEW3D_OT_view_roll", WHEELDOWNMOUSE, KM_PRESS, KM_CTRL | KM_SHIFT, 0)->ptr, "type", V3D_VIEW_STEPRIGHT);
/* active aligned, replaces '*' key in 2.4x */
kmi = WM_keymap_add_item(keymap, "VIEW3D_OT_viewnumpad", PAD1, KM_PRESS, KM_SHIFT, 0);
@@ -343,8 +347,8 @@ void view3d_keymap(wmKeyConfig *keyconf)
WM_keymap_add_item(keymap, "VIEW3D_OT_ndof_all", NDOF_MOTION, 0, KM_CTRL | KM_SHIFT, 0);
kmi = WM_keymap_add_item(keymap, "VIEW3D_OT_view_selected", NDOF_BUTTON_FIT, KM_PRESS, 0, 0);
RNA_boolean_set(kmi->ptr, "use_all_regions", false);
- RNA_float_set(WM_keymap_add_item(keymap, "VIEW3D_OT_view_roll", NDOF_BUTTON_ROLL_CCW, KM_PRESS, 0, 0)->ptr, "angle", M_PI / -2);
- RNA_float_set(WM_keymap_add_item(keymap, "VIEW3D_OT_view_roll", NDOF_BUTTON_ROLL_CW, KM_PRESS, 0, 0)->ptr, "angle", M_PI / 2);
+ RNA_float_set(WM_keymap_add_item(keymap, "VIEW3D_OT_view_roll", NDOF_BUTTON_ROLL_CCW, KM_PRESS, 0, 0)->ptr, "angle", -M_PI_2);
+ RNA_float_set(WM_keymap_add_item(keymap, "VIEW3D_OT_view_roll", NDOF_BUTTON_ROLL_CW, KM_PRESS, 0, 0)->ptr, "angle", M_PI_2);
RNA_enum_set(WM_keymap_add_item(keymap, "VIEW3D_OT_viewnumpad", NDOF_BUTTON_FRONT, KM_PRESS, 0, 0)->ptr, "type", RV3D_VIEW_FRONT);
diff --git a/source/blender/editors/space_view3d/view3d_project.c b/source/blender/editors/space_view3d/view3d_project.c
index 75c1d9dcd22..ba0626c58ea 100644
--- a/source/blender/editors/space_view3d/view3d_project.c
+++ b/source/blender/editors/space_view3d/view3d_project.c
@@ -497,7 +497,7 @@ void ED_view3d_win_to_3d(const ARegion *ar, const float depth_pt[3], const float
float dy = (2.0f * mval[1] / (float)ar->winy) - 1.0f;
if (rv3d->persp == RV3D_CAMOB) {
/* ortho camera needs offset applied */
- const float zoomfac = BKE_screen_view3d_zoom_to_fac((float)rv3d->camzoom) * 4.0f;
+ const float zoomfac = BKE_screen_view3d_zoom_to_fac(rv3d->camzoom) * 4.0f;
dx += rv3d->camdx * zoomfac;
dy += rv3d->camdy * zoomfac;
}
@@ -605,6 +605,14 @@ void ED_view3d_ob_project_mat_get(const RegionView3D *rv3d, Object *ob, float pm
mul_m4_m4m4(pmat, (float (*)[4])rv3d->winmat, vmat);
}
+void ED_view3d_ob_project_mat_get_from_obmat(const RegionView3D *rv3d, float obmat[4][4], float pmat[4][4])
+{
+ float vmat[4][4];
+
+ mul_m4_m4m4(vmat, (float (*)[4])rv3d->viewmat, obmat);
+ mul_m4_m4m4(pmat, (float (*)[4])rv3d->winmat, vmat);
+}
+
/**
* Uses window coordinates (x,y) and depth component z to find a point in
* modelspace */
diff --git a/source/blender/editors/space_view3d/view3d_ruler.c b/source/blender/editors/space_view3d/view3d_ruler.c
index 9d0a70ea9d0..98b1e846c70 100644
--- a/source/blender/editors/space_view3d/view3d_ruler.c
+++ b/source/blender/editors/space_view3d/view3d_ruler.c
@@ -70,7 +70,7 @@
* \param r_co hit location.
* \param r_no hit normal (optional).
* \param co_ss Screenspace coordinate.
- * \param use_depth Snap to the closest element, use when using more then one snap type.
+ * \param use_depth Snap to the closest element, use when using more than one snap type.
* \param use_obedit Use editmode cage.
* \param use_vert Snap to verts.
* \param use_edge Snap to edges.
@@ -122,12 +122,10 @@ static bool ED_view3d_snap_ray(bContext *C, float r_co[3],
bool ret;
Scene *scene = CTX_data_scene(C);
- View3D *v3d = CTX_wm_view3d(C);
- ARegion *ar = CTX_wm_region(C);
struct Object *obedit = CTX_data_edit_object(C);
/* try snap edge, then face if it fails */
- ret = snapObjectsRayEx(scene, NULL, v3d, ar, obedit, SCE_SNAP_MODE_FACE,
+ ret = snapObjectsRayEx(scene, NULL, NULL, NULL, obedit, SCE_SNAP_MODE_FACE,
NULL, NULL,
ray_start, ray_normal, &ray_dist,
NULL, &dist_px, r_co, r_no_dummy, SNAP_ALL);
@@ -190,8 +188,8 @@ typedef struct RulerInfo {
/* wm state */
wmWindow *win;
ScrArea *sa;
- ARegion *ar;
void *draw_handle_pixel;
+ ARegion *ar; /* re-assigned every modal update */
} RulerInfo;
/* -------------------------------------------------------------------- */
@@ -438,7 +436,7 @@ static void ruler_info_draw_pixel(const struct bContext *C, ARegion *ar, void *a
UnitSettings *unit = &scene->unit;
RulerItem *ruler_item;
RulerInfo *ruler_info = arg;
- RegionView3D *rv3d = ruler_info->ar->regiondata;
+ RegionView3D *rv3d = ar->regiondata;
// ARegion *ar = ruler_info->ar;
const float cap_size = 4.0f;
const float bg_margin = 4.0f * U.pixelsize;
@@ -552,10 +550,11 @@ static void ruler_info_draw_pixel(const struct bContext *C, ARegion *ar, void *a
/* draw text (bg) */
glColor4ubv(color_back);
- uiSetRoundBox(UI_CNR_ALL);
- uiRoundBox(pos[0] - bg_margin, pos[1] - bg_margin,
- pos[0] + bg_margin + numstr_size[0], pos[1] + bg_margin + numstr_size[1],
- bg_radius);
+ UI_draw_roundbox_corner_set(UI_CNR_ALL);
+ UI_draw_roundbox(
+ pos[0] - bg_margin, pos[1] - bg_margin,
+ pos[0] + bg_margin + numstr_size[0], pos[1] + bg_margin + numstr_size[1],
+ bg_radius);
/* draw text */
glColor3ubv(color_text);
BLF_position(blf_mono_font, pos[0], pos[1], 0.0f);
@@ -641,8 +640,8 @@ static void ruler_info_draw_pixel(const struct bContext *C, ARegion *ar, void *a
/* draw text (bg) */
glColor4ubv(color_back);
- uiSetRoundBox(UI_CNR_ALL);
- uiRoundBox(pos[0] - bg_margin, pos[1] - bg_margin,
+ UI_draw_roundbox_corner_set(UI_CNR_ALL);
+ UI_draw_roundbox(pos[0] - bg_margin, pos[1] - bg_margin,
pos[0] + bg_margin + numstr_size[0], pos[1] + bg_margin + numstr_size[1],
bg_radius);
/* draw text */
@@ -801,12 +800,13 @@ static int view3d_ruler_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSE
ruler_info->win = win;
ruler_info->sa = sa;
- ruler_info->ar = ar;
ruler_info->draw_handle_pixel = ED_region_draw_cb_activate(ar->type, ruler_info_draw_pixel,
ruler_info, REGION_DRAW_POST_PIXEL);
view3d_ruler_header_update(sa);
+ op->flag |= OP_IS_MODAL_CURSOR_REGION;
+
WM_cursor_modal_set(win, BC_CROSSCURSOR);
WM_event_add_modal_handler(C, op);
@@ -827,16 +827,18 @@ static int view3d_ruler_modal(bContext *C, wmOperator *op, const wmEvent *event)
bool do_draw = false;
int exit_code = OPERATOR_RUNNING_MODAL;
RulerInfo *ruler_info = op->customdata;
- ScrArea *sa = ruler_info->sa;
- ARegion *ar = ruler_info->ar;
+ ScrArea *sa = CTX_wm_area(C);
+ ARegion *ar = CTX_wm_region(C);
RegionView3D *rv3d = ar->regiondata;
- /* its possible to change spaces while running the operator [#34894] */
- if (UNLIKELY(ar != CTX_wm_region(C))) {
+ /* its possible to change spaces while running the operator [#34894] */
+ if (UNLIKELY(sa != ruler_info->sa)) {
exit_code = OPERATOR_FINISHED;
goto exit;
}
+ ruler_info->ar = ar;
+
switch (event->type) {
case LEFTMOUSE:
if (event->val == KM_RELEASE) {
@@ -1022,6 +1024,13 @@ static int view3d_ruler_modal(bContext *C, wmOperator *op, const wmEvent *event)
}
+ if (ruler_info->state == RULER_STATE_DRAG) {
+ op->flag &= ~OP_IS_MODAL_CURSOR_REGION;
+ }
+ else {
+ op->flag |= OP_IS_MODAL_CURSOR_REGION;
+ }
+
if (do_draw) {
view3d_ruler_header_update(sa);
diff --git a/source/blender/editors/space_view3d/view3d_select.c b/source/blender/editors/space_view3d/view3d_select.c
index ad716d1a98f..69e354d87c7 100644
--- a/source/blender/editors/space_view3d/view3d_select.c
+++ b/source/blender/editors/space_view3d/view3d_select.c
@@ -93,7 +93,6 @@
#include "ED_mball.h"
#include "UI_interface.h"
-#include "UI_resources.h"
#include "view3d_intern.h" /* own include */
@@ -726,7 +725,7 @@ static void do_lasso_select_meshobject__doSelectVert(void *userData, MVert *mv,
}
static void do_lasso_select_paintvert(ViewContext *vc, const int mcords[][2], short moves, bool extend, bool select)
{
- const int use_zbuf = (vc->v3d->flag & V3D_ZBUF_SELECT);
+ const bool use_zbuf = (vc->v3d->flag & V3D_ZBUF_SELECT) != 0;
Object *ob = vc->obact;
Mesh *me = ob->data;
rcti rect;
@@ -1143,7 +1142,7 @@ static Base *object_mouse_select_menu(bContext *C, ViewContext *vc, unsigned int
const char *name = ob->id.name + 2;
BLI_strncpy(object_mouse_select_menu_data[i].idname, name, MAX_ID_NAME - 2);
- object_mouse_select_menu_data[i].icon = uiIconFromID(&ob->id);
+ object_mouse_select_menu_data[i].icon = UI_icon_from_id(&ob->id);
}
{
@@ -1181,20 +1180,23 @@ static short selectbuffer_ret_hits_15(unsigned int *UNUSED(buffer), const short
static short selectbuffer_ret_hits_9(unsigned int *buffer, const short hits15, const short hits9)
{
const int offs = 4 * hits15;
- memcpy(buffer, buffer + offs, 4 * hits9);
+ memcpy(buffer, buffer + offs, 4 * hits9 * sizeof(unsigned int));
return hits9;
}
static short selectbuffer_ret_hits_5(unsigned int *buffer, const short hits15, const short hits9, const short hits5)
{
const int offs = 4 * hits15 + 4 * hits9;
- memcpy(buffer, buffer + offs, 4 * hits5);
+ memcpy(buffer, buffer + offs, 4 * hits5 * sizeof(unsigned int));
return hits5;
}
/* we want a select buffer with bones, if there are... */
/* so check three selection levels and compare */
-static short mixed_bones_object_selectbuffer(ViewContext *vc, unsigned int *buffer, const int mval[2], bool *p_do_nearest, bool enumerate)
+static short mixed_bones_object_selectbuffer(
+ ViewContext *vc, unsigned int *buffer, const int mval[2],
+ bool use_cycle, bool enumerate,
+ bool *r_do_nearest)
{
rcti rect;
int offs;
@@ -1205,16 +1207,24 @@ static short mixed_bones_object_selectbuffer(ViewContext *vc, unsigned int *buff
View3D *v3d = vc->v3d;
/* define if we use solid nearest select or not */
- if (v3d->drawtype > OB_WIRE) {
- do_nearest = true;
- if (len_manhattan_v2v2_int(mval, last_mval) < 3) {
- do_nearest = false;
+ if (use_cycle) {
+ if (v3d->drawtype > OB_WIRE) {
+ do_nearest = true;
+ if (len_manhattan_v2v2_int(mval, last_mval) < 3) {
+ do_nearest = false;
+ }
+ }
+ copy_v2_v2_int(last_mval, mval);
+ }
+ else {
+ if (v3d->drawtype > OB_WIRE) {
+ do_nearest = true;
}
}
- copy_v2_v2_int(last_mval, mval);
- if (p_do_nearest)
- *p_do_nearest = do_nearest;
+ if (r_do_nearest) {
+ *r_do_nearest = do_nearest;
+ }
do_nearest = do_nearest && !enumerate;
@@ -1346,7 +1356,7 @@ Base *ED_view3d_give_base_under_cursor(bContext *C, const int mval[2])
{
ViewContext vc;
Base *basact = NULL;
- unsigned int buffer[4 * MAXPICKBUF];
+ unsigned int buffer[MAXPICKBUF];
int hits;
bool do_nearest;
@@ -1354,7 +1364,7 @@ Base *ED_view3d_give_base_under_cursor(bContext *C, const int mval[2])
view3d_operator_needs_opengl(C);
view3d_set_viewcontext(C, &vc);
- hits = mixed_bones_object_selectbuffer(&vc, buffer, mval, &do_nearest, false);
+ hits = mixed_bones_object_selectbuffer(&vc, buffer, mval, false, false, &do_nearest);
if (hits > 0) {
const bool has_bones = selectbuffer_has_bones(buffer, hits);
@@ -1444,12 +1454,12 @@ static bool mouse_select(bContext *C, const int mval[2],
}
}
else {
- unsigned int buffer[4 * MAXPICKBUF];
+ unsigned int buffer[MAXPICKBUF];
bool do_nearest;
/* if objects have posemode set, the bones are in the same selection buffer */
- hits = mixed_bones_object_selectbuffer(&vc, buffer, mval, &do_nearest, enumerate);
+ hits = mixed_bones_object_selectbuffer(&vc, buffer, mval, true, enumerate, &do_nearest);
if (hits > 0) {
/* note: bundles are handling in the same way as bones */
@@ -1642,39 +1652,48 @@ static void do_paintvert_box_select__doSelectVert(void *userData, MVert *mv, con
}
static int do_paintvert_box_select(ViewContext *vc, rcti *rect, bool select, bool extend)
{
- const int use_zbuf = (vc->v3d->flag & V3D_ZBUF_SELECT);
+ const bool use_zbuf = (vc->v3d->flag & V3D_ZBUF_SELECT) != 0;
Mesh *me;
MVert *mvert;
struct ImBuf *ibuf;
unsigned int *rt;
int a, index;
char *selar;
- int sx = BLI_rcti_size_x(rect) + 1;
- int sy = BLI_rcti_size_y(rect) + 1;
+ const int size[2] = {
+ BLI_rcti_size_x(rect) + 1,
+ BLI_rcti_size_y(rect) + 1};
me = vc->obact->data;
- if (me == NULL || me->totvert == 0 || sx * sy <= 0)
+ if ((me == NULL) || (me->totvert == 0) || (size[0] * size[1] <= 0)) {
return OPERATOR_CANCELLED;
-
+ }
if (extend == false && select)
paintvert_deselect_all_visible(vc->obact, SEL_DESELECT, false);
if (use_zbuf) {
selar = MEM_callocN(me->totvert + 1, "selar");
- view3d_validate_backbuf(vc);
+ ED_view3d_backbuf_validate(vc);
- ibuf = IMB_allocImBuf(sx, sy, 32, IB_rect);
+ ibuf = IMB_allocImBuf(size[0], size[1], 32, IB_rect);
rt = ibuf->rect;
- glReadPixels(rect->xmin + vc->ar->winrct.xmin, rect->ymin + vc->ar->winrct.ymin, sx, sy, GL_RGBA, GL_UNSIGNED_BYTE, ibuf->rect);
- if (ENDIAN_ORDER == B_ENDIAN) IMB_convert_rgba_to_abgr(ibuf);
+ glReadPixels(
+ rect->xmin + vc->ar->winrct.xmin,
+ rect->ymin + vc->ar->winrct.ymin,
+ size[0], size[1], GL_RGBA, GL_UNSIGNED_BYTE, ibuf->rect);
+ if (ENDIAN_ORDER == B_ENDIAN) {
+ IMB_convert_rgba_to_abgr(ibuf);
+ }
+ WM_framebuffer_to_index_array(ibuf->rect, size[0] * size[1]);
- a = sx * sy;
+ a = size[0] * size[1];
while (a--) {
if (*rt) {
- index = WM_framebuffer_to_index(*rt);
- if (index <= me->totvert) selar[index] = 1;
+ index = *rt;
+ if (index <= me->totvert) {
+ selar[index] = 1;
+ }
}
rt++;
}
@@ -1877,7 +1896,7 @@ static int do_meta_box_select(ViewContext *vc, rcti *rect, bool select, bool ext
MetaElem *ml;
int a;
- unsigned int buffer[4 * MAXPICKBUF];
+ unsigned int buffer[MAXPICKBUF];
short hits;
hits = view3d_opengl_select(vc, buffer, MAXPICKBUF, rect, false);
@@ -1911,7 +1930,7 @@ static int do_armature_box_select(ViewContext *vc, rcti *rect, bool select, bool
EditBone *ebone;
int a;
- unsigned int buffer[4 * MAXPICKBUF];
+ unsigned int buffer[MAXPICKBUF];
short hits;
hits = view3d_opengl_select(vc, buffer, MAXPICKBUF, rect, false);
@@ -1972,7 +1991,7 @@ static int do_armature_box_select(ViewContext *vc, rcti *rect, bool select, bool
ED_armature_sync_selection(arm->edbo);
- return OPERATOR_CANCELLED;
+ return hits > 0 ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
}
static int do_object_pose_box_select(bContext *C, ViewContext *vc, rcti *rect, bool select, bool extend)
@@ -2007,8 +2026,8 @@ static int do_object_pose_box_select(bContext *C, ViewContext *vc, rcti *rect, b
}
/* selection buffer now has bones potentially too, so we add MAXPICKBUF */
- vbuffer = MEM_mallocN(4 * (totobj + MAXPICKBUF) * sizeof(unsigned int), "selection buffer");
- hits = view3d_opengl_select(vc, vbuffer, 4 * (totobj + MAXPICKBUF), rect, false);
+ vbuffer = MEM_mallocN(4 * (totobj + MAXPICKELEMS) * sizeof(unsigned int), "selection buffer");
+ hits = view3d_opengl_select(vc, vbuffer, 4 * (totobj + MAXPICKELEMS), rect, false);
/*
* LOGIC NOTES (theeth):
* The buffer and ListBase have the same relative order, which makes the selection
@@ -2186,7 +2205,7 @@ void VIEW3D_OT_select_border(wmOperatorType *ot)
static bool mouse_weight_paint_vertex_select(bContext *C, const int mval[2], bool extend, bool deselect, bool toggle, Object *obact)
{
View3D *v3d = CTX_wm_view3d(C);
- const int use_zbuf = (v3d->flag & V3D_ZBUF_SELECT);
+ const bool use_zbuf = (v3d->flag & V3D_ZBUF_SELECT) != 0;
Mesh *me = obact->data; /* already checked for NULL */
unsigned int index = 0;
@@ -2454,7 +2473,7 @@ static void paint_vertsel_circle_select_doSelectVert(void *userData, MVert *mv,
}
static void paint_vertsel_circle_select(ViewContext *vc, const bool select, const int mval[2], float rad)
{
- const int use_zbuf = (vc->v3d->flag & V3D_ZBUF_SELECT);
+ const bool use_zbuf = (vc->v3d->flag & V3D_ZBUF_SELECT) != 0;
Object *ob = vc->obact;
Mesh *me = ob->data;
bool bbsel;
diff --git a/source/blender/editors/space_view3d/view3d_snap.c b/source/blender/editors/space_view3d/view3d_snap.c
index 8e6deeddc39..8bb84d00c83 100644
--- a/source/blender/editors/space_view3d/view3d_snap.c
+++ b/source/blender/editors/space_view3d/view3d_snap.c
@@ -31,20 +31,19 @@
#include "DNA_armature_types.h"
-#include "DNA_curve_types.h"
#include "DNA_object_types.h"
#include "BLI_blenlib.h"
#include "BLI_utildefines.h"
#include "BLI_math.h"
+#include "BKE_action.h"
#include "BKE_armature.h"
#include "BKE_context.h"
#include "BKE_depsgraph.h"
-#include "BKE_lattice.h"
+#include "BKE_main.h"
#include "BKE_mball.h"
#include "BKE_object.h"
-#include "BKE_editmesh.h"
#include "BKE_tracking.h"
#include "WM_api.h"
@@ -53,6 +52,7 @@
#include "RNA_access.h"
#include "RNA_define.h"
+#include "ED_object.h"
#include "ED_transverts.h"
#include "ED_keyframing.h"
#include "ED_screen.h"
@@ -60,6 +60,7 @@
#include "view3d_intern.h"
static bool snap_curs_to_sel_ex(bContext *C, float cursor[3]);
+static bool snap_calc_active_center(bContext *C, const bool select_only, float r_center[3]);
/* *********************** operators ******************** */
@@ -205,8 +206,9 @@ void VIEW3D_OT_snap_selected_to_grid(wmOperatorType *ot)
static int snap_sel_to_curs_exec(bContext *C, wmOperator *op)
{
- Object *obedit = CTX_data_edit_object(C);
Scene *scene = CTX_data_scene(C);
+ Object *obedit = CTX_data_edit_object(C);
+ Object *obact = CTX_data_active_object(C);
View3D *v3d = CTX_wm_view3d(C);
TransVertStore tvs = {NULL};
TransVert *tv;
@@ -221,7 +223,14 @@ static int snap_sel_to_curs_exec(bContext *C, wmOperator *op)
cursor_global = ED_view3d_cursor3d_get(scene, v3d);
if (use_offset) {
- snap_curs_to_sel_ex(C, center_global);
+ if ((v3d && v3d->around == V3D_ACTIVE) &&
+ snap_calc_active_center(C, true, center_global))
+ {
+ /* pass */
+ }
+ else {
+ snap_curs_to_sel_ex(C, center_global);
+ }
sub_v3_v3v3(offset_global, cursor_global, center_global);
}
@@ -260,59 +269,98 @@ static int snap_sel_to_curs_exec(bContext *C, wmOperator *op)
ED_transverts_update_obedit(&tvs, obedit);
ED_transverts_free(&tvs);
}
- else {
+ else if (obact && (obact->mode & OB_MODE_POSE)) {
struct KeyingSet *ks = ANIM_get_keyingset_for_autokeying(scene, ANIM_KS_LOCATION_ID);
- CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects)
- {
- if (ob->mode & OB_MODE_POSE) {
- bPoseChannel *pchan;
- bArmature *arm = ob->data;
- float cursor_local[3];
-
- invert_m4_m4(ob->imat, ob->obmat);
- mul_v3_m4v3(cursor_local, ob->imat, cursor_global);
+ bPoseChannel *pchan;
+ bArmature *arm = obact->data;
+ float cursor_local[3];
- for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
- if (pchan->bone->flag & BONE_SELECTED) {
- if (PBONE_VISIBLE(arm, pchan->bone)) {
- if ((pchan->bone->flag & BONE_CONNECTED) == 0) {
- /* Get position in pchan (pose) space. */
- float cursor_pose[3];
+ invert_m4_m4(obact->imat, obact->obmat);
+ mul_v3_m4v3(cursor_local, obact->imat, cursor_global);
- if (use_offset) {
- mul_v3_m4v3(cursor_pose, ob->obmat, pchan->pose_mat[3]);
- add_v3_v3(cursor_pose, offset_global);
+ for (pchan = obact->pose->chanbase.first; pchan; pchan = pchan->next) {
+ if ((pchan->bone->flag & BONE_SELECTED) &&
+ (PBONE_VISIBLE(arm, pchan->bone)) &&
+ /* if the bone has a parent and is connected to the parent,
+ * don't do anything - will break chain unless we do auto-ik.
+ */
+ (pchan->bone->flag & BONE_CONNECTED) == 0)
+ {
+ pchan->bone->flag |= BONE_TRANSFORM;
+ }
+ else {
+ pchan->bone->flag &= ~BONE_TRANSFORM;
+ }
+ }
- mul_m4_v3(ob->imat, cursor_pose);
- BKE_armature_loc_pose_to_bone(pchan, cursor_pose, cursor_pose);
- }
- else {
- BKE_armature_loc_pose_to_bone(pchan, cursor_local, cursor_pose);
- }
+ for (pchan = obact->pose->chanbase.first; pchan; pchan = pchan->next) {
+ if ((pchan->bone->flag & BONE_TRANSFORM) &&
+ /* check that our parents not transformed (if we have one) */
+ ((pchan->bone->parent &&
+ BKE_armature_bone_flag_test_recursive(pchan->bone->parent, BONE_TRANSFORM)) == 0))
+ {
+ /* Get position in pchan (pose) space. */
+ float cursor_pose[3];
- /* copy new position */
- if ((pchan->protectflag & OB_LOCK_LOCX) == 0)
- pchan->loc[0] = cursor_pose[0];
- if ((pchan->protectflag & OB_LOCK_LOCY) == 0)
- pchan->loc[1] = cursor_pose[1];
- if ((pchan->protectflag & OB_LOCK_LOCZ) == 0)
- pchan->loc[2] = cursor_pose[2];
+ if (use_offset) {
+ mul_v3_m4v3(cursor_pose, obact->obmat, pchan->pose_mat[3]);
+ add_v3_v3(cursor_pose, offset_global);
- /* auto-keyframing */
- ED_autokeyframe_pchan(C, scene, ob, pchan, ks);
- }
- /* if the bone has a parent and is connected to the parent,
- * don't do anything - will break chain unless we do auto-ik.
- */
- }
- }
+ mul_m4_v3(obact->imat, cursor_pose);
+ BKE_armature_loc_pose_to_bone(pchan, cursor_pose, cursor_pose);
}
- ob->pose->flag |= (POSE_LOCKED | POSE_DO_UNLOCK);
-
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ else {
+ BKE_armature_loc_pose_to_bone(pchan, cursor_local, cursor_pose);
+ }
+
+ /* copy new position */
+ if ((pchan->protectflag & OB_LOCK_LOCX) == 0)
+ pchan->loc[0] = cursor_pose[0];
+ if ((pchan->protectflag & OB_LOCK_LOCY) == 0)
+ pchan->loc[1] = cursor_pose[1];
+ if ((pchan->protectflag & OB_LOCK_LOCZ) == 0)
+ pchan->loc[2] = cursor_pose[2];
+
+ /* auto-keyframing */
+ ED_autokeyframe_pchan(C, scene, obact, pchan, ks);
}
- else {
+ }
+
+ for (pchan = obact->pose->chanbase.first; pchan; pchan = pchan->next) {
+ pchan->bone->flag &= ~BONE_TRANSFORM;
+ }
+
+ obact->pose->flag |= (POSE_LOCKED | POSE_DO_UNLOCK);
+
+ DAG_id_tag_update(&obact->id, OB_RECALC_DATA);
+ }
+ else {
+ struct KeyingSet *ks = ANIM_get_keyingset_for_autokeying(scene, ANIM_KS_LOCATION_ID);
+ Main *bmain = CTX_data_main(C);
+
+ ListBase ctx_data_list;
+ CollectionPointerLink *ctx_ob;
+ Object *ob;
+
+ CTX_data_selected_editable_objects(C, &ctx_data_list);
+
+ /* reset flags */
+ for (ob = bmain->object.first; ob; ob = ob->id.next) {
+ ob->flag &= ~OB_DONE;
+ }
+
+ /* tag objects we're transforming */
+ for (ctx_ob = ctx_data_list.first; ctx_ob; ctx_ob = ctx_ob->next) {
+ ob = ctx_ob->ptr.data;
+ ob->flag |= OB_DONE;
+ }
+
+ for (ctx_ob = ctx_data_list.first; ctx_ob; ctx_ob = ctx_ob->next) {
+ ob = ctx_ob->ptr.data;
+
+ if ((ob->parent && BKE_object_flag_test_recursive(ob->parent, OB_DONE)) == 0) {
+
float cursor_parent[3]; /* parent-relative */
if (use_offset) {
@@ -323,11 +371,11 @@ static int snap_sel_to_curs_exec(bContext *C, wmOperator *op)
}
sub_v3_v3(cursor_parent, ob->obmat[3]);
-
+
if (ob->parent) {
float originmat[3][3];
BKE_object_where_is_calc_ex(scene, NULL, ob, originmat);
-
+
invert_m3_m3(imat, originmat);
mul_m3_v3(imat, cursor_parent);
}
@@ -344,7 +392,8 @@ static int snap_sel_to_curs_exec(bContext *C, wmOperator *op)
DAG_id_tag_update(&ob->id, OB_RECALC_OB);
}
}
- CTX_DATA_END;
+
+ BLI_freelistN(&ctx_data_list);
}
WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
@@ -592,45 +641,60 @@ void VIEW3D_OT_snap_cursor_to_selected(wmOperatorType *ot)
/* ********************************************** */
-static int snap_curs_to_active_exec(bContext *C, wmOperator *UNUSED(op))
+/* this could be exported to be a generic function
+ * see: calculateCenterActive */
+
+static bool snap_calc_active_center(bContext *C, const bool select_only, float r_center[3])
{
Object *obedit = CTX_data_edit_object(C);
- Object *obact = CTX_data_active_object(C);
- Scene *scene = CTX_data_scene(C);
- View3D *v3d = CTX_wm_view3d(C);
- float *curs;
-
- curs = ED_view3d_cursor3d_get(scene, v3d);
if (obedit) {
- if (obedit->type == OB_MESH) {
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
- /* check active */
- BMEditSelection ese;
-
- if (BM_select_history_active_get(em->bm, &ese)) {
- BM_editselection_center(&ese, curs);
- }
-
- mul_m4_v3(obedit->obmat, curs);
+ if (ED_object_editmode_calc_active_center(obedit, select_only, r_center)) {
+ mul_m4_v3(obedit->obmat, r_center);
+ return true;
}
- else if (obedit->type == OB_LATTICE) {
- BPoint *actbp = BKE_lattice_active_point_get(obedit->data);
+ }
+ else {
+ Object *ob = CTX_data_active_object(C);
- if (actbp) {
- copy_v3_v3(curs, actbp->vec);
- mul_m4_v3(obedit->obmat, curs);
+ if (ob) {
+ if (ob->mode & OB_MODE_POSE) {
+ bPoseChannel *pchan = BKE_pose_channel_active(ob);
+ if (pchan) {
+ if (!select_only || (pchan->bone->flag & BONE_SELECTED)) {
+ copy_v3_v3(r_center, pchan->pose_head);
+ mul_m4_v3(ob->obmat, r_center);
+ return true;
+ }
+ }
+ }
+ else {
+ if (!select_only || (ob->flag & SELECT)) {
+ copy_v3_v3(r_center, ob->obmat[3]);
+ return true;
+ }
}
}
}
+
+ return false;
+}
+
+static int snap_curs_to_active_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ Scene *scene = CTX_data_scene(C);
+ View3D *v3d = CTX_wm_view3d(C);
+ float *curs;
+
+ curs = ED_view3d_cursor3d_get(scene, v3d);
+
+ if (snap_calc_active_center(C, false, curs)) {
+ WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, v3d);
+ return OPERATOR_FINISHED;
+ }
else {
- if (obact) {
- copy_v3_v3(curs, obact->obmat[3]);
- }
+ return OPERATOR_CANCELLED;
}
-
- WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, v3d);
- return OPERATOR_FINISHED;
}
void VIEW3D_OT_snap_cursor_to_active(wmOperatorType *ot)
diff --git a/source/blender/editors/space_view3d/view3d_toolbar.c b/source/blender/editors/space_view3d/view3d_toolbar.c
index 3f7f12d2020..065c336d001 100644
--- a/source/blender/editors/space_view3d/view3d_toolbar.c
+++ b/source/blender/editors/space_view3d/view3d_toolbar.c
@@ -39,12 +39,11 @@
#include "MEM_guardedalloc.h"
-#include "BLI_math.h"
#include "BLI_blenlib.h"
#include "BLI_utildefines.h"
#include "BLI_ghash.h"
-#include "BLF_translation.h"
+#include "BLT_translation.h"
#include "BKE_context.h"
#include "BKE_screen.h"
@@ -118,7 +117,7 @@ static void view3d_panel_operator_redo(const bContext *C, Panel *pa)
uiLayoutSetEnabled(pa->layout, false);
/* note, blockfunc is a default but->func, use Handle func to allow button callbacks too */
- uiBlockSetHandleFunc(block, ED_undo_operator_repeat_cb_evt, op);
+ UI_block_func_handle_set(block, ED_undo_operator_repeat_cb_evt, op);
view3d_panel_operator_redo_operator(C, pa, op);
}
@@ -151,20 +150,19 @@ static void operator_call_cb(struct bContext *C, void *arg_listbase, void *arg2)
static void operator_search_cb(const struct bContext *C, void *UNUSED(arg), const char *str, uiSearchItems *items)
{
- GHashIterator *iter = WM_operatortype_iter();
+ GHashIterator iter;
- for (; !BLI_ghashIterator_done(iter); BLI_ghashIterator_step(iter)) {
- wmOperatorType *ot = BLI_ghashIterator_getValue(iter);
+ for (WM_operatortype_iter(&iter); !BLI_ghashIterator_done(&iter); BLI_ghashIterator_step(&iter)) {
+ wmOperatorType *ot = BLI_ghashIterator_getValue(&iter);
if (BLI_strcasestr(ot->name, str)) {
if (WM_operator_poll((bContext *)C, ot)) {
- if (false == uiSearchItemAdd(items, ot->name, ot, 0))
+ if (false == UI_search_item_add(items, ot->name, ot, 0))
break;
}
}
}
- BLI_ghashIterator_free(iter);
}
@@ -180,18 +178,18 @@ static uiBlock *tool_search_menu(bContext *C, ARegion *ar, void *arg_listbase)
/* clear initial search string, then all items show */
search[0] = 0;
- block = uiBeginBlock(C, ar, "_popup", UI_EMBOSS);
- uiBlockSetFlag(block, UI_BLOCK_LOOP | UI_BLOCK_REDRAW | UI_BLOCK_SEARCH_MENU);
+ block = UI_block_begin(C, ar, "_popup", UI_EMBOSS);
+ UI_block_flag_enable(block, UI_BLOCK_LOOP | UI_BLOCK_SEARCH_MENU);
/* fake button, it holds space for search items */
- uiDefBut(block, LABEL, 0, "", 10, 15, uiSearchBoxWidth(), uiSearchBoxHeight(), NULL, 0, 0, 0, 0, NULL);
+ uiDefBut(block, UI_BTYPE_LABEL, 0, "", 10, 15, UI_searchbox_size_x(), UI_searchbox_size_y(), NULL, 0, 0, 0, 0, NULL);
but = uiDefSearchBut(block, search, 0, ICON_VIEWZOOM, sizeof(search), 10, 0, 150, 19, 0, 0, "");
- uiButSetSearchFunc(but, operator_search_cb, arg_listbase, operator_call_cb, NULL);
+ UI_but_func_search_set(but, operator_search_cb, arg_listbase, operator_call_cb, NULL);
- uiBoundsBlock(block, 6);
- uiBlockSetDirection(block, UI_DOWN);
- uiEndBlock(C, block);
+ UI_block_bounds_set_normal(block, 6);
+ UI_block_direction_set(block, UI_DIR_DOWN);
+ UI_block_end(C, block);
wm_event_init_from_window(win, &event);
event.type = EVT_BUT_OPEN;
@@ -218,7 +216,7 @@ static void view3d_panel_tool_shelf(const bContext *C, Panel *pa)
CustomTool *ct;
for (ct = st->toolshelf.first; ct; ct = ct->next) {
- if (0 == strncmp(context, ct->context, OP_MAX_TYPENAME)) {
+ if (STREQLEN(context, ct->context, OP_MAX_TYPENAME)) {
col = uiLayoutColumn(pa->layout, true);
uiItemFullO(col, ct->opname, NULL, ICON_NONE, NULL, WM_OP_INVOKE_REGION_WIN, 0);
}
@@ -236,7 +234,7 @@ void view3d_toolshelf_register(ARegionType *art)
pt = MEM_callocN(sizeof(PanelType), "spacetype view3d panel tools");
strcpy(pt->idname, "VIEW3D_PT_tool_shelf");
strcpy(pt->label, N_("Tool Shelf"));
- strcpy(pt->translation_context, BLF_I18NCONTEXT_DEFAULT_BPYRNA);
+ strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
pt->draw = view3d_panel_tool_shelf;
BLI_addtail(&art->paneltypes, pt);
}
@@ -248,7 +246,7 @@ void view3d_tool_props_register(ARegionType *art)
pt = MEM_callocN(sizeof(PanelType), "spacetype view3d panel last operator");
strcpy(pt->idname, "VIEW3D_PT_last_operator");
strcpy(pt->label, N_("Operator"));
- strcpy(pt->translation_context, BLF_I18NCONTEXT_DEFAULT_BPYRNA);
+ strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
pt->draw_header = view3d_panel_operator_redo_header;
pt->draw = view3d_panel_operator_redo;
BLI_addtail(&art->paneltypes, pt);
diff --git a/source/blender/editors/space_view3d/view3d_view.c b/source/blender/editors/space_view3d/view3d_view.c
index 7d3f7ce282e..0f05f4e52dd 100644
--- a/source/blender/editors/space_view3d/view3d_view.c
+++ b/source/blender/editors/space_view3d/view3d_view.c
@@ -37,9 +37,7 @@
#include "BLI_math.h"
#include "BLI_rect.h"
-#include "BLI_listbase.h"
#include "BLI_utildefines.h"
-#include "BLI_callbacks.h"
#include "BKE_anim.h"
#include "BKE_action.h"
@@ -51,11 +49,11 @@
#include "BKE_main.h"
#include "BKE_report.h"
#include "BKE_scene.h"
+#include "BKE_screen.h"
#include "BIF_gl.h"
#include "BIF_glutil.h"
-#include "GPU_draw.h"
#include "GPU_select.h"
#include "WM_api.h"
@@ -64,14 +62,16 @@
#include "ED_screen.h"
#include "ED_armature.h"
-#include "RE_engine.h"
#ifdef WITH_GAMEENGINE
-#include "BL_System.h"
+# include "BLI_listbase.h"
+# include "BLI_callbacks.h"
+
+# include "GPU_draw.h"
+
+# include "BL_System.h"
#endif
-#include "RNA_access.h"
-#include "RNA_define.h"
#include "view3d_intern.h" /* own include */
@@ -137,6 +137,9 @@ struct SmoothView3DStore {
struct SmoothView3DState org; /* original */
bool to_camera;
+
+ /* When smooth-view is enabled, store the 'rv3d->view' here,
+ * assign back when the view motion is completed. */
char org_view;
double time_allowed;
@@ -180,12 +183,12 @@ void ED_view3d_smooth_view_ex(
/* if smoothview runs multiple times... */
if (rv3d->sms == NULL) {
view3d_smooth_view_state_backup(&sms.org, v3d, rv3d);
- sms.org_view = rv3d->view;
}
else {
sms.org = rv3d->sms->org;
- sms.org_view = rv3d->sms->org_view;
}
+ sms.org_view = rv3d->view;
+
/* sms.to_camera = false; */ /* initizlized to zero anyway */
/* note on camera locking, this is a little confusing but works ok.
@@ -356,6 +359,7 @@ static int view3d_smoothview_invoke(bContext *C, wmOperator *UNUSED(op), const w
view3d_smooth_view_state_restore(&sms->dst, v3d, rv3d);
ED_view3d_camera_lock_sync(v3d, rv3d);
+ ED_view3d_camera_lock_autokey(v3d, rv3d, C, true, true);
}
if ((rv3d->viewlock & RV3D_LOCKED) == 0) {
@@ -382,6 +386,10 @@ static int view3d_smoothview_invoke(bContext *C, wmOperator *UNUSED(op), const w
v3d->lens = sms->dst.lens * step + sms->src.lens * step_inv;
ED_view3d_camera_lock_sync(v3d, rv3d);
+ if (ED_screen_animation_playing(CTX_wm_manager(C))) {
+ ED_view3d_camera_lock_autokey(v3d, rv3d, C, true, true);
+ }
+
}
if (rv3d->viewlock & RV3D_BOXVIEW)
@@ -492,26 +500,22 @@ static int view3d_camera_to_view_selected_exec(bContext *C, wmOperator *op)
Object *camera_ob = v3d ? v3d->camera : scene->camera;
float r_co[3]; /* the new location to apply */
+ float r_scale; /* only for ortho cameras */
if (camera_ob == NULL) {
BKE_report(op->reports, RPT_ERROR, "No active camera");
return OPERATOR_CANCELLED;
}
- else if (camera_ob->type != OB_CAMERA) {
- BKE_report(op->reports, RPT_ERROR, "Object not a camera");
- return OPERATOR_CANCELLED;
- }
- else if (((Camera *)camera_ob->data)->type == R_ORTHO) {
- BKE_report(op->reports, RPT_ERROR, "Orthographic cameras not supported");
- return OPERATOR_CANCELLED;
- }
/* this function does all the important stuff */
- if (BKE_camera_view_frame_fit_to_scene(scene, v3d, camera_ob, r_co)) {
-
+ if (BKE_camera_view_frame_fit_to_scene(scene, v3d, camera_ob, r_co, &r_scale)) {
ObjectTfmProtectedChannels obtfm;
float obmat_new[4][4];
+ if ((camera_ob->type == OB_CAMERA) && (((Camera *)camera_ob->data)->type == CAM_ORTHO)) {
+ ((Camera *)camera_ob->data)->ortho_scale = r_scale;
+ }
+
copy_m4_m4(obmat_new, camera_ob->obmat);
copy_v3_v3(obmat_new[3], r_co);
@@ -609,6 +613,20 @@ void VIEW3D_OT_object_as_camera(wmOperatorType *ot)
/* ********************************** */
+void ED_view3d_clipping_calc_from_boundbox(float clip[4][4], const BoundBox *bb, const bool is_flip)
+{
+ int val;
+
+ for (val = 0; val < 4; val++) {
+ normal_tri_v3(clip[val], bb->vec[val], bb->vec[val == 3 ? 0 : val + 1], bb->vec[val + 4]);
+ if (UNLIKELY(is_flip)) {
+ negate_v3(clip[val]);
+ }
+
+ clip[val][3] = -dot_v3v3(clip[val], bb->vec[val]);
+ }
+}
+
void ED_view3d_clipping_calc(BoundBox *bb, float planes[4][4], bglMats *mats, const rcti *rect)
{
float modelview[4][4];
@@ -644,16 +662,7 @@ void ED_view3d_clipping_calc(BoundBox *bb, float planes[4][4], bglMats *mats, co
((float *)modelview)[a] = mats->modelview[a];
flip_sign = is_negative_m4(modelview);
- /* then plane equations */
- for (val = 0; val < 4; val++) {
-
- normal_tri_v3(planes[val], bb->vec[val], bb->vec[val == 3 ? 0 : val + 1], bb->vec[val + 4]);
-
- if (flip_sign)
- negate_v3(planes[val]);
-
- planes[val][3] = -dot_v3v3(planes[val], bb->vec[val]);
- }
+ ED_view3d_clipping_calc_from_boundbox(planes, bb, flip_sign);
}
static bool view3d_boundbox_clip_m4(const BoundBox *bb, float persmatob[4][4])
@@ -683,7 +692,7 @@ static bool view3d_boundbox_clip_m4(const BoundBox *bb, float persmatob[4][4])
return false;
}
-bool ED_view3d_boundbox_clip_ex(RegionView3D *rv3d, const BoundBox *bb, float obmat[4][4])
+bool ED_view3d_boundbox_clip_ex(const RegionView3D *rv3d, const BoundBox *bb, float obmat[4][4])
{
/* return 1: draw */
@@ -692,7 +701,7 @@ bool ED_view3d_boundbox_clip_ex(RegionView3D *rv3d, const BoundBox *bb, float ob
if (bb == NULL) return true;
if (bb->flag & BOUNDBOX_DISABLED) return true;
- mul_m4_m4m4(persmatob, rv3d->persmat, obmat);
+ mul_m4_m4m4(persmatob, (float(*)[4])rv3d->persmat, obmat);
return view3d_boundbox_clip_m4(bb, persmatob);
}
@@ -705,7 +714,7 @@ bool ED_view3d_boundbox_clip(RegionView3D *rv3d, const BoundBox *bb)
return view3d_boundbox_clip_m4(bb, rv3d->persmatob);
}
-float ED_view3d_depth_read_cached(ViewContext *vc, int x, int y)
+float ED_view3d_depth_read_cached(const ViewContext *vc, int x, int y)
{
ViewDepths *vd = vc->rv3d->depths;
@@ -724,16 +733,19 @@ void ED_view3d_depth_tag_update(RegionView3D *rv3d)
rv3d->depths->damaged = true;
}
-void ED_view3d_dist_range_get(struct View3D *v3d,
- float r_dist_range[2])
+void ED_view3d_dist_range_get(
+ const View3D *v3d,
+ float r_dist_range[2])
{
r_dist_range[0] = v3d->grid * 0.001f;
r_dist_range[1] = v3d->far * 10.0f;
}
/* copies logic of get_view3d_viewplane(), keep in sync */
-bool ED_view3d_clip_range_get(View3D *v3d, RegionView3D *rv3d, float *r_clipsta, float *r_clipend,
- const bool use_ortho_factor)
+bool ED_view3d_clip_range_get(
+ const View3D *v3d, const RegionView3D *rv3d,
+ float *r_clipsta, float *r_clipend,
+ const bool use_ortho_factor)
{
CameraParams params;
@@ -753,8 +765,9 @@ bool ED_view3d_clip_range_get(View3D *v3d, RegionView3D *rv3d, float *r_clipsta,
}
/* also exposed in previewrender.c */
-bool ED_view3d_viewplane_get(View3D *v3d, RegionView3D *rv3d, int winx, int winy,
- rctf *r_viewplane, float *r_clipsta, float *r_clipend, float *r_pixsize)
+bool ED_view3d_viewplane_get(
+ const View3D *v3d, const RegionView3D *rv3d, int winx, int winy,
+ rctf *r_viewplane, float *r_clipsta, float *r_clipend, float *r_pixsize)
{
CameraParams params;
@@ -775,7 +788,13 @@ bool ED_view3d_viewplane_get(View3D *v3d, RegionView3D *rv3d, int winx, int winy
*/
void ED_view3d_polygon_offset(const RegionView3D *rv3d, const float dist)
{
- float viewdist = rv3d->dist;
+ float viewdist;
+
+ if (rv3d->rflag & RV3D_ZOFFSET_DISABLED) {
+ return;
+ }
+
+ viewdist = rv3d->dist;
/* special exception for ortho camera (viewdist isnt used for perspective cameras) */
if (dist != 0.0f) {
@@ -792,7 +811,7 @@ void ED_view3d_polygon_offset(const RegionView3D *rv3d, const float dist)
/**
* \param rect optional for picking (can be NULL).
*/
-void view3d_winmatrix_set(ARegion *ar, View3D *v3d, const rctf *rect)
+void view3d_winmatrix_set(ARegion *ar, const View3D *v3d, const rctf *rect)
{
RegionView3D *rv3d = ar->regiondata;
rctf viewplane;
@@ -891,13 +910,28 @@ char ED_view3d_lock_view_from_index(int index)
}
+char ED_view3d_axis_view_opposite(char view)
+{
+ switch (view) {
+ case RV3D_VIEW_FRONT: return RV3D_VIEW_BACK;
+ case RV3D_VIEW_BACK: return RV3D_VIEW_FRONT;
+ case RV3D_VIEW_LEFT: return RV3D_VIEW_RIGHT;
+ case RV3D_VIEW_RIGHT: return RV3D_VIEW_LEFT;
+ case RV3D_VIEW_TOP: return RV3D_VIEW_BOTTOM;
+ case RV3D_VIEW_BOTTOM: return RV3D_VIEW_TOP;
+ }
+
+ return RV3D_VIEW_USER;
+}
+
+
bool ED_view3d_lock(RegionView3D *rv3d)
{
return ED_view3d_quat_from_axis_view(rv3d->view, rv3d->viewquat);
}
/* don't set windows active in here, is used by renderwin too */
-void view3d_viewmatrix_set(Scene *scene, View3D *v3d, RegionView3D *rv3d)
+void view3d_viewmatrix_set(Scene *scene, const View3D *v3d, RegionView3D *rv3d)
{
if (rv3d->persp == RV3D_CAMOB) { /* obs/camera */
if (v3d->camera) {
@@ -936,7 +970,7 @@ void view3d_viewmatrix_set(Scene *scene, View3D *v3d, RegionView3D *rv3d)
}
else if (v3d->ob_centre_cursor) {
float vec[3];
- copy_v3_v3(vec, ED_view3d_cursor3d_get(scene, v3d));
+ copy_v3_v3(vec, ED_view3d_cursor3d_get(scene, (View3D *)v3d));
translate_m4(rv3d->viewmat, -vec[0], -vec[1], -vec[2]);
use_lock_ofs = true;
}
@@ -1047,7 +1081,7 @@ short view3d_opengl_select(ViewContext *vc, unsigned int *buffer, unsigned int b
Scene *scene = vc->scene;
View3D *v3d = vc->v3d;
ARegion *ar = vc->ar;
- rctf rect, selrect;
+ rctf rect;
short hits;
const bool use_obedit_skip = (scene->obedit != NULL) && (vc->obedit == NULL);
const bool do_passes = do_nearest && GPU_select_query_check_active();
@@ -1064,8 +1098,6 @@ short view3d_opengl_select(ViewContext *vc, unsigned int *buffer, unsigned int b
else {
BLI_rctf_rcti_copy(&rect, input);
}
-
- selrect = rect;
view3d_winmatrix_set(ar, v3d, &rect);
mul_m4_m4m4(vc->rv3d->persmat, vc->rv3d->winmat, vc->rv3d->viewmat);
@@ -1079,9 +1111,9 @@ short view3d_opengl_select(ViewContext *vc, unsigned int *buffer, unsigned int b
ED_view3d_clipping_set(vc->rv3d);
if (do_passes)
- GPU_select_begin(buffer, bufsize, &selrect, GPU_SELECT_NEAREST_FIRST_PASS, 0);
+ GPU_select_begin(buffer, bufsize, &rect, GPU_SELECT_NEAREST_FIRST_PASS, 0);
else
- GPU_select_begin(buffer, bufsize, &selrect, GPU_SELECT_ALL, 0);
+ GPU_select_begin(buffer, bufsize, &rect, GPU_SELECT_ALL, 0);
view3d_select_loop(vc, scene, v3d, ar, use_obedit_skip);
@@ -1089,7 +1121,7 @@ short view3d_opengl_select(ViewContext *vc, unsigned int *buffer, unsigned int b
/* second pass, to get the closest object to camera */
if (do_passes) {
- GPU_select_begin(buffer, bufsize, &selrect, GPU_SELECT_NEAREST_SECOND_PASS, hits);
+ GPU_select_begin(buffer, bufsize, &rect, GPU_SELECT_NEAREST_SECOND_PASS, hits);
view3d_select_loop(vc, scene, v3d, ar, use_obedit_skip);
@@ -1196,7 +1228,7 @@ static bool view3d_localview_init(
View3D *v3d = sa->spacedata.first;
Base *base;
float min[3], max[3], box[3], mid[3];
- float size = 0.0f, size_persp = 0.0f, size_ortho = 0.0f;
+ float size = 0.0f;
unsigned int locallay;
bool ok = false;
@@ -1234,13 +1266,6 @@ static bool view3d_localview_init(
sub_v3_v3v3(box, max, min);
size = max_fff(box[0], box[1], box[2]);
-
- /* do not zoom closer than the near clipping plane */
- size = max_ff(size, v3d->near * 1.5f);
-
- /* perspective size (we always switch out of camera view so no need to use its lens size) */
- size_persp = ED_view3d_radius_to_persp_dist(focallength_to_fov(v3d->lens, DEFAULT_SENSOR_WIDTH), size / 2.0f) * VIEW3D_MARGIN;
- size_ortho = ED_view3d_radius_to_ortho_dist(v3d->lens, size / 2.0f) * VIEW3D_MARGIN;
}
if (ok == true) {
@@ -1257,6 +1282,7 @@ static bool view3d_localview_init(
for (ar = sa->regionbase.first; ar; ar = ar->next) {
if (ar->regiontype == RGN_TYPE_WINDOW) {
RegionView3D *rv3d = ar->regiondata;
+ bool ok_dist = true;
/* new view values */
Object *camera_old = NULL;
@@ -1272,25 +1298,24 @@ static bool view3d_localview_init(
camera_old = v3d->camera;
}
- /* perspective should be a bit farther away to look nice */
- if (rv3d->persp != RV3D_ORTHO) {
- dist_new = size_persp;
- }
- else {
- dist_new = size_ortho;
+ if (rv3d->persp == RV3D_ORTHO) {
+ if (size < 0.0001f) {
+ ok_dist = false;
+ }
}
- /* correction for window aspect ratio */
- if (ar->winy > 2 && ar->winx > 2) {
- float asp = (float)ar->winx / (float)ar->winy;
- if (asp < 1.0f) asp = 1.0f / asp;
- dist_new *= asp;
+ if (ok_dist) {
+ dist_new = ED_view3d_radius_to_dist(v3d, ar, rv3d->persp, true, (size / 2) * VIEW3D_MARGIN);
+ if (rv3d->persp == RV3D_PERSP) {
+ /* don't zoom closer than the near clipping plane */
+ dist_new = max_ff(dist_new, v3d->near * 1.5f);
+ }
}
ED_view3d_smooth_view_ex(
wm, win, sa,
v3d, ar, camera_old, NULL,
- ofs_new, NULL, &dist_new, NULL,
+ ofs_new, NULL, ok_dist ? &dist_new : NULL, NULL,
smooth_viewtx);
}
}
@@ -1545,18 +1570,21 @@ static void game_set_commmandline_options(GameData *gm)
static int game_engine_poll(bContext *C)
{
+ bScreen *screen;
/* we need a context and area to launch BGE
* it's a temporary solution to avoid crash at load time
* if we try to auto run the BGE. Ideally we want the
* context to be set as soon as we load the file. */
if (CTX_wm_window(C) == NULL) return 0;
- if (CTX_wm_screen(C) == NULL) return 0;
- if (CTX_wm_area(C) == NULL) return 0;
+ if ((screen = CTX_wm_screen(C)) == NULL) return 0;
if (CTX_data_mode_enum(C) != CTX_MODE_OBJECT)
return 0;
+ if (!BKE_scene_uses_blender_game(screen->scene))
+ return 0;
+
return 1;
}
@@ -1567,20 +1595,18 @@ bool ED_view3d_context_activate(bContext *C)
ARegion *ar;
/* sa can be NULL when called from python */
- if (sa == NULL || sa->spacetype != SPACE_VIEW3D)
- for (sa = sc->areabase.first; sa; sa = sa->next)
- if (sa->spacetype == SPACE_VIEW3D)
- break;
+ if (sa == NULL || sa->spacetype != SPACE_VIEW3D) {
+ sa = BKE_screen_find_big_area(sc, SPACE_VIEW3D, 0);
+ }
- if (!sa)
+ if (sa == NULL) {
return false;
+ }
- for (ar = sa->regionbase.first; ar; ar = ar->next)
- if (ar->regiontype == RGN_TYPE_WINDOW)
- break;
-
- if (!ar)
+ ar = BKE_area_find_region_active_win(sa);
+ if (ar == NULL) {
return false;
+ }
/* bad context switch .. */
CTX_wm_area_set(C, sa);
@@ -1693,21 +1719,116 @@ void VIEW3D_OT_game_start(wmOperatorType *ot)
/* ************************************** */
-float ED_view3d_pixel_size(RegionView3D *rv3d, const float co[3])
+float ED_view3d_pixel_size(const RegionView3D *rv3d, const float co[3])
{
- return mul_project_m4_v3_zfac(rv3d->persmat, co) * rv3d->pixsize * U.pixelsize;
+ return mul_project_m4_v3_zfac((float(*)[4])rv3d->persmat, co) * rv3d->pixsize * U.pixelsize;
}
-float ED_view3d_radius_to_persp_dist(const float angle, const float radius)
+float ED_view3d_radius_to_dist_persp(const float angle, const float radius)
{
- return (radius / 2.0f) * fabsf(1.0f / cosf((((float)M_PI) - angle) / 2.0f));
+ return radius * (1.0f / tanf(angle / 2.0f));
}
-float ED_view3d_radius_to_ortho_dist(const float lens, const float radius)
+float ED_view3d_radius_to_dist_ortho(const float lens, const float radius)
{
return radius / (DEFAULT_SENSOR_WIDTH / lens);
}
+/**
+ * Return a new RegionView3D.dist value to fit the \a radius.
+ *
+ * \note Depth isn't taken into account, this will fit a flat plane exactly,
+ * but points towards the view (with a perspective projection),
+ * may be within the radius but outside the view. eg:
+ *
+ * <pre>
+ * +
+ * pt --> + /^ radius
+ * / |
+ * / |
+ * view + +
+ * \ |
+ * \ |
+ * \|
+ * +
+ * </pre>
+ *
+ * \param ar Can be NULL if \a use_aspect is false.
+ * \param persp Allow the caller to tell what kind of perspective to use (ortho/view/camera)
+ * \param use_aspect Increase the distance to account for non 1:1 view aspect.
+ * \param radius The radius will be fitted exactly, typically pre-scaled by a margin (#VIEW3D_MARGIN).
+ */
+float ED_view3d_radius_to_dist(
+ const View3D *v3d, const ARegion *ar,
+ const char persp, const bool use_aspect,
+ const float radius)
+{
+ float dist;
+
+ BLI_assert(ELEM(persp, RV3D_ORTHO, RV3D_PERSP, RV3D_CAMOB));
+ BLI_assert((persp != RV3D_CAMOB) || v3d->camera);
+
+ if (persp == RV3D_ORTHO) {
+ dist = ED_view3d_radius_to_dist_ortho(v3d->lens, radius);
+ }
+ else {
+ float lens, sensor_size, zoom;
+ float angle;
+
+ if (persp == RV3D_CAMOB) {
+ CameraParams params;
+ BKE_camera_params_init(&params);
+ params.clipsta = v3d->near;
+ params.clipend = v3d->far;
+ BKE_camera_params_from_object(&params, v3d->camera);
+
+ lens = params.lens;
+ sensor_size = BKE_camera_sensor_size(params.sensor_fit, params.sensor_x, params.sensor_y);
+
+ /* ignore 'rv3d->camzoom' because we want to fit to the cameras frame */
+ zoom = CAMERA_PARAM_ZOOM_INIT_CAMOB;
+ }
+ else {
+ lens = v3d->lens;
+ sensor_size = DEFAULT_SENSOR_WIDTH;
+ zoom = CAMERA_PARAM_ZOOM_INIT_PERSP;
+ }
+
+ angle = focallength_to_fov(lens, sensor_size);
+
+ /* zoom influences lens, correct this by scaling the angle as a distance (by the zoom-level) */
+ angle = atanf(tanf(angle / 2.0f) * zoom) * 2.0f;
+
+ dist = ED_view3d_radius_to_dist_persp(angle, radius);
+ }
+
+ if (use_aspect) {
+ const RegionView3D *rv3d = ar->regiondata;
+
+ float winx, winy;
+
+ if (persp == RV3D_CAMOB) {
+ /* camera frame x/y in pixels */
+ winx = ar->winx / rv3d->viewcamtexcofac[0];
+ winy = ar->winy / rv3d->viewcamtexcofac[1];
+ }
+ else {
+ winx = ar->winx;
+ winy = ar->winy;
+ }
+
+ if (winx && winy) {
+ float aspect = winx / winy;
+ if (aspect < 1.0f) {
+ aspect = 1.0f / aspect;
+ }
+ dist *= aspect;
+ }
+ }
+
+ return dist;
+}
+
/* view matrix properties utilities */
/* unused */
diff --git a/source/blender/editors/space_view3d/view3d_walk.c b/source/blender/editors/space_view3d/view3d_walk.c
index c54948b23c6..0bda6e37fd1 100644
--- a/source/blender/editors/space_view3d/view3d_walk.c
+++ b/source/blender/editors/space_view3d/view3d_walk.c
@@ -26,8 +26,6 @@
/* 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"
@@ -40,10 +38,8 @@
#include "BKE_context.h"
#include "BKE_report.h"
-#include "BLF_translation.h"
+#include "BLT_translation.h"
-#include "RNA_define.h"
-#include "RNA_enum_types.h"
#include "BIF_gl.h"
@@ -56,10 +52,19 @@
#include "PIL_time.h" /* smoothview */
+#include "UI_interface.h"
#include "UI_resources.h"
#include "view3d_intern.h" /* own include */
+//#define NDOF_WALK_DEBUG
+//#define NDOF_WALK_DRAW_TOOMUCH /* is this needed for ndof? - commented so redraw doesnt thrash - campbell */
+
+#define USE_TABLET_SUPPORT
+
+/* ensure the target position is one we can reach, see: T45771 */
+#define USE_PIXELSIZE_NATIVE_SUPPORT
+
/* prototypes */
static float getVelocityZeroTime(const float gravity, const float velocity);
@@ -152,6 +157,8 @@ void walk_modal_keymap(wmKeyConfig *keyconf)
{WALK_MODAL_JUMP, "JUMP", 0, "Jump", "Jump when in walk mode"},
{WALK_MODAL_JUMP_STOP, "JUMP_STOP", 0, "Jump Stop", "Stop pushing jump"},
+ {WALK_MODAL_TOGGLE, "GRAVITY_TOGGLE", 0, "Toggle Gravity", "Toggle gravity effect"},
+
{0, NULL, 0, NULL, NULL}};
wmKeyMap *keymap = WM_modalkeymap_get(keyconf, "View3D Walk Modal");
@@ -220,8 +227,7 @@ void walk_modal_keymap(wmKeyConfig *keyconf)
}
-typedef struct WalkTeleport
-{
+typedef struct WalkTeleport {
eWalkTeleportState state;
float duration; /* from user preferences */
float origin[3];
@@ -277,6 +283,14 @@ typedef struct WalkInfo {
/* mouse reverse */
bool is_reversed;
+#ifdef USE_TABLET_SUPPORT
+ /* check if we had a cursor event before */
+ bool is_cursor_first;
+
+ /* tablet devices (we can't relocate the cursor) */
+ bool is_cursor_absolute;
+#endif
+
/* gravity system */
eWalkGravityState gravity_state;
float gravity;
@@ -335,27 +349,42 @@ static void drawWalkPixel(const struct bContext *UNUSED(C), ARegion *ar, void *a
glEnd();
}
-static void walk_update_header(bContext *C, WalkInfo *walk)
+static void walk_update_header(bContext *C, wmOperator *op, WalkInfo *walk)
{
- bool gravity = walk->navigation_mode == WALK_MODE_GRAVITY ||
- (walk->teleport.state == WALK_TELEPORT_STATE_ON &&
- walk->teleport.navigation_mode == WALK_MODE_GRAVITY);
-
-#define HEADER_LENGTH 256
- char header[HEADER_LENGTH];
-
- BLI_snprintf(header, HEADER_LENGTH, IFACE_("LMB/Return: confirm, Esc/RMB: cancel, "
- "Tab: gravity (%s), "
- "WASD: move around, "
- "Shift: fast, Alt: slow, "
- "QE: up and down, MMB/Space: teleport, V: jump, "
- "Pad +/Wheel Up: increase speed, Pad -/Wheel Down: decrease speed"),
- WM_bool_as_string(gravity));
+ const bool gravity = (walk->navigation_mode == WALK_MODE_GRAVITY) ||
+ ((walk->teleport.state == WALK_TELEPORT_STATE_ON) &&
+ (walk->teleport.navigation_mode == WALK_MODE_GRAVITY));
+ char header[UI_MAX_DRAW_STR];
+ char buf[UI_MAX_DRAW_STR];
+
+ char *p = buf;
+ int available_len = sizeof(buf);
+
+#define WM_MODALKEY(_id) \
+ WM_modalkeymap_operator_items_to_string_buf(op->type, (_id), true, UI_MAX_SHORTCUT_STR, &available_len, &p)
+
+ BLI_snprintf(header, sizeof(header), IFACE_("%s: confirm, %s: cancel, "
+ "%s: gravity (%s), "
+ "%s|%s|%s|%s: move around, "
+ "%s: fast, %s: slow, "
+ "%s|%s: up and down, "
+ "%s: teleport, %s: jump, "
+ "%s: increase speed, %s: decrease speed"),
+ WM_MODALKEY(WALK_MODAL_CONFIRM), WM_MODALKEY(WALK_MODAL_CANCEL),
+ WM_MODALKEY(WALK_MODAL_TOGGLE), WM_bool_as_string(gravity),
+ WM_MODALKEY(WALK_MODAL_DIR_FORWARD), WM_MODALKEY(WALK_MODAL_DIR_LEFT),
+ WM_MODALKEY(WALK_MODAL_DIR_BACKWARD), WM_MODALKEY(WALK_MODAL_DIR_RIGHT),
+ WM_MODALKEY(WALK_MODAL_FAST_ENABLE), WM_MODALKEY(WALK_MODAL_SLOW_ENABLE),
+ WM_MODALKEY(WALK_MODAL_DIR_UP), WM_MODALKEY(WALK_MODAL_DIR_DOWN),
+ WM_MODALKEY(WALK_MODAL_TELEPORT), WM_MODALKEY(WALK_MODAL_JUMP),
+ WM_MODALKEY(WALK_MODAL_ACCELERATE), WM_MODALKEY(WALK_MODAL_DECELERATE));
+
+#undef WM_MODALKEY
+
ED_area_headerprint(CTX_wm_area(C), header);
-#undef HEADER_LENGTH
}
-static void walk_navigation_mode_set(bContext *C, WalkInfo *walk, eWalkMethod mode)
+static void walk_navigation_mode_set(bContext *C, wmOperator *op, WalkInfo *walk, eWalkMethod mode)
{
if (mode == WALK_MODE_FREE) {
walk->navigation_mode = WALK_MODE_FREE;
@@ -366,7 +395,7 @@ static void walk_navigation_mode_set(bContext *C, WalkInfo *walk, eWalkMethod mo
walk->gravity_state = WALK_GRAVITY_STATE_START;
}
- walk_update_header(C, walk);
+ walk_update_header(C, op, walk);
}
/**
@@ -493,16 +522,16 @@ static bool initWalkInfo(bContext *C, WalkInfo *walk, wmOperator *op)
walk->speed = 0.0f;
walk->is_fast = false;
walk->is_slow = false;
- walk->grid = 1.f / walk->scene->unit.scale_length;
+ walk->grid = (walk->scene->unit.system == USER_UNIT_NONE) ? 1.f : 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(C, walk, WALK_MODE_GRAVITY);
+ walk_navigation_mode_set(C, op, walk, WALK_MODE_GRAVITY);
else
- walk_navigation_mode_set(C, walk, WALK_MODE_FREE);
+ walk_navigation_mode_set(C, op, walk, WALK_MODE_FREE);
walk->view_height = U.walk_navigation.view_height;
walk->jump_height = U.walk_navigation.jump_height;
@@ -520,6 +549,12 @@ static bool initWalkInfo(bContext *C, WalkInfo *walk, wmOperator *op)
walk->is_reversed = ((U.walk_navigation.flag & USER_WALK_MOUSE_REVERSE) != 0);
+#ifdef USE_TABLET_SUPPORT
+ walk->is_cursor_first = true;
+
+ walk->is_cursor_absolute = false;
+#endif
+
walk->active_directions = 0;
#ifdef NDOF_WALK_DRAW_TOOMUCH
@@ -546,6 +581,16 @@ static bool initWalkInfo(bContext *C, WalkInfo *walk, wmOperator *op)
walk->center_mval[0] = walk->ar->winx * 0.5f;
walk->center_mval[1] = walk->ar->winy * 0.5f;
+#ifdef USE_PIXELSIZE_NATIVE_SUPPORT
+ walk->center_mval[0] += walk->ar->winrct.xmin;
+ walk->center_mval[1] += walk->ar->winrct.ymin;
+
+ WM_cursor_compatible_xy(win, &walk->center_mval[0], &walk->center_mval[1]);
+
+ walk->center_mval[0] -= walk->ar->winrct.xmin;
+ walk->center_mval[1] -= walk->ar->winrct.ymin;
+#endif
+
copy_v2_v2_int(walk->prev_mval, walk->center_mval);
WM_cursor_warp(win,
@@ -587,10 +632,16 @@ static int walkEnd(bContext *C, WalkInfo *walk)
/* 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]);
+#ifdef USE_TABLET_SUPPORT
+ if (walk->is_cursor_absolute == false)
+#endif
+ {
+ /* 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);
@@ -611,13 +662,42 @@ static bool wm_event_is_last_mousemove(const wmEvent *event)
return true;
}
-static void walkEvent(bContext *C, wmOperator *UNUSED(op), WalkInfo *walk, const wmEvent *event)
+static void walkEvent(bContext *C, wmOperator *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)) {
+#ifdef USE_TABLET_SUPPORT
+ if (walk->is_cursor_first) {
+ /* wait until we get the 'warp' event */
+ if ((walk->center_mval[0] == event->mval[0]) &&
+ (walk->center_mval[1] == event->mval[1]))
+ {
+ walk->is_cursor_first = false;
+ }
+ else {
+ /* note, its possible the system isn't giving us the warp event
+ * ideally we shouldn't have to worry about this, see: T45361 */
+ wmWindow *win = CTX_wm_window(C);
+ WM_cursor_warp(win,
+ walk->ar->winrct.xmin + walk->center_mval[0],
+ walk->ar->winrct.ymin + walk->center_mval[1]);
+ }
+ return;
+ }
+
+ if ((walk->is_cursor_absolute == false) && WM_event_is_absolute(event)) {
+ walk->is_cursor_absolute = true;
+ copy_v2_v2_int(walk->prev_mval, event->mval);
+ copy_v2_v2_int(walk->center_mval, event->mval);
+ /* without this we can't turn 180d */
+ CLAMP_MIN(walk->mouse_speed, 4.0f);
+ }
+#endif /* USE_TABLET_SUPPORT */
+
+
walk->moffset[0] += event->mval[0] - walk->prev_mval[0];
walk->moffset[1] += event->mval[1] - walk->prev_mval[1];
@@ -628,6 +708,12 @@ static void walkEvent(bContext *C, wmOperator *UNUSED(op), WalkInfo *walk, const
{
walk->redraw = true;
+#ifdef USE_TABLET_SUPPORT
+ if (walk->is_cursor_absolute) {
+ /* pass */
+ }
+ else
+#endif
if (wm_event_is_last_mousemove(event)) {
wmWindow *win = CTX_wm_window(C);
@@ -820,7 +906,7 @@ static void walkEvent(bContext *C, wmOperator *UNUSED(op), WalkInfo *walk, const
teleport->duration = U.walk_navigation.teleport_time;
teleport->navigation_mode = walk->navigation_mode;
- walk_navigation_mode_set(C, walk, WALK_MODE_FREE);
+ walk_navigation_mode_set(C, op, walk, WALK_MODE_FREE);
copy_v3_v3(teleport->origin, walk->rv3d->viewinv[3]);
@@ -843,10 +929,10 @@ static void walkEvent(bContext *C, wmOperator *UNUSED(op), WalkInfo *walk, const
case WALK_MODAL_TOGGLE:
if (walk->navigation_mode == WALK_MODE_GRAVITY) {
- walk_navigation_mode_set(C, walk, WALK_MODE_FREE);
+ walk_navigation_mode_set(C, op, walk, WALK_MODE_FREE);
}
else { /* WALK_MODE_FREE */
- walk_navigation_mode_set(C, walk, WALK_MODE_GRAVITY);
+ walk_navigation_mode_set(C, op, walk, WALK_MODE_GRAVITY);
}
break;
}
@@ -869,7 +955,7 @@ static float getVelocityZeroTime(const float gravity, const float velocity)
return velocity / gravity;
}
-static int walkApply(bContext *C, WalkInfo *walk)
+static int walkApply(bContext *C, wmOperator *op, WalkInfo *walk)
{
#define WALK_ROTATE_FAC 2.2f /* more is faster */
#define WALK_TOP_LIMIT DEG2RADF(85.0f)
@@ -1182,7 +1268,7 @@ static int walkApply(bContext *C, WalkInfo *walk)
if (t >= 1.0f) {
t = 1.0f;
walk->teleport.state = WALK_TELEPORT_STATE_OFF;
- walk_navigation_mode_set(C, walk, walk->teleport.navigation_mode);
+ walk_navigation_mode_set(C, op, walk, walk->teleport.navigation_mode);
}
mul_v3_v3fl(new_loc, walk->teleport.direction, t);
@@ -1299,7 +1385,7 @@ static int walk_modal(bContext *C, wmOperator *op, const wmEvent *event)
}
}
else if (event->type == TIMER && event->customdata == walk->timer) {
- walkApply(C, walk);
+ walkApply(C, op, walk);
}
do_draw |= walk->redraw;
diff --git a/source/blender/editors/transform/CMakeLists.txt b/source/blender/editors/transform/CMakeLists.txt
index 3ad5d94efd6..42aa6a0a3a3 100644
--- a/source/blender/editors/transform/CMakeLists.txt
+++ b/source/blender/editors/transform/CMakeLists.txt
@@ -23,6 +23,7 @@ set(INC
../../blenfont
../../blenkernel
../../blenlib
+ ../../blentranslation
../../bmesh
../../gpu
../../ikplugin
@@ -30,6 +31,7 @@ set(INC
../../makesrna
../../windowmanager
../../../../intern/guardedalloc
+ ../../../../intern/glew-mx
)
set(INC_SYS
@@ -54,4 +56,10 @@ if(WITH_INTERNATIONAL)
add_definitions(-DWITH_INTERNATIONAL)
endif()
+if(WITH_LEGACY_DEPSGRAPH)
+ add_definitions(-DWITH_LEGACY_DEPSGRAPH)
+endif()
+
+add_definitions(${GL_DEFINITIONS})
+
blender_add_lib(bf_editor_transform "${SRC}" "${INC}" "${INC_SYS}")
diff --git a/source/blender/editors/transform/SConscript b/source/blender/editors/transform/SConscript
index 4f47062e3a3..0f34ce546de 100644
--- a/source/blender/editors/transform/SConscript
+++ b/source/blender/editors/transform/SConscript
@@ -31,22 +31,28 @@ sources = env.Glob('*.c')
incs = [
'#/intern/guardedalloc',
- '#/extern/glew/include',
+ env['BF_GLEW_INC'],
+ '#/intern/glew-mx',
'../include',
'../../blenfont',
'../../blenkernel',
'../../blenlib',
+ '../../blentranslation',
'../../bmesh',
+ '../../gpu',
'../../ikplugin',
'../../makesdna',
'../../makesrna',
- '../../gpu',
'../../windowmanager',
]
defs = []
+defs += env['BF_GL_DEFINITIONS']
if env['WITH_BF_INTERNATIONAL']:
defs.append('WITH_INTERNATIONAL')
+if env['WITH_BF_LEGACY_DEPSGRAPH']:
+ defs.append('WITH_LEGACY_DEPSGRAPH')
+
env.BlenderLib ( 'bf_editors_transform', sources, incs, defs, libtype=['core'], priority=[40] )
diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c
index 008022a9859..2b295b85da0 100644
--- a/source/blender/editors/transform/transform.c
+++ b/source/blender/editors/transform/transform.c
@@ -44,20 +44,24 @@
#include "DNA_movieclip_types.h"
#include "DNA_scene_types.h" /* PET modes */
+#include "BLI_alloca.h"
#include "BLI_utildefines.h"
#include "BLI_math.h"
#include "BLI_rect.h"
#include "BLI_listbase.h"
#include "BLI_string.h"
#include "BLI_ghash.h"
+#include "BLI_memarena.h"
#include "BKE_nla.h"
+#include "BKE_editmesh.h"
#include "BKE_editmesh_bvh.h"
#include "BKE_context.h"
#include "BKE_constraint.h"
#include "BKE_particle.h"
#include "BKE_unit.h"
#include "BKE_mask.h"
+#include "BKE_report.h"
#include "BIF_gl.h"
#include "BIF_glutil.h"
@@ -82,7 +86,7 @@
#include "RNA_access.h"
#include "BLF_api.h"
-#include "BLF_translation.h"
+#include "BLT_translation.h"
#include "transform.h"
@@ -92,14 +96,17 @@
#define MAX_INFO_LEN 256
static void drawTransformApply(const struct bContext *C, ARegion *ar, void *arg);
-static int doEdgeSlide(TransInfo *t, float perc);
-static int doVertSlide(TransInfo *t, float perc);
+static void doEdgeSlide(TransInfo *t, float perc);
+static void doVertSlide(TransInfo *t, float perc);
-static void drawEdgeSlide(const struct bContext *C, TransInfo *t);
-static void drawVertSlide(const struct bContext *C, TransInfo *t);
+static void drawEdgeSlide(TransInfo *t);
+static void drawVertSlide(TransInfo *t);
static void len_v3_ensure(float v[3], const float length);
static void postInputRotation(TransInfo *t, float values[3]);
+static void ElementRotation(TransInfo *t, TransData *td, float mat[3][3], short around);
+static void initSnapSpatial(TransInfo *t, float r_snap[3]);
+
/* Transform Callbacks */
static void initBend(TransInfo *t);
@@ -137,6 +144,9 @@ static void applyCurveShrinkFatten(TransInfo *t, const int mval[2]);
static void initMaskShrinkFatten(TransInfo *t);
static void applyMaskShrinkFatten(TransInfo *t, const int mval[2]);
+static void initGPShrinkFatten(TransInfo *t);
+static void applyGPShrinkFatten(TransInfo *t, const int mval[2]);
+
static void initTrackball(TransInfo *t);
static void applyTrackball(TransInfo *t, const int mval[2]);
@@ -158,6 +168,7 @@ static void applyBoneEnvelope(TransInfo *t, const int mval[2]);
static void initBoneRoll(TransInfo *t);
static void applyBoneRoll(TransInfo *t, const int mval[2]);
+static void initEdgeSlide_ex(TransInfo *t, bool use_double_side);
static void initEdgeSlide(TransInfo *t);
static eRedrawFlag handleEventEdgeSlide(TransInfo *t, const struct wmEvent *event);
static void applyEdgeSlide(TransInfo *t, const int mval[2]);
@@ -199,6 +210,12 @@ static bool transdata_check_local_center(TransInfo *t, short around)
);
}
+bool transdata_check_local_islands(TransInfo *t, short around)
+{
+ return ((around == V3D_LOCAL) && (
+ (t->obedit && ELEM(t->obedit->type, OB_MESH))));
+}
+
/* ************************** SPACE DEPENDANT CODE **************************** */
void setTransformViewMatrices(TransInfo *t)
@@ -223,6 +240,38 @@ void setTransformViewMatrices(TransInfo *t)
calculateCenter2D(t);
}
+void setTransformViewAspect(TransInfo *t, float r_aspect[3])
+{
+ copy_v3_fl(r_aspect, 1.0f);
+
+ if (t->spacetype == SPACE_IMAGE) {
+ SpaceImage *sima = t->sa->spacedata.first;
+
+ if (t->options & CTX_MASK) {
+ ED_space_image_get_aspect(sima, &r_aspect[0], &r_aspect[1]);
+ }
+ else if (t->options & CTX_PAINT_CURVE) {
+ /* pass */
+ }
+ else {
+ ED_space_image_get_uv_aspect(sima, &r_aspect[0], &r_aspect[1]);
+ }
+ }
+ else if (t->spacetype == SPACE_CLIP) {
+ SpaceClip *sclip = t->sa->spacedata.first;
+
+ if (t->options & CTX_MOVIECLIP) {
+ ED_space_clip_get_aspect_dimension_aware(sclip, &r_aspect[0], &r_aspect[1]);
+ }
+ else {
+ ED_space_clip_get_aspect(sclip, &r_aspect[0], &r_aspect[1]);
+ }
+ }
+ else if (t->spacetype == SPACE_IPO) {
+ /* depemds on context of usage */
+ }
+}
+
static void convertViewVec2D(View2D *v2d, float r_vec[3], int dx, int dy)
{
float divx, divy;
@@ -270,30 +319,25 @@ void convertViewVec(TransInfo *t, float r_vec[3], int dx, int dy)
r_vec[0] = dx;
r_vec[1] = dy;
}
- else { const float mval_f[2] = {(float)dx, (float)dy};
+ else {
+ const float mval_f[2] = {(float)dx, (float)dy};
ED_view3d_win_to_delta(t->ar, mval_f, r_vec, t->zfac);
}
}
else if (t->spacetype == SPACE_IMAGE) {
- float aspx, aspy;
-
if (t->options & CTX_MASK) {
convertViewVec2D_mask(t->view, r_vec, dx, dy);
- ED_space_image_get_aspect(t->sa->spacedata.first, &aspx, &aspy);
}
else if (t->options & CTX_PAINT_CURVE) {
r_vec[0] = dx;
r_vec[1] = dy;
-
- aspx = aspy = 1.0;
}
else {
convertViewVec2D(t->view, r_vec, dx, dy);
- ED_space_image_get_uv_aspect(t->sa->spacedata.first, &aspx, &aspy);
}
- r_vec[0] *= aspx;
- r_vec[1] *= aspy;
+ r_vec[0] *= t->aspect[0];
+ r_vec[1] *= t->aspect[1];
}
else if (ELEM(t->spacetype, SPACE_IPO, SPACE_NLA)) {
convertViewVec2D(t->view, r_vec, dx, dy);
@@ -302,8 +346,6 @@ void convertViewVec(TransInfo *t, float r_vec[3], int dx, int dy)
convertViewVec2D(&t->ar->v2d, r_vec, dx, dy);
}
else if (t->spacetype == SPACE_CLIP) {
- float aspx, aspy;
-
if (t->options & CTX_MASK) {
convertViewVec2D_mask(t->view, r_vec, dx, dy);
}
@@ -311,21 +353,8 @@ void convertViewVec(TransInfo *t, float r_vec[3], int dx, int dy)
convertViewVec2D(t->view, r_vec, dx, dy);
}
- if (t->options & CTX_MOVIECLIP) {
- ED_space_clip_get_aspect_dimension_aware(t->sa->spacedata.first, &aspx, &aspy);
- }
- else if (t->options & CTX_MASK) {
- /* TODO - NOT WORKING, this isnt so bad since its only display aspect */
- ED_space_clip_get_aspect(t->sa->spacedata.first, &aspx, &aspy);
- }
- else {
- /* should never happen, quiet warnings */
- BLI_assert(0);
- aspx = aspy = 1.0f;
- }
-
- r_vec[0] *= aspx;
- r_vec[1] *= aspy;
+ r_vec[0] *= t->aspect[0];
+ r_vec[1] *= t->aspect[1];
}
else {
printf("%s: called in an invalid context\n", __func__);
@@ -347,15 +376,10 @@ void projectIntViewEx(TransInfo *t, const float vec[3], int adr[2], const eV3DPr
SpaceImage *sima = t->sa->spacedata.first;
if (t->options & CTX_MASK) {
- float aspx, aspy;
float v[2];
- ED_space_image_get_aspect(sima, &aspx, &aspy);
-
- copy_v2_v2(v, vec);
-
- v[0] = v[0] / aspx;
- v[1] = v[1] / aspy;
+ v[0] = vec[0] / t->aspect[0];
+ v[1] = vec[1] / t->aspect[1];
BKE_mask_coord_to_image(sima->image, &sima->iuser, v, v);
@@ -369,11 +393,10 @@ void projectIntViewEx(TransInfo *t, const float vec[3], int adr[2], const eV3DPr
adr[1] = vec[1];
}
else {
- float aspx, aspy, v[2];
+ float v[2];
- ED_space_image_get_uv_aspect(t->sa->spacedata.first, &aspx, &aspy);
- v[0] = vec[0] / aspx;
- v[1] = vec[1] / aspy;
+ v[0] = vec[0] / t->aspect[0];
+ v[1] = vec[1] / t->aspect[1];
UI_view2d_view_to_region(t->view, v[0], v[1], &adr[0], &adr[1]);
}
@@ -418,15 +441,10 @@ void projectIntViewEx(TransInfo *t, const float vec[3], int adr[2], const eV3DPr
MovieClip *clip = ED_space_clip_get_clip(sc);
if (clip) {
- float aspx, aspy;
float v[2];
- ED_space_clip_get_aspect(sc, &aspx, &aspy);
-
- copy_v2_v2(v, vec);
-
- v[0] = v[0] / aspx;
- v[1] = v[1] / aspy;
+ v[0] = vec[0] / t->aspect[0];
+ v[1] = vec[1] / t->aspect[1];
BKE_mask_coord_to_movieclip(sc->clip, &sc->user, v, v);
@@ -441,13 +459,10 @@ void projectIntViewEx(TransInfo *t, const float vec[3], int adr[2], const eV3DPr
}
}
else if (t->options & CTX_MOVIECLIP) {
- float v[2], aspx, aspy;
-
- copy_v2_v2(v, vec);
- ED_space_clip_get_aspect_dimension_aware(t->sa->spacedata.first, &aspx, &aspy);
+ float v[2];
- v[0] /= aspx;
- v[1] /= aspy;
+ v[0] = vec[0] / t->aspect[0];
+ v[1] = vec[1] / t->aspect[1];
UI_view2d_view_to_region(t->view, v[0], v[1], &adr[0], &adr[1]);
}
@@ -503,7 +518,6 @@ void applyAspectRatio(TransInfo *t, float vec[2])
{
if ((t->spacetype == SPACE_IMAGE) && (t->mode == TFM_TRANSLATION) && !(t->options & CTX_PAINT_CURVE)) {
SpaceImage *sima = t->sa->spacedata.first;
- float aspx, aspy;
if ((sima->flag & SI_COORDFLOATS) == 0) {
int width, height;
@@ -513,28 +527,13 @@ void applyAspectRatio(TransInfo *t, float vec[2])
vec[1] *= height;
}
- ED_space_image_get_uv_aspect(sima, &aspx, &aspy);
- vec[0] /= aspx;
- vec[1] /= aspy;
+ vec[0] /= t->aspect[0];
+ vec[1] /= t->aspect[1];
}
else if ((t->spacetype == SPACE_CLIP) && (t->mode == TFM_TRANSLATION)) {
if (t->options & (CTX_MOVIECLIP | CTX_MASK)) {
- SpaceClip *sc = t->sa->spacedata.first;
- float aspx, aspy;
-
-
- if (t->options & CTX_MOVIECLIP) {
- ED_space_clip_get_aspect_dimension_aware(sc, &aspx, &aspy);
-
- vec[0] /= aspx;
- vec[1] /= aspy;
- }
- else if (t->options & CTX_MASK) {
- ED_space_clip_get_aspect(sc, &aspx, &aspy);
-
- vec[0] /= aspx;
- vec[1] /= aspy;
- }
+ vec[0] /= t->aspect[0];
+ vec[1] /= t->aspect[1];
}
}
}
@@ -543,7 +542,6 @@ void removeAspectRatio(TransInfo *t, float vec[2])
{
if ((t->spacetype == SPACE_IMAGE) && (t->mode == TFM_TRANSLATION)) {
SpaceImage *sima = t->sa->spacedata.first;
- float aspx, aspy;
if ((sima->flag & SI_COORDFLOATS) == 0) {
int width, height;
@@ -553,31 +551,23 @@ void removeAspectRatio(TransInfo *t, float vec[2])
vec[1] /= height;
}
- ED_space_image_get_uv_aspect(sima, &aspx, &aspy);
- vec[0] *= aspx;
- vec[1] *= aspy;
+ vec[0] *= t->aspect[0];
+ vec[1] *= t->aspect[1];
}
else if ((t->spacetype == SPACE_CLIP) && (t->mode == TFM_TRANSLATION)) {
if (t->options & (CTX_MOVIECLIP | CTX_MASK)) {
- SpaceClip *sc = t->sa->spacedata.first;
- float aspx = 1.0f, aspy = 1.0f;
-
- if (t->options & CTX_MOVIECLIP) {
- ED_space_clip_get_aspect_dimension_aware(sc, &aspx, &aspy);
- }
- else if (t->options & CTX_MASK) {
- ED_space_clip_get_aspect(sc, &aspx, &aspy);
- }
-
- vec[0] *= aspx;
- vec[1] *= aspy;
+ vec[0] *= t->aspect[0];
+ vec[1] *= t->aspect[1];
}
}
}
static void viewRedrawForce(const bContext *C, TransInfo *t)
{
- if (t->spacetype == SPACE_VIEW3D) {
+ if (t->options & CTX_GPENCIL_STROKES) {
+ WM_event_add_notifier(C, NC_GPENCIL | NA_EDITED, NULL);
+ }
+ else if (t->spacetype == SPACE_VIEW3D) {
if (t->options & CTX_PAINT_CURVE) {
wmWindow *window = CTX_wm_window(C);
WM_paint_cursor_tag_redraw(window, t->ar);
@@ -660,8 +650,11 @@ static void viewRedrawPost(bContext *C, TransInfo *t)
WM_main_add_notifier(NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL);
/* redraw UV editor */
- if (t->mode == TFM_EDGE_SLIDE && (t->settings->uvcalc_flag & UVCALC_TRANSFORM_CORRECT))
+ if (ELEM(t->mode, TFM_VERT_SLIDE, TFM_EDGE_SLIDE) &&
+ (t->settings->uvcalc_flag & UVCALC_TRANSFORM_CORRECT))
+ {
WM_event_add_notifier(C, NC_GEOM | ND_DATA, NULL);
+ }
/* XXX temp, first hack to get auto-render in compositor work (ton) */
WM_event_add_notifier(C, NC_SCENE | ND_TRANSFORM_DONE, CTX_data_scene(C));
@@ -710,7 +703,6 @@ static void view_editmove(unsigned short UNUSED(event))
switch (event) {
case WHEELUPMOUSE:
-
if (G.qual & LR_SHIFTKEY) {
if (G.qual & LR_ALTKEY) {
G.qual &= ~LR_SHIFTKEY;
@@ -776,35 +768,40 @@ static void view_editmove(unsigned short UNUSED(event))
/* ************************************************* */
/* NOTE: these defines are saved in keymap files, do not change values but just add new ones */
-#define TFM_MODAL_CANCEL 1
-#define TFM_MODAL_CONFIRM 2
-#define TFM_MODAL_TRANSLATE 3
-#define TFM_MODAL_ROTATE 4
-#define TFM_MODAL_RESIZE 5
-#define TFM_MODAL_SNAP_INV_ON 6
-#define TFM_MODAL_SNAP_INV_OFF 7
-#define TFM_MODAL_SNAP_TOGGLE 8
-#define TFM_MODAL_AXIS_X 9
-#define TFM_MODAL_AXIS_Y 10
-#define TFM_MODAL_AXIS_Z 11
-#define TFM_MODAL_PLANE_X 12
-#define TFM_MODAL_PLANE_Y 13
-#define TFM_MODAL_PLANE_Z 14
-#define TFM_MODAL_CONS_OFF 15
-#define TFM_MODAL_ADD_SNAP 16
-#define TFM_MODAL_REMOVE_SNAP 17
-/* 18 and 19 used by numinput, defined in transform.h
- * */
-#define TFM_MODAL_PROPSIZE_UP 20
-#define TFM_MODAL_PROPSIZE_DOWN 21
-#define TFM_MODAL_AUTOIK_LEN_INC 22
-#define TFM_MODAL_AUTOIK_LEN_DEC 23
-
-#define TFM_MODAL_EDGESLIDE_UP 24
-#define TFM_MODAL_EDGESLIDE_DOWN 25
+enum {
+ TFM_MODAL_CANCEL = 1,
+ TFM_MODAL_CONFIRM = 2,
+ TFM_MODAL_TRANSLATE = 3,
+ TFM_MODAL_ROTATE = 4,
+ TFM_MODAL_RESIZE = 5,
+ TFM_MODAL_SNAP_INV_ON = 6,
+ TFM_MODAL_SNAP_INV_OFF = 7,
+ TFM_MODAL_SNAP_TOGGLE = 8,
+ TFM_MODAL_AXIS_X = 9,
+ TFM_MODAL_AXIS_Y = 10,
+ TFM_MODAL_AXIS_Z = 11,
+ TFM_MODAL_PLANE_X = 12,
+ TFM_MODAL_PLANE_Y = 13,
+ TFM_MODAL_PLANE_Z = 14,
+ TFM_MODAL_CONS_OFF = 15,
+ TFM_MODAL_ADD_SNAP = 16,
+ TFM_MODAL_REMOVE_SNAP = 17,
+
+/* 18 and 19 used by numinput, defined in transform.h */
+
+ TFM_MODAL_PROPSIZE_UP = 20,
+ TFM_MODAL_PROPSIZE_DOWN = 21,
+ TFM_MODAL_AUTOIK_LEN_INC = 22,
+ TFM_MODAL_AUTOIK_LEN_DEC = 23,
+
+ TFM_MODAL_EDGESLIDE_UP = 24,
+ TFM_MODAL_EDGESLIDE_DOWN = 25,
/* for analog input, like trackpad */
-#define TFM_MODAL_PROPSIZE 26
+ TFM_MODAL_PROPSIZE = 26,
+/* node editor insert offset (aka auto-offset) direction toggle */
+ TFM_MODAL_INSERTOFS_TOGGLE_DIR = 27,
+};
/* called in transform_ops.c, on each regeneration of keymaps */
wmKeyMap *transform_modal_keymap(wmKeyConfig *keyconf)
@@ -836,6 +833,7 @@ wmKeyMap *transform_modal_keymap(wmKeyConfig *keyconf)
{TFM_MODAL_EDGESLIDE_UP, "EDGESLIDE_EDGE_NEXT", 0, "Select next Edge Slide Edge", ""},
{TFM_MODAL_EDGESLIDE_DOWN, "EDGESLIDE_PREV_NEXT", 0, "Select previous Edge Slide Edge", ""},
{TFM_MODAL_PROPSIZE, "PROPORTIONAL_SIZE", 0, "Adjust Proportional Influence", ""},
+ {TFM_MODAL_INSERTOFS_TOGGLE_DIR, "INSERTOFS_TOGGLE_DIR", 0, "Toggle Direction for Node Auto-offset", ""},
{0, NULL, 0, NULL, NULL}
};
@@ -849,8 +847,8 @@ wmKeyMap *transform_modal_keymap(wmKeyConfig *keyconf)
/* items for modal map */
WM_modalkeymap_add_item(keymap, ESCKEY, KM_PRESS, KM_ANY, 0, TFM_MODAL_CANCEL);
WM_modalkeymap_add_item(keymap, LEFTMOUSE, KM_PRESS, KM_ANY, 0, TFM_MODAL_CONFIRM);
- WM_modalkeymap_add_item(keymap, RETKEY, KM_PRESS, KM_ANY, 0, TFM_MODAL_CONFIRM);
- WM_modalkeymap_add_item(keymap, PADENTER, KM_PRESS, KM_ANY, 0, TFM_MODAL_CONFIRM);
+ WM_modalkeymap_add_item(keymap, RETKEY, KM_PRESS, KM_ANY, 0, TFM_MODAL_CONFIRM);
+ WM_modalkeymap_add_item(keymap, PADENTER, KM_PRESS, KM_ANY, 0, TFM_MODAL_CONFIRM);
WM_modalkeymap_add_item(keymap, GKEY, KM_PRESS, 0, 0, TFM_MODAL_TRANSLATE);
WM_modalkeymap_add_item(keymap, RKEY, KM_PRESS, 0, 0, TFM_MODAL_ROTATE);
@@ -869,8 +867,12 @@ wmKeyMap *transform_modal_keymap(wmKeyConfig *keyconf)
WM_modalkeymap_add_item(keymap, PAGEUPKEY, KM_PRESS, 0, 0, TFM_MODAL_PROPSIZE_UP);
WM_modalkeymap_add_item(keymap, PAGEDOWNKEY, KM_PRESS, 0, 0, TFM_MODAL_PROPSIZE_DOWN);
+ WM_modalkeymap_add_item(keymap, PAGEUPKEY, KM_PRESS, KM_SHIFT, 0, TFM_MODAL_PROPSIZE_UP);
+ WM_modalkeymap_add_item(keymap, PAGEDOWNKEY, KM_PRESS, KM_SHIFT, 0, TFM_MODAL_PROPSIZE_DOWN);
WM_modalkeymap_add_item(keymap, WHEELDOWNMOUSE, KM_PRESS, 0, 0, TFM_MODAL_PROPSIZE_UP);
WM_modalkeymap_add_item(keymap, WHEELUPMOUSE, KM_PRESS, 0, 0, TFM_MODAL_PROPSIZE_DOWN);
+ WM_modalkeymap_add_item(keymap, WHEELDOWNMOUSE, KM_PRESS, KM_SHIFT, 0, TFM_MODAL_PROPSIZE_UP);
+ WM_modalkeymap_add_item(keymap, WHEELUPMOUSE, KM_PRESS, KM_SHIFT, 0, TFM_MODAL_PROPSIZE_DOWN);
WM_modalkeymap_add_item(keymap, MOUSEPAN, 0, 0, 0, TFM_MODAL_PROPSIZE);
WM_modalkeymap_add_item(keymap, WHEELDOWNMOUSE, KM_PRESS, KM_ALT, 0, TFM_MODAL_EDGESLIDE_UP);
@@ -880,7 +882,10 @@ wmKeyMap *transform_modal_keymap(wmKeyConfig *keyconf)
WM_modalkeymap_add_item(keymap, PAGEDOWNKEY, KM_PRESS, KM_SHIFT, 0, TFM_MODAL_AUTOIK_LEN_DEC);
WM_modalkeymap_add_item(keymap, WHEELDOWNMOUSE, KM_PRESS, KM_SHIFT, 0, TFM_MODAL_AUTOIK_LEN_INC);
WM_modalkeymap_add_item(keymap, WHEELUPMOUSE, KM_PRESS, KM_SHIFT, 0, TFM_MODAL_AUTOIK_LEN_DEC);
-
+
+ /* node editor only */
+ WM_modalkeymap_add_item(keymap, TKEY, KM_PRESS, 0, 0, TFM_MODAL_INSERTOFS_TOGGLE_DIR);
+
return keymap;
}
@@ -888,7 +893,7 @@ static void transform_event_xyz_constraint(TransInfo *t, short key_type, char cm
{
if (!(t->flag & T_NO_CONSTRAINT)) {
int constraint_axis, constraint_plane;
- int edit_2d = (t->flag & T_2D_EDIT);
+ const bool edit_2d = (t->flag & T_2D_EDIT) != 0;
const char *msg1 = "", *msg2 = "", *msg3 = "";
char axis;
@@ -958,6 +963,7 @@ int transformEvent(TransInfo *t, const wmEvent *event)
{
char cmode = constraintModeToChar(t);
bool handled = false;
+ const int modifiers_prev = t->modifiers;
t->redraw |= handleMouseInput(t, &t->mouse, event);
@@ -1001,9 +1007,9 @@ int transformEvent(TransInfo *t, const wmEvent *event)
case TFM_MODAL_TRANSLATE:
/* only switch when... */
if (ELEM(t->mode, TFM_ROTATION, TFM_RESIZE, TFM_TRACKBALL, TFM_EDGE_SLIDE, TFM_VERT_SLIDE)) {
+ restoreTransObjects(t);
resetTransModal(t);
resetTransRestrictions(t);
- restoreTransObjects(t);
initTranslation(t);
initSnapping(t, NULL); // need to reinit after mode change
t->redraw |= TREDRAW_HARD;
@@ -1018,9 +1024,9 @@ int transformEvent(TransInfo *t, const wmEvent *event)
else {
if (t->obedit && t->obedit->type == OB_MESH) {
if ((t->mode == TFM_TRANSLATION) && (t->spacetype == SPACE_VIEW3D)) {
+ restoreTransObjects(t);
resetTransModal(t);
resetTransRestrictions(t);
- restoreTransObjects(t);
/* first try edge slide */
initEdgeSlide(t);
@@ -1032,8 +1038,8 @@ int transformEvent(TransInfo *t, const wmEvent *event)
/* vert slide can fail on unconnected vertices (rare but possible) */
if (t->state == TRANS_CANCEL) {
t->state = TRANS_STARTING;
- resetTransRestrictions(t);
restoreTransObjects(t);
+ resetTransRestrictions(t);
initTranslation(t);
}
initSnapping(t, NULL); // need to reinit after mode change
@@ -1057,15 +1063,14 @@ int transformEvent(TransInfo *t, const wmEvent *event)
/* only switch when... */
if (!(t->options & CTX_TEXTURE) && !(t->options & (CTX_MOVIECLIP | CTX_MASK))) {
if (ELEM(t->mode, TFM_ROTATION, TFM_RESIZE, TFM_TRACKBALL, TFM_TRANSLATION, TFM_EDGE_SLIDE, TFM_VERT_SLIDE)) {
+ restoreTransObjects(t);
resetTransModal(t);
resetTransRestrictions(t);
if (t->mode == TFM_ROTATION) {
- restoreTransObjects(t);
initTrackball(t);
}
else {
- restoreTransObjects(t);
initRotation(t);
}
initSnapping(t, NULL); // need to reinit after mode change
@@ -1083,9 +1088,9 @@ int transformEvent(TransInfo *t, const wmEvent *event)
stopConstraint(t);
}
+ restoreTransObjects(t);
resetTransModal(t);
resetTransRestrictions(t);
- restoreTransObjects(t);
initResize(t);
initSnapping(t, NULL); // need to reinit after mode change
t->redraw |= TREDRAW_HARD;
@@ -1123,47 +1128,22 @@ int transformEvent(TransInfo *t, const wmEvent *event)
handled = true;
break;
case TFM_MODAL_AXIS_X:
- if ((t->flag & T_NO_CONSTRAINT) == 0) {
- if (cmode == 'X') {
- stopConstraint(t);
- }
- else {
- if (t->flag & T_2D_EDIT) {
- setUserConstraint(t, V3D_MANIP_GLOBAL, (CON_AXIS0), IFACE_("along X"));
- }
- else {
- setUserConstraint(t, t->current_orientation, (CON_AXIS0), IFACE_("along %s X"));
- }
- }
+ if (!(t->flag & T_NO_CONSTRAINT)) {
+ transform_event_xyz_constraint(t, XKEY, cmode);
t->redraw |= TREDRAW_HARD;
handled = true;
}
break;
case TFM_MODAL_AXIS_Y:
if ((t->flag & T_NO_CONSTRAINT) == 0) {
- if (cmode == 'Y') {
- stopConstraint(t);
- }
- else {
- if (t->flag & T_2D_EDIT) {
- setUserConstraint(t, V3D_MANIP_GLOBAL, (CON_AXIS1), IFACE_("along Y"));
- }
- else {
- setUserConstraint(t, t->current_orientation, (CON_AXIS1), IFACE_("along %s Y"));
- }
- }
+ transform_event_xyz_constraint(t, YKEY, cmode);
t->redraw |= TREDRAW_HARD;
handled = true;
}
break;
case TFM_MODAL_AXIS_Z:
- if ((t->flag & (T_NO_CONSTRAINT | T_2D_EDIT)) == 0) {
- if (cmode == 'Z') {
- stopConstraint(t);
- }
- else {
- setUserConstraint(t, t->current_orientation, (CON_AXIS2), IFACE_("along %s Z"));
- }
+ if ((t->flag & (T_NO_CONSTRAINT)) == 0) {
+ transform_event_xyz_constraint(t, ZKEY, cmode);
t->redraw |= TREDRAW_HARD;
handled = true;
}
@@ -1235,7 +1215,7 @@ int transformEvent(TransInfo *t, const wmEvent *event)
break;
case TFM_MODAL_PROPSIZE_UP:
if (t->flag & T_PROP_EDIT) {
- t->prop_size *= 1.1f;
+ t->prop_size *= (t->modifiers & MOD_PRECISION) ? 1.01f : 1.1f;
if (t->spacetype == SPACE_VIEW3D && t->persp != RV3D_ORTHO)
t->prop_size = min_ff(t->prop_size, ((View3D *)t->view)->far);
calculatePropRatio(t);
@@ -1245,17 +1225,12 @@ int transformEvent(TransInfo *t, const wmEvent *event)
break;
case TFM_MODAL_PROPSIZE_DOWN:
if (t->flag & T_PROP_EDIT) {
- t->prop_size *= 0.90909090f;
+ t->prop_size /= (t->modifiers & MOD_PRECISION) ? 1.01f : 1.1f;
calculatePropRatio(t);
t->redraw |= TREDRAW_HARD;
handled = true;
}
break;
- case TFM_MODAL_EDGESLIDE_UP:
- case TFM_MODAL_EDGESLIDE_DOWN:
- t->redraw |= TREDRAW_HARD;
- handled = true;
- break;
case TFM_MODAL_AUTOIK_LEN_INC:
if (t->flag & T_AUTOIK) {
transform_autoik_update(t, 1);
@@ -1270,6 +1245,28 @@ int transformEvent(TransInfo *t, const wmEvent *event)
handled = true;
}
break;
+ case TFM_MODAL_INSERTOFS_TOGGLE_DIR:
+ if (t->spacetype == SPACE_NODE) {
+ SpaceNode *snode = (SpaceNode *)t->sa->spacedata.first;
+
+ BLI_assert(t->sa->spacetype == t->spacetype);
+
+ if (snode->insert_ofs_dir == SNODE_INSERTOFS_DIR_RIGHT) {
+ snode->insert_ofs_dir = SNODE_INSERTOFS_DIR_LEFT;
+ }
+ else if (snode->insert_ofs_dir == SNODE_INSERTOFS_DIR_LEFT) {
+ snode->insert_ofs_dir = SNODE_INSERTOFS_DIR_RIGHT;
+ }
+ else {
+ BLI_assert(0);
+ }
+
+ t->redraw |= TREDRAW_SOFT;
+ }
+ break;
+ /* Those two are only handled in transform's own handler, see T44634! */
+ case TFM_MODAL_EDGESLIDE_UP:
+ case TFM_MODAL_EDGESLIDE_DOWN:
default:
break;
}
@@ -1340,9 +1337,9 @@ int transformEvent(TransInfo *t, const wmEvent *event)
case GKEY:
/* only switch when... */
if (ELEM(t->mode, TFM_ROTATION, TFM_RESIZE, TFM_TRACKBALL)) {
+ restoreTransObjects(t);
resetTransModal(t);
resetTransRestrictions(t);
- restoreTransObjects(t);
initTranslation(t);
initSnapping(t, NULL); // need to reinit after mode change
t->redraw |= TREDRAW_HARD;
@@ -1352,9 +1349,9 @@ int transformEvent(TransInfo *t, const wmEvent *event)
case SKEY:
/* only switch when... */
if (ELEM(t->mode, TFM_ROTATION, TFM_TRANSLATION, TFM_TRACKBALL)) {
+ restoreTransObjects(t);
resetTransModal(t);
resetTransRestrictions(t);
- restoreTransObjects(t);
initResize(t);
initSnapping(t, NULL); // need to reinit after mode change
t->redraw |= TREDRAW_HARD;
@@ -1365,15 +1362,14 @@ int transformEvent(TransInfo *t, const wmEvent *event)
/* only switch when... */
if (!(t->options & CTX_TEXTURE)) {
if (ELEM(t->mode, TFM_ROTATION, TFM_RESIZE, TFM_TRACKBALL, TFM_TRANSLATION)) {
+ restoreTransObjects(t);
resetTransModal(t);
resetTransRestrictions(t);
if (t->mode == TFM_ROTATION) {
- restoreTransObjects(t);
initTrackball(t);
}
else {
- restoreTransObjects(t);
initRotation(t);
}
initSnapping(t, NULL); // need to reinit after mode change
@@ -1418,7 +1414,7 @@ int transformEvent(TransInfo *t, const wmEvent *event)
break;
case PADPLUSKEY:
if (event->alt && t->flag & T_PROP_EDIT) {
- t->prop_size *= 1.1f;
+ t->prop_size *= (t->modifiers & MOD_PRECISION) ? 1.01f : 1.1f;
if (t->spacetype == SPACE_VIEW3D && t->persp != RV3D_ORTHO)
t->prop_size = min_ff(t->prop_size, ((View3D *)t->view)->far);
calculatePropRatio(t);
@@ -1439,7 +1435,7 @@ int transformEvent(TransInfo *t, const wmEvent *event)
break;
case PADMINUS:
if (event->alt && t->flag & T_PROP_EDIT) {
- t->prop_size *= 0.90909090f;
+ t->prop_size /= (t->modifiers & MOD_PRECISION) ? 1.01f : 1.1f;
calculatePropRatio(t);
t->redraw = TREDRAW_HARD;
handled = true;
@@ -1509,6 +1505,13 @@ int transformEvent(TransInfo *t, const wmEvent *event)
}
}
+ /* if we change snap options, get the unsnapped values back */
+ if ((t->modifiers & (MOD_SNAP | MOD_SNAP_INVERT)) !=
+ (modifiers_prev & (MOD_SNAP | MOD_SNAP_INVERT)))
+ {
+ applyMouseInput(t, &t->mouse, t->mval, t->values);
+ }
+
/* Per transform event, if present */
if (t->handleEvent &&
(!handled ||
@@ -1569,7 +1572,7 @@ bool calculateTransformCenter(bContext *C, int centerMode, float cent3d[3], floa
if (cent3d) {
// Copy center from constraint center. Transform center can be local
- copy_v3_v3(cent3d, t->con.center);
+ copy_v3_v3(cent3d, t->center_global);
}
}
@@ -1716,7 +1719,7 @@ static void drawHelpline(bContext *UNUSED(C), int x, int y, void *customdata)
glVertex2fv(cent);
glEnd();
- glTranslatef(mval[0], mval[1], 0);
+ glTranslate2fv((const float *)mval);
glRotatef(-RAD2DEGF(atan2f(cent[0] - t->mval[0], cent[1] - t->mval[1])), 0, 0, 1);
setlinestyle(0);
@@ -1728,7 +1731,7 @@ static void drawHelpline(bContext *UNUSED(C), int x, int y, void *customdata)
case HLP_HARROW:
UI_ThemeColor(TH_VIEW_OVERLAY);
- glTranslatef(mval[0], mval[1], 0);
+ glTranslate2fv((const float *)mval);
glLineWidth(3.0);
drawArrow(RIGHT, 5, 10, 5);
@@ -1738,7 +1741,7 @@ static void drawHelpline(bContext *UNUSED(C), int x, int y, void *customdata)
case HLP_VARROW:
UI_ThemeColor(TH_VIEW_OVERLAY);
- glTranslatef(mval[0], mval[1], 0);
+ glTranslate2fv((const float *)mval);
glLineWidth(3.0);
drawArrow(UP, 5, 10, 5);
@@ -1789,7 +1792,7 @@ static void drawHelpline(bContext *UNUSED(C), int x, int y, void *customdata)
unsigned char col[3], col2[3];
UI_GetThemeColor3ubv(TH_GRID, col);
- glTranslatef(mval[0], mval[1], 0);
+ glTranslate2fv((const float *)mval);
glLineWidth(3.0);
@@ -1822,8 +1825,8 @@ static void drawTransformView(const struct bContext *C, ARegion *UNUSED(ar), voi
drawSnapping(C, t);
/* edge slide, vert slide */
- drawEdgeSlide(C, t);
- drawVertSlide(C, t);
+ drawEdgeSlide(t);
+ drawVertSlide(t);
}
/* just draw a little warning message in the top-right corner of the viewport to warn that autokeying is enabled */
@@ -1932,7 +1935,11 @@ void saveTransform(bContext *C, TransInfo *t, wmOperator *op)
if ((prop = RNA_struct_find_property(op->ptr, "proportional")) &&
!RNA_property_is_set(op->ptr, prop))
{
- if (t->obedit)
+ if (t->spacetype == SPACE_IPO)
+ ts->proportional_fcurve = proportional;
+ else if (t->spacetype == SPACE_ACTION)
+ ts->proportional_action = proportional;
+ else if (t->obedit)
ts->proportional = proportional;
else if (t->options & CTX_MASK)
ts->proportional_mask = (proportional != PROP_EDIT_OFF);
@@ -1972,8 +1979,8 @@ void saveTransform(bContext *C, TransInfo *t, wmOperator *op)
}
}
- if (RNA_struct_find_property(op->ptr, "proportional")) {
- RNA_enum_set(op->ptr, "proportional", proportional);
+ if ((prop = RNA_struct_find_property(op->ptr, "proportional"))) {
+ RNA_property_enum_set(op->ptr, prop, proportional);
RNA_enum_set(op->ptr, "proportional_edit_falloff", t->prop_mode);
RNA_float_set(op->ptr, "proportional_size", t->prop_size);
}
@@ -1983,7 +1990,7 @@ void saveTransform(bContext *C, TransInfo *t, wmOperator *op)
}
if ((prop = RNA_struct_find_property(op->ptr, "mirror"))) {
- RNA_property_boolean_set(op->ptr, prop, t->flag & T_MIRROR);
+ RNA_property_boolean_set(op->ptr, prop, (t->flag & T_MIRROR) != 0);
}
if ((prop = RNA_struct_find_property(op->ptr, "constraint_axis"))) {
@@ -2011,6 +2018,18 @@ void saveTransform(bContext *C, TransInfo *t, wmOperator *op)
RNA_property_boolean_set_array(op->ptr, prop, constraint_axis);
}
+
+ {
+ const char *prop_id = NULL;
+ if (t->mode == TFM_SHRINKFATTEN) {
+ prop_id = "use_even_offset";
+ }
+
+ if (prop_id && (prop = RNA_struct_find_property(op->ptr, prop_id))) {
+
+ RNA_property_boolean_set(op->ptr, prop, (t->flag & T_ALT_TRANSFORM) != 0);
+ }
+ }
}
/* note: caller needs to free 't' on a 0 return */
@@ -2030,6 +2049,12 @@ bool initTransform(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve
options |= CTX_TEXTURE;
}
}
+
+ if ((prop = RNA_struct_find_property(op->ptr, "gpencil_strokes")) && RNA_property_is_set(op->ptr, prop)) {
+ if (RNA_property_boolean_get(op->ptr, prop)) {
+ options |= CTX_GPENCIL_STROKES;
+ }
+ }
t->options = options;
@@ -2050,36 +2075,41 @@ bool initTransform(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve
t->launch_event = LEFTMOUSE;
}
+ unit_m3(t->spacemtx);
+
initTransInfo(C, t, op, event);
+ initTransformOrientation(C, t);
if (t->spacetype == SPACE_VIEW3D) {
- //calc_manipulator_stats(curarea);
- initTransformOrientation(C, t);
-
t->draw_handle_apply = ED_region_draw_cb_activate(t->ar->type, drawTransformApply, t, REGION_DRAW_PRE_VIEW);
t->draw_handle_view = ED_region_draw_cb_activate(t->ar->type, drawTransformView, t, REGION_DRAW_POST_VIEW);
t->draw_handle_pixel = ED_region_draw_cb_activate(t->ar->type, drawTransformPixel, t, REGION_DRAW_POST_PIXEL);
t->draw_handle_cursor = WM_paint_cursor_activate(CTX_wm_manager(C), helpline_poll, drawHelpline, t);
}
else if (t->spacetype == SPACE_IMAGE) {
- unit_m3(t->spacemtx);
t->draw_handle_view = ED_region_draw_cb_activate(t->ar->type, drawTransformView, t, REGION_DRAW_POST_VIEW);
//t->draw_handle_pixel = ED_region_draw_cb_activate(t->ar->type, drawTransformPixel, t, REGION_DRAW_POST_PIXEL);
t->draw_handle_cursor = WM_paint_cursor_activate(CTX_wm_manager(C), helpline_poll, drawHelpline, t);
}
else if (t->spacetype == SPACE_CLIP) {
- unit_m3(t->spacemtx);
t->draw_handle_view = ED_region_draw_cb_activate(t->ar->type, drawTransformView, t, REGION_DRAW_POST_VIEW);
t->draw_handle_cursor = WM_paint_cursor_activate(CTX_wm_manager(C), helpline_poll, drawHelpline, t);
}
else if (t->spacetype == SPACE_NODE) {
- unit_m3(t->spacemtx);
/*t->draw_handle_apply = ED_region_draw_cb_activate(t->ar->type, drawTransformApply, t, REGION_DRAW_PRE_VIEW);*/
t->draw_handle_view = ED_region_draw_cb_activate(t->ar->type, drawTransformView, t, REGION_DRAW_POST_VIEW);
t->draw_handle_cursor = WM_paint_cursor_activate(CTX_wm_manager(C), helpline_poll, drawHelpline, t);
}
- else
- unit_m3(t->spacemtx);
+ else if (t->spacetype == SPACE_IPO) {
+ t->draw_handle_view = ED_region_draw_cb_activate(t->ar->type, drawTransformView, t, REGION_DRAW_POST_VIEW);
+ //t->draw_handle_pixel = ED_region_draw_cb_activate(t->ar->type, drawTransformPixel, t, REGION_DRAW_POST_PIXEL);
+ t->draw_handle_cursor = WM_paint_cursor_activate(CTX_wm_manager(C), helpline_poll, drawHelpline, t);
+ }
+ else if (t->spacetype == SPACE_ACTION) {
+ t->draw_handle_view = ED_region_draw_cb_activate(t->ar->type, drawTransformView, t, REGION_DRAW_POST_VIEW);
+ //t->draw_handle_pixel = ED_region_draw_cb_activate(t->ar->type, drawTransformPixel, t, REGION_DRAW_POST_PIXEL);
+ t->draw_handle_cursor = WM_paint_cursor_activate(CTX_wm_manager(C), helpline_poll, drawHelpline, t);
+ }
createTransData(C, t); // make TransData structs from selection
@@ -2118,6 +2148,8 @@ bool initTransform(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve
initSnapping(t, op); // Initialize snapping data AFTER mode flags
+ initSnapSpatial(t, t->snap_spatial);
+
/* EVIL! posemode code can switch translation to rotate when 1 bone is selected. will be removed (ton) */
/* EVIL2: we gave as argument also texture space context bit... was cleared */
/* EVIL3: extend mode for animation editors also switches modes... but is best way to avoid duplicate code */
@@ -2162,6 +2194,9 @@ bool initTransform(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve
case TFM_MASK_SHRINKFATTEN:
initMaskShrinkFatten(t);
break;
+ case TFM_GPENCIL_SHRINKFATTEN:
+ initGPShrinkFatten(t);
+ break;
case TFM_TRACKBALL:
initTrackball(t);
break;
@@ -2174,18 +2209,28 @@ bool initTransform(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve
case TFM_BONESIZE:
{ /* used for both B-Bone width (bonesize) as for deform-dist (envelope) */
bArmature *arm = t->poseobj->data;
- if (arm->drawtype == ARM_ENVELOPE)
+ if (arm->drawtype == ARM_ENVELOPE) {
initBoneEnvelope(t);
- else
+ t->mode = TFM_BONE_ENVELOPE_DIST;
+ }
+ else {
initBoneSize(t);
+ }
break;
}
case TFM_BONE_ENVELOPE:
initBoneEnvelope(t);
break;
+ case TFM_BONE_ENVELOPE_DIST:
+ initBoneEnvelope(t);
+ t->mode = TFM_BONE_ENVELOPE_DIST;
+ break;
case TFM_EDGE_SLIDE:
- initEdgeSlide(t);
+ {
+ const bool use_double_side = (op ? !RNA_boolean_get(op->ptr, "single_side") : true);
+ initEdgeSlide_ex(t, use_double_side);
break;
+ }
case TFM_VERT_SLIDE:
initVertSlide(t);
break;
@@ -2244,7 +2289,6 @@ bool initTransform(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve
return 0;
}
-
/* overwrite initial values if operator supplied a non-null vector */
if ((prop = RNA_struct_find_property(op->ptr, "value")) && RNA_property_is_set(op->ptr, prop)) {
float values[4] = {0}; /* in case value isn't length 4, avoid uninitialized memory */
@@ -2340,8 +2384,12 @@ int transformEnd(bContext *C, TransInfo *t)
/* handle restoring objects */
if (t->state == TRANS_CANCEL) {
/* exception, edge slide transformed UVs too */
- if (t->mode == TFM_EDGE_SLIDE)
+ if (t->mode == TFM_EDGE_SLIDE) {
doEdgeSlide(t, 0.0f);
+ }
+ else if (t->mode == TFM_VERT_SLIDE) {
+ doVertSlide(t, 0.0f);
+ }
exit_code = OPERATOR_CANCELLED;
restoreTransObjects(t); // calls recalcData()
@@ -2498,8 +2546,8 @@ static void protectedQuaternionBits(short protectflag, float quat[4], const floa
static void constraintTransLim(TransInfo *t, TransData *td)
{
if (td->con) {
- bConstraintTypeInfo *ctiLoc = BKE_constraint_typeinfo_from_type(CONSTRAINT_TYPE_LOCLIMIT);
- bConstraintTypeInfo *ctiDist = BKE_constraint_typeinfo_from_type(CONSTRAINT_TYPE_DISTLIMIT);
+ const bConstraintTypeInfo *ctiLoc = BKE_constraint_typeinfo_from_type(CONSTRAINT_TYPE_LOCLIMIT);
+ const bConstraintTypeInfo *ctiDist = BKE_constraint_typeinfo_from_type(CONSTRAINT_TYPE_DISTLIMIT);
bConstraintOb cob = {NULL};
bConstraint *con;
@@ -2514,7 +2562,7 @@ static void constraintTransLim(TransInfo *t, TransData *td)
/* Evaluate valid constraints */
for (con = td->con; con; con = con->next) {
- bConstraintTypeInfo *cti = NULL;
+ const bConstraintTypeInfo *cti = NULL;
ListBase targets = {NULL, NULL};
/* only consider constraint if enabled */
@@ -2601,7 +2649,7 @@ static void constraintob_from_transdata(bConstraintOb *cob, TransData *td)
static void constraintRotLim(TransInfo *UNUSED(t), TransData *td)
{
if (td->con) {
- bConstraintTypeInfo *cti = BKE_constraint_typeinfo_from_type(CONSTRAINT_TYPE_ROTLIMIT);
+ const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_from_type(CONSTRAINT_TYPE_ROTLIMIT);
bConstraintOb cob;
bConstraint *con;
bool do_limit = false;
@@ -2668,7 +2716,7 @@ static void constraintRotLim(TransInfo *UNUSED(t), TransData *td)
static void constraintSizeLim(TransInfo *t, TransData *td)
{
if (td->con && td->ext) {
- bConstraintTypeInfo *cti = BKE_constraint_typeinfo_from_type(CONSTRAINT_TYPE_SIZELIMIT);
+ const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_from_type(CONSTRAINT_TYPE_SIZELIMIT);
bConstraintOb cob = {NULL};
bConstraint *con;
float size_sign[3], size_abs[3];
@@ -2792,10 +2840,11 @@ static void initBend(TransInfo *t)
t->num.unit_type[0] = B_UNIT_ROTATION;
t->num.unit_type[1] = B_UNIT_LENGTH;
- t->flag |= T_NO_CONSTRAINT;
+ t->flag |= T_NO_CONSTRAINT | T_FREE_CUSTOMDATA;
//copy_v3_v3(t->center, ED_view3d_cursor3d_get(t->scene, t->view));
calculateCenterCursor(t, t->center);
+ calculateCenterGlobal(t);
t->val = 0.0f;
@@ -2870,6 +2919,8 @@ static void Bend(TransInfo *t, const int UNUSED(mval[2]))
values.scale = values.scale / data->warp_init_dist;
}
+ copy_v2_v2(t->values, values.vector);
+
/* header print for NumInput */
if (hasNumInput(&t->num)) {
char c[NUM_STR_REP_LEN * 2];
@@ -2887,8 +2938,6 @@ static void Bend(TransInfo *t, const int UNUSED(mval[2]))
WM_bool_as_string(is_clamp));
}
- copy_v2_v2(t->values, values.vector);
-
values.angle *= -1.0f;
values.scale *= data->warp_init_dist;
@@ -2943,6 +2992,13 @@ static void Bend(TransInfo *t, const int UNUSED(mval[2]))
add_v3_v3(vec, pivot);
mul_m3_v3(td->smtx, vec);
+
+ /* rotation */
+ if ((t->flag & T_POINTS) == 0) {
+ ElementRotation(t, td, mat, V3D_LOCAL);
+ }
+
+ /* location */
copy_v3_v3(td->loc, vec);
}
@@ -3038,6 +3094,8 @@ static void applyShear(TransInfo *t, const int UNUSED(mval[2]))
applyNumInput(&t->num, &value);
+ t->values[0] = value;
+
/* header print for NumInput */
if (hasNumInput(&t->num)) {
char c[NUM_STR_REP_LEN];
@@ -3051,8 +3109,6 @@ static void applyShear(TransInfo *t, const int UNUSED(mval[2]))
BLI_snprintf(str, MAX_INFO_LEN, IFACE_("Shear: %.3f %s (Press X or Y to set shear axis)"), value, t->proptext);
}
- t->values[0] = value;
-
unit_m3(smat);
// Custom data signals shear direction
@@ -3138,7 +3194,7 @@ static void initResize(TransInfo *t)
t->num.unit_type[2] = B_UNIT_NONE;
}
-static void headerResize(TransInfo *t, float vec[3], char str[MAX_INFO_LEN])
+static void headerResize(TransInfo *t, const float vec[3], char str[MAX_INFO_LEN])
{
char tvec[NUM_STR_REP_LEN * 3];
size_t ofs = 0;
@@ -3183,38 +3239,23 @@ static void headerResize(TransInfo *t, float vec[3], char str[MAX_INFO_LEN])
}
}
-/* FLT_EPSILON is too small [#29633], 0.0000001f starts to flip */
-#define TX_FLIP_EPS 0.00001f
-BLI_INLINE int tx_sign(const float a)
-{
- return (a < -TX_FLIP_EPS ? 1 : a > TX_FLIP_EPS ? 2 : 3);
-}
-BLI_INLINE int tx_vec_sign_flip(const float a[3], const float b[3])
-{
- return ((tx_sign(a[0]) & tx_sign(b[0])) == 0 ||
- (tx_sign(a[1]) & tx_sign(b[1])) == 0 ||
- (tx_sign(a[2]) & tx_sign(b[2])) == 0);
-}
-
-/* smat is reference matrix, only scaled */
+/**
+ * \a smat is reference matrix only.
+ *
+ * \note this is a tricky area, before making changes see: T29633, T42444
+ */
static void TransMat3ToSize(float mat[3][3], float smat[3][3], float size[3])
{
- float vec[3];
-
- copy_v3_v3(vec, mat[0]);
- size[0] = normalize_v3(vec);
- copy_v3_v3(vec, mat[1]);
- size[1] = normalize_v3(vec);
- copy_v3_v3(vec, mat[2]);
- size[2] = normalize_v3(vec);
-
+ float rmat[3][3];
+
+ mat3_to_rot_size(rmat, size, mat);
+
/* first tried with dotproduct... but the sign flip is crucial */
- if (tx_vec_sign_flip(mat[0], smat[0]) ) size[0] = -size[0];
- if (tx_vec_sign_flip(mat[1], smat[1]) ) size[1] = -size[1];
- if (tx_vec_sign_flip(mat[2], smat[2]) ) size[2] = -size[2];
+ if (dot_v3v3(rmat[0], smat[0]) < 0.0f) size[0] = -size[0];
+ if (dot_v3v3(rmat[1], smat[1]) < 0.0f) size[1] = -size[1];
+ if (dot_v3v3(rmat[2], smat[2]) < 0.0f) size[2] = -size[2];
}
-
static void ElementResize(TransInfo *t, TransData *td, float mat[3][3])
{
float tmat[3][3], smat[3][3], center[3];
@@ -3330,7 +3371,7 @@ static void applyResize(TransInfo *t, const int mval[2])
ratio = t->values[0];
}
- size[0] = size[1] = size[2] = ratio;
+ copy_v3_fl(size, ratio);
snapGridIncrement(t, size);
@@ -3436,12 +3477,10 @@ static void applySkinResize(TransInfo *t, const int UNUSED(mval[2]))
{
TransData *td;
float size[3], mat[3][3];
- float ratio;
int i;
char str[MAX_INFO_LEN];
- ratio = t->values[0];
- size[0] = size[1] = size[2] = ratio;
+ copy_v3_fl(size, t->values[0]);
snapGridIncrement(t, size);
@@ -3546,10 +3585,7 @@ static void applyToSphere(TransInfo *t, const int UNUSED(mval[2]))
applyNumInput(&t->num, &ratio);
- if (ratio < 0)
- ratio = 0.0f;
- else if (ratio > 1)
- ratio = 1.0f;
+ CLAMP(ratio, 0.0f, 1.0f);
t->values[0] = ratio;
@@ -3918,6 +3954,8 @@ static void applyRotation(TransInfo *t, const int UNUSED(mval[2]))
final = angle_wrap_rad(final);
}
+ t->values[0] = final;
+
if (hasNumInput(&t->num)) {
char c[NUM_STR_REP_LEN];
@@ -3934,8 +3972,6 @@ static void applyRotation(TransInfo *t, const int UNUSED(mval[2]))
ofs += BLI_snprintf(str + ofs, MAX_INFO_LEN - ofs, IFACE_(" Proportional size: %.2f"), t->prop_size);
}
- t->values[0] = final;
-
applyRotationValue(t, final, t->axis);
recalcData(t);
@@ -4007,7 +4043,9 @@ static void applyTrackball(TransInfo *t, const int UNUSED(mval[2]))
char str[MAX_INFO_LEN];
size_t ofs = 0;
float axis1[3], axis2[3];
+#if 0 /* UNUSED */
float mat[3][3], totmat[3][3], smat[3][3];
+#endif
float phi[2];
copy_v3_v3(axis1, t->persinv[0]);
@@ -4015,13 +4053,14 @@ static void applyTrackball(TransInfo *t, const int UNUSED(mval[2]))
normalize_v3(axis1);
normalize_v3(axis2);
- phi[0] = t->values[0];
- phi[1] = t->values[1];
+ copy_v2_v2(phi, t->values);
snapGridIncrement(t, phi);
applyNumInput(&t->num, phi);
+ copy_v2_v2(t->values, phi);
+
if (hasNumInput(&t->num)) {
char c[NUM_STR_REP_LEN * 2];
@@ -4039,6 +4078,7 @@ static void applyTrackball(TransInfo *t, const int UNUSED(mval[2]))
ofs += BLI_snprintf(str + ofs, MAX_INFO_LEN - ofs, IFACE_(" Proportional size: %.2f"), t->prop_size);
}
+#if 0 /* UNUSED */
axis_angle_normalized_to_mat3(smat, axis1, phi[0]);
axis_angle_normalized_to_mat3(totmat, axis2, phi[1]);
@@ -4046,6 +4086,7 @@ static void applyTrackball(TransInfo *t, const int UNUSED(mval[2]))
// TRANSFORM_FIX_ME
//copy_m3_m3(t->mat, mat); // used in manipulator
+#endif
applyTrackballValue(t, axis1, axis2, phi);
@@ -4059,6 +4100,38 @@ static void applyTrackball(TransInfo *t, const int UNUSED(mval[2]))
/* -------------------------------------------------------------------- */
/* Transform (Translation) */
+static void initSnapSpatial(TransInfo *t, float r_snap[3])
+{
+ if (t->spacetype == SPACE_VIEW3D) {
+ RegionView3D *rv3d = t->ar->regiondata;
+
+ if (rv3d) {
+ r_snap[0] = 0.0f;
+ r_snap[1] = rv3d->gridview * 1.0f;
+ r_snap[2] = r_snap[1] * 0.1f;
+ }
+ }
+ else if (ELEM(t->spacetype, SPACE_IMAGE, SPACE_CLIP)) {
+ r_snap[0] = 0.0f;
+ r_snap[1] = 0.125f;
+ r_snap[2] = 0.0625f;
+ }
+ else if (t->spacetype == SPACE_NODE) {
+ r_snap[0] = 0.0f;
+ r_snap[1] = ED_node_grid_size();
+ r_snap[2] = ED_node_grid_size();
+ }
+ else if (t->spacetype == SPACE_IPO) {
+ r_snap[0] = 0.0f;
+ r_snap[1] = 1.0;
+ r_snap[2] = 0.1f;
+ }
+ else {
+ r_snap[0] = 0.0f;
+ r_snap[1] = r_snap[2] = 1.0f;
+ }
+}
+
/** \name Transform Translation
* \{ */
@@ -4066,6 +4139,9 @@ static void initTranslation(TransInfo *t)
{
if (t->spacetype == SPACE_ACTION) {
/* this space uses time translate */
+ BKE_report(t->reports, RPT_ERROR,
+ "Use 'Time_Translate' transform mode instead of 'Translation' mode "
+ "for translating keyframes in Dope Sheet Editor");
t->state = TRANS_CANCEL;
}
@@ -4078,29 +4154,7 @@ static void initTranslation(TransInfo *t)
t->num.flag = 0;
t->num.idx_max = t->idx_max;
- if (t->spacetype == SPACE_VIEW3D) {
- RegionView3D *rv3d = t->ar->regiondata;
-
- if (rv3d) {
- t->snap[0] = 0.0f;
- t->snap[1] = rv3d->gridview * 1.0f;
- t->snap[2] = t->snap[1] * 0.1f;
- }
- }
- else if (ELEM(t->spacetype, SPACE_IMAGE, SPACE_CLIP)) {
- t->snap[0] = 0.0f;
- t->snap[1] = 0.125f;
- t->snap[2] = 0.0625f;
- }
- else if (t->spacetype == SPACE_NODE) {
- t->snap[0] = 0.0f;
- t->snap[1] = ED_node_grid_size() * NODE_GRID_STEPS;
- t->snap[2] = ED_node_grid_size();
- }
- else {
- t->snap[0] = 0.0f;
- t->snap[1] = t->snap[2] = 1.0f;
- }
+ copy_v3_v3(t->snap, t->snap_spatial);
copy_v3_fl(t->num.val_inc, t->snap[1]);
t->num.unit_sys = t->scene->unit.system;
@@ -4118,7 +4172,7 @@ static void initTranslation(TransInfo *t)
}
}
-static void headerTranslation(TransInfo *t, float vec[3], char str[MAX_INFO_LEN])
+static void headerTranslation(TransInfo *t, const float vec[3], char str[MAX_INFO_LEN])
{
size_t ofs = 0;
char tvec[NUM_STR_REP_LEN * 3];
@@ -4209,9 +4263,26 @@ static void headerTranslation(TransInfo *t, float vec[3], char str[MAX_INFO_LEN]
if (t->flag & T_PROP_EDIT_ALL) {
ofs += BLI_snprintf(str + ofs, MAX_INFO_LEN - ofs, IFACE_(" Proportional size: %.2f"), t->prop_size);
}
+
+ if (t->spacetype == SPACE_NODE) {
+ SpaceNode *snode = (SpaceNode *)t->sa->spacedata.first;
+
+ if ((snode->flag & SNODE_SKIP_INSOFFSET) == 0) {
+ const char *str_old = BLI_strdup(str);
+ const char *str_dir = (snode->insert_ofs_dir == SNODE_INSERTOFS_DIR_RIGHT) ? "right" : "left";
+ char str_km[MAX_INFO_LEN];
+
+ WM_modalkeymap_items_to_string(t->keymap, TFM_MODAL_INSERTOFS_TOGGLE_DIR, true, sizeof(str_km), str_km);
+
+ ofs += BLI_snprintf(str, MAX_INFO_LEN, "Auto-offset set to %s - press %s to toggle direction | %s",
+ str_dir, str_km, str_old);
+
+ MEM_freeN((void *)str_old);
+ }
+ }
}
-static void applyTranslationValue(TransInfo *t, float vec[3])
+static void applyTranslationValue(TransInfo *t, const float vec[3])
{
TransData *td = t->data;
float tvec[3];
@@ -4223,29 +4294,21 @@ static void applyTranslationValue(TransInfo *t, float vec[3])
if (td->flag & TD_SKIP)
continue;
-
+
/* handle snapping rotation before doing the translation */
if (usingSnappingNormal(t)) {
if (validSnappingNormal(t)) {
const float *original_normal;
- float axis[3];
- float quat[4];
float mat[3][3];
- float angle;
/* In pose mode, we want to align normals with Y axis of bones... */
if (t->flag & T_POSE)
original_normal = td->axismtx[1];
else
original_normal = td->axismtx[2];
-
- cross_v3_v3v3(axis, original_normal, t->tsnap.snapNormal);
- angle = saacos(dot_v3v3(original_normal, t->tsnap.snapNormal));
-
- axis_angle_to_quat(quat, axis, angle);
-
- quat_to_mat3(mat, quat);
-
+
+ rotation_between_vecs_to_mat3(mat, original_normal, t->tsnap.snapNormal);
+
ElementRotation(t, td, mat, V3D_LOCAL);
}
else {
@@ -4371,6 +4434,8 @@ static void applyShrinkFatten(TransInfo *t, const int UNUSED(mval[2]))
applyNumInput(&t->num, &distance);
+ t->values[0] = -distance;
+
/* header print for NumInput */
ofs += BLI_strncpy_rlen(str + ofs, IFACE_("Shrink/Fatten:"), MAX_INFO_LEN - ofs);
if (hasNumInput(&t->num)) {
@@ -4391,16 +4456,13 @@ static void applyShrinkFatten(TransInfo *t, const int UNUSED(mval[2]))
if (t->keymap) {
wmKeyMapItem *kmi = WM_modalkeymap_find_propvalue(t->keymap, TFM_MODAL_RESIZE);
if (kmi) {
- ofs += WM_keymap_item_to_string(kmi, str + ofs, MAX_INFO_LEN - ofs);
+ ofs += WM_keymap_item_to_string(kmi, false, MAX_INFO_LEN - ofs, str + ofs);
}
}
BLI_snprintf(str + ofs, MAX_INFO_LEN - ofs, IFACE_(" or Alt) Even Thickness %s"),
WM_bool_as_string((t->flag & T_ALT_TRANSFORM) != 0));
/* done with header string */
-
- t->values[0] = -distance;
-
for (i = 0; i < t->total; i++, td++) {
float tdistance; /* temp dist */
if (td->flag & TD_NOACTION)
@@ -4467,6 +4529,8 @@ static void applyTilt(TransInfo *t, const int UNUSED(mval[2]))
applyNumInput(&t->num, &final);
+ t->values[0] = final;
+
if (hasNumInput(&t->num)) {
char c[NUM_STR_REP_LEN];
@@ -4544,6 +4608,8 @@ static void applyCurveShrinkFatten(TransInfo *t, const int UNUSED(mval[2]))
applyNumInput(&t->num, &ratio);
+ t->values[0] = ratio;
+
/* header print for NumInput */
if (hasNumInput(&t->num)) {
char c[NUM_STR_REP_LEN];
@@ -4622,6 +4688,8 @@ static void applyMaskShrinkFatten(TransInfo *t, const int UNUSED(mval[2]))
applyNumInput(&t->num, &ratio);
+ t->values[0] = ratio;
+
/* header print for NumInput */
if (hasNumInput(&t->num)) {
char c[NUM_STR_REP_LEN];
@@ -4677,6 +4745,85 @@ static void applyMaskShrinkFatten(TransInfo *t, const int UNUSED(mval[2]))
/* -------------------------------------------------------------------- */
+/* Transform (GPencil Shrink/Fatten) */
+
+/** \name Transform GPencil Strokes Shrink/Fatten
+ * \{ */
+
+static void initGPShrinkFatten(TransInfo *t)
+{
+ t->mode = TFM_GPENCIL_SHRINKFATTEN;
+ t->transform = applyGPShrinkFatten;
+
+ initMouseInputMode(t, &t->mouse, INPUT_SPRING);
+
+ t->idx_max = 0;
+ t->num.idx_max = 0;
+ t->snap[0] = 0.0f;
+ t->snap[1] = 0.1f;
+ t->snap[2] = t->snap[1] * 0.1f;
+
+ copy_v3_fl(t->num.val_inc, t->snap[1]);
+ t->num.unit_sys = t->scene->unit.system;
+ t->num.unit_type[0] = B_UNIT_NONE;
+
+ t->flag |= T_NO_ZERO;
+#ifdef USE_NUM_NO_ZERO
+ t->num.val_flag[0] |= NUM_NO_ZERO;
+#endif
+
+ t->flag |= T_NO_CONSTRAINT;
+}
+
+static void applyGPShrinkFatten(TransInfo *t, const int UNUSED(mval[2]))
+{
+ TransData *td = t->data;
+ float ratio;
+ int i;
+ char str[MAX_INFO_LEN];
+
+ ratio = t->values[0];
+
+ snapGridIncrement(t, &ratio);
+
+ applyNumInput(&t->num, &ratio);
+
+ t->values[0] = ratio;
+
+ /* header print for NumInput */
+ if (hasNumInput(&t->num)) {
+ char c[NUM_STR_REP_LEN];
+
+ outputNumInput(&(t->num), c, &t->scene->unit);
+ BLI_snprintf(str, MAX_INFO_LEN, IFACE_("Shrink/Fatten: %s"), c);
+ }
+ else {
+ BLI_snprintf(str, MAX_INFO_LEN, IFACE_("Shrink/Fatten: %3f"), ratio);
+ }
+
+ for (i = 0; i < t->total; i++, td++) {
+ if (td->flag & TD_NOACTION)
+ break;
+
+ if (td->flag & TD_SKIP)
+ continue;
+
+ if (td->val) {
+ *td->val = td->ival * ratio;
+ /* apply PET */
+ *td->val = (*td->val * td->factor) + ((1.0f - td->factor) * td->ival);
+ if (*td->val <= 0.0f) *td->val = 0.001f;
+ }
+ }
+
+ recalcData(t);
+
+ ED_area_headerprint(t->sa, str);
+}
+/** \} */
+
+
+/* -------------------------------------------------------------------- */
/* Transform (Push/Pull) */
/** \name Transform Push/Pull
@@ -4715,6 +4862,8 @@ static void applyPushPull(TransInfo *t, const int UNUSED(mval[2]))
applyNumInput(&t->num, &distance);
+ t->values[0] = distance;
+
/* header print for NumInput */
if (hasNumInput(&t->num)) {
char c[NUM_STR_REP_LEN];
@@ -4728,8 +4877,6 @@ static void applyPushPull(TransInfo *t, const int UNUSED(mval[2]))
BLI_snprintf(str, MAX_INFO_LEN, IFACE_("Push/Pull: %.4f%s %s"), distance, t->con.text, t->proptext);
}
- t->values[0] = distance;
-
if (t->con.applyRot && t->con.mode & CON_APPLY) {
t->con.applyRot(t, NULL, axis, NULL);
}
@@ -4802,12 +4949,14 @@ static void applyBevelWeight(TransInfo *t, const int UNUSED(mval[2]))
weight = t->values[0];
- if (weight > 1.0f) weight = 1.0f;
+ CLAMP_MAX(weight, 1.0f);
snapGridIncrement(t, &weight);
applyNumInput(&t->num, &weight);
+ t->values[0] = weight;
+
/* header print for NumInput */
if (hasNumInput(&t->num)) {
char c[NUM_STR_REP_LEN];
@@ -4880,12 +5029,14 @@ static void applyCrease(TransInfo *t, const int UNUSED(mval[2]))
crease = t->values[0];
- if (crease > 1.0f) crease = 1.0f;
+ CLAMP_MAX(crease, 1.0f);
snapGridIncrement(t, &crease);
applyNumInput(&t->num, &crease);
+ t->values[0] = crease;
+
/* header print for NumInput */
if (hasNumInput(&t->num)) {
char c[NUM_STR_REP_LEN];
@@ -4956,7 +5107,7 @@ static void initBoneSize(TransInfo *t)
t->num.unit_type[2] = B_UNIT_NONE;
}
-static void headerBoneSize(TransInfo *t, float vec[3], char str[MAX_INFO_LEN])
+static void headerBoneSize(TransInfo *t, const float vec[3], char str[MAX_INFO_LEN])
{
char tvec[NUM_STR_REP_LEN * 3];
if (hasNumInput(&t->num)) {
@@ -5019,7 +5170,7 @@ static void applyBoneSize(TransInfo *t, const int mval[2])
ratio = t->values[0];
}
- size[0] = size[1] = size[2] = ratio;
+ copy_v3_fl(size, ratio);
snapGridIncrement(t, size);
@@ -5027,6 +5178,8 @@ static void applyBoneSize(TransInfo *t, const int mval[2])
constraintNumInput(t, size);
}
+ copy_v3_v3(t->values, size);
+
size_to_mat3(mat, size);
if (t->con.applySize) {
@@ -5093,6 +5246,8 @@ static void applyBoneEnvelope(TransInfo *t, const int UNUSED(mval[2]))
applyNumInput(&t->num, &ratio);
+ t->values[0] = ratio;
+
/* header print for NumInput */
if (hasNumInput(&t->num)) {
char c[NUM_STR_REP_LEN];
@@ -5126,6 +5281,312 @@ static void applyBoneEnvelope(TransInfo *t, const int UNUSED(mval[2]))
}
/** \} */
+/* -------------------------------------------------------------------- */
+/* Original Data Store */
+
+/** \name Orig-Data Store Utility Functions
+ * \{ */
+
+static void slide_origdata_init_flag(
+ TransInfo *t, SlideOrigData *sod)
+{
+ BMEditMesh *em = BKE_editmesh_from_object(t->obedit);
+ BMesh *bm = em->bm;
+
+ if ((t->settings->uvcalc_flag & UVCALC_TRANSFORM_CORRECT) &&
+ /* don't do this at all for non-basis shape keys, too easy to
+ * accidentally break uv maps or vertex colors then */
+ (bm->shapenr <= 1) &&
+ CustomData_has_math(&bm->ldata))
+ {
+ sod->use_origfaces = true;
+ }
+ else {
+ sod->use_origfaces = false;
+ }
+}
+
+static void slide_origdata_init_data(
+ TransInfo *t, SlideOrigData *sod)
+{
+ if (sod->use_origfaces) {
+ BMEditMesh *em = BKE_editmesh_from_object(t->obedit);
+ BMesh *bm = em->bm;
+
+ sod->origfaces = BLI_ghash_ptr_new(__func__);
+ sod->bm_origfaces = BM_mesh_create(&bm_mesh_allocsize_default);
+ /* we need to have matching customdata */
+ BM_mesh_copy_init_customdata(sod->bm_origfaces, bm, NULL);
+ }
+}
+
+static void slide_origdata_create_data_vert(
+ BMesh *bm, SlideOrigData *sod,
+ TransDataGenericSlideVert *sv)
+{
+ BMIter liter;
+ int j, l_num;
+ float *loop_weights;
+
+ /* copy face data */
+ // BM_ITER_ELEM (l, &liter, sv->v, BM_LOOPS_OF_VERT) {
+ BM_iter_init(&liter, bm, BM_LOOPS_OF_VERT, sv->v);
+ l_num = liter.count;
+ loop_weights = BLI_array_alloca(loop_weights, l_num);
+ for (j = 0; j < l_num; j++) {
+ BMLoop *l = BM_iter_step(&liter);
+ BMLoop *l_prev, *l_next;
+ void **val_p;
+ if (!BLI_ghash_ensure_p(sod->origfaces, l->f, &val_p)) {
+ BMFace *f_copy = BM_face_copy(sod->bm_origfaces, bm, l->f, true, true);
+ *val_p = f_copy;
+ }
+
+ if ((l_prev = BM_loop_find_prev_nodouble(l, l->next, FLT_EPSILON)) &&
+ (l_next = BM_loop_find_next_nodouble(l, l_prev, FLT_EPSILON)))
+ {
+ loop_weights[j] = angle_v3v3v3(l_prev->v->co, l->v->co, l_next->v->co);
+ }
+ else {
+ loop_weights[j] = 0.0f;
+ }
+
+ }
+
+ /* store cd_loop_groups */
+ if (l_num != 0) {
+ sv->cd_loop_groups = BLI_memarena_alloc(sod->arena, sod->layer_math_map_num * sizeof(void *));
+ for (j = 0; j < sod->layer_math_map_num; j++) {
+ const int layer_nr = sod->layer_math_map[j];
+ sv->cd_loop_groups[j] = BM_vert_loop_groups_data_layer_create(bm, sv->v, layer_nr, loop_weights, sod->arena);
+ }
+ }
+ else {
+ sv->cd_loop_groups = NULL;
+ }
+
+ BLI_ghash_insert(sod->origverts, sv->v, sv);
+}
+
+static void slide_origdata_create_data(
+ TransInfo *t, SlideOrigData *sod,
+ TransDataGenericSlideVert *sv_array, unsigned int v_stride, unsigned int v_num)
+{
+ if (sod->use_origfaces) {
+ BMEditMesh *em = BKE_editmesh_from_object(t->obedit);
+ BMesh *bm = em->bm;
+ unsigned int i;
+ TransDataGenericSlideVert *sv;
+
+ int layer_index_dst;
+ int j;
+
+ /* over alloc, only 'math' layers are indexed */
+ sod->layer_math_map = MEM_mallocN(bm->ldata.totlayer * sizeof(int), __func__);
+ layer_index_dst = 0;
+ for (j = 0; j < bm->ldata.totlayer; j++) {
+ if (CustomData_layer_has_math(&bm->ldata, j)) {
+ sod->layer_math_map[layer_index_dst++] = j;
+ }
+ }
+ BLI_assert(layer_index_dst != 0);
+ sod->layer_math_map_num = layer_index_dst;
+
+ sod->arena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__);
+
+ sod->origverts = BLI_ghash_ptr_new_ex(__func__, v_num);
+
+ for (i = 0, sv = sv_array; i < v_num; i++, sv = POINTER_OFFSET(sv, v_stride)) {
+ slide_origdata_create_data_vert(bm, sod, sv);
+ }
+
+ if (t->flag & T_MIRROR) {
+ TransData *td = t->data;
+ TransDataGenericSlideVert *sv_mirror;
+
+ sod->sv_mirror = MEM_callocN(sizeof(*sv_mirror) * t->total, __func__);
+ sod->totsv_mirror = t->total;
+
+ sv_mirror = sod->sv_mirror;
+
+ for (i = 0; i < t->total; i++, td++) {
+ BMVert *eve = td->extra;
+ if (eve) {
+ sv_mirror->v = eve;
+ copy_v3_v3(sv_mirror->co_orig_3d, eve->co);
+
+ slide_origdata_create_data_vert(bm, sod, sv_mirror);
+ sv_mirror++;
+ }
+ else {
+ sod->totsv_mirror--;
+ }
+ }
+
+ if (sod->totsv_mirror == 0) {
+ MEM_freeN(sod->sv_mirror);
+ sod->sv_mirror = NULL;
+ }
+ }
+ }
+}
+
+/**
+ * If we're sliding the vert, return its original location, if not, the current location is good.
+ */
+static const float *slide_origdata_orig_vert_co(SlideOrigData *sod, BMVert *v)
+{
+ TransDataGenericSlideVert *sv = BLI_ghash_lookup(sod->origverts, v);
+ return sv ? sv->co_orig_3d : v->co;
+}
+
+static void slide_origdata_interp_data_vert(
+ SlideOrigData *sod, BMesh *bm, bool is_final,
+ TransDataGenericSlideVert *sv)
+{
+ BMIter liter;
+ int j, l_num;
+ float *loop_weights;
+ const bool do_loop_weight = (len_squared_v3v3(sv->v->co, sv->co_orig_3d) > FLT_EPSILON);
+ const float *v_proj_axis = sv->v->no;
+ /* original (l->prev, l, l->next) projections for each loop ('l' remains unchanged) */
+ float v_proj[3][3];
+
+ if (do_loop_weight) {
+ project_plane_v3_v3v3(v_proj[1], sv->co_orig_3d, v_proj_axis);
+ }
+
+ // BM_ITER_ELEM (l, &liter, sv->v, BM_LOOPS_OF_VERT) {
+ BM_iter_init(&liter, bm, BM_LOOPS_OF_VERT, sv->v);
+ l_num = liter.count;
+ loop_weights = do_loop_weight ? BLI_array_alloca(loop_weights, l_num) : NULL;
+ for (j = 0; j < l_num; j++) {
+ BMFace *f_copy; /* the copy of 'f' */
+ BMLoop *l = BM_iter_step(&liter);
+
+ f_copy = BLI_ghash_lookup(sod->origfaces, l->f);
+
+ /* only loop data, no vertex data since that contains shape keys,
+ * and we do not want to mess up other shape keys */
+ BM_loop_interp_from_face(bm, l, f_copy, false, is_final);
+
+ /* make sure face-attributes are correct (e.g. MTexPoly) */
+ BM_elem_attrs_copy(sod->bm_origfaces, bm, f_copy, l->f);
+
+ /* weight the loop */
+ if (do_loop_weight) {
+ const float eps = 1.0e-8f;
+ const BMLoop *l_prev = l->prev;
+ const BMLoop *l_next = l->next;
+ const float *co_prev = slide_origdata_orig_vert_co(sod, l_prev->v);
+ const float *co_next = slide_origdata_orig_vert_co(sod, l_next->v);
+ bool co_prev_ok;
+ bool co_next_ok;
+
+
+ /* In the unlikely case that we're next to a zero length edge - walk around the to the next.
+ * Since we only need to check if the vertex is in this corner,
+ * its not important _which_ loop - as long as its not overlapping 'sv->co_orig_3d', see: T45096. */
+ project_plane_v3_v3v3(v_proj[0], co_prev, v_proj_axis);
+ while (UNLIKELY(((co_prev_ok = (len_squared_v3v3(v_proj[1], v_proj[0]) > eps)) == false) &&
+ ((l_prev = l_prev->prev) != l->next)))
+ {
+ co_prev = slide_origdata_orig_vert_co(sod, l_prev->v);
+ project_plane_v3_v3v3(v_proj[0], co_prev, v_proj_axis);
+ }
+ project_plane_v3_v3v3(v_proj[2], co_next, v_proj_axis);
+ while (UNLIKELY(((co_next_ok = (len_squared_v3v3(v_proj[1], v_proj[2]) > eps)) == false) &&
+ ((l_next = l_next->next) != l->prev)))
+ {
+ co_next = slide_origdata_orig_vert_co(sod, l_next->v);
+ project_plane_v3_v3v3(v_proj[2], co_next, v_proj_axis);
+ }
+
+ if (co_prev_ok && co_next_ok) {
+ const float dist = dist_signed_squared_to_corner_v3v3v3(sv->v->co, UNPACK3(v_proj), v_proj_axis);
+
+ loop_weights[j] = (dist >= 0.0f) ? 1.0f : ((dist <= -eps) ? 0.0f : (1.0f + (dist / eps)));
+ if (UNLIKELY(!isfinite(loop_weights[j]))) {
+ loop_weights[j] = 0.0f;
+ }
+ }
+ else {
+ loop_weights[j] = 0.0f;
+ }
+ }
+ }
+
+ if (do_loop_weight) {
+ for (j = 0; j < sod->layer_math_map_num; j++) {
+ BM_vert_loop_groups_data_layer_merge_weights(bm, sv->cd_loop_groups[j], sod->layer_math_map[j], loop_weights);
+ }
+ }
+ else {
+ for (j = 0; j < sod->layer_math_map_num; j++) {
+ BM_vert_loop_groups_data_layer_merge(bm, sv->cd_loop_groups[j], sod->layer_math_map[j]);
+ }
+ }
+}
+
+static void slide_origdata_interp_data(
+ TransInfo *t, SlideOrigData *sod,
+ TransDataGenericSlideVert *sv, unsigned int v_stride, unsigned int v_num,
+ bool is_final)
+{
+ if (sod->use_origfaces) {
+ BMEditMesh *em = BKE_editmesh_from_object(t->obedit);
+ BMesh *bm = em->bm;
+ unsigned int i;
+
+ for (i = 0; i < v_num; i++, sv = POINTER_OFFSET(sv, v_stride)) {
+
+ if (sv->cd_loop_groups) {
+ slide_origdata_interp_data_vert(sod, bm, is_final, sv);
+ }
+ }
+
+ if (sod->sv_mirror) {
+ sv = sod->sv_mirror;
+ for (i = 0; i < v_num; i++, sv++) {
+ if (sv->cd_loop_groups) {
+ slide_origdata_interp_data_vert(sod, bm, is_final, sv);
+ }
+ }
+ }
+ }
+}
+
+static void slide_origdata_free_date(
+ SlideOrigData *sod)
+{
+ if (sod->use_origfaces) {
+ if (sod->bm_origfaces) {
+ BM_mesh_free(sod->bm_origfaces);
+ sod->bm_origfaces = NULL;
+ }
+
+ if (sod->origfaces) {
+ BLI_ghash_free(sod->origfaces, NULL, NULL);
+ sod->origfaces = NULL;
+ }
+
+ if (sod->origverts) {
+ BLI_ghash_free(sod->origverts, NULL, NULL);
+ sod->origverts = NULL;
+ }
+
+ if (sod->arena) {
+ BLI_memarena_free(sod->arena);
+ sod->arena = NULL;
+ }
+
+ MEM_SAFE_FREE(sod->layer_math_map);
+
+ MEM_SAFE_FREE(sod->sv_mirror);
+ }
+}
+
+/** \} */
/* -------------------------------------------------------------------- */
/* Transform (Edge Slide) */
@@ -5133,6 +5594,19 @@ static void applyBoneEnvelope(TransInfo *t, const int UNUSED(mval[2]))
/** \name Transform Edge Slide
* \{ */
+static void calcEdgeSlideCustomPoints(struct TransInfo *t)
+{
+ EdgeSlideData *sld = t->customData;
+
+ setCustomPoints(t, &t->mouse, sld->mval_end, sld->mval_start);
+
+ /* setCustomPoints isn't normally changing as the mouse moves,
+ * in this case apply mouse input immediatly so we don't refresh
+ * with the value from the previous points */
+ applyMouseInput(t, &t->mouse, t->mval, t->values);
+}
+
+
static BMEdge *get_other_edge(BMVert *v, BMEdge *e)
{
BMIter iter;
@@ -5148,7 +5622,7 @@ static BMEdge *get_other_edge(BMVert *v, BMEdge *e)
}
/* interpoaltes along a line made up of 2 segments (used for edge slide) */
-static void interp_line_v3_v3v3v3(float p[3], const float v1[3], const float v2[3], const float v3[3], const float t)
+static void interp_line_v3_v3v3v3(float p[3], const float v1[3], const float v2[3], const float v3[3], float t)
{
float t_mid, t_delta;
@@ -5156,17 +5630,28 @@ static void interp_line_v3_v3v3v3(float p[3], const float v1[3], const float v2[
t_mid = line_point_factor_v3(v2, v1, v3);
t_delta = t - t_mid;
- if (fabsf(t_delta) < FLT_EPSILON) {
- copy_v3_v3(p, v2);
- }
- else if (t_delta < 0.0f) {
- interp_v3_v3v3(p, v1, v2, t / t_mid);
+ if (t_delta < 0.0f) {
+ if (UNLIKELY(fabsf(t_mid) < FLT_EPSILON)) {
+ copy_v3_v3(p, v2);
+ }
+ else {
+ interp_v3_v3v3(p, v1, v2, t / t_mid);
+ }
}
else {
- interp_v3_v3v3(p, v2, v3, (t - t_mid) / (1.0f - t_mid));
+ t = t - t_mid;
+ t_mid = 1.0f - t_mid;
+
+ if (UNLIKELY(fabsf(t_mid) < FLT_EPSILON)) {
+ copy_v3_v3(p, v3);
+ }
+ else {
+ interp_v3_v3v3(p, v2, v3, t / t_mid);
+ }
}
}
+
static void len_v3_ensure(float v[3], const float length)
{
normalize_v3(v);
@@ -5311,7 +5796,171 @@ static BMLoop *get_next_loop(BMVert *v, BMLoop *l,
return NULL;
}
-static void calcNonProportionalEdgeSlide(TransInfo *t, EdgeSlideData *sld, const float mval[2])
+/**
+ * Calculate screenspace `mval_start` / `mval_end`, optionally slide direction.
+ */
+static void calcEdgeSlide_mval_range(
+ TransInfo *t, EdgeSlideData *sld, const int *sv_table, const int loop_nr,
+ const float mval[2], const bool use_btree_disp, const bool use_calc_direction)
+{
+ TransDataEdgeSlideVert *sv_array = sld->sv;
+ BMEditMesh *em = BKE_editmesh_from_object(t->obedit);
+ BMesh *bm = em->bm;
+ ARegion *ar = t->ar;
+ View3D *v3d = NULL;
+ RegionView3D *rv3d = NULL;
+ float projectMat[4][4];
+ BMBVHTree *btree;
+
+ /* only for use_calc_direction */
+ float (*loop_dir)[3] = NULL, *loop_maxdist = NULL;
+
+ float mval_start[2], mval_end[2];
+ float mval_dir[3], dist_best_sq;
+ BMIter iter;
+ BMEdge *e;
+
+ if (t->spacetype == SPACE_VIEW3D) {
+ /* background mode support */
+ v3d = t->sa ? t->sa->spacedata.first : NULL;
+ rv3d = t->ar ? t->ar->regiondata : NULL;
+ }
+
+ if (!rv3d) {
+ /* ok, let's try to survive this */
+ unit_m4(projectMat);
+ }
+ else {
+ ED_view3d_ob_project_mat_get(rv3d, t->obedit, projectMat);
+ }
+
+ if (use_btree_disp) {
+ btree = BKE_bmbvh_new_from_editmesh(em, BMBVH_RESPECT_HIDDEN, NULL, false);
+ }
+ else {
+ btree = NULL;
+ }
+
+ /* find mouse vectors, the global one, and one per loop in case we have
+ * multiple loops selected, in case they are oriented different */
+ zero_v3(mval_dir);
+ dist_best_sq = -1.0f;
+
+ if (use_calc_direction) {
+ loop_dir = MEM_callocN(sizeof(float[3]) * loop_nr, "sv loop_dir");
+ loop_maxdist = MEM_mallocN(sizeof(float) * loop_nr, "sv loop_maxdist");
+ copy_vn_fl(loop_maxdist, loop_nr, -1.0f);
+ }
+
+ BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
+ if (BM_elem_flag_test(e, BM_ELEM_SELECT)) {
+ int i;
+
+ /* search cross edges for visible edge to the mouse cursor,
+ * then use the shared vertex to calculate screen vector*/
+ for (i = 0; i < 2; i++) {
+ BMIter iter_other;
+ BMEdge *e_other;
+
+ BMVert *v = i ? e->v1 : e->v2;
+ BM_ITER_ELEM (e_other, &iter_other, v, BM_EDGES_OF_VERT) {
+ /* screen-space coords */
+ float sco_a[3], sco_b[3];
+ float dist_sq;
+ int j, l_nr;
+
+ if (BM_elem_flag_test(e_other, BM_ELEM_SELECT))
+ continue;
+
+ /* This test is only relevant if object is not wire-drawn! See [#32068]. */
+ if (use_btree_disp && !BMBVH_EdgeVisible(btree, e_other, ar, v3d, t->obedit)) {
+ continue;
+ }
+
+ BLI_assert(sv_table[BM_elem_index_get(v)] != -1);
+ j = sv_table[BM_elem_index_get(v)];
+
+ if (sv_array[j].v_side[1]) {
+ ED_view3d_project_float_v3_m4(ar, sv_array[j].v_side[1]->co, sco_b, projectMat);
+ }
+ else {
+ add_v3_v3v3(sco_b, v->co, sv_array[j].dir_side[1]);
+ ED_view3d_project_float_v3_m4(ar, sco_b, sco_b, projectMat);
+ }
+
+ if (sv_array[j].v_side[0]) {
+ ED_view3d_project_float_v3_m4(ar, sv_array[j].v_side[0]->co, sco_a, projectMat);
+ }
+ else {
+ add_v3_v3v3(sco_a, v->co, sv_array[j].dir_side[0]);
+ ED_view3d_project_float_v3_m4(ar, sco_a, sco_a, projectMat);
+ }
+
+ /* global direction */
+ dist_sq = dist_squared_to_line_segment_v2(mval, sco_b, sco_a);
+ if ((dist_best_sq == -1.0f) ||
+ /* intentionally use 2d size on 3d vector */
+ (dist_sq < dist_best_sq && (len_squared_v2v2(sco_b, sco_a) > 0.1f)))
+ {
+ dist_best_sq = dist_sq;
+ sub_v3_v3v3(mval_dir, sco_b, sco_a);
+ }
+
+ if (use_calc_direction) {
+ /* per loop direction */
+ l_nr = sv_array[j].loop_nr;
+ if (loop_maxdist[l_nr] == -1.0f || dist_sq < loop_maxdist[l_nr]) {
+ loop_maxdist[l_nr] = dist_sq;
+ sub_v3_v3v3(loop_dir[l_nr], sco_b, sco_a);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (use_calc_direction) {
+ int i;
+ sv_array = sld->sv;
+ for (i = 0; i < sld->totsv; i++, sv_array++) {
+ /* switch a/b if loop direction is different from global direction */
+ int l_nr = sv_array->loop_nr;
+ if (dot_v3v3(loop_dir[l_nr], mval_dir) < 0.0f) {
+ swap_v3_v3(sv_array->dir_side[0], sv_array->dir_side[1]);
+ SWAP(BMVert *, sv_array->v_side[0], sv_array->v_side[1]);
+ }
+ }
+
+ MEM_freeN(loop_dir);
+ MEM_freeN(loop_maxdist);
+ }
+
+ /* possible all of the edge loops are pointing directly at the view */
+ if (UNLIKELY(len_squared_v2(mval_dir) < 0.1f)) {
+ mval_dir[0] = 0.0f;
+ mval_dir[1] = 100.0f;
+ }
+
+ /* zero out start */
+ zero_v2(mval_start);
+
+ /* dir holds a vector along edge loop */
+ copy_v2_v2(mval_end, mval_dir);
+ mul_v2_fl(mval_end, 0.5f);
+
+ sld->mval_start[0] = t->mval[0] + mval_start[0];
+ sld->mval_start[1] = t->mval[1] + mval_start[1];
+
+ sld->mval_end[0] = t->mval[0] + mval_end[0];
+ sld->mval_end[1] = t->mval[1] + mval_end[1];
+
+ if (btree) {
+ BKE_bmbvh_free(btree);
+ }
+}
+
+static void calcEdgeSlide_non_proportional(
+ TransInfo *t, EdgeSlideData *sld, const float mval[2])
{
TransDataEdgeSlideVert *sv = sld->sv;
@@ -5341,7 +5990,7 @@ static void calcNonProportionalEdgeSlide(TransInfo *t, EdgeSlideData *sld, const
for (i = 0; i < sld->totsv; i++, sv++) {
/* Set length */
- sv->edge_len = len_v3v3(sv->dir_a, sv->dir_b);
+ sv->edge_len = len_v3v3(sv->dir_side[0], sv->dir_side[1]);
ED_view3d_project_float_v2_m4(ar, sv->v->co, v_proj, projectMat);
dist_sq = len_squared_v2v2(mval, v_proj);
@@ -5356,7 +6005,7 @@ static void calcNonProportionalEdgeSlide(TransInfo *t, EdgeSlideData *sld, const
}
}
-static bool createEdgeSlideVerts(TransInfo *t)
+static bool createEdgeSlideVerts_double_side(TransInfo *t)
{
BMEditMesh *em = BKE_editmesh_from_object(t->obedit);
BMesh *bm = em->bm;
@@ -5365,48 +6014,20 @@ static bool createEdgeSlideVerts(TransInfo *t)
BMVert *v;
TransDataEdgeSlideVert *sv_array;
int sv_tot;
- BMBVHTree *btree;
int *sv_table; /* BMVert -> sv_array index */
EdgeSlideData *sld = MEM_callocN(sizeof(*sld), "sld");
+ float mval[2] = {(float)t->mval[0], (float)t->mval[1]};
+ int numsel, i, j, loop_nr;
+ bool use_btree_disp = false;
View3D *v3d = NULL;
RegionView3D *rv3d = NULL;
- ARegion *ar = t->ar;
- float projectMat[4][4];
- float mval[2] = {(float)t->mval[0], (float)t->mval[1]};
- float mval_start[2], mval_end[2];
- float mval_dir[3], maxdist, (*loop_dir)[3], *loop_maxdist;
- int numsel, i, j, loop_nr, l_nr;
- int use_btree_disp;
-
- if (t->spacetype == SPACE_VIEW3D) {
- /* background mode support */
- v3d = t->sa ? t->sa->spacedata.first : NULL;
- rv3d = t->ar ? t->ar->regiondata : NULL;
- }
- if ((t->settings->uvcalc_flag & UVCALC_TRANSFORM_CORRECT) &&
- /* don't do this at all for non-basis shape keys, too easy to
- * accidentally break uv maps or vertex colors then */
- (bm->shapenr <= 1))
- {
- sld->use_origfaces = true;
- }
- else {
- sld->use_origfaces = false;
- }
+ slide_origdata_init_flag(t, &sld->orig_data);
sld->is_proportional = true;
sld->curr_sv_index = 0;
sld->flipped_vtx = false;
- if (!rv3d) {
- /* ok, let's try to survive this */
- unit_m4(projectMat);
- }
- else {
- ED_view3d_ob_project_mat_get(rv3d, t->obedit, projectMat);
- }
-
/*ensure valid selection*/
BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
if (BM_elem_flag_test(v, BM_ELEM_SELECT)) {
@@ -5578,14 +6199,14 @@ static bool createEdgeSlideVerts(TransInfo *t)
if (l_a || l_a_prev) {
BMLoop *l_tmp = BM_loop_other_edge_loop(l_a ? l_a : l_a_prev, v);
- sv->v_a = BM_edge_other_vert(l_tmp->e, v);
- copy_v3_v3(sv->dir_a, vec_a);
+ sv->v_side[0] = BM_edge_other_vert(l_tmp->e, v);
+ copy_v3_v3(sv->dir_side[0], vec_a);
}
if (l_b || l_b_prev) {
BMLoop *l_tmp = BM_loop_other_edge_loop(l_b ? l_b : l_b_prev, v);
- sv->v_b = BM_edge_other_vert(l_tmp->e, v);
- copy_v3_v3(sv->dir_b, vec_b);
+ sv->v_side[1] = BM_edge_other_vert(l_tmp->e, v);
+ copy_v3_v3(sv->dir_side[1], vec_b);
}
v_prev = v;
@@ -5604,23 +6225,23 @@ static bool createEdgeSlideVerts(TransInfo *t)
if (l_a) {
BMLoop *l_tmp = BM_loop_other_edge_loop(l_a, v);
- sv->v_a = BM_edge_other_vert(l_tmp->e, v);
+ sv->v_side[0] = BM_edge_other_vert(l_tmp->e, v);
if (EDGESLIDE_VERT_IS_INNER(v, l_tmp->e)) {
- get_next_loop(v, l_a, e_prev, l_tmp->e, sv->dir_a);
+ get_next_loop(v, l_a, e_prev, l_tmp->e, sv->dir_side[0]);
}
else {
- sub_v3_v3v3(sv->dir_a, BM_edge_other_vert(l_tmp->e, v)->co, v->co);
+ sub_v3_v3v3(sv->dir_side[0], sv->v_side[0]->co, v->co);
}
}
if (l_b) {
BMLoop *l_tmp = BM_loop_other_edge_loop(l_b, v);
- sv->v_b = BM_edge_other_vert(l_tmp->e, v);
+ sv->v_side[1] = BM_edge_other_vert(l_tmp->e, v);
if (EDGESLIDE_VERT_IS_INNER(v, l_tmp->e)) {
- get_next_loop(v, l_b, e_prev, l_tmp->e, sv->dir_b);
+ get_next_loop(v, l_b, e_prev, l_tmp->e, sv->dir_side[1]);
}
else {
- sub_v3_v3v3(sv->dir_b, BM_edge_other_vert(l_tmp->e, v)->co, v->co);
+ sub_v3_v3v3(sv->dir_side[1], sv->v_side[1]->co, v->co);
}
}
@@ -5691,160 +6312,228 @@ static bool createEdgeSlideVerts(TransInfo *t)
#undef EDGESLIDE_VERT_IS_INNER
}
- /* use for visibility checks */
- use_btree_disp = (v3d && t->obedit->dt > OB_WIRE && v3d->drawtype > OB_WIRE);
-
- if (use_btree_disp) {
- btree = BKE_bmbvh_new_from_editmesh(em, BMBVH_RESPECT_HIDDEN, NULL, false);
- }
- else {
- btree = NULL;
- }
-
-
/* EDBM_flag_disable_all(em, BM_ELEM_SELECT); */
sld->sv = sv_array;
sld->totsv = sv_tot;
-
- /* find mouse vectors, the global one, and one per loop in case we have
- * multiple loops selected, in case they are oriented different */
- zero_v3(mval_dir);
- maxdist = -1.0f;
- loop_dir = MEM_callocN(sizeof(float) * 3 * loop_nr, "sv loop_dir");
- loop_maxdist = MEM_mallocN(sizeof(float) * loop_nr, "sv loop_maxdist");
- fill_vn_fl(loop_maxdist, loop_nr, -1.0f);
+ /* use for visibility checks */
+ if (t->spacetype == SPACE_VIEW3D) {
+ v3d = t->sa ? t->sa->spacedata.first : NULL;
+ rv3d = t->ar ? t->ar->regiondata : NULL;
+ use_btree_disp = (v3d && t->obedit->dt > OB_WIRE && v3d->drawtype > OB_WIRE);
+ }
- BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
- if (BM_elem_flag_test(e, BM_ELEM_SELECT)) {
- BMIter iter2;
- BMEdge *e2;
- float d;
+ calcEdgeSlide_mval_range(t, sld, sv_table, loop_nr, mval, use_btree_disp, true);
- /* search cross edges for visible edge to the mouse cursor,
- * then use the shared vertex to calculate screen vector*/
- for (i = 0; i < 2; i++) {
- v = i ? e->v1 : e->v2;
- BM_ITER_ELEM (e2, &iter2, v, BM_EDGES_OF_VERT) {
- /* screen-space coords */
- float sco_a[3], sco_b[3];
+ /* create copies of faces for customdata projection */
+ bmesh_edit_begin(bm, BMO_OPTYPE_FLAG_UNTAN_MULTIRES);
+ slide_origdata_init_data(t, &sld->orig_data);
+ slide_origdata_create_data(t, &sld->orig_data, (TransDataGenericSlideVert *)sld->sv, sizeof(*sld->sv), sld->totsv);
- if (BM_elem_flag_test(e2, BM_ELEM_SELECT))
- continue;
+ if (rv3d) {
+ calcEdgeSlide_non_proportional(t, sld, mval);
+ }
- /* This test is only relevant if object is not wire-drawn! See [#32068]. */
- if (use_btree_disp && !BMBVH_EdgeVisible(btree, e2, ar, v3d, t->obedit)) {
- continue;
- }
+ sld->em = em;
+
+ sld->perc = 0.0f;
+
+ t->customData = sld;
+
+ MEM_freeN(sv_table);
- BLI_assert(sv_table[BM_elem_index_get(v)] != -1);
- j = sv_table[BM_elem_index_get(v)];
+ return true;
+}
- if (sv_array[j].v_b) {
- ED_view3d_project_float_v3_m4(ar, sv_array[j].v_b->co, sco_b, projectMat);
- }
- else {
- add_v3_v3v3(sco_b, v->co, sv_array[j].dir_b);
- ED_view3d_project_float_v3_m4(ar, sco_b, sco_b, projectMat);
- }
-
- if (sv_array[j].v_a) {
- ED_view3d_project_float_v3_m4(ar, sv_array[j].v_a->co, sco_a, projectMat);
- }
- else {
- add_v3_v3v3(sco_a, v->co, sv_array[j].dir_a);
- ED_view3d_project_float_v3_m4(ar, sco_a, sco_a, projectMat);
- }
-
- /* global direction */
- d = dist_to_line_segment_v2(mval, sco_b, sco_a);
- if ((maxdist == -1.0f) ||
- /* intentionally use 2d size on 3d vector */
- (d < maxdist && (len_squared_v2v2(sco_b, sco_a) > 0.1f)))
- {
- maxdist = d;
- sub_v3_v3v3(mval_dir, sco_b, sco_a);
- }
+/**
+ * A simple version of #createEdgeSlideVerts_double_side
+ * Which assumes the longest unselected.
+ */
+static bool createEdgeSlideVerts_single_side(TransInfo *t)
+{
+ BMEditMesh *em = BKE_editmesh_from_object(t->obedit);
+ BMesh *bm = em->bm;
+ BMIter iter;
+ BMEdge *e;
+ BMVert *v;
+ TransDataEdgeSlideVert *sv_array;
+ int sv_tot;
+ int *sv_table; /* BMVert -> sv_array index */
+ EdgeSlideData *sld = MEM_callocN(sizeof(*sld), "sld");
+ float mval[2] = {(float)t->mval[0], (float)t->mval[1]};
+ int i, j, loop_nr;
+ bool use_btree_disp = false;
+ View3D *v3d = NULL;
+ RegionView3D *rv3d = NULL;
+
+ if (t->spacetype == SPACE_VIEW3D) {
+ /* background mode support */
+ v3d = t->sa ? t->sa->spacedata.first : NULL;
+ rv3d = t->ar ? t->ar->regiondata : NULL;
+ }
+
+ slide_origdata_init_flag(t, &sld->orig_data);
+
+ sld->is_proportional = true;
+ sld->curr_sv_index = 0;
+ /* heppans to be best for single-sided */
+ sld->flipped_vtx = true;
- /* per loop direction */
- l_nr = sv_array[j].loop_nr;
- if (loop_maxdist[l_nr] == -1.0f || d < loop_maxdist[l_nr]) {
- loop_maxdist[l_nr] = d;
- sub_v3_v3v3(loop_dir[l_nr], sco_b, sco_a);
+ /* ensure valid selection */
+ j = 0;
+ BM_ITER_MESH_INDEX (v, &iter, bm, BM_VERTS_OF_MESH, i) {
+ if (BM_elem_flag_test(v, BM_ELEM_SELECT)) {
+ float len_sq_max = -1.0f;
+ BMIter iter2;
+ BM_ITER_ELEM (e, &iter2, v, BM_EDGES_OF_VERT) {
+ if (!BM_elem_flag_test(e, BM_ELEM_SELECT)) {
+ float len_sq = BM_edge_calc_length_squared(e);
+ if (len_sq > len_sq_max) {
+ len_sq_max = len_sq;
+ v->e = e;
}
}
}
+
+ if (len_sq_max != -1.0f) {
+ j++;
+ }
}
+ BM_elem_index_set(v, i); /* set_inline */
}
+ bm->elem_index_dirty &= ~BM_VERT;
- /* possible all of the edge loops are pointing directly at the view */
- if (UNLIKELY(len_squared_v2(mval_dir) < 0.1f)) {
- mval_dir[0] = 0.0f;
- mval_dir[1] = 100.0f;
+ if (!j) {
+ return false;
}
- bmesh_edit_begin(bm, BMO_OPTYPE_FLAG_UNTAN_MULTIRES);
- if (sld->use_origfaces) {
- sld->origfaces = BLI_ghash_ptr_new(__func__);
- sld->bm_origfaces = BM_mesh_create(&bm_mesh_allocsize_default);
- /* we need to have matching customdata */
- BM_mesh_copy_init_customdata(sld->bm_origfaces, bm, NULL);
+ sv_tot = j;
+ BLI_assert(sv_tot != 0);
+ /* over alloc */
+ sv_array = MEM_callocN(sizeof(TransDataEdgeSlideVert) * bm->totvertsel, "sv_array");
+
+ /* same loop for all loops, weak but we dont connect loops in this case */
+ loop_nr = 1;
+
+ sv_table = MEM_mallocN(sizeof(*sv_table) * bm->totvert, __func__);
+
+ j = 0;
+ BM_ITER_MESH_INDEX (v, &iter, bm, BM_VERTS_OF_MESH, i) {
+ sv_table[i] = -1;
+ if ((v->e != NULL) && (BM_elem_flag_test(v, BM_ELEM_SELECT))) {
+ if (BM_elem_flag_test(v->e, BM_ELEM_SELECT) == 0) {
+ TransDataEdgeSlideVert *sv;
+ sv = &sv_array[j];
+ sv->v = v;
+ copy_v3_v3(sv->v_co_orig, v->co);
+ sv->v_side[0] = BM_edge_other_vert(v->e, v);
+ sub_v3_v3v3(sv->dir_side[0], sv->v_side[0]->co, v->co);
+ sv->loop_nr = 0;
+ sv_table[i] = j;
+ j += 1;
+ }
+ }
}
- /*create copies of faces for customdata projection*/
- sv_array = sld->sv;
- for (i = 0; i < sld->totsv; i++, sv_array++) {
- BMIter fiter;
- BMFace *f;
-
+ /* check for wire vertices,
+ * interpolate the directions of wire verts between non-wire verts */
+ if (sv_tot != bm->totvert) {
+ const int sv_tot_nowire = sv_tot;
+ TransDataEdgeSlideVert *sv_iter = sv_array;
+ int i;
+ for (i = 0; i < sv_tot_nowire; i++, sv_iter++) {
+ BMIter eiter;
+ BM_ITER_ELEM (e, &eiter, sv_iter->v, BM_EDGES_OF_VERT) {
+ /* walk over wire */
+ TransDataEdgeSlideVert *sv_end = NULL;
+ BMEdge *e_step = e;
+ BMVert *v = sv_iter->v;
+
+ j = sv_tot;
+
+ while (1) {
+ BMVert *v_other = BM_edge_other_vert(e_step, v);
+ int endpoint = (
+ (sv_table[BM_elem_index_get(v_other)] != -1) +
+ (BM_vert_is_edge_pair(v_other) == false));
+
+ if ((BM_elem_flag_test(e_step, BM_ELEM_SELECT) &&
+ BM_elem_flag_test(v_other, BM_ELEM_SELECT)) &&
+ (endpoint == 0))
+ {
+ /* scan down the list */
+ TransDataEdgeSlideVert *sv;
+ BLI_assert(sv_table[BM_elem_index_get(v_other)] == -1);
+ sv_table[BM_elem_index_get(v_other)] = j;
+ sv = &sv_array[j];
+ sv->v = v_other;
+ copy_v3_v3(sv->v_co_orig, v_other->co);
+ copy_v3_v3(sv->dir_side[0], sv_iter->dir_side[0]);
+ j++;
+
+ /* advance! */
+ v = v_other;
+ e_step = BM_DISK_EDGE_NEXT(e_step, v_other);
+ }
+ else {
+ if ((endpoint == 2) && (sv_tot != j)) {
+ BLI_assert(BM_elem_index_get(v_other) != -1);
+ sv_end = &sv_array[sv_table[BM_elem_index_get(v_other)]];
+ }
+ break;
+ }
+ }
- if (sld->use_origfaces) {
- BM_ITER_ELEM (f, &fiter, sv_array->v, BM_FACES_OF_VERT) {
- if (!BLI_ghash_haskey(sld->origfaces, f)) {
- BMFace *f_copy = BM_face_copy(sld->bm_origfaces, bm, f, true, true);
- BLI_ghash_insert(sld->origfaces, f, f_copy);
+ if (sv_end) {
+ int sv_tot_prev = sv_tot;
+ const float *co_src = sv_iter->v->co;
+ const float *co_dst = sv_end->v->co;
+ const float *dir_src = sv_iter->dir_side[0];
+ const float *dir_dst = sv_end->dir_side[0];
+ sv_tot = j;
+
+ while (j-- != sv_tot_prev) {
+ float factor;
+ factor = line_point_factor_v3(sv_array[j].v->co, co_src, co_dst);
+ interp_v3_v3v3(sv_array[j].dir_side[0], dir_src, dir_dst, factor);
+ }
}
}
}
+ }
- /* switch a/b if loop direction is different from global direction */
- l_nr = sv_array->loop_nr;
- if (dot_v3v3(loop_dir[l_nr], mval_dir) < 0.0f) {
- swap_v3_v3(sv_array->dir_a, sv_array->dir_b);
- SWAP(BMVert *, sv_array->v_a, sv_array->v_b);
- }
+ /* EDBM_flag_disable_all(em, BM_ELEM_SELECT); */
+
+ sld->sv = sv_array;
+ sld->totsv = sv_tot;
+
+ /* use for visibility checks */
+ if (t->spacetype == SPACE_VIEW3D) {
+ v3d = t->sa ? t->sa->spacedata.first : NULL;
+ rv3d = t->ar ? t->ar->regiondata : NULL;
+ use_btree_disp = (v3d && t->obedit->dt > OB_WIRE && v3d->drawtype > OB_WIRE);
}
- if (rv3d)
- calcNonProportionalEdgeSlide(t, sld, mval);
+ calcEdgeSlide_mval_range(t, sld, sv_table, loop_nr, mval, use_btree_disp, false);
- sld->em = em;
+ /* create copies of faces for customdata projection */
+ bmesh_edit_begin(bm, BMO_OPTYPE_FLAG_UNTAN_MULTIRES);
+ slide_origdata_init_data(t, &sld->orig_data);
+ slide_origdata_create_data(t, &sld->orig_data, (TransDataGenericSlideVert *)sld->sv, sizeof(*sld->sv), sld->totsv);
- /*zero out start*/
- zero_v2(mval_start);
+ if (rv3d) {
+ calcEdgeSlide_non_proportional(t, sld, mval);
+ }
- /*dir holds a vector along edge loop*/
- copy_v2_v2(mval_end, mval_dir);
- mul_v2_fl(mval_end, 0.5f);
-
- sld->mval_start[0] = t->mval[0] + mval_start[0];
- sld->mval_start[1] = t->mval[1] + mval_start[1];
+ sld->em = em;
- sld->mval_end[0] = t->mval[0] + mval_end[0];
- sld->mval_end[1] = t->mval[1] + mval_end[1];
-
sld->perc = 0.0f;
-
+
t->customData = sld;
-
+
MEM_freeN(sv_table);
- if (btree) {
- BKE_bmbvh_free(btree);
- }
- MEM_freeN(loop_dir);
- MEM_freeN(loop_maxdist);
return true;
}
@@ -5852,172 +6541,27 @@ static bool createEdgeSlideVerts(TransInfo *t)
void projectEdgeSlideData(TransInfo *t, bool is_final)
{
EdgeSlideData *sld = t->customData;
- TransDataEdgeSlideVert *sv;
- BMEditMesh *em = sld->em;
- int i;
+ SlideOrigData *sod = &sld->orig_data;
- if (sld->use_origfaces == false) {
+ if (sod->use_origfaces == false) {
return;
}
- for (i = 0, sv = sld->sv; i < sld->totsv; sv++, i++) {
- BMIter fiter;
- BMLoop *l;
-
- BM_ITER_ELEM (l, &fiter, sv->v, BM_LOOPS_OF_VERT) {
- BMFace *f_copy; /* the copy of 'f' */
- BMFace *f_copy_flip; /* the copy of 'f' or detect if we need to flip to the shorter side. */
-
- f_copy = BLI_ghash_lookup(sld->origfaces, l->f);
-
- /* project onto copied projection face */
- f_copy_flip = f_copy;
-
- if (BM_elem_flag_test(l->e, BM_ELEM_SELECT) || BM_elem_flag_test(l->prev->e, BM_ELEM_SELECT)) {
- /* the loop is attached of the selected edges that are sliding */
- BMLoop *l_ed_sel = l;
-
- if (!BM_elem_flag_test(l->e, BM_ELEM_SELECT))
- l_ed_sel = l_ed_sel->prev;
-
- if (sld->perc < 0.0f) {
- if (BM_vert_in_face(l_ed_sel->radial_next->f, sv->v_b)) {
- f_copy_flip = BLI_ghash_lookup(sld->origfaces, l_ed_sel->radial_next->f);
- }
- }
- else if (sld->perc > 0.0f) {
- if (BM_vert_in_face(l_ed_sel->radial_next->f, sv->v_a)) {
- f_copy_flip = BLI_ghash_lookup(sld->origfaces, l_ed_sel->radial_next->f);
- }
- }
-
- BLI_assert(f_copy_flip != NULL);
- if (!f_copy_flip) {
- continue; /* shouldn't happen, but protection */
- }
- }
- else {
- /* the loop is attached to only one vertex and not a selected edge,
- * this means we have to find a selected edges face going in the right direction
- * to copy from else we get bad distortion see: [#31080] */
- BMIter eiter;
- BMEdge *e_sel;
-
- BLI_assert(l->v == sv->v);
- BM_ITER_ELEM (e_sel, &eiter, sv->v, BM_EDGES_OF_VERT) {
- if (BM_elem_flag_test(e_sel, BM_ELEM_SELECT)) {
- break;
- }
- }
-
- if (e_sel) {
- /* warning if the UV's are not contiguous, this will copy from the _wrong_ UVs
- * in fact whenever the face being copied is not 'f_copy' this can happen,
- * we could be a lot smarter about this but would need to deal with every UV channel or
- * add a way to mask out lauers when calling #BM_loop_interp_from_face() */
-
- /*
- * + +----------------+
- * \ | |
- * (this) l_adj| |
- * \ | |
- * \| e_sel |
- * +----------+----------------+ <- the edge we are sliding.
- * /|sv->v |
- * / | |
- * (or) l_adj| |
- * / | |
- * + +----------------+
- * (above)
- * 'other connected loops', attached to sv->v slide faces.
- *
- * NOTE: The faces connected to the edge may not have contiguous UV's
- * so step around the loops to find l_adj.
- * However if the 'other loops' are not cotiguous it will still give problems.
- *
- * A full solution to this would have to store
- * per-customdata-layer map of which loops are contiguous
- * and take this into account when interpolating.
- *
- * NOTE: If l_adj's edge isnt manifold then use then
- * interpolate the loop from its own face.
- * Can happen when 'other connected loops' are disconnected from the face-fan.
- */
-
- BMLoop *l_adj = NULL;
- if (sld->perc < 0.0f) {
- if (BM_vert_in_face(e_sel->l->f, sv->v_b)) {
- l_adj = e_sel->l;
- }
- else if (BM_vert_in_face(e_sel->l->radial_next->f, sv->v_b)) {
- l_adj = e_sel->l->radial_next;
- }
- }
- else if (sld->perc > 0.0f) {
- if (BM_vert_in_face(e_sel->l->f, sv->v_a)) {
- l_adj = e_sel->l;
- }
- else if (BM_vert_in_face(e_sel->l->radial_next->f, sv->v_a)) {
- l_adj = e_sel->l->radial_next;
- }
- }
-
- /* step across to the face */
- if (l_adj) {
- l_adj = BM_loop_other_edge_loop(l_adj, sv->v);
- if (!BM_edge_is_boundary(l_adj->e)) {
- l_adj = l_adj->radial_next;
- }
- else {
- /* disconnected face-fan, fallback to self */
- l_adj = l;
- }
-
- f_copy_flip = BLI_ghash_lookup(sld->origfaces, l_adj->f);
- }
- }
- }
-
- /* only loop data, no vertex data since that contains shape keys,
- * and we do not want to mess up other shape keys */
- BM_loop_interp_from_face(em->bm, l, f_copy_flip, false, false);
-
- if (is_final) {
- BM_loop_interp_multires(em->bm, l, f_copy_flip);
- if (f_copy != f_copy_flip) {
- BM_loop_interp_multires(em->bm, l, f_copy);
- }
- }
-
- /* make sure face-attributes are correct (e.g. MTexPoly) */
- BM_elem_attrs_copy(sld->bm_origfaces, em->bm, f_copy, l->f);
- }
- }
+ slide_origdata_interp_data(t, sod, (TransDataGenericSlideVert *)sld->sv, sizeof(*sld->sv), sld->totsv, is_final);
}
void freeEdgeSlideTempFaces(EdgeSlideData *sld)
{
- if (sld->use_origfaces) {
- if (sld->bm_origfaces) {
- BM_mesh_free(sld->bm_origfaces);
- sld->bm_origfaces = NULL;
- }
-
- if (sld->origfaces) {
- BLI_ghash_free(sld->origfaces, NULL, NULL);
- sld->origfaces = NULL;
- }
- }
+ slide_origdata_free_date(&sld->orig_data);
}
-
void freeEdgeSlideVerts(TransInfo *t)
{
EdgeSlideData *sld = t->customData;
if (!sld)
return;
-
+
freeEdgeSlideTempFaces(sld);
bmesh_edit_end(sld->em->bm, BMO_OPTYPE_FLAG_UNTAN_MULTIRES);
@@ -6026,19 +6570,25 @@ void freeEdgeSlideVerts(TransInfo *t)
MEM_freeN(sld);
t->customData = NULL;
-
- recalcData(t);
}
-static void initEdgeSlide(TransInfo *t)
+static void initEdgeSlide_ex(TransInfo *t, bool use_double_side)
{
EdgeSlideData *sld;
+ bool ok;
t->mode = TFM_EDGE_SLIDE;
t->transform = applyEdgeSlide;
t->handleEvent = handleEventEdgeSlide;
- if (!createEdgeSlideVerts(t)) {
+ if (use_double_side) {
+ ok = createEdgeSlideVerts_double_side(t);
+ }
+ else {
+ ok = createEdgeSlideVerts_single_side(t);
+ }
+
+ if (!ok) {
t->state = TRANS_CANCEL;
return;
}
@@ -6051,7 +6601,7 @@ static void initEdgeSlide(TransInfo *t)
t->customFree = freeEdgeSlideVerts;
/* set custom point first if you want value to be initialized by init */
- setCustomPoints(t, &t->mouse, sld->mval_end, sld->mval_start);
+ calcEdgeSlideCustomPoints(t);
initMouseInputMode(t, &t->mouse, INPUT_CUSTOM_RATIO_FLIP);
t->idx_max = 0;
@@ -6067,6 +6617,11 @@ static void initEdgeSlide(TransInfo *t)
t->flag |= T_NO_CONSTRAINT | T_NO_PROJECT;
}
+static void initEdgeSlide(TransInfo *t)
+{
+ initEdgeSlide_ex(t, true);
+}
+
static eRedrawFlag handleEventEdgeSlide(struct TransInfo *t, const struct wmEvent *event)
{
if (t->mode == TFM_EDGE_SLIDE) {
@@ -6077,35 +6632,40 @@ static eRedrawFlag handleEventEdgeSlide(struct TransInfo *t, const struct wmEven
case EKEY:
if (event->val == KM_PRESS) {
sld->is_proportional = !sld->is_proportional;
+ calcEdgeSlideCustomPoints(t);
return TREDRAW_HARD;
}
break;
case FKEY:
- {
if (event->val == KM_PRESS) {
if (sld->is_proportional == false) {
sld->flipped_vtx = !sld->flipped_vtx;
}
+ calcEdgeSlideCustomPoints(t);
+ return TREDRAW_HARD;
+ }
+ break;
+ case CKEY:
+ /* use like a modifier key */
+ if (event->val == KM_PRESS) {
+ t->flag ^= T_ALT_TRANSFORM;
+ calcEdgeSlideCustomPoints(t);
return TREDRAW_HARD;
}
break;
- }
case EVT_MODAL_MAP:
- {
switch (event->val) {
case TFM_MODAL_EDGESLIDE_DOWN:
- {
sld->curr_sv_index = ((sld->curr_sv_index - 1) + sld->totsv) % sld->totsv;
- break;
- }
+ return TREDRAW_HARD;
case TFM_MODAL_EDGESLIDE_UP:
- {
sld->curr_sv_index = (sld->curr_sv_index + 1) % sld->totsv;
- break;
- }
+ return TREDRAW_HARD;
}
break;
- }
+ case MOUSEMOVE:
+ calcEdgeSlideCustomPoints(t);
+ break;
default:
break;
}
@@ -6114,23 +6674,16 @@ static eRedrawFlag handleEventEdgeSlide(struct TransInfo *t, const struct wmEven
return TREDRAW_NOTHING;
}
-static void drawEdgeSlide(const struct bContext *C, TransInfo *t)
+static void drawEdgeSlide(TransInfo *t)
{
- if (t->mode == TFM_EDGE_SLIDE) {
- EdgeSlideData *sld = (EdgeSlideData *)t->customData;
+ if ((t->mode == TFM_EDGE_SLIDE) && t->customData) {
+ EdgeSlideData *sld = t->customData;
+ const bool is_clamp = !(t->flag & T_ALT_TRANSFORM);
+
/* Non-Prop mode */
- if (sld && sld->is_proportional == false) {
- View3D *v3d = CTX_wm_view3d(C);
- float co_a[3], co_b[3], co_mark[3];
- TransDataEdgeSlideVert *curr_sv = &sld->sv[sld->curr_sv_index];
- const float fac = (sld->perc + 1.0f) / 2.0f;
- const float ctrl_size = UI_GetThemeValuef(TH_FACEDOT_SIZE) + 1.5f;
- const float guide_size = ctrl_size - 0.5f;
+ if ((sld->is_proportional == false) || (is_clamp == false)) {
+ View3D *v3d = t->view;
const float line_size = UI_GetThemeValuef(TH_OUTLINE_WIDTH) + 0.5f;
- const int alpha_shade = -30;
-
- add_v3_v3v3(co_a, curr_sv->v_co_orig, curr_sv->dir_a);
- add_v3_v3v3(co_b, curr_sv->v_co_orig, curr_sv->dir_b);
if (v3d && v3d->zbuf)
glDisable(GL_DEPTH_TEST);
@@ -6143,42 +6696,88 @@ static void drawEdgeSlide(const struct bContext *C, TransInfo *t)
glMultMatrixf(t->obedit->obmat);
- glLineWidth(line_size);
- UI_ThemeColorShadeAlpha(TH_EDGE_SELECT, 80, alpha_shade);
- glBegin(GL_LINES);
- if (curr_sv->v_a) {
- glVertex3fv(curr_sv->v_a->co);
- glVertex3fv(curr_sv->v_co_orig);
- }
- if (curr_sv->v_b) {
- glVertex3fv(curr_sv->v_b->co);
- glVertex3fv(curr_sv->v_co_orig);
- }
- bglEnd();
+ if (sld->is_proportional == false) {
+ float co_a[3], co_b[3], co_mark[3];
+ TransDataEdgeSlideVert *curr_sv = &sld->sv[sld->curr_sv_index];
+ const float fac = (sld->perc + 1.0f) / 2.0f;
+ const float ctrl_size = UI_GetThemeValuef(TH_FACEDOT_SIZE) + 1.5f;
+ const float guide_size = ctrl_size - 0.5f;
+ const int alpha_shade = -30;
+
+ add_v3_v3v3(co_a, curr_sv->v_co_orig, curr_sv->dir_side[0]);
+ add_v3_v3v3(co_b, curr_sv->v_co_orig, curr_sv->dir_side[1]);
+
+ glLineWidth(line_size);
+ UI_ThemeColorShadeAlpha(TH_EDGE_SELECT, 80, alpha_shade);
+ glBegin(GL_LINES);
+ if (curr_sv->v_side[0]) {
+ glVertex3fv(curr_sv->v_side[0]->co);
+ glVertex3fv(curr_sv->v_co_orig);
+ }
+ if (curr_sv->v_side[1]) {
+ glVertex3fv(curr_sv->v_side[1]->co);
+ glVertex3fv(curr_sv->v_co_orig);
+ }
+ glEnd();
+ UI_ThemeColorShadeAlpha(TH_SELECT, -30, alpha_shade);
+ glPointSize(ctrl_size);
+ bglBegin(GL_POINTS);
+ if (sld->flipped_vtx) {
+ if (curr_sv->v_side[1]) bglVertex3fv(curr_sv->v_side[1]->co);
+ }
+ else {
+ if (curr_sv->v_side[0]) bglVertex3fv(curr_sv->v_side[0]->co);
+ }
+ bglEnd();
- UI_ThemeColorShadeAlpha(TH_SELECT, -30, alpha_shade);
- glPointSize(ctrl_size);
- bglBegin(GL_POINTS);
- if (sld->flipped_vtx) {
- if (curr_sv->v_b) bglVertex3fv(curr_sv->v_b->co);
+ UI_ThemeColorShadeAlpha(TH_SELECT, 255, alpha_shade);
+ glPointSize(guide_size);
+ bglBegin(GL_POINTS);
+#if 0
+ interp_v3_v3v3(co_mark, co_b, co_a, fac);
+ bglVertex3fv(co_mark);
+#endif
+ interp_line_v3_v3v3v3(co_mark, co_b, curr_sv->v_co_orig, co_a, fac);
+ bglVertex3fv(co_mark);
+ bglEnd();
}
else {
- if (curr_sv->v_a) bglVertex3fv(curr_sv->v_a->co);
- }
- bglEnd();
+ if (is_clamp == false) {
+ const int side_index = sld->curr_side_unclamp;
+ TransDataEdgeSlideVert *sv;
+ int i;
+ const int alpha_shade = -160;
+
+ glLineWidth(line_size);
+ UI_ThemeColorShadeAlpha(TH_EDGE_SELECT, 80, alpha_shade);
+ glBegin(GL_LINES);
+
+ sv = sld->sv;
+ for (i = 0; i < sld->totsv; i++, sv++) {
+ float a[3], b[3];
+
+ if (!is_zero_v3(sv->dir_side[side_index])) {
+ copy_v3_v3(a, sv->dir_side[side_index]);
+ }
+ else {
+ copy_v3_v3(a, sv->dir_side[!side_index]);
+ }
- UI_ThemeColorShadeAlpha(TH_SELECT, 255, alpha_shade);
- glPointSize(guide_size);
- bglBegin(GL_POINTS);
-#if 0
- interp_v3_v3v3(co_mark, co_b, co_a, fac);
- bglVertex3fv(co_mark);
-#endif
- interp_line_v3_v3v3v3(co_mark, co_b, curr_sv->v_co_orig, co_a, fac);
- bglVertex3fv(co_mark);
- bglEnd();
+ mul_v3_fl(a, 100.0f);
+ negate_v3_v3(b, a);
+ add_v3_v3(a, sv->v_co_orig);
+ add_v3_v3(b, sv->v_co_orig);
+ glVertex3fv(a);
+ glVertex3fv(b);
+ }
+ glEnd();
+ }
+ else {
+ BLI_assert(0);
+ }
+ }
glPopMatrix();
glPopAttrib();
@@ -6191,7 +6790,7 @@ static void drawEdgeSlide(const struct bContext *C, TransInfo *t)
}
}
-static int doEdgeSlide(TransInfo *t, float perc)
+static void doEdgeSlide(TransInfo *t, float perc)
{
EdgeSlideData *sld = t->customData;
TransDataEdgeSlideVert *svlist = sld->sv, *sv;
@@ -6201,17 +6800,30 @@ static int doEdgeSlide(TransInfo *t, float perc)
sv = svlist;
if (sld->is_proportional == true) {
- for (i = 0; i < sld->totsv; i++, sv++) {
- float vec[3];
- if (perc > 0.0f) {
- copy_v3_v3(vec, sv->dir_a);
- mul_v3_fl(vec, perc);
- add_v3_v3v3(sv->v->co, sv->v_co_orig, vec);
+ const bool is_clamp = !(t->flag & T_ALT_TRANSFORM);
+ if (is_clamp) {
+ const int side_index = (perc < 0.0f);
+ const float perc_final = fabsf(perc);
+ for (i = 0; i < sld->totsv; i++, sv++) {
+ madd_v3_v3v3fl(sv->v->co, sv->v_co_orig, sv->dir_side[side_index], perc_final);
}
- else {
- copy_v3_v3(vec, sv->dir_b);
- mul_v3_fl(vec, -perc);
- add_v3_v3v3(sv->v->co, sv->v_co_orig, vec);
+
+ sld->curr_side_unclamp = side_index;
+ }
+ else {
+ const int side_index = sld->curr_side_unclamp;
+ const float perc_init = fabsf(perc) * ((sld->curr_side_unclamp == (perc < 0.0f)) ? 1 : -1);
+ for (i = 0; i < sld->totsv; i++, sv++) {
+ float dir_flip[3];
+ float perc_final = perc_init;
+ if (!is_zero_v3(sv->dir_side[side_index])) {
+ copy_v3_v3(dir_flip, sv->dir_side[side_index]);
+ }
+ else {
+ copy_v3_v3(dir_flip, sv->dir_side[!side_index]);
+ perc_final *= -1;
+ }
+ madd_v3_v3v3fl(sv->v->co, sv->v_co_orig, dir_flip, perc_final);
}
}
}
@@ -6221,7 +6833,7 @@ static int doEdgeSlide(TransInfo *t, float perc)
* a/b verts, this could be changed/improved so the distance is still met but the verts are moved along
* their original path (which may not be straight), however how it works now is OK and matches 2.4x - Campbell
*
- * \note len_v3v3(curr_sv->dir_a, curr_sv->dir_b)
+ * \note len_v3v3(curr_sv->dir_side[0], curr_sv->dir_side[1])
* is the same as the distance between the original vert locations, same goes for the lines below.
*/
TransDataEdgeSlideVert *curr_sv = &sld->sv[sld->curr_sv_index];
@@ -6234,8 +6846,8 @@ static int doEdgeSlide(TransInfo *t, float perc)
if (sv->edge_len > FLT_EPSILON) {
const float fac = min_ff(sv->edge_len, curr_length_perc) / sv->edge_len;
- add_v3_v3v3(co_a, sv->v_co_orig, sv->dir_a);
- add_v3_v3v3(co_b, sv->v_co_orig, sv->dir_b);
+ add_v3_v3v3(co_a, sv->v_co_orig, sv->dir_side[0]);
+ add_v3_v3v3(co_b, sv->v_co_orig, sv->dir_side[1]);
if (sld->flipped_vtx) {
interp_line_v3_v3v3v3(sv->v->co, co_b, sv->v_co_orig, co_a, fac);
@@ -6246,55 +6858,48 @@ static int doEdgeSlide(TransInfo *t, float perc)
}
}
}
-
- projectEdgeSlideData(t, 0);
-
- return 1;
}
static void applyEdgeSlide(TransInfo *t, const int UNUSED(mval[2]))
{
char str[MAX_INFO_LEN];
+ size_t ofs = 0;
float final;
EdgeSlideData *sld = t->customData;
bool flipped = sld->flipped_vtx;
bool is_proportional = sld->is_proportional;
+ const bool is_clamp = !(t->flag & T_ALT_TRANSFORM);
+ const bool is_constrained = !(is_clamp == false || hasNumInput(&t->num));
final = t->values[0];
snapGridIncrement(t, &final);
/* only do this so out of range values are not displayed */
- CLAMP(final, -1.0f, 1.0f);
+ if (is_constrained) {
+ CLAMP(final, -1.0f, 1.0f);
+ }
applyNumInput(&t->num, &final);
+ t->values[0] = final;
+
+ /* header string */
+ ofs += BLI_strncpy_rlen(str + ofs, IFACE_("Edge Slide: "), MAX_INFO_LEN - ofs);
if (hasNumInput(&t->num)) {
char c[NUM_STR_REP_LEN];
-
outputNumInput(&(t->num), c, &t->scene->unit);
-
- if (is_proportional) {
- BLI_snprintf(str, MAX_INFO_LEN, IFACE_("Edge Slide: %s (E)ven: %s"),
- &c[0], WM_bool_as_string(!is_proportional));
- }
- else {
- BLI_snprintf(str, MAX_INFO_LEN, IFACE_("Edge Slide: %s (E)ven: %s, (F)lipped: %s"),
- &c[0], WM_bool_as_string(!is_proportional), WM_bool_as_string(flipped));
- }
- }
- else if (is_proportional) {
- BLI_snprintf(str, MAX_INFO_LEN, IFACE_("Edge Slide: %.4f (E)ven: %s"),
- final, WM_bool_as_string(!is_proportional));
+ ofs += BLI_strncpy_rlen(str + ofs, &c[0], MAX_INFO_LEN - ofs);
}
else {
- BLI_snprintf(str, MAX_INFO_LEN, IFACE_("Edge Slide: %.4f (E)ven: %s, (F)lipped: %s"),
- final, WM_bool_as_string(!is_proportional), WM_bool_as_string(flipped));
+ ofs += BLI_snprintf(str + ofs, MAX_INFO_LEN - ofs, "%.4f ", final);
}
-
- CLAMP(final, -1.0f, 1.0f);
-
- t->values[0] = final;
+ ofs += BLI_snprintf(str + ofs, MAX_INFO_LEN - ofs, IFACE_("(E)ven: %s, "), WM_bool_as_string(!is_proportional));
+ if (!is_proportional) {
+ ofs += BLI_snprintf(str + ofs, MAX_INFO_LEN - ofs, IFACE_("(F)lipped: %s, "), WM_bool_as_string(flipped));
+ }
+ ofs += BLI_snprintf(str + ofs, MAX_INFO_LEN - ofs, IFACE_("Alt or (C)lamp: %s"), WM_bool_as_string(is_clamp));
+ /* done with header string */
/* do stuff here */
doEdgeSlide(t, final);
@@ -6316,10 +6921,20 @@ static void calcVertSlideCustomPoints(struct TransInfo *t)
{
VertSlideData *sld = t->customData;
TransDataVertSlideVert *sv = &sld->sv[sld->curr_sv_index];
- const float *co_orig = sv->co_orig_2d;
- const float *co_curr = sv->co_link_orig_2d[sv->co_link_curr];
- const int mval_start[2] = {co_orig[0], co_orig[1]};
- const int mval_end[2] = {co_curr[0], co_curr[1]};
+
+ const float *co_orig_3d = sv->co_orig_3d;
+ const float *co_curr_3d = sv->co_link_orig_3d[sv->co_link_curr];
+
+ float co_curr_2d[2], co_orig_2d[2];
+
+ int mval_ofs[2], mval_start[2], mval_end[2];
+
+ ED_view3d_project_float_v2_m4(t->ar, co_orig_3d, co_orig_2d, sld->proj_mat);
+ ED_view3d_project_float_v2_m4(t->ar, co_curr_3d, co_curr_2d, sld->proj_mat);
+
+ ARRAY_SET_ITEMS(mval_ofs, t->imval[0] - co_orig_2d[0], t->imval[1] - co_orig_2d[1]);
+ ARRAY_SET_ITEMS(mval_start, co_orig_2d[0] + mval_ofs[0], co_orig_2d[1] + mval_ofs[1]);
+ ARRAY_SET_ITEMS(mval_end, co_curr_2d[0] + mval_ofs[0], co_curr_2d[1] + mval_ofs[1]);
if (sld->flipped_vtx && sld->is_proportional == false) {
setCustomPoints(t, &t->mouse, mval_start, mval_end);
@@ -6327,6 +6942,11 @@ static void calcVertSlideCustomPoints(struct TransInfo *t)
else {
setCustomPoints(t, &t->mouse, mval_end, mval_start);
}
+
+ /* setCustomPoints isn't normally changing as the mouse moves,
+ * in this case apply mouse input immediatly so we don't refresh
+ * with the value from the previous points */
+ applyMouseInput(t, &t->mouse, t->mval, t->values);
}
/**
@@ -6344,28 +6964,39 @@ static void calcVertSlideMouseActiveVert(struct TransInfo *t, const int mval[2])
int i;
for (i = 0, sv = sld->sv; i < sld->totsv; i++, sv++) {
- dist_sq = len_squared_v2v2(mval_fl, sv->co_orig_2d);
+ float co_2d[2];
+
+ ED_view3d_project_float_v2_m4(t->ar, sv->co_orig_3d, co_2d, sld->proj_mat);
+
+ dist_sq = len_squared_v2v2(mval_fl, co_2d);
if (dist_sq < dist_min_sq) {
dist_min_sq = dist_sq;
sld->curr_sv_index = i;
}
}
}
+
/**
* Run while moving the mouse to slide along the edge matching the mouse direction
*/
static void calcVertSlideMouseActiveEdges(struct TransInfo *t, const int mval[2])
{
VertSlideData *sld = t->customData;
- float mval_fl[2] = {UNPACK2(mval)};
+ float imval_fl[2] = {UNPACK2(t->imval)};
+ float mval_fl[2] = {UNPACK2(mval)};
- float dir[2];
+ float dir[3];
TransDataVertSlideVert *sv;
int i;
- /* first get the direction of the original vertex */
- sub_v2_v2v2(dir, sld->sv[sld->curr_sv_index].co_orig_2d, mval_fl);
- normalize_v2(dir);
+ /* note: we could save a matrix-multiply for each vertex
+ * by finding the closest edge in local-space.
+ * However this skews the outcome with non-uniform-scale. */
+
+ /* first get the direction of the original mouse position */
+ sub_v2_v2v2(dir, imval_fl, mval_fl);
+ ED_view3d_win_to_delta(t->ar, dir, dir, t->zfac);
+ normalize_v3(dir);
for (i = 0, sv = sld->sv; i < sld->totsv; i++, sv++) {
if (sv->co_link_tot > 1) {
@@ -6374,11 +7005,15 @@ static void calcVertSlideMouseActiveEdges(struct TransInfo *t, const int mval[2]
int j;
for (j = 0; j < sv->co_link_tot; j++) {
- float tdir[2];
+ float tdir[3];
float dir_dot;
- sub_v2_v2v2(tdir, sv->co_orig_2d, sv->co_link_orig_2d[j]);
- normalize_v2(tdir);
- dir_dot = dot_v2v2(dir, tdir);
+
+ sub_v3_v3v3(tdir, sv->co_orig_3d, sv->co_link_orig_3d[j]);
+ mul_mat3_m4_v3(t->obedit->obmat, tdir);
+ project_plane_v3_v3v3(tdir, tdir, t->viewinv[2]);
+
+ normalize_v3(tdir);
+ dir_dot = dot_v3v3(dir, tdir);
if (dir_dot > dir_dot_best) {
dir_dot_best = dir_dot;
co_link_curr_best = j;
@@ -6402,30 +7037,14 @@ static bool createVertSlideVerts(TransInfo *t)
BMVert *v;
TransDataVertSlideVert *sv_array;
VertSlideData *sld = MEM_callocN(sizeof(*sld), "sld");
-// View3D *v3d = NULL;
- RegionView3D *rv3d = NULL;
- ARegion *ar = t->ar;
- float projectMat[4][4];
int j;
- if (t->spacetype == SPACE_VIEW3D) {
- /* background mode support */
-// v3d = t->sa ? t->sa->spacedata.first : NULL;
- rv3d = ar ? ar->regiondata : NULL;
- }
+ slide_origdata_init_flag(t, &sld->orig_data);
sld->is_proportional = true;
sld->curr_sv_index = 0;
sld->flipped_vtx = false;
- if (!rv3d) {
- /* ok, let's try to survive this */
- unit_m4(projectMat);
- }
- else {
- ED_view3d_ob_project_mat_get(rv3d, t->obedit, projectMat);
- }
-
j = 0;
BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
bool ok = false;
@@ -6469,7 +7088,6 @@ static bool createVertSlideVerts(TransInfo *t)
}
sv_array[j].co_link_orig_3d = MEM_mallocN(sizeof(*sv_array[j].co_link_orig_3d) * k, __func__);
- sv_array[j].co_link_orig_2d = MEM_mallocN(sizeof(*sv_array[j].co_link_orig_2d) * k, __func__);
sv_array[j].co_link_tot = k;
k = 0;
@@ -6477,31 +7095,9 @@ static bool createVertSlideVerts(TransInfo *t)
if (!BM_elem_flag_test(e, BM_ELEM_HIDDEN)) {
BMVert *v_other = BM_edge_other_vert(e, v);
copy_v3_v3(sv_array[j].co_link_orig_3d[k], v_other->co);
- if (ar) {
- ED_view3d_project_float_v2_m4(ar,
- sv_array[j].co_link_orig_3d[k],
- sv_array[j].co_link_orig_2d[k],
- projectMat);
- }
- else {
- copy_v2_v2(sv_array[j].co_link_orig_2d[k],
- sv_array[j].co_link_orig_3d[k]);
- }
k++;
}
}
-
- if (ar) {
- ED_view3d_project_float_v2_m4(ar,
- sv_array[j].co_orig_3d,
- sv_array[j].co_orig_2d,
- projectMat);
- }
- else {
- copy_v2_v2(sv_array[j].co_orig_2d,
- sv_array[j].co_orig_3d);
- }
-
j++;
}
}
@@ -6509,13 +7105,29 @@ static bool createVertSlideVerts(TransInfo *t)
sld->sv = sv_array;
sld->totsv = j;
+ bmesh_edit_begin(bm, BMO_OPTYPE_FLAG_UNTAN_MULTIRES);
+ slide_origdata_init_data(t, &sld->orig_data);
+ slide_origdata_create_data(t, &sld->orig_data, (TransDataGenericSlideVert *)sld->sv, sizeof(*sld->sv), sld->totsv);
+
sld->em = em;
sld->perc = 0.0f;
t->customData = sld;
- if (rv3d) {
+ /* most likely will be set below */
+ unit_m4(sld->proj_mat);
+
+ if (t->spacetype == SPACE_VIEW3D) {
+ /* view vars */
+ RegionView3D *rv3d = NULL;
+ ARegion *ar = t->ar;
+
+ rv3d = ar ? ar->regiondata : NULL;
+ if (rv3d) {
+ ED_view3d_ob_project_mat_get(rv3d, t->obedit, sld->proj_mat);
+ }
+
calcVertSlideMouseActiveVert(t, t->mval);
calcVertSlideMouseActiveEdges(t, t->mval);
}
@@ -6523,6 +7135,23 @@ static bool createVertSlideVerts(TransInfo *t)
return true;
}
+void projectVertSlideData(TransInfo *t, bool is_final)
+{
+ VertSlideData *sld = t->customData;
+ SlideOrigData *sod = &sld->orig_data;
+
+ if (sod->use_origfaces == false) {
+ return;
+ }
+
+ slide_origdata_interp_data(t, sod, (TransDataGenericSlideVert *)sld->sv, sizeof(*sld->sv), sld->totsv, is_final);
+}
+
+void freeVertSlideTempFaces(VertSlideData *sld)
+{
+ slide_origdata_free_date(&sld->orig_data);
+}
+
void freeVertSlideVerts(TransInfo *t)
{
VertSlideData *sld = t->customData;
@@ -6530,12 +7159,14 @@ void freeVertSlideVerts(TransInfo *t)
if (!sld)
return;
+ freeVertSlideTempFaces(sld);
+
+ bmesh_edit_end(sld->em->bm, BMO_OPTYPE_FLAG_UNTAN_MULTIRES);
if (sld->totsv > 0) {
TransDataVertSlideVert *sv = sld->sv;
int i = 0;
for (i = 0; i < sld->totsv; i++, sv++) {
- MEM_freeN(sv->co_link_orig_2d);
MEM_freeN(sv->co_link_orig_3d);
}
}
@@ -6544,8 +7175,6 @@ void freeVertSlideVerts(TransInfo *t)
MEM_freeN(sld);
t->customData = NULL;
-
- recalcData(t);
}
static void initVertSlide(TransInfo *t)
@@ -6602,16 +7231,13 @@ static eRedrawFlag handleEventVertSlide(struct TransInfo *t, const struct wmEven
}
break;
case FKEY:
- {
if (event->val == KM_PRESS) {
sld->flipped_vtx = !sld->flipped_vtx;
calcVertSlideCustomPoints(t);
return TREDRAW_HARD;
}
break;
- }
case CKEY:
- {
/* use like a modifier key */
if (event->val == KM_PRESS) {
t->flag ^= T_ALT_TRANSFORM;
@@ -6619,27 +7245,21 @@ static eRedrawFlag handleEventVertSlide(struct TransInfo *t, const struct wmEven
return TREDRAW_HARD;
}
break;
- }
#if 0
case EVT_MODAL_MAP:
- {
switch (event->val) {
case TFM_MODAL_EDGESLIDE_DOWN:
- {
sld->curr_sv_index = ((sld->curr_sv_index - 1) + sld->totsv) % sld->totsv;
break;
- }
case TFM_MODAL_EDGESLIDE_UP:
- {
sld->curr_sv_index = (sld->curr_sv_index + 1) % sld->totsv;
break;
- }
}
- }
+ break;
#endif
case MOUSEMOVE:
{
- /* don't recalculat the best edge */
+ /* don't recalculate the best edge */
const bool is_clamp = !(t->flag & T_ALT_TRANSFORM);
if (is_clamp) {
calcVertSlideMouseActiveEdges(t, event->mval);
@@ -6655,19 +7275,20 @@ static eRedrawFlag handleEventVertSlide(struct TransInfo *t, const struct wmEven
return TREDRAW_NOTHING;
}
-static void drawVertSlide(const struct bContext *C, TransInfo *t)
+static void drawVertSlide(TransInfo *t)
{
- if (t->mode == TFM_VERT_SLIDE) {
- VertSlideData *sld = (VertSlideData *)t->customData;
+ if ((t->mode == TFM_VERT_SLIDE) && t->customData) {
+ VertSlideData *sld = t->customData;
+ const bool is_clamp = !(t->flag & T_ALT_TRANSFORM);
+
/* Non-Prop mode */
- if (sld) {
- View3D *v3d = CTX_wm_view3d(C);
+ {
+ View3D *v3d = t->view;
TransDataVertSlideVert *curr_sv = &sld->sv[sld->curr_sv_index];
TransDataVertSlideVert *sv;
const float ctrl_size = UI_GetThemeValuef(TH_FACEDOT_SIZE) + 1.5f;
const float line_size = UI_GetThemeValuef(TH_OUTLINE_WIDTH) + 0.5f;
const int alpha_shade = -160;
- const bool is_clamp = !(t->flag & T_ALT_TRANSFORM);
int i;
if (v3d && v3d->zbuf)
@@ -6715,18 +7336,51 @@ static void drawVertSlide(const struct bContext *C, TransInfo *t)
curr_sv->co_orig_3d);
bglEnd();
+ glDisable(GL_BLEND);
+
+ /* direction from active vertex! */
+ if ((t->mval[0] != t->imval[0]) ||
+ (t->mval[1] != t->imval[1]))
+ {
+ float zfac;
+ float mval_ofs[2];
+ float co_orig_3d[3];
+ float co_dest_3d[3];
+
+ mval_ofs[0] = t->mval[0] - t->imval[0];
+ mval_ofs[1] = t->mval[1] - t->imval[1];
+
+ mul_v3_m4v3(co_orig_3d, t->obedit->obmat, curr_sv->co_orig_3d);
+ zfac = ED_view3d_calc_zfac(t->ar->regiondata, co_orig_3d, NULL);
+
+ ED_view3d_win_to_delta(t->ar, mval_ofs, co_dest_3d, zfac);
+
+ invert_m4_m4(t->obedit->imat, t->obedit->obmat);
+ mul_mat3_m4_v3(t->obedit->imat, co_dest_3d);
+
+ add_v3_v3(co_dest_3d, curr_sv->co_orig_3d);
+
+ glLineWidth(1);
+ setlinestyle(1);
+
+ cpack(0xffffff);
+ glBegin(GL_LINES);
+ glVertex3fv(curr_sv->co_orig_3d);
+ glVertex3fv(co_dest_3d);
+
+ glEnd();
+ }
+
glPopMatrix();
glPopAttrib();
- glDisable(GL_BLEND);
-
if (v3d && v3d->zbuf)
glEnable(GL_DEPTH_TEST);
}
}
}
-static int doVertSlide(TransInfo *t, float perc)
+static void doVertSlide(TransInfo *t, float perc)
{
VertSlideData *sld = t->customData;
TransDataVertSlideVert *svlist = sld->sv, *sv;
@@ -6765,8 +7419,6 @@ static int doVertSlide(TransInfo *t, float perc)
}
}
}
-
- return 1;
}
static void applyVertSlide(TransInfo *t, const int UNUSED(mval[2]))
@@ -6791,6 +7443,8 @@ static void applyVertSlide(TransInfo *t, const int UNUSED(mval[2]))
applyNumInput(&t->num, &final);
+ t->values[0] = final;
+
/* header string */
ofs += BLI_strncpy_rlen(str + ofs, IFACE_("Vert Slide: "), MAX_INFO_LEN - ofs);
if (hasNumInput(&t->num)) {
@@ -6859,6 +7513,8 @@ static void applyBoneRoll(TransInfo *t, const int UNUSED(mval[2]))
applyNumInput(&t->num, &final);
+ t->values[0] = final;
+
if (hasNumInput(&t->num)) {
char c[NUM_STR_REP_LEN];
@@ -7131,7 +7787,7 @@ static void initSeqSlide(TransInfo *t)
t->num.idx_max = t->idx_max;
t->snap[0] = 0.0f;
- t->snap[1] = floor(t->scene->r.frs_sec / t->scene->r.frs_sec_base);
+ t->snap[1] = floorf(t->scene->r.frs_sec / t->scene->r.frs_sec_base);
t->snap[2] = 10.0f;
copy_v3_fl(t->num.val_inc, t->snap[1]);
@@ -7141,7 +7797,7 @@ static void initSeqSlide(TransInfo *t)
t->num.unit_type[1] = B_UNIT_NONE;
}
-static void headerSeqSlide(TransInfo *t, float val[2], char str[MAX_INFO_LEN])
+static void headerSeqSlide(TransInfo *t, const float val[2], char str[MAX_INFO_LEN])
{
char tvec[NUM_STR_REP_LEN * 3];
size_t ofs = 0;
@@ -7158,7 +7814,7 @@ static void headerSeqSlide(TransInfo *t, float val[2], char str[MAX_INFO_LEN])
if (t->keymap) {
wmKeyMapItem *kmi = WM_modalkeymap_find_propvalue(t->keymap, TFM_MODAL_TRANSLATE);
if (kmi) {
- ofs += WM_keymap_item_to_string(kmi, str + ofs, MAX_INFO_LEN - ofs);
+ ofs += WM_keymap_item_to_string(kmi, false, MAX_INFO_LEN - ofs, str + ofs);
}
}
ofs += BLI_snprintf(str + ofs, MAX_INFO_LEN - ofs, IFACE_(" or Alt) Expand to fit %s"),
@@ -7171,27 +7827,22 @@ static void applySeqSlideValue(TransInfo *t, const float val[2])
int i;
for (i = 0; i < t->total; i++, td++) {
- float tvec[2];
-
if (td->flag & TD_NOACTION)
break;
if (td->flag & TD_SKIP)
continue;
- copy_v2_v2(tvec, val);
-
- mul_v2_fl(tvec, td->factor);
-
- td->loc[0] = td->iloc[0] + tvec[0];
- td->loc[1] = td->iloc[1] + tvec[1];
+ madd_v2_v2v2fl(td->loc, td->iloc, val, td->factor);
}
}
-static void applySeqSlide(TransInfo *t, const int UNUSED(mval[2]))
+static void applySeqSlide(TransInfo *t, const int mval[2])
{
char str[MAX_INFO_LEN];
+ snapSequenceBounds(t, mval);
+
if (t->con.mode & CON_APPLY) {
float pvec[3] = {0.0f, 0.0f, 0.0f};
float tvec[3];
@@ -7199,12 +7850,12 @@ static void applySeqSlide(TransInfo *t, const int UNUSED(mval[2]))
copy_v3_v3(t->values, tvec);
}
else {
- snapGridIncrement(t, t->values);
+ // snapGridIncrement(t, t->values);
applyNumInput(&t->num, t->values);
}
- t->values[0] = floor(t->values[0] + 0.5f);
- t->values[1] = floor(t->values[1] + 0.5f);
+ t->values[0] = floorf(t->values[0] + 0.5f);
+ t->values[1] = floorf(t->values[1] + 0.5f);
headerSeqSlide(t, t->values, str);
applySeqSlideValue(t, t->values);
@@ -7370,6 +8021,7 @@ static void initTimeTranslate(TransInfo *t)
static void headerTimeTranslate(TransInfo *t, char str[MAX_INFO_LEN])
{
char tvec[NUM_STR_REP_LEN * 3];
+ int ofs = 0;
/* if numeric input is active, use results from that, otherwise apply snapping to result */
if (hasNumInput(&t->num)) {
@@ -7405,10 +8057,14 @@ static void headerTimeTranslate(TransInfo *t, char str[MAX_INFO_LEN])
BLI_snprintf(&tvec[0], NUM_STR_REP_LEN, "%.4f", val);
}
- BLI_snprintf(str, MAX_INFO_LEN, IFACE_("DeltaX: %s"), &tvec[0]);
+ ofs += BLI_snprintf(str, MAX_INFO_LEN, IFACE_("DeltaX: %s"), &tvec[0]);
+
+ if (t->flag & T_PROP_EDIT_ALL) {
+ ofs += BLI_snprintf(str + ofs, MAX_INFO_LEN - ofs, IFACE_(" Proportional size: %.2f"), t->prop_size);
+ }
}
-static void applyTimeTranslateValue(TransInfo *t, float UNUSED(sval))
+static void applyTimeTranslateValue(TransInfo *t)
{
TransData *td = t->data;
TransData2D *td2d = t->data2d;
@@ -7438,11 +8094,11 @@ static void applyTimeTranslateValue(TransInfo *t, float UNUSED(sval))
deltax = (float)(floor(((double)deltax / secf) + 0.5) * secf);
}
else if (autosnap == SACTSNAP_STEP) {
- deltax = (float)(floor(deltax + 0.5f));
+ deltax = floorf(deltax + 0.5f);
}
val = BKE_nla_tweakedit_remap(adt, td->ival, NLATIME_CONVERT_MAP);
- val += deltax;
+ val += deltax * td->factor;
*(td->val) = BKE_nla_tweakedit_remap(adt, val, NLATIME_CONVERT_UNMAP);
}
else {
@@ -7452,7 +8108,7 @@ static void applyTimeTranslateValue(TransInfo *t, float UNUSED(sval))
val = (float)(floor(((double)deltax / secf) + 0.5) * secf);
}
else if (autosnap == SACTSNAP_STEP) {
- val = (float)(floor(val + 0.5f));
+ val = floorf(val + 0.5f);
}
*(td->val) = td->ival + val;
@@ -7466,15 +8122,17 @@ static void applyTimeTranslateValue(TransInfo *t, float UNUSED(sval))
static void applyTimeTranslate(TransInfo *t, const int mval[2])
{
View2D *v2d = (View2D *)t->view;
- float cval[2], sval[2];
char str[MAX_INFO_LEN];
/* calculate translation amount from mouse movement - in 'time-grid space' */
- UI_view2d_region_to_view(v2d, mval[0], mval[0], &cval[0], &cval[1]);
- UI_view2d_region_to_view(v2d, t->imval[0], t->imval[0], &sval[0], &sval[1]);
+ if (t->flag & T_MODAL) {
+ float cval[2], sval[2];
+ UI_view2d_region_to_view(v2d, mval[0], mval[0], &cval[0], &cval[1]);
+ UI_view2d_region_to_view(v2d, t->imval[0], t->imval[0], &sval[0], &sval[1]);
- /* we only need to calculate effect for time (applyTimeTranslate only needs that) */
- t->values[0] = cval[0] - sval[0];
+ /* we only need to calculate effect for time (applyTimeTranslate only needs that) */
+ t->values[0] = cval[0] - sval[0];
+ }
/* handle numeric-input stuff */
t->vec[0] = t->values[0];
@@ -7482,7 +8140,7 @@ static void applyTimeTranslate(TransInfo *t, const int mval[2])
t->values[0] = t->vec[0];
headerTimeTranslate(t, str);
- applyTimeTranslateValue(t, sval[0]);
+ applyTimeTranslateValue(t);
recalcData(t);
@@ -7532,7 +8190,7 @@ static void initTimeSlide(TransInfo *t)
t->num.unit_type[0] = B_UNIT_NONE;
}
-static void headerTimeSlide(TransInfo *t, float sval, char str[MAX_INFO_LEN])
+static void headerTimeSlide(TransInfo *t, const float sval, char str[MAX_INFO_LEN])
{
char tvec[NUM_STR_REP_LEN * 3];
@@ -7615,7 +8273,7 @@ static void applyTimeSlide(TransInfo *t, const int mval[2])
/* t->values[0] stores cval[0], which is the current mouse-pointer location (in frames) */
// XXX Need to be able to repeat this
- t->values[0] = cval[0];
+ /* t->values[0] = cval[0]; */ /* UNUSED (reset again later). */
/* handle numeric-input stuff */
t->vec[0] = 2.0f * (cval[0] - sval[0]) / (maxx - minx);
@@ -7716,7 +8374,7 @@ static void applyTimeScaleValue(TransInfo *t)
fac = (float)(floor((double)fac / secf + 0.5) * secf);
}
else if (autosnap == SACTSNAP_STEP) {
- fac = (float)(floor(fac + 0.5f));
+ fac = floorf(fac + 0.5f);
}
/* check if any need to apply nla-mapping */
diff --git a/source/blender/editors/transform/transform.h b/source/blender/editors/transform/transform.h
index 012f9185d8b..aab065675fe 100644
--- a/source/blender/editors/transform/transform.h
+++ b/source/blender/editors/transform/transform.h
@@ -39,9 +39,6 @@
#include "DNA_listBase.h"
-#include "BLI_smallhash.h"
-#include "BKE_editmesh.h"
-
/* ************************** Types ***************************** */
struct TransInfo;
@@ -84,6 +81,7 @@ typedef struct TransSnap {
bool project;
bool snap_self;
bool peel;
+ bool snap_spatial_grid;
short status;
float snapPoint[3]; /* snapping from this point */
float snapTarget[3]; /* to this point */
@@ -107,8 +105,6 @@ typedef struct TransCon {
float mtx[3][3]; /* Matrix of the Constraint space */
float imtx[3][3]; /* Inverse Matrix of the Constraint space */
float pmtx[3][3]; /* Projection Constraint Matrix (same as imtx with some axis == 0) */
- float center[3]; /* transformation center to define where to draw the view widget
- * ALWAYS in global space. Unlike the transformation center */
int imval[2]; /* initial mouse value for visual calculation */
/* the one in TransInfo is not garanty to stay the same (Rotates change it) */
int mode; /* Mode flags of the Constraint */
@@ -173,6 +169,13 @@ typedef struct TransDataSeq {
} TransDataSeq;
+typedef struct TransSeq {
+ TransDataSeq *tdseq;
+ int min;
+ int max;
+ bool snap_left;
+} TransSeq;
+
/* for NLA transform (stored in td->extra pointer) */
typedef struct TransDataNla {
ID *id; /* ID-block NLA-data is attached to */
@@ -193,31 +196,59 @@ typedef struct TransDataNla {
struct LinkNode;
struct GHash;
+/* header of TransDataEdgeSlideVert, TransDataEdgeSlideEdge */
+typedef struct TransDataGenericSlideVert {
+ struct BMVert *v;
+ struct LinkNode **cd_loop_groups;
+ float co_orig_3d[3];
+} TransDataGenericSlideVert;
+
typedef struct TransDataEdgeSlideVert {
- struct BMVert *v_a, *v_b;
+ /* TransDataGenericSlideVert */
struct BMVert *v;
+ struct LinkNode **cd_loop_groups;
float v_co_orig[3];
+ /* end generic */
float edge_len;
+ struct BMVert *v_side[2];
+
/* add origvert.co to get the original locations */
- float dir_a[3], dir_b[3];
+ float dir_side[2][3];
int loop_nr;
} TransDataEdgeSlideVert;
+
+/* store original data so we can correct UV's and similar when sliding */
+typedef struct SlideOrigData {
+ /* flag that is set when origfaces is initialized */
+ bool use_origfaces;
+ struct GHash *origverts; /* map {BMVert: TransDataGenericSlideVert} */
+ struct GHash *origfaces;
+ struct BMesh *bm_origfaces;
+
+ struct MemArena *arena;
+ /* number of math BMLoop layers */
+ int layer_math_map_num;
+ /* array size of 'layer_math_map_num'
+ * maps TransDataVertSlideVert.cd_group index to absolute CustomData layer index */
+ int *layer_math_map;
+
+ /* array of slide vert data especially for mirror verts */
+ TransDataGenericSlideVert *sv_mirror;
+ int totsv_mirror;
+} SlideOrigData;
+
typedef struct EdgeSlideData {
TransDataEdgeSlideVert *sv;
int totsv;
-
- struct GHash *origfaces;
int mval_start[2], mval_end[2];
struct BMEditMesh *em;
- /* flag that is set when origfaces is initialized */
- bool use_origfaces;
- struct BMesh *bm_origfaces;
+ SlideOrigData orig_data;
float perc;
@@ -225,15 +256,20 @@ typedef struct EdgeSlideData {
bool flipped_vtx;
int curr_sv_index;
+
+ /** when un-clamped - use this index: #TransDataEdgeSlideVert.dir_side */
+ int curr_side_unclamp;
} EdgeSlideData;
typedef struct TransDataVertSlideVert {
- BMVert *v;
+ /* TransDataGenericSlideVert */
+ struct BMVert *v;
+ struct LinkNode **cd_loop_groups;
float co_orig_3d[3];
- float co_orig_2d[2];
+ /* end generic */
+
float (*co_link_orig_3d)[3];
- float (*co_link_orig_2d)[2];
int co_link_tot;
int co_link_curr;
} TransDataVertSlideVert;
@@ -244,12 +280,17 @@ typedef struct VertSlideData {
struct BMEditMesh *em;
+ SlideOrigData orig_data;
+
float perc;
bool is_proportional;
bool flipped_vtx;
int curr_sv_index;
+
+ /* result of ED_view3d_ob_project_mat_get */
+ float proj_mat[4][4];
} VertSlideData;
typedef struct BoneInitData {
@@ -319,12 +360,16 @@ typedef struct TransInfo {
eRedrawFlag redraw; /* redraw flag */
float prop_size; /* proportional circle radius */
char proptext[20]; /* proportional falloff text */
- float center[3]; /* center of transformation */
+ float aspect[3]; /* spaces using non 1:1 aspect, (uv's, f-curve, movie-clip... etc)
+ * use for conversion and snapping. */
+ float center[3]; /* center of transformation (in local-space) */
+ float center_global[3]; /* center of transformation (in global-space) */
float center2d[2]; /* center in screen coordinates */
int imval[2]; /* initial mouse position */
short event_type; /* event->type used to invoke transform */
short idx_max; /* maximum index on the input vector */
float snap[3]; /* Snapping Gears */
+ float snap_spatial[3]; /* Spatial snapping gears(even when rotating, scaling... etc) */
char frame_side; /* Mouse side of the cfra, 'L', 'R' or 'B' */
float viewmat[4][4]; /* copy from G.vd, prevents feedback, */
@@ -504,6 +549,7 @@ void transformApply(struct bContext *C, TransInfo *t);
int transformEnd(struct bContext *C, TransInfo *t);
void setTransformViewMatrices(TransInfo *t);
+void setTransformViewAspect(TransInfo *t, float r_aspect[3]);
void convertViewVec(TransInfo *t, float r_vec[3], int dx, int dy);
void projectIntViewEx(TransInfo *t, const float vec[3], int adr[2], const eV3DProjTest flag);
void projectIntView(TransInfo *t, const float vec[3], int adr[2]);
@@ -537,7 +583,6 @@ void restoreBones(TransInfo *t);
/*********************** exported from transform_manipulator.c ********** */
bool gimbal_axis(struct Object *ob, float gmat[3][3]); /* return 0 when no gimbal for selection */
-int calc_manipulator_stats(const struct bContext *C);
/*********************** TransData Creation and General Handling *********** */
void createTransData(struct bContext *C, TransInfo *t);
@@ -546,6 +591,7 @@ void special_aftertrans_update(struct bContext *C, TransInfo *t);
int special_transform_moving(TransInfo *t);
void transform_autoik_update(TransInfo *t, short mode);
+bool transdata_check_local_islands(TransInfo *t, short around);
int count_set_pose_transflags(int *out_mode, short around, struct Object *ob);
@@ -589,6 +635,8 @@ typedef enum {
void snapGridIncrement(TransInfo *t, float *val);
void snapGridIncrementAction(TransInfo *t, float *val, GearsType action);
+void snapSequenceBounds(TransInfo *t, const int mval[2]);
+
bool activeSnap(TransInfo *t);
bool validSnap(TransInfo *t);
@@ -651,6 +699,7 @@ void restoreTransObjects(TransInfo *t);
void recalcData(TransInfo *t);
void calculateCenter2D(TransInfo *t);
+void calculateCenterGlobal(TransInfo *t);
void calculateCenter(TransInfo *t);
@@ -666,6 +715,8 @@ void calculatePropRatio(TransInfo *t);
void getViewVector(TransInfo *t, float coord[3], float vec[3]);
+void transform_data_ext_rotate(TransData *td, float mat[3][3], bool use_drot);
+
/*********************** Transform Orientations ******************************/
void initTransformOrientation(struct bContext *C, TransInfo *t);
@@ -676,7 +727,7 @@ bool createSpaceNormalTangent(float mat[3][3], const float normal[3], const floa
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]);
+bool applyTransformOrientation(const struct bContext *C, float mat[3][3], char r_name[64], int index);
#define ORIENTATION_NONE 0
#define ORIENTATION_NORMAL 1
@@ -684,13 +735,16 @@ bool applyTransformOrientation(const struct bContext *C, float mat[3][3], char r
#define ORIENTATION_EDGE 3
#define ORIENTATION_FACE 4
-int getTransformOrientation(const struct bContext *C, float normal[3], float plane[3], const bool activeOnly);
+int getTransformOrientation_ex(const struct bContext *C, float normal[3], float plane[3], const short around);
+int getTransformOrientation(const struct bContext *C, float normal[3], float plane[3]);
void freeEdgeSlideTempFaces(EdgeSlideData *sld);
void freeEdgeSlideVerts(TransInfo *t);
void projectEdgeSlideData(TransInfo *t, bool is_final);
+void freeVertSlideTempFaces(VertSlideData *sld);
void freeVertSlideVerts(TransInfo *t);
+void projectVertSlideData(TransInfo *t, bool is_final);
/* TODO. transform_queries.c */
diff --git a/source/blender/editors/transform/transform_constraints.c b/source/blender/editors/transform/transform_constraints.c
index d8f17315c01..895c8a81044 100644
--- a/source/blender/editors/transform/transform_constraints.c
+++ b/source/blender/editors/transform/transform_constraints.c
@@ -46,13 +46,14 @@
#include "BLI_math.h"
#include "BLI_utildefines.h"
#include "BLI_string.h"
+#include "BLI_rect.h"
#include "BKE_context.h"
#include "ED_image.h"
#include "ED_view3d.h"
-#include "BLF_translation.h"
+#include "BLT_translation.h"
#include "UI_resources.h"
@@ -202,13 +203,13 @@ static void axisProjection(TransInfo *t, const float axis[3], const float in[3],
return;
}
- copy_v3_v3(t_con_center, t->con.center);
+ copy_v3_v3(t_con_center, t->center_global);
/* checks for center being too close to the view center */
viewAxisCorrectCenter(t, t_con_center);
angle = fabsf(angle_v3v3(axis, t->viewinv[2]));
- if (angle > (float)M_PI / 2.0f) {
+ if (angle > (float)M_PI_2) {
angle = (float)M_PI - angle;
}
angle = RAD2DEGF(angle);
@@ -276,7 +277,7 @@ static void planeProjection(TransInfo *t, const float in[3], float out[3])
{
float vec[3], factor, norm[3];
- add_v3_v3v3(vec, in, t->con.center);
+ add_v3_v3v3(vec, in, t->center_global);
getViewVector(t, vec, norm);
sub_v3_v3v3(vec, out, in);
@@ -309,7 +310,7 @@ static void applyAxisConstraintVec(TransInfo *t, TransData *td, const float in[3
mul_m3_v3(t->con.pmtx, out);
// With snap, a projection is alright, no need to correct for view alignment
- if (!(t->tsnap.mode != SCE_SNAP_MODE_INCREMENT && activeSnap(t))) {
+ if (!(!ELEM(t->tsnap.mode, SCE_SNAP_MODE_INCREMENT, SCE_SNAP_MODE_GRID) && activeSnap(t))) {
if (getConstraintSpaceDimension(t) == 2) {
if (out[0] != 0.0f || out[1] != 0.0f || out[2] != 0.0f) {
planeProjection(t, in, out);
@@ -687,11 +688,11 @@ void drawConstraint(TransInfo *t)
int depth_test_enabled;
convertViewVec(t, vec, (t->mval[0] - t->con.imval[0]), (t->mval[1] - t->con.imval[1]));
- add_v3_v3(vec, tc->center);
+ add_v3_v3(vec, t->center_global);
- drawLine(t, tc->center, tc->mtx[0], 'X', 0);
- drawLine(t, tc->center, tc->mtx[1], 'Y', 0);
- drawLine(t, tc->center, tc->mtx[2], 'Z', 0);
+ drawLine(t, t->center_global, tc->mtx[0], 'X', 0);
+ drawLine(t, t->center_global, tc->mtx[1], 'Y', 0);
+ drawLine(t, t->center_global, tc->mtx[2], 'Z', 0);
glColor3ubv((GLubyte *)col2);
@@ -701,7 +702,7 @@ void drawConstraint(TransInfo *t)
setlinestyle(1);
glBegin(GL_LINE_STRIP);
- glVertex3fv(tc->center);
+ glVertex3fv(t->center_global);
glVertex3fv(vec);
glEnd();
setlinestyle(0);
@@ -711,13 +712,13 @@ void drawConstraint(TransInfo *t)
}
if (tc->mode & CON_AXIS0) {
- drawLine(t, tc->center, tc->mtx[0], 'X', DRAWLIGHT);
+ drawLine(t, t->center_global, tc->mtx[0], 'X', DRAWLIGHT);
}
if (tc->mode & CON_AXIS1) {
- drawLine(t, tc->center, tc->mtx[1], 'Y', DRAWLIGHT);
+ drawLine(t, t->center_global, tc->mtx[1], 'Y', DRAWLIGHT);
}
if (tc->mode & CON_AXIS2) {
- drawLine(t, tc->center, tc->mtx[2], 'Z', DRAWLIGHT);
+ drawLine(t, t->center_global, tc->mtx[2], 'Z', DRAWLIGHT);
}
}
}
@@ -728,7 +729,6 @@ void drawPropCircle(const struct bContext *C, TransInfo *t)
if (t->flag & T_PROP_EDIT) {
RegionView3D *rv3d = CTX_wm_region_view3d(C);
float tmat[4][4], imat[4][4];
- float center[3];
int depth_test_enabled;
UI_ThemeColor(TH_GRID);
@@ -744,25 +744,21 @@ void drawPropCircle(const struct bContext *C, TransInfo *t)
glPushMatrix();
- copy_v3_v3(center, t->center);
-
- if ((t->spacetype == SPACE_VIEW3D) && t->obedit) {
- mul_m4_v3(t->obedit->obmat, center); /* because t->center is in local space */
+ if (t->spacetype == SPACE_VIEW3D) {
+ /* pass */
}
else if (t->spacetype == SPACE_IMAGE) {
- float aspx, aspy;
-
- if (t->options & CTX_MASK) {
- /* untested - mask aspect is TODO */
- ED_space_image_get_aspect(t->sa->spacedata.first, &aspx, &aspy);
- }
- else if (t->options & CTX_PAINT_CURVE) {
- aspx = aspy = 1.0;
- }
- else {
- ED_space_image_get_uv_aspect(t->sa->spacedata.first, &aspx, &aspy);
- }
- glScalef(1.0f / aspx, 1.0f / aspy, 1.0);
+ glScalef(1.0f / t->aspect[0], 1.0f / t->aspect[1], 1.0f);
+ }
+ else if (ELEM(t->spacetype, SPACE_IPO, SPACE_ACTION)) {
+ /* only scale y */
+ rcti *mask = &t->ar->v2d.mask;
+ rctf *datamask = &t->ar->v2d.cur;
+ float xsize = BLI_rctf_size_x(datamask);
+ float ysize = BLI_rctf_size_y(datamask);
+ float xmask = BLI_rcti_size_x(mask);
+ float ymask = BLI_rcti_size_y(mask);
+ glScalef(1.0f, (ysize / xsize) * (xmask / ymask), 1.0f);
}
depth_test_enabled = glIsEnabled(GL_DEPTH_TEST);
@@ -770,7 +766,7 @@ void drawPropCircle(const struct bContext *C, TransInfo *t)
glDisable(GL_DEPTH_TEST);
set_inverted_drawing(1);
- drawcircball(GL_LINE_LOOP, center, t->prop_size, imat);
+ drawcircball(GL_LINE_LOOP, t->center_global, t->prop_size, imat);
set_inverted_drawing(0);
if (depth_test_enabled)
@@ -859,21 +855,15 @@ void getConstraintMatrix(TransInfo *t)
unit_m3(t->con.pmtx);
if (!(t->con.mode & CON_AXIS0)) {
- t->con.pmtx[0][0] =
- t->con.pmtx[0][1] =
- t->con.pmtx[0][2] = 0.0f;
+ zero_v3(t->con.pmtx[0]);
}
if (!(t->con.mode & CON_AXIS1)) {
- t->con.pmtx[1][0] =
- t->con.pmtx[1][1] =
- t->con.pmtx[1][2] = 0.0f;
+ zero_v3(t->con.pmtx[1]);
}
if (!(t->con.mode & CON_AXIS2)) {
- t->con.pmtx[2][0] =
- t->con.pmtx[2][1] =
- t->con.pmtx[2][2] = 0.0f;
+ zero_v3(t->con.pmtx[2]);
}
mul_m3_m3m3(mat, t->con.pmtx, t->con.imtx);
@@ -961,7 +951,7 @@ static void setNearestAxis3d(TransInfo *t)
mul_v3_fl(axis, zfac);
/* now we can project to get window coordinate */
- add_v3_v3(axis, t->con.center);
+ add_v3_v3(axis, t->center_global);
projectFloatView(t, axis, axis_2d);
sub_v2_v2v2(axis, axis_2d, t->center2d);
diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c
index b7098085ac2..c12418f1a0f 100644
--- a/source/blender/editors/transform/transform_conversions.c
+++ b/source/blender/editors/transform/transform_conversions.c
@@ -31,6 +31,7 @@
#include <string.h>
#include <math.h>
+#include <limits.h>
#include "DNA_anim_types.h"
#include "DNA_brush_types.h"
@@ -54,11 +55,11 @@
#include "BLI_math.h"
#include "BLI_utildefines.h"
-#include "BLI_smallhash.h"
#include "BLI_listbase.h"
#include "BLI_linklist_stack.h"
#include "BLI_string.h"
#include "BLI_bitmap.h"
+#include "BLI_rect.h"
#include "BKE_DerivedMesh.h"
#include "BKE_action.h"
@@ -90,7 +91,6 @@
#include "BKE_editmesh.h"
#include "BKE_tracking.h"
#include "BKE_mask.h"
-#include "BKE_lattice.h"
#include "BIK_api.h"
@@ -107,6 +107,7 @@
#include "ED_uvedit.h"
#include "ED_clip.h"
#include "ED_mask.h"
+#include "ED_gpencil.h"
#include "WM_api.h" /* for WM_event_add_notifier to deal with stabilization nodes */
#include "WM_types.h"
@@ -218,6 +219,9 @@ static void set_prop_dist(TransInfo *t, const bool with_dist)
float _proj_vec[3];
const float *proj_vec = NULL;
+ /* support for face-islands */
+ const bool use_island = transdata_check_local_islands(t, t->around);
+
if (t->flag & T_PROP_PROJECTED) {
if (t->spacetype == SPACE_VIEW3D && t->ar && t->ar->regiontype == RGN_TYPE_WINDOW) {
RegionView3D *rv3d = t->ar->regiondata;
@@ -239,7 +243,12 @@ static void set_prop_dist(TransInfo *t, const bool with_dist)
for (i = 0, td = t->data; i < t->total; i++, td++) {
if (td->flag & TD_SELECTED) {
- sub_v3_v3v3(vec, tob->center, td->center);
+ if (use_island) {
+ sub_v3_v3v3(vec, tob->iloc, td->iloc);
+ }
+ else {
+ sub_v3_v3v3(vec, tob->center, td->center);
+ }
mul_m3_v3(tob->mtx, vec);
if (proj_vec) {
@@ -249,8 +258,12 @@ static void set_prop_dist(TransInfo *t, const bool with_dist)
}
dist_sq = len_squared_v3(vec);
- if ((tob->rdist == -1.0f) || (dist_sq < (tob->rdist * tob->rdist))) {
+ if ((tob->rdist == -1.0f) || (dist_sq < SQUARE(tob->rdist))) {
tob->rdist = sqrtf(dist_sq);
+ if (use_island) {
+ copy_v3_v3(tob->center, td->center);
+ copy_m3_m3(tob->axismtx, td->axismtx);
+ }
}
}
else {
@@ -329,20 +342,20 @@ static void createTransEdge(TransInfo *t)
BMIter iter;
float mtx[3][3], smtx[3][3];
int count = 0, countsel = 0;
- int propmode = t->flag & T_PROP_EDIT;
+ const bool is_prop_edit = (t->flag & T_PROP_EDIT) != 0;
int cd_edge_float_offset;
BM_ITER_MESH (eed, &iter, em->bm, BM_EDGES_OF_MESH) {
if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN)) {
if (BM_elem_flag_test(eed, BM_ELEM_SELECT)) countsel++;
- if (propmode) count++;
+ if (is_prop_edit) count++;
}
}
if (countsel == 0)
return;
- if (propmode) {
+ if (is_prop_edit) {
t->total = count;
}
else {
@@ -368,7 +381,7 @@ static void createTransEdge(TransInfo *t)
BLI_assert(cd_edge_float_offset != -1);
BM_ITER_MESH (eed, &iter, em->bm, BM_EDGES_OF_MESH) {
- if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN) && (BM_elem_flag_test(eed, BM_ELEM_SELECT) || propmode)) {
+ if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN) && (BM_elem_flag_test(eed, BM_ELEM_SELECT) || is_prop_edit)) {
float *fl_ptr;
/* need to set center for center calculations */
mid_v3_v3v3(td->center, eed->v1->co, eed->v2->co);
@@ -616,10 +629,10 @@ static void add_pose_transdata(TransInfo *t, bPoseChannel *pchan, Object *ob, Tr
mul_m3_m3m3(td->axismtx, omat, pmat);
normalize_m3(td->axismtx);
- if (t->mode == TFM_BONESIZE) {
+ if (ELEM(t->mode, TFM_BONESIZE, TFM_BONE_ENVELOPE_DIST)) {
bArmature *arm = t->poseobj->data;
- if (arm->drawtype == ARM_ENVELOPE) {
+ if ((t->mode == TFM_BONE_ENVELOPE_DIST) || (arm->drawtype == ARM_ENVELOPE)) {
td->loc = NULL;
td->val = &bone->dist;
td->ival = bone->dist;
@@ -706,7 +719,7 @@ int count_set_pose_transflags(int *out_mode, short around, Object *ob)
/* make sure no bone can be transformed when a parent is transformed */
/* since pchans are depsgraph sorted, the parents are in beginning of list */
- if (mode != TFM_BONESIZE) {
+ if (!ELEM(mode, TFM_BONESIZE, TFM_BONE_ENVELOPE_DIST)) {
for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
bone = pchan->bone;
if (bone->flag & BONE_TRANSFORM)
@@ -1056,11 +1069,13 @@ static void createTransPose(TransInfo *t, Object *ob)
void restoreBones(TransInfo *t)
{
+ bArmature *arm = t->obedit->data;
BoneInitData *bid = t->customData;
EditBone *ebo;
while (bid->bone) {
ebo = bid->bone;
+
ebo->dist = bid->dist;
ebo->rad_tail = bid->rad_tail;
ebo->roll = bid->roll;
@@ -1068,7 +1083,26 @@ void restoreBones(TransInfo *t)
ebo->zwidth = bid->zwidth;
copy_v3_v3(ebo->head, bid->head);
copy_v3_v3(ebo->tail, bid->tail);
+
+ if (arm->flag & ARM_MIRROR_EDIT) {
+ EditBone *ebo_child;
+
+ /* Also move connected ebo_child, in case ebo_child's name aren't mirrored properly */
+ for (ebo_child = arm->edbo->first; ebo_child; ebo_child = ebo_child->next) {
+ if ((ebo_child->flag & BONE_CONNECTED) && (ebo_child->parent == ebo)) {
+ copy_v3_v3(ebo_child->head, ebo->tail);
+ ebo_child->rad_head = ebo->rad_tail;
+ }
+ }
+ /* Also move connected parent, in case parent's name isn't mirrored properly */
+ if ((ebo->flag & BONE_CONNECTED) && ebo->parent) {
+ EditBone *parent = ebo->parent;
+ copy_v3_v3(parent->tail, ebo->head);
+ parent->rad_tail = ebo->rad_head;
+ }
+ }
+
bid++;
}
}
@@ -1092,7 +1126,7 @@ static void createTransArmatureVerts(TransInfo *t)
oldtot = t->total;
if (EBONE_VISIBLE(arm, ebo) && !(ebo->flag & BONE_EDITMODE_LOCKED)) {
- if (t->mode == TFM_BONESIZE) {
+ if (ELEM(t->mode, TFM_BONESIZE, TFM_BONE_ENVELOPE_DIST)) {
if (ebo->flag & BONE_SELECTED)
t->total++;
}
@@ -1170,9 +1204,9 @@ static void createTransArmatureVerts(TransInfo *t)
}
}
- else if (t->mode == TFM_BONESIZE) {
+ else if (ELEM(t->mode, TFM_BONESIZE, TFM_BONE_ENVELOPE_DIST)) {
if (ebo->flag & BONE_SELECTED) {
- if (arm->drawtype == ARM_ENVELOPE) {
+ if ((t->mode == TFM_BONE_ENVELOPE_DIST) || (arm->drawtype == ARM_ENVELOPE)) {
td->loc = NULL;
td->val = &ebo->dist;
td->ival = ebo->dist;
@@ -1218,7 +1252,13 @@ static void createTransArmatureVerts(TransInfo *t)
else {
if (ebo->flag & BONE_TIPSEL) {
copy_v3_v3(td->iloc, ebo->tail);
- copy_v3_v3(td->center, (t->around == V3D_LOCAL) ? ebo->head : td->iloc);
+
+ /* don't allow single selected tips to have a modified center,
+ * causes problem with snapping T45974 */
+ copy_v3_v3(td->center,
+ ((t->around == V3D_LOCAL) &&
+ (ebo->flag & BONE_ROOTSEL)) ? ebo->head : td->iloc);
+
td->loc = ebo->tail;
td->flag = TD_SELECTED;
if (ebo->flag & BONE_EDITMODE_LOCKED)
@@ -1297,18 +1337,18 @@ static void createTransMBallVerts(TransInfo *t)
TransDataExtension *tx;
float mtx[3][3], smtx[3][3];
int count = 0, countsel = 0;
- int propmode = t->flag & T_PROP_EDIT;
+ const bool is_prop_edit = (t->flag & T_PROP_EDIT) != 0;
/* count totals */
for (ml = mb->editelems->first; ml; ml = ml->next) {
if (ml->flag & SELECT) countsel++;
- if (propmode) count++;
+ if (is_prop_edit) count++;
}
/* note: in prop mode we need at least 1 selected */
if (countsel == 0) return;
- if (propmode) t->total = count;
+ if (is_prop_edit) t->total = count;
else t->total = countsel;
td = t->data = MEM_callocN(t->total * sizeof(TransData), "TransObData(MBall EditMode)");
@@ -1318,7 +1358,7 @@ static void createTransMBallVerts(TransInfo *t)
pseudoinverse_m3_m3(smtx, mtx, PSEUDOINVERSE_EPSILON);
for (ml = mb->editelems->first; ml; ml = ml->next) {
- if (propmode || (ml->flag & SELECT)) {
+ if (is_prop_edit || (ml->flag & SELECT)) {
td->loc = &ml->x;
copy_v3_v3(td->iloc, td->loc);
copy_v3_v3(td->center, td->loc);
@@ -1431,7 +1471,7 @@ static void createTransCurveVerts(TransInfo *t)
float mtx[3][3], smtx[3][3];
int a;
int count = 0, countsel = 0;
- int propmode = t->flag & T_PROP_EDIT;
+ const bool is_prop_edit = (t->flag & T_PROP_EDIT) != 0;
short hide_handles = (cu->drawflag & CU_HIDE_HANDLES);
ListBase *nurbs;
@@ -1446,13 +1486,13 @@ static void createTransCurveVerts(TransInfo *t)
if (bezt->hide == 0) {
if (hide_handles) {
if (bezt->f2 & SELECT) countsel += 3;
- if (propmode) count += 3;
+ if (is_prop_edit) count += 3;
}
else {
if (bezt->f1 & SELECT) countsel++;
if (bezt->f2 & SELECT) countsel++;
if (bezt->f3 & SELECT) countsel++;
- if (propmode) count += 3;
+ if (is_prop_edit) count += 3;
}
}
}
@@ -1460,7 +1500,7 @@ static void createTransCurveVerts(TransInfo *t)
else {
for (a = nu->pntsu * nu->pntsv, bp = nu->bp; a > 0; a--, bp++) {
if (bp->hide == 0) {
- if (propmode) count++;
+ if (is_prop_edit) count++;
if (bp->f1 & SELECT) countsel++;
}
}
@@ -1469,7 +1509,7 @@ static void createTransCurveVerts(TransInfo *t)
/* note: in prop mode we need at least 1 selected */
if (countsel == 0) return;
- if (propmode) t->total = count;
+ if (is_prop_edit) t->total = count;
else t->total = countsel;
t->data = MEM_callocN(t->total * sizeof(TransData), "TransObData(Curve EditMode)");
@@ -1504,7 +1544,7 @@ static void createTransCurveVerts(TransInfo *t)
}
}
- if (propmode ||
+ if (is_prop_edit ||
((bezt->f2 & SELECT) && hide_handles) ||
((bezt->f1 & SELECT) && hide_handles == 0))
{
@@ -1538,7 +1578,7 @@ static void createTransCurveVerts(TransInfo *t)
}
/* This is the Curve Point, the other two are handles */
- if (propmode || (bezt->f2 & SELECT)) {
+ if (is_prop_edit || (bezt->f2 & SELECT)) {
copy_v3_v3(td->iloc, bezt->vec[1]);
td->loc = bezt->vec[1];
copy_v3_v3(td->center, td->loc);
@@ -1574,7 +1614,7 @@ static void createTransCurveVerts(TransInfo *t)
count++;
tail++;
}
- if (propmode ||
+ if (is_prop_edit ||
((bezt->f2 & SELECT) && hide_handles) ||
((bezt->f3 & SELECT) && hide_handles == 0))
{
@@ -1611,17 +1651,17 @@ static void createTransCurveVerts(TransInfo *t)
(void)hdata; /* quiet warning */
}
- else if (propmode && head != tail) {
+ else if (is_prop_edit && head != tail) {
calc_distanceCurveVerts(head, tail - 1);
head = tail;
}
}
- if (propmode && head != tail)
+ if (is_prop_edit && head != tail)
calc_distanceCurveVerts(head, tail - 1);
/* TODO - in the case of tilt and radius we can also avoid allocating the initTransDataCurveHandles
* but for now just don't change handle types */
- if (ELEM(t->mode, TFM_CURVE_SHRINKFATTEN, TFM_TILT) == 0) {
+ if (ELEM(t->mode, TFM_CURVE_SHRINKFATTEN, TFM_TILT, TFM_DUMMY) == 0) {
/* sets the handles based on their selection, do this after the data is copied to the TransData */
BKE_nurb_handles_test(nu, !hide_handles);
}
@@ -1631,7 +1671,7 @@ static void createTransCurveVerts(TransInfo *t)
head = tail = td;
for (a = nu->pntsu * nu->pntsv, bp = nu->bp; a > 0; a--, bp++) {
if (bp->hide == 0) {
- if (propmode || (bp->f1 & SELECT)) {
+ if (is_prop_edit || (bp->f1 & SELECT)) {
copy_v3_v3(td->iloc, bp->vec);
td->loc = bp->vec;
copy_v3_v3(td->center, td->loc);
@@ -1656,12 +1696,12 @@ static void createTransCurveVerts(TransInfo *t)
tail++;
}
}
- else if (propmode && head != tail) {
+ else if (is_prop_edit && head != tail) {
calc_distanceCurveVerts(head, tail - 1);
head = tail;
}
}
- if (propmode && head != tail)
+ if (is_prop_edit && head != tail)
calc_distanceCurveVerts(head, tail - 1);
}
}
@@ -1677,14 +1717,14 @@ static void createTransLatticeVerts(TransInfo *t)
float mtx[3][3], smtx[3][3];
int a;
int count = 0, countsel = 0;
- int propmode = t->flag & T_PROP_EDIT;
+ const bool is_prop_edit = (t->flag & T_PROP_EDIT) != 0;
bp = latt->def;
a = latt->pntsu * latt->pntsv * latt->pntsw;
while (a--) {
if (bp->hide == 0) {
if (bp->f1 & SELECT) countsel++;
- if (propmode) count++;
+ if (is_prop_edit) count++;
}
bp++;
}
@@ -1692,7 +1732,7 @@ static void createTransLatticeVerts(TransInfo *t)
/* note: in prop mode we need at least 1 selected */
if (countsel == 0) return;
- if (propmode) t->total = count;
+ if (is_prop_edit) t->total = count;
else t->total = countsel;
t->data = MEM_callocN(t->total * sizeof(TransData), "TransObData(Lattice EditMode)");
@@ -1703,7 +1743,7 @@ static void createTransLatticeVerts(TransInfo *t)
bp = latt->def;
a = latt->pntsu * latt->pntsv * latt->pntsw;
while (a--) {
- if (propmode || (bp->f1 & SELECT)) {
+ if (is_prop_edit || (bp->f1 & SELECT)) {
if (bp->hide == 0) {
copy_v3_v3(td->iloc, bp->vec);
td->loc = bp->vec;
@@ -1711,7 +1751,9 @@ static void createTransLatticeVerts(TransInfo *t)
if (bp->f1 & SELECT) {
td->flag = TD_SELECTED;
}
- else td->flag = 0;
+ else {
+ td->flag = 0;
+ }
copy_m3_m3(td->smtx, smtx);
copy_m3_m3(td->mtx, mtx);
@@ -1742,7 +1784,7 @@ static void createTransParticleVerts(bContext *C, TransInfo *t)
float mat[4][4];
int i, k, transformparticle;
int count = 0, hasselected = 0;
- int propmode = t->flag & T_PROP_EDIT;
+ const bool is_prop_edit = (t->flag & T_PROP_EDIT) != 0;
if (edit == NULL || t->settings->particle.selectmode == SCE_SELECT_PATH) return;
@@ -1764,7 +1806,7 @@ static void createTransParticleVerts(bContext *C, TransInfo *t)
hasselected = 1;
transformparticle = 1;
}
- else if (propmode)
+ else if (is_prop_edit)
transformparticle = 1;
}
}
@@ -1814,7 +1856,7 @@ static void createTransParticleVerts(bContext *C, TransInfo *t)
if (key->flag & PEK_SELECT)
td->flag |= TD_SELECTED;
- else if (!propmode)
+ else if (!is_prop_edit)
td->flag |= TD_SKIP;
unit_m3(td->mtx);
@@ -1843,7 +1885,7 @@ static void createTransParticleVerts(bContext *C, TransInfo *t)
tx++;
tail++;
}
- if (propmode && head != tail)
+ if (is_prop_edit && head != tail)
calc_distanceCurveVerts(head, tail - 1);
}
}
@@ -1859,7 +1901,8 @@ void flushTransParticles(TransInfo *t)
PTCacheEditKey *key;
TransData *td;
float mat[4][4], imat[4][4], co[3];
- int i, k, propmode = t->flag & T_PROP_EDIT;
+ int i, k;
+ const bool is_prop_edit = (t->flag & T_PROP_EDIT) != 0;
if (psys)
psmd = psys_get_modifier(ob, psys);
@@ -1880,7 +1923,7 @@ void flushTransParticles(TransInfo *t)
/* optimization for proportional edit */
- if (!propmode || !compare_v3v3(key->co, co, 0.0001f)) {
+ if (!is_prop_edit || !compare_v3v3(key->co, co, 0.0001f)) {
copy_v3_v3(key->co, co);
point->flag |= PEP_EDIT_RECALC;
}
@@ -1938,17 +1981,19 @@ static void editmesh_set_connectivity_distance(BMesh *bm, float mtx[3][3], float
int i;
BM_ITER_MESH_INDEX (v, &viter, bm, BM_VERTS_OF_MESH, i) {
+ float dist;
BM_elem_index_set(v, i); /* set_inline */
BM_elem_flag_disable(v, BM_ELEM_TAG);
if (BM_elem_flag_test(v, BM_ELEM_SELECT) == 0 || BM_elem_flag_test(v, BM_ELEM_HIDDEN)) {
- dists[i] = FLT_MAX;
+ dist = FLT_MAX;
}
else {
BLI_LINKSTACK_PUSH(queue, v);
-
- dists[i] = 0.0f;
+ dist = 0.0f;
}
+
+ dists[i] = dists_prev[i] = dist;
}
bm->elem_index_dirty &= ~BM_VERT;
}
@@ -1957,55 +2002,77 @@ static void editmesh_set_connectivity_distance(BMesh *bm, float mtx[3][3], float
BMVert *v;
LinkNode *lnk;
+ /* this is correct but slow to do each iteration,
+ * instead sync the dist's while clearing BM_ELEM_TAG (below) */
+#if 0
memcpy(dists_prev, dists, sizeof(float) * bm->totvert);
+#endif
while ((v = BLI_LINKSTACK_POP(queue))) {
- /* quick checks */
- bool has_edges = (v->e != NULL);
- bool has_faces = false;
+ BLI_assert(dists[BM_elem_index_get(v)] != FLT_MAX);
/* connected edge-verts */
- if (has_edges) {
- BMIter iter;
- BMEdge *e;
+ if (v->e != NULL) {
+ BMEdge *e_iter, *e_first;
+
+ e_iter = e_first = v->e;
- BM_ITER_ELEM (e, &iter, v, BM_EDGES_OF_VERT) {
- has_faces |= (BM_edge_is_wire(e) == false);
+ /* would normally use BM_EDGES_OF_VERT, but this runs so often,
+ * its faster to iterate on the data directly */
+ do {
- if (BM_elem_flag_test(e, BM_ELEM_HIDDEN) == 0) {
- BMVert *v_other = BM_edge_other_vert(e, v);
+ if (BM_elem_flag_test(e_iter, BM_ELEM_HIDDEN) == 0) {
+
+ /* edge distance */
+ BMVert *v_other = BM_edge_other_vert(e_iter, v);
if (bmesh_test_dist_add(v, v_other, dists, dists_prev, mtx)) {
if (BM_elem_flag_test(v_other, BM_ELEM_TAG) == 0) {
BM_elem_flag_enable(v_other, BM_ELEM_TAG);
BLI_LINKSTACK_PUSH(queue_next, v_other);
}
}
- }
- }
- }
-
- /* imaginary edge diagonally across quad */
- if (has_faces) {
- BMIter iter;
- BMLoop *l;
- BM_ITER_ELEM (l, &iter, v, BM_LOOPS_OF_VERT) {
- if ((BM_elem_flag_test(l->f, BM_ELEM_HIDDEN) == 0) && (l->f->len == 4)) {
- BMVert *v_other = l->next->next->v;
- if (bmesh_test_dist_add(v, v_other, dists, dists_prev, mtx)) {
- if (BM_elem_flag_test(v_other, BM_ELEM_TAG) == 0) {
- BM_elem_flag_enable(v_other, BM_ELEM_TAG);
- BLI_LINKSTACK_PUSH(queue_next, v_other);
- }
+ /* face distance */
+ if (e_iter->l) {
+ BMLoop *l_iter_radial, *l_first_radial;
+ /**
+ * imaginary edge diagonally across quad,
+ * \note, this takes advantage of the rules of winding that we
+ * know 2 or more of a verts edges wont reference the same face twice.
+ * Also, if the edge is hidden, the face will be hidden too.
+ */
+ l_iter_radial = l_first_radial = e_iter->l;
+
+ do {
+ if ((l_iter_radial->v == v) &&
+ (l_iter_radial->f->len == 4) &&
+ (BM_elem_flag_test(l_iter_radial->f, BM_ELEM_HIDDEN) == 0))
+ {
+ BMVert *v_other = l_iter_radial->next->next->v;
+ if (bmesh_test_dist_add(v, v_other, dists, dists_prev, mtx)) {
+ if (BM_elem_flag_test(v_other, BM_ELEM_TAG) == 0) {
+ BM_elem_flag_enable(v_other, BM_ELEM_TAG);
+ BLI_LINKSTACK_PUSH(queue_next, v_other);
+ }
+ }
+ }
+ } while ((l_iter_radial = l_iter_radial->radial_next) != l_first_radial);
}
}
- }
+ } while ((e_iter = BM_DISK_EDGE_NEXT(e_iter, v)) != e_first);
}
}
+
/* clear for the next loop */
for (lnk = queue_next; lnk; lnk = lnk->next) {
- BM_elem_flag_disable((BMVert *)lnk->link, BM_ELEM_TAG);
+ BMVert *v = lnk->link;
+ const int i = BM_elem_index_get(v);
+
+ BM_elem_flag_disable(v, BM_ELEM_TAG);
+
+ /* keep in sync, avoid having to do full memcpy each iteration */
+ dists_prev[i] = dists[i];
}
BLI_LINKSTACK_SWAP(queue, queue_next);
@@ -2063,7 +2130,7 @@ static struct TransIslandData *editmesh_islands_info_calc(BMEditMesh *em, int *r
vert_map = MEM_mallocN(sizeof(*vert_map) * bm->totvert, __func__);
/* we shouldn't need this, but with incorrect selection flushing
* its possible we have a selected vertex thats not in a face, for now best not crash in that case. */
- fill_vn_i(vert_map, bm->totvert, -1);
+ copy_vn_i(vert_map, bm->totvert, -1);
BM_mesh_elem_table_ensure(bm, htype);
ele_array = (htype == BM_FACE) ? (void **)bm->ftable : (void **)bm->etable;
@@ -2144,6 +2211,7 @@ static void VertsToTransData(TransInfo *t, TransData *td, TransDataExtension *tx
BMEditMesh *em, BMVert *eve, float *bweight,
struct TransIslandData *v_island)
{
+ float *no, _no[3];
BLI_assert(BM_elem_flag_test(eve, BM_ELEM_HIDDEN) == 0);
td->flag = 0;
@@ -2153,19 +2221,30 @@ static void VertsToTransData(TransInfo *t, TransData *td, TransDataExtension *tx
td->loc = eve->co;
copy_v3_v3(td->iloc, td->loc);
+ if ((t->mode == TFM_SHRINKFATTEN) &&
+ (em->selectmode & SCE_SELECT_FACE) &&
+ BM_elem_flag_test(eve, BM_ELEM_SELECT) &&
+ (BM_vert_normal_update_ex(eve, BM_ELEM_SELECT, _no)))
+ {
+ no = _no;
+ }
+ else {
+ no = eve->no;
+ }
+
if (v_island) {
copy_v3_v3(td->center, v_island->co);
copy_m3_m3(td->axismtx, v_island->axismtx);
}
else if (t->around == V3D_LOCAL) {
copy_v3_v3(td->center, td->loc);
- createSpaceNormal(td->axismtx, eve->no);
+ createSpaceNormal(td->axismtx, no);
}
else {
copy_v3_v3(td->center, td->loc);
/* Setting normals */
- copy_v3_v3(td->axismtx[2], eve->no);
+ copy_v3_v3(td->axismtx[2], no);
td->axismtx[0][0] =
td->axismtx[0][1] =
td->axismtx[0][2] =
@@ -2194,7 +2273,7 @@ static void VertsToTransData(TransInfo *t, TransData *td, TransDataExtension *tx
}
else if (t->mode == TFM_SHRINKFATTEN) {
td->ext = tx;
- tx->isize[0] = BM_vert_calc_shell_factor_ex(eve, BM_ELEM_SELECT);
+ tx->isize[0] = BM_vert_calc_shell_factor_ex(eve, no, BM_ELEM_SELECT);
}
}
@@ -2211,7 +2290,7 @@ static void createTransEditVerts(TransInfo *t)
float mtx[3][3], smtx[3][3], (*defmats)[3][3] = NULL, (*defcos)[3] = NULL;
float *dists = NULL;
int a;
- int propmode = (t->flag & T_PROP_EDIT) ? (t->flag & T_PROP_EDIT_ALL) : 0;
+ const int prop_mode = (t->flag & T_PROP_EDIT) ? (t->flag & T_PROP_EDIT_ALL) : 0;
int mirror = 0;
int cd_vert_bweight_offset = -1;
bool use_topology = (me->editflag & ME_EDIT_MIRROR_TOPO) != 0;
@@ -2251,7 +2330,7 @@ static void createTransEditVerts(TransInfo *t)
cd_vert_bweight_offset = CustomData_get_offset(&bm->vdata, CD_BWEIGHT);
}
- if (propmode) {
+ if (prop_mode) {
unsigned int count = 0;
BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) {
if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) {
@@ -2262,7 +2341,7 @@ static void createTransEditVerts(TransInfo *t)
t->total = count;
/* allocating scratch arrays */
- if (propmode & T_PROP_CONNECTED)
+ if (prop_mode & T_PROP_CONNECTED)
dists = MEM_mallocN(em->bm->totvert * sizeof(float), "scratch nears");
}
else {
@@ -2284,7 +2363,7 @@ static void createTransEditVerts(TransInfo *t)
* matrix inversion still works and we can still moving along the other */
pseudoinverse_m3_m3(smtx, mtx, PSEUDOINVERSE_EPSILON);
- if (propmode & T_PROP_CONNECTED) {
+ if (prop_mode & T_PROP_CONNECTED) {
editmesh_set_connectivity_distance(em->bm, mtx, dists);
}
@@ -2298,7 +2377,7 @@ static void createTransEditVerts(TransInfo *t)
if (modifiers_isCorrectableDeformed(t->scene, t->obedit)) {
/* check if we can use deform matrices for modifier from the
* start up to stack, they are more accurate than quats */
- totleft = editbmesh_get_first_deform_matrices(t->scene, t->obedit, em, &defmats, &defcos);
+ totleft = BKE_crazyspace_get_first_deform_matrices_editbmesh(t->scene, t->obedit, em, &defmats, &defcos);
}
/* if we still have more modifiers, also do crazyspace
@@ -2313,7 +2392,7 @@ static void createTransEditVerts(TransInfo *t)
{
mappedcos = BKE_crazyspace_get_mapped_editverts(t->scene, t->obedit);
quats = MEM_mallocN(em->bm->totvert * sizeof(*quats), "crazy quats");
- BKE_crazyspace_set_quats_editmesh(em, defcos, mappedcos, quats, !propmode);
+ BKE_crazyspace_set_quats_editmesh(em, defcos, mappedcos, quats, !prop_mode);
if (mappedcos)
MEM_freeN(mappedcos);
}
@@ -2338,7 +2417,7 @@ static void createTransEditVerts(TransInfo *t)
BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, a) {
if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) {
- if (propmode || BM_elem_flag_test(eve, BM_ELEM_SELECT)) {
+ if (prop_mode || BM_elem_flag_test(eve, BM_ELEM_SELECT)) {
struct TransIslandData *v_island = (island_info && island_vert_map[a] != -1) ?
&island_info[island_vert_map[a]] : NULL;
float *bweight = (cd_vert_bweight_offset != -1) ? BM_ELEM_CD_GET_VOID_P(eve, cd_vert_bweight_offset) : NULL;
@@ -2351,8 +2430,8 @@ static void createTransEditVerts(TransInfo *t)
if (BM_elem_flag_test(eve, BM_ELEM_SELECT))
tob->flag |= TD_SELECTED;
- if (propmode) {
- if (propmode & T_PROP_CONNECTED) {
+ if (prop_mode) {
+ if (prop_mode & T_PROP_CONNECTED) {
tob->dist = dists[a];
}
else {
@@ -2604,24 +2683,23 @@ void flushTransSeq(TransInfo *t)
/* ********************* UV ****************** */
-static void UVsToTransData(SpaceImage *sima, TransData *td, TransData2D *td2d, float *uv, int selected)
+static void UVsToTransData(
+ const float aspect[2], TransData *td, TransData2D *td2d,
+ float *uv, const float *center, bool selected)
{
- float aspx, aspy;
-
- ED_space_image_get_uv_aspect(sima, &aspx, &aspy);
-
/* uv coords are scaled by aspects. this is needed for rotations and
* proportional editing to be consistent with the stretched uv coords
* that are displayed. this also means that for display and numinput,
- * and when the the uv coords are flushed, these are converted each time */
- td2d->loc[0] = uv[0] * aspx;
- td2d->loc[1] = uv[1] * aspy;
+ * and when the uv coords are flushed, these are converted each time */
+ td2d->loc[0] = uv[0] * aspect[0];
+ td2d->loc[1] = uv[1] * aspect[1];
td2d->loc[2] = 0.0f;
td2d->loc2d = uv;
td->flag = 0;
td->loc = td2d->loc;
- copy_v3_v3(td->center, td->loc);
+ copy_v2_v2(td->center, center ? center : td->loc);
+ td->center[2] = 0.0f;
copy_v3_v3(td->iloc, td->loc);
memset(td->axismtx, 0, sizeof(td->axismtx));
@@ -2648,36 +2726,43 @@ static void createTransUVs(bContext *C, TransInfo *t)
ToolSettings *ts = CTX_data_tool_settings(C);
TransData *td = NULL;
TransData2D *td2d = NULL;
- MTexPoly *tf;
- MLoopUV *luv;
BMEditMesh *em = BKE_editmesh_from_object(t->obedit);
BMFace *efa;
- BMLoop *l;
BMIter iter, liter;
UvElementMap *elementmap = NULL;
BLI_bitmap *island_enabled = NULL;
+ struct { float co[2]; int co_num; } *island_center = NULL;
int count = 0, countsel = 0, count_rejected = 0;
- const bool propmode = (t->flag & T_PROP_EDIT) != 0;
- const bool propconnected = (t->flag & T_PROP_CONNECTED) != 0;
-
+ const bool is_prop_edit = (t->flag & T_PROP_EDIT) != 0;
+ const bool is_prop_connected = (t->flag & T_PROP_CONNECTED) != 0;
+ const bool is_island_center = (t->around == V3D_LOCAL);
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);
- if (!ED_space_image_show_uvedit(sima, t->obedit)) return;
+ if (!ED_space_image_show_uvedit(sima, t->obedit))
+ return;
/* count */
- if (propconnected) {
+ if (is_prop_connected || is_island_center) {
/* create element map with island information */
- if (ts->uv_flag & UV_SYNC_SELECTION) {
- elementmap = BM_uv_element_map_create(em->bm, false, true);
+ const bool use_facesel = (ts->uv_flag & UV_SYNC_SELECTION) == 0;
+ elementmap = BM_uv_element_map_create(em->bm, use_facesel, false, true);
+ if (elementmap == NULL) {
+ return;
}
- else {
- elementmap = BM_uv_element_map_create(em->bm, true, true);
+
+ if (is_prop_connected) {
+ island_enabled = BLI_BITMAP_NEW(elementmap->totalIslands, "TransIslandData(UV Editing)");
+ }
+
+ if (is_island_center) {
+ island_center = MEM_callocN(sizeof(*island_center) * elementmap->totalIslands, __func__);
}
- island_enabled = BLI_BITMAP_NEW(elementmap->totalIslands, "TransIslandData(UV Editing)");
}
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
+ MTexPoly *tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset);
+ BMLoop *l;
if (!uvedit_face_visible_test(scene, ima, efa, tf)) {
BM_elem_flag_disable(efa, BM_ELEM_TAG);
@@ -2689,14 +2774,25 @@ static void createTransUVs(bContext *C, TransInfo *t)
if (uvedit_uv_select_test(scene, l, cd_loop_uv_offset)) {
countsel++;
- if (propconnected) {
+ if (is_prop_connected || island_center) {
UvElement *element = BM_uv_element_get(elementmap, efa, l);
- BLI_BITMAP_ENABLE(island_enabled, element->island);
- }
+ if (is_prop_connected) {
+ BLI_BITMAP_ENABLE(island_enabled, element->island);
+ }
+
+ if (is_island_center) {
+ if (element->flag == false) {
+ MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
+ add_v2_v2(island_center[element->island].co, luv->uv);
+ island_center[element->island].co_num++;
+ element->flag = true;
+ }
+ }
+ }
}
- if (propmode) {
+ if (is_prop_edit) {
count++;
}
}
@@ -2704,13 +2800,19 @@ static void createTransUVs(bContext *C, TransInfo *t)
/* note: in prop mode we need at least 1 selected */
if (countsel == 0) {
- if (propconnected) {
- MEM_freeN(island_enabled);
+ goto finally;
+ }
+
+ if (is_island_center) {
+ int i;
+
+ for (i = 0; i < elementmap->totalIslands; i++) {
+ mul_v2_fl(island_center[i].co, 1.0f / island_center[i].co_num);
+ mul_v2_v2(island_center[i].co, t->aspect);
}
- return;
}
- t->total = (propmode) ? count : countsel;
+ t->total = (is_prop_edit) ? count : countsel;
t->data = MEM_callocN(t->total * sizeof(TransData), "TransObData(UV Editing)");
/* for each 2d uv coord a 3d vector is allocated, so that they can be
* treated just as if they were 3d verts */
@@ -2723,56 +2825,88 @@ static void createTransUVs(bContext *C, TransInfo *t)
td2d = t->data2d;
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
+ BMLoop *l;
+
if (!BM_elem_flag_test(efa, BM_ELEM_TAG))
continue;
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
- if (!propmode && !uvedit_uv_select_test(scene, l, cd_loop_uv_offset))
+ const bool selected = uvedit_uv_select_test(scene, l, cd_loop_uv_offset);
+ MLoopUV *luv;
+ const float *center = NULL;
+
+ if (!is_prop_edit && !selected)
continue;
- if (propconnected) {
+ if (is_prop_connected || is_island_center) {
UvElement *element = BM_uv_element_get(elementmap, efa, l);
- if (!BLI_BITMAP_TEST(island_enabled, element->island)) {
- count_rejected++;
- continue;
+
+ if (is_prop_connected) {
+ if (!BLI_BITMAP_TEST(island_enabled, element->island)) {
+ count_rejected++;
+ continue;
+ }
+ }
+
+ if (is_island_center) {
+ center = island_center[element->island].co;
}
}
+ BM_elem_flag_enable(l, BM_ELEM_TAG);
luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
- UVsToTransData(sima, td++, td2d++, luv->uv, uvedit_uv_select_test(scene, l, cd_loop_uv_offset));
+ UVsToTransData(t->aspect, td++, td2d++, luv->uv, center, selected);
}
}
- if (propconnected) {
+ if (is_prop_connected) {
t->total -= count_rejected;
- BM_uv_element_map_free(elementmap);
- MEM_freeN(island_enabled);
}
if (sima->flag & SI_LIVE_UNWRAP)
ED_uvedit_live_unwrap_begin(t->scene, t->obedit);
+
+
+finally:
+ if (is_prop_connected || is_island_center) {
+ BM_uv_element_map_free(elementmap);
+
+ if (is_prop_connected) {
+ MEM_freeN(island_enabled);
+ }
+
+ if (island_center) {
+ MEM_freeN(island_center);
+ }
+ }
}
void flushTransUVs(TransInfo *t)
{
SpaceImage *sima = t->sa->spacedata.first;
TransData2D *td;
- int a, width, height;
- float aspx, aspy, invx, invy;
+ int a;
+ float aspect_inv[2], size[2];
+ const bool use_pixel_snap = ((sima->flag & SI_PIXELSNAP) && (t->state != TRANS_CANCEL));
+
+ aspect_inv[0] = 1.0f / t->aspect[0];
+ aspect_inv[1] = 1.0f / t->aspect[1];
- ED_space_image_get_uv_aspect(sima, &aspx, &aspy);
- ED_space_image_get_size(sima, &width, &height);
- invx = 1.0f / aspx;
- invy = 1.0f / aspy;
+ if (use_pixel_snap) {
+ int size_i[2];
+ ED_space_image_get_size(sima, &size_i[0], &size_i[1]);
+ size[0] = size_i[0];
+ size[1] = size_i[1];
+ }
/* flush to 2d vector from internally used 3d vector */
for (a = 0, td = t->data2d; a < t->total; a++, td++) {
- td->loc2d[0] = td->loc[0] * invx;
- td->loc2d[1] = td->loc[1] * invy;
+ td->loc2d[0] = td->loc[0] * aspect_inv[0];
+ td->loc2d[1] = td->loc[1] * aspect_inv[1];
- if ((sima->flag & SI_PIXELSNAP) && (t->state != TRANS_CANCEL)) {
- td->loc2d[0] = (float)floor(width * td->loc2d[0] + 0.5f) / width;
- td->loc2d[1] = (float)floor(height * td->loc2d[1] + 0.5f) / height;
+ if (use_pixel_snap) {
+ td->loc2d[0] = roundf(td->loc2d[0] * size[0]) / size[0];
+ td->loc2d[1] = roundf(td->loc2d[1] * size[1]) / size[1];
}
}
}
@@ -2780,44 +2914,45 @@ void flushTransUVs(TransInfo *t)
bool clipUVTransform(TransInfo *t, float vec[2], const bool resize)
{
TransData *td;
- int a, clipx = 1, clipy = 1;
- float aspx, aspy, min[2], max[2];
+ int a;
+ bool clipx = true, clipy = true;
+ float min[2], max[2];
- ED_space_image_get_uv_aspect(t->sa->spacedata.first, &aspx, &aspy);
min[0] = min[1] = 0.0f;
- max[0] = aspx; max[1] = aspy;
+ max[0] = t->aspect[0];
+ max[1] = t->aspect[1];
for (a = 0, td = t->data; a < t->total; a++, td++) {
minmax_v2v2_v2(min, max, td->loc);
}
if (resize) {
- if (min[0] < 0.0f && t->center[0] > 0.0f && t->center[0] < aspx * 0.5f)
+ if (min[0] < 0.0f && t->center[0] > 0.0f && t->center[0] < t->aspect[0] * 0.5f)
vec[0] *= t->center[0] / (t->center[0] - min[0]);
- else if (max[0] > aspx && t->center[0] < aspx)
- vec[0] *= (t->center[0] - aspx) / (t->center[0] - max[0]);
+ else if (max[0] > t->aspect[0] && t->center[0] < t->aspect[0])
+ vec[0] *= (t->center[0] - t->aspect[0]) / (t->center[0] - max[0]);
else
clipx = 0;
- if (min[1] < 0.0f && t->center[1] > 0.0f && t->center[1] < aspy * 0.5f)
+ if (min[1] < 0.0f && t->center[1] > 0.0f && t->center[1] < t->aspect[1] * 0.5f)
vec[1] *= t->center[1] / (t->center[1] - min[1]);
- else if (max[1] > aspy && t->center[1] < aspy)
- vec[1] *= (t->center[1] - aspy) / (t->center[1] - max[1]);
+ else if (max[1] > t->aspect[1] && t->center[1] < t->aspect[1])
+ vec[1] *= (t->center[1] - t->aspect[1]) / (t->center[1] - max[1]);
else
clipy = 0;
}
else {
if (min[0] < 0.0f)
vec[0] -= min[0];
- else if (max[0] > aspx)
- vec[0] -= max[0] - aspx;
+ else if (max[0] > t->aspect[0])
+ vec[0] -= max[0] - t->aspect[0];
else
clipx = 0;
if (min[1] < 0.0f)
vec[1] -= min[1];
- else if (max[1] > aspy)
- vec[1] -= max[1] - aspy;
+ else if (max[1] > t->aspect[1])
+ vec[1] -= max[1] - t->aspect[1];
else
clipy = 0;
}
@@ -2829,9 +2964,6 @@ void clipUVData(TransInfo *t)
{
TransData *td = NULL;
int a;
- float aspx, aspy;
-
- ED_space_image_get_uv_aspect(t->sa->spacedata.first, &aspx, &aspy);
for (a = 0, td = t->data; a < t->total; a++, td++) {
if (td->flag & TD_NOACTION)
@@ -2840,8 +2972,8 @@ void clipUVData(TransInfo *t)
if ((td->flag & TD_SKIP) || (!td->loc))
continue;
- td->loc[0] = min_ff(max_ff(0.0f, td->loc[0]), aspx);
- td->loc[1] = min_ff(max_ff(0.0f, td->loc[1]), aspy);
+ td->loc[0] = min_ff(max_ff(0.0f, td->loc[0]), t->aspect[0]);
+ td->loc[1] = min_ff(max_ff(0.0f, td->loc[1]), t->aspect[1]);
}
}
@@ -3115,7 +3247,7 @@ static void posttrans_gpd_clean(bGPdata *gpd)
bGPDframe *gpf, *gpfn;
bool is_double = false;
- BLI_sortlist_r(&gpl->frames, &is_double, gpf_cmp_frame);
+ BLI_listbase_sort_r(&gpl->frames, gpf_cmp_frame, &is_double);
if (is_double) {
for (gpf = gpl->frames.first; gpf; gpf = gpfn) {
@@ -3142,7 +3274,7 @@ static void posttrans_mask_clean(Mask *mask)
MaskLayerShape *masklay_shape, *masklay_shape_next;
bool is_double = false;
- BLI_sortlist_r(&masklay->splines_shapes, &is_double, masklay_shape_cmp_frame);
+ BLI_listbase_sort_r(&masklay->splines_shapes, masklay_shape_cmp_frame, &is_double);
if (is_double) {
for (masklay_shape = masklay->splines_shapes.first; masklay_shape; masklay_shape = masklay_shape_next) {
@@ -3164,7 +3296,7 @@ static void posttrans_mask_clean(Mask *mask)
/* Called during special_aftertrans_update to make sure selected keyframes replace
* any other keyframes which may reside on that frame (that is not selected).
*/
-static void posttrans_fcurve_clean(FCurve *fcu, const short use_handle)
+static void posttrans_fcurve_clean(FCurve *fcu, const bool use_handle)
{
float *selcache; /* cache for frame numbers of selected frames (fcu->totvert*sizeof(float)) */
int len, index, i; /* number of frames in cache, item index */
@@ -3186,7 +3318,7 @@ static void posttrans_fcurve_clean(FCurve *fcu, const short use_handle)
for (i = 0; i < fcu->totvert; i++) {
BezTriple *bezt = &fcu->bezt[i];
- if (BEZSELECTED(bezt)) {
+ if (BEZT_ISSEL_ANY(bezt)) {
selcache[index] = bezt->vec[1][0];
index++;
len++;
@@ -3200,7 +3332,7 @@ static void posttrans_fcurve_clean(FCurve *fcu, const short use_handle)
for (i = fcu->totvert - 1; i >= 0; i--) {
BezTriple *bezt = &fcu->bezt[i];
- if (BEZSELECTED(bezt) == 0) {
+ if (BEZT_ISSEL_ANY(bezt) == 0) {
/* check beztriple should be removed according to cache */
for (index = 0; index < len; index++) {
if (IS_EQF(bezt->vec[1][0], selcache[index])) {
@@ -3258,76 +3390,90 @@ static void posttrans_action_clean(bAnimContext *ac, bAction *act)
/* ----------------------------- */
/* fully select selected beztriples, but only include if it's on the right side of cfra */
-static int count_fcurve_keys(FCurve *fcu, char side, float cfra)
+static int count_fcurve_keys(FCurve *fcu, char side, float cfra, bool is_prop_edit)
{
BezTriple *bezt;
- int i, count = 0;
+ int i, count = 0, count_all = 0;
if (ELEM(NULL, fcu, fcu->bezt))
return count;
/* only include points that occur on the right side of cfra */
for (i = 0, bezt = fcu->bezt; i < fcu->totvert; i++, bezt++) {
- if (bezt->f2 & SELECT) {
+ if (FrameOnMouseSide(side, bezt->vec[1][0], cfra)) {
/* no need to adjust the handle selection since they are assumed
* selected (like graph editor with SIPO_NOHANDLES) */
- if (FrameOnMouseSide(side, bezt->vec[1][0], cfra)) {
- count += 1;
- }
+ if (bezt->f2 & SELECT)
+ count++;
+
+ count_all++;
}
}
- return count;
+ if (is_prop_edit && count > 0)
+ return count_all;
+ else return count;
}
/* fully select selected beztriples, but only include if it's on the right side of cfra */
-static int count_gplayer_frames(bGPDlayer *gpl, char side, float cfra)
+static int count_gplayer_frames(bGPDlayer *gpl, char side, float cfra, bool is_prop_edit)
{
bGPDframe *gpf;
- int count = 0;
+ int count = 0, count_all = 0;
if (gpl == NULL)
return count;
/* only include points that occur on the right side of cfra */
for (gpf = gpl->frames.first; gpf; gpf = gpf->next) {
- if (gpf->flag & GP_FRAME_SELECT) {
- if (FrameOnMouseSide(side, (float)gpf->framenum, cfra))
+ if (FrameOnMouseSide(side, (float)gpf->framenum, cfra)) {
+ if (gpf->flag & GP_FRAME_SELECT)
count++;
+ count_all++;
}
}
- return count;
+ if (is_prop_edit && count > 0)
+ return count_all;
+ else
+ return count;
}
/* fully select selected beztriples, but only include if it's on the right side of cfra */
-static int count_masklayer_frames(MaskLayer *masklay, char side, float cfra)
+static int count_masklayer_frames(MaskLayer *masklay, char side, float cfra, bool is_prop_edit)
{
MaskLayerShape *masklayer_shape;
- int count = 0;
+ int count = 0, count_all = 0;
if (masklay == NULL)
return count;
/* only include points that occur on the right side of cfra */
for (masklayer_shape = masklay->splines_shapes.first; masklayer_shape; masklayer_shape = masklayer_shape->next) {
- if (masklayer_shape->flag & MASK_SHAPE_SELECT) {
- if (FrameOnMouseSide(side, (float)masklayer_shape->frame, cfra))
+ if (FrameOnMouseSide(side, (float)masklayer_shape->frame, cfra)) {
+ if (masklayer_shape->flag & MASK_SHAPE_SELECT)
count++;
+ count_all++;
}
}
- return count;
+ if (is_prop_edit && count > 0)
+ return count_all;
+ else
+ return count;
}
/* This function assigns the information to transdata */
-static void TimeToTransData(TransData *td, float *time, AnimData *adt)
+static void TimeToTransData(TransData *td, float *time, AnimData *adt, float ypos)
{
/* memory is calloc'ed, so that should zero everything nicely for us */
td->val = time;
td->ival = *(time);
+ td->center[0] = td->ival;
+ td->center[1] = ypos;
+
/* store the AnimData where this keyframe exists as a keyframe of the
* active action as td->extra.
*/
@@ -3341,7 +3487,7 @@ static void TimeToTransData(TransData *td, float *time, AnimData *adt)
* The 'side' argument is needed for the extend mode. 'B' = both sides, 'R'/'L' mean only data
* on the named side are used.
*/
-static TransData *ActionFCurveToTransData(TransData *td, TransData2D **td2dv, FCurve *fcu, AnimData *adt, char side, float cfra)
+static TransData *ActionFCurveToTransData(TransData *td, TransData2D **td2dv, FCurve *fcu, AnimData *adt, char side, float cfra, bool is_prop_edit, float ypos)
{
BezTriple *bezt;
TransData2D *td2d = *td2dv;
@@ -3352,11 +3498,14 @@ static TransData *ActionFCurveToTransData(TransData *td, TransData2D **td2dv, FC
for (i = 0, bezt = fcu->bezt; i < fcu->totvert; i++, bezt++) {
/* only add selected keyframes (for now, proportional edit is not enabled) */
- if (bezt->f2 & SELECT) { /* note this MUST match count_fcurve_keys(), so can't use BEZSELECTED() macro */
+ if (is_prop_edit || (bezt->f2 & SELECT)) { /* note this MUST match count_fcurve_keys(), so can't use BEZT_ISSEL_ANY() macro */
/* only add if on the right 'side' of the current frame */
if (FrameOnMouseSide(side, bezt->vec[1][0], cfra)) {
- TimeToTransData(td, bezt->vec[1], adt);
+ TimeToTransData(td, bezt->vec[1], adt, ypos);
+ if (bezt->f2 & SELECT)
+ td->flag |= TD_SELECTED;
+
/*set flags to move handles as necessary*/
td->flag |= TD_MOVEHANDLE1 | TD_MOVEHANDLE2;
td2d->h1 = bezt->vec[0];
@@ -3407,19 +3556,22 @@ void flushTransIntFrameActionData(TransInfo *t)
* The 'side' argument is needed for the extend mode. 'B' = both sides, 'R'/'L' mean only data
* on the named side are used.
*/
-static int GPLayerToTransData(TransData *td, tGPFtransdata *tfd, bGPDlayer *gpl, char side, float cfra)
+static int GPLayerToTransData(TransData *td, tGPFtransdata *tfd, bGPDlayer *gpl, char side, float cfra, bool is_prop_edit, float ypos)
{
bGPDframe *gpf;
int count = 0;
/* check for select frames on right side of current frame */
for (gpf = gpl->frames.first; gpf; gpf = gpf->next) {
- if (gpf->flag & GP_FRAME_SELECT) {
+ if (is_prop_edit || (gpf->flag & GP_FRAME_SELECT)) {
if (FrameOnMouseSide(side, (float)gpf->framenum, cfra)) {
/* memory is calloc'ed, so that should zero everything nicely for us */
td->val = &tfd->val;
td->ival = (float)gpf->framenum;
+ td->center[0] = td->ival;
+ td->center[1] = ypos;
+
tfd->val = (float)gpf->framenum;
tfd->sdata = &gpf->framenum;
@@ -3435,19 +3587,22 @@ static int GPLayerToTransData(TransData *td, tGPFtransdata *tfd, bGPDlayer *gpl,
}
/* refer to comment above #GPLayerToTransData, this is the same but for masks */
-static int MaskLayerToTransData(TransData *td, tGPFtransdata *tfd, MaskLayer *masklay, char side, float cfra)
+static int MaskLayerToTransData(TransData *td, tGPFtransdata *tfd, MaskLayer *masklay, char side, float cfra, bool is_prop_edit, float ypos)
{
MaskLayerShape *masklay_shape;
int count = 0;
/* check for select frames on right side of current frame */
for (masklay_shape = masklay->splines_shapes.first; masklay_shape; masklay_shape = masklay_shape->next) {
- if (masklay_shape->flag & MASK_SHAPE_SELECT) {
+ if (is_prop_edit || (masklay_shape->flag & MASK_SHAPE_SELECT)) {
if (FrameOnMouseSide(side, (float)masklay_shape->frame, cfra)) {
/* memory is calloc'ed, so that should zero everything nicely for us */
td->val = &tfd->val;
td->ival = (float)masklay_shape->frame;
+ td->center[0] = td->ival;
+ td->center[1] = ypos;
+
tfd->val = (float)masklay_shape->frame;
tfd->sdata = &masklay_shape->frame;
@@ -3469,15 +3624,25 @@ static void createTransActionData(bContext *C, TransInfo *t)
TransData *td = NULL;
TransData2D *td2d = NULL;
tGPFtransdata *tfd = NULL;
-
+
+ rcti *mask = &t->ar->v2d.mask;
+ rctf *datamask = &t->ar->v2d.cur;
+
+ float xsize = BLI_rctf_size_x(datamask);
+ float ysize = BLI_rctf_size_y(datamask);
+ float xmask = BLI_rcti_size_x(mask);
+ float ymask = BLI_rcti_size_y(mask);
+
bAnimContext ac;
ListBase anim_data = {NULL, NULL};
bAnimListElem *ale;
int filter;
-
+ const bool is_prop_edit = (t->flag & T_PROP_EDIT) != 0;
+
int count = 0;
float cfra;
-
+ float ypos = 1.0f / ((ysize / xsize) * (xmask / ymask)) * BLI_rctf_cent_y(&t->ar->v2d.cur);
+
/* determine what type of data we are operating on */
if (ANIM_animdata_get_context(C, &ac) == 0)
return;
@@ -3505,7 +3670,7 @@ static void createTransActionData(bContext *C, TransInfo *t)
/* loop 1: fully select ipo-keys and count how many BezTriples are selected */
for (ale = anim_data.first; ale; ale = ale->next) {
AnimData *adt = ANIM_nla_mapping_get(&ac, ale);
-
+ int adt_count = 0;
/* convert current-frame to action-time (slightly less accurate, especially under
* higher scaling ratios, but is faster than converting all points)
*/
@@ -3514,14 +3679,19 @@ static void createTransActionData(bContext *C, TransInfo *t)
else
cfra = (float)CFRA;
- if (ale->type == ANIMTYPE_FCURVE)
- count += count_fcurve_keys(ale->key_data, t->frame_side, cfra);
+ if (ELEM(ale->type, ANIMTYPE_FCURVE, ANIMTYPE_NLACURVE))
+ adt_count = count_fcurve_keys(ale->key_data, t->frame_side, cfra, is_prop_edit);
else if (ale->type == ANIMTYPE_GPLAYER)
- count += count_gplayer_frames(ale->data, t->frame_side, cfra);
+ adt_count = count_gplayer_frames(ale->data, t->frame_side, cfra, is_prop_edit);
else if (ale->type == ANIMTYPE_MASKLAYER)
- count += count_masklayer_frames(ale->data, t->frame_side, cfra);
+ adt_count = count_masklayer_frames(ale->data, t->frame_side, cfra, is_prop_edit);
else
BLI_assert(0);
+
+ if (adt_count > 0) {
+ count += adt_count;
+ ale->tag = true;
+ }
}
/* stop if trying to build list if nothing selected */
@@ -3558,11 +3728,22 @@ static void createTransActionData(bContext *C, TransInfo *t)
/* loop 2: build transdata array */
for (ale = anim_data.first; ale; ale = ale->next) {
+ AnimData *adt;
+
+ if (is_prop_edit && !ale->tag)
+ continue;
+
+ adt = ANIM_nla_mapping_get(&ac, ale);
+ if (adt)
+ cfra = BKE_nla_tweakedit_remap(adt, (float)CFRA, NLATIME_CONVERT_UNMAP);
+ else
+ cfra = (float)CFRA;
+
if (ale->type == ANIMTYPE_GPLAYER) {
bGPDlayer *gpl = (bGPDlayer *)ale->data;
int i;
- i = GPLayerToTransData(td, tfd, gpl, t->frame_side, cfra);
+ i = GPLayerToTransData(td, tfd, gpl, t->frame_side, cfra, is_prop_edit, ypos);
td += i;
tfd += i;
}
@@ -3570,7 +3751,7 @@ static void createTransActionData(bContext *C, TransInfo *t)
MaskLayer *masklay = (MaskLayer *)ale->data;
int i;
- i = MaskLayerToTransData(td, tfd, masklay, t->frame_side, cfra);
+ i = MaskLayerToTransData(td, tfd, masklay, t->frame_side, cfra, is_prop_edit, ypos);
td += i;
tfd += i;
}
@@ -3578,15 +3759,7 @@ static void createTransActionData(bContext *C, TransInfo *t)
AnimData *adt = ANIM_nla_mapping_get(&ac, ale);
FCurve *fcu = (FCurve *)ale->key_data;
- /* convert current-frame to action-time (slightly less accurate, especially under
- * higher scaling ratios, but is faster than converting all points)
- */
- if (adt)
- cfra = BKE_nla_tweakedit_remap(adt, (float)CFRA, NLATIME_CONVERT_UNMAP);
- else
- cfra = (float)CFRA;
-
- td = ActionFCurveToTransData(td, &td2d, fcu, adt, t->frame_side, cfra);
+ td = ActionFCurveToTransData(td, &td2d, fcu, adt, t->frame_side, cfra, is_prop_edit, ypos);
}
}
@@ -3615,6 +3788,109 @@ static void createTransActionData(bContext *C, TransInfo *t)
*((float *)(t->customData) + 1) = max;
}
+ /* calculate distances for proportional editing */
+ if (is_prop_edit) {
+ td = t->data;
+
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ AnimData *adt;
+
+ /* F-Curve may not have any keyframes */
+ if (!ale->tag)
+ continue;
+
+ adt = ANIM_nla_mapping_get(&ac, ale);
+ if (adt)
+ cfra = BKE_nla_tweakedit_remap(adt, (float)CFRA, NLATIME_CONVERT_UNMAP);
+ else
+ cfra = (float)CFRA;
+
+ if (ale->type == ANIMTYPE_GPLAYER) {
+ bGPDlayer *gpl = (bGPDlayer *)ale->data;
+ bGPDframe *gpf;
+
+ for (gpf = gpl->frames.first; gpf; gpf = gpf->next) {
+ if (gpf->flag & GP_FRAME_SELECT) {
+ td->dist = td->rdist = 0.0f;
+ }
+ else {
+ bGPDframe *gpf_iter;
+ int min = INT_MAX;
+ for (gpf_iter = gpl->frames.first; gpf_iter; gpf_iter = gpf->next) {
+ if (gpf_iter->flag & GP_FRAME_SELECT) {
+ if (FrameOnMouseSide(t->frame_side, (float)gpf_iter->framenum, cfra)) {
+ int val = abs(gpf->framenum - gpf_iter->framenum);
+ if (val < min) {
+ min = val;
+ }
+ }
+ }
+ }
+ td->dist = td->rdist = min;
+ }
+ td++;
+ }
+ }
+ else if (ale->type == ANIMTYPE_MASKLAYER) {
+ MaskLayer *masklay = (MaskLayer *)ale->data;
+ MaskLayerShape *masklay_shape;
+
+ for (masklay_shape = masklay->splines_shapes.first; masklay_shape; masklay_shape = masklay_shape->next) {
+ if (FrameOnMouseSide(t->frame_side, (float)masklay_shape->frame, cfra)) {
+ if (masklay_shape->flag & MASK_SHAPE_SELECT) {
+ td->dist = td->rdist = 0.0f;
+ }
+ else {
+ MaskLayerShape *masklay_iter;
+ int min = INT_MAX;
+ for (masklay_iter = masklay->splines_shapes.first; masklay_iter; masklay_iter = masklay_iter->next) {
+ if (masklay_iter->flag & MASK_SHAPE_SELECT) {
+ if (FrameOnMouseSide(t->frame_side, (float)masklay_iter->frame, cfra)) {
+ int val = abs(masklay_shape->frame - masklay_iter->frame);
+ if (val < min) {
+ min = val;
+ }
+ }
+ }
+ }
+ td->dist = td->rdist = min;
+ }
+ td++;
+ }
+ }
+ }
+ else {
+ FCurve *fcu = (FCurve *)ale->key_data;
+ BezTriple *bezt;
+ int i;
+
+ for (i = 0, bezt = fcu->bezt; i < fcu->totvert; i++, bezt++) {
+ if (FrameOnMouseSide(t->frame_side, bezt->vec[1][0], cfra)) {
+ if (bezt->f2 & SELECT) {
+ td->dist = td->rdist = 0.0f;
+ }
+ else {
+ BezTriple *bezt_iter;
+ int j;
+ float min = FLT_MAX;
+ for (j = 0, bezt_iter = fcu->bezt; j < fcu->totvert; j++, bezt_iter++) {
+ if (bezt_iter->f2 & SELECT) {
+ if (FrameOnMouseSide(t->frame_side, (float)bezt_iter->vec[1][0], cfra)) {
+ float val = fabs(bezt->vec[1][0] - bezt_iter->vec[1][0]);
+ if (val < min)
+ min = val;
+ }
+ }
+ }
+ td->dist = td->rdist = min;
+ }
+ td++;
+ }
+ }
+ }
+ }
+ }
+
/* cleanup temp list */
ANIM_animdata_freelist(&anim_data);
}
@@ -3623,6 +3899,7 @@ static void createTransActionData(bContext *C, TransInfo *t)
typedef struct TransDataGraph {
float unit_scale;
+ float offset;
} TransDataGraph;
/* Helper function for createTransGraphEditData, which is responsible for associating
@@ -3631,7 +3908,7 @@ typedef struct TransDataGraph {
static void bezt_to_transdata(TransData *td, TransData2D *td2d, TransDataGraph *tdg,
AnimData *adt, BezTriple *bezt,
int bi, bool selected, bool ishandle, bool intvals,
- float mtx[3][3], float smtx[3][3], float unit_scale)
+ float mtx[3][3], float smtx[3][3], float unit_scale, float offset)
{
float *loc = bezt->vec[bi];
const float *cent = bezt->vec[1];
@@ -3645,26 +3922,26 @@ static void bezt_to_transdata(TransData *td, TransData2D *td2d, TransDataGraph *
if (adt) {
td2d->loc[0] = BKE_nla_tweakedit_remap(adt, loc[0], NLATIME_CONVERT_MAP);
- td2d->loc[1] = loc[1] * unit_scale;
+ td2d->loc[1] = (loc[1] + offset) * unit_scale;
td2d->loc[2] = 0.0f;
td2d->loc2d = loc;
td->loc = td2d->loc;
td->center[0] = BKE_nla_tweakedit_remap(adt, cent[0], NLATIME_CONVERT_MAP);
- td->center[1] = cent[1] * unit_scale;
+ td->center[1] = (cent[1] + offset) * unit_scale;
td->center[2] = 0.0f;
copy_v3_v3(td->iloc, td->loc);
}
else {
td2d->loc[0] = loc[0];
- td2d->loc[1] = loc[1] * unit_scale;
+ td2d->loc[1] = (loc[1] + offset) * unit_scale;
td2d->loc[2] = 0.0f;
td2d->loc2d = loc;
td->loc = td2d->loc;
copy_v3_v3(td->center, cent);
- td->center[1] *= unit_scale;
+ td->center[1] = (td->center[1] + offset) * unit_scale;
copy_v3_v3(td->iloc, td->loc);
}
@@ -3704,6 +3981,7 @@ static void bezt_to_transdata(TransData *td, TransData2D *td2d, TransDataGraph *
copy_m3_m3(td->smtx, smtx);
tdg->unit_scale = unit_scale;
+ tdg->offset = offset;
}
static bool graph_edit_is_translation_mode(TransInfo *t)
@@ -3716,6 +3994,29 @@ static bool graph_edit_use_local_center(TransInfo *t)
return (t->around == V3D_LOCAL) && !graph_edit_is_translation_mode(t);
}
+
+static void graph_key_shortest_dist(TransInfo *t, FCurve *fcu, TransData *td_start, TransData *td, int cfra, bool use_handle)
+{
+ int j = 0;
+ TransData *td_iter = td_start;
+
+ td->dist = FLT_MAX;
+ for (; j < fcu->totvert; j++) {
+ BezTriple *bezt = fcu->bezt + j;
+ if (FrameOnMouseSide(t->frame_side, bezt->vec[1][0], cfra)) {
+ const bool sel2 = (bezt->f2 & SELECT) != 0;
+ const bool sel1 = use_handle ? (bezt->f1 & SELECT) != 0 : sel2;
+ const bool sel3 = use_handle ? (bezt->f3 & SELECT) != 0 : sel2;
+
+ if (sel1 || sel2 || sel3) {
+ td->dist = td->rdist = min_ff(td->dist, fabs(td_iter->center[0] - td->center[0]));
+ }
+
+ td_iter += 3;
+ }
+ }
+}
+
static void createTransGraphEditData(bContext *C, TransInfo *t)
{
SpaceIpo *sipo = (SpaceIpo *)t->sa->spacedata.first;
@@ -3734,11 +4035,11 @@ static void createTransGraphEditData(bContext *C, TransInfo *t)
BezTriple *bezt;
int count = 0, i;
- float cfra;
float mtx[3][3], smtx[3][3];
const bool is_translation_mode = graph_edit_is_translation_mode(t);
const bool use_handle = !(sipo->flag & SIPO_NOHANDLES);
const bool use_local_center = graph_edit_use_local_center(t);
+ const bool is_prop_edit = (t->flag & T_PROP_EDIT) != 0;
short anim_map_flag = ANIM_UNITCONV_ONLYSEL | ANIM_UNITCONV_SELVERTS;
/* determine what type of data we are operating on */
@@ -3769,7 +4070,14 @@ static void createTransGraphEditData(bContext *C, TransInfo *t)
for (ale = anim_data.first; ale; ale = ale->next) {
AnimData *adt = ANIM_nla_mapping_get(&ac, ale);
FCurve *fcu = (FCurve *)ale->key_data;
-
+ float cfra;
+ int curvecount = 0;
+ bool selected = false;
+
+ /* F-Curve may not have any keyframes */
+ if (fcu->bezt == NULL)
+ continue;
+
/* convert current-frame to action-time (slightly less accurate, especially under
* higher scaling ratios, but is faster than converting all points)
*/
@@ -3777,48 +4085,44 @@ static void createTransGraphEditData(bContext *C, TransInfo *t)
cfra = BKE_nla_tweakedit_remap(adt, (float)CFRA, NLATIME_CONVERT_UNMAP);
else
cfra = (float)CFRA;
-
- /* F-Curve may not have any keyframes */
- if (fcu->bezt == NULL)
- continue;
-
+
/* only include BezTriples whose 'keyframe' occurs on the same side of the current frame as mouse */
for (i = 0, bezt = fcu->bezt; i < fcu->totvert; i++, bezt++) {
if (FrameOnMouseSide(t->frame_side, bezt->vec[1][0], cfra)) {
- const bool sel2 = bezt->f2 & SELECT;
- const bool sel1 = use_handle ? bezt->f1 & SELECT : sel2;
- const bool sel3 = use_handle ? bezt->f3 & SELECT : sel2;
+ const bool sel2 = (bezt->f2 & SELECT) != 0;
+ const bool sel1 = use_handle ? (bezt->f1 & SELECT) != 0 : sel2;
+ const bool sel3 = use_handle ? (bezt->f3 & SELECT) != 0 : sel2;
+
+ if (is_prop_edit) {
+ curvecount += 3;
+ if (sel2 || sel1 || sel3)
+ selected = true;
+ }
+ else {
+ if (!is_translation_mode || !(sel2)) {
+ if (sel1) {
+ count++;
+ }
- if (is_translation_mode) {
- /* for 'normal' pivots - just include anything that is selected.
- * this works a bit differently in translation modes */
- if (sel2) {
- count++;
- }
- else {
- if (sel1) count++;
- if (sel3) count++;
+ if (sel3) {
+ count++;
+ }
}
- }
- else if (use_local_center) {
- /* for local-pivot we only need to count the number of selected handles only,
- * so that centerpoints don't get moved wrong
- */
- if (bezt->ipo == BEZT_IPO_BEZ) {
- if (sel1) count++;
- if (sel3) count++;
+
+ /* only include main vert if selected */
+ if (sel2 && !use_local_center) {
+ count++;
}
- /* else if (sel2) count++; // TODO: could this cause problems? */
- /* - yes this causes problems, because no td is created for the center point */
- }
- else {
- /* for 'normal' pivots - just include anything that is selected */
- if (sel1) count++;
- if (sel2) count++;
- if (sel3) count++;
}
}
}
+
+ if (is_prop_edit) {
+ if (selected) {
+ count += curvecount;
+ ale->tag = true;
+ }
+ }
}
/* stop if trying to build list if nothing selected */
@@ -3864,8 +4168,13 @@ static void createTransGraphEditData(bContext *C, TransInfo *t)
for (ale = anim_data.first; ale; ale = ale->next) {
AnimData *adt = ANIM_nla_mapping_get(&ac, ale);
FCurve *fcu = (FCurve *)ale->key_data;
- bool intvals = (fcu->flag & FCURVE_INT_VALUES);
- float unit_scale;
+ bool intvals = (fcu->flag & FCURVE_INT_VALUES) != 0;
+ float unit_scale, offset;
+ float cfra;
+
+ /* F-Curve may not have any keyframes */
+ if (fcu->bezt == NULL || (is_prop_edit && ale->tag == 0))
+ continue;
/* convert current-frame to action-time (slightly less accurate, especially under
* higher scaling ratios, but is faster than converting all points)
@@ -3874,83 +4183,148 @@ static void createTransGraphEditData(bContext *C, TransInfo *t)
cfra = BKE_nla_tweakedit_remap(adt, (float)CFRA, NLATIME_CONVERT_UNMAP);
else
cfra = (float)CFRA;
-
- /* F-Curve may not have any keyframes */
- if (fcu->bezt == NULL)
- continue;
-
- unit_scale = ANIM_unit_mapping_get_factor(ac.scene, ale->id, ale->key_data, anim_map_flag);
+
+ unit_scale = ANIM_unit_mapping_get_factor(ac.scene, ale->id, ale->key_data, anim_map_flag, &offset);
/* only include BezTriples whose 'keyframe' occurs on the same side of the current frame as mouse (if applicable) */
for (i = 0, bezt = fcu->bezt; i < fcu->totvert; i++, bezt++) {
if (FrameOnMouseSide(t->frame_side, bezt->vec[1][0], cfra)) {
- const bool sel2 = bezt->f2 & SELECT;
- const bool sel1 = use_handle ? bezt->f1 & SELECT : sel2;
- const bool sel3 = use_handle ? bezt->f3 & SELECT : sel2;
+ const bool sel2 = (bezt->f2 & SELECT) != 0;
+ const bool sel1 = use_handle ? (bezt->f1 & SELECT) != 0 : sel2;
+ const bool sel3 = use_handle ? (bezt->f3 & SELECT) != 0 : sel2;
TransDataCurveHandleFlags *hdata = NULL;
/* short h1=1, h2=1; */ /* UNUSED */
- /* only include handles if selected, irrespective of the interpolation modes.
- * also, only treat handles specially if the center point isn't selected.
- */
- if (!is_translation_mode || !(sel2)) {
- if (sel1) {
- hdata = initTransDataCurveHandles(td, bezt);
- bezt_to_transdata(td++, td2d++, tdg++, adt, bezt, 0, sel1, true, intvals, mtx, smtx, unit_scale);
+ if (is_prop_edit) {
+ bool is_sel = (sel2 || sel1 || sel3);
+ /* we always select all handles for proportional editing if central handle is selected */
+ initTransDataCurveHandles(td, bezt);
+ bezt_to_transdata(td++, td2d++, tdg++, adt, bezt, 0, is_sel, true, intvals, mtx, smtx, unit_scale, offset);
+ initTransDataCurveHandles(td, bezt);
+ bezt_to_transdata(td++, td2d++, tdg++, adt, bezt, 1, is_sel, false, intvals, mtx, smtx, unit_scale, offset);
+ initTransDataCurveHandles(td, bezt);
+ bezt_to_transdata(td++, td2d++, tdg++, adt, bezt, 2, is_sel, true, intvals, mtx, smtx, unit_scale, offset);
+ }
+ else {
+ /* only include handles if selected, irrespective of the interpolation modes.
+ * also, only treat handles specially if the center point isn't selected.
+ */
+ if (!is_translation_mode || !(sel2)) {
+ if (sel1) {
+ hdata = initTransDataCurveHandles(td, bezt);
+ bezt_to_transdata(td++, td2d++, tdg++, adt, bezt, 0, sel1, true, intvals, mtx, smtx, unit_scale, offset);
+ }
+ else {
+ /* h1 = 0; */ /* UNUSED */
+ }
+
+ if (sel3) {
+ if (hdata == NULL)
+ hdata = initTransDataCurveHandles(td, bezt);
+ bezt_to_transdata(td++, td2d++, tdg++, adt, bezt, 2, sel3, true, intvals, mtx, smtx, unit_scale, offset);
+ }
+ else {
+ /* h2 = 0; */ /* UNUSED */
+ }
}
- else {
- /* h1 = 0; */ /* UNUSED */
+
+ /* only include main vert if selected */
+ if (sel2 && !use_local_center) {
+ /* move handles relative to center */
+ if (is_translation_mode) {
+ if (sel1) td->flag |= TD_MOVEHANDLE1;
+ if (sel3) td->flag |= TD_MOVEHANDLE2;
+ }
+
+ /* if handles were not selected, store their selection status */
+ if (!(sel1) || !(sel3)) {
+ if (hdata == NULL)
+ hdata = initTransDataCurveHandles(td, bezt);
+ }
+
+ bezt_to_transdata(td++, td2d++, tdg++, adt, bezt, 1, sel2, false, intvals, mtx, smtx, unit_scale, offset);
+
}
-
- if (sel3) {
- if (hdata == NULL)
- hdata = initTransDataCurveHandles(td, bezt);
- bezt_to_transdata(td++, td2d++, tdg++, adt, bezt, 2, sel3, true, intvals, mtx, smtx, unit_scale);
+ /* special hack (must be done after initTransDataCurveHandles(), as that stores handle settings to restore...):
+ * - Check if we've got entire BezTriple selected and we're scaling/rotating that point,
+ * then check if we're using auto-handles.
+ * - If so, change them auto-handles to aligned handles so that handles get affected too
+ */
+ if (ELEM(bezt->h1, HD_AUTO, HD_AUTO_ANIM) &&
+ ELEM(bezt->h2, HD_AUTO, HD_AUTO_ANIM) &&
+ ELEM(t->mode, TFM_ROTATION, TFM_RESIZE))
+ {
+ if (hdata && (sel1) && (sel3)) {
+ bezt->h1 = HD_ALIGN;
+ bezt->h2 = HD_ALIGN;
+ }
+ }
+ }
+ }
+ }
+
+ /* Sets handles based on the selection */
+ testhandles_fcurve(fcu, use_handle);
+ }
+
+ if (is_prop_edit) {
+ /* loop 2: build transdata arrays */
+ td = t->data;
+
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ AnimData *adt = ANIM_nla_mapping_get(&ac, ale);
+ FCurve *fcu = (FCurve *)ale->key_data;
+ TransData *td_start = td;
+ float cfra;
+
+ /* F-Curve may not have any keyframes */
+ if (fcu->bezt == NULL || (ale->tag == 0))
+ continue;
+
+ /* convert current-frame to action-time (slightly less accurate, especially under
+ * higher scaling ratios, but is faster than converting all points)
+ */
+ if (adt)
+ cfra = BKE_nla_tweakedit_remap(adt, (float)CFRA, NLATIME_CONVERT_UNMAP);
+ else
+ cfra = (float)CFRA;
+
+ /* only include BezTriples whose 'keyframe' occurs on the same side of the current frame as mouse (if applicable) */
+ for (i = 0, bezt = fcu->bezt; i < fcu->totvert; i++, bezt++) {
+ if (FrameOnMouseSide(t->frame_side, bezt->vec[1][0], cfra)) {
+ const bool sel2 = (bezt->f2 & SELECT) != 0;
+ const bool sel1 = use_handle ? (bezt->f1 & SELECT) != 0 : sel2;
+ const bool sel3 = use_handle ? (bezt->f3 & SELECT) != 0 : sel2;
+
+ if (sel1 || sel2) {
+ td->dist = td->rdist = 0.0f;
}
else {
- /* h2 = 0; */ /* UNUSED */
+ graph_key_shortest_dist(t, fcu, td_start, td, cfra, use_handle);
}
- }
-
- /* only include main vert if selected */
- if (sel2 && !use_local_center) {
- /* move handles relative to center */
- if (is_translation_mode) {
- if (sel1) td->flag |= TD_MOVEHANDLE1;
- if (sel3) td->flag |= TD_MOVEHANDLE2;
+ td++;
+
+ if (sel2) {
+ td->dist = td->rdist = 0.0f;
}
-
- /* if handles were not selected, store their selection status */
- if (!(sel1) || !(sel3)) {
- if (hdata == NULL)
- hdata = initTransDataCurveHandles(td, bezt);
+ else {
+ graph_key_shortest_dist(t, fcu, td_start, td, cfra, use_handle);
}
-
- bezt_to_transdata(td++, td2d++, tdg++, adt, bezt, 1, sel2, false, intvals, mtx, smtx, unit_scale);
-
- }
- /* special hack (must be done after initTransDataCurveHandles(), as that stores handle settings to restore...):
- * - Check if we've got entire BezTriple selected and we're scaling/rotating that point,
- * then check if we're using auto-handles.
- * - If so, change them auto-handles to aligned handles so that handles get affected too
- */
- if (ELEM(bezt->h1, HD_AUTO, HD_AUTO_ANIM) &&
- ELEM(bezt->h2, HD_AUTO, HD_AUTO_ANIM) &&
- ELEM(t->mode, TFM_ROTATION, TFM_RESIZE))
- {
- if (hdata && (sel1) && (sel3)) {
- bezt->h1 = HD_ALIGN;
- bezt->h2 = HD_ALIGN;
+ td++;
+
+ if (sel3 || sel2) {
+ td->dist = td->rdist = 0.0f;
+ }
+ else {
+ graph_key_shortest_dist(t, fcu, td_start, td, cfra, use_handle);
}
+ td++;
}
}
}
-
- /* Sets handles based on the selection */
- testhandles_fcurve(fcu, use_handle);
}
-
+
/* cleanup temp list */
ANIM_animdata_freelist(&anim_data);
}
@@ -4130,7 +4504,7 @@ void remake_graph_transdata(TransInfo *t, ListBase *anim_data)
{
SpaceIpo *sipo = (SpaceIpo *)t->sa->spacedata.first;
bAnimListElem *ale;
- const short use_handle = !(sipo->flag & SIPO_NOHANDLES);
+ const bool use_handle = (sipo->flag & SIPO_NOHANDLES) == 0;
/* sort and reassign verts */
for (ale = anim_data->first; ale; ale = ale->next) {
@@ -4234,7 +4608,7 @@ void flushTransGraphData(TransInfo *t)
if (td->flag & TD_INTVALUES)
td2d->loc2d[1] = floorf(td2d->loc[1] + 0.5f);
else
- td2d->loc2d[1] = td2d->loc[1] * inv_unit_scale;
+ td2d->loc2d[1] = td2d->loc[1] * inv_unit_scale - tdg->offset;
if ((td->flag & TD_MOVEHANDLE1) && td2d->h1) {
td2d->h1[0] = td2d->ih1[0] + td->loc[0] - td->iloc[0];
@@ -4493,10 +4867,47 @@ static int SeqToTransData_Recursive(TransInfo *t, ListBase *seqbase, TransData *
}
}
}
-
return tot;
}
+
+static void SeqTransDataBounds(TransInfo *t, ListBase *seqbase, TransSeq *ts)
+{
+ Sequence *seq;
+ int recursive, count, flag;
+ int max = INT32_MIN, min = INT32_MAX;
+
+ for (seq = seqbase->first; seq; seq = seq->next) {
+
+ /* just to get the flag since there are corner cases where this isn't totally obvious */
+ SeqTransInfo(t, seq, &recursive, &count, &flag);
+
+ /* use 'flag' which is derived from seq->flag but modified for special cases */
+ if (flag & SELECT) {
+ if (flag & (SEQ_LEFTSEL | SEQ_RIGHTSEL)) {
+ if (flag & SEQ_LEFTSEL) {
+ min = min_ii(seq->startdisp, min);
+ max = max_ii(seq->startdisp, max);
+ }
+ if (flag & SEQ_RIGHTSEL) {
+ min = min_ii(seq->enddisp, min);
+ max = max_ii(seq->enddisp, max);
+ }
+ }
+ else {
+ min = min_ii(seq->startdisp, min);
+ max = max_ii(seq->enddisp, max);
+ }
+ }
+ }
+
+ if (ts) {
+ ts->max = max;
+ ts->min = min;
+ }
+}
+
+
static void freeSeqData(TransInfo *t)
{
Editing *ed = BKE_sequencer_editing_get(t->scene, false);
@@ -4659,6 +5070,8 @@ static void freeSeqData(TransInfo *t)
}
if ((t->customData != NULL) && (t->flag & T_FREE_CUSTOMDATA)) {
+ TransSeq *ts = t->customData;
+ MEM_freeN(ts->tdseq);
MEM_freeN(t->customData);
t->customData = NULL;
}
@@ -4678,6 +5091,8 @@ static void createTransSeqData(bContext *C, TransInfo *t)
TransData *td = NULL;
TransData2D *td2d = NULL;
TransDataSeq *tdsq = NULL;
+ TransSeq *ts = NULL;
+ int xmouse;
int count = 0;
@@ -4688,12 +5103,11 @@ static void createTransSeqData(bContext *C, TransInfo *t)
t->customFree = freeSeqData;
+ xmouse = (int)UI_view2d_region_to_view_x(v2d, t->imval[0]);
+
/* which side of the current frame should be allowed */
if (t->mode == TFM_TIME_EXTEND) {
/* only side on which mouse is gets transformed */
- float xmouse, ymouse;
-
- UI_view2d_region_to_view(v2d, t->imval[0], t->imval[1], &xmouse, &ymouse);
t->frame_side = (xmouse > CFRA) ? 'R' : 'L';
}
else {
@@ -4733,15 +5147,19 @@ static void createTransSeqData(bContext *C, TransInfo *t)
return;
}
+ t->customData = ts = MEM_mallocN(sizeof(TransSeq), "transseq");
td = t->data = MEM_callocN(t->total * sizeof(TransData), "TransSeq TransData");
td2d = t->data2d = MEM_callocN(t->total * sizeof(TransData2D), "TransSeq TransData2D");
- tdsq = t->customData = MEM_callocN(t->total * sizeof(TransDataSeq), "TransSeq TransDataSeq");
+ ts->tdseq = tdsq = MEM_callocN(t->total * sizeof(TransDataSeq), "TransSeq TransDataSeq");
t->flag |= T_FREE_CUSTOMDATA;
-
-
/* loop 2: build transdata array */
SeqToTransData_Recursive(t, ed->seqbasep, td, td2d, tdsq);
+ SeqTransDataBounds(t, ed->seqbasep, ts);
+
+ /* set the snap mode based on how close the mouse is at the end/start points */
+ if (abs(xmouse - ts->max) > abs(xmouse - ts->min))
+ ts->snap_left = true;
#undef XXX_DURIAN_ANIM_TX_HACK
}
@@ -4769,7 +5187,6 @@ static bool constraints_list_needinv(TransInfo *t, ListBase *list)
/* (affirmative) returns for specific constraints here... */
/* constraints that require this regardless */
if (ELEM(con->type,
- CONSTRAINT_TYPE_CHILDOF,
CONSTRAINT_TYPE_FOLLOWPATH,
CONSTRAINT_TYPE_CLAMPTO,
CONSTRAINT_TYPE_OBJECTSOLVER,
@@ -4779,7 +5196,14 @@ static bool constraints_list_needinv(TransInfo *t, ListBase *list)
}
/* constraints that require this only under special conditions */
- if (con->type == CONSTRAINT_TYPE_ROTLIKE) {
+ if (con->type == CONSTRAINT_TYPE_CHILDOF) {
+ /* ChildOf constraint only works when using all location components, see T42256. */
+ bChildOfConstraint *data = (bChildOfConstraint *)con->data;
+
+ if ((data->flag & CHILDOF_LOCX) && (data->flag & CHILDOF_LOCY) && (data->flag & CHILDOF_LOCZ))
+ return true;
+ }
+ else if (con->type == CONSTRAINT_TYPE_ROTLIKE) {
/* CopyRot constraint only does this when rotating, and offset is on */
bRotateLikeConstraint *data = (bRotateLikeConstraint *)con->data;
@@ -4997,7 +5421,9 @@ static void set_trans_object_base_flags(TransInfo *t)
}
/* all recalc flags get flushed to all layers, so a layer flip later on works fine */
+#ifdef WITH_LEGACY_DEPSGRAPH
DAG_scene_flush_update(G.main, t->scene, -1, 0);
+#endif
/* and we store them temporal in base (only used for transform code) */
/* this because after doing updates, the object->recalc is cleared */
@@ -5074,7 +5500,9 @@ static int count_proportional_objects(TransInfo *t)
/* all recalc flags get flushed to all layers, so a layer flip later on works fine */
DAG_scene_relations_update(G.main, t->scene);
+#ifdef WITH_LEGACY_DEPSGRAPH
DAG_scene_flush_update(G.main, t->scene, -1, 0);
+#endif
/* and we store them temporal in base (only used for transform code) */
/* this because after doing updates, the object->recalc is cleared */
@@ -5271,7 +5699,7 @@ void autokeyframe_pose_cb_func(bContext *C, Scene *scene, View3D *v3d, Object *o
/* only if bone name matches too...
* NOTE: this will do constraints too, but those are ok to do here too?
*/
- if (pchanName && strcmp(pchanName, pchan->name) == 0)
+ if (pchanName && STREQ(pchanName, pchan->name))
insert_keyframe(reports, id, act, ((fcu->grp) ? (fcu->grp->name) : (NULL)), fcu->rna_path, fcu->array_index, cfra, flag);
if (pchanName) MEM_freeN(pchanName);
@@ -5514,6 +5942,12 @@ void special_aftertrans_update(bContext *C, TransInfo *t)
* during cleanup - psy-fi */
freeEdgeSlideTempFaces(sld);
}
+ else if (t->mode == TFM_VERT_SLIDE) {
+ /* as above */
+ VertSlideData *sld = t->customData;
+ projectVertSlideData(t, true);
+ freeVertSlideTempFaces(sld);
+ }
if (t->obedit->type == OB_MESH) {
special_aftertrans_update__mesh(C, t);
@@ -5526,12 +5960,21 @@ void special_aftertrans_update(bContext *C, TransInfo *t)
sld->perc = 0.0;
projectEdgeSlideData(t, false);
}
+ else if (t->mode == TFM_VERT_SLIDE) {
+ VertSlideData *sld = t->customData;
+
+ sld->perc = 0.0;
+ projectVertSlideData(t, false);
+ }
}
}
}
- if (t->spacetype == SPACE_SEQ) {
+ if (t->options & CTX_GPENCIL_STROKES) {
+ /* pass */
+ }
+ else if (t->spacetype == SPACE_SEQ) {
/* freeSeqData in transform_conversions.c does this
* keep here so the else at the end wont run... */
@@ -5714,7 +6157,7 @@ void special_aftertrans_update(bContext *C, TransInfo *t)
else if (t->spacetype == SPACE_IPO) {
SpaceIpo *sipo = (SpaceIpo *)t->sa->spacedata.first;
bAnimContext ac;
- const short use_handle = !(sipo->flag & SIPO_NOHANDLES);
+ const bool use_handle = (sipo->flag & SIPO_NOHANDLES) == 0;
/* initialize relevant anim-context 'context' data */
if (ANIM_animdata_get_context(C, &ac) == 0)
@@ -5941,7 +6384,7 @@ static void createTransObject(bContext *C, TransInfo *t)
TransData *td = NULL;
TransDataExtension *tx;
- int propmode = t->flag & T_PROP_EDIT;
+ const bool is_prop_edit = (t->flag & T_PROP_EDIT) != 0;
set_trans_object_base_flags(t);
@@ -5954,7 +6397,7 @@ static void createTransObject(bContext *C, TransInfo *t)
return;
}
- if (propmode) {
+ if (is_prop_edit) {
t->total += count_proportional_objects(t);
}
@@ -5987,7 +6430,7 @@ static void createTransObject(bContext *C, TransInfo *t)
}
CTX_DATA_END;
- if (propmode) {
+ if (is_prop_edit) {
View3D *v3d = t->view;
Base *base;
@@ -6141,22 +6584,22 @@ typedef struct TransDataTracking {
static void markerToTransDataInit(TransData *td, TransData2D *td2d, TransDataTracking *tdt,
MovieTrackingTrack *track, MovieTrackingMarker *marker,
- int area, float loc[2], float rel[2], const float off[2], float aspx, float aspy)
+ int area, float loc[2], float rel[2], const float off[2], const float aspect[2])
{
int anchor = area == TRACK_AREA_POINT && off;
tdt->mode = transDataTracking_ModeTracks;
if (anchor) {
- td2d->loc[0] = rel[0] * aspx; /* hold original location */
- td2d->loc[1] = rel[1] * aspy;
+ td2d->loc[0] = rel[0] * aspect[0]; /* hold original location */
+ td2d->loc[1] = rel[1] * aspect[1];
tdt->loc = loc;
td2d->loc2d = loc; /* current location */
}
else {
- td2d->loc[0] = loc[0] * aspx; /* hold original location */
- td2d->loc[1] = loc[1] * aspy;
+ td2d->loc[0] = loc[0] * aspect[0]; /* hold original location */
+ td2d->loc[1] = loc[1] * aspect[1];
td2d->loc2d = loc; /* current location */
}
@@ -6171,8 +6614,8 @@ static void markerToTransDataInit(TransData *td, TransData2D *td2d, TransDataTra
if (rel) {
if (!anchor) {
- td2d->loc[0] += rel[0] * aspx;
- td2d->loc[1] += rel[1] * aspy;
+ td2d->loc[0] += rel[0] * aspect[0];
+ td2d->loc[1] += rel[1] * aspect[1];
}
copy_v2_v2(tdt->srelative, rel);
@@ -6187,8 +6630,8 @@ static void markerToTransDataInit(TransData *td, TransData2D *td2d, TransDataTra
//copy_v3_v3(td->center, td->loc);
td->flag |= TD_INDIVIDUAL_SCALE;
- td->center[0] = marker->pos[0] * aspx;
- td->center[1] = marker->pos[1] * aspy;
+ td->center[0] = marker->pos[0] * aspect[0];
+ td->center[1] = marker->pos[1] * aspect[1];
memset(td->axismtx, 0, sizeof(td->axismtx));
td->axismtx[2][2] = 1.0f;
@@ -6203,8 +6646,9 @@ static void markerToTransDataInit(TransData *td, TransData2D *td2d, TransDataTra
unit_m3(td->smtx);
}
-static void trackToTransData(const int framenr, TransData *td, TransData2D *td2d,
- TransDataTracking *tdt, MovieTrackingTrack *track, float aspx, float aspy)
+static void trackToTransData(
+ const int framenr, TransData *td, TransData2D *td2d,
+ TransDataTracking *tdt, MovieTrackingTrack *track, const float aspect[2])
{
MovieTrackingMarker *marker = BKE_tracking_marker_ensure(track, framenr);
@@ -6212,11 +6656,11 @@ static void trackToTransData(const int framenr, TransData *td, TransData2D *td2d
marker->flag &= ~(MARKER_DISABLED | MARKER_TRACKED);
markerToTransDataInit(td++, td2d++, tdt++, track, marker, TRACK_AREA_POINT,
- track->offset, marker->pos, track->offset, aspx, aspy);
+ track->offset, marker->pos, track->offset, aspect);
if (track->flag & SELECT) {
markerToTransDataInit(td++, td2d++, tdt++, track, marker, TRACK_AREA_POINT,
- marker->pos, NULL, NULL, aspx, aspy);
+ marker->pos, NULL, NULL, aspect);
}
if (track->pat_flag & SELECT) {
@@ -6224,28 +6668,28 @@ static void trackToTransData(const int framenr, TransData *td, TransData2D *td2d
for (a = 0; a < 4; a++) {
markerToTransDataInit(td++, td2d++, tdt++, track, marker, TRACK_AREA_PAT,
- marker->pattern_corners[a], marker->pos, NULL, aspx, aspy);
+ marker->pattern_corners[a], marker->pos, NULL, aspect);
}
}
if (track->search_flag & SELECT) {
markerToTransDataInit(td++, td2d++, tdt++, track, marker, TRACK_AREA_SEARCH,
- marker->search_min, marker->pos, NULL, aspx, aspy);
+ marker->search_min, marker->pos, NULL, aspect);
markerToTransDataInit(td++, td2d++, tdt++, track, marker, TRACK_AREA_SEARCH,
- marker->search_max, marker->pos, NULL, aspx, aspy);
+ marker->search_max, marker->pos, NULL, aspect);
}
}
static void planeMarkerToTransDataInit(TransData *td, TransData2D *td2d, TransDataTracking *tdt,
MovieTrackingPlaneTrack *plane_track, float corner[2],
- float aspx, float aspy)
+ const float aspect[2])
{
tdt->mode = transDataTracking_ModePlaneTracks;
tdt->plane_track = plane_track;
- td2d->loc[0] = corner[0] * aspx; /* hold original location */
- td2d->loc[1] = corner[1] * aspy;
+ td2d->loc[0] = corner[0] * aspect[0]; /* hold original location */
+ td2d->loc[1] = corner[1] * aspect[1];
td2d->loc2d = corner; /* current location */
td2d->loc[2] = 0.0f;
@@ -6270,7 +6714,7 @@ static void planeMarkerToTransDataInit(TransData *td, TransData2D *td2d, TransDa
static void planeTrackToTransData(const int framenr, TransData *td, TransData2D *td2d,
TransDataTracking *tdt, MovieTrackingPlaneTrack *plane_track,
- float aspx, float aspy)
+ const float aspect[2])
{
MovieTrackingPlaneMarker *plane_marker = BKE_tracking_plane_marker_ensure(plane_track, framenr);
int i;
@@ -6279,7 +6723,7 @@ static void planeTrackToTransData(const int framenr, TransData *td, TransData2D
plane_marker->flag &= ~PLANE_MARKER_TRACKED;
for (i = 0; i < 4; i++) {
- planeMarkerToTransDataInit(td++, td2d++, tdt++, plane_track, plane_marker->corners[i], aspx, aspy);
+ planeMarkerToTransDataInit(td++, td2d++, tdt++, plane_track, plane_marker->corners[i], aspect);
}
}
@@ -6308,7 +6752,6 @@ static void createTransTrackingTracksData(bContext *C, TransInfo *t)
MovieTrackingPlaneTrack *plane_track;
TransDataTracking *tdt;
int framenr = ED_space_clip_get_clip_frame_number(sc);
- float aspx, aspy;
/* count */
t->total = 0;
@@ -6343,8 +6786,6 @@ static void createTransTrackingTracksData(bContext *C, TransInfo *t)
if (t->total == 0)
return;
- ED_space_clip_get_aspect_dimension_aware(sc, &aspx, &aspy);
-
td = t->data = MEM_callocN(t->total * sizeof(TransData), "TransTracking TransData");
td2d = t->data2d = MEM_callocN(t->total * sizeof(TransData2D), "TransTracking TransData2D");
tdt = t->customData = MEM_callocN(t->total * sizeof(TransDataTracking), "TransTracking TransDataTracking");
@@ -6355,7 +6796,7 @@ static void createTransTrackingTracksData(bContext *C, TransInfo *t)
track = tracksbase->first;
while (track) {
if (TRACK_VIEW_SELECTED(sc, track) && (track->flag & TRACK_LOCKED) == 0) {
- trackToTransData(framenr, td, td2d, tdt, track, aspx, aspy);
+ trackToTransData(framenr, td, td2d, tdt, track, t->aspect);
/* offset */
td++;
@@ -6389,7 +6830,7 @@ static void createTransTrackingTracksData(bContext *C, TransInfo *t)
plane_track = plane_track->next)
{
if (PLANE_TRACK_VIEW_SELECTED(plane_track)) {
- planeTrackToTransData(framenr, td, td2d, tdt, plane_track, aspx, aspy);
+ planeTrackToTransData(framenr, td, td2d, tdt, plane_track, t->aspect);
td += 4;
td2d += 4;
tdt += 4;
@@ -6601,14 +7042,10 @@ static void cancelTransTracking(TransInfo *t)
void flushTransTracking(TransInfo *t)
{
- SpaceClip *sc = t->sa->spacedata.first;
TransData *td;
TransData2D *td2d;
TransDataTracking *tdt;
int a;
- float aspx, aspy;
-
- ED_space_clip_get_aspect_dimension_aware(sc, &aspx, &aspy);
if (t->state == TRANS_CANCEL)
cancelTransTracking(t);
@@ -6622,8 +7059,8 @@ void flushTransTracking(TransInfo *t)
continue;
}
- loc2d[0] = td2d->loc[0] / aspx;
- loc2d[1] = td2d->loc[1] / aspy;
+ loc2d[0] = td2d->loc[0] / t->aspect[0];
+ loc2d[1] = td2d->loc[1] / t->aspect[1];
if (t->flag & T_ALT_TRANSFORM) {
if (t->mode == TFM_RESIZE) {
@@ -6665,8 +7102,8 @@ void flushTransTracking(TransInfo *t)
td2d->loc2d[tdt->coord] = tdt->prev_pos[tdt->coord] + td2d->loc[1] * tdt->scale;
}
else if (tdt->mode == transDataTracking_ModePlaneTracks) {
- td2d->loc2d[0] = td2d->loc[0] / aspx;
- td2d->loc2d[1] = td2d->loc[1] / aspy;
+ td2d->loc2d[0] = td2d->loc[0] / t->aspect[0];
+ td2d->loc2d[1] = td2d->loc[1] / t->aspect[1];
}
}
}
@@ -6744,9 +7181,10 @@ static void MaskHandleToTransData(MaskSplinePoint *point, eMaskWhichHandle which
}
}
-static void MaskPointToTransData(Scene *scene, MaskSplinePoint *point,
- TransData *td, TransData2D *td2d, TransDataMasking *tdm,
- const int propmode, const float asp[2])
+static void MaskPointToTransData(
+ Scene *scene, MaskSplinePoint *point,
+ TransData *td, TransData2D *td2d, TransDataMasking *tdm,
+ const bool is_prop_edit, const float asp[2])
{
BezTriple *bezt = &point->bezt;
const bool is_sel_point = MASKPOINT_ISSEL_KNOT(point);
@@ -6756,7 +7194,7 @@ static void MaskPointToTransData(Scene *scene, MaskSplinePoint *point,
BKE_mask_point_parent_matrix_get(point, CFRA, parent_matrix);
invert_m3_m3(parent_inverse_matrix, parent_matrix);
- if (propmode || is_sel_point) {
+ if (is_prop_edit || is_sel_point) {
int i;
tdm->point = point;
@@ -6769,7 +7207,7 @@ static void MaskPointToTransData(Scene *scene, MaskSplinePoint *point,
/* CV coords are scaled by aspects. this is needed for rotations and
* proportional editing to be consistent with the stretched CV coords
* that are displayed. this also means that for display and numinput,
- * and when the the CV coords are flushed, these are converted each time */
+ * and when the CV coords are flushed, these are converted each time */
mul_v2_m3v2(td2d->loc, parent_matrix, bezt->vec[i]);
td2d->loc[0] *= asp[0];
td2d->loc[1] *= asp[1];
@@ -6876,7 +7314,7 @@ static void createTransMaskingData(bContext *C, TransInfo *t)
TransData2D *td2d = NULL;
TransDataMasking *tdm = NULL;
int count = 0, countsel = 0;
- int propmode = t->flag & T_PROP_EDIT;
+ const bool is_prop_edit = (t->flag & T_PROP_EDIT);
float asp[2];
t->total = 0;
@@ -6926,7 +7364,7 @@ static void createTransMaskingData(bContext *C, TransInfo *t)
}
}
- if (propmode)
+ if (is_prop_edit)
count += 3;
}
}
@@ -6939,7 +7377,7 @@ static void createTransMaskingData(bContext *C, TransInfo *t)
ED_mask_get_aspect(t->sa, t->ar, &asp[0], &asp[1]);
- t->total = (propmode) ? count : countsel;
+ t->total = (is_prop_edit) ? count : countsel;
td = t->data = MEM_callocN(t->total * sizeof(TransData), "TransObData(Mask Editing)");
/* for each 2d uv coord a 3d vector is allocated, so that they can be
* treated just as if they were 3d verts */
@@ -6962,10 +7400,10 @@ static void createTransMaskingData(bContext *C, TransInfo *t)
for (i = 0; i < spline->tot_point; i++) {
MaskSplinePoint *point = &spline->points[i];
- if (propmode || MASKPOINT_ISSEL_ANY(point)) {
- MaskPointToTransData(scene, point, td, td2d, tdm, propmode, asp);
+ if (is_prop_edit || MASKPOINT_ISSEL_ANY(point)) {
+ MaskPointToTransData(scene, point, td, td2d, tdm, is_prop_edit, asp);
- if (propmode || MASKPOINT_ISSEL_KNOT(point)) {
+ if (is_prop_edit || MASKPOINT_ISSEL_KNOT(point)) {
td += 3;
td2d += 3;
tdm += 3;
@@ -7198,6 +7636,246 @@ void flushTransPaintCurve(TransInfo *t)
}
+static void createTransGPencil(bContext *C, TransInfo *t)
+{
+ bGPdata *gpd = ED_gpencil_data_get_active(C);
+ bGPDlayer *gpl;
+ TransData *td = NULL;
+ float mtx[3][3], smtx[3][3];
+
+ const Scene *scene = CTX_data_scene(C);
+ const int cfra = CFRA;
+
+ const bool is_prop_edit = (t->flag & T_PROP_EDIT) != 0;
+ const bool is_prop_edit_connected = (t->flag & T_PROP_CONNECTED) != 0;
+
+
+ /* == Grease Pencil Strokes to Transform Data ==
+ * Grease Pencil stroke points can be a mixture of 2D (screen-space),
+ * or 3D coordinates. However, they're always saved as 3D points.
+ * For now, we just do these without creating TransData2D for the 2D
+ * strokes. This may cause issues in future though.
+ */
+ t->total = 0;
+
+ if (gpd == NULL)
+ return;
+
+ /* First Pass: Count the number of datapoints required for the strokes,
+ * (and additional info about the configuration - e.g. 2D/3D?)
+ */
+ for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ /* only editable and visible layers are considered */
+ if ((gpl->flag & (GP_LAYER_HIDE | GP_LAYER_LOCKED)) == 0 &&
+ (gpl->actframe != NULL))
+ {
+ bGPDframe *gpf = gpl->actframe;
+ bGPDstroke *gps;
+
+ for (gps = gpf->strokes.first; gps; gps = gps->next) {
+ /* skip strokes that are invalid for current view */
+ if (ED_gpencil_stroke_can_use(C, gps) == false) {
+ continue;
+ }
+
+ if (is_prop_edit) {
+ /* Proportional Editing... */
+ if (is_prop_edit_connected) {
+ /* connected only - so only if selected */
+ if (gps->flag & GP_STROKE_SELECT)
+ t->total += gps->totpoints;
+ }
+ else {
+ /* everything goes - connection status doesn't matter */
+ t->total += gps->totpoints;
+ }
+ }
+ else {
+ /* only selected stroke points are considered */
+ if (gps->flag & GP_STROKE_SELECT) {
+ bGPDspoint *pt;
+ int i;
+
+ // TODO: 2D vs 3D?
+ for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
+ if (pt->flag & GP_SPOINT_SELECT)
+ t->total++;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /* Stop trying if nothing selected */
+ if (t->total == 0) {
+ return;
+ }
+
+ /* Allocate memory for data */
+ t->data = MEM_callocN(t->total * sizeof(TransData), "TransData(GPencil)");
+ td = t->data;
+
+ unit_m3(smtx);
+ unit_m3(mtx);
+
+ /* Second Pass: Build transdata array */
+ for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ /* only editable and visible layers are considered */
+ if ((gpl->flag & (GP_LAYER_HIDE | GP_LAYER_LOCKED)) == 0 &&
+ (gpl->actframe != NULL))
+ {
+ bGPDframe *gpf = gpl->actframe;
+ bGPDstroke *gps;
+
+ /* Make a new frame to work on if the layer's frame and the current scene frame don't match up
+ * - This is useful when animating as it saves that "uh-oh" moment when you realize you've
+ * spent too much time editing the wrong frame...
+ */
+ // XXX: should this be allowed when framelock is enabled?
+ if (gpf->framenum != cfra) {
+ bGPDframe *new_frame = gpencil_frame_duplicate(gpf);
+ bGPDframe *gf;
+ bool found = false;
+
+ /* Find frame to insert it before */
+ for (gf = gpf->next; gf; gf = gf->next) {
+ if (gf->framenum > cfra) {
+ /* Add it here */
+ BLI_insertlinkbefore(&gpl->frames, gf, new_frame);
+
+ found = true;
+ break;
+ }
+ else if (gf->framenum == cfra) {
+ /* This only happens when we're editing with framelock on...
+ * - Delete the new frame and don't do anything else here...
+ */
+ //printf("GP Frame convert to TransData - Copy aborted for frame %d -> %d\n", gpf->framenum, gf->framenum);
+ free_gpencil_strokes(new_frame);
+ MEM_freeN(new_frame);
+ new_frame = NULL;
+
+ found = true;
+ break;
+ }
+ }
+
+ if (found == false) {
+ /* Add new frame to the end */
+ BLI_addtail(&gpl->frames, new_frame);
+ }
+
+ /* Edit the new frame instead, if it did get created + added */
+ if (new_frame) {
+ // TODO: tag this one as being "newly created" so that we can remove it if the edit is cancelled
+ new_frame->framenum = cfra;
+
+ gpf = new_frame;
+ }
+ }
+
+ /* Loop over strokes, adding TransData for points as needed... */
+ for (gps = gpf->strokes.first; gps; gps = gps->next) {
+ TransData *head = td;
+ TransData *tail = td;
+ bool stroke_ok;
+
+ /* skip strokes that are invalid for current view */
+ if (ED_gpencil_stroke_can_use(C, gps) == false) {
+ continue;
+ }
+
+ /* What we need to include depends on proportional editing settings... */
+ if (is_prop_edit) {
+ if (is_prop_edit_connected) {
+ /* A) "Connected" - Only those in selected strokes */
+ stroke_ok = (gps->flag & GP_STROKE_SELECT) != 0;
+ }
+ else {
+ /* B) All points, always */
+ stroke_ok = true;
+ }
+ }
+ else {
+ /* C) Only selected points in selected strokes */
+ stroke_ok = (gps->flag & GP_STROKE_SELECT) != 0;
+ }
+
+ /* Do stroke... */
+ if (stroke_ok && gps->totpoints) {
+ bGPDspoint *pt;
+ int i;
+
+#if 0 /* XXX: this isn't needed anymore; cannot calculate center this way or is_prop_edit breaks */
+ const float ninv = 1.0f / gps->totpoints;
+ float center[3] = {0.0f};
+
+ /* compute midpoint of stroke */
+ for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
+ madd_v3_v3v3fl(center, center, &pt->x, ninv);
+ }
+#endif
+
+ /* add all necessary points... */
+ for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
+ bool point_ok;
+
+ /* include point? */
+ if (is_prop_edit) {
+ /* Always all points in strokes that get included */
+ point_ok = true;
+ }
+ else {
+ /* Only selected points in selected strokes */
+ point_ok = (pt->flag & GP_SPOINT_SELECT) != 0;
+ }
+
+ /* do point... */
+ if (point_ok) {
+ copy_v3_v3(td->iloc, &pt->x);
+ copy_v3_v3(td->center, &pt->x); // XXX: what about t->around == local?
+
+ td->loc = &pt->x;
+
+ td->flag = 0;
+
+ if (pt->flag & GP_SPOINT_SELECT)
+ td->flag |= TD_SELECTED;
+
+ /* for other transform modes (e.g. shrink-fatten), need to additional data */
+ if (t->mode == TFM_GPENCIL_SHRINKFATTEN) {
+ td->val = &pt->pressure;
+ td->ival = pt->pressure;
+ }
+
+ /* configure 2D points so that they don't play up... */
+ if (gps->flag & (GP_STROKE_2DSPACE | GP_STROKE_2DIMAGE)) {
+ td->protectflag = OB_LOCK_LOCZ | OB_LOCK_ROTZ | OB_LOCK_SCALEZ;
+ // XXX: matrices may need to be different?
+ }
+
+ copy_m3_m3(td->smtx, smtx);
+ copy_m3_m3(td->mtx, mtx);
+ unit_m3(td->axismtx); // XXX?
+
+ td++;
+ tail++;
+ }
+ }
+
+ /* March over these points, and calculate the proportional editing distances */
+ if (is_prop_edit && (head != tail)) {
+ /* XXX: for now, we are similar enough that this works... */
+ calc_distanceCurveVerts(head, tail - 1);
+ }
+ }
+ }
+ }
+ }
+}
+
+
void createTransData(bContext *C, TransInfo *t)
{
Scene *scene = t->scene;
@@ -7218,6 +7896,16 @@ void createTransData(bContext *C, TransInfo *t)
sort_trans_data_dist(t);
}
}
+ else if (t->options & CTX_GPENCIL_STROKES) {
+ t->flag |= T_POINTS; // XXX...
+ createTransGPencil(C, t);
+
+ if (t->data && (t->flag & T_PROP_EDIT)) {
+ sort_trans_data(t); // makes selected become first in array
+ set_prop_dist(t, 1);
+ sort_trans_data_dist(t);
+ }
+ }
else if (t->spacetype == SPACE_IMAGE) {
t->flag |= T_POINTS | T_2D_EDIT;
if (t->options & CTX_MASK) {
@@ -7246,6 +7934,12 @@ void createTransData(bContext *C, TransInfo *t)
else if (t->spacetype == SPACE_ACTION) {
t->flag |= T_POINTS | T_2D_EDIT;
createTransActionData(C, t);
+
+ if (t->data && (t->flag & T_PROP_EDIT)) {
+ sort_trans_data(t); // makes selected become first in array
+ //set_prop_dist(t, false); /* don't do that, distance has been set in createTransActionData already */
+ sort_trans_data_dist(t);
+ }
}
else if (t->spacetype == SPACE_NLA) {
t->flag |= T_POINTS | T_2D_EDIT;
@@ -7259,13 +7953,12 @@ void createTransData(bContext *C, TransInfo *t)
else if (t->spacetype == SPACE_IPO) {
t->flag |= T_POINTS | T_2D_EDIT;
createTransGraphEditData(C, t);
-#if 0
+
if (t->data && (t->flag & T_PROP_EDIT)) {
sort_trans_data(t); // makes selected become first in array
- set_prop_dist(t, 1);
+ set_prop_dist(t, false); /* don't do that, distance has been set in createTransGraphEditData already */
sort_trans_data_dist(t);
}
-#endif
}
else if (t->spacetype == SPACE_NODE) {
t->flag |= T_POINTS | T_2D_EDIT;
diff --git a/source/blender/editors/transform/transform_generics.c b/source/blender/editors/transform/transform_generics.c
index 24dc6f6e74b..dc541c6da42 100644
--- a/source/blender/editors/transform/transform_generics.c
+++ b/source/blender/editors/transform/transform_generics.c
@@ -57,7 +57,7 @@
#include "BLI_rand.h"
#include "BLI_utildefines.h"
-#include "BLF_translation.h"
+#include "BLT_translation.h"
#include "RNA_access.h"
@@ -80,6 +80,7 @@
#include "BKE_editmesh.h"
#include "BKE_tracking.h"
#include "BKE_mask.h"
+#include "BKE_utildefines.h"
#include "ED_anim_api.h"
#include "ED_armature.h"
@@ -87,6 +88,7 @@
#include "ED_keyframing.h"
#include "ED_markers.h"
#include "ED_mesh.h"
+#include "ED_object.h"
#include "ED_particle.h"
#include "ED_screen_types.h"
#include "ED_space_api.h"
@@ -109,21 +111,7 @@
void getViewVector(TransInfo *t, float coord[3], float vec[3])
{
if (t->persp != RV3D_ORTHO) {
- float p1[4], p2[4];
-
- copy_v3_v3(p1, coord);
- p1[3] = 1.0f;
- copy_v3_v3(p2, p1);
- p2[3] = 1.0f;
- mul_m4_v4(t->viewmat, p2);
-
- p2[0] = 2.0f * p2[0];
- p2[1] = 2.0f * p2[1];
- p2[2] = 2.0f * p2[2];
-
- mul_m4_v4(t->viewinv, p2);
-
- sub_v3_v3v3(vec, p1, p2);
+ sub_v3_v3v3(vec, coord, t->viewinv[3]);
}
else {
copy_v3_v3(vec, t->viewinv[2]);
@@ -316,7 +304,7 @@ static bool fcu_test_selected(FCurve *fcu)
return 0;
for (i = 0; i < fcu->totvert; i++, bezt++) {
- if (BEZSELECTED(bezt)) return 1;
+ if (BEZT_ISSEL_ANY(bezt)) return 1;
}
return 0;
@@ -720,7 +708,7 @@ static void recalcData_spaceclip(TransInfo *t)
static void recalcData_objects(TransInfo *t)
{
Base *base = t->scene->basact;
-
+
if (t->obedit) {
if (ELEM(t->obedit->type, OB_CURVE, OB_SURF)) {
Curve *cu = t->obedit->data;
@@ -770,7 +758,14 @@ static void recalcData_objects(TransInfo *t)
}
if ((t->options & CTX_NO_MIRROR) == 0 && (t->flag & T_MIRROR))
editbmesh_apply_to_mirror(t);
-
+
+ if (t->mode == TFM_EDGE_SLIDE) {
+ projectEdgeSlideData(t, false);
+ }
+ else if (t->mode == TFM_VERT_SLIDE) {
+ projectVertSlideData(t, false);
+ }
+
DAG_id_tag_update(t->obedit->data, 0); /* sets recalc flags */
EDBM_mesh_normals_update(em);
@@ -779,7 +774,7 @@ static void recalcData_objects(TransInfo *t)
else if (t->obedit->type == OB_ARMATURE) { /* no recalc flag, does pose */
bArmature *arm = t->obedit->data;
ListBase *edbo = arm->edbo;
- EditBone *ebo;
+ EditBone *ebo, *ebo_parent;
TransData *td = t->data;
int i;
@@ -789,17 +784,18 @@ static void recalcData_objects(TransInfo *t)
/* Ensure all bones are correctly adjusted */
for (ebo = edbo->first; ebo; ebo = ebo->next) {
+ ebo_parent = (ebo->flag & BONE_CONNECTED) ? ebo->parent : NULL;
- if ((ebo->flag & BONE_CONNECTED) && ebo->parent) {
+ if (ebo_parent) {
/* If this bone has a parent tip that has been moved */
- if (ebo->parent->flag & BONE_TIPSEL) {
- copy_v3_v3(ebo->head, ebo->parent->tail);
- if (t->mode == TFM_BONE_ENVELOPE) ebo->rad_head = ebo->parent->rad_tail;
+ if (ebo_parent->flag & BONE_TIPSEL) {
+ copy_v3_v3(ebo->head, ebo_parent->tail);
+ if (t->mode == TFM_BONE_ENVELOPE) ebo->rad_head = ebo_parent->rad_tail;
}
/* If this bone has a parent tip that has NOT been moved */
else {
- copy_v3_v3(ebo->parent->tail, ebo->head);
- if (t->mode == TFM_BONE_ENVELOPE) ebo->parent->rad_tail = ebo->rad_head;
+ copy_v3_v3(ebo_parent->tail, ebo->head);
+ if (t->mode == TFM_BONE_ENVELOPE) ebo_parent->rad_tail = ebo->rad_head;
}
}
@@ -820,10 +816,14 @@ static void recalcData_objects(TransInfo *t)
ebo->rad_head *= ebo->length / ebo->oldlength;
ebo->rad_tail *= ebo->length / ebo->oldlength;
ebo->oldlength = ebo->length;
+
+ if (ebo_parent) {
+ ebo_parent->rad_tail = ebo->rad_head;
+ }
}
}
- if (!ELEM(t->mode, TFM_BONE_ROLL, TFM_BONE_ENVELOPE, TFM_BONESIZE)) {
+ if (!ELEM(t->mode, TFM_BONE_ROLL, TFM_BONE_ENVELOPE, TFM_BONE_ENVELOPE_DIST, TFM_BONESIZE)) {
/* fix roll */
for (i = 0; i < t->total; i++, td++) {
if (td->extra) {
@@ -974,6 +974,9 @@ void recalcData(TransInfo *t)
else if (t->options & CTX_PAINT_CURVE) {
flushTransPaintCurve(t);
}
+ else if (t->options & CTX_GPENCIL_STROKES) {
+ /* pass? */
+ }
else if (t->spacetype == SPACE_IMAGE) {
recalcData_image(t);
}
@@ -1074,6 +1077,8 @@ static int initTransInfo_edit_pet_to_flag(const int proportional)
* Setup internal data, mouse, vectors
*
* \note \a op and \a event can be NULL
+ *
+ * \see #saveTransform does the reverse.
*/
void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *event)
{
@@ -1130,6 +1135,7 @@ void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve
zero_v3(t->vec);
zero_v3(t->center);
+ zero_v3(t->center_global);
unit_m3(t->mat);
@@ -1165,6 +1171,19 @@ void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve
t->spacetype = sa->spacetype;
}
+ /* handle T_ALT_TRANSFORM initialization, we may use for different operators */
+ if (op) {
+ const char *prop_id = NULL;
+ if (t->mode == TFM_SHRINKFATTEN) {
+ prop_id = "use_even_offset";
+ }
+
+ if (prop_id && (prop = RNA_struct_find_property(op->ptr, prop_id)) &&
+ RNA_property_is_set(op->ptr, prop))
+ {
+ BKE_BIT_TEST_SET(t->flag, RNA_property_boolean_get(op->ptr, prop), T_ALT_TRANSFORM);
+ }
+ }
if (t->spacetype == SPACE_VIEW3D) {
View3D *v3d = sa->spacedata.first;
@@ -1188,23 +1207,16 @@ void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve
t->around = V3D_CURSOR;
}
- if (op && ((prop = RNA_struct_find_property(op->ptr, "constraint_orientation")) &&
- RNA_property_is_set(op->ptr, prop)))
- {
- t->current_orientation = RNA_property_enum_get(op->ptr, prop);
-
- if (t->current_orientation >= V3D_MANIP_CUSTOM + BIF_countTransformOrientation(C)) {
- t->current_orientation = V3D_MANIP_GLOBAL;
- }
- }
- else {
- t->current_orientation = v3d->twmode;
- }
+ t->current_orientation = v3d->twmode;
/* exceptional case */
- if (t->around == V3D_LOCAL && (t->settings->selectmode & SCE_SELECT_FACE)) {
+ if (t->around == V3D_LOCAL) {
if (ELEM(t->mode, TFM_ROTATION, TFM_RESIZE, TFM_TRACKBALL)) {
- t->options |= CTX_NO_PET;
+ const bool use_island = transdata_check_local_islands(t, t->around);
+
+ if (obedit && !use_island) {
+ t->options |= CTX_NO_PET;
+ }
}
}
@@ -1226,7 +1238,7 @@ void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve
}
}
else {
- RNA_property_boolean_set(op->ptr, prop, t->settings->uvcalc_flag & UVCALC_TRANSFORM_CORRECT);
+ RNA_property_boolean_set(op->ptr, prop, (t->settings->uvcalc_flag & UVCALC_TRANSFORM_CORRECT) != 0);
}
}
@@ -1282,6 +1294,16 @@ void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve
}
t->around = V3D_CENTER;
}
+
+ if (op && ((prop = RNA_struct_find_property(op->ptr, "constraint_orientation")) &&
+ RNA_property_is_set(op->ptr, prop)))
+ {
+ t->current_orientation = RNA_property_enum_get(op->ptr, prop);
+
+ if (t->current_orientation >= V3D_MANIP_CUSTOM + BIF_countTransformOrientation(C)) {
+ t->current_orientation = V3D_MANIP_GLOBAL;
+ }
+ }
if (op && ((prop = RNA_struct_find_property(op->ptr, "release_confirm")) &&
RNA_property_is_set(op->ptr, prop)))
@@ -1321,7 +1343,16 @@ void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve
/* use settings from scene only if modal */
if (t->flag & T_MODAL) {
if ((t->options & CTX_NO_PET) == 0) {
- if (t->obedit) {
+ if (t->spacetype == SPACE_IPO) {
+ t->flag |= initTransInfo_edit_pet_to_flag(ts->proportional_fcurve);
+ }
+ else if (t->spacetype == SPACE_ACTION) {
+ t->flag |= initTransInfo_edit_pet_to_flag(ts->proportional_action);
+ }
+ else if (t->obedit) {
+ t->flag |= initTransInfo_edit_pet_to_flag(ts->proportional);
+ }
+ else if (t->options & CTX_GPENCIL_STROKES) {
t->flag |= initTransInfo_edit_pet_to_flag(ts->proportional);
}
else if (t->options & CTX_MASK) {
@@ -1377,6 +1408,7 @@ void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve
#endif
setTransformViewMatrices(t);
+ setTransformViewAspect(t, t->aspect);
initNumInput(&t->num);
}
@@ -1543,6 +1575,19 @@ void calculateCenter2D(TransInfo *t)
}
}
+void calculateCenterGlobal(TransInfo *t)
+{
+ /* setting constraint center */
+ /* note, init functions may over-ride t->center */
+ if (t->flag & (T_EDIT | T_POSE)) {
+ Object *ob = t->obedit ? t->obedit : t->poseobj;
+ mul_v3_m4v3(t->center_global, ob->obmat, t->center);
+ }
+ else {
+ copy_v3_v3(t->center_global, t->center);
+ }
+}
+
void calculateCenterCursor(TransInfo *t, float r_center[3])
{
const float *cursor;
@@ -1571,30 +1616,17 @@ void calculateCenterCursor(TransInfo *t, float r_center[3])
void calculateCenterCursor2D(TransInfo *t, float r_center[2])
{
- float aspx = 1.0, aspy = 1.0;
const float *cursor = NULL;
if (t->spacetype == SPACE_IMAGE) {
SpaceImage *sima = (SpaceImage *)t->sa->spacedata.first;
- if (t->options & CTX_MASK) {
- ED_space_image_get_aspect(sima, &aspx, &aspy);
- }
- else {
- ED_space_image_get_uv_aspect(sima, &aspx, &aspy);
- }
cursor = sima->cursor;
}
else if (t->spacetype == SPACE_CLIP) {
SpaceClip *space_clip = (SpaceClip *) t->sa->spacedata.first;
- if (t->options & CTX_MOVIECLIP) {
- ED_space_clip_get_aspect_dimension_aware(space_clip, &aspx, &aspy);
- }
- else {
- ED_space_clip_get_aspect(space_clip, &aspx, &aspy);
- }
cursor = space_clip->cursor;
}
-
+
if (cursor) {
if (t->options & CTX_MASK) {
float co[2];
@@ -1611,8 +1643,8 @@ void calculateCenterCursor2D(TransInfo *t, float r_center[2])
BLI_assert(!"Shall not happen");
}
- r_center[0] = co[0] * aspx;
- r_center[1] = co[1] * aspy;
+ r_center[0] = co[0] * t->aspect[0];
+ r_center[1] = co[1] * t->aspect[1];
}
else if (t->options & CTX_PAINT_CURVE) {
if (t->spacetype == SPACE_IMAGE) {
@@ -1621,8 +1653,8 @@ void calculateCenterCursor2D(TransInfo *t, float r_center[2])
}
}
else {
- r_center[0] = cursor[0] * aspx;
- r_center[1] = cursor[1] * aspy;
+ r_center[0] = cursor[0] * t->aspect[0];
+ r_center[1] = cursor[1] * t->aspect[1];
}
}
}
@@ -1651,8 +1683,9 @@ void calculateCenterMedian(TransInfo *t, float r_center[3])
}
}
}
- if (i)
- mul_v3_fl(partial, 1.0f / total);
+ if (total) {
+ mul_v3_fl(partial, 1.0f / (float)total);
+ }
copy_v3_v3(r_center, partial);
}
@@ -1684,63 +1717,8 @@ bool calculateCenterActive(TransInfo *t, bool select_only, float r_center[3])
bool ok = false;
if (t->obedit) {
- switch (t->obedit->type) {
- case OB_MESH:
- {
- BMEditSelection ese;
- BMEditMesh *em = BKE_editmesh_from_object(t->obedit);
-
- if (BM_select_history_active_get(em->bm, &ese)) {
- BM_editselection_center(&ese, r_center);
- ok = true;
- }
- break;
- }
- case OB_ARMATURE:
- {
- bArmature *arm = t->obedit->data;
- EditBone *ebo = arm->act_edbone;
-
- if (ebo && (!select_only || (ebo->flag & (BONE_SELECTED | BONE_ROOTSEL)))) {
- copy_v3_v3(r_center, ebo->head);
- ok = true;
- }
-
- break;
- }
- case OB_CURVE:
- case OB_SURF:
- {
- float center[3];
- Curve *cu = (Curve *)t->obedit->data;
-
- if (ED_curve_active_center(cu, center)) {
- copy_v3_v3(r_center, center);
- ok = true;
- }
- break;
- }
- case OB_MBALL:
- {
- MetaBall *mb = (MetaBall *)t->obedit->data;
- MetaElem *ml_act = mb->lastelem;
-
- if (ml_act && (!select_only || (ml_act->flag & SELECT))) {
- copy_v3_v3(r_center, &ml_act->x);
- ok = true;
- }
- break;
- }
- case OB_LATTICE:
- {
- BPoint *actbp = BKE_lattice_active_point_get(t->obedit->data);
-
- if (actbp) {
- copy_v3_v3(r_center, actbp->vec);
- ok = true;
- }
- break;
- }
+ if (ED_object_editmode_calc_active_center(t->obedit, select_only, r_center)) {
+ ok = true;
}
}
else if (t->flag & T_POSE) {
@@ -1811,14 +1789,8 @@ void calculateCenter(TransInfo *t)
}
calculateCenter2D(t);
+ calculateCenterGlobal(t);
- /* setting constraint center */
- copy_v3_v3(t->con.center, t->center);
- if (t->flag & (T_EDIT | T_POSE)) {
- Object *ob = t->obedit ? t->obedit : t->poseobj;
- mul_m4_v3(ob->obmat, t->con.center);
- }
-
/* for panning from cameraview */
if (t->flag & T_OBJECT) {
if (t->spacetype == SPACE_VIEW3D && t->ar && t->ar->regiontype == RGN_TYPE_WINDOW) {
@@ -1839,7 +1811,7 @@ void calculateCenter(TransInfo *t)
/* rotate only needs correct 2d center, grab needs ED_view3d_calc_zfac() value */
if (t->mode == TFM_TRANSLATION) {
copy_v3_v3(t->center, axis);
- copy_v3_v3(t->con.center, t->center);
+ copy_v3_v3(t->center_global, t->center);
}
}
}
@@ -1859,7 +1831,7 @@ void calculateCenter(TransInfo *t)
/* zfac is only used convertViewVec only in cases operator was invoked in RGN_TYPE_WINDOW
* and never used in other cases.
*
- * We need special case here as well, since ED_view3d_calc_zfac will crahs when called
+ * We need special case here as well, since ED_view3d_calc_zfac will crash when called
* for a region different from RGN_TYPE_WINDOW.
*/
if (t->ar->regiontype == RGN_TYPE_WINDOW) {
@@ -1876,9 +1848,12 @@ void calculatePropRatio(TransInfo *t)
TransData *td = t->data;
int i;
float dist;
- short connected = t->flag & T_PROP_CONNECTED;
+ const bool connected = (t->flag & T_PROP_CONNECTED) != 0;
+
+ t->proptext[0] = '\0';
if (t->flag & T_PROP_EDIT) {
+ const char *pet_id = NULL;
for (i = 0; i < t->total; i++, td++) {
if (td->flag & TD_SELECTED) {
td->factor = 1.0f;
@@ -1939,6 +1914,9 @@ void calculatePropRatio(TransInfo *t)
case PROP_RANDOM:
td->factor = BLI_frand() * dist;
break;
+ case PROP_INVSQUARE:
+ td->factor = dist * (2.0f - dist);
+ break;
default:
td->factor = 1;
break;
@@ -1947,35 +1925,147 @@ void calculatePropRatio(TransInfo *t)
}
switch (t->prop_mode) {
case PROP_SHARP:
- strcpy(t->proptext, IFACE_("(Sharp)"));
+ pet_id = N_("(Sharp)");
break;
case PROP_SMOOTH:
- strcpy(t->proptext, IFACE_("(Smooth)"));
+ pet_id = N_("(Smooth)");
break;
case PROP_ROOT:
- strcpy(t->proptext, IFACE_("(Root)"));
+ pet_id = N_("(Root)");
break;
case PROP_LIN:
- strcpy(t->proptext, IFACE_("(Linear)"));
+ pet_id = N_("(Linear)");
break;
case PROP_CONST:
- strcpy(t->proptext, IFACE_("(Constant)"));
+ pet_id = N_("(Constant)");
break;
case PROP_SPHERE:
- strcpy(t->proptext, IFACE_("(Sphere)"));
+ pet_id = N_("(Sphere)");
break;
case PROP_RANDOM:
- strcpy(t->proptext, IFACE_("(Random)"));
+ pet_id = N_("(Random)");
+ break;
+ case PROP_INVSQUARE:
+ pet_id = N_("(InvSquare)");
break;
default:
- t->proptext[0] = '\0';
break;
}
+
+ if (pet_id) {
+ BLI_strncpy(t->proptext, IFACE_(pet_id), sizeof(t->proptext));
+ }
}
else {
for (i = 0; i < t->total; i++, td++) {
td->factor = 1.0;
}
- t->proptext[0] = '\0';
}
}
+
+/**
+ * Rotate an element, low level code, ignore protected channels.
+ * (use for objects or pose-bones)
+ * Similar to #ElementRotation.
+ */
+void transform_data_ext_rotate(TransData *td, float mat[3][3], bool use_drot)
+{
+ float totmat[3][3];
+ float smat[3][3];
+ float fmat[3][3];
+ float obmat[3][3];
+
+ float dmat[3][3]; /* delta rotation */
+ float dmat_inv[3][3];
+
+ mul_m3_m3m3(totmat, mat, td->mtx);
+ mul_m3_m3m3(smat, td->smtx, mat);
+
+ /* logic from BKE_object_rot_to_mat3 */
+ if (use_drot) {
+ if (td->ext->rotOrder > 0) {
+ eulO_to_mat3(dmat, td->ext->drot, td->ext->rotOrder);
+ }
+ else if (td->ext->rotOrder == ROT_MODE_AXISANGLE) {
+#if 0
+ axis_angle_to_mat3(dmat, td->ext->drotAxis, td->ext->drotAngle);
+#else
+ unit_m3(dmat);
+#endif
+ }
+ else {
+ float tquat[4];
+ normalize_qt_qt(tquat, td->ext->dquat);
+ quat_to_mat3(dmat, tquat);
+ }
+
+ invert_m3_m3(dmat_inv, dmat);
+ }
+
+
+ if (td->ext->rotOrder == ROT_MODE_QUAT) {
+ float quat[4];
+
+ /* calculate the total rotatation */
+ quat_to_mat3(obmat, td->ext->iquat);
+ if (use_drot) {
+ mul_m3_m3m3(obmat, dmat, obmat);
+ }
+
+ /* mat = transform, obmat = object rotation */
+ mul_m3_m3m3(fmat, smat, obmat);
+
+ if (use_drot) {
+ mul_m3_m3m3(fmat, dmat_inv, fmat);
+ }
+
+ mat3_to_quat(quat, fmat);
+
+ /* apply */
+ copy_qt_qt(td->ext->quat, quat);
+ }
+ else if (td->ext->rotOrder == ROT_MODE_AXISANGLE) {
+ float axis[3], angle;
+
+ /* calculate the total rotatation */
+ axis_angle_to_mat3(obmat, td->ext->irotAxis, td->ext->irotAngle);
+ if (use_drot) {
+ mul_m3_m3m3(obmat, dmat, obmat);
+ }
+
+ /* mat = transform, obmat = object rotation */
+ mul_m3_m3m3(fmat, smat, obmat);
+
+ if (use_drot) {
+ mul_m3_m3m3(fmat, dmat_inv, fmat);
+ }
+
+ mat3_to_axis_angle(axis, &angle, fmat);
+
+ /* apply */
+ copy_v3_v3(td->ext->rotAxis, axis);
+ *td->ext->rotAngle = angle;
+ }
+ else {
+ float eul[3];
+
+ /* calculate the total rotatation */
+ eulO_to_mat3(obmat, td->ext->irot, td->ext->rotOrder);
+ if (use_drot) {
+ mul_m3_m3m3(obmat, dmat, obmat);
+ }
+
+ /* mat = transform, obmat = object rotation */
+ mul_m3_m3m3(fmat, smat, obmat);
+
+ if (use_drot) {
+ mul_m3_m3m3(fmat, dmat_inv, fmat);
+ }
+
+ mat3_to_compatible_eulO(eul, td->ext->rot, td->ext->rotOrder, fmat);
+
+ /* apply */
+ copy_v3_v3(td->ext->rot, eul);
+ }
+}
+
diff --git a/source/blender/editors/transform/transform_manipulator.c b/source/blender/editors/transform/transform_manipulator.c
index 2161e52d7b2..f13bc6b6b55 100644
--- a/source/blender/editors/transform/transform_manipulator.c
+++ b/source/blender/editors/transform/transform_manipulator.c
@@ -177,7 +177,7 @@ static void axis_angle_to_gimbal_axis(float gmat[3][3], const float axis[3], con
mul_qt_v3(quat, gmat[0]);
/* Y-axis */
- axis_angle_to_quat(quat, axis, M_PI / 2.0);
+ axis_angle_to_quat(quat, axis, M_PI_2);
copy_v3_v3(gmat[1], gmat[0]);
mul_qt_v3(quat, gmat[1]);
@@ -262,13 +262,12 @@ bool gimbal_axis(Object *ob, float gmat[3][3])
/* centroid, boundbox, of selection */
/* returns total items selected */
-int calc_manipulator_stats(const bContext *C)
+static int calc_manipulator_stats(const bContext *C)
{
ScrArea *sa = CTX_wm_area(C);
ARegion *ar = CTX_wm_region(C);
Scene *scene = CTX_data_scene(C);
Object *obedit = CTX_data_edit_object(C);
- ToolSettings *ts = CTX_data_tool_settings(C);
View3D *v3d = sa->spacedata.first;
RegionView3D *rv3d = ar->regiondata;
Base *base;
@@ -305,48 +304,11 @@ int calc_manipulator_stats(const bContext *C)
BMIter iter;
- /* do vertices/edges/faces for center depending on selection
- * mode. note we can't use just vertex selection flag because
- * it is not flush down on changes */
- if (ts->selectmode & SCE_SELECT_VERTEX) {
- BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) {
- if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) {
- if (BM_elem_flag_test(eve, BM_ELEM_SELECT)) {
- totsel++;
- calc_tw_center(scene, eve->co);
- }
- }
- }
- }
- else if (ts->selectmode & SCE_SELECT_EDGE) {
- BMIter itersub;
- BMEdge *eed;
- BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) {
- if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) {
- /* check the vertex has a selected edge, only add it once */
- BM_ITER_ELEM (eed, &itersub, eve, BM_EDGES_OF_VERT) {
- if (BM_elem_flag_test(eed, BM_ELEM_SELECT)) {
- totsel++;
- calc_tw_center(scene, eve->co);
- break;
- }
- }
- }
- }
- }
- else {
- BMIter itersub;
- BMFace *efa;
- BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) {
- if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) {
- /* check the vertex has a selected face, only add it once */
- BM_ITER_ELEM (efa, &itersub, eve, BM_FACES_OF_VERT) {
- if (BM_elem_flag_test(efa, BM_ELEM_SELECT)) {
- totsel++;
- calc_tw_center(scene, eve->co);
- break;
- }
- }
+ BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) {
+ if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) {
+ if (BM_elem_flag_test(eve, BM_ELEM_SELECT)) {
+ totsel++;
+ calc_tw_center(scene, eve->co);
}
}
}
@@ -550,7 +512,7 @@ int calc_manipulator_stats(const bContext *C)
for (k = 0, ek = point->keys; k < point->totkey; k++, ek++) {
if (ek->flag & PEK_SELECT) {
- calc_tw_center(scene, ek->flag & PEK_USE_WCO ? ek->world_co : ek->co);
+ calc_tw_center(scene, (ek->flag & PEK_USE_WCO) ? ek->world_co : ek->co);
totsel++;
}
}
@@ -606,7 +568,7 @@ int calc_manipulator_stats(const bContext *C)
{
if (obedit || ob->mode & OB_MODE_POSE) {
float mat[3][3];
- ED_getTransformOrientationMatrix(C, mat, (v3d->around == V3D_ACTIVE));
+ ED_getTransformOrientationMatrix(C, mat, v3d->around);
copy_m4_m3(rv3d->twmat, mat);
break;
}
@@ -621,7 +583,7 @@ int calc_manipulator_stats(const bContext *C)
* and users who select many bones will understand whats going on and what local means
* when they start transforming */
float mat[3][3];
- ED_getTransformOrientationMatrix(C, mat, (v3d->around == V3D_ACTIVE));
+ ED_getTransformOrientationMatrix(C, mat, v3d->around);
copy_m4_m3(rv3d->twmat, mat);
break;
}
@@ -640,7 +602,7 @@ int calc_manipulator_stats(const bContext *C)
default: /* V3D_MANIP_CUSTOM */
{
float mat[3][3];
- if (applyTransformOrientation(C, mat, NULL)) {
+ if (applyTransformOrientation(C, mat, NULL, v3d->twmode - V3D_MANIP_CUSTOM)) {
copy_m4_m3(rv3d->twmat, mat);
}
break;
@@ -681,7 +643,7 @@ static void test_manipulator_axis(const bContext *C)
static float screen_aligned(RegionView3D *rv3d, float mat[4][4])
{
- glTranslatef(mat[3][0], mat[3][1], mat[3][2]);
+ glTranslate3fv(mat[3]);
/* sets view screen aligned */
glRotatef(-360.0f * saacos(rv3d->viewquat[0]) / (float)M_PI, rv3d->viewquat[1], rv3d->viewquat[2], rv3d->viewquat[3]);
@@ -933,6 +895,11 @@ static void postOrtho(const bool ortho)
}
}
+BLI_INLINE bool manipulator_rotate_is_visible(const int drawflags)
+{
+ return (drawflags & (MAN_ROT_X | MAN_ROT_Y | MAN_ROT_Z));
+}
+
static void draw_manipulator_rotate(
View3D *v3d, RegionView3D *rv3d, const int drawflags, const int combo,
const bool is_moving, const bool is_picksel)
@@ -946,8 +913,8 @@ static void draw_manipulator_rotate(
const int colcode = (is_moving) ? MAN_MOVECOL : MAN_RGB;
bool ortho;
- /* when called while moving in mixed mode, do not draw when... */
- if ((drawflags & MAN_ROT_C) == 0) return;
+ /* skip drawing if all axes are locked */
+ if (manipulator_rotate_is_visible(drawflags) == false) return;
/* Init stuff */
glDisable(GL_DEPTH_TEST);
@@ -956,7 +923,7 @@ static void draw_manipulator_rotate(
/* prepare for screen aligned draw */
size = len_v3(rv3d->twmat[0]);
glPushMatrix();
- glTranslatef(rv3d->twmat[3][0], rv3d->twmat[3][1], rv3d->twmat[3][2]);
+ glTranslate3fv(rv3d->twmat[3]);
if (arcs) {
/* clipplane makes nice handles, calc here because of multmatrix but with translate! */
@@ -1089,8 +1056,6 @@ static void draw_manipulator_rotate(
glRotatef(90.0, 1.0, 0.0, 0.0);
postOrtho(ortho);
}
-
- if (arcs) glDisable(GL_CLIP_PLANE0);
}
// donut arcs
if (arcs) {
@@ -1397,7 +1362,7 @@ static void draw_manipulator_translate(
manipulator_axis_order(rv3d, axis_order);
- // XXX if (moving) glTranslatef(t->vec[0], t->vec[1], t->vec[2]);
+ // XXX if (moving) glTranslate3fv(t->vec);
glDisable(GL_DEPTH_TEST);
/* center circle, do not add to selection when shift is pressed (planar constraint) */
@@ -1486,8 +1451,8 @@ static void draw_manipulator_rotate_cyl(
int axis_order[3] = {2, 0, 1};
int i;
- /* when called while moving in mixed mode, do not draw when... */
- if ((drawflags & MAN_ROT_C) == 0) return;
+ /* skip drawing if all axes are locked */
+ if (manipulator_rotate_is_visible(drawflags) == false) return;
manipulator_axis_order(rv3d, axis_order);
@@ -1850,7 +1815,6 @@ int BIF_do_manipulator(bContext *C, const struct wmEvent *event, wmOperator *op)
}
RNA_boolean_set_array(op->ptr, "constraint_axis", constraint_axis);
WM_operator_name_call(C, "TRANSFORM_OT_translate", WM_OP_INVOKE_DEFAULT, op->ptr);
- //wm_operator_invoke(C, WM_operatortype_find("TRANSFORM_OT_translate", 0), event, op->ptr, NULL, false);
}
else if (drawflags & MAN_SCALE_C) {
switch (drawflags) {
@@ -1881,7 +1845,6 @@ int BIF_do_manipulator(bContext *C, const struct wmEvent *event, wmOperator *op)
}
RNA_boolean_set_array(op->ptr, "constraint_axis", constraint_axis);
WM_operator_name_call(C, "TRANSFORM_OT_resize", WM_OP_INVOKE_DEFAULT, op->ptr);
- //wm_operator_invoke(C, WM_operatortype_find("TRANSFORM_OT_resize", 0), event, op->ptr, NULL, false);
}
else if (drawflags == MAN_ROT_T) { /* trackball need special case, init is different */
/* Do not pass op->ptr!!! trackball has no "constraint" properties!
@@ -1894,8 +1857,7 @@ int BIF_do_manipulator(bContext *C, const struct wmEvent *event, wmOperator *op)
if ((prop = RNA_struct_find_property(op->ptr, "release_confirm")) && RNA_property_is_set(op->ptr, prop)) {
RNA_property_boolean_set(&props_ptr, prop, RNA_property_boolean_get(op->ptr, prop));
}
- WM_operator_name_call(C, ot->idname, WM_OP_INVOKE_DEFAULT, &props_ptr);
- //wm_operator_invoke(C, WM_operatortype_find(ot->idname, 0), event, NULL, NULL, false);
+ WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &props_ptr);
WM_operator_properties_free(&props_ptr);
}
else if (drawflags & MAN_ROT_C) {
@@ -1912,7 +1874,6 @@ int BIF_do_manipulator(bContext *C, const struct wmEvent *event, wmOperator *op)
}
RNA_boolean_set_array(op->ptr, "constraint_axis", constraint_axis);
WM_operator_name_call(C, "TRANSFORM_OT_rotate", WM_OP_INVOKE_DEFAULT, op->ptr);
- //wm_operator_invoke(C, WM_operatortype_find("TRANSFORM_OT_rotate", 0), event, op->ptr, NULL, false);
}
}
/* after transform, restore drawflags */
diff --git a/source/blender/editors/transform/transform_ops.c b/source/blender/editors/transform/transform_ops.c
index 81e065ee33a..c6d0d6cde2e 100644
--- a/source/blender/editors/transform/transform_ops.c
+++ b/source/blender/editors/transform/transform_ops.c
@@ -33,11 +33,12 @@
#include "BLI_math.h"
#include "BLI_utildefines.h"
-#include "BLF_translation.h"
+#include "BLT_translation.h"
#include "BKE_context.h"
#include "BKE_global.h"
#include "BKE_report.h"
+#include "BKE_editmesh.h"
#include "RNA_access.h"
#include "RNA_define.h"
@@ -63,23 +64,23 @@ typedef struct TransformModeItem {
static const float VecOne[3] = {1, 1, 1};
-static char OP_TRANSLATION[] = "TRANSFORM_OT_translate";
-static char OP_ROTATION[] = "TRANSFORM_OT_rotate";
-static char OP_TOSPHERE[] = "TRANSFORM_OT_tosphere";
-static char OP_RESIZE[] = "TRANSFORM_OT_resize";
-static char OP_SKIN_RESIZE[] = "TRANSFORM_OT_skin_resize";
-static char OP_SHEAR[] = "TRANSFORM_OT_shear";
-static char OP_BEND[] = "TRANSFORM_OT_bend";
-static char OP_SHRINK_FATTEN[] = "TRANSFORM_OT_shrink_fatten";
-static char OP_PUSH_PULL[] = "TRANSFORM_OT_push_pull";
-static char OP_TILT[] = "TRANSFORM_OT_tilt";
-static char OP_TRACKBALL[] = "TRANSFORM_OT_trackball";
-static char OP_MIRROR[] = "TRANSFORM_OT_mirror";
-static char OP_EDGE_SLIDE[] = "TRANSFORM_OT_edge_slide";
-static char OP_VERT_SLIDE[] = "TRANSFORM_OT_vert_slide";
-static char OP_EDGE_CREASE[] = "TRANSFORM_OT_edge_crease";
-static char OP_EDGE_BWEIGHT[] = "TRANSFORM_OT_edge_bevelweight";
-static char OP_SEQ_SLIDE[] = "TRANSFORM_OT_seq_slide";
+static const char OP_TRANSLATION[] = "TRANSFORM_OT_translate";
+static const char OP_ROTATION[] = "TRANSFORM_OT_rotate";
+static const char OP_TOSPHERE[] = "TRANSFORM_OT_tosphere";
+static const char OP_RESIZE[] = "TRANSFORM_OT_resize";
+static const char OP_SKIN_RESIZE[] = "TRANSFORM_OT_skin_resize";
+static const char OP_SHEAR[] = "TRANSFORM_OT_shear";
+static const char OP_BEND[] = "TRANSFORM_OT_bend";
+static const char OP_SHRINK_FATTEN[] = "TRANSFORM_OT_shrink_fatten";
+static const char OP_PUSH_PULL[] = "TRANSFORM_OT_push_pull";
+static const char OP_TILT[] = "TRANSFORM_OT_tilt";
+static const char OP_TRACKBALL[] = "TRANSFORM_OT_trackball";
+static const char OP_MIRROR[] = "TRANSFORM_OT_mirror";
+static const char OP_EDGE_SLIDE[] = "TRANSFORM_OT_edge_slide";
+static const char OP_VERT_SLIDE[] = "TRANSFORM_OT_vert_slide";
+static const char OP_EDGE_CREASE[] = "TRANSFORM_OT_edge_crease";
+static const char OP_EDGE_BWEIGHT[] = "TRANSFORM_OT_edge_bevelweight";
+static const char OP_SEQ_SLIDE[] = "TRANSFORM_OT_seq_slide";
static void TRANSFORM_OT_translate(struct wmOperatorType *ot);
static void TRANSFORM_OT_rotate(struct wmOperatorType *ot);
@@ -140,8 +141,10 @@ EnumPropertyItem transform_mode_types[] =
{TFM_MIRROR, "MIRROR", 0, "Mirror", ""},
{TFM_BONESIZE, "BONE_SIZE", 0, "Bonesize", ""},
{TFM_BONE_ENVELOPE, "BONE_ENVELOPE", 0, "Bone_Envelope", ""},
+ {TFM_BONE_ENVELOPE_DIST, "BONE_ENVELOPE_DIST", 0, "Bone_Envelope_Distance", ""},
{TFM_CURVE_SHRINKFATTEN, "CURVE_SHRINKFATTEN", 0, "Curve_Shrinkfatten", ""},
{TFM_MASK_SHRINKFATTEN, "MASK_SHRINKFATTEN", 0, "Mask_Shrinkfatten", ""},
+ {TFM_GPENCIL_SHRINKFATTEN, "GPENCIL_SHRINKFATTEN", 0, "GPencil_Shrinkfatten", ""},
{TFM_BONE_ROLL, "BONE_ROLL", 0, "Bone_Roll", ""},
{TFM_TIME_TRANSLATE, "TIME_TRANSLATE", 0, "Time_Translate", ""},
{TFM_TIME_SLIDE, "TIME_SLIDE", 0, "Time_Slide", ""},
@@ -171,12 +174,12 @@ static int select_orientation_invoke(bContext *C, wmOperator *UNUSED(op), const
uiPopupMenu *pup;
uiLayout *layout;
- pup = uiPupMenuBegin(C, IFACE_("Orientation"), ICON_NONE);
- layout = uiPupMenuLayout(pup);
+ pup = UI_popup_menu_begin(C, IFACE_("Orientation"), ICON_NONE);
+ layout = UI_popup_menu_layout(pup);
uiItemsEnumO(layout, "TRANSFORM_OT_select_orientation", "orientation");
- uiPupMenuEnd(C, pup);
+ UI_popup_menu_end(C, pup);
- return OPERATOR_CANCELLED;
+ return OPERATOR_INTERFACE;
}
static void TRANSFORM_OT_select_orientation(struct wmOperatorType *ot)
@@ -324,6 +327,9 @@ static void transformops_loopsel_hack(bContext *C, wmOperator *op)
}
}
}
+#else
+/* prevent removal by cleanup */
+# error "loopslide hack removed!"
#endif /* USE_LOOPSLIDE_HACK */
@@ -484,7 +490,7 @@ static int transform_invoke(bContext *C, wmOperator *op, const wmEvent *event)
/* add temp handler */
WM_event_add_modal_handler(C, op);
- op->flag |= OP_GRAB_POINTER; // XXX maybe we want this with the manipulator only?
+ op->flag |= OP_IS_MODAL_GRAB_CURSOR; // XXX maybe we want this with the manipulator only?
return OPERATOR_RUNNING_MODAL;
}
}
@@ -521,7 +527,7 @@ void Transform_Properties(struct wmOperatorType *ot, int flags)
RNA_def_enum(ot->srna, "proportional", proportional_editing_items, 0, "Proportional Editing", "");
prop = RNA_def_enum(ot->srna, "proportional_edit_falloff", proportional_falloff_items, 0,
"Proportional Editing Falloff", "Falloff type for proportional editing mode");
- RNA_def_property_translation_context(prop, BLF_I18NCONTEXT_ID_CURVE); /* Abusing id_curve :/ */
+ RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_CURVE); /* Abusing id_curve :/ */
RNA_def_float(ot->srna, "proportional_size", 1, 0.00001f, FLT_MAX, "Proportional Size", "", 0.001, 100);
}
@@ -543,7 +549,11 @@ void Transform_Properties(struct wmOperatorType *ot, int flags)
}
}
}
-
+
+ if (flags & P_GPENCIL_EDIT) {
+ RNA_def_boolean(ot->srna, "gpencil_strokes", 0, "Edit Grease Pencil", "Edit selected Grease Pencil strokes");
+ }
+
if ((flags & P_OPTIONS) && !(flags & P_NO_TEXSPACE)) {
RNA_def_boolean(ot->srna, "texture_space", 0, "Edit Texture Space", "Edit Object data texture space");
prop = RNA_def_boolean(ot->srna, "remove_on_cancel", 0, "Remove on Cancel", "Remove elements on cancel");
@@ -578,7 +588,7 @@ static void TRANSFORM_OT_translate(struct wmOperatorType *ot)
RNA_def_float_vector_xyz(ot->srna, "value", 3, NULL, -FLT_MAX, FLT_MAX, "Vector", "", -FLT_MAX, FLT_MAX);
- Transform_Properties(ot, P_CONSTRAINT | P_PROPORTIONAL | P_MIRROR | P_ALIGN_SNAP | P_OPTIONS);
+ Transform_Properties(ot, P_CONSTRAINT | P_PROPORTIONAL | P_MIRROR | P_ALIGN_SNAP | P_OPTIONS | P_GPENCIL_EDIT);
}
static void TRANSFORM_OT_resize(struct wmOperatorType *ot)
@@ -598,7 +608,7 @@ static void TRANSFORM_OT_resize(struct wmOperatorType *ot)
RNA_def_float_vector(ot->srna, "value", 3, VecOne, -FLT_MAX, FLT_MAX, "Vector", "", -FLT_MAX, FLT_MAX);
- Transform_Properties(ot, P_CONSTRAINT | P_PROPORTIONAL | P_MIRROR | P_GEO_SNAP | P_OPTIONS);
+ Transform_Properties(ot, P_CONSTRAINT | P_PROPORTIONAL | P_MIRROR | P_GEO_SNAP | P_OPTIONS | P_GPENCIL_EDIT);
}
static int skin_resize_poll(bContext *C)
@@ -633,8 +643,6 @@ static void TRANSFORM_OT_skin_resize(struct wmOperatorType *ot)
static void TRANSFORM_OT_trackball(struct wmOperatorType *ot)
{
- PropertyRNA *prop;
-
/* identifiers */
ot->name = "Trackball";
ot->description = "Trackball style rotation of selected items";
@@ -649,16 +657,13 @@ static void TRANSFORM_OT_trackball(struct wmOperatorType *ot)
ot->poll = ED_operator_screenactive;
/* Maybe we could use float_vector_xyz here too? */
- prop = RNA_def_float_vector(ot->srna, "value", 2, NULL, -FLT_MAX, FLT_MAX, "Angle", "", -FLT_MAX, FLT_MAX);
- RNA_def_property_subtype(prop, PROP_ANGLE);
+ RNA_def_float_rotation(ot->srna, "value", 2, NULL, -FLT_MAX, FLT_MAX, "Angle", "", -FLT_MAX, FLT_MAX);
- Transform_Properties(ot, P_PROPORTIONAL | P_MIRROR | P_SNAP);
+ Transform_Properties(ot, P_PROPORTIONAL | P_MIRROR | P_SNAP | P_GPENCIL_EDIT);
}
static void TRANSFORM_OT_rotate(struct wmOperatorType *ot)
{
- PropertyRNA *prop;
-
/* identifiers */
ot->name = "Rotate";
ot->description = "Rotate selected items";
@@ -672,10 +677,9 @@ static void TRANSFORM_OT_rotate(struct wmOperatorType *ot)
ot->cancel = transform_cancel;
ot->poll = ED_operator_screenactive;
- prop = RNA_def_float(ot->srna, "value", 0.0f, -FLT_MAX, FLT_MAX, "Angle", "", -M_PI * 2, M_PI * 2);
- RNA_def_property_subtype(prop, PROP_ANGLE);
+ RNA_def_float_rotation(ot->srna, "value", 0, NULL, -FLT_MAX, FLT_MAX, "Angle", "", -M_PI * 2, M_PI * 2);
- Transform_Properties(ot, P_AXIS | P_CONSTRAINT | P_PROPORTIONAL | P_MIRROR | P_GEO_SNAP);
+ Transform_Properties(ot, P_AXIS | P_CONSTRAINT | P_PROPORTIONAL | P_MIRROR | P_GEO_SNAP | P_GPENCIL_EDIT);
}
static void TRANSFORM_OT_tilt(struct wmOperatorType *ot)
@@ -721,7 +725,7 @@ static void TRANSFORM_OT_bend(struct wmOperatorType *ot)
RNA_def_float_rotation(ot->srna, "value", 1, NULL, -FLT_MAX, FLT_MAX, "Angle", "", -M_PI * 2, M_PI * 2);
- Transform_Properties(ot, P_PROPORTIONAL | P_MIRROR | P_SNAP);
+ Transform_Properties(ot, P_PROPORTIONAL | P_MIRROR | P_SNAP | P_GPENCIL_EDIT);
}
static void TRANSFORM_OT_shear(struct wmOperatorType *ot)
@@ -741,7 +745,7 @@ static void TRANSFORM_OT_shear(struct wmOperatorType *ot)
RNA_def_float(ot->srna, "value", 0, -FLT_MAX, FLT_MAX, "Offset", "", -FLT_MAX, FLT_MAX);
- Transform_Properties(ot, P_PROPORTIONAL | P_MIRROR | P_SNAP);
+ Transform_Properties(ot, P_PROPORTIONAL | P_MIRROR | P_SNAP | P_GPENCIL_EDIT);
// XXX Shear axis?
}
@@ -782,6 +786,8 @@ static void TRANSFORM_OT_shrink_fatten(struct wmOperatorType *ot)
RNA_def_float(ot->srna, "value", 0, -FLT_MAX, FLT_MAX, "Offset", "", -FLT_MAX, FLT_MAX);
+ RNA_def_boolean(ot->srna, "use_even_offset", true, "Offset Even", "Scale the offset to give more even thickness");
+
Transform_Properties(ot, P_PROPORTIONAL | P_MIRROR | P_SNAP);
}
@@ -803,7 +809,7 @@ static void TRANSFORM_OT_tosphere(struct wmOperatorType *ot)
RNA_def_float_factor(ot->srna, "value", 0, 0, 1, "Factor", "", 0, 1);
- Transform_Properties(ot, P_PROPORTIONAL | P_MIRROR | P_SNAP);
+ Transform_Properties(ot, P_PROPORTIONAL | P_MIRROR | P_SNAP | P_GPENCIL_EDIT);
}
static void TRANSFORM_OT_mirror(struct wmOperatorType *ot)
@@ -821,11 +827,13 @@ static void TRANSFORM_OT_mirror(struct wmOperatorType *ot)
ot->cancel = transform_cancel;
ot->poll = ED_operator_screenactive;
- Transform_Properties(ot, P_CONSTRAINT | P_PROPORTIONAL);
+ Transform_Properties(ot, P_CONSTRAINT | P_PROPORTIONAL | P_GPENCIL_EDIT);
}
static void TRANSFORM_OT_edge_slide(struct wmOperatorType *ot)
{
+ PropertyRNA *prop;
+
/* identifiers */
ot->name = "Edge Slide";
ot->description = "Slide an edge loop along a mesh";
@@ -837,9 +845,12 @@ static void TRANSFORM_OT_edge_slide(struct wmOperatorType *ot)
ot->exec = transform_exec;
ot->modal = transform_modal;
ot->cancel = transform_cancel;
- ot->poll = ED_operator_editmesh;
+ ot->poll = ED_operator_editmesh_region_view3d;
- RNA_def_float_factor(ot->srna, "value", 0, -1.0f, 1.0f, "Factor", "", -1.0f, 1.0f);
+ RNA_def_float_factor(ot->srna, "value", 0, -10.0f, 10.0f, "Factor", "", -1.0f, 1.0f);
+
+ prop = RNA_def_boolean(ot->srna, "single_side", false, "Single Side", "");
+ RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
Transform_Properties(ot, P_MIRROR | P_SNAP | P_CORRECT_UV);
}
@@ -857,11 +868,11 @@ static void TRANSFORM_OT_vert_slide(struct wmOperatorType *ot)
ot->exec = transform_exec;
ot->modal = transform_modal;
ot->cancel = transform_cancel;
- ot->poll = ED_operator_editmesh;
+ ot->poll = ED_operator_editmesh_region_view3d;
RNA_def_float_factor(ot->srna, "value", 0, -10.0f, 10.0f, "Factor", "", -1.0f, 1.0f);
- Transform_Properties(ot, P_MIRROR | P_SNAP);
+ Transform_Properties(ot, P_MIRROR | P_SNAP | P_CORRECT_UV);
}
static void TRANSFORM_OT_edge_crease(struct wmOperatorType *ot)
@@ -967,7 +978,7 @@ static void TRANSFORM_OT_transform(struct wmOperatorType *ot)
RNA_def_float_vector(ot->srna, "value", 4, NULL, -FLT_MAX, FLT_MAX, "Values", "", -FLT_MAX, FLT_MAX);
- Transform_Properties(ot, P_AXIS | P_CONSTRAINT | P_PROPORTIONAL | P_MIRROR | P_ALIGN_SNAP);
+ Transform_Properties(ot, P_AXIS | P_CONSTRAINT | P_PROPORTIONAL | P_MIRROR | P_ALIGN_SNAP | P_GPENCIL_EDIT);
}
void transform_operatortypes(void)
@@ -1107,8 +1118,10 @@ void transform_keymap_for_space(wmKeyConfig *keyconf, wmKeyMap *keymap, int spac
WM_keymap_add_item(keymap, "NODE_OT_move_detach_links_release", EVT_TWEAK_A, KM_ANY, KM_ALT, 0);
WM_keymap_add_item(keymap, "NODE_OT_move_detach_links", EVT_TWEAK_S, KM_ANY, KM_ALT, 0);
- /* dettach and translate */
- WM_keymap_add_item(keymap, "NODE_OT_detach_translate_attach", FKEY, KM_PRESS, KM_ALT, 0);
+ kmi = WM_keymap_add_item(keymap, "WM_OT_context_toggle", TABKEY, KM_PRESS, KM_SHIFT, 0);
+ RNA_string_set(kmi->ptr, "data_path", "tool_settings.use_snap");
+ kmi = WM_keymap_add_item(keymap, "WM_OT_context_menu_enum", TABKEY, KM_PRESS, KM_SHIFT | KM_CTRL, 0);
+ RNA_string_set(kmi->ptr, "data_path", "tool_settings.snap_node_element");
break;
case SPACE_SEQ:
WM_keymap_add_item(keymap, OP_SEQ_SLIDE, GKEY, KM_PRESS, 0, 0);
diff --git a/source/blender/editors/transform/transform_orientations.c b/source/blender/editors/transform/transform_orientations.c
index c7d63da8281..a1bb6f4e0f3 100644
--- a/source/blender/editors/transform/transform_orientations.c
+++ b/source/blender/editors/transform/transform_orientations.c
@@ -24,7 +24,6 @@
* \ingroup edtransform
*/
-
#include <string.h>
#include <stddef.h>
#include <ctype.h>
@@ -37,6 +36,7 @@
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
#include "DNA_screen_types.h"
+#include "DNA_space_types.h"
#include "DNA_view3d_types.h"
#include "BLI_math.h"
@@ -53,14 +53,10 @@
#include "BKE_main.h"
#include "BKE_screen.h"
-#include "BLF_translation.h"
+#include "BLT_translation.h"
#include "ED_armature.h"
-#include "RNA_define.h"
-
-#include "UI_interface.h"
-
#include "transform.h"
/* *********************** TransSpace ************************** */
@@ -90,7 +86,7 @@ static bool uniqueOrientationNameCheck(void *arg, const char *name)
static void uniqueOrientationName(ListBase *lb, char *name)
{
- BLI_uniquename_cb(uniqueOrientationNameCheck, lb, CTX_DATA_(BLF_I18NCONTEXT_ID_SCENE, "Space"), '.', name,
+ BLI_uniquename_cb(uniqueOrientationNameCheck, lb, CTX_DATA_(BLT_I18NCONTEXT_ID_SCENE, "Space"), '.', name,
sizeof(((TransformOrientation *)NULL)->name));
}
@@ -149,7 +145,7 @@ static TransformOrientation *createBoneSpace(bContext *C, ReportList *reports,
float mat[3][3];
float normal[3], plane[3];
- getTransformOrientation(C, normal, plane, 0);
+ getTransformOrientation(C, normal, plane);
if (createSpaceNormalTangent(mat, normal, plane) == 0) {
BKE_reports_prepend(reports, "Cannot use zero-length bone");
@@ -169,7 +165,7 @@ static TransformOrientation *createCurveSpace(bContext *C, ReportList *reports,
float mat[3][3];
float normal[3], plane[3];
- getTransformOrientation(C, normal, plane, 0);
+ getTransformOrientation(C, normal, plane);
if (createSpaceNormalTangent(mat, normal, plane) == 0) {
BKE_reports_prepend(reports, "Cannot use zero-length curve");
@@ -191,7 +187,7 @@ static TransformOrientation *createMeshSpace(bContext *C, ReportList *reports,
float normal[3], plane[3];
int type;
- type = getTransformOrientation(C, normal, plane, 0);
+ type = getTransformOrientation(C, normal, plane);
switch (type) {
case ORIENTATION_VERT:
@@ -392,18 +388,15 @@ void BIF_selectTransformOrientationValue(bContext *C, int orientation)
int BIF_countTransformOrientation(const bContext *C)
{
ListBase *transform_spaces = &CTX_data_scene(C)->transform_spaces;
- return BLI_countlist(transform_spaces);
+ return BLI_listbase_count(transform_spaces);
}
-bool applyTransformOrientation(const bContext *C, float mat[3][3], char *r_name)
+bool applyTransformOrientation(const bContext *C, float mat[3][3], char *r_name, int index)
{
- View3D *v3d = CTX_wm_view3d(C);
- int selected_index = (v3d->twmode - V3D_MANIP_CUSTOM);
-
ListBase *transform_spaces = &CTX_data_scene(C)->transform_spaces;
- TransformOrientation *ts = BLI_findlink(transform_spaces, selected_index);
+ TransformOrientation *ts = BLI_findlink(transform_spaces, index);
- BLI_assert(selected_index >= 0);
+ BLI_assert(index >= 0);
if (ts) {
if (r_name) {
@@ -447,7 +440,6 @@ static int count_bone_select(bArmature *arm, ListBase *lb, const bool do_it)
void initTransformOrientation(bContext *C, TransInfo *t)
{
- View3D *v3d = CTX_wm_view3d(C);
Object *ob = CTX_data_active_object(C);
Object *obedit = CTX_data_active_object(C);
@@ -467,7 +459,7 @@ void initTransformOrientation(bContext *C, TransInfo *t)
case V3D_MANIP_NORMAL:
if (obedit || (ob && ob->mode & OB_MODE_POSE)) {
BLI_strncpy(t->spacename, IFACE_("normal"), sizeof(t->spacename));
- ED_getTransformOrientationMatrix(C, t->spacemtx, (v3d->around == V3D_ACTIVE));
+ ED_getTransformOrientationMatrix(C, t->spacemtx, t->around);
break;
}
/* fall-through */ /* we define 'normal' as 'local' in Object mode */
@@ -485,7 +477,9 @@ void initTransformOrientation(bContext *C, TransInfo *t)
break;
case V3D_MANIP_VIEW:
- if (t->ar->regiontype == RGN_TYPE_WINDOW) {
+ if ((t->spacetype == SPACE_VIEW3D) &&
+ (t->ar->regiontype == RGN_TYPE_WINDOW))
+ {
RegionView3D *rv3d = t->ar->regiondata;
float mat[3][3];
@@ -499,7 +493,7 @@ void initTransformOrientation(bContext *C, TransInfo *t)
}
break;
default: /* V3D_MANIP_CUSTOM */
- if (applyTransformOrientation(C, t->spacemtx, t->spacename)) {
+ if (applyTransformOrientation(C, t->spacemtx, t->spacename, t->current_orientation - V3D_MANIP_CUSTOM)) {
/* pass */
}
else {
@@ -590,14 +584,14 @@ static unsigned int bm_mesh_faces_select_get_n(BMesh *bm, BMVert **elems, const
}
#endif
-int getTransformOrientation(const bContext *C, float normal[3], float plane[3], const bool activeOnly)
+int getTransformOrientation_ex(const bContext *C, float normal[3], float plane[3], const short around)
{
Scene *scene = CTX_data_scene(C);
- View3D *v3d = CTX_wm_view3d(C);
Object *obedit = CTX_data_edit_object(C);
Base *base;
Object *ob = OBACT;
int result = ORIENTATION_NONE;
+ const bool activeOnly = (around == V3D_ACTIVE);
zero_v3(normal);
zero_v3(plane);
@@ -723,14 +717,15 @@ int getTransformOrientation(const bContext *C, float normal[3], float plane[3],
/* should never fail */
if (LIKELY(v_pair[0] && v_pair[1])) {
bool v_pair_swap = false;
- /* Logic explained:
+ /**
+ * Logic explained:
*
* - Edges and vert-pairs treated the same way.
- * - Point the Z axis along the edge vector (towards the active vertex).
- * - Point the Y axis outwards (the same direction as the normals).
+ * - Point the Y axis along the edge vector (towards the active vertex).
+ * - Point the Z axis outwards (the same direction as the normals).
*
- * Note that this is at odds a little with face select (and 3 vertices)
- * which point the Z axis along the normal, however in both cases Z is the dominant axis.
+ * \note Z points outwards - along the normal.
+ * take care making changes here, see: T38592, T43708
*/
/* be deterministic where possible and ensure v_pair[0] is active */
@@ -738,7 +733,7 @@ int getTransformOrientation(const bContext *C, float normal[3], float plane[3],
v_pair_swap = true;
}
else if (eed && BM_edge_is_boundary(eed)) {
- /* pradictable direction for boundary edges */
+ /* predictable direction for boundary edges */
if (eed->l->v != v_pair[0]) {
v_pair_swap = true;
}
@@ -748,8 +743,8 @@ int getTransformOrientation(const bContext *C, float normal[3], float plane[3],
SWAP(BMVert *, v_pair[0], v_pair[1]);
}
- add_v3_v3v3(plane, v_pair[0]->no, v_pair[1]->no);
- sub_v3_v3v3(normal, v_pair[0]->co, v_pair[1]->co);
+ add_v3_v3v3(normal, v_pair[0]->no, v_pair[1]->no);
+ sub_v3_v3v3(plane, v_pair[0]->co, v_pair[1]->co);
/* flip the plane normal so we point outwards */
negate_v3(plane);
}
@@ -859,7 +854,7 @@ int getTransformOrientation(const bContext *C, float normal[3], float plane[3],
/* exception */
if (flag) {
float tvec[3];
- if ((v3d->around == V3D_LOCAL) ||
+ if ((around == V3D_LOCAL) ||
ELEM(flag, SEL_F2, SEL_F1 | SEL_F3, SEL_F1 | SEL_F2 | SEL_F3))
{
BKE_nurb_bezt_calc_normal(nu, bezt, tvec);
@@ -960,8 +955,16 @@ int getTransformOrientation(const bContext *C, float normal[3], float plane[3],
/* Vectors from edges don't need the special transpose inverse multiplication */
if (result == ORIENTATION_EDGE) {
+ float tvec[3];
+
mul_mat3_m4_v3(ob->obmat, normal);
mul_mat3_m4_v3(ob->obmat, plane);
+
+ /* align normal to edge direction (so normal is perpendicular to the plane).
+ * 'ORIENTATION_EDGE' will do the other way around.
+ * This has to be done **after** applying obmat, see T45775! */
+ project_v3_v3v3(tvec, normal, plane);
+ sub_v3_v3(normal, tvec);
}
else {
mul_m3_v3(mat, normal);
@@ -1013,6 +1016,7 @@ int getTransformOrientation(const bContext *C, float normal[3], float plane[3],
}
else {
/* we need the one selected object, if its not active */
+ View3D *v3d = CTX_wm_view3d(C);
ob = OBACT;
if (ob && (ob->flag & SELECT)) {
/* pass */
@@ -1038,14 +1042,22 @@ int getTransformOrientation(const bContext *C, float normal[3], float plane[3],
return result;
}
-void ED_getTransformOrientationMatrix(const bContext *C, float orientation_mat[3][3], const bool activeOnly)
+int getTransformOrientation(const bContext *C, float normal[3], float plane[3])
+{
+ /* dummy value, not V3D_ACTIVE and not V3D_LOCAL */
+ short around = V3D_CENTER;
+
+ return getTransformOrientation_ex(C, normal, plane, around);
+}
+
+void ED_getTransformOrientationMatrix(const bContext *C, float orientation_mat[3][3], const short around)
{
float normal[3] = {0.0, 0.0, 0.0};
float plane[3] = {0.0, 0.0, 0.0};
int type;
- type = getTransformOrientation(C, normal, plane, activeOnly);
+ type = getTransformOrientation_ex(C, normal, plane, around);
switch (type) {
case ORIENTATION_NORMAL:
diff --git a/source/blender/editors/transform/transform_snap.c b/source/blender/editors/transform/transform_snap.c
index af563f71376..a7aad427dd6 100644
--- a/source/blender/editors/transform/transform_snap.c
+++ b/source/blender/editors/transform/transform_snap.c
@@ -59,6 +59,7 @@
#include "BKE_anim.h" /* for duplis */
#include "BKE_context.h"
#include "BKE_editmesh.h"
+#include "BKE_sequencer.h"
#include "BKE_main.h"
#include "BKE_tracking.h"
@@ -219,7 +220,7 @@ void drawSnapping(const struct bContext *C, TransInfo *t)
h = (((float)hi) / IMG_SIZE_FALLBACK) * G.sima->zoom * yuser_asp;
cpack(0xFFFFFF);
- glTranslatef(t->tsnap.snapPoint[0], t->tsnap.snapPoint[1], 0.0f);
+ glTranslate2fv(t->tsnap.snapPoint);
//glRectf(0, 0, 1, 1);
@@ -341,39 +342,14 @@ void applyProject(TransInfo *t)
if (t->tsnap.align && (t->flag & T_OBJECT)) {
/* handle alignment as well */
const float *original_normal;
- float axis[3];
float mat[3][3];
- float angle;
- float totmat[3][3], smat[3][3];
- float eul[3], fmat[3][3], quat[4];
- float obmat[3][3];
/* In pose mode, we want to align normals with Y axis of bones... */
original_normal = td->axismtx[2];
- cross_v3_v3v3(axis, original_normal, no);
- angle = saacos(dot_v3v3(original_normal, no));
+ rotation_between_vecs_to_mat3(mat, original_normal, no);
- axis_angle_to_quat(quat, axis, angle);
-
- quat_to_mat3(mat, quat);
-
- mul_m3_m3m3(totmat, mat, td->mtx);
- mul_m3_m3m3(smat, td->smtx, totmat);
-
- /* calculate the total rotatation in eulers */
- add_v3_v3v3(eul, td->ext->irot, td->ext->drot); /* we have to correct for delta rot */
- eulO_to_mat3(obmat, eul, td->ext->rotOrder);
- /* mat = transform, obmat = object rotation */
- mul_m3_m3m3(fmat, smat, obmat);
-
- mat3_to_compatible_eulO(eul, td->ext->rot, td->ext->rotOrder, fmat);
-
- /* correct back for delta rot */
- sub_v3_v3v3(eul, eul, td->ext->drot);
-
- /* and apply */
- copy_v3_v3(td->ext->rot, eul);
+ transform_data_ext_rotate(td, mat, true);
/* TODO support constraints for rotation too? see ElementRotation */
}
@@ -390,10 +366,11 @@ void applyGridAbsolute(TransInfo *t)
float grid_size = 0.0f;
GearsType grid_action;
TransData *td;
- float imat[4][4];
+ float (*obmat)[4] = NULL;
+ bool use_obmat = false;
int i;
- if (!(activeSnap(t) && (t->tsnap.mode == SCE_SNAP_MODE_GRID)))
+ if (!(activeSnap(t) && (ELEM(t->tsnap.mode, SCE_SNAP_MODE_INCREMENT, SCE_SNAP_MODE_GRID))))
return;
grid_action = BIG_GEARS;
@@ -401,9 +378,9 @@ void applyGridAbsolute(TransInfo *t)
grid_action = SMALL_GEARS;
switch (grid_action) {
- case NO_GEARS: grid_size = t->snap[0]; break;
- case BIG_GEARS: grid_size = t->snap[1]; break;
- case SMALL_GEARS: grid_size = t->snap[2]; break;
+ case NO_GEARS: grid_size = t->snap_spatial[0]; break;
+ case BIG_GEARS: grid_size = t->snap_spatial[1]; break;
+ case SMALL_GEARS: grid_size = t->snap_spatial[2]; break;
}
/* early exit on unusable grid size */
if (grid_size == 0.0f)
@@ -411,7 +388,8 @@ void applyGridAbsolute(TransInfo *t)
if (t->flag & (T_EDIT | T_POSE)) {
Object *ob = t->obedit ? t->obedit : t->poseobj;
- invert_m4_m4(imat, ob->obmat);
+ obmat = ob->obmat;
+ use_obmat = true;
}
for (i = 0, td = t->data; i < t->total; i++, td++) {
@@ -427,9 +405,8 @@ void applyGridAbsolute(TransInfo *t)
continue;
copy_v3_v3(iloc, td->loc);
- if (t->flag & (T_EDIT | T_POSE)) {
- Object *ob = t->obedit ? t->obedit : t->poseobj;
- mul_m4_v3(ob->obmat, iloc);
+ if (use_obmat) {
+ mul_m4_v3(obmat, iloc);
}
else if (t->flag & T_OBJECT) {
td->ob->recalc |= OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME;
@@ -438,11 +415,11 @@ void applyGridAbsolute(TransInfo *t)
}
mul_v3_v3fl(loc, iloc, 1.0f / grid_size);
- loc[0] = floorf(loc[0]);
- loc[1] = floorf(loc[1]);
- loc[2] = floorf(loc[2]);
+ loc[0] = roundf(loc[0]);
+ loc[1] = roundf(loc[1]);
+ loc[2] = roundf(loc[2]);
mul_v3_fl(loc, grid_size);
-
+
sub_v3_v3v3(tvec, loc, iloc);
mul_m3_v3(td->smtx, tvec);
add_v3_v3(td->loc, tvec);
@@ -460,7 +437,7 @@ void applySnapping(TransInfo *t, float *vec)
t->tsnap.applySnap(t, vec);
}
- else if ((t->tsnap.mode != SCE_SNAP_MODE_INCREMENT) && activeSnap(t)) {
+ else if (!ELEM(t->tsnap.mode, SCE_SNAP_MODE_INCREMENT, SCE_SNAP_MODE_GRID) && activeSnap(t)) {
double current = PIL_check_seconds_timer();
// Time base quirky code to go around findnearest slowness
@@ -583,6 +560,10 @@ static void initSnappingMode(TransInfo *t)
t->tsnap.mode = SCE_SNAP_MODE_INCREMENT;
}
}
+ else if (t->spacetype == SPACE_SEQ) {
+ /* We do our own snapping currently, so nothing here */
+ t->tsnap.mode = SCE_SNAP_MODE_GRID; /* Dummy, should we rather add a NOP mode? */
+ }
else {
/* Always grid outside of 3D view */
t->tsnap.mode = SCE_SNAP_MODE_INCREMENT;
@@ -638,6 +619,11 @@ void initSnapping(TransInfo *t, wmOperator *op)
t->tsnap.snap_self = !((t->settings->snap_flag & SCE_SNAP_NO_SELF) != 0);
t->tsnap.peel = ((t->settings->snap_flag & SCE_SNAP_PROJECT) != 0);
}
+
+ /* for now only 3d view (others can be added if we want) */
+ if (t->spacetype == SPACE_VIEW3D) {
+ t->tsnap.snap_spatial_grid = ((t->settings->snap_flag & SCE_SNAP_ABS_GRID) != 0);
+ }
}
t->tsnap.target = snap_target;
@@ -824,14 +810,18 @@ static void ApplySnapRotation(TransInfo *t, float *value)
static void ApplySnapResize(TransInfo *t, float vec[3])
{
+ float dist;
+
if (t->tsnap.target == SCE_SNAP_TARGET_CLOSEST) {
- vec[0] = vec[1] = vec[2] = t->tsnap.dist;
+ dist = t->tsnap.dist;
}
else {
float point[3];
getSnapPoint(t, point);
- vec[0] = vec[1] = vec[2] = ResizeBetween(t, t->tsnap.snapTarget, point);
+ dist = ResizeBetween(t, t->tsnap.snapTarget, point);
}
+
+ copy_v3_fl(vec, dist);
}
/********************** DISTANCE **************************/
@@ -843,16 +833,10 @@ static float TranslationBetween(TransInfo *UNUSED(t), const float p1[3], const f
static float RotationBetween(TransInfo *t, const float p1[3], const float p2[3])
{
- float angle, start[3], end[3], center[3];
-
- copy_v3_v3(center, t->center);
- if (t->flag & (T_EDIT | T_POSE)) {
- Object *ob = t->obedit ? t->obedit : t->poseobj;
- mul_m4_v3(ob->obmat, center);
- }
+ float angle, start[3], end[3];
- sub_v3_v3v3(start, p1, center);
- sub_v3_v3v3(end, p2, center);
+ sub_v3_v3v3(start, p1, t->center_global);
+ sub_v3_v3v3(end, p2, t->center_global);
// Angle around a constraint axis (error prone, will need debug)
if (t->con.applyRot != NULL && (t->con.mode & CON_APPLY)) {
@@ -899,17 +883,13 @@ static float RotationBetween(TransInfo *t, const float p1[3], const float p2[3])
static float ResizeBetween(TransInfo *t, const float p1[3], const float p2[3])
{
- float d1[3], d2[3], center[3], len_d1;
-
- copy_v3_v3(center, t->center);
- if (t->flag & (T_EDIT | T_POSE)) {
- Object *ob = t->obedit ? t->obedit : t->poseobj;
- mul_m4_v3(ob->obmat, center);
- }
+ float d1[3], d2[3], len_d1;
- sub_v3_v3v3(d1, p1, center);
- sub_v3_v3v3(d2, p2, center);
+ sub_v3_v3v3(d1, p1, t->center_global);
+ sub_v3_v3v3(d2, p2, t->center_global);
+ project_v3_v3v3(d1, d1, d2);
+
if (t->con.applyRot != NULL && (t->con.mode & CON_APPLY)) {
mul_m3_v3(t->con.pmtx, d1);
mul_m3_v3(t->con.pmtx, d2);
@@ -955,9 +935,9 @@ static void CalcSnapGeometry(TransInfo *t, float *UNUSED(vec))
// last_p = LAST_SNAP_POINT;
// }
// else
-// {
+ {
last_p = t->tsnap.snapPoint;
-// }
+ }
for (p1 = depth_peels.first; p1; p1 = p1->next) {
@@ -1001,7 +981,7 @@ static void CalcSnapGeometry(TransInfo *t, float *UNUSED(vec))
break;
}
- new_dist = len_v3v3(last_p, vec);
+ new_dist = len_squared_v3v3(last_p, vec);
if (new_dist < max_dist) {
copy_v3_v3(p, vec);
@@ -1022,6 +1002,7 @@ static void CalcSnapGeometry(TransInfo *t, float *UNUSED(vec))
BLI_freelistN(&depth_peels);
}
else {
+ zero_v3(no); /* objects won't set this */
found = snapObjectsTransform(t, mval, &dist_px, loc, no, t->tsnap.modeSelect);
}
@@ -1047,14 +1028,13 @@ static void CalcSnapGeometry(TransInfo *t, float *UNUSED(vec))
else if (t->spacetype == SPACE_IMAGE && t->obedit != NULL && t->obedit->type == OB_MESH) {
/* same as above but for UV's */
Image *ima = ED_space_image(t->sa->spacedata.first);
- float aspx, aspy, co[2];
+ float co[2];
UI_view2d_region_to_view(&t->ar->v2d, t->mval[0], t->mval[1], &co[0], &co[1]);
if (ED_uvedit_nearest_uv(t->scene, t->obedit, ima, co, t->tsnap.snapPoint)) {
- ED_space_image_get_uv_aspect(t->sa->spacedata.first, &aspx, &aspy);
- t->tsnap.snapPoint[0] *= aspx;
- t->tsnap.snapPoint[1] *= aspy;
+ t->tsnap.snapPoint[0] *= t->aspect[0];
+ t->tsnap.snapPoint[1] *= t->aspect[1];
t->tsnap.status |= POINT_INIT;
}
@@ -1115,13 +1095,7 @@ static void TargetSnapCenter(TransInfo *t)
{
/* Only need to calculate once */
if ((t->tsnap.status & TARGET_INIT) == 0) {
- copy_v3_v3(t->tsnap.snapTarget, t->center);
-
- if (t->flag & (T_EDIT | T_POSE)) {
- Object *ob = t->obedit ? t->obedit : t->poseobj;
- mul_m4_v3(ob->obmat, t->tsnap.snapTarget);
- }
-
+ copy_v3_v3(t->tsnap.snapTarget, t->center_global);
TargetSnapOffset(t, NULL);
t->tsnap.status |= TARGET_INIT;
@@ -1402,11 +1376,8 @@ static bool snapArmature(short snap_mode, ARegion *ar, Object *ob, bArmature *ar
invert_m4_m4(imat, obmat);
- copy_v3_v3(ray_start_local, ray_start);
- copy_v3_v3(ray_normal_local, ray_normal);
-
- mul_m4_v3(imat, ray_start_local);
- mul_mat3_m4_v3(imat, ray_normal_local);
+ mul_v3_m4v3(ray_start_local, imat, ray_start);
+ mul_v3_mat3_m4v3(ray_normal_local, imat, ray_normal);
if (arm->edbo) {
EditBone *eBone;
@@ -1543,8 +1514,7 @@ static bool snapDerivedMesh(short snap_mode, ARegion *ar, Object *ob, DerivedMes
float ray_start_local[3], ray_normal_local[3], local_scale, len_diff = TRANSFORM_DIST_MAX_RAY;
invert_m4_m4(imat, obmat);
- copy_m3_m4(timat, imat);
- transpose_m3(timat);
+ transpose_m3_m4(timat, imat);
copy_v3_v3(ray_start_local, ray_start);
copy_v3_v3(ray_normal_local, ray_normal);
@@ -1557,8 +1527,17 @@ static bool snapDerivedMesh(short snap_mode, ARegion *ar, Object *ob, DerivedMes
if (do_bb) {
BoundBox *bb = BKE_object_boundbox_get(ob);
- if (!BKE_boundbox_ray_hit_check(bb, ray_start_local, ray_normal_local, &len_diff)) {
- return retval;
+
+ if (bb) {
+ BoundBox bb_temp;
+
+ /* We cannot aford a bbox with some null dimension, which may happen in some cases...
+ * Threshold is rather high, but seems to be needed to get good behavior, see T46099. */
+ bb = BKE_boundbox_ensure_minimum_dimensions(bb, &bb_temp, 1e-1f);
+
+ if (!BKE_boundbox_ray_hit_check(bb, ray_start_local, ray_normal_local, &len_diff)) {
+ return retval;
+ }
}
}
else if (do_ray_start_correction) {
@@ -1570,7 +1549,7 @@ static bool snapDerivedMesh(short snap_mode, ARegion *ar, Object *ob, DerivedMes
len_diff = 0.0f; /* In case BVHTree would fail for some reason... */
treeData.em_evil = em;
- bvhtree_from_mesh_faces(&treeData, dm, 0.0f, 2, 6);
+ bvhtree_from_mesh_looptri(&treeData, dm, 0.0f, 2, 6);
if (treeData.tree != NULL) {
nearest.index = -1;
nearest.dist_sq = FLT_MAX;
@@ -1612,7 +1591,7 @@ static bool snapDerivedMesh(short snap_mode, ARegion *ar, Object *ob, DerivedMes
}
treeData.em_evil = em;
- bvhtree_from_mesh_faces(&treeData, dm, 0.0f, 4, 6);
+ bvhtree_from_mesh_looptri(&treeData, dm, 0.0f, 4, 6);
hit.index = -1;
hit.dist = *r_depth;
@@ -1765,11 +1744,8 @@ static bool snapEmpty(short snap_mode, ARegion *ar, Object *ob, float obmat[4][4
invert_m4_m4(imat, obmat);
- copy_v3_v3(ray_start_local, ray_start);
- copy_v3_v3(ray_normal_local, ray_normal);
-
- mul_m4_v3(imat, ray_start_local);
- mul_mat3_m4_v3(imat, ray_normal_local);
+ mul_v3_m4v3(ray_start_local, imat, ray_start);
+ mul_v3_mat3_m4v3(ray_normal_local, imat, ray_normal);
switch (snap_mode) {
case SCE_SNAP_MODE_VERTEX:
@@ -1887,8 +1863,16 @@ static bool snapObject(Scene *scene, short snap_mode, ARegion *ar, Object *ob, f
do_bb = false;
}
else {
+ /* in this case we want the mesh from the editmesh, avoids stale data. see: T45978.
+ * still set the 'em' to NULL, since we only want the 'dm'. */
+ em = BKE_editmesh_from_object(ob);
+ if (em) {
+ editbmesh_get_derived_cage_and_final(scene, ob, em, CD_MASK_BAREMESH, &dm);
+ }
+ else {
+ dm = mesh_get_derived_final(scene, ob, CD_MASK_BAREMESH);
+ }
em = NULL;
- dm = mesh_get_derived_final(scene, ob, CD_MASK_BAREMESH);
}
retval = snapDerivedMesh(snap_mode, ar, ob, dm, em, obmat, ray_start, ray_normal, ray_origin, mval, r_loc, r_no, r_dist_px, r_depth, do_bb);
@@ -1956,21 +1940,32 @@ static bool snapObjectsRay(Scene *scene, short snap_mode, Base *base_act, View3D
(ELEM(mode, SNAP_ALL, SNAP_NOT_OBEDIT) && base != base_act)))
{
Object *ob = base->object;
-
+ Object *ob_snap = ob;
+ bool use_obedit = false;
+
+ /* for linked objects, use the same object but a different matrix */
+ if (obedit && ob->data == obedit->data) {
+ use_obedit = true;
+ ob_snap = obedit;
+ }
+
if (ob->transflag & OB_DUPLI) {
DupliObject *dupli_ob;
ListBase *lb = object_duplilist(G.main->eval_ctx, scene, ob);
for (dupli_ob = lb->first; dupli_ob; dupli_ob = dupli_ob->next) {
- retval |= snapObject(scene, snap_mode, ar, dupli_ob->ob, dupli_ob->mat, false,
+ bool use_obedit_dupli = (obedit && dupli_ob->ob->data == obedit->data);
+ Object *dupli_snap = (use_obedit_dupli) ? obedit : dupli_ob->ob;
+
+ retval |= snapObject(scene, snap_mode, ar, dupli_snap, dupli_ob->mat, use_obedit_dupli,
r_ob, r_obmat,
ray_start, ray_normal, ray_origin, mval, r_loc, r_no, r_dist_px, r_ray_dist);
}
free_object_duplilist(lb);
}
-
- retval |= snapObject(scene, snap_mode, ar, ob, ob->obmat, false,
+
+ retval |= snapObject(scene, snap_mode, ar, ob_snap, ob->obmat, use_obedit,
r_ob, r_obmat,
ray_start, ray_normal, ray_origin, mval, r_loc, r_no, r_dist_px, r_ray_dist);
}
@@ -1997,8 +1992,20 @@ static bool snapObjects(Scene *scene, short snap_mode, Base *base_act, View3D *v
bool snapObjectsTransform(TransInfo *t, const float mval[2], float *r_dist_px, float r_loc[3], float r_no[3], SnapMode mode)
{
float ray_dist = TRANSFORM_DIST_MAX_RAY;
- return snapObjects(t->scene, t->scene->toolsettings->snap_mode, t->scene->basact, t->view, t->ar, t->obedit,
- mval, r_dist_px, r_loc, r_no, &ray_dist, mode);
+ Object *obedit = NULL;
+ Base *base_act = NULL;
+
+ if (t->flag & T_EDIT) {
+ obedit = t->obedit;
+ }
+
+ if ((t->options & CTX_GPENCIL_STROKES) == 0) {
+ base_act = t->scene->basact;
+ }
+
+ return snapObjects(
+ t->scene, t->scene->toolsettings->snap_mode, base_act, t->view, t->ar, obedit,
+ mval, r_dist_px, r_loc, r_no, &ray_dist, mode);
}
bool snapObjectsContext(bContext *C, const float mval[2], float *r_dist_px, float r_loc[3], float r_no[3], SnapMode mode)
@@ -2085,110 +2092,108 @@ static void addDepthPeel(ListBase *depth_peels, float depth, float p[3], float n
peel->flag = 0;
}
-static bool peelDerivedMesh(Object *ob, DerivedMesh *dm, float obmat[4][4],
- const float ray_start[3], const float ray_normal[3], const float UNUSED(mval[2]),
- ListBase *depth_peels)
+struct PeelRayCast_Data {
+ BVHTreeFromMesh bvhdata;
+
+ /* internal vars for adding peel */
+ Object *ob;
+ const float (*obmat)[4];
+ const float (*timat)[3];
+
+ const float *ray_start; /* globalspace */
+
+ const MLoopTri *looptri;
+ const float (*polynors)[3]; /* optional, can be NULL */
+
+ /* output list */
+ ListBase *depth_peels;
+};
+
+static void peelRayCast_cb(void *userdata, int index, const BVHTreeRay *ray, BVHTreeRayHit *hit)
+{
+ struct PeelRayCast_Data *data = userdata;
+
+ data->bvhdata.raycast_callback(&data->bvhdata, index, ray, hit);
+
+ if (hit->index != -1) {
+ /* get all values in worldspace */
+ float location[3], normal[3];
+ float depth;
+
+ /* worldspace location */
+ mul_v3_m4v3(location, (float (*)[4])data->obmat, hit->co);
+ depth = len_v3v3(location, data->ray_start);
+
+ /* worldspace normal */
+ copy_v3_v3(normal, data->polynors ? data->polynors[data->looptri[hit->index].poly] : hit->no);
+ mul_m3_v3((float (*)[3])data->timat, normal);
+ normalize_v3(normal);
+
+ addDepthPeel(data->depth_peels, depth, location, normal, data->ob);
+ }
+}
+
+static bool peelDerivedMesh(
+ Object *ob, DerivedMesh *dm, BMEditMesh *em, float obmat[4][4],
+ const float ray_start[3], const float ray_normal[3], const float UNUSED(mval[2]),
+ ListBase *depth_peels)
{
bool retval = false;
int totvert = dm->getNumVerts(dm);
- int totface = dm->getNumTessFaces(dm);
if (totvert > 0) {
+ const MLoopTri *looptri = dm->getLoopTriArray(dm);
+ const int looptri_num = dm->getNumLoopTri(dm);
float imat[4][4];
float timat[3][3]; /* transpose inverse matrix for normals */
float ray_start_local[3], ray_normal_local[3];
- int test = 1;
+ bool test = true;
invert_m4_m4(imat, obmat);
- copy_m3_m4(timat, imat);
- transpose_m3(timat);
-
- copy_v3_v3(ray_start_local, ray_start);
- copy_v3_v3(ray_normal_local, ray_normal);
-
- mul_m4_v3(imat, ray_start_local);
- mul_mat3_m4_v3(imat, ray_normal_local);
+ transpose_m3_m4(timat, imat);
+ mul_v3_m4v3(ray_start_local, imat, ray_start);
+ mul_v3_mat3_m4v3(ray_normal_local, imat, ray_normal);
/* If number of vert is more than an arbitrary limit,
* test against boundbox first
* */
- if (totface > 16) {
- struct BoundBox *bb = BKE_object_boundbox_get(ob);
- test = BKE_boundbox_ray_hit_check(bb, ray_start_local, ray_normal_local, NULL);
- }
-
- if (test == 1) {
- MVert *verts = dm->getVertArray(dm);
- MFace *faces = dm->getTessFaceArray(dm);
- int i;
-
- for (i = 0; i < totface; i++) {
- MFace *f = faces + i;
- float lambda;
- int result;
-
-
- result = isect_ray_tri_threshold_v3(ray_start_local, ray_normal_local, verts[f->v1].co, verts[f->v2].co, verts[f->v3].co, &lambda, NULL, 0.001);
-
- if (result) {
- float location[3], normal[3];
- float intersect[3];
- float new_depth;
-
- copy_v3_v3(intersect, ray_normal_local);
- mul_v3_fl(intersect, lambda);
- add_v3_v3(intersect, ray_start_local);
-
- copy_v3_v3(location, intersect);
-
- if (f->v4)
- normal_quad_v3(normal, verts[f->v1].co, verts[f->v2].co, verts[f->v3].co, verts[f->v4].co);
- else
- normal_tri_v3(normal, verts[f->v1].co, verts[f->v2].co, verts[f->v3].co);
+ if (looptri_num > 16) {
+ BoundBox *bb = BKE_object_boundbox_get(ob);
- mul_m4_v3(obmat, location);
-
- new_depth = len_v3v3(location, ray_start);
-
- mul_m3_v3(timat, normal);
- normalize_v3(normal);
+ if (bb) {
+ BoundBox bb_temp;
- addDepthPeel(depth_peels, new_depth, location, normal, ob);
- }
-
- if (f->v4 && result == 0) {
- result = isect_ray_tri_threshold_v3(ray_start_local, ray_normal_local, verts[f->v3].co, verts[f->v4].co, verts[f->v1].co, &lambda, NULL, 0.001);
-
- if (result) {
- float location[3], normal[3];
- float intersect[3];
- float new_depth;
-
- copy_v3_v3(intersect, ray_normal_local);
- mul_v3_fl(intersect, lambda);
- add_v3_v3(intersect, ray_start_local);
-
- copy_v3_v3(location, intersect);
-
- if (f->v4)
- normal_quad_v3(normal, verts[f->v1].co, verts[f->v2].co, verts[f->v3].co, verts[f->v4].co);
- else
- normal_tri_v3(normal, verts[f->v1].co, verts[f->v2].co, verts[f->v3].co);
+ /* We cannot aford a bbox with some null dimension, which may happen in some cases...
+ * Threshold is rather high, but seems to be needed to get good behavior, see T46099. */
+ bb = BKE_boundbox_ensure_minimum_dimensions(bb, &bb_temp, 1e-1f);
- mul_m4_v3(obmat, location);
-
- new_depth = len_v3v3(location, ray_start);
-
- mul_m3_v3(timat, normal);
- normalize_v3(normal);
-
- addDepthPeel(depth_peels, new_depth, location, normal, ob);
- }
- }
+ test = BKE_boundbox_ray_hit_check(bb, ray_start_local, ray_normal_local, NULL);
}
}
+
+ if (test == true) {
+ struct PeelRayCast_Data data;
+
+ data.bvhdata.em_evil = em;
+ bvhtree_from_mesh_looptri(&data.bvhdata, dm, 0.0f, 4, 6);
+
+ if (data.bvhdata.tree != NULL) {
+ data.ob = ob;
+ data.obmat = (const float (*)[4])obmat;
+ data.timat = (const float (*)[3])timat;
+ data.ray_start = ray_start;
+ data.looptri = looptri;
+ data.polynors = dm->getPolyDataArray(dm, CD_NORMAL); /* can be NULL */
+ data.depth_peels = depth_peels;
+
+ BLI_bvhtree_ray_cast_all(data.bvhdata.tree, ray_start_local, ray_normal_local, 0.0f,
+ peelRayCast_cb, &data);
+ }
+
+ free_bvhtree_from_mesh(&data.bvhdata);
+ }
}
return retval;
@@ -2224,13 +2229,13 @@ static bool peelObjects(Scene *scene, View3D *v3d, ARegion *ar, Object *obedit,
if (dob != obedit) {
dm = mesh_get_derived_final(scene, dob, CD_MASK_BAREMESH);
- val = peelDerivedMesh(dob, dm, dob->obmat, ray_start, ray_normal, mval, depth_peels);
+ val = peelDerivedMesh(dob, dm, NULL, dob->obmat, ray_start, ray_normal, mval, depth_peels);
}
else {
em = BKE_editmesh_from_object(dob);
dm = editbmesh_get_derived_cage(scene, obedit, em, CD_MASK_BAREMESH);
- val = peelDerivedMesh(dob, dm, dob->obmat, ray_start, ray_normal, mval, depth_peels);
+ val = peelDerivedMesh(dob, dm, em, dob->obmat, ray_start, ray_normal, mval, depth_peels);
}
retval = retval || val;
@@ -2248,14 +2253,14 @@ static bool peelObjects(Scene *scene, View3D *v3d, ARegion *ar, Object *obedit,
if (ob != obedit && ((mode == SNAP_NOT_SELECTED && (base->flag & (SELECT | BA_WAS_SEL)) == 0) || ELEM(mode, SNAP_ALL, SNAP_NOT_OBEDIT))) {
DerivedMesh *dm = mesh_get_derived_final(scene, ob, CD_MASK_BAREMESH);
- val = peelDerivedMesh(ob, dm, ob->obmat, ray_start, ray_normal, mval, depth_peels);
+ val = peelDerivedMesh(ob, dm, NULL, ob->obmat, ray_start, ray_normal, mval, depth_peels);
dm->release(dm);
}
else if (ob == obedit && mode != SNAP_NOT_OBEDIT) {
BMEditMesh *em = BKE_editmesh_from_object(ob);
DerivedMesh *dm = editbmesh_get_derived_cage(scene, obedit, em, CD_MASK_BAREMESH);
- val = peelDerivedMesh(ob, dm, ob->obmat, ray_start, ray_normal, mval, depth_peels);
+ val = peelDerivedMesh(ob, dm, NULL, ob->obmat, ray_start, ray_normal, mval, depth_peels);
dm->release(dm);
}
@@ -2265,7 +2270,7 @@ static bool peelObjects(Scene *scene, View3D *v3d, ARegion *ar, Object *obedit,
}
}
- BLI_sortlist(depth_peels, cmpPeel);
+ BLI_listbase_sort(depth_peels, cmpPeel);
removeDoublesPeel(depth_peels);
return retval;
@@ -2396,7 +2401,7 @@ bool snapNodesContext(bContext *C, const int mval[2], float *r_dist_px, float r_
/*================================================================*/
-static void applyGridIncrement(TransInfo *t, float *val, int max_index, float fac[3], GearsType action);
+static void applyGridIncrement(TransInfo *t, float *val, int max_index, const float fac[3], GearsType action);
void snapGridIncrementAction(TransInfo *t, float *val, GearsType action)
@@ -2415,8 +2420,8 @@ void snapGridIncrement(TransInfo *t, float *val)
{
GearsType action;
- // Only do something if using Snap to Grid
- if (t->tsnap.mode != SCE_SNAP_MODE_INCREMENT)
+ /* only do something if using absolute or incremental grid snapping */
+ if (!ELEM(t->tsnap.mode, SCE_SNAP_MODE_INCREMENT, SCE_SNAP_MODE_GRID))
return;
action = activeSnap(t) ? BIG_GEARS : NO_GEARS;
@@ -2428,35 +2433,77 @@ void snapGridIncrement(TransInfo *t, float *val)
snapGridIncrementAction(t, val, action);
}
+void snapSequenceBounds(TransInfo *t, const int mval[2])
+{
+ float xmouse, ymouse;
+ int frame;
+ int mframe;
+ TransSeq *ts = t->customData;
+ /* reuse increment, strictly speaking could be another snap mode, but leave as is */
+ if (!(t->modifiers & MOD_SNAP_INVERT))
+ return;
+
+ /* convert to frame range */
+ UI_view2d_region_to_view(&t->ar->v2d, mval[0], mval[1], &xmouse, &ymouse);
+ mframe = iroundf(xmouse);
+ /* now find the closest sequence */
+ frame = BKE_sequencer_find_next_prev_edit(t->scene, mframe, SEQ_SIDE_BOTH, true, false, true);
-static void applyGridIncrement(TransInfo *t, float *val, int max_index, float fac[3], GearsType action)
+ if (!ts->snap_left)
+ frame = frame - (ts->max - ts->min);
+
+ t->values[0] = frame - ts->min;
+}
+
+static void applyGridIncrement(TransInfo *t, float *val, int max_index, const float fac[3], GearsType action)
{
+ float asp_local[3] = {1, 1, 1};
+ const bool use_aspect = ELEM(t->mode, TFM_TRANSLATION);
+ const float *asp = use_aspect ? t->aspect : asp_local;
int i;
- float asp[3] = {1.0f, 1.0f, 1.0f}; // TODO: Remove hard coded limit here (3)
- if (max_index > 2) {
- printf("applyGridIncrement: invalid index %d, clamping\n", max_index);
- max_index = 2;
- }
+ BLI_assert(ELEM(t->tsnap.mode, SCE_SNAP_MODE_INCREMENT, SCE_SNAP_MODE_GRID));
+ BLI_assert(max_index <= 2);
- // Early bailing out if no need to snap
- if (fac[action] == 0.0f)
+ /* Early bailing out if no need to snap */
+ if (fac[action] == 0.0f) {
return;
-
- /* evil hack - snapping needs to be adapted for image aspect ratio */
- if ((t->spacetype == SPACE_IMAGE) && (t->mode == TFM_TRANSLATION)) {
- if (t->options & CTX_MASK) {
- ED_space_image_get_aspect(t->sa->spacedata.first, asp, asp + 1);
- }
- else if (t->options & CTX_PAINT_CURVE) {
- asp[0] = asp[1] = 1.0;
- }
- else {
- ED_space_image_get_uv_aspect(t->sa->spacedata.first, asp, asp + 1);
+ }
+
+ if (use_aspect) {
+ /* custom aspect for fcurve */
+ if (t->spacetype == SPACE_IPO) {
+ View2D *v2d = &t->ar->v2d;
+ View2DGrid *grid;
+ SpaceIpo *sipo = t->sa->spacedata.first;
+ int unity = V2D_UNIT_VALUES;
+ int unitx = (sipo->flag & SIPO_DRAWTIME) ? V2D_UNIT_SECONDS : V2D_UNIT_FRAMESCALE;
+
+ /* grid */
+ grid = UI_view2d_grid_calc(t->scene, v2d, unitx, V2D_GRID_NOCLAMP, unity, V2D_GRID_NOCLAMP, t->ar->winx, t->ar->winy);
+
+ UI_view2d_grid_size(grid, &asp_local[0], &asp_local[1]);
+ UI_view2d_grid_free(grid);
+
+ asp = asp_local;
}
}
- for (i = 0; i <= max_index; i++) {
- val[i] = fac[action] * asp[i] * (float)floor(val[i] / (fac[action] * asp[i]) + 0.5f);
+ /* absolute snapping on grid based on global center */
+ if ((t->tsnap.snap_spatial_grid) && (t->mode == TFM_TRANSLATION)) {
+ for (i = 0; i <= max_index; i++) {
+ /* do not let unconstrained axis jump to absolute grid increments */
+ if (!(t->con.mode & CON_APPLY) || t->con.mode & (CON_AXIS0 << i)) {
+ const float iter_fac = fac[action] * asp[i];
+ val[i] = iter_fac * roundf((val[i] + t->center_global[i]) / iter_fac) - t->center_global[i];
+ }
+ }
+ }
+ else {
+ /* relative snapping in fixed increments */
+ for (i = 0; i <= max_index; i++) {
+ const float iter_fac = fac[action] * asp[i];
+ val[i] = iter_fac * roundf(val[i] / iter_fac);
+ }
}
}
diff --git a/source/blender/editors/util/CMakeLists.txt b/source/blender/editors/util/CMakeLists.txt
index 4400870f1b8..7de788dca56 100644
--- a/source/blender/editors/util/CMakeLists.txt
+++ b/source/blender/editors/util/CMakeLists.txt
@@ -20,14 +20,17 @@
set(INC
../include
- ../../blenfont
../../blenkernel
../../blenlib
+ ../../blentranslation
../../bmesh
+ ../../imbuf
+ ../../gpu
../../makesdna
../../makesrna
../../windowmanager
../../../../intern/guardedalloc
+ ../../../../intern/glew-mx
)
set(INC_SYS
@@ -67,6 +70,7 @@ set(SRC
../include/ED_node.h
../include/ED_numinput.h
../include/ED_object.h
+ ../include/ED_outliner.h
../include/ED_paint.h
../include/ED_particle.h
../include/ED_physics.h
@@ -91,7 +95,7 @@ set(SRC
../include/UI_view2d.h
)
-add_definitions(-DGLEW_STATIC)
+add_definitions(${GL_DEFINITIONS})
if(WITH_INTERNATIONAL)
add_definitions(-DWITH_INTERNATIONAL)
diff --git a/source/blender/editors/util/SConscript b/source/blender/editors/util/SConscript
index 0876fe48c91..7d9991e6483 100644
--- a/source/blender/editors/util/SConscript
+++ b/source/blender/editors/util/SConscript
@@ -28,16 +28,20 @@
Import ('env')
sources = env.Glob('*.c')
-defs = [ 'GLEW_STATIC' ]
+
+defs = []
+defs += env['BF_GL_DEFINITIONS']
incs = [
'#/intern/guardedalloc',
- '#/extern/glew/include',
+ env['BF_GLEW_INC'],
+ '#/intern/glew-mx',
'../include',
- '../../blenfont',
'../../blenkernel',
'../../blenlib',
+ '../../blentranslation',
'../../bmesh',
+ '../../gpu',
'../../makesdna',
'../../makesrna',
'../../windowmanager',
diff --git a/source/blender/editors/util/ed_transverts.c b/source/blender/editors/util/ed_transverts.c
index 104b628c25a..b0970cdfd48 100644
--- a/source/blender/editors/util/ed_transverts.c
+++ b/source/blender/editors/util/ed_transverts.c
@@ -310,7 +310,7 @@ void ED_transverts_create_from_obedit(TransVertStore *tvs, Object *obedit, const
}
else if (obedit->type == OB_ARMATURE) {
bArmature *arm = obedit->data;
- int totmalloc = BLI_countlist(arm->edbo);
+ int totmalloc = BLI_listbase_count(arm->edbo);
totmalloc *= 2; /* probably overkill but bones can have 2 trans verts each */
@@ -318,9 +318,9 @@ void ED_transverts_create_from_obedit(TransVertStore *tvs, Object *obedit, const
for (ebo = arm->edbo->first; ebo; ebo = ebo->next) {
if (ebo->layer & arm->layer) {
- short tipsel = (ebo->flag & BONE_TIPSEL);
- short rootsel = (ebo->flag & BONE_ROOTSEL);
- short rootok = (!(ebo->parent && (ebo->flag & BONE_CONNECTED) && (ebo->parent->flag & BONE_TIPSEL)));
+ const bool tipsel = (ebo->flag & BONE_TIPSEL) != 0;
+ const bool rootsel = (ebo->flag & BONE_ROOTSEL) != 0;
+ const bool rootok = (!(ebo->parent && (ebo->flag & BONE_CONNECTED) && (ebo->parent->flag & BONE_TIPSEL)));
if ((tipsel && rootsel) || (rootsel)) {
/* Don't add the tip (unless mode & TM_ALL_JOINTS, for getting all joints),
@@ -441,7 +441,7 @@ void ED_transverts_create_from_obedit(TransVertStore *tvs, Object *obedit, const
}
else if (obedit->type == OB_MBALL) {
MetaBall *mb = obedit->data;
- int totmalloc = BLI_countlist(mb->editelems);
+ int totmalloc = BLI_listbase_count(mb->editelems);
tv = tvs->transverts = MEM_callocN(totmalloc * sizeof(TransVert), __func__);
diff --git a/source/blender/editors/util/ed_util.c b/source/blender/editors/util/ed_util.c
index 56b12fcdcda..f727f48e993 100644
--- a/source/blender/editors/util/ed_util.c
+++ b/source/blender/editors/util/ed_util.c
@@ -38,6 +38,7 @@
#include "DNA_mesh_types.h"
#include "DNA_object_types.h"
#include "DNA_screen_types.h"
+#include "DNA_space_types.h"
#include "DNA_scene_types.h"
#include "DNA_packedFile_types.h"
@@ -48,7 +49,7 @@
#include "BIF_gl.h"
#include "BIF_glutil.h"
-#include "BLF_translation.h"
+#include "BLT_translation.h"
#include "BKE_context.h"
#include "BKE_global.h"
@@ -58,9 +59,12 @@
#include "BKE_paint.h"
#include "ED_armature.h"
+#include "ED_buttons.h"
#include "ED_image.h"
#include "ED_mesh.h"
+#include "ED_node.h"
#include "ED_object.h"
+#include "ED_outliner.h"
#include "ED_paint.h"
#include "ED_space_api.h"
#include "ED_util.h"
@@ -107,7 +111,7 @@ void ED_editors_init(bContext *C)
/* image editor paint mode */
if (sce) {
- ED_space_image_paint_update(wm, sce->toolsettings);
+ ED_space_image_paint_update(wm, sce);
}
SWAP(int, reports->flag, reports_flag_prev);
@@ -153,19 +157,20 @@ void ED_editors_exit(bContext *C)
/* flush any temp data from object editing to DNA before writing files,
* rendering, copying, etc. */
-void ED_editors_flush_edits(const bContext *C, bool for_render)
+bool ED_editors_flush_edits(const bContext *C, bool for_render)
{
+ bool has_edited = false;
Object *ob;
- Object *obedit = CTX_data_edit_object(C);
Main *bmain = CTX_data_main(C);
- /* get editmode results */
- if (obedit)
- ED_object_editmode_load(obedit);
+ /* loop through all data to find edit mode or object mode, because during
+ * exiting we might not have a context for edit object and multiple sculpt
+ * objects can exist at the same time */
for (ob = bmain->object.first; ob; ob = ob->id.next) {
- if (ob && (ob->mode & OB_MODE_SCULPT)) {
+ if (ob->mode & OB_MODE_SCULPT) {
/* flush multires changes (for sculpt) */
multires_force_update(ob);
+ has_edited = true;
if (for_render) {
/* flush changes from dynamic topology sculpt */
@@ -173,11 +178,18 @@ void ED_editors_flush_edits(const bContext *C, bool for_render)
}
else {
/* Set reorder=false so that saving the file doesn't reorder
- * the BMesh's elements */
+ * the BMesh's elements */
BKE_sculptsession_bm_to_me(ob, false);
}
}
+ else if (ob->mode & OB_MODE_EDIT) {
+ /* get editmode results */
+ has_edited = true;
+ ED_object_editmode_load(ob);
+ }
}
+
+ return has_edited;
}
/* ***** XXX: functions are using old blender names, cleanup later ***** */
@@ -210,8 +222,8 @@ void unpack_menu(bContext *C, const char *opname, const char *id_name, const cha
char line[FILE_MAX + 100];
wmOperatorType *ot = WM_operatortype_find(opname, 1);
- pup = uiPupMenuBegin(C, IFACE_("Unpack File"), ICON_NONE);
- layout = uiPupMenuLayout(pup);
+ pup = UI_popup_menu_begin(C, IFACE_("Unpack File"), ICON_NONE);
+ layout = UI_popup_menu_layout(pup);
props_ptr = uiItemFullO_ptr(layout, ot, IFACE_("Remove Pack"), ICON_NONE,
NULL, WM_OP_EXEC_DEFAULT, UI_ITEM_O_RETURN_PROPS);
@@ -223,7 +235,7 @@ void unpack_menu(bContext *C, const char *opname, const char *id_name, const cha
BLI_split_file_part(abs_name, fi, sizeof(fi));
BLI_snprintf(local_name, sizeof(local_name), "//%s/%s", folder, fi);
- if (strcmp(abs_name, local_name) != 0) {
+ if (!STREQ(abs_name, local_name)) {
switch (checkPackedFile(local_name, pf)) {
case PF_NOFILE:
BLI_snprintf(line, sizeof(line), IFACE_("Create %s"), local_name);
@@ -287,7 +299,7 @@ void unpack_menu(bContext *C, const char *opname, const char *id_name, const cha
break;
}
- uiPupMenuEnd(C, pup);
+ UI_popup_menu_end(C, pup);
}
/* ********************* generic callbacks for drawcall api *********************** */
@@ -310,3 +322,25 @@ void ED_region_draw_mouse_line_cb(const bContext *C, ARegion *ar, void *arg_info
glEnd();
setlinestyle(0);
}
+
+/**
+ * Use to free ID references within runtime data (stored outside of DNA)
+ *
+ * \note Typically notifiers take care of this,
+ * but there are times we have to free references immediately, see: T44376
+ */
+void ED_spacedata_id_unref(struct SpaceLink *sl, const ID *id)
+{
+
+ switch (sl->spacetype) {
+ case SPACE_OUTLINER:
+ ED_outliner_id_unref((SpaceOops *)sl, id);
+ break;
+ case SPACE_BUTS:
+ ED_buttons_id_unref((SpaceButs *)sl, id);
+ break;
+ case SPACE_NODE:
+ ED_node_id_unref((SpaceNode *)sl, id);
+ break;
+ }
+}
diff --git a/source/blender/editors/util/editmode_undo.c b/source/blender/editors/util/editmode_undo.c
index ef95e4cb3ff..bc7a8374c73 100644
--- a/source/blender/editors/util/editmode_undo.c
+++ b/source/blender/editors/util/editmode_undo.c
@@ -48,8 +48,6 @@
#include "ED_util.h"
#include "ED_mesh.h"
-#include "UI_interface.h"
-#include "UI_resources.h"
#include "util_intern.h"
@@ -208,7 +206,7 @@ static void undo_clean_stack(bContext *C)
/* for when objects are converted, renamed, or global undo changes pointers... */
if (uel->type == obedit->type) {
- if (strcmp(uel->id.name, obedit->id.name) == 0) {
+ if (STREQ(uel->id.name, obedit->id.name)) {
if (uel->validate_undo == NULL)
is_valid = true;
else if (uel->validate_undo(uel->undodata, editdata))
@@ -307,7 +305,7 @@ void undo_editmode_name(bContext *C, const char *undoname)
UndoElem *uel;
for (uel = undobase.last; uel; uel = uel->prev) {
- if (strcmp(undoname, uel->name) == 0)
+ if (STREQ(undoname, uel->name))
break;
}
if (uel && uel->prev) {
@@ -317,13 +315,13 @@ void undo_editmode_name(bContext *C, const char *undoname)
}
/* undoname optionally, if NULL it just checks for existing undo steps */
-int undo_editmode_valid(const char *undoname)
+bool undo_editmode_is_valid(const char *undoname)
{
if (undoname) {
UndoElem *uel;
for (uel = undobase.last; uel; uel = uel->prev) {
- if (strcmp(undoname, uel->name) == 0)
+ if (STREQ(undoname, uel->name))
break;
}
return uel != NULL;
@@ -334,19 +332,20 @@ int undo_editmode_valid(const char *undoname)
/* get name of undo item, return null if no item with this index */
/* if active pointer, set it to 1 if true */
-const char *undo_editmode_get_name(bContext *C, int nr, int *active)
+const char *undo_editmode_get_name(bContext *C, int nr, bool *r_active)
{
UndoElem *uel;
/* prevent wrong numbers to be returned */
undo_clean_stack(C);
- if (active) *active = 0;
+ if (r_active) *r_active = false;
uel = BLI_findlink(&undobase, nr);
if (uel) {
- if (active && uel == curundo)
- *active = 1;
+ if (r_active && (uel == curundo)) {
+ *r_active = true;
+ }
return uel->name;
}
return NULL;
diff --git a/source/blender/editors/util/numinput.c b/source/blender/editors/util/numinput.c
index a154f12a786..d2bc8bc80c0 100644
--- a/source/blender/editors/util/numinput.c
+++ b/source/blender/editors/util/numinput.c
@@ -73,14 +73,14 @@ void initNumInput(NumInput *n)
{
n->idx_max = 0;
n->unit_sys = USER_UNIT_NONE;
- fill_vn_i(n->unit_type, NUM_MAX_ELEMENTS, B_UNIT_NONE);
+ copy_vn_i(n->unit_type, NUM_MAX_ELEMENTS, B_UNIT_NONE);
n->unit_use_radians = false;
n->flag = 0;
- fill_vn_short(n->val_flag, NUM_MAX_ELEMENTS, 0);
+ copy_vn_short(n->val_flag, NUM_MAX_ELEMENTS, 0);
zero_v3(n->val);
- fill_vn_fl(n->val_org, NUM_MAX_ELEMENTS, 0.0f);
- fill_vn_fl(n->val_inc, NUM_MAX_ELEMENTS, 1.0f);
+ copy_vn_fl(n->val_org, NUM_MAX_ELEMENTS, 0.0f);
+ copy_vn_fl(n->val_inc, NUM_MAX_ELEMENTS, 1.0f);
n->idx = 0;
n->str[0] = '\0';
@@ -103,7 +103,7 @@ void outputNumInput(NumInput *n, char *str, UnitSettings *unit_settings)
if (n->val_flag[i] & NUM_EDITED) {
/* Get the best precision, allows us to draw '10.0001' as '10' instead! */
- prec = uiFloatPrecisionCalc(prec, (double)n->val[i]);
+ prec = UI_calc_float_precision(prec, (double)n->val[i]);
if (i == n->idx) {
const char *heading_exp = "", *trailing_exp = "";
char before_cursor[NUM_STR_REP_LEN];
@@ -365,9 +365,10 @@ bool handleNumInput(bContext *C, NumInput *n, const wmEvent *event)
ascii[0] = '.';
utf8_buf = ascii;
break;
-#if 0 /* Those keys are not directly accessible in all layouts, preventing to generate matching events.
- * So we use a hack (ascii value) instead, see below.
- */
+#if 0
+ /* Those keys are not directly accessible in all layouts, preventing to generate matching events.
+ * So we use a hack (ascii value) instead, see below.
+ */
case EQUALKEY:
case PADASTERKEY:
if (!(n->flag & NUM_EDIT_FULL)) {
diff --git a/source/blender/editors/util/undo.c b/source/blender/editors/util/undo.c
index 189a938e3d8..cd68df52ed4 100644
--- a/source/blender/editors/util/undo.c
+++ b/source/blender/editors/util/undo.c
@@ -29,8 +29,6 @@
* \ingroup edutil
*/
-
-
#include <stdlib.h>
#include <string.h>
#include <math.h>
@@ -42,11 +40,12 @@
#include "BLI_utildefines.h"
-#include "BLF_translation.h"
+#include "BLT_translation.h"
#include "BKE_blender.h"
#include "BKE_context.h"
#include "BKE_global.h"
+#include "BKE_main.h"
#include "BKE_screen.h"
#include "ED_armature.h"
@@ -109,7 +108,7 @@ void ED_undo_push(bContext *C, const char *str)
/* do nothing for now */
}
else {
- BKE_write_undo(C, str);
+ BKE_undo_write(C, str);
}
if (wm->file_saved) {
@@ -124,6 +123,7 @@ static int ed_undo_step(bContext *C, int step, const char *undoname)
{
wmWindowManager *wm = CTX_wm_manager(C);
wmWindow *win = CTX_wm_window(C);
+ Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
Object *obedit = CTX_data_edit_object(C);
Object *obact = CTX_data_active_object(C);
@@ -146,7 +146,7 @@ static int ed_undo_step(bContext *C, int step, const char *undoname)
if ((obact && (obact->mode & OB_MODE_TEXTURE_PAINT)) || (sima->mode == SI_MODE_PAINT)) {
if (!ED_undo_paint_step(C, UNDO_PAINT_IMAGE, step, undoname) && undoname) {
if (U.uiflag & USER_GLOBALUNDO) {
- ED_viewport_render_kill_jobs(C, true);
+ ED_viewport_render_kill_jobs(wm, bmain, true);
BKE_undo_name(C, undoname);
}
}
@@ -199,7 +199,7 @@ static int ed_undo_step(bContext *C, int step, const char *undoname)
/* for example, texface stores image pointers */
undo_editmode_clear();
- ED_viewport_render_kill_jobs(C, true);
+ ED_viewport_render_kill_jobs(wm, bmain, true);
if (undoname)
BKE_undo_name(C, undoname);
@@ -244,7 +244,7 @@ void ED_undo_pop_op(bContext *C, wmOperator *op)
}
/* name optionally, function used to check for operator redo panel */
-int ED_undo_valid(const bContext *C, const char *undoname)
+bool ED_undo_is_valid(const bContext *C, const char *undoname)
{
Object *obedit = CTX_data_edit_object(C);
Object *obact = CTX_data_active_object(C);
@@ -263,7 +263,7 @@ int ED_undo_valid(const bContext *C, const char *undoname)
}
else if (obedit) {
if (OB_TYPE_SUPPORT_EDITMODE(obedit->type)) {
- return undo_editmode_valid(undoname);
+ return undo_editmode_is_valid(undoname);
}
}
else {
@@ -271,19 +271,19 @@ int ED_undo_valid(const bContext *C, const char *undoname)
/* if below tests fail, global undo gets executed */
if (obact && obact->mode & OB_MODE_TEXTURE_PAINT) {
- if (ED_undo_paint_valid(UNDO_PAINT_IMAGE, undoname))
+ if (ED_undo_paint_is_valid(UNDO_PAINT_IMAGE, undoname))
return 1;
}
else if (obact && obact->mode & OB_MODE_SCULPT) {
- if (ED_undo_paint_valid(UNDO_PAINT_MESH, undoname))
+ if (ED_undo_paint_is_valid(UNDO_PAINT_MESH, undoname))
return 1;
}
else if (obact && obact->mode & OB_MODE_PARTICLE_EDIT) {
- return PE_undo_valid(CTX_data_scene(C));
+ return PE_undo_is_valid(CTX_data_scene(C));
}
if (U.uiflag & USER_GLOBALUNDO) {
- return BKE_undo_valid(undoname);
+ return BKE_undo_is_valid(undoname);
}
}
return 0;
@@ -379,7 +379,7 @@ int ED_undo_operator_repeat(bContext *C, struct wmOperator *op)
{
int retval;
- ED_viewport_render_kill_jobs(C, true);
+ ED_viewport_render_kill_jobs(wm, CTX_data_main(C), true);
if (G.debug & G_DEBUG)
printf("redo_cb: operator redo %s\n", op->type->name);
@@ -487,7 +487,8 @@ static int get_undo_system(bContext *C)
static EnumPropertyItem *rna_undo_itemf(bContext *C, int undosys, int *totitem)
{
EnumPropertyItem item_tmp = {0}, *item = NULL;
- int active, i = 0;
+ int i = 0;
+ bool active;
while (true) {
const char *name = NULL;
@@ -536,8 +537,8 @@ static int undo_history_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSE
EnumPropertyItem *item = rna_undo_itemf(C, undosys, &totitem);
if (totitem > 0) {
- uiPopupMenu *pup = uiPupMenuBegin(C, RNA_struct_ui_name(op->type->srna), ICON_NONE);
- uiLayout *layout = uiPupMenuLayout(pup);
+ uiPopupMenu *pup = UI_popup_menu_begin(C, RNA_struct_ui_name(op->type->srna), ICON_NONE);
+ uiLayout *layout = UI_popup_menu_layout(pup);
uiLayout *split = uiLayoutSplit(layout, 0.0f, false);
uiLayout *column = NULL;
const int col_size = 20 + totitem / 12;
@@ -558,7 +559,7 @@ static int undo_history_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSE
MEM_freeN(item);
- uiPupMenuEnd(C, pup);
+ UI_popup_menu_end(C, pup);
}
}
@@ -580,10 +581,10 @@ static int undo_history_exec(bContext *C, wmOperator *op)
WM_event_add_notifier(C, NC_GEOM | ND_DATA, NULL);
}
else if (undosys == UNDOSYSTEM_IMAPAINT) {
- ED_undo_paint_step_num(C, UNDO_PAINT_IMAGE, item );
+ ED_undo_paint_step_num(C, UNDO_PAINT_IMAGE, item);
}
else {
- ED_viewport_render_kill_jobs(C, true);
+ ED_viewport_render_kill_jobs(CTX_wm_manager(C), CTX_data_main(C), true);
BKE_undo_number(C, item);
WM_event_add_notifier(C, NC_SCENE | ND_LAYER_CONTENT, CTX_data_scene(C));
}
diff --git a/source/blender/editors/util/util_intern.h b/source/blender/editors/util/util_intern.h
index d366ad7997f..0f650330951 100644
--- a/source/blender/editors/util/util_intern.h
+++ b/source/blender/editors/util/util_intern.h
@@ -35,12 +35,12 @@
/* internal exports only */
/* editmode_undo.c */
-void undo_editmode_name (struct bContext *C, const char *undoname);
-int undo_editmode_valid (const char *undoname);
-const char *undo_editmode_get_name (struct bContext *C, int nr, int *active);
-void *undo_editmode_get_prev (struct Object *ob);
-void undo_editmode_step (struct bContext *C, int step);
-void undo_editmode_number (struct bContext *C, int nr);
+void undo_editmode_name(struct bContext *C, const char *undoname);
+bool undo_editmode_is_valid(const char *undoname);
+const char *undo_editmode_get_name(struct bContext *C, int nr, bool *r_active);
+void *undo_editmode_get_prev(struct Object *ob);
+void undo_editmode_step(struct bContext *C, int step);
+void undo_editmode_number(struct bContext *C, int nr);
#endif /* __UTIL_INTERN_H__ */
diff --git a/source/blender/editors/uvedit/CMakeLists.txt b/source/blender/editors/uvedit/CMakeLists.txt
index 45edbde7482..a90763eed4e 100644
--- a/source/blender/editors/uvedit/CMakeLists.txt
+++ b/source/blender/editors/uvedit/CMakeLists.txt
@@ -22,12 +22,14 @@ set(INC
../include
../../blenkernel
../../blenlib
- ../../blenfont
+ ../../blentranslation
../../bmesh
+ ../../gpu
../../makesdna
../../makesrna
../../windowmanager
../../../../intern/guardedalloc
+ ../../../../intern/glew-mx
)
set(INC_SYS
@@ -57,4 +59,6 @@ if(WITH_OPENNL)
)
endif()
+add_definitions(${GL_DEFINITIONS})
+
blender_add_lib(bf_editor_uvedit "${SRC}" "${INC}" "${INC_SYS}")
diff --git a/source/blender/editors/uvedit/SConscript b/source/blender/editors/uvedit/SConscript
index 413503191cd..b5cccab4002 100644
--- a/source/blender/editors/uvedit/SConscript
+++ b/source/blender/editors/uvedit/SConscript
@@ -28,17 +28,19 @@
Import ('env')
defs = []
+defs += env['BF_GL_DEFINITIONS']
sources = env.Glob('*.c')
incs = [
'#/intern/guardedalloc',
- '#/extern/glew/include',
+ env['BF_GLEW_INC'],
+ '#/intern/glew-mx',
'#/intern/opennl/extern',
'../include',
- '../../blenfont',
'../../blenkernel',
'../../blenlib',
+ '../../blentranslation',
'../../bmesh',
'../../gpu',
'../../makesdna',
diff --git a/source/blender/editors/uvedit/uvedit_buttons.c b/source/blender/editors/uvedit/uvedit_buttons.c
index 6816e785c1f..ab415c0cb83 100644
--- a/source/blender/editors/uvedit/uvedit_buttons.c
+++ b/source/blender/editors/uvedit/uvedit_buttons.c
@@ -42,7 +42,7 @@
#include "BLI_math.h"
#include "BLI_utildefines.h"
-#include "BLF_translation.h"
+#include "BLT_translation.h"
#include "BKE_context.h"
#include "BKE_customdata.h"
@@ -53,7 +53,6 @@
#include "ED_uvedit.h"
#include "UI_interface.h"
-#include "UI_resources.h"
#include "WM_api.h"
#include "WM_types.h"
@@ -142,11 +141,25 @@ static void uvedit_vertex_buttons(const bContext *C, uiBlock *block)
em = BKE_editmesh_from_object(obedit);
if (uvedit_center(scene, em, ima, center)) {
+ float range_xy[2][2] = {
+ {-10.0f, 10.0f},
+ {-10.0f, 10.0f},
+ };
+
copy_v2_v2(uvedit_old_center, center);
+ /* expand UI range by center */
+ CLAMP_MAX(range_xy[0][0], uvedit_old_center[0]);
+ CLAMP_MIN(range_xy[0][1], uvedit_old_center[0]);
+ CLAMP_MAX(range_xy[1][0], uvedit_old_center[1]);
+ CLAMP_MIN(range_xy[1][1], uvedit_old_center[1]);
+
if (!(sima->flag & SI_COORDFLOATS)) {
uvedit_old_center[0] *= imx;
uvedit_old_center[1] *= imy;
+
+ mul_v2_fl(range_xy[0], imx);
+ mul_v2_fl(range_xy[1], imy);
}
if (sima->flag & SI_COORDFLOATS) {
@@ -158,12 +171,12 @@ static void uvedit_vertex_buttons(const bContext *C, uiBlock *block)
digits = 2;
}
- uiBlockBeginAlign(block);
- uiDefButF(block, NUM, B_UVEDIT_VERTEX, IFACE_("X:"), 0, 0, width, UI_UNIT_Y, &uvedit_old_center[0],
- -10 * imx, 10.0 * imx, step, digits, "");
- uiDefButF(block, NUM, B_UVEDIT_VERTEX, IFACE_("Y:"), width, 0, width, UI_UNIT_Y, &uvedit_old_center[1],
- -10 * imy, 10.0 * imy, step, digits, "");
- uiBlockEndAlign(block);
+ UI_block_align_begin(block);
+ uiDefButF(block, UI_BTYPE_NUM, B_UVEDIT_VERTEX, IFACE_("X:"), 0, 0, width, UI_UNIT_Y, &uvedit_old_center[0],
+ UNPACK2(range_xy[0]), step, digits, "");
+ uiDefButF(block, UI_BTYPE_NUM, B_UVEDIT_VERTEX, IFACE_("Y:"), width, 0, width, UI_UNIT_Y, &uvedit_old_center[1],
+ UNPACK2(range_xy[1]), step, digits, "");
+ UI_block_align_end(block);
}
}
@@ -212,7 +225,7 @@ static void image_panel_uv(const bContext *C, Panel *pa)
uiBlock *block;
block = uiLayoutAbsoluteBlock(pa->layout);
- uiBlockSetHandleFunc(block, do_uvedit_vertex, NULL);
+ UI_block_func_handle_set(block, do_uvedit_vertex, NULL);
uvedit_vertex_buttons(C, block);
}
diff --git a/source/blender/editors/uvedit/uvedit_draw.c b/source/blender/editors/uvedit/uvedit_draw.c
index 36c96a8d011..4e9ab680dc6 100644
--- a/source/blender/editors/uvedit/uvedit_draw.c
+++ b/source/blender/editors/uvedit/uvedit_draw.c
@@ -43,7 +43,6 @@
#include "BLI_math.h"
#include "BLI_utildefines.h"
-#include "BLI_alloca.h"
#include "BLI_buffer.h"
#include "BLI_bitmap.h"
@@ -71,7 +70,7 @@
static void draw_uvs_lineloop_bmface(BMFace *efa, const int cd_loop_uv_offset);
-void draw_image_cursor(ARegion *ar, const float cursor[2])
+void ED_image_draw_cursor(ARegion *ar, const float cursor[2])
{
float zoom[2], x_fac, y_fac;
@@ -82,7 +81,7 @@ void draw_image_cursor(ARegion *ar, const float cursor[2])
y_fac = zoom[1];
cpack(0xFFFFFF);
- glTranslatef(cursor[0], cursor[1], 0.0);
+ glTranslate2fv(cursor);
fdrawline(-0.05f * x_fac, 0, 0, 0.05f * y_fac);
fdrawline(0, 0.05f * y_fac, 0.05f * x_fac, 0.0f);
fdrawline(0.05f * x_fac, 0.0f, 0.0f, -0.05f * y_fac);
@@ -325,7 +324,7 @@ static void draw_uvs_stretch(SpaceImage *sima, Scene *scene, BMEditMesh *em, MTe
BM_ITER_ELEM_INDEX (l, &liter, efa, BM_LOOPS_OF_FACE, i) {
luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
a = fabsf(uvang[i] - ang[i]) / (float)M_PI;
- weight_to_rgb(col, 1.0f - powf((1.0f - a), 2.0f));
+ weight_to_rgb(col, 1.0f - pow2f(1.0f - a));
glColor3fv(col);
glVertex2fv(luv->uv);
}
@@ -506,6 +505,8 @@ static void draw_uvs_texpaint(SpaceImage *sima, Scene *scene, Object *ob)
mloopuv_base = mloopuv;
for (a = me->totpoly; a > 0; a--, mpoly++) {
+ if ((scene->toolsettings->uv_flag & UV_SHOW_SAME_IMAGE) && mpoly->mat_nr != ob->actcol - 1)
+ continue;
glBegin(GL_LINE_LOOP);
mloopuv = mloopuv_base + mpoly->loopstart;
@@ -597,7 +598,9 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit)
/* first try existing derivedmesh */
if (!draw_uvs_dm_shadow(em->derivedFinal)) {
/* create one if it does not exist */
- cagedm = editbmesh_get_derived_cage_and_final(scene, obedit, me->edit_btmesh, &finaldm, CD_MASK_BAREMESH | CD_MASK_MTFACE);
+ cagedm = editbmesh_get_derived_cage_and_final(
+ scene, obedit, me->edit_btmesh, CD_MASK_BAREMESH | CD_MASK_MTFACE,
+ &finaldm);
/* when sync selection is enabled, all faces are drawn (except for hidden)
* so if cage is the same as the final, theres no point in drawing this */
@@ -946,14 +949,30 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit)
glPointSize(1.0);
}
-void draw_uvedit_main(SpaceImage *sima, ARegion *ar, Scene *scene, Object *obedit, Object *obact)
+
+static void draw_uv_shadows_get(SpaceImage *sima, Object *ob, Object *obedit, bool *show_shadow, bool *show_texpaint)
+{
+ *show_shadow = *show_texpaint = false;
+
+ if (ED_space_image_show_render(sima) || (sima->flag & SI_NO_DRAW_TEXPAINT))
+ return;
+
+ if ((sima->mode == SI_MODE_PAINT) && obedit && obedit->type == OB_MESH) {
+ struct BMEditMesh *em = BKE_editmesh_from_object(obedit);
+
+ *show_shadow = EDBM_mtexpoly_check(em);
+ }
+
+ *show_texpaint = (ob && ob->type == OB_MESH && ob->mode == OB_MODE_TEXTURE_PAINT);
+}
+
+void ED_uvedit_draw_main(SpaceImage *sima, ARegion *ar, Scene *scene, Object *obedit, Object *obact)
{
ToolSettings *toolsettings = scene->toolsettings;
- int show_uvedit, show_uvshadow, show_texpaint_uvshadow;
+ bool show_uvedit, show_uvshadow, show_texpaint_uvshadow;
- show_texpaint_uvshadow = ED_space_image_show_texpaint(sima, obact);
show_uvedit = ED_space_image_show_uvedit(sima, obedit);
- show_uvshadow = ED_space_image_show_uvshadow(sima, obedit);
+ draw_uv_shadows_get(sima, obact, obedit, &show_uvshadow, &show_texpaint_uvshadow);
if (show_uvedit || show_uvshadow || show_texpaint_uvshadow) {
if (show_uvshadow)
@@ -964,7 +983,7 @@ void draw_uvedit_main(SpaceImage *sima, ARegion *ar, Scene *scene, Object *obedi
draw_uvs_texpaint(sima, scene, obact);
if (show_uvedit && !(toolsettings->use_uv_sculpt))
- draw_image_cursor(ar, sima->cursor);
+ ED_image_draw_cursor(ar, sima->cursor);
}
}
diff --git a/source/blender/editors/uvedit/uvedit_intern.h b/source/blender/editors/uvedit/uvedit_intern.h
index 52365ff3478..e028c08091c 100644
--- a/source/blender/editors/uvedit/uvedit_intern.h
+++ b/source/blender/editors/uvedit/uvedit_intern.h
@@ -34,17 +34,13 @@
struct MTexPoly;
struct Image;
-struct MTFace;
struct Object;
struct Scene;
struct SpaceImage;
-struct UvElementMap;
struct wmOperatorType;
struct BMEditMesh;
struct BMFace;
struct BMLoop;
-struct BMEdge;
-struct BMVert;
/* visibility and selection */
bool uvedit_face_visible_nolocal(struct Scene *scene, struct BMFace *efa);
@@ -71,7 +67,6 @@ void uv_find_nearest_edge(struct Scene *scene, struct Image *ima, struct BMEditM
/* utility tool functions */
void uvedit_live_unwrap_update(struct SpaceImage *sima, struct Scene *scene, struct Object *obedit);
-void uvedit_get_aspect(struct Scene *scene, struct Object *ob, struct BMEditMesh *em, float *aspx, float *aspy);
/* operators */
diff --git a/source/blender/editors/uvedit/uvedit_ops.c b/source/blender/editors/uvedit/uvedit_ops.c
index 4b341547370..71d557f6fc7 100644
--- a/source/blender/editors/uvedit/uvedit_ops.c
+++ b/source/blender/editors/uvedit/uvedit_ops.c
@@ -53,6 +53,8 @@
#include "BLI_blenlib.h"
#include "BLI_array.h"
+#include "BLT_translation.h"
+
#include "BKE_context.h"
#include "BKE_customdata.h"
#include "BKE_depsgraph.h"
@@ -80,6 +82,8 @@
#include "WM_api.h"
#include "WM_types.h"
+#include "UI_interface.h"
+#include "UI_resources.h"
#include "UI_view2d.h"
#include "uvedit_intern.h"
@@ -668,6 +672,24 @@ bool ED_uvedit_minmax(Scene *scene, Image *ima, Object *obedit, float r_min[2],
return changed;
}
+/* Be careful when using this, it bypasses all synchronization options */
+void ED_uvedit_select_all(BMesh *bm)
+{
+ BMFace *efa;
+ BMLoop *l;
+ BMIter iter, liter;
+ MLoopUV *luv;
+
+ const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
+
+ BM_ITER_MESH (efa, &iter, 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);
+ luv->flag |= MLOOPUV_VERTSEL;
+ }
+ }
+}
+
static bool ED_uvedit_median(Scene *scene, Image *ima, Object *obedit, float co[2])
{
BMEditMesh *em = BKE_editmesh_from_object(obedit);
@@ -1010,7 +1032,7 @@ static int uv_select_edgeloop(Scene *scene, Image *ima, BMEditMesh *em, NearestH
/* setup */
BM_mesh_elem_table_ensure(em->bm, BM_FACE);
- vmap = BM_uv_vert_map_create(em->bm, 0, limit);
+ vmap = BM_uv_vert_map_create(em->bm, limit, false, false);
BM_mesh_elem_index_ensure(em->bm, BM_VERT | BM_FACE);
@@ -1096,7 +1118,7 @@ static int uv_select_edgeloop(Scene *scene, Image *ima, BMEditMesh *em, NearestH
/*********************** linked select ***********************/
-static void uv_select_linked(Scene *scene, Image *ima, BMEditMesh *em, const float limit[2], NearestHit *hit, bool extend)
+static void uv_select_linked(Scene *scene, Image *ima, BMEditMesh *em, const float limit[2], NearestHit *hit, bool extend, bool select_faces)
{
BMFace *efa;
BMLoop *l;
@@ -1113,7 +1135,9 @@ static void uv_select_linked(Scene *scene, Image *ima, BMEditMesh *em, const flo
const int cd_poly_tex_offset = CustomData_get_offset(&em->bm->pdata, CD_MTEXPOLY);
BM_mesh_elem_table_ensure(em->bm, BM_FACE); /* we can use this too */
- vmap = BM_uv_vert_map_create(em->bm, 1, limit);
+
+ /* use winding so we don't consider overlapping islands as connected, see T44320 */
+ vmap = BM_uv_vert_map_create(em->bm, limit, !select_faces, true);
if (vmap == NULL)
return;
@@ -1126,15 +1150,24 @@ static void uv_select_linked(Scene *scene, Image *ima, BMEditMesh *em, const flo
tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset);
if (uvedit_face_visible_test(scene, ima, efa, tf)) {
- BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
- luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
-
- if (luv->flag & MLOOPUV_VERTSEL) {
+ if (select_faces) {
+ if (BM_elem_flag_test(efa, BM_ELEM_SELECT)) {
stack[stacksize] = a;
stacksize++;
flag[a] = 1;
+ }
+ }
+ else {
+ BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
+ luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
- break;
+ if (luv->flag & MLOOPUV_VERTSEL) {
+ stack[stacksize] = a;
+ stacksize++;
+ flag[a] = 1;
+
+ break;
+ }
}
}
}
@@ -1186,13 +1219,21 @@ static void uv_select_linked(Scene *scene, Image *ima, BMEditMesh *em, const flo
if (!extend) {
BM_ITER_MESH_INDEX (efa, &iter, em->bm, BM_FACES_OF_MESH, a) {
- BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
- luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
-
+ if (select_faces) {
if (flag[a])
- luv->flag |= MLOOPUV_VERTSEL;
+ BM_face_select_set(em->bm, efa, true);
else
- luv->flag &= ~MLOOPUV_VERTSEL;
+ BM_face_select_set(em->bm, efa, false);
+ }
+ else {
+ BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
+ luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
+
+ if (flag[a])
+ luv->flag |= MLOOPUV_VERTSEL;
+ else
+ luv->flag &= ~MLOOPUV_VERTSEL;
+ }
}
}
}
@@ -1201,17 +1242,23 @@ static void uv_select_linked(Scene *scene, Image *ima, BMEditMesh *em, const flo
if (!flag[a]) {
continue;
}
-
- BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
- luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
-
- if (luv->flag & MLOOPUV_VERTSEL) {
+
+ if (select_faces) {
+ if (BM_elem_flag_test(efa, BM_ELEM_SELECT) && !BM_elem_flag_test(efa, BM_ELEM_HIDDEN))
break;
- }
}
-
- if (l) {
- break;
+ else {
+ BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
+ luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
+
+ if (luv->flag & MLOOPUV_VERTSEL) {
+ break;
+ }
+ }
+
+ if (l) {
+ break;
+ }
}
}
@@ -1221,10 +1268,15 @@ static void uv_select_linked(Scene *scene, Image *ima, BMEditMesh *em, const flo
continue;
}
- BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
- luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
-
- luv->flag &= ~MLOOPUV_VERTSEL;
+ if (select_faces) {
+ BM_face_select_set(em->bm, efa, false);
+ }
+ else {
+ BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
+ luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
+
+ luv->flag &= ~MLOOPUV_VERTSEL;
+ }
}
}
}
@@ -1234,10 +1286,15 @@ static void uv_select_linked(Scene *scene, Image *ima, BMEditMesh *em, const flo
continue;
}
- BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
- luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
-
- luv->flag |= MLOOPUV_VERTSEL;
+ if (select_faces) {
+ BM_face_select_set(em->bm, efa, true);
+ }
+ else {
+ BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
+ luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
+
+ luv->flag |= MLOOPUV_VERTSEL;
+ }
}
}
}
@@ -1291,10 +1348,10 @@ static int uv_select_more_less(bContext *C, const bool select)
if (ts->uv_flag & UV_SYNC_SELECTION) {
if (select) {
- EDBM_select_more(em);
+ EDBM_select_more(em, true);
}
else {
- EDBM_select_less(em);
+ EDBM_select_less(em, true);
}
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
@@ -1753,7 +1810,7 @@ static int uv_remove_doubles_exec(bContext *C, wmOperator *op)
if ((vert_arr[uv_b_index].weld == false) &&
(len_manhattan_v2v2(uv_a, uv_b) < threshold))
{
- minmax_v2v2_v2(uv_max, uv_min, uv_b);
+ minmax_v2v2_v2(uv_min, uv_max, uv_b);
BLI_array_append(loop_arr, vert_arr[uv_b_index].uv_loop);
vert_arr[uv_b_index].weld = true;
}
@@ -2069,7 +2126,7 @@ static int uv_mouse_select(bContext *C, const float co[2], bool extend, bool loo
/* mark 1 vertex as being hit */
hitv = BLI_array_alloca(hitv, hit.efa->len);
hituv = BLI_array_alloca(hituv, hit.efa->len);
- fill_vn_i(hitv, hit.efa->len, 0xFFFFFFFF);
+ copy_vn_i(hitv, hit.efa->len, 0xFFFFFFFF);
hitv[hit.lindex] = BM_elem_index_get(hit.l->v);
hituv[hit.lindex] = hit.luv->uv;
@@ -2086,7 +2143,7 @@ static int uv_mouse_select(bContext *C, const float co[2], bool extend, bool loo
/* mark 2 edge vertices as being hit */
hitv = BLI_array_alloca(hitv, hit.efa->len);
hituv = BLI_array_alloca(hituv, hit.efa->len);
- fill_vn_i(hitv, hit.efa->len, 0xFFFFFFFF);
+ copy_vn_i(hitv, hit.efa->len, 0xFFFFFFFF);
hitv[hit.lindex] = BM_elem_index_get(hit.l->v);
hitv[(hit.lindex + 1) % hit.efa->len] = BM_elem_index_get(hit.l->next->v);
@@ -2136,7 +2193,7 @@ static int uv_mouse_select(bContext *C, const float co[2], bool extend, bool loo
flush = uv_select_edgeloop(scene, ima, em, &hit, limit, extend);
}
else if (selectmode == UV_SELECT_ISLAND) {
- uv_select_linked(scene, ima, em, limit, &hit, extend);
+ uv_select_linked(scene, ima, em, limit, &hit, extend, false);
}
else if (extend) {
if (selectmode == UV_SELECT_VERTEX) {
@@ -2357,11 +2414,12 @@ static int uv_select_linked_internal(bContext *C, wmOperator *op, const wmEvent
BMEditMesh *em = BKE_editmesh_from_object(obedit);
float limit[2];
int extend;
+ bool select_faces = (ts->uv_flag & UV_SYNC_SELECTION) && (ts->selectmode & SCE_SELECT_FACE);
NearestHit hit, *hit_p = NULL;
- if (ts->uv_flag & UV_SYNC_SELECTION) {
- BKE_report(op->reports, RPT_ERROR, "Cannot select linked when sync selection is enabled");
+ if ((ts->uv_flag & UV_SYNC_SELECTION) && !(ts->selectmode & SCE_SELECT_FACE)) {
+ BKE_report(op->reports, RPT_ERROR, "Select linked only works in face select mode when sync selection is enabled");
return OPERATOR_CANCELLED;
}
@@ -2387,7 +2445,7 @@ static int uv_select_linked_internal(bContext *C, wmOperator *op, const wmEvent
hit_p = &hit;
}
- uv_select_linked(scene, ima, em, limit, hit_p, extend);
+ uv_select_linked(scene, ima, em, limit, hit_p, extend, select_faces);
DAG_id_tag_update(obedit->data, 0);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
@@ -2662,7 +2720,7 @@ static void uv_select_flush_from_tag_face(SpaceImage *sima, Scene *scene, Object
uvedit_pixel_to_float(sima, limit, 0.05);
BM_mesh_elem_table_ensure(em->bm, BM_FACE);
- vmap = BM_uv_vert_map_create(em->bm, 0, limit);
+ vmap = BM_uv_vert_map_create(em->bm, limit, false, false);
if (vmap == NULL) {
return;
}
@@ -2753,7 +2811,7 @@ static void uv_select_flush_from_tag_loop(SpaceImage *sima, Scene *scene, Object
uvedit_pixel_to_float(sima, limit, 0.05);
BM_mesh_elem_table_ensure(em->bm, BM_FACE);
- vmap = BM_uv_vert_map_create(em->bm, 0, limit);
+ vmap = BM_uv_vert_map_create(em->bm, limit, false, false);
if (vmap == NULL) {
return;
}
@@ -3046,9 +3104,10 @@ static bool do_lasso_select_mesh_uv(bContext *C, const int mcords[][2], short mo
Scene *scene = CTX_data_scene(C);
ToolSettings *ts = scene->toolsettings;
BMEditMesh *em = BKE_editmesh_from_object(obedit);
- const int use_face_center = (ts->uv_flag & UV_SYNC_SELECTION) ?
- (ts->selectmode == SCE_SELECT_FACE) :
- (ts->uv_selectmode == UV_SELECT_FACE);
+ const bool use_face_center = (
+ (ts->uv_flag & UV_SYNC_SELECTION) ?
+ (ts->selectmode == SCE_SELECT_FACE) :
+ (ts->uv_selectmode == UV_SELECT_FACE));
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);
@@ -3171,8 +3230,8 @@ static void UV_OT_select_lasso(wmOperatorType *ot)
static void uv_snap_to_pixel(float uvco[2], float w, float h)
{
- uvco[0] = ((float)((int)((uvco[0] * w) + 0.5f))) / w;
- uvco[1] = ((float)((int)((uvco[1] * h) + 0.5f))) / h;
+ uvco[0] = roundf(uvco[0] * w) / w;
+ uvco[1] = roundf(uvco[1] * h) / h;
}
static void uv_snap_cursor_to_pixels(SpaceImage *sima)
@@ -3273,7 +3332,7 @@ static bool uv_snap_uvs_offset(Scene *scene, Image *ima, Object *obedit, const f
BMFace *efa;
BMLoop *l;
BMIter iter, liter;
- MTexPoly *tface;
+ MTexPoly *mtexpoly;
MLoopUV *luv;
bool changed = false;
@@ -3281,8 +3340,8 @@ static bool uv_snap_uvs_offset(Scene *scene, Image *ima, Object *obedit, const f
const int cd_poly_tex_offset = CustomData_get_offset(&em->bm->pdata, CD_MTEXPOLY);
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- tface = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset);
- if (!uvedit_face_visible_test(scene, ima, efa, tface))
+ mtexpoly = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset);
+ if (!uvedit_face_visible_test(scene, ima, efa, mtexpoly))
continue;
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
@@ -3859,6 +3918,15 @@ static int uv_set_2d_cursor_invoke(bContext *C, wmOperator *op, const wmEvent *e
ARegion *ar = CTX_wm_region(C);
float location[2];
+ if (ar->regiontype == RGN_TYPE_WINDOW) {
+ if (event->mval[1] <= 16) {
+ SpaceImage *sima = CTX_wm_space_image(C);
+ if (sima && ED_space_image_show_cache(sima)) {
+ return OPERATOR_PASS_THROUGH;
+ }
+ }
+ }
+
UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &location[0], &location[1]);
RNA_float_set_array(op->ptr, "location", location);
@@ -3975,7 +4043,7 @@ static int uv_seams_from_islands_exec(bContext *C, wmOperator *op)
/* This code sets editvert->tmp.l to the index. This will be useful later on. */
BM_mesh_elem_table_ensure(bm, BM_FACE);
- vmap = BM_uv_vert_map_create(bm, 0, limit);
+ vmap = BM_uv_vert_map_create(bm, limit, false, false);
BM_ITER_MESH (editedge, &iter, bm, BM_EDGES_OF_MESH) {
/* flags to determine if we uv is separated from first editface match */
@@ -4080,7 +4148,7 @@ static void UV_OT_seams_from_islands(wmOperatorType *ot)
RNA_def_boolean(ot->srna, "mark_sharp", 0, "Mark Sharp", "Mark boundary edges as sharp");
}
-static int uv_mark_seam_exec(bContext *C, wmOperator *UNUSED(op))
+static int uv_mark_seam_exec(bContext *C, wmOperator *op)
{
Object *ob = CTX_data_edit_object(C);
Scene *scene = CTX_data_scene(C);
@@ -4090,13 +4158,17 @@ static int uv_mark_seam_exec(bContext *C, wmOperator *UNUSED(op))
BMFace *efa;
BMLoop *loop;
BMIter iter, liter;
+ bool clear = RNA_boolean_get(op->ptr, "clear");
const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
BM_ITER_ELEM (loop, &liter, efa, BM_LOOPS_OF_FACE) {
if (uvedit_edge_select_test(scene, loop, cd_loop_uv_offset)) {
- BM_elem_flag_enable(loop->e, BM_ELEM_SEAM);
+ if (clear)
+ BM_elem_flag_disable(loop->e, BM_ELEM_SEAM);
+ else
+ BM_elem_flag_enable(loop->e, BM_ELEM_SEAM);
}
}
}
@@ -4112,10 +4184,27 @@ static int uv_mark_seam_exec(bContext *C, wmOperator *UNUSED(op))
return OPERATOR_FINISHED;
}
+static int uv_mark_seam_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
+{
+ uiPopupMenu *pup;
+ uiLayout *layout;
+
+ pup = UI_popup_menu_begin(C, IFACE_("Edges"), ICON_NONE);
+ layout = UI_popup_menu_layout(pup);
+
+ uiLayoutSetOperatorContext(layout, WM_OP_EXEC_DEFAULT);
+ uiItemBooleanO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Mark Seam"), ICON_NONE, op->type->idname, "clear", false);
+ uiItemBooleanO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Clear Seam"), ICON_NONE, op->type->idname, "clear", true);
+
+ UI_popup_menu_end(C, pup);
+
+ return OPERATOR_INTERFACE;
+}
+
static void UV_OT_mark_seam(wmOperatorType *ot)
{
/* identifiers */
- ot->name = "Mark Seams";
+ ot->name = "Mark Seam";
ot->description = "Mark selected UV edges as seams";
ot->idname = "UV_OT_mark_seam";
@@ -4124,7 +4213,10 @@ static void UV_OT_mark_seam(wmOperatorType *ot)
/* api callbacks */
ot->exec = uv_mark_seam_exec;
+ ot->invoke = uv_mark_seam_invoke;
ot->poll = ED_operator_uvedit;
+
+ RNA_def_boolean(ot->srna, "clear", false, "Clear Seams", "Clear instead of marking seams");
}
diff --git a/source/blender/editors/uvedit/uvedit_parametrizer.c b/source/blender/editors/uvedit/uvedit_parametrizer.c
index 79f53e1d971..00615f9bef7 100644
--- a/source/blender/editors/uvedit/uvedit_parametrizer.c
+++ b/source/blender/editors/uvedit/uvedit_parametrizer.c
@@ -35,7 +35,6 @@
#include "BLI_boxpack2d.h"
#include "BLI_convexhull2d.h"
-#include "uvedit_intern.h"
#include "uvedit_parametrizer.h"
#include <math.h>
@@ -2673,8 +2672,8 @@ static PBool p_abf_matrix_invert(PAbfSystem *sys, PChart *chart)
}
for (i = 0; i < ninterior; i++) {
- sys->lambdaPlanar[i] += nlGetVariable(0, i);
- sys->lambdaLength[i] += nlGetVariable(0, ninterior + i);
+ sys->lambdaPlanar[i] += (float)nlGetVariable(0, i);
+ sys->lambdaLength[i] += (float)nlGetVariable(0, ninterior + i);
}
}
@@ -3403,8 +3402,8 @@ static void p_chart_stretch_minimize(PChart *chart, RNG *rng)
static int p_compare_geometric_uv(const void *a, const void *b)
{
- PVert *v1 = *(PVert **)a;
- PVert *v2 = *(PVert **)b;
+ const PVert *v1 = *(const PVert * const *)a;
+ const PVert *v2 = *(const PVert * const *)b;
if (v1->uv[0] < v2->uv[0])
return -1;
@@ -3789,11 +3788,14 @@ static PBool p_node_intersect(SmoothNode *node, float co[2])
/* smoothing */
-static int p_compare_float(const void *a, const void *b)
+static int p_compare_float(const void *a_, const void *b_)
{
- if (*((float *)a) < *((float *)b))
+ const float a = *(const float *)a_;
+ const float b = *(const float *)b_;
+
+ if (a < b)
return -1;
- else if (*((float *)a) == *((float *)b))
+ else if (a == b)
return 0;
else
return 1;
@@ -4194,7 +4196,7 @@ void param_delete(ParamHandle *handle)
static void p_add_ngon(ParamHandle *handle, ParamKey key, int nverts,
ParamKey *vkeys, float **co, float **uv,
- ParamBool *pin, ParamBool *select, float normal[3])
+ ParamBool *pin, ParamBool *select, const float normal[3])
{
int *boundary = BLI_array_alloca(boundary, nverts);
int i;
@@ -4559,7 +4561,7 @@ void param_pack(ParamHandle *handle, float margin, bool do_rotate)
box->index = i; /* warning this index skips PCHART_NOPACK boxes */
if (margin > 0.0f)
- area += sqrtf(box->w * box->h);
+ area += (double)sqrtf(box->w * box->h);
}
if (margin > 0.0f) {
diff --git a/source/blender/editors/uvedit/uvedit_smart_stitch.c b/source/blender/editors/uvedit/uvedit_smart_stitch.c
index fcd5267fd44..828537fd585 100644
--- a/source/blender/editors/uvedit/uvedit_smart_stitch.c
+++ b/source/blender/editors/uvedit/uvedit_smart_stitch.c
@@ -574,11 +574,11 @@ static void stitch_island_calculate_vert_rotation(UvElement *element, StitchStat
edgecos = dot_v2v2(normal, state->normals + index_tmp1 * 2);
edgesin = cross_v2v2(normal, state->normals + index_tmp1 * 2);
if (edgesin > 0.0f) {
- rotation += acosf(max_ff(-1.0f, min_ff(1.0f, edgecos)));
+ rotation += acosf(max_ff(-1.0f, min_ff(1.0f, edgecos)));
rot_elem++;
}
else {
- rotation_neg += acosf(max_ff(-1.0f, min_ff(1.0f, edgecos)));
+ rotation_neg += acosf(max_ff(-1.0f, min_ff(1.0f, edgecos)));
rot_elem_neg++;
}
}
@@ -1354,16 +1354,15 @@ static int stitch_process_data(StitchState *state, Scene *scene, int final)
/* Stitch hash initialization functions */
static unsigned int uv_edge_hash(const void *key)
{
- UvEdge *edge = (UvEdge *)key;
- return
- BLI_ghashutil_uinthash(edge->uv2) +
- BLI_ghashutil_uinthash(edge->uv1);
+ const UvEdge *edge = key;
+ return (BLI_ghashutil_uinthash(edge->uv2) +
+ BLI_ghashutil_uinthash(edge->uv1));
}
static bool uv_edge_compare(const void *a, const void *b)
{
- UvEdge *edge1 = (UvEdge *)a;
- UvEdge *edge2 = (UvEdge *)b;
+ const UvEdge *edge1 = a;
+ const UvEdge *edge2 = b;
if ((edge1->uv1 == edge2->uv1) && (edge1->uv2 == edge2->uv2)) {
return 0;
@@ -1602,7 +1601,7 @@ static int stitch_init(bContext *C, wmOperator *op)
BMFace *efa;
BMLoop *l;
BMIter iter, liter;
- GHashIterator *ghi;
+ GHashIterator gh_iter;
UvEdge *all_edges;
StitchState *state;
Scene *scene = CTX_data_scene(C);
@@ -1650,17 +1649,17 @@ static int stitch_init(bContext *C, wmOperator *op)
/* in uv synch selection, all uv's are visible */
if (ts->uv_flag & UV_SYNC_SELECTION) {
- state->element_map = BM_uv_element_map_create(state->em->bm, false, true);
+ state->element_map = BM_uv_element_map_create(state->em->bm, false, true, true);
}
else {
- state->element_map = BM_uv_element_map_create(state->em->bm, true, true);
+ state->element_map = BM_uv_element_map_create(state->em->bm, true, true, true);
}
if (!state->element_map) {
state_delete(state);
return 0;
}
- uvedit_get_aspect(scene, obedit, em, &aspx, &aspy);
+ ED_uvedit_get_aspect(scene, obedit, em->bm, &aspx, &aspy);
state->aspect = aspx / aspy;
/* Entirely possible if redoing last operator that static island is bigger than total number of islands.
@@ -1749,14 +1748,11 @@ static int stitch_init(bContext *C, wmOperator *op)
}
}
-
- ghi = BLI_ghashIterator_new(edge_hash);
total_edges = BLI_ghash_size(edge_hash);
state->edges = edges = MEM_mallocN(sizeof(*edges) * total_edges, "stitch_edges");
/* I assume any system will be able to at least allocate an iterator :p */
if (!edges) {
- BLI_ghashIterator_free(ghi);
state_delete(state);
return 0;
}
@@ -1764,12 +1760,12 @@ static int stitch_init(bContext *C, wmOperator *op)
state->total_separate_edges = total_edges;
/* fill the edges with data */
- for (i = 0, BLI_ghashIterator_init(ghi, edge_hash); !BLI_ghashIterator_done(ghi); BLI_ghashIterator_step(ghi)) {
- edges[i++] = *((UvEdge *)BLI_ghashIterator_getKey(ghi));
+ i = 0;
+ GHASH_ITER (gh_iter, edge_hash) {
+ edges[i++] = *((UvEdge *)BLI_ghashIterator_getKey(&gh_iter));
}
/* cleanup temporary stuff */
- BLI_ghashIterator_free(ghi);
MEM_freeN(all_edges);
BLI_ghash_free(edge_hash, NULL, NULL);
diff --git a/source/blender/editors/uvedit/uvedit_unwrap_ops.c b/source/blender/editors/uvedit/uvedit_unwrap_ops.c
index 335d8e6589e..f915a4b2e51 100644
--- a/source/blender/editors/uvedit/uvedit_unwrap_ops.c
+++ b/source/blender/editors/uvedit/uvedit_unwrap_ops.c
@@ -190,21 +190,21 @@ static bool uvedit_have_selection(Scene *scene, BMEditMesh *em, bool implicit)
return false;
}
-void uvedit_get_aspect(Scene *scene, Object *ob, BMEditMesh *em, float *aspx, float *aspy)
+void ED_uvedit_get_aspect(Scene *scene, Object *ob, BMesh *bm, float *aspx, float *aspy)
{
bool sloppy = true;
bool selected = false;
BMFace *efa;
Image *ima;
- efa = BM_mesh_active_face_get(em->bm, sloppy, selected);
+ efa = BM_mesh_active_face_get(bm, sloppy, selected);
if (efa) {
if (BKE_scene_use_new_shading_nodes(scene)) {
ED_object_get_active_image(ob, efa->mat_nr + 1, &ima, NULL, NULL, NULL);
}
else {
- MTexPoly *tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
+ MTexPoly *tf = CustomData_bmesh_get(&bm->pdata, efa->head.data, CD_MTEXPOLY);
ima = tf->tpage;
}
@@ -247,11 +247,10 @@ static void construct_param_handle_face_add(ParamHandle *handle, Scene *scene,
param_face_add(handle, key, i, vkeys, co, uv, pin, select, efa->no);
}
-static ParamHandle *construct_param_handle(Scene *scene, Object *ob, BMEditMesh *em,
+static ParamHandle *construct_param_handle(Scene *scene, Object *ob, BMesh *bm,
const bool implicit, const bool fill, const bool sel,
const bool correct_aspect)
{
- BMesh *bm = em->bm;
ParamHandle *handle;
BMFace *efa;
BMLoop *l;
@@ -262,20 +261,19 @@ static ParamHandle *construct_param_handle(Scene *scene, Object *ob, BMEditMesh
handle = param_construct_begin();
-
if (correct_aspect) {
float aspx, aspy;
- uvedit_get_aspect(scene, ob, em, &aspx, &aspy);
+ ED_uvedit_get_aspect(scene, ob, bm, &aspx, &aspy);
if (aspx != aspy)
param_aspect_ratio(handle, aspx, aspy);
}
/* we need the vert indices */
- BM_mesh_elem_index_ensure(em->bm, BM_VERT);
+ BM_mesh_elem_index_ensure(bm, BM_VERT);
- BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
+ BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
if ((BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) || (sel && BM_elem_flag_test(efa, BM_ELEM_SELECT) == 0)) {
continue;
@@ -299,7 +297,7 @@ static ParamHandle *construct_param_handle(Scene *scene, Object *ob, BMEditMesh
}
if (!implicit) {
- BM_ITER_MESH (eed, &iter, em->bm, BM_EDGES_OF_MESH) {
+ BM_ITER_MESH (eed, &iter, bm, BM_EDGES_OF_MESH) {
if (BM_elem_flag_test(eed, BM_ELEM_SEAM)) {
ParamKey vkeys[2];
vkeys[0] = (ParamKey)BM_elem_index_get(eed->v1);
@@ -378,7 +376,7 @@ static ParamHandle *construct_param_handle_subsurfed(Scene *scene, Object *ob, B
if (correct_aspect) {
float aspx, aspy;
- uvedit_get_aspect(scene, ob, em, &aspx, &aspy);
+ ED_uvedit_get_aspect(scene, ob, em->bm, &aspx, &aspy);
if (aspx != aspy)
param_aspect_ratio(handle, aspx, aspy);
@@ -522,7 +520,7 @@ static bool minimize_stretch_init(bContext *C, wmOperator *op)
ms->blend = RNA_float_get(op->ptr, "blend");
ms->iterations = RNA_int_get(op->ptr, "iterations");
ms->i = 0;
- ms->handle = construct_param_handle(scene, obedit, em, implicit, fill_holes, 1, 1);
+ ms->handle = construct_param_handle(scene, obedit, em->bm, implicit, fill_holes, 1, 1);
ms->lasttime = PIL_check_seconds_timer();
param_stretch_begin(ms->handle);
@@ -683,7 +681,7 @@ void UV_OT_minimize_stretch(wmOperatorType *ot)
/* identifiers */
ot->name = "Minimize Stretch";
ot->idname = "UV_OT_minimize_stretch";
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_GRAB_POINTER | OPTYPE_BLOCKING;
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_GRAB_CURSOR | OPTYPE_BLOCKING;
ot->description = "Reduce UV stretching by relaxing angles";
/* api callbacks */
@@ -701,16 +699,23 @@ void UV_OT_minimize_stretch(wmOperatorType *ot)
/* ******************** Pack Islands operator **************** */
+void ED_uvedit_pack_islands(Scene *scene, Object *ob, BMesh *bm, bool selected, bool correct_aspect, bool do_rotate)
+{
+ ParamHandle *handle;
+ handle = construct_param_handle(scene, ob, bm, true, false, selected, correct_aspect);
+ param_pack(handle, scene->toolsettings->uvcalc_margin, do_rotate);
+ param_flush(handle);
+ param_delete(handle);
+}
+
static int pack_islands_exec(bContext *C, wmOperator *op)
{
Scene *scene = CTX_data_scene(C);
Object *obedit = CTX_data_edit_object(C);
BMEditMesh *em = BKE_editmesh_from_object(obedit);
- ParamHandle *handle;
- bool implicit = true;
bool do_rotate = RNA_boolean_get(op->ptr, "rotate");
- if (!uvedit_have_selection(scene, em, implicit)) {
+ if (!uvedit_have_selection(scene, em, true)) {
return OPERATOR_CANCELLED;
}
@@ -719,10 +724,7 @@ static int pack_islands_exec(bContext *C, wmOperator *op)
else
RNA_float_set(op->ptr, "margin", scene->toolsettings->uvcalc_margin);
- handle = construct_param_handle(scene, obedit, em, implicit, 0, 1, 1);
- param_pack(handle, scene->toolsettings->uvcalc_margin, do_rotate);
- param_flush(handle);
- param_delete(handle);
+ ED_uvedit_pack_islands(scene, obedit, em->bm, true, true, do_rotate);
DAG_id_tag_update(obedit->data, 0);
WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
@@ -762,7 +764,7 @@ static int average_islands_scale_exec(bContext *C, wmOperator *UNUSED(op))
return OPERATOR_CANCELLED;
}
- handle = construct_param_handle(scene, obedit, em, implicit, 0, 1, 1);
+ handle = construct_param_handle(scene, obedit, em->bm, implicit, 0, 1, 1);
param_average(handle);
param_flush(handle);
param_delete(handle);
@@ -807,7 +809,7 @@ void ED_uvedit_live_unwrap_begin(Scene *scene, Object *obedit)
if (use_subsurf)
liveHandle = construct_param_handle_subsurfed(scene, obedit, em, fillholes, false, true);
else
- liveHandle = construct_param_handle(scene, obedit, em, false, fillholes, false, true);
+ liveHandle = construct_param_handle(scene, obedit, em->bm, false, fillholes, false, true);
param_lscm_begin(liveHandle, PARAM_TRUE, abf);
}
@@ -1008,7 +1010,7 @@ static void correct_uv_aspect(Scene *scene, Object *ob, BMEditMesh *em)
const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
- uvedit_get_aspect(scene, ob, em, &aspx, &aspy);
+ ED_uvedit_get_aspect(scene, ob, em->bm, &aspx, &aspy);
if (aspx == aspy)
return;
@@ -1072,7 +1074,7 @@ static void uv_map_clip_correct(Scene *scene, Object *ob, BMEditMesh *em, wmOper
if (scale_to_bounds) {
INIT_MINMAX2(min, max);
-
+
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
if (!BM_elem_flag_test(efa, BM_ELEM_SELECT))
continue;
@@ -1082,7 +1084,7 @@ static void uv_map_clip_correct(Scene *scene, Object *ob, BMEditMesh *em, wmOper
minmax_v2v2_v2(min, max, luv->uv);
}
}
-
+
/* rescale UV to be in 1/1 */
dx = (max[0] - min[0]);
dy = (max[1] - min[1]);
@@ -1098,7 +1100,7 @@ static void uv_map_clip_correct(Scene *scene, Object *ob, BMEditMesh *em, wmOper
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
-
+
luv->uv[0] = (luv->uv[0] - min[0]) * dx;
luv->uv[1] = (luv->uv[1] - min[1]) * dy;
}
@@ -1128,7 +1130,7 @@ void ED_unwrap_lscm(Scene *scene, Object *obedit, const short sel)
ParamHandle *handle;
const bool fill_holes = (scene->toolsettings->uvcalc_flag & UVCALC_FILLHOLES) != 0;
- const bool correct_aspect = (scene->toolsettings->uvcalc_flag & UVCALC_NO_ASPECT_CORRECT) != 0;
+ const bool correct_aspect = (scene->toolsettings->uvcalc_flag & UVCALC_NO_ASPECT_CORRECT) == 0;
bool use_subsurf;
modifier_unwrap_state(obedit, scene, &use_subsurf);
@@ -1136,7 +1138,7 @@ void ED_unwrap_lscm(Scene *scene, Object *obedit, const short sel)
if (use_subsurf)
handle = construct_param_handle_subsurfed(scene, obedit, em, fill_holes, sel, correct_aspect);
else
- handle = construct_param_handle(scene, obedit, em, false, fill_holes, sel, correct_aspect);
+ handle = construct_param_handle(scene, obedit, em->bm, false, fill_holes, sel, correct_aspect);
param_lscm_begin(handle, PARAM_FALSE, scene->toolsettings->unwrapper == 0);
param_lscm_solve(handle);
@@ -1599,39 +1601,30 @@ void UV_OT_cylinder_project(wmOperatorType *ot)
/******************* Cube Project operator ****************/
-static int cube_project_exec(bContext *C, wmOperator *op)
+void ED_uvedit_unwrap_cube_project(Object *ob, BMesh *bm, float cube_size, bool use_select)
{
- Scene *scene = CTX_data_scene(C);
- Object *obedit = CTX_data_edit_object(C);
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
BMFace *efa;
BMLoop *l;
BMIter iter, liter;
/* MTexPoly *tf; */ /* UNUSED */
MLoopUV *luv;
- float cube_size, *loc, dx, dy;
+ float *loc, dx, dy;
int cox, coy;
int cd_loop_uv_offset;
- /* add uvs if they don't exist yet */
- if (!ED_uvedit_ensure_uvs(C, scene, obedit)) {
- return OPERATOR_CANCELLED;
- }
+ cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
- cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
-
- loc = obedit->obmat[3];
- cube_size = RNA_float_get(op->ptr, "cube_size");
+ loc = ob->obmat[3];
/* choose x,y,z axis for projection depending on the largest normal
* component, but clusters all together around the center of map. */
- BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
+ BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
int first = 1;
/* tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); */ /* UNUSED */
- if (!BM_elem_flag_test(efa, BM_ELEM_SELECT))
+ if (use_select && !BM_elem_flag_test(efa, BM_ELEM_SELECT))
continue;
axis_dominant_v3(&cox, &coy, efa->no);
@@ -1642,19 +1635,34 @@ static int cube_project_exec(bContext *C, wmOperator *op)
luv->uv[0] = 0.5f + 0.5f * cube_size * (loc[cox] + l->v->co[cox]);
luv->uv[1] = 0.5f + 0.5f * cube_size * (loc[coy] + l->v->co[coy]);
-
+
if (first) {
dx = floor(luv->uv[0]);
dy = floor(luv->uv[1]);
first = 0;
}
-
+
luv->uv[0] -= dx;
luv->uv[1] -= dy;
}
}
+}
+
+static int cube_project_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene = CTX_data_scene(C);
+ Object *obedit = CTX_data_edit_object(C);
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ float cube_size = RNA_float_get(op->ptr, "cube_size");
+
+ /* add uvs if they don't exist yet */
+ if (!ED_uvedit_ensure_uvs(C, scene, obedit)) {
+ return OPERATOR_CANCELLED;
+ }
+
+ ED_uvedit_unwrap_cube_project(obedit, em->bm, cube_size, true);
uv_map_clip_correct(scene, obedit, em, op);
DAG_id_tag_update(obedit->data, 0);
diff --git a/source/blender/freestyle/CMakeLists.txt b/source/blender/freestyle/CMakeLists.txt
index c94a5ac9f92..c14a5c53734 100644
--- a/source/blender/freestyle/CMakeLists.txt
+++ b/source/blender/freestyle/CMakeLists.txt
@@ -189,8 +189,6 @@ set(SRC
intern/python/StrokeShader/BPy_CalligraphicShader.h
intern/python/StrokeShader/BPy_ColorNoiseShader.cpp
intern/python/StrokeShader/BPy_ColorNoiseShader.h
- intern/python/StrokeShader/BPy_ColorVariationPatternShader.cpp
- intern/python/StrokeShader/BPy_ColorVariationPatternShader.h
intern/python/StrokeShader/BPy_ConstantColorShader.cpp
intern/python/StrokeShader/BPy_ConstantColorShader.h
intern/python/StrokeShader/BPy_ConstantThicknessShader.cpp
@@ -211,22 +209,12 @@ set(SRC
intern/python/StrokeShader/BPy_SmoothingShader.h
intern/python/StrokeShader/BPy_SpatialNoiseShader.cpp
intern/python/StrokeShader/BPy_SpatialNoiseShader.h
- intern/python/StrokeShader/BPy_StrokeTextureShader.cpp
- intern/python/StrokeShader/BPy_StrokeTextureShader.h
intern/python/StrokeShader/BPy_StrokeTextureStepShader.cpp
intern/python/StrokeShader/BPy_StrokeTextureStepShader.h
- intern/python/StrokeShader/BPy_TextureAssignerShader.cpp
- intern/python/StrokeShader/BPy_TextureAssignerShader.h
intern/python/StrokeShader/BPy_ThicknessNoiseShader.cpp
intern/python/StrokeShader/BPy_ThicknessNoiseShader.h
- intern/python/StrokeShader/BPy_ThicknessVariationPatternShader.cpp
- intern/python/StrokeShader/BPy_ThicknessVariationPatternShader.h
intern/python/StrokeShader/BPy_TipRemoverShader.cpp
intern/python/StrokeShader/BPy_TipRemoverShader.h
- intern/python/StrokeShader/BPy_fstreamShader.cpp
- intern/python/StrokeShader/BPy_fstreamShader.h
- intern/python/StrokeShader/BPy_streamShader.cpp
- intern/python/StrokeShader/BPy_streamShader.h
intern/python/UnaryFunction0D/BPy_UnaryFunction0DDouble.cpp
intern/python/UnaryFunction0D/BPy_UnaryFunction0DDouble.h
intern/python/UnaryFunction0D/BPy_UnaryFunction0DEdgeNature.cpp
@@ -404,6 +392,8 @@ set(SRC
intern/scene_graph/NodeGroup.h
intern/scene_graph/NodeLight.cpp
intern/scene_graph/NodeLight.h
+ intern/scene_graph/NodeSceneRenderLayer.cpp
+ intern/scene_graph/NodeSceneRenderLayer.h
intern/scene_graph/NodeShape.cpp
intern/scene_graph/NodeShape.h
intern/scene_graph/NodeTransform.cpp
@@ -412,6 +402,8 @@ set(SRC
intern/scene_graph/OrientedLineRep.h
intern/scene_graph/Rep.cpp
intern/scene_graph/Rep.h
+ intern/scene_graph/SceneHash.cpp
+ intern/scene_graph/SceneHash.h
intern/scene_graph/ScenePrettyPrinter.cpp
intern/scene_graph/ScenePrettyPrinter.h
intern/scene_graph/SceneVisitor.cpp
@@ -499,6 +491,7 @@ set(SRC
intern/system/TimeUtils.h
intern/view_map/ArbitraryGridDensityProvider.cpp
intern/view_map/ArbitraryGridDensityProvider.h
+ intern/view_map/AutoPtrHelper.h
intern/view_map/AverageAreaGridDensityProvider.cpp
intern/view_map/AverageAreaGridDensityProvider.h
intern/view_map/BoxGrid.cpp
@@ -585,6 +578,6 @@ if(WIN32)
list(APPEND INC_SYS
${PTHREADS_INC}
)
-endif(WIN32)
+endif()
blender_add_lib(bf_freestyle "${SRC}" "${INC}" "${INC_SYS}")
diff --git a/source/blender/freestyle/FRS_freestyle.h b/source/blender/freestyle/FRS_freestyle.h
index fc9fc35e410..975b1212695 100644
--- a/source/blender/freestyle/FRS_freestyle.h
+++ b/source/blender/freestyle/FRS_freestyle.h
@@ -45,9 +45,11 @@ void FRS_initialize(void);
void FRS_set_context(struct bContext *C);
void FRS_read_file(struct bContext *C);
int FRS_is_freestyle_enabled(struct SceneRenderLayer *srl);
-void FRS_init_stroke_rendering(struct Render *re);
+void FRS_init_stroke_renderer(struct Render *re);
+void FRS_begin_stroke_rendering(struct Render *re);
struct Render *FRS_do_stroke_rendering(struct Render *re, struct SceneRenderLayer *srl, int render);
-void FRS_finish_stroke_rendering(struct Render *re);
+void FRS_end_stroke_rendering(struct Render *re);
+void FRS_free_view_map_cache(void);
void FRS_composite_result(struct Render *re, struct SceneRenderLayer *srl, struct Render *freestyle_render);
void FRS_exit(void);
diff --git a/source/blender/freestyle/intern/application/AppConfig.cpp b/source/blender/freestyle/intern/application/AppConfig.cpp
index cf7959ffaef..44f8e9b135e 100644
--- a/source/blender/freestyle/intern/application/AppConfig.cpp
+++ b/source/blender/freestyle/intern/application/AppConfig.cpp
@@ -31,7 +31,7 @@
using namespace std;
extern "C" {
-#include "BLI_path_util.h"
+#include "BKE_appdir.h"
}
namespace Freestyle {
@@ -43,7 +43,7 @@ Path::Path()
{
// get the root directory
// soc
- setRootDir(BLI_get_folder(BLENDER_SYSTEM_SCRIPTS, NULL));
+ setRootDir(BKE_appdir_folder_id(BLENDER_SYSTEM_SCRIPTS, NULL));
_pInstance = this;
}
diff --git a/source/blender/freestyle/intern/application/AppView.cpp b/source/blender/freestyle/intern/application/AppView.cpp
index ae202412c09..9de426b91ab 100644
--- a/source/blender/freestyle/intern/application/AppView.cpp
+++ b/source/blender/freestyle/intern/application/AppView.cpp
@@ -58,7 +58,7 @@ extern "C" {
namespace Freestyle {
-AppView::AppView(const char *iName)
+AppView::AppView(const char * /*iName*/)
{
_Fovy = DEG2RADF(30.0f);
_ModelRootNode = new NodeDrawingStyle;
diff --git a/source/blender/freestyle/intern/application/AppView.h b/source/blender/freestyle/intern/application/AppView.h
index 14101909ca1..6338ace53c0 100644
--- a/source/blender/freestyle/intern/application/AppView.h
+++ b/source/blender/freestyle/intern/application/AppView.h
@@ -100,12 +100,12 @@ public:
_SilhouetteRootNode->AddChild(iSilhouette);
}
- inline void Add2DSilhouette(NodeGroup *iSilhouette)
+ inline void Add2DSilhouette(NodeGroup * /*iSilhouette*/)
{
//_pFENode->AddChild(iSilhouette);
}
- inline void Add2DVisibleSilhouette(NodeGroup *iVSilhouette)
+ inline void Add2DVisibleSilhouette(NodeGroup * /*iVSilhouette*/)
{
//_pVisibleSilhouetteNode->AddChild(iVSilhouette);
}
diff --git a/source/blender/freestyle/intern/application/Controller.cpp b/source/blender/freestyle/intern/application/Controller.cpp
index 176199600ac..8983a781237 100644
--- a/source/blender/freestyle/intern/application/Controller.cpp
+++ b/source/blender/freestyle/intern/application/Controller.cpp
@@ -40,6 +40,7 @@ extern "C" {
#include "../scene_graph/NodeDrawingStyle.h"
#include "../scene_graph/NodeShape.h"
#include "../scene_graph/NodeTransform.h"
+#include "../scene_graph/NodeSceneRenderLayer.h"
#include "../scene_graph/ScenePrettyPrinter.h"
#include "../scene_graph/VertexRep.h"
@@ -67,6 +68,7 @@ extern "C" {
#include "BKE_global.h"
#include "BLI_utildefines.h"
+#include "BLI_path_util.h"
#include "DNA_freestyle_types.h"
@@ -86,14 +88,14 @@ Controller::Controller()
_RootNode = new NodeGroup;
_RootNode->addRef();
- _SilhouetteNode = NULL;
#if 0
+ _SilhouetteNode = NULL;
_ProjectedSilhouette = NULL;
_VisibleProjectedSilhouette = NULL;
-#endif
_DebugNode = new NodeGroup;
_DebugNode->addRef();
+#endif
_winged_edge = NULL;
@@ -118,6 +120,7 @@ Controller::Controller()
_Canvas = new AppCanvas;
_inter = new PythonInterpreter();
+ _EnableViewMapCache = false;
_EnableQI = true;
_EnableFaceSmoothness = false;
_ComputeRidges = true;
@@ -126,6 +129,7 @@ Controller::Controller()
_ComputeMaterialBoundaries = true;
_sphereRadius = 1.0;
_creaseAngle = 134.43;
+ prevSceneHash = -1.0;
init_options();
}
@@ -138,6 +142,7 @@ Controller::~Controller()
delete _RootNode;
}
+#if 0
if (NULL != _SilhouetteNode) {
int ref = _SilhouetteNode->destroy();
if (0 == ref)
@@ -149,6 +154,7 @@ Controller::~Controller()
if (0 == ref)
delete _DebugNode;
}
+#endif
if (_winged_edge) {
delete _winged_edge;
@@ -212,6 +218,18 @@ void Controller::setContext(bContext *C)
py_inter->setContext(C);
}
+bool Controller::hitViewMapCache()
+{
+ if (!_EnableViewMapCache) {
+ return false;
+ }
+ if (sceneHashFunc.match()) {
+ return (NULL != _ViewMap);
+ }
+ sceneHashFunc.store();
+ return false;
+}
+
int Controller::LoadMesh(Render *re, SceneRenderLayer *srl)
{
BlenderFileLoader loader(re, srl);
@@ -242,6 +260,7 @@ int Controller::LoadMesh(Render *re, SceneRenderLayer *srl)
if (G.debug & G_DEBUG_FREESTYLE) {
cout << "Scene loaded" << endl;
printf("Mesh cleaning : %lf\n", duration);
+ printf("View map cache : %s\n", _EnableViewMapCache ? "enabled" : "disabled");
}
_SceneNumFaces += loader.numFacesRead();
@@ -263,6 +282,39 @@ int Controller::LoadMesh(Render *re, SceneRenderLayer *srl)
if (_pRenderMonitor->testBreak())
return 0;
+ if (_EnableViewMapCache) {
+
+ NodeCamera *cam;
+ if (freestyle_proj[3][3] != 0.0)
+ cam = new NodeOrthographicCamera;
+ else
+ cam = new NodePerspectiveCamera;
+ double proj[16];
+ for (int i = 0; i < 4; i++) {
+ for (int j = 0; j < 4; j++) {
+ proj[i * 4 + j] = freestyle_proj[i][j];
+ }
+ }
+ cam->setProjectionMatrix(proj);
+ _RootNode->AddChild(cam);
+ _RootNode->AddChild(new NodeSceneRenderLayer(*re->scene, *srl));
+
+ sceneHashFunc.reset();
+ //blenderScene->accept(sceneHashFunc);
+ _RootNode->accept(sceneHashFunc);
+ if (G.debug & G_DEBUG_FREESTYLE) {
+ cout << "Scene hash : " << sceneHashFunc.toString() << endl;
+ }
+ if (hitViewMapCache()) {
+ ClearRootNode();
+ return 0;
+ }
+ else {
+ delete _ViewMap;
+ _ViewMap = NULL;
+ }
+ }
+
_Chrono.start();
WXEdgeBuilder wx_builder;
@@ -357,8 +409,9 @@ void Controller::DeleteWingedEdge()
_minEdgeSize = DBL_MAX;
}
-void Controller::DeleteViewMap()
+void Controller::DeleteViewMap(bool freeCache)
{
+#if 0
_pView->DetachSilhouette();
if (NULL != _SilhouetteNode) {
int ref = _SilhouetteNode->destroy();
@@ -368,7 +421,6 @@ void Controller::DeleteViewMap()
}
}
-#if 0
if (NULL != _ProjectedSilhouette) {
int ref = _ProjectedSilhouette->destroy();
if (0 == ref) {
@@ -383,18 +435,24 @@ void Controller::DeleteViewMap()
_VisibleProjectedSilhouette = NULL;
}
}
-#endif
_pView->DetachDebug();
if (NULL != _DebugNode) {
- int ref = _DebugNode->destroy();
+ int ref = _DebugNode->destroy();
if (0 == ref)
_DebugNode->addRef();
}
+#endif
if (NULL != _ViewMap) {
- delete _ViewMap;
- _ViewMap = NULL;
+ if (freeCache || !_EnableViewMapCache) {
+ delete _ViewMap;
+ _ViewMap = NULL;
+ prevSceneHash = -1.0;
+ }
+ else {
+ _ViewMap->Clean();
+ }
}
}
@@ -403,40 +461,7 @@ void Controller::ComputeViewMap()
if (!_ListOfModels.size())
return;
- if (NULL != _ViewMap) {
- delete _ViewMap;
- _ViewMap = NULL;
- }
-
- _pView->DetachDebug();
- if (NULL != _DebugNode) {
- int ref = _DebugNode->destroy();
- if (0 == ref)
- _DebugNode->addRef();
- }
-
- _pView->DetachSilhouette();
- if (NULL != _SilhouetteNode) {
- int ref = _SilhouetteNode->destroy();
- if (0 == ref)
- delete _SilhouetteNode;
- }
-
-#if 0
- if (NULL != _ProjectedSilhouette) {
- int ref = _ProjectedSilhouette->destroy();
- if (0 == ref)
- delete _ProjectedSilhouette;
- }
-
- if (NULL != _VisibleProjectedSilhouette) {
- int ref = _VisibleProjectedSilhouette->destroy();
- if (0 == ref) {
- delete _VisibleProjectedSilhouette;
- _VisibleProjectedSilhouette = NULL;
- }
- }
-#endif
+ DeleteViewMap(true);
// retrieve the 3D viewpoint and transformations information
//----------------------------------------------------------
@@ -446,7 +471,7 @@ void Controller::ComputeViewMap()
// Restore the context of view:
// we need to perform all these operations while the
// 3D context is on.
- Vec3r vp(freestyle_viewpoint[0], freestyle_viewpoint[1], freestyle_viewpoint[2]);
+ Vec3f vp(freestyle_viewpoint[0], freestyle_viewpoint[1], freestyle_viewpoint[2]);
#if 0
if (G.debug & G_DEBUG_FREESTYLE) {
@@ -510,7 +535,7 @@ void Controller::ComputeViewMap()
}
_Chrono.start();
- edgeDetector.setViewpoint(Vec3r(vp));
+ edgeDetector.setViewpoint(vp);
edgeDetector.enableOrthographicProjection(proj[3][3] != 0.0);
edgeDetector.enableRidgesAndValleysFlag(_ComputeRidges);
edgeDetector.enableSuggestiveContours(_ComputeSuggestive);
@@ -534,20 +559,20 @@ void Controller::ComputeViewMap()
//----------------------------------------------------------
ViewMapBuilder vmBuilder;
vmBuilder.setEnableQI(_EnableQI);
- vmBuilder.setViewpoint(Vec3r(vp));
+ vmBuilder.setViewpoint(vp);
vmBuilder.setTransform(mv, proj, viewport, _pView->GetFocalLength(), _pView->GetAspect(), _pView->GetFovyRadian());
vmBuilder.setFrustum(_pView->znear(), _pView->zfar());
vmBuilder.setGrid(&_Grid);
vmBuilder.setRenderMonitor(_pRenderMonitor);
+#if 0
// Builds a tesselated form of the silhouette for display purpose:
//---------------------------------------------------------------
ViewMapTesselator3D sTesselator3d;
-#if 0
ViewMapTesselator2D sTesselator2d;
sTesselator2d.setNature(_edgeTesselationNature);
-#endif
sTesselator3d.setNature(_edgeTesselationNature);
+#endif
if (G.debug & G_DEBUG_FREESTYLE) {
cout << "\n=== Building the view map ===" << endl;
@@ -561,12 +586,12 @@ void Controller::ComputeViewMap()
printf("ViewMap edge count : %i\n", _ViewMap->viewedges_size());
}
+#if 0
// Tesselate the 3D edges:
_SilhouetteNode = sTesselator3d.Tesselate(_ViewMap);
_SilhouetteNode->addRef();
// Tesselate 2D edges
-#if 0
_ProjectedSilhouette = sTesselator2d.Tesselate(_ViewMap);
_ProjectedSilhouette->addRef();
#endif
@@ -576,13 +601,13 @@ void Controller::ComputeViewMap()
printf("ViewMap building : %lf\n", duration);
}
- _pView->AddSilhouette(_SilhouetteNode);
#if 0
+ _pView->AddSilhouette(_SilhouetteNode);
_pView->AddSilhouette(_WRoot);
_pView->Add2DSilhouette(_ProjectedSilhouette);
_pView->Add2DVisibleSilhouette(_VisibleProjectedSilhouette);
-#endif
_pView->AddDebug(_DebugNode);
+#endif
// Draw the steerable density map:
//--------------------------------
@@ -763,6 +788,16 @@ int Controller::getVisibilityAlgo()
return FREESTYLE_ALGO_ADAPTIVE_TRADITIONAL;
}
+void Controller::setViewMapCache(bool iBool)
+{
+ _EnableViewMapCache = iBool;
+}
+
+bool Controller::getViewMapCache() const
+{
+ return _EnableViewMapCache;
+}
+
void Controller::setQuantitativeInvisibility(bool iBool)
{
_EnableQI = iBool;
@@ -836,7 +871,7 @@ void Controller::DrawStrokes()
real d = _Chrono.stop();
if (G.debug & G_DEBUG_FREESTYLE) {
cout << "Strokes generation : " << d << endl;
- cout << "Stroke count : " << _Canvas->stroke_count << endl;
+ cout << "Stroke count : " << _Canvas->getStrokeCount() << endl;
}
resetModified();
DeleteViewMap();
@@ -849,10 +884,13 @@ void Controller::ResetRenderCount()
Render *Controller::RenderStrokes(Render *re, bool render)
{
+ int totmesh = 0;
_Chrono.start();
BlenderStrokeRenderer *blenderRenderer = new BlenderStrokeRenderer(re, ++_render_count);
- if (render)
+ if (render) {
_Canvas->Render(blenderRenderer);
+ totmesh = blenderRenderer->GenerateScene();
+ }
real d = _Chrono.stop();
if (G.debug & G_DEBUG_FREESTYLE) {
cout << "Temporary scene generation: " << d << endl;
@@ -871,8 +909,8 @@ Render *Controller::RenderStrokes(Render *re, bool render)
float mmap_used_memory = (mmap_in_use) / (1024.0 * 1024.0);
float megs_peak_memory = (peak_memory) / (1024.0 * 1024.0);
- printf("%d verts, %d faces, mem %.2fM (%.2fM, peak %.2fM)\n",
- freestyle_render->i.totvert, freestyle_render->i.totface,
+ printf("%d objs, %d verts, %d faces, mem %.2fM (%.2fM, peak %.2fM)\n",
+ totmesh, freestyle_render->i.totvert, freestyle_render->i.totface,
megs_used_memory, mmap_used_memory, megs_peak_memory);
}
delete blenderRenderer;
@@ -891,13 +929,19 @@ void Controller::InsertStyleModule(unsigned index, const char *iFileName)
_Canvas->InsertStyleModule(index, sm);
}
+void Controller::InsertStyleModule(unsigned index, const char *iName, const char *iBuffer)
+{
+ StyleModule *sm = new BufferedStyleModule(iBuffer, iName, _inter);
+ _Canvas->InsertStyleModule(index, sm);
+}
+
void Controller::InsertStyleModule(unsigned index, const char *iName, struct Text *iText)
{
StyleModule *sm = new BlenderStyleModule(iText, iName, _inter);
_Canvas->InsertStyleModule(index, sm);
}
-void Controller::AddStyleModule(const char *iFileName)
+void Controller::AddStyleModule(const char * /*iFileName*/)
{
//_pStyleWindow->Add(iFileName);
}
@@ -967,7 +1011,7 @@ void Controller::toggleEdgeTesselationNature(Nature::EdgeNature iNature)
ComputeViewMap();
}
-void Controller::setModelsDir(const string& dir)
+void Controller::setModelsDir(const string& /*dir*/)
{
//_current_dirs->setValue("models/dir", dir);
}
@@ -979,7 +1023,7 @@ string Controller::getModelsDir() const
return dir;
}
-void Controller::setModulesDir(const string& dir)
+void Controller::setModulesDir(const string& /*dir*/)
{
//_current_dirs->setValue("modules/dir", dir);
}
diff --git a/source/blender/freestyle/intern/application/Controller.h b/source/blender/freestyle/intern/application/Controller.h
index f5e50347d0f..22eaaf5082f 100644
--- a/source/blender/freestyle/intern/application/Controller.h
+++ b/source/blender/freestyle/intern/application/Controller.h
@@ -30,37 +30,28 @@
#include <string>
-//#include "ConfigIO.h"
#include "../geometry/FastGrid.h"
-#include "../system/Interpreter.h"
-#include "../system/ProgressBar.h"
+#include "../scene_graph/SceneHash.h"
#include "../system/Precision.h"
-#include "../system/RenderMonitor.h"
#include "../system/TimeUtils.h"
#include "../view_map/FEdgeXDetector.h"
#include "../view_map/ViewMapBuilder.h"
-extern "C" {
-#include "render_types.h"
-#include "DNA_scene_types.h"
-}
-
#ifdef WITH_CXX_GUARDEDALLOC
#include "MEM_guardedalloc.h"
#endif
namespace Freestyle {
+class AppCanvas;
class AppView;
+class Interpreter;
class NodeGroup;
-class WShape;
+class ProgressBar;
+class RenderMonitor;
class SShape;
-class ViewMap;
class ViewEdge;
-class AppCanvas;
-class InteractiveShader;
-class Shader;
-class StrokeRenderer;
+class ViewMap;
class Controller
{
@@ -89,6 +80,7 @@ public:
Render *RenderStrokes(Render *re, bool render);
void SwapStyleModules(unsigned i1, unsigned i2);
void InsertStyleModule(unsigned index, const char *iFileName);
+ void InsertStyleModule(unsigned index, const char *iName, const char *iBuffer);
void InsertStyleModule(unsigned index, const char *iName, struct Text *iText);
void AddStyleModule(const char *iFileName);
void RemoveStyleModule(unsigned index);
@@ -96,7 +88,7 @@ public:
void Clear();
void ClearRootNode();
void DeleteWingedEdge();
- void DeleteViewMap();
+ void DeleteViewMap(bool freeCache = false);
void toggleLayer(unsigned index, bool iDisplay);
void setModified(unsigned index, bool iMod);
void resetModified(bool iMod=false);
@@ -118,6 +110,8 @@ public:
void setVisibilityAlgo(int algo);
int getVisibilityAlgo();
+ void setViewMapCache(bool iBool);
+ bool getViewMapCache() const;
void setQuantitativeInvisibility(bool iBool); // if true, we compute quantitativeInvisibility
bool getQuantitativeInvisibility() const;
void setFaceSmoothness(bool iBool);
@@ -132,18 +126,20 @@ public:
void setComputeSteerableViewMapFlag(bool iBool);
bool getComputeSteerableViewMapFlag() const;
- void setCreaseAngle(real angle) {_creaseAngle = angle;}
- real getCreaseAngle() const {return _creaseAngle;}
- void setSphereRadius(real s) {_sphereRadius = s;}
- real getSphereRadius() const {return _sphereRadius;}
- void setSuggestiveContourKrDerivativeEpsilon(real dkr) {_suggestiveContourKrDerivativeEpsilon = dkr;}
- real getSuggestiveContourKrDerivativeEpsilon() const {return _suggestiveContourKrDerivativeEpsilon;}
+ void setCreaseAngle(float angle) {_creaseAngle = angle;}
+ float getCreaseAngle() const {return _creaseAngle;}
+ void setSphereRadius(float s) {_sphereRadius = s;}
+ float getSphereRadius() const {return _sphereRadius;}
+ void setSuggestiveContourKrDerivativeEpsilon(float dkr) {_suggestiveContourKrDerivativeEpsilon = dkr;}
+ float getSuggestiveContourKrDerivativeEpsilon() const {return _suggestiveContourKrDerivativeEpsilon;}
void setModelsDir(const string& dir);
string getModelsDir() const;
void setModulesDir(const string& dir);
string getModulesDir() const;
+ bool hitViewMapCache();
+
void resetInterpreter();
public:
@@ -182,11 +178,10 @@ private:
// Winged-Edge structure
WingedEdge *_winged_edge;
- // Silhouette structure:
#if 0
+ // Silhouette structure:
std::vector<SShape*> _SShapes;
NodeGroup *_SRoot;
-#endif
// Silhouette
NodeGroup *_SilhouetteNode;
@@ -195,6 +190,7 @@ private:
// more Debug info
NodeGroup *_DebugNode;
+#endif
// debug
//NodeUser<ViewMap> *_ViewMapNode; // FIXME
@@ -231,19 +227,23 @@ private:
string _help_index;
string _browser_cmd;
+ bool _EnableViewMapCache;
bool _EnableQI;
bool _EnableFaceSmoothness;
bool _ComputeRidges;
bool _ComputeSuggestive;
bool _ComputeMaterialBoundaries;
- real _creaseAngle;
- real _sphereRadius;
- real _suggestiveContourKrDerivativeEpsilon;
+ float _creaseAngle;
+ float _sphereRadius;
+ float _suggestiveContourKrDerivativeEpsilon;
bool _ComputeSteerableViewMap;
FEdgeXDetector edgeDetector;
+ SceneHash sceneHashFunc;
+ real prevSceneHash;
+
#ifdef WITH_CXX_GUARDEDALLOC
MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:Controller")
#endif
diff --git a/source/blender/freestyle/intern/blender_interface/BlenderFileLoader.cpp b/source/blender/freestyle/intern/blender_interface/BlenderFileLoader.cpp
index 57882cbce0c..2b0d3b14697 100644
--- a/source/blender/freestyle/intern/blender_interface/BlenderFileLoader.cpp
+++ b/source/blender/freestyle/intern/blender_interface/BlenderFileLoader.cpp
@@ -64,12 +64,11 @@ NodeGroup *BlenderFileLoader::Load()
_viewplane_bottom = _re->viewplane.ymin;
_viewplane_top = _re->viewplane.ymax;
- if ((_re->r.scemode & R_VIEWPORT_PREVIEW) && (_re->r.mode & R_ORTHO)) {
+ if (_re->clipsta < 0.f) {
// Adjust clipping start/end and set up a Z offset when the viewport preview
// is used with the orthographic view. In this case, _re->clipsta is negative,
// while Freestyle assumes that imported mesh data are in the camera coordinate
// system with the view point located at origin [bug #36009].
- BLI_assert(_re->clipsta < 0.f);
_z_near = -0.001f;
_z_offset = _re->clipsta + _z_near;
_z_far = -_re->clipend + _z_offset;
@@ -256,6 +255,7 @@ void BlenderFileLoader::clipTriangle(int numTris, float triCoords[][3], float v1
}
}
BLI_assert(k == 2 + numTris);
+ (void)numTris; /* Ignored in release builds. */
}
void BlenderFileLoader::addTriangle(struct LoaderState *ls, float v1[3], float v2[3], float v3[3],
@@ -457,6 +457,7 @@ void BlenderFileLoader::insertShapeNode(ObjectInstanceRen *obi, int id)
unsigned nSize = vSize;
float *normals = new float[nSize];
unsigned *numVertexPerFaces = new unsigned[numFaces];
+ vector<Material *> meshMaterials;
vector<FrsMaterial> meshFrsMaterials;
IndexedFaceSet::TRIANGLES_STYLE *faceStyle = new IndexedFaceSet::TRIANGLES_STYLE[numFaces];
@@ -535,8 +536,12 @@ void BlenderFileLoader::insertShapeNode(ObjectInstanceRen *obi, int id)
else {
RE_vlakren_get_normal(_re, obi, vlr, facenormal);
#ifndef NDEBUG
+ /* test if normals are inverted in rendering [T39669] */
float tnor[3];
- normal_tri_v3(tnor, v3, v2, v1); /* normals are inverted in rendering */
+ if (vlr->v4)
+ normal_quad_v3(tnor, v4, v3, v2, v1);
+ else
+ normal_tri_v3(tnor, v3, v2, v1);
BLI_assert(dot_v3v3(tnor, facenormal) > 0.0f);
#endif
copy_v3_v3(n1, facenormal);
@@ -588,20 +593,21 @@ void BlenderFileLoader::insertShapeNode(ObjectInstanceRen *obi, int id)
tmpMat.setPriority(mat->line_priority);
}
- if (meshFrsMaterials.empty()) {
+ if (meshMaterials.empty()) {
+ meshMaterials.push_back(mat);
meshFrsMaterials.push_back(tmpMat);
shape->setFrsMaterial(tmpMat);
}
else {
- // find if the material is already in the list
+ // find if the Blender material is already in the list
unsigned int i = 0;
bool found = false;
- for (vector<FrsMaterial>::iterator it = meshFrsMaterials.begin(), itend = meshFrsMaterials.end();
+ for (vector<Material *>::iterator it = meshMaterials.begin(), itend = meshMaterials.end();
it != itend;
it++, i++)
{
- if (*it == tmpMat) {
+ if (*it == mat) {
ls.currentMIndex = i;
found = true;
break;
@@ -609,6 +615,7 @@ void BlenderFileLoader::insertShapeNode(ObjectInstanceRen *obi, int id)
}
if (!found) {
+ meshMaterials.push_back(mat);
meshFrsMaterials.push_back(tmpMat);
ls.currentMIndex = meshFrsMaterials.size() - 1;
}
@@ -656,13 +663,13 @@ void BlenderFileLoader::insertShapeNode(ObjectInstanceRen *obi, int id)
// We might have several times the same vertex. We want a clean
// shape with no real-vertex. Here, we are making a cleaning pass.
- real *cleanVertices = NULL;
+ float *cleanVertices = NULL;
unsigned int cvSize;
unsigned int *cleanVIndices = NULL;
GeomCleaner::CleanIndexedVertexArray(vertices, vSize, VIndices, viSize, &cleanVertices, &cvSize, &cleanVIndices);
- real *cleanNormals = NULL;
+ float *cleanNormals = NULL;
unsigned int cnSize;
unsigned int *cleanNIndices = NULL;
@@ -769,12 +776,12 @@ void BlenderFileLoader::insertShapeNode(ObjectInstanceRen *obi, int id)
for (v = detriList.begin(); v != detriList.end(); v++) {
detri_t detri = (*v);
if (detri.n == 0) {
- cleanVertices[detri.viP] = cleanVertices[detri.viA];
+ cleanVertices[detri.viP] = cleanVertices[detri.viA];
cleanVertices[detri.viP + 1] = cleanVertices[detri.viA + 1];
cleanVertices[detri.viP + 2] = cleanVertices[detri.viA + 2];
}
else if (detri.v.norm() > 0.0) {
- cleanVertices[detri.viP] += 1.0e-5 * detri.v.x();
+ cleanVertices[detri.viP] += 1.0e-5 * detri.v.x();
cleanVertices[detri.viP + 1] += 1.0e-5 * detri.v.y();
cleanVertices[detri.viP + 2] += 1.0e-5 * detri.v.z();
}
diff --git a/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp b/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp
index 456118d4d2f..64ef49d74a3 100644
--- a/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp
+++ b/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp
@@ -66,6 +66,8 @@ extern "C" {
namespace Freestyle {
+const char *BlenderStrokeRenderer::uvNames[] = {"along_stroke", "along_stroke_tips"};
+
BlenderStrokeRenderer::BlenderStrokeRenderer(Render *re, int render_count) : StrokeRenderer()
{
freestyle_bmain = re->freestyle_bmain;
@@ -92,7 +94,7 @@ BlenderStrokeRenderer::BlenderStrokeRenderer(Render *re, int render_count) : Str
//freestyle_scene->r.maximsize = old_scene->r.maximsize; /* DEPRECATED */
freestyle_scene->r.ocres = old_scene->r.ocres;
freestyle_scene->r.color_mgt_flag = 0; // old_scene->r.color_mgt_flag;
- freestyle_scene->r.scemode = old_scene->r.scemode & ~(R_SINGLE_LAYER | R_NO_FRAME_UPDATE);
+ freestyle_scene->r.scemode = old_scene->r.scemode & ~(R_SINGLE_LAYER | R_NO_FRAME_UPDATE | R_MULTIVIEW);
freestyle_scene->r.flag = old_scene->r.flag;
freestyle_scene->r.threads = old_scene->r.threads;
freestyle_scene->r.border.xmin = old_scene->r.border.xmin;
@@ -124,7 +126,8 @@ BlenderStrokeRenderer::BlenderStrokeRenderer(Render *re, int render_count) : Str
BKE_scene_set_background(freestyle_bmain, freestyle_scene);
// Camera
- Object *object_camera = BKE_object_add(freestyle_bmain, freestyle_scene, OB_CAMERA);
+ Object *object_camera = BKE_object_add(freestyle_bmain, freestyle_scene, OB_CAMERA, NULL);
+ DAG_relations_tag_update(freestyle_bmain);
Camera *camera = (Camera *)object_camera->data;
camera->type = CAM_ORTHO;
@@ -208,6 +211,8 @@ BlenderStrokeRenderer::~BlenderStrokeRenderer()
if (_use_shading_nodes)
BLI_ghash_free(_nodetree_hash, NULL, NULL);
+
+ FreeStrokeGroups();
}
float BlenderStrokeRenderer::get_stroke_vertex_z(void) const
@@ -414,10 +419,10 @@ Material* BlenderStrokeRenderer::GetStrokeShader(Main *bmain, bNodeTree *iNodeTr
input_uvmap->locy = node->locy;
NodeShaderUVMap *storage = (NodeShaderUVMap *)input_uvmap->storage;
if (node->custom1 & 1) { // use_tips
- BLI_strncpy(storage->uv_map, "along_stroke_tips", sizeof(storage->uv_map));
+ BLI_strncpy(storage->uv_map, uvNames[1], sizeof(storage->uv_map));
}
else {
- BLI_strncpy(storage->uv_map, "along_stroke", sizeof(storage->uv_map));
+ BLI_strncpy(storage->uv_map, uvNames[0], sizeof(storage->uv_map));
}
fromsock = (bNodeSocket *)BLI_findlink(&input_uvmap->outputs, 0); // UV
@@ -440,6 +445,11 @@ Material* BlenderStrokeRenderer::GetStrokeShader(Main *bmain, bNodeTree *iNodeTr
void BlenderStrokeRenderer::RenderStrokeRep(StrokeRep *iStrokeRep) const
{
+ RenderStrokeRepBasic(iStrokeRep);
+}
+
+void BlenderStrokeRenderer::RenderStrokeRepBasic(StrokeRep *iStrokeRep) const
+{
if (_use_shading_nodes) {
bNodeTree *nt = iStrokeRep->getNodeTree();
Material *ma = (Material *)BLI_ghash_lookup(_nodetree_hash, nt);
@@ -448,7 +458,7 @@ void BlenderStrokeRenderer::RenderStrokeRep(StrokeRep *iStrokeRep) const
BLI_ghash_insert(_nodetree_hash, nt, ma);
}
- if (strcmp(freestyle_scene->r.engine, "CYCLES") == 0) {
+ if (STREQ(freestyle_scene->r.engine, RE_engine_id_CYCLES)) {
PointerRNA scene_ptr, freestyle_scene_ptr;
RNA_pointer_create(NULL, &RNA_Scene, old_scene, &scene_ptr);
RNA_pointer_create(NULL, &RNA_Scene, freestyle_scene, &freestyle_scene_ptr);
@@ -497,6 +507,7 @@ void BlenderStrokeRenderer::RenderStrokeRep(StrokeRep *iStrokeRep) const
// If still no material, create one
if (!has_mat) {
Material *ma = BKE_material_add(freestyle_bmain, "stroke_material");
+ DAG_relations_tag_update(freestyle_bmain);
ma->mode |= MA_VERTEXCOLP;
ma->mode |= MA_TRANSP;
ma->mode |= MA_SHLESS;
@@ -509,10 +520,10 @@ void BlenderStrokeRenderer::RenderStrokeRep(StrokeRep *iStrokeRep) const
// We'll generate both with tips and without tips
// coordinates, on two different UV layers.
if (ma->mtex[a]->texflag & MTEX_TIPS) {
- BLI_strncpy(ma->mtex[a]->uvname, "along_stroke_tips", sizeof(ma->mtex[a]->uvname));
+ BLI_strncpy(ma->mtex[a]->uvname, uvNames[1], sizeof(ma->mtex[a]->uvname));
}
else {
- BLI_strncpy(ma->mtex[a]->uvname, "along_stroke", sizeof(ma->mtex[a]->uvname));
+ BLI_strncpy(ma->mtex[a]->uvname, uvNames[0], sizeof(ma->mtex[a]->uvname));
}
a++;
}
@@ -521,7 +532,42 @@ void BlenderStrokeRenderer::RenderStrokeRep(StrokeRep *iStrokeRep) const
}
}
- RenderStrokeRepBasic(iStrokeRep);
+ const vector<Strip*>& strips = iStrokeRep->getStrips();
+ const bool hasTex = iStrokeRep->hasTex();
+ int totvert = 0, totedge = 0, totpoly = 0, totloop = 0;
+ int visible_faces, visible_segments;
+ for (vector<Strip*>::const_iterator s = strips.begin(), send = strips.end(); s != send; ++s) {
+ Strip::vertex_container& strip_vertices = (*s)->vertices();
+
+ // count visible faces and strip segments
+ test_strip_visibility(strip_vertices, &visible_faces, &visible_segments);
+ if (visible_faces == 0)
+ continue;
+
+ totvert += visible_faces + visible_segments * 2;
+ totedge += visible_faces * 2 + visible_segments;
+ totpoly += visible_faces;
+ totloop += visible_faces * 3;
+ }
+
+ BlenderStrokeRenderer *self = const_cast<BlenderStrokeRenderer *>(this); // FIXME
+ vector<StrokeGroup*> *groups = hasTex ? &self->texturedStrokeGroups : &self->strokeGroups;
+ StrokeGroup *group;
+ if (groups->empty() || !(groups->back()->totvert + totvert < MESH_MAX_VERTS &&
+ groups->back()->totcol + 1 < MAXMAT))
+ {
+ group = new StrokeGroup;
+ groups->push_back(group);
+ }
+ else {
+ group = groups->back();
+ }
+ group->strokes.push_back(iStrokeRep);
+ group->totvert += totvert;
+ group->totedge += totedge;
+ group->totpoly += totpoly;
+ group->totloop += totloop;
+ group->totcol++;
}
// Check if the triangle is visible (i.e., within the render image boundary)
@@ -578,127 +624,174 @@ void BlenderStrokeRenderer::test_strip_visibility(Strip::vertex_container& strip
}
}
-// Build a mesh object representing a stroke
-void BlenderStrokeRenderer::RenderStrokeRepBasic(StrokeRep *iStrokeRep) const
+// Release allocated memory for stroke groups
+void BlenderStrokeRenderer::FreeStrokeGroups()
{
- vector<Strip*>& strips = iStrokeRep->getStrips();
- const bool hasTex = iStrokeRep->hasTex();
- Strip::vertex_container::iterator v[3];
- StrokeVertexRep *svRep[3];
- unsigned int vertex_index, edge_index, loop_index;
- Vec2r p;
-
- int totvert = 0, totedge = 0, totpoly = 0, totloop = 0;
- int visible_faces, visible_segments;
+ vector<StrokeGroup*>::const_iterator it, itend;
- bool visible;
- for (vector<Strip*>::iterator s = strips.begin(), send = strips.end(); s != send; ++s) {
- Strip::vertex_container& strip_vertices = (*s)->vertices();
+ for (it = strokeGroups.begin(), itend = strokeGroups.end();
+ it != itend; ++it)
+ {
+ delete (*it);
+ }
+ for (it = texturedStrokeGroups.begin(), itend = texturedStrokeGroups.end();
+ it != itend; ++it)
+ {
+ delete (*it);
+ }
+}
- // count visible faces and strip segments
- test_strip_visibility(strip_vertices, &visible_faces, &visible_segments);
- if (visible_faces == 0)
- continue;
+// Build a scene populated by mesh objects representing stylized strokes
+int BlenderStrokeRenderer::GenerateScene()
+{
+ vector<StrokeGroup*>::const_iterator it, itend;
- totvert += visible_faces + visible_segments * 2;
- totedge += visible_faces * 2 + visible_segments;
- totpoly += visible_faces;
- totloop += visible_faces * 3;
+ for (it = strokeGroups.begin(), itend = strokeGroups.end();
+ it != itend; ++it)
+ {
+ GenerateStrokeMesh(*it, false);
+ }
+ for (it = texturedStrokeGroups.begin(), itend = texturedStrokeGroups.end();
+ it != itend; ++it)
+ {
+ GenerateStrokeMesh(*it, true);
}
+ return get_stroke_count();
+}
+
+// Return the number of strokes
+int BlenderStrokeRenderer::get_stroke_count() const
+{
+ return strokeGroups.size() + texturedStrokeGroups.size();
+}
+// Build a mesh object representing a group of stylized strokes
+void BlenderStrokeRenderer::GenerateStrokeMesh(StrokeGroup *group, bool hasTex)
+{
#if 0
Object *object_mesh = BKE_object_add(freestyle_bmain, freestyle_scene, OB_MESH);
+ DAG_relations_tag_update(freestyle_bmain);
#else
Object *object_mesh = NewMesh();
#endif
Mesh *mesh = (Mesh *)object_mesh->data;
- mesh->mat = (Material **)MEM_mallocN(1 * sizeof(Material *), "MaterialList");
- mesh->mat[0] = iStrokeRep->getMaterial();
- mesh->totcol = 1;
- test_object_materials(freestyle_bmain, (ID *)mesh);
-
- // vertices allocation
- mesh->totvert = totvert; // visible_faces + visible_segments * 2;
- CustomData_add_layer(&mesh->vdata, CD_MVERT, CD_CALLOC, NULL, mesh->totvert);
-
- // edges allocation
- mesh->totedge = totedge; // visible_faces * 2 + visible_segments;
- CustomData_add_layer(&mesh->edata, CD_MEDGE, CD_CALLOC, NULL, mesh->totedge);
- // faces allocation
- mesh->totpoly = totpoly; // visible_faces;
- CustomData_add_layer(&mesh->pdata, CD_MPOLY, CD_CALLOC, NULL, mesh->totpoly);
+ mesh->totvert = group->totvert;
+ mesh->totedge = group->totedge;
+ mesh->totpoly = group->totpoly;
+ mesh->totloop = group->totloop;
+ mesh->totcol = group->totcol;
- // loops allocation
- mesh->totloop = totloop; // visible_faces * 3;
- CustomData_add_layer(&mesh->ldata, CD_MLOOP, CD_CALLOC, NULL, mesh->totloop);
+ mesh->mvert = (MVert *)CustomData_add_layer(&mesh->vdata, CD_MVERT, CD_CALLOC, NULL, mesh->totvert);
+ mesh->medge = (MEdge *)CustomData_add_layer(&mesh->edata, CD_MEDGE, CD_CALLOC, NULL, mesh->totedge);
+ mesh->mpoly = (MPoly *)CustomData_add_layer(&mesh->pdata, CD_MPOLY, CD_CALLOC, NULL, mesh->totpoly);
+ mesh->mloop = (MLoop *)CustomData_add_layer(&mesh->ldata, CD_MLOOP, CD_CALLOC, NULL, mesh->totloop);
- // uv maps
+ MVert *vertices = mesh->mvert;
+ MEdge *edges = mesh->medge;
+ MPoly *polys = mesh->mpoly;
+ MLoop *loops = mesh->mloop;
MLoopUV *loopsuv[2] = { NULL };
- if (hasTex) {
- loopsuv[0] = (MLoopUV *)CustomData_add_layer_named(&mesh->ldata, CD_MLOOPUV, CD_CALLOC, NULL, mesh->totloop, "along_stroke");
- loopsuv[1] = (MLoopUV *)CustomData_add_layer_named(&mesh->ldata, CD_MLOOPUV, CD_CALLOC, NULL, mesh->totloop, "along_stroke_tips");
- CustomData_add_layer_named(&mesh->pdata, CD_MTEXPOLY, CD_CALLOC, NULL, mesh->totpoly, "along_stroke");
- CustomData_add_layer_named(&mesh->pdata, CD_MTEXPOLY, CD_CALLOC, NULL, mesh->totpoly, "along_stroke_tips");
+ if (hasTex) {
+ // First UV layer
+ CustomData_add_layer_named(&mesh->pdata, CD_MTEXPOLY, CD_CALLOC, NULL, mesh->totpoly, uvNames[0]);
+ CustomData_add_layer_named(&mesh->ldata, CD_MLOOPUV, CD_CALLOC, NULL, mesh->totloop, uvNames[0]);
+ CustomData_set_layer_active(&mesh->pdata, CD_MTEXPOLY, 0);
+ CustomData_set_layer_active(&mesh->ldata, CD_MLOOPUV, 0);
+ BKE_mesh_update_customdata_pointers(mesh, true);
+ loopsuv[0] = mesh->mloopuv;
+
+ // Second UV layer
+ CustomData_add_layer_named(&mesh->pdata, CD_MTEXPOLY, CD_CALLOC, NULL, mesh->totpoly, uvNames[1]);
+ CustomData_add_layer_named(&mesh->ldata, CD_MLOOPUV, CD_CALLOC, NULL, mesh->totloop, uvNames[1]);
+ CustomData_set_layer_active(&mesh->pdata, CD_MTEXPOLY, 1);
+ CustomData_set_layer_active(&mesh->ldata, CD_MLOOPUV, 1);
+ BKE_mesh_update_customdata_pointers(mesh, true);
+ loopsuv[1] = mesh->mloopuv;
}
// colors and transparency (the latter represented by grayscale colors)
MLoopCol *colors = (MLoopCol *)CustomData_add_layer_named(&mesh->ldata, CD_MLOOPCOL, CD_CALLOC, NULL, mesh->totloop, "Color");
MLoopCol *transp = (MLoopCol *)CustomData_add_layer_named(&mesh->ldata, CD_MLOOPCOL, CD_CALLOC, NULL, mesh->totloop, "Alpha");
+ mesh->mloopcol = colors;
- BKE_mesh_update_customdata_pointers(mesh, true);
+ mesh->mat = (Material **)MEM_mallocN(sizeof(Material *) * mesh->totcol, "MaterialList");
////////////////////
// Data copy
////////////////////
- MVert *vertices = mesh->mvert;
- MEdge *edges = mesh->medge;
- MPoly *polys = mesh->mpoly;
- MLoop *loops = mesh->mloop;
+ int vertex_index = 0, edge_index = 0, loop_index = 0, material_index = 0;
+ int visible_faces, visible_segments;
+ bool visible;
+ Strip::vertex_container::iterator v[3];
+ StrokeVertexRep *svRep[3];
+ Vec2r p;
- vertex_index = edge_index = loop_index = 0;
+ for (vector<StrokeRep*>::const_iterator it = group->strokes.begin(), itend = group->strokes.end();
+ it != itend; ++it)
+ {
+ mesh->mat[material_index] = (*it)->getMaterial();
- for (vector<Strip*>::iterator s = strips.begin(), send = strips.end(); s != send; ++s) {
- Strip::vertex_container& strip_vertices = (*s)->vertices();
- int strip_vertex_count = strip_vertices.size();
+ vector<Strip*>& strips = (*it)->getStrips();
+ for (vector<Strip*>::const_iterator s = strips.begin(), send = strips.end(); s != send; ++s) {
+ Strip::vertex_container& strip_vertices = (*s)->vertices();
+ int strip_vertex_count = strip_vertices.size();
- // count visible faces and strip segments
- test_strip_visibility(strip_vertices, &visible_faces, &visible_segments);
- if (visible_faces == 0)
- continue;
+ // count visible faces and strip segments
+ test_strip_visibility(strip_vertices, &visible_faces, &visible_segments);
+ if (visible_faces == 0)
+ continue;
- v[0] = strip_vertices.begin();
- v[1] = v[0] + 1;
- v[2] = v[0] + 2;
+ v[0] = strip_vertices.begin();
+ v[1] = v[0] + 1;
+ v[2] = v[0] + 2;
- visible = false;
+ visible = false;
- // Note: Mesh generation in the following loop assumes stroke strips
- // to be triangle strips.
- for (int n = 2; n < strip_vertex_count; n++, v[0]++, v[1]++, v[2]++) {
- svRep[0] = *(v[0]);
- svRep[1] = *(v[1]);
- svRep[2] = *(v[2]);
- if (!test_triangle_visibility(svRep)) {
- visible = false;
- }
- else {
- if (!visible) {
- // first vertex
- vertices->co[0] = svRep[0]->point2d()[0];
- vertices->co[1] = svRep[0]->point2d()[1];
- vertices->co[2] = get_stroke_vertex_z();
- vertices->no[0] = 0;
- vertices->no[1] = 0;
- vertices->no[2] = SHRT_MAX;
- ++vertices;
- ++vertex_index;
+ // Note: Mesh generation in the following loop assumes stroke strips
+ // to be triangle strips.
+ for (int n = 2; n < strip_vertex_count; n++, v[0]++, v[1]++, v[2]++) {
+ svRep[0] = *(v[0]);
+ svRep[1] = *(v[1]);
+ svRep[2] = *(v[2]);
+ if (!test_triangle_visibility(svRep)) {
+ visible = false;
+ }
+ else {
+ if (!visible) {
+ // first vertex
+ vertices->co[0] = svRep[0]->point2d()[0];
+ vertices->co[1] = svRep[0]->point2d()[1];
+ vertices->co[2] = get_stroke_vertex_z();
+ vertices->no[0] = 0;
+ vertices->no[1] = 0;
+ vertices->no[2] = SHRT_MAX;
+ ++vertices;
+ ++vertex_index;
+
+ // second vertex
+ vertices->co[0] = svRep[1]->point2d()[0];
+ vertices->co[1] = svRep[1]->point2d()[1];
+ vertices->co[2] = get_stroke_vertex_z();
+ vertices->no[0] = 0;
+ vertices->no[1] = 0;
+ vertices->no[2] = SHRT_MAX;
+ ++vertices;
+ ++vertex_index;
+
+ // first edge
+ edges->v1 = vertex_index - 2;
+ edges->v2 = vertex_index - 1;
+ ++edges;
+ ++edge_index;
+ }
+ visible = true;
- // second vertex
- vertices->co[0] = svRep[1]->point2d()[0];
- vertices->co[1] = svRep[1]->point2d()[1];
+ // vertex
+ vertices->co[0] = svRep[2]->point2d()[0];
+ vertices->co[1] = svRep[2]->point2d()[1];
vertices->co[2] = get_stroke_vertex_z();
vertices->no[0] = 0;
vertices->no[1] = 0;
@@ -706,141 +799,130 @@ void BlenderStrokeRenderer::RenderStrokeRepBasic(StrokeRep *iStrokeRep) const
++vertices;
++vertex_index;
- // first edge
- edges->v1 = vertex_index - 2;
- edges->v2 = vertex_index - 1;
+ // edges
+ edges->v1 = vertex_index - 1;
+ edges->v2 = vertex_index - 3;
++edges;
++edge_index;
- }
- visible = true;
-
- // vertex
- vertices->co[0] = svRep[2]->point2d()[0];
- vertices->co[1] = svRep[2]->point2d()[1];
- vertices->co[2] = get_stroke_vertex_z();
- vertices->no[0] = 0;
- vertices->no[1] = 0;
- vertices->no[2] = SHRT_MAX;
- ++vertices;
- ++vertex_index;
-
- // edges
- edges->v1 = vertex_index - 1;
- edges->v2 = vertex_index - 3;
- ++edges;
- ++edge_index;
-
- edges->v1 = vertex_index - 1;
- edges->v2 = vertex_index - 2;
- ++edges;
- ++edge_index;
-
- // poly
- polys->loopstart = loop_index;
- polys->totloop = 3;
- ++polys;
-
- // Even and odd loops connect triangles vertices differently
- bool is_odd = n % 2;
- // loops
- if (is_odd) {
- loops[0].v = vertex_index - 1;
- loops[0].e = edge_index - 2;
-
- loops[1].v = vertex_index - 3;
- loops[1].e = edge_index - 3;
-
- loops[2].v = vertex_index - 2;
- loops[2].e = edge_index - 1;
- }
- else {
- loops[0].v = vertex_index - 1;
- loops[0].e = edge_index - 1;
- loops[1].v = vertex_index - 2;
- loops[1].e = edge_index - 3;
+ edges->v1 = vertex_index - 1;
+ edges->v2 = vertex_index - 2;
+ ++edges;
+ ++edge_index;
- loops[2].v = vertex_index - 3;
- loops[2].e = edge_index - 2;
- }
- loops += 3;
- loop_index += 3;
-
- // UV
- if (hasTex) {
- // First UV layer (loopsuv[0]) has no tips (texCoord(0)).
- // Second UV layer (loopsuv[1]) has tips: (texCoord(1)).
- for (int L = 0; L < 2; L++) {
- if (is_odd) {
- loopsuv[L][0].uv[0] = svRep[2]->texCoord(L).x();
- loopsuv[L][0].uv[1] = svRep[2]->texCoord(L).y();
-
- loopsuv[L][1].uv[0] = svRep[0]->texCoord(L).x();
- loopsuv[L][1].uv[1] = svRep[0]->texCoord(L).y();
-
- loopsuv[L][2].uv[0] = svRep[1]->texCoord(L).x();
- loopsuv[L][2].uv[1] = svRep[1]->texCoord(L).y();
- }
- else {
- loopsuv[L][0].uv[0] = svRep[2]->texCoord(L).x();
- loopsuv[L][0].uv[1] = svRep[2]->texCoord(L).y();
+ // poly
+ polys->loopstart = loop_index;
+ polys->totloop = 3;
+ polys->mat_nr = material_index;
+ ++polys;
+
+ // Even and odd loops connect triangles vertices differently
+ bool is_odd = n % 2;
+ // loops
+ if (is_odd) {
+ loops[0].v = vertex_index - 1;
+ loops[0].e = edge_index - 2;
- loopsuv[L][1].uv[0] = svRep[1]->texCoord(L).x();
- loopsuv[L][1].uv[1] = svRep[1]->texCoord(L).y();
+ loops[1].v = vertex_index - 3;
+ loops[1].e = edge_index - 3;
- loopsuv[L][2].uv[0] = svRep[0]->texCoord(L).x();
- loopsuv[L][2].uv[1] = svRep[0]->texCoord(L).y();
+ loops[2].v = vertex_index - 2;
+ loops[2].e = edge_index - 1;
+ }
+ else {
+ loops[0].v = vertex_index - 1;
+ loops[0].e = edge_index - 1;
+
+ loops[1].v = vertex_index - 2;
+ loops[1].e = edge_index - 3;
+
+ loops[2].v = vertex_index - 3;
+ loops[2].e = edge_index - 2;
+ }
+ loops += 3;
+ loop_index += 3;
+
+ // UV
+ if (hasTex) {
+ // First UV layer (loopsuv[0]) has no tips (texCoord(0)).
+ // Second UV layer (loopsuv[1]) has tips: (texCoord(1)).
+ for (int L = 0; L < 2; L++) {
+ if (is_odd) {
+ loopsuv[L][0].uv[0] = svRep[2]->texCoord(L).x();
+ loopsuv[L][0].uv[1] = svRep[2]->texCoord(L).y();
+
+ loopsuv[L][1].uv[0] = svRep[0]->texCoord(L).x();
+ loopsuv[L][1].uv[1] = svRep[0]->texCoord(L).y();
+
+ loopsuv[L][2].uv[0] = svRep[1]->texCoord(L).x();
+ loopsuv[L][2].uv[1] = svRep[1]->texCoord(L).y();
+ }
+ else {
+ loopsuv[L][0].uv[0] = svRep[2]->texCoord(L).x();
+ loopsuv[L][0].uv[1] = svRep[2]->texCoord(L).y();
+
+ loopsuv[L][1].uv[0] = svRep[1]->texCoord(L).x();
+ loopsuv[L][1].uv[1] = svRep[1]->texCoord(L).y();
+
+ loopsuv[L][2].uv[0] = svRep[0]->texCoord(L).x();
+ loopsuv[L][2].uv[1] = svRep[0]->texCoord(L).y();
+ }
+ loopsuv[L] += 3;
}
- loopsuv[L] += 3;
}
- }
- // colors and alpha transparency
- if (is_odd) {
- colors[0].r = (short)(255.0f * svRep[2]->color()[0]);
- colors[0].g = (short)(255.0f * svRep[2]->color()[1]);
- colors[0].b = (short)(255.0f * svRep[2]->color()[2]);
- colors[0].a = (short)(255.0f * svRep[2]->alpha());
-
- colors[1].r = (short)(255.0f * svRep[0]->color()[0]);
- colors[1].g = (short)(255.0f * svRep[0]->color()[1]);
- colors[1].b = (short)(255.0f * svRep[0]->color()[2]);
- colors[1].a = (short)(255.0f * svRep[0]->alpha());
-
- colors[2].r = (short)(255.0f * svRep[1]->color()[0]);
- colors[2].g = (short)(255.0f * svRep[1]->color()[1]);
- colors[2].b = (short)(255.0f * svRep[1]->color()[2]);
- colors[2].a = (short)(255.0f * svRep[1]->alpha());
- }
- else {
- colors[0].r = (short)(255.0f * svRep[2]->color()[0]);
- colors[0].g = (short)(255.0f * svRep[2]->color()[1]);
- colors[0].b = (short)(255.0f * svRep[2]->color()[2]);
- colors[0].a = (short)(255.0f * svRep[2]->alpha());
-
- colors[1].r = (short)(255.0f * svRep[1]->color()[0]);
- colors[1].g = (short)(255.0f * svRep[1]->color()[1]);
- colors[1].b = (short)(255.0f * svRep[1]->color()[2]);
- colors[1].a = (short)(255.0f * svRep[1]->alpha());
-
- colors[2].r = (short)(255.0f * svRep[0]->color()[0]);
- colors[2].g = (short)(255.0f * svRep[0]->color()[1]);
- colors[2].b = (short)(255.0f * svRep[0]->color()[2]);
- colors[2].a = (short)(255.0f * svRep[0]->alpha());
+ // colors and alpha transparency
+ if (is_odd) {
+ colors[0].r = (short)(255.0f * svRep[2]->color()[0]);
+ colors[0].g = (short)(255.0f * svRep[2]->color()[1]);
+ colors[0].b = (short)(255.0f * svRep[2]->color()[2]);
+ colors[0].a = (short)(255.0f * svRep[2]->alpha());
+
+ colors[1].r = (short)(255.0f * svRep[0]->color()[0]);
+ colors[1].g = (short)(255.0f * svRep[0]->color()[1]);
+ colors[1].b = (short)(255.0f * svRep[0]->color()[2]);
+ colors[1].a = (short)(255.0f * svRep[0]->alpha());
+
+ colors[2].r = (short)(255.0f * svRep[1]->color()[0]);
+ colors[2].g = (short)(255.0f * svRep[1]->color()[1]);
+ colors[2].b = (short)(255.0f * svRep[1]->color()[2]);
+ colors[2].a = (short)(255.0f * svRep[1]->alpha());
+ }
+ else {
+ colors[0].r = (short)(255.0f * svRep[2]->color()[0]);
+ colors[0].g = (short)(255.0f * svRep[2]->color()[1]);
+ colors[0].b = (short)(255.0f * svRep[2]->color()[2]);
+ colors[0].a = (short)(255.0f * svRep[2]->alpha());
+
+ colors[1].r = (short)(255.0f * svRep[1]->color()[0]);
+ colors[1].g = (short)(255.0f * svRep[1]->color()[1]);
+ colors[1].b = (short)(255.0f * svRep[1]->color()[2]);
+ colors[1].a = (short)(255.0f * svRep[1]->alpha());
+
+ colors[2].r = (short)(255.0f * svRep[0]->color()[0]);
+ colors[2].g = (short)(255.0f * svRep[0]->color()[1]);
+ colors[2].b = (short)(255.0f * svRep[0]->color()[2]);
+ colors[2].a = (short)(255.0f * svRep[0]->alpha());
+ }
+ transp[0].r = transp[0].g = transp[0].b = colors[0].a;
+ transp[1].r = transp[1].g = transp[1].b = colors[1].a;
+ transp[2].r = transp[2].g = transp[2].b = colors[2].a;
+ colors += 3;
+ transp += 3;
}
- transp[0].r = transp[0].g = transp[0].b = colors[0].a;
- transp[1].r = transp[1].g = transp[1].b = colors[1].a;
- transp[2].r = transp[2].g = transp[2].b = colors[2].a;
- colors += 3;
- transp += 3;
- }
- } // loop over strip vertices
- } // loop over strips
-#if 0
- BLI_assert(totvert == vertex_index);
- BLI_assert(totedge == edge_index);
- BLI_assert(totloop == loop_index);
- BKE_mesh_validate(mesh, true);
+ } // loop over strip vertices
+ } // loop over strips
+ material_index++;
+ } // loop over strokes
+
+ test_object_materials(freestyle_bmain, (ID *)mesh);
+
+#if 0 // XXX
+ BLI_assert(mesh->totvert == vertex_index);
+ BLI_assert(mesh->totedge == edge_index);
+ BLI_assert(mesh->totloop == loop_index);
+ BLI_assert(mesh->totcol == material_index);
+ BKE_mesh_validate(mesh, true, true);
#endif
}
@@ -859,6 +941,7 @@ Object *BlenderStrokeRenderer::NewMesh() const
ob->lay = 1;
base = BKE_scene_base_add(freestyle_scene, ob);
+ DAG_relations_tag_update(freestyle_bmain);
#if 0
BKE_scene_base_deselect_all(scene);
BKE_scene_base_select(scene, base);
@@ -871,7 +954,7 @@ Object *BlenderStrokeRenderer::NewMesh() const
return ob;
}
-Render *BlenderStrokeRenderer::RenderScene(Render *re, bool render)
+Render *BlenderStrokeRenderer::RenderScene(Render * /*re*/, bool render)
{
Camera *camera = (Camera *)freestyle_scene->camera->data;
if (camera->clipend < _z)
@@ -884,7 +967,8 @@ Render *BlenderStrokeRenderer::RenderScene(Render *re, bool render)
Render *freestyle_render = RE_NewRender(freestyle_scene->id.name);
- RE_RenderFreestyleStrokes(freestyle_render, freestyle_bmain, freestyle_scene, render);
+ RE_RenderFreestyleStrokes(freestyle_render, freestyle_bmain, freestyle_scene,
+ render && get_stroke_count() > 0);
return freestyle_render;
}
diff --git a/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.h b/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.h
index 74e5d321df2..ec53efa14cd 100644
--- a/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.h
+++ b/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.h
@@ -53,6 +53,21 @@ public:
Object *NewMesh() const;
+ struct StrokeGroup {
+ explicit StrokeGroup() : totvert(0), totedge(0), totpoly(0), totloop(0), totcol(0) {}
+ vector<StrokeRep*> strokes;
+ int totvert;
+ int totedge;
+ int totpoly;
+ int totloop;
+ int totcol;
+ };
+ vector<StrokeGroup*> strokeGroups, texturedStrokeGroups;
+
+ int GenerateScene();
+ void GenerateStrokeMesh(StrokeGroup *group, bool hasTex);
+ void FreeStrokeGroups();
+
Render *RenderScene(Render *re, bool render);
static Material* GetStrokeShader(Main *bmain, bNodeTree *iNodeTree, bool do_id_user);
@@ -68,16 +83,20 @@ protected:
bool _use_shading_nodes;
struct GHash *_nodetree_hash;
+ static const char *uvNames[];
+
+ int get_stroke_count() const;
float get_stroke_vertex_z(void) const;
unsigned int get_stroke_mesh_id(void) const;
bool test_triangle_visibility(StrokeVertexRep *svRep[3]) const;
void test_strip_visibility(Strip::vertex_container& strip_vertices,
int *visible_faces, int *visible_segments) const;
+ vector<StrokeRep *> _strokeReps;
+
#ifdef WITH_CXX_GUARDEDALLOC
MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:BlenderStrokeRenderer")
#endif
-
};
} /* namespace Freestyle */
diff --git a/source/blender/freestyle/intern/blender_interface/BlenderStyleModule.h b/source/blender/freestyle/intern/blender_interface/BlenderStyleModule.h
index 21776396ebc..1d73125f627 100644
--- a/source/blender/freestyle/intern/blender_interface/BlenderStyleModule.h
+++ b/source/blender/freestyle/intern/blender_interface/BlenderStyleModule.h
@@ -31,12 +31,39 @@
extern "C" {
#include "BLI_utildefines.h" // BLI_assert()
-struct Scene;
struct Text;
}
namespace Freestyle {
+class BufferedStyleModule : public StyleModule
+{
+public:
+ BufferedStyleModule(const string& buffer, const string& file_name, Interpreter *inter) : StyleModule(file_name, inter)
+ {
+ _buffer = buffer;
+ }
+
+ virtual ~BufferedStyleModule()
+ {
+ }
+
+protected:
+ virtual int interpret()
+ {
+ PythonInterpreter *py_inter = dynamic_cast<PythonInterpreter*>(_inter);
+ BLI_assert(py_inter != 0);
+ return py_inter->interpretString(_buffer, getFileName());
+ }
+
+private:
+ string _buffer;
+
+#ifdef WITH_CXX_GUARDEDALLOC
+ MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:BufferedStyleModule")
+#endif
+};
+
class BlenderStyleModule : public StyleModule
{
public:
@@ -63,7 +90,6 @@ private:
#ifdef WITH_CXX_GUARDEDALLOC
MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:BlenderStyleModule")
#endif
-
};
} /* namespace Freestyle */
diff --git a/source/blender/freestyle/intern/blender_interface/FRS_freestyle.cpp b/source/blender/freestyle/intern/blender_interface/FRS_freestyle.cpp
index 32f49d48ee7..46724ff530a 100644
--- a/source/blender/freestyle/intern/blender_interface/FRS_freestyle.cpp
+++ b/source/blender/freestyle/intern/blender_interface/FRS_freestyle.cpp
@@ -87,7 +87,7 @@ int freestyle_viewport[4];
// current scene
Scene *freestyle_scene;
-static void load_post_callback(struct Main *main, struct ID *id, void *arg)
+static void load_post_callback(struct Main * /*main*/, struct ID * /*id*/, void * /*arg*/)
{
lineset_copied = false;
}
@@ -182,7 +182,7 @@ static void init_camera(Render *re)
{
// It is assumed that imported meshes are in the camera coordinate system.
// Therefore, the view point (i.e., camera position) is at the origin, and
- // the the model-view matrix is simply the identity matrix.
+ // the model-view matrix is simply the identity matrix.
freestyle_viewpoint[0] = 0.0;
freestyle_viewpoint[1] = 0.0;
@@ -211,16 +211,12 @@ static char *escape_quotes(char *name)
return s;
}
-static Text *create_lineset_handler(Main *bmain, char *layer_name, char *lineset_name)
+static char * create_lineset_handler(char *layer_name, char *lineset_name)
{
+ const char *fmt = "__import__('parameter_editor').process('%s', '%s')\n";
char *s1 = escape_quotes(layer_name);
char *s2 = escape_quotes(lineset_name);
- Text *text = BKE_text_add(bmain, lineset_name);
- BKE_text_write(text, "import parameter_editor; parameter_editor.process('");
- BKE_text_write(text, s1);
- BKE_text_write(text, "', '");
- BKE_text_write(text, s2);
- BKE_text_write(text, "')\n");
+ char *text = BLI_sprintfN(fmt, s1, s2);
MEM_freeN(s1);
MEM_freeN(s2);
return text;
@@ -293,7 +289,7 @@ static bool test_edge_type_conditions(struct edge_type_condition *conditions,
return true;
}
-static void prepare(Main *bmain, Render *re, SceneRenderLayer *srl)
+static void prepare(Render *re, SceneRenderLayer *srl)
{
// load mesh
re->i.infostr = "Freestyle: Mesh loading";
@@ -369,9 +365,10 @@ static void prepare(Main *bmain, Render *re, SceneRenderLayer *srl)
cout << " " << layer_count+1 << ": " << lineset->name << " - " <<
(lineset->linestyle ? (lineset->linestyle->id.name + 2) : "<NULL>") << endl;
}
- Text *text = create_lineset_handler(bmain, srl->name, lineset->name);
- controller->InsertStyleModule(layer_count, lineset->name, text);
+ char *buffer = create_lineset_handler(srl->name, lineset->name);
+ controller->InsertStyleModule(layer_count, lineset->name, buffer);
controller->toggleLayer(layer_count, true);
+ MEM_freeN(buffer);
if (!(lineset->selection & FREESTYLE_SEL_EDGE_TYPES) || !lineset->edge_types) {
++use_ridges_and_valleys;
++use_suggestive_contours;
@@ -474,6 +471,9 @@ static void prepare(Main *bmain, Render *re, SceneRenderLayer *srl)
cout << " Z = " << (z ? "enabled" : "disabled") << endl;
}
+ if (controller->hitViewMapCache())
+ return;
+
// compute view map
re->i.infostr = "Freestyle: View map creation";
re->stats_draw(re->sdh, &re->i);
@@ -491,13 +491,20 @@ void FRS_composite_result(Render *re, SceneRenderLayer *srl, Render *freestyle_r
return;
rl = render_get_active_layer( freestyle_render, freestyle_render->result );
- if (!rl || rl->rectf == NULL) {
+ if (!rl) {
+ if (G.debug & G_DEBUG_FREESTYLE) {
+ cout << "No source render layer to composite" << endl;
+ }
+ return;
+ }
+
+ src = RE_RenderLayerGetPass(rl, SCE_PASS_COMBINED, freestyle_render->viewname);
+ if (!src) {
if (G.debug & G_DEBUG_FREESTYLE) {
- cout << "Cannot find Freestyle result image" << endl;
+ cout << "No source result image to composite" << endl;
}
return;
}
- src = rl->rectf;
#if 0
if (G.debug & G_DEBUG_FREESTYLE) {
cout << "src: " << rl->rectx << " x " << rl->recty << endl;
@@ -505,13 +512,19 @@ void FRS_composite_result(Render *re, SceneRenderLayer *srl, Render *freestyle_r
#endif
rl = RE_GetRenderLayer(re->result, srl->name);
- if (!rl || rl->rectf == NULL) {
+ if (!rl) {
if (G.debug & G_DEBUG_FREESTYLE) {
- cout << "No layer to composite to" << endl;
+ cout << "No destination render layer to composite to" << endl;
+ }
+ return;
+ }
+ dest = RE_RenderLayerGetPass(rl, SCE_PASS_COMBINED, re->viewname);
+ if (!dest) {
+ if (G.debug & G_DEBUG_FREESTYLE) {
+ cout << "No destination result image to composite to" << endl;
}
return;
}
- dest = rl->rectf;
#if 0
if (G.debug & G_DEBUG_FREESTYLE) {
cout << "dest: " << rl->rectx << " x " << rl->recty << endl;
@@ -563,7 +576,7 @@ int FRS_is_freestyle_enabled(SceneRenderLayer *srl)
return (!(srl->layflag & SCE_LAY_DISABLE) && srl->layflag & SCE_LAY_FRS && displayed_layer_count(srl) > 0);
}
-void FRS_init_stroke_rendering(Render *re)
+void FRS_init_stroke_renderer(Render *re)
{
if (G.debug & G_DEBUG_FREESTYLE) {
cout << endl;
@@ -573,22 +586,25 @@ void FRS_init_stroke_rendering(Render *re)
}
init_view(re);
- init_camera(re);
controller->ResetRenderCount();
}
+void FRS_begin_stroke_rendering(Render *re)
+{
+ init_camera(re);
+}
+
Render *FRS_do_stroke_rendering(Render *re, SceneRenderLayer *srl, int render)
{
- Main *freestyle_bmain = re->freestyle_bmain;
Render *freestyle_render = NULL;
- Text *text, *next_text;
if (!render)
return controller->RenderStrokes(re, false);
RenderMonitor monitor(re);
controller->setRenderMonitor(&monitor);
+ controller->setViewMapCache((srl->freestyleConfig.flags & FREESTYLE_VIEW_MAP_CACHE) ? true : false);
if (G.debug & G_DEBUG_FREESTYLE) {
cout << endl;
@@ -602,7 +618,7 @@ Render *FRS_do_stroke_rendering(Render *re, SceneRenderLayer *srl, int render)
// - add style modules
// - set parameters
// - compute view map
- prepare(freestyle_bmain, re, srl);
+ prepare(re, srl);
if (re->test_break(re->tbh)) {
controller->CloseFile();
@@ -630,23 +646,26 @@ Render *FRS_do_stroke_rendering(Render *re, SceneRenderLayer *srl, int render)
}
}
- // Free temp main (currently only text blocks are stored there)
- for (text = (Text *)freestyle_bmain->text.first; text; text = next_text) {
- next_text = (Text *) text->id.next;
-
- BKE_text_unlink(freestyle_bmain, text);
- BKE_libblock_free(freestyle_bmain, text);
- }
-
return freestyle_render;
}
-void FRS_finish_stroke_rendering(Render *re)
+void FRS_end_stroke_rendering(Render * /*re*/)
{
// clear canvas
controller->Clear();
}
+void FRS_free_view_map_cache(void)
+{
+ // free cache
+ controller->DeleteViewMap(true);
+#if 0
+ if (G.debug & G_DEBUG_FREESTYLE) {
+ printf("View map cache freed\n");
+ }
+#endif
+}
+
//=======================================================
// Freestyle Panel Configuration
//=======================================================
diff --git a/source/blender/freestyle/intern/geometry/GeomCleaner.cpp b/source/blender/freestyle/intern/geometry/GeomCleaner.cpp
index acbc668118e..c5d1c8df17b 100644
--- a/source/blender/freestyle/intern/geometry/GeomCleaner.cpp
+++ b/source/blender/freestyle/intern/geometry/GeomCleaner.cpp
@@ -50,13 +50,13 @@ using namespace std;
namespace Freestyle {
void GeomCleaner::SortIndexedVertexArray(const float *iVertices, unsigned iVSize, const unsigned *iIndices,
- unsigned iISize, real **oVertices, unsigned **oIndices)
+ unsigned iISize, float **oVertices, unsigned **oIndices)
{
// First, we build a list of IndexVertex:
list<IndexedVertex> indexedVertices;
unsigned i;
for (i = 0; i < iVSize; i += 3) {
- indexedVertices.push_back(IndexedVertex(Vec3r(iVertices[i], iVertices[i + 1], iVertices[i + 2]), i / 3));
+ indexedVertices.push_back(IndexedVertex(Vec3f(iVertices[i], iVertices[i + 1], iVertices[i + 2]), i / 3));
}
// q-sort
@@ -64,7 +64,7 @@ void GeomCleaner::SortIndexedVertexArray(const float *iVertices, unsigned iVSize
// build the indices mapping array:
unsigned *mapIndices = new unsigned[iVSize / 3];
- *oVertices = new real[iVSize];
+ *oVertices = new float[iVSize];
list<IndexedVertex>::iterator iv;
unsigned newIndex = 0;
unsigned vIndex = 0;
@@ -88,26 +88,26 @@ void GeomCleaner::SortIndexedVertexArray(const float *iVertices, unsigned iVSize
delete [] mapIndices;
}
-void GeomCleaner::CompressIndexedVertexArray(const real *iVertices, unsigned iVSize, const unsigned *iIndices,
- unsigned iISize, real **oVertices, unsigned *oVSize, unsigned **oIndices)
+void GeomCleaner::CompressIndexedVertexArray(const float *iVertices, unsigned iVSize, const unsigned *iIndices,
+ unsigned iISize, float **oVertices, unsigned *oVSize, unsigned **oIndices)
{
// First, we build a list of IndexVertex:
- vector<Vec3r> vertices;
+ vector<Vec3f> vertices;
unsigned i;
for (i = 0; i < iVSize; i += 3) {
- vertices.push_back(Vec3r(iVertices[i], iVertices[i + 1], iVertices[i + 2]));
+ vertices.push_back(Vec3f(iVertices[i], iVertices[i + 1], iVertices[i + 2]));
}
unsigned *mapVertex = new unsigned[iVSize];
- vector<Vec3r>::iterator v = vertices.begin();
+ vector<Vec3f>::iterator v = vertices.begin();
- vector<Vec3r> compressedVertices;
- Vec3r previous = *v;
+ vector<Vec3f> compressedVertices;
+ Vec3f previous = *v;
mapVertex[0] = 0;
compressedVertices.push_back(vertices.front());
v++;
- Vec3r current;
+ Vec3f current;
i = 1;
for (; v != vertices.end(); v++) {
current = *v;
@@ -123,7 +123,7 @@ void GeomCleaner::CompressIndexedVertexArray(const real *iVertices, unsigned iVS
// Builds the resulting vertex array:
*oVSize = 3 * compressedVertices.size();
- *oVertices = new real[*oVSize];
+ *oVertices = new float[*oVSize];
i = 0;
for (v = compressedVertices.begin(); v != compressedVertices.end(); v++) {
(*oVertices)[i] = (*v)[0];
@@ -142,11 +142,11 @@ void GeomCleaner::CompressIndexedVertexArray(const real *iVertices, unsigned iVS
}
void GeomCleaner::SortAndCompressIndexedVertexArray(const float *iVertices, unsigned iVSize, const unsigned *iIndices,
- unsigned iISize, real **oVertices, unsigned *oVSize,
+ unsigned iISize, float **oVertices, unsigned *oVSize,
unsigned **oIndices)
{
// tmp arrays used to store the sorted data:
- real *tmpVertices;
+ float *tmpVertices;
unsigned *tmpIndices;
Chronometer chrono;
@@ -154,7 +154,7 @@ void GeomCleaner::SortAndCompressIndexedVertexArray(const float *iVertices, unsi
chrono.start();
GeomCleaner::SortIndexedVertexArray(iVertices, iVSize, iIndices, iISize, &tmpVertices, &tmpIndices);
if (G.debug & G_DEBUG_FREESTYLE) {
- printf("Sorting: %lf\n", chrono.stop());
+ printf("Sorting: %lf sec.\n", chrono.stop());
}
// compress data
@@ -162,7 +162,7 @@ void GeomCleaner::SortAndCompressIndexedVertexArray(const float *iVertices, unsi
GeomCleaner::CompressIndexedVertexArray(tmpVertices, iVSize, tmpIndices, iISize, oVertices, oVSize, oIndices);
real duration = chrono.stop();
if (G.debug & G_DEBUG_FREESTYLE) {
- printf("Merging: %lf\n", duration);
+ printf("Merging: %lf sec.\n", duration);
}
// deallocates memory:
@@ -185,22 +185,22 @@ struct GeomCleanerHasher {
};
void GeomCleaner::CleanIndexedVertexArray(const float *iVertices, unsigned iVSize, const unsigned *iIndices,
- unsigned iISize, real **oVertices, unsigned *oVSize, unsigned **oIndices)
+ unsigned iISize, float **oVertices, unsigned *oVSize, unsigned **oIndices)
{
- typedef map<Vec3r, unsigned> cleanHashTable;
- vector<Vec3r> vertices;
+ typedef map<Vec3f, unsigned> cleanHashTable;
+ vector<Vec3f> vertices;
unsigned i;
for (i = 0; i < iVSize; i += 3)
- vertices.push_back(Vec3r(iVertices[i], iVertices[i + 1], iVertices[i + 2]));
+ vertices.push_back(Vec3f(iVertices[i], iVertices[i + 1], iVertices[i + 2]));
cleanHashTable ht;
vector<unsigned> newIndices;
- vector<Vec3r> newVertices;
+ vector<Vec3f> newVertices;
// elimination of needless points
unsigned currentIndex = 0;
- vector<Vec3r>::const_iterator v = vertices.begin();
- vector<Vec3r>::const_iterator end = vertices.end();
+ vector<Vec3f>::const_iterator v = vertices.begin();
+ vector<Vec3f>::const_iterator end = vertices.end();
cleanHashTable::const_iterator found;
for (; v != end; v++) {
found = ht.find(*v);
@@ -218,7 +218,7 @@ void GeomCleaner::CleanIndexedVertexArray(const float *iVertices, unsigned iVSiz
// creation of oVertices array:
*oVSize = 3 * newVertices.size();
- *oVertices = new real[*oVSize];
+ *oVertices = new float[*oVSize];
currentIndex = 0;
end = newVertices.end();
for (v = newVertices.begin(); v != end ; v++) {
diff --git a/source/blender/freestyle/intern/geometry/GeomCleaner.h b/source/blender/freestyle/intern/geometry/GeomCleaner.h
index d516c5623b9..aeca592a8c4 100644
--- a/source/blender/freestyle/intern/geometry/GeomCleaner.h
+++ b/source/blender/freestyle/intern/geometry/GeomCleaner.h
@@ -64,7 +64,7 @@ public:
* Output corresponding to the iIndices array but reorganized in order to match the sorted vertex array.
*/
static void SortIndexedVertexArray(const float *iVertices, unsigned iVSize, const unsigned *iIndices,
- unsigned iISize, real **oVertices, unsigned **oIndices);
+ unsigned iISize, float **oVertices, unsigned **oIndices);
/*! Compress a SORTED indexed vertex array by eliminating multiple appearing occurences of a single vertex.
* iVertices
@@ -84,8 +84,8 @@ public:
* oIndices
* The indices array, reorganized to match the compressed oVertices array.
*/
- static void CompressIndexedVertexArray(const real *iVertices, unsigned iVSize, const unsigned *iIndices,
- unsigned iISize, real **oVertices, unsigned *oVSize, unsigned **oIndices);
+ static void CompressIndexedVertexArray(const float *iVertices, unsigned iVSize, const unsigned *iIndices,
+ unsigned iISize, float **oVertices, unsigned *oVSize, unsigned **oIndices);
/*! Sorts and compress an array of indexed vertices.
* iVertices
@@ -107,7 +107,7 @@ public:
* The indices array, reorganized to match the sorted and compressed oVertices array.
*/
static void SortAndCompressIndexedVertexArray(const float *iVertices, unsigned iVSize, const unsigned *iIndices,
- unsigned iISize, real **oVertices, unsigned *oVSize,
+ unsigned iISize, float **oVertices, unsigned *oVSize,
unsigned **oIndices);
/*! Cleans an indexed vertex array. (Identical to SortAndCompress except that we use here a hash table
@@ -131,7 +131,7 @@ public:
* The indices array, reorganized to match the sorted and compressed oVertices array.
*/
static void CleanIndexedVertexArray(const float *iVertices, unsigned iVSize, const unsigned *iIndices,
- unsigned iISize, real **oVertices, unsigned *oVSize, unsigned **oIndices);
+ unsigned iISize, float **oVertices, unsigned *oVSize, unsigned **oIndices);
#ifdef WITH_CXX_GUARDEDALLOC
MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:GeomCleaner")
@@ -146,20 +146,20 @@ public:
class IndexedVertex
{
private:
- Vec3r _Vector;
+ Vec3f _Vector;
unsigned _index;
public:
inline IndexedVertex() {}
- inline IndexedVertex(Vec3r iVector, unsigned iIndex)
+ inline IndexedVertex(Vec3f iVector, unsigned iIndex)
{
_Vector = iVector;
_index = iIndex;
}
/*! accessors */
- inline const Vec3r& vector() const
+ inline const Vec3f& vector() const
{
return _Vector;
}
@@ -169,23 +169,23 @@ public:
return _index;
}
- inline real x()
+ inline float x()
{
return _Vector[0];
}
- inline real y()
+ inline float y()
{
return _Vector[1];
}
- inline real z()
+ inline float z()
{
return _Vector[2];
}
/*! modifiers */
- inline void setVector(const Vec3r& iVector)
+ inline void setVector(const Vec3f& iVector)
{
_Vector = iVector;
}
@@ -203,7 +203,7 @@ public:
return *this;
}
- inline real operator[](const unsigned i)
+ inline float operator[](const unsigned i)
{
return _Vector[i];
}
diff --git a/source/blender/freestyle/intern/geometry/GeomUtils.cpp b/source/blender/freestyle/intern/geometry/GeomUtils.cpp
index a750cf2f7cf..3eb92c559fe 100644
--- a/source/blender/freestyle/intern/geometry/GeomUtils.cpp
+++ b/source/blender/freestyle/intern/geometry/GeomUtils.cpp
@@ -495,7 +495,7 @@ bool intersectRayBBox(const Vec3r& orig, const Vec3r& dir, // ray origin an
real t0, real t1,
real& tmin, // I0 = orig + tmin * dir is the first intersection
real& tmax, // I1 = orig + tmax * dir is the second intersection
- real epsilon)
+ real /*epsilon*/)
{
float tymin, tymax, tzmin, tzmax;
Vec3r inv_direction(1.0 / dir[0], 1.0 / dir[1], 1.0 / dir[2]);
diff --git a/source/blender/freestyle/intern/geometry/GeomUtils.h b/source/blender/freestyle/intern/geometry/GeomUtils.h
index 64aa6379e80..5a5d0809083 100644
--- a/source/blender/freestyle/intern/geometry/GeomUtils.h
+++ b/source/blender/freestyle/intern/geometry/GeomUtils.h
@@ -200,7 +200,7 @@ void fromWorldToCamera(const Vec3r& p, Vec3r& q, const real model_view_matrix[4]
void fromCameraToRetina(const Vec3r& p, Vec3r& q, const real projection_matrix[4][4]);
/*! From retina to image.
- * Returns the coordinates expressed in Image coorinates system.
+ * Returns the coordinates expressed in Image coordinates system.
* p
* point's coordinates expressed in retina system
* q
diff --git a/source/blender/freestyle/intern/geometry/Grid.h b/source/blender/freestyle/intern/geometry/Grid.h
index c1d04f6b4cc..62c0e58232a 100644
--- a/source/blender/freestyle/intern/geometry/Grid.h
+++ b/source/blender/freestyle/intern/geometry/Grid.h
@@ -97,11 +97,11 @@ class GridVisitor
public:
virtual ~GridVisitor() {}; //soc
- virtual void discoverCell(Cell *cell) {}
+ virtual void discoverCell(Cell * /*cell*/) {}
- virtual void examineOccluder(Polygon3r *occ) {}
+ virtual void examineOccluder(Polygon3r * /*occ*/) {}
- virtual void finishCell(Cell *cell) {}
+ virtual void finishCell(Cell * /*cell*/) {}
virtual bool stop() {
return false;
diff --git a/source/blender/freestyle/intern/image/Image.h b/source/blender/freestyle/intern/image/Image.h
index 577dc0fb866..2e78e784214 100644
--- a/source/blender/freestyle/intern/image/Image.h
+++ b/source/blender/freestyle/intern/image/Image.h
@@ -134,7 +134,7 @@ public:
return _height;
}
- /*! Returns the grey value for pixel x,y */
+ /*! Returns the gray value for pixel x,y */
virtual float pixel(unsigned x, unsigned y) const = 0;
/*! Sets the array.
diff --git a/source/blender/freestyle/intern/image/ImagePyramid.cpp b/source/blender/freestyle/intern/image/ImagePyramid.cpp
index 251f47bc44c..b81f8303945 100644
--- a/source/blender/freestyle/intern/image/ImagePyramid.cpp
+++ b/source/blender/freestyle/intern/image/ImagePyramid.cpp
@@ -42,7 +42,7 @@ ImagePyramid::ImagePyramid(const GrayImage& level0, unsigned nbLevels)
}
#endif
-ImagePyramid::ImagePyramid(const ImagePyramid& iBrother)
+ImagePyramid::ImagePyramid(const ImagePyramid& /*iBrother*/)
{
if (!_levels.empty()) {
for (vector<GrayImage*>::iterator im = _levels.begin(), imend = _levels.end(); im != imend; ++im) {
diff --git a/source/blender/freestyle/intern/python/BPy_ContextFunctions.cpp b/source/blender/freestyle/intern/python/BPy_ContextFunctions.cpp
index dd678ee6fbd..50d82656819 100644
--- a/source/blender/freestyle/intern/python/BPy_ContextFunctions.cpp
+++ b/source/blender/freestyle/intern/python/BPy_ContextFunctions.cpp
@@ -46,7 +46,7 @@ static char ContextFunctions_get_time_stamp___doc__[] =
" :rtype: int\n";
static PyObject *
-ContextFunctions_get_time_stamp(PyObject *self)
+ContextFunctions_get_time_stamp(PyObject * /*self*/)
{
return PyLong_FromLong(ContextFunctions::GetTimeStampCF());
}
@@ -60,7 +60,7 @@ static char ContextFunctions_get_canvas_width___doc__[] =
" :rtype: int\n";
static PyObject *
-ContextFunctions_get_canvas_width(PyObject *self)
+ContextFunctions_get_canvas_width(PyObject * /*self*/)
{
return PyLong_FromLong(ContextFunctions::GetCanvasWidthCF());
}
@@ -74,7 +74,7 @@ static char ContextFunctions_get_canvas_height___doc__[] =
" :rtype: int\n";
static PyObject *
-ContextFunctions_get_canvas_height(PyObject *self)
+ContextFunctions_get_canvas_height(PyObject * /*self*/)
{
return PyLong_FromLong(ContextFunctions::GetCanvasHeightCF());
}
@@ -88,14 +88,15 @@ static char ContextFunctions_get_border___doc__[] =
" :rtype: tuple\n";
static PyObject *
-ContextFunctions_get_border(PyObject *self)
+ContextFunctions_get_border(PyObject * /*self*/)
{
BBox<Vec2i> border(ContextFunctions::GetBorderCF());
PyObject *v = PyTuple_New(4);
- PyTuple_SET_ITEM(v, 0, PyLong_FromLong(border.getMin().x()));
- PyTuple_SET_ITEM(v, 1, PyLong_FromLong(border.getMin().y()));
- PyTuple_SET_ITEM(v, 2, PyLong_FromLong(border.getMax().x()));
- PyTuple_SET_ITEM(v, 3, PyLong_FromLong(border.getMax().y()));
+ PyTuple_SET_ITEMS(v,
+ PyLong_FromLong(border.getMin().x()),
+ PyLong_FromLong(border.getMin().y()),
+ PyLong_FromLong(border.getMax().x()),
+ PyLong_FromLong(border.getMax().y()));
return v;
}
@@ -116,7 +117,7 @@ static char ContextFunctions_load_map___doc__[] =
" :type sigma: float\n";
static PyObject *
-ContextFunctions_load_map(PyObject *self, PyObject *args, PyObject *kwds)
+ContextFunctions_load_map(PyObject * /*self*/, PyObject *args, PyObject *kwds)
{
static const char *kwlist[] = {"file_name", "map_name", "num_levels", "sigma", NULL};
char *fileName, *mapName;
@@ -149,7 +150,7 @@ static char ContextFunctions_read_map_pixel___doc__[] =
" :rtype: float\n";
static PyObject *
-ContextFunctions_read_map_pixel(PyObject *self, PyObject *args, PyObject *kwds)
+ContextFunctions_read_map_pixel(PyObject * /*self*/, PyObject *args, PyObject *kwds)
{
static const char *kwlist[] = {"map_name", "level", "x", "y", NULL};
char *mapName;
@@ -179,7 +180,7 @@ static char ContextFunctions_read_complete_view_map_pixel___doc__[] =
" :rtype: float\n";
static PyObject *
-ContextFunctions_read_complete_view_map_pixel(PyObject *self, PyObject *args, PyObject *kwds)
+ContextFunctions_read_complete_view_map_pixel(PyObject * /*self*/, PyObject *args, PyObject *kwds)
{
static const char *kwlist[] = {"level", "x", "y", NULL};
int level;
@@ -211,7 +212,7 @@ static char ContextFunctions_read_directional_view_map_pixel___doc__[] =
" :rtype: float\n";
static PyObject *
-ContextFunctions_read_directional_view_map_pixel(PyObject *self, PyObject *args, PyObject *kwds)
+ContextFunctions_read_directional_view_map_pixel(PyObject * /*self*/, PyObject *args, PyObject *kwds)
{
static const char *kwlist[] = {"orientation", "level", "x", "y", NULL};
int orientation, level;
@@ -231,7 +232,7 @@ static char ContextFunctions_get_selected_fedge___doc__[] =
" :rtype: :class:`FEdge`\n";
static PyObject *
-ContextFunctions_get_selected_fedge(PyObject *self)
+ContextFunctions_get_selected_fedge(PyObject * /*self*/)
{
FEdge *fe = ContextFunctions::GetSelectedFEdgeCF();
if (fe)
diff --git a/source/blender/freestyle/intern/python/BPy_Convert.cpp b/source/blender/freestyle/intern/python/BPy_Convert.cpp
index dbd836bc562..4e1a0a119aa 100644
--- a/source/blender/freestyle/intern/python/BPy_Convert.cpp
+++ b/source/blender/freestyle/intern/python/BPy_Convert.cpp
@@ -81,7 +81,7 @@ PyObject *Vector_from_Vec2f(Vec2f& vec)
float vec_data[2]; // because vec->_coord is protected
vec_data[0] = vec.x();
vec_data[1] = vec.y();
- return Vector_CreatePyObject(vec_data, 2, Py_NEW, NULL);
+ return Vector_CreatePyObject(vec_data, 2, NULL);
}
PyObject *Vector_from_Vec3f(Vec3f& vec)
@@ -90,7 +90,7 @@ PyObject *Vector_from_Vec3f(Vec3f& vec)
vec_data[0] = vec.x();
vec_data[1] = vec.y();
vec_data[2] = vec.z();
- return Vector_CreatePyObject(vec_data, 3, Py_NEW, NULL);
+ return Vector_CreatePyObject(vec_data, 3, NULL);
}
PyObject *Vector_from_Vec3r(Vec3r& vec)
@@ -99,7 +99,7 @@ PyObject *Vector_from_Vec3r(Vec3r& vec)
vec_data[0] = vec.x();
vec_data[1] = vec.y();
vec_data[2] = vec.z();
- return Vector_CreatePyObject(vec_data, 3, Py_NEW, NULL);
+ return Vector_CreatePyObject(vec_data, 3, NULL);
}
PyObject *BPy_Id_from_Id(Id& id)
@@ -401,8 +401,9 @@ PyObject *BPy_CurvePoint_from_CurvePoint(CurvePoint& cp)
PyObject *BPy_directedViewEdge_from_directedViewEdge(ViewVertex::directedViewEdge& dve)
{
PyObject *py_dve = PyTuple_New(2);
- PyTuple_SET_ITEM(py_dve, 0, BPy_ViewEdge_from_ViewEdge(*(dve.first)));
- PyTuple_SET_ITEM(py_dve, 1, PyBool_from_bool(dve.second));
+ PyTuple_SET_ITEMS(py_dve,
+ BPy_ViewEdge_from_ViewEdge(*(dve.first)),
+ PyBool_from_bool(dve.second));
return py_dve;
}
diff --git a/source/blender/freestyle/intern/python/BPy_Convert.h b/source/blender/freestyle/intern/python/BPy_Convert.h
index e6e763e763e..35c1e58369c 100644
--- a/source/blender/freestyle/intern/python/BPy_Convert.h
+++ b/source/blender/freestyle/intern/python/BPy_Convert.h
@@ -92,6 +92,7 @@ extern "C" {
///////////////////////////////////////////////////////////////////////////////////////////
#include "mathutils/mathutils.h"
+#include "generic/python_utildefines.h"
//==============================
// C++ => Python
diff --git a/source/blender/freestyle/intern/python/BPy_Freestyle.cpp b/source/blender/freestyle/intern/python/BPy_Freestyle.cpp
index 5b8d50eb5eb..d22632040f4 100644
--- a/source/blender/freestyle/intern/python/BPy_Freestyle.cpp
+++ b/source/blender/freestyle/intern/python/BPy_Freestyle.cpp
@@ -60,6 +60,7 @@ extern "C" {
#include "FRS_freestyle.h"
#include "RNA_access.h"
+#include "BKE_appdir.h"
#include "DNA_scene_types.h"
#include "bpy_rna.h" /* pyrna_struct_CreatePyObject() */
@@ -71,7 +72,7 @@ static char Freestyle_getCurrentScene___doc__[] =
" :return: The current scene.\n"
" :rtype: :class:`bpy.types.Scene`\n";
-static PyObject *Freestyle_getCurrentScene(PyObject *self)
+static PyObject *Freestyle_getCurrentScene(PyObject * /*self*/)
{
if (!freestyle_scene) {
PyErr_SetString(PyExc_TypeError, "current scene not available");
@@ -86,24 +87,24 @@ static PyObject *Freestyle_getCurrentScene(PyObject *self)
static int ramp_blend_type(const char *type)
{
- if (!strcmp(type, "MIX")) return MA_RAMP_BLEND;
- if (!strcmp(type, "ADD")) return MA_RAMP_ADD;
- if (!strcmp(type, "MULTIPLY")) return MA_RAMP_MULT;
- if (!strcmp(type, "SUBTRACT")) return MA_RAMP_SUB;
- if (!strcmp(type, "SCREEN")) return MA_RAMP_SCREEN;
- if (!strcmp(type, "DIVIDE")) return MA_RAMP_DIV;
- if (!strcmp(type, "DIFFERENCE")) return MA_RAMP_DIFF;
- if (!strcmp(type, "DARKEN")) return MA_RAMP_DARK;
- if (!strcmp(type, "LIGHTEN")) return MA_RAMP_LIGHT;
- if (!strcmp(type, "OVERLAY")) return MA_RAMP_OVERLAY;
- if (!strcmp(type, "DODGE")) return MA_RAMP_DODGE;
- if (!strcmp(type, "BURN")) return MA_RAMP_BURN;
- if (!strcmp(type, "HUE")) return MA_RAMP_HUE;
- if (!strcmp(type, "SATURATION")) return MA_RAMP_SAT;
- if (!strcmp(type, "VALUE")) return MA_RAMP_VAL;
- if (!strcmp(type, "COLOR")) return MA_RAMP_COLOR;
- if (!strcmp(type, "SOFT_LIGHT")) return MA_RAMP_SOFT;
- if (!strcmp(type, "LINEAR_LIGHT")) return MA_RAMP_LINEAR;
+ if (STREQ(type, "MIX")) return MA_RAMP_BLEND;
+ if (STREQ(type, "ADD")) return MA_RAMP_ADD;
+ if (STREQ(type, "MULTIPLY")) return MA_RAMP_MULT;
+ if (STREQ(type, "SUBTRACT")) return MA_RAMP_SUB;
+ if (STREQ(type, "SCREEN")) return MA_RAMP_SCREEN;
+ if (STREQ(type, "DIVIDE")) return MA_RAMP_DIV;
+ if (STREQ(type, "DIFFERENCE")) return MA_RAMP_DIFF;
+ if (STREQ(type, "DARKEN")) return MA_RAMP_DARK;
+ if (STREQ(type, "LIGHTEN")) return MA_RAMP_LIGHT;
+ if (STREQ(type, "OVERLAY")) return MA_RAMP_OVERLAY;
+ if (STREQ(type, "DODGE")) return MA_RAMP_DODGE;
+ if (STREQ(type, "BURN")) return MA_RAMP_BURN;
+ if (STREQ(type, "HUE")) return MA_RAMP_HUE;
+ if (STREQ(type, "SATURATION")) return MA_RAMP_SAT;
+ if (STREQ(type, "VALUE")) return MA_RAMP_VAL;
+ if (STREQ(type, "COLOR")) return MA_RAMP_COLOR;
+ if (STREQ(type, "SOFT_LIGHT")) return MA_RAMP_SOFT;
+ if (STREQ(type, "LINEAR_LIGHT")) return MA_RAMP_LINEAR;
return -1;
}
@@ -125,7 +126,7 @@ static char Freestyle_blendRamp___doc__[] =
" :return: Blended color in RGB format.\n"
" :rtype: :class:`mathutils.Vector`\n";
-static PyObject *Freestyle_blendRamp(PyObject *self, PyObject *args)
+static PyObject *Freestyle_blendRamp(PyObject * /*self*/, PyObject *args)
{
PyObject *obj1, *obj2;
char *s;
@@ -152,7 +153,7 @@ static PyObject *Freestyle_blendRamp(PyObject *self, PyObject *args)
return NULL;
}
ramp_blend(type, a, fac, b);
- return Vector_CreatePyObject(a, 3, Py_NEW, NULL);
+ return Vector_CreatePyObject(a, 3, NULL);
}
#include "BKE_texture.h" /* do_colorband() */
@@ -169,7 +170,7 @@ static char Freestyle_evaluateColorRamp___doc__[] =
" :return: color in RGBA format.\n"
" :rtype: :class:`mathutils.Vector`\n";
-static PyObject *Freestyle_evaluateColorRamp(PyObject *self, PyObject *args)
+static PyObject *Freestyle_evaluateColorRamp(PyObject * /*self*/, PyObject *args)
{
BPy_StructRNA *py_srna;
ColorBand *coba;
@@ -186,7 +187,7 @@ static PyObject *Freestyle_evaluateColorRamp(PyObject *self, PyObject *args)
PyErr_SetString(PyExc_ValueError, "failed to evaluate the color ramp");
return NULL;
}
- return Vector_CreatePyObject(out, 4, Py_NEW, NULL);
+ return Vector_CreatePyObject(out, 4, NULL);
}
#include "DNA_color_types.h"
@@ -206,7 +207,7 @@ static char Freestyle_evaluateCurveMappingF___doc__[] =
" :return: Mapped output value.\n"
" :rtype: float\n";
-static PyObject *Freestyle_evaluateCurveMappingF(PyObject *self, PyObject *args)
+static PyObject *Freestyle_evaluateCurveMappingF(PyObject * /*self*/, PyObject *args)
{
BPy_StructRNA *py_srna;
CurveMapping *cumap;
@@ -492,7 +493,7 @@ PyObject *Freestyle_Init(void)
PyDict_SetItemString(PySys_GetObject("modules"), module_definition.m_name, module);
// update 'sys.path' for Freestyle Python API modules
- const char * const path = BLI_get_folder(BLENDER_SYSTEM_SCRIPTS, "freestyle");
+ const char * const path = BKE_appdir_folder_id(BLENDER_SYSTEM_SCRIPTS, "freestyle");
if (path) {
char modpath[FILE_MAX];
BLI_join_dirfile(modpath, sizeof(modpath), path, "modules");
diff --git a/source/blender/freestyle/intern/python/BPy_FrsMaterial.cpp b/source/blender/freestyle/intern/python/BPy_FrsMaterial.cpp
index 4d0d140474a..1866058a151 100644
--- a/source/blender/freestyle/intern/python/BPy_FrsMaterial.cpp
+++ b/source/blender/freestyle/intern/python/BPy_FrsMaterial.cpp
@@ -30,6 +30,9 @@
extern "C" {
#endif
+#include "BLI_hash_mm2a.h"
+
+
///////////////////////////////////////////////////////////////////////////////////////////
//-------------------MODULE INITIALIZATION--------------------------------
@@ -220,10 +223,10 @@ static int FrsMaterial_mathutils_get_index(BaseMathObject *bmo, int subtype, int
BPy_FrsMaterial *self = (BPy_FrsMaterial *)bmo->cb_user;
switch (subtype) {
case MATHUTILS_SUBTYPE_LINE:
- {
- const float *color = self->m->line();
- bmo->data[index] = color[index];
- }
+ {
+ const float *color = self->m->line();
+ bmo->data[index] = color[index];
+ }
break;
case MATHUTILS_SUBTYPE_DIFFUSE:
{
@@ -478,6 +481,48 @@ static PyGetSetDef BPy_FrsMaterial_getseters[] = {
{NULL, NULL, NULL, NULL, NULL} /* Sentinel */
};
+static PyObject *BPy_FrsMaterial_richcmpr(PyObject *objectA, PyObject *objectB, int comparison_type)
+{
+ const BPy_FrsMaterial *matA = NULL, *matB = NULL;
+ bool result = 0;
+
+ if (!BPy_FrsMaterial_Check(objectA) || !BPy_FrsMaterial_Check(objectB)) {
+ if (comparison_type == Py_NE) {
+ Py_RETURN_TRUE;
+ }
+ else {
+ Py_RETURN_FALSE;
+ }
+ }
+
+ matA = (BPy_FrsMaterial *)objectA;
+ matB = (BPy_FrsMaterial *)objectB;
+
+ switch (comparison_type) {
+ case Py_NE:
+ result = (*matA->m) != (*matB->m);
+ break;
+ case Py_EQ:
+ result = (*matA->m) == (*matB->m);
+ break;
+ default:
+ PyErr_SetString(PyExc_TypeError, "Material does not support this comparison type");
+ return NULL;
+ }
+
+ if (result == true) {
+ Py_RETURN_TRUE;
+ }
+ else {
+ Py_RETURN_FALSE;
+ }
+}
+
+
+static Py_hash_t FrsMaterial_hash(PyObject *self)
+{
+ return (Py_uhash_t)BLI_hash_mm2((const unsigned char *)self, sizeof(*self), 0);
+}
/*-----------------------BPy_FrsMaterial type definition ------------------------------*/
PyTypeObject FrsMaterial_Type = {
@@ -494,7 +539,7 @@ PyTypeObject FrsMaterial_Type = {
0, /* tp_as_number */
0, /* tp_as_sequence */
0, /* tp_as_mapping */
- 0, /* tp_hash */
+ (hashfunc)FrsMaterial_hash, /* tp_hash */
0, /* tp_call */
0, /* tp_str */
0, /* tp_getattro */
@@ -504,7 +549,7 @@ PyTypeObject FrsMaterial_Type = {
FrsMaterial_doc, /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
- 0, /* tp_richcompare */
+ (richcmpfunc)BPy_FrsMaterial_richcmpr, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
diff --git a/source/blender/freestyle/intern/python/BPy_FrsNoise.cpp b/source/blender/freestyle/intern/python/BPy_FrsNoise.cpp
index 39e4aed7cc0..3f29d9899e8 100644
--- a/source/blender/freestyle/intern/python/BPy_FrsNoise.cpp
+++ b/source/blender/freestyle/intern/python/BPy_FrsNoise.cpp
@@ -25,6 +25,8 @@
#include "BPy_FrsNoise.h"
#include "BPy_Convert.h"
+#include "../system/RandGen.h"
+
#include <sstream>
#ifdef __cplusplus
@@ -69,12 +71,14 @@ static int FrsNoise_init(BPy_FrsNoise *self, PyObject *args, PyObject *kwds)
if (!PyArg_ParseTupleAndKeywords(args, kwds, "|l", (char **)kwlist, &seed))
return -1;
self->n = new Noise(seed);
+ self->pn = new PseudoNoise();
return 0;
}
static void FrsNoise_dealloc(BPy_FrsNoise *self)
{
delete self->n;
+ delete self->pn;
Py_TYPE(self)->tp_free((PyObject *)self);
}
@@ -99,6 +103,32 @@ PyDoc_STRVAR(FrsNoise_turbulence1_doc,
" :return: A noise value.\n"
" :rtype: float");
+static PyObject *FrsNoise_drand(BPy_FrsNoise * /*self*/, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {"seed", NULL};
+ long seed = 0;
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "|I", (char **)kwlist, &seed)) {
+ PyErr_SetString(PyExc_TypeError, "optional argument 1 must be of type int");
+ return NULL;
+ }
+ if (seed){
+ RandGen::srand48(seed);
+ }
+ return PyFloat_FromDouble(RandGen::drand48());
+}
+
+static PyObject *FrsNoise_turbulence_smooth(BPy_FrsNoise *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {"v", "oct", NULL};
+
+ double x; // note: this has to be a double (not float)
+ unsigned nbOctaves = 8;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "d|I", (char **)kwlist, &x, &nbOctaves))
+ return NULL;
+ return PyFloat_FromDouble(self->pn->turbulenceSmooth(x, nbOctaves));
+}
+
static PyObject *FrsNoise_turbulence1(BPy_FrsNoise *self, PyObject *args, PyObject *kwds)
{
static const char *kwlist[] = {"v", "freq", "amp", "oct", NULL};
@@ -257,6 +287,8 @@ static PyMethodDef BPy_FrsNoise_methods[] = {
{"smoothNoise1", (PyCFunction)FrsNoise_smoothNoise1, METH_VARARGS | METH_KEYWORDS, FrsNoise_smoothNoise1_doc},
{"smoothNoise2", (PyCFunction)FrsNoise_smoothNoise2, METH_VARARGS | METH_KEYWORDS, FrsNoise_smoothNoise2_doc},
{"smoothNoise3", (PyCFunction)FrsNoise_smoothNoise3, METH_VARARGS | METH_KEYWORDS, FrsNoise_smoothNoise3_doc},
+ {"rand", (PyCFunction)FrsNoise_drand, METH_VARARGS | METH_KEYWORDS, NULL},
+ {"turbulence_smooth", (PyCFunction)FrsNoise_turbulence_smooth, METH_VARARGS | METH_KEYWORDS, NULL},
{NULL, NULL, 0, NULL}
};
diff --git a/source/blender/freestyle/intern/python/BPy_FrsNoise.h b/source/blender/freestyle/intern/python/BPy_FrsNoise.h
index 19788e30a43..a5a1064ea8d 100644
--- a/source/blender/freestyle/intern/python/BPy_FrsNoise.h
+++ b/source/blender/freestyle/intern/python/BPy_FrsNoise.h
@@ -30,6 +30,7 @@ extern "C" {
}
#include "../geometry/Noise.h"
+#include "../system/PseudoNoise.h"
using namespace Freestyle;
@@ -47,6 +48,7 @@ extern PyTypeObject FrsNoise_Type;
typedef struct {
PyObject_HEAD
Noise *n;
+ PseudoNoise *pn;
} BPy_FrsNoise;
/*---------------------------Python BPy_FrsNoise visible prototypes-----------*/
diff --git a/source/blender/freestyle/intern/python/BPy_IntegrationType.cpp b/source/blender/freestyle/intern/python/BPy_IntegrationType.cpp
index 7a3624f248e..0db25753caa 100644
--- a/source/blender/freestyle/intern/python/BPy_IntegrationType.cpp
+++ b/source/blender/freestyle/intern/python/BPy_IntegrationType.cpp
@@ -63,7 +63,7 @@ PyDoc_STRVAR(Integrator_integrate_doc,
" :class:`UnaryFunction0DUnsigned` type.\n"
" :rtype: int or float");
-static PyObject * Integrator_integrate(PyObject *self, PyObject *args, PyObject *kwds)
+static PyObject * Integrator_integrate(PyObject * /*self*/, PyObject *args, PyObject *kwds)
{
static const char *kwlist[] = {"func", "it", "it_end", "integration_type", NULL};
PyObject *obj1, *obj4 = 0;
diff --git a/source/blender/freestyle/intern/python/BPy_Operators.cpp b/source/blender/freestyle/intern/python/BPy_Operators.cpp
index 6beeafe0065..1b2b18c2c99 100644
--- a/source/blender/freestyle/intern/python/BPy_Operators.cpp
+++ b/source/blender/freestyle/intern/python/BPy_Operators.cpp
@@ -34,6 +34,8 @@
#include "BPy_StrokeShader.h"
#include "BPy_Convert.h"
+#include <sstream>
+
#ifdef __cplusplus
extern "C" {
#endif
@@ -76,7 +78,7 @@ PyDoc_STRVAR(Operators_select_doc,
" :arg pred: The predicate expressing this condition.\n"
" :type pred: :class:`UnaryPredicate1D`");
-static PyObject *Operators_select(BPy_Operators *self, PyObject *args, PyObject *kwds)
+static PyObject *Operators_select(BPy_Operators * /*self*/, PyObject *args, PyObject *kwds)
{
static const char *kwlist[] = {"pred", NULL};
PyObject *obj = 0;
@@ -135,7 +137,7 @@ PyDoc_STRVAR(Operators_chain_doc,
" stopping condition.\n"
" :type pred: :class:`UnaryPredicate1D`");
-static PyObject *Operators_chain(BPy_Operators *self, PyObject *args, PyObject *kwds)
+static PyObject *Operators_chain(BPy_Operators * /*self*/, PyObject *args, PyObject *kwds)
{
static const char *kwlist[] = {"it", "pred", "modifier", NULL};
PyObject *obj1 = 0, *obj2 = 0, *obj3 = 0;
@@ -224,7 +226,7 @@ PyDoc_STRVAR(Operators_bidirectional_chain_doc,
" contains the chaining rule.\n"
" :type it: :class:`ChainingIterator`");
-static PyObject *Operators_bidirectional_chain(BPy_Operators *self, PyObject *args, PyObject *kwds)
+static PyObject *Operators_bidirectional_chain(BPy_Operators * /*self*/, PyObject *args, PyObject *kwds)
{
static const char *kwlist[] = {"it", "pred", NULL};
PyObject *obj1 = 0, *obj2 = 0;
@@ -304,7 +306,7 @@ PyDoc_STRVAR(Operators_sequential_split_doc,
" resolution.)\n"
" :type sampling: float");
-static PyObject *Operators_sequential_split(BPy_Operators *self, PyObject *args, PyObject *kwds)
+static PyObject *Operators_sequential_split(BPy_Operators * /*self*/, PyObject *args, PyObject *kwds)
{
static const char *kwlist_1[] = {"starting_pred", "stopping_pred", "sampling", NULL};
static const char *kwlist_2[] = {"pred", "sampling", NULL};
@@ -411,7 +413,7 @@ PyDoc_STRVAR(Operators_recursive_split_doc,
" resolution.)\n"
" :type sampling: float");
-static PyObject *Operators_recursive_split(BPy_Operators *self, PyObject *args, PyObject *kwds)
+static PyObject *Operators_recursive_split(BPy_Operators * /*self*/, PyObject *args, PyObject *kwds)
{
static const char *kwlist_1[] = {"func", "pred_1d", "sampling", NULL};
static const char *kwlist_2[] = {"func", "pred_0d", "pred_1d", "sampling", NULL};
@@ -486,7 +488,7 @@ PyDoc_STRVAR(Operators_sort_doc,
" :arg pred: The binary predicate used for the comparison.\n"
" :type pred: :class:`BinaryPredicate1D`");
-static PyObject *Operators_sort(BPy_Operators *self, PyObject *args, PyObject *kwds)
+static PyObject *Operators_sort(BPy_Operators * /*self*/, PyObject *args, PyObject *kwds)
{
static const char *kwlist[] = {"pred", NULL};
PyObject *obj = 0;
@@ -517,7 +519,7 @@ PyDoc_STRVAR(Operators_create_doc,
" :arg shaders: The list of shaders used to shade the strokes.\n"
" :type shaders: list of :class:`StrokeShader` objects");
-static PyObject *Operators_create(BPy_Operators *self, PyObject *args, PyObject *kwds)
+static PyObject *Operators_create(BPy_Operators * /*self*/, PyObject *args, PyObject *kwds)
{
static const char *kwlist[] = {"pred", "shaders", NULL};
PyObject *obj1 = 0, *obj2 = 0;
@@ -532,13 +534,22 @@ static PyObject *Operators_create(BPy_Operators *self, PyObject *args, PyObject
return NULL;
}
vector<StrokeShader *> shaders;
+ shaders.reserve(PyList_Size(obj2));
for (int i = 0; i < PyList_Size(obj2); i++) {
- PyObject *py_ss = PyList_GetItem(obj2, i);
+ PyObject *py_ss = PyList_GET_ITEM(obj2, i);
if (!BPy_StrokeShader_Check(py_ss)) {
PyErr_SetString(PyExc_TypeError, "Operators.create(): 2nd argument must be a list of StrokeShader objects");
return NULL;
}
- shaders.push_back(((BPy_StrokeShader *)py_ss)->ss);
+ StrokeShader *shader = ((BPy_StrokeShader *)py_ss)->ss;
+ if (!shader) {
+ stringstream ss;
+ ss << "Operators.create(): item " << (i + 1)
+ << " of the shaders list is invalid likely due to missing call of StrokeShader.__init__()";
+ PyErr_SetString(PyExc_TypeError, ss.str().c_str());
+ return NULL;
+ }
+ shaders.push_back(shader);
}
if (Operators::create(*(((BPy_UnaryPredicate1D *)obj1)->up1D), shaders) < 0) {
if (!PyErr_Occurred())
@@ -548,6 +559,30 @@ static PyObject *Operators_create(BPy_Operators *self, PyObject *args, PyObject
Py_RETURN_NONE;
}
+PyDoc_STRVAR(Operators_reset_doc,
+".. staticmethod:: reset(delete_strokes=True)\n"
+"\n"
+" Resets the line stylization process to the initial state. The results of\n"
+" stroke creation are accumulated if **delete_strokes** is set to False.\n"
+"\n"
+" :arg delete_strokes: Delete the strokes that are currently stored.\n"
+" :type delete_strokes: bool\n");
+
+static PyObject *Operators_reset(BPy_Operators * /*self*/, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {"delete_strokes", NULL};
+ PyObject *obj1 = 0;
+ if (PyArg_ParseTupleAndKeywords(args, kwds, "|O!", (char **)kwlist, &PyBool_Type, &obj1)) {
+ // true is the default
+ Operators::reset(obj1 ? bool_from_PyBool(obj1) : true);
+ }
+ else {
+ PyErr_SetString(PyExc_RuntimeError, "Operators.reset() failed");
+ return NULL;
+ }
+ Py_RETURN_NONE;
+}
+
PyDoc_STRVAR(Operators_get_viewedge_from_index_doc,
".. staticmethod:: get_viewedge_from_index(i)\n"
"\n"
@@ -558,7 +593,7 @@ PyDoc_STRVAR(Operators_get_viewedge_from_index_doc,
" :return: The ViewEdge object.\n"
" :rtype: :class:`ViewEdge`");
-static PyObject *Operators_get_viewedge_from_index(BPy_Operators *self, PyObject *args, PyObject *kwds)
+static PyObject *Operators_get_viewedge_from_index(BPy_Operators * /*self*/, PyObject *args, PyObject *kwds)
{
static const char *kwlist[] = {"i", NULL};
unsigned int i;
@@ -582,7 +617,7 @@ PyDoc_STRVAR(Operators_get_chain_from_index_doc,
" :return: The Chain object.\n"
" :rtype: :class:`Chain`");
-static PyObject *Operators_get_chain_from_index(BPy_Operators *self, PyObject *args, PyObject *kwds)
+static PyObject *Operators_get_chain_from_index(BPy_Operators * /*self*/, PyObject *args, PyObject *kwds)
{
static const char *kwlist[] = {"i", NULL};
unsigned int i;
@@ -606,7 +641,7 @@ PyDoc_STRVAR(Operators_get_stroke_from_index_doc,
" :return: The Stroke object.\n"
" :rtype: :class:`Stroke`");
-static PyObject *Operators_get_stroke_from_index(BPy_Operators *self, PyObject *args, PyObject *kwds)
+static PyObject *Operators_get_stroke_from_index(BPy_Operators * /*self*/, PyObject *args, PyObject *kwds)
{
static const char *kwlist[] = {"i", NULL};
unsigned int i;
@@ -628,7 +663,7 @@ PyDoc_STRVAR(Operators_get_view_edges_size_doc,
" :return: The number of ViewEdges.\n"
" :rtype: int");
-static PyObject *Operators_get_view_edges_size(BPy_Operators *self)
+static PyObject *Operators_get_view_edges_size(BPy_Operators * /*self*/)
{
return PyLong_FromLong(Operators::getViewEdgesSize());
}
@@ -641,7 +676,7 @@ PyDoc_STRVAR(Operators_get_chains_size_doc,
" :return: The number of Chains.\n"
" :rtype: int");
-static PyObject *Operators_get_chains_size(BPy_Operators *self)
+static PyObject *Operators_get_chains_size(BPy_Operators * /*self*/)
{
return PyLong_FromLong(Operators::getChainsSize());
}
@@ -654,7 +689,7 @@ PyDoc_STRVAR(Operators_get_strokes_size_doc,
" :return: The number of Strokes.\n"
" :rtype: int");
-static PyObject *Operators_get_strokes_size(BPy_Operators *self)
+static PyObject *Operators_get_strokes_size(BPy_Operators * /*self*/)
{
return PyLong_FromLong(Operators::getStrokesSize());
}
@@ -671,6 +706,7 @@ static PyMethodDef BPy_Operators_methods[] = {
Operators_recursive_split_doc},
{"sort", (PyCFunction) Operators_sort, METH_VARARGS | METH_KEYWORDS | METH_STATIC, Operators_sort_doc},
{"create", (PyCFunction) Operators_create, METH_VARARGS | METH_KEYWORDS | METH_STATIC, Operators_create_doc},
+ {"reset", (PyCFunction) Operators_reset, METH_VARARGS | METH_KEYWORDS | METH_STATIC, Operators_reset_doc},
{"get_viewedge_from_index", (PyCFunction) Operators_get_viewedge_from_index,
METH_VARARGS | METH_KEYWORDS | METH_STATIC, Operators_get_viewedge_from_index_doc},
{"get_chain_from_index", (PyCFunction) Operators_get_chain_from_index, METH_VARARGS | METH_KEYWORDS | METH_STATIC,
diff --git a/source/blender/freestyle/intern/python/BPy_SShape.cpp b/source/blender/freestyle/intern/python/BPy_SShape.cpp
index e5a38171ecd..9169adf4d9f 100644
--- a/source/blender/freestyle/intern/python/BPy_SShape.cpp
+++ b/source/blender/freestyle/intern/python/BPy_SShape.cpp
@@ -185,7 +185,7 @@ PyDoc_STRVAR(SShape_name_doc,
static PyObject *SShape_name_get(BPy_SShape *self, void *UNUSED(closure))
{
- return PyUnicode_FromString(self->ss->getName().c_str());
+ return PyUnicode_FromString(self->ss->getName());
}
static int SShape_name_set(BPy_SShape *self, PyObject *value, void *UNUSED(closure))
@@ -194,7 +194,7 @@ static int SShape_name_set(BPy_SShape *self, PyObject *value, void *UNUSED(closu
PyErr_SetString(PyExc_TypeError, "value must be a string");
return -1;
}
- const string name = _PyUnicode_AsString(value);
+ const char *name = _PyUnicode_AsString(value);
self->ss->setName(name);
return 0;
}
@@ -227,13 +227,14 @@ PyDoc_STRVAR(SShape_vertices_doc,
static PyObject *SShape_vertices_get(BPy_SShape *self, void *UNUSED(closure))
{
- PyObject *py_vertices = PyList_New(0);
vector< SVertex * > vertices = self->ss->getVertexList();
vector< SVertex * >::iterator it;
+ PyObject *py_vertices = PyList_New(vertices.size());
+ unsigned int i = 0;
for (it = vertices.begin(); it != vertices.end(); it++) {
- PyList_Append(py_vertices, BPy_SVertex_from_SVertex(*(*it)));
+ PyList_SET_ITEM(py_vertices, i++, BPy_SVertex_from_SVertex(*(*it)));
}
return py_vertices;
@@ -246,13 +247,14 @@ PyDoc_STRVAR(SShape_edges_doc,
static PyObject *SShape_edges_get(BPy_SShape *self, void *UNUSED(closure))
{
- PyObject *py_edges = PyList_New(0);
vector< FEdge * > edges = self->ss->getEdgeList();
vector< FEdge * >::iterator it;
+ PyObject *py_edges = PyList_New(edges.size());
+ unsigned int i = 0;
for (it = edges.begin(); it != edges.end(); it++) {
- PyList_Append(py_edges, Any_BPy_FEdge_from_FEdge(*(*it)));
+ PyList_SET_ITEM(py_edges, i++, Any_BPy_FEdge_from_FEdge(*(*it)));
}
return py_edges;
diff --git a/source/blender/freestyle/intern/python/BPy_StrokeShader.cpp b/source/blender/freestyle/intern/python/BPy_StrokeShader.cpp
index a6c7a40e780..6b4a1872b61 100644
--- a/source/blender/freestyle/intern/python/BPy_StrokeShader.cpp
+++ b/source/blender/freestyle/intern/python/BPy_StrokeShader.cpp
@@ -32,11 +32,9 @@
#include "StrokeShader/BPy_BlenderTextureShader.h"
#include "StrokeShader/BPy_CalligraphicShader.h"
#include "StrokeShader/BPy_ColorNoiseShader.h"
-#include "StrokeShader/BPy_ColorVariationPatternShader.h"
#include "StrokeShader/BPy_ConstantColorShader.h"
#include "StrokeShader/BPy_ConstantThicknessShader.h"
#include "StrokeShader/BPy_ConstrainedIncreasingThicknessShader.h"
-#include "StrokeShader/BPy_fstreamShader.h"
#include "StrokeShader/BPy_GuidingLinesShader.h"
#include "StrokeShader/BPy_IncreasingColorShader.h"
#include "StrokeShader/BPy_IncreasingThicknessShader.h"
@@ -44,12 +42,8 @@
#include "StrokeShader/BPy_SamplingShader.h"
#include "StrokeShader/BPy_SmoothingShader.h"
#include "StrokeShader/BPy_SpatialNoiseShader.h"
-#include "StrokeShader/BPy_streamShader.h"
-#include "StrokeShader/BPy_StrokeTextureShader.h"
#include "StrokeShader/BPy_StrokeTextureStepShader.h"
-#include "StrokeShader/BPy_TextureAssignerShader.h"
#include "StrokeShader/BPy_ThicknessNoiseShader.h"
-#include "StrokeShader/BPy_ThicknessVariationPatternShader.h"
#include "StrokeShader/BPy_TipRemoverShader.h"
#ifdef __cplusplus
@@ -94,11 +88,6 @@ int StrokeShader_Init(PyObject *module)
Py_INCREF(&ColorNoiseShader_Type);
PyModule_AddObject(module, "ColorNoiseShader", (PyObject *)&ColorNoiseShader_Type);
- if (PyType_Ready(&ColorVariationPatternShader_Type) < 0)
- return -1;
- Py_INCREF(&ColorVariationPatternShader_Type);
- PyModule_AddObject(module, "ColorVariationPatternShader", (PyObject *)&ColorVariationPatternShader_Type);
-
if (PyType_Ready(&ConstantColorShader_Type) < 0)
return -1;
Py_INCREF(&ConstantColorShader_Type);
@@ -115,11 +104,6 @@ int StrokeShader_Init(PyObject *module)
PyModule_AddObject(module, "ConstrainedIncreasingThicknessShader",
(PyObject *)&ConstrainedIncreasingThicknessShader_Type);
- if (PyType_Ready(&fstreamShader_Type) < 0)
- return -1;
- Py_INCREF(&fstreamShader_Type);
- PyModule_AddObject(module, "fstreamShader", (PyObject *)&fstreamShader_Type);
-
if (PyType_Ready(&GuidingLinesShader_Type) < 0)
return -1;
Py_INCREF(&GuidingLinesShader_Type);
@@ -155,36 +139,16 @@ int StrokeShader_Init(PyObject *module)
Py_INCREF(&SpatialNoiseShader_Type);
PyModule_AddObject(module, "SpatialNoiseShader", (PyObject *)&SpatialNoiseShader_Type);
- if (PyType_Ready(&streamShader_Type) < 0)
- return -1;
- Py_INCREF(&streamShader_Type);
- PyModule_AddObject(module, "streamShader", (PyObject *)&streamShader_Type);
-
- if (PyType_Ready(&StrokeTextureShader_Type) < 0)
- return -1;
- Py_INCREF(&StrokeTextureShader_Type);
- PyModule_AddObject(module, "StrokeTextureShader", (PyObject *)&StrokeTextureShader_Type);
-
if (PyType_Ready(&StrokeTextureStepShader_Type) < 0)
return -1;
Py_INCREF(&StrokeTextureStepShader_Type);
PyModule_AddObject(module, "StrokeTextureStepShader", (PyObject *)&StrokeTextureStepShader_Type);
- if (PyType_Ready(&TextureAssignerShader_Type) < 0)
- return -1;
- Py_INCREF(&TextureAssignerShader_Type);
- PyModule_AddObject(module, "TextureAssignerShader", (PyObject *)&TextureAssignerShader_Type);
-
if (PyType_Ready(&ThicknessNoiseShader_Type) < 0)
return -1;
Py_INCREF(&ThicknessNoiseShader_Type);
PyModule_AddObject(module, "ThicknessNoiseShader", (PyObject *)&ThicknessNoiseShader_Type);
- if (PyType_Ready(&ThicknessVariationPatternShader_Type) < 0)
- return -1;
- Py_INCREF(&ThicknessVariationPatternShader_Type);
- PyModule_AddObject(module, "ThicknessVariationPatternShader", (PyObject *)&ThicknessVariationPatternShader_Type);
-
if (PyType_Ready(&TipRemoverShader_Type) < 0)
return -1;
Py_INCREF(&TipRemoverShader_Type);
diff --git a/source/blender/freestyle/intern/python/BPy_UnaryFunction0D.cpp b/source/blender/freestyle/intern/python/BPy_UnaryFunction0D.cpp
index be20febba2b..0941efe9df5 100644
--- a/source/blender/freestyle/intern/python/BPy_UnaryFunction0D.cpp
+++ b/source/blender/freestyle/intern/python/BPy_UnaryFunction0D.cpp
@@ -93,7 +93,7 @@ static void UnaryFunction0D___dealloc__(BPy_UnaryFunction0D *self)
Py_TYPE(self)->tp_free((PyObject *)self);
}
-static PyObject *UnaryFunction0D___repr__(BPy_UnaryFunction0D *self)
+static PyObject *UnaryFunction0D___repr__(BPy_UnaryFunction0D * /*self*/)
{
return PyUnicode_FromString("UnaryFunction0D");
}
diff --git a/source/blender/freestyle/intern/python/BPy_UnaryFunction1D.cpp b/source/blender/freestyle/intern/python/BPy_UnaryFunction1D.cpp
index b88d609e48d..1b82c7777c7 100644
--- a/source/blender/freestyle/intern/python/BPy_UnaryFunction1D.cpp
+++ b/source/blender/freestyle/intern/python/BPy_UnaryFunction1D.cpp
@@ -87,7 +87,7 @@ static void UnaryFunction1D___dealloc__(BPy_UnaryFunction1D *self)
Py_TYPE(self)->tp_free((PyObject *)self);
}
-static PyObject *UnaryFunction1D___repr__(BPy_UnaryFunction1D *self)
+static PyObject *UnaryFunction1D___repr__(BPy_UnaryFunction1D * /*self*/)
{
return PyUnicode_FromString("UnaryFunction1D");
}
diff --git a/source/blender/freestyle/intern/python/BPy_ViewShape.cpp b/source/blender/freestyle/intern/python/BPy_ViewShape.cpp
index 2c767eacaec..253bf278478 100644
--- a/source/blender/freestyle/intern/python/BPy_ViewShape.cpp
+++ b/source/blender/freestyle/intern/python/BPy_ViewShape.cpp
@@ -207,19 +207,19 @@ PyDoc_STRVAR(ViewShape_vertices_doc,
static PyObject *ViewShape_vertices_get(BPy_ViewShape *self, void *UNUSED(closure))
{
- PyObject *py_vertices = PyList_New(0);
-
vector<ViewVertex *> vertices = self->vs->vertices();
vector<ViewVertex *>::iterator it;
+ PyObject *py_vertices = PyList_New(vertices.size());
+ unsigned int i = 0;
+
for (it = vertices.begin(); it != vertices.end(); it++) {
- PyList_Append( py_vertices, Any_BPy_ViewVertex_from_ViewVertex(*(*it)));
+ PyList_SET_ITEM(py_vertices, i++, Any_BPy_ViewVertex_from_ViewVertex(*(*it)));
}
return py_vertices;
}
static int ViewShape_vertices_set(BPy_ViewShape *self, PyObject *value, void *UNUSED(closure))
{
- PyObject *list = 0;
PyObject *item;
vector< ViewVertex *> v;
@@ -227,8 +227,10 @@ static int ViewShape_vertices_set(BPy_ViewShape *self, PyObject *value, void *UN
PyErr_SetString(PyExc_TypeError, "value must be a list of ViewVertex objects");
return -1;
}
- for (int i = 0; i < PyList_Size(list); i++) {
- item = PyList_GetItem(list, i);
+
+ v.reserve(PyList_GET_SIZE(value));
+ for (unsigned int i = 0; i < PyList_GET_SIZE(value); i++) {
+ item = PyList_GET_ITEM(value, i);
if (BPy_ViewVertex_Check(item)) {
v.push_back(((BPy_ViewVertex *)item)->vv);
}
@@ -248,20 +250,19 @@ PyDoc_STRVAR(ViewShape_edges_doc,
static PyObject *ViewShape_edges_get(BPy_ViewShape *self, void *UNUSED(closure))
{
- PyObject *py_edges = PyList_New(0);
-
vector<ViewEdge *> edges = self->vs->edges();
vector<ViewEdge *>::iterator it;
+ PyObject *py_edges = PyList_New(edges.size());
+ unsigned int i = 0;
for (it = edges.begin(); it != edges.end(); it++) {
- PyList_Append(py_edges, BPy_ViewEdge_from_ViewEdge(*(*it)));
+ PyList_SET_ITEM(py_edges, i++, BPy_ViewEdge_from_ViewEdge(*(*it)));
}
return py_edges;
}
static int ViewShape_edges_set(BPy_ViewShape *self, PyObject *value, void *UNUSED(closure))
{
- PyObject *list = 0;
PyObject *item;
vector<ViewEdge *> v;
@@ -269,8 +270,10 @@ static int ViewShape_edges_set(BPy_ViewShape *self, PyObject *value, void *UNUSE
PyErr_SetString(PyExc_TypeError, "value must be a list of ViewEdge objects");
return -1;
}
- for (int i = 0; i < PyList_Size(list); i++) {
- item = PyList_GetItem(list, i);
+
+ v.reserve(PyList_GET_SIZE(value));
+ for (int i = 0; i < PyList_GET_SIZE(value); i++) {
+ item = PyList_GET_ITEM(value, i);
if (BPy_ViewEdge_Check(item)) {
v.push_back(((BPy_ViewEdge *)item)->ve);
}
@@ -290,7 +293,7 @@ PyDoc_STRVAR(ViewShape_name_doc,
static PyObject *ViewShape_name_get(BPy_ViewShape *self, void *UNUSED(closure))
{
- return PyUnicode_FromString(self->vs->getName().c_str());
+ return PyUnicode_FromString(self->vs->getName());
}
PyDoc_STRVAR(ViewShape_id_doc,
diff --git a/source/blender/freestyle/intern/python/Director.cpp b/source/blender/freestyle/intern/python/Director.cpp
index 653fd0b1d29..9f85e84e297 100644
--- a/source/blender/freestyle/intern/python/Director.cpp
+++ b/source/blender/freestyle/intern/python/Director.cpp
@@ -265,8 +265,9 @@ int Director_BPy_UnaryFunction0D___call__(void *uf0D, void *py_uf0D, Interface0D
}
else if (BPy_UnaryFunction0DVectorViewShape_Check(obj)) {
vector<ViewShape*> vec;
+ vec.reserve(PyList_Size(result));
for (int i = 0; i < PyList_Size(result); i++) {
- ViewShape *b = ((BPy_ViewShape *)PyList_GetItem(result, i))->vs;
+ ViewShape *b = ((BPy_ViewShape *)PyList_GET_ITEM(result, i))->vs;
vec.push_back(b);
}
((UnaryFunction0D< vector<ViewShape*> > *)uf0D)->result = vec;
@@ -318,8 +319,9 @@ int Director_BPy_UnaryFunction1D___call__(void *uf1D, void *py_uf1D, Interface1D
}
else if (BPy_UnaryFunction1DVectorViewShape_Check(obj)) {
vector<ViewShape*> vec;
+ vec.reserve(PyList_Size(result));
for (int i = 1; i < PyList_Size(result); i++) {
- ViewShape *b = ((BPy_ViewShape *)PyList_GetItem(result, i))->vs;
+ ViewShape *b = ((BPy_ViewShape *)PyList_GET_ITEM(result, i))->vs;
vec.push_back(b);
}
((UnaryFunction1D< vector<ViewShape*> > *)uf1D)->result = vec;
diff --git a/source/blender/freestyle/intern/python/Interface0D/BPy_CurvePoint.cpp b/source/blender/freestyle/intern/python/Interface0D/BPy_CurvePoint.cpp
index 1ef29792d56..446587c2388 100644
--- a/source/blender/freestyle/intern/python/Interface0D/BPy_CurvePoint.cpp
+++ b/source/blender/freestyle/intern/python/Interface0D/BPy_CurvePoint.cpp
@@ -188,7 +188,10 @@ static PyObject *CurvePoint_fedge_get(BPy_CurvePoint *self, void *UNUSED(closure
{
SVertex *A = self->cp->A();
Interface0D *B = (Interface0D *)self->cp->B();
- return Any_BPy_Interface1D_from_Interface1D(*(A->getFEdge(*B)));
+ // B can be NULL under certain circumstances
+ if (B)
+ return Any_BPy_Interface1D_from_Interface1D(*(A->getFEdge(*B)));
+ Py_RETURN_NONE;
}
PyDoc_STRVAR(CurvePoint_t2d_doc,
@@ -217,8 +220,8 @@ static PyGetSetDef BPy_CurvePoint_getseters[] = {
(char *)CurvePoint_first_svertex_doc, NULL},
{(char *)"second_svertex", (getter)CurvePoint_second_svertex_get, (setter)CurvePoint_second_svertex_set,
(char *)CurvePoint_second_svertex_doc, NULL},
- {(char *)"fedge", (getter)CurvePoint_fedge_get, NULL,
- CurvePoint_fedge_doc, NULL},
+ {(char *)"fedge", (getter)CurvePoint_fedge_get, NULL,
+ CurvePoint_fedge_doc, NULL},
{(char *)"t2d", (getter)CurvePoint_t2d_get, (setter)CurvePoint_t2d_set, (char *)CurvePoint_t2d_doc, NULL},
{NULL, NULL, NULL, NULL, NULL} /* Sentinel */
};
diff --git a/source/blender/freestyle/intern/python/Interface0D/BPy_SVertex.cpp b/source/blender/freestyle/intern/python/Interface0D/BPy_SVertex.cpp
index 6f47ce93ca8..39919b41423 100644
--- a/source/blender/freestyle/intern/python/Interface0D/BPy_SVertex.cpp
+++ b/source/blender/freestyle/intern/python/Interface0D/BPy_SVertex.cpp
@@ -342,13 +342,14 @@ PyDoc_STRVAR(SVertex_normals_doc,
static PyObject *SVertex_normals_get(BPy_SVertex *self, void *UNUSED(closure))
{
PyObject *py_normals;
- set< Vec3r > normals;
-
- py_normals = PyList_New(0);
- normals = self->sv->normals();
- for (set< Vec3r >::iterator set_iterator = normals.begin(); set_iterator != normals.end(); set_iterator++) {
- Vec3r v(*set_iterator);
- PyList_Append(py_normals, Vector_from_Vec3r(v));
+ set< Vec3r > normals = self->sv->normals();
+ set< Vec3r >::iterator it;
+ py_normals = PyList_New(normals.size());
+ unsigned int i = 0;
+
+ for (it = normals.begin(); it != normals.end(); it++) {
+ Vec3r v(*it);
+ PyList_SET_ITEM(py_normals, i++, Vector_from_Vec3r(v));
}
return py_normals;
}
@@ -386,7 +387,7 @@ PyDoc_STRVAR(SVertex_curvatures_doc,
"directions, i.e. the directions of the normal plane where the\n"
"curvature takes its maximum and minimum values, respectively; and Kr,\n"
"er and dKr are the radial curvature, radial direction, and the\n"
-"derivative of the radial curvature at this SVertex, repectively.\n"
+"derivative of the radial curvature at this SVertex, respectively.\n"
"\n"
":type: tuple");
@@ -399,13 +400,14 @@ static PyObject *SVertex_curvatures_get(BPy_SVertex *self, void *UNUSED(closure)
Vec3r e2(info->e2.x(), info->e2.y(), info->e2.z());
Vec3r er(info->er.x(), info->er.y(), info->er.z());
PyObject *retval = PyTuple_New(7);
- PyTuple_SET_ITEM(retval, 0, PyFloat_FromDouble(info->K1));
- PyTuple_SET_ITEM(retval, 2, Vector_from_Vec3r(e1));
- PyTuple_SET_ITEM(retval, 1, PyFloat_FromDouble(info->K2));
- PyTuple_SET_ITEM(retval, 3, Vector_from_Vec3r(e2));
- PyTuple_SET_ITEM(retval, 4, PyFloat_FromDouble(info->Kr));
- PyTuple_SET_ITEM(retval, 5, Vector_from_Vec3r(er));
- PyTuple_SET_ITEM(retval, 6, PyFloat_FromDouble(info->dKr));
+ PyTuple_SET_ITEMS(retval,
+ PyFloat_FromDouble(info->K1),
+ PyFloat_FromDouble(info->K2),
+ Vector_from_Vec3r(e1),
+ Vector_from_Vec3r(e2),
+ PyFloat_FromDouble(info->Kr),
+ Vector_from_Vec3r(er),
+ PyFloat_FromDouble(info->dKr));
return retval;
}
diff --git a/source/blender/freestyle/intern/python/Interface0D/BPy_ViewVertex.cpp b/source/blender/freestyle/intern/python/Interface0D/BPy_ViewVertex.cpp
index 5e2130ac8e7..f8d0b34d6a9 100644
--- a/source/blender/freestyle/intern/python/Interface0D/BPy_ViewVertex.cpp
+++ b/source/blender/freestyle/intern/python/Interface0D/BPy_ViewVertex.cpp
@@ -49,7 +49,7 @@ PyDoc_STRVAR(ViewVertex_doc,
"Thus, this class can be specialized into two classes, the\n"
":class:`TVertex` class and the :class:`NonTVertex` class.");
-static int ViewVertex_init(BPy_ViewVertex *self, PyObject *args, PyObject *kwds)
+static int ViewVertex_init(BPy_ViewVertex * /*self*/, PyObject * /*args*/, PyObject * /*kwds*/)
{
PyErr_SetString(PyExc_TypeError, "cannot instantiate abstract class");
return -1;
@@ -82,7 +82,7 @@ PyDoc_STRVAR(ViewVertex_edges_end_doc,
" :return: An orientedViewEdgeIterator pointing after the last ViewEdge.\n"
" :rtype: :class:`orientedViewEdgeIterator`");
-static PyObject *ViewVertex_edges_end(BPy_ViewVertex *self)
+static PyObject *ViewVertex_edges_end(BPy_ViewVertex * /*self*/)
{
#if 0
ViewVertexInternal::orientedViewEdgeIterator ove_it(self->vv->edgesEnd());
diff --git a/source/blender/freestyle/intern/python/Interface0D/CurvePoint/BPy_StrokeVertex.cpp b/source/blender/freestyle/intern/python/Interface0D/CurvePoint/BPy_StrokeVertex.cpp
index ae4fe0764b6..ba773d4f4cf 100644
--- a/source/blender/freestyle/intern/python/Interface0D/CurvePoint/BPy_StrokeVertex.cpp
+++ b/source/blender/freestyle/intern/python/Interface0D/CurvePoint/BPy_StrokeVertex.cpp
@@ -166,7 +166,7 @@ static int StrokeVertex_mathutils_check(BaseMathObject *bmo)
return 0;
}
-static int StrokeVertex_mathutils_get(BaseMathObject *bmo, int subtype)
+static int StrokeVertex_mathutils_get(BaseMathObject *bmo, int /*subtype*/)
{
BPy_StrokeVertex *self = (BPy_StrokeVertex *)bmo->cb_user;
bmo->data[0] = (float)self->sv->x();
@@ -174,7 +174,7 @@ static int StrokeVertex_mathutils_get(BaseMathObject *bmo, int subtype)
return 0;
}
-static int StrokeVertex_mathutils_set(BaseMathObject *bmo, int subtype)
+static int StrokeVertex_mathutils_set(BaseMathObject *bmo, int /*subtype*/)
{
BPy_StrokeVertex *self = (BPy_StrokeVertex *)bmo->cb_user;
self->sv->setX((real)bmo->data[0]);
@@ -182,7 +182,7 @@ static int StrokeVertex_mathutils_set(BaseMathObject *bmo, int subtype)
return 0;
}
-static int StrokeVertex_mathutils_get_index(BaseMathObject *bmo, int subtype, int index)
+static int StrokeVertex_mathutils_get_index(BaseMathObject *bmo, int /*subtype*/, int index)
{
BPy_StrokeVertex *self = (BPy_StrokeVertex *)bmo->cb_user;
switch (index) {
@@ -194,7 +194,7 @@ static int StrokeVertex_mathutils_get_index(BaseMathObject *bmo, int subtype, in
return 0;
}
-static int StrokeVertex_mathutils_set_index(BaseMathObject *bmo, int subtype, int index)
+static int StrokeVertex_mathutils_set_index(BaseMathObject *bmo, int /*subtype*/, int index)
{
BPy_StrokeVertex *self = (BPy_StrokeVertex *)bmo->cb_user;
switch (index) {
diff --git a/source/blender/freestyle/intern/python/Interface1D/BPy_FEdge.cpp b/source/blender/freestyle/intern/python/Interface1D/BPy_FEdge.cpp
index 7592508902b..4c9e0630d40 100644
--- a/source/blender/freestyle/intern/python/Interface1D/BPy_FEdge.cpp
+++ b/source/blender/freestyle/intern/python/Interface1D/BPy_FEdge.cpp
@@ -100,7 +100,7 @@ static int FEdge_init(BPy_FEdge *self, PyObject *args, PyObject *kwds)
/*----------------------FEdge sequence protocol ----------------------------*/
-static Py_ssize_t FEdge_sq_length(BPy_FEdge *self)
+static Py_ssize_t FEdge_sq_length(BPy_FEdge * /*self*/)
{
return 2;
}
diff --git a/source/blender/freestyle/intern/python/Interface1D/FEdge/BPy_FEdgeSmooth.cpp b/source/blender/freestyle/intern/python/Interface1D/FEdge/BPy_FEdgeSmooth.cpp
index a2079c7d685..cf893ad9481 100644
--- a/source/blender/freestyle/intern/python/Interface1D/FEdge/BPy_FEdgeSmooth.cpp
+++ b/source/blender/freestyle/intern/python/Interface1D/FEdge/BPy_FEdgeSmooth.cpp
@@ -99,7 +99,7 @@ static int FEdgeSmooth_mathutils_check(BaseMathObject *bmo)
return 0;
}
-static int FEdgeSmooth_mathutils_get(BaseMathObject *bmo, int subtype)
+static int FEdgeSmooth_mathutils_get(BaseMathObject *bmo, int /*subtype*/)
{
BPy_FEdgeSmooth *self = (BPy_FEdgeSmooth *)bmo->cb_user;
Vec3r p(self->fes->normal());
@@ -109,7 +109,7 @@ static int FEdgeSmooth_mathutils_get(BaseMathObject *bmo, int subtype)
return 0;
}
-static int FEdgeSmooth_mathutils_set(BaseMathObject *bmo, int subtype)
+static int FEdgeSmooth_mathutils_set(BaseMathObject *bmo, int /*subtype*/)
{
BPy_FEdgeSmooth *self = (BPy_FEdgeSmooth *)bmo->cb_user;
Vec3r p(bmo->data[0], bmo->data[1], bmo->data[2]);
@@ -117,7 +117,7 @@ static int FEdgeSmooth_mathutils_set(BaseMathObject *bmo, int subtype)
return 0;
}
-static int FEdgeSmooth_mathutils_get_index(BaseMathObject *bmo, int subtype, int index)
+static int FEdgeSmooth_mathutils_get_index(BaseMathObject *bmo, int /*subtype*/, int index)
{
BPy_FEdgeSmooth *self = (BPy_FEdgeSmooth *)bmo->cb_user;
Vec3r p(self->fes->normal());
@@ -125,7 +125,7 @@ static int FEdgeSmooth_mathutils_get_index(BaseMathObject *bmo, int subtype, int
return 0;
}
-static int FEdgeSmooth_mathutils_set_index(BaseMathObject *bmo, int subtype, int index)
+static int FEdgeSmooth_mathutils_set_index(BaseMathObject *bmo, int /*subtype*/, int index)
{
BPy_FEdgeSmooth *self = (BPy_FEdgeSmooth *)bmo->cb_user;
Vec3r p(self->fes->normal());
diff --git a/source/blender/freestyle/intern/python/Iterator/BPy_AdjacencyIterator.cpp b/source/blender/freestyle/intern/python/Iterator/BPy_AdjacencyIterator.cpp
index 9329bd40c76..edc49eb8004 100644
--- a/source/blender/freestyle/intern/python/Iterator/BPy_AdjacencyIterator.cpp
+++ b/source/blender/freestyle/intern/python/Iterator/BPy_AdjacencyIterator.cpp
@@ -117,7 +117,7 @@ static PyObject *AdjacencyIterator_iternext(BPy_AdjacencyIterator *self)
self->at_start = false;
else {
self->a_it->increment();
- if (self->a_it->isEnd()){
+ if (self->a_it->isEnd()) {
PyErr_SetNone(PyExc_StopIteration);
return NULL;
}
diff --git a/source/blender/freestyle/intern/python/Iterator/BPy_Interface0DIterator.cpp b/source/blender/freestyle/intern/python/Iterator/BPy_Interface0DIterator.cpp
index c972db1e680..7419f0ed127 100644
--- a/source/blender/freestyle/intern/python/Iterator/BPy_Interface0DIterator.cpp
+++ b/source/blender/freestyle/intern/python/Iterator/BPy_Interface0DIterator.cpp
@@ -120,14 +120,20 @@ static PyObject *Interface0DIterator_iternext(BPy_Interface0DIterator *self)
self->if0D_it->decrement();
}
else {
- if (self->if0D_it->atLast() || self->if0D_it->isEnd()) {
+ if (self->if0D_it->isEnd()) {
PyErr_SetNone(PyExc_StopIteration);
return NULL;
}
- if (self->at_start)
+ else if (self->at_start) {
self->at_start = false;
- else
+ }
+ else if (self->if0D_it->atLast()) {
+ PyErr_SetNone(PyExc_StopIteration);
+ return NULL;
+ }
+ else {
self->if0D_it->increment();
+ }
}
Interface0D *if0D = self->if0D_it->operator->();
return Any_BPy_Interface0D_from_Interface0D(*if0D);
diff --git a/source/blender/freestyle/intern/python/Iterator/BPy_StrokeVertexIterator.cpp b/source/blender/freestyle/intern/python/Iterator/BPy_StrokeVertexIterator.cpp
index 18d1b37eb3b..e35076ec7fe 100644
--- a/source/blender/freestyle/intern/python/Iterator/BPy_StrokeVertexIterator.cpp
+++ b/source/blender/freestyle/intern/python/Iterator/BPy_StrokeVertexIterator.cpp
@@ -115,19 +115,25 @@ static PyObject *StrokeVertexIterator_iternext(BPy_StrokeVertexIterator *self)
self->sv_it->decrement();
}
else {
- /* if sv_it.isEnd() is true, the iterator can't be incremented. if sv_it.isLast() is true,
- * the iterator is currently pointing to the final valid argument. Incrementing it further would
- * give a python object that can't be dereferenced. */
- if (self->sv_it->atLast() || self->sv_it->isEnd()) {
+ /* If sv_it.isEnd() is true, the iterator can't be incremented. */
+ if (self->sv_it->isEnd()) {
PyErr_SetNone(PyExc_StopIteration);
return NULL;
}
- /* if at the start of the iterator, only return the object
- * and don't increment, to keep for-loops in sync */
- if (self->at_start)
+ /* If at the start of the iterator, only return the object
+ * and don't increment, to keep for-loops in sync */
+ else if (self->at_start) {
self->at_start = false;
- else
+ }
+ /* If sv_it.atLast() is true, the iterator is currently pointing to the final valid element.
+ * Incrementing it further would lead to a state that the iterator can't be dereferenced. */
+ else if (self->sv_it->atLast()) {
+ PyErr_SetNone(PyExc_StopIteration);
+ return NULL;
+ }
+ else {
self->sv_it->increment();
+ }
}
StrokeVertex *sv = self->sv_it->operator->();
return BPy_StrokeVertex_from_StrokeVertex(*sv);
@@ -149,9 +155,9 @@ static PyObject *StrokeVertexIterator_incremented(BPy_StrokeVertexIterator *self
PyErr_SetString(PyExc_RuntimeError, "cannot increment any more");
return NULL;
}
- StrokeInternal::StrokeVertexIterator *copy = new StrokeInternal::StrokeVertexIterator(*self->sv_it);
- copy->increment();
- return BPy_StrokeVertexIterator_from_StrokeVertexIterator(*copy, self->reversed);
+ StrokeInternal::StrokeVertexIterator copy(*self->sv_it);
+ copy.increment();
+ return BPy_StrokeVertexIterator_from_StrokeVertexIterator(copy, self->reversed);
}
PyDoc_STRVAR(StrokeVertexIterator_decremented_doc,
@@ -168,10 +174,9 @@ static PyObject *StrokeVertexIterator_decremented(BPy_StrokeVertexIterator *self
PyErr_SetString(PyExc_RuntimeError, "cannot decrement any more");
return NULL;
}
-
- StrokeInternal::StrokeVertexIterator *copy = new StrokeInternal::StrokeVertexIterator(*self->sv_it);
- copy->decrement();
- return BPy_StrokeVertexIterator_from_StrokeVertexIterator(*copy, self->reversed);
+ StrokeInternal::StrokeVertexIterator copy(*self->sv_it);
+ copy.decrement();
+ return BPy_StrokeVertexIterator_from_StrokeVertexIterator(copy, self->reversed);
}
PyDoc_STRVAR(StrokeVertexIterator_reversed_doc,
@@ -185,8 +190,7 @@ PyDoc_STRVAR(StrokeVertexIterator_reversed_doc,
static PyObject *StrokeVertexIterator_reversed(BPy_StrokeVertexIterator *self)
{
- StrokeInternal::StrokeVertexIterator *copy = new StrokeInternal::StrokeVertexIterator(*self->sv_it);
- return BPy_StrokeVertexIterator_from_StrokeVertexIterator(*copy, !self->reversed);
+ return BPy_StrokeVertexIterator_from_StrokeVertexIterator(*self->sv_it, !self->reversed);
}
static PyMethodDef BPy_StrokeVertexIterator_methods[] = {
diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_BlenderTextureShader.h b/source/blender/freestyle/intern/python/StrokeShader/BPy_BlenderTextureShader.h
index 46294c07b66..c4fead6a4e4 100644
--- a/source/blender/freestyle/intern/python/StrokeShader/BPy_BlenderTextureShader.h
+++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_BlenderTextureShader.h
@@ -31,7 +31,6 @@
extern "C" {
#endif
-struct MTex;
///////////////////////////////////////////////////////////////////////////////////////////
diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_ColorVariationPatternShader.cpp b/source/blender/freestyle/intern/python/StrokeShader/BPy_ColorVariationPatternShader.cpp
deleted file mode 100644
index 173e00b0ed8..00000000000
--- a/source/blender/freestyle/intern/python/StrokeShader/BPy_ColorVariationPatternShader.cpp
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
- * ***** BEGIN GPL LICENSE BLOCK *****
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-
-/** \file source/blender/freestyle/intern/python/StrokeShader/BPy_ColorVariationPatternShader.cpp
- * \ingroup freestyle
- */
-
-#include "BPy_ColorVariationPatternShader.h"
-
-#include "../../stroke/BasicStrokeShaders.h"
-#include "../BPy_Convert.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-///////////////////////////////////////////////////////////////////////////////////////////
-
-//------------------------INSTANCE METHODS ----------------------------------
-
-static char ColorVariationPatternShader___doc__[] =
-"Class hierarchy: :class:`freestyle.types.StrokeShader` > :class:`ColorVariationPatternShader`\n"
-"\n"
-"[Color shader]\n"
-"\n"
-".. method:: __init__(pattern_name, stretch=True)\n"
-"\n"
-" Builds a ColorVariationPatternShader object.\n"
-"\n"
-" :arg pattern_name: The file name of the texture file to use as\n"
-" pattern.\n"
-" :type pattern_name: str\n"
-" :arg stretch: Tells whether the texture must be strecthed or\n"
-" repeted to fit the stroke.\n"
-" :type stretch: bool\n"
-"\n"
-".. method:: shade(stroke)\n"
-"\n"
-" Applies a pattern to vary the original color. The new color is the\n"
-" result of the multiplication of the pattern and the original color.\n"
-"\n"
-" :arg stroke: A Stroke object.\n"
-" :type stroke: :class:`freestyle.types.Stroke`\n";
-
-static int ColorVariationPatternShader___init__(BPy_ColorVariationPatternShader *self, PyObject *args, PyObject *kwds)
-{
- static const char *kwlist[] = {"pattern_name", "stretch", NULL};
- const char *s;
- PyObject *obj = 0;
-
- if (!PyArg_ParseTupleAndKeywords(args, kwds, "s|O!", (char **)kwlist, &s, &PyBool_Type, &obj))
- return -1;
- bool b = (!obj) ? true : bool_from_PyBool(obj);
- self->py_ss.ss = new StrokeShaders::ColorVariationPatternShader(s, b);
- return 0;
-}
-
-/*-----------------------BPy_ColorVariationPatternShader type definition ------------------------------*/
-
-PyTypeObject ColorVariationPatternShader_Type = {
- PyVarObject_HEAD_INIT(NULL, 0)
- "ColorVariationPatternShader", /* tp_name */
- sizeof(BPy_ColorVariationPatternShader), /* tp_basicsize */
- 0, /* tp_itemsize */
- 0, /* tp_dealloc */
- 0, /* tp_print */
- 0, /* tp_getattr */
- 0, /* tp_setattr */
- 0, /* tp_reserved */
- 0, /* tp_repr */
- 0, /* tp_as_number */
- 0, /* tp_as_sequence */
- 0, /* tp_as_mapping */
- 0, /* tp_hash */
- 0, /* tp_call */
- 0, /* tp_str */
- 0, /* tp_getattro */
- 0, /* tp_setattro */
- 0, /* tp_as_buffer */
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
- ColorVariationPatternShader___doc__, /* tp_doc */
- 0, /* tp_traverse */
- 0, /* tp_clear */
- 0, /* tp_richcompare */
- 0, /* tp_weaklistoffset */
- 0, /* tp_iter */
- 0, /* tp_iternext */
- 0, /* tp_methods */
- 0, /* tp_members */
- 0, /* tp_getset */
- &StrokeShader_Type, /* tp_base */
- 0, /* tp_dict */
- 0, /* tp_descr_get */
- 0, /* tp_descr_set */
- 0, /* tp_dictoffset */
- (initproc)ColorVariationPatternShader___init__, /* tp_init */
- 0, /* tp_alloc */
- 0, /* tp_new */
-};
-
-///////////////////////////////////////////////////////////////////////////////////////////
-
-#ifdef __cplusplus
-}
-#endif
diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_ColorVariationPatternShader.h b/source/blender/freestyle/intern/python/StrokeShader/BPy_ColorVariationPatternShader.h
deleted file mode 100644
index af5cf17caff..00000000000
--- a/source/blender/freestyle/intern/python/StrokeShader/BPy_ColorVariationPatternShader.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * ***** BEGIN GPL LICENSE BLOCK *****
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-
-/** \file source/blender/freestyle/intern/python/StrokeShader/BPy_ColorVariationPatternShader.h
- * \ingroup freestyle
- */
-
-#ifndef __FREESTYLE_PYTHON_COLORVARIATIONPATTERNSHADER_H__
-#define __FREESTYLE_PYTHON_COLORVARIATIONPATTERNSHADER_H__
-
-#include "../BPy_StrokeShader.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-///////////////////////////////////////////////////////////////////////////////////////////
-
-extern PyTypeObject ColorVariationPatternShader_Type;
-
-#define BPy_ColorVariationPatternShader_Check(v) \
- (PyObject_IsInstance((PyObject *)v, (PyObject *)&ColorVariationPatternShader_Type))
-
-/*---------------------------Python BPy_ColorVariationPatternShader structure definition----------*/
-typedef struct {
- BPy_StrokeShader py_ss;
-} BPy_ColorVariationPatternShader;
-
-
-///////////////////////////////////////////////////////////////////////////////////////////
-
-#ifdef __cplusplus
-}
-#endif
-
-
-#endif /* __FREESTYLE_PYTHON_COLORVARIATIONPATTERNSHADER_H__ */
diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_StrokeTextureShader.cpp b/source/blender/freestyle/intern/python/StrokeShader/BPy_StrokeTextureShader.cpp
deleted file mode 100644
index db2807addc4..00000000000
--- a/source/blender/freestyle/intern/python/StrokeShader/BPy_StrokeTextureShader.cpp
+++ /dev/null
@@ -1,143 +0,0 @@
-/*
- * ***** BEGIN GPL LICENSE BLOCK *****
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-
-/** \file source/blender/freestyle/intern/python/StrokeShader/BPy_StrokeTextureShader.cpp
- * \ingroup freestyle
- */
-
-#include "BPy_StrokeTextureShader.h"
-
-#include "../../stroke/BasicStrokeShaders.h"
-#include "../BPy_Convert.h"
-#include "../BPy_MediumType.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-///////////////////////////////////////////////////////////////////////////////////////////
-
-//------------------------INSTANCE METHODS ----------------------------------
-
-static char StrokeTextureShader___doc__[] =
-"Class hierarchy: :class:`freestyle.types.StrokeShader` > :class:`StrokeTextureShader`\n"
-"\n"
-"[Texture shader]\n"
-"\n"
-".. method:: __init__(texture_file, medium_type=Stroke.OPAQUE_MEDIUM, tips=False)\n"
-"\n"
-" Builds a StrokeTextureShader object.\n"
-"\n"
-" :arg texture_file: \n"
-" :type texture_file: str\n"
-" :arg medium_type: The medium type and therefore, the blending mode\n"
-" that must be used for the rendering of this stroke.\n"
-" :type medium_type: :class:`freestyle.types.MediumType`\n"
-" :arg tips: Tells whether the texture includes tips or not. If it\n"
-" is the case, the texture image must respect the following format.\n"
-" :type tips: bool\n"
-"\n"
-" The format of a texture image including tips::\n"
-"\n"
-" ___________\n"
-" | |\n"
-" | A |\n"
-" |___________|\n"
-" | | |\n"
-" | B | C |\n"
-" |_____|_____|\n"
-"\n"
-" * A : The stroke's corpus texture.\n"
-" * B : The stroke's left extremity texture.\n"
-" * C : The stroke's right extremity texture.\n"
-"\n"
-".. method:: shade(stroke)\n"
-"\n"
-" Assigns a texture and a blending mode to the stroke in order to\n"
-" simulate its marks system.\n"
-"\n"
-" :arg stroke: A Stroke object.\n"
-" :type stroke: :class:`freestyle.types.Stroke`\n";
-
-static int StrokeTextureShader___init__(BPy_StrokeTextureShader *self, PyObject *args, PyObject *kwds)
-{
- static const char *kwlist[] = {"texture_file", "medium_type", "tips", NULL};
- const char *s1;
- PyObject *obj2 = 0, *obj3 = 0;
-
- if (!PyArg_ParseTupleAndKeywords(args, kwds, "s|O!O!", (char **)kwlist,
- &s1, &MediumType_Type, &obj2, &PyBool_Type, &obj3))
- {
- return -1;
- }
- Stroke::MediumType mt = (!obj2) ? Stroke::OPAQUE_MEDIUM : MediumType_from_BPy_MediumType(obj2);
- bool b = (!obj3) ? false : bool_from_PyBool(obj3);
- self->py_ss.ss = new StrokeShaders::StrokeTextureShader(s1, mt, b);
- return 0;
-}
-
-/*-----------------------BPy_StrokeTextureShader type definition ------------------------------*/
-
-PyTypeObject StrokeTextureShader_Type = {
- PyVarObject_HEAD_INIT(NULL, 0)
- "StrokeTextureShader", /* tp_name */
- sizeof(BPy_StrokeTextureShader), /* tp_basicsize */
- 0, /* tp_itemsize */
- 0, /* tp_dealloc */
- 0, /* tp_print */
- 0, /* tp_getattr */
- 0, /* tp_setattr */
- 0, /* tp_reserved */
- 0, /* tp_repr */
- 0, /* tp_as_number */
- 0, /* tp_as_sequence */
- 0, /* tp_as_mapping */
- 0, /* tp_hash */
- 0, /* tp_call */
- 0, /* tp_str */
- 0, /* tp_getattro */
- 0, /* tp_setattro */
- 0, /* tp_as_buffer */
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
- StrokeTextureShader___doc__, /* tp_doc */
- 0, /* tp_traverse */
- 0, /* tp_clear */
- 0, /* tp_richcompare */
- 0, /* tp_weaklistoffset */
- 0, /* tp_iter */
- 0, /* tp_iternext */
- 0, /* tp_methods */
- 0, /* tp_members */
- 0, /* tp_getset */
- &StrokeShader_Type, /* tp_base */
- 0, /* tp_dict */
- 0, /* tp_descr_get */
- 0, /* tp_descr_set */
- 0, /* tp_dictoffset */
- (initproc)StrokeTextureShader___init__, /* tp_init */
- 0, /* tp_alloc */
- 0, /* tp_new */
-};
-
-///////////////////////////////////////////////////////////////////////////////////////////
-
-#ifdef __cplusplus
-}
-#endif
diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_StrokeTextureShader.h b/source/blender/freestyle/intern/python/StrokeShader/BPy_StrokeTextureShader.h
deleted file mode 100644
index d025e8b7c2d..00000000000
--- a/source/blender/freestyle/intern/python/StrokeShader/BPy_StrokeTextureShader.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * ***** BEGIN GPL LICENSE BLOCK *****
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-
-/** \file source/blender/freestyle/intern/python/StrokeShader/BPy_StrokeTextureShader.h
- * \ingroup freestyle
- */
-
-#ifndef __FREESTYLE_PYTHON_STROKETEXTURESHADER_H__
-#define __FREESTYLE_PYTHON_STROKETEXTURESHADER_H__
-
-#include "../BPy_StrokeShader.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-///////////////////////////////////////////////////////////////////////////////////////////
-
-extern PyTypeObject StrokeTextureShader_Type;
-
-#define BPy_StrokeTextureShader_Check(v) (PyObject_IsInstance((PyObject *)v, (PyObject *)&StrokeTextureShader_Type))
-
-/*---------------------------Python BPy_StrokeTextureShader structure definition----------*/
-typedef struct {
- BPy_StrokeShader py_ss;
-} BPy_StrokeTextureShader;
-
-
-///////////////////////////////////////////////////////////////////////////////////////////
-
-#ifdef __cplusplus
-}
-#endif
-
-
-#endif /* __FREESTYLE_PYTHON_STROKETEXTURESHADER_H__ */
diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_TextureAssignerShader.cpp b/source/blender/freestyle/intern/python/StrokeShader/BPy_TextureAssignerShader.cpp
deleted file mode 100644
index 78a07cb6c38..00000000000
--- a/source/blender/freestyle/intern/python/StrokeShader/BPy_TextureAssignerShader.cpp
+++ /dev/null
@@ -1,130 +0,0 @@
-/*
- * ***** BEGIN GPL LICENSE BLOCK *****
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-
-/** \file source/blender/freestyle/intern/python/StrokeShader/BPy_TextureAssignerShader.cpp
- * \ingroup freestyle
- */
-
-#include "BPy_TextureAssignerShader.h"
-
-#include "../../stroke/BasicStrokeShaders.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-///////////////////////////////////////////////////////////////////////////////////////////
-
-//------------------------INSTANCE METHODS ----------------------------------
-
-static char TextureAssignerShader___doc__[] =
-"Class hierarchy: :class:`freestyle.types.StrokeShader` > :class:`TextureAssignerShader`\n"
-"\n"
-"[Texture shader]\n"
-"\n"
-".. method:: __init__(preset)\n"
-"\n"
-" Builds a TextureAssignerShader object.\n"
-"\n"
-" :arg preset: The preset number to use.\n"
-" :type preset: int\n"
-"\n"
-".. method:: shade(stroke)\n"
-"\n"
-" Assigns a texture to the stroke in order to simulate its marks\n"
-" system. This shader takes as input an integer value telling which\n"
-" texture and blending mode to use among a set of predefined\n"
-" textures. Here are the different presets:\n"
-"\n"
-" * 0: `/brushes/charcoalAlpha.bmp`, `Stroke.HUMID_MEDIUM`\n"
-" * 1: `/brushes/washbrushAlpha.bmp`, `Stroke.HUMID_MEDIUM`\n"
-" * 2: `/brushes/oil.bmp`, `Stroke.HUMID_MEDIUM`\n"
-" * 3: `/brushes/oilnoblend.bmp`, `Stroke.HUMID_MEDIUM`\n"
-" * 4: `/brushes/charcoalAlpha.bmp`, `Stroke.DRY_MEDIUM`\n"
-" * 5: `/brushes/washbrushAlpha.bmp`, `Stroke.DRY_MEDIUM`\n"
-" * 6: `/brushes/opaqueDryBrushAlpha.bmp`, `Stroke.OPAQUE_MEDIUM`\n"
-" * 7: `/brushes/opaqueBrushAlpha.bmp`, `Stroke.OPAQUE_MEDIUM`\n"
-"\n"
-" Any other value will lead to the following preset:\n"
-"\n"
-" * Default: `/brushes/smoothAlpha.bmp`, `Stroke.OPAQUE_MEDIUM`\n"
-"\n"
-" :arg stroke: A Stroke object.\n"
-" :type stroke: :class:`freestyle.types.Stroke`\n";
-
-static int TextureAssignerShader___init__(BPy_TextureAssignerShader *self, PyObject *args, PyObject *kwds)
-{
- static const char *kwlist[] = {"preset", NULL};
- int i;
-
- if (!PyArg_ParseTupleAndKeywords(args, kwds, "i", (char **)kwlist, &i))
- return -1;
- self->py_ss.ss = new StrokeShaders::TextureAssignerShader(i);
- return 0;
-}
-
-/*-----------------------BPy_TextureAssignerShader type definition ------------------------------*/
-
-PyTypeObject TextureAssignerShader_Type = {
- PyVarObject_HEAD_INIT(NULL, 0)
- "TextureAssignerShader", /* tp_name */
- sizeof(BPy_TextureAssignerShader), /* tp_basicsize */
- 0, /* tp_itemsize */
- 0, /* tp_dealloc */
- 0, /* tp_print */
- 0, /* tp_getattr */
- 0, /* tp_setattr */
- 0, /* tp_reserved */
- 0, /* tp_repr */
- 0, /* tp_as_number */
- 0, /* tp_as_sequence */
- 0, /* tp_as_mapping */
- 0, /* tp_hash */
- 0, /* tp_call */
- 0, /* tp_str */
- 0, /* tp_getattro */
- 0, /* tp_setattro */
- 0, /* tp_as_buffer */
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
- TextureAssignerShader___doc__, /* tp_doc */
- 0, /* tp_traverse */
- 0, /* tp_clear */
- 0, /* tp_richcompare */
- 0, /* tp_weaklistoffset */
- 0, /* tp_iter */
- 0, /* tp_iternext */
- 0, /* tp_methods */
- 0, /* tp_members */
- 0, /* tp_getset */
- &StrokeShader_Type, /* tp_base */
- 0, /* tp_dict */
- 0, /* tp_descr_get */
- 0, /* tp_descr_set */
- 0, /* tp_dictoffset */
- (initproc)TextureAssignerShader___init__, /* tp_init */
- 0, /* tp_alloc */
- 0, /* tp_new */
-};
-
-///////////////////////////////////////////////////////////////////////////////////////////
-
-#ifdef __cplusplus
-}
-#endif
diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_TextureAssignerShader.h b/source/blender/freestyle/intern/python/StrokeShader/BPy_TextureAssignerShader.h
deleted file mode 100644
index 046f785dc57..00000000000
--- a/source/blender/freestyle/intern/python/StrokeShader/BPy_TextureAssignerShader.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * ***** BEGIN GPL LICENSE BLOCK *****
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-
-/** \file source/blender/freestyle/intern/python/StrokeShader/BPy_TextureAssignerShader.h
- * \ingroup freestyle
- */
-
-#ifndef __FREESTYLE_PYTHON_TEXTUREASSIGNERSHADER_H__
-#define __FREESTYLE_PYTHON_TEXTUREASSIGNERSHADER_H__
-
-#include "../BPy_StrokeShader.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-///////////////////////////////////////////////////////////////////////////////////////////
-
-extern PyTypeObject TextureAssignerShader_Type;
-
-#define BPy_TextureAssignerShader_Check(v) (PyObject_IsInstance((PyObject *)v, (PyObject *)&TextureAssignerShader_Type))
-
-/*---------------------------Python BPy_TextureAssignerShader structure definition----------*/
-typedef struct {
- BPy_StrokeShader py_ss;
-} BPy_TextureAssignerShader;
-
-
-///////////////////////////////////////////////////////////////////////////////////////////
-
-#ifdef __cplusplus
-}
-#endif
-
-
-#endif /* __FREESTYLE_PYTHON_TEXTUREASSIGNERSHADER_H__ */
diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_ThicknessVariationPatternShader.cpp b/source/blender/freestyle/intern/python/StrokeShader/BPy_ThicknessVariationPatternShader.cpp
deleted file mode 100644
index 3196065cd34..00000000000
--- a/source/blender/freestyle/intern/python/StrokeShader/BPy_ThicknessVariationPatternShader.cpp
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
- * ***** BEGIN GPL LICENSE BLOCK *****
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-
-/** \file source/blender/freestyle/intern/python/StrokeShader/BPy_ThicknessVariationPatternShader.cpp
- * \ingroup freestyle
- */
-
-#include "BPy_ThicknessVariationPatternShader.h"
-
-#include "../../stroke/BasicStrokeShaders.h"
-#include "../BPy_Convert.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-///////////////////////////////////////////////////////////////////////////////////////////
-
-//------------------------INSTANCE METHODS ----------------------------------
-
-static char ThicknessVariationPatternShader___doc__[] =
-"Class hierarchy: :class:`freestyle.types.StrokeShader` > :class:`ThicknessVariationPatternShader`\n"
-"\n"
-"[Thickness shader]\n"
-"\n"
-".. method:: __init__(pattern_name, thickness_min=1.0, thickness_max=5.0, stretch=True)\n"
-"\n"
-" Builds a ThicknessVariationPatternShader object.\n"
-"\n"
-" :arg pattern_name: The texture file name.\n"
-" :type pattern_name: str\n"
-" :arg thickness_min: The minimum thickness we don't want to exceed.\n"
-" :type thickness_min: float\n"
-" :arg thickness_max: The maximum thickness we don't want to exceed.\n"
-" :type thickness_max: float\n"
-" :arg stretch: Tells whether the pattern texture must be stretched\n"
-" or repeated to fit the stroke.\n"
-" :type stretch: bool\n"
-"\n"
-".. method:: shade(stroke)\n"
-"\n"
-" Applies a pattern (texture) to vary thickness. The new thicknesses\n"
-" are the result of the multiplication of the pattern and the\n"
-" original thickness.\n"
-"\n"
-" :arg stroke: A Stroke object.\n"
-" :type stroke: :class:`freestyle.types.Stroke`\n";
-
-static int ThicknessVariationPatternShader___init__(BPy_ThicknessVariationPatternShader *self,
- PyObject *args, PyObject *kwds)
-{
- static const char *kwlist[] = {"pattern_name", "thickness_min", "thickness_max", "stretch", NULL};
- const char *s1;
- float f2 = 1.0, f3 = 5.0;
- PyObject *obj4 = 0;
-
- if (!PyArg_ParseTupleAndKeywords(args, kwds, "s|ffO!", (char **)kwlist, &s1, &f2, &f3, &PyBool_Type, &obj4))
- return -1;
- bool b = (!obj4) ? true : bool_from_PyBool(obj4);
- self->py_ss.ss = new StrokeShaders::ThicknessVariationPatternShader(s1, f2, f3, b);
- return 0;
-}
-
-/*-----------------------BPy_ThicknessVariationPatternShader type definition ------------------------------*/
-
-PyTypeObject ThicknessVariationPatternShader_Type = {
- PyVarObject_HEAD_INIT(NULL, 0)
- "ThicknessVariationPatternShader", /* tp_name */
- sizeof(BPy_ThicknessVariationPatternShader), /* tp_basicsize */
- 0, /* tp_itemsize */
- 0, /* tp_dealloc */
- 0, /* tp_print */
- 0, /* tp_getattr */
- 0, /* tp_setattr */
- 0, /* tp_reserved */
- 0, /* tp_repr */
- 0, /* tp_as_number */
- 0, /* tp_as_sequence */
- 0, /* tp_as_mapping */
- 0, /* tp_hash */
- 0, /* tp_call */
- 0, /* tp_str */
- 0, /* tp_getattro */
- 0, /* tp_setattro */
- 0, /* tp_as_buffer */
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
- ThicknessVariationPatternShader___doc__, /* tp_doc */
- 0, /* tp_traverse */
- 0, /* tp_clear */
- 0, /* tp_richcompare */
- 0, /* tp_weaklistoffset */
- 0, /* tp_iter */
- 0, /* tp_iternext */
- 0, /* tp_methods */
- 0, /* tp_members */
- 0, /* tp_getset */
- &StrokeShader_Type, /* tp_base */
- 0, /* tp_dict */
- 0, /* tp_descr_get */
- 0, /* tp_descr_set */
- 0, /* tp_dictoffset */
- (initproc)ThicknessVariationPatternShader___init__, /* tp_init */
- 0, /* tp_alloc */
- 0, /* tp_new */
-};
-
-///////////////////////////////////////////////////////////////////////////////////////////
-
-#ifdef __cplusplus
-}
-#endif
diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_ThicknessVariationPatternShader.h b/source/blender/freestyle/intern/python/StrokeShader/BPy_ThicknessVariationPatternShader.h
deleted file mode 100644
index 604e875f815..00000000000
--- a/source/blender/freestyle/intern/python/StrokeShader/BPy_ThicknessVariationPatternShader.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * ***** BEGIN GPL LICENSE BLOCK *****
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-
-/** \file source/blender/freestyle/intern/python/StrokeShader/BPy_ThicknessVariationPatternShader.h
- * \ingroup freestyle
- */
-
-#ifndef __FREESTYLE_PYTHON_THICKNESSVARIATIONPATTERNSHADER_H__
-#define __FREESTYLE_PYTHON_THICKNESSVARIATIONPATTERNSHADER_H__
-
-#include "../BPy_StrokeShader.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-///////////////////////////////////////////////////////////////////////////////////////////
-
-extern PyTypeObject ThicknessVariationPatternShader_Type;
-
-#define BPy_ThicknessVariationPatternShader_Check(v) \
- (PyObject_IsInstance((PyObject *)v, (PyObject *)&ThicknessVariationPatternShader_Type))
-
-/*---------------------------Python BPy_ThicknessVariationPatternShader structure definition----------*/
-typedef struct {
- BPy_StrokeShader py_ss;
-} BPy_ThicknessVariationPatternShader;
-
-
-///////////////////////////////////////////////////////////////////////////////////////////
-
-#ifdef __cplusplus
-}
-#endif
-
-
-#endif /* __FREESTYLE_PYTHON_THICKNESSVARIATIONPATTERNSHADER_H__ */
diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_fstreamShader.cpp b/source/blender/freestyle/intern/python/StrokeShader/BPy_fstreamShader.cpp
deleted file mode 100644
index b838cae9817..00000000000
--- a/source/blender/freestyle/intern/python/StrokeShader/BPy_fstreamShader.cpp
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * ***** BEGIN GPL LICENSE BLOCK *****
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-
-/** \file source/blender/freestyle/intern/python/StrokeShader/BPy_fstreamShader.cpp
- * \ingroup freestyle
- */
-
-#include "BPy_fstreamShader.h"
-
-#include "../../stroke/AdvancedStrokeShaders.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-///////////////////////////////////////////////////////////////////////////////////////////
-
-//------------------------INSTANCE METHODS ----------------------------------
-
-static char fstreamShader___doc__[] =
-"Class hierarchy: :class:`freestyle.types.StrokeShader` > :class:`fstreamShader`\n"
-"\n"
-"[Output shader]\n"
-"\n"
-".. method:: __init__(filename)\n"
-"\n"
-" Builds a fstreamShader object.\n"
-"\n"
-" :arg filename: The output file name.\n"
-" :type filename: str\n"
-"\n"
-".. method:: shade(stroke)\n"
-"\n"
-" Streams the Stroke in a file.\n"
-"\n"
-" :arg stroke: A Stroke object.\n"
-" :type stroke: :class:`freestyle.types.Stroke`\n";
-
-static int fstreamShader___init__(BPy_fstreamShader *self, PyObject *args, PyObject *kwds)
-{
- static const char *kwlist[] = {"filename", NULL};
- const char *s;
-
- if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", (char **)kwlist, &s))
- return -1;
- self->py_ss.ss = new StrokeShaders::fstreamShader(s);
- return 0;
-}
-
-/*-----------------------BPy_fstreamShader type definition ------------------------------*/
-
-PyTypeObject fstreamShader_Type = {
- PyVarObject_HEAD_INIT(NULL, 0)
- "fstreamShader", /* tp_name */
- sizeof(BPy_fstreamShader), /* tp_basicsize */
- 0, /* tp_itemsize */
- 0, /* tp_dealloc */
- 0, /* tp_print */
- 0, /* tp_getattr */
- 0, /* tp_setattr */
- 0, /* tp_reserved */
- 0, /* tp_repr */
- 0, /* tp_as_number */
- 0, /* tp_as_sequence */
- 0, /* tp_as_mapping */
- 0, /* tp_hash */
- 0, /* tp_call */
- 0, /* tp_str */
- 0, /* tp_getattro */
- 0, /* tp_setattro */
- 0, /* tp_as_buffer */
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
- fstreamShader___doc__, /* tp_doc */
- 0, /* tp_traverse */
- 0, /* tp_clear */
- 0, /* tp_richcompare */
- 0, /* tp_weaklistoffset */
- 0, /* tp_iter */
- 0, /* tp_iternext */
- 0, /* tp_methods */
- 0, /* tp_members */
- 0, /* tp_getset */
- &StrokeShader_Type, /* tp_base */
- 0, /* tp_dict */
- 0, /* tp_descr_get */
- 0, /* tp_descr_set */
- 0, /* tp_dictoffset */
- (initproc)fstreamShader___init__, /* tp_init */
- 0, /* tp_alloc */
- 0, /* tp_new */
-};
-
-///////////////////////////////////////////////////////////////////////////////////////////
-
-#ifdef __cplusplus
-}
-#endif
diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_fstreamShader.h b/source/blender/freestyle/intern/python/StrokeShader/BPy_fstreamShader.h
deleted file mode 100644
index 9f2371a3756..00000000000
--- a/source/blender/freestyle/intern/python/StrokeShader/BPy_fstreamShader.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * ***** BEGIN GPL LICENSE BLOCK *****
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-
-/** \file source/blender/freestyle/intern/python/StrokeShader/BPy_fstreamShader.h
- * \ingroup freestyle
- */
-
-#ifndef __FREESTYLE_PYTHON_FSTREAMSHADER_H__
-#define __FREESTYLE_PYTHON_FSTREAMSHADER_H__
-
-#include "../BPy_StrokeShader.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-///////////////////////////////////////////////////////////////////////////////////////////
-
-extern PyTypeObject fstreamShader_Type;
-
-#define BPy_fstreamShader_Check(v) (PyObject_IsInstance((PyObject *)v, (PyObject *)&fstreamShader_Type))
-
-/*---------------------------Python BPy_fstreamShader structure definition----------*/
-typedef struct {
- BPy_StrokeShader py_ss;
-} BPy_fstreamShader;
-
-
-///////////////////////////////////////////////////////////////////////////////////////////
-
-#ifdef __cplusplus
-}
-#endif
-
-
-#endif /* __FREESTYLE_PYTHON_FSTREAMSHADER_H__ */
diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_streamShader.cpp b/source/blender/freestyle/intern/python/StrokeShader/BPy_streamShader.cpp
deleted file mode 100644
index 97a6ca0d39e..00000000000
--- a/source/blender/freestyle/intern/python/StrokeShader/BPy_streamShader.cpp
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * ***** BEGIN GPL LICENSE BLOCK *****
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-
-/** \file source/blender/freestyle/intern/python/StrokeShader/BPy_streamShader.cpp
- * \ingroup freestyle
- */
-
-#include "BPy_streamShader.h"
-
-#include "../../stroke/BasicStrokeShaders.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-///////////////////////////////////////////////////////////////////////////////////////////
-
-//------------------------INSTANCE METHODS ----------------------------------
-
-static char streamShader___doc__[] =
-"Class hierarchy: :class:`freestyle.types.StrokeShader` > :class:`streamShader`\n"
-"\n"
-"[Output shader]\n"
-"\n"
-".. method:: __init__()\n"
-"\n"
-" Builds a streamShader object.\n"
-"\n"
-".. method:: shade(stroke)\n"
-"\n"
-" Streams the Stroke into stdout.\n"
-"\n"
-" :arg stroke: A Stroke object.\n"
-" :type stroke: :class:`freestyle.types.Stroke`\n";
-
-static int streamShader___init__(BPy_streamShader *self, PyObject *args, PyObject *kwds)
-{
- static const char *kwlist[] = {NULL};
-
- if (!PyArg_ParseTupleAndKeywords(args, kwds, "", (char **)kwlist))
- return -1;
- self->py_ss.ss = new StrokeShaders::streamShader();
- return 0;
-}
-
-/*-----------------------BPy_streamShader type definition ------------------------------*/
-
-PyTypeObject streamShader_Type = {
- PyVarObject_HEAD_INIT(NULL, 0)
- "streamShader", /* tp_name */
- sizeof(BPy_streamShader), /* tp_basicsize */
- 0, /* tp_itemsize */
- 0, /* tp_dealloc */
- 0, /* tp_print */
- 0, /* tp_getattr */
- 0, /* tp_setattr */
- 0, /* tp_reserved */
- 0, /* tp_repr */
- 0, /* tp_as_number */
- 0, /* tp_as_sequence */
- 0, /* tp_as_mapping */
- 0, /* tp_hash */
- 0, /* tp_call */
- 0, /* tp_str */
- 0, /* tp_getattro */
- 0, /* tp_setattro */
- 0, /* tp_as_buffer */
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
- streamShader___doc__, /* tp_doc */
- 0, /* tp_traverse */
- 0, /* tp_clear */
- 0, /* tp_richcompare */
- 0, /* tp_weaklistoffset */
- 0, /* tp_iter */
- 0, /* tp_iternext */
- 0, /* tp_methods */
- 0, /* tp_members */
- 0, /* tp_getset */
- &StrokeShader_Type, /* tp_base */
- 0, /* tp_dict */
- 0, /* tp_descr_get */
- 0, /* tp_descr_set */
- 0, /* tp_dictoffset */
- (initproc)streamShader___init__, /* tp_init */
- 0, /* tp_alloc */
- 0, /* tp_new */
-};
-
-///////////////////////////////////////////////////////////////////////////////////////////
-
-#ifdef __cplusplus
-}
-#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DVectorViewShape.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DVectorViewShape.cpp
index c72ab2aba71..2a61dfb075a 100644
--- a/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DVectorViewShape.cpp
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DVectorViewShape.cpp
@@ -112,20 +112,14 @@ static PyObject *UnaryFunction0DVectorViewShape___call__(BPy_UnaryFunction0DVect
}
return NULL;
}
- PyObject *list = PyList_New(0);
- PyObject *item;
- for (unsigned int i = 0; i < self->uf0D_vectorviewshape->result.size(); i++) {
+
+ const unsigned int list_len = self->uf0D_vectorviewshape->result.size();
+ PyObject *list = PyList_New(list_len);
+ for (unsigned int i = 0; i < list_len; i++) {
ViewShape *v = self->uf0D_vectorviewshape->result[i];
- if (v) {
- item = BPy_ViewShape_from_ViewShape(*v);
- }
- else {
- item = Py_None;
- Py_INCREF(item);
- }
- PyList_Append(list, item);
+ PyList_SET_ITEM(list, i, v ? BPy_ViewShape_from_ViewShape(*v) : (Py_INCREF(Py_None), Py_None));
}
-
+
return list;
}
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVectorViewShape.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVectorViewShape.cpp
index a028952fa69..c15d974e771 100644
--- a/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVectorViewShape.cpp
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVectorViewShape.cpp
@@ -142,18 +142,12 @@ static PyObject *UnaryFunction1DVectorViewShape___call__(BPy_UnaryFunction1DVect
}
return NULL;
}
- PyObject *list = PyList_New(0);
- PyObject *item;
- for (unsigned int i = 0; i < self->uf1D_vectorviewshape->result.size(); i++) {
+
+ const unsigned int list_len = self->uf1D_vectorviewshape->result.size();
+ PyObject *list = PyList_New(list_len);
+ for (unsigned int i = 0; i < list_len; i++) {
ViewShape *v = self->uf1D_vectorviewshape->result[i];
- if (v) {
- item = BPy_ViewShape_from_ViewShape(*v);
- }
- else {
- item = Py_None;
- Py_INCREF(item);
- }
- PyList_Append(list, item);
+ PyList_SET_ITEM(list, i, v ? BPy_ViewShape_from_ViewShape(*v) : (Py_INCREF(Py_None), Py_None));
}
return list;
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetDirectionalViewMapDensityF1D.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetDirectionalViewMapDensityF1D.cpp
index 517b07f5c7f..041bb60b507 100644
--- a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetDirectionalViewMapDensityF1D.cpp
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetDirectionalViewMapDensityF1D.cpp
@@ -63,7 +63,7 @@ static char GetDirectionalViewMapDensityF1D___doc__[] =
"\n"
" Returns the density evaluated for an Interface1D in of the steerable\n"
" viewmaps image. The direction telling which Directional map to choose\n"
-" is explicitely specified by the user. The density is evaluated for a\n"
+" is explicitly specified by the user. The density is evaluated for a\n"
" set of points along the Interface1D (using the\n"
" :class:`freestyle.functions.ReadSteerableViewMapPixelF0D` functor) and\n"
" then integrated into a single value using a user-defined integration\n"
diff --git a/source/blender/freestyle/intern/scene_graph/IndexedFaceSet.cpp b/source/blender/freestyle/intern/scene_graph/IndexedFaceSet.cpp
index 8a2740b94df..9c462bb6b2b 100644
--- a/source/blender/freestyle/intern/scene_graph/IndexedFaceSet.cpp
+++ b/source/blender/freestyle/intern/scene_graph/IndexedFaceSet.cpp
@@ -34,7 +34,7 @@ IndexedFaceSet::IndexedFaceSet() : Rep()
_Vertices = NULL;
_Normals = NULL;
_FrsMaterials = 0;
- _TexCoords = 0;
+ _TexCoords = NULL;
_FaceEdgeMarks = 0;
_VSize = 0;
_NSize = 0;
@@ -54,8 +54,8 @@ IndexedFaceSet::IndexedFaceSet() : Rep()
_displayList = 0;
}
-IndexedFaceSet::IndexedFaceSet(real *iVertices, unsigned iVSize, real *iNormals, unsigned iNSize,
- FrsMaterial **iMaterials, unsigned iMSize, real *iTexCoords, unsigned iTSize,
+IndexedFaceSet::IndexedFaceSet(float *iVertices, unsigned iVSize, float *iNormals, unsigned iNSize,
+ FrsMaterial **iMaterials, unsigned iMSize, float *iTexCoords, unsigned iTSize,
unsigned iNumFaces, unsigned *iNumVertexPerFace, TRIANGLES_STYLE *iFaceStyle,
FaceEdgeMark *iFaceEdgeMarks, unsigned *iVIndices, unsigned iVISize,
unsigned *iNIndices, unsigned iNISize, unsigned *iMIndices, unsigned iMISize,
@@ -64,12 +64,12 @@ IndexedFaceSet::IndexedFaceSet(real *iVertices, unsigned iVSize, real *iNormals,
{
if (1 == iCopy) {
_VSize = iVSize;
- _Vertices = new real[_VSize];
- memcpy(_Vertices, iVertices, iVSize * sizeof(real));
+ _Vertices = new float[_VSize];
+ memcpy(_Vertices, iVertices, iVSize * sizeof(float));
_NSize = iNSize;
- _Normals = new real[_NSize];
- memcpy(_Normals, iNormals, iNSize * sizeof(real));
+ _Normals = new float[_NSize];
+ memcpy(_Normals, iNormals, iNSize * sizeof(float));
_MSize = iMSize;
_FrsMaterials = 0;
@@ -81,8 +81,8 @@ IndexedFaceSet::IndexedFaceSet(real *iVertices, unsigned iVSize, real *iNormals,
_TSize = iTSize;
_TexCoords = 0;
if (_TSize) {
- _TexCoords = new real[_TSize];
- memcpy(_TexCoords, iTexCoords, iTSize * sizeof(real));
+ _TexCoords = new float[_TSize];
+ memcpy(_TexCoords, iTexCoords, iTSize * sizeof(float));
}
_NumFaces = iNumFaces;
@@ -157,12 +157,12 @@ IndexedFaceSet::IndexedFaceSet(real *iVertices, unsigned iVSize, real *iNormals,
IndexedFaceSet::IndexedFaceSet(const IndexedFaceSet& iBrother) : Rep(iBrother)
{
_VSize = iBrother.vsize();
- _Vertices = new real[_VSize];
- memcpy(_Vertices, iBrother.vertices(), _VSize * sizeof(real));
+ _Vertices = new float[_VSize];
+ memcpy(_Vertices, iBrother.vertices(), _VSize * sizeof(float));
_NSize = iBrother.nsize();
- _Normals = new real[_NSize];
- memcpy(_Normals, iBrother.normals(), _NSize * sizeof(real));
+ _Normals = new float[_NSize];
+ memcpy(_Normals, iBrother.normals(), _NSize * sizeof(float));
_MSize = iBrother.msize();
if (_MSize) {
@@ -178,8 +178,8 @@ IndexedFaceSet::IndexedFaceSet(const IndexedFaceSet& iBrother) : Rep(iBrother)
_TSize = iBrother.tsize();
_TexCoords = 0;
if (_TSize) {
- _TexCoords = new real[_TSize];
- memcpy(_TexCoords, iBrother.texCoords(), _TSize * sizeof(real));
+ _TexCoords = new float[_TSize];
+ memcpy(_TexCoords, iBrother.texCoords(), _TSize * sizeof(float));
}
_NumFaces = iBrother.numFaces();
@@ -290,16 +290,16 @@ void IndexedFaceSet::accept(SceneVisitor& v)
void IndexedFaceSet::ComputeBBox()
{
- real XMax = _Vertices[0];
- real YMax = _Vertices[1];
- real ZMax = _Vertices[2];
+ float XMax = _Vertices[0];
+ float YMax = _Vertices[1];
+ float ZMax = _Vertices[2];
- real XMin = _Vertices[0];
- real YMin = _Vertices[1];
- real ZMin = _Vertices[2];
+ float XMin = _Vertices[0];
+ float YMin = _Vertices[1];
+ float ZMin = _Vertices[2];
// parse all the coordinates to find the Xmax, YMax, ZMax
- real *v = _Vertices;
+ float *v = _Vertices;
for (unsigned int i = 0; i < (_VSize / 3); ++i) {
if (*v > XMax)
@@ -321,7 +321,7 @@ void IndexedFaceSet::ComputeBBox()
++v;
}
- setBBox(BBox<Vec3r>(Vec3r(XMin, YMin, ZMin), Vec3r(XMax, YMax, ZMax)));
+ setBBox(BBox<Vec3f>(Vec3f(XMin, YMin, ZMin), Vec3f(XMax, YMax, ZMax)));
}
} /* namespace Freestyle */
diff --git a/source/blender/freestyle/intern/scene_graph/IndexedFaceSet.h b/source/blender/freestyle/intern/scene_graph/IndexedFaceSet.h
index d3a10aab4dd..8d7bf986bde 100644
--- a/source/blender/freestyle/intern/scene_graph/IndexedFaceSet.h
+++ b/source/blender/freestyle/intern/scene_graph/IndexedFaceSet.h
@@ -114,8 +114,8 @@ public:
* arrays desallocation in charge.
* 1 : the arrays are copied. The caller is in charge of the arrays, passed as arguments desallocation.
*/
- IndexedFaceSet(real *iVertices, unsigned iVSize, real *iNormals, unsigned iNSize, FrsMaterial **iMaterials,
- unsigned iMSize, real *iTexCoords, unsigned iTSize, unsigned iNumFaces, unsigned *iNumVertexPerFace,
+ IndexedFaceSet(float *iVertices, unsigned iVSize, float *iNormals, unsigned iNSize, FrsMaterial **iMaterials,
+ unsigned iMSize, float *iTexCoords, unsigned iTSize, unsigned iNumFaces, unsigned *iNumVertexPerFace,
TRIANGLES_STYLE *iFaceStyle, FaceEdgeMark *iFaceEdgeMarks, unsigned *iVIndices, unsigned iVISize,
unsigned *iNIndices, unsigned iNISize, unsigned *iMIndices, unsigned iMISize, unsigned *iTIndices,
unsigned iTISize, unsigned iCopy = 1);
@@ -180,12 +180,12 @@ public:
}
/*! Accessors */
- virtual const real *vertices() const
+ virtual const float *vertices() const
{
return _Vertices;
}
- virtual const real *normals() const
+ virtual const float *normals() const
{
return _Normals;
}
@@ -195,7 +195,7 @@ public:
return _FrsMaterials;
}
- virtual const real *texCoords() const
+ virtual const float *texCoords() const
{
return _TexCoords;
}
@@ -286,10 +286,10 @@ public:
}
protected:
- real *_Vertices;
- real *_Normals;
+ float *_Vertices;
+ float *_Normals;
FrsMaterial **_FrsMaterials;
- real *_TexCoords;
+ float *_TexCoords;
unsigned _VSize;
unsigned _NSize;
@@ -316,7 +316,6 @@ protected:
#ifdef WITH_CXX_GUARDEDALLOC
MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:IndexedFaceSet")
#endif
-
};
} /* namespace Freestyle */
diff --git a/source/blender/freestyle/intern/scene_graph/NodeCamera.h b/source/blender/freestyle/intern/scene_graph/NodeCamera.h
index 5d84a624830..78c34fdef6d 100644
--- a/source/blender/freestyle/intern/scene_graph/NodeCamera.h
+++ b/source/blender/freestyle/intern/scene_graph/NodeCamera.h
@@ -53,7 +53,9 @@ public:
/*! Default matrices: Identity for both projection and modelview. */
NodeCamera(CameraType camera_type = GENERIC);
+#if 0 /* UNUSED, gives warning in gcc */
NodeCamera(const NodeCamera& iBrother);
+#endif
virtual ~NodeCamera() {}
diff --git a/source/blender/freestyle/intern/scene_graph/NodeSceneRenderLayer.cpp b/source/blender/freestyle/intern/scene_graph/NodeSceneRenderLayer.cpp
new file mode 100644
index 00000000000..24c56ff4e28
--- /dev/null
+++ b/source/blender/freestyle/intern/scene_graph/NodeSceneRenderLayer.cpp
@@ -0,0 +1,35 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/freestyle/intern/scene_graph/NodeSceneRenderLayer.cpp
+ * \ingroup freestyle
+ * \brief Class to represent a scene render layer in Blender.
+ */
+
+#include "NodeSceneRenderLayer.h"
+
+namespace Freestyle {
+
+void NodeSceneRenderLayer::accept(SceneVisitor& v)
+{
+ v.visitNodeSceneRenderLayer(*this);
+}
+
+} /* namespace Freestyle */
diff --git a/source/blender/freestyle/intern/scene_graph/NodeSceneRenderLayer.h b/source/blender/freestyle/intern/scene_graph/NodeSceneRenderLayer.h
new file mode 100644
index 00000000000..4b079df5632
--- /dev/null
+++ b/source/blender/freestyle/intern/scene_graph/NodeSceneRenderLayer.h
@@ -0,0 +1,76 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __FREESTYLE_NODE_SCENE_RENDER_LAYER_H__
+#define __FREESTYLE_NODE_SCENE_RENDER_LAYER_H__
+
+/** \file blender/freestyle/intern/scene_graph/NodeSceneRenderLayer.h
+ * \ingroup freestyle
+ * \brief Class to represent a scene render layer in Blender.
+ */
+
+#include "Node.h"
+
+extern "C" {
+#include "DNA_scene_types.h" /* for Scene and SceneRenderLayer */
+}
+
+using namespace std;
+
+namespace Freestyle {
+
+class NodeSceneRenderLayer : public Node
+{
+public:
+ inline NodeSceneRenderLayer(Scene& scene, SceneRenderLayer& srl) : Node(), _Scene(scene), _SceneRenderLayer(srl) {}
+ virtual ~NodeSceneRenderLayer() {}
+
+ inline struct Scene& scene() const
+ {
+ return _Scene;
+ }
+
+ inline struct SceneRenderLayer& sceneRenderLayer() const
+ {
+ return _SceneRenderLayer;
+ }
+
+ inline void setSceneRenderLayer(Scene& scene)
+ {
+ _Scene = scene;
+ }
+
+ inline void setSceneRenderLayer(SceneRenderLayer& srl)
+ {
+ _SceneRenderLayer = srl;
+ }
+
+ /*! Accept the corresponding visitor */
+ virtual void accept(SceneVisitor& v);
+
+protected:
+
+ Scene& _Scene;
+ SceneRenderLayer& _SceneRenderLayer;
+};
+
+} /* namespace Freestyle */
+
+#endif // __FREESTYLE_NODE_SCENE_RENDER_LAYER_H__
diff --git a/source/blender/freestyle/intern/scene_graph/Rep.h b/source/blender/freestyle/intern/scene_graph/Rep.h
index 88ee0d2a801..c5036cdb153 100644
--- a/source/blender/freestyle/intern/scene_graph/Rep.h
+++ b/source/blender/freestyle/intern/scene_graph/Rep.h
@@ -117,7 +117,7 @@ public:
virtual void ComputeBBox() = 0;
/*! Returns the rep bounding box */
- virtual const BBox<Vec3r>& bbox() const
+ virtual const BBox<Vec3f>& bbox() const
{
return _BBox;
}
@@ -127,7 +127,7 @@ public:
return _Id;
}
- inline const string& getName() const
+ inline const char *getName() const
{
return _Name;
}
@@ -138,7 +138,7 @@ public:
}
/*! Sets the Rep bounding box */
- virtual void setBBox(const BBox<Vec3r>& iBox)
+ virtual void setBBox(const BBox<Vec3f>& iBox)
{
_BBox = iBox;
}
@@ -148,7 +148,7 @@ public:
_Id = id;
}
- inline void setName(const string& name)
+ inline void setName(const char *name)
{
_Name = name;
}
@@ -159,9 +159,9 @@ public:
}
private:
- BBox<Vec3r> _BBox;
+ BBox<Vec3f> _BBox;
Id _Id;
- string _Name;
+ const char *_Name;
FrsMaterial *_FrsMaterial;
};
diff --git a/source/blender/freestyle/intern/scene_graph/SceneHash.cpp b/source/blender/freestyle/intern/scene_graph/SceneHash.cpp
new file mode 100644
index 00000000000..9d595c235c2
--- /dev/null
+++ b/source/blender/freestyle/intern/scene_graph/SceneHash.cpp
@@ -0,0 +1,84 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/freestyle/intern/scene_graph/SceneHash.cpp
+ * \ingroup freestyle
+ */
+
+#include "SceneHash.h"
+
+#include <sstream>
+
+namespace Freestyle {
+
+string SceneHash::toString()
+{
+ stringstream ss;
+ ss << hex << _sum;
+ return ss.str();
+}
+
+void SceneHash::visitNodeSceneRenderLayer(NodeSceneRenderLayer& node)
+{
+ struct RenderData *r = &node.scene().r;
+ adler32((unsigned char *)&r->xsch, sizeof(r->xsch)); // resolution_x
+ adler32((unsigned char *)&r->ysch, sizeof(r->ysch)); // resolution_y
+ adler32((unsigned char *)&r->size, sizeof(r->size)); // resolution_percentage
+
+ struct FreestyleConfig *config = &node.sceneRenderLayer().freestyleConfig;
+ adler32((unsigned char *)&config->flags, sizeof(config->flags));
+ adler32((unsigned char *)&config->crease_angle, sizeof(config->crease_angle));
+ adler32((unsigned char *)&config->sphere_radius, sizeof(config->sphere_radius));
+ adler32((unsigned char *)&config->dkr_epsilon, sizeof(config->dkr_epsilon));
+}
+
+void SceneHash::visitNodeCamera(NodeCamera& cam)
+{
+ double *proj = cam.projectionMatrix();
+ for (int i = 0; i < 16; i++) {
+ adler32((unsigned char *)&proj[i], sizeof(double));
+ }
+}
+
+void SceneHash::visitIndexedFaceSet(IndexedFaceSet& ifs)
+{
+ const float *v = ifs.vertices();
+ const unsigned n = ifs.vsize();
+
+ for (unsigned i = 0; i < n; i++) {
+ adler32((unsigned char *)&v[i], sizeof(v[i]));
+ }
+}
+
+static const int MOD_ADLER = 65521;
+
+void SceneHash::adler32(unsigned char *data, int size)
+{
+ uint32_t sum1 = _sum & 0xffff;
+ uint32_t sum2 = (_sum >> 16) & 0xffff;
+
+ for (int i = 0; i < size; i++) {
+ sum1 = (sum1 + data[i]) % MOD_ADLER;
+ sum2 = (sum1 + sum2) % MOD_ADLER;
+ }
+ _sum = sum1 | (sum2 << 16);
+}
+
+} /* namespace Freestyle */
diff --git a/source/blender/freestyle/intern/scene_graph/SceneHash.h b/source/blender/freestyle/intern/scene_graph/SceneHash.h
new file mode 100644
index 00000000000..9da711673f0
--- /dev/null
+++ b/source/blender/freestyle/intern/scene_graph/SceneHash.h
@@ -0,0 +1,82 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __FREESTYLE_SCENE_HASH_H__
+#define __FREESTYLE_SCENE_HASH_H__
+
+/** \file blender/freestyle/intern/scene_graph/SceneHash.h
+ * \ingroup freestyle
+ */
+
+#include "IndexedFaceSet.h"
+#include "NodeSceneRenderLayer.h"
+#include "NodeCamera.h"
+#include "SceneVisitor.h"
+
+#include "BLI_sys_types.h"
+
+#ifdef WITH_CXX_GUARDEDALLOC
+#include "MEM_guardedalloc.h"
+#endif
+
+namespace Freestyle {
+
+class SceneHash : public SceneVisitor
+{
+public:
+ inline SceneHash() : SceneVisitor()
+ {
+ _sum = 1;
+ }
+
+ virtual ~SceneHash() {}
+
+ VISIT_DECL(NodeCamera)
+ VISIT_DECL(NodeSceneRenderLayer)
+ VISIT_DECL(IndexedFaceSet)
+
+ string toString();
+
+ inline bool match() {
+ return _sum == _prevSum;
+ }
+
+ inline void store() {
+ _prevSum = _sum;
+ }
+
+ inline void reset() {
+ _sum = 1;
+ }
+
+private:
+ void adler32(unsigned char *data, int size);
+
+ uint32_t _sum;
+ uint32_t _prevSum;
+
+#ifdef WITH_CXX_GUARDEDALLOC
+ MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:SceneHash")
+#endif
+};
+
+} /* namespace Freestyle */
+
+#endif // __FREESTYLE_SCENE_HASH_H__
diff --git a/source/blender/freestyle/intern/scene_graph/ScenePrettyPrinter.cpp b/source/blender/freestyle/intern/scene_graph/ScenePrettyPrinter.cpp
index 4e87625f6f9..e7041f04cf0 100644
--- a/source/blender/freestyle/intern/scene_graph/ScenePrettyPrinter.cpp
+++ b/source/blender/freestyle/intern/scene_graph/ScenePrettyPrinter.cpp
@@ -93,11 +93,11 @@ VISIT(VertexRep)
void ScenePrettyPrinter::visitIndexedFaceSet(IndexedFaceSet& ifs)
{
- const real *vertices = ifs.vertices();
+ const float *vertices = ifs.vertices();
unsigned vsize = ifs.vsize();
_ofs << _space << "IndexedFaceSet" << endl;
- const real *p = vertices;
+ const float *p = vertices;
for (unsigned int i = 0; i < vsize / 3; i++) {
_ofs << _space << " " << setw(3) << setfill('0') << i << ": " << p[0] << ", " << p[1] << ", " << p[2] << endl;
p += 3;
diff --git a/source/blender/freestyle/intern/scene_graph/SceneVisitor.h b/source/blender/freestyle/intern/scene_graph/SceneVisitor.h
index c00f5124a31..712585c4064 100644
--- a/source/blender/freestyle/intern/scene_graph/SceneVisitor.h
+++ b/source/blender/freestyle/intern/scene_graph/SceneVisitor.h
@@ -56,6 +56,7 @@ class NodeLight;
class NodeCamera;
class NodeDrawingStyle;
class NodeTransform;
+class NodeSceneRenderLayer;
class Rep;
class LineRep;
@@ -87,6 +88,7 @@ public:
VISIT_COMPLETE_DEF(NodeCamera)
VISIT_COMPLETE_DEF(NodeDrawingStyle)
VISIT_COMPLETE_DEF(NodeTransform)
+ VISIT_COMPLETE_DEF(NodeSceneRenderLayer)
VISIT_COMPLETE_DEF(Rep)
VISIT_COMPLETE_DEF(LineRep)
diff --git a/source/blender/freestyle/intern/stroke/AdvancedFunctions1D.h b/source/blender/freestyle/intern/stroke/AdvancedFunctions1D.h
index cbdff4ed96c..9df690cf5b0 100644
--- a/source/blender/freestyle/intern/stroke/AdvancedFunctions1D.h
+++ b/source/blender/freestyle/intern/stroke/AdvancedFunctions1D.h
@@ -168,7 +168,7 @@ private:
// GetDirectionalViewMapDensity
/*! Returns the density evaluated for an Interface1D in of the steerable viewmaps image.
- * The direction telling which Directional map to choose is explicitely specified by the user.
+ * The direction telling which Directional map to choose is explicitly specified by the user.
* The density is evaluated for a set of points along the Interface1D (using the ReadSteerableViewMapPixelF0D functor)
* and then integrated into a single value using a user-defined integration method.
*/
diff --git a/source/blender/freestyle/intern/stroke/AdvancedStrokeShaders.cpp b/source/blender/freestyle/intern/stroke/AdvancedStrokeShaders.cpp
index 274e36a4c9b..e37631e5bd6 100644
--- a/source/blender/freestyle/intern/stroke/AdvancedStrokeShaders.cpp
+++ b/source/blender/freestyle/intern/stroke/AdvancedStrokeShaders.cpp
@@ -81,20 +81,6 @@ int CalligraphicShader::shade(Stroke &ioStroke) const
return 0;
}
-#if 0
-void TipRemoverShader::shade(Stroke &ioStroke) const
-{
- StrokeInternal::StrokeVertexIterator v, vend;
- for (v = ioStroke.strokeVerticesBegin(), vend = ioStroke.strokeVerticesEnd(); v != vend; ++v) {
- if (((*v)->curvilinearAbscissa() < _tipLength) ||
- (((*v)->strokeLength() - (*v)->curvilinearAbscissa()) < _tipLength)) {
- (*v)->attribute().setThickness(0.0, 0.0);
- (*v)->attribute().setColor(1, 1, 1);
- }
- }
-}
-#endif
-
/////////////////////////////////////////
//
// SPATIAL NOISE SHADER
@@ -347,63 +333,4 @@ void Smoother::copyVertices()
_stroke->UpdateLength();
}
-#if 0 // FIXME
-
-/////////////////////////////////////////
-//
-// OMISSION SHADER
-//
-/////////////////////////////////////////
-
-OmissionShader::OmissionShader(real sizeWindow, real thrVari, real thrFlat, real lFlat)
-{
- _sizeWindow = sizeWindow;
- _thresholdVariation = thrVari;
- _thresholdFlat = thrFlat;
- _lengthFlat = lFlat;
-}
-
-int OmissionShader::shade(Stroke &ioStroke) const
-{
- Omitter omi(ioStroke);
- omi.omit(_sizeWindow, _thresholdVariation, _thresholdFlat, _lengthFlat);
-
- return 0;
-}
-
-
-// OMITTER
-///////////////////////////
-
-Omitter::Omitter(Stroke &ioStroke) : Smoother(ioStroke)
-{
- StrokeInternal::StrokeVertexIterator v, vend;
- int i = 0;
- for (v = ioStroke.strokeVerticesBegin(), vend = ioStroke.strokeVerticesEnd(); v != vend; ++v, ++i) {
- _u[i] = (v)->curvilinearAbscissa();
- }
-}
-
-void Omitter::omit(real sizeWindow, real thrVari, real thrFlat, real lFlat)
-{
- _sizeWindow=sizeWindow;
- _thresholdVariation=thrVari;
- _thresholdFlat=thrFlat;
- _lengthFlat=lFlat;
-
- for (int i = 1; i < _nbVertices-1; ++i) {
- if (_u[i] < _lengthFlat)
- continue;
- // is the previous segment flat?
- int j = i - 1;
- while ((j >= 0) && (_u[i] - _u[j] < _lengthFlat)) {
- if ((_normal[j] * _normal[i]) < _thresholdFlat)
- ; // FIXME
- --j;
- }
- }
-}
-
-#endif
-
} /* namespace Freestyle */
diff --git a/source/blender/freestyle/intern/stroke/BasicStrokeShaders.cpp b/source/blender/freestyle/intern/stroke/BasicStrokeShaders.cpp
index 69ca45d3ec7..eed90a53d77 100644
--- a/source/blender/freestyle/intern/stroke/BasicStrokeShaders.cpp
+++ b/source/blender/freestyle/intern/stroke/BasicStrokeShaders.cpp
@@ -43,9 +43,6 @@
#include "BKE_global.h"
-//soc #include <qimage.h>
-//soc #include <QString>
-
extern "C" {
# include "IMB_imbuf.h"
# include "IMB_imbuf_types.h"
@@ -53,32 +50,6 @@ extern "C" {
namespace Freestyle {
-// Internal function
-
-#if 0 // soc
-void convert(const QImage& iImage, float **oArray, unsigned &oSize)
-{
- oSize = iImage.width();
- *oArray = new float[oSize];
- for (unsigned int i = 0; i < oSize; ++i) {
- QRgb rgb = iImage.pixel(i,0);
- (*oArray)[i] = ((float)qBlue(rgb)) / 255.0f;
- }
-}
-#endif
-
-static void convert(ImBuf *imBuf, float **oArray, unsigned &oSize)
-{
- oSize = imBuf->x;
- *oArray = new float[oSize];
-
- char *pix;
- for (unsigned int i = 0; i < oSize; ++i) {
- pix = (char *) imBuf->rect + i * 4;
- (*oArray)[i] = ((float) pix[2]) / 255.0f;
- }
-}
-
namespace StrokeShaders {
//
@@ -191,76 +162,6 @@ int LengthDependingThicknessShader::shade(Stroke& stroke) const
return 0;
}
-
-ThicknessVariationPatternShader::ThicknessVariationPatternShader(const string pattern_name, float iMinThickness,
- float iMaxThickness, bool stretch)
-: StrokeShader()
-{
- _stretch = stretch;
- _minThickness = iMinThickness;
- _maxThickness = iMaxThickness;
- ImBuf *image = NULL;
- vector<string> pathnames;
- StringUtils::getPathName(TextureManager::Options::getPatternsPath(), pattern_name, pathnames);
- for (vector<string>::const_iterator j = pathnames.begin(); j != pathnames.end(); ++j) {
- ifstream ifs(j->c_str());
- if (ifs.is_open()) {
- /* OCIO_TODO: support different input color space */
- image = IMB_loadiffname(j->c_str(), 0, NULL);
- break;
- }
- }
- if (image == NULL)
- cerr << "Error: cannot find pattern \"" << pattern_name << "\" - check the path in the Options" << endl;
- else
- convert(image, &_aThickness, _size);
- IMB_freeImBuf(image);
-}
-
-
-int ThicknessVariationPatternShader::shade(Stroke& stroke) const
-{
- StrokeInternal::StrokeVertexIterator v, vend;
- float *array = NULL;
- /* int size; */ /* UNUSED */
- array = _aThickness;
- /* size = _size; */ /* UNUSED */
- int vert_size = stroke.strokeVerticesSize();
- int sig = 0;
- unsigned index;
- const float *originalThickness;
- for (v = stroke.strokeVerticesBegin(), vend = stroke.strokeVerticesEnd(); v != vend; ++v) {
- originalThickness = v->attribute().getThickness();
- if (_stretch) {
- float tmp = v->u() * (_size - 1);
- index = (unsigned)floor(tmp);
- if ((tmp - index) > (index + 1 - tmp))
- ++index;
- }
- else {
- index = (unsigned)floor(v->curvilinearAbscissa());
- }
- index %= _size;
- float thicknessR = array[index] * originalThickness[0];
- float thicknessL = array[index] * originalThickness[1];
- if (thicknessR + thicknessL < _minThickness) {
- thicknessL = _minThickness / 2.0f;
- thicknessR = _minThickness / 2.0f;
- }
- if (thicknessR + thicknessL > _maxThickness) {
- thicknessL = _maxThickness / 2.0f;
- thicknessR = _maxThickness / 2.0f;
- }
- if ((sig == 0) || (sig == vert_size - 1))
- v->attribute().setThickness(1, 1);
- else
- v->attribute().setThickness(thicknessR, thicknessL);
- ++sig;
- }
- return 0;
-}
-
-
static const unsigned NB_VALUE_NOISE = 512;
ThicknessNoiseShader::ThicknessNoiseShader() : StrokeShader()
@@ -284,7 +185,7 @@ int ThicknessNoiseShader::shade(Stroke& stroke) const
real bruit, bruit2;
PseudoNoise mynoise, mynoise2;
for (vend = stroke.strokeVerticesEnd(); v != vend; ++v) {
- bruit = mynoise.turbulenceSmooth(_scale * v->curvilinearAbscissa() + initU1, 2); // 2 : nbOctaves
+ bruit = mynoise.turbulenceSmooth(_scale * v->curvilinearAbscissa() + initU1, 2); // 2 : nbOctaves
bruit2 = mynoise2.turbulenceSmooth(_scale * v->curvilinearAbscissa() + initU2, 2); // 2 : nbOctaves
const float *originalThickness = v->attribute().getThickness();
float r = bruit * _amplitude + originalThickness[0];
@@ -328,51 +229,6 @@ int IncreasingColorShader::shade(Stroke& stroke) const
return 0;
}
-ColorVariationPatternShader::ColorVariationPatternShader(const string pattern_name, bool stretch) : StrokeShader()
-{
- _stretch = stretch;
- ImBuf *image = NULL;
- vector<string> pathnames;
- StringUtils::getPathName(TextureManager::Options::getPatternsPath(), pattern_name, pathnames);
- for (vector<string>::const_iterator j = pathnames.begin(); j != pathnames.end(); ++j) {
- ifstream ifs(j->c_str());
- if (ifs.is_open()) {
- /* OCIO_TODO: support different input color space */
- image = IMB_loadiffname(j->c_str(), 0, NULL); //soc
- break;
- }
- }
- if (image == NULL)
- cerr << "Error: cannot find pattern \"" << pattern_name << "\" - check the path in the Options" << endl;
- else
- convert(image, &_aVariation, _size);
- IMB_freeImBuf(image);
-}
-
-int ColorVariationPatternShader::shade(Stroke& stroke) const
-{
- StrokeInternal::StrokeVertexIterator v, vend;
- unsigned index;
- for (v = stroke.strokeVerticesBegin(), vend = stroke.strokeVerticesEnd(); v != vend; ++v) {
- const float *originalColor = v->attribute().getColor();
- if (_stretch) {
- float tmp = v->u() * (_size - 1);
- index = (unsigned)floor(tmp);
- if ((tmp - index) > (index + 1 - tmp))
- ++index;
- }
- else {
- index = (unsigned)floor(v->curvilinearAbscissa());
- }
- index %= _size;
- float r = _aVariation[index] * originalColor[0];
- float g = _aVariation[index] * originalColor[1];
- float b = _aVariation[index] * originalColor[2];
- v->attribute().setColor(r, g, b);
- }
- return 0;
-}
-
int MaterialColorShader::shade(Stroke& stroke) const
{
Interface0DIterator v, vend;
@@ -389,29 +245,6 @@ int MaterialColorShader::shade(Stroke& stroke) const
return 0;
}
-
-int CalligraphicColorShader::shade(Stroke& stroke) const
-{
- Interface0DIterator v;
- Functions0D::VertexOrientation2DF0D fun;
- StrokeVertex *sv;
- for (v = stroke.verticesBegin(); !v.isEnd(); ++v) {
- if (fun(v) < 0)
- return -1;
- Vec2f vertexOri(fun.result);
- Vec2d ori2d(-vertexOri[1], vertexOri[0]);
- ori2d.normalizeSafe();
- real scal = ori2d * _orientation;
- sv = dynamic_cast<StrokeVertex*>(&(*v));
- if ((scal < 0))
- sv->attribute().setColor(0, 0, 0);
- else
- sv->attribute().setColor(1, 1, 1);
- }
- return 0;
-}
-
-
ColorNoiseShader::ColorNoiseShader() : StrokeShader()
{
_amplitude = 1.0f;
@@ -439,11 +272,9 @@ int ColorNoiseShader::shade(Stroke& stroke) const
float b = bruit * _amplitude + originalColor[2];
v->attribute().setColor(r, g, b);
}
-
return 0;
}
-
//
// Texture Shaders
//
@@ -466,19 +297,6 @@ int StrokeTextureStepShader::shade(Stroke& stroke) const
return 0;
}
-// Legacy shaders from freestyle standalone texture system
-int TextureAssignerShader::shade(Stroke& stroke) const
-{
- cout << "TextureAssignerShader is not supported in blender, please use the BlenderTextureShader" << endl;
- return 0;
-}
-
-int StrokeTextureShader::shade(Stroke& stroke) const
-{
- cout << "StrokeTextureShader is not supported in blender, please use the BlenderTextureShader" << endl;
- return 0;
-}
-
//
// Geometry Shaders
//
@@ -541,119 +359,6 @@ int ExternalContourStretcherShader::shade(Stroke& stroke) const
return 0;
}
-int BSplineShader::shade(Stroke& stroke) const
-{
- if (stroke.strokeVerticesSize() < 4)
- return 0;
-
- // Find the new vertices
- vector<Vec2d> newVertices;
- double t = 0.0;
- float _sampling = 5.0f;
-
- StrokeInternal::StrokeVertexIterator p0, p1, p2, p3, end;
- p0 = stroke.strokeVerticesBegin();
- p1 = p0;
- p2 = p1;
- p3 = p2;
- end = stroke.strokeVerticesEnd();
- double a[4], b[4];
- int n = 0;
- while (p1 != end) {
-#if 0
- if (p1 == end)
- p1 = p0;
-#endif
- if (p2 == end)
- p2 = p1;
- if (p3 == end)
- p3 = p2;
- // compute new matrix
- a[0] = (-(p0)->x() + 3 * (p1)->x() - 3 * (p2)->x() + (p3)->x()) / 6.0;
- a[1] = (3 * (p0)->x() - 6 * (p1)->x() + 3 * (p2)->x()) / 6.0;
- a[2] = (-3 * (p0)->x() + 3 * (p2)->x()) / 6.0;
- a[3] = ((p0)->x() + 4 * (p1)->x() + (p2)->x()) / 6.0;
-
- b[0] = (-(p0)->y() + 3 * (p1)->y() - 3 * (p2)->y() + (p3)->y()) / 6.0;
- b[1] = (3 * (p0)->y() - 6 * (p1)->y() + 3 * (p2)->y()) / 6.0;
- b[2] = (-3 * (p0)->y() + 3 * (p2)->y()) / 6.0;
- b[3] = ((p0)->y() + 4 * (p1)->y() + (p2)->y()) / 6.0;
-
- // draw the spline depending on resolution:
- Vec2d p1p2((p2)->x() - (p1)->x(), (p2)->y() - (p1)->y());
- double norm = p1p2.norm();
- //t = _sampling / norm;
- t = 0;
- while (t < 1) {
- newVertices.push_back(Vec2d((a[3] + t * (a[2] + t * (a[1] + t * a[0]))),
- (b[3] + t * (b[2] + t * (b[1] + t * b[0])))));
- t = t + _sampling / norm;
- }
- if (n > 2) {
- ++p0;
- ++p1;
- ++p2;
- ++p3;
- }
- else {
- if (n == 0)
- ++p3;
- if (n == 1) {
- ++p2;
- ++p3;
- }
- if (n == 2) {
- ++p1;
- ++p2;
- ++p3;
- }
- ++n;
- }
- }
- //last point:
- newVertices.push_back(Vec2d((p0)->x(), (p0)->y()));
-
- int originalSize = newVertices.size();
- _sampling = stroke.ComputeSampling(originalSize);
-
- // Resample and set x,y coordinates
- stroke.Resample(_sampling);
- int newsize = stroke.strokeVerticesSize();
-
- int nExtraVertex = 0;
- if (newsize < originalSize) {
- cerr << "Warning: unsufficient resampling" << endl;
- }
- else {
- nExtraVertex = newsize - originalSize;
- }
-
- // assigns the new coordinates:
- vector<Vec2d>::iterator p = newVertices.begin(), pend = newVertices.end();
- vector<Vec2d>::iterator last = p;
- n = 0;
- StrokeInternal::StrokeVertexIterator it, itend;
- for (it = stroke.strokeVerticesBegin(), itend = stroke.strokeVerticesEnd();
- (it != itend) && (p != pend);
- ++it, ++p, ++n)
- {
- it->setX(p->x());
- it->setY(p->y());
- last = p;
- }
-
- // nExtraVertex should stay unassigned
- for (int i = 0; i < nExtraVertex; ++i, ++it, ++n) {
- it->setX(last->x());
- it->setY(last->y());
- if (it.isEnd()) {
- // XXX Shouldn't we break in this case???
- cerr << "Warning: Problem encountered while creating B-spline" << endl;
- }
- }
- stroke.UpdateLength();
- return 0;
-}
//!! Bezier curve stroke shader
int BezierCurveShader::shade(Stroke& stroke) const
@@ -673,15 +378,6 @@ int BezierCurveShader::shade(Stroke& stroke) const
previous = v;
}
-#if 0
- Vec2d tmp;
- bool equal = false;
- if (data.front() == data.back()) {
- tmp = data.back();
- data.pop_back();
- equal = true;
- }
-#endif
// here we build the bezier curve
BezierCurve bcurve(data, _error);
@@ -702,25 +398,6 @@ int BezierCurveShader::shade(Stroke& stroke) const
}
}
-#if 0
- if (equal) {
- if (data.back() == data.front()) {
- vector<Vec2d>::iterator d = data.begin(), dend;
- if (G.debug & G_DEBUG_FREESTYLE) {
- cout << "ending point = starting point" << endl;
- cout << "---------------DATA----------" << endl;
- for (dend = data.end(); d != dend; ++d) {
- cout << d->x() << "-" << d->y() << endl;
- }
- cout << "--------------BEZIER RESULT----------" << endl;
- for (d = CurveVertices.begin(), dend = CurveVertices.end(); d != dend; ++d) {
- cout << d->x() << "-" << d->y() << endl;
- }
- }
- }
- }
-#endif
-
// Resample the Stroke depending on the number of vertices of the bezier curve:
int originalSize = CurveVertices.size();
#if 0
@@ -734,11 +411,6 @@ int BezierCurveShader::shade(Stroke& stroke) const
cerr << "Warning: unsufficient resampling" << endl;
}
else {
-#if 0
- if (G.debug & G_DEBUG_FREESTYLE) {
- cout << "Oversampling" << endl;
- }
-#endif
nExtraVertex = newsize - originalSize;
if (nExtraVertex != 0) {
if (G.debug & G_DEBUG_FREESTYLE) {
@@ -752,22 +424,12 @@ int BezierCurveShader::shade(Stroke& stroke) const
vector<Vec2d>::iterator last = p;
int n;
StrokeInternal::StrokeVertexIterator it, itend;
-#if 0
- for (; p != pend; ++n, ++p);
-#endif
for (n = 0, it = stroke.strokeVerticesBegin(), itend = stroke.strokeVerticesEnd(), pend = CurveVertices.end();
(it != itend) && (p != pend);
++it, ++p, ++n)
{
it->setX(p->x());
it->setY(p->y());
-#if 0
- double x = p->x();
- double y = p->y();
- if (G.debug & G_DEBUG_FREESTYLE) {
- cout << "x = " << x << "-" << "y = " << y << endl;
- }
-#endif
last = p;
}
stroke.UpdateLength();
@@ -816,46 +478,6 @@ int BezierCurveShader::shade(Stroke& stroke) const
return 0;
}
-int InflateShader::shade(Stroke& stroke) const
-{
- // we're computing the curvature variance of the stroke. (Combo 5)
- // If it's too high, forget about it
- Functions1D::Curvature2DAngleF1D fun;
- if (fun(stroke) < 0)
- return -1;
- if (fun.result > _curvatureThreshold)
- return 0;
-
- Functions0D::VertexOrientation2DF0D ori_fun;
- Functions0D::Curvature2DAngleF0D curv_fun;
- Functions1D::Normal2DF1D norm_fun;
- Interface0DIterator it;
- StrokeVertex *sv;
- for (it = stroke.verticesBegin(); !it.isEnd(); ++it) {
- if (ori_fun(it) < 0)
- return -1;
- Vec2f ntmp(ori_fun.result);
- Vec2f n(ntmp.y(), -ntmp.x());
- if (norm_fun(stroke) < 0)
- return -1;
- Vec2f strokeN(norm_fun.result);
- if (n * strokeN < 0) {
- n[0] = -n[0];
- n[1] = -n[1];
- }
- sv = dynamic_cast<StrokeVertex*>(&(*it));
- float u = sv->u();
- float t = 4.0f * (0.25f - (u - 0.5) * (u - 0.5));
- if (curv_fun(it) < 0)
- return -1;
- float curvature_coeff = (M_PI - curv_fun.result) / M_PI;
- Vec2d newPoint(sv->x() + curvature_coeff * t * _amount * n.x(),
- sv->y() + curvature_coeff * t * _amount * n.y());
- sv->setPoint(newPoint[0], newPoint[1]);
- }
- stroke.UpdateLength();
- return 0;
-}
class CurvePiece
{
@@ -1040,40 +662,16 @@ int TipRemoverShader::shade(Stroke& stroke) const
// assign old attributes to new stroke vertices:
vector<StrokeAttribute>::iterator a = oldAttributes.begin(), aend = oldAttributes.end();
-#if 0
- if (G.debug & G_DEBUG_FREESTYLE) {
- cout << "-----------------------------------------------" << endl;
- }
-#endif
for (v = stroke.strokeVerticesBegin(), vend = stroke.strokeVerticesEnd();
(v != vend) && (a != aend);
++v, ++a)
{
v->setAttribute(*a);
-#if 0
- if (G.debug & G_DEBUG_FREESTYLE) {
- cout << "thickness = " << (*a).getThickness()[0] << "-" << (*a).getThickness()[1] << endl;
- }
-#endif
}
// we're done!
return 0;
}
-int streamShader::shade(Stroke& stroke) const
-{
- if (G.debug & G_DEBUG_FREESTYLE) {
- cout << stroke << endl;
- }
- return 0;
-}
-
-int fstreamShader::shade(Stroke& stroke) const
-{
- _stream << stroke << endl;
- return 0;
-}
-
} // end of namespace StrokeShaders
} /* namespace Freestyle */
diff --git a/source/blender/freestyle/intern/stroke/BasicStrokeShaders.h b/source/blender/freestyle/intern/stroke/BasicStrokeShaders.h
index 6ac22c5b2d1..e3842f45eb0 100644
--- a/source/blender/freestyle/intern/stroke/BasicStrokeShaders.h
+++ b/source/blender/freestyle/intern/stroke/BasicStrokeShaders.h
@@ -218,51 +218,6 @@ public:
virtual int shade(Stroke& stroke) const;
};
-/*! [ Thickness Shader ].
-* Applys a pattern (texture) to vary thickness.
-* The new thicknesses are the result of the multiplication
-* of the pattern and the original thickness
-*/
-class ThicknessVariationPatternShader : public StrokeShader
-{
-public:
- /*! Builds the shader.
- * \param pattern_name
- * The texture file name.
- * \param iMinThickness
- * The minimum thickness we don't want to exceed.
- * \param iMaxThickness
- * The maximum thickness we don't want to exceed.
- * \param stretch
- * Tells whether the pattern texture must be stretched or repeted to fit the stroke.
- */
- ThicknessVariationPatternShader(const string pattern_name, float iMinThickness = 1.0f, float iMaxThickness = 5.0f,
- bool stretch = true);
-
- /*! Destructor.*/
- virtual ~ThicknessVariationPatternShader()
- {
- if (0 != _aThickness) {
- delete[] _aThickness;
- _aThickness = 0;
- }
- }
-
- virtual string getName() const
- {
- return "ThicknessVariationPatternShader";
- }
-
- /*! The shading method. */
- virtual int shade(Stroke& stroke) const;
-
-private:
- float *_aThickness; // array of thickness values, in % of the max (i.e comprised between 0 and 1)
- unsigned _size;
- float _minThickness;
- float _maxThickness;
- bool _stretch;
-};
/*! [ Thickness Shader ].
* Adds some noise to the stroke thickness.
@@ -389,44 +344,6 @@ public:
virtual int shade(Stroke& stroke) const;
};
-/*! [ Color Shader ].
- * Applys a pattern to vary original color.
- * The new color is the result of the multiplication of the pattern and the original color
- */
-class ColorVariationPatternShader : public StrokeShader
-{
-public:
- /*! Builds the shader from the pattern texture file name.
- * \param pattern_name
- * The file name of the texture file to use as pattern
- * \param stretch
- * Tells whether the texture must be strecthed or repeted to fit the stroke.
- */
- ColorVariationPatternShader(const string pattern_name, bool stretch = true);
-
- /*! Destructor */
- virtual ~ColorVariationPatternShader()
- {
- if (0 != _aVariation) {
- delete[] _aVariation;
- _aVariation = 0;
- }
- }
-
- virtual string getName() const
- {
- return "ColorVariationPatternShader";
- }
-
- /*! The shading method. */
- virtual int shade(Stroke& stroke) const;
-
-private:
- float *_aVariation; // array of coef values, in % of the max (i.e comprised between 0 and 1)
- unsigned _size;
- bool _stretch;
-};
-
/* [ Color Shader ].
* Assigns a color to the stroke depending on the material of the shape to which ot belongs to. (Disney shader)
*/
@@ -449,28 +366,6 @@ public:
virtual int shade(Stroke& stroke) const;
};
-class CalligraphicColorShader : public StrokeShader
-{
-private:
- /* UNUSED */
- // int _textureId;
- Vec2d _orientation;
-
-public:
- CalligraphicColorShader(const Vec2d &iOrientation) : StrokeShader()
- {
- _orientation = iOrientation;
- _orientation.normalize();
- }
-
- virtual string getName() const
- {
- return "CalligraphicColorShader";
- }
-
- virtual int shade(Stroke& stroke) const;
-};
-
/*! [ Color Shader ].
* Shader to add noise to the stroke colors.
*/
@@ -501,105 +396,6 @@ public:
};
//
-// Texture Shaders
-//
-///////////////////////////////////////////////////////////////////////////////
-/*! [ Texture Shader ].
-* Assigns a texture to the stroke in order to simulate
-* its marks system. This shader takes as input an integer value
-* telling which texture and blending mode to use among a set of
-* predefined textures.
-* Here are the different presets:
-* 0) -> /brushes/charcoalAlpha.bmp, HUMID_MEDIUM
-* 1) -> /brushes/washbrushAlpha.bmp, HUMID_MEDIUM
-* 2) -> /brushes/oil.bmp, HUMID_MEDIUM
-* 3) -> /brushes/oilnoblend.bmp, HUMID_MEDIUM
-* 4) -> /brushes/charcoalAlpha.bmp, DRY_MEDIUM
-* 5) -> /brushes/washbrushAlpha.bmp, DRY_MEDIUM
-* 6) -> /brushes/opaqueDryBrushAlpha.bmp, OPAQUE_MEDIUM
-* 7) -> /brushes/opaqueBrushAlpha.bmp, Stroke::OPAQUE_MEDIUM
-* Any other value will lead to the following preset:
-* default) -> /brushes/smoothAlpha.bmp, OPAQUE_MEDIUM.
-*/
-class TextureAssignerShader : public StrokeShader // FIXME
-{
-private:
- int _textureId;
-
-public:
- /*! Builds the shader.
- * \param id
- * The number of the preset to use.
- */
- TextureAssignerShader(int id) : StrokeShader()
- {
- _textureId = id;
- }
-
- virtual string getName() const
- {
- return "TextureAssignerShader";
- }
-
- /*! The shading method */
- virtual int shade(Stroke& stroke) const;
-};
-
-/*! [ Texture Shader ].
-* Assigns a texture and a blending mode to the stroke
-* in order to simulate its marks system.
-*/
-class StrokeTextureShader : public StrokeShader
-{
-private:
- string _texturePath;
- Stroke::MediumType _mediumType;
- bool _tips; // 0 or 1
-
-public:
- /*! Builds the shader from the texture file name and the blending mode to use.
- * \param textureFile
- * The the texture file name.
- * \attention The textures must be placed in the $FREESTYLE_DIR/data/textures/brushes directory.
- * \param mediumType
- * The medium type and therefore, the blending mode that must be used for the rendering of this stroke.
- * \param iTips
- * Tells whether the texture includes tips or not.
- * If it is the case, the texture image must respect the following format:
- * \verbatim
- * __________
- * | |
- * | A |
- * |__________|
- * | | |
- * | B | C |
- * |_____|____|
- *
- * \endverbatim
- * - A : The stroke's corpus texture
- * - B : The stroke's left extremity texture
- * - C : The stroke's right extremity texture
- */
- StrokeTextureShader(const string textureFile, Stroke::MediumType mediumType = Stroke::OPAQUE_MEDIUM,
- bool iTips = false)
- : StrokeShader()
- {
- _texturePath = textureFile;
- _mediumType = mediumType;
- _tips = iTips;
- }
-
- virtual string getName() const
- {
- return "StrokeTextureShader";
- }
-
- /*! The shading method */
- virtual int shade(Stroke& stroke) const;
-};
-
-
-//
// Geometry Shaders
//
///////////////////////////////////////////////////////////////////////////////
@@ -678,20 +474,6 @@ public:
virtual int shade(Stroke& stroke) const;
};
-// B-Spline stroke shader
-class BSplineShader: public StrokeShader
-{
-public:
- BSplineShader() : StrokeShader() {}
-
- virtual string getName() const
- {
- return "BSplineShader";
- }
-
- virtual int shade(Stroke& stroke) const;
-};
-
// Bezier curve stroke shader
/*! [ Geometry Shader ].
@@ -724,37 +506,6 @@ public:
virtual int shade(Stroke& stroke) const;
};
-/* Shader to inflate the curves. It keeps the extreme points positions and moves the other ones along the 2D normal.
- * The displacement value is proportional to the 2d curvature at the considered point (the higher the curvature,
- * the smaller the displacement) and to a value specified by the user.
- */
-class InflateShader : public StrokeShader
-{
-private:
- float _amount;
- float _curvatureThreshold;
-
-public:
- /*! Builds an inflate shader
- * \param iAmount
- * A multiplicative coefficient that acts on the amount and direction of displacement
- * \param iThreshold
- * The curves having a 2d curvature > iThreshold at one of their points is not inflated
- */
- InflateShader(float iAmount, float iThreshold) : StrokeShader()
- {
- _amount = iAmount;
- _curvatureThreshold = iThreshold;
- }
-
- virtual string getName() const
- {
- return "InflateShader";
- }
-
- /*! The shading method */
- virtual int shade(Stroke& stroke) const;
-};
/*! [ Geometry Shader ].
* Shader to modify the Stroke geometry so that it looks more "polygonal".
@@ -846,59 +597,6 @@ protected:
real _tipLength;
};
-/*! [ output Shader ].
- * streams the Stroke
- */
-class streamShader : public StrokeShader
-{
-public:
- /*! Destructor. */
- virtual ~streamShader() {}
-
- /*! Returns the string "streamShader".*/
- virtual string getName() const
- {
- return "streamShader";
- }
-
- /*! The shading method. */
- virtual int shade(Stroke& stroke) const;
-};
-
-/*! [ output Shader ].
- * streams the Stroke in a file
- */
-class fstreamShader : public StrokeShader
-{
-protected:
- mutable ofstream _stream;
-
-public:
- /*! Builds the shader from the output file name */
- fstreamShader(const char *iFileName) : StrokeShader()
- {
- _stream.open(iFileName);
- if (!_stream.is_open()) {
- cerr << "couldn't open file " << iFileName << endl;
- }
- }
-
- /*! Destructor. */
- virtual ~fstreamShader()
- {
- _stream.close();
- }
-
- /*! Returns the string "fstreamShader".*/
- virtual string getName() const
- {
- return "fstreamShader";
- }
-
- /*! The shading method. */
- virtual int shade(Stroke& stroke) const;
-};
-
/*! [ Texture Shader ].
* Shader to assign texture to the Stroke material.
*/
diff --git a/source/blender/freestyle/intern/stroke/Canvas.cpp b/source/blender/freestyle/intern/stroke/Canvas.cpp
index 69d37f61df9..63cb58b4042 100644
--- a/source/blender/freestyle/intern/stroke/Canvas.cpp
+++ b/source/blender/freestyle/intern/stroke/Canvas.cpp
@@ -425,7 +425,7 @@ void Canvas::loadMap(const char *iFileName, const char *iMapName, unsigned int i
stringstream filename;
filename << base;
filename << i << ".bmp";
- qtmp->ftype = BMP;
+ qtmp->ftype = IMB_FTYPE_BMP;
IMB_saveiff(qtmp, const_cast<char *>(filename.str().c_str()), 0);
}
diff --git a/source/blender/freestyle/intern/stroke/Canvas.h b/source/blender/freestyle/intern/stroke/Canvas.h
index b56b5f92c14..5919344b6e0 100644
--- a/source/blender/freestyle/intern/stroke/Canvas.h
+++ b/source/blender/freestyle/intern/stroke/Canvas.h
@@ -95,6 +95,7 @@ protected:
static const char *_MapsPath;
SteerableViewMap *_steerableViewMap;
bool _basic;
+ int stroke_count;
public:
/* Builds the Canvas */
@@ -213,7 +214,10 @@ public:
return false;
}
- int stroke_count;
+ inline int getStrokeCount() const
+ {
+ return stroke_count;
+ }
/*! modifiers */
inline void setSelectedFEdge(FEdge *iFEdge)
diff --git a/source/blender/freestyle/intern/stroke/Chain.cpp b/source/blender/freestyle/intern/stroke/Chain.cpp
index 7fd756472b0..0e8c2c9ae6f 100644
--- a/source/blender/freestyle/intern/stroke/Chain.cpp
+++ b/source/blender/freestyle/intern/stroke/Chain.cpp
@@ -59,6 +59,7 @@ void Chain::push_viewedge_back(ViewEdge *iViewEdge, bool orientation)
CurvePoint *cp = _Vertices.back(); // assumed to be instantiated as new CurvePoint(iSVertex, 0, 0.f);
SVertex *sv_first = (*vfirst);
FEdge *fe = _fedgeB->duplicate();
+ fe->setTemporary(true);
fe->setVertexB(sv_first);
fe->vertexA()->shape()->AddEdge(fe);
fe->vertexA()->AddFEdge(fe);
@@ -119,6 +120,7 @@ void Chain::push_viewedge_front(ViewEdge *iViewEdge, bool orientation)
SVertex *sv_curr = (*v);
FEdge *fe = (orientation) ? iViewEdge->fedgeA() : iViewEdge->fedgeB();
FEdge *fe2 = fe->duplicate();
+ fe2->setTemporary(true);
fe2->setVertexA(sv_curr);
fe2->setVertexB(sv_last);
sv_last->AddFEdge(fe2);
diff --git a/source/blender/freestyle/intern/stroke/Chain.h b/source/blender/freestyle/intern/stroke/Chain.h
index 95e825e270b..6cf3a7199bf 100644
--- a/source/blender/freestyle/intern/stroke/Chain.h
+++ b/source/blender/freestyle/intern/stroke/Chain.h
@@ -106,6 +106,10 @@ public:
{
return _splittingId;
}
+
+#ifdef WITH_CXX_GUARDEDALLOC
+ MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:Chain")
+#endif
};
} /* namespace Freestyle */
diff --git a/source/blender/freestyle/intern/stroke/ChainingIterators.h b/source/blender/freestyle/intern/stroke/ChainingIterators.h
index 5d05ed2776d..4ece24c5ecf 100644
--- a/source/blender/freestyle/intern/stroke/ChainingIterators.h
+++ b/source/blender/freestyle/intern/stroke/ChainingIterators.h
@@ -101,7 +101,7 @@ public:
return _internalIterator.isBegin();
}
- /*! Returns true if the current ViewEdge is is coming towards the iteration vertex. False otherwise. */
+ /*! Returns true if the current ViewEdge is coming towards the iteration vertex. False otherwise. */
bool isIncoming() const;
/*! Returns a *pointer* to the pointed ViewEdge. */
diff --git a/source/blender/freestyle/intern/stroke/Curve.cpp b/source/blender/freestyle/intern/stroke/Curve.cpp
index 32cfac016d6..69c5dcdfe28 100644
--- a/source/blender/freestyle/intern/stroke/Curve.cpp
+++ b/source/blender/freestyle/intern/stroke/Curve.cpp
@@ -25,6 +25,8 @@
* \date 11/01/2003
*/
+#include <stdio.h> /* printf */
+
#include "Curve.h"
#include "CurveIterators.h"
#include "CurveAdvancedIterators.h"
diff --git a/source/blender/freestyle/intern/stroke/Curve.h b/source/blender/freestyle/intern/stroke/Curve.h
index 6b799c921a4..726b238c74b 100644
--- a/source/blender/freestyle/intern/stroke/Curve.h
+++ b/source/blender/freestyle/intern/stroke/Curve.h
@@ -341,6 +341,10 @@ public:
real curvatureFredo() const;
Vec2d directionFredo() const;
#endif
+
+#ifdef WITH_CXX_GUARDEDALLOC
+ MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:CurvePoint")
+#endif
};
@@ -586,6 +590,10 @@ public:
* At each iteration a virtual temporary CurvePoint is created.
*/
virtual Interface0DIterator pointsEnd(float t = 0.0f);
+
+#ifdef WITH_CXX_GUARDEDALLOC
+ MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:Curve")
+#endif
};
} /* namespace Freestyle */
diff --git a/source/blender/freestyle/intern/stroke/Operators.cpp b/source/blender/freestyle/intern/stroke/Operators.cpp
index 427994f80f1..87ba34e8f42 100644
--- a/source/blender/freestyle/intern/stroke/Operators.cpp
+++ b/source/blender/freestyle/intern/stroke/Operators.cpp
@@ -1242,7 +1242,7 @@ error:
return -1;
}
-void Operators::reset()
+void Operators::reset(bool removeStrokes)
{
ViewMap *vm = ViewMap::getInstance();
if (!vm) {
@@ -1253,11 +1253,7 @@ void Operators::reset()
for (I1DContainer::iterator it = _current_chains_set.begin(); it != _current_chains_set.end(); ++it)
delete *it;
_current_chains_set.clear();
-#if 0
- _current_view_edges_set.insert(_current_view_edges_set.begin(),
- vm->ViewEdges().begin(),
- vm->ViewEdges().end());
-#else
+
ViewMap::viewedges_container& vedges = vm->ViewEdges();
ViewMap::viewedges_container::iterator ve = vedges.begin(), veend = vedges.end();
for (; ve != veend; ++ve) {
@@ -1265,9 +1261,9 @@ void Operators::reset()
continue;
_current_view_edges_set.push_back(*ve);
}
-#endif
_current_set = &_current_view_edges_set;
- _current_strokes_set.clear();
+ if (removeStrokes)
+ _current_strokes_set.clear();
}
} /* namespace Freestyle */
diff --git a/source/blender/freestyle/intern/stroke/Operators.h b/source/blender/freestyle/intern/stroke/Operators.h
index 59ebec57246..c7b0e3f8b81 100644
--- a/source/blender/freestyle/intern/stroke/Operators.h
+++ b/source/blender/freestyle/intern/stroke/Operators.h
@@ -259,7 +259,7 @@ public:
return &_current_strokes_set;
}
- static void reset();
+ static void reset(bool removeStrokes=true);
private:
Operators() {}
diff --git a/source/blender/freestyle/intern/stroke/Predicates1D.h b/source/blender/freestyle/intern/stroke/Predicates1D.h
index 46efeae9f12..05fc043822f 100644
--- a/source/blender/freestyle/intern/stroke/Predicates1D.h
+++ b/source/blender/freestyle/intern/stroke/Predicates1D.h
@@ -471,7 +471,7 @@ public:
}
/*! The () operator. */
- int operator()(Interface1D& i1, Interface1D& i2)
+ int operator()(Interface1D& /*i1*/, Interface1D& /*i2*/)
{
result = true;
return 0;
@@ -490,7 +490,7 @@ public:
}
/*! The () operator. */
- int operator()(Interface1D& i1, Interface1D& i2)
+ int operator()(Interface1D& /*i1*/, Interface1D& /*i2*/)
{
result = false;
return 0;
diff --git a/source/blender/freestyle/intern/stroke/Stroke.cpp b/source/blender/freestyle/intern/stroke/Stroke.cpp
index 863da069259..b4a3646edef 100644
--- a/source/blender/freestyle/intern/stroke/Stroke.cpp
+++ b/source/blender/freestyle/intern/stroke/Stroke.cpp
@@ -400,6 +400,7 @@ Stroke::Stroke()
}
_nodeTree = NULL;
_tips = false;
+ _rep = NULL;
}
Stroke::Stroke(const Stroke& iBrother)
@@ -427,6 +428,10 @@ Stroke::Stroke(const Stroke& iBrother)
}
_nodeTree = iBrother._nodeTree;
_tips = iBrother._tips;
+ if (iBrother._rep)
+ _rep = new StrokeRep(*(iBrother._rep));
+ else
+ _rep = NULL;
}
Stroke::~Stroke()
@@ -439,6 +444,10 @@ Stroke::~Stroke()
}
_ViewEdges.clear();
+ if (_rep) {
+ delete _rep;
+ _rep = NULL;
+ }
}
Stroke& Stroke::operator=(const Stroke& iBrother)
@@ -456,6 +465,12 @@ Stroke& Stroke::operator=(const Stroke& iBrother)
_id = iBrother._id;
_ViewEdges = iBrother._ViewEdges;
_sampling = iBrother._sampling;
+ if (_rep)
+ delete _rep;
+ if (iBrother._rep)
+ _rep = new StrokeRep(*(iBrother._rep));
+ else
+ _rep = NULL;
return *this;
}
@@ -737,12 +752,12 @@ Interface0DIterator Stroke::verticesEnd()
return ret;
}
-Interface0DIterator Stroke::pointsBegin(float t)
+Interface0DIterator Stroke::pointsBegin(float /*t*/)
{
return verticesBegin(); // FIXME
}
-Interface0DIterator Stroke::pointsEnd(float t)
+Interface0DIterator Stroke::pointsEnd(float /*t*/)
{
return verticesEnd();
}
@@ -757,14 +772,16 @@ void Stroke::ScaleThickness(float iFactor)
void Stroke::Render(const StrokeRenderer *iRenderer)
{
- StrokeRep rep(this);
- iRenderer->RenderStrokeRep(&rep);
+ if (!_rep)
+ _rep = new StrokeRep(this);
+ iRenderer->RenderStrokeRep(_rep);
}
void Stroke::RenderBasic(const StrokeRenderer *iRenderer)
{
- StrokeRep rep(this);
- iRenderer->RenderStrokeRepBasic(&rep);
+ if (!_rep)
+ _rep = new StrokeRep(this);
+ iRenderer->RenderStrokeRep(_rep);
}
Stroke::vertex_iterator Stroke::vertices_begin(float sampling)
diff --git a/source/blender/freestyle/intern/stroke/Stroke.h b/source/blender/freestyle/intern/stroke/Stroke.h
index 86c667a38b6..5f0b4eab309 100644
--- a/source/blender/freestyle/intern/stroke/Stroke.h
+++ b/source/blender/freestyle/intern/stroke/Stroke.h
@@ -474,6 +474,10 @@ public:
/* interface definition */
/* inherited */
+
+#ifdef WITH_CXX_GUARDEDALLOC
+ MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:StrokeVertex")
+#endif
};
@@ -545,6 +549,7 @@ private:
MTex *_mtex[MAX_MTEX];
bNodeTree *_nodeTree;
bool _tips;
+ StrokeRep *_rep;
Vec2r _extremityOrientations[2]; // the orientations of the first and last extermity
public:
@@ -862,6 +867,10 @@ public:
virtual Interface0DIterator pointsBegin(float t = 0.0f);
virtual Interface0DIterator pointsEnd(float t = 0.0f);
+
+#ifdef WITH_CXX_GUARDEDALLOC
+ MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:Stroke")
+#endif
};
diff --git a/source/blender/freestyle/intern/stroke/StrokeRep.cpp b/source/blender/freestyle/intern/stroke/StrokeRep.cpp
index f7857107006..ab06e207331 100644
--- a/source/blender/freestyle/intern/stroke/StrokeRep.cpp
+++ b/source/blender/freestyle/intern/stroke/StrokeRep.cpp
@@ -425,7 +425,7 @@ void Strip::cleanUpSingularities (const vector<StrokeVertex*>& iStrokeVertices)
Vec2r avP(0.0, 0.0);
for (j = i - timeSinceSingu1; j <= i; j++)
avP = Vec2r(avP + _vertices[2 * j]->point2d());
- avP = Vec2r( 1.0 / float(timeSinceSingu1 + 1) * avP);
+ avP = Vec2r(1.0 / float(timeSinceSingu1 + 1) * avP);
for (j = i - timeSinceSingu1; j <= i; j++)
_vertices[2 * j]->setPoint2d(avP);
//_vertex[2 * j] = _vertex[2 * i];
diff --git a/source/blender/freestyle/intern/system/BaseObject.h b/source/blender/freestyle/intern/system/BaseObject.h
index 8cabd9130b4..945c2c8d35e 100644
--- a/source/blender/freestyle/intern/system/BaseObject.h
+++ b/source/blender/freestyle/intern/system/BaseObject.h
@@ -46,7 +46,7 @@ public:
virtual ~BaseObject() {}
/*! At least makes a release on this.
- * The BaseObject::destroy method must be explicitely called at the end of any overloaded destroy
+ * The BaseObject::destroy method must be explicitly called at the end of any overloaded destroy
*/
virtual int destroy()
{
diff --git a/source/blender/freestyle/intern/system/PythonInterpreter.h b/source/blender/freestyle/intern/system/PythonInterpreter.h
index 60193590944..ddb79b2df0b 100644
--- a/source/blender/freestyle/intern/system/PythonInterpreter.h
+++ b/source/blender/freestyle/intern/system/PythonInterpreter.h
@@ -51,6 +51,8 @@ extern "C" {
#include "BKE_text.h"
#include "BPY_extern.h"
+
+#include "bpy_util.h"
}
namespace Freestyle {
@@ -105,6 +107,26 @@ public:
return 0;
}
+ int interpretString(const string& str, const string& name)
+ {
+ ReportList *reports = CTX_wm_reports(_context);
+
+ BKE_reports_clear(reports);
+
+ if (BPY_string_exec(_context, str.c_str()) != 0) {
+ BPy_errors_to_report(reports);
+ cerr << "\nError executing Python script from PythonInterpreter::interpretString" << endl;
+ cerr << "Name: " << name << endl;
+ cerr << "Errors: " << endl;
+ BKE_reports_print(reports, RPT_ERROR);
+ return 1;
+ }
+
+ BKE_reports_clear(reports);
+
+ return 0;
+ }
+
int interpretText(struct Text *text, const string& name)
{
ReportList *reports = CTX_wm_reports(_context);
diff --git a/source/blender/freestyle/intern/system/StringUtils.h b/source/blender/freestyle/intern/system/StringUtils.h
index 77b543c7886..e11798762e4 100644
--- a/source/blender/freestyle/intern/system/StringUtils.h
+++ b/source/blender/freestyle/intern/system/StringUtils.h
@@ -36,7 +36,8 @@
extern "C" {
#include "BKE_utildefines.h"
-#include "BLI_blenlib.h"
+#include "BLI_string.h"
+#include "BLI_path_util.h"
}
using namespace std;
diff --git a/source/blender/freestyle/intern/view_map/ArbitraryGridDensityProvider.cpp b/source/blender/freestyle/intern/view_map/ArbitraryGridDensityProvider.cpp
index 8bc7c0952a8..3243c4d1fb7 100644
--- a/source/blender/freestyle/intern/view_map/ArbitraryGridDensityProvider.cpp
+++ b/source/blender/freestyle/intern/view_map/ArbitraryGridDensityProvider.cpp
@@ -100,22 +100,22 @@ ArbitraryGridDensityProviderFactory::ArbitraryGridDensityProviderFactory(unsigne
ArbitraryGridDensityProviderFactory::~ArbitraryGridDensityProviderFactory() {}
-auto_ptr<GridDensityProvider> ArbitraryGridDensityProviderFactory::newGridDensityProvider(OccluderSource& source,
- const real proscenium[4])
+AutoPtr<GridDensityProvider> ArbitraryGridDensityProviderFactory::newGridDensityProvider(OccluderSource& source,
+ const real proscenium[4])
{
- return auto_ptr<GridDensityProvider>(new ArbitraryGridDensityProvider(source, proscenium, numCells));
+ return AutoPtr<GridDensityProvider>(new ArbitraryGridDensityProvider(source, proscenium, numCells));
}
-auto_ptr<GridDensityProvider>
+AutoPtr<GridDensityProvider>
ArbitraryGridDensityProviderFactory::newGridDensityProvider(OccluderSource& source, const BBox<Vec3r>& bbox,
const GridHelpers::Transform& transform)
{
- return auto_ptr<GridDensityProvider>(new ArbitraryGridDensityProvider(source, bbox, transform, numCells));
+ return AutoPtr<GridDensityProvider>(new ArbitraryGridDensityProvider(source, bbox, transform, numCells));
}
-auto_ptr<GridDensityProvider> ArbitraryGridDensityProviderFactory::newGridDensityProvider(OccluderSource& source)
+AutoPtr<GridDensityProvider> ArbitraryGridDensityProviderFactory::newGridDensityProvider(OccluderSource& source)
{
- return auto_ptr<GridDensityProvider>(new ArbitraryGridDensityProvider(source, numCells));
+ return AutoPtr<GridDensityProvider>(new ArbitraryGridDensityProvider(source, numCells));
}
} /* namespace Freestyle */
diff --git a/source/blender/freestyle/intern/view_map/ArbitraryGridDensityProvider.h b/source/blender/freestyle/intern/view_map/ArbitraryGridDensityProvider.h
index 652cb9b34b0..c7939d34da4 100644
--- a/source/blender/freestyle/intern/view_map/ArbitraryGridDensityProvider.h
+++ b/source/blender/freestyle/intern/view_map/ArbitraryGridDensityProvider.h
@@ -58,10 +58,10 @@ public:
ArbitraryGridDensityProviderFactory(unsigned numCells);
~ArbitraryGridDensityProviderFactory();
- auto_ptr<GridDensityProvider> newGridDensityProvider(OccluderSource& source, const real proscenium[4]);
- auto_ptr<GridDensityProvider> newGridDensityProvider(OccluderSource& source, const BBox<Vec3r>& bbox,
- const GridHelpers::Transform& transform);
- auto_ptr<GridDensityProvider> newGridDensityProvider(OccluderSource& source);
+ AutoPtr<GridDensityProvider> newGridDensityProvider(OccluderSource& source, const real proscenium[4]);
+ AutoPtr<GridDensityProvider> newGridDensityProvider(OccluderSource& source, const BBox<Vec3r>& bbox,
+ const GridHelpers::Transform& transform);
+ AutoPtr<GridDensityProvider> newGridDensityProvider(OccluderSource& source);
protected:
unsigned numCells;
diff --git a/source/blender/freestyle/intern/view_map/AutoPtrHelper.h b/source/blender/freestyle/intern/view_map/AutoPtrHelper.h
new file mode 100644
index 00000000000..17a43c184c7
--- /dev/null
+++ b/source/blender/freestyle/intern/view_map/AutoPtrHelper.h
@@ -0,0 +1,60 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __FREESTYLE_AUTOPTR_HELPER_H__
+#define __FREESTYLE_AUTOPTR_HELPER_H__
+
+/** \file blender/freestyle/intern/view_map/AutoPtrHelper.h
+ * \ingroup freestyle
+ * \brief Utility header for auto_ptr/unique_ptr selection
+ * \author Sergey Sharybin
+ * \date 2015-02-09
+ */
+
+#include <memory>
+
+namespace Freestyle {
+
+#if __cplusplus > 199711L
+template<typename T>
+class AutoPtr : public std::unique_ptr<T> {
+public:
+ AutoPtr() : std::unique_ptr<T>() {}
+ AutoPtr(T *ptr) : std::unique_ptr<T>(ptr) {}
+
+ /* TODO(sergey): Is there more clear way to do this? */
+ template<typename X>
+ AutoPtr(AutoPtr<X>& other) : std::unique_ptr<T>(other.get()) {
+ other.release();
+ }
+};
+#else
+template<typename T>
+class AutoPtr : public std::auto_ptr<T> {
+public:
+ AutoPtr() : std::auto_ptr<T>() {}
+ AutoPtr(T *ptr) : std::auto_ptr<T>(ptr) {}
+ AutoPtr(std::auto_ptr_ref<T> ref) : std::auto_ptr<T>(ref) {}
+};
+#endif
+
+} /* namespace Freestyle */
+
+#endif // __FREESTYLE_AUTOPTR_HELPER_H__
diff --git a/source/blender/freestyle/intern/view_map/AverageAreaGridDensityProvider.cpp b/source/blender/freestyle/intern/view_map/AverageAreaGridDensityProvider.cpp
index 952b9752a3e..b5e133ec441 100644
--- a/source/blender/freestyle/intern/view_map/AverageAreaGridDensityProvider.cpp
+++ b/source/blender/freestyle/intern/view_map/AverageAreaGridDensityProvider.cpp
@@ -121,22 +121,22 @@ AverageAreaGridDensityProviderFactory::AverageAreaGridDensityProviderFactory(rea
AverageAreaGridDensityProviderFactory::~AverageAreaGridDensityProviderFactory() {}
-auto_ptr<GridDensityProvider>
+AutoPtr<GridDensityProvider>
AverageAreaGridDensityProviderFactory::newGridDensityProvider(OccluderSource& source, const real proscenium[4])
{
- return auto_ptr<GridDensityProvider>(new AverageAreaGridDensityProvider(source, proscenium, sizeFactor));
+ return AutoPtr<GridDensityProvider>(new AverageAreaGridDensityProvider(source, proscenium, sizeFactor));
}
-auto_ptr<GridDensityProvider>
+AutoPtr<GridDensityProvider>
AverageAreaGridDensityProviderFactory::newGridDensityProvider(OccluderSource& source, const BBox<Vec3r>& bbox,
const GridHelpers::Transform& transform)
{
- return auto_ptr<GridDensityProvider>(new AverageAreaGridDensityProvider(source, bbox, transform, sizeFactor));
+ return AutoPtr<GridDensityProvider>(new AverageAreaGridDensityProvider(source, bbox, transform, sizeFactor));
}
-auto_ptr<GridDensityProvider> AverageAreaGridDensityProviderFactory::newGridDensityProvider(OccluderSource& source)
+AutoPtr<GridDensityProvider> AverageAreaGridDensityProviderFactory::newGridDensityProvider(OccluderSource& source)
{
- return auto_ptr<GridDensityProvider>(new AverageAreaGridDensityProvider(source, sizeFactor));
+ return AutoPtr<GridDensityProvider>(new AverageAreaGridDensityProvider(source, sizeFactor));
}
} /* namespace Freestyle */
diff --git a/source/blender/freestyle/intern/view_map/AverageAreaGridDensityProvider.h b/source/blender/freestyle/intern/view_map/AverageAreaGridDensityProvider.h
index d63557f5cda..2c58cc32da9 100644
--- a/source/blender/freestyle/intern/view_map/AverageAreaGridDensityProvider.h
+++ b/source/blender/freestyle/intern/view_map/AverageAreaGridDensityProvider.h
@@ -55,10 +55,10 @@ public:
AverageAreaGridDensityProviderFactory(real sizeFactor);
~AverageAreaGridDensityProviderFactory();
- auto_ptr<GridDensityProvider> newGridDensityProvider(OccluderSource& source, const real proscenium[4]);
- auto_ptr<GridDensityProvider> newGridDensityProvider(OccluderSource& source, const BBox<Vec3r>& bbox,
- const GridHelpers::Transform& transform);
- auto_ptr<GridDensityProvider> newGridDensityProvider(OccluderSource& source);
+ AutoPtr<GridDensityProvider> newGridDensityProvider(OccluderSource& source, const real proscenium[4]);
+ AutoPtr<GridDensityProvider> newGridDensityProvider(OccluderSource& source, const BBox<Vec3r>& bbox,
+ const GridHelpers::Transform& transform);
+ AutoPtr<GridDensityProvider> newGridDensityProvider(OccluderSource& source);
protected:
real sizeFactor;
diff --git a/source/blender/freestyle/intern/view_map/BoxGrid.cpp b/source/blender/freestyle/intern/view_map/BoxGrid.cpp
index f770bf6843f..ae22a26ec9b 100644
--- a/source/blender/freestyle/intern/view_map/BoxGrid.cpp
+++ b/source/blender/freestyle/intern/view_map/BoxGrid.cpp
@@ -71,18 +71,18 @@ void BoxGrid::Cell::indexPolygons()
// Iterator
//////////////////
-BoxGrid::Iterator::Iterator (BoxGrid& grid, Vec3r& center, real epsilon)
+BoxGrid::Iterator::Iterator (BoxGrid& grid, Vec3r& center, real /*epsilon*/)
: _target(grid.transform(center)), _foundOccludee(false)
{
// Find target cell
_cell = grid.findCell(_target);
- #if BOX_GRID_LOGGING
+#if BOX_GRID_LOGGING
if (G.debug & G_DEBUG_FREESTYLE) {
cout << "Searching for occluders of edge centered at " << _target << " in cell [" <<
1_cell->boundary[0] << ", " << _cell->boundary[1] << ", " << _cell->boundary[2] <<
", " << _cell->boundary[3] << "] (" << _cell->faces.size() << " occluders)" << endl;
}
- #endif
+#endif
// Set iterator
_current = _cell->faces.begin();
@@ -122,7 +122,7 @@ BoxGrid::BoxGrid(OccluderSource& source, GridDensityProvider& density, ViewMap *
BoxGrid::~BoxGrid() {}
-void BoxGrid::assignCells (OccluderSource& source, GridDensityProvider& density, ViewMap *viewMap)
+void BoxGrid::assignCells (OccluderSource& /*source*/, GridDensityProvider& density, ViewMap *viewMap)
{
_cellSize = density.cellSize();
_cellsX = density.cellsX();
diff --git a/source/blender/freestyle/intern/view_map/BoxGrid.h b/source/blender/freestyle/intern/view_map/BoxGrid.h
index 0ef4ce37b11..b8e751d041d 100644
--- a/source/blender/freestyle/intern/view_map/BoxGrid.h
+++ b/source/blender/freestyle/intern/view_map/BoxGrid.h
@@ -303,11 +303,11 @@ inline void BoxGrid::Iterator::reportDepth(Vec3r origin, Vec3r u, real t)
// The reported depth is the length of a ray in camera space
// We need to convert it into a Z-value in grid space
real depth = -(origin + (u * t))[2];
- #if BOX_GRID_LOGGING
+#if BOX_GRID_LOGGING
if (G.debug & G_DEBUG_FREESTYLE) {
std::cout << "\t\tReporting depth of occluder/ee: " << depth;
}
- #endif
+#endif
if (depth > _target[2]) {
#if BOX_GRID_LOGGING
if (G.debug & G_DEBUG_FREESTYLE) {
diff --git a/source/blender/freestyle/intern/view_map/FEdgeXDetector.cpp b/source/blender/freestyle/intern/view_map/FEdgeXDetector.cpp
index 9c9cd88f188..85c6390cb9e 100644
--- a/source/blender/freestyle/intern/view_map/FEdgeXDetector.cpp
+++ b/source/blender/freestyle/intern/view_map/FEdgeXDetector.cpp
@@ -39,7 +39,9 @@ namespace Freestyle {
void FEdgeXDetector::processShapes(WingedEdge& we)
{
bool progressBarDisplay = false;
+#if 0
Vec3r Min, Max;
+#endif
vector<WShape*> wshapes = we.getWShapes();
WXShape *wxs;
@@ -55,22 +57,24 @@ void FEdgeXDetector::processShapes(WingedEdge& we)
if (_pRenderMonitor && _pRenderMonitor->testBreak())
break;
wxs = dynamic_cast<WXShape*>(*it);
+#if 0
wxs->bbox(Min, Max);
_bbox_diagonal = (Max - Min).norm();
+#endif
if (_changes) {
vector<WFace*>& wfaces = wxs->GetFaceList();
for (vector<WFace*>::iterator wf = wfaces.begin(), wfend = wfaces.end(); wf != wfend; ++wf) {
WXFace *wxf = dynamic_cast<WXFace*>(*wf);
wxf->Clear();
}
- _computeViewIndependant = true;
+ _computeViewIndependent = true;
}
- else if (!(wxs)->getComputeViewIndependantFlag()) {
+ else if (!(wxs)->getComputeViewIndependentFlag()) {
wxs->Reset();
- _computeViewIndependant = false;
+ _computeViewIndependent = false;
}
else {
- _computeViewIndependant = true;
+ _computeViewIndependent = true;
}
preProcessShape(wxs);
if (progressBarDisplay)
@@ -97,8 +101,8 @@ void FEdgeXDetector::processShapes(WingedEdge& we)
if (progressBarDisplay)
_pProgressBar->setProgress(_pProgressBar->getProgress() + 1);
- wxs->setComputeViewIndependantFlag(false);
- _computeViewIndependant = false;
+ wxs->setComputeViewIndependentFlag(false);
+ _computeViewIndependent = false;
_changes = false;
// reset user data
@@ -117,7 +121,11 @@ void FEdgeXDetector::preProcessShape(WXShape *iWShape)
_minKr = FLT_MAX;
_maxKr = -FLT_MAX;
_nPoints = 0;
+#if 0
_meanEdgeSize = iWShape->getMeanEdgeSize();
+#else
+ _meanEdgeSize = iWShape->ComputeMeanEdgeSize();
+#endif
vector<WFace*>& wfaces = iWShape->GetFaceList();
vector<WFace*>::iterator f, fend;
@@ -140,16 +148,16 @@ void FEdgeXDetector::preProcessShape(WXShape *iWShape)
void FEdgeXDetector::preProcessFace(WXFace *iFace)
{
- Vec3r firstPoint = iFace->GetVertex(0)->GetVertex();
- Vec3r N = iFace->GetNormal();
+ Vec3f firstPoint = iFace->GetVertex(0)->GetVertex();
+ Vec3f N = iFace->GetNormal();
// Compute the dot product between V (=_Viewpoint - firstPoint) and N:
- Vec3r V;
+ Vec3f V;
if (_orthographicProjection) {
- V = Vec3r(0.0, 0.0, _Viewpoint.z() - firstPoint.z());
+ V = Vec3f(0.0f, 0.0f, _Viewpoint.z() - firstPoint.z());
}
else {
- V = Vec3r(_Viewpoint - firstPoint);
+ V = Vec3f(_Viewpoint - firstPoint);
}
N.normalize();
V.normalize();
@@ -160,7 +168,7 @@ void FEdgeXDetector::preProcessFace(WXFace *iFace)
iFace->setZ(iFace->center().z() - _Viewpoint.z());
}
else {
- Vec3r dist_vec(iFace->center() - _Viewpoint);
+ Vec3f dist_vec(iFace->center() - _Viewpoint);
iFace->setZ(dist_vec.norm());
}
}
@@ -187,8 +195,8 @@ void FEdgeXDetector::computeCurvatures(WXVertex *vertex)
CurvatureInfo *C;
float radius = _sphereRadius * _meanEdgeSize;
- // view independant stuff
- if (_computeViewIndependant) {
+ // view independent stuff
+ if (_computeViewIndependent) {
C = new CurvatureInfo();
vertex->setCurvatures(C);
OGF::NormalCycle ncycle;
@@ -265,33 +273,33 @@ void FEdgeXDetector::processSilhouetteShape(WXShape *iWShape)
void FEdgeXDetector::ProcessSilhouetteFace(WXFace *iFace)
{
// SILHOUETTE LAYER
- Vec3r normal;
+ Vec3f normal;
// Compute the dot products between View direction and N at each vertex of the face:
- Vec3r point;
+ Vec3f point;
int closestPointId = 0;
- real dist, minDist = FLT_MAX;
+ float dist, minDist = FLT_MAX;
int numVertices = iFace->numberOfVertices();
WXFaceLayer *faceLayer = new WXFaceLayer(iFace, Nature::SILHOUETTE, true);
for (int i = 0; i < numVertices; i++) {
point = iFace->GetVertex(i)->GetVertex();
normal = iFace->GetVertexNormal(i);
normal.normalize();
- Vec3r V;
+ Vec3f V;
if (_orthographicProjection) {
- V = Vec3r(0.0, 0.0, _Viewpoint.z() - point.z());
+ V = Vec3f(0.0f, 0.0f, _Viewpoint.z() - point.z());
}
else {
- V = Vec3r(_Viewpoint - point);
+ V = Vec3f(_Viewpoint - point);
}
V.normalize();
- real d = normal * V;
+ float d = normal * V;
faceLayer->PushDotP(d);
// Find the point the closest to the viewpoint
if (_orthographicProjection) {
dist = point.z() - _Viewpoint.z();
}
else {
- Vec3r dist_vec(point - _Viewpoint);
+ Vec3f dist_vec(point - _Viewpoint);
dist = dist_vec.norm();
}
if (dist < minDist) {
@@ -333,7 +341,7 @@ void FEdgeXDetector::ProcessSilhouetteEdge(WXEdge *iEdge)
/////////
void FEdgeXDetector::processBorderShape(WXShape *iWShape)
{
- if (!_computeViewIndependant)
+ if (!_computeViewIndependent)
return;
// Make a pass on the edges to detect the BORDER
vector<WEdge*>::iterator we, weend;
@@ -358,7 +366,7 @@ void FEdgeXDetector::ProcessBorderEdge(WXEdge *iEdge)
/////////
void FEdgeXDetector::processCreaseShape(WXShape *iWShape)
{
- if (!_computeViewIndependant)
+ if (!_computeViewIndependent)
return;
// Make a pass on the edges to detect the CREASE
@@ -390,7 +398,7 @@ void FEdgeXDetector::processRidgesAndValleysShape(WXShape *iWShape)
// Don't forget to add the built layer to the face at the end of the ProcessFace:
//iFace->AddSmoothLayer(faceLayer);
- if (!_computeViewIndependant)
+ if (!_computeViewIndependent)
return;
// Here the curvatures must already have been computed
@@ -416,6 +424,7 @@ void FEdgeXDetector::ProcessRidgeFace(WXFace *iFace)
flayer->PushDotP(wxv->curvatures()->K1);
}
+#if 0 // XXX fabs(flayer->dotP(i)) < threshold cannot be true
real threshold = 0;
//real threshold = _maxK1 - (_maxK1 - _meanK1) / 20.0;
@@ -428,6 +437,7 @@ void FEdgeXDetector::ProcessRidgeFace(WXFace *iFace)
flayer->ReplaceDotP(2, 0);
}
}
+#endif
}
#if 0
@@ -497,7 +507,7 @@ void FEdgeXDetector::ProcessRidgeFace(WXFace *iFace)
}
}
}
- // Once we have K1 along the the ppal direction compute the derivative : K1b - K1a put it in DotP
+ // Once we have K1 along the ppal direction compute the derivative : K1b - K1a put it in DotP
//real d = fabs(K1_b) - fabs(K1_a);
real d = 0;
real threshold = _meanK1 + (_maxK1 - _meanK1) / 7.0;
@@ -684,7 +694,7 @@ void FEdgeXDetector::postProcessSuggestiveContourFace(WXFace *iFace)
////////////////////
void FEdgeXDetector::processMaterialBoundaryShape(WXShape *iWShape)
{
- if (!_computeViewIndependant)
+ if (!_computeViewIndependent)
return;
// Make a pass on the edges to detect material boundaries
vector<WEdge*>::iterator we, weend;
diff --git a/source/blender/freestyle/intern/view_map/FEdgeXDetector.h b/source/blender/freestyle/intern/view_map/FEdgeXDetector.h
index 8adf685a6eb..cbb47d387fb 100644
--- a/source/blender/freestyle/intern/view_map/FEdgeXDetector.h
+++ b/source/blender/freestyle/intern/view_map/FEdgeXDetector.h
@@ -57,8 +57,10 @@ public:
{
_pProgressBar = NULL;
_pRenderMonitor = NULL;
- _computeViewIndependant = true;
+ _computeViewIndependent = true;
+#if 0
_bbox_diagonal = 1.0;
+#endif
_meanEdgeSize = 0;
_computeRidgesAndValleys = true;
_computeSuggestiveContours = true;
@@ -96,7 +98,7 @@ public:
* a crease edge if the angle between two faces sharing the edge is smaller than the given threshold.
*/
// XXX angle should be in radian...
- inline void setCreaseAngle(real angle)
+ inline void setCreaseAngle(float angle)
{
if (angle < 0.0)
angle = 0.0;
@@ -126,7 +128,7 @@ public:
* \param dkr
* The minimal derivative of the radial curvature
*/
- inline void setSuggestiveContourKrDerivativeEpsilon(real dkr)
+ inline void setSuggestiveContourKrDerivativeEpsilon(float dkr)
{
if (dkr != _kr_derivative_epsilon) {
_kr_derivative_epsilon = dkr;
@@ -146,7 +148,7 @@ public:
virtual void buildSmoothEdges(WXShape *iShape);
/*! Sets the current viewpoint */
- inline void setViewpoint(const Vec3r& ivp)
+ inline void setViewpoint(const Vec3f& ivp)
{
_Viewpoint = ivp;
}
@@ -191,7 +193,7 @@ public:
* \param r
* The radius of the sphere expressed as a ratio of the mean edge size
*/
- inline void setSphereRadius(real r)
+ inline void setSphereRadius(float r)
{
if (r != _sphereRadius) {
_sphereRadius = r;
@@ -210,10 +212,12 @@ public:
}
protected:
- Vec3r _Viewpoint;
+ Vec3f _Viewpoint;
+#if 0
real _bbox_diagonal; // diagonal of the current processed shape bbox
+#endif
//oldtmp values
- bool _computeViewIndependant;
+ bool _computeViewIndependent;
real _meanK1;
real _meanKr;
real _minK1;
@@ -229,11 +233,11 @@ protected:
bool _computeMaterialBoundaries;
bool _faceSmoothness;
bool _faceMarks;
- real _sphereRadius; // expressed as a ratio of the mean edge size
- real _creaseAngle; // [-1, 1] compared with the inner product of face normals
+ float _sphereRadius; // expressed as a ratio of the mean edge size
+ float _creaseAngle; // [-1, 1] compared with the inner product of face normals
bool _changes;
- real _kr_derivative_epsilon;
+ float _kr_derivative_epsilon;
ProgressBar *_pProgressBar;
RenderMonitor *_pRenderMonitor;
diff --git a/source/blender/freestyle/intern/view_map/GridDensityProvider.h b/source/blender/freestyle/intern/view_map/GridDensityProvider.h
index 272d64dd6de..b49e74d6402 100644
--- a/source/blender/freestyle/intern/view_map/GridDensityProvider.h
+++ b/source/blender/freestyle/intern/view_map/GridDensityProvider.h
@@ -32,6 +32,7 @@
#include <algorithm>
#include <memory>
+#include "AutoPtrHelper.h"
#include "OccluderSource.h"
#include "../geometry/BBox.h"
@@ -148,12 +149,12 @@ class GridDensityProviderFactory
public:
GridDensityProviderFactory() {}
- virtual auto_ptr<GridDensityProvider> newGridDensityProvider(OccluderSource& source, const real proscenium[4]) = 0;
+ virtual AutoPtr<GridDensityProvider> newGridDensityProvider(OccluderSource& source, const real proscenium[4]) = 0;
- virtual auto_ptr<GridDensityProvider> newGridDensityProvider(OccluderSource& source, const BBox<Vec3r>& bbox,
- const GridHelpers::Transform& transform) = 0;
+ virtual AutoPtr<GridDensityProvider> newGridDensityProvider(OccluderSource& source, const BBox<Vec3r>& bbox,
+ const GridHelpers::Transform& transform) = 0;
- virtual auto_ptr<GridDensityProvider> newGridDensityProvider(OccluderSource& source) = 0;
+ virtual AutoPtr<GridDensityProvider> newGridDensityProvider(OccluderSource& source) = 0;
virtual ~GridDensityProviderFactory () {}
diff --git a/source/blender/freestyle/intern/view_map/HeuristicGridDensityProviderFactory.cpp b/source/blender/freestyle/intern/view_map/HeuristicGridDensityProviderFactory.cpp
index 00f5cc90cc4..18edc82b096 100644
--- a/source/blender/freestyle/intern/view_map/HeuristicGridDensityProviderFactory.cpp
+++ b/source/blender/freestyle/intern/view_map/HeuristicGridDensityProviderFactory.cpp
@@ -36,45 +36,45 @@ HeuristicGridDensityProviderFactory::HeuristicGridDensityProviderFactory(real si
HeuristicGridDensityProviderFactory::~HeuristicGridDensityProviderFactory() {}
-auto_ptr<GridDensityProvider>
+AutoPtr<GridDensityProvider>
HeuristicGridDensityProviderFactory::newGridDensityProvider(OccluderSource& source, const real proscenium[4])
{
- auto_ptr<AverageAreaGridDensityProvider> avg(new AverageAreaGridDensityProvider(source, proscenium, sizeFactor));
- auto_ptr<Pow23GridDensityProvider> p23(new Pow23GridDensityProvider(source, proscenium, numFaces));
+ AutoPtr<AverageAreaGridDensityProvider> avg(new AverageAreaGridDensityProvider(source, proscenium, sizeFactor));
+ AutoPtr<Pow23GridDensityProvider> p23(new Pow23GridDensityProvider(source, proscenium, numFaces));
if (avg->cellSize() > p23->cellSize()) {
- return (auto_ptr<GridDensityProvider>) p23;
+ return (AutoPtr<GridDensityProvider>) p23;
}
else {
- return (auto_ptr<GridDensityProvider>) avg;
+ return (AutoPtr<GridDensityProvider>) avg;
}
}
-auto_ptr<GridDensityProvider>
+AutoPtr<GridDensityProvider>
HeuristicGridDensityProviderFactory::newGridDensityProvider(OccluderSource& source, const BBox<Vec3r>& bbox,
const GridHelpers::Transform& transform)
{
- auto_ptr<AverageAreaGridDensityProvider> avg(new AverageAreaGridDensityProvider(source, bbox,
- transform, sizeFactor));
- auto_ptr<Pow23GridDensityProvider> p23(new Pow23GridDensityProvider(source, bbox, transform, numFaces));
+ AutoPtr<AverageAreaGridDensityProvider> avg(new AverageAreaGridDensityProvider(source, bbox,
+ transform, sizeFactor));
+ AutoPtr<Pow23GridDensityProvider> p23(new Pow23GridDensityProvider(source, bbox, transform, numFaces));
if (avg->cellSize() > p23->cellSize()) {
- return (auto_ptr<GridDensityProvider>) p23;
+ return (AutoPtr<GridDensityProvider>) p23;
}
else {
- return (auto_ptr<GridDensityProvider>) avg;
+ return (AutoPtr<GridDensityProvider>) avg;
}
}
-auto_ptr<GridDensityProvider> HeuristicGridDensityProviderFactory::newGridDensityProvider(OccluderSource& source)
+AutoPtr<GridDensityProvider> HeuristicGridDensityProviderFactory::newGridDensityProvider(OccluderSource& source)
{
real proscenium[4];
GridDensityProvider::calculateOptimalProscenium(source, proscenium);
- auto_ptr<AverageAreaGridDensityProvider> avg(new AverageAreaGridDensityProvider(source, proscenium, sizeFactor));
- auto_ptr<Pow23GridDensityProvider> p23(new Pow23GridDensityProvider(source, proscenium, numFaces));
+ AutoPtr<AverageAreaGridDensityProvider> avg(new AverageAreaGridDensityProvider(source, proscenium, sizeFactor));
+ AutoPtr<Pow23GridDensityProvider> p23(new Pow23GridDensityProvider(source, proscenium, numFaces));
if (avg->cellSize() > p23->cellSize()) {
- return (auto_ptr<GridDensityProvider>) p23;
+ return (AutoPtr<GridDensityProvider>) p23;
}
else {
- return (auto_ptr<GridDensityProvider>) avg;
+ return (AutoPtr<GridDensityProvider>) avg;
}
}
diff --git a/source/blender/freestyle/intern/view_map/HeuristicGridDensityProviderFactory.h b/source/blender/freestyle/intern/view_map/HeuristicGridDensityProviderFactory.h
index 65f2af6df2f..9414e4931f5 100644
--- a/source/blender/freestyle/intern/view_map/HeuristicGridDensityProviderFactory.h
+++ b/source/blender/freestyle/intern/view_map/HeuristicGridDensityProviderFactory.h
@@ -42,10 +42,10 @@ public:
HeuristicGridDensityProviderFactory(real sizeFactor, unsigned numFaces);
~HeuristicGridDensityProviderFactory();
- auto_ptr<GridDensityProvider> newGridDensityProvider(OccluderSource& source, const real proscenium[4]);
- auto_ptr<GridDensityProvider> newGridDensityProvider(OccluderSource& source, const BBox<Vec3r>& bbox,
- const GridHelpers::Transform& transform);
- auto_ptr<GridDensityProvider> newGridDensityProvider(OccluderSource& source);
+ AutoPtr<GridDensityProvider> newGridDensityProvider(OccluderSource& source, const real proscenium[4]);
+ AutoPtr<GridDensityProvider> newGridDensityProvider(OccluderSource& source, const BBox<Vec3r>& bbox,
+ const GridHelpers::Transform& transform);
+ AutoPtr<GridDensityProvider> newGridDensityProvider(OccluderSource& source);
protected:
real sizeFactor;
diff --git a/source/blender/freestyle/intern/view_map/Interface1D.cpp b/source/blender/freestyle/intern/view_map/Interface1D.cpp
index 985310e52b5..f4abad11479 100644
--- a/source/blender/freestyle/intern/view_map/Interface1D.cpp
+++ b/source/blender/freestyle/intern/view_map/Interface1D.cpp
@@ -42,13 +42,13 @@ Interface0DIterator Interface1D::verticesEnd()
return Interface0DIterator();
}
-Interface0DIterator Interface1D::pointsBegin(float t)
+Interface0DIterator Interface1D::pointsBegin(float /*t*/)
{
PyErr_SetString(PyExc_TypeError, "method pointsBegin() not properly overridden");
return Interface0DIterator();
}
-Interface0DIterator Interface1D::pointsEnd(float t)
+Interface0DIterator Interface1D::pointsEnd(float /*t*/)
{
PyErr_SetString(PyExc_TypeError, "method pointsEnd() not properly overridden");
return Interface0DIterator();
diff --git a/source/blender/freestyle/intern/view_map/Pow23GridDensityProvider.cpp b/source/blender/freestyle/intern/view_map/Pow23GridDensityProvider.cpp
index e3bb9b87ecc..8dff079e0cf 100644
--- a/source/blender/freestyle/intern/view_map/Pow23GridDensityProvider.cpp
+++ b/source/blender/freestyle/intern/view_map/Pow23GridDensityProvider.cpp
@@ -99,22 +99,22 @@ Pow23GridDensityProviderFactory::Pow23GridDensityProviderFactory(unsigned numFac
Pow23GridDensityProviderFactory::~Pow23GridDensityProviderFactory () {}
-auto_ptr<GridDensityProvider>
+AutoPtr<GridDensityProvider>
Pow23GridDensityProviderFactory::newGridDensityProvider(OccluderSource& source, const real proscenium[4])
{
- return auto_ptr<GridDensityProvider>(new Pow23GridDensityProvider(source, proscenium, numFaces));
+ return AutoPtr<GridDensityProvider>(new Pow23GridDensityProvider(source, proscenium, numFaces));
}
-auto_ptr<GridDensityProvider>
+AutoPtr<GridDensityProvider>
Pow23GridDensityProviderFactory::newGridDensityProvider(OccluderSource& source, const BBox<Vec3r>& bbox,
const GridHelpers::Transform& transform)
{
- return auto_ptr<GridDensityProvider>(new Pow23GridDensityProvider(source, bbox, transform, numFaces));
+ return AutoPtr<GridDensityProvider>(new Pow23GridDensityProvider(source, bbox, transform, numFaces));
}
-auto_ptr<GridDensityProvider> Pow23GridDensityProviderFactory::newGridDensityProvider(OccluderSource& source)
+AutoPtr<GridDensityProvider> Pow23GridDensityProviderFactory::newGridDensityProvider(OccluderSource& source)
{
- return auto_ptr<GridDensityProvider>(new Pow23GridDensityProvider(source, numFaces));
+ return AutoPtr<GridDensityProvider>(new Pow23GridDensityProvider(source, numFaces));
}
} /* namespace Freestyle */
diff --git a/source/blender/freestyle/intern/view_map/Pow23GridDensityProvider.h b/source/blender/freestyle/intern/view_map/Pow23GridDensityProvider.h
index 7f646790ab6..5dfa9cdfc87 100644
--- a/source/blender/freestyle/intern/view_map/Pow23GridDensityProvider.h
+++ b/source/blender/freestyle/intern/view_map/Pow23GridDensityProvider.h
@@ -58,10 +58,10 @@ public:
Pow23GridDensityProviderFactory(unsigned numFaces);
~Pow23GridDensityProviderFactory();
- auto_ptr<GridDensityProvider> newGridDensityProvider(OccluderSource& source, const real proscenium[4]);
- auto_ptr<GridDensityProvider> newGridDensityProvider(OccluderSource& source, const BBox<Vec3r>& bbox,
- const GridHelpers::Transform& transform);
- auto_ptr<GridDensityProvider> newGridDensityProvider(OccluderSource& source);
+ AutoPtr<GridDensityProvider> newGridDensityProvider(OccluderSource& source, const real proscenium[4]);
+ AutoPtr<GridDensityProvider> newGridDensityProvider(OccluderSource& source, const BBox<Vec3r>& bbox,
+ const GridHelpers::Transform& transform);
+ AutoPtr<GridDensityProvider> newGridDensityProvider(OccluderSource& source);
protected:
unsigned numFaces;
diff --git a/source/blender/freestyle/intern/view_map/Silhouette.h b/source/blender/freestyle/intern/view_map/Silhouette.h
index d838b98c1a8..0b20c9f6aa2 100644
--- a/source/blender/freestyle/intern/view_map/Silhouette.h
+++ b/source/blender/freestyle/intern/view_map/Silhouette.h
@@ -378,6 +378,17 @@ public:
_FEdges.push_back(iFEdge);
}
+ /*! Remove an FEdge from the list of edges emanating from this SVertex. */
+ inline void RemoveFEdge(FEdge *iFEdge)
+ {
+ for (vector<FEdge *>::iterator fe = _FEdges.begin(), fend = _FEdges.end(); fe != fend; fe++) {
+ if (iFEdge == (*fe)) {
+ _FEdges.erase(fe);
+ break;
+ }
+ }
+ }
+
/* replaces edge 1 by edge 2 in the list of edges */
inline void Replace(FEdge *e1, FEdge *e2)
{
@@ -441,6 +452,10 @@ public:
/*! angle in radians */
inline real curvature2d_as_angle() const;
#endif
+
+#ifdef WITH_CXX_GUARDEDALLOC
+ MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:SVertex")
+#endif
};
/**********************************/
@@ -518,6 +533,8 @@ protected:
bool _isInImage;
+ bool _isTemporary;
+
public:
/*! A field that can be used by the user to store any data.
* This field must be reseted afterwards using ResetUserData().
@@ -538,6 +555,7 @@ public:
_occludeeEmpty = true;
_isSmooth = false;
_isInImage = true;
+ _isTemporary = false;
}
/*! Builds an FEdge going from vA to vB. */
@@ -554,6 +572,7 @@ public:
_occludeeEmpty = true;
_isSmooth = false;
_isInImage = true;
+ _isTemporary = false;
}
/*! Copy constructor */
@@ -573,6 +592,7 @@ public:
_occludeeEmpty = iBrother._occludeeEmpty;
_isSmooth = iBrother._isSmooth;
_isInImage = iBrother._isInImage;
+ _isTemporary = iBrother._isTemporary;
iBrother.userdata = this;
userdata = 0;
}
@@ -708,6 +728,11 @@ public:
return _isInImage;
}
+ inline bool isTemporary() const
+ {
+ return _isTemporary;
+ }
+
/* modifiers */
/*! Sets the first SVertex. */
inline void setVertexA(SVertex *vA)
@@ -803,6 +828,11 @@ public:
_isInImage = iFlag;
}
+ inline void setTemporary(bool iFlag)
+ {
+ _isTemporary = iFlag;
+ }
+
/* checks whether two FEdge have a common vertex.
* Returns a pointer on the common vertex if it exists, NULL otherwise.
*/
@@ -931,6 +961,10 @@ public:
* The sampling with which we want to iterate over points of this FEdge.
*/
virtual inline Interface0DIterator pointsEnd(float t = 0.0f);
+
+#ifdef WITH_CXX_GUARDEDALLOC
+ MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:FEdge")
+#endif
};
//
@@ -1088,12 +1122,12 @@ Interface0DIterator FEdge::verticesEnd()
return ret;
}
-Interface0DIterator FEdge::pointsBegin(float t)
+Interface0DIterator FEdge::pointsBegin(float /*t*/)
{
return verticesBegin();
}
-Interface0DIterator FEdge::pointsEnd(float t)
+Interface0DIterator FEdge::pointsEnd(float /*t*/)
{
return verticesEnd();
}
@@ -1241,6 +1275,10 @@ public:
{
_bFaceMark = iFaceMark;
}
+
+#ifdef WITH_CXX_GUARDEDALLOC
+ MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:FEdgeSharp")
+#endif
};
/*! Class defining a smooth edge. This kind of edge typically runs across a face of the input mesh. It can be
@@ -1353,6 +1391,10 @@ public:
{
_FrsMaterialIndex = i;
}
+
+#ifdef WITH_CXX_GUARDEDALLOC
+ MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:FEdgeSmooth")
+#endif
};
@@ -1373,7 +1415,7 @@ private:
vector<SVertex*> _verticesList; // list of all vertices
vector<FEdge*> _edgesList; // list of all edges
Id _Id;
- string _Name;
+ const char *_Name;
BBox<Vec3r> _BBox;
vector<FrsMaterial> _FrsMaterials;
@@ -1393,6 +1435,7 @@ public:
userdata = NULL;
_importance = 0.0f;
_ViewShape = NULL;
+ _Name = NULL;
}
/*! Copy constructor */
@@ -1845,7 +1888,7 @@ public:
}
/*! Returns the name of the Shape. */
- inline const string& getName() const
+ inline const char *getName() const
{
return _Name;
}
@@ -1858,7 +1901,7 @@ public:
}
/*! Sets the name of the shape.*/
- inline void setName(const string& name)
+ inline void setName(const char *name)
{
_Name = name;
}
diff --git a/source/blender/freestyle/intern/view_map/SphericalGrid.cpp b/source/blender/freestyle/intern/view_map/SphericalGrid.cpp
index 60ad7daea0a..10c88190cb3 100644
--- a/source/blender/freestyle/intern/view_map/SphericalGrid.cpp
+++ b/source/blender/freestyle/intern/view_map/SphericalGrid.cpp
@@ -72,18 +72,18 @@ void SphericalGrid::Cell::indexPolygons()
// Iterator
//////////////////
-SphericalGrid::Iterator::Iterator(SphericalGrid& grid, Vec3r& center, real epsilon)
+SphericalGrid::Iterator::Iterator(SphericalGrid& grid, Vec3r& center, real /*epsilon*/)
: _target(SphericalGrid::Transform::sphericalProjection(center)), _foundOccludee(false)
{
// Find target cell
_cell = grid.findCell(_target);
- #if SPHERICAL_GRID_LOGGING
+#if SPHERICAL_GRID_LOGGING
if (G.debug & G_DEBUG_FREESTYLE) {
cout << "Searching for occluders of edge centered at " << _target << " in cell [" <<
_cell->boundary[0] << ", " << _cell->boundary[1] << ", " << _cell->boundary[2] <<
", " << _cell->boundary[3] << "] (" << _cell->faces.size() << " occluders)" << endl;
}
- #endif
+#endif
// Set iterator
_current = _cell->faces.begin();
@@ -120,7 +120,7 @@ SphericalGrid::SphericalGrid(OccluderSource& source, GridDensityProvider& densit
SphericalGrid::~SphericalGrid() {}
-void SphericalGrid::assignCells(OccluderSource& source, GridDensityProvider& density, ViewMap *viewMap)
+void SphericalGrid::assignCells(OccluderSource& /*source*/, GridDensityProvider& density, ViewMap *viewMap)
{
_cellSize = density.cellSize();
_cellsX = density.cellsX();
diff --git a/source/blender/freestyle/intern/view_map/SteerableViewMap.cpp b/source/blender/freestyle/intern/view_map/SteerableViewMap.cpp
index fe6f3f1892d..4f5b4cba779 100644
--- a/source/blender/freestyle/intern/view_map/SteerableViewMap.cpp
+++ b/source/blender/freestyle/intern/view_map/SteerableViewMap.cpp
@@ -268,7 +268,7 @@ void SteerableViewMap::saveSteerableViewMap() const
//soc qtmp.save(base+QString::number(i)+"-"+QString::number(j)+".png", "PNG");
filename << base;
filename << i << "-" << j << ".png";
- ibuf->ftype = PNG;
+ ibuf->ftype = IMB_FTYPE_PNG;
IMB_saveiff(ibuf, const_cast<char *>(filename.str().c_str()), 0);
}
#if 0
diff --git a/source/blender/freestyle/intern/view_map/ViewEdgeXBuilder.cpp b/source/blender/freestyle/intern/view_map/ViewEdgeXBuilder.cpp
index b5d73640c11..139502e8d5e 100644
--- a/source/blender/freestyle/intern/view_map/ViewEdgeXBuilder.cpp
+++ b/source/blender/freestyle/intern/view_map/ViewEdgeXBuilder.cpp
@@ -632,18 +632,18 @@ FEdge *ViewEdgeXBuilder::BuildSharpFEdge(FEdge *feprevious, const OWXEdge& iwe)
{
SVertex *va, *vb;
FEdgeSharp *fe;
- WXVertex *wxVA, *wxVB;
+ Vec3r vA, vB;
if (iwe.order) {
- wxVA = (WXVertex *)iwe.e->GetaVertex();
- wxVB = (WXVertex *)iwe.e->GetbVertex();
+ vA = iwe.e->GetaVertex()->GetVertex();
+ vB = iwe.e->GetbVertex()->GetVertex();
}
else {
- wxVA = (WXVertex *)iwe.e->GetbVertex();
- wxVB = (WXVertex *)iwe.e->GetaVertex();
+ vA = iwe.e->GetbVertex()->GetVertex();
+ vB = iwe.e->GetaVertex()->GetVertex();
}
// Make the 2 SVertex
- va = MakeSVertex(wxVA->GetVertex(), true);
- vb = MakeSVertex(wxVB->GetVertex(), true);
+ va = MakeSVertex(vA, true);
+ vb = MakeSVertex(vB, true);
// get the faces normals and the material indices
Vec3r normalA, normalB;
diff --git a/source/blender/freestyle/intern/view_map/ViewMap.cpp b/source/blender/freestyle/intern/view_map/ViewMap.cpp
index fd5ebb99f72..52769413e79 100644
--- a/source/blender/freestyle/intern/view_map/ViewMap.cpp
+++ b/source/blender/freestyle/intern/view_map/ViewMap.cpp
@@ -63,6 +63,30 @@ ViewMap::~ViewMap()
_VEdges.clear();
}
+void ViewMap::Clean()
+{
+ vector<FEdge*> tmpEdges;
+
+ for (vector<ViewShape*>::iterator vs = _VShapes.begin(), vsend = _VShapes.end(); vs != vsend; vs++) {
+ vector<FEdge*>& edges = (*vs)->sshape()->getEdgeList();
+ for (vector<FEdge*>::iterator it = edges.begin(), itend = edges.end(); it != itend; it++) {
+ if ((*it)->isTemporary()) {
+ (*it)->setTemporary(false); // avoid being counted multiple times
+ tmpEdges.push_back(*it);
+ }
+ }
+ }
+
+ for (vector<FEdge*>::iterator it = tmpEdges.begin(), itend = tmpEdges.end(); it != itend; it++) {
+ for (vector<ViewShape*>::iterator vs = _VShapes.begin(), vsend = _VShapes.end(); vs != vsend; vs++) {
+ (*vs)->sshape()->RemoveEdge(*it);
+ }
+ (*it)->vertexA()->RemoveFEdge(*it);
+ (*it)->vertexB()->RemoveFEdge(*it);
+ delete (*it);
+ }
+}
+
ViewShape *ViewMap::viewShape(unsigned id)
{
int index = _shapeIdToIndex[id];
@@ -677,12 +701,12 @@ Interface0DIterator ViewEdge::verticesEnd()
return ret;
}
-Interface0DIterator ViewEdge::pointsBegin(float t)
+Interface0DIterator ViewEdge::pointsBegin(float /*t*/)
{
return verticesBegin();
}
-Interface0DIterator ViewEdge::pointsEnd(float t)
+Interface0DIterator ViewEdge::pointsEnd(float /*t*/)
{
return verticesEnd();
}
diff --git a/source/blender/freestyle/intern/view_map/ViewMap.h b/source/blender/freestyle/intern/view_map/ViewMap.h
index d87341503fa..74297e1dbfd 100644
--- a/source/blender/freestyle/intern/view_map/ViewMap.h
+++ b/source/blender/freestyle/intern/view_map/ViewMap.h
@@ -236,6 +236,9 @@ public:
/* connects a FEdge to the graph trough a SVertex */
//FEdge *Connect(FEdge *ioEdge, SVertex *ioVertex);
+ /* Clean temporary FEdges created by chaining */
+ virtual void Clean();
+
#ifdef WITH_CXX_GUARDEDALLOC
MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:ViewMap")
#endif
@@ -369,7 +372,6 @@ public:
#ifdef WITH_CXX_GUARDEDALLOC
MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:ViewVertex")
#endif
-
};
/**********************************/
@@ -642,7 +644,6 @@ public:
#ifdef WITH_CXX_GUARDEDALLOC
MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:TVertex")
#endif
-
};
@@ -859,7 +860,6 @@ public:
#ifdef WITH_CXX_GUARDEDALLOC
MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:NonTVertex")
#endif
-
};
/**********************************/
@@ -1379,7 +1379,6 @@ public:
#ifdef WITH_CXX_GUARDEDALLOC
MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:ViewEdge")
#endif
-
};
@@ -1567,7 +1566,7 @@ public:
}
/*! Returns the ViewShape id. */
- inline const string& getName() const
+ inline const char *getName() const
{
return _SShape->getName();
}
diff --git a/source/blender/freestyle/intern/view_map/ViewMapBuilder.cpp b/source/blender/freestyle/intern/view_map/ViewMapBuilder.cpp
index a0a1282219c..9ca021475b2 100644
--- a/source/blender/freestyle/intern/view_map/ViewMapBuilder.cpp
+++ b/source/blender/freestyle/intern/view_map/ViewMapBuilder.cpp
@@ -56,7 +56,7 @@ static const Global &_global = G;
using namespace std;
template <typename G, typename I>
-static void findOccludee(FEdge *fe, G& grid, I& occluders, real epsilon, WFace **oaWFace,
+static void findOccludee(FEdge *fe, G& /*grid*/, I& occluders, real epsilon, WFace **oaWFace,
Vec3r& u, Vec3r& A, Vec3r& origin, Vec3r& edge, vector<WVertex*>& faceVertices)
{
WFace *face = NULL;
@@ -169,7 +169,7 @@ static void findOccludee(FEdge *fe, G& grid, I& occluders, real epsilon, WFace *
}
template <typename G, typename I>
-static void findOccludee(FEdge *fe, G& grid, real epsilon, ViewEdge *ve, WFace **oaFace)
+static void findOccludee(FEdge *fe, G& grid, real epsilon, ViewEdge * /*ve*/, WFace **oaFace)
{
Vec3r A;
Vec3r edge;
@@ -205,7 +205,7 @@ static void findOccludee(FEdge *fe, G& grid, real epsilon, ViewEdge *ve, WFace *
// computeVisibility takes a pointer to foundOccluders, instead of using a reference,
// so that computeVeryFastVisibility can skip the AddOccluders step with minimal overhead.
template <typename G, typename I>
-static int computeVisibility(ViewMap *viewMap, FEdge *fe, G& grid, real epsilon, ViewEdge *ve, WFace **oaWFace,
+static int computeVisibility(ViewMap *viewMap, FEdge *fe, G& grid, real epsilon, ViewEdge * /*ve*/, WFace **oaWFace,
set<ViewShape*> *foundOccluders)
{
int qi = 0;
@@ -1300,8 +1300,8 @@ void ViewMapBuilder::computeCusps(ViewMap *ioViewMap)
void ViewMapBuilder::ComputeCumulativeVisibility(ViewMap *ioViewMap, WingedEdge& we, const BBox<Vec3r>& bbox,
real epsilon, bool cull, GridDensityProviderFactory& factory)
{
- auto_ptr<GridHelpers::Transform> transform;
- auto_ptr<OccluderSource> source;
+ AutoPtr<GridHelpers::Transform> transform;
+ AutoPtr<OccluderSource> source;
if (_orthographicProjection) {
transform.reset(new BoxGrid::Transform);
@@ -1317,7 +1317,7 @@ void ViewMapBuilder::ComputeCumulativeVisibility(ViewMap *ioViewMap, WingedEdge&
source.reset(new OccluderSource(*transform, we));
}
- auto_ptr<GridDensityProvider> density(factory.newGridDensityProvider(*source, bbox, *transform));
+ AutoPtr<GridDensityProvider> density(factory.newGridDensityProvider(*source, bbox, *transform));
if (_orthographicProjection) {
BoxGrid grid(*source, *density, ioViewMap, _viewpoint, _EnableQI);
@@ -1332,8 +1332,8 @@ void ViewMapBuilder::ComputeCumulativeVisibility(ViewMap *ioViewMap, WingedEdge&
void ViewMapBuilder::ComputeDetailedVisibility(ViewMap *ioViewMap, WingedEdge& we, const BBox<Vec3r>& bbox,
real epsilon, bool cull, GridDensityProviderFactory& factory)
{
- auto_ptr<GridHelpers::Transform> transform;
- auto_ptr<OccluderSource> source;
+ AutoPtr<GridHelpers::Transform> transform;
+ AutoPtr<OccluderSource> source;
if (_orthographicProjection) {
transform.reset(new BoxGrid::Transform);
@@ -1349,7 +1349,7 @@ void ViewMapBuilder::ComputeDetailedVisibility(ViewMap *ioViewMap, WingedEdge& w
source.reset(new OccluderSource(*transform, we));
}
- auto_ptr<GridDensityProvider> density(factory.newGridDensityProvider(*source, bbox, *transform));
+ AutoPtr<GridDensityProvider> density(factory.newGridDensityProvider(*source, bbox, *transform));
if (_orthographicProjection) {
BoxGrid grid(*source, *density, ioViewMap, _viewpoint, _EnableQI);
@@ -2112,14 +2112,14 @@ void ViewMapBuilder::ComputeIntersections(ViewMap *ioViewMap, intersection_algo
default:
break;
}
- ViewMap::viewvertices_container& vvertices = ioViewMap->ViewVertices();
- for (ViewMap::viewvertices_container::iterator vv = vvertices.begin(), vvend = vvertices.end();
- vv != vvend;
- ++vv)
- {
- if ((*vv)->getNature() == Nature::T_VERTEX) {
- TVertex *tvertex = (TVertex *)(*vv);
- if (_global.debug & G_DEBUG_FREESTYLE) {
+#if 0
+ if (_global.debug & G_DEBUG_FREESTYLE) {
+ ViewMap::viewvertices_container& vvertices = ioViewMap->ViewVertices();
+ for (ViewMap::viewvertices_container::iterator vv = vvertices.begin(), vvend = vvertices.end();
+ vv != vvend; ++vv)
+ {
+ if ((*vv)->getNature() == Nature::T_VERTEX) {
+ TVertex *tvertex = (TVertex *)(*vv);
cout << "TVertex " << tvertex->getId() << " has :" << endl;
cout << "FrontEdgeA: " << tvertex->frontEdgeA().first << endl;
cout << "FrontEdgeB: " << tvertex->frontEdgeB().first << endl;
@@ -2128,6 +2128,7 @@ void ViewMapBuilder::ComputeIntersections(ViewMap *ioViewMap, intersection_algo
}
}
}
+#endif
}
struct less_SVertex2D : public binary_function<SVertex *, SVertex *, bool>
diff --git a/source/blender/freestyle/intern/view_map/ViewMapBuilder.h b/source/blender/freestyle/intern/view_map/ViewMapBuilder.h
index 08b2fde8f31..36497bf8d22 100644
--- a/source/blender/freestyle/intern/view_map/ViewMapBuilder.h
+++ b/source/blender/freestyle/intern/view_map/ViewMapBuilder.h
@@ -145,7 +145,7 @@ public:
* The viewport. 4 real array: origin.x, origin.y, width, length
*/
inline void setTransform(const real iModelViewMatrix[4][4], const real iProjectionMatrix[4][4],
- const int iViewport[4], real iFocalLength, real iAspect, real iFovy)
+ const int iViewport[4], real iFocalLength, real /*iAspect*/, real /*iFovy*/)
{
_orthographicProjection = (iProjectionMatrix[3][3] != 0.0);
SilhouetteGeomEngine::setTransform(iModelViewMatrix, iProjectionMatrix, iViewport, iFocalLength);
diff --git a/source/blender/freestyle/intern/winged_edge/Curvature.cpp b/source/blender/freestyle/intern/winged_edge/Curvature.cpp
index 38941b23357..97dcc86cf31 100644
--- a/source/blender/freestyle/intern/winged_edge/Curvature.cpp
+++ b/source/blender/freestyle/intern/winged_edge/Curvature.cpp
@@ -211,8 +211,9 @@ bool gts_vertex_gaussian_curvature(WVertex *v, real *Kg)
}
WVertex::incoming_edge_iterator itE;
- for (itE = v->incoming_edges_begin(); itE != v->incoming_edges_end(); itE++)
- area += (*itE)->GetaFace()->getArea();
+ for (itE = v->incoming_edges_begin(); itE != v->incoming_edges_end(); itE++) {
+ area += (*itE)->GetaFace()->getArea();
+ }
for (itE = v->incoming_edges_begin(); itE != v->incoming_edges_end(); itE++) {
WOEdge *e = (*itE)->getPrevOnFace();
@@ -535,6 +536,7 @@ void gts_vertex_principal_directions(WVertex *v, Vec3r Kh, real Kg, Vec3r &e1, V
namespace OGF {
+#if 0
inline static real angle(WOEdge *h)
{
const Vec3r& n1 = h->GetbFace()->GetNormal();
@@ -549,6 +551,7 @@ inline static real angle(WOEdge *h)
}
return ::asin(sine);
}
+#endif
// precondition1: P is inside the sphere
// precondition2: P,V points to the outside of the sphere (i.e. OP.V > 0)
diff --git a/source/blender/freestyle/intern/winged_edge/Nature.h b/source/blender/freestyle/intern/winged_edge/Nature.h
index 99a3f902cd0..b1b5c88df5a 100644
--- a/source/blender/freestyle/intern/winged_edge/Nature.h
+++ b/source/blender/freestyle/intern/winged_edge/Nature.h
@@ -34,6 +34,7 @@ namespace Freestyle {
namespace Nature {
/* XXX Why not using enums??? */
+/* In order to optimize for space (enum is int) - T.K. */
typedef unsigned short VertexNature;
/*! true for any 0D element */
diff --git a/source/blender/freestyle/intern/winged_edge/WEdge.cpp b/source/blender/freestyle/intern/winged_edge/WEdge.cpp
index de166531d8b..87ca3a4235f 100644
--- a/source/blender/freestyle/intern/winged_edge/WEdge.cpp
+++ b/source/blender/freestyle/intern/winged_edge/WEdge.cpp
@@ -410,16 +410,16 @@ bool WFace::getOppositeEdge(const WVertex *v, WOEdge *&e)
return true;
}
-real WFace::getArea ()
+float WFace::getArea()
{
vector<WOEdge *>::iterator it;
- Vec3r origin = (*(_OEdgeList.begin()))->GetaVertex()->GetVertex();
+ Vec3f origin = (*(_OEdgeList.begin()))->GetaVertex()->GetVertex();
it = _OEdgeList.begin();
- real a = 0;
+ float a = 0;
for (it = it++; it != _OEdgeList.end(); it++) {
- Vec3r v1 = Vec3r((*it)->GetaVertex()->GetVertex() - origin);
- Vec3r v2 = Vec3r((*it)->GetbVertex()->GetVertex() - origin);
- a += (v1 ^ v2).norm() / 2.0;
+ Vec3f v1 = Vec3f((*it)->GetaVertex()->GetVertex() - origin);
+ Vec3f v2 = Vec3f((*it)->GetbVertex()->GetVertex() - origin);
+ a += (v1 ^ v2).norm() / 2.0f;
}
return a;
}
@@ -472,8 +472,10 @@ WShape::WShape(WShape& iBrother)
_Id = iBrother.GetId();
_Name = iBrother._Name;
_FrsMaterials = iBrother._FrsMaterials;
+#if 0
_meanEdgeSize = iBrother._meanEdgeSize;
iBrother.bbox(_min, _max);
+#endif
vector<WVertex *>& vertexList = iBrother.getVertexList();
vector<WVertex *>::iterator v = vertexList.begin(), vend = vertexList.end();
for (; v != vend; ++v) {
@@ -597,7 +599,7 @@ WFace *WShape::MakeFace(vector<WVertex *>& iVertexList, vector<bool>& iFaceEdgeM
return result;
}
-WFace *WShape::MakeFace(vector<WVertex *>& iVertexList, vector<Vec3r>& iNormalsList, vector<Vec2r>& iTexCoordsList,
+WFace *WShape::MakeFace(vector<WVertex *>& iVertexList, vector<Vec3f>& iNormalsList, vector<Vec2f>& iTexCoordsList,
vector<bool>& iFaceEdgeMarksList, unsigned iMaterial)
{
// allocate the new face
@@ -646,10 +648,10 @@ WFace *WShape::MakeFace(vector<WVertex *>& iVertexList, vector<bool>& iFaceEdgeM
it++;
v3 = *it;
- Vec3r vector1(v2->GetVertex() - v1->GetVertex());
- Vec3r vector2(v3->GetVertex() - v1->GetVertex());
+ Vec3f vector1(v2->GetVertex() - v1->GetVertex());
+ Vec3f vector2(v3->GetVertex() - v1->GetVertex());
- Vec3r normal(vector1 ^ vector2);
+ Vec3f normal(vector1 ^ vector2);
normal.normalize();
face->setNormal(normal);
@@ -681,8 +683,10 @@ WFace *WShape::MakeFace(vector<WVertex *>& iVertexList, vector<bool>& iFaceEdgeM
// means that we just created a new edge and that we must add it to the shape's edges list
edge->setId(_EdgeList.size());
AddEdge(edge);
+#if 0
// compute the mean edge value:
_meanEdgeSize += edge->GetaOEdge()->GetVec().norm();
+#endif
}
edge->setMark(*mit);
@@ -696,4 +700,16 @@ WFace *WShape::MakeFace(vector<WVertex *>& iVertexList, vector<bool>& iFaceEdgeM
return face;
}
+real WShape::ComputeMeanEdgeSize() const
+{
+ real meanEdgeSize = 0.0;
+ for (vector<WEdge *>::const_iterator it = _EdgeList.begin(), itend = _EdgeList.end();
+ it != itend;
+ it++)
+ {
+ meanEdgeSize += (*it)->GetaOEdge()->GetVec().norm();
+ }
+ return meanEdgeSize / (real)_EdgeList.size();
+}
+
} /* namespace Freestyle */
diff --git a/source/blender/freestyle/intern/winged_edge/WEdge.h b/source/blender/freestyle/intern/winged_edge/WEdge.h
index 41525e03d8e..8001342775b 100644
--- a/source/blender/freestyle/intern/winged_edge/WEdge.h
+++ b/source/blender/freestyle/intern/winged_edge/WEdge.h
@@ -68,15 +68,15 @@ class WVertex
{
protected:
int _Id; // an identificator
- Vec3r _Vertex;
+ Vec3f _Vertex;
vector<WEdge*> _EdgeList;
WShape *_Shape; // the shape to which the vertex belongs
bool _Smooth; // flag to indicate whether the Vertex belongs to a smooth edge or not
- int _Border; // 1 -> border, 0 -> no border, -1 -> not set
+ short _Border; // 1 -> border, 0 -> no border, -1 -> not set
public:
void *userdata; // designed to store specific user data
- inline WVertex(const Vec3r &v)
+ inline WVertex(const Vec3f &v)
{
_Id = 0;
_Vertex = v;
@@ -92,7 +92,7 @@ public:
virtual ~WVertex() {}
/*! accessors */
- inline Vec3r& GetVertex()
+ inline Vec3f& GetVertex()
{
return _Vertex;
}
@@ -120,7 +120,7 @@ public:
bool isBoundary();
/*! modifiers */
- inline void setVertex(const Vec3r& v)
+ inline void setVertex(const Vec3f& v)
{
_Vertex = v;
}
@@ -381,8 +381,8 @@ protected:
WFace *_pbFace; // when following the edge, face on the left
WEdge *_pOwner; // Edge
- Vec3r _vec;
- real _angle;
+ Vec3f _vec;
+ float _angle;
public:
void *userdata;
@@ -457,17 +457,16 @@ public:
return _pOwner;
}
- inline const Vec3r& GetVec()
+ inline const Vec3f& GetVec()
{
return _vec;
}
- inline const real GetAngle()
+ inline const float GetAngle()
{
return _angle;
}
-
/*! modifiers */
#if 0
inline void SetaCWEdge(WOEdge *pe)
@@ -552,7 +551,7 @@ class WEdge
protected:
WOEdge *_paOEdge; // first oriented edge
WOEdge *_pbOEdge; // second oriented edge
- int _nOEdges; // number of oriented edges associated with this edge. (1 means border edge)
+ short _nOEdges; // number of oriented edges associated with this edge. (1 means border edge)
bool _Mark; // user-specified edge mark for feature edge detection
int _Id; // Identifier for the edge
@@ -633,7 +632,7 @@ public:
return _pbOEdge;
}
- inline int GetNumberOfOEdges()
+ inline short GetNumberOfOEdges()
{
return _nOEdges;
}
@@ -700,7 +699,7 @@ public:
}
}
- inline void setNumberOfOEdges(int n)
+ inline void setNumberOfOEdges(short n)
{
_nOEdges = n;
}
@@ -739,11 +738,11 @@ class WFace
{
protected:
vector<WOEdge *> _OEdgeList; // list of oriented edges of bording the face
- Vec3r _Normal; // normal to the face
+ Vec3f _Normal; // normal to the face
// in case there is a normal per vertex.
// The normal number i corresponds to the aVertex of the oedge number i, for that face
- vector<Vec3r> _VerticesNormals;
- vector<Vec2r> _VerticesTexCoords;
+ vector<Vec3f> _VerticesNormals;
+ vector<Vec2f> _VerticesTexCoords;
int _Id;
unsigned _FrsMaterialIndex;
@@ -773,7 +772,7 @@ public:
return _OEdgeList[i];
}
- inline Vec3r& GetNormal()
+ inline Vec3f& GetNormal()
{
return _Normal;
}
@@ -849,30 +848,30 @@ public:
return iOEdge->GetaFace();
}
- inline vector<Vec3r>& GetPerVertexNormals()
+ inline vector<Vec3f>& GetPerVertexNormals()
{
return _VerticesNormals;
}
- inline vector<Vec2r>& GetPerVertexTexCoords()
+ inline vector<Vec2f>& GetPerVertexTexCoords()
{
return _VerticesTexCoords;
}
/*! Returns the normal of the vertex of index index */
- inline Vec3r& GetVertexNormal(int index)
+ inline Vec3f& GetVertexNormal(int index)
{
return _VerticesNormals[index];
}
/*! Returns the tex coords of the vertex of index index */
- inline Vec2r& GetVertexTexCoords(int index)
+ inline Vec2f& GetVertexTexCoords(int index)
{
return _VerticesTexCoords[index];
}
/*! Returns the normal of the vertex iVertex for that face */
- inline Vec3r& GetVertexNormal(WVertex *iVertex)
+ inline Vec3f& GetVertexNormal(WVertex *iVertex)
{
int i = 0;
int index = 0;
@@ -939,17 +938,17 @@ public:
_OEdgeList = iEdgeList;
}
- inline void setNormal(const Vec3r& iNormal)
+ inline void setNormal(const Vec3f& iNormal)
{
_Normal = iNormal;
}
- inline void setNormalList(const vector<Vec3r>& iNormalsList)
+ inline void setNormalList(const vector<Vec3f>& iNormalsList)
{
_VerticesNormals = iNormalsList;
}
- inline void setTexCoordsList(const vector<Vec2r>& iTexCoordsList)
+ inline void setTexCoordsList(const vector<Vec2f>& iTexCoordsList)
{
_VerticesTexCoords = iTexCoordsList;
}
@@ -990,12 +989,12 @@ public:
}
/*! For triangles, returns the edge opposite to the vertex in e.
- * returns flase if the face is not a triangle or if the vertex is not found
+ * returns false if the face is not a triangle or if the vertex is not found
*/
bool getOppositeEdge (const WVertex *v, WOEdge *&e);
/*! compute the area of the face */
- real getArea ();
+ float getArea ();
WShape *getShape();
virtual void ResetUserData()
@@ -1025,17 +1024,23 @@ protected:
vector<WEdge *> _EdgeList;
vector<WFace *> _FaceList;
int _Id;
- string _Name;
+ const char *_Name;
static unsigned _SceneCurrentId;
- Vec3r _min;
- Vec3r _max;
+#if 0
+ Vec3f _min;
+ Vec3f _max;
+#endif
vector<FrsMaterial> _FrsMaterials;
- real _meanEdgeSize;
+#if 0
+ float _meanEdgeSize;
+#endif
public:
inline WShape()
{
+#if 0
_meanEdgeSize = 0;
+#endif
_Id = _SceneCurrentId;
_SceneCurrentId++;
}
@@ -1092,11 +1097,13 @@ public:
return _Id;
}
- inline void bbox(Vec3r& min, Vec3r& max)
+#if 0
+ inline void bbox(Vec3f& min, Vec3f& max)
{
min = _min;
max = _max;
}
+#endif
inline const FrsMaterial& frs_material(unsigned i) const
{
@@ -1108,12 +1115,14 @@ public:
return _FrsMaterials;
}
- inline const real getMeanEdgeSize() const
+#if 0
+ inline const float getMeanEdgeSize() const
{
return _meanEdgeSize;
}
+#endif
- inline const string& getName() const
+ inline const char *getName() const
{
return _Name;
}
@@ -1144,11 +1153,13 @@ public:
_Id = id;
}
- inline void setBBox(const Vec3r& min, const Vec3r& max)
+#if 0
+ inline void setBBox(const Vec3f& min, const Vec3f& max)
{
_min = min;
_max = max;
}
+#endif
inline void setFrsMaterial(const FrsMaterial& frs_material, unsigned i)
{
@@ -1160,7 +1171,7 @@ public:
_FrsMaterials = iMaterials;
}
- inline void setName(const string& name)
+ inline void setName(const char *name)
{
_Name = name;
}
@@ -1199,7 +1210,7 @@ public:
* The list of tex coords, iTexCoordsList[i] corresponding to the normal of the vertex iVertexList[i] for
* that face.
*/
- virtual WFace *MakeFace(vector<WVertex *>& iVertexList, vector<Vec3r>& iNormalsList, vector<Vec2r>& iTexCoordsList,
+ virtual WFace *MakeFace(vector<WVertex *>& iVertexList, vector<Vec3f>& iNormalsList, vector<Vec2f>& iTexCoordsList,
vector<bool>& iFaceEdgeMarksList, unsigned iMaterialIndex);
inline void AddEdge(WEdge *iEdge)
@@ -1240,12 +1251,13 @@ public:
}
}
+#if 0
inline void ComputeBBox()
{
_min = _VertexList[0]->GetVertex();
_max = _VertexList[0]->GetVertex();
- Vec3r v;
+ Vec3f v;
for (vector<WVertex *>::iterator wv = _VertexList.begin(), wvend = _VertexList.end(); wv != wvend; wv++) {
for (unsigned int i = 0; i < 3; i++) {
v = (*wv)->GetVertex();
@@ -1256,12 +1268,17 @@ public:
}
}
}
+#endif
- inline real ComputeMeanEdgeSize()
+#if 0
+ inline float ComputeMeanEdgeSize()
{
_meanEdgeSize = _meanEdgeSize / _EdgeList.size();
return _meanEdgeSize;
}
+#else
+ real ComputeMeanEdgeSize() const;
+#endif
protected:
/*! Builds the face passed as argument (which as already been allocated)
@@ -1368,7 +1385,7 @@ inline void WOEdge::setVecAndAngle()
if (_paVertex && _pbVertex) {
_vec = _pbVertex->GetVertex() - _paVertex->GetVertex();
if (_paFace && _pbFace) {
- real sine = (_pbFace->GetNormal() ^ _paFace->GetNormal()) * _vec / _vec.norm();
+ float sine = (_pbFace->GetNormal() ^ _paFace->GetNormal()) * _vec / _vec.norm();
if (sine >= 1.0) {
_angle = M_PI / 2.0;
return;
diff --git a/source/blender/freestyle/intern/winged_edge/WXEdge.cpp b/source/blender/freestyle/intern/winged_edge/WXEdge.cpp
index 84dbd5fbef8..11bce2b007e 100644
--- a/source/blender/freestyle/intern/winged_edge/WXEdge.cpp
+++ b/source/blender/freestyle/intern/winged_edge/WXEdge.cpp
@@ -43,7 +43,7 @@ unsigned int WXFaceLayer::Get0VertexIndex() const
int i = 0;
int nEdges = _pWXFace->numberOfEdges();
for (i = 0; i < nEdges; ++i) {
- if (_DotP[i] == 0) {
+ if (_DotP[i] == 0.0f) { // TODO this comparison is weak, check if it actually works
return i;
}
}
@@ -54,7 +54,7 @@ unsigned int WXFaceLayer::GetSmoothEdgeIndex() const
int i = 0;
int nEdges = _pWXFace->numberOfEdges();
for (i = 0; i < nEdges; ++i) {
- if ((_DotP[i] == 0) && (_DotP[(i + 1) % nEdges] == 0)) {
+ if ((_DotP[i] == 0.0f) && (_DotP[(i + 1) % nEdges] == 0.0f)) { // TODO ditto
return i;
}
}
@@ -66,7 +66,7 @@ void WXFaceLayer::RetrieveCuspEdgesIndices(vector<int>& oCuspEdges)
int i = 0;
int nEdges = _pWXFace->numberOfEdges();
for (i = 0; i < nEdges; ++i) {
- if (_DotP[i] * _DotP[(i + 1) % nEdges] < 0) {
+ if (_DotP[i] * _DotP[(i + 1) % nEdges] < 0.0f) {
// we got one
oCuspEdges.push_back(i);
}
@@ -78,7 +78,7 @@ WXSmoothEdge *WXFaceLayer::BuildSmoothEdge()
// if the smooth edge has already been built: exit
if (_pSmoothEdge)
return _pSmoothEdge;
- real ta, tb;
+ float ta, tb;
WOEdge *woea(0), *woeb(0);
bool ok = false;
vector<int> cuspEdgesIndices;
@@ -101,7 +101,7 @@ WXSmoothEdge *WXFaceLayer::BuildSmoothEdge()
// So if the WOEdge woea is such that woea[0].dotp > 0 and woea[1].dotp < 0, it is the starting edge.
//-------------------------------------------
- if (_DotP[cuspEdgesIndices[0]] > 0) {
+ if (_DotP[cuspEdgesIndices[0]] > 0.0f) {
woea = _pWXFace->GetOEdge(cuspEdgesIndices[0]);
woeb = _pWXFace->GetOEdge(cuspEdgesIndices[1]);
indexStart = cuspEdgesIndices[0];
@@ -136,18 +136,18 @@ WXSmoothEdge *WXFaceLayer::BuildSmoothEdge()
}
unsigned index0 = Get0VertexIndex(); // retrieve the 0 vertex index
unsigned nedges = _pWXFace->numberOfEdges();
- if (_DotP[cuspEdgesIndices[0]] > 0) {
+ if (_DotP[cuspEdgesIndices[0]] > 0.0f) {
woea = _pWXFace->GetOEdge(cuspEdgesIndices[0]);
woeb = _pWXFace->GetOEdge(index0);
indexStart = cuspEdgesIndices[0];
ta = _DotP[indexStart] / (_DotP[indexStart] - _DotP[(indexStart + 1) % nedges]);
- tb = 0.0;
+ tb = 0.0f;
}
else {
woea = _pWXFace->GetOEdge(index0);
woeb = _pWXFace->GetOEdge(cuspEdgesIndices[0]);
indexEnd = cuspEdgesIndices[0];
- ta = 0.0;
+ ta = 0.0f;
tb = _DotP[indexEnd] / (_DotP[indexEnd] - _DotP[(indexEnd + 1) % nedges]);
}
ok = true;
@@ -159,8 +159,8 @@ WXSmoothEdge *WXFaceLayer::BuildSmoothEdge()
// the order of the WOEdge index is wrong
woea = _pWXFace->GetOEdge((index + 1) % nedges);
woeb = _pWXFace->GetOEdge((index - 1) % nedges);
- ta = 0;
- tb = 1;
+ ta = 0.0f;
+ tb = 1.0f;
ok = true;
}
else {
@@ -170,8 +170,8 @@ WXSmoothEdge *WXFaceLayer::BuildSmoothEdge()
// the order of the WOEdge index is good
woea = _pWXFace->GetOEdge((index - 1) % nedges);
woeb = _pWXFace->GetOEdge((index + 1) % nedges);
- ta = 1;
- tb = 0;
+ ta = 1.0f;
+ tb = 0.0f;
#endif
}
}
@@ -183,7 +183,7 @@ WXSmoothEdge *WXFaceLayer::BuildSmoothEdge()
_pSmoothEdge->setTb(tb);
if (_Nature & Nature::SILHOUETTE) {
if (_nNullDotP != 2) {
- if (_DotP[_ClosestPointIndex] + 0.01 > 0)
+ if (_DotP[_ClosestPointIndex] + 0.01f > 0.0f)
_pSmoothEdge->setFront(true);
else
_pSmoothEdge->setFront(false);
@@ -205,7 +205,7 @@ WXSmoothEdge *WXFaceLayer::BuildSmoothEdge()
}
// Else we must build it
WOEdge *woea, *woeb;
- real ta, tb;
+ float ta, tb;
if (!front()) { // is it in the right order ?
// the order of the WOEdge index is wrong
woea = _OEdgeList[(i + 1) % numberOfEdges()];
@@ -213,8 +213,8 @@ WXSmoothEdge *WXFaceLayer::BuildSmoothEdge()
woeb = _OEdgeList[numberOfEdges() - 1];
else
woeb = _OEdgeList[(i - 1)];
- ta = 0;
- tb = 1;
+ ta = 0.0f;
+ tb = 1.0f;
}
else {
// the order of the WOEdge index is good
@@ -223,8 +223,8 @@ WXSmoothEdge *WXFaceLayer::BuildSmoothEdge()
else
woea = _OEdgeList[(i - 1)];
woeb = _OEdgeList[(i + 1) % numberOfEdges()];
- ta = 1;
- tb = 0;
+ ta = 1.0f;
+ tb = 0.0f;
}
_pSmoothEdge = new ExactSilhouetteEdge(ExactSilhouetteEdge::VERTEX_VERTEX);
@@ -246,11 +246,11 @@ void WXFace::ComputeCenter()
{
vector<WVertex *> iVertexList;
RetrieveVertexList(iVertexList);
- Vec3r center;
+ Vec3f center;
for (vector<WVertex *>::iterator wv = iVertexList.begin(), wvend = iVertexList.end(); wv != wvend; ++wv) {
center += (*wv)->GetVertex();
}
- center /= (real)iVertexList.size();
+ center /= (float)iVertexList.size();
setCenter(center);
}
@@ -268,28 +268,28 @@ WFace *WXShape::MakeFace(vector<WVertex *>& iVertexList, vector<bool>& iFaceEdge
if (!face)
return NULL;
- Vec3r center;
+ Vec3f center;
for (vector<WVertex *>::iterator wv = iVertexList.begin(), wvend = iVertexList.end(); wv != wvend; ++wv) {
center += (*wv)->GetVertex();
}
- center /= (real)iVertexList.size();
+ center /= (float)iVertexList.size();
((WXFace *)face)->setCenter(center);
return face;
}
-WFace *WXShape::MakeFace(vector<WVertex *>& iVertexList, vector<Vec3r>& iNormalsList, vector<Vec2r>& iTexCoordsList,
+WFace *WXShape::MakeFace(vector<WVertex *>& iVertexList, vector<Vec3f>& iNormalsList, vector<Vec2f>& iTexCoordsList,
vector<bool>& iFaceEdgeMarksList, unsigned iMaterialIndex)
{
WFace *face = WShape::MakeFace(iVertexList, iNormalsList, iTexCoordsList, iFaceEdgeMarksList, iMaterialIndex);
#if 0
- Vec3r center;
+ Vec3f center;
for (vector<WVertex *>::iterator wv = iVertexList.begin(), wvend = iVertexList.end(); wv != wvend; ++wv) {
center += (*wv)->GetVertex();
}
- center /= (real)iVertexList.size();
- ((WSFace *)face)->setCenter(center);
+ center /= (float)iVertexList.size();
+ ((WXFace *)face)->setCenter(center);
#endif
return face;
diff --git a/source/blender/freestyle/intern/winged_edge/WXEdge.h b/source/blender/freestyle/intern/winged_edge/WXEdge.h
index ce9749369fc..774cc67f3ab 100644
--- a/source/blender/freestyle/intern/winged_edge/WXEdge.h
+++ b/source/blender/freestyle/intern/winged_edge/WXEdge.h
@@ -55,7 +55,7 @@ private:
CurvatureInfo *_curvatures;
public:
- inline WXVertex(const Vec3r &v) : WVertex(v)
+ inline WXVertex(const Vec3f &v) : WVertex(v)
{
_curvatures = NULL;
}
@@ -99,7 +99,6 @@ public:
#ifdef WITH_CXX_GUARDEDALLOC
MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:WXVertex")
#endif
-
};
@@ -117,7 +116,7 @@ private:
// flag to indicate whether the edge is a silhouette edge or not
WXNature _nature;
// 0: the order doesn't matter. 1: the order is the orginal one. -1: the order is not good
- int _order;
+ short _order;
// A front facing edge is an edge for which the bording face which is the nearest from the viewpoint is front.
// A back facing edge is the opposite.
bool _front;
@@ -177,7 +176,7 @@ public:
return _front;
}
- inline int order() const
+ inline short order() const
{
return _order;
}
@@ -206,7 +205,6 @@ public:
#ifdef WITH_CXX_GUARDEDALLOC
MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:WXEdge")
#endif
-
};
/**********************************
@@ -221,16 +219,15 @@ public:
class WXSmoothEdge
{
public:
- typedef enum {
- EDGE_EDGE,
- VERTEX_EDGE,
- EDGE_VERTEX,
- } Configuration;
+ typedef unsigned short Configuration;
+ static const Configuration EDGE_EDGE = 1;
+ static const Configuration VERTEX_EDGE = 2;
+ static const Configuration EDGE_VERTEX = 3;
WOEdge *_woea; // Oriented edge from which the silhouette edge starts
WOEdge *_woeb; // Oriented edge where the silhouette edge ends
- real _ta; // The silhouette starting point's coordinates are : _woea[0]+ta*(_woea[1]-_woea[0])
- real _tb; // The silhouette ending point's coordinates are : _woeb[0]+ta*(_woeb[1]-_woeb[0])
+ float _ta; // The silhouette starting point's coordinates are : _woea[0]+ta*(_woea[1]-_woea[0])
+ float _tb; // The silhouette ending point's coordinates are : _woeb[0]+ta*(_woeb[1]-_woeb[0])
bool _front;
Configuration _config;
@@ -238,8 +235,8 @@ public:
{
_woea = NULL;
_woeb = NULL;
- _ta = 0;
- _tb = 0;
+ _ta = 0.0f;
+ _tb = 0.0f;
_front = false;
_config = EDGE_EDGE;
}
@@ -266,12 +263,12 @@ public:
return _woeb;
}
- inline real ta() const
+ inline float ta() const
{
return _ta;
}
- inline real tb() const
+ inline float tb() const
{
return _tb;
}
@@ -297,12 +294,12 @@ public:
_woeb = iwoeb;
}
- inline void setTa(real ta)
+ inline void setTa(float ta)
{
_ta = ta;
}
- inline void setTb(real tb)
+ inline void setTb(float tb)
{
_tb = tb;
}
@@ -334,7 +331,7 @@ public:
WXFace *_pWXFace;
// in case of silhouette: the values obtained when computing the normal-view direction dot product. _DotP[i] is
// this value for the vertex i for that face.
- vector<real> _DotP;
+ vector<float> _DotP;
WXSmoothEdge *_pSmoothEdge;
WXNature _Nature;
@@ -383,7 +380,7 @@ public:
}
}
- inline const real dotP(int i) const
+ inline const float dotP(int i) const
{
return _DotP[i];
}
@@ -403,7 +400,7 @@ public:
return _ClosestPointIndex;
}
- inline Nature::EdgeNature nature() const
+ inline WXNature nature() const
{
return _Nature;
}
@@ -458,21 +455,21 @@ public:
WXSmoothEdge *BuildSmoothEdge();
- inline void setDotP(const vector<real>& iDotP)
+ inline void setDotP(const vector<float>& iDotP)
{
_DotP = iDotP;
}
- inline void PushDotP(real iDotP)
+ inline void PushDotP(float iDotP)
{
_DotP.push_back(iDotP);
- if (iDotP > 0)
+ if (iDotP > 0.0f)
++_nPosDotP;
- if (iDotP == 0)
+ if (iDotP == 0.0f) // TODO this comparison is weak, check if it actually works
++_nNullDotP;
}
- inline void ReplaceDotP(unsigned int index, real newDotP)
+ inline void ReplaceDotP(unsigned int index, float newDotP)
{
_DotP[index] = newDotP;
updateDotPInfos();
@@ -482,10 +479,10 @@ public:
{
_nPosDotP = 0;
_nNullDotP = 0;
- for (vector<real>::iterator d = _DotP.begin(), dend = _DotP.end(); d != dend; ++d) {
- if ((*d) > 0)
+ for (vector<float>::iterator d = _DotP.begin(), dend = _DotP.end(); d != dend; ++d) {
+ if ((*d) > 0.0f)
++_nPosDotP;
- if ((*d) == 0)
+ if ((*d) == 0.0f) // TODO ditto
++_nNullDotP;
}
}
@@ -498,17 +495,17 @@ public:
class WXFace : public WFace
{
protected:
- Vec3r _center; // center of the face
- real _Z; // distance from viewpoint to the center of the face
+ Vec3f _center; // center of the face
+ float _Z; // distance from viewpoint to the center of the face
bool _front; // flag to tell whether the face is front facing or back facing
- real _dotp; // value obtained when computing the normal-viewpoint dot product
+ float _dotp; // value obtained when computing the normal-viewpoint dot product
vector<WXFaceLayer *> _SmoothLayers; // The data needed to store one or several smooth edges that traverse the face
public:
inline WXFace() : WFace()
{
- _Z = 0.0;
+ _Z = 0.0f;
_front = false;
}
@@ -552,12 +549,12 @@ public:
}
/*! accessors */
- inline Vec3r& center()
+ inline Vec3f& center()
{
return _center;
}
- inline real Z()
+ inline float Z()
{
return _Z;
}
@@ -567,7 +564,7 @@ public:
return _front;
}
- inline real dotp()
+ inline float dotp()
{
return _dotp;
}
@@ -628,14 +625,14 @@ public:
}
/*! modifiers */
- inline void setCenter(const Vec3r& iCenter)
+ inline void setCenter(const Vec3f& iCenter)
{
_center = iCenter;
}
void ComputeCenter();
- inline void setZ(real z)
+ inline void setZ(float z)
{
_Z = z;
}
@@ -645,10 +642,10 @@ public:
_front = iFront;
}
- inline void setDotP(real iDotP)
+ inline void setDotP(float iDotP)
{
_dotp = iDotP;
- if (_dotp > 0)
+ if (_dotp > 0.0f)
_front = true;
else
_front = false;
@@ -700,7 +697,6 @@ public:
#ifdef WITH_CXX_GUARDEDALLOC
MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:WXFace")
#endif
-
};
@@ -714,22 +710,24 @@ public:
class WXShape : public WShape
{
+#if 0
public:
typedef WXShape type_name;
+#endif
protected:
- bool _computeViewIndependant; // flag to indicate whether the view independant stuff must be computed or not
+ bool _computeViewIndependent; // flag to indicate whether the view independent stuff must be computed or not
public:
inline WXShape() : WShape()
{
- _computeViewIndependant = true;
+ _computeViewIndependent = true;
}
/*! copy constructor */
inline WXShape(WXShape& iBrother) : WShape(iBrother)
{
- _computeViewIndependant = iBrother._computeViewIndependant;
+ _computeViewIndependent = iBrother._computeViewIndependent;
}
virtual WShape *duplicate()
@@ -740,14 +738,14 @@ public:
virtual ~WXShape() {}
- inline bool getComputeViewIndependantFlag() const
+ inline bool getComputeViewIndependentFlag() const
{
- return _computeViewIndependant;
+ return _computeViewIndependent;
}
- inline void setComputeViewIndependantFlag(bool iFlag)
+ inline void setComputeViewIndependentFlag(bool iFlag)
{
- _computeViewIndependant = iFlag;
+ _computeViewIndependent = iFlag;
}
/*! designed to build a specialized WFace for use in MakeFace */
@@ -778,7 +776,7 @@ public:
* The list of tex coords, iTexCoordsList[i] corresponding to the normal of the vertex iVertexList[i] for
* that face.
*/
- virtual WFace *MakeFace(vector<WVertex *>& iVertexList, vector<Vec3r>& iNormalsList, vector<Vec2r>& iTexCoordsList,
+ virtual WFace *MakeFace(vector<WVertex *>& iVertexList, vector<Vec3f>& iNormalsList, vector<Vec2f>& iTexCoordsList,
vector<bool>& iFaceEdgeMarksList, unsigned iMaterialIndex);
/*! Reset all edges and vertices flags (which might have been set up on a previous pass) */
@@ -801,7 +799,6 @@ public:
#ifdef WITH_CXX_GUARDEDALLOC
MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:WXShape")
#endif
-
};
/*
diff --git a/source/blender/freestyle/intern/winged_edge/WXEdgeBuilder.cpp b/source/blender/freestyle/intern/winged_edge/WXEdgeBuilder.cpp
index 590e03255f5..78773a9680d 100644
--- a/source/blender/freestyle/intern/winged_edge/WXEdgeBuilder.cpp
+++ b/source/blender/freestyle/intern/winged_edge/WXEdgeBuilder.cpp
@@ -45,11 +45,11 @@ void WXEdgeBuilder::visitIndexedFaceSet(IndexedFaceSet& ifs)
//ifs.setId(shape->GetId());
}
-void WXEdgeBuilder::buildWVertices(WShape& shape, const real *vertices, unsigned vsize)
+void WXEdgeBuilder::buildWVertices(WShape& shape, const float *vertices, unsigned vsize)
{
WXVertex *vertex;
for (unsigned int i = 0; i < vsize; i += 3) {
- vertex = new WXVertex(Vec3r(vertices[i], vertices[i + 1], vertices[i + 2]));
+ vertex = new WXVertex(Vec3f(vertices[i], vertices[i + 1], vertices[i + 2]));
vertex->setId(i / 3);
shape.AddVertex(vertex);
}
diff --git a/source/blender/freestyle/intern/winged_edge/WXEdgeBuilder.h b/source/blender/freestyle/intern/winged_edge/WXEdgeBuilder.h
index 143c2e33608..6df4efcd9b7 100644
--- a/source/blender/freestyle/intern/winged_edge/WXEdgeBuilder.h
+++ b/source/blender/freestyle/intern/winged_edge/WXEdgeBuilder.h
@@ -43,7 +43,7 @@ public:
VISIT_DECL(IndexedFaceSet)
protected:
- virtual void buildWVertices(WShape& shape, const real *vertices, unsigned vsize);
+ virtual void buildWVertices(WShape& shape, const float *vertices, unsigned vsize);
#ifdef WITH_CXX_GUARDEDALLOC
MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:WXEdgeBuilder")
diff --git a/source/blender/freestyle/intern/winged_edge/WingedEdgeBuilder.cpp b/source/blender/freestyle/intern/winged_edge/WingedEdgeBuilder.cpp
index c9f2f3badab..2ddc821da78 100644
--- a/source/blender/freestyle/intern/winged_edge/WingedEdgeBuilder.cpp
+++ b/source/blender/freestyle/intern/winged_edge/WingedEdgeBuilder.cpp
@@ -89,15 +89,15 @@ bool WingedEdgeBuilder::buildWShape(WShape& shape, IndexedFaceSet& ifs)
unsigned int nsize = ifs.nsize();
//soc unused - unsigned tsize = ifs.tsize();
- const real *vertices = ifs.vertices();
- const real *normals = ifs.normals();
- const real *texCoords = ifs.texCoords();
+ const float *vertices = ifs.vertices();
+ const float *normals = ifs.normals();
+ const float *texCoords = ifs.texCoords();
- real *new_vertices;
- real *new_normals;
+ float *new_vertices;
+ float *new_normals;
- new_vertices = new real[vsize];
- new_normals = new real[nsize];
+ new_vertices = new float[vsize];
+ new_normals = new float[nsize];
// transform coordinates from local to world system
if (_current_matrix) {
@@ -177,13 +177,15 @@ bool WingedEdgeBuilder::buildWShape(WShape& shape, IndexedFaceSet& ifs)
if (shape.GetFaceList().size() == 0) // this may happen due to degenerate triangles
return false;
+#if 0
// compute bbox
shape.ComputeBBox();
// compute mean edge size:
shape.ComputeMeanEdgeSize();
+#endif
// Parse the built winged-edge shape to update post-flags
- set<Vec3r> normalsSet;
+ set<Vec3f> normalsSet;
vector<WVertex *>& wvertices = shape.getVertexList();
for (vector<WVertex *>::iterator wv = wvertices.begin(), wvend = wvertices.end(); wv != wvend; ++wv) {
if ((*wv)->isBoundary())
@@ -211,18 +213,18 @@ bool WingedEdgeBuilder::buildWShape(WShape& shape, IndexedFaceSet& ifs)
return true;
}
-void WingedEdgeBuilder::buildWVertices(WShape& shape, const real *vertices, unsigned vsize)
+void WingedEdgeBuilder::buildWVertices(WShape& shape, const float *vertices, unsigned vsize)
{
WVertex *vertex;
for (unsigned int i = 0; i < vsize; i += 3) {
- vertex = new WVertex(Vec3r(vertices[i], vertices[i + 1], vertices[i + 2]));
+ vertex = new WVertex(Vec3f(vertices[i], vertices[i + 1], vertices[i + 2]));
vertex->setId(i / 3);
shape.AddVertex(vertex);
}
}
-void WingedEdgeBuilder::buildTriangleStrip(const real *vertices, const real *normals, vector<FrsMaterial>& iMaterials,
- const real *texCoords, const IndexedFaceSet::FaceEdgeMark *iFaceEdgeMarks,
+void WingedEdgeBuilder::buildTriangleStrip(const float * /*vertices*/, const float *normals, vector<FrsMaterial>& /*iMaterials*/,
+ const float *texCoords, const IndexedFaceSet::FaceEdgeMark *iFaceEdgeMarks,
const unsigned *vindices, const unsigned *nindices, const unsigned *mindices,
const unsigned *tindices, const unsigned nvertices)
{
@@ -232,8 +234,8 @@ void WingedEdgeBuilder::buildTriangleStrip(const real *vertices, const real *nor
WShape *currentShape = _current_wshape; // the current shape being built
vector<WVertex *> triangleVertices;
- vector<Vec3r> triangleNormals;
- vector<Vec2r> triangleTexCoords;
+ vector<Vec3f> triangleNormals;
+ vector<Vec2f> triangleTexCoords;
vector<bool> triangleFaceEdgeMarks;
while (nDoneVertices < nvertices) {
@@ -245,18 +247,18 @@ void WingedEdgeBuilder::buildTriangleStrip(const real *vertices, const real *nor
triangleVertices.push_back(currentShape->getVertexList()[vindices[nTriangle + 1] / 3]);
triangleVertices.push_back(currentShape->getVertexList()[vindices[nTriangle + 2] / 3]);
- triangleNormals.push_back(Vec3r(normals[nindices[nTriangle]], normals[nindices[nTriangle] + 1],
+ triangleNormals.push_back(Vec3f(normals[nindices[nTriangle]], normals[nindices[nTriangle] + 1],
normals[nindices[nTriangle] + 2]));
- triangleNormals.push_back(Vec3r(normals[nindices[nTriangle + 1]], normals[nindices[nTriangle + 1] + 1],
+ triangleNormals.push_back(Vec3f(normals[nindices[nTriangle + 1]], normals[nindices[nTriangle + 1] + 1],
normals[nindices[nTriangle + 1] + 2]));
- triangleNormals.push_back(Vec3r(normals[nindices[nTriangle + 2]], normals[nindices[nTriangle + 2] + 1],
+ triangleNormals.push_back(Vec3f(normals[nindices[nTriangle + 2]], normals[nindices[nTriangle + 2] + 1],
normals[nindices[nTriangle + 2] + 2]));
if (texCoords) {
- triangleTexCoords.push_back(Vec2r(texCoords[tindices[nTriangle]], texCoords[tindices[nTriangle] + 1]));
- triangleTexCoords.push_back(Vec2r(texCoords[tindices[nTriangle + 1]],
+ triangleTexCoords.push_back(Vec2f(texCoords[tindices[nTriangle]], texCoords[tindices[nTriangle] + 1]));
+ triangleTexCoords.push_back(Vec2f(texCoords[tindices[nTriangle + 1]],
texCoords[tindices[nTriangle + 1] + 1]));
- triangleTexCoords.push_back(Vec2r(texCoords[tindices[nTriangle + 2]],
+ triangleTexCoords.push_back(Vec2f(texCoords[tindices[nTriangle + 2]],
texCoords[tindices[nTriangle + 2] + 1]));
}
}
@@ -265,18 +267,18 @@ void WingedEdgeBuilder::buildTriangleStrip(const real *vertices, const real *nor
triangleVertices.push_back(currentShape->getVertexList()[vindices[nTriangle + 2] / 3]);
triangleVertices.push_back(currentShape->getVertexList()[vindices[nTriangle + 1] / 3]);
- triangleNormals.push_back(Vec3r(normals[nindices[nTriangle]], normals[nindices[nTriangle] + 1],
+ triangleNormals.push_back(Vec3f(normals[nindices[nTriangle]], normals[nindices[nTriangle] + 1],
normals[nindices[nTriangle] + 2]));
- triangleNormals.push_back(Vec3r(normals[nindices[nTriangle + 2]], normals[nindices[nTriangle + 2] + 1],
+ triangleNormals.push_back(Vec3f(normals[nindices[nTriangle + 2]], normals[nindices[nTriangle + 2] + 1],
normals[nindices[nTriangle + 2] + 2]));
- triangleNormals.push_back(Vec3r(normals[nindices[nTriangle + 1]], normals[nindices[nTriangle + 1] + 1],
+ triangleNormals.push_back(Vec3f(normals[nindices[nTriangle + 1]], normals[nindices[nTriangle + 1] + 1],
normals[nindices[nTriangle + 1] + 2]));
if (texCoords) {
- triangleTexCoords.push_back(Vec2r(texCoords[tindices[nTriangle]], texCoords[tindices[nTriangle] + 1]));
- triangleTexCoords.push_back(Vec2r(texCoords[tindices[nTriangle + 2]],
+ triangleTexCoords.push_back(Vec2f(texCoords[tindices[nTriangle]], texCoords[tindices[nTriangle] + 1]));
+ triangleTexCoords.push_back(Vec2f(texCoords[tindices[nTriangle + 2]],
texCoords[tindices[nTriangle + 2] + 1]));
- triangleTexCoords.push_back(Vec2r(texCoords[tindices[nTriangle + 1]],
+ triangleTexCoords.push_back(Vec2f(texCoords[tindices[nTriangle + 1]],
texCoords[tindices[nTriangle + 1] + 1]));
}
}
@@ -296,23 +298,23 @@ void WingedEdgeBuilder::buildTriangleStrip(const real *vertices, const real *nor
}
}
-void WingedEdgeBuilder::buildTriangleFan(const real *vertices, const real *normals, vector<FrsMaterial>& iMaterials,
- const real *texCoords, const IndexedFaceSet::FaceEdgeMark *iFaceEdgeMarks,
- const unsigned *vindices, const unsigned *nindices, const unsigned *mindices,
- const unsigned *tindices, const unsigned nvertices)
+void WingedEdgeBuilder::buildTriangleFan(const float * /*vertices*/, const float * /*normals*/, vector<FrsMaterial>& /*iMaterials*/,
+ const float * /*texCoords*/, const IndexedFaceSet::FaceEdgeMark * /*iFaceEdgeMarks*/,
+ const unsigned * /*vindices*/, const unsigned * /*nindices*/, const unsigned * /*mindices*/,
+ const unsigned * /*tindices*/, const unsigned /*nvertices*/)
{
// Nothing to be done
}
-void WingedEdgeBuilder::buildTriangles(const real *vertices, const real *normals, vector<FrsMaterial>& iMaterials,
- const real *texCoords, const IndexedFaceSet::FaceEdgeMark *iFaceEdgeMarks,
+void WingedEdgeBuilder::buildTriangles(const float * /*vertices*/, const float *normals, vector<FrsMaterial>& /*iMaterials*/,
+ const float *texCoords, const IndexedFaceSet::FaceEdgeMark *iFaceEdgeMarks,
const unsigned *vindices, const unsigned *nindices, const unsigned *mindices,
const unsigned *tindices, const unsigned nvertices)
{
WShape *currentShape = _current_wshape; // the current shape begin built
vector<WVertex *> triangleVertices;
- vector<Vec3r> triangleNormals;
- vector<Vec2r> triangleTexCoords;
+ vector<Vec3f> triangleNormals;
+ vector<Vec2f> triangleTexCoords;
vector<bool> triangleFaceEdgeMarks;
// Each triplet of vertices is considered as an independent triangle
@@ -321,17 +323,17 @@ void WingedEdgeBuilder::buildTriangles(const real *vertices, const real *normals
triangleVertices.push_back(currentShape->getVertexList()[vindices[3 * i + 1] / 3]);
triangleVertices.push_back(currentShape->getVertexList()[vindices[3 * i + 2] / 3]);
- triangleNormals.push_back(Vec3r(normals[nindices[3 * i]], normals[nindices[3 * i] + 1],
+ triangleNormals.push_back(Vec3f(normals[nindices[3 * i]], normals[nindices[3 * i] + 1],
normals[nindices[3 * i] + 2]));
- triangleNormals.push_back(Vec3r(normals[nindices[3 * i + 1]], normals[nindices[3 * i + 1] + 1],
+ triangleNormals.push_back(Vec3f(normals[nindices[3 * i + 1]], normals[nindices[3 * i + 1] + 1],
normals[nindices[3 * i + 1] + 2]));
- triangleNormals.push_back(Vec3r(normals[nindices[3 * i + 2]], normals[nindices[3 * i + 2] + 1],
+ triangleNormals.push_back(Vec3f(normals[nindices[3 * i + 2]], normals[nindices[3 * i + 2] + 1],
normals[nindices[3 * i + 2] + 2]));
if (texCoords) {
- triangleTexCoords.push_back(Vec2r(texCoords[tindices[3 * i]], texCoords[tindices[3 * i] + 1]));
- triangleTexCoords.push_back(Vec2r(texCoords[tindices[3 * i + 1]], texCoords[tindices[3 * i + 1] + 1]));
- triangleTexCoords.push_back(Vec2r(texCoords[tindices[3 * i + 2]], texCoords[tindices[3 * i + 2] + 1]));
+ triangleTexCoords.push_back(Vec2f(texCoords[tindices[3 * i]], texCoords[tindices[3 * i] + 1]));
+ triangleTexCoords.push_back(Vec2f(texCoords[tindices[3 * i + 1]], texCoords[tindices[3 * i + 1] + 1]));
+ triangleTexCoords.push_back(Vec2f(texCoords[tindices[3 * i + 2]], texCoords[tindices[3 * i + 2] + 1]));
}
triangleFaceEdgeMarks.push_back((iFaceEdgeMarks[i] & IndexedFaceSet::FACE_MARK) != 0);
@@ -346,10 +348,10 @@ void WingedEdgeBuilder::buildTriangles(const real *vertices, const real *normals
currentShape->MakeFace(triangleVertices, triangleNormals, triangleTexCoords, triangleFaceEdgeMarks, 0);
}
-void WingedEdgeBuilder::transformVertices(const real *vertices, unsigned vsize, const Matrix44r& transform, real *res)
+void WingedEdgeBuilder::transformVertices(const float *vertices, unsigned vsize, const Matrix44r& transform, float *res)
{
- const real *v = vertices;
- real *pv = res;
+ const float *v = vertices;
+ float *pv = res;
for (unsigned int i = 0; i < vsize / 3; i++) {
HVec3r hv_tmp(v[0], v[1], v[2]);
@@ -361,10 +363,10 @@ void WingedEdgeBuilder::transformVertices(const real *vertices, unsigned vsize,
}
}
-void WingedEdgeBuilder::transformNormals(const real *normals, unsigned nsize, const Matrix44r& transform, real *res)
+void WingedEdgeBuilder::transformNormals(const float *normals, unsigned nsize, const Matrix44r& transform, float *res)
{
- const real *n = normals;
- real *pn = res;
+ const float *n = normals;
+ float *pn = res;
for (unsigned int i = 0; i < nsize / 3; i++) {
Vec3r hn(n[0], n[1], n[2]);
diff --git a/source/blender/freestyle/intern/winged_edge/WingedEdgeBuilder.h b/source/blender/freestyle/intern/winged_edge/WingedEdgeBuilder.h
index 36f090f4ae9..5683b39fd28 100644
--- a/source/blender/freestyle/intern/winged_edge/WingedEdgeBuilder.h
+++ b/source/blender/freestyle/intern/winged_edge/WingedEdgeBuilder.h
@@ -118,29 +118,29 @@ public:
protected:
virtual bool buildWShape(WShape& shape, IndexedFaceSet& ifs);
- virtual void buildWVertices(WShape& shape, const real *vertices, unsigned vsize);
+ virtual void buildWVertices(WShape& shape, const float *vertices, unsigned vsize);
RenderMonitor *_pRenderMonitor;
private:
- void buildTriangleStrip(const real *vertices, const real *normals, vector<FrsMaterial>& iMaterials,
- const real *texCoords, const IndexedFaceSet::FaceEdgeMark *iFaceEdgeMarks,
+ void buildTriangleStrip(const float *vertices, const float *normals, vector<FrsMaterial>& iMaterials,
+ const float *texCoords, const IndexedFaceSet::FaceEdgeMark *iFaceEdgeMarks,
const unsigned *vindices, const unsigned *nindices, const unsigned *mindices,
const unsigned *tindices, const unsigned nvertices);
- void buildTriangleFan(const real *vertices, const real *normals, vector<FrsMaterial>& iMaterials,
- const real *texCoords, const IndexedFaceSet::FaceEdgeMark *iFaceEdgeMarks,
+ void buildTriangleFan(const float *vertices, const float *normals, vector<FrsMaterial>& iMaterials,
+ const float *texCoords, const IndexedFaceSet::FaceEdgeMark *iFaceEdgeMarks,
const unsigned *vindices, const unsigned *nindices, const unsigned *mindices,
const unsigned *tindices, const unsigned nvertices);
- void buildTriangles(const real *vertices, const real *normals, vector<FrsMaterial>& iMaterials,
- const real *texCoords, const IndexedFaceSet::FaceEdgeMark *iFaceEdgeMarks,
+ void buildTriangles(const float *vertices, const float *normals, vector<FrsMaterial>& iMaterials,
+ const float *texCoords, const IndexedFaceSet::FaceEdgeMark *iFaceEdgeMarks,
const unsigned *vindices, const unsigned *nindices, const unsigned *mindices,
const unsigned *tindices, const unsigned nvertices);
- void transformVertices(const real *vertices, unsigned vsize, const Matrix44r& transform, real *res);
+ void transformVertices(const float *vertices, unsigned vsize, const Matrix44r& transform, float *res);
- void transformNormals(const real *normals, unsigned nsize, const Matrix44r& transform, real *res);
+ void transformNormals(const float *normals, unsigned nsize, const Matrix44r& transform, float *res);
WShape *_current_wshape;
FrsMaterial *_current_frs_material;
@@ -151,7 +151,6 @@ private:
#ifdef WITH_CXX_GUARDEDALLOC
MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:WingedEdgeBuilder")
#endif
-
};
} /* namespace Freestyle */
diff --git a/source/blender/gpu/CMakeLists.txt b/source/blender/gpu/CMakeLists.txt
index 13e46bc7de8..328623f884f 100644
--- a/source/blender/gpu/CMakeLists.txt
+++ b/source/blender/gpu/CMakeLists.txt
@@ -36,6 +36,7 @@ set(INC
../nodes
../nodes/intern
+ ../../../intern/glew-mx
../../../intern/guardedalloc
../../../intern/smoke/extern
)
@@ -49,27 +50,69 @@ set(SRC
intern/gpu_codegen.c
intern/gpu_draw.c
intern/gpu_extensions.c
+ intern/gpu_init_exit.c
intern/gpu_material.c
intern/gpu_simple_shader.c
intern/gpu_select.c
+ intern/gpu_compositing.c
+ intern/gpu_debug.c
+
+ shaders/gpu_program_smoke_frag.glsl
+ shaders/gpu_program_smoke_color_frag.glsl
+
+ shaders/gpu_shader_fx_lib.glsl
+ shaders/gpu_shader_fx_ssao_frag.glsl
+ shaders/gpu_shader_fx_dof_frag.glsl
+ shaders/gpu_shader_fx_dof_vert.glsl
+ shaders/gpu_shader_fx_dof_hq_frag.glsl
+ shaders/gpu_shader_fx_dof_hq_vert.glsl
+ shaders/gpu_shader_fx_dof_hq_geo.glsl
+ shaders/gpu_shader_fx_vert.glsl
+ shaders/gpu_shader_material.glsl
+ shaders/gpu_shader_sep_gaussian_blur_frag.glsl
+ shaders/gpu_shader_sep_gaussian_blur_vert.glsl
+ shaders/gpu_shader_simple_frag.glsl
+ shaders/gpu_shader_simple_vert.glsl
+ shaders/gpu_shader_vertex.glsl
+ shaders/gpu_shader_vsm_store_frag.glsl
+ shaders/gpu_shader_vsm_store_vert.glsl
+ shaders/gpu_shader_fx_depth_resolve.glsl
GPU_buffers.h
GPU_draw.h
+ GPU_debug.h
GPU_extensions.h
+ GPU_glew.h
+ GPU_init_exit.h
GPU_material.h
GPU_simple_shader.h
GPU_select.h
+ GPU_compositing.h
intern/gpu_codegen.h
+ intern/gpu_private.h
)
+data_to_c_simple(shaders/gpu_shader_geometry.glsl SRC)
+data_to_c_simple(shaders/gpu_program_smoke_frag.glsl SRC)
+data_to_c_simple(shaders/gpu_program_smoke_color_frag.glsl SRC)
data_to_c_simple(shaders/gpu_shader_material.glsl SRC)
data_to_c_simple(shaders/gpu_shader_sep_gaussian_blur_frag.glsl SRC)
data_to_c_simple(shaders/gpu_shader_sep_gaussian_blur_vert.glsl SRC)
data_to_c_simple(shaders/gpu_shader_simple_frag.glsl SRC)
data_to_c_simple(shaders/gpu_shader_simple_vert.glsl SRC)
data_to_c_simple(shaders/gpu_shader_vertex.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_vertex_world.glsl SRC)
data_to_c_simple(shaders/gpu_shader_vsm_store_frag.glsl SRC)
data_to_c_simple(shaders/gpu_shader_vsm_store_vert.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_fx_vert.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_fx_ssao_frag.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_fx_dof_frag.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_fx_dof_vert.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_fx_dof_hq_frag.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_fx_dof_hq_vert.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_fx_dof_hq_geo.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_fx_depth_resolve.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_fx_lib.glsl SRC)
if(WITH_GAMEENGINE)
add_definitions(-DWITH_GAMEENGINE)
@@ -79,12 +122,15 @@ if(WITH_MOD_SMOKE)
add_definitions(-DWITH_SMOKE)
endif()
-add_definitions(-DGLEW_STATIC)
+add_definitions(${GL_DEFINITIONS})
if(WITH_IMAGE_DDS)
add_definitions(-DWITH_DDS)
endif()
+if(WITH_OPENSUBDIV)
+ add_definitions(-DWITH_OPENSUBDIV)
+endif()
blender_add_lib(bf_gpu "${SRC}" "${INC}" "${INC_SYS}")
diff --git a/source/blender/gpu/GPU_buffers.h b/source/blender/gpu/GPU_buffers.h
index ba461d5f8a2..e653af0c7ec 100644
--- a/source/blender/gpu/GPU_buffers.h
+++ b/source/blender/gpu/GPU_buffers.h
@@ -39,32 +39,41 @@
# define DEBUG_VBO(X)
#endif
+#include <stddef.h>
+
struct BMesh;
struct CCGElem;
struct CCGKey;
-struct CustomData;
struct DMFlagMat;
struct DerivedMesh;
-struct GHash;
struct GSet;
struct GPUVertPointLink;
+struct GPUDrawObject;
struct PBVH;
+struct MVert;
typedef struct GPUBuffer {
- int size; /* in bytes */
- void *pointer; /* used with vertex arrays */
- unsigned int id; /* used with vertex buffer objects */
+ size_t size; /* in bytes */
+ void *pointer; /* used with vertex arrays */
+ unsigned int id; /* used with vertex buffer objects */
+ bool use_vbo; /* true for VBOs, false for vertex arrays */
} GPUBuffer;
typedef struct GPUBufferMaterial {
/* range of points used for this material */
- int start;
- int totpoint;
+ unsigned int start;
+ unsigned int totelements;
+ unsigned int totloops;
+ unsigned int *polys; /* array of polygons for this material */
+ unsigned int totpolys; /* total polygons in polys */
+ unsigned int totvisiblepolys; /* total visible polygons */
/* original material index */
short mat_nr;
} GPUBufferMaterial;
+void GPU_buffer_material_finalize(struct GPUDrawObject *gdo, GPUBufferMaterial *matinfo, int totmat);
+
/* meshes are split up by material since changing materials requires
* GL state changes that can't occur in the middle of drawing an
* array.
@@ -85,12 +94,11 @@ typedef struct GPUDrawObject {
GPUBuffer *points;
GPUBuffer *normals;
GPUBuffer *uv;
+ GPUBuffer *uv_tex;
GPUBuffer *colors;
GPUBuffer *edges;
GPUBuffer *uvedges;
-
- /* for each triangle, the original MFace index */
- int *triangle_to_mface;
+ GPUBuffer *triangles; /* triangle index buffer */
/* for each original vertex, the list of related points */
struct GPUVertPointLink *vert_points;
@@ -107,18 +115,37 @@ typedef struct GPUDrawObject {
GPUBufferMaterial *materials;
int totmaterial;
- int tot_triangle_point;
- int tot_loose_point;
+ unsigned int tot_triangle_point;
+ unsigned int tot_loose_point;
+ /* different than total loops since ngons get tesselated still */
+ unsigned int tot_loop_verts;
/* caches of the original DerivedMesh values */
- int totvert;
- int totedge;
+ unsigned int totvert;
+ unsigned int totedge;
+
+ unsigned int loose_edge_offset;
+ unsigned int tot_loose_edge_drawn;
+ unsigned int tot_edge_drawn;
- /* if there was a failure allocating some buffer, use old
- * rendering code */
- bool legacy;
+ /* for subsurf, offset where drawing of interior edges starts */
+ unsigned int interior_offset;
+ unsigned int totinterior;
} GPUDrawObject;
+/* currently unused */
+// #define USE_GPU_POINT_LINK
+
+typedef struct GPUVertPointLink {
+#ifdef USE_GPU_POINT_LINK
+ struct GPUVertPointLink *next;
+#endif
+ /* -1 means uninitialized */
+ int point_index;
+} GPUVertPointLink;
+
+
+
/* used for GLSL materials */
typedef struct GPUAttrib {
int index;
@@ -129,12 +156,31 @@ typedef struct GPUAttrib {
void GPU_global_buffer_pool_free(void);
void GPU_global_buffer_pool_free_unused(void);
-GPUBuffer *GPU_buffer_alloc(int size);
+GPUBuffer *GPU_buffer_alloc(size_t size, bool force_vertex_arrays);
void GPU_buffer_free(GPUBuffer *buffer);
-GPUDrawObject *GPU_drawobject_new(struct DerivedMesh *dm);
void GPU_drawobject_free(struct DerivedMesh *dm);
+/* free special global multires grid buffer */
+void GPU_buffer_multires_free(bool force);
+
+/* flag that controls data type to fill buffer with, a modifier will prepare. */
+typedef enum {
+ GPU_BUFFER_VERTEX = 0,
+ GPU_BUFFER_NORMAL,
+ GPU_BUFFER_COLOR,
+ GPU_BUFFER_UV,
+ GPU_BUFFER_UV_TEXPAINT,
+ GPU_BUFFER_EDGE,
+ GPU_BUFFER_UVEDGE,
+ GPU_BUFFER_TRIANGLES
+} GPUBufferType;
+
+typedef enum {
+ GPU_BINDING_ARRAY = 0,
+ GPU_BINDING_INDEX = 1,
+} GPUBindingType;
+
/* called before drawing */
void GPU_vertex_setup(struct DerivedMesh *dm);
void GPU_normal_setup(struct DerivedMesh *dm);
@@ -142,15 +188,22 @@ void GPU_uv_setup(struct DerivedMesh *dm);
void GPU_texpaint_uv_setup(struct DerivedMesh *dm);
/* colType is the cddata MCol type to use! */
void GPU_color_setup(struct DerivedMesh *dm, int colType);
+void GPU_buffer_bind_as_color(GPUBuffer *buffer);
void GPU_edge_setup(struct DerivedMesh *dm); /* does not mix with other data */
void GPU_uvedge_setup(struct DerivedMesh *dm);
+
+void GPU_triangle_setup(struct DerivedMesh *dm);
+
int GPU_attrib_element_size(GPUAttrib data[], int numdata);
-void GPU_interleaved_attrib_setup(GPUBuffer *buffer, GPUAttrib data[], int numdata);
+void GPU_interleaved_attrib_setup(GPUBuffer *buffer, GPUAttrib data[], int numdata, int element_size);
+
+void GPU_buffer_bind(GPUBuffer *buffer, GPUBindingType binding);
+void GPU_buffer_unbind(GPUBuffer *buffer, GPUBindingType binding);
/* can't lock more than one buffer at once */
-void *GPU_buffer_lock(GPUBuffer *buffer);
-void *GPU_buffer_lock_stream(GPUBuffer *buffer);
-void GPU_buffer_unlock(GPUBuffer *buffer);
+void *GPU_buffer_lock(GPUBuffer *buffer, GPUBindingType binding);
+void *GPU_buffer_lock_stream(GPUBuffer *buffer, GPUBindingType binding);
+void GPU_buffer_unlock(GPUBuffer *buffer, GPUBindingType binding);
/* switch color rendering on=1/off=0 */
void GPU_color_switch(int mode);
@@ -159,29 +212,33 @@ void GPU_color_switch(int mode);
void GPU_buffer_draw_elements(GPUBuffer *elements, unsigned int mode, int start, int count);
/* called after drawing */
-void GPU_buffer_unbind(void);
+void GPU_buffers_unbind(void);
-/* used to check whether to use the old (without buffers) code */
-bool GPU_buffer_legacy(struct DerivedMesh *dm);
+/* only unbind interleaved data */
+void GPU_interleaved_attrib_unbind(void);
/* Buffers for non-DerivedMesh drawing */
typedef struct GPU_PBVH_Buffers GPU_PBVH_Buffers;
/* build */
-GPU_PBVH_Buffers *GPU_build_mesh_pbvh_buffers(int (*face_vert_indices)[4],
- struct MFace *mface, struct MVert *mvert,
- int *face_indices, int totface);
+GPU_PBVH_Buffers *GPU_build_mesh_pbvh_buffers(
+ const int (*face_vert_indices)[4],
+ const struct MPoly *mpoly, const struct MLoop *mloop, const struct MLoopTri *looptri,
+ const struct MVert *verts,
+ const int *face_indices,
+ const int face_indices_len);
GPU_PBVH_Buffers *GPU_build_grid_pbvh_buffers(int *grid_indices, int totgrid,
- unsigned int **grid_hidden, int gridsize);
+ unsigned int **grid_hidden, int gridsize, const struct CCGKey *key);
GPU_PBVH_Buffers *GPU_build_bmesh_pbvh_buffers(int smooth_shading);
/* update */
-void GPU_update_mesh_pbvh_buffers(GPU_PBVH_Buffers *buffers, MVert *mvert,
- int *vert_indices, int totvert, const float *vmask,
- int (*face_vert_indices)[4], bool show_diffuse_color);
+void GPU_update_mesh_pbvh_buffers(
+ GPU_PBVH_Buffers *buffers, const struct MVert *mvert,
+ const int *vert_indices, int totvert, const float *vmask,
+ const int (*face_vert_indices)[4], bool show_diffuse_color);
void GPU_update_bmesh_pbvh_buffers(GPU_PBVH_Buffers *buffers,
struct BMesh *bm,
@@ -197,7 +254,7 @@ void GPU_update_grid_pbvh_buffers(GPU_PBVH_Buffers *buffers, struct CCGElem **gr
/* draw */
void GPU_draw_pbvh_buffers(GPU_PBVH_Buffers *buffers, DMSetMaterial setMaterial,
- bool wireframe);
+ bool wireframe, bool fast);
/* debug PBVH draw*/
void GPU_draw_pbvh_BB(float min[3], float max[3], bool leaf);
diff --git a/source/blender/gpu/GPU_compositing.h b/source/blender/gpu/GPU_compositing.h
new file mode 100644
index 00000000000..04e89da00a7
--- /dev/null
+++ b/source/blender/gpu/GPU_compositing.h
@@ -0,0 +1,99 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2005 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Antony Riakiotakis.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file GPU_compositing.h
+ * \ingroup gpu
+ */
+
+#ifndef __GPU_COMPOSITING_H__
+#define __GPU_COMPOSITING_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* opaque handle for framebuffer compositing effects (defined in gpu_compositing.c )*/
+typedef struct GPUFX GPUFX;
+struct GPUDOFSettings;
+struct GPUSSAOSettings;
+struct GPUOffScreen;
+struct GPUFXSettings;
+struct rcti;
+struct Scene;
+enum eGPUFXFlags;
+
+/**** Public API *****/
+
+typedef enum GPUFXShaderEffect {
+ /* Screen space ambient occlusion shader */
+ GPU_SHADER_FX_SSAO = 1,
+
+ /* depth of field passes. Yep, quite a complex effect */
+ GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_ONE = 2,
+ GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_TWO = 3,
+ GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_THREE = 4,
+ GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_FOUR = 5,
+ GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_FIVE = 6,
+
+ /* high quality */
+ GPU_SHADER_FX_DEPTH_OF_FIELD_HQ_PASS_ONE = 7,
+ GPU_SHADER_FX_DEPTH_OF_FIELD_HQ_PASS_TWO = 8,
+ GPU_SHADER_FX_DEPTH_OF_FIELD_HQ_PASS_THREE = 9,
+
+ GPU_SHADER_FX_DEPTH_RESOLVE = 10,
+} GPUFXShaderEffect;
+
+/* keep in synch with enum above! */
+#define MAX_FX_SHADERS 11
+
+/* generate a new FX compositor */
+GPUFX *GPU_fx_compositor_create(void);
+
+/* destroy a text compositor */
+void GPU_fx_compositor_destroy(GPUFX *fx);
+
+/* initialize a framebuffer with size taken from the viewport */
+bool GPU_fx_compositor_initialize_passes(
+ GPUFX *fx, const struct rcti *rect, const struct rcti *scissor_rect,
+ const struct GPUFXSettings *fx_settings);
+
+/* do compositing on the fx passes that have been initialized */
+bool GPU_fx_do_composite_pass(GPUFX *fx, float projmat[4][4], bool is_persp, struct Scene *scene, struct GPUOffScreen *ofs);
+
+/* bind new depth buffer for XRay pass */
+void GPU_fx_compositor_setup_XRay_pass(GPUFX *fx, bool do_xray);
+
+/* resolve a final depth buffer by compositing the XRay and normal depth buffers */
+void GPU_fx_compositor_XRay_resolve(GPUFX *fx);
+
+void GPU_fx_compositor_init_dof_settings(struct GPUDOFSettings *dof);
+void GPU_fx_compositor_init_ssao_settings(struct GPUSSAOSettings *ssao);
+#ifdef __cplusplus
+}
+#endif
+
+#endif // __GPU_COMPOSITING_H__
diff --git a/source/blender/gpu/GPU_debug.h b/source/blender/gpu/GPU_debug.h
new file mode 100644
index 00000000000..2c1728bfff1
--- /dev/null
+++ b/source/blender/gpu/GPU_debug.h
@@ -0,0 +1,71 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2005 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Jason Wilkins.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/gpu/GPU_debug.h
+ * \ingroup gpu
+ */
+
+#ifndef __GPU_DEBUG_H__
+#define __GPU_DEBUG_H__
+
+#include "GPU_glew.h"
+
+#include "BLI_utildefines.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* prints something if debug mode is active only */
+void GPU_print_error_debug(const char *str);
+
+/* replacement for gluErrorString */
+const char *gpuErrorString(GLenum err);
+
+/* prints current OpenGL state */
+void GPU_state_print(void);
+
+void GPU_assert_no_gl_errors(const char *file, int line, const char *str);
+
+# define GPU_ASSERT_NO_GL_ERRORS(str) GPU_assert_no_gl_errors(__FILE__, __LINE__, (str))
+
+# define GPU_CHECK_ERRORS_AROUND(glProcCall) \
+ ( \
+ GPU_ASSERT_NO_GL_ERRORS("Pre: " #glProcCall), \
+ (glProcCall), \
+ GPU_ASSERT_NO_GL_ERRORS("Post: " #glProcCall) \
+ )
+
+
+/* inserts a debug marker message for the debug context messaging system */
+void GPU_string_marker(size_t size, const char *str);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __GPU_DEBUG_H__ */
diff --git a/source/blender/gpu/GPU_draw.h b/source/blender/gpu/GPU_draw.h
index 3ddec157c49..0992f8e9d21 100644
--- a/source/blender/gpu/GPU_draw.h
+++ b/source/blender/gpu/GPU_draw.h
@@ -36,14 +36,16 @@
extern "C" {
#endif
+struct ImBuf;
struct Image;
struct ImageUser;
-struct MTFace;
+struct MTexPoly;
struct Object;
struct Scene;
struct View3D;
struct RegionView3D;
struct SmokeModifierData;
+struct DupliObject;
/* OpenGL drawing functions related to shading. These are also
* shared with the game engine, where there were previously
@@ -57,10 +59,6 @@ struct SmokeModifierData;
void GPU_state_init(void);
-/* Debugging */
-
-void GPU_state_print(void);
-
/* Material drawing
* - first the state is initialized by a particular object and
* it's materials
@@ -71,10 +69,14 @@ void GPU_state_print(void);
void GPU_begin_object_materials(struct View3D *v3d, struct RegionView3D *rv3d,
struct Scene *scene, struct Object *ob, bool glsl, bool *do_alpha_after);
void GPU_end_object_materials(void);
+bool GPU_object_materials_check(void);
int GPU_enable_material(int nr, void *attribs);
void GPU_disable_material(void);
+void GPU_begin_dupli_object(struct DupliObject *dob);
+void GPU_end_dupli_object(void);
+
void GPU_material_diffuse_get(int nr, float diff[4]);
bool GPU_material_use_matcaps_get(void);
@@ -86,8 +88,9 @@ int GPU_get_material_alpha_blend(void);
* be drawn using one or the other
* - passing NULL clears the state again */
-int GPU_set_tpage(struct MTFace *tface, int mipmap, int transp);
+int GPU_set_tpage(struct MTexPoly *mtexpoly, int mipmap, int transp);
void GPU_clear_tpage(bool force);
+
/* Lights
* - returns how many lights were enabled
* - this affects fixed functions materials and texface, not glsl */
@@ -99,18 +102,20 @@ int GPU_scene_object_lights(struct Scene *scene, struct Object *ob,
/* Text render
* - based on moving uv coordinates */
-void GPU_render_text(struct MTFace *tface, int mode,
- const char *textstr, int textlen, unsigned int *col,
- float *v1, float *v2, float *v3, float *v4, int glattrib);
+void GPU_render_text(
+ struct MTexPoly *mtexpoly, int mode,
+ const char *textstr, int textlen, unsigned int *col,
+ const float *v_quad[4], const float *uv_quad[4],
+ int glattrib);
/* Mipmap settings
* - these will free textures on changes */
-void GPU_set_mipmap(int mipmap);
-int GPU_get_mipmap(void);
-void GPU_set_linear_mipmap(int linear);
-int GPU_get_linear_mipmap(void);
-void GPU_paint_set_mipmap(int mipmap);
+void GPU_set_mipmap(bool mipmap);
+bool GPU_get_mipmap(void);
+void GPU_set_linear_mipmap(bool linear);
+bool GPU_get_linear_mipmap(void);
+void GPU_paint_set_mipmap(bool mipmap);
/* Anisotropic filtering settings
* - these will free textures on changes */
@@ -123,11 +128,11 @@ void GPU_set_gpu_mipmapping(int gpu_mipmap);
/* Image updates and free
* - these deal with images bound as opengl textures */
-void GPU_paint_update_image(struct Image *ima, int x, int y, int w, int h);
+void GPU_paint_update_image(struct Image *ima, ImageUser *iuser, int x, int y, int w, int h);
void GPU_update_images_framechange(void);
int GPU_update_image_time(struct Image *ima, double time);
int GPU_verify_image(struct Image *ima, struct ImageUser *iuser, int tftile, bool compare, bool mipmap, bool is_data);
-void GPU_create_gl_tex(unsigned int *bind, unsigned int *pix, float *frect, int rectw, int recth,
+void GPU_create_gl_tex(unsigned int *bind, unsigned int *rect, float *frect, int rectw, int recth,
bool mipmap, bool use_hight_bit_depth, struct Image *ima);
void GPU_create_gl_tex_compressed(unsigned int *bind, unsigned int *pix, int x, int y, int mipmap, struct Image *ima, struct ImBuf *ibuf);
bool GPU_upload_dxt_texture(struct ImBuf *ibuf);
@@ -143,6 +148,11 @@ void GPU_create_smoke(struct SmokeModifierData *smd, int highres);
/* Delayed free of OpenGL buffers by main thread */
void GPU_free_unused_buffers(void);
+#ifdef WITH_OPENSUBDIV
+struct DerivedMesh;
+void GPU_draw_update_fvar_offset(struct DerivedMesh *dm);
+#endif
+
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/gpu/GPU_extensions.h b/source/blender/gpu/GPU_extensions.h
index 04c4119df6e..0e8d204d224 100644
--- a/source/blender/gpu/GPU_extensions.h
+++ b/source/blender/gpu/GPU_extensions.h
@@ -52,48 +52,56 @@ typedef struct GPUOffScreen GPUOffScreen;
struct GPUShader;
typedef struct GPUShader GPUShader;
+struct GPUProgram;
+typedef struct GPUProgram GPUProgram;
+
/* GPU extensions support */
void GPU_extensions_disable(void);
-void GPU_extensions_init(void); /* call this before running any of the functions below */
-void GPU_extensions_exit(void);
-int GPU_print_error(const char *str);
-int GPU_glsl_support(void);
-int GPU_non_power_of_two_support(void);
-int GPU_display_list_support(void);
+bool GPU_glsl_support(void);
+bool GPU_non_power_of_two_support(void);
+bool GPU_vertex_buffer_support(void);
+bool GPU_display_list_support(void);
+bool GPU_bicubic_bump_support(void);
+bool GPU_geometry_shader_support(void);
+bool GPU_instanced_drawing_support(void);
+
+int GPU_max_texture_size(void);
int GPU_color_depth(void);
-void GPU_code_generate_glsl_lib(void);
-int GPU_bicubic_bump_support(void);
-int GPU_max_texture_size (void);
+void GPU_get_dfdy_factors(float fac[2]);
+
+bool GPU_mem_stats_supported(void);
+void GPU_mem_stats_get(int *totalmem, int *freemem);
+void GPU_code_generate_glsl_lib(void);
/* GPU Types */
typedef enum GPUDeviceType {
- GPU_DEVICE_NVIDIA = (1<<0),
- GPU_DEVICE_ATI = (1<<1),
- GPU_DEVICE_INTEL = (1<<2),
- GPU_DEVICE_SOFTWARE = (1<<3),
- GPU_DEVICE_UNKNOWN = (1<<4),
- GPU_DEVICE_ANY = (0xff)
+ GPU_DEVICE_NVIDIA = (1<<0),
+ GPU_DEVICE_ATI = (1<<1),
+ GPU_DEVICE_INTEL = (1<<2),
+ GPU_DEVICE_SOFTWARE = (1<<3),
+ GPU_DEVICE_UNKNOWN = (1<<4),
+ GPU_DEVICE_ANY = (0xff)
} GPUDeviceType;
typedef enum GPUOSType {
- GPU_OS_WIN = (1<<8),
- GPU_OS_MAC = (1<<9),
- GPU_OS_UNIX = (1<<10),
- GPU_OS_ANY = (0xff00)
+ GPU_OS_WIN = (1<<8),
+ GPU_OS_MAC = (1<<9),
+ GPU_OS_UNIX = (1<<10),
+ GPU_OS_ANY = (0xff00)
} GPUOSType;
typedef enum GPUDriverType {
- GPU_DRIVER_OFFICIAL = (1<<16),
+ GPU_DRIVER_OFFICIAL = (1<<16),
GPU_DRIVER_OPENSOURCE = (1<<17),
- GPU_DRIVER_SOFTWARE = (1<<18),
- GPU_DRIVER_ANY = (0xff0000)
+ GPU_DRIVER_SOFTWARE = (1<<18),
+ GPU_DRIVER_ANY = (0xff0000)
} GPUDriverType;
-int GPU_type_matches(GPUDeviceType device, GPUOSType os, GPUDriverType driver);
+bool GPU_type_matches(GPUDeviceType device, GPUOSType os, GPUDriverType driver);
/* GPU Texture
* - always returns unsigned char RGBA textures
@@ -109,11 +117,19 @@ int GPU_type_matches(GPUDeviceType device, GPUOSType os, GPUDriverType driver);
* - if created with from_blender, will not free the texture
*/
-GPUTexture *GPU_texture_create_1D(int w, float *pixels, char err_out[256]);
-GPUTexture *GPU_texture_create_2D(int w, int h, float *pixels, char err_out[256]);
-GPUTexture *GPU_texture_create_3D(int w, int h, int depth, int channels, float *fpixels);
+typedef enum GPUHDRType {
+ GPU_HDR_NONE = 0,
+ GPU_HDR_HALF_FLOAT = 1,
+ GPU_HDR_FULL_FLOAT = (1 << 1),
+} GPUHDRType;
+
+GPUTexture *GPU_texture_create_1D(int w, const float *pixels, char err_out[256]);
+GPUTexture *GPU_texture_create_2D(int w, int h, const float *pixels, GPUHDRType hdr, char err_out[256]);
+GPUTexture *GPU_texture_create_3D(int w, int h, int depth, int channels, const float *fpixels);
GPUTexture *GPU_texture_create_depth(int w, int h, char err_out[256]);
GPUTexture *GPU_texture_create_vsm_shadow_map(int size, char err_out[256]);
+GPUTexture *GPU_texture_create_2D_procedural(int w, int h, const float *pixels, bool repeat, char err_out[256]);
+GPUTexture *GPU_texture_create_1D_procedural(int w, const float *pixels, char err_out[256]);
GPUTexture *GPU_texture_from_blender(struct Image *ima,
struct ImageUser *iuser, bool is_data, double time, int mipmap);
GPUTexture *GPU_texture_from_preview(struct PreviewImage *prv, int mipmap);
@@ -128,12 +144,14 @@ void GPU_texture_ref(GPUTexture *tex);
void GPU_texture_bind(GPUTexture *tex, int number);
void GPU_texture_unbind(GPUTexture *tex);
+void GPU_texture_filter_mode(GPUTexture *tex, bool compare, bool use_filter);
+
GPUFrameBuffer *GPU_texture_framebuffer(GPUTexture *tex);
-int GPU_texture_target(GPUTexture *tex);
-int GPU_texture_opengl_width(GPUTexture *tex);
-int GPU_texture_opengl_height(GPUTexture *tex);
-int GPU_texture_opengl_bindcode(GPUTexture *tex);
+int GPU_texture_target(const GPUTexture *tex);
+int GPU_texture_opengl_width(const GPUTexture *tex);
+int GPU_texture_opengl_height(const GPUTexture *tex);
+int GPU_texture_opengl_bindcode(const GPUTexture *tex);
/* GPU Framebuffer
* - this is a wrapper for an OpenGL framebuffer object (FBO). in practice
@@ -142,12 +160,17 @@ int GPU_texture_opengl_bindcode(GPUTexture *tex);
* - after any of the GPU_framebuffer_* functions, GPU_framebuffer_restore must
* be called before rendering to the window framebuffer again */
+void GPU_texture_bind_as_framebuffer(GPUTexture *tex);
+
GPUFrameBuffer *GPU_framebuffer_create(void);
-int GPU_framebuffer_texture_attach(GPUFrameBuffer *fb, GPUTexture *tex, char err_out[256]);
-void GPU_framebuffer_texture_detach(GPUFrameBuffer *fb, GPUTexture *tex);
-void GPU_framebuffer_texture_bind(GPUFrameBuffer *fb, GPUTexture *tex, int w, int h);
+int GPU_framebuffer_texture_attach(GPUFrameBuffer *fb, GPUTexture *tex, int slot, char err_out[256]);
+void GPU_framebuffer_texture_detach(GPUTexture *tex);
+void GPU_framebuffer_slots_bind(GPUFrameBuffer *fb, int slot);
void GPU_framebuffer_texture_unbind(GPUFrameBuffer *fb, GPUTexture *tex);
void GPU_framebuffer_free(GPUFrameBuffer *fb);
+bool GPU_framebuffer_check_valid(GPUFrameBuffer *fb, char err_out[256]);
+
+void GPU_framebuffer_bind_no_save(GPUFrameBuffer *fb, int slot);
void GPU_framebuffer_restore(void);
void GPU_framebuffer_blur(GPUFrameBuffer *fb, GPUTexture *tex, GPUFrameBuffer *blurfb, GPUTexture *blurtex);
@@ -158,17 +181,42 @@ void GPU_framebuffer_blur(GPUFrameBuffer *fb, GPUTexture *tex, GPUFrameBuffer *b
GPUOffScreen *GPU_offscreen_create(int width, int height, char err_out[256]);
void GPU_offscreen_free(GPUOffScreen *ofs);
-void GPU_offscreen_bind(GPUOffScreen *ofs);
-void GPU_offscreen_unbind(GPUOffScreen *ofs);
+void GPU_offscreen_bind(GPUOffScreen *ofs, bool save);
+void GPU_offscreen_unbind(GPUOffScreen *ofs, bool restore);
void GPU_offscreen_read_pixels(GPUOffScreen *ofs, int type, void *pixels);
-int GPU_offscreen_width(GPUOffScreen *ofs);
-int GPU_offscreen_height(GPUOffScreen *ofs);
+int GPU_offscreen_width(const GPUOffScreen *ofs);
+int GPU_offscreen_height(const GPUOffScreen *ofs);
+
+/* Builtin/Non-generated shaders */
+typedef enum GPUProgramType {
+ GPU_PROGRAM_TYPE_FRAGMENT = 0
+} GPUProgramType;
+
+
+GPUProgram *GPU_program_shader_create(GPUProgramType type, const char *code);
+void GPU_program_free(GPUProgram *program);
+void GPU_program_parameter_4f(GPUProgram *program, unsigned int location, float x, float y, float z, float w);
+void GPU_program_bind(GPUProgram *);
+void GPU_program_unbind(GPUProgram *);
/* GPU Shader
* - only for fragment shaders now
* - must call texture bind before setting a texture as uniform! */
-GPUShader *GPU_shader_create(const char *vertexcode, const char *fragcode, const char *libcode, const char *defines);
+GPUShader *GPU_shader_create(const char *vertexcode, const char *fragcode, const char *geocode, const char *libcode, const char *defines, int input, int output, int number);
+enum {
+ GPU_SHADER_FLAGS_NONE = 0,
+ GPU_SHADER_FLAGS_SPECIAL_OPENSUBDIV = (1 << 0),
+};
+GPUShader *GPU_shader_create_ex(const char *vertexcode,
+ const char *fragcode,
+ const char *geocode,
+ const char *libcode,
+ const char *defines,
+ int input,
+ int output,
+ int number,
+ const int flags);
void GPU_shader_free(GPUShader *shader);
void GPU_shader_bind(GPUShader *shader);
@@ -176,24 +224,36 @@ void GPU_shader_unbind(void);
int GPU_shader_get_uniform(GPUShader *shader, const char *name);
void GPU_shader_uniform_vector(GPUShader *shader, int location, int length,
- int arraysize, float *value);
+ int arraysize, const float *value);
+void GPU_shader_uniform_vector_int(GPUShader *shader, int location, int length,
+ int arraysize, const int *value);
+
void GPU_shader_uniform_texture(GPUShader *shader, int location, GPUTexture *tex);
void GPU_shader_uniform_int(GPUShader *shader, int location, int value);
+void GPU_shader_geometry_stage_primitive_io(GPUShader *shader, int input, int output, int number);
int GPU_shader_get_attribute(GPUShader *shader, const char *name);
/* Builtin/Non-generated shaders */
typedef enum GPUBuiltinShader {
- GPU_SHADER_VSM_STORE = (1<<0),
- GPU_SHADER_SEP_GAUSSIAN_BLUR = (1<<1),
+ GPU_SHADER_VSM_STORE = 0,
+ GPU_SHADER_SEP_GAUSSIAN_BLUR = 1,
} GPUBuiltinShader;
+typedef enum GPUBuiltinProgram {
+ GPU_PROGRAM_SMOKE = 0,
+ GPU_PROGRAM_SMOKE_COLORED = 1,
+} GPUBuiltinProgram;
+
GPUShader *GPU_shader_get_builtin_shader(GPUBuiltinShader shader);
+GPUProgram *GPU_shader_get_builtin_program(GPUBuiltinProgram program);
+GPUShader *GPU_shader_get_builtin_fx_shader(int effects, bool persp);
+
void GPU_shader_free_builtin_shaders(void);
/* Vertex attributes for shaders */
-#define GPU_MAX_ATTRIB 32
+#define GPU_MAX_ATTRIB 32
typedef struct GPUVertexAttribs {
struct {
diff --git a/source/blender/gpu/GPU_glew.h b/source/blender/gpu/GPU_glew.h
new file mode 100644
index 00000000000..94217863fd6
--- /dev/null
+++ b/source/blender/gpu/GPU_glew.h
@@ -0,0 +1,37 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2012 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Jason Wilkins.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/gpu/GPU_glew.h
+ * \ingroup gpu
+ */
+
+#ifndef __GPU_GLEW_H__
+#define __GPU_GLEW_H__
+
+#include "glew-mx.h"
+
+#endif /* __GPU_GLEW_H__ */
diff --git a/source/blender/gpu/GPU_init_exit.h b/source/blender/gpu/GPU_init_exit.h
new file mode 100644
index 00000000000..e89c970b7d9
--- /dev/null
+++ b/source/blender/gpu/GPU_init_exit.h
@@ -0,0 +1,46 @@
+/*
+ * ***** 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): Jason Wilkins.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/gpu/GPU_init_exit.h
+ * \ingroup gpu
+ */
+
+#ifndef __GPU_INIT_EXIT_H__
+#define __GPU_INIT_EXIT_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void GPU_init(void);
+void GPU_exit(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __GPU_INIT_EXIT_H__ */
diff --git a/source/blender/gpu/GPU_material.h b/source/blender/gpu/GPU_material.h
index 8d44ad87916..dd08ed83e5a 100644
--- a/source/blender/gpu/GPU_material.h
+++ b/source/blender/gpu/GPU_material.h
@@ -32,8 +32,11 @@
#ifndef __GPU_MATERIAL_H__
#define __GPU_MATERIAL_H__
+#include "DNA_customdata_types.h" /* for CustomDataType */
#include "DNA_listBase.h"
+#include "BLI_sys_types.h" /* for bool */
+
#ifdef __cplusplus
extern "C" {
#endif
@@ -42,10 +45,7 @@ struct Image;
struct ImageUser;
struct Material;
struct Object;
-struct Lamp;
struct Image;
-struct bNode;
-struct LinkNode;
struct Scene;
struct SceneRenderLayer;
struct GPUVertexAttribs;
@@ -56,15 +56,18 @@ struct GPUMaterial;
struct GPUTexture;
struct GPULamp;
struct PreviewImage;
+struct World;
typedef struct GPUNode GPUNode;
typedef struct GPUNodeLink GPUNodeLink;
typedef struct GPUMaterial GPUMaterial;
typedef struct GPULamp GPULamp;
+typedef struct GPUParticleInfo GPUParticleInfo;
/* Functions to create GPU Materials nodes */
typedef enum GPUType {
+ /* The value indicates the number of elements in each type */
GPU_NONE = 0,
GPU_FLOAT = 1,
GPU_VEC2 = 2,
@@ -72,20 +75,26 @@ typedef enum GPUType {
GPU_VEC4 = 4,
GPU_MAT3 = 9,
GPU_MAT4 = 16,
+
GPU_TEX2D = 1002,
GPU_SHADOW2D = 1003,
GPU_ATTRIB = 3001
} GPUType;
typedef enum GPUBuiltin {
- GPU_VIEW_MATRIX = 1,
- GPU_OBJECT_MATRIX = 2,
- GPU_INVERSE_VIEW_MATRIX = 4,
- GPU_INVERSE_OBJECT_MATRIX = 8,
- GPU_VIEW_POSITION = 16,
- GPU_VIEW_NORMAL = 32,
- GPU_OBCOLOR = 64,
- GPU_AUTO_BUMPSCALE = 128,
+ GPU_VIEW_MATRIX = (1 << 0),
+ GPU_OBJECT_MATRIX = (1 << 1),
+ GPU_INVERSE_VIEW_MATRIX = (1 << 2),
+ GPU_INVERSE_OBJECT_MATRIX = (1 << 3),
+ GPU_VIEW_POSITION = (1 << 4),
+ GPU_VIEW_NORMAL = (1 << 5),
+ GPU_OBCOLOR = (1 << 6),
+ GPU_AUTO_BUMPSCALE = (1 << 7),
+ GPU_CAMERA_TEXCO_FACTORS = (1 << 8),
+ GPU_PARTICLE_SCALAR_PROPS = (1 << 9),
+ GPU_PARTICLE_LOCATION = (1 << 10),
+ GPU_PARTICLE_VELOCITY = (1 << 11),
+ GPU_PARTICLE_ANG_VELOCITY = (1 << 12),
} GPUBuiltin;
typedef enum GPUOpenGLBuiltin {
@@ -93,12 +102,19 @@ typedef enum GPUOpenGLBuiltin {
GPU_COLOR = 2,
} GPUOpenGLBuiltin;
+typedef enum GPUMatType {
+ GPU_MATERIAL_TYPE_MESH = 1,
+ GPU_MATERIAL_TYPE_WORLD = 2,
+} GPUMatType;
+
+
typedef enum GPUBlendMode {
GPU_BLEND_SOLID = 0,
GPU_BLEND_ADD = 1,
GPU_BLEND_ALPHA = 2,
GPU_BLEND_CLIP = 4,
- GPU_BLEND_ALPHA_SORT = 8
+ GPU_BLEND_ALPHA_SORT = 8,
+ GPU_BLEND_ALPHA_TO_COVERAGE = 16
} GPUBlendMode;
typedef struct GPUNodeStack {
@@ -111,15 +127,74 @@ typedef struct GPUNodeStack {
short sockettype;
} GPUNodeStack;
-GPUNodeLink *GPU_attribute(int type, const char *name);
+
+#define GPU_DYNAMIC_GROUP_FROM_TYPE(f) ((f) & 0xFFFF0000)
+
+#define GPU_DYNAMIC_GROUP_MISC 0x00010000
+#define GPU_DYNAMIC_GROUP_LAMP 0x00020000
+#define GPU_DYNAMIC_GROUP_OBJECT 0x00030000
+#define GPU_DYNAMIC_GROUP_SAMPLER 0x00040000
+#define GPU_DYNAMIC_GROUP_MIST 0x00050000
+#define GPU_DYNAMIC_GROUP_WORLD 0x00060000
+#define GPU_DYNAMIC_GROUP_MAT 0x00070000
+
+typedef enum GPUDynamicType {
+
+ GPU_DYNAMIC_NONE = 0,
+
+ GPU_DYNAMIC_OBJECT_VIEWMAT = 1 | GPU_DYNAMIC_GROUP_OBJECT,
+ GPU_DYNAMIC_OBJECT_MAT = 2 | GPU_DYNAMIC_GROUP_OBJECT,
+ GPU_DYNAMIC_OBJECT_VIEWIMAT = 3 | GPU_DYNAMIC_GROUP_OBJECT,
+ GPU_DYNAMIC_OBJECT_IMAT = 4 | GPU_DYNAMIC_GROUP_OBJECT,
+ GPU_DYNAMIC_OBJECT_COLOR = 5 | GPU_DYNAMIC_GROUP_OBJECT,
+ GPU_DYNAMIC_OBJECT_AUTOBUMPSCALE = 6 | GPU_DYNAMIC_GROUP_OBJECT,
+
+ GPU_DYNAMIC_LAMP_DYNVEC = 1 | GPU_DYNAMIC_GROUP_LAMP,
+ GPU_DYNAMIC_LAMP_DYNCO = 2 | GPU_DYNAMIC_GROUP_LAMP,
+ GPU_DYNAMIC_LAMP_DYNIMAT = 3 | GPU_DYNAMIC_GROUP_LAMP,
+ GPU_DYNAMIC_LAMP_DYNPERSMAT = 4 | GPU_DYNAMIC_GROUP_LAMP,
+ GPU_DYNAMIC_LAMP_DYNENERGY = 5 | GPU_DYNAMIC_GROUP_LAMP,
+ GPU_DYNAMIC_LAMP_DYNCOL = 6 | GPU_DYNAMIC_GROUP_LAMP,
+ GPU_DYNAMIC_LAMP_DISTANCE = 7 | GPU_DYNAMIC_GROUP_LAMP,
+ GPU_DYNAMIC_LAMP_ATT1 = 8 | GPU_DYNAMIC_GROUP_LAMP,
+ GPU_DYNAMIC_LAMP_ATT2 = 9 | GPU_DYNAMIC_GROUP_LAMP,
+ GPU_DYNAMIC_LAMP_SPOTSIZE = 10 | GPU_DYNAMIC_GROUP_LAMP,
+ GPU_DYNAMIC_LAMP_SPOTBLEND = 11 | GPU_DYNAMIC_GROUP_LAMP,
+
+ GPU_DYNAMIC_SAMPLER_2DBUFFER = 1 | GPU_DYNAMIC_GROUP_SAMPLER,
+ GPU_DYNAMIC_SAMPLER_2DIMAGE = 2 | GPU_DYNAMIC_GROUP_SAMPLER,
+ GPU_DYNAMIC_SAMPLER_2DSHADOW = 3 | GPU_DYNAMIC_GROUP_SAMPLER,
+
+ GPU_DYNAMIC_MIST_ENABLE = 1 | GPU_DYNAMIC_GROUP_MIST,
+ GPU_DYNAMIC_MIST_START = 2 | GPU_DYNAMIC_GROUP_MIST,
+ GPU_DYNAMIC_MIST_DISTANCE = 3 | GPU_DYNAMIC_GROUP_MIST,
+ GPU_DYNAMIC_MIST_INTENSITY = 4 | GPU_DYNAMIC_GROUP_MIST,
+ GPU_DYNAMIC_MIST_TYPE = 5 | GPU_DYNAMIC_GROUP_MIST,
+ GPU_DYNAMIC_MIST_COLOR = 6 | GPU_DYNAMIC_GROUP_MIST,
+
+ GPU_DYNAMIC_HORIZON_COLOR = 1 | GPU_DYNAMIC_GROUP_WORLD,
+ GPU_DYNAMIC_AMBIENT_COLOR = 2 | GPU_DYNAMIC_GROUP_WORLD,
+
+ GPU_DYNAMIC_MAT_DIFFRGB = 1 | GPU_DYNAMIC_GROUP_MAT,
+ GPU_DYNAMIC_MAT_REF = 2 | GPU_DYNAMIC_GROUP_MAT,
+ GPU_DYNAMIC_MAT_SPECRGB = 3 | GPU_DYNAMIC_GROUP_MAT,
+ GPU_DYNAMIC_MAT_SPEC = 4 | GPU_DYNAMIC_GROUP_MAT,
+ GPU_DYNAMIC_MAT_HARD = 5 | GPU_DYNAMIC_GROUP_MAT,
+ GPU_DYNAMIC_MAT_EMIT = 6 | GPU_DYNAMIC_GROUP_MAT,
+ GPU_DYNAMIC_MAT_AMB = 7 | GPU_DYNAMIC_GROUP_MAT,
+ GPU_DYNAMIC_MAT_ALPHA = 8 | GPU_DYNAMIC_GROUP_MAT
+} GPUDynamicType;
+
+GPUNodeLink *GPU_attribute(CustomDataType type, const char *name);
GPUNodeLink *GPU_uniform(float *num);
-GPUNodeLink *GPU_dynamic_uniform(float *num, int dynamictype, void *data);
+GPUNodeLink *GPU_dynamic_uniform(float *num, GPUDynamicType dynamictype, void *data);
GPUNodeLink *GPU_image(struct Image *ima, struct ImageUser *iuser, bool is_data);
GPUNodeLink *GPU_image_preview(struct PreviewImage *prv);
GPUNodeLink *GPU_texture(int size, float *pixels);
-GPUNodeLink *GPU_dynamic_texture(struct GPUTexture *tex, int dynamictype, void *data);
+GPUNodeLink *GPU_dynamic_texture(struct GPUTexture *tex, GPUDynamicType dynamictype, void *data);
GPUNodeLink *GPU_builtin(GPUBuiltin builtin);
GPUNodeLink *GPU_opengl_builtin(GPUOpenGLBuiltin builtin);
+void GPU_node_link_set_type(GPUNodeLink *link, GPUType type);
bool GPU_link(GPUMaterial *mat, const char *name, ...);
bool GPU_stack_link(GPUMaterial *mat, const char *name, GPUNodeStack *in, GPUNodeStack *out, ...);
@@ -129,19 +204,21 @@ void GPU_material_enable_alpha(GPUMaterial *material);
GPUBlendMode GPU_material_alpha_blend(GPUMaterial *material, float obcol[4]);
/* High level functions to create and use GPU materials */
+GPUMaterial *GPU_material_world(struct Scene *scene, struct World *wo);
-GPUMaterial *GPU_material_from_blender(struct Scene *scene, struct Material *ma);
-GPUMaterial *GPU_material_matcap(struct Scene *scene, struct Material *ma);
-void GPU_material_free(struct Material *ma);
+GPUMaterial *GPU_material_from_blender(struct Scene *scene, struct Material *ma, bool use_opensubdiv);
+GPUMaterial *GPU_material_matcap(struct Scene *scene, struct Material *ma, bool use_opensubdiv);
+void GPU_material_free(struct ListBase *gpumaterial);
void GPU_materials_free(void);
bool GPU_lamp_override_visible(GPULamp *lamp, struct SceneRenderLayer *srl, struct Material *ma);
-void GPU_material_bind(GPUMaterial *material, int oblay, int viewlay, double time, int mipmap, float viewmat[4][4], float viewinv[4][4], bool scenelock);
-void GPU_material_bind_uniforms(GPUMaterial *material, float obmat[4][4], float obcol[4], float autobumpscale);
+void GPU_material_bind(GPUMaterial *material, int oblay, int viewlay, double time, int mipmap, float viewmat[4][4], float viewinv[4][4], float cameraborder[4], bool scenelock);
+void GPU_material_bind_uniforms(GPUMaterial *material, float obmat[4][4], float obcol[4], float autobumpscale, GPUParticleInfo *pi);
void GPU_material_unbind(GPUMaterial *material);
-int GPU_material_bound(GPUMaterial *material);
+bool GPU_material_bound(GPUMaterial *material);
struct Scene *GPU_material_scene(GPUMaterial *material);
+GPUMatType GPU_Material_get_type(GPUMaterial *material);
void GPU_material_vertex_attributes(GPUMaterial *material,
struct GPUVertexAttribs *attrib);
@@ -157,6 +234,7 @@ typedef struct GPUShadeInput {
GPUNodeLink *rgb, *specrgb, *vn, *view, *vcol, *ref;
GPUNodeLink *alpha, *refl, *spec, *emit, *har, *amb;
+ GPUNodeLink *spectra;
} GPUShadeInput;
typedef struct GPUShadeResult {
@@ -168,36 +246,9 @@ void GPU_shaderesult_set(GPUShadeInput *shi, GPUShadeResult *shr);
/* Export GLSL shader */
-typedef enum GPUDynamicType {
- GPU_DYNAMIC_NONE = 0,
- GPU_DYNAMIC_OBJECT_VIEWMAT = 1,
- GPU_DYNAMIC_OBJECT_MAT = 2,
- GPU_DYNAMIC_OBJECT_VIEWIMAT = 3,
- 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,
- GPU_DYNAMIC_LAMP_DYNIMAT = 8,
- GPU_DYNAMIC_LAMP_DYNPERSMAT = 9,
- GPU_DYNAMIC_LAMP_DYNENERGY = 10,
- GPU_DYNAMIC_LAMP_DYNCOL = 11,
- GPU_DYNAMIC_LAMP_LAST = 11,
- GPU_DYNAMIC_SAMPLER_2DBUFFER = 12,
- GPU_DYNAMIC_SAMPLER_2DIMAGE = 13,
- GPU_DYNAMIC_SAMPLER_2DSHADOW = 14,
- 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 {
GPU_DATA_NONE = 0,
- GPU_DATA_1I = 1, // 1 integer
+ GPU_DATA_1I = 1, /* 1 integer */
GPU_DATA_1F = 2,
GPU_DATA_2F = 3,
GPU_DATA_3F = 4,
@@ -210,23 +261,23 @@ typedef enum GPUDataType {
/* this structure gives information of each uniform found in the shader */
typedef struct GPUInputUniform {
struct GPUInputUniform *next, *prev;
- char varname[32]; /* name of uniform in shader */
- GPUDynamicType type; /* type of uniform, data format and calculation derive from it */
- GPUDataType datatype; /* type of uniform data */
- struct Object *lamp; /* when type=GPU_DYNAMIC_LAMP_... or GPU_DYNAMIC_SAMPLER_2DSHADOW */
- struct Image *image; /* when type=GPU_DYNAMIC_SAMPLER_2DIMAGE */
- int texnumber; /* when type=GPU_DYNAMIC_SAMPLER, texture number: 0.. */
- unsigned char *texpixels; /* for internally generated texture, pixel data in RGBA format */
- int texsize; /* size in pixel of the texture in texpixels buffer: for 2D textures, this is S and T size (square texture) */
+ char varname[32]; /* name of uniform in shader */
+ GPUDynamicType type; /* type of uniform, data format and calculation derive from it */
+ GPUDataType datatype; /* type of uniform data */
+ struct Object *lamp; /* when type=GPU_DYNAMIC_LAMP_... or GPU_DYNAMIC_SAMPLER_2DSHADOW */
+ struct Image *image; /* when type=GPU_DYNAMIC_SAMPLER_2DIMAGE */
+ int texnumber; /* when type=GPU_DYNAMIC_SAMPLER, texture number: 0.. */
+ unsigned char *texpixels; /* for internally generated texture, pixel data in RGBA format */
+ int texsize; /* size in pixel of the texture in texpixels buffer: for 2D textures, this is S and T size (square texture) */
} GPUInputUniform;
typedef struct GPUInputAttribute {
struct GPUInputAttribute *next, *prev;
- char varname[32]; /* name of attribute in shader */
- int type; /* from CustomData.type, data type derives from it */
- GPUDataType datatype; /* type of attribute data */
- const char *name; /* layer name */
- int number; /* generic attribute number */
+ char varname[32]; /* name of attribute in shader */
+ int type; /* from CustomData.type, data type derives from it */
+ GPUDataType datatype; /* type of attribute data */
+ const char *name; /* layer name */
+ int number; /* generic attribute number */
} GPUInputAttribute;
typedef struct GPUShaderExport {
@@ -255,7 +306,27 @@ 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);
+GPUNodeLink *GPU_lamp_get_data(GPUMaterial *mat, GPULamp *lamp, GPUNodeLink **col, GPUNodeLink **lv, GPUNodeLink **dist, GPUNodeLink **shadow, GPUNodeLink **energy);
+
+/* World */
+void GPU_mist_update_enable(short enable);
+void GPU_mist_update_values(int type, float start, float dist, float inten, float color[3]);
+void GPU_horizon_update_color(float color[3]);
+void GPU_ambient_update_color(float color[3]);
+
+typedef struct GPUParticleInfo
+{
+ float scalprops[4];
+ float location[3];
+ float velocity[3];
+ float angular_velocity[3];
+} GPUParticleInfo;
+
+#ifdef WITH_OPENSUBDIV
+struct DerivedMesh;
+void GPU_material_update_fvar_offset(GPUMaterial *gpu_material,
+ struct DerivedMesh *dm);
+#endif
#ifdef __cplusplus
}
diff --git a/source/blender/gpu/GPU_select.h b/source/blender/gpu/GPU_select.h
index 1a274e0ad9d..09137fc998b 100644
--- a/source/blender/gpu/GPU_select.h
+++ b/source/blender/gpu/GPU_select.h
@@ -27,8 +27,8 @@
* \ingroup gpu
*/
-#ifndef __GPU_SELECT__
-#define __GPU_SELECT__
+#ifndef __GPU_SELECT_H__
+#define __GPU_SELECT_H__
#include "DNA_vec_types.h" /* rcft */
#include "BLI_sys_types.h"
diff --git a/source/blender/gpu/GPU_simple_shader.h b/source/blender/gpu/GPU_simple_shader.h
index c8fb1f09b04..239296209b4 100644
--- a/source/blender/gpu/GPU_simple_shader.h
+++ b/source/blender/gpu/GPU_simple_shader.h
@@ -42,11 +42,11 @@ extern "C" {
typedef enum GPUSimpleShaderOption {
GPU_SHADER_OVERRIDE_DIFFUSE = (1<<0), /* replace diffuse with glcolor */
- GPU_SHADER_LIGHTING = (1<<1), /* use lighting */
- GPU_SHADER_TWO_SIDED = (1<<2), /* flip normals towards viewer */
- GPU_SHADER_TEXTURE_2D = (1<<3), /* use 2D texture to replace diffuse color */
+ GPU_SHADER_LIGHTING = (1<<1), /* use lighting */
+ GPU_SHADER_TWO_SIDED = (1<<2), /* flip normals towards viewer */
+ GPU_SHADER_TEXTURE_2D = (1<<3), /* use 2D texture to replace diffuse color */
- GPU_SHADER_SOLID_LIGHTING = (1<<4), /* use faster lighting (set automatically) */
+ GPU_SHADER_SOLID_LIGHTING = (1<<4), /* use faster lighting (set automatically) */
GPU_SHADER_OPTIONS_NUM = 5,
GPU_SHADER_OPTION_COMBINATIONS = (1<<GPU_SHADER_OPTIONS_NUM)
} GPUSimpleShaderOption;
diff --git a/source/blender/gpu/SConscript b/source/blender/gpu/SConscript
index e9320f08eff..d27d5b09b56 100644
--- a/source/blender/gpu/SConscript
+++ b/source/blender/gpu/SConscript
@@ -30,13 +30,15 @@ Import ('env')
sources = env.Glob('intern/*.c')
sources += env.Glob('shaders/*.c')
-defs = [ 'GLEW_STATIC' ]
+defs = []
+defs += env['BF_GL_DEFINITIONS']
incs = [
'.',
+ '#/intern/glew-mx',
'#/intern/guardedalloc',
+ env['BF_GLEW_INC'],
'#/intern/smoke/extern',
- '#/extern/glew/include',
'../blenkernel',
'../blenlib',
'../bmesh',
@@ -46,7 +48,6 @@ incs = [
'../makesrna',
'../nodes',
'../nodes/intern',
- env['BF_OPENGL_INC'],
]
if env['WITH_BF_GAMEENGINE']:
@@ -60,15 +61,31 @@ if env['WITH_BF_SMOKE']:
if env['WITH_BF_DDS']:
defs.append('WITH_DDS')
+if env['WITH_BF_OPENSUBDIV']:
+ defs.append('WITH_OPENSUBDIV')
+
# generated data files
import os
sources.extend((
+ os.path.join(env['DATA_SOURCES'], "gpu_shader_geometry.glsl.c"),
+ os.path.join(env['DATA_SOURCES'], "gpu_program_smoke_frag.glsl.c"),
+ os.path.join(env['DATA_SOURCES'], "gpu_program_smoke_color_frag.glsl.c"),
os.path.join(env['DATA_SOURCES'], "gpu_shader_simple_frag.glsl.c"),
os.path.join(env['DATA_SOURCES'], "gpu_shader_simple_vert.glsl.c"),
+ os.path.join(env['DATA_SOURCES'], "gpu_shader_fx_ssao_frag.glsl.c"),
+ os.path.join(env['DATA_SOURCES'], "gpu_shader_fx_dof_hq_frag.glsl.c"),
+ os.path.join(env['DATA_SOURCES'], "gpu_shader_fx_dof_hq_vert.glsl.c"),
+ os.path.join(env['DATA_SOURCES'], "gpu_shader_fx_dof_hq_geo.glsl.c"),
+ os.path.join(env['DATA_SOURCES'], "gpu_shader_fx_dof_frag.glsl.c"),
+ os.path.join(env['DATA_SOURCES'], "gpu_shader_fx_dof_vert.glsl.c"),
+ os.path.join(env['DATA_SOURCES'], "gpu_shader_fx_depth_resolve.glsl.c"),
+ os.path.join(env['DATA_SOURCES'], "gpu_shader_fx_lib.glsl.c"),
+ os.path.join(env['DATA_SOURCES'], "gpu_shader_fx_vert.glsl.c"),
os.path.join(env['DATA_SOURCES'], "gpu_shader_material.glsl.c"),
os.path.join(env['DATA_SOURCES'], "gpu_shader_sep_gaussian_blur_frag.glsl.c"),
os.path.join(env['DATA_SOURCES'], "gpu_shader_sep_gaussian_blur_vert.glsl.c"),
os.path.join(env['DATA_SOURCES'], "gpu_shader_vertex.glsl.c"),
+ os.path.join(env['DATA_SOURCES'], "gpu_shader_vertex_world.glsl.c"),
os.path.join(env['DATA_SOURCES'], "gpu_shader_vsm_store_frag.glsl.c"),
os.path.join(env['DATA_SOURCES'], "gpu_shader_vsm_store_vert.glsl.c"),
))
diff --git a/source/blender/gpu/intern/gpu_buffers.c b/source/blender/gpu/intern/gpu_buffers.c
index 5d2c9cd3a90..b4617b9790e 100644
--- a/source/blender/gpu/intern/gpu_buffers.c
+++ b/source/blender/gpu/intern/gpu_buffers.c
@@ -36,7 +36,7 @@
#include <stddef.h>
#include <string.h>
-#include "GL/glew.h"
+#include "GPU_glew.h"
#include "MEM_guardedalloc.h"
@@ -46,13 +46,12 @@
#include "BLI_ghash.h"
#include "BLI_threads.h"
-#include "DNA_material_types.h"
#include "DNA_meshdata_types.h"
#include "BKE_ccg.h"
#include "BKE_DerivedMesh.h"
#include "BKE_paint.h"
-#include "BKE_material.h"
+#include "BKE_mesh.h"
#include "BKE_pbvh.h"
#include "DNA_userdef_types.h"
@@ -71,17 +70,80 @@ typedef enum {
GPU_BUFFER_ELEMENT_STATE = (1 << 5),
} GPUBufferState;
+typedef struct {
+ GLenum gl_buffer_type;
+ int num_components; /* number of data components for one vertex */
+} GPUBufferTypeSettings;
+
+
+static size_t gpu_buffer_size_from_type(DerivedMesh *dm, GPUBufferType type);
+
+const GPUBufferTypeSettings gpu_buffer_type_settings[] = {
+ /* vertex */
+ {GL_ARRAY_BUFFER_ARB, 3},
+ /* normal */
+ {GL_ARRAY_BUFFER_ARB, 4}, /* we copy 3 shorts per normal but we add a fourth for alignment */
+ /* mcol */
+ {GL_ARRAY_BUFFER_ARB, 3},
+ /* uv */
+ {GL_ARRAY_BUFFER_ARB, 2},
+ /* uv for texpaint */
+ {GL_ARRAY_BUFFER_ARB, 4},
+ /* edge */
+ {GL_ELEMENT_ARRAY_BUFFER_ARB, 2},
+ /* uv edge */
+ {GL_ELEMENT_ARRAY_BUFFER_ARB, 4},
+ /* triangles, 1 point since we are allocating from tottriangle points, which account for all points */
+ {GL_ELEMENT_ARRAY_BUFFER_ARB, 1},
+};
+
#define MAX_GPU_ATTRIB_DATA 32
#define BUFFER_OFFSET(n) ((GLubyte *)NULL + (n))
/* -1 - undefined, 0 - vertex arrays, 1 - VBOs */
-static int useVBOs = -1;
static GPUBufferState GLStates = 0;
static GPUAttrib attribData[MAX_GPU_ATTRIB_DATA] = { { -1, 0, 0 } };
static ThreadMutex buffer_mutex = BLI_MUTEX_INITIALIZER;
+/* multires global buffer, can be used for many grids having the same grid size */
+static GPUBuffer *mres_glob_buffer = NULL;
+static int mres_prev_gridsize = -1;
+static GLenum mres_prev_index_type = 0;
+static unsigned mres_prev_totquad = 0;
+
+void GPU_buffer_material_finalize(GPUDrawObject *gdo, GPUBufferMaterial *matinfo, int totmat)
+{
+ int i, curmat, curelement;
+
+ /* count the number of materials used by this DerivedMesh */
+ for (i = 0; i < totmat; i++) {
+ if (matinfo[i].totelements > 0)
+ gdo->totmaterial++;
+ }
+
+ /* allocate an array of materials used by this DerivedMesh */
+ gdo->materials = MEM_mallocN(sizeof(GPUBufferMaterial) * gdo->totmaterial,
+ "GPUDrawObject.materials");
+
+ /* initialize the materials array */
+ for (i = 0, curmat = 0, curelement = 0; i < totmat; i++) {
+ if (matinfo[i].totelements > 0) {
+ gdo->materials[curmat] = matinfo[i];
+ gdo->materials[curmat].start = curelement;
+ gdo->materials[curmat].mat_nr = i;
+ gdo->materials[curmat].polys = MEM_mallocN(sizeof(int) * matinfo[i].totpolys, "GPUBufferMaterial.polys");
+
+ curelement += matinfo[i].totelements;
+ curmat++;
+ }
+ }
+
+ MEM_freeN(matinfo);
+}
+
+
/* stores recently-deleted buffers so that new buffers won't have to
* be recreated as often
*
@@ -96,33 +158,22 @@ static ThreadMutex buffer_mutex = BLI_MUTEX_INITIALIZER;
typedef struct GPUBufferPool {
/* number of allocated buffers stored */
int totbuf;
- int totpbvhbufids;
/* actual allocated length of the arrays */
int maxsize;
- int maxpbvhsize;
GPUBuffer **buffers;
- GLuint *pbvhbufids;
} GPUBufferPool;
#define MAX_FREE_GPU_BUFFERS 8
-#define MAX_FREE_GPU_BUFF_IDS 100
/* create a new GPUBufferPool */
static GPUBufferPool *gpu_buffer_pool_new(void)
{
GPUBufferPool *pool;
- /* enable VBOs if supported */
- if (useVBOs == -1)
- useVBOs = (GLEW_ARB_vertex_buffer_object ? 1 : 0);
-
pool = MEM_callocN(sizeof(GPUBufferPool), "GPUBuffer_Pool");
pool->maxsize = MAX_FREE_GPU_BUFFERS;
- pool->maxpbvhsize = MAX_FREE_GPU_BUFF_IDS;
pool->buffers = MEM_mallocN(sizeof(*pool->buffers) * pool->maxsize,
"GPUBufferPool.buffers");
- pool->pbvhbufids = MEM_mallocN(sizeof(*pool->pbvhbufids) * pool->maxpbvhsize,
- "GPUBufferPool.pbvhbuffers");
return pool;
}
@@ -158,7 +209,7 @@ static void gpu_buffer_pool_delete_last(GPUBufferPool *pool)
return;
/* delete the buffer's data */
- if (useVBOs)
+ if (last->use_vbo)
glDeleteBuffersARB(1, &last->id);
else
MEM_freeN(last->pointer);
@@ -180,7 +231,6 @@ static void gpu_buffer_pool_free(GPUBufferPool *pool)
gpu_buffer_pool_delete_last(pool);
MEM_freeN(pool->buffers);
- MEM_freeN(pool->pbvhbufids);
MEM_freeN(pool);
}
@@ -194,9 +244,6 @@ static void gpu_buffer_pool_free_unused(GPUBufferPool *pool)
while (pool->totbuf)
gpu_buffer_pool_delete_last(pool);
- glDeleteBuffersARB(pool->totpbvhbufids, pool->pbvhbufids);
- pool->totpbvhbufids = 0;
-
BLI_mutex_unlock(&buffer_mutex);
}
@@ -226,11 +273,12 @@ void GPU_global_buffer_pool_free_unused(void)
*
* Thread-unsafe version for internal usage only.
*/
-static GPUBuffer *gpu_buffer_alloc_intern(int size)
+static GPUBuffer *gpu_buffer_alloc_intern(size_t size, bool use_VBO)
{
GPUBufferPool *pool;
GPUBuffer *buf;
- int i, bufsize, bestfit = -1;
+ int i, bestfit = -1;
+ size_t bufsize;
/* bad case, leads to leak of buf since buf->pointer will allocate
* NULL, leading to return without cleanup. In any case better detect early
@@ -251,6 +299,11 @@ static GPUBuffer *gpu_buffer_alloc_intern(int size)
for (i = 0; i < pool->totbuf; i++) {
bufsize = pool->buffers[i]->size;
+ /* only return a buffer that matches the VBO preference */
+ if (pool->buffers[i]->use_vbo != use_VBO) {
+ continue;
+ }
+
/* check for an exact size match */
if (bufsize == size) {
bestfit = i;
@@ -279,8 +332,9 @@ static GPUBuffer *gpu_buffer_alloc_intern(int size)
/* no acceptable buffer found in the pool, create a new one */
buf = MEM_callocN(sizeof(GPUBuffer), "GPUBuffer");
buf->size = size;
+ buf->use_vbo = use_VBO;
- if (useVBOs == 1) {
+ if (use_VBO) {
/* create a new VBO and initialize it to the requested
* size */
glGenBuffersARB(1, &buf->id);
@@ -289,8 +343,11 @@ static GPUBuffer *gpu_buffer_alloc_intern(int size)
glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
}
else {
+ static int time = 0;
+
buf->pointer = MEM_mallocN(size, "GPUBuffer.pointer");
-
+
+ time++;
/* purpose of this seems to be dealing with
* out-of-memory errors? looks a bit iffy to me
* though, at least on Linux I expect malloc() would
@@ -299,17 +356,20 @@ static GPUBuffer *gpu_buffer_alloc_intern(int size)
gpu_buffer_pool_delete_last(pool);
buf->pointer = MEM_mallocN(size, "GPUBuffer.pointer");
}
- if (!buf->pointer)
+ if (!buf->pointer) {
+ MEM_freeN(buf);
return NULL;
+ }
}
return buf;
}
/* Same as above, but safe for threading. */
-GPUBuffer *GPU_buffer_alloc(int size)
+GPUBuffer *GPU_buffer_alloc(size_t size, bool force_vertex_arrays)
{
GPUBuffer *buffer;
+ bool use_VBOs = (GLEW_ARB_vertex_buffer_object) && !(U.gameflags & USER_DISABLE_VBO) && !force_vertex_arrays;
if (size == 0) {
/* Early out, no lock needed in this case. */
@@ -317,7 +377,7 @@ GPUBuffer *GPU_buffer_alloc(int size)
}
BLI_mutex_lock(&buffer_mutex);
- buffer = gpu_buffer_alloc_intern(size);
+ buffer = gpu_buffer_alloc_intern(size, use_VBOs);
BLI_mutex_unlock(&buffer_mutex);
return buffer;
@@ -381,224 +441,95 @@ void GPU_buffer_free(GPUBuffer *buffer)
BLI_mutex_unlock(&buffer_mutex);
}
-/* currently unused */
-// #define USE_GPU_POINT_LINK
-
-typedef struct GPUVertPointLink {
-#ifdef USE_GPU_POINT_LINK
- struct GPUVertPointLink *next;
-#endif
- /* -1 means uninitialized */
- int point_index;
-} GPUVertPointLink;
-
-
-/* add a new point to the list of points related to a particular
- * vertex */
-#ifdef USE_GPU_POINT_LINK
-
-static void gpu_drawobject_add_vert_point(GPUDrawObject *gdo, int vert_index, int point_index)
-{
- GPUVertPointLink *lnk;
-
- lnk = &gdo->vert_points[vert_index];
-
- /* if first link is in use, add a new link at the end */
- if (lnk->point_index != -1) {
- /* get last link */
- for (; lnk->next; lnk = lnk->next) ;
-
- /* add a new link from the pool */
- lnk = lnk->next = &gdo->vert_points_mem[gdo->vert_points_usage];
- gdo->vert_points_usage++;
- }
-
- lnk->point_index = point_index;
-}
-
-#else
-
-static void gpu_drawobject_add_vert_point(GPUDrawObject *gdo, int vert_index, int point_index)
+void GPU_buffer_multires_free(bool force)
{
- GPUVertPointLink *lnk;
- lnk = &gdo->vert_points[vert_index];
- if (lnk->point_index == -1) {
- lnk->point_index = point_index;
- }
-}
-
-#endif /* USE_GPU_POINT_LINK */
-
-/* update the vert_points and triangle_to_mface fields with a new
- * triangle */
-static void gpu_drawobject_add_triangle(GPUDrawObject *gdo,
- int base_point_index,
- int face_index,
- int v1, int v2, int v3)
-{
- int i, v[3] = {v1, v2, v3};
- for (i = 0; i < 3; i++)
- gpu_drawobject_add_vert_point(gdo, v[i], base_point_index + i);
- gdo->triangle_to_mface[base_point_index / 3] = face_index;
-}
-
-/* for each vertex, build a list of points related to it; these lists
- * are stored in an array sized to the number of vertices */
-static void gpu_drawobject_init_vert_points(GPUDrawObject *gdo, MFace *f, int totface, int totmat)
-{
- GPUBufferMaterial *mat;
- int i, *mat_orig_to_new;
-
- mat_orig_to_new = MEM_callocN(sizeof(*mat_orig_to_new) * totmat,
- "GPUDrawObject.mat_orig_to_new");
- /* allocate the array and space for links */
- gdo->vert_points = MEM_mallocN(sizeof(GPUVertPointLink) * gdo->totvert,
- "GPUDrawObject.vert_points");
-#ifdef USE_GPU_POINT_LINK
- gdo->vert_points_mem = MEM_callocN(sizeof(GPUVertPointLink) * gdo->tot_triangle_point,
- "GPUDrawObject.vert_points_mem");
- gdo->vert_points_usage = 0;
-#endif
-
- /* build a map from the original material indices to the new
- * GPUBufferMaterial indices */
- for (i = 0; i < gdo->totmaterial; i++)
- mat_orig_to_new[gdo->materials[i].mat_nr] = i;
-
- /* -1 indicates the link is not yet used */
- for (i = 0; i < gdo->totvert; i++) {
-#ifdef USE_GPU_POINT_LINK
- gdo->vert_points[i].link = NULL;
-#endif
- gdo->vert_points[i].point_index = -1;
+ if (!mres_glob_buffer) {
+ /* Early output, no need to lock in this case, */
+ return;
}
- for (i = 0; i < totface; i++, f++) {
- mat = &gdo->materials[mat_orig_to_new[f->mat_nr]];
-
- /* add triangle */
- gpu_drawobject_add_triangle(gdo, mat->start + mat->totpoint,
- i, f->v1, f->v2, f->v3);
- mat->totpoint += 3;
-
- /* add second triangle for quads */
- if (f->v4) {
- gpu_drawobject_add_triangle(gdo, mat->start + mat->totpoint,
- i, f->v3, f->v4, f->v1);
- mat->totpoint += 3;
+ if (force && BLI_thread_is_main()) {
+ if (mres_glob_buffer) {
+ if (mres_glob_buffer->id)
+ glDeleteBuffersARB(1, &mres_glob_buffer->id);
+ else if (mres_glob_buffer->pointer)
+ MEM_freeN(mres_glob_buffer->pointer);
+ MEM_freeN(mres_glob_buffer);
}
}
-
- /* map any unused vertices to loose points */
- for (i = 0; i < gdo->totvert; i++) {
- if (gdo->vert_points[i].point_index == -1) {
- gdo->vert_points[i].point_index = gdo->tot_triangle_point + gdo->tot_loose_point;
- gdo->tot_loose_point++;
- }
+ else {
+ BLI_mutex_lock(&buffer_mutex);
+ gpu_buffer_free_intern(mres_glob_buffer);
+ BLI_mutex_unlock(&buffer_mutex);
}
- MEM_freeN(mat_orig_to_new);
+ mres_glob_buffer = NULL;
+ mres_prev_gridsize = -1;
+ mres_prev_index_type = 0;
+ mres_prev_totquad = 0;
}
-/* see GPUDrawObject's structure definition for a description of the
- * data being initialized here */
-GPUDrawObject *GPU_drawobject_new(DerivedMesh *dm)
-{
- GPUDrawObject *gdo;
- MFace *mface;
- int totmat = dm->totmat;
- int *points_per_mat;
- int i, curmat, curpoint, totface;
-
- /* object contains at least one material (default included) so zero means uninitialized dm */
- BLI_assert(totmat != 0);
-
- mface = dm->getTessFaceArray(dm);
- totface = dm->getNumTessFaces(dm);
-
- /* get the number of points used by each material, treating
- * each quad as two triangles */
- points_per_mat = MEM_callocN(sizeof(*points_per_mat) * totmat, "GPU_drawobject_new.mat_orig_to_new");
- for (i = 0; i < totface; i++)
- points_per_mat[mface[i].mat_nr] += mface[i].v4 ? 6 : 3;
-
- /* create the GPUDrawObject */
- gdo = MEM_callocN(sizeof(GPUDrawObject), "GPUDrawObject");
- gdo->totvert = dm->getNumVerts(dm);
- gdo->totedge = dm->getNumEdges(dm);
-
- /* count the number of materials used by this DerivedMesh */
- for (i = 0; i < totmat; i++) {
- if (points_per_mat[i] > 0)
- gdo->totmaterial++;
- }
-
- /* allocate an array of materials used by this DerivedMesh */
- gdo->materials = MEM_mallocN(sizeof(GPUBufferMaterial) * gdo->totmaterial,
- "GPUDrawObject.materials");
-
- /* initialize the materials array */
- for (i = 0, curmat = 0, curpoint = 0; i < totmat; i++) {
- if (points_per_mat[i] > 0) {
- gdo->materials[curmat].start = curpoint;
- gdo->materials[curmat].totpoint = 0;
- gdo->materials[curmat].mat_nr = i;
-
- curpoint += points_per_mat[i];
- curmat++;
- }
- }
-
- /* store total number of points used for triangles */
- gdo->tot_triangle_point = curpoint;
-
- gdo->triangle_to_mface = MEM_mallocN(sizeof(int) * (gdo->tot_triangle_point / 3),
- "GPUDrawObject.triangle_to_mface");
-
- gpu_drawobject_init_vert_points(gdo, mface, totface, totmat);
- MEM_freeN(points_per_mat);
-
- return gdo;
-}
void GPU_drawobject_free(DerivedMesh *dm)
{
GPUDrawObject *gdo;
+ int i;
if (!dm || !(gdo = dm->drawObject))
return;
+ for (i = 0; i < gdo->totmaterial; i++) {
+ if (gdo->materials[i].polys)
+ MEM_freeN(gdo->materials[i].polys);
+ }
+
MEM_freeN(gdo->materials);
- MEM_freeN(gdo->triangle_to_mface);
- MEM_freeN(gdo->vert_points);
+ if (gdo->vert_points)
+ MEM_freeN(gdo->vert_points);
#ifdef USE_GPU_POINT_LINK
MEM_freeN(gdo->vert_points_mem);
#endif
GPU_buffer_free(gdo->points);
GPU_buffer_free(gdo->normals);
GPU_buffer_free(gdo->uv);
+ GPU_buffer_free(gdo->uv_tex);
GPU_buffer_free(gdo->colors);
GPU_buffer_free(gdo->edges);
GPU_buffer_free(gdo->uvedges);
+ GPU_buffer_free(gdo->triangles);
MEM_freeN(gdo);
dm->drawObject = NULL;
}
-typedef void (*GPUBufferCopyFunc)(DerivedMesh *dm, float *varray, int *index,
- int *mat_orig_to_new, void *user_data);
+static GPUBuffer *gpu_try_realloc(GPUBufferPool *pool, GPUBuffer *buffer, size_t size, bool use_VBOs)
+{
+ /* try freeing an entry from the pool
+ * and reallocating the buffer */
+ gpu_buffer_free_intern(buffer);
+
+ buffer = NULL;
+
+ while (pool->totbuf && !buffer) {
+ gpu_buffer_pool_delete_last(pool);
+ buffer = gpu_buffer_alloc_intern(size, use_VBOs);
+ }
+
+ return buffer;
+}
static GPUBuffer *gpu_buffer_setup(DerivedMesh *dm, GPUDrawObject *object,
- int vector_size, int size, GLenum target,
- void *user, GPUBufferCopyFunc copy_f)
+ int type, void *user)
{
GPUBufferPool *pool;
GPUBuffer *buffer;
float *varray;
int *mat_orig_to_new;
- int *cur_index_per_mat;
int i;
- bool success;
+ const GPUBufferTypeSettings *ts = &gpu_buffer_type_settings[type];
+ GLenum target = ts->gl_buffer_type;
+ size_t size = gpu_buffer_size_from_type(dm, type);
+ bool use_VBOs = (GLEW_ARB_vertex_buffer_object) && !(U.gameflags & USER_DISABLE_VBO);
GLboolean uploaded;
pool = gpu_get_global_buffer_pool();
@@ -606,30 +537,21 @@ static GPUBuffer *gpu_buffer_setup(DerivedMesh *dm, GPUDrawObject *object,
BLI_mutex_lock(&buffer_mutex);
/* alloc a GPUBuffer; fall back to legacy mode on failure */
- if (!(buffer = gpu_buffer_alloc_intern(size)))
- dm->drawObject->legacy = 1;
-
- /* nothing to do for legacy mode */
- if (dm->drawObject->legacy) {
+ if (!(buffer = gpu_buffer_alloc_intern(size, use_VBOs))) {
BLI_mutex_unlock(&buffer_mutex);
return NULL;
}
mat_orig_to_new = MEM_mallocN(sizeof(*mat_orig_to_new) * dm->totmat,
"GPU_buffer_setup.mat_orig_to_new");
- cur_index_per_mat = MEM_mallocN(sizeof(int) * object->totmaterial,
- "GPU_buffer_setup.cur_index_per_mat");
for (i = 0; i < object->totmaterial; i++) {
- /* for each material, the current index to copy data to */
- cur_index_per_mat[i] = object->materials[i].start * vector_size;
-
/* map from original material index to new
* GPUBufferMaterial index */
mat_orig_to_new[object->materials[i].mat_nr] = i;
}
- if (useVBOs) {
- success = 0;
+ if (use_VBOs) {
+ bool success = false;
while (!success) {
/* bind the buffer and discard previous data,
@@ -639,36 +561,26 @@ static GPUBuffer *gpu_buffer_setup(DerivedMesh *dm, GPUDrawObject *object,
/* attempt to map the buffer */
if (!(varray = glMapBufferARB(target, GL_WRITE_ONLY_ARB))) {
- /* failed to map the buffer; delete it */
- gpu_buffer_free_intern(buffer);
- gpu_buffer_pool_delete_last(pool);
- buffer = NULL;
-
- /* try freeing an entry from the pool
- * and reallocating the buffer */
- if (pool->totbuf > 0) {
- gpu_buffer_pool_delete_last(pool);
- buffer = gpu_buffer_alloc_intern(size);
- }
+ buffer = gpu_try_realloc(pool, buffer, size, true);
/* allocation still failed; fall back
* to legacy mode */
- if (!buffer) {
- dm->drawObject->legacy = 1;
- success = 1;
+ if (!(buffer && (varray = glMapBufferARB(target, GL_WRITE_ONLY_ARB)))) {
+ use_VBOs = false;
+ success = true;
}
}
else {
- success = 1;
+ success = true;
}
}
/* check legacy fallback didn't happen */
- if (dm->drawObject->legacy == 0) {
+ if (use_VBOs) {
uploaded = GL_FALSE;
/* attempt to upload the data to the VBO */
while (uploaded == GL_FALSE) {
- (*copy_f)(dm, varray, cur_index_per_mat, mat_orig_to_new, user);
+ dm->copy_gpu_data(dm, type, varray, mat_orig_to_new, user);
/* glUnmapBuffer returns GL_FALSE if
* the data store is corrupted; retry
* in that case */
@@ -677,18 +589,18 @@ static GPUBuffer *gpu_buffer_setup(DerivedMesh *dm, GPUDrawObject *object,
}
glBindBufferARB(target, 0);
}
- else {
+ if (!use_VBOs) {
/* VBO not supported, use vertex array fallback */
- if (buffer->pointer) {
- varray = buffer->pointer;
- (*copy_f)(dm, varray, cur_index_per_mat, mat_orig_to_new, user);
+ if (!buffer || !buffer->pointer) {
+ buffer = gpu_try_realloc(pool, buffer, size, false);
}
- else {
- dm->drawObject->legacy = 1;
+
+ if (buffer) {
+ varray = buffer->pointer;
+ dm->copy_gpu_data(dm, type, varray, mat_orig_to_new, user);
}
}
- MEM_freeN(cur_index_per_mat);
MEM_freeN(mat_orig_to_new);
BLI_mutex_unlock(&buffer_mutex);
@@ -696,316 +608,6 @@ static GPUBuffer *gpu_buffer_setup(DerivedMesh *dm, GPUDrawObject *object,
return buffer;
}
-static void GPU_buffer_copy_vertex(DerivedMesh *dm, float *varray, int *index, int *mat_orig_to_new, void *UNUSED(user))
-{
- MVert *mvert;
- MFace *f;
- int i, j, start, totface;
-
- mvert = dm->getVertArray(dm);
- f = dm->getTessFaceArray(dm);
-
- totface = dm->getNumTessFaces(dm);
- for (i = 0; i < totface; i++, f++) {
- start = index[mat_orig_to_new[f->mat_nr]];
-
- /* v1 v2 v3 */
- copy_v3_v3(&varray[start], mvert[f->v1].co);
- copy_v3_v3(&varray[start + 3], mvert[f->v2].co);
- copy_v3_v3(&varray[start + 6], mvert[f->v3].co);
- index[mat_orig_to_new[f->mat_nr]] += 9;
-
- if (f->v4) {
- /* v3 v4 v1 */
- copy_v3_v3(&varray[start + 9], mvert[f->v3].co);
- copy_v3_v3(&varray[start + 12], mvert[f->v4].co);
- copy_v3_v3(&varray[start + 15], mvert[f->v1].co);
- index[mat_orig_to_new[f->mat_nr]] += 9;
- }
- }
-
- /* copy loose points */
- j = dm->drawObject->tot_triangle_point * 3;
- for (i = 0; i < dm->drawObject->totvert; i++) {
- if (dm->drawObject->vert_points[i].point_index >= dm->drawObject->tot_triangle_point) {
- copy_v3_v3(&varray[j], mvert[i].co);
- j += 3;
- }
- }
-}
-
-static void GPU_buffer_copy_normal(DerivedMesh *dm, float *varray, int *index, int *mat_orig_to_new, void *UNUSED(user))
-{
- int i, totface;
- int start;
- float f_no[3];
-
- const float *nors = dm->getTessFaceDataArray(dm, CD_NORMAL);
- short (*tlnors)[4][3] = dm->getTessFaceDataArray(dm, CD_TESSLOOPNORMAL);
- MVert *mvert = dm->getVertArray(dm);
- MFace *f = dm->getTessFaceArray(dm);
-
- totface = dm->getNumTessFaces(dm);
- for (i = 0; i < totface; i++, f++) {
- const int smoothnormal = (f->flag & ME_SMOOTH);
-
- start = index[mat_orig_to_new[f->mat_nr]];
- index[mat_orig_to_new[f->mat_nr]] += f->v4 ? 18 : 9;
-
- if (tlnors) {
- short (*tlnor)[3] = tlnors[i];
- /* Copy loop normals */
- normal_short_to_float_v3(&varray[start], tlnor[0]);
- normal_short_to_float_v3(&varray[start + 3], tlnor[1]);
- normal_short_to_float_v3(&varray[start + 6], tlnor[2]);
-
- if (f->v4) {
- normal_short_to_float_v3(&varray[start + 9], tlnor[2]);
- normal_short_to_float_v3(&varray[start + 12], tlnor[3]);
- normal_short_to_float_v3(&varray[start + 15], tlnor[0]);
- }
- }
- else if (smoothnormal) {
- /* copy vertex normal */
- normal_short_to_float_v3(&varray[start], mvert[f->v1].no);
- normal_short_to_float_v3(&varray[start + 3], mvert[f->v2].no);
- normal_short_to_float_v3(&varray[start + 6], mvert[f->v3].no);
-
- if (f->v4) {
- normal_short_to_float_v3(&varray[start + 9], mvert[f->v3].no);
- normal_short_to_float_v3(&varray[start + 12], mvert[f->v4].no);
- normal_short_to_float_v3(&varray[start + 15], mvert[f->v1].no);
- }
- }
- else if (nors) {
- /* copy cached face normal */
- copy_v3_v3(&varray[start], &nors[i * 3]);
- copy_v3_v3(&varray[start + 3], &nors[i * 3]);
- copy_v3_v3(&varray[start + 6], &nors[i * 3]);
-
- if (f->v4) {
- copy_v3_v3(&varray[start + 9], &nors[i * 3]);
- copy_v3_v3(&varray[start + 12], &nors[i * 3]);
- copy_v3_v3(&varray[start + 15], &nors[i * 3]);
- }
- }
- else {
- /* calculate face normal */
- if (f->v4)
- normal_quad_v3(f_no, mvert[f->v1].co, mvert[f->v2].co, mvert[f->v3].co, mvert[f->v4].co);
- else
- normal_tri_v3(f_no, mvert[f->v1].co, mvert[f->v2].co, mvert[f->v3].co);
-
- copy_v3_v3(&varray[start], f_no);
- copy_v3_v3(&varray[start + 3], f_no);
- copy_v3_v3(&varray[start + 6], f_no);
-
- if (f->v4) {
- copy_v3_v3(&varray[start + 9], f_no);
- copy_v3_v3(&varray[start + 12], f_no);
- copy_v3_v3(&varray[start + 15], f_no);
- }
- }
- }
-}
-
-static void GPU_buffer_copy_uv(DerivedMesh *dm, float *varray, int *index, int *mat_orig_to_new, void *UNUSED(user))
-{
- int start;
- int i, totface;
-
- MTFace *mtface;
- MFace *f;
-
- if (!(mtface = DM_get_tessface_data_layer(dm, CD_MTFACE)))
- return;
- f = dm->getTessFaceArray(dm);
-
- totface = dm->getNumTessFaces(dm);
- for (i = 0; i < totface; i++, f++) {
- start = index[mat_orig_to_new[f->mat_nr]];
-
- /* v1 v2 v3 */
- copy_v2_v2(&varray[start], mtface[i].uv[0]);
- copy_v2_v2(&varray[start + 2], mtface[i].uv[1]);
- copy_v2_v2(&varray[start + 4], mtface[i].uv[2]);
- index[mat_orig_to_new[f->mat_nr]] += 6;
-
- if (f->v4) {
- /* v3 v4 v1 */
- copy_v2_v2(&varray[start + 6], mtface[i].uv[2]);
- copy_v2_v2(&varray[start + 8], mtface[i].uv[3]);
- copy_v2_v2(&varray[start + 10], mtface[i].uv[0]);
- index[mat_orig_to_new[f->mat_nr]] += 6;
- }
- }
-}
-
-
-static void GPU_buffer_copy_uv_texpaint(DerivedMesh *dm, float *varray, int *index, int *mat_orig_to_new, void *UNUSED(user))
-{
- int start;
- int i, totface;
-
- int totmaterial = dm->totmat;
- MTFace **mtface_base;
- MTFace *stencil_base;
- int stencil;
- MFace *mf;
-
- /* should have been checked for before, reassert */
- BLI_assert(DM_get_tessface_data_layer(dm, CD_MTFACE));
- mf = dm->getTessFaceArray(dm);
- mtface_base = MEM_mallocN(totmaterial * sizeof(*mtface_base), "texslots");
-
- for (i = 0; i < totmaterial; i++) {
- mtface_base[i] = DM_paint_uvlayer_active_get(dm, i);
- }
-
- stencil = CustomData_get_stencil_layer(&dm->faceData, CD_MTFACE);
- stencil_base = CustomData_get_layer_n(&dm->faceData, CD_MTFACE, stencil);
-
- totface = dm->getNumTessFaces(dm);
-
- for (i = 0; i < totface; i++, mf++) {
- int mat_i = mf->mat_nr;
- start = index[mat_orig_to_new[mat_i]];
-
- /* v1 v2 v3 */
- copy_v2_v2(&varray[start], mtface_base[mat_i][i].uv[0]);
- copy_v2_v2(&varray[start + 2], stencil_base[i].uv[0]);
- copy_v2_v2(&varray[start + 4], mtface_base[mat_i][i].uv[1]);
- copy_v2_v2(&varray[start + 6], stencil_base[i].uv[1]);
- copy_v2_v2(&varray[start + 8], mtface_base[mat_i][i].uv[2]);
- copy_v2_v2(&varray[start + 10], stencil_base[i].uv[2]);
- index[mat_orig_to_new[mat_i]] += 12;
-
- if (mf->v4) {
- /* v3 v4 v1 */
- copy_v2_v2(&varray[start + 12], mtface_base[mat_i][i].uv[2]);
- copy_v2_v2(&varray[start + 14], stencil_base[i].uv[2]);
- copy_v2_v2(&varray[start + 16], mtface_base[mat_i][i].uv[3]);
- copy_v2_v2(&varray[start + 18], stencil_base[i].uv[3]);
- copy_v2_v2(&varray[start + 20], mtface_base[mat_i][i].uv[0]);
- copy_v2_v2(&varray[start + 22], stencil_base[i].uv[0]);
- index[mat_orig_to_new[mat_i]] += 12;
- }
- }
-
- MEM_freeN(mtface_base);
-}
-
-
-static void copy_mcol_uc3(unsigned char *v, unsigned char *col)
-{
- v[0] = col[3];
- v[1] = col[2];
- v[2] = col[1];
-}
-
-/* treat varray_ as an array of MCol, four MCol's per face */
-static void GPU_buffer_copy_mcol(DerivedMesh *dm, float *varray_, int *index, int *mat_orig_to_new, void *user)
-{
- int i, totface;
- unsigned char *varray = (unsigned char *)varray_;
- unsigned char *mcol = (unsigned char *)user;
- MFace *f = dm->getTessFaceArray(dm);
-
- totface = dm->getNumTessFaces(dm);
- for (i = 0; i < totface; i++, f++) {
- int start = index[mat_orig_to_new[f->mat_nr]];
-
- /* v1 v2 v3 */
- copy_mcol_uc3(&varray[start], &mcol[i * 16]);
- copy_mcol_uc3(&varray[start + 3], &mcol[i * 16 + 4]);
- copy_mcol_uc3(&varray[start + 6], &mcol[i * 16 + 8]);
- index[mat_orig_to_new[f->mat_nr]] += 9;
-
- if (f->v4) {
- /* v3 v4 v1 */
- copy_mcol_uc3(&varray[start + 9], &mcol[i * 16 + 8]);
- copy_mcol_uc3(&varray[start + 12], &mcol[i * 16 + 12]);
- copy_mcol_uc3(&varray[start + 15], &mcol[i * 16]);
- index[mat_orig_to_new[f->mat_nr]] += 9;
- }
- }
-}
-
-static void GPU_buffer_copy_edge(DerivedMesh *dm, float *varray_, int *UNUSED(index), int *UNUSED(mat_orig_to_new), void *UNUSED(user))
-{
- MEdge *medge;
- unsigned int *varray = (unsigned int *)varray_;
- int i, totedge;
-
- medge = dm->getEdgeArray(dm);
- totedge = dm->getNumEdges(dm);
-
- for (i = 0; i < totedge; i++, medge++) {
- varray[i * 2] = dm->drawObject->vert_points[medge->v1].point_index;
- varray[i * 2 + 1] = dm->drawObject->vert_points[medge->v2].point_index;
- }
-}
-
-static void GPU_buffer_copy_uvedge(DerivedMesh *dm, float *varray, int *UNUSED(index), int *UNUSED(mat_orig_to_new), void *UNUSED(user))
-{
- MTFace *tf = DM_get_tessface_data_layer(dm, CD_MTFACE);
- int i, j = 0;
-
- if (!tf)
- return;
-
- for (i = 0; i < dm->numTessFaceData; i++, tf++) {
- MFace mf;
- dm->getTessFace(dm, i, &mf);
-
- copy_v2_v2(&varray[j], tf->uv[0]);
- copy_v2_v2(&varray[j + 2], tf->uv[1]);
-
- copy_v2_v2(&varray[j + 4], tf->uv[1]);
- copy_v2_v2(&varray[j + 6], tf->uv[2]);
-
- if (!mf.v4) {
- copy_v2_v2(&varray[j + 8], tf->uv[2]);
- copy_v2_v2(&varray[j + 10], tf->uv[0]);
- j += 12;
- }
- else {
- copy_v2_v2(&varray[j + 8], tf->uv[2]);
- copy_v2_v2(&varray[j + 10], tf->uv[3]);
-
- copy_v2_v2(&varray[j + 12], tf->uv[3]);
- copy_v2_v2(&varray[j + 14], tf->uv[0]);
- j += 16;
- }
- }
-}
-
-typedef enum {
- GPU_BUFFER_VERTEX = 0,
- GPU_BUFFER_NORMAL,
- GPU_BUFFER_COLOR,
- GPU_BUFFER_UV,
- GPU_BUFFER_UV_TEXPAINT,
- GPU_BUFFER_EDGE,
- GPU_BUFFER_UVEDGE,
-} GPUBufferType;
-
-typedef struct {
- GPUBufferCopyFunc copy;
- GLenum gl_buffer_type;
- int vector_size;
-} GPUBufferTypeSettings;
-
-const GPUBufferTypeSettings gpu_buffer_type_settings[] = {
- {GPU_buffer_copy_vertex, GL_ARRAY_BUFFER_ARB, 3},
- {GPU_buffer_copy_normal, GL_ARRAY_BUFFER_ARB, 3},
- {GPU_buffer_copy_mcol, GL_ARRAY_BUFFER_ARB, 3},
- {GPU_buffer_copy_uv, GL_ARRAY_BUFFER_ARB, 2},
- {GPU_buffer_copy_uv_texpaint, GL_ARRAY_BUFFER_ARB, 4},
- {GPU_buffer_copy_edge, GL_ELEMENT_ARRAY_BUFFER_ARB, 2},
- {GPU_buffer_copy_uvedge, GL_ELEMENT_ARRAY_BUFFER_ARB, 4}
-};
-
/* get the GPUDrawObject buffer associated with a type */
static GPUBuffer **gpu_drawobject_buffer_from_type(GPUDrawObject *gdo, GPUBufferType type)
{
@@ -1019,39 +621,38 @@ static GPUBuffer **gpu_drawobject_buffer_from_type(GPUDrawObject *gdo, GPUBuffer
case GPU_BUFFER_UV:
return &gdo->uv;
case GPU_BUFFER_UV_TEXPAINT:
- return &gdo->uv;
+ return &gdo->uv_tex;
case GPU_BUFFER_EDGE:
return &gdo->edges;
case GPU_BUFFER_UVEDGE:
return &gdo->uvedges;
+ case GPU_BUFFER_TRIANGLES:
+ return &gdo->triangles;
default:
return NULL;
}
}
/* get the amount of space to allocate for a buffer of a particular type */
-static int gpu_buffer_size_from_type(DerivedMesh *dm, GPUBufferType type)
+static size_t gpu_buffer_size_from_type(DerivedMesh *dm, GPUBufferType type)
{
switch (type) {
case GPU_BUFFER_VERTEX:
- return sizeof(float) * 3 * (dm->drawObject->tot_triangle_point + dm->drawObject->tot_loose_point);
+ return sizeof(float) * gpu_buffer_type_settings[type].num_components * (dm->drawObject->tot_loop_verts + dm->drawObject->tot_loose_point);
case GPU_BUFFER_NORMAL:
- return sizeof(float) * 3 * dm->drawObject->tot_triangle_point;
+ return sizeof(short) * gpu_buffer_type_settings[type].num_components * dm->drawObject->tot_loop_verts;
case GPU_BUFFER_COLOR:
- return sizeof(char) * 3 * dm->drawObject->tot_triangle_point;
+ return sizeof(char) * gpu_buffer_type_settings[type].num_components * dm->drawObject->tot_loop_verts;
case GPU_BUFFER_UV:
- return sizeof(float) * 2 * dm->drawObject->tot_triangle_point;
+ return sizeof(float) * gpu_buffer_type_settings[type].num_components * dm->drawObject->tot_loop_verts;
case GPU_BUFFER_UV_TEXPAINT:
- return sizeof(float) * 4 * dm->drawObject->tot_triangle_point;
+ return sizeof(float) * gpu_buffer_type_settings[type].num_components * dm->drawObject->tot_loop_verts;
case GPU_BUFFER_EDGE:
- return sizeof(int) * 2 * dm->drawObject->totedge;
+ return sizeof(int) * gpu_buffer_type_settings[type].num_components * dm->drawObject->totedge;
case GPU_BUFFER_UVEDGE:
- /* each face gets 3 points, 3 edges per triangle, and
- * each edge has its own, non-shared coords, so each
- * tri corner needs minimum of 4 floats, quads used
- * less so here we can over allocate and assume all
- * tris. */
- return sizeof(float) * 4 * dm->drawObject->tot_triangle_point;
+ return sizeof(int) * gpu_buffer_type_settings[type].num_components * dm->drawObject->tot_loop_verts;
+ case GPU_BUFFER_TRIANGLES:
+ return sizeof(int) * gpu_buffer_type_settings[type].num_components * dm->drawObject->tot_triangle_point;
default:
return -1;
}
@@ -1060,25 +661,20 @@ static int gpu_buffer_size_from_type(DerivedMesh *dm, GPUBufferType type)
/* call gpu_buffer_setup with settings for a particular type of buffer */
static GPUBuffer *gpu_buffer_setup_type(DerivedMesh *dm, GPUBufferType type)
{
- const GPUBufferTypeSettings *ts;
void *user_data = NULL;
GPUBuffer *buf;
- ts = &gpu_buffer_type_settings[type];
-
/* special handling for MCol and UV buffers */
if (type == GPU_BUFFER_COLOR) {
- if (!(user_data = DM_get_tessface_data_layer(dm, dm->drawObject->colType)))
+ if (!(user_data = DM_get_loop_data_layer(dm, dm->drawObject->colType)))
return NULL;
}
else if (ELEM(type, GPU_BUFFER_UV, GPU_BUFFER_UV_TEXPAINT)) {
- if (!DM_get_tessface_data_layer(dm, CD_MTFACE))
+ if (!DM_get_loop_data_layer(dm, CD_MLOOPUV))
return NULL;
}
- buf = gpu_buffer_setup(dm, dm->drawObject, ts->vector_size,
- gpu_buffer_size_from_type(dm, type),
- ts->gl_buffer_type, user_data, ts->copy);
+ buf = gpu_buffer_setup(dm, dm->drawObject, type, user_data);
return buf;
}
@@ -1090,7 +686,7 @@ static GPUBuffer *gpu_buffer_setup_common(DerivedMesh *dm, GPUBufferType type)
GPUBuffer **buf;
if (!dm->drawObject)
- dm->drawObject = GPU_drawobject_new(dm);
+ dm->drawObject = dm->gpuObjectNew(dm);
buf = gpu_drawobject_buffer_from_type(dm->drawObject, type);
if (!(*buf))
@@ -1105,7 +701,7 @@ void GPU_vertex_setup(DerivedMesh *dm)
return;
glEnableClientState(GL_VERTEX_ARRAY);
- if (useVBOs) {
+ if (dm->drawObject->points->use_vbo) {
glBindBufferARB(GL_ARRAY_BUFFER_ARB, dm->drawObject->points->id);
glVertexPointer(3, GL_FLOAT, 0, 0);
}
@@ -1122,12 +718,12 @@ void GPU_normal_setup(DerivedMesh *dm)
return;
glEnableClientState(GL_NORMAL_ARRAY);
- if (useVBOs) {
+ if (dm->drawObject->normals->use_vbo) {
glBindBufferARB(GL_ARRAY_BUFFER_ARB, dm->drawObject->normals->id);
- glNormalPointer(GL_FLOAT, 0, 0);
+ glNormalPointer(GL_SHORT, 4 * sizeof(short), 0);
}
else {
- glNormalPointer(GL_FLOAT, 0, dm->drawObject->normals->pointer);
+ glNormalPointer(GL_SHORT, 4 * sizeof(short), dm->drawObject->normals->pointer);
}
GLStates |= GPU_BUFFER_NORMAL_STATE;
@@ -1139,7 +735,7 @@ void GPU_uv_setup(DerivedMesh *dm)
return;
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
- if (useVBOs) {
+ if (dm->drawObject->uv->use_vbo) {
glBindBufferARB(GL_ARRAY_BUFFER_ARB, dm->drawObject->uv->id);
glTexCoordPointer(2, GL_FLOAT, 0, 0);
}
@@ -1156,8 +752,8 @@ void GPU_texpaint_uv_setup(DerivedMesh *dm)
return;
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
- if (useVBOs) {
- glBindBufferARB(GL_ARRAY_BUFFER_ARB, dm->drawObject->uv->id);
+ if (dm->drawObject->uv_tex->use_vbo) {
+ glBindBufferARB(GL_ARRAY_BUFFER_ARB, dm->drawObject->uv_tex->id);
glTexCoordPointer(2, GL_FLOAT, 4 * sizeof(float), 0);
glClientActiveTexture(GL_TEXTURE2);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
@@ -1165,10 +761,10 @@ void GPU_texpaint_uv_setup(DerivedMesh *dm)
glClientActiveTexture(GL_TEXTURE0);
}
else {
- glTexCoordPointer(2, GL_FLOAT, 4 * sizeof(float), dm->drawObject->uv->pointer);
+ glTexCoordPointer(2, GL_FLOAT, 4 * sizeof(float), dm->drawObject->uv_tex->pointer);
glClientActiveTexture(GL_TEXTURE2);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
- glTexCoordPointer(2, GL_FLOAT, 4 * sizeof(float), (char *)dm->drawObject->uv->pointer + 2 * sizeof(float));
+ glTexCoordPointer(2, GL_FLOAT, 4 * sizeof(float), (char *)dm->drawObject->uv_tex->pointer + 2 * sizeof(float));
glClientActiveTexture(GL_TEXTURE0);
}
@@ -1181,7 +777,7 @@ void GPU_color_setup(DerivedMesh *dm, int colType)
if (!dm->drawObject) {
/* XXX Not really nice, but we need a valid gpu draw object to set the colType...
* Else we would have to add a new param to gpu_buffer_setup_common. */
- dm->drawObject = GPU_drawobject_new(dm);
+ dm->drawObject = dm->gpuObjectNew(dm);
dm->dirty &= ~DM_DIRTY_MCOL_UPDATE_DRAW;
dm->drawObject->colType = colType;
}
@@ -1202,7 +798,7 @@ void GPU_color_setup(DerivedMesh *dm, int colType)
return;
glEnableClientState(GL_COLOR_ARRAY);
- if (useVBOs) {
+ if (dm->drawObject->colors->use_vbo) {
glBindBufferARB(GL_ARRAY_BUFFER_ARB, dm->drawObject->colors->id);
glColorPointer(3, GL_UNSIGNED_BYTE, 0, 0);
}
@@ -1213,6 +809,21 @@ void GPU_color_setup(DerivedMesh *dm, int colType)
GLStates |= GPU_BUFFER_COLOR_STATE;
}
+void GPU_buffer_bind_as_color(GPUBuffer *buffer)
+{
+ glEnableClientState(GL_COLOR_ARRAY);
+ if (buffer->use_vbo) {
+ glBindBufferARB(GL_ARRAY_BUFFER_ARB, buffer->id);
+ glColorPointer(4, GL_UNSIGNED_BYTE, 0, 0);
+ }
+ else {
+ glColorPointer(4, GL_UNSIGNED_BYTE, 0, buffer->pointer);
+ }
+
+ GLStates |= GPU_BUFFER_COLOR_STATE;
+}
+
+
void GPU_edge_setup(DerivedMesh *dm)
{
if (!gpu_buffer_setup_common(dm, GPU_BUFFER_EDGE))
@@ -1222,7 +833,7 @@ void GPU_edge_setup(DerivedMesh *dm)
return;
glEnableClientState(GL_VERTEX_ARRAY);
- if (useVBOs) {
+ if (dm->drawObject->points->use_vbo) {
glBindBufferARB(GL_ARRAY_BUFFER_ARB, dm->drawObject->points->id);
glVertexPointer(3, GL_FLOAT, 0, 0);
}
@@ -1232,7 +843,7 @@ void GPU_edge_setup(DerivedMesh *dm)
GLStates |= GPU_BUFFER_VERTEX_STATE;
- if (useVBOs)
+ if (dm->drawObject->edges->use_vbo)
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, dm->drawObject->edges->id);
GLStates |= GPU_BUFFER_ELEMENT_STATE;
@@ -1244,7 +855,7 @@ void GPU_uvedge_setup(DerivedMesh *dm)
return;
glEnableClientState(GL_VERTEX_ARRAY);
- if (useVBOs) {
+ if (dm->drawObject->uvedges->use_vbo) {
glBindBufferARB(GL_ARRAY_BUFFER_ARB, dm->drawObject->uvedges->id);
glVertexPointer(2, GL_FLOAT, 0, 0);
}
@@ -1255,6 +866,18 @@ void GPU_uvedge_setup(DerivedMesh *dm)
GLStates |= GPU_BUFFER_VERTEX_STATE;
}
+void GPU_triangle_setup(struct DerivedMesh *dm)
+{
+ if (!gpu_buffer_setup_common(dm, GPU_BUFFER_TRIANGLES))
+ return;
+
+ if (dm->drawObject->triangles->use_vbo) {
+ glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, dm->drawObject->triangles->id);
+ }
+
+ GLStates |= GPU_BUFFER_ELEMENT_STATE;
+}
+
static int GPU_typesize(int type)
{
switch (type) {
@@ -1285,11 +908,12 @@ int GPU_attrib_element_size(GPUAttrib data[], int numdata)
return elementsize;
}
-void GPU_interleaved_attrib_setup(GPUBuffer *buffer, GPUAttrib data[], int numdata)
+void GPU_interleaved_attrib_setup(GPUBuffer *buffer, GPUAttrib data[], int numdata, int element_size)
{
int i;
int elementsize;
intptr_t offset = 0;
+ char *basep;
for (i = 0; i < MAX_GPU_ATTRIB_DATA; i++) {
if (attribData[i].index != -1) {
@@ -1298,34 +922,47 @@ void GPU_interleaved_attrib_setup(GPUBuffer *buffer, GPUAttrib data[], int numda
else
break;
}
- elementsize = GPU_attrib_element_size(data, numdata);
+ if (element_size == 0)
+ elementsize = GPU_attrib_element_size(data, numdata);
+ else
+ elementsize = element_size;
- if (useVBOs) {
+ if (buffer->use_vbo) {
glBindBufferARB(GL_ARRAY_BUFFER_ARB, buffer->id);
- for (i = 0; i < numdata; i++) {
- glEnableVertexAttribArrayARB(data[i].index);
- glVertexAttribPointerARB(data[i].index, data[i].size, data[i].type,
- GL_FALSE, elementsize, (void *)offset);
- offset += data[i].size * GPU_typesize(data[i].type);
-
- attribData[i].index = data[i].index;
- attribData[i].size = data[i].size;
- attribData[i].type = data[i].type;
- }
- attribData[numdata].index = -1;
+ basep = NULL;
}
else {
- for (i = 0; i < numdata; i++) {
- glEnableVertexAttribArrayARB(data[i].index);
- glVertexAttribPointerARB(data[i].index, data[i].size, data[i].type,
- GL_FALSE, elementsize, (char *)buffer->pointer + offset);
- offset += data[i].size * GPU_typesize(data[i].type);
- }
+ basep = buffer->pointer;
}
+
+ for (i = 0; i < numdata; i++) {
+ glEnableVertexAttribArrayARB(data[i].index);
+ glVertexAttribPointerARB(data[i].index, data[i].size, data[i].type,
+ GL_FALSE, elementsize, (void *)(basep + offset));
+ offset += data[i].size * GPU_typesize(data[i].type);
+
+ attribData[i].index = data[i].index;
+ attribData[i].size = data[i].size;
+ attribData[i].type = data[i].type;
+ }
+
+ attribData[numdata].index = -1;
}
+void GPU_interleaved_attrib_unbind(void)
+{
+ int i;
+ for (i = 0; i < MAX_GPU_ATTRIB_DATA; i++) {
+ if (attribData[i].index != -1) {
+ glDisableVertexAttribArrayARB(attribData[i].index);
+ }
+ else
+ break;
+ }
+ attribData[0].index = -1;
+}
-void GPU_buffer_unbind(void)
+void GPU_buffers_unbind(void)
{
int i;
@@ -1343,7 +980,8 @@ void GPU_buffer_unbind(void)
if (GLStates & GPU_BUFFER_COLOR_STATE)
glDisableClientState(GL_COLOR_ARRAY);
if (GLStates & GPU_BUFFER_ELEMENT_STATE) {
- if (useVBOs) {
+ /* not guaranteed we used VBOs but in that case it's just a no-op */
+ if (GLEW_ARB_vertex_buffer_object) {
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
}
}
@@ -1358,8 +996,10 @@ void GPU_buffer_unbind(void)
else
break;
}
+ attribData[0].index = -1;
- if (useVBOs)
+ /* not guaranteed we used VBOs but in that case it's just a no-op */
+ if (GLEW_ARB_vertex_buffer_object)
glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
}
@@ -1377,29 +1017,23 @@ void GPU_color_switch(int mode)
}
}
-/* return 1 if drawing should be done using old immediate-mode
- * code, 0 otherwise */
-bool GPU_buffer_legacy(DerivedMesh *dm)
+static int gpu_binding_type_gl[] =
{
- int test = (U.gameflags & USER_DISABLE_VBO);
- if (test)
- return 1;
-
- if (dm->drawObject == NULL)
- dm->drawObject = GPU_drawobject_new(dm);
- return dm->drawObject->legacy;
-}
+ GL_ARRAY_BUFFER_ARB,
+ GL_ELEMENT_ARRAY_BUFFER_ARB
+};
-void *GPU_buffer_lock(GPUBuffer *buffer)
+void *GPU_buffer_lock(GPUBuffer *buffer, GPUBindingType binding)
{
float *varray;
if (!buffer)
return 0;
- if (useVBOs) {
- glBindBufferARB(GL_ARRAY_BUFFER_ARB, buffer->id);
- varray = glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
+ if (buffer->use_vbo) {
+ int bindtypegl = gpu_binding_type_gl[binding];
+ glBindBufferARB(bindtypegl, buffer->id);
+ varray = glMapBufferARB(bindtypegl, GL_WRITE_ONLY_ARB);
return varray;
}
else {
@@ -1407,18 +1041,19 @@ void *GPU_buffer_lock(GPUBuffer *buffer)
}
}
-void *GPU_buffer_lock_stream(GPUBuffer *buffer)
+void *GPU_buffer_lock_stream(GPUBuffer *buffer, GPUBindingType binding)
{
float *varray;
if (!buffer)
return 0;
- if (useVBOs) {
- glBindBufferARB(GL_ARRAY_BUFFER_ARB, buffer->id);
+ if (buffer->use_vbo) {
+ int bindtypegl = gpu_binding_type_gl[binding];
+ glBindBufferARB(bindtypegl, buffer->id);
/* discard previous data, avoid stalling gpu */
- glBufferDataARB(GL_ARRAY_BUFFER_ARB, buffer->size, 0, GL_STREAM_DRAW_ARB);
- varray = glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
+ glBufferDataARB(bindtypegl, buffer->size, 0, GL_STREAM_DRAW_ARB);
+ varray = glMapBufferARB(bindtypegl, GL_WRITE_ONLY_ARB);
return varray;
}
else {
@@ -1426,15 +1061,30 @@ void *GPU_buffer_lock_stream(GPUBuffer *buffer)
}
}
-void GPU_buffer_unlock(GPUBuffer *buffer)
+void GPU_buffer_unlock(GPUBuffer *buffer, GPUBindingType binding)
{
- if (useVBOs) {
- if (buffer) {
- /* note: this operation can fail, could return
- * an error code from this function? */
- glUnmapBufferARB(GL_ARRAY_BUFFER_ARB);
- }
- glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
+ if (buffer->use_vbo) {
+ int bindtypegl = gpu_binding_type_gl[binding];
+ /* note: this operation can fail, could return
+ * an error code from this function? */
+ glUnmapBufferARB(bindtypegl);
+ glBindBufferARB(bindtypegl, 0);
+ }
+}
+
+void GPU_buffer_bind(GPUBuffer *buffer, GPUBindingType binding)
+{
+ if (buffer->use_vbo) {
+ int bindtypegl = gpu_binding_type_gl[binding];
+ glBindBufferARB(bindtypegl, buffer->id);
+ }
+}
+
+void GPU_buffer_unbind(GPUBuffer *buffer, GPUBindingType binding)
+{
+ if (buffer->use_vbo) {
+ int bindtypegl = gpu_binding_type_gl[binding];
+ glBindBufferARB(bindtypegl, 0);
}
}
@@ -1442,7 +1092,7 @@ void GPU_buffer_unlock(GPUBuffer *buffer)
void GPU_buffer_draw_elements(GPUBuffer *elements, unsigned int mode, int start, int count)
{
glDrawElements(mode, count, GL_UNSIGNED_INT,
- (useVBOs ?
+ (elements->use_vbo ?
(void *)(start * sizeof(unsigned int)) :
((int *)elements->pointer) + start));
}
@@ -1451,14 +1101,6 @@ void GPU_buffer_draw_elements(GPUBuffer *elements, unsigned int mode, int start,
/* XXX: the rest of the code in this file is used for optimized PBVH
* drawing and doesn't interact at all with the buffer code above */
-/* Return false if VBO is either unavailable or disabled by the user,
- * true otherwise */
-static int gpu_vbo_enabled(void)
-{
- return (GLEW_ARB_vertex_buffer_object &&
- !(U.gameflags & USER_DISABLE_VBO));
-}
-
/* Convenience struct for building the VBO. */
typedef struct {
float co[3];
@@ -1474,14 +1116,20 @@ typedef struct {
struct GPU_PBVH_Buffers {
/* opengl buffer handles */
- GLuint vert_buf, index_buf;
+ GPUBuffer *vert_buf, *index_buf, *index_buf_fast;
GLenum index_type;
+ int *baseelemarray;
+ void **baseindex;
+
/* mesh pointers in case buffer allocation fails */
- MFace *mface;
- MVert *mvert;
+ const MPoly *mpoly;
+ const MLoop *mloop;
+ const MLoopTri *looptri;
+ const MVert *mvert;
+
const int *face_indices;
- int totface;
+ int face_indices_len;
const float *vmask;
/* grid pointers */
@@ -1505,6 +1153,7 @@ struct GPU_PBVH_Buffers {
bool use_matcaps;
float diffuse_color[4];
};
+
typedef enum {
VBO_ENABLED,
VBO_DISABLED
@@ -1541,22 +1190,6 @@ static void gpu_color_from_mask_copy(float mask, const float diffuse_color[4], u
out[2] = diffuse_color[2] * mask_color;
}
-static void gpu_color_from_mask_set(float mask, float diffuse_color[4])
-{
- float color = gpu_color_from_mask(mask);
- glColor3f(diffuse_color[0] * color, diffuse_color[1] * color, diffuse_color[2] * color);
-}
-
-static float gpu_color_from_mask_quad(const CCGKey *key,
- CCGElem *a, CCGElem *b,
- CCGElem *c, CCGElem *d)
-{
- return gpu_color_from_mask((*CCG_elem_mask(key, a) +
- *CCG_elem_mask(key, b) +
- *CCG_elem_mask(key, c) +
- *CCG_elem_mask(key, d)) * 0.25f);
-}
-
static void gpu_color_from_mask_quad_copy(const CCGKey *key,
CCGElem *a, CCGElem *b,
CCGElem *c, CCGElem *d,
@@ -1574,47 +1207,38 @@ static void gpu_color_from_mask_quad_copy(const CCGKey *key,
out[2] = diffuse_color[2] * mask_color;
}
-static void gpu_color_from_mask_quad_set(const CCGKey *key,
- CCGElem *a, CCGElem *b,
- CCGElem *c, CCGElem *d,
- const float diffuse_color[4])
-{
- float color = gpu_color_from_mask_quad(key, a, b, c, d);
- glColor3f(diffuse_color[0] * color, diffuse_color[1] * color, diffuse_color[2] * color);
-}
-
-void GPU_update_mesh_pbvh_buffers(GPU_PBVH_Buffers *buffers, MVert *mvert,
- int *vert_indices, int totvert, const float *vmask,
- int (*face_vert_indices)[4], bool show_diffuse_color)
+void GPU_update_mesh_pbvh_buffers(
+ GPU_PBVH_Buffers *buffers, const MVert *mvert,
+ const int *vert_indices, int totvert, const float *vmask,
+ const int (*face_vert_indices)[4], bool show_diffuse_color)
{
VertexBufferFormat *vert_data;
- int i, j, k;
+ int i, j;
buffers->vmask = vmask;
buffers->show_diffuse_color = show_diffuse_color;
buffers->use_matcaps = GPU_material_use_matcaps_get();
- if (buffers->vert_buf) {
+ {
int totelem = (buffers->smooth ? totvert : (buffers->tot_tri * 3));
float diffuse_color[4] = {0.8f, 0.8f, 0.8f, 0.8f};
if (buffers->use_matcaps)
diffuse_color[0] = diffuse_color[1] = diffuse_color[2] = 1.0;
else if (show_diffuse_color) {
- MFace *f = buffers->mface + buffers->face_indices[0];
+ const MLoopTri *lt = &buffers->looptri[buffers->face_indices[0]];
+ const MPoly *mp = &buffers->mpoly[lt->poly];
- GPU_material_diffuse_get(f->mat_nr + 1, diffuse_color);
+ GPU_material_diffuse_get(mp->mat_nr + 1, diffuse_color);
}
copy_v4_v4(buffers->diffuse_color, diffuse_color);
/* Build VBO */
- glBindBufferARB(GL_ARRAY_BUFFER_ARB, buffers->vert_buf);
- glBufferDataARB(GL_ARRAY_BUFFER_ARB,
- sizeof(VertexBufferFormat) * totelem,
- NULL, GL_STATIC_DRAW_ARB);
-
- vert_data = glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
+ if (buffers->vert_buf)
+ GPU_buffer_free(buffers->vert_buf);
+ buffers->vert_buf = GPU_buffer_alloc(sizeof(VertexBufferFormat) * totelem, false);
+ vert_data = GPU_buffer_lock(buffers->vert_buf, GPU_BINDING_ARRAY);
if (vert_data) {
/* Vertex data is shared if smooth-shaded, but separate
@@ -1622,7 +1246,7 @@ void GPU_update_mesh_pbvh_buffers(GPU_PBVH_Buffers *buffers, MVert *mvert,
* shouldn't be shared. */
if (buffers->smooth) {
for (i = 0; i < totvert; ++i) {
- MVert *v = mvert + vert_indices[i];
+ const MVert *v = &mvert[vert_indices[i]];
VertexBufferFormat *out = vert_data + i;
copy_v3_v3(out->co, v->co);
@@ -1638,118 +1262,114 @@ void GPU_update_mesh_pbvh_buffers(GPU_PBVH_Buffers *buffers, MVert *mvert,
rgb_float_to_uchar(out->color, diffuse_color); \
} (void)0
- for (i = 0; i < buffers->totface; i++) {
- MFace *f = buffers->mface + buffers->face_indices[i];
+ for (i = 0; i < buffers->face_indices_len; i++) {
+ const MLoopTri *lt = &buffers->looptri[buffers->face_indices[i]];
+ const unsigned int vtri[3] = {
+ buffers->mloop[lt->tri[0]].v,
+ buffers->mloop[lt->tri[1]].v,
+ buffers->mloop[lt->tri[2]].v,
+ };
- UPDATE_VERTEX(i, f->v1, 0, diffuse_color);
- UPDATE_VERTEX(i, f->v2, 1, diffuse_color);
- UPDATE_VERTEX(i, f->v3, 2, diffuse_color);
- if (f->v4)
- UPDATE_VERTEX(i, f->v4, 3, diffuse_color);
+ UPDATE_VERTEX(i, vtri[0], 0, diffuse_color);
+ UPDATE_VERTEX(i, vtri[1], 1, diffuse_color);
+ UPDATE_VERTEX(i, vtri[2], 2, diffuse_color);
}
#undef UPDATE_VERTEX
}
else {
- for (i = 0; i < buffers->totface; ++i) {
- const MFace *f = &buffers->mface[buffers->face_indices[i]];
- const unsigned int *fv = &f->v1;
- const int vi[2][3] = {{0, 1, 2}, {3, 0, 2}};
- float fno[3];
- short no[3];
+ /* calculate normal for each polygon only once */
+ unsigned int mpoly_prev = UINT_MAX;
+ short no[3];
+
+ for (i = 0; i < buffers->face_indices_len; ++i) {
+ const MLoopTri *lt = &buffers->looptri[buffers->face_indices[i]];
+ const unsigned int vtri[3] = {
+ buffers->mloop[lt->tri[0]].v,
+ buffers->mloop[lt->tri[1]].v,
+ buffers->mloop[lt->tri[2]].v,
+ };
float fmask;
- if (paint_is_face_hidden(f, mvert))
+ if (paint_is_face_hidden(lt, mvert, buffers->mloop))
continue;
/* Face normal and mask */
- if (f->v4) {
- normal_quad_v3(fno,
- mvert[fv[0]].co,
- mvert[fv[1]].co,
- mvert[fv[2]].co,
- mvert[fv[3]].co);
- if (vmask) {
- fmask = (vmask[fv[0]] +
- vmask[fv[1]] +
- vmask[fv[2]] +
- vmask[fv[3]]) * 0.25f;
- }
+ if (lt->poly != mpoly_prev) {
+ const MPoly *mp = &buffers->mpoly[lt->poly];
+ float fno[3];
+ BKE_mesh_calc_poly_normal(mp, &buffers->mloop[mp->loopstart], mvert, fno);
+ normal_float_to_short_v3(no, fno);
+ mpoly_prev = lt->poly;
}
- else {
- normal_tri_v3(fno,
- mvert[fv[0]].co,
- mvert[fv[1]].co,
- mvert[fv[2]].co);
- if (vmask) {
- fmask = (vmask[fv[0]] +
- vmask[fv[1]] +
- vmask[fv[2]]) / 3.0f;
- }
+
+ if (vmask) {
+ fmask = (vmask[vtri[0]] +
+ vmask[vtri[1]] +
+ vmask[vtri[2]]) / 3.0f;
}
- normal_float_to_short_v3(no, fno);
- for (j = 0; j < (f->v4 ? 2 : 1); j++) {
- for (k = 0; k < 3; k++) {
- const MVert *v = &mvert[fv[vi[j][k]]];
- VertexBufferFormat *out = vert_data;
+ for (j = 0; j < 3; j++) {
+ const MVert *v = &mvert[vtri[j]];
+ VertexBufferFormat *out = vert_data;
- copy_v3_v3(out->co, v->co);
- memcpy(out->no, no, sizeof(short) * 3);
+ copy_v3_v3(out->co, v->co);
+ copy_v3_v3_short(out->no, no);
- if (vmask)
- gpu_color_from_mask_copy(fmask, diffuse_color, out->color);
- else
- rgb_float_to_uchar(out->color, diffuse_color);
+ if (vmask)
+ gpu_color_from_mask_copy(fmask, diffuse_color, out->color);
+ else
+ rgb_float_to_uchar(out->color, diffuse_color);
- vert_data++;
- }
+ vert_data++;
}
}
}
- glUnmapBufferARB(GL_ARRAY_BUFFER_ARB);
+ GPU_buffer_unlock(buffers->vert_buf, GPU_BINDING_ARRAY);
}
else {
- glDeleteBuffersARB(1, &buffers->vert_buf);
- buffers->vert_buf = 0;
+ GPU_buffer_free(buffers->vert_buf);
+ buffers->vert_buf = NULL;
}
-
- glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
}
buffers->mvert = mvert;
}
-GPU_PBVH_Buffers *GPU_build_mesh_pbvh_buffers(int (*face_vert_indices)[4],
- MFace *mface, MVert *mvert,
- int *face_indices,
- int totface)
+GPU_PBVH_Buffers *GPU_build_mesh_pbvh_buffers(
+ const int (*face_vert_indices)[4],
+ const MPoly *mpoly, const MLoop *mloop, const MLoopTri *looptri,
+ const MVert *mvert,
+ const int *face_indices,
+ const int face_indices_len)
{
GPU_PBVH_Buffers *buffers;
unsigned short *tri_data;
- int i, j, k, tottri;
+ int i, j, tottri;
buffers = MEM_callocN(sizeof(GPU_PBVH_Buffers), "GPU_Buffers");
buffers->index_type = GL_UNSIGNED_SHORT;
- buffers->smooth = mface[face_indices[0]].flag & ME_SMOOTH;
+ buffers->smooth = mpoly[looptri[face_indices[0]].poly].flag & ME_SMOOTH;
buffers->show_diffuse_color = false;
buffers->use_matcaps = false;
/* Count the number of visible triangles */
- for (i = 0, tottri = 0; i < totface; ++i) {
- const MFace *f = &mface[face_indices[i]];
- if (!paint_is_face_hidden(f, mvert))
- tottri += f->v4 ? 2 : 1;
+ for (i = 0, tottri = 0; i < face_indices_len; ++i) {
+ const MLoopTri *lt = &looptri[face_indices[i]];
+ if (!paint_is_face_hidden(lt, mvert, mloop))
+ tottri++;
}
if (tottri == 0) {
buffers->tot_tri = 0;
- buffers->mface = mface;
+ buffers->mpoly = mpoly;
+ buffers->mloop = mloop;
+ buffers->looptri = looptri;
buffers->face_indices = face_indices;
- buffers->totface = 0;
+ buffers->face_indices_len = 0;
return buffers;
}
@@ -1757,65 +1377,48 @@ GPU_PBVH_Buffers *GPU_build_mesh_pbvh_buffers(int (*face_vert_indices)[4],
/* An element index buffer is used for smooth shading, but flat
* shading requires separate vertex normals so an index buffer is
* can't be used there. */
- if (gpu_vbo_enabled() && buffers->smooth)
- glGenBuffersARB(1, &buffers->index_buf);
+ if (buffers->smooth)
+ buffers->index_buf = GPU_buffer_alloc(sizeof(unsigned short) * tottri * 3, false);
if (buffers->index_buf) {
- /* Generate index buffer object */
- glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, buffers->index_buf);
- glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB,
- sizeof(unsigned short) * tottri * 3, NULL, GL_STATIC_DRAW_ARB);
-
/* Fill the triangle buffer */
- tri_data = glMapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
+ tri_data = GPU_buffer_lock(buffers->index_buf, GPU_BINDING_INDEX);
if (tri_data) {
- for (i = 0; i < totface; ++i) {
- const MFace *f = mface + face_indices[i];
- int v[3];
+ for (i = 0; i < face_indices_len; ++i) {
+ const MLoopTri *lt = &looptri[face_indices[i]];
/* Skip hidden faces */
- if (paint_is_face_hidden(f, mvert))
+ if (paint_is_face_hidden(lt, mvert, mloop))
continue;
- v[0] = 0;
- v[1] = 1;
- v[2] = 2;
-
- for (j = 0; j < (f->v4 ? 2 : 1); ++j) {
- for (k = 0; k < 3; ++k) {
- *tri_data = face_vert_indices[i][v[k]];
- tri_data++;
- }
- v[0] = 3;
- v[1] = 0;
- v[2] = 2;
+ for (j = 0; j < 3; ++j) {
+ *tri_data = face_vert_indices[i][j];
+ tri_data++;
}
}
- glUnmapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB);
+ GPU_buffer_unlock(buffers->index_buf, GPU_BINDING_INDEX);
}
else {
- glDeleteBuffersARB(1, &buffers->index_buf);
- buffers->index_buf = 0;
+ GPU_buffer_free(buffers->index_buf);
+ buffers->index_buf = NULL;
}
-
- glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
}
- if (gpu_vbo_enabled() && (buffers->index_buf || !buffers->smooth))
- glGenBuffersARB(1, &buffers->vert_buf);
-
buffers->tot_tri = tottri;
- buffers->mface = mface;
+ buffers->mpoly = mpoly;
+ buffers->mloop = mloop;
+ buffers->looptri = looptri;
+
buffers->face_indices = face_indices;
- buffers->totface = totface;
+ buffers->face_indices_len = face_indices_len;
return buffers;
}
void GPU_update_grid_pbvh_buffers(GPU_PBVH_Buffers *buffers, CCGElem **grids,
- const DMFlagMat *grid_flag_mats, int *grid_indices,
- int totgrid, const CCGKey *key, bool show_diffuse_color)
+ const DMFlagMat *grid_flag_mats, int *grid_indices,
+ int totgrid, const CCGKey *key, bool show_diffuse_color)
{
VertexBufferFormat *vert_data;
int i, j, k, x, y;
@@ -1825,7 +1428,6 @@ void GPU_update_grid_pbvh_buffers(GPU_PBVH_Buffers *buffers, CCGElem **grids,
/* Build VBO */
if (buffers->vert_buf) {
- int totvert = key->grid_area * totgrid;
int smooth = grid_flag_mats[grid_indices[0]].flag & ME_SMOOTH;
const int has_mask = key->has_mask;
float diffuse_color[4] = {0.8f, 0.8f, 0.8f, 1.0f};
@@ -1840,11 +1442,7 @@ void GPU_update_grid_pbvh_buffers(GPU_PBVH_Buffers *buffers, CCGElem **grids,
copy_v4_v4(buffers->diffuse_color, diffuse_color);
- glBindBufferARB(GL_ARRAY_BUFFER_ARB, buffers->vert_buf);
- glBufferDataARB(GL_ARRAY_BUFFER_ARB,
- sizeof(VertexBufferFormat) * totvert,
- NULL, GL_STATIC_DRAW_ARB);
- vert_data = glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
+ vert_data = GPU_buffer_lock_stream(buffers->vert_buf, GPU_BINDING_ARRAY);
if (vert_data) {
for (i = 0; i < totgrid; ++i) {
VertexBufferFormat *vd = vert_data;
@@ -1905,13 +1503,13 @@ void GPU_update_grid_pbvh_buffers(GPU_PBVH_Buffers *buffers, CCGElem **grids,
vert_data += key->grid_area;
}
- glUnmapBufferARB(GL_ARRAY_BUFFER_ARB);
+
+ GPU_buffer_unlock(buffers->vert_buf, GPU_BINDING_ARRAY);
}
else {
- glDeleteBuffersARB(1, &buffers->vert_buf);
- buffers->vert_buf = 0;
+ GPU_buffer_free(buffers->vert_buf);
+ buffers->vert_buf = NULL;
}
- glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
}
buffers->grids = grids;
@@ -1928,107 +1526,112 @@ void GPU_update_grid_pbvh_buffers(GPU_PBVH_Buffers *buffers, CCGElem **grids,
/* Build the element array buffer of grid indices using either
* unsigned shorts or unsigned ints. */
#define FILL_QUAD_BUFFER(type_, tot_quad_, buffer_) \
- { \
- type_ *tri_data; \
- int offset = 0; \
- int i, j, k; \
- \
- glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, \
- sizeof(type_) * (tot_quad_) * 6, NULL, \
- GL_STATIC_DRAW_ARB); \
- \
- /* Fill the buffer */ \
- tri_data = glMapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, \
- GL_WRITE_ONLY_ARB); \
- if (tri_data) { \
- for (i = 0; i < totgrid; ++i) { \
- BLI_bitmap *gh = NULL; \
- if (grid_hidden) \
- gh = grid_hidden[(grid_indices)[i]]; \
- \
- for (j = 0; j < gridsize - 1; ++j) { \
- for (k = 0; k < gridsize - 1; ++k) { \
- /* Skip hidden grid face */ \
- if (gh && \
- paint_is_grid_face_hidden(gh, \
- gridsize, k, j)) \
- continue; \
- \
- *(tri_data++) = offset + j * gridsize + k + 1; \
- *(tri_data++) = offset + j * gridsize + k; \
- *(tri_data++) = offset + (j + 1) * gridsize + k; \
- \
- *(tri_data++) = offset + (j + 1) * gridsize + k + 1; \
- *(tri_data++) = offset + j * gridsize + k + 1; \
- *(tri_data++) = offset + (j + 1) * gridsize + k; \
- } \
- } \
- \
- offset += gridsize * gridsize; \
- } \
- glUnmapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB); \
- } \
- else { \
- glDeleteBuffersARB(1, &(buffer_)); \
- (buffer_) = 0; \
- } \
- } (void)0
+ { \
+ type_ *tri_data; \
+ int offset = 0; \
+ int i, j, k; \
+ buffer_ = GPU_buffer_alloc(sizeof(type_) * (tot_quad_) * 6, \
+ false); \
+ \
+ /* Fill the buffer */ \
+ tri_data = GPU_buffer_lock(buffer_, GPU_BINDING_INDEX); \
+ if (tri_data) { \
+ for (i = 0; i < totgrid; ++i) { \
+ BLI_bitmap *gh = NULL; \
+ if (grid_hidden) \
+ gh = grid_hidden[(grid_indices)[i]]; \
+ \
+ for (j = 0; j < gridsize - 1; ++j) { \
+ for (k = 0; k < gridsize - 1; ++k) { \
+ /* Skip hidden grid face */ \
+ if (gh && \
+ paint_is_grid_face_hidden(gh, \
+ gridsize, k, j)) \
+ continue; \
+ \
+ *(tri_data++) = offset + j * gridsize + k + 1; \
+ *(tri_data++) = offset + j * gridsize + k; \
+ *(tri_data++) = offset + (j + 1) * gridsize + k; \
+ \
+ *(tri_data++) = offset + (j + 1) * gridsize + k + 1; \
+ *(tri_data++) = offset + j * gridsize + k + 1; \
+ *(tri_data++) = offset + (j + 1) * gridsize + k; \
+ } \
+ } \
+ \
+ offset += gridsize * gridsize; \
+ } \
+ GPU_buffer_unlock(buffer_, GPU_BINDING_INDEX); \
+ } \
+ else { \
+ GPU_buffer_free(buffer_); \
+ (buffer_) = NULL; \
+ } \
+ } (void)0
/* end FILL_QUAD_BUFFER */
-static GLuint gpu_get_grid_buffer(int gridsize, GLenum *index_type, unsigned *totquad)
+static GPUBuffer *gpu_get_grid_buffer(int gridsize, GLenum *index_type, unsigned *totquad)
{
- static int prev_gridsize = -1;
- static GLenum prev_index_type = 0;
- static GLuint buffer = 0;
- static unsigned prev_totquad;
-
/* used in the FILL_QUAD_BUFFER macro */
BLI_bitmap * const *grid_hidden = NULL;
const int *grid_indices = NULL;
int totgrid = 1;
- /* VBO is disabled; delete the previous buffer (if it exists) and
- * return an invalid handle */
- if (!gpu_vbo_enabled()) {
- if (buffer)
- glDeleteBuffersARB(1, &buffer);
- return 0;
- }
-
/* VBO is already built */
- if (buffer && prev_gridsize == gridsize) {
- *index_type = prev_index_type;
- *totquad = prev_totquad;
- return buffer;
+ if (mres_glob_buffer && mres_prev_gridsize == gridsize) {
+ *index_type = mres_prev_index_type;
+ *totquad = mres_prev_totquad;
+ return mres_glob_buffer;
+ }
+ /* we can't reuse old, delete the existing buffer */
+ else if (mres_glob_buffer) {
+ GPU_buffer_free(mres_glob_buffer);
}
/* Build new VBO */
- glGenBuffersARB(1, &buffer);
- if (buffer) {
- *totquad = (gridsize - 1) * (gridsize - 1);
+ *totquad = (gridsize - 1) * (gridsize - 1);
- glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, buffer);
-
- if (gridsize * gridsize < USHRT_MAX) {
- *index_type = GL_UNSIGNED_SHORT;
- FILL_QUAD_BUFFER(unsigned short, *totquad, buffer);
- }
- else {
- *index_type = GL_UNSIGNED_INT;
- FILL_QUAD_BUFFER(unsigned int, *totquad, buffer);
- }
-
- glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
+ if (gridsize * gridsize < USHRT_MAX) {
+ *index_type = GL_UNSIGNED_SHORT;
+ FILL_QUAD_BUFFER(unsigned short, *totquad, mres_glob_buffer);
}
-
- prev_gridsize = gridsize;
- prev_index_type = *index_type;
- prev_totquad = *totquad;
- return buffer;
-}
+ else {
+ *index_type = GL_UNSIGNED_INT;
+ FILL_QUAD_BUFFER(unsigned int, *totquad, mres_glob_buffer);
+ }
+
+ mres_prev_gridsize = gridsize;
+ mres_prev_index_type = *index_type;
+ mres_prev_totquad = *totquad;
+ return mres_glob_buffer;
+}
+
+#define FILL_FAST_BUFFER(type_) \
+{ \
+ type_ *buffer; \
+ buffers->index_buf_fast = GPU_buffer_alloc(sizeof(type_) * 6 * totgrid, false); \
+ buffer = GPU_buffer_lock(buffers->index_buf_fast, GPU_BINDING_INDEX); \
+ if (buffer) { \
+ int i; \
+ for (i = 0; i < totgrid; i++) { \
+ int currentquad = i * 6; \
+ buffer[currentquad] = i * gridsize * gridsize + gridsize - 1; \
+ buffer[currentquad + 1] = i * gridsize * gridsize; \
+ buffer[currentquad + 2] = (i + 1) * gridsize * gridsize - gridsize; \
+ buffer[currentquad + 3] = (i + 1) * gridsize * gridsize - 1; \
+ buffer[currentquad + 4] = i * gridsize * gridsize + gridsize - 1; \
+ buffer[currentquad + 5] = (i + 1) * gridsize * gridsize - gridsize; \
+ } \
+ GPU_buffer_unlock(buffers->index_buf_fast, GPU_BINDING_INDEX); \
+ } \
+ else { \
+ GPU_buffer_free(buffers->index_buf_fast); \
+ buffers->index_buf_fast = NULL; \
+ } \
+} (void)0
GPU_PBVH_Buffers *GPU_build_grid_pbvh_buffers(int *grid_indices, int totgrid,
- BLI_bitmap **grid_hidden, int gridsize)
+ BLI_bitmap **grid_hidden, int gridsize, const CCGKey *key)
{
GPU_PBVH_Buffers *buffers;
int totquad;
@@ -2048,28 +1651,28 @@ GPU_PBVH_Buffers *GPU_build_grid_pbvh_buffers(int *grid_indices, int totgrid,
if (totquad == 0)
return buffers;
+ /* create and fill indices of the fast buffer too */
+ if (totgrid * gridsize * gridsize < USHRT_MAX) {
+ FILL_FAST_BUFFER(unsigned short);
+ }
+ else {
+ FILL_FAST_BUFFER(unsigned int);
+ }
+
if (totquad == fully_visible_totquad) {
buffers->index_buf = gpu_get_grid_buffer(gridsize, &buffers->index_type, &buffers->tot_quad);
buffers->has_hidden = 0;
}
- else if (GLEW_ARB_vertex_buffer_object && !(U.gameflags & USER_DISABLE_VBO)) {
- /* Build new VBO */
- glGenBuffersARB(1, &buffers->index_buf);
- if (buffers->index_buf) {
- buffers->tot_quad = totquad;
-
- glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, buffers->index_buf);
-
- if (totgrid * gridsize * gridsize < USHRT_MAX) {
- buffers->index_type = GL_UNSIGNED_SHORT;
- FILL_QUAD_BUFFER(unsigned short, totquad, buffers->index_buf);
- }
- else {
- buffers->index_type = GL_UNSIGNED_INT;
- FILL_QUAD_BUFFER(unsigned int, totquad, buffers->index_buf);
- }
+ else {
+ buffers->tot_quad = totquad;
- glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
+ if (totgrid * gridsize * gridsize < USHRT_MAX) {
+ buffers->index_type = GL_UNSIGNED_SHORT;
+ FILL_QUAD_BUFFER(unsigned short, totquad, buffers->index_buf);
+ }
+ else {
+ buffers->index_type = GL_UNSIGNED_INT;
+ FILL_QUAD_BUFFER(unsigned int, totquad, buffers->index_buf);
}
buffers->has_hidden = 1;
@@ -2077,7 +1680,19 @@ GPU_PBVH_Buffers *GPU_build_grid_pbvh_buffers(int *grid_indices, int totgrid,
/* Build coord/normal VBO */
if (buffers->index_buf)
- glGenBuffersARB(1, &buffers->vert_buf);
+ buffers->vert_buf = GPU_buffer_alloc(sizeof(VertexBufferFormat) * totgrid * key->grid_area, false);
+
+ if (GLEW_ARB_draw_elements_base_vertex) {
+ int i;
+ buffers->baseelemarray = MEM_mallocN(sizeof(int) * totgrid * 2, "GPU_PBVH_Buffers.baseelemarray");
+ buffers->baseindex = MEM_mallocN(sizeof(void *) * totgrid, "GPU_PBVH_Buffers.baseindex");
+ for (i = 0; i < totgrid; i++) {
+ buffers->baseelemarray[i] = buffers->tot_quad * 6;
+ buffers->baseelemarray[i + totgrid] = i * key->grid_area;
+ buffers->baseindex[i] = buffers->index_buf && !buffers->index_buf->use_vbo ?
+ buffers->index_buf->pointer : NULL;
+ }
+ }
return buffers;
}
@@ -2110,7 +1725,6 @@ static void gpu_bmesh_vert_to_buffer_copy(BMVert *v,
BM_ELEM_CD_GET_FLOAT(v, cd_vert_mask_offset),
diffuse_color,
vd->color);
-
/* Assign index for use in the triangle index buffer */
/* note: caller must set: bm->elem_index_dirty |= BM_VERT; */
@@ -2160,11 +1774,11 @@ static int gpu_bmesh_face_visible_count(GSet *bm_faces)
/* Creates a vertex buffer (coordinate, normal, color) and, if smooth
* shading, an element index buffer. */
void GPU_update_bmesh_pbvh_buffers(GPU_PBVH_Buffers *buffers,
- BMesh *bm,
- GSet *bm_faces,
- GSet *bm_unique_verts,
- GSet *bm_other_verts,
- bool show_diffuse_color)
+ BMesh *bm,
+ GSet *bm_faces,
+ GSet *bm_unique_verts,
+ GSet *bm_other_verts,
+ bool show_diffuse_color)
{
VertexBufferFormat *vert_data;
void *tri_data;
@@ -2177,9 +1791,6 @@ void GPU_update_bmesh_pbvh_buffers(GPU_PBVH_Buffers *buffers,
buffers->show_diffuse_color = show_diffuse_color;
buffers->use_matcaps = GPU_material_use_matcaps_get();
- if (!buffers->vert_buf || (buffers->smooth && !buffers->index_buf))
- return;
-
/* Count visible triangles */
tottri = gpu_bmesh_face_visible_count(bm_faces);
@@ -2209,13 +1820,12 @@ void GPU_update_bmesh_pbvh_buffers(GPU_PBVH_Buffers *buffers,
copy_v4_v4(buffers->diffuse_color, diffuse_color);
/* Initialize vertex buffer */
- glBindBufferARB(GL_ARRAY_BUFFER_ARB, buffers->vert_buf);
- glBufferDataARB(GL_ARRAY_BUFFER_ARB,
- sizeof(VertexBufferFormat) * totvert,
- NULL, GL_STATIC_DRAW_ARB);
+ if (buffers->vert_buf)
+ GPU_buffer_free(buffers->vert_buf);
+ buffers->vert_buf = GPU_buffer_alloc(sizeof(VertexBufferFormat) * totvert, false);
/* Fill vertex buffer */
- vert_data = glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
+ vert_data = GPU_buffer_lock(buffers->vert_buf, GPU_BINDING_ARRAY);
if (vert_data) {
int v_index = 0;
@@ -2253,7 +1863,9 @@ void GPU_update_bmesh_pbvh_buffers(GPU_PBVH_Buffers *buffers,
float fmask = 0;
int i;
- // BM_iter_as_array(bm, BM_VERTS_OF_FACE, f, (void**)v, 3);
+#if 0
+ BM_iter_as_array(bm, BM_VERTS_OF_FACE, f, (void**)v, 3);
+#endif
BM_face_as_array_vert_tri(f, v);
/* Average mask value */
@@ -2273,15 +1885,15 @@ void GPU_update_bmesh_pbvh_buffers(GPU_PBVH_Buffers *buffers,
buffers->tot_tri = tottri;
}
- glUnmapBufferARB(GL_ARRAY_BUFFER_ARB);
+ GPU_buffer_unlock(buffers->vert_buf, GPU_BINDING_ARRAY);
/* gpu_bmesh_vert_to_buffer_copy sets dirty index values */
bm->elem_index_dirty |= BM_VERT;
}
else {
/* Memory map failed */
- glDeleteBuffersARB(1, &buffers->vert_buf);
- buffers->vert_buf = 0;
+ GPU_buffer_free(buffers->vert_buf);
+ buffers->vert_buf = NULL;
return;
}
@@ -2289,15 +1901,14 @@ void GPU_update_bmesh_pbvh_buffers(GPU_PBVH_Buffers *buffers,
const int use_short = (maxvert < USHRT_MAX);
/* Initialize triangle index buffer */
- glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, buffers->index_buf);
- glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB,
- (use_short ?
- sizeof(unsigned short) :
- sizeof(unsigned int)) * 3 * tottri,
- NULL, GL_STATIC_DRAW_ARB);
+ if (buffers->index_buf)
+ GPU_buffer_free(buffers->index_buf);
+ buffers->index_buf = GPU_buffer_alloc((use_short ?
+ sizeof(unsigned short) :
+ sizeof(unsigned int)) * 3 * tottri, false);
/* Fill triangle index buffer */
- tri_data = glMapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
+ tri_data = GPU_buffer_lock(buffers->index_buf, GPU_BINDING_INDEX);
if (tri_data) {
GSetIterator gs_iter;
@@ -2327,7 +1938,7 @@ void GPU_update_bmesh_pbvh_buffers(GPU_PBVH_Buffers *buffers,
}
}
- glUnmapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB);
+ GPU_buffer_unlock(buffers->index_buf, GPU_BINDING_INDEX);
buffers->tot_tri = tottri;
buffers->index_type = (use_short ?
@@ -2336,10 +1947,13 @@ void GPU_update_bmesh_pbvh_buffers(GPU_PBVH_Buffers *buffers,
}
else {
/* Memory map failed */
- glDeleteBuffersARB(1, &buffers->index_buf);
- buffers->index_buf = 0;
+ GPU_buffer_free(buffers->index_buf);
+ buffers->index_buf = NULL;
}
}
+ else if (buffers->index_buf) {
+ GPU_buffer_free(buffers->index_buf);
+ }
}
GPU_PBVH_Buffers *GPU_build_bmesh_pbvh_buffers(int smooth_shading)
@@ -2347,9 +1961,6 @@ GPU_PBVH_Buffers *GPU_build_bmesh_pbvh_buffers(int smooth_shading)
GPU_PBVH_Buffers *buffers;
buffers = MEM_callocN(sizeof(GPU_PBVH_Buffers), "GPU_Buffers");
- if (smooth_shading)
- glGenBuffersARB(1, &buffers->index_buf);
- glGenBuffersARB(1, &buffers->vert_buf);
buffers->use_bmesh = true;
buffers->smooth = smooth_shading;
buffers->show_diffuse_color = false;
@@ -2358,217 +1969,17 @@ GPU_PBVH_Buffers *GPU_build_bmesh_pbvh_buffers(int smooth_shading)
return buffers;
}
-static void gpu_draw_buffers_legacy_mesh(GPU_PBVH_Buffers *buffers)
-{
- const MVert *mvert = buffers->mvert;
- int i, j;
- const int has_mask = (buffers->vmask != NULL);
- const MFace *face = &buffers->mface[buffers->face_indices[0]];
- float diffuse_color[4] = {0.8f, 0.8f, 0.8f, 1.0f};
-
- if (buffers->use_matcaps)
- diffuse_color[0] = diffuse_color[1] = diffuse_color[2] = 1.0;
- else if (buffers->show_diffuse_color)
- GPU_material_diffuse_get(face->mat_nr + 1, diffuse_color);
-
- if (has_mask) {
- gpu_colors_enable(VBO_DISABLED);
- }
-
- for (i = 0; i < buffers->totface; ++i) {
- MFace *f = buffers->mface + buffers->face_indices[i];
- int S = f->v4 ? 4 : 3;
- unsigned int *fv = &f->v1;
-
- if (paint_is_face_hidden(f, buffers->mvert))
- continue;
-
- glBegin((f->v4) ? GL_QUADS : GL_TRIANGLES);
-
- if (buffers->smooth) {
- for (j = 0; j < S; j++) {
- if (has_mask) {
- gpu_color_from_mask_set(buffers->vmask[fv[j]], diffuse_color);
- }
- glNormal3sv(mvert[fv[j]].no);
- glVertex3fv(mvert[fv[j]].co);
- }
- }
- else {
- float fno[3];
-
- /* calculate face normal */
- if (f->v4) {
- normal_quad_v3(fno, mvert[fv[0]].co, mvert[fv[1]].co,
- mvert[fv[2]].co, mvert[fv[3]].co);
- }
- else
- normal_tri_v3(fno, mvert[fv[0]].co, mvert[fv[1]].co, mvert[fv[2]].co);
- glNormal3fv(fno);
-
- if (has_mask) {
- float fmask;
-
- /* calculate face mask color */
- fmask = (buffers->vmask[fv[0]] +
- buffers->vmask[fv[1]] +
- buffers->vmask[fv[2]]);
- if (f->v4)
- fmask = (fmask + buffers->vmask[fv[3]]) * 0.25f;
- else
- fmask /= 3.0f;
- gpu_color_from_mask_set(fmask, diffuse_color);
- }
-
- for (j = 0; j < S; j++)
- glVertex3fv(mvert[fv[j]].co);
- }
-
- glEnd();
- }
-
- if (has_mask) {
- gpu_colors_disable(VBO_DISABLED);
- }
-}
-
-static void gpu_draw_buffers_legacy_grids(GPU_PBVH_Buffers *buffers)
-{
- const CCGKey *key = &buffers->gridkey;
- int i, j, x, y, gridsize = buffers->gridkey.grid_size;
- const int has_mask = key->has_mask;
- const DMFlagMat *flags = &buffers->grid_flag_mats[buffers->grid_indices[0]];
- float diffuse_color[4] = {0.8f, 0.8f, 0.8f, 1.0f};
-
- if (buffers->use_matcaps)
- diffuse_color[0] = diffuse_color[1] = diffuse_color[2] = 1.0;
- else if (buffers->show_diffuse_color)
- GPU_material_diffuse_get(flags->mat_nr + 1, diffuse_color);
-
- if (has_mask) {
- gpu_colors_enable(VBO_DISABLED);
- }
-
- for (i = 0; i < buffers->totgrid; ++i) {
- int g = buffers->grid_indices[i];
- CCGElem *grid = buffers->grids[g];
- BLI_bitmap *gh = buffers->grid_hidden[g];
-
- /* TODO: could use strips with hiding as well */
-
- if (gh) {
- glBegin(GL_QUADS);
-
- for (y = 0; y < gridsize - 1; y++) {
- for (x = 0; x < gridsize - 1; x++) {
- CCGElem *e[4] = {
- CCG_grid_elem(key, grid, x + 1, y + 1),
- CCG_grid_elem(key, grid, x + 1, y),
- CCG_grid_elem(key, grid, x, y),
- CCG_grid_elem(key, grid, x, y + 1)
- };
-
- /* skip face if any of its corners are hidden */
- if (paint_is_grid_face_hidden(gh, gridsize, x, y))
- continue;
-
- if (buffers->smooth) {
- for (j = 0; j < 4; j++) {
- if (has_mask) {
- gpu_color_from_mask_set(*CCG_elem_mask(key, e[j]), diffuse_color);
- }
- glNormal3fv(CCG_elem_no(key, e[j]));
- glVertex3fv(CCG_elem_co(key, e[j]));
- }
- }
- else {
- float fno[3];
- normal_quad_v3(fno,
- CCG_elem_co(key, e[0]),
- CCG_elem_co(key, e[1]),
- CCG_elem_co(key, e[2]),
- CCG_elem_co(key, e[3]));
- glNormal3fv(fno);
-
- if (has_mask) {
- gpu_color_from_mask_quad_set(key, e[0], e[1], e[2], e[3], diffuse_color);
- }
-
- for (j = 0; j < 4; j++)
- glVertex3fv(CCG_elem_co(key, e[j]));
- }
- }
- }
-
- glEnd();
- }
- else if (buffers->smooth) {
- for (y = 0; y < gridsize - 1; y++) {
- glBegin(GL_QUAD_STRIP);
- for (x = 0; x < gridsize; x++) {
- CCGElem *a = CCG_grid_elem(key, grid, x, y);
- CCGElem *b = CCG_grid_elem(key, grid, x, y + 1);
-
- if (has_mask) {
- gpu_color_from_mask_set(*CCG_elem_mask(key, a), diffuse_color);
- }
- glNormal3fv(CCG_elem_no(key, a));
- glVertex3fv(CCG_elem_co(key, a));
- if (has_mask) {
- gpu_color_from_mask_set(*CCG_elem_mask(key, b), diffuse_color);
- }
- glNormal3fv(CCG_elem_no(key, b));
- glVertex3fv(CCG_elem_co(key, b));
- }
- glEnd();
- }
- }
- else {
- for (y = 0; y < gridsize - 1; y++) {
- glBegin(GL_QUAD_STRIP);
- for (x = 0; x < gridsize; x++) {
- CCGElem *a = CCG_grid_elem(key, grid, x, y);
- CCGElem *b = CCG_grid_elem(key, grid, x, y + 1);
-
- if (x > 0) {
- CCGElem *c = CCG_grid_elem(key, grid, x - 1, y);
- CCGElem *d = CCG_grid_elem(key, grid, x - 1, y + 1);
-
- float fno[3];
- normal_quad_v3(fno,
- CCG_elem_co(key, d),
- CCG_elem_co(key, b),
- CCG_elem_co(key, a),
- CCG_elem_co(key, c));
- glNormal3fv(fno);
-
- if (has_mask) {
- gpu_color_from_mask_quad_set(key, a, b, c, d, diffuse_color);
- }
- }
-
- glVertex3fv(CCG_elem_co(key, a));
- glVertex3fv(CCG_elem_co(key, b));
- }
- glEnd();
- }
- }
- }
-
- if (has_mask) {
- gpu_colors_disable(VBO_DISABLED);
- }
-}
-
void GPU_draw_pbvh_buffers(GPU_PBVH_Buffers *buffers, DMSetMaterial setMaterial,
- bool wireframe)
+ bool wireframe, bool fast)
{
+ bool do_fast = fast && buffers->index_buf_fast;
/* sets material from the first face, to solve properly face would need to
* be sorted in buckets by materials */
if (setMaterial) {
- if (buffers->totface) {
- const MFace *f = &buffers->mface[buffers->face_indices[0]];
- if (!setMaterial(f->mat_nr + 1, NULL))
+ if (buffers->face_indices_len) {
+ const MLoopTri *lt = &buffers->looptri[buffers->face_indices[0]];
+ const MPoly *mp = &buffers->mpoly[lt->poly];
+ if (!setMaterial(mp->mat_nr + 1, NULL))
return;
}
else if (buffers->totgrid) {
@@ -2582,51 +1993,86 @@ void GPU_draw_pbvh_buffers(GPU_PBVH_Buffers *buffers, DMSetMaterial setMaterial,
}
}
- glShadeModel((buffers->smooth || buffers->totface) ? GL_SMOOTH : GL_FLAT);
+ glShadeModel((buffers->smooth || buffers->face_indices_len) ? GL_SMOOTH : GL_FLAT);
if (buffers->vert_buf) {
+ char *base = NULL;
+ char *index_base = NULL;
glEnableClientState(GL_VERTEX_ARRAY);
if (!wireframe) {
glEnableClientState(GL_NORMAL_ARRAY);
gpu_colors_enable(VBO_ENABLED);
}
- glBindBufferARB(GL_ARRAY_BUFFER_ARB, buffers->vert_buf);
+ GPU_buffer_bind(buffers->vert_buf, GPU_BINDING_ARRAY);
- if (buffers->index_buf)
- glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, buffers->index_buf);
+ if (!buffers->vert_buf->use_vbo)
+ base = (char *)buffers->vert_buf->pointer;
+
+ if (do_fast) {
+ GPU_buffer_bind(buffers->index_buf_fast, GPU_BINDING_INDEX);
+ if (!buffers->index_buf_fast->use_vbo)
+ index_base = buffers->index_buf_fast->pointer;
+ }
+ else if (buffers->index_buf) {
+ GPU_buffer_bind(buffers->index_buf, GPU_BINDING_INDEX);
+ if (!buffers->index_buf->use_vbo)
+ index_base = buffers->index_buf->pointer;
+ }
if (wireframe)
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
if (buffers->tot_quad) {
- const char *offset = 0;
- int i, last = buffers->has_hidden ? 1 : buffers->totgrid;
- for (i = 0; i < last; i++) {
+ const char *offset = base;
+ const bool drawall = !(buffers->has_hidden || do_fast);
+
+ if (GLEW_ARB_draw_elements_base_vertex && drawall) {
+
glVertexPointer(3, GL_FLOAT, sizeof(VertexBufferFormat),
offset + offsetof(VertexBufferFormat, co));
glNormalPointer(GL_SHORT, sizeof(VertexBufferFormat),
offset + offsetof(VertexBufferFormat, no));
glColorPointer(3, GL_UNSIGNED_BYTE, sizeof(VertexBufferFormat),
offset + offsetof(VertexBufferFormat, color));
-
- glDrawElements(GL_TRIANGLES, buffers->tot_quad * 6, buffers->index_type, 0);
- offset += buffers->gridkey.grid_area * sizeof(VertexBufferFormat);
+ glMultiDrawElementsBaseVertex(GL_TRIANGLES, buffers->baseelemarray, buffers->index_type,
+ (const void * const *)buffers->baseindex,
+ buffers->totgrid, &buffers->baseelemarray[buffers->totgrid]);
+ }
+ else {
+ int i, last = drawall ? buffers->totgrid : 1;
+
+ /* we could optimize this to one draw call, but it would need more memory */
+ for (i = 0; i < last; i++) {
+ glVertexPointer(3, GL_FLOAT, sizeof(VertexBufferFormat),
+ offset + offsetof(VertexBufferFormat, co));
+ glNormalPointer(GL_SHORT, sizeof(VertexBufferFormat),
+ offset + offsetof(VertexBufferFormat, no));
+ glColorPointer(3, GL_UNSIGNED_BYTE, sizeof(VertexBufferFormat),
+ offset + offsetof(VertexBufferFormat, color));
+
+ if (do_fast)
+ glDrawElements(GL_TRIANGLES, buffers->totgrid * 6, buffers->index_type, index_base);
+ else
+ glDrawElements(GL_TRIANGLES, buffers->tot_quad * 6, buffers->index_type, index_base);
+
+ offset += buffers->gridkey.grid_area * sizeof(VertexBufferFormat);
+ }
}
}
else if (buffers->tot_tri) {
int totelem = buffers->tot_tri * 3;
glVertexPointer(3, GL_FLOAT, sizeof(VertexBufferFormat),
- (void *)offsetof(VertexBufferFormat, co));
+ (void *)(base + offsetof(VertexBufferFormat, co)));
glNormalPointer(GL_SHORT, sizeof(VertexBufferFormat),
- (void *)offsetof(VertexBufferFormat, no));
+ (void *)(base + offsetof(VertexBufferFormat, no)));
glColorPointer(3, GL_UNSIGNED_BYTE, sizeof(VertexBufferFormat),
- (void *)offsetof(VertexBufferFormat, color));
+ (void *)(base + offsetof(VertexBufferFormat, color)));
if (buffers->index_buf)
- glDrawElements(GL_TRIANGLES, totelem, buffers->index_type, 0);
+ glDrawElements(GL_TRIANGLES, totelem, buffers->index_type, index_base);
else
glDrawArrays(GL_TRIANGLES, 0, totelem);
}
@@ -2634,9 +2080,9 @@ void GPU_draw_pbvh_buffers(GPU_PBVH_Buffers *buffers, DMSetMaterial setMaterial,
if (wireframe)
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
- glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
- if (buffers->index_buf)
- glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
+ GPU_buffer_unbind(buffers->vert_buf, GPU_BINDING_ARRAY);
+ if (buffers->index_buf || do_fast)
+ GPU_buffer_unbind(do_fast ? buffers->index_buf_fast : buffers->index_buf, GPU_BINDING_INDEX);
glDisableClientState(GL_VERTEX_ARRAY);
if (!wireframe) {
@@ -2644,13 +2090,6 @@ void GPU_draw_pbvh_buffers(GPU_PBVH_Buffers *buffers, DMSetMaterial setMaterial,
gpu_colors_disable(VBO_ENABLED);
}
}
- /* fallbacks if we are out of memory or VBO is disabled */
- else if (buffers->totface) {
- gpu_draw_buffers_legacy_mesh(buffers);
- }
- else if (buffers->totgrid) {
- gpu_draw_buffers_legacy_grids(buffers);
- }
}
bool GPU_pbvh_buffers_diffuse_changed(GPU_PBVH_Buffers *buffers, GSet *bm_faces, bool show_diffuse_color)
@@ -2667,13 +2106,14 @@ bool GPU_pbvh_buffers_diffuse_changed(GPU_PBVH_Buffers *buffers, GSet *bm_faces,
if ((buffers->show_diffuse_color == false) || use_matcaps)
return false;
- if (buffers->mface) {
- MFace *f = buffers->mface + buffers->face_indices[0];
+ if (buffers->looptri) {
+ const MLoopTri *lt = &buffers->looptri[buffers->face_indices[0]];
+ const MPoly *mp = &buffers->mpoly[lt->poly];
- GPU_material_diffuse_get(f->mat_nr + 1, diffuse_color);
+ GPU_material_diffuse_get(mp->mat_nr + 1, diffuse_color);
}
else if (buffers->use_bmesh) {
- /* due to dynamc nature of dyntopo, only get first material */
+ /* due to dynamic nature of dyntopo, only get first material */
if (BLI_gset_size(bm_faces) > 0) {
GSetIterator gs_iter;
BMFace *f;
@@ -2695,50 +2135,19 @@ bool GPU_pbvh_buffers_diffuse_changed(GPU_PBVH_Buffers *buffers, GSet *bm_faces,
return !equals_v3v3(diffuse_color, buffers->diffuse_color);
}
-/* release a GPU_PBVH_Buffers id;
- *
- * Thread-unsafe version for internal usage only.
- */
-static void gpu_pbvh_buffer_free_intern(GLuint id)
-{
- GPUBufferPool *pool;
-
- /* zero id is vertex buffers off */
- if (!id)
- return;
-
- pool = gpu_get_global_buffer_pool();
-
- /* free the buffers immediately if we are on main thread */
- if (BLI_thread_is_main()) {
- glDeleteBuffersARB(1, &id);
-
- if (pool->totpbvhbufids > 0) {
- glDeleteBuffersARB(pool->totpbvhbufids, pool->pbvhbufids);
- pool->totpbvhbufids = 0;
- }
- return;
- }
- /* outside of main thread, can't safely delete the
- * buffer, so increase pool size */
- if (pool->maxpbvhsize == pool->totpbvhbufids) {
- pool->maxpbvhsize += MAX_FREE_GPU_BUFF_IDS;
- pool->pbvhbufids = MEM_reallocN(pool->pbvhbufids,
- sizeof(*pool->pbvhbufids) * pool->maxpbvhsize);
- }
-
- /* insert the buffer into the beginning of the pool */
- pool->pbvhbufids[pool->totpbvhbufids++] = id;
-}
-
-
void GPU_free_pbvh_buffers(GPU_PBVH_Buffers *buffers)
{
if (buffers) {
if (buffers->vert_buf)
- gpu_pbvh_buffer_free_intern(buffers->vert_buf);
+ GPU_buffer_free(buffers->vert_buf);
if (buffers->index_buf && (buffers->tot_tri || buffers->has_hidden))
- gpu_pbvh_buffer_free_intern(buffers->index_buf);
+ GPU_buffer_free(buffers->index_buf);
+ if (buffers->index_buf_fast)
+ GPU_buffer_free(buffers->index_buf_fast);
+ if (buffers->baseelemarray)
+ MEM_freeN(buffers->baseelemarray);
+ if (buffers->baseindex)
+ MEM_freeN(buffers->baseindex);
MEM_freeN(buffers);
}
@@ -2748,34 +2157,34 @@ void GPU_free_pbvh_buffers(GPU_PBVH_Buffers *buffers)
/* debug function, draws the pbvh BB */
void GPU_draw_pbvh_BB(float min[3], float max[3], bool leaf)
{
- float quads[4][4][3] = {
- {
- {min[0], min[1], min[2]},
- {max[0], min[1], min[2]},
- {max[0], min[1], max[2]},
- {min[0], min[1], max[2]}
- },
-
- {
- {min[0], min[1], min[2]},
- {min[0], max[1], min[2]},
- {min[0], max[1], max[2]},
- {min[0], min[1], max[2]}
- },
-
- {
- {max[0], max[1], min[2]},
- {max[0], min[1], min[2]},
- {max[0], min[1], max[2]},
- {max[0], max[1], max[2]}
- },
-
- {
- {max[0], max[1], min[2]},
- {min[0], max[1], min[2]},
- {min[0], max[1], max[2]},
- {max[0], max[1], max[2]}
- },
+ const float quads[4][4][3] = {
+ {
+ {min[0], min[1], min[2]},
+ {max[0], min[1], min[2]},
+ {max[0], min[1], max[2]},
+ {min[0], min[1], max[2]}
+ },
+
+ {
+ {min[0], min[1], min[2]},
+ {min[0], max[1], min[2]},
+ {min[0], max[1], max[2]},
+ {min[0], min[1], max[2]}
+ },
+
+ {
+ {max[0], max[1], min[2]},
+ {max[0], min[1], min[2]},
+ {max[0], min[1], max[2]},
+ {max[0], max[1], max[2]}
+ },
+
+ {
+ {max[0], max[1], min[2]},
+ {min[0], max[1], min[2]},
+ {min[0], max[1], max[2]},
+ {max[0], max[1], max[2]}
+ },
};
if (leaf)
@@ -2797,7 +2206,6 @@ void GPU_init_draw_pbvh_BB(void)
glDisable(GL_LIGHTING);
glDisable(GL_COLOR_MATERIAL);
glEnable(GL_BLEND);
- glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
}
void GPU_end_draw_pbvh_BB(void)
diff --git a/source/blender/gpu/intern/gpu_codegen.c b/source/blender/gpu/intern/gpu_codegen.c
index 6b46db89a93..496302bb44e 100644
--- a/source/blender/gpu/intern/gpu_codegen.c
+++ b/source/blender/gpu/intern/gpu_codegen.c
@@ -31,8 +31,6 @@
* Convert material node-trees to GLSL.
*/
-#include "GL/glew.h"
-
#include "MEM_guardedalloc.h"
#include "DNA_customdata_types.h"
@@ -44,39 +42,59 @@
#include "BLI_dynstr.h"
#include "BLI_ghash.h"
+#include "GPU_glew.h"
#include "GPU_material.h"
#include "GPU_extensions.h"
-#include "BLI_sys_types.h" // for intptr_t support
+#include "BLI_sys_types.h" /* for intptr_t support */
#include "gpu_codegen.h"
-#include "node_util.h" /* For muting node stuff... */
-
#include <string.h>
#include <stdarg.h>
extern char datatoc_gpu_shader_material_glsl[];
extern char datatoc_gpu_shader_vertex_glsl[];
-
+extern char datatoc_gpu_shader_vertex_world_glsl[];
+extern char datatoc_gpu_shader_geometry_glsl[];
static char *glsl_material_library = NULL;
-/* structs and defines */
+/* type definitions and constants */
+
+enum {
+ MAX_FUNCTION_NAME = 64
+};
+enum {
+ MAX_PARAMETER = 32
+};
+typedef enum {
+ FUNCTION_QUAL_IN,
+ FUNCTION_QUAL_OUT,
+ FUNCTION_QUAL_INOUT
+} GPUFunctionQual;
+
+typedef struct GPUFunction {
+ char name[MAX_FUNCTION_NAME];
+ GPUType paramtype[MAX_PARAMETER];
+ GPUFunctionQual paramqual[MAX_PARAMETER];
+ int totparam;
+} GPUFunction;
+
+/* Indices match the GPUType enum */
static const char *GPU_DATATYPE_STR[17] = {"", "float", "vec2", "vec3", "vec4",
NULL, NULL, NULL, NULL, "mat3", NULL, NULL, NULL, NULL, NULL, NULL, "mat4"};
-#define LINK_IMAGE_BLENDER 1
-#define LINK_IMAGE_PREVIEW 2
-
/* GLSL code parsing for finding function definitions.
* These are stored in a hash for lookup when creating a material. */
-static GHash *FUNCTION_HASH= NULL;
-/* static char *FUNCTION_PROTOTYPES= NULL;
- * static GPUShader *FUNCTION_LIB= NULL;*/
+static GHash *FUNCTION_HASH = NULL;
+#if 0
+static char *FUNCTION_PROTOTYPES = NULL;
+static GPUShader *FUNCTION_LIB = NULL;
+#endif
static int gpu_str_prefix(const char *str, const char *prefix)
{
@@ -100,8 +118,8 @@ static char *gpu_str_skip_token(char *str, char *token, int max)
if (ELEM(*str, ' ', '(', ')', ',', '\t', '\n', '\r'))
break;
else {
- if (token && len < max-1) {
- *token= *str;
+ if (token && len < max - 1) {
+ *token = *str;
token++;
len++;
}
@@ -110,7 +128,7 @@ static char *gpu_str_skip_token(char *str, char *token, int max)
}
if (token)
- *token= '\0';
+ *token = '\0';
/* skip the next special characters:
* note the missing ')' */
@@ -127,7 +145,9 @@ static char *gpu_str_skip_token(char *str, char *token, int max)
static void gpu_parse_functions_string(GHash *hash, char *code)
{
GPUFunction *function;
- int i, type, qual;
+ GPUType type;
+ GPUFunctionQual qual;
+ int i;
while ((code = strstr(code, "void "))) {
function = MEM_callocN(sizeof(GPUFunction), "GPUFunction");
@@ -147,10 +167,10 @@ static void gpu_parse_functions_string(GHash *hash, char *code)
code = gpu_str_skip_token(code, NULL, 0);
/* test for type */
- type= 0;
- for (i=1; i<=16; i++) {
+ type = GPU_NONE;
+ for (i = 1; i <= 16; i++) {
if (GPU_DATATYPE_STR[i] && gpu_str_prefix(code, GPU_DATATYPE_STR[i])) {
- type= i;
+ type = i;
break;
}
}
@@ -161,11 +181,11 @@ static void gpu_parse_functions_string(GHash *hash, char *code)
type= GPU_TEX2D;
if (type) {
- /* add paramater */
+ /* add parameter */
code = gpu_str_skip_token(code, NULL, 0);
code = gpu_str_skip_token(code, NULL, 0);
- function->paramqual[function->totparam]= qual;
- function->paramtype[function->totparam]= type;
+ function->paramqual[function->totparam] = qual;
+ function->paramtype[function->totparam] = type;
function->totparam++;
}
else {
@@ -202,7 +222,7 @@ static char *gpu_generate_function_prototyps(GHash *hash)
function = BLI_ghashIterator_getValue(ghi);
BLI_dynstr_appendf(ds, "void %s(", name);
- for (a=0; a<function->totparam; a++) {
+ for (a = 0; a < function->totparam; a++) {
if (function->paramqual[a] == FUNCTION_QUAL_OUT)
BLI_dynstr_append(ds, "out ");
else if (function->paramqual[a] == FUNCTION_QUAL_INOUT)
@@ -214,10 +234,11 @@ static char *gpu_generate_function_prototyps(GHash *hash)
BLI_dynstr_append(ds, "sampler2DShadow");
else
BLI_dynstr_append(ds, GPU_DATATYPE_STR[function->paramtype[a]]);
-
- //BLI_dynstr_appendf(ds, " param%d", a);
-
- if (a != function->totparam-1)
+# if 0
+ BLI_dynstr_appendf(ds, " param%d", a);
+# endif
+
+ if (a != function->totparam - 1)
BLI_dynstr_append(ds, ", ");
}
BLI_dynstr_append(ds, ");\n");
@@ -232,27 +253,27 @@ static char *gpu_generate_function_prototyps(GHash *hash)
}
#endif
-GPUFunction *GPU_lookup_function(const char *name)
+static GPUFunction *gpu_lookup_function(const char *name)
{
if (!FUNCTION_HASH) {
FUNCTION_HASH = BLI_ghash_str_new("GPU_lookup_function gh");
gpu_parse_functions_string(FUNCTION_HASH, glsl_material_library);
}
- return (GPUFunction*)BLI_ghash_lookup(FUNCTION_HASH, (void *)name);
+ return BLI_ghash_lookup(FUNCTION_HASH, (const void *)name);
}
-void GPU_codegen_init(void)
+void gpu_codegen_init(void)
{
GPU_code_generate_glsl_lib();
}
-void GPU_codegen_exit(void)
+void gpu_codegen_exit(void)
{
- extern Material defmaterial; // render module abuse...
+ extern Material defmaterial; /* render module abuse... */
if (defmaterial.gpumaterial.first)
- GPU_material_free(&defmaterial);
+ GPU_material_free(&defmaterial.gpumaterial);
if (FUNCTION_HASH) {
BLI_ghash_free(FUNCTION_HASH, NULL, MEM_freeN);
@@ -266,14 +287,16 @@ void GPU_codegen_exit(void)
glsl_material_library = NULL;
}
- /*if (FUNCTION_PROTOTYPES) {
+#if 0
+ if (FUNCTION_PROTOTYPES) {
MEM_freeN(FUNCTION_PROTOTYPES);
FUNCTION_PROTOTYPES = NULL;
- }*/
- /*if (FUNCTION_LIB) {
+ }
+ if (FUNCTION_LIB) {
GPU_shader_free(FUNCTION_LIB);
FUNCTION_LIB = NULL;
- }*/
+ }
+#endif
}
/* GLSL code generation */
@@ -288,18 +311,16 @@ static void codegen_convert_datatype(DynStr *ds, int from, int to, const char *t
BLI_dynstr_append(ds, name);
}
else if (to == GPU_FLOAT) {
- if (from == GPU_VEC4)
- BLI_dynstr_appendf(ds, "dot(%s.rgb, vec3(0.35, 0.45, 0.2))", name);
- else if (from == GPU_VEC3)
- BLI_dynstr_appendf(ds, "dot(%s, vec3(0.33))", name);
+ if (from == GPU_VEC4 || from == GPU_VEC3)
+ BLI_dynstr_appendf(ds, "(%s.r + %s.g + %s.b) / 3.0", name, name, name);
else if (from == GPU_VEC2)
BLI_dynstr_appendf(ds, "%s.r", name);
}
else if (to == GPU_VEC2) {
if (from == GPU_VEC4)
- BLI_dynstr_appendf(ds, "vec2(dot(%s.rgb, vec3(0.35, 0.45, 0.2)), %s.a)", name, name);
+ BLI_dynstr_appendf(ds, "vec2((%s.r + %s.g + %s.b) / 3.0, %s.a)", name, name, name, name);
else if (from == GPU_VEC3)
- BLI_dynstr_appendf(ds, "vec2(dot(%s.rgb, vec3(0.33)), 1.0)", name);
+ BLI_dynstr_appendf(ds, "vec2((%s.r + %s.g + %s.b) / 3.0, 1.0)", name, name, name);
else if (from == GPU_FLOAT)
BLI_dynstr_appendf(ds, "vec2(%s, 1.0)", name);
}
@@ -321,15 +342,15 @@ static void codegen_convert_datatype(DynStr *ds, int from, int to, const char *t
}
}
-static void codegen_print_datatype(DynStr *ds, int type, float *data)
+static void codegen_print_datatype(DynStr *ds, const GPUType type, float *data)
{
int i;
BLI_dynstr_appendf(ds, "%s(", GPU_DATATYPE_STR[type]);
- for (i=0; i<type; i++) {
+ for (i = 0; i < type; i++) {
BLI_dynstr_appendf(ds, "%f", data[i]);
- if (i == type-1)
+ if (i == type - 1)
BLI_dynstr_append(ds, ")");
else
BLI_dynstr_append(ds, ", ");
@@ -364,10 +385,36 @@ const char *GPU_builtin_name(GPUBuiltin builtin)
return "unfobcolor";
else if (builtin == GPU_AUTO_BUMPSCALE)
return "unfobautobumpscale";
+ else if (builtin == GPU_CAMERA_TEXCO_FACTORS)
+ return "unfcameratexfactors";
+ else if (builtin == GPU_PARTICLE_SCALAR_PROPS)
+ return "unfparticlescalarprops";
+ else if (builtin == GPU_PARTICLE_LOCATION)
+ return "unfparticleco";
+ else if (builtin == GPU_PARTICLE_VELOCITY)
+ return "unfparticlevel";
+ else if (builtin == GPU_PARTICLE_ANG_VELOCITY)
+ return "unfparticleangvel";
else
return "";
}
+/* assign only one texid per buffer to avoid sampling the same texture twice */
+static void codegen_set_texid(GHash *bindhash, GPUInput *input, int *texid, void *key)
+{
+ if (BLI_ghash_haskey(bindhash, key)) {
+ /* Reuse existing texid */
+ input->texid = GET_INT_FROM_POINTER(BLI_ghash_lookup(bindhash, key));
+ }
+ else {
+ /* Allocate new texid */
+ input->texid = *texid;
+ (*texid)++;
+ input->bindtex = true;
+ BLI_ghash_insert(bindhash, key, SET_INT_IN_POINTER(input->texid));
+ }
+}
+
static void codegen_set_unique_ids(ListBase *nodes)
{
GHash *bindhash, *definehash;
@@ -376,75 +423,50 @@ static void codegen_set_unique_ids(ListBase *nodes)
GPUOutput *output;
int id = 1, texid = 0;
- bindhash= BLI_ghash_ptr_new("codegen_set_unique_ids1 gh");
- definehash= BLI_ghash_ptr_new("codegen_set_unique_ids2 gh");
+ bindhash = BLI_ghash_ptr_new("codegen_set_unique_ids1 gh");
+ definehash = BLI_ghash_ptr_new("codegen_set_unique_ids2 gh");
- for (node=nodes->first; node; node=node->next) {
- for (input=node->inputs.first; input; input=input->next) {
+ for (node = nodes->first; node; node = node->next) {
+ for (input = node->inputs.first; input; input = input->next) {
/* set id for unique names of uniform variables */
input->id = id++;
- input->bindtex = 0;
- input->definetex = 0;
+ input->bindtex = false;
+ input->definetex = false;
/* set texid used for settings texture slot with multitexture */
if (codegen_input_has_texture(input) &&
((input->source == GPU_SOURCE_TEX) || (input->source == GPU_SOURCE_TEX_PIXEL)))
{
+ /* assign only one texid per buffer to avoid sampling
+ * the same texture twice */
if (input->link) {
- /* input is texture from buffer, assign only one texid per
- * buffer to avoid sampling the same texture twice */
- if (!BLI_ghash_haskey(bindhash, input->link)) {
- input->texid = texid++;
- input->bindtex = 1;
- BLI_ghash_insert(bindhash, input->link, SET_INT_IN_POINTER(input->texid));
- }
- else
- input->texid = GET_INT_FROM_POINTER(BLI_ghash_lookup(bindhash, input->link));
+ /* input is texture from buffer */
+ codegen_set_texid(bindhash, input, &texid, input->link);
}
else if (input->ima) {
- /* input is texture from image, assign only one texid per
- * buffer to avoid sampling the same texture twice */
- if (!BLI_ghash_haskey(bindhash, input->ima)) {
- input->texid = texid++;
- input->bindtex = 1;
- BLI_ghash_insert(bindhash, input->ima, SET_INT_IN_POINTER(input->texid));
- }
- else
- input->texid = GET_INT_FROM_POINTER(BLI_ghash_lookup(bindhash, input->ima));
+ /* input is texture from image */
+ codegen_set_texid(bindhash, input, &texid, input->ima);
}
else if (input->prv) {
- /* input is texture from preview render, assign only one texid per
- * buffer to avoid sampling the same texture twice */
- if (!BLI_ghash_haskey(bindhash, input->prv)) {
- input->texid = texid++;
- input->bindtex = 1;
- BLI_ghash_insert(bindhash, input->prv, SET_INT_IN_POINTER(input->texid));
- }
- else
- input->texid = GET_INT_FROM_POINTER(BLI_ghash_lookup(bindhash, input->prv));
+ /* input is texture from preview render */
+ codegen_set_texid(bindhash, input, &texid, input->prv);
}
- else {
- if (!BLI_ghash_haskey(bindhash, input->tex)) {
- /* input is user created texture, check tex pointer */
- input->texid = texid++;
- input->bindtex = 1;
- BLI_ghash_insert(bindhash, input->tex, SET_INT_IN_POINTER(input->texid));
- }
- else
- input->texid = GET_INT_FROM_POINTER(BLI_ghash_lookup(bindhash, input->tex));
+ else if (input->tex) {
+ /* input is user created texture, check tex pointer */
+ codegen_set_texid(bindhash, input, &texid, input->tex);
}
/* make sure this pixel is defined exactly once */
if (input->source == GPU_SOURCE_TEX_PIXEL) {
if (input->ima) {
if (!BLI_ghash_haskey(definehash, input->ima)) {
- input->definetex = 1;
+ input->definetex = true;
BLI_ghash_insert(definehash, input->ima, SET_INT_IN_POINTER(input->texid));
}
}
else {
if (!BLI_ghash_haskey(definehash, input->link)) {
- input->definetex = 1;
+ input->definetex = true;
BLI_ghash_insert(definehash, input->link, SET_INT_IN_POINTER(input->texid));
}
}
@@ -452,7 +474,7 @@ static void codegen_set_unique_ids(ListBase *nodes)
}
}
- for (output=node->outputs.first; output; output=output->next)
+ for (output = node->outputs.first; output; output = output->next)
/* set id for unique names of tmp variables storing output */
output->id = id++;
}
@@ -469,8 +491,8 @@ static int codegen_print_uniforms_functions(DynStr *ds, ListBase *nodes)
int builtins = 0;
/* print uniforms */
- for (node=nodes->first; node; node=node->next) {
- for (input=node->inputs.first; input; input=input->next) {
+ for (node = nodes->first; node; node = node->next) {
+ for (input = node->inputs.first; input; input = input->next) {
if ((input->source == GPU_SOURCE_TEX) || (input->source == GPU_SOURCE_TEX_PIXEL)) {
/* create exactly one sampler for each texture */
if (codegen_input_has_texture(input) && input->bindtex)
@@ -509,8 +531,19 @@ static int codegen_print_uniforms_functions(DynStr *ds, ListBase *nodes)
}
}
else if (input->source == GPU_SOURCE_ATTRIB && input->attribfirst) {
+#ifdef WITH_OPENSUBDIV
+ bool skip_opensubdiv = input->attribtype == CD_TANGENT;
+ if (skip_opensubdiv) {
+ BLI_dynstr_appendf(ds, "#ifndef USE_OPENSUBDIV\n");
+ }
+#endif
BLI_dynstr_appendf(ds, "varying %s var%d;\n",
GPU_DATATYPE_STR[input->type], input->attribid);
+#ifdef WITH_OPENSUBDIV
+ if (skip_opensubdiv) {
+ BLI_dynstr_appendf(ds, "#endif\n");
+ }
+#endif
}
}
}
@@ -526,9 +559,9 @@ static void codegen_declare_tmps(DynStr *ds, ListBase *nodes)
GPUInput *input;
GPUOutput *output;
- for (node=nodes->first; node; node=node->next) {
+ for (node = nodes->first; node; node = node->next) {
/* load pixels from textures */
- for (input=node->inputs.first; input; input=input->next) {
+ for (input = node->inputs.first; input; input = input->next) {
if (input->source == GPU_SOURCE_TEX_PIXEL) {
if (codegen_input_has_texture(input) && input->definetex) {
BLI_dynstr_appendf(ds, "\tvec4 tex%d = texture2D(", input->texid);
@@ -539,7 +572,7 @@ static void codegen_declare_tmps(DynStr *ds, ListBase *nodes)
}
/* declare temporary variables for node output storage */
- for (output=node->outputs.first; output; output=output->next)
+ for (output = node->outputs.first; output; output = output->next)
BLI_dynstr_appendf(ds, "\t%s tmp%d;\n",
GPU_DATATYPE_STR[output->type], output->id);
}
@@ -553,10 +586,10 @@ static void codegen_call_functions(DynStr *ds, ListBase *nodes, GPUOutput *final
GPUInput *input;
GPUOutput *output;
- for (node=nodes->first; node; node=node->next) {
+ for (node = nodes->first; node; node = node->next) {
BLI_dynstr_appendf(ds, "\t%s(", node->name);
- for (input=node->inputs.first; input; input=input->next) {
+ for (input = node->inputs.first; input; input = input->next) {
if (input->source == GPU_SOURCE_TEX) {
BLI_dynstr_appendf(ds, "samp%d", input->texid);
if (input->link)
@@ -591,7 +624,7 @@ static void codegen_call_functions(DynStr *ds, ListBase *nodes, GPUOutput *final
BLI_dynstr_append(ds, ", ");
}
- for (output=node->outputs.first; output; output=output->next) {
+ for (output = node->outputs.first; output; output = output->next) {
BLI_dynstr_appendf(ds, "tmp%d", output->id);
if (output->next)
BLI_dynstr_append(ds, ", ");
@@ -605,26 +638,63 @@ static void codegen_call_functions(DynStr *ds, ListBase *nodes, GPUOutput *final
BLI_dynstr_append(ds, ";\n");
}
-static char *code_generate_fragment(ListBase *nodes, GPUOutput *output, const char *UNUSED(name))
+static char *code_generate_fragment(ListBase *nodes, GPUOutput *output)
{
DynStr *ds = BLI_dynstr_new();
char *code;
int builtins;
- /*BLI_dynstr_append(ds, FUNCTION_PROTOTYPES);*/
+#ifdef WITH_OPENSUBDIV
+ GPUNode *node;
+ GPUInput *input;
+#endif
+
+
+#if 0
+ BLI_dynstr_append(ds, FUNCTION_PROTOTYPES);
+#endif
codegen_set_unique_ids(nodes);
builtins = codegen_print_uniforms_functions(ds, nodes);
- //if (G.debug & G_DEBUG)
- // BLI_dynstr_appendf(ds, "/* %s */\n", name);
+#if 0
+ if (G.debug & G_DEBUG)
+ BLI_dynstr_appendf(ds, "/* %s */\n", name);
+#endif
BLI_dynstr_append(ds, "void main(void)\n");
BLI_dynstr_append(ds, "{\n");
if (builtins & GPU_VIEW_NORMAL)
BLI_dynstr_append(ds, "\tvec3 facingnormal = (gl_FrontFacing)? varnormal: -varnormal;\n");
-
+
+ /* Calculate tangent space. */
+#ifdef WITH_OPENSUBDIV
+ {
+ bool has_tangent = false;
+ for (node = nodes->first; node; node = node->next) {
+ for (input = node->inputs.first; input; input = input->next) {
+ if (input->source == GPU_SOURCE_ATTRIB && input->attribfirst) {
+ if (input->attribtype == CD_TANGENT) {
+ BLI_dynstr_appendf(ds, "#ifdef USE_OPENSUBDIV\n");
+ BLI_dynstr_appendf(ds, "\t%s var%d;\n",
+ GPU_DATATYPE_STR[input->type],
+ input->attribid);
+ if (has_tangent == false) {
+ BLI_dynstr_appendf(ds, "\tvec3 Q1 = dFdx(inpt.v.position.xyz);\n");
+ BLI_dynstr_appendf(ds, "\tvec3 Q2 = dFdy(inpt.v.position.xyz);\n");
+ BLI_dynstr_appendf(ds, "\tvec2 st1 = dFdx(inpt.v.uv);\n");
+ BLI_dynstr_appendf(ds, "\tvec2 st2 = dFdy(inpt.v.uv);\n");
+ BLI_dynstr_appendf(ds, "\tvec3 T = normalize(Q1 * st2.t - Q2 * st1.t);\n");
+ }
+ BLI_dynstr_appendf(ds, "\tvar%d = vec4(T, 1.0);\n", input->attribid);
+ BLI_dynstr_appendf(ds, "#endif\n");
+ }
+ }
+ }
+ }
+ }
+#endif
codegen_declare_tmps(ds, nodes);
codegen_call_functions(ds, nodes, output);
@@ -635,41 +705,86 @@ static char *code_generate_fragment(ListBase *nodes, GPUOutput *output, const ch
code = BLI_dynstr_get_cstring(ds);
BLI_dynstr_free(ds);
- //if (G.debug & G_DEBUG) printf("%s\n", code);
+#if 0
+ if (G.debug & G_DEBUG) printf("%s\n", code);
+#endif
return code;
}
-static char *code_generate_vertex(ListBase *nodes)
+static char *code_generate_vertex(ListBase *nodes, const GPUMatType type)
{
DynStr *ds = BLI_dynstr_new();
GPUNode *node;
GPUInput *input;
char *code;
+ char *vertcode = NULL;
- for (node=nodes->first; node; node=node->next) {
- for (input=node->inputs.first; input; input=input->next) {
+ for (node = nodes->first; node; node = node->next) {
+ for (input = node->inputs.first; input; input = input->next) {
if (input->source == GPU_SOURCE_ATTRIB && input->attribfirst) {
+#ifdef WITH_OPENSUBDIV
+ bool skip_opensubdiv = ELEM(input->attribtype, CD_MTFACE, CD_TANGENT);
+ if (skip_opensubdiv) {
+ BLI_dynstr_appendf(ds, "#ifndef USE_OPENSUBDIV\n");
+ }
+#endif
BLI_dynstr_appendf(ds, "attribute %s att%d;\n",
GPU_DATATYPE_STR[input->type], input->attribid);
BLI_dynstr_appendf(ds, "varying %s var%d;\n",
GPU_DATATYPE_STR[input->type], input->attribid);
+#ifdef WITH_OPENSUBDIV
+ if (skip_opensubdiv) {
+ BLI_dynstr_appendf(ds, "#endif\n");
+ }
+#endif
}
}
}
BLI_dynstr_append(ds, "\n");
- BLI_dynstr_append(ds, datatoc_gpu_shader_vertex_glsl);
- for (node=nodes->first; node; node=node->next)
- for (input=node->inputs.first; input; input=input->next)
+ switch (type) {
+ case GPU_MATERIAL_TYPE_MESH:
+ vertcode = datatoc_gpu_shader_vertex_glsl;
+ break;
+ case GPU_MATERIAL_TYPE_WORLD:
+ vertcode = datatoc_gpu_shader_vertex_world_glsl;
+ break;
+ default:
+ fprintf(stderr, "invalid material type, set one after GPU_material_construct_begin\n");
+ break;
+ }
+
+ BLI_dynstr_append(ds, vertcode);
+
+ for (node = nodes->first; node; node = node->next)
+ for (input = node->inputs.first; input; input = input->next)
if (input->source == GPU_SOURCE_ATTRIB && input->attribfirst) {
if (input->attribtype == CD_TANGENT) { /* silly exception */
- BLI_dynstr_appendf(ds, "\tvar%d.xyz = normalize((gl_ModelViewMatrix * vec4(att%d.xyz, 0)).xyz);\n", input->attribid, input->attribid);
+#ifdef WITH_OPENSUBDIV
+ BLI_dynstr_appendf(ds, "#ifndef USE_OPENSUBDIV\n");
+#endif
+ BLI_dynstr_appendf(ds, "\tvar%d.xyz = normalize(gl_NormalMatrix * att%d.xyz);\n", input->attribid, input->attribid);
BLI_dynstr_appendf(ds, "\tvar%d.w = att%d.w;\n", input->attribid, input->attribid);
+#ifdef WITH_OPENSUBDIV
+ BLI_dynstr_appendf(ds, "#endif\n");
+#endif
}
- else
+ else {
+#ifdef WITH_OPENSUBDIV
+ bool is_mtface = input->attribtype == CD_MTFACE;
+ if (is_mtface) {
+ BLI_dynstr_appendf(ds, "#ifndef USE_OPENSUBDIV\n");
+ }
+#endif
BLI_dynstr_appendf(ds, "\tvar%d = att%d;\n", input->attribid, input->attribid);
+#ifdef WITH_OPENSUBDIV
+ if (is_mtface) {
+ BLI_dynstr_appendf(ds, "#endif\n");
+ }
+#endif
+ }
}
/* unfortunately special handling is needed here because we abuse gl_Color/gl_SecondaryColor flat shading */
else if (input->source == GPU_SOURCE_OPENGL_BUILTIN) {
@@ -690,14 +805,69 @@ static char *code_generate_vertex(ListBase *nodes)
BLI_dynstr_free(ds);
- //if (G.debug & G_DEBUG) printf("%s\n", code);
+#if 0
+ if (G.debug & G_DEBUG) printf("%s\n", code);
+#endif
return code;
}
-int GPU_bicubic_bump_support(void)
+static char *code_generate_geometry(ListBase *nodes, bool use_opensubdiv)
{
- return GLEW_ARB_texture_query_lod && GLEW_VERSION_3_0;
+#ifdef WITH_OPENSUBDIV
+ if (use_opensubdiv) {
+ DynStr *ds = BLI_dynstr_new();
+ GPUNode *node;
+ GPUInput *input;
+ char *code;
+
+ /* Generate varying declarations. */
+ for (node = nodes->first; node; node = node->next) {
+ for (input = node->inputs.first; input; input = input->next) {
+ if (input->source == GPU_SOURCE_ATTRIB && input->attribfirst) {
+ if (input->attribtype == CD_MTFACE) {
+ BLI_dynstr_appendf(ds, "varying %s var%d;\n",
+ GPU_DATATYPE_STR[input->type],
+ input->attribid);
+ BLI_dynstr_appendf(ds, "uniform int fvar%d_offset;\n",
+ input->attribid);
+ }
+ }
+ }
+ }
+
+ BLI_dynstr_append(ds, datatoc_gpu_shader_geometry_glsl);
+
+ /* Generate varying assignments. */
+ /* TODO(sergey): Disabled for now, needs revisit. */
+#if 0
+ for (node = nodes->first; node; node = node->next) {
+ for (input = node->inputs.first; input; input = input->next) {
+ if (input->source == GPU_SOURCE_ATTRIB && input->attribfirst) {
+ if (input->attribtype == CD_MTFACE) {
+ BLI_dynstr_appendf(ds,
+ "\tINTERP_FACE_VARYING_2(var%d, "
+ "fvar%d_offset, st);\n",
+ input->attribid,
+ input->attribid);
+ }
+ }
+ }
+ }
+#endif
+
+ BLI_dynstr_append(ds, "}\n\n");
+ code = BLI_dynstr_get_cstring(ds);
+ BLI_dynstr_free(ds);
+
+ //if (G.debug & G_DEBUG) printf("%s\n", code);
+
+ return code;
+ }
+#else
+ UNUSED_VARS(nodes, use_opensubdiv);
+#endif
+ return NULL;
}
void GPU_code_generate_glsl_lib(void)
@@ -726,7 +896,7 @@ GPUShader *GPU_pass_shader(GPUPass *pass)
return pass->shader;
}
-static void GPU_nodes_extract_dynamic_inputs(GPUPass *pass, ListBase *nodes)
+static void gpu_nodes_extract_dynamic_inputs(GPUPass *pass, ListBase *nodes)
{
GPUShader *shader = pass->shader;
GPUNode *node;
@@ -741,15 +911,35 @@ static void GPU_nodes_extract_dynamic_inputs(GPUPass *pass, ListBase *nodes)
GPU_shader_bind(shader);
- for (node=nodes->first; node; node=node->next) {
+ for (node = nodes->first; node; node = node->next) {
z = 0;
- for (input=node->inputs.first; input; input=next, z++) {
+ for (input = node->inputs.first; input; input = next, z++) {
next = input->next;
/* attributes don't need to be bound, they already have
* an id that the drawing functions will use */
- if (input->source == GPU_SOURCE_ATTRIB ||
- input->source == GPU_SOURCE_BUILTIN ||
+ if (input->source == GPU_SOURCE_ATTRIB) {
+#ifdef WITH_OPENSUBDIV
+ /* We do need mtface attributes for later, so we can
+ * update face-varuing variables offset in the texture
+ * buffer for proper sampling from the shader.
+ *
+ * We don't do anything about attribute itself, we
+ * only use it to learn which uniform name is to be
+ * updated.
+ *
+ * TODO(sergey): We can add ad extra uniform input
+ * for the offset, which will be purely internal and
+ * which would avoid having such an exceptions.
+ */
+ if (input->attribtype != CD_MTFACE) {
+ continue;
+ }
+#else
+ continue;
+#endif
+ }
+ if (input->source == GPU_SOURCE_BUILTIN ||
input->source == GPU_SOURCE_OPENGL_BUILTIN)
{
continue;
@@ -773,6 +963,14 @@ static void GPU_nodes_extract_dynamic_inputs(GPUPass *pass, ListBase *nodes)
if (extract)
input->shaderloc = GPU_shader_get_uniform(shader, input->shadername);
+#ifdef WITH_OPENSUBDIV
+ if (input->source == GPU_SOURCE_ATTRIB &&
+ input->attribtype == CD_MTFACE)
+ {
+ extract = 1;
+ }
+#endif
+
/* extract nodes */
if (extract) {
BLI_remlink(&node->inputs, input);
@@ -796,7 +994,7 @@ void GPU_pass_bind(GPUPass *pass, double time, int mipmap)
GPU_shader_bind(shader);
/* now bind the textures */
- for (input=inputs->first; input; input=input->next) {
+ for (input = inputs->first; input; input = input->next) {
if (input->ima)
input->tex = GPU_texture_from_blender(input->ima, input->iuser, input->image_isdata, time, mipmap);
else if (input->prv)
@@ -820,10 +1018,19 @@ void GPU_pass_update_uniforms(GPUPass *pass)
return;
/* pass dynamic inputs to opengl, others were removed */
- for (input=inputs->first; input; input=input->next)
- if (!(input->ima || input->tex || input->prv))
- GPU_shader_uniform_vector(shader, input->shaderloc, input->type, 1,
- input->dynamicvec);
+ for (input = inputs->first; input; input = input->next) {
+ if (!(input->ima || input->tex || input->prv)) {
+ if (input->dynamictype == GPU_DYNAMIC_MAT_HARD) {
+ // The hardness is actually a short pointer, so we convert it here
+ float val = (float)(*(short*)input->dynamicvec);
+ GPU_shader_uniform_vector(shader, input->shaderloc, 1, 1, &val);
+ }
+ else {
+ GPU_shader_uniform_vector(shader, input->shaderloc, input->type, 1,
+ input->dynamicvec);
+ }
+ }
+ }
}
void GPU_pass_unbind(GPUPass *pass)
@@ -835,7 +1042,7 @@ void GPU_pass_unbind(GPUPass *pass)
if (!shader)
return;
- for (input=inputs->first; input; input=input->next) {
+ for (input = inputs->first; input; input = input->next) {
if (input->tex && input->bindtex)
GPU_texture_unbind(input->tex);
@@ -848,16 +1055,16 @@ void GPU_pass_unbind(GPUPass *pass)
/* Node Link Functions */
-static GPUNodeLink *GPU_node_link_create(int type)
+static GPUNodeLink *GPU_node_link_create(void)
{
GPUNodeLink *link = MEM_callocN(sizeof(GPUNodeLink), "GPUNodeLink");
- link->type = type;
+ link->type = GPU_NONE;
link->users++;
return link;
}
-static void GPU_node_link_free(GPUNodeLink *link)
+static void gpu_node_link_free(GPUNodeLink *link)
{
link->users--;
@@ -877,17 +1084,12 @@ static GPUNode *GPU_node_begin(const char *name)
{
GPUNode *node = MEM_callocN(sizeof(GPUNode), "GPUNode");
- node->name= name;
+ node->name = name;
return node;
}
-static void GPU_node_end(GPUNode *UNUSED(node))
-{
- /* empty */
-}
-
-static void gpu_node_input_link(GPUNode *node, GPUNodeLink *link, int type)
+static void gpu_node_input_link(GPUNode *node, GPUNodeLink *link, const GPUType type)
{
GPUInput *input;
GPUNode *outnode;
@@ -896,8 +1098,11 @@ static void gpu_node_input_link(GPUNode *node, GPUNodeLink *link, int type)
if (link->output) {
outnode = link->output->node;
name = outnode->name;
+ input = outnode->inputs.first;
- if (strcmp(name, "set_value")==0 || strcmp(name, "set_rgb")==0) {
+ if ((STREQ(name, "set_value") || STREQ(name, "set_rgb")) &&
+ (input->type == type))
+ {
input = MEM_dupallocN(outnode->inputs.first);
input->type = type;
if (input->link)
@@ -941,7 +1146,7 @@ static void gpu_node_input_link(GPUNode *node, GPUNodeLink *link, int type)
input->tex = link->dynamictex;
input->textarget = GL_TEXTURE_2D;
input->textype = type;
- input->dynamictex = 1;
+ input->dynamictex = true;
input->dynamicdata = link->ptr2;
MEM_freeN(link);
}
@@ -951,8 +1156,10 @@ static void gpu_node_input_link(GPUNode *node, GPUNodeLink *link, int type)
input->source = GPU_SOURCE_TEX;
input->textype = type;
- //input->tex = GPU_texture_create_2D(link->texturesize, link->texturesize, link->ptr2, NULL);
- input->tex = GPU_texture_create_2D(link->texturesize, 1, link->ptr1, NULL);
+#if 0
+ input->tex = GPU_texture_create_2D(link->texturesize, link->texturesize, link->ptr2, NULL);
+#endif
+ input->tex = GPU_texture_create_2D(link->texturesize, 1, link->ptr1, GPU_HDR_NONE, NULL);
input->textarget = GL_TEXTURE_2D;
MEM_freeN(link->ptr1);
@@ -963,7 +1170,7 @@ static void gpu_node_input_link(GPUNode *node, GPUNodeLink *link, int type)
input->type = GPU_VEC4;
input->source = GPU_SOURCE_TEX;
- if (link->image == LINK_IMAGE_PREVIEW)
+ if (link->image == GPU_NODE_LINK_IMAGE_PREVIEW)
input->prv = link->ptr1;
else {
input->ima = link->ptr1;
@@ -990,9 +1197,9 @@ static void gpu_node_input_link(GPUNode *node, GPUNodeLink *link, int type)
memcpy(input->vec, link->ptr1, type*sizeof(float));
if (link->dynamic) {
- input->dynamicvec= link->ptr1;
- input->dynamictype= link->dynamictype;
- input->dynamicdata= link->ptr2;
+ input->dynamicvec = link->ptr1;
+ input->dynamictype = link->dynamictype;
+ input->dynamicdata = link->ptr2;
}
MEM_freeN(link);
}
@@ -1008,13 +1215,13 @@ static void gpu_node_input_socket(GPUNode *node, GPUNodeStack *sock)
gpu_node_input_link(node, sock->link, sock->type);
}
else {
- link = GPU_node_link_create(0);
+ link = GPU_node_link_create();
link->ptr1 = sock->vec;
gpu_node_input_link(node, link, sock->type);
}
}
-static void GPU_node_output(GPUNode *node, int type, const char *UNUSED(name), GPUNodeLink **link)
+static void gpu_node_output(GPUNode *node, const GPUType type, GPUNodeLink **link)
{
GPUOutput *output = MEM_callocN(sizeof(GPUOutput), "GPUOutput");
@@ -1022,10 +1229,11 @@ static void GPU_node_output(GPUNode *node, int type, const char *UNUSED(name), G
output->node = node;
if (link) {
- *link = output->link = GPU_node_link_create(type);
+ *link = output->link = GPU_node_link_create();
+ output->link->type = type;
output->link->output = output;
- /* note: the caller owns the reference to the linkfer, GPUOutput
+ /* note: the caller owns the reference to the link, GPUOutput
* merely points to it, and if the node is destroyed it will
* set that pointer to NULL */
}
@@ -1033,13 +1241,13 @@ static void GPU_node_output(GPUNode *node, int type, const char *UNUSED(name), G
BLI_addtail(&node->outputs, output);
}
-static void GPU_inputs_free(ListBase *inputs)
+static void gpu_inputs_free(ListBase *inputs)
{
GPUInput *input;
- for (input=inputs->first; input; input=input->next) {
+ for (input = inputs->first; input; input = input->next) {
if (input->link)
- GPU_node_link_free(input->link);
+ gpu_node_link_free(input->link);
else if (input->tex && !input->dynamictex)
GPU_texture_free(input->tex);
}
@@ -1047,28 +1255,28 @@ static void GPU_inputs_free(ListBase *inputs)
BLI_freelistN(inputs);
}
-static void GPU_node_free(GPUNode *node)
+static void gpu_node_free(GPUNode *node)
{
GPUOutput *output;
- GPU_inputs_free(&node->inputs);
+ gpu_inputs_free(&node->inputs);
- for (output=node->outputs.first; output; output=output->next)
+ for (output = node->outputs.first; output; output = output->next)
if (output->link) {
output->link->output = NULL;
- GPU_node_link_free(output->link);
+ gpu_node_link_free(output->link);
}
BLI_freelistN(&node->outputs);
MEM_freeN(node);
}
-static void GPU_nodes_free(ListBase *nodes)
+static void gpu_nodes_free(ListBase *nodes)
{
GPUNode *node;
while ((node = BLI_pophead(nodes))) {
- GPU_node_free(node);
+ gpu_node_free(node);
}
}
@@ -1085,12 +1293,12 @@ static void gpu_nodes_get_vertex_attributes(ListBase *nodes, GPUVertexAttribs *a
memset(attribs, 0, sizeof(*attribs));
- for (node=nodes->first; node; node=node->next) {
- for (input=node->inputs.first; input; input=input->next) {
+ for (node = nodes->first; node; node = node->next) {
+ for (input = node->inputs.first; input; input = input->next) {
if (input->source == GPU_SOURCE_ATTRIB) {
- for (a=0; a<attribs->totlayer; a++) {
+ for (a = 0; a < attribs->totlayer; a++) {
if (attribs->layer[a].type == input->attribtype &&
- strcmp(attribs->layer[a].name, input->attribname) == 0)
+ STREQ(attribs->layer[a].name, input->attribname))
{
break;
}
@@ -1120,43 +1328,43 @@ static void gpu_nodes_get_builtin_flag(ListBase *nodes, int *builtin)
GPUNode *node;
GPUInput *input;
- *builtin= 0;
+ *builtin = 0;
- for (node=nodes->first; node; node=node->next)
- for (input=node->inputs.first; input; input=input->next)
+ for (node = nodes->first; node; node = node->next)
+ for (input = node->inputs.first; input; input = input->next)
if (input->source == GPU_SOURCE_BUILTIN)
*builtin |= input->builtin;
}
/* varargs linking */
-GPUNodeLink *GPU_attribute(int type, const char *name)
+GPUNodeLink *GPU_attribute(const CustomDataType type, const char *name)
{
- GPUNodeLink *link = GPU_node_link_create(0);
+ GPUNodeLink *link = GPU_node_link_create();
- link->attribtype= type;
- link->attribname= name;
+ link->attribtype = type;
+ link->attribname = name;
return link;
}
GPUNodeLink *GPU_uniform(float *num)
{
- GPUNodeLink *link = GPU_node_link_create(0);
+ GPUNodeLink *link = GPU_node_link_create();
- link->ptr1= num;
- link->ptr2= NULL;
+ link->ptr1 = num;
+ link->ptr2 = NULL;
return link;
}
-GPUNodeLink *GPU_dynamic_uniform(float *num, int dynamictype, void *data)
+GPUNodeLink *GPU_dynamic_uniform(float *num, GPUDynamicType dynamictype, void *data)
{
- GPUNodeLink *link = GPU_node_link_create(0);
+ GPUNodeLink *link = GPU_node_link_create();
- link->ptr1= num;
- link->ptr2= data;
- link->dynamic= 1;
+ link->ptr1 = num;
+ link->ptr2 = data;
+ link->dynamic = true;
link->dynamictype = dynamictype;
@@ -1165,9 +1373,9 @@ GPUNodeLink *GPU_dynamic_uniform(float *num, int dynamictype, void *data)
GPUNodeLink *GPU_image(Image *ima, ImageUser *iuser, bool is_data)
{
- GPUNodeLink *link = GPU_node_link_create(0);
+ GPUNodeLink *link = GPU_node_link_create();
- link->image = LINK_IMAGE_BLENDER;
+ link->image = GPU_NODE_LINK_IMAGE_BLENDER;
link->ptr1 = ima;
link->ptr2 = iuser;
link->image_isdata = is_data;
@@ -1177,10 +1385,10 @@ GPUNodeLink *GPU_image(Image *ima, ImageUser *iuser, bool is_data)
GPUNodeLink *GPU_image_preview(PreviewImage *prv)
{
- GPUNodeLink *link = GPU_node_link_create(0);
+ GPUNodeLink *link = GPU_node_link_create();
- link->image= LINK_IMAGE_PREVIEW;
- link->ptr1= prv;
+ link->image = GPU_NODE_LINK_IMAGE_PREVIEW;
+ link->ptr1 = prv;
return link;
}
@@ -1188,20 +1396,20 @@ GPUNodeLink *GPU_image_preview(PreviewImage *prv)
GPUNodeLink *GPU_texture(int size, float *pixels)
{
- GPUNodeLink *link = GPU_node_link_create(0);
+ GPUNodeLink *link = GPU_node_link_create();
- link->texture = 1;
+ link->texture = true;
link->texturesize = size;
- link->ptr1= pixels;
+ link->ptr1 = pixels;
return link;
}
-GPUNodeLink *GPU_dynamic_texture(GPUTexture *tex, int dynamictype, void *data)
+GPUNodeLink *GPU_dynamic_texture(GPUTexture *tex, GPUDynamicType dynamictype, void *data)
{
- GPUNodeLink *link = GPU_node_link_create(0);
+ GPUNodeLink *link = GPU_node_link_create();
- link->dynamic = 1;
+ link->dynamic = true;
link->dynamictex = tex;
link->dynamictype = dynamictype;
link->ptr2 = data;
@@ -1211,7 +1419,7 @@ GPUNodeLink *GPU_dynamic_texture(GPUTexture *tex, int dynamictype, void *data)
GPUNodeLink *GPU_builtin(GPUBuiltin builtin)
{
- GPUNodeLink *link = GPU_node_link_create(0);
+ GPUNodeLink *link = GPU_node_link_create();
link->builtin= builtin;
@@ -1220,7 +1428,7 @@ GPUNodeLink *GPU_builtin(GPUBuiltin builtin)
GPUNodeLink *GPU_opengl_builtin(GPUOpenGLBuiltin builtin)
{
- GPUNodeLink *link = GPU_node_link_create(0);
+ GPUNodeLink *link = GPU_node_link_create();
link->oglbuiltin = builtin;
@@ -1235,7 +1443,7 @@ bool GPU_link(GPUMaterial *mat, const char *name, ...)
va_list params;
int i;
- function = GPU_lookup_function(name);
+ function = gpu_lookup_function(name);
if (!function) {
fprintf(stderr, "GPU failed to find function %s\n", name);
return 0;
@@ -1244,20 +1452,18 @@ bool GPU_link(GPUMaterial *mat, const char *name, ...)
node = GPU_node_begin(name);
va_start(params, name);
- for (i=0; i<function->totparam; i++) {
+ for (i = 0; i<function->totparam; i++) {
if (function->paramqual[i] != FUNCTION_QUAL_IN) {
- linkptr= va_arg(params, GPUNodeLink**);
- GPU_node_output(node, function->paramtype[i], "", linkptr);
+ linkptr = va_arg(params, GPUNodeLink**);
+ gpu_node_output(node, function->paramtype[i], linkptr);
}
else {
- link= va_arg(params, GPUNodeLink*);
+ link = va_arg(params, GPUNodeLink*);
gpu_node_input_link(node, link, function->paramtype[i]);
}
}
va_end(params);
- GPU_node_end(node);
-
gpu_material_add_node(mat, node);
return 1;
@@ -1271,7 +1477,7 @@ bool GPU_stack_link(GPUMaterial *mat, const char *name, GPUNodeStack *in, GPUNod
va_list params;
int i, totin, totout;
- function = GPU_lookup_function(name);
+ function = gpu_lookup_function(name);
if (!function) {
fprintf(stderr, "GPU failed to find function %s\n", name);
return 0;
@@ -1290,24 +1496,24 @@ bool GPU_stack_link(GPUMaterial *mat, const char *name, GPUNodeStack *in, GPUNod
if (out) {
for (i = 0; out[i].type != GPU_NONE; i++) {
- GPU_node_output(node, out[i].type, out[i].name, &out[i].link);
+ gpu_node_output(node, out[i].type, &out[i].link);
totout++;
}
}
va_start(params, out);
- for (i=0; i<function->totparam; i++) {
+ for (i = 0; i<function->totparam; i++) {
if (function->paramqual[i] != FUNCTION_QUAL_IN) {
if (totout == 0) {
- linkptr= va_arg(params, GPUNodeLink**);
- GPU_node_output(node, function->paramtype[i], "", linkptr);
+ linkptr = va_arg(params, GPUNodeLink**);
+ gpu_node_output(node, function->paramtype[i], linkptr);
}
else
totout--;
}
else {
if (totin == 0) {
- link= va_arg(params, GPUNodeLink*);
+ link = va_arg(params, GPUNodeLink*);
if (link->socket)
gpu_node_input_socket(node, link->socket);
else
@@ -1319,8 +1525,6 @@ bool GPU_stack_link(GPUMaterial *mat, const char *name, GPUNodeStack *in, GPUNod
}
va_end(params);
- GPU_node_end(node);
-
gpu_material_add_node(mat, node);
return 1;
@@ -1336,7 +1540,7 @@ int GPU_link_changed(GPUNodeLink *link)
node = link->output->node;
name = node->name;
- if (strcmp(name, "set_value")==0 || strcmp(name, "set_rgb")==0) {
+ if (STREQ(name, "set_value") || STREQ(name, "set_rgb")) {
input = node->inputs.first;
return (input->link != NULL);
}
@@ -1361,8 +1565,8 @@ static void gpu_nodes_tag(GPUNodeLink *link)
if (node->tag)
return;
- node->tag= 1;
- for (input=node->inputs.first; input; input=input->next)
+ node->tag = true;
+ for (input = node->inputs.first; input; input = input->next)
if (input->link)
gpu_nodes_tag(input->link);
}
@@ -1371,31 +1575,35 @@ static void gpu_nodes_prune(ListBase *nodes, GPUNodeLink *outlink)
{
GPUNode *node, *next;
- for (node=nodes->first; node; node=node->next)
- node->tag= 0;
+ for (node = nodes->first; node; node = node->next)
+ node->tag = false;
gpu_nodes_tag(outlink);
- for (node=nodes->first; node; node=next) {
+ for (node = nodes->first; node; node = next) {
next = node->next;
if (!node->tag) {
BLI_remlink(nodes, node);
- GPU_node_free(node);
+ gpu_node_free(node);
}
}
}
-GPUPass *GPU_generate_pass(ListBase *nodes, GPUNodeLink *outlink, GPUVertexAttribs *attribs, int *builtins, const char *name)
+GPUPass *GPU_generate_pass(ListBase *nodes, GPUNodeLink *outlink,
+ GPUVertexAttribs *attribs, int *builtins,
+ const GPUMatType type, const char *UNUSED(name), const bool use_opensubdiv)
{
GPUShader *shader;
GPUPass *pass;
- char *vertexcode, *fragmentcode;
+ char *vertexcode, *geometrycode, *fragmentcode;
- /*if (!FUNCTION_LIB) {
+#if 0
+ if (!FUNCTION_LIB) {
GPU_nodes_free(nodes);
return NULL;
- }*/
+ }
+#endif
/* prune unused nodes */
gpu_nodes_prune(nodes, outlink);
@@ -1404,9 +1612,19 @@ GPUPass *GPU_generate_pass(ListBase *nodes, GPUNodeLink *outlink, GPUVertexAttri
gpu_nodes_get_builtin_flag(nodes, builtins);
/* generate code and compile with opengl */
- fragmentcode = code_generate_fragment(nodes, outlink->output, name);
- vertexcode = code_generate_vertex(nodes);
- shader = GPU_shader_create(vertexcode, fragmentcode, glsl_material_library, NULL);
+ fragmentcode = code_generate_fragment(nodes, outlink->output);
+ vertexcode = code_generate_vertex(nodes, type);
+ geometrycode = code_generate_geometry(nodes, use_opensubdiv);
+ shader = GPU_shader_create_ex(vertexcode,
+ fragmentcode,
+ geometrycode,
+ glsl_material_library,
+ NULL,
+ 0,
+ 0,
+ 0,
+ use_opensubdiv ? GPU_SHADER_FLAGS_SPECIAL_OPENSUBDIV
+ : GPU_SHADER_FLAGS_NONE);
/* failed? */
if (!shader) {
@@ -1416,7 +1634,7 @@ GPUPass *GPU_generate_pass(ListBase *nodes, GPUNodeLink *outlink, GPUVertexAttri
MEM_freeN(vertexcode);
memset(attribs, 0, sizeof(*attribs));
memset(builtins, 0, sizeof(*builtins));
- GPU_nodes_free(nodes);
+ gpu_nodes_free(nodes);
return NULL;
}
@@ -1426,12 +1644,13 @@ GPUPass *GPU_generate_pass(ListBase *nodes, GPUNodeLink *outlink, GPUVertexAttri
pass->output = outlink->output;
pass->shader = shader;
pass->fragmentcode = fragmentcode;
+ pass->geometrycode = geometrycode;
pass->vertexcode = vertexcode;
pass->libcode = glsl_material_library;
/* extract dynamic inputs and throw away nodes */
- GPU_nodes_extract_dynamic_inputs(pass, nodes);
- GPU_nodes_free(nodes);
+ gpu_nodes_extract_dynamic_inputs(pass, nodes);
+ gpu_nodes_free(nodes);
return pass;
}
@@ -1439,11 +1658,12 @@ GPUPass *GPU_generate_pass(ListBase *nodes, GPUNodeLink *outlink, GPUVertexAttri
void GPU_pass_free(GPUPass *pass)
{
GPU_shader_free(pass->shader);
- GPU_inputs_free(&pass->inputs);
+ gpu_inputs_free(&pass->inputs);
if (pass->fragmentcode)
MEM_freeN(pass->fragmentcode);
+ if (pass->geometrycode)
+ MEM_freeN(pass->geometrycode);
if (pass->vertexcode)
MEM_freeN(pass->vertexcode);
MEM_freeN(pass);
}
-
diff --git a/source/blender/gpu/intern/gpu_codegen.h b/source/blender/gpu/intern/gpu_codegen.h
index b6db923e5c2..5aa187014ba 100644
--- a/source/blender/gpu/intern/gpu_codegen.h
+++ b/source/blender/gpu/intern/gpu_codegen.h
@@ -33,34 +33,18 @@
#ifndef __GPU_CODEGEN_H__
#define __GPU_CODEGEN_H__
+#include "DNA_customdata_types.h"
#include "DNA_listBase.h"
#include "GPU_material.h"
-#include "GL/glew.h"
+#include "GPU_glew.h"
struct ListBase;
struct GPUShader;
struct GPUOutput;
struct GPUNode;
struct GPUVertexAttribs;
-struct GPUFrameBuffer;
struct PreviewImage;
-#define MAX_FUNCTION_NAME 64
-#define MAX_PARAMETER 32
-
-#define FUNCTION_QUAL_IN 0
-#define FUNCTION_QUAL_OUT 1
-#define FUNCTION_QUAL_INOUT 2
-
-typedef struct GPUFunction {
- char name[MAX_FUNCTION_NAME];
- int paramtype[MAX_PARAMETER];
- int paramqual[MAX_PARAMETER];
- int totparam;
-} GPUFunction;
-
-GPUFunction *GPU_lookup_function(const char *name);
-
/* Pass Generation
* - Takes a list of nodes and a desired output, and makes a pass. This
* will take ownership of the nodes and free them early if unused or
@@ -76,11 +60,19 @@ typedef enum GPUDataSource {
GPU_SOURCE_ATTRIB
} GPUDataSource;
+typedef enum {
+ GPU_NODE_LINK_IMAGE_NONE = 0,
+ GPU_NODE_LINK_IMAGE_BLENDER = 1,
+ GPU_NODE_LINK_IMAGE_PREVIEW = 2
+} GPUNodeLinkImage;
+
struct GPUNode {
struct GPUNode *next, *prev;
const char *name;
- int tag;
+
+ /* Internal flag to mark nodes during pruning */
+ bool tag;
ListBase inputs;
ListBase outputs;
@@ -89,24 +81,26 @@ struct GPUNode {
struct GPUNodeLink {
GPUNodeStack *socket;
- int attribtype;
+ CustomDataType attribtype;
const char *attribname;
- int image;
- int image_isdata;
+ GPUNodeLinkImage image;
+ bool image_isdata;
- int texture;
+ bool texture;
int texturesize;
void *ptr1, *ptr2;
- int dynamic;
- int dynamictype;
+ bool dynamic;
+ GPUDynamicType dynamictype;
+
+ GPUType type;
- int type;
+ /* Refcount */
int users;
- GPUTexture *dynamictex;
+ struct GPUTexture *dynamictex;
GPUBuiltin builtin;
GPUOpenGLBuiltin oglbuiltin;
@@ -118,9 +112,9 @@ typedef struct GPUOutput {
struct GPUOutput *next, *prev;
GPUNode *node;
- int type; /* data type = length of vector/matrix */
- GPUNodeLink *link; /* output link */
- int id; /* unique id as created by code generator */
+ GPUType type; /* data type = length of vector/matrix */
+ GPUNodeLink *link; /* output link */
+ int id; /* unique id as created by code generator */
} GPUOutput;
typedef struct GPUInput {
@@ -128,35 +122,35 @@ typedef struct GPUInput {
GPUNode *node;
- int type; /* datatype */
- int source; /* data source */
-
- int id; /* unique id as created by code generator */
- int texid; /* number for multitexture */
- int attribid; /* id for vertex attributes */
- int bindtex; /* input is responsible for binding the texture? */
- int definetex; /* input is responsible for defining the pixel? */
- int textarget; /* GL_TEXTURE_* */
- int textype; /* datatype */
-
- struct Image *ima; /* image */
- struct ImageUser *iuser;/* image user */
- struct PreviewImage *prv; /* preview images & icons */
- int image_isdata; /* image does not contain color data */
- float *dynamicvec; /* vector data in case it is dynamic */
- int dynamictype; /* origin of the dynamic uniform (GPUDynamicType) */
- void *dynamicdata; /* data source of the dynamic uniform */
- GPUTexture *tex; /* input texture, only set at runtime */
- int shaderloc; /* id from opengl */
- char shadername[32]; /* name in shader */
-
- float vec[16]; /* vector data */
+ GPUType type; /* datatype */
+ GPUDataSource source; /* data source */
+
+ int id; /* unique id as created by code generator */
+ int texid; /* number for multitexture, starting from zero */
+ int attribid; /* id for vertex attributes */
+ bool bindtex; /* input is responsible for binding the texture? */
+ bool definetex; /* input is responsible for defining the pixel? */
+ int textarget; /* GL texture target, e.g. GL_TEXTURE_2D */
+ GPUType textype; /* datatype */
+
+ struct Image *ima; /* image */
+ struct ImageUser *iuser; /* image user */
+ struct PreviewImage *prv; /* preview images & icons */
+ bool image_isdata; /* image does not contain color data */
+ float *dynamicvec; /* vector data in case it is dynamic */
+ GPUDynamicType dynamictype; /* origin of the dynamic uniform */
+ void *dynamicdata; /* data source of the dynamic uniform */
+ struct GPUTexture *tex; /* input texture, only set at runtime */
+ int shaderloc; /* id from opengl */
+ char shadername[32]; /* name in shader */
+
+ float vec[16]; /* vector data */
GPUNodeLink *link;
- int dynamictex; /* dynamic? */
- int attribtype; /* attribute type */
- char attribname[32]; /* attribute name */
- int attribfirst; /* this is the first one that is bound */
- GPUBuiltin builtin; /* builtin uniform */
+ bool dynamictex; /* dynamic? */
+ CustomDataType attribtype; /* attribute type */
+ char attribname[MAX_CUSTOMDATA_LAYER_NAME]; /* attribute name */
+ int attribfirst; /* this is the first one that is bound */
+ GPUBuiltin builtin; /* builtin uniform */
GPUOpenGLBuiltin oglbuiltin; /* opengl built in varying */
} GPUInput;
@@ -167,6 +161,7 @@ struct GPUPass {
struct GPUOutput *output;
struct GPUShader *shader;
char *fragmentcode;
+ char *geometrycode;
char *vertexcode;
const char *libcode;
};
@@ -175,7 +170,8 @@ struct GPUPass {
typedef struct GPUPass GPUPass;
GPUPass *GPU_generate_pass(ListBase *nodes, struct GPUNodeLink *outlink,
- struct GPUVertexAttribs *attribs, int *builtin, const char *name);
+ struct GPUVertexAttribs *attribs, int *builtin,
+ const GPUMatType type, const char *name, const bool use_opensubdiv);
struct GPUShader *GPU_pass_shader(GPUPass *pass);
@@ -185,8 +181,8 @@ void GPU_pass_unbind(GPUPass *pass);
void GPU_pass_free(GPUPass *pass);
-void GPU_codegen_init(void);
-void GPU_codegen_exit(void);
+void gpu_codegen_init(void);
+void gpu_codegen_exit(void);
/* Material calls */
diff --git a/source/blender/gpu/intern/gpu_compositing.c b/source/blender/gpu/intern/gpu_compositing.c
new file mode 100644
index 00000000000..da5db73d382
--- /dev/null
+++ b/source/blender/gpu/intern/gpu_compositing.c
@@ -0,0 +1,1289 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2006 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Antony Riakiotakis.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/gpu/intern/gpu_compositing.c
+ * \ingroup gpu
+ *
+ * System that manages framebuffer compositing.
+ */
+
+#include "BLI_sys_types.h"
+#include "BLI_rect.h"
+#include "BLI_math.h"
+#include "BLI_listbase.h"
+#include "BLI_linklist.h"
+
+#include "BLI_rand.h"
+#include "BLI_listbase.h"
+
+#include "DNA_vec_types.h"
+#include "DNA_view3d_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_object_types.h"
+#include "DNA_camera_types.h"
+#include "DNA_gpu_types.h"
+
+#include "GPU_extensions.h"
+#include "GPU_compositing.h"
+
+#include "GPU_glew.h"
+
+#include "MEM_guardedalloc.h"
+
+static const float fullscreencos[4][2] = {{-1.0f, -1.0f}, {1.0f, -1.0f}, {-1.0f, 1.0f}, {1.0f, 1.0f}};
+static const float fullscreenuvs[4][2] = {{0.0f, 0.0f}, {1.0f, 0.0f}, {0.0f, 1.0f}, {1.0f, 1.0f}};
+
+struct GPUFX {
+ /* we borrow the term gbuffer from deferred rendering however this is just a regular
+ * depth/color framebuffer. Could be extended later though */
+ GPUFrameBuffer *gbuffer;
+
+ /* dimensions of the gbuffer */
+ int gbuffer_dim[2];
+
+ /* texture bound to the first color attachment of the gbuffer */
+ GPUTexture *color_buffer;
+
+ /* second texture used for ping-pong compositing */
+ GPUTexture *color_buffer_sec;
+ /* texture bound to the depth attachment of the gbuffer */
+ GPUTexture *depth_buffer;
+ GPUTexture *depth_buffer_xray;
+
+ /* texture used for jittering for various effects */
+ GPUTexture *jitter_buffer;
+
+ /* all those buffers below have to coexist. Fortunately they are all quarter sized (1/16th of memory) of original framebuffer */
+ int dof_downsampled_w;
+ int dof_downsampled_h;
+
+ /* texture used for near coc and color blurring calculation */
+ GPUTexture *dof_near_coc_buffer;
+ /* blurred near coc buffer. */
+ GPUTexture *dof_near_coc_blurred_buffer;
+ /* final near coc buffer. */
+ GPUTexture *dof_near_coc_final_buffer;
+
+ /* half size blur buffer */
+ GPUTexture *dof_half_downsampled_near;
+ GPUTexture *dof_half_downsampled_far;
+ /* high quality dof texture downsamplers. 6 levels means 64 pixels wide - should be enough */
+ GPUTexture *dof_nearfar_coc;
+ GPUTexture *dof_near_blur;
+ GPUTexture *dof_far_blur;
+
+ /* for high quality we use again a spiral texture with radius adapted */
+ bool dof_high_quality;
+
+ /* texture used for ssao */
+ int ssao_sample_count_cache;
+ GPUTexture *ssao_spiral_samples_tex;
+
+
+ GPUFXSettings settings;
+
+ /* or-ed flags of enabled effects */
+ int effects;
+
+ /* number of passes, needed to detect if ping pong buffer allocation is needed */
+ int num_passes;
+
+ /* we have a stencil, restore the previous state */
+ bool restore_stencil;
+
+ unsigned int vbuffer;
+};
+
+#if 0
+/* concentric mapping, see "A Low Distortion Map Between Disk and Square" and
+ * http://psgraphics.blogspot.nl/2011/01/improved-code-for-concentric-map.html */
+static GPUTexture * create_concentric_sample_texture(int side)
+{
+ GPUTexture *tex;
+ float midpoint = 0.5f * (side - 1);
+ float *texels = (float *)MEM_mallocN(sizeof(float) * 2 * side * side, "concentric_tex");
+ int i, j;
+
+ for (i = 0; i < side; i++) {
+ for (j = 0; j < side; j++) {
+ int index = (i * side + j) * 2;
+ float a = 1.0f - i / midpoint;
+ float b = 1.0f - j / midpoint;
+ float phi, r;
+ if (a * a > b * b) {
+ r = a;
+ phi = (M_PI_4) * (b / a);
+ }
+ else {
+ r = b;
+ phi = M_PI_2 - (M_PI_4) * (a / b);
+ }
+ texels[index] = r * cos(phi);
+ texels[index + 1] = r * sin(phi);
+ }
+ }
+
+ tex = GPU_texture_create_1D_procedural(side * side, texels, NULL);
+ MEM_freeN(texels);
+ return tex;
+}
+#endif
+
+static GPUTexture *create_spiral_sample_texture(int numsaples)
+{
+ GPUTexture *tex;
+ float (*texels)[2] = MEM_mallocN(sizeof(float[2]) * numsaples, "concentric_tex");
+ const float numsaples_inv = 1.0f / numsaples;
+ int i;
+ /* arbitrary number to ensure we don't get conciding samples every circle */
+ const float spirals = 7.357;
+
+ for (i = 0; i < numsaples; i++) {
+ float r = (i + 0.5f) * numsaples_inv;
+ float phi = r * spirals * (float)(2.0 * M_PI);
+ texels[i][0] = r * cosf(phi);
+ texels[i][1] = r * sinf(phi);
+ }
+
+ tex = GPU_texture_create_1D_procedural(numsaples, (float *)texels, NULL);
+ MEM_freeN(texels);
+ return tex;
+}
+
+/* generate a new FX compositor */
+GPUFX *GPU_fx_compositor_create(void)
+{
+ GPUFX *fx = MEM_callocN(sizeof(GPUFX), "GPUFX compositor");
+
+ if (GLEW_ARB_vertex_buffer_object) {
+ glGenBuffersARB(1, &fx->vbuffer);
+ glBindBufferARB(GL_ARRAY_BUFFER_ARB, fx->vbuffer);
+ glBufferDataARB(GL_ARRAY_BUFFER_ARB, 16 * sizeof(float), NULL, GL_STATIC_DRAW);
+ glBufferSubDataARB(GL_ARRAY_BUFFER_ARB, 0, 8 * sizeof(float), fullscreencos);
+ glBufferSubDataARB(GL_ARRAY_BUFFER_ARB, 8 * sizeof(float), 8 * sizeof(float), fullscreenuvs);
+ glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
+ }
+ return fx;
+}
+
+static void cleanup_fx_dof_buffers(GPUFX *fx)
+{
+ if (fx->dof_near_coc_blurred_buffer) {
+ GPU_texture_free(fx->dof_near_coc_blurred_buffer);
+ fx->dof_near_coc_blurred_buffer = NULL;
+ }
+ if (fx->dof_near_coc_buffer) {
+ GPU_texture_free(fx->dof_near_coc_buffer);
+ fx->dof_near_coc_buffer = NULL;
+ }
+ if (fx->dof_near_coc_final_buffer) {
+ GPU_texture_free(fx->dof_near_coc_final_buffer);
+ fx->dof_near_coc_final_buffer = NULL;
+ }
+
+ if (fx->dof_half_downsampled_near) {
+ GPU_texture_free(fx->dof_half_downsampled_near);
+ fx->dof_half_downsampled_near = NULL;
+ }
+ if (fx->dof_half_downsampled_far) {
+ GPU_texture_free(fx->dof_half_downsampled_far);
+ fx->dof_half_downsampled_far = NULL;
+ }
+ if (fx->dof_nearfar_coc) {
+ GPU_texture_free(fx->dof_nearfar_coc);
+ fx->dof_nearfar_coc = NULL;
+ }
+ if (fx->dof_near_blur) {
+ GPU_texture_free(fx->dof_near_blur);
+ fx->dof_near_blur = NULL;
+ }
+ if (fx->dof_far_blur) {
+ GPU_texture_free(fx->dof_far_blur);
+ fx->dof_far_blur = NULL;
+ }
+}
+
+static void cleanup_fx_gl_data(GPUFX *fx, bool do_fbo)
+{
+ if (fx->color_buffer) {
+ GPU_framebuffer_texture_detach(fx->color_buffer);
+ GPU_texture_free(fx->color_buffer);
+ fx->color_buffer = NULL;
+ }
+
+ if (fx->color_buffer_sec) {
+ GPU_framebuffer_texture_detach(fx->color_buffer_sec);
+ GPU_texture_free(fx->color_buffer_sec);
+ fx->color_buffer_sec = NULL;
+ }
+
+ if (fx->depth_buffer) {
+ GPU_framebuffer_texture_detach(fx->depth_buffer);
+ GPU_texture_free(fx->depth_buffer);
+ fx->depth_buffer = NULL;
+ }
+
+ if (fx->depth_buffer_xray) {
+ GPU_framebuffer_texture_detach(fx->depth_buffer_xray);
+ GPU_texture_free(fx->depth_buffer_xray);
+ fx->depth_buffer_xray = NULL;
+ }
+
+ cleanup_fx_dof_buffers(fx);
+
+ if (fx->ssao_spiral_samples_tex) {
+ GPU_texture_free(fx->ssao_spiral_samples_tex);
+ fx->ssao_spiral_samples_tex = NULL;
+ }
+
+ if (fx->jitter_buffer && do_fbo) {
+ GPU_texture_free(fx->jitter_buffer);
+ fx->jitter_buffer = NULL;
+ }
+
+ if (fx->gbuffer && do_fbo) {
+ GPU_framebuffer_free(fx->gbuffer);
+ fx->gbuffer = NULL;
+ }
+}
+
+/* destroy a text compositor */
+void GPU_fx_compositor_destroy(GPUFX *fx)
+{
+ cleanup_fx_gl_data(fx, true);
+ if (GLEW_ARB_vertex_buffer_object)
+ glDeleteBuffersARB(1, &fx->vbuffer);
+ MEM_freeN(fx);
+}
+
+static GPUTexture * create_jitter_texture(void)
+{
+ float jitter [64 * 64][2];
+ int i;
+
+ for (i = 0; i < 64 * 64; i++) {
+ jitter[i][0] = 2.0f * BLI_frand() - 1.0f;
+ jitter[i][1] = 2.0f * BLI_frand() - 1.0f;
+ normalize_v2(jitter[i]);
+ }
+
+ return GPU_texture_create_2D_procedural(64, 64, &jitter[0][0], true, NULL);
+}
+
+
+bool GPU_fx_compositor_initialize_passes(
+ GPUFX *fx, const rcti *rect, const rcti *scissor_rect,
+ const GPUFXSettings *fx_settings)
+{
+ int w = BLI_rcti_size_x(rect), h = BLI_rcti_size_y(rect);
+ char err_out[256];
+ int num_passes = 0;
+ char fx_flag;
+
+ fx->effects = 0;
+
+ if (!GPU_non_power_of_two_support() || !GLEW_EXT_framebuffer_object || !GLEW_ARB_fragment_shader)
+ return false;
+
+ if (!fx_settings) {
+ cleanup_fx_gl_data(fx, true);
+ return false;
+ }
+
+ fx_flag = fx_settings->fx_flag;
+
+ /* disable effects if no options passed for them */
+ if (!fx_settings->dof) {
+ fx_flag &= ~GPU_FX_FLAG_DOF;
+ }
+ if (!fx_settings->ssao || fx_settings->ssao->samples < 1) {
+ fx_flag &= ~GPU_FX_FLAG_SSAO;
+ }
+
+ if (!fx_flag) {
+ cleanup_fx_gl_data(fx, true);
+ return false;
+ }
+
+ /* scissor is missing when drawing offscreen, in that case, dimensions match exactly. In opposite case
+ * add one to match viewport dimensions */
+ if (scissor_rect) {
+ w++, h++;
+ }
+
+ fx->num_passes = 0;
+ /* dof really needs a ping-pong buffer to work */
+ if (fx_flag & GPU_FX_FLAG_DOF)
+ num_passes++;
+
+ if (fx_flag & GPU_FX_FLAG_SSAO)
+ num_passes++;
+
+ if (!fx->gbuffer) {
+ fx->gbuffer = GPU_framebuffer_create();
+
+ if (!fx->gbuffer) {
+ return false;
+ }
+ }
+
+ /* try creating the jitter texture */
+ if (!fx->jitter_buffer)
+ fx->jitter_buffer = create_jitter_texture();
+
+ /* check if color buffers need recreation */
+ if (!fx->color_buffer || !fx->depth_buffer || w != fx->gbuffer_dim[0] || h != fx->gbuffer_dim[1]) {
+ cleanup_fx_gl_data(fx, false);
+
+ if (!(fx->color_buffer = GPU_texture_create_2D(w, h, NULL, GPU_HDR_NONE, err_out))) {
+ printf(".256%s\n", err_out);
+ cleanup_fx_gl_data(fx, true);
+ return false;
+ }
+
+ if (!(fx->depth_buffer = GPU_texture_create_depth(w, h, err_out))) {
+ printf("%.256s\n", err_out);
+ cleanup_fx_gl_data(fx, true);
+ return false;
+ }
+ }
+
+ if (fx_flag & GPU_FX_FLAG_SSAO) {
+ if (fx_settings->ssao->samples != fx->ssao_sample_count_cache || !fx->ssao_spiral_samples_tex) {
+ if (fx_settings->ssao->samples < 1)
+ fx_settings->ssao->samples = 1;
+
+ fx->ssao_sample_count_cache = fx_settings->ssao->samples;
+
+ if (fx->ssao_spiral_samples_tex) {
+ GPU_texture_free(fx->ssao_spiral_samples_tex);
+ }
+
+ fx->ssao_spiral_samples_tex = create_spiral_sample_texture(fx_settings->ssao->samples);
+ }
+ }
+ else {
+ if (fx->ssao_spiral_samples_tex) {
+ GPU_texture_free(fx->ssao_spiral_samples_tex);
+ fx->ssao_spiral_samples_tex = NULL;
+ }
+ }
+
+ /* create textures for dof effect */
+ if (fx_flag & GPU_FX_FLAG_DOF) {
+ bool dof_high_quality = (fx_settings->dof->high_quality != 0) &&
+ GPU_geometry_shader_support() && GPU_instanced_drawing_support();
+
+ /* cleanup buffers if quality setting has changed (no need to keep more buffers around than necessary ) */
+ if (dof_high_quality != fx->dof_high_quality)
+ cleanup_fx_dof_buffers(fx);
+
+ if (dof_high_quality) {
+ fx->dof_downsampled_w = w / 2;
+ fx->dof_downsampled_h = h / 2;
+
+ if (!fx->dof_half_downsampled_near || !fx->dof_nearfar_coc || !fx->dof_near_blur ||
+ !fx->dof_far_blur || !fx->dof_half_downsampled_far) {
+
+ if (!(fx->dof_half_downsampled_near = GPU_texture_create_2D(
+ fx->dof_downsampled_w, fx->dof_downsampled_h, NULL, GPU_HDR_NONE, err_out)))
+ {
+ printf("%.256s\n", err_out);
+ cleanup_fx_gl_data(fx, true);
+ return false;
+ }
+ if (!(fx->dof_half_downsampled_far = GPU_texture_create_2D(
+ fx->dof_downsampled_w, fx->dof_downsampled_h, NULL, GPU_HDR_NONE, err_out)))
+ {
+ printf("%.256s\n", err_out);
+ cleanup_fx_gl_data(fx, true);
+ return false;
+ }
+ if (!(fx->dof_nearfar_coc = GPU_texture_create_2D_procedural(
+ fx->dof_downsampled_w, fx->dof_downsampled_h, NULL, false, err_out)))
+ {
+ printf("%.256s\n", err_out);
+ cleanup_fx_gl_data(fx, true);
+ return false;
+ }
+
+
+ if (!(fx->dof_near_blur = GPU_texture_create_2D(
+ fx->dof_downsampled_w, fx->dof_downsampled_h, NULL, GPU_HDR_HALF_FLOAT, err_out)))
+ {
+ printf("%.256s\n", err_out);
+ cleanup_fx_gl_data(fx, true);
+ return false;
+ }
+
+ if (!(fx->dof_far_blur = GPU_texture_create_2D(
+ fx->dof_downsampled_w, fx->dof_downsampled_h, NULL, GPU_HDR_HALF_FLOAT, err_out)))
+ {
+ printf("%.256s\n", err_out);
+ cleanup_fx_gl_data(fx, true);
+ return false;
+ }
+ }
+ }
+ else {
+ fx->dof_downsampled_w = w / 4;
+ fx->dof_downsampled_h = h / 4;
+
+ if (!fx->dof_near_coc_buffer || !fx->dof_near_coc_blurred_buffer || !fx->dof_near_coc_final_buffer) {
+
+ if (!(fx->dof_near_coc_buffer = GPU_texture_create_2D(
+ fx->dof_downsampled_w, fx->dof_downsampled_h, NULL, GPU_HDR_NONE, err_out)))
+ {
+ printf("%.256s\n", err_out);
+ cleanup_fx_gl_data(fx, true);
+ return false;
+ }
+ if (!(fx->dof_near_coc_blurred_buffer = GPU_texture_create_2D(
+ fx->dof_downsampled_w, fx->dof_downsampled_h, NULL, GPU_HDR_NONE, err_out)))
+ {
+ printf("%.256s\n", err_out);
+ cleanup_fx_gl_data(fx, true);
+ return false;
+ }
+ if (!(fx->dof_near_coc_final_buffer = GPU_texture_create_2D(
+ fx->dof_downsampled_w, fx->dof_downsampled_h, NULL, GPU_HDR_NONE, err_out)))
+ {
+ printf("%.256s\n", err_out);
+ cleanup_fx_gl_data(fx, true);
+ return false;
+ }
+ }
+ }
+
+ fx->dof_high_quality = dof_high_quality;
+ }
+ else {
+ /* cleanup unnecessary buffers */
+ cleanup_fx_dof_buffers(fx);
+ }
+
+ /* we need to pass data between shader stages, allocate an extra color buffer */
+ if (num_passes > 1) {
+ if (!fx->color_buffer_sec) {
+ if (!(fx->color_buffer_sec = GPU_texture_create_2D(w, h, NULL, GPU_HDR_NONE, err_out))) {
+ printf(".256%s\n", err_out);
+ cleanup_fx_gl_data(fx, true);
+ return false;
+ }
+ }
+ }
+ else {
+ if (fx->color_buffer_sec) {
+ GPU_framebuffer_texture_detach(fx->color_buffer_sec);
+ GPU_texture_free(fx->color_buffer_sec);
+ fx->color_buffer_sec = NULL;
+ }
+ }
+
+ /* bind the buffers */
+
+ /* first depth buffer, because system assumes read/write buffers */
+ if (!GPU_framebuffer_texture_attach(fx->gbuffer, fx->depth_buffer, 0, err_out))
+ printf("%.256s\n", err_out);
+
+ if (!GPU_framebuffer_texture_attach(fx->gbuffer, fx->color_buffer, 0, err_out))
+ printf("%.256s\n", err_out);
+
+ if (!GPU_framebuffer_check_valid(fx->gbuffer, err_out))
+ printf("%.256s\n", err_out);
+
+ GPU_texture_bind_as_framebuffer(fx->color_buffer);
+
+ /* enable scissor test. It's needed to ensure sculpting works correctly */
+ if (scissor_rect) {
+ int w_sc = BLI_rcti_size_x(scissor_rect) + 1;
+ int h_sc = BLI_rcti_size_y(scissor_rect) + 1;
+ glPushAttrib(GL_SCISSOR_BIT);
+ glEnable(GL_SCISSOR_TEST);
+ glScissor(scissor_rect->xmin - rect->xmin, scissor_rect->ymin - rect->ymin,
+ w_sc, h_sc);
+ fx->restore_stencil = true;
+ }
+ else {
+ fx->restore_stencil = false;
+ }
+
+ fx->effects = fx_flag;
+
+ if (fx_settings)
+ fx->settings = *fx_settings;
+ fx->gbuffer_dim[0] = w;
+ fx->gbuffer_dim[1] = h;
+
+ fx->num_passes = num_passes;
+
+ return true;
+}
+
+static void gpu_fx_bind_render_target(int *passes_left, GPUFX *fx, struct GPUOffScreen *ofs, GPUTexture *target)
+{
+ if ((*passes_left)-- == 1) {
+ GPU_framebuffer_texture_unbind(fx->gbuffer, NULL);
+ if (ofs) {
+ GPU_offscreen_bind(ofs, false);
+ }
+ else
+ GPU_framebuffer_restore();
+ }
+ else {
+ /* bind the ping buffer to the color buffer */
+ GPU_framebuffer_texture_attach(fx->gbuffer, target, 0, NULL);
+ }
+}
+
+void GPU_fx_compositor_setup_XRay_pass(GPUFX *fx, bool do_xray)
+{
+ char err_out[256];
+
+ if (do_xray) {
+ if (!fx->depth_buffer_xray && !(fx->depth_buffer_xray = GPU_texture_create_depth(fx->gbuffer_dim[0], fx->gbuffer_dim[1], err_out))) {
+ printf("%.256s\n", err_out);
+ cleanup_fx_gl_data(fx, true);
+ return;
+ }
+ }
+ else {
+ if (fx->depth_buffer_xray) {
+ GPU_framebuffer_texture_detach(fx->depth_buffer_xray);
+ GPU_texture_free(fx->depth_buffer_xray);
+ fx->depth_buffer_xray = NULL;
+ }
+ return;
+ }
+
+ GPU_framebuffer_texture_detach(fx->depth_buffer);
+
+ /* first depth buffer, because system assumes read/write buffers */
+ if (!GPU_framebuffer_texture_attach(fx->gbuffer, fx->depth_buffer_xray, 0, err_out))
+ printf("%.256s\n", err_out);
+}
+
+
+void GPU_fx_compositor_XRay_resolve(GPUFX *fx)
+{
+ GPUShader *depth_resolve_shader;
+ GPU_framebuffer_texture_detach(fx->depth_buffer_xray);
+
+ /* attach regular framebuffer */
+ GPU_framebuffer_texture_attach(fx->gbuffer, fx->depth_buffer, 0, NULL);
+
+ /* full screen quad where we will always write to depth buffer */
+ glPushAttrib(GL_DEPTH_BUFFER_BIT | GL_SCISSOR_BIT);
+ glDepthFunc(GL_ALWAYS);
+ /* disable scissor from sculpt if any */
+ glDisable(GL_SCISSOR_TEST);
+ /* disable writing to color buffer, it's depth only pass */
+ glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
+
+ /* set up quad buffer */
+ glBindBufferARB(GL_ARRAY_BUFFER_ARB, fx->vbuffer);
+ glVertexPointer(2, GL_FLOAT, 0, NULL);
+ glTexCoordPointer(2, GL_FLOAT, 0, ((GLubyte *)NULL + 8 * sizeof(float)));
+ glEnableClientState(GL_VERTEX_ARRAY);
+ glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+
+ depth_resolve_shader = GPU_shader_get_builtin_fx_shader(GPU_SHADER_FX_DEPTH_RESOLVE, false);
+
+ if (depth_resolve_shader) {
+ int depth_uniform;
+
+ depth_uniform = GPU_shader_get_uniform(depth_resolve_shader, "depthbuffer");
+
+ GPU_shader_bind(depth_resolve_shader);
+
+ GPU_texture_bind(fx->depth_buffer_xray, 0);
+ GPU_texture_filter_mode(fx->depth_buffer_xray, false, true);
+ GPU_shader_uniform_texture(depth_resolve_shader, depth_uniform, fx->depth_buffer_xray);
+
+ /* draw */
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+
+ /* disable bindings */
+ GPU_texture_filter_mode(fx->depth_buffer_xray, true, false);
+ GPU_texture_unbind(fx->depth_buffer_xray);
+
+ GPU_shader_unbind();
+ }
+
+ glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
+
+ glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
+ glDisableClientState(GL_VERTEX_ARRAY);
+ glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+
+ glPopAttrib();
+}
+
+
+bool GPU_fx_do_composite_pass(GPUFX *fx, float projmat[4][4], bool is_persp, struct Scene *scene, struct GPUOffScreen *ofs)
+{
+ GPUTexture *src, *target;
+ int numslots = 0;
+ float invproj[4][4];
+ int i;
+ float dfdyfac[2];
+ /* number of passes left. when there are no more passes, the result is passed to the frambuffer */
+ int passes_left = fx->num_passes;
+ /* view vectors for the corners of the view frustum. Can be used to recreate the world space position easily */
+ float viewvecs[3][4] = {
+ {-1.0f, -1.0f, -1.0f, 1.0f},
+ {1.0f, -1.0f, -1.0f, 1.0f},
+ {-1.0f, 1.0f, -1.0f, 1.0f}
+ };
+
+ if (fx->effects == 0)
+ return false;
+
+ GPU_get_dfdy_factors(dfdyfac);
+ /* first, unbind the render-to-texture framebuffer */
+ GPU_framebuffer_texture_detach(fx->color_buffer);
+ GPU_framebuffer_texture_detach(fx->depth_buffer);
+
+ if (fx->restore_stencil)
+ glPopAttrib();
+
+ src = fx->color_buffer;
+ target = fx->color_buffer_sec;
+
+ /* set up quad buffer */
+ glBindBufferARB(GL_ARRAY_BUFFER_ARB, fx->vbuffer);
+ glVertexPointer(2, GL_FLOAT, 0, NULL);
+ glTexCoordPointer(2, GL_FLOAT, 0, ((GLubyte *)NULL + 8 * sizeof(float)));
+ glEnableClientState(GL_VERTEX_ARRAY);
+ glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+
+ /* full screen FX pass */
+
+ /* invert the view matrix */
+ invert_m4_m4(invproj, projmat);
+
+ /* convert the view vectors to view space */
+ for (i = 0; i < 3; i++) {
+ mul_m4_v4(invproj, viewvecs[i]);
+ /* normalized trick see http://www.derschmale.com/2014/01/26/reconstructing-positions-from-the-depth-buffer */
+ mul_v3_fl(viewvecs[i], 1.0f / viewvecs[i][3]);
+ if (is_persp)
+ mul_v3_fl(viewvecs[i], 1.0f / viewvecs[i][2]);
+ viewvecs[i][3] = 1.0;
+ }
+
+ /* we need to store the differences */
+ viewvecs[1][0] -= viewvecs[0][0];
+ viewvecs[1][1] = viewvecs[2][1] - viewvecs[0][1];
+
+ /* calculate a depth offset as well */
+ if (!is_persp) {
+ float vec_far[] = {-1.0f, -1.0f, 1.0f, 1.0f};
+ mul_m4_v4(invproj, vec_far);
+ mul_v3_fl(vec_far, 1.0f / vec_far[3]);
+ viewvecs[1][2] = vec_far[2] - viewvecs[0][2];
+ }
+
+ /* set invalid color in case shader fails */
+ glColor3f(1.0, 0.0, 1.0);
+ glDisable(GL_DEPTH_TEST);
+
+ /* ssao pass */
+ if (fx->effects & GPU_FX_FLAG_SSAO) {
+ GPUShader *ssao_shader;
+ ssao_shader = GPU_shader_get_builtin_fx_shader(GPU_SHADER_FX_SSAO, is_persp);
+ if (ssao_shader) {
+ const GPUSSAOSettings *fx_ssao = fx->settings.ssao;
+ int color_uniform, depth_uniform;
+ int ssao_uniform, ssao_color_uniform, viewvecs_uniform, ssao_sample_params_uniform;
+ int ssao_jitter_uniform, ssao_concentric_tex;
+ float ssao_params[4] = {fx_ssao->distance_max, fx_ssao->factor, fx_ssao->attenuation, 0.0f};
+ float sample_params[3];
+
+ sample_params[0] = fx->ssao_sample_count_cache;
+ /* multiplier so we tile the random texture on screen */
+ sample_params[1] = fx->gbuffer_dim[0] / 64.0;
+ sample_params[2] = fx->gbuffer_dim[1] / 64.0;
+
+ ssao_params[3] = (passes_left == 1 && !ofs) ? dfdyfac[0] : dfdyfac[1];
+
+ ssao_uniform = GPU_shader_get_uniform(ssao_shader, "ssao_params");
+ ssao_color_uniform = GPU_shader_get_uniform(ssao_shader, "ssao_color");
+ color_uniform = GPU_shader_get_uniform(ssao_shader, "colorbuffer");
+ depth_uniform = GPU_shader_get_uniform(ssao_shader, "depthbuffer");
+ viewvecs_uniform = GPU_shader_get_uniform(ssao_shader, "viewvecs");
+ ssao_sample_params_uniform = GPU_shader_get_uniform(ssao_shader, "ssao_sample_params");
+ ssao_concentric_tex = GPU_shader_get_uniform(ssao_shader, "ssao_concentric_tex");
+ ssao_jitter_uniform = GPU_shader_get_uniform(ssao_shader, "jitter_tex");
+
+ GPU_shader_bind(ssao_shader);
+
+ GPU_shader_uniform_vector(ssao_shader, ssao_uniform, 4, 1, ssao_params);
+ GPU_shader_uniform_vector(ssao_shader, ssao_color_uniform, 4, 1, fx_ssao->color);
+ GPU_shader_uniform_vector(ssao_shader, viewvecs_uniform, 4, 3, viewvecs[0]);
+ GPU_shader_uniform_vector(ssao_shader, ssao_sample_params_uniform, 3, 1, sample_params);
+
+ GPU_texture_bind(src, numslots++);
+ GPU_shader_uniform_texture(ssao_shader, color_uniform, src);
+
+ GPU_texture_bind(fx->depth_buffer, numslots++);
+ GPU_texture_filter_mode(fx->depth_buffer, false, true);
+ GPU_shader_uniform_texture(ssao_shader, depth_uniform, fx->depth_buffer);
+
+ GPU_texture_bind(fx->jitter_buffer, numslots++);
+ GPU_shader_uniform_texture(ssao_shader, ssao_jitter_uniform, fx->jitter_buffer);
+
+ GPU_texture_bind(fx->ssao_spiral_samples_tex, numslots++);
+ GPU_shader_uniform_texture(ssao_shader, ssao_concentric_tex, fx->ssao_spiral_samples_tex);
+
+ /* draw */
+ gpu_fx_bind_render_target(&passes_left, fx, ofs, target);
+
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+
+ /* disable bindings */
+ GPU_texture_unbind(src);
+ GPU_texture_filter_mode(fx->depth_buffer, true, false);
+ GPU_texture_unbind(fx->depth_buffer);
+ GPU_texture_unbind(fx->jitter_buffer);
+ GPU_texture_unbind(fx->ssao_spiral_samples_tex);
+
+ /* may not be attached, in that case this just returns */
+ if (target) {
+ GPU_framebuffer_texture_detach(target);
+ if (ofs) {
+ GPU_offscreen_bind(ofs, false);
+ }
+ else {
+ GPU_framebuffer_restore();
+ }
+ }
+
+ /* swap here, after src/target have been unbound */
+ SWAP(GPUTexture *, target, src);
+ numslots = 0;
+ }
+ }
+
+ /* second pass, dof */
+ if (fx->effects & GPU_FX_FLAG_DOF) {
+ const GPUDOFSettings *fx_dof = fx->settings.dof;
+ float dof_params[4];
+ float scale = scene->unit.system ? scene->unit.scale_length : 1.0f;
+ /* this is factor that converts to the scene scale. focal length and sensor are expressed in mm
+ * unit.scale_length is how many meters per blender unit we have. We want to convert to blender units though
+ * because the shader reads coordinates in world space, which is in blender units. */
+ float scale_camera = 0.001f / scale;
+ /* we want radius here for the aperture number */
+ float aperture = 0.5f * scale_camera * fx_dof->focal_length / fx_dof->fstop;
+
+ dof_params[0] = aperture * fabsf(scale_camera * fx_dof->focal_length / ((fx_dof->focus_distance / scale) - scale_camera * fx_dof->focal_length));
+ dof_params[1] = fx_dof->focus_distance / scale;
+ dof_params[2] = fx->gbuffer_dim[0] / (scale_camera * fx_dof->sensor);
+ dof_params[3] = fx_dof->num_blades;
+
+ if (fx->dof_high_quality) {
+ GPUShader *dof_shader_pass1, *dof_shader_pass2, *dof_shader_pass3;
+
+ /* custom shaders close to the effect described in CryEngine 3 Graphics Gems */
+ dof_shader_pass1 = GPU_shader_get_builtin_fx_shader(GPU_SHADER_FX_DEPTH_OF_FIELD_HQ_PASS_ONE, is_persp);
+ dof_shader_pass2 = GPU_shader_get_builtin_fx_shader(GPU_SHADER_FX_DEPTH_OF_FIELD_HQ_PASS_TWO, is_persp);
+ dof_shader_pass3 = GPU_shader_get_builtin_fx_shader(GPU_SHADER_FX_DEPTH_OF_FIELD_HQ_PASS_THREE, is_persp);
+
+ /* error occured, restore framebuffers and return */
+ if (!(dof_shader_pass1 && dof_shader_pass2 && dof_shader_pass3)) {
+ GPU_framebuffer_texture_unbind(fx->gbuffer, NULL);
+ GPU_framebuffer_restore();
+ glDisableClientState(GL_VERTEX_ARRAY);
+ glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+
+ GPU_shader_unbind();
+ glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
+ return false;
+ }
+
+ /* pass first, downsample the color buffer to near/far targets and calculate coc texture */
+ {
+ int depth_uniform, dof_uniform;
+ int viewvecs_uniform;
+ int invrendertargetdim_uniform, color_uniform;
+
+ float invrendertargetdim[2] = {1.0f / fx->dof_downsampled_w, 1.0f / fx->dof_downsampled_h};
+
+ invrendertargetdim_uniform = GPU_shader_get_uniform(dof_shader_pass1, "invrendertargetdim");
+ color_uniform = GPU_shader_get_uniform(dof_shader_pass1, "colorbuffer");
+ dof_uniform = GPU_shader_get_uniform(dof_shader_pass1, "dof_params");
+ invrendertargetdim_uniform = GPU_shader_get_uniform(dof_shader_pass1, "invrendertargetdim");
+ depth_uniform = GPU_shader_get_uniform(dof_shader_pass1, "depthbuffer");
+ viewvecs_uniform = GPU_shader_get_uniform(dof_shader_pass1, "viewvecs");
+
+ GPU_shader_bind(dof_shader_pass1);
+
+ GPU_shader_uniform_vector(dof_shader_pass1, dof_uniform, 4, 1, dof_params);
+ GPU_shader_uniform_vector(dof_shader_pass1, invrendertargetdim_uniform, 2, 1, invrendertargetdim);
+ GPU_shader_uniform_vector(dof_shader_pass1, viewvecs_uniform, 4, 3, viewvecs[0]);
+
+ GPU_shader_uniform_vector(dof_shader_pass1, invrendertargetdim_uniform, 2, 1, invrendertargetdim);
+
+ GPU_texture_bind(fx->depth_buffer, numslots++);
+ GPU_texture_filter_mode(fx->depth_buffer, false, false);
+ GPU_shader_uniform_texture(dof_shader_pass1, depth_uniform, fx->depth_buffer);
+
+ GPU_texture_bind(src, numslots++);
+ /* disable filtering for the texture so custom downsample can do the right thing */
+ GPU_texture_filter_mode(src, false, false);
+ GPU_shader_uniform_texture(dof_shader_pass2, color_uniform, src);
+
+ /* target is the downsampled coc buffer */
+ GPU_framebuffer_texture_attach(fx->gbuffer, fx->dof_half_downsampled_near, 0, NULL);
+ GPU_framebuffer_texture_attach(fx->gbuffer, fx->dof_half_downsampled_far, 1, NULL);
+ GPU_framebuffer_texture_attach(fx->gbuffer, fx->dof_nearfar_coc, 2, NULL);
+ /* binding takes care of setting the viewport to the downsampled size */
+ GPU_framebuffer_slots_bind(fx->gbuffer, 0);
+
+ GPU_framebuffer_check_valid(fx->gbuffer, NULL);
+
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+ /* disable bindings */
+ GPU_texture_filter_mode(src, false, true);
+ GPU_texture_unbind(src);
+ GPU_texture_filter_mode(fx->depth_buffer, true, false);
+ GPU_texture_unbind(fx->depth_buffer);
+
+ GPU_framebuffer_texture_detach(fx->dof_half_downsampled_near);
+ GPU_framebuffer_texture_detach(fx->dof_half_downsampled_far);
+ GPU_framebuffer_texture_detach(fx->dof_nearfar_coc);
+ GPU_framebuffer_texture_unbind(fx->gbuffer, fx->dof_half_downsampled_near);
+
+ numslots = 0;
+ }
+
+ /* second pass, shoot quads for every pixel in the downsampled buffers, scaling according
+ * to circle of confusion */
+ {
+ int rendertargetdim_uniform, coc_uniform, color_uniform, select_uniform, dof_uniform;
+ int rendertargetdim[2] = {fx->dof_downsampled_w, fx->dof_downsampled_h};
+ float selection[2] = {0.0f, 1.0f};
+
+ rendertargetdim_uniform = GPU_shader_get_uniform(dof_shader_pass2, "rendertargetdim");
+
+ color_uniform = GPU_shader_get_uniform(dof_shader_pass2, "colorbuffer");
+ coc_uniform = GPU_shader_get_uniform(dof_shader_pass2, "cocbuffer");
+ select_uniform = GPU_shader_get_uniform(dof_shader_pass2, "layerselection");
+ dof_uniform = GPU_shader_get_uniform(dof_shader_pass2, "dof_params");
+
+ GPU_shader_bind(dof_shader_pass2);
+
+ GPU_shader_uniform_vector(dof_shader_pass2, dof_uniform, 4, 1, dof_params);
+ GPU_shader_uniform_vector_int(dof_shader_pass2, rendertargetdim_uniform, 2, 1, rendertargetdim);
+ GPU_shader_uniform_vector(dof_shader_pass2, select_uniform, 2, 1, selection);
+
+ GPU_texture_bind(fx->dof_nearfar_coc, numslots++);
+ GPU_shader_uniform_texture(dof_shader_pass2, coc_uniform, fx->dof_nearfar_coc);
+
+ GPU_texture_bind(fx->dof_half_downsampled_far, numslots++);
+ GPU_texture_bind(fx->dof_half_downsampled_near, numslots++);
+ GPU_shader_uniform_texture(dof_shader_pass2, color_uniform, fx->dof_half_downsampled_far);
+ GPU_texture_filter_mode(fx->dof_half_downsampled_far, false, false);
+
+ /* target is the downsampled coc buffer */
+ GPU_framebuffer_texture_attach(fx->gbuffer, fx->dof_far_blur, 0, NULL);
+ GPU_texture_bind_as_framebuffer(fx->dof_far_blur);
+
+ glDisable(GL_DEPTH_TEST);
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_ONE, GL_ONE);
+ /* have to clear the buffer unfortunately */
+ glClearColor(0.0, 0.0, 0.0, 0.0);
+ glClear(GL_COLOR_BUFFER_BIT);
+ /* the draw call we all waited for, draw a point per pixel, scaled per circle of confusion */
+ glDrawArraysInstancedARB(GL_POINTS, 0, 1, fx->dof_downsampled_w * fx->dof_downsampled_h);
+
+ GPU_texture_unbind(fx->dof_half_downsampled_far);
+ GPU_framebuffer_texture_detach(fx->dof_far_blur);
+
+ GPU_shader_uniform_texture(dof_shader_pass2, color_uniform, fx->dof_half_downsampled_near);
+ GPU_texture_filter_mode(fx->dof_half_downsampled_near, false, false);
+
+ selection[0] = 1.0f;
+ selection[1] = 0.0f;
+
+ GPU_shader_uniform_vector(dof_shader_pass2, select_uniform, 2, 1, selection);
+
+ GPU_framebuffer_texture_attach(fx->gbuffer, fx->dof_near_blur, 0, NULL);
+ /* have to clear the buffer unfortunately */
+ glClear(GL_COLOR_BUFFER_BIT);
+ /* the draw call we all waited for, draw a point per pixel, scaled per circle of confusion */
+ glDrawArraysInstancedARB(GL_POINTS, 0, 1, fx->dof_downsampled_w * fx->dof_downsampled_h);
+
+ /* disable bindings */
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glDisable(GL_BLEND);
+
+ GPU_framebuffer_texture_detach(fx->dof_near_blur);
+
+ GPU_texture_unbind(fx->dof_half_downsampled_near);
+ GPU_texture_unbind(fx->dof_nearfar_coc);
+
+ GPU_framebuffer_texture_unbind(fx->gbuffer, fx->dof_far_blur);
+ }
+
+ /* third pass, accumulate the near/far blur fields */
+ {
+ int invrendertargetdim_uniform, near_uniform, color_uniform;
+ int dof_uniform, far_uniform, viewvecs_uniform, depth_uniform;
+
+ float invrendertargetdim[2] = {1.0f / fx->dof_downsampled_w, 1.0f / fx->dof_downsampled_h};
+
+ dof_uniform = GPU_shader_get_uniform(dof_shader_pass3, "dof_params");
+ invrendertargetdim_uniform = GPU_shader_get_uniform(dof_shader_pass3, "invrendertargetdim");
+ color_uniform = GPU_shader_get_uniform(dof_shader_pass3, "colorbuffer");
+ far_uniform = GPU_shader_get_uniform(dof_shader_pass3, "farbuffer");
+ near_uniform = GPU_shader_get_uniform(dof_shader_pass3, "nearbuffer");
+ viewvecs_uniform = GPU_shader_get_uniform(dof_shader_pass3, "viewvecs");
+ depth_uniform = GPU_shader_get_uniform(dof_shader_pass3, "depthbuffer");
+
+ GPU_shader_bind(dof_shader_pass3);
+
+ GPU_shader_uniform_vector(dof_shader_pass3, dof_uniform, 4, 1, dof_params);
+
+ GPU_shader_uniform_vector(dof_shader_pass3, invrendertargetdim_uniform, 2, 1, invrendertargetdim);
+ GPU_shader_uniform_vector(dof_shader_pass3, viewvecs_uniform, 4, 3, viewvecs[0]);
+
+ GPU_texture_bind(fx->dof_near_blur, numslots++);
+ GPU_shader_uniform_texture(dof_shader_pass3, near_uniform, fx->dof_near_blur);
+ GPU_texture_filter_mode(fx->dof_near_blur, false, true);
+
+ GPU_texture_bind(fx->dof_far_blur, numslots++);
+ GPU_shader_uniform_texture(dof_shader_pass3, far_uniform, fx->dof_far_blur);
+ GPU_texture_filter_mode(fx->dof_far_blur, false, true);
+
+ GPU_texture_bind(fx->depth_buffer, numslots++);
+ GPU_texture_filter_mode(fx->depth_buffer, false, false);
+ GPU_shader_uniform_texture(dof_shader_pass3, depth_uniform, fx->depth_buffer);
+
+ GPU_texture_bind(src, numslots++);
+ GPU_shader_uniform_texture(dof_shader_pass3, color_uniform, src);
+
+ /* if this is the last pass, prepare for rendering on the frambuffer */
+ gpu_fx_bind_render_target(&passes_left, fx, ofs, target);
+
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+
+ /* disable bindings */
+ GPU_texture_unbind(fx->dof_near_blur);
+ GPU_texture_unbind(fx->dof_far_blur);
+ GPU_texture_unbind(src);
+ GPU_texture_filter_mode(fx->depth_buffer, true, false);
+ GPU_texture_unbind(fx->depth_buffer);
+
+ /* may not be attached, in that case this just returns */
+ if (target) {
+ GPU_framebuffer_texture_detach(target);
+ if (ofs) {
+ GPU_offscreen_bind(ofs, false);
+ }
+ else {
+ GPU_framebuffer_restore();
+ }
+ }
+
+ numslots = 0;
+ }
+ }
+ else {
+ GPUShader *dof_shader_pass1, *dof_shader_pass2, *dof_shader_pass3, *dof_shader_pass4, *dof_shader_pass5;
+
+ /* DOF effect has many passes but most of them are performed on a texture whose dimensions are 4 times less than the original
+ * (16 times lower than original screen resolution). Technique used is not very exact but should be fast enough and is based
+ * on "Practical Post-Process Depth of Field" see http://http.developer.nvidia.com/GPUGems3/gpugems3_ch28.html */
+ dof_shader_pass1 = GPU_shader_get_builtin_fx_shader(GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_ONE, is_persp);
+ dof_shader_pass2 = GPU_shader_get_builtin_fx_shader(GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_TWO, is_persp);
+ dof_shader_pass3 = GPU_shader_get_builtin_fx_shader(GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_THREE, is_persp);
+ dof_shader_pass4 = GPU_shader_get_builtin_fx_shader(GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_FOUR, is_persp);
+ dof_shader_pass5 = GPU_shader_get_builtin_fx_shader(GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_FIVE, is_persp);
+
+ /* error occured, restore framebuffers and return */
+ if (!(dof_shader_pass1 && dof_shader_pass2 && dof_shader_pass3 && dof_shader_pass4 && dof_shader_pass5)) {
+ GPU_framebuffer_texture_unbind(fx->gbuffer, NULL);
+ GPU_framebuffer_restore();
+ glDisableClientState(GL_VERTEX_ARRAY);
+ glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+
+ GPU_shader_unbind();
+ glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
+ return false;
+ }
+
+ /* pass first, first level of blur in low res buffer */
+ {
+ int invrendertargetdim_uniform, color_uniform, depth_uniform, dof_uniform;
+ int viewvecs_uniform;
+
+ float invrendertargetdim[2] = {1.0f / fx->gbuffer_dim[0], 1.0f / fx->gbuffer_dim[1]};
+
+ dof_uniform = GPU_shader_get_uniform(dof_shader_pass1, "dof_params");
+ invrendertargetdim_uniform = GPU_shader_get_uniform(dof_shader_pass1, "invrendertargetdim");
+ color_uniform = GPU_shader_get_uniform(dof_shader_pass1, "colorbuffer");
+ depth_uniform = GPU_shader_get_uniform(dof_shader_pass1, "depthbuffer");
+ viewvecs_uniform = GPU_shader_get_uniform(dof_shader_pass1, "viewvecs");
+
+ GPU_shader_bind(dof_shader_pass1);
+
+ GPU_shader_uniform_vector(dof_shader_pass1, dof_uniform, 4, 1, dof_params);
+ GPU_shader_uniform_vector(dof_shader_pass1, invrendertargetdim_uniform, 2, 1, invrendertargetdim);
+ GPU_shader_uniform_vector(dof_shader_pass1, viewvecs_uniform, 4, 3, viewvecs[0]);
+
+ GPU_texture_bind(src, numslots++);
+ GPU_shader_uniform_texture(dof_shader_pass1, color_uniform, src);
+
+ GPU_texture_bind(fx->depth_buffer, numslots++);
+ GPU_texture_filter_mode(fx->depth_buffer, false, true);
+ GPU_shader_uniform_texture(dof_shader_pass1, depth_uniform, fx->depth_buffer);
+
+ /* target is the downsampled coc buffer */
+ GPU_framebuffer_texture_attach(fx->gbuffer, fx->dof_near_coc_buffer, 0, NULL);
+ /* binding takes care of setting the viewport to the downsampled size */
+ GPU_texture_bind_as_framebuffer(fx->dof_near_coc_buffer);
+
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+ /* disable bindings */
+ GPU_texture_unbind(src);
+ GPU_texture_filter_mode(fx->depth_buffer, true, false);
+ GPU_texture_unbind(fx->depth_buffer);
+
+ GPU_framebuffer_texture_detach(fx->dof_near_coc_buffer);
+ numslots = 0;
+ }
+
+ /* second pass, gaussian blur the downsampled image */
+ {
+ int invrendertargetdim_uniform, color_uniform, depth_uniform, dof_uniform;
+ int viewvecs_uniform;
+ float invrendertargetdim[2] = {1.0f / GPU_texture_opengl_width(fx->dof_near_coc_blurred_buffer),
+ 1.0f / GPU_texture_opengl_height(fx->dof_near_coc_blurred_buffer)};
+ float tmp = invrendertargetdim[0];
+ invrendertargetdim[0] = 0.0f;
+
+ dof_params[2] = GPU_texture_opengl_width(fx->dof_near_coc_blurred_buffer) / (scale_camera * fx_dof->sensor);
+
+ dof_uniform = GPU_shader_get_uniform(dof_shader_pass2, "dof_params");
+ invrendertargetdim_uniform = GPU_shader_get_uniform(dof_shader_pass2, "invrendertargetdim");
+ color_uniform = GPU_shader_get_uniform(dof_shader_pass2, "colorbuffer");
+ depth_uniform = GPU_shader_get_uniform(dof_shader_pass2, "depthbuffer");
+ viewvecs_uniform = GPU_shader_get_uniform(dof_shader_pass2, "viewvecs");
+
+ /* Blurring vertically */
+ GPU_shader_bind(dof_shader_pass2);
+
+ GPU_shader_uniform_vector(dof_shader_pass2, dof_uniform, 4, 1, dof_params);
+ GPU_shader_uniform_vector(dof_shader_pass2, invrendertargetdim_uniform, 2, 1, invrendertargetdim);
+ GPU_shader_uniform_vector(dof_shader_pass2, viewvecs_uniform, 4, 3, viewvecs[0]);
+
+ GPU_texture_bind(fx->depth_buffer, numslots++);
+ GPU_texture_filter_mode(fx->depth_buffer, false, true);
+ GPU_shader_uniform_texture(dof_shader_pass2, depth_uniform, fx->depth_buffer);
+
+ GPU_texture_bind(fx->dof_near_coc_buffer, numslots++);
+ GPU_shader_uniform_texture(dof_shader_pass2, color_uniform, fx->dof_near_coc_buffer);
+
+ /* use final buffer as a temp here */
+ GPU_framebuffer_texture_attach(fx->gbuffer, fx->dof_near_coc_final_buffer, 0, NULL);
+
+ /* Drawing quad */
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+
+ /* *unbind/detach */
+ GPU_texture_unbind(fx->dof_near_coc_buffer);
+ GPU_framebuffer_texture_detach(fx->dof_near_coc_final_buffer);
+
+ /* Blurring horizontally */
+ invrendertargetdim[0] = tmp;
+ invrendertargetdim[1] = 0.0f;
+ GPU_shader_uniform_vector(dof_shader_pass2, invrendertargetdim_uniform, 2, 1, invrendertargetdim);
+
+ GPU_texture_bind(fx->dof_near_coc_final_buffer, numslots++);
+ GPU_shader_uniform_texture(dof_shader_pass2, color_uniform, fx->dof_near_coc_final_buffer);
+
+ GPU_framebuffer_texture_attach(fx->gbuffer, fx->dof_near_coc_blurred_buffer, 0, NULL);
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+
+ /* *unbind/detach */
+ GPU_texture_filter_mode(fx->depth_buffer, true, false);
+ GPU_texture_unbind(fx->depth_buffer);
+
+ GPU_texture_unbind(fx->dof_near_coc_final_buffer);
+ GPU_framebuffer_texture_detach(fx->dof_near_coc_blurred_buffer);
+
+ dof_params[2] = fx->gbuffer_dim[0] / (scale_camera * fx_dof->sensor);
+
+ numslots = 0;
+ }
+
+ /* third pass, calculate near coc */
+ {
+ int near_coc_downsampled, near_coc_blurred;
+
+ near_coc_downsampled = GPU_shader_get_uniform(dof_shader_pass3, "colorbuffer");
+ near_coc_blurred = GPU_shader_get_uniform(dof_shader_pass3, "blurredcolorbuffer");
+
+ GPU_shader_bind(dof_shader_pass3);
+
+ GPU_texture_bind(fx->dof_near_coc_buffer, numslots++);
+ GPU_shader_uniform_texture(dof_shader_pass3, near_coc_downsampled, fx->dof_near_coc_buffer);
+
+ GPU_texture_bind(fx->dof_near_coc_blurred_buffer, numslots++);
+ GPU_shader_uniform_texture(dof_shader_pass3, near_coc_blurred, fx->dof_near_coc_blurred_buffer);
+
+ GPU_framebuffer_texture_attach(fx->gbuffer, fx->dof_near_coc_final_buffer, 0, NULL);
+
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+ /* disable bindings */
+ GPU_texture_unbind(fx->dof_near_coc_buffer);
+ GPU_texture_unbind(fx->dof_near_coc_blurred_buffer);
+
+ /* unbinding here restores the size to the original */
+ GPU_framebuffer_texture_detach(fx->dof_near_coc_final_buffer);
+
+ numslots = 0;
+ }
+
+ /* fourth pass blur final coc once to eliminate discontinuities */
+ {
+ int near_coc_downsampled;
+ int invrendertargetdim_uniform;
+ float invrendertargetdim[2] = {1.0f / GPU_texture_opengl_width(fx->dof_near_coc_blurred_buffer),
+ 1.0f / GPU_texture_opengl_height(fx->dof_near_coc_blurred_buffer)};
+
+ near_coc_downsampled = GPU_shader_get_uniform(dof_shader_pass4, "colorbuffer");
+ invrendertargetdim_uniform = GPU_shader_get_uniform(dof_shader_pass4, "invrendertargetdim");
+
+ GPU_shader_bind(dof_shader_pass4);
+
+ GPU_texture_bind(fx->dof_near_coc_final_buffer, numslots++);
+ GPU_shader_uniform_texture(dof_shader_pass4, near_coc_downsampled, fx->dof_near_coc_final_buffer);
+ GPU_shader_uniform_vector(dof_shader_pass4, invrendertargetdim_uniform, 2, 1, invrendertargetdim);
+
+ GPU_framebuffer_texture_attach(fx->gbuffer, fx->dof_near_coc_buffer, 0, NULL);
+
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+ /* disable bindings */
+ GPU_texture_unbind(fx->dof_near_coc_final_buffer);
+
+ /* unbinding here restores the size to the original */
+ GPU_framebuffer_texture_unbind(fx->gbuffer, fx->dof_near_coc_buffer);
+ GPU_framebuffer_texture_detach(fx->dof_near_coc_buffer);
+
+ numslots = 0;
+ }
+
+ /* final pass, merge blurred layers according to final calculated coc */
+ {
+ int medium_blurred_uniform, high_blurred_uniform, original_uniform, depth_uniform, dof_uniform;
+ int invrendertargetdim_uniform, viewvecs_uniform;
+ float invrendertargetdim[2] = {1.0f / fx->gbuffer_dim[0], 1.0f / fx->gbuffer_dim[1]};
+
+ medium_blurred_uniform = GPU_shader_get_uniform(dof_shader_pass5, "mblurredcolorbuffer");
+ high_blurred_uniform = GPU_shader_get_uniform(dof_shader_pass5, "blurredcolorbuffer");
+ dof_uniform = GPU_shader_get_uniform(dof_shader_pass5, "dof_params");
+ invrendertargetdim_uniform = GPU_shader_get_uniform(dof_shader_pass5, "invrendertargetdim");
+ original_uniform = GPU_shader_get_uniform(dof_shader_pass5, "colorbuffer");
+ depth_uniform = GPU_shader_get_uniform(dof_shader_pass5, "depthbuffer");
+ viewvecs_uniform = GPU_shader_get_uniform(dof_shader_pass5, "viewvecs");
+
+ GPU_shader_bind(dof_shader_pass5);
+
+ GPU_shader_uniform_vector(dof_shader_pass5, dof_uniform, 4, 1, dof_params);
+ GPU_shader_uniform_vector(dof_shader_pass5, invrendertargetdim_uniform, 2, 1, invrendertargetdim);
+ GPU_shader_uniform_vector(dof_shader_pass5, viewvecs_uniform, 4, 3, viewvecs[0]);
+
+ GPU_texture_bind(src, numslots++);
+ GPU_shader_uniform_texture(dof_shader_pass5, original_uniform, src);
+
+ GPU_texture_bind(fx->dof_near_coc_blurred_buffer, numslots++);
+ GPU_shader_uniform_texture(dof_shader_pass5, high_blurred_uniform, fx->dof_near_coc_blurred_buffer);
+
+ GPU_texture_bind(fx->dof_near_coc_buffer, numslots++);
+ GPU_shader_uniform_texture(dof_shader_pass5, medium_blurred_uniform, fx->dof_near_coc_buffer);
+
+ GPU_texture_bind(fx->depth_buffer, numslots++);
+ GPU_texture_filter_mode(fx->depth_buffer, false, true);
+ GPU_shader_uniform_texture(dof_shader_pass5, depth_uniform, fx->depth_buffer);
+
+ /* if this is the last pass, prepare for rendering on the frambuffer */
+ gpu_fx_bind_render_target(&passes_left, fx, ofs, target);
+
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+ /* disable bindings */
+ GPU_texture_unbind(fx->dof_near_coc_buffer);
+ GPU_texture_unbind(fx->dof_near_coc_blurred_buffer);
+ GPU_texture_unbind(src);
+ GPU_texture_filter_mode(fx->depth_buffer, true, false);
+ GPU_texture_unbind(fx->depth_buffer);
+
+ /* may not be attached, in that case this just returns */
+ if (target) {
+ GPU_framebuffer_texture_detach(target);
+ if (ofs) {
+ GPU_offscreen_bind(ofs, false);
+ }
+ else {
+ GPU_framebuffer_restore();
+ }
+ }
+
+ SWAP(GPUTexture *, target, src);
+ numslots = 0;
+ }
+ }
+ }
+
+ glDisableClientState(GL_VERTEX_ARRAY);
+ glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+ glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
+
+ GPU_shader_unbind();
+
+ return true;
+}
+
+void GPU_fx_compositor_init_dof_settings(GPUDOFSettings *fx_dof)
+{
+ fx_dof->fstop = 128.0f;
+ fx_dof->focal_length = 1.0f;
+ fx_dof->focus_distance = 1.0f;
+ fx_dof->sensor = 1.0f;
+ fx_dof->num_blades = 6;
+}
+
+void GPU_fx_compositor_init_ssao_settings(GPUSSAOSettings *fx_ssao)
+{
+ fx_ssao->factor = 1.0f;
+ fx_ssao->distance_max = 0.2f;
+ fx_ssao->attenuation = 1.0f;
+ fx_ssao->samples = 20;
+}
diff --git a/source/blender/gpu/intern/gpu_debug.c b/source/blender/gpu/intern/gpu_debug.c
new file mode 100644
index 00000000000..1c194f517aa
--- /dev/null
+++ b/source/blender/gpu/intern/gpu_debug.c
@@ -0,0 +1,724 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2005 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Brecht Van Lommel, Jason Wilkins.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/gpu/intern/gpu_debug.c
+ * \ingroup gpu
+ */
+
+#include "BLI_sys_types.h"
+
+#include "BKE_global.h"
+
+#include "GPU_glew.h"
+#include "GPU_debug.h"
+#include "intern/gpu_private.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define CASE_CODE_RETURN_STR(code) case code: return #code;
+
+static const char* gpu_gl_error_symbol(GLenum err)
+{
+ switch (err) {
+ CASE_CODE_RETURN_STR(GL_NO_ERROR)
+ CASE_CODE_RETURN_STR(GL_INVALID_ENUM)
+ CASE_CODE_RETURN_STR(GL_INVALID_VALUE)
+ CASE_CODE_RETURN_STR(GL_INVALID_OPERATION)
+ CASE_CODE_RETURN_STR(GL_STACK_OVERFLOW)
+ CASE_CODE_RETURN_STR(GL_STACK_UNDERFLOW)
+ CASE_CODE_RETURN_STR(GL_OUT_OF_MEMORY)
+
+#if GL_ARB_imaging
+ CASE_CODE_RETURN_STR(GL_TABLE_TOO_LARGE)
+#endif
+
+#if defined(WITH_GLU)
+ CASE_CODE_RETURN_STR(GLU_INVALID_ENUM)
+ CASE_CODE_RETURN_STR(GLU_INVALID_VALUE)
+ CASE_CODE_RETURN_STR(GLU_OUT_OF_MEMORY)
+#endif
+
+ default:
+ return "<unknown error>";
+ }
+}
+
+#undef CASE_CODE_RETURN_STR
+
+
+static bool gpu_report_gl_errors(const char *file, int line, const char *str)
+{
+ GLenum gl_error = glGetError();
+
+ if (gl_error == GL_NO_ERROR) {
+ return true;
+ }
+ else {
+ /* glGetError should have cleared the error flag, so if we get the
+ same flag twice that means glGetError itself probably triggered
+ the error. This happens on Windows if the GL context is invalid.
+ */
+ {
+ GLenum new_error = glGetError();
+ if (gl_error == new_error) {
+ fprintf(stderr, "GL: Possible context invalidation issue\n");
+ return false;
+ }
+ }
+
+ fprintf(
+ stderr,
+ "%s(%d): ``%s'' -> GL Error (0x%04X - %s): %s\n",
+ file,
+ line,
+ str,
+ gl_error,
+ gpu_gl_error_symbol(gl_error),
+ gpuErrorString(gl_error));
+
+ return false;
+ }
+}
+
+
+const char* gpuErrorString(GLenum err)
+{
+ switch (err) {
+ case GL_NO_ERROR:
+ return "No Error";
+
+ case GL_INVALID_ENUM:
+ return "Invalid Enumeration";
+
+ case GL_INVALID_VALUE:
+ return "Invalid Value";
+
+ case GL_INVALID_OPERATION:
+ return "Invalid Operation";
+
+ case GL_STACK_OVERFLOW:
+ return "Stack Overflow";
+
+ case GL_STACK_UNDERFLOW:
+ return "Stack Underflow";
+
+ case GL_OUT_OF_MEMORY:
+ return "Out of Memory";
+
+#if GL_ARB_imaging
+ case GL_TABLE_TOO_LARGE:
+ return "Table Too Large";
+#endif
+
+#if defined(WITH_GLU)
+ case GLU_INVALID_ENUM:
+ return "Invalid Enum (GLU)";
+
+ case GLU_INVALID_VALUE:
+ return "Invalid Value (GLU)";
+
+ case GLU_OUT_OF_MEMORY:
+ return "Out of Memory (GLU)";
+#endif
+
+ default:
+ return "<unknown error>";
+ }
+}
+
+
+/* Debug callbacks need the same calling convention as OpenGL functions.
+ */
+#if defined(_WIN32) && !defined(_WIN32_WCE) && !defined(__SCITECH_SNAP__)
+ /* Win32 but not WinCE */
+# define APIENTRY __stdcall
+#else
+# define APIENTRY
+#endif
+
+
+static void APIENTRY gpu_debug_proc(
+ GLenum source, GLenum type, GLuint UNUSED(id),
+ GLenum UNUSED(severity), GLsizei UNUSED(length),
+ const GLchar *message, const GLvoid *UNUSED(userParm))
+{
+ if (source == GL_DEBUG_SOURCE_API && type == GL_DEBUG_TYPE_ERROR) {
+ fprintf(stderr, "GL: %s\n", message);
+ fflush(stderr);
+ }
+ else if (G.debug_value == 20) {
+ fprintf(stderr, "GL: %s\n", message);
+ fflush(stderr);
+ }
+}
+
+
+#ifndef GLEW_ES_ONLY
+static void APIENTRY gpu_debug_proc_amd(
+ GLuint UNUSED(id), GLenum UNUSED(category),
+ GLenum UNUSED(severity), GLsizei UNUSED(length),
+ const GLchar *message, GLvoid *UNUSED(userParm))
+{
+ fprintf(stderr, "GL: %s\n", message);
+}
+#endif
+
+
+#undef APIENTRY
+
+void gpu_debug_init(void)
+{
+ const char success[] = "Successfully hooked OpenGL debug callback.";
+
+#if !defined(WITH_GLEW_ES) && !defined(GLEW_ES_ONLY)
+ if (GLEW_VERSION_4_3) {
+ glEnable(GL_DEBUG_OUTPUT);
+ glDebugMessageCallback(gpu_debug_proc, mxGetCurrentContext());
+ glDebugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, NULL, GL_TRUE);
+ GPU_string_marker(sizeof(success), success);
+ return;
+ }
+#endif
+
+ if (GLEW_KHR_debug) {
+#ifndef GLEW_ES_ONLY
+ glDebugMessageCallback(gpu_debug_proc, mxGetCurrentContext());
+ glDebugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, NULL, GL_TRUE);
+ GPU_string_marker(sizeof(success), success);
+#endif
+ return;
+ }
+
+#ifndef GLEW_ES_ONLY
+ if (GLEW_ARB_debug_output) {
+ glDebugMessageCallbackARB(gpu_debug_proc, mxGetCurrentContext());
+ glDebugMessageControlARB(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, NULL, GL_TRUE);
+ GPU_string_marker(sizeof(success), success);
+
+ return;
+ }
+
+ if (GLEW_AMD_debug_output) {
+ glDebugMessageCallbackAMD(gpu_debug_proc_amd, mxGetCurrentContext());
+ glDebugMessageEnableAMD(GL_DONT_CARE, GL_DONT_CARE, 0, NULL, GL_TRUE);
+ GPU_string_marker(sizeof(success), success);
+
+ return;
+ }
+#endif
+
+ fprintf(stderr, "Failed to hook OpenGL debug callback.\n");
+
+ return;
+}
+
+
+void gpu_debug_exit(void)
+{
+#ifndef WITH_GLEW_ES
+#ifndef GLEW_ES_ONLY
+ if (GLEW_VERSION_4_3) {
+ glDebugMessageCallback(NULL, NULL);
+
+ return;
+ }
+#endif
+#endif
+
+ if (GLEW_KHR_debug) {
+#ifndef GLEW_ES_ONLY
+ glDebugMessageCallback(NULL, NULL);
+#endif
+ return;
+ }
+
+#ifndef GLEW_ES_ONLY
+ if (GLEW_ARB_debug_output) {
+ glDebugMessageCallbackARB(NULL, NULL);
+
+ return;
+ }
+
+ if (GLEW_AMD_debug_output) {
+ glDebugMessageCallbackAMD(NULL, NULL);
+
+ return;
+ }
+#endif
+
+ return;
+}
+
+void GPU_string_marker(size_t length, const char *buf)
+{
+#ifndef WITH_GLEW_ES
+#ifndef GLEW_ES_ONLY
+ if (GLEW_VERSION_4_3) {
+ glDebugMessageInsert(GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_MARKER, 0, GL_DEBUG_SEVERITY_NOTIFICATION, length, buf);
+
+ return;
+ }
+#endif
+#endif
+
+ if (GLEW_KHR_debug) {
+#ifndef GLEW_ES_ONLY
+ glDebugMessageInsert(GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_MARKER, 0, GL_DEBUG_SEVERITY_NOTIFICATION, length, buf);
+#endif
+ return;
+ }
+
+#ifndef GLEW_ES_ONLY
+ if (GLEW_ARB_debug_output) {
+ glDebugMessageInsertARB(GL_DEBUG_SOURCE_APPLICATION_ARB, GL_DEBUG_TYPE_OTHER_ARB, 0, GL_DEBUG_SEVERITY_LOW_ARB, length, buf);
+
+ return;
+ }
+
+ if (GLEW_AMD_debug_output) {
+ glDebugMessageInsertAMD(GL_DEBUG_CATEGORY_APPLICATION_AMD, GL_DEBUG_SEVERITY_LOW_AMD, 0, length, buf);
+
+ return;
+ }
+
+ if (GLEW_GREMEDY_string_marker) {
+ glStringMarkerGREMEDY(length, buf);
+
+ return;
+ }
+#endif
+
+ return;
+}
+
+void GPU_print_error_debug(const char *str)
+{
+ if (G.debug & G_DEBUG)
+ fprintf(stderr, "GPU: %s\n", str);
+}
+
+
+void GPU_assert_no_gl_errors(const char* file, int line, const char* str)
+{
+ if (G.debug) {
+ GLboolean gl_ok = gpu_report_gl_errors(file, line, str);
+
+ BLI_assert(gl_ok);
+ (void) gl_ok;
+ }
+}
+
+
+static void gpu_state_print_fl_ex(const char *name, GLenum type)
+{
+ const unsigned char err_mark[4] = {0xff, 0xff, 0xff, 0xff};
+
+ float value[32];
+ int a;
+
+ memset(value, 0xff, sizeof(value));
+ glGetFloatv(type, value);
+
+ if (glGetError() == GL_NO_ERROR) {
+ printf("%s: ", name);
+ for (a = 0; a < 32; a++) {
+ if (memcmp(&value[a], err_mark, sizeof(value[a])) == 0) {
+ break;
+ }
+ printf("%.2f ", value[a]);
+ }
+ printf("\n");
+ }
+}
+
+#define gpu_state_print_fl(val) gpu_state_print_fl_ex(#val, val)
+
+void GPU_state_print(void)
+{
+ GPU_ASSERT_NO_GL_ERRORS("GPU_state_print"); /* clear any errors */
+
+ gpu_state_print_fl(GL_ACCUM_ALPHA_BITS);
+ gpu_state_print_fl(GL_ACCUM_BLUE_BITS);
+ gpu_state_print_fl(GL_ACCUM_CLEAR_VALUE);
+ gpu_state_print_fl(GL_ACCUM_GREEN_BITS);
+ gpu_state_print_fl(GL_ACCUM_RED_BITS);
+ gpu_state_print_fl(GL_ACTIVE_TEXTURE);
+ gpu_state_print_fl(GL_ALIASED_LINE_WIDTH_RANGE);
+ gpu_state_print_fl(GL_ALIASED_POINT_SIZE_RANGE);
+ gpu_state_print_fl(GL_ALPHA_BIAS);
+ gpu_state_print_fl(GL_ALPHA_BITS);
+ gpu_state_print_fl(GL_ALPHA_SCALE);
+ gpu_state_print_fl(GL_ALPHA_TEST);
+ gpu_state_print_fl(GL_ALPHA_TEST_FUNC);
+ gpu_state_print_fl(GL_ALPHA_TEST_REF);
+ gpu_state_print_fl(GL_ARRAY_BUFFER_BINDING);
+ gpu_state_print_fl(GL_ATTRIB_STACK_DEPTH);
+ gpu_state_print_fl(GL_AUTO_NORMAL);
+ gpu_state_print_fl(GL_AUX_BUFFERS);
+ gpu_state_print_fl(GL_BLEND);
+ gpu_state_print_fl(GL_BLEND_COLOR);
+ gpu_state_print_fl(GL_BLEND_DST_ALPHA);
+ gpu_state_print_fl(GL_BLEND_DST_RGB);
+ gpu_state_print_fl(GL_BLEND_EQUATION_ALPHA);
+ gpu_state_print_fl(GL_BLEND_EQUATION_RGB);
+ gpu_state_print_fl(GL_BLEND_SRC_ALPHA);
+ gpu_state_print_fl(GL_BLEND_SRC_RGB);
+ gpu_state_print_fl(GL_BLUE_BIAS);
+ gpu_state_print_fl(GL_BLUE_BITS);
+ gpu_state_print_fl(GL_BLUE_SCALE);
+ gpu_state_print_fl(GL_CLIENT_ACTIVE_TEXTURE);
+ gpu_state_print_fl(GL_CLIENT_ATTRIB_STACK_DEPTH);
+ gpu_state_print_fl(GL_CLIP_PLANE0);
+ gpu_state_print_fl(GL_COLOR_ARRAY);
+ gpu_state_print_fl(GL_COLOR_ARRAY_BUFFER_BINDING);
+ gpu_state_print_fl(GL_COLOR_ARRAY_SIZE);
+ gpu_state_print_fl(GL_COLOR_ARRAY_STRIDE);
+ gpu_state_print_fl(GL_COLOR_ARRAY_TYPE);
+ gpu_state_print_fl(GL_COLOR_CLEAR_VALUE);
+ gpu_state_print_fl(GL_COLOR_LOGIC_OP);
+ gpu_state_print_fl(GL_COLOR_MATERIAL);
+ gpu_state_print_fl(GL_COLOR_MATERIAL_FACE);
+ gpu_state_print_fl(GL_COLOR_MATERIAL_PARAMETER);
+ gpu_state_print_fl(GL_COLOR_MATRIX);
+ gpu_state_print_fl(GL_COLOR_MATRIX_STACK_DEPTH);
+ gpu_state_print_fl(GL_COLOR_SUM);
+ gpu_state_print_fl(GL_COLOR_TABLE);
+ gpu_state_print_fl(GL_COLOR_WRITEMASK);
+ gpu_state_print_fl(GL_COMPRESSED_TEXTURE_FORMATS);
+ gpu_state_print_fl(GL_CONVOLUTION_1D);
+ gpu_state_print_fl(GL_CONVOLUTION_2D);
+ gpu_state_print_fl(GL_CULL_FACE);
+ gpu_state_print_fl(GL_CULL_FACE_MODE);
+ gpu_state_print_fl(GL_CURRENT_COLOR);
+ gpu_state_print_fl(GL_CURRENT_FOG_COORD);
+ gpu_state_print_fl(GL_CURRENT_INDEX);
+ gpu_state_print_fl(GL_CURRENT_NORMAL);
+ gpu_state_print_fl(GL_CURRENT_PROGRAM);
+ gpu_state_print_fl(GL_CURRENT_RASTER_COLOR);
+ gpu_state_print_fl(GL_CURRENT_RASTER_DISTANCE);
+ gpu_state_print_fl(GL_CURRENT_RASTER_INDEX);
+ gpu_state_print_fl(GL_CURRENT_RASTER_POSITION);
+ gpu_state_print_fl(GL_CURRENT_RASTER_POSITION_VALID);
+ gpu_state_print_fl(GL_CURRENT_RASTER_SECONDARY_COLOR);
+ gpu_state_print_fl(GL_CURRENT_RASTER_TEXTURE_COORDS);
+ gpu_state_print_fl(GL_CURRENT_SECONDARY_COLOR);
+ gpu_state_print_fl(GL_CURRENT_TEXTURE_COORDS);
+ gpu_state_print_fl(GL_DEPTH_BIAS);
+ gpu_state_print_fl(GL_DEPTH_BITS);
+ gpu_state_print_fl(GL_DEPTH_CLEAR_VALUE);
+ gpu_state_print_fl(GL_DEPTH_FUNC);
+ gpu_state_print_fl(GL_DEPTH_RANGE);
+ gpu_state_print_fl(GL_DEPTH_SCALE);
+ gpu_state_print_fl(GL_DEPTH_TEST);
+ gpu_state_print_fl(GL_DEPTH_WRITEMASK);
+ gpu_state_print_fl(GL_DITHER);
+ gpu_state_print_fl(GL_DOUBLEBUFFER);
+ gpu_state_print_fl(GL_DRAW_BUFFER);
+ gpu_state_print_fl(GL_DRAW_BUFFER0);
+ gpu_state_print_fl(GL_EDGE_FLAG);
+ gpu_state_print_fl(GL_EDGE_FLAG_ARRAY);
+ gpu_state_print_fl(GL_EDGE_FLAG_ARRAY_BUFFER_BINDING);
+ gpu_state_print_fl(GL_EDGE_FLAG_ARRAY_STRIDE);
+ gpu_state_print_fl(GL_ELEMENT_ARRAY_BUFFER_BINDING);
+ gpu_state_print_fl(GL_FEEDBACK_BUFFER_SIZE);
+ gpu_state_print_fl(GL_FEEDBACK_BUFFER_TYPE);
+ gpu_state_print_fl(GL_FOG);
+ gpu_state_print_fl(GL_FOG_COLOR);
+ gpu_state_print_fl(GL_FOG_COORD_ARRAY);
+ gpu_state_print_fl(GL_FOG_COORD_ARRAY_BUFFER_BINDING);
+ gpu_state_print_fl(GL_FOG_COORD_ARRAY_STRIDE);
+ gpu_state_print_fl(GL_FOG_COORD_ARRAY_TYPE);
+ gpu_state_print_fl(GL_FOG_COORD_SRC);
+ gpu_state_print_fl(GL_FOG_DENSITY);
+ gpu_state_print_fl(GL_FOG_END);
+ gpu_state_print_fl(GL_FOG_HINT);
+ gpu_state_print_fl(GL_FOG_INDEX);
+ gpu_state_print_fl(GL_FOG_MODE);
+ gpu_state_print_fl(GL_FOG_START);
+ gpu_state_print_fl(GL_FRAGMENT_PROGRAM_ARB);
+ gpu_state_print_fl(GL_FRAGMENT_SHADER_DERIVATIVE_HINT);
+ gpu_state_print_fl(GL_FRONT_FACE);
+ gpu_state_print_fl(GL_GENERATE_MIPMAP_HINT);
+ gpu_state_print_fl(GL_GREEN_BIAS);
+ gpu_state_print_fl(GL_GREEN_BITS);
+ gpu_state_print_fl(GL_GREEN_SCALE);
+ gpu_state_print_fl(GL_HISTOGRAM);
+ gpu_state_print_fl(GL_INDEX_ARRAY);
+ gpu_state_print_fl(GL_INDEX_ARRAY_BUFFER_BINDING);
+ gpu_state_print_fl(GL_INDEX_ARRAY_STRIDE);
+ gpu_state_print_fl(GL_INDEX_ARRAY_TYPE);
+ gpu_state_print_fl(GL_INDEX_BITS);
+ gpu_state_print_fl(GL_INDEX_CLEAR_VALUE);
+ gpu_state_print_fl(GL_INDEX_LOGIC_OP);
+ gpu_state_print_fl(GL_INDEX_MODE);
+ gpu_state_print_fl(GL_INDEX_OFFSET);
+ gpu_state_print_fl(GL_INDEX_SHIFT);
+ gpu_state_print_fl(GL_INDEX_WRITEMASK);
+ gpu_state_print_fl(GL_LIGHT0);
+ gpu_state_print_fl(GL_LIGHT1);
+ gpu_state_print_fl(GL_LIGHT2);
+ gpu_state_print_fl(GL_LIGHT3);
+ gpu_state_print_fl(GL_LIGHT4);
+ gpu_state_print_fl(GL_LIGHT5);
+ gpu_state_print_fl(GL_LIGHT6);
+ gpu_state_print_fl(GL_LIGHT7);
+ gpu_state_print_fl(GL_LIGHTING);
+ gpu_state_print_fl(GL_LIGHT_MODEL_AMBIENT);
+ gpu_state_print_fl(GL_LIGHT_MODEL_COLOR_CONTROL);
+ gpu_state_print_fl(GL_LIGHT_MODEL_LOCAL_VIEWER);
+ gpu_state_print_fl(GL_LIGHT_MODEL_TWO_SIDE);
+ gpu_state_print_fl(GL_LINE_SMOOTH);
+ gpu_state_print_fl(GL_LINE_SMOOTH_HINT);
+ gpu_state_print_fl(GL_LINE_STIPPLE);
+ gpu_state_print_fl(GL_LINE_STIPPLE_PATTERN);
+ gpu_state_print_fl(GL_LINE_STIPPLE_REPEAT);
+ gpu_state_print_fl(GL_LINE_WIDTH);
+ gpu_state_print_fl(GL_LINE_WIDTH_GRANULARITY);
+ gpu_state_print_fl(GL_LINE_WIDTH_RANGE);
+ gpu_state_print_fl(GL_LIST_BASE);
+ gpu_state_print_fl(GL_LIST_INDEX);
+ gpu_state_print_fl(GL_LIST_MODE);
+ gpu_state_print_fl(GL_LOGIC_OP);
+ gpu_state_print_fl(GL_LOGIC_OP_MODE);
+ gpu_state_print_fl(GL_MAP1_COLOR_4);
+ gpu_state_print_fl(GL_MAP1_GRID_DOMAIN);
+ gpu_state_print_fl(GL_MAP1_GRID_SEGMENTS);
+ gpu_state_print_fl(GL_MAP1_INDEX);
+ gpu_state_print_fl(GL_MAP1_NORMAL);
+ gpu_state_print_fl(GL_MAP1_TEXTURE_COORD_1);
+ gpu_state_print_fl(GL_MAP1_TEXTURE_COORD_2);
+ gpu_state_print_fl(GL_MAP1_TEXTURE_COORD_3);
+ gpu_state_print_fl(GL_MAP1_TEXTURE_COORD_4);
+ gpu_state_print_fl(GL_MAP1_VERTEX_3);
+ gpu_state_print_fl(GL_MAP1_VERTEX_4);
+ gpu_state_print_fl(GL_MAP2_COLOR_4);
+ gpu_state_print_fl(GL_MAP2_GRID_DOMAIN);
+ gpu_state_print_fl(GL_MAP2_GRID_SEGMENTS);
+ gpu_state_print_fl(GL_MAP2_INDEX);
+ gpu_state_print_fl(GL_MAP2_NORMAL);
+ gpu_state_print_fl(GL_MAP2_TEXTURE_COORD_1);
+ gpu_state_print_fl(GL_MAP2_TEXTURE_COORD_2);
+ gpu_state_print_fl(GL_MAP2_TEXTURE_COORD_3);
+ gpu_state_print_fl(GL_MAP2_TEXTURE_COORD_4);
+ gpu_state_print_fl(GL_MAP2_VERTEX_3);
+ gpu_state_print_fl(GL_MAP2_VERTEX_4);
+ gpu_state_print_fl(GL_MAP_COLOR);
+ gpu_state_print_fl(GL_MAP_STENCIL);
+ gpu_state_print_fl(GL_MATRIX_MODE);
+ gpu_state_print_fl(GL_MAX_3D_TEXTURE_SIZE);
+ gpu_state_print_fl(GL_MAX_ATTRIB_STACK_DEPTH);
+ gpu_state_print_fl(GL_MAX_CLIENT_ATTRIB_STACK_DEPTH);
+ gpu_state_print_fl(GL_MAX_CLIP_PLANES);
+ gpu_state_print_fl(GL_MAX_COLOR_MATRIX_STACK_DEPTH);
+ gpu_state_print_fl(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS);
+ gpu_state_print_fl(GL_MAX_CUBE_MAP_TEXTURE_SIZE);
+ gpu_state_print_fl(GL_MAX_DRAW_BUFFERS);
+ gpu_state_print_fl(GL_MAX_ELEMENTS_INDICES);
+ gpu_state_print_fl(GL_MAX_ELEMENTS_VERTICES);
+ gpu_state_print_fl(GL_MAX_EVAL_ORDER);
+ gpu_state_print_fl(GL_MAX_FRAGMENT_UNIFORM_COMPONENTS);
+ gpu_state_print_fl(GL_MAX_LIGHTS);
+ gpu_state_print_fl(GL_MAX_LIST_NESTING);
+ gpu_state_print_fl(GL_MAX_MODELVIEW_STACK_DEPTH);
+ gpu_state_print_fl(GL_MAX_NAME_STACK_DEPTH);
+ gpu_state_print_fl(GL_MAX_PIXEL_MAP_TABLE);
+ gpu_state_print_fl(GL_MAX_PROJECTION_STACK_DEPTH);
+ gpu_state_print_fl(GL_MAX_TEXTURE_COORDS);
+ gpu_state_print_fl(GL_MAX_TEXTURE_IMAGE_UNITS);
+ gpu_state_print_fl(GL_MAX_TEXTURE_LOD_BIAS);
+ gpu_state_print_fl(GL_MAX_TEXTURE_SIZE);
+ gpu_state_print_fl(GL_MAX_TEXTURE_STACK_DEPTH);
+ gpu_state_print_fl(GL_MAX_TEXTURE_UNITS);
+ gpu_state_print_fl(GL_MAX_VARYING_FLOATS);
+ gpu_state_print_fl(GL_MAX_VERTEX_ATTRIBS);
+ gpu_state_print_fl(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS);
+ gpu_state_print_fl(GL_MAX_VERTEX_UNIFORM_COMPONENTS);
+ gpu_state_print_fl(GL_MAX_VIEWPORT_DIMS);
+ gpu_state_print_fl(GL_MINMAX);
+ gpu_state_print_fl(GL_MODELVIEW_MATRIX);
+ gpu_state_print_fl(GL_MODELVIEW_STACK_DEPTH);
+ gpu_state_print_fl(GL_MULTISAMPLE);
+ gpu_state_print_fl(GL_MULTISAMPLE_ARB);
+ gpu_state_print_fl(GL_NAME_STACK_DEPTH);
+ gpu_state_print_fl(GL_NORMALIZE);
+ gpu_state_print_fl(GL_NORMAL_ARRAY);
+ gpu_state_print_fl(GL_NORMAL_ARRAY_BUFFER_BINDING);
+ gpu_state_print_fl(GL_NORMAL_ARRAY_STRIDE);
+ gpu_state_print_fl(GL_NORMAL_ARRAY_TYPE);
+ gpu_state_print_fl(GL_NUM_COMPRESSED_TEXTURE_FORMATS);
+ gpu_state_print_fl(GL_PACK_ALIGNMENT);
+ gpu_state_print_fl(GL_PACK_IMAGE_HEIGHT);
+ gpu_state_print_fl(GL_PACK_LSB_FIRST);
+ gpu_state_print_fl(GL_PACK_ROW_LENGTH);
+ gpu_state_print_fl(GL_PACK_SKIP_IMAGES);
+ gpu_state_print_fl(GL_PACK_SKIP_PIXELS);
+ gpu_state_print_fl(GL_PACK_SKIP_ROWS);
+ gpu_state_print_fl(GL_PACK_SWAP_BYTES);
+ gpu_state_print_fl(GL_PERSPECTIVE_CORRECTION_HINT);
+ gpu_state_print_fl(GL_PIXEL_MAP_A_TO_A_SIZE);
+ gpu_state_print_fl(GL_PIXEL_MAP_B_TO_B_SIZE);
+ gpu_state_print_fl(GL_PIXEL_MAP_G_TO_G_SIZE);
+ gpu_state_print_fl(GL_PIXEL_MAP_I_TO_A_SIZE);
+ gpu_state_print_fl(GL_PIXEL_MAP_I_TO_B_SIZE);
+ gpu_state_print_fl(GL_PIXEL_MAP_I_TO_G_SIZE);
+ gpu_state_print_fl(GL_PIXEL_MAP_I_TO_I_SIZE);
+ gpu_state_print_fl(GL_PIXEL_MAP_I_TO_R_SIZE);
+ gpu_state_print_fl(GL_PIXEL_MAP_R_TO_R_SIZE);
+ gpu_state_print_fl(GL_PIXEL_MAP_S_TO_S_SIZE);
+ gpu_state_print_fl(GL_PIXEL_PACK_BUFFER_BINDING);
+ gpu_state_print_fl(GL_PIXEL_UNPACK_BUFFER_BINDING);
+ gpu_state_print_fl(GL_POINT_DISTANCE_ATTENUATION);
+ gpu_state_print_fl(GL_POINT_FADE_THRESHOLD_SIZE);
+ gpu_state_print_fl(GL_POINT_SIZE);
+ gpu_state_print_fl(GL_POINT_SIZE_GRANULARITY);
+ gpu_state_print_fl(GL_POINT_SIZE_MAX);
+ gpu_state_print_fl(GL_POINT_SIZE_MIN);
+ gpu_state_print_fl(GL_POINT_SIZE_RANGE);
+ gpu_state_print_fl(GL_POINT_SMOOTH);
+ gpu_state_print_fl(GL_POINT_SMOOTH_HINT);
+ gpu_state_print_fl(GL_POINT_SPRITE);
+ gpu_state_print_fl(GL_POLYGON_MODE);
+ gpu_state_print_fl(GL_POLYGON_OFFSET_FACTOR);
+ gpu_state_print_fl(GL_POLYGON_OFFSET_FILL);
+ gpu_state_print_fl(GL_POLYGON_OFFSET_LINE);
+ gpu_state_print_fl(GL_POLYGON_OFFSET_POINT);
+ gpu_state_print_fl(GL_POLYGON_OFFSET_UNITS);
+ gpu_state_print_fl(GL_POLYGON_SMOOTH);
+ gpu_state_print_fl(GL_POLYGON_SMOOTH_HINT);
+ gpu_state_print_fl(GL_POLYGON_STIPPLE);
+ gpu_state_print_fl(GL_POST_COLOR_MATRIX_ALPHA_BIAS);
+ gpu_state_print_fl(GL_POST_COLOR_MATRIX_ALPHA_SCALE);
+ gpu_state_print_fl(GL_POST_COLOR_MATRIX_BLUE_BIAS);
+ gpu_state_print_fl(GL_POST_COLOR_MATRIX_BLUE_SCALE);
+ gpu_state_print_fl(GL_POST_COLOR_MATRIX_COLOR_TABLE);
+ gpu_state_print_fl(GL_POST_COLOR_MATRIX_GREEN_BIAS);
+ gpu_state_print_fl(GL_POST_COLOR_MATRIX_GREEN_SCALE);
+ gpu_state_print_fl(GL_POST_COLOR_MATRIX_RED_BIAS);
+ gpu_state_print_fl(GL_POST_COLOR_MATRIX_RED_SCALE);
+ gpu_state_print_fl(GL_POST_CONVOLUTION_ALPHA_BIAS);
+ gpu_state_print_fl(GL_POST_CONVOLUTION_ALPHA_SCALE);
+ gpu_state_print_fl(GL_POST_CONVOLUTION_BLUE_BIAS);
+ gpu_state_print_fl(GL_POST_CONVOLUTION_BLUE_SCALE);
+ gpu_state_print_fl(GL_POST_CONVOLUTION_COLOR_TABLE);
+ gpu_state_print_fl(GL_POST_CONVOLUTION_GREEN_BIAS);
+ gpu_state_print_fl(GL_POST_CONVOLUTION_GREEN_SCALE);
+ gpu_state_print_fl(GL_POST_CONVOLUTION_RED_BIAS);
+ gpu_state_print_fl(GL_POST_CONVOLUTION_RED_SCALE);
+ gpu_state_print_fl(GL_PROJECTION_MATRIX);
+ gpu_state_print_fl(GL_PROJECTION_STACK_DEPTH);
+ gpu_state_print_fl(GL_READ_BUFFER);
+ gpu_state_print_fl(GL_RED_BIAS);
+ gpu_state_print_fl(GL_RED_BITS);
+ gpu_state_print_fl(GL_RED_SCALE);
+ gpu_state_print_fl(GL_RENDER_MODE);
+ gpu_state_print_fl(GL_RESCALE_NORMAL);
+ gpu_state_print_fl(GL_RGBA_MODE);
+ gpu_state_print_fl(GL_SAMPLES);
+ gpu_state_print_fl(GL_SAMPLE_BUFFERS);
+ gpu_state_print_fl(GL_SAMPLE_COVERAGE_INVERT);
+ gpu_state_print_fl(GL_SAMPLE_COVERAGE_VALUE);
+ gpu_state_print_fl(GL_SCISSOR_BOX);
+ gpu_state_print_fl(GL_SCISSOR_TEST);
+ gpu_state_print_fl(GL_SECONDARY_COLOR_ARRAY);
+ gpu_state_print_fl(GL_SECONDARY_COLOR_ARRAY_BUFFER_BINDING);
+ gpu_state_print_fl(GL_SECONDARY_COLOR_ARRAY_SIZE);
+ gpu_state_print_fl(GL_SECONDARY_COLOR_ARRAY_STRIDE);
+ gpu_state_print_fl(GL_SECONDARY_COLOR_ARRAY_TYPE);
+ gpu_state_print_fl(GL_SELECTION_BUFFER_SIZE);
+ gpu_state_print_fl(GL_SEPARABLE_2D);
+ gpu_state_print_fl(GL_SHADE_MODEL);
+ gpu_state_print_fl(GL_SMOOTH_LINE_WIDTH_GRANULARITY);
+ gpu_state_print_fl(GL_SMOOTH_LINE_WIDTH_RANGE);
+ gpu_state_print_fl(GL_SMOOTH_POINT_SIZE_GRANULARITY);
+ gpu_state_print_fl(GL_SMOOTH_POINT_SIZE_RANGE);
+ gpu_state_print_fl(GL_STENCIL_BACK_FAIL);
+ gpu_state_print_fl(GL_STENCIL_BACK_FUNC);
+ gpu_state_print_fl(GL_STENCIL_BACK_PASS_DEPTH_FAIL);
+ gpu_state_print_fl(GL_STENCIL_BACK_PASS_DEPTH_PASS);
+ gpu_state_print_fl(GL_STENCIL_BACK_REF);
+ gpu_state_print_fl(GL_STENCIL_BACK_VALUE_MASK);
+ gpu_state_print_fl(GL_STENCIL_BACK_WRITEMASK);
+ gpu_state_print_fl(GL_STENCIL_BITS);
+ gpu_state_print_fl(GL_STENCIL_CLEAR_VALUE);
+ gpu_state_print_fl(GL_STENCIL_FAIL);
+ gpu_state_print_fl(GL_STENCIL_FUNC);
+ gpu_state_print_fl(GL_STENCIL_PASS_DEPTH_FAIL);
+ gpu_state_print_fl(GL_STENCIL_PASS_DEPTH_PASS);
+ gpu_state_print_fl(GL_STENCIL_REF);
+ gpu_state_print_fl(GL_STENCIL_TEST);
+ gpu_state_print_fl(GL_STENCIL_VALUE_MASK);
+ gpu_state_print_fl(GL_STENCIL_WRITEMASK);
+ gpu_state_print_fl(GL_STEREO);
+ gpu_state_print_fl(GL_SUBPIXEL_BITS);
+ gpu_state_print_fl(GL_TEXTURE_1D);
+ gpu_state_print_fl(GL_TEXTURE_2D);
+ gpu_state_print_fl(GL_TEXTURE_3D);
+ gpu_state_print_fl(GL_TEXTURE_BINDING_1D);
+ gpu_state_print_fl(GL_TEXTURE_BINDING_2D);
+ gpu_state_print_fl(GL_TEXTURE_BINDING_3D);
+ gpu_state_print_fl(GL_TEXTURE_BINDING_CUBE_MAP);
+ gpu_state_print_fl(GL_TEXTURE_COMPRESSION_HINT);
+ gpu_state_print_fl(GL_TEXTURE_COORD_ARRAY);
+ gpu_state_print_fl(GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING);
+ gpu_state_print_fl(GL_TEXTURE_COORD_ARRAY_SIZE);
+ gpu_state_print_fl(GL_TEXTURE_COORD_ARRAY_STRIDE);
+ gpu_state_print_fl(GL_TEXTURE_COORD_ARRAY_TYPE);
+ gpu_state_print_fl(GL_TEXTURE_CUBE_MAP);
+ gpu_state_print_fl(GL_TEXTURE_CUBE_MAP_ARB);
+ gpu_state_print_fl(GL_TEXTURE_GEN_Q);
+ gpu_state_print_fl(GL_TEXTURE_GEN_R);
+ gpu_state_print_fl(GL_TEXTURE_GEN_S);
+ gpu_state_print_fl(GL_TEXTURE_GEN_T);
+ gpu_state_print_fl(GL_TEXTURE_MATRIX);
+ gpu_state_print_fl(GL_TEXTURE_STACK_DEPTH);
+ gpu_state_print_fl(GL_TRANSPOSE_COLOR_MATRIX);
+ gpu_state_print_fl(GL_TRANSPOSE_MODELVIEW_MATRIX);
+ gpu_state_print_fl(GL_TRANSPOSE_PROJECTION_MATRIX);
+ gpu_state_print_fl(GL_TRANSPOSE_TEXTURE_MATRIX);
+ gpu_state_print_fl(GL_UNPACK_ALIGNMENT);
+ gpu_state_print_fl(GL_UNPACK_IMAGE_HEIGHT);
+ gpu_state_print_fl(GL_UNPACK_LSB_FIRST);
+ gpu_state_print_fl(GL_UNPACK_ROW_LENGTH);
+ gpu_state_print_fl(GL_UNPACK_SKIP_IMAGES);
+ gpu_state_print_fl(GL_UNPACK_SKIP_PIXELS);
+ gpu_state_print_fl(GL_UNPACK_SKIP_ROWS);
+ gpu_state_print_fl(GL_UNPACK_SWAP_BYTES);
+ gpu_state_print_fl(GL_VERTEX_ARRAY);
+ gpu_state_print_fl(GL_VERTEX_ARRAY_BUFFER_BINDING);
+ gpu_state_print_fl(GL_VERTEX_ARRAY_SIZE);
+ gpu_state_print_fl(GL_VERTEX_ARRAY_STRIDE);
+ gpu_state_print_fl(GL_VERTEX_ARRAY_TYPE);
+ gpu_state_print_fl(GL_VERTEX_PROGRAM_POINT_SIZE);
+ gpu_state_print_fl(GL_VERTEX_PROGRAM_TWO_SIDE);
+ gpu_state_print_fl(GL_VIEWPORT);
+ gpu_state_print_fl(GL_ZOOM_X);
+ gpu_state_print_fl(GL_ZOOM_Y);
+}
+
+#undef gpu_state_print_fl
diff --git a/source/blender/gpu/intern/gpu_draw.c b/source/blender/gpu/intern/gpu_draw.c
index 7295f0259c5..bf7b8fbc386 100644
--- a/source/blender/gpu/intern/gpu_draw.c
+++ b/source/blender/gpu/intern/gpu_draw.c
@@ -38,7 +38,8 @@
#include <string.h>
-#include "GL/glew.h"
+#include "GPU_glew.h"
+#include "GPU_debug.h"
#include "BLI_blenlib.h"
#include "BLI_linklist.h"
@@ -55,6 +56,7 @@
#include "DNA_scene_types.h"
#include "DNA_smoke_types.h"
#include "DNA_view3d_types.h"
+#include "DNA_particle_types.h"
#include "MEM_guardedalloc.h"
@@ -69,6 +71,7 @@
#include "BKE_node.h"
#include "BKE_object.h"
#include "BKE_scene.h"
+#include "BKE_subsurf.h"
#include "BKE_DerivedMesh.h"
#include "GPU_buffers.h"
@@ -80,6 +83,13 @@
#include "smoke_API.h"
+#ifdef WITH_OPENSUBDIV
+# include "DNA_mesh_types.h"
+# include "BKE_editmesh.h"
+
+# include "gpu_codegen.h"
+#endif
+
extern Material defmaterial; /* from material.c */
/* Text Rendering */
@@ -87,16 +97,22 @@ extern Material defmaterial; /* from material.c */
static void gpu_mcol(unsigned int ucol)
{
/* mcol order is swapped */
- const char *cp= (char *)&ucol;
+ const char *cp = (char *)&ucol;
glColor3ub(cp[3], cp[2], cp[1]);
}
-void GPU_render_text(MTFace *tface, int mode,
- const char *textstr, int textlen, unsigned int *col,
- float *v1, float *v2, float *v3, float *v4, int glattrib)
+void GPU_render_text(
+ MTexPoly *mtexpoly, int mode,
+ const char *textstr, int textlen, unsigned int *col,
+ const float *v_quad[4], const float *uv_quad[4],
+ int glattrib)
{
- if ((mode & GEMAT_TEXT) && (textlen>0) && tface->tpage) {
- Image* ima = (Image *)tface->tpage;
+ if ((mode & GEMAT_TEXT) && (textlen > 0) && mtexpoly->tpage) {
+ const float *v1 = v_quad[0];
+ const float *v2 = v_quad[1];
+ const float *v3 = v_quad[2];
+ const float *v4 = v_quad[3];
+ Image *ima = (Image *)mtexpoly->tpage;
ImBuf *first_ibuf;
const size_t textlen_st = textlen;
size_t index;
@@ -104,7 +120,7 @@ void GPU_render_text(MTFace *tface, int mode,
float advance_tab;
/* multiline */
- float line_start= 0.0f, line_height;
+ float line_start = 0.0f, line_height;
if (v4)
line_height = max_ffff(v1[1], v2[1], v3[1], v4[2]) - min_ffff(v1[1], v2[1], v3[1], v4[2]);
@@ -115,8 +131,8 @@ void GPU_render_text(MTFace *tface, int mode,
/* color has been set */
- if (tface->mode & TF_OBCOL)
- col= NULL;
+ if (mtexpoly->mode & TF_OBCOL)
+ col = NULL;
else if (!col)
glColor3f(1.0f, 1.0f, 1.0f);
@@ -127,23 +143,23 @@ void GPU_render_text(MTFace *tface, int mode,
matrixGlyph(first_ibuf, ' ', &centerx, &centery,
&sizex, &sizey, &transx, &transy, &movex, &movey, &advance);
- advance_tab= advance * 4; /* tab width could also be an option */
+ advance_tab = advance * 4; /* tab width could also be an option */
for (index = 0; index < textlen_st; ) {
unsigned int character;
float uv[4][2];
- // lets calculate offset stuff
+ /* lets calculate offset stuff */
character = BLI_str_utf8_as_unicode_and_size_safe(textstr + index, &index);
- if (character=='\n') {
- glTranslatef(line_start, -line_height, 0.0);
+ if (character == '\n') {
+ glTranslatef(line_start, -line_height, 0.0f);
line_start = 0.0f;
continue;
}
- else if (character=='\t') {
- glTranslatef(advance_tab, 0.0, 0.0);
+ else if (character == '\t') {
+ glTranslatef(advance_tab, 0.0f, 0.0f);
line_start -= advance_tab; /* so we can go back to the start of the line */
continue;
@@ -153,17 +169,17 @@ void GPU_render_text(MTFace *tface, int mode,
character = '?';
}
- // space starts at offset 1
- // character = character - ' ' + 1;
+ /* space starts at offset 1 */
+ /* character = character - ' ' + 1; */
matrixGlyph(first_ibuf, character, & centerx, &centery,
&sizex, &sizey, &transx, &transy, &movex, &movey, &advance);
- uv[0][0] = (tface->uv[0][0] - centerx) * sizex + transx;
- uv[0][1] = (tface->uv[0][1] - centery) * sizey + transy;
- uv[1][0] = (tface->uv[1][0] - centerx) * sizex + transx;
- uv[1][1] = (tface->uv[1][1] - centery) * sizey + transy;
- uv[2][0] = (tface->uv[2][0] - centerx) * sizex + transx;
- uv[2][1] = (tface->uv[2][1] - centery) * sizey + transy;
+ uv[0][0] = (uv_quad[0][0] - centerx) * sizex + transx;
+ uv[0][1] = (uv_quad[0][1] - centery) * sizey + transy;
+ uv[1][0] = (uv_quad[1][0] - centerx) * sizex + transx;
+ uv[1][1] = (uv_quad[1][1] - centery) * sizey + transy;
+ uv[2][0] = (uv_quad[2][0] - centerx) * sizex + transx;
+ uv[2][1] = (uv_quad[2][1] - centery) * sizey + transy;
glBegin(GL_POLYGON);
if (glattrib >= 0) glVertexAttrib2fvARB(glattrib, uv[0]);
@@ -182,8 +198,8 @@ void GPU_render_text(MTFace *tface, int mode,
glVertex3f(sizex * v3[0] + movex, sizey * v3[1] + movey, v3[2]);
if (v4) {
- uv[3][0] = (tface->uv[3][0] - centerx) * sizex + transx;
- uv[3][1] = (tface->uv[3][1] - centery) * sizey + transy;
+ uv[3][0] = (uv_quad[3][0] - centerx) * sizex + transx;
+ uv[3][1] = (uv_quad[3][1] - centery) * sizey + transy;
if (glattrib >= 0) glVertexAttrib2fvARB(glattrib, uv[3]);
else glTexCoord2fv(uv[3]);
@@ -192,7 +208,7 @@ void GPU_render_text(MTFace *tface, int mode,
}
glEnd();
- glTranslatef(advance, 0.0, 0.0);
+ glTranslatef(advance, 0.0f, 0.0f);
line_start -= advance; /* so we can go back to the start of the line */
}
glPopMatrix();
@@ -238,14 +254,18 @@ static struct GPUTextureState {
int curtileYRep, tileYRep;
Image *ima, *curima;
- int domipmap, linearmipmap;
- int texpaint; /* store this so that new images created while texture painting won't be set to mipmapped */
+ /* also controls min/mag filtering */
+ bool domipmap;
+ /* only use when 'domipmap' is set */
+ bool linearmipmap;
+ /* store this so that new images created while texture painting won't be set to mipmapped */
+ bool texpaint;
int alphablend;
float anisotropic;
int gpu_mipmap;
- MTFace *lasttface;
-} GTS = {0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, 1, 0, 0, -1, 1.f, 0, NULL};
+ MTexPoly *lasttface;
+} GTS = {0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, 1, 0, 0, -1, 1.0f, 0, NULL};
/* Mipmap settings */
@@ -280,49 +300,53 @@ static void gpu_generate_mipmap(GLenum target)
glDisable(target);
}
-void GPU_set_mipmap(int mipmap)
+void GPU_set_mipmap(bool mipmap)
{
- if (GTS.domipmap != (mipmap != 0)) {
+ if (GTS.domipmap != mipmap) {
GPU_free_images();
- GTS.domipmap = mipmap != 0;
+ GTS.domipmap = mipmap;
}
}
-void GPU_set_linear_mipmap(int linear)
+void GPU_set_linear_mipmap(bool linear)
{
- if (GTS.linearmipmap != (linear != 0)) {
- GPU_free_images();
- GTS.linearmipmap = linear != 0;
+ if (GTS.linearmipmap != linear) {
+ GTS.linearmipmap = linear;
}
}
-int GPU_get_mipmap(void)
+bool GPU_get_mipmap(void)
{
return GTS.domipmap && !GTS.texpaint;
}
-int GPU_get_linear_mipmap(void)
+bool GPU_get_linear_mipmap(void)
{
return GTS.linearmipmap;
}
-static GLenum gpu_get_mipmap_filter(int mag)
+static GLenum gpu_get_mipmap_filter(bool mag)
{
/* linearmipmap is off by default *when mipmapping is off,
* use unfiltered display */
if (mag) {
- if (GTS.linearmipmap || GTS.domipmap)
+ if (GTS.domipmap)
return GL_LINEAR;
else
return GL_NEAREST;
}
else {
- if (GTS.linearmipmap)
- return GL_LINEAR_MIPMAP_LINEAR;
- else if (GTS.domipmap)
- return GL_LINEAR_MIPMAP_NEAREST;
- else
+ if (GTS.domipmap) {
+ if (GTS.linearmipmap) {
+ return GL_LINEAR_MIPMAP_LINEAR;
+ }
+ else {
+ return GL_LINEAR_MIPMAP_NEAREST;
+ }
+ }
+ else {
return GL_NEAREST;
+ }
}
}
@@ -352,41 +376,41 @@ static void gpu_make_repbind(Image *ima)
ImBuf *ibuf;
ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL);
- if (ibuf==NULL)
+ if (ibuf == NULL)
return;
if (ima->repbind) {
glDeleteTextures(ima->totbind, (GLuint *)ima->repbind);
MEM_freeN(ima->repbind);
- ima->repbind= NULL;
+ ima->repbind = NULL;
ima->tpageflag &= ~IMA_MIPMAP_COMPLETE;
}
- ima->totbind= ima->xrep*ima->yrep;
+ ima->totbind = ima->xrep*ima->yrep;
if (ima->totbind>1)
- ima->repbind= MEM_callocN(sizeof(int)*ima->totbind, "repbind");
+ ima->repbind = MEM_callocN(sizeof(int) * ima->totbind, "repbind");
BKE_image_release_ibuf(ima, ibuf, NULL);
}
void GPU_clear_tpage(bool force)
{
- if (GTS.lasttface==NULL && !force)
+ if (GTS.lasttface == NULL && !force)
return;
- GTS.lasttface= NULL;
- GTS.curtile= 0;
- GTS.curima= NULL;
- if (GTS.curtilemode!=0) {
+ GTS.lasttface = NULL;
+ GTS.curtile = 0;
+ GTS.curima = NULL;
+ if (GTS.curtilemode != 0) {
glMatrixMode(GL_TEXTURE);
glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
}
- GTS.curtilemode= 0;
- GTS.curtileXRep=0;
- GTS.curtileYRep=0;
- GTS.alphablend= -1;
+ GTS.curtilemode = 0;
+ GTS.curtileXRep = 0;
+ GTS.curtileYRep = 0;
+ GTS.alphablend = -1;
glDisable(GL_BLEND);
glDisable(GL_TEXTURE_2D);
@@ -400,15 +424,18 @@ static void gpu_set_alpha_blend(GPUBlendMode alphablend)
if (alphablend == GPU_BLEND_SOLID) {
glDisable(GL_BLEND);
glDisable(GL_ALPHA_TEST);
+ glDisable(GL_SAMPLE_ALPHA_TO_COVERAGE);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}
- else if (alphablend==GPU_BLEND_ADD) {
+ else if (alphablend == GPU_BLEND_ADD) {
glEnable(GL_BLEND);
glBlendFunc(GL_ONE, GL_ONE);
glDisable(GL_ALPHA_TEST);
+ glDisable(GL_SAMPLE_ALPHA_TO_COVERAGE);
}
else if (ELEM(alphablend, GPU_BLEND_ALPHA, GPU_BLEND_ALPHA_SORT)) {
glEnable(GL_BLEND);
+ glDisable(GL_SAMPLE_ALPHA_TO_COVERAGE);
/* for OpenGL render we use the alpha channel, this makes alpha blend correct */
if (GLEW_VERSION_1_4)
@@ -428,11 +455,17 @@ static void gpu_set_alpha_blend(GPUBlendMode alphablend)
glAlphaFunc(GL_GREATER, U.glalphaclip);
}
}
- else if (alphablend==GPU_BLEND_CLIP) {
- glDisable(GL_BLEND);
+ else if (alphablend == GPU_BLEND_CLIP) {
+ glDisable(GL_BLEND);
+ glDisable(GL_SAMPLE_ALPHA_TO_COVERAGE);
glEnable(GL_ALPHA_TEST);
glAlphaFunc(GL_GREATER, 0.5f);
}
+ else if (alphablend == GPU_BLEND_ALPHA_TO_COVERAGE) {
+ glEnable(GL_ALPHA_TEST);
+ glAlphaFunc(GL_GREATER, U.glalphaclip);
+ glEnable(GL_SAMPLE_ALPHA_TO_COVERAGE);
+ }
}
static void gpu_verify_alpha_blend(int alphablend)
@@ -442,7 +475,7 @@ static void gpu_verify_alpha_blend(int alphablend)
return;
gpu_set_alpha_blend(alphablend);
- GTS.alphablend= alphablend;
+ GTS.alphablend = alphablend;
}
static void gpu_verify_reflection(Image *ima)
@@ -466,9 +499,9 @@ int GPU_verify_image(Image *ima, ImageUser *iuser, int tftile, bool compare, boo
{
ImBuf *ibuf = NULL;
unsigned int *bind = NULL;
- int rectw, recth, tpx=0, tpy=0, y;
- unsigned int *tilerect= NULL, *rect= NULL;
- float *ftilerect= NULL, *frect = NULL;
+ int rectw, recth, tpx = 0, tpy = 0, y;
+ unsigned int *tilerect = NULL, *rect = NULL;
+ float *ftilerect = NULL, *frect = NULL;
float *srgb_frect = NULL;
short texwindx, texwindy, texwinsx, texwinsy;
/* flag to determine whether high resolution format is used */
@@ -476,15 +509,15 @@ int GPU_verify_image(Image *ima, ImageUser *iuser, int tftile, bool compare, boo
/* initialize tile mode and number of repeats */
GTS.ima = ima;
- GTS.tilemode= (ima && (ima->tpageflag & (IMA_TILES|IMA_TWINANIM)));
+ GTS.tilemode = (ima && (ima->tpageflag & (IMA_TILES|IMA_TWINANIM)));
GTS.tileXRep = 0;
GTS.tileYRep = 0;
/* setting current tile according to frame */
if (ima && (ima->tpageflag & IMA_TWINANIM))
- GTS.tile= ima->lastframe;
+ GTS.tile = ima->lastframe;
else
- GTS.tile= tftile;
+ GTS.tile = tftile;
GTS.tile = MAX2(0, GTS.tile);
@@ -502,26 +535,26 @@ int GPU_verify_image(Image *ima, ImageUser *iuser, int tftile, bool compare, boo
}
/* if tiling mode or repeat changed, change texture matrix to fit */
- if (GTS.tilemode!=GTS.curtilemode || GTS.curtileXRep!=GTS.tileXRep ||
+ if (GTS.tilemode != GTS.curtilemode || GTS.curtileXRep != GTS.tileXRep ||
GTS.curtileYRep != GTS.tileYRep)
{
glMatrixMode(GL_TEXTURE);
glLoadIdentity();
if (ima && (ima->tpageflag & IMA_TILES))
- glScalef(ima->xrep, ima->yrep, 1.0);
+ glScalef(ima->xrep, ima->yrep, 1.0f);
glMatrixMode(GL_MODELVIEW);
}
/* check if we have a valid image */
- if (ima==NULL || ima->ok==0)
+ if (ima == NULL || ima->ok == 0)
return 0;
/* check if we have a valid image buffer */
- ibuf= BKE_image_acquire_ibuf(ima, iuser, NULL);
+ ibuf = BKE_image_acquire_ibuf(ima, iuser, NULL);
- if (ibuf==NULL)
+ if (ibuf == NULL)
return 0;
if (ibuf->rect_float) {
@@ -551,59 +584,58 @@ int GPU_verify_image(Image *ima, ImageUser *iuser, int tftile, bool compare, boo
if (GTS.tilemode) {
/* tiled mode */
- if (ima->repbind==NULL) gpu_make_repbind(ima);
- if (GTS.tile>=ima->totbind) GTS.tile= 0;
+ if (ima->repbind == NULL) gpu_make_repbind(ima);
+ if (GTS.tile >= ima->totbind) GTS.tile = 0;
/* this happens when you change repeat buttons */
- if (ima->repbind) bind= &ima->repbind[GTS.tile];
- else bind= &ima->bindcode;
+ if (ima->repbind) bind = &ima->repbind[GTS.tile];
+ else bind = &ima->bindcode;
- if (*bind==0) {
-
- texwindx= ibuf->x/ima->xrep;
- texwindy= ibuf->y/ima->yrep;
+ if (*bind == 0) {
+ texwindx = ibuf->x / ima->xrep;
+ texwindy = ibuf->y / ima->yrep;
- if (GTS.tile>=ima->xrep*ima->yrep)
- GTS.tile= ima->xrep*ima->yrep-1;
+ if (GTS.tile >= ima->xrep * ima->yrep)
+ GTS.tile = ima->xrep * ima->yrep - 1;
- texwinsy= GTS.tile / ima->xrep;
- texwinsx= GTS.tile - texwinsy*ima->xrep;
+ texwinsy = GTS.tile / ima->xrep;
+ texwinsx = GTS.tile - texwinsy * ima->xrep;
- texwinsx*= texwindx;
- texwinsy*= texwindy;
+ texwinsx *= texwindx;
+ texwinsy *= texwindy;
- tpx= texwindx;
- tpy= texwindy;
+ tpx = texwindx;
+ tpy = texwindy;
if (use_high_bit_depth) {
if (do_color_management) {
- srgb_frect = MEM_mallocN(ibuf->x*ibuf->y*sizeof(float)*4, "floar_buf_col_cor");
+ srgb_frect = MEM_mallocN(ibuf->x * ibuf->y * sizeof(float) * 4, "floar_buf_col_cor");
IMB_buffer_float_from_float(srgb_frect, ibuf->rect_float,
ibuf->channels, IB_PROFILE_SRGB, IB_PROFILE_LINEAR_RGB, true,
ibuf->x, ibuf->y, ibuf->x, ibuf->x);
IMB_buffer_float_unpremultiply(srgb_frect, ibuf->x, ibuf->y);
/* clamp buffer colors to 1.0 to avoid artifacts due to glu for hdr images */
IMB_buffer_float_clamp(srgb_frect, ibuf->x, ibuf->y);
- frect= srgb_frect + texwinsy*ibuf->x + texwinsx;
+ frect = srgb_frect + texwinsy*ibuf->x + texwinsx;
}
else
- frect= ibuf->rect_float + texwinsy*ibuf->x + texwinsx;
+ frect = ibuf->rect_float + texwinsy*ibuf->x + texwinsx;
}
else
- rect= ibuf->rect + texwinsy*ibuf->x + texwinsx;
+ rect = ibuf->rect + texwinsy*ibuf->x + texwinsx;
}
}
else {
/* regular image mode */
bind= &ima->bindcode;
- if (*bind==0) {
- tpx= ibuf->x;
- tpy= ibuf->y;
- rect= ibuf->rect;
+ if (*bind == 0) {
+ tpx = ibuf->x;
+ tpy = ibuf->y;
+ rect = ibuf->rect;
if (use_high_bit_depth) {
if (do_color_management) {
- frect = srgb_frect = MEM_mallocN(ibuf->x*ibuf->y*sizeof(*srgb_frect)*4, "floar_buf_col_cor");
+ frect = srgb_frect = MEM_mallocN(ibuf->x * ibuf->y * sizeof(*srgb_frect) * 4, "floar_buf_col_cor");
IMB_buffer_float_from_float(srgb_frect, ibuf->rect_float,
ibuf->channels, IB_PROFILE_SRGB, IB_PROFILE_LINEAR_RGB, true,
ibuf->x, ibuf->y, ibuf->x, ibuf->x);
@@ -612,7 +644,7 @@ int GPU_verify_image(Image *ima, ImageUser *iuser, int tftile, bool compare, boo
IMB_buffer_float_clamp(srgb_frect, ibuf->x, ibuf->y);
}
else
- frect= ibuf->rect_float;
+ frect = ibuf->rect_float;
}
}
}
@@ -632,35 +664,35 @@ int GPU_verify_image(Image *ima, ImageUser *iuser, int tftile, bool compare, boo
if (use_high_bit_depth) {
float *frectrow, *ftilerectrow;
- ftilerect= MEM_mallocN(rectw*recth*sizeof(*ftilerect), "tilerect");
+ ftilerect = MEM_mallocN(rectw*recth*sizeof(*ftilerect), "tilerect");
- for (y=0; y<recth; y++) {
- frectrow= &frect[y*ibuf->x];
- ftilerectrow= &ftilerect[y*rectw];
+ for (y = 0; y < recth; y++) {
+ frectrow = &frect[y * ibuf->x];
+ ftilerectrow = &ftilerect[y * rectw];
- memcpy(ftilerectrow, frectrow, tpx*sizeof(*frectrow));
+ memcpy(ftilerectrow, frectrow, tpx * sizeof(*frectrow));
}
- frect= ftilerect;
+ frect = ftilerect;
}
else {
unsigned int *rectrow, *tilerectrow;
- tilerect= MEM_mallocN(rectw*recth*sizeof(*tilerect), "tilerect");
+ tilerect = MEM_mallocN(rectw*recth*sizeof(*tilerect), "tilerect");
- for (y=0; y<recth; y++) {
- rectrow= &rect[y*ibuf->x];
- tilerectrow= &tilerect[y*rectw];
+ for (y = 0; y < recth; y++) {
+ rectrow = &rect[y * ibuf->x];
+ tilerectrow = &tilerect[y * rectw];
- memcpy(tilerectrow, rectrow, tpx*sizeof(*rectrow));
+ memcpy(tilerectrow, rectrow, tpx * sizeof(*rectrow));
}
- rect= tilerect;
+ rect = tilerect;
}
}
#ifdef WITH_DDS
- if (ibuf->ftype & DDS)
+ if (ibuf->ftype == IMB_FTYPE_DDS)
GPU_create_gl_tex_compressed(bind, rect, rectw, recth, mipmap, ima, ibuf);
else
#endif
@@ -688,11 +720,10 @@ int GPU_verify_image(Image *ima, ImageUser *iuser, int tftile, bool compare, boo
}
/* Image *ima can be NULL */
-void GPU_create_gl_tex(unsigned int *bind, unsigned int *pix, float *frect, int rectw, int recth,
+void GPU_create_gl_tex(unsigned int *bind, unsigned int *rect, float *frect, int rectw, int recth,
bool mipmap, bool use_high_bit_depth, Image *ima)
{
- unsigned int *scalerect = NULL;
- float *fscalerect = NULL;
+ ImBuf *ibuf = NULL;
int tpx = rectw;
int tpy = recth;
@@ -702,20 +733,20 @@ void GPU_create_gl_tex(unsigned int *bind, unsigned int *pix, float *frect, int
* Then don't bother scaling for hardware that supports NPOT textures! */
if ((!GPU_non_power_of_two_support() && !is_power_of_2_resolution(rectw, recth)) ||
is_over_resolution_limit(rectw, recth)) {
- rectw= smaller_power_of_2_limit(rectw);
- recth= smaller_power_of_2_limit(recth);
+ rectw = smaller_power_of_2_limit(rectw);
+ recth = smaller_power_of_2_limit(recth);
if (use_high_bit_depth) {
- fscalerect= MEM_mallocN(rectw*recth*sizeof(*fscalerect)*4, "fscalerect");
- gluScaleImage(GL_RGBA, tpx, tpy, GL_FLOAT, frect, rectw, recth, GL_FLOAT, fscalerect);
+ ibuf = IMB_allocFromBuffer(NULL, frect, tpx, tpy);
+ IMB_scaleImBuf(ibuf, rectw, recth);
- frect = fscalerect;
+ frect = ibuf->rect_float;
}
else {
- scalerect= MEM_mallocN(rectw*recth*sizeof(*scalerect), "scalerect");
- gluScaleImage(GL_RGBA, tpx, tpy, GL_UNSIGNED_BYTE, pix, rectw, recth, GL_UNSIGNED_BYTE, scalerect);
+ ibuf = IMB_allocFromBuffer(rect, NULL, tpx, tpy);
+ IMB_scaleImBuf(ibuf, rectw, recth);
- pix= scalerect;
+ rect = ibuf->rect;
}
}
@@ -723,45 +754,64 @@ void GPU_create_gl_tex(unsigned int *bind, unsigned int *pix, float *frect, int
glGenTextures(1, (GLuint *)bind);
glBindTexture(GL_TEXTURE_2D, *bind);
- if (!(GPU_get_mipmap() && mipmap)) {
- if (use_high_bit_depth)
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16, rectw, recth, 0, GL_RGBA, GL_FLOAT, frect);
+ if (use_high_bit_depth) {
+ if (GLEW_ARB_texture_float)
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, rectw, recth, 0, GL_RGBA, GL_FLOAT, frect);
else
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, rectw, recth, 0, GL_RGBA, GL_UNSIGNED_BYTE, pix);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gpu_get_mipmap_filter(1));
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16, rectw, recth, 0, GL_RGBA, GL_FLOAT, frect);
}
- else {
- if (GTS.gpu_mipmap) {
- if (use_high_bit_depth)
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16, rectw, recth, 0, GL_RGBA, GL_FLOAT, frect);
- else
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, rectw, recth, 0, GL_RGBA, GL_UNSIGNED_BYTE, pix);
+ else
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, rectw, recth, 0, GL_RGBA, GL_UNSIGNED_BYTE, rect);
+
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gpu_get_mipmap_filter(1));
+ if (GPU_get_mipmap() && mipmap) {
+ if (GTS.gpu_mipmap) {
gpu_generate_mipmap(GL_TEXTURE_2D);
}
else {
- if (use_high_bit_depth)
- gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGBA16, rectw, recth, GL_RGBA, GL_FLOAT, frect);
- else
- gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGBA, rectw, recth, GL_RGBA, GL_UNSIGNED_BYTE, pix);
+ int i;
+
+ if (!ibuf) {
+ if (use_high_bit_depth) {
+ ibuf = IMB_allocFromBuffer(NULL, frect, tpx, tpy);
+ }
+ else {
+ ibuf = IMB_allocFromBuffer(rect, NULL, tpx, tpy);
+ }
+ }
+
+ IMB_makemipmap(ibuf, true);
+
+ for (i = 1; i < ibuf->miptot; i++) {
+ ImBuf *mip = ibuf->mipmap[i - 1];
+ if (use_high_bit_depth) {
+ if (GLEW_ARB_texture_float)
+ glTexImage2D(GL_TEXTURE_2D, i, GL_RGBA16F, mip->x, mip->y, 0, GL_RGBA, GL_FLOAT, mip->rect_float);
+ else
+ glTexImage2D(GL_TEXTURE_2D, i, GL_RGBA16, mip->x, mip->y, 0, GL_RGBA, GL_FLOAT, mip->rect_float);
+ }
+ else {
+ glTexImage2D(GL_TEXTURE_2D, i, GL_RGBA, mip->x, mip->y, 0, GL_RGBA, GL_UNSIGNED_BYTE, mip->rect);
+ }
+ }
}
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gpu_get_mipmap_filter(0));
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gpu_get_mipmap_filter(1));
if (ima)
ima->tpageflag |= IMA_MIPMAP_COMPLETE;
}
+ else {
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ }
if (GLEW_EXT_texture_filter_anisotropic)
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, GPU_get_anisotropic());
/* set to modulate with vertex color */
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
- if (scalerect)
- MEM_freeN(scalerect);
- if (fscalerect)
- MEM_freeN(fscalerect);
+ if (ibuf)
+ IMB_freeImBuf(ibuf);
}
/**
@@ -788,12 +838,12 @@ bool GPU_upload_dxt_texture(ImBuf *ibuf)
}
if (format == 0) {
- printf("Unable to find a suitable DXT compression, falling back to uncompressed\n");
+ fprintf(stderr, "Unable to find a suitable DXT compression, falling back to uncompressed\n");
return false;
}
if (!is_power_of_2_resolution(width, height)) {
- printf("Unable to load non-power-of-two DXT image resolution, falling back to uncompressed\n");
+ fprintf(stderr, "Unable to load non-power-of-two DXT image resolution, falling back to uncompressed\n");
return false;
}
@@ -806,7 +856,7 @@ bool GPU_upload_dxt_texture(ImBuf *ibuf)
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, GPU_get_anisotropic());
blocksize = (ibuf->dds_data.fourcc == FOURCC_DXT1) ? 8 : 16;
- for (i=0; i<ibuf->dds_data.nummipmaps && (width||height); ++i) {
+ for (i = 0; i < ibuf->dds_data.nummipmaps && (width||height); ++i) {
if (width == 0)
width = 1;
if (height == 0)
@@ -823,7 +873,7 @@ bool GPU_upload_dxt_texture(ImBuf *ibuf)
}
/* set number of mipmap levels we have, needed in case they don't go down to 1x1 */
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, i-1);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, i - 1);
return true;
#else
@@ -864,26 +914,26 @@ static void gpu_verify_repeat(Image *ima)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
}
-int GPU_set_tpage(MTFace *tface, int mipmap, int alphablend)
+int GPU_set_tpage(MTexPoly *mtexpoly, int mipmap, int alphablend)
{
Image *ima;
/* check if we need to clear the state */
- if (tface==NULL) {
+ if (mtexpoly == NULL) {
GPU_clear_tpage(false);
return 0;
}
- ima= tface->tpage;
- GTS.lasttface= tface;
+ ima = mtexpoly->tpage;
+ GTS.lasttface = mtexpoly;
gpu_verify_alpha_blend(alphablend);
gpu_verify_reflection(ima);
- if (GPU_verify_image(ima, NULL, tface->tile, 1, mipmap, false)) {
- GTS.curtile= GTS.tile;
- GTS.curima= GTS.ima;
- GTS.curtilemode= GTS.tilemode;
+ if (GPU_verify_image(ima, NULL, mtexpoly->tile, 1, mipmap, false)) {
+ GTS.curtile = GTS.tile;
+ GTS.curima = GTS.ima;
+ GTS.curtilemode = GTS.tilemode;
GTS.curtileXRep = GTS.tileXRep;
GTS.curtileYRep = GTS.tileYRep;
@@ -892,9 +942,9 @@ int GPU_set_tpage(MTFace *tface, int mipmap, int alphablend)
else {
glDisable(GL_TEXTURE_2D);
- GTS.curtile= 0;
- GTS.curima= NULL;
- GTS.curtilemode= 0;
+ GTS.curtile = 0;
+ GTS.curima = NULL;
+ GTS.curtilemode = 0;
GTS.curtileXRep = 0;
GTS.curtileYRep = 0;
@@ -913,9 +963,9 @@ int GPU_set_tpage(MTFace *tface, int mipmap, int alphablend)
* temporary disabling/enabling mipmapping on all images for quick texture
* updates with glTexSubImage2D. images that didn't change don't have to be
* re-uploaded to OpenGL */
-void GPU_paint_set_mipmap(int mipmap)
+void GPU_paint_set_mipmap(bool mipmap)
{
- Image* ima;
+ Image *ima;
if (!GTS.domipmap)
return;
@@ -923,7 +973,7 @@ void GPU_paint_set_mipmap(int mipmap)
GTS.texpaint = !mipmap;
if (mipmap) {
- for (ima=G.main->image.first; ima; ima=ima->id.next) {
+ for (ima = G.main->image.first; ima; ima = ima->id.next) {
if (ima->bindcode) {
if (ima->tpageflag & IMA_MIPMAP_COMPLETE) {
glBindTexture(GL_TEXTURE_2D, ima->bindcode);
@@ -939,7 +989,7 @@ void GPU_paint_set_mipmap(int mipmap)
}
else {
- for (ima=G.main->image.first; ima; ima=ima->id.next) {
+ for (ima = G.main->image.first; ima; ima = ima->id.next) {
if (ima->bindcode) {
glBindTexture(GL_TEXTURE_2D, ima->bindcode);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
@@ -977,16 +1027,16 @@ static bool GPU_check_scaled_image(ImBuf *ibuf, Image *ima, float *frect, int x,
if (rectw + x > x_limit) rectw--;
if (recth + y > y_limit) recth--;
- /* float rectangles are already continuous in memory so we can use gluScaleImage */
+ /* float rectangles are already continuous in memory so we can use IMB_scaleImBuf */
if (frect) {
- float *fscalerect = MEM_mallocN(rectw*recth*sizeof(*fscalerect)*4, "fscalerect");
- gluScaleImage(GL_RGBA, w, h, GL_FLOAT, frect, rectw, recth, GL_FLOAT, fscalerect);
+ ImBuf *ibuf = IMB_allocFromBuffer(NULL, frect, w, h);
+ IMB_scaleImBuf(ibuf, rectw, recth);
glBindTexture(GL_TEXTURE_2D, ima->bindcode);
glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, rectw, recth, GL_RGBA,
- GL_FLOAT, fscalerect);
+ GL_FLOAT, ibuf->rect_float);
- MEM_freeN(fscalerect);
+ IMB_freeImBuf(ibuf);
}
/* byte images are not continuous in memory so do manual interpolation */
else {
@@ -1022,11 +1072,11 @@ static bool GPU_check_scaled_image(ImBuf *ibuf, Image *ima, float *frect, int x,
return false;
}
-void GPU_paint_update_image(Image *ima, int x, int y, int w, int h)
+void GPU_paint_update_image(Image *ima, ImageUser *iuser, int x, int y, int w, int h)
{
ImBuf *ibuf;
- ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL);
+ ibuf = BKE_image_acquire_ibuf(ima, iuser, NULL);
if (ima->repbind || (GPU_get_mipmap() && !GTS.gpu_mipmap) || !ima->bindcode || !ibuf ||
(w == 0) || (h == 0))
@@ -1052,8 +1102,7 @@ void GPU_paint_update_image(Image *ima, int x, int y, int w, int h)
}
glBindTexture(GL_TEXTURE_2D, ima->bindcode);
- glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, w, h, GL_RGBA,
- GL_FLOAT, buffer);
+ glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, w, h, GL_RGBA, GL_FLOAT, buffer);
MEM_freeN(buffer);
@@ -1108,16 +1157,16 @@ void GPU_update_images_framechange(void)
{
Image *ima;
- for (ima=G.main->image.first; ima; ima=ima->id.next) {
+ for (ima = G.main->image.first; ima; ima = ima->id.next) {
if (ima->tpageflag & IMA_TWINANIM) {
- if (ima->twend >= ima->xrep*ima->yrep)
- ima->twend= ima->xrep*ima->yrep-1;
+ if (ima->twend >= ima->xrep * ima->yrep)
+ ima->twend = ima->xrep * ima->yrep - 1;
/* check: is bindcode not in the array? free. (to do) */
ima->lastframe++;
if (ima->lastframe > ima->twend)
- ima->lastframe= ima->twsta;
+ ima->lastframe = ima->twsta;
}
}
}
@@ -1125,33 +1174,33 @@ void GPU_update_images_framechange(void)
int GPU_update_image_time(Image *ima, double time)
{
int inc = 0;
- float diff;
+ float diff;
int newframe;
if (!ima)
return 0;
- if (ima->lastupdate<0)
+ if (ima->lastupdate < 0)
ima->lastupdate = 0;
if (ima->lastupdate > (float)time)
- ima->lastupdate=(float)time;
+ ima->lastupdate = (float)time;
if (ima->tpageflag & IMA_TWINANIM) {
- if (ima->twend >= ima->xrep*ima->yrep) ima->twend= ima->xrep*ima->yrep-1;
+ if (ima->twend >= ima->xrep * ima->yrep) ima->twend = ima->xrep * ima->yrep - 1;
/* check: is the bindcode not in the array? Then free. (still to do) */
diff = (float)((float)time - ima->lastupdate);
- inc = (int)(diff*(float)ima->animspeed);
+ inc = (int)(diff * (float)ima->animspeed);
- ima->lastupdate+=((float)inc/(float)ima->animspeed);
+ ima->lastupdate += ((float)inc / (float)ima->animspeed);
- newframe = ima->lastframe+inc;
+ newframe = ima->lastframe + inc;
if (newframe > (int)ima->twend) {
- if (ima->twend-ima->twsta != 0)
- newframe = (int)ima->twsta-1 + (newframe-ima->twend)%(ima->twend-ima->twsta);
+ if (ima->twend - ima->twsta != 0)
+ newframe = (int)ima->twsta - 1 + (newframe - ima->twend) % (ima->twend - ima->twsta);
else
newframe = ima->twsta;
}
@@ -1188,7 +1237,7 @@ void GPU_create_smoke(SmokeModifierData *smd, int highres)
if (!sds->tex && !highres) {
/* rgba texture for color + density */
if (smoke_has_colors(sds->fluid)) {
- float *data = MEM_callocN(sizeof(float)*sds->total_cells*4, "smokeColorTexture");
+ float *data = MEM_callocN(sizeof(float) * sds->total_cells * 4, "smokeColorTexture");
smoke_get_rgba(sds->fluid, data, 0);
sds->tex = GPU_texture_create_3D(sds->res[0], sds->res[1], sds->res[2], 4, data);
MEM_freeN(data);
@@ -1202,7 +1251,7 @@ void GPU_create_smoke(SmokeModifierData *smd, int highres)
else if (!sds->tex && highres) {
/* rgba texture for color + density */
if (smoke_turbulence_has_colors(sds->wt)) {
- float *data = MEM_callocN(sizeof(float)*smoke_turbulence_get_cells(sds->wt)*4, "smokeColorTexture");
+ float *data = MEM_callocN(sizeof(float) * smoke_turbulence_get_cells(sds->wt) * 4, "smokeColorTexture");
smoke_turbulence_get_rgba(sds->wt, data, 0);
sds->tex = GPU_texture_create_3D(sds->res_wt[0], sds->res_wt[1], sds->res_wt[2], 4, data);
MEM_freeN(data);
@@ -1218,9 +1267,9 @@ void GPU_create_smoke(SmokeModifierData *smd, int highres)
}
#else // WITH_SMOKE
(void)highres;
- smd->domain->tex= NULL;
- smd->domain->tex_flame= NULL;
- smd->domain->tex_shadow= NULL;
+ smd->domain->tex = NULL;
+ smd->domain->tex_flame = NULL;
+ smd->domain->tex_shadow = NULL;
#endif // WITH_SMOKE
}
@@ -1244,7 +1293,7 @@ void GPU_free_unused_buffers(void)
BLI_lock_thread(LOCK_OPENGL);
/* images */
- for (node=image_free_queue; node; node=node->next) {
+ for (node = image_free_queue; node; node = node->next) {
ima = node->link;
/* check in case it was freed in the meantime */
@@ -1271,13 +1320,13 @@ void GPU_free_image(Image *ima)
/* free regular image binding */
if (ima->bindcode) {
glDeleteTextures(1, (GLuint *)&ima->bindcode);
- ima->bindcode= 0;
+ ima->bindcode = 0;
}
/* free glsl image binding */
if (ima->gputexture) {
GPU_texture_free(ima->gputexture);
- ima->gputexture= NULL;
+ ima->gputexture = NULL;
}
/* free repeated image binding */
@@ -1285,7 +1334,7 @@ void GPU_free_image(Image *ima)
glDeleteTextures(ima->totbind, (GLuint *)ima->repbind);
MEM_freeN(ima->repbind);
- ima->repbind= NULL;
+ ima->repbind = NULL;
}
ima->tpageflag &= ~(IMA_MIPMAP_COMPLETE|IMA_GLBIND_IS_DATA);
@@ -1293,20 +1342,20 @@ void GPU_free_image(Image *ima)
void GPU_free_images(void)
{
- Image* ima;
+ Image *ima;
if (G.main)
- for (ima=G.main->image.first; ima; ima=ima->id.next)
+ for (ima = G.main->image.first; ima; ima = ima->id.next)
GPU_free_image(ima);
}
/* same as above but only free animated images */
void GPU_free_images_anim(void)
{
- Image* ima;
+ Image *ima;
if (G.main)
- for (ima=G.main->image.first; ima; ima=ima->id.next)
+ for (ima = G.main->image.first; ima; ima = ima->id.next)
if (BKE_image_is_animated(ima))
GPU_free_image(ima);
}
@@ -1352,7 +1401,7 @@ void GPU_free_images_old(void)
/* OpenGL Materials */
-#define FIXEDMAT 8
+#define FIXEDMAT 8
/* OpenGL state caching for materials */
@@ -1367,15 +1416,21 @@ static struct GPUMaterialState {
GPUMaterialFixed matbuf_fixed[FIXEDMAT];
int totmat;
+ /* set when called inside GPU_begin_object_materials / GPU_end_object_materials
+ * otherwise calling GPU_enable_material returns zero */
+ bool is_enabled;
+
Material **gmatbuf;
Material *gmatbuf_fixed[FIXEDMAT];
Material *gboundmat;
Object *gob;
+ DupliObject *dob;
Scene *gscene;
int glay;
bool gscenelock;
float (*gviewmat)[4];
float (*gviewinv)[4];
+ float (*gviewcamtexcofac);
bool backface_culling;
@@ -1386,30 +1441,50 @@ static struct GPUMaterialState {
int lastmatnr, lastretval;
GPUBlendMode lastalphablend;
+ bool is_opensubdiv;
} GMS = {NULL};
/* fixed function material, alpha handed by caller */
-static void gpu_material_to_fixed(GPUMaterialFixed *smat, const Material *bmat, const int gamma, const Object *ob, const int new_shading_nodes)
+static void gpu_material_to_fixed(GPUMaterialFixed *smat, const Material *bmat, const int gamma, const Object *ob, const int new_shading_nodes,
+ const bool dimdown)
{
- if (new_shading_nodes || bmat->mode & MA_SHLESS) {
+ if (bmat->mode & MA_SHLESS) {
copy_v3_v3(smat->diff, &bmat->r);
- smat->diff[3]= 1.0;
+ smat->diff[3] = 1.0;
if (gamma)
linearrgb_to_srgb_v3_v3(smat->diff, smat->diff);
zero_v4(smat->spec);
- smat->hard= 0;
+ smat->hard = 0;
+ }
+ else if (new_shading_nodes) {
+ copy_v3_v3(smat->diff, &bmat->r);
+ smat->diff[3] = 1.0;
+
+ copy_v3_v3(smat->spec, &bmat->specr);
+ smat->spec[3] = 1.0;
+ smat->hard = CLAMPIS(bmat->har, 0, 128);
+
+ if (dimdown) {
+ mul_v3_fl(smat->diff, 0.8f);
+ mul_v3_fl(smat->spec, 0.5f);
+ }
+
+ if (gamma) {
+ linearrgb_to_srgb_v3_v3(smat->diff, smat->diff);
+ linearrgb_to_srgb_v3_v3(smat->spec, smat->spec);
+ }
}
else {
mul_v3_v3fl(smat->diff, &bmat->r, bmat->ref + bmat->emit);
- smat->diff[3]= 1.0; /* caller may set this to bmat->alpha */
+ smat->diff[3] = 1.0; /* caller may set this to bmat->alpha */
if (bmat->shade_flag & MA_OBCOLOR)
mul_v3_v3(smat->diff, ob->col);
mul_v3_v3fl(smat->spec, &bmat->specr, bmat->spec);
- smat->spec[3]= 1.0; /* always 1 */
+ smat->spec[3] = 1.0; /* always 1 */
smat->hard= CLAMPIS(bmat->har, 0, 128);
if (gamma) {
@@ -1433,15 +1508,51 @@ static Material *gpu_active_node_material(Material *ma)
return ma;
}
+void GPU_begin_dupli_object(DupliObject *dob)
+{
+ GMS.dob = dob;
+}
+
+void GPU_end_dupli_object(void)
+{
+ GMS.dob = NULL;
+}
+
void GPU_begin_object_materials(View3D *v3d, RegionView3D *rv3d, Scene *scene, Object *ob, bool glsl, bool *do_alpha_after)
{
Material *ma;
GPUMaterial *gpumat;
GPUBlendMode alphablend;
+ DupliObject *dob;
int a;
const bool gamma = BKE_scene_check_color_management_enabled(scene);
const bool new_shading_nodes = BKE_scene_use_new_shading_nodes(scene);
const bool use_matcap = (v3d->flag2 & V3D_SHOW_SOLID_MATCAP) != 0; /* assumes v3d->defmaterial->preview is set */
+ bool use_opensubdiv = false;
+
+#ifdef WITH_OPENSUBDIV
+ {
+ DerivedMesh *derivedFinal = NULL;
+ if (ob->type == OB_MESH) {
+ Mesh *me = ob->data;
+ BMEditMesh *em = me->edit_btmesh;
+ if (em != NULL) {
+ derivedFinal = em->derivedFinal;
+ }
+ else {
+ derivedFinal = ob->derivedFinal;
+ }
+ }
+ else {
+ derivedFinal = ob->derivedFinal;
+ }
+
+ if (derivedFinal != NULL && derivedFinal->type == DM_TYPE_CCGDM) {
+ CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) derivedFinal;
+ use_opensubdiv = ccgdm->useGpuBackend;
+ }
+ }
+#endif
#ifdef WITH_GAMEENGINE
if (rv3d->rflag & RV3D_IS_GAME_ENGINE) {
@@ -1450,7 +1561,11 @@ void GPU_begin_object_materials(View3D *v3d, RegionView3D *rv3d, Scene *scene, O
#endif
/* initialize state */
+ /* DupliObject must be restored */
+ dob = GMS.dob;
memset(&GMS, 0, sizeof(GMS));
+ GMS.is_enabled = true;
+ GMS.dob = dob;
GMS.lastmatnr = -1;
GMS.lastretval = -1;
GMS.lastalphablend = GPU_BLEND_SOLID;
@@ -1460,11 +1575,13 @@ void GPU_begin_object_materials(View3D *v3d, RegionView3D *rv3d, Scene *scene, O
GMS.gob = ob;
GMS.gscene = scene;
+ GMS.is_opensubdiv = use_opensubdiv;
GMS.totmat = use_matcap ? 1 : ob->totcol + 1; /* materials start from 1, default material is 0 */
- GMS.glay= (v3d->localvd)? v3d->localvd->lay: v3d->lay; /* keep lamps visible in local view */
+ GMS.glay = (v3d->localvd)? v3d->localvd->lay: v3d->lay; /* keep lamps visible in local view */
GMS.gscenelock = (v3d->scenelock != 0);
- GMS.gviewmat= rv3d->viewmat;
- GMS.gviewinv= rv3d->viewinv;
+ GMS.gviewmat = rv3d->viewmat;
+ GMS.gviewinv = rv3d->viewinv;
+ GMS.gviewcamtexcofac = rv3d->viewcamtexcofac;
/* alpha pass setup. there's various cases to handle here:
* - object transparency on: only solid materials draw in the first pass,
@@ -1477,68 +1594,68 @@ void GPU_begin_object_materials(View3D *v3d, RegionView3D *rv3d, Scene *scene, O
*do_alpha_after = false;
if (GMS.totmat > FIXEDMAT) {
- GMS.matbuf= MEM_callocN(sizeof(GPUMaterialFixed)*GMS.totmat, "GMS.matbuf");
- GMS.gmatbuf= MEM_callocN(sizeof(*GMS.gmatbuf)*GMS.totmat, "GMS.matbuf");
- GMS.alphablend= MEM_callocN(sizeof(*GMS.alphablend)*GMS.totmat, "GMS.matbuf");
+ GMS.matbuf = MEM_callocN(sizeof(GPUMaterialFixed) * GMS.totmat, "GMS.matbuf");
+ GMS.gmatbuf = MEM_callocN(sizeof(*GMS.gmatbuf) * GMS.totmat, "GMS.matbuf");
+ GMS.alphablend = MEM_callocN(sizeof(*GMS.alphablend) * GMS.totmat, "GMS.matbuf");
}
else {
- GMS.matbuf= GMS.matbuf_fixed;
- GMS.gmatbuf= GMS.gmatbuf_fixed;
- GMS.alphablend= GMS.alphablend_fixed;
+ GMS.matbuf = GMS.matbuf_fixed;
+ GMS.gmatbuf = GMS.gmatbuf_fixed;
+ GMS.alphablend = GMS.alphablend_fixed;
}
/* viewport material, setup in space_view3d, defaults to matcap using ma->preview now */
if (use_matcap) {
GMS.gmatbuf[0] = v3d->defmaterial;
- GPU_material_matcap(scene, v3d->defmaterial);
+ GPU_material_matcap(scene, v3d->defmaterial, use_opensubdiv);
/* do material 1 too, for displists! */
memcpy(&GMS.matbuf[1], &GMS.matbuf[0], sizeof(GPUMaterialFixed));
- GMS.alphablend[0]= GPU_BLEND_SOLID;
+ GMS.alphablend[0] = GPU_BLEND_SOLID;
}
else {
/* no materials assigned? */
- if (ob->totcol==0) {
- gpu_material_to_fixed(&GMS.matbuf[0], &defmaterial, 0, ob, new_shading_nodes);
+ if (ob->totcol == 0) {
+ gpu_material_to_fixed(&GMS.matbuf[0], &defmaterial, 0, ob, new_shading_nodes, true);
/* do material 1 too, for displists! */
memcpy(&GMS.matbuf[1], &GMS.matbuf[0], sizeof(GPUMaterialFixed));
if (glsl) {
- GMS.gmatbuf[0]= &defmaterial;
- GPU_material_from_blender(GMS.gscene, &defmaterial);
+ GMS.gmatbuf[0] = &defmaterial;
+ GPU_material_from_blender(GMS.gscene, &defmaterial, GMS.is_opensubdiv);
}
- GMS.alphablend[0]= GPU_BLEND_SOLID;
+ GMS.alphablend[0] = GPU_BLEND_SOLID;
}
/* setup materials */
- for (a=1; a<=ob->totcol; a++) {
+ for (a = 1; a <= ob->totcol; a++) {
/* find a suitable material */
- ma= give_current_material(ob, a);
- if (!glsl && !new_shading_nodes) ma= gpu_active_node_material(ma);
- if (ma==NULL) ma= &defmaterial;
+ ma = give_current_material(ob, a);
+ if (!glsl && !new_shading_nodes) ma = gpu_active_node_material(ma);
+ if (ma == NULL) ma = &defmaterial;
/* create glsl material if requested */
- gpumat = (glsl)? GPU_material_from_blender(GMS.gscene, ma): NULL;
+ gpumat = glsl? GPU_material_from_blender(GMS.gscene, ma, GMS.is_opensubdiv): NULL;
if (gpumat) {
/* do glsl only if creating it succeed, else fallback */
- GMS.gmatbuf[a]= ma;
+ GMS.gmatbuf[a] = ma;
alphablend = GPU_material_alpha_blend(gpumat, ob->col);
}
else {
/* fixed function opengl materials */
- gpu_material_to_fixed(&GMS.matbuf[a], ma, gamma, ob, new_shading_nodes);
+ gpu_material_to_fixed(&GMS.matbuf[a], ma, gamma, ob, new_shading_nodes, false);
if (GMS.use_alpha_pass && ((ma->mode & MA_TRANSP) || (new_shading_nodes && ma->alpha != 1.0f))) {
- GMS.matbuf[a].diff[3]= ma->alpha;
+ GMS.matbuf[a].diff[3] = ma->alpha;
alphablend = (ma->alpha == 1.0f)? GPU_BLEND_SOLID: GPU_BLEND_ALPHA;
}
else {
- GMS.matbuf[a].diff[3]= 1.0f;
+ GMS.matbuf[a].diff[3] = 1.0f;
alphablend = GPU_BLEND_SOLID;
}
}
@@ -1549,14 +1666,44 @@ void GPU_begin_object_materials(View3D *v3d, RegionView3D *rv3d, Scene *scene, O
if (ELEM(alphablend, GPU_BLEND_ALPHA, GPU_BLEND_ADD, GPU_BLEND_ALPHA_SORT))
*do_alpha_after = true;
- GMS.alphablend[a]= alphablend;
+ GMS.alphablend[a] = alphablend;
}
}
-
+
/* let's start with a clean state */
GPU_disable_material();
}
+static int GPU_get_particle_info(GPUParticleInfo *pi)
+{
+ ParticleData *p;
+ DupliObject *dob = GMS.dob;
+ int ind;
+ if (dob->particle_system) {
+ if (dob->persistent_id[0] < dob->particle_system->totpart)
+ ind = dob->persistent_id[0];
+ else {
+ ind = dob->particle_system->child[dob->persistent_id[0] - dob->particle_system->totpart].parent;
+ }
+ if (ind >= 0) {
+ p = &dob->particle_system->particles[ind];
+
+ pi->scalprops[0] = ind;
+ pi->scalprops[1] = GMS.gscene->r.cfra - p->time;
+ pi->scalprops[2] = p->lifetime;
+ pi->scalprops[3] = p->size;
+
+ copy_v3_v3(pi->location, p->state.co);
+ copy_v3_v3(pi->velocity, p->state.vel);
+ copy_v3_v3(pi->angular_velocity, p->state.ave);
+ return 1;
+ }
+ else return 0;
+ }
+ else
+ return 0;
+}
+
int GPU_enable_material(int nr, void *attribs)
{
GPUVertexAttribs *gattribs = attribs;
@@ -1570,10 +1717,10 @@ int GPU_enable_material(int nr, void *attribs)
memset(&GMS, 0, sizeof(GMS));
mul_v3_v3fl(diff, &defmaterial.r, defmaterial.ref + defmaterial.emit);
- diff[3]= 1.0;
+ diff[3] = 1.0;
mul_v3_v3fl(spec, &defmaterial.specr, defmaterial.spec);
- spec[3]= 1.0;
+ spec[3] = 1.0;
glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, diff);
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, spec);
@@ -1583,21 +1730,21 @@ int GPU_enable_material(int nr, void *attribs)
}
/* prevent index to use un-initialized array items */
- if (nr>=GMS.totmat)
- nr= 0;
+ if (nr >= GMS.totmat)
+ nr = 0;
if (gattribs)
memset(gattribs, 0, sizeof(*gattribs));
/* keep current material */
- if (nr==GMS.lastmatnr)
+ if (nr == GMS.lastmatnr)
return GMS.lastretval;
/* unbind glsl material */
if (GMS.gboundmat) {
if (GMS.is_alpha_pass) glDepthMask(0);
- GPU_material_unbind(GPU_material_from_blender(GMS.gscene, GMS.gboundmat));
- GMS.gboundmat= NULL;
+ GPU_material_unbind(GPU_material_from_blender(GMS.gscene, GMS.gboundmat, GMS.is_opensubdiv));
+ GMS.gboundmat = NULL;
}
/* draw materials with alpha in alpha pass */
@@ -1619,15 +1766,21 @@ int GPU_enable_material(int nr, void *attribs)
if (gattribs && GMS.gmatbuf[nr]) {
/* bind glsl material and get attributes */
Material *mat = GMS.gmatbuf[nr];
+ GPUParticleInfo partile_info;
+
float auto_bump_scale;
- gpumat = GPU_material_from_blender(GMS.gscene, mat);
+ gpumat = GPU_material_from_blender(GMS.gscene, mat, GMS.is_opensubdiv);
GPU_material_vertex_attributes(gpumat, gattribs);
- GPU_material_bind(gpumat, GMS.gob->lay, GMS.glay, 1.0, !(GMS.gob->mode & OB_MODE_TEXTURE_PAINT), GMS.gviewmat, GMS.gviewinv, GMS.gscenelock);
+
+ if (GMS.dob)
+ GPU_get_particle_info(&partile_info);
+
+ GPU_material_bind(gpumat, GMS.gob->lay, GMS.glay, 1.0, !(GMS.gob->mode & OB_MODE_TEXTURE_PAINT), GMS.gviewmat, GMS.gviewinv, GMS.gviewcamtexcofac, GMS.gscenelock);
auto_bump_scale = GMS.gob->derivedFinal != NULL ? GMS.gob->derivedFinal->auto_bump_scale : 1.0f;
- GPU_material_bind_uniforms(gpumat, GMS.gob->obmat, GMS.gob->col, auto_bump_scale);
- GMS.gboundmat= mat;
+ GPU_material_bind_uniforms(gpumat, GMS.gob->obmat, GMS.gob->col, auto_bump_scale, &partile_info);
+ GMS.gboundmat = mat;
/* for glsl use alpha blend mode, unless it's set to solid and
* we are already drawing in an alpha pass */
@@ -1644,7 +1797,7 @@ int GPU_enable_material(int nr, void *attribs)
}
if (GMS.use_matcaps)
- glColor3f(1.0, 1.0, 1.0f);
+ glColor3f(1.0f, 1.0f, 1.0f);
}
else {
/* or do fixed function opengl material */
@@ -1676,16 +1829,16 @@ int GPU_get_material_alpha_blend(void)
void GPU_disable_material(void)
{
- GMS.lastmatnr= -1;
- GMS.lastretval= 1;
+ GMS.lastmatnr = -1;
+ GMS.lastretval = 1;
if (GMS.gboundmat) {
if (GMS.backface_culling)
glDisable(GL_CULL_FACE);
if (GMS.is_alpha_pass) glDepthMask(0);
- GPU_material_unbind(GPU_material_from_blender(GMS.gscene, GMS.gboundmat));
- GMS.gboundmat= NULL;
+ GPU_material_unbind(GPU_material_from_blender(GMS.gscene, GMS.gboundmat, GMS.is_opensubdiv));
+ GMS.gboundmat = NULL;
}
GPU_set_material_alpha_blend(GPU_BLEND_SOLID);
@@ -1711,20 +1864,26 @@ bool GPU_material_use_matcaps_get(void)
return GMS.use_matcaps;
}
+bool GPU_object_materials_check(void)
+{
+ return GMS.is_enabled;
+}
void GPU_end_object_materials(void)
{
GPU_disable_material();
+ GMS.is_enabled = false;
+
if (GMS.matbuf && GMS.matbuf != GMS.matbuf_fixed) {
MEM_freeN(GMS.matbuf);
MEM_freeN(GMS.gmatbuf);
MEM_freeN(GMS.alphablend);
}
- GMS.matbuf= NULL;
- GMS.gmatbuf= NULL;
- GMS.alphablend= NULL;
+ GMS.matbuf = NULL;
+ GMS.gmatbuf = NULL;
+ GMS.alphablend = NULL;
/* resetting the texture matrix after the scaling needed for tiled textures */
if (GTS.tilemode) {
@@ -1742,57 +1901,57 @@ int GPU_default_lights(void)
int a, count = 0;
/* initialize */
- if (U.light[0].flag==0 && U.light[1].flag==0 && U.light[2].flag==0) {
- U.light[0].flag= 1;
- U.light[0].vec[0]= -0.3; U.light[0].vec[1]= 0.3; U.light[0].vec[2]= 0.9;
- U.light[0].col[0]= 0.8; U.light[0].col[1]= 0.8; U.light[0].col[2]= 0.8;
- U.light[0].spec[0]= 0.5; U.light[0].spec[1]= 0.5; U.light[0].spec[2]= 0.5;
- U.light[0].spec[3]= 1.0;
+ if (U.light[0].flag == 0 && U.light[1].flag == 0 && U.light[2].flag == 0) {
+ U.light[0].flag = 1;
+ U.light[0].vec[0] = -0.3; U.light[0].vec[1] = 0.3; U.light[0].vec[2] = 0.9;
+ U.light[0].col[0] = 0.8; U.light[0].col[1] = 0.8; U.light[0].col[2] = 0.8;
+ U.light[0].spec[0] = 0.5; U.light[0].spec[1] = 0.5; U.light[0].spec[2] = 0.5;
+ U.light[0].spec[3] = 1.0;
- U.light[1].flag= 0;
- U.light[1].vec[0]= 0.5; U.light[1].vec[1]= 0.5; U.light[1].vec[2]= 0.1;
- U.light[1].col[0]= 0.4; U.light[1].col[1]= 0.4; U.light[1].col[2]= 0.8;
- U.light[1].spec[0]= 0.3; U.light[1].spec[1]= 0.3; U.light[1].spec[2]= 0.5;
- U.light[1].spec[3]= 1.0;
+ U.light[1].flag = 0;
+ U.light[1].vec[0] = 0.5; U.light[1].vec[1] = 0.5; U.light[1].vec[2] = 0.1;
+ U.light[1].col[0] = 0.4; U.light[1].col[1] = 0.4; U.light[1].col[2] = 0.8;
+ U.light[1].spec[0] = 0.3; U.light[1].spec[1] = 0.3; U.light[1].spec[2] = 0.5;
+ U.light[1].spec[3] = 1.0;
- U.light[2].flag= 0;
- U.light[2].vec[0]= 0.3; U.light[2].vec[1]= -0.3; U.light[2].vec[2]= -0.2;
- U.light[2].col[0]= 0.8; U.light[2].col[1]= 0.5; U.light[2].col[2]= 0.4;
- U.light[2].spec[0]= 0.5; U.light[2].spec[1]= 0.4; U.light[2].spec[2]= 0.3;
- U.light[2].spec[3]= 1.0;
+ U.light[2].flag = 0;
+ U.light[2].vec[0] = 0.3; U.light[2].vec[1] = -0.3; U.light[2].vec[2] = -0.2;
+ U.light[2].col[0] = 0.8; U.light[2].col[1] = 0.5; U.light[2].col[2] = 0.4;
+ U.light[2].spec[0] = 0.5; U.light[2].spec[1] = 0.4; U.light[2].spec[2] = 0.3;
+ U.light[2].spec[3] = 1.0;
}
glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_FALSE);
- for (a=0; a<8; a++) {
- if (a<3) {
+ for (a = 0; a < 8; a++) {
+ if (a < 3) {
if (U.light[a].flag) {
- glEnable(GL_LIGHT0+a);
+ glEnable(GL_LIGHT0 + a);
normalize_v3_v3(position, U.light[a].vec);
- position[3]= 0.0f;
+ position[3] = 0.0f;
- glLightfv(GL_LIGHT0+a, GL_POSITION, position);
- glLightfv(GL_LIGHT0+a, GL_DIFFUSE, U.light[a].col);
- glLightfv(GL_LIGHT0+a, GL_SPECULAR, U.light[a].spec);
+ glLightfv(GL_LIGHT0 + a, GL_POSITION, position);
+ glLightfv(GL_LIGHT0 + a, GL_DIFFUSE, U.light[a].col);
+ glLightfv(GL_LIGHT0 + a, GL_SPECULAR, U.light[a].spec);
count++;
}
else {
- glDisable(GL_LIGHT0+a);
+ glDisable(GL_LIGHT0 + a);
- glLightfv(GL_LIGHT0+a, GL_POSITION, zero);
- glLightfv(GL_LIGHT0+a, GL_DIFFUSE, zero);
- glLightfv(GL_LIGHT0+a, GL_SPECULAR, zero);
+ glLightfv(GL_LIGHT0 + a, GL_POSITION, zero);
+ glLightfv(GL_LIGHT0 + a, GL_DIFFUSE, zero);
+ glLightfv(GL_LIGHT0 + a, GL_SPECULAR, zero);
}
- // clear stuff from other opengl lamp usage
- glLightf(GL_LIGHT0+a, GL_SPOT_CUTOFF, 180.0);
- glLightf(GL_LIGHT0+a, GL_CONSTANT_ATTENUATION, 1.0);
- glLightf(GL_LIGHT0+a, GL_LINEAR_ATTENUATION, 0.0);
+ /* clear stuff from other opengl lamp usage */
+ glLightf(GL_LIGHT0 + a, GL_SPOT_CUTOFF, 180.0);
+ glLightf(GL_LIGHT0 + a, GL_CONSTANT_ATTENUATION, 1.0);
+ glLightf(GL_LIGHT0 + a, GL_LINEAR_ATTENUATION, 0.0);
}
else
- glDisable(GL_LIGHT0+a);
+ glDisable(GL_LIGHT0 + a);
}
glDisable(GL_LIGHTING);
@@ -1810,74 +1969,105 @@ int GPU_scene_object_lights(Scene *scene, Object *ob, int lay, float viewmat[4][
float position[4], direction[4], energy[4];
/* disable all lights */
- for (count=0; count<8; count++)
- glDisable(GL_LIGHT0+count);
+ for (count = 0; count < 8; count++)
+ glDisable(GL_LIGHT0 + count);
- /* view direction for specular is not compute correct by default in
+ /* view direction for specular is not computed correct by default in
* opengl, so we set the settings ourselfs */
- glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, (ortho)? GL_FALSE: GL_TRUE);
+ glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, ortho ? GL_FALSE : GL_TRUE);
- count= 0;
-
- for (base=scene->base.first; base; base=base->next) {
- if (base->object->type!=OB_LAMP)
+ count = 0;
+
+ for (base = scene->base.first; base; base = base->next) {
+ if (base->object->type != OB_LAMP)
continue;
if (!(base->lay & lay) || !(base->lay & ob->lay))
continue;
- la= base->object->data;
+ la = base->object->data;
/* setup lamp transform */
glPushMatrix();
glLoadMatrixf((float *)viewmat);
- if (la->type==LA_SUN) {
+ if (la->type == LA_SUN) {
/* sun lamp */
copy_v3_v3(direction, base->object->obmat[2]);
- direction[3]= 0.0;
+ direction[3] = 0.0;
glLightfv(GL_LIGHT0+count, GL_POSITION, direction);
}
else {
/* other lamps with attenuation */
copy_v3_v3(position, base->object->obmat[3]);
- position[3]= 1.0f;
+ position[3] = 1.0f;
glLightfv(GL_LIGHT0+count, GL_POSITION, position);
glLightf(GL_LIGHT0+count, GL_CONSTANT_ATTENUATION, 1.0);
- glLightf(GL_LIGHT0+count, GL_LINEAR_ATTENUATION, la->att1/la->dist);
- glLightf(GL_LIGHT0+count, GL_QUADRATIC_ATTENUATION, la->att2/(la->dist*la->dist));
+ glLightf(GL_LIGHT0+count, GL_LINEAR_ATTENUATION, la->att1 / la->dist);
+ glLightf(GL_LIGHT0+count, GL_QUADRATIC_ATTENUATION, la->att2 / (la->dist * la->dist));
- if (la->type==LA_SPOT) {
+ if (la->type == LA_SPOT) {
/* 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, RAD2DEGF(la->spotsize * 0.5f));
- glLightf(GL_LIGHT0+count, GL_SPOT_EXPONENT, 128.0f*la->spotblend);
+ glLightfv(GL_LIGHT0 + count, GL_SPOT_DIRECTION, direction);
+ glLightf(GL_LIGHT0 + count, GL_SPOT_CUTOFF, RAD2DEGF(la->spotsize * 0.5f));
+ glLightf(GL_LIGHT0 + count, GL_SPOT_EXPONENT, 128.0f * la->spotblend);
}
else
- glLightf(GL_LIGHT0+count, GL_SPOT_CUTOFF, 180.0);
+ glLightf(GL_LIGHT0 + count, GL_SPOT_CUTOFF, 180.0);
}
/* setup energy */
mul_v3_v3fl(energy, &la->r, la->energy);
- energy[3]= 1.0;
+ energy[3] = 1.0;
- glLightfv(GL_LIGHT0+count, GL_DIFFUSE, energy);
- glLightfv(GL_LIGHT0+count, GL_SPECULAR, energy);
- glEnable(GL_LIGHT0+count);
+ glLightfv(GL_LIGHT0 + count, GL_DIFFUSE, energy);
+ glLightfv(GL_LIGHT0 + count, GL_SPECULAR, energy);
+ glEnable(GL_LIGHT0 + count);
glPopMatrix();
count++;
- if (count==8)
+ if (count == 8)
break;
}
return count;
}
+static void gpu_multisample(bool enable)
+{
+ if (GLEW_VERSION_1_3 || GLEW_ARB_multisample) {
+#ifdef __linux__
+ /* changing multisample from the default (enabled) causes problems on some
+ * systems (NVIDIA/Linux) when the pixel format doesn't have a multisample buffer */
+ bool toggle_ok = true;
+
+ if (GPU_type_matches(GPU_DEVICE_NVIDIA, GPU_OS_UNIX, GPU_DRIVER_ANY)) {
+ int samples = 0;
+ glGetIntegerv(GL_SAMPLES, &samples);
+
+ if (samples == 0)
+ toggle_ok = false;
+ }
+
+ if (toggle_ok) {
+ if (enable)
+ glEnable(GL_MULTISAMPLE);
+ else
+ glDisable(GL_MULTISAMPLE);
+ }
+#else
+ if (enable)
+ glEnable(GL_MULTISAMPLE);
+ else
+ glDisable(GL_MULTISAMPLE);
+#endif
+ }
+}
+
/* Default OpenGL State */
void GPU_state_init(void)
@@ -1886,8 +2076,8 @@ void GPU_state_init(void)
float mat_ambient[] = { 0.0, 0.0, 0.0, 0.0 };
float mat_specular[] = { 0.5, 0.5, 0.5, 1.0 };
int a, x, y;
- GLubyte pat[32*32];
- const GLubyte *patc= pat;
+ GLubyte pat[32 * 32];
+ const GLubyte *patc = pat;
glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, mat_ambient);
glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mat_specular);
@@ -1932,14 +2122,14 @@ void GPU_state_init(void)
glPixelTransferi(GL_DEPTH_SCALE, 1);
glDepthRange(0.0, 1.0);
- a= 0;
- for (x=0; x<32; x++) {
- for (y=0; y<4; y++) {
- if ( (x) & 1) pat[a++]= 0x88;
- else pat[a++]= 0x22;
+ a = 0;
+ for (x = 0; x < 32; x++) {
+ for (y = 0; y < 4; y++) {
+ if (x & 1) pat[a++] = 0x88;
+ else pat[a++] = 0x22;
}
}
-
+
glPolygonStipple(patc);
glMatrixMode(GL_TEXTURE);
@@ -1950,395 +2140,34 @@ void GPU_state_init(void)
glCullFace(GL_BACK);
glDisable(GL_CULL_FACE);
- /* calling this makes drawing very slow when AA is not set up in ghost
- * on Linux/NVIDIA. */
- // glDisable(GL_MULTISAMPLE);
+ gpu_multisample(false);
}
-#ifdef DEBUG
-/* debugging aid */
-static void gpu_state_print_fl_ex(const char *name, GLenum type)
+#ifdef WITH_OPENSUBDIV
+/* Update face-varying variables offset which might be
+ * different from mesh to mesh sharing the same material.
+ */
+void GPU_draw_update_fvar_offset(DerivedMesh *dm)
{
- const unsigned char err_mark[4] = {0xff, 0xff, 0xff, 0xff};
+ int i;
- float value[32];
- int a;
+ /* Sanity check to be sure we only do this for OpenSubdiv draw. */
+ BLI_assert(dm->type == DM_TYPE_CCGDM);
+ BLI_assert(GMS.is_opensubdiv);
- memset(value, 0xff, sizeof(value));
- glGetFloatv(type, value);
+ for (i = 0; i < GMS.totmat; ++i) {
+ Material *material = GMS.gmatbuf[i];
+ GPUMaterial *gpu_material;
- printf("%s: ", name);
- for (a = 0; a < 32; a++) {
- if (memcmp(&value[a], err_mark, sizeof(value[a])) == 0) {
- break;
+ if (material == NULL) {
+ continue;
}
- printf("%.2f ", value[a]);
- }
- printf("\n");
-}
-#define gpu_state_print_fl(val) gpu_state_print_fl_ex(#val, val)
+ gpu_material = GPU_material_from_blender(GMS.gscene,
+ material,
+ GMS.is_opensubdiv);
-void GPU_state_print(void)
-{
- gpu_state_print_fl(GL_ACCUM_ALPHA_BITS);
- gpu_state_print_fl(GL_ACCUM_BLUE_BITS);
- gpu_state_print_fl(GL_ACCUM_CLEAR_VALUE);
- gpu_state_print_fl(GL_ACCUM_GREEN_BITS);
- gpu_state_print_fl(GL_ACCUM_RED_BITS);
- gpu_state_print_fl(GL_ACTIVE_TEXTURE);
- gpu_state_print_fl(GL_ALIASED_LINE_WIDTH_RANGE);
- gpu_state_print_fl(GL_ALIASED_POINT_SIZE_RANGE);
- gpu_state_print_fl(GL_ALPHA_BIAS);
- gpu_state_print_fl(GL_ALPHA_BITS);
- gpu_state_print_fl(GL_ALPHA_SCALE);
- gpu_state_print_fl(GL_ALPHA_TEST);
- gpu_state_print_fl(GL_ALPHA_TEST_FUNC);
- gpu_state_print_fl(GL_ALPHA_TEST_REF);
- gpu_state_print_fl(GL_ARRAY_BUFFER_BINDING);
- gpu_state_print_fl(GL_ATTRIB_STACK_DEPTH);
- gpu_state_print_fl(GL_AUTO_NORMAL);
- gpu_state_print_fl(GL_AUX_BUFFERS);
- gpu_state_print_fl(GL_BLEND);
- gpu_state_print_fl(GL_BLEND_COLOR);
- gpu_state_print_fl(GL_BLEND_DST_ALPHA);
- gpu_state_print_fl(GL_BLEND_DST_RGB);
- gpu_state_print_fl(GL_BLEND_EQUATION_ALPHA);
- gpu_state_print_fl(GL_BLEND_EQUATION_RGB);
- gpu_state_print_fl(GL_BLEND_SRC_ALPHA);
- gpu_state_print_fl(GL_BLEND_SRC_RGB);
- gpu_state_print_fl(GL_BLUE_BIAS);
- gpu_state_print_fl(GL_BLUE_BITS);
- gpu_state_print_fl(GL_BLUE_SCALE);
- gpu_state_print_fl(GL_CLIENT_ACTIVE_TEXTURE);
- gpu_state_print_fl(GL_CLIENT_ATTRIB_STACK_DEPTH);
- gpu_state_print_fl(GL_CLIP_PLANE0);
- gpu_state_print_fl(GL_COLOR_ARRAY);
- gpu_state_print_fl(GL_COLOR_ARRAY_BUFFER_BINDING);
- gpu_state_print_fl(GL_COLOR_ARRAY_SIZE);
- gpu_state_print_fl(GL_COLOR_ARRAY_STRIDE);
- gpu_state_print_fl(GL_COLOR_ARRAY_TYPE);
- gpu_state_print_fl(GL_COLOR_CLEAR_VALUE);
- gpu_state_print_fl(GL_COLOR_LOGIC_OP);
- gpu_state_print_fl(GL_COLOR_MATERIAL);
- gpu_state_print_fl(GL_COLOR_MATERIAL_FACE);
- gpu_state_print_fl(GL_COLOR_MATERIAL_PARAMETER);
- gpu_state_print_fl(GL_COLOR_MATRIX);
- gpu_state_print_fl(GL_COLOR_MATRIX_STACK_DEPTH);
- gpu_state_print_fl(GL_COLOR_SUM);
- gpu_state_print_fl(GL_COLOR_TABLE);
- gpu_state_print_fl(GL_COLOR_WRITEMASK);
- gpu_state_print_fl(GL_COMPRESSED_TEXTURE_FORMATS);
- gpu_state_print_fl(GL_CONVOLUTION_1D);
- gpu_state_print_fl(GL_CONVOLUTION_2D);
- gpu_state_print_fl(GL_CULL_FACE);
- gpu_state_print_fl(GL_CULL_FACE_MODE);
- gpu_state_print_fl(GL_CURRENT_COLOR);
- gpu_state_print_fl(GL_CURRENT_FOG_COORD);
- gpu_state_print_fl(GL_CURRENT_INDEX);
- gpu_state_print_fl(GL_CURRENT_NORMAL);
- gpu_state_print_fl(GL_CURRENT_PROGRAM);
- gpu_state_print_fl(GL_CURRENT_RASTER_COLOR);
- gpu_state_print_fl(GL_CURRENT_RASTER_DISTANCE);
- gpu_state_print_fl(GL_CURRENT_RASTER_INDEX);
- gpu_state_print_fl(GL_CURRENT_RASTER_POSITION);
- gpu_state_print_fl(GL_CURRENT_RASTER_POSITION_VALID);
- gpu_state_print_fl(GL_CURRENT_RASTER_SECONDARY_COLOR);
- gpu_state_print_fl(GL_CURRENT_RASTER_TEXTURE_COORDS);
- gpu_state_print_fl(GL_CURRENT_SECONDARY_COLOR);
- gpu_state_print_fl(GL_CURRENT_TEXTURE_COORDS);
- gpu_state_print_fl(GL_DEPTH_BIAS);
- gpu_state_print_fl(GL_DEPTH_BITS);
- gpu_state_print_fl(GL_DEPTH_CLEAR_VALUE);
- gpu_state_print_fl(GL_DEPTH_FUNC);
- gpu_state_print_fl(GL_DEPTH_RANGE);
- gpu_state_print_fl(GL_DEPTH_SCALE);
- gpu_state_print_fl(GL_DEPTH_TEST);
- gpu_state_print_fl(GL_DEPTH_WRITEMASK);
- gpu_state_print_fl(GL_DITHER);
- gpu_state_print_fl(GL_DOUBLEBUFFER);
- gpu_state_print_fl(GL_DRAW_BUFFER);
- gpu_state_print_fl(GL_DRAW_BUFFER0);
- gpu_state_print_fl(GL_EDGE_FLAG);
- gpu_state_print_fl(GL_EDGE_FLAG_ARRAY);
- gpu_state_print_fl(GL_EDGE_FLAG_ARRAY_BUFFER_BINDING);
- gpu_state_print_fl(GL_EDGE_FLAG_ARRAY_STRIDE);
- gpu_state_print_fl(GL_ELEMENT_ARRAY_BUFFER_BINDING);
- gpu_state_print_fl(GL_FEEDBACK_BUFFER_SIZE);
- gpu_state_print_fl(GL_FEEDBACK_BUFFER_TYPE);
- gpu_state_print_fl(GL_FOG);
- gpu_state_print_fl(GL_FOG_COLOR);
- gpu_state_print_fl(GL_FOG_COORD_ARRAY);
- gpu_state_print_fl(GL_FOG_COORD_ARRAY_BUFFER_BINDING);
- gpu_state_print_fl(GL_FOG_COORD_ARRAY_STRIDE);
- gpu_state_print_fl(GL_FOG_COORD_ARRAY_TYPE);
- gpu_state_print_fl(GL_FOG_COORD_SRC);
- gpu_state_print_fl(GL_FOG_DENSITY);
- gpu_state_print_fl(GL_FOG_END);
- gpu_state_print_fl(GL_FOG_HINT);
- gpu_state_print_fl(GL_FOG_INDEX);
- gpu_state_print_fl(GL_FOG_MODE);
- gpu_state_print_fl(GL_FOG_START);
- gpu_state_print_fl(GL_FRAGMENT_PROGRAM_ARB);
- gpu_state_print_fl(GL_FRAGMENT_SHADER_DERIVATIVE_HINT);
- gpu_state_print_fl(GL_FRONT_FACE);
- gpu_state_print_fl(GL_GENERATE_MIPMAP_HINT);
- gpu_state_print_fl(GL_GREEN_BIAS);
- gpu_state_print_fl(GL_GREEN_BITS);
- gpu_state_print_fl(GL_GREEN_SCALE);
- gpu_state_print_fl(GL_HISTOGRAM);
- gpu_state_print_fl(GL_INDEX_ARRAY);
- gpu_state_print_fl(GL_INDEX_ARRAY_BUFFER_BINDING);
- gpu_state_print_fl(GL_INDEX_ARRAY_STRIDE);
- gpu_state_print_fl(GL_INDEX_ARRAY_TYPE);
- gpu_state_print_fl(GL_INDEX_BITS);
- gpu_state_print_fl(GL_INDEX_CLEAR_VALUE);
- gpu_state_print_fl(GL_INDEX_LOGIC_OP);
- gpu_state_print_fl(GL_INDEX_MODE);
- gpu_state_print_fl(GL_INDEX_OFFSET);
- gpu_state_print_fl(GL_INDEX_SHIFT);
- gpu_state_print_fl(GL_INDEX_WRITEMASK);
- gpu_state_print_fl(GL_LIGHT0);
- gpu_state_print_fl(GL_LIGHT1);
- gpu_state_print_fl(GL_LIGHT2);
- gpu_state_print_fl(GL_LIGHT3);
- gpu_state_print_fl(GL_LIGHT4);
- gpu_state_print_fl(GL_LIGHT5);
- gpu_state_print_fl(GL_LIGHT6);
- gpu_state_print_fl(GL_LIGHT7);
- gpu_state_print_fl(GL_LIGHTING);
- gpu_state_print_fl(GL_LIGHT_MODEL_AMBIENT);
- gpu_state_print_fl(GL_LIGHT_MODEL_COLOR_CONTROL);
- gpu_state_print_fl(GL_LIGHT_MODEL_LOCAL_VIEWER);
- gpu_state_print_fl(GL_LIGHT_MODEL_TWO_SIDE);
- gpu_state_print_fl(GL_LINE_SMOOTH);
- gpu_state_print_fl(GL_LINE_SMOOTH_HINT);
- gpu_state_print_fl(GL_LINE_STIPPLE);
- gpu_state_print_fl(GL_LINE_STIPPLE_PATTERN);
- gpu_state_print_fl(GL_LINE_STIPPLE_REPEAT);
- gpu_state_print_fl(GL_LINE_WIDTH);
- gpu_state_print_fl(GL_LINE_WIDTH_GRANULARITY);
- gpu_state_print_fl(GL_LINE_WIDTH_RANGE);
- gpu_state_print_fl(GL_LIST_BASE);
- gpu_state_print_fl(GL_LIST_INDEX);
- gpu_state_print_fl(GL_LIST_MODE);
- gpu_state_print_fl(GL_LOGIC_OP);
- gpu_state_print_fl(GL_LOGIC_OP_MODE);
- gpu_state_print_fl(GL_MAP1_COLOR_4);
- gpu_state_print_fl(GL_MAP1_GRID_DOMAIN);
- gpu_state_print_fl(GL_MAP1_GRID_SEGMENTS);
- gpu_state_print_fl(GL_MAP1_INDEX);
- gpu_state_print_fl(GL_MAP1_NORMAL);
- gpu_state_print_fl(GL_MAP1_TEXTURE_COORD_1);
- gpu_state_print_fl(GL_MAP1_TEXTURE_COORD_2);
- gpu_state_print_fl(GL_MAP1_TEXTURE_COORD_3);
- gpu_state_print_fl(GL_MAP1_TEXTURE_COORD_4);
- gpu_state_print_fl(GL_MAP1_VERTEX_3);
- gpu_state_print_fl(GL_MAP1_VERTEX_4);
- gpu_state_print_fl(GL_MAP2_COLOR_4);
- gpu_state_print_fl(GL_MAP2_GRID_DOMAIN);
- gpu_state_print_fl(GL_MAP2_GRID_SEGMENTS);
- gpu_state_print_fl(GL_MAP2_INDEX);
- gpu_state_print_fl(GL_MAP2_NORMAL);
- gpu_state_print_fl(GL_MAP2_TEXTURE_COORD_1);
- gpu_state_print_fl(GL_MAP2_TEXTURE_COORD_2);
- gpu_state_print_fl(GL_MAP2_TEXTURE_COORD_3);
- gpu_state_print_fl(GL_MAP2_TEXTURE_COORD_4);
- gpu_state_print_fl(GL_MAP2_VERTEX_3);
- gpu_state_print_fl(GL_MAP2_VERTEX_4);
- gpu_state_print_fl(GL_MAP_COLOR);
- gpu_state_print_fl(GL_MAP_STENCIL);
- gpu_state_print_fl(GL_MATRIX_MODE);
- gpu_state_print_fl(GL_MAX_3D_TEXTURE_SIZE);
- gpu_state_print_fl(GL_MAX_ATTRIB_STACK_DEPTH);
- gpu_state_print_fl(GL_MAX_CLIENT_ATTRIB_STACK_DEPTH);
- gpu_state_print_fl(GL_MAX_CLIP_PLANES);
- gpu_state_print_fl(GL_MAX_COLOR_MATRIX_STACK_DEPTH);
- gpu_state_print_fl(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS);
- gpu_state_print_fl(GL_MAX_CUBE_MAP_TEXTURE_SIZE);
- gpu_state_print_fl(GL_MAX_DRAW_BUFFERS);
- gpu_state_print_fl(GL_MAX_ELEMENTS_INDICES);
- gpu_state_print_fl(GL_MAX_ELEMENTS_VERTICES);
- gpu_state_print_fl(GL_MAX_EVAL_ORDER);
- gpu_state_print_fl(GL_MAX_FRAGMENT_UNIFORM_COMPONENTS);
- gpu_state_print_fl(GL_MAX_LIGHTS);
- gpu_state_print_fl(GL_MAX_LIST_NESTING);
- gpu_state_print_fl(GL_MAX_MODELVIEW_STACK_DEPTH);
- gpu_state_print_fl(GL_MAX_NAME_STACK_DEPTH);
- gpu_state_print_fl(GL_MAX_PIXEL_MAP_TABLE);
- gpu_state_print_fl(GL_MAX_PROJECTION_STACK_DEPTH);
- gpu_state_print_fl(GL_MAX_TEXTURE_COORDS);
- gpu_state_print_fl(GL_MAX_TEXTURE_IMAGE_UNITS);
- gpu_state_print_fl(GL_MAX_TEXTURE_LOD_BIAS);
- gpu_state_print_fl(GL_MAX_TEXTURE_SIZE);
- gpu_state_print_fl(GL_MAX_TEXTURE_STACK_DEPTH);
- gpu_state_print_fl(GL_MAX_TEXTURE_UNITS);
- gpu_state_print_fl(GL_MAX_VARYING_FLOATS);
- gpu_state_print_fl(GL_MAX_VERTEX_ATTRIBS);
- gpu_state_print_fl(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS);
- gpu_state_print_fl(GL_MAX_VERTEX_UNIFORM_COMPONENTS);
- gpu_state_print_fl(GL_MAX_VIEWPORT_DIMS);
- gpu_state_print_fl(GL_MINMAX);
- gpu_state_print_fl(GL_MODELVIEW_MATRIX);
- gpu_state_print_fl(GL_MODELVIEW_STACK_DEPTH);
- gpu_state_print_fl(GL_MULTISAMPLE);
- gpu_state_print_fl(GL_MULTISAMPLE_ARB);
- gpu_state_print_fl(GL_NAME_STACK_DEPTH);
- gpu_state_print_fl(GL_NORMALIZE);
- gpu_state_print_fl(GL_NORMAL_ARRAY);
- gpu_state_print_fl(GL_NORMAL_ARRAY_BUFFER_BINDING);
- gpu_state_print_fl(GL_NORMAL_ARRAY_STRIDE);
- gpu_state_print_fl(GL_NORMAL_ARRAY_TYPE);
- gpu_state_print_fl(GL_NUM_COMPRESSED_TEXTURE_FORMATS);
- gpu_state_print_fl(GL_PACK_ALIGNMENT);
- gpu_state_print_fl(GL_PACK_IMAGE_HEIGHT);
- gpu_state_print_fl(GL_PACK_LSB_FIRST);
- gpu_state_print_fl(GL_PACK_ROW_LENGTH);
- gpu_state_print_fl(GL_PACK_SKIP_IMAGES);
- gpu_state_print_fl(GL_PACK_SKIP_PIXELS);
- gpu_state_print_fl(GL_PACK_SKIP_ROWS);
- gpu_state_print_fl(GL_PACK_SWAP_BYTES);
- gpu_state_print_fl(GL_PERSPECTIVE_CORRECTION_HINT);
- gpu_state_print_fl(GL_PIXEL_MAP_A_TO_A_SIZE);
- gpu_state_print_fl(GL_PIXEL_MAP_B_TO_B_SIZE);
- gpu_state_print_fl(GL_PIXEL_MAP_G_TO_G_SIZE);
- gpu_state_print_fl(GL_PIXEL_MAP_I_TO_A_SIZE);
- gpu_state_print_fl(GL_PIXEL_MAP_I_TO_B_SIZE);
- gpu_state_print_fl(GL_PIXEL_MAP_I_TO_G_SIZE);
- gpu_state_print_fl(GL_PIXEL_MAP_I_TO_I_SIZE);
- gpu_state_print_fl(GL_PIXEL_MAP_I_TO_R_SIZE);
- gpu_state_print_fl(GL_PIXEL_MAP_R_TO_R_SIZE);
- gpu_state_print_fl(GL_PIXEL_MAP_S_TO_S_SIZE);
- gpu_state_print_fl(GL_PIXEL_PACK_BUFFER_BINDING);
- gpu_state_print_fl(GL_PIXEL_UNPACK_BUFFER_BINDING);
- gpu_state_print_fl(GL_POINT_DISTANCE_ATTENUATION);
- gpu_state_print_fl(GL_POINT_FADE_THRESHOLD_SIZE);
- gpu_state_print_fl(GL_POINT_SIZE);
- gpu_state_print_fl(GL_POINT_SIZE_GRANULARITY);
- gpu_state_print_fl(GL_POINT_SIZE_MAX);
- gpu_state_print_fl(GL_POINT_SIZE_MIN);
- gpu_state_print_fl(GL_POINT_SIZE_RANGE);
- gpu_state_print_fl(GL_POINT_SMOOTH);
- gpu_state_print_fl(GL_POINT_SMOOTH_HINT);
- gpu_state_print_fl(GL_POINT_SPRITE);
- gpu_state_print_fl(GL_POLYGON_MODE);
- gpu_state_print_fl(GL_POLYGON_OFFSET_FACTOR);
- gpu_state_print_fl(GL_POLYGON_OFFSET_FILL);
- gpu_state_print_fl(GL_POLYGON_OFFSET_LINE);
- gpu_state_print_fl(GL_POLYGON_OFFSET_POINT);
- gpu_state_print_fl(GL_POLYGON_OFFSET_UNITS);
- gpu_state_print_fl(GL_POLYGON_SMOOTH);
- gpu_state_print_fl(GL_POLYGON_SMOOTH_HINT);
- gpu_state_print_fl(GL_POLYGON_STIPPLE);
- gpu_state_print_fl(GL_POST_COLOR_MATRIX_ALPHA_BIAS);
- gpu_state_print_fl(GL_POST_COLOR_MATRIX_ALPHA_SCALE);
- gpu_state_print_fl(GL_POST_COLOR_MATRIX_BLUE_BIAS);
- gpu_state_print_fl(GL_POST_COLOR_MATRIX_BLUE_SCALE);
- gpu_state_print_fl(GL_POST_COLOR_MATRIX_COLOR_TABLE);
- gpu_state_print_fl(GL_POST_COLOR_MATRIX_GREEN_BIAS);
- gpu_state_print_fl(GL_POST_COLOR_MATRIX_GREEN_SCALE);
- gpu_state_print_fl(GL_POST_COLOR_MATRIX_RED_BIAS);
- gpu_state_print_fl(GL_POST_COLOR_MATRIX_RED_SCALE);
- gpu_state_print_fl(GL_POST_CONVOLUTION_ALPHA_BIAS);
- gpu_state_print_fl(GL_POST_CONVOLUTION_ALPHA_SCALE);
- gpu_state_print_fl(GL_POST_CONVOLUTION_BLUE_BIAS);
- gpu_state_print_fl(GL_POST_CONVOLUTION_BLUE_SCALE);
- gpu_state_print_fl(GL_POST_CONVOLUTION_COLOR_TABLE);
- gpu_state_print_fl(GL_POST_CONVOLUTION_GREEN_BIAS);
- gpu_state_print_fl(GL_POST_CONVOLUTION_GREEN_SCALE);
- gpu_state_print_fl(GL_POST_CONVOLUTION_RED_BIAS);
- gpu_state_print_fl(GL_POST_CONVOLUTION_RED_SCALE);
- gpu_state_print_fl(GL_PROJECTION_MATRIX);
- gpu_state_print_fl(GL_PROJECTION_STACK_DEPTH);
- gpu_state_print_fl(GL_READ_BUFFER);
- gpu_state_print_fl(GL_RED_BIAS);
- gpu_state_print_fl(GL_RED_BITS);
- gpu_state_print_fl(GL_RED_SCALE);
- gpu_state_print_fl(GL_RENDER_MODE);
- gpu_state_print_fl(GL_RESCALE_NORMAL);
- gpu_state_print_fl(GL_RGBA_MODE);
- gpu_state_print_fl(GL_SAMPLES);
- gpu_state_print_fl(GL_SAMPLE_BUFFERS);
- gpu_state_print_fl(GL_SAMPLE_COVERAGE_INVERT);
- gpu_state_print_fl(GL_SAMPLE_COVERAGE_VALUE);
- gpu_state_print_fl(GL_SCISSOR_BOX);
- gpu_state_print_fl(GL_SCISSOR_TEST);
- gpu_state_print_fl(GL_SECONDARY_COLOR_ARRAY);
- gpu_state_print_fl(GL_SECONDARY_COLOR_ARRAY_BUFFER_BINDING);
- gpu_state_print_fl(GL_SECONDARY_COLOR_ARRAY_SIZE);
- gpu_state_print_fl(GL_SECONDARY_COLOR_ARRAY_STRIDE);
- gpu_state_print_fl(GL_SECONDARY_COLOR_ARRAY_TYPE);
- gpu_state_print_fl(GL_SELECTION_BUFFER_SIZE);
- gpu_state_print_fl(GL_SEPARABLE_2D);
- gpu_state_print_fl(GL_SHADE_MODEL);
- gpu_state_print_fl(GL_SMOOTH_LINE_WIDTH_GRANULARITY);
- gpu_state_print_fl(GL_SMOOTH_LINE_WIDTH_RANGE);
- gpu_state_print_fl(GL_SMOOTH_POINT_SIZE_GRANULARITY);
- gpu_state_print_fl(GL_SMOOTH_POINT_SIZE_RANGE);
- gpu_state_print_fl(GL_STENCIL_BACK_FAIL);
- gpu_state_print_fl(GL_STENCIL_BACK_FUNC);
- gpu_state_print_fl(GL_STENCIL_BACK_PASS_DEPTH_FAIL);
- gpu_state_print_fl(GL_STENCIL_BACK_PASS_DEPTH_PASS);
- gpu_state_print_fl(GL_STENCIL_BACK_REF);
- gpu_state_print_fl(GL_STENCIL_BACK_VALUE_MASK);
- gpu_state_print_fl(GL_STENCIL_BACK_WRITEMASK);
- gpu_state_print_fl(GL_STENCIL_BITS);
- gpu_state_print_fl(GL_STENCIL_CLEAR_VALUE);
- gpu_state_print_fl(GL_STENCIL_FAIL);
- gpu_state_print_fl(GL_STENCIL_FUNC);
- gpu_state_print_fl(GL_STENCIL_PASS_DEPTH_FAIL);
- gpu_state_print_fl(GL_STENCIL_PASS_DEPTH_PASS);
- gpu_state_print_fl(GL_STENCIL_REF);
- gpu_state_print_fl(GL_STENCIL_TEST);
- gpu_state_print_fl(GL_STENCIL_VALUE_MASK);
- gpu_state_print_fl(GL_STENCIL_WRITEMASK);
- gpu_state_print_fl(GL_STEREO);
- gpu_state_print_fl(GL_SUBPIXEL_BITS);
- gpu_state_print_fl(GL_TEXTURE_1D);
- gpu_state_print_fl(GL_TEXTURE_2D);
- gpu_state_print_fl(GL_TEXTURE_3D);
- gpu_state_print_fl(GL_TEXTURE_BINDING_1D);
- gpu_state_print_fl(GL_TEXTURE_BINDING_2D);
- gpu_state_print_fl(GL_TEXTURE_BINDING_3D);
- gpu_state_print_fl(GL_TEXTURE_BINDING_CUBE_MAP);
- gpu_state_print_fl(GL_TEXTURE_COMPRESSION_HINT);
- gpu_state_print_fl(GL_TEXTURE_COORD_ARRAY);
- gpu_state_print_fl(GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING);
- gpu_state_print_fl(GL_TEXTURE_COORD_ARRAY_SIZE);
- gpu_state_print_fl(GL_TEXTURE_COORD_ARRAY_STRIDE);
- gpu_state_print_fl(GL_TEXTURE_COORD_ARRAY_TYPE);
- gpu_state_print_fl(GL_TEXTURE_CUBE_MAP);
- gpu_state_print_fl(GL_TEXTURE_CUBE_MAP_ARB);
- gpu_state_print_fl(GL_TEXTURE_GEN_Q);
- gpu_state_print_fl(GL_TEXTURE_GEN_R);
- gpu_state_print_fl(GL_TEXTURE_GEN_S);
- gpu_state_print_fl(GL_TEXTURE_GEN_T);
- gpu_state_print_fl(GL_TEXTURE_MATRIX);
- gpu_state_print_fl(GL_TEXTURE_STACK_DEPTH);
- gpu_state_print_fl(GL_TRANSPOSE_COLOR_MATRIX);
- gpu_state_print_fl(GL_TRANSPOSE_MODELVIEW_MATRIX);
- gpu_state_print_fl(GL_TRANSPOSE_PROJECTION_MATRIX);
- gpu_state_print_fl(GL_TRANSPOSE_TEXTURE_MATRIX);
- gpu_state_print_fl(GL_UNPACK_ALIGNMENT);
- gpu_state_print_fl(GL_UNPACK_IMAGE_HEIGHT);
- gpu_state_print_fl(GL_UNPACK_LSB_FIRST);
- gpu_state_print_fl(GL_UNPACK_ROW_LENGTH);
- gpu_state_print_fl(GL_UNPACK_SKIP_IMAGES);
- gpu_state_print_fl(GL_UNPACK_SKIP_PIXELS);
- gpu_state_print_fl(GL_UNPACK_SKIP_ROWS);
- gpu_state_print_fl(GL_UNPACK_SWAP_BYTES);
- gpu_state_print_fl(GL_VERTEX_ARRAY);
- gpu_state_print_fl(GL_VERTEX_ARRAY_BUFFER_BINDING);
- gpu_state_print_fl(GL_VERTEX_ARRAY_SIZE);
- gpu_state_print_fl(GL_VERTEX_ARRAY_STRIDE);
- gpu_state_print_fl(GL_VERTEX_ARRAY_TYPE);
- gpu_state_print_fl(GL_VERTEX_PROGRAM_POINT_SIZE);
- gpu_state_print_fl(GL_VERTEX_PROGRAM_TWO_SIDE);
- gpu_state_print_fl(GL_VIEWPORT);
- gpu_state_print_fl(GL_ZOOM_X);
- gpu_state_print_fl(GL_ZOOM_Y);
+ GPU_material_update_fvar_offset(gpu_material, dm);
+ }
}
-
-#undef gpu_state_print_fl
-
#endif
diff --git a/source/blender/gpu/intern/gpu_extensions.c b/source/blender/gpu/intern/gpu_extensions.c
index 17c495c82d6..e30eeebf934 100644
--- a/source/blender/gpu/intern/gpu_extensions.c
+++ b/source/blender/gpu/intern/gpu_extensions.c
@@ -33,8 +33,6 @@
*/
-#include "GL/glew.h"
-
#include "DNA_image_types.h"
#include "MEM_guardedalloc.h"
@@ -42,13 +40,18 @@
#include "BLI_blenlib.h"
#include "BLI_utildefines.h"
#include "BLI_math_base.h"
+#include "BLI_math_vector.h"
#include "BKE_global.h"
+#include "GPU_glew.h"
+#include "GPU_debug.h"
#include "GPU_draw.h"
#include "GPU_extensions.h"
+#include "GPU_compositing.h"
#include "GPU_simple_shader.h"
-#include "gpu_codegen.h"
+
+#include "intern/gpu_private.h"
#include <stdlib.h>
#include <stdio.h>
@@ -58,7 +61,9 @@
# include "BLI_winstuff.h"
#endif
-#define MAX_DEFINE_LENGTH 72
+/* TODO(sergey): Find better default values for this constants. */
+#define MAX_DEFINE_LENGTH 1024
+#define MAX_EXT_DEFINE_LENGTH 1024
/* Extensions support */
@@ -73,14 +78,29 @@
*/
/* Non-generated shaders */
+extern char datatoc_gpu_program_smoke_frag_glsl[];
+extern char datatoc_gpu_program_smoke_color_frag_glsl[];
extern char datatoc_gpu_shader_vsm_store_vert_glsl[];
extern char datatoc_gpu_shader_vsm_store_frag_glsl[];
extern char datatoc_gpu_shader_sep_gaussian_blur_vert_glsl[];
extern char datatoc_gpu_shader_sep_gaussian_blur_frag_glsl[];
+extern char datatoc_gpu_shader_fx_vert_glsl[];
+extern char datatoc_gpu_shader_fx_ssao_frag_glsl[];
+extern char datatoc_gpu_shader_fx_dof_frag_glsl[];
+extern char datatoc_gpu_shader_fx_dof_vert_glsl[];
+extern char datatoc_gpu_shader_fx_dof_hq_frag_glsl[];
+extern char datatoc_gpu_shader_fx_dof_hq_vert_glsl[];
+extern char datatoc_gpu_shader_fx_dof_hq_geo_glsl[];
+extern char datatoc_gpu_shader_fx_depth_resolve_glsl[];
+extern char datatoc_gpu_shader_fx_lib_glsl[];
typedef struct GPUShaders {
GPUShader *vsm_store;
GPUShader *sep_gaussian_blur;
+ GPUProgram *smoke;
+ GPUProgram *smoke_colored;
+ /* cache for shader fx. Those can exist in combinations so store them here */
+ GPUShader *fx_shaders[MAX_FX_SHADERS * 2];
} GPUShaders;
static struct GPUGlobal {
@@ -99,19 +119,30 @@ static struct GPUGlobal {
GPUTexture *invalid_tex_1D; /* texture used in place of invalid textures (not loaded correctly, missing) */
GPUTexture *invalid_tex_2D;
GPUTexture *invalid_tex_3D;
+ float dfdyfactors[2]; /* workaround for different calculation of dfdy factors on GPUs. Some GPUs/drivers
+ calculate dfdy in shader differently when drawing to an offscreen buffer. First
+ number is factor on screen and second is off-screen */
} GG = {1, 0};
+/* Number of maximum output slots. We support 4 outputs for now (usually we wouldn't need more to preserve fill rate) */
+#define GPU_FB_MAX_SLOTS 4
+
+struct GPUFrameBuffer {
+ GLuint object;
+ GPUTexture *colortex[GPU_FB_MAX_SLOTS];
+ GPUTexture *depthtex;
+};
+
+
/* GPU Types */
-int GPU_type_matches(GPUDeviceType device, GPUOSType os, GPUDriverType driver)
+bool GPU_type_matches(GPUDeviceType device, GPUOSType os, GPUDriverType driver)
{
return (GG.device & device) && (GG.os & os) && (GG.driver & driver);
}
/* GPU Extensions */
-static int gpu_extensions_init = 0;
-
void GPU_extensions_disable(void)
{
GG.extdisabled = 1;
@@ -122,17 +153,15 @@ int GPU_max_texture_size(void)
return GG.maxtexsize;
}
-void GPU_extensions_init(void)
+void GPU_get_dfdy_factors(float fac[2])
{
- GLint r, g, b;
- const char *vendor, *renderer;
-
- /* can't avoid calling this multiple times, see wm_window_add_ghostwindow */
- if (gpu_extensions_init) return;
- gpu_extensions_init= 1;
+ copy_v2_v2(fac, GG.dfdyfactors);
+}
- glewInit();
- GPU_codegen_init();
+void gpu_extensions_init(void)
+{
+ GLint r, g, b;
+ const char *vendor, *renderer, *version;
/* glewIsSupported("GL_VERSION_2_0") */
@@ -149,10 +178,11 @@ void GPU_extensions_init(void)
glGetIntegerv(GL_RED_BITS, &r);
glGetIntegerv(GL_GREEN_BITS, &g);
glGetIntegerv(GL_BLUE_BITS, &b);
- GG.colordepth = r+g+b; /* assumes same depth for RGB */
+ GG.colordepth = r + g + b; /* assumes same depth for RGB */
vendor = (const char *)glGetString(GL_VENDOR);
renderer = (const char *)glGetString(GL_RENDERER);
+ version = (const char *)glGetString(GL_VERSION);
if (strstr(vendor, "ATI")) {
GG.device = GPU_DEVICE_ATI;
@@ -229,85 +259,110 @@ void GPU_extensions_init(void)
#endif
+ /* df/dy calculation factors, those are dependent on driver */
+ if ((strstr(vendor, "ATI") && strstr(version, "3.3.10750"))) {
+ GG.dfdyfactors[0] = 1.0;
+ GG.dfdyfactors[1] = -1.0;
+ }
+ else if (GG.device == GPU_DEVICE_INTEL && GG.os == GPU_OS_WIN &&
+ (strstr(version, "4.0.0 - Build 10.18.10.3308") ||
+ strstr(version, "4.0.0 - Build 9.18.10.3186") ||
+ strstr(version, "4.0.0 - Build 9.18.10.3165") ||
+ strstr(version, "3.1.0 - Build 9.17.10.3347") ||
+ strstr(version, "3.1.0 - Build 9.17.10.4101")))
+ {
+ GG.dfdyfactors[0] = -1.0;
+ GG.dfdyfactors[1] = 1.0;
+ }
+ else {
+ GG.dfdyfactors[0] = 1.0;
+ GG.dfdyfactors[1] = 1.0;
+ }
+
+
GPU_invalid_tex_init();
GPU_simple_shaders_init();
}
-void GPU_extensions_exit(void)
+void gpu_extensions_exit(void)
{
- gpu_extensions_init = 0;
- GPU_codegen_exit();
GPU_simple_shaders_exit();
GPU_invalid_tex_free();
}
-int GPU_glsl_support(void)
+bool GPU_glsl_support(void)
{
return !GG.extdisabled && GG.glslsupport;
}
-int GPU_non_power_of_two_support(void)
+bool GPU_non_power_of_two_support(void)
{
if (GG.npotdisabled)
- return 0;
+ return false;
return GLEW_ARB_texture_non_power_of_two;
}
-int GPU_display_list_support(void)
+bool GPU_vertex_buffer_support(void)
+{
+ return GLEW_ARB_vertex_buffer_object || GLEW_VERSION_1_5;
+}
+
+bool GPU_display_list_support(void)
{
return !GG.dlistsdisabled;
}
-int GPU_color_depth(void)
+bool GPU_bicubic_bump_support(void)
{
- return GG.colordepth;
+ return GLEW_ARB_texture_query_lod && GLEW_VERSION_3_0;
}
-int GPU_print_error(const char *str)
+bool GPU_geometry_shader_support(void)
{
- GLenum errCode;
+ return GLEW_EXT_geometry_shader4 || GLEW_VERSION_3_2;
+}
- if (G.debug & G_DEBUG) {
- if ((errCode = glGetError()) != GL_NO_ERROR) {
- fprintf(stderr, "%s opengl error: %s\n", str, gluErrorString(errCode));
- return 1;
- }
- }
+bool GPU_instanced_drawing_support(void)
+{
+ return GLEW_ARB_draw_instanced;
+}
- return 0;
+int GPU_color_depth(void)
+{
+ return GG.colordepth;
}
static void GPU_print_framebuffer_error(GLenum status, char err_out[256])
{
- const char *err= "unknown";
+ const char *err = "unknown";
switch (status) {
case GL_FRAMEBUFFER_COMPLETE_EXT:
break;
case GL_INVALID_OPERATION:
- err= "Invalid operation";
+ err = "Invalid operation";
break;
case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT:
- err= "Incomplete attachment";
+ err = "Incomplete attachment";
break;
case GL_FRAMEBUFFER_UNSUPPORTED_EXT:
- err= "Unsupported framebuffer format";
+ err = "Unsupported framebuffer format";
break;
case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT:
- err= "Missing attachment";
+ err = "Missing attachment";
break;
case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT:
- err= "Attached images must have same dimensions";
+ err = "Attached images must have same dimensions";
break;
case GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT:
- err= "Attached images must have same format";
+ err = "Attached images must have same format";
break;
case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT:
- err= "Missing draw buffer";
+ err = "Missing draw buffer";
break;
case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT:
- err= "Missing read buffer";
+ err = "Missing read buffer";
break;
}
@@ -324,28 +379,30 @@ static void GPU_print_framebuffer_error(GLenum status, char err_out[256])
/* GPUTexture */
struct GPUTexture {
- int w, h; /* width/height */
- int number; /* number for multitexture binding */
- int refcount; /* reference count */
- GLenum target; /* GL_TEXTURE_* */
- GLuint bindcode; /* opengl identifier for texture */
- int fromblender; /* we got the texture from Blender */
-
- GPUFrameBuffer *fb; /* GPUFramebuffer this texture is attached to */
- int depth; /* is a depth texture? */
+ int w, h; /* width/height */
+ int w_orig, h_orig; /* width/height (before power of 2 is applied) */
+ int number; /* number for multitexture binding */
+ int refcount; /* reference count */
+ GLenum target; /* GL_TEXTURE_* */
+ GLuint bindcode; /* opengl identifier for texture */
+ int fromblender; /* we got the texture from Blender */
+
+ GPUFrameBuffer *fb; /* GPUFramebuffer this texture is attached to */
+ int fb_attachment; /* slot the texture is attached to */
+ int depth; /* is a depth texture? if 3D how deep? */
+ int depth_orig; /* depth (before power of 2 is applied) */
};
-static unsigned char *GPU_texture_convert_pixels(int length, float *fpixels)
+static unsigned char *GPU_texture_convert_pixels(int length, const float *fpixels)
{
unsigned char *pixels, *p;
- const float *fp;
- int a, len;
+ const float *fp = fpixels;
+ const int len = 4 * length;
+ int a;
- len = 4*length;
- fp = fpixels;
- p = pixels = MEM_callocN(sizeof(unsigned char)*len, "GPUTexturePixels");
+ p = pixels = MEM_callocN(sizeof(unsigned char) * len, "GPUTexturePixels");
- for (a=0; a<len; a++, p++, fp++)
+ for (a = 0; a < len; a++, p++, fp++)
*p = FTOCHAR((*fp));
return pixels;
@@ -353,7 +410,7 @@ static unsigned char *GPU_texture_convert_pixels(int length, float *fpixels)
static void GPU_glTexSubImageEmpty(GLenum target, GLenum format, int x, int y, int w, int h)
{
- void *pixels = MEM_callocN(sizeof(char)*4*w*h, "GPUTextureEmptyPixels");
+ void *pixels = MEM_callocN(sizeof(char) * 4 * w * h, "GPUTextureEmptyPixels");
if (target == GL_TEXTURE_1D)
glTexSubImage1D(target, 0, x, w, format, GL_UNSIGNED_BYTE, pixels);
@@ -363,7 +420,9 @@ static void GPU_glTexSubImageEmpty(GLenum target, GLenum format, int x, int y, i
MEM_freeN(pixels);
}
-static GPUTexture *GPU_texture_create_nD(int w, int h, int n, float *fpixels, int depth, char err_out[256])
+static GPUTexture *GPU_texture_create_nD(
+ int w, int h, int n, const float *fpixels, int depth, GPUHDRType hdr_type, int components,
+ char err_out[256])
{
GPUTexture *tex;
GLenum type, format, internalformat;
@@ -373,12 +432,13 @@ static GPUTexture *GPU_texture_create_nD(int w, int h, int n, float *fpixels, in
return NULL;
tex = MEM_callocN(sizeof(GPUTexture), "GPUTexture");
- tex->w = w;
- tex->h = h;
+ tex->w = tex->w_orig = w;
+ tex->h = tex->h_orig = h;
tex->number = -1;
tex->refcount = 1;
tex->target = (n == 1)? GL_TEXTURE_1D: GL_TEXTURE_2D;
- tex->depth = depth;
+ tex->depth = tex->depth_orig = depth;
+ tex->fb_attachment = -1;
glGenTextures(1, &tex->bindcode);
@@ -409,12 +469,45 @@ static GPUTexture *GPU_texture_create_nD(int w, int h, int n, float *fpixels, in
internalformat = GL_DEPTH_COMPONENT;
}
else {
- type = GL_UNSIGNED_BYTE;
- format = GL_RGBA;
- internalformat = GL_RGBA8;
+ type = GL_FLOAT;
+
+ if (components == 4) {
+ format = GL_RGBA;
+ switch (hdr_type) {
+ case GPU_HDR_NONE:
+ internalformat = GL_RGBA8;
+ break;
+ case GPU_HDR_HALF_FLOAT:
+ internalformat = GL_RGBA16F;
+ break;
+ case GPU_HDR_FULL_FLOAT:
+ internalformat = GL_RGBA32F;
+ break;
+ default:
+ break;
+ }
+ }
+ else if (components == 2) {
+ format = GL_RG;
+ switch (hdr_type) {
+ case GPU_HDR_NONE:
+ internalformat = GL_RG8;
+ break;
+ case GPU_HDR_HALF_FLOAT:
+ internalformat = GL_RG16F;
+ break;
+ case GPU_HDR_FULL_FLOAT:
+ internalformat = GL_RG32F;
+ break;
+ default:
+ break;
+ }
+ }
- if (fpixels)
+ if (fpixels && hdr_type == GPU_HDR_NONE) {
+ type = GL_UNSIGNED_BYTE;
pixels = GPU_texture_convert_pixels(w*h, fpixels);
+ }
}
if (tex->target == GL_TEXTURE_1D) {
@@ -460,15 +553,8 @@ static GPUTexture *GPU_texture_create_nD(int w, int h, int n, float *fpixels, in
}
if (tex->target != GL_TEXTURE_1D) {
- /* CLAMP_TO_BORDER is an OpenGL 1.3 core feature */
- GLenum wrapmode = (depth || tex->h == 1)? GL_CLAMP_TO_EDGE: GL_CLAMP_TO_BORDER;
- glTexParameteri(tex->target, GL_TEXTURE_WRAP_S, wrapmode);
- glTexParameteri(tex->target, GL_TEXTURE_WRAP_T, wrapmode);
-
-#if 0
- float borderColor[] = { 1.0f, 1.0f, 1.0f, 1.0f };
- glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, borderColor);
-#endif
+ glTexParameteri(tex->target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(tex->target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
}
else
glTexParameteri(tex->target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
@@ -477,20 +563,21 @@ static GPUTexture *GPU_texture_create_nD(int w, int h, int n, float *fpixels, in
}
-GPUTexture *GPU_texture_create_3D(int w, int h, int depth, int channels, float *fpixels)
+GPUTexture *GPU_texture_create_3D(int w, int h, int depth, int channels, const float *fpixels)
{
GPUTexture *tex;
GLenum type, format, internalformat;
void *pixels = NULL;
- float vfBorderColor[4] = {0.0f, 0.0f, 0.0f, 0.0f};
+ int r_width;
+ bool rescale = false;
if (!GLEW_VERSION_1_2)
return NULL;
tex = MEM_callocN(sizeof(GPUTexture), "GPUTexture");
- tex->w = w;
- tex->h = h;
- tex->depth = depth;
+ tex->w = tex->w_orig = w;
+ tex->h = tex->h_orig = h;
+ tex->depth = tex->depth_orig = depth;
tex->number = -1;
tex->refcount = 1;
tex->target = GL_TEXTURE_3D;
@@ -513,7 +600,7 @@ GPUTexture *GPU_texture_create_3D(int w, int h, int depth, int channels, float *
tex->number = 0;
glBindTexture(tex->target, tex->bindcode);
- GPU_print_error("3D glBindTexture");
+ GPU_ASSERT_NO_GL_ERRORS("3D glBindTexture");
type = GL_FLOAT;
if (channels == 4) {
@@ -525,35 +612,90 @@ GPUTexture *GPU_texture_create_3D(int w, int h, int depth, int channels, float *
internalformat = GL_INTENSITY;
}
- //if (fpixels)
- // pixels = GPU_texture_convert_pixels(w*h*depth, fpixels);
+ /* 3D textures are quite heavy, test if it's possible to create them first */
+ glTexImage3D(GL_PROXY_TEXTURE_3D, 0, internalformat, tex->w, tex->h, tex->depth, 0, format, type, NULL);
+ glGetTexLevelParameteriv(GL_PROXY_TEXTURE_3D, 0, GL_TEXTURE_WIDTH, &r_width);
- glTexImage3D(tex->target, 0, internalformat, tex->w, tex->h, tex->depth, 0, format, type, NULL);
+ while (r_width == 0) {
+ rescale = true;
+ tex->w /= 2;
+ tex->h /= 2;
+ tex->depth /= 2;
+ glTexImage3D(GL_PROXY_TEXTURE_3D, 0, internalformat, tex->w, tex->h, tex->depth, 0, format, type, NULL);
+ glGetTexLevelParameteriv(GL_PROXY_TEXTURE_3D, 0, GL_TEXTURE_WIDTH, &r_width);
+ }
+
+ /* really unlikely to happen but keep this just in case */
+ tex->w = max_ii(tex->w, 1);
+ tex->h = max_ii(tex->h, 1);
+ tex->depth = max_ii(tex->depth, 1);
- GPU_print_error("3D glTexImage3D");
+#if 0
+ if (fpixels)
+ pixels = GPU_texture_convert_pixels(w*h*depth, fpixels);
+#endif
- if (fpixels) {
- if (!GPU_non_power_of_two_support() && (w != tex->w || h != tex->h || depth != tex->depth)) {
- /* clear first to avoid unitialized pixels */
- float *zero= MEM_callocN(sizeof(float)*tex->w*tex->h*tex->depth, "zero");
- glTexSubImage3D(tex->target, 0, 0, 0, 0, tex->w, tex->h, tex->depth, format, type, zero);
- MEM_freeN(zero);
+ GPU_ASSERT_NO_GL_ERRORS("3D glTexImage3D");
+
+ /* hardcore stuff, 3D texture rescaling - warning, this is gonna hurt your performance a lot, but we need it
+ * for gooseberry */
+ if (rescale && fpixels) {
+ unsigned int i, j, k;
+ unsigned int xf = w / tex->w, yf = h / tex->h, zf = depth / tex->depth;
+ float *tex3d = MEM_mallocN(channels * sizeof(float)*tex->w*tex->h*tex->depth, "tex3d");
+
+ GPU_print_error_debug("You need to scale a 3D texture, feel the pain!");
+
+ for (k = 0; k < tex->depth; k++) {
+ for (j = 0; j < tex->h; j++) {
+ for (i = 0; i < tex->w; i++) {
+ /* obviously doing nearest filtering here, it's going to be slow in any case, let's not make it worse */
+ float xb = i * xf;
+ float yb = j * yf;
+ float zb = k * zf;
+ unsigned int offset = k * (tex->w * tex->h) + i * tex->h + j;
+ unsigned int offset_orig = (zb) * (w * h) + (xb) * h + (yb);
+
+ if (channels == 4) {
+ tex3d[offset * 4] = fpixels[offset_orig * 4];
+ tex3d[offset * 4 + 1] = fpixels[offset_orig * 4 + 1];
+ tex3d[offset * 4 + 2] = fpixels[offset_orig * 4 + 2];
+ tex3d[offset * 4 + 3] = fpixels[offset_orig * 4 + 3];
+ }
+ else
+ tex3d[offset] = fpixels[offset_orig];
+ }
+ }
}
- glTexSubImage3D(tex->target, 0, 0, 0, 0, w, h, depth, format, type, fpixels);
- GPU_print_error("3D glTexSubImage3D");
+ glTexImage3D(tex->target, 0, internalformat, tex->w, tex->h, tex->depth, 0, format, type, tex3d);
+
+ MEM_freeN(tex3d);
+ }
+ else {
+ if (fpixels) {
+ if (!GPU_non_power_of_two_support() && (w != tex->w || h != tex->h || depth != tex->depth)) {
+ /* clear first to avoid unitialized pixels */
+ float *zero= MEM_callocN(sizeof(float)*tex->w*tex->h*tex->depth, "zero");
+ glTexImage3D(tex->target, 0, internalformat, tex->w, tex->h, tex->depth, 0, format, type, NULL);
+ glTexSubImage3D(tex->target, 0, 0, 0, 0, tex->w, tex->h, tex->depth, GL_INTENSITY, GL_FLOAT, zero);
+ glTexSubImage3D(tex->target, 0, 0, 0, 0, w, h, depth, format, type, fpixels);
+ MEM_freeN(zero);
+ }
+ else {
+ glTexImage3D(tex->target, 0, internalformat, tex->w, tex->h, tex->depth, 0, format, type, fpixels);
+ }
+
+ GPU_ASSERT_NO_GL_ERRORS("3D glTexSubImage3D");
+ }
}
- glTexParameterfv(GL_TEXTURE_3D, GL_TEXTURE_BORDER_COLOR, vfBorderColor);
- GPU_print_error("3D GL_TEXTURE_BORDER_COLOR");
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- GPU_print_error("3D GL_LINEAR");
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
- GPU_print_error("3D GL_CLAMP_TO_BORDER");
if (pixels)
MEM_freeN(pixels);
@@ -590,7 +732,7 @@ GPUTexture *GPU_texture_from_blender(Image *ima, ImageUser *iuser, bool is_data,
ima->gputexture= tex;
if (!glIsTexture(tex->bindcode)) {
- GPU_print_error("Blender Texture Not Loaded");
+ GPU_ASSERT_NO_GL_ERRORS("Blender Texture Not Loaded");
}
else {
glBindTexture(GL_TEXTURE_2D, tex->bindcode);
@@ -598,8 +740,8 @@ GPUTexture *GPU_texture_from_blender(Image *ima, ImageUser *iuser, bool is_data,
glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &h);
glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_BORDER, &border);
- tex->w = w - border;
- tex->h = h - border;
+ tex->w = tex->w_orig = w - border;
+ tex->h = tex->h_orig = h - border;
}
glBindTexture(GL_TEXTURE_2D, lastbindcode);
@@ -634,18 +776,18 @@ GPUTexture *GPU_texture_from_preview(PreviewImage *prv, int mipmap)
tex->refcount = 1;
tex->target = GL_TEXTURE_2D;
- prv->gputexture[0]= tex;
+ prv->gputexture[0] = tex;
if (!glIsTexture(tex->bindcode)) {
- GPU_print_error("Blender Texture Not Loaded");
+ GPU_ASSERT_NO_GL_ERRORS("Blender Texture Not Loaded");
}
else {
glBindTexture(GL_TEXTURE_2D, tex->bindcode);
glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &w);
glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &h);
- tex->w = w;
- tex->h = h;
+ tex->w = tex->w_orig = w;
+ tex->h = tex->h_orig = h;
}
glBindTexture(GL_TEXTURE_2D, lastbindcode);
@@ -654,9 +796,9 @@ GPUTexture *GPU_texture_from_preview(PreviewImage *prv, int mipmap)
}
-GPUTexture *GPU_texture_create_1D(int w, float *fpixels, char err_out[256])
+GPUTexture *GPU_texture_create_1D(int w, const float *fpixels, char err_out[256])
{
- GPUTexture *tex = GPU_texture_create_nD(w, 1, 1, fpixels, 0, err_out);
+ GPUTexture *tex = GPU_texture_create_nD(w, 1, 1, fpixels, 0, GPU_HDR_NONE, 4, err_out);
if (tex)
GPU_texture_unbind(tex);
@@ -664,9 +806,9 @@ GPUTexture *GPU_texture_create_1D(int w, float *fpixels, char err_out[256])
return tex;
}
-GPUTexture *GPU_texture_create_2D(int w, int h, float *fpixels, char err_out[256])
+GPUTexture *GPU_texture_create_2D(int w, int h, const float *fpixels, GPUHDRType hdr, char err_out[256])
{
- GPUTexture *tex = GPU_texture_create_nD(w, h, 2, fpixels, 0, err_out);
+ GPUTexture *tex = GPU_texture_create_nD(w, h, 2, fpixels, 0, hdr, 4, err_out);
if (tex)
GPU_texture_unbind(tex);
@@ -676,7 +818,7 @@ GPUTexture *GPU_texture_create_2D(int w, int h, float *fpixels, char err_out[256
GPUTexture *GPU_texture_create_depth(int w, int h, char err_out[256])
{
- GPUTexture *tex = GPU_texture_create_nD(w, h, 2, NULL, 1, err_out);
+ GPUTexture *tex = GPU_texture_create_nD(w, h, 2, NULL, 1, GPU_HDR_NONE, 1, err_out);
if (tex)
GPU_texture_unbind(tex);
@@ -689,13 +831,47 @@ GPUTexture *GPU_texture_create_depth(int w, int h, char err_out[256])
*/
GPUTexture *GPU_texture_create_vsm_shadow_map(int size, char err_out[256])
{
- GPUTexture *tex = GPU_texture_create_nD(size, size, 2, NULL, 0, err_out);
+ GPUTexture *tex = GPU_texture_create_nD(size, size, 2, NULL, 0, GPU_HDR_FULL_FLOAT, 2, err_out);
if (tex) {
/* Now we tweak some of the settings */
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RG32F, size, size, 0, GL_RG, GL_FLOAT, NULL);
+
+ GPU_texture_unbind(tex);
+ }
+
+ return tex;
+}
+
+GPUTexture *GPU_texture_create_2D_procedural(int w, int h, const float *pixels, bool repeat, char err_out[256])
+{
+ GPUTexture *tex = GPU_texture_create_nD(w, h, 2, pixels, 0, GPU_HDR_HALF_FLOAT, 2, err_out);
+
+ if (tex) {
+ /* Now we tweak some of the settings */
+ if (repeat) {
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
+ }
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+
+ GPU_texture_unbind(tex);
+ }
+
+ return tex;
+}
+
+GPUTexture *GPU_texture_create_1D_procedural(int w, const float *pixels, char err_out[256])
+{
+ GPUTexture *tex = GPU_texture_create_nD(w, 0, 1, pixels, 0, GPU_HDR_HALF_FLOAT, 2, err_out);
+
+ if (tex) {
+ /* Now we tweak some of the settings */
+ glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_REPEAT);
+ glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
GPU_texture_unbind(tex);
}
@@ -705,9 +881,9 @@ GPUTexture *GPU_texture_create_vsm_shadow_map(int size, char err_out[256])
void GPU_invalid_tex_init(void)
{
- float color[4] = {1.0f, 0.0f, 1.0f, 1.0};
+ const float color[4] = {1.0f, 0.0f, 1.0f, 1.0f};
GG.invalid_tex_1D = GPU_texture_create_1D(1, color, NULL);
- GG.invalid_tex_2D = GPU_texture_create_2D(1, 1, color, NULL);
+ GG.invalid_tex_2D = GPU_texture_create_2D(1, 1, color, GPU_HDR_NONE, NULL);
GG.invalid_tex_3D = GPU_texture_create_3D(1, 1, 1, 4, color);
}
@@ -728,9 +904,12 @@ void GPU_invalid_tex_bind(int mode)
void GPU_invalid_tex_free(void)
{
- GPU_texture_free(GG.invalid_tex_1D);
- GPU_texture_free(GG.invalid_tex_2D);
- GPU_texture_free(GG.invalid_tex_3D);
+ if (GG.invalid_tex_1D)
+ GPU_texture_free(GG.invalid_tex_1D);
+ if (GG.invalid_tex_2D)
+ GPU_texture_free(GG.invalid_tex_2D);
+ if (GG.invalid_tex_3D)
+ GPU_texture_free(GG.invalid_tex_3D);
}
@@ -739,14 +918,20 @@ void GPU_texture_bind(GPUTexture *tex, int number)
GLenum arbnumber;
if (number >= GG.maxtextures) {
- GPU_print_error("Not enough texture slots.");
+ fprintf(stderr, "Not enough texture slots.");
return;
}
- if (number == -1)
+ if ((G.debug & G_DEBUG)) {
+ if (tex->fb && tex->fb->object == GG.currentfb) {
+ fprintf(stderr, "Feedback loop warning!: Attempting to bind texture attached to current framebuffer!\n");
+ }
+ }
+
+ if (number < 0)
return;
- GPU_print_error("Pre Texture Bind");
+ GPU_ASSERT_NO_GL_ERRORS("Pre Texture Bind");
arbnumber = (GLenum)((GLuint)GL_TEXTURE0_ARB + number);
if (number != 0) glActiveTextureARB(arbnumber);
@@ -760,7 +945,7 @@ void GPU_texture_bind(GPUTexture *tex, int number)
tex->number = number;
- GPU_print_error("Post Texture Bind");
+ GPU_ASSERT_NO_GL_ERRORS("Post Texture Bind");
}
void GPU_texture_unbind(GPUTexture *tex)
@@ -768,14 +953,14 @@ void GPU_texture_unbind(GPUTexture *tex)
GLenum arbnumber;
if (tex->number >= GG.maxtextures) {
- GPU_print_error("Not enough texture slots.");
+ fprintf(stderr, "Not enough texture slots.");
return;
}
if (tex->number == -1)
return;
- GPU_print_error("Pre Texture Unbind");
+ GPU_ASSERT_NO_GL_ERRORS("Pre Texture Unbind");
arbnumber = (GLenum)((GLuint)GL_TEXTURE0_ARB + tex->number);
if (tex->number != 0) glActiveTextureARB(arbnumber);
@@ -785,7 +970,44 @@ void GPU_texture_unbind(GPUTexture *tex)
tex->number = -1;
- GPU_print_error("Post Texture Unbind");
+ GPU_ASSERT_NO_GL_ERRORS("Post Texture Unbind");
+}
+
+void GPU_texture_filter_mode(GPUTexture *tex, bool compare, bool use_filter)
+{
+ GLenum arbnumber;
+
+ if (tex->number >= GG.maxtextures) {
+ fprintf(stderr, "Not enough texture slots.");
+ return;
+ }
+
+ if (tex->number == -1)
+ return;
+
+ GPU_ASSERT_NO_GL_ERRORS("Pre Texture Unbind");
+
+ arbnumber = (GLenum)((GLuint)GL_TEXTURE0_ARB + tex->number);
+ if (tex->number != 0) glActiveTextureARB(arbnumber);
+
+ if (tex->depth) {
+ if (compare)
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_R_TO_TEXTURE);
+ else
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE);
+ }
+
+ if (use_filter) {
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ }
+ else {
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ }
+ if (tex->number != 0) glActiveTextureARB(GL_TEXTURE0_ARB);
+
+ GPU_ASSERT_NO_GL_ERRORS("Post Texture Unbind");
}
void GPU_texture_free(GPUTexture *tex)
@@ -797,7 +1019,7 @@ void GPU_texture_free(GPUTexture *tex)
if (tex->refcount == 0) {
if (tex->fb)
- GPU_framebuffer_texture_detach(tex->fb, tex);
+ GPU_framebuffer_texture_detach(tex);
if (tex->bindcode && !tex->fromblender)
glDeleteTextures(1, &tex->bindcode);
@@ -810,22 +1032,22 @@ void GPU_texture_ref(GPUTexture *tex)
tex->refcount++;
}
-int GPU_texture_target(GPUTexture *tex)
+int GPU_texture_target(const GPUTexture *tex)
{
return tex->target;
}
-int GPU_texture_opengl_width(GPUTexture *tex)
+int GPU_texture_opengl_width(const GPUTexture *tex)
{
return tex->w;
}
-int GPU_texture_opengl_height(GPUTexture *tex)
+int GPU_texture_opengl_height(const GPUTexture *tex)
{
return tex->h;
}
-int GPU_texture_opengl_bindcode(GPUTexture *tex)
+int GPU_texture_opengl_bindcode(const GPUTexture *tex)
{
return tex->bindcode;
}
@@ -837,12 +1059,6 @@ GPUFrameBuffer *GPU_texture_framebuffer(GPUTexture *tex)
/* GPUFrameBuffer */
-struct GPUFrameBuffer {
- GLuint object;
- GPUTexture *colortex;
- GPUTexture *depthtex;
-};
-
GPUFrameBuffer *GPU_framebuffer_create(void)
{
GPUFrameBuffer *fb;
@@ -850,7 +1066,7 @@ GPUFrameBuffer *GPU_framebuffer_create(void)
if (!GLEW_EXT_framebuffer_object)
return NULL;
- fb= MEM_callocN(sizeof(GPUFrameBuffer), "GPUFrameBuffer");
+ fb = MEM_callocN(sizeof(GPUFrameBuffer), "GPUFrameBuffer");
glGenFramebuffersEXT(1, &fb->object);
if (!fb->object) {
@@ -860,19 +1076,35 @@ GPUFrameBuffer *GPU_framebuffer_create(void)
return NULL;
}
+ /* make sure no read buffer is enabled, so completeness check will not fail. We set those at binding time */
+ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb->object);
+ glReadBuffer(GL_NONE);
+ glDrawBuffer(GL_NONE);
+ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
+
return fb;
}
-int GPU_framebuffer_texture_attach(GPUFrameBuffer *fb, GPUTexture *tex, char err_out[256])
+int GPU_framebuffer_texture_attach(GPUFrameBuffer *fb, GPUTexture *tex, int slot, char err_out[256])
{
- GLenum status;
GLenum attachment;
GLenum error;
+ if (slot >= GPU_FB_MAX_SLOTS) {
+ fprintf(stderr, "Attaching to index %d framebuffer slot unsupported in blender use at most %d\n", slot, GPU_FB_MAX_SLOTS);
+ return 0;
+ }
+
+ if ((G.debug & G_DEBUG)) {
+ if (tex->number != -1) {
+ fprintf(stderr, "Feedback loop warning!: Attempting to attach texture to framebuffer while still bound to texture unit for drawing!");
+ }
+ }
+
if (tex->depth)
attachment = GL_DEPTH_ATTACHMENT_EXT;
else
- attachment = GL_COLOR_ATTACHMENT0_EXT;
+ attachment = GL_COLOR_ATTACHMENT0_EXT + slot;
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb->object);
GG.currentfb = fb->object;
@@ -891,42 +1123,29 @@ int GPU_framebuffer_texture_attach(GPUFrameBuffer *fb, GPUTexture *tex, char err
return 0;
}
- if (tex->depth) {
- glDrawBuffer(GL_NONE);
- glReadBuffer(GL_NONE);
- }
- else {
- glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);
- glReadBuffer(GL_COLOR_ATTACHMENT0_EXT);
- }
-
- status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
-
- if (status != GL_FRAMEBUFFER_COMPLETE_EXT) {
- GPU_framebuffer_restore();
- GPU_print_framebuffer_error(status, err_out);
- return 0;
- }
-
if (tex->depth)
fb->depthtex = tex;
else
- fb->colortex = tex;
+ fb->colortex[slot] = tex;
tex->fb= fb;
+ tex->fb_attachment = slot;
return 1;
}
-void GPU_framebuffer_texture_detach(GPUFrameBuffer *fb, GPUTexture *tex)
+void GPU_framebuffer_texture_detach(GPUTexture *tex)
{
GLenum attachment;
+ GPUFrameBuffer *fb;
if (!tex->fb)
return;
- if (GG.currentfb != tex->fb->object) {
- glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, tex->fb->object);
+ fb = tex->fb;
+
+ if (GG.currentfb != fb->object) {
+ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb->object);
GG.currentfb = tex->fb->object;
}
@@ -935,18 +1154,24 @@ void GPU_framebuffer_texture_detach(GPUFrameBuffer *fb, GPUTexture *tex)
attachment = GL_DEPTH_ATTACHMENT_EXT;
}
else {
- fb->colortex = NULL;
- attachment = GL_COLOR_ATTACHMENT0_EXT;
+ BLI_assert(fb->colortex[tex->fb_attachment] == tex);
+ fb->colortex[tex->fb_attachment] = NULL;
+ attachment = GL_COLOR_ATTACHMENT0_EXT + tex->fb_attachment;
}
- glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, attachment,
- tex->target, 0, 0);
+ glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, attachment, tex->target, 0, 0);
tex->fb = NULL;
+ tex->fb_attachment = -1;
}
-void GPU_framebuffer_texture_bind(GPUFrameBuffer *UNUSED(fb), GPUTexture *tex, int w, int h)
+void GPU_texture_bind_as_framebuffer(GPUTexture *tex)
{
+ if (!tex->fb) {
+ fprintf(stderr, "Error, texture not bound to framebuffer!");
+ return;
+ }
+
/* push attributes */
glPushAttrib(GL_ENABLE_BIT | GL_VIEWPORT_BIT);
glDisable(GL_SCISSOR_TEST);
@@ -954,8 +1179,18 @@ void GPU_framebuffer_texture_bind(GPUFrameBuffer *UNUSED(fb), GPUTexture *tex, i
/* bind framebuffer */
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, tex->fb->object);
+ if (tex->depth) {
+ glDrawBuffer(GL_NONE);
+ glReadBuffer(GL_NONE);
+ }
+ else {
+ /* last bound prevails here, better allow explicit control here too */
+ glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT + tex->fb_attachment);
+ glReadBuffer(GL_COLOR_ATTACHMENT0_EXT + tex->fb_attachment);
+ }
+
/* push matrices and set default viewport and matrix */
- glViewport(0, 0, w, h);
+ glViewport(0, 0, tex->w_orig, tex->h_orig);
GG.currentfb = tex->fb->object;
glMatrixMode(GL_PROJECTION);
@@ -964,6 +1199,45 @@ void GPU_framebuffer_texture_bind(GPUFrameBuffer *UNUSED(fb), GPUTexture *tex, i
glPushMatrix();
}
+void GPU_framebuffer_slots_bind(GPUFrameBuffer *fb, int slot)
+{
+ int numslots = 0, i;
+ GLenum attachments[4];
+
+ if (!fb->colortex[slot]) {
+ fprintf(stderr, "Error, framebuffer slot empty!");
+ return;
+ }
+
+ for (i = 0; i < 4; i++) {
+ if (fb->colortex[i]) {
+ attachments[numslots] = GL_COLOR_ATTACHMENT0_EXT + i;
+ numslots++;
+ }
+ }
+
+ /* push attributes */
+ glPushAttrib(GL_ENABLE_BIT | GL_VIEWPORT_BIT);
+ glDisable(GL_SCISSOR_TEST);
+
+ /* bind framebuffer */
+ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb->object);
+
+ /* last bound prevails here, better allow explicit control here too */
+ glDrawBuffers(numslots, attachments);
+ glReadBuffer(GL_COLOR_ATTACHMENT0_EXT + slot);
+
+ /* push matrices and set default viewport and matrix */
+ glViewport(0, 0, fb->colortex[slot]->w_orig, fb->colortex[slot]->h_orig);
+ GG.currentfb = fb->object;
+
+ glMatrixMode(GL_PROJECTION);
+ glPushMatrix();
+ glMatrixMode(GL_MODELVIEW);
+ glPushMatrix();
+}
+
+
void GPU_framebuffer_texture_unbind(GPUFrameBuffer *UNUSED(fb), GPUTexture *UNUSED(tex))
{
/* restore matrix */
@@ -974,15 +1248,53 @@ void GPU_framebuffer_texture_unbind(GPUFrameBuffer *UNUSED(fb), GPUTexture *UNUS
/* restore attributes */
glPopAttrib();
- glEnable(GL_SCISSOR_TEST);
+}
+
+void GPU_framebuffer_bind_no_save(GPUFrameBuffer *fb, int slot)
+{
+ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb->object);
+ /* last bound prevails here, better allow explicit control here too */
+ glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT + slot);
+ glReadBuffer(GL_COLOR_ATTACHMENT0_EXT + slot);
+
+ /* push matrices and set default viewport and matrix */
+ glViewport(0, 0, fb->colortex[slot]->w_orig, fb->colortex[slot]->h_orig);
+ GG.currentfb = fb->object;
+ GG.currentfb = fb->object;
+}
+
+bool GPU_framebuffer_check_valid(GPUFrameBuffer *fb, char err_out[256])
+{
+ GLenum status;
+
+ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb->object);
+ GG.currentfb = fb->object;
+
+ /* Clean glError buffer. */
+ while (glGetError() != GL_NO_ERROR) {}
+
+ status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
+
+ if (status != GL_FRAMEBUFFER_COMPLETE_EXT) {
+ GPU_framebuffer_restore();
+ GPU_print_framebuffer_error(status, err_out);
+ return false;
+ }
+
+ return true;
}
void GPU_framebuffer_free(GPUFrameBuffer *fb)
{
+ int i;
if (fb->depthtex)
- GPU_framebuffer_texture_detach(fb, fb->depthtex);
- if (fb->colortex)
- GPU_framebuffer_texture_detach(fb, fb->colortex);
+ GPU_framebuffer_texture_detach(fb->depthtex);
+
+ for (i = 0; i < GPU_FB_MAX_SLOTS; i++) {
+ if (fb->colortex[i]) {
+ GPU_framebuffer_texture_detach(fb->colortex[i]);
+ }
+ }
if (fb->object) {
glDeleteFramebuffersEXT(1, &fb->object);
@@ -1006,8 +1318,8 @@ void GPU_framebuffer_restore(void)
void GPU_framebuffer_blur(GPUFrameBuffer *fb, GPUTexture *tex, GPUFrameBuffer *blurfb, GPUTexture *blurtex)
{
- float scaleh[2] = {1.0f/GPU_texture_opengl_width(blurtex), 0.0f};
- float scalev[2] = {0.0f, 1.0f/GPU_texture_opengl_height(tex)};
+ const float scaleh[2] = {1.0f / blurtex->w_orig, 0.0f};
+ const float scalev[2] = {0.0f, 1.0f / tex->h_orig};
GPUShader *blur_shader = GPU_shader_get_builtin_shader(GPU_SHADER_SEP_GAUSSIAN_BLUR);
int scale_uniform, texture_source_uniform;
@@ -1023,11 +1335,15 @@ void GPU_framebuffer_blur(GPUFrameBuffer *fb, GPUTexture *tex, GPUFrameBuffer *b
/* We do the bind ourselves rather than using GPU_framebuffer_texture_bind() to avoid
* pushing unnecessary matrices onto the OpenGL stack. */
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, blurfb->object);
+ glDrawBuffer(GL_COLOR_ATTACHMENT0);
+
+ /* avoid warnings from texture binding */
+ GG.currentfb = blurfb->object;
GPU_shader_bind(blur_shader);
- GPU_shader_uniform_vector(blur_shader, scale_uniform, 2, 1, (float *)scaleh);
+ GPU_shader_uniform_vector(blur_shader, scale_uniform, 2, 1, scaleh);
GPU_shader_uniform_texture(blur_shader, texture_source_uniform, tex);
- glViewport(0, 0, GPU_texture_opengl_width(blurtex), GPU_texture_opengl_height(blurtex));
+ glViewport(0, 0, blurtex->w_orig, blurtex->h_orig);
/* Peparing to draw quad */
glMatrixMode(GL_MODELVIEW);
@@ -1048,12 +1364,16 @@ void GPU_framebuffer_blur(GPUFrameBuffer *fb, GPUTexture *tex, GPUFrameBuffer *b
glTexCoord2d(1, 1); glVertex2f(-1, -1);
glTexCoord2d(0, 1); glVertex2f(1, -1);
glEnd();
-
+
/* Blurring vertically */
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb->object);
- glViewport(0, 0, GPU_texture_opengl_width(tex), GPU_texture_opengl_height(tex));
- GPU_shader_uniform_vector(blur_shader, scale_uniform, 2, 1, (float *)scalev);
+ glDrawBuffer(GL_COLOR_ATTACHMENT0);
+
+ GG.currentfb = fb->object;
+
+ glViewport(0, 0, tex->w_orig, tex->h_orig);
+ GPU_shader_uniform_vector(blur_shader, scale_uniform, 2, 1, scalev);
GPU_shader_uniform_texture(blur_shader, texture_source_uniform, blurtex);
GPU_texture_bind(blurtex, 0);
@@ -1073,19 +1393,13 @@ struct GPUOffScreen {
GPUFrameBuffer *fb;
GPUTexture *color;
GPUTexture *depth;
-
- /* requested width/height, may be smaller than actual texture size due
- * to missing non-power of two support, so we compensate for that */
- int w, h;
};
GPUOffScreen *GPU_offscreen_create(int width, int height, char err_out[256])
{
GPUOffScreen *ofs;
- ofs= MEM_callocN(sizeof(GPUOffScreen), "GPUOffScreen");
- ofs->w= width;
- ofs->h= height;
+ ofs = MEM_callocN(sizeof(GPUOffScreen), "GPUOffScreen");
ofs->fb = GPU_framebuffer_create();
if (!ofs->fb) {
@@ -1099,21 +1413,27 @@ GPUOffScreen *GPU_offscreen_create(int width, int height, char err_out[256])
return NULL;
}
- if (!GPU_framebuffer_texture_attach(ofs->fb, ofs->depth, err_out)) {
+ if (!GPU_framebuffer_texture_attach(ofs->fb, ofs->depth, 0, err_out)) {
GPU_offscreen_free(ofs);
return NULL;
}
- ofs->color = GPU_texture_create_2D(width, height, NULL, err_out);
+ ofs->color = GPU_texture_create_2D(width, height, NULL, GPU_HDR_NONE, err_out);
if (!ofs->color) {
GPU_offscreen_free(ofs);
return NULL;
}
- if (!GPU_framebuffer_texture_attach(ofs->fb, ofs->color, err_out)) {
+ if (!GPU_framebuffer_texture_attach(ofs->fb, ofs->color, 0, err_out)) {
GPU_offscreen_free(ofs);
return NULL;
}
+
+ /* check validity at the very end! */
+ if (!GPU_framebuffer_check_valid(ofs->fb, err_out)) {
+ GPU_offscreen_free(ofs);
+ return NULL;
+ }
GPU_framebuffer_restore();
@@ -1132,62 +1452,75 @@ void GPU_offscreen_free(GPUOffScreen *ofs)
MEM_freeN(ofs);
}
-void GPU_offscreen_bind(GPUOffScreen *ofs)
+void GPU_offscreen_bind(GPUOffScreen *ofs, bool save)
{
glDisable(GL_SCISSOR_TEST);
- GPU_framebuffer_texture_bind(ofs->fb, ofs->color, ofs->w, ofs->h);
+ if (save)
+ GPU_texture_bind_as_framebuffer(ofs->color);
+ else {
+ GPU_framebuffer_bind_no_save(ofs->fb, 0);
+ }
}
-void GPU_offscreen_unbind(GPUOffScreen *ofs)
+void GPU_offscreen_unbind(GPUOffScreen *ofs, bool restore)
{
- GPU_framebuffer_texture_unbind(ofs->fb, ofs->color);
+ if (restore)
+ GPU_framebuffer_texture_unbind(ofs->fb, ofs->color);
GPU_framebuffer_restore();
glEnable(GL_SCISSOR_TEST);
}
void GPU_offscreen_read_pixels(GPUOffScreen *ofs, int type, void *pixels)
{
- glReadPixels(0, 0, ofs->w, ofs->h, GL_RGBA, type, pixels);
+ glReadPixels(0, 0, ofs->color->w_orig, ofs->color->h_orig, GL_RGBA, type, pixels);
}
-int GPU_offscreen_width(GPUOffScreen *ofs)
+int GPU_offscreen_width(const GPUOffScreen *ofs)
{
- return ofs->w;
+ return ofs->color->w_orig;
}
-int GPU_offscreen_height(GPUOffScreen *ofs)
+int GPU_offscreen_height(const GPUOffScreen *ofs)
{
- return ofs->h;
+ return ofs->color->h_orig;
}
/* GPUShader */
struct GPUShader {
- GLhandleARB object; /* handle for full shader */
- GLhandleARB vertex; /* handle for vertex shader */
- GLhandleARB fragment; /* handle for fragment shader */
- GLhandleARB lib; /* handle for libment shader */
- int totattrib; /* total number of attributes */
+ GLhandleARB object; /* handle for full shader */
+ GLhandleARB vertex; /* handle for vertex shader */
+ GLhandleARB fragment; /* handle for fragment shader */
+ GLhandleARB geometry; /* handle for geometry shader */
+ GLhandleARB lib; /* handle for libment shader */
+ int totattrib; /* total number of attributes */
+ int uniforms; /* required uniforms */
};
-static void shader_print_errors(const char *task, char *log, const char **code, int totcode)
+struct GPUProgram {
+ GPUProgramType type;
+ GLuint prog;
+};
+
+
+static void shader_print_errors(const char *task, const char *log, const char **code, int totcode)
{
int i;
+ int line = 1;
fprintf(stderr, "GPUShader: %s error:\n", task);
for (i = 0; i < totcode; i++) {
const char *c, *pos, *end = code[i] + strlen(code[i]);
- int line = 1;
-
- if (G.debug & G_DEBUG) {
+
+ if ((G.debug & G_DEBUG)) {
fprintf(stderr, "===== shader string %d ====\n", i + 1);
c = code[i];
while ((c < end) && (pos = strchr(c, '\n'))) {
fprintf(stderr, "%2d ", line);
- fwrite(c, (pos+1)-c, 1, stderr);
- c = pos+1;
+ fwrite(c, (pos + 1) - c, 1, stderr);
+ c = pos + 1;
line++;
}
@@ -1198,8 +1531,16 @@ static void shader_print_errors(const char *task, char *log, const char **code,
fprintf(stderr, "%s\n", log);
}
-static const char *gpu_shader_version(void)
+static const char *gpu_shader_version(bool use_opensubdiv)
{
+#ifdef WITH_OPENSUBDIV
+ if (use_opensubdiv) {
+ return "#version 130\n";
+ }
+#else
+ UNUSED_VARS(use_opensubdiv);
+#endif
+
/* turn on glsl 1.30 for bicubic bump mapping and ATI clipping support */
if (GLEW_VERSION_3_0 &&
(GPU_bicubic_bump_support() || GPU_type_matches(GPU_DEVICE_ATI, GPU_OS_ANY, GPU_DRIVER_ANY)))
@@ -1211,16 +1552,34 @@ static const char *gpu_shader_version(void)
}
-static const char *gpu_shader_standard_extensions(void)
+static void gpu_shader_standard_extensions(char defines[MAX_EXT_DEFINE_LENGTH], bool use_opensubdiv)
{
- /* need this extensions for high quality bump mapping */
+#ifdef WITH_OPENSUBDIV
+ if (use_opensubdiv) {
+ strcat(defines, "#extension GL_ARB_texture_query_lod: enable\n"
+ "#extension GL_ARB_gpu_shader5 : enable\n"
+ "#extension GL_ARB_explicit_attrib_location : require\n");
+ }
+ else if (GPU_bicubic_bump_support())
+ strcat(defines, "#extension GL_ARB_texture_query_lod: enable\n");
+#else
+ /* need this extension for high quality bump mapping */
if (GPU_bicubic_bump_support())
- return "#extension GL_ARB_texture_query_lod: enable\n";
+ strcat(defines, "#extension GL_ARB_texture_query_lod: enable\n");
+ (void) use_opensubdiv;
+#endif
- return "";
+ if (GPU_geometry_shader_support())
+ strcat(defines, "#extension GL_EXT_geometry_shader4: enable\n");
+
+ if (GPU_instanced_drawing_support()) {
+ strcat(defines, "#extension GL_EXT_gpu_shader4: enable\n");
+ strcat(defines, "#extension GL_ARB_draw_instanced: enable\n");
+ }
}
-static void gpu_shader_standard_defines(char defines[MAX_DEFINE_LENGTH])
+static void gpu_shader_standard_defines(bool use_opensubdiv,
+ char defines[MAX_DEFINE_LENGTH])
{
/* some useful defines to detect GPU type */
if (GPU_type_matches(GPU_DEVICE_ATI, GPU_OS_ANY, GPU_DRIVER_ANY)) {
@@ -1235,18 +1594,144 @@ static void gpu_shader_standard_defines(char defines[MAX_DEFINE_LENGTH])
if (GPU_bicubic_bump_support())
strcat(defines, "#define BUMP_BICUBIC\n");
+
+#ifdef WITH_OPENSUBDIV
+ /* TODO(sergey): Check whether we actually compiling shader for
+ * the OpenSubdiv mesh.
+ */
+ if (use_opensubdiv) {
+ strcat(defines, "#define USE_OPENSUBDIV\n");
+
+ /* TODO(sergey): not strictly speaking a define, but this is
+ * a global typedef which we don't have better place to define
+ * in yet.
+ */
+ strcat(defines, "struct VertexData {\n"
+ " vec4 position;\n"
+ " vec3 normal;\n"
+ " vec2 uv;"
+ "};\n");
+ }
+#else
+ UNUSED_VARS(use_opensubdiv);
+#endif
+
return;
}
-GPUShader *GPU_shader_create(const char *vertexcode, const char *fragcode, const char *libcode, const char *defines)
+void GPU_program_bind(GPUProgram *program)
+{
+ glEnable(program->type);
+ glBindProgramARB(program->type, program->prog);
+}
+
+void GPU_program_unbind(GPUProgram *program)
+{
+ glDisable(program->type);
+ glBindProgramARB(program->type, 0);
+}
+
+
+GPUProgram *GPU_program_shader_create(GPUProgramType type, const char *code)
+{
+ GPUProgram *program;
+ GLint error_pos, is_native;
+
+ if (!(GLEW_ARB_fragment_program && type == GPU_PROGRAM_TYPE_FRAGMENT))
+ return NULL;
+
+ program = MEM_callocN(sizeof(GPUProgram), "GPUProgram");
+
+ switch (type) {
+ case GPU_PROGRAM_TYPE_FRAGMENT:
+ program->type = GL_FRAGMENT_PROGRAM_ARB;
+ break;
+ }
+
+ /* create the object and set its code string */
+ glGenProgramsARB(1, &program->prog);
+ glBindProgramARB(program->type, program->prog);
+
+ glProgramStringARB(program->type, GL_PROGRAM_FORMAT_ASCII_ARB, (GLsizei)strlen(code), code);
+
+ glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &error_pos);
+ glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_UNDER_NATIVE_LIMITS_ARB, &is_native);
+ if ((error_pos == -1) && (is_native == 1)) {
+ return program;
+ }
+ else {
+ /* glGetError is set before that, clear it */
+ while (glGetError() != GL_NO_ERROR)
+ ;
+ shader_print_errors("compile", (const char *)glGetString(GL_PROGRAM_ERROR_STRING_ARB), &code, 1);
+ MEM_freeN(program);
+ }
+
+ return NULL;
+}
+
+void GPU_program_free(GPUProgram *program)
+{
+ glDeleteProgramsARB(1, &program->prog);
+ MEM_freeN(program);
+}
+
+void GPU_program_parameter_4f(GPUProgram *program, unsigned int location, float x, float y, float z, float w)
{
+ glProgramLocalParameter4fARB(program->type, location, x, y, z, w);
+}
+
+GPUShader *GPU_shader_create(const char *vertexcode,
+ const char *fragcode,
+ const char *geocode,
+ const char *libcode,
+ const char *defines,
+ int input,
+ int output,
+ int number)
+{
+ return GPU_shader_create_ex(vertexcode,
+ fragcode,
+ geocode,
+ libcode,
+ defines,
+ input,
+ output,
+ number,
+ GPU_SHADER_FLAGS_NONE);
+}
+
+GPUShader *GPU_shader_create_ex(const char *vertexcode,
+ const char *fragcode,
+ const char *geocode,
+ const char *libcode,
+ const char *defines,
+ int input,
+ int output,
+ int number,
+ const int flags)
+{
+#ifdef WITH_OPENSUBDIV
+ /* TODO(sergey): used to add #version 150 to the geometry shader.
+ * Could safely be renamed to "use_geometry_code" since it's very
+ * likely any of geometry code will want to use GLSL 1.5.
+ */
+ bool use_opensubdiv = (flags & GPU_SHADER_FLAGS_SPECIAL_OPENSUBDIV) != 0;
+#else
+ bool use_opensubdiv = false;
+#endif
GLint status;
GLcharARB log[5000];
GLsizei length = 0;
GPUShader *shader;
char standard_defines[MAX_DEFINE_LENGTH] = "";
+ char standard_extensions[MAX_EXT_DEFINE_LENGTH] = "";
- if (!GLEW_ARB_vertex_shader || !GLEW_ARB_fragment_shader)
+#ifndef WITH_OPENSUBDIV
+ UNUSED_VARS(flags);
+#endif
+
+ if (!GLEW_ARB_vertex_shader || !GLEW_ARB_fragment_shader || (geocode && !GPU_geometry_shader_support()))
return NULL;
shader = MEM_callocN(sizeof(GPUShader), "GPUShader");
@@ -1255,30 +1740,35 @@ GPUShader *GPU_shader_create(const char *vertexcode, const char *fragcode, const
shader->vertex = glCreateShaderObjectARB(GL_VERTEX_SHADER_ARB);
if (fragcode)
shader->fragment = glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB);
+ if (geocode)
+ shader->geometry = glCreateShaderObjectARB(GL_GEOMETRY_SHADER_EXT);
+
shader->object = glCreateProgramObjectARB();
if (!shader->object ||
(vertexcode && !shader->vertex) ||
- (fragcode && !shader->fragment))
+ (fragcode && !shader->fragment) ||
+ (geocode && !shader->geometry))
{
fprintf(stderr, "GPUShader, object creation failed.\n");
GPU_shader_free(shader);
return NULL;
}
- gpu_shader_standard_defines(standard_defines);
+ gpu_shader_standard_defines(use_opensubdiv, standard_defines);
+ gpu_shader_standard_extensions(standard_extensions, use_opensubdiv);
if (vertexcode) {
const char *source[5];
/* custom limit, may be too small, beware */
int num_source = 0;
- source[num_source++] = gpu_shader_version();
- source[num_source++] = gpu_shader_standard_extensions();
+ source[num_source++] = gpu_shader_version(use_opensubdiv);
+ source[num_source++] = standard_extensions;
source[num_source++] = standard_defines;
if (defines) source[num_source++] = defines;
- if (vertexcode) source[num_source++] = vertexcode;
+ source[num_source++] = vertexcode;
glAttachObjectARB(shader->object, shader->vertex);
glShaderSourceARB(shader->vertex, num_source, source, NULL);
@@ -1296,16 +1786,28 @@ GPUShader *GPU_shader_create(const char *vertexcode, const char *fragcode, const
}
if (fragcode) {
- const char *source[6];
+ const char *source[7];
int num_source = 0;
- source[num_source++] = gpu_shader_version();
- source[num_source++] = gpu_shader_standard_extensions();
+ source[num_source++] = gpu_shader_version(use_opensubdiv);
+ source[num_source++] = standard_extensions;
source[num_source++] = standard_defines;
+#ifdef WITH_OPENSUBDIV
+ /* TODO(sergey): Move to fragment shader source code generation. */
+ if (use_opensubdiv) {
+ source[num_source++] =
+ "#ifdef USE_OPENSUBDIV\n"
+ "in block {\n"
+ " VertexData v;\n"
+ "} inpt;\n"
+ "#endif\n";
+ }
+#endif
+
if (defines) source[num_source++] = defines;
if (libcode) source[num_source++] = libcode;
- if (fragcode) source[num_source++] = fragcode;
+ source[num_source++] = fragcode;
glAttachObjectARB(shader->object, shader->fragment);
glShaderSourceARB(shader->fragment, num_source, source, NULL);
@@ -1322,11 +1824,54 @@ GPUShader *GPU_shader_create(const char *vertexcode, const char *fragcode, const
}
}
+ if (geocode) {
+ const char *source[6];
+ int num_source = 0;
+
+ source[num_source++] = gpu_shader_version(use_opensubdiv);
+ source[num_source++] = standard_extensions;
+ source[num_source++] = standard_defines;
+
+ if (defines) source[num_source++] = defines;
+ source[num_source++] = geocode;
+
+ glAttachObjectARB(shader->object, shader->geometry);
+ glShaderSourceARB(shader->geometry, num_source, source, NULL);
+
+ glCompileShaderARB(shader->geometry);
+ glGetObjectParameterivARB(shader->geometry, GL_OBJECT_COMPILE_STATUS_ARB, &status);
+
+ if (!status) {
+ glGetInfoLogARB(shader->geometry, sizeof(log), &length, log);
+ shader_print_errors("compile", log, source, num_source);
+
+ GPU_shader_free(shader);
+ return NULL;
+ }
+
+ if (!use_opensubdiv) {
+ GPU_shader_geometry_stage_primitive_io(shader, input, output, number);
+ }
+ }
+
+
#if 0
if (lib && lib->lib)
glAttachObjectARB(shader->object, lib->lib);
#endif
+#ifdef WITH_OPENSUBDIV
+ if (use_opensubdiv) {
+ glBindAttribLocation(shader->object, 0, "position");
+ glBindAttribLocation(shader->object, 1, "normal");
+ GPU_shader_geometry_stage_primitive_io(shader,
+ GL_LINES_ADJACENCY_EXT,
+ GL_TRIANGLE_STRIP,
+ 4);
+
+ }
+#endif
+
glLinkProgramARB(shader->object);
glGetObjectParameterivARB(shader->object, GL_OBJECT_LINK_STATUS_ARB, &status);
if (!status) {
@@ -1334,11 +1879,21 @@ GPUShader *GPU_shader_create(const char *vertexcode, const char *fragcode, const
if (fragcode) shader_print_errors("linking", log, &fragcode, 1);
else if (vertexcode) shader_print_errors("linking", log, &vertexcode, 1);
else if (libcode) shader_print_errors("linking", log, &libcode, 1);
+ else if (geocode) shader_print_errors("linking", log, &geocode, 1);
GPU_shader_free(shader);
return NULL;
}
+#ifdef WITH_OPENSUBDIV
+ /* TODO(sergey): Find a better place for this. */
+ if (use_opensubdiv && GLEW_VERSION_4_1) {
+ glProgramUniform1i(shader->object,
+ glGetUniformLocation(shader->object, "FVarDataBuffer"),
+ 31); /* GL_TEXTURE31 */
+ }
+#endif
+
return shader;
}
@@ -1382,16 +1937,16 @@ GPUShader *GPU_shader_create_lib(const char *code)
void GPU_shader_bind(GPUShader *shader)
{
- GPU_print_error("Pre Shader Bind");
+ GPU_ASSERT_NO_GL_ERRORS("Pre Shader Bind");
glUseProgramObjectARB(shader->object);
- GPU_print_error("Post Shader Bind");
+ GPU_ASSERT_NO_GL_ERRORS("Post Shader Bind");
}
void GPU_shader_unbind(void)
{
- GPU_print_error("Pre Shader Unbind");
+ GPU_ASSERT_NO_GL_ERRORS("Pre Shader Unbind");
glUseProgramObjectARB(0);
- GPU_print_error("Post Shader Unbind");
+ GPU_ASSERT_NO_GL_ERRORS("Post Shader Unbind");
}
void GPU_shader_free(GPUShader *shader)
@@ -1412,12 +1967,12 @@ int GPU_shader_get_uniform(GPUShader *shader, const char *name)
return glGetUniformLocationARB(shader->object, name);
}
-void GPU_shader_uniform_vector(GPUShader *UNUSED(shader), int location, int length, int arraysize, float *value)
+void GPU_shader_uniform_vector(GPUShader *UNUSED(shader), int location, int length, int arraysize, const float *value)
{
- if (location == -1)
+ if (location == -1 || value == NULL)
return;
- GPU_print_error("Pre Uniform Vector");
+ GPU_ASSERT_NO_GL_ERRORS("Pre Uniform Vector");
if (length == 1) glUniform1fvARB(location, arraysize, value);
else if (length == 2) glUniform2fvARB(location, arraysize, value);
@@ -1426,7 +1981,22 @@ void GPU_shader_uniform_vector(GPUShader *UNUSED(shader), int location, int leng
else if (length == 9) glUniformMatrix3fvARB(location, arraysize, 0, value);
else if (length == 16) glUniformMatrix4fvARB(location, arraysize, 0, value);
- GPU_print_error("Post Uniform Vector");
+ GPU_ASSERT_NO_GL_ERRORS("Post Uniform Vector");
+}
+
+void GPU_shader_uniform_vector_int(GPUShader *UNUSED(shader), int location, int length, int arraysize, const int *value)
+{
+ if (location == -1)
+ return;
+
+ GPU_ASSERT_NO_GL_ERRORS("Pre Uniform Vector");
+
+ if (length == 1) glUniform1ivARB(location, arraysize, value);
+ else if (length == 2) glUniform2ivARB(location, arraysize, value);
+ else if (length == 3) glUniform3ivARB(location, arraysize, value);
+ else if (length == 4) glUniform4ivARB(location, arraysize, value);
+
+ GPU_ASSERT_NO_GL_ERRORS("Post Uniform Vector");
}
void GPU_shader_uniform_int(GPUShader *UNUSED(shader), int location, int value)
@@ -1434,9 +2004,14 @@ void GPU_shader_uniform_int(GPUShader *UNUSED(shader), int location, int value)
if (location == -1)
return;
- GPU_print_error("Pre Uniform Int");
- glUniform1iARB(location, value);
- GPU_print_error("Post Uniform Int");
+ GPU_CHECK_ERRORS_AROUND(glUniform1iARB(location, value));
+}
+
+void GPU_shader_geometry_stage_primitive_io(GPUShader *shader, int input, int output, int number)
+{
+ glProgramParameteriEXT(shader->object, GL_GEOMETRY_INPUT_TYPE_EXT, input);
+ glProgramParameteriEXT(shader->object, GL_GEOMETRY_OUTPUT_TYPE_EXT, output);
+ glProgramParameteriEXT(shader->object, GL_GEOMETRY_VERTICES_OUT_EXT, number);
}
void GPU_shader_uniform_texture(GPUShader *UNUSED(shader), int location, GPUTexture *tex)
@@ -1444,7 +2019,7 @@ void GPU_shader_uniform_texture(GPUShader *UNUSED(shader), int location, GPUText
GLenum arbnumber;
if (tex->number >= GG.maxtextures) {
- GPU_print_error("Not enough texture slots.");
+ fprintf(stderr, "Not enough texture slots.");
return;
}
@@ -1454,7 +2029,7 @@ void GPU_shader_uniform_texture(GPUShader *UNUSED(shader), int location, GPUText
if (location == -1)
return;
- GPU_print_error("Pre Uniform Texture");
+ GPU_ASSERT_NO_GL_ERRORS("Pre Uniform Texture");
arbnumber = (GLenum)((GLuint)GL_TEXTURE0_ARB + tex->number);
@@ -1467,18 +2042,14 @@ void GPU_shader_uniform_texture(GPUShader *UNUSED(shader), int location, GPUText
glEnable(tex->target);
if (tex->number != 0) glActiveTextureARB(GL_TEXTURE0_ARB);
- GPU_print_error("Post Uniform Texture");
+ GPU_ASSERT_NO_GL_ERRORS("Post Uniform Texture");
}
int GPU_shader_get_attribute(GPUShader *shader, const char *name)
{
int index;
- GPU_print_error("Pre Get Attribute");
-
- index = glGetAttribLocationARB(shader->object, name);
-
- GPU_print_error("Post Get Attribute");
+ GPU_CHECK_ERRORS_AROUND(index = glGetAttribLocationARB(shader->object, name));
return index;
}
@@ -1490,36 +2061,183 @@ GPUShader *GPU_shader_get_builtin_shader(GPUBuiltinShader shader)
switch (shader) {
case GPU_SHADER_VSM_STORE:
if (!GG.shaders.vsm_store)
- GG.shaders.vsm_store = GPU_shader_create(datatoc_gpu_shader_vsm_store_vert_glsl, datatoc_gpu_shader_vsm_store_frag_glsl, NULL, NULL);
+ GG.shaders.vsm_store = GPU_shader_create(datatoc_gpu_shader_vsm_store_vert_glsl, datatoc_gpu_shader_vsm_store_frag_glsl, NULL, NULL, NULL, 0, 0, 0);
retval = GG.shaders.vsm_store;
break;
case GPU_SHADER_SEP_GAUSSIAN_BLUR:
if (!GG.shaders.sep_gaussian_blur)
- GG.shaders.sep_gaussian_blur = GPU_shader_create(datatoc_gpu_shader_sep_gaussian_blur_vert_glsl, datatoc_gpu_shader_sep_gaussian_blur_frag_glsl, NULL, NULL);
+ GG.shaders.sep_gaussian_blur = GPU_shader_create(datatoc_gpu_shader_sep_gaussian_blur_vert_glsl, datatoc_gpu_shader_sep_gaussian_blur_frag_glsl, NULL, NULL, NULL, 0, 0, 0);
retval = GG.shaders.sep_gaussian_blur;
break;
}
if (retval == NULL)
- printf("Unable to create a GPUShader for builtin shader: %d\n", shader);
+ printf("Unable to create a GPUShader for builtin shader: %u\n", shader);
return retval;
}
+GPUProgram *GPU_shader_get_builtin_program(GPUBuiltinProgram program)
+{
+ GPUProgram *retval = NULL;
+
+ switch (program) {
+ case GPU_PROGRAM_SMOKE:
+ if (!GG.shaders.smoke)
+ GG.shaders.smoke = GPU_program_shader_create(GPU_PROGRAM_TYPE_FRAGMENT, datatoc_gpu_program_smoke_frag_glsl);
+ retval = GG.shaders.smoke;
+ break;
+ case GPU_PROGRAM_SMOKE_COLORED:
+ if (!GG.shaders.smoke_colored)
+ GG.shaders.smoke_colored = GPU_program_shader_create(GPU_PROGRAM_TYPE_FRAGMENT, datatoc_gpu_program_smoke_color_frag_glsl);
+ retval = GG.shaders.smoke_colored;
+ break;
+ }
+
+ if (retval == NULL)
+ printf("Unable to create a GPUProgram for builtin program: %u\n", program);
+
+ return retval;
+}
+
+#define MAX_DEFINES 100
+
+GPUShader *GPU_shader_get_builtin_fx_shader(int effects, bool persp)
+{
+ int offset;
+ char defines[MAX_DEFINES] = "";
+ /* avoid shaders out of range */
+ if (effects >= MAX_FX_SHADERS)
+ return NULL;
+
+ offset = 2 * effects;
+
+ if (persp) {
+ offset += 1;
+ strcat(defines, "#define PERSP_MATRIX\n");
+ }
+
+ if (!GG.shaders.fx_shaders[offset]) {
+ GPUShader *shader;
+
+ switch (effects) {
+ case GPU_SHADER_FX_SSAO:
+ GG.shaders.fx_shaders[offset] = GPU_shader_create(datatoc_gpu_shader_fx_vert_glsl, datatoc_gpu_shader_fx_ssao_frag_glsl, NULL, datatoc_gpu_shader_fx_lib_glsl, defines, 0, 0, 0);
+ break;
+
+ case GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_ONE:
+ strcat(defines, "#define FIRST_PASS\n");
+ GG.shaders.fx_shaders[offset] = GPU_shader_create(datatoc_gpu_shader_fx_dof_vert_glsl, datatoc_gpu_shader_fx_dof_frag_glsl, NULL, datatoc_gpu_shader_fx_lib_glsl, defines, 0, 0, 0);
+ break;
+
+ case GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_TWO:
+ strcat(defines, "#define SECOND_PASS\n");
+ GG.shaders.fx_shaders[offset] = GPU_shader_create(datatoc_gpu_shader_fx_dof_vert_glsl, datatoc_gpu_shader_fx_dof_frag_glsl, NULL, datatoc_gpu_shader_fx_lib_glsl, defines, 0, 0, 0);
+ break;
+
+ case GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_THREE:
+ strcat(defines, "#define THIRD_PASS\n");
+ GG.shaders.fx_shaders[offset] = GPU_shader_create(datatoc_gpu_shader_fx_dof_vert_glsl, datatoc_gpu_shader_fx_dof_frag_glsl, NULL, datatoc_gpu_shader_fx_lib_glsl, defines, 0, 0, 0);
+ break;
+
+ case GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_FOUR:
+ strcat(defines, "#define FOURTH_PASS\n");
+ GG.shaders.fx_shaders[offset] = GPU_shader_create(datatoc_gpu_shader_fx_dof_vert_glsl, datatoc_gpu_shader_fx_dof_frag_glsl, NULL, datatoc_gpu_shader_fx_lib_glsl, defines, 0, 0, 0);
+ break;
+
+ case GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_FIVE:
+ strcat(defines, "#define FIFTH_PASS\n");
+ GG.shaders.fx_shaders[offset] = GPU_shader_create(datatoc_gpu_shader_fx_dof_vert_glsl, datatoc_gpu_shader_fx_dof_frag_glsl, NULL, datatoc_gpu_shader_fx_lib_glsl, defines, 0, 0, 0);
+ break;
+
+ case GPU_SHADER_FX_DEPTH_OF_FIELD_HQ_PASS_ONE:
+ strcat(defines, "#define FIRST_PASS\n");
+ GG.shaders.fx_shaders[offset] = GPU_shader_create(datatoc_gpu_shader_fx_dof_hq_vert_glsl, datatoc_gpu_shader_fx_dof_hq_frag_glsl, NULL, datatoc_gpu_shader_fx_lib_glsl, defines, 0, 0, 0);
+ break;
+
+ case GPU_SHADER_FX_DEPTH_OF_FIELD_HQ_PASS_TWO:
+ strcat(defines, "#define SECOND_PASS\n");
+ shader = GPU_shader_create(datatoc_gpu_shader_fx_dof_hq_vert_glsl, datatoc_gpu_shader_fx_dof_hq_frag_glsl, datatoc_gpu_shader_fx_dof_hq_geo_glsl, datatoc_gpu_shader_fx_lib_glsl,
+ defines, GL_POINTS, GL_TRIANGLE_STRIP, 4);
+ GG.shaders.fx_shaders[offset] = shader;
+ break;
+
+ case GPU_SHADER_FX_DEPTH_OF_FIELD_HQ_PASS_THREE:
+ strcat(defines, "#define THIRD_PASS\n");
+ GG.shaders.fx_shaders[offset] = GPU_shader_create(datatoc_gpu_shader_fx_dof_hq_vert_glsl, datatoc_gpu_shader_fx_dof_hq_frag_glsl, NULL, datatoc_gpu_shader_fx_lib_glsl, defines, 0, 0, 0);
+ break;
+
+ case GPU_SHADER_FX_DEPTH_RESOLVE:
+ GG.shaders.fx_shaders[offset] = GPU_shader_create(datatoc_gpu_shader_fx_vert_glsl, datatoc_gpu_shader_fx_depth_resolve_glsl, NULL, NULL, defines, 0, 0, 0);
+ }
+ }
+
+ return GG.shaders.fx_shaders[offset];
+}
+
+
void GPU_shader_free_builtin_shaders(void)
{
+ int i;
+
if (GG.shaders.vsm_store) {
- MEM_freeN(GG.shaders.vsm_store);
+ GPU_shader_free(GG.shaders.vsm_store);
GG.shaders.vsm_store = NULL;
}
if (GG.shaders.sep_gaussian_blur) {
- MEM_freeN(GG.shaders.sep_gaussian_blur);
+ GPU_shader_free(GG.shaders.sep_gaussian_blur);
GG.shaders.sep_gaussian_blur = NULL;
}
+
+ if (GG.shaders.smoke) {
+ GPU_program_free(GG.shaders.smoke);
+ GG.shaders.smoke = NULL;
+ }
+
+ if (GG.shaders.smoke_colored) {
+ GPU_program_free(GG.shaders.smoke_colored);
+ GG.shaders.smoke_colored = NULL;
+ }
+
+ for (i = 0; i < 2 * MAX_FX_SHADERS; i++) {
+ if (GG.shaders.fx_shaders[i]) {
+ GPU_shader_free(GG.shaders.fx_shaders[i]);
+ GG.shaders.fx_shaders[i] = NULL;
+ }
+ }
}
-#if 0
+bool GPU_mem_stats_supported(void)
+{
+ return (GLEW_NVX_gpu_memory_info || (GLEW_ATI_meminfo)) && (G.debug & G_DEBUG_GPU_MEM);
+}
+
+
+void GPU_mem_stats_get(int *totalmem, int *freemem)
+{
+ if (GLEW_NVX_gpu_memory_info) {
+ /* returned value in Kb */
+ glGetIntegerv(GL_GPU_MEMORY_INFO_TOTAL_AVAILABLE_MEMORY_NVX, totalmem);
+
+ glGetIntegerv(GL_GPU_MEMORY_INFO_CURRENT_AVAILABLE_VIDMEM_NVX, freemem);
+ }
+ else if (GLEW_ATI_meminfo) {
+ int stats[4];
+
+ glGetIntegerv(GL_TEXTURE_FREE_MEMORY_ATI, stats);
+ *freemem = stats[0];
+ *totalmem = 0;
+ }
+ else {
+ *totalmem = 0;
+ *freemem = 0;
+ }
+}
+
+
+#if 0 /* unused */
+
/* GPUPixelBuffer */
typedef struct GPUPixelBuffer {
@@ -1545,7 +2263,7 @@ GPUPixelBuffer *gpu_pixelbuffer_create(int x, int y, int halffloat, int numbuffe
return NULL;
pb = MEM_callocN(sizeof(GPUPixelBuffer), "GPUPBO");
- pb->datasize = x*y*4*((halffloat)? 16: 8);
+ pb->datasize = x * y * 4 * (halffloat ? 16 : 8);
pb->numbuffers = numbuffers;
pb->halffloat = halffloat;
@@ -1573,10 +2291,13 @@ void GPU_pixelbuffer_texture(GPUTexture *tex, GPUPixelBuffer *pb)
GL_STREAM_DRAW_ARB);
pixels = glMapBufferARB(GL_PIXEL_UNPACK_BUFFER_EXT, GL_WRITE_ONLY);
- /*memcpy(pixels, _oImage.data(), pb->datasize);*/
+
+# if 0
+ memcpy(pixels, _oImage.data(), pb->datasize);
+# endif
if (!glUnmapBufferARB(GL_PIXEL_UNPACK_BUFFER_EXT)) {
- fprintf(stderr, "Could not unmap opengl PBO\n");
+ fprintf(stderr, "Could not unmap OpenGL PBO\n");
break;
}
}
@@ -1594,7 +2315,7 @@ static int pixelbuffer_map_into_gpu(GLuint bindcode)
/* do stuff in pixels */
if (!glUnmapBufferARB(GL_PIXEL_UNPACK_BUFFER_EXT)) {
- fprintf(stderr, "Could not unmap opengl PBO\n");
+ fprintf(stderr, "Could not unmap OpenGL PBO\n");
return 0;
}
@@ -1607,8 +2328,7 @@ static void pixelbuffer_copy_to_texture(GPUTexture *tex, GPUPixelBuffer *pb, GLu
glBindTexture(GL_TEXTURE_RECTANGLE_EXT, tex->bindcode);
glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_EXT, bindcode);
- glTexSubImage2D(GL_TEXTURE_RECTANGLE_EXT, 0, 0, 0, tex->w, tex->h,
- GL_RGBA, type, NULL);
+ glTexSubImage2D(GL_TEXTURE_RECTANGLE_EXT, 0, 0, 0, tex->w, tex->h, GL_RGBA, type, NULL);
glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_EXT, 0);
glBindTexture(GL_TEXTURE_RECTANGLE_EXT, 0);
@@ -1623,12 +2343,12 @@ void GPU_pixelbuffer_async_to_gpu(GPUTexture *tex, GPUPixelBuffer *pb)
pixelbuffer_map_into_gpu(pb->bindcode[0]);
}
else {
- pb->current = (pb->current+1)%pb->numbuffers;
- newbuffer = (pb->current+1)%pb->numbuffers;
+ pb->current = (pb->current + 1) % pb->numbuffers;
+ newbuffer = (pb->current + 1) % pb->numbuffers;
pixelbuffer_map_into_gpu(pb->bindcode[newbuffer]);
pixelbuffer_copy_to_texture(tex, pb, pb->bindcode[pb->current]);
}
}
-#endif
+#endif /* unused */
diff --git a/source/blender/gpu/intern/gpu_init_exit.c b/source/blender/gpu/intern/gpu_init_exit.c
new file mode 100644
index 00000000000..3a8a6fca23b
--- /dev/null
+++ b/source/blender/gpu/intern/gpu_init_exit.c
@@ -0,0 +1,79 @@
+/*
+ * ***** 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): Jason Wilkins
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/gpu/intern/gpu_init_exit.c
+ * \ingroup gpu
+ */
+
+#include "BKE_DerivedMesh.h"
+
+#include "BLI_sys_types.h"
+#include "GPU_init_exit.h" /* interface */
+#include "GPU_buffers.h"
+
+#include "BKE_global.h"
+
+#include "intern/gpu_codegen.h"
+#include "intern/gpu_private.h"
+
+/**
+ * although the order of initialization and shutdown should not matter
+ * (except for the extensions), I chose alphabetical and reverse alphabetical order
+ */
+
+static bool initialized = false;
+
+void GPU_init(void)
+{
+ /* can't avoid calling this multiple times, see wm_window_add_ghostwindow */
+ if (initialized)
+ return;
+
+ initialized = true;
+
+ gpu_extensions_init(); /* must come first */
+
+ gpu_codegen_init();
+
+ if (G.debug & G_DEBUG_GPU)
+ gpu_debug_init();
+
+}
+
+
+
+void GPU_exit(void)
+{
+ if (G.debug & G_DEBUG_GPU)
+ gpu_debug_exit();
+ gpu_codegen_exit();
+
+ gpu_extensions_exit(); /* must come last */
+ GPU_buffer_multires_free(true);
+
+ initialized = false;
+}
diff --git a/source/blender/gpu/intern/gpu_material.c b/source/blender/gpu/intern/gpu_material.c
index 81dcd9cf450..5b647232934 100644
--- a/source/blender/gpu/intern/gpu_material.c
+++ b/source/blender/gpu/intern/gpu_material.c
@@ -35,8 +35,6 @@
#include <math.h>
#include <string.h>
-#include "GL/glew.h"
-
#include "MEM_guardedalloc.h"
#include "DNA_lamp_types.h"
@@ -78,10 +76,25 @@ typedef enum DynMatProperty {
DYN_LAMP_PERSMAT = 8,
} DynMatProperty;
+static struct GPUWorld {
+ float mistenabled;
+ float mistype;
+ float miststart;
+ float mistdistance;
+ float mistintensity;
+ float mistcol[4];
+ float horicol[3];
+ float ambcol[4];
+} GPUWorld;
+
struct GPUMaterial {
Scene *scene;
Material *ma;
+ /* material for mesh surface, worlds or something else.
+ * some code generation is done differently depending on the use case */
+ int type;
+
/* for creating the material */
ListBase nodes;
GPUNodeLink *outlink;
@@ -89,7 +102,6 @@ struct GPUMaterial {
/* for binding the material */
GPUPass *pass;
GPUVertexAttribs attribs;
- int bound;
int builtins;
int alpha, obcolalpha;
int dynproperty;
@@ -98,8 +110,17 @@ struct GPUMaterial {
int viewmatloc, invviewmatloc;
int obmatloc, invobmatloc;
int obcolloc, obautobumpscaleloc;
+ int cameratexcofacloc;
+
+ int partscalarpropsloc;
+ int partcoloc;
+ int partvel;
+ int partangvel;
ListBase lamps;
+ bool bound;
+
+ bool is_opensubdiv;
};
struct GPULamp {
@@ -153,7 +174,7 @@ static GPUMaterial *GPU_material_construct_begin(Material *ma)
{
GPUMaterial *material = MEM_callocN(sizeof(GPUMaterial), "GPUMaterial");
- material->ma= ma;
+ material->ma = ma;
return material;
}
@@ -166,14 +187,14 @@ static void gpu_material_set_attrib_id(GPUMaterial *material)
char name[32];
int a, b;
- attribs= &material->attribs;
- pass= material->pass;
+ attribs = &material->attribs;
+ pass = material->pass;
if (!pass) {
attribs->totlayer = 0;
return;
}
- shader= GPU_pass_shader(pass);
+ shader = GPU_pass_shader(pass);
if (!shader) {
attribs->totlayer = 0;
return;
@@ -183,7 +204,7 @@ static void gpu_material_set_attrib_id(GPUMaterial *material)
* in case the attrib does not get a valid index back, it was probably
* removed by the glsl compiler by dead code elimination */
- for (a=0, b=0; a<attribs->totlayer; a++) {
+ for (a = 0, b = 0; a < attribs->totlayer; a++) {
BLI_snprintf(name, sizeof(name), "att%d", attribs->layer[a].attribid);
attribs->layer[a].glindex = GPU_shader_get_attribute(shader, name);
@@ -196,7 +217,7 @@ static void gpu_material_set_attrib_id(GPUMaterial *material)
attribs->totlayer = b;
}
-static int GPU_material_construct_end(GPUMaterial *material)
+static int GPU_material_construct_end(GPUMaterial *material, const char *passname)
{
if (material->outlink) {
GPUNodeLink *outlink;
@@ -204,7 +225,8 @@ static int GPU_material_construct_end(GPUMaterial *material)
outlink = material->outlink;
material->pass = GPU_generate_pass(&material->nodes, outlink,
- &material->attribs, &material->builtins, material->ma->id.name);
+ &material->attribs, &material->builtins, material->type,
+ passname, material->is_opensubdiv);
if (!material->pass)
return 0;
@@ -225,39 +247,53 @@ static int GPU_material_construct_end(GPUMaterial *material)
material->obcolloc = GPU_shader_get_uniform(shader, GPU_builtin_name(GPU_OBCOLOR));
if (material->builtins & GPU_AUTO_BUMPSCALE)
material->obautobumpscaleloc = GPU_shader_get_uniform(shader, GPU_builtin_name(GPU_AUTO_BUMPSCALE));
+ if (material->builtins & GPU_CAMERA_TEXCO_FACTORS)
+ material->cameratexcofacloc = GPU_shader_get_uniform(shader, GPU_builtin_name(GPU_CAMERA_TEXCO_FACTORS));
+ if (material->builtins & GPU_PARTICLE_SCALAR_PROPS)
+ material->partscalarpropsloc = GPU_shader_get_uniform(shader, GPU_builtin_name(GPU_PARTICLE_SCALAR_PROPS));
+ if (material->builtins & GPU_PARTICLE_LOCATION)
+ material->partcoloc = GPU_shader_get_uniform(shader, GPU_builtin_name(GPU_PARTICLE_LOCATION));
+ if (material->builtins & GPU_PARTICLE_VELOCITY)
+ material->partvel = GPU_shader_get_uniform(shader, GPU_builtin_name(GPU_PARTICLE_VELOCITY));
+ if (material->builtins & GPU_PARTICLE_ANG_VELOCITY)
+ material->partangvel = GPU_shader_get_uniform(shader, GPU_builtin_name(GPU_PARTICLE_ANG_VELOCITY));
return 1;
}
return 0;
}
-void GPU_material_free(Material *ma)
+void GPU_material_free(ListBase *gpumaterial)
{
LinkData *link;
LinkData *nlink, *mlink, *next;
- for (link=ma->gpumaterial.first; link; link=link->next) {
+ for (link = gpumaterial->first; link; link = link->next) {
GPUMaterial *material = link->data;
if (material->pass)
GPU_pass_free(material->pass);
- for (nlink=material->lamps.first; nlink; nlink=nlink->next) {
+ for (nlink = material->lamps.first; nlink; nlink = nlink->next) {
GPULamp *lamp = nlink->data;
- for (mlink=lamp->materials.first; mlink; mlink=next) {
- next = mlink->next;
- if (mlink->data == ma)
- BLI_freelinkN(&lamp->materials, mlink);
+ if (material->ma) {
+ Material *ma = material->ma;
+
+ for (mlink = lamp->materials.first; mlink; mlink = next) {
+ next = mlink->next;
+ if (mlink->data == ma)
+ BLI_freelinkN(&lamp->materials, mlink);
+ }
}
}
-
+
BLI_freelistN(&material->lamps);
MEM_freeN(material);
}
- BLI_freelistN(&ma->gpumaterial);
+ BLI_freelistN(gpumaterial);
}
bool GPU_lamp_override_visible(GPULamp *lamp, SceneRenderLayer *srl, Material *ma)
@@ -270,7 +306,7 @@ bool GPU_lamp_override_visible(GPULamp *lamp, SceneRenderLayer *srl, Material *m
return true;
}
-void GPU_material_bind(GPUMaterial *material, int oblay, int viewlay, double time, int mipmap, float viewmat[4][4], float viewinv[4][4], bool scenelock)
+void GPU_material_bind(GPUMaterial *material, int oblay, int viewlay, double time, int mipmap, float viewmat[4][4], float viewinv[4][4], float camerafactors[4], bool scenelock)
{
if (material->pass) {
LinkData *nlink;
@@ -282,42 +318,44 @@ void GPU_material_bind(GPUMaterial *material, int oblay, int viewlay, double tim
viewlay &= srl->lay;
/* handle layer lamps */
- for (nlink=material->lamps.first; nlink; nlink=nlink->next) {
- lamp= nlink->data;
-
- if (!lamp->hide && (lamp->lay & viewlay) && (!(lamp->mode & LA_LAYER) || (lamp->lay & oblay))
- && GPU_lamp_override_visible(lamp, srl, material->ma)) {
- lamp->dynenergy = lamp->energy;
- copy_v3_v3(lamp->dyncol, lamp->col);
- }
- else {
- lamp->dynenergy = 0.0f;
- lamp->dyncol[0]= lamp->dyncol[1]= lamp->dyncol[2] = 0.0f;
- }
-
- if (material->dynproperty & DYN_LAMP_VEC) {
- copy_v3_v3(lamp->dynvec, lamp->vec);
- normalize_v3(lamp->dynvec);
- negate_v3(lamp->dynvec);
- mul_mat3_m4_v3(viewmat, lamp->dynvec);
- }
-
- if (material->dynproperty & DYN_LAMP_CO) {
- copy_v3_v3(lamp->dynco, lamp->co);
- mul_m4_v3(viewmat, lamp->dynco);
- }
-
- if (material->dynproperty & DYN_LAMP_IMAT) {
- mul_m4_m4m4(lamp->dynimat, lamp->imat, viewinv);
- }
-
- if (material->dynproperty & DYN_LAMP_PERSMAT) {
- if (!GPU_lamp_has_shadow_buffer(lamp)) /* The lamp matrices are already updated if we're using shadow buffers */
- GPU_lamp_update_buffer_mats(lamp);
- mul_m4_m4m4(lamp->dynpersmat, lamp->persmat, viewinv);
+ if (material->type == GPU_MATERIAL_TYPE_MESH) {
+ for (nlink = material->lamps.first; nlink; nlink = nlink->next) {
+ lamp = nlink->data;
+
+ if (!lamp->hide && (lamp->lay & viewlay) && (!(lamp->mode & LA_LAYER) || (lamp->lay & oblay))
+ && GPU_lamp_override_visible(lamp, srl, material->ma)) {
+ lamp->dynenergy = lamp->energy;
+ copy_v3_v3(lamp->dyncol, lamp->col);
+ }
+ else {
+ lamp->dynenergy = 0.0f;
+ lamp->dyncol[0] = lamp->dyncol[1] = lamp->dyncol[2] = 0.0f;
+ }
+
+ if (material->dynproperty & DYN_LAMP_VEC) {
+ copy_v3_v3(lamp->dynvec, lamp->vec);
+ normalize_v3(lamp->dynvec);
+ negate_v3(lamp->dynvec);
+ mul_mat3_m4_v3(viewmat, lamp->dynvec);
+ }
+
+ if (material->dynproperty & DYN_LAMP_CO) {
+ copy_v3_v3(lamp->dynco, lamp->co);
+ mul_m4_v3(viewmat, lamp->dynco);
+ }
+
+ if (material->dynproperty & DYN_LAMP_IMAT) {
+ mul_m4_m4m4(lamp->dynimat, lamp->imat, viewinv);
+ }
+
+ if (material->dynproperty & DYN_LAMP_PERSMAT) {
+ if (!GPU_lamp_has_shadow_buffer(lamp)) /* The lamp matrices are already updated if we're using shadow buffers */
+ GPU_lamp_update_buffer_mats(lamp);
+ mul_m4_m4m4(lamp->dynpersmat, lamp->persmat, viewinv);
+ }
}
}
-
+
/* note material must be bound before setting uniforms */
GPU_pass_bind(material->pass, time, mipmap);
@@ -328,6 +366,16 @@ void GPU_material_bind(GPUMaterial *material, int oblay, int viewlay, double tim
if (material->builtins & GPU_INVERSE_VIEW_MATRIX) {
GPU_shader_uniform_vector(shader, material->invviewmatloc, 16, 1, (float*)viewinv);
}
+ if (material->builtins & GPU_CAMERA_TEXCO_FACTORS) {
+ if (camerafactors) {
+ GPU_shader_uniform_vector(shader, material->cameratexcofacloc, 4, 1, (float*)camerafactors);
+ }
+ else {
+ /* use default, no scaling no offset */
+ float borders[4] = {1.0f, 1.0f, 0.0f, 0.0f};
+ GPU_shader_uniform_vector(shader, material->cameratexcofacloc, 4, 1, (float*)borders);
+ }
+ }
GPU_pass_update_uniforms(material->pass);
@@ -335,7 +383,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_bind_uniforms(GPUMaterial *material, float obmat[4][4], float obcol[4], float autobumpscale, GPUParticleInfo* pi)
{
if (material->pass) {
GPUShader *shader = GPU_pass_shader(material->pass);
@@ -357,6 +405,19 @@ void GPU_material_bind_uniforms(GPUMaterial *material, float obmat[4][4], float
if (material->builtins & GPU_AUTO_BUMPSCALE) {
GPU_shader_uniform_vector(shader, material->obautobumpscaleloc, 1, 1, &autobumpscale);
}
+ if (material->builtins & GPU_PARTICLE_SCALAR_PROPS) {
+ GPU_shader_uniform_vector(shader, material->partscalarpropsloc, 4, 1, pi->scalprops);
+ }
+ if (material->builtins & GPU_PARTICLE_LOCATION) {
+ GPU_shader_uniform_vector(shader, material->partcoloc, 3, 1, pi->location);
+ }
+ if (material->builtins & GPU_PARTICLE_VELOCITY) {
+ GPU_shader_uniform_vector(shader, material->partvel, 3, 1, pi->velocity);
+ }
+ if (material->builtins & GPU_PARTICLE_ANG_VELOCITY) {
+ GPU_shader_uniform_vector(shader, material->partangvel, 3, 1, pi->angular_velocity);
+ }
+
}
}
@@ -368,7 +429,7 @@ void GPU_material_unbind(GPUMaterial *material)
}
}
-int GPU_material_bound(GPUMaterial *material)
+bool GPU_material_bound(GPUMaterial *material)
{
return material->bound;
}
@@ -378,6 +439,12 @@ Scene *GPU_material_scene(GPUMaterial *material)
return material->scene;
}
+GPUMatType GPU_Material_get_type(GPUMaterial *material)
+{
+ return material->type;
+}
+
+
void GPU_material_vertex_attributes(GPUMaterial *material, GPUVertexAttribs *attribs)
{
*attribs = material->attribs;
@@ -386,12 +453,12 @@ void GPU_material_vertex_attributes(GPUMaterial *material, GPUVertexAttribs *att
void GPU_material_output_link(GPUMaterial *material, GPUNodeLink *link)
{
if (!material->outlink)
- material->outlink= link;
+ material->outlink = link;
}
void GPU_material_enable_alpha(GPUMaterial *material)
{
- material->alpha= 1;
+ material->alpha = 1;
}
GPUBlendMode GPU_material_alpha_blend(GPUMaterial *material, float obcol[4])
@@ -414,7 +481,7 @@ bool GPU_material_do_color_management(GPUMaterial *mat)
if (!BKE_scene_check_color_management_enabled(mat->scene))
return false;
- return !((mat->scene->gm.flag & GAME_GLSL_NO_COLOR_MANAGEMENT));
+ return true;
}
bool GPU_material_use_new_shading_nodes(GPUMaterial *mat)
@@ -427,7 +494,7 @@ static GPUNodeLink *lamp_get_visibility(GPUMaterial *mat, GPULamp *lamp, GPUNode
GPUNodeLink *visifac, *inpr;
/* from get_lamp_visibility */
- if (lamp->type==LA_SUN || lamp->type==LA_HEMI) {
+ if (lamp->type == LA_SUN || lamp->type == LA_HEMI) {
mat->dynproperty |= DYN_LAMP_VEC;
GPU_link(mat, "lamp_visibility_sun_hemi", GPU_dynamic_uniform(lamp->dynvec, GPU_DYNAMIC_LAMP_DYNVEC, lamp->ob), lv, dist, &visifac);
return visifac;
@@ -436,7 +503,7 @@ static GPUNodeLink *lamp_get_visibility(GPUMaterial *mat, GPULamp *lamp, GPUNode
mat->dynproperty |= DYN_LAMP_CO;
GPU_link(mat, "lamp_visibility_other", GPU_builtin(GPU_VIEW_POSITION), GPU_dynamic_uniform(lamp->dynco, GPU_DYNAMIC_LAMP_DYNCO, lamp->ob), lv, dist, &visifac);
- if (lamp->type==LA_AREA)
+ if (lamp->type == LA_AREA)
return visifac;
switch (lamp->falloff_type) {
@@ -452,15 +519,16 @@ static GPUNodeLink *lamp_get_visibility(GPUMaterial *mat, GPULamp *lamp, GPUNode
GPU_link(mat, "lamp_falloff_sliders", GPU_dynamic_uniform(&lamp->dist, GPU_DYNAMIC_LAMP_DISTANCE, lamp->ob), GPU_dynamic_uniform(&lamp->att1, GPU_DYNAMIC_LAMP_ATT1, lamp->ob), GPU_dynamic_uniform(&lamp->att2, GPU_DYNAMIC_LAMP_ATT2, lamp->ob), *dist, &visifac);
break;
case LA_FALLOFF_CURVE:
- {
- float *array;
- int size;
+ {
+ float *array;
+ int size;
+
+ curvemapping_initialize(lamp->curfalloff);
+ curvemapping_table_RGBA(lamp->curfalloff, &array, &size);
+ GPU_link(mat, "lamp_falloff_curve", GPU_dynamic_uniform(&lamp->dist, GPU_DYNAMIC_LAMP_DISTANCE, lamp->ob), GPU_texture(size, array), *dist, &visifac);
- curvemapping_initialize(lamp->curfalloff);
- curvemapping_table_RGBA(lamp->curfalloff, &array, &size);
- GPU_link(mat, "lamp_falloff_curve", GPU_dynamic_uniform(&lamp->dist, GPU_DYNAMIC_LAMP_DISTANCE, lamp->ob), GPU_texture(size, array), *dist, &visifac);
- }
break;
+ }
}
if (lamp->mode & LA_SPHERE)
@@ -488,34 +556,34 @@ static GPUNodeLink *lamp_get_visibility(GPUMaterial *mat, GPULamp *lamp, GPUNode
#if 0
static void area_lamp_vectors(LampRen *lar)
{
- float xsize= 0.5*lar->area_size, ysize= 0.5*lar->area_sizey, multifac;
+ float xsize = 0.5f * lar->area_size, ysize = 0.5f * lar->area_sizey, multifac;
/* make it smaller, so area light can be multisampled */
- multifac= 1.0f/sqrt((float)lar->ray_totsamp);
+ multifac = 1.0f / sqrtf((float)lar->ray_totsamp);
xsize *= multifac;
ysize *= multifac;
/* corner vectors */
- lar->area[0][0]= lar->co[0] - xsize*lar->mat[0][0] - ysize*lar->mat[1][0];
- lar->area[0][1]= lar->co[1] - xsize*lar->mat[0][1] - ysize*lar->mat[1][1];
- lar->area[0][2]= lar->co[2] - xsize*lar->mat[0][2] - ysize*lar->mat[1][2];
+ lar->area[0][0] = lar->co[0] - xsize * lar->mat[0][0] - ysize * lar->mat[1][0];
+ lar->area[0][1] = lar->co[1] - xsize * lar->mat[0][1] - ysize * lar->mat[1][1];
+ lar->area[0][2] = lar->co[2] - xsize * lar->mat[0][2] - ysize * lar->mat[1][2];
/* corner vectors */
- lar->area[1][0]= lar->co[0] - xsize*lar->mat[0][0] + ysize*lar->mat[1][0];
- lar->area[1][1]= lar->co[1] - xsize*lar->mat[0][1] + ysize*lar->mat[1][1];
- lar->area[1][2]= lar->co[2] - xsize*lar->mat[0][2] + ysize*lar->mat[1][2];
+ lar->area[1][0] = lar->co[0] - xsize * lar->mat[0][0] + ysize * lar->mat[1][0];
+ lar->area[1][1] = lar->co[1] - xsize * lar->mat[0][1] + ysize * lar->mat[1][1];
+ lar->area[1][2] = lar->co[2] - xsize * lar->mat[0][2] + ysize * lar->mat[1][2];
/* corner vectors */
- lar->area[2][0]= lar->co[0] + xsize*lar->mat[0][0] + ysize*lar->mat[1][0];
- lar->area[2][1]= lar->co[1] + xsize*lar->mat[0][1] + ysize*lar->mat[1][1];
- lar->area[2][2]= lar->co[2] + xsize*lar->mat[0][2] + ysize*lar->mat[1][2];
+ lar->area[2][0] = lar->co[0] + xsize * lar->mat[0][0] + ysize * lar->mat[1][0];
+ lar->area[2][1] = lar->co[1] + xsize * lar->mat[0][1] + ysize * lar->mat[1][1];
+ lar->area[2][2] = lar->co[2] + xsize * lar->mat[0][2] + ysize * lar->mat[1][2];
/* corner vectors */
- lar->area[3][0]= lar->co[0] + xsize*lar->mat[0][0] - ysize*lar->mat[1][0];
- lar->area[3][1]= lar->co[1] + xsize*lar->mat[0][1] - ysize*lar->mat[1][1];
- lar->area[3][2]= lar->co[2] + xsize*lar->mat[0][2] - ysize*lar->mat[1][2];
+ lar->area[3][0] = lar->co[0] + xsize * lar->mat[0][0] - ysize * lar->mat[1][0];
+ lar->area[3][1] = lar->co[1] + xsize * lar->mat[0][1] - ysize * lar->mat[1][1];
+ lar->area[3][2] = lar->co[2] + xsize * lar->mat[0][2] - ysize * lar->mat[1][2];
/* only for correction button size, matrix size works on energy */
- lar->areasize= lar->dist*lar->dist/(4.0*xsize*ysize);
+ lar->areasize = lar->dist * lar->dist / (4.0f * xsize * ysize);
}
#endif
@@ -549,8 +617,8 @@ static void do_colorband_blend(GPUMaterial *mat, ColorBand *coba, GPUNodeLink *f
static void ramp_diffuse_result(GPUShadeInput *shi, GPUNodeLink **diff)
{
- Material *ma= shi->mat;
- GPUMaterial *mat= shi->gpumat;
+ Material *ma = shi->mat;
+ GPUMaterial *mat = shi->gpumat;
GPUNodeLink *fac;
if (!(mat->scene->gm.flag & GAME_GLSL_NO_RAMPS)) {
@@ -579,18 +647,18 @@ static void add_to_diffuse(GPUMaterial *mat, Material *ma, GPUShadeInput *shi, G
else {
/* input */
switch (ma->rampin_col) {
- case MA_RAMP_IN_ENERGY:
- GPU_link(mat, "ramp_rgbtobw", rgb, &fac);
- break;
- case MA_RAMP_IN_SHADER:
- fac= is;
- break;
- case MA_RAMP_IN_NOR:
- GPU_link(mat, "vec_math_dot", shi->view, shi->vn, &tmp, &fac);
- break;
- default:
- GPU_link(mat, "set_value_zero", &fac);
- break;
+ case MA_RAMP_IN_ENERGY:
+ GPU_link(mat, "ramp_rgbtobw", rgb, &fac);
+ break;
+ case MA_RAMP_IN_SHADER:
+ fac= is;
+ break;
+ case MA_RAMP_IN_NOR:
+ GPU_link(mat, "vec_math_dot", shi->view, shi->vn, &tmp, &fac);
+ break;
+ default:
+ GPU_link(mat, "set_value_zero", &fac);
+ break;
}
/* colorband + blend */
@@ -606,12 +674,12 @@ static void add_to_diffuse(GPUMaterial *mat, Material *ma, GPUShadeInput *shi, G
static void ramp_spec_result(GPUShadeInput *shi, GPUNodeLink **spec)
{
- Material *ma= shi->mat;
- GPUMaterial *mat= shi->gpumat;
+ Material *ma = shi->mat;
+ GPUMaterial *mat = shi->gpumat;
GPUNodeLink *fac;
if (!(mat->scene->gm.flag & GAME_GLSL_NO_RAMPS) &&
- ma->ramp_spec && ma->rampin_spec==MA_RAMP_IN_RESULT)
+ ma->ramp_spec && ma->rampin_spec == MA_RAMP_IN_RESULT)
{
GPU_link(mat, "ramp_rgbtobw", *spec, &fac);
@@ -622,29 +690,29 @@ static void ramp_spec_result(GPUShadeInput *shi, GPUNodeLink **spec)
static void do_specular_ramp(GPUShadeInput *shi, GPUNodeLink *is, GPUNodeLink *t, GPUNodeLink **spec)
{
- Material *ma= shi->mat;
- GPUMaterial *mat= shi->gpumat;
+ Material *ma = shi->mat;
+ GPUMaterial *mat = shi->gpumat;
GPUNodeLink *fac, *tmp;
*spec = shi->specrgb;
/* MA_RAMP_IN_RESULT is exception */
- if (ma->ramp_spec && (ma->rampin_spec!=MA_RAMP_IN_RESULT)) {
+ if (ma->ramp_spec && (ma->rampin_spec != MA_RAMP_IN_RESULT)) {
/* input */
switch (ma->rampin_spec) {
- case MA_RAMP_IN_ENERGY:
- fac = t;
- break;
- case MA_RAMP_IN_SHADER:
- fac = is;
- break;
- case MA_RAMP_IN_NOR:
- GPU_link(mat, "vec_math_dot", shi->view, shi->vn, &tmp, &fac);
- break;
- default:
- GPU_link(mat, "set_value_zero", &fac);
- break;
+ case MA_RAMP_IN_ENERGY:
+ fac = t;
+ break;
+ case MA_RAMP_IN_SHADER:
+ fac = is;
+ break;
+ case MA_RAMP_IN_NOR:
+ GPU_link(mat, "vec_math_dot", shi->view, shi->vn, &tmp, &fac);
+ break;
+ default:
+ GPU_link(mat, "set_value_zero", &fac);
+ break;
}
/* colorband + blend */
@@ -666,10 +734,10 @@ static void shade_light_textures(GPUMaterial *mat, GPULamp *lamp, GPUNodeLink **
int i;
float one = 1.f;
- for (i=0; i<MAX_MTEX; ++i) {
+ for (i = 0; i < MAX_MTEX; ++i) {
mtex = lamp->la->mtex[i];
- if (mtex && mtex->tex->type & TEX_IMAGE && mtex->tex->ima) {
+ if (mtex && mtex->tex->type & TEX_IMAGE && mtex->tex->ima) {
mat->dynproperty |= DYN_LAMP_PERSMAT;
GPU_link(mat, "shade_light_texture",
@@ -677,29 +745,31 @@ static void shade_light_textures(GPUMaterial *mat, GPULamp *lamp, GPUNodeLink **
GPU_image(mtex->tex->ima, &mtex->tex->iuser, false),
GPU_dynamic_uniform((float*)lamp->dynpersmat, GPU_DYNAMIC_LAMP_DYNPERSMAT, lamp->ob),
&tex_rgb);
- texture_rgb_blend(mat, tex_rgb, *rgb, GPU_uniform(&one), GPU_uniform(&mtex->colfac), mtex->blendtype, rgb);
+ texture_rgb_blend(mat, tex_rgb, *rgb, GPU_uniform(&one), GPU_uniform(&mtex->colfac), mtex->blendtype, rgb);
}
}
}
static void shade_one_light(GPUShadeInput *shi, GPUShadeResult *shr, GPULamp *lamp)
{
- Material *ma= shi->mat;
- GPUMaterial *mat= shi->gpumat;
+ Material *ma = shi->mat;
+ GPUMaterial *mat = shi->gpumat;
GPUNodeLink *lv, *dist, *visifac, *is, *inp, *i, *vn, *view;
- GPUNodeLink *outcol, *specfac, *t, *shadfac= NULL, *lcol;
+ GPUNodeLink *outcol, *specfac, *t, *shadfac = NULL, *lcol;
float one = 1.0f;
if ((lamp->mode & LA_ONLYSHADOW) && !(ma->mode & MA_SHADOW))
return;
- vn= shi->vn;
- view= shi->view;
+ vn = shi->vn;
+ view = shi->view;
- visifac= lamp_get_visibility(mat, lamp, &lv, &dist);
+ visifac = lamp_get_visibility(mat, lamp, &lv, &dist);
- /*if (ma->mode & MA_TANGENT_V)
- GPU_link(mat, "shade_tangent_v", lv, GPU_attribute(CD_TANGENT, ""), &vn);*/
+#if 0
+ if (ma->mode & MA_TANGENT_V)
+ GPU_link(mat, "shade_tangent_v", lv, GPU_attribute(CD_TANGENT, ""), &vn);
+#endif
GPU_link(mat, "shade_inp", vn, lv, &inp);
@@ -711,23 +781,23 @@ static void shade_one_light(GPUShadeInput *shi, GPUShadeResult *shr, GPULamp *la
}
else {
if (lamp->type == LA_AREA) {
- float area[4][4]= {{0.0f}}, areasize= 0.0f;
+ float area[4][4] = {{0.0f}}, areasize = 0.0f;
mat->dynproperty |= DYN_LAMP_VEC|DYN_LAMP_CO;
GPU_link(mat, "shade_inp_area", GPU_builtin(GPU_VIEW_POSITION), GPU_dynamic_uniform(lamp->dynco, GPU_DYNAMIC_LAMP_DYNCO, lamp->ob), GPU_dynamic_uniform(lamp->dynvec, GPU_DYNAMIC_LAMP_DYNVEC, lamp->ob), vn, GPU_uniform((float*)area),
GPU_uniform(&areasize), GPU_uniform(&lamp->k), &inp);
}
- is= inp; /* Lambert */
+ is = inp; /* Lambert */
if (!(mat->scene->gm.flag & GAME_GLSL_NO_SHADERS)) {
- if (ma->diff_shader==MA_DIFF_ORENNAYAR)
+ if (ma->diff_shader == MA_DIFF_ORENNAYAR)
GPU_link(mat, "shade_diffuse_oren_nayer", inp, vn, lv, view, GPU_uniform(&ma->roughness), &is);
- else if (ma->diff_shader==MA_DIFF_TOON)
+ else if (ma->diff_shader == MA_DIFF_TOON)
GPU_link(mat, "shade_diffuse_toon", vn, lv, view, GPU_uniform(&ma->param[0]), GPU_uniform(&ma->param[1]), &is);
- else if (ma->diff_shader==MA_DIFF_MINNAERT)
+ else if (ma->diff_shader == MA_DIFF_MINNAERT)
GPU_link(mat, "shade_diffuse_minnaert", inp, vn, view, GPU_uniform(&ma->darkness), &is);
- else if (ma->diff_shader==MA_DIFF_FRESNEL)
+ else if (ma->diff_shader == MA_DIFF_FRESNEL)
GPU_link(mat, "shade_diffuse_fresnel", vn, lv, view, GPU_uniform(&ma->param[0]), GPU_uniform(&ma->param[1]), &is);
}
}
@@ -739,8 +809,9 @@ static void shade_one_light(GPUShadeInput *shi, GPUShadeResult *shr, GPULamp *la
i = is;
GPU_link(mat, "shade_visifac", i, visifac, shi->refl, &i);
- GPU_link(mat, "set_value", GPU_dynamic_uniform(lamp->dyncol, GPU_DYNAMIC_LAMP_DYNCOL, lamp->ob), &lcol);
+ GPU_link(mat, "set_rgb", GPU_dynamic_uniform(lamp->dyncol, GPU_DYNAMIC_LAMP_DYNCOL, lamp->ob), &lcol);
shade_light_textures(mat, lamp, &lcol);
+ GPU_link(mat, "shade_mul_value_v3", GPU_dynamic_uniform(&lamp->dynenergy, GPU_DYNAMIC_LAMP_DYNENERGY, lamp->ob), lcol, &lcol);
#if 0
if (ma->mode & MA_TANGENT_VN)
@@ -748,7 +819,7 @@ static void shade_one_light(GPUShadeInput *shi, GPUShadeResult *shr, GPULamp *la
#endif
/* this replaces if (i > 0.0) conditional until that is supported */
- // done in shade_visifac now, GPU_link(mat, "mtex_value_clamp_positive", i, &i);
+ /* done in shade_visifac now, GPU_link(mat, "mtex_value_clamp_positive", i, &i); */
if ((ma->mode & MA_SHADOW) && GPU_lamp_has_shadow_buffer(lamp)) {
if (!(mat->scene->gm.flag & GAME_GLSL_NO_SHADOWS)) {
@@ -821,18 +892,18 @@ static void shade_one_light(GPUShadeInput *shi, GPUShadeResult *shr, GPULamp *la
GPU_link(mat, "shade_add_clamped", shr->spec, outcol, &shr->spec);
}
else {
- if (ma->spec_shader==MA_SPEC_PHONG)
+ if (ma->spec_shader == MA_SPEC_PHONG)
GPU_link(mat, "shade_phong_spec", vn, lv, view, shi->har, &specfac);
- else if (ma->spec_shader==MA_SPEC_COOKTORR)
+ else if (ma->spec_shader == MA_SPEC_COOKTORR)
GPU_link(mat, "shade_cooktorr_spec", vn, lv, view, shi->har, &specfac);
- else if (ma->spec_shader==MA_SPEC_BLINN)
+ else if (ma->spec_shader == MA_SPEC_BLINN)
GPU_link(mat, "shade_blinn_spec", vn, lv, view, GPU_uniform(&ma->refrac), shi->har, &specfac);
- else if (ma->spec_shader==MA_SPEC_WARDISO)
+ else if (ma->spec_shader == MA_SPEC_WARDISO)
GPU_link(mat, "shade_wardiso_spec", vn, lv, view, GPU_uniform(&ma->rms), &specfac);
else
GPU_link(mat, "shade_toon_spec", vn, lv, view, GPU_uniform(&ma->param[2]), GPU_uniform(&ma->param[3]), &specfac);
- if (lamp->type==LA_AREA)
+ if (lamp->type == LA_AREA)
GPU_link(mat, "shade_spec_area_inp", specfac, inp, &specfac);
GPU_link(mat, "shade_spec_t", shadfac, shi->spec, visifac, specfac, &t);
@@ -862,9 +933,9 @@ static void material_lights(GPUShadeInput *shi, GPUShadeResult *shr)
GPULamp *lamp;
for (SETLOOPER(shi->gpumat->scene, sce_iter, base)) {
- ob= base->object;
+ ob = base->object;
- if (ob->type==OB_LAMP) {
+ if (ob->type == OB_LAMP) {
lamp = GPU_lamp_from_blender(shi->gpumat->scene, ob, NULL);
if (lamp)
shade_one_light(shi, shr, lamp);
@@ -874,10 +945,10 @@ static void material_lights(GPUShadeInput *shi, GPUShadeResult *shr)
DupliObject *dob;
ListBase *lb = object_duplilist(G.main->eval_ctx, shi->gpumat->scene, ob);
- for (dob=lb->first; dob; dob=dob->next) {
+ for (dob = lb->first; dob; dob = dob->next) {
Object *ob_iter = dob->ob;
- if (ob_iter->type==OB_LAMP) {
+ if (ob_iter->type == OB_LAMP) {
float omat[4][4];
copy_m4_m4(omat, ob_iter->obmat);
copy_m4_m4(ob_iter->obmat, dob->mat);
@@ -994,8 +1065,8 @@ static void texture_value_blend(GPUMaterial *mat, GPUNodeLink *tex, GPUNodeLink
static void do_material_tex(GPUShadeInput *shi)
{
- Material *ma= shi->mat;
- GPUMaterial *mat= shi->gpumat;
+ Material *ma = shi->mat;
+ GPUMaterial *mat = shi->gpumat;
MTex *mtex;
Tex *tex;
GPUNodeLink *texco, *tin, *trgb, *tnor, *tcol, *stencil, *tnorfac;
@@ -1006,9 +1077,9 @@ static void do_material_tex(GPUShadeInput *shi)
float one = 1.0f, norfac, ofs[3];
int tex_nr, rgbnor, talpha;
bool init_done = false;
- int iBumpSpacePrev = 0; /* Not necessary, quiting gcc warning. */
+ int iBumpSpacePrev = 0; /* Not necessary, quieting gcc warning. */
GPUNodeLink *vNorg, *vNacc, *fPrevMagnitude;
- int iFirstTimeNMap=1;
+ int iFirstTimeNMap = 1;
int found_deriv_map = 0;
GPU_link(mat, "set_value", GPU_uniform(&one), &stencil);
@@ -1018,44 +1089,46 @@ static void do_material_tex(GPUShadeInput *shi)
GPU_link(mat, "texco_object", GPU_builtin(GPU_INVERSE_VIEW_MATRIX),
GPU_builtin(GPU_INVERSE_OBJECT_MATRIX),
GPU_builtin(GPU_VIEW_POSITION), &texco_object);
- //GPU_link(mat, "texco_tangent", GPU_attribute(CD_TANGENT, ""), &texco_tangent);
+#if 0
+ GPU_link(mat, "texco_tangent", GPU_attribute(CD_TANGENT, ""), &texco_tangent);
+#endif
GPU_link(mat, "texco_global", GPU_builtin(GPU_INVERSE_VIEW_MATRIX),
GPU_builtin(GPU_VIEW_POSITION), &texco_global);
orn= texco_norm;
/* go over texture slots */
- for (tex_nr=0; tex_nr<MAX_MTEX; tex_nr++) {
+ for (tex_nr = 0; tex_nr < MAX_MTEX; tex_nr++) {
/* separate tex switching */
- if (ma->septex & (1<<tex_nr)) continue;
+ if (ma->septex & (1 << tex_nr)) continue;
if (ma->mtex[tex_nr]) {
- mtex= ma->mtex[tex_nr];
+ mtex = ma->mtex[tex_nr];
- tex= mtex->tex;
+ tex = mtex->tex;
if (tex == NULL) continue;
/* which coords */
- if (mtex->texco==TEXCO_ORCO)
- texco= texco_orco;
- else if (mtex->texco==TEXCO_OBJECT)
- texco= texco_object;
- else if (mtex->texco==TEXCO_NORM)
- texco= orn;
- else if (mtex->texco==TEXCO_TANGENT)
- texco= texco_object;
- else if (mtex->texco==TEXCO_GLOB)
- texco= texco_global;
- else if (mtex->texco==TEXCO_REFL) {
+ if (mtex->texco == TEXCO_ORCO)
+ texco = texco_orco;
+ else if (mtex->texco == TEXCO_OBJECT)
+ texco = texco_object;
+ else if (mtex->texco == TEXCO_NORM)
+ texco = orn;
+ else if (mtex->texco == TEXCO_TANGENT)
+ texco = texco_object;
+ else if (mtex->texco == TEXCO_GLOB)
+ texco = texco_global;
+ else if (mtex->texco == TEXCO_REFL) {
GPU_link(mat, "texco_refl", shi->vn, shi->view, &shi->ref);
- texco= shi->ref;
+ texco = shi->ref;
}
- else if (mtex->texco==TEXCO_UV) {
+ else if (mtex->texco == TEXCO_UV) {
if (1) { //!(texco_uv && strcmp(mtex->uvname, lastuvname) == 0)) {
GPU_link(mat, "texco_uv", GPU_attribute(CD_MTFACE, mtex->uvname), &texco_uv);
/*lastuvname = mtex->uvname;*/ /*UNUSED*/
}
- texco= texco_uv;
+ texco = texco_uv;
}
else
continue;
@@ -1067,8 +1140,8 @@ static void do_material_tex(GPUShadeInput *shi)
if (mtex->size[0] != 1.0f || mtex->size[1] != 1.0f || mtex->size[2] != 1.0f)
GPU_link(mat, "mtex_mapping_size", texco, GPU_uniform(mtex->size), &texco);
- ofs[0] = mtex->ofs[0] + 0.5f - 0.5f*mtex->size[0];
- ofs[1] = mtex->ofs[1] + 0.5f - 0.5f*mtex->size[1];
+ ofs[0] = mtex->ofs[0] + 0.5f - 0.5f * mtex->size[0];
+ ofs[1] = mtex->ofs[1] + 0.5f - 0.5f * mtex->size[1];
ofs[2] = 0.0f;
if (ofs[0] != 0.0f || ofs[1] != 0.0f || ofs[2] != 0.0f)
GPU_link(mat, "mtex_mapping_ofs", texco, GPU_uniform(ofs), &texco);
@@ -1077,7 +1150,7 @@ static void do_material_tex(GPUShadeInput *shi)
if (tex && tex->type == TEX_IMAGE && tex->ima) {
GPU_link(mat, "mtex_image", texco, GPU_image(tex->ima, &tex->iuser, false), &tin, &trgb);
- rgbnor= TEX_RGB;
+ rgbnor = TEX_RGB;
talpha = ((tex->imaflag & TEX_USEALPHA) && tex->ima && (tex->ima->flag & IMA_IGNORE_ALPHA) == 0);
}
@@ -1122,7 +1195,7 @@ static void do_material_tex(GPUShadeInput *shi)
GPU_link(mat, "set_value_one", &tin);
}
- if (tex->type==TEX_IMAGE)
+ if (tex->type == TEX_IMAGE)
if (GPU_material_do_color_management(mat))
GPU_link(mat, "srgb_to_linearrgb", tcol, &tcol);
@@ -1146,7 +1219,7 @@ static void do_material_tex(GPUShadeInput *shi)
}
if (!(mat->scene->gm.flag & GAME_GLSL_NO_EXTRA_TEX) && (mtex->mapto & MAP_NORM)) {
- if (tex->type==TEX_IMAGE) {
+ if (tex->type == TEX_IMAGE) {
found_deriv_map = tex->imaflag & TEX_DERIVATIVEMAP;
if (tex->imaflag & TEX_NORMALMAP) {
@@ -1170,7 +1243,7 @@ static void do_material_tex(GPUShadeInput *shi)
}
else if (mtex->normapspace == MTEX_NSPACE_OBJECT) {
/* transform normal by object then view matrix */
- GPU_link(mat, "mtex_nspace_object", GPU_builtin(GPU_VIEW_MATRIX), GPU_builtin(GPU_OBJECT_MATRIX), tnor, &newnor);
+ GPU_link(mat, "mtex_nspace_object", tnor, &newnor);
}
else if (mtex->normapspace == MTEX_NSPACE_WORLD) {
/* transform normal by view matrix */
@@ -1196,44 +1269,43 @@ static void do_material_tex(GPUShadeInput *shi)
}
}
- else if ( (mtex->texflag & (MTEX_3TAP_BUMP|MTEX_5TAP_BUMP|MTEX_BICUBIC_BUMP)) || found_deriv_map) {
+ else if ((mtex->texflag & (MTEX_3TAP_BUMP | MTEX_5TAP_BUMP | MTEX_BICUBIC_BUMP)) || found_deriv_map) {
/* ntap bumpmap image */
int iBumpSpace;
float ima_x, ima_y;
float hScale;
- float imag_tspace_dimension_x = 1024.0f; // only used for texture space variant
+ float imag_tspace_dimension_x = 1024.0f; /* only used for texture space variant */
float aspect = 1.0f;
- GPUNodeLink *surf_pos = GPU_builtin(GPU_VIEW_POSITION);
GPUNodeLink *vR1, *vR2;
GPUNodeLink *dBs, *dBt, *fDet;
- hScale = 0.1; // compatibility adjustment factor for all bumpspace types
- if ( mtex->texflag & MTEX_BUMP_TEXTURESPACE )
- hScale = 13.0f; // factor for scaling texspace bumps
+ hScale = 0.1; /* compatibility adjustment factor for all bumpspace types */
+ if (mtex->texflag & MTEX_BUMP_TEXTURESPACE)
+ hScale = 13.0f; /* factor for scaling texspace bumps */
else if (found_deriv_map!=0)
hScale = 1.0f;
- // resolve texture resolution
- if ( (mtex->texflag & MTEX_BUMP_TEXTURESPACE) || found_deriv_map ) {
- ImBuf *ibuf= BKE_image_acquire_ibuf(tex->ima, &tex->iuser, NULL);
- ima_x= 512.0f; ima_y= 512.f; // prevent calling textureSize, glsl 1.3 only
+ /* resolve texture resolution */
+ if ((mtex->texflag & MTEX_BUMP_TEXTURESPACE) || found_deriv_map) {
+ ImBuf *ibuf = BKE_image_acquire_ibuf(tex->ima, &tex->iuser, NULL);
+ ima_x = 512.0f; ima_y = 512.f; /* prevent calling textureSize, glsl 1.3 only */
if (ibuf) {
- ima_x= ibuf->x;
- ima_y= ibuf->y;
- aspect = ((float) ima_y) / ima_x;
+ ima_x = ibuf->x;
+ ima_y = ibuf->y;
+ aspect = (float)ima_y / ima_x;
}
BKE_image_release_ibuf(tex->ima, ibuf, NULL);
}
- // The negate on norfac is done because the
- // normal in the renderer points inward which corresponds
- // to inverting the bump map. Should this ever change
- // this negate must be removed.
+ /* The negate on norfac is done because the
+ * normal in the renderer points inward which corresponds
+ * to inverting the bump map. Should this ever change
+ * this negate must be removed. */
norfac = -hScale * mtex->norfac;
if (found_deriv_map) {
- float fVirtDim = sqrtf(fabsf(ima_x*mtex->size[0]*ima_y*mtex->size[1]));
+ float fVirtDim = sqrtf(fabsf(ima_x * mtex->size[0] * ima_y * mtex->size[1]));
norfac /= MAX2(fVirtDim, FLT_EPSILON);
}
@@ -1245,25 +1317,26 @@ static void do_material_tex(GPUShadeInput *shi)
if (GPU_link_changed(stencil))
GPU_link(mat, "math_multiply", tnorfac, stencil, &tnorfac);
- if ( !init_done ) {
- // copy shi->vn to vNorg and vNacc, set magnitude to 1
+ if (!init_done) {
+ /* copy shi->vn to vNorg and vNacc, set magnitude to 1 */
GPU_link(mat, "mtex_bump_normals_init", shi->vn, &vNorg, &vNacc, &fPrevMagnitude);
iBumpSpacePrev = 0;
init_done = true;
}
// find current bump space
- if ( mtex->texflag & MTEX_BUMP_OBJECTSPACE )
+ if (mtex->texflag & MTEX_BUMP_OBJECTSPACE)
iBumpSpace = 1;
- else if ( mtex->texflag & MTEX_BUMP_TEXTURESPACE )
+ else if (mtex->texflag & MTEX_BUMP_TEXTURESPACE)
iBumpSpace = 2;
else
- iBumpSpace = 4; // ViewSpace
+ iBumpSpace = 4; /* ViewSpace */
- // re-initialize if bump space changed
- if ( iBumpSpacePrev != iBumpSpace ) {
-
- if ( mtex->texflag & MTEX_BUMP_OBJECTSPACE )
+ /* re-initialize if bump space changed */
+ if (iBumpSpacePrev != iBumpSpace) {
+ GPUNodeLink *surf_pos = GPU_builtin(GPU_VIEW_POSITION);
+
+ if (mtex->texflag & MTEX_BUMP_OBJECTSPACE)
GPU_link(mat, "mtex_bump_init_objspace",
surf_pos, vNorg,
GPU_builtin(GPU_VIEW_MATRIX), GPU_builtin(GPU_INVERSE_VIEW_MATRIX), GPU_builtin(GPU_OBJECT_MATRIX), GPU_builtin(GPU_INVERSE_OBJECT_MATRIX),
@@ -1271,7 +1344,7 @@ static void do_material_tex(GPUShadeInput *shi)
&fPrevMagnitude, &vNacc,
&vR1, &vR2, &fDet);
- else if ( mtex->texflag & MTEX_BUMP_TEXTURESPACE )
+ else if (mtex->texflag & MTEX_BUMP_TEXTURESPACE)
GPU_link(mat, "mtex_bump_init_texturespace",
surf_pos, vNorg,
fPrevMagnitude, vNacc,
@@ -1292,17 +1365,17 @@ static void do_material_tex(GPUShadeInput *shi)
if (found_deriv_map) {
GPU_link(mat, "mtex_bump_deriv",
texco, GPU_image(tex->ima, &tex->iuser, true), GPU_uniform(&ima_x), GPU_uniform(&ima_y), tnorfac,
- &dBs, &dBt );
+ &dBs, &dBt);
}
- else if ( mtex->texflag & MTEX_3TAP_BUMP)
+ else if (mtex->texflag & MTEX_3TAP_BUMP)
GPU_link(mat, "mtex_bump_tap3",
texco, GPU_image(tex->ima, &tex->iuser, true), tnorfac,
- &dBs, &dBt );
- else if ( mtex->texflag & MTEX_5TAP_BUMP)
+ &dBs, &dBt);
+ else if (mtex->texflag & MTEX_5TAP_BUMP)
GPU_link(mat, "mtex_bump_tap5",
texco, GPU_image(tex->ima, &tex->iuser, true), tnorfac,
- &dBs, &dBt );
- else if ( mtex->texflag & MTEX_BICUBIC_BUMP ) {
+ &dBs, &dBt);
+ else if (mtex->texflag & MTEX_BICUBIC_BUMP) {
if (GPU_bicubic_bump_support()) {
GPU_link(mat, "mtex_bump_bicubic",
texco, GPU_image(tex->ima, &tex->iuser, true), tnorfac,
@@ -1316,18 +1389,18 @@ static void do_material_tex(GPUShadeInput *shi)
}
- if ( mtex->texflag & MTEX_BUMP_TEXTURESPACE ) {
- float imag_tspace_dimension_y = aspect*imag_tspace_dimension_x;
+ if (mtex->texflag & MTEX_BUMP_TEXTURESPACE) {
+ float imag_tspace_dimension_y = aspect * imag_tspace_dimension_x;
GPU_link(mat, "mtex_bump_apply_texspace",
fDet, dBs, dBt, vR1, vR2,
GPU_image(tex->ima, &tex->iuser, true), texco,
GPU_uniform(&imag_tspace_dimension_x), GPU_uniform(&imag_tspace_dimension_y), vNacc,
- &vNacc, &shi->vn );
+ &vNacc, &shi->vn);
}
else
GPU_link(mat, "mtex_bump_apply",
fDet, dBs, dBt, vR1, vR2, vNacc,
- &vNacc, &shi->vn );
+ &vNacc, &shi->vn);
}
}
@@ -1405,7 +1478,6 @@ static void do_material_tex(GPUShadeInput *shi)
void GPU_shadeinput_set(GPUMaterial *mat, Material *ma, GPUShadeInput *shi)
{
- float hard = ma->har;
float one = 1.0f;
memset(shi, 0, sizeof(*shi));
@@ -1413,20 +1485,21 @@ void GPU_shadeinput_set(GPUMaterial *mat, Material *ma, GPUShadeInput *shi)
shi->gpumat = mat;
shi->mat = ma;
- GPU_link(mat, "set_rgb", GPU_uniform(&ma->r), &shi->rgb);
- GPU_link(mat, "set_rgb", GPU_uniform(&ma->specr), &shi->specrgb);
+ GPU_link(mat, "set_rgb", GPU_dynamic_uniform(&ma->r, GPU_DYNAMIC_MAT_DIFFRGB, NULL), &shi->rgb);
+ GPU_link(mat, "set_rgb", GPU_dynamic_uniform(&ma->specr, GPU_DYNAMIC_MAT_SPECRGB, NULL), &shi->specrgb);
GPU_link(mat, "shade_norm", GPU_builtin(GPU_VIEW_NORMAL), &shi->vn);
if (mat->alpha)
- GPU_link(mat, "set_value", GPU_uniform(&ma->alpha), &shi->alpha);
+ GPU_link(mat, "set_value", GPU_dynamic_uniform(&ma->alpha, GPU_DYNAMIC_MAT_ALPHA, NULL), &shi->alpha);
else
GPU_link(mat, "set_value", GPU_uniform(&one), &shi->alpha);
- GPU_link(mat, "set_value", GPU_uniform(&ma->ref), &shi->refl);
- GPU_link(mat, "set_value", GPU_uniform(&ma->spec), &shi->spec);
- GPU_link(mat, "set_value", GPU_uniform(&ma->emit), &shi->emit);
- GPU_link(mat, "set_value", GPU_uniform(&hard), &shi->har);
- GPU_link(mat, "set_value", GPU_uniform(&ma->amb), &shi->amb);
+ GPU_link(mat, "set_value", GPU_dynamic_uniform(&ma->ref, GPU_DYNAMIC_MAT_REF, NULL), &shi->refl);
+ GPU_link(mat, "set_value", GPU_dynamic_uniform(&ma->spec, GPU_DYNAMIC_MAT_SPEC, NULL), &shi->spec);
+ GPU_link(mat, "set_value", GPU_dynamic_uniform(&ma->emit, GPU_DYNAMIC_MAT_EMIT, NULL), &shi->emit);
+ GPU_link(mat, "set_value", GPU_dynamic_uniform((float*)&ma->har, GPU_DYNAMIC_MAT_HARD, NULL), &shi->har);
+ GPU_link(mat, "set_value", GPU_dynamic_uniform(&ma->amb, GPU_DYNAMIC_MAT_AMB, NULL), &shi->amb);
+ GPU_link(mat, "set_value", GPU_uniform(&ma->spectra), &shi->spectra);
GPU_link(mat, "shade_view", GPU_builtin(GPU_VIEW_POSITION), &shi->view);
GPU_link(mat, "vcol_attribute", GPU_attribute(CD_MCOL, ""), &shi->vcol);
if (GPU_material_do_color_management(mat))
@@ -1434,13 +1507,39 @@ void GPU_shadeinput_set(GPUMaterial *mat, Material *ma, GPUShadeInput *shi)
GPU_link(mat, "texco_refl", shi->vn, shi->view, &shi->ref);
}
+void GPU_mist_update_enable(short enable)
+{
+ GPUWorld.mistenabled = (float)enable;
+}
+
+void GPU_mist_update_values(int type, float start, float dist, float inten, float color[3])
+{
+ GPUWorld.mistype = (float)type;
+ GPUWorld.miststart = start;
+ GPUWorld.mistdistance = dist;
+ GPUWorld.mistintensity = inten;
+ copy_v3_v3(GPUWorld.mistcol, color);
+ GPUWorld.mistcol[3] = 1.0f;
+}
+
+void GPU_horizon_update_color(float color[3])
+{
+ copy_v3_v3(GPUWorld.horicol, color);
+}
+
+void GPU_ambient_update_color(float color[3])
+{
+ copy_v3_v3(GPUWorld.ambcol, color);
+ GPUWorld.ambcol[3] = 1.0f;
+}
+
void GPU_shaderesult_set(GPUShadeInput *shi, GPUShadeResult *shr)
{
- GPUMaterial *mat= shi->gpumat;
+ GPUMaterial *mat = shi->gpumat;
GPUNodeLink *emit, *ulinfac, *ulogfac, *mistfac;
- Material *ma= shi->mat;
- World *world= mat->scene->world;
- float linfac, logfac, misttype;
+ Material *ma = shi->mat;
+ World *world = mat->scene->world;
+ float linfac, logfac;
memset(shr, 0, sizeof(*shr));
@@ -1457,7 +1556,7 @@ void GPU_shaderesult_set(GPUShadeInput *shi, GPUShadeResult *shr)
}
else {
if (GPU_link_changed(shi->emit) || ma->emit != 0.0f) {
- if ((ma->mode & (MA_VERTEXCOL|MA_VERTEXCOLP))== MA_VERTEXCOL) {
+ if ((ma->mode & (MA_VERTEXCOL|MA_VERTEXCOLP)) == MA_VERTEXCOL) {
GPU_link(mat, "shade_add", shi->emit, shi->vcol, &emit);
GPU_link(mat, "shade_mul", emit, shi->rgb, &shr->diff);
}
@@ -1477,9 +1576,9 @@ void GPU_shaderesult_set(GPUShadeInput *shi, GPUShadeResult *shr)
if (world) {
/* exposure correction */
- if (world->exp!=0.0f || world->range!=1.0f) {
- linfac= 1.0f + powf((2.0f*world->exp + 0.5f), -10);
- logfac= logf((linfac-1.0f)/linfac)/world->range;
+ if (world->exp != 0.0f || world->range != 1.0f) {
+ linfac = 1.0f + powf((2.0f * world->exp + 0.5f), -10);
+ logfac = logf((linfac - 1.0f) / linfac) / world->range;
GPU_link(mat, "set_value", GPU_uniform(&linfac), &ulinfac);
GPU_link(mat, "set_value", GPU_uniform(&logfac), &ulogfac);
@@ -1491,13 +1590,19 @@ void GPU_shaderesult_set(GPUShadeInput *shi, GPUShadeResult *shr)
}
/* ambient color */
- if (world->ambr!=0.0f || world->ambg!=0.0f || world->ambb!=0.0f) {
- if (GPU_link_changed(shi->amb) || ma->amb != 0.0f)
- GPU_link(mat, "shade_maddf", shr->combined, GPU_uniform(&ma->amb),
- GPU_uniform(&world->ambr), &shr->combined);
+ if (GPU_link_changed(shi->amb) || ma->amb != 0.0f) {
+ GPU_link(mat, "shade_maddf", shr->combined, GPU_uniform(&ma->amb),
+ GPU_dynamic_uniform(GPUWorld.ambcol, GPU_DYNAMIC_AMBIENT_COLOR, NULL),
+ &shr->combined);
}
}
+ if (ma->mode & MA_TRANSP && (ma->mode & (MA_ZTRANSP|MA_RAYTRANSP))) {
+ if (GPU_link_changed(shi->spectra) || ma->spectra != 0.0f)
+ GPU_link(mat, "alpha_spec_correction", shr->spec, shi->spectra,
+ shi->alpha, &shr->alpha);
+ }
+
if (ma->mode & MA_RAMP_COL) ramp_diffuse_result(shi, &shr->combined);
if (ma->mode & MA_RAMP_SPEC) ramp_spec_result(shi, &shr->spec);
@@ -1510,21 +1615,22 @@ void GPU_shaderesult_set(GPUShadeInput *shi, GPUShadeResult *shr)
if (ma->shade_flag & MA_OBCOLOR)
GPU_link(mat, "shade_obcolor", shr->combined, GPU_builtin(GPU_OBCOLOR), &shr->combined);
- if (world && (world->mode & WO_MIST) && !(ma->mode & MA_NOMIST)) {
- misttype = world->mistype;
-
+ if (!(ma->mode & MA_NOMIST)) {
GPU_link(mat, "shade_mist_factor", GPU_builtin(GPU_VIEW_POSITION),
- GPU_uniform(&world->miststa), GPU_uniform(&world->mistdist),
- GPU_uniform(&misttype), GPU_uniform(&world->misi), &mistfac);
+ GPU_dynamic_uniform(&GPUWorld.mistenabled, GPU_DYNAMIC_MIST_ENABLE, NULL),
+ GPU_dynamic_uniform(&GPUWorld.miststart, GPU_DYNAMIC_MIST_START, NULL),
+ GPU_dynamic_uniform(&GPUWorld.mistdistance, GPU_DYNAMIC_MIST_DISTANCE, NULL),
+ GPU_dynamic_uniform(&GPUWorld.mistype, GPU_DYNAMIC_MIST_TYPE, NULL),
+ GPU_dynamic_uniform(&GPUWorld.mistintensity, GPU_DYNAMIC_MIST_INTENSITY, NULL), &mistfac);
GPU_link(mat, "mix_blend", mistfac, shr->combined,
- GPU_uniform(&world->horr), &shr->combined);
+ GPU_dynamic_uniform(GPUWorld.mistcol, GPU_DYNAMIC_MIST_COLOR, NULL), &shr->combined);
}
if (!mat->alpha) {
if (world && (GPU_link_changed(shr->alpha) || ma->alpha != 1.0f))
- GPU_link(mat, "shade_world_mix", GPU_uniform(&world->horr),
- shr->combined, &shr->combined);
+ GPU_link(mat, "shade_world_mix", GPU_dynamic_uniform(GPUWorld.horicol, GPU_DYNAMIC_HORIZON_COLOR, NULL),
+ shr->combined, &shr->combined);
GPU_link(mat, "shade_alpha_opaque", shr->combined, &shr->combined);
}
@@ -1570,20 +1676,27 @@ static GPUNodeLink *gpu_material_preview_matcap(GPUMaterial *mat, Material *ma)
}
/* new solid draw mode with glsl matcaps */
-GPUMaterial *GPU_material_matcap(Scene *scene, Material *ma)
+GPUMaterial *GPU_material_matcap(Scene *scene, Material *ma, bool use_opensubdiv)
{
GPUMaterial *mat;
GPUNodeLink *outlink;
LinkData *link;
- for (link=ma->gpumaterial.first; link; link=link->next)
- if (((GPUMaterial*)link->data)->scene == scene)
- return link->data;
+ for (link = ma->gpumaterial.first; link; link = link->next) {
+ GPUMaterial *current_material = (GPUMaterial*)link->data;
+ if (current_material->scene == scene &&
+ current_material->is_opensubdiv == use_opensubdiv)
+ {
+ return current_material;
+ }
+ }
/* allocate material */
mat = GPU_material_construct_begin(ma);
mat->scene = scene;
-
+ mat->type = GPU_MATERIAL_TYPE_MESH;
+ mat->is_opensubdiv = use_opensubdiv;
+
if (ma->preview && ma->preview->rect[0]) {
outlink = gpu_material_preview_matcap(mat, ma);
}
@@ -1593,7 +1706,7 @@ GPUMaterial *GPU_material_matcap(Scene *scene, Material *ma)
GPU_material_output_link(mat, outlink);
- GPU_material_construct_end(mat);
+ GPU_material_construct_end(mat, "matcap_pass");
/* note that even if building the shader fails in some way, we still keep
* it to avoid trying to compile again and again, and simple do not use
@@ -1606,19 +1719,65 @@ GPUMaterial *GPU_material_matcap(Scene *scene, Material *ma)
return mat;
}
-GPUMaterial *GPU_material_from_blender(Scene *scene, Material *ma)
+GPUMaterial *GPU_material_world(struct Scene *scene, struct World *wo)
{
- GPUMaterial *mat;
- GPUNodeLink *outlink;
LinkData *link;
+ GPUMaterial *mat;
- for (link=ma->gpumaterial.first; link; link=link->next)
+ for (link = wo->gpumaterial.first; link; link = link->next)
if (((GPUMaterial*)link->data)->scene == scene)
return link->data;
/* allocate material */
+ mat = GPU_material_construct_begin(NULL);
+ mat->scene = scene;
+ mat->type = GPU_MATERIAL_TYPE_WORLD;
+
+ /* create nodes */
+ if (BKE_scene_use_new_shading_nodes(scene) && wo->nodetree && wo->use_nodes)
+ ntreeGPUMaterialNodes(wo->nodetree, mat, NODE_NEW_SHADING);
+ else {
+ /* old fixed function world */
+ }
+
+ if (GPU_material_do_color_management(mat))
+ if (mat->outlink)
+ GPU_link(mat, "linearrgb_to_srgb", mat->outlink, &mat->outlink);
+
+ GPU_material_construct_end(mat, wo->id.name);
+
+ /* note that even if building the shader fails in some way, we still keep
+ * it to avoid trying to compile again and again, and simple do not use
+ * the actual shader on drawing */
+
+ link = MEM_callocN(sizeof(LinkData), "GPUMaterialLink");
+ link->data = mat;
+ BLI_addtail(&wo->gpumaterial, link);
+
+ return mat;
+}
+
+
+GPUMaterial *GPU_material_from_blender(Scene *scene, Material *ma, bool use_opensubdiv)
+{
+ GPUMaterial *mat;
+ GPUNodeLink *outlink;
+ LinkData *link;
+
+ for (link = ma->gpumaterial.first; link; link = link->next) {
+ GPUMaterial *current_material = (GPUMaterial*)link->data;
+ if (current_material->scene == scene &&
+ current_material->is_opensubdiv == use_opensubdiv)
+ {
+ return current_material;
+ }
+ }
+
+ /* allocate material */
mat = GPU_material_construct_begin(ma);
mat->scene = scene;
+ mat->type = GPU_MATERIAL_TYPE_MESH;
+ mat->is_opensubdiv = use_opensubdiv;
/* render pipeline option */
if (ma->mode & MA_TRANSP)
@@ -1648,7 +1807,7 @@ GPUMaterial *GPU_material_from_blender(Scene *scene, Material *ma)
if (mat->outlink)
GPU_link(mat, "linearrgb_to_srgb", mat->outlink, &mat->outlink);
- GPU_material_construct_end(mat);
+ GPU_material_construct_end(mat, ma->id.name);
/* note that even if building the shader fails in some way, we still keep
* it to avoid trying to compile again and again, and simple do not use
@@ -1665,14 +1824,18 @@ void GPU_materials_free(void)
{
Object *ob;
Material *ma;
+ World *wo;
extern Material defmaterial;
- for (ma=G.main->mat.first; ma; ma=ma->id.next)
- GPU_material_free(ma);
+ for (ma = G.main->mat.first; ma; ma = ma->id.next)
+ GPU_material_free(&ma->gpumaterial);
- GPU_material_free(&defmaterial);
+ for (wo = G.main->world.first; wo; wo = wo->id.next)
+ GPU_material_free(&wo->gpumaterial);
+
+ GPU_material_free(&defmaterial.gpumaterial);
- for (ob=G.main->object.first; ob; ob=ob->id.next)
+ for (ob = G.main->object.first; ob; ob = ob->id.next)
GPU_lamp_free(ob);
}
@@ -1687,10 +1850,10 @@ static void gpu_lamp_calc_winmat(GPULamp *lamp)
orthographic_m4(lamp->winmat, -wsize, wsize, -wsize, wsize, lamp->d, lamp->clipend);
}
else {
- angle= saacos(lamp->spotsi);
- temp= 0.5f*lamp->size*cosf(angle)/sinf(angle);
- pixsize= (lamp->d)/temp;
- wsize= pixsize*0.5f*lamp->size;
+ angle = saacos(lamp->spotsi);
+ temp = 0.5f * lamp->size * cosf(angle) / sinf(angle);
+ pixsize = lamp->d / temp;
+ wsize = pixsize * 0.5f * lamp->size;
perspective_m4(lamp->winmat, -wsize, wsize, -wsize, wsize, lamp->d, lamp->clipend);
}
}
@@ -1714,11 +1877,11 @@ void GPU_lamp_update(GPULamp *lamp, int lay, int hide, float obmat[4][4])
void GPU_lamp_update_colors(GPULamp *lamp, float r, float g, float b, float energy)
{
lamp->energy = energy;
- if (lamp->mode & LA_NEG) lamp->energy= -lamp->energy;
+ if (lamp->mode & LA_NEG) lamp->energy = -lamp->energy;
- lamp->col[0]= r* lamp->energy;
- lamp->col[1]= g* lamp->energy;
- lamp->col[2]= b* lamp->energy;
+ lamp->col[0] = r;
+ lamp->col[1] = g;
+ lamp->col[2] = b;
}
void GPU_lamp_update_distance(GPULamp *lamp, float distance, float att1, float att2)
@@ -1748,11 +1911,11 @@ static void gpu_lamp_from_blender(Scene *scene, Object *ob, Object *par, Lamp *l
lamp->type = la->type;
lamp->energy = la->energy;
- if (lamp->mode & LA_NEG) lamp->energy= -lamp->energy;
+ if (lamp->mode & LA_NEG) lamp->energy = -lamp->energy;
- lamp->col[0]= la->r*lamp->energy;
- lamp->col[1]= la->g*lamp->energy;
- lamp->col[2]= la->b*lamp->energy;
+ lamp->col[0] = la->r;
+ lamp->col[1] = la->g;
+ lamp->col[2] = la->b;
GPU_lamp_update(lamp, ob->lay, (ob->restrictflag & OB_RESTRICT_RENDER), ob->obmat);
@@ -1761,20 +1924,20 @@ static void gpu_lamp_from_blender(Scene *scene, Object *ob, Object *par, Lamp *l
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;
+ lamp->spotbl = (1.0f - lamp->spotsi) * la->spotblend;
+ lamp->k = la->k;
- lamp->dist= la->dist;
- lamp->falloff_type= la->falloff_type;
- lamp->att1= la->att1;
- lamp->att2= la->att2;
- lamp->curfalloff= la->curfalloff;
+ lamp->dist = la->dist;
+ lamp->falloff_type = la->falloff_type;
+ lamp->att1 = la->att1;
+ lamp->att2 = la->att2;
+ lamp->curfalloff = la->curfalloff;
/* initshadowbuf */
- lamp->bias = 0.02f*la->bias;
+ lamp->bias = 0.02f * la->bias;
lamp->size = la->bufsize;
- lamp->d= la->clipsta;
- lamp->clipend= la->clipend;
+ lamp->d = la->clipsta;
+ lamp->clipend = la->clipend;
/* arbitrary correction for the fact we do no soft transition */
lamp->bias *= 0.25f;
@@ -1787,23 +1950,23 @@ static void gpu_lamp_shadow_free(GPULamp *lamp)
{
if (lamp->tex) {
GPU_texture_free(lamp->tex);
- lamp->tex= NULL;
+ lamp->tex = NULL;
}
if (lamp->depthtex) {
GPU_texture_free(lamp->depthtex);
- lamp->depthtex= NULL;
+ lamp->depthtex = NULL;
}
if (lamp->fb) {
GPU_framebuffer_free(lamp->fb);
- lamp->fb= NULL;
+ lamp->fb = NULL;
}
if (lamp->blurtex) {
GPU_texture_free(lamp->blurtex);
- lamp->blurtex= NULL;
+ lamp->blurtex = NULL;
}
if (lamp->blurfb) {
GPU_framebuffer_free(lamp->blurfb);
- lamp->blurfb= NULL;
+ lamp->blurfb = NULL;
}
}
@@ -1813,7 +1976,7 @@ GPULamp *GPU_lamp_from_blender(Scene *scene, Object *ob, Object *par)
GPULamp *lamp;
LinkData *link;
- for (link=ob->gpulamp.first; link; link=link->next) {
+ for (link = ob->gpulamp.first; link; link = link->next) {
lamp = (GPULamp*)link->data;
if (lamp->par == par && lamp->scene == scene)
@@ -1829,7 +1992,7 @@ GPULamp *GPU_lamp_from_blender(Scene *scene, Object *ob, Object *par)
la = ob->data;
gpu_lamp_from_blender(scene, ob, par, la, lamp);
- if ((la->type==LA_SPOT && (la->mode & (LA_SHAD_BUF | LA_SHAD_RAY))) || (la->type==LA_SUN && (la->mode & LA_SHAD_RAY))) {
+ if ((la->type == LA_SPOT && (la->mode & (LA_SHAD_BUF | LA_SHAD_RAY))) || (la->type == LA_SUN && (la->mode & LA_SHAD_RAY))) {
/* opengl */
lamp->fb = GPU_framebuffer_create();
if (!lamp->fb) {
@@ -1845,7 +2008,7 @@ GPULamp *GPU_lamp_from_blender(Scene *scene, Object *ob, Object *par)
return lamp;
}
- if (!GPU_framebuffer_texture_attach(lamp->fb, lamp->depthtex, NULL)) {
+ if (!GPU_framebuffer_texture_attach(lamp->fb, lamp->depthtex, 0, NULL)) {
gpu_lamp_shadow_free(lamp);
return lamp;
}
@@ -1857,11 +2020,16 @@ GPULamp *GPU_lamp_from_blender(Scene *scene, Object *ob, Object *par)
return lamp;
}
- if (!GPU_framebuffer_texture_attach(lamp->fb, lamp->tex, NULL)) {
+ if (!GPU_framebuffer_texture_attach(lamp->fb, lamp->tex, 0, NULL)) {
gpu_lamp_shadow_free(lamp);
return lamp;
}
+ if (!GPU_framebuffer_check_valid(lamp->fb, NULL)) {
+ gpu_lamp_shadow_free(lamp);
+ return lamp;
+ }
+
/* FBO and texture for blurring */
lamp->blurfb = GPU_framebuffer_create();
if (!lamp->blurfb) {
@@ -1869,16 +2037,26 @@ GPULamp *GPU_lamp_from_blender(Scene *scene, Object *ob, Object *par)
return lamp;
}
- lamp->blurtex = GPU_texture_create_vsm_shadow_map(lamp->size*0.5, NULL);
+ lamp->blurtex = GPU_texture_create_vsm_shadow_map(lamp->size * 0.5, NULL);
if (!lamp->blurtex) {
gpu_lamp_shadow_free(lamp);
return lamp;
}
- if (!GPU_framebuffer_texture_attach(lamp->blurfb, lamp->blurtex, NULL)) {
+ if (!GPU_framebuffer_texture_attach(lamp->blurfb, lamp->blurtex, 0, NULL)) {
gpu_lamp_shadow_free(lamp);
return lamp;
}
+
+ /* we need to properly bind to test for completeness */
+ GPU_texture_bind_as_framebuffer(lamp->blurtex);
+
+ if (!GPU_framebuffer_check_valid(lamp->blurfb, NULL)) {
+ gpu_lamp_shadow_free(lamp);
+ return lamp;
+ }
+
+ GPU_framebuffer_texture_unbind(lamp->blurfb, lamp->blurtex);
}
else {
lamp->tex = GPU_texture_create_depth(lamp->size, lamp->size, NULL);
@@ -1887,10 +2065,15 @@ GPULamp *GPU_lamp_from_blender(Scene *scene, Object *ob, Object *par)
return lamp;
}
- if (!GPU_framebuffer_texture_attach(lamp->fb, lamp->tex, NULL)) {
+ if (!GPU_framebuffer_texture_attach(lamp->fb, lamp->tex, 0, NULL)) {
gpu_lamp_shadow_free(lamp);
return lamp;
}
+
+ if (!GPU_framebuffer_check_valid(lamp->fb, NULL)) {
+ gpu_lamp_shadow_free(lamp);
+ return lamp;
+ }
}
GPU_framebuffer_restore();
@@ -1915,7 +2098,7 @@ void GPU_lamp_free(Object *ob)
LinkData *nlink;
Material *ma;
- for (link=ob->gpulamp.first; link; link=link->next) {
+ for (link = ob->gpulamp.first; link; link = link->next) {
lamp = link->data;
while (lamp->materials.first) {
@@ -1924,7 +2107,7 @@ void GPU_lamp_free(Object *ob)
BLI_freelinkN(&lamp->materials, nlink);
if (ma->gpumaterial.first)
- GPU_material_free(ma);
+ GPU_material_free(&ma->gpumaterial);
}
gpu_lamp_shadow_free(lamp);
@@ -1973,8 +2156,7 @@ void GPU_lamp_shadow_buffer_bind(GPULamp *lamp, float viewmat[4][4], int *winsiz
/* opengl */
glDisable(GL_SCISSOR_TEST);
- GPU_framebuffer_texture_bind(lamp->fb, lamp->tex,
- GPU_texture_opengl_width(lamp->tex), GPU_texture_opengl_height(lamp->tex));
+ GPU_texture_bind_as_framebuffer(lamp->tex);
if (lamp->la->shadowmap_type == LA_SHADMAP_VARIANCE)
GPU_shader_bind(GPU_shader_get_builtin_shader(GPU_SHADER_VSM_STORE));
@@ -2009,12 +2191,14 @@ 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 *GPU_lamp_get_data(GPUMaterial *mat, GPULamp *lamp, GPUNodeLink **col, GPUNodeLink **lv, GPUNodeLink **dist, GPUNodeLink **shadow, GPUNodeLink **energy)
{
GPUNodeLink *visifac;
*col = GPU_dynamic_uniform(lamp->dyncol, GPU_DYNAMIC_LAMP_DYNCOL, lamp->ob);
+ *energy = GPU_dynamic_uniform(&lamp->dynenergy, GPU_DYNAMIC_LAMP_DYNENERGY, lamp->ob);
visifac = lamp_get_visibility(mat, lamp, lv, dist);
+
shade_light_textures(mat, lamp, col);
if (GPU_lamp_has_shadow_buffer(lamp)) {
@@ -2026,18 +2210,18 @@ GPUNodeLink *GPU_lamp_get_data(GPUMaterial *mat, GPULamp *lamp, GPUNodeLink **co
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);
+ 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);
+ 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 {
@@ -2081,7 +2265,8 @@ GPUShaderExport *GPU_shader_export(struct Scene *scene, struct Material *ma)
if (!GPU_glsl_support())
return NULL;
- mat = GPU_material_from_blender(scene, ma);
+ /* TODO(sergey): How to detemine whether we need OSD or not here? */
+ mat = GPU_material_from_blender(scene, ma, false);
pass = (mat)? mat->pass: NULL;
if (pass && pass->fragmentcode && pass->vertexcode) {
@@ -2120,33 +2305,49 @@ GPUShaderExport *GPU_shader_export(struct Scene *scene, struct Material *ma)
glBindTexture(GL_TEXTURE_2D, lastbindcode);
}
break;
+
+ case GPU_NONE:
+ case GPU_FLOAT:
+ case GPU_VEC2:
+ case GPU_VEC3:
+ case GPU_VEC4:
+ case GPU_MAT3:
+ case GPU_MAT4:
+ case GPU_ATTRIB:
+ break;
}
}
else {
uniform->type = input->dynamictype;
BLI_strncpy(uniform->varname, input->shadername, sizeof(uniform->varname));
switch (input->type) {
- case 1:
+ case GPU_FLOAT:
uniform->datatype = GPU_DATA_1F;
break;
- case 2:
+ case GPU_VEC2:
uniform->datatype = GPU_DATA_2F;
break;
- case 3:
+ case GPU_VEC3:
uniform->datatype = GPU_DATA_3F;
break;
- case 4:
+ case GPU_VEC4:
uniform->datatype = GPU_DATA_4F;
break;
- case 9:
+ case GPU_MAT3:
uniform->datatype = GPU_DATA_9F;
break;
- case 16:
+ case GPU_MAT4:
uniform->datatype = GPU_DATA_16F;
break;
+
+ case GPU_NONE:
+ case GPU_TEX2D:
+ case GPU_SHADOW2D:
+ case GPU_ATTRIB:
+ break;
}
- if (uniform->type >= GPU_DYNAMIC_LAMP_FIRST && uniform->type <= GPU_DYNAMIC_LAMP_LAST)
+ if (GPU_DYNAMIC_GROUP_FROM_TYPE(uniform->type) == GPU_DYNAMIC_GROUP_LAMP)
uniform->lamp = input->dynamicdata;
}
@@ -2157,7 +2358,7 @@ GPUShaderExport *GPU_shader_export(struct Scene *scene, struct Material *ma)
}
/* process builtin uniform */
- for (i=0; builtins[i].gputype; i++) {
+ for (i = 0; builtins[i].gputype; i++) {
if (mat->builtins & builtins[i].gputype) {
uniform = MEM_callocN(sizeof(GPUInputUniform), "GPUInputUniform");
uniform->type = builtins[i].dynamictype;
@@ -2171,14 +2372,14 @@ GPUShaderExport *GPU_shader_export(struct Scene *scene, struct Material *ma)
/* TBD: remove the function that are not used in the main function */
liblen = (pass->libcode) ? strlen(pass->libcode) : 0;
fraglen = strlen(pass->fragmentcode);
- shader->fragment = (char *)MEM_mallocN(liblen+fraglen+1, "GPUFragShader");
+ shader->fragment = (char *)MEM_mallocN(liblen + fraglen + 1, "GPUFragShader");
if (pass->libcode)
memcpy(shader->fragment, pass->libcode, liblen);
memcpy(&shader->fragment[liblen], pass->fragmentcode, fraglen);
- shader->fragment[liblen+fraglen] = 0;
+ shader->fragment[liblen + fraglen] = 0;
// export the attribute
- for (i=0; i<mat->attribs.totlayer; i++) {
+ for (i = 0; i < mat->attribs.totlayer; i++) {
attribute = MEM_callocN(sizeof(GPUInputAttribute), "GPUInputAttribute");
attribute->type = mat->attribs.layer[i].type;
attribute->number = mat->attribs.layer[i].glindex;
@@ -2207,7 +2408,7 @@ GPUShaderExport *GPU_shader_export(struct Scene *scene, struct Material *ma)
MEM_freeN(attribute);
}
- // export the vertex shader
+ /* export the vertex shader */
shader->vertex = BLI_strdup(pass->vertexcode);
}
@@ -2221,7 +2422,7 @@ void GPU_free_shader_export(GPUShaderExport *shader)
if (shader == NULL)
return;
- for (uniform = shader->uniforms.first; uniform; uniform=uniform->next)
+ for (uniform = shader->uniforms.first; uniform; uniform = uniform->next)
if (uniform->texpixels)
MEM_freeN(uniform->texpixels);
@@ -2236,3 +2437,54 @@ void GPU_free_shader_export(GPUShaderExport *shader)
MEM_freeN(shader);
}
+#ifdef WITH_OPENSUBDIV
+void GPU_material_update_fvar_offset(GPUMaterial *gpu_material,
+ DerivedMesh *dm)
+{
+ GPUPass *pass = gpu_material->pass;
+ GPUShader *shader = (pass != NULL ? pass->shader : NULL);
+ ListBase *inputs = (pass != NULL ? &pass->inputs : NULL);
+ GPUInput *input;
+
+ if (shader == NULL) {
+ return;
+ }
+
+ GPU_shader_bind(shader);
+
+ for (input = inputs->first;
+ input != NULL;
+ input = input->next)
+ {
+ if (input->source == GPU_SOURCE_ATTRIB &&
+ input->attribtype == CD_MTFACE)
+ {
+ char name[64];
+ /* TODO(sergey): This will work for until names are
+ * consistent, we'll need to solve this somehow in the future.
+ */
+ int layer_index;
+ int location;
+
+ if (input->attribname[0] != '\0') {
+ layer_index = CustomData_get_named_layer(&dm->loopData,
+ CD_MLOOPUV,
+ input->attribname);
+ }
+ else {
+ layer_index = CustomData_get_active_layer(&dm->loopData,
+ CD_MLOOPUV);
+ }
+
+ BLI_snprintf(name, sizeof(name),
+ "fvar%d_offset",
+ input->attribid);
+ location = GPU_shader_get_uniform(shader, name);
+ /* Multiply by 2 because we're offseting U and V variables. */
+ GPU_shader_uniform_int(shader, location, layer_index * 2);
+ }
+ }
+
+ GPU_shader_unbind();
+}
+#endif
diff --git a/source/blender/gpu/intern/gpu_private.h b/source/blender/gpu/intern/gpu_private.h
new file mode 100644
index 00000000000..72627e3563e
--- /dev/null
+++ b/source/blender/gpu/intern/gpu_private.h
@@ -0,0 +1,36 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file gpu_private.h
+ * \ingroup gpu
+ */
+
+#ifndef __GPU_PRIVATE_H__
+#define __GPU_PRIVATE_H__
+
+/* call this before running any of the functions below */
+void gpu_extensions_init(void);
+void gpu_extensions_exit(void);
+
+/* gpu_debug.c */
+void gpu_debug_init(void);
+void gpu_debug_exit(void);
+
+#endif /* __GPU_PRIVATE_H__ */
diff --git a/source/blender/gpu/intern/gpu_select.c b/source/blender/gpu/intern/gpu_select.c
index 1d448231dda..4978229a350 100644
--- a/source/blender/gpu/intern/gpu_select.c
+++ b/source/blender/gpu/intern/gpu_select.c
@@ -31,14 +31,13 @@
*/
#include "GPU_select.h"
#include "GPU_extensions.h"
-
-#include "BLI_utildefines.h"
-
+#include "GPU_glew.h"
+
#include "MEM_guardedalloc.h"
#include "DNA_userdef_types.h"
-#include <GL/glew.h>
+#include "BLI_utildefines.h"
/* Ad hoc number of queries to allocate to skip doing many glGenQueries */
#define ALLOC_QUERIES 200
@@ -60,6 +59,7 @@ typedef struct GPUQueryState {
bool use_gpu_select;
/* cache on initialization */
unsigned int *buffer;
+ /* buffer size (stores number of integers, for actual size multiply by sizeof integer)*/
unsigned int bufsize;
/* mode of operation */
char mode;
@@ -83,7 +83,7 @@ void GPU_select_begin(unsigned int *buffer, unsigned int bufsize, rctf *input, c
g_query_state.oldhits = oldhits;
if (!g_query_state.use_gpu_select) {
- glSelectBuffer( bufsize, (GLuint *)buffer);
+ glSelectBuffer(bufsize, (GLuint *)buffer);
glRenderMode(GL_SELECT);
glInitNames();
glPushName(-1);
@@ -93,8 +93,8 @@ void GPU_select_begin(unsigned int *buffer, unsigned int bufsize, rctf *input, c
g_query_state.num_of_queries = ALLOC_QUERIES;
- g_query_state.queries = MEM_mallocN(g_query_state.num_of_queries * sizeof(*g_query_state.queries) , "gpu selection queries");
- g_query_state.id = MEM_mallocN(g_query_state.num_of_queries * sizeof(*g_query_state.id) , "gpu selection ids");
+ g_query_state.queries = MEM_mallocN(g_query_state.num_of_queries * sizeof(*g_query_state.queries), "gpu selection queries");
+ g_query_state.id = MEM_mallocN(g_query_state.num_of_queries * sizeof(*g_query_state.id), "gpu selection ids");
glGenQueriesARB(g_query_state.num_of_queries, g_query_state.queries);
glPushAttrib(GL_DEPTH_BUFFER_BIT | GL_VIEWPORT_BIT);
@@ -136,7 +136,7 @@ void GPU_select_begin(unsigned int *buffer, unsigned int bufsize, rctf *input, c
bool GPU_select_load_id(unsigned int id)
{
/* if no selection mode active, ignore */
- if(!g_query_state.select_is_active)
+ if (!g_query_state.select_is_active)
return true;
if (!g_query_state.use_gpu_select) {
@@ -159,7 +159,7 @@ bool GPU_select_load_id(unsigned int id)
g_query_state.active_query++;
g_query_state.query_issued = true;
- if (g_query_state.mode == GPU_SELECT_NEAREST_SECOND_PASS) {
+ if (g_query_state.mode == GPU_SELECT_NEAREST_SECOND_PASS && g_query_state.index < g_query_state.oldhits) {
if (g_query_state.buffer[g_query_state.index * 4 + 3] == id) {
g_query_state.index++;
return true;
@@ -192,7 +192,9 @@ unsigned int GPU_select_end(void)
glGetQueryObjectuivARB(g_query_state.queries[i], GL_QUERY_RESULT_ARB, &result);
if (result > 0) {
if (g_query_state.mode != GPU_SELECT_NEAREST_SECOND_PASS) {
- if(hits < g_query_state.bufsize) {
+ int maxhits = g_query_state.bufsize / 4;
+
+ if (hits < maxhits) {
g_query_state.buffer[hits * 4] = 1;
g_query_state.buffer[hits * 4 + 1] = 0xFFFF;
g_query_state.buffer[hits * 4 + 2] = 0xFFFF;
diff --git a/source/blender/gpu/intern/gpu_simple_shader.c b/source/blender/gpu/intern/gpu_simple_shader.c
index 0cb712d220f..89d3c0f59df 100644
--- a/source/blender/gpu/intern/gpu_simple_shader.c
+++ b/source/blender/gpu/intern/gpu_simple_shader.c
@@ -42,14 +42,11 @@
* - Optimize for case where no texture matrix is used.
*/
-#include "GL/glew.h"
+#include "GPU_glew.h"
#include "BLI_math.h"
#include "BLI_utildefines.h"
-#include "DNA_mesh_types.h"
-#include "DNA_object_types.h"
-
#include "GPU_extensions.h"
#include "GPU_simple_shader.h"
@@ -154,7 +151,9 @@ static GPUShader *gpu_simple_shader(int options)
shader = GPU_shader_create(
datatoc_gpu_shader_simple_vert_glsl,
datatoc_gpu_shader_simple_frag_glsl,
- NULL, defines);
+ NULL,
+ NULL,
+ defines, 0, 0, 0);
if (shader) {
/* set texture map to first texture unit */
diff --git a/source/blender/gpu/shaders/gpu_program_smoke_color_frag.glsl b/source/blender/gpu/shaders/gpu_program_smoke_color_frag.glsl
new file mode 100644
index 00000000000..a94c823f408
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_program_smoke_color_frag.glsl
@@ -0,0 +1,32 @@
+!!ARBfp1.0
+PARAM dx = program.local[0];
+PARAM darkness = program.local[1];
+PARAM render = program.local[2];
+PARAM f = {1.442695041, 1.442695041, 1.442695041, 1.442695041};
+TEMP temp, shadow, flame, spec, value;
+TEX temp, fragment.texcoord[0], texture[0], 3D;
+TEX shadow, fragment.texcoord[0], texture[1], 3D;
+TEX flame, fragment.texcoord[0], texture[2], 3D;
+TEX spec, flame.r, texture[3], 1D;
+# unpremultiply volume texture
+RCP value.r, temp.a;
+MUL temp.r, temp.r, value.r;
+MUL temp.g, temp.g, value.r;
+MUL temp.b, temp.b, value.r;
+# calculate shading factor from density
+MUL value.r, temp.a, darkness.a;
+MUL value.r, value.r, dx.r;
+MUL value.r, value.r, f.r;
+EX2 value.r, -value.r;
+# alpha
+SUB temp.a, 1.0, value.r;
+# shade colors
+MUL temp.r, temp.r, shadow.r;
+MUL temp.g, temp.g, shadow.r;
+MUL temp.b, temp.b, shadow.r;
+MUL temp.r, temp.r, value.r;
+MUL temp.g, temp.g, value.r;
+MUL temp.b, temp.b, value.r;
+# for now this just replace smoke shading if rendering fire
+CMP result.color, render.r, temp, spec;
+END
diff --git a/source/blender/gpu/shaders/gpu_program_smoke_frag.glsl b/source/blender/gpu/shaders/gpu_program_smoke_frag.glsl
new file mode 100644
index 00000000000..04b171d24bd
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_program_smoke_frag.glsl
@@ -0,0 +1,27 @@
+!!ARBfp1.0
+PARAM dx = program.local[0];
+PARAM darkness = program.local[1];
+PARAM render = program.local[2];
+PARAM f = {1.442695041, 1.442695041, 1.442695041, 0.01};
+TEMP temp, shadow, flame, spec, value;
+TEX temp, fragment.texcoord[0], texture[0], 3D;
+TEX shadow, fragment.texcoord[0], texture[1], 3D;
+TEX flame, fragment.texcoord[0], texture[2], 3D;
+TEX spec, flame.r, texture[3], 1D;
+# calculate shading factor from density
+MUL value.r, temp.a, darkness.a;
+MUL value.r, value.r, dx.r;
+MUL value.r, value.r, f.r;
+EX2 temp, -value.r;
+# alpha
+SUB temp.a, 1.0, temp.r;
+# shade colors
+MUL temp.r, temp.r, shadow.r;
+MUL temp.g, temp.g, shadow.r;
+MUL temp.b, temp.b, shadow.r;
+MUL temp.r, temp.r, darkness.r;
+MUL temp.g, temp.g, darkness.g;
+MUL temp.b, temp.b, darkness.b;
+# for now this just replace smoke shading if rendering fire
+CMP result.color, render.r, temp, spec;
+END
diff --git a/source/blender/gpu/shaders/gpu_shader_fx_depth_resolve.glsl b/source/blender/gpu/shaders/gpu_shader_fx_depth_resolve.glsl
new file mode 100644
index 00000000000..e04cd7d3306
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_fx_depth_resolve.glsl
@@ -0,0 +1,14 @@
+uniform sampler2D depthbuffer;
+varying vec4 uvcoordsvar;
+
+void main(void)
+{
+ float depth = texture2D(depthbuffer, uvcoordsvar.xy).r;
+
+ /* XRay background, discard */
+ if (depth >= 1.0) {
+ discard;
+ }
+
+ gl_FragDepth = depth;
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_fx_dof_frag.glsl b/source/blender/gpu/shaders/gpu_shader_fx_dof_frag.glsl
new file mode 100644
index 00000000000..e9dab04de5d
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_fx_dof_frag.glsl
@@ -0,0 +1,208 @@
+/* amount of offset to move one pixel left-right.
+ * In second pass some dimensions are zero to control verical/horizontal convolution */
+uniform vec2 invrendertargetdim;
+// color buffer
+uniform sampler2D colorbuffer;
+//blurred color buffer for DOF effect
+uniform sampler2D blurredcolorbuffer;
+// slightly blurred buffer
+uniform sampler2D mblurredcolorbuffer;
+// depth buffer
+uniform sampler2D depthbuffer;
+
+// this includes focal distance in x and aperture size in y
+uniform vec4 dof_params;
+
+// viewvectors for reconstruction of world space
+uniform vec4 viewvecs[3];
+
+// coordinates on framebuffer in normalized (0.0-1.0) uv space
+varying vec4 uvcoordsvar;
+
+/* color texture coordinates, offset by a small amount */
+varying vec2 color_uv1;
+varying vec2 color_uv2;
+
+varying vec2 depth_uv1;
+varying vec2 depth_uv2;
+varying vec2 depth_uv3;
+varying vec2 depth_uv4;
+
+
+float calculate_far_coc(in float zdepth)
+{
+ float coc = dof_params.x * max(1.0 - dof_params.y / zdepth, 0.0);
+
+ /* multiply by 1.0 / sensor size to get the normalized size */
+ return coc * dof_params.z;
+}
+
+/* near coc only! when distance is nearer than focus plane first term is bigger than one */
+vec4 calculate_near_coc(in vec4 zdepth)
+{
+ vec4 coc = dof_params.x * max(vec4(dof_params.y) / zdepth - vec4(1.0), vec4(0.0));
+
+ /* multiply by 1.0 / sensor size to get the normalized size */
+ return coc * dof_params.z;
+}
+
+/* first pass blurs the color buffer heavily and gets the near coc only.
+ * There are many texture accesses here but they are done on a
+ * lower resolution image so overall bandwidth is not a concern */
+void first_pass()
+{
+ vec4 depth;
+ vec4 zdepth;
+ vec4 coc;
+ float final_coc;
+
+ /* amount to add to uvs so that they move one row further */
+ vec2 offset_row[3];
+ offset_row[0] = vec2(0.0, invrendertargetdim.y);
+ offset_row[1] = 2.0 * offset_row[0];
+ offset_row[2] = 3.0 * offset_row[0];
+
+ /* heavily blur the image */
+ vec4 color = texture2D(colorbuffer, color_uv1);
+ color += texture2D(colorbuffer, color_uv1 + offset_row[1]);
+ color += texture2D(colorbuffer, color_uv2);
+ color += texture2D(colorbuffer, color_uv2 + offset_row[1]);
+ color /= 4.0;
+
+ depth.r = texture2D(depthbuffer, depth_uv1).r;
+ depth.g = texture2D(depthbuffer, depth_uv2).r;
+ depth.b = texture2D(depthbuffer, depth_uv3).r;
+ depth.a = texture2D(depthbuffer, depth_uv4).r;
+
+ zdepth = get_view_space_z_from_depth(vec4(viewvecs[0].z), vec4(viewvecs[1].z), depth);
+ coc = calculate_near_coc(zdepth);
+
+ depth.r = texture2D(depthbuffer, depth_uv1 + offset_row[0]).r;
+ depth.g = texture2D(depthbuffer, depth_uv2 + offset_row[0]).r;
+ depth.b = texture2D(depthbuffer, depth_uv3 + offset_row[0]).r;
+ depth.a = texture2D(depthbuffer, depth_uv4 + offset_row[0]).r;
+
+ zdepth = get_view_space_z_from_depth(vec4(viewvecs[0].z), vec4(viewvecs[1].z), depth);
+ coc = max(calculate_near_coc(zdepth), coc);
+
+ depth.r = texture2D(depthbuffer, depth_uv1 + offset_row[1]).r;
+ depth.g = texture2D(depthbuffer, depth_uv2 + offset_row[1]).r;
+ depth.b = texture2D(depthbuffer, depth_uv3 + offset_row[1]).r;
+ depth.a = texture2D(depthbuffer, depth_uv4 + offset_row[1]).r;
+
+ zdepth = get_view_space_z_from_depth(vec4(viewvecs[0].z), vec4(viewvecs[1].z), depth);
+ coc = max(calculate_near_coc(zdepth), coc);
+
+ depth.r = texture2D(depthbuffer, depth_uv1 + offset_row[2]).r;
+ depth.g = texture2D(depthbuffer, depth_uv2 + offset_row[2]).r;
+ depth.b = texture2D(depthbuffer, depth_uv3 + offset_row[2]).r;
+ depth.a = texture2D(depthbuffer, depth_uv4 + offset_row[2]).r;
+
+ zdepth = get_view_space_z_from_depth(vec4(viewvecs[0].z), vec4(viewvecs[1].z), depth);
+ coc = max(calculate_near_coc(zdepth), coc);
+
+ final_coc = max(max(coc.x, coc.y), max(coc.z, coc.w));
+ gl_FragColor = vec4(color.rgb, final_coc);
+}
+
+/* second pass, gaussian blur the downsampled image */
+void second_pass()
+{
+ vec4 depth = vec4(texture2D(depthbuffer, uvcoordsvar.xy).r);
+
+ /* clever sampling to sample 2 pixels at once. Of course it's not real gaussian sampling this way */
+ vec4 color = texture2D(colorbuffer, uvcoordsvar.xy) * 0.3125;
+ color += texture2D(colorbuffer, uvcoordsvar.xy + invrendertargetdim) * 0.234375;
+ color += texture2D(colorbuffer, uvcoordsvar.xy + 2.5 * invrendertargetdim) * 0.09375;
+ color += texture2D(colorbuffer, uvcoordsvar.xy + 4.5 * invrendertargetdim) * 0.015625;
+ color += texture2D(colorbuffer, uvcoordsvar.xy -invrendertargetdim) * 0.234375;
+ color += texture2D(colorbuffer, uvcoordsvar.xy -2.5 * invrendertargetdim) * 0.09375;
+ color += texture2D(colorbuffer, uvcoordsvar.xy -4.5 * invrendertargetdim) * 0.015625;
+
+ gl_FragColor = color;
+}
+
+
+/* third pass, calculate the final coc from blurred and unblurred images */
+void third_pass()
+{
+ vec4 color = texture2D(colorbuffer, uvcoordsvar.xy);
+ vec4 color_blurred = texture2D(blurredcolorbuffer, uvcoordsvar.xy);
+ float coc = 2.0 * max(color_blurred.a, color.a); - color.a;
+ gl_FragColor = vec4(color.rgb, coc);
+}
+
+
+/* fourth pass, blur the final coc once to get rid of discontinuities */
+void fourth_pass()
+{
+ vec4 color = texture2D(colorbuffer, uvcoordsvar.xz);
+ color += texture2D(colorbuffer, uvcoordsvar.yz);
+ color += texture2D(colorbuffer, uvcoordsvar.xw);
+ color += texture2D(colorbuffer, uvcoordsvar.yw);
+
+ gl_FragColor = color / 4.0;
+}
+
+vec4 small_sample_blur(in sampler2D colorbuffer, in vec2 uv, in vec4 color)
+{
+ float weight = 1.0/ 17.0;
+ vec4 result = weight * color;
+ weight *= 4.0;
+
+ result += weight * texture2D(colorbuffer, uv + color_uv1.xy);
+ result += weight * texture2D(colorbuffer, uv - color_uv1.xy);
+ result += weight * texture2D(colorbuffer, uv + color_uv1.yx);
+ result += weight * texture2D(colorbuffer, uv - color_uv1.yx);
+
+ return result;
+}
+
+
+/* fourth pass, just visualize the third pass contents */
+void fifth_pass()
+{
+ vec4 factors;
+ vec4 color_orig = texture2D(colorbuffer, uvcoordsvar.xy);
+ vec4 highblurred = texture2D(blurredcolorbuffer, uvcoordsvar.xy);
+ vec4 mediumblurred = texture2D(mblurredcolorbuffer, uvcoordsvar.xy);
+ vec4 smallblurred = small_sample_blur(colorbuffer, uvcoordsvar.xy, color_orig);
+ float depth = texture2D(depthbuffer, uvcoordsvar.xy).r;
+
+ float zdepth = get_view_space_z_from_depth(vec4(viewvecs[0].z), vec4(viewvecs[1].z), vec4(depth)).r;
+ float coc_far = clamp(calculate_far_coc(zdepth), 0.0, 1.0);
+
+ /* calculate final coc here */
+ float coc = max(max(coc_far, mediumblurred.a), 0.0);
+
+ float width = 2.5;
+ float radius = 0.2;
+
+ factors.x = 1.0 - clamp(width * coc, 0.0, 1.0);
+ factors.y = 1.0 - clamp(abs(width * (coc - 2.0 * radius)), 0.0, 1.0);
+ factors.z = 1.0 - clamp(abs(width * (coc - 3.0 * radius)), 0.0, 1.0);
+ factors.w = 1.0 - clamp(abs(width * (coc - 4.0 * radius)), 0.0, 1.0);
+ /* blend! */
+ vec4 color = factors.x * color_orig + factors.y * smallblurred + factors.z * mediumblurred + factors.w * highblurred;
+
+ color /= dot(factors, vec4(1.0));
+ /* using original color is not correct, but use that for now because alpha of
+ * blurred buffers uses CoC instead */
+ gl_FragColor = vec4(color.rgb, color_orig.a);
+}
+
+
+void main()
+{
+#ifdef FIRST_PASS
+ first_pass();
+#elif defined(SECOND_PASS)
+ second_pass();
+#elif defined(THIRD_PASS)
+ third_pass();
+#elif defined(FOURTH_PASS)
+ fourth_pass();
+#elif defined(FIFTH_PASS)
+ fifth_pass();
+#endif
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_fx_dof_hq_frag.glsl b/source/blender/gpu/shaders/gpu_shader_fx_dof_hq_frag.glsl
new file mode 100644
index 00000000000..e315d2fb97a
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_fx_dof_hq_frag.glsl
@@ -0,0 +1,166 @@
+/* amount of offset to move one pixel left-right.
+ * In second pass some dimensions are zero to control verical/horizontal convolution */
+uniform vec2 invrendertargetdim;
+
+uniform ivec2 rendertargetdim;
+
+/* color buffer */
+uniform sampler2D colorbuffer;
+uniform sampler2D farbuffer;
+uniform sampler2D nearbuffer;
+
+/* depth buffer */
+uniform sampler2D depthbuffer;
+
+uniform sampler2D cocbuffer;
+
+/* this includes focal distance in x and aperture size in y */
+uniform vec4 dof_params;
+
+/* viewvectors for reconstruction of world space */
+uniform vec4 viewvecs[3];
+
+/* initial uv coordinate */
+varying vec2 uvcoord;
+
+/* coordinate used for calculating radius et al set in geometry shader */
+varying vec2 particlecoord;
+varying vec4 color;
+
+/* downsampling coordinates */
+varying vec2 downsample1;
+varying vec2 downsample2;
+varying vec2 downsample3;
+varying vec2 downsample4;
+
+#define M_PI 3.1415926535897932384626433832795
+
+/* calculate 4 samples at once */
+vec4 calculate_coc(in vec4 zdepth)
+{
+ vec4 coc = dof_params.x * (vec4(dof_params.y) / zdepth - vec4(1.0));
+
+ /* multiply by 1.0 / sensor size to get the normalized size */
+ return coc * dof_params.z;
+}
+
+#define THRESHOLD 0.0
+
+/* downsample the color buffer to half resolution */
+void downsample_pass()
+{
+ vec4 depth;
+ vec4 zdepth;
+ vec4 coc;
+ float far_coc, near_coc;
+
+ /* custom downsampling. We need to be careful to sample nearest here to avoid leaks */
+ vec4 color1 = texture2D(colorbuffer, downsample1);
+ vec4 color2 = texture2D(colorbuffer, downsample2);
+ vec4 color3 = texture2D(colorbuffer, downsample3);
+ vec4 color4 = texture2D(colorbuffer, downsample4);
+
+ depth.r = texture2D(depthbuffer, downsample1).r;
+ depth.g = texture2D(depthbuffer, downsample2).r;
+ depth.b = texture2D(depthbuffer, downsample3).r;
+ depth.a = texture2D(depthbuffer, downsample4).r;
+
+ zdepth = get_view_space_z_from_depth(vec4(viewvecs[0].z), vec4(viewvecs[1].z), depth);
+ coc = calculate_coc(zdepth);
+ vec4 coc_far = -coc;
+
+ /* now we need to write the near-far fields premultiplied by the coc */
+ vec4 near_weights = vec4((coc.x >= THRESHOLD) ? 1.0 : 0.0, (coc.y >= THRESHOLD) ? 1.0 : 0.0,
+ (coc.z >= THRESHOLD) ? 1.0 : 0.0, (coc.w >= THRESHOLD) ? 1.0 : 0.0);
+ vec4 far_weights = vec4((coc_far.x >= THRESHOLD) ? 1.0 : 0.0, (coc_far.y >= THRESHOLD) ? 1.0 : 0.0,
+ (coc_far.z >= THRESHOLD) ? 1.0 : 0.0, (coc_far.w >= THRESHOLD) ? 1.0 : 0.0);
+
+ near_coc = max(max(max(coc.x, coc.y), max(coc.z, coc.w)), 0.0);
+ far_coc = max(max(max(coc_far.x, coc_far.y), max(coc_far.z, coc_far.w)), 0.0);
+
+ float norm_near = dot(near_weights, vec4(1.0));
+ float norm_far = dot(far_weights, vec4(1.0));
+
+ /* now write output to weighted buffers. */
+ gl_FragData[0] = color1 * near_weights.x + color2 * near_weights.y + color3 * near_weights.z +
+ color4 * near_weights.w;
+ gl_FragData[1] = color1 * far_weights.x + color2 * far_weights.y + color3 * far_weights.z +
+ color4 * far_weights.w;
+
+ if (norm_near > 0.0)
+ gl_FragData[0] /= norm_near;
+ if (norm_far > 0.0)
+ gl_FragData[1] /= norm_far;
+ gl_FragData[2] = vec4(near_coc, far_coc, 0.0, 1.0);
+}
+
+/* accumulate color in the near/far blur buffers */
+void accumulate_pass(void) {
+ float theta = atan(particlecoord.y, particlecoord.x);
+ float r;
+
+ if (dof_params.w == 0.0)
+ r = 1.0;
+ else
+ r = cos(M_PI / dof_params.w) / (cos(theta - (2.0 * M_PI / dof_params.w) * floor((dof_params.w * theta + M_PI) / (2.0 * M_PI))));
+
+ if (dot(particlecoord, particlecoord) > r * r)
+ discard;
+
+ gl_FragData[0] = color;
+}
+#define MERGE_THRESHOLD 4.0
+
+/* combine the passes, */
+void final_pass(void) {
+ vec4 finalcolor;
+ float totalweight;
+ float depth = texture2D(depthbuffer, uvcoord).r;
+
+ vec4 zdepth = get_view_space_z_from_depth(vec4(viewvecs[0].z), vec4(viewvecs[1].z), vec4(depth));
+ float coc_near = calculate_coc(zdepth).r;
+ float coc_far = max(-coc_near, 0.0);
+ coc_near = max(coc_near, 0.0);
+
+ vec4 farcolor = texture2D(farbuffer, uvcoord);
+ float farweight = farcolor.a;
+ if (farweight > 0.0)
+ farcolor /= farweight;
+ vec4 nearcolor = texture2D(nearbuffer, uvcoord);
+
+ vec4 srccolor = texture2D(colorbuffer, uvcoord);
+
+ vec4 coc = texture2D(cocbuffer, uvcoord);
+
+ float mixfac = smoothstep(1.0, MERGE_THRESHOLD, coc_far);
+ finalcolor = mix(srccolor, farcolor, mixfac);
+
+ farweight = mix(1.0, farweight, mixfac);
+
+ float nearweight = nearcolor.a;
+ if (nearweight > 0.0) {
+ nearcolor /= nearweight;
+ }
+
+ if (coc_near > 1.0) {
+ nearweight = 1.0;
+ finalcolor = nearcolor;
+ }
+ else {
+ totalweight = nearweight + farweight;
+ finalcolor = mix(finalcolor, nearcolor, nearweight / totalweight);
+ }
+
+ gl_FragData[0] = finalcolor;
+}
+
+void main()
+{
+#ifdef FIRST_PASS
+ downsample_pass();
+#elif defined(SECOND_PASS)
+ accumulate_pass();
+#elif defined(THIRD_PASS)
+ final_pass();
+#endif
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_fx_dof_hq_geo.glsl b/source/blender/gpu/shaders/gpu_shader_fx_dof_hq_geo.glsl
new file mode 100644
index 00000000000..7918122a681
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_fx_dof_hq_geo.glsl
@@ -0,0 +1,50 @@
+uniform ivec2 rendertargetdim;
+uniform sampler2D colorbuffer;
+
+uniform vec2 layerselection;
+
+uniform sampler2D cocbuffer;
+
+/* initial uv coordinate */
+varying in vec2 uvcoord[1];
+varying out vec2 particlecoord;
+varying out vec4 color;
+
+
+#define M_PI 3.1415926535897932384626433832795
+
+void main(void)
+{
+ vec4 coc = texture2DLod(cocbuffer, uvcoord[0], 0.0);
+
+ float offset_val = dot(coc.rg, layerselection);
+ if (offset_val < 1.0)
+ return;
+
+ vec4 colortex = texture2DLod(colorbuffer, uvcoord[0], 0.0);
+
+ /* find the area the pixel will cover and divide the color by it */
+ float alpha = 1.0 / (offset_val * offset_val * M_PI);
+ colortex *= alpha;
+ colortex.a = alpha;
+
+ vec2 offset_far = vec2(offset_val * 0.5) / vec2(rendertargetdim.x, rendertargetdim.y);
+
+ gl_Position = gl_PositionIn[0] + vec4(-offset_far.x, -offset_far.y, 0.0, 0.0);
+ color = colortex;
+ particlecoord = vec2(-1.0, -1.0);
+ EmitVertex();
+ gl_Position = gl_PositionIn[0] + vec4(-offset_far.x, offset_far.y, 0.0, 0.0);
+ particlecoord = vec2(-1.0, 1.0);
+ color = colortex;
+ EmitVertex();
+ gl_Position = gl_PositionIn[0] + vec4(offset_far.x, -offset_far.y, 0.0, 0.0);
+ particlecoord = vec2(1.0, -1.0);
+ color = colortex;
+ EmitVertex();
+ gl_Position = gl_PositionIn[0] + vec4(offset_far.x, offset_far.y, 0.0, 0.0);
+ particlecoord = vec2(1.0, 1.0);
+ color = colortex;
+ EmitVertex();
+ EndPrimitive();
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_fx_dof_hq_vert.glsl b/source/blender/gpu/shaders/gpu_shader_fx_dof_hq_vert.glsl
new file mode 100644
index 00000000000..09a0c75facc
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_fx_dof_hq_vert.glsl
@@ -0,0 +1,58 @@
+uniform vec2 invrendertargetdim;
+uniform ivec2 rendertargetdim;
+/* initial uv coordinate */
+varying vec2 uvcoord;
+
+/* coordinate used for calculating radius et al set in geometry shader */
+varying vec2 particlecoord;
+
+/* downsampling coordinates */
+varying vec2 downsample1;
+varying vec2 downsample2;
+varying vec2 downsample3;
+varying vec2 downsample4;
+
+void vert_dof_downsample()
+{
+ /* gather pixels from neighbors. half dimensions means we offset half a pixel to
+ * get this right though it's possible we may lose a pixel at some point */
+ downsample1 = gl_MultiTexCoord0.xy + vec2(-0.5, -0.5) * invrendertargetdim;
+ downsample2 = gl_MultiTexCoord0.xy + vec2(-0.5, 0.5) * invrendertargetdim;
+ downsample3 = gl_MultiTexCoord0.xy + vec2(0.5, 0.5) * invrendertargetdim;
+ downsample4 = gl_MultiTexCoord0.xy + vec2(0.5, -0.5) * invrendertargetdim;
+
+ gl_Position = gl_Vertex;
+}
+
+/* geometry shading pass, calculate a texture coordinate based on the indexed id */
+void vert_dof_coc_scatter_pass()
+{
+ vec2 pixel = vec2(rendertargetdim.x, rendertargetdim.y);
+ /* some math to get the target pixel */
+ int row = gl_InstanceID / rendertargetdim.x;
+ int column = gl_InstanceID % rendertargetdim.x;
+ uvcoord = (vec2(column, row) + vec2(0.5)) / pixel;
+
+ vec2 pos = uvcoord * 2.0 - vec2(1.0);
+ gl_Position = vec4(pos.x, pos.y, 0.0, 1.0);
+
+// uvcoord = vec2(0.5, 0.5);
+// gl_Position = vec4(0.0, 0.0, 0.0, 1.0);
+}
+
+void vert_dof_final()
+{
+ uvcoord = gl_MultiTexCoord0.xy;
+ gl_Position = gl_Vertex;
+}
+
+void main()
+{
+#if defined(FIRST_PASS)
+ vert_dof_downsample();
+#elif defined(SECOND_PASS)
+ vert_dof_coc_scatter_pass();
+#else
+ vert_dof_final();
+#endif
+} \ No newline at end of file
diff --git a/source/blender/gpu/shaders/gpu_shader_fx_dof_vert.glsl b/source/blender/gpu/shaders/gpu_shader_fx_dof_vert.glsl
new file mode 100644
index 00000000000..a2ef990c4e8
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_fx_dof_vert.glsl
@@ -0,0 +1,68 @@
+uniform vec2 invrendertargetdim;
+
+//texture coordinates for framebuffer read
+varying vec4 uvcoordsvar;
+
+/* color texture coordinates, offset by a small amount */
+varying vec2 color_uv1;
+varying vec2 color_uv2;
+
+varying vec2 depth_uv1;
+varying vec2 depth_uv2;
+varying vec2 depth_uv3;
+varying vec2 depth_uv4;
+
+//very simple shader for gull screen FX, just pass values on
+
+void vert_generic()
+{
+ uvcoordsvar = gl_MultiTexCoord0;
+ gl_Position = gl_Vertex;
+}
+
+void vert_dof_first_pass()
+{
+ /* we offset the texture coordinates by 1.5 pixel,
+ * then we reuse that to sample the surrounding pixels */
+ color_uv1 = gl_MultiTexCoord0.xy + vec2(-1.5, -1.5) * invrendertargetdim;
+ color_uv2 = gl_MultiTexCoord0.xy + vec2(0.5, -1.5) * invrendertargetdim;
+
+ depth_uv1 = gl_MultiTexCoord0.xy + vec2(-1.5, -1.5) * invrendertargetdim;
+ depth_uv2 = gl_MultiTexCoord0.xy + vec2(-0.5, -1.5) * invrendertargetdim;
+ depth_uv3 = gl_MultiTexCoord0.xy + vec2(0.5, -1.5) * invrendertargetdim;
+ depth_uv4 = gl_MultiTexCoord0.xy + vec2(1.5, -1.5) * invrendertargetdim;
+
+ gl_Position = gl_Vertex;
+}
+
+void vert_dof_fourth_pass()
+{
+ vec4 halfpixel = vec4(-0.5, 0.5, -0.5, 0.5);
+ uvcoordsvar = gl_MultiTexCoord0.xxyy + halfpixel * vec4(invrendertargetdim.x,
+ invrendertargetdim.x, invrendertargetdim.y, invrendertargetdim.y);
+
+ gl_Position = gl_Vertex;
+}
+
+void vert_dof_fifth_pass()
+{
+ vec4 halfpixel = vec4(-0.5, 0.5, -0.5, 0.5);
+ color_uv1 = vec2(0.5, 1.5) * invrendertargetdim;
+
+ uvcoordsvar = gl_MultiTexCoord0;
+ gl_Position = gl_Vertex;
+}
+
+void main()
+{
+#ifdef FIRST_PASS
+ vert_dof_first_pass();
+#elif defined(FOURTH_PASS)
+ vert_dof_fourth_pass();
+#elif defined(FIFTH_PASS)
+ vert_dof_fifth_pass();
+#else
+ vert_generic();
+#endif
+}
+
diff --git a/source/blender/gpu/shaders/gpu_shader_fx_lib.glsl b/source/blender/gpu/shaders/gpu_shader_fx_lib.glsl
new file mode 100644
index 00000000000..1dc49b52be1
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_fx_lib.glsl
@@ -0,0 +1,39 @@
+/* simple depth reconstruction, see http://www.derschmale.com/2014/01/26/reconstructing-positions-from-the-depth-buffer
+ * we change the factors from the article to fit the OpennGL model. */
+#ifdef PERSP_MATRIX
+
+/* perspective camera code */
+
+vec3 get_view_space_from_depth(in vec2 uvcoords, in vec3 viewvec_origin, in vec3 viewvec_diff, in float depth)
+{
+ float d = 2.0 * depth - 1.0;
+
+ float zview = -gl_ProjectionMatrix[3][2] / (d + gl_ProjectionMatrix[2][2]);
+
+ return zview * (viewvec_origin + vec3(uvcoords, 0.0) * viewvec_diff);
+}
+
+vec4 get_view_space_z_from_depth(in vec4 near, in vec4 range, in vec4 depth)
+{
+ vec4 d = 2.0 * depth - vec4(1.0);
+
+ /* return positive value, so sign differs! */
+ return vec4(gl_ProjectionMatrix[3][2]) / (d + vec4(gl_ProjectionMatrix[2][2]));
+}
+
+#else
+/* orthographic camera code */
+
+vec3 get_view_space_from_depth(in vec2 uvcoords, in vec3 viewvec_origin, in vec3 viewvec_diff, in float depth)
+{
+ vec3 offset = vec3(uvcoords, depth);
+
+ return vec3(viewvec_origin + offset * viewvec_diff);
+}
+
+vec4 get_view_space_z_from_depth(in vec4 near, in vec4 range, in vec4 depth)
+{
+ return -(near + depth * range);
+}
+
+#endif
diff --git a/source/blender/gpu/shaders/gpu_shader_fx_ssao_frag.glsl b/source/blender/gpu/shaders/gpu_shader_fx_ssao_frag.glsl
new file mode 100644
index 00000000000..494a74dcdf8
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_fx_ssao_frag.glsl
@@ -0,0 +1,94 @@
+// color buffer
+uniform sampler2D colorbuffer;
+
+// jitter texture for ssao
+uniform sampler2D jitter_tex;
+
+// concentric sample texture for ssao
+uniform sampler1D ssao_concentric_tex;
+
+// depth buffer
+uniform sampler2D depthbuffer;
+// coordinates on framebuffer in normalized (0.0-1.0) uv space
+varying vec4 uvcoordsvar;
+
+/* ssao_params.x : pixel scale for the ssao radious */
+/* ssao_params.y : factor for the ssao darkening */
+uniform vec4 ssao_params;
+uniform vec3 ssao_sample_params;
+uniform vec4 ssao_color;
+
+/* store the view space vectors for the corners of the view frustum here.
+ * It helps to quickly reconstruct view space vectors by using uv coordinates,
+ * see http://www.derschmale.com/2014/01/26/reconstructing-positions-from-the-depth-buffer */
+uniform vec4 viewvecs[3];
+
+vec3 calculate_view_space_normal(in vec3 viewposition)
+{
+ vec3 normal = cross(normalize(dFdx(viewposition)),
+ ssao_params.w * normalize(dFdy(viewposition)));
+ normalize(normal);
+ return normal;
+}
+
+float calculate_ssao_factor(float depth)
+{
+ /* take the normalized ray direction here */
+ vec2 rotX = texture2D(jitter_tex, uvcoordsvar.xy * ssao_sample_params.yz).rg;
+ vec2 rotY = vec2(-rotX.y, rotX.x);
+
+ /* occlusion is zero in full depth */
+ if (depth == 1.0)
+ return 0.0;
+
+ vec3 position = get_view_space_from_depth(uvcoordsvar.xy, viewvecs[0].xyz, viewvecs[1].xyz, depth);
+ vec3 normal = calculate_view_space_normal(position);
+
+ // find the offset in screen space by multiplying a point in camera space at the depth of the point by the projection matrix.
+ vec2 offset;
+ float homcoord = gl_ProjectionMatrix[2][3] * position.z + gl_ProjectionMatrix[3][3];
+ offset.x = gl_ProjectionMatrix[0][0] * ssao_params.x / homcoord;
+ offset.y = gl_ProjectionMatrix[1][1] * ssao_params.x / homcoord;
+ /* convert from -1.0...1.0 range to 0.0..1.0 for easy use with texture coordinates */
+ offset *= 0.5;
+
+ float factor = 0.0;
+ int x;
+ int num_samples = int(ssao_sample_params.x);
+
+ for (x = 0; x < num_samples; x++) {
+ vec2 dir_sample = texture1D(ssao_concentric_tex, (float(x) + 0.5) / ssao_sample_params.x).rg;
+
+ /* rotate with random direction to get jittered result */
+ vec2 dir_jittered = vec2(dot(dir_sample, rotX), dot(dir_sample, rotY));
+
+ vec2 uvcoords = uvcoordsvar.xy + dir_jittered * offset;
+
+ if (uvcoords.x > 1.0 || uvcoords.x < 0.0 || uvcoords.y > 1.0 || uvcoords.y < 0.0)
+ continue;
+
+ float depth_new = texture2D(depthbuffer, uvcoords).r;
+ if (depth_new != 1.0) {
+ vec3 pos_new = get_view_space_from_depth(uvcoords, viewvecs[0].xyz, viewvecs[1].xyz, depth_new);
+ vec3 dir = pos_new - position;
+ float len = length(dir);
+ float f = dot(dir, normal);
+
+ /* use minor bias here to avoid self shadowing */
+ if (f > 0.05 * len + 0.0001)
+ factor += f * 1.0/(len * (1.0 + len * len * ssao_params.z));
+ }
+ }
+
+ factor /= ssao_sample_params.x;
+
+ return clamp(factor * ssao_params.y, 0.0, 1.0);
+}
+
+void main()
+{
+ float depth = texture2D(depthbuffer, uvcoordsvar.xy).r;
+ vec4 scene_col = texture2D(colorbuffer, uvcoordsvar.xy);
+ vec3 final_color = mix(scene_col.rgb, ssao_color.rgb, calculate_ssao_factor(depth));
+ gl_FragColor = vec4(final_color.rgb, scene_col.a);
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_fx_vert.glsl b/source/blender/gpu/shaders/gpu_shader_fx_vert.glsl
new file mode 100644
index 00000000000..5194e414520
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_fx_vert.glsl
@@ -0,0 +1,9 @@
+varying vec4 uvcoordsvar;
+
+//very simple shader for full screen FX, just pass values on
+
+void main()
+{
+ uvcoordsvar = gl_MultiTexCoord0;
+ gl_Position = gl_Vertex;
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_geometry.glsl b/source/blender/gpu/shaders/gpu_shader_geometry.glsl
new file mode 100644
index 00000000000..a0ae96a1f72
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_geometry.glsl
@@ -0,0 +1,100 @@
+uniform int PrimitiveIdBase;
+uniform int osd_active_uv_offset;
+
+varying vec3 varnormal;
+varying vec3 varposition;
+
+in block {
+ VertexData v;
+} inpt[4];
+
+uniform bool osd_flat_shading;
+uniform int osd_fvar_count;
+
+#define INTERP_FACE_VARYING_2(result, fvarOffset, tessCoord) \
+ { \
+ vec2 v[4]; \
+ int primOffset = (gl_PrimitiveID + PrimitiveIdBase) * 4; \
+ for (int i = 0; i < 4; ++i) { \
+ int index = (primOffset + i) * osd_fvar_count + fvarOffset; \
+ v[i] = vec2(texelFetch(FVarDataBuffer, index).s, \
+ texelFetch(FVarDataBuffer, index + 1).s); \
+ } \
+ result = mix(mix(v[0], v[1], tessCoord.s), \
+ mix(v[3], v[2], tessCoord.s), \
+ tessCoord.t); \
+ }
+
+uniform samplerBuffer FVarDataBuffer;
+
+out block {
+ VertexData v;
+} outpt;
+
+void set_mtface_vertex_attrs(vec2 st);
+
+void emit_flat(int index, vec3 normal)
+{
+ outpt.v.position = inpt[index].v.position;
+ outpt.v.normal = normal;
+
+ /* Compatibility */
+ varnormal = outpt.v.normal;
+ varposition = outpt.v.position.xyz;
+
+ /* TODO(sergey): Only uniform subdivisions atm. */
+ vec2 quadst[4] = vec2[](vec2(0,0), vec2(1,0), vec2(1,1), vec2(0,1));
+ vec2 st = quadst[index];
+
+ INTERP_FACE_VARYING_2(outpt.v.uv, osd_active_uv_offset, st);
+
+ set_mtface_vertex_attrs(st);
+
+ gl_Position = gl_ProjectionMatrix * inpt[index].v.position;
+ EmitVertex();
+}
+
+void emit_smooth(int index)
+{
+ outpt.v.position = inpt[index].v.position;
+ outpt.v.normal = inpt[index].v.normal;
+
+ /* Compatibility */
+ varnormal = outpt.v.normal;
+ varposition = outpt.v.position.xyz;
+
+ /* TODO(sergey): Only uniform subdivisions atm. */
+ vec2 quadst[4] = vec2[](vec2(0,0), vec2(1,0), vec2(1,1), vec2(0,1));
+ vec2 st = quadst[index];
+
+ INTERP_FACE_VARYING_2(outpt.v.uv, osd_active_uv_offset, st);
+
+ set_mtface_vertex_attrs(st);
+
+ gl_Position = gl_ProjectionMatrix * inpt[index].v.position;
+ EmitVertex();
+}
+
+void main()
+{
+ gl_PrimitiveID = gl_PrimitiveIDIn;
+
+ if (osd_flat_shading) {
+ vec3 A = (inpt[0].v.position - inpt[1].v.position).xyz;
+ vec3 B = (inpt[3].v.position - inpt[1].v.position).xyz;
+ vec3 flat_normal = normalize(cross(B, A));
+ emit_flat(0, flat_normal);
+ emit_flat(1, flat_normal);
+ emit_flat(3, flat_normal);
+ emit_flat(2, flat_normal);
+ }
+ else {
+ emit_smooth(0);
+ emit_smooth(1);
+ emit_smooth(3);
+ emit_smooth(2);
+ }
+ EndPrimitive();
+}
+
+void set_mtface_vertex_attrs(vec2 st) {
diff --git a/source/blender/gpu/shaders/gpu_shader_material.glsl b/source/blender/gpu/shaders/gpu_shader_material.glsl
index 3ba36c11311..311fcb8ead2 100644
--- a/source/blender/gpu/shaders/gpu_shader_material.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_material.glsl
@@ -149,10 +149,23 @@ void geom(vec3 co, vec3 nor, mat4 viewinvmat, vec3 attorco, vec2 attuv, vec4 att
uv_attribute(attuv, uv);
normal = -normalize(nor); /* blender render normal is negated */
vcol_attribute(attvcol, vcol);
+ srgb_to_linearrgb(vcol, vcol);
vcol_alpha = attvcol.a;
frontback = (gl_FrontFacing)? 1.0: 0.0;
}
+void particle_info(vec4 sprops, vec3 loc, vec3 vel, vec3 avel, out float index, out float age, out float life_time, out vec3 location, out float size, out vec3 velocity, out vec3 angular_velocity)
+{
+ index = sprops.x;
+ age = sprops.y;
+ life_time = sprops.z;
+ size = sprops.w;
+
+ location = loc;
+ velocity = vel;
+ angular_velocity = avel;
+}
+
void mapping(vec3 vec, mat4 mat, vec3 minvec, vec3 maxvec, float domin, float domax, out vec3 outvec)
{
outvec = (mat * vec4(vec, 1.0)).xyz;
@@ -169,9 +182,9 @@ 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)
+void lamp(vec4 col, float energy, 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;
+ outcol = col * energy;
outlv = lv;
outdist = dist;
outshadow = vec4(shadow, 1.0);
@@ -297,6 +310,10 @@ void math_modulo(float val1, float val2, out float outval)
outval = 0.0;
else
outval = mod(val1, val2);
+
+ /* change sign to match C convention, mod in GLSL will take absolute for negative numbers,
+ * see https://www.opengl.org/sdk/docs/man/html/mod.xhtml */
+ outval = (val1 > 0.0) ? outval : -outval;
}
void math_abs(float val1, out float outval)
@@ -338,6 +355,7 @@ void vec_math_cross(vec3 v1, vec3 v2, out vec3 outvec, out float outval)
{
outvec = cross(v1, v2);
outval = length(outvec);
+ outvec /= outval;
}
void vec_math_normalize(vec3 v, out vec3 outvec, out float outval)
@@ -357,6 +375,12 @@ void normal(vec3 dir, vec3 nor, out vec3 outnor, out float outdot)
outdot = -dot(dir, nor);
}
+void normal_new_shading(vec3 dir, vec3 nor, out vec3 outnor, out float outdot)
+{
+ outnor = normalize(nor);
+ outdot = dot(normalize(dir), nor);
+}
+
void curves_vec(float fac, vec3 vec, sampler2D curvemap, out vec3 outvec)
{
outvec.x = texture2D(curvemap, vec2((vec.x + 1.0)*0.5, 0.0)).x;
@@ -687,22 +711,7 @@ void mix_linear(float fac, vec4 col1, vec4 col2, out vec4 outcol)
{
fac = clamp(fac, 0.0, 1.0);
- outcol = col1;
-
- if(col2.r > 0.5)
- outcol.r= col1.r + fac*(2.0*(col2.r - 0.5));
- else
- outcol.r= col1.r + fac*(2.0*(col2.r) - 1.0);
-
- if(col2.g > 0.5)
- outcol.g= col1.g + fac*(2.0*(col2.g - 0.5));
- else
- outcol.g= col1.g + fac*(2.0*(col2.g) - 1.0);
-
- if(col2.b > 0.5)
- outcol.b= col1.b + fac*(2.0*(col2.b - 0.5));
- else
- outcol.b= col1.b + fac*(2.0*(col2.b) - 1.0);
+ outcol = col1 + fac*(2.0*(col2 - vec4(0.5)));
}
void valtorgb(float fac, sampler2D colormap, out vec4 outcol, out float outalpha)
@@ -722,6 +731,16 @@ void invert(float fac, vec4 col, out vec4 outcol)
outcol.w = col.w;
}
+void clamp_vec3(vec3 vec, vec3 min, vec3 max, out vec3 out_vec)
+{
+ out_vec = clamp(vec, min, max);
+}
+
+void clamp_val(float value, float min, float max, out float out_value)
+{
+ out_value = clamp(value, min, max);
+}
+
void hue_sat(float hue, float sat, float value, float fac, vec4 col, out vec4 outcol)
{
vec4 hsv;
@@ -1507,9 +1526,9 @@ void mtex_nspace_world(mat4 viewmat, vec3 texnormal, out vec3 outnormal)
outnormal = normalize((viewmat*vec4(texnormal, 0.0)).xyz);
}
-void mtex_nspace_object(mat4 viewmat, mat4 obmat, vec3 texnormal, out vec3 outnormal)
+void mtex_nspace_object(vec3 texnormal, out vec3 outnormal)
{
- outnormal = normalize((viewmat*(obmat*vec4(texnormal, 0.0))).xyz);
+ outnormal = normalize(gl_NormalMatrix * texnormal);
}
void mtex_blend_normal(float norfac, vec3 normal, vec3 newnormal, out vec3 outnormal)
@@ -1925,6 +1944,17 @@ void shade_add_spec(float t, vec3 lampcol, vec3 speccol, out vec3 outcol)
outcol = t*lampcol*speccol;
}
+void alpha_spec_correction(vec3 spec, float spectra, float alpha, out float outalpha)
+{
+ if (spectra > 0.0) {
+ float t = clamp(max(max(spec.r, spec.g), spec.b) * spectra, 0.0, 1.0);
+ outalpha = (1.0 - t) * alpha + t;
+ }
+ else {
+ outalpha = alpha;
+ }
+}
+
void shade_add(vec4 col1, vec4 col2, out vec4 outcol)
{
outcol = col1 + col2;
@@ -1960,6 +1990,11 @@ void shade_mul_value(float fac, vec4 col, out vec4 outcol)
outcol = col*fac;
}
+void shade_mul_value_v3(float fac, vec3 col, out vec3 outcol)
+{
+ outcol = col*fac;
+}
+
void shade_obcolor(vec4 col, vec4 obcol, out vec4 outcol)
{
outcol = vec4(col.rgb*obcol.rgb, col.a);
@@ -2077,18 +2112,23 @@ void shade_exposure_correct(vec3 col, float linfac, float logfac, out vec3 outco
outcol = linfac*(1.0 - exp(col*logfac));
}
-void shade_mist_factor(vec3 co, float miststa, float mistdist, float misttype, float misi, out float outfac)
+void shade_mist_factor(vec3 co, float enable, float miststa, float mistdist, float misttype, float misi, out float outfac)
{
- float fac, zcor;
+ if(enable == 1.0) {
+ float fac, zcor;
- zcor = (gl_ProjectionMatrix[3][3] == 0.0)? length(co): -co[2];
-
- fac = clamp((zcor-miststa)/mistdist, 0.0, 1.0);
- if(misttype == 0.0) fac *= fac;
- else if(misttype == 1.0);
- else fac = sqrt(fac);
+ zcor = (gl_ProjectionMatrix[3][3] == 0.0)? length(co): -co[2];
+
+ fac = clamp((zcor - miststa) / mistdist, 0.0, 1.0);
+ if(misttype == 0.0) fac *= fac;
+ else if(misttype == 1.0);
+ else fac = sqrt(fac);
- outfac = 1.0 - (1.0-fac)*(1.0-misi);
+ outfac = 1.0 - (1.0 - fac) * (1.0 - misi);
+ }
+ else {
+ outfac = 0.0;
+ }
}
void shade_world_mix(vec3 hor, vec4 col, out vec4 outcol)
@@ -2223,6 +2263,16 @@ void node_bsdf_hair(vec4 color, float offset, float roughnessu, float roughnessv
result = color;
}
+void node_bsdf_refraction(vec4 color, float roughness, float ior, vec3 N, out vec4 result)
+{
+ node_bsdf_diffuse(color, 0.0, N, result);
+}
+
+void node_ambient_occlusion(vec4 color, out vec4 result)
+{
+ result = color;
+}
+
/* emission */
void node_emission(vec4 color, float strength, vec3 N, out vec4 result)
@@ -2230,6 +2280,22 @@ void node_emission(vec4 color, float strength, vec3 N, out vec4 result)
result = color*strength;
}
+/* background */
+
+void background_transform_to_world(vec3 viewvec, out vec3 worldvec)
+{
+ vec4 v = (gl_ProjectionMatrix[3][3] == 0.0) ? vec4(viewvec, 1.0) : vec4(0.0, 0.0, 1.0, 1.0);
+ vec4 co_homogenous = (gl_ProjectionMatrixInverse * v);
+
+ vec4 co = vec4(co_homogenous.xyz / co_homogenous.w, 0.0);
+ worldvec = (gl_ModelViewMatrixInverse * co).xyz;
+}
+
+void node_background(vec4 color, float strength, vec3 N, out vec4 result)
+{
+ result = color*strength;
+}
+
/* closures */
void node_mix_shader(float fac, vec4 shader1, vec4 shader2, out vec4 shader)
@@ -2259,10 +2325,12 @@ void node_layer_weight(float blend, vec3 N, vec3 I, out float fresnel, out float
{
/* fresnel */
float eta = max(1.0 - blend, 0.00001);
- fresnel = fresnel_dielectric(normalize(I), N, (gl_FrontFacing)? 1.0/eta : eta );
+ vec3 I_view = (gl_ProjectionMatrix[3][3] == 0.0)? normalize(I): vec3(0.0, 0.0, -1.0);
+
+ fresnel = fresnel_dielectric(I_view, N, (gl_FrontFacing)? 1.0/eta : eta );
/* facing */
- facing = abs(dot(normalize(I), N));
+ facing = abs(dot(I_view, N));
if(blend != 0.5) {
blend = clamp(blend, 0.0, 0.99999);
blend = (blend < 0.5)? 2.0*blend: 0.5/(1.0 - blend);
@@ -2302,7 +2370,7 @@ void node_uvmap(vec3 attr_uv, out vec3 outvec)
void node_geometry(vec3 I, vec3 N, mat4 toworld,
out vec3 position, out vec3 normal, out vec3 tangent,
out vec3 true_normal, out vec3 incoming, out vec3 parametric,
- out float backfacing)
+ out float backfacing, out float pointiness)
{
position = (toworld*vec4(I, 1.0)).xyz;
normal = (toworld*vec4(N, 0.0)).xyz;
@@ -2315,20 +2383,21 @@ void node_geometry(vec3 I, vec3 N, mat4 toworld,
parametric = vec3(0.0);
backfacing = (gl_FrontFacing)? 0.0: 1.0;
+ pointiness = 0.0;
}
-void node_tex_coord(vec3 I, vec3 N, mat4 viewinvmat, mat4 obinvmat,
+void node_tex_coord(vec3 I, vec3 N, mat4 viewinvmat, mat4 obinvmat, vec4 camerafac,
vec3 attr_orco, vec3 attr_uv,
out vec3 generated, out vec3 normal, out vec3 uv, out vec3 object,
out vec3 camera, out vec3 window, out vec3 reflection)
{
- generated = mtex_2d_mapping(attr_orco);
+ generated = attr_orco * 0.5 + vec3(0.5);
normal = normalize((obinvmat*(viewinvmat*vec4(N, 0.0))).xyz);
uv = attr_uv;
object = (obinvmat*(viewinvmat*vec4(I, 1.0))).xyz;
- camera = I;
+ camera = vec3(I.xy, -I.z);
vec4 projvec = gl_ProjectionMatrix * vec4(I, 1.0);
- window = mtex_2d_mapping(projvec.xyz/projvec.w);
+ window = vec3(mtex_2d_mapping(projvec.xyz/projvec.w).xy * camerafac.xy + camerafac.zw, 0.0);
vec3 shade_I;
shade_view(I, shade_I);
@@ -2336,6 +2405,32 @@ void node_tex_coord(vec3 I, vec3 N, mat4 viewinvmat, mat4 obinvmat,
reflection = (viewinvmat*vec4(view_reflection, 0.0)).xyz;
}
+void node_tex_coord_background(vec3 I, vec3 N, mat4 viewinvmat, mat4 obinvmat, vec4 camerafac,
+ vec3 attr_orco, vec3 attr_uv,
+ out vec3 generated, out vec3 normal, out vec3 uv, out vec3 object,
+ out vec3 camera, out vec3 window, out vec3 reflection)
+{
+ vec4 v = (gl_ProjectionMatrix[3][3] == 0.0) ? vec4(I, 1.0) : vec4(0.0, 0.0, 1.0, 1.0);
+ vec4 co_homogenous = (gl_ProjectionMatrixInverse * v);
+
+ vec4 co = vec4(co_homogenous.xyz / co_homogenous.w, 0.0);
+
+ co = normalize(co);
+ vec3 coords = (gl_ModelViewMatrixInverse * co).xyz;
+
+ generated = coords;
+ normal = -coords;
+ uv = vec3(attr_uv.xy, 0.0);
+ object = coords;
+
+ camera = vec3(co.xy, -co.z);
+ window = (gl_ProjectionMatrix[3][3] == 0.0) ?
+ vec3(mtex_2d_mapping(I).xy * camerafac.xy + camerafac.zw, 0.0) :
+ vec3(vec2(0.5) * camerafac.xy + camerafac.zw, 0.0);
+
+ reflection = -coords;
+}
+
/* textures */
void node_tex_gradient(vec3 co, out vec4 color, out float fac)
@@ -2362,17 +2457,34 @@ void node_tex_clouds(vec3 co, float size, out vec4 color, out float fac)
fac = 1.0;
}
-void node_tex_environment(vec3 co, sampler2D ima, out vec4 color)
+void node_tex_environment_equirectangular(vec3 co, sampler2D ima, out vec4 color)
+{
+ vec3 nco = normalize(co);
+ float u = -atan(nco.y, nco.x)/(2.0*M_PI) + 0.5;
+ float v = atan(nco.z, hypot(nco.x, nco.y))/M_PI + 0.5;
+
+ color = texture2D(ima, vec2(u, v));
+}
+
+void node_tex_environment_mirror_ball(vec3 co, sampler2D ima, out vec4 color)
{
- float u = (atan(co.y, co.x) + M_PI)/(2.0*M_PI);
- float v = atan(co.z, hypot(co.x, co.y))/M_PI + 0.5;
+ vec3 nco = normalize(co);
+
+ nco.y -= 1.0;
+
+ float div = 2.0*sqrt(max(-0.5*nco.y, 0.0));
+ if(div > 0.0)
+ nco /= div;
+
+ float u = 0.5*(nco.x + 1.0);
+ float v = 0.5*(nco.z + 1.0);
color = texture2D(ima, vec2(u, v));
}
void node_tex_environment_empty(vec3 co, out vec4 color)
{
- color = vec4(0.0);
+ color = vec4(1.0, 0.0, 1.0, 1.0);
}
void node_tex_image(vec3 co, sampler2D ima, out vec4 color, out float alpha)
@@ -2480,6 +2592,11 @@ void node_output_material(vec4 surface, vec4 volume, float displacement, out vec
result = surface;
}
+void node_output_world(vec4 surface, vec4 volume, out vec4 result)
+{
+ result = surface;
+}
+
/* ********************** matcap style render ******************** */
void material_preview_matcap(vec4 color, sampler2D ima, vec4 N, vec4 mask, out vec4 result)
@@ -2487,6 +2604,7 @@ void material_preview_matcap(vec4 color, sampler2D ima, vec4 N, vec4 mask, out v
vec3 normal;
vec2 tex;
+#ifndef USE_OPENSUBDIV
/* remap to 0.0 - 1.0 range. This is done because OpenGL 2.0 clamps colors
* between shader stages and we want the full range of the normal */
normal = vec3(2.0, 2.0, 2.0) * vec3(N.x, N.y, N.z) - vec3(1.0, 1.0, 1.0);
@@ -2494,6 +2612,10 @@ void material_preview_matcap(vec4 color, sampler2D ima, vec4 N, vec4 mask, out v
normal.z = 0.0;
}
normal = normalize(normal);
+#else
+ normal = inpt.v.normal;
+ mask = vec4(1.0, 1.0, 1.0, 1.0);
+#endif
tex.x = 0.5 + 0.49 * normal.x;
tex.y = 0.5 + 0.49 * normal.y;
diff --git a/source/blender/gpu/shaders/gpu_shader_sep_gaussian_blur_frag.glsl b/source/blender/gpu/shaders/gpu_shader_sep_gaussian_blur_frag.glsl
index 978b6db1b9a..5f406c959f1 100644
--- a/source/blender/gpu/shaders/gpu_shader_sep_gaussian_blur_frag.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_sep_gaussian_blur_frag.glsl
@@ -10,7 +10,7 @@ void main()
color += texture2D( textureSource, gl_TexCoord[0].st + vec2(0.0, 0.0)) * 0.3125;
color += texture2D( textureSource, gl_TexCoord[0].st + vec2(1.0 * ScaleU.x, 1.0 * ScaleU.y ) ) * 0.234375;
color += texture2D( textureSource, gl_TexCoord[0].st + vec2(2.0 * ScaleU.x, 2.0 * ScaleU.y ) ) * 0.09375;
- color += texture2D( textureSource, gl_TexCoord[0].st + vec2(3.0 * ScaleU.x, -3.0 * ScaleU.y ) ) * 0.015625;
+ color += texture2D( textureSource, gl_TexCoord[0].st + vec2(3.0 * ScaleU.x, 3.0 * ScaleU.y ) ) * 0.015625;
gl_FragColor = color;
}
diff --git a/source/blender/gpu/shaders/gpu_shader_vertex.glsl b/source/blender/gpu/shaders/gpu_shader_vertex.glsl
index b5d8dcc0f35..7e332706695 100644
--- a/source/blender/gpu/shaders/gpu_shader_vertex.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_vertex.glsl
@@ -1,3 +1,11 @@
+#ifdef USE_OPENSUBDIV
+in vec3 normal;
+in vec4 position;
+
+out block {
+ VertexData v;
+} outpt;
+#endif
varying vec3 varposition;
varying vec3 varnormal;
@@ -8,10 +16,15 @@ varying float gl_ClipDistance[6];
void main()
{
- vec4 co = gl_ModelViewMatrix * gl_Vertex;
+#ifndef USE_OPENSUBDIV
+ vec4 position = gl_Vertex;
+ vec3 normal = gl_Normal;
+#endif
+
+ vec4 co = gl_ModelViewMatrix * position;
varposition = co.xyz;
- varnormal = normalize(gl_NormalMatrix * gl_Normal);
+ varnormal = normalize(gl_NormalMatrix * normal);
gl_Position = gl_ProjectionMatrix * co;
#ifdef CLIP_WORKAROUND
@@ -24,3 +37,7 @@ void main()
gl_ClipVertex = co;
#endif
+#ifdef USE_OPENSUBDIV
+ outpt.v.position = co;
+ outpt.v.normal = varnormal;
+#endif
diff --git a/source/blender/gpu/shaders/gpu_shader_vertex_world.glsl b/source/blender/gpu/shaders/gpu_shader_vertex_world.glsl
new file mode 100644
index 00000000000..9dbcaeb7a32
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_vertex_world.glsl
@@ -0,0 +1,13 @@
+
+varying vec3 varposition;
+varying vec3 varnormal;
+
+void main()
+{
+ /* position does not need to be transformed, we already have it */
+ gl_Position = gl_Vertex;
+
+ varposition = gl_Vertex.xyz;
+
+ varnormal = normalize(-varposition);
+
diff --git a/source/blender/ikplugin/BIK_api.h b/source/blender/ikplugin/BIK_api.h
index 95b1dafd129..177be074897 100644
--- a/source/blender/ikplugin/BIK_api.h
+++ b/source/blender/ikplugin/BIK_api.h
@@ -41,7 +41,6 @@ extern "C" {
struct Object;
struct bPoseChannel;
struct bPose;
-struct bArmature;
struct Scene;
struct bConstraint;
diff --git a/source/blender/ikplugin/CMakeLists.txt b/source/blender/ikplugin/CMakeLists.txt
index 0a0e0e664b4..8991e113410 100644
--- a/source/blender/ikplugin/CMakeLists.txt
+++ b/source/blender/ikplugin/CMakeLists.txt
@@ -23,6 +23,8 @@
#
# ***** END GPL LICENSE BLOCK *****
+remove_extra_strict_flags()
+
set(INC
.
../blenkernel
@@ -59,7 +61,7 @@ if(WITH_IK_ITASC)
../../../intern/itasc
)
list(APPEND INC_SYS
- ../../../extern/Eigen3
+ ${EIGEN3_INCLUDE_DIRS}
)
list(APPEND SRC
intern/itasc_plugin.cpp
diff --git a/source/blender/ikplugin/intern/ikplugin_api.c b/source/blender/ikplugin/intern/ikplugin_api.c
index 2ca50afb0f2..0f81fb34a63 100644
--- a/source/blender/ikplugin/intern/ikplugin_api.c
+++ b/source/blender/ikplugin/intern/ikplugin_api.c
@@ -30,19 +30,12 @@
* \ingroup ikplugin
*/
-
-
#include "BIK_api.h"
#include "BLI_blenlib.h"
-#include "BLI_math.h"
-
-#include "BKE_armature.h"
#include "DNA_object_types.h"
#include "DNA_action_types.h"
#include "DNA_scene_types.h"
-#include "DNA_constraint_types.h"
-#include "DNA_armature_types.h"
#include "ikplugin_api.h"
diff --git a/source/blender/ikplugin/intern/ikplugin_api.h b/source/blender/ikplugin/intern/ikplugin_api.h
index 53d9da8e614..cd32bf26242 100644
--- a/source/blender/ikplugin/intern/ikplugin_api.h
+++ b/source/blender/ikplugin/intern/ikplugin_api.h
@@ -40,7 +40,6 @@ extern "C" {
struct Object;
struct bPoseChannel;
-struct bArmature;
struct Scene;
diff --git a/source/blender/ikplugin/intern/iksolver_plugin.c b/source/blender/ikplugin/intern/iksolver_plugin.c
index cd09b56b262..5da06ed91ec 100644
--- a/source/blender/ikplugin/intern/iksolver_plugin.c
+++ b/source/blender/ikplugin/intern/iksolver_plugin.c
@@ -307,8 +307,7 @@ static void execute_posetree(struct Scene *scene, Object *ob, PoseTree *tree)
/* compute rest basis and its inverse */
copy_m3_m3(rest_basis, bone->bone_mat);
- copy_m3_m3(irest_basis, bone->bone_mat);
- transpose_m3(irest_basis);
+ transpose_m3_m3(irest_basis, bone->bone_mat);
/* compute basis with rest_basis removed */
invert_m3_m3(iR_parmat, R_parmat);
diff --git a/source/blender/ikplugin/intern/itasc_plugin.cpp b/source/blender/ikplugin/intern/itasc_plugin.cpp
index afff97a8409..d4814a4e3a2 100644
--- a/source/blender/ikplugin/intern/itasc_plugin.cpp
+++ b/source/blender/ikplugin/intern/itasc_plugin.cpp
@@ -89,8 +89,7 @@ struct IK_Target;
typedef void (*ErrorCallback)(const iTaSC::ConstraintValues *values, unsigned int nvalues, IK_Target *iktarget);
// one structure for each target in the scene
-struct IK_Target
-{
+struct IK_Target {
struct Scene *blscene;
iTaSC::MovingFrame* target;
iTaSC::ConstraintSet* constraint;
diff --git a/source/blender/imbuf/CMakeLists.txt b/source/blender/imbuf/CMakeLists.txt
index e8977913948..295a48dc245 100644
--- a/source/blender/imbuf/CMakeLists.txt
+++ b/source/blender/imbuf/CMakeLists.txt
@@ -62,9 +62,11 @@ set(SRC
intern/rectop.c
intern/rotate.c
intern/scaling.c
+ intern/stereoimbuf.c
intern/targa.c
intern/thumbs.c
intern/thumbs_blend.c
+ intern/thumbs_font.c
intern/util.c
intern/writeimage.c
@@ -118,7 +120,7 @@ if(WITH_IMAGE_OPENJPEG)
intern/jp2.c
)
- add_definitions(-DWITH_OPENJPEG)
+ add_definitions(-DWITH_OPENJPEG ${OPENJPEG_DEFINES})
endif()
if(WITH_IMAGE_REDCODE)
diff --git a/source/blender/imbuf/IMB_colormanagement.h b/source/blender/imbuf/IMB_colormanagement.h
index 262e87bedf5..59df8334099 100644
--- a/source/blender/imbuf/IMB_colormanagement.h
+++ b/source/blender/imbuf/IMB_colormanagement.h
@@ -47,10 +47,6 @@ struct ColormanageProcessor;
struct EnumPropertyItem;
struct ImBuf;
struct Main;
-struct rcti;
-struct PartialBufferUpdateContext;
-struct wmWindow;
-struct Scene;
struct ImageFormatData;
struct ColorSpace;
@@ -71,6 +67,9 @@ void IMB_colormanagement_assign_rect_colorspace(struct ImBuf *ibuf, const char *
const char *IMB_colormanagement_get_float_colorspace(struct ImBuf *ibuf);
const char *IMB_colormanagement_get_rect_colorspace(struct ImBuf *ibuf);
+float IMB_colormanagement_get_luminance(const float rgb[3]);
+unsigned char IMB_colormanagement_get_luminance_byte(const unsigned char[3]);
+
/* ** Color space transformation functions ** */
void IMB_colormanagement_transform(float *buffer, int width, int height, int channels,
const char *from_colorspace, const char *to_colorspace, bool predivide);
diff --git a/source/blender/imbuf/IMB_imbuf.h b/source/blender/imbuf/IMB_imbuf.h
index ce6a7eb1c47..77e860191b2 100644
--- a/source/blender/imbuf/IMB_imbuf.h
+++ b/source/blender/imbuf/IMB_imbuf.h
@@ -38,21 +38,21 @@
* \page IMB Imbuf module external interface
*
*
- * \section about About the IMB module
+ * \section imb_about About the IMB module
*
* External interface of the IMage Buffer module. This module offers
* import/export of several graphical file formats. It offers the
* ImBuf type as a common structure to refer to different graphical
* file formats, and to enable a uniform way of handling them.
*
- * \section issues Known issues with IMB
+ * \section imb_issues Known issues with IMB
*
* - imbuf is written in C.
* - Endianness issues are dealt with internally.
* - File I/O must be done externally. The module uses FILE*'s to
* direct input/output.
*
- * \section dependencies Dependencies
+ * \section imb_dependencies Dependencies
*
* IMB needs:
* - \ref DNA module
@@ -86,6 +86,14 @@ struct anim;
struct ColorManagedDisplay;
+struct GSet;
+/**
+ *
+ * \attention defined in DNA_scene_types.h
+ */
+struct ImageFormatData;
+struct Stereo3dFormat;
+
/**
*
* \attention Defined in allocimbuf.c
@@ -125,6 +133,13 @@ struct ImBuf *IMB_allocImBuf(unsigned int x, unsigned int y,
unsigned char d, unsigned int flags);
/**
+ * Create a copy of a pixel buffer and wrap it to a new ImBuf
+ * \attention Defined in allocimbuf.c
+ */
+struct ImBuf *IMB_allocFromBuffer(const unsigned int *rect, const float *rectf,
+ unsigned int w, unsigned int h);
+
+/**
*
* Increase reference count to imbuf
* (to delete an imbuf you have to call freeImBuf as many times as it
@@ -212,7 +227,7 @@ typedef enum IMB_Timecode_Type {
* and is a sane default) */
IMB_TC_FREE_RUN = 2, /* use global timestamp written by recording
- * device (prosumer camcorders e.g. can do that) */
+ * device (prosumer camcorders e.g. can do that) */
IMB_TC_INTERPOLATED_REC_DATE_FREE_RUN = 4, /* interpolate a global timestamp using the
* record date and time written by recording
* device (*every* consumer camcorder can do
@@ -232,15 +247,19 @@ typedef enum IMB_Proxy_Size {
/* defaults to BL_proxy within the directory of the animation */
void IMB_anim_set_index_dir(struct anim *anim, const char *dir);
+void IMB_anim_get_fname(struct anim *anim, char *file, int size);
int IMB_anim_index_get_frame_index(struct anim *anim, IMB_Timecode_Type tc,
int position);
+IMB_Proxy_Size IMB_anim_proxy_get_existing(struct anim *anim);
+
struct IndexBuildContext;
/* prepare context for proxies/imecodes builder */
struct IndexBuildContext *IMB_anim_index_rebuild_context(struct anim *anim, IMB_Timecode_Type tcs_in_use,
- IMB_Proxy_Size proxy_sizes_in_use, int quality);
+ IMB_Proxy_Size proxy_sizes_in_use, int quality,
+ const bool overwite, struct GSet *file_list);
/* will rebuild all used indices and proxies at once */
void IMB_anim_index_rebuild(struct IndexBuildContext *context,
@@ -260,17 +279,17 @@ int IMB_anim_get_duration(struct anim *anim, IMB_Timecode_Type tc);
* and frs_sec and frs_sec_base untouched if none available!)
*/
bool IMB_anim_get_fps(struct anim *anim,
- short *frs_sec, float *frs_sec_base);
+ short *frs_sec, float *frs_sec_base, bool no_av_base);
/**
*
* \attention Defined in anim_movie.c
*/
struct anim *IMB_open_anim(const char *name, int ib_flags, int streamindex, char colorspace[IM_MAX_SPACE]);
+void IMB_suffix_anim(struct anim *anim, const char *suffix);
void IMB_close_anim(struct anim *anim);
void IMB_close_anim_proxies(struct anim *anim);
-
/**
*
* \attention Defined in anim_movie.c
@@ -365,6 +384,7 @@ void IMB_scaleImBuf_threaded(struct ImBuf *ibuf, unsigned int newx, unsigned int
* \attention Defined in writeimage.c
*/
short IMB_saveiff(struct ImBuf *ibuf, const char *filepath, int flags);
+struct ImBuf *IMB_prepare_write_ImBuf(const bool isfloat, struct ImBuf *ibuf);
/**
*
@@ -387,6 +407,12 @@ int imb_get_anim_type(const char *name);
/**
*
+ * \attention Defined in util.c
+ */
+bool IMB_isfloat(struct ImBuf *ibuf);
+
+/**
+ *
* \attention Defined in divers.c
*/
void IMB_de_interlace(struct ImBuf *ibuf);
@@ -441,6 +467,7 @@ void bilinear_interpolation(struct ImBuf *in, struct ImBuf *out, float u, float
void bicubic_interpolation_color(struct ImBuf *in, unsigned char col[4], float col_float[4], float u, float v);
void nearest_interpolation_color(struct ImBuf *in, unsigned char col[4], float col_float[4], float u, float v);
+void nearest_interpolation_color_wrap(struct ImBuf *in, unsigned char col[4], float col_float[4], float u, float v);
void bilinear_interpolation_color(struct ImBuf *in, unsigned char col[4], float col_float[4], float u, float v);
void bilinear_interpolation_color_wrap(struct ImBuf *in, unsigned char col[4], float col_float[4], float u, float v);
@@ -521,8 +548,21 @@ void buf_rectfill_area(unsigned char *rect, float *rectf, int width, int height,
const float col[4], struct ColorManagedDisplay *display,
int x1, int y1, int x2, int y2);
-/* defined in metadata.c */
+/**
+ *
+ * \attention Defined in metadata.c
+ */
+/** read the field from the image info into the field
+ * \param img - the ImBuf that contains the image data
+ * \param key - the key of the field
+ * \param value - the data in the field, first one found with key is returned,
+ * memory has to be allocated by user.
+ * \param len - length of value buffer allocated by user.
+ * \return - 1 (true) if ImageInfo present and value for the key found, 0 (false) otherwise
+ */
+bool IMB_metadata_get_field(struct ImBuf *img, const char *key, char *value, const size_t len);
bool IMB_metadata_change_field(struct ImBuf *img, const char *key, const char *field);
+void IMB_metadata_copy(struct ImBuf *dimb, struct ImBuf *simb);
/* exported for image tools in blender, to quickly allocate 32 bits rect */
bool imb_addrectImBuf(struct ImBuf *ibuf);
@@ -545,5 +585,27 @@ void IMB_processor_apply_threaded(int buffer_lines, int handle_size, void *init_
void IMB_ffmpeg_init(void);
const char *IMB_ffmpeg_last_error(void);
-#endif
+/**
+ *
+ * \attention defined in stereoimbuf.c
+ */
+void IMB_stereo3d_write_dimensions(
+ const char mode, const bool is_squeezed, const size_t width, const size_t height,
+ size_t *r_width, size_t *r_height);
+void IMB_stereo3d_read_dimensions(
+ const char mode, const bool is_squeezed, const size_t width, const size_t height,
+ size_t *r_width, size_t *r_height);
+int *IMB_stereo3d_from_rect(
+ struct ImageFormatData *im_format, const size_t x, const size_t y, const size_t channels,
+ int *rect_left, int *rect_right);
+float *IMB_stereo3d_from_rectf(
+ struct ImageFormatData *im_format, const size_t x, const size_t y, const size_t channels,
+ float *rectf_left, float *rectf_right);
+struct ImBuf *IMB_stereo3d_ImBuf(
+ struct ImageFormatData *im_format,
+ struct ImBuf *ibuf_left, struct ImBuf *ibuf_right);
+void IMB_ImBufFromStereo3d(
+ struct Stereo3dFormat *s3d, struct ImBuf *ibuf_stereo,
+ struct ImBuf **r_ibuf_left, struct ImBuf **r_ibuf_right);
+#endif
diff --git a/source/blender/imbuf/IMB_imbuf_types.h b/source/blender/imbuf/IMB_imbuf_types.h
index 44cb7f1211e..08ce9c0469b 100644
--- a/source/blender/imbuf/IMB_imbuf_types.h
+++ b/source/blender/imbuf/IMB_imbuf_types.h
@@ -47,10 +47,8 @@
* contains an Amiga-format file).
*/
-struct ImMetaData;
-
-#define IB_MIPMAP_LEVELS 20
-#define IB_FILENAME_SIZE 1024
+#define IMB_MIPMAP_LEVELS 20
+#define IMB_FILENAME_SIZE 1024
typedef struct DDSData {
unsigned int fourcc; /* DDS fourcc info */
@@ -67,6 +65,80 @@ typedef struct DDSData {
* Also; add new variables to the end to save pain!
*
*/
+
+/* ibuf->ftype flag, main image types */
+enum eImbTypes {
+ IMB_FTYPE_PNG = 1,
+ IMB_FTYPE_TGA,
+ IMB_FTYPE_JPG,
+ IMB_FTYPE_BMP,
+ IMB_FTYPE_OPENEXR,
+ IMB_FTYPE_IMAGIC,
+#ifdef WITH_OPENIMAGEIO
+ IMB_FTYPE_PSD,
+#endif
+#ifdef WITH_OPENJPEG
+ IMB_FTYPE_JP2,
+#endif
+#ifdef WITH_HDR
+ IMB_FTYPE_RADHDR,
+#endif
+#ifdef WITH_TIFF
+ IMB_FTYPE_TIF,
+#endif
+#ifdef WITH_CINEON
+ IMB_FTYPE_CINEON,
+ IMB_FTYPE_DPX,
+#endif
+
+#ifdef WITH_DDS
+ IMB_FTYPE_DDS,
+#endif
+};
+
+/* ibuf->foptions flag, type specific options.
+ * Some formats include compression rations on some bits */
+
+#define OPENEXR_HALF (1 << 8 )
+/* careful changing this, it's used in DNA as well */
+#define OPENEXR_COMPRESS (15)
+
+#ifdef WITH_CINEON
+#define CINEON_LOG (1 << 8)
+#define CINEON_16BIT (1 << 7)
+#define CINEON_12BIT (1 << 6)
+#define CINEON_10BIT (1 << 5)
+#endif
+
+#ifdef WITH_OPENJPEG
+#define JP2_12BIT (1 << 9)
+#define JP2_16BIT (1 << 8)
+#define JP2_YCC (1 << 7)
+#define JP2_CINE (1 << 6)
+#define JP2_CINE_48FPS (1 << 5)
+#define JP2_JP2 (1 << 4)
+#define JP2_J2K (1 << 3)
+#endif
+
+#define PNG_16BIT (1 << 10)
+
+#define RAWTGA 1
+
+#define JPG_STD 0
+#define JPG_VID 1
+#define JPG_JST 2
+#define JPG_MAX 3
+#define JPG_MSK 0x03
+
+#ifdef WITH_TIFF
+#define TIF_16BIT (1 << 8 )
+#endif
+
+typedef struct ImbFormatOptions {
+ short flag;
+ char quality; /* quality serves dual purpose as quality number for jpeg or compression amount for png */
+} ImbFormatOptions;
+
typedef struct ImBuf {
struct ImBuf *next, *prev; /**< allow lists of ImBufs, for caches or flipbooks */
@@ -105,19 +177,20 @@ typedef struct ImBuf {
float dither; /* random dither value, for conversion from float -> byte rect */
/* mipmapping */
- struct ImBuf *mipmap[IB_MIPMAP_LEVELS]; /* MipMap levels, a series of halved images */
+ struct ImBuf *mipmap[IMB_MIPMAP_LEVELS]; /* MipMap levels, a series of halved images */
int miptot, miplevel;
/* externally used data */
int index; /* reference index for ImBuf lists */
int userflags; /* used to set imbuf to dirty and other stuff */
- struct ImMetaData *metadata; /* image metadata */
- void *userdata; /* temporary storage, only used by baking at the moment */
+ struct IDProperty *metadata; /* image metadata */
+ void *userdata; /* temporary storage */
/* file information */
- int ftype; /* file type we are going to save as */
- char name[IB_FILENAME_SIZE]; /* filename associated with this image */
- char cachename[IB_FILENAME_SIZE]; /* full filename used for reading from cache */
+ enum eImbTypes ftype; /* file type we are going to save as */
+ ImbFormatOptions foptions; /* file format specific flags */
+ char name[IMB_FILENAME_SIZE]; /* filename associated with this image */
+ char cachename[IMB_FILENAME_SIZE]; /* full filename used for reading from cache */
/* memory cache limiter */
struct MEM_CacheLimiterHandle_s *c_handle; /* handle for cache limiter */
@@ -174,73 +247,8 @@ typedef struct ImBuf {
#define IB_alphamode_premul (1 << 12) /* indicates whether image on disk have premul alpha */
#define IB_alphamode_detect (1 << 13) /* if this flag is set, alpha mode would be guessed from file */
#define IB_ignore_alpha (1 << 14) /* ignore alpha on load and substitude it with 1.0f */
-
-/*
- * The bit flag is stored in the ImBuf.ftype variable.
- * Note that the lower 11 bits is used for storing custom flags
- */
-#define IB_CUSTOM_FLAGS_MASK 0x7ff
-
-#ifdef WITH_OPENIMAGEIO
-#define PSD (1 << 31)
-#endif
-
-#define PNG (1 << 30)
-#define TGA (1 << 28)
-#define JPG (1 << 27)
-#define BMP (1 << 26)
-
-#ifdef WITH_QUICKTIME
-#define QUICKTIME (1 << 25)
-#endif
-
-#ifdef WITH_HDR
-#define RADHDR (1 << 24)
-#endif
-#ifdef WITH_TIFF
-#define TIF (1 << 23)
-#define TIF_16BIT (1 << 8 )
-#endif
-
-#define OPENEXR (1 << 22)
-#define OPENEXR_HALF (1 << 8 )
-#define OPENEXR_COMPRESS (7)
-
-#ifdef WITH_CINEON
-#define CINEON (1 << 21)
-#define DPX (1 << 20)
-#define CINEON_LOG (1 << 8)
-#define CINEON_16BIT (1 << 7)
-#define CINEON_12BIT (1 << 6)
-#define CINEON_10BIT (1 << 5)
-#endif
-
-#ifdef WITH_DDS
-#define DDS (1 << 19)
-#endif
-
-#ifdef WITH_OPENJPEG
-#define JP2 (1 << 18)
-#define JP2_12BIT (1 << 17)
-#define JP2_16BIT (1 << 16)
-#define JP2_YCC (1 << 15)
-#define JP2_CINE (1 << 14)
-#define JP2_CINE_48FPS (1 << 13)
-#define JP2_JP2 (1 << 12)
-#define JP2_J2K (1 << 11)
-#endif
-
-#define PNG_16BIT (1 << 10)
-
-#define RAWTGA (TGA | 1)
-
-#define JPG_STD (JPG | (0 << 8))
-#define JPG_VID (JPG | (1 << 8))
-#define JPG_JST (JPG | (2 << 8))
-#define JPG_MAX (JPG | (3 << 8))
-#define JPG_MSK (0xffffff00)
-
-#define IMAGIC 0732
+#define IB_thumbnail (1 << 15)
+#define IB_multiview (1 << 16)
/**
* \name Imbuf preset profile tags
diff --git a/source/blender/imbuf/IMB_thumbs.h b/source/blender/imbuf/IMB_thumbs.h
index 9fc075e4e8b..aaa5eea04ad 100644
--- a/source/blender/imbuf/IMB_thumbs.h
+++ b/source/blender/imbuf/IMB_thumbs.h
@@ -54,13 +54,19 @@ typedef enum ThumbSize {
typedef enum ThumbSource {
THB_SOURCE_IMAGE,
THB_SOURCE_MOVIE,
- THB_SOURCE_BLEND
+ THB_SOURCE_BLEND,
+ THB_SOURCE_FONT,
} ThumbSource;
/* don't generate thumbs for images bigger then this (100mb) */
#define THUMB_SIZE_MAX (100 * 1024 * 1024)
-// IB_metadata
+#define PREVIEW_RENDER_DEFAULT_HEIGHT 128
+
+/* Note this can also be used as versionning system,
+ * to force refreshing all thumbnails if e.g. we change some thumb generating code or so.
+ * Only used by fonts so far. */
+#define THUMB_DEFAULT_HASH "00000000000000000000000000000000"
/* create thumbnail for file and returns new imbuf for thumbnail */
ImBuf *IMB_thumb_create(const char *path, ThumbSize size, ThumbSource source, ImBuf *ibuf);
@@ -78,8 +84,18 @@ ImBuf *IMB_thumb_manage(const char *path, ThumbSize size, ThumbSource source);
void IMB_thumb_makedirs(void);
/* special function for loading a thumbnail embedded into a blend file */
-ImBuf *IMB_loadblend_thumb(const char *path);
-void IMB_overlayblend_thumb(unsigned int *thumb, int width, int height, float aspect);
+ImBuf *IMB_thumb_load_blend(const char *blen_path, const char *blen_group, const char *blen_id);
+void IMB_thumb_overlay_blend(unsigned int *thumb, int width, int height, float aspect);
+
+/* special function for previewing fonts */
+ImBuf *IMB_thumb_load_font(const char *filename, unsigned int x, unsigned int y);
+bool IMB_thumb_load_font_get_hash(char *r_hash);
+
+/* Threading */
+void IMB_thumb_locks_acquire(void);
+void IMB_thumb_locks_release(void);
+void IMB_thumb_path_lock(const char *path);
+void IMB_thumb_path_unlock(const char *path);
#ifdef __cplusplus
}
diff --git a/source/blender/imbuf/intern/IMB_anim.h b/source/blender/imbuf/intern/IMB_anim.h
index ed349e8f7eb..690ec813407 100644
--- a/source/blender/imbuf/intern/IMB_anim.h
+++ b/source/blender/imbuf/intern/IMB_anim.h
@@ -79,11 +79,7 @@
#endif
#ifdef WITH_REDCODE
-# ifdef _WIN32 /* on windows we use the one in extern instead */
-# include "libredcode/format.h"
-# else
-# include "libredcode/format.h"
-# endif
+# include "libredcode/format.h"
#endif
#include "IMB_imbuf_types.h"
@@ -194,6 +190,7 @@ struct anim {
struct anim_index *curr_idx[IMB_TC_MAX_SLOT];
char colorspace[64];
+ char suffix[64]; /* MAX_NAME - multiview */
};
#endif
diff --git a/source/blender/imbuf/intern/IMB_filetype.h b/source/blender/imbuf/intern/IMB_filetype.h
index 9327c15c415..2bd7cbcf6eb 100644
--- a/source/blender/imbuf/intern/IMB_filetype.h
+++ b/source/blender/imbuf/intern/IMB_filetype.h
@@ -38,21 +38,21 @@ typedef struct ImFileType {
void (*init)(void);
void (*exit)(void);
- int (*is_a)(unsigned char *buf);
+ int (*is_a)(const unsigned char *buf);
int (*is_a_filepath)(const char *name);
- int (*ftype)(struct ImFileType *type, struct ImBuf *ibuf);
- struct ImBuf *(*load)(unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE]);
+ int (*ftype)(const struct ImFileType *type, struct ImBuf *ibuf);
+ struct ImBuf *(*load)(const unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE]);
struct ImBuf *(*load_filepath)(const char *name, int flags, char colorspace[IM_MAX_SPACE]);
int (*save)(struct ImBuf *ibuf, const char *name, int flags);
- void (*load_tile)(struct ImBuf *ibuf, unsigned char *mem, size_t size, int tx, int ty, unsigned int *rect);
+ void (*load_tile)(struct ImBuf *ibuf, const unsigned char *mem, size_t size, int tx, int ty, unsigned int *rect);
int flag;
int filetype;
int default_save_role;
} ImFileType;
-extern ImFileType IMB_FILE_TYPES[];
-extern ImFileType *IMB_FILE_TYPES_LAST;
+extern const ImFileType IMB_FILE_TYPES[];
+extern const ImFileType *IMB_FILE_TYPES_LAST;
void imb_filetypes_init(void);
void imb_filetypes_exit(void);
@@ -66,58 +66,55 @@ void imb_tile_cache_tile_free(struct ImBuf *ibuf, int tx, int ty);
/* Type Specific Functions */
/* png */
-int imb_is_a_png(unsigned char *buf);
-struct ImBuf *imb_loadpng(unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE]);
+int imb_is_a_png(const unsigned char *buf);
+struct ImBuf *imb_loadpng(const unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE]);
int imb_savepng(struct ImBuf *ibuf, const char *name, int flags);
/* targa */
-int imb_is_a_targa(unsigned char *buf);
-struct ImBuf *imb_loadtarga(unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE]);
+int imb_is_a_targa(const unsigned char *buf);
+struct ImBuf *imb_loadtarga(const unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE]);
int imb_savetarga(struct ImBuf *ibuf, const char *name, int flags);
/* iris */
-int imb_is_a_iris(unsigned char *mem);
-struct ImBuf *imb_loadiris(unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE]);
+int imb_is_a_iris(const unsigned char *mem);
+struct ImBuf *imb_loadiris(const unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE]);
int imb_saveiris(struct ImBuf *ibuf, const char *name, int flags);
/* jp2 */
-int imb_is_a_jp2(unsigned char *buf);
-struct ImBuf *imb_jp2_decode(unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE]);
+int imb_is_a_jp2(const unsigned char *buf);
+struct ImBuf *imb_jp2_decode(const unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE]);
int imb_savejp2(struct ImBuf *ibuf, const char *name, int flags);
/* jpeg */
-int imb_is_a_jpeg(unsigned char *mem);
+int imb_is_a_jpeg(const unsigned char *mem);
int imb_savejpeg(struct ImBuf *ibuf, const char *name, int flags);
-struct ImBuf *imb_load_jpeg (unsigned char *buffer, size_t size, int flags, char colorspace[IM_MAX_SPACE]);
+struct ImBuf *imb_load_jpeg(const unsigned char *buffer, size_t size, int flags, char colorspace[IM_MAX_SPACE]);
/* bmp */
-int imb_is_a_bmp(unsigned char *buf);
-struct ImBuf *imb_bmp_decode(unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE]);
+int imb_is_a_bmp(const unsigned char *buf);
+struct ImBuf *imb_bmp_decode(const unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE]);
int imb_savebmp(struct ImBuf *ibuf, const char *name, int flags);
-/* cocoa */
-struct ImBuf *imb_cocoaLoadImage(unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE]);
-
/* cineon */
+int imb_is_cineon(const unsigned char *buf);
int imb_save_cineon(struct ImBuf *buf, const char *name, int flags);
-struct ImBuf *imb_load_cineon(unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE]);
-int imb_is_cineon(unsigned char *buf);
+struct ImBuf *imb_load_cineon(const unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE]);
/* dpx */
+int imb_is_dpx(const unsigned char *buf);
int imb_save_dpx(struct ImBuf *buf, const char *name, int flags);
-struct ImBuf *imb_load_dpx(unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE]);
-int imb_is_dpx(unsigned char *buf);
+struct ImBuf *imb_load_dpx(const unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE]);
/* hdr */
-int imb_is_a_hdr(unsigned char *buf);
-struct ImBuf *imb_loadhdr(unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE]);
+int imb_is_a_hdr(const unsigned char *buf);
+struct ImBuf *imb_loadhdr(const unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE]);
int imb_savehdr(struct ImBuf *ibuf, const char *name, int flags);
/* tiff */
void imb_inittiff(void);
-int imb_is_a_tiff(unsigned char *buf);
-struct ImBuf *imb_loadtiff(unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE]);
-void imb_loadtiletiff(struct ImBuf *ibuf, unsigned char *mem, size_t size,
+int imb_is_a_tiff(const unsigned char *buf);
+struct ImBuf *imb_loadtiff(const unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE]);
+void imb_loadtiletiff(struct ImBuf *ibuf, const unsigned char *mem, size_t size,
int tx, int ty, unsigned int *rect);
int imb_savetiff(struct ImBuf *ibuf, const char *name, int flags);
diff --git a/source/blender/imbuf/intern/IMB_metadata.h b/source/blender/imbuf/intern/IMB_metadata.h
index a717764b44f..bc0b2c70ecb 100644
--- a/source/blender/imbuf/intern/IMB_metadata.h
+++ b/source/blender/imbuf/intern/IMB_metadata.h
@@ -35,13 +35,6 @@
struct ImBuf;
-typedef struct ImMetaData {
- struct ImMetaData *next, *prev;
- char *key;
- char *value;
- int len;
-} ImMetaData;
-
/** The metadata is a list of key/value pairs (both char *) that can me
* saved in the header of several image formats.
* Apart from some common keys like
@@ -54,16 +47,6 @@ typedef struct ImMetaData {
/* free blender ImMetaData struct */
void IMB_metadata_free(struct ImBuf *img);
-/** read the field from the image info into the field
- * \param img - the ImBuf that contains the image data
- * \param key - the key of the field
- * \param value - the data in the field, first one found with key is returned,
- * memory has to be allocated by user.
- * \param len - length of value buffer allocated by user.
- * \return - 1 (true) if ImageInfo present and value for the key found, 0 (false) otherwise
- */
-bool IMB_metadata_get_field(struct ImBuf *img, const char *key, char *value, const size_t len);
-
/** set user data in the ImMetaData struct, which has to be allocated with IMB_metadata_create
* before calling this function.
* \param img - the ImBuf that contains the image data
diff --git a/source/blender/imbuf/intern/allocimbuf.c b/source/blender/imbuf/intern/allocimbuf.c
index 612517775f4..5c79eb2c544 100644
--- a/source/blender/imbuf/intern/allocimbuf.c
+++ b/source/blender/imbuf/intern/allocimbuf.c
@@ -47,8 +47,8 @@
#include "MEM_guardedalloc.h"
-#include "BLI_threads.h"
#include "BLI_utildefines.h"
+#include "BLI_threads.h"
static SpinLock refcounter_spin;
@@ -128,6 +128,13 @@ void imb_freetilesImBuf(ImBuf *ibuf)
ibuf->mall &= ~IB_tiles;
}
+static void imb_free_bitmap_font(ImBuf *ibuf)
+{
+ if (ibuf->userdata && (ibuf->userflags & IB_BITMAPFONT)) {
+ MEM_freeN(ibuf->userdata);
+ }
+}
+
static void freeencodedbufferImBuf(ImBuf *ibuf)
{
if (ibuf == NULL) return;
@@ -181,6 +188,7 @@ void IMB_freeImBuf(ImBuf *ibuf)
imb_freerectImBuf(ibuf);
imb_freerectfloatImBuf(ibuf);
imb_freetilesImBuf(ibuf);
+ imb_free_bitmap_font(ibuf);
IMB_freezbufImBuf(ibuf);
IMB_freezbuffloatImBuf(ibuf);
freeencodedbufferImBuf(ibuf);
@@ -206,10 +214,23 @@ ImBuf *IMB_makeSingleUser(ImBuf *ibuf)
{
ImBuf *rval;
- if (!ibuf || ibuf->refcounter == 0) { return ibuf; }
+ if (ibuf) {
+ bool is_single;
+ BLI_spin_lock(&refcounter_spin);
+ is_single = (ibuf->refcounter == 0);
+ BLI_spin_unlock(&refcounter_spin);
+ if (is_single) {
+ return ibuf;
+ }
+ }
+ else {
+ return NULL;
+ }
rval = IMB_dupImBuf(ibuf);
+ IMB_metadata_copy(rval, ibuf);
+
IMB_freeImBuf(ibuf);
return rval;
@@ -362,6 +383,30 @@ bool imb_addrectImBuf(ImBuf *ibuf)
return false;
}
+struct ImBuf *IMB_allocFromBuffer(const unsigned int *rect, const float *rectf,
+ unsigned int w, unsigned int h)
+{
+ ImBuf *ibuf = NULL;
+
+ if (!(rect || rectf))
+ return NULL;
+
+ ibuf = IMB_allocImBuf(w, h, 32, 0);
+
+ if (rectf) {
+ ibuf->rect_float = MEM_dupallocN(rectf);
+ ibuf->flags |= IB_rectfloat;
+ ibuf->mall |= IB_rectfloat;
+ }
+ if (rect) {
+ ibuf->rect = MEM_dupallocN(rect);
+ ibuf->flags |= IB_rect;
+ ibuf->mall |= IB_rect;
+ }
+
+ return ibuf;
+}
+
bool imb_addtilesImBuf(ImBuf *ibuf)
{
if (ibuf == NULL) return false;
@@ -383,7 +428,8 @@ ImBuf *IMB_allocImBuf(unsigned int x, unsigned int y, uchar planes, unsigned int
ibuf->x = x;
ibuf->y = y;
ibuf->planes = planes;
- ibuf->ftype = PNG | 15; /* the 15 means, set compression to low ratio but not time consuming */
+ ibuf->ftype = IMB_FTYPE_PNG;
+ ibuf->foptions.quality = 15; /* the 15 means, set compression to low ratio but not time consuming */
ibuf->channels = 4; /* float option, is set to other values when buffers get assigned */
ibuf->ppm[0] = ibuf->ppm[1] = IMB_DPI_DEFAULT / 0.0254f; /* IMB_DPI_DEFAULT -> pixels-per-meter */
@@ -441,10 +487,10 @@ ImBuf *IMB_dupImBuf(ImBuf *ibuf1)
if (ibuf2 == NULL) return NULL;
if (flags & IB_rect)
- memcpy(ibuf2->rect, ibuf1->rect, x * y * sizeof(int));
+ memcpy(ibuf2->rect, ibuf1->rect, ((size_t)x) * y * sizeof(int));
if (flags & IB_rectfloat)
- memcpy(ibuf2->rect_float, ibuf1->rect_float, ibuf1->channels * x * y * sizeof(float));
+ memcpy(ibuf2->rect_float, ibuf1->rect_float, ((size_t)ibuf1->channels) * x * y * sizeof(float));
if (ibuf1->encodedbuffer) {
ibuf2->encodedbuffersize = ibuf1->encodedbuffersize;
@@ -465,7 +511,7 @@ ImBuf *IMB_dupImBuf(ImBuf *ibuf1)
tbuf.encodedbuffer = ibuf2->encodedbuffer;
tbuf.zbuf = NULL;
tbuf.zbuf_float = NULL;
- for (a = 0; a < IB_MIPMAP_LEVELS; a++)
+ for (a = 0; a < IMB_MIPMAP_LEVELS; a++)
tbuf.mipmap[a] = NULL;
tbuf.dds_data.data = NULL;
diff --git a/source/blender/imbuf/intern/anim_movie.c b/source/blender/imbuf/intern/anim_movie.c
index eef7964ef3f..e2d56d29726 100644
--- a/source/blender/imbuf/intern/anim_movie.c
+++ b/source/blender/imbuf/intern/anim_movie.c
@@ -70,12 +70,8 @@
#include "MEM_guardedalloc.h"
-#include "DNA_userdef_types.h"
-
#include "BKE_global.h"
-#include "imbuf.h"
-
#ifdef WITH_AVI
# include "AVI_avi.h"
#endif
@@ -89,7 +85,6 @@
#include "IMB_imbuf_types.h"
#include "IMB_imbuf.h"
-#include "IMB_allocimbuf.h"
#include "IMB_anim.h"
#include "IMB_indexer.h"
@@ -104,13 +99,8 @@
#endif //WITH_FFMPEG
#ifdef WITH_REDCODE
-#ifdef _WIN32 /* on windows we use the ones in extern instead */
-#include "libredcode/format.h"
-#include "libredcode/codec.h"
-#else
-#include "libredcode/format.h"
-#include "libredcode/codec.h"
-#endif
+# include "libredcode/format.h"
+# include "libredcode/codec.h"
#endif
#include "IMB_colormanagement.h"
@@ -276,6 +266,8 @@ struct anim *IMB_open_anim(const char *name, int ib_flags, int streamindex, char
{
struct anim *anim;
+ BLI_assert(!BLI_path_is_rel(name));
+
anim = (struct anim *)MEM_callocN(sizeof(struct anim), "anim struct");
if (anim != NULL) {
if (colorspace) {
@@ -293,6 +285,11 @@ struct anim *IMB_open_anim(const char *name, int ib_flags, int streamindex, char
return(anim);
}
+void IMB_suffix_anim(struct anim *anim, const char *suffix)
+{
+ BLI_strncpy(anim->suffix, suffix, sizeof(anim->suffix));
+}
+
#ifdef WITH_AVI
static int startavi(struct anim *anim)
{
@@ -1319,25 +1316,27 @@ struct ImBuf *IMB_anim_absolute(struct anim *anim, int position,
filter_y = (anim->ib_flags & IB_animdeinterlace);
- if (anim->curtype == 0) {
- ibuf = anim_getnew(anim);
- if (ibuf == NULL) {
- return(NULL);
+ if (preview_size == IMB_PROXY_NONE) {
+ if (anim->curtype == 0) {
+ ibuf = anim_getnew(anim);
+ if (ibuf == NULL) {
+ return(NULL);
+ }
+
+ IMB_freeImBuf(ibuf); /* ???? */
+ ibuf = NULL;
}
- IMB_freeImBuf(ibuf); /* ???? */
- ibuf = NULL;
+ if (position < 0) return(NULL);
+ if (position >= anim->duration) return(NULL);
}
-
- if (position < 0) return(NULL);
- if (position >= anim->duration) return(NULL);
-
- if (preview_size != IMB_PROXY_NONE) {
+ else {
struct anim *proxy = IMB_anim_open_proxy(anim, preview_size);
if (proxy) {
position = IMB_anim_index_get_frame_index(
anim, tc, position);
+
return IMB_anim_absolute(
proxy, position,
IMB_TC_NONE, IMB_PROXY_NONE);
@@ -1425,11 +1424,18 @@ int IMB_anim_get_duration(struct anim *anim, IMB_Timecode_Type tc)
}
bool IMB_anim_get_fps(struct anim *anim,
- short *frs_sec, float *frs_sec_base)
+ short *frs_sec, float *frs_sec_base, bool no_av_base)
{
if (anim->frs_sec) {
*frs_sec = anim->frs_sec;
*frs_sec_base = anim->frs_sec_base;
+#ifdef WITH_FFMPEG
+ if (no_av_base) {
+ *frs_sec_base /= AV_TIME_BASE;
+ }
+#else
+ UNUSED_VARS(no_av_base);
+#endif
return true;
}
return false;
diff --git a/source/blender/imbuf/intern/bmp.c b/source/blender/imbuf/intern/bmp.c
index dabeec74a62..c5694148127 100644
--- a/source/blender/imbuf/intern/bmp.c
+++ b/source/blender/imbuf/intern/bmp.c
@@ -36,7 +36,6 @@
#include "IMB_imbuf_types.h"
#include "IMB_imbuf.h"
-#include "IMB_allocimbuf.h"
#include "IMB_filetype.h"
#include "IMB_colormanagement.h"
@@ -73,22 +72,24 @@ typedef struct BMPHEADER {
#define BMP_FILEHEADER_SIZE 14
-static int checkbmp(unsigned char *mem)
+#define CHECK_HEADER_FIELD(_mem, _field) ((_mem[0] == _field[0]) && (_mem[1] == _field[1]))
+#define CHECK_HEADER_FIELD_BMP(_mem) \
+ (CHECK_HEADER_FIELD(_mem, "BM") || \
+ CHECK_HEADER_FIELD(_mem, "BA") || \
+ CHECK_HEADER_FIELD(_mem, "CI") || \
+ CHECK_HEADER_FIELD(_mem, "CP") || \
+ CHECK_HEADER_FIELD(_mem, "IC") || \
+ CHECK_HEADER_FIELD(_mem, "PT"))
+
+static int checkbmp(const unsigned char *mem)
{
-#define CHECK_HEADER_FIELD(mem, field) ((mem[0] == field[0]) && (mem[1] == field[1]))
int ret_val = 0;
BMPINFOHEADER bmi;
unsigned int u;
if (mem) {
- if (CHECK_HEADER_FIELD(mem, "BM") ||
- CHECK_HEADER_FIELD(mem, "BA") ||
- CHECK_HEADER_FIELD(mem, "CI") ||
- CHECK_HEADER_FIELD(mem, "CP") ||
- CHECK_HEADER_FIELD(mem, "IC") ||
- CHECK_HEADER_FIELD(mem, "PT"))
- {
+ if (CHECK_HEADER_FIELD_BMP(mem)) {
/* skip fileheader */
mem += BMP_FILEHEADER_SIZE;
}
@@ -104,7 +105,7 @@ static int checkbmp(unsigned char *mem)
if (u >= sizeof(BMPINFOHEADER)) {
if (bmi.biCompression == 0) {
u = LITTLE_SHORT(bmi.biBitCount);
- if (u >= 8) {
+ if (u > 0 && u <= 32) {
ret_val = 1;
}
}
@@ -112,23 +113,23 @@ static int checkbmp(unsigned char *mem)
}
return(ret_val);
-
-#undef CHECK_HEADER_FIELD
}
-int imb_is_a_bmp(unsigned char *buf)
+int imb_is_a_bmp(const unsigned char *buf)
{
return checkbmp(buf);
}
-struct ImBuf *imb_bmp_decode(unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE])
+struct ImBuf *imb_bmp_decode(const unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE])
{
struct ImBuf *ibuf = NULL;
BMPINFOHEADER bmi;
- int x, y, depth, ibuf_depth, skip, i;
- unsigned char *bmp, *rect;
+ int x, y, depth, ibuf_depth, skip, i, j;
+ const unsigned char *bmp;
+ unsigned char *rect;
unsigned short col;
double xppm, yppm;
+ bool top_to_bottom = false;
(void)size; /* unused */
@@ -136,10 +137,15 @@ struct ImBuf *imb_bmp_decode(unsigned char *mem, size_t size, int flags, char co
colorspace_set_default_role(colorspace, IM_MAX_SPACE, COLOR_ROLE_DEFAULT_BYTE);
- if ((mem[0] == 'B') && (mem[1] == 'M')) {
+ bmp = mem + LITTLE_LONG(*(int *)(mem + 10));
+
+ if (CHECK_HEADER_FIELD_BMP(mem)) {
/* skip fileheader */
mem += BMP_FILEHEADER_SIZE;
}
+ else {
+ return NULL;
+ }
/* for systems where an int needs to be 4 bytes aligned */
memcpy(&bmi, mem, sizeof(bmi));
@@ -158,11 +164,14 @@ struct ImBuf *imb_bmp_decode(unsigned char *mem, size_t size, int flags, char co
ibuf_depth = depth;
}
+ if (y < 0) {
+ /* Negative height means bitmap is stored top-to-bottom... */
+ y = -y;
+ top_to_bottom = true;
+ }
+
#if 0
- printf("skip: %d, x: %d y: %d, depth: %d (%x)\n", skip, x, y,
- depth, bmi.biBitCount);
- printf("skip: %d, x: %d y: %d, depth: %d (%x)\n", skip, x, y,
- depth, bmi.biBitCount);
+ printf("skip: %d, x: %d y: %d, depth: %d (%x)\n", skip, x, y, depth, bmi.biBitCount);
#endif
if (flags & IB_test) {
@@ -170,44 +179,67 @@ struct ImBuf *imb_bmp_decode(unsigned char *mem, size_t size, int flags, char co
}
else {
ibuf = IMB_allocImBuf(x, y, ibuf_depth, IB_rect);
- bmp = mem + skip;
rect = (unsigned char *) ibuf->rect;
- if (depth == 8) {
- const int x_pad = (4 - (x % 4)) % 4;
- const char (*palette)[4] = (void *)bmp;
- bmp += bmi.biClrUsed * 4;
+ if (depth <= 8) {
+ const int rowsize = (depth * x + 31) / 32 * 4;
+ const char (*palette)[4] = (void *)(mem + skip);
+ const int startmask = ((1 << depth) - 1) << 8;
for (i = y; i > 0; i--) {
- int j;
+ int index;
+ int bitoffs = 8;
+ int bitmask = startmask;
+ int nbytes = 0;
+ const char *pcol;
+ if (top_to_bottom) {
+ rect = (unsigned char *) &ibuf->rect[(i - 1) * x];
+ }
for (j = x; j > 0; j--) {
- const char *pcol = palette[bmp[0]];
- rect[0] = pcol[0];
+ bitoffs -= depth;
+ bitmask >>= depth;
+ index = (bmp[0] & bitmask) >> bitoffs;
+ pcol = palette[index];
+ /* intentionally BGR -> RGB */
+ rect[0] = pcol[2];
rect[1] = pcol[1];
- rect[2] = pcol[2];
+ rect[2] = pcol[0];
rect[3] = 255;
- rect += 4; bmp += 1;
+ rect += 4;
+ if (bitoffs == 0) {
+ /* Advance to the next byte */
+ bitoffs = 8;
+ bitmask = startmask;
+ nbytes += 1;
+ bmp += 1;
+ }
}
- /* rows are padded to multiples of 4 */
- bmp += x_pad;
+ /* Advance to the next row */
+ bmp += (rowsize - nbytes);
}
}
else if (depth == 16) {
- for (i = x * y; i > 0; i--) {
- col = bmp[0] + (bmp[1] << 8);
- rect[0] = ((col >> 10) & 0x1f) << 3;
- rect[1] = ((col >> 5) & 0x1f) << 3;
- rect[2] = ((col >> 0) & 0x1f) << 3;
-
- rect[3] = 255;
- rect += 4; bmp += 2;
- }
+ for (i = y; i > 0; i--) {
+ if (top_to_bottom) {
+ rect = (unsigned char *) &ibuf->rect[(i - 1) * x];
+ }
+ for (j = x; j > 0; j--) {
+ col = bmp[0] + (bmp[1] << 8);
+ rect[0] = ((col >> 10) & 0x1f) << 3;
+ rect[1] = ((col >> 5) & 0x1f) << 3;
+ rect[2] = ((col >> 0) & 0x1f) << 3;
+ rect[3] = 255;
+ rect += 4; bmp += 2;
+ }
+ }
}
else if (depth == 24) {
const int x_pad = x % 4;
for (i = y; i > 0; i--) {
- int j;
+ if (top_to_bottom) {
+ rect = (unsigned char *) &ibuf->rect[(i - 1) * x];
+ }
for (j = x; j > 0; j--) {
rect[0] = bmp[2];
rect[1] = bmp[1];
@@ -221,12 +253,17 @@ struct ImBuf *imb_bmp_decode(unsigned char *mem, size_t size, int flags, char co
}
}
else if (depth == 32) {
- for (i = x * y; i > 0; i--) {
- rect[0] = bmp[2];
- rect[1] = bmp[1];
- rect[2] = bmp[0];
- rect[3] = bmp[3];
- rect += 4; bmp += 4;
+ for (i = y; i > 0; i--) {
+ if (top_to_bottom) {
+ rect = (unsigned char *) &ibuf->rect[(i - 1) * x];
+ }
+ for (j = x; j > 0; j--) {
+ rect[0] = bmp[2];
+ rect[1] = bmp[1];
+ rect[2] = bmp[0];
+ rect[3] = bmp[3];
+ rect += 4; bmp += 4;
+ }
}
}
}
@@ -234,12 +271,15 @@ struct ImBuf *imb_bmp_decode(unsigned char *mem, size_t size, int flags, char co
if (ibuf) {
ibuf->ppm[0] = xppm;
ibuf->ppm[1] = yppm;
- ibuf->ftype = BMP;
+ ibuf->ftype = IMB_FTYPE_BMP;
}
return(ibuf);
}
+#undef CHECK_HEADER_FIELD_BMP
+#undef CHECK_HEADER_FIELD
+
/* Couple of helper functions for writing our data */
static int putIntLSB(unsigned int ui, FILE *ofile)
{
@@ -299,7 +339,9 @@ int imb_savebmp(struct ImBuf *ibuf, const char *name, int flags)
if (putc(data[ptr], ofile) == EOF) return 0;
}
/* add padding here */
- for (t = 0; t < extrabytes; t++) if (putc(0, ofile) == EOF) return 0;
+ for (t = 0; t < extrabytes; t++) {
+ if (putc(0, ofile) == EOF) return 0;
+ }
}
if (ofile) {
fflush(ofile);
diff --git a/source/blender/imbuf/intern/cache.c b/source/blender/imbuf/intern/cache.c
index 677c3dbe700..759f8cc82c2 100644
--- a/source/blender/imbuf/intern/cache.c
+++ b/source/blender/imbuf/intern/cache.c
@@ -22,7 +22,6 @@
* \ingroup imbuf
*/
-
#include "MEM_guardedalloc.h"
#include "BLI_utildefines.h"
@@ -31,8 +30,6 @@
#include "BLI_memarena.h"
#include "BLI_threads.h"
-
-
#include "IMB_imbuf.h"
#include "IMB_imbuf_types.h"
#include "IMB_filetype.h"
diff --git a/source/blender/imbuf/intern/cineon/cineon_dpx.c b/source/blender/imbuf/intern/cineon/cineon_dpx.c
index 56ce46bf92e..3e2206dc013 100644
--- a/source/blender/imbuf/intern/cineon/cineon_dpx.c
+++ b/source/blender/imbuf/intern/cineon/cineon_dpx.c
@@ -49,8 +49,9 @@
#include "MEM_guardedalloc.h"
-static struct ImBuf *imb_load_dpx_cineon(unsigned char *mem, size_t size, int use_cineon, int flags,
- char colorspace[IM_MAX_SPACE])
+static struct ImBuf *imb_load_dpx_cineon(
+ const unsigned char *mem, size_t size, int use_cineon, int flags,
+ char colorspace[IM_MAX_SPACE])
{
ImBuf *ibuf;
LogImageFile *image;
@@ -85,7 +86,7 @@ static struct ImBuf *imb_load_dpx_cineon(unsigned char *mem, size_t size, int us
}
logImageClose(image);
- ibuf->ftype = use_cineon ? CINEON : DPX;
+ ibuf->ftype = use_cineon ? IMB_FTYPE_CINEON : IMB_FTYPE_DPX;
if (flags & IB_alphamode_detect)
ibuf->flags |= IB_alphamode_premul;
@@ -114,17 +115,17 @@ static int imb_save_dpx_cineon(ImBuf *ibuf, const char *filename, int use_cineon
return 0;
}
- if (ibuf->ftype & CINEON_10BIT)
+ if (ibuf->foptions.flag & CINEON_10BIT)
bitspersample = 10;
- else if (ibuf->ftype & CINEON_12BIT)
+ else if (ibuf->foptions.flag & CINEON_12BIT)
bitspersample = 12;
- else if (ibuf->ftype & CINEON_16BIT)
+ else if (ibuf->foptions.flag & CINEON_16BIT)
bitspersample = 16;
else
bitspersample = 8;
logImage = logImageCreate(filename, use_cineon, ibuf->x, ibuf->y, bitspersample, (depth == 4),
- (ibuf->ftype & CINEON_LOG), -1, -1, -1, "Blender");
+ (ibuf->foptions.flag & CINEON_LOG), -1, -1, -1, "Blender");
if (logImage == NULL) {
printf("DPX/Cineon: error creating file.\n");
@@ -181,12 +182,12 @@ int imb_save_cineon(struct ImBuf *buf, const char *myfile, int flags)
return imb_save_dpx_cineon(buf, myfile, 1, flags);
}
-int imb_is_cineon(unsigned char *buf)
+int imb_is_cineon(const unsigned char *buf)
{
return logImageIsCineon(buf);
}
-ImBuf *imb_load_cineon(unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE])
+ImBuf *imb_load_cineon(const unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE])
{
if (imb_is_cineon(mem))
return imb_load_dpx_cineon(mem, size, 1, flags, colorspace);
@@ -198,12 +199,12 @@ int imb_save_dpx(struct ImBuf *buf, const char *myfile, int flags)
return imb_save_dpx_cineon(buf, myfile, 0, flags);
}
-int imb_is_dpx(unsigned char *buf)
+int imb_is_dpx(const unsigned char *buf)
{
return logImageIsDpx(buf);
}
-ImBuf *imb_load_dpx(unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE])
+ImBuf *imb_load_dpx(const unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE])
{
if (imb_is_dpx(mem))
return imb_load_dpx_cineon(mem, size, 0, flags, colorspace);
diff --git a/source/blender/imbuf/intern/cineon/cineonlib.c b/source/blender/imbuf/intern/cineon/cineonlib.c
index 880df0ce5c3..fbce508af17 100644
--- a/source/blender/imbuf/intern/cineon/cineonlib.c
+++ b/source/blender/imbuf/intern/cineon/cineonlib.c
@@ -135,7 +135,7 @@ LogImageFile *cineonOpen(const unsigned char *byteStuff, int fromMemory, size_t
{
CineonMainHeader header;
LogImageFile *cineon = (LogImageFile *)MEM_mallocN(sizeof(LogImageFile), __func__);
- char *filename = (char *)byteStuff;
+ const char *filename = (const char *)byteStuff;
int i;
unsigned int dataOffset;
@@ -307,7 +307,7 @@ LogImageFile *cineonOpen(const unsigned char *byteStuff, int fromMemory, size_t
printf(" Transfer characteristics: %d\n", cineon->element[i].transfer);
printf(" Packing: %d\n", cineon->element[i].packing);
printf(" Descriptor: %d\n", cineon->element[i].descriptor);
- printf(" Data offset: %u\n", cineon->element[i].dataOffset);
+ printf(" Data offset: %d\n", cineon->element[i].dataOffset);
printf(" Reference low data: %u\n", cineon->element[i].refLowData);
printf(" Reference low quantity: %f\n", cineon->element[i].refLowQuantity);
printf(" Reference high data: %u\n", cineon->element[i].refHighData);
diff --git a/source/blender/imbuf/intern/cineon/dpxlib.c b/source/blender/imbuf/intern/cineon/dpxlib.c
index 626d05b05c5..562bdecb842 100644
--- a/source/blender/imbuf/intern/cineon/dpxlib.c
+++ b/source/blender/imbuf/intern/cineon/dpxlib.c
@@ -67,7 +67,7 @@ static void fillDpxMainHeader(LogImageFile *dpx, DpxMainHeader *header, const ch
/* --- File header --- */
header->fileHeader.magic_num = swap_uint(DPX_FILE_MAGIC, dpx->isMSB);
header->fileHeader.offset = swap_uint(dpx->element[0].dataOffset, dpx->isMSB);
- strcpy(header->fileHeader.version, "v2.0");
+ strcpy(header->fileHeader.version, "V2.0");
header->fileHeader.file_size = swap_uint(dpx->element[0].dataOffset + dpx->height * getRowLength(dpx->width, dpx->element[0]), dpx->isMSB);
header->fileHeader.ditto_key = 0;
header->fileHeader.gen_hdr_size = swap_uint(sizeof(DpxFileHeader) + sizeof(DpxImageHeader) + sizeof(DpxOrientationHeader), dpx->isMSB);
@@ -134,7 +134,7 @@ LogImageFile *dpxOpen(const unsigned char *byteStuff, int fromMemory, size_t buf
{
DpxMainHeader header;
LogImageFile *dpx = (LogImageFile *)MEM_mallocN(sizeof(LogImageFile), __func__);
- char *filename = (char *)byteStuff;
+ const char *filename = (const char *)byteStuff;
int i;
if (dpx == NULL) {
@@ -183,8 +183,10 @@ LogImageFile *dpxOpen(const unsigned char *byteStuff, int fromMemory, size_t buf
if (verbose) printf("DPX: File is LSB.\n");
}
else {
- if (verbose) printf("DPX: Bad magic number %lu in \"%s\".\n",
- (uintptr_t)header.fileHeader.magic_num, byteStuff);
+ if (verbose) {
+ printf("DPX: Bad magic number %lu in \"%s\".\n",
+ (uintptr_t)header.fileHeader.magic_num, byteStuff);
+ }
logImageClose(dpx);
return NULL;
}
@@ -364,7 +366,7 @@ LogImageFile *dpxOpen(const unsigned char *byteStuff, int fromMemory, size_t buf
printf(" Transfer characteristics: %d\n", dpx->element[i].transfer);
printf(" Packing: %d\n", dpx->element[i].packing);
printf(" Descriptor: %d\n", dpx->element[i].descriptor);
- printf(" Data offset: %u\n", dpx->element[i].dataOffset);
+ printf(" Data offset: %d\n", dpx->element[i].dataOffset);
printf(" Reference low data: %u\n", dpx->element[i].refLowData);
printf(" Reference low quantity: %f\n", dpx->element[i].refLowQuantity);
printf(" Reference high data: %u\n", dpx->element[i].refHighData);
diff --git a/source/blender/imbuf/intern/cineon/logImageCore.c b/source/blender/imbuf/intern/cineon/logImageCore.c
index 1500f4282e5..5ec0a87890c 100644
--- a/source/blender/imbuf/intern/cineon/logImageCore.c
+++ b/source/blender/imbuf/intern/cineon/logImageCore.c
@@ -623,7 +623,7 @@ static int logImageElementGetData8(LogImageFile *logImage, LogImageElement logEl
for (y = 0; y < logImage->height; y++) {
/* 8 bits are 32-bits padded so we need to seek at each row */
if (logimage_fseek(logImage, logElement.dataOffset + y * rowLength, SEEK_SET) != 0) {
- if (verbose) printf("DPX/Cineon: Couldn't seek at %d\n", logElement.dataOffset + y * rowLength);
+ if (verbose) printf("DPX/Cineon: Couldn't seek at %d\n", logElement.dataOffset + y * (int)rowLength);
return 1;
}
diff --git a/source/blender/imbuf/intern/cineon/logImageCore.h b/source/blender/imbuf/intern/cineon/logImageCore.h
index 6b1435817d2..389e88a24de 100644
--- a/source/blender/imbuf/intern/cineon/logImageCore.h
+++ b/source/blender/imbuf/intern/cineon/logImageCore.h
@@ -52,8 +52,7 @@ enum format {
format_Cineon
};
-typedef struct LogImageElement
-{
+typedef struct LogImageElement {
int depth;
int bitsPerSample;
int dataOffset;
@@ -67,8 +66,7 @@ typedef struct LogImageElement
float maxValue; /* = 2^bitsPerSample - 1 (used internally, doesn't come from the file header) */
} LogImageElement;
-typedef struct LogImageFile
-{
+typedef struct LogImageFile {
/* specified in header */
int width;
int height;
diff --git a/source/blender/imbuf/intern/colormanagement.c b/source/blender/imbuf/intern/colormanagement.c
index 5dd6b366a93..5a3d9b4c653 100644
--- a/source/blender/imbuf/intern/colormanagement.c
+++ b/source/blender/imbuf/intern/colormanagement.c
@@ -44,7 +44,6 @@
#include "DNA_scene_types.h"
#include "DNA_space_types.h"
-#include "IMB_filter.h"
#include "IMB_imbuf.h"
#include "IMB_imbuf_types.h"
#include "IMB_filetype.h"
@@ -53,14 +52,13 @@
#include "MEM_guardedalloc.h"
#include "BLI_blenlib.h"
-#include "BLI_fileops.h"
#include "BLI_math.h"
#include "BLI_math_color.h"
-#include "BLI_path_util.h"
#include "BLI_string.h"
#include "BLI_threads.h"
#include "BLI_rect.h"
+#include "BKE_appdir.h"
#include "BKE_colortools.h"
#include "BKE_context.h"
#include "BKE_image.h"
@@ -92,6 +90,11 @@ static int global_tot_display = 0;
static int global_tot_view = 0;
static int global_tot_looks = 0;
+/* Set to ITU-BT.709 / sRGB primaries weight. Brute force stupid, but only
+ * option with no colormanagement in place.
+ */
+static float luma_coefficients[3] = { 0.2126f, 0.7152f, 0.0722f };
+
/* lock used by pre-cached processors getters, so processor wouldn't
* be created several times
* LOCK_COLORMANAGE can not be used since this mutex could be needed to
@@ -245,7 +248,7 @@ static ColormnaageCacheData *colormanage_cachedata_get(const ImBuf *ibuf)
static unsigned int colormanage_hashhash(const void *key_v)
{
- ColormanageCacheKey *key = (ColormanageCacheKey *)key_v;
+ const ColormanageCacheKey *key = key_v;
unsigned int rval = (key->display << 16) | (key->view % 0xffff);
@@ -254,8 +257,8 @@ static unsigned int colormanage_hashhash(const void *key_v)
static bool colormanage_hashcmp(const void *av, const void *bv)
{
- const ColormanageCacheKey *a = (ColormanageCacheKey *) av;
- const ColormanageCacheKey *b = (ColormanageCacheKey *) bv;
+ const ColormanageCacheKey *a = av;
+ const ColormanageCacheKey *b = bv;
return ((a->view != b->view) ||
(a->display != b->display));
@@ -547,6 +550,9 @@ static void colormanage_load_config(OCIO_ConstConfigRcPtr *config)
colormanage_look_add(name, process_space, false);
}
+
+ /* Load luminance coefficients. */
+ OCIO_configGetDefaultLumaCoefs(config, luma_coefficients);
}
static void colormanage_free_config(void)
@@ -625,7 +631,7 @@ void colormanagement_init(void)
}
if (config == NULL) {
- configdir = BLI_get_folder(BLENDER_DATAFILES, "colormanagement");
+ configdir = BKE_appdir_folder_id(BLENDER_DATAFILES, "colormanagement");
if (configdir) {
BLI_join_dirfile(configfile, sizeof(configfile), configdir, BCM_CONFIG_FILE);
@@ -1143,7 +1149,7 @@ void IMB_colormanagement_validate_settings(ColorManagedDisplaySettings *display_
for (view_link = display->views.first; view_link; view_link = view_link->next) {
ColorManagedView *view = view_link->data;
- if (!strcmp(view->name, view_settings->view_transform))
+ if (STREQ(view->name, view_settings->view_transform))
break;
}
@@ -1224,6 +1230,34 @@ const char *IMB_colormanagement_get_rect_colorspace(ImBuf *ibuf)
return ibuf->rect_colorspace->name;
}
+/* Convert a float RGB triplet to the correct luminance weighted average.
+ *
+ * Grayscale, or Luma is a distillation of RGB data values down to a weighted average
+ * based on the luminance positions of the red, green, and blue primaries.
+ * Given that the internal reference space may be arbitrarily set, any
+ * effort to glean the luminance coefficients must be aware of the reference
+ * space primaries.
+ *
+ * See http://wiki.blender.org/index.php/User:Nazg-gul/ColorManagement#Luminance
+ */
+
+float IMB_colormanagement_get_luminance(const float rgb[3])
+{
+ return dot_v3v3(luma_coefficients, rgb);
+}
+
+/* Byte equivalent of IMB_colormanagement_get_luminance(). */
+unsigned char IMB_colormanagement_get_luminance_byte(const unsigned char rgb[3])
+{
+ float rgbf[3];
+ float val;
+
+ rgb_uchar_to_float(rgbf, rgb);
+ val = dot_v3v3(luma_coefficients, rgbf);
+
+ return FTOCHAR(val);
+}
+
/*********************** Threaded display buffer transform routines *************************/
typedef struct DisplayBufferThread {
@@ -1272,8 +1306,8 @@ static void display_buffer_init_handle(void *handle_v, int start_line, int tot_l
float dither = ibuf->dither;
bool is_data = (ibuf->colormanage_flag & IMB_COLORMANAGE_IS_DATA) != 0;
- int offset = channels * start_line * ibuf->x;
- int display_buffer_byte_offset = DISPLAY_BUFFER_CHANNELS * start_line * ibuf->x;
+ size_t offset = ((size_t)channels) * start_line * ibuf->x;
+ size_t display_buffer_byte_offset = ((size_t)DISPLAY_BUFFER_CHANNELS) * start_line * ibuf->x;
memset(handle, 0, sizeof(DisplayBufferThread));
@@ -1310,7 +1344,7 @@ static void display_buffer_apply_get_linear_buffer(DisplayBufferThread *handle,
int channels = handle->channels;
int width = handle->width;
- int buffer_size = channels * width * height;
+ size_t buffer_size = ((size_t)channels) * width * height;
bool is_data = handle->is_data;
bool is_data_display = handle->cm_processor->is_data_result;
@@ -1323,11 +1357,12 @@ static void display_buffer_apply_get_linear_buffer(DisplayBufferThread *handle,
float *fp;
unsigned char *cp;
- int i;
+ const size_t i_last = ((size_t)width) * height;
+ size_t i;
/* first convert byte buffer to float, keep in image space */
for (i = 0, fp = linear_buffer, cp = byte_buffer;
- i < width * height;
+ i != i_last;
i++, fp += channels, cp += channels)
{
if (channels == 3) {
@@ -1406,7 +1441,7 @@ static void *do_display_buffer_apply_thread(void *handle_v)
}
else {
bool is_straight_alpha, predivide;
- float *linear_buffer = MEM_mallocN(channels * width * height * sizeof(float),
+ float *linear_buffer = MEM_mallocN(((size_t)channels) * width * height * sizeof(float),
"color conversion linear buffer");
display_buffer_apply_get_linear_buffer(handle, height, linear_buffer, &is_straight_alpha);
@@ -1433,14 +1468,15 @@ static void *do_display_buffer_apply_thread(void *handle_v)
}
if (display_buffer) {
- memcpy(display_buffer, linear_buffer, width * height * channels * sizeof(float));
+ memcpy(display_buffer, linear_buffer, ((size_t)width) * height * channels * sizeof(float));
if (is_straight_alpha && channels == 4) {
- int i;
+ const size_t i_last = ((size_t)width) * height;
+ size_t i;
float *fp;
for (i = 0, fp = display_buffer;
- i < width * height;
+ i != i_last;
i++, fp += channels)
{
straight_to_premul_v4(fp);
@@ -1498,7 +1534,7 @@ static bool is_ibuf_rect_in_display_space(ImBuf *ibuf, const ColorManagedViewSet
const char *from_colorspace = ibuf->rect_colorspace->name;
const char *to_colorspace = IMB_colormanagement_get_display_colorspace_name(view_settings, display_settings);
- if (to_colorspace && !strcmp(from_colorspace, to_colorspace))
+ if (to_colorspace && STREQ(from_colorspace, to_colorspace))
return true;
}
@@ -1568,7 +1604,7 @@ static void processor_transform_init_handle(void *handle_v, int start_line, int
int width = init_data->width;
bool predivide = init_data->predivide;
- int offset = channels * start_line * width;
+ size_t offset = ((size_t)channels) * start_line * width;
memset(handle, 0, sizeof(ProcessorTransformThread));
@@ -1627,7 +1663,7 @@ static void colormanagement_transform_ex(float *buffer, int width, int height, i
return;
}
- if (!strcmp(from_colorspace, to_colorspace)) {
+ if (STREQ(from_colorspace, to_colorspace)) {
/* if source and destination color spaces are identical, skip
* threading overhead and simply do nothing
*/
@@ -1668,7 +1704,7 @@ void IMB_colormanagement_transform_v4(float pixel[4], const char *from_colorspac
return;
}
- if (!strcmp(from_colorspace, to_colorspace)) {
+ if (STREQ(from_colorspace, to_colorspace)) {
/* if source and destination color spaces are identical, skip
* threading overhead and simply do nothing
*/
@@ -1753,8 +1789,10 @@ void IMB_colormanagement_colorspace_to_scene_linear(float *buffer, int width, in
if (processor) {
OCIO_PackedImageDesc *img;
- img = OCIO_createOCIO_PackedImageDesc(buffer, width, height, channels, sizeof(float),
- channels * sizeof(float), channels * sizeof(float) * width);
+ img = OCIO_createOCIO_PackedImageDesc(
+ buffer, width, height, channels, sizeof(float),
+ (size_t)channels * sizeof(float),
+ (size_t)channels * sizeof(float) * width);
if (predivide)
OCIO_processorApply_predivide(processor, img);
@@ -1914,13 +1952,13 @@ ImBuf *IMB_colormanagement_imbuf_for_write(ImBuf *ibuf, bool save_as_render, boo
if (do_colormanagement) {
bool make_byte = false;
- ImFileType *type;
+ const ImFileType *type;
/* for proper check whether byte buffer is required by a format or not
* should be pretty safe since this image buffer is supposed to be used for
* saving only and ftype would be overwritten a bit later by BKE_imbuf_write
*/
- colormanaged_ibuf->ftype = BKE_imtype_to_ftype(image_format_data->imtype);
+ colormanaged_ibuf->ftype = BKE_image_imtype_to_ftype(image_format_data->imtype, &colormanaged_ibuf->foptions);
/* if file format isn't able to handle float buffer itself,
* we need to allocate byte buffer and store color managed
@@ -1956,7 +1994,7 @@ void IMB_colormanagement_buffer_make_display_space(float *buffer, unsigned char
const ColorManagedDisplaySettings *display_settings)
{
ColormanageProcessor *cm_processor;
- size_t float_buffer_size = width * height * channels * sizeof(float);
+ size_t float_buffer_size = ((size_t)width) * height * channels * sizeof(float);
float *display_buffer_float = MEM_mallocN(float_buffer_size, "byte_buffer_make_display_space");
memcpy(display_buffer_float, buffer, float_buffer_size);
@@ -1981,7 +2019,7 @@ unsigned char *IMB_display_buffer_acquire(ImBuf *ibuf, const ColorManagedViewSet
const ColorManagedDisplaySettings *display_settings, void **cache_handle)
{
unsigned char *display_buffer;
- int buffer_size;
+ size_t buffer_size;
ColormanageCacheViewSettings cache_view_settings;
ColormanageCacheDisplaySettings cache_display_settings;
ColorManagedViewSettings default_view_settings;
@@ -2049,7 +2087,7 @@ unsigned char *IMB_display_buffer_acquire(ImBuf *ibuf, const ColorManagedViewSet
return display_buffer;
}
- buffer_size = DISPLAY_BUFFER_CHANNELS * ibuf->x * ibuf->y * sizeof(char);
+ buffer_size = DISPLAY_BUFFER_CHANNELS * ((size_t)ibuf->x) * ibuf->y * sizeof(char);
display_buffer = MEM_callocN(buffer_size, "imbuf display buffer");
colormanage_display_buffer_process(ibuf, display_buffer, applied_view_settings, display_settings);
@@ -2079,8 +2117,8 @@ void IMB_display_buffer_transform_apply(unsigned char *display_buffer, float *li
float *buffer;
ColormanageProcessor *cm_processor = IMB_colormanagement_display_processor_new(view_settings, display_settings);
- buffer = MEM_callocN(channels * width * height * sizeof(float), "display transform temp buffer");
- memcpy(buffer, linear_buffer, channels * width * height * sizeof(float));
+ buffer = MEM_mallocN((size_t)channels * width * height * sizeof(float), "display transform temp buffer");
+ memcpy(buffer, linear_buffer, (size_t)channels * width * height * sizeof(float));
IMB_colormanagement_processor_apply(cm_processor, buffer, width, height, channels, predivide);
@@ -2154,7 +2192,7 @@ ColorManagedDisplay *colormanage_display_get_named(const char *name)
ColorManagedDisplay *display;
for (display = global_displays.first; display; display = display->next) {
- if (!strcmp(display->name, name))
+ if (STREQ(display->name, name))
return display;
}
@@ -2259,7 +2297,7 @@ ColorManagedView *colormanage_view_get_named(const char *name)
ColorManagedView *view;
for (view = global_views.first; view; view = view->next) {
- if (!strcmp(view->name, name))
+ if (STREQ(view->name, name))
return view;
}
@@ -2375,7 +2413,7 @@ ColorSpace *colormanage_colorspace_get_named(const char *name)
ColorSpace *colorspace;
for (colorspace = global_colorspaces.first; colorspace; colorspace = colorspace->next) {
- if (!strcmp(colorspace->name, name))
+ if (STREQ(colorspace->name, name))
return colorspace;
}
@@ -2423,7 +2461,7 @@ const char *IMB_colormanagement_colorspace_get_indexed_name(int index)
void IMB_colormanagment_colorspace_from_ibuf_ftype(ColorManagedColorspaceSettings *colorspace_settings, ImBuf *ibuf)
{
- ImFileType *type;
+ const ImFileType *type;
for (type = IMB_FILE_TYPES; type < IMB_FILE_TYPES_LAST; type++) {
if (type->save && type->ftype(type, ibuf)) {
@@ -2461,7 +2499,7 @@ ColorManagedLook *colormanage_look_get_named(const char *name)
ColorManagedLook *look;
for (look = global_looks.first; look; look = look->next) {
- if (!strcmp(look->name, name)) {
+ if (STREQ(look->name, name)) {
return look;
}
}
@@ -2624,14 +2662,14 @@ static void partial_buffer_update_rect(ImBuf *ibuf, unsigned char *display_buffe
if (!cm_processor)
channels = 4;
- display_buffer_float = MEM_callocN(channels * width * height * sizeof(float), "display buffer for dither");
+ display_buffer_float = MEM_callocN((size_t)channels * width * height * sizeof(float), "display buffer for dither");
}
if (cm_processor) {
for (y = ymin; y < ymax; y++) {
for (x = xmin; x < xmax; x++) {
- int display_index = (y * display_stride + x) * 4;
- int linear_index = ((y - linear_offset_y) * linear_stride + (x - linear_offset_x)) * channels;
+ size_t display_index = ((size_t)y * display_stride + x) * 4;
+ size_t linear_index = ((size_t)(y - linear_offset_y) * linear_stride + (x - linear_offset_x)) * channels;
float pixel[4];
if (linear_buffer) {
@@ -2660,7 +2698,7 @@ static void partial_buffer_update_rect(ImBuf *ibuf, unsigned char *display_buffe
}
if (display_buffer_float) {
- int index = ((y - ymin) * width + (x - xmin)) * channels;
+ size_t index = ((size_t)(y - ymin) * width + (x - xmin)) * channels;
if (channels == 4) {
copy_v4_v4(display_buffer_float + index, pixel);
@@ -2703,8 +2741,8 @@ static void partial_buffer_update_rect(ImBuf *ibuf, unsigned char *display_buffe
int i;
for (i = ymin; i < ymax; i++) {
- int byte_offset = (linear_stride * i + xmin) * 4;
- int display_offset = (display_stride * i + xmin) * 4;
+ size_t byte_offset = ((size_t)linear_stride * i + xmin) * 4;
+ size_t display_offset = ((size_t)display_stride * i + xmin) * 4;
memcpy(display_buffer + display_offset, byte_buffer + byte_offset, 4 * sizeof(char) * width);
}
@@ -2712,7 +2750,7 @@ static void partial_buffer_update_rect(ImBuf *ibuf, unsigned char *display_buffe
}
if (display_buffer_float) {
- int display_index = (ymin * display_stride + xmin) * channels;
+ size_t display_index = ((size_t)ymin * display_stride + xmin) * channels;
IMB_buffer_byte_from_float(display_buffer + display_index, display_buffer_float, channels, dither,
IB_PROFILE_SRGB, IB_PROFILE_SRGB, true, width, height, display_stride, width);
@@ -2799,8 +2837,8 @@ void IMB_partial_display_buffer_update(ImBuf *ibuf, const float *linear_buffer,
if (copy_display_to_byte_buffer && (unsigned char *) ibuf->rect != display_buffer) {
int y;
for (y = ymin; y < ymax; y++) {
- int index = y * buffer_width * 4;
- memcpy((unsigned char *)ibuf->rect + index, display_buffer + index, (xmax - xmin) * 4);
+ size_t index = (size_t)y * buffer_width * 4;
+ memcpy((unsigned char *)ibuf->rect + index, display_buffer + index, (size_t)(xmax - xmin) * 4);
}
}
}
@@ -2925,7 +2963,7 @@ void IMB_colormanagement_processor_apply(ColormanageProcessor *cm_processor, flo
for (y = 0; y < height; y++) {
for (x = 0; x < width; x++) {
- float *pixel = buffer + channels * (y * width + x);
+ float *pixel = buffer + channels * (((size_t)y) * width + x);
curve_mapping_apply_pixel(cm_processor->curve_mapping, pixel, channels);
}
@@ -2936,8 +2974,10 @@ void IMB_colormanagement_processor_apply(ColormanageProcessor *cm_processor, flo
OCIO_PackedImageDesc *img;
/* apply OCIO processor */
- img = OCIO_createOCIO_PackedImageDesc(buffer, width, height, channels, sizeof(float),
- channels * sizeof(float), channels * sizeof(float) * width);
+ img = OCIO_createOCIO_PackedImageDesc(
+ buffer, width, height, channels, sizeof(float),
+ (size_t)channels * sizeof(float),
+ (size_t)channels * sizeof(float) * width);
if (predivide)
OCIO_processorApply_predivide(cm_processor->processor, img);
diff --git a/source/blender/imbuf/intern/dds/BlockDXT.h b/source/blender/imbuf/intern/dds/BlockDXT.h
index 7e5a1e504b8..6aae9c9817c 100644
--- a/source/blender/imbuf/intern/dds/BlockDXT.h
+++ b/source/blender/imbuf/intern/dds/BlockDXT.h
@@ -64,8 +64,7 @@
#include <Stream.h>
/// DXT1 block.
-struct BlockDXT1
-{
+struct BlockDXT1 {
Color16 col0;
Color16 col1;
union {
@@ -98,8 +97,7 @@ inline bool BlockDXT1::isFourColorMode() const
/// DXT3 alpha block with explicit alpha.
-struct AlphaBlockDXT3
-{
+struct AlphaBlockDXT3 {
union {
struct {
uint alpha0 : 4;
@@ -130,8 +128,7 @@ struct AlphaBlockDXT3
/// DXT3 block.
-struct BlockDXT3
-{
+struct BlockDXT3 {
AlphaBlockDXT3 alpha;
BlockDXT1 color;
@@ -144,8 +141,7 @@ struct BlockDXT3
/// DXT5 alpha block.
-struct AlphaBlockDXT5
-{
+struct AlphaBlockDXT5 {
// uint64 unions do not compile on all platforms
#if 0
union {
@@ -208,8 +204,7 @@ struct AlphaBlockDXT5
/// DXT5 block.
-struct BlockDXT5
-{
+struct BlockDXT5 {
AlphaBlockDXT5 alpha;
BlockDXT1 color;
@@ -221,8 +216,7 @@ struct BlockDXT5
};
/// ATI1 block.
-struct BlockATI1
-{
+struct BlockATI1 {
AlphaBlockDXT5 alpha;
void decodeBlock(ColorBlock * block) const;
@@ -232,8 +226,7 @@ struct BlockATI1
};
/// ATI2 block.
-struct BlockATI2
-{
+struct BlockATI2 {
AlphaBlockDXT5 x;
AlphaBlockDXT5 y;
@@ -244,8 +237,7 @@ struct BlockATI2
};
/// CTX1 block.
-struct BlockCTX1
-{
+struct BlockCTX1 {
uint8 col0[2];
uint8 col1[2];
union {
diff --git a/source/blender/imbuf/intern/dds/ColorBlock.h b/source/blender/imbuf/intern/dds/ColorBlock.h
index 730a19d84fd..8d5031aa603 100644
--- a/source/blender/imbuf/intern/dds/ColorBlock.h
+++ b/source/blender/imbuf/intern/dds/ColorBlock.h
@@ -41,8 +41,7 @@
#include <Image.h>
/// Uncompressed 4x4 color block.
-struct ColorBlock
-{
+struct ColorBlock {
ColorBlock();
ColorBlock(const uint * linearImage);
ColorBlock(const ColorBlock & block);
diff --git a/source/blender/imbuf/intern/dds/DirectDrawSurface.cpp b/source/blender/imbuf/intern/dds/DirectDrawSurface.cpp
index 028026527dc..6bf82776afe 100644
--- a/source/blender/imbuf/intern/dds/DirectDrawSurface.cpp
+++ b/source/blender/imbuf/intern/dds/DirectDrawSurface.cpp
@@ -60,6 +60,7 @@
#include <PixelFormat.h>
#include <stdio.h> // printf
+#include <stdlib.h> // malloc
#include <math.h> // sqrt
#include <sys/types.h>
@@ -496,8 +497,7 @@ void mem_read(Stream & mem, DDSHeader & header)
namespace
{
-struct FormatDescriptor
-{
+struct FormatDescriptor {
uint format;
uint bitcount;
uint rmask;
@@ -1148,7 +1148,7 @@ void* DirectDrawSurface::readData(uint &rsize)
uint size = stream.size - header_size;
rsize = size;
- unsigned char *data = new unsigned char[size];
+ unsigned char *data = (unsigned char *)malloc(sizeof(*data) * size);
stream.seek(header_size);
mem_read(stream, data, size);
diff --git a/source/blender/imbuf/intern/dds/DirectDrawSurface.h b/source/blender/imbuf/intern/dds/DirectDrawSurface.h
index 3d308ba1ff1..44c27a98c1d 100644
--- a/source/blender/imbuf/intern/dds/DirectDrawSurface.h
+++ b/source/blender/imbuf/intern/dds/DirectDrawSurface.h
@@ -63,8 +63,7 @@
#include <ColorBlock.h>
#include <Image.h>
-struct DDSPixelFormat
-{
+struct DDSPixelFormat {
uint size;
uint flags;
uint fourcc;
@@ -75,8 +74,7 @@ struct DDSPixelFormat
uint amask;
};
-struct DDSCaps
-{
+struct DDSCaps {
uint caps1;
uint caps2;
uint caps3;
@@ -84,8 +82,7 @@ struct DDSCaps
};
/// DDS file header for DX10.
-struct DDSHeader10
-{
+struct DDSHeader10 {
uint dxgiFormat;
uint resourceDimension;
uint miscFlag;
@@ -94,8 +91,7 @@ struct DDSHeader10
};
/// DDS file header.
-struct DDSHeader
-{
+struct DDSHeader {
uint fourcc;
uint size;
uint flags;
diff --git a/source/blender/imbuf/intern/dds/Stream.cpp b/source/blender/imbuf/intern/dds/Stream.cpp
index 57a251261a1..d8387b92530 100644
--- a/source/blender/imbuf/intern/dds/Stream.cpp
+++ b/source/blender/imbuf/intern/dds/Stream.cpp
@@ -30,10 +30,13 @@
#include <stdio.h> // printf
#include <string.h> // memcpy
+static const char *msg_error_seek = "DDS: trying to seek beyond end of stream (corrupt file?)";
+static const char *msg_error_read = "DDS: trying to read beyond end of stream (corrupt file?)";
+
unsigned int Stream::seek(unsigned int p)
{
if (p > size) {
- printf("DDS: trying to seek beyond end of stream (corrupt file?)");
+ puts(msg_error_seek);
}
else {
pos = p;
@@ -45,7 +48,7 @@ unsigned int Stream::seek(unsigned int p)
unsigned int mem_read(Stream & mem, unsigned long long & i)
{
if (mem.pos + 8 > mem.size) {
- printf("DDS: trying to read beyond end of stream (corrupt file?)");
+ puts(msg_error_seek);
return(0);
}
memcpy(&i, mem.mem + mem.pos, 8); // @@ todo: make sure little endian
@@ -56,7 +59,7 @@ unsigned int mem_read(Stream & mem, unsigned long long & i)
unsigned int mem_read(Stream & mem, unsigned int & i)
{
if (mem.pos + 4 > mem.size) {
- printf("DDS: trying to read beyond end of stream (corrupt file?)");
+ puts(msg_error_read);
return(0);
}
memcpy(&i, mem.mem + mem.pos, 4); // @@ todo: make sure little endian
@@ -67,7 +70,7 @@ unsigned int mem_read(Stream & mem, unsigned int & i)
unsigned int mem_read(Stream & mem, unsigned short & i)
{
if (mem.pos + 2 > mem.size) {
- printf("DDS: trying to read beyond end of stream (corrupt file?)");
+ puts(msg_error_read);
return(0);
}
memcpy(&i, mem.mem + mem.pos, 2); // @@ todo: make sure little endian
@@ -78,7 +81,7 @@ unsigned int mem_read(Stream & mem, unsigned short & i)
unsigned int mem_read(Stream & mem, unsigned char & i)
{
if (mem.pos + 1 > mem.size) {
- printf("DDS: trying to read beyond end of stream (corrupt file?)");
+ puts(msg_error_read);
return(0);
}
i = (mem.mem + mem.pos)[0];
@@ -89,7 +92,7 @@ unsigned int mem_read(Stream & mem, unsigned char & i)
unsigned int mem_read(Stream & mem, unsigned char *i, unsigned int cnt)
{
if (mem.pos + cnt > mem.size) {
- printf("DDS: trying to read beyond end of stream (corrupt file?)");
+ puts(msg_error_read);
return(0);
}
memcpy(i, mem.mem + mem.pos, cnt);
diff --git a/source/blender/imbuf/intern/dds/Stream.h b/source/blender/imbuf/intern/dds/Stream.h
index a1ac49b58da..6557fb4f063 100644
--- a/source/blender/imbuf/intern/dds/Stream.h
+++ b/source/blender/imbuf/intern/dds/Stream.h
@@ -30,8 +30,7 @@
#ifndef __STREAM_H__
#define __STREAM_H__
-struct Stream
-{
+struct Stream {
unsigned char *mem; // location in memory
unsigned int size; // size
unsigned int pos; // current position
diff --git a/source/blender/imbuf/intern/dds/dds_api.cpp b/source/blender/imbuf/intern/dds/dds_api.cpp
index a6d53ffac96..c963609b321 100644
--- a/source/blender/imbuf/intern/dds/dds_api.cpp
+++ b/source/blender/imbuf/intern/dds/dds_api.cpp
@@ -47,7 +47,7 @@ extern "C" {
#include "IMB_colormanagement.h"
#include "IMB_colormanagement_intern.h"
-int imb_save_dds(struct ImBuf *ibuf, const char *name, int flags)
+int imb_save_dds(struct ImBuf *ibuf, const char *name, int /*flags*/)
{
return(0); /* todo: finish this function */
@@ -73,7 +73,7 @@ int imb_save_dds(struct ImBuf *ibuf, const char *name, int flags)
return(1);
}
-int imb_is_a_dds(unsigned char *mem) // note: use at most first 32 bytes
+int imb_is_a_dds(const unsigned char *mem) // note: use at most first 32 bytes
{
/* heuristic check to see if mem contains a DDS file */
/* header.fourcc == FOURCC_DDS */
@@ -83,10 +83,10 @@ int imb_is_a_dds(unsigned char *mem) // note: use at most first 32 bytes
return(1);
}
-struct ImBuf *imb_load_dds(unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE])
+struct ImBuf *imb_load_dds(const unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE])
{
struct ImBuf *ibuf = NULL;
- DirectDrawSurface dds(mem, size); /* reads header */
+ DirectDrawSurface dds((unsigned char *)mem, size); /* reads header */
unsigned char bits_per_pixel;
unsigned int *rect;
Image img;
@@ -142,7 +142,7 @@ struct ImBuf *imb_load_dds(unsigned char *mem, size_t size, int flags, char colo
ibuf = IMB_allocImBuf(dds.width(), dds.height(), bits_per_pixel, 0);
if (ibuf == 0) return(0); /* memory allocation failed */
- ibuf->ftype = DDS;
+ ibuf->ftype = IMB_FTYPE_DDS;
ibuf->dds_data.fourcc = dds.fourCC();
ibuf->dds_data.nummipmaps = dds.mipmapCount();
diff --git a/source/blender/imbuf/intern/dds/dds_api.h b/source/blender/imbuf/intern/dds/dds_api.h
index 2316fefce69..d911a163098 100644
--- a/source/blender/imbuf/intern/dds/dds_api.h
+++ b/source/blender/imbuf/intern/dds/dds_api.h
@@ -34,9 +34,9 @@ extern "C" {
#include "../../IMB_imbuf.h"
+int imb_is_a_dds(const unsigned char *mem); /* use only first 32 bytes of mem */
int imb_save_dds(struct ImBuf *ibuf, const char *name, int flags);
-int imb_is_a_dds(unsigned char *mem); /* use only first 32 bytes of mem */
-struct ImBuf *imb_load_dds(unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE]);
+struct ImBuf *imb_load_dds(const unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE]);
#ifdef __cplusplus
}
diff --git a/source/blender/imbuf/intern/divers.c b/source/blender/imbuf/intern/divers.c
index 03cd5ecd646..455b78bce4d 100644
--- a/source/blender/imbuf/intern/divers.c
+++ b/source/blender/imbuf/intern/divers.c
@@ -37,7 +37,6 @@
#include "imbuf.h"
#include "IMB_imbuf_types.h"
#include "IMB_imbuf.h"
-#include "IMB_allocimbuf.h"
#include "IMB_filter.h"
#include "IMB_colormanagement.h"
@@ -123,16 +122,6 @@ static void clear_dither_context(DitherContext *di)
MEM_freeN(di);
}
-MINLINE float dither_random_value(float s, float t)
-{
- static float vec[2] = {12.9898f, 78.233f};
- float st[2];
- float value;
- copy_v2_fl2(st, s, t);
-
- value = sinf(dot_v2v2(st, vec)) * 43758.5453f;
- return value - floorf(value);
-}
/************************* Generic Buffer Conversion *************************/
@@ -180,8 +169,8 @@ void IMB_buffer_byte_from_float(uchar *rect_to, const float *rect_from,
float tmp[4];
int x, y;
DitherContext *di = NULL;
- float inv_width = 1.0f / width,
- inv_height = 1.0f / height;
+ float inv_width = 1.0f / width;
+ float inv_height = 1.0f / height;
/* we need valid profiles */
BLI_assert(profile_to != IB_PROFILE_NONE);
@@ -195,16 +184,16 @@ void IMB_buffer_byte_from_float(uchar *rect_to, const float *rect_from,
if (channels_from == 1) {
/* single channel input */
- const float *from = rect_from + stride_from * y;
- uchar *to = rect_to + stride_to * y * 4;
+ const float *from = rect_from + ((size_t)stride_from) * y;
+ uchar *to = rect_to + ((size_t)stride_to) * y * 4;
for (x = 0; x < width; x++, from++, to += 4)
to[0] = to[1] = to[2] = to[3] = FTOCHAR(from[0]);
}
else if (channels_from == 3) {
/* RGB input */
- const float *from = rect_from + stride_from * y * 3;
- uchar *to = rect_to + stride_to * y * 4;
+ const float *from = rect_from + ((size_t)stride_from) * y * 3;
+ uchar *to = rect_to + ((size_t)stride_to) * y * 4;
if (profile_to == profile_from) {
/* no color space conversion */
@@ -232,8 +221,8 @@ void IMB_buffer_byte_from_float(uchar *rect_to, const float *rect_from,
}
else if (channels_from == 4) {
/* RGBA input */
- const float *from = rect_from + stride_from * y * 4;
- uchar *to = rect_to + stride_to * y * 4;
+ const float *from = rect_from + ((size_t)stride_from) * y * 4;
+ uchar *to = rect_to + ((size_t)stride_to) * y * 4;
if (profile_to == profile_from) {
float straight[4];
@@ -345,8 +334,8 @@ void IMB_buffer_byte_from_float_mask(uchar *rect_to, const float *rect_from,
if (channels_from == 1) {
/* single channel input */
- const float *from = rect_from + stride_from * y;
- uchar *to = rect_to + stride_to * y * 4;
+ const float *from = rect_from + ((size_t)stride_from) * y;
+ uchar *to = rect_to + ((size_t)stride_to) * y * 4;
for (x = 0; x < width; x++, from++, to += 4)
if (*mask++ == FILTER_MASK_USED)
@@ -354,8 +343,8 @@ void IMB_buffer_byte_from_float_mask(uchar *rect_to, const float *rect_from,
}
else if (channels_from == 3) {
/* RGB input */
- const float *from = rect_from + stride_from * y * 3;
- uchar *to = rect_to + stride_to * y * 4;
+ const float *from = rect_from + ((size_t)stride_from) * y * 3;
+ uchar *to = rect_to + ((size_t)stride_to) * y * 4;
for (x = 0; x < width; x++, from += 3, to += 4) {
if (*mask++ == FILTER_MASK_USED) {
@@ -366,8 +355,8 @@ void IMB_buffer_byte_from_float_mask(uchar *rect_to, const float *rect_from,
}
else if (channels_from == 4) {
/* RGBA input */
- const float *from = rect_from + stride_from * y * 4;
- uchar *to = rect_to + stride_to * y * 4;
+ const float *from = rect_from + ((size_t)stride_from) * y * 4;
+ uchar *to = rect_to + ((size_t)stride_to) * y * 4;
float straight[4];
@@ -419,7 +408,7 @@ void IMB_buffer_float_from_byte(float *rect_to, const uchar *rect_from,
/* RGBA input */
for (y = 0; y < height; y++) {
const uchar *from = rect_from + stride_from * y * 4;
- float *to = rect_to + stride_to * y * 4;
+ float *to = rect_to + ((size_t)stride_to) * y * 4;
if (profile_to == profile_from) {
/* no color space conversion */
@@ -471,8 +460,8 @@ void IMB_buffer_float_from_float(float *rect_to, const float *rect_from,
if (channels_from == 1) {
/* single channel input */
for (y = 0; y < height; y++) {
- const float *from = rect_from + stride_from * y;
- float *to = rect_to + stride_to * y * 4;
+ const float *from = rect_from + ((size_t)stride_from) * y;
+ float *to = rect_to + ((size_t)stride_to) * y * 4;
for (x = 0; x < width; x++, from++, to += 4)
to[0] = to[1] = to[2] = to[3] = from[0];
@@ -481,8 +470,8 @@ void IMB_buffer_float_from_float(float *rect_to, const float *rect_from,
else if (channels_from == 3) {
/* RGB input */
for (y = 0; y < height; y++) {
- const float *from = rect_from + stride_from * y * 3;
- float *to = rect_to + stride_to * y * 4;
+ const float *from = rect_from + ((size_t)stride_from) * y * 3;
+ float *to = rect_to + ((size_t)stride_to) * y * 4;
if (profile_to == profile_from) {
/* no color space conversion */
@@ -510,12 +499,12 @@ void IMB_buffer_float_from_float(float *rect_to, const float *rect_from,
else if (channels_from == 4) {
/* RGBA input */
for (y = 0; y < height; y++) {
- const float *from = rect_from + stride_from * y * 4;
- float *to = rect_to + stride_to * y * 4;
+ const float *from = rect_from + ((size_t)stride_from) * y * 4;
+ float *to = rect_to + ((size_t)stride_to) * y * 4;
if (profile_to == profile_from) {
/* same profile, copy */
- memcpy(to, from, sizeof(float) * 4 * width);
+ memcpy(to, from, sizeof(float) * ((size_t)4) * width);
}
else if (profile_to == IB_PROFILE_LINEAR_RGB) {
/* convert to sRGB to linear */
@@ -552,8 +541,8 @@ void IMB_buffer_float_from_float_mask(float *rect_to, const float *rect_from, in
if (channels_from == 1) {
/* single channel input */
for (y = 0; y < height; y++) {
- const float *from = rect_from + stride_from * y;
- float *to = rect_to + stride_to * y * 4;
+ const float *from = rect_from + ((size_t)stride_from) * y;
+ float *to = rect_to + ((size_t)stride_to) * y * 4;
for (x = 0; x < width; x++, from++, to += 4)
if (*mask++ == FILTER_MASK_USED)
@@ -563,8 +552,8 @@ void IMB_buffer_float_from_float_mask(float *rect_to, const float *rect_from, in
else if (channels_from == 3) {
/* RGB input */
for (y = 0; y < height; y++) {
- const float *from = rect_from + stride_from * y * 3;
- float *to = rect_to + stride_to * y * 4;
+ const float *from = rect_from + ((size_t)stride_from) * y * 3;
+ float *to = rect_to + ((size_t)stride_to) * y * 4;
for (x = 0; x < width; x++, from += 3, to += 4) {
if (*mask++ == FILTER_MASK_USED) {
@@ -577,8 +566,8 @@ void IMB_buffer_float_from_float_mask(float *rect_to, const float *rect_from, in
else if (channels_from == 4) {
/* RGBA input */
for (y = 0; y < height; y++) {
- const float *from = rect_from + stride_from * y * 4;
- float *to = rect_to + stride_to * y * 4;
+ const float *from = rect_from + ((size_t)stride_from) * y * 4;
+ float *to = rect_to + ((size_t)stride_to) * y * 4;
for (x = 0; x < width; x++, from += 4, to += 4)
if (*mask++ == FILTER_MASK_USED)
@@ -601,8 +590,8 @@ void IMB_buffer_byte_from_byte(uchar *rect_to, const uchar *rect_from,
/* always RGBA input */
for (y = 0; y < height; y++) {
- const uchar *from = rect_from + stride_from * y * 4;
- uchar *to = rect_to + stride_to * y * 4;
+ const uchar *from = rect_from + ((size_t)stride_from) * y * 4;
+ uchar *to = rect_to + ((size_t)stride_to) * y * 4;
if (profile_to == profile_from) {
/* same profile, copy */
@@ -701,8 +690,8 @@ void IMB_partial_rect_from_float(ImBuf *ibuf, float *buffer, int x, int y, int w
imb_addrectImBuf(ibuf);
/* do conversion */
- rect_float = ibuf->rect_float + (x + y * ibuf->x) * ibuf->channels;
- rect_byte = (uchar *)ibuf->rect + (x + y * ibuf->x) * 4;
+ rect_float = ibuf->rect_float + (x + ((size_t)y) * ibuf->x) * ibuf->channels;
+ rect_byte = (uchar *)ibuf->rect + (x + ((size_t)y) * ibuf->x) * 4;
if (is_data) {
/* exception for non-color data, just copy float */
@@ -745,9 +734,9 @@ void IMB_float_from_rect(ImBuf *ibuf)
*/
rect_float = ibuf->rect_float;
if (rect_float == NULL) {
- int size;
+ size_t size;
- size = ibuf->x * ibuf->y;
+ size = ((size_t)ibuf->x) * ibuf->y;
size = size * 4 * sizeof(float);
ibuf->channels = 4;
@@ -782,22 +771,22 @@ void IMB_color_to_bw(ImBuf *ibuf)
{
float *rct_fl = ibuf->rect_float;
uchar *rct = (uchar *)ibuf->rect;
- int i;
+ size_t i;
if (rct_fl) {
- for (i = ibuf->x * ibuf->y; i > 0; i--, rct_fl += 4)
- rct_fl[0] = rct_fl[1] = rct_fl[2] = rgb_to_grayscale(rct_fl);
+ for (i = ((size_t)ibuf->x) * ibuf->y; i > 0; i--, rct_fl += 4)
+ rct_fl[0] = rct_fl[1] = rct_fl[2] = IMB_colormanagement_get_luminance(rct_fl);
}
if (rct) {
- for (i = ibuf->x * ibuf->y; i > 0; i--, rct += 4)
- rct[0] = rct[1] = rct[2] = rgb_to_grayscale_byte(rct);
+ for (i = ((size_t)ibuf->x * ibuf->y); i > 0; i--, rct += 4)
+ rct[0] = rct[1] = rct[2] = IMB_colormanagement_get_luminance_byte(rct);
}
}
void IMB_buffer_float_clamp(float *buf, int width, int height)
{
- int i, total = width * height * 4;
+ size_t i, total = ((size_t)width) * height * 4;
for (i = 0; i < total; i++) {
buf[i] = min_ff(1.0, buf[i]);
}
@@ -805,7 +794,7 @@ void IMB_buffer_float_clamp(float *buf, int width, int height)
void IMB_buffer_float_unpremultiply(float *buf, int width, int height)
{
- int total = width * height;
+ size_t total = ((size_t)width) * height;
float *fp = buf;
while (total--) {
premul_to_straight_v4(fp);
@@ -815,7 +804,7 @@ void IMB_buffer_float_unpremultiply(float *buf, int width, int height)
void IMB_buffer_float_premultiply(float *buf, int width, int height)
{
- int total = width * height;
+ size_t total = ((size_t)width) * height;
float *fp = buf;
while (total--) {
straight_to_premul_v4(fp);
@@ -827,14 +816,14 @@ void IMB_buffer_float_premultiply(float *buf, int width, int height)
void IMB_saturation(ImBuf *ibuf, float sat)
{
- int i;
+ size_t i;
unsigned char *rct = (unsigned char *)ibuf->rect;
float *rct_fl = ibuf->rect_float;
float hsv[3];
if (rct) {
float rgb[3];
- for (i = ibuf->x * ibuf->y; i > 0; i--, rct += 4) {
+ for (i = ((size_t)ibuf->x) * ibuf->y; i > 0; i--, rct += 4) {
rgb_uchar_to_float(rgb, rct);
rgb_to_hsv_v(rgb, hsv);
hsv_to_rgb(hsv[0], hsv[1] * sat, hsv[2], rgb, rgb + 1, rgb + 2);
@@ -843,7 +832,7 @@ void IMB_saturation(ImBuf *ibuf, float sat)
}
if (rct_fl) {
- for (i = ibuf->x * ibuf->y; i > 0; i--, rct_fl += 4) {
+ for (i = ((size_t)ibuf->x) * ibuf->y; i > 0; i--, rct_fl += 4) {
rgb_to_hsv_v(rct_fl, hsv);
hsv_to_rgb(hsv[0], hsv[1] * sat, hsv[2], rct_fl, rct_fl + 1, rct_fl + 2);
}
diff --git a/source/blender/imbuf/intern/filetype.c b/source/blender/imbuf/intern/filetype.c
index b6b46c72384..3d3e8a0646a 100644
--- a/source/blender/imbuf/intern/filetype.c
+++ b/source/blender/imbuf/intern/filetype.c
@@ -51,54 +51,52 @@
#include "quicktime_import.h"
#endif
-#include "imbuf.h"
-
-static int imb_ftype_default(ImFileType *type, ImBuf *ibuf)
+static int imb_ftype_default(const ImFileType *type, ImBuf *ibuf)
{
- return (ibuf->ftype & type->filetype);
+ return (ibuf->ftype == type->filetype);
}
-static int imb_ftype_iris(ImFileType *type, ImBuf *ibuf)
+static int imb_ftype_iris(const ImFileType *type, ImBuf *ibuf)
{
(void)type;
- return (ibuf->ftype == IMAGIC);
+ return (ibuf->ftype == IMB_FTYPE_IMAGIC);
}
-ImFileType IMB_FILE_TYPES[] = {
- {NULL, NULL, imb_is_a_jpeg, NULL, imb_ftype_default, imb_load_jpeg, NULL, imb_savejpeg, NULL, 0, JPG, COLOR_ROLE_DEFAULT_BYTE},
- {NULL, NULL, imb_is_a_png, NULL, imb_ftype_default, imb_loadpng, NULL, imb_savepng, NULL, 0, PNG, COLOR_ROLE_DEFAULT_BYTE},
- {NULL, NULL, imb_is_a_bmp, NULL, imb_ftype_default, imb_bmp_decode, NULL, imb_savebmp, NULL, 0, BMP, COLOR_ROLE_DEFAULT_BYTE},
- {NULL, NULL, imb_is_a_targa, NULL, imb_ftype_default, imb_loadtarga, NULL, imb_savetarga, NULL, 0, TGA, COLOR_ROLE_DEFAULT_BYTE},
- {NULL, NULL, imb_is_a_iris, NULL, imb_ftype_iris, imb_loadiris, NULL, imb_saveiris, NULL, 0, IMAGIC, COLOR_ROLE_DEFAULT_BYTE},
+const ImFileType IMB_FILE_TYPES[] = {
+ {NULL, NULL, imb_is_a_jpeg, NULL, imb_ftype_default, imb_load_jpeg, NULL, imb_savejpeg, NULL, 0, IMB_FTYPE_JPG, COLOR_ROLE_DEFAULT_BYTE},
+ {NULL, NULL, imb_is_a_png, NULL, imb_ftype_default, imb_loadpng, NULL, imb_savepng, NULL, 0, IMB_FTYPE_PNG, COLOR_ROLE_DEFAULT_BYTE},
+ {NULL, NULL, imb_is_a_bmp, NULL, imb_ftype_default, imb_bmp_decode, NULL, imb_savebmp, NULL, 0, IMB_FTYPE_BMP, COLOR_ROLE_DEFAULT_BYTE},
+ {NULL, NULL, imb_is_a_targa, NULL, imb_ftype_default, imb_loadtarga, NULL, imb_savetarga, NULL, 0, IMB_FTYPE_TGA, COLOR_ROLE_DEFAULT_BYTE},
+ {NULL, NULL, imb_is_a_iris, NULL, imb_ftype_iris, imb_loadiris, NULL, imb_saveiris, NULL, 0, IMB_FTYPE_IMAGIC, COLOR_ROLE_DEFAULT_BYTE},
#ifdef WITH_CINEON
- {NULL, NULL, imb_is_dpx, NULL, imb_ftype_default, imb_load_dpx, NULL, imb_save_dpx, NULL, IM_FTYPE_FLOAT, DPX, COLOR_ROLE_DEFAULT_FLOAT},
- {NULL, NULL, imb_is_cineon, NULL, imb_ftype_default, imb_load_cineon, NULL, imb_save_cineon, NULL, IM_FTYPE_FLOAT, CINEON, COLOR_ROLE_DEFAULT_FLOAT},
+ {NULL, NULL, imb_is_dpx, NULL, imb_ftype_default, imb_load_dpx, NULL, imb_save_dpx, NULL, IM_FTYPE_FLOAT, IMB_FTYPE_DPX, COLOR_ROLE_DEFAULT_FLOAT},
+ {NULL, NULL, imb_is_cineon, NULL, imb_ftype_default, imb_load_cineon, NULL, imb_save_cineon, NULL, IM_FTYPE_FLOAT, IMB_FTYPE_CINEON, COLOR_ROLE_DEFAULT_FLOAT},
#endif
#ifdef WITH_TIFF
- {imb_inittiff, NULL, imb_is_a_tiff, NULL, imb_ftype_default, imb_loadtiff, NULL, imb_savetiff, imb_loadtiletiff, 0, TIF, COLOR_ROLE_DEFAULT_BYTE},
+ {imb_inittiff, NULL, imb_is_a_tiff, NULL, imb_ftype_default, imb_loadtiff, NULL, imb_savetiff, imb_loadtiletiff, 0, IMB_FTYPE_TIF, COLOR_ROLE_DEFAULT_BYTE},
#endif
#ifdef WITH_HDR
- {NULL, NULL, imb_is_a_hdr, NULL, imb_ftype_default, imb_loadhdr, NULL, imb_savehdr, NULL, IM_FTYPE_FLOAT, RADHDR, COLOR_ROLE_DEFAULT_FLOAT},
+ {NULL, NULL, imb_is_a_hdr, NULL, imb_ftype_default, imb_loadhdr, NULL, imb_savehdr, NULL, IM_FTYPE_FLOAT, IMB_FTYPE_RADHDR, COLOR_ROLE_DEFAULT_FLOAT},
#endif
#ifdef WITH_OPENEXR
- {imb_initopenexr, NULL, imb_is_a_openexr, NULL, imb_ftype_default, imb_load_openexr, NULL, imb_save_openexr, NULL, IM_FTYPE_FLOAT, OPENEXR, COLOR_ROLE_DEFAULT_FLOAT},
+ {imb_initopenexr, NULL, imb_is_a_openexr, NULL, imb_ftype_default, imb_load_openexr, NULL, imb_save_openexr, NULL, IM_FTYPE_FLOAT, IMB_FTYPE_OPENEXR, COLOR_ROLE_DEFAULT_FLOAT},
#endif
#ifdef WITH_OPENJPEG
- {NULL, NULL, imb_is_a_jp2, NULL, imb_ftype_default, imb_jp2_decode, NULL, imb_savejp2, NULL, IM_FTYPE_FLOAT, JP2, COLOR_ROLE_DEFAULT_BYTE},
+ {NULL, NULL, imb_is_a_jp2, NULL, imb_ftype_default, imb_jp2_decode, NULL, imb_savejp2, NULL, IM_FTYPE_FLOAT, IMB_FTYPE_JP2, COLOR_ROLE_DEFAULT_BYTE},
#endif
#ifdef WITH_DDS
- {NULL, NULL, imb_is_a_dds, NULL, imb_ftype_default, imb_load_dds, NULL, NULL, NULL, 0, DDS, COLOR_ROLE_DEFAULT_BYTE},
+ {NULL, NULL, imb_is_a_dds, NULL, imb_ftype_default, imb_load_dds, NULL, NULL, NULL, 0, IMB_FTYPE_DDS, COLOR_ROLE_DEFAULT_BYTE},
#endif
#ifdef WITH_OPENIMAGEIO
- {NULL, NULL, NULL, imb_is_a_photoshop, imb_ftype_default, NULL, imb_load_photoshop, NULL, NULL, IM_FTYPE_FLOAT, PSD, COLOR_ROLE_DEFAULT_FLOAT},
+ {NULL, NULL, NULL, imb_is_a_photoshop, imb_ftype_default, NULL, imb_load_photoshop, NULL, NULL, IM_FTYPE_FLOAT, IMB_FTYPE_PSD, COLOR_ROLE_DEFAULT_FLOAT},
#endif
{NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0}
};
-ImFileType *IMB_FILE_TYPES_LAST = &IMB_FILE_TYPES[sizeof(IMB_FILE_TYPES) / sizeof(ImFileType) - 1];
+const ImFileType *IMB_FILE_TYPES_LAST = &IMB_FILE_TYPES[sizeof(IMB_FILE_TYPES) / sizeof(ImFileType) - 1];
void imb_filetypes_init(void)
{
- ImFileType *type;
+ const ImFileType *type;
for (type = IMB_FILE_TYPES; type < IMB_FILE_TYPES_LAST; type++)
if (type->init)
@@ -111,7 +109,7 @@ void imb_filetypes_init(void)
void imb_filetypes_exit(void)
{
- ImFileType *type;
+ const ImFileType *type;
for (type = IMB_FILE_TYPES; type < IMB_FILE_TYPES_LAST; type++)
if (type->exit)
diff --git a/source/blender/imbuf/intern/filter.c b/source/blender/imbuf/intern/filter.c
index 352e230068b..ef445239491 100644
--- a/source/blender/imbuf/intern/filter.c
+++ b/source/blender/imbuf/intern/filter.c
@@ -472,7 +472,7 @@ void IMB_remakemipmap(ImBuf *ibuf, int use_filter)
ibuf->miptot = 1;
- while (curmap < IB_MIPMAP_LEVELS) {
+ while (curmap < IMB_MIPMAP_LEVELS) {
if (ibuf->mipmap[curmap]) {
@@ -512,7 +512,7 @@ void IMB_makemipmap(ImBuf *ibuf, int use_filter)
ibuf->miptot = 1;
- while (curmap < IB_MIPMAP_LEVELS) {
+ while (curmap < IMB_MIPMAP_LEVELS) {
if (use_filter) {
ImBuf *nbuf = IMB_allocImBuf(hbuf->x, hbuf->y, 32, IB_rect);
IMB_filterN(nbuf, hbuf);
@@ -526,7 +526,7 @@ void IMB_makemipmap(ImBuf *ibuf, int use_filter)
hbuf = ibuf->mipmap[curmap];
hbuf->miplevel = curmap + 1;
- if (hbuf->x <= 2 && hbuf->y <= 2)
+ if (hbuf->x < 2 && hbuf->y < 2)
break;
curmap++;
diff --git a/source/blender/imbuf/intern/imageprocess.c b/source/blender/imbuf/intern/imageprocess.c
index cf875bb247b..d44f0dc86f4 100644
--- a/source/blender/imbuf/intern/imageprocess.c
+++ b/source/blender/imbuf/intern/imageprocess.c
@@ -51,7 +51,7 @@
/* Only this one is used liberally here, and in imbuf */
void IMB_convert_rgba_to_abgr(struct ImBuf *ibuf)
{
- int size;
+ size_t size;
unsigned char rt, *cp = (unsigned char *)ibuf->rect;
float rtf, *cpf = ibuf->rect_float;
@@ -86,7 +86,7 @@ void IMB_convert_rgba_to_abgr(struct ImBuf *ibuf)
static void pixel_from_buffer(struct ImBuf *ibuf, unsigned char **outI, float **outF, int x, int y)
{
- int offset = ibuf->x * y * 4 + 4 * x;
+ size_t offset = ((size_t)ibuf->x) * y * 4 + 4 * x;
if (ibuf->rect)
*outI = (unsigned char *)ibuf->rect + offset;
@@ -166,32 +166,34 @@ void bilinear_interpolation_color_wrap(struct ImBuf *in, unsigned char outI[4],
if (x2 >= in->x) x2 = x2 - in->x;
if (y2 >= in->y) y2 = y2 - in->y;
+ a = u - floorf(u);
+ b = v - floorf(v);
+ 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 (outF) {
/* sample including outside of edges of image */
- row1 = in->rect_float + in->x * y1 * 4 + 4 * x1;
- row2 = in->rect_float + in->x * y2 * 4 + 4 * x1;
- row3 = in->rect_float + in->x * y1 * 4 + 4 * x2;
- row4 = in->rect_float + in->x * y2 * 4 + 4 * x2;
-
- a = u - floorf(u);
- b = v - floorf(v);
- a_b = a * b; ma_b = (1.0f - a) * b; a_mb = a * (1.0f - b); ma_mb = (1.0f - a) * (1.0f - b);
+ row1 = in->rect_float + ((size_t)in->x) * y1 * 4 + 4 * x1;
+ row2 = in->rect_float + ((size_t)in->x) * y2 * 4 + 4 * x1;
+ row3 = in->rect_float + ((size_t)in->x) * y1 * 4 + 4 * x2;
+ row4 = in->rect_float + ((size_t)in->x) * y2 * 4 + 4 * x2;
outF[0] = ma_mb * row1[0] + a_mb * row3[0] + ma_b * row2[0] + a_b * row4[0];
outF[1] = ma_mb * row1[1] + a_mb * row3[1] + ma_b * row2[1] + a_b * row4[1];
outF[2] = ma_mb * row1[2] + a_mb * row3[2] + ma_b * row2[2] + a_b * row4[2];
outF[3] = ma_mb * row1[3] + a_mb * row3[3] + ma_b * row2[3] + a_b * row4[3];
+
+ /* clamp here or else we can easily get off-range */
+ CLAMP(outF[0], 0.0f, 1.0f);
+ CLAMP(outF[1], 0.0f, 1.0f);
+ CLAMP(outF[2], 0.0f, 1.0f);
+ CLAMP(outF[3], 0.0f, 1.0f);
}
if (outI) {
/* sample including outside of edges of image */
- row1I = (unsigned char *)in->rect + in->x * y1 * 4 + 4 * x1;
- row2I = (unsigned char *)in->rect + in->x * y2 * 4 + 4 * x1;
- row3I = (unsigned char *)in->rect + in->x * y1 * 4 + 4 * x2;
- row4I = (unsigned char *)in->rect + in->x * y2 * 4 + 4 * x2;
-
- a = u - floorf(u);
- b = v - floorf(v);
- a_b = a * b; ma_b = (1.0f - a) * b; a_mb = a * (1.0f - b); ma_mb = (1.0f - a) * (1.0f - b);
+ row1I = (unsigned char *)in->rect + ((size_t)in->x) * y1 * 4 + 4 * x1;
+ row2I = (unsigned char *)in->rect + ((size_t)in->x) * y2 * 4 + 4 * x1;
+ row3I = (unsigned char *)in->rect + ((size_t)in->x) * y1 * 4 + 4 * x2;
+ row4I = (unsigned char *)in->rect + ((size_t)in->x) * y2 * 4 + 4 * x2;
/* need to add 0.5 to avoid rounding down (causes darken with the smear brush)
* tested with white images and this should not wrap back to zero */
@@ -254,14 +256,14 @@ void nearest_interpolation_color(struct ImBuf *in, unsigned char outI[4], float
}
}
else {
- dataI = (unsigned char *)in->rect + in->x * y1 * 4 + 4 * x1;
+ dataI = (unsigned char *)in->rect + ((size_t)in->x) * y1 * 4 + 4 * x1;
if (outI) {
outI[0] = dataI[0];
outI[1] = dataI[1];
outI[2] = dataI[2];
outI[3] = dataI[3];
}
- dataF = in->rect_float + in->x * y1 * 4 + 4 * x1;
+ dataF = in->rect_float + ((size_t)in->x) * y1 * 4 + 4 * x1;
if (outF) {
outF[0] = dataF[0];
outF[1] = dataF[1];
@@ -271,6 +273,41 @@ void nearest_interpolation_color(struct ImBuf *in, unsigned char outI[4], float
}
}
+
+void nearest_interpolation_color_wrap(struct ImBuf *in, unsigned char outI[4], float outF[4], float u, float v)
+{
+ const float *dataF;
+ unsigned char *dataI;
+ int y, x;
+
+ /* ImBuf in must have a valid rect or rect_float, assume this is already checked */
+
+ x = (int) floor(u);
+ y = (int) floor(v);
+
+ x = x % in->x;
+ y = y % in->y;
+
+ /* wrap interpolation pixels - main difference from nearest_interpolation_color */
+ if (x < 0) x += in->x;
+ if (y < 0) y += in->y;
+
+ dataI = (unsigned char *)in->rect + ((size_t)in->x) * y * 4 + 4 * x;
+ if (outI) {
+ outI[0] = dataI[0];
+ outI[1] = dataI[1];
+ outI[2] = dataI[2];
+ outI[3] = dataI[3];
+ }
+ dataF = in->rect_float + ((size_t)in->x) * y * 4 + 4 * x;
+ if (outF) {
+ outF[0] = dataF[0];
+ outF[1] = dataF[1];
+ outF[2] = dataF[2];
+ outF[3] = dataF[3];
+ }
+}
+
void nearest_interpolation(ImBuf *in, ImBuf *out, float x, float y, int xout, int yout)
{
unsigned char *outI = NULL;
@@ -341,7 +378,7 @@ void IMB_processor_apply_threaded(int buffer_lines, int handle_size, void *init_
void IMB_alpha_under_color_float(float *rect_float, int x, int y, float backcol[3])
{
- int a = x * y;
+ size_t a = ((size_t)x) * y;
float *fp = rect_float;
while (a--) {
@@ -364,7 +401,7 @@ void IMB_alpha_under_color_float(float *rect_float, int x, int y, float backcol[
void IMB_alpha_under_color_byte(unsigned char *rect, int x, int y, float backcol[3])
{
- int a = x * y;
+ size_t a = ((size_t)x) * y;
unsigned char *cp = rect;
while (a--) {
diff --git a/source/blender/imbuf/intern/indexer.c b/source/blender/imbuf/intern/indexer.c
index 547a8df4438..ac57b095800 100644
--- a/source/blender/imbuf/intern/indexer.c
+++ b/source/blender/imbuf/intern/indexer.c
@@ -35,12 +35,12 @@
#include "BLI_path_util.h"
#include "BLI_string.h"
#include "BLI_fileops.h"
+#include "BLI_ghash.h"
#include "IMB_indexer.h"
#include "IMB_anim.h"
#include "imbuf.h"
-#include "MEM_guardedalloc.h"
#include "BKE_global.h"
#ifdef WITH_AVI
@@ -373,6 +373,13 @@ static void get_index_dir(struct anim *anim, char *index_dir, size_t index_dir_l
}
}
+void IMB_anim_get_fname(struct anim *anim, char *file, int size)
+{
+ char fname[FILE_MAXFILE];
+ BLI_split_dirfile(anim->name, file, fname, size, sizeof(fname));
+ BLI_strncpy(file, fname, size);
+}
+
static void get_proxy_filename(struct anim *anim, IMB_Proxy_Size preview_size,
char *fname, bool temp)
{
@@ -380,8 +387,8 @@ static void get_proxy_filename(struct anim *anim, IMB_Proxy_Size preview_size,
int i = IMB_proxy_size_to_array_index(preview_size);
char proxy_name[256];
- char proxy_temp_name[256];
char stream_suffix[20];
+ const char *name = (temp) ? "proxy_%d%s_part.avi" : "proxy_%d%s.avi";
stream_suffix[0] = 0;
@@ -389,15 +396,12 @@ static void get_proxy_filename(struct anim *anim, IMB_Proxy_Size preview_size,
BLI_snprintf(stream_suffix, sizeof(stream_suffix), "_st%d", anim->streamindex);
}
- BLI_snprintf(proxy_name, sizeof(proxy_name), "proxy_%d%s.avi",
- (int) (proxy_fac[i] * 100), stream_suffix);
- BLI_snprintf(proxy_temp_name, sizeof(proxy_temp_name), "proxy_%d%s_part.avi",
- (int) (proxy_fac[i] * 100), stream_suffix);
+ BLI_snprintf(proxy_name, sizeof(proxy_name), name,
+ (int) (proxy_fac[i] * 100), stream_suffix, anim->suffix);
get_index_dir(anim, index_dir, sizeof(index_dir));
- BLI_join_dirfile(fname, FILE_MAXFILE + FILE_MAXDIR, index_dir,
- temp ? proxy_temp_name : proxy_name);
+ BLI_join_dirfile(fname, FILE_MAXFILE + FILE_MAXDIR, index_dir, proxy_name);
}
static void get_tc_filename(struct anim *anim, IMB_Timecode_Type tc,
@@ -406,10 +410,10 @@ static void get_tc_filename(struct anim *anim, IMB_Timecode_Type tc,
char index_dir[FILE_MAXDIR];
int i = IMB_timecode_to_array_index(tc);
const char *index_names[] = {
- "record_run%s.blen_tc",
- "free_run%s.blen_tc",
- "interp_free_run%s.blen_tc",
- "record_run_no_gaps%s.blen_tc"
+ "record_run%s%s.blen_tc",
+ "free_run%s%s.blen_tc",
+ "interp_free_run%s%s.blen_tc",
+ "record_run_no_gaps%s%s.blen_tc"
};
char stream_suffix[20];
@@ -421,7 +425,7 @@ static void get_tc_filename(struct anim *anim, IMB_Timecode_Type tc,
BLI_snprintf(stream_suffix, 20, "_st%d", anim->streamindex);
}
- BLI_snprintf(index_name, 256, index_names[i], stream_suffix);
+ BLI_snprintf(index_name, 256, index_names[i], stream_suffix, anim->suffix);
get_index_dir(anim, index_dir, sizeof(index_dir));
@@ -1001,7 +1005,7 @@ static AviMovie *alloc_proxy_output_avi(
* but sane defaults help anyways...*/
float frs_sec_base = 1.0;
- IMB_anim_get_fps(anim, &frs_sec, &frs_sec_base);
+ IMB_anim_get_fps(anim, &frs_sec, &frs_sec_base, false);
x = width;
y = height;
@@ -1148,19 +1152,64 @@ static void index_rebuild_fallback(FallbackIndexBuilderContext *context,
* ---------------------------------------------------------------------- */
IndexBuildContext *IMB_anim_index_rebuild_context(struct anim *anim, IMB_Timecode_Type tcs_in_use,
- IMB_Proxy_Size proxy_sizes_in_use, int quality)
+ IMB_Proxy_Size proxy_sizes_in_use, int quality,
+ const bool overwrite, GSet *file_list)
{
IndexBuildContext *context = NULL;
+ IMB_Proxy_Size proxy_sizes_to_build = proxy_sizes_in_use;
+ int i;
+
+ /* Don't generate the same file twice! */
+ if (file_list) {
+ for (i = 0; i < IMB_PROXY_MAX_SLOT; ++i) {
+ IMB_Proxy_Size proxy_size = proxy_sizes[i];
+ if (proxy_size & proxy_sizes_to_build) {
+ char filename[FILE_MAX];
+ get_proxy_filename(anim, proxy_size, filename, false);
+
+ if (BLI_gset_haskey(file_list, filename)) {
+ proxy_sizes_to_build &= ~proxy_size;
+ printf("Proxy: %s already registered for generation, skipping\n", filename);
+ }
+ else {
+ BLI_gset_insert(file_list, BLI_strdup(filename));
+ }
+ }
+ }
+ }
+
+ if (!overwrite) {
+ IMB_Proxy_Size built_proxies = IMB_anim_proxy_get_existing(anim);
+ if (built_proxies != 0) {
+
+ for (i = 0; i < IMB_PROXY_MAX_SLOT; ++i) {
+ IMB_Proxy_Size proxy_size = proxy_sizes[i];
+ if (proxy_size & built_proxies) {
+ char filename[FILE_MAX];
+ get_proxy_filename(anim, proxy_size, filename, false);
+ printf("Skipping proxy: %s\n", filename);
+ }
+ }
+ }
+ proxy_sizes_to_build &= ~built_proxies;
+ }
+
+ fflush(stdout);
+
+ if (proxy_sizes_to_build == 0) {
+ return NULL;
+ }
+
switch (anim->curtype) {
#ifdef WITH_FFMPEG
case ANIM_FFMPEG:
- context = index_ffmpeg_create_context(anim, tcs_in_use, proxy_sizes_in_use, quality);
+ context = index_ffmpeg_create_context(anim, tcs_in_use, proxy_sizes_to_build, quality);
break;
#endif
#ifdef WITH_AVI
default:
- context = index_fallback_create_context(anim, tcs_in_use, proxy_sizes_in_use, quality);
+ context = index_fallback_create_context(anim, tcs_in_use, proxy_sizes_to_build, quality);
break;
#endif
}
@@ -1170,7 +1219,7 @@ IndexBuildContext *IMB_anim_index_rebuild_context(struct anim *anim, IMB_Timecod
return context;
- (void)tcs_in_use, (void)proxy_sizes_in_use, (void)quality;
+ UNUSED_VARS(tcs_in_use, proxy_sizes_in_use, quality);
}
void IMB_anim_index_rebuild(struct IndexBuildContext *context,
@@ -1189,7 +1238,7 @@ void IMB_anim_index_rebuild(struct IndexBuildContext *context,
#endif
}
- (void)stop, (void)do_update, (void)progress;
+ UNUSED_VARS(stop, do_update, progress);
}
void IMB_anim_index_rebuild_finish(IndexBuildContext *context, short stop)
@@ -1207,8 +1256,8 @@ void IMB_anim_index_rebuild_finish(IndexBuildContext *context, short stop)
#endif
}
- (void)stop;
- (void)proxy_sizes; /* static defined at top of the file */
+ /* static defined at top of the file */
+ UNUSED_VARS(stop, proxy_sizes);
}
@@ -1237,7 +1286,7 @@ void IMB_free_indices(struct anim *anim)
void IMB_anim_set_index_dir(struct anim *anim, const char *dir)
{
- if (strcmp(anim->index_dir, dir) == 0) {
+ if (STREQ(anim->index_dir, dir)) {
return;
}
BLI_strncpy(anim->index_dir, dir, sizeof(anim->index_dir));
@@ -1304,3 +1353,18 @@ int IMB_anim_index_get_frame_index(struct anim *anim, IMB_Timecode_Type tc,
return IMB_indexer_get_frame_index(idx, position);
}
+IMB_Proxy_Size IMB_anim_proxy_get_existing(struct anim *anim)
+{
+ const int num_proxy_sizes = IMB_PROXY_MAX_SLOT;
+ IMB_Proxy_Size existing = 0;
+ int i;
+ for (i = 0; i < num_proxy_sizes; ++i) {
+ IMB_Proxy_Size proxy_size = proxy_sizes[i];
+ char filename[FILE_MAX];
+ get_proxy_filename(anim, proxy_size, filename, false);
+ if (BLI_exists(filename)) {
+ existing |= proxy_size;
+ }
+ }
+ return existing;
+}
diff --git a/source/blender/imbuf/intern/iris.c b/source/blender/imbuf/intern/iris.c
index 8f98f240053..7a9fa2b9768 100644
--- a/source/blender/imbuf/intern/iris.c
+++ b/source/blender/imbuf/intern/iris.c
@@ -40,12 +40,13 @@
#include "imbuf.h"
#include "IMB_imbuf_types.h"
#include "IMB_imbuf.h"
-#include "IMB_allocimbuf.h"
#include "IMB_filetype.h"
#include "IMB_colormanagement.h"
#include "IMB_colormanagement_intern.h"
+#define IMAGIC 0732
+
typedef struct {
unsigned short imagic; /* stuff saved on disk . . */
unsigned short type;
@@ -75,6 +76,8 @@ typedef struct {
const int *rowsize; /* for rle images */
} IMAGE;
+#define HEADER_SIZE 512
+
#define RINTLUM (79)
#define GINTLUM (156)
#define BINTLUM (21)
@@ -100,21 +103,31 @@ typedef struct {
// #define IBUFSIZE(pixels) ((pixels + (pixels >> 6)) << 2) // UNUSED
// #define RLE_NOP 0x00
+/* local struct for mem access */
+typedef struct MFileOffset {
+ const uchar *_file_data;
+ unsigned int _file_offset;
+} MFileOffset;
+
+#define MFILE_DATA(inf) ((void)0, (inf)->_file_data + (inf)->_file_offset)
+#define MFILE_STEP(inf, step) { (inf)->_file_offset += step; } ((void)0)
+#define MFILE_SEEK(inf, pos) { (inf)->_file_offset = pos; } ((void)0)
+
/* funcs */
-static void readheader(FILE *inf, IMAGE *image);
+static void readheader(MFileOffset *inf, IMAGE *image);
static int writeheader(FILE *outf, IMAGE *image);
-static unsigned short getshort(FILE *inf);
-static unsigned int getlong(FILE *inf);
+static unsigned short getshort(MFileOffset *inf);
+static unsigned int getlong(MFileOffset *inf);
static void putshort(FILE *outf, unsigned short val);
static int putlong(FILE *outf, unsigned int val);
static int writetab(FILE *outf, unsigned int *tab, int len);
-static void readtab(FILE *inf, unsigned int *tab, int len);
+static void readtab(MFileOffset *inf, unsigned int *tab, int len);
-static void expandrow(unsigned char *optr, unsigned char *iptr, int z);
-static void expandrow2(float *optr, unsigned char *iptr, int z);
-static void interleaverow(unsigned char *lptr, unsigned char *cptr, int z, int n);
-static void interleaverow2(float *lptr, unsigned char *cptr, int z, int n);
+static void expandrow(unsigned char *optr, const unsigned char *iptr, int z);
+static void expandrow2(float *optr, const unsigned char *iptr, int z);
+static void interleaverow(unsigned char *lptr, const unsigned char *cptr, int z, int n);
+static void interleaverow2(float *lptr, const unsigned char *cptr, int z, int n);
static int compressrow(unsigned char *lbuf, unsigned char *rlebuf, int z, int cnt);
static void lumrow(unsigned char *rgbptr, unsigned char *lumptr, int n);
@@ -123,27 +136,22 @@ static void lumrow(unsigned char *rgbptr, unsigned char *lumptr, int n);
*
*/
-static uchar *file_data;
-static int file_offset;
-
-static unsigned short getshort(FILE *inf)
+static unsigned short getshort(MFileOffset *inf)
{
- unsigned char *buf;
- (void)inf; /* unused */
+ const unsigned char *buf;
- buf = file_data + file_offset;
- file_offset += 2;
+ buf = MFILE_DATA(inf);
+ MFILE_STEP(inf, 2);
return (buf[0] << 8) + (buf[1] << 0);
}
-static unsigned int getlong(FILE *inf)
+static unsigned int getlong(MFileOffset *mofs)
{
- unsigned char *buf;
- (void)inf; /* unused */
+ const unsigned char *buf;
- buf = file_data + file_offset;
- file_offset += 4;
+ buf = MFILE_DATA(mofs);
+ MFILE_STEP(mofs, 4);
return (buf[0] << 24) + (buf[1] << 16) + (buf[2] << 8) + (buf[3] << 0);
}
@@ -168,7 +176,7 @@ static int putlong(FILE *outf, unsigned int val)
return fwrite(buf, 4, 1, outf);
}
-static void readheader(FILE *inf, IMAGE *image)
+static void readheader(MFileOffset *inf, IMAGE *image)
{
memset(image, 0, sizeof(IMAGE));
image->imagic = getshort(inf);
@@ -208,7 +216,7 @@ static int writetab(FILE *outf, unsigned int *tab, int len)
return r;
}
-static void readtab(FILE *inf, unsigned int *tab, int len)
+static void readtab(MFileOffset *inf, unsigned int *tab, int len)
{
while (len) {
*tab++ = getlong(inf);
@@ -239,7 +247,7 @@ static void test_endian_zbuf(struct ImBuf *ibuf)
/* this one is only def-ed once, strangely... */
#define GSS(x) (((uchar *)(x))[1] << 8 | ((uchar *)(x))[0])
-int imb_is_a_iris(unsigned char *mem)
+int imb_is_a_iris(const unsigned char *mem)
{
return ((GS(mem) == IMAGIC) || (GSS(mem) == IMAGIC));
}
@@ -251,14 +259,14 @@ int imb_is_a_iris(unsigned char *mem)
*
*/
-struct ImBuf *imb_loadiris(unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE])
+struct ImBuf *imb_loadiris(const unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE])
{
unsigned int *base, *lptr = NULL;
float *fbase, *fptr = NULL;
unsigned int *zbase, *zptr;
- unsigned char *rledat;
+ const unsigned char *rledat;
unsigned int *starttab, *lengthtab;
- FILE *inf = NULL;
+ MFileOffset _inf_data = {mem, 0}, *inf = &_inf_data;
IMAGE image;
int x, y, z, tablen;
int xsize, ysize, zsize;
@@ -274,9 +282,6 @@ struct ImBuf *imb_loadiris(unsigned char *mem, size_t size, int flags, char colo
/*printf("new iris\n");*/
- file_data = mem;
- file_offset = 0;
-
readheader(inf, &image);
if (image.imagic != IMAGIC) {
fprintf(stderr, "longimagedata: bad magic number in image file\n");
@@ -296,7 +301,7 @@ struct ImBuf *imb_loadiris(unsigned char *mem, size_t size, int flags, char colo
if (flags & IB_test) {
ibuf = IMB_allocImBuf(image.xsize, image.ysize, 8 * image.zsize, 0);
- if (ibuf) ibuf->ftype = IMAGIC;
+ if (ibuf) ibuf->ftype = IMB_FTYPE_IMAGIC;
return(ibuf);
}
@@ -305,7 +310,7 @@ struct ImBuf *imb_loadiris(unsigned char *mem, size_t size, int flags, char colo
tablen = ysize * zsize * sizeof(int);
starttab = (unsigned int *)MEM_mallocN(tablen, "iris starttab");
lengthtab = (unsigned int *)MEM_mallocN(tablen, "iris endtab");
- file_offset = 512;
+ MFILE_SEEK(inf, HEADER_SIZE);
readtab(inf, starttab, tablen);
readtab(inf, lengthtab, tablen);
@@ -336,10 +341,9 @@ struct ImBuf *imb_loadiris(unsigned char *mem, size_t size, int flags, char colo
for (z = 0; z < zsize; z++) {
lptr = base;
for (y = 0; y < ysize; y++) {
- file_offset = starttab[y + z * ysize];
-
- rledat = file_data + file_offset;
- file_offset += lengthtab[y + z * ysize];
+ MFILE_SEEK(inf, starttab[y + z * ysize]);
+ rledat = MFILE_DATA(inf);
+ MFILE_STEP(inf, lengthtab[y + z * ysize]);
expandrow((uchar *)lptr, rledat, 3 - z);
lptr += xsize;
@@ -352,11 +356,9 @@ struct ImBuf *imb_loadiris(unsigned char *mem, size_t size, int flags, char colo
for (y = 0; y < ysize; y++) {
for (z = 0; z < zsize; z++) {
-
- file_offset = starttab[y + z * ysize];
-
- rledat = file_data + file_offset;
- file_offset += lengthtab[y + z * ysize];
+ MFILE_SEEK(inf, starttab[y + z * ysize]);
+ rledat = MFILE_DATA(inf);
+ MFILE_STEP(inf, lengthtab[y + z * ysize]);
if (z < 4) expandrow((uchar *)lptr, rledat, 3 - z);
else if (z < 8) expandrow((uchar *)zptr, rledat, 7 - z);
@@ -378,10 +380,9 @@ struct ImBuf *imb_loadiris(unsigned char *mem, size_t size, int flags, char colo
for (z = 0; z < zsize; z++) {
fptr = fbase;
for (y = 0; y < ysize; y++) {
- file_offset = starttab[y + z * ysize];
-
- rledat = file_data + file_offset;
- file_offset += lengthtab[y + z * ysize];
+ MFILE_SEEK(inf, starttab[y + z * ysize]);
+ rledat = MFILE_DATA(inf);
+ MFILE_STEP(inf, lengthtab[y + z * ysize]);
expandrow2(fptr, rledat, 3 - z);
fptr += xsize * 4;
@@ -394,11 +395,9 @@ struct ImBuf *imb_loadiris(unsigned char *mem, size_t size, int flags, char colo
for (y = 0; y < ysize; y++) {
for (z = 0; z < zsize; z++) {
-
- file_offset = starttab[y + z * ysize];
-
- rledat = file_data + file_offset;
- file_offset += lengthtab[y + z * ysize];
+ MFILE_SEEK(inf, starttab[y + z * ysize]);
+ rledat = MFILE_DATA(inf);
+ MFILE_STEP(inf, lengthtab[y + z * ysize]);
expandrow2(fptr, rledat, 3 - z);
@@ -421,8 +420,8 @@ struct ImBuf *imb_loadiris(unsigned char *mem, size_t size, int flags, char colo
base = ibuf->rect;
zbase = (unsigned int *)ibuf->zbuf;
- file_offset = 512;
- rledat = file_data + file_offset;
+ MFILE_SEEK(inf, HEADER_SIZE);
+ rledat = MFILE_DATA(inf);
for (z = 0; z < zsize; z++) {
@@ -445,8 +444,8 @@ struct ImBuf *imb_loadiris(unsigned char *mem, size_t size, int flags, char colo
fbase = ibuf->rect_float;
- file_offset = 512;
- rledat = file_data + file_offset;
+ MFILE_SEEK(inf, HEADER_SIZE);
+ rledat = MFILE_DATA(inf);
for (z = 0; z < zsize; z++) {
@@ -529,7 +528,7 @@ struct ImBuf *imb_loadiris(unsigned char *mem, size_t size, int flags, char colo
}
- ibuf->ftype = IMAGIC;
+ ibuf->ftype = IMB_FTYPE_IMAGIC;
test_endian_zbuf(ibuf);
@@ -542,7 +541,7 @@ struct ImBuf *imb_loadiris(unsigned char *mem, size_t size, int flags, char colo
/* static utility functions for longimagedata */
-static void interleaverow(unsigned char *lptr, unsigned char *cptr, int z, int n)
+static void interleaverow(unsigned char *lptr, const unsigned char *cptr, int z, int n)
{
lptr += z;
while (n--) {
@@ -551,7 +550,7 @@ static void interleaverow(unsigned char *lptr, unsigned char *cptr, int z, int n
}
}
-static void interleaverow2(float *lptr, unsigned char *cptr, int z, int n)
+static void interleaverow2(float *lptr, const unsigned char *cptr, int z, int n)
{
lptr += z;
while (n--) {
@@ -561,7 +560,7 @@ static void interleaverow2(float *lptr, unsigned char *cptr, int z, int n)
}
}
-static void expandrow2(float *optr, unsigned char *iptr, int z)
+static void expandrow2(float *optr, const unsigned char *iptr, int z)
{
unsigned short pixel, count;
float pixel_f;
@@ -617,7 +616,7 @@ static void expandrow2(float *optr, unsigned char *iptr, int z)
}
}
-static void expandrow(unsigned char *optr, unsigned char *iptr, int z)
+static void expandrow(unsigned char *optr, const unsigned char *iptr, int z)
{
unsigned char pixel, count;
@@ -704,7 +703,7 @@ static int output_iris(unsigned int *lptr, int xsize, int ysize, int zsize, cons
lumbuf = (unsigned int *)MEM_mallocN(xsize * sizeof(int), "iris lumbuf");
memset(image, 0, sizeof(IMAGE));
- image->imagic = IMAGIC;
+ image->imagic = IMB_FTYPE_IMAGIC;
image->type = RLE(1);
if (zsize > 1)
image->dim = 3;
@@ -716,8 +715,8 @@ static int output_iris(unsigned int *lptr, int xsize, int ysize, int zsize, cons
image->min = 0;
image->max = 255;
goodwrite *= writeheader(outf, image);
- fseek(outf, 512 + 2 * tablen, SEEK_SET);
- pos = 512 + 2 * tablen;
+ fseek(outf, HEADER_SIZE + (2 * tablen), SEEK_SET);
+ pos = HEADER_SIZE + (2 * tablen);
for (y = 0; y < ysize; y++) {
for (z = 0; z < zsize; z++) {
@@ -747,7 +746,7 @@ static int output_iris(unsigned int *lptr, int xsize, int ysize, int zsize, cons
if (zptr) zptr += xsize;
}
- fseek(outf, 512, SEEK_SET);
+ fseek(outf, HEADER_SIZE, SEEK_SET);
goodwrite *= writetab(outf, starttab, tablen);
goodwrite *= writetab(outf, lengthtab, tablen);
MEM_freeN(image);
diff --git a/source/blender/imbuf/intern/jp2.c b/source/blender/imbuf/intern/jp2.c
index 18c096450af..570ca5ba06e 100644
--- a/source/blender/imbuf/intern/jp2.c
+++ b/source/blender/imbuf/intern/jp2.c
@@ -29,11 +29,8 @@
#include "BLI_math.h"
#include "BLI_fileops.h"
-#include "imbuf.h"
-
#include "IMB_imbuf_types.h"
#include "IMB_imbuf.h"
-#include "IMB_allocimbuf.h"
#include "IMB_filetype.h"
#include "IMB_colormanagement.h"
@@ -43,8 +40,8 @@
// #define JP2_FILEHEADER_SIZE 14 /* UNUSED */
-static char JP2_HEAD[] = {0x0, 0x0, 0x0, 0x0C, 0x6A, 0x50, 0x20, 0x20, 0x0D, 0x0A, 0x87, 0x0A};
-static char J2K_HEAD[] = {0xFF, 0x4F, 0xFF, 0x51, 0x00};
+static const char JP2_HEAD[] = {0x0, 0x0, 0x0, 0x0C, 0x6A, 0x50, 0x20, 0x20, 0x0D, 0x0A, 0x87, 0x0A};
+static const char J2K_HEAD[] = {0xFF, 0x4F, 0xFF, 0x51, 0x00};
/* We only need this because of how the presets are set */
/* this typedef is copied from 'openjpeg-1.5.0/applications/codec/image_to_j2k.c' */
@@ -61,17 +58,22 @@ typedef struct img_folder {
float *rates;
} img_fol_t;
-static int check_jp2(unsigned char *mem) /* J2K_CFMT */
+enum {
+ DCP_CINEMA2K = 3,
+ DCP_CINEMA4K = 4,
+};
+
+static int check_jp2(const unsigned char *mem) /* J2K_CFMT */
{
return memcmp(JP2_HEAD, mem, sizeof(JP2_HEAD)) ? 0 : 1;
}
-static int check_j2k(unsigned char *mem) /* J2K_CFMT */
+static int check_j2k(const unsigned char *mem) /* J2K_CFMT */
{
return memcmp(J2K_HEAD, mem, sizeof(J2K_HEAD)) ? 0 : 1;
}
-int imb_is_a_jp2(unsigned char *buf)
+int imb_is_a_jp2(const unsigned char *buf)
{
return check_jp2(buf);
}
@@ -119,7 +121,7 @@ static void info_callback(const char *msg, void *client_data)
} \
} (void)0 \
-struct ImBuf *imb_jp2_decode(unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE])
+struct ImBuf *imb_jp2_decode(const unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE])
{
struct ImBuf *ibuf = NULL;
bool use_float = false; /* for precision higher then 8 use float */
@@ -173,7 +175,8 @@ struct ImBuf *imb_jp2_decode(unsigned char *mem, size_t size, int flags, char co
opj_setup_decoder(dinfo, &parameters);
/* open a byte stream */
- cio = opj_cio_open((opj_common_ptr)dinfo, mem, size);
+ /* note, we can't avoid removing 'const' cast here */
+ cio = opj_cio_open((opj_common_ptr)dinfo, (unsigned char *)mem, size);
/* decode the stream and fill the image structure */
image = opj_decode(dinfo, cio);
@@ -234,11 +237,11 @@ struct ImBuf *imb_jp2_decode(unsigned char *mem, size_t size, int flags, char co
return NULL;
}
- ibuf->ftype = JP2;
+ ibuf->ftype = IMB_FTYPE_JP2;
if (is_jp2)
- ibuf->ftype |= JP2_JP2;
+ ibuf->foptions.flag |= JP2_JP2;
else
- ibuf->ftype |= JP2_J2K;
+ ibuf->foptions.flag |= JP2_J2K;
if (use_float) {
float *rect_float = ibuf->rect_float;
@@ -461,7 +464,6 @@ static void cinema_parameters(opj_cparameters_t *parameters)
/* 9-7 transform */
parameters->irreversible = 1;
-
}
static void cinema_setup_encoder(opj_cparameters_t *parameters, opj_image_t *image, img_fol_t *img_fol)
@@ -481,6 +483,9 @@ static void cinema_setup_encoder(opj_cparameters_t *parameters, opj_image_t *ima
image->comps[0].w, image->comps[0].h);
parameters->cp_rsiz = STD_RSIZ;
}
+ else {
+ parameters->cp_rsiz = DCP_CINEMA2K;
+ }
break;
case CINEMA4K_24:
@@ -496,6 +501,9 @@ static void cinema_setup_encoder(opj_cparameters_t *parameters, opj_image_t *ima
image->comps[0].w, image->comps[0].h);
parameters->cp_rsiz = STD_RSIZ;
}
+ else {
+ parameters->cp_rsiz = DCP_CINEMA2K;
+ }
parameters->numpocs = initialise_4K_poc(parameters->POC, parameters->numresolution);
break;
case OFF:
@@ -589,12 +597,12 @@ static opj_image_t *ibuftoimage(ImBuf *ibuf, opj_cparameters_t *parameters)
chanel_colormanage_cb = linearrgb_to_srgb;
}
- if (ibuf->ftype & JP2_CINE) {
+ if (ibuf->foptions.flag & JP2_CINE) {
if (ibuf->x == 4096 || ibuf->y == 2160)
parameters->cp_cinema = CINEMA4K_24;
else {
- if (ibuf->ftype & JP2_CINE_48FPS) {
+ if (ibuf->foptions.flag & JP2_CINE_48FPS) {
parameters->cp_cinema = CINEMA2K_48;
}
else {
@@ -609,16 +617,16 @@ static opj_image_t *ibuftoimage(ImBuf *ibuf, opj_cparameters_t *parameters)
cinema_parameters(parameters);
}
- color_space = CLRSPC_SYCC;
+ color_space = (ibuf->foptions.flag & JP2_YCC) ? CLRSPC_SYCC : CLRSPC_SRGB;
prec = 12;
numcomps = 3;
}
else {
/* Get settings from the imbuf */
- color_space = (ibuf->ftype & JP2_YCC) ? CLRSPC_SYCC : CLRSPC_SRGB;
+ color_space = (ibuf->foptions.flag & JP2_YCC) ? CLRSPC_SYCC : CLRSPC_SRGB;
- if (ibuf->ftype & JP2_16BIT) prec = 16;
- else if (ibuf->ftype & JP2_12BIT) prec = 12;
+ if (ibuf->foptions.flag & JP2_16BIT) prec = 16;
+ else if (ibuf->foptions.flag & JP2_12BIT) prec = 12;
else prec = 8;
/* 32bit images == alpha channel */
@@ -954,7 +962,7 @@ static opj_image_t *ibuftoimage(ImBuf *ibuf, opj_cparameters_t *parameters)
/* Found write info at http://users.ece.gatech.edu/~slabaugh/personal/c/bitmapUnix.c */
int imb_savejp2(struct ImBuf *ibuf, const char *name, int flags)
{
- int quality = ibuf->ftype & 0xff;
+ int quality = ibuf->foptions.quality;
int bSuccess;
opj_cparameters_t parameters; /* compression parameters */
@@ -994,9 +1002,9 @@ int imb_savejp2(struct ImBuf *ibuf, const char *name, int flags)
opj_cinfo_t *cinfo = NULL;
/* get a JP2 compressor handle */
- if (ibuf->ftype & JP2_JP2)
+ if (ibuf->foptions.flag & JP2_JP2)
cinfo = opj_create_compress(CODEC_JP2);
- else if (ibuf->ftype & JP2_J2K)
+ else if (ibuf->foptions.flag & JP2_J2K)
cinfo = opj_create_compress(CODEC_J2K);
else
BLI_assert(!"Unsupported codec was specified in save settings");
diff --git a/source/blender/imbuf/intern/jpeg.c b/source/blender/imbuf/intern/jpeg.c
index f4b5f987869..ff2a9767386 100644
--- a/source/blender/imbuf/intern/jpeg.c
+++ b/source/blender/imbuf/intern/jpeg.c
@@ -37,9 +37,12 @@
#include "MEM_guardedalloc.h"
+#include "BLI_utildefines.h"
#include "BLI_string.h"
#include "BLI_fileops.h"
+#include "BKE_idprop.h"
+
#include "imbuf.h"
#include "IMB_imbuf_types.h"
#include "IMB_imbuf.h"
@@ -52,10 +55,10 @@
#include "IMB_colormanagement_intern.h"
// #define IS_jpg(x) (x->ftype & JPG) // UNUSED
-#define IS_stdjpg(x) ((x->ftype & JPG_MSK) == JPG_STD)
-// #define IS_vidjpg(x) ((x->ftype & JPG_MSK) == JPG_VID) // UNUSED
-#define IS_jstjpg(x) ((x->ftype & JPG_MSK) == JPG_JST)
-#define IS_maxjpg(x) ((x->ftype & JPG_MSK) == JPG_MAX)
+#define IS_stdjpg(x) ((x->foptions.flag & JPG_MSK) == JPG_STD)
+// #define IS_vidjpg(x) ((x->foptions & JPG_MSK) == JPG_VID) // UNUSED
+#define IS_jstjpg(x) ((x->foptions.flag & JPG_MSK) == JPG_JST)
+#define IS_maxjpg(x) ((x->foptions.flag & JPG_MSK) == JPG_MAX)
/* the types are from the jpeg lib */
static void jpeg_error(j_common_ptr cinfo) ATTR_NORETURN;
@@ -63,7 +66,7 @@ static void init_source(j_decompress_ptr cinfo);
static boolean fill_input_buffer(j_decompress_ptr cinfo);
static void skip_input_data(j_decompress_ptr cinfo, long num_bytes);
static void term_source(j_decompress_ptr cinfo);
-static void memory_source(j_decompress_ptr cinfo, unsigned char *buffer, size_t size);
+static void memory_source(j_decompress_ptr cinfo, const unsigned char *buffer, size_t size);
static boolean handle_app1(j_decompress_ptr cinfo);
static ImBuf *ibJpegImageFromCinfo(struct jpeg_decompress_struct *cinfo, int flags);
@@ -82,9 +85,9 @@ static ImBuf *ibJpegImageFromCinfo(struct jpeg_decompress_struct *cinfo, int fla
*/
static int jpeg_default_quality;
-static int ibuf_ftype;
+static int ibuf_foptions;
-int imb_is_a_jpeg(unsigned char *mem)
+int imb_is_a_jpeg(const unsigned char *mem)
{
if ((mem[0] == 0xFF) && (mem[1] == 0xD8)) return 1;
return 0;
@@ -130,7 +133,7 @@ typedef struct {
typedef struct {
struct jpeg_source_mgr pub; /* public fields */
- unsigned char *buffer;
+ const unsigned char *buffer;
int size;
JOCTET terminal[2];
} my_source_mgr;
@@ -179,7 +182,7 @@ static void term_source(j_decompress_ptr cinfo)
(void)cinfo; /* unused */
}
-static void memory_source(j_decompress_ptr cinfo, unsigned char *buffer, size_t size)
+static void memory_source(j_decompress_ptr cinfo, const unsigned char *buffer, size_t size)
{
my_src_ptr src;
@@ -252,8 +255,7 @@ static void memory_source(j_decompress_ptr cinfo, unsigned char *buffer, size_t
V += GETJOCTET(*next_input_byte++); )
-static boolean
-handle_app1(j_decompress_ptr cinfo)
+static boolean handle_app1(j_decompress_ptr cinfo)
{
INT32 length; /* initialized by the macro */
INT32 i;
@@ -267,8 +269,8 @@ handle_app1(j_decompress_ptr cinfo)
if (length < 16) {
for (i = 0; i < length; i++) INPUT_BYTE(cinfo, neogeo[i], return false);
length = 0;
- if (strncmp(neogeo, "NeoGeo", 6) == 0) memcpy(&ibuf_ftype, neogeo + 6, 4);
- ibuf_ftype = BIG_LONG(ibuf_ftype);
+ if (STREQLEN(neogeo, "NeoGeo", 6)) memcpy(&ibuf_foptions, neogeo + 6, 4);
+ ibuf_foptions = BIG_LONG(ibuf_foptions);
}
INPUT_SYNC(cinfo); /* do before skip_input_data */
if (length > 0) (*cinfo->src->skip_input_data)(cinfo, length);
@@ -288,7 +290,7 @@ static ImBuf *ibJpegImageFromCinfo(struct jpeg_decompress_struct *cinfo, int fla
char *str, *key, *value;
/* install own app1 handler */
- ibuf_ftype = 0;
+ ibuf_foptions = 0;
jpeg_set_marker_processor(cinfo, 0xe1, handle_app1);
cinfo->dct_method = JDCT_FLOAT;
jpeg_save_markers(cinfo, JPEG_COM, 0xffff);
@@ -302,11 +304,11 @@ static ImBuf *ibJpegImageFromCinfo(struct jpeg_decompress_struct *cinfo, int fla
jpeg_start_decompress(cinfo);
- if (ibuf_ftype == 0) {
- ibuf_ftype = JPG_STD;
+ if (ibuf_foptions == 0) {
+ ibuf_foptions = JPG_STD;
if (cinfo->max_v_samp_factor == 1) {
- if (cinfo->max_h_samp_factor == 1) ibuf_ftype = JPG_MAX;
- else ibuf_ftype = JPG_VID;
+ if (cinfo->max_h_samp_factor == 1) ibuf_foptions = JPG_MAX;
+ else ibuf_foptions = JPG_VID;
}
}
@@ -385,7 +387,7 @@ static ImBuf *ibJpegImageFromCinfo(struct jpeg_decompress_struct *cinfo, int fla
* That is why we need split it to the
* common key/value here.
*/
- if (strncmp(str, "Blender", 7)) {
+ if (!STREQLEN(str, "Blender", 7)) {
/*
* Maybe the file have text that
* we don't know "what it's", in that
@@ -433,14 +435,15 @@ next_stamp_marker:
jpeg_destroy((j_common_ptr) cinfo);
if (ibuf) {
- ibuf->ftype = ibuf_ftype;
+ ibuf->ftype = IMB_FTYPE_JPG;
+ ibuf->foptions.flag = ibuf_foptions;
}
}
return(ibuf);
}
-ImBuf *imb_load_jpeg(unsigned char *buffer, size_t size, int flags, char colorspace[IM_MAX_SPACE])
+ImBuf *imb_load_jpeg(const unsigned char *buffer, size_t size, int flags, char colorspace[IM_MAX_SPACE])
{
struct jpeg_decompress_struct _cinfo, *cinfo = &_cinfo;
struct my_error_mgr jerr;
@@ -478,40 +481,39 @@ static void write_jpeg(struct jpeg_compress_struct *cinfo, struct ImBuf *ibuf)
uchar *rect;
int x, y;
char neogeo[128];
- ImMetaData *iptr;
char *text;
jpeg_start_compress(cinfo, true);
strcpy(neogeo, "NeoGeo");
- ibuf_ftype = BIG_LONG(ibuf->ftype);
+ ibuf_foptions = BIG_LONG((((int)ibuf->foptions.flag) << 8) | (int)ibuf->foptions.quality);
- memcpy(neogeo + 6, &ibuf_ftype, 4);
+ memcpy(neogeo + 6, &ibuf_foptions, 4);
jpeg_write_marker(cinfo, 0xe1, (JOCTET *) neogeo, 10);
if (ibuf->metadata) {
+ IDProperty *prop;
/* key + max value + "Blender" */
text = MEM_mallocN(530, "stamp info read");
- iptr = ibuf->metadata;
- while (iptr) {
- if (!strcmp(iptr->key, "None")) {
- jpeg_write_marker(cinfo, JPEG_COM, (JOCTET *) iptr->value, strlen(iptr->value) + 1);
- goto next_stamp_info;
- }
+ for (prop = ibuf->metadata->data.group.first; prop; prop = prop->next) {
+ if (prop->type == IDP_STRING) {
+ int text_len;
+ if (!strcmp(prop->name, "None")) {
+ jpeg_write_marker(cinfo, JPEG_COM, (JOCTET *) IDP_String(prop), prop->len + 1);
+ }
- /*
- * The JPEG format don't support a pair "key/value"
- * like PNG, so we "encode" the stamp in a
- * single string:
- * "Blender:key:value"
- *
- * The first "Blender" is a simple identify to help
- * in the read process.
- */
- sprintf(text, "Blender:%s:%s", iptr->key, iptr->value);
- jpeg_write_marker(cinfo, JPEG_COM, (JOCTET *) text, strlen(text) + 1);
-next_stamp_info:
- iptr = iptr->next;
+ /*
+ * The JPEG format don't support a pair "key/value"
+ * like PNG, so we "encode" the stamp in a
+ * single string:
+ * "Blender:key:value"
+ *
+ * The first "Blender" is a simple identify to help
+ * in the read process.
+ */
+ text_len = sprintf(text, "Blender:%s:%s", prop->name, IDP_String(prop));
+ jpeg_write_marker(cinfo, JPEG_COM, (JOCTET *) text, text_len + 1);
+ }
}
MEM_freeN(text);
}
@@ -561,7 +563,7 @@ static int init_jpeg(FILE *outfile, struct jpeg_compress_struct *cinfo, struct I
{
int quality;
- quality = ibuf->ftype & 0xff;
+ quality = ibuf->foptions.quality;
if (quality <= 0) quality = jpeg_default_quality;
if (quality > 100) quality = 100;
@@ -686,6 +688,7 @@ static int save_jstjpeg(const char *name, struct ImBuf *ibuf)
tbuf = IMB_allocImBuf(ibuf->x, ibuf->y / 2, 24, IB_rect);
tbuf->ftype = ibuf->ftype;
+ tbuf->foptions = ibuf->foptions;
tbuf->flags = ibuf->flags;
oldy = ibuf->y;
diff --git a/source/blender/imbuf/intern/metadata.c b/source/blender/imbuf/intern/metadata.c
index 797d34d118b..134bbe88f15 100644
--- a/source/blender/imbuf/intern/metadata.c
+++ b/source/blender/imbuf/intern/metadata.c
@@ -36,6 +36,8 @@
#include "BLI_utildefines.h"
#include "BLI_string.h"
+#include "BKE_idprop.h"
+
#include "MEM_guardedalloc.h"
#include "IMB_imbuf_types.h"
@@ -47,119 +49,91 @@
void IMB_metadata_free(struct ImBuf *img)
{
- ImMetaData *info;
-
if (!img)
return;
if (!img->metadata) {
return;
}
- info = img->metadata;
- while (info) {
- ImMetaData *next = info->next;
- MEM_freeN(info->key);
- MEM_freeN(info->value);
- MEM_freeN(info);
- info = next;
- }
+
+ IDP_FreeProperty(img->metadata);
+ MEM_freeN(img->metadata);
}
bool IMB_metadata_get_field(struct ImBuf *img, const char *key, char *field, const size_t len)
{
- ImMetaData *info;
+ IDProperty *prop;
+
bool retval = false;
if (!img)
return false;
- if (!img->metadata) {
+ if (!img->metadata)
return false;
- }
- info = img->metadata;
- while (info) {
- if (strcmp(key, info->key) == 0) {
- BLI_strncpy(field, info->value, len);
- retval = true;
- break;
- }
- info = info->next;
+
+ prop = IDP_GetPropertyFromGroup(img->metadata, key);
+
+ if (prop && prop->type == IDP_STRING) {
+ BLI_strncpy(field, IDP_String(prop), len);
+ retval = true;
}
return retval;
}
+void IMB_metadata_copy(struct ImBuf *dimb, struct ImBuf *simb)
+{
+ if (simb->metadata) {
+ dimb->metadata = IDP_CopyProperty(simb->metadata);
+ }
+}
+
bool IMB_metadata_add_field(struct ImBuf *img, const char *key, const char *value)
{
- ImMetaData *info;
- ImMetaData *last;
+ IDProperty *prop;
if (!img)
return false;
if (!img->metadata) {
- img->metadata = MEM_callocN(sizeof(ImMetaData), "ImMetaData");
- info = img->metadata;
+ IDPropertyTemplate val;
+ img->metadata = IDP_New(IDP_GROUP, &val, "metadata");
}
- else {
- info = img->metadata;
- last = info;
- while (info) {
- last = info;
- info = info->next;
- }
- info = MEM_callocN(sizeof(ImMetaData), "ImMetaData");
- last->next = info;
- }
- info->key = BLI_strdup(key);
- info->value = BLI_strdup(value);
- return true;
+
+ prop = IDP_NewString(value, key, 512);
+ return IDP_AddToGroup(img->metadata, prop);
}
bool IMB_metadata_del_field(struct ImBuf *img, const char *key)
{
- ImMetaData *p, *p1;
+ IDProperty *prop;
if ((!img) || (!img->metadata))
return false;
- p = img->metadata;
- p1 = NULL;
- while (p) {
- if (!strcmp(key, p->key)) {
- if (p1)
- p1->next = p->next;
- else
- img->metadata = p->next;
-
- MEM_freeN(p->key);
- MEM_freeN(p->value);
- MEM_freeN(p);
- return true;
- }
- p1 = p;
- p = p->next;
+ prop = IDP_GetPropertyFromGroup(img->metadata, key);
+
+ if (prop) {
+ IDP_FreeFromGroup(img->metadata, prop);
}
return false;
}
bool IMB_metadata_change_field(struct ImBuf *img, const char *key, const char *field)
{
- ImMetaData *p;
+ IDProperty *prop;
if (!img)
return false;
- if (!img->metadata)
- return (IMB_metadata_add_field(img, key, field));
+ prop = (img->metadata) ? IDP_GetPropertyFromGroup(img->metadata, key) : NULL;
- p = img->metadata;
- while (p) {
- if (!strcmp(key, p->key)) {
- MEM_freeN(p->value);
- p->value = BLI_strdup(field);
- return true;
- }
- p = p->next;
+ if (!prop) {
+ return (IMB_metadata_add_field(img, key, field));
+ }
+ else if (prop->type == IDP_STRING) {
+ IDP_AssignString(prop, field, 1024);
+ return true;
+ }
+ else {
+ return false;
}
-
- return (IMB_metadata_add_field(img, key, field));
}
-
diff --git a/source/blender/imbuf/intern/moviecache.c b/source/blender/imbuf/intern/moviecache.c
index 1641bd3089b..4b49076dcd6 100644
--- a/source/blender/imbuf/intern/moviecache.c
+++ b/source/blender/imbuf/intern/moviecache.c
@@ -99,22 +99,22 @@ typedef struct MovieCacheItem {
static unsigned int moviecache_hashhash(const void *keyv)
{
- MovieCacheKey *key = (MovieCacheKey *)keyv;
+ const MovieCacheKey *key = keyv;
return key->cache_owner->hashfp(key->userkey);
}
static bool moviecache_hashcmp(const void *av, const void *bv)
{
- const MovieCacheKey *a = (MovieCacheKey *)av;
- const MovieCacheKey *b = (MovieCacheKey *)bv;
+ const MovieCacheKey *a = av;
+ const MovieCacheKey *b = bv;
return a->cache_owner->cmpfp(a->userkey, b->userkey);
}
static void moviecache_keyfree(void *val)
{
- MovieCacheKey *key = (MovieCacheKey *)val;
+ MovieCacheKey *key = val;
BLI_mempool_free(key->cache_owner->userkeys_pool, key->userkey);
@@ -142,15 +142,16 @@ static void moviecache_valfree(void *val)
static void check_unused_keys(MovieCache *cache)
{
- GHashIterator *iter;
+ GHashIterator gh_iter;
- iter = BLI_ghashIterator_new(cache->hash);
- while (!BLI_ghashIterator_done(iter)) {
- MovieCacheKey *key = BLI_ghashIterator_getKey(iter);
- MovieCacheItem *item = BLI_ghashIterator_getValue(iter);
- int remove = 0;
+ BLI_ghashIterator_init(&gh_iter, cache->hash);
+
+ while (!BLI_ghashIterator_done(&gh_iter)) {
+ const MovieCacheKey *key = BLI_ghashIterator_getKey(&gh_iter);
+ const MovieCacheItem *item = BLI_ghashIterator_getValue(&gh_iter);
+ bool remove;
- BLI_ghashIterator_step(iter);
+ BLI_ghashIterator_step(&gh_iter);
remove = !item->ibuf;
@@ -161,14 +162,12 @@ static void check_unused_keys(MovieCache *cache)
if (remove)
BLI_ghash_remove(cache->hash, key, moviecache_keyfree, moviecache_valfree);
}
-
- BLI_ghashIterator_free(iter);
}
static int compare_int(const void *av, const void *bv)
{
- const int *a = (int *)av;
- const int *b = (int *)bv;
+ const int *a = av;
+ const int *b = bv;
return *a - *b;
}
@@ -363,8 +362,7 @@ static void do_moviecache_put(MovieCache *cache, void *userkey, ImBuf *ibuf, boo
item->priority_data = cache->getprioritydatafp(userkey);
}
- BLI_ghash_remove(cache->hash, key, moviecache_keyfree, moviecache_valfree);
- BLI_ghash_insert(cache->hash, key, item);
+ BLI_ghash_reinsert(cache->hash, key, item, moviecache_keyfree, moviecache_valfree);
if (cache->last_userkey) {
memcpy(cache->last_userkey, userkey, cache->keysize);
@@ -474,16 +472,17 @@ void IMB_moviecache_free(MovieCache *cache)
void IMB_moviecache_cleanup(MovieCache *cache, bool (cleanup_check_cb) (ImBuf *ibuf, void *userkey, void *userdata), void *userdata)
{
- GHashIterator *iter;
+ GHashIterator gh_iter;
check_unused_keys(cache);
- iter = BLI_ghashIterator_new(cache->hash);
- while (!BLI_ghashIterator_done(iter)) {
- MovieCacheKey *key = BLI_ghashIterator_getKey(iter);
- MovieCacheItem *item = BLI_ghashIterator_getValue(iter);
+ BLI_ghashIterator_init(&gh_iter, cache->hash);
+
+ while (!BLI_ghashIterator_done(&gh_iter)) {
+ MovieCacheKey *key = BLI_ghashIterator_getKey(&gh_iter);
+ MovieCacheItem *item = BLI_ghashIterator_getValue(&gh_iter);
- BLI_ghashIterator_step(iter);
+ BLI_ghashIterator_step(&gh_iter);
if (cleanup_check_cb(item->ibuf, key->userkey, userdata)) {
PRINT("%s: cache '%s' remove item %p\n", __func__, cache->name, item);
@@ -491,8 +490,6 @@ void IMB_moviecache_cleanup(MovieCache *cache, bool (cleanup_check_cb) (ImBuf *i
BLI_ghash_remove(cache->hash, key, moviecache_keyfree, moviecache_valfree);
}
}
-
- BLI_ghashIterator_free(iter);
}
/* get segments of cached frames. useful for debugging cache policies */
@@ -519,13 +516,12 @@ void IMB_moviecache_get_cache_segments(MovieCache *cache, int proxy, int render_
int totframe = BLI_ghash_size(cache->hash);
int *frames = MEM_callocN(totframe * sizeof(int), "movieclip cache frames");
int a, totseg = 0;
- GHashIterator *iter;
+ GHashIterator gh_iter;
- iter = BLI_ghashIterator_new(cache->hash);
a = 0;
- while (!BLI_ghashIterator_done(iter)) {
- MovieCacheKey *key = BLI_ghashIterator_getKey(iter);
- MovieCacheItem *item = BLI_ghashIterator_getValue(iter);
+ GHASH_ITER(gh_iter, cache->hash) {
+ MovieCacheKey *key = BLI_ghashIterator_getKey(&gh_iter);
+ MovieCacheItem *item = BLI_ghashIterator_getValue(&gh_iter);
int framenr, curproxy, curflags;
if (item->ibuf) {
@@ -534,12 +530,8 @@ void IMB_moviecache_get_cache_segments(MovieCache *cache, int proxy, int render_
if (curproxy == proxy && curflags == render_flags)
frames[a++] = framenr;
}
-
- BLI_ghashIterator_step(iter);
}
- BLI_ghashIterator_free(iter);
-
qsort(frames, totframe, sizeof(int), compare_int);
/* count */
diff --git a/source/blender/imbuf/intern/oiio/CMakeLists.txt b/source/blender/imbuf/intern/oiio/CMakeLists.txt
index 5fb8f11602e..c873fa3f32d 100644
--- a/source/blender/imbuf/intern/oiio/CMakeLists.txt
+++ b/source/blender/imbuf/intern/oiio/CMakeLists.txt
@@ -47,6 +47,7 @@ set(SRC
if(WITH_OPENIMAGEIO)
list(APPEND INC_SYS
${OPENIMAGEIO_INCLUDE_DIRS}
+ ${BOOST_INCLUDE_DIR}
)
add_definitions(-DWITH_OPENIMAGEIO)
endif()
diff --git a/source/blender/imbuf/intern/oiio/openimageio_api.cpp b/source/blender/imbuf/intern/oiio/openimageio_api.cpp
index 6e3f97a4902..0a2e8742ba8 100644
--- a/source/blender/imbuf/intern/oiio/openimageio_api.cpp
+++ b/source/blender/imbuf/intern/oiio/openimageio_api.cpp
@@ -182,7 +182,7 @@ int imb_is_a_photoshop(const char *filename)
return BLI_testextensie_array(filename, photoshop_extension);
}
-int imb_save_photoshop(struct ImBuf *ibuf, const char *name, int flags)
+int imb_save_photoshop(struct ImBuf *ibuf, const char * /*name*/, int flags)
{
if (flags & IB_mem) {
std::cerr << __func__ << ": Photoshop PSD-save: Create PSD in memory"
@@ -268,7 +268,7 @@ struct ImBuf *imb_load_photoshop(const char *filename, int flags, char colorspac
return NULL;
/* ImBuf always needs 4 channels */
- ibuf->ftype = PSD;
+ ibuf->ftype = IMB_FTYPE_PSD;
ibuf->channels = 4;
ibuf->planes = (3 + (is_alpha ? 1 : 0)) * 4 << basesize;
diff --git a/source/blender/imbuf/intern/openexr/openexr_api.cpp b/source/blender/imbuf/intern/openexr/openexr_api.cpp
index ba1bda640a6..e3c02736755 100644
--- a/source/blender/imbuf/intern/openexr/openexr_api.cpp
+++ b/source/blender/imbuf/intern/openexr/openexr_api.cpp
@@ -38,6 +38,8 @@
#include <errno.h>
#include <algorithm>
+#include "DNA_scene_types.h" /* For OpenEXR compression constants */
+
#include <openexr_api.h>
#if defined (WIN32) && !defined(FREE_WINDOWS)
@@ -60,6 +62,9 @@ _CRTIMP void __cdecl _invalid_parameter_noinfo(void)
#include "BLI_math_color.h"
#include "BLI_threads.h"
+#include "BKE_idprop.h"
+#include "BKE_image.h"
+
#include "IMB_imbuf_types.h"
#include "IMB_imbuf.h"
#include "IMB_allocimbuf.h"
@@ -88,9 +93,32 @@ _CRTIMP void __cdecl _invalid_parameter_noinfo(void)
#include <ImfStringAttribute.h>
#include <ImfStandardAttributes.h>
+/* multiview/multipart */
+#include <ImfMultiView.h>
+#include <ImfMultiPartInputFile.h>
+#include <ImfInputPart.h>
+#include <ImfOutputPart.h>
+#include <ImfMultiPartOutputFile.h>
+#include <ImfTiledOutputPart.h>
+#include <ImfPartType.h>
+#include <ImfPartHelper.h>
+
using namespace Imf;
using namespace Imath;
+extern "C"
+{
+/* prototype */
+static struct ExrPass *imb_exr_get_pass(ListBase *lb, char *passname);
+static bool exr_has_multiview(MultiPartInputFile& file);
+static bool exr_has_multipart_file(MultiPartInputFile& file);
+static bool exr_has_alpha(MultiPartInputFile& file);
+static bool exr_has_zbuffer(MultiPartInputFile& file);
+static void exr_printf(const char *__restrict format, ...);
+static void imb_exr_type_by_channels(ChannelList& channels, StringVector& views,
+ bool *r_singlelayer, bool *r_multilayer, bool *r_multiview);
+}
+
/* Memory Input Stream */
class Mem_IStream : public Imf::IStream
@@ -274,7 +302,7 @@ extern "C"
* Test presence of OpenEXR file.
* \param mem pointer to loaded OpenEXR bitstream
*/
-int imb_is_a_openexr(unsigned char *mem)
+int imb_is_a_openexr(const unsigned char *mem)
{
return Imf::isImfMagic((const char *)mem);
}
@@ -282,21 +310,38 @@ int imb_is_a_openexr(unsigned char *mem)
static void openexr_header_compression(Header *header, int compression)
{
switch (compression) {
- case 0:
+ case R_IMF_EXR_CODEC_NONE:
header->compression() = NO_COMPRESSION;
break;
- case 1:
+ case R_IMF_EXR_CODEC_PXR24:
header->compression() = PXR24_COMPRESSION;
break;
- case 2:
+ case R_IMF_EXR_CODEC_ZIP:
header->compression() = ZIP_COMPRESSION;
break;
- case 3:
+ case R_IMF_EXR_CODEC_PIZ:
header->compression() = PIZ_COMPRESSION;
break;
- case 4:
+ case R_IMF_EXR_CODEC_RLE:
header->compression() = RLE_COMPRESSION;
break;
+ case R_IMF_EXR_CODEC_ZIPS:
+ header->compression() = ZIPS_COMPRESSION;
+ break;
+ case R_IMF_EXR_CODEC_B44:
+ header->compression() = B44_COMPRESSION;
+ break;
+ case R_IMF_EXR_CODEC_B44A:
+ header->compression() = B44A_COMPRESSION;
+ break;
+#if OPENEXR_VERSION_MAJOR >= 2 && OPENEXR_VERSION_MINOR >= 2
+ case R_IMF_EXR_CODEC_DWAA:
+ header->compression() = DWAA_COMPRESSION;
+ break;
+ case R_IMF_EXR_CODEC_DWAB:
+ header->compression() = DWAB_COMPRESSION;
+ break;
+#endif
default:
header->compression() = ZIP_COMPRESSION;
break;
@@ -305,37 +350,66 @@ static void openexr_header_compression(Header *header, int compression)
static void openexr_header_metadata(Header *header, struct ImBuf *ibuf)
{
- ImMetaData *info;
+ if (ibuf->metadata) {
+ IDProperty *prop;
- for (info = ibuf->metadata; info; info = info->next)
- header->insert(info->key, StringAttribute(info->value));
+ for (prop = (IDProperty *)ibuf->metadata->data.group.first; prop; prop = prop->next) {
+ if (prop->type == IDP_STRING) {
+ header->insert(prop->name, StringAttribute(IDP_String(prop)));
+ }
+ }
+ }
if (ibuf->ppm[0] > 0.0)
addXDensity(*header, ibuf->ppm[0] / 39.3700787); /* 1 meter = 39.3700787 inches */
}
-static int imb_save_openexr_half(struct ImBuf *ibuf, const char *name, int flags)
+static void openexr_header_metadata_callback(void *data, const char *propname, char *prop, int UNUSED(len))
+{
+ Header *header = (Header *)data;
+ header->insert(propname, StringAttribute(prop));
+}
+
+
+static bool imb_save_openexr_half(ImBuf *ibuf, const char *name, const int flags, const size_t totviews,
+ const char * (*getview)(void *base, size_t view_id),
+ ImBuf * (*getbuffer)(void *base, const size_t view_id))
{
const int channels = ibuf->channels;
- const int is_alpha = (channels >= 4) && (ibuf->planes == 32);
- const int is_zbuf = (flags & IB_zbuffloat) && ibuf->zbuf_float != NULL; /* summarize */
+ const bool is_alpha = (channels >= 4) && (ibuf->planes == 32);
+ const bool is_zbuf = (flags & IB_zbuffloat) && ibuf->zbuf_float != NULL; /* summarize */
const int width = ibuf->x;
const int height = ibuf->y;
+ const bool is_multiview = (flags & IB_multiview) && ibuf->userdata;
+
+ BLI_assert((!is_multiview) || (getview && getbuffer));
+
+ std::vector <string> views;
+ size_t view_id;
try
{
Header header(width, height);
- openexr_header_compression(&header, ibuf->ftype & OPENEXR_COMPRESS);
+ openexr_header_compression(&header, ibuf->foptions.flag & OPENEXR_COMPRESS);
openexr_header_metadata(&header, ibuf);
- header.channels().insert("R", Channel(HALF));
- header.channels().insert("G", Channel(HALF));
- header.channels().insert("B", Channel(HALF));
- if (is_alpha)
- header.channels().insert("A", Channel(HALF));
- if (is_zbuf) // z we do as float always
- header.channels().insert("Z", Channel(Imf::FLOAT));
+ /* create views when possible */
+ for (view_id = 0; view_id < totviews; view_id ++)
+ views.push_back(is_multiview ? getview(ibuf->userdata, view_id) : "");
+
+ if (is_multiview)
+ addMultiView(header, views);
+
+ for (view_id = 0; view_id < totviews; view_id ++) {
+ header.channels().insert(insertViewName("R", views, view_id), Channel(HALF));
+ header.channels().insert(insertViewName("G", views, view_id), Channel(HALF));
+ header.channels().insert(insertViewName("B", views, view_id), Channel(HALF));
+ if (is_alpha)
+ header.channels().insert(insertViewName("A", views, view_id), Channel(HALF));
+ if (is_zbuf) // z we do as float always
+ header.channels().insert(insertViewName("Z", views, view_id), Channel(Imf::FLOAT));
+ }
FrameBuffer frameBuffer;
@@ -344,90 +418,115 @@ static int imb_save_openexr_half(struct ImBuf *ibuf, const char *name, int flags
OutputFile file(file_stream, header);
/* we store first everything in half array */
- RGBAZ *pixels = new RGBAZ[height * width];
- RGBAZ *to = pixels;
+ RGBAZ *pixels = new RGBAZ[height * width * totviews];
int xstride = sizeof(RGBAZ);
int ystride = xstride * width;
- /* indicate used buffers */
- frameBuffer.insert("R", Slice(HALF, (char *) &pixels[0].r, xstride, ystride));
- frameBuffer.insert("G", Slice(HALF, (char *) &pixels[0].g, xstride, ystride));
- frameBuffer.insert("B", Slice(HALF, (char *) &pixels[0].b, xstride, ystride));
- if (is_alpha)
- frameBuffer.insert("A", Slice(HALF, (char *) &pixels[0].a, xstride, ystride));
- if (is_zbuf)
- frameBuffer.insert("Z", Slice(Imf::FLOAT, (char *)(ibuf->zbuf_float + (height - 1) * width),
- sizeof(float), sizeof(float) * -width));
- if (ibuf->rect_float) {
- float *from;
-
- for (int i = ibuf->y - 1; i >= 0; i--) {
- from = ibuf->rect_float + channels * i * width;
-
- for (int j = ibuf->x; j > 0; j--) {
- to->r = from[0];
- to->g = (channels >= 2) ? from[1] : from[0];
- to->b = (channels >= 3) ? from[2] : from[0];
- to->a = (channels >= 4) ? from[3] : 1.0f;
- to++; from += channels;
+ for (view_id = 0; view_id < totviews; view_id ++) {
+ ImBuf *view_ibuf = is_multiview ? getbuffer(ibuf->userdata, view_id) : ibuf;
+ const size_t offset = view_id * width * height;
+ RGBAZ *to = pixels + offset;
+
+ /* indicate used buffers */
+ frameBuffer.insert(insertViewName("R", views, view_id), Slice(HALF, (char *) &pixels[offset].r, xstride, ystride));
+ frameBuffer.insert(insertViewName("G", views, view_id), Slice(HALF, (char *) &pixels[offset].g, xstride, ystride));
+ frameBuffer.insert(insertViewName("B", views, view_id), Slice(HALF, (char *) &pixels[offset].b, xstride, ystride));
+ if (is_alpha)
+ frameBuffer.insert(insertViewName("A", views, view_id), Slice(HALF, (char *) &pixels[offset].a, xstride, ystride));
+ if (is_zbuf)
+ frameBuffer.insert(insertViewName("Z", views, view_id), Slice(Imf::FLOAT, (char *)(view_ibuf->zbuf_float + (height - 1) * width),
+ sizeof(float), sizeof(float) * -width));
+ if (view_ibuf->rect_float) {
+ float *from;
+
+ for (int i = view_ibuf->y - 1; i >= 0; i--) {
+ from = view_ibuf->rect_float + channels * i * width;
+
+ for (int j = view_ibuf->x; j > 0; j--) {
+ to->r = from[0];
+ to->g = (channels >= 2) ? from[1] : from[0];
+ to->b = (channels >= 3) ? from[2] : from[0];
+ to->a = (channels >= 4) ? from[3] : 1.0f;
+ to++; from += channels;
+ }
}
}
- }
- else {
- unsigned char *from;
-
- for (int i = ibuf->y - 1; i >= 0; i--) {
- from = (unsigned char *)ibuf->rect + 4 * i * width;
-
- for (int j = ibuf->x; j > 0; j--) {
- to->r = srgb_to_linearrgb((float)from[0] / 255.0f);
- to->g = srgb_to_linearrgb((float)from[1] / 255.0f);
- to->b = srgb_to_linearrgb((float)from[2] / 255.0f);
- to->a = channels >= 4 ? (float)from[3] / 255.0f : 1.0f;
- to++; from += 4;
+ else {
+ unsigned char *from;
+
+ for (int i = view_ibuf->y - 1; i >= 0; i--) {
+ from = (unsigned char *)view_ibuf->rect + 4 * i * width;
+
+ for (int j = view_ibuf->x; j > 0; j--) {
+ to->r = srgb_to_linearrgb((float)from[0] / 255.0f);
+ to->g = srgb_to_linearrgb((float)from[1] / 255.0f);
+ to->b = srgb_to_linearrgb((float)from[2] / 255.0f);
+ to->a = channels >= 4 ? (float)from[3] / 255.0f : 1.0f;
+ to++; from += 4;
+ }
}
}
+
+ if (is_multiview)
+ IMB_freeImBuf(view_ibuf);
}
-// printf("OpenEXR-save: Writing OpenEXR file of height %d.\n", height);
+ exr_printf("OpenEXR-save: Writing OpenEXR file of height %d.\n", height);
file.setFrameBuffer(frameBuffer);
file.writePixels(height);
delete[] pixels;
}
- catch (const std::exception &exc)
+ catch (const std::exception& exc)
{
printf("OpenEXR-save: ERROR: %s\n", exc.what());
- return (0);
+ return false;
}
- return (1);
+ return true;
}
-static int imb_save_openexr_float(struct ImBuf *ibuf, const char *name, int flags)
+static bool imb_save_openexr_float(ImBuf *ibuf, const char *name, const int flags, const size_t totviews,
+ const char * (*getview)(void *base, const size_t view_id),
+ ImBuf * (*getbuffer)(void *base, const size_t view_id))
{
const int channels = ibuf->channels;
- const int is_alpha = (channels >= 4) && (ibuf->planes == 32);
- const int is_zbuf = (flags & IB_zbuffloat) && ibuf->zbuf_float != NULL; /* summarize */
+ const bool is_alpha = (channels >= 4) && (ibuf->planes == 32);
+ const bool is_zbuf = (flags & IB_zbuffloat) && ibuf->zbuf_float != NULL; /* summarize */
const int width = ibuf->x;
const int height = ibuf->y;
+ const bool is_multiview = (flags & IB_multiview) && ibuf->userdata;
+
+ BLI_assert((!is_multiview) || (getview && getbuffer));
+
+ std::vector <string> views;
+ size_t view_id;
try
{
Header header(width, height);
- openexr_header_compression(&header, ibuf->ftype & OPENEXR_COMPRESS);
+ openexr_header_compression(&header, ibuf->foptions.flag & OPENEXR_COMPRESS);
openexr_header_metadata(&header, ibuf);
- header.channels().insert("R", Channel(Imf::FLOAT));
- header.channels().insert("G", Channel(Imf::FLOAT));
- header.channels().insert("B", Channel(Imf::FLOAT));
- if (is_alpha)
- header.channels().insert("A", Channel(Imf::FLOAT));
- if (is_zbuf)
- header.channels().insert("Z", Channel(Imf::FLOAT));
+ /* create views when possible */
+ for (view_id = 0; view_id < totviews; view_id ++)
+ views.push_back(is_multiview ? getview(ibuf->userdata, view_id) : "");
+
+ if (is_multiview)
+ addMultiView(header, views);
+
+ for (view_id = 0; view_id < totviews; view_id ++) {
+ header.channels().insert(insertViewName("R", views, view_id), Channel(Imf::FLOAT));
+ header.channels().insert(insertViewName("G", views, view_id), Channel(Imf::FLOAT));
+ header.channels().insert(insertViewName("B", views, view_id), Channel(Imf::FLOAT));
+ if (is_alpha)
+ header.channels().insert(insertViewName("A", views, view_id), Channel(Imf::FLOAT));
+ if (is_zbuf)
+ header.channels().insert(insertViewName("Z", views, view_id), Channel(Imf::FLOAT));
+ }
FrameBuffer frameBuffer;
@@ -437,37 +536,41 @@ static int imb_save_openexr_float(struct ImBuf *ibuf, const char *name, int flag
int xstride = sizeof(float) * channels;
int ystride = -xstride * width;
- float *rect[4] = {NULL, NULL, NULL, NULL};
- /* last scanline, stride negative */
- rect[0] = ibuf->rect_float + channels * (height - 1) * width;
- rect[1] = (channels >= 2) ? rect[0] + 1 : rect[0];
- rect[2] = (channels >= 3) ? rect[0] + 2 : rect[0];
- rect[3] = (channels >= 4) ? rect[0] + 3 : rect[0]; /* red as alpha, is this needed since alpha isn't written? */
-
- frameBuffer.insert("R", Slice(Imf::FLOAT, (char *)rect[0], xstride, ystride));
- frameBuffer.insert("G", Slice(Imf::FLOAT, (char *)rect[1], xstride, ystride));
- frameBuffer.insert("B", Slice(Imf::FLOAT, (char *)rect[2], xstride, ystride));
- if (is_alpha)
- frameBuffer.insert("A", Slice(Imf::FLOAT, (char *)rect[3], xstride, ystride));
- if (is_zbuf)
- frameBuffer.insert("Z", Slice(Imf::FLOAT, (char *) (ibuf->zbuf_float + (height - 1) * width),
- sizeof(float), sizeof(float) * -width));
+ for (view_id = 0; view_id < totviews; view_id ++) {
+ float *rect[4] = {NULL, NULL, NULL, NULL};
+ ImBuf *view_ibuf = is_multiview ? getbuffer(ibuf->userdata, view_id) : ibuf;
+
+ /* last scanline, stride negative */
+ rect[0] = view_ibuf->rect_float + channels * (height - 1) * width;
+ rect[1] = (channels >= 2) ? rect[0] + 1 : rect[0];
+ rect[2] = (channels >= 3) ? rect[0] + 2 : rect[0];
+ rect[3] = (channels >= 4) ? rect[0] + 3 : rect[0]; /* red as alpha, is this needed since alpha isn't written? */
+
+ frameBuffer.insert(insertViewName("R", views, view_id), Slice(Imf::FLOAT, (char *)rect[0], xstride, ystride));
+ frameBuffer.insert(insertViewName("G", views, view_id), Slice(Imf::FLOAT, (char *)rect[1], xstride, ystride));
+ frameBuffer.insert(insertViewName("B", views, view_id), Slice(Imf::FLOAT, (char *)rect[2], xstride, ystride));
+ if (is_alpha)
+ frameBuffer.insert(insertViewName("A", views, view_id), Slice(Imf::FLOAT, (char *)rect[3], xstride, ystride));
+ if (is_zbuf)
+ frameBuffer.insert(insertViewName("Z", views, view_id), Slice(Imf::FLOAT, (char *) (view_ibuf->zbuf_float + (height - 1) * width),
+ sizeof(float), sizeof(float) * -width));
+
+ if (is_multiview)
+ IMB_freeImBuf(view_ibuf);
+ }
file.setFrameBuffer(frameBuffer);
file.writePixels(height);
}
- catch (const std::exception &exc)
+ catch (const std::exception& exc)
{
printf("OpenEXR-save: ERROR: %s\n", exc.what());
-
- return (0);
+ return false;
}
- return (1);
- // printf("OpenEXR-save: Done.\n");
+ return true;
}
-
int imb_save_openexr(struct ImBuf *ibuf, const char *name, int flags)
{
if (flags & IB_mem) {
@@ -477,17 +580,49 @@ int imb_save_openexr(struct ImBuf *ibuf, const char *name, int flags)
return(0);
}
- if (ibuf->ftype & OPENEXR_HALF)
- return imb_save_openexr_half(ibuf, name, flags);
+ if (ibuf->foptions.flag & OPENEXR_HALF)
+ return (int) imb_save_openexr_half(ibuf, name, flags, 1, NULL, NULL);
+ else {
+ /* when no float rect, we save as half (16 bits is sufficient) */
+ if (ibuf->rect_float == NULL)
+ return (int) imb_save_openexr_half(ibuf, name, flags, 1, NULL, NULL);
+ else
+ return (int) imb_save_openexr_float(ibuf, name, flags, 1, NULL, NULL);
+ }
+}
+
+static bool imb_save_openexr_multiview(ImBuf *ibuf, const char *name, const int flags, const size_t totviews,
+ const char * (*getview)(void *base, const size_t view_id),
+ ImBuf * (*getbuffer)(void *base, const size_t view_id))
+{
+ if (flags & IB_mem) {
+ printf("OpenEXR-save: Create multiview EXR in memory CURRENTLY NOT SUPPORTED !\n");
+ imb_addencodedbufferImBuf(ibuf);
+ ibuf->encodedsize = 0;
+ return false;
+ }
+
+ if (ibuf->foptions.flag & OPENEXR_HALF)
+ return imb_save_openexr_half(ibuf, name, flags, totviews, getview, getbuffer);
else {
/* when no float rect, we save as half (16 bits is sufficient) */
if (ibuf->rect_float == NULL)
- return imb_save_openexr_half(ibuf, name, flags);
+ return imb_save_openexr_half(ibuf, name, flags, totviews, getview, getbuffer);
else
- return imb_save_openexr_float(ibuf, name, flags);
+ return imb_save_openexr_float(ibuf, name, flags, totviews, getview, getbuffer);
}
}
+/* Save single-layer multiview OpenEXR
+ * If we have more multiview formats in the future, the function below could be incorporated
+ * in our ImBuf write functions, meanwhile this is an OpenEXR special case only */
+bool IMB_exr_multiview_save(ImBuf *ibuf, const char *name, const int flags, const size_t totviews,
+ const char * (*getview)(void *base, size_t view_id),
+ ImBuf * (*getbuffer)(void *base, const size_t view_id))
+{
+ return imb_save_openexr_multiview(ibuf, name, flags, totviews, getview, getbuffer);
+}
+
/* ********************* Nicer API, MultiLayer and with Tile file support ************************************ */
/* naming rules:
@@ -501,30 +636,39 @@ static ListBase exrhandles = {NULL, NULL};
typedef struct ExrHandle {
struct ExrHandle *next, *prev;
+ char name[FILE_MAX];
- IFileStream *ifile_stream;
- InputFile *ifile;
+ IStream *ifile_stream;
+ MultiPartInputFile *ifile;
OFileStream *ofile_stream;
- TiledOutputFile *tofile;
+ MultiPartOutputFile *mpofile;
OutputFile *ofile;
int tilex, tiley;
int width, height;
int mipmap;
+ StringVector *multiView; /* it needs to be a pointer due to Windows release builds of EXR2.0 segfault when opening EXR bug */
+ int parts;
+
ListBase channels; /* flattened out, ExrChannel */
ListBase layers; /* hierarchical, pointing in end to ExrChannel */
+
+ int num_half_channels; /* used during filr save, allows faster temporary buffers allocation */
} ExrHandle;
/* flattened out channel */
typedef struct ExrChannel {
struct ExrChannel *next, *prev;
- char name[EXR_TOT_MAXNAME + 1]; /* full name of layer+pass */
+ char name[EXR_TOT_MAXNAME + 1]; /* full name with everything */
+ struct MultiViewChannelName *m; /* struct to store all multipart channel info */
int xstride, ystride; /* step to next pixel, to next scanline */
float *rect; /* first pointer to write in */
char chan_id; /* quick lookup of channel char */
+ int view_id; /* quick lookup of channel view */
+ bool use_half_float; /* when saving use half float for file storage */
} ExrChannel;
@@ -536,6 +680,10 @@ typedef struct ExrPass {
float *rect;
struct ExrChannel *chan[EXR_PASS_MAXCHAN];
char chan_id[EXR_PASS_MAXCHAN];
+
+ char internal_name[EXR_PASS_MAXNAME]; /* name with no view */
+ char view[EXR_VIEW_MAXNAME];
+ int view_id;
} ExrPass;
typedef struct ExrLayer {
@@ -549,40 +697,153 @@ typedef struct ExrLayer {
void *IMB_exr_get_handle(void)
{
ExrHandle *data = (ExrHandle *)MEM_callocN(sizeof(ExrHandle), "exr handle");
+ data->multiView = new StringVector();
+
BLI_addtail(&exrhandles, data);
return data;
}
+void *IMB_exr_get_handle_name(const char *name)
+{
+ ExrHandle *data = (ExrHandle *) BLI_rfindstring(&exrhandles, name, offsetof(ExrHandle, name));
+
+ if (data == NULL) {
+ data = (ExrHandle *)IMB_exr_get_handle();
+ BLI_strncpy(data->name, name, strlen(name) + 1);
+ }
+ return data;
+}
+
+/* multiview functions */
+} // extern "C"
+
+extern "C"
+{
+
+void IMB_exr_add_view(void *handle, const char *name)
+{
+ ExrHandle *data = (ExrHandle *)handle;
+ data->multiView->push_back(name);
+}
+
+static int imb_exr_get_multiView_id(StringVector& views, const std::string& name)
+{
+ int count = 0;
+ for (StringVector::const_iterator i = views.begin(); count < views.size(); ++i) {
+ if (name == *i)
+ return count;
+ else
+ count ++;
+ }
+
+ /* no views or wrong name */
+ return -1;
+}
+
+static void imb_exr_get_views(MultiPartInputFile& file, StringVector& views)
+{
+ if (exr_has_multipart_file(file) == false) {
+ if (exr_has_multiview(file)) {
+ StringVector sv = multiView(file.header(0));
+ for (StringVector::const_iterator i = sv.begin(); i != sv.end(); ++i)
+ views.push_back(*i);
+ }
+ }
+
+ else {
+ for (int p = 0; p < file.parts(); p++) {
+ std::string view = "";
+ if (file.header(p).hasView())
+ view = file.header(p).view();
+
+ if (imb_exr_get_multiView_id(views, view) == -1)
+ views.push_back(view);
+ }
+ }
+}
+
+/* Multilayer Blender files have the view name in all the passes (even the default view one) */
+static void imb_exr_insert_view_name(char *name_full, const char *passname, const char *viewname)
+{
+ BLI_assert(!ELEM(name_full, passname, viewname));
+
+ if (viewname == NULL || viewname[0] == '\0') {
+ BLI_strncpy(name_full, passname, sizeof(((ExrChannel *)NULL)->name));
+ return;
+ }
+
+ const char delims[] = {'.', '\0'};
+ const char *sep;
+ const char *token;
+ size_t len;
+
+ len = BLI_str_rpartition(passname, delims, &sep, &token);
+
+ if (sep) {
+ BLI_snprintf(name_full, EXR_PASS_MAXNAME, "%.*s.%s.%s", (int)len, passname, viewname, token);
+ }
+ else {
+ BLI_snprintf(name_full, EXR_PASS_MAXNAME, "%s.%s", passname, viewname);
+ }
+}
+
/* adds flattened ExrChannels */
/* xstride, ystride and rect can be done in set_channel too, for tile writing */
-void IMB_exr_add_channel(void *handle, const char *layname, const char *passname, int xstride, int ystride, float *rect)
+/* passname does not include view */
+void IMB_exr_add_channel(void *handle,
+ const char *layname, const char *passname, const char *viewname,
+ int xstride, int ystride, float *rect,
+ bool use_half_float)
{
ExrHandle *data = (ExrHandle *)handle;
ExrChannel *echan;
- echan = (ExrChannel *)MEM_callocN(sizeof(ExrChannel), "exr tile channel");
+ echan = (ExrChannel *)MEM_callocN(sizeof(ExrChannel), "exr channel");
+ echan->m = new MultiViewChannelName ();
- if (layname) {
- char lay[EXR_LAY_MAXNAME + 1], pass[EXR_PASS_MAXNAME + 1];
- BLI_strncpy(lay, layname, EXR_LAY_MAXNAME);
- BLI_strncpy(pass, passname, EXR_PASS_MAXNAME);
+ if (layname && layname[0] != '\0') {
+ echan->m->name = layname;
+ echan->m->name.append(".");
+ echan->m->name.append(passname);
+ }
+ else {
+ echan->m->name.assign(passname);
+ }
+
+ echan->m->internal_name = echan->m->name;
+
+ echan->m->view.assign(viewname ? viewname : "");
- BLI_snprintf(echan->name, sizeof(echan->name), "%s.%s", lay, pass);
+ /* quick look up */
+ echan->view_id = std::max(0, imb_exr_get_multiView_id(*data->multiView, echan->m->view));
+
+ /* name has to be unique, thus it's a combination of layer, pass, view, and channel */
+ if (layname && layname[0] != '\0') {
+ imb_exr_insert_view_name(echan->name, echan->m->name.c_str(), echan->m->view.c_str());
+ }
+ else if (data->multiView->size() > 1) {
+ std::string raw_name = insertViewName(echan->m->name, *data->multiView, echan->view_id);
+ BLI_strncpy(echan->name, raw_name.c_str(), sizeof(echan->name));
}
else {
- BLI_strncpy(echan->name, passname, EXR_TOT_MAXNAME - 1);
+ BLI_strncpy(echan->name, echan->m->name.c_str(), sizeof(echan->name));
}
echan->xstride = xstride;
echan->ystride = ystride;
echan->rect = rect;
+ echan->use_half_float = use_half_float;
- // printf("added channel %s\n", echan->name);
+ if (echan->use_half_float) {
+ data->num_half_channels++;
+ }
+
+ exr_printf("added channel %s\n", echan->name);
BLI_addtail(&data->channels, echan);
}
-/* only used for writing temp. render results (not image files) */
-int IMB_exr_begin_write(void *handle, const char *filename, int width, int height, int compress)
+/* used for output files (from RenderResult) (single and multilayer, single and multiview) */
+int IMB_exr_begin_write(void *handle, const char *filename, int width, int height, int compress, const StampData *stamp)
{
ExrHandle *data = (ExrHandle *)handle;
Header header(width, height);
@@ -591,14 +852,24 @@ int IMB_exr_begin_write(void *handle, const char *filename, int width, int heigh
data->width = width;
data->height = height;
- for (echan = (ExrChannel *)data->channels.first; echan; echan = echan->next)
- header.channels().insert(echan->name, Channel(Imf::FLOAT));
+ bool is_singlelayer, is_multilayer, is_multiview;
+
+ for (echan = (ExrChannel *)data->channels.first; echan; echan = echan->next) {
+ header.channels().insert(echan->name,
+ Channel(echan->use_half_float ? Imf::HALF : Imf::FLOAT));
+ }
openexr_header_compression(&header, compress);
- // openexr_header_metadata(&header, ibuf); // no imbuf. cant write
+ BKE_stamp_info_callback(&header, const_cast<StampData *>(stamp), openexr_header_metadata_callback, false);
/* header.lineOrder() = DECREASING_Y; this crashes in windows for file read! */
- header.insert("BlenderMultiChannel", StringAttribute("Blender V2.55.1 and newer"));
+ imb_exr_type_by_channels(header.channels(), *data->multiView, &is_singlelayer, &is_multilayer, &is_multiview);
+
+ if (is_multilayer)
+ header.insert("BlenderMultiChannel", StringAttribute("Blender V2.55.1 and newer"));
+
+ if (is_multiview)
+ addMultiView(header, *data->multiView);
/* avoid crash/abort when we don't have permission to write here */
/* manually create ofstream, so we can handle utf-8 filepaths on windows */
@@ -606,7 +877,7 @@ int IMB_exr_begin_write(void *handle, const char *filename, int width, int heigh
data->ofile_stream = new OFileStream(filename);
data->ofile = new OutputFile(*(data->ofile_stream), header);
}
- catch (const std::exception &exc) {
+ catch (const std::exception& exc) {
std::cerr << "IMB_exr_begin_write: ERROR: " << exc.what() << std::endl;
delete data->ofile;
@@ -619,10 +890,13 @@ int IMB_exr_begin_write(void *handle, const char *filename, int width, int heigh
return (data->ofile != NULL);
}
+/* only used for writing temp. render results (not image files)
+ * (FSA and Save Buffers) */
void IMB_exrtile_begin_write(void *handle, const char *filename, int mipmap, int width, int height, int tilex, int tiley)
{
ExrHandle *data = (ExrHandle *)handle;
Header header(width, height);
+ std::vector<Header> headers;
ExrChannel *echan;
data->tilex = tilex;
@@ -631,26 +905,49 @@ void IMB_exrtile_begin_write(void *handle, const char *filename, int mipmap, int
data->height = height;
data->mipmap = mipmap;
- for (echan = (ExrChannel *)data->channels.first; echan; echan = echan->next)
- header.channels().insert(echan->name, Channel(Imf::FLOAT));
-
header.setTileDescription(TileDescription(tilex, tiley, (mipmap) ? MIPMAP_LEVELS : ONE_LEVEL));
- header.lineOrder() = RANDOM_Y;
header.compression() = RLE_COMPRESSION;
+ header.setType(TILEDIMAGE);
header.insert("BlenderMultiChannel", StringAttribute("Blender V2.43"));
+ int numparts = data->multiView->size();
+
+ /* copy header from all parts of input to our header array
+ * those temporary files have one part per view */
+ for (int i = 0; i < numparts; i++) {
+ headers.push_back (header);
+ headers[headers.size() - 1].setView((*(data->multiView))[i]);
+ headers[headers.size() - 1].setName((*(data->multiView))[i]);
+ }
+
+ exr_printf("\nIMB_exrtile_begin_write\n");
+ exr_printf("%s %-6s %-22s \"%s\"\n", "p", "view", "name", "internal_name");
+ exr_printf("---------------------------------------------------------------\n");
+
+ /* assign channels */
+ for (echan = (ExrChannel *)data->channels.first; echan; echan = echan->next) {
+ /* Tiles are expected to be saved with full float currently. */
+ BLI_assert(echan->use_half_float == 0);
+
+ echan->m->internal_name = echan->m->name;
+ echan->m->part_number = echan->view_id;
+
+ headers[echan->view_id].channels().insert(echan->m->internal_name, Channel(Imf::FLOAT));
+ exr_printf("%d %-6s %-22s \"%s\"\n", echan->m->part_number, echan->m->view.c_str(), echan->m->name.c_str(), echan->m->internal_name.c_str());
+ }
+
/* avoid crash/abort when we don't have permission to write here */
/* manually create ofstream, so we can handle utf-8 filepaths on windows */
try {
data->ofile_stream = new OFileStream(filename);
- data->tofile = new TiledOutputFile(*(data->ofile_stream), header);
+ data->mpofile = new MultiPartOutputFile(*(data->ofile_stream), &headers[0], headers.size());
}
catch (const std::exception &) {
- delete data->tofile;
+ delete data->mpofile;
delete data->ofile_stream;
- data->tofile = NULL;
+ data->mpofile = NULL;
data->ofile_stream = NULL;
}
}
@@ -659,12 +956,13 @@ void IMB_exrtile_begin_write(void *handle, const char *filename, int mipmap, int
int IMB_exr_begin_read(void *handle, const char *filename, int *width, int *height)
{
ExrHandle *data = (ExrHandle *)handle;
+ ExrChannel *echan;
if (BLI_exists(filename) && BLI_file_size(filename) > 32) { /* 32 is arbitrary, but zero length files crashes exr */
/* avoid crash/abort when we don't have permission to write here */
try {
data->ifile_stream = new IFileStream(filename);
- data->ifile = new InputFile(*(data->ifile_stream));
+ data->ifile = new MultiPartInputFile(*(data->ifile_stream));
}
catch (const std::exception &) {
delete data->ifile;
@@ -675,14 +973,24 @@ int IMB_exr_begin_read(void *handle, const char *filename, int *width, int *heig
}
if (data->ifile) {
- Box2i dw = data->ifile->header().dataWindow();
+ Box2i dw = data->ifile->header(0).dataWindow();
data->width = *width = dw.max.x - dw.min.x + 1;
data->height = *height = dw.max.y - dw.min.y + 1;
- const ChannelList &channels = data->ifile->header().channels();
+ imb_exr_get_views(*data->ifile, *data->multiView);
+
+ std::vector<MultiViewChannelName> channels;
+ GetChannelsInMultiPartFile(*data->ifile, channels);
- for (ChannelList::ConstIterator i = channels.begin(); i != channels.end(); ++i)
- IMB_exr_add_channel(data, NULL, i.name(), 0, 0, NULL);
+ for (size_t i = 0; i < channels.size(); i++) {
+ IMB_exr_add_channel(data, NULL, channels[i].name.c_str(), channels[i].view.c_str(), 0, 0, NULL, false);
+
+ echan = (ExrChannel *)data->channels.last;
+ echan->m->name = channels[i].name;
+ echan->m->view = channels[i].view;
+ echan->m->part_number = channels[i].part_number;
+ echan->m->internal_name = channels[i].internal_name;
+ }
return 1;
}
@@ -691,6 +999,7 @@ int IMB_exr_begin_read(void *handle, const char *filename, int *width, int *heig
}
/* still clumsy name handling, layers/channels can be ordered as list in list later */
+/* passname here is the raw channel name without the layer */
void IMB_exr_set_channel(void *handle, const char *layname, const char *passname, int xstride, int ystride, float *rect)
{
ExrHandle *data = (ExrHandle *)handle;
@@ -715,37 +1024,54 @@ void IMB_exr_set_channel(void *handle, const char *layname, const char *passname
echan->rect = rect;
}
else
- printf("IMB_exrtile_set_channel error %s\n", name);
-}
-
-void IMB_exrtile_clear_channels(void *handle)
-{
- ExrHandle *data = (ExrHandle *)handle;
- BLI_freelistN(&data->channels);
+ printf("IMB_exr_set_channel error %s\n", name);
}
-void IMB_exrtile_write_channels(void *handle, int partx, int party, int level)
+float *IMB_exr_channel_rect(void *handle, const char *layname, const char *passname, const char *viewname)
{
ExrHandle *data = (ExrHandle *)handle;
- FrameBuffer frameBuffer;
ExrChannel *echan;
+ char name[EXR_TOT_MAXNAME + 1];
- for (echan = (ExrChannel *)data->channels.first; echan; echan = echan->next) {
- float *rect = echan->rect - echan->xstride * partx - echan->ystride * party;
+ if (layname) {
+ char lay[EXR_LAY_MAXNAME + 1], pass[EXR_PASS_MAXNAME + 1];
+ BLI_strncpy(lay, layname, EXR_LAY_MAXNAME);
+ BLI_strncpy(pass, passname, EXR_PASS_MAXNAME);
- frameBuffer.insert(echan->name, Slice(Imf::FLOAT, (char *)rect,
- echan->xstride * sizeof(float), echan->ystride * sizeof(float)));
+ BLI_snprintf(name, sizeof(name), "%s.%s", lay, pass);
}
+ else
+ BLI_strncpy(name, passname, EXR_TOT_MAXNAME - 1);
- data->tofile->setFrameBuffer(frameBuffer);
-
- try {
- // printf("write tile %d %d\n", partx/data->tilex, party/data->tiley);
- data->tofile->writeTile(partx / data->tilex, party / data->tiley, level);
+ /* name has to be unique, thus it's a combination of layer, pass, view, and channel */
+ if (layname && layname[0] != '\0') {
+ char temp_buf[EXR_PASS_MAXNAME];
+ imb_exr_insert_view_name(temp_buf, name, viewname);
+ BLI_strncpy(name, temp_buf, sizeof(name));
}
- catch (const std::exception &exc) {
- std::cerr << "OpenEXR-writeTile: ERROR: " << exc.what() << std::endl;
+ else if (data->multiView->size() > 1) {
+ size_t view_id = std::max(0, imb_exr_get_multiView_id(*data->multiView, viewname));
+ std::string raw_name = insertViewName(name, *data->multiView, view_id);
+ BLI_strncpy(name, raw_name.c_str(), sizeof(name));
}
+
+ echan = (ExrChannel *)BLI_findstring(&data->channels, name, offsetof(ExrChannel, name));
+
+ if (echan)
+ return echan->rect;
+
+ return NULL;
+}
+
+void IMB_exr_clear_channels(void *handle)
+{
+ ExrHandle *data = (ExrHandle *)handle;
+ ExrChannel *chan;
+
+ for (chan = (ExrChannel *)data->channels.first; chan; chan = chan->next)
+ delete chan->m;
+
+ BLI_freelistN(&data->channels);
}
void IMB_exr_write_channels(void *handle)
@@ -755,70 +1081,223 @@ void IMB_exr_write_channels(void *handle)
ExrChannel *echan;
if (data->channels.first) {
- for (echan = (ExrChannel *)data->channels.first; echan; echan = echan->next) {
- /* last scanline, stride negative */
- float *rect = echan->rect + echan->xstride * (data->height - 1) * data->width;
+ const size_t num_pixels = ((size_t)data->width) * data->height;
+ half *rect_half = NULL, *current_rect_half;
- frameBuffer.insert(echan->name, Slice(Imf::FLOAT, (char *)rect,
- echan->xstride * sizeof(float), -echan->ystride * sizeof(float)));
+ /* We allocate teporary storage for half pixels for all the channels at once. */
+ if (data->num_half_channels != 0) {
+ rect_half = (half *)MEM_mallocN(sizeof(half) * data->num_half_channels * num_pixels, __func__);
+ current_rect_half = rect_half;
+ }
+
+ for (echan = (ExrChannel *)data->channels.first; echan; echan = echan->next) {
+ /* Writting starts from last scanline, stride negative. */
+ if (echan->use_half_float) {
+ float *rect = echan->rect;
+ half *cur = current_rect_half;
+ for (size_t i = 0; i < num_pixels; ++i, ++cur) {
+ *cur = rect[i * echan->xstride];
+ }
+ half *rect_to_write = current_rect_half + (data->height - 1) * data->width;
+ frameBuffer.insert(echan->name, Slice(Imf::HALF, (char *)rect_to_write,
+ sizeof(half), -data->width * sizeof(half)));
+ current_rect_half += num_pixels;
+ }
+ else {
+ float *rect = echan->rect + echan->xstride * (data->height - 1) * data->width;
+ frameBuffer.insert(echan->name, Slice(Imf::FLOAT, (char *)rect,
+ echan->xstride * sizeof(float), -echan->ystride * sizeof(float)));
+ }
}
data->ofile->setFrameBuffer(frameBuffer);
try {
data->ofile->writePixels(data->height);
}
- catch (const std::exception &exc) {
+ catch (const std::exception& exc) {
std::cerr << "OpenEXR-writePixels: ERROR: " << exc.what() << std::endl;
}
+ /* Free temporary buffers. */
+ if (rect_half != NULL) {
+ MEM_freeN(rect_half);
+ }
}
else {
printf("Error: attempt to save MultiLayer without layers.\n");
}
}
-void IMB_exr_read_channels(void *handle)
+/* temporary function, used for FSA and Save Buffers */
+/* called once per tile * view */
+void IMB_exrtile_write_channels(void *handle, int partx, int party, int level, const char *viewname)
{
ExrHandle *data = (ExrHandle *)handle;
FrameBuffer frameBuffer;
ExrChannel *echan;
+ std::string view(viewname);
+ const size_t view_id = imb_exr_get_multiView_id(*data->multiView, view);
+
+ exr_printf("\nIMB_exrtile_write_channels(view: %s)\n", viewname);
+ exr_printf("%s %-6s %-22s \"%s\"\n", "p", "view", "name", "internal_name");
+ exr_printf("---------------------------------------------------------------------\n");
+
+ for (echan = (ExrChannel *)data->channels.first; echan; echan = echan->next) {
+
+ /* eventually we can make the parts' channels to include
+ only the current view TODO */
+ if (strcmp(viewname, echan->m->view.c_str()) != 0)
+ continue;
+
+ exr_printf("%d %-6s %-22s \"%s\"\n",
+ echan->m->part_number,
+ echan->m->view.c_str(),
+ echan->m->name.c_str(),
+ echan->m->internal_name.c_str()
+ );
+
+ float *rect = echan->rect - echan->xstride * partx - echan->ystride * party;
+ frameBuffer.insert(echan->m->internal_name,
+ Slice(Imf::FLOAT,
+ (char *)rect,
+ echan->xstride * sizeof(float),
+ echan->ystride * sizeof(float)
+ )
+ );
+ }
+
+ TiledOutputPart out (*data->mpofile, view_id);
+ out.setFrameBuffer(frameBuffer);
+
+ try {
+ // printf("write tile %d %d\n", partx/data->tilex, party/data->tiley);
+ out.writeTile(partx / data->tilex, party / data->tiley, level);
+ }
+ catch (const std::exception& exc) {
+ std::cerr << "OpenEXR-writeTile: ERROR: " << exc.what() << std::endl;
+ }
+}
+
+/* called only when handle has all views */
+void IMB_exrmultiview_write_channels(void *handle, const char *viewname)
+{
+ ExrHandle *data = (ExrHandle *)handle;
+ const size_t view_id = viewname ? imb_exr_get_multiView_id(*data->multiView, viewname) : -1;
+ int numparts = (view_id == -1 ? data->parts : view_id + 1);
+ std::vector <FrameBuffer> frameBuffers(numparts);
+ std::vector <OutputPart> outputParts;
+ ExrChannel *echan;
+ int i, part;
+
+ if (data->channels.first == NULL)
+ return;
+
+ exr_printf("\nIMB_exrmultiview_write_channels()\n");
+
+ for (echan = (ExrChannel *)data->channels.first; echan; echan = echan->next) {
+ if (view_id != -1 && echan->view_id != view_id)
+ continue;
+
+ part = (view_id == -1 ? echan->m->part_number : echan->view_id);
+
+ /* last scanline, stride negative */
+ float *rect = echan->rect + echan->xstride * (data->height - 1) * data->width;
+ frameBuffers[part].insert(echan->m->internal_name,
+ Slice(Imf::FLOAT,
+ (char *)rect,
+ echan->xstride * sizeof(float),
+ -echan->ystride * sizeof(float))
+ );
+ }
+
+ for (i = 0; i < numparts; i++) {
+ OutputPart out(*data->mpofile, i);
+ out.setFrameBuffer(frameBuffers[i]);
+ outputParts.push_back(out);
+ }
+
+ try {
+ for (i = 0; i < numparts; i++) {
+ if (view_id != -1 && i != view_id)
+ continue;
+
+ outputParts[i].writePixels(data->height);
+ }
+ }
+ catch (const std::exception& exc) {
+ std::cerr << "OpenEXR-write Multi Part: ERROR: " << exc.what() << std::endl;
+ }
+}
+
+void IMB_exr_read_channels(void *handle)
+{
+ ExrHandle *data = (ExrHandle *)handle;
+ ExrChannel *echan;
+ int numparts = data->ifile->parts();
+ std::vector<FrameBuffer> frameBuffers(numparts);
+ std::vector<InputPart> inputParts;
/* check if exr was saved with previous versions of blender which flipped images */
- const StringAttribute *ta = data->ifile->header().findTypedAttribute <StringAttribute> ("BlenderMultiChannel");
- short flip = (ta && strncmp(ta->value().c_str(), "Blender V2.43", 13) == 0); /* 'previous multilayer attribute, flipped */
+ const StringAttribute *ta = data->ifile->header(0).findTypedAttribute <StringAttribute> ("BlenderMultiChannel");
+ short flip = (ta && STREQLEN(ta->value().c_str(), "Blender V2.43", 13)); /* 'previous multilayer attribute, flipped */
+
+ exr_printf("\nIMB_exr_read_channels\n%s %-6s %-22s \"%s\"\n---------------------------------------------------------------------\n", "p", "view", "name", "internal_name");
for (echan = (ExrChannel *)data->channels.first; echan; echan = echan->next) {
+ exr_printf("%d %-6s %-22s \"%s\"\n", echan->m->part_number, echan->m->view.c_str(), echan->m->name.c_str(), echan->m->internal_name.c_str());
if (echan->rect) {
if (flip)
- frameBuffer.insert(echan->name, Slice(Imf::FLOAT, (char *)echan->rect,
+ frameBuffers[echan->m->part_number].insert(echan->m->internal_name, Slice(Imf::FLOAT, (char *)echan->rect,
echan->xstride * sizeof(float), echan->ystride * sizeof(float)));
else
- frameBuffer.insert(echan->name, Slice(Imf::FLOAT, (char *)(echan->rect + echan->xstride * (data->height - 1) * data->width),
+ frameBuffers[echan->m->part_number].insert(echan->m->internal_name, Slice(Imf::FLOAT, (char *)(echan->rect + echan->xstride * (data->height - 1) * data->width),
echan->xstride * sizeof(float), -echan->ystride * sizeof(float)));
}
else
- printf("warning, channel with no rect set %s\n", echan->name);
+ printf("warning, channel with no rect set %s\n", echan->m->internal_name.c_str());
}
- data->ifile->setFrameBuffer(frameBuffer);
+ for (int i = 0; i < numparts; i++) {
+ InputPart in (*data->ifile, i);
+ in.setFrameBuffer(frameBuffers[i]);
+ inputParts.push_back(in);
+ }
try {
- data->ifile->readPixels(0, data->height - 1);
+ for (int i = 0; i < numparts; i++) {
+ Header header = inputParts[i].header();
+ exr_printf("readPixels:readPixels[%d]: min.y: %d, max.y: %d\n", i, header.dataWindow().min.y, header.dataWindow().max.y);
+ inputParts[i].readPixels(header.dataWindow().min.y, header.dataWindow().max.y);
+ inputParts[i].readPixels(0, data->height - 1);
+ }
}
- catch (const std::exception &exc) {
+ catch (const std::exception& exc) {
std::cerr << "OpenEXR-readPixels: ERROR: " << exc.what() << std::endl;
}
}
void IMB_exr_multilayer_convert(void *handle, void *base,
+ void * (*addview)(void *base, const char *str),
void * (*addlayer)(void *base, const char *str),
void (*addpass)(void *base, void *lay, const char *str,
- float *rect, int totchan, const char *chan_id))
+ float *rect, int totchan, const char *chan_id,
+ const char *view))
{
ExrHandle *data = (ExrHandle *)handle;
ExrLayer *lay;
ExrPass *pass;
+ /* RenderResult needs at least one RenderView */
+ if (data->multiView->size() == 0) {
+ addview(base, "");
+ }
+ else {
+ /* add views to RenderResult */
+ for (StringVector::const_iterator i = data->multiView->begin(); i != data->multiView->end(); ++i) {
+ addview(base, (*i).c_str());
+ }
+ }
+
if (BLI_listbase_is_empty(&data->layers)) {
printf("cannot convert multilayer, no layers in handle\n");
return;
@@ -828,32 +1307,99 @@ void IMB_exr_multilayer_convert(void *handle, void *base,
void *laybase = addlayer(base, lay->name);
if (laybase) {
for (pass = (ExrPass *)lay->passes.first; pass; pass = pass->next) {
- addpass(base, laybase, pass->name, pass->rect, pass->totchan, pass->chan_id);
+ addpass(base, laybase, pass->internal_name, pass->rect, pass->totchan, pass->chan_id, pass->view);
pass->rect = NULL;
}
}
}
}
+void IMB_exr_multiview_convert(void *handle, void *base,
+ void (*addview)(void *base, const char *str),
+ void (*addbuffer)(void *base, const char *str, ImBuf *ibuf, const int frame),
+ const int frame)
+{
+ ExrHandle *data = (ExrHandle *)handle;
+ MultiPartInputFile *file = data->ifile;
+ ExrLayer *lay;
+ ExrPass *pass;
+ ImBuf *ibuf = NULL;
+ const bool is_alpha = exr_has_alpha(*file);
+ Box2i dw = file->header(0).dataWindow();
+ const size_t width = dw.max.x - dw.min.x + 1;
+ const size_t height = dw.max.y - dw.min.y + 1;
+ const bool is_depth = exr_has_zbuffer(*file);
+
+ /* add views to RenderResult */
+ for (StringVector::const_iterator i = data->multiView->begin(); i != data->multiView->end(); ++i) {
+ addview(base, (*i).c_str());
+ }
+
+ if (BLI_listbase_is_empty(&data->layers)) {
+ printf("cannot convert multiviews, no views in handle\n");
+ return;
+ }
+
+ /* there is one float/pass per layer (layer here is a view) */
+ BLI_assert(BLI_listbase_count_ex(&data->layers, 2) == 1);
+ lay = (ExrLayer *)data->layers.first;
+ for (pass = (ExrPass *)lay->passes.first; pass; pass = pass->next) {
+ if (STREQ(pass->chan_id, "RGB") || STREQ(pass->chan_id, "RGBA")) {
+ ibuf = IMB_allocImBuf(width, height, is_alpha ? 32 : 24, IB_rectfloat);
+
+ if (!ibuf) {
+ printf("error creating multiview buffer\n");
+ return;
+ }
+
+ IMB_buffer_float_from_float(
+ ibuf->rect_float, pass->rect, pass->totchan,
+ IB_PROFILE_LINEAR_RGB, IB_PROFILE_LINEAR_RGB, false,
+ ibuf->x, ibuf->y, ibuf->x, ibuf->x);
+
+ if (hasXDensity(file->header(0))) {
+ ibuf->ppm[0] = xDensity(file->header(0)) * 39.3700787f;
+ ibuf->ppm[1] = ibuf->ppm[0] * (double)file->header(0).pixelAspectRatio();
+ }
+
+ if (is_depth) {
+ ExrPass *zpass;
+ for (zpass = (ExrPass *)lay->passes.first; zpass; zpass = zpass->next) {
+ if (STREQ(zpass->chan_id, "Z") && STREQ(zpass->view, pass->view)) {
+ addzbuffloatImBuf(ibuf);
+ memcpy(ibuf->zbuf_float, zpass->rect, sizeof(float) * ibuf->x * ibuf->y);
+ }
+ }
+ }
+
+ addbuffer(base, pass->view, ibuf, frame);
+ }
+ }
+}
void IMB_exr_close(void *handle)
{
ExrHandle *data = (ExrHandle *)handle;
ExrLayer *lay;
ExrPass *pass;
+ ExrChannel *chan;
delete data->ifile;
delete data->ifile_stream;
delete data->ofile;
- delete data->tofile;
+ delete data->mpofile;
delete data->ofile_stream;
+ delete data->multiView;
data->ifile = NULL;
data->ifile_stream = NULL;
data->ofile = NULL;
- data->tofile = NULL;
+ data->mpofile = NULL;
data->ofile_stream = NULL;
+ for (chan = (ExrChannel *)data->channels.first; chan; chan = chan->next) {
+ delete chan->m;
+ }
BLI_freelistN(&data->channels);
for (lay = (ExrLayer *)data->layers.first; lay; lay = lay->next) {
@@ -873,19 +1419,21 @@ void IMB_exr_close(void *handle)
/* get a substring from the end of the name, separated by '.' */
static int imb_exr_split_token(const char *str, const char *end, const char **token)
{
- ptrdiff_t maxlen = end - str;
- int len = 0;
- while (len < maxlen && *(end - len - 1) != '.') {
- len++;
+ const char delims[] = {'.', '\0'};
+ const char *sep;
+
+ BLI_str_partition_ex(str, end, delims, &sep, token, true);
+
+ if (!sep) {
+ *token = str;
}
- *token = end - len;
- return len;
+ return (int)(end - *token);
}
static int imb_exr_split_channel_name(ExrChannel *echan, char *layname, char *passname)
{
- const char *name = echan->name;
+ const char *name = echan->m->name.c_str();
const char *end = name + strlen(name);
const char *token;
char tokenbuf[EXR_TOT_MAXNAME];
@@ -982,7 +1530,7 @@ static ExrPass *imb_exr_get_pass(ListBase *lb, char *passname)
if (pass == NULL) {
pass = (ExrPass *)MEM_callocN(sizeof(ExrPass), "exr pass");
- if (strcmp(passname, "Combined") == 0)
+ if (STREQ(passname, "Combined"))
BLI_addhead(lb, pass);
else
BLI_addtail(lb, pass);
@@ -994,7 +1542,7 @@ static ExrPass *imb_exr_get_pass(ListBase *lb, char *passname)
}
/* creates channels, makes a hierarchy and assigns memory to channels */
-static ExrHandle *imb_exr_begin_read_mem(InputFile *file, int width, int height)
+static ExrHandle *imb_exr_begin_read_mem(IStream &file_stream, MultiPartInputFile &file, int width, int height)
{
ExrLayer *lay;
ExrPass *pass;
@@ -1003,30 +1551,58 @@ static ExrHandle *imb_exr_begin_read_mem(InputFile *file, int width, int height)
int a;
char layname[EXR_TOT_MAXNAME], passname[EXR_TOT_MAXNAME];
- data->ifile = file;
+ data->ifile_stream = &file_stream;
+ data->ifile = &file;
+
data->width = width;
data->height = height;
- const ChannelList &channels = data->ifile->header().channels();
+ std::vector<MultiViewChannelName> channels;
+ GetChannelsInMultiPartFile(*data->ifile, channels);
+
+ imb_exr_get_views(*data->ifile, *data->multiView);
- for (ChannelList::ConstIterator i = channels.begin(); i != channels.end(); ++i)
- IMB_exr_add_channel(data, NULL, i.name(), 0, 0, NULL);
+ for (size_t i = 0; i < channels.size(); i++) {
+ IMB_exr_add_channel(data, NULL, channels[i].name.c_str(), channels[i].view.c_str(), 0, 0, NULL, false);
+
+ echan = (ExrChannel *)data->channels.last;
+ echan->m->name = channels[i].name;
+ echan->m->view = channels[i].view;
+ echan->m->part_number = channels[i].part_number;
+ echan->m->internal_name = channels[i].internal_name;
+ }
/* now try to sort out how to assign memory to the channels */
/* first build hierarchical layer list */
for (echan = (ExrChannel *)data->channels.first; echan; echan = echan->next) {
- if (imb_exr_split_channel_name(echan, layname, passname) ) {
+ if (imb_exr_split_channel_name(echan, layname, passname)) {
+
+ const char *view = echan->m->view.c_str();
+ char internal_name[EXR_PASS_MAXNAME];
+
+ BLI_strncpy(internal_name, passname, EXR_PASS_MAXNAME);
+
+ if (view[0] != '\0') {
+ char tmp_pass[EXR_PASS_MAXNAME];
+ BLI_snprintf(tmp_pass, sizeof(tmp_pass), "%s.%s", passname, view);
+ BLI_strncpy(passname, tmp_pass, sizeof(passname));
+ }
+
ExrLayer *lay = imb_exr_get_layer(&data->layers, layname);
ExrPass *pass = imb_exr_get_pass(&lay->passes, passname);
pass->chan[pass->totchan] = echan;
pass->totchan++;
+ pass->view_id = echan->view_id;
+ BLI_strncpy(pass->view, view, sizeof(pass->view));
+ BLI_strncpy(pass->internal_name, internal_name, EXR_PASS_MAXNAME);
+
if (pass->totchan >= EXR_PASS_MAXCHAN)
break;
}
}
if (echan) {
- printf("error, too many channels in one pass: %s\n", echan->name);
+ printf("error, too many channels in one pass: %s\n", echan->m->name.c_str());
IMB_exr_close(data);
return NULL;
}
@@ -1096,20 +1672,52 @@ static ExrHandle *imb_exr_begin_read_mem(InputFile *file, int width, int height)
/* ********************************************************* */
/* debug only */
-static void exr_print_filecontents(InputFile *file)
+static void exr_printf(const char *fmt, ...)
{
- const ChannelList &channels = file->header().channels();
+#if 0
+ char output[1024];
+ va_list args;
+ va_start(args, fmt);
+ std::vsprintf(output, fmt, args);
+ va_end(args);
+ printf("%s", output);
+#else
+ (void)fmt;
+#endif
+}
- for (ChannelList::ConstIterator i = channels.begin(); i != channels.end(); ++i) {
- const Channel &channel = i.channel();
- printf("OpenEXR-load: Found channel %s of type %d\n", i.name(), channel.type);
+static void exr_print_filecontents(MultiPartInputFile& file)
+{
+ int numparts = file.parts();
+ if (numparts == 1 && hasMultiView(file.header(0))) {
+ const StringVector views = multiView(file.header(0));
+ printf("OpenEXR-load: MultiView file\n");
+ printf("OpenEXR-load: Default view: %s\n", defaultViewName(views).c_str());
+ for (StringVector::const_iterator i = views.begin(); i != views.end(); ++i) {
+ printf("OpenEXR-load: Found view %s\n", (*i).c_str());
+ }
+ }
+ else if (numparts > 1) {
+ printf("OpenEXR-load: MultiPart file\n");
+ for (int i = 0; i < numparts; i++) {
+ if (file.header(i).hasView())
+ printf("OpenEXR-load: Part %d: view = \"%s\"\n", i, file.header(i).view().c_str());
+ }
+ }
+
+ for (int j = 0; j < numparts; j++) {
+ const ChannelList& channels = file.header(j).channels();
+ for (ChannelList::ConstIterator i = channels.begin(); i != channels.end(); ++i) {
+ const Channel& channel = i.channel();
+ printf("OpenEXR-load: Found channel %s of type %d\n", i.name(), channel.type);
+ }
}
}
/* for non-multilayer, map R G B A channel names to something that's in this file */
-static const char *exr_rgba_channelname(InputFile *file, const char *chan)
+static const char *exr_rgba_channelname(MultiPartInputFile& file, const char *chan)
{
- const ChannelList &channels = file->header().channels();
+ const ChannelList& channels = file.header(0).channels();
for (ChannelList::ConstIterator i = channels.begin(); i != channels.end(); ++i) {
/* const Channel &channel = i.channel(); */ /* Not used yet */
@@ -1124,48 +1732,48 @@ static const char *exr_rgba_channelname(InputFile *file, const char *chan)
return chan;
}
-static bool exr_has_rgb(InputFile *file)
+static bool exr_has_rgb(MultiPartInputFile& file)
{
- return file->header().channels().findChannel("R") != NULL &&
- file->header().channels().findChannel("G") != NULL &&
- file->header().channels().findChannel("B") != NULL;
+ return file.header(0).channels().findChannel("R") != NULL &&
+ file.header(0).channels().findChannel("G") != NULL &&
+ file.header(0).channels().findChannel("B") != NULL;
}
-static bool exr_has_luma(InputFile *file)
+static bool exr_has_luma(MultiPartInputFile& file)
{
/* Y channel is the luma and should always present fir luma space images,
* optionally it could be also channels for chromas called BY and RY.
*/
- return file->header().channels().findChannel("Y") != NULL;
+ return file.header(0).channels().findChannel("Y") != NULL;
}
-static bool exr_has_chroma(InputFile *file)
+static bool exr_has_chroma(MultiPartInputFile& file)
{
- return file->header().channels().findChannel("BY") != NULL &&
- file->header().channels().findChannel("RY") != NULL;
+ return file.header(0).channels().findChannel("BY") != NULL &&
+ file.header(0).channels().findChannel("RY") != NULL;
}
-static int exr_has_zbuffer(InputFile *file)
+static bool exr_has_zbuffer(MultiPartInputFile& file)
{
- return !(file->header().channels().findChannel("Z") == NULL);
+ return !(file.header(0).channels().findChannel("Z") == NULL);
}
-static int exr_has_alpha(InputFile *file)
+static bool exr_has_alpha(MultiPartInputFile& file)
{
- return !(file->header().channels().findChannel("A") == NULL);
+ return !(file.header(0).channels().findChannel("A") == NULL);
}
-static bool exr_is_multilayer(InputFile *file)
+static bool imb_exr_is_multilayer_file(MultiPartInputFile& file)
{
- const StringAttribute *comments = file->header().findTypedAttribute<StringAttribute>("BlenderMultiChannel");
- const ChannelList &channels = file->header().channels();
+ const StringAttribute *comments = file.header(0).findTypedAttribute<StringAttribute>("BlenderMultiChannel");
+ const ChannelList& channels = file.header(0).channels();
std::set <std::string> layerNames;
/* will not include empty layer names */
channels.layers(layerNames);
if (comments || layerNames.size() > 1)
- return 1;
+ return true;
if (layerNames.size()) {
/* if layerNames is not empty, it means at least one layer is non-empty,
@@ -1180,17 +1788,123 @@ static bool exr_is_multilayer(InputFile *file)
size_t pos = layerName.rfind ('.');
if (pos == std::string::npos)
- return 1;
+ return true;
}
}
- return 0;
+ return false;
+}
+
+static void imb_exr_type_by_channels(ChannelList& channels, StringVector& views,
+ bool *r_singlelayer, bool *r_multilayer, bool *r_multiview)
+{
+ std::set <std::string> layerNames;
+
+ *r_singlelayer = true;
+ *r_multilayer = *r_multiview = false;
+
+ /* will not include empty layer names */
+ channels.layers(layerNames);
+
+ if (views.size() && views[0] != "")
+ *r_multiview = true;
+
+ if (layerNames.size()) {
+ /* if layerNames is not empty, it means at least one layer is non-empty,
+ * but it also could be layers without names in the file and such case
+ * shall be considered a multilayer exr
+ *
+ * that's what we do here: test whether there're empty layer names together
+ * with non-empty ones in the file
+ */
+ for (ChannelList::ConstIterator i = channels.begin(); i != channels.end(); i++)
+ for (std::set<string>::iterator i = layerNames.begin(); i != layerNames.end(); i++)
+ /* see if any layername differs from a viewname */
+ if (imb_exr_get_multiView_id(views, *i) == -1) {
+ std::string layerName = *i;
+ size_t pos = layerName.rfind ('.');
+
+ if (pos != std::string::npos) {
+ *r_multilayer = true;
+ *r_singlelayer = false;
+ return;
+ }
+ }
+ }
+ else {
+ *r_singlelayer = true;
+ *r_multilayer = false;
+ *r_multiview = false;
+ }
+
+ BLI_assert(r_singlelayer != r_multilayer);
}
-struct ImBuf *imb_load_openexr(unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE])
+bool IMB_exr_has_singlelayer_multiview(void *handle)
+{
+ ExrHandle *data = (ExrHandle *)handle;
+ MultiPartInputFile *file = data->ifile;
+ std::set <std::string> layerNames;
+ const ChannelList& channels = file->header(0).channels();
+ const StringAttribute *comments;
+
+ if (exr_has_multiview(*file) == false)
+ return false;
+
+ comments = file->header(0).findTypedAttribute<StringAttribute>("BlenderMultiChannel");
+
+ if (comments)
+ return false;
+
+ /* will not include empty layer names */
+ channels.layers(layerNames);
+
+ /* returns false if any layer differs from views list */
+ if (layerNames.size())
+ for (std::set<string>::iterator i = layerNames.begin(); i != layerNames.end(); i++)
+ if (imb_exr_get_multiView_id(*data->multiView, *i) == -1)
+ return false;
+
+ return true;
+}
+
+bool IMB_exr_has_multilayer(void *handle)
+{
+ ExrHandle *data = (ExrHandle *)handle;
+ return imb_exr_is_multilayer_file(*data->ifile);
+}
+
+static bool exr_has_multiview(MultiPartInputFile& file)
+{
+ return hasMultiView(file.header(0));
+}
+
+static bool exr_has_multipart_file(MultiPartInputFile& file)
+{
+ return file.parts() > 1;
+}
+
+/* it returns true if the file is multilayer or multiview */
+static bool imb_exr_is_multi(MultiPartInputFile& file)
+{
+ /* multipart files are treated as multilayer in blender - even if they are single layer openexr with multiview */
+ if (exr_has_multipart_file(file))
+ return true;
+
+ if (exr_has_multiview(file))
+ return true;
+
+ if (imb_exr_is_multilayer_file(file))
+ return true;
+
+ return false;
+}
+
+struct ImBuf *imb_load_openexr(const unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE])
{
struct ImBuf *ibuf = NULL;
- InputFile *file = NULL;
+ Mem_IStream *membuf = NULL;
+ MultiPartInputFile *file = NULL;
if (imb_is_a_openexr(mem) == 0) return(NULL);
@@ -1198,11 +1912,12 @@ struct ImBuf *imb_load_openexr(unsigned char *mem, size_t size, int flags, char
try
{
- Mem_IStream *membuf = new Mem_IStream(mem, size);
bool is_multi;
- file = new InputFile(*membuf);
- Box2i dw = file->header().dataWindow();
+ membuf = new Mem_IStream((unsigned char *)mem, size);
+ file = new MultiPartInputFile(*membuf);
+
+ Box2i dw = file->header(0).dataWindow();
const int width = dw.max.x - dw.min.x + 1;
const int height = dw.max.y - dw.min.y + 1;
@@ -1210,38 +1925,54 @@ struct ImBuf *imb_load_openexr(unsigned char *mem, size_t size, int flags, char
// dw.min.x, dw.min.y, dw.max.x, dw.max.y);
if (0) // debug
- exr_print_filecontents(file);
+ exr_print_filecontents(*file);
- is_multi = exr_is_multilayer(file);
+ is_multi = imb_exr_is_multi(*file);
/* do not make an ibuf when */
if (is_multi && !(flags & IB_test) && !(flags & IB_multilayer)) {
printf("Error: can't process EXR multilayer file\n");
}
else {
- const int is_alpha = exr_has_alpha(file);
+ const int is_alpha = exr_has_alpha(*file);
ibuf = IMB_allocImBuf(width, height, is_alpha ? 32 : 24, 0);
- if (hasXDensity(file->header())) {
- ibuf->ppm[0] = xDensity(file->header()) * 39.3700787f;
- ibuf->ppm[1] = ibuf->ppm[0] * (double)file->header().pixelAspectRatio();
+ if (hasXDensity(file->header(0))) {
+ ibuf->ppm[0] = xDensity(file->header(0)) * 39.3700787f;
+ ibuf->ppm[1] = ibuf->ppm[0] * (double)file->header(0).pixelAspectRatio();
}
- ibuf->ftype = OPENEXR;
+ ibuf->ftype = IMB_FTYPE_OPENEXR;
if (!(flags & IB_test)) {
- if (is_multi) { /* only enters with IB_multilayer flag set */
+
+ if (flags & IB_metadata) {
+ const Header & header = file->header(0);
+ Header::ConstIterator iter;
+
+ for (iter = header.begin(); iter != header.end(); iter++) {
+ const StringAttribute *attrib = file->header(0).findTypedAttribute <StringAttribute> (iter.name());
+
+ /* not all attributes are string attributes so we might get some NULLs here */
+ if (attrib) {
+ IMB_metadata_add_field(ibuf, iter.name(), attrib->value().c_str());
+ ibuf->flags |= IB_metadata;
+ }
+ }
+ }
+
+ if (is_multi && ((flags & IB_thumbnail) == 0)) { /* only enters with IB_multilayer flag set */
/* constructs channels for reading, allocates memory in channels */
- ExrHandle *handle = imb_exr_begin_read_mem(file, width, height);
+ ExrHandle *handle = imb_exr_begin_read_mem(*membuf, *file, width, height);
if (handle) {
IMB_exr_read_channels(handle);
ibuf->userdata = handle; /* potential danger, the caller has to check for this! */
}
}
else {
- const bool has_rgb = exr_has_rgb(file);
- const bool has_luma = exr_has_luma(file);
+ const bool has_rgb = exr_has_rgb(*file);
+ const bool has_luma = exr_has_luma(*file);
FrameBuffer frameBuffer;
float *first;
int xstride = sizeof(float) * 4;
@@ -1255,27 +1986,27 @@ struct ImBuf *imb_load_openexr(unsigned char *mem, size_t size, int flags, char
first += 4 * (height - 1) * width;
if (has_rgb) {
- frameBuffer.insert(exr_rgba_channelname(file, "R"),
+ frameBuffer.insert(exr_rgba_channelname(*file, "R"),
Slice(Imf::FLOAT, (char *) first, xstride, ystride));
- frameBuffer.insert(exr_rgba_channelname(file, "G"),
+ frameBuffer.insert(exr_rgba_channelname(*file, "G"),
Slice(Imf::FLOAT, (char *) (first + 1), xstride, ystride));
- frameBuffer.insert(exr_rgba_channelname(file, "B"),
+ frameBuffer.insert(exr_rgba_channelname(*file, "B"),
Slice(Imf::FLOAT, (char *) (first + 2), xstride, ystride));
}
else if (has_luma) {
- frameBuffer.insert(exr_rgba_channelname(file, "Y"),
+ frameBuffer.insert(exr_rgba_channelname(*file, "Y"),
Slice(Imf::FLOAT, (char *) first, xstride, ystride));
- frameBuffer.insert(exr_rgba_channelname(file, "BY"),
+ frameBuffer.insert(exr_rgba_channelname(*file, "BY"),
Slice(Imf::FLOAT, (char *) (first + 1), xstride, ystride, 1, 1, 0.5f));
- frameBuffer.insert(exr_rgba_channelname(file, "RY"),
+ frameBuffer.insert(exr_rgba_channelname(*file, "RY"),
Slice(Imf::FLOAT, (char *) (first + 2), xstride, ystride, 1, 1, 0.5f));
}
/* 1.0 is fill value, this still needs to be assigned even when (is_alpha == 0) */
- frameBuffer.insert(exr_rgba_channelname(file, "A"),
+ frameBuffer.insert(exr_rgba_channelname(*file, "A"),
Slice(Imf::FLOAT, (char *) (first + 3), xstride, ystride, 1, 1, 1.0f));
- if (exr_has_zbuffer(file)) {
+ if (exr_has_zbuffer(*file)) {
float *firstz;
addzbuffloatImBuf(ibuf);
@@ -1284,8 +2015,9 @@ struct ImBuf *imb_load_openexr(unsigned char *mem, size_t size, int flags, char
frameBuffer.insert("Z", Slice(Imf::FLOAT, (char *)firstz, sizeof(float), -width * sizeof(float)));
}
- file->setFrameBuffer(frameBuffer);
- file->readPixels(dw.min.y, dw.max.y);
+ InputPart in (*file, 0);
+ in.setFrameBuffer(frameBuffer);
+ in.readPixels(dw.min.y, dw.max.y);
// XXX, ImBuf has no nice way to deal with this.
// ideally IM_rect would be used when the caller wants a rect BUT
@@ -1299,7 +2031,7 @@ struct ImBuf *imb_load_openexr(unsigned char *mem, size_t size, int flags, char
if (!has_rgb && has_luma) {
size_t a;
- if (exr_has_chroma(file)) {
+ if (exr_has_chroma(*file)) {
for (a = 0; a < (size_t) ibuf->x * ibuf->y; ++a) {
float *color = ibuf->rect_float + a * 4;
ycc_to_rgb(color[0] * 255.0f, color[1] * 255.0f, color[2] * 255.0f,
@@ -1316,20 +2048,26 @@ struct ImBuf *imb_load_openexr(unsigned char *mem, size_t size, int flags, char
}
/* file is no longer needed */
+ delete membuf;
delete file;
}
}
+ else {
+ delete membuf;
+ delete file;
+ }
if (flags & IB_alphamode_detect)
ibuf->flags |= IB_alphamode_premul;
}
return(ibuf);
}
- catch (const std::exception &exc)
+ catch (const std::exception& exc)
{
std::cerr << exc.what() << std::endl;
if (ibuf) IMB_freeImBuf(ibuf);
delete file;
+ delete membuf;
return (0);
}
diff --git a/source/blender/imbuf/intern/openexr/openexr_api.h b/source/blender/imbuf/intern/openexr/openexr_api.h
index bc21d8cea7b..ec4ae94795d 100644
--- a/source/blender/imbuf/intern/openexr/openexr_api.h
+++ b/source/blender/imbuf/intern/openexr/openexr_api.h
@@ -41,11 +41,11 @@ extern "C" {
void imb_initopenexr (void);
-int imb_is_a_openexr (unsigned char *mem);
+int imb_is_a_openexr (const unsigned char *mem);
int imb_save_openexr (struct ImBuf *ibuf, const char *name, int flags);
-struct ImBuf *imb_load_openexr (unsigned char *mem, size_t size, int flags, char *colorspace);
+struct ImBuf *imb_load_openexr (const unsigned char *mem, size_t size, int flags, char *colorspace);
#ifdef __cplusplus
}
diff --git a/source/blender/imbuf/intern/openexr/openexr_multi.h b/source/blender/imbuf/intern/openexr/openexr_multi.h
index 376d2401b1c..70ba4978124 100644
--- a/source/blender/imbuf/intern/openexr/openexr_multi.h
+++ b/source/blender/imbuf/intern/openexr/openexr_multi.h
@@ -39,34 +39,63 @@
/* This api also supports max 8 channels per pass now. easy to fix! */
#define EXR_LAY_MAXNAME 64
#define EXR_PASS_MAXNAME 64
+#define EXR_VIEW_MAXNAME 64
#define EXR_TOT_MAXNAME 64
-#define EXR_PASS_MAXCHAN 8
+#define EXR_PASS_MAXCHAN 24
#ifdef __cplusplus
extern "C" {
#endif
+struct StampData;
+
void *IMB_exr_get_handle(void);
-void IMB_exr_add_channel(void *handle, const char *layname, const char *passname, int xstride, int ystride, float *rect);
+void *IMB_exr_get_handle_name(const char *name);
+void IMB_exr_add_channel(void *handle,
+ const char *layname, const char *passname, const char *view,
+ int xstride, int ystride,
+ float *rect,
+ bool use_half_float);
int IMB_exr_begin_read(void *handle, const char *filename, int *width, int *height);
-int IMB_exr_begin_write(void *handle, const char *filename, int width, int height, int compress);
+int IMB_exr_begin_write(void *handle, const char *filename, int width, int height, int compress, const struct StampData *stamp);
void IMB_exrtile_begin_write(void *handle, const char *filename, int mipmap, int width, int height, int tilex, int tiley);
void IMB_exr_set_channel(void *handle, const char *layname, const char *passname, int xstride, int ystride, float *rect);
+float *IMB_exr_channel_rect(void *handle, const char *layname, const char *passname, const char *view);
void IMB_exr_read_channels(void *handle);
void IMB_exr_write_channels(void *handle);
-void IMB_exrtile_write_channels(void *handle, int partx, int party, int level);
-void IMB_exrtile_clear_channels(void *handle);
+void IMB_exrtile_write_channels(void *handle, int partx, int party, int level, const char *viewname);
+void IMB_exrmultiview_write_channels(void *handle, const char *viewname);
+void IMB_exr_clear_channels(void *handle);
+
+void IMB_exr_multilayer_convert(
+ void *handle, void *base,
+ void * (*addview)(void *base, const char *str),
+ void * (*addlayer)(void *base, const char *str),
+ void (*addpass)(void *base, void *lay, const char *str, float *rect, int totchan,
+ const char *chan_id, const char *view));
+
+void IMB_exr_multiview_convert(
+ void *handle, void *base,
+ void (*addview)(void *base, const char *str),
+ void (*addbuffer)(void *base, const char *str, struct ImBuf *ibuf, const int frame),
+ const int frame);
-void IMB_exr_multilayer_convert(void *handle, void *base,
- void * (*addlayer)(void *base, const char *str),
- void (*addpass)(void *base, void *lay, const char *str, float *rect, int totchan, const char *chan_id));
+bool IMB_exr_multiview_save(
+ struct ImBuf *ibuf, const char *name, const int flags, const size_t totviews,
+ const char * (*getview)(void *base, size_t view_id),
+ struct ImBuf * (*getbuffer)(void *base, const size_t view_id));
void IMB_exr_close(void *handle);
+void IMB_exr_add_view(void *handle, const char *name);
+
+bool IMB_exr_has_multilayer(void *handle);
+bool IMB_exr_has_singlelayer_multiview(void *handle);
+
#ifdef __cplusplus
} // extern "C"
#endif
diff --git a/source/blender/imbuf/intern/openexr/openexr_stub.cpp b/source/blender/imbuf/intern/openexr/openexr_stub.cpp
index 21fa878c08a..c198cac6357 100644
--- a/source/blender/imbuf/intern/openexr/openexr_stub.cpp
+++ b/source/blender/imbuf/intern/openexr/openexr_stub.cpp
@@ -32,26 +32,52 @@
#include "openexr_api.h"
#include "openexr_multi.h"
-
void *IMB_exr_get_handle (void) {return NULL;}
-void IMB_exr_add_channel (void *handle, const char *layname, const char *channame, int xstride, int ystride, float *rect) { (void)handle; (void)layname; (void)channame; (void)xstride; (void)ystride; (void)rect; }
+void *IMB_exr_get_handle_name (const char * /*name*/) { return NULL;}
+void IMB_exr_add_channel (void * /*handle*/, const char * /*layname*/, const char * /*passname*/, const char * /*view*/,
+ int /*xstride*/, int /*ystride*/, float * /*rect*/,
+ bool /*use_half_float*/) { }
+
+int IMB_exr_begin_read (void * /*handle*/, const char * /*filename*/, int * /*width*/, int * /*height*/) { return 0;}
+int IMB_exr_begin_write (void * /*handle*/, const char * /*filename*/, int /*width*/, int /*height*/, int /*compress*/, const struct StampData * /*stamp*/) { return 0;}
+void IMB_exrtile_begin_write (void * /*handle*/, const char * /*filename*/, int /*mipmap*/, int /*width*/, int /*height*/, int /*tilex*/, int /*tiley*/) { }
-int IMB_exr_begin_read (void *handle, const char *filename, int *width, int *height) { (void)handle; (void)filename; (void)width; (void)height; return 0;}
-int IMB_exr_begin_write (void *handle, const char *filename, int width, int height, int compress) { (void)handle; (void)filename; (void)width; (void)height; (void)compress; return 0;}
-void IMB_exrtile_begin_write (void *handle, const char *filename, int mipmap, int width, int height, int tilex, int tiley) { (void)handle; (void)filename; (void)mipmap; (void)width; (void)height; (void)tilex; (void)tiley; }
+void IMB_exr_set_channel (void * /*handle*/, const char * /*layname*/, const char * /*passname*/, int /*xstride*/, int /*ystride*/, float * /*rect*/) { }
+float *IMB_exr_channel_rect (void * /*handle*/, const char * /*layname*/, const char * /*passname*/, const char * /*view*/) { return NULL; }
-void IMB_exr_set_channel (void *handle, const char *layname, const char *channame, int xstride, int ystride, float *rect) { (void)handle; (void)layname; (void)channame; (void)xstride; (void)ystride; (void)rect; }
+void IMB_exr_read_channels (void * /*handle*/) { }
+void IMB_exr_write_channels (void * /*handle*/) { }
+void IMB_exrtile_write_channels (void * /*handle*/, int /*partx*/, int /*party*/, int /*level*/, const char * /*viewname*/) { }
+void IMB_exrmultiview_write_channels(void * /*handle*/, const char * /*viewname*/) { }
+void IMB_exr_clear_channels (void * /*handle*/) { }
+
+void IMB_exr_multilayer_convert(
+ void * /*handle*/, void * /*base*/,
+ void * (* /*addview*/)(void *base, const char *str),
+ void * (* /*addlayer*/)(void *base, const char *str),
+ void (* /*addpass*/)(void *base, void *lay, const char *str, float *rect, int totchan,
+ const char *chan_id, const char *view))
+{
+}
-void IMB_exr_read_channels (void *handle) { (void)handle; }
-void IMB_exr_write_channels (void *handle) { (void)handle; }
-void IMB_exrtile_write_channels (void *handle, int partx, int party, int level) { (void)handle; (void)partx; (void)party; (void)level; }
-void IMB_exrtile_clear_channels (void *handle) { (void)handle; }
+void IMB_exr_multiview_convert(
+ void * /*handle*/, void * /*base*/,
+ void (* /*addview*/)(void *base, const char *str),
+ void (* /*addbuffer*/)(void *base, const char *str, struct ImBuf *ibuf, const int frame),
+ const int /*frame*/)
+{
+}
-void IMB_exr_multilayer_convert (void *handle, void *base,
- void * (*addlayer)(void *base, const char *str),
- void (*addpass)(void *base, void *lay, const char *str, float *rect, int totchan, const char *chan_id))
+bool IMB_exr_multiview_save(
+ struct ImBuf * /*ibuf*/, const char * /*name*/, const int /*flags*/, const size_t /*totviews*/,
+ const char * (* /*getview*/)(void *base, size_t view_id),
+ struct ImBuf * (* /*getbuffer*/)(void *base, const size_t view_id))
{
- (void)handle; (void)base; (void)addlayer; (void)addpass;
+ return false;
}
-void IMB_exr_close (void *handle) { (void)handle; }
+void IMB_exr_close (void * /*handle*/) { }
+
+void IMB_exr_add_view(void * /*handle*/, const char * /*name*/) { }
+bool IMB_exr_has_multilayer(void * /*handle*/) { return false; }
+bool IMB_exr_has_singlelayer_multiview(void * /*handle*/) { return false; }
diff --git a/source/blender/imbuf/intern/png.c b/source/blender/imbuf/intern/png.c
index d00a836667e..744a05c7091 100644
--- a/source/blender/imbuf/intern/png.c
+++ b/source/blender/imbuf/intern/png.c
@@ -38,11 +38,10 @@
#include "BLI_math.h"
#include "BKE_global.h"
+#include "BKE_idprop.h"
#include "MEM_guardedalloc.h"
-#include "imbuf.h"
-
#include "IMB_imbuf_types.h"
#include "IMB_imbuf.h"
@@ -54,7 +53,7 @@
#include "IMB_colormanagement_intern.h"
typedef struct PNGReadStruct {
- unsigned char *data;
+ const unsigned char *data;
unsigned int size;
unsigned int seek;
} PNGReadStruct;
@@ -68,11 +67,18 @@ BLI_INLINE unsigned short UPSAMPLE_8_TO_16(const unsigned char _val)
return (_val << 8) + _val;
}
-int imb_is_a_png(unsigned char *mem)
+int imb_is_a_png(const unsigned char *mem)
{
int ret_val = 0;
- if (mem) ret_val = !png_sig_cmp(mem, 0, 8);
+ if (mem) {
+#if (PNG_LIBPNG_VER_MAJOR == 1) && (PNG_LIBPNG_VER_MINOR == 2)
+ /* Older version of libpng doesn't use const pointer to memory. */
+ ret_val = !png_sig_cmp((png_bytep)mem, 0, 8);
+#else
+ ret_val = !png_sig_cmp(mem, 0, 8);
+#endif
+ }
return(ret_val);
}
@@ -134,15 +140,16 @@ int imb_savepng(struct ImBuf *ibuf, const char *name, int flags)
int i, bytesperpixel, color_type = PNG_COLOR_TYPE_GRAY;
FILE *fp = NULL;
- bool is_16bit = (ibuf->ftype & PNG_16BIT) != 0;
+ bool is_16bit = (ibuf->foptions.flag & PNG_16BIT) != 0;
bool has_float = (ibuf->rect_float != NULL);
int channels_in_float = ibuf->channels ? ibuf->channels : 4;
float (*chanel_colormanage_cb)(float);
+ size_t num_bytes;
/* use the jpeg quality setting for compression */
int compression;
- compression = (int)(((float)(ibuf->ftype & 0xff) / 11.1111f));
+ compression = (int)(((float)(ibuf->foptions.quality) / 11.1111f));
compression = compression < 0 ? 0 : (compression > 9 ? 9 : compression);
if (ibuf->float_colorspace) {
@@ -185,11 +192,11 @@ int imb_savepng(struct ImBuf *ibuf, const char *name, int flags)
}
/* copy image data */
-
+ num_bytes = ((size_t)ibuf->x) * ibuf->y * bytesperpixel;
if (is_16bit)
- pixels16 = MEM_mallocN(ibuf->x * ibuf->y * bytesperpixel * sizeof(unsigned short), "png 16bit pixels");
+ pixels16 = MEM_mallocN(num_bytes * sizeof(unsigned short), "png 16bit pixels");
else
- pixels = MEM_mallocN(ibuf->x * ibuf->y * bytesperpixel * sizeof(unsigned char), "png 8bit pixels");
+ pixels = MEM_mallocN(num_bytes * sizeof(unsigned char), "png 8bit pixels");
if (pixels == NULL && pixels16 == NULL) {
png_destroy_write_struct(&png_ptr, &info_ptr);
@@ -313,7 +320,7 @@ int imb_savepng(struct ImBuf *ibuf, const char *name, int flags)
rgb[0] = chanel_colormanage_cb(from_straight[0]);
rgb[1] = chanel_colormanage_cb(from_straight[1]);
rgb[2] = chanel_colormanage_cb(from_straight[2]);
- to16[0] = ftoshort(rgb_to_bw(rgb));
+ to16[0] = ftoshort(IMB_colormanagement_get_luminance(rgb));
to16++; from_float += 4;
}
}
@@ -322,7 +329,7 @@ int imb_savepng(struct ImBuf *ibuf, const char *name, int flags)
rgb[0] = chanel_colormanage_cb(from_float[0]);
rgb[1] = chanel_colormanage_cb(from_float[1]);
rgb[2] = chanel_colormanage_cb(from_float[2]);
- to16[0] = ftoshort(rgb_to_bw(rgb));
+ to16[0] = ftoshort(IMB_colormanagement_get_luminance(rgb));
to16++; from_float += 3;
}
}
@@ -399,24 +406,25 @@ int imb_savepng(struct ImBuf *ibuf, const char *name, int flags)
/* image text info */
if (ibuf->metadata) {
png_text *metadata;
- ImMetaData *iptr;
+ IDProperty *prop;
+
int num_text = 0;
- iptr = ibuf->metadata;
- while (iptr) {
- num_text++;
- iptr = iptr->next;
+
+ for (prop = ibuf->metadata->data.group.first; prop; prop = prop->next) {
+ if (prop->type == IDP_STRING) {
+ num_text++;
+ }
}
metadata = MEM_callocN(num_text * sizeof(png_text), "png_metadata");
- iptr = ibuf->metadata;
num_text = 0;
- while (iptr) {
-
- metadata[num_text].compression = PNG_TEXT_COMPRESSION_NONE;
- metadata[num_text].key = iptr->key;
- metadata[num_text].text = iptr->value;
- num_text++;
- iptr = iptr->next;
+ for (prop = ibuf->metadata->data.group.first; prop; prop = prop->next) {
+ if (prop->type == IDP_STRING) {
+ metadata[num_text].compression = PNG_TEXT_COMPRESSION_NONE;
+ metadata[num_text].key = prop->name;
+ metadata[num_text].text = IDP_String(prop);
+ num_text++;
+ }
}
png_set_text(png_ptr, info_ptr, metadata, num_text);
@@ -454,13 +462,13 @@ int imb_savepng(struct ImBuf *ibuf, const char *name, int flags)
if (is_16bit) {
for (i = 0; i < ibuf->y; i++) {
row_pointers[ibuf->y - 1 - i] = (png_bytep)
- ((unsigned short *)pixels16 + (i * ibuf->x) * bytesperpixel);
+ ((unsigned short *)pixels16 + (((size_t)i) * ibuf->x) * bytesperpixel);
}
}
else {
for (i = 0; i < ibuf->y; i++) {
row_pointers[ibuf->y - 1 - i] = (png_bytep)
- ((unsigned char *)pixels + (i * ibuf->x) * bytesperpixel * sizeof(unsigned char));
+ ((unsigned char *)pixels + (((size_t)i) * ibuf->x) * bytesperpixel * sizeof(unsigned char));
}
}
@@ -492,7 +500,7 @@ static void imb_png_warning(png_structp UNUSED(png_ptr), png_const_charp message
* and with new libpng it became too much picky, giving a warning on
* the splash screen even.
*/
- if ((G.debug & G_DEBUG) == 0 && !strncmp(message, "iCCP", 4)) {
+ if ((G.debug & G_DEBUG) == 0 && STREQLEN(message, "iCCP", 4)) {
return;
}
fprintf(stderr, "libpng warning: %s\n", message);
@@ -503,7 +511,7 @@ static void imb_png_error(png_structp UNUSED(png_ptr), png_const_charp message)
fprintf(stderr, "libpng error: %s\n", message);
}
-ImBuf *imb_loadpng(unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE])
+ImBuf *imb_loadpng(const unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE])
{
struct ImBuf *ibuf = NULL;
png_structp png_ptr;
@@ -583,6 +591,10 @@ ImBuf *imb_loadpng(unsigned char *mem, size_t size, int flags, char colorspace[I
if (bit_depth < 8) {
png_set_expand(png_ptr);
bit_depth = 8;
+ if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) {
+ /* PNG_COLOR_TYPE_GRAY may also have alpha 'values', like with palette. */
+ bytesperpixel = 2;
+ }
}
break;
default:
@@ -594,9 +606,9 @@ ImBuf *imb_loadpng(unsigned char *mem, size_t size, int flags, char colorspace[I
ibuf = IMB_allocImBuf(width, height, 8 * bytesperpixel, 0);
if (ibuf) {
- ibuf->ftype = PNG;
+ ibuf->ftype = IMB_FTYPE_PNG;
if (bit_depth == 16)
- ibuf->ftype |= PNG_16BIT;
+ ibuf->foptions.flag |= PNG_16BIT;
if (png_get_valid(png_ptr, info_ptr, PNG_INFO_pHYs)) {
int unit_type;
@@ -682,7 +694,7 @@ ImBuf *imb_loadpng(unsigned char *mem, size_t size, int flags, char colorspace[I
else {
imb_addrectImBuf(ibuf);
- pixels = MEM_mallocN(ibuf->x * ibuf->y * bytesperpixel * sizeof(unsigned char), "pixels");
+ pixels = MEM_mallocN(((size_t)ibuf->x) * ibuf->y * bytesperpixel * sizeof(unsigned char), "pixels");
if (pixels == NULL) {
printf("Cannot allocate pixels array\n");
longjmp(png_jmpbuf(png_ptr), 1);
@@ -698,7 +710,7 @@ ImBuf *imb_loadpng(unsigned char *mem, size_t size, int flags, char colorspace[I
/* set the individual row-pointers to point at the correct offsets */
for (i = 0; i < ibuf->y; i++) {
row_pointers[ibuf->y - 1 - i] = (png_bytep)
- ((unsigned char *)pixels + (i * ibuf->x) * bytesperpixel * sizeof(unsigned char));
+ ((unsigned char *)pixels + (((size_t)i) * ibuf->x) * bytesperpixel * sizeof(unsigned char));
}
png_read_image(png_ptr, row_pointers);
diff --git a/source/blender/imbuf/intern/radiance_hdr.c b/source/blender/imbuf/intern/radiance_hdr.c
index db268546480..f97860cc66c 100644
--- a/source/blender/imbuf/intern/radiance_hdr.c
+++ b/source/blender/imbuf/intern/radiance_hdr.c
@@ -38,7 +38,7 @@
*/
#ifdef WIN32
-# include <io.h>
+# include "BLI_utildefines.h"
#endif
#include "MEM_guardedalloc.h"
@@ -72,10 +72,13 @@ typedef float fCOLOR[3];
#define COPY_RGBE(c1, c2) (c2[RED] = c1[RED], c2[GRN] = c1[GRN], c2[BLU] = c1[BLU], c2[EXP] = c1[EXP])
/* read routines */
-static unsigned char *oldreadcolrs(RGBE *scan, unsigned char *mem, int xmax)
+static const unsigned char *oldreadcolrs(RGBE *scan, const unsigned char *mem, int xmax, const unsigned char *mem_eof)
{
int i, rshift = 0, len = xmax;
while (len > 0) {
+ if (mem_eof - mem < 4) {
+ return NULL;
+ }
scan[0][RED] = *mem++;
scan[0][GRN] = *mem++;
scan[0][BLU] = *mem++;
@@ -97,34 +100,62 @@ static unsigned char *oldreadcolrs(RGBE *scan, unsigned char *mem, int xmax)
return mem;
}
-static unsigned char *freadcolrs(RGBE *scan, unsigned char *mem, int xmax)
+static const unsigned char *freadcolrs(RGBE *scan, const unsigned char *mem, int xmax, const unsigned char *mem_eof)
{
int i, j, code, val;
- if ((xmax < MINELEN) | (xmax > MAXELEN)) return oldreadcolrs(scan, mem, xmax);
+ if (mem_eof - mem < 4) {
+ return NULL;
+ }
+
+ if ((xmax < MINELEN) | (xmax > MAXELEN)) {
+ return oldreadcolrs(scan, mem, xmax, mem_eof);
+ }
i = *mem++;
- if (i != 2) return oldreadcolrs(scan, mem - 1, xmax);
+ if (i != 2) {
+ return oldreadcolrs(scan, mem - 1, xmax, mem_eof);
+ }
scan[0][GRN] = *mem++;
scan[0][BLU] = *mem++;
i = *mem++;
- if (((scan[0][BLU] << 8) | i) != xmax) return NULL;
- for (i = 0; i < 4; i++)
+ if (scan[0][GRN] != 2 || scan[0][BLU] & 128) {
+ scan[0][RED] = 2;
+ scan[0][EXP] = i;
+ return oldreadcolrs(scan + 1, mem, xmax - 1, mem_eof);
+ }
+
+ if (((scan[0][BLU] << 8) | i) != xmax) {
+ return NULL;
+ }
+
+ for (i = 0; i < 4; i++) {
+ if (mem_eof - mem < 2) {
+ return NULL;
+ }
for (j = 0; j < xmax; ) {
code = *mem++;
if (code > 128) {
code &= 127;
val = *mem++;
- while (code--)
+ while (code--) {
scan[j++][i] = (unsigned char)val;
+ }
}
- else
- while (code--)
+ else {
+ if (mem_eof - mem < code) {
+ return NULL;
+ }
+ while (code--) {
scan[j++][i] = *mem++;
+ }
+ }
}
+ }
+
return mem;
}
@@ -163,7 +194,7 @@ static void FLOAT2RGBE(fCOLOR fcol, RGBE rgbe)
/* ImBuf read */
-int imb_is_a_hdr(unsigned char *buf)
+int imb_is_a_hdr(const unsigned char *buf)
{
/* For recognition, Blender only loads first 32 bytes, so use #?RADIANCE id instead */
/* update: actually, the 'RADIANCE' part is just an optional program name, the magic word is really only the '#?' part */
@@ -173,7 +204,7 @@ int imb_is_a_hdr(unsigned char *buf)
return 0;
}
-struct ImBuf *imb_loadhdr(unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE])
+struct ImBuf *imb_loadhdr(const unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE])
{
struct ImBuf *ibuf;
RGBE *sline;
@@ -182,7 +213,7 @@ struct ImBuf *imb_loadhdr(unsigned char *mem, size_t size, int flags, char color
int found = 0;
int width = 0, height = 0;
int x, y;
- unsigned char *ptr;
+ const unsigned char *ptr, *mem_eof = mem + size;
char oriY[80], oriX[80];
if (imb_is_a_hdr((void *)mem)) {
@@ -210,7 +241,7 @@ struct ImBuf *imb_loadhdr(unsigned char *mem, size_t size, int flags, char color
else ibuf = IMB_allocImBuf(width, height, 32, (flags & IB_rect) | IB_rectfloat);
if (ibuf == NULL) return NULL;
- ibuf->ftype = RADHDR;
+ ibuf->ftype = IMB_FTYPE_RADHDR;
if (flags & IB_alphamode_detect)
ibuf->flags |= IB_alphamode_premul;
@@ -218,15 +249,14 @@ struct ImBuf *imb_loadhdr(unsigned char *mem, size_t size, int flags, char color
if (flags & IB_test) return ibuf;
/* read in and decode the actual data */
- sline = (RGBE *)MEM_mallocN(sizeof(RGBE) * width, "radhdr_read_tmpscan");
+ sline = (RGBE *)MEM_mallocN(sizeof(*sline) * width, __func__);
rect_float = ibuf->rect_float;
for (y = 0; y < height; y++) {
- ptr = freadcolrs(sline, ptr, width);
+ ptr = freadcolrs(sline, ptr, width, mem_eof);
if (ptr == NULL) {
- printf("HDR decode error\n");
- MEM_freeN(sline);
- return ibuf;
+ printf("WARNING! HDR decode error, image may be just truncated, or completely wrong...\n");
+ break;
}
for (x = 0; x < width; x++) {
/* convert to ldr */
diff --git a/source/blender/imbuf/intern/readimage.c b/source/blender/imbuf/intern/readimage.c
index f0bcfcea62d..1c83b33e296 100644
--- a/source/blender/imbuf/intern/readimage.c
+++ b/source/blender/imbuf/intern/readimage.c
@@ -58,7 +58,7 @@ static void imb_handle_alpha(ImBuf *ibuf, int flags, char colorspace[IM_MAX_SPAC
int alpha_flags;
if (colorspace) {
- if (ibuf->rect) {
+ if (ibuf->rect != NULL && ibuf->rect_float == NULL) {
/* byte buffer is never internally converted to some standard space,
* store pointer to it's color space descriptor instead
*/
@@ -103,7 +103,7 @@ static void imb_handle_alpha(ImBuf *ibuf, int flags, char colorspace[IM_MAX_SPAC
ImBuf *IMB_ibImageFromMemory(unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE], const char *descr)
{
ImBuf *ibuf;
- ImFileType *type;
+ const ImFileType *type;
char effective_colorspace[IM_MAX_SPACE] = "";
if (mem == NULL) {
@@ -133,7 +133,7 @@ ImBuf *IMB_ibImageFromMemory(unsigned char *mem, size_t size, int flags, char co
static ImBuf *IMB_ibImageFromFile(const char *filepath, int flags, char colorspace[IM_MAX_SPACE], const char *descr)
{
ImBuf *ibuf;
- ImFileType *type;
+ const ImFileType *type;
char effective_colorspace[IM_MAX_SPACE] = "";
if (colorspace)
@@ -192,22 +192,24 @@ static void imb_cache_filename(char *filename, const char *name, int flags)
{
/* read .tx instead if it exists and is not older */
if (flags & IB_tilecache) {
- BLI_strncpy(filename, name, IB_FILENAME_SIZE);
- if (!BLI_replace_extension(filename, IB_FILENAME_SIZE, ".tx"))
+ BLI_strncpy(filename, name, IMB_FILENAME_SIZE);
+ if (!BLI_replace_extension(filename, IMB_FILENAME_SIZE, ".tx"))
return;
if (BLI_file_older(name, filename))
return;
}
- BLI_strncpy(filename, name, IB_FILENAME_SIZE);
+ BLI_strncpy(filename, name, IMB_FILENAME_SIZE);
}
ImBuf *IMB_loadiffname(const char *filepath, int flags, char colorspace[IM_MAX_SPACE])
{
ImBuf *ibuf;
int file, a;
- char filepath_tx[IB_FILENAME_SIZE];
+ char filepath_tx[IMB_FILENAME_SIZE];
+
+ BLI_assert(!BLI_path_is_rel(filepath));
imb_cache_filename(filepath_tx, filepath, flags);
@@ -234,9 +236,11 @@ ImBuf *IMB_testiffname(const char *filepath, int flags)
{
ImBuf *ibuf;
int file;
- char filepath_tx[IB_FILENAME_SIZE];
+ char filepath_tx[IMB_FILENAME_SIZE];
char colorspace[IM_MAX_SPACE] = "\0";
+ BLI_assert(!BLI_path_is_rel(filepath));
+
imb_cache_filename(filepath_tx, filepath, flags);
file = BLI_open(filepath_tx, O_BINARY | O_RDONLY, 0);
@@ -257,7 +261,7 @@ ImBuf *IMB_testiffname(const char *filepath, int flags)
static void imb_loadtilefile(ImBuf *ibuf, int file, int tx, int ty, unsigned int *rect)
{
- ImFileType *type;
+ const ImFileType *type;
unsigned char *mem;
size_t size;
diff --git a/source/blender/imbuf/intern/rectop.c b/source/blender/imbuf/intern/rectop.c
index dd2406e234e..c7b347cb20c 100644
--- a/source/blender/imbuf/intern/rectop.c
+++ b/source/blender/imbuf/intern/rectop.c
@@ -39,11 +39,9 @@
#include "BLI_math_color_blend.h"
#include "BLI_math_vector.h"
-#include "imbuf.h"
#include "IMB_imbuf_types.h"
#include "IMB_imbuf.h"
-#include "IMB_allocimbuf.h"
#include "IMB_colormanagement.h"
void IMB_blend_color_byte(unsigned char dst[4], unsigned char src1[4], unsigned char src2[4], IMB_BlendMode mode)
@@ -324,30 +322,30 @@ void IMB_rectblend(ImBuf *dbuf, ImBuf *obuf, ImBuf *sbuf, unsigned short *dmask,
do_float = (sbuf && sbuf->rect_float && dbuf->rect_float && obuf->rect_float);
if (do_char) {
- drect = dbuf->rect + desty * dbuf->x + destx;
- orect = obuf->rect + origy * obuf->x + origx;
+ drect = dbuf->rect + ((size_t)desty) * dbuf->x + destx;
+ orect = obuf->rect + ((size_t)origy) * obuf->x + origx;
}
if (do_float) {
- drectf = dbuf->rect_float + (desty * dbuf->x + destx) * 4;
- orectf = obuf->rect_float + (origy * obuf->x + origx) * 4;
+ drectf = dbuf->rect_float + (((size_t)desty) * dbuf->x + destx) * 4;
+ orectf = obuf->rect_float + (((size_t)origy) * obuf->x + origx) * 4;
}
if (dmaskrect)
- dmaskrect += origy * obuf->x + origx;
+ dmaskrect += ((size_t)origy) * obuf->x + origx;
destskip = dbuf->x;
origskip = obuf->x;
if (sbuf) {
- if (do_char) srect = sbuf->rect + srcy * sbuf->x + srcx;
- if (do_float) srectf = sbuf->rect_float + (srcy * sbuf->x + srcx) * 4;
+ if (do_char) srect = sbuf->rect + ((size_t)srcy) * sbuf->x + srcx;
+ if (do_float) srectf = sbuf->rect_float + (((size_t)srcy) * sbuf->x + srcx) * 4;
srcskip = sbuf->x;
if (cmaskrect)
- cmaskrect += srcy * sbuf->x + srcx;
+ cmaskrect += ((size_t)srcy) * sbuf->x + srcx;
if (texmaskrect)
- texmaskrect += srcy * sbuf->x + srcx;
+ texmaskrect += ((size_t)srcy) * sbuf->x + srcx;
}
else {
srect = drect;
diff --git a/source/blender/imbuf/intern/rotate.c b/source/blender/imbuf/intern/rotate.c
index e98757883be..886944f6190 100644
--- a/source/blender/imbuf/intern/rotate.c
+++ b/source/blender/imbuf/intern/rotate.c
@@ -39,8 +39,6 @@
#include "IMB_imbuf_types.h"
#include "IMB_imbuf.h"
-#include "IMB_allocimbuf.h"
-
void IMB_flipy(struct ImBuf *ibuf)
{
int x, y;
diff --git a/source/blender/imbuf/intern/scaling.c b/source/blender/imbuf/intern/scaling.c
index e480f06da2b..605adffb813 100644
--- a/source/blender/imbuf/intern/scaling.c
+++ b/source/blender/imbuf/intern/scaling.c
@@ -33,7 +33,6 @@
#include "BLI_utildefines.h"
-#include "BLI_math_base.h"
#include "BLI_math_color.h"
#include "BLI_math_interp.h"
#include "MEM_guardedalloc.h"
@@ -42,7 +41,6 @@
#include "IMB_imbuf_types.h"
#include "IMB_imbuf.h"
-#include "IMB_allocimbuf.h"
#include "IMB_filter.h"
#include "BLI_sys_types.h" // for intptr_t support
@@ -1557,7 +1555,7 @@ struct ImBuf *IMB_scalefastImBuf(struct ImBuf *ibuf, unsigned int newx, unsigned
struct imbufRGBA *rectf, *_newrectf, *newrectf;
int x, y;
bool do_float = false, do_rect = false;
- int ofsx, ofsy, stepx, stepy;
+ size_t ofsx, ofsy, stepx, stepy;
rect = NULL; _newrect = NULL; newrect = NULL;
rectf = NULL; _newrectf = NULL; newrectf = NULL;
diff --git a/source/blender/imbuf/intern/stereoimbuf.c b/source/blender/imbuf/intern/stereoimbuf.c
new file mode 100644
index 00000000000..3b9da639a86
--- /dev/null
+++ b/source/blender/imbuf/intern/stereoimbuf.c
@@ -0,0 +1,1292 @@
+/*
+ * ***** 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) 2015 by Blender Foundation
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Dalai Felinto
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/imbuf/intern/stereoimbuf.c
+ * \ingroup imbuf
+ */
+
+#include <stddef.h>
+
+#include "IMB_imbuf.h"
+#include "IMB_imbuf_types.h"
+
+#include "IMB_allocimbuf.h"
+#include "IMB_filetype.h"
+#include "IMB_metadata.h"
+#include "IMB_colormanagement_intern.h"
+
+#include "imbuf.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_threads.h"
+#include "BLI_utildefines.h"
+
+#include "BLI_math.h"
+
+#include "DNA_userdef_types.h"
+#include "DNA_scene_types.h"
+
+/* prototypes */
+struct Stereo3DData;
+static void imb_stereo3d_write_doit(struct Stereo3DData *s3d_data, struct Stereo3dFormat *s3d);
+static void imb_stereo3d_read_doit(struct Stereo3DData *s3d_data, struct Stereo3dFormat *s3d);
+
+typedef struct Stereo3DData {
+ struct { float *left, *right, *stereo; } rectf;
+ struct { uchar *left, *right, *stereo; } rect;
+ size_t x, y, channels;
+ bool is_float;
+} Stereo3DData;
+
+static void imb_stereo3d_write_anaglyph(Stereo3DData *s3d, enum eStereo3dAnaglyphType mode)
+{
+ int x, y;
+ size_t width = s3d->x;
+ size_t height = s3d->y;
+ const size_t channels = s3d->channels;
+
+ const int stride_from = width;
+ const int stride_to = width;
+
+ int anaglyph_encoding[3][3] = {
+ {0, 1, 1},
+ {1, 0, 1},
+ {0, 0, 1},
+ };
+
+ int r, g, b;
+
+ r = anaglyph_encoding[mode][0];
+ g = anaglyph_encoding[mode][1];
+ b = anaglyph_encoding[mode][2];
+
+ if (s3d->is_float) {
+ float *rect_left = s3d->rectf.left;
+ float *rect_right = s3d->rectf.right;
+ float *rect_to = s3d->rectf.stereo;
+
+ if (channels == 3) {
+ for (y = 0; y < height; y++) {
+ float *to = rect_to + stride_to * y * 3;
+ float *from[2] = {
+ rect_left + stride_from * y * 3,
+ rect_right + stride_from * y * 3,
+ };
+
+ for (x = 0; x < width; x++, from[0] += 3, from[1] += 3, to += 3) {
+ to[0] = from[r][0];
+ to[1] = from[g][1];
+ to[2] = from[b][2];
+ }
+ }
+ }
+ else if (channels == 4) {
+ for (y = 0; y < height; y++) {
+ float *to = rect_to + stride_to * y * 4;
+ float *from[2] = {
+ rect_left + stride_from * y * 4,
+ rect_right + stride_from * y * 4,
+ };
+
+ for (x = 0; x < width; x++, from[0] += 4, from[1] += 4, to += 4) {
+ to[0] = from[r][0];
+ to[1] = from[g][1];
+ to[2] = from[b][2];
+ to[3] = MAX2(from[0][3], from[0][3]);
+ }
+ }
+ }
+ }
+ else {
+ uchar *rect_left = s3d->rect.left;
+ uchar *rect_right = s3d->rect.right;
+ uchar *rect_to = s3d->rect.stereo;
+
+ if (channels == 3) {
+ for (y = 0; y < height; y++) {
+ uchar *to = rect_to + stride_to * y * 3;
+ uchar *from[2] = {
+ rect_left + stride_from * y * 3,
+ rect_right + stride_from * y * 3,
+ };
+
+ for (x = 0; x < width; x++, from[0] += 3, from[1] += 3, to += 3) {
+ to[0] = from[r][0];
+ to[1] = from[g][1];
+ to[2] = from[b][2];
+ }
+ }
+ }
+ else if (channels == 4) {
+ for (y = 0; y < height; y++) {
+ uchar *to = rect_to + stride_to * y * 4;
+ uchar *from[2] = {
+ rect_left + stride_from * y * 4,
+ rect_right + stride_from * y * 4,
+ };
+
+ for (x = 0; x < width; x++, from[0] += 4, from[1] += 4, to += 4) {
+ to[0] = from[r][0];
+ to[1] = from[g][1];
+ to[2] = from[b][2];
+ to[3] = MAX2(from[0][3], from[0][3]);
+ }
+ }
+ }
+ }
+}
+
+static void imb_stereo3d_write_interlace(Stereo3DData *s3d, enum eStereo3dInterlaceType mode, const bool swap)
+{
+ int x, y;
+ size_t width = s3d->x;
+ size_t height = s3d->y;
+ const size_t channels = s3d->channels;
+
+ const int stride_from = width;
+ const int stride_to = width;
+
+ if (s3d->is_float) {
+ const float *rect_left = s3d->rectf.left;
+ const float *rect_right = s3d->rectf.right;
+ float *rect_to = s3d->rectf.stereo;
+
+ switch (mode) {
+ case S3D_INTERLACE_ROW:
+ {
+ char i = (char) swap;
+ for (y = 0; y < height; y++) {
+ float *to = rect_to + stride_to * y * channels;
+ const float *from[2] = {
+ rect_left + stride_from * y * channels,
+ rect_right + stride_from * y * channels,
+ };
+ memcpy(to, from[i], sizeof(float) * channels * stride_from);
+ i = !i;
+ }
+ break;
+ }
+ case S3D_INTERLACE_COLUMN:
+ {
+ if (channels == 1) {
+ for (y = 0; y < height; y++) {
+ float *to = rect_to + stride_to * y;
+ const float *from[2] = {
+ rect_left + stride_from * y,
+ rect_right + stride_from * y,
+ };
+
+ char i = (char) swap;
+ for (x = 0; x < width; x++, from[0] += 1, from[1] += 1, to += 1) {
+ to[0] = from[i][0];
+ i = !i;
+ }
+ }
+ }
+ else if (channels == 3) {
+ for (y = 0; y < height; y++) {
+ float *to = rect_to + stride_to * y * 3;
+ const float *from[2] = {
+ rect_left + stride_from * y * 3,
+ rect_right + stride_from * y * 3,
+ };
+
+ char i = (char) swap;
+ for (x = 0; x < width; x++, from[0] += 3, from[1] += 3, to += 3) {
+ copy_v3_v3(to, from[i]);
+ i = !i;
+ }
+ }
+ }
+ else if (channels == 4) {
+ for (y = 0; y < height; y++) {
+ float *to = rect_to + stride_to * y * channels;
+ const float *from[2] = {
+ rect_left + stride_from * y * channels,
+ rect_right + stride_from * y * channels,
+ };
+
+ char i = (char) swap;
+ for (x = 0; x < width; x++, from[0] += 4, from[1] += 4, to += 4) {
+ copy_v4_v4(to, from[i]);
+ i = !i;
+ }
+ }
+ }
+ break;
+ }
+ case S3D_INTERLACE_CHECKERBOARD:
+ {
+ if (channels == 1) {
+ char i = (char) swap;
+ for (y = 0; y < height; y++) {
+ float *to = rect_to + stride_to * y;
+ const float *from[2] = {
+ rect_left + stride_from * y,
+ rect_right + stride_from * y,
+ };
+ char j = i;
+ for (x = 0; x < width; x++, from[0] += 1, from[1] += 1, to += 1) {
+ to[0] = from[j][0];
+ j = !j;
+ }
+ i = !i;
+ }
+ }
+ else if (channels == 3) {
+ char i = (char) swap;
+ for (y = 0; y < height; y++) {
+ float *to = rect_to + stride_to * y * 3;
+ const float *from[2] = {
+ rect_left + stride_from * y * 3,
+ rect_right + stride_from * y * 3,
+ };
+ char j = i;
+ for (x = 0; x < width; x++, from[0] += 3, from[1] += 3, to += 3) {
+ copy_v3_v3(to, from[j]);
+ j = !j;
+ }
+ i = !i;
+ }
+ }
+ else if (channels == 4) {
+ char i = (char) swap;
+ for (y = 0; y < height; y++) {
+ float *to = rect_to + stride_to * y * 4;
+ const float *from[2] = {
+ rect_left + stride_from * y * 4,
+ rect_right + stride_from * y * 4,
+ };
+ char j = i;
+ for (x = 0; x < width; x++, from[0] += 4, from[1] += 4, to += 4) {
+ copy_v4_v4(to, from[j]);
+ j = !j;
+ }
+ i = !i;
+ }
+ }
+ break;
+ }
+ default:
+ {
+ break;
+ }
+ }
+ }
+ else {
+ const uchar *rect_left = s3d->rect.left;
+ const uchar *rect_right = s3d->rect.right;
+ uchar *rect_to = s3d->rect.stereo;
+
+ switch (mode) {
+ case S3D_INTERLACE_ROW:
+ {
+ char i = (char) swap;
+ for (y = 0; y < height; y++) {
+ uchar *to = rect_to + stride_to * y * channels;
+ const uchar *from[2] = {
+ rect_left + stride_from * y * channels,
+ rect_right + stride_from * y * channels,
+ };
+ memcpy(to, from[i], sizeof(uchar) * channels * stride_from);
+ i = !i;
+ }
+ break;
+ }
+ case S3D_INTERLACE_COLUMN:
+ {
+ if (channels == 1) {
+ for (y = 0; y < height; y++) {
+ uchar *to = rect_to + stride_to * y;
+ const uchar *from[2] = {
+ rect_left + stride_from * y,
+ rect_right + stride_from * y,
+ };
+ char i = (char) swap;
+ for (x = 0; x < width; x++, from[0] += 1, from[1] += 1, to += 1) {
+ to[0] = from[i][0];
+ i = !i;
+ }
+ }
+ }
+ else if (channels == 3) {
+ for (y = 0; y < height; y++) {
+ uchar *to = rect_to + stride_to * y * 3;
+ const uchar *from[2] = {
+ rect_left + stride_from * y * 3,
+ rect_right + stride_from * y * 3,
+ };
+ char i = (char) swap;
+ for (x = 0; x < width; x++, from[0] += 3, from[1] += 3, to += 3) {
+ copy_v3_v3_char((char *)to, (char *)from[i]);
+ i = !i;
+ }
+ }
+ }
+ else if (channels == 4) {
+ for (y = 0; y < height; y++) {
+ uchar *to = rect_to + stride_to * y * 4;
+ const uchar *from[2] = {
+ rect_left + stride_from * y * 4,
+ rect_right + stride_from * y * 4,
+ };
+ char i = (char) swap;
+ for (x = 0; x < width; x++, from[0] += 4, from[1] += 4, to += 4) {
+ copy_v4_v4_char((char *)to, (char *)from[i]);
+ i = !i;
+ }
+ }
+ }
+ break;
+ }
+ case S3D_INTERLACE_CHECKERBOARD:
+ {
+ if (channels == 1) {
+ char i = (char) swap;
+ for (y = 0; y < height; y++) {
+ uchar *to = rect_to + stride_to * y;
+ const uchar *from[2] = {
+ rect_left + stride_from * y,
+ rect_right + stride_from * y,
+ };
+ char j = i;
+ for (x = 0; x < width; x++, from[0] += 1, from[1] += 1, to += 1) {
+ to[0] = from[j][0];
+ j = !j;
+ }
+ i = !i;
+ }
+ }
+ else if (channels == 3) {
+ char i = (char) swap;
+ for (y = 0; y < height; y++) {
+ uchar *to = rect_to + stride_to * y * 3;
+ const uchar *from[2] = {
+ rect_left + stride_from * y * 3,
+ rect_right + stride_from * y * 3,
+ };
+ char j = i;
+ for (x = 0; x < width; x++, from[0] += 3, from[1] += 3, to += 3) {
+ copy_v3_v3_char((char *)to, (char *)from[j]);
+ j = !j;
+ }
+ i = !i;
+ }
+ }
+ else if (channels == 4) {
+ char i = (char) swap;
+ for (y = 0; y < height; y++) {
+ uchar *to = rect_to + stride_to * y * 4;
+ const uchar *from[2] = {
+ rect_left + stride_from * y * 4,
+ rect_right + stride_from * y * 4,
+ };
+ char j = i;
+ for (x = 0; x < width; x++, from[0] += 4, from[1] += 4, to += 4) {
+ copy_v4_v4_char((char *)to, (char *)from[j]);
+ j = !j;
+ }
+ i = !i;
+ }
+ }
+ break;
+ }
+ default:
+ {
+ break;
+ }
+ }
+ }
+}
+
+/* stereo3d output (s3d->rectf.stereo) is always unsqueezed */
+static void imb_stereo3d_write_sidebyside(Stereo3DData *s3d, const bool crosseyed)
+{
+ int y;
+ size_t width = s3d->x;
+ size_t height = s3d->y;
+ const size_t channels = s3d->channels;
+
+ const int stride_from = width;
+ const int stride_to = width * 2;
+
+ const int l = (int) crosseyed;
+ const int r = !l;
+
+ if (s3d->is_float) {
+ const float *rect_left = s3d->rectf.left;
+ const float *rect_right = s3d->rectf.right;
+ float *rect_to = s3d->rectf.stereo;
+
+ for (y = 0; y < height; y++) {
+ float *to = rect_to + stride_to * y * channels;
+ const float *from[2] = {
+ rect_left + stride_from * y * channels,
+ rect_right + stride_from * y * channels,
+ };
+
+ memcpy(to, from[l], sizeof(float) * channels * stride_from);
+ memcpy(to + channels * stride_from, from[r], sizeof(float) * channels * stride_from);
+ }
+ }
+ else {
+ const uchar *rect_left = s3d->rect.left;
+ const uchar *rect_right = s3d->rect.right;
+ uchar *rect_to = s3d->rect.stereo;
+
+ for (y = 0; y < height; y++) {
+ uchar *to = rect_to + stride_to * y * channels;
+ const uchar *from[2] = {
+ rect_left + stride_from * y * channels,
+ rect_right + stride_from * y * channels,
+ };
+
+ memcpy(to, from[l], sizeof(uchar) * channels * stride_from);
+ memcpy(to + channels * stride_from, from[r], sizeof(uchar) * channels * stride_from);
+ }
+ }
+}
+
+/* stereo3d output (s3d->rectf.stereo) is always unsqueezed */
+static void imb_stereo3d_write_topbottom(Stereo3DData *s3d)
+{
+ int y;
+ size_t width = s3d->x;
+ size_t height = s3d->y;
+ const size_t channels = s3d->channels;
+
+ const int stride_from = width;
+ const int stride_to = width;
+
+ if (s3d->is_float) {
+ const float *rect_left = s3d->rectf.left;
+ const float *rect_right = s3d->rectf.right;
+ float *rect_to = s3d->rectf.stereo;
+
+ for (y = 0; y < height; y++) {
+ float *to = rect_to + stride_to * y * channels;
+ const float *from[2] = {
+ rect_left + stride_from * y * channels,
+ rect_right + stride_from * y * channels,
+ };
+
+ memcpy(to, from[1], sizeof(float) * channels * stride_from);
+ memcpy(to + channels * height * stride_from, from[0], sizeof(float) * channels * stride_from);
+ }
+ }
+ else {
+ const uchar *rect_left = s3d->rect.left;
+ const uchar *rect_right = s3d->rect.right;
+ uchar *rect_to = s3d->rect.stereo;
+
+ for (y = 0; y < height; y++) {
+ uchar *to = rect_to + stride_to * y * channels;
+ const uchar *from[2] = {
+ rect_left + stride_from * y * channels,
+ rect_right + stride_from * y * channels,
+ };
+
+ memcpy(to, from[1], sizeof(uchar) * channels * stride_from);
+ memcpy(to + channels * height * stride_from, from[0], sizeof(uchar) * channels * stride_from);
+ }
+ }
+}
+
+/**************************** dimension utils ****************************************/
+
+void IMB_stereo3d_write_dimensions(
+ const char mode, const bool is_squeezed, const size_t width, const size_t height,
+ size_t *r_width, size_t *r_height)
+{
+ switch (mode) {
+ case S3D_DISPLAY_SIDEBYSIDE:
+ {
+ *r_width = is_squeezed ? width : width * 2;
+ *r_height = height;
+ break;
+ }
+ case S3D_DISPLAY_TOPBOTTOM:
+ {
+ *r_width = width;
+ *r_height = is_squeezed ? height : height * 2;
+ break;
+ }
+ case S3D_DISPLAY_ANAGLYPH:
+ case S3D_DISPLAY_INTERLACE:
+ default:
+ {
+ *r_width = width;
+ *r_height = height;
+ break;
+ }
+ }
+}
+
+void IMB_stereo3d_read_dimensions(
+ const char mode, const bool is_squeezed, const size_t width, const size_t height,
+ size_t *r_width, size_t *r_height)
+{
+ switch (mode) {
+ case S3D_DISPLAY_SIDEBYSIDE:
+ {
+ *r_width = is_squeezed ? width / 2 : width;
+ *r_height = height;
+ break;
+ }
+ case S3D_DISPLAY_TOPBOTTOM:
+ {
+ *r_width = width;
+ *r_height = is_squeezed ? height / 2 : height;
+ break;
+ }
+ case S3D_DISPLAY_ANAGLYPH:
+ case S3D_DISPLAY_INTERLACE:
+ default:
+ {
+ *r_width = width;
+ *r_height = height;
+ break;
+ }
+ }
+}
+
+/**************************** un/squeeze frame ****************************************/
+
+static void imb_stereo3d_squeeze_ImBuf(ImBuf *ibuf, Stereo3dFormat *s3d, const size_t x, const size_t y)
+{
+ if (ELEM(s3d->display_mode, S3D_DISPLAY_SIDEBYSIDE, S3D_DISPLAY_TOPBOTTOM) == false)
+ return;
+
+ if ((s3d->flag & S3D_SQUEEZED_FRAME) == 0)
+ return;
+
+ IMB_scaleImBuf_threaded(ibuf, x, y);
+}
+
+static void imb_stereo3d_unsqueeze_ImBuf(ImBuf *ibuf, Stereo3dFormat *s3d, const size_t x, const size_t y)
+{
+ if (ELEM(s3d->display_mode, S3D_DISPLAY_SIDEBYSIDE, S3D_DISPLAY_TOPBOTTOM) == false)
+ return;
+
+ if ((s3d->flag & S3D_SQUEEZED_FRAME) == 0)
+ return;
+
+ IMB_scaleImBuf_threaded(ibuf, x, y);
+}
+
+static void imb_stereo3d_squeeze_rectf(float *rectf, Stereo3dFormat *s3d, const size_t x, const size_t y, const size_t channels)
+{
+ ImBuf *ibuf;
+ size_t width, height;
+
+ if (ELEM(s3d->display_mode, S3D_DISPLAY_SIDEBYSIDE, S3D_DISPLAY_TOPBOTTOM) == false)
+ return;
+
+ if ((s3d->flag & S3D_SQUEEZED_FRAME) == 0)
+ return;
+
+ /* creates temporary imbuf to store the rectf */
+ IMB_stereo3d_write_dimensions(s3d->display_mode, false, x, y, &width, &height);
+ ibuf = IMB_allocImBuf(width, height, channels, IB_rectfloat);
+
+ IMB_buffer_float_from_float(
+ ibuf->rect_float, rectf, channels,
+ IB_PROFILE_LINEAR_RGB, IB_PROFILE_LINEAR_RGB, false,
+ width, height, width, width);
+
+ IMB_scaleImBuf_threaded(ibuf, x, y);
+ memcpy(rectf, ibuf->rect_float, x * y * sizeof(float[4]));
+ IMB_freeImBuf(ibuf);
+}
+
+static void imb_stereo3d_squeeze_rect(int *rect, Stereo3dFormat *s3d, const size_t x, const size_t y, const size_t channels)
+{
+ ImBuf *ibuf;
+ size_t width, height;
+
+ if (ELEM(s3d->display_mode, S3D_DISPLAY_SIDEBYSIDE, S3D_DISPLAY_TOPBOTTOM) == false)
+ return;
+
+ if ((s3d->flag & S3D_SQUEEZED_FRAME) == 0)
+ return;
+
+ /* creates temporary imbuf to store the rectf */
+ IMB_stereo3d_write_dimensions(s3d->display_mode, false, x, y, &width, &height);
+ ibuf = IMB_allocImBuf(width, height, channels, IB_rect);
+
+ IMB_buffer_byte_from_byte(
+ (unsigned char *)ibuf->rect, (unsigned char *)rect,
+ IB_PROFILE_SRGB, IB_PROFILE_SRGB, false,
+ width, height, width, width);
+
+ IMB_scaleImBuf_threaded(ibuf, x, y);
+ memcpy(rect, ibuf->rect, x * y * sizeof(unsigned int));
+ IMB_freeImBuf(ibuf);
+}
+
+
+/*************************** preparing to call the write functions **************************/
+
+static void imb_stereo3d_data_initialize(
+ Stereo3DData *s3d_data, const bool is_float,
+ const size_t x, const size_t y, const size_t channels,
+ int *rect_left, int *rect_right, int *rect_stereo,
+ float *rectf_left, float *rectf_right, float *rectf_stereo)
+{
+ s3d_data->is_float = is_float;
+ s3d_data->x = x;
+ s3d_data->y = y;
+ s3d_data->channels = channels;
+ s3d_data->rect.left = (uchar *)rect_left;
+ s3d_data->rect.right = (uchar *)rect_right;
+ s3d_data->rect.stereo = (uchar *)rect_stereo;
+ s3d_data->rectf.left = rectf_left;
+ s3d_data->rectf.right = rectf_right;
+ s3d_data->rectf.stereo = rectf_stereo;
+}
+
+int *IMB_stereo3d_from_rect(
+ ImageFormatData *im_format, const size_t x, const size_t y, const size_t channels,
+ int *rect_left, int *rect_right)
+{
+ int *r_rect;
+ Stereo3DData s3d_data = {{NULL}};
+ size_t width, height;
+ const bool is_float = im_format->depth > 8;
+
+ IMB_stereo3d_write_dimensions(im_format->stereo3d_format.display_mode, false, x, y, &width, &height);
+ r_rect = MEM_mallocN(channels * sizeof(int) * width * height, __func__);
+
+ imb_stereo3d_data_initialize(&s3d_data, is_float, x, y, channels, rect_left, rect_right, r_rect, NULL, NULL, NULL);
+ imb_stereo3d_write_doit(&s3d_data, &im_format->stereo3d_format);
+ imb_stereo3d_squeeze_rect(r_rect, &im_format->stereo3d_format, x, y, channels);
+
+ return r_rect;
+}
+
+float *IMB_stereo3d_from_rectf(
+ ImageFormatData *im_format, const size_t x, const size_t y, const size_t channels,
+ float *rectf_left, float *rectf_right)
+{
+ float *r_rectf;
+ Stereo3DData s3d_data = {{NULL}};
+ size_t width, height;
+ const bool is_float = im_format->depth > 8;
+
+ IMB_stereo3d_write_dimensions(im_format->stereo3d_format.display_mode, false, x, y, &width, &height);
+ r_rectf = MEM_mallocN(channels * sizeof(float) * width * height, __func__);
+
+ imb_stereo3d_data_initialize(&s3d_data, is_float, x, y, channels, NULL, NULL, NULL, rectf_left, rectf_right, r_rectf);
+ imb_stereo3d_write_doit(&s3d_data, &im_format->stereo3d_format);
+ imb_stereo3d_squeeze_rectf(r_rectf, &im_format->stereo3d_format, x, y, channels);
+
+ return r_rectf;
+}
+
+/* left/right are always float */
+ImBuf *IMB_stereo3d_ImBuf(ImageFormatData *im_format, ImBuf *ibuf_left, ImBuf *ibuf_right)
+{
+ ImBuf *ibuf_stereo = NULL;
+ Stereo3DData s3d_data = {{NULL}};
+ size_t width, height;
+ const bool is_float = im_format->depth > 8;
+
+ IMB_stereo3d_write_dimensions(im_format->stereo3d_format.display_mode, false, ibuf_left->x, ibuf_left->y, &width, &height);
+ ibuf_stereo = IMB_allocImBuf(width, height, ibuf_left->planes, (is_float ? IB_rectfloat : IB_rect));
+
+ /* copy flags for IB_fields and other settings */
+ ibuf_stereo->flags = ibuf_left->flags;
+
+ imb_stereo3d_data_initialize(
+ &s3d_data, is_float, ibuf_left->x, ibuf_left->y, 4,
+ (int *)ibuf_left->rect, (int *)ibuf_right->rect, (int *)ibuf_stereo->rect,
+ ibuf_left->rect_float, ibuf_right->rect_float, ibuf_stereo->rect_float);
+
+ imb_stereo3d_write_doit(&s3d_data, &im_format->stereo3d_format);
+ imb_stereo3d_squeeze_ImBuf(ibuf_stereo, &im_format->stereo3d_format, ibuf_left->x, ibuf_left->y);
+
+ return ibuf_stereo;
+}
+
+static void imb_stereo3d_write_doit(Stereo3DData *s3d_data, Stereo3dFormat *s3d)
+{
+ switch (s3d->display_mode) {
+ case S3D_DISPLAY_ANAGLYPH:
+ imb_stereo3d_write_anaglyph(s3d_data, s3d->anaglyph_type);
+ break;
+ case S3D_DISPLAY_INTERLACE:
+ imb_stereo3d_write_interlace(s3d_data, s3d->interlace_type, (s3d->flag & S3D_INTERLACE_SWAP) != 0);
+ break;
+ case S3D_DISPLAY_SIDEBYSIDE:
+ imb_stereo3d_write_sidebyside(s3d_data, (s3d->flag & S3D_SIDEBYSIDE_CROSSEYED) != 0);
+ break;
+ case S3D_DISPLAY_TOPBOTTOM:
+ imb_stereo3d_write_topbottom(s3d_data);
+ break;
+ default:
+ break;
+ }
+}
+
+/******************************** reading stereo imbufs **********************/
+
+static void imb_stereo3d_read_anaglyph(Stereo3DData *s3d, enum eStereo3dAnaglyphType mode)
+{
+ int x, y;
+ size_t width = s3d->x;
+ size_t height = s3d->y;
+ const size_t channels = s3d->channels;
+
+ const int stride_from = width;
+ const int stride_to = width;
+
+ int anaglyph_encoding[3][3] = {
+ {0, 1, 1},
+ {1, 0, 1},
+ {0, 0, 1},
+ };
+
+ int r, g, b;
+
+ r = anaglyph_encoding[mode][0];
+ g = anaglyph_encoding[mode][1];
+ b = anaglyph_encoding[mode][2];
+
+ if (s3d->is_float) {
+ float *rect_left = s3d->rectf.left;
+ float *rect_right = s3d->rectf.right;
+ float *rect_from = s3d->rectf.stereo;
+
+ if (channels == 3) {
+ for (y = 0; y < height; y++) {
+ float *from = rect_from + stride_from * y * 3;
+ float *to[2] = {
+ rect_left + stride_to * y * 3,
+ rect_right + stride_to * y * 3,
+ };
+
+ for (x = 0; x < width; x++, from += 3, to[0] += 3, to[1] += 3) {
+ to[r][0] = from[0];
+ to[g][1] = from[1];
+ to[b][2] = from[2];
+ }
+ }
+ }
+ else if (channels == 4) {
+ for (y = 0; y < height; y++) {
+ float *from = rect_from + stride_from * y * 4;
+ float *to[2] = {
+ rect_left + stride_to * y * 4,
+ rect_right + stride_to * y * 4,
+ };
+
+ for (x = 0; x < width; x++, from += 4, to[0] += 4, to[1] += 4) {
+ to[r][0] = from[0];
+ to[g][1] = from[1];
+ to[b][2] = from[2];
+ to[0][3] = to[1][3] = from[3];
+ }
+ }
+ }
+ }
+ else {
+ uchar *rect_left = s3d->rect.left;
+ uchar *rect_right = s3d->rect.right;
+ uchar *rect_from = s3d->rect.stereo;
+
+ if (channels == 3) {
+ for (y = 0; y < height; y++) {
+ uchar *from = rect_from + stride_from * y * 3;
+ uchar *to[2] = {
+ rect_left + stride_to * y * 3,
+ rect_right + stride_to * y * 3,
+ };
+
+ for (x = 0; x < width; x++, from += 3, to[0] += 3, to[1] += 3) {
+ to[r][0] = from[0];
+ to[g][1] = from[1];
+ to[b][2] = from[2];
+ }
+ }
+ }
+ else if (channels == 4) {
+ for (y = 0; y < height; y++) {
+ uchar *from = rect_from + stride_from * y * 4;
+ uchar *to[2] = {
+ rect_left + stride_to * y * 4,
+ rect_right + stride_to * y * 4,
+ };
+
+ for (x = 0; x < width; x++, from += 4, to[0] += 4, to[1] += 4) {
+ to[r][0] = from[0];
+ to[g][1] = from[1];
+ to[b][2] = from[2];
+ to[0][3] = to[1][3] = from[3];
+ }
+ }
+ }
+ }
+}
+
+static void imb_stereo3d_read_interlace(Stereo3DData *s3d, enum eStereo3dInterlaceType mode, const bool swap)
+{
+ int x, y;
+ size_t width = s3d->x;
+ size_t height = s3d->y;
+ const size_t channels = s3d->channels;
+
+ const int stride_from = width;
+ const int stride_to = width;
+
+ if (s3d->is_float) {
+ float *rect_left = s3d->rectf.left;
+ float *rect_right = s3d->rectf.right;
+ const float *rect_from = s3d->rectf.stereo;
+
+ switch (mode) {
+ case S3D_INTERLACE_ROW:
+ {
+ char i = (char) swap;
+ for (y = 0; y < height; y++) {
+ const float *from = rect_from + stride_from * y * channels;
+ float *to[2] = {
+ rect_left + stride_to * y * channels,
+ rect_right + stride_to * y * channels,
+ };
+ memcpy(to[i], from, sizeof(float) * channels * stride_to);
+ i = !i;
+ }
+ break;
+ }
+ case S3D_INTERLACE_COLUMN:
+ {
+ if (channels == 1) {
+ for (y = 0; y < height; y++) {
+ const float *from = rect_from + stride_from * y;
+ float *to[2] = {
+ rect_left + stride_to * y,
+ rect_right + stride_to * y,
+ };
+
+ char i = (char) swap;
+ for (x = 0; x < width; x++, from += 1, to[0] += 1, to[1] += 1) {
+ to[i][0] = from[0];
+ i = !i;
+ }
+ }
+ }
+ else if (channels == 3) {
+ for (y = 0; y < height; y++) {
+ const float *from = rect_from + stride_from * y * 3;
+ float *to[2] = {
+ rect_left + stride_to * y * 3,
+ rect_right + stride_to * y * 3,
+ };
+
+ char i = (char) swap;
+ for (x = 0; x < width; x++, from += 3, to[0] += 3, to[1] += 3) {
+ copy_v3_v3(to[i], from);
+ i = !i;
+ }
+ }
+ }
+ else if (channels == 4) {
+ for (y = 0; y < height; y++) {
+ const float *from = rect_from + stride_from * y * channels;
+ float *to[2] = {
+ rect_left + stride_to * y * channels,
+ rect_right + stride_to * y * channels,
+ };
+
+ char i = (char) swap;
+ for (x = 0; x < width; x++, from += 4, to[0] += 4, to[1] += 4) {
+ copy_v4_v4(to[i], from);
+ i = !i;
+ }
+ }
+ }
+ break;
+ }
+ case S3D_INTERLACE_CHECKERBOARD:
+ {
+ if (channels == 1) {
+ char i = (char) swap;
+ for (y = 0; y < height; y++) {
+ const float *from = rect_from + stride_from * y;
+ float *to[2] = {
+ rect_left + stride_to * y,
+ rect_right + stride_to * y,
+ };
+ char j = i;
+ for (x = 0; x < width; x++, from += 1, to[0] += 1, to[1] += 1) {
+ to[j][0] = from[0];
+ j = !j;
+ }
+ i = !i;
+ }
+ }
+ else if (channels == 3) {
+ char i = (char) swap;
+ for (y = 0; y < height; y++) {
+ const float *from = rect_from + stride_from * y * 3;
+ float *to[2] = {
+ rect_left + stride_to * y * 3,
+ rect_right + stride_to * y * 3,
+ };
+ char j = i;
+ for (x = 0; x < width; x++, from += 3, to[0] += 3, to[1] += 3) {
+ copy_v3_v3(to[j], from);
+ j = !j;
+ }
+ i = !i;
+ }
+ }
+ else if (channels == 4) {
+ char i = (char) swap;
+ for (y = 0; y < height; y++) {
+ const float *from = rect_from + stride_from * y * 4;
+ float *to[2] = {
+ rect_left + stride_to * y * 4,
+ rect_right + stride_to * y * 4,
+ };
+ char j = i;
+ for (x = 0; x < width; x++, from += 4, to[0] += 4, to[1] += 4) {
+ copy_v4_v4(to[j], from);
+ j = !j;
+ }
+ i = !i;
+ }
+ }
+ break;
+ }
+ default:
+ {
+ break;
+ }
+ }
+ }
+ else {
+ uchar *rect_left = s3d->rect.right;
+ uchar *rect_right = s3d->rect.left;
+ const uchar *rect_from = s3d->rect.stereo;
+
+ switch (mode) {
+ case S3D_INTERLACE_ROW:
+ {
+ char i = (char) swap;
+ for (y = 0; y < height; y++) {
+ const uchar *from = rect_from + stride_from * y * channels;
+ uchar *to[2] = {
+ rect_left + stride_to * y * channels,
+ rect_right + stride_to * y * channels,
+ };
+ memcpy(to[i], from, sizeof(uchar) * channels * stride_to);
+ i = !i;
+ }
+ break;
+ }
+ case S3D_INTERLACE_COLUMN:
+ {
+ if (channels == 1) {
+ for (y = 0; y < height; y++) {
+ const uchar *from = rect_from + stride_from * y;
+ uchar *to[2] = {
+ rect_left + stride_to * y,
+ rect_right + stride_to * y,
+ };
+ char i = (char) swap;
+ for (x = 0; x < width; x++, from += 1, to[0] += 1, to[1] += 1) {
+ to[i][0] = from[0];
+ i = !i;
+ }
+ }
+ }
+ else if (channels == 3) {
+ for (y = 0; y < height; y++) {
+ const uchar *from = rect_from + stride_from * y * 3;
+ uchar *to[2] = {
+ rect_left + stride_to * y * 3,
+ rect_right + stride_to * y * 3,
+ };
+ char i = (char) swap;
+ for (x = 0; x < width; x++, from += 3, to[0] += 3, to[1] += 3) {
+ copy_v3_v3_char((char *)to[i], (char *)from);
+ i = !i;
+ }
+ }
+ }
+ else if (channels == 4) {
+ for (y = 0; y < height; y++) {
+ const uchar *from = rect_from + stride_from * y * 4;
+ uchar *to[2] = {
+ rect_left + stride_to * y * 4,
+ rect_right + stride_to * y * 4,
+ };
+ char i = (char) swap;
+ for (x = 0; x < width; x++, from += 4, to[0] += 4, to[1] += 4) {
+ copy_v4_v4_char((char *)to[i], (char *)from);
+ i = !i;
+ }
+ }
+ }
+ break;
+ }
+ case S3D_INTERLACE_CHECKERBOARD:
+ {
+ if (channels == 1) {
+ char i = (char) swap;
+ for (y = 0; y < height; y++) {
+ const uchar *from = rect_from + stride_from * y;
+ uchar *to[2] = {
+ rect_left + stride_to * y,
+ rect_right + stride_to * y,
+ };
+ char j = i;
+ for (x = 0; x < width; x++, from += 1, to[0] += 1, to[1] += 1) {
+ to[j][0] = from[0];
+ j = !j;
+ }
+ i = !i;
+ }
+ }
+ else if (channels == 3) {
+ char i = (char) swap;
+ for (y = 0; y < height; y++) {
+ const uchar *from = rect_from + stride_from * y * 3;
+ uchar *to[2] = {
+ rect_left + stride_to * y * 3,
+ rect_right + stride_to * y * 3,
+ };
+ char j = i;
+ for (x = 0; x < width; x++, from += 3, to[0] += 3, to[1] += 3) {
+ copy_v3_v3_char((char *)to[j], (char *)from);
+ j = !j;
+ }
+ i = !i;
+ }
+ }
+ else if (channels == 4) {
+ char i = (char) swap;
+ for (y = 0; y < height; y++) {
+ const uchar *from = rect_from + stride_from * y * 4;
+ uchar *to[2] = {
+ rect_left + stride_to * y * 4,
+ rect_right + stride_to * y * 4,
+ };
+ char j = i;
+ for (x = 0; x < width; x++, from += 4, to[0] += 4, to[1] += 4) {
+ copy_v4_v4_char((char *)to[j], (char *)from);
+ j = !j;
+ }
+ i = !i;
+ }
+ }
+ break;
+ }
+ default:
+ {
+ break;
+ }
+ }
+ }
+}
+
+/* stereo input (s3d->rectf.stereo) is always unsqueezed */
+static void imb_stereo3d_read_sidebyside(Stereo3DData *s3d, const bool crosseyed)
+{
+ int y;
+ size_t width = s3d->x;
+ size_t height = s3d->y;
+ const size_t channels = s3d->channels;
+
+ const int stride_from = width * 2;
+ const int stride_to = width;
+
+ const int l = (int) crosseyed;
+ const int r = !l;
+
+ if (s3d->is_float) {
+ float *rect_left = s3d->rectf.left;
+ float *rect_right = s3d->rectf.right;
+ const float *rect_from = s3d->rectf.stereo;
+
+ for (y = 0; y < height; y++) {
+ const float *from = rect_from + stride_from * y * channels;
+ float *to[2] = {
+ rect_left + stride_to * y * channels,
+ rect_right + stride_to * y * channels,
+ };
+
+ memcpy(to[l], from, sizeof(float) * channels * stride_to);
+ memcpy(to[r], from + channels * stride_to, sizeof(float) * channels * stride_to);
+ }
+ }
+ else {
+ uchar *rect_left = s3d->rect.left;
+ uchar *rect_right = s3d->rect.right;
+ const uchar *rect_from = s3d->rect.stereo;
+
+ /* always RGBA input/output */
+ for (y = 0; y < height; y++) {
+ const uchar *from = rect_from + stride_from * y * channels;
+ uchar *to[2] = {
+ rect_left + stride_to * y * channels,
+ rect_right + stride_to * y * channels,
+ };
+
+ memcpy(to[l], from, sizeof(uchar) * channels * stride_to);
+ memcpy(to[r], from + channels * stride_to, sizeof(uchar) * channels * stride_to);
+ }
+ }
+}
+
+/* stereo input (s3d->rectf.stereo) is always unsqueezed */
+static void imb_stereo3d_read_topbottom(Stereo3DData *s3d)
+{
+ int y;
+ size_t width = s3d->x;
+ size_t height = s3d->y;
+ const size_t channels = s3d->channels;
+
+ const int stride_from = width;
+ const int stride_to = width;
+
+ if (s3d->is_float) {
+ float *rect_left = s3d->rectf.left;
+ float *rect_right = s3d->rectf.right;
+ const float *rect_from = s3d->rectf.stereo;
+
+ for (y = 0; y < height; y++) {
+ const float *from = rect_from + stride_from * y * channels;
+ float *to[2] = {
+ rect_left + stride_to * y * channels,
+ rect_right + stride_to * y * channels,
+ };
+
+ memcpy(to[1], from, sizeof(float) * channels * stride_to);
+ memcpy(to[0], from + channels * height * stride_to, sizeof(float) * channels * stride_to);
+ }
+ }
+ else {
+ uchar *rect_left = s3d->rect.left;
+ uchar *rect_right = s3d->rect.right;
+ const uchar *rect_from = s3d->rect.stereo;
+
+ for (y = 0; y < height; y++) {
+ const uchar *from = rect_from + stride_from * y * channels;
+ uchar *to[2] = {
+ rect_left + stride_to * y * channels,
+ rect_right + stride_to * y * channels,
+ };
+
+ memcpy(to[1], from, sizeof(uchar) * channels * stride_to);
+ memcpy(to[0], from + channels * height * stride_to, sizeof(uchar) * channels * stride_to);
+ }
+ }
+}
+
+
+/*************************** preparing to call the read functions **************************/
+
+/* reading a stereo encoded ibuf (*left) and generating two ibufs from it (*left and *right) */
+void IMB_ImBufFromStereo3d(
+ Stereo3dFormat *s3d, ImBuf *ibuf_stereo3d,
+ ImBuf **r_ibuf_left, ImBuf **r_ibuf_right)
+{
+ Stereo3DData s3d_data = {{NULL}};
+ ImBuf *ibuf_left, *ibuf_right;
+ size_t width, height;
+ const bool is_float = (ibuf_stereo3d->rect_float != NULL);
+
+ IMB_stereo3d_read_dimensions(
+ s3d->display_mode, ((s3d->flag & S3D_SQUEEZED_FRAME) == 0), ibuf_stereo3d->x, ibuf_stereo3d->y,
+ &width, &height);
+
+ ibuf_left = IMB_allocImBuf(width, height, ibuf_stereo3d->planes, (is_float ? IB_rectfloat : IB_rect));
+ ibuf_right = IMB_allocImBuf(width, height, ibuf_stereo3d->planes, (is_float ? IB_rectfloat : IB_rect));
+
+ /* copy flags for IB_fields and other settings */
+ ibuf_left->flags = ibuf_stereo3d->flags;
+ ibuf_right->flags = ibuf_stereo3d->flags;
+
+ /* we always work with unsqueezed formats */
+ IMB_stereo3d_write_dimensions(
+ s3d->display_mode, ((s3d->flag & S3D_SQUEEZED_FRAME) == 0), ibuf_stereo3d->x, ibuf_stereo3d->y,
+ &width, &height);
+ imb_stereo3d_unsqueeze_ImBuf(ibuf_stereo3d, s3d, width, height);
+
+ imb_stereo3d_data_initialize(
+ &s3d_data, is_float, ibuf_left->x, ibuf_left->y, 4,
+ (int *)ibuf_left->rect, (int *)ibuf_right->rect, (int *)ibuf_stereo3d->rect,
+ ibuf_left->rect_float, ibuf_right->rect_float, ibuf_stereo3d->rect_float);
+
+ imb_stereo3d_read_doit(&s3d_data, s3d);
+
+ if (ibuf_stereo3d->flags & (IB_zbuf | IB_zbuffloat)) {
+ if (is_float) {
+ addzbuffloatImBuf(ibuf_left);
+ addzbuffloatImBuf(ibuf_right);
+ }
+ else {
+ addzbufImBuf(ibuf_left);
+ addzbufImBuf(ibuf_right);
+ }
+
+ imb_stereo3d_data_initialize(
+ &s3d_data, is_float, ibuf_left->x, ibuf_left->y, 1,
+ (int *)ibuf_left->zbuf, (int *)ibuf_right->zbuf, (int *)ibuf_stereo3d->zbuf,
+ ibuf_left->zbuf_float, ibuf_right->zbuf_float, ibuf_stereo3d->zbuf_float);
+
+ imb_stereo3d_read_doit(&s3d_data, s3d);
+ }
+
+ IMB_freeImBuf(ibuf_stereo3d);
+
+ *r_ibuf_left = ibuf_left;
+ *r_ibuf_right = ibuf_right;
+}
+
+static void imb_stereo3d_read_doit(Stereo3DData *s3d_data, Stereo3dFormat *s3d)
+{
+ switch (s3d->display_mode) {
+ case S3D_DISPLAY_ANAGLYPH:
+ imb_stereo3d_read_anaglyph(s3d_data, s3d->anaglyph_type);
+ break;
+ case S3D_DISPLAY_INTERLACE:
+ imb_stereo3d_read_interlace(s3d_data, s3d->interlace_type, (s3d->flag & S3D_INTERLACE_SWAP) != 0);
+ break;
+ case S3D_DISPLAY_SIDEBYSIDE:
+ imb_stereo3d_read_sidebyside(s3d_data, (s3d->flag & S3D_SIDEBYSIDE_CROSSEYED) != 0);
+ break;
+ case S3D_DISPLAY_TOPBOTTOM:
+ imb_stereo3d_read_topbottom(s3d_data);
+ break;
+ default:
+ break;
+ }
+}
diff --git a/source/blender/imbuf/intern/targa.c b/source/blender/imbuf/intern/targa.c
index 2dcb27a05d4..7073d34e2bc 100644
--- a/source/blender/imbuf/intern/targa.c
+++ b/source/blender/imbuf/intern/targa.c
@@ -44,7 +44,6 @@
#include "IMB_imbuf_types.h"
#include "IMB_imbuf.h"
-#include "IMB_allocimbuf.h"
#include "IMB_filetype.h"
#include "IMB_colormanagement.h"
@@ -265,7 +264,7 @@ int imb_savetarga(struct ImBuf *ibuf, const char *name, int flags)
buf[2] = 11;
}
- if (ibuf->ftype == RAWTGA) buf[2] &= ~8;
+ if (ibuf->foptions.flag & RAWTGA) buf[2] &= ~8;
buf[8] = 0;
buf[9] = 0;
@@ -290,7 +289,7 @@ int imb_savetarga(struct ImBuf *ibuf, const char *name, int flags)
return 0;
}
- if (ibuf->ftype == RAWTGA) {
+ if (ibuf->foptions.flag & RAWTGA) {
ok = dumptarga(ibuf, fildes);
}
else {
@@ -315,7 +314,7 @@ int imb_savetarga(struct ImBuf *ibuf, const char *name, int flags)
}
-static int checktarga(TARGA *tga, unsigned char *mem)
+static int checktarga(TARGA *tga, const unsigned char *mem)
{
tga->numid = mem[0];
tga->maptyp = mem[1];
@@ -351,7 +350,7 @@ static int checktarga(TARGA *tga, unsigned char *mem)
return 1;
}
-int imb_is_a_targa(unsigned char *buf)
+int imb_is_a_targa(const unsigned char *buf)
{
TARGA tga;
@@ -373,9 +372,9 @@ static void complete_partial_load(struct ImBuf *ibuf, unsigned int *rect)
}
}
-static void decodetarga(struct ImBuf *ibuf, unsigned char *mem, size_t mem_size, int psize)
+static void decodetarga(struct ImBuf *ibuf, const unsigned char *mem, size_t mem_size, int psize)
{
- unsigned char *mem_end = mem + mem_size;
+ const unsigned char *mem_end = mem + mem_size;
int count, col, size;
unsigned int *rect;
uchar *cp = (uchar *) &col;
@@ -491,9 +490,9 @@ partial_load:
complete_partial_load(ibuf, rect);
}
-static void ldtarga(struct ImBuf *ibuf, unsigned char *mem, size_t mem_size, int psize)
+static void ldtarga(struct ImBuf *ibuf, const unsigned char *mem, size_t mem_size, int psize)
{
- unsigned char *mem_end = mem + mem_size;
+ const unsigned char *mem_end = mem + mem_size;
int col, size;
unsigned int *rect;
uchar *cp = (uchar *) &col;
@@ -551,7 +550,7 @@ partial_load:
}
-ImBuf *imb_loadtarga(unsigned char *mem, size_t mem_size, int flags, char colorspace[IM_MAX_SPACE])
+ImBuf *imb_loadtarga(const unsigned char *mem, size_t mem_size, int flags, char colorspace[IM_MAX_SPACE])
{
TARGA tga;
struct ImBuf *ibuf;
@@ -569,7 +568,9 @@ ImBuf *imb_loadtarga(unsigned char *mem, size_t mem_size, int flags, char colors
else ibuf = IMB_allocImBuf(tga.xsize, tga.ysize, (tga.pixsize + 0x7) & ~0x7, IB_rect);
if (ibuf == NULL) return NULL;
- ibuf->ftype = TGA;
+ ibuf->ftype = IMB_FTYPE_TGA;
+ if (tga.imgtyp < 4)
+ ibuf->foptions.flag |= RAWTGA;
mem = mem + 18 + tga.numid;
cp[0] = 0xff;
diff --git a/source/blender/imbuf/intern/thumbs.c b/source/blender/imbuf/intern/thumbs.c
index 9a97a142198..e7bec7e643c 100644
--- a/source/blender/imbuf/intern/thumbs.c
+++ b/source/blender/imbuf/intern/thumbs.c
@@ -30,15 +30,22 @@
*/
#include <stdio.h>
+#include <stdlib.h>
+
+#include "MEM_guardedalloc.h"
#include "BLI_utildefines.h"
#include "BLI_string.h"
#include "BLI_path_util.h"
#include "BLI_fileops.h"
-#include "BLI_md5.h"
+#include "BLI_ghash.h"
+#include "BLI_hash_md5.h"
#include "BLI_system.h"
+#include "BLI_threads.h"
#include BLI_SYSTEM_PID_H
+#include "BLO_readfile.h"
+
#include "IMB_imbuf_types.h"
#include "IMB_imbuf.h"
#include "IMB_thumbs.h"
@@ -199,6 +206,17 @@ static void escape_uri_string(const char *string, char *escaped_string, int esca
/** ----- end of adapted code from glib --- */
+static bool thumbhash_from_path(const char *UNUSED(path), ThumbSource source, char *r_hash)
+{
+ switch (source) {
+ case THB_SOURCE_FONT:
+ return IMB_thumb_load_font_get_hash(r_hash);
+ default:
+ r_hash[0] = '\0';
+ return false;
+ }
+}
+
static int uri_from_filename(const char *path, char *uri)
{
char orig_uri[URI_MAX];
@@ -221,7 +239,7 @@ static int uri_from_filename(const char *path, char *uri)
dirstart += 2;
}
strcat(orig_uri, dirstart);
- BLI_char_switch(orig_uri, '\\', '/');
+ BLI_str_replace_char(orig_uri, '\\', '/');
#else
BLI_snprintf(orig_uri, URI_MAX, "file://%s", dirstart);
#endif
@@ -238,47 +256,69 @@ static int uri_from_filename(const char *path, char *uri)
return 1;
}
-static void thumbname_from_uri(const char *uri, char *thumb, const int thumb_len)
+static bool thumbpathname_from_uri(
+ const char *uri, char *r_path, const int path_len, char *r_name, int name_len, ThumbSize size)
{
- char hexdigest[33];
- unsigned char digest[16];
+ char name_buff[40];
+
+ if (r_path && !r_name) {
+ r_name = name_buff;
+ name_len = sizeof(name_buff);
+ }
- md5_buffer(uri, strlen(uri), digest);
- hexdigest[0] = '\0';
- BLI_snprintf(thumb, thumb_len, "%s.png", md5_to_hexdigest(digest, hexdigest));
+ if (r_name) {
+ char hexdigest[33];
+ unsigned char digest[16];
+ BLI_hash_md5_buffer(uri, strlen(uri), digest);
+ hexdigest[0] = '\0';
+ BLI_snprintf(r_name, name_len, "%s.png", BLI_hash_md5_to_hexdigest(digest, hexdigest));
+// printf("%s: '%s' --> '%s'\n", __func__, uri, r_name);
+ }
- // printf("%s: '%s' --> '%s'\n", __func__, uri, thumb);
+ if (r_path) {
+ char tmppath[FILE_MAX];
+
+ if (get_thumb_dir(tmppath, size)) {
+ BLI_snprintf(r_path, path_len, "%s%s", tmppath, r_name);
+// printf("%s: '%s' --> '%s'\n", __func__, uri, r_path);
+ return true;
+ }
+ }
+ return false;
}
-static int thumbpath_from_uri(const char *uri, char *path, const int path_len, ThumbSize size)
+static void thumbname_from_uri(const char *uri, char *thumb, const int thumb_len)
{
- char tmppath[FILE_MAX];
- int rv = 0;
-
- if (get_thumb_dir(tmppath, size)) {
- char thumb[40];
- thumbname_from_uri(uri, thumb, sizeof(thumb));
- BLI_snprintf(path, path_len, "%s%s", tmppath, thumb);
- rv = 1;
- }
- return rv;
+ thumbpathname_from_uri(uri, NULL, 0, thumb, thumb_len, THB_FAIL);
+}
+
+static bool thumbpath_from_uri(const char *uri, char *path, const int path_len, ThumbSize size)
+{
+ return thumbpathname_from_uri(uri, path, path_len, NULL, 0, size);
}
void IMB_thumb_makedirs(void)
{
char tpath[FILE_MAX];
+#if 0 /* UNUSED */
if (get_thumb_dir(tpath, THB_NORMAL)) {
BLI_dir_create_recursive(tpath);
}
+#endif
+ if (get_thumb_dir(tpath, THB_LARGE)) {
+ BLI_dir_create_recursive(tpath);
+ }
if (get_thumb_dir(tpath, THB_FAIL)) {
BLI_dir_create_recursive(tpath);
}
}
/* create thumbnail for file and returns new imbuf for thumbnail */
-ImBuf *IMB_thumb_create(const char *path, ThumbSize size, ThumbSource source, ImBuf *img)
+static ImBuf *thumb_create_ex(
+ const char *file_path, const char *uri, const char *thumb, const bool use_hash, const char *hash,
+ const char *blen_group, const char *blen_id,
+ ThumbSize size, ThumbSource source, ImBuf *img)
{
- char uri[URI_MAX] = "";
char desc[URI_MAX + 22];
char tpath[FILE_MAX];
char tdir[FILE_MAX];
@@ -286,7 +326,6 @@ ImBuf *IMB_thumb_create(const char *path, ThumbSize size, ThumbSource source, Im
char mtime[40] = "0"; /* in case we can't stat the file */
char cwidth[40] = "0"; /* in case images have no data */
char cheight[40] = "0";
- char thumb[40];
short tsize = 128;
short ex, ey;
float scaledx, scaledy;
@@ -294,10 +333,10 @@ ImBuf *IMB_thumb_create(const char *path, ThumbSize size, ThumbSource source, Im
switch (size) {
case THB_NORMAL:
- tsize = 128;
+ tsize = PREVIEW_RENDER_DEFAULT_HEIGHT;
break;
case THB_LARGE:
- tsize = 256;
+ tsize = PREVIEW_RENDER_DEFAULT_HEIGHT * 2;
break;
case THB_FAIL:
tsize = 1;
@@ -308,20 +347,18 @@ ImBuf *IMB_thumb_create(const char *path, ThumbSize size, ThumbSource source, Im
/* exception, skip images over 100mb */
if (source == THB_SOURCE_IMAGE) {
- const size_t file_size = BLI_file_size(path);
+ const size_t file_size = BLI_file_size(file_path);
if (file_size != -1 && file_size > THUMB_SIZE_MAX) {
- // printf("file too big: %d, skipping %s\n", (int)size, path);
+ // printf("file too big: %d, skipping %s\n", (int)size, file_path);
return NULL;
}
}
- uri_from_filename(path, uri);
- thumbname_from_uri(uri, thumb, sizeof(thumb));
if (get_thumb_dir(tdir, size)) {
BLI_snprintf(tpath, FILE_MAX, "%s%s", tdir, thumb);
- thumb[8] = '\0'; /* shorten for tempname, not needed anymore */
+// thumb[8] = '\0'; /* shorten for tempname, not needed anymore */
BLI_snprintf(temp, FILE_MAX, "%sblender_%d_%s.png", tdir, abs(getpid()), thumb);
- if (BLI_path_ncmp(path, tdir, sizeof(tdir)) == 0) {
+ if (BLI_path_ncmp(file_path, tdir, sizeof(tdir)) == 0) {
return NULL;
}
if (size == THB_FAIL) {
@@ -329,32 +366,39 @@ ImBuf *IMB_thumb_create(const char *path, ThumbSize size, ThumbSource source, Im
if (!img) return NULL;
}
else {
- if (THB_SOURCE_IMAGE == source || THB_SOURCE_BLEND == source) {
-
+ if (ELEM(source, THB_SOURCE_IMAGE, THB_SOURCE_BLEND, THB_SOURCE_FONT)) {
/* only load if we didnt give an image */
if (img == NULL) {
- if (THB_SOURCE_BLEND == source) {
- img = IMB_loadblend_thumb(path);
- }
- else {
- img = IMB_loadiffname(path, IB_rect | IB_metadata, NULL);
+ switch (source) {
+ case THB_SOURCE_IMAGE:
+ img = IMB_loadiffname(file_path, IB_rect | IB_metadata, NULL);
+ break;
+ case THB_SOURCE_BLEND:
+ img = IMB_thumb_load_blend(file_path, blen_group, blen_id);
+ break;
+ case THB_SOURCE_FONT:
+ img = IMB_thumb_load_font(file_path, tsize, tsize);
+ break;
+ default:
+ BLI_assert(0); /* This should never happen */
}
}
if (img != NULL) {
- BLI_stat(path, &info);
- BLI_snprintf(mtime, sizeof(mtime), "%ld", (long int)info.st_mtime);
+ if (BLI_stat(file_path, &info) != -1) {
+ BLI_snprintf(mtime, sizeof(mtime), "%ld", (long int)info.st_mtime);
+ }
BLI_snprintf(cwidth, sizeof(cwidth), "%d", img->x);
BLI_snprintf(cheight, sizeof(cheight), "%d", img->y);
}
}
else if (THB_SOURCE_MOVIE == source) {
struct anim *anim = NULL;
- anim = IMB_open_anim(path, IB_rect | IB_metadata, 0, NULL);
+ anim = IMB_open_anim(file_path, IB_rect | IB_metadata, 0, NULL);
if (anim != NULL) {
img = IMB_anim_absolute(anim, 0, IMB_TC_NONE, IMB_PROXY_NONE);
if (img == NULL) {
- printf("not an anim; %s\n", path);
+ printf("not an anim; %s\n", file_path);
}
else {
IMB_freeImBuf(img);
@@ -362,8 +406,9 @@ ImBuf *IMB_thumb_create(const char *path, ThumbSize size, ThumbSource source, Im
}
IMB_free_anim(anim);
}
- BLI_stat(path, &info);
- BLI_snprintf(mtime, sizeof(mtime), "%ld", (long int)info.st_mtime);
+ if (BLI_stat(file_path, &info) != -1) {
+ BLI_snprintf(mtime, sizeof(mtime), "%ld", (long int)info.st_mtime);
+ }
}
if (!img) return NULL;
@@ -377,7 +422,7 @@ ImBuf *IMB_thumb_create(const char *path, ThumbSize size, ThumbSource source, Im
}
ex = (short)scaledx;
ey = (short)scaledy;
-
+
/* save some time by only scaling byte buf */
if (img->rect_float) {
if (img->rect == NULL) {
@@ -394,13 +439,20 @@ ImBuf *IMB_thumb_create(const char *path, ThumbSize size, ThumbSource source, Im
IMB_metadata_change_field(img, "Software", "Blender");
IMB_metadata_change_field(img, "Thumb::URI", uri);
IMB_metadata_change_field(img, "Thumb::MTime", mtime);
- if (THB_SOURCE_IMAGE == source) {
+ if (use_hash) {
+ IMB_metadata_change_field(img, "X-Blender::Hash", hash);
+ }
+ if (ELEM(source, THB_SOURCE_IMAGE, THB_SOURCE_BLEND, THB_SOURCE_FONT)) {
IMB_metadata_change_field(img, "Thumb::Image::Width", cwidth);
IMB_metadata_change_field(img, "Thumb::Image::Height", cheight);
}
- img->ftype = PNG;
+ img->ftype = IMB_FTYPE_PNG;
img->planes = 32;
+ /* If we generated from a 16bit PNG e.g., we have a float rect, not a byte one - fix this. */
+ IMB_rect_from_float(img);
+ imb_freerectfloatImBuf(img);
+
if (IMB_saveiff(img, temp, IB_rect | IB_metadata)) {
#ifndef WIN32
chmod(temp, S_IRUSR | S_IWUSR);
@@ -409,12 +461,40 @@ ImBuf *IMB_thumb_create(const char *path, ThumbSize size, ThumbSource source, Im
BLI_rename(temp, tpath);
}
+ }
+ return img;
+}
- return img;
+static ImBuf *thumb_create_or_fail(
+ const char *file_path, const char *uri, const char *thumb, const bool use_hash, const char *hash,
+ const char *blen_group, const char *blen_id, ThumbSize size, ThumbSource source)
+{
+ ImBuf *img = thumb_create_ex(file_path, uri, thumb, use_hash, hash, blen_group, blen_id, size, source, NULL);
+
+ if (!img) {
+ /* thumb creation failed, write fail thumb */
+ img = thumb_create_ex(file_path, uri, thumb, use_hash, hash, blen_group, blen_id, THB_FAIL, source, NULL);
+ if (img) {
+ /* we don't need failed thumb anymore */
+ IMB_freeImBuf(img);
+ img = NULL;
+ }
}
+
return img;
}
+ImBuf *IMB_thumb_create(const char *path, ThumbSize size, ThumbSource source, ImBuf *img)
+{
+ char uri[URI_MAX] = "";
+ char thumb_name[40];
+
+ uri_from_filename(path, uri);
+ thumbname_from_uri(uri, thumb_name, sizeof(thumb_name));
+
+ return thumb_create_ex(path, uri, thumb_name, false, THUMB_DEFAULT_HASH, NULL, NULL, size, source, img);
+}
+
/* read thumbnail for file and returns new imbuf for thumbnail */
ImBuf *IMB_thumb_read(const char *path, ThumbSize size)
{
@@ -453,25 +533,43 @@ void IMB_thumb_delete(const char *path, ThumbSize size)
/* create the thumb if necessary and manage failed and old thumbs */
-ImBuf *IMB_thumb_manage(const char *path, ThumbSize size, ThumbSource source)
+ImBuf *IMB_thumb_manage(const char *org_path, ThumbSize size, ThumbSource source)
{
- char thumb[FILE_MAX];
+ char thumb_path[FILE_MAX];
+ char thumb_name[40];
char uri[URI_MAX];
+ char path_buff[FILE_MAX];
+ const char *file_path;
+ const char *path;
BLI_stat_t st;
ImBuf *img = NULL;
-
- if (BLI_stat(path, &st)) {
+ char *blen_group = NULL, *blen_id = NULL;
+
+ path = file_path = org_path;
+ if (source == THB_SOURCE_BLEND) {
+ if (BLO_library_path_explode(path, path_buff, &blen_group, &blen_id)) {
+ if (blen_group) {
+ if (!blen_id) {
+ /* No preview for blen groups */
+ return NULL;
+ }
+ file_path = path_buff; /* path needs to be a valid file! */
+ }
+ }
+ }
+
+ if (BLI_stat(file_path, &st) == -1) {
return NULL;
}
if (!uri_from_filename(path, uri)) {
return NULL;
}
- if (thumbpath_from_uri(uri, thumb, sizeof(thumb), THB_FAIL)) {
+ if (thumbpath_from_uri(uri, thumb_path, sizeof(thumb_path), THB_FAIL)) {
/* failure thumb exists, don't try recreating */
- if (BLI_exists(thumb)) {
- /* clear out of date fail case */
- if (BLI_file_older(thumb, path)) {
- BLI_delete(thumb, false, false);
+ if (BLI_exists(thumb_path)) {
+ /* clear out of date fail case (note for blen IDs we use blender file itself here) */
+ if (BLI_file_older(thumb_path, file_path)) {
+ BLI_delete(thumb_path, false, false);
}
else {
return NULL;
@@ -479,55 +577,142 @@ ImBuf *IMB_thumb_manage(const char *path, ThumbSize size, ThumbSource source)
}
}
- if (thumbpath_from_uri(uri, thumb, sizeof(thumb), size)) {
- if (BLI_path_ncmp(path, thumb, sizeof(thumb)) == 0) {
+ if (thumbpathname_from_uri(uri, thumb_path, sizeof(thumb_path), thumb_name, sizeof(thumb_name), size)) {
+ if (BLI_path_ncmp(path, thumb_path, sizeof(thumb_path)) == 0) {
img = IMB_loadiffname(path, IB_rect, NULL);
}
else {
- img = IMB_loadiffname(thumb, IB_rect | IB_metadata, NULL);
+ img = IMB_loadiffname(thumb_path, IB_rect | IB_metadata, NULL);
if (img) {
+ bool regenerate = false;
+
char mtime[40];
- if (!IMB_metadata_get_field(img, "Thumb::MTime", mtime, 40)) {
- /* illegal thumb, forget it! */
- IMB_freeImBuf(img);
- img = NULL;
+ char thumb_hash[33];
+ char thumb_hash_curr[33];
+
+ const bool use_hash = thumbhash_from_path(file_path, source, thumb_hash);
+
+ if (IMB_metadata_get_field(img, "Thumb::MTime", mtime, sizeof(mtime))) {
+ regenerate = (st.st_mtime != atol(mtime));
}
else {
- time_t t = atol(mtime);
- if (st.st_mtime != t) {
- /* recreate all thumbs */
- IMB_freeImBuf(img);
- img = NULL;
- IMB_thumb_delete(path, THB_NORMAL);
- IMB_thumb_delete(path, THB_LARGE);
- IMB_thumb_delete(path, THB_FAIL);
- img = IMB_thumb_create(path, size, source, NULL);
- if (!img) {
- /* thumb creation failed, write fail thumb */
- img = IMB_thumb_create(path, THB_FAIL, source, NULL);
- if (img) {
- /* we don't need failed thumb anymore */
- IMB_freeImBuf(img);
- img = NULL;
- }
- }
+ /* illegal thumb, regenerate it! */
+ regenerate = true;
+ }
+
+ if (use_hash && !regenerate) {
+ if (IMB_metadata_get_field(img, "X-Blender::Hash", thumb_hash_curr, sizeof(thumb_hash_curr))) {
+ regenerate = !STREQ(thumb_hash, thumb_hash_curr);
+ }
+ else {
+ regenerate = true;
}
}
+
+ if (regenerate) {
+ /* recreate all thumbs */
+ IMB_freeImBuf(img);
+ img = NULL;
+ IMB_thumb_delete(path, THB_NORMAL);
+ IMB_thumb_delete(path, THB_LARGE);
+ IMB_thumb_delete(path, THB_FAIL);
+ img = thumb_create_or_fail(
+ file_path, uri, thumb_name, use_hash, thumb_hash, blen_group, blen_id, size, source);
+ }
}
else {
- img = IMB_thumb_create(path, size, source, NULL);
- if (!img) {
- /* thumb creation failed, write fail thumb */
- img = IMB_thumb_create(path, THB_FAIL, source, NULL);
- if (img) {
- /* we don't need failed thumb anymore */
- IMB_freeImBuf(img);
- img = NULL;
- }
- }
+ char thumb_hash[33];
+ const bool use_hash = thumbhash_from_path(file_path, source, thumb_hash);
+
+ img = thumb_create_or_fail(
+ file_path, uri, thumb_name, use_hash, thumb_hash, blen_group, blen_id, size, source);
}
}
}
+ /* Our imbuf **must** have a valid rect (i.e. 8-bits/channels) data, we rely on this in draw code.
+ * However, in some cases we may end loading 16bits PNGs, which generated float buffers.
+ * This should be taken care of in generation step, but add also a safeguard here! */
+ if (img) {
+ IMB_rect_from_float(img);
+ imb_freerectfloatImBuf(img);
+ }
+
return img;
}
+
+/* ***** Threading ***** */
+/* Thumbnail handling is not really threadsafe in itself.
+ * However, as long as we do not operate on the same file, we shall have no collision.
+ * So idea is to 'lock' a given source file path.
+ */
+
+static struct IMBThumbLocks {
+ GSet *locked_paths;
+ int lock_counter;
+ ThreadCondition cond;
+} thumb_locks = {0};
+
+void IMB_thumb_locks_acquire(void)
+{
+ BLI_lock_thread(LOCK_IMAGE);
+
+ if (thumb_locks.lock_counter == 0) {
+ BLI_assert(thumb_locks.locked_paths == NULL);
+ thumb_locks.locked_paths = BLI_gset_str_new(__func__);
+ BLI_condition_init(&thumb_locks.cond);
+ }
+ thumb_locks.lock_counter++;
+
+ BLI_assert(thumb_locks.locked_paths != NULL);
+ BLI_assert(thumb_locks.lock_counter > 0);
+ BLI_unlock_thread(LOCK_IMAGE);
+}
+
+void IMB_thumb_locks_release(void)
+{
+ BLI_lock_thread(LOCK_IMAGE);
+ BLI_assert((thumb_locks.locked_paths != NULL) && (thumb_locks.lock_counter > 0));
+
+ thumb_locks.lock_counter--;
+ if (thumb_locks.lock_counter == 0) {
+ BLI_gset_free(thumb_locks.locked_paths, MEM_freeN);
+ thumb_locks.locked_paths = NULL;
+ BLI_condition_end(&thumb_locks.cond);
+ }
+
+ BLI_unlock_thread(LOCK_IMAGE);
+}
+
+void IMB_thumb_path_lock(const char *path)
+{
+ void *key = BLI_strdup(path);
+
+ BLI_lock_thread(LOCK_IMAGE);
+ BLI_assert((thumb_locks.locked_paths != NULL) && (thumb_locks.lock_counter > 0));
+
+ if (thumb_locks.locked_paths) {
+ while (!BLI_gset_add(thumb_locks.locked_paths, key)) {
+ BLI_condition_wait_global_mutex(&thumb_locks.cond, LOCK_IMAGE);
+ }
+ }
+
+ BLI_unlock_thread(LOCK_IMAGE);
+}
+
+void IMB_thumb_path_unlock(const char *path)
+{
+ const void *key = path;
+
+ BLI_lock_thread(LOCK_IMAGE);
+ BLI_assert((thumb_locks.locked_paths != NULL) && (thumb_locks.lock_counter > 0));
+
+ if (thumb_locks.locked_paths) {
+ if (!BLI_gset_remove(thumb_locks.locked_paths, key, MEM_freeN)) {
+ BLI_assert(0);
+ }
+ BLI_condition_notify_all(&thumb_locks.cond);
+ }
+
+ BLI_unlock_thread(LOCK_IMAGE);
+}
diff --git a/source/blender/imbuf/intern/thumbs_blend.c b/source/blender/imbuf/intern/thumbs_blend.c
index 73ced4095f9..b5c6deb6b01 100644
--- a/source/blender/imbuf/intern/thumbs_blend.c
+++ b/source/blender/imbuf/intern/thumbs_blend.c
@@ -25,127 +25,103 @@
*/
+#include <stdlib.h>
#include <string.h>
-#include "zlib.h"
-
-#include "MEM_guardedalloc.h"
-
#include "BLI_utildefines.h"
#include "BLI_endian_switch.h"
#include "BLI_fileops.h"
+#include "BLI_linklist.h"
#include "BLO_blend_defs.h"
+#include "BLO_readfile.h"
#include "BKE_global.h"
+#include "BKE_idcode.h"
+#include "BKE_icons.h"
+#include "BKE_library.h"
+#include "BKE_main.h"
+
+#include "DNA_ID.h" /* For preview images... */
#include "IMB_imbuf_types.h"
#include "IMB_imbuf.h"
#include "IMB_thumbs.h"
-/* extracts the thumbnail from between the 'REND' and the 'GLOB'
- * chunks of the header, don't use typical blend loader because its too slow */
+#include "MEM_guardedalloc.h"
-static ImBuf *loadblend_thumb(gzFile gzfile)
+ImBuf *IMB_thumb_load_blend(const char *blen_path, const char *blen_group, const char *blen_id)
{
- char buf[12];
- int bhead[24 / sizeof(int)]; /* max size on 64bit */
- char endian, pointer_size;
- char endian_switch;
- int sizeof_bhead;
-
- /* read the blend file header */
- if (gzread(gzfile, buf, 12) != 12)
- return NULL;
- if (strncmp(buf, "BLENDER", 7))
- return NULL;
-
- if (buf[7] == '-')
- pointer_size = 8;
- else if (buf[7] == '_')
- pointer_size = 4;
- else
- return NULL;
-
- sizeof_bhead = 16 + pointer_size;
-
- if (buf[8] == 'V')
- endian = B_ENDIAN; /* big: PPC */
- else if (buf[8] == 'v')
- endian = L_ENDIAN; /* little: x86 */
- else
- return NULL;
-
- endian_switch = ((ENDIAN_ORDER != endian)) ? 1 : 0;
-
- while (gzread(gzfile, bhead, sizeof_bhead) == sizeof_bhead) {
- if (endian_switch)
- BLI_endian_switch_int32(&bhead[1]); /* length */
-
- if (bhead[0] == REND) {
- gzseek(gzfile, bhead[1], SEEK_CUR); /* skip to the next */
- }
- else {
- break;
+ ImBuf *ima = NULL;
+
+ if (blen_group && blen_id) {
+ LinkNode *ln, *names, *lp, *previews = NULL;
+ struct BlendHandle *libfiledata = BLO_blendhandle_from_file(blen_path, NULL);
+ int idcode = BKE_idcode_from_name(blen_group);
+ int i, nprevs, nnames;
+
+ if (libfiledata == NULL) {
+ return ima;
}
- }
- /* using 'TEST' since new names segfault when loading in old blenders */
- if (bhead[0] == TEST) {
- ImBuf *img = NULL;
- int size[2];
+ /* Note: we should handle all previews for a same group at once, would avoid reopening .blend file
+ * for each and every ID. However, this adds some complexity, so keep it for later. */
+ names = BLO_blendhandle_get_datablock_names(libfiledata, idcode, &nnames);
+ previews = BLO_blendhandle_get_previews(libfiledata, idcode, &nprevs);
- if (gzread(gzfile, size, sizeof(size)) != sizeof(size))
- return NULL;
+ BLO_blendhandle_close(libfiledata);
- if (endian_switch) {
- BLI_endian_switch_int32(&size[0]);
- BLI_endian_switch_int32(&size[1]);
- }
- /* length */
- bhead[1] -= sizeof(int) * 2;
-
- /* inconsistent image size, quit early */
- if (bhead[1] != size[0] * size[1] * sizeof(int))
- return NULL;
-
- /* finally malloc and read the data */
- img = IMB_allocImBuf(size[0], size[1], 32, IB_rect | IB_metadata);
-
- if (gzread(gzfile, img->rect, bhead[1]) != bhead[1]) {
- IMB_freeImBuf(img);
- img = NULL;
+ if (!previews || (nnames != nprevs)) {
+ if (previews != 0) {
+ /* No previews at all is not a bug! */
+ printf("%s: error, found %d items, %d previews\n", __func__, nnames, nprevs);
+ }
+ BLI_linklist_free(previews, BKE_previewimg_freefunc);
+ BLI_linklist_free(names, free);
+ return ima;
}
-
- return img;
- }
-
- return NULL;
-}
-ImBuf *IMB_loadblend_thumb(const char *path)
-{
- gzFile gzfile;
- /* not necessarily a gzip */
- gzfile = BLI_gzopen(path, "rb");
+ for (i = 0, ln = names, lp = previews; i < nnames; i++, ln = ln->next, lp = lp->next) {
+ const char *blockname = ln->link;
+ PreviewImage *img = lp->link;
- if (NULL == gzfile) {
- return NULL;
+ if (STREQ(blockname, blen_id)) {
+ if (img) {
+ unsigned int w = img->w[ICON_SIZE_PREVIEW];
+ unsigned int h = img->h[ICON_SIZE_PREVIEW];
+ unsigned int *rect = img->rect[ICON_SIZE_PREVIEW];
+
+ if (w > 0 && h > 0 && rect) {
+ /* first allocate imbuf for copying preview into it */
+ ima = IMB_allocImBuf(w, h, 32, IB_rect);
+ memcpy(ima->rect, rect, w * h * sizeof(unsigned int));
+ }
+ }
+ break;
+ }
+ }
+
+ BLI_linklist_free(previews, BKE_previewimg_freefunc);
+ BLI_linklist_free(names, free);
}
else {
- ImBuf *img = loadblend_thumb(gzfile);
+ BlendThumbnail *data;
- /* read ok! */
- gzclose(gzfile);
+ data = BLO_thumbnail_from_file(blen_path);
+ ima = BKE_main_thumbnail_to_imbuf(NULL, data);
- return img;
+ if (data) {
+ MEM_freeN(data);
+ }
}
+
+ return ima;
}
/* add a fake passepartout overlay to a byte buffer, use for blend file thumbnails */
#define MARGIN 2
-void IMB_overlayblend_thumb(unsigned int *thumb, int width, int height, float aspect)
+void IMB_thumb_overlay_blend(unsigned int *thumb, int width, int height, float aspect)
{
unsigned char *px = (unsigned char *)thumb;
int margin_l = MARGIN;
diff --git a/source/blender/imbuf/intern/thumbs_font.c b/source/blender/imbuf/intern/thumbs_font.c
new file mode 100644
index 00000000000..7715e1bc470
--- /dev/null
+++ b/source/blender/imbuf/intern/thumbs_font.c
@@ -0,0 +1,100 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributor(s): Thomas Beck.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/imbuf/intern/thumbs_font.c
+ * \ingroup imbuf
+ */
+
+#include "BLI_utildefines.h"
+#include "BLI_string.h"
+#include "BLI_fileops.h"
+#include "BLI_hash_md5.h"
+
+#include "IMB_imbuf_types.h"
+#include "IMB_imbuf.h"
+
+#include "IMB_thumbs.h"
+
+
+/* XXX, bad level call */
+#include "../../blenfont/BLF_api.h"
+#include "../../blentranslation/BLT_translation.h"
+
+static const char *thumb_str[] = {
+ N_("AaBbCc"),
+
+ N_("The quick"),
+ N_("brown fox"),
+ N_("jumps over"),
+ N_("the lazy dog"),
+};
+
+struct ImBuf *IMB_thumb_load_font(const char *filename, unsigned int x, unsigned int y)
+{
+ const int font_size = y / 4;
+
+ struct ImBuf *ibuf;
+ float font_color[4];
+
+ /* create a white image (theme color is used for drawing) */
+ font_color[0] = font_color[1] = font_color[2] = 1.0f;
+
+ /* fill with zero alpha */
+ font_color[3] = 0.0f;
+
+ ibuf = IMB_allocImBuf(x, y, 32, IB_rect | IB_metadata);
+ IMB_rectfill(ibuf, font_color);
+
+ /* draw with full alpha */
+ font_color[3] = 1.0f;
+
+ BLF_thumb_preview(
+ filename, thumb_str, ARRAY_SIZE(thumb_str),
+ font_color, font_size,
+ (unsigned char *)ibuf->rect, ibuf->x, ibuf->y, ibuf->channels);
+
+ return ibuf;
+}
+
+bool IMB_thumb_load_font_get_hash(char *r_hash)
+{
+ char buf[1024];
+ char *str = buf;
+ size_t len = 0;
+
+ int draw_str_lines = ARRAY_SIZE(thumb_str);
+ int i;
+
+ unsigned char digest[16];
+
+ len += BLI_strncpy_rlen(str + len, THUMB_DEFAULT_HASH, sizeof(buf) - len);
+
+ for (i = 0; (i < draw_str_lines) && (len < sizeof(buf)); i++) {
+ len += BLI_strncpy_rlen(str + len, BLT_translate_do(BLT_I18NCONTEXT_DEFAULT, thumb_str[i]), sizeof(buf) - len);
+ }
+
+ BLI_hash_md5_buffer(str, len, digest);
+ r_hash[0] = '\0';
+ BLI_hash_md5_to_hexdigest(digest, r_hash);
+
+ return true;
+}
diff --git a/source/blender/imbuf/intern/tiff.c b/source/blender/imbuf/intern/tiff.c
index eb8f94cbc6e..1c501f8f592 100644
--- a/source/blender/imbuf/intern/tiff.c
+++ b/source/blender/imbuf/intern/tiff.c
@@ -53,9 +53,7 @@
#include "IMB_imbuf_types.h"
#include "IMB_imbuf.h"
-#include "IMB_allocimbuf.h"
#include "IMB_filetype.h"
-#include "IMB_filter.h"
#include "IMB_colormanagement.h"
#include "IMB_colormanagement_intern.h"
@@ -81,9 +79,9 @@ static void imb_tiff_DummyUnmapProc(thandle_t fd, tdata_t base, toff_t size);
/* Structure for in-memory TIFF file. */
typedef struct ImbTIFFMemFile {
- unsigned char *mem; /* Location of first byte of TIFF file. */
- toff_t offset; /* Current offset within the file. */
- tsize_t size; /* Size of the TIFF file. */
+ const unsigned char *mem; /* Location of first byte of TIFF file. */
+ toff_t offset; /* Current offset within the file. */
+ tsize_t size; /* Size of the TIFF file. */
} ImbTIFFMemFile;
#define IMB_TIFF_GET_MEMFILE(x) ((ImbTIFFMemFile *)(x))
@@ -276,7 +274,7 @@ static toff_t imb_tiff_SizeProc(thandle_t handle)
return (toff_t)(mfile->size);
}
-static TIFF *imb_tiff_client_open(ImbTIFFMemFile *memFile, unsigned char *mem, size_t size)
+static TIFF *imb_tiff_client_open(ImbTIFFMemFile *memFile, const unsigned char *mem, size_t size)
{
/* open the TIFF client layer interface to the in-memory file */
memFile->mem = mem;
@@ -306,13 +304,13 @@ static TIFF *imb_tiff_client_open(ImbTIFFMemFile *memFile, unsigned char *mem, s
* hence my manual comparison. - Jonathan Merritt (lancelet) 4th Sept 2005.
*/
#define IMB_TIFF_NCB 4 /* number of comparison bytes used */
-int imb_is_a_tiff(unsigned char *mem)
+int imb_is_a_tiff(const unsigned char *mem)
{
char big_endian[IMB_TIFF_NCB] = { 0x4d, 0x4d, 0x00, 0x2a };
char lil_endian[IMB_TIFF_NCB] = { 0x49, 0x49, 0x2a, 0x00 };
- return ( (memcmp(big_endian, mem, IMB_TIFF_NCB) == 0) ||
- (memcmp(lil_endian, mem, IMB_TIFF_NCB) == 0) );
+ return ((memcmp(big_endian, mem, IMB_TIFF_NCB) == 0) ||
+ (memcmp(lil_endian, mem, IMB_TIFF_NCB) == 0));
}
static void scanline_contig_16bit(float *rectf, const unsigned short *sbuf, int scanline_w, int spp)
@@ -456,7 +454,7 @@ static int imb_read_tiff_pixels(ImBuf *ibuf, TIFF *image)
if (bitspersample == 32) {
if (chan == 3 && spp == 3) /* fill alpha if only RGB TIFF */
- fill_vn_fl(fbuf, ibuf->x, 1.0f);
+ copy_vn_fl(fbuf, ibuf->x, 1.0f);
else if (chan >= spp) /* for grayscale, duplicate first channel into G and B */
success |= TIFFReadScanline(image, fbuf, row, 0);
else
@@ -466,7 +464,7 @@ static int imb_read_tiff_pixels(ImBuf *ibuf, TIFF *image)
}
else if (bitspersample == 16) {
if (chan == 3 && spp == 3) /* fill alpha if only RGB TIFF */
- fill_vn_ushort(sbuf, ibuf->x, 65535);
+ copy_vn_ushort(sbuf, ibuf->x, 65535);
else if (chan >= spp) /* for grayscale, duplicate first channel into G and B */
success |= TIFFReadScanline(image, fbuf, row, 0);
else
@@ -522,7 +520,7 @@ void imb_inittiff(void)
*
* \return: A newly allocated ImBuf structure if successful, otherwise NULL.
*/
-ImBuf *imb_loadtiff(unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE])
+ImBuf *imb_loadtiff(const unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE])
{
TIFF *image = NULL;
ImBuf *ibuf = NULL, *hbuf;
@@ -561,7 +559,7 @@ ImBuf *imb_loadtiff(unsigned char *mem, size_t size, int flags, char colorspace[
ibuf = IMB_allocImBuf(width, height, ib_depth, 0);
if (ibuf) {
- ibuf->ftype = TIF;
+ ibuf->ftype = IMB_FTYPE_TIF;
}
else {
fprintf(stderr,
@@ -596,7 +594,7 @@ ImBuf *imb_loadtiff(unsigned char *mem, size_t size, int flags, char colorspace[
format = NULL;
TIFFGetField(image, TIFFTAG_PIXAR_TEXTUREFORMAT, &format);
- if (format && strcmp(format, "Plain Texture") == 0 && TIFFIsTiled(image)) {
+ if (format && STREQ(format, "Plain Texture") && TIFFIsTiled(image)) {
int numlevel = TIFFNumberOfDirectories(image);
/* create empty mipmap levels in advance */
@@ -645,7 +643,7 @@ ImBuf *imb_loadtiff(unsigned char *mem, size_t size, int flags, char colorspace[
return ibuf;
}
-void imb_loadtiletiff(ImBuf *ibuf, unsigned char *mem, size_t size, int tx, int ty, unsigned int *rect)
+void imb_loadtiletiff(ImBuf *ibuf, const unsigned char *mem, size_t size, int tx, int ty, unsigned int *rect)
{
TIFF *image = NULL;
uint32 width, height;
@@ -722,7 +720,7 @@ int imb_savetiff(ImBuf *ibuf, const char *name, int flags)
return (0);
}
- if ((ibuf->ftype & TIF_16BIT) && ibuf->rect_float)
+ if ((ibuf->foptions.flag & TIF_16BIT) && ibuf->rect_float)
bitspersample = 16;
else
bitspersample = 8;
diff --git a/source/blender/imbuf/intern/util.c b/source/blender/imbuf/intern/util.c
index 32100aa2288..ca793d04d9b 100644
--- a/source/blender/imbuf/intern/util.c
+++ b/source/blender/imbuf/intern/util.c
@@ -186,11 +186,13 @@ int IMB_ispic_type(const char *name)
#define HEADER_SIZE 64
unsigned char buf[HEADER_SIZE];
- ImFileType *type;
+ const ImFileType *type;
BLI_stat_t st;
int fp;
- if (UTIL_DEBUG) printf("IMB_ispic_name: loading %s\n", name);
+ BLI_assert(!BLI_path_is_rel(name));
+
+ if (UTIL_DEBUG) printf("%s: loading %s\n", __func__, name);
if (BLI_stat(name, &st) == -1)
return false;
@@ -210,7 +212,7 @@ int IMB_ispic_type(const char *name)
/* XXX move this exception */
if ((BIG_LONG(((int *)buf)[0]) & 0xfffffff0) == 0xffd8ffe0)
- return JPG;
+ return IMB_FTYPE_JPG;
for (type = IMB_FILE_TYPES; type < IMB_FILE_TYPES_LAST; type++) {
if (type->is_a) {
@@ -389,7 +391,9 @@ int imb_get_anim_type(const char *name)
int type;
BLI_stat_t st;
- if (UTIL_DEBUG) printf("in getanimtype: %s\n", name);
+ BLI_assert(!BLI_path_is_rel(name));
+
+ if (UTIL_DEBUG) printf("%s: %s\n", __func__, name);
#ifndef _WIN32
# ifdef WITH_QUICKTIME
@@ -434,8 +438,20 @@ int imb_get_anim_type(const char *name)
bool IMB_isanim(const char *filename)
{
int type;
-
+
type = imb_get_anim_type(filename);
return (type && type != ANIM_SEQUENCE);
}
+
+bool IMB_isfloat(ImBuf *ibuf)
+{
+ const ImFileType *type;
+
+ for (type = IMB_FILE_TYPES; type < IMB_FILE_TYPES_LAST; type++) {
+ if (type->ftype(type, ibuf)) {
+ return (type->flag & IM_FTYPE_FLOAT) != 0;
+ }
+ }
+ return false;
+}
diff --git a/source/blender/imbuf/intern/writeimage.c b/source/blender/imbuf/intern/writeimage.c
index d4a9bf7dc09..28710fba823 100644
--- a/source/blender/imbuf/intern/writeimage.c
+++ b/source/blender/imbuf/intern/writeimage.c
@@ -33,6 +33,10 @@
#include <stdio.h>
+#include <stdlib.h>
+
+#include "BLI_utildefines.h"
+#include "BLI_path_util.h"
#include "IMB_imbuf_types.h"
#include "IMB_imbuf.h"
@@ -41,28 +45,16 @@
#include "IMB_colormanagement.h"
#include "IMB_colormanagement_intern.h"
-#include "imbuf.h"
-
-static ImBuf *prepare_write_imbuf(ImFileType *type, ImBuf *ibuf)
+static ImBuf *prepare_write_imbuf(const ImFileType *type, ImBuf *ibuf)
{
- ImBuf *write_ibuf = ibuf;
-
- if (type->flag & IM_FTYPE_FLOAT) {
- /* pass */
- }
- else {
- if (ibuf->rect == NULL && ibuf->rect_float) {
- ibuf->rect_colorspace = colormanage_colorspace_get_roled(COLOR_ROLE_DEFAULT_BYTE);
- IMB_rect_from_float(ibuf);
- }
- }
-
- return write_ibuf;
+ return IMB_prepare_write_ImBuf((type->flag & IM_FTYPE_FLOAT), ibuf);
}
short IMB_saveiff(struct ImBuf *ibuf, const char *name, int flags)
{
- ImFileType *type;
+ const ImFileType *type;
+
+ BLI_assert(!BLI_path_is_rel(name));
if (ibuf == NULL) return (false);
ibuf->flags = flags;
@@ -88,3 +80,19 @@ short IMB_saveiff(struct ImBuf *ibuf, const char *name, int flags)
return false;
}
+ImBuf *IMB_prepare_write_ImBuf(const bool isfloat, ImBuf *ibuf)
+{
+ ImBuf *write_ibuf = ibuf;
+
+ if (isfloat) {
+ /* pass */
+ }
+ else {
+ if (ibuf->rect == NULL && ibuf->rect_float) {
+ ibuf->rect_colorspace = colormanage_colorspace_get_roled(COLOR_ROLE_DEFAULT_BYTE);
+ IMB_rect_from_float(ibuf);
+ }
+ }
+
+ return write_ibuf;
+}
diff --git a/source/blender/makesdna/DNA_ID.h b/source/blender/makesdna/DNA_ID.h
index 33d1445fb93..342245fa393 100644
--- a/source/blender/makesdna/DNA_ID.h
+++ b/source/blender/makesdna/DNA_ID.h
@@ -44,54 +44,65 @@ struct FileData;
struct ID;
struct PackedFile;
struct GPUTexture;
-
+
typedef struct IDPropertyData {
void *pointer;
ListBase group;
- int val, val2; /*note, we actually fit a double into these two ints*/
+ int val, val2; /* note, we actually fit a double into these two ints */
} IDPropertyData;
typedef struct IDProperty {
struct IDProperty *next, *prev;
char type, subtype;
short flag;
- char name[64]; /* MAX_IDPROP_NAME */
- int saved; /* saved is used to indicate if this struct has been saved yet.
- * seemed like a good idea as a pad var was needed anyway :)*/
- IDPropertyData data; /* note, alignment for 64 bits */
- int len; /* array length, also (this is important!) string length + 1.
- * the idea is to be able to reuse array realloc functions on strings.*/
+ char name[64]; /* MAX_IDPROP_NAME */
+
+ /* saved is used to indicate if this struct has been saved yet.
+ * seemed like a good idea as a pad var was needed anyway :) */
+ int saved;
+ IDPropertyData data; /* note, alignment for 64 bits */
+
+ /* array length, also (this is important!) string length + 1.
+ * the idea is to be able to reuse array realloc functions on strings.*/
+ int len;
+
+ /* Strings and arrays are both buffered, though the buffer isn't saved. */
/* totallen is total length of allocated array/string, including a buffer.
- * Note that the buffering is mild; the code comes from python's list implementation.*/
- int totallen; /*strings and arrays are both buffered, though the buffer isn't saved.*/
+ * Note that the buffering is mild; the code comes from python's list implementation. */
+ int totallen;
} IDProperty;
-#define MAX_IDPROP_NAME 64
-#define DEFAULT_ALLOC_FOR_NULL_STRINGS 64
+#define MAX_IDPROP_NAME 64
+#define DEFAULT_ALLOC_FOR_NULL_STRINGS 64
/*->type*/
-#define IDP_STRING 0
-#define IDP_INT 1
-#define IDP_FLOAT 2
-#define IDP_ARRAY 5
-#define IDP_GROUP 6
-/* the ID link property type hasn't been implemented yet, this will require
- * some cleanup of blenkernel, most likely.*/
-#define IDP_ID 7
-#define IDP_DOUBLE 8
-#define IDP_IDPARRAY 9
-#define IDP_NUMTYPES 10
+enum {
+ IDP_STRING = 0,
+ IDP_INT = 1,
+ IDP_FLOAT = 2,
+ IDP_ARRAY = 5,
+ IDP_GROUP = 6,
+ /* the ID link property type hasn't been implemented yet, this will require
+ * some cleanup of blenkernel, most likely. */
+ IDP_ID = 7,
+ IDP_DOUBLE = 8,
+ IDP_IDPARRAY = 9,
+ IDP_NUMTYPES = 10,
+};
/*->subtype */
/* IDP_STRING */
-#define IDP_STRING_SUB_UTF8 0 /* default */
-#define IDP_STRING_SUB_BYTE 1 /* arbitrary byte array, _not_ null terminated */
-/*->flag*/
-#define IDP_FLAG_GHOST (1<<7) /* this means the property is set but RNA will return
- * false when checking 'RNA_property_is_set',
- * currently this is a runtime flag */
+enum {
+ IDP_STRING_SUB_UTF8 = 0, /* default */
+ IDP_STRING_SUB_BYTE = 1, /* arbitrary byte array, _not_ null terminated */
+};
+/*->flag*/
+enum {
+ IDP_FLAG_GHOST = 1 << 7, /* this means the property is set but RNA will return false when checking
+ * 'RNA_property_is_set', currently this is a runtime flag */
+};
/* add any future new id property types here.*/
@@ -102,7 +113,7 @@ typedef struct IDProperty {
* */
/* 2 characters for ID code and 64 for actual name */
-#define MAX_ID_NAME 66
+#define MAX_ID_NAME 66
/* There's a nasty circular dependency here.... 'void *' to the rescue! I
* really wonder why this is needed. */
@@ -129,14 +140,14 @@ typedef struct Library {
ID id;
ID *idblock;
struct FileData *filedata;
- char name[1024]; /* path name used for reading, can be relative and edited in the outliner */
- char filepath[1024]; /* absolute filepath, this is only for convenience,
- * 'name' is the real path used on file read but in
- * some cases its useful to access the absolute one,
- * This is set on file read.
- * Use BKE_library_filepath_set() rather than
- * setting 'name' directly and it will be kept in
- * sync - campbell */
+ char name[1024]; /* path name used for reading, can be relative and edited in the outliner */
+
+ /* absolute filepath, this is only for convenience, 'name' is the real path used on file read but in
+ * some cases its useful to access the absolute one.
+ * This is set on file read.
+ * Use BKE_library_filepath_set() rather than setting 'name' directly and it will be kept in sync - campbell */
+ char filepath[1024];
+
struct Library *parent; /* set for indirectly linked libs, used in the outliner and while reading */
struct PackedFile *packedfile;
@@ -144,20 +155,36 @@ typedef struct Library {
enum eIconSizes {
ICON_SIZE_ICON = 0,
- ICON_SIZE_PREVIEW = 1
+ ICON_SIZE_PREVIEW = 1,
+
+ NUM_ICON_SIZES
+};
+
+/* for PreviewImage->flag */
+enum ePreviewImage_Flag {
+ PRV_CHANGED = (1 << 0),
+ PRV_USER_EDITED = (1 << 1), /* if user-edited, do not auto-update this anymore! */
};
-#define NUM_ICON_SIZES (ICON_SIZE_PREVIEW + 1)
typedef struct PreviewImage {
/* All values of 2 are really NUM_ICON_SIZES */
unsigned int w[2];
unsigned int h[2];
- short changed[2];
+ short flag[2];
short changed_timestamp[2];
unsigned int *rect[2];
+
+ /* Runtime-only data. */
struct GPUTexture *gputexture[2];
+ int icon_id; /* Used by previews outside of ID context. */
+
+ char pad[3];
+ char use_deferred; /* for now a mere bool, if we add more deferred loading methods we can switch to bitflag. */
} PreviewImage;
+#define PRV_DEFERRED_DATA(prv) \
+ (CHECK_TYPE_INLINE(prv, PreviewImage *), BLI_assert((prv)->use_deferred), (void *)((prv) + 1))
+
/**
* Defines for working with IDs.
*
@@ -174,7 +201,12 @@ typedef struct PreviewImage {
# define MAKE_ID2(c, d) ((d) << 8 | (c))
#endif
-/* ID from database */
+/**
+ * ID from database.
+ *
+ * Written to #BHead.code (for file IO)
+ * and the first 2 bytes of #ID.name (for runtime checks, see #GS macro).
+ */
#define ID_SCE MAKE_ID2('S', 'C') /* Scene */
#define ID_LI MAKE_ID2('L', 'I') /* Library */
#define ID_OB MAKE_ID2('O', 'B') /* Object */
@@ -232,33 +264,72 @@ typedef struct PreviewImage {
#ifdef GS
# undef GS
#endif
-// #define GS(a) (*((short *)(a)))
-#define GS(a) (CHECK_TYPE_INLINE(a, char *), (*((short *)(a))))
+#define GS(a) (CHECK_TYPE_ANY(a, char *, const char *, char [66], const char[66]), (*((const short *)(a))))
#define ID_NEW(a) if ( (a) && (a)->id.newid ) (a) = (void *)(a)->id.newid
#define ID_NEW_US(a) if ( (a)->id.newid) { (a) = (void *)(a)->id.newid; (a)->id.us++; }
#define ID_NEW_US2(a) if (((ID *)a)->newid) { (a) = ((ID *)a)->newid; ((ID *)a)->us++; }
-/* id->flag: set frist 8 bits always at zero while reading */
-#define LIB_LOCAL 0
-#define LIB_EXTERN 1
-#define LIB_INDIRECT 2
-#define LIB_NEED_EXPAND 8
-#define LIB_TESTEXT (LIB_NEED_EXPAND | LIB_EXTERN)
-#define LIB_TESTIND (LIB_NEED_EXPAND | LIB_INDIRECT)
-#define LIB_READ 16
-#define LIB_NEED_LINK 32
-
-#define LIB_NEW 256
-#define LIB_FAKEUSER 512
-/* free test flag */
-#define LIB_DOIT 1024
-/* tag existing data before linking so we know what is new */
-#define LIB_PRE_EXISTING 2048
-/* runtime */
-#define LIB_ID_RECALC 4096
-#define LIB_ID_RECALC_DATA 8192
-#define LIB_ANIM_NO_RECALC 16384
+/* id->flag: set first 8 bits always at zero while reading */
+enum {
+ LIB_LOCAL = 0,
+ LIB_EXTERN = 1 << 0,
+ LIB_INDIRECT = 1 << 1,
+ LIB_NEED_EXPAND = 1 << 3,
+ LIB_TESTEXT = (LIB_NEED_EXPAND | LIB_EXTERN),
+ LIB_TESTIND = (LIB_NEED_EXPAND | LIB_INDIRECT),
+ LIB_READ = 1 << 4,
+ LIB_NEED_LINK = 1 << 5,
+
+ LIB_NEW = 1 << 8,
+ LIB_FAKEUSER = 1 << 9,
+ /* free test flag */
+ LIB_DOIT = 1 << 10,
+ /* tag existing data before linking so we know what is new */
+ LIB_PRE_EXISTING = 1 << 11,
+ /* runtime */
+ LIB_ID_RECALC = 1 << 12,
+ LIB_ID_RECALC_DATA = 1 << 13,
+ LIB_ANIM_NO_RECALC = 1 << 14,
+
+ LIB_ID_RECALC_ALL = (LIB_ID_RECALC | LIB_ID_RECALC_DATA),
+};
+
+/* To filter ID types (filter_id) */
+/* XXX We cannot put all needed IDs inside an enum...
+ * We'll have to see whether we can fit all needed ones inside 32 values,
+ * or if we need to fallback to longlong defines :/
+ */
+enum {
+ FILTER_ID_AC = (1 << 0),
+ FILTER_ID_AR = (1 << 1),
+ FILTER_ID_BR = (1 << 2),
+ FILTER_ID_CA = (1 << 3),
+ FILTER_ID_CU = (1 << 4),
+ FILTER_ID_GD = (1 << 5),
+ FILTER_ID_GR = (1 << 6),
+ FILTER_ID_IM = (1 << 7),
+ FILTER_ID_LA = (1 << 8),
+ FILTER_ID_LS = (1 << 9),
+ FILTER_ID_LT = (1 << 10),
+ FILTER_ID_MA = (1 << 11),
+ FILTER_ID_MB = (1 << 12),
+ FILTER_ID_MC = (1 << 13),
+ FILTER_ID_ME = (1 << 14),
+ FILTER_ID_MSK = (1 << 15),
+ FILTER_ID_NT = (1 << 16),
+ FILTER_ID_OB = (1 << 17),
+ FILTER_ID_PAL = (1 << 18),
+ FILTER_ID_PC = (1 << 19),
+ FILTER_ID_SCE = (1 << 20),
+ FILTER_ID_SPK = (1 << 21),
+ FILTER_ID_SO = (1 << 22),
+ FILTER_ID_TE = (1 << 23),
+ FILTER_ID_TXT = (1 << 24),
+ FILTER_ID_VF = (1 << 25),
+ FILTER_ID_WO = (1 << 26),
+ FILTER_ID_PA = (1 << 27),
+};
#ifdef __cplusplus
}
diff --git a/source/blender/makesdna/DNA_action_types.h b/source/blender/makesdna/DNA_action_types.h
index dab825c856e..d574694c70d 100644
--- a/source/blender/makesdna/DNA_action_types.h
+++ b/source/blender/makesdna/DNA_action_types.h
@@ -198,7 +198,8 @@ typedef struct bPoseChannel {
short agrp_index; /* index of action-group this bone belongs to (0 = default/no group) */
char constflag; /* for quick detecting which constraints affect this channel */
char selectflag; /* copy of bone flag, so you can work with library armatures, not for runtime use */
- char pad0[6];
+ char drawflag;
+ char pad0[5];
struct Bone *bone; /* set on read file or rebuild pose */
struct bPoseChannel *parent; /* set on read file or rebuild pose */
@@ -212,6 +213,9 @@ typedef struct bPoseChannel {
struct bPoseChannel *custom_tx; /* odd feature, display with another bones transform.
* needed in rare cases for advanced rigs,
* since the alternative is highly complicated - campbell */
+ float custom_scale;
+
+ char pad1[4];
/* transforms - written in by actions or transform */
float loc[3];
@@ -250,6 +254,7 @@ typedef enum ePchan_Flag {
POSE_ROT = (1 << 1),
POSE_SIZE = (1 << 2),
/* old IK/cache stuff... */
+#if 0
POSE_IK_MAT = (1 << 3),
POSE_UNUSED2 = (1 << 4),
POSE_UNUSED3 = (1 << 5),
@@ -257,6 +262,7 @@ typedef enum ePchan_Flag {
POSE_UNUSED5 = (1 << 7),
/* has Standard IK */
POSE_HAS_IK = (1 << 8),
+#endif
/* IK/Pose solving*/
POSE_CHAIN = (1 << 9),
POSE_DONE = (1 << 10),
@@ -265,8 +271,10 @@ typedef enum ePchan_Flag {
POSE_STRIDE = (1 << 12),
/* standard IK solving */
POSE_IKTREE = (1 << 13),
+#if 0
/* has Spline IK */
POSE_HAS_IKS = (1 << 14),
+#endif
/* spline IK solving */
POSE_IKSPLINE = (1 << 15)
} ePchan_Flag;
@@ -302,6 +310,14 @@ typedef enum ePchan_IkFlag {
BONE_IK_NO_ZDOF_TEMP = (1 << 12)
} ePchan_IkFlag;
+/* PoseChannel->drawflag */
+typedef enum ePchan_DrawFlag {
+ PCHAN_DRAW_NO_CUSTOM_BONE_SIZE = (1 << 0),
+} ePchan_DrawFlag;
+
+#define PCHAN_CUSTOM_DRAW_SIZE(pchan) \
+ (pchan)->custom_scale * (((pchan)->drawflag & PCHAN_DRAW_NO_CUSTOM_BONE_SIZE) ? 1.0f : (pchan)->bone->length)
+
/* PoseChannel->rotmode and Object->rotmode */
typedef enum eRotationModes {
/* quaternion rotations (default, and for older Blender versions) */
@@ -371,7 +387,9 @@ typedef enum ePose_Flags {
/* set by BKE_pose_rebuild to give a chance to the IK solver to rebuild IK tree */
POSE_WAS_REBUILT = (1 << 5),
/* set by game_copy_pose to indicate that this pose is used in the game engine */
- POSE_GAME_ENGINE = (1 << 6)
+ POSE_GAME_ENGINE = (1 << 6),
+ /* pose constraint flags needs to be updated */
+ POSE_CONSTRAINTS_NEED_UPDATE_FLAGS = (1 << 7),
} ePose_Flags;
/* IK Solvers ------------------------------------ */
@@ -465,6 +483,9 @@ typedef enum eActionGroup_Flag {
AGRP_NOTVISIBLE = (1 << 5),
/* for UI (Graph Editor), sub-channels are shown */
AGRP_EXPANDED_G = (1 << 6),
+
+ /* sub channel modifiers off */
+ AGRP_MODIFIERS_OFF = (1 << 7),
AGRP_TEMP = (1 << 30),
AGRP_MOVED = (1 << 31)
@@ -487,7 +508,7 @@ typedef struct bAction {
ID id; /* ID-serialisation for relinking */
ListBase curves; /* function-curves (FCurve) */
- ListBase chanbase; /* legacy data - Action Channels (bActionChannel) in pre-2.5 animation system */
+ ListBase chanbase DNA_DEPRECATED; /* legacy data - Action Channels (bActionChannel) in pre-2.5 animation system */
ListBase groups; /* groups of function-curves (bActionGroup) */
ListBase markers; /* markers local to the Action (used to provide Pose-Libraries) */
@@ -541,7 +562,7 @@ typedef enum eDopeSheet_FilterFlag {
ADS_FILTER_ONLYNLA = (1 << 2), /* for 'NLA' editor - only include NLA data from AnimData */
ADS_FILTER_SELEDIT = (1 << 3), /* for Graph Editor - used to indicate whether to include a filtering flag or not */
- /* general filtering 2 */
+ /* general filtering */
ADS_FILTER_SUMMARY = (1 << 4), /* for 'DopeSheet' Editors - include 'summary' line */
ADS_FILTER_ONLYOBGROUP = (1 << 5), /* only the objects in the specified object group get used */
@@ -564,6 +585,8 @@ typedef enum eDopeSheet_FilterFlag {
ADS_FILTER_NOSPK = (1 << 21),
ADS_FILTER_NOLINESTYLE = (1 << 22),
ADS_FILTER_NOMODIFIERS = (1 << 23),
+ ADS_FILTER_NOGPENCIL = (1 << 24),
+ /* NOTE: all new datablock filters will have to go in filterflag2 (see below) */
/* NLA-specific filters */
ADS_FILTER_NLA_NOACT = (1 << 25), /* if the AnimData block has no NLA data, don't include to just show Action-line */
@@ -581,6 +604,8 @@ typedef enum eDopeSheet_FilterFlag {
typedef enum eDopeSheet_Flag {
ADS_FLAG_SUMMARY_COLLAPSED = (1 << 0), /* when summary is shown, it is collapsed, so all other channels get hidden */
ADS_FLAG_SHOW_DBFILTERS = (1 << 1) /* show filters for datablocks */
+
+ /* NOTE: datablock filter flags continued (1 << 10) onwards... */
} eDopeSheet_Flag;
diff --git a/source/blender/makesdna/DNA_actuator_types.h b/source/blender/makesdna/DNA_actuator_types.h
index dcde9007cd8..9af0c1dac10 100644
--- a/source/blender/makesdna/DNA_actuator_types.h
+++ b/source/blender/makesdna/DNA_actuator_types.h
@@ -57,7 +57,7 @@ typedef struct bActionActuator {
short blendin; /* Number of frames of blending */
short priority; /* Execution priority */
short layer; /* Animation layer */
- short end_reset; /* Ending the actuator (negative pulse) wont reset the the action to its starting frame */
+ short end_reset; /* Ending the actuator (negative pulse) wont reset the action to its starting frame */
short strideaxis; /* Displacement axis */
short blend_mode; /* Layer blending mode */
float stridelength; /* Displacement incurred by cycle */ // not in use
@@ -570,6 +570,7 @@ typedef struct bActuator {
#define ACT_STEERING_ENABLEVISUALIZATION 2
#define ACT_STEERING_AUTOMATICFACING 4
#define ACT_STEERING_NORMALUP 8
+#define ACT_STEERING_LOCKZVEL 16
/* mouseactuator->type */
#define ACT_MOUSE_VISIBILITY 0
diff --git a/source/blender/makesdna/DNA_anim_types.h b/source/blender/makesdna/DNA_anim_types.h
index 3d0d6b820d7..590179e0a0f 100644
--- a/source/blender/makesdna/DNA_anim_types.h
+++ b/source/blender/makesdna/DNA_anim_types.h
@@ -459,7 +459,7 @@ typedef struct FCurve {
int color_mode; /* coloring method to use (eFCurve_Coloring) */
float color[3]; /* the last-color this curve took */
- float prev_norm_factor, pad;
+ float prev_norm_factor, prev_offset;
} FCurve;
@@ -479,7 +479,7 @@ typedef enum eFCurve_Flags {
/* fcurve uses 'auto-handles', which stay horizontal... */
// DEPRECATED
FCURVE_AUTO_HANDLES = (1<<5),
-
+ FCURVE_MOD_OFF = (1<<6),
/* skip evaluation, as RNA-path cannot be resolved (similar to muting, but cannot be set by user) */
FCURVE_DISABLED = (1<<10),
/* curve can only have whole-number values (integer types) */
@@ -719,13 +719,13 @@ typedef struct KS_Path {
int idtype; /* ID-type that path can be used on */
short groupmode; /* group naming (eKSP_Grouping) */
- short pad;
+ short flag; /* various settings, etc. */
char *rna_path; /* dynamically (or statically in the case of predefined sets) path */
int array_index; /* index that path affects */
- short flag; /* various settings, etc. */
- short keyingflag; /* settings to supply insertkey() with */
+ short keyingflag; /* (eInsertKeyFlags) settings to supply insertkey() with */
+ short keyingoverride; /* (eInsertKeyFlags) for each flag set, the relevant keyingflag bit overrides the default */
} KS_Path;
/* KS_Path->flag */
@@ -770,10 +770,14 @@ typedef struct KeyingSet {
char description[240]; /* (RNA_DYN_DESCR_MAX) short help text. */
char typeinfo[64]; /* name of the typeinfo data used for the relative paths */
+ int active_path; /* index of the active path */
+
short flag; /* settings for KeyingSet */
- short keyingflag; /* settings to supply insertkey() with */
- int active_path; /* index of the active path */
+ short keyingflag; /* (eInsertKeyFlags) settings to supply insertkey() with */
+ short keyingoverride; /* (eInsertKeyFlags) for each flag set, the relevant keyingflag bit overrides the default */
+
+ char pad[6];
} KeyingSet;
/* KeyingSet settings */
@@ -849,6 +853,8 @@ typedef struct AnimData {
/* nla-tracks */
ListBase nla_tracks;
+ /* active NLA-track (only set/used during tweaking, so no need to worry about dangling pointers) */
+ NlaTrack *act_track;
/* active NLA-strip (only set/used during tweaking, so no need to worry about dangling pointers) */
NlaStrip *actstrip;
diff --git a/source/blender/makesdna/DNA_armature_types.h b/source/blender/makesdna/DNA_armature_types.h
index b6d4a8c9db8..b995e6917a9 100644
--- a/source/blender/makesdna/DNA_armature_types.h
+++ b/source/blender/makesdna/DNA_armature_types.h
@@ -153,16 +153,15 @@ typedef enum eArmature_DeformFlag {
ARM_DEF_VGROUP = (1<<0),
ARM_DEF_ENVELOPE = (1<<1),
ARM_DEF_QUATERNION = (1<<2),
+#ifdef DNA_DEPRECATED
ARM_DEF_B_BONE_REST = (1<<3), /* deprecated */
+#endif
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)
+#ifdef DNA_DEPRECATED
typedef enum eArmature_PathFlag {
ARM_PATH_FNUMS = (1<<0),
ARM_PATH_KFRAS = (1<<1),
@@ -170,9 +169,6 @@ typedef enum eArmature_PathFlag {
ARM_PATH_ACFRA = (1<<3),
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 */
@@ -188,7 +184,7 @@ typedef enum eBone_Flag {
BONE_SELECTED = (1 << 0),
BONE_ROOTSEL = (1 << 1),
BONE_TIPSEL = (1 << 2),
- BONE_TRANSFORM = (1 << 3), /* Used instead of BONE_SELECTED during transform */
+ BONE_TRANSFORM = (1 << 3), /* Used instead of BONE_SELECTED during transform (clear before use) */
BONE_CONNECTED = (1 << 4), /* when bone has a parent, connect head of bone to parent's tail*/
/* 32 used to be quatrot, was always set in files, do not reuse unless you clear it always */
BONE_HIDDEN_P = (1 << 6), /* hidden Bones when drawing PoseChannels */
diff --git a/source/blender/makesdna/DNA_brush_types.h b/source/blender/makesdna/DNA_brush_types.h
index b14861fcf47..7ec86459f0c 100644
--- a/source/blender/makesdna/DNA_brush_types.h
+++ b/source/blender/makesdna/DNA_brush_types.h
@@ -93,7 +93,7 @@ typedef struct Brush {
float plane_offset; /* offset for plane brushes (clay, flatten, fill, scrape) */
- float pad;
+ int flag2;
int gradient_spacing;
int gradient_stroke_mode; /* source for stroke color gradient application */
int gradient_fill_mode; /* source for fill tool color gradient application */
@@ -102,7 +102,7 @@ typedef struct Brush {
char vertexpaint_tool; /* active vertex/weight paint blend mode (poorly named) */
char imagepaint_tool; /* active image paint tool */
char mask_tool; /* enum BrushMaskTool, only used if sculpt_tool is SCULPT_TOOL_MASK */
-
+
float autosmooth_factor;
float crease_pinch_factor;
@@ -137,34 +137,29 @@ typedef struct Brush {
float mask_stencil_dimension[2];
} Brush;
-typedef struct PaletteColor
-{
+typedef struct PaletteColor {
struct PaletteColor *next, *prev;
/* two values, one to store rgb, other to store values for sculpt/weight */
float rgb[3];
float value;
} PaletteColor;
-typedef struct Palette
-{
+typedef struct Palette {
ID id;
/* pointer to individual colours */
ListBase colors;
- ListBase deleted;
int active_color;
int pad;
} Palette;
-typedef struct PaintCurvePoint
-{
+typedef struct PaintCurvePoint {
BezTriple bez; /* bezier handle */
float pressure; /* pressure on that point */
} PaintCurvePoint;
-typedef struct PaintCurve
-{
+typedef struct PaintCurve {
ID id;
PaintCurvePoint *points; /* points of curve */
int tot_points;
@@ -186,13 +181,13 @@ typedef enum BrushGradientSourceFill {
/* Brush.flag */
typedef enum BrushFlags {
BRUSH_AIRBRUSH = (1 << 0),
- BRUSH_TORUS = (1 << 1),
+// BRUSH_TORUS = (1 << 1), deprecated, use paint->symmetry_flags & PAINT_TILE_*
BRUSH_ALPHA_PRESSURE = (1 << 2),
BRUSH_SIZE_PRESSURE = (1 << 3),
BRUSH_JITTER_PRESSURE = (1 << 4),
BRUSH_SPACING_PRESSURE = (1 << 5),
BRUSH_UNUSED = (1 << 6),
- BRUSH_RAKE = (1 << 7),
+// BRUSH_RAKE = (1 << 7), deprecated, use brush_angle_mode
BRUSH_ANCHORED = (1 << 8),
BRUSH_DIR_IN = (1 << 9),
BRUSH_SPACE = (1 << 10),
@@ -209,7 +204,7 @@ typedef enum BrushFlags {
BRUSH_EDGE_TO_EDGE = (1 << 22),
BRUSH_DRAG_DOT = (1 << 23),
BRUSH_INVERSE_SMOOTH_PRESSURE = (1 << 24),
- BRUSH_RANDOM_ROTATION = (1 << 25),
+// BRUSH_RANDOM_ROTATION = (1 << 25), deprecated, use brush_angle_mode
BRUSH_PLANE_TRIM = (1 << 26),
BRUSH_FRONTFACE = (1 << 27),
BRUSH_CUSTOM_ICON = (1 << 28),
@@ -260,6 +255,36 @@ typedef enum BrushSculptTool {
SCULPT_TOOL_MASK = 19
} BrushSculptTool;
+/** When #BRUSH_ACCUMULATE is used */
+#define SCULPT_TOOL_HAS_ACCUMULATE(t) ELEM(t, \
+ SCULPT_TOOL_DRAW, \
+ SCULPT_TOOL_CREASE, \
+ SCULPT_TOOL_BLOB, \
+ SCULPT_TOOL_LAYER, \
+ SCULPT_TOOL_INFLATE, \
+ SCULPT_TOOL_CLAY, \
+ SCULPT_TOOL_CLAY_STRIPS, \
+ SCULPT_TOOL_ROTATE, \
+ SCULPT_TOOL_FLATTEN \
+ )
+
+#define SCULPT_TOOL_HAS_NORMAL_WEIGHT(t) ELEM(t, \
+ SCULPT_TOOL_GRAB, \
+ SCULPT_TOOL_SNAKE_HOOK \
+ )
+
+#define SCULPT_TOOL_HAS_DYNTOPO(t) (ELEM(t, \
+ /* These brushes, as currently coded, cannot support dynamic topology */ \
+ SCULPT_TOOL_GRAB, \
+ SCULPT_TOOL_ROTATE, \
+ SCULPT_TOOL_THUMB, \
+ SCULPT_TOOL_LAYER, \
+ \
+ /* These brushes could handle dynamic topology, but user feedback indicates it's better not to */ \
+ SCULPT_TOOL_SMOOTH, \
+ SCULPT_TOOL_MASK \
+ ) == 0)
+
/* ImagePaintSettings.tool */
typedef enum BrushImagePaintTool {
PAINT_TOOL_DRAW = 0,
@@ -300,7 +325,7 @@ typedef enum BlurKernelType {
KERNEL_BOX
} BlurKernelType;
-#define MAX_BRUSH_PIXEL_RADIUS 200
+#define MAX_BRUSH_PIXEL_RADIUS 500
#endif
diff --git a/source/blender/makesdna/DNA_camera_types.h b/source/blender/makesdna/DNA_camera_types.h
index c99494ce00e..c45322b818f 100644
--- a/source/blender/makesdna/DNA_camera_types.h
+++ b/source/blender/makesdna/DNA_camera_types.h
@@ -33,7 +33,7 @@
#define __DNA_CAMERA_TYPES_H__
#include "DNA_defs.h"
-
+#include "DNA_gpu_types.h"
#include "DNA_ID.h"
#ifdef __cplusplus
@@ -44,6 +44,16 @@ struct Object;
struct AnimData;
struct Ipo;
+/* ------------------------------------------- */
+/* Stereo Settings */
+typedef struct CameraStereoSettings {
+ float interocular_distance;
+ float convergence_distance;
+ short convergence_mode;
+ short pivot;
+ short pad, pad2;
+} CameraStereoSettings;
+
typedef struct Camera {
ID id;
struct AnimData *adt; /* animation data (must be immediately after id for utilities to use it) */
@@ -56,7 +66,7 @@ typedef struct Camera {
float lens, ortho_scale, drawsize;
float sensor_x, sensor_y;
float shiftx, shifty;
-
+
/* yafray: dof params */
/* qdn: yafray var 'YF_dofdist' now enabled for defocus composite node as well.
* The name was not changed so that no other files need to be modified */
@@ -65,9 +75,13 @@ typedef struct Camera {
struct Ipo *ipo DNA_DEPRECATED; /* old animation system, deprecated for 2.5 */
struct Object *dof_ob;
+ struct GPUDOFSettings gpu_dof;
char sensor_fit;
char pad[7];
+
+ /* Stereo settings */
+ struct CameraStereoSettings stereo;
} Camera;
/* **************** CAMERA ********************* */
@@ -96,18 +110,17 @@ enum {
CAM_SHOWLIMITS = (1 << 0),
CAM_SHOWMIST = (1 << 1),
CAM_SHOWPASSEPARTOUT = (1 << 2),
- CAM_SHOWTITLESAFE = (1 << 3),
+ CAM_SHOW_SAFE_MARGINS = (1 << 3),
CAM_SHOWNAME = (1 << 4),
CAM_ANGLETOGGLE = (1 << 5),
CAM_DS_EXPAND = (1 << 6),
+#ifdef DNA_DEPRECATED
CAM_PANORAMA = (1 << 7), /* deprecated */
+#endif
CAM_SHOWSENSOR = (1 << 8),
+ CAM_SHOW_SAFE_CENTER = (1 << 9),
};
-#if (DNA_DEPRECATED_GCC_POISON == 1)
-#pragma GCC poison CAM_PANORAMA
-#endif
-
/* yafray: dof sampling switch */
/* #define CAM_YF_NO_QMC 512 */ /* deprecated */
@@ -121,6 +134,20 @@ enum {
#define DEFAULT_SENSOR_WIDTH 32.0f
#define DEFAULT_SENSOR_HEIGHT 18.0f
+/* stereo->convergence_mode */
+enum {
+ CAM_S3D_OFFAXIS = 0,
+ CAM_S3D_PARALLEL = 1,
+ CAM_S3D_TOE = 2,
+};
+
+/* stereo->pivot */
+enum {
+ CAM_S3D_PIVOT_LEFT = 0,
+ CAM_S3D_PIVOT_RIGHT = 1,
+ CAM_S3D_PIVOT_CENTER = 2,
+};
+
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/makesdna/DNA_cloth_types.h b/source/blender/makesdna/DNA_cloth_types.h
index 6c7d500e4e2..07bc2478837 100644
--- a/source/blender/makesdna/DNA_cloth_types.h
+++ b/source/blender/makesdna/DNA_cloth_types.h
@@ -32,6 +32,8 @@
#ifndef __DNA_CLOTH_TYPES_H__
#define __DNA_CLOTH_TYPES_H__
+#include "DNA_defs.h"
+
/**
* This struct contains all the global data required to run a simulation.
* At the time of this writing, this structure contains data appropriate
@@ -69,14 +71,23 @@ typedef struct ClothSimSettings {
float goalspring;
float goalfrict;
float velocity_smooth; /* smoothing of velocities for hair */
+ float density_target; /* minimum density for hair */
+ float density_strength; /* influence of hair density */
float collider_friction; /* friction with colliders */
float vel_damping; /* damp the velocity to speed up getting to the resting position */
float shrink_min; /* min amount to shrink cloth by 0.0f (no shrink) - 1.0f (shrink to nothing) */
float shrink_max; /* max amount to shrink cloth by 0.0f (no shrink) - 1.0f (shrink to nothing) */
+
+ /* XXX various hair stuff
+ * should really be separate, this struct is a horrible mess already
+ */
+ float bending_damping; /* damping of bending springs */
+ float voxel_cell_size; /* size of voxel grid cells for continuum dynamics */
+ int pad;
int stepsPerFrame; /* Number of time steps per frame. */
int flags; /* flags, see CSIMSETT_FLAGS enum above. */
- int preroll; /* How many frames of simulation to do before we start. */
+ int preroll DNA_DEPRECATED; /* How many frames of simulation to do before we start. */
int maxspringlen; /* in percent!; if tearing enabled, a spring will get cut */
short solver_type; /* which solver should be used? txold */
short vgroup_bend; /* vertex group for scaling bending stiffness */
@@ -86,7 +97,6 @@ typedef struct ClothSimSettings {
short shapekey_rest; /* vertex group for scaling structural stiffness */
short presets; /* used for presets on GUI */
short reset;
- char pad[4];
struct EffectorWeights *effector_weights;
} ClothSimSettings;
@@ -97,15 +107,16 @@ typedef struct ClothCollSettings {
float epsilon; /* min distance for collisions. */
float self_friction; /* Fiction/damping with self contact. */
float friction; /* Friction/damping applied on contact with other object.*/
+ float damping; /* Collision restitution on contact with other object.*/
float selfepsilon; /* for selfcollision */
float repel_force, distance_repel;
int flags; /* collision flags defined in BKE_cloth.h */
short self_loop_count; /* How many iterations for the selfcollision loop */
short loop_count; /* How many iterations for the collision loop. */
+ int pad;
struct Group *group; /* Only use colliders from this group of objects */
short vgroup_selfcol; /* vgroup to paint which vertices are used for self collisions */
- short pad;
- int pad2;
+ short pad2[3];
} ClothCollSettings;
diff --git a/source/blender/makesdna/DNA_color_types.h b/source/blender/makesdna/DNA_color_types.h
index e3731129632..c9a5e056e4a 100644
--- a/source/blender/makesdna/DNA_color_types.h
+++ b/source/blender/makesdna/DNA_color_types.h
@@ -133,7 +133,6 @@ typedef struct Histogram {
float co[2][2];
} Histogram;
-struct ImBuf;
typedef struct Scopes {
int ok;
diff --git a/source/blender/makesdna/DNA_constraint_types.h b/source/blender/makesdna/DNA_constraint_types.h
index 0277956cac5..86991245068 100644
--- a/source/blender/makesdna/DNA_constraint_types.h
+++ b/source/blender/makesdna/DNA_constraint_types.h
@@ -173,6 +173,12 @@ typedef struct bSplineIKConstraint {
/* settings */
short flag; /* general settings for constraint */
short xzScaleMode; /* method used for determining the x & z scaling of the bones */
+
+ /* volume preservation settings */
+ float bulge;
+ float bulge_min;
+ float bulge_max;
+ float bulge_smooth;
} bSplineIKConstraint;
@@ -284,10 +290,14 @@ typedef struct bFollowPathConstraint {
/* Stretch to constraint */
typedef struct bStretchToConstraint {
struct Object *tar;
+ int flag;
int volmode;
- int plane;
+ int plane;
float orglength;
float bulge;
+ float bulge_min;
+ float bulge_max;
+ float bulge_smooth;
char subtarget[64]; /* MAX_ID_NAME-2 */
} bStretchToConstraint;
@@ -676,15 +686,19 @@ typedef enum eKinematic_Flags {
/* bSplineIKConstraint->flag */
typedef enum eSplineIK_Flags {
/* chain has been attached to spline */
- CONSTRAINT_SPLINEIK_BOUND = (1<<0),
+ CONSTRAINT_SPLINEIK_BOUND = (1 << 0),
/* root of chain is not influenced by the constraint */
- CONSTRAINT_SPLINEIK_NO_ROOT = (1<<1),
+ CONSTRAINT_SPLINEIK_NO_ROOT = (1 << 1),
/* bones in the chain should not scale to fit the curve */
- CONSTRAINT_SPLINEIK_SCALE_LIMITED = (1<<2),
+ CONSTRAINT_SPLINEIK_SCALE_LIMITED = (1 << 2),
/* evenly distribute the bones along the path regardless of length */
- CONSTRAINT_SPLINEIK_EVENSPLITS = (1<<3),
+ CONSTRAINT_SPLINEIK_EVENSPLITS = (1 << 3),
/* don't adjust the x and z scaling of the bones by the curve radius */
- CONSTRAINT_SPLINEIK_NO_CURVERAD = (1<<4)
+ CONSTRAINT_SPLINEIK_NO_CURVERAD = (1 << 4),
+
+ /* for "volumetric" xz scale mode, limit the minimum or maximum scale values */
+ CONSTRAINT_SPLINEIK_USE_BULGE_MIN = (1 << 5),
+ CONSTRAINT_SPLINEIK_USE_BULGE_MAX = (1 << 6),
} eSplineIK_Flags;
/* bSplineIKConstraint->xzScaleMode */
@@ -694,7 +708,9 @@ typedef enum eSplineIK_XZScaleModes {
/* bones in the chain should take their x/z scales from the original scaling */
CONSTRAINT_SPLINEIK_XZS_ORIGINAL = 1,
/* x/z scales are the inverse of the y-scale */
- CONSTRAINT_SPLINEIK_XZS_VOLUMETRIC = 2
+ CONSTRAINT_SPLINEIK_XZS_INVERSE = 2,
+ /* x/z scales are computed using a volume preserving technique (from Stretch To constraint) */
+ CONSTRAINT_SPLINEIK_XZS_VOLUMETRIC = 3
} eSplineIK_XZScaleModes;
/* MinMax (floor) flags */
@@ -820,6 +836,12 @@ typedef enum eObjectSolver_Flags {
#define CONSTRAINT_DRAW_PIVOT 0x40
#define CONSTRAINT_DISABLE_LINKED_COLLISION 0x80
+/* ObjectSolver Constraint -> flag */
+typedef enum eStretchTo_Flags {
+ STRETCHTOCON_USE_BULGE_MIN = (1 << 0),
+ STRETCHTOCON_USE_BULGE_MAX = (1 << 1),
+} eStretchTo_Flags;
+
/* important: these defines need to match up with PHY_DynamicTypes headerfile */
#define CONSTRAINT_RB_BALL 1
#define CONSTRAINT_RB_HINGE 2
diff --git a/source/blender/makesdna/DNA_curve_types.h b/source/blender/makesdna/DNA_curve_types.h
index 87496fb491f..9be3fbc2348 100644
--- a/source/blender/makesdna/DNA_curve_types.h
+++ b/source/blender/makesdna/DNA_curve_types.h
@@ -46,7 +46,6 @@ struct Key;
struct Material;
struct VFont;
struct AnimData;
-struct SelBox;
struct EditFont;
struct GHash;
@@ -158,6 +157,7 @@ typedef struct Nurb {
short tilt_interp; /* KEY_LINEAR, KEY_CARDINAL, KEY_BSPLINE */
short radius_interp;
+ /* only used for dynamically generated Nurbs created from OB_FONT's */
int charidx;
} Nurb;
@@ -270,86 +270,101 @@ typedef struct Curve {
/* **************** CURVE ********************* */
-/* texflag */
-#define CU_AUTOSPACE 1
-
-/* drawflag */
-#define CU_HIDE_HANDLES (1 << 0)
-#define CU_HIDE_NORMALS (1 << 1)
-
-/* flag */
-#define CU_3D 1
-#define CU_FRONT 2
-#define CU_BACK 4
-#define CU_PATH 8
-#define CU_FOLLOW 16
-#define CU_UV_ORCO 32
-#define CU_DEFORM_BOUNDS_OFF 64
-#define CU_STRETCH 128
-/* #define CU_OFFS_PATHDIST 256 */ /* DEPRECATED */
-#define CU_FAST 512 /* Font: no filling inside editmode */
-/* #define CU_RETOPO 1024 */ /* DEPRECATED */
-#define CU_DS_EXPAND 2048
-#define CU_PATH_RADIUS 4096 /* make use of the path radius if this is enabled (default for new curves) */
-#define CU_DEFORM_FILL 8192 /* fill 2d curve after deformation */
-#define CU_FILL_CAPS 16384 /* fill bevel caps */
-#define CU_MAP_TAPER 32768 /* map taper object to beveled area */
-
-/* twist mode */
-#define CU_TWIST_Z_UP 0
-// #define CU_TWIST_Y_UP 1 // not used yet
-// #define CU_TWIST_X_UP 2
-#define CU_TWIST_MINIMUM 3
-#define CU_TWIST_TANGENT 4
-
-/* bevel factor mapping */
+/* Curve.texflag */
enum {
- CU_BEVFAC_MAP_RESOLU = 0,
+ CU_AUTOSPACE = 1,
+};
+
+/* Curve.drawflag */
+enum {
+ CU_HIDE_HANDLES = 1 << 0,
+ CU_HIDE_NORMALS = 1 << 1,
+};
+
+/* Curve.flag */
+enum {
+ CU_3D = 1 << 0,
+ CU_FRONT = 1 << 1,
+ CU_BACK = 1 << 2,
+ CU_PATH = 1 << 3,
+ CU_FOLLOW = 1 << 4,
+ CU_UV_ORCO = 1 << 5,
+ CU_DEFORM_BOUNDS_OFF = 1 << 6,
+ CU_STRETCH = 1 << 7,
+ /* CU_OFFS_PATHDIST = 1 << 8, */ /* DEPRECATED */
+ CU_FAST = 1 << 9, /* Font: no filling inside editmode */
+ /* CU_RETOPO = 1 << 10, */ /* DEPRECATED */
+ CU_DS_EXPAND = 1 << 11,
+ CU_PATH_RADIUS = 1 << 12, /* make use of the path radius if this is enabled (default for new curves) */
+ CU_DEFORM_FILL = 1 << 13, /* fill 2d curve after deformation */
+ CU_FILL_CAPS = 1 << 14, /* fill bevel caps */
+ CU_MAP_TAPER = 1 << 15, /* map taper object to beveled area */
+};
+
+/* Curve.twist_mode */
+enum {
+ CU_TWIST_Z_UP = 0,
+ /* CU_TWIST_Y_UP = 1, */ /* not used yet */
+ /* CU_TWIST_X_UP = 2, */
+ CU_TWIST_MINIMUM = 3,
+ CU_TWIST_TANGENT = 4,
+};
+
+/* Curve.bevfac1_mapping, Curve.bevfac2_mapping, bevel factor mapping */
+enum {
+ CU_BEVFAC_MAP_RESOLU = 0,
CU_BEVFAC_MAP_SEGMENT = 1,
- CU_BEVFAC_MAP_SPLINE = 2
+ CU_BEVFAC_MAP_SPLINE = 2,
};
-/* spacemode */
-#define CU_LEFT 0
-#define CU_MIDDLE 1
-#define CU_RIGHT 2
-#define CU_JUSTIFY 3
-#define CU_FLUSH 4
-
-/* flag (nurb) */
-#define CU_SMOOTH 1
-#define CU_2D 8 /* moved from type since 2.4x */
-
-/* type (nurb) */
-#define CU_POLY 0
-#define CU_BEZIER 1
-#define CU_BSPLINE 2
-#define CU_CARDINAL 3
-#define CU_NURBS 4
-#define CU_TYPE (CU_POLY|CU_BEZIER|CU_BSPLINE|CU_CARDINAL|CU_NURBS)
-
- /* only for adding */
-#define CU_PRIMITIVE 0xF00
-
- /* 2 or 4 points */
-#define CU_PRIM_CURVE 0x100
- /* 8 points circle */
-#define CU_PRIM_CIRCLE 0x200
- /* 4x4 patch Nurb */
-#define CU_PRIM_PATCH 0x300
-#define CU_PRIM_TUBE 0x400
-#define CU_PRIM_SPHERE 0x500
-#define CU_PRIM_DONUT 0x600
- /* 5 points, 5th order straight line (for anim path) */
-#define CU_PRIM_PATH 0x700
-
-
-/* flagu flagv (nurb) */
-#define CU_NURB_CYCLIC 1
-#define CU_NURB_ENDPOINT 2
-#define CU_NURB_BEZIER 4
-
-#define CU_ACT_NONE -1
+/* Curve.spacemode */
+enum {
+ CU_LEFT = 0,
+ CU_MIDDLE = 1,
+ CU_RIGHT = 2,
+ CU_JUSTIFY = 3,
+ CU_FLUSH = 4,
+};
+
+/* Nurb.flag */
+enum {
+ CU_SMOOTH = 1 << 0,
+ CU_2D = 1 << 3, /* moved from type since 2.4x */
+};
+
+/* Nurb.type */
+enum {
+ CU_POLY = 0,
+ CU_BEZIER = 1,
+ CU_BSPLINE = 2,
+ CU_CARDINAL = 3,
+ CU_NURBS = 4,
+ CU_TYPE = (CU_POLY | CU_BEZIER | CU_BSPLINE | CU_CARDINAL | CU_NURBS),
+
+ /* only for adding */
+ CU_PRIMITIVE = 0xF00,
+
+ /* 2 or 4 points */
+ CU_PRIM_CURVE = 0x100,
+ /* 8 points circle */
+ CU_PRIM_CIRCLE = 0x200,
+ /* 4x4 patch Nurb */
+ CU_PRIM_PATCH = 0x300,
+ CU_PRIM_TUBE = 0x400,
+ CU_PRIM_SPHERE = 0x500,
+ CU_PRIM_DONUT = 0x600,
+ /* 5 points, 5th order straight line (for anim path) */
+ CU_PRIM_PATH = 0x700,
+};
+
+/* Nurb.flagu, Nurb.flagv */
+enum {
+ CU_NURB_CYCLIC = 1 << 0,
+ CU_NURB_ENDPOINT = 1 << 1,
+ CU_NURB_BEZIER = 1 << 2,
+};
+
+#define CU_ACT_NONE -1
/* *************** BEZTRIPLE **************** */
@@ -366,9 +381,9 @@ typedef enum eBezTriple_Handle {
/* interpolation modes (used only for BezTriple->ipo) */
typedef enum eBezTriple_Interpolation {
/* traditional interpolation */
- BEZT_IPO_CONST = 0, /* constant interpolation */
- BEZT_IPO_LIN = 1, /* linear interpolation */
- BEZT_IPO_BEZ = 2, /* bezier interpolation */
+ BEZT_IPO_CONST = 0, /* constant interpolation */
+ BEZT_IPO_LIN = 1, /* linear interpolation */
+ BEZT_IPO_BEZ = 2, /* bezier interpolation */
/* easing equations */
BEZT_IPO_BACK = 3,
@@ -380,7 +395,7 @@ typedef enum eBezTriple_Interpolation {
BEZT_IPO_QUAD = 9,
BEZT_IPO_QUART = 10,
BEZT_IPO_QUINT = 11,
- BEZT_IPO_SINE = 12
+ BEZT_IPO_SINE = 12,
} eBezTriple_Interpolation;
/* easing modes (used only for Keyframes - BezTriple->easing) */
@@ -389,31 +404,38 @@ typedef enum eBezTriple_Easing {
BEZT_IPO_EASE_IN = 1,
BEZT_IPO_EASE_OUT = 2,
- BEZT_IPO_EASE_IN_OUT = 3
+ BEZT_IPO_EASE_IN_OUT = 3,
} eBezTriple_Easing;
/* types of keyframe (used only for BezTriple->hide when BezTriple is used in F-Curves) */
typedef enum eBezTriple_KeyframeType {
- BEZT_KEYTYPE_KEYFRAME = 0, /* default - 'proper' Keyframe */
- BEZT_KEYTYPE_EXTREME = 1, /* 'extreme' keyframe */
- BEZT_KEYTYPE_BREAKDOWN = 2, /* 'breakdown' keyframe */
- BEZT_KEYTYPE_JITTER = 3, /* 'jitter' keyframe (for adding 'filler' secondary motion) */
+ BEZT_KEYTYPE_KEYFRAME = 0, /* default - 'proper' Keyframe */
+ BEZT_KEYTYPE_EXTREME = 1, /* 'extreme' keyframe */
+ BEZT_KEYTYPE_BREAKDOWN = 2, /* 'breakdown' keyframe */
+ BEZT_KEYTYPE_JITTER = 3, /* 'jitter' keyframe (for adding 'filler' secondary motion) */
} eBezTriple_KeyframeType;
/* checks if the given BezTriple is selected */
-#define BEZSELECTED(bezt) (((bezt)->f2 & SELECT) || ((bezt)->f1 & SELECT) || ((bezt)->f3 & SELECT))
-#define BEZSELECTED_HIDDENHANDLES(cu, bezt) (((cu)->drawflag & CU_HIDE_HANDLES) ? (bezt)->f2 & SELECT : BEZSELECTED(bezt))
+#define BEZT_ISSEL_ANY(bezt) \
+ (((bezt)->f2 & SELECT) || ((bezt)->f1 & SELECT) || ((bezt)->f3 & SELECT))
+#define BEZT_ISSEL_ANY_HIDDENHANDLES(cu, bezt) \
+ (((cu)->drawflag & CU_HIDE_HANDLES) ? (bezt)->f2 & SELECT : BEZT_ISSEL_ANY(bezt))
+
+#define BEZT_SEL_ALL(bezt) { (bezt)->f1 |= SELECT; (bezt)->f2 |= SELECT; (bezt)->f3 |= SELECT; } ((void)0)
+#define BEZT_DESEL_ALL(bezt) { (bezt)->f1 &= ~SELECT; (bezt)->f2 &= ~SELECT; (bezt)->f3 &= ~SELECT; } ((void)0)
/* *************** CHARINFO **************** */
-/* flag */
-/* note: CU_CHINFO_WRAP and CU_CHINFO_SMALLCAPS_TEST are set dynamically */
-#define CU_CHINFO_BOLD (1<<0)
-#define CU_CHINFO_ITALIC (1<<1)
-#define CU_CHINFO_UNDERLINE (1<<2)
-#define CU_CHINFO_WRAP (1<<3) /* wordwrap occurred here */
-#define CU_CHINFO_SMALLCAPS (1<<4)
-#define CU_CHINFO_SMALLCAPS_CHECK (1<<5) /* set at runtime, checks if case switching is needed */
+/* CharInfo.flag */
+enum {
+ /* note: CU_CHINFO_WRAP and CU_CHINFO_SMALLCAPS_TEST are set dynamically */
+ CU_CHINFO_BOLD = 1 << 0,
+ CU_CHINFO_ITALIC = 1 << 1,
+ CU_CHINFO_UNDERLINE = 1 << 2,
+ CU_CHINFO_WRAP = 1 << 3, /* wordwrap occurred here */
+ CU_CHINFO_SMALLCAPS = 1 << 4,
+ CU_CHINFO_SMALLCAPS_CHECK = 1 << 5, /* set at runtime, checks if case switching is needed */
+};
/* mixed with KEY_LINEAR but define here since only curve supports */
#define KEY_CU_EASE 3
diff --git a/source/blender/makesdna/DNA_customdata_types.h b/source/blender/makesdna/DNA_customdata_types.h
index 70dc43676ac..3807bb296fd 100644
--- a/source/blender/makesdna/DNA_customdata_types.h
+++ b/source/blender/makesdna/DNA_customdata_types.h
@@ -63,9 +63,10 @@ typedef struct CustomDataExternal {
* layers, each with a data type (e.g. MTFace, MDeformVert, etc.). */
typedef struct CustomData {
CustomDataLayer *layers; /* CustomDataLayers, ordered by type */
- int typemap[41]; /* runtime only! - maps types to indices of first layer of that type,
+ int typemap[42]; /* runtime only! - maps types to indices of first layer of that type,
* MUST be >= CD_NUMTYPES, but we cant use a define here.
* Correct size is ensured in CustomData_update_typemap assert() */
+ int pad_i1;
int totlayer, maxlayer; /* number of layers, size of layers array */
int totsize; /* in editmode, total size of all data layers */
struct BLI_mempool *pool; /* (BMesh Only): Memory pool for allocation of blocks */
@@ -73,9 +74,11 @@ typedef struct CustomData {
} CustomData;
/* CustomData.type */
-enum {
+typedef enum CustomDataType {
CD_MVERT = 0,
+#ifdef DNA_DEPRECATED
CD_MSTICKY = 1, /* DEPRECATED */
+#endif
CD_MDEFORMVERT = 2,
CD_MEDGE = 3,
CD_MFACE = 4,
@@ -95,8 +98,8 @@ enum {
CD_TANGENT = 18,
CD_MDISPS = 19,
CD_PREVIEW_MCOL = 20, /* for displaying weightpaint colors */
- CD_ID_MCOL = 21,
- CD_TEXTURE_MCOL = 22,
+/* CD_ID_MCOL = 21, */
+ CD_TEXTURE_MLOOPCOL = 22,
CD_CLOTH_ORCO = 23,
CD_RECAST = 24,
@@ -119,13 +122,14 @@ enum {
CD_FREESTYLE_FACE = 38,
CD_MLOOPTANGENT = 39,
CD_TESSLOOPNORMAL = 40,
+ CD_CUSTOMLOOPNORMAL = 41,
- CD_NUMTYPES = 41
-};
+ CD_NUMTYPES = 42
+} CustomDataType;
/* Bits for CustomDataMask */
#define CD_MASK_MVERT (1 << CD_MVERT)
-#define CD_MASK_MSTICKY (1 << CD_MSTICKY) /* DEPRECATED */
+// #define CD_MASK_MSTICKY (1 << CD_MSTICKY) /* DEPRECATED */
#define CD_MASK_MDEFORMVERT (1 << CD_MDEFORMVERT)
#define CD_MASK_MEDGE (1 << CD_MEDGE)
#define CD_MASK_MFACE (1 << CD_MFACE)
@@ -167,6 +171,7 @@ enum {
#define CD_MASK_FREESTYLE_FACE (1LL << CD_FREESTYLE_FACE)
#define CD_MASK_MLOOPTANGENT (1LL << CD_MLOOPTANGENT)
#define CD_MASK_TESSLOOPNORMAL (1LL << CD_TESSLOOPNORMAL)
+#define CD_MASK_CUSTOMLOOPNORMAL (1LL << CD_CUSTOMLOOPNORMAL)
/* CustomData.flag */
enum {
@@ -188,6 +193,8 @@ enum {
#define DYNTOPO_NODE_NONE -1
+#define CD_TEMP_CHUNK_SIZE 128
+
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/makesdna/DNA_documentation.h b/source/blender/makesdna/DNA_documentation.h
index 0dd7f37f8b4..0a0d46d70ff 100644
--- a/source/blender/makesdna/DNA_documentation.h
+++ b/source/blender/makesdna/DNA_documentation.h
@@ -48,6 +48,24 @@
* be badly defined. The reason for this is that it is called with
* different types of arguments. It takes a char* at this moment...
*
+ * - Ignoring structs:
+ *
+ * Sometimes we need to define structs in DNA which aren't written
+ * to disk, and can be excluded from blend file DNA string.
+ * in this case, add two '#' chars directly before the struct. eg.
+ *
+ * \code{.c}
+ * #
+ * #
+ * typedef struct MyStruct {
+ * int value;
+ * } MyStruct;
+ * \endcode
+ *
+ * Ignored structs can only be referred to from non-ignored structs
+ * when referred to as a pointer (where they're usually allocated
+ * and cleared in ``readfile.c``).
+ *
* - %Path to the header files
*
* Also because of historical reasons, there is a path prefix to the
diff --git a/source/blender/makesdna/DNA_dynamicpaint_types.h b/source/blender/makesdna/DNA_dynamicpaint_types.h
index d2b95c959b3..17553e98817 100644
--- a/source/blender/makesdna/DNA_dynamicpaint_types.h
+++ b/source/blender/makesdna/DNA_dynamicpaint_types.h
@@ -29,59 +29,74 @@
#define __DNA_DYNAMICPAINT_TYPES_H__
#include "DNA_listBase.h"
-struct CurveMapping;
struct PaintSurfaceData;
/* surface format */
-#define MOD_DPAINT_SURFACE_F_PTEX 0
-#define MOD_DPAINT_SURFACE_F_VERTEX 1
-#define MOD_DPAINT_SURFACE_F_IMAGESEQ 2
+enum {
+ MOD_DPAINT_SURFACE_F_PTEX = 0,
+ MOD_DPAINT_SURFACE_F_VERTEX = 1,
+ MOD_DPAINT_SURFACE_F_IMAGESEQ = 2,
+};
/* surface type */
-#define MOD_DPAINT_SURFACE_T_PAINT 0
-#define MOD_DPAINT_SURFACE_T_DISPLACE 1
-#define MOD_DPAINT_SURFACE_T_WEIGHT 2
-#define MOD_DPAINT_SURFACE_T_WAVE 3
+enum {
+ MOD_DPAINT_SURFACE_T_PAINT = 0,
+ MOD_DPAINT_SURFACE_T_DISPLACE = 1,
+ MOD_DPAINT_SURFACE_T_WEIGHT = 2,
+ MOD_DPAINT_SURFACE_T_WAVE = 3,
+};
/* surface flags */
-#define MOD_DPAINT_ACTIVE (1<<0) /* Is surface enabled */
+enum {
+ MOD_DPAINT_ACTIVE = 1 << 0, /* Is surface enabled */
-#define MOD_DPAINT_ANTIALIAS (1<<1) /* do antialiasing */
-#define MOD_DPAINT_DISSOLVE (1<<2) /* do dissolve */
-#define MOD_DPAINT_MULALPHA (1<<3) /* Multiply color by alpha when saving image */
-#define MOD_DPAINT_DISSOLVE_LOG (1<<4) /* Use 1/x for surface dissolve */
-#define MOD_DPAINT_DRY_LOG (1<<5) /* Use 1/x for drying paint */
-#define MOD_DPAINT_PREVIEW (1<<6) /* preview this surface on viewport*/
+ MOD_DPAINT_ANTIALIAS = 1 << 1, /* do antialiasing */
+ MOD_DPAINT_DISSOLVE = 1 << 2, /* do dissolve */
+ MOD_DPAINT_MULALPHA = 1 << 3, /* Multiply color by alpha when saving image */
+ MOD_DPAINT_DISSOLVE_LOG = 1 << 4, /* Use 1/x for surface dissolve */
+ MOD_DPAINT_DRY_LOG = 1 << 5, /* Use 1/x for drying paint */
+ MOD_DPAINT_PREVIEW = 1 << 6, /* preview this surface on viewport*/
-#define MOD_DPAINT_WAVE_OPEN_BORDERS (1<<7) /* passes waves through mesh edges */
-#define MOD_DPAINT_DISP_INCREMENTAL (1<<8) /* builds displace on top of earlier values */
-#define MOD_DPAINT_USE_DRYING (1<<9) /* use drying */
+ MOD_DPAINT_WAVE_OPEN_BORDERS = 1 << 7, /* passes waves through mesh edges */
+ MOD_DPAINT_DISP_INCREMENTAL = 1 << 8, /* builds displace on top of earlier values */
+ MOD_DPAINT_USE_DRYING = 1 << 9, /* use drying */
-#define MOD_DPAINT_OUT1 (1<<10) /* output primary surface */
-#define MOD_DPAINT_OUT2 (1<<11) /* output secondary surface */
+ MOD_DPAINT_OUT1 = 1 << 10, /* output primary surface */
+ MOD_DPAINT_OUT2 = 1 << 11, /* output secondary surface */
+};
/* image_fileformat */
-#define MOD_DPAINT_IMGFORMAT_PNG 0
-#define MOD_DPAINT_IMGFORMAT_OPENEXR 1
+enum {
+ MOD_DPAINT_IMGFORMAT_PNG = 0,
+ MOD_DPAINT_IMGFORMAT_OPENEXR = 1,
+};
/* disp_format */
-#define MOD_DPAINT_DISP_DISPLACE 0 /* displacement output displace map */
-#define MOD_DPAINT_DISP_DEPTH 1 /* displacement output depth data */
+enum {
+ MOD_DPAINT_DISP_DISPLACE = 0, /* displacement output displace map */
+ MOD_DPAINT_DISP_DEPTH = 1, /* displacement output depth data */
+};
/* effect */
-#define MOD_DPAINT_EFFECT_DO_SPREAD (1<<0) /* do spread effect */
-#define MOD_DPAINT_EFFECT_DO_DRIP (1<<1) /* do drip effect */
-#define MOD_DPAINT_EFFECT_DO_SHRINK (1<<2) /* do shrink effect */
+enum {
+ MOD_DPAINT_EFFECT_DO_SPREAD = 1 << 0, /* do spread effect */
+ MOD_DPAINT_EFFECT_DO_DRIP = 1 << 1, /* do drip effect */
+ MOD_DPAINT_EFFECT_DO_SHRINK = 1 << 2, /* do shrink effect */
+};
/* preview_id */
-#define MOD_DPAINT_SURFACE_PREV_PAINT 0
-#define MOD_DPAINT_SURFACE_PREV_WETMAP 1
+enum {
+ MOD_DPAINT_SURFACE_PREV_PAINT = 0,
+ MOD_DPAINT_SURFACE_PREV_WETMAP = 1,
+};
/* init_color_type */
-#define MOD_DPAINT_INITIAL_NONE 0
-#define MOD_DPAINT_INITIAL_COLOR 1
-#define MOD_DPAINT_INITIAL_TEXTURE 2
-#define MOD_DPAINT_INITIAL_VERTEXCOLOR 3
+enum {
+ MOD_DPAINT_INITIAL_NONE = 0,
+ MOD_DPAINT_INITIAL_COLOR = 1,
+ MOD_DPAINT_INITIAL_TEXTURE = 2,
+ MOD_DPAINT_INITIAL_VERTEXCOLOR = 3,
+};
typedef struct DynamicPaintSurface {
@@ -136,11 +151,14 @@ typedef struct DynamicPaintSurface {
} DynamicPaintSurface;
/* canvas flags */
-#if 0 /* This should not be needed, having a valid WEIGHT_MCOL layer should be enough.
- * And if not, should be a general flag. But seems unnecessary for now... */
-#define MOD_DPAINT_PREVIEW_READY (1<<0) /* if viewport preview is ready */
+enum {
+ /* This should not be needed, having a valid WEIGHT_MCOL layer should be enough.
+ * And if not, should be a general flag. But seems unnecessary for now... */
+#if 0
+ MOD_DPAINT_PREVIEW_READY = 1 << 0, /* if viewport preview is ready */
#endif
-#define MOD_DPAINT_BAKING (1<<1) /* surface is already baking, so it wont get updated (loop) */
+ MOD_DPAINT_BAKING = 1 << 1, /* surface is already baking, so it wont get updated (loop) */
+};
/* Canvas settings */
typedef struct DynamicPaintCanvasSettings {
@@ -157,47 +175,56 @@ typedef struct DynamicPaintCanvasSettings {
/* flags */
-#define MOD_DPAINT_PART_RAD (1<<0) /* use particle radius */
-#define MOD_DPAINT_USE_MATERIAL (1<<1) /* use object material */
-#define MOD_DPAINT_ABS_ALPHA (1<<2) /* don't increase alpha unless
- * paint alpha is higher than existing */
-#define MOD_DPAINT_ERASE (1<<3) /* removes paint */
-
-#define MOD_DPAINT_RAMP_ALPHA (1<<4) /* only read falloff ramp alpha */
-#define MOD_DPAINT_PROX_PROJECT (1<<5) /* do proximity check only in defined dir */
-#define MOD_DPAINT_INVERSE_PROX (1<<6) /* inverse proximity painting */
-#define MOD_DPAINT_NEGATE_VOLUME (1<<7) /* negates volume influence on "volume + prox" mode */
-
-#define MOD_DPAINT_DO_SMUDGE (1<<8) /* brush smudges existing paint */
-#define MOD_DPAINT_VELOCITY_ALPHA (1<<9) /* multiply brush influence by velocity */
-#define MOD_DPAINT_VELOCITY_COLOR (1<<10) /* replace brush color by velocity color ramp */
-#define MOD_DPAINT_VELOCITY_DEPTH (1<<11) /* multiply brush intersection depth by velocity */
-
-#define MOD_DPAINT_USES_VELOCITY ((1<<8)|(1<<9)|(1<<10)|(1<<11))
+enum {
+ MOD_DPAINT_PART_RAD = 1 << 0, /* use particle radius */
+ MOD_DPAINT_USE_MATERIAL = 1 << 1, /* use object material */
+ MOD_DPAINT_ABS_ALPHA = 1 << 2, /* don't increase alpha unless paint alpha is higher than existing */
+ MOD_DPAINT_ERASE = 1 << 3, /* removes paint */
+
+ MOD_DPAINT_RAMP_ALPHA = 1 << 4, /* only read falloff ramp alpha */
+ MOD_DPAINT_PROX_PROJECT = 1 << 5, /* do proximity check only in defined dir */
+ MOD_DPAINT_INVERSE_PROX = 1 << 6, /* inverse proximity painting */
+ MOD_DPAINT_NEGATE_VOLUME = 1 << 7, /* negates volume influence on "volume + prox" mode */
+
+ MOD_DPAINT_DO_SMUDGE = 1 << 8, /* brush smudges existing paint */
+ MOD_DPAINT_VELOCITY_ALPHA = 1 << 9, /* multiply brush influence by velocity */
+ MOD_DPAINT_VELOCITY_COLOR = 1 << 10, /* replace brush color by velocity color ramp */
+ MOD_DPAINT_VELOCITY_DEPTH = 1 << 11, /* multiply brush intersection depth by velocity */
+
+ MOD_DPAINT_USES_VELOCITY = (MOD_DPAINT_DO_SMUDGE | MOD_DPAINT_VELOCITY_ALPHA |
+ MOD_DPAINT_VELOCITY_COLOR | MOD_DPAINT_VELOCITY_DEPTH),
+};
/* collision type */
-#define MOD_DPAINT_COL_VOLUME 0 /* paint with mesh volume */
-#define MOD_DPAINT_COL_DIST 1 /* paint using distance to mesh surface */
-#define MOD_DPAINT_COL_VOLDIST 2 /* use both volume and distance */
-#define MOD_DPAINT_COL_PSYS 3 /* use particle system */
-#define MOD_DPAINT_COL_POINT 4 /* use distance to object center point */
+enum {
+ MOD_DPAINT_COL_VOLUME = 0, /* paint with mesh volume */
+ MOD_DPAINT_COL_DIST = 1, /* paint using distance to mesh surface */
+ MOD_DPAINT_COL_VOLDIST = 2, /* use both volume and distance */
+ MOD_DPAINT_COL_PSYS = 3, /* use particle system */
+ MOD_DPAINT_COL_POINT = 4, /* use distance to object center point */
+};
/* proximity_falloff */
-#define MOD_DPAINT_PRFALL_CONSTANT 0 /* no-falloff */
-#define MOD_DPAINT_PRFALL_SMOOTH 1 /* smooth, linear falloff */
-#define MOD_DPAINT_PRFALL_RAMP 2 /* use color ramp */
+enum {
+ MOD_DPAINT_PRFALL_CONSTANT = 0, /* no-falloff */
+ MOD_DPAINT_PRFALL_SMOOTH = 1, /* smooth, linear falloff */
+ MOD_DPAINT_PRFALL_RAMP = 2, /* use color ramp */
+};
/* wave_brush_type */
-#define MOD_DPAINT_WAVEB_DEPTH 0 /* use intersection depth */
-#define MOD_DPAINT_WAVEB_FORCE 1 /* act as a force on intersection area */
-#define MOD_DPAINT_WAVEB_REFLECT 2 /* obstacle that reflects waves */
-#define MOD_DPAINT_WAVEB_CHANGE 3 /* use change of intersection depth from previous frame */
+enum {
+ MOD_DPAINT_WAVEB_DEPTH = 0, /* use intersection depth */
+ MOD_DPAINT_WAVEB_FORCE = 1, /* act as a force on intersection area */
+ MOD_DPAINT_WAVEB_REFLECT = 2, /* obstacle that reflects waves */
+ MOD_DPAINT_WAVEB_CHANGE = 3, /* use change of intersection depth from previous frame */
+};
/* brush ray_dir */
-#define MOD_DPAINT_RAY_CANVAS 0
-#define MOD_DPAINT_RAY_BRUSH_AVG 1
-#define MOD_DPAINT_RAY_ZPLUS 2
-
+enum {
+ MOD_DPAINT_RAY_CANVAS = 0,
+ MOD_DPAINT_RAY_BRUSH_AVG = 1,
+ MOD_DPAINT_RAY_ZPLUS = 2,
+};
/* Brush settings */
typedef struct DynamicPaintBrushSettings {
diff --git a/source/blender/makesdna/DNA_fileglobal_types.h b/source/blender/makesdna/DNA_fileglobal_types.h
index 040b55d9eb6..fc7959c0043 100644
--- a/source/blender/makesdna/DNA_fileglobal_types.h
+++ b/source/blender/makesdna/DNA_fileglobal_types.h
@@ -41,9 +41,9 @@ struct Scene;
*/
typedef struct FileGlobal {
char subvstr[4]; /* needs to be here, for human fileformat recognition */
- short subversion, pads;
+ short subversion;
short minversion, minsubversion;
- short displaymode, winpos;
+ char pad[6];
struct bScreen *curscreen;
struct Scene *curscene;
int fileflags;
diff --git a/source/blender/makesdna/DNA_freestyle_types.h b/source/blender/makesdna/DNA_freestyle_types.h
index 195c7eb4841..2359d1e9738 100644
--- a/source/blender/makesdna/DNA_freestyle_types.h
+++ b/source/blender/makesdna/DNA_freestyle_types.h
@@ -44,59 +44,74 @@ struct Group;
struct Text;
/* FreestyleConfig::flags */
-#define FREESTYLE_SUGGESTIVE_CONTOURS_FLAG (1 << 0)
-#define FREESTYLE_RIDGES_AND_VALLEYS_FLAG (1 << 1)
-#define FREESTYLE_MATERIAL_BOUNDARIES_FLAG (1 << 2)
-#define FREESTYLE_FACE_SMOOTHNESS_FLAG (1 << 3)
-#define FREESTYLE_ADVANCED_OPTIONS_FLAG (1 << 4)
-#define FREESTYLE_CULLING (1 << 5)
+enum {
+ FREESTYLE_SUGGESTIVE_CONTOURS_FLAG = 1 << 0,
+ FREESTYLE_RIDGES_AND_VALLEYS_FLAG = 1 << 1,
+ FREESTYLE_MATERIAL_BOUNDARIES_FLAG = 1 << 2,
+ FREESTYLE_FACE_SMOOTHNESS_FLAG = 1 << 3,
+ FREESTYLE_ADVANCED_OPTIONS_FLAG = 1 << 4,
+ FREESTYLE_CULLING = 1 << 5,
+ FREESTYLE_VIEW_MAP_CACHE = 1 << 6,
+};
/* FreestyleConfig::mode */
-#define FREESTYLE_CONTROL_SCRIPT_MODE 1
-#define FREESTYLE_CONTROL_EDITOR_MODE 2
+enum {
+ FREESTYLE_CONTROL_SCRIPT_MODE = 1,
+ FREESTYLE_CONTROL_EDITOR_MODE = 2,
+};
/* FreestyleLineSet::flags */
-#define FREESTYLE_LINESET_CURRENT (1 << 0)
-#define FREESTYLE_LINESET_ENABLED (1 << 1)
-#define FREESTYLE_LINESET_FE_NOT (1 << 2)
-#define FREESTYLE_LINESET_FE_AND (1 << 3)
-#define FREESTYLE_LINESET_GR_NOT (1 << 4)
-#define FREESTYLE_LINESET_FM_NOT (1 << 5)
-#define FREESTYLE_LINESET_FM_BOTH (1 << 6)
+enum {
+ FREESTYLE_LINESET_CURRENT = 1 << 0,
+ FREESTYLE_LINESET_ENABLED = 1 << 1,
+ FREESTYLE_LINESET_FE_NOT = 1 << 2,
+ FREESTYLE_LINESET_FE_AND = 1 << 3,
+ FREESTYLE_LINESET_GR_NOT = 1 << 4,
+ FREESTYLE_LINESET_FM_NOT = 1 << 5,
+ FREESTYLE_LINESET_FM_BOTH = 1 << 6,
+};
/* FreestyleLineSet::selection */
-#define FREESTYLE_SEL_VISIBILITY (1 << 0)
-#define FREESTYLE_SEL_EDGE_TYPES (1 << 1)
-#define FREESTYLE_SEL_GROUP (1 << 2)
-#define FREESTYLE_SEL_IMAGE_BORDER (1 << 3)
-#define FREESTYLE_SEL_FACE_MARK (1 << 4)
+enum {
+ FREESTYLE_SEL_VISIBILITY = 1 << 0,
+ FREESTYLE_SEL_EDGE_TYPES = 1 << 1,
+ FREESTYLE_SEL_GROUP = 1 << 2,
+ FREESTYLE_SEL_IMAGE_BORDER = 1 << 3,
+ FREESTYLE_SEL_FACE_MARK = 1 << 4,
+};
/* FreestyleLineSet::edge_types, exclude_edge_types */
-#define FREESTYLE_FE_SILHOUETTE (1 << 0)
-#define FREESTYLE_FE_BORDER (1 << 1)
-#define FREESTYLE_FE_CREASE (1 << 2)
-#define FREESTYLE_FE_RIDGE_VALLEY (1 << 3)
-/* Note: FREESTYLE_FE_VALLEY = (1 << 4) is no longer used */
-#define FREESTYLE_FE_SUGGESTIVE_CONTOUR (1 << 5)
-#define FREESTYLE_FE_MATERIAL_BOUNDARY (1 << 6)
-#define FREESTYLE_FE_CONTOUR (1 << 7)
-#define FREESTYLE_FE_EXTERNAL_CONTOUR (1 << 8)
-#define FREESTYLE_FE_EDGE_MARK (1 << 9)
+enum {
+ FREESTYLE_FE_SILHOUETTE = 1 << 0,
+ FREESTYLE_FE_BORDER = 1 << 1,
+ FREESTYLE_FE_CREASE = 1 << 2,
+ FREESTYLE_FE_RIDGE_VALLEY = 1 << 3,
+ /* FREESTYLE_FE_VALLEY = 1 << 4, */ /* No longer used */
+ FREESTYLE_FE_SUGGESTIVE_CONTOUR = 1 << 5,
+ FREESTYLE_FE_MATERIAL_BOUNDARY = 1 << 6,
+ FREESTYLE_FE_CONTOUR = 1 << 7,
+ FREESTYLE_FE_EXTERNAL_CONTOUR = 1 << 8,
+ FREESTYLE_FE_EDGE_MARK = 1 << 9,
+};
/* FreestyleLineSet::qi */
-#define FREESTYLE_QI_VISIBLE 1
-#define FREESTYLE_QI_HIDDEN 2
-#define FREESTYLE_QI_RANGE 3
+enum {
+ FREESTYLE_QI_VISIBLE = 1,
+ FREESTYLE_QI_HIDDEN = 2,
+ FREESTYLE_QI_RANGE = 3,
+};
/* FreestyleConfig::raycasting_algorithm */
/* Defines should be replaced with ViewMapBuilder::visibility_algo */
-#define FREESTYLE_ALGO_REGULAR 1
-#define FREESTYLE_ALGO_FAST 2
-#define FREESTYLE_ALGO_VERYFAST 3
-#define FREESTYLE_ALGO_CULLED_ADAPTIVE_TRADITIONAL 4
-#define FREESTYLE_ALGO_ADAPTIVE_TRADITIONAL 5
-#define FREESTYLE_ALGO_CULLED_ADAPTIVE_CUMULATIVE 6
-#define FREESTYLE_ALGO_ADAPTIVE_CUMULATIVE 7
+enum {
+ FREESTYLE_ALGO_REGULAR = 1,
+ FREESTYLE_ALGO_FAST = 2,
+ FREESTYLE_ALGO_VERYFAST = 3,
+ FREESTYLE_ALGO_CULLED_ADAPTIVE_TRADITIONAL = 4,
+ FREESTYLE_ALGO_ADAPTIVE_TRADITIONAL = 5,
+ FREESTYLE_ALGO_CULLED_ADAPTIVE_CUMULATIVE = 6,
+ FREESTYLE_ALGO_ADAPTIVE_CUMULATIVE = 7,
+};
typedef struct FreestyleLineSet {
struct FreestyleLineSet *next, *prev;
diff --git a/source/blender/makesdna/DNA_gpencil_types.h b/source/blender/makesdna/DNA_gpencil_types.h
index 2bf874d3a85..beffbc4c017 100644
--- a/source/blender/makesdna/DNA_gpencil_types.h
+++ b/source/blender/makesdna/DNA_gpencil_types.h
@@ -33,6 +33,9 @@
#include "DNA_listBase.h"
#include "DNA_ID.h"
+struct AnimData;
+
+
/* Grease-Pencil Annotations - 'Stroke Point'
* -> Coordinates may either be 2d or 3d depending on settings at the time
* -> Coordinates of point on stroke, in proportions of window size
@@ -42,8 +45,15 @@ typedef struct bGPDspoint {
float x, y, z; /* co-ordinates of point (usually 2d, but can be 3d as well) */
float pressure; /* pressure of input device (from 0 to 1) at this point */
float time; /* seconds since start of stroke */
+ int flag; /* additional options (NOTE: can shrink this field down later if needed) */
} bGPDspoint;
+/* bGPDspoint->flag */
+typedef enum eGPDspoint_Flag {
+ /* stroke point is selected (for editing) */
+ GP_SPOINT_SELECT = (1 << 0)
+} eGPSPoint_Flag;
+
/* Grease-Pencil Annotations - 'Stroke'
* -> A stroke represents a (simplified version) of the curve
* drawn by the user in one 'mousedown'->'mouseup' operation
@@ -61,15 +71,18 @@ typedef struct bGPDstroke {
} bGPDstroke;
/* bGPDstroke->flag */
+typedef enum eGPDstroke_Flag {
/* stroke is in 3d-space */
-#define GP_STROKE_3DSPACE (1<<0)
+ GP_STROKE_3DSPACE = (1 << 0),
/* stroke is in 2d-space */
-#define GP_STROKE_2DSPACE (1<<1)
+ GP_STROKE_2DSPACE = (1 << 1),
/* stroke is in 2d-space (but with special 'image' scaling) */
-#define GP_STROKE_2DIMAGE (1<<2)
+ GP_STROKE_2DIMAGE = (1 << 2),
+ /* stroke is selected */
+ GP_STROKE_SELECT = (1 << 3),
/* only for use with stroke-buffer (while drawing eraser) */
-#define GP_STROKE_ERASER (1<<15)
-
+ GP_STROKE_ERASER = (1 << 15)
+} eGPDstroke_Flag;
/* Grease-Pencil Annotations - 'Frame'
* -> Acts as storage for the 'image' formed by strokes
@@ -80,15 +93,18 @@ typedef struct bGPDframe {
ListBase strokes; /* list of the simplified 'strokes' that make up the frame's data */
int framenum; /* frame number of this frame */
- int flag; /* temp settings */
+
+ short flag; /* temp settings */
+ short key_type; /* keyframe type (eBezTriple_KeyframeType) */
} bGPDframe;
-/* bGPDframe->flag */
+/* bGPDframe->flag */
+typedef enum eGPDframe_Flag {
/* frame is being painted on */
-#define GP_FRAME_PAINT (1<<0)
+ GP_FRAME_PAINT = (1 << 0),
/* for editing in Action Editor */
-#define GP_FRAME_SELECT (1<<1)
-
+ GP_FRAME_SELECT = (1 << 1)
+} eGPDframe_Flag;
/* Grease-Pencil Annotations - 'Layer' */
typedef struct bGPDlayer {
@@ -97,38 +113,52 @@ typedef struct bGPDlayer {
ListBase frames; /* list of annotations to display for frames (bGPDframe list) */
bGPDframe *actframe; /* active frame (should be the frame that is currently being displayed) */
- int flag; /* settings for layer */
+ short flag; /* settings for layer */
short thickness; /* current thickness to apply to strokes */
- short gstep; /* max number of frames between active and ghost to show (0=only those on either side) */
+
+ short gstep; /* Ghosts Before: max number of ghost frames to show between active frame and the one before it (0 = only the ghost itself) */
+ short gstep_next; /* Ghosts After: max number of ghost frames to show after active frame and the following it (0 = only the ghost itself) */
+
+ float gcolor_prev[3]; /* optional color for ghosts before the active frame */
+ float gcolor_next[3]; /* optional color for ghosts after the active frame */
float color[4]; /* color that should be used to draw all the strokes in this layer */
+ float fill[4]; /* color that should be used for drawing "fills" for strokes */
char info[128]; /* optional reference info about this layer (i.e. "director's comments, 12/3")
* this is used for the name of the layer too and kept unique. */
} bGPDlayer;
/* bGPDlayer->flag */
+typedef enum eGPDlayer_Flag {
/* don't display layer */
-#define GP_LAYER_HIDE (1<<0)
+ GP_LAYER_HIDE = (1 << 0),
/* protected from further editing */
-#define GP_LAYER_LOCKED (1<<1)
+ GP_LAYER_LOCKED = (1 << 1),
/* layer is 'active' layer being edited */
-#define GP_LAYER_ACTIVE (1<<2)
+ GP_LAYER_ACTIVE = (1 << 2),
/* draw points of stroke for debugging purposes */
-#define GP_LAYER_DRAWDEBUG (1<<3)
- /* do onionskinning */
-#define GP_LAYER_ONIONSKIN (1<<4)
+ GP_LAYER_DRAWDEBUG = (1 << 3),
+ /* do onion skinning */
+ GP_LAYER_ONIONSKIN = (1 << 4),
/* for editing in Action Editor */
-#define GP_LAYER_SELECT (1<<5)
+ GP_LAYER_SELECT = (1 << 5),
/* current frame for layer can't be changed */
-#define GP_LAYER_FRAMELOCK (1<<6)
+ GP_LAYER_FRAMELOCK = (1 << 6),
/* don't render xray (which is default) */
-#define GP_LAYER_NO_XRAY (1<<7)
-
+ GP_LAYER_NO_XRAY = (1 << 7),
+ /* use custom color for ghosts before current frame */
+ GP_LAYER_GHOST_PREVCOL = (1 << 8),
+ /* use custom color for ghosts after current frame */
+ GP_LAYER_GHOST_NEXTCOL = (1 << 9),
+ /* "volumetric" strokes (i.e. GLU Quadric discs in 3D) */
+ GP_LAYER_VOLUMETRIC = (1 << 10),
+} eGPDlayer_Flag;
/* Grease-Pencil Annotations - 'DataBlock' */
typedef struct bGPdata {
- ID id; /* Grease Pencil data is */
+ ID id; /* Grease Pencil data is a datablock */
+ struct AnimData *adt; /* animation data - for animating draw settings */
/* saved Grease-Pencil data */
ListBase layers; /* bGPDlayers */
@@ -144,23 +174,33 @@ typedef struct bGPdata {
} bGPdata;
/* bGPdata->flag */
-// XXX many of these flags should be deprecated for more general ideas in 2.5
+/* NOTE: A few flags have been deprecated since early 2.5,
+ * since they have been made redundant by interaction
+ * changes made during the porting process.
+ */
+typedef enum eGPdata_Flag {
/* don't allow painting to occur at all */
- // XXX is deprecated - not well understood
-// #define GP_DATA_LMBPLOCK (1<<0)
+ /* GP_DATA_LMBPLOCK = (1 << 0), */
+
/* show debugging info in viewport (i.e. status print) */
-#define GP_DATA_DISPINFO (1<<1)
+ GP_DATA_DISPINFO = (1 << 1),
/* in Action Editor, show as expanded channel */
-#define GP_DATA_EXPAND (1<<2)
+ GP_DATA_EXPAND = (1 << 2),
+
/* is the block overriding all clicks? */
- // XXX is deprecated - nasty old concept
-// #define GP_DATA_EDITPAINT (1<<3)
+ /* GP_DATA_EDITPAINT = (1 << 3), */
+
/* new strokes are added in viewport space */
-#define GP_DATA_VIEWALIGN (1<<4)
- /* Project into the screens Z values */
-#define GP_DATA_DEPTH_VIEW (1<<5)
-#define GP_DATA_DEPTH_STROKE (1<<6)
+ GP_DATA_VIEWALIGN = (1 << 4),
+
+ /* Project into the screen's Z values */
+ GP_DATA_DEPTH_VIEW = (1 << 5),
+ GP_DATA_DEPTH_STROKE = (1 << 6),
-#define GP_DATA_DEPTH_STROKE_ENDPOINTS (1<<7)
+ GP_DATA_DEPTH_STROKE_ENDPOINTS = (1 << 7),
+
+ /* Stroke Editing Mode - Toggle to enable alternative keymap for easier editing of stroke points */
+ GP_DATA_STROKE_EDITMODE = (1 << 8)
+} eGPdata_Flag;
#endif /* __DNA_GPENCIL_TYPES_H__ */
diff --git a/source/blender/makesdna/DNA_gpu_types.h b/source/blender/makesdna/DNA_gpu_types.h
new file mode 100644
index 00000000000..967cb7284dc
--- /dev/null
+++ b/source/blender/makesdna/DNA_gpu_types.h
@@ -0,0 +1,68 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file DNA_gpu_types.h
+ * \ingroup DNA
+ */
+
+#ifndef __DNA_GPU_TYPES_H__
+#define __DNA_GPU_TYPES_H__
+
+/* properties for dof effect */
+typedef struct GPUDOFSettings {
+ float focus_distance; /* focal distance for depth of field */
+ float fstop;
+ float focal_length;
+ float sensor;
+ int num_blades;
+ int high_quality;
+} GPUDOFSettings;
+
+/* properties for SSAO effect */
+typedef struct GPUSSAOSettings {
+ float factor;
+ float color[3];
+ float distance_max;
+ float attenuation;
+ int samples; /* ray samples, we use presets here for easy control instead of */
+ int pad;
+} GPUSSAOSettings;
+
+typedef struct GPUFXSettings {
+ GPUDOFSettings *dof;
+ GPUSSAOSettings *ssao;
+ char fx_flag; /* eGPUFXFlags */
+ char pad[7];
+} GPUFXSettings;
+
+/* shaderfx enables */
+typedef enum eGPUFXFlags {
+ GPU_FX_FLAG_DOF = (1 << 0),
+ GPU_FX_FLAG_SSAO = (1 << 1),
+} eGPUFXFlags;
+
+#endif /* __DNA_GPU_TYPES_H__ */
diff --git a/source/blender/makesdna/DNA_group_types.h b/source/blender/makesdna/DNA_group_types.h
index 2740281b4c0..45dd0cb9ff2 100644
--- a/source/blender/makesdna/DNA_group_types.h
+++ b/source/blender/makesdna/DNA_group_types.h
@@ -52,7 +52,9 @@ typedef struct Group {
ID id;
ListBase gobject; /* GroupObject */
-
+
+ struct PreviewImage *preview;
+
/* Bad design, since layers stored in the scenes 'Base'
* the objects that show in the group can change depending
* on the last used scene */
diff --git a/source/blender/makesdna/DNA_image_types.h b/source/blender/makesdna/DNA_image_types.h
index 0b9dddd0ea5..56a8842a8d2 100644
--- a/source/blender/makesdna/DNA_image_types.h
+++ b/source/blender/makesdna/DNA_image_types.h
@@ -39,12 +39,10 @@
struct PackedFile;
struct Scene;
struct anim;
-struct ImBuf;
struct MovieCache;
struct RenderResult;
struct GPUTexture;
-
/* ImageUser is in Texture, in Nodes, Background Image, Image Window, .... */
/* should be used in conjunction with an ID * to Image. */
typedef struct ImageUser {
@@ -54,21 +52,43 @@ typedef struct ImageUser {
int frames; /* total amount of frames to use */
int offset, sfra; /* offset within movie, start frame in global time */
char fie_ima, cycl; /* fields/image in movie, cyclic flag */
- char ok, pad;
+ char ok;
- short multi_index, layer, pass; /* listbase indices, for menu browsing or retrieve buffer */
+ char multiview_eye; /* multiview current eye - for internal use of drawing routines */
+ short pass;
+ short pad;
+ short multi_index, view, layer; /* listbase indices, for menu browsing or retrieve buffer */
short flag;
-
- int pad2;
-
} ImageUser;
+typedef struct ImageAnim {
+ struct ImageAnim *next, *prev;
+ struct anim *anim;
+} ImageAnim;
+
+typedef struct ImageView {
+ struct ImageView *next, *prev;
+ char name[64]; /* MAX_NAME */
+ char filepath[1024]; /* 1024 = FILE_MAX */
+} ImageView;
+
+typedef struct ImagePackedFile {
+ struct ImagePackedFile *next, *prev;
+ struct PackedFile *packedfile;
+ char filepath[1024]; /* 1024 = FILE_MAX */
+} ImagePackedFile;
+
+typedef struct RenderSlot {
+ char name[64]; /* 64 = MAX_NAME */
+} RenderSlot;
+
/* iuser->flag */
#define IMA_ANIM_ALWAYS 1
#define IMA_ANIM_REFRESHED 2
/* #define IMA_DO_PREMUL 4 */
#define IMA_NEED_FRAME_RECALC 8
+#define IMA_SHOW_STEREO 16
typedef struct Image {
ID id;
@@ -79,13 +99,13 @@ typedef struct Image {
struct GPUTexture *gputexture; /* not written in file */
/* sources from: */
- struct anim *anim;
+ ListBase anims;
struct RenderResult *rr;
struct RenderResult *renders[8]; /* IMA_MAX_RENDER_SLOT */
short render_slot, last_render_slot;
-
- short ok, flag;
+
+ int flag;
short source, type;
int lastframe;
@@ -96,19 +116,22 @@ typedef struct Image {
unsigned int bindcode; /* only for current image... */
unsigned int *repbind; /* for repeat of parts of images */
- struct PackedFile *packedfile;
+ struct PackedFile *packedfile DNA_DEPRECATED; /* deprecated */
+ struct ListBase packedfiles;
struct PreviewImage *preview;
/* game engine tile animation */
float lastupdate;
int lastused;
short animspeed;
- short pad2;
+
+ short ok;
/* for generated images */
int gen_x, gen_y;
char gen_type, gen_flag;
short gen_depth;
+ float gen_color[4];
/* display aspect - for UV editing images resized for faster openGL display */
float aspx, aspy;
@@ -117,7 +140,15 @@ typedef struct Image {
ColorManagedColorspaceSettings colorspace_settings;
char alpha_mode;
- char pad[7];
+ char pad[5];
+
+ /* Multiview */
+ char eye; /* for viewer node stereoscopy */
+ char views_format;
+ ListBase views;
+ struct Stereo3dFormat *stereo3d_format;
+
+ RenderSlot render_slots[8]; /* 8 = IMA_MAX_RENDER_SLOT */
} Image;
@@ -127,7 +158,9 @@ typedef struct Image {
enum {
IMA_FIELDS = (1 << 0),
IMA_STD_FIELD = (1 << 1),
+#ifdef DNA_DEPRECATED
IMA_DO_PREMUL = (1 << 2), /* deprecated, should not be used */
+#endif
IMA_REFLECT = (1 << 4),
IMA_NOCOLLECT = (1 << 5),
//IMA_DONE_TAG = (1 << 6), // UNUSED
@@ -137,12 +170,12 @@ enum {
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),
+ IMA_DEINTERLACE = (1 << 13),
+ IMA_USE_VIEWS = (1 << 14),
+ IMA_IS_STEREO = (1 << 15),
+ IMA_IS_MULTIVIEW = (1 << 16), /* similar to stereo, but a more general case */
};
-#if (DNA_DEPRECATED_GCC_POISON == 1)
-#pragma GCC poison IMA_DO_PREMUL
-#endif
-
/* Image.tpageflag */
#define IMA_TILES 1
#define IMA_TWINANIM 2
diff --git a/source/blender/makesdna/DNA_key_types.h b/source/blender/makesdna/DNA_key_types.h
index f5ce3c8d8c1..60ab01c901b 100644
--- a/source/blender/makesdna/DNA_key_types.h
+++ b/source/blender/makesdna/DNA_key_types.h
@@ -91,10 +91,10 @@ typedef struct Key {
ID *from;
- short type; /* absolute or relative shape key */
- short totkey; /* (totkey == BLI_countlist(&key->block)) */
- short slurph; /* quaint feature to delay moving points based on their order (Key->type == KEY_NORMAL) only */
+ int totkey; /* (totkey == BLI_listbase_count(&key->block)) */
short flag;
+ char type; /* absolute or relative shape key */
+ char pad2;
/* only used when (Key->type == KEY_NORMAL), this value is used as a time slider,
* rather then using the scenes time, this value can be animated to give greater control */
diff --git a/source/blender/makesdna/DNA_lamp_types.h b/source/blender/makesdna/DNA_lamp_types.h
index b7aae005e3b..ce8e86cb512 100644
--- a/source/blender/makesdna/DNA_lamp_types.h
+++ b/source/blender/makesdna/DNA_lamp_types.h
@@ -131,26 +131,27 @@ typedef struct Lamp {
#define LA_YF_PHOTON 5
/* mode */
-#define LA_SHAD_BUF 1
-#define LA_HALO 2
-#define LA_LAYER 4
-#define LA_QUAD 8 /* no longer used */
-#define LA_NEG 16
-#define LA_ONLYSHADOW 32
-#define LA_SPHERE 64
-#define LA_SQUARE 128
-#define LA_TEXTURE 256
-#define LA_OSATEX 512
-/* #define LA_DEEP_SHADOW 1024 */ /* not used anywhere */
-#define LA_NO_DIFF 2048
-#define LA_NO_SPEC 4096
-#define LA_SHAD_RAY 8192
+#define LA_SHAD_BUF (1 << 0)
+#define LA_HALO (1 << 1)
+#define LA_LAYER (1 << 2)
+#define LA_QUAD (1 << 3) /* no longer used */
+#define LA_NEG (1 << 4)
+#define LA_ONLYSHADOW (1 << 5)
+#define LA_SPHERE (1 << 6)
+#define LA_SQUARE (1 << 7)
+#define LA_TEXTURE (1 << 8)
+#define LA_OSATEX (1 << 9)
+/* #define LA_DEEP_SHADOW (1 << 10) */ /* not used anywhere */
+#define LA_NO_DIFF (1 << 11)
+#define LA_NO_SPEC (1 << 12)
+#define LA_SHAD_RAY (1 << 13)
/* yafray: lamp shadowbuffer flag, softlight */
/* Since it is used with LOCAL lamp, can't use LA_SHAD */
-/* #define LA_YF_SOFT 16384 */ /* no longer used */
-#define LA_LAYER_SHADOW 32768
-#define LA_SHAD_TEX (1<<16)
-#define LA_SHOW_CONE (1<<17)
+/* #define LA_YF_SOFT (1 << 14) */ /* no longer used */
+#define LA_LAYER_SHADOW (1 << 15)
+#define LA_SHAD_TEX (1 << 16)
+#define LA_SHOW_CONE (1 << 17)
+#define LA_SHOW_SHADOW_BOX (1 << 18)
/* layer_shadow */
#define LA_LAYER_SHADOW_BOTH 0
diff --git a/source/blender/makesdna/DNA_linestyle_types.h b/source/blender/makesdna/DNA_linestyle_types.h
index bac03b4efd7..f9b9f8a4641 100644
--- a/source/blender/makesdna/DNA_linestyle_types.h
+++ b/source/blender/makesdna/DNA_linestyle_types.h
@@ -57,7 +57,6 @@ typedef struct LineStyleModifier {
float influence;
int flags;
int blend;
-
} LineStyleModifier;
/* LineStyleModifier::type */
@@ -79,7 +78,12 @@ typedef struct LineStyleModifier {
#define LS_MODIFIER_BLUEPRINT 16
#define LS_MODIFIER_2D_OFFSET 17
#define LS_MODIFIER_2D_TRANSFORM 18
-#define LS_MODIFIER_NUM 19
+#define LS_MODIFIER_TANGENT 19
+#define LS_MODIFIER_NOISE 20
+#define LS_MODIFIER_CREASE_ANGLE 21
+#define LS_MODIFIER_SIMPLIFICATION 22
+#define LS_MODIFIER_CURVATURE_3D 23
+#define LS_MODIFIER_NUM 24
/* LineStyleModifier::flags */
#define LS_MODIFIER_ENABLED 1
@@ -92,6 +96,9 @@ typedef struct LineStyleModifier {
#define LS_MODIFIER_USE_CURVE 1
#define LS_MODIFIER_INVERT 2
+/* flags (for asymmetric thickness application) */
+#define LS_THICKNESS_ASYMMETRIC 1
+
/* blend (for alpha & thickness) */
#define LS_VALUE_BLEND 0
#define LS_VALUE_ADD 1
@@ -186,6 +193,113 @@ typedef struct LineStyleThicknessModifier_DistanceFromObject {
int pad;
} LineStyleThicknessModifier_DistanceFromObject;
+/* 3D curvature modifiers */
+
+typedef struct LineStyleColorModifier_Curvature_3D {
+ struct LineStyleModifier modifier;
+
+ float min_curvature, max_curvature;
+ struct ColorBand *color_ramp;
+ float range_min, range_max;
+} LineStyleColorModifier_Curvature_3D;
+
+typedef struct LineStyleAlphaModifier_Curvature_3D {
+ struct LineStyleModifier modifier;
+
+ struct CurveMapping *curve;
+ int flags;
+ float min_curvature, max_curvature;
+ int pad;
+} LineStyleAlphaModifier_Curvature_3D;
+
+typedef struct LineStyleThicknessModifier_Curvature_3D {
+ struct LineStyleModifier modifier;
+
+ struct CurveMapping *curve;
+ int flags, pad;
+ float min_curvature, max_curvature;
+ float min_thickness, max_thickness;
+} LineStyleThicknessModifier_Curvature_3D;
+
+/* Noise modifiers (for color, alpha and thickness) */
+
+typedef struct LineStyleColorModifier_Noise {
+ struct LineStyleModifier modifier;
+
+ struct ColorBand *color_ramp;
+ float period, amplitude;
+ int seed, pad;
+} LineStyleColorModifier_Noise;
+
+typedef struct LineStyleAlphaModifier_Noise {
+ struct LineStyleModifier modifier;
+
+ struct CurveMapping *curve;
+ int flags;
+ float period, amplitude;
+ int seed;
+} LineStyleAlphaModifier_Noise;
+
+typedef struct LineStyleThicknessModifier_Noise {
+ struct LineStyleModifier modifier;
+
+ float period, amplitude;
+ int flags;
+ int seed;
+} LineStyleThicknessModifier_Noise;
+
+/* Crease Angle modifiers */
+
+typedef struct LineStyleColorModifier_CreaseAngle {
+ struct LineStyleModifier modifier;
+
+ struct ColorBand *color_ramp;
+ float min_angle, max_angle;
+} LineStyleColorModifier_CreaseAngle;
+
+typedef struct LineStyleAlphaModifier_CreaseAngle {
+ struct LineStyleModifier modifier;
+
+ struct CurveMapping *curve;
+ int flags;
+ float min_angle, max_angle;
+ int pad;
+} LineStyleAlphaModifier_CreaseAngle;
+
+typedef struct LineStyleThicknessModifier_CreaseAngle {
+ struct LineStyleModifier modifier;
+
+ struct CurveMapping *curve;
+ int flags, pad;
+ float min_angle, max_angle;
+ float min_thickness, max_thickness;
+} LineStyleThicknessModifier_CreaseAngle;
+
+/* Tangent modifiers */
+
+typedef struct LineStyleColorModifier_Tangent {
+ struct LineStyleModifier modifier;
+
+ struct ColorBand *color_ramp;
+} LineStyleColorModifier_Tangent;
+
+typedef struct LineStyleAlphaModifier_Tangent {
+ struct LineStyleModifier modifier;
+
+ struct CurveMapping *curve;
+ int flags;
+ int pad;
+} LineStyleAlphaModifier_Tangent;
+
+typedef struct LineStyleThicknessModifier_Tangent {
+ struct LineStyleModifier modifier;
+
+ struct CurveMapping *curve;
+ int flags;
+ float min_thickness, max_thickness;
+ int pad;
+} LineStyleThicknessModifier_Tangent;
+
/* Material modifiers */
/* mat_attr */
@@ -203,6 +317,7 @@ typedef struct LineStyleThicknessModifier_DistanceFromObject {
#define LS_MODIFIER_MATERIAL_LINE_R 12
#define LS_MODIFIER_MATERIAL_LINE_G 13
#define LS_MODIFIER_MATERIAL_LINE_B 14
+#define LS_MODIFIER_MATERIAL_LINE_A 15
typedef struct LineStyleColorModifier_Material {
struct LineStyleModifier modifier;
@@ -353,6 +468,13 @@ typedef struct LineStyleGeometryModifier_2DTransform {
int pad;
} LineStyleGeometryModifier_2DTransform;
+typedef struct LineStyleGeometryModifier_Simplification {
+ struct LineStyleModifier modifier;
+
+ float tolerance;
+ int pad;
+}LineStyleGeometryModifier_Simplification;
+
/* Calligraphic thickness modifier */
typedef struct LineStyleThicknessModifier_Calligraphy {
@@ -387,6 +509,7 @@ typedef struct LineStyleThicknessModifier_Calligraphy {
#define LS_NO_SORTING (1 << 11)
#define LS_REVERSE_ORDER (1 << 12) /* for sorting */
#define LS_TEXTURE (1 << 13)
+#define LS_CHAIN_COUNT (1 << 14)
/* FreestyleLineStyle::chaining */
#define LS_CHAINING_PLAIN 1
@@ -406,6 +529,8 @@ typedef struct LineStyleThicknessModifier_Calligraphy {
/* FreestyleLineStyle::sort_key */
#define LS_SORT_KEY_DISTANCE_FROM_CAMERA 1
#define LS_SORT_KEY_2D_LENGTH 2
+#define LS_SORT_KEY_PROJECTED_X 3
+#define LS_SORT_KEY_PROJECTED_Y 4
/* FreestyleLineStyle::integration_type */
#define LS_INTEGRATION_MEAN 1
@@ -428,17 +553,17 @@ typedef struct FreestyleLineStyle {
float split_length;
float min_angle, max_angle; /* in radians, for splitting */
float min_length, max_length;
+ unsigned int chain_count;
unsigned short split_dash1, split_gap1;
unsigned short split_dash2, split_gap2;
unsigned short split_dash3, split_gap3;
int sort_key, integration_type;
float texstep;
short texact, pr_texture;
- short use_nodes, pad;
+ short use_nodes, pad[3];
unsigned short dash1, gap1, dash2, gap2, dash3, gap3;
int panel; /* for UI */
-
- struct MTex *mtex[18]; /* MAX_MTEX */
+ struct MTex *mtex[18]; /* MAX_MTEX */
/* nodes */
struct bNodeTree *nodetree;
diff --git a/source/blender/makesdna/DNA_material_types.h b/source/blender/makesdna/DNA_material_types.h
index 3f94a9cfebb..8790f736600 100644
--- a/source/blender/makesdna/DNA_material_types.h
+++ b/source/blender/makesdna/DNA_material_types.h
@@ -210,6 +210,7 @@ typedef struct Material {
#define GEMAT_ALPHA 2 /* GPU_BLEND_ALPHA */
#define GEMAT_CLIP 4 /* GPU_BLEND_CLIP */
#define GEMAT_ALPHA_SORT 8 /* GPU_BLEND_ALPHA_SORT */
+#define GEMAT_ALPHA_TO_COVERAGE 16 /* GPU_BLEND_ALPHA_TO_COVERAGE */
// Game Options - flag
#define GEMAT_BACKCULL 16 /* KX_BACKCULL */
@@ -438,6 +439,7 @@ typedef struct Material {
#define MAP_PA_CLUMP 128
#define MAP_PA_KINK 256
#define MAP_PA_ROUGH 512
+#define MAP_PA_FREQ 1024
/* pr_type */
#define MA_FLAT 0
diff --git a/source/blender/makesdna/DNA_mesh_types.h b/source/blender/makesdna/DNA_mesh_types.h
index e535e6012b3..39e56925903 100644
--- a/source/blender/makesdna/DNA_mesh_types.h
+++ b/source/blender/makesdna/DNA_mesh_types.h
@@ -37,7 +37,6 @@
#include "DNA_customdata_types.h"
struct AnimData;
-struct DerivedMesh;
struct Ipo;
struct Key;
struct MCol;
@@ -47,13 +46,11 @@ struct MLoop;
struct MLoopCol;
struct MLoopUV;
struct MPoly;
-struct MSticky;
struct MTexPoly;
struct MVert;
struct Material;
struct Mesh;
struct Multires;
-struct OcInfo;
typedef struct Mesh {
ID id;
@@ -133,6 +130,7 @@ typedef struct Mesh {
} Mesh;
/* deprecated by MTFace, only here for file reading */
+#ifdef DNA_DEPRECATED
typedef struct TFace {
void *tpage; /* the faces image for the active UVLayer */
float uv[4][2];
@@ -140,24 +138,25 @@ typedef struct TFace {
char flag, transp;
short mode, tile, unwrap;
} TFace;
-
-#if (DNA_DEPRECATED_GCC_POISON == 1)
-#pragma GCC poison TFace
#endif
/* **************** MESH ********************* */
/* texflag */
-#define ME_AUTOSPACE 1
+enum {
+ ME_AUTOSPACE = 1,
+};
/* me->editflag */
-#define ME_EDIT_MIRROR_X (1 << 0)
-#define ME_EDIT_MIRROR_Y (1 << 1) // unused so far
-#define ME_EDIT_MIRROR_Z (1 << 2) // unused so far
+enum {
+ ME_EDIT_MIRROR_X = 1 << 0,
+ ME_EDIT_MIRROR_Y = 1 << 1, /* unused so far */
+ ME_EDIT_MIRROR_Z = 1 << 2, /* unused so far */
-#define ME_EDIT_PAINT_FACE_SEL (1 << 3)
-#define ME_EDIT_MIRROR_TOPO (1 << 4)
-#define ME_EDIT_PAINT_VERT_SEL (1 << 5)
+ ME_EDIT_PAINT_FACE_SEL = 1 << 3,
+ ME_EDIT_MIRROR_TOPO = 1 << 4,
+ ME_EDIT_PAINT_VERT_SEL = 1 << 5,
+};
/* we cant have both flags enabled at once,
* flags defined in DNA_scene_types.h */
@@ -168,57 +167,65 @@ typedef struct TFace {
)
/* me->flag */
-/* #define ME_ISDONE 1 */
-/* #define ME_DEPRECATED 2 */
-#define ME_TWOSIDED 4
-#define ME_UVEFFECT 8
-#define ME_VCOLEFFECT 16
-#define ME_AUTOSMOOTH 32
-#define ME_SMESH 64
-#define ME_SUBSURF 128
-#define ME_OPT_EDGES 256
-#define ME_DS_EXPAND 512
-#define ME_SCULPT_DYNAMIC_TOPOLOGY 1024
+enum {
+/* ME_ISDONE = 1 << 0, */
+/* ME_DEPRECATED = 1 << 1, */
+ ME_TWOSIDED = 1 << 2,
+ ME_UVEFFECT = 1 << 3,
+ ME_VCOLEFFECT = 1 << 4,
+ ME_AUTOSMOOTH = 1 << 5,
+ ME_SMESH = 1 << 6,
+ ME_SUBSURF = 1 << 7,
+ ME_OPT_EDGES = 1 << 8,
+ ME_DS_EXPAND = 1 << 9,
+ ME_SCULPT_DYNAMIC_TOPOLOGY = 1 << 10,
+};
/* me->cd_flag */
-#define ME_CDFLAG_VERT_BWEIGHT (1 << 0)
-#define ME_CDFLAG_EDGE_BWEIGHT (1 << 1)
-#define ME_CDFLAG_EDGE_CREASE (1 << 2)
+enum {
+ ME_CDFLAG_VERT_BWEIGHT = 1 << 0,
+ ME_CDFLAG_EDGE_BWEIGHT = 1 << 1,
+ ME_CDFLAG_EDGE_CREASE = 1 << 2,
+};
/* me->drawflag, short */
-#define ME_DRAWEDGES (1 << 0)
-#define ME_DRAWFACES (1 << 1)
-#define ME_DRAWNORMALS (1 << 2)
-#define ME_DRAW_VNORMALS (1 << 3)
+enum {
+ ME_DRAWEDGES = 1 << 0,
+ ME_DRAWFACES = 1 << 1,
+ ME_DRAWNORMALS = 1 << 2,
+ ME_DRAW_VNORMALS = 1 << 3,
-#define ME_DRAWEIGHT (1 << 4)
-#define ME_HIDDENEDGES (1 << 5)
+ ME_DRAWEIGHT = 1 << 4,
+ /* ME_HIDDENEDGES = 1 << 5, */ /* DEPRECATED */
-#define ME_DRAWCREASES (1 << 6)
-#define ME_DRAWSEAMS (1 << 7)
-#define ME_DRAWSHARP (1 << 8)
-#define ME_DRAWBWEIGHTS (1 << 9)
+ ME_DRAWCREASES = 1 << 6,
+ ME_DRAWSEAMS = 1 << 7,
+ ME_DRAWSHARP = 1 << 8,
+ ME_DRAWBWEIGHTS = 1 << 9,
-#define ME_DRAWEXTRA_EDGELEN (1 << 10)
-#define ME_DRAWEXTRA_FACEAREA (1 << 11)
-#define ME_DRAWEXTRA_FACEANG (1 << 12)
-#define ME_DRAWEXTRA_EDGEANG (1 << 13)
+ ME_DRAWEXTRA_EDGELEN = 1 << 10,
+ ME_DRAWEXTRA_FACEAREA = 1 << 11,
+ ME_DRAWEXTRA_FACEANG = 1 << 12,
+ ME_DRAWEXTRA_EDGEANG = 1 << 13,
/* debug only option */
-#define ME_DRAWEXTRA_INDICES (1 << 14)
+ ME_DRAWEXTRA_INDICES = 1 << 14,
-#define ME_DRAW_FREESTYLE_EDGE (1 << 15)
-#define ME_DRAW_FREESTYLE_FACE (1 << 16)
+ ME_DRAW_FREESTYLE_EDGE = 1 << 15,
+ ME_DRAW_FREESTYLE_FACE = 1 << 16,
/* draw stats */
-#define ME_DRAW_STATVIS (1 << 17)
+ ME_DRAW_STATVIS = 1 << 17,
/* draw loop normals */
-#define ME_DRAW_LNORMALS (1 << 18)
+ ME_DRAW_LNORMALS = 1 << 18,
+};
/* Subsurf Type */
-#define ME_CC_SUBSURF 0
-#define ME_SIMPLE_SUBSURF 1
+enum {
+ ME_CC_SUBSURF = 0,
+ ME_SIMPLE_SUBSURF = 1,
+};
#define MESH_MAX_VERTS 2000000000L
@@ -229,6 +236,6 @@ typedef struct TFace {
#define USE_BMESH_SAVE_WITHOUT_MFACE
/* enable this so meshes get tessfaces calculated by default */
-// #define USE_TESSFACE_DEFAULT
+/* #define USE_TESSFACE_DEFAULT */
#endif
diff --git a/source/blender/makesdna/DNA_meshdata_types.h b/source/blender/makesdna/DNA_meshdata_types.h
index 3304980f964..59e6f28804a 100644
--- a/source/blender/makesdna/DNA_meshdata_types.h
+++ b/source/blender/makesdna/DNA_meshdata_types.h
@@ -35,7 +35,6 @@
#include "DNA_customdata_types.h"
#include "DNA_listBase.h"
-struct Bone;
struct Image;
/*tessellation face, see MLoop/MPoly for the real face data*/
@@ -90,6 +89,104 @@ typedef struct MLoop {
unsigned int e; /* edge index */
} MLoop;
+/**
+ * #MLoopTri's are lightweight triangulation data, for functionality that doesn't support ngons (#MPoly).
+ * This is cache data created from (#MPoly, #MLoop & #MVert arrays).
+ * There is no attempt to maintain this data's validity over time, any changes to the underlying mesh
+ * invalidate the #MLoopTri array, which will need to be re-calculated.
+ *
+ * Users normally access this via #DerivedMesh.getLoopTriArray.
+ * In rare cases its calculated directly, with #BKE_mesh_recalc_looptri.
+ *
+ * Typical usage includes:
+ * - OpenGL drawing.
+ * - #BVHTree creation.
+ * - Physics/collision detection.
+ *
+ * Storing loop indices (instead of vertex indices) allows us to
+ * directly access UV's, vertex-colors as well as vertices.
+ * The index of the source polygon is stored as well, giving access to materials and polygon normals.
+ *
+ * \note This data is runtime only, never written to disk.
+ *
+ * Usage examples:
+ * \code{.c}
+ * // access original material.
+ * short mat_nr = mpoly[lt->poly].mat_nr;
+ *
+ * // access vertex locations.
+ * float *vtri_co[3] = {
+ * mvert[mloop[lt->tri[0]].v].co,
+ * mvert[mloop[lt->tri[1]].v].co,
+ * mvert[mloop[lt->tri[2]].v].co,
+ * };
+ *
+ * // access UV coordinates (works for all loop data, vertex colors... etc).
+ * float *uvtri_co[3] = {
+ * mloopuv[lt->tri[0]].uv,
+ * mloopuv[lt->tri[1]].uv,
+ * mloopuv[lt->tri[2]].uv,
+ * };
+ * \endcode
+ *
+ * #MLoopTri's are allocated in an array, where each polygon's #MLoopTri's are stored contiguously,
+ * the number of triangles for each polygon is guaranteed to be (#MPoly.totloop - 2),
+ * even for degenerate geometry. See #ME_POLY_TRI_TOT macro.
+ *
+ * It's also possible to perform a reverse lookup (find all #MLoopTri's for any given #MPoly).
+ *
+ * \code{.c}
+ * // loop over all looptri's for a given polygon: i
+ * MPoly *mp = &mpoly[i];
+ * MLoopTri *lt = &looptri[poly_to_tri_count(i, mp->loopstart)];
+ * int j, lt_tot = ME_POLY_TRI_TOT(mp);
+ *
+ * for (j = 0; j < lt_tot; j++, lt++) {
+ * unsigned int vtri[3] = {
+ * mloop[lt->tri[0]].v,
+ * mloop[lt->tri[1]].v,
+ * mloop[lt->tri[2]].v,
+ * };
+ * printf("tri %u %u %u\n", vtri[0], vtri[1], vtri[2]);
+ * };
+ * \endcode
+ *
+ * It may also be useful to check whether or not two vertices of a triangle form an edge in the underlying mesh.
+ *
+ * This can be done by checking the edge of the referenced loop (#MLoop.e),
+ * the winding of the #MLoopTri and the #MLoop's will always match,
+ * however the order of vertices in the edge is undefined.
+ *
+ * \code{.c}
+ * // print real edges from an MLoopTri: lt
+ * int j, j_next;
+ * for (j = 2, j_next = 0; j_next < 3; j = j_next++) {
+ * MEdge *ed = &medge[mloop[lt->tri[j]].e];
+ * unsigned int tri_edge[2] = {mloop[lt->tri[j]].v, mloop[lt->tri[j_next]].v};
+ *
+ * if (ELEM(ed->v1, tri_edge[0], tri_edge[1]) &&
+ * ELEM(ed->v2, tri_edge[0], tri_edge[1]))
+ * {
+ * printf("real edge found %u %u\n", tri_edge[0], tri_edge[1]);
+ * }
+ * }
+ * \endcode
+ *
+ * \note A #MLoopTri may be in the middle of an ngon and not reference **any** edges.
+ */
+#
+#
+typedef struct MLoopTri {
+ unsigned int tri[3];
+ unsigned int poly;
+} MLoopTri;
+#
+#
+typedef struct MVertTri {
+ unsigned int tri[3];
+} MVertTri;
+
+
typedef struct MTexPoly {
struct Image *tpage;
char flag, transp;
@@ -216,7 +313,6 @@ typedef struct MultiresEdge {
unsigned int mid;
} MultiresEdge;
-struct MultiresMapNode;
typedef struct MultiresLevel {
struct MultiresLevel *next, *prev;
@@ -347,6 +443,19 @@ enum {
#define ME_POLY_LOOP_PREV(mloop, mp, i) (&(mloop)[(mp)->loopstart + (((i) + (mp)->totloop - 1) % (mp)->totloop)])
#define ME_POLY_LOOP_NEXT(mloop, mp, i) (&(mloop)[(mp)->loopstart + (((i) + 1) % (mp)->totloop)])
+/* number of tri's that make up this polygon once tessellated */
+#define ME_POLY_TRI_TOT(mp) ((mp)->totloop - 2)
+
+/**
+ * Check out-of-bounds material, note that this is nearly always prevented,
+ * yet its still possible in rare cases.
+ * So usage such as array lookup needs to check.
+ */
+#define ME_MAT_NR_TEST(mat_nr, totmat) \
+ (CHECK_TYPE_ANY(mat_nr, short, const short), \
+ CHECK_TYPE_ANY(totmat, short, const short), \
+ (LIKELY(mat_nr < totmat) ? mat_nr : 0))
+
/* mselect->type */
enum {
ME_VSEL = 0,
diff --git a/source/blender/makesdna/DNA_modifier_types.h b/source/blender/makesdna/DNA_modifier_types.h
index 47782bb3ae1..67ec9fe3db3 100644
--- a/source/blender/makesdna/DNA_modifier_types.h
+++ b/source/blender/makesdna/DNA_modifier_types.h
@@ -82,6 +82,9 @@ typedef enum ModifierType {
eModifierType_MeshCache = 46,
eModifierType_LaplacianDeform = 47,
eModifierType_Wireframe = 48,
+ eModifierType_DataTransfer = 49,
+ eModifierType_NormalEdit = 50,
+ eModifierType_CorrectiveSmooth = 51,
NUM_MODIFIER_TYPES
} ModifierType;
@@ -131,6 +134,7 @@ typedef struct SubsurfModifierData {
ModifierData modifier;
short subdivType, levels, renderLevels, flags;
+ short use_opensubdiv, pad[3];
void *emCache, *mCache;
} SubsurfModifierData;
@@ -335,6 +339,7 @@ enum {
/* MOD_BEVEL_EVEN = (1 << 11), */
/* MOD_BEVEL_DIST = (1 << 12), */ /* same as above */
MOD_BEVEL_OVERLAP_OK = (1 << 13),
+ MOD_BEVEL_EVEN_WIDTHS = (1 << 14),
};
/* BevelModifierData->val_flags (not used as flags any more) */
@@ -387,6 +392,7 @@ enum {
MOD_DISP_DIR_Z = 2,
MOD_DISP_DIR_NOR = 3,
MOD_DISP_DIR_RGB_XYZ = 4,
+ MOD_DISP_DIR_CLNOR = 5,
};
/* DisplaceModifierData->texmapping */
@@ -428,10 +434,11 @@ typedef struct DecimateModifierData {
float angle; /* (mode == MOD_DECIM_MODE_DISSOLVE) */
char defgrp_name[64]; /* MAX_VGROUP_NAME */
+ float defgrp_factor;
short flag, mode;
/* runtime only */
- int face_count, pad2;
+ int face_count;
} DecimateModifierData;
enum {
@@ -534,16 +541,39 @@ typedef struct ArmatureModifierData {
char defgrp_name[64]; /* MAX_VGROUP_NAME */
} ArmatureModifierData;
+enum {
+ MOD_HOOK_UNIFORM_SPACE = (1 << 0),
+};
+
+/* same as WarpModifierFalloff */
+typedef enum {
+ eHook_Falloff_None = 0,
+ eHook_Falloff_Curve = 1,
+ eHook_Falloff_Sharp = 2, /* PROP_SHARP */
+ eHook_Falloff_Smooth = 3, /* PROP_SMOOTH */
+ eHook_Falloff_Root = 4, /* PROP_ROOT */
+ eHook_Falloff_Linear = 5, /* PROP_LIN */
+ eHook_Falloff_Const = 6, /* PROP_CONST */
+ eHook_Falloff_Sphere = 7, /* PROP_SPHERE */
+ eHook_Falloff_InvSquare = 8, /* PROP_INVSQUARE */
+ /* PROP_RANDOM not used */
+} HookModifierFalloff;
+
typedef struct HookModifierData {
ModifierData modifier;
struct Object *object;
char subtarget[64]; /* optional name of bone target, MAX_ID_NAME-2 */
+ char flag;
+ char falloff_type; /* use enums from WarpModifier (exact same functionality) */
+ char pad[6];
float parentinv[4][4]; /* matrix making current transform unmodified */
float cent[3]; /* visualization of hook */
float falloff; /* if not zero, falloff is distance where influence zero */
+ struct CurveMapping *curfalloff;
+
int *indexar; /* if NULL, it's using vertexgroup */
int totindex;
float force;
@@ -563,6 +593,15 @@ typedef struct ClothModifierData {
struct ClothCollSettings *coll_parms; /* definition is in DNA_cloth_types.h */
struct PointCache *point_cache; /* definition is in DNA_object_force.h */
struct ListBase ptcaches;
+ /* XXX nasty hack, remove once hair can be separated from cloth modifier data */
+ struct ClothHairData *hairdata;
+ /* grid geometry values of hair continuum */
+ float hair_grid_min[3];
+ float hair_grid_max[3];
+ int hair_grid_res[3];
+ float hair_grid_cellsize;
+
+ struct ClothSolverResult *solver_result;
} ClothModifierData;
typedef struct CollisionModifierData {
@@ -575,10 +614,10 @@ typedef struct CollisionModifierData {
struct MVert *current_x; /* position at the actual inter-frame step */
struct MVert *current_v; /* (xnew - x) at the actual inter-frame step */
- struct MFace *mfaces; /* object face data */
+ struct MVertTri *tri;
- unsigned int numverts;
- unsigned int numfaces;
+ unsigned int mvert_num;
+ unsigned int tri_num;
float time_x, time_xnew; /* cfra time of modifier */
struct BVHTree *bvhtree; /* bounding volume hierarchy for this cloth object */
} CollisionModifierData;
@@ -838,15 +877,13 @@ enum {
MOD_SOLIDIFY_EVEN = (1 << 1),
MOD_SOLIDIFY_NORMAL_CALC = (1 << 2),
MOD_SOLIDIFY_VGROUP_INV = (1 << 3),
+#ifdef DNA_DEPRECATED
MOD_SOLIDIFY_RIM_MATERIAL = (1 << 4), /* deprecated, used in do_versions */
+#endif
MOD_SOLIDIFY_FLIP = (1 << 5),
MOD_SOLIDIFY_NOSHELL = (1 << 6),
};
-#if (DNA_DEPRECATED_GCC_POISON == 1)
-#pragma GCC poison MOD_SOLIDIFY_RIM_MATERIAL
-#endif
-
typedef struct ScrewModifierData {
ModifierData modifier;
@@ -968,6 +1005,7 @@ typedef enum {
eWarp_Falloff_Linear = 5, /* PROP_LIN */
eWarp_Falloff_Const = 6, /* PROP_CONST */
eWarp_Falloff_Sphere = 7, /* PROP_SPHERE */
+ eWarp_Falloff_InvSquare = 8, /* PROP_INVSQUARE */
/* PROP_RANDOM not used */
} WarpModifierFalloff;
@@ -1214,12 +1252,10 @@ typedef struct TriangulateModifierData {
int pad;
} TriangulateModifierData;
+#ifdef DNA_DEPRECATED
enum {
MOD_TRIANGULATE_BEAUTY = (1 << 0), /* deprecated */
};
-
-#if (DNA_DEPRECATED_GCC_POISON == 1)
-#pragma GCC poison MOD_TRIANGULATE_BEAUTY
#endif
/* Triangulate methods - NGons */
@@ -1253,6 +1289,48 @@ enum {
MOD_LAPLACIANSMOOTH_NORMALIZED = (1 << 5),
};
+
+typedef struct CorrectiveSmoothModifierData {
+ ModifierData modifier;
+
+ /* positions set during 'bind' operator
+ * use for MOD_CORRECTIVESMOOTH_RESTSOURCE_BIND */
+ float (*bind_coords)[3];
+
+ /* note: -1 is used to bind */
+ unsigned int bind_coords_num;
+
+ float lambda;
+ short repeat, flag;
+ char smooth_type, rest_source;
+ char pad[2];
+
+ char defgrp_name[64]; /* MAX_VGROUP_NAME */
+
+ /* runtime-only cache (delta's between),
+ * delta's between the original positions and the smoothed positions */
+ float (*delta_cache)[3];
+ unsigned int delta_cache_num;
+ char pad2[4];
+} CorrectiveSmoothModifierData;
+
+enum {
+ MOD_CORRECTIVESMOOTH_SMOOTH_SIMPLE = 0,
+ MOD_CORRECTIVESMOOTH_SMOOTH_LENGTH_WEIGHT = 1,
+};
+
+enum {
+ MOD_CORRECTIVESMOOTH_RESTSOURCE_ORCO = 0,
+ MOD_CORRECTIVESMOOTH_RESTSOURCE_BIND = 1,
+};
+
+/* Corrective Smooth modifier flags */
+enum {
+ MOD_CORRECTIVESMOOTH_INVERT_VGROUP = (1 << 0),
+ MOD_CORRECTIVESMOOTH_ONLY_SMOOTH = (1 << 1),
+ MOD_CORRECTIVESMOOTH_PIN_BOUNDARY = (1 << 2),
+};
+
typedef struct UVWarpModifierData {
ModifierData modifier;
@@ -1367,5 +1445,79 @@ enum {
};
+typedef struct DataTransferModifierData {
+ ModifierData modifier;
+
+ struct Object *ob_source;
+
+ int data_types; /* See DT_TYPE_ enum in ED_object.h */
+
+ /* See MREMAP_MODE_ enum in BKE_mesh_mapping.h */
+ int vmap_mode;
+ int emap_mode;
+ int lmap_mode;
+ int pmap_mode;
+
+ float map_max_distance;
+ float map_ray_radius;
+ float islands_precision;
+
+ int pad_i1;
+
+ int layers_select_src[4]; /* DT_MULTILAYER_INDEX_MAX; See DT_FROMLAYERS_ enum in ED_object.h */
+ int layers_select_dst[4]; /* DT_MULTILAYER_INDEX_MAX; See DT_TOLAYERS_ enum in ED_object.h */
+
+ int mix_mode; /* See CDT_MIX_ enum in BKE_customdata.h */
+ float mix_factor;
+ char defgrp_name[64]; /* MAX_VGROUP_NAME */
+
+ int flags;
+} DataTransferModifierData;
+
+/* DataTransferModifierData.flags */
+enum {
+ MOD_DATATRANSFER_OBSRC_TRANSFORM = 1 << 0,
+ MOD_DATATRANSFER_MAP_MAXDIST = 1 << 1,
+ MOD_DATATRANSFER_INVERT_VGROUP = 1 << 2,
+
+ /* Only for UI really. */
+ MOD_DATATRANSFER_USE_VERT = 1 << 28,
+ MOD_DATATRANSFER_USE_EDGE = 1 << 29,
+ MOD_DATATRANSFER_USE_LOOP = 1 << 30,
+ MOD_DATATRANSFER_USE_POLY = 1 << 31,
+};
+
+/* Set Split Normals modifier */
+typedef struct NormalEditModifierData {
+ ModifierData modifier;
+ char defgrp_name[64]; /* MAX_VGROUP_NAME */
+ struct Object *target; /* Source of normals, or center of ellipsoid. */
+ short mode;
+ short flag;
+ short mix_mode;
+ char pad[2];
+ float mix_factor;
+ float offset[3];
+} NormalEditModifierData;
+
+/* NormalEditModifierData.mode */
+enum {
+ MOD_NORMALEDIT_MODE_RADIAL = 0,
+ MOD_NORMALEDIT_MODE_DIRECTIONAL = 1,
+};
+
+/* NormalEditModifierData.flags */
+enum {
+ MOD_NORMALEDIT_INVERT_VGROUP = (1 << 0),
+ MOD_NORMALEDIT_USE_DIRECTION_PARALLEL = (1 << 1),
+};
+
+/* NormalEditModifierData.mix_mode */
+enum {
+ MOD_NORMALEDIT_MIX_COPY = 0,
+ MOD_NORMALEDIT_MIX_ADD = 1,
+ MOD_NORMALEDIT_MIX_SUB = 2,
+ MOD_NORMALEDIT_MIX_MUL = 3,
+};
#endif /* __DNA_MODIFIER_TYPES_H__ */
diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h
index e0d25e763d4..32f766ecae5 100644
--- a/source/blender/makesdna/DNA_node_types.h
+++ b/source/blender/makesdna/DNA_node_types.h
@@ -40,7 +40,6 @@
struct ID;
struct ListBase;
-struct SpaceNode;
struct bNodeLink;
struct bNodeType;
struct bNodeTreeExec;
@@ -192,6 +191,8 @@ typedef struct bNode {
float width, height; /* node custom width and height */
float miniwidth; /* node width if hidden */
float offsetx, offsety; /* additional offset from loc */
+ float anim_init_locx; /* initial locx for insert offset animation */
+ float anim_ofsx; /* offset that will be added to locx for insert offset animation */
int update; /* update flags */
@@ -264,12 +265,12 @@ typedef struct bNode {
*/
#define NODE_UPDATE 0xFFFF /* generic update flag (includes all others) */
#define NODE_UPDATE_ID 1 /* associated id data block has changed */
+#define NODE_UPDATE_OPERATOR 2 /* node update triggered from update operator */
/* Unique hash key for identifying node instances
* Defined as a struct because DNA does not support other typedefs.
*/
-typedef struct bNodeInstanceKey
-{
+typedef struct bNodeInstanceKey {
unsigned int value;
} bNodeInstanceKey;
@@ -383,10 +384,12 @@ typedef struct bNodeTree {
/* callbacks */
void (*progress)(void *, float progress);
- void (*stats_draw)(void *, char *str);
+ void (*stats_draw)(void *, const char *str);
int (*test_break)(void *);
void (*update_draw)(void *);
void *tbh, *prh, *sdh, *udh;
+
+ void *duplilock;
} bNodeTree;
@@ -726,6 +729,8 @@ typedef struct NodeTexImage {
int projection;
float projection_blend;
int interpolation;
+ int extension;
+ int pad;
} NodeTexImage;
typedef struct NodeTexChecker {
@@ -789,6 +794,18 @@ typedef struct NodeShaderVectTransform {
int pad;
} NodeShaderVectTransform;
+typedef struct NodeShaderTexPointDensity {
+ NodeTexBase base;
+ short point_source, pad;
+ int particle_system;
+ float radius;
+ int resolution;
+ short space;
+ short interpolation;
+ short color_source;
+ short pad2;
+} NodeShaderTexPointDensity;
+
/* TEX_output */
typedef struct TexNodeOutput {
char name[64];
@@ -825,6 +842,10 @@ typedef struct NodeTranslateData {
typedef struct NodePlaneTrackDeformData {
char tracking_object[64];
char plane_track_name[64];
+ char flag;
+ char motion_blur_samples;
+ char pad[2];
+ float motion_blur_shutter;
} NodePlaneTrackDeformData;
typedef struct NodeShaderScript {
@@ -959,9 +980,15 @@ typedef struct NodeSunBeams {
#define SHD_PROJ_EQUIRECTANGULAR 0
#define SHD_PROJ_MIRROR_BALL 1
+#define SHD_IMAGE_EXTENSION_REPEAT 0
+#define SHD_IMAGE_EXTENSION_EXTEND 1
+#define SHD_IMAGE_EXTENSION_CLIP 2
+
/* image texture */
#define SHD_PROJ_FLAT 0
#define SHD_PROJ_BOX 1
+#define SHD_PROJ_SPHERE 2
+#define SHD_PROJ_TUBE 3
/* image texture interpolation */
#define SHD_INTERP_LINEAR 0
@@ -985,17 +1012,45 @@ typedef struct NodeSunBeams {
#define SHD_NORMAL_MAP_BLENDER_OBJECT 3
#define SHD_NORMAL_MAP_BLENDER_WORLD 4
+/* math node clamp */
+#define SHD_MATH_CLAMP 1
+
+/* Math node operation/ */
+enum {
+ NODE_MATH_ADD = 0,
+ NODE_MATH_SUB = 1,
+ NODE_MATH_MUL = 2,
+ NODE_MATH_DIVIDE = 3,
+ NODE_MATH_SIN = 4,
+ NODE_MATH_COS = 5,
+ NODE_MATH_TAN = 6,
+ NODE_MATH_ASIN = 7,
+ NODE_MATH_ACOS = 8,
+ NODE_MATH_ATAN = 9,
+ NODE_MATH_POW = 10,
+ NODE_MATH_LOG = 11,
+ NODE_MATH_MIN = 12,
+ NODE_MATH_MAX = 13,
+ NODE_MATH_ROUND = 14,
+ NODE_MATH_LESS = 15,
+ NODE_MATH_GREATER = 16,
+ NODE_MATH_MOD = 17,
+ NODE_MATH_ABS = 18,
+};
+
+/* mix rgb node flags */
+#define SHD_MIXRGB_USE_ALPHA 1
+#define SHD_MIXRGB_CLAMP 2
+
/* subsurface */
enum {
+#ifdef DNA_DEPRECATED
SHD_SUBSURFACE_COMPATIBLE = 0, // Deprecated
+#endif
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
#define CMP_NODE_BLUR_ASPECT_Y 1
@@ -1048,4 +1103,29 @@ enum {
/* viewer and cmposite output */
#define CMP_NODE_OUTPUT_IGNORE_ALPHA 1
+/* Plane track deform node */
+enum {
+ CMP_NODEFLAG_PLANETRACKDEFORM_MOTION_BLUR = 1,
+};
+
+#define CMP_NODE_PLANETRACKDEFORM_MBLUR_SAMPLES_MAX 64
+
+/* Point Density shader node */
+
+enum {
+ SHD_POINTDENSITY_SOURCE_PSYS = 0,
+ SHD_POINTDENSITY_SOURCE_OBJECT = 1,
+};
+
+enum {
+ SHD_POINTDENSITY_SPACE_OBJECT = 0,
+ SHD_POINTDENSITY_SPACE_WORLD = 1,
+};
+
+enum {
+ SHD_POINTDENSITY_COLOR_PARTAGE = 1,
+ SHD_POINTDENSITY_COLOR_PARTSPEED = 2,
+ SHD_POINTDENSITY_COLOR_PARTVEL = 3,
+};
+
#endif
diff --git a/source/blender/makesdna/DNA_object_force.h b/source/blender/makesdna/DNA_object_force.h
index 5cc56d861a3..c9c1f618e86 100644
--- a/source/blender/makesdna/DNA_object_force.h
+++ b/source/blender/makesdna/DNA_object_force.h
@@ -297,7 +297,7 @@ typedef struct SoftBody {
char namedVG_Softgoal[64]; /* MAX_VGROUP_NAME */
/* starting to fix old bug .. nastiness that VG are indexes
* rather find them by name tag to find it -> jow20090613 */
-
+
short fuzzyness; /* */
/* springs */
diff --git a/source/blender/makesdna/DNA_object_types.h b/source/blender/makesdna/DNA_object_types.h
index 0bcc6bfd70e..faae78ab500 100644
--- a/source/blender/makesdna/DNA_object_types.h
+++ b/source/blender/makesdna/DNA_object_types.h
@@ -48,7 +48,6 @@ struct Ipo;
struct BoundBox;
struct Path;
struct Material;
-struct bConstraintChannel;
struct PartDeflect;
struct SoftBody;
struct FluidsimSettings;
@@ -109,7 +108,8 @@ typedef struct LodLevel {
struct LodLevel *next, *prev;
struct Object *source;
int flags;
- float distance;
+ float distance, pad;
+ int obhysteresis;
} LodLevel;
typedef struct Object {
@@ -183,16 +183,17 @@ typedef struct Object {
short transflag, protectflag; /* transformation settings and transform locks */
short trackflag, upflag;
short nlaflag; /* used for DopeSheet filtering settings (expanded/collapsed) */
- short ipoflag; // xxx deprecated... old animation system
short scaflag; /* ui state for game logic */
char scavisflag; /* more display settings for game logic */
char depsflag;
+ /* did last modifier stack generation need mapping support? */
+ char lastNeedMapping; /* bool */
+ char pad[5];
+
/* dupli-frame settings */
int dupon, dupoff, dupsta, dupend;
- int pad;
-
/* during realtime */
/* note that inertia is only called inertia for historical reasons
@@ -213,6 +214,8 @@ typedef struct Object {
float margin;
float max_vel; /* clamp the maximum velocity 0.0 is disabled */
float min_vel; /* clamp the minimum velocity 0.0 is disabled */
+ float max_angvel; /* clamp the maximum angular velocity, 0.0 is disabled */
+ float min_angvel; /* clamp the minimum angular velocity, 0.0 is disabled */
float obstacleRad;
/* "Character" physics properties */
@@ -292,6 +295,8 @@ typedef struct Object {
ListBase lodlevels; /* contains data for levels of detail */
LodLevel *currentlod;
+
+ struct PreviewImage *preview;
} Object;
/* Warning, this is not used anymore because hooks are now modifiers */
@@ -377,8 +382,10 @@ enum {
enum {
PARTYPE = (1 << 4) - 1,
PAROBJECT = 0,
- PARCURVE = 1,
- PARKEY = 2,
+#ifdef DNA_DEPRECATED
+ PARCURVE = 1, /* Deprecated. */
+#endif
+ PARKEY = 2, /* XXX Unused, deprecated? */
PARSKEL = 4,
PARVERT1 = 5,
@@ -397,7 +404,7 @@ enum {
OB_DUPLIVERTS = 1 << 4,
OB_DUPLIROT = 1 << 5,
OB_DUPLINOSPEED = 1 << 6,
-/* OB_POWERTRACK = 1 << 7,*/ /*UNUSED*/
+ OB_DUPLICALCDERIVED = 1 << 7, /* runtime, calculate derivedmesh for dupli before it's used */
OB_DUPLIGROUP = 1 << 8,
OB_DUPLIFACES = 1 << 9,
OB_DUPLIFACES_SCALE = 1 << 10,
@@ -409,13 +416,6 @@ enum {
OB_DUPLI = OB_DUPLIFRAMES | OB_DUPLIVERTS | OB_DUPLIGROUP | OB_DUPLIFACES | OB_DUPLIPARTS,
};
-/* (short) ipoflag */
-/* XXX: many old flags for features removed due to incompatibility
- * with new system and/or other design issues were here
- */
- /* for stride/path editing (XXX: NEEDS REVIEW) */
-#define OB_DISABLE_PATH (1 << 10)
-
/* (short) trackflag / upflag */
enum {
OB_POSX = 0,
@@ -484,6 +484,7 @@ enum {
enum {
OB_LOD_USE_MESH = 1 << 0,
OB_LOD_USE_MAT = 1 << 1,
+ OB_LOD_USE_HYST = 1 << 2,
};
@@ -510,7 +511,7 @@ enum {
#define OB_FROMDUPLI (1 << 9)
-#define OB_DONE (1 << 10)
+#define OB_DONE (1 << 10) /* unknown state, clear before use */
/* #define OB_RADIO (1 << 11) */ /* deprecated */
#define OB_FROMGROUP (1 << 12)
@@ -529,7 +530,7 @@ enum {
#define OB_MAX_STATES 30
/* collision masks */
-#define OB_MAX_COL_MASKS 8
+#define OB_MAX_COL_MASKS 16
/* ob->gameflag */
enum {
diff --git a/source/blender/makesdna/DNA_outliner_types.h b/source/blender/makesdna/DNA_outliner_types.h
index 53061b55e2d..984e3334414 100644
--- a/source/blender/makesdna/DNA_outliner_types.h
+++ b/source/blender/makesdna/DNA_outliner_types.h
@@ -56,7 +56,55 @@ typedef struct TreeStore {
#define TSE_CHILDSEARCH 8
#define TSE_SEARCHMATCH 16
-/* TreeStoreElem types in BIF_outliner.h */
+/* TreeStoreElem->types */
+#define TSE_NLA 1 /* NO ID */
+#define TSE_NLA_ACTION 2
+#define TSE_DEFGROUP_BASE 3
+#define TSE_DEFGROUP 4
+#define TSE_BONE 5
+#define TSE_EBONE 6
+#define TSE_CONSTRAINT_BASE 7
+#define TSE_CONSTRAINT 8
+#define TSE_MODIFIER_BASE 9
+#define TSE_MODIFIER 10
+#define TSE_LINKED_OB 11
+/* #define TSE_SCRIPT_BASE 12 */ /* UNUSED */
+#define TSE_POSE_BASE 13
+#define TSE_POSE_CHANNEL 14
+#define TSE_ANIM_DATA 15
+#define TSE_DRIVER_BASE 16 /* NO ID */
+/* #define TSE_DRIVER 17 */ /* UNUSED */
+
+#define TSE_PROXY 18
+#define TSE_R_LAYER_BASE 19
+#define TSE_R_LAYER 20
+#define TSE_R_PASS 21
+#define TSE_LINKED_MAT 22
+/* NOTE, is used for light group */
+#define TSE_LINKED_LAMP 23
+#define TSE_POSEGRP_BASE 24
+#define TSE_POSEGRP 25
+#define TSE_SEQUENCE 26 /* NO ID */
+#define TSE_SEQ_STRIP 27 /* NO ID */
+#define TSE_SEQUENCE_DUP 28 /* NO ID */
+#define TSE_LINKED_PSYS 29
+#define TSE_RNA_STRUCT 30 /* NO ID */
+#define TSE_RNA_PROPERTY 31 /* NO ID */
+#define TSE_RNA_ARRAY_ELEM 32 /* NO ID */
+#define TSE_NLA_TRACK 33 /* NO ID */
+#define TSE_KEYMAP 34 /* NO ID */
+#define TSE_KEYMAP_ITEM 35 /* NO ID */
+#define TSE_ID_BASE 36 /* NO ID */
+#define TSE_GP_LAYER 37 /* NO ID */
+
+
+/* Check whether given TreeStoreElem should have a real ID in its ->id member. */
+#define TSE_IS_REAL_ID(_tse) \
+ (!ELEM((_tse)->type, TSE_NLA, TSE_NLA_TRACK, TSE_DRIVER_BASE, \
+ TSE_SEQUENCE, TSE_SEQ_STRIP, TSE_SEQUENCE_DUP, \
+ TSE_RNA_STRUCT, TSE_RNA_PROPERTY, TSE_RNA_ARRAY_ELEM, \
+ TSE_KEYMAP, TSE_KEYMAP_ITEM, TSE_ID_BASE, TSE_GP_LAYER))
+
#endif
diff --git a/source/blender/makesdna/DNA_packedFile_types.h b/source/blender/makesdna/DNA_packedFile_types.h
index ef0a0f642d6..56140c84cb1 100644
--- a/source/blender/makesdna/DNA_packedFile_types.h
+++ b/source/blender/makesdna/DNA_packedFile_types.h
@@ -40,8 +40,7 @@ typedef struct PackedFile {
void *data;
} PackedFile;
-enum PF_FileStatus
-{
+enum PF_FileStatus {
PF_EQUAL = 0,
PF_DIFFERS = 1,
PF_NOFILE = 2,
diff --git a/source/blender/makesdna/DNA_particle_types.h b/source/blender/makesdna/DNA_particle_types.h
index a2a724b6a32..95cb5c84bed 100644
--- a/source/blender/makesdna/DNA_particle_types.h
+++ b/source/blender/makesdna/DNA_particle_types.h
@@ -44,6 +44,7 @@ typedef struct HairKey {
float weight; /* softbody weight */
short editflag; /* saved particled edit mode flags */
short pad;
+ float world_co[3];
} HairKey;
typedef struct ParticleKey { /* when changed update size of struct to copy_particleKey()!! */
@@ -207,6 +208,8 @@ typedef struct ParticleSettings {
/* length */
float randlength;
/* children */
+ int child_flag;
+ int pad3;
int child_nbr, ren_child_nbr;
float parents, childsize, childrandsize;
float childrad, childflat;
@@ -215,6 +218,8 @@ typedef struct ParticleSettings {
/* kink */
float kink_amp, kink_freq, kink_shape, kink_flat;
float kink_amp_clump;
+ int kink_extra_steps, pad4;
+ float kink_axis_random, kink_amp_random;
/* rough */
float rough1, rough1_size;
float rough2, rough2_size, rough2_thres;
@@ -232,6 +237,12 @@ typedef struct ParticleSettings {
int trail_count;
/* keyed particles */
int keyed_loops;
+ struct CurveMapping *clumpcurve;
+ struct CurveMapping *roughcurve;
+ float clump_noise_size;
+
+ /* hair dynamics */
+ float bending_random;
struct MTex *mtex[18]; /* MAX_MTEX */
@@ -246,7 +257,7 @@ typedef struct ParticleSettings {
/* modified dm support */
short use_modifier_stack;
- short pad[3];
+ short pad5[3];
} ParticleSettings;
@@ -293,7 +304,7 @@ typedef struct ParticleSystem {
short vgroup[12], vg_neg, rt3; /* vertex groups, 0==disable, 1==starting index */
/* temporary storage during render */
- void *renderdata;
+ struct ParticleRenderData *renderdata;
/* point cache */
struct PointCache *pointcache;
@@ -313,6 +324,29 @@ typedef struct ParticleSystem {
float _pad; /* spare capacity */
} ParticleSystem;
+typedef enum eParticleDrawFlag {
+ PART_DRAW_VEL = (1 << 0),
+ PART_DRAW_GLOBAL_OB = (1 << 1),
+ PART_DRAW_SIZE = (1 << 2),
+ PART_DRAW_EMITTER = (1 << 3), /* render emitter also */
+ PART_DRAW_HEALTH = (1 << 4),
+ PART_ABS_PATH_TIME = (1 << 5),
+ PART_DRAW_COUNT_GR = (1 << 6),
+ PART_DRAW_BB_LOCK = (1 << 7), /* used with billboards */
+ PART_DRAW_ROTATE_OB = (1 << 7), /* used with dupliobjects/groups */
+ PART_DRAW_PARENT = (1 << 8),
+ PART_DRAW_NUM = (1 << 9),
+ PART_DRAW_RAND_GR = (1 << 10),
+ PART_DRAW_REN_ADAPT = (1 << 11),
+ PART_DRAW_VEL_LENGTH = (1 << 12),
+ PART_DRAW_MAT_COL = (1 << 13), /* deprecated, but used in do_versions */
+ PART_DRAW_WHOLE_GR = (1 << 14),
+ PART_DRAW_REN_STRAND = (1 << 15),
+ PART_DRAW_NO_SCALE_OB = (1 << 16), /* used with dupliobjects/groups */
+ PART_DRAW_GUIDE_HAIRS = (1 << 17),
+ PART_DRAW_HAIR_GRID = (1 << 18),
+} eParticleDrawFlag;
+
/* part->type */
/* hair is allways baked static in object/geometry space */
/* other types (normal particles) are in global space and not static baked */
@@ -385,31 +419,21 @@ typedef struct ParticleSystem {
#define PART_PHYS_FLUID 4
/* part->kink */
-#define PART_KINK_NO 0
-#define PART_KINK_CURL 1
-#define PART_KINK_RADIAL 2
-#define PART_KINK_WAVE 3
-#define PART_KINK_BRAID 4
-
-/* part->draw */
-#define PART_DRAW_VEL 1
-#define PART_DRAW_GLOBAL_OB 2
-#define PART_DRAW_SIZE 4
-#define PART_DRAW_EMITTER 8 /* render emitter also */
-#define PART_DRAW_HEALTH 16
-#define PART_ABS_PATH_TIME 32
-#define PART_DRAW_COUNT_GR 64
-#define PART_DRAW_BB_LOCK 128 /* used with billboards */
-#define PART_DRAW_ROTATE_OB 128 /* used with dupliobjects/groups */
-#define PART_DRAW_PARENT 256
-#define PART_DRAW_NUM 512
-#define PART_DRAW_RAND_GR 1024
-#define PART_DRAW_REN_ADAPT 2048
-#define PART_DRAW_VEL_LENGTH (1<<12)
-#define PART_DRAW_MAT_COL (1<<13) /* deprecated, but used in do_versions */
-#define PART_DRAW_WHOLE_GR (1<<14)
-#define PART_DRAW_REN_STRAND (1<<15)
-#define PART_DRAW_NO_SCALE_OB (1<<16) /* used with dupliobjects/groups */
+typedef enum eParticleKink {
+ PART_KINK_NO = 0,
+ PART_KINK_CURL = 1,
+ PART_KINK_RADIAL = 2,
+ PART_KINK_WAVE = 3,
+ PART_KINK_BRAID = 4,
+ PART_KINK_SPIRAL = 5,
+} eParticleKink;
+
+/* part->child_flag */
+typedef enum eParticleChildFlag {
+ PART_CHILD_USE_CLUMP_NOISE = (1<<0),
+ PART_CHILD_USE_CLUMP_CURVE = (1<<1),
+ PART_CHILD_USE_ROUGH_CURVE = (1<<2),
+} eParticleChildFlag;
/* part->draw_col */
#define PART_DRAW_COL_NONE 0
@@ -561,24 +585,27 @@ typedef struct ParticleSystem {
#define PTARGET_MODE_ENEMY 2
/* mapto */
-/* init */
-#define PAMAP_INIT (PAMAP_TIME | PAMAP_LIFE | PAMAP_DENS | PAMAP_SIZE)
-#define PAMAP_TIME (1<<0) /* emission time */
-#define PAMAP_LIFE (1<<1) /* life time */
-#define PAMAP_DENS (1<<2) /* density */
-#define PAMAP_SIZE (1<<3) /* physical size */
-/* reset */
-#define PAMAP_IVEL (1<<5) /* initial velocity */
-/* physics */
-#define PAMAP_PHYSICS (PAMAP_FIELD | PAMAP_GRAVITY | PAMAP_DAMP)
-#define PAMAP_FIELD (1<<6) /* force fields */
-#define PAMAP_GRAVITY (1<<10)
-#define PAMAP_DAMP (1<<11)
-/* children */
-#define PAMAP_CHILD (PAMAP_CLUMP | PAMAP_KINK | PAMAP_ROUGH | PAMAP_LENGTH)
-#define PAMAP_CLUMP (1<<7)
-#define PAMAP_KINK (1<<8)
-#define PAMAP_ROUGH (1<<9)
-#define PAMAP_LENGTH (1<<4)
+typedef enum eParticleTextureInfluence {
+ /* init */
+ PAMAP_TIME = (1<<0), /* emission time */
+ PAMAP_LIFE = (1<<1), /* life time */
+ PAMAP_DENS = (1<<2), /* density */
+ PAMAP_SIZE = (1<<3), /* physical size */
+ PAMAP_INIT = (PAMAP_TIME | PAMAP_LIFE | PAMAP_DENS | PAMAP_SIZE),
+ /* reset */
+ PAMAP_IVEL = (1<<5), /* initial velocity */
+ /* physics */
+ PAMAP_FIELD = (1<<6), /* force fields */
+ PAMAP_GRAVITY = (1<<10),
+ PAMAP_DAMP = (1<<11),
+ PAMAP_PHYSICS = (PAMAP_FIELD | PAMAP_GRAVITY | PAMAP_DAMP),
+ /* children */
+ PAMAP_CLUMP = (1<<7),
+ PAMAP_KINK_FREQ = (1<<8),
+ PAMAP_KINK_AMP = (1<<12),
+ PAMAP_ROUGH = (1<<9),
+ PAMAP_LENGTH = (1<<4),
+ PAMAP_CHILD = (PAMAP_CLUMP | PAMAP_KINK_FREQ | PAMAP_KINK_AMP | PAMAP_ROUGH | PAMAP_LENGTH),
+} eParticleTextureInfluence;
#endif
diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h
index c8b8e4d52a4..f9cea3871f6 100644
--- a/source/blender/makesdna/DNA_scene_types.h
+++ b/source/blender/makesdna/DNA_scene_types.h
@@ -46,7 +46,10 @@ extern "C" {
#include "DNA_listBase.h"
#include "DNA_ID.h"
#include "DNA_freestyle_types.h"
+#include "DNA_gpu_types.h"
+#include "DNA_userdef_types.h"
+struct CurveMapping;
struct Object;
struct Brush;
struct World;
@@ -242,10 +245,78 @@ typedef enum ScenePassType {
SCE_PASS_SUBSURFACE_DIRECT = (1 << 28),
SCE_PASS_SUBSURFACE_INDIRECT = (1 << 29),
SCE_PASS_SUBSURFACE_COLOR = (1 << 30),
+ SCE_PASS_DEBUG = (1 << 31), /* This is a virtual pass. */
} ScenePassType;
/* note, srl->passflag is treestore element 'nr' in outliner, short still... */
+/* View - MultiView */
+typedef struct SceneRenderView {
+ struct SceneRenderView *next, *prev;
+
+ char name[64]; /* MAX_NAME */
+ char suffix[64]; /* MAX_NAME */
+
+ int viewflag;
+ int pad[2];
+ char pad2[4];
+
+} SceneRenderView;
+
+/* srv->viewflag */
+#define SCE_VIEW_DISABLE (1<<0)
+
+/* scene.render.views_format */
+enum {
+ SCE_VIEWS_FORMAT_STEREO_3D = 0,
+ SCE_VIEWS_FORMAT_MULTIVIEW = 1,
+};
+
+/* ImageFormatData.views_output */
+enum {
+ R_IMF_VIEWS_INDIVIDUAL = 0,
+ R_IMF_VIEWS_STEREO_3D = 1,
+ R_IMF_VIEWS_MULTIVIEW = 2,
+};
+
+typedef struct Stereo3dFormat {
+ short flag;
+ char display_mode; /* encoding mode */
+ char anaglyph_type; /* anaglyph scheme for the user display */
+ char interlace_type; /* interlace type for the user display */
+ char pad[3];
+} Stereo3dFormat;
+
+/* Stereo3dFormat.display_mode */
+typedef enum eStereoDisplayMode {
+ S3D_DISPLAY_ANAGLYPH = 0,
+ S3D_DISPLAY_INTERLACE = 1,
+ S3D_DISPLAY_PAGEFLIP = 2,
+ S3D_DISPLAY_SIDEBYSIDE = 3,
+ S3D_DISPLAY_TOPBOTTOM = 4,
+} eStereoDisplayMode;
+
+/* Stereo3dFormat.flag */
+typedef enum eStereo3dFlag {
+ S3D_INTERLACE_SWAP = (1 << 0),
+ S3D_SIDEBYSIDE_CROSSEYED = (1 << 1),
+ S3D_SQUEEZED_FRAME = (1 << 2),
+} eStereo3dFlag;
+
+/* Stereo3dFormat.anaglyph_type */
+typedef enum eStereo3dAnaglyphType {
+ S3D_ANAGLYPH_REDCYAN = 0,
+ S3D_ANAGLYPH_GREENMAGENTA = 1,
+ S3D_ANAGLYPH_YELLOWBLUE = 2,
+} eStereo3dAnaglyphType;
+
+/* Stereo3dFormat.interlace_type */
+typedef enum eStereo3dInterlaceType {
+ S3D_INTERLACE_ROW = 0,
+ S3D_INTERLACE_COLUMN = 1,
+ S3D_INTERLACE_CHECKERBOARD = 2,
+} eStereo3dInterlaceType;
+
/* *************************************************************** */
/* Generic image format settings,
@@ -283,7 +354,11 @@ typedef struct ImageFormatData {
char jp2_flag;
char jp2_codec;
- char pad[6];
+ char pad[5];
+
+ /* Multiview */
+ char views_format;
+ Stereo3dFormat stereo3d_format;
/* color management */
ColorManagedViewSettings view_settings;
@@ -347,6 +422,12 @@ typedef struct ImageFormatData {
#define R_IMF_EXR_CODEC_ZIP 2
#define R_IMF_EXR_CODEC_PIZ 3
#define R_IMF_EXR_CODEC_RLE 4
+#define R_IMF_EXR_CODEC_ZIPS 5
+#define R_IMF_EXR_CODEC_B44 6
+#define R_IMF_EXR_CODEC_B44A 7
+#define R_IMF_EXR_CODEC_DWAA 8
+#define R_IMF_EXR_CODEC_DWAB 9
+#define R_IMF_EXR_CODEC_MAX 10
/* ImageFormatData.jp2_flag */
#define R_IMF_JP2_FLAG_YCC (1<<0) /* when disabled use RGB */ /* was R_JPEG2K_YCC */
@@ -576,8 +657,10 @@ typedef struct RenderData {
/* render simplify */
int simplify_flag;
short simplify_subsurf;
- short simplify_shadowsamples;
+ short simplify_subsurf_render;
+ short simplify_shadowsamples, pad9;
float simplify_particles;
+ float simplify_particles_render;
float simplify_aosss;
/* cineon */
@@ -606,7 +689,19 @@ typedef struct RenderData {
struct BakeData bake;
int preview_start_resolution;
- int pad;
+
+ /* Type of the debug pass to use.
+ * Only used when built with debug passes support.
+ */
+ short debug_pass_type;
+
+ short pad;
+
+ /* MultiView */
+ ListBase views;
+ short actview;
+ short views_format;
+ short pad8[2];
} RenderData;
/* *************************************************************** */
@@ -709,7 +804,12 @@ typedef struct GameData {
short obstacleSimulation;
short raster_storage;
float levelHeight;
- float deactivationtime, lineardeactthreshold, angulardeactthreshold, pad2;
+ float deactivationtime, lineardeactthreshold, angulardeactthreshold;
+
+ /* Scene LoD */
+ short lodflag, pad2;
+ int scehysteresis, pad5;
+
} GameData;
#define STEREO_NOSTEREO 1
@@ -773,14 +873,15 @@ typedef struct GameData {
/* GameData.matmode */
enum {
+#ifdef DNA_DEPRECATED
GAME_MAT_TEXFACE = 0, /* deprecated */
+#endif
GAME_MAT_MULTITEX = 1,
GAME_MAT_GLSL = 2,
};
-#if (DNA_DEPRECATED_GCC_POISON == 1)
-#pragma GCC poison GAME_MAT_TEXFACE
-#endif
+/* GameData.lodflag */
+#define SCE_LOD_USE_HYST (1 << 0)
/* UV Paint */
#define UV_SCULPT_LOCK_BORDERS 1
@@ -793,6 +894,19 @@ enum {
#define UV_SCULPT_TOOL_RELAX_LAPLACIAN 1
#define UV_SCULPT_TOOL_RELAX_HC 2
+/* Stereo Flags */
+#define STEREO_RIGHT_NAME "right"
+#define STEREO_LEFT_NAME "left"
+#define STEREO_RIGHT_SUFFIX "_R"
+#define STEREO_LEFT_SUFFIX "_L"
+
+typedef enum StereoViews {
+ STEREO_LEFT_ID = 0,
+ STEREO_RIGHT_ID = 1,
+ STEREO_3D_ID = 2,
+ STEREO_MONO_ID = 3,
+} StereoViews;
+
/* Markers */
typedef struct TimeMarker {
@@ -812,6 +926,7 @@ typedef struct TimeMarker {
typedef struct Paint {
struct Brush *brush;
struct Palette *palette;
+ struct CurveMapping *cavity_curve; /* cavity curve */
/* WM Paint cursor */
void *paint_cursor;
@@ -826,6 +941,9 @@ typedef struct Paint {
/* flags used for symmetry */
int symmetry_flags;
+
+ float tile_offset[3];
+ int pad2;
} Paint;
/* ------------------------------------------- */
@@ -835,7 +953,7 @@ typedef struct Paint {
typedef struct ImagePaintSettings {
Paint paint;
- short flag, pad;
+ short flag, missing_data;
/* for projection painting only */
short seam_bleed, normal_angle;
@@ -848,7 +966,7 @@ typedef struct ImagePaintSettings {
struct Image *clone; /* clone layer for image mode for projective texture painting */
struct Image *canvas; /* canvas when the explicit system is used for painting */
float stencil_col[3];
- float pad1;
+ float dither; /* dither amount used when painting on byte images */
} ImagePaintSettings;
/* ------------------------------------------- */
@@ -881,6 +999,7 @@ typedef struct ParticleEditSettings {
struct Scene *scene;
struct Object *object;
+ struct Object *shape_object;
} ParticleEditSettings;
/* ------------------------------------------- */
@@ -909,9 +1028,10 @@ typedef struct Sculpt {
/* scale for constant detail size */
float constant_detail;
+ float detail_percent;
+ float pad;
struct Object *gravity_object;
- void *pad2;
} Sculpt;
typedef struct UvSculpt {
@@ -984,25 +1104,36 @@ typedef struct UnifiedPaintSettings {
/* record movement of mouse so that rake can start at an intuitive angle */
float last_rake[2];
+ float last_rake_angle;
+
+ int last_stroke_valid;
+ float average_stroke_accum[3];
+ int average_stroke_counter;
+
float brush_rotation;
+ float brush_rotation_sec;
/*********************************************************************************
* all data below are used to communicate with cursor drawing and tex sampling *
*********************************************************************************/
- int draw_anchored;
int anchored_size;
- char draw_inverted;
- char pad3[7];
-
float overlap_factor; /* normalization factor due to accumulated value of curve along spacing.
* Calculated when brush spacing changes to dampen strength of stroke
* if space attenuation is used*/
+ char draw_inverted;
+ /* check is there an ongoing stroke right now */
+ char stroke_active;
+
+ char draw_anchored;
+ char do_linear_conversion;
+
float anchored_initial_mouse[2];
- /* check is there an ongoing stroke right now */
- int stroke_active;
+ /* radius of brush, premultiplied with pressure.
+ * In case of anchored brushes contains the anchored radius */
+ float pixel_radius;
/* drawing pressure */
float size_pressure_value;
@@ -1014,13 +1145,7 @@ typedef struct UnifiedPaintSettings {
float mask_tex_mouse[2];
/* ColorSpace cache to avoid locking up during sampling */
- int do_linear_conversion;
struct ColorSpace *colorspace;
-
- /* radius of brush, premultiplied with pressure.
- * In case of anchored brushes contains the anchored radius */
- float pixel_radius;
- int pad4;
} UnifiedPaintSettings;
typedef enum {
@@ -1092,9 +1217,10 @@ typedef struct ToolSettings {
short autoik_chainlen; /* runtime only */
/* Grease Pencil */
- char gpencil_flags;
+ char gpencil_flags; /* flags/options for how the tool works */
+ char gpencil_src; /* for main 3D view Grease Pencil, where data comes from */
- char pad[5];
+ char pad[4];
/* Image Paint (8 byttse aligned please!) */
struct ImagePaintSettings imapaint;
@@ -1153,7 +1279,11 @@ typedef struct ToolSettings {
short snap_flag, snap_target;
short proportional, prop_mode;
char proportional_objects; /* proportional edit, object mode */
- char proportional_mask; /* proportional edit, object mode */
+ char proportional_mask; /* proportional edit, mask editing */
+ char proportional_action; /* proportional edit, action editor */
+ char proportional_fcurve; /* proportional edit, graph editor */
+ char lock_markers; /* lock marker editing */
+ char pad4[5];
char auto_normalize; /*auto normalizing mode in wpaint*/
char multipaint; /* paint multiple bones in wpaint */
@@ -1209,6 +1339,21 @@ typedef struct PhysicsSettings {
int flag, quick_cache_step, rt;
} PhysicsSettings;
+/* ------------------------------------------- */
+/* Safe Area options used in Camera View & VSE
+ */
+typedef struct DisplaySafeAreas {
+ /* each value represents the (x,y) margins as a multiplier.
+ * 'center' in this context is just the name for a different kind of safe-area */
+
+ float title[2]; /* Title Safe */
+ float action[2]; /* Image/Graphics Safe */
+
+ /* use for alternate aspect ratio */
+ float title_center[2];
+ float action_center[2];
+} DisplaySafeAreas;
+
/* *************************************************************** */
/* Scene ID-Block */
@@ -1244,6 +1389,7 @@ typedef struct Scene {
struct ToolSettings *toolsettings; /* default allocated now */
struct SceneStats *stats; /* default allocated now */
+ struct DisplaySafeAreas safe_areas;
/* migrate or replace? depends on some internal things... */
/* no, is on the right place (ton) */
@@ -1254,13 +1400,15 @@ typedef struct Scene {
ListBase transform_spaces;
void *sound_scene;
- void *sound_scene_handle;
+ void *playback_handle;
void *sound_scrub_handle;
void *speaker_handles;
void *fps_info; /* (runtime) info/cache used for presenting playback framerate info to the user */
/* none of the dependency graph vars is mean to be saved */
+ struct Depsgraph *depsgraph;
+ void *pad1;
struct DagForest *theDag;
short dagflags;
short recalc; /* recalc = counterpart of ob->recalc */
@@ -1295,6 +1443,8 @@ typedef struct Scene {
/* RigidBody simulation world+settings */
struct RigidBodyWorld *rigidbody_world;
+
+ struct PreviewImage *preview;
} Scene;
/* **************** RENDERDATA ********************* */
@@ -1399,6 +1549,7 @@ typedef struct Scene {
#define R_TEXNODE_PREVIEW 0x40000
#define R_VIEWPORT_PREVIEW 0x80000
#define R_EXR_CACHE_FILE 0x100000
+#define R_MULTIVIEW 0x200000
/* r->stamp */
#define R_STAMP_TIME 0x0001
@@ -1413,6 +1564,7 @@ typedef struct Scene {
#define R_STAMP_SEQSTRIP 0x0200
#define R_STAMP_RENDERTIME 0x0400
#define R_STAMP_CAMERALENS 0x0800
+#define R_STAMP_STRIPMETA 0x1000
#define R_STAMP_ALL (R_STAMP_TIME|R_STAMP_FRAME|R_STAMP_DATE|R_STAMP_CAMERA|R_STAMP_SCENE| \
R_STAMP_NOTE|R_STAMP_MARKER|R_STAMP_FILENAME|R_STAMP_SEQSTRIP| \
R_STAMP_RENDERTIME|R_STAMP_CAMERALENS)
@@ -1428,12 +1580,7 @@ enum {
/*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
-
+#ifdef DNA_DEPRECATED
/* subimtype, flag options for imtype */
enum {
R_OPENEXR_HALF = 1, /*deprecated*/
@@ -1448,10 +1595,6 @@ enum {
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 */
@@ -1483,7 +1626,10 @@ enum {
/* sequencer seq_prev_type seq_rend_type */
-
+/* scene->r.engine (scene.c) */
+extern const char *RE_engine_id_BLENDER_RENDER;
+extern const char *RE_engine_id_BLENDER_GAME;
+extern const char *RE_engine_id_CYCLES;
/* **************** SCENE ********************* */
@@ -1554,6 +1700,8 @@ enum {
#define SCE_SNAP_PEEL_OBJECT 4
#define SCE_SNAP_PROJECT 8
#define SCE_SNAP_NO_SELF 16
+#define SCE_SNAP_ABS_GRID 32
+
/* toolsettings->snap_target */
#define SCE_SNAP_TARGET_CLOSEST 0
#define SCE_SNAP_TARGET_CENTER 1
@@ -1598,7 +1746,8 @@ enum {
#define PROP_LIN 4
#define PROP_CONST 5
#define PROP_RANDOM 6
-#define PROP_MODE_MAX 7
+#define PROP_INVSQUARE 7
+#define PROP_MODE_MAX 8
/* toolsettings->proportional */
#define PROP_EDIT_OFF 0
@@ -1651,21 +1800,19 @@ typedef enum eVGroupSelect {
#define AUDIO_VOLUME_ANIMATED (1<<3)
enum {
+#ifdef DNA_DEPRECATED
FFMPEG_MULTIPLEX_AUDIO = 1, /* deprecated, you can choose none as audiocodec now */
+#endif
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 {
PAINT_SHOW_BRUSH = (1 << 0),
PAINT_FAST_NAVIGATE = (1 << 1),
- PAINT_SHOW_BRUSH_ON_SURFACE = (1 << 2)
+ PAINT_SHOW_BRUSH_ON_SURFACE = (1 << 2),
+ PAINT_USE_CAVITY_MASK = (1 << 3)
} PaintFlags;
/* Paint.symmetry_flags
@@ -1674,7 +1821,10 @@ typedef enum SymmetryFlags {
PAINT_SYMM_X = (1 << 0),
PAINT_SYMM_Y = (1 << 1),
PAINT_SYMM_Z = (1 << 2),
- PAINT_SYMMETRY_FEATHER = (1 << 3)
+ PAINT_SYMMETRY_FEATHER = (1 << 3),
+ PAINT_TILE_X = (1 << 4),
+ PAINT_TILE_Y = (1 << 5),
+ PAINT_TILE_Z = (1 << 6),
} SymmetryFlags;
#define PAINT_SYMM_AXIS_ALL (PAINT_SYMM_X | PAINT_SYMM_Y | PAINT_SYMM_Z)
@@ -1682,10 +1832,12 @@ typedef enum SymmetryFlags {
/* Sculpt.flags */
/* These can eventually be moved to paint flags? */
typedef enum SculptFlags {
+#ifdef DNA_DEPRECATED
/* deprecated, part of paint struct symmetry_flags now */
SCULPT_SYMM_X = (1 << 0),
SCULPT_SYMM_Y = (1 << 1),
SCULPT_SYMM_Z = (1 << 2),
+#endif
SCULPT_LOCK_X = (1 << 3),
SCULPT_LOCK_Y = (1 << 4),
@@ -1707,7 +1859,8 @@ typedef enum SculptFlags {
SCULPT_DYNTOPO_COLLAPSE = (1 << 11),
/* If set, dynamic-topology detail size will be constant in object space */
- SCULPT_DYNTOPO_DETAIL_CONSTANT = (1 << 13)
+ SCULPT_DYNTOPO_DETAIL_CONSTANT = (1 << 13),
+ SCULPT_DYNTOPO_DETAIL_BRUSH = (1 << 14),
} SculptFlags;
typedef enum ImagePaintMode {
@@ -1715,23 +1868,24 @@ typedef enum ImagePaintMode {
IMAGEPAINT_MODE_IMAGE, /* select texture paint image directly */
} ImagePaintMode;
-#if (DNA_DEPRECATED_GCC_POISON == 1)
-#pragma GCC poison SCULPT_SYMM_X SCULPT_SYMM_Y SCULPT_SYMM_Z SCULPT_SYMMETRY_FEATHER
-#endif
-
-
/* ImagePaintSettings.flag */
#define IMAGEPAINT_DRAWING 1
// #define IMAGEPAINT_DRAW_TOOL 2 // deprecated
// #define IMAGEPAINT_DRAW_TOOL_DRAWING 4 // deprecated
/* projection painting only */
-#define IMAGEPAINT_PROJECT_XRAY 16
-#define IMAGEPAINT_PROJECT_BACKFACE 32
-#define IMAGEPAINT_PROJECT_FLAT 64
-#define IMAGEPAINT_PROJECT_LAYER_CLONE 128
-#define IMAGEPAINT_PROJECT_LAYER_STENCIL 256
-#define IMAGEPAINT_PROJECT_LAYER_STENCIL_INV 512
+#define IMAGEPAINT_PROJECT_XRAY (1 << 4)
+#define IMAGEPAINT_PROJECT_BACKFACE (1 << 5)
+#define IMAGEPAINT_PROJECT_FLAT (1 << 6)
+#define IMAGEPAINT_PROJECT_LAYER_CLONE (1 << 7)
+#define IMAGEPAINT_PROJECT_LAYER_STENCIL (1 << 8)
+#define IMAGEPAINT_PROJECT_LAYER_STENCIL_INV (1 << 9)
+
+
+#define IMAGEPAINT_MISSING_UVS (1 << 0)
+#define IMAGEPAINT_MISSING_MATERIAL (1 << 1)
+#define IMAGEPAINT_MISSING_TEX (1 << 2)
+#define IMAGEPAINT_MISSING_STENCIL (1 << 3)
/* toolsettings->uvcalc_flag */
#define UVCALC_FILLHOLES 1
@@ -1760,6 +1914,12 @@ typedef enum ImagePaintMode {
/* toolsettings->gpencil_flags */
#define GP_TOOL_FLAG_PAINTSESSIONS_ON (1<<0)
+/* toolsettings->gpencil_src */
+typedef enum eGPencil_Source_3D {
+ GP_TOOL_SOURCE_SCENE = 0,
+ GP_TOOL_SOURCE_OBJECT = 1
+} eGPencil_Source_3d;
+
/* toolsettings->particle flag */
#define PE_KEEP_LENGTHS 1
#define PE_LOCK_FIRST 2
diff --git a/source/blender/makesdna/DNA_screen_types.h b/source/blender/makesdna/DNA_screen_types.h
index 8a900c3946e..45b3aad92e4 100644
--- a/source/blender/makesdna/DNA_screen_types.h
+++ b/source/blender/makesdna/DNA_screen_types.h
@@ -41,7 +41,6 @@ struct SpaceLink;
struct ARegion;
struct ARegionType;
struct PanelType;
-struct HeaderType;
struct Scene;
struct uiLayout;
struct wmTimer;
@@ -57,24 +56,24 @@ typedef struct bScreen {
struct Scene *scene;
struct Scene *newscene; /* temporary when switching */
- int redraws_flag; /* user-setting for which editors get redrawn during anim playback (used to be time->redraws) */
- int pad1;
-
- short full; /* temp screen for image render display or fileselect */
- short temp; /* temp screen in a temp window, don't save (like user prefs) */
short winid; /* winid from WM, starts with 1 */
- short do_draw; /* notifier for drawing edges */
- short do_refresh; /* notifier for scale screen, changed screen, etc */
- short do_draw_gesture; /* notifier for gesture draw. */
- short do_draw_paintcursor; /* notifier for paint cursor draw. */
- short do_draw_drag; /* notifier for dragging draw. */
- short swap; /* indicator to survive swap-exchange systems */
+ short redraws_flag; /* user-setting for which editors get redrawn during anim playback (used to be time->redraws) */
+
+ char temp; /* temp screen in a temp window, don't save (like user prefs) */
+ char state; /* temp screen for image render display or fileselect */
+ char do_draw; /* notifier for drawing edges */
+ char do_refresh; /* notifier for scale screen, changed screen, etc */
+ char do_draw_gesture; /* notifier for gesture draw. */
+ char do_draw_paintcursor; /* notifier for paint cursor draw. */
+ char do_draw_drag; /* notifier for dragging draw. */
+ char swap; /* indicator to survive swap-exchange systems */
+ char skip_handling; /* set to delay screen handling after switching back from maximized area */
+ char scrubbing; /* set when scrubbing to avoid some costly updates */
+ char pad[6];
short mainwin; /* screensize subwindow, for screenedges and global menus */
short subwinactive; /* active subwindow */
-
- short pad;
-
+
struct wmTimer *animtimer; /* if set, screen has timer handler added in window */
void *context; /* context callback */
} bScreen;
@@ -215,7 +214,7 @@ typedef struct ScrArea {
short do_refresh; /* private, for spacetype refresh callback */
short flag;
short region_active_win; /* index of last used region of 'RGN_TYPE_WINDOW'
- * runtuime variable, updated by executing operators */
+ * runtime variable, updated by executing operators */
char temp, pad;
struct SpaceType *type; /* callbacks for this space type */
@@ -247,7 +246,8 @@ typedef struct ARegion {
short do_draw_overlay; /* private, cached notifier events */
short swap; /* private, indicator to survive swap-exchange */
short overlap; /* private, set for indicate drawing overlapped */
- short pad[2];
+ short flagfullscreen; /* temporary copy of flag settings for clean fullscreen */
+ short pad;
struct ARegionType *type; /* callbacks for this region type */
@@ -271,12 +271,20 @@ typedef struct ARegion {
// #define WIN_EQUAL 3 // UNUSED
/* area->flag */
-#define HEADER_NO_PULLDOWN (1 << 0)
-#define AREA_FLAG_DRAWJOINTO (1 << 1)
-#define AREA_FLAG_DRAWJOINFROM (1 << 2)
-#define AREA_TEMP_INFO (1 << 3)
-#define AREA_FLAG_DRAWSPLIT_H (1 << 4)
-#define AREA_FLAG_DRAWSPLIT_V (1 << 5)
+enum {
+ HEADER_NO_PULLDOWN = (1 << 0),
+ AREA_FLAG_DRAWJOINTO = (1 << 1),
+ AREA_FLAG_DRAWJOINFROM = (1 << 2),
+ AREA_TEMP_INFO = (1 << 3),
+ AREA_FLAG_DRAWSPLIT_H = (1 << 4),
+ AREA_FLAG_DRAWSPLIT_V = (1 << 5),
+ /* used to check if we should switch back to prevspace (of a different type) */
+ AREA_FLAG_TEMP_TYPE = (1 << 6),
+ /* for temporary fullscreens (file browser, image editor render) that are opened above user set fullscreens */
+ AREA_FLAG_STACKED_FULLSCREEN = (1 << 7),
+ /* update action zones (even if the mouse is not intersecting them) */
+ AREA_FLAG_ACTIONZONES_UPDATE = (1 << 8),
+};
#define EDGEWIDTH 1
#define AREAGRID 4
@@ -287,9 +295,12 @@ typedef struct ARegion {
#define HEADERDOWN 1
#define HEADERTOP 2
-/* screen->full */
-#define SCREENNORMAL 0
-#define SCREENFULL 1
+/* screen->state */
+enum {
+ SCREENNORMAL = 0,
+ SCREENMAXIMIZED = 1, /* one editor taking over the screen */
+ SCREENFULL = 2, /* one editor taking over the screen with no bare-minimum UI elements */
+};
/* Panel->flag */
enum {
@@ -364,6 +375,8 @@ enum {
RGN_TYPE_TOOL_PROPS = 6,
RGN_TYPE_PREVIEW = 7
};
+/* use for function args */
+#define RGN_TYPE_ANY -1
/* region alignment */
#define RGN_ALIGN_NONE 0
diff --git a/source/blender/makesdna/DNA_sensor_types.h b/source/blender/makesdna/DNA_sensor_types.h
index 8d59a13768b..d886dcf2807 100644
--- a/source/blender/makesdna/DNA_sensor_types.h
+++ b/source/blender/makesdna/DNA_sensor_types.h
@@ -164,7 +164,7 @@ typedef struct bSensor {
struct bSensor *next, *prev;
/* pulse and freq are the bool toggle and frame count for pulse mode */
short type, otype, flag, pulse;
- short freq, totlinks, pad1, pad2;
+ short freq, totlinks, pad1, pad2; /* freq makes reference to skipped ticks between 2 active pulses */
char name[64]; /* MAX_NAME */
void *data;
diff --git a/source/blender/makesdna/DNA_sequence_types.h b/source/blender/makesdna/DNA_sequence_types.h
index 4795048d346..69e7fb43fb6 100644
--- a/source/blender/makesdna/DNA_sequence_types.h
+++ b/source/blender/makesdna/DNA_sequence_types.h
@@ -53,6 +53,11 @@ struct MovieClip;
/* strlens; 256= FILE_MAXFILE, 768= FILE_MAXDIR */
+typedef struct StripAnim {
+ struct StripAnim *next, *prev;
+ struct anim *anim;
+} StripAnim;
+
typedef struct StripElem {
char name[256];
int orig_width, orig_height;
@@ -94,6 +99,9 @@ typedef struct StripProxy {
// to build
short build_tc_flags; // time code flags (see below) of all tc indices
// to build
+ short build_flags;
+ char storage;
+ char pad[5];
} StripProxy;
typedef struct Strip {
@@ -131,10 +139,11 @@ typedef struct Sequence {
int flag, type; /*flags bitmap (see below) and the type of sequence*/
int len; /* the length of the contents of this strip - before handles are applied */
- int start, startofs, endofs;
- int startstill, endstill;
+ int start; /* start frame of contents of strip in absolute frame coordinates. For metastrips start of first strip startdisp */
+ int startofs, endofs; /* frames after the first frame where display starts, frames before the last frame where display ends */
+ int startstill, endstill; /* frames that use the first frame before data begins, frames that use the last frame after data ends */
int machine, depth; /*machine - the strip channel, depth - the depth in the sequence when dealing with metastrips */
- int startdisp, enddisp; /*starting and ending points in the sequence*/
+ int startdisp, enddisp; /* starting and ending points of the strip in the sequence*/
float sat;
float mul, handsize;
@@ -152,8 +161,7 @@ typedef struct Sequence {
struct Object *scene_camera; /* override scene camera */
struct MovieClip *clip; /* for MOVIECLIP strips */
struct Mask *mask; /* for MASK strips */
-
- struct anim *anim; /* for MOVIE strips */
+ ListBase anims; /* for MOVIE strips */
float effect_fader;
float speed_fader;
@@ -183,7 +191,13 @@ typedef struct Sequence {
int sfra; /* starting frame according to the timeline of the scene. */
char alpha_mode;
- char pad[3];
+ char pad[2];
+
+ /* Multiview */
+ char views_format;
+ struct Stereo3dFormat *stereo3d_format;
+
+ struct IDProperty *prop;
/* modifiers */
ListBase modifiers;
@@ -193,6 +207,8 @@ typedef struct MetaStack {
struct MetaStack *next, *prev;
ListBase *oldbasep;
Sequence *parseq;
+ /* the startdisp/enddisp when entering the meta */
+ int disp_range[2];
} MetaStack;
typedef struct Editing {
@@ -204,9 +220,10 @@ typedef struct Editing {
Sequence *act_seq;
char act_imagedir[1024]; /* 1024 = FILE_MAX */
char act_sounddir[1024]; /* 1024 = FILE_MAX */
+ char proxy_dir[1024]; /* 1024 = FILE_MAX */
int over_ofs, over_cfra;
- int over_flag, pad;
+ int over_flag, proxy_storage;
rctf over_border;
} Editing;
@@ -254,6 +271,35 @@ typedef struct GaussianBlurVars {
float size_y;
} GaussianBlurVars;
+typedef struct TextVars {
+ char text[512];
+ int text_size;
+ float loc[2];
+ float wrap_width;
+ char flag;
+ char align, align_y;
+ char pad[5];
+} TextVars;
+
+/* TextVars.flag */
+enum {
+ SEQ_TEXT_SHADOW = (1 << 0),
+};
+
+/* TextVars.align */
+enum {
+ SEQ_TEXT_ALIGN_X_LEFT = 0,
+ SEQ_TEXT_ALIGN_X_CENTER = 1,
+ SEQ_TEXT_ALIGN_X_RIGHT = 2,
+};
+
+/* TextVars.align_y */
+enum {
+ SEQ_TEXT_ALIGN_Y_TOP = 0,
+ SEQ_TEXT_ALIGN_Y_CENTER = 1,
+ SEQ_TEXT_ALIGN_Y_BOTTOM = 2,
+};
+
/* ***************** Sequence modifiers ****************** */
typedef struct SequenceModifierData {
@@ -321,6 +367,10 @@ typedef struct SequencerScopes {
#define SEQ_STRIP_OFSBOTTOM 0.2f
#define SEQ_STRIP_OFSTOP 0.8f
+/* Editor->proxy_storage */
+/* store proxies in project directory */
+#define SEQ_EDIT_PROXY_DIR_STORAGE 1
+
/* SpeedControlVars->flags */
#define SEQ_SPEED_INTEGRATE 1
/* #define SEQ_SPEED_BLEND 2 */ /* DEPRECATED */
@@ -336,7 +386,9 @@ enum {
SEQ_OVERLAP = (1 << 3),
SEQ_FILTERY = (1 << 4),
SEQ_MUTE = (1 << 5),
+#ifdef DNA_DEPRECATED
SEQ_MAKE_PREMUL = (1 << 6), /* deprecated, used for compatibility code only */
+#endif
SEQ_REVERSE_FRAMES = (1 << 7),
SEQ_IPO_FRAME_LOCKED = (1 << 8),
SEQ_EFFECT_NOT_LOADED = (1 << 9),
@@ -349,9 +401,9 @@ enum {
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_DIR = (1 << 19), */ /* DEPRECATED */
- SEQ_USE_PROXY_CUSTOM_FILE = (1 << 21),
+ /* SEQ_USE_PROXY_CUSTOM_FILE = (1 << 21), */ /* DEPRECATED */
SEQ_USE_EFFECT_DEFAULT_FADE = (1 << 22),
SEQ_USE_LINEAR_MODIFIERS = (1 << 23),
@@ -360,13 +412,19 @@ enum {
SEQ_AUDIO_PITCH_ANIMATED = (1 << 25),
SEQ_AUDIO_PAN_ANIMATED = (1 << 26),
SEQ_AUDIO_DRAW_WAVEFORM = (1 << 27),
+
+ /* don't include Grease Pencil in OpenGL previews of Scene strips */
+ SEQ_SCENE_NO_GPENCIL = (1 << 28),
+ SEQ_USE_VIEWS = (1 << 29),
SEQ_INVALID_EFFECT = (1 << 31),
};
-#if (DNA_DEPRECATED_GCC_POISON == 1)
-#pragma GCC poison SEQ_MAKE_PREMUL
-#endif
+/* StripProxy->storage */
+enum {
+ SEQ_STORAGE_PROXY_CUSTOM_FILE = (1 << 1), /* store proxy in custom directory */
+ SEQ_STORAGE_PROXY_CUSTOM_DIR = (1 << 2), /* store proxy in custom file */
+};
/* convenience define for all selection flags */
#define SEQ_ALLSEL (SELECT + SEQ_LEFTSEL + SEQ_RIGHTSEL)
@@ -392,6 +450,11 @@ enum {
#define SEQ_PROXY_TC_RECORD_RUN_NO_GAPS 8
#define SEQ_PROXY_TC_ALL 15
+/* SeqProxy->build_flags */
+enum {
+ SEQ_PROXY_SKIP_EXISTING = 1,
+};
+
/* seq->alpha_mode */
enum {
SEQ_ALPHA_STRAIGHT = 0,
@@ -427,7 +490,9 @@ enum {
SEQ_TYPE_MULTICAM = 30,
SEQ_TYPE_ADJUSTMENT = 31,
SEQ_TYPE_GAUSSIAN_BLUR = 40,
- SEQ_TYPE_EFFECT_MAX = 40
+ SEQ_TYPE_TEXT = 41,
+
+ SEQ_TYPE_MAX = 41
};
#define SEQ_MOVIECLIP_RENDER_UNDISTORTED (1 << 0)
diff --git a/source/blender/makesdna/DNA_smoke_types.h b/source/blender/makesdna/DNA_smoke_types.h
index 25c98b4f07e..5e011678fee 100644
--- a/source/blender/makesdna/DNA_smoke_types.h
+++ b/source/blender/makesdna/DNA_smoke_types.h
@@ -38,15 +38,13 @@ enum {
MOD_SMOKE_DISSOLVE = (1 << 2), /* let smoke dissolve */
MOD_SMOKE_DISSOLVE_LOG = (1 << 3), /* using 1/x for dissolve */
+#ifdef DNA_DEPRECATED
MOD_SMOKE_HIGH_SMOOTH = (1 << 5), /* -- Deprecated -- */
+#endif
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)
#define MOD_SMOKE_NOISEFFT (1<<1)
diff --git a/source/blender/makesdna/DNA_sound_types.h b/source/blender/makesdna/DNA_sound_types.h
index d7a51359777..aefe1a7d5a3 100644
--- a/source/blender/makesdna/DNA_sound_types.h
+++ b/source/blender/makesdna/DNA_sound_types.h
@@ -41,7 +41,6 @@
struct Ipo;
struct PackedFile;
-struct SpaceLink;
typedef struct bSound {
ID id;
@@ -95,6 +94,8 @@ typedef struct bSound {
*/
void *playback_handle;
+ /* spinlock for asynchronous loading of sounds */
+ void *spinlock;
/* XXX unused currently (SOUND_TYPE_LIMITER) */
/* float start, end; */
} bSound;
@@ -116,14 +117,13 @@ enum {
};
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
+#ifdef DNA_DEPRECATED
+ SOUND_FLAGS_3D = (1 << 3), /* deprecated! used for sound actuator loading */
#endif
+ SOUND_FLAGS_CACHING = (1 << 4),
+ SOUND_FLAGS_MONO = (1 << 5),
+ SOUND_FLAGS_WAVEFORM_LOADING = (1 << 6),
+};
/* to DNA_sound_types.h*/
diff --git a/source/blender/makesdna/DNA_space_types.h b/source/blender/makesdna/DNA_space_types.h
index 6f57f549efb..b8f2ce1b2ea 100644
--- a/source/blender/makesdna/DNA_space_types.h
+++ b/source/blender/makesdna/DNA_space_types.h
@@ -50,29 +50,21 @@
struct ID;
struct Text;
struct Script;
-struct bSound;
-struct ImBuf;
struct Image;
struct Scopes;
struct Histogram;
struct SpaceIpo;
-struct BlendHandle;
-struct RenderInfo;
struct bNodeTree;
-struct uiBlock;
struct FileList;
struct bGPdata;
struct bDopeSheet;
struct FileSelectParams;
struct FileLayout;
-struct bScreen;
-struct Scene;
struct wmOperator;
struct wmTimer;
struct MovieClip;
struct MovieClipScopes;
struct Mask;
-struct GHash;
struct BLI_mempool;
@@ -274,6 +266,7 @@ typedef enum eSpaceOutliner_Flag {
SO_NEWSELECTED = (1 << 1),
SO_HIDE_RESTRICTCOLS = (1 << 2),
SO_HIDE_KEYINGSETINFO = (1 << 3),
+ SO_SKIP_SORT_ALPHA = (1 << 4),
} eSpaceOutliner_Flag;
/* SpaceOops->outlinevis */
@@ -292,14 +285,18 @@ typedef enum eSpaceOutliner_Mode {
SO_DATABLOCKS = 11,
SO_USERDEF = 12,
/* SO_KEYMAP = 13, */ /* deprecated! */
+ SO_ID_ORPHANS = 14,
} eSpaceOutliner_Mode;
/* SpaceOops->storeflag */
typedef enum eSpaceOutliner_StoreFlag {
- /* rebuild tree */
+ /* cleanup tree */
SO_TREESTORE_CLEANUP = (1 << 0),
/* if set, it allows redraws. gets set for some allqueue events */
SO_TREESTORE_REDRAW = (1 << 1),
+ /* rebuild the tree, similar to cleanup,
+ * but defer a call to BKE_outliner_treehash_rebuild_from_treestore instead */
+ SO_TREESTORE_REBUILD = (1 << 2),
} eSpaceOutliner_StoreFlag;
/* outliner search flags (SpaceOops->search_flags) */
@@ -462,6 +459,8 @@ typedef enum eScreen_Redraws_Flag {
// TIME_CONTINUE_PHYSICS = (1 << 7), /* UNUSED */
TIME_NODES = (1 << 8),
TIME_CLIPS = (1 << 9),
+
+ TIME_FOLLOW = (1 << 15),
} eScreen_Redraws_Flag;
/* time->cache */
@@ -491,17 +490,22 @@ typedef struct SpaceSeq {
float xof DNA_DEPRECATED, yof DNA_DEPRECATED; /* deprecated: offset for drawing the image preview */
short mainb; /* weird name for the sequencer subtype (seq, image, luma... etc) */
- short render_size;
+ short render_size; /* eSpaceSeq_Proxy_RenderSize */
short chanshown;
short zebra;
int flag;
float zoom DNA_DEPRECATED; /* deprecated, handled by View2D now */
int view; /* see SEQ_VIEW_* below */
int overlay_type;
+ int draw_flag; /* overlay an image of the editing on below the strips */
+ int pad;
struct bGPdata *gpd; /* grease-pencil data */
struct SequencerScopes scopes; /* different scoped displayed in space */
+
+ char multiview_eye; /* multiview current eye - for internal use */
+ char pad2[7];
} SpaceSeq;
@@ -514,15 +518,26 @@ typedef enum eSpaceSeq_RegionType {
SEQ_DRAW_IMG_HISTOGRAM = 4,
} eSpaceSeq_RegionType;
+/* sseq->draw_flag */
+typedef enum eSpaceSeq_DrawFlag {
+ SEQ_DRAW_BACKDROP = (1 << 0),
+ SEQ_DRAW_OFFSET_EXT = (1 << 1),
+} eSpaceSeq_DrawFlag;
+
+
/* sseq->flag */
typedef enum eSpaceSeq_Flag {
SEQ_DRAWFRAMES = (1 << 0),
SEQ_MARKER_TRANS = (1 << 1),
SEQ_DRAW_COLOR_SEPARATED = (1 << 2),
- SEQ_DRAW_SAFE_MARGINS = (1 << 3),
+ SEQ_SHOW_SAFE_MARGINS = (1 << 3),
SEQ_SHOW_GPENCIL = (1 << 4),
SEQ_NO_DRAW_CFRANUM = (1 << 5),
SEQ_USE_ALPHA = (1 << 6), /* use RGBA display mode for preview */
+ SEQ_ALL_WAVEFORMS = (1 << 7), /* draw all waveforms */
+ SEQ_NO_WAVEFORMS = (1 << 8), /* draw no waveforms */
+ SEQ_SHOW_SAFE_CENTER = (1 << 9),
+ SEQ_SHOW_METADATA = (1 << 10),
} eSpaceSeq_Flag;
/* sseq->view */
@@ -543,8 +558,7 @@ typedef enum eSpaceSeq_Proxy_RenderSize {
SEQ_PROXY_RENDER_SIZE_FULL = 100
} eSpaceSeq_Proxy_RenderSize;
-typedef struct MaskSpaceInfo
-{
+typedef struct MaskSpaceInfo {
/* **** mask editing **** */
struct Mask *mask;
/* draw options */
@@ -566,24 +580,33 @@ typedef enum eSpaceSeq_OverlayType {
/* Config and Input for File Selector */
typedef struct FileSelectParams {
char title[96]; /* title, also used for the text of the execute button */
- char dir[1056]; /* directory, FILE_MAX_LIBEXTRA, 1024 + 32, this is for extreme case when 1023 length path
+ char dir[1090]; /* directory, FILE_MAX_LIBEXTRA, 1024 + 66, this is for extreme case when 1023 length path
* needs to be linked in, where foo.blend/Armature need adding */
+ char pad_c1[2];
char file[256]; /* file */
char renamefile[256];
char renameedit[256]; /* annoying but the first is only used for initialization */
char filter_glob[64]; /* list of filetypes to filter */
- int active_file;
+ char filter_search[64]; /* text items' name must match to be shown. */
+ int filter_id; /* same as filter, but for ID types (aka library groups). */
+
+ int active_file; /* active file used for keyboard navigation */
+ int highlight_file; /* file under cursor */
int sel_first;
int sel_last;
+ unsigned short thumbnail_size;
+ short pad;
/* short */
short type; /* XXXXX for now store type here, should be moved to the operator */
short flag; /* settings for filter, hiding dots files,... */
short sort; /* sort order */
short display; /* display mode flag */
- short filter; /* filter when (flags & FILE_FILTER) is true */
+ int filter; /* filter when (flags & FILE_FILTER) is true */
+
+ short recursion_level; /* max number of levels in dirtree to show at once, 0 to disable recursion. */
/* XXX --- still unused -- */
short f_fp; /* show font preview */
@@ -615,13 +638,24 @@ typedef struct SpaceFile {
struct wmOperator *op;
struct wmTimer *smoothscroll_timer;
+ struct wmTimer *previews_timer;
struct FileLayout *layout;
short recentnr, bookmarknr;
- short systemnr, pad2;
+ short systemnr, system_bookmarknr;
} SpaceFile;
+/* FSMenuEntry's without paths indicate seperators */
+typedef struct FSMenuEntry {
+ struct FSMenuEntry *next;
+
+ char *path;
+ char name[256]; /* FILE_MAXFILE */
+ short save;
+ short valid;
+ short pad[2];
+} FSMenuEntry;
/* FileSelectParams.display */
enum FileDisplayTypeE {
@@ -679,32 +713,151 @@ typedef enum eFileSel_Params_Flag {
} eFileSel_Params_Flag;
-/* files in filesel list: file types */
+/* files in filesel list: file types
+ * Note we could use mere values (instead of bitflags) for file types themselves,
+ * but since we do not lack of bytes currently...
+ */
typedef enum eFileSel_File_Types {
- BLENDERFILE = (1 << 2),
- BLENDERFILE_BACKUP = (1 << 3),
- IMAGEFILE = (1 << 4),
- MOVIEFILE = (1 << 5),
- PYSCRIPTFILE = (1 << 6),
- FTFONTFILE = (1 << 7),
- SOUNDFILE = (1 << 8),
- TEXTFILE = (1 << 9),
- MOVIEFILE_ICON = (1 << 10), /* movie file that preview can't load */
- FOLDERFILE = (1 << 11), /* represents folders for filtering */
- BTXFILE = (1 << 12),
- COLLADAFILE = (1 << 13),
- OPERATORFILE = (1 << 14), /* from filter_glob operator property */
- APPLICATIONBUNDLE = (1 << 15),
+ FILE_TYPE_BLENDER = (1 << 2),
+ FILE_TYPE_BLENDER_BACKUP = (1 << 3),
+ FILE_TYPE_IMAGE = (1 << 4),
+ FILE_TYPE_MOVIE = (1 << 5),
+ FILE_TYPE_PYSCRIPT = (1 << 6),
+ FILE_TYPE_FTFONT = (1 << 7),
+ FILE_TYPE_SOUND = (1 << 8),
+ FILE_TYPE_TEXT = (1 << 9),
+ /* 1 << 10 was FILE_TYPE_MOVIE_ICON, got rid of this so free slot for future type... */
+ FILE_TYPE_FOLDER = (1 << 11), /* represents folders for filtering */
+ FILE_TYPE_BTX = (1 << 12),
+ FILE_TYPE_COLLADA = (1 << 13),
+ FILE_TYPE_OPERATOR = (1 << 14), /* from filter_glob operator property */
+ FILE_TYPE_APPLICATIONBUNDLE = (1 << 15),
+
+ FILE_TYPE_DIR = (1 << 30), /* An FS directory (i.e. S_ISDIR on its path is true). */
+ FILE_TYPE_BLENDERLIB = (1 << 31),
} eFileSel_File_Types;
/* Selection Flags in filesel: struct direntry, unsigned char selflag */
typedef enum eDirEntry_SelectFlag {
-/* ACTIVE_FILE = (1 << 1), */ /* UNUSED */
- HILITED_FILE = (1 << 2),
- SELECTED_FILE = (1 << 3),
- EDITING_FILE = (1 << 4),
+/* FILE_SEL_ACTIVE = (1 << 1), */ /* UNUSED */
+ FILE_SEL_HIGHLIGHTED = (1 << 2),
+ FILE_SEL_SELECTED = (1 << 3),
+ FILE_SEL_EDITING = (1 << 4),
} eDirEntry_SelectFlag;
+#define FILE_LIST_MAX_RECURSION 4
+
+/* ***** Related to file browser, but never saved in DNA, only here to help with RNA. ***** */
+
+/* About Unique identifier.
+ * Stored in a CustomProps once imported.
+ * Each engine is free to use it as it likes - it will be the only thing passed to it by blender to identify
+ * asset/variant/version (concatenating the three into a single 48 bytes one).
+ * Assumed to be 128bits, handled as four integers due to lack of real bytes proptype in RNA :|.
+ */
+#define ASSET_UUID_LENGTH 16
+
+/* Used to communicate with asset engines outside of 'import' context. */
+typedef struct AssetUUID {
+ int uuid_asset[4];
+ int uuid_variant[4];
+ int uuid_revision[4];
+} AssetUUID;
+
+typedef struct AssetUUIDList {
+ AssetUUID *uuids;
+ int nbr_uuids, pad;
+} AssetUUIDList;
+
+/* Container for a revision, only relevant in asset context. */
+typedef struct FileDirEntryRevision {
+ struct FileDirEntryRevision *next, *prev;
+
+ char *comment;
+ void *pad;
+
+ int uuid[4];
+
+ uint64_t size;
+ int64_t time;
+ /* Temp caching of UI-generated strings... */
+ char size_str[16];
+ char time_str[8];
+ char date_str[16];
+} FileDirEntryRevision;
+
+/* Container for a variant, only relevant in asset context.
+ * In case there are no variants, a single one shall exist, with NULL name/description. */
+typedef struct FileDirEntryVariant {
+ struct FileDirEntryVariant *next, *prev;
+
+ int uuid[4];
+ char *name;
+ char *description;
+
+ ListBase revisions;
+ int nbr_revisions;
+ int act_revision;
+} FileDirEntryVariant;
+
+/* Container for mere direntry, with additional asset-related data. */
+typedef struct FileDirEntry {
+ struct FileDirEntry *next, *prev;
+
+ int uuid[4];
+ char *name;
+ char *description;
+
+ /* Either point to active variant/revision if available, or own entry (in mere filebrowser case). */
+ FileDirEntryRevision *entry;
+
+ int typeflag; /* eFileSel_File_Types */
+ int blentype; /* ID type, in case typeflag has FILE_TYPE_BLENDERLIB set. */
+
+ char *relpath;
+
+ void *poin; /* TODO: make this a real ID pointer? */
+ struct ImBuf *image;
+
+ /* Tags are for info only, most of filtering is done in asset engine. */
+ char **tags;
+ int nbr_tags;
+
+ short status;
+ short flags;
+
+ ListBase variants;
+ int nbr_variants;
+ int act_variant;
+} FileDirEntry;
+
+/* Array of direntries. */
+/* This struct is used in various, different contexts.
+ * In Filebrowser UI, it stores the total number of available entries, the number of visible (filtered) entries,
+ * and a subset of those in 'entries' ListBase, from idx_start (included) to idx_end (excluded).
+ * In AssetEngine context (i.e. outside of 'browsing' context), entries contain all needed data, there is no filtering,
+ * so nbr_entries_filtered, entry_idx_start and entry_idx_end should all be set to -1.
+ */
+typedef struct FileDirEntryArr {
+ ListBase entries;
+ int nbr_entries;
+ int nbr_entries_filtered;
+ int entry_idx_start, entry_idx_end;
+
+ char root[1024]; /* FILE_MAX */
+} FileDirEntryArr;
+
+/* FileDirEntry.status */
+enum {
+ ASSET_STATUS_LOCAL = 1 << 0, /* If active uuid is available localy/immediately. */
+ ASSET_STATUS_LATEST = 1 << 1, /* If active uuid is latest available version. */
+};
+
+/* FileDirEntry.flags */
+enum {
+ FILE_ENTRY_INVALID_PREVIEW = 1 << 0, /* The preview for this entry could not be generated. */
+};
+
/* Image/UV Editor ======================================== */
/* Image/UV Editor */
@@ -810,7 +963,8 @@ typedef enum eSpaceImage_Flag {
SI_COLOR_CORRECTION = (1 << 24),
- SI_NO_DRAW_TEXPAINT = (1 << 25)
+ SI_NO_DRAW_TEXPAINT = (1 << 25),
+ SI_DRAW_METADATA = (1 << 26)
} eSpaceImage_Flag;
/* Text Editor ============================================ */
@@ -919,7 +1073,7 @@ typedef struct bNodeTreePath {
bNodeInstanceKey parent_key; /* base key for nodes in this tree instance */
int pad;
float view_center[2]; /* v2d center point, so node trees can have different offsets in editors */
- /* XXX this is not automatically updated when node names are changed! */
+
char node_name[64]; /* MAX_NAME */
} bNodeTreePath;
@@ -954,12 +1108,17 @@ typedef struct SpaceNode {
int treetype DNA_DEPRECATED; /* treetype: as same nodetree->type */
int pad3;
- short texfrom; /* texfrom object, world or brush */
- short shaderfrom; /* shader from object or world */
- short recalc; /* currently on 0/1, for auto compo */
- short pad4;
- ListBase linkdrag; /* temporary data for modal linking operator */
-
+ short texfrom; /* texfrom object, world or brush */
+ short shaderfrom; /* shader from object or world */
+ short recalc; /* currently on 0/1, for auto compo */
+
+ char insert_ofs_dir; /* direction for offsetting nodes on insertion */
+ char pad4;
+
+ ListBase linkdrag; /* temporary data for modal linking operator */
+ /* XXX hack for translate_attach op-macros to pass data from transform op to insert_offset op */
+ struct NodeInsertOfsData *iofsd; /* temporary data for node insert offset (in UI called Auto-offset) */
+
struct bGPdata *gpd; /* grease-pencil data */
} SpaceNode;
@@ -975,8 +1134,9 @@ typedef enum eSpaceNode_Flag {
SNODE_AUTO_RENDER = (1 << 5),
SNODE_SHOW_HIGHLIGHT = (1 << 6),
// SNODE_USE_HIDDEN_PREVIEW = (1 << 10), DNA_DEPRECATED December2013
- SNODE_NEW_SHADERS = (1 << 11),
+ SNODE_NEW_SHADERS = (1 << 11),
SNODE_PIN = (1 << 12),
+ SNODE_SKIP_INSOFFSET = (1 << 13), /* automatically offset following nodes in a chain on insertion */
} eSpaceNode_Flag;
/* snode->texfrom */
@@ -994,6 +1154,12 @@ typedef enum eSpaceNode_ShaderFrom {
SNODE_SHADER_LINESTYLE = 2,
} eSpaceNode_ShaderFrom;
+/* snode->insert_ofs_dir */
+enum {
+ SNODE_INSERTOFS_DIR_RIGHT = 0,
+ SNODE_INSERTOFS_DIR_LEFT = 1,
+};
+
/* Game Logic Editor ===================================== */
/* Logic Editor */
@@ -1134,6 +1300,7 @@ typedef enum eSpaceClip_Flag {
SC_SHOW_GRAPH_SEL_ONLY = (1 << 19),
SC_SHOW_GRAPH_HIDDEN = (1 << 20),
SC_SHOW_GRAPH_TRACKS_ERROR = (1 << 21),
+ SC_SHOW_METADATA = (1 << 22),
} eSpaceClip_Flag;
/* SpaceClip->mode */
@@ -1172,10 +1339,13 @@ typedef enum eSpace_Type {
SPACE_INFO = 7,
SPACE_SEQ = 8,
SPACE_TEXT = 9,
+#ifdef DNA_DEPRECATED
SPACE_IMASEL = 10, /* deprecated */
SPACE_SOUND = 11, /* Deprecated */
+#endif
SPACE_ACTION = 12,
SPACE_NLA = 13,
+ /* TODO: fully deprecate */
SPACE_SCRIPT = 14, /* Deprecated */
SPACE_TIME = 15,
SPACE_NODE = 16,
@@ -1187,10 +1357,9 @@ 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
+/* use for function args */
+#define SPACE_TYPE_ANY -1
+
#define IMG_SIZE_FALLBACK 256
diff --git a/source/blender/makesdna/DNA_texture_types.h b/source/blender/makesdna/DNA_texture_types.h
index d256cfb2e85..af6adbecd83 100644
--- a/source/blender/makesdna/DNA_texture_types.h
+++ b/source/blender/makesdna/DNA_texture_types.h
@@ -62,11 +62,12 @@ typedef struct MTex {
char uvname[64]; /* MAX_CUSTOMDATA_LAYER_NAME */
char projx, projy, projz, mapping;
- float ofs[3], size[3], rot;
-
+ char brush_map_mode, brush_angle_mode;
+ char pad[2];
+ float ofs[3], size[3], rot, random_angle;
+
short texflag, colormodel, pmapto, pmaptoneg;
short normapspace, which_output;
- char brush_map_mode, pad[7];
float r, g, b, k;
float def_var, rt;
@@ -83,8 +84,9 @@ typedef struct MTex {
/* particles */
float timefac, lengthfac, clumpfac, dampfac;
- float kinkfac, roughfac, padensfac, gravityfac;
+ float kinkfac, kinkampfac, roughfac, padensfac, gravityfac;
float lifefac, sizefac, ivelfac, fieldfac;
+ int pad2;
/* lamp */
float shadowfac;
@@ -174,8 +176,8 @@ typedef struct VoxelData {
short flag;
short extend;
short smoked_type;
+ short hair_type;
short data_type;
- short pad;
int _pad;
struct Object *object; /* for rendering smoke sims */
@@ -512,6 +514,10 @@ typedef struct ColorMapping {
#define MTEX_MAP_MODE_RANDOM 4
#define MTEX_MAP_MODE_STENCIL 5
+/* brush_angle_mode */
+#define MTEX_ANGLE_RANDOM 1
+#define MTEX_ANGLE_RAKE 2
+
/* **************** ColorBand ********************* */
/* colormode */
@@ -612,6 +618,7 @@ enum {
#define TEX_VD_RAW_16BIT 2
#define TEX_VD_IMAGE_SEQUENCE 3
#define TEX_VD_SMOKE 4
+#define TEX_VD_HAIR 5
/* for voxels which use VoxelData->source_path */
#define TEX_VD_IS_SOURCE_PATH(_format) (ELEM(_format, TEX_VD_BLENDERVOXEL, TEX_VD_RAW_8BIT, TEX_VD_RAW_16BIT))
@@ -621,6 +628,11 @@ enum {
#define TEX_VD_SMOKEVEL 2
#define TEX_VD_SMOKEFLAME 3
+#define TEX_VD_HAIRDENSITY 0
+#define TEX_VD_HAIRVELOCITY 1
+#define TEX_VD_HAIRENERGY 2
+#define TEX_VD_HAIRRESTDENSITY 3
+
/* data_type */
#define TEX_VD_INTENSITY 0
#define TEX_VD_RGBA_PREMUL 1
diff --git a/source/blender/makesdna/DNA_tracking_types.h b/source/blender/makesdna/DNA_tracking_types.h
index c471cb26892..9888b735b8b 100644
--- a/source/blender/makesdna/DNA_tracking_types.h
+++ b/source/blender/makesdna/DNA_tracking_types.h
@@ -43,11 +43,9 @@
/* match-moving data */
struct bGPdata;
-struct ImBuf;
struct Image;
struct MovieReconstructedCamera;
struct MovieTrackingCamera;
-struct MovieTrackingBundle;
struct MovieTrackingMarker;
struct MovieTrackingTrack;
struct MovieTracking;
diff --git a/source/blender/makesdna/DNA_userdef_types.h b/source/blender/makesdna/DNA_userdef_types.h
index ed59014cf75..00dc1c1205e 100644
--- a/source/blender/makesdna/DNA_userdef_types.h
+++ b/source/blender/makesdna/DNA_userdef_types.h
@@ -74,7 +74,8 @@ typedef struct uiFontStyle {
short uifont_id; /* saved in file, 0 is default */
short points; /* actual size depends on 'global' dpi */
short kerning; /* unfitted or default kerning value. */
- char pad[6];
+ char word_wrap; /* enable word-wrap when drawing */
+ char pad[5];
short italic, bold; /* style hint */
short shadow; /* value is amount of pixels blur */
short shadx, shady; /* shadow offset in pixels */
@@ -168,11 +169,13 @@ typedef struct ThemeUI {
uiPanelColors panel; /* depricated, but we keep it for do_versions (2.66.1) */
+ char widget_emboss[4];
+
/* fac: 0 - 1 for blend factor, width in pixels */
float menu_shadow_fac;
short menu_shadow_width;
- short pad;
+ short pad[3];
char iconfile[256]; // FILE_MAXFILE length
float icon_alpha;
@@ -249,6 +252,7 @@ typedef struct ThemeSpace {
char bone_solid[4], bone_pose[4], bone_pose_active[4];
char strip[4], strip_select[4];
char cframe[4];
+ char time_keyframe[4], time_gp_keyframe[4];
char freestyle_edge_mark[4], freestyle_face_mark[4];
char nurb_uline[4], nurb_vline[4];
@@ -285,15 +289,19 @@ typedef struct ThemeSpace {
char handle_vertex[4];
char handle_vertex_select[4];
- char pad2[4];
char handle_vertex_size;
+
+ char clipping_border_3d[4];
char marker_outline[4], marker[4], act_marker[4], sel_marker[4], dis_marker[4], lock_marker[4];
char bundle_solid[4];
char path_before[4], path_after[4];
char camera_path[4];
- char hpad[3];
+ char hpad[2];
+
+ char gp_vertex_size;
+ char gp_vertex[4], gp_vertex_select[4];
char preview_back[4];
char preview_stitch_face[4];
@@ -331,6 +339,9 @@ typedef struct ThemeSpace {
char paint_curve_pivot[4];
char paint_curve_handle[4];
+
+ char metadatabg[4];
+ char metadatatext[4];
} ThemeSpace;
@@ -455,7 +466,8 @@ typedef struct UserDef {
int scrollback; /* console scrollback limit */
int dpi; /* range 48-128? */
- short encoding;
+ char node_margin; /* node insert offset (aka auto-offset) margin, but might be useful for later stuff as well */
+ char pad2;
short transopts;
short menuthreshold1, menuthreshold2;
@@ -480,8 +492,9 @@ typedef struct UserDef {
short dragthreshold;
int memcachelimit;
int prefetchframes;
+ float pad_rot_angle; /* control the rotation step of the view when PAD2, PAD4, PAD6&PAD8 is use */
short frameserverport;
- short pad_rot_angle; /* control the rotation step of the view when PAD2, PAD4, PAD6&PAD8 is use */
+ short pad4;
short obcenter_dia;
short rvisize; /* rotating view icon size */
short rvibright; /* rotating view icon brightness */
@@ -493,7 +506,10 @@ typedef struct UserDef {
char ipo_new; /* interpolation mode for newly added F-Curves */
char keyhandles_new; /* handle types for newly added keyframes */
char gpu_select_method;
- char pad1;
+ char view_frame_type;
+
+ int view_frame_keyframes; /* number of keyframes to zoom around current frame */
+ float view_frame_seconds; /* seconds to zoom around current frame */
short scrcastfps; /* frame rate for screencast to be played back */
short scrcastwait; /* milliseconds between screencast snapshots */
@@ -504,6 +520,7 @@ typedef struct UserDef {
float ndof_sensitivity; /* overall sensitivity of 3D mouse */
float ndof_orbit_sensitivity;
+ float ndof_deadzone; /* deadzone of 3D mouse */
int ndof_flag; /* flags for 3D mouse */
short ogl_multisamples; /* amount of samples for OpenGL FSA, if zero no FSA */
@@ -534,17 +551,21 @@ 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 */
+ int virtual_pixel; /* virtual pixelsize mode */
short pie_interaction_type; /* if keeping a pie menu spawn button pressed after this time, it turns into
* a drag/release pie menu */
short pie_initial_timeout; /* direction in the pie menu will always be calculated from the initial position
* within this time limit */
- int pie_animation_timeout;
- int pad2;
+ short pie_animation_timeout;
+ short pie_menu_confirm;
short pie_menu_radius; /* pie menu radius */
short pie_menu_threshold; /* pie menu distance from center before a direction is set */
struct WalkNavigation walk_navigation;
+
+ short opensubdiv_compute_type;
+ char pad5[6];
} UserDef;
extern UserDef U; /* from blenkernel blender.c */
@@ -659,9 +680,10 @@ typedef enum eUserpref_UI_Flag {
/* uiflag2 */
typedef enum eUserpref_UI_Flag2 {
- USER_KEEP_SESSION = (1 << 0),
- USER_REGION_OVERLAP = (1 << 1),
- USER_TRACKPAD_NATURAL = (1 << 2)
+ USER_KEEP_SESSION = (1 << 0),
+ USER_REGION_OVERLAP = (1 << 1),
+ USER_TRACKPAD_NATURAL = (1 << 2),
+ USER_OPENGL_NO_WARN_SUPPORT = (1 << 3)
} eUserpref_UI_Flag2;
/* Auto-Keying mode */
@@ -674,6 +696,13 @@ typedef enum eAutokey_Mode {
AUTOKEY_MODE_EDITKEYS = 5
} eAutokey_Mode;
+/* Zoom to frame mode */
+typedef enum eZoomFrame_Mode {
+ ZOOM_FRAME_MODE_KEEP_RANGE = 0,
+ ZOOM_FRAME_MODE_SECONDS = 1,
+ ZOOM_FRAME_MODE_KEYFRAMES = 2
+} eZoomFrame_Mode;
+
/* Auto-Keying flag
* U.autokey_flag (not strictly used when autokeying only - is also used when keyframing these days)
* note: AUTOKEY_FLAG_* is used with a macro, search for lines like IS_AUTOKEY_FLAG(INSERTAVAIL)
@@ -854,6 +883,21 @@ typedef enum eImageDrawMethod {
IMAGE_DRAW_METHOD_DRAWPIXELS = 3,
} eImageDrawMethod;
+typedef enum eUserpref_VirtualPixel {
+ VIRTUAL_PIXEL_NATIVE = 0,
+ VIRTUAL_PIXEL_DOUBLE = 1,
+} eUserpref_VirtualPixel;
+
+typedef enum eOpensubdiv_Computee_Type {
+ USER_OPENSUBDIV_COMPUTE_NONE = 0,
+ USER_OPENSUBDIV_COMPUTE_CPU = 1,
+ USER_OPENSUBDIV_COMPUTE_OPENMP = 2,
+ USER_OPENSUBDIV_COMPUTE_OPENCL = 3,
+ USER_OPENSUBDIV_COMPUTE_CUDA = 4,
+ USER_OPENSUBDIV_COMPUTE_GLSL_TRANSFORM_FEEDBACK = 5,
+ USER_OPENSUBDIV_COMPUTE_GLSL_COMPUTE = 6,
+} eOpensubdiv_Computee_Type;
+
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/makesdna/DNA_view2d_types.h b/source/blender/makesdna/DNA_view2d_types.h
index a7921be44d5..6f2e347c84d 100644
--- a/source/blender/makesdna/DNA_view2d_types.h
+++ b/source/blender/makesdna/DNA_view2d_types.h
@@ -43,7 +43,7 @@ typedef struct View2D {
rcti mask; /* mask - region (in screenspace) within which 'cur' can be viewed */
float min[2], max[2]; /* min/max sizes of 'cur' rect (only when keepzoom not set) */
- float minzoom, maxzoom; /* self explanatory. allowable zoom factor range (only when keepzoom set) */
+ float minzoom, maxzoom; /* allowable zoom factor range (only when (keepzoom & V2D_LIMITZOOM)) is set */
short scroll; /* scroll - scrollbars to display (bitflag) */
short scroll_ui; /* scroll_ui - temp settings used for UI drawing of scrollers */
diff --git a/source/blender/makesdna/DNA_view3d_types.h b/source/blender/makesdna/DNA_view3d_types.h
index 98c12e9cc11..0ba6c4dcf01 100644
--- a/source/blender/makesdna/DNA_view3d_types.h
+++ b/source/blender/makesdna/DNA_view3d_types.h
@@ -35,18 +35,16 @@
struct ViewDepths;
struct Object;
struct Image;
-struct Tex;
struct SpaceLink;
-struct Base;
struct BoundBox;
struct MovieClip;
struct MovieClipUser;
-struct RenderInfo;
struct RenderEngine;
struct bGPdata;
struct SmoothView3DStore;
struct wmTimer;
struct Material;
+struct GPUFX;
/* This is needed to not let VC choke on near and far... old
* proprietary MS extensions... */
@@ -61,6 +59,7 @@ struct Material;
#include "DNA_listBase.h"
#include "DNA_image_types.h"
#include "DNA_movieclip_types.h"
+#include "DNA_gpu_types.h"
/* ******************************** */
@@ -75,10 +74,11 @@ typedef struct BGpic {
struct ImageUser iuser;
struct MovieClip *clip;
struct MovieClipUser cuser;
- float xof, yof, size, blend;
+ float xof, yof, size, blend, rotation;
short view;
short flag;
- short source, pad;
+ short source;
+ char pad[6];
} BGpic;
/* ********************************* */
@@ -90,19 +90,18 @@ typedef struct RegionView3D {
float viewinv[4][4]; /* inverse of viewmat */
float persmat[4][4]; /* viewmat*winmat */
float persinv[4][4]; /* inverse of persmat */
+ float viewcamtexcofac[4]; /* offset/scale for camera glsl texcoords */
/* viewmat/persmat multiplied with object matrix, while drawing and selection */
float viewmatob[4][4];
float persmatob[4][4];
-
/* user defined clipping planes */
float clip[6][4];
float clip_local[6][4]; /* clip in object space, means we can test for clipping in editmode without first going into worldspace */
struct BoundBox *clipbb;
struct RegionView3D *localvd; /* allocated backup of its self while in localview */
- struct RenderInfo *ri;
struct RenderEngine *render_engine;
struct ViewDepths *depths;
void *gpuoffscreen;
@@ -147,6 +146,7 @@ typedef struct RegionView3D {
float rot_angle;
float rot_axis[3];
+ struct GPUFX *compositor;
} RegionView3D;
/* 3D ViewPort Struct */
@@ -203,16 +203,26 @@ typedef struct View3D {
char gridflag;
/* transform widget info */
- char twtype, twmode, twflag, pad2[2];
+ char twtype, twmode, twflag;
+
+ short flag3;
/* afterdraw, for xray & transparent */
struct ListBase afterdraw_transp;
struct ListBase afterdraw_xray;
struct ListBase afterdraw_xraytransp;
-
+
/* drawflags, denoting state */
char zbuf, transp, xray;
- char pad3[5];
+
+ char multiview_eye; /* multiview current eye - for internal use */
+
+ /* built-in shader effects (eGPUFXFlags) */
+ char pad3[4];
+
+ /* note, 'fx_settings.dof' is currently _not_ allocated,
+ * instead set (temporarily) from camera */
+ struct GPUFXSettings fx_settings;
void *properties_storage; /* Nkey panel stores stuff here (runtime only!) */
struct Material *defmaterial; /* used by matcap now */
@@ -220,9 +230,21 @@ typedef struct View3D {
/* XXX deprecated? */
struct bGPdata *gpd DNA_DEPRECATED; /* Grease-Pencil Data (annotation layers) */
+ /* multiview - stereo 3d */
+ short stereo3d_flag;
+ char stereo3d_camera;
+ char pad4;
+ float stereo3d_convergence_factor;
+ float stereo3d_volume_alpha;
+ float stereo3d_convergence_alpha;
} View3D;
+/* View3D->stereo_flag (short) */
+#define V3D_S3D_DISPCAMERAS (1 << 0)
+#define V3D_S3D_DISPPLANE (1 << 1)
+#define V3D_S3D_DISPVOLUME (1 << 2)
+
/* View3D->flag (short) */
/*#define V3D_DISPIMAGE 1*/ /*UNUSED*/
#define V3D_DISPBGPICS 2
@@ -246,6 +268,11 @@ typedef struct View3D {
#define RV3D_NAVIGATING 8
#define RV3D_GPULIGHT_UPDATE 16
#define RV3D_IS_GAME_ENGINE 32 /* runtime flag, used to check if LoD's should be used */
+/**
+ * Disable zbuffer offset, skip calls to #ED_view3d_polygon_offset.
+ * Use when precise surface depth is needed and picking bias isn't, see T45434).
+ */
+#define RV3D_ZOFFSET_DISABLED 64
/* RegionView3d->viewlock */
#define RV3D_LOCKED (1 << 0)
@@ -269,21 +296,24 @@ typedef struct View3D {
((view >= RV3D_VIEW_FRONT) && (view <= RV3D_VIEW_BOTTOM))
/* View3d->flag2 (short) */
-#define V3D_RENDER_OVERRIDE 4
-#define V3D_SOLID_TEX 8
-#define V3D_SHOW_GPENCIL 16
-#define V3D_LOCK_CAMERA 32
-#define V3D_RENDER_SHADOW 64 /* This is a runtime only flag that's used to tell draw_mesh_object() that we're doing a shadow pass instead of a regular draw */
-#define V3D_SHOW_RECONSTRUCTION 128
-#define V3D_SHOW_CAMERAPATH 256
-#define V3D_SHOW_BUNDLENAME 512
-#define V3D_BACKFACE_CULLING 1024
-#define V3D_RENDER_BORDER 2048
-#define V3D_SOLID_MATCAP 4096 /* user flag */
-#define V3D_SHOW_SOLID_MATCAP 8192 /* runtime flag */
-#define V3D_OCCLUDE_WIRE 16384
-#define V3D_SHADELESS_TEX 32768
-
+#define V3D_RENDER_OVERRIDE (1 << 2)
+#define V3D_SOLID_TEX (1 << 3)
+#define V3D_SHOW_GPENCIL (1 << 4)
+#define V3D_LOCK_CAMERA (1 << 5)
+#define V3D_RENDER_SHADOW (1 << 6) /* This is a runtime only flag that's used to tell draw_mesh_object() that we're doing a shadow pass instead of a regular draw */
+#define V3D_SHOW_RECONSTRUCTION (1 << 7)
+#define V3D_SHOW_CAMERAPATH (1 << 8)
+#define V3D_SHOW_BUNDLENAME (1 << 9)
+#define V3D_BACKFACE_CULLING (1 << 10)
+#define V3D_RENDER_BORDER (1 << 11)
+#define V3D_SOLID_MATCAP (1 << 12) /* user flag */
+#define V3D_SHOW_SOLID_MATCAP (1 << 13) /* runtime flag */
+#define V3D_OCCLUDE_WIRE (1 << 14)
+#define V3D_SHADELESS_TEX (1 << 15)
+
+
+/* View3d->flag3 (short) */
+#define V3D_SHOW_WORLD (1 << 0)
/* View3D->around */
#define V3D_CENTER 0
@@ -337,7 +367,11 @@ enum {
/* Camera framing options */
V3D_BGPIC_CAMERA_ASPECT = (1 << 5), /* don't stretch to fit the camera view */
- V3D_BGPIC_CAMERA_CROP = (1 << 6) /* crop out the image */
+ V3D_BGPIC_CAMERA_CROP = (1 << 6), /* crop out the image */
+
+ /* Axis flip options */
+ V3D_BGPIC_FLIP_X = (1 << 7),
+ V3D_BGPIC_FLIP_Y = (1 << 8),
};
#define V3D_BGPIC_EXPANDED (V3D_BGPIC_EXPANDED | V3D_BGPIC_CAMERACLIP)
@@ -350,6 +384,9 @@ enum {
#define RV3D_CAMZOOM_MIN -30
#define RV3D_CAMZOOM_MAX 600
-#endif
+/* #BKE_screen_view3d_zoom_to_fac() values above */
+#define RV3D_CAMZOOM_MIN_FACTOR 0.1657359312880714853f
+#define RV3D_CAMZOOM_MAX_FACTOR 44.9852813742385702928f
+#endif
diff --git a/source/blender/makesdna/DNA_windowmanager_types.h b/source/blender/makesdna/DNA_windowmanager_types.h
index a17e416b5bd..51ed8bb6c0d 100644
--- a/source/blender/makesdna/DNA_windowmanager_types.h
+++ b/source/blender/makesdna/DNA_windowmanager_types.h
@@ -33,6 +33,7 @@
#include "DNA_listBase.h"
#include "DNA_vec_types.h"
+#include "DNA_userdef_types.h"
#include "DNA_ID.h"
@@ -49,16 +50,14 @@ struct wmKeyConfig;
/* forwards */
struct bContext;
-struct wmLocal;
struct bScreen;
-struct uiBlock;
struct wmSubWindow;
struct wmTimer;
-struct StructRNA;
struct PointerRNA;
struct ReportList;
struct Report;
struct uiLayout;
+struct Stereo3dFormat;
#define OP_MAX_TYPENAME 64
#define KMAP_MAX_NAME 64
@@ -165,17 +164,19 @@ enum {
WM_INIT_KEYMAP = (1<<1),
};
+/* IME is win32 only! */
+#ifndef WIN32
+# ifdef __GNUC__
+# define ime_data ime_data __attribute__ ((deprecated))
+# endif
+#endif
+
/* the savable part, rest of data is local in ghostwinlay */
typedef struct wmWindow {
struct wmWindow *next, *prev;
void *ghostwin; /* don't want to include ghost.h stuff */
- int winid; /* winid also in screens, is for retrieving this window after read */
-
- short grabcursor; /* cursor grab mode */
- short pad;
-
struct bScreen *screen; /* active screen */
struct bScreen *newscreen; /* temporary when switching */
char screenname[64]; /* MAX_ID_NAME for matching window with active screen after file read */
@@ -187,8 +188,14 @@ typedef struct wmWindow {
short cursor; /* current mouse cursor type */
short lastcursor; /* previous cursor when setting modal one */
short modalcursor; /* the current modal cursor */
+ short grabcursor; /* cursor grab mode */
short addmousemove; /* internal: tag this for extra mousemove event, makes cursors/buttons active on UI switching */
- short pad2;
+
+ int winid; /* winid also in screens, is for retrieving this window after read */
+
+ short lock_pie_event; /* internal, lock pie creation from this event until released */
+ short last_pie_event; /* exception to the above rule for nested pies, store last pie event for operators
+ * that spawn a new pie right after destruction of last pie */
struct wmEvent *eventstate; /* storage for event system */
@@ -196,8 +203,12 @@ typedef struct wmWindow {
struct wmGesture *tweak; /* internal for wm_operators.c */
+ /* Input Method Editor data - complex character input (esp. for asian character input)
+ * Currently WIN32, runtime-only data */
+ struct wmIMEData *ime_data;
+
int drawmethod, drawfail; /* internal for wm_draw.c only */
- void *drawdata; /* internal for wm_draw.c only */
+ ListBase drawdata; /* internal for wm_draw.c only */
ListBase queue; /* all events (ghost level events were handled) */
ListBase handlers; /* window+screen handlers, handled last */
@@ -205,8 +216,14 @@ typedef struct wmWindow {
ListBase subwindows; /* opengl stuff for sub windows, see notes in wm_subwindow.c */
ListBase gesture; /* gesture stuff */
+
+ struct Stereo3dFormat *stereo3d_format; /* properties for stereoscopic displays */
} wmWindow;
+#ifdef ime_data
+# undef ime_data
+#endif
+
/* These two Lines with # tell makesdna this struct can be excluded. */
/* should be something like DNA_EXCLUDE
* but the preprocessor first removes all comments, spaces etc */
@@ -351,23 +368,38 @@ enum {
OPERATOR_RUNNING_MODAL = (1 << 0),
OPERATOR_CANCELLED = (1 << 1),
OPERATOR_FINISHED = (1 << 2),
-/* add this flag if the event should pass through */
+ /* add this flag if the event should pass through */
OPERATOR_PASS_THROUGH = (1 << 3),
-/* in case operator got executed outside WM code... like via fileselect */
+ /* in case operator got executed outside WM code... like via fileselect */
OPERATOR_HANDLED = (1 << 4),
+ /* used for operators that act indirectly (eg. popup menu)
+ * note: this isn't great design (using operators to trigger UI) avoid where possible. */
+ OPERATOR_INTERFACE = (1 << 5),
};
-#define OPERATOR_FLAGS_ALL (OPERATOR_RUNNING_MODAL | OPERATOR_CANCELLED | OPERATOR_FINISHED | \
- OPERATOR_PASS_THROUGH | OPERATOR_HANDLED)
+#define OPERATOR_FLAGS_ALL ( \
+ OPERATOR_RUNNING_MODAL | \
+ OPERATOR_CANCELLED | \
+ OPERATOR_FINISHED | \
+ OPERATOR_PASS_THROUGH | \
+ OPERATOR_HANDLED | \
+ OPERATOR_INTERFACE | \
+ 0)
/* sanity checks for debug mode only */
#define OPERATOR_RETVAL_CHECK(ret) (void)ret, BLI_assert(ret != 0 && (ret & OPERATOR_FLAGS_ALL) == ret)
/* wmOperator flag */
enum {
- OP_GRAB_POINTER = (1 << 0),
/* low level flag so exec() operators can tell if they were invoked, use with care.
* typically this shouldn't make any difference, but it rare cases its needed (see smooth-view) */
- OP_IS_INVOKE = (1 << 1),
+ OP_IS_INVOKE = (1 << 0),
+
+ /* When the cursor is grabbed */
+ OP_IS_MODAL_GRAB_CURSOR = (1 << 1),
+
+ /* allow modal operators to have the region under the cursor for their context
+ * (the regiontype is maintained to prevent errors) */
+ OP_IS_MODAL_CURSOR_REGION = (1 << 2),
};
#endif /* __DNA_WINDOWMANAGER_TYPES_H__ */
diff --git a/source/blender/makesdna/DNA_world_types.h b/source/blender/makesdna/DNA_world_types.h
index 50542797f0b..73bfa7a36fe 100644
--- a/source/blender/makesdna/DNA_world_types.h
+++ b/source/blender/makesdna/DNA_world_types.h
@@ -128,6 +128,7 @@ typedef struct World {
/* nodes */
struct bNodeTree *nodetree;
+ ListBase gpumaterial; /* runtime */
} World;
/* **************** WORLD ********************* */
@@ -153,15 +154,13 @@ typedef struct World {
/* aomix */
enum {
WO_AOADD = 0,
+#ifdef DNA_DEPRECATED
WO_AOSUB = 1, /* deprecated */
WO_AOADDSUB = 2, /* deprecated */
+#endif
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
#define WO_AOSAMP_HALTON 1
diff --git a/source/blender/makesdna/intern/CMakeLists.txt b/source/blender/makesdna/intern/CMakeLists.txt
index 317141b14e3..52487edfd2b 100644
--- a/source/blender/makesdna/intern/CMakeLists.txt
+++ b/source/blender/makesdna/intern/CMakeLists.txt
@@ -57,7 +57,7 @@ add_executable(makesdna ${SRC} ${SRC_DNA_INC})
# Output dna.c
add_custom_command(
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/dna.c
- COMMAND ${CMAKE_BINARY_DIR}/bin/${CMAKE_CFG_INTDIR}/makesdna ${CMAKE_CURRENT_BINARY_DIR}/dna.c ${CMAKE_SOURCE_DIR}/source/blender/makesdna/
+ COMMAND "$<TARGET_FILE:makesdna>" ${CMAKE_CURRENT_BINARY_DIR}/dna.c ${CMAKE_SOURCE_DIR}/source/blender/makesdna/
DEPENDS makesdna
)
@@ -74,7 +74,7 @@ set(INC_SYS
set(SRC
dna_genfile.c
- dna.c
+ ${CMAKE_CURRENT_BINARY_DIR}/dna.c
${SRC_DNA_INC}
)
@@ -97,6 +97,7 @@ set(SRC
../../blenlib/intern/BLI_mempool.c
../../blenlib/intern/listbase.c
../../blenlib/intern/BLI_ghash.c
+ ../../blenlib/intern/hash_mm2a.c
)
blender_add_lib(bf_dna_blenlib "${SRC}" "${INC}" "${INC_SYS}")
diff --git a/source/blender/makesdna/intern/dna_genfile.c b/source/blender/makesdna/intern/dna_genfile.c
index f60562f1ac9..16fbcbebe50 100644
--- a/source/blender/makesdna/intern/dna_genfile.c
+++ b/source/blender/makesdna/intern/dna_genfile.c
@@ -64,7 +64,7 @@
*
* Create a structDNA: only needed when one of the input include (.h) files change.
* File Syntax:
- * <pre>
+ * \code{.unparsed}
* SDNA (4 bytes) (magic number)
* NAME (4 bytes)
* <nr> (4 bytes) amount of names (int)
@@ -86,13 +86,13 @@
* STRC (4 bytes)
* <nr> amount of structs (int)
* <typenr><nr_of_elems> <typenr><namenr> <typenr><namenr> ...
- *</pre>
+ * \endcode
*
* **Remember to read/write integer and short aligned!**
*
* While writing a file, the names of a struct is indicated with a type number,
* to be found with: ``type = DNA_struct_find_nr(SDNA *, const char *)``
- * The value of ``type`` corresponds with the the index within the structs array
+ * The value of ``type`` corresponds with the index within the structs array
*
* For the moment: the complete DNA file is included in a .blend file. For
* the future we can think of smarter methods, like only included the used
@@ -311,7 +311,21 @@ int DNA_struct_find_nr(SDNA *sdna, const char *str)
}
#ifdef WITH_DNA_GHASH
- return (intptr_t)BLI_ghash_lookup(sdna->structs_map, str) - 1;
+ {
+ void **index_p;
+ int a;
+
+ index_p = BLI_ghash_lookup_p(sdna->structs_map, str);
+
+ if (index_p) {
+ a = GET_INT_FROM_POINTER(*index_p);
+ sdna->lastfind = a;
+ }
+ else {
+ a = -1;
+ }
+ return a;
+ }
#else
{
int a;
@@ -525,7 +539,7 @@ static void init_structDNA(SDNA *sdna, bool do_endian_swap)
for (nr = 0; nr < sdna->nr_structs; nr++) {
sp = sdna->structs[nr];
- BLI_ghash_insert(sdna->structs_map, (void *)sdna->types[sp[0]], (void *)(nr + 1));
+ BLI_ghash_insert(sdna->structs_map, sdna->types[sp[0]], SET_INT_IN_POINTER(nr));
}
#endif
}
diff --git a/source/blender/makesdna/intern/makesdna.c b/source/blender/makesdna/intern/makesdna.c
index 51a0c5a7b0f..a7ff4244d5f 100644
--- a/source/blender/makesdna/intern/makesdna.c
+++ b/source/blender/makesdna/intern/makesdna.c
@@ -73,6 +73,7 @@ static const char *includefiles[] = {
"DNA_key_types.h",
"DNA_text_types.h",
"DNA_packedFile_types.h",
+ "DNA_gpu_types.h",
"DNA_camera_types.h",
"DNA_image_types.h",
"DNA_texture_types.h",
@@ -538,6 +539,11 @@ static void *read_file_data(char *filename, int *r_len)
*r_len = ftell(fp);
fseek(fp, 0L, SEEK_SET);
+ if (*r_len == -1) {
+ fclose(fp);
+ return NULL;
+ }
+
data = MEM_mallocN(*r_len, "read_file_data");
if (!data) {
*r_len = -1;
@@ -909,7 +915,7 @@ static void dna_write(FILE *file, const void *pntr, const int size)
int i;
const char *data;
- data = (char *) pntr;
+ data = (const char *)pntr;
for (i = 0; i < size; i++) {
fprintf(file, "%d, ", data[i]);
diff --git a/source/blender/makesrna/RNA_access.h b/source/blender/makesrna/RNA_access.h
index f0582b39819..406bab011aa 100644
--- a/source/blender/makesrna/RNA_access.h
+++ b/source/blender/makesrna/RNA_access.h
@@ -172,6 +172,7 @@ extern StructRNA RNA_CompositorNodeSepYCCA;
extern StructRNA RNA_CompositorNodeSepYUVA;
extern StructRNA RNA_CompositorNodeSetAlpha;
extern StructRNA RNA_CompositorNodeSplitViewer;
+extern StructRNA RNA_CompositorNodeSwitchView;
extern StructRNA RNA_CompositorNodeTexture;
extern StructRNA RNA_CompositorNodeTime;
extern StructRNA RNA_CompositorNodeTonemap;
@@ -199,9 +200,12 @@ extern StructRNA RNA_CurveMapping;
extern StructRNA RNA_CurveModifier;
extern StructRNA RNA_CurvePoint;
extern StructRNA RNA_DampedTrackConstraint;
+extern StructRNA RNA_DataTransferModifier;
extern StructRNA RNA_DecimateModifier;
extern StructRNA RNA_DelaySensor;
+extern StructRNA RNA_CorrectiveSmoothModifier;
extern StructRNA RNA_DisplaceModifier;
+extern StructRNA RNA_DisplaySafeAreas;
extern StructRNA RNA_DistortedNoiseTexture;
extern StructRNA RNA_DomainFluidSettings;
extern StructRNA RNA_DopeSheet;
@@ -238,6 +242,7 @@ extern StructRNA RNA_FModifierNoise;
extern StructRNA RNA_FModifierPython;
extern StructRNA RNA_FModifierStepped;
extern StructRNA RNA_FieldSettings;
+extern StructRNA RNA_FileBrowserFSMenuEntry;
extern StructRNA RNA_FileSelectParams;
extern StructRNA RNA_FloatProperty;
extern StructRNA RNA_FloorConstraint;
@@ -275,6 +280,7 @@ extern StructRNA RNA_IKParam;
extern StructRNA RNA_Image;
extern StructRNA RNA_ImageFormatSettings;
extern StructRNA RNA_ImagePaint;
+extern StructRNA RNA_ImagePreview;
extern StructRNA RNA_ImageSequence;
extern StructRNA RNA_ImageTexture;
extern StructRNA RNA_ImageUser;
@@ -310,14 +316,22 @@ extern StructRNA RNA_LimitRotationConstraint;
extern StructRNA RNA_LimitScaleConstraint;
extern StructRNA RNA_LineStyleAlphaModifier;
extern StructRNA RNA_LineStyleAlphaModifier_AlongStroke;
+extern StructRNA RNA_LineStyleAlphaModifier_CreaseAngle;
+extern StructRNA RNA_LineStyleAlphaModifier_Curvature_3D;
extern StructRNA RNA_LineStyleAlphaModifier_DistanceFromCamera;
extern StructRNA RNA_LineStyleAlphaModifier_DistanceFromObject;
extern StructRNA RNA_LineStyleAlphaModifier_Material;
+extern StructRNA RNA_LineStyleAlphaModifier_Noise;
+extern StructRNA RNA_LineStyleAlphaModifier_Tangent;
extern StructRNA RNA_LineStyleColorModifier;
extern StructRNA RNA_LineStyleColorModifier_AlongStroke;
+extern StructRNA RNA_LineStyleColorModifier_CreaseAngle;
+extern StructRNA RNA_LineStyleColorModifier_Curvature_3D;
extern StructRNA RNA_LineStyleColorModifier_DistanceFromCamera;
extern StructRNA RNA_LineStyleColorModifier_DistanceFromObject;
extern StructRNA RNA_LineStyleColorModifier_Material;
+extern StructRNA RNA_LineStyleColorModifier_Noise;
+extern StructRNA RNA_LineStyleColorModifier_Tangent;
extern StructRNA RNA_LineStyleGeometryModifier;
extern StructRNA RNA_LineStyleGeometryModifier_2DOffset;
extern StructRNA RNA_LineStyleGeometryModifier_2DTransform;
@@ -329,6 +343,7 @@ extern StructRNA RNA_LineStyleGeometryModifier_PerlinNoise1D;
extern StructRNA RNA_LineStyleGeometryModifier_PerlinNoise2D;
extern StructRNA RNA_LineStyleGeometryModifier_Polygonalization;
extern StructRNA RNA_LineStyleGeometryModifier_Sampling;
+extern StructRNA RNA_LineStyleGeometryModifier_Simplification;
extern StructRNA RNA_LineStyleGeometryModifier_SinusDisplacement;
extern StructRNA RNA_LineStyleGeometryModifier_SpatialNoise;
extern StructRNA RNA_LineStyleGeometryModifier_TipRemover;
@@ -337,9 +352,13 @@ extern StructRNA RNA_LineStyleTextureSlot;
extern StructRNA RNA_LineStyleThicknessModifier;
extern StructRNA RNA_LineStyleThicknessModifier_AlongStroke;
extern StructRNA RNA_LineStyleThicknessModifier_Calligraphy;
+extern StructRNA RNA_LineStyleThicknessModifier_CreaseAngle;
+extern StructRNA RNA_LineStyleThicknessModifier_Curvature_3D;
extern StructRNA RNA_LineStyleThicknessModifier_DistanceFromCamera;
extern StructRNA RNA_LineStyleThicknessModifier_DistanceFromObject;
extern StructRNA RNA_LineStyleThicknessModifier_Material;
+extern StructRNA RNA_LineStyleThicknessModifier_Noise;
+extern StructRNA RNA_LineStyleThicknessModifier_Tangent;
extern StructRNA RNA_LockedTrackConstraint;
extern StructRNA RNA_Macro;
extern StructRNA RNA_MagicTexture;
@@ -492,6 +511,7 @@ extern StructRNA RNA_SequenceEditor;
extern StructRNA RNA_SequenceElement;
extern StructRNA RNA_SequenceProxy;
extern StructRNA RNA_SequenceTransform;
+extern StructRNA RNA_NormalEditModifier;
extern StructRNA RNA_ShaderNode;
extern StructRNA RNA_ShaderNodeCameraData;
extern StructRNA RNA_ShaderNodeCombineRGB;
@@ -505,6 +525,7 @@ extern StructRNA RNA_ShaderNodeMaterial;
extern StructRNA RNA_ShaderNodeMath;
extern StructRNA RNA_ShaderNodeMixRGB;
extern StructRNA RNA_ShaderNodeNormal;
+extern StructRNA RNA_ShaderNodeGamma;
extern StructRNA RNA_ShaderNodeOutput;
extern StructRNA RNA_ShaderNodeScript;
extern StructRNA RNA_ShaderNodeRGB;
@@ -560,6 +581,7 @@ extern StructRNA RNA_SpeedControlSequence;
extern StructRNA RNA_Spline;
extern StructRNA RNA_SplineIKConstraint;
extern StructRNA RNA_SpotLamp;
+extern StructRNA RNA_Stereo3dDisplay;
extern StructRNA RNA_StretchToConstraint;
extern StructRNA RNA_StringProperty;
extern StructRNA RNA_Struct;
@@ -616,6 +638,7 @@ extern StructRNA RNA_ThemeNodeEditor;
extern StructRNA RNA_ThemeOutliner;
extern StructRNA RNA_ThemeProperties;
extern StructRNA RNA_ThemeSequenceEditor;
+extern StructRNA RNA_TextSequence;
extern StructRNA RNA_ThemeSpaceGeneric;
extern StructRNA RNA_ThemeSpaceGradient;
extern StructRNA RNA_ThemeSpaceListGeneric;
diff --git a/source/blender/makesrna/RNA_enum_types.h b/source/blender/makesrna/RNA_enum_types.h
index 3d4ed0d6f51..b1a631cc610 100644
--- a/source/blender/makesrna/RNA_enum_types.h
+++ b/source/blender/makesrna/RNA_enum_types.h
@@ -72,6 +72,13 @@ extern EnumPropertyItem normal_space_items[];
extern EnumPropertyItem normal_swizzle_items[];
extern EnumPropertyItem bake_save_mode_items[];
+extern EnumPropertyItem views_format_items[];
+extern EnumPropertyItem views_format_multilayer_items[];
+extern EnumPropertyItem views_format_multiview_items[];
+extern EnumPropertyItem stereo3d_display_items[];
+extern EnumPropertyItem stereo3d_anaglyph_type_items[];
+extern EnumPropertyItem stereo3d_interlace_type_items[];
+
extern EnumPropertyItem exr_codec_items[];
extern EnumPropertyItem color_sets_items[];
@@ -125,6 +132,7 @@ extern EnumPropertyItem object_axis_unsigned_items[];
extern EnumPropertyItem controller_type_items[];
extern EnumPropertyItem render_pass_type_items[];
+extern EnumPropertyItem render_pass_debug_type_items[];
extern EnumPropertyItem keymap_propvalue_items[];
@@ -146,6 +154,8 @@ extern EnumPropertyItem viewport_shade_items[];
extern EnumPropertyItem navigation_mode_items[];
+extern EnumPropertyItem file_sort_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);
@@ -184,6 +194,14 @@ extern EnumPropertyItem linestyle_geometry_modifier_type_items[];
extern EnumPropertyItem window_cursor_items[];
+extern EnumPropertyItem DT_method_vertex_items[];
+extern EnumPropertyItem DT_method_edge_items[];
+extern EnumPropertyItem DT_method_loop_items[];
+extern EnumPropertyItem DT_method_poly_items[];
+extern EnumPropertyItem DT_mix_mode_items[];
+extern EnumPropertyItem DT_layers_select_src_items[];
+extern EnumPropertyItem DT_layers_select_dst_items[];
+
struct bContext;
struct PointerRNA;
struct PropertyRNA;
diff --git a/source/blender/makesrna/RNA_types.h b/source/blender/makesrna/RNA_types.h
index 83f3870c29a..0c99769a390 100644
--- a/source/blender/makesrna/RNA_types.h
+++ b/source/blender/makesrna/RNA_types.h
@@ -37,10 +37,8 @@ extern "C" {
struct ParameterList;
struct FunctionRNA;
struct PropertyRNA;
-struct EnumPropertyRNA;
struct StructRNA;
struct BlenderRNA;
-struct IDProperty;
struct bContext;
struct Main;
struct ReportList;
@@ -147,7 +145,7 @@ typedef enum PropertySubType {
} PropertySubType;
/* Make sure enums are updated with these */
-/* HIGHEST FLAG IN USE: 1 << 30 */
+/* HIGHEST FLAG IN USE: 1 << 31 */
typedef enum PropertyFlag {
/* editable means the property is editable in the user
* interface, properties are editable by default except
@@ -165,6 +163,10 @@ typedef enum PropertyFlag {
* and collections */
PROP_ANIMATABLE = (1 << 1),
+ /* This flag means when the property's widget is in 'textedit' mode, it will be updated after every typed char,
+ * instead of waiting final validation. Used e.g. for text searchbox. */
+ PROP_TEXTEDIT_UPDATE = (1 << 31),
+
/* icon */
PROP_ICONS_CONSECUTIVE = (1 << 12),
diff --git a/source/blender/makesrna/SConscript b/source/blender/makesrna/SConscript
index 7abda8790c3..260784788db 100644
--- a/source/blender/makesrna/SConscript
+++ b/source/blender/makesrna/SConscript
@@ -38,26 +38,30 @@ incs = [
'#/intern/guardedalloc',
'#/intern/atomic',
'#/intern/memutil',
- '#/extern/glew/include',
- '#/intern/audaspace/intern',
+ env['BF_GLEW_INC'],
+ '#/intern/glew-mx',
'#/intern/cycles/blender',
'#/intern/smoke/extern',
'../blenfont',
'../blenkernel',
'../blenlib',
+ '../blentranslation',
'../bmesh',
+ '../depsgraph',
'../editors/include',
'../gpu',
'../ikplugin',
'../imbuf',
'../makesdna',
'../nodes',
+ '../physics',
'../render/extern/include',
'../windowmanager',
]
incs = ' '.join(incs)
defs = []
+defs += env['BF_GL_DEFINITIONS']
if env['WITH_BF_SMOKE']:
defs.append('WITH_SMOKE')
@@ -97,6 +101,10 @@ if env['WITH_BF_FFMPEG']:
if env['WITH_BF_QUICKTIME']:
defs.append('WITH_QUICKTIME')
incs += ' ../quicktime'
+ # Quicktime needs audaspace defines
+ if env['WITH_BF_AUDASPACE']:
+ defs += env['BF_AUDASPACE_DEF']
+ incs += ' ' + env['BF_AUDASPACE_C_INC']
if env['WITH_BF_GAMEENGINE']:
defs.append('WITH_GAMEENGINE')
@@ -117,7 +125,13 @@ if env['WITH_BF_OCEANSIM']:
if env['WITH_BF_CYCLES']:
defs.append('WITH_CYCLES')
+ if env['WITH_BF_CYCLES_DEBUG']:
+ defs.append('WITH_CYCLES_DEBUG')
+
if env['WITH_BF_SDL']:
+ if env['WITH_BF_SDL_DYNLOAD']:
+ defs.append('WITH_SDL_DYNLOAD')
+ incs += ' #extern/sdlew/include'
defs.append('WITH_SDL')
if env['WITH_BF_OPENAL']:
@@ -126,6 +140,14 @@ if env['WITH_BF_OPENAL']:
if env['WITH_BF_JACK']:
defs.append('WITH_JACK')
+if env['WITH_BF_FREESTYLE']:
+ defs.append('WITH_FREESTYLE')
+ incs += ' ../freestyle'
+
+if env['WITH_BF_OPENSUBDIV']:
+ incs += ' #/intern/opensubdiv'
+ defs.append('WITH_OPENSUBDIV')
+
if env['OURPLATFORM'] == 'linux':
cflags='-pthread'
diff --git a/source/blender/makesrna/intern/CMakeLists.txt b/source/blender/makesrna/intern/CMakeLists.txt
index 15f5253257a..987b594421f 100644
--- a/source/blender/makesrna/intern/CMakeLists.txt
+++ b/source/blender/makesrna/intern/CMakeLists.txt
@@ -28,8 +28,6 @@ if(CMAKE_COMPILER_IS_GNUCC)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror=implicit-function-declaration")
endif()
-# message(STATUS "Configuring makesrna")
-
# files rna_access.c rna_define.c makesrna.c intentionally excluded.
set(DEFSRC
rna_ID.c
@@ -47,6 +45,7 @@ set(DEFSRC
rna_context.c
rna_controller.c
rna_curve.c
+ rna_depsgraph.c
rna_dynamicpaint.c
rna_fcurve.c
rna_fluidsim.c
@@ -69,6 +68,7 @@ set(DEFSRC
rna_object.c
rna_object_force.c
rna_packedfile.c
+ rna_palette.c
rna_particle.c
rna_pose.c
rna_property.c
@@ -117,15 +117,35 @@ set(APISRC
rna_scene_api.c
rna_sensor_api.c
rna_sequencer_api.c
+ rna_sound_api.c
rna_space_api.c
rna_text_api.c
rna_ui_api.c
+ rna_vfont_api.c
rna_wm_api.c
)
string(REGEX REPLACE "rna_([a-zA-Z0-9_-]*).c" "${CMAKE_CURRENT_BINARY_DIR}/rna_\\1_gen.c" GENSRC "${DEFSRC}")
+list(APPEND GENSRC
+ "${CMAKE_CURRENT_BINARY_DIR}/rna_prototypes_gen.h"
+)
set_source_files_properties(${GENSRC} PROPERTIES GENERATED TRUE)
+# --------------------------
+# CFLAGS for Generated Files
+#
+# less strict flags for generated source
+set(GENSRC_CFLAGS)
+if(CMAKE_COMPILER_IS_GNUCC OR (CMAKE_C_COMPILER_ID MATCHES "Clang"))
+ set(GENSRC_CFLAGS "-Wno-missing-prototypes")
+endif()
+
+if(GENSRC_CFLAGS)
+ set_source_files_properties(${GENSRC} PROPERTIES COMPILE_FLAGS "${GENSRC_CFLAGS}")
+endif()
+unset(GENSRC_CFLAGS)
+
+
set(SRC_RNA_INC
../RNA_access.h
../RNA_define.h
@@ -155,6 +175,9 @@ set(INC_SYS
if(WITH_CYCLES)
add_definitions(-DWITH_CYCLES)
+ if(WITH_CYCLES_DEBUG)
+ add_definitions(-DWITH_CYCLES_DEBUG)
+ endif()
endif()
if(WITH_PYTHON)
@@ -201,7 +224,11 @@ if(WITH_IMAGE_FRAMESERVER)
endif()
if(WITH_AUDASPACE)
- add_definitions(-DWITH_AUDASPACE)
+ add_definitions(${AUDASPACE_DEFINITIONS})
+
+ list(APPEND INC_SYS
+ ${AUDASPACE_C_INCLUDE_DIRS}
+ )
endif()
if(WITH_CODEC_QUICKTIME)
@@ -238,6 +265,12 @@ if(WITH_MOD_OCEANSIM)
endif()
if(WITH_SDL)
+ if(WITH_SDL_DYNLOAD)
+ add_definitions(-DWITH_SDL_DYNLOAD)
+ list(APPEND INC
+ ../../../../extern/sdlew/include
+ )
+ endif()
add_definitions(-DWITH_SDL)
endif()
@@ -265,49 +298,59 @@ if(WITH_BULLET)
endif()
if(WITH_FREESTYLE)
+ list(APPEND INC
+ ../../freestyle
+ )
add_definitions(-DWITH_FREESTYLE)
endif()
+if(WITH_OPENSUBDIV)
+ list(APPEND INC
+ ../../../../intern/opensubdiv
+ )
+ add_definitions(-DWITH_OPENSUBDIV)
+endif()
+
# Build makesrna executable
blender_include_dirs(
.
..
+ ../../blenfont
../../blenkernel
../../blenlib
../../bmesh
- ../../blenfont
+ ../../blentranslation
+ ../../depsgraph
../../gpu
../../imbuf
../../ikplugin
../../makesdna
../../nodes/
+ ../../physics
../../windowmanager
../../editors/include
../../render/extern/include
- ../../../../intern/audaspace/intern
../../../../intern/cycles/blender
../../../../intern/guardedalloc
+ ../../../../intern/glew-mx
../../../../intern/atomic
../../../../intern/memutil
../../../../intern/smoke/extern
)
blender_include_dirs_sys(
- ${GLEW_INCLUDE_PATH}
+ "${GLEW_INCLUDE_PATH}"
)
add_executable(makesrna ${SRC} ${SRC_RNA_INC} ${SRC_DNA_INC})
target_link_libraries(makesrna bf_dna)
target_link_libraries(makesrna bf_dna_blenlib)
-# too many warnings with clang
-remove_cc_flag("-Wmissing-prototypes")
-
# Output rna_*_gen.c
# note (linux only): with crashes try add this after COMMAND: valgrind --leak-check=full --track-origins=yes
add_custom_command(
OUTPUT ${GENSRC}
- COMMAND ${CMAKE_BINARY_DIR}/bin/${CMAKE_CFG_INTDIR}/makesrna ${CMAKE_CURRENT_BINARY_DIR}/
+ COMMAND "$<TARGET_FILE:makesrna>" ${CMAKE_CURRENT_BINARY_DIR}/
DEPENDS makesrna
)
@@ -322,4 +365,6 @@ set(SRC
rna_mesh_utils.h
)
+add_definitions(${GL_DEFINITIONS})
+
blender_add_lib(bf_rna "${SRC}" "${INC}" "${INC_SYS}")
diff --git a/source/blender/makesrna/intern/SConscript b/source/blender/makesrna/intern/SConscript
index 08cbd6143a5..e8842ae2943 100644
--- a/source/blender/makesrna/intern/SConscript
+++ b/source/blender/makesrna/intern/SConscript
@@ -54,22 +54,27 @@ rna = env.Clone()
makesrna_tool.Append(CCFLAGS = '-DBASE_HEADER="\\"source/blender/makesrna/\\"" ')
defs = []
+defs += env['BF_GL_DEFINITIONS']
incs = [
'#/intern/guardedalloc',
- '#/extern/glew/include',
- '#/intern/audaspace/intern',
+ env['BF_GLEW_INC'],
+ '#/intern/glew-mx',
'#/intern/cycles/blender',
'#/intern/smoke/extern',
'../../blenfont',
'../../blenkernel',
'../../blenlib',
+ '../../blentranslation',
'../../bmesh',
+ '../../depsgraph',
'../../editors/include',
+ '../../gpu',
'../../ikplugin',
'../../imbuf',
'../../makesdna',
'../../makesrna',
+ '../../physics',
'../../render/extern/include',
'../../windowmanager',
]
@@ -106,6 +111,10 @@ if env['WITH_BF_HDR']:
if env['WITH_BF_FRAMESERVER']:
defs.append('WITH_FRAMESERVER')
+if env['WITH_BF_AUDASPACE']:
+ defs += env['BF_AUDASPACE_DEF']
+ incs += ' ' + env['BF_AUDASPACE_C_INC']
+
if env['WITH_BF_FFMPEG']:
defs.append('WITH_FFMPEG')
incs += ' ' + env['BF_FFMPEG_INC'] + ' #/intern/ffmpeg'
@@ -121,6 +130,9 @@ if env['WITH_BF_FFTW3']:
defs.append('WITH_FFTW3')
if env['WITH_BF_SDL']:
+ if env['WITH_BF_SDL_DYNLOAD']:
+ defs.append('WITH_SDL_DYNLOAD')
+ incs += ' #extern/sdlew/include'
defs.append('WITH_SDL')
if env['WITH_BF_OPENAL']:
@@ -140,9 +152,16 @@ if env['WITH_BF_COLLADA']:
if env['WITH_BF_CYCLES']:
defs.append('WITH_CYCLES')
+ if env['WITH_BF_CYCLES_DEBUG']:
+ defs.append('WITH_CYCLES_DEBUG')
if env['WITH_BF_FREESTYLE']:
defs.append('WITH_FREESTYLE')
+ incs += ' ../../freestyle'
+
+if env['WITH_BF_OPENSUBDIV']:
+ defs.append('WITH_OPENSUBDIV')
+ incs += ' #intern/opensubdiv'
if env['OURPLATFORM'] == 'linux':
cflags='-pthread'
diff --git a/source/blender/makesrna/intern/makesrna.c b/source/blender/makesrna/intern/makesrna.c
index 9023f25e3d5..0f00dd7a586 100644
--- a/source/blender/makesrna/intern/makesrna.c
+++ b/source/blender/makesrna/intern/makesrna.c
@@ -35,7 +35,6 @@
#include "BLI_utildefines.h"
-#include "RNA_access.h"
#include "RNA_define.h"
#include "RNA_types.h"
@@ -47,6 +46,14 @@
# endif
#endif
+/* stub for BLI_abort() */
+#ifndef NDEBUG
+void BLI_system_backtrace(FILE *fp)
+{
+ (void)fp;
+}
+#endif
+
/* Replace if different */
#define TMP_EXT ".tmp"
@@ -214,11 +221,11 @@ static int replace_if_different(const char *tmpfile, const char *dep_files[])
static const char *rna_safe_id(const char *id)
{
- if (strcmp(id, "default") == 0)
+ if (STREQ(id, "default"))
return "default_value";
- else if (strcmp(id, "operator") == 0)
+ else if (STREQ(id, "operator"))
return "operator_value";
- else if (strcmp(id, "new") == 0)
+ else if (STREQ(id, "new"))
return "create";
return id;
@@ -239,11 +246,11 @@ static int cmp_property(const void *a, const void *b)
const PropertyRNA *propa = *(const PropertyRNA **)a;
const PropertyRNA *propb = *(const PropertyRNA **)b;
- if (strcmp(propa->identifier, "rna_type") == 0) return -1;
- else if (strcmp(propb->identifier, "rna_type") == 0) return 1;
+ if (STREQ(propa->identifier, "rna_type")) return -1;
+ else if (STREQ(propb->identifier, "rna_type")) return 1;
- if (strcmp(propa->identifier, "name") == 0) return -1;
- else if (strcmp(propb->identifier, "name") == 0) return 1;
+ if (STREQ(propa->identifier, "name")) return -1;
+ else if (STREQ(propb->identifier, "name")) return 1;
return strcmp(propa->name, propb->name);
}
@@ -365,7 +372,7 @@ static StructRNA *rna_find_struct(const char *identifier)
StructDefRNA *ds;
for (ds = DefRNA.structs.first; ds; ds = ds->cont.next)
- if (strcmp(ds->srna->identifier, identifier) == 0)
+ if (STREQ(ds->srna->identifier, identifier))
return ds->srna;
return NULL;
@@ -376,7 +383,7 @@ static const char *rna_find_type(const char *type)
StructDefRNA *ds;
for (ds = DefRNA.structs.first; ds; ds = ds->cont.next)
- if (ds->dnaname && strcmp(ds->dnaname, type) == 0)
+ if (ds->dnaname && STREQ(ds->dnaname, type))
return ds->srna->identifier;
return NULL;
@@ -387,7 +394,7 @@ static const char *rna_find_dna_type(const char *type)
StructDefRNA *ds;
for (ds = DefRNA.structs.first; ds; ds = ds->cont.next)
- if (strcmp(ds->srna->identifier, type) == 0)
+ if (STREQ(ds->srna->identifier, type))
return ds->dnaname;
return NULL;
@@ -496,7 +503,7 @@ static void rna_float_print(FILE *f, float num)
{
if (num == -FLT_MAX) fprintf(f, "-FLT_MAX");
else if (num == FLT_MAX) fprintf(f, "FLT_MAX");
- else if ((int)num == num) fprintf(f, "%.1ff", num);
+ else if ((int64_t)num == num) fprintf(f, "%.1ff", num);
else fprintf(f, "%.10ff", num);
}
@@ -614,9 +621,9 @@ static char *rna_def_property_get_func(FILE *f, StructRNA *srna, PropertyRNA *pr
fprintf(f, "static PointerRNA %s(CollectionPropertyIterator *iter)\n", func);
fprintf(f, "{\n");
if (manualfunc) {
- if (strcmp(manualfunc, "rna_iterator_listbase_get") == 0 ||
- strcmp(manualfunc, "rna_iterator_array_get") == 0 ||
- strcmp(manualfunc, "rna_iterator_array_dereference_get") == 0)
+ if (STREQ(manualfunc, "rna_iterator_listbase_get") ||
+ STREQ(manualfunc, "rna_iterator_array_get") ||
+ STREQ(manualfunc, "rna_iterator_array_dereference_get"))
{
fprintf(f, " return rna_pointer_inherit_refine(&iter->parent, &RNA_%s, %s(iter));\n",
(cprop->item_type) ? (const char *)cprop->item_type : "UnknownType", manualfunc);
@@ -929,7 +936,7 @@ static char *rna_def_property_set_func(FILE *f, StructRNA *srna, PropertyRNA *pr
if (dp->dnaarraylength == 1) {
if (prop->type == PROP_BOOLEAN && dp->booleanbit) {
- fprintf(f, " if (%svalues[i]) data->%s |= (%d<<i);\n",
+ fprintf(f, " if (%svalues[i]) data->%s |= (%du << i);\n",
(dp->booleannegative) ? "!" : "", dp->dnaname, dp->booleanbit);
fprintf(f, " else data->%s &= ~(%du << i);\n", dp->dnaname, dp->booleanbit);
}
@@ -1150,7 +1157,7 @@ static char *rna_def_property_lookup_int_func(FILE *f, StructRNA *srna, Property
const char *manualfunc, const char *nextfunc)
{
/* note on indices, this is for external functions and ignores skipped values.
- * so the the index can only be checked against the length when there is no 'skip' function. */
+ * so the index can only be checked against the length when there is no 'skip' function. */
char *func;
if (prop->flag & PROP_IDPROPERTY && manualfunc == NULL)
@@ -1161,8 +1168,8 @@ static char *rna_def_property_lookup_int_func(FILE *f, StructRNA *srna, Property
return NULL;
/* only supported in case of standard next functions */
- if (strcmp(nextfunc, "rna_iterator_array_next") == 0) {}
- else if (strcmp(nextfunc, "rna_iterator_listbase_next") == 0) {}
+ if (STREQ(nextfunc, "rna_iterator_array_next")) {}
+ else if (STREQ(nextfunc, "rna_iterator_listbase_next")) {}
else return NULL;
}
@@ -1183,7 +1190,7 @@ static char *rna_def_property_lookup_int_func(FILE *f, StructRNA *srna, Property
fprintf(f, " %s_%s_begin(&iter, ptr);\n\n", srna->identifier, rna_safe_id(prop->identifier));
fprintf(f, " if (iter.valid) {\n");
- if (strcmp(nextfunc, "rna_iterator_array_next") == 0) {
+ if (STREQ(nextfunc, "rna_iterator_array_next")) {
fprintf(f, " ArrayIterator *internal = &iter.internal.array;\n");
fprintf(f, " if (index < 0 || index >= internal->length) {\n");
fprintf(f, "#ifdef __GNUC__\n");
@@ -1203,7 +1210,7 @@ static char *rna_def_property_lookup_int_func(FILE *f, StructRNA *srna, Property
fprintf(f, " found = 1;\n");
fprintf(f, " }\n");
}
- else if (strcmp(nextfunc, "rna_iterator_listbase_next") == 0) {
+ else if (STREQ(nextfunc, "rna_iterator_listbase_next")) {
fprintf(f, " ListBaseIterator *internal = &iter.internal.listbase;\n");
fprintf(f, " if (internal->skip) {\n");
fprintf(f, " while (index-- > 0 && iter.valid) {\n");
@@ -1389,23 +1396,23 @@ static void rna_set_raw_property(PropertyDefRNA *dp, PropertyRNA *prop)
if (!dp->dnatype || !dp->dnaname || !dp->dnastructname)
return;
- if (strcmp(dp->dnatype, "char") == 0) {
+ if (STREQ(dp->dnatype, "char")) {
prop->rawtype = PROP_RAW_CHAR;
prop->flag |= PROP_RAW_ACCESS;
}
- else if (strcmp(dp->dnatype, "short") == 0) {
+ else if (STREQ(dp->dnatype, "short")) {
prop->rawtype = PROP_RAW_SHORT;
prop->flag |= PROP_RAW_ACCESS;
}
- else if (strcmp(dp->dnatype, "int") == 0) {
+ else if (STREQ(dp->dnatype, "int")) {
prop->rawtype = PROP_RAW_INT;
prop->flag |= PROP_RAW_ACCESS;
}
- else if (strcmp(dp->dnatype, "float") == 0) {
+ else if (STREQ(dp->dnatype, "float")) {
prop->rawtype = PROP_RAW_FLOAT;
prop->flag |= PROP_RAW_ACCESS;
}
- else if (strcmp(dp->dnatype, "double") == 0) {
+ else if (STREQ(dp->dnatype, "double")) {
prop->rawtype = PROP_RAW_DOUBLE;
prop->flag |= PROP_RAW_ACCESS;
}
@@ -1518,7 +1525,7 @@ static void rna_def_property_funcs(FILE *f, StructRNA *srna, PropertyDefRNA *dp)
const char *nextfunc = (const char *)cprop->next;
const char *item_type = (const char *)cprop->item_type;
- if (dp->dnatype && strcmp(dp->dnatype, "ListBase") == 0) {
+ if (dp->dnatype && STREQ(dp->dnatype, "ListBase")) {
/* pass */
}
else if (dp->dnalengthname || dp->dnalengthfixed) {
@@ -1528,8 +1535,8 @@ static void rna_def_property_funcs(FILE *f, StructRNA *srna, PropertyDefRNA *dp)
/* test if we can allow raw array access, if it is using our standard
* array get/next function, we can be sure it is an actual array */
if (cprop->next && cprop->get)
- if (strcmp((const char *)cprop->next, "rna_iterator_array_next") == 0 &&
- strcmp((const char *)cprop->get, "rna_iterator_array_get") == 0)
+ if (STREQ((const char *)cprop->next, "rna_iterator_array_next") &&
+ STREQ((const char *)cprop->get, "rna_iterator_array_get"))
{
prop->flag |= PROP_RAW_ARRAY;
}
@@ -1621,7 +1628,7 @@ static void rna_def_property_funcs_header(FILE *f, StructRNA *srna, PropertyDefR
EnumPropertyRNA *eprop = (EnumPropertyRNA *)prop;
int i;
- if (eprop->item) {
+ if (eprop->item && eprop->totitem) {
fprintf(f, "enum {\n");
for (i = 0; i < eprop->totitem; i++)
@@ -2020,7 +2027,8 @@ static void rna_def_struct_function_call_impl_cpp(FILE *f, StructRNA *srna, Func
if ((func->flag & FUNC_NO_SELF) == 0) {
WRITE_COMMA;
- if (dsrna->dnaname) fprintf(f, "(::%s *) this->ptr.data", dsrna->dnaname);
+ if (dsrna->dnafromprop) fprintf(f, "(::%s *) this->ptr.data", dsrna->dnafromname);
+ else if (dsrna->dnaname) fprintf(f, "(::%s *) this->ptr.data", dsrna->dnaname);
else fprintf(f, "(::%s *) this->ptr.data", srna->identifier);
}
else if (func->flag & FUNC_USE_SELF_TYPE) {
@@ -2215,7 +2223,8 @@ static void rna_def_function_funcs(FILE *f, StructDefRNA *dsrna, FunctionDefRNA
}
if ((func->flag & FUNC_NO_SELF) == 0) {
- if (dsrna->dnaname) fprintf(f, "\tstruct %s *_self;\n", dsrna->dnaname);
+ if (dsrna->dnafromprop) fprintf(f, "\tstruct %s *_self;\n", dsrna->dnafromname);
+ else if (dsrna->dnaname) fprintf(f, "\tstruct %s *_self;\n", dsrna->dnaname);
else fprintf(f, "\tstruct %s *_self;\n", srna->identifier);
}
else if (func->flag & FUNC_USE_SELF_TYPE) {
@@ -2267,7 +2276,8 @@ static void rna_def_function_funcs(FILE *f, StructDefRNA *dsrna, FunctionDefRNA
}
if ((func->flag & FUNC_NO_SELF) == 0) {
- if (dsrna->dnaname) fprintf(f, "\t_self = (struct %s *)_ptr->data;\n", dsrna->dnaname);
+ if (dsrna->dnafromprop) fprintf(f, "\t_self = (struct %s *)_ptr->data;\n", dsrna->dnafromname);
+ else if (dsrna->dnaname) fprintf(f, "\t_self = (struct %s *)_ptr->data;\n", dsrna->dnaname);
else fprintf(f, "\t_self = (struct %s *)_ptr->data;\n", srna->identifier);
}
else if (func->flag & FUNC_USE_SELF_TYPE) {
@@ -2412,11 +2422,11 @@ static void rna_auto_types(void)
for (ds = DefRNA.structs.first; ds; ds = ds->cont.next) {
/* DNA name for Screen is patched in 2.5, we do the reverse here .. */
- if (ds->dnaname && strcmp(ds->dnaname, "Screen") == 0)
+ if (ds->dnaname && STREQ(ds->dnaname, "Screen"))
ds->dnaname = "bScreen";
for (dp = ds->cont.properties.first; dp; dp = dp->next) {
- if (dp->dnastructname && strcmp(dp->dnastructname, "Screen") == 0)
+ if (dp->dnastructname && STREQ(dp->dnastructname, "Screen"))
dp->dnastructname = "bScreen";
if (dp->dnatype) {
@@ -2436,7 +2446,7 @@ static void rna_auto_types(void)
else if (dp->prop->type == PROP_COLLECTION) {
CollectionPropertyRNA *cprop = (CollectionPropertyRNA *)dp->prop;
- if (!cprop->item_type && !cprop->get && strcmp(dp->dnatype, "ListBase") == 0)
+ if (!cprop->item_type && !cprop->get && STREQ(dp->dnatype, "ListBase"))
cprop->item_type = (StructRNA *)rna_find_type(dp->dnatype);
}
}
@@ -2668,7 +2678,8 @@ static void rna_generate_static_parameter_prototypes(FILE *f, StructRNA *srna, F
if ((func->flag & FUNC_NO_SELF) == 0) {
if (!first) fprintf(f, ", ");
- if (dsrna->dnaname) fprintf(f, "struct %s *_self", dsrna->dnaname);
+ if (dsrna->dnafromprop) fprintf(f, "struct %s *_self", dsrna->dnafromname);
+ else if (dsrna->dnaname) fprintf(f, "struct %s *_self", dsrna->dnaname);
else fprintf(f, "struct %s *_self", srna->identifier);
first = 0;
}
@@ -2779,7 +2790,7 @@ static void rna_generate_struct_prototypes(FILE *f)
const char *struct_name = rna_parameter_type_name(dp->prop);
for (a = 0; a < all_structures; a++) {
- if (strcmp(struct_name, structures[a]) == 0) {
+ if (STREQ(struct_name, structures[a])) {
found = 1;
break;
}
@@ -3282,6 +3293,7 @@ static RNAProcessItem PROCESS_ITEMS[] = {
{"rna_context.c", NULL, RNA_def_context},
{"rna_controller.c", "rna_controller_api.c", RNA_def_controller},
{"rna_curve.c", "rna_curve_api.c", RNA_def_curve},
+ {"rna_depsgraph.c", NULL, RNA_def_depsgraph},
{"rna_dynamicpaint.c", NULL, RNA_def_dynamic_paint},
{"rna_fcurve.c", "rna_fcurve_api.c", RNA_def_fcurve},
{"rna_fluidsim.c", NULL, RNA_def_fluidsim},
@@ -3302,6 +3314,7 @@ static RNAProcessItem PROCESS_ITEMS[] = {
{"rna_object.c", "rna_object_api.c", RNA_def_object},
{"rna_object_force.c", NULL, RNA_def_object_force},
{"rna_packedfile.c", NULL, RNA_def_packedfile},
+ {"rna_palette.c", NULL, RNA_def_palette},
{"rna_particle.c", NULL, RNA_def_particle},
{"rna_pose.c", "rna_pose_api.c", RNA_def_pose},
{"rna_property.c", NULL, RNA_def_gameproperty},
@@ -3318,10 +3331,10 @@ static RNAProcessItem PROCESS_ITEMS[] = {
{"rna_test.c", NULL, RNA_def_test},
{"rna_text.c", "rna_text_api.c", RNA_def_text},
{"rna_timeline.c", NULL, RNA_def_timeline_marker},
- {"rna_sound.c", NULL, RNA_def_sound},
+ {"rna_sound.c", "rna_sound_api.c", RNA_def_sound},
{"rna_ui.c", "rna_ui_api.c", RNA_def_ui},
{"rna_userdef.c", NULL, RNA_def_userdef},
- {"rna_vfont.c", NULL, RNA_def_vfont},
+ {"rna_vfont.c", "rna_vfont_api.c", RNA_def_vfont},
{"rna_wm.c", "rna_wm_api.c", RNA_def_wm},
{"rna_world.c", NULL, RNA_def_world},
{"rna_movieclip.c", NULL, RNA_def_movieclip},
@@ -3365,7 +3378,9 @@ static void rna_generate(BlenderRNA *brna, FILE *f, const char *filename, const
fprintf(f, "#include \"RNA_types.h\"\n");
fprintf(f, "#include \"rna_internal.h\"\n\n");
- rna_generate_prototypes(brna, f);
+
+ /* include the generated prototypes header */
+ fprintf(f, "#include \"rna_prototypes_gen.h\"\n\n");
fprintf(f, "#include \"%s\"\n", filename);
if (api_filename)
@@ -3410,7 +3425,7 @@ static void rna_generate(BlenderRNA *brna, FILE *f, const char *filename, const
if (!filename || ds->filename == filename)
rna_generate_struct(brna, ds->srna, f);
- if (strcmp(filename, "rna_ID.c") == 0) {
+ if (STREQ(filename, "rna_ID.c")) {
/* this is ugly, but we cannot have c files compiled for both
* makesrna and blender with some build systems at the moment */
fprintf(f, "#include \"rna_define.c\"\n\n");
@@ -3675,7 +3690,7 @@ static const char *cpp_classes = ""
" int length;\n"
"\n"
" DynamicArray() : data(NULL), length(0) {}\n"
-" DynamicArray(int new_length) : data(NULL), length(new_length) { data = (float *)malloc(sizeof(T) * new_length); }\n"
+" DynamicArray(int new_length) : data(NULL), length(new_length) { data = (T *)malloc(sizeof(T) * new_length); }\n"
" DynamicArray(const DynamicArray<T>& other) { copy_from(other); }\n"
" const DynamicArray<T>& operator = (const DynamicArray<T>& other) { copy_from(other); return *this; }\n"
"\n"
@@ -3686,7 +3701,7 @@ static const char *cpp_classes = ""
"protected:\n"
" void copy_from(const DynamicArray<T>& other) {\n"
" if (data) free(data);\n"
-" data = (float *)malloc(sizeof(T) * other.length);\n"
+" data = (T *)malloc(sizeof(T) * other.length);\n"
" memcpy(data, other.data, sizeof(T) * other.length);\n"
" length = other.length;\n"
" }\n"
@@ -3753,7 +3768,7 @@ static const char *cpp_classes = ""
"\n"
"class DefaultCollectionFunctions {\n"
"public:\n"
-" DefaultCollectionFunctions(const PointerRNA &p) {}\n"
+" DefaultCollectionFunctions(const PointerRNA & /*p*/) {}\n"
"};\n"
"\n"
"\n";
@@ -3772,7 +3787,7 @@ static int rna_is_collection_functions_struct(const char **collection_structs, c
int a = 0, found = 0;
while (collection_structs[a]) {
- if (!strcmp(collection_structs[a], struct_name)) {
+ if (STREQ(collection_structs[a], struct_name)) {
found = 1;
break;
}
@@ -3873,7 +3888,7 @@ static void rna_generate_header_cpp(BlenderRNA *UNUSED(brna), FILE *f)
for (ds = DefRNA.structs.first; ds; ds = ds->cont.next) {
srna = ds->srna;
- if (!strcmp(srna->identifier, first_collection_func_struct)) {
+ if (STREQ(srna->identifier, first_collection_func_struct)) {
StructDefRNA *ds2;
StructRNA *srna2;
@@ -3960,6 +3975,26 @@ static int rna_preprocess(const char *outfile)
status = (DefRNA.error != 0);
+ /* create rna prototype header file */
+ strcpy(deffile, outfile);
+ strcat(deffile, "rna_prototypes_gen.h");
+ if (status) {
+ make_bad_file(deffile, __LINE__);
+ }
+ file = fopen(deffile, "w");
+ if (!file) {
+ fprintf(stderr, "Unable to open file: %s\n", deffile);
+ status = 1;
+ }
+ else {
+ fprintf(file,
+ "/* Automatically generated function declarations for the Data API.\n"
+ " * Do not edit manually, changes will be overwritten. */\n\n");
+ rna_generate_prototypes(brna, file);
+ fclose(file);
+ status = (DefRNA.error != 0);
+ }
+
/* create rna_gen_*.c files */
for (i = 0; PROCESS_ITEMS[i].filename; i++) {
strcpy(deffile, outfile);
diff --git a/source/blender/makesrna/intern/rna_ID.c b/source/blender/makesrna/intern/rna_ID.c
index 83fe56102ac..88065d29a50 100644
--- a/source/blender/makesrna/intern/rna_ID.c
+++ b/source/blender/makesrna/intern/rna_ID.c
@@ -34,6 +34,8 @@
#include "BLI_utildefines.h"
+#include "BKE_icons.h"
+
#include "RNA_access.h"
#include "RNA_define.h"
#include "RNA_enum_types.h"
@@ -60,25 +62,31 @@ EnumPropertyItem id_type_items[] = {
{ID_LI, "LIBRARY", ICON_LIBRARY_DATA_DIRECT, "Library", ""},
{ID_LS, "LINESTYLE", ICON_LINE_DATA, "Line Style", ""},
{ID_LT, "LATTICE", ICON_LATTICE_DATA, "Lattice", ""},
+ {ID_MSK, "MASK", ICON_MOD_MASK, "Mask", ""},
{ID_MA, "MATERIAL", ICON_MATERIAL_DATA, "Material", ""},
{ID_MB, "META", ICON_META_DATA, "MetaBall", ""},
{ID_ME, "MESH", ICON_MESH_DATA, "Mesh", ""},
+ {ID_MC, "MOVIECLIP", ICON_CLIP, "MovieClip", ""},
{ID_NT, "NODETREE", ICON_NODETREE, "NodeTree", ""},
{ID_OB, "OBJECT", ICON_OBJECT_DATA, "Object", ""},
+ {ID_PC, "PAINTCURVE", ICON_CURVE_BEZCURVE, "Paint Curve", ""},
+ {ID_PAL, "PALETTE", ICON_COLOR, "Palette", ""},
{ID_PA, "PARTICLE", ICON_PARTICLE_DATA, "Particle", ""},
{ID_SCE, "SCENE", ICON_SCENE_DATA, "Scene", ""},
{ID_SCR, "SCREEN", ICON_SPLITSCREEN, "Screen", ""},
- {ID_SPK, "SPEAKER", ICON_SPEAKER, "Speaker", ""},
{ID_SO, "SOUND", ICON_PLAY_AUDIO, "Sound", ""},
+ {ID_SPK, "SPEAKER", ICON_SPEAKER, "Speaker", ""},
{ID_TXT, "TEXT", ICON_TEXT, "Text", ""},
{ID_TE, "TEXTURE", ICON_TEXTURE_DATA, "Texture", ""},
- {ID_WO, "WORLD", ICON_WORLD_DATA, "World", ""},
{ID_WM, "WINDOWMANAGER", ICON_FULLSCREEN, "Window Manager", ""},
+ {ID_WO, "WORLD", ICON_WORLD_DATA, "World", ""},
{0, NULL, 0, NULL, NULL}
};
#ifdef RNA_RUNTIME
+#include "DNA_anim_types.h"
+
#include "BKE_font.h"
#include "BKE_idprop.h"
#include "BKE_library.h"
@@ -138,23 +146,23 @@ short RNA_type_to_ID_code(StructRNA *type)
if (RNA_struct_is_a(type, &RNA_Lattice)) return ID_LT;
if (RNA_struct_is_a(type, &RNA_Material)) return ID_MA;
if (RNA_struct_is_a(type, &RNA_MetaBall)) return ID_MB;
- if (RNA_struct_is_a(type, &RNA_NodeTree)) return ID_NT;
+ if (RNA_struct_is_a(type, &RNA_MovieClip)) return ID_MC;
if (RNA_struct_is_a(type, &RNA_Mesh)) return ID_ME;
+ if (RNA_struct_is_a(type, &RNA_Mask)) return ID_MSK;
+ if (RNA_struct_is_a(type, &RNA_NodeTree)) return ID_NT;
if (RNA_struct_is_a(type, &RNA_Object)) return ID_OB;
if (RNA_struct_is_a(type, &RNA_ParticleSettings)) return ID_PA;
+ if (RNA_struct_is_a(type, &RNA_Palette)) return ID_PAL;
+ if (RNA_struct_is_a(type, &RNA_PaintCurve)) return ID_PC;
if (RNA_struct_is_a(type, &RNA_Scene)) return ID_SCE;
if (RNA_struct_is_a(type, &RNA_Screen)) return ID_SCR;
- if (RNA_struct_is_a(type, &RNA_Speaker)) return ID_SPK;
if (RNA_struct_is_a(type, &RNA_Sound)) return ID_SO;
- if (RNA_struct_is_a(type, &RNA_Text)) return ID_TXT;
+ if (RNA_struct_is_a(type, &RNA_Speaker)) return ID_SPK;
if (RNA_struct_is_a(type, &RNA_Texture)) return ID_TE;
+ if (RNA_struct_is_a(type, &RNA_Text)) return ID_TXT;
if (RNA_struct_is_a(type, &RNA_VectorFont)) return ID_VF;
if (RNA_struct_is_a(type, &RNA_World)) return ID_WO;
if (RNA_struct_is_a(type, &RNA_WindowManager)) return ID_WM;
- if (RNA_struct_is_a(type, &RNA_MovieClip)) return ID_MC;
- if (RNA_struct_is_a(type, &RNA_Mask)) return ID_MSK;
- if (RNA_struct_is_a(type, &RNA_Palette)) return ID_PAL;
- if (RNA_struct_is_a(type, &RNA_PaintCurve)) return ID_PC;
return 0;
}
@@ -177,23 +185,23 @@ StructRNA *ID_code_to_RNA_type(short idcode)
case ID_LT: return &RNA_Lattice;
case ID_MA: return &RNA_Material;
case ID_MB: return &RNA_MetaBall;
- case ID_NT: return &RNA_NodeTree;
+ case ID_MC: return &RNA_MovieClip;
case ID_ME: return &RNA_Mesh;
+ case ID_MSK: return &RNA_Mask;
+ case ID_NT: return &RNA_NodeTree;
case ID_OB: return &RNA_Object;
case ID_PA: return &RNA_ParticleSettings;
+ case ID_PAL: return &RNA_Palette;
+ case ID_PC: return &RNA_PaintCurve;
case ID_SCE: return &RNA_Scene;
case ID_SCR: return &RNA_Screen;
- case ID_SPK: return &RNA_Speaker;
case ID_SO: return &RNA_Sound;
- case ID_TXT: return &RNA_Text;
+ case ID_SPK: return &RNA_Speaker;
case ID_TE: return &RNA_Texture;
+ case ID_TXT: return &RNA_Text;
case ID_VF: return &RNA_VectorFont;
- case ID_WO: return &RNA_World;
case ID_WM: return &RNA_WindowManager;
- case ID_MC: return &RNA_MovieClip;
- case ID_MSK: return &RNA_Mask;
- case ID_PAL: return &RNA_Palette;
- case ID_PC: return &RNA_PaintCurve;
+ case ID_WO: return &RNA_World;
default: return &RNA_ID;
}
@@ -325,6 +333,19 @@ static void rna_ID_user_clear(ID *id)
id->flag &= ~LIB_FAKEUSER;
}
+static AnimData * rna_ID_animation_data_create(ID *id, Main *bmain)
+{
+ AnimData *adt = BKE_animdata_add_id(id);
+ DAG_relations_tag_update(bmain);
+ return adt;
+}
+
+static void rna_ID_animation_data_free(ID *id, Main *bmain)
+{
+ BKE_animdata_free(id);
+ DAG_relations_tag_update(bmain);
+}
+
static void rna_IDPArray_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
{
IDProperty *prop = (IDProperty *)ptr->data;
@@ -402,6 +423,288 @@ static void rna_Library_filepath_set(PointerRNA *ptr, const char *value)
BKE_library_filepath_set(lib, value);
}
+/* ***** ImagePreview ***** */
+
+static void rna_ImagePreview_is_custom_set(PointerRNA *ptr, int value, enum eIconSizes size)
+{
+ ID *id = ptr->id.data;
+ PreviewImage *prv_img = (PreviewImage *)ptr->data;
+
+ if (id != NULL) {
+ BLI_assert(prv_img == BKE_previewimg_id_ensure(id));
+ }
+
+ if ((value && (prv_img->flag[size] & PRV_USER_EDITED)) || (!value && !(prv_img->flag[size] & PRV_USER_EDITED))) {
+ return;
+ }
+
+ if (value)
+ prv_img->flag[size] |= PRV_USER_EDITED;
+ else
+ prv_img->flag[size] &= ~PRV_USER_EDITED;
+
+ prv_img->flag[size] |= PRV_CHANGED;
+
+ BKE_previewimg_clear_single(prv_img, size);
+}
+
+static void rna_ImagePreview_size_get(PointerRNA *ptr, int *values, enum eIconSizes size)
+{
+ ID *id = (ID *)ptr->id.data;
+ PreviewImage *prv_img = (PreviewImage *)ptr->data;
+
+ if (id != NULL) {
+ BLI_assert(prv_img == BKE_previewimg_id_ensure(id));
+ }
+
+ BKE_previewimg_ensure(prv_img, size);
+
+ values[0] = prv_img->w[size];
+ values[1] = prv_img->h[size];
+}
+
+static void rna_ImagePreview_size_set(PointerRNA *ptr, const int *values, enum eIconSizes size)
+{
+ ID *id = (ID *)ptr->id.data;
+ PreviewImage *prv_img = (PreviewImage *)ptr->data;
+
+ if (id != NULL) {
+ BLI_assert(prv_img == BKE_previewimg_id_ensure(id));
+ }
+
+ BKE_previewimg_clear_single(prv_img, size);
+
+ if (values[0] && values[1]) {
+ prv_img->rect[size] = MEM_callocN(values[0] * values[1] * sizeof(unsigned int), "prv_rect");
+
+ prv_img->w[size] = values[0];
+ prv_img->h[size] = values[1];
+ }
+
+ prv_img->flag[size] |= (PRV_CHANGED | PRV_USER_EDITED);
+}
+
+
+static int rna_ImagePreview_pixels_get_length(PointerRNA *ptr, int length[RNA_MAX_ARRAY_DIMENSION], enum eIconSizes size)
+{
+ ID *id = ptr->id.data;
+ PreviewImage *prv_img = (PreviewImage *)ptr->data;
+
+ if (id != NULL) {
+ BLI_assert(prv_img == BKE_previewimg_id_ensure(id));
+ }
+
+ BKE_previewimg_ensure(prv_img, size);
+
+ length[0] = prv_img->w[size] * prv_img->h[size];
+
+ return length[0];
+}
+
+static void rna_ImagePreview_pixels_get(PointerRNA *ptr, int *values, enum eIconSizes size)
+{
+ ID *id = ptr->id.data;
+ PreviewImage *prv_img = (PreviewImage *)ptr->data;
+
+ if (id != NULL) {
+ BLI_assert(prv_img == BKE_previewimg_id_ensure(id));
+ }
+
+ BKE_previewimg_ensure(prv_img, size);
+
+ memcpy(values, prv_img->rect[size], prv_img->w[size] * prv_img->h[size] * sizeof(unsigned int));
+}
+
+static void rna_ImagePreview_pixels_set(PointerRNA *ptr, const int *values, enum eIconSizes size)
+{
+ ID *id = ptr->id.data;
+ PreviewImage *prv_img = (PreviewImage *)ptr->data;
+
+ if (id != NULL) {
+ BLI_assert(prv_img == BKE_previewimg_id_ensure(id));
+ }
+
+ memcpy(prv_img->rect[size], values, prv_img->w[size] * prv_img->h[size] * sizeof(unsigned int));
+ prv_img->flag[size] |= PRV_USER_EDITED;
+}
+
+
+static int rna_ImagePreview_pixels_float_get_length(
+ PointerRNA *ptr, int length[RNA_MAX_ARRAY_DIMENSION], enum eIconSizes size)
+{
+ ID *id = ptr->id.data;
+ PreviewImage *prv_img = (PreviewImage *)ptr->data;
+
+ BLI_assert(sizeof(unsigned int) == 4);
+
+ if (id != NULL) {
+ BLI_assert(prv_img == BKE_previewimg_id_ensure(id));
+ }
+
+ BKE_previewimg_ensure(prv_img, size);
+
+ length[0] = prv_img->w[size] * prv_img->h[size] * 4;
+
+ return length[0];
+}
+
+static void rna_ImagePreview_pixels_float_get(PointerRNA *ptr, float *values, enum eIconSizes size)
+{
+ ID *id = ptr->id.data;
+ PreviewImage *prv_img = (PreviewImage *)ptr->data;
+
+ unsigned char *data = (unsigned char *)prv_img->rect[size];
+ const size_t len = prv_img->w[size] * prv_img->h[size] * 4;
+ size_t i;
+
+ BLI_assert(sizeof(unsigned int) == 4);
+
+ if (id != NULL) {
+ BLI_assert(prv_img == BKE_previewimg_id_ensure(id));
+ }
+
+ BKE_previewimg_ensure(prv_img, size);
+
+ for (i = 0; i < len; i++) {
+ values[i] = data[i] * (1.0f / 255.0f);
+ }
+}
+
+static void rna_ImagePreview_pixels_float_set(PointerRNA *ptr, const float *values, enum eIconSizes size)
+{
+ ID *id = ptr->id.data;
+ PreviewImage *prv_img = (PreviewImage *)ptr->data;
+
+ unsigned char *data = (unsigned char *)prv_img->rect[size];
+ const size_t len = prv_img->w[size] * prv_img->h[size] * 4;
+ size_t i;
+
+ BLI_assert(sizeof(unsigned int) == 4);
+
+ if (id != NULL) {
+ BLI_assert(prv_img == BKE_previewimg_id_ensure(id));
+ }
+
+ for (i = 0; i < len; i++) {
+ data[i] = FTOCHAR(values[i]);
+ }
+ prv_img->flag[size] |= PRV_USER_EDITED;
+}
+
+
+static void rna_ImagePreview_is_image_custom_set(PointerRNA *ptr, int value)
+{
+ rna_ImagePreview_is_custom_set(ptr, value, ICON_SIZE_PREVIEW);
+}
+
+static void rna_ImagePreview_image_size_get(PointerRNA *ptr, int *values)
+{
+ rna_ImagePreview_size_get(ptr, values, ICON_SIZE_PREVIEW);
+}
+
+static void rna_ImagePreview_image_size_set(PointerRNA *ptr, const int *values)
+{
+ rna_ImagePreview_size_set(ptr, values, ICON_SIZE_PREVIEW);
+}
+
+static int rna_ImagePreview_image_pixels_get_length(PointerRNA *ptr, int length[RNA_MAX_ARRAY_DIMENSION])
+{
+ return rna_ImagePreview_pixels_get_length(ptr, length, ICON_SIZE_PREVIEW);
+}
+
+static void rna_ImagePreview_image_pixels_get(PointerRNA *ptr, int *values)
+{
+ rna_ImagePreview_pixels_get(ptr, values, ICON_SIZE_PREVIEW);
+}
+
+static void rna_ImagePreview_image_pixels_set(PointerRNA *ptr, const int *values)
+{
+ rna_ImagePreview_pixels_set(ptr, values, ICON_SIZE_PREVIEW);
+}
+
+static int rna_ImagePreview_image_pixels_float_get_length(PointerRNA *ptr, int length[RNA_MAX_ARRAY_DIMENSION])
+{
+ return rna_ImagePreview_pixels_float_get_length(ptr, length, ICON_SIZE_PREVIEW);
+}
+
+static void rna_ImagePreview_image_pixels_float_get(PointerRNA *ptr, float *values)
+{
+ rna_ImagePreview_pixels_float_get(ptr, values, ICON_SIZE_PREVIEW);
+}
+
+static void rna_ImagePreview_image_pixels_float_set(PointerRNA *ptr, const float *values)
+{
+ rna_ImagePreview_pixels_float_set(ptr, values, ICON_SIZE_PREVIEW);
+}
+
+
+static void rna_ImagePreview_is_icon_custom_set(PointerRNA *ptr, int value)
+{
+ rna_ImagePreview_is_custom_set(ptr, value, ICON_SIZE_ICON);
+}
+
+static void rna_ImagePreview_icon_size_get(PointerRNA *ptr, int *values)
+{
+ rna_ImagePreview_size_get(ptr, values, ICON_SIZE_ICON);
+}
+
+static void rna_ImagePreview_icon_size_set(PointerRNA *ptr, const int *values)
+{
+ rna_ImagePreview_size_set(ptr, values, ICON_SIZE_ICON);
+}
+
+static int rna_ImagePreview_icon_pixels_get_length(PointerRNA *ptr, int length[RNA_MAX_ARRAY_DIMENSION])
+{
+ return rna_ImagePreview_pixels_get_length(ptr, length, ICON_SIZE_ICON);
+}
+
+static void rna_ImagePreview_icon_pixels_get(PointerRNA *ptr, int *values)
+{
+ rna_ImagePreview_pixels_get(ptr, values, ICON_SIZE_ICON);
+}
+
+static void rna_ImagePreview_icon_pixels_set(PointerRNA *ptr, const int *values)
+{
+ rna_ImagePreview_pixels_set(ptr, values, ICON_SIZE_ICON);
+}
+
+static int rna_ImagePreview_icon_pixels_float_get_length(PointerRNA *ptr, int length[RNA_MAX_ARRAY_DIMENSION])
+{
+ return rna_ImagePreview_pixels_float_get_length(ptr, length, ICON_SIZE_ICON);
+}
+
+static void rna_ImagePreview_icon_pixels_float_get(PointerRNA *ptr, float *values)
+{
+ rna_ImagePreview_pixels_float_get(ptr, values, ICON_SIZE_ICON);
+}
+
+static void rna_ImagePreview_icon_pixels_float_set(PointerRNA *ptr, const float *values)
+{
+ rna_ImagePreview_pixels_float_set(ptr, values, ICON_SIZE_ICON);
+}
+
+
+static int rna_ImagePreview_icon_id_get(PointerRNA *ptr)
+{
+ /* Using a callback here allows us to only generate icon matching that preview when icon_id is requested. */
+ return BKE_icon_preview_ensure((PreviewImage *)(ptr->data));
+}
+static void rna_ImagePreview_icon_reload(PreviewImage *prv)
+{
+ /* will lazy load on next use, but only in case icon is not user-modified! */
+ if (!(prv->flag[ICON_SIZE_ICON] & PRV_USER_EDITED) && !(prv->flag[ICON_SIZE_PREVIEW] & PRV_USER_EDITED)) {
+ BKE_previewimg_clear(prv);
+ }
+}
+
+static PointerRNA rna_IDPreview_get(PointerRNA *ptr)
+{
+ ID *id = (ID *)ptr->data;
+ PreviewImage *prv_img = BKE_previewimg_id_ensure(id);
+
+ return rna_pointer_inherit_refine(ptr, &RNA_ImagePreview, prv_img);
+}
+
#else
static void rna_def_ID_properties(BlenderRNA *brna)
@@ -520,6 +823,79 @@ static void rna_def_ID_materials(BlenderRNA *brna)
RNA_def_boolean(func, "update_data", 0, "", "Update data by re-adjusting the material slots assigned");
}
+static void rna_def_image_preview(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ FunctionRNA *func;
+ PropertyRNA *prop;
+
+ srna = RNA_def_struct(brna, "ImagePreview", NULL);
+ RNA_def_struct_sdna(srna, "PreviewImage");
+ RNA_def_struct_ui_text(srna, "Image Preview", "Preview image and icon");
+
+ prop = RNA_def_property(srna, "is_image_custom", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag[ICON_SIZE_PREVIEW]", PRV_USER_EDITED);
+ RNA_def_property_boolean_funcs(prop, NULL, "rna_ImagePreview_is_image_custom_set");
+ RNA_def_property_ui_text(prop, "Custom Image", "True if this preview image has been modified by py script,"
+ "and is no more auto-generated by Blender");
+
+ prop = RNA_def_int_vector(srna, "image_size", 2, NULL, 0, 0, "Image Size",
+ "Width and height in pixels", 0, 0);
+ RNA_def_property_subtype(prop, PROP_PIXEL);
+ RNA_def_property_int_funcs(prop, "rna_ImagePreview_image_size_get", "rna_ImagePreview_image_size_set", NULL);
+
+ prop = RNA_def_property(srna, "image_pixels", PROP_INT, PROP_NONE);
+ RNA_def_property_flag(prop, PROP_DYNAMIC);
+ RNA_def_property_multi_array(prop, 1, NULL);
+ RNA_def_property_ui_text(prop, "Image Pixels", "Image pixels, as bytes (always RGBA 32bits)");
+ RNA_def_property_dynamic_array_funcs(prop, "rna_ImagePreview_image_pixels_get_length");
+ RNA_def_property_int_funcs(prop, "rna_ImagePreview_image_pixels_get", "rna_ImagePreview_image_pixels_set", NULL);
+
+ prop = RNA_def_property(srna, "image_pixels_float", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_flag(prop, PROP_DYNAMIC);
+ RNA_def_property_multi_array(prop, 1, NULL);
+ RNA_def_property_ui_text(prop, "Float Image Pixels",
+ "Image pixels components, as floats (RGBA concatenated values)");
+ RNA_def_property_dynamic_array_funcs(prop, "rna_ImagePreview_image_pixels_float_get_length");
+ RNA_def_property_float_funcs(prop, "rna_ImagePreview_image_pixels_float_get",
+ "rna_ImagePreview_image_pixels_float_set", NULL);
+
+
+ prop = RNA_def_property(srna, "is_icon_custom", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag[ICON_SIZE_ICON]", PRV_USER_EDITED);
+ RNA_def_property_boolean_funcs(prop, NULL, "rna_ImagePreview_is_icon_custom_set");
+ RNA_def_property_ui_text(prop, "Custom Icon", "True if this preview icon has been modified by py script,"
+ "and is no more auto-generated by Blender");
+
+ prop = RNA_def_int_vector(srna, "icon_size", 2, NULL, 0, 0, "Icon Size",
+ "Width and height in pixels", 0, 0);
+ RNA_def_property_subtype(prop, PROP_PIXEL);
+ RNA_def_property_int_funcs(prop, "rna_ImagePreview_icon_size_get", "rna_ImagePreview_icon_size_set", NULL);
+
+ prop = RNA_def_property(srna, "icon_pixels", PROP_INT, PROP_NONE);
+ RNA_def_property_flag(prop, PROP_DYNAMIC);
+ RNA_def_property_multi_array(prop, 1, NULL);
+ RNA_def_property_ui_text(prop, "Icon Pixels", "Icon pixels, as bytes (always RGBA 32bits)");
+ RNA_def_property_dynamic_array_funcs(prop, "rna_ImagePreview_icon_pixels_get_length");
+ RNA_def_property_int_funcs(prop, "rna_ImagePreview_icon_pixels_get", "rna_ImagePreview_icon_pixels_set", NULL);
+
+ prop = RNA_def_property(srna, "icon_pixels_float", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_flag(prop, PROP_DYNAMIC);
+ RNA_def_property_multi_array(prop, 1, NULL);
+ RNA_def_property_ui_text(prop, "Float Icon Pixels", "Icon pixels components, as floats (RGBA concatenated values)");
+ RNA_def_property_dynamic_array_funcs(prop, "rna_ImagePreview_icon_pixels_float_get_length");
+ RNA_def_property_float_funcs(prop, "rna_ImagePreview_icon_pixels_float_get",
+ "rna_ImagePreview_icon_pixels_float_set", NULL);
+
+ prop = RNA_def_int(srna, "icon_id", 0, INT_MIN, INT_MAX, "Icon ID",
+ "Unique integer identifying this preview as an icon (zero means invalid)", INT_MIN, INT_MAX);
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_property_int_funcs(prop, "rna_ImagePreview_icon_id_get", NULL, NULL);
+
+ func = RNA_def_function(srna, "reload", "rna_ImagePreview_icon_reload");
+ RNA_def_function_ui_description(func, "Reload the preview from its source path");
+}
+
static void rna_def_ID(BlenderRNA *brna)
{
StructRNA *srna;
@@ -562,7 +938,9 @@ static void rna_def_ID(BlenderRNA *brna)
prop = RNA_def_property(srna, "tag", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", LIB_DOIT);
RNA_def_property_flag(prop, PROP_LIB_EXCEPTION);
- RNA_def_property_ui_text(prop, "Tag", "Tools can use this to tag data (initial state is undefined)");
+ RNA_def_property_ui_text(prop, "Tag",
+ "Tools can use this to tag data for their own purposes "
+ "(initial state is undefined)");
prop = RNA_def_property(srna, "is_updated", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", LIB_ID_RECALC);
@@ -584,6 +962,11 @@ static void rna_def_ID(BlenderRNA *brna)
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_ui_text(prop, "Library", "Library file the datablock is linked from");
+ prop = RNA_def_pointer(srna, "preview", "ImagePreview", "Preview",
+ "Preview image and icon of this datablock (None if not supported for this type of data)");
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_property_pointer_funcs(prop, "rna_IDPreview_get", NULL, NULL, NULL);
+
/* functions */
func = RNA_def_function(srna, "copy", "rna_ID_copy");
RNA_def_function_ui_description(func, "Create a copy of this datablock (not supported for all datablocks)");
@@ -594,17 +977,21 @@ static void rna_def_ID(BlenderRNA *brna)
RNA_def_function_ui_description(func, "Clear the user count of a datablock so its not saved, "
"on reload the data will be removed");
- func = RNA_def_function(srna, "animation_data_create", "BKE_id_add_animdata");
+ func = RNA_def_function(srna, "animation_data_create", "rna_ID_animation_data_create");
+ RNA_def_function_flag(func, FUNC_USE_MAIN);
RNA_def_function_ui_description(func, "Create animation data to this ID, note that not all ID types support this");
parm = RNA_def_pointer(func, "anim_data", "AnimData", "", "New animation data or NULL");
RNA_def_function_return(func, parm);
- func = RNA_def_function(srna, "animation_data_clear", "BKE_free_animdata");
+ func = RNA_def_function(srna, "animation_data_clear", "rna_ID_animation_data_free");
+ RNA_def_function_flag(func, FUNC_USE_MAIN);
RNA_def_function_ui_description(func, "Clear animation on this this ID");
func = RNA_def_function(srna, "update_tag", "rna_ID_update_tag");
RNA_def_function_flag(func, FUNC_USE_REPORTS);
- RNA_def_function_ui_description(func, "Tag the ID to update its display data");
+ RNA_def_function_ui_description(func,
+ "Tag the ID to update its display data, "
+ "e.g. when calling :class:`bpy.types.Scene.update`");
RNA_def_enum_flag(func, "refresh", update_flag_items, 0, "", "Type of updates to perform");
}
@@ -643,6 +1030,7 @@ void RNA_def_ID(BlenderRNA *brna)
RNA_def_struct_ui_text(srna, "Any Type", "RNA type used for pointers to any possible data");
rna_def_ID(brna);
+ rna_def_image_preview(brna);
rna_def_ID_properties(brna);
rna_def_ID_materials(brna);
rna_def_library(brna);
diff --git a/source/blender/makesrna/intern/rna_access.c b/source/blender/makesrna/intern/rna_access.c
index 34e78018b03..b7478fd3311 100644
--- a/source/blender/makesrna/intern/rna_access.c
+++ b/source/blender/makesrna/intern/rna_access.c
@@ -43,7 +43,7 @@
#include "BLI_math.h"
#include "BLF_api.h"
-#include "BLF_translation.h"
+#include "BLT_translation.h"
#include "BKE_animsys.h"
#include "BKE_context.h"
@@ -241,13 +241,13 @@ static IDProperty *rna_idproperty_ui(PropertyRNA *prop)
IDProperty *idprop;
for (idprop = ((IDProperty *)prop)->prev; idprop; idprop = idprop->prev) {
- if (strcmp(RNA_IDP_UI, idprop->name) == 0)
+ if (STREQ(RNA_IDP_UI, idprop->name))
break;
}
if (idprop == NULL) {
for (idprop = ((IDProperty *)prop)->next; idprop; idprop = idprop->next) {
- if (strcmp(RNA_IDP_UI, idprop->name) == 0)
+ if (STREQ(RNA_IDP_UI, idprop->name))
break;
}
}
@@ -466,7 +466,7 @@ static const char *rna_ensure_property_identifier(const PropertyRNA *prop)
if (prop->magic == RNA_MAGIC)
return prop->identifier;
else
- return ((IDProperty *)prop)->name;
+ return ((const IDProperty *)prop)->name;
}
static const char *rna_ensure_property_description(PropertyRNA *prop)
@@ -499,7 +499,7 @@ static const char *rna_ensure_property_name(const PropertyRNA *prop)
if (prop->magic == RNA_MAGIC)
name = prop->name;
else
- name = ((IDProperty *)prop)->name;
+ name = ((const IDProperty *)prop)->name;
return name;
}
@@ -511,7 +511,7 @@ StructRNA *RNA_struct_find(const char *identifier)
StructRNA *type;
if (identifier) {
for (type = BLENDER_RNA.structs.first; type; type = type->cont.next)
- if (strcmp(type->identifier, identifier) == 0)
+ if (STREQ(type->identifier, identifier))
return type;
}
return NULL;
@@ -719,7 +719,7 @@ FunctionRNA *RNA_struct_find_function(StructRNA *srna, const char *identifier)
RNA_PROP_BEGIN (&tptr, funcptr, iterprop)
{
- if (strcmp(identifier, RNA_function_identifier(funcptr.data)) == 0) {
+ if (STREQ(identifier, RNA_function_identifier(funcptr.data))) {
func = funcptr.data;
break;
}
@@ -903,7 +903,7 @@ int RNA_property_array_item_index(PropertyRNA *prop, char name)
return 3;
}
}
- else if (ELEM(subtype, PROP_TRANSLATION, PROP_DIRECTION, PROP_XYZ,
+ else if (ELEM(subtype, PROP_TRANSLATION, PROP_DIRECTION, PROP_XYZ, PROP_XYZ_LENGTH,
PROP_EULER, PROP_VELOCITY, PROP_ACCELERATION))
{
switch (name) {
@@ -1256,9 +1256,9 @@ static void property_enum_translate(PropertyRNA *prop, EnumPropertyItem **r_item
if (!(prop->flag & PROP_ENUM_NO_TRANSLATE)) {
int i;
- /* Note: Only do those tests once, and then use BLF_pgettext. */
- bool do_iface = BLF_translate_iface();
- bool do_tooltip = BLF_translate_tooltips();
+ /* Note: Only do those tests once, and then use BLT_pgettext. */
+ bool do_iface = BLT_translate_iface();
+ bool do_tooltip = BLT_translate_tooltips();
EnumPropertyItem *nitem;
if (!(do_iface || do_tooltip))
@@ -1289,10 +1289,10 @@ static void property_enum_translate(PropertyRNA *prop, EnumPropertyItem **r_item
for (i = 0; nitem[i].identifier; i++) {
if (nitem[i].name && do_iface) {
- nitem[i].name = BLF_pgettext(prop->translation_context, nitem[i].name);
+ nitem[i].name = BLT_pgettext(prop->translation_context, nitem[i].name);
}
if (nitem[i].description && do_tooltip) {
- nitem[i].description = BLF_pgettext(NULL, nitem[i].description);
+ nitem[i].description = BLT_pgettext(NULL, nitem[i].description);
}
}
@@ -1505,8 +1505,8 @@ bool RNA_property_enum_name_gettexted(bContext *C, PointerRNA *ptr, PropertyRNA
if (result) {
if (!(prop->flag & PROP_ENUM_NO_TRANSLATE)) {
- if (BLF_translate_iface()) {
- *name = BLF_pgettext(prop->translation_context, *name);
+ if (BLT_translate_iface()) {
+ *name = BLT_pgettext(prop->translation_context, *name);
}
}
}
@@ -1622,7 +1622,7 @@ bool RNA_property_animateable(PointerRNA *ptr, PropertyRNA *prop)
bool RNA_property_animated(PointerRNA *ptr, PropertyRNA *prop)
{
int len = 1, index;
- bool driven;
+ bool driven, special;
if (!prop)
return false;
@@ -1630,9 +1630,10 @@ bool RNA_property_animated(PointerRNA *ptr, PropertyRNA *prop)
if (RNA_property_array_check(prop))
len = RNA_property_array_length(ptr, prop);
- for (index = 0; index < len; index++)
- if (rna_get_fcurve(ptr, prop, index, NULL, &driven))
+ for (index = 0; index < len; index++) {
+ if (rna_get_fcurve(ptr, prop, index, NULL, NULL, &driven, &special))
return true;
+ }
return false;
}
@@ -1691,6 +1692,15 @@ static void rna_property_update(bContext *C, Main *bmain, Scene *scene, PointerR
* not especially nice */
DAG_id_tag_update(ptr->id.data, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
WM_main_add_notifier(NC_WINDOW, NULL);
+ /* Not nice as well, but the only way to make sure material preview
+ * is updated with custom nodes.
+ */
+ if ((prop->flag & PROP_IDPROPERTY) != 0 &&
+ (ptr->id.data != NULL) &&
+ (GS(((ID *)ptr->id.data)->name) == ID_NT))
+ {
+ WM_main_add_notifier(NC_MATERIAL | ND_SHADING, NULL);
+ }
}
}
@@ -1825,18 +1835,23 @@ int RNA_property_boolean_get(PointerRNA *ptr, PropertyRNA *prop)
{
BoolPropertyRNA *bprop = (BoolPropertyRNA *)prop;
IDProperty *idprop;
+ int value;
BLI_assert(RNA_property_type(prop) == PROP_BOOLEAN);
BLI_assert(RNA_property_array_check(prop) == false);
if ((idprop = rna_idproperty_check(&prop, ptr)))
- return IDP_Int(idprop);
+ value = IDP_Int(idprop);
else if (bprop->get)
- return bprop->get(ptr);
+ value = bprop->get(ptr);
else if (bprop->get_ex)
- return bprop->get_ex(ptr, prop);
+ value = bprop->get_ex(ptr, prop);
else
- return bprop->defaultvalue;
+ value = bprop->defaultvalue;
+
+ BLI_assert(ELEM(value, false, true));
+
+ return value;
}
void RNA_property_boolean_set(PointerRNA *ptr, PropertyRNA *prop, int value)
@@ -1846,6 +1861,7 @@ void RNA_property_boolean_set(PointerRNA *ptr, PropertyRNA *prop, int value)
BLI_assert(RNA_property_type(prop) == PROP_BOOLEAN);
BLI_assert(RNA_property_array_check(prop) == false);
+ BLI_assert(ELEM(value, false, true));
/* just in case other values are passed */
if (value) value = 1;
@@ -1902,25 +1918,29 @@ int RNA_property_boolean_get_index(PointerRNA *ptr, PropertyRNA *prop, int index
{
int tmp[RNA_MAX_ARRAY_LENGTH];
int len = rna_ensure_property_array_length(ptr, prop);
+ int value;
BLI_assert(RNA_property_type(prop) == PROP_BOOLEAN);
BLI_assert(RNA_property_array_check(prop) != false);
BLI_assert(index >= 0);
+ BLI_assert(index < len);
if (len <= RNA_MAX_ARRAY_LENGTH) {
RNA_property_boolean_get_array(ptr, prop, tmp);
- return tmp[index];
+ value = tmp[index];
}
else {
- int *tmparray, value;
+ int *tmparray;
- tmparray = MEM_callocN(sizeof(int) * len, "RNA_property_boolean_get_index");
+ tmparray = MEM_mallocN(sizeof(int) * len, __func__);
RNA_property_boolean_get_array(ptr, prop, tmparray);
value = tmparray[index];
MEM_freeN(tmparray);
-
- return value;
}
+
+ BLI_assert(ELEM(value, false, true));
+
+ return value;
}
void RNA_property_boolean_set_array(PointerRNA *ptr, PropertyRNA *prop, const int *values)
@@ -1969,6 +1989,8 @@ void RNA_property_boolean_set_index(PointerRNA *ptr, PropertyRNA *prop, int inde
BLI_assert(RNA_property_type(prop) == PROP_BOOLEAN);
BLI_assert(RNA_property_array_check(prop) != false);
BLI_assert(index >= 0);
+ BLI_assert(index < len);
+ BLI_assert(ELEM(value, false, true));
if (len <= RNA_MAX_ARRAY_LENGTH) {
RNA_property_boolean_get_array(ptr, prop, tmp);
@@ -1978,7 +2000,7 @@ void RNA_property_boolean_set_index(PointerRNA *ptr, PropertyRNA *prop, int inde
else {
int *tmparray;
- tmparray = MEM_callocN(sizeof(int) * len, "RNA_property_boolean_get_index");
+ tmparray = MEM_mallocN(sizeof(int) * len, __func__);
RNA_property_boolean_get_array(ptr, prop, tmparray);
tmparray[index] = value;
RNA_property_boolean_set_array(ptr, prop, tmparray);
@@ -1992,6 +2014,7 @@ int RNA_property_boolean_get_default(PointerRNA *UNUSED(ptr), PropertyRNA *prop)
BLI_assert(RNA_property_type(prop) == PROP_BOOLEAN);
BLI_assert(RNA_property_array_check(prop) == false);
+ BLI_assert(ELEM(bprop->defaultvalue, false, true));
return bprop->defaultvalue;
}
@@ -2019,6 +2042,7 @@ int RNA_property_boolean_get_default_index(PointerRNA *ptr, PropertyRNA *prop, i
BLI_assert(RNA_property_type(prop) == PROP_BOOLEAN);
BLI_assert(RNA_property_array_check(prop) != false);
BLI_assert(index >= 0);
+ BLI_assert(index < prop->totarraylength);
if (len <= RNA_MAX_ARRAY_LENGTH) {
RNA_property_boolean_get_default_array(ptr, prop, tmp);
@@ -2027,7 +2051,7 @@ int RNA_property_boolean_get_default_index(PointerRNA *ptr, PropertyRNA *prop, i
else {
int *tmparray, value;
- tmparray = MEM_callocN(sizeof(int) * len, "RNA_property_boolean_get_default_index");
+ tmparray = MEM_mallocN(sizeof(int) * len, __func__);
RNA_property_boolean_get_default_array(ptr, prop, tmparray);
value = tmparray[index];
MEM_freeN(tmparray);
@@ -2131,7 +2155,7 @@ void RNA_property_int_get_array_range(PointerRNA *ptr, PropertyRNA *prop, int va
int i;
if (array_len > 32) {
- arr = MEM_mallocN(sizeof(int) * array_len, "RNA_property_int_get_array_range");
+ arr = MEM_mallocN(sizeof(int) * array_len, __func__);
}
else {
arr = arr_stack;
@@ -2158,6 +2182,7 @@ int RNA_property_int_get_index(PointerRNA *ptr, PropertyRNA *prop, int index)
BLI_assert(RNA_property_type(prop) == PROP_INT);
BLI_assert(RNA_property_array_check(prop) != false);
BLI_assert(index >= 0);
+ BLI_assert(index < len);
if (len <= RNA_MAX_ARRAY_LENGTH) {
RNA_property_int_get_array(ptr, prop, tmp);
@@ -2166,7 +2191,7 @@ int RNA_property_int_get_index(PointerRNA *ptr, PropertyRNA *prop, int index)
else {
int *tmparray, value;
- tmparray = MEM_callocN(sizeof(int) * len, "RNA_property_int_get_index");
+ tmparray = MEM_mallocN(sizeof(int) * len, __func__);
RNA_property_int_get_array(ptr, prop, tmparray);
value = tmparray[index];
MEM_freeN(tmparray);
@@ -2224,6 +2249,7 @@ void RNA_property_int_set_index(PointerRNA *ptr, PropertyRNA *prop, int index, i
BLI_assert(RNA_property_type(prop) == PROP_INT);
BLI_assert(RNA_property_array_check(prop) != false);
BLI_assert(index >= 0);
+ BLI_assert(index < len);
if (len <= RNA_MAX_ARRAY_LENGTH) {
RNA_property_int_get_array(ptr, prop, tmp);
@@ -2233,7 +2259,7 @@ void RNA_property_int_set_index(PointerRNA *ptr, PropertyRNA *prop, int index, i
else {
int *tmparray;
- tmparray = MEM_callocN(sizeof(int) * len, "RNA_property_int_get_index");
+ tmparray = MEM_mallocN(sizeof(int) * len, __func__);
RNA_property_int_get_array(ptr, prop, tmparray);
tmparray[index] = value;
RNA_property_int_set_array(ptr, prop, tmparray);
@@ -2270,6 +2296,7 @@ int RNA_property_int_get_default_index(PointerRNA *ptr, PropertyRNA *prop, int i
BLI_assert(RNA_property_type(prop) == PROP_INT);
BLI_assert(RNA_property_array_check(prop) != false);
BLI_assert(index >= 0);
+ BLI_assert(index < prop->totarraylength);
if (len <= RNA_MAX_ARRAY_LENGTH) {
RNA_property_int_get_default_array(ptr, prop, tmp);
@@ -2278,7 +2305,7 @@ int RNA_property_int_get_default_index(PointerRNA *ptr, PropertyRNA *prop, int i
else {
int *tmparray, value;
- tmparray = MEM_callocN(sizeof(int) * len, "RNA_property_int_get_default_index");
+ tmparray = MEM_mallocN(sizeof(int) * len, __func__);
RNA_property_int_get_default_array(ptr, prop, tmparray);
value = tmparray[index];
MEM_freeN(tmparray);
@@ -2398,7 +2425,7 @@ void RNA_property_float_get_array_range(PointerRNA *ptr, PropertyRNA *prop, floa
int i;
if (array_len > 32) {
- arr = MEM_mallocN(sizeof(float) * array_len, "RNA_property_float_get_array_range");
+ arr = MEM_mallocN(sizeof(float) * array_len, __func__);
}
else {
arr = arr_stack;
@@ -2425,6 +2452,7 @@ float RNA_property_float_get_index(PointerRNA *ptr, PropertyRNA *prop, int index
BLI_assert(RNA_property_type(prop) == PROP_FLOAT);
BLI_assert(RNA_property_array_check(prop) != false);
BLI_assert(index >= 0);
+ BLI_assert(index < len);
if (len <= RNA_MAX_ARRAY_LENGTH) {
RNA_property_float_get_array(ptr, prop, tmp);
@@ -2433,7 +2461,7 @@ float RNA_property_float_get_index(PointerRNA *ptr, PropertyRNA *prop, int index
else {
float *tmparray, value;
- tmparray = MEM_callocN(sizeof(float) * len, "RNA_property_float_get_index");
+ tmparray = MEM_mallocN(sizeof(float) * len, __func__);
RNA_property_float_get_array(ptr, prop, tmparray);
value = tmparray[index];
MEM_freeN(tmparray);
@@ -2503,6 +2531,7 @@ void RNA_property_float_set_index(PointerRNA *ptr, PropertyRNA *prop, int index,
BLI_assert(RNA_property_type(prop) == PROP_FLOAT);
BLI_assert(RNA_property_array_check(prop) != false);
BLI_assert(index >= 0);
+ BLI_assert(index < len);
if (len <= RNA_MAX_ARRAY_LENGTH) {
RNA_property_float_get_array(ptr, prop, tmp);
@@ -2512,7 +2541,7 @@ void RNA_property_float_set_index(PointerRNA *ptr, PropertyRNA *prop, int index,
else {
float *tmparray;
- tmparray = MEM_callocN(sizeof(float) * len, "RNA_property_float_get_index");
+ tmparray = MEM_mallocN(sizeof(float) * len, __func__);
RNA_property_float_get_array(ptr, prop, tmparray);
tmparray[index] = value;
RNA_property_float_set_array(ptr, prop, tmparray);
@@ -2553,6 +2582,7 @@ float RNA_property_float_get_default_index(PointerRNA *ptr, PropertyRNA *prop, i
BLI_assert(RNA_property_type(prop) == PROP_FLOAT);
BLI_assert(RNA_property_array_check(prop) != false);
BLI_assert(index >= 0);
+ BLI_assert(index < prop->totarraylength);
if (len <= RNA_MAX_ARRAY_LENGTH) {
RNA_property_float_get_default_array(ptr, prop, tmp);
@@ -2561,7 +2591,7 @@ float RNA_property_float_get_default_index(PointerRNA *ptr, PropertyRNA *prop, i
else {
float *tmparray, value;
- tmparray = MEM_callocN(sizeof(float) * len, "RNA_property_float_get_default_index");
+ tmparray = MEM_mallocN(sizeof(float) * len, __func__);
RNA_property_float_get_default_array(ptr, prop, tmparray);
value = tmparray[index];
MEM_freeN(tmparray);
@@ -3228,7 +3258,7 @@ int RNA_property_collection_lookup_string(PointerRNA *ptr, PropertyRNA *prop, co
nameptr = RNA_property_string_get_alloc(&iter.ptr, nameprop, name, sizeof(name), &namelen);
- if ((keylen == namelen) && (strcmp(nameptr, key) == 0)) {
+ if ((keylen == namelen) && STREQ(nameptr, key)) {
*r_ptr = iter.ptr;
found = 1;
}
@@ -3546,7 +3576,7 @@ static int rna_raw_access(ReportList *reports, PointerRNA *ptr, PropertyRNA *pro
tmparray = NULL;
}
if (!tmparray) {
- tmparray = MEM_callocN(sizeof(float) * itemlen, "RNA tmparray\n");
+ tmparray = MEM_callocN(sizeof(float) * itemlen, "RNA tmparray");
tmplen = itemlen;
}
@@ -3889,7 +3919,7 @@ static char *rna_path_token(const char **path, char *fixedbuf, int fixedlen, int
if (len + 1 < fixedlen)
buf = fixedbuf;
else
- buf = MEM_callocN(sizeof(char) * (len + 1), "rna_path_token");
+ buf = MEM_mallocN(sizeof(char) * (len + 1), "rna_path_token");
/* copy string, taking into account escaped ] */
if (bracket) {
@@ -4283,7 +4313,7 @@ char *RNA_path_append(const char *path, PointerRNA *UNUSED(ptr), PropertyRNA *pr
/* add .identifier */
if (path) {
- BLI_dynstr_append(dynstr, (char *)path);
+ BLI_dynstr_append(dynstr, path);
if (*path)
BLI_dynstr_append(dynstr, ".");
}
@@ -4690,6 +4720,7 @@ char *RNA_path_full_struct_py(struct PointerRNA *ptr)
char *RNA_path_full_property_py(PointerRNA *ptr, PropertyRNA *prop, int index)
{
char *id_path;
+ const char *data_delim;
char *data_path;
char *ret;
@@ -4703,13 +4734,15 @@ char *RNA_path_full_property_py(PointerRNA *ptr, PropertyRNA *prop, int index)
data_path = RNA_path_from_ID_to_property(ptr, prop);
+ data_delim = (data_path && data_path[0] == '[') ? "" : ".";
+
if ((index == -1) || (RNA_property_array_check(prop) == false)) {
- ret = BLI_sprintfN("%s.%s",
- id_path, data_path);
+ ret = BLI_sprintfN("%s%s%s",
+ id_path, data_delim, data_path);
}
else {
- ret = BLI_sprintfN("%s.%s[%d]",
- id_path, data_path, index);
+ ret = BLI_sprintfN("%s%s%s[%d]",
+ id_path, data_delim, data_path, index);
}
MEM_freeN(id_path);
if (data_path) {
@@ -4739,8 +4772,9 @@ char *RNA_path_struct_property_py(PointerRNA *ptr, PropertyRNA *prop, int index)
/* this may not be an ID at all, check for simple when pointer owns property.
* TODO, more complex nested case */
if (!RNA_struct_is_ID(ptr->type)) {
- if (RNA_struct_find_property(ptr, RNA_property_identifier(prop)) == prop) {
- data_path = BLI_strdup(RNA_property_identifier(prop));
+ const char *prop_identifier = RNA_property_identifier(prop);
+ if (RNA_struct_find_property(ptr, prop_identifier) == prop) {
+ data_path = BLI_strdup(prop_identifier);
}
}
}
@@ -4959,7 +4993,7 @@ bool RNA_enum_is_equal(bContext *C, PointerRNA *ptr, const char *name, const cha
if (prop) {
int i;
- bool cmp;
+ bool cmp = false;
RNA_property_enum_items(C, ptr, prop, &item, NULL, &free);
i = RNA_enum_from_identifier(item, enumname);
@@ -5263,7 +5297,7 @@ char *RNA_pointer_as_string_id(bContext *C, PointerRNA *ptr)
{
propname = RNA_property_identifier(prop);
- if (strcmp(propname, "rna_type") == 0)
+ if (STREQ(propname, "rna_type"))
continue;
if (first_time == 0)
@@ -5334,7 +5368,7 @@ char *RNA_pointer_as_string_keywords_ex(bContext *C, PointerRNA *ptr,
arg_name = RNA_property_identifier(prop);
- if (strcmp(arg_name, "rna_type") == 0) {
+ if (STREQ(arg_name, "rna_type")) {
continue;
}
@@ -5440,14 +5474,20 @@ char *RNA_property_as_string(bContext *C, PointerRNA *ptr, PropertyRNA *prop, in
BLI_dynstr_append(dynstr, bool_as_py_string(RNA_property_boolean_get_index(ptr, prop, index)));
}
else {
+ int fixedbuf[RNA_MAX_ARRAY_LENGTH];
+ int *buf = ARRAY_SIZE(fixedbuf) >= len ? fixedbuf : MEM_mallocN(sizeof(*buf) * len, __func__);
+
+ RNA_property_boolean_get_array(ptr, prop, buf);
BLI_dynstr_append(dynstr, "(");
for (i = 0; i < len; i++) {
- BLI_dynstr_appendf(dynstr, i ? ", %s" : "%s",
- bool_as_py_string(RNA_property_boolean_get_index(ptr, prop, i)));
+ BLI_dynstr_appendf(dynstr, i ? ", %s" : "%s", bool_as_py_string(buf[i]));
}
if (len == 1)
BLI_dynstr_append(dynstr, ","); /* otherwise python wont see it as a tuple */
BLI_dynstr_append(dynstr, ")");
+ if (buf != fixedbuf) {
+ MEM_freeN(buf);
+ }
}
}
break;
@@ -5460,13 +5500,20 @@ char *RNA_property_as_string(bContext *C, PointerRNA *ptr, PropertyRNA *prop, in
BLI_dynstr_appendf(dynstr, "%d", RNA_property_int_get_index(ptr, prop, index));
}
else {
+ int fixedbuf[RNA_MAX_ARRAY_LENGTH];
+ int *buf = ARRAY_SIZE(fixedbuf) >= len ? fixedbuf : MEM_mallocN(sizeof(*buf) * len, __func__);
+
+ RNA_property_int_get_array(ptr, prop, buf);
BLI_dynstr_append(dynstr, "(");
for (i = 0; i < len; i++) {
- BLI_dynstr_appendf(dynstr, i ? ", %d" : "%d", RNA_property_int_get_index(ptr, prop, i));
+ BLI_dynstr_appendf(dynstr, i ? ", %d" : "%d", buf[i]);
}
if (len == 1)
BLI_dynstr_append(dynstr, ","); /* otherwise python wont see it as a tuple */
BLI_dynstr_append(dynstr, ")");
+ if (buf != fixedbuf) {
+ MEM_freeN(buf);
+ }
}
}
break;
@@ -5479,13 +5526,20 @@ char *RNA_property_as_string(bContext *C, PointerRNA *ptr, PropertyRNA *prop, in
BLI_dynstr_appendf(dynstr, "%g", RNA_property_float_get_index(ptr, prop, index));
}
else {
+ float fixedbuf[RNA_MAX_ARRAY_LENGTH];
+ float *buf = ARRAY_SIZE(fixedbuf) >= len ? fixedbuf : MEM_mallocN(sizeof(*buf) * len, __func__);
+
+ RNA_property_float_get_array(ptr, prop, buf);
BLI_dynstr_append(dynstr, "(");
for (i = 0; i < len; i++) {
- BLI_dynstr_appendf(dynstr, i ? ", %g" : "%g", RNA_property_float_get_index(ptr, prop, i));
+ BLI_dynstr_appendf(dynstr, i ? ", %g" : "%g", buf[i]);
}
if (len == 1)
BLI_dynstr_append(dynstr, ","); /* otherwise python wont see it as a tuple */
BLI_dynstr_append(dynstr, ")");
+ if (buf != fixedbuf) {
+ MEM_freeN(buf);
+ }
}
}
break;
@@ -5631,7 +5685,7 @@ PropertyRNA *RNA_function_find_parameter(PointerRNA *UNUSED(ptr), FunctionRNA *f
parm = func->cont.properties.first;
for (; parm; parm = parm->next)
- if (strcmp(RNA_property_identifier(parm), identifier) == 0)
+ if (STREQ(RNA_property_identifier(parm), identifier))
break;
return parm;
@@ -5829,7 +5883,7 @@ void RNA_parameter_get_lookup(ParameterList *parms, const char *identifier, void
parm = parms->func->cont.properties.first;
for (; parm; parm = parm->next)
- if (strcmp(RNA_property_identifier(parm), identifier) == 0)
+ if (STREQ(RNA_property_identifier(parm), identifier))
break;
if (parm)
@@ -5885,7 +5939,7 @@ void RNA_parameter_set_lookup(ParameterList *parms, const char *identifier, cons
parm = parms->func->cont.properties.first;
for (; parm; parm = parm->next)
- if (strcmp(RNA_property_identifier(parm), identifier) == 0)
+ if (STREQ(RNA_property_identifier(parm), identifier))
break;
if (parm)
@@ -6475,6 +6529,12 @@ bool RNA_property_copy(PointerRNA *ptr, PointerRNA *fromptr, PropertyRNA *prop,
/* In case of IDProperty, we have to find the *real* idprop of ptr,
* since prop in this case is just a fake wrapper around actual IDProp data, and not a 'real' PropertyRNA. */
prop = (PropertyRNA *)rna_idproperty_find(ptr, ((IDProperty *)fromprop)->name);
+
+ /* its possible the custom-prop doesn't exist on this datablock */
+ if (prop == NULL) {
+ return false;
+ }
+
/* Even though currently we now prop will always be the 'fromprop', this might not be the case in the future. */
if (prop == fromprop) {
fromprop = (PropertyRNA *)rna_idproperty_find(fromptr, ((IDProperty *)prop)->name);
@@ -6629,8 +6689,8 @@ bool RNA_property_equals(PointerRNA *a, PointerRNA *b, PropertyRNA *prop, eRNAEq
int *array_a, *array_b;
bool equals;
- array_a = (len > 16) ? MEM_callocN(sizeof(int) * len, "RNA equals") : fixed_a;
- array_b = (len > 16) ? MEM_callocN(sizeof(int) * len, "RNA equals") : fixed_b;
+ array_a = (len > 16) ? MEM_mallocN(sizeof(int) * len, "RNA equals") : fixed_a;
+ array_b = (len > 16) ? MEM_mallocN(sizeof(int) * len, "RNA equals") : fixed_b;
RNA_property_boolean_get_array(a, prop, array_a);
RNA_property_boolean_get_array(b, prop, array_b);
@@ -6655,8 +6715,8 @@ bool RNA_property_equals(PointerRNA *a, PointerRNA *b, PropertyRNA *prop, eRNAEq
int *array_a, *array_b;
bool equals;
- array_a = (len > 16) ? MEM_callocN(sizeof(int) * len, "RNA equals") : fixed_a;
- array_b = (len > 16) ? MEM_callocN(sizeof(int) * len, "RNA equals") : fixed_b;
+ array_a = (len > 16) ? MEM_mallocN(sizeof(int) * len, "RNA equals") : fixed_a;
+ array_b = (len > 16) ? MEM_mallocN(sizeof(int) * len, "RNA equals") : fixed_b;
RNA_property_int_get_array(a, prop, array_a);
RNA_property_int_get_array(b, prop, array_b);
@@ -6681,8 +6741,8 @@ bool RNA_property_equals(PointerRNA *a, PointerRNA *b, PropertyRNA *prop, eRNAEq
float *array_a, *array_b;
bool equals;
- array_a = (len > 16) ? MEM_callocN(sizeof(float) * len, "RNA equals") : fixed_a;
- array_b = (len > 16) ? MEM_callocN(sizeof(float) * len, "RNA equals") : fixed_b;
+ array_a = (len > 16) ? MEM_mallocN(sizeof(float) * len, "RNA equals") : fixed_a;
+ array_b = (len > 16) ? MEM_mallocN(sizeof(float) * len, "RNA equals") : fixed_b;
RNA_property_float_get_array(a, prop, array_a);
RNA_property_float_get_array(b, prop, array_b);
@@ -6712,7 +6772,7 @@ bool RNA_property_equals(PointerRNA *a, PointerRNA *b, PropertyRNA *prop, eRNAEq
int len_a, len_b;
char *value_a = RNA_property_string_get_alloc(a, prop, fixed_a, sizeof(fixed_a), &len_a);
char *value_b = RNA_property_string_get_alloc(b, prop, fixed_b, sizeof(fixed_b), &len_b);
- bool equals = strcmp(value_a, value_b) == 0;
+ bool equals = STREQ(value_a, value_b);
if (value_a != fixed_a) MEM_freeN(value_a);
if (value_b != fixed_b) MEM_freeN(value_b);
diff --git a/source/blender/makesrna/intern/rna_action.c b/source/blender/makesrna/intern/rna_action.c
index 750c98a536d..b8a490ea904 100644
--- a/source/blender/makesrna/intern/rna_action.c
+++ b/source/blender/makesrna/intern/rna_action.c
@@ -60,7 +60,7 @@ static void rna_ActionGroup_channels_next(CollectionPropertyIterator *iter)
FCurve *fcu = (FCurve *)internal->link;
bActionGroup *grp = fcu->grp;
- /* only continue if the next F-Curve (if existant) belongs in the same group */
+ /* only continue if the next F-Curve (if existent) belongs in the same group */
if ((fcu->next) && (fcu->next->grp == grp))
internal->link = (Link *)fcu->next;
else
@@ -119,6 +119,17 @@ static FCurve *rna_Action_fcurve_new(bAction *act, ReportList *reports, const ch
return verify_fcurve(act, group, NULL, data_path, index, 1);
}
+static FCurve *rna_Action_fcurve_find(bAction *act, ReportList *reports, const char *data_path, int index)
+{
+ if (data_path[0] == '\0') {
+ BKE_report(reports, RPT_ERROR, "F-Curve data path empty, invalid argument");
+ return NULL;
+ }
+
+ /* Returns NULL if not found. */
+ return list_find_fcurve(&act->curves, data_path, index);
+}
+
static void rna_Action_fcurve_remove(bAction *act, ReportList *reports, PointerRNA *fcu_ptr)
{
FCurve *fcu = fcu_ptr->data;
@@ -197,7 +208,7 @@ static void rna_Action_active_pose_marker_index_range(PointerRNA *ptr, int *min,
bAction *act = (bAction *)ptr->data;
*min = 0;
- *max = max_ii(0, BLI_countlist(&act->markers) - 1);
+ *max = max_ii(0, BLI_listbase_count(&act->markers) - 1);
}
@@ -329,6 +340,21 @@ static void rna_def_dopesheet(BlenderRNA *brna)
prop = RNA_def_property(srna, "filter_fcurve_name", PROP_STRING, PROP_NONE);
RNA_def_property_string_sdna(prop, NULL, "searchstr");
RNA_def_property_ui_text(prop, "F-Curve Name Filter", "F-Curve live filtering string");
+ RNA_def_property_flag(prop, PROP_TEXTEDIT_UPDATE);
+ RNA_def_property_update(prop, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL);
+
+ /* NLA Name Search Settings (Shared with FCurve setting, but with different labels) */
+ prop = RNA_def_property(srna, "use_filter_text", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "filterflag", ADS_FILTER_BY_FCU_NAME);
+ RNA_def_property_ui_text(prop, "Only Matching Channels",
+ "Only include channels with names containing search text");
+ RNA_def_property_ui_icon(prop, ICON_VIEWZOOM, 0);
+ RNA_def_property_update(prop, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL);
+
+ prop = RNA_def_property(srna, "filter_text", PROP_STRING, PROP_NONE);
+ RNA_def_property_string_sdna(prop, NULL, "searchstr");
+ RNA_def_property_ui_text(prop, "Name Filter", "Live filtering string");
+ RNA_def_property_flag(prop, PROP_TEXTEDIT_UPDATE);
RNA_def_property_update(prop, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL);
/* NLA Specific Settings */
@@ -462,6 +488,12 @@ static void rna_def_dopesheet(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Display Speaker", "Include visualization of speaker related animation data");
RNA_def_property_ui_icon(prop, ICON_SPEAKER, 0);
RNA_def_property_update(prop, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL);
+
+ prop = RNA_def_property(srna, "show_gpencil", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_negative_sdna(prop, NULL, "filterflag", ADS_FILTER_NOGPENCIL);
+ RNA_def_property_ui_text(prop, "Display Grease Pencil", "Include visualization of Grease Pencil related animation data and frames");
+ RNA_def_property_ui_icon(prop, ICON_GREASEPENCIL, 0);
+ RNA_def_property_update(prop, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL);
}
static void rna_def_action_group(BlenderRNA *brna)
@@ -527,7 +559,7 @@ static void rna_def_action_groups(BlenderRNA *brna, PropertyRNA *cprop)
RNA_def_struct_ui_text(srna, "Action Groups", "Collection of action groups");
func = RNA_def_function(srna, "new", "rna_Action_groups_new");
- RNA_def_function_ui_description(func, "Add a keyframe to the curve");
+ RNA_def_function_ui_description(func, "Create a new action group and add it to the action");
parm = RNA_def_string(func, "name", "Group", 0, "", "New name for the action group");
RNA_def_property_flag(parm, PROP_REQUIRED);
@@ -555,8 +587,9 @@ static void rna_def_action_fcurves(BlenderRNA *brna, PropertyRNA *cprop)
RNA_def_struct_sdna(srna, "bAction");
RNA_def_struct_ui_text(srna, "Action F-Curves", "Collection of action F-Curves");
+ /* Action.fcurves.new(...) */
func = RNA_def_function(srna, "new", "rna_Action_fcurve_new");
- RNA_def_function_ui_description(func, "Add a keyframe to the F-Curve");
+ RNA_def_function_ui_description(func, "Add an F-Curve to the action");
RNA_def_function_flag(func, FUNC_USE_REPORTS);
parm = RNA_def_string(func, "data_path", NULL, 0, "Data Path", "F-Curve data path to use");
RNA_def_property_flag(parm, PROP_REQUIRED);
@@ -566,7 +599,19 @@ static void rna_def_action_fcurves(BlenderRNA *brna, PropertyRNA *cprop)
parm = RNA_def_pointer(func, "fcurve", "FCurve", "", "Newly created F-Curve");
RNA_def_function_return(func, parm);
+ /* Action.fcurves.find(...) */
+ func = RNA_def_function(srna, "find", "rna_Action_fcurve_find");
+ RNA_def_function_ui_description(func, "Find an F-Curve. Note that this function performs a linear scan "
+ "of all F-Curves in the action.");
+ RNA_def_function_flag(func, FUNC_USE_REPORTS);
+ parm = RNA_def_string(func, "data_path", NULL, 0, "Data Path", "F-Curve data path");
+ RNA_def_property_flag(parm, PROP_REQUIRED);
+ RNA_def_int(func, "index", 0, 0, INT_MAX, "Index", "Array index", 0, INT_MAX);
+ parm = RNA_def_pointer(func, "fcurve", "FCurve", "", "The found F-Curve, or None if it doesn't exist");
+ RNA_def_function_return(func, parm);
+
+ /* Action.fcurves.remove(...) */
func = RNA_def_function(srna, "remove", "rna_Action_fcurve_remove");
RNA_def_function_ui_description(func, "Remove action group");
RNA_def_function_flag(func, FUNC_USE_REPORTS);
@@ -605,13 +650,14 @@ static void rna_def_action_pose_markers(BlenderRNA *brna, PropertyRNA *cprop)
prop = RNA_def_property(srna, "active", PROP_POINTER, PROP_NONE);
RNA_def_property_struct_type(prop, "TimelineMarker");
- RNA_def_property_flag(prop, PROP_EDITABLE);
+ RNA_def_property_flag(prop, PROP_EDITABLE | PROP_LIB_EXCEPTION);
RNA_def_property_pointer_funcs(prop, "rna_Action_active_pose_marker_get",
"rna_Action_active_pose_marker_set", NULL, NULL);
RNA_def_property_ui_text(prop, "Active Pose Marker", "Active pose marker for this action");
prop = RNA_def_property(srna, "active_index", PROP_INT, PROP_UNSIGNED);
RNA_def_property_int_sdna(prop, NULL, "active_marker");
+ RNA_def_property_flag(prop, PROP_LIB_EXCEPTION);
RNA_def_property_int_funcs(prop, "rna_Action_active_pose_marker_index_get",
"rna_Action_active_pose_marker_index_set", "rna_Action_active_pose_marker_index_range");
RNA_def_property_ui_text(prop, "Active Pose Marker Index", "Index of active pose marker");
@@ -643,6 +689,7 @@ static void rna_def_action(BlenderRNA *brna)
prop = RNA_def_property(srna, "pose_markers", PROP_COLLECTION, PROP_NONE);
RNA_def_property_collection_sdna(prop, NULL, "markers", NULL);
RNA_def_property_struct_type(prop, "TimelineMarker");
+ RNA_def_property_flag(prop, PROP_LIB_EXCEPTION); /* T45689 - so that the list isn't greyed out; adding/removing is still banned though */
RNA_def_property_ui_text(prop, "Pose Markers", "Markers specific to this action, for labeling poses");
rna_def_action_pose_markers(brna, prop);
diff --git a/source/blender/makesrna/intern/rna_actuator.c b/source/blender/makesrna/intern/rna_actuator.c
index 0114ffa35c0..5dba21dda40 100644
--- a/source/blender/makesrna/intern/rna_actuator.c
+++ b/source/blender/makesrna/intern/rna_actuator.c
@@ -35,7 +35,7 @@
#include "BLI_utildefines.h"
#include "BLI_math.h"
-#include "BLF_translation.h"
+#include "BLT_translation.h"
#include "RNA_define.h"
#include "RNA_access.h"
@@ -55,16 +55,16 @@ static EnumPropertyItem actuator_type_items[] = {
{ACT_2DFILTER, "FILTER_2D", 0, "Filter 2D", ""},
{ACT_GAME, "GAME", 0, "Game", ""},
{ACT_MESSAGE, "MESSAGE", 0, "Message", ""},
- {ACT_MOUSE, "MOUSE", 0, "Mouse", ""},
{ACT_OBJECT, "MOTION", 0, "Motion", ""},
+ {ACT_MOUSE, "MOUSE", 0, "Mouse", ""},
{ACT_PARENT, "PARENT", 0, "Parent", ""},
{ACT_PROPERTY, "PROPERTY", 0, "Property", ""},
{ACT_RANDOM, "RANDOM", 0, "Random", ""},
{ACT_SCENE, "SCENE", 0, "Scene", ""},
{ACT_SOUND, "SOUND", 0, "Sound", ""},
{ACT_STATE, "STATE", 0, "State", ""},
- {ACT_VISIBILITY, "VISIBILITY", 0, "Visibility", ""},
{ACT_STEERING, "STEERING", 0, "Steering", ""},
+ {ACT_VISIBILITY, "VISIBILITY", 0, "Visibility", ""},
{0, NULL, 0, NULL, NULL}
};
@@ -120,14 +120,10 @@ static StructRNA *rna_Actuator_refine(struct PointerRNA *ptr)
static void rna_Actuator_name_set(PointerRNA *ptr, const char *value)
{
- bActuator *act = (bActuator *)ptr->data;
-
+ Object *ob = ptr->id.data;
+ bActuator *act = ptr->data;
BLI_strncpy_utf8(act->name, value, sizeof(act->name));
-
- if (ptr->id.data) {
- Object *ob = (Object *)ptr->id.data;
- BLI_uniquename(&ob->actuators, act, DATA_("Actuator"), '.', offsetof(bActuator, name), sizeof(act->name));
- }
+ BLI_uniquename(&ob->actuators, act, DATA_("Actuator"), '.', offsetof(bActuator, name), sizeof(act->name));
}
static void rna_Actuator_type_set(struct PointerRNA *ptr, int value)
@@ -494,11 +490,11 @@ static void rna_Actuator_Armature_update(Main *UNUSED(bmain), Scene *UNUSED(scen
bPoseChannel *pchan;
bPose *pose = ob->pose;
for (pchan = pose->chanbase.first; pchan; pchan = pchan->next) {
- if (!strcmp(pchan->name, posechannel)) {
+ if (STREQ(pchan->name, posechannel)) {
/* found it, now look for constraint channel */
bConstraint *con;
for (con = pchan->constraints.first; con; con = con->next) {
- if (!strcmp(con->name, constraint)) {
+ if (STREQ(con->name, constraint)) {
/* found it, all ok */
return;
}
@@ -535,14 +531,6 @@ static void rna_Actuator_editobject_mesh_set(PointerRNA *ptr, PointerRNA value)
eoa->me = value.data;
}
-static void rna_Actuator_action_action_set(PointerRNA *ptr, PointerRNA value)
-{
- bActuator *act = (bActuator *)ptr->data;
- bActionActuator *aa = (bActionActuator *) act->data;
-
- aa->act = value.data;
-}
-
#else
static void rna_def_actuator(BlenderRNA *brna)
@@ -622,10 +610,8 @@ static void rna_def_action_actuator(BlenderRNA *brna)
prop = RNA_def_property(srna, "action", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "act");
RNA_def_property_struct_type(prop, "Action");
- RNA_def_property_flag(prop, PROP_EDITABLE);
+ RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_REFCOUNT);
RNA_def_property_ui_text(prop, "Action", "");
- /* note: custom set function is ONLY to avoid rna setting a user for this. */
- RNA_def_property_pointer_funcs(prop, NULL, "rna_Actuator_action_action_set", NULL, NULL);
RNA_def_property_update(prop, NC_LOGIC, NULL);
prop = RNA_def_property(srna, "use_continue_last_frame", PROP_BOOLEAN, PROP_NONE);
@@ -1013,13 +999,13 @@ static void rna_def_sound_actuator(BlenderRNA *brna)
RNA_def_property_ui_range(prop, 0.0, 1.0, 1, 2);
RNA_def_property_range(prop, 0.0, 2.0);
RNA_def_property_ui_text(prop, "Volume", "Initial volume of the sound");
- RNA_def_property_translation_context(prop, BLF_I18NCONTEXT_ID_SOUND);
+ RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_SOUND);
RNA_def_property_update(prop, NC_LOGIC, NULL);
prop = RNA_def_property(srna, "pitch", PROP_FLOAT, PROP_NONE);
RNA_def_property_ui_range(prop, -12.0, 12.0, 1, 2);
RNA_def_property_ui_text(prop, "Pitch", "Pitch of the sound");
- RNA_def_property_translation_context(prop, BLF_I18NCONTEXT_ID_SOUND);
+ RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_SOUND);
RNA_def_property_update(prop, NC_LOGIC, NULL);
/* floats - 3D Parameters */
@@ -2070,6 +2056,11 @@ static void rna_def_steering_actuator(BlenderRNA *brna)
RNA_def_property_boolean_sdna(prop, NULL, "flag", ACT_STEERING_NORMALUP);
RNA_def_property_ui_text(prop, "N", "Use normal of the navmesh to set \"UP\" vector");
RNA_def_property_update(prop, NC_LOGIC, NULL);
+
+ prop = RNA_def_property(srna, "lock_z_velocity", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", ACT_STEERING_LOCKZVEL);
+ RNA_def_property_ui_text(prop, "Lock Z velocity", "Disable simulation of linear motion along Z axis");
+ RNA_def_property_update(prop, NC_LOGIC, NULL);
}
static void rna_def_mouse_actuator(BlenderRNA *brna)
diff --git a/source/blender/makesrna/intern/rna_animation.c b/source/blender/makesrna/intern/rna_animation.c
index f2881bf2541..ac30c615438 100644
--- a/source/blender/makesrna/intern/rna_animation.c
+++ b/source/blender/makesrna/intern/rna_animation.c
@@ -112,6 +112,7 @@ static void rna_AnimData_action_set(PointerRNA *ptr, PointerRNA value)
adt = BKE_animdata_from_id(ownerId);
if (adt) {
adt->recalc |= ADT_RECALC_ANIM;
+ DAG_id_tag_update(ownerId, OB_RECALC_TIME);
}
}
@@ -343,7 +344,7 @@ static void rna_KeyingSet_name_set(PointerRNA *ptr, const char *value)
KeyingSet *ks = (KeyingSet *)ptr->data;
/* update names of corresponding groups if name changes */
- if (strcmp(ks->name, value)) {
+ if (!STREQ(ks->name, value)) {
KS_Path *ksp;
for (ksp = ks->paths.first; ksp; ksp = ksp->next) {
@@ -359,7 +360,7 @@ static void rna_KeyingSet_name_set(PointerRNA *ptr, const char *value)
* conflicts
*/
for (agrp = adt->action->groups.first; agrp; agrp = agrp->next) {
- if (strcmp(ks->name, agrp->name) == 0) {
+ if (STREQ(ks->name, agrp->name)) {
/* there should only be one of these in the action, so can stop... */
BLI_strncpy(agrp->name, value, sizeof(agrp->name));
break;
@@ -414,7 +415,7 @@ static void rna_KeyingSet_active_ksPath_index_range(PointerRNA *ptr, int *min, i
KeyingSet *ks = (KeyingSet *)ptr->data;
*min = 0;
- *max = max_ii(0, BLI_countlist(&ks->paths) - 1);
+ *max = max_ii(0, BLI_listbase_count(&ks->paths) - 1);
}
static PointerRNA rna_KeyingSet_typeinfo_get(PointerRNA *ptr)
@@ -445,7 +446,7 @@ static KS_Path *rna_KeyingSet_paths_add(KeyingSet *keyingset, ReportList *report
/* if data is valid, call the API function for this */
if (keyingset) {
ksp = BKE_keyingset_add_path(keyingset, id, group_name, rna_path, index, flag, group_method);
- keyingset->active_path = BLI_countlist(&keyingset->paths);
+ keyingset->active_path = BLI_listbase_count(&keyingset->paths);
}
else {
BKE_report(reports, RPT_ERROR, "Keying set path could not be added");
@@ -554,16 +555,46 @@ static FCurve *rna_Driver_from_existing(AnimData *adt, bContext *C, FCurve *src_
#else
/* helper function for Keying Set -> keying settings */
-/* TODO: use reg option! */
-static void rna_def_common_keying_flags(StructRNA *srna, short UNUSED(reg))
+static void rna_def_common_keying_flags(StructRNA *srna, short reg)
{
PropertyRNA *prop;
-
- prop = RNA_def_property(srna, "bl_options", PROP_ENUM, PROP_NONE);
- RNA_def_property_enum_sdna(prop, NULL, "keyingflag");
- RNA_def_property_enum_items(prop, keying_flag_items);
- RNA_def_property_flag(prop, PROP_REGISTER_OPTIONAL | PROP_ENUM_FLAG);
- RNA_def_property_ui_text(prop, "Options", "Keying set options");
+
+ /* override scene/userpref defaults? */
+ prop = RNA_def_property(srna, "use_insertkey_override_needed", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "keyingoverride", INSERTKEY_NEEDED);
+ RNA_def_property_ui_text(prop, "Override Insert Keyframes Default- Only Needed",
+ "Override default setting to only insert keyframes where they're needed in the relevant F-Curves");
+ if (reg) RNA_def_property_flag(prop, PROP_REGISTER_OPTIONAL);
+
+ prop = RNA_def_property(srna, "use_insertkey_override_visual", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "keyingoverride", INSERTKEY_MATRIX);
+ RNA_def_property_ui_text(prop, "Override Insert Keyframes Default - Visual",
+ "Override default setting to insert keyframes based on 'visual transforms'");
+ if (reg) RNA_def_property_flag(prop, PROP_REGISTER_OPTIONAL);
+
+ prop = RNA_def_property(srna, "use_insertkey_override_xyz_to_rgb", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "keyingoverride", INSERTKEY_XYZ2RGB);
+ RNA_def_property_ui_text(prop, "Override F-Curve Colors - XYZ to RGB",
+ "Override default setting to set color for newly added transformation F-Curves "
+ "(Location, Rotation, Scale) to be based on the transform axis");
+ if (reg) RNA_def_property_flag(prop, PROP_REGISTER_OPTIONAL);
+
+
+ /* value to override defaults with */
+ prop = RNA_def_property(srna, "use_insertkey_needed", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "keyingflag", INSERTKEY_NEEDED);
+ RNA_def_property_ui_text(prop, "Insert Keyframes - Only Needed", "Only insert keyframes where they're needed in the relevant F-Curves");
+ if (reg) RNA_def_property_flag(prop, PROP_REGISTER_OPTIONAL);
+
+ prop = RNA_def_property(srna, "use_insertkey_visual", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "keyingflag", INSERTKEY_MATRIX);
+ RNA_def_property_ui_text(prop, "Insert Keyframes - Visual", "Insert keyframes based on 'visual transforms'");
+ if (reg) RNA_def_property_flag(prop, PROP_REGISTER_OPTIONAL);
+
+ prop = RNA_def_property(srna, "use_insertkey_xyz_to_rgb", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "keyingflag", INSERTKEY_XYZ2RGB);
+ RNA_def_property_ui_text(prop, "F-Curve Colors - XYZ to RGB", "Color for newly added transformation F-Curves (Location, Rotation, Scale) is based on the transform axis");
+ if (reg) RNA_def_property_flag(prop, PROP_REGISTER_OPTIONAL);
}
/* --- */
@@ -610,7 +641,20 @@ static void rna_def_keyingset_info(BlenderRNA *brna)
RNA_def_property_flag(prop, PROP_REGISTER_OPTIONAL);
RNA_def_property_ui_text(prop, "Description", "A short description of the keying set");
- rna_def_common_keying_flags(srna, 1); /* '1' arg here is to indicate that we need these to be set on registering */
+ /* Regarding why we don't use rna_def_common_keying_flags() here:
+ * - Using it would keep this case in sync with the other places
+ * where these options are exposed (which are optimised for being
+ * used in the UI).
+ * - Unlike all the other places, this case is used for defining
+ * new "built in" Keying Sets via the Python API. In that case,
+ * it makes more sense to expose these in a way more similar to
+ * other places featuring bl_idname/label/description (i.e. operators)
+ */
+ prop = RNA_def_property(srna, "bl_options", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "keyingflag");
+ RNA_def_property_enum_items(prop, keying_flag_items);
+ RNA_def_property_flag(prop, PROP_REGISTER_OPTIONAL | PROP_ENUM_FLAG);
+ RNA_def_property_ui_text(prop, "Options", "Keying Set options to use when inserting keyframes");
RNA_define_verify_sdna(1);
diff --git a/source/blender/makesrna/intern/rna_animviz.c b/source/blender/makesrna/intern/rna_animviz.c
index ee107fdfe9f..719eb9f8a20 100644
--- a/source/blender/makesrna/intern/rna_animviz.c
+++ b/source/blender/makesrna/intern/rna_animviz.c
@@ -66,33 +66,33 @@ static void rna_AnimViz_ghost_start_frame_set(PointerRNA *ptr, int value)
{
bAnimVizSettings *data = (bAnimVizSettings *)ptr->data;
- CLAMP(value, 1, data->ghost_ef);
data->ghost_sf = value;
+ CLAMP(data->ghost_ef, data->ghost_sf, MAXFRAME / 2);
}
static void rna_AnimViz_ghost_end_frame_set(PointerRNA *ptr, int value)
{
bAnimVizSettings *data = (bAnimVizSettings *)ptr->data;
- CLAMP(value, data->ghost_sf, (int)(MAXFRAMEF / 2));
data->ghost_ef = value;
+ CLAMP(data->ghost_sf, 1, data->ghost_ef);
}
static void rna_AnimViz_path_start_frame_set(PointerRNA *ptr, int value)
{
bAnimVizSettings *data = (bAnimVizSettings *)ptr->data;
- CLAMP(value, 1, data->path_ef - 1);
+ /* XXX: watchit! Path Start > MAXFRAME/2 could be a problem... */
data->path_sf = value;
+ CLAMP(data->path_ef, data->path_sf + 1, MAXFRAME / 2);
}
static void rna_AnimViz_path_end_frame_set(PointerRNA *ptr, int value)
{
bAnimVizSettings *data = (bAnimVizSettings *)ptr->data;
- /* XXX: watchit! Path Start > MAXFRAME/2 could be a problem... */
- CLAMP(value, data->path_sf + 1, (int)(MAXFRAMEF / 2));
data->path_ef = value;
+ CLAMP(data->path_sf, 1, data->path_ef - 1);
}
#else
diff --git a/source/blender/makesrna/intern/rna_armature.c b/source/blender/makesrna/intern/rna_armature.c
index 421d7b28dda..3e41ea4134c 100644
--- a/source/blender/makesrna/intern/rna_armature.c
+++ b/source/blender/makesrna/intern/rna_armature.c
@@ -247,8 +247,8 @@ static void rna_bone_layer_set(int *layer, const int *values)
return;
for (i = 0; i < 32; i++) {
- if (values[i]) *layer |= (1 << i);
- else *layer &= ~(1 << i);
+ if (values[i]) *layer |= (1u << i);
+ else *layer &= ~(1u << i);
}
}
@@ -272,8 +272,8 @@ static void rna_Armature_layer_set(PointerRNA *ptr, const int *values)
return;
for (i = 0; i < 32; i++) {
- if (values[i]) arm->layer |= (1 << i);
- else arm->layer &= ~(1 << i);
+ if (values[i]) arm->layer |= (1u << i);
+ else arm->layer &= ~(1u << i);
}
}
@@ -746,7 +746,7 @@ static void rna_def_edit_bone(BlenderRNA *brna)
prop = RNA_def_property(srna, "roll", PROP_FLOAT, PROP_ANGLE);
RNA_def_property_float_sdna(prop, NULL, "roll");
- RNA_def_property_ui_range(prop, -M_PI * 2, M_PI * 2, 0.1, 2);
+ RNA_def_property_ui_range(prop, -M_PI * 2, M_PI * 2, 10, 2);
RNA_def_property_ui_text(prop, "Roll", "Bone rotation around head-tail axis");
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
RNA_def_property_update(prop, 0, "rna_Armature_editbone_transform_update");
diff --git a/source/blender/makesrna/intern/rna_boid.c b/source/blender/makesrna/intern/rna_boid.c
index 6233649fb12..33048a7196b 100644
--- a/source/blender/makesrna/intern/rna_boid.c
+++ b/source/blender/makesrna/intern/rna_boid.c
@@ -169,7 +169,7 @@ static void rna_BoidState_active_boid_rule_index_range(PointerRNA *ptr, int *min
{
BoidState *state = (BoidState *)ptr->data;
*min = 0;
- *max = max_ii(0, BLI_countlist(&state->rules) - 1);
+ *max = max_ii(0, BLI_listbase_count(&state->rules) - 1);
}
static int rna_BoidState_active_boid_rule_index_get(PointerRNA *ptr)
@@ -235,7 +235,7 @@ static void rna_BoidSettings_active_boid_state_index_range(PointerRNA *ptr, int
{
BoidSettings *boids = (BoidSettings *)ptr->data;
*min = 0;
- *max = max_ii(0, BLI_countlist(&boids->states) - 1);
+ *max = max_ii(0, BLI_listbase_count(&boids->states) - 1);
}
static int rna_BoidSettings_active_boid_state_index_get(PointerRNA *ptr)
diff --git a/source/blender/makesrna/intern/rna_brush.c b/source/blender/makesrna/intern/rna_brush.c
index 1ff99271146..93cbd5fa246 100644
--- a/source/blender/makesrna/intern/rna_brush.c
+++ b/source/blender/makesrna/intern/rna_brush.c
@@ -111,8 +111,6 @@ EnumPropertyItem brush_image_tool_items[] = {
#include "MEM_guardedalloc.h"
-#include "DNA_object_types.h"
-
#include "RNA_access.h"
#include "BKE_texture.h"
@@ -125,9 +123,7 @@ EnumPropertyItem brush_image_tool_items[] = {
static int rna_SculptToolCapabilities_has_accumulate_get(PointerRNA *ptr)
{
Brush *br = (Brush *)ptr->data;
- return ELEM(br->sculpt_tool,
- SCULPT_TOOL_BLOB, SCULPT_TOOL_CLAY, SCULPT_TOOL_CREASE,
- SCULPT_TOOL_DRAW, SCULPT_TOOL_INFLATE, SCULPT_TOOL_LAYER);
+ return SCULPT_TOOL_HAS_ACCUMULATE(br->sculpt_tool);
}
static int rna_SculptToolCapabilities_has_auto_smooth_get(PointerRNA *ptr)
@@ -155,7 +151,7 @@ static int rna_SculptToolCapabilities_has_jitter_get(PointerRNA *ptr)
static int rna_SculptToolCapabilities_has_normal_weight_get(PointerRNA *ptr)
{
Brush *br = (Brush *)ptr->data;
- return ELEM(br->sculpt_tool, SCULPT_TOOL_GRAB, SCULPT_TOOL_SNAKE_HOOK);
+ return SCULPT_TOOL_HAS_NORMAL_WEIGHT(br->sculpt_tool);
}
static int rna_BrushCapabilities_has_overlay_get(PointerRNA *ptr)
@@ -194,14 +190,20 @@ static int rna_SculptToolCapabilities_has_random_texture_angle_get(PointerRNA *p
SCULPT_TOOL_SNAKE_HOOK, SCULPT_TOOL_THUMB));
}
-static int rna_BrushCapabilities_has_random_texture_angle_get(PointerRNA *ptr)
+static int rna_TextureCapabilities_has_random_texture_angle_get(PointerRNA *ptr)
{
- Brush *br = (Brush *)ptr->data;
- return (ELEM(br->mtex.brush_map_mode,
+ MTex *mtex = (MTex *)ptr->data;
+ return ELEM(mtex->brush_map_mode,
MTEX_MAP_MODE_VIEW,
MTEX_MAP_MODE_AREA,
- MTEX_MAP_MODE_RANDOM) &&
- !(br->flag & BRUSH_ANCHORED));
+ MTEX_MAP_MODE_RANDOM);
+}
+
+
+static int rna_BrushCapabilities_has_random_texture_angle_get(PointerRNA *ptr)
+{
+ Brush *br = (Brush *)ptr->data;
+ return !(br->flag & BRUSH_ANCHORED);
}
static int rna_SculptToolCapabilities_has_sculpt_plane_get(PointerRNA *ptr)
@@ -264,21 +266,16 @@ static int rna_BrushCapabilities_has_spacing_get(PointerRNA *ptr)
return (!(br->flag & BRUSH_ANCHORED));
}
-static int rna_SculptToolCapabilities_has_strength_get(PointerRNA *ptr)
+static int rna_SculptToolCapabilities_has_strength_pressure_get(PointerRNA *ptr)
{
Brush *br = (Brush *)ptr->data;
return !ELEM(br->sculpt_tool, SCULPT_TOOL_GRAB, SCULPT_TOOL_SNAKE_HOOK);
}
-static int rna_BrushCapabilities_has_texture_angle_get(PointerRNA *ptr)
+static int rna_TextureCapabilities_has_texture_angle_get(PointerRNA *ptr)
{
- Brush *br = (Brush *)ptr->data;
- return ELEM(br->mtex.brush_map_mode,
- MTEX_MAP_MODE_VIEW,
- MTEX_MAP_MODE_AREA,
- MTEX_MAP_MODE_TILED,
- MTEX_MAP_MODE_STENCIL,
- MTEX_MAP_MODE_RANDOM);
+ MTex *mtex = (MTex *)ptr->data;
+ return mtex->brush_map_mode != MTEX_MAP_MODE_3D;
}
static int rna_SculptToolCapabilities_has_gravity_get(PointerRNA *ptr)
@@ -287,10 +284,10 @@ static int rna_SculptToolCapabilities_has_gravity_get(PointerRNA *ptr)
return !ELEM(br->sculpt_tool, SCULPT_TOOL_MASK, SCULPT_TOOL_SMOOTH);
}
-static int rna_BrushCapabilities_has_texture_angle_source_get(PointerRNA *ptr)
+static int rna_TextureCapabilities_has_texture_angle_source_get(PointerRNA *ptr)
{
- Brush *br = (Brush *)ptr->data;
- return ELEM(br->mtex.brush_map_mode,
+ MTex *mtex = (MTex *)ptr->data;
+ return ELEM(mtex->brush_map_mode,
MTEX_MAP_MODE_VIEW,
MTEX_MAP_MODE_AREA,
MTEX_MAP_MODE_RANDOM);
@@ -343,8 +340,8 @@ static void rna_Brush_reset_icon(Brush *br, const char *UNUSED(type))
return;
if (id->icon_id >= BIFICONID_LAST) {
- BKE_icon_delete(id);
- BKE_previewimg_free_id(id);
+ BKE_icon_id_delete(id);
+ BKE_previewimg_id_free(id);
}
id->icon_id = 0;
@@ -416,8 +413,8 @@ static void rna_Brush_icon_update(Main *UNUSED(bmain), Scene *UNUSED(scene), Poi
br->id.icon_id = 0;
if (br->flag & BRUSH_CUSTOM_ICON) {
- BKE_previewimg_get(&br->id);
- BKE_icon_changed(BKE_icon_getid(&br->id));
+ BKE_previewimg_id_ensure(&br->id);
+ BKE_icon_changed(BKE_icon_id_ensure(&br->id));
}
WM_main_add_notifier(NC_BRUSH | NA_EDITED, br);
@@ -513,7 +510,7 @@ static EnumPropertyItem *rna_Brush_direction_itemf(bContext *C, PointerRNA *ptr,
Brush *me = (Brush *)(ptr->data);
switch (mode) {
- case PAINT_SCULPT:
+ case ePaintSculpt:
switch (me->sculpt_tool) {
case SCULPT_TOOL_DRAW:
case SCULPT_TOOL_CREASE:
@@ -553,8 +550,8 @@ static EnumPropertyItem *rna_Brush_direction_itemf(bContext *C, PointerRNA *ptr,
}
break;
- case PAINT_TEXTURE_2D:
- case PAINT_TEXTURE_PROJECTIVE:
+ case ePaintTexture2D:
+ case ePaintTextureProjective:
switch (me->imagepaint_tool) {
case PAINT_TOOL_SOFTEN:
return prop_soften_sharpen_items;
@@ -584,9 +581,9 @@ static EnumPropertyItem *rna_Brush_stroke_itemf(bContext *C, PointerRNA *UNUSED(
};
switch (mode) {
- case PAINT_SCULPT:
- case PAINT_TEXTURE_2D:
- case PAINT_TEXTURE_PROJECTIVE:
+ case ePaintSculpt:
+ case ePaintTexture2D:
+ case ePaintTextureProjective:
return sculpt_stroke_method_items;
default:
@@ -627,6 +624,15 @@ static void rna_def_brush_texture_slot(BlenderRNA *brna)
{0, NULL, 0, NULL, NULL}
};
+#define TEXTURE_CAPABILITY(prop_name_, ui_name_) \
+ prop = RNA_def_property(srna, #prop_name_, \
+ PROP_BOOLEAN, PROP_NONE); \
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE); \
+ RNA_def_property_boolean_funcs(prop, "rna_TextureCapabilities_" \
+ #prop_name_ "_get", NULL); \
+ RNA_def_property_ui_text(prop, ui_name_, NULL)
+
+
srna = RNA_def_struct(brna, "BrushTextureSlot", "TextureSlot");
RNA_def_struct_sdna(srna, "MTex");
RNA_def_struct_ui_text(srna, "Brush Texture Slot", "Texture slot for textures in a Brush datablock");
@@ -654,6 +660,25 @@ static void rna_def_brush_texture_slot(BlenderRNA *brna)
RNA_def_property_enum_items(prop, prop_mask_paint_map_mode_items);
RNA_def_property_ui_text(prop, "Mode", "");
RNA_def_property_update(prop, 0, "rna_TextureSlot_brush_update");
+
+ prop = RNA_def_property(srna, "use_rake", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "brush_angle_mode", MTEX_ANGLE_RAKE);
+ RNA_def_property_ui_text(prop, "Rake", "");
+ RNA_def_property_update(prop, 0, "rna_TextureSlot_brush_update");
+
+ prop = RNA_def_property(srna, "use_random", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "brush_angle_mode", MTEX_ANGLE_RANDOM);
+ RNA_def_property_ui_text(prop, "Random", "");
+ RNA_def_property_update(prop, 0, "rna_TextureSlot_brush_update");
+
+ prop = RNA_def_property(srna, "random_angle", PROP_FLOAT, PROP_ANGLE);
+ RNA_def_property_range(prop, 0, M_PI * 2);
+ RNA_def_property_ui_text(prop, "Random Angle", "Brush texture random angle");
+ RNA_def_property_update(prop, 0, "rna_TextureSlot_brush_update");
+
+ TEXTURE_CAPABILITY(has_texture_angle_source, "Has Texture Angle Source");
+ TEXTURE_CAPABILITY(has_random_texture_angle, "Has Random Texture Angle");
+ TEXTURE_CAPABILITY(has_texture_angle, "Has Texture Angle Source");
}
static void rna_def_sculpt_capabilities(BlenderRNA *brna)
@@ -689,7 +714,7 @@ static void rna_def_sculpt_capabilities(BlenderRNA *brna)
SCULPT_TOOL_CAPABILITY(has_secondary_color, "Has Secondary Color");
SCULPT_TOOL_CAPABILITY(has_smooth_stroke, "Has Smooth Stroke");
SCULPT_TOOL_CAPABILITY(has_space_attenuation, "Has Space Attenuation");
- SCULPT_TOOL_CAPABILITY(has_strength, "Has Strength");
+ SCULPT_TOOL_CAPABILITY(has_strength_pressure, "Has Strength Pressure");
SCULPT_TOOL_CAPABILITY(has_gravity, "Has Gravity");
#undef SCULPT_CAPABILITY
@@ -717,8 +742,6 @@ static void rna_def_brush_capabilities(BlenderRNA *brna)
BRUSH_CAPABILITY(has_overlay, "Has Overlay");
BRUSH_CAPABILITY(has_random_texture_angle, "Has Random Texture Angle");
- BRUSH_CAPABILITY(has_texture_angle, "Has Texture Angle");
- BRUSH_CAPABILITY(has_texture_angle_source, "Has Texture Angle Source");
BRUSH_CAPABILITY(has_spacing, "Has Spacing");
BRUSH_CAPABILITY(has_smooth_stroke, "Has Smooth Stroke");
@@ -786,19 +809,6 @@ static void rna_def_brush(BlenderRNA *brna)
{0, NULL, 0, NULL, NULL}
};
- static EnumPropertyItem texture_angle_source_items[] = {
- {0, "USER", 0, "User", "Rotate the brush texture by given angle"},
- {BRUSH_RAKE, "RAKE", 0, "Rake", "Rotate the brush texture to match the stroke direction"},
- {BRUSH_RANDOM_ROTATION, "RANDOM", 0, "Random", "Rotate the brush texture at random"},
- {0, NULL, 0, NULL, NULL}
- };
-
- static EnumPropertyItem texture_angle_source_no_random_items[] = {
- {0, "USER", 0, "User", "Rotate the brush texture by given angle"},
- {BRUSH_RAKE, "RAKE", 0, "Rake", "Rotate the brush texture to match the stroke direction"},
- {0, NULL, 0, NULL, NULL}
- };
-
static EnumPropertyItem brush_sculpt_plane_items[] = {
{SCULPT_DISP_DIR_AREA, "AREA", 0, "Area Plane", ""},
{SCULPT_DISP_DIR_VIEW, "VIEW", 0, "View Plane", ""},
@@ -881,18 +891,6 @@ static void rna_def_brush(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Stroke Method", "");
RNA_def_property_update(prop, 0, "rna_Brush_stroke_update");
- prop = RNA_def_property(srna, "texture_angle_source_random", PROP_ENUM, PROP_NONE);
- RNA_def_property_enum_bitflag_sdna(prop, NULL, "flag");
- RNA_def_property_enum_items(prop, texture_angle_source_items);
- RNA_def_property_ui_text(prop, "Texture Angle Source", "");
- RNA_def_property_update(prop, 0, "rna_Brush_update");
-
- prop = RNA_def_property(srna, "texture_angle_source_no_random", PROP_ENUM, PROP_NONE);
- RNA_def_property_enum_bitflag_sdna(prop, NULL, "flag");
- RNA_def_property_enum_items(prop, texture_angle_source_no_random_items);
- RNA_def_property_ui_text(prop, "Texture Angle Source", "");
- RNA_def_property_update(prop, 0, "rna_Brush_update");
-
prop = RNA_def_property(srna, "sculpt_plane", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, brush_sculpt_plane_items);
RNA_def_property_ui_text(prop, "Sculpt Plane", "");
@@ -1104,12 +1102,7 @@ static void rna_def_brush(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Original Normal",
"When locked keep using normal of surface where stroke was initiated");
RNA_def_property_update(prop, 0, "rna_Brush_update");
-
- prop = RNA_def_property(srna, "use_wrap", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", BRUSH_TORUS);
- RNA_def_property_ui_text(prop, "Wrap", "Enable torus wrapping while painting");
- RNA_def_property_update(prop, 0, "rna_Brush_update");
-
+
prop = RNA_def_property(srna, "use_pressure_strength", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", BRUSH_ALPHA_PRESSURE);
RNA_def_property_ui_icon(prop, ICON_STYLUS_PRESSURE, 0);
@@ -1158,22 +1151,12 @@ static void rna_def_brush(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Inverse Smooth Pressure", "Lighter pressure causes more smoothing to be applied");
RNA_def_property_update(prop, 0, "rna_Brush_update");
- prop = RNA_def_property(srna, "use_rake", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", BRUSH_RAKE);
- RNA_def_property_ui_text(prop, "Rake", "Rotate the brush texture to match the stroke direction");
- RNA_def_property_update(prop, 0, "rna_Brush_update");
-
prop = RNA_def_property(srna, "use_relative_jitter", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", BRUSH_ABSOLUTE_JITTER);
RNA_def_property_ui_icon(prop, ICON_UNLOCKED, true);
RNA_def_property_ui_text(prop, "Absolute Jitter", "Jittering happens in screen space, not relative to brush size");
RNA_def_property_update(prop, 0, "rna_Brush_update");
- prop = RNA_def_property(srna, "use_random_rotation", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", BRUSH_RANDOM_ROTATION);
- RNA_def_property_ui_text(prop, "Random Rotation", "Rotate the brush texture at random");
- RNA_def_property_update(prop, 0, "rna_Brush_update");
-
prop = RNA_def_property(srna, "use_plane_trim", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", BRUSH_PLANE_TRIM);
RNA_def_property_ui_text(prop, "Use Plane Trim", "Enable Plane Trim");
diff --git a/source/blender/makesrna/intern/rna_camera.c b/source/blender/makesrna/intern/rna_camera.c
index be973ab33f8..b82f3c88c56 100644
--- a/source/blender/makesrna/intern/rna_camera.c
+++ b/source/blender/makesrna/intern/rna_camera.c
@@ -87,8 +87,65 @@ static void rna_Camera_update(Main *UNUSED(bmain), Scene *UNUSED(scene), Pointer
DAG_id_tag_update(&camera->id, 0);
}
+static void rna_Camera_dependency_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr)
+{
+ Camera *camera = (Camera *)ptr->id.data;
+ DAG_relations_tag_update(bmain);
+ DAG_id_tag_update(&camera->id, 0);
+}
+
#else
+static void rna_def_camera_stereo_data(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ static EnumPropertyItem convergence_mode_items[] = {
+ {CAM_S3D_OFFAXIS, "OFFAXIS", 0, "Off-Axis", "Off-axis frustums converging in a plane"},
+ {CAM_S3D_PARALLEL, "PARALLEL", 0, "Parallel", "Parallel cameras with no convergence"},
+ {CAM_S3D_TOE, "TOE", 0, "Toe-in", "Rotated cameras, looking at the convergence distance"},
+ {0, NULL, 0, NULL, NULL}
+ };
+
+ static EnumPropertyItem pivot_items[] = {
+ {CAM_S3D_PIVOT_LEFT, "LEFT", 0, "Left", ""},
+ {CAM_S3D_PIVOT_RIGHT, "RIGHT", 0, "Right", ""},
+ {CAM_S3D_PIVOT_CENTER, "CENTER", 0, "Center", ""},
+ {0, NULL, 0, NULL, NULL}
+ };
+
+ srna = RNA_def_struct(brna, "CameraStereoData", NULL);
+ RNA_def_struct_sdna(srna, "CameraStereoSettings");
+ RNA_def_struct_nested(brna, srna, "Camera");
+ RNA_def_struct_ui_text(srna, "Stereo", "Stereoscopy settings for a Camera datablock");
+
+ prop = RNA_def_property(srna, "convergence_mode", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_items(prop, convergence_mode_items);
+ RNA_def_property_ui_text(prop, "Mode", "");
+ RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, NULL);
+
+ prop = RNA_def_property(srna, "pivot", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_items(prop, pivot_items);
+ RNA_def_property_ui_text(prop, "Pivot", "");
+ RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, NULL);
+
+ prop = RNA_def_property(srna, "interocular_distance", PROP_FLOAT, PROP_DISTANCE);
+ RNA_def_property_range(prop, 0.0f, 100.0f);
+ RNA_def_property_ui_range(prop, 0.0f, 1.f, 1, 2);
+ RNA_def_property_ui_text(prop, "Interocular Distance",
+ "Set the distance between the eyes - the stereo plane distance / 30 should be fine");
+ RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, NULL);
+
+ prop = RNA_def_property(srna, "convergence_distance", PROP_FLOAT, PROP_DISTANCE);
+ RNA_def_property_range(prop, 0.00001f, FLT_MAX);
+ RNA_def_property_ui_range(prop, 0.0f, 15.f, 1, 2);
+ RNA_def_property_ui_text(prop, "Convergence Plane Distance",
+ "The converge point for the stereo cameras "
+ "(often the distance between a projector and the projection screen)");
+ RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, NULL);
+}
+
void RNA_def_camera(BlenderRNA *brna)
{
StructRNA *srna;
@@ -137,7 +194,7 @@ void RNA_def_camera(BlenderRNA *brna)
RNA_def_property_enum_items(prop, prop_draw_type_extra_items);
RNA_def_property_flag(prop, PROP_ENUM_FLAG);
RNA_def_property_ui_text(prop, "Composition Guides", "Draw overlay");
- RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, NULL);
+ RNA_def_property_update(prop, NC_CAMERA | ND_DRAW_RENDER_VIEWPORT, NULL);
prop = RNA_def_property(srna, "sensor_fit", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "sensor_fit");
@@ -150,7 +207,7 @@ void RNA_def_camera(BlenderRNA *brna)
prop = RNA_def_property(srna, "passepartout_alpha", PROP_FLOAT, PROP_FACTOR);
RNA_def_property_float_sdna(prop, NULL, "passepartalpha");
RNA_def_property_ui_text(prop, "Passepartout Alpha", "Opacity (alpha) of the darkened overlay in Camera view");
- RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, NULL);
+ RNA_def_property_update(prop, NC_CAMERA | ND_DRAW_RENDER_VIEWPORT, NULL);
prop = RNA_def_property(srna, "angle_x", PROP_FLOAT, PROP_ANGLE);
RNA_def_property_range(prop, DEG2RAD(0.367), DEG2RAD(172.847));
@@ -224,14 +281,14 @@ void RNA_def_camera(BlenderRNA *brna)
RNA_def_property_float_sdna(prop, NULL, "shiftx");
RNA_def_property_range(prop, -10.0f, 10.0f);
RNA_def_property_ui_range(prop, -2.0, 2.0, 1, 3);
- RNA_def_property_ui_text(prop, "Shift X", "Perspective Camera horizontal shift");
+ RNA_def_property_ui_text(prop, "Shift X", "Camera horizontal shift");
RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_Camera_update");
prop = RNA_def_property(srna, "shift_y", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "shifty");
RNA_def_property_range(prop, -10.0f, 10.0f);
RNA_def_property_ui_range(prop, -2.0, 2.0, 1, 3);
- RNA_def_property_ui_text(prop, "Shift Y", "Perspective Camera vertical shift");
+ RNA_def_property_ui_text(prop, "Shift Y", "Camera vertical shift");
RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_Camera_update");
prop = RNA_def_property(srna, "dof_distance", PROP_FLOAT, PROP_DISTANCE);
@@ -241,6 +298,13 @@ void RNA_def_camera(BlenderRNA *brna)
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);
+ /* Stereo Settings */
+ prop = RNA_def_property(srna, "stereo", PROP_POINTER, PROP_NONE);
+ RNA_def_property_flag(prop, PROP_NEVER_NULL);
+ RNA_def_property_pointer_sdna(prop, NULL, "stereo");
+ RNA_def_property_struct_type(prop, "CameraStereoData");
+ RNA_def_property_ui_text(prop, "Stereo", "");
+
/* flag */
prop = RNA_def_property(srna, "show_limits", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", CAM_SHOWLIMITS);
@@ -256,22 +320,28 @@ void RNA_def_camera(BlenderRNA *brna)
RNA_def_property_boolean_sdna(prop, NULL, "flag", CAM_SHOWPASSEPARTOUT);
RNA_def_property_ui_text(prop, "Show Passepartout",
"Show a darkened overlay outside the image area in Camera view");
- RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, NULL);
+ RNA_def_property_update(prop, NC_CAMERA | ND_DRAW_RENDER_VIEWPORT, NULL);
- prop = RNA_def_property(srna, "show_title_safe", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", CAM_SHOWTITLESAFE);
- RNA_def_property_ui_text(prop, "Show Safe Areas", "Show TV title safe and action safe zones in Camera view");
- RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, NULL);
+ prop = RNA_def_property(srna, "show_safe_areas", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", CAM_SHOW_SAFE_MARGINS);
+ RNA_def_property_ui_text(prop, "Show Safe Areas", "Show TV title safe and action safe areas in Camera view");
+ RNA_def_property_update(prop, NC_CAMERA | ND_DRAW_RENDER_VIEWPORT, NULL);
+
+ prop = RNA_def_property(srna, "show_safe_center", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", CAM_SHOW_SAFE_CENTER);
+ RNA_def_property_ui_text(prop, "Show Center-cut safe areas",
+ "Show safe areas to fit content in a different aspect ratio");
+ RNA_def_property_update(prop, NC_CAMERA | ND_DRAW_RENDER_VIEWPORT, NULL);
prop = RNA_def_property(srna, "show_name", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", CAM_SHOWNAME);
RNA_def_property_ui_text(prop, "Show Name", "Show the active Camera's name in Camera view");
- RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, NULL);
+ RNA_def_property_update(prop, NC_CAMERA | ND_DRAW_RENDER_VIEWPORT, NULL);
prop = RNA_def_property(srna, "show_sensor", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", CAM_SHOWSENSOR);
RNA_def_property_ui_text(prop, "Show Sensor Size", "Show sensor size (film gate) in Camera view");
- RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, NULL);
+ RNA_def_property_update(prop, NC_CAMERA | ND_DRAW_RENDER_VIEWPORT, NULL);
prop = RNA_def_property(srna, "lens_unit", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_bitflag_sdna(prop, NULL, "flag");
@@ -279,15 +349,26 @@ void RNA_def_camera(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Lens Unit", "Unit to edit lens in for the user interface");
/* pointers */
- rna_def_animdata_common(srna);
-
prop = RNA_def_property(srna, "dof_object", PROP_POINTER, PROP_NONE);
RNA_def_property_struct_type(prop, "Object");
RNA_def_property_pointer_sdna(prop, NULL, "dof_ob");
RNA_def_property_flag(prop, PROP_EDITABLE);
RNA_def_property_ui_text(prop, "DOF Object", "Use this object to define the depth of field focal point");
+ RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_Camera_dependency_update");
+
+ prop = RNA_def_property(srna, "gpu_dof", PROP_POINTER, PROP_NONE);
+ RNA_def_property_struct_type(prop, "GPUDOFSettings");
+ RNA_def_property_ui_text(prop, "GPU Depth Of Field", "");
RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, NULL);
+ rna_def_animdata_common(srna);
+
+ /* Nested Data */
+ RNA_define_animate_sdna(true);
+
+ /* *** Animated *** */
+ rna_def_camera_stereo_data(brna);
+
/* Camera API */
RNA_api_camera(srna);
}
diff --git a/source/blender/makesrna/intern/rna_cloth.c b/source/blender/makesrna/intern/rna_cloth.c
index cecc39c8e15..bcb3544049c 100644
--- a/source/blender/makesrna/intern/rna_cloth.c
+++ b/source/blender/makesrna/intern/rna_cloth.c
@@ -38,6 +38,8 @@
#include "BKE_cloth.h"
#include "BKE_modifier.h"
+#include "BPH_mass_spring.h"
+
#include "WM_api.h"
#include "WM_types.h"
@@ -66,17 +68,6 @@ static void rna_cloth_pinning_changed(Main *UNUSED(bmain), Scene *UNUSED(scene),
WM_main_add_notifier(NC_OBJECT | ND_MODIFIER, ob);
}
-static void rna_cloth_reset(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
-{
- Object *ob = (Object *)ptr->id.data;
- ClothSimSettings *settings = (ClothSimSettings *)ptr->data;
-
- settings->reset = 1;
-
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
- WM_main_add_notifier(NC_OBJECT | ND_MODIFIER, ob);
-}
-
static void rna_ClothSettings_max_bend_set(struct PointerRNA *ptr, float value)
{
@@ -268,6 +259,64 @@ static char *rna_ClothCollisionSettings_path(PointerRNA *ptr)
#else
+static void rna_def_cloth_solver_result(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ static EnumPropertyItem status_items[] = {
+ {BPH_SOLVER_SUCCESS, "SUCCESS", 0, "Success", "Computation was successful"},
+ {BPH_SOLVER_NUMERICAL_ISSUE, "NUMERICAL_ISSUE", 0, "Numerical Issue", "The provided data did not satisfy the prerequisites"},
+ {BPH_SOLVER_NO_CONVERGENCE, "NO_CONVERGENCE", 0, "No Convergence", "Iterative procedure did not converge"},
+ {BPH_SOLVER_INVALID_INPUT, "INVALID_INPUT", 0, "Invalid Input", "The inputs are invalid, or the algorithm has been improperly called"},
+ {0, NULL, 0, NULL, NULL}
+ };
+
+ srna = RNA_def_struct(brna, "ClothSolverResult", NULL);
+ RNA_def_struct_ui_text(srna, "Solver Result", "Result of cloth solver iteration");
+
+ RNA_define_verify_sdna(0);
+
+ prop = RNA_def_property(srna, "status", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_items(prop, status_items);
+ RNA_def_property_enum_sdna(prop, NULL, "status");
+ RNA_def_property_flag(prop, PROP_ENUM_FLAG);
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_property_ui_text(prop, "Status", "Status of the solver iteration");
+
+ prop = RNA_def_property(srna, "max_error", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "max_error");
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_property_ui_text(prop, "Maximum Error", "Maximum error during substeps");
+
+ prop = RNA_def_property(srna, "min_error", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "min_error");
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_property_ui_text(prop, "Minimum Error", "Minimum error during substeps");
+
+ prop = RNA_def_property(srna, "avg_error", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "avg_error");
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_property_ui_text(prop, "Average Error", "Average error during substeps");
+
+ prop = RNA_def_property(srna, "max_iterations", PROP_INT, PROP_NONE);
+ RNA_def_property_int_sdna(prop, NULL, "max_iterations");
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_property_ui_text(prop, "Maximum Iterations", "Maximum iterations during substeps");
+
+ prop = RNA_def_property(srna, "min_iterations", PROP_INT, PROP_NONE);
+ RNA_def_property_int_sdna(prop, NULL, "min_iterations");
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_property_ui_text(prop, "Minimum Iterations", "Minimum iterations during substeps");
+
+ prop = RNA_def_property(srna, "avg_iterations", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "avg_iterations");
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_property_ui_text(prop, "Average Iterations", "Average iterations during substeps");
+
+ RNA_define_verify_sdna(1);
+}
+
static void rna_def_cloth_sim_settings(BlenderRNA *brna)
{
StructRNA *srna;
@@ -325,6 +374,18 @@ static void rna_def_cloth_sim_settings(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Collider Friction", "");
RNA_def_property_update(prop, 0, "rna_cloth_update");
+ prop = RNA_def_property(srna, "density_target", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "density_target");
+ RNA_def_property_range(prop, 0.0f, 10000.0f);
+ RNA_def_property_ui_text(prop, "Target Density", "Maximum density of hair");
+ RNA_def_property_update(prop, 0, "rna_cloth_update");
+
+ prop = RNA_def_property(srna, "density_strength", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "density_strength");
+ RNA_def_property_range(prop, 0.0f, 1.0f);
+ RNA_def_property_ui_text(prop, "Target Density Strength", "Influence of target density on the simulation");
+ RNA_def_property_update(prop, 0, "rna_cloth_update");
+
/* mass */
prop = RNA_def_property(srna, "mass", PROP_FLOAT, PROP_NONE);
@@ -375,7 +436,7 @@ static void rna_def_cloth_sim_settings(BlenderRNA *brna)
prop = RNA_def_property(srna, "quality", PROP_INT, PROP_NONE);
RNA_def_property_int_sdna(prop, NULL, "stepsPerFrame");
- RNA_def_property_range(prop, 4, 80);
+ RNA_def_property_range(prop, 1, 80);
RNA_def_property_ui_text(prop, "Quality",
"Quality of the simulation in steps per frame (higher is better quality but slower)");
RNA_def_property_update(prop, 0, "rna_cloth_update");
@@ -398,6 +459,13 @@ static void rna_def_cloth_sim_settings(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Shrink Factor Max", "Max amount to shrink cloth by");
RNA_def_property_update(prop, 0, "rna_cloth_update");
+ prop = RNA_def_property(srna, "voxel_cell_size", PROP_FLOAT, PROP_UNSIGNED);
+ RNA_def_property_float_sdna(prop, NULL, "voxel_cell_size");
+ RNA_def_property_range(prop, 0.0001f, 10000.0f);
+ RNA_def_property_float_default(prop, 0.1f);
+ RNA_def_property_ui_text(prop, "Voxel Grid Cell Size", "Size of the voxel grid cells for interaction effects");
+ RNA_def_property_update(prop, 0, "rna_cloth_update");
+
/* springs */
prop = RNA_def_property(srna, "use_stiffness_scale", PROP_BOOLEAN, PROP_NONE);
@@ -456,6 +524,13 @@ static void rna_def_cloth_sim_settings(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Bending Stiffness Maximum", "Maximum bending stiffness value");
RNA_def_property_update(prop, 0, "rna_cloth_update");
+ prop = RNA_def_property(srna, "bending_damping", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "bending_damping");
+ RNA_def_property_range(prop, 0.0f, 1000.0f);
+ RNA_def_property_ui_text(prop, "Bending Spring Damping",
+ "Damping of bending motion");
+ RNA_def_property_update(prop, 0, "rna_cloth_update");
+
prop = RNA_def_property(srna, "use_sewing_springs", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flags", CLOTH_SIMSETTINGS_FLAG_SEW);
RNA_def_property_ui_text(prop, "Sew Cloth", "Pulls loose edges together");
@@ -473,12 +548,6 @@ static void rna_def_cloth_sim_settings(BlenderRNA *brna)
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_ui_text(prop, "Effector Weights", "");
- prop = RNA_def_property(srna, "pre_roll", PROP_INT, PROP_NONE);
- RNA_def_property_int_sdna(prop, NULL, "preroll");
- RNA_def_property_range(prop, 0, MAXFRAME);
- RNA_def_property_ui_text(prop, "Pre Roll", "Start simulation a number of frames earlier to let the cloth settle in");
- RNA_def_property_update(prop, 0, "rna_cloth_reset");
-
prop = RNA_def_property(srna, "rest_shape_key", PROP_POINTER, PROP_NONE);
RNA_def_property_flag(prop, PROP_EDITABLE);
RNA_def_property_struct_type(prop, "ShapeKey");
@@ -577,6 +646,13 @@ static void rna_def_cloth_collision_settings(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Friction", "Friction force if a collision happened (higher = less movement)");
RNA_def_property_update(prop, 0, "rna_cloth_update");
+ prop = RNA_def_property(srna, "damping", PROP_FLOAT, PROP_FACTOR);
+ RNA_def_property_float_sdna(prop, NULL, "damping");
+ RNA_def_property_range(prop, 0.0f, 1.0f);
+ RNA_def_property_float_default(prop, 1.0f);
+ RNA_def_property_ui_text(prop, "Restitution", "Amount of velocity lost on collision");
+ RNA_def_property_update(prop, 0, "rna_cloth_update");
+
prop = RNA_def_property(srna, "collision_quality", PROP_INT, PROP_NONE);
RNA_def_property_int_sdna(prop, NULL, "loop_count");
RNA_def_property_range(prop, 1, 20);
@@ -625,6 +701,7 @@ static void rna_def_cloth_collision_settings(BlenderRNA *brna)
void RNA_def_cloth(BlenderRNA *brna)
{
+ rna_def_cloth_solver_result(brna);
rna_def_cloth_sim_settings(brna);
rna_def_cloth_collision_settings(brna);
}
diff --git a/source/blender/makesrna/intern/rna_color.c b/source/blender/makesrna/intern/rna_color.c
index fa2a3258d1a..8ea67a34fbb 100644
--- a/source/blender/makesrna/intern/rna_color.c
+++ b/source/blender/makesrna/intern/rna_color.c
@@ -46,6 +46,8 @@
#include "DNA_material_types.h"
#include "DNA_movieclip_types.h"
#include "DNA_node_types.h"
+#include "DNA_object_types.h"
+#include "DNA_particle_types.h"
#include "DNA_sequence_types.h"
#include "MEM_guardedalloc.h"
@@ -345,6 +347,13 @@ static void rna_ColorRamp_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *
WM_main_add_notifier(NC_LINESTYLE, linestyle);
break;
}
+ case ID_PA:
+ {
+ ParticleSettings *part = ptr->id.data;
+
+ DAG_id_tag_update(&part->id, OB_RECALC_DATA | PSYS_RECALC_REDO);
+ WM_main_add_notifier(NC_OBJECT | ND_PARTICLE | NA_EDITED, part);
+ }
default:
break;
}
@@ -438,6 +447,7 @@ static void rna_ColorManagedDisplaySettings_display_device_update(Main *UNUSED(b
IMB_colormanagement_validate_settings(&scene->display_settings, &scene->view_settings);
+ DAG_id_tag_update(id, 0);
WM_main_add_notifier(NC_SCENE | ND_SEQUENCER, NULL);
}
}
@@ -610,9 +620,11 @@ static void rna_ColorManagedColorspaceSettings_reload_update(Main *UNUSED(bmain)
}
if (seq_found) {
- if (seq->anim) {
- IMB_free_anim(seq->anim);
- seq->anim = NULL;
+ BKE_sequence_free_anim(seq);
+
+ if (seq->strip->proxy && seq->strip->proxy->anim) {
+ IMB_free_anim(seq->strip->proxy->anim);
+ seq->strip->proxy->anim = NULL;
}
BKE_sequence_invalidate_cache(scene, seq);
@@ -621,10 +633,7 @@ static void rna_ColorManagedColorspaceSettings_reload_update(Main *UNUSED(bmain)
else {
SEQ_BEGIN(scene->ed, seq);
{
- if (seq->anim) {
- IMB_free_anim(seq->anim);
- seq->anim = NULL;
- }
+ BKE_sequence_free_anim(seq);
}
SEQ_END;
@@ -664,7 +673,7 @@ static void rna_ColorManagement_update(Main *UNUSED(bmain), Scene *UNUSED(scene)
static float rna_CurveMap_evaluateF(struct CurveMap *cuma, ReportList *reports, float value)
{
if (!cuma->table) {
- BKE_reportf(reports, RPT_ERROR, "CurveMap table not initialized, call initialize() on CurveMapping owner of the CurveMap");
+ BKE_report(reports, RPT_ERROR, "CurveMap table not initialized, call initialize() on CurveMapping owner of the CurveMap");
return 0.0f;
}
return curvemap_evaluateF(cuma, value);
diff --git a/source/blender/makesrna/intern/rna_constraint.c b/source/blender/makesrna/intern/rna_constraint.c
index 5519b192ca4..6dac2e27f9c 100644
--- a/source/blender/makesrna/intern/rna_constraint.c
+++ b/source/blender/makesrna/intern/rna_constraint.c
@@ -28,7 +28,7 @@
#include "BLI_math.h"
-#include "BLF_translation.h"
+#include "BLT_translation.h"
#include "DNA_action_types.h"
#include "DNA_constraint_types.h"
@@ -241,7 +241,7 @@ static void rna_Constraint_name_set(PointerRNA *ptr, const char *value)
}
/* fix all the animation data which may link to this */
- BKE_all_animdata_fix_paths_rename(NULL, "constraints", oldname, con->name);
+ BKE_animdata_fix_paths_rename_all(NULL, "constraints", oldname, con->name);
}
static char *rna_Constraint_path(PointerRNA *ptr)
@@ -271,12 +271,12 @@ static char *rna_Constraint_path(PointerRNA *ptr)
static void rna_Constraint_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
{
- ED_object_constraint_update(ptr->id.data);
+ ED_object_constraint_tag_update(ptr->id.data, ptr->data);
}
static void rna_Constraint_dependency_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr)
{
- ED_object_constraint_dependency_update(bmain, ptr->id.data);
+ ED_object_constraint_dependency_tag_update(bmain, ptr->id.data, ptr->data);
}
static void rna_Constraint_influence_update(Main *bmain, Scene *scene, PointerRNA *ptr)
@@ -323,7 +323,7 @@ static EnumPropertyItem *rna_Constraint_target_space_itemf(bContext *UNUSED(C),
PropertyRNA *UNUSED(prop), bool *UNUSED(r_free))
{
bConstraint *con = (bConstraint *)ptr->data;
- bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
+ const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
ListBase targets = {NULL, NULL};
bConstraintTarget *ct;
@@ -1357,7 +1357,8 @@ static void rna_def_constraint_stretch_to(BlenderRNA *brna)
prop = RNA_def_property(srna, "rest_length", PROP_FLOAT, PROP_DISTANCE);
RNA_def_property_float_sdna(prop, NULL, "orglength");
- RNA_def_property_range(prop, 0.0, 100.f);
+ RNA_def_property_range(prop, 0.0, 1000.f);
+ RNA_def_property_ui_range(prop, 0, 100.0f, 10, RNA_TRANSLATION_PREC_DEFAULT);
RNA_def_property_ui_text(prop, "Original Length", "Length at rest position");
RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update");
@@ -1365,6 +1366,31 @@ static void rna_def_constraint_stretch_to(BlenderRNA *brna)
RNA_def_property_range(prop, 0.0, 100.f);
RNA_def_property_ui_text(prop, "Volume Variation", "Factor between volume variation and stretching");
RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update");
+
+ prop = RNA_def_property(srna, "use_bulge_min", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", STRETCHTOCON_USE_BULGE_MIN);
+ RNA_def_property_ui_text(prop, "Use Volume Variation Minimum", "Use lower limit for volume variation");
+ RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update");
+
+ prop = RNA_def_property(srna, "use_bulge_max", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", STRETCHTOCON_USE_BULGE_MAX);
+ RNA_def_property_ui_text(prop, "Use Volume Variation Maximum", "Use upper limit for volume variation");
+ RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update");
+
+ prop = RNA_def_property(srna, "bulge_min", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_range(prop, 0.0, 1.0f);
+ RNA_def_property_ui_text(prop, "Volume Variation Minimum", "Minimum volume stretching factor");
+ RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update");
+
+ prop = RNA_def_property(srna, "bulge_max", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_range(prop, 1.0, 100.0f);
+ RNA_def_property_ui_text(prop, "Volume Variation Maximum", "Maximum volume stretching factor");
+ RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update");
+
+ prop = RNA_def_property(srna, "bulge_smooth", PROP_FLOAT, PROP_FACTOR);
+ RNA_def_property_range(prop, 0.0, 1.0f);
+ RNA_def_property_ui_text(prop, "Volume Variation Smoothness", "Strength of volume stretching clamping");
+ RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update");
}
static void rna_def_constraint_rigid_body_joint(BlenderRNA *brna)
@@ -2247,8 +2273,10 @@ static void rna_def_constraint_spline_ik(BlenderRNA *brna)
{CONSTRAINT_SPLINEIK_XZS_NONE, "NONE", 0, "None", "Don't scale the X and Z axes (Default)"},
{CONSTRAINT_SPLINEIK_XZS_ORIGINAL, "BONE_ORIGINAL", 0, "Bone Original",
"Use the original scaling of the bones"},
+ {CONSTRAINT_SPLINEIK_XZS_INVERSE, "INVERSE_PRESERVE", 0, "Inverse Scale",
+ "Scale of the X and Z axes is the inverse of the Y-Scale"},
{CONSTRAINT_SPLINEIK_XZS_VOLUMETRIC, "VOLUME_PRESERVE", 0, "Volume Preservation",
- "Scale of the X and Z axes is the inverse of the Y-Scale"},
+ "Scale of the X and Z axes are adjusted to preserve the volume of the bones"},
{0, NULL, 0, NULL, NULL}
};
@@ -2259,6 +2287,7 @@ static void rna_def_constraint_spline_ik(BlenderRNA *brna)
/* target chain */
prop = RNA_def_property(srna, "target", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "tar");
+ RNA_def_property_pointer_funcs(prop, NULL, NULL, NULL, "rna_Curve_object_poll");
RNA_def_property_ui_text(prop, "Target", "Curve that controls this relationship");
RNA_def_property_flag(prop, PROP_EDITABLE);
RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_dependency_update");
@@ -2308,12 +2337,44 @@ static void rna_def_constraint_spline_ik(BlenderRNA *brna)
"on top of XZ Scale mode");
RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update");
+ /* xz scaling mode */
prop = RNA_def_property(srna, "xz_scale_mode", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "xzScaleMode");
RNA_def_property_enum_items(prop, splineik_xz_scale_mode);
RNA_def_property_ui_text(prop, "XZ Scale Mode",
"Method used for determining the scaling of the X and Z axes of the bones");
RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update");
+
+ /* volume presevation for "volumetric" scale mode */
+ prop = RNA_def_property(srna, "bulge", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_range(prop, 0.0, 100.f);
+ RNA_def_property_ui_text(prop, "Volume Variation", "Factor between volume variation and stretching");
+ RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update");
+
+ prop = RNA_def_property(srna, "use_bulge_min", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", CONSTRAINT_SPLINEIK_USE_BULGE_MIN);
+ RNA_def_property_ui_text(prop, "Use Volume Variation Minimum", "Use lower limit for volume variation");
+ RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update");
+
+ prop = RNA_def_property(srna, "use_bulge_max", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", CONSTRAINT_SPLINEIK_USE_BULGE_MAX);
+ RNA_def_property_ui_text(prop, "Use Volume Variation Maximum", "Use upper limit for volume variation");
+ RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update");
+
+ prop = RNA_def_property(srna, "bulge_min", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_range(prop, 0.0, 1.0f);
+ RNA_def_property_ui_text(prop, "Volume Variation Minimum", "Minimum volume stretching factor");
+ RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update");
+
+ prop = RNA_def_property(srna, "bulge_max", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_range(prop, 1.0, 100.0f);
+ RNA_def_property_ui_text(prop, "Volume Variation Maximum", "Maximum volume stretching factor");
+ RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update");
+
+ prop = RNA_def_property(srna, "bulge_smooth", PROP_FLOAT, PROP_FACTOR);
+ RNA_def_property_range(prop, 0.0, 1.0f);
+ RNA_def_property_ui_text(prop, "Volume Variation Smoothness", "Strength of volume stretching clamping");
+ RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update");
}
static void rna_def_constraint_pivot(BlenderRNA *brna)
diff --git a/source/blender/makesrna/intern/rna_controller.c b/source/blender/makesrna/intern/rna_controller.c
index 8b5074eaf0d..1a0f3c30b03 100644
--- a/source/blender/makesrna/intern/rna_controller.c
+++ b/source/blender/makesrna/intern/rna_controller.c
@@ -31,7 +31,7 @@
#include "BLI_utildefines.h"
-#include "BLF_translation.h"
+#include "BLT_translation.h"
#include "RNA_define.h"
#include "RNA_enum_types.h"
@@ -85,15 +85,10 @@ static StructRNA *rna_Controller_refine(struct PointerRNA *ptr)
static void rna_Constroller_name_set(PointerRNA *ptr, const char *value)
{
- bController *cont = (bController *)ptr->data;
-
+ Object *ob = ptr->id.data;
+ bController *cont = ptr->data;
BLI_strncpy_utf8(cont->name, value, sizeof(cont->name));
-
- if (ptr->id.data) {
- Object *ob = (Object *)ptr->id.data;
- BLI_uniquename(&ob->controllers, cont, DATA_("Controller"), '.', offsetof(bController, name),
- sizeof(cont->name));
- }
+ BLI_uniquename(&ob->controllers, cont, DATA_("Controller"), '.', offsetof(bController, name), sizeof(cont->name));
}
static void rna_Controller_type_set(struct PointerRNA *ptr, int value)
@@ -125,7 +120,7 @@ static int rna_Controller_state_number_get(struct PointerRNA *ptr)
int bit;
for (bit = 0; bit < 32; bit++) {
- if (cont->state_mask & (1 << bit))
+ if (cont->state_mask & (1u << bit))
return bit + 1;
}
return 0;
diff --git a/source/blender/makesrna/intern/rna_curve.c b/source/blender/makesrna/intern/rna_curve.c
index 29f1dd5f29f..e1e9fc1cf68 100644
--- a/source/blender/makesrna/intern/rna_curve.c
+++ b/source/blender/makesrna/intern/rna_curve.c
@@ -34,7 +34,7 @@
#include "BLI_utildefines.h"
#include "BLI_math.h"
-#include "BLF_translation.h"
+#include "BLT_translation.h"
#include "BKE_font.h"
@@ -46,9 +46,6 @@
#include "WM_types.h"
-#include "BKE_curve.h"
-#include "ED_curve.h"
-
#ifndef RNA_RUNTIME
static EnumPropertyItem beztriple_handle_type_items[] = {
{HD_FREE, "FREE", 0, "Free", ""},
@@ -124,8 +121,6 @@ static const EnumPropertyItem curve2d_fill_mode_items[] = {
#ifdef RNA_RUNTIME
-#include "BLI_math.h"
-
#include "DNA_object_types.h"
#include "BKE_curve.h"
@@ -752,11 +747,12 @@ static int rna_Curve_is_editmode_get(PointerRNA *ptr)
#else
+static const float tilt_limit = DEG2RADF(21600.0f);
+
static void rna_def_bpoint(BlenderRNA *brna)
{
StructRNA *srna;
PropertyRNA *prop;
- const float tilt_limit = DEG2RADF(21600.0f);
srna = RNA_def_struct(brna, "SplinePoint", NULL);
RNA_def_struct_sdna(srna, "BPoint");
@@ -790,7 +786,7 @@ static void rna_def_bpoint(BlenderRNA *brna)
prop = RNA_def_property(srna, "tilt", PROP_FLOAT, PROP_ANGLE);
RNA_def_property_float_sdna(prop, NULL, "alfa");
RNA_def_property_range(prop, -tilt_limit, tilt_limit);
- RNA_def_property_ui_range(prop, -tilt_limit, tilt_limit, 0.1, 3);
+ RNA_def_property_ui_range(prop, -tilt_limit, tilt_limit, 10, 3);
RNA_def_property_ui_text(prop, "Tilt", "Tilt in 3D View");
RNA_def_property_update(prop, 0, "rna_Curve_update_data");
@@ -877,7 +873,8 @@ static void rna_def_beztriple(BlenderRNA *brna)
/* Number values */
prop = RNA_def_property(srna, "tilt", PROP_FLOAT, PROP_ANGLE);
RNA_def_property_float_sdna(prop, NULL, "alfa");
- /*RNA_def_property_range(prop, -FLT_MAX, FLT_MAX);*/
+ RNA_def_property_range(prop, -tilt_limit, tilt_limit);
+ RNA_def_property_ui_range(prop, -tilt_limit, tilt_limit, 10, 3);
RNA_def_property_ui_text(prop, "Tilt", "Tilt in 3D View");
RNA_def_property_update(prop, 0, "rna_Curve_update_data");
@@ -1300,16 +1297,13 @@ static void rna_def_curve_splines(BlenderRNA *brna, PropertyRNA *cprop)
RNA_def_property_clear_flag(parm, PROP_THICK_WRAP);
func = RNA_def_function(srna, "clear", "rna_Curve_spline_clear");
- RNA_def_function_ui_description(func, "Remove all spline from a curve");
+ RNA_def_function_ui_description(func, "Remove all splines from a curve");
prop = RNA_def_property(srna, "active", PROP_POINTER, PROP_NONE);
- RNA_def_property_struct_type(prop, "Object");
+ RNA_def_property_struct_type(prop, "Spline");
RNA_def_property_pointer_funcs(prop, "rna_Curve_active_spline_get", "rna_Curve_active_spline_set", NULL, NULL);
RNA_def_property_flag(prop, PROP_EDITABLE);
RNA_def_property_ui_text(prop, "Active Spline", "Active curve spline");
- /* Could call: ED_base_object_activate(C, scene->basact);
- * but would be a bad level call and it seems the notifier is enough */
- RNA_def_property_update(prop, NC_SCENE | ND_OB_ACTIVE, NULL);
}
diff --git a/source/blender/makesrna/intern/rna_define.c b/source/blender/makesrna/intern/rna_define.c
index 6668ce812cf..3b01305110c 100644
--- a/source/blender/makesrna/intern/rna_define.c
+++ b/source/blender/makesrna/intern/rna_define.c
@@ -42,7 +42,7 @@
#include "BLI_listbase.h"
#include "BLI_ghash.h"
-#include "BLF_translation.h"
+#include "BLT_translation.h"
#include "RNA_define.h"
@@ -65,15 +65,15 @@ BlenderDefRNA DefRNA = {NULL, {NULL, NULL}, {NULL, NULL}, NULL, 0, 0, 0, 1, 1};
/* Duplicated code since we can't link in blenkernel or blenlib */
-/* pedantic check for '.', do this since its a hassle for translators */
+/* pedantic check for final '.', note '...' are allowed though. */
#ifndef NDEBUG
-# define DESCR_CHECK(description, id1, id2) \
- if (description && (description)[0]) { \
- int i = strlen(description); \
- if ((description)[i - 1] == '.') { \
- fprintf(stderr, "%s: '%s' '%s' description ends with a '.' !\n", \
- __func__, id1 ? id1 : "", id2 ? id2 : ""); \
- } \
+# define DESCR_CHECK(description, id1, id2) \
+ if (description && (description)[0]) { \
+ int i = strlen(description); \
+ if (i > 3 && (description)[i - 1] == '.' && (description)[i - 3] != '.') { \
+ fprintf(stderr, "%s: '%s' '%s' description ends with a '.' !\n", \
+ __func__, id1 ? id1 : "", id2 ? id2 : ""); \
+ } \
} (void)0
#else
@@ -109,7 +109,7 @@ PropertyDefRNA *rna_findlink(ListBase *listbase, const char *identifier)
for (link = listbase->first; link; link = link->next) {
PropertyRNA *prop = ((PropertyDefRNA *)link)->prop;
- if (prop && (strcmp(prop->identifier, identifier) == 0)) {
+ if (prop && (STREQ(prop->identifier, identifier))) {
return (PropertyDefRNA *)link;
}
}
@@ -428,7 +428,7 @@ static int rna_validate_identifier(const char *identifier, char *error, bool pro
}
for (a = 0; kwlist[a]; a++) {
- if (strcmp(identifier, kwlist[a]) == 0) {
+ if (STREQ(identifier, kwlist[a])) {
strcpy(error, "this keyword is reserved by python");
return 0;
}
@@ -442,7 +442,7 @@ static int rna_validate_identifier(const char *identifier, char *error, bool pro
};
for (a = 0; kwlist_prop[a]; a++) {
- if (strcmp(identifier, kwlist_prop[a]) == 0) {
+ if (STREQ(identifier, kwlist_prop[a])) {
strcpy(error, "this keyword is reserved by python");
return 0;
}
@@ -496,7 +496,7 @@ void RNA_identifier_sanitize(char *identifier, int property)
}
for (a = 0; kwlist[a]; a++) {
- if (strcmp(identifier, kwlist[a]) == 0) {
+ if (STREQ(identifier, kwlist[a])) {
/* this keyword is reserved by python.
* just replace the last character by '_' to keep it readable.
*/
@@ -513,7 +513,7 @@ void RNA_identifier_sanitize(char *identifier, int property)
};
for (a = 0; kwlist_prop[a]; a++) {
- if (strcmp(identifier, kwlist_prop[a]) == 0) {
+ if (STREQ(identifier, kwlist_prop[a])) {
/* this keyword is reserved by python.
* just replace the last character by '_' to keep it readable.
*/
@@ -533,7 +533,7 @@ BlenderRNA *RNA_create(void)
brna = MEM_callocN(sizeof(BlenderRNA), "BlenderRNA");
DefRNA.sdna = DNA_sdna_from_data(DNAstr, DNAlen, false);
- DefRNA.structs.first = DefRNA.structs.last = NULL;
+ BLI_listbase_clear(&DefRNA.structs);
DefRNA.error = 0;
DefRNA.preprocess = 1;
@@ -639,7 +639,7 @@ void RNA_struct_free(BlenderRNA *brna, StructRNA *srna)
if (srna->flag & STRUCT_RUNTIME)
rna_freelinkN(&brna->structs, srna);
#else
- (void)brna, (void)srna;
+ UNUSED_VARS(brna, srna);
#endif
}
@@ -720,8 +720,8 @@ StructRNA *RNA_def_struct_ptr(BlenderRNA *brna, const char *identifier, StructRN
* use MEM_dupallocN, data structs may not be alloced but builtin */
memcpy(srna, srnafrom, sizeof(StructRNA));
srna->cont.prophash = NULL;
- srna->cont.properties.first = srna->cont.properties.last = NULL;
- srna->functions.first = srna->functions.last = NULL;
+ BLI_listbase_clear(&srna->cont.properties);
+ BLI_listbase_clear(&srna->functions);
srna->py_type = NULL;
if (DefRNA.preprocess) {
@@ -736,7 +736,7 @@ StructRNA *RNA_def_struct_ptr(BlenderRNA *brna, const char *identifier, StructRN
srna->name = identifier; /* may be overwritten later RNA_def_struct_ui_text */
srna->description = "";
/* may be overwritten later RNA_def_struct_translation_context */
- srna->translation_context = BLF_I18NCONTEXT_DEFAULT_BPYRNA;
+ srna->translation_context = BLT_I18NCONTEXT_DEFAULT_BPYRNA;
srna->flag |= STRUCT_UNDO;
if (!srnafrom)
srna->icon = ICON_DOT;
@@ -814,7 +814,7 @@ StructRNA *RNA_def_struct(BlenderRNA *brna, const char *identifier, const char *
if (from) {
/* find struct to derive from */
for (srnafrom = brna->structs.first; srnafrom; srnafrom = srnafrom->cont.next)
- if (strcmp(srnafrom->identifier, from) == 0)
+ if (STREQ(srnafrom->identifier, from))
break;
if (!srnafrom) {
@@ -896,7 +896,7 @@ void RNA_def_struct_nested(BlenderRNA *brna, StructRNA *srna, const char *struct
/* find struct to derive from */
for (srnafrom = brna->structs.first; srnafrom; srnafrom = srnafrom->cont.next)
- if (strcmp(srnafrom->identifier, structname) == 0)
+ if (STREQ(srnafrom->identifier, structname))
break;
if (!srnafrom) {
@@ -984,7 +984,7 @@ void RNA_def_struct_ui_icon(StructRNA *srna, int icon)
void RNA_def_struct_translation_context(StructRNA *srna, const char *context)
{
- srna->translation_context = context ? context : BLF_I18NCONTEXT_DEFAULT_BPYRNA;
+ srna->translation_context = context ? context : BLT_I18NCONTEXT_DEFAULT_BPYRNA;
}
/* Property Definition */
@@ -1113,7 +1113,7 @@ PropertyRNA *RNA_def_property(StructOrFunctionRNA *cont_, const char *identifier
prop->subtype = subtype;
prop->name = identifier;
prop->description = "";
- prop->translation_context = BLF_I18NCONTEXT_DEFAULT_BPYRNA;
+ prop->translation_context = BLT_I18NCONTEXT_DEFAULT_BPYRNA;
/* a priori not raw editable */
prop->rawtype = -1;
@@ -1314,8 +1314,10 @@ void RNA_def_property_ui_icon(PropertyRNA *prop, int icon, bool consecutive)
/**
* The values hare are a little confusing:
*
- * \param step For floats this is (step / 100), why /100? - nobody knows.
- * for int's, whole values are used.
+ * \param step: Used as the value to increase/decrease when clicking on number buttons,
+ * \as well as scaling mouse input for click-dragging number buttons.
+ * For floats this is (step * UI_PRECISION_FLOAT_SCALE), why? - nobody knows.
+ * For ints, whole values are used.
*
* \param precision The number of zeros to show
* (as a whole number - common range is 1 - 6), see PRECISION_FLOAT_MAX
@@ -1550,6 +1552,7 @@ void RNA_def_property_boolean_default(PropertyRNA *prop, int value)
case PROP_BOOLEAN:
{
BoolPropertyRNA *bprop = (BoolPropertyRNA *)prop;
+ BLI_assert(ELEM(value, false, true));
bprop->defaultvalue = value;
break;
}
@@ -1871,15 +1874,15 @@ void RNA_def_property_int_sdna(PropertyRNA *prop, const char *structname, const
}
/* SDNA doesn't pass us unsigned unfortunately .. */
- if (dp->dnatype && strcmp(dp->dnatype, "char") == 0) {
+ if (dp->dnatype && STREQ(dp->dnatype, "char")) {
iprop->hardmin = iprop->softmin = CHAR_MIN;
iprop->hardmax = iprop->softmax = CHAR_MAX;
}
- else if (dp->dnatype && strcmp(dp->dnatype, "short") == 0) {
+ else if (dp->dnatype && STREQ(dp->dnatype, "short")) {
iprop->hardmin = iprop->softmin = SHRT_MIN;
iprop->hardmax = iprop->softmax = SHRT_MAX;
}
- else if (dp->dnatype && strcmp(dp->dnatype, "int") == 0) {
+ else if (dp->dnatype && STREQ(dp->dnatype, "int")) {
iprop->hardmin = INT_MIN;
iprop->hardmax = INT_MAX;
@@ -1923,7 +1926,7 @@ void RNA_def_property_float_sdna(PropertyRNA *prop, const char *structname, cons
}
}
- if (dp->dnatype && strcmp(dp->dnatype, "char") == 0) {
+ if (dp->dnatype && STREQ(dp->dnatype, "char")) {
fprop->hardmin = fprop->softmin = 0.0f;
fprop->hardmax = fprop->softmax = 1.0f;
}
@@ -2060,7 +2063,7 @@ void RNA_def_property_collection_sdna(PropertyRNA *prop, const char *structname,
}
}
- if (dp->dnatype && strcmp(dp->dnatype, "ListBase") == 0) {
+ if (dp->dnatype && STREQ(dp->dnatype, "ListBase")) {
cprop->next = (PropCollectionNextFunc)"rna_iterator_listbase_next";
cprop->get = (PropCollectionGetFunc)"rna_iterator_listbase_get";
cprop->end = (PropCollectionEndFunc)"rna_iterator_listbase_end";
@@ -2105,7 +2108,7 @@ void RNA_def_property_collection_sdna(PropertyRNA *prop, const char *structname,
void RNA_def_property_translation_context(PropertyRNA *prop, const char *context)
{
- prop->translation_context = context ? context : BLF_I18NCONTEXT_DEFAULT_BPYRNA;
+ prop->translation_context = context ? context : BLT_I18NCONTEXT_DEFAULT_BPYRNA;
}
/* Functions */
@@ -2856,7 +2859,7 @@ PropertyRNA *RNA_def_float_rotation(StructOrFunctionRNA *cont_, const char *iden
ASSERT_SOFT_HARD_LIMITS;
- prop = RNA_def_property(cont, identifier, PROP_FLOAT, (len != 0) ? PROP_EULER : PROP_ANGLE);
+ prop = RNA_def_property(cont, identifier, PROP_FLOAT, (len >= 3) ? PROP_EULER : PROP_ANGLE);
if (len != 0) {
RNA_def_property_array(prop, len);
if (default_value) RNA_def_property_float_array_default(prop, default_value);
@@ -2867,7 +2870,7 @@ PropertyRNA *RNA_def_float_rotation(StructOrFunctionRNA *cont_, const char *iden
}
if (hardmin != hardmax) RNA_def_property_range(prop, hardmin, hardmax);
RNA_def_property_ui_text(prop, ui_name, ui_description);
- RNA_def_property_ui_range(prop, softmin, softmax, 1, 3);
+ RNA_def_property_ui_range(prop, softmin, softmax, 10, 3);
return prop;
}
@@ -3410,7 +3413,7 @@ static void rna_def_property_free(StructOrFunctionRNA *cont_, PropertyRNA *prop)
if (prop->flag & PROP_RUNTIME) {
if (cont->prophash)
- BLI_ghash_remove(cont->prophash, (void *)prop->identifier, NULL, NULL);
+ BLI_ghash_remove(cont->prophash, prop->identifier, NULL, NULL);
RNA_def_property_free_pointers(prop);
rna_freelinkN(&cont->properties, prop);
@@ -3427,7 +3430,7 @@ int RNA_def_property_free_identifier(StructOrFunctionRNA *cont_, const char *ide
PropertyRNA *prop;
for (prop = cont->properties.first; prop; prop = prop->next) {
- if (strcmp(prop->identifier, identifier) == 0) {
+ if (STREQ(prop->identifier, identifier)) {
if (prop->flag & PROP_RUNTIME) {
rna_def_property_free(cont_, prop);
return 1;
diff --git a/source/blender/makesrna/intern/rna_depsgraph.c b/source/blender/makesrna/intern/rna_depsgraph.c
new file mode 100644
index 00000000000..8ac1e2acc60
--- /dev/null
+++ b/source/blender/makesrna/intern/rna_depsgraph.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): Blender Foundation (2014).
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/makesrna/intern/rna_depsgraph.c
+ * \ingroup RNA
+ */
+
+#include <stdlib.h>
+
+#include "BLI_utildefines.h"
+#include "BLI_path_util.h"
+
+#include "RNA_define.h"
+#include "RNA_enum_types.h"
+
+#include "rna_internal.h"
+
+#include "DEG_depsgraph.h"
+
+#include "BKE_depsgraph.h"
+
+#ifdef RNA_RUNTIME
+
+#include "BKE_report.h"
+
+#include "DEG_depsgraph_debug.h"
+
+static void rna_Depsgraph_debug_graphviz(Depsgraph *graph, const char *filename)
+{
+ FILE *f = fopen(filename, "w");
+ if (f == NULL)
+ return;
+
+ DEG_debug_graphviz(graph, f, "Depsgraph", false);
+
+ fclose(f);
+}
+
+static void rna_Depsgraph_debug_rebuild(Depsgraph *UNUSED(graph), Main *bmain)
+{
+ Scene *sce;
+ DAG_relations_tag_update(bmain);
+ for (sce = bmain->scene.first; sce; sce = sce->id.next) {
+ DAG_scene_relations_rebuild(bmain, sce);
+ DEG_graph_on_visible_update(bmain, sce);
+ }
+}
+
+static void rna_Depsgraph_debug_stats(Depsgraph *graph, ReportList *reports)
+{
+ size_t outer, ops, rels;
+
+ DEG_stats_simple(graph, &outer, &ops, &rels);
+
+ // XXX: report doesn't seem to work
+ printf("Approx %lu Operations, %lu Relations, %lu Outer Nodes\n",
+ ops, rels, outer);
+
+ BKE_reportf(reports, RPT_WARNING, "Approx. %lu Operations, %lu Relations, %lu Outer Nodes",
+ ops, rels, outer);
+}
+
+#else
+
+static void rna_def_depsgraph(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ FunctionRNA *func;
+ PropertyRNA *parm;
+
+ srna = RNA_def_struct(brna, "Depsgraph", NULL);
+ RNA_def_struct_ui_text(srna, "Dependency Graph", "");
+
+ func = RNA_def_function(srna, "debug_graphviz", "rna_Depsgraph_debug_graphviz");
+ parm = RNA_def_string_file_path(func, "filename", NULL, FILE_MAX, "File Name",
+ "File in which to store graphviz debug output");
+ RNA_def_property_flag(parm, PROP_REQUIRED);
+
+ func = RNA_def_function(srna, "debug_rebuild", "rna_Depsgraph_debug_rebuild");
+ RNA_def_function_flag(func, FUNC_USE_MAIN);
+ RNA_def_property_flag(parm, PROP_REQUIRED);
+
+ func = RNA_def_function(srna, "debug_stats", "rna_Depsgraph_debug_stats");
+ RNA_def_function_ui_description(func, "Report the number of elements in the Dependency Graph");
+ RNA_def_function_flag(func, FUNC_USE_REPORTS);
+}
+
+void RNA_def_depsgraph(BlenderRNA *brna)
+{
+ rna_def_depsgraph(brna);
+}
+
+#endif
diff --git a/source/blender/makesrna/intern/rna_dynamicpaint.c b/source/blender/makesrna/intern/rna_dynamicpaint.c
index 4288bf2dddb..229cdaa6005 100644
--- a/source/blender/makesrna/intern/rna_dynamicpaint.c
+++ b/source/blender/makesrna/intern/rna_dynamicpaint.c
@@ -203,7 +203,7 @@ static void rna_Surface_active_point_range(PointerRNA *ptr, int *min, int *max,
DynamicPaintCanvasSettings *canvas = (DynamicPaintCanvasSettings *)ptr->data;
*min = 0;
- *max = BLI_countlist(&canvas->surfaces) - 1;
+ *max = BLI_listbase_count(&canvas->surfaces) - 1;
}
/* uvlayer */
diff --git a/source/blender/makesrna/intern/rna_fcurve.c b/source/blender/makesrna/intern/rna_fcurve.c
index 3b9078153f3..576af7b3a1c 100644
--- a/source/blender/makesrna/intern/rna_fcurve.c
+++ b/source/blender/makesrna/intern/rna_fcurve.c
@@ -574,7 +574,7 @@ static void rna_FModifier_blending_range(PointerRNA *ptr, float *min, float *max
static void rna_FModifier_verify_data_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
{
FModifier *fcm = (FModifier *)ptr->data;
- FModifierTypeInfo *fmi = fmodifier_get_typeinfo(fcm);
+ const FModifierTypeInfo *fmi = fmodifier_get_typeinfo(fcm);
/* call the verify callback on the modifier if applicable */
if (fmi && fmi->verify_data)
@@ -1948,6 +1948,10 @@ static void rna_def_fcurve(BlenderRNA *brna)
parm = RNA_def_pointer(func, "data", "AnyType", "Data",
"Data containing the property controlled by given FCurve");
RNA_def_property_flag(parm, PROP_REQUIRED | PROP_RNAPTR | PROP_NEVER_NULL);
+
+
+ /* Functions */
+ RNA_api_fcurves(srna);
}
/* *********************** */
diff --git a/source/blender/makesrna/intern/rna_fcurve_api.c b/source/blender/makesrna/intern/rna_fcurve_api.c
index ab96f6f384d..8551ca609f4 100644
--- a/source/blender/makesrna/intern/rna_fcurve_api.c
+++ b/source/blender/makesrna/intern/rna_fcurve_api.c
@@ -39,6 +39,7 @@
#include "RNA_define.h"
#include "DNA_anim_types.h"
+#include "DNA_scene_types.h"
#include "rna_internal.h" /* own include */
@@ -49,8 +50,115 @@
#include "BKE_animsys.h"
#include "BKE_fcurve.h"
+#include "BLI_math.h"
+
+static void rna_FCurve_convert_to_samples(FCurve *fcu, ReportList *reports, int start, int end)
+{
+ /* XXX fcurve_store_samples uses end frame included, which is not consistent with usual behavior in Blender,
+ * nor python slices, etc. Let have public py API be consistent here at least. */
+ end--;
+ if (start > end) {
+ BKE_reportf(reports, RPT_ERROR, "Invalid frame range (%d - %d)", start, end + 1);
+ }
+ else if (fcu->fpt) {
+ BKE_report(reports, RPT_WARNING, "FCurve has already sample points");
+ }
+ else if (!fcu->bezt) {
+ BKE_report(reports, RPT_WARNING, "FCurve has no keyframes");
+ }
+ else {
+ fcurve_store_samples(fcu, NULL, start, end, fcurve_samplingcb_evalcurve);
+ WM_main_add_notifier(NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL);
+ }
+}
+
+static void rna_FCurve_convert_to_keyframes(FCurve *fcu, ReportList *reports, int start, int end)
+{
+ if (start >= end) {
+ BKE_reportf(reports, RPT_ERROR, "Invalid frame range (%d - %d)", start, end);
+ }
+ else if (fcu->bezt) {
+ BKE_report(reports, RPT_WARNING, "FCurve has already keyframes");
+ }
+ else if (!fcu->fpt) {
+ BKE_report(reports, RPT_WARNING, "FCurve has no sample points");
+ }
+ else {
+ BezTriple *bezt;
+ FPoint *fpt = fcu->fpt;
+ int tot_kf = end - start;
+ int tot_sp = fcu->totvert;
+
+ bezt = fcu->bezt = MEM_callocN(sizeof(*fcu->bezt) * (size_t)tot_kf, __func__);
+ fcu->totvert = tot_kf;
+
+ /* Get first sample point to 'copy' as keyframe. */
+ for (; tot_sp && (fpt->vec[0] < (float)start); fpt++, tot_sp--);
+
+ /* Add heading dummy flat points if needed. */
+ for (; tot_kf && (fpt->vec[0] > (float)start); start++, bezt++, tot_kf--) {
+ /* Linear interpolation, of course. */
+ bezt->f1 = bezt->f2 = bezt->f3 = SELECT;
+ bezt->ipo = BEZT_IPO_LIN;
+ bezt->h1 = bezt->h2 = HD_AUTO_ANIM;
+ bezt->vec[1][0] = (float)start;
+ bezt->vec[1][1] = fpt->vec[1];
+ }
+
+ /* Copy actual sample points. */
+ for (; tot_kf && tot_sp; start++, bezt++, tot_kf--, fpt++, tot_sp--) {
+ /* Linear interpolation, of course. */
+ bezt->f1 = bezt->f2 = bezt->f3 = SELECT;
+ bezt->ipo = BEZT_IPO_LIN;
+ bezt->h1 = bezt->h2 = HD_AUTO_ANIM;
+ copy_v2_v2(bezt->vec[1], fpt->vec);
+ }
+
+ /* Add leading dummy flat points if needed. */
+ for (fpt--; tot_kf; start++, bezt++, tot_kf--) {
+ /* Linear interpolation, of course. */
+ bezt->f1 = bezt->f2 = bezt->f3 = SELECT;
+ bezt->ipo = BEZT_IPO_LIN;
+ bezt->h1 = bezt->h2 = HD_AUTO_ANIM;
+ bezt->vec[1][0] = (float)start;
+ bezt->vec[1][1] = fpt->vec[1];
+ }
+
+ MEM_SAFE_FREE(fcu->fpt);
+
+ /* Not strictly needed since we use linear interpolation, but better be consistent here. */
+ calchandles_fcurve(fcu);
+ WM_main_add_notifier(NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL);
+ }
+}
+
#else
+void RNA_api_fcurves(StructRNA *srna)
+{
+ FunctionRNA *func;
+ PropertyRNA *parm;
+
+ func = RNA_def_function(srna, "convert_to_samples", "rna_FCurve_convert_to_samples");
+ RNA_def_function_ui_description(func,
+ "Convert current FCurve from keyframes to sample points, if necessary");
+ RNA_def_function_flag(func, FUNC_USE_REPORTS);
+ parm = RNA_def_int(func, "start", 0, MINAFRAME, MAXFRAME, "Start Frame", "", MINAFRAME, MAXFRAME);
+ RNA_def_property_flag(parm, PROP_REQUIRED);
+ parm = RNA_def_int(func, "end", 0, MINAFRAME, MAXFRAME, "End Frame", "", MINAFRAME, MAXFRAME);
+ RNA_def_property_flag(parm, PROP_REQUIRED);
+
+ func = RNA_def_function(srna, "convert_to_keyframes", "rna_FCurve_convert_to_keyframes");
+ RNA_def_function_ui_description(func,
+ "Convert current FCurve from sample points to keyframes (linear interpolation), "
+ "if necessary");
+ RNA_def_function_flag(func, FUNC_USE_REPORTS);
+ parm = RNA_def_int(func, "start", 0, MINAFRAME, MAXFRAME, "Start Frame", "", MINAFRAME, MAXFRAME);
+ RNA_def_property_flag(parm, PROP_REQUIRED);
+ parm = RNA_def_int(func, "end", 0, MINAFRAME, MAXFRAME, "End Frame", "", MINAFRAME, MAXFRAME);
+ RNA_def_property_flag(parm, PROP_REQUIRED);
+}
+
void RNA_api_drivers(StructRNA *UNUSED(srna))
{
/* FunctionRNA *func; */
diff --git a/source/blender/makesrna/intern/rna_fluidsim.c b/source/blender/makesrna/intern/rna_fluidsim.c
index 01feb3cb748..16e0f17eac5 100644
--- a/source/blender/makesrna/intern/rna_fluidsim.c
+++ b/source/blender/makesrna/intern/rna_fluidsim.c
@@ -343,12 +343,12 @@ static void rna_def_fluidsim_domain(BlenderRNA *brna)
prop = RNA_def_property(srna, "start_time", PROP_FLOAT, PROP_TIME);
RNA_def_property_float_sdna(prop, NULL, "animStart");
- RNA_def_property_range(prop, 0, 100);
+ RNA_def_property_range(prop, 0, FLT_MAX);
RNA_def_property_ui_text(prop, "Start Time", "Simulation time of the first blender frame (in seconds)");
prop = RNA_def_property(srna, "end_time", PROP_FLOAT, PROP_TIME);
RNA_def_property_float_sdna(prop, NULL, "animEnd");
- RNA_def_property_range(prop, 0, 100);
+ RNA_def_property_range(prop, 0, FLT_MAX);
RNA_def_property_ui_text(prop, "End Time", "Simulation time of the last blender frame (in seconds)");
prop = RNA_def_property(srna, "frame_offset", PROP_INT, PROP_NONE);
@@ -627,12 +627,12 @@ static void rna_def_fluidsim_control(BlenderRNA *brna)
prop = RNA_def_property(srna, "start_time", PROP_FLOAT, PROP_TIME);
RNA_def_property_float_sdna(prop, NULL, "cpsTimeStart");
- RNA_def_property_range(prop, 0.0, 100.0);
+ RNA_def_property_range(prop, 0.0, FLT_MAX);
RNA_def_property_ui_text(prop, "Start Time", "Time when the control particles are activated");
prop = RNA_def_property(srna, "end_time", PROP_FLOAT, PROP_TIME);
RNA_def_property_float_sdna(prop, NULL, "cpsTimeEnd");
- RNA_def_property_range(prop, 0.0, 100.0);
+ RNA_def_property_range(prop, 0.0, FLT_MAX);
RNA_def_property_ui_text(prop, "End Time", "Time when the control particles are deactivated");
prop = RNA_def_property(srna, "attraction_strength", PROP_FLOAT, PROP_NONE);
diff --git a/source/blender/makesrna/intern/rna_gpencil.c b/source/blender/makesrna/intern/rna_gpencil.c
index cdedb3576b0..333220146d6 100644
--- a/source/blender/makesrna/intern/rna_gpencil.c
+++ b/source/blender/makesrna/intern/rna_gpencil.c
@@ -33,7 +33,7 @@
#include "BLI_utildefines.h"
-#include "BLF_translation.h"
+#include "BLT_translation.h"
#include "RNA_access.h"
#include "RNA_define.h"
@@ -44,6 +44,8 @@
#ifdef RNA_RUNTIME
+#include "BLI_math.h"
+
#include "WM_api.h"
#include "BKE_gpencil.h"
@@ -53,6 +55,16 @@ static void rna_GPencil_update(Main *UNUSED(bmain), Scene *UNUSED(scene), Pointe
WM_main_add_notifier(NC_GPENCIL | NA_EDITED, NULL);
}
+static char *rna_GPencilLayer_path(PointerRNA *ptr)
+{
+ bGPDlayer *gpl = (bGPDlayer *)ptr->data;
+ char name_esc[sizeof(gpl->info) * 2];
+
+ BLI_strescape(name_esc, gpl->info, sizeof(name_esc));
+
+ return BLI_sprintfN("layers[\"%s\"]", name_esc);
+}
+
static int rna_GPencilLayer_active_frame_editable(PointerRNA *ptr)
{
bGPDlayer *gpl = (bGPDlayer *)ptr->data;
@@ -64,9 +76,54 @@ static int rna_GPencilLayer_active_frame_editable(PointerRNA *ptr)
return 1;
}
-static PointerRNA rna_GPencil_active_layer_get(PointerRNA *ptr)
+static void rna_GPencilLayer_line_width_range(PointerRNA *ptr, int *min, int *max,
+ int *softmin, int *softmax)
+{
+ bGPDlayer *gpl = ptr->data;
+
+ /* The restrictions on max width here are due to OpenGL on Windows not supporting
+ * any widths greater than 10 (for driver-drawn) strokes/points.
+ *
+ * Although most of our 2D strokes also don't suffer from this restriction,
+ * it's relatively hard to test for that. So, for now, only volumetric strokes
+ * get to be larger...
+ */
+ if (gpl->flag & GP_LAYER_VOLUMETRIC) {
+ *min = 1;
+ *max = 300;
+
+ *softmin = 1;
+ *softmax = 100;
+ }
+ else {
+ *min = 1;
+ *max = 10;
+
+ *softmin = 1;
+ *softmax = 10;
+ }
+}
+
+static int rna_GPencilLayer_is_stroke_visible_get(PointerRNA *ptr)
{
+ /* see drawgpencil.c -> gp_draw_data_layers() for more details
+ * about this limit for showing/not showing
+ */
+ bGPDlayer *gpl = (bGPDlayer *)ptr->data;
+ return (gpl->color[3] > 0.001f);
+}
+
+static int rna_GPencilLayer_is_fill_visible_get(PointerRNA *ptr)
+{
+ /* see drawgpencil.c -> gp_draw_data_layers() for more details
+ * about this limit for showing/not showing
+ */
+ bGPDlayer *gpl = (bGPDlayer *)ptr->data;
+ return (gpl->fill[3] > 0.001f);
+}
+static PointerRNA rna_GPencil_active_layer_get(PointerRNA *ptr)
+{
bGPdata *gpd = ptr->id.data;
if (GS(gpd->id.name) == ID_GD) { /* why would this ever be not GD */
@@ -101,9 +158,38 @@ static void rna_GPencil_active_layer_set(PointerRNA *ptr, PointerRNA value)
gl->flag &= ~GP_LAYER_ACTIVE;
}
}
+
+ WM_main_add_notifier(NC_GPENCIL | NA_EDITED, NULL);
}
}
+static int rna_GPencil_active_layer_index_get(PointerRNA *ptr)
+{
+ bGPdata *gpd = (bGPdata *)ptr->id.data;
+ bGPDlayer *gpl = gpencil_layer_getactive(gpd);
+
+ return BLI_findindex(&gpd->layers, gpl);
+}
+
+static void rna_GPencil_active_layer_index_set(PointerRNA *ptr, int value)
+{
+ bGPdata *gpd = (bGPdata *)ptr->id.data;
+ bGPDlayer *gpl = BLI_findlink(&gpd->layers, value);
+
+ gpencil_layer_setactive(gpd, gpl);
+}
+
+static void rna_GPencil_active_layer_index_range(PointerRNA *ptr, int *min, int *max, int *softmin, int *softmax)
+{
+ bGPdata *gpd = (bGPdata *)ptr->id.data;
+
+ *min = 0;
+ *max = max_ii(0, BLI_listbase_count(&gpd->layers) - 1);
+
+ *softmin = *min;
+ *softmax = *max;
+}
+
static void rna_GPencilLayer_info_set(PointerRNA *ptr, const char *value)
{
bGPdata *gpd = ptr->id.data;
@@ -115,6 +201,63 @@ static void rna_GPencilLayer_info_set(PointerRNA *ptr, const char *value)
BLI_uniquename(&gpd->layers, gpl, DATA_("GP_Layer"), '.', offsetof(bGPDlayer, info), sizeof(gpl->info));
}
+
+static bGPDstroke *rna_GPencil_stroke_point_find_stroke(const bGPdata *gpd, const bGPDspoint *pt, bGPDlayer **r_gpl, bGPDframe **r_gpf)
+{
+ bGPDlayer *gpl;
+ bGPDstroke *gps;
+
+ /* sanity checks */
+ if (ELEM(NULL, gpd, pt)) {
+ return NULL;
+ }
+
+ if (r_gpl) *r_gpl = NULL;
+ if (r_gpf) *r_gpf = NULL;
+
+ /* there's no faster alternative than just looping over everything... */
+ for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ if (gpl->actframe) {
+ for (gps = gpl->actframe->strokes.first; gps; gps = gps->next) {
+ if ((pt >= gps->points) && (pt < &gps->points[gps->totpoints])) {
+ /* found it */
+ if (r_gpl) *r_gpl = gpl;
+ if (r_gpf) *r_gpf = gpl->actframe;
+
+ return gps;
+ }
+ }
+ }
+ }
+
+ /* didn't find it */
+ return NULL;
+}
+
+static void rna_GPencil_stroke_point_select_set(PointerRNA *ptr, const int value)
+{
+ bGPdata *gpd = ptr->id.data;
+ bGPDspoint *pt = ptr->data;
+ bGPDstroke *gps = NULL;
+
+ /* Ensure that corresponding stroke is set
+ * - Since we don't have direct access, we're going to have to search
+ * - We don't apply selection value unless we can find the corresponding
+ * stroke, so that they don't get out of sync
+ */
+ gps = rna_GPencil_stroke_point_find_stroke(gpd, pt, NULL, NULL);
+ if (gps) {
+ /* Set the new selection state for the point */
+ if (value)
+ pt->flag |= GP_SPOINT_SELECT;
+ else
+ pt->flag &= ~GP_SPOINT_SELECT;
+
+ /* Check if the stroke should be selected or not... */
+ gpencil_stroke_sync_selection(gps);
+ }
+}
+
static void rna_GPencil_stroke_point_add(bGPDstroke *stroke, int count)
{
if (count > 0) {
@@ -178,6 +321,27 @@ static void rna_GPencil_stroke_remove(bGPDframe *frame, ReportList *reports, Poi
WM_main_add_notifier(NC_GPENCIL | NA_EDITED, NULL);
}
+static void rna_GPencil_stroke_select_set(PointerRNA *ptr, const int value)
+{
+ bGPDstroke *gps = ptr->data;
+ bGPDspoint *pt;
+ int i;
+
+ /* set new value */
+ if (value)
+ gps->flag |= GP_STROKE_SELECT;
+ else
+ gps->flag &= ~GP_STROKE_SELECT;
+
+ /* ensure that the stroke's points are selected in the same way */
+ for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
+ if (value)
+ pt->flag |= GP_SPOINT_SELECT;
+ else
+ pt->flag &= ~GP_SPOINT_SELECT;
+ }
+}
+
static bGPDframe *rna_GPencil_frame_new(bGPDlayer *layer, ReportList *reports, int frame_number)
{
bGPDframe *frame;
@@ -289,6 +453,12 @@ static void rna_def_gpencil_stroke_point(BlenderRNA *brna)
RNA_def_property_range(prop, 0.0f, 1.0f);
RNA_def_property_ui_text(prop, "Pressure", "Pressure of tablet at point when drawing it");
RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update");
+
+ prop = RNA_def_property(srna, "select", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_SPOINT_SELECT);
+ RNA_def_property_boolean_funcs(prop, NULL, "rna_GPencil_stroke_point_select_set");
+ RNA_def_property_ui_text(prop, "Select", "Point is selected for viewport editing");
+ RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update");
}
static void rna_def_gpencil_stroke_points_api(BlenderRNA *brna, PropertyRNA *cprop)
@@ -336,12 +506,19 @@ static void rna_def_gpencil_stroke(BlenderRNA *brna)
RNA_def_property_struct_type(prop, "GPencilStrokePoint");
RNA_def_property_ui_text(prop, "Stroke Points", "Stroke data points");
rna_def_gpencil_stroke_points_api(brna, prop);
-
+
+ /* Settings */
prop = RNA_def_property(srna, "draw_mode", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_bitflag_sdna(prop, NULL, "flag");
RNA_def_property_enum_items(prop, stroke_draw_mode_items);
RNA_def_property_ui_text(prop, "Draw Mode", "");
RNA_def_property_update(prop, 0, "rna_GPencil_update");
+
+ prop = RNA_def_property(srna, "select", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_STROKE_SELECT);
+ RNA_def_property_boolean_funcs(prop, NULL, "rna_GPencil_stroke_select_set");
+ RNA_def_property_ui_text(prop, "Select", "Stroke is selected for viewport editing");
+ RNA_def_property_update(prop, 0, "rna_GPencil_update");
}
static void rna_def_gpencil_strokes_api(BlenderRNA *brna, PropertyRNA *cprop)
@@ -391,7 +568,7 @@ static void rna_def_gpencil_frame(BlenderRNA *brna)
prop = RNA_def_property(srna, "frame_number", PROP_INT, PROP_NONE);
RNA_def_property_int_sdna(prop, NULL, "framenum");
/* XXX note: this cannot occur on the same frame as another sketch */
- RNA_def_property_range(prop, MINAFRAME, MAXFRAME);
+ RNA_def_property_range(prop, -MAXFRAME, MAXFRAME);
RNA_def_property_ui_text(prop, "Frame Number", "The frame on which this sketch appears");
/* Flags */
@@ -402,7 +579,9 @@ static void rna_def_gpencil_frame(BlenderRNA *brna)
prop = RNA_def_property(srna, "select", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_FRAME_SELECT);
RNA_def_property_ui_text(prop, "Select", "Frame is selected for editing in the Dope Sheet");
-
+
+
+ /* API */
func = RNA_def_function(srna, "clear", "rna_GPencil_frame_clear");
RNA_def_function_ui_description(func, "Remove all the grease pencil frame data");
}
@@ -453,6 +632,7 @@ static void rna_def_gpencil_layer(BlenderRNA *brna)
srna = RNA_def_struct(brna, "GPencilLayer", NULL);
RNA_def_struct_sdna(srna, "bGPDlayer");
RNA_def_struct_ui_text(srna, "Grease Pencil Layer", "Collection of related sketches");
+ RNA_def_struct_path_func(srna, "rna_GPencilLayer_path");
/* Name */
prop = RNA_def_property(srna, "info", PROP_STRING, PROP_NONE);
@@ -475,7 +655,14 @@ static void rna_def_gpencil_layer(BlenderRNA *brna)
RNA_def_property_editable_func(prop, "rna_GPencilLayer_active_frame_editable");
RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, NULL);
- /* Drawing Color */
+ /* Draw Style */
+ // TODO: replace these with a "draw type" combo (i.e. strokes only, filled strokes, strokes + fills, volumetric)?
+ prop = RNA_def_property(srna, "use_volumetric_strokes", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_LAYER_VOLUMETRIC);
+ RNA_def_property_ui_text(prop, "Volumetric Strokes", "Draw strokes as a series of circular blobs, resulting in a volumetric effect");
+ RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update");
+
+ /* Stroke Drawing Color */
prop = RNA_def_property(srna, "color", PROP_FLOAT, PROP_COLOR_GAMMA);
RNA_def_property_array(prop, 3);
RNA_def_property_range(prop, 0.0f, 1.0f);
@@ -484,14 +671,29 @@ static void rna_def_gpencil_layer(BlenderRNA *brna)
prop = RNA_def_property(srna, "alpha", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "color[3]");
- RNA_def_property_range(prop, 0.3, 1.0f);
+ RNA_def_property_range(prop, 0.0, 1.0f);
RNA_def_property_ui_text(prop, "Opacity", "Layer Opacity");
RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update");
+ /* Fill Drawing Color */
+ prop = RNA_def_property(srna, "fill_color", PROP_FLOAT, PROP_COLOR_GAMMA);
+ RNA_def_property_float_sdna(prop, NULL, "fill");
+ RNA_def_property_array(prop, 3);
+ RNA_def_property_range(prop, 0.0f, 1.0f);
+ RNA_def_property_ui_text(prop, "Fill Color", "Color for filling region bounded by each stroke");
+ RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update");
+
+ prop = RNA_def_property(srna, "fill_alpha", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "fill[3]");
+ RNA_def_property_range(prop, 0.0, 1.0f);
+ RNA_def_property_ui_text(prop, "Fill Opacity", "Opacity for filling region bounded by each stroke");
+ RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update");
+
/* Line Thickness */
prop = RNA_def_property(srna, "line_width", PROP_INT, PROP_PIXEL);
RNA_def_property_int_sdna(prop, NULL, "thickness");
- RNA_def_property_range(prop, 1, 10);
+ //RNA_def_property_range(prop, 1, 10); /* 10 px limit comes from Windows OpenGL limits for natively-drawn strokes */
+ RNA_def_property_int_funcs(prop, NULL, NULL, "rna_GPencilLayer_line_width_range");
RNA_def_property_ui_text(prop, "Thickness", "Thickness of strokes (in pixels)");
RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update");
@@ -501,29 +703,59 @@ static void rna_def_gpencil_layer(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Onion Skinning", "Ghost frames on either side of frame");
RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update");
- prop = RNA_def_property(srna, "ghost_range_max", PROP_INT, PROP_NONE);
+ prop = RNA_def_property(srna, "ghost_before_range", PROP_INT, PROP_NONE);
RNA_def_property_int_sdna(prop, NULL, "gstep");
RNA_def_property_range(prop, 0, 120);
- RNA_def_property_ui_text(prop, "Max Ghost Range",
- "Maximum number of frames on either side of the active frame to show "
- "(0 = show the 'first' available sketch on either side)");
+ RNA_def_property_ui_text(prop, "Frames Before",
+ "Maximum number of frames to show before current frame "
+ "(0 = show only the previous sketch)");
+ RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update");
+
+ prop = RNA_def_property(srna, "ghost_after_range", PROP_INT, PROP_NONE);
+ RNA_def_property_int_sdna(prop, NULL, "gstep_next");
+ RNA_def_property_range(prop, 0, 120);
+ RNA_def_property_ui_text(prop, "Frames After",
+ "Maximum number of frames to show after current frame "
+ "(0 = show only the next sketch)");
+ RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update");
+
+ prop = RNA_def_property(srna, "use_ghost_custom_colors", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_LAYER_GHOST_PREVCOL | GP_LAYER_GHOST_NEXTCOL);
+ RNA_def_property_ui_text(prop, "Use Custom Ghost Colors", "Use custom colors for ghost frames");
+ RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update");
+
+ prop = RNA_def_property(srna, "before_color", PROP_FLOAT, PROP_COLOR_GAMMA);
+ RNA_def_property_float_sdna(prop, NULL, "gcolor_prev");
+ RNA_def_property_array(prop, 3);
+ RNA_def_property_range(prop, 0.0f, 1.0f);
+ RNA_def_property_ui_text(prop, "Before Color", "Base color for ghosts before the active frame");
+ RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update");
+
+ prop = RNA_def_property(srna, "after_color", PROP_FLOAT, PROP_COLOR_GAMMA);
+ RNA_def_property_float_sdna(prop, NULL, "gcolor_next");
+ RNA_def_property_array(prop, 3);
+ RNA_def_property_range(prop, 0.0f, 1.0f);
+ RNA_def_property_ui_text(prop, "After Color", "Base color for ghosts after the active frame");
RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update");
/* Flags */
prop = RNA_def_property(srna, "hide", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_LAYER_HIDE);
+ RNA_def_property_ui_icon(prop, ICON_RESTRICT_VIEW_OFF, 1);
RNA_def_property_ui_text(prop, "Hide", "Set layer Visibility");
RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update");
prop = RNA_def_property(srna, "lock", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_LAYER_LOCKED);
+ RNA_def_property_ui_icon(prop, ICON_UNLOCKED, 1);
RNA_def_property_ui_text(prop, "Locked", "Protect layer from further editing and/or frame changes");
- RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, NULL);
+ RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update");
prop = RNA_def_property(srna, "lock_frame", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_LAYER_FRAMELOCK);
+ RNA_def_property_ui_icon(prop, ICON_UNLOCKED, 1);
RNA_def_property_ui_text(prop, "Frame Locked", "Lock current frame displayed by layer");
- RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, NULL);
+ RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update");
/* expose as layers.active */
#if 0
@@ -537,14 +769,14 @@ static void rna_def_gpencil_layer(BlenderRNA *brna)
prop = RNA_def_property(srna, "select", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_LAYER_SELECT);
RNA_def_property_ui_text(prop, "Select", "Layer is selected for editing in the Dope Sheet");
- RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, NULL);
+ RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update");
/* XXX keep this option? */
prop = RNA_def_property(srna, "show_points", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_LAYER_DRAWDEBUG);
RNA_def_property_ui_text(prop, "Show Points", "Draw the points which make up the strokes (for debugging purposes)");
- RNA_def_property_update_runtime(prop, "rna_GPencil_update");
-
+ RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update");
+
/* X-Ray */
prop = RNA_def_property(srna, "show_x_ray", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", GP_LAYER_NO_XRAY);
@@ -552,6 +784,17 @@ static void rna_def_gpencil_layer(BlenderRNA *brna)
RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update");
+ /* Read-only state props (for simpler UI code) */
+ prop = RNA_def_property(srna, "is_stroke_visible", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_funcs(prop, "rna_GPencilLayer_is_stroke_visible_get", NULL);
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_property_ui_text(prop, "Is Stroke Visible", "True when opacity of stroke is set high enough to be visible");
+
+ prop = RNA_def_property(srna, "is_fill_visible", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_funcs(prop, "rna_GPencilLayer_is_fill_visible_get", NULL);
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_property_ui_text(prop, "Is Fill Visible", "True when opacity of fill is set high enough to be visible");
+
/* Layers API */
func = RNA_def_function(srna, "clear", "rna_GPencil_layer_clear");
RNA_def_function_ui_description(func, "Remove all the grease pencil layer data");
@@ -586,10 +829,18 @@ static void rna_def_gpencil_layers_api(BlenderRNA *brna, PropertyRNA *cprop)
RNA_def_property_clear_flag(parm, PROP_THICK_WRAP);
prop = RNA_def_property(srna, "active", PROP_POINTER, PROP_NONE);
- RNA_def_property_struct_type(prop, "GreasePencil");
+ RNA_def_property_struct_type(prop, "GPencilLayer");
RNA_def_property_pointer_funcs(prop, "rna_GPencil_active_layer_get", "rna_GPencil_active_layer_set", NULL, NULL);
RNA_def_property_flag(prop, PROP_EDITABLE);
RNA_def_property_ui_text(prop, "Active Layer", "Active grease pencil layer");
+
+ prop = RNA_def_property(srna, "active_index", PROP_INT, PROP_UNSIGNED);
+
+ RNA_def_property_int_funcs(prop,
+ "rna_GPencil_active_layer_index_get",
+ "rna_GPencil_active_layer_index_set",
+ "rna_GPencil_active_layer_index_range");
+ RNA_def_property_ui_text(prop, "Active Layer Index", "Index of active grease pencil layer");
}
static void rna_def_gpencil_data(BlenderRNA *brna)
@@ -618,6 +869,9 @@ static void rna_def_gpencil_data(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Layers", "");
rna_def_gpencil_layers_api(brna, prop);
+ /* Animation Data */
+ rna_def_animdata_common(srna);
+
/* Flags */
prop = RNA_def_property(srna, "draw_mode", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_bitflag_sdna(prop, NULL, "flag");
@@ -629,7 +883,13 @@ static void rna_def_gpencil_data(BlenderRNA *brna)
RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_DATA_DEPTH_STROKE_ENDPOINTS);
RNA_def_property_ui_text(prop, "Only Endpoints", "Only use the first and last parts of the stroke for snapping");
RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, NULL);
-
+
+ prop = RNA_def_property(srna, "use_stroke_edit_mode", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_DATA_STROKE_EDITMODE);
+ RNA_def_property_ui_text(prop, "Stroke Edit Mode", "Enable alternative keymap to make editing stroke points easier");
+ RNA_def_property_update(prop, NC_GPENCIL | ND_DATA | ND_GPENCIL_EDITMODE, "rna_GPencil_update");
+
+ /* API Functions */
func = RNA_def_function(srna, "clear", "rna_GPencil_clear");
RNA_def_function_ui_description(func, "Remove all the grease pencil data");
}
diff --git a/source/blender/makesrna/intern/rna_image.c b/source/blender/makesrna/intern/rna_image.c
index 0b129bab524..561f5c9dd26 100644
--- a/source/blender/makesrna/intern/rna_image.c
+++ b/source/blender/makesrna/intern/rna_image.c
@@ -35,6 +35,7 @@
#include "BKE_depsgraph.h"
#include "BKE_image.h"
+#include "RNA_access.h"
#include "RNA_define.h"
#include "RNA_enum_types.h"
@@ -137,6 +138,23 @@ static void rna_Image_colormanage_update(Main *UNUSED(bmain), Scene *UNUSED(scen
WM_main_add_notifier(NC_IMAGE | NA_EDITED, &ima->id);
}
+static void rna_Image_views_format_update(Main *UNUSED(bmain), Scene *scene, PointerRNA *ptr)
+{
+ Image *ima = ptr->id.data;
+ ImBuf *ibuf;
+ void *lock;
+
+ ibuf = BKE_image_acquire_ibuf(ima, NULL, &lock);
+
+ if (ibuf) {
+ ImageUser iuser = {NULL};
+ iuser.scene = scene;
+ BKE_image_signal(ima, &iuser, IMA_SIGNAL_FREE);
+ }
+
+ BKE_image_release_ibuf(ima, ibuf, lock);
+}
+
static void rna_ImageUser_update(Main *UNUSED(bmain), Scene *scene, PointerRNA *ptr)
{
ImageUser *iuser = ptr->data;
@@ -193,7 +211,7 @@ static int rna_Image_file_format_get(PointerRNA *ptr)
{
Image *image = (Image *)ptr->data;
ImBuf *ibuf = BKE_image_acquire_ibuf(image, NULL, NULL);
- int imtype = BKE_ftype_to_imtype(ibuf ? ibuf->ftype : 0);
+ int imtype = BKE_image_ftype_to_imtype(ibuf ? ibuf->ftype : 0, ibuf ? &ibuf->foptions : NULL);
BKE_image_release_ibuf(image, ibuf, NULL);
@@ -204,8 +222,9 @@ static void rna_Image_file_format_set(PointerRNA *ptr, int value)
{
Image *image = (Image *)ptr->data;
if (BKE_imtype_is_movie(value) == 0) { /* should be able to throw an error here */
- int ftype = BKE_imtype_to_ftype(value);
- BKE_image_file_format_set(image, ftype);
+ ImbFormatOptions options;
+ int ftype = BKE_image_imtype_to_ftype(value, &options);
+ BKE_image_file_format_set(image, ftype, &options);
}
}
@@ -292,11 +311,20 @@ static int rna_Image_depth_get(PointerRNA *ptr)
static int rna_Image_frame_duration_get(PointerRNA *ptr)
{
- Image *im = (Image *)ptr->data;
+ Image *ima = ptr->id.data;
+ int duration = 1;
+
+ if (BKE_image_has_anim(ima)) {
+ duration = IMB_anim_get_duration(((ImageAnim *)ima->anims.first)->anim, IMB_TC_RECORD_RUN);
+ }
+ else {
+ /* acquire ensures ima->anim is set, if possible! */
+ void *lock;
+ ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, &lock);
+ BKE_image_release_ibuf(ima, ibuf, lock);
+ }
- if (im->anim)
- return IMB_anim_get_duration(im->anim, IMB_TC_RECORD_RUN);
- return 1;
+ return duration;
}
static int rna_Image_pixels_get_length(PointerRNA *ptr, int length[RNA_MAX_ARRAY_DIMENSION])
@@ -399,6 +427,56 @@ static int rna_Image_is_float_get(PointerRNA *ptr)
return is_float;
}
+static PointerRNA rna_Image_packed_file_get(PointerRNA *ptr)
+{
+ Image *ima = (Image *)ptr->id.data;
+
+ if (BKE_image_has_packedfile(ima)) {
+ ImagePackedFile *imapf = ima->packedfiles.first;
+ return rna_pointer_inherit_refine(ptr, &RNA_PackedFile, imapf->packedfile);
+ }
+ else {
+ return PointerRNA_NULL;
+ }
+}
+
+static void rna_Image_render_slots_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
+{
+ Image *image = (Image *)ptr->id.data;
+ rna_iterator_array_begin(iter, (void *)image->render_slots, sizeof(RenderSlot), IMA_MAX_RENDER_SLOT, 0, NULL);
+}
+
+static PointerRNA rna_render_slots_active_get(PointerRNA *ptr)
+{
+ Image *image = (Image *)ptr->id.data;
+ RenderSlot *render_slot = &image->render_slots[image->render_slot];
+
+ return rna_pointer_inherit_refine(ptr, &RNA_RenderSlot, render_slot);
+}
+
+static void rna_render_slots_active_set(PointerRNA *ptr, PointerRNA value)
+{
+ Image *image = (Image *)ptr->id.data;
+ if (value.id.data == image) {
+ RenderSlot *render_slot = (RenderSlot *)value.data;
+ int index = render_slot - image->render_slots;
+ image->render_slot = CLAMPIS(index, 0, IMA_MAX_RENDER_SLOT - 1);
+ }
+}
+
+static int rna_render_slots_active_index_get(PointerRNA *ptr)
+{
+ Image *image = (Image *)ptr->id.data;
+ return image->render_slot;
+}
+
+static void rna_render_slots_active_index_set(PointerRNA *ptr, int value)
+{
+ Image *image = (Image *)ptr->id.data;
+ image->render_slot = value;
+ CLAMP(image->render_slot, 0, IMA_MAX_RENDER_SLOT - 1);
+}
+
#else
static void rna_def_imageuser(BlenderRNA *brna)
@@ -465,6 +543,71 @@ static void rna_def_imageuser(BlenderRNA *brna)
RNA_def_property_int_sdna(prop, NULL, "pass");
RNA_def_property_clear_flag(prop, PROP_EDITABLE); /* image_multi_cb */
RNA_def_property_ui_text(prop, "Pass", "Pass in multilayer image");
+
+ prop = RNA_def_property(srna, "multilayer_view", PROP_INT, PROP_UNSIGNED);
+ RNA_def_property_int_sdna(prop, NULL, "view");
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE); /* image_multi_cb */
+ RNA_def_property_ui_text(prop, "View", "View in multilayer image");
+}
+
+/* image.packed_files */
+static void rna_def_image_packed_files(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ srna = RNA_def_struct(brna, "ImagePackedFile", NULL);
+ RNA_def_struct_sdna(srna, "ImagePackedFile");
+
+ prop = RNA_def_property(srna, "packed_file", PROP_POINTER, PROP_NONE);
+ RNA_def_property_pointer_sdna(prop, NULL, "packedfile");
+ RNA_def_property_ui_text(prop, "Packed File", "");
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+
+ prop = RNA_def_property(srna, "filepath", PROP_STRING, PROP_FILEPATH);
+ RNA_def_property_string_sdna(prop, NULL, "filepath");
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_struct_name_property(srna, prop);
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+}
+
+static void rna_def_render_slot(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+ srna = RNA_def_struct(brna, "RenderSlot", NULL);
+ RNA_def_struct_ui_text(srna, "Render Slot", "Parameters defining the render slot");
+
+ prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE);
+ RNA_def_property_string_sdna(prop, NULL, "name");
+ RNA_def_property_ui_text(prop, "Name", "Render slot name");
+ RNA_def_property_update(prop, NC_IMAGE | ND_DISPLAY, NULL);
+}
+
+static void rna_def_render_slots(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ srna = RNA_def_struct(brna, "RenderSlots", NULL);
+ RNA_def_struct_sdna(srna, "RenderSlot");
+ RNA_def_struct_ui_text(srna, "Render Slots", "Collection of the render slots");
+
+ prop = RNA_def_property(srna, "active", PROP_POINTER, PROP_NONE);
+ RNA_def_property_struct_type(prop, "RenderSlot");
+ RNA_def_property_pointer_funcs(prop, "rna_render_slots_active_get", "rna_render_slots_active_set", NULL, NULL);
+ RNA_def_property_flag(prop, PROP_EDITABLE | PROP_NEVER_UNLINK);
+ RNA_def_property_ui_text(prop, "Active", "Active render slot of the image");
+ RNA_def_property_update(prop, NC_IMAGE | ND_DISPLAY, NULL);
+
+ prop = RNA_def_property(srna, "active_index", PROP_INT, PROP_NONE);
+ RNA_def_property_int_funcs(prop, "rna_render_slots_active_index_get",
+ "rna_render_slots_active_index_set",
+ NULL);
+ RNA_def_property_range(prop, 0, IMA_MAX_RENDER_SLOT);
+ RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
+ RNA_def_property_ui_text(prop, "Active Index", "Index of an active render slot of the image");
+ RNA_def_property_update(prop, NC_IMAGE | ND_DISPLAY, NULL);
}
static void rna_def_image(BlenderRNA *brna)
@@ -527,15 +670,23 @@ static void rna_def_image(BlenderRNA *brna)
RNA_def_property_update(prop, NC_IMAGE | ND_DISPLAY, NULL);
prop = RNA_def_property(srna, "packed_file", PROP_POINTER, PROP_NONE);
+ RNA_def_property_struct_type(prop, "PackedFile");
RNA_def_property_pointer_sdna(prop, NULL, "packedfile");
- RNA_def_property_ui_text(prop, "Packed File", "");
-
+ RNA_def_property_pointer_funcs(prop, "rna_Image_packed_file_get", NULL, NULL, NULL);
+ RNA_def_property_ui_text(prop, "Packed File", "First packed file of the image");
+
+ prop = RNA_def_property(srna, "packed_files", PROP_COLLECTION, PROP_NONE);
+ RNA_def_property_collection_sdna(prop, NULL, "packedfiles", NULL);
+ RNA_def_property_struct_type(prop, "ImagePackedFile");
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_property_ui_text(prop, "Packed Files", "Collection of packed images");
+
prop = RNA_def_property(srna, "field_order", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_bitflag_sdna(prop, NULL, "flag");
RNA_def_property_enum_items(prop, prop_field_order_items);
RNA_def_property_ui_text(prop, "Field Order", "Order of video fields (select which lines are displayed first)");
RNA_def_property_update(prop, NC_IMAGE | ND_DISPLAY, NULL);
-
+
/* booleans */
prop = RNA_def_property(srna, "use_fields", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", IMA_FIELDS);
@@ -554,6 +705,26 @@ static void rna_def_image(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Use Alpha", "Use the alpha channel information from the image or make image fully opaque");
RNA_def_property_update(prop, NC_IMAGE | ND_DISPLAY, "rna_Image_colormanage_update");
+ prop = RNA_def_property(srna, "use_deinterlace", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", IMA_DEINTERLACE);
+ RNA_def_property_ui_text(prop, "Deinterlace", "Deinterlace movie file on load");
+ RNA_def_property_update(prop, NC_IMAGE | ND_DISPLAY, "rna_Image_reload_update");
+
+ prop = RNA_def_property(srna, "use_multiview", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", IMA_USE_VIEWS);
+ RNA_def_property_ui_text(prop, "Use Multi-View", "Use Multiple Views (when available)");
+ RNA_def_property_update(prop, NC_IMAGE | ND_DISPLAY, "rna_Image_views_format_update");
+
+ prop = RNA_def_property(srna, "is_stereo_3d", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", IMA_IS_STEREO);
+ RNA_def_property_ui_text(prop, "Stereo 3D", "Image has left and right views");
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+
+ prop = RNA_def_property(srna, "is_multiview", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", IMA_IS_MULTIVIEW);
+ RNA_def_property_ui_text(prop, "Multiple Views", "Image has more than one view");
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+
prop = RNA_def_property(srna, "is_dirty", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_funcs(prop, "rna_Image_dirty_get", NULL);
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
@@ -589,6 +760,13 @@ static void rna_def_image(BlenderRNA *brna)
RNA_def_property_update(prop, NC_IMAGE | ND_DISPLAY, "rna_Image_generated_update");
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
+ prop = RNA_def_property(srna, "generated_color", PROP_FLOAT, PROP_COLOR_GAMMA);
+ RNA_def_property_float_sdna(prop, NULL, "gen_color");
+ RNA_def_property_array(prop, 4);
+ RNA_def_property_ui_text(prop, "Color", "Fill color for the generated image");
+ RNA_def_property_update(prop, NC_IMAGE | ND_DISPLAY, "rna_Image_generated_update");
+ RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
+
/* realtime properties */
prop = RNA_def_property(srna, "mapping", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_bitflag_sdna(prop, NULL, "flag");
@@ -611,13 +789,13 @@ static void rna_def_image(BlenderRNA *brna)
prop = RNA_def_property(srna, "frame_start", PROP_INT, PROP_NONE);
RNA_def_property_int_sdna(prop, NULL, "twsta");
- RNA_def_property_range(prop, 0, 128);
+ RNA_def_property_range(prop, 0, 255);
RNA_def_property_ui_text(prop, "Animation Start", "Start frame of an animated texture");
RNA_def_property_update(prop, NC_IMAGE | ND_DISPLAY, "rna_Image_animated_update");
prop = RNA_def_property(srna, "frame_end", PROP_INT, PROP_NONE);
RNA_def_property_int_sdna(prop, NULL, "twend");
- RNA_def_property_range(prop, 0, 128);
+ RNA_def_property_range(prop, 0, 255);
RNA_def_property_ui_text(prop, "Animation End", "End frame of an animated texture");
RNA_def_property_update(prop, NC_IMAGE | ND_DISPLAY, "rna_Image_animated_update");
@@ -661,10 +839,12 @@ static void rna_def_image(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Bindcode", "OpenGL bindcode");
RNA_def_property_update(prop, NC_IMAGE | ND_DISPLAY, NULL);
- prop = RNA_def_property(srna, "render_slot", PROP_INT, PROP_UNSIGNED);
- RNA_def_property_range(prop, 0, IMA_MAX_RENDER_SLOT - 1);
- RNA_def_property_ui_text(prop, "Render Slot", "The current render slot displayed, only for viewer type images");
- RNA_def_property_update(prop, NC_IMAGE | ND_DISPLAY, NULL);
+ prop = RNA_def_property(srna, "render_slots", PROP_COLLECTION, PROP_NONE);
+ RNA_def_property_struct_type(prop, "RenderSlot");
+ RNA_def_property_ui_text(prop, "Render Slots", "Render slots of the image");
+ RNA_def_property_collection_funcs(prop, "rna_Image_render_slots_begin", "rna_iterator_array_next",
+ "rna_iterator_array_end", "rna_iterator_array_get", NULL, NULL, NULL, NULL);
+ RNA_def_property_srna(prop, "RenderSlots");
/*
* Image.has_data and Image.depth are temporary,
@@ -725,13 +905,29 @@ static void rna_def_image(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Alpha Mode", "Representation of alpha information in the RGBA pixels");
RNA_def_property_update(prop, NC_IMAGE | ND_DISPLAY, "rna_Image_colormanage_update");
+ /* multiview */
+ prop = RNA_def_property(srna, "views_format", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "views_format");
+ RNA_def_property_enum_items(prop, views_format_items);
+ RNA_def_property_ui_text(prop, "Views Format", "Mode to load image views");
+ RNA_def_property_update(prop, NC_IMAGE | ND_DISPLAY, "rna_Image_views_format_update");
+
+ prop = RNA_def_property(srna, "stereo_3d_format", PROP_POINTER, PROP_NONE);
+ RNA_def_property_pointer_sdna(prop, NULL, "stereo3d_format");
+ RNA_def_property_flag(prop, PROP_NEVER_NULL);
+ RNA_def_property_struct_type(prop, "Stereo3dFormat");
+ RNA_def_property_ui_text(prop, "Stereo 3D Format", "Settings for stereo 3d");
+
RNA_api_image(srna);
}
void RNA_def_image(BlenderRNA *brna)
{
+ rna_def_render_slot(brna);
+ rna_def_render_slots(brna);
rna_def_image(brna);
rna_def_imageuser(brna);
+ rna_def_image_packed_files(brna);
}
#endif
diff --git a/source/blender/makesrna/intern/rna_image_api.c b/source/blender/makesrna/intern/rna_image_api.c
index d9a59c4dc55..f187a0e1804 100644
--- a/source/blender/makesrna/intern/rna_image_api.c
+++ b/source/blender/makesrna/intern/rna_image_api.c
@@ -52,13 +52,11 @@
#include "BKE_packedFile.h"
#include "BKE_main.h"
-#include "BKE_global.h" /* grr: G.main->name */
-
#include "IMB_imbuf.h"
#include "IMB_colormanagement.h"
-#include "BIF_gl.h"
#include "GPU_draw.h"
+#include "GPU_debug.h"
#include "DNA_image_types.h"
#include "DNA_scene_types.h"
@@ -74,7 +72,7 @@ static void rna_Image_save_render(Image *image, bContext *C, ReportList *reports
}
if (scene) {
- ImageUser iuser;
+ ImageUser iuser = {NULL};
void *lock;
iuser.scene = scene;
@@ -109,17 +107,22 @@ static void rna_Image_save_render(Image *image, bContext *C, ReportList *reports
}
}
-static void rna_Image_save(Image *image, bContext *C, ReportList *reports)
+static void rna_Image_save(Image *image, Main *bmain, bContext *C, ReportList *reports)
{
ImBuf *ibuf = BKE_image_acquire_ibuf(image, NULL, NULL);
if (ibuf) {
char filename[FILE_MAX];
BLI_strncpy(filename, image->name, sizeof(filename));
- BLI_path_abs(filename, ID_BLEND_PATH(G.main, &image->id));
+ BLI_path_abs(filename, ID_BLEND_PATH(bmain, &image->id));
- if (image->packedfile) {
- if (writePackedFile(reports, image->name, image->packedfile, 0) != RET_OK) {
- BKE_reportf(reports, RPT_ERROR, "Image '%s' could not save packed file to '%s'", image->id.name + 2, image->name);
+ if (BKE_image_has_packedfile(image)) {
+ ImagePackedFile *imapf;
+
+ for (imapf = image->packedfiles.first; imapf; imapf = imapf->next) {
+ if (writePackedFile(reports, imapf->filepath, imapf->packedfile, 0) != RET_OK) {
+ BKE_reportf(reports, RPT_ERROR, "Image '%s' could not save packed file to '%s'",
+ image->id.name + 2, imapf->filepath);
+ }
}
}
else if (IMB_saveiff(ibuf, filename, ibuf->flags)) {
@@ -144,7 +147,9 @@ static void rna_Image_save(Image *image, bContext *C, ReportList *reports)
WM_event_add_notifier(C, NC_IMAGE | NA_EDITED, image);
}
-static void rna_Image_pack(Image *image, bContext *C, ReportList *reports, int as_png)
+static void rna_Image_pack(
+ Image *image, Main *bmain, bContext *C, ReportList *reports,
+ int as_png, const char *data, int data_len)
{
ImBuf *ibuf = BKE_image_acquire_ibuf(image, NULL, NULL);
@@ -152,11 +157,17 @@ static void rna_Image_pack(Image *image, bContext *C, ReportList *reports, int a
BKE_report(reports, RPT_ERROR, "Cannot pack edited image from disk, only as internal PNG");
}
else {
+ BKE_image_free_packedfiles(image);
if (as_png) {
BKE_image_memorypack(image);
}
+ else if (data) {
+ char *data_dup = MEM_mallocN(sizeof(*data_dup) * (size_t)data_len, __func__);
+ memcpy(data_dup, data, (size_t)data_len);
+ BKE_image_packfiles_from_mem(reports, image, data_dup, (size_t)data_len);
+ }
else {
- image->packedfile = newPackedFile(reports, image->name, ID_BLEND_PATH(G.main, &image->id));
+ BKE_image_packfiles(reports, image, ID_BLEND_PATH(bmain, &image->id));
}
}
@@ -166,7 +177,7 @@ static void rna_Image_pack(Image *image, bContext *C, ReportList *reports, int a
static void rna_Image_unpack(Image *image, ReportList *reports, int method)
{
- if (!image->packedfile) {
+ if (!BKE_image_has_packedfile(image)) {
BKE_report(reports, RPT_ERROR, "Image not packed");
}
else if (BKE_image_is_animated(image)) {
@@ -223,31 +234,23 @@ static int rna_Image_gl_load(Image *image, ReportList *reports, int frame, int f
ibuf = BKE_image_acquire_ibuf(image, &iuser, &lock);
+ /* clean glError buffer */
+ while (glGetError() != GL_NO_ERROR) {}
+
if (ibuf == NULL || ibuf->rect == NULL) {
BKE_reportf(reports, RPT_ERROR, "Image '%s' does not have any image data", image->id.name + 2);
BKE_image_release_ibuf(image, ibuf, NULL);
return (int)GL_INVALID_OPERATION;
}
- /* could be made into a function? */
- glGenTextures(1, (GLuint *)bind);
- glBindTexture(GL_TEXTURE_2D, *bind);
-
- if (filter != GL_NEAREST && filter != GL_LINEAR)
- error = (int)gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGBA, ibuf->x, ibuf->y, GL_RGBA, GL_UNSIGNED_BYTE, ibuf->rect);
+ GPU_create_gl_tex(bind, ibuf->rect, ibuf->rect_float, ibuf->x, ibuf->y,
+ (filter != GL_NEAREST && filter != GL_LINEAR), false, image);
- if (!error) {
- /* clean glError buffer */
- while (glGetError() != GL_NO_ERROR) {}
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, (GLint)filter);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, (GLint)mag);
+ glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, image->tpageflag & IMA_CLAMP_U ? GL_CLAMP : GL_REPEAT);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, image->tpageflag & IMA_CLAMP_V ? GL_CLAMP : GL_REPEAT);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, (GLint)filter);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, (GLint)mag);
- glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, ibuf->x, ibuf->y, 0, GL_RGBA, GL_UNSIGNED_BYTE, ibuf->rect);
- error = (int)glGetError();
- }
+ error = glGetError();
if (error) {
glDeleteTextures(1, (GLuint *)bind);
@@ -285,6 +288,11 @@ static void rna_Image_filepath_from_user(Image *image, ImageUser *image_user, ch
BKE_image_user_file_path(image_user, image, filepath);
}
+static void rna_Image_buffers_free(Image *image)
+{
+ BKE_image_free_buffers(image);
+}
+
#else
void RNA_api_image(StructRNA *srna)
@@ -301,12 +309,16 @@ void RNA_api_image(StructRNA *srna)
func = RNA_def_function(srna, "save", "rna_Image_save");
RNA_def_function_ui_description(func, "Save image to its source path");
- RNA_def_function_flag(func, FUNC_USE_CONTEXT | FUNC_USE_REPORTS);
+ RNA_def_function_flag(func, FUNC_USE_MAIN | FUNC_USE_CONTEXT | FUNC_USE_REPORTS);
func = RNA_def_function(srna, "pack", "rna_Image_pack");
RNA_def_function_ui_description(func, "Pack an image as embedded data into the .blend file");
- RNA_def_function_flag(func, FUNC_USE_CONTEXT | FUNC_USE_REPORTS);
+ RNA_def_function_flag(func, FUNC_USE_MAIN | FUNC_USE_CONTEXT | FUNC_USE_REPORTS);
RNA_def_boolean(func, "as_png", 0, "as_png", "Pack the image as PNG (needed for generated/dirty images)");
+ parm = RNA_def_property(func, "data", PROP_STRING, PROP_BYTESTRING);
+ RNA_def_property_ui_text(parm, "data", "Raw data (bytes, exact content of the embedded file)");
+ RNA_def_int(func, "data_len", 0, 0, INT_MAX,
+ "data_len", "length of given data (mandatory if data is provided)", 0, INT_MAX);
func = RNA_def_function(srna, "unpack", "rna_Image_unpack");
RNA_def_function_ui_description(func, "Save an image packed in the .blend file to disk");
@@ -367,6 +379,9 @@ void RNA_api_image(StructRNA *srna)
RNA_def_property_flag(parm, PROP_THICK_WRAP); /* needed for string return value */
RNA_def_function_output(func, parm);
+ func = RNA_def_function(srna, "buffers_free", "rna_Image_buffers_free");
+ RNA_def_function_ui_description(func, "Free the image buffers from memory");
+
/* TODO, pack/unpack, maybe should be generic functions? */
}
diff --git a/source/blender/makesrna/intern/rna_internal.h b/source/blender/makesrna/intern/rna_internal.h
index 83b7a81c649..eab14be9085 100644
--- a/source/blender/makesrna/intern/rna_internal.h
+++ b/source/blender/makesrna/intern/rna_internal.h
@@ -35,16 +35,13 @@
#define RNA_MAGIC ((int)~0)
-struct ColorBand;
struct ID;
struct IDProperty;
struct Main;
struct Mesh;
struct Object;
-struct RenderEngine;
struct ReportList;
struct SDNA;
-struct Sequence;
/* Data structures used during define */
@@ -143,6 +140,7 @@ void RNA_def_constraint(struct BlenderRNA *brna);
void RNA_def_context(struct BlenderRNA *brna);
void RNA_def_controller(struct BlenderRNA *brna);
void RNA_def_curve(struct BlenderRNA *brna);
+void RNA_def_depsgraph(struct BlenderRNA *brna);
void RNA_def_dynamic_paint(struct BlenderRNA *brna);
void RNA_def_fluidsim(struct BlenderRNA *brna);
void RNA_def_fcurve(struct BlenderRNA *brna);
@@ -164,6 +162,7 @@ void RNA_def_nodetree(struct BlenderRNA *brna);
void RNA_def_object(struct BlenderRNA *brna);
void RNA_def_object_force(struct BlenderRNA *brna);
void RNA_def_packedfile(struct BlenderRNA *brna);
+void RNA_def_palette(struct BlenderRNA *brna);
void RNA_def_particle(struct BlenderRNA *brna);
void RNA_def_pose(struct BlenderRNA *brna);
void RNA_def_render(struct BlenderRNA *brna);
@@ -207,6 +206,7 @@ void rna_def_render_layer_common(struct StructRNA *srna, int scene);
void rna_def_actionbone_group_common(struct StructRNA *srna, int update_flag, const char *update_cb);
void rna_ActionGroup_colorset_set(struct PointerRNA *ptr, int value);
+int rna_ActionGroup_is_custom_colorset_get(struct PointerRNA *ptr);
void rna_ID_name_get(struct PointerRNA *ptr, char *value);
int rna_ID_name_length(struct PointerRNA *ptr);
@@ -258,6 +258,7 @@ void RNA_api_armature_edit_bone(StructRNA *srna);
void RNA_api_bone(StructRNA *srna);
void RNA_api_camera(StructRNA *srna);
void RNA_api_curve(StructRNA *srna);
+void RNA_api_fcurves(StructRNA *srna);
void RNA_api_drivers(StructRNA *srna);
void RNA_api_image(struct StructRNA *srna);
void RNA_api_lattice(struct StructRNA *srna);
@@ -286,6 +287,7 @@ void RNA_api_ui_layout(struct StructRNA *srna);
void RNA_api_window(struct StructRNA *srna);
void RNA_api_wm(struct StructRNA *srna);
void RNA_api_space_node(struct StructRNA *srna);
+void RNA_api_space_text(struct StructRNA *srna);
void RNA_api_region_view3d(struct StructRNA *srna);
void RNA_api_sensor(struct StructRNA *srna);
void RNA_api_controller(struct StructRNA *srna);
@@ -294,6 +296,8 @@ void RNA_api_texture(struct StructRNA *srna);
void RNA_api_environment_map(struct StructRNA *srna);
void RNA_api_sequences(BlenderRNA *brna, PropertyRNA *cprop);
void RNA_api_sequence_elements(BlenderRNA *brna, PropertyRNA *cprop);
+void RNA_api_sound(struct StructRNA *srna);
+void RNA_api_vfont(struct StructRNA *srna);
/* main collection functions */
void RNA_def_main_cameras(BlenderRNA *brna, PropertyRNA *cprop);
@@ -321,6 +325,7 @@ void RNA_def_main_sounds(BlenderRNA *brna, PropertyRNA *cprop);
void RNA_def_main_armatures(BlenderRNA *brna, PropertyRNA *cprop);
void RNA_def_main_actions(BlenderRNA *brna, PropertyRNA *cprop);
void RNA_def_main_particles(BlenderRNA *brna, PropertyRNA *cprop);
+void RNA_def_main_palettes(BlenderRNA *brna, PropertyRNA *cprop);
void RNA_def_main_gpencil(BlenderRNA *brna, PropertyRNA *cprop);
void RNA_def_main_movieclips(BlenderRNA *brna, PropertyRNA *cprop);
void RNA_def_main_masks(BlenderRNA *brna, PropertyRNA *cprop);
diff --git a/source/blender/makesrna/intern/rna_internal_types.h b/source/blender/makesrna/intern/rna_internal_types.h
index 845d76debd2..ba0705b5caa 100644
--- a/source/blender/makesrna/intern/rna_internal_types.h
+++ b/source/blender/makesrna/intern/rna_internal_types.h
@@ -38,10 +38,8 @@ struct StructRNA;
struct PropertyRNA;
struct PointerRNA;
struct FunctionRNA;
-struct ReportList;
struct CollectionPropertyIterator;
struct bContext;
-struct EnumProperty;
struct IDProperty;
struct GHash;
struct Main;
diff --git a/source/blender/makesrna/intern/rna_key.c b/source/blender/makesrna/intern/rna_key.c
index 7d10511d1c4..c25566b6e33 100644
--- a/source/blender/makesrna/intern/rna_key.c
+++ b/source/blender/makesrna/intern/rna_key.c
@@ -35,7 +35,7 @@
#include "BLI_utildefines.h"
-#include "BLF_translation.h"
+#include "BLT_translation.h"
#include "RNA_access.h"
#include "RNA_define.h"
@@ -48,7 +48,6 @@
#include <stddef.h>
#include "DNA_object_types.h"
-#include "DNA_scene_types.h"
#include "BKE_animsys.h"
#include "BKE_depsgraph.h"
@@ -84,12 +83,12 @@ static void rna_ShapeKey_name_set(PointerRNA *ptr, const char *value)
/* make sure the name is truly unique */
if (ptr->id.data) {
Key *key = rna_ShapeKey_find_key(ptr->id.data);
- BLI_uniquename(&key->block, kb, CTX_DATA_(BLF_I18NCONTEXT_ID_SHAPEKEY, "Key"), '.',
+ BLI_uniquename(&key->block, kb, CTX_DATA_(BLT_I18NCONTEXT_ID_SHAPEKEY, "Key"), '.',
offsetof(KeyBlock, name), sizeof(kb->name));
}
/* fix all the animation data which may link to this */
- BKE_all_animdata_fix_paths_rename(NULL, "key_blocks", oldname, kb->name);
+ BKE_animdata_fix_paths_rename_all(NULL, "key_blocks", oldname, kb->name);
}
static float rna_ShapeKey_frame_get(PointerRNA *ptr)
@@ -675,13 +674,6 @@ static void rna_def_key(BlenderRNA *brna)
RNA_def_property_range(prop, MINFRAME, MAXFRAME);
RNA_def_property_ui_text(prop, "Evaluation Time", "Evaluation time for absolute shape keys");
RNA_def_property_update(prop, 0, "rna_Key_update_data");
-
- prop = RNA_def_property(srna, "slurph", PROP_INT, PROP_UNSIGNED);
- RNA_def_property_int_sdna(prop, NULL, "slurph");
- RNA_def_property_range(prop, -500, 500);
- RNA_def_property_ui_text(prop, "Slurph",
- "Create a delay (in frames) in applying key positions, first vertex goes first");
- RNA_def_property_update(prop, 0, "rna_Key_update_data");
}
void RNA_def_key(BlenderRNA *brna)
diff --git a/source/blender/makesrna/intern/rna_lamp.c b/source/blender/makesrna/intern/rna_lamp.c
index e9861b90956..3cd51f5d66f 100644
--- a/source/blender/makesrna/intern/rna_lamp.c
+++ b/source/blender/makesrna/intern/rna_lamp.c
@@ -30,7 +30,7 @@
#include "BLI_math_base.h"
#include "BLI_math_rotation.h"
-#include "BLF_translation.h"
+#include "BLT_translation.h"
#include "RNA_define.h"
#include "RNA_enum_types.h"
@@ -93,23 +93,21 @@ static int rna_use_shadow_get(PointerRNA *ptr)
{
Lamp *la = (Lamp *)ptr->data;
- if (la->type == LA_SPOT)
- return la->mode & LA_SHAD_BUF;
- else
- return la->mode & LA_SHAD_RAY;
+ if (la->type == LA_SPOT) {
+ return (la->mode & (LA_SHAD_BUF | LA_SHAD_RAY)) != 0;
+ }
+ else {
+ return (la->mode & LA_SHAD_RAY) != 0;
+ }
}
static void rna_use_shadow_set(PointerRNA *ptr, int value)
{
Lamp *la = (Lamp *)ptr->data;
+ la->mode &= ~(LA_SHAD_BUF | LA_SHAD_RAY);
if (value) {
- if (la->type == LA_SPOT)
- la->mode |= LA_SHAD_BUF;
- else
- la->mode |= LA_SHAD_RAY;
+ la->mode |= LA_SHAD_RAY;
}
- else
- la->mode &= ~(LA_SHAD_BUF | LA_SHAD_RAY);
}
static StructRNA *rna_Lamp_refine(struct PointerRNA *ptr)
@@ -351,7 +349,7 @@ static void rna_def_lamp(BlenderRNA *brna)
prop = RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, lamp_type_items);
RNA_def_property_ui_text(prop, "Type", "Type of Lamp");
- RNA_def_property_translation_context(prop, BLF_I18NCONTEXT_ID_LAMP);
+ RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_LAMP);
RNA_def_property_update(prop, 0, "rna_Lamp_draw_update");
prop = RNA_def_property(srna, "distance", PROP_FLOAT, PROP_DISTANCE);
@@ -827,6 +825,12 @@ static void rna_def_sun_lamp(BlenderRNA *brna)
RNA_def_property_ui_range(prop, 0.001, 100.0, 2, 1);
RNA_def_property_ui_text(prop, "Frustum Size", "Size of the frustum used for creating the shadow map");
RNA_def_property_update(prop, 0, "rna_Lamp_draw_update");
+
+ prop = RNA_def_property(srna, "show_shadow_box", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "mode", LA_SHOW_SHADOW_BOX);
+ RNA_def_property_ui_text(prop, "Show Shadow Box",
+ "Draw a box in 3D view to visualize which objects are contained in it");
+ RNA_def_property_update(prop, 0, "rna_Lamp_draw_update");
}
static void rna_def_hemi_lamp(BlenderRNA *brna)
diff --git a/source/blender/makesrna/intern/rna_linestyle.c b/source/blender/makesrna/intern/rna_linestyle.c
index 96b81f12620..fe8f52469be 100644
--- a/source/blender/makesrna/intern/rna_linestyle.c
+++ b/source/blender/makesrna/intern/rna_linestyle.c
@@ -41,26 +41,38 @@
EnumPropertyItem linestyle_color_modifier_type_items[] = {
{LS_MODIFIER_ALONG_STROKE, "ALONG_STROKE", ICON_MODIFIER, "Along Stroke", ""},
+ {LS_MODIFIER_CREASE_ANGLE, "CREASE_ANGLE", ICON_MODIFIER, "Crease Angle", ""},
+ {LS_MODIFIER_CURVATURE_3D, "CURVATURE_3D", ICON_MODIFIER, "Curvature 3D", ""},
{LS_MODIFIER_DISTANCE_FROM_CAMERA, "DISTANCE_FROM_CAMERA", ICON_MODIFIER, "Distance from Camera", ""},
{LS_MODIFIER_DISTANCE_FROM_OBJECT, "DISTANCE_FROM_OBJECT", ICON_MODIFIER, "Distance from Object", ""},
{LS_MODIFIER_MATERIAL, "MATERIAL", ICON_MODIFIER, "Material", ""},
+ {LS_MODIFIER_NOISE, "NOISE", ICON_MODIFIER, "Noise", ""},
+ {LS_MODIFIER_TANGENT, "TANGENT", ICON_MODIFIER, "Tangent", ""},
{0, NULL, 0, NULL, NULL}
};
EnumPropertyItem linestyle_alpha_modifier_type_items[] = {
{LS_MODIFIER_ALONG_STROKE, "ALONG_STROKE", ICON_MODIFIER, "Along Stroke", ""},
+ {LS_MODIFIER_CREASE_ANGLE, "CREASE_ANGLE", ICON_MODIFIER, "Crease Angle", ""},
+ {LS_MODIFIER_CURVATURE_3D, "CURVATURE_3D", ICON_MODIFIER, "Curvature 3D", ""},
{LS_MODIFIER_DISTANCE_FROM_CAMERA, "DISTANCE_FROM_CAMERA", ICON_MODIFIER, "Distance from Camera", ""},
{LS_MODIFIER_DISTANCE_FROM_OBJECT, "DISTANCE_FROM_OBJECT", ICON_MODIFIER, "Distance from Object", ""},
{LS_MODIFIER_MATERIAL, "MATERIAL", ICON_MODIFIER, "Material", ""},
+ {LS_MODIFIER_NOISE, "NOISE", ICON_MODIFIER, "Noise", ""},
+ {LS_MODIFIER_TANGENT, "TANGENT", ICON_MODIFIER, "Tangent", ""},
{0, NULL, 0, NULL, NULL}
};
EnumPropertyItem linestyle_thickness_modifier_type_items[] = {
{LS_MODIFIER_ALONG_STROKE, "ALONG_STROKE", ICON_MODIFIER, "Along Stroke", ""},
{LS_MODIFIER_CALLIGRAPHY, "CALLIGRAPHY", ICON_MODIFIER, "Calligraphy", ""},
+ {LS_MODIFIER_CREASE_ANGLE, "CREASE_ANGLE", ICON_MODIFIER, "Crease Angle", ""},
+ {LS_MODIFIER_CURVATURE_3D, "CURVATURE_3D", ICON_MODIFIER, "Curvature 3D", ""},
{LS_MODIFIER_DISTANCE_FROM_CAMERA, "DISTANCE_FROM_CAMERA", ICON_MODIFIER, "Distance from Camera", ""},
{LS_MODIFIER_DISTANCE_FROM_OBJECT, "DISTANCE_FROM_OBJECT", ICON_MODIFIER, "Distance from Object", ""},
{LS_MODIFIER_MATERIAL, "MATERIAL", ICON_MODIFIER, "Material", ""},
+ {LS_MODIFIER_NOISE, "NOISE", ICON_MODIFIER, "Noise", ""},
+ {LS_MODIFIER_TANGENT, "TANGENT", ICON_MODIFIER, "Tangent", ""},
{0, NULL, 0, NULL, NULL}
};
@@ -75,6 +87,7 @@ EnumPropertyItem linestyle_geometry_modifier_type_items[] = {
{LS_MODIFIER_PERLIN_NOISE_2D, "PERLIN_NOISE_2D", ICON_MODIFIER, "Perlin Noise 2D", ""},
{LS_MODIFIER_POLYGONIZATION, "POLYGONIZATION", ICON_MODIFIER, "Polygonization", ""},
{LS_MODIFIER_SAMPLING, "SAMPLING", ICON_MODIFIER, "Sampling", ""},
+ {LS_MODIFIER_SIMPLIFICATION, "SIMPLIFICATION", ICON_MODIFIER, "Simplification", ""},
{LS_MODIFIER_SINUS_DISPLACEMENT, "SINUS_DISPLACEMENT", ICON_MODIFIER, "Sinus Displacement", ""},
{LS_MODIFIER_SPATIAL_NOISE, "SPATIAL_NOISE", ICON_MODIFIER, "Spatial Noise", ""},
{LS_MODIFIER_TIP_REMOVER, "TIP_REMOVER", ICON_MODIFIER, "Tip Remover", ""},
@@ -104,6 +117,14 @@ static StructRNA *rna_LineStyle_color_modifier_refine(struct PointerRNA *ptr)
return &RNA_LineStyleColorModifier_DistanceFromObject;
case LS_MODIFIER_MATERIAL:
return &RNA_LineStyleColorModifier_Material;
+ case LS_MODIFIER_TANGENT:
+ return &RNA_LineStyleColorModifier_Tangent;
+ case LS_MODIFIER_NOISE:
+ return &RNA_LineStyleColorModifier_Noise;
+ case LS_MODIFIER_CREASE_ANGLE:
+ return &RNA_LineStyleColorModifier_CreaseAngle;
+ case LS_MODIFIER_CURVATURE_3D:
+ return &RNA_LineStyleColorModifier_Curvature_3D;
default:
return &RNA_LineStyleColorModifier;
}
@@ -122,6 +143,14 @@ static StructRNA *rna_LineStyle_alpha_modifier_refine(struct PointerRNA *ptr)
return &RNA_LineStyleAlphaModifier_DistanceFromObject;
case LS_MODIFIER_MATERIAL:
return &RNA_LineStyleAlphaModifier_Material;
+ case LS_MODIFIER_TANGENT:
+ return &RNA_LineStyleAlphaModifier_Tangent;
+ case LS_MODIFIER_NOISE:
+ return &RNA_LineStyleAlphaModifier_Noise;
+ case LS_MODIFIER_CREASE_ANGLE:
+ return &RNA_LineStyleAlphaModifier_CreaseAngle;
+ case LS_MODIFIER_CURVATURE_3D:
+ return &RNA_LineStyleAlphaModifier_Curvature_3D;
default:
return &RNA_LineStyleAlphaModifier;
}
@@ -142,6 +171,14 @@ static StructRNA *rna_LineStyle_thickness_modifier_refine(struct PointerRNA *ptr
return &RNA_LineStyleThicknessModifier_Material;
case LS_MODIFIER_CALLIGRAPHY:
return &RNA_LineStyleThicknessModifier_Calligraphy;
+ case LS_MODIFIER_TANGENT:
+ return &RNA_LineStyleThicknessModifier_Tangent;
+ case LS_MODIFIER_NOISE:
+ return &RNA_LineStyleThicknessModifier_Noise;
+ case LS_MODIFIER_CREASE_ANGLE:
+ return &RNA_LineStyleThicknessModifier_CreaseAngle;
+ case LS_MODIFIER_CURVATURE_3D:
+ return &RNA_LineStyleThicknessModifier_Curvature_3D;
default:
return &RNA_LineStyleThicknessModifier;
}
@@ -178,6 +215,8 @@ static StructRNA *rna_LineStyle_geometry_modifier_refine(struct PointerRNA *ptr)
return &RNA_LineStyleGeometryModifier_2DOffset;
case LS_MODIFIER_2D_TRANSFORM:
return &RNA_LineStyleGeometryModifier_2DTransform;
+ case LS_MODIFIER_SIMPLIFICATION:
+ return &RNA_LineStyleGeometryModifier_Simplification;
default:
return &RNA_LineStyleGeometryModifier;
}
@@ -698,6 +737,7 @@ static void rna_def_modifier_material_common(StructRNA *srna)
{LS_MODIFIER_MATERIAL_LINE_R, "LINE_R", 0, "Line Color Red", ""},
{LS_MODIFIER_MATERIAL_LINE_G, "LINE_G", 0, "Line Color Green", ""},
{LS_MODIFIER_MATERIAL_LINE_B, "LINE_B", 0, "Line Color Blue", ""},
+ {LS_MODIFIER_MATERIAL_LINE_A, "LINE_A", 0, "Line Color Alpha", ""},
{LS_MODIFIER_MATERIAL_DIFF, "DIFF", 0, "Diffuse Color", ""},
{LS_MODIFIER_MATERIAL_DIFF_R, "DIFF_R", 0, "Diffuse Color Red", ""},
{LS_MODIFIER_MATERIAL_DIFF_G, "DIFF_G", 0, "Diffuse Color Green", ""},
@@ -784,6 +824,62 @@ static void rna_def_linestyle_modifiers(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Ramp", "Use color ramp to map the BW average into an RGB color");
RNA_def_property_update(prop, NC_LINESTYLE, "rna_LineStyle_update");
+ srna = RNA_def_struct(brna, "LineStyleColorModifier_Tangent", "LineStyleColorModifier");
+ RNA_def_struct_ui_text(srna, "Tangent", "Change line color based on the direction of a stroke");
+ rna_def_color_modifier(srna);
+ rna_def_modifier_color_ramp_common(srna, false);
+
+ srna = RNA_def_struct(brna, "LineStyleColorModifier_Noise", "LineStyleColorModifier");
+ RNA_def_struct_ui_text(srna, "Noise", "Change line color based on random noise");
+ rna_def_color_modifier(srna);
+ rna_def_modifier_color_ramp_common(srna, false);
+
+ prop = RNA_def_property(srna, "amplitude", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "amplitude");
+ RNA_def_property_ui_text(prop, "Amplitude", "Amplitude of the noise");
+ RNA_def_property_update(prop, NC_LINESTYLE, "rna_LineStyle_update");
+
+ prop = RNA_def_property(srna, "period", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "period");
+ RNA_def_property_ui_text(prop, "Period", "Period of the noise");
+ RNA_def_property_update(prop, NC_LINESTYLE, "rna_LineStyle_update");
+
+ prop = RNA_def_property(srna, "seed", PROP_INT, PROP_NONE);
+ RNA_def_property_int_sdna(prop, NULL, "seed");
+ RNA_def_property_ui_text(prop, "Seed", "Seed for the noise generation");
+ RNA_def_property_update(prop, NC_LINESTYLE, "rna_LineStyle_update");
+
+ srna = RNA_def_struct(brna, "LineStyleColorModifier_CreaseAngle", "LineStyleColorModifier");
+ RNA_def_struct_ui_text(srna, "Crease Angle", "Change line color based on the underlying crease angle");
+ rna_def_color_modifier(srna);
+ rna_def_modifier_color_ramp_common(srna, false);
+
+ prop = RNA_def_property(srna, "angle_min", PROP_FLOAT, PROP_ANGLE);
+ RNA_def_property_float_sdna(prop, NULL, "min_angle");
+ RNA_def_property_ui_text(prop, "Min Angle", "Minimum angle to modify thickness");
+ RNA_def_property_update(prop, NC_LINESTYLE, "rna_LineStyle_update");
+
+ prop = RNA_def_property(srna, "angle_max", PROP_FLOAT, PROP_ANGLE);
+ RNA_def_property_float_sdna(prop, NULL, "max_angle");
+ RNA_def_property_ui_text(prop, "Max Angle", "Maximum angle to modify thickness");
+ RNA_def_property_update(prop, NC_LINESTYLE, "rna_LineStyle_update");
+
+ srna = RNA_def_struct(brna, "LineStyleColorModifier_Curvature_3D", "LineStyleColorModifier");
+ RNA_def_struct_ui_text(srna, "Curvature 3D",
+ "Change line color based on the radial curvature of 3D mesh surfaces");
+ rna_def_color_modifier(srna);
+ rna_def_modifier_color_ramp_common(srna, false);
+
+ prop = RNA_def_property(srna, "curvature_min", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "min_curvature");
+ RNA_def_property_ui_text(prop, "Min Curvature", "Minimum Curvature");
+ RNA_def_property_update(prop, NC_LINESTYLE, "rna_LineStyle_update");
+
+ prop = RNA_def_property(srna, "curvature_max", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "max_curvature");
+ RNA_def_property_ui_text(prop, "Max Curvature", "Maximum Curvature");
+ RNA_def_property_update(prop, NC_LINESTYLE, "rna_LineStyle_update");
+
/* alpha transparency modifiers */
srna = RNA_def_struct(brna, "LineStyleAlphaModifier", "LineStyleModifier");
@@ -822,14 +918,90 @@ static void rna_def_linestyle_modifiers(BlenderRNA *brna)
rna_def_modifier_material_common(srna);
rna_def_modifier_curve_common(srna, false, false);
- /* line thickness modifiers */
+ srna = RNA_def_struct(brna, "LineStyleAlphaModifier_Tangent", "LineStyleAlphaModifier");
+ RNA_def_struct_ui_text(srna, "Tangent", "Alpha transparency based on the direction of the stroke");
+ rna_def_alpha_modifier(srna);
+ rna_def_modifier_curve_common(srna, false, false);
+ srna = RNA_def_struct(brna, "LineStyleAlphaModifier_Noise", "LineStyleAlphaModifier");
+ RNA_def_struct_ui_text(srna, "Noise", "Alpha transparency based on random noise");
+ rna_def_alpha_modifier(srna);
+ rna_def_modifier_curve_common(srna, false, false);
+
+ prop = RNA_def_property(srna, "amplitude", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "amplitude");
+ RNA_def_property_ui_text(prop, "Amplitude", "Amplitude of the noise");
+ RNA_def_property_update(prop, NC_LINESTYLE, "rna_LineStyle_update");
+
+ prop = RNA_def_property(srna, "period", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "period");
+ RNA_def_property_ui_text(prop, "Period", "Period of the noise");
+ RNA_def_property_update(prop, NC_LINESTYLE, "rna_LineStyle_update");
+
+ prop = RNA_def_property(srna, "seed", PROP_INT, PROP_NONE);
+ RNA_def_property_int_sdna(prop, NULL, "seed");
+ RNA_def_property_ui_text(prop, "Seed", "Seed for the noise generation");
+ RNA_def_property_update(prop, NC_LINESTYLE, "rna_LineStyle_update");
+
+ srna = RNA_def_struct(brna, "LineStyleAlphaModifier_CreaseAngle", "LineStyleAlphaModifier");
+ RNA_def_struct_ui_text(srna, "Crease Angle",
+ "Alpha transparency based on the angle between two adjacent faces");
+ rna_def_alpha_modifier(srna);
+ rna_def_modifier_curve_common(srna, false, false);
+
+ prop = RNA_def_property(srna, "angle_min", PROP_FLOAT, PROP_ANGLE);
+ RNA_def_property_float_sdna(prop, NULL, "min_angle");
+ RNA_def_property_ui_text(prop, "Min Angle", "Minimum angle to modify thickness");
+ RNA_def_property_update(prop, NC_LINESTYLE, "rna_LineStyle_update");
+
+ prop = RNA_def_property(srna, "angle_max", PROP_FLOAT, PROP_ANGLE);
+ RNA_def_property_float_sdna(prop, NULL, "max_angle");
+ RNA_def_property_ui_text(prop, "Max Angle", "Maximum angle to modify thickness");
+ RNA_def_property_update(prop, NC_LINESTYLE, "rna_LineStyle_update");
+
+ srna = RNA_def_struct(brna, "LineStyleAlphaModifier_Curvature_3D", "LineStyleAlphaModifier");
+ RNA_def_struct_ui_text(srna, "Curvature 3D",
+ "Alpha transparency based on the radial curvature of 3D mesh surfaces");
+ rna_def_alpha_modifier(srna);
+ rna_def_modifier_curve_common(srna, false, false);
+
+ prop = RNA_def_property(srna, "curvature_min", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "min_curvature");
+ RNA_def_property_range(prop, 0.0f, 10000.0f);
+ RNA_def_property_ui_text(prop, "Min Curvature", "Minimum Curvature");
+ RNA_def_property_update(prop, NC_LINESTYLE, "rna_LineStyle_update");
+
+ prop = RNA_def_property(srna, "curvature_max", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "max_curvature");
+ RNA_def_property_range(prop, 0.0f, 10000.0f);
+ RNA_def_property_ui_text(prop, "Max Curvature", "Maximum Curvature");
+ RNA_def_property_update(prop, NC_LINESTYLE, "rna_LineStyle_update");
+
+ /* line thickness modifiers */
srna = RNA_def_struct(brna, "LineStyleThicknessModifier", "LineStyleModifier");
RNA_def_struct_sdna(srna, "LineStyleModifier");
RNA_def_struct_refine_func(srna, "rna_LineStyle_thickness_modifier_refine");
RNA_def_struct_path_func(srna, "rna_LineStyle_thickness_modifier_path");
RNA_def_struct_ui_text(srna, "Line Style Thickness Modifier", "Base type to define line thickness modifiers");
+ srna = RNA_def_struct(brna, "LineStyleThicknessModifier_Tangent", "LineStyleThicknessModifier");
+ RNA_def_struct_ui_text(srna, "Tangent", "Thickness based on the direction of the stroke");
+ rna_def_thickness_modifier(srna);
+ rna_def_modifier_curve_common(srna, false, false);
+
+ prop = RNA_def_property(srna, "thickness_min", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "min_thickness");
+ RNA_def_property_range(prop, 0.0f, 10000.0f);
+ RNA_def_property_ui_text(prop, "Min Thickness",
+ "Minimum thickness");
+ RNA_def_property_update(prop, NC_LINESTYLE, "rna_LineStyle_update");
+
+ prop = RNA_def_property(srna, "thickness_max", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "max_thickness");
+ RNA_def_property_range(prop, 0.0f, 10000.0f);
+ RNA_def_property_ui_text(prop, "Max Thickness", "Maximum thickness");
+ RNA_def_property_update(prop, NC_LINESTYLE, "rna_LineStyle_update");
+
srna = RNA_def_struct(brna, "LineStyleThicknessModifier_AlongStroke", "LineStyleThicknessModifier");
RNA_def_struct_ui_text(srna, "Along Stroke", "Change line thickness along stroke");
rna_def_thickness_modifier(srna);
@@ -881,6 +1053,88 @@ static void rna_def_linestyle_modifiers(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Max Thickness", "Maximum thickness in the main direction");
RNA_def_property_update(prop, NC_LINESTYLE, "rna_LineStyle_update");
+ srna = RNA_def_struct(brna, "LineStyleThicknessModifier_Noise", "LineStyleThicknessModifier");
+ RNA_def_struct_ui_text(srna, "Noise", "Line thickness based on random noise");
+ rna_def_thickness_modifier(srna);
+
+ prop = RNA_def_property(srna, "amplitude", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "amplitude");
+ RNA_def_property_ui_text(prop, "Amplitude", "Amplitude of the noise");
+ RNA_def_property_update(prop, NC_LINESTYLE, "rna_LineStyle_update");
+
+ prop = RNA_def_property(srna, "period", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "period");
+ RNA_def_property_ui_text(prop, "Period", "Period of the noise");
+ RNA_def_property_update(prop, NC_LINESTYLE, "rna_LineStyle_update");
+
+ prop = RNA_def_property(srna, "seed", PROP_INT, PROP_NONE);
+ RNA_def_property_int_sdna(prop, NULL, "seed");
+ RNA_def_property_ui_text(prop, "Seed", "Seed for the noise generation");
+ RNA_def_property_update(prop, NC_LINESTYLE, "rna_LineStyle_update");
+
+ prop = RNA_def_property(srna, "use_asymmetric", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flags", LS_THICKNESS_ASYMMETRIC);
+ RNA_def_property_ui_text(prop, "Asymmetric", "Allow thickness to be assigned asymmetrically");
+ RNA_def_property_update(prop, NC_LINESTYLE, "rna_LineStyle_update");
+
+ srna = RNA_def_struct(brna, "LineStyleThicknessModifier_Curvature_3D", "LineStyleThicknessModifier");
+ RNA_def_struct_ui_text(srna, "Curvature 3D",
+ "Line thickness based on the radial curvature of 3D mesh surfaces");
+ rna_def_thickness_modifier(srna);
+ rna_def_modifier_curve_common(srna, false, false);
+
+ prop = RNA_def_property(srna, "thickness_min", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "min_thickness");
+ RNA_def_property_range(prop, 0.0f, 10000.0f);
+ RNA_def_property_ui_text(prop, "Min Thickness", "Minimum thickness");
+ RNA_def_property_update(prop, NC_LINESTYLE, "rna_LineStyle_update");
+
+ prop = RNA_def_property(srna, "thickness_max", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "max_thickness");
+ RNA_def_property_range(prop, 0.0f, 10000.0f);
+ RNA_def_property_ui_text(prop, "Max Thickness", "Maximum thickness");
+ RNA_def_property_update(prop, NC_LINESTYLE, "rna_LineStyle_update");
+
+ prop = RNA_def_property(srna, "curvature_min", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "min_curvature");
+ RNA_def_property_range(prop, 0.0f, 10000.0f);
+ RNA_def_property_ui_text(prop, "Min Curvature", "Minimum Curvature");
+ RNA_def_property_update(prop, NC_LINESTYLE, "rna_LineStyle_update");
+
+ prop = RNA_def_property(srna, "curvature_max", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "max_curvature");
+ RNA_def_property_range(prop, 0.0f, 10000.0f);
+ RNA_def_property_ui_text(prop, "Max Curvature", "Maximum Curvature");
+ RNA_def_property_update(prop, NC_LINESTYLE, "rna_LineStyle_update");
+
+ srna = RNA_def_struct(brna, "LineStyleThicknessModifier_CreaseAngle", "LineStyleThicknessModifier");
+ RNA_def_struct_ui_text(srna, "Crease Angle",
+ "Line thickness based on the angle between two adjacent faces");
+ rna_def_thickness_modifier(srna);
+ rna_def_modifier_curve_common(srna, false, false);
+
+ prop = RNA_def_property(srna, "angle_min", PROP_FLOAT, PROP_ANGLE);
+ RNA_def_property_float_sdna(prop, NULL, "min_angle");
+ RNA_def_property_ui_text(prop, "Min Angle", "Minimum angle to modify thickness");
+ RNA_def_property_update(prop, NC_LINESTYLE, "rna_LineStyle_update");
+
+ prop = RNA_def_property(srna, "angle_max", PROP_FLOAT, PROP_ANGLE);
+ RNA_def_property_float_sdna(prop, NULL, "max_angle");
+ RNA_def_property_ui_text(prop, "Max Angle", "Maximum angle to modify thickness");
+ RNA_def_property_update(prop, NC_LINESTYLE, "rna_LineStyle_update");
+
+ prop = RNA_def_property(srna, "thickness_min", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "min_thickness");
+ RNA_def_property_range(prop, 0.0f, 10000.0f);
+ RNA_def_property_ui_text(prop, "Min Thickness", "Minimum thickness");
+ RNA_def_property_update(prop, NC_LINESTYLE, "rna_LineStyle_update");
+
+ prop = RNA_def_property(srna, "thickness_max", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "max_thickness");
+ RNA_def_property_range(prop, 0.0f, 10000.0f);
+ RNA_def_property_ui_text(prop, "Max Thickness", "Maximum thickness");
+ RNA_def_property_update(prop, NC_LINESTYLE, "rna_LineStyle_update");
+
/* geometry modifiers */
srna = RNA_def_struct(brna, "LineStyleGeometryModifier", "LineStyleModifier");
@@ -1166,6 +1420,15 @@ static void rna_def_linestyle_modifiers(BlenderRNA *brna)
RNA_def_property_float_sdna(prop, NULL, "pivot_y");
RNA_def_property_ui_text(prop, "Pivot Y", "2D Y coordinate of the absolute pivot");
RNA_def_property_update(prop, NC_LINESTYLE, "rna_LineStyle_update");
+
+ srna = RNA_def_struct(brna, "LineStyleGeometryModifier_Simplification", "LineStyleGeometryModifier");
+ RNA_def_struct_ui_text(srna, "Simplification", "Simplify the stroke set");
+ rna_def_geometry_modifier(srna);
+
+ prop = RNA_def_property(srna, "tolerance", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "tolerance");
+ RNA_def_property_ui_text(prop, "Tolerance", "Distance below which segments will be merged");
+ RNA_def_property_update(prop, NC_LINESTYLE, "rna_LineStyle_update");
}
static void rna_def_freestyle_color_modifiers(BlenderRNA *brna, PropertyRNA *cprop)
@@ -1322,6 +1585,8 @@ static void rna_def_linestyle(BlenderRNA *brna)
static EnumPropertyItem sort_key_items[] = {
{LS_SORT_KEY_DISTANCE_FROM_CAMERA, "DISTANCE_FROM_CAMERA", 0, "Distance from Camera", "Sort by distance from camera (closer lines lie on top of further lines)"},
{LS_SORT_KEY_2D_LENGTH, "2D_LENGTH", 0, "2D Length", "Sort by curvilinear 2D length (longer lines lie on top of shorter lines)"},
+ {LS_SORT_KEY_PROJECTED_X, "PROJECTED_X", 0, "Projected X", "Sort by the projected X value in the image coordinate system"},
+ {LS_SORT_KEY_PROJECTED_Y, "PROJECTED_Y", 0, "Projected Y", "Sort by the projected Y value in the image coordinate system"},
{0, NULL, 0, NULL, NULL}
};
static EnumPropertyItem sort_order_items[] = {
@@ -1488,6 +1753,16 @@ static void rna_def_linestyle(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Max 2D Length", "Maximum curvilinear 2D length for the selection of chains");
RNA_def_property_update(prop, NC_LINESTYLE, "rna_LineStyle_update");
+ prop = RNA_def_property(srna, "use_chain_count", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", LS_CHAIN_COUNT);
+ RNA_def_property_ui_text(prop, "Use Chain Count", "Enable the selection of first N chains");
+ RNA_def_property_update(prop, NC_LINESTYLE, "rna_LineStyle_update");
+
+ prop = RNA_def_property(srna, "chain_count", PROP_INT, PROP_UNSIGNED);
+ RNA_def_property_int_sdna(prop, NULL, "chain_count");
+ RNA_def_property_ui_text(prop, "Chain Count", "Chain count for the selection of first N chains");
+ RNA_def_property_update(prop, NC_LINESTYLE, "rna_LineStyle_update");
+
prop = RNA_def_property(srna, "use_split_pattern", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", LS_SPLIT_PATTERN);
RNA_def_property_ui_text(prop, "Use Split Pattern", "Enable chain splitting by dashed line patterns");
diff --git a/source/blender/makesrna/intern/rna_main.c b/source/blender/makesrna/intern/rna_main.c
index 65d81359045..348fa3c8302 100644
--- a/source/blender/makesrna/intern/rna_main.c
+++ b/source/blender/makesrna/intern/rna_main.c
@@ -251,6 +251,12 @@ static void rna_Main_particle_begin(CollectionPropertyIterator *iter, PointerRNA
rna_iterator_listbase_begin(iter, &bmain->particle, NULL);
}
+static void rna_Main_palettes_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
+{
+ Main *bmain = (Main *)ptr->data;
+ rna_iterator_listbase_begin(iter, &bmain->palettes, NULL);
+}
+
static void rna_Main_gpencil_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
{
Main *bmain = (Main *)ptr->data;
@@ -350,6 +356,7 @@ void RNA_def_main(BlenderRNA *brna)
{"armatures", "Armature", "rna_Main_armature_begin", "Armatures", "Armature datablocks", RNA_def_main_armatures},
{"actions", "Action", "rna_Main_action_begin", "Actions", "Action datablocks", RNA_def_main_actions},
{"particles", "ParticleSettings", "rna_Main_particle_begin", "Particles", "Particle datablocks", RNA_def_main_particles},
+ {"palettes", "Palette", "rna_Main_palettes_begin", "Palettes", "Palette datablocks", RNA_def_main_palettes},
{"grease_pencil", "GreasePencil", "rna_Main_gpencil_begin", "Grease Pencil", "Grease Pencil datablocks", RNA_def_main_gpencil},
{"movieclips", "MovieClip", "rna_Main_movieclips_begin", "Movie Clips", "Movie Clip datablocks", RNA_def_main_movieclips},
{"masks", "Mask", "rna_Main_masks_begin", "Masks", "Masks datablocks", RNA_def_main_masks},
diff --git a/source/blender/makesrna/intern/rna_main_api.c b/source/blender/makesrna/intern/rna_main_api.c
index b4c332be373..b38f4fa67b6 100644
--- a/source/blender/makesrna/intern/rna_main_api.c
+++ b/source/blender/makesrna/intern/rna_main_api.c
@@ -35,6 +35,8 @@
#include "DNA_ID.h"
#include "DNA_modifier_types.h"
+#include "DNA_space_types.h"
+#include "DNA_object_types.h"
#include "BLI_utildefines.h"
#include "BLI_path_util.h"
@@ -58,9 +60,11 @@
#include "BKE_library.h"
#include "BKE_object.h"
#include "BKE_material.h"
+#include "BKE_icons.h"
#include "BKE_image.h"
#include "BKE_texture.h"
#include "BKE_scene.h"
+#include "BKE_sound.h"
#include "BKE_text.h"
#include "BKE_action.h"
#include "BKE_group.h"
@@ -69,6 +73,7 @@
#include "BKE_mball.h"
#include "BKE_world.h"
#include "BKE_particle.h"
+#include "BKE_paint.h"
#include "BKE_font.h"
#include "BKE_node.h"
#include "BKE_depsgraph.h"
@@ -84,8 +89,8 @@
#include "DNA_lamp_types.h"
#include "DNA_material_types.h"
#include "DNA_mesh_types.h"
-#include "DNA_object_types.h"
#include "DNA_speaker_types.h"
+#include "DNA_sound_types.h"
#include "DNA_text_types.h"
#include "DNA_texture_types.h"
#include "DNA_group_types.h"
@@ -102,7 +107,7 @@
#include "ED_screen.h"
-#include "BLF_translation.h"
+#include "BLT_translation.h"
#ifdef WITH_PYTHON
# include "BPY_extern.h"
@@ -340,10 +345,10 @@ static void rna_Main_lamps_remove(Main *bmain, ReportList *reports, PointerRNA *
}
}
-static Image *rna_Main_images_new(Main *bmain, const char *name, int width, int height, int alpha, int float_buffer)
+static Image *rna_Main_images_new(Main *bmain, const char *name, int width, int height, int alpha, int float_buffer, int stereo3d)
{
float color[4] = {0.0, 0.0, 0.0, 1.0};
- Image *image = BKE_image_add_generated(bmain, width, height, name, alpha ? 32 : 24, float_buffer, 0, color);
+ Image *image = BKE_image_add_generated(bmain, width, height, name, alpha ? 32 : 24, float_buffer, 0, color, stereo3d);
id_us_min(&image->id);
return image;
}
@@ -460,8 +465,8 @@ static void rna_Main_fonts_remove(Main *bmain, ReportList *reports, PointerRNA *
static Tex *rna_Main_textures_new(Main *bmain, const char *name, int type)
{
- Tex *tex = add_texture(bmain, name);
- tex_set_type(tex, type);
+ Tex *tex = BKE_texture_add(bmain, name);
+ BKE_texture_type_set(tex, type);
id_us_min(&tex->id);
return tex;
}
@@ -478,12 +483,13 @@ static void rna_Main_textures_remove(Main *bmain, ReportList *reports, PointerRN
}
}
-static Brush *rna_Main_brushes_new(Main *bmain, const char *name)
+static Brush *rna_Main_brushes_new(Main *bmain, const char *name, int mode)
{
- Brush *brush = BKE_brush_add(bmain, name);
+ Brush *brush = BKE_brush_add(bmain, name, mode);
id_us_min(&brush->id);
return brush;
}
+
static void rna_Main_brushes_remove(Main *bmain, ReportList *reports, PointerRNA *brush_ptr)
{
Brush *brush = brush_ptr->data;
@@ -547,6 +553,25 @@ static void rna_Main_speakers_remove(Main *bmain, ReportList *reports, PointerRN
}
}
+static bSound *rna_Main_sounds_load(Main *bmain, const char *name)
+{
+ bSound *sound = BKE_sound_new_file(bmain, name);
+ id_us_min(&sound->id);
+ return sound;
+}
+static void rna_Main_sounds_remove(Main *bmain, ReportList *reports, PointerRNA *sound_ptr)
+{
+ Speaker *sound = sound_ptr->data;
+ if (ID_REAL_USERS(sound) <= 0) {
+ BKE_libblock_free(bmain, sound);
+ RNA_POINTER_INVALIDATE(sound_ptr);
+ }
+ else {
+ BKE_reportf(reports, RPT_ERROR, "Sound '%s' must have zero users to be removed, found %d",
+ sound->id.name + 2, ID_REAL_USERS(sound));
+ }
+}
+
static Text *rna_Main_texts_new(Main *bmain, const char *name)
{
return BKE_text_add(bmain, name);
@@ -631,6 +656,25 @@ static void rna_Main_particles_remove(Main *bmain, ReportList *reports, PointerR
}
}
+static Palette *rna_Main_palettes_new(Main *bmain, const char *name)
+{
+ Palette *palette = BKE_palette_add(bmain, name);
+ id_us_min(&palette->id);
+ return (Palette *)palette;
+}
+static void rna_Main_palettes_remove(Main *bmain, ReportList *reports, PointerRNA *palette_ptr)
+{
+ Palette *palette = palette_ptr->data;
+ if (ID_REAL_USERS(palette) <= 0) {
+ BKE_libblock_free(bmain, palette);
+ RNA_POINTER_INVALIDATE(palette_ptr);
+ }
+ else {
+ BKE_reportf(reports, RPT_ERROR, "Palette settings '%s' must have zero users to be removed, found %d",
+ palette->id.name + 2, ID_REAL_USERS(palette));
+ }
+}
+
static MovieClip *rna_Main_movieclip_load(Main *bmain, ReportList *reports, const char *filepath)
{
MovieClip *clip;
@@ -685,7 +729,7 @@ static void rna_Main_grease_pencil_remove(Main *bmain, ReportList *reports, Poin
static FreestyleLineStyle *rna_Main_linestyles_new(Main *bmain, const char *name)
{
- FreestyleLineStyle *linestyle = BKE_linestyle_new(name, bmain);
+ FreestyleLineStyle *linestyle = BKE_linestyle_new(bmain, name);
id_us_min(&linestyle->id);
return linestyle;
}
@@ -729,46 +773,49 @@ static void rna_Main_sounds_tag(Main *bmain, int value) { BKE_main_id_tag_listba
static void rna_Main_armatures_tag(Main *bmain, int value) { BKE_main_id_tag_listbase(&bmain->armature, value); }
static void rna_Main_actions_tag(Main *bmain, int value) { BKE_main_id_tag_listbase(&bmain->action, value); }
static void rna_Main_particles_tag(Main *bmain, int value) { BKE_main_id_tag_listbase(&bmain->particle, value); }
+static void rna_Main_palettes_tag(Main *bmain, int value) { BKE_main_id_tag_listbase(&bmain->palettes, value); }
static void rna_Main_gpencil_tag(Main *bmain, int value) { BKE_main_id_tag_listbase(&bmain->gpencil, value); }
static void rna_Main_movieclips_tag(Main *bmain, int value) { BKE_main_id_tag_listbase(&bmain->movieclip, value); }
static void rna_Main_masks_tag(Main *bmain, int value) { BKE_main_id_tag_listbase(&bmain->mask, value); }
static void rna_Main_linestyle_tag(Main *bmain, int value) { BKE_main_id_tag_listbase(&bmain->linestyle, value); }
-static int rna_Main_cameras_is_updated_get(PointerRNA *ptr) { return DAG_id_type_tagged(ptr->data, ID_CA); }
-static int rna_Main_scenes_is_updated_get(PointerRNA *ptr) { return DAG_id_type_tagged(ptr->data, ID_SCE); }
-static int rna_Main_objects_is_updated_get(PointerRNA *ptr) { return DAG_id_type_tagged(ptr->data, ID_OB); }
-static int rna_Main_materials_is_updated_get(PointerRNA *ptr) { return DAG_id_type_tagged(ptr->data, ID_MA); }
-static int rna_Main_node_groups_is_updated_get(PointerRNA *ptr) { return DAG_id_type_tagged(ptr->data, ID_NT); }
-static int rna_Main_meshes_is_updated_get(PointerRNA *ptr) { return DAG_id_type_tagged(ptr->data, ID_ME); }
-static int rna_Main_lamps_is_updated_get(PointerRNA *ptr) { return DAG_id_type_tagged(ptr->data, ID_LA); }
-static int rna_Main_libraries_is_updated_get(PointerRNA *ptr) { return DAG_id_type_tagged(ptr->data, ID_LI); }
-static int rna_Main_screens_is_updated_get(PointerRNA *ptr) { return DAG_id_type_tagged(ptr->data, ID_SCR); }
-static int rna_Main_window_managers_is_updated_get(PointerRNA *ptr) { return DAG_id_type_tagged(ptr->data, ID_WM); }
-static int rna_Main_images_is_updated_get(PointerRNA *ptr) { return DAG_id_type_tagged(ptr->data, ID_IM); }
-static int rna_Main_lattices_is_updated_get(PointerRNA *ptr) { return DAG_id_type_tagged(ptr->data, ID_LT); }
-static int rna_Main_curves_is_updated_get(PointerRNA *ptr) { return DAG_id_type_tagged(ptr->data, ID_CU); }
-static int rna_Main_metaballs_is_updated_get(PointerRNA *ptr) { return DAG_id_type_tagged(ptr->data, ID_MB); }
-static int rna_Main_fonts_is_updated_get(PointerRNA *ptr) { return DAG_id_type_tagged(ptr->data, ID_VF); }
-static int rna_Main_textures_is_updated_get(PointerRNA *ptr) { return DAG_id_type_tagged(ptr->data, ID_TE); }
-static int rna_Main_brushes_is_updated_get(PointerRNA *ptr) { return DAG_id_type_tagged(ptr->data, ID_BR); }
-static int rna_Main_worlds_is_updated_get(PointerRNA *ptr) { return DAG_id_type_tagged(ptr->data, ID_WO); }
-static int rna_Main_groups_is_updated_get(PointerRNA *ptr) { return DAG_id_type_tagged(ptr->data, ID_GR); }
-static int rna_Main_texts_is_updated_get(PointerRNA *ptr) { return DAG_id_type_tagged(ptr->data, ID_TXT); }
-static int rna_Main_speakers_is_updated_get(PointerRNA *ptr) { return DAG_id_type_tagged(ptr->data, ID_SPK); }
-static int rna_Main_sounds_is_updated_get(PointerRNA *ptr) { return DAG_id_type_tagged(ptr->data, ID_SO); }
-static int rna_Main_armatures_is_updated_get(PointerRNA *ptr) { return DAG_id_type_tagged(ptr->data, ID_AR); }
-static int rna_Main_actions_is_updated_get(PointerRNA *ptr) { return DAG_id_type_tagged(ptr->data, ID_AC); }
-static int rna_Main_particles_is_updated_get(PointerRNA *ptr) { return DAG_id_type_tagged(ptr->data, ID_PA); }
-static int rna_Main_gpencil_is_updated_get(PointerRNA *ptr) { return DAG_id_type_tagged(ptr->data, ID_GD); }
-static int rna_Main_linestyle_is_updated_get(PointerRNA *ptr) { return DAG_id_type_tagged(ptr->data, ID_LS); }
+static int rna_Main_cameras_is_updated_get(PointerRNA *ptr) { return DAG_id_type_tagged(ptr->data, ID_CA) != 0; }
+static int rna_Main_scenes_is_updated_get(PointerRNA *ptr) { return DAG_id_type_tagged(ptr->data, ID_SCE) != 0; }
+static int rna_Main_objects_is_updated_get(PointerRNA *ptr) { return DAG_id_type_tagged(ptr->data, ID_OB) != 0; }
+static int rna_Main_materials_is_updated_get(PointerRNA *ptr) { return DAG_id_type_tagged(ptr->data, ID_MA) != 0; }
+static int rna_Main_node_groups_is_updated_get(PointerRNA *ptr) { return DAG_id_type_tagged(ptr->data, ID_NT) != 0; }
+static int rna_Main_meshes_is_updated_get(PointerRNA *ptr) { return DAG_id_type_tagged(ptr->data, ID_ME) != 0; }
+static int rna_Main_lamps_is_updated_get(PointerRNA *ptr) { return DAG_id_type_tagged(ptr->data, ID_LA) != 0; }
+static int rna_Main_libraries_is_updated_get(PointerRNA *ptr) { return DAG_id_type_tagged(ptr->data, ID_LI) != 0; }
+static int rna_Main_screens_is_updated_get(PointerRNA *ptr) { return DAG_id_type_tagged(ptr->data, ID_SCR) != 0; }
+static int rna_Main_window_managers_is_updated_get(PointerRNA *ptr) { return DAG_id_type_tagged(ptr->data, ID_WM) != 0; }
+static int rna_Main_images_is_updated_get(PointerRNA *ptr) { return DAG_id_type_tagged(ptr->data, ID_IM) != 0; }
+static int rna_Main_lattices_is_updated_get(PointerRNA *ptr) { return DAG_id_type_tagged(ptr->data, ID_LT) != 0; }
+static int rna_Main_curves_is_updated_get(PointerRNA *ptr) { return DAG_id_type_tagged(ptr->data, ID_CU) != 0; }
+static int rna_Main_metaballs_is_updated_get(PointerRNA *ptr) { return DAG_id_type_tagged(ptr->data, ID_MB) != 0; }
+static int rna_Main_fonts_is_updated_get(PointerRNA *ptr) { return DAG_id_type_tagged(ptr->data, ID_VF) != 0; }
+static int rna_Main_textures_is_updated_get(PointerRNA *ptr) { return DAG_id_type_tagged(ptr->data, ID_TE) != 0; }
+static int rna_Main_brushes_is_updated_get(PointerRNA *ptr) { return DAG_id_type_tagged(ptr->data, ID_BR) != 0; }
+static int rna_Main_worlds_is_updated_get(PointerRNA *ptr) { return DAG_id_type_tagged(ptr->data, ID_WO) != 0; }
+static int rna_Main_groups_is_updated_get(PointerRNA *ptr) { return DAG_id_type_tagged(ptr->data, ID_GR) != 0; }
+static int rna_Main_texts_is_updated_get(PointerRNA *ptr) { return DAG_id_type_tagged(ptr->data, ID_TXT) != 0; }
+static int rna_Main_speakers_is_updated_get(PointerRNA *ptr) { return DAG_id_type_tagged(ptr->data, ID_SPK) != 0; }
+static int rna_Main_sounds_is_updated_get(PointerRNA *ptr) { return DAG_id_type_tagged(ptr->data, ID_SO) != 0; }
+static int rna_Main_armatures_is_updated_get(PointerRNA *ptr) { return DAG_id_type_tagged(ptr->data, ID_AR) != 0; }
+static int rna_Main_actions_is_updated_get(PointerRNA *ptr) { return DAG_id_type_tagged(ptr->data, ID_AC) != 0; }
+static int rna_Main_particles_is_updated_get(PointerRNA *ptr) { return DAG_id_type_tagged(ptr->data, ID_PA) != 0; }
+static int rna_Main_palettes_is_updated_get(PointerRNA *ptr) { return DAG_id_type_tagged(ptr->data, ID_PAL) != 0; }
+static int rna_Main_gpencil_is_updated_get(PointerRNA *ptr) { return DAG_id_type_tagged(ptr->data, ID_GD) != 0; }
+static int rna_Main_linestyle_is_updated_get(PointerRNA *ptr) { return DAG_id_type_tagged(ptr->data, ID_LS) != 0; }
#else
-void RNA_api_main(StructRNA *srna)
+void RNA_api_main(StructRNA *UNUSED(srna))
{
#if 0
FunctionRNA *func;
PropertyRNA *parm;
+
/* maybe we want to add functions in 'bpy.data' still?
* for now they are all in collections bpy.data.images.new(...) */
func = RNA_def_function(srna, "add_image", "rna_Main_add_image");
@@ -777,8 +824,6 @@ void RNA_api_main(StructRNA *srna)
RNA_def_property_flag(parm, PROP_REQUIRED);
parm = RNA_def_pointer(func, "image", "Image", "", "New image");
RNA_def_function_return(func, parm);
-#else
- (void)srna;
#endif
}
@@ -1152,6 +1197,7 @@ void RNA_def_main_images(BlenderRNA *brna, PropertyRNA *cprop)
RNA_def_property_flag(parm, PROP_REQUIRED);
RNA_def_boolean(func, "alpha", 0, "Alpha", "Use alpha channel");
RNA_def_boolean(func, "float_buffer", 0, "Float Buffer", "Create an image with floating point color");
+ RNA_def_boolean(func, "stereo3d", 0, "Stereo 3D", "Create left and right views");
/* return type */
parm = RNA_def_pointer(func, "image", "Image", "", "New image datablock");
RNA_def_function_return(func, parm);
@@ -1377,6 +1423,7 @@ void RNA_def_main_brushes(BlenderRNA *brna, PropertyRNA *cprop)
RNA_def_function_ui_description(func, "Add a new brush to the main database");
parm = RNA_def_string(func, "name", "Brush", 0, "", "New name for the datablock");
RNA_def_property_flag(parm, PROP_REQUIRED);
+ parm = RNA_def_enum(func, "mode", object_mode_items, OB_MODE_TEXTURE_PAINT, "", "Paint Mode for the new brush");
/* return type */
parm = RNA_def_pointer(func, "brush", "Brush", "", "New brush datablock");
RNA_def_function_return(func, parm);
@@ -1562,7 +1609,21 @@ void RNA_def_main_sounds(BlenderRNA *brna, PropertyRNA *cprop)
RNA_def_struct_sdna(srna, "Main");
RNA_def_struct_ui_text(srna, "Main Sounds", "Collection of sounds");
- /* TODO, 'load' */
+ /* load func */
+ func = RNA_def_function(srna, "load", "rna_Main_sounds_load");
+ RNA_def_function_ui_description(func, "Add a new sound to the main database from a file");
+ parm = RNA_def_string_file_path(func, "filepath", "Path", FILE_MAX, "", "path for the datablock");
+ RNA_def_property_flag(parm, PROP_REQUIRED);
+ /* return type */
+ parm = RNA_def_pointer(func, "sound", "Sound", "", "New text datablock");
+ RNA_def_function_return(func, parm);
+
+ func = RNA_def_function(srna, "remove", "rna_Main_sounds_remove");
+ RNA_def_function_flag(func, FUNC_USE_REPORTS);
+ RNA_def_function_ui_description(func, "Remove a sound from the current blendfile");
+ parm = RNA_def_pointer(func, "sound", "Sound", "", "Sound to remove");
+ RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL | PROP_RNAPTR);
+ RNA_def_property_clear_flag(parm, PROP_THICK_WRAP);
func = RNA_def_function(srna, "tag", "rna_Main_sounds_tag");
parm = RNA_def_boolean(func, "value", 0, "Value", "");
@@ -1678,7 +1739,41 @@ void RNA_def_main_particles(BlenderRNA *brna, PropertyRNA *cprop)
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_boolean_funcs(prop, "rna_Main_particles_is_updated_get", NULL);
}
+void RNA_def_main_palettes(BlenderRNA *brna, PropertyRNA *cprop)
+{
+ StructRNA *srna;
+ FunctionRNA *func;
+ PropertyRNA *parm;
+ PropertyRNA *prop;
+
+ RNA_def_property_srna(cprop, "BlendDataPalettes");
+ srna = RNA_def_struct(brna, "BlendDataPalettes", NULL);
+ RNA_def_struct_sdna(srna, "Main");
+ RNA_def_struct_ui_text(srna, "Main Palettes", "Collection of palettes");
+ func = RNA_def_function(srna, "new", "rna_Main_palettes_new");
+ RNA_def_function_ui_description(func, "Add a new palette to the main database");
+ parm = RNA_def_string(func, "name", "Palette", 0, "", "New name for the datablock");
+ RNA_def_property_flag(parm, PROP_REQUIRED);
+ /* return type */
+ parm = RNA_def_pointer(func, "palette", "Palette", "", "New palette datablock");
+ RNA_def_function_return(func, parm);
+
+ func = RNA_def_function(srna, "remove", "rna_Main_palettes_remove");
+ RNA_def_function_flag(func, FUNC_USE_REPORTS);
+ RNA_def_function_ui_description(func, "Remove a palette from the current blendfile");
+ parm = RNA_def_pointer(func, "palette", "Palette", "", "Palette to remove");
+ RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL | PROP_RNAPTR);
+ RNA_def_property_clear_flag(parm, PROP_THICK_WRAP);
+
+ func = RNA_def_function(srna, "tag", "rna_Main_palettes_tag");
+ parm = RNA_def_boolean(func, "value", 0, "Value", "");
+ RNA_def_property_flag(parm, PROP_REQUIRED);
+
+ prop = RNA_def_property(srna, "is_updated", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_property_boolean_funcs(prop, "rna_Main_palettes_is_updated_get", NULL);
+}
void RNA_def_main_gpencil(BlenderRNA *brna, PropertyRNA *cprop)
{
StructRNA *srna;
diff --git a/source/blender/makesrna/intern/rna_mask.c b/source/blender/makesrna/intern/rna_mask.c
index afd149a755a..1a8cea143a1 100644
--- a/source/blender/makesrna/intern/rna_mask.c
+++ b/source/blender/makesrna/intern/rna_mask.c
@@ -35,7 +35,7 @@
#include "DNA_object_types.h" /* SELECT */
#include "DNA_scene_types.h"
-#include "BLF_translation.h"
+#include "BLT_translation.h"
#include "BKE_movieclip.h"
#include "BKE_tracking.h"
@@ -52,12 +52,10 @@
#ifdef RNA_RUNTIME
-#include "DNA_mask_types.h"
#include "DNA_movieclip_types.h"
#include "BKE_depsgraph.h"
#include "BKE_mask.h"
-#include "BKE_tracking.h"
#include "BLI_math.h"
@@ -213,10 +211,13 @@ static void rna_MaskLayer_name_set(PointerRNA *ptr, const char *value)
{
Mask *mask = (Mask *)ptr->id.data;
MaskLayer *masklay = (MaskLayer *)ptr->data;
+ char oldname[sizeof(masklay->name)], newname[sizeof(masklay->name)];
- BLI_strncpy(masklay->name, value, sizeof(masklay->name));
+ /* need to be on the stack */
+ BLI_strncpy(oldname, masklay->name, sizeof(masklay->name));
+ BLI_strncpy_utf8(newname, value, sizeof(masklay->name));
- BKE_mask_layer_unique_name(mask, masklay);
+ BKE_mask_layer_rename(mask, masklay, oldname, newname);
}
static PointerRNA rna_MaskLayer_active_spline_get(PointerRNA *ptr)
@@ -975,7 +976,7 @@ static void rna_def_mask_layer(BlenderRNA *brna)
RNA_def_property_enum_sdna(prop, NULL, "falloff");
RNA_def_property_enum_items(prop, proportional_falloff_curve_only_items);
RNA_def_property_ui_text(prop, "Falloff", "Falloff type the feather");
- RNA_def_property_translation_context(prop, BLF_I18NCONTEXT_ID_CURVE); /* Abusing id_curve :/ */
+ RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_CURVE); /* Abusing id_curve :/ */
RNA_def_property_update(prop, NC_MASK | NA_EDITED, NULL);
/* filling options */
diff --git a/source/blender/makesrna/intern/rna_material.c b/source/blender/makesrna/intern/rna_material.c
index 2e4f24fc0ce..a1fa6ab13be 100644
--- a/source/blender/makesrna/intern/rna_material.c
+++ b/source/blender/makesrna/intern/rna_material.c
@@ -181,7 +181,7 @@ static void rna_Material_active_paint_texture_index_update(Main *bmain, Scene *s
bScreen *sc;
Material *ma = ptr->id.data;
- if (ma->use_nodes && ma->nodetree && BKE_scene_use_new_shading_nodes(scene)) {
+ if (ma->use_nodes && ma->nodetree) {
struct bNode *node;
int index = 0;
for (node = ma->nodetree->nodes.first; node; node = node->next) {
@@ -377,7 +377,7 @@ static EnumPropertyItem *rna_Material_texture_coordinates_itemf(bContext *UNUSED
MTex *rna_mtex_texture_slots_add(ID *self_id, struct bContext *C, ReportList *reports)
{
- MTex *mtex = add_mtex_id(self_id, -1);
+ MTex *mtex = BKE_texture_mtex_add_id(self_id, -1);
if (mtex == NULL) {
BKE_reportf(reports, RPT_ERROR, "Maximum number of textures added %d", MAX_MTEX);
return NULL;
@@ -398,7 +398,7 @@ MTex *rna_mtex_texture_slots_create(ID *self_id, struct bContext *C, ReportList
return NULL;
}
- mtex = add_mtex_id(self_id, index);
+ mtex = BKE_texture_mtex_add_id(self_id, index);
/* for redraw only */
WM_event_add_notifier(C, NC_TEXTURE, CTX_data_scene(C));
@@ -834,9 +834,11 @@ static void rna_def_material_gamesettings(BlenderRNA *brna)
{GEMAT_ADD, "ADD", 0, "Add", "Render face transparent and add color of face"},
{GEMAT_CLIP, "CLIP", 0, "Alpha Clip", "Use the image alpha values clipped with no blending (binary alpha)"},
{GEMAT_ALPHA, "ALPHA", 0, "Alpha Blend",
- "Render polygon transparent, depending on alpha channel of the texture"},
+ "Render polygon transparent, depending on alpha channel of the texture"},
{GEMAT_ALPHA_SORT, "ALPHA_SORT", 0, "Alpha Sort",
- "Sort faces for correct alpha drawing (slow, use Alpha Clip instead when possible)"},
+ "Sort faces for correct alpha drawing (slow, use Alpha Clip instead when possible)"},
+ {GEMAT_ALPHA_TO_COVERAGE, "ALPHA_ANTIALIASING", 0, "Alpha Anti-Aliasing",
+ "Use textures alpha as anti-aliasing mask, requires multi-sample OpenGL display"},
{0, NULL, 0, NULL, NULL}
};
diff --git a/source/blender/makesrna/intern/rna_mesh.c b/source/blender/makesrna/intern/rna_mesh.c
index b0b99dcd2ca..ec64aa38275 100644
--- a/source/blender/makesrna/intern/rna_mesh.c
+++ b/source/blender/makesrna/intern/rna_mesh.c
@@ -55,6 +55,8 @@ EnumPropertyItem mesh_delimit_mode_items[] = {
{BMO_DELIM_NORMAL, "NORMAL", 0, "Normal", "Delimit by face directions"},
{BMO_DELIM_MATERIAL, "MATERIAL", 0, "Material", "Delimit by face material"},
{BMO_DELIM_SEAM, "SEAM", 0, "Seam", "Delimit by edge seams"},
+ {BMO_DELIM_SHARP, "SHARP", 0, "Sharp", "Delimit by sharp edges"},
+ {BMO_DELIM_UV, "UV", 0, "UVs", "Delimit by UV coordinates"},
{0, NULL, 0, NULL, NULL},
};
@@ -73,7 +75,6 @@ EnumPropertyItem mesh_delimit_mode_items[] = {
#include "ED_mesh.h" /* XXX Bad level call */
#include "WM_api.h"
-#include "WM_types.h"
#include "rna_mesh_utils.h"
@@ -207,6 +208,11 @@ static void rna_MeshAnyLayer_name_set(PointerRNA *ptr, const char *value)
rna_cd_layer_name_set(cd, (CustomDataLayer *)ptr->data, value);
}
+static int rna_Mesh_has_custom_normals_get(PointerRNA *ptr)
+{
+ Mesh *me = ptr->data;
+ return (int)BKE_mesh_has_custom_loop_normals(me);
+}
/* -------------------------------------------------------------------- */
/* Update Callbacks */
@@ -338,6 +344,17 @@ static void rna_MeshLoop_normal_get(PointerRNA *ptr, float *values)
}
}
+static void rna_MeshLoop_normal_set(PointerRNA *ptr, const float *values)
+{
+ Mesh *me = rna_mesh(ptr);
+ MLoop *ml = (MLoop *)ptr->data;
+ float (*vec)[3] = CustomData_get(&me->ldata, (int)(ml - me->mloop), CD_NORMAL);
+
+ if (vec) {
+ normalize_v3_v3(*vec, values);
+ }
+}
+
static void rna_MeshLoop_tangent_get(PointerRNA *ptr, float *values)
{
Mesh *me = rna_mesh(ptr);
@@ -696,7 +713,7 @@ static void rna_MeshVertex_undeformed_co_get(PointerRNA *ptr, float values[3])
copy_v3_v3(values, mvert->co);
}
-static int rna_CustomDataLayer_active_get(PointerRNA *ptr, CustomData *data, int type, int render)
+static int rna_CustomDataLayer_active_get(PointerRNA *ptr, CustomData *data, int type, bool render)
{
int n = ((CustomDataLayer *)ptr->data) - data->layers;
@@ -1011,25 +1028,18 @@ static void rna_MeshLoopColorLayer_active_set(PointerRNA *ptr, int value)
rna_CustomDataLayer_active_set(ptr, rna_mesh_ldata(ptr), value, CD_MLOOPCOL, 0);
}
-static void rna_MeshFloatPropertyLayer_data_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
-{
- Mesh *me = rna_mesh(ptr);
- CustomDataLayer *layer = (CustomDataLayer *)ptr->data;
- rna_iterator_array_begin(iter, layer->data, sizeof(MFloatProperty), me->totpoly, 0, NULL);
-}
-
-static int rna_MeshFloatPropertyLayer_data_length(PointerRNA *ptr)
-{
- Mesh *me = rna_mesh(ptr);
- return me->totpoly;
-}
-
static int rna_float_layer_check(CollectionPropertyIterator *UNUSED(iter), void *data)
{
CustomDataLayer *layer = (CustomDataLayer *)data;
return (layer->type != CD_PROP_FLT);
}
+static void rna_Mesh_vertex_float_layers_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
+{
+ CustomData *vdata = rna_mesh_vdata(ptr);
+ rna_iterator_array_begin(iter, (void *)vdata->layers, sizeof(CustomDataLayer), vdata->totlayer, 0,
+ rna_float_layer_check);
+}
static void rna_Mesh_polygon_float_layers_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
{
CustomData *pdata = rna_mesh_pdata(ptr);
@@ -1037,6 +1047,10 @@ static void rna_Mesh_polygon_float_layers_begin(CollectionPropertyIterator *iter
rna_float_layer_check);
}
+static int rna_Mesh_vertex_float_layers_length(PointerRNA *ptr)
+{
+ return CustomData_number_of_layers(rna_mesh_vdata(ptr), CD_PROP_FLT);
+}
static int rna_Mesh_polygon_float_layers_length(PointerRNA *ptr)
{
return CustomData_number_of_layers(rna_mesh_pdata(ptr), CD_PROP_FLT);
@@ -1048,19 +1062,12 @@ static int rna_int_layer_check(CollectionPropertyIterator *UNUSED(iter), void *d
return (layer->type != CD_PROP_INT);
}
-static void rna_MeshIntPropertyLayer_data_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
+static void rna_Mesh_vertex_int_layers_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
{
- Mesh *me = rna_mesh(ptr);
- CustomDataLayer *layer = (CustomDataLayer *)ptr->data;
- rna_iterator_array_begin(iter, layer->data, sizeof(MIntProperty), me->totpoly, 0, NULL);
-}
-
-static int rna_MeshIntPropertyLayer_data_length(PointerRNA *ptr)
-{
- Mesh *me = rna_mesh(ptr);
- return me->totpoly;
+ CustomData *vdata = rna_mesh_vdata(ptr);
+ rna_iterator_array_begin(iter, (void *)vdata->layers, sizeof(CustomDataLayer), vdata->totlayer, 0,
+ rna_int_layer_check);
}
-
static void rna_Mesh_polygon_int_layers_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
{
CustomData *pdata = rna_mesh_pdata(ptr);
@@ -1068,6 +1075,10 @@ static void rna_Mesh_polygon_int_layers_begin(CollectionPropertyIterator *iter,
rna_int_layer_check);
}
+static int rna_Mesh_vertex_int_layers_length(PointerRNA *ptr)
+{
+ return CustomData_number_of_layers(rna_mesh_vdata(ptr), CD_PROP_INT);
+}
static int rna_Mesh_polygon_int_layers_length(PointerRNA *ptr)
{
return CustomData_number_of_layers(rna_mesh_pdata(ptr), CD_PROP_INT);
@@ -1079,19 +1090,12 @@ static int rna_string_layer_check(CollectionPropertyIterator *UNUSED(iter), void
return (layer->type != CD_PROP_STR);
}
-static void rna_MeshStringPropertyLayer_data_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
-{
- Mesh *me = rna_mesh(ptr);
- CustomDataLayer *layer = (CustomDataLayer *)ptr->data;
- rna_iterator_array_begin(iter, layer->data, sizeof(MStringProperty), me->totpoly, 0, NULL);
-}
-
-static int rna_MeshStringPropertyLayer_data_length(PointerRNA *ptr)
+static void rna_Mesh_vertex_string_layers_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
{
- Mesh *me = rna_mesh(ptr);
- return me->totpoly;
+ CustomData *vdata = rna_mesh_vdata(ptr);
+ rna_iterator_array_begin(iter, (void *)vdata->layers, sizeof(CustomDataLayer), vdata->totlayer, 0,
+ rna_string_layer_check);
}
-
static void rna_Mesh_polygon_string_layers_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
{
CustomData *pdata = rna_mesh_pdata(ptr);
@@ -1099,6 +1103,10 @@ static void rna_Mesh_polygon_string_layers_begin(CollectionPropertyIterator *ite
rna_string_layer_check);
}
+static int rna_Mesh_vertex_string_layers_length(PointerRNA *ptr)
+{
+ return CustomData_number_of_layers(rna_mesh_vdata(ptr), CD_PROP_STR);
+}
static int rna_Mesh_polygon_string_layers_length(PointerRNA *ptr)
{
return CustomData_number_of_layers(rna_mesh_pdata(ptr), CD_PROP_STR);
@@ -1136,6 +1144,37 @@ static int rna_MeshSkinVertexLayer_data_length(PointerRNA *ptr)
/* End skin vertices */
+/* Paint mask */
+DEFINE_CUSTOMDATA_LAYER_COLLECTION(vertex_paint_mask, vdata, CD_PAINT_MASK)
+
+static char *rna_MeshPaintMaskLayer_path(PointerRNA *ptr)
+{
+ CustomDataLayer *cdl = ptr->data;
+ char name_esc[sizeof(cdl->name) * 2];
+ BLI_strescape(name_esc, cdl->name, sizeof(name_esc));
+ return BLI_sprintfN("vertex_paint_masks[\"%s\"]", name_esc);
+}
+
+static char *rna_MeshPaintMask_path(PointerRNA *ptr)
+{
+ return rna_VertCustomData_data_path(ptr, "vertex_paint_masks", CD_PAINT_MASK);
+}
+
+static void rna_MeshPaintMaskLayer_data_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
+{
+ Mesh *me = rna_mesh(ptr);
+ CustomDataLayer *layer = (CustomDataLayer *)ptr->data;
+ rna_iterator_array_begin(iter, layer->data, sizeof(MFloatProperty), me->totvert, 0, NULL);
+}
+
+static int rna_MeshPaintMaskLayer_data_length(PointerRNA *ptr)
+{
+ Mesh *me = rna_mesh(ptr);
+ return me->totvert;
+}
+
+/* End paint mask */
+
static void rna_TexturePoly_image_set(PointerRNA *ptr, PointerRNA value)
{
MTexPoly *tf = (MTexPoly *)ptr->data;
@@ -1415,8 +1454,6 @@ static char *rna_FaceCustomData_data_path(PointerRNA *ptr, const char *collectio
}
-
-
static char *rna_MeshUVLoop_path(PointerRNA *ptr)
{
return rna_LoopCustomData_data_path(ptr, "uv_layers", CD_MLOOPUV);
@@ -1453,43 +1490,151 @@ static char *rna_MeshColor_path(PointerRNA *ptr)
return rna_LoopCustomData_data_path(ptr, "vertex_colors", CD_MLOOPCOL);
}
-static char *rna_MeshIntPropertyLayer_path(PointerRNA *ptr)
+/**** Float Property Layer API ****/
+static char *rna_MeshVertexFloatPropertyLayer_path(PointerRNA *ptr)
+{
+ CustomDataLayer *cdl = ptr->data;
+ char name_esc[sizeof(cdl->name) * 2];
+ BLI_strescape(name_esc, cdl->name, sizeof(name_esc));
+ return BLI_sprintfN("vertex_float_layers[\"%s\"]", name_esc);
+}
+static char *rna_MeshPolygonFloatPropertyLayer_path(PointerRNA *ptr)
{
CustomDataLayer *cdl = ptr->data;
char name_esc[sizeof(cdl->name) * 2];
BLI_strescape(name_esc, cdl->name, sizeof(name_esc));
- return BLI_sprintfN("int_layers[\"%s\"]", name_esc);
+ return BLI_sprintfN("polygon_float_layers[\"%s\"]", name_esc);
+}
+
+static char *rna_MeshVertexFloatProperty_path(PointerRNA *ptr)
+{
+ return rna_VertCustomData_data_path(ptr, "vertex_layers_float", CD_PROP_FLT);
+}
+static char *rna_MeshPolygonFloatProperty_path(PointerRNA *ptr)
+{
+ return rna_PolyCustomData_data_path(ptr, "polygon_layers_float", CD_PROP_FLT);
+}
+
+static void rna_MeshVertexFloatPropertyLayer_data_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
+{
+ Mesh *me = rna_mesh(ptr);
+ CustomDataLayer *layer = (CustomDataLayer *)ptr->data;
+ rna_iterator_array_begin(iter, layer->data, sizeof(MFloatProperty), me->totvert, 0, NULL);
+}
+static void rna_MeshPolygonFloatPropertyLayer_data_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
+{
+ Mesh *me = rna_mesh(ptr);
+ CustomDataLayer *layer = (CustomDataLayer *)ptr->data;
+ rna_iterator_array_begin(iter, layer->data, sizeof(MFloatProperty), me->totpoly, 0, NULL);
}
-static char *rna_MeshIntProperty_path(PointerRNA *ptr)
+static int rna_MeshVertexFloatPropertyLayer_data_length(PointerRNA *ptr)
+{
+ Mesh *me = rna_mesh(ptr);
+ return me->totvert;
+}
+static int rna_MeshPolygonFloatPropertyLayer_data_length(PointerRNA *ptr)
{
- return rna_PolyCustomData_data_path(ptr, "layers_int", CD_PROP_INT);
+ Mesh *me = rna_mesh(ptr);
+ return me->totpoly;
}
-static char *rna_MeshFloatPropertyLayer_path(PointerRNA *ptr)
+/**** Int Property Layer API ****/
+static char *rna_MeshVertexIntPropertyLayer_path(PointerRNA *ptr)
{
CustomDataLayer *cdl = ptr->data;
char name_esc[sizeof(cdl->name) * 2];
BLI_strescape(name_esc, cdl->name, sizeof(name_esc));
- return BLI_sprintfN("float_layers[\"%s\"]", name_esc);
+ return BLI_sprintfN("vertex_int_layers[\"%s\"]", name_esc);
+}
+static char *rna_MeshPolygonIntPropertyLayer_path(PointerRNA *ptr)
+{
+ CustomDataLayer *cdl = ptr->data;
+ char name_esc[sizeof(cdl->name) * 2];
+ BLI_strescape(name_esc, cdl->name, sizeof(name_esc));
+ return BLI_sprintfN("polygon_int_layers[\"%s\"]", name_esc);
+}
+
+static char *rna_MeshVertexIntProperty_path(PointerRNA *ptr)
+{
+ return rna_VertCustomData_data_path(ptr, "vertex_layers_int", CD_PROP_INT);
+}
+static char *rna_MeshPolygonIntProperty_path(PointerRNA *ptr)
+{
+ return rna_PolyCustomData_data_path(ptr, "polygon_layers_int", CD_PROP_INT);
+}
+
+static void rna_MeshVertexIntPropertyLayer_data_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
+{
+ Mesh *me = rna_mesh(ptr);
+ CustomDataLayer *layer = (CustomDataLayer *)ptr->data;
+ rna_iterator_array_begin(iter, layer->data, sizeof(MIntProperty), me->totvert, 0, NULL);
+}
+static void rna_MeshPolygonIntPropertyLayer_data_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
+{
+ Mesh *me = rna_mesh(ptr);
+ CustomDataLayer *layer = (CustomDataLayer *)ptr->data;
+ rna_iterator_array_begin(iter, layer->data, sizeof(MIntProperty), me->totpoly, 0, NULL);
}
-static char *rna_MeshFloatProperty_path(PointerRNA *ptr)
+static int rna_MeshVertexIntPropertyLayer_data_length(PointerRNA *ptr)
{
- return rna_PolyCustomData_data_path(ptr, "layers_float", CD_PROP_FLT);
+ Mesh *me = rna_mesh(ptr);
+ return me->totvert;
+}
+static int rna_MeshPolygonIntPropertyLayer_data_length(PointerRNA *ptr)
+{
+ Mesh *me = rna_mesh(ptr);
+ return me->totpoly;
}
-static char *rna_MeshStringPropertyLayer_path(PointerRNA *ptr)
+/**** String Property Layer API ****/
+static char *rna_MeshVertexStringPropertyLayer_path(PointerRNA *ptr)
+{
+ CustomDataLayer *cdl = ptr->data;
+ char name_esc[sizeof(cdl->name) * 2];
+ BLI_strescape(name_esc, cdl->name, sizeof(name_esc));
+ return BLI_sprintfN("vertex_string_layers[\"%s\"]", name_esc);
+}
+static char *rna_MeshPolygonStringPropertyLayer_path(PointerRNA *ptr)
{
CustomDataLayer *cdl = ptr->data;
char name_esc[sizeof(cdl->name) * 2];
BLI_strescape(name_esc, cdl->name, sizeof(name_esc));
- return BLI_sprintfN("string_layers[\"%s\"]", name_esc);
+ return BLI_sprintfN("polygon_string_layers[\"%s\"]", name_esc);
+}
+
+static char *rna_MeshVertexStringProperty_path(PointerRNA *ptr)
+{
+ return rna_VertCustomData_data_path(ptr, "vertex_layers_string", CD_PROP_STR);
+}
+static char *rna_MeshPolygonStringProperty_path(PointerRNA *ptr)
+{
+ return rna_PolyCustomData_data_path(ptr, "polygon_layers_string", CD_PROP_STR);
}
-static char *rna_MeshStringProperty_path(PointerRNA *ptr)
+static void rna_MeshVertexStringPropertyLayer_data_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
+{
+ Mesh *me = rna_mesh(ptr);
+ CustomDataLayer *layer = (CustomDataLayer *)ptr->data;
+ rna_iterator_array_begin(iter, layer->data, sizeof(MStringProperty), me->totvert, 0, NULL);
+}
+static void rna_MeshPolygonStringPropertyLayer_data_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
+{
+ Mesh *me = rna_mesh(ptr);
+ CustomDataLayer *layer = (CustomDataLayer *)ptr->data;
+ rna_iterator_array_begin(iter, layer->data, sizeof(MStringProperty), me->totpoly, 0, NULL);
+}
+
+static int rna_MeshVertexStringPropertyLayer_data_length(PointerRNA *ptr)
+{
+ Mesh *me = rna_mesh(ptr);
+ return me->totvert;
+}
+static int rna_MeshPolygonStringPropertyLayer_data_length(PointerRNA *ptr)
{
- return rna_PolyCustomData_data_path(ptr, "layers_string", CD_PROP_STR);
+ Mesh *me = rna_mesh(ptr);
+ return me->totpoly;
}
/* XXX, we dont have propper byte string support yet, so for now use the (bytes + 1)
@@ -1511,6 +1656,7 @@ void rna_MeshStringProperty_s_set(PointerRNA *ptr, const char *value)
MStringProperty *ms = (MStringProperty *)ptr->data;
BLI_strncpy(ms->s, value, sizeof(ms->s));
}
+/***************************************/
static int rna_Mesh_tot_vert_get(PointerRNA *ptr)
{
@@ -1579,50 +1725,29 @@ static PointerRNA rna_Mesh_tessface_vertex_color_new(struct Mesh *me, ReportList
return ptr;
}
-static PointerRNA rna_Mesh_polygon_int_property_new(struct Mesh *me, const char *name)
-{
- PointerRNA ptr;
- CustomDataLayer *cdl = NULL;
- int index;
-
- CustomData_add_layer_named(&me->pdata, CD_PROP_INT, CD_DEFAULT, NULL, me->totpoly, name);
- index = CustomData_get_named_layer_index(&me->pdata, CD_PROP_INT, name);
-
- cdl = (index == -1) ? NULL : &(me->pdata.layers[index]);
-
- RNA_pointer_create(&me->id, &RNA_MeshIntPropertyLayer, cdl, &ptr);
- return ptr;
-}
-
-static PointerRNA rna_Mesh_polygon_float_property_new(struct Mesh *me, const char *name)
-{
- PointerRNA ptr;
- CustomDataLayer *cdl = NULL;
- int index;
-
- CustomData_add_layer_named(&me->pdata, CD_PROP_FLT, CD_DEFAULT, NULL, me->totpoly, name);
- index = CustomData_get_named_layer_index(&me->pdata, CD_PROP_FLT, name);
-
- cdl = (index == -1) ? NULL : &(me->pdata.layers[index]);
-
- RNA_pointer_create(&me->id, &RNA_MeshFloatPropertyLayer, cdl, &ptr);
- return ptr;
-}
-
-static PointerRNA rna_Mesh_polygon_string_property_new(struct Mesh *me, const char *name)
-{
- PointerRNA ptr;
- CustomDataLayer *cdl = NULL;
- int index;
-
- CustomData_add_layer_named(&me->pdata, CD_PROP_STR, CD_DEFAULT, NULL, me->totpoly, name);
- index = CustomData_get_named_layer_index(&me->pdata, CD_PROP_STR, name);
-
- cdl = (index == -1) ? NULL : &(me->pdata.layers[index]);
-
- RNA_pointer_create(&me->id, &RNA_MeshStringPropertyLayer, cdl, &ptr);
- return ptr;
-}
+#define DEFINE_CUSTOMDATA_PROPERTY_API(elemname, datatype, cd_prop_type, cdata, countvar, layertype) \
+static PointerRNA rna_Mesh_##elemname##_##datatype##_property_new(struct Mesh *me, const char *name) \
+{ \
+ PointerRNA ptr; \
+ CustomDataLayer *cdl = NULL; \
+ int index; \
+ \
+ CustomData_add_layer_named(&me->cdata, cd_prop_type, CD_DEFAULT, NULL, me->countvar, name); \
+ index = CustomData_get_named_layer_index(&me->cdata, cd_prop_type, name); \
+ \
+ cdl = (index == -1) ? NULL : &(me->cdata.layers[index]); \
+ \
+ RNA_pointer_create(&me->id, &RNA_##layertype, cdl, &ptr); \
+ return ptr; \
+}
+
+DEFINE_CUSTOMDATA_PROPERTY_API(vertex, float, CD_PROP_FLT, vdata, totvert, MeshVertexFloatPropertyLayer)
+DEFINE_CUSTOMDATA_PROPERTY_API(vertex, int, CD_PROP_INT, vdata, totvert, MeshVertexIntPropertyLayer)
+DEFINE_CUSTOMDATA_PROPERTY_API(vertex, string, CD_PROP_STR, vdata, totvert, MeshVertexStringPropertyLayer)
+DEFINE_CUSTOMDATA_PROPERTY_API(polygon, float, CD_PROP_FLT, pdata, totpoly, MeshPolygonFloatPropertyLayer)
+DEFINE_CUSTOMDATA_PROPERTY_API(polygon, int, CD_PROP_INT, pdata, totpoly, MeshPolygonIntPropertyLayer)
+DEFINE_CUSTOMDATA_PROPERTY_API(polygon, string, CD_PROP_STR, pdata, totpoly, MeshPolygonStringPropertyLayer)
+#undef DEFINE_CUSTOMDATA_PROPERTY_API
static PointerRNA rna_Mesh_uv_texture_new(struct Mesh *me, const char *name)
{
@@ -1690,6 +1815,7 @@ static void UNUSED_FUNCTION(rna_mesh_unused)(void)
{
/* unused functions made by macros */
(void)rna_Mesh_skin_vertice_index_range;
+ (void)rna_Mesh_vertex_paint_mask_index_range;
(void)rna_Mesh_tessface_uv_texture_active_set;
(void)rna_Mesh_tessface_uv_texture_clone_get;
(void)rna_Mesh_tessface_uv_texture_clone_index_get;
@@ -1976,8 +2102,7 @@ static void rna_def_mloop(BlenderRNA *brna)
prop = RNA_def_property(srna, "normal", PROP_FLOAT, PROP_DIRECTION);
RNA_def_property_array(prop, 3);
RNA_def_property_range(prop, -1.0f, 1.0f);
- RNA_def_property_clear_flag(prop, PROP_EDITABLE);
- RNA_def_property_float_funcs(prop, "rna_MeshLoop_normal_get", NULL, NULL);
+ RNA_def_property_float_funcs(prop, "rna_MeshLoop_normal_get", "rna_MeshLoop_normal_set", NULL);
RNA_def_property_ui_text(prop, "Normal",
"Local space unit length split normal vector of this vertex for this polygon "
"(must be computed beforehand using calc_normals_split or calc_tangents)");
@@ -2449,96 +2574,108 @@ static void rna_def_mproperties(BlenderRNA *brna)
PropertyRNA *prop;
/* Float */
- srna = RNA_def_struct(brna, "MeshFloatPropertyLayer", NULL);
- RNA_def_struct_sdna(srna, "CustomDataLayer");
- RNA_def_struct_ui_text(srna, "Mesh Float Property Layer", "User defined layer of floating point number values");
- RNA_def_struct_path_func(srna, "rna_MeshFloatPropertyLayer_path");
-
- prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE);
- RNA_def_struct_name_property(srna, prop);
- RNA_def_property_string_funcs(prop, NULL, NULL, "rna_MeshAnyLayer_name_set");
- RNA_def_property_ui_text(prop, "Name", "");
- RNA_def_property_update(prop, 0, "rna_Mesh_update_data");
-
- prop = RNA_def_property(srna, "data", PROP_COLLECTION, PROP_NONE);
- RNA_def_property_struct_type(prop, "MeshFloatProperty");
- RNA_def_property_ui_text(prop, "Data", "");
- RNA_def_property_collection_funcs(prop, "rna_MeshFloatPropertyLayer_data_begin", "rna_iterator_array_next",
- "rna_iterator_array_end", "rna_iterator_array_get",
- "rna_MeshFloatPropertyLayer_data_length", NULL, NULL, NULL);
-
- srna = RNA_def_struct(brna, "MeshFloatProperty", NULL);
- RNA_def_struct_sdna(srna, "MFloatProperty");
- RNA_def_struct_ui_text(srna, "Mesh Float Property",
- "User defined floating point number value in a float properties layer");
- RNA_def_struct_path_func(srna, "rna_MeshFloatProperty_path");
-
- prop = RNA_def_property(srna, "value", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "f");
- RNA_def_property_ui_text(prop, "Value", "");
+#define MESH_FLOAT_PROPERTY_LAYER(elemname) \
+ srna = RNA_def_struct(brna, "Mesh" elemname "FloatPropertyLayer", NULL); \
+ RNA_def_struct_sdna(srna, "CustomDataLayer"); \
+ RNA_def_struct_ui_text(srna, "Mesh " elemname " Float Property Layer", "User defined layer of floating point number values"); \
+ RNA_def_struct_path_func(srna, "rna_Mesh" elemname "FloatPropertyLayer_path"); \
+ \
+ prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE); \
+ RNA_def_struct_name_property(srna, prop); \
+ RNA_def_property_string_funcs(prop, NULL, NULL, "rna_MeshAnyLayer_name_set"); \
+ RNA_def_property_ui_text(prop, "Name", ""); \
+ RNA_def_property_update(prop, 0, "rna_Mesh_update_data"); \
+ \
+ prop = RNA_def_property(srna, "data", PROP_COLLECTION, PROP_NONE); \
+ RNA_def_property_struct_type(prop, "Mesh" elemname "FloatProperty"); \
+ RNA_def_property_ui_text(prop, "Data", ""); \
+ RNA_def_property_collection_funcs(prop, "rna_Mesh" elemname "FloatPropertyLayer_data_begin", "rna_iterator_array_next", \
+ "rna_iterator_array_end", "rna_iterator_array_get", \
+ "rna_Mesh" elemname "FloatPropertyLayer_data_length", NULL, NULL, NULL); \
+ \
+ srna = RNA_def_struct(brna, "Mesh" elemname "FloatProperty", NULL); \
+ RNA_def_struct_sdna(srna, "MFloatProperty"); \
+ RNA_def_struct_ui_text(srna, "Mesh " elemname " Float Property", \
+ "User defined floating point number value in a float properties layer"); \
+ RNA_def_struct_path_func(srna, "rna_Mesh" elemname "FloatProperty_path"); \
+ \
+ prop = RNA_def_property(srna, "value", PROP_FLOAT, PROP_NONE); \
+ RNA_def_property_float_sdna(prop, NULL, "f"); \
+ RNA_def_property_ui_text(prop, "Value", ""); \
RNA_def_property_update(prop, 0, "rna_Mesh_update_data");
/* Int */
- srna = RNA_def_struct(brna, "MeshIntPropertyLayer", NULL);
- RNA_def_struct_sdna(srna, "CustomDataLayer");
- RNA_def_struct_ui_text(srna, "Mesh Int Property Layer", "User defined layer of integer number values");
- RNA_def_struct_path_func(srna, "rna_MeshIntPropertyLayer_path");
-
- prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE);
- RNA_def_struct_name_property(srna, prop);
- RNA_def_property_string_funcs(prop, NULL, NULL, "rna_MeshAnyLayer_name_set");
- RNA_def_property_ui_text(prop, "Name", "");
- RNA_def_property_update(prop, 0, "rna_Mesh_update_data");
-
- prop = RNA_def_property(srna, "data", PROP_COLLECTION, PROP_NONE);
- RNA_def_property_struct_type(prop, "MeshIntProperty");
- RNA_def_property_ui_text(prop, "Data", "");
- RNA_def_property_collection_funcs(prop, "rna_MeshIntPropertyLayer_data_begin", "rna_iterator_array_next",
- "rna_iterator_array_end", "rna_iterator_array_get",
- "rna_MeshIntPropertyLayer_data_length", NULL, NULL, NULL);
-
- srna = RNA_def_struct(brna, "MeshIntProperty", NULL);
- RNA_def_struct_sdna(srna, "MIntProperty");
- RNA_def_struct_ui_text(srna, "Mesh Int Property",
- "User defined integer number value in an integer properties layer");
- RNA_def_struct_path_func(srna, "rna_MeshIntProperty_path");
-
- prop = RNA_def_property(srna, "value", PROP_INT, PROP_NONE);
- RNA_def_property_int_sdna(prop, NULL, "i");
- RNA_def_property_ui_text(prop, "Value", "");
- RNA_def_property_update(prop, 0, "rna_Mesh_update_data");
+#define MESH_INT_PROPERTY_LAYER(elemname) \
+ srna = RNA_def_struct(brna, "Mesh" elemname "IntPropertyLayer", NULL); \
+ RNA_def_struct_sdna(srna, "CustomDataLayer"); \
+ RNA_def_struct_ui_text(srna, "Mesh " elemname " Int Property Layer", "User defined layer of integer number values"); \
+ RNA_def_struct_path_func(srna, "rna_Mesh" elemname "IntPropertyLayer_path"); \
+ \
+ prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE); \
+ RNA_def_struct_name_property(srna, prop); \
+ RNA_def_property_string_funcs(prop, NULL, NULL, "rna_MeshAnyLayer_name_set"); \
+ RNA_def_property_ui_text(prop, "Name", ""); \
+ RNA_def_property_update(prop, 0, "rna_Mesh_update_data"); \
+ \
+ prop = RNA_def_property(srna, "data", PROP_COLLECTION, PROP_NONE); \
+ RNA_def_property_struct_type(prop, "Mesh" elemname "IntProperty"); \
+ RNA_def_property_ui_text(prop, "Data", ""); \
+ RNA_def_property_collection_funcs(prop, "rna_Mesh" elemname "IntPropertyLayer_data_begin", "rna_iterator_array_next", \
+ "rna_iterator_array_end", "rna_iterator_array_get", \
+ "rna_Mesh" elemname "IntPropertyLayer_data_length", NULL, NULL, NULL); \
+ \
+ srna = RNA_def_struct(brna, "Mesh" elemname "IntProperty", NULL); \
+ RNA_def_struct_sdna(srna, "MIntProperty"); \
+ RNA_def_struct_ui_text(srna, "Mesh " elemname " Int Property", \
+ "User defined integer number value in an integer properties layer"); \
+ RNA_def_struct_path_func(srna, "rna_Mesh" elemname "IntProperty_path"); \
+ \
+ prop = RNA_def_property(srna, "value", PROP_INT, PROP_NONE); \
+ RNA_def_property_int_sdna(prop, NULL, "i"); \
+ RNA_def_property_ui_text(prop, "Value", ""); \
+ RNA_def_property_update(prop, 0, "rna_Mesh_update_data"); \
/* String */
- srna = RNA_def_struct(brna, "MeshStringPropertyLayer", NULL);
- RNA_def_struct_sdna(srna, "CustomDataLayer");
- RNA_def_struct_ui_text(srna, "Mesh String Property Layer", "User defined layer of string text values");
- RNA_def_struct_path_func(srna, "rna_MeshStringPropertyLayer_path");
+#define MESH_STRING_PROPERTY_LAYER(elemname) \
+ srna = RNA_def_struct(brna, "Mesh" elemname "StringPropertyLayer", NULL); \
+ RNA_def_struct_sdna(srna, "CustomDataLayer"); \
+ RNA_def_struct_ui_text(srna, "Mesh " elemname " String Property Layer", "User defined layer of string text values"); \
+ RNA_def_struct_path_func(srna, "rna_Mesh" elemname "StringPropertyLayer_path"); \
+ \
+ prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE); \
+ RNA_def_struct_name_property(srna, prop); \
+ RNA_def_property_string_funcs(prop, NULL, NULL, "rna_MeshAnyLayer_name_set"); \
+ RNA_def_property_ui_text(prop, "Name", ""); \
+ RNA_def_property_update(prop, 0, "rna_Mesh_update_data"); \
+ \
+ prop = RNA_def_property(srna, "data", PROP_COLLECTION, PROP_NONE); \
+ RNA_def_property_struct_type(prop, "Mesh" elemname "StringProperty"); \
+ RNA_def_property_ui_text(prop, "Data", ""); \
+ RNA_def_property_collection_funcs(prop, "rna_Mesh" elemname "StringPropertyLayer_data_begin", "rna_iterator_array_next", \
+ "rna_iterator_array_end", "rna_iterator_array_get", \
+ "rna_Mesh" elemname "StringPropertyLayer_data_length", NULL, NULL, NULL); \
+ \
+ srna = RNA_def_struct(brna, "Mesh" elemname "StringProperty", NULL); \
+ RNA_def_struct_sdna(srna, "MStringProperty"); \
+ RNA_def_struct_ui_text(srna, "Mesh " elemname " String Property", \
+ "User defined string text value in a string properties layer"); \
+ RNA_def_struct_path_func(srna, "rna_Mesh" elemname "StringProperty_path"); \
+ \
+ /* low level mesh data access, treat as bytes */ \
+ prop = RNA_def_property(srna, "value", PROP_STRING, PROP_BYTESTRING); \
+ RNA_def_property_string_sdna(prop, NULL, "s"); \
+ RNA_def_property_string_funcs(prop, "rna_MeshStringProperty_s_get", "rna_MeshStringProperty_s_length", "rna_MeshStringProperty_s_set"); \
+ RNA_def_property_ui_text(prop, "Value", ""); \
+ RNA_def_property_update(prop, 0, "rna_Mesh_update_data"); \
+
+ MESH_FLOAT_PROPERTY_LAYER("Vertex")
+ MESH_FLOAT_PROPERTY_LAYER("Polygon")
+ MESH_INT_PROPERTY_LAYER("Vertex")
+ MESH_INT_PROPERTY_LAYER("Polygon")
+ MESH_STRING_PROPERTY_LAYER("Vertex")
+ MESH_STRING_PROPERTY_LAYER("Polygon")
+#undef MESH_PROPERTY_LAYER
- prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE);
- RNA_def_struct_name_property(srna, prop);
- RNA_def_property_string_funcs(prop, NULL, NULL, "rna_MeshAnyLayer_name_set");
- RNA_def_property_ui_text(prop, "Name", "");
- RNA_def_property_update(prop, 0, "rna_Mesh_update_data");
-
- prop = RNA_def_property(srna, "data", PROP_COLLECTION, PROP_NONE);
- RNA_def_property_struct_type(prop, "MeshStringProperty");
- RNA_def_property_ui_text(prop, "Data", "");
- RNA_def_property_collection_funcs(prop, "rna_MeshStringPropertyLayer_data_begin", "rna_iterator_array_next",
- "rna_iterator_array_end", "rna_iterator_array_get",
- "rna_MeshStringPropertyLayer_data_length", NULL, NULL, NULL);
-
- srna = RNA_def_struct(brna, "MeshStringProperty", NULL);
- RNA_def_struct_sdna(srna, "MStringProperty");
- RNA_def_struct_ui_text(srna, "Mesh String Property",
- "User defined string text value in a string properties layer");
- RNA_def_struct_path_func(srna, "rna_MeshStringProperty_path");
-
- /* low level mesh data access, treat as bytes */
- prop = RNA_def_property(srna, "value", PROP_STRING, PROP_BYTESTRING);
- RNA_def_property_string_sdna(prop, NULL, "s");
- RNA_def_property_string_funcs(prop, "rna_MeshStringProperty_s_get", "rna_MeshStringProperty_s_length", "rna_MeshStringProperty_s_set");
- RNA_def_property_ui_text(prop, "Value", "");
- RNA_def_property_update(prop, 0, "rna_Mesh_update_data");
}
void rna_def_texmat_common(StructRNA *srna, const char *texspace_editable)
@@ -2814,23 +2951,65 @@ static void rna_def_uv_layers(BlenderRNA *brna, PropertyRNA *cprop)
RNA_def_property_update(prop, 0, "rna_Mesh_update_data");
}
+/* mesh float layers */
+static void rna_def_vertex_float_layers(BlenderRNA *brna, PropertyRNA *cprop)
+{
+ StructRNA *srna;
+
+ FunctionRNA *func;
+ PropertyRNA *parm;
+
+ RNA_def_property_srna(cprop, "VertexFloatProperties");
+ srna = RNA_def_struct(brna, "VertexFloatProperties", NULL);
+ RNA_def_struct_sdna(srna, "Mesh");
+ RNA_def_struct_ui_text(srna, "Vertex Float Properties", "Collection of float properties");
+
+ func = RNA_def_function(srna, "new", "rna_Mesh_vertex_float_property_new");
+ RNA_def_function_ui_description(func, "Add a float property layer to Mesh");
+ RNA_def_string(func, "name", "Float Prop", 0, "", "Float property name");
+ parm = RNA_def_pointer(func, "layer", "MeshVertexFloatPropertyLayer", "", "The newly created layer");
+ RNA_def_property_flag(parm, PROP_RNAPTR);
+ RNA_def_function_return(func, parm);
+}
+
/* mesh int layers */
-static void rna_def_polygon_int_layers(BlenderRNA *brna, PropertyRNA *cprop)
+static void rna_def_vertex_int_layers(BlenderRNA *brna, PropertyRNA *cprop)
{
StructRNA *srna;
FunctionRNA *func;
PropertyRNA *parm;
- RNA_def_property_srna(cprop, "IntProperties");
- srna = RNA_def_struct(brna, "IntProperties", NULL);
+ RNA_def_property_srna(cprop, "VertexIntProperties");
+ srna = RNA_def_struct(brna, "VertexIntProperties", NULL);
RNA_def_struct_sdna(srna, "Mesh");
- RNA_def_struct_ui_text(srna, "Int Properties", "Collection of int properties");
+ RNA_def_struct_ui_text(srna, "Vertex Int Properties", "Collection of int properties");
- func = RNA_def_function(srna, "new", "rna_Mesh_polygon_int_property_new");
+ func = RNA_def_function(srna, "new", "rna_Mesh_vertex_int_property_new");
RNA_def_function_ui_description(func, "Add a integer property layer to Mesh");
RNA_def_string(func, "name", "Int Prop", 0, "", "Int property name");
- parm = RNA_def_pointer(func, "layer", "MeshIntPropertyLayer", "", "The newly created layer");
+ parm = RNA_def_pointer(func, "layer", "MeshVertexIntPropertyLayer", "", "The newly created layer");
+ RNA_def_property_flag(parm, PROP_RNAPTR);
+ RNA_def_function_return(func, parm);
+}
+
+/* mesh string layers */
+static void rna_def_vertex_string_layers(BlenderRNA *brna, PropertyRNA *cprop)
+{
+ StructRNA *srna;
+
+ FunctionRNA *func;
+ PropertyRNA *parm;
+
+ RNA_def_property_srna(cprop, "VertexStringProperties");
+ srna = RNA_def_struct(brna, "VertexStringProperties", NULL);
+ RNA_def_struct_sdna(srna, "Mesh");
+ RNA_def_struct_ui_text(srna, "Vertex String Properties", "Collection of string properties");
+
+ func = RNA_def_function(srna, "new", "rna_Mesh_vertex_string_property_new");
+ RNA_def_function_ui_description(func, "Add a string property layer to Mesh");
+ RNA_def_string(func, "name", "String Prop", 0, "", "String property name");
+ parm = RNA_def_pointer(func, "layer", "MeshVertexStringPropertyLayer", "", "The newly created layer");
RNA_def_property_flag(parm, PROP_RNAPTR);
RNA_def_function_return(func, parm);
}
@@ -2843,15 +3022,36 @@ static void rna_def_polygon_float_layers(BlenderRNA *brna, PropertyRNA *cprop)
FunctionRNA *func;
PropertyRNA *parm;
- RNA_def_property_srna(cprop, "FloatProperties");
- srna = RNA_def_struct(brna, "FloatProperties", NULL);
+ RNA_def_property_srna(cprop, "PolygonFloatProperties");
+ srna = RNA_def_struct(brna, "PolygonFloatProperties", NULL);
RNA_def_struct_sdna(srna, "Mesh");
- RNA_def_struct_ui_text(srna, "Float Properties", "Collection of float properties");
+ RNA_def_struct_ui_text(srna, "Polygon Float Properties", "Collection of float properties");
func = RNA_def_function(srna, "new", "rna_Mesh_polygon_float_property_new");
RNA_def_function_ui_description(func, "Add a float property layer to Mesh");
RNA_def_string(func, "name", "Float Prop", 0, "", "Float property name");
- parm = RNA_def_pointer(func, "layer", "MeshFloatPropertyLayer", "", "The newly created layer");
+ parm = RNA_def_pointer(func, "layer", "MeshPolygonFloatPropertyLayer", "", "The newly created layer");
+ RNA_def_property_flag(parm, PROP_RNAPTR);
+ RNA_def_function_return(func, parm);
+}
+
+/* mesh int layers */
+static void rna_def_polygon_int_layers(BlenderRNA *brna, PropertyRNA *cprop)
+{
+ StructRNA *srna;
+
+ FunctionRNA *func;
+ PropertyRNA *parm;
+
+ RNA_def_property_srna(cprop, "PolygonIntProperties");
+ srna = RNA_def_struct(brna, "PolygonIntProperties", NULL);
+ RNA_def_struct_sdna(srna, "Mesh");
+ RNA_def_struct_ui_text(srna, "Polygon Int Properties", "Collection of int properties");
+
+ func = RNA_def_function(srna, "new", "rna_Mesh_polygon_int_property_new");
+ RNA_def_function_ui_description(func, "Add a integer property layer to Mesh");
+ RNA_def_string(func, "name", "Int Prop", 0, "", "Int property name");
+ parm = RNA_def_pointer(func, "layer", "MeshPolygonIntPropertyLayer", "", "The newly created layer");
RNA_def_property_flag(parm, PROP_RNAPTR);
RNA_def_function_return(func, parm);
}
@@ -2864,15 +3064,15 @@ static void rna_def_polygon_string_layers(BlenderRNA *brna, PropertyRNA *cprop)
FunctionRNA *func;
PropertyRNA *parm;
- RNA_def_property_srna(cprop, "StringProperties");
- srna = RNA_def_struct(brna, "StringProperties", NULL);
+ RNA_def_property_srna(cprop, "PolygonStringProperties");
+ srna = RNA_def_struct(brna, "PolygonStringProperties", NULL);
RNA_def_struct_sdna(srna, "Mesh");
- RNA_def_struct_ui_text(srna, "String Properties", "Collection of string properties");
+ RNA_def_struct_ui_text(srna, "Polygon String Properties", "Collection of string properties");
func = RNA_def_function(srna, "new", "rna_Mesh_polygon_string_property_new");
RNA_def_function_ui_description(func, "Add a string property layer to Mesh");
RNA_def_string(func, "name", "String Prop", 0, "", "String property name");
- parm = RNA_def_pointer(func, "layer", "MeshStringPropertyLayer", "", "The newly created layer");
+ parm = RNA_def_pointer(func, "layer", "MeshPolygonStringPropertyLayer", "", "The newly created layer");
RNA_def_property_flag(parm, PROP_RNAPTR);
RNA_def_function_return(func, parm);
}
@@ -3005,6 +3205,36 @@ static void rna_def_skin_vertices(BlenderRNA *brna, PropertyRNA *UNUSED(cprop))
RNA_def_property_update(prop, 0, "rna_Mesh_update_data");
}
+static void rna_def_paint_mask(BlenderRNA *brna, PropertyRNA *UNUSED(cprop))
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ srna = RNA_def_struct(brna, "MeshPaintMaskLayer", NULL);
+ RNA_def_struct_ui_text(srna, "Mesh Paint Mask Layer", "Per-vertex paint mask data");
+ RNA_def_struct_sdna(srna, "CustomDataLayer");
+ RNA_def_struct_path_func(srna, "rna_MeshPaintMaskLayer_path");
+
+ prop = RNA_def_property(srna, "data", PROP_COLLECTION, PROP_NONE);
+ RNA_def_property_struct_type(prop, "MeshPaintMaskProperty");
+ RNA_def_property_ui_text(prop, "Data", "");
+
+ RNA_def_property_collection_funcs(prop, "rna_MeshPaintMaskLayer_data_begin", "rna_iterator_array_next",
+ "rna_iterator_array_end", "rna_iterator_array_get",
+ "rna_MeshPaintMaskLayer_data_length", NULL, NULL, NULL);
+
+ srna = RNA_def_struct(brna, "MeshPaintMaskProperty", NULL);
+ RNA_def_struct_sdna(srna, "MFloatProperty");
+ RNA_def_struct_ui_text(srna, "Mesh Paint Mask Property",
+ "Floating point paint mask value");
+ RNA_def_struct_path_func(srna, "rna_MeshPaintMask_path");
+
+ prop = RNA_def_property(srna, "value", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "f");
+ RNA_def_property_ui_text(prop, "Value", "");
+ RNA_def_property_update(prop, 0, "rna_Mesh_update_data");
+}
+
static void rna_def_mesh(BlenderRNA *brna)
{
StructRNA *srna;
@@ -3150,12 +3380,36 @@ static void rna_def_mesh(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Vertex Colors", "All vertex colors");
rna_def_loop_colors(brna, prop);
- /* TODO, vertex, edge customdata layers (bmesh py api can access already) */
+ /* TODO, edge customdata layers (bmesh py api can access already) */
+ prop = RNA_def_property(srna, "vertex_layers_float", PROP_COLLECTION, PROP_NONE);
+ RNA_def_property_collection_sdna(prop, NULL, "vdata.layers", "vdata.totlayer");
+ RNA_def_property_collection_funcs(prop, "rna_Mesh_vertex_float_layers_begin", NULL, NULL, NULL,
+ "rna_Mesh_vertex_float_layers_length", NULL, NULL, NULL);
+ RNA_def_property_struct_type(prop, "MeshVertexFloatPropertyLayer");
+ RNA_def_property_ui_text(prop, "Float Property Layers", "");
+ rna_def_vertex_float_layers(brna, prop);
+
+ prop = RNA_def_property(srna, "vertex_layers_int", PROP_COLLECTION, PROP_NONE);
+ RNA_def_property_collection_sdna(prop, NULL, "vdata.layers", "vdata.totlayer");
+ RNA_def_property_collection_funcs(prop, "rna_Mesh_vertex_int_layers_begin", NULL, NULL, NULL,
+ "rna_Mesh_vertex_int_layers_length", NULL, NULL, NULL);
+ RNA_def_property_struct_type(prop, "MeshVertexIntPropertyLayer");
+ RNA_def_property_ui_text(prop, "Int Property Layers", "");
+ rna_def_vertex_int_layers(brna, prop);
+
+ prop = RNA_def_property(srna, "vertex_layers_string", PROP_COLLECTION, PROP_NONE);
+ RNA_def_property_collection_sdna(prop, NULL, "vdata.layers", "vdata.totlayer");
+ RNA_def_property_collection_funcs(prop, "rna_Mesh_vertex_string_layers_begin", NULL, NULL, NULL,
+ "rna_Mesh_vertex_string_layers_length", NULL, NULL, NULL);
+ RNA_def_property_struct_type(prop, "MeshVertexStringPropertyLayer");
+ RNA_def_property_ui_text(prop, "String Property Layers", "");
+ rna_def_vertex_string_layers(brna, prop);
+
prop = RNA_def_property(srna, "polygon_layers_float", PROP_COLLECTION, PROP_NONE);
RNA_def_property_collection_sdna(prop, NULL, "pdata.layers", "pdata.totlayer");
RNA_def_property_collection_funcs(prop, "rna_Mesh_polygon_float_layers_begin", NULL, NULL, NULL,
"rna_Mesh_polygon_float_layers_length", NULL, NULL, NULL);
- RNA_def_property_struct_type(prop, "MeshFloatPropertyLayer");
+ RNA_def_property_struct_type(prop, "MeshPolygonFloatPropertyLayer");
RNA_def_property_ui_text(prop, "Float Property Layers", "");
rna_def_polygon_float_layers(brna, prop);
@@ -3163,7 +3417,7 @@ static void rna_def_mesh(BlenderRNA *brna)
RNA_def_property_collection_sdna(prop, NULL, "pdata.layers", "pdata.totlayer");
RNA_def_property_collection_funcs(prop, "rna_Mesh_polygon_int_layers_begin", NULL, NULL, NULL,
"rna_Mesh_polygon_int_layers_length", NULL, NULL, NULL);
- RNA_def_property_struct_type(prop, "MeshIntPropertyLayer");
+ RNA_def_property_struct_type(prop, "MeshPolygonIntPropertyLayer");
RNA_def_property_ui_text(prop, "Int Property Layers", "");
rna_def_polygon_int_layers(brna, prop);
@@ -3171,7 +3425,7 @@ static void rna_def_mesh(BlenderRNA *brna)
RNA_def_property_collection_sdna(prop, NULL, "pdata.layers", "pdata.totlayer");
RNA_def_property_collection_funcs(prop, "rna_Mesh_polygon_string_layers_begin", NULL, NULL, NULL,
"rna_Mesh_polygon_string_layers_length", NULL, NULL, NULL);
- RNA_def_property_struct_type(prop, "MeshStringPropertyLayer");
+ RNA_def_property_struct_type(prop, "MeshPolygonStringPropertyLayer");
RNA_def_property_ui_text(prop, "String Property Layers", "");
rna_def_polygon_string_layers(brna, prop);
@@ -3185,11 +3439,21 @@ static void rna_def_mesh(BlenderRNA *brna)
rna_def_skin_vertices(brna, prop);
/* End skin vertices */
+ /* Paint mask */
+ prop = RNA_def_property(srna, "vertex_paint_masks", PROP_COLLECTION, PROP_NONE);
+ RNA_def_property_collection_sdna(prop, NULL, "vdata.layers", "vdata.totlayer");
+ RNA_def_property_collection_funcs(prop, "rna_Mesh_vertex_paint_masks_begin", NULL, NULL, NULL,
+ "rna_Mesh_vertex_paint_masks_length", NULL, NULL, NULL);
+ RNA_def_property_struct_type(prop, "MeshPaintMaskLayer");
+ RNA_def_property_ui_text(prop, "Vertex Paint Mask", "Vertex paint mask");
+ rna_def_paint_mask(brna, prop);
+ /* End paint mask */
+
prop = RNA_def_property(srna, "use_auto_smooth", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", ME_AUTOSMOOTH);
RNA_def_property_ui_text(prop, "Auto Smooth",
- "Treat all set-smoothed faces with angles less than the specified angle "
- "as 'smooth', unless they are linked by a sharp edge");
+ "Auto smooth (based on smooth/sharp faces/edges and angle between faces), "
+ "or use custom split normals data if available");
RNA_def_property_update(prop, 0, "rna_Mesh_update_data");
prop = RNA_def_property(srna, "auto_smooth_angle", PROP_FLOAT, PROP_ANGLE);
@@ -3198,12 +3462,22 @@ static void rna_def_mesh(BlenderRNA *brna)
RNA_def_property_range(prop, 0.0f, DEG2RADF(180.0f));
RNA_def_property_ui_range(prop, DEG2RADF(0.0f), DEG2RADF(180.0f), 1.0, 1);
RNA_def_property_ui_text(prop, "Auto Smooth Angle",
- "Maximum angle between face normals that 'Auto Smooth' will operate on");
+ "Maximum angle between face normals that will be considered as smooth "
+ "(unused if custom split normals data are available)");
RNA_def_property_update(prop, 0, "rna_Mesh_update_data");
+ RNA_define_verify_sdna(false);
+ prop = RNA_def_property(srna, "has_custom_normals", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "", 0);
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_property_ui_text(prop, "Has Custom Normals",
+ "True if there are custom split normals data in this mesh");
+ RNA_def_property_boolean_funcs(prop, "rna_Mesh_has_custom_normals_get", NULL);
+ RNA_define_verify_sdna(true);
+
prop = RNA_def_property(srna, "show_double_sided", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", ME_TWOSIDED);
- RNA_def_property_ui_text(prop, "Double Sided", "Render/display the mesh with double or single sided lighting");
+ RNA_def_property_ui_text(prop, "Double Sided", "Display the mesh with double or single sided lighting (OpenGL only)");
RNA_def_property_update(prop, 0, "rna_Mesh_update_data");
prop = RNA_def_property(srna, "texco_mesh", PROP_POINTER, PROP_NONE);
diff --git a/source/blender/makesrna/intern/rna_mesh_api.c b/source/blender/makesrna/intern/rna_mesh_api.c
index cc1f57d8a14..632b07c19ce 100644
--- a/source/blender/makesrna/intern/rna_mesh_api.c
+++ b/source/blender/makesrna/intern/rna_mesh_api.c
@@ -61,40 +61,12 @@ static const char *rna_Mesh_unit_test_compare(struct Mesh *mesh, struct Mesh *me
return ret;
}
-static void rna_Mesh_calc_normals_split(Mesh *mesh, float min_angle)
+static void rna_Mesh_create_normals_split(Mesh *mesh)
{
- float (*r_loopnors)[3];
- float (*polynors)[3];
- bool free_polynors = false;
-
- if (CustomData_has_layer(&mesh->ldata, CD_NORMAL)) {
- r_loopnors = CustomData_get_layer(&mesh->ldata, CD_NORMAL);
- memset(r_loopnors, 0, sizeof(float[3]) * mesh->totloop);
- }
- else {
- r_loopnors = CustomData_add_layer(&mesh->ldata, CD_NORMAL, CD_CALLOC, NULL, mesh->totloop);
+ if (!CustomData_has_layer(&mesh->ldata, CD_NORMAL)) {
+ CustomData_add_layer(&mesh->ldata, CD_NORMAL, CD_CALLOC, NULL, mesh->totloop);
CustomData_set_layer_flag(&mesh->ldata, CD_NORMAL, CD_FLAG_TEMPORARY);
}
-
- if (CustomData_has_layer(&mesh->pdata, CD_NORMAL)) {
- /* This assume that layer is always up to date, not sure this is the case (esp. in Edit mode?)... */
- polynors = CustomData_get_layer(&mesh->pdata, CD_NORMAL);
- free_polynors = false;
- }
- else {
- polynors = MEM_mallocN(sizeof(float[3]) * mesh->totpoly, __func__);
- BKE_mesh_calc_normals_poly(mesh->mvert, mesh->totvert, mesh->mloop, mesh->mpoly, mesh->totloop, mesh->totpoly,
- polynors, false);
- free_polynors = true;
- }
-
- BKE_mesh_normals_loop_split(mesh->mvert, mesh->totvert, mesh->medge, mesh->totedge,
- mesh->mloop, r_loopnors, mesh->totloop, mesh->mpoly, polynors, mesh->totpoly,
- min_angle);
-
- if (free_polynors) {
- MEM_freeN(polynors);
- }
}
static void rna_Mesh_free_normals_split(Mesh *mesh)
@@ -117,7 +89,7 @@ static void rna_Mesh_calc_tangents(Mesh *mesh, ReportList *reports, const char *
/* Compute loop normals if needed. */
if (!CustomData_has_layer(&mesh->ldata, CD_NORMAL)) {
- rna_Mesh_calc_normals_split(mesh, (float)M_PI);
+ BKE_mesh_calc_normals_split(mesh);
}
BKE_mesh_loop_tangents(mesh, uvmap, r_looptangents, reports);
@@ -128,6 +100,11 @@ static void rna_Mesh_free_tangents(Mesh *mesh)
CustomData_free_layers(&mesh->ldata, CD_MLOOPTANGENT, mesh->totloop);
}
+static void rna_Mesh_calc_tessface(Mesh *mesh, int free_mpoly)
+{
+ ED_mesh_calc_tessface(mesh, free_mpoly != 0);
+}
+
static void rna_Mesh_calc_smooth_groups(Mesh *mesh, int use_bitflags, int *r_poly_group_len,
int **r_poly_group, int *r_group_total)
{
@@ -139,6 +116,82 @@ static void rna_Mesh_calc_smooth_groups(Mesh *mesh, int use_bitflags, int *r_pol
r_group_total, use_bitflags);
}
+static void rna_Mesh_normals_split_custom_do(Mesh *mesh, float (*custom_loopnors)[3], const bool use_vertices)
+{
+ float (*polynors)[3];
+ short (*clnors)[2];
+ const int numloops = mesh->totloop;
+ bool free_polynors = false;
+
+ clnors = CustomData_get_layer(&mesh->ldata, CD_CUSTOMLOOPNORMAL);
+ if (clnors) {
+ memset(clnors, 0, sizeof(*clnors) * numloops);
+ }
+ else {
+ clnors = CustomData_add_layer(&mesh->ldata, CD_CUSTOMLOOPNORMAL, CD_DEFAULT, NULL, numloops);
+ }
+
+ if (CustomData_has_layer(&mesh->pdata, CD_NORMAL)) {
+ polynors = CustomData_get_layer(&mesh->pdata, CD_NORMAL);
+ }
+ else {
+ polynors = MEM_mallocN(sizeof(float[3]) * mesh->totpoly, __func__);
+ BKE_mesh_calc_normals_poly(mesh->mvert, mesh->totvert, mesh->mloop, mesh->mpoly, mesh->totloop, mesh->totpoly,
+ polynors, false);
+ free_polynors = true;
+ }
+
+ if (use_vertices) {
+ BKE_mesh_normals_loop_custom_from_vertices_set(
+ mesh->mvert, custom_loopnors, mesh->totvert, mesh->medge, mesh->totedge, mesh->mloop, mesh->totloop,
+ mesh->mpoly, (const float (*)[3])polynors, mesh->totpoly, clnors);
+ }
+ else {
+ BKE_mesh_normals_loop_custom_set(
+ mesh->mvert, mesh->totvert, mesh->medge, mesh->totedge, mesh->mloop, custom_loopnors, mesh->totloop,
+ mesh->mpoly, (const float (*)[3])polynors, mesh->totpoly, clnors);
+ }
+
+ if (free_polynors) {
+ MEM_freeN(polynors);
+ }
+}
+
+static void rna_Mesh_normals_split_custom_set(Mesh *mesh, ReportList *reports, int normals_len, float *normals)
+{
+ float (*loopnors)[3] = (float (*)[3])normals;
+ const int numloops = mesh->totloop;
+
+ if (normals_len != numloops * 3) {
+ BKE_reportf(reports, RPT_ERROR,
+ "Number of custom normals is not number of loops (%f / %d)",
+ (float)normals_len / 3.0f, numloops);
+ return;
+ }
+
+ rna_Mesh_normals_split_custom_do(mesh, loopnors, false);
+
+ DAG_id_tag_update(&mesh->id, 0);
+}
+
+static void rna_Mesh_normals_split_custom_set_from_vertices(
+ Mesh *mesh, ReportList *reports, int normals_len, float *normals)
+{
+ float (*vertnors)[3] = (float (*)[3])normals;
+ const int numverts = mesh->totvert;
+
+ if (normals_len != numverts * 3) {
+ BKE_reportf(reports, RPT_ERROR,
+ "Number of custom normals is not number of vertices (%f / %d)",
+ (float)normals_len / 3.0f, numverts);
+ return;
+ }
+
+ rna_Mesh_normals_split_custom_do(mesh, vertnors, true);
+
+ DAG_id_tag_update(&mesh->id, 0);
+}
+
static void rna_Mesh_transform(Mesh *mesh, float *mat, int shape_keys)
{
BKE_mesh_transform(mesh, (float (*)[4])mat, shape_keys);
@@ -152,6 +205,7 @@ void RNA_api_mesh(StructRNA *srna)
{
FunctionRNA *func;
PropertyRNA *parm;
+ const int normals_array_dim[] = {1, 3};
func = RNA_def_function(srna, "transform", "rna_Mesh_transform");
RNA_def_function_ui_description(func, "Transform mesh vertices by a matrix");
@@ -162,12 +216,11 @@ void RNA_api_mesh(StructRNA *srna)
func = RNA_def_function(srna, "calc_normals", "BKE_mesh_calc_normals");
RNA_def_function_ui_description(func, "Calculate vertex normals");
- func = RNA_def_function(srna, "calc_normals_split", "rna_Mesh_calc_normals_split");
+ func = RNA_def_function(srna, "create_normals_split", "rna_Mesh_create_normals_split");
+ RNA_def_function_ui_description(func, "Empty split vertex normals");
+
+ func = RNA_def_function(srna, "calc_normals_split", "BKE_mesh_calc_normals_split");
RNA_def_function_ui_description(func, "Calculate split vertex normals, which preserve sharp edges");
- parm = RNA_def_float(func, "split_angle", M_PI, 0.0f, M_PI, "",
- "Angle between polys' normals above which an edge is always sharp (180° to disable)",
- 0.0f, M_PI);
- RNA_def_property_subtype(parm, (PropertySubType)PROP_UNIT_ROTATION);
func = RNA_def_function(srna, "free_normals_split", "rna_Mesh_free_normals_split");
RNA_def_function_ui_description(func, "Free split vertex normals");
@@ -184,8 +237,12 @@ void RNA_api_mesh(StructRNA *srna)
func = RNA_def_function(srna, "free_tangents", "rna_Mesh_free_tangents");
RNA_def_function_ui_description(func, "Free tangents");
- func = RNA_def_function(srna, "calc_tessface", "ED_mesh_calc_tessface");
+ func = RNA_def_function(srna, "calc_tessface", "rna_Mesh_calc_tessface");
RNA_def_function_ui_description(func, "Calculate face tessellation (supports editmode too)");
+ RNA_def_boolean(func, "free_mpoly", 0, "Free MPoly", "Free data used by polygons and loops. "
+ "WARNING: This destructive operation removes regular faces, "
+ "only used on temporary mesh data-blocks to reduce memory footprint of render "
+ "engines and export scripts");
func = RNA_def_function(srna, "calc_smooth_groups", "rna_Mesh_calc_smooth_groups");
RNA_def_function_ui_description(func, "Calculate smooth groups from sharp edges");
@@ -196,6 +253,26 @@ void RNA_api_mesh(StructRNA *srna)
parm = RNA_def_int(func, "groups", 0, 0, INT_MAX, "groups", "Total number of groups", 0, INT_MAX);
RNA_def_property_flag(parm, PROP_OUTPUT);
+ func = RNA_def_function(srna, "normals_split_custom_set", "rna_Mesh_normals_split_custom_set");
+ RNA_def_function_ui_description(func,
+ "Define custom split normals of this mesh "
+ "(use zero-vectors to keep auto ones)");
+ RNA_def_function_flag(func, FUNC_USE_REPORTS);
+ /* TODO, see how array size of 0 works, this shouldnt be used */
+ parm = RNA_def_float_array(func, "normals", 1, NULL, -1.0f, 1.0f, "", "Normals", 0.0f, 0.0f);
+ RNA_def_property_multi_array(parm, 2, normals_array_dim);
+ RNA_def_property_flag(parm, PROP_DYNAMIC | PROP_REQUIRED);
+
+ func = RNA_def_function(srna, "normals_split_custom_set_from_vertices",
+ "rna_Mesh_normals_split_custom_set_from_vertices");
+ RNA_def_function_ui_description(func,
+ "Define custom split normals of this mesh, from vertices' normals "
+ "(use zero-vectors to keep auto ones)");
+ RNA_def_function_flag(func, FUNC_USE_REPORTS);
+ /* TODO, see how array size of 0 works, this shouldnt be used */
+ parm = RNA_def_float_array(func, "normals", 1, NULL, -1.0f, 1.0f, "", "Normals", 0.0f, 0.0f);
+ RNA_def_property_multi_array(parm, 2, normals_array_dim);
+ RNA_def_property_flag(parm, PROP_DYNAMIC | PROP_REQUIRED);
func = RNA_def_function(srna, "update", "ED_mesh_update");
RNA_def_boolean(func, "calc_edges", 0, "Calculate Edges", "Force recalculation of edges");
@@ -211,7 +288,9 @@ void RNA_api_mesh(StructRNA *srna)
func = RNA_def_function(srna, "validate", "BKE_mesh_validate");
RNA_def_function_ui_description(func, "Validate geometry, return True when the mesh has had "
"invalid geometry corrected/removed");
- RNA_def_boolean(func, "verbose", 0, "Verbose", "Output information about the errors found");
+ RNA_def_boolean(func, "verbose", false, "Verbose", "Output information about the errors found");
+ RNA_def_boolean(func, "clean_customdata", true, "Clean Custom Data",
+ "Remove temp/cached custom-data layers, like e.g. normals...");
parm = RNA_def_boolean(func, "result", 0, "Result", "");
RNA_def_function_return(func, parm);
diff --git a/source/blender/makesrna/intern/rna_mesh_utils.h b/source/blender/makesrna/intern/rna_mesh_utils.h
index c0ea1a153ff..0f42596ff13 100644
--- a/source/blender/makesrna/intern/rna_mesh_utils.h
+++ b/source/blender/makesrna/intern/rna_mesh_utils.h
@@ -20,7 +20,7 @@
* ***** END GPL LICENSE BLOCK *****
*/
-/** \file blender/source/blender/makesrna/intern/rna_mesh_utils.h
+/** \file blender/makesrna/intern/rna_mesh_utils.h
* \ingroup RNA
*/
@@ -81,7 +81,7 @@
CustomDataLayer *layer; \
if (data) { \
int index = CustomData_get_##active_type##_layer_index(data, layer_type); \
- layer = (index == -1) ? NULL: &data->layers[index]; \
+ layer = (index == -1) ? NULL : &data->layers[index]; \
} \
else { \
layer = NULL; \
diff --git a/source/blender/makesrna/intern/rna_modifier.c b/source/blender/makesrna/intern/rna_modifier.c
index 4911c106f53..27c4bf0e985 100644
--- a/source/blender/makesrna/intern/rna_modifier.c
+++ b/source/blender/makesrna/intern/rna_modifier.c
@@ -40,13 +40,19 @@
#include "BLI_math.h"
-#include "BLF_translation.h"
+#include "BLT_translation.h"
#include "BKE_animsys.h"
+#include "BKE_data_transfer.h"
+#include "BKE_DerivedMesh.h"
#include "BKE_dynamicpaint.h"
+#include "BKE_effect.h"
+#include "BKE_mesh_mapping.h"
+#include "BKE_mesh_remap.h"
#include "BKE_multires.h"
#include "BKE_smoke.h" /* For smokeModifier_free & smokeModifier_createType */
+#include "RNA_access.h"
#include "RNA_define.h"
#include "RNA_enum_types.h"
@@ -57,7 +63,9 @@
EnumPropertyItem modifier_type_items[] = {
{0, "", 0, N_("Modify"), ""},
+ {eModifierType_DataTransfer, "DATA_TRANSFER", ICON_MOD_DATA_TRANSFER, "Data Transfer", ""},
{eModifierType_MeshCache, "MESH_CACHE", ICON_MOD_MESHDEFORM, "Mesh Cache", ""},
+ {eModifierType_NormalEdit, "NORMAL_EDIT", ICON_MOD_NORMALEDIT, "Normal Edit", ""},
{eModifierType_UVProject, "UV_PROJECT", ICON_MOD_UVPROJECT, "UV Project", ""},
{eModifierType_UVWarp, "UV_WARP", ICON_MOD_UVPROJECT, "UV Warp", ""},
{eModifierType_WeightVGEdit, "VERTEX_WEIGHT_EDIT", ICON_MOD_VERTEX_WEIGHT, "Vertex Weight Edit", ""},
@@ -84,6 +92,7 @@ EnumPropertyItem modifier_type_items[] = {
{0, "", 0, N_("Deform"), ""},
{eModifierType_Armature, "ARMATURE", ICON_MOD_ARMATURE, "Armature", ""},
{eModifierType_Cast, "CAST", ICON_MOD_CAST, "Cast", ""},
+ {eModifierType_CorrectiveSmooth, "CORRECTIVE_SMOOTH", ICON_MOD_SMOOTH, "Corrective Smooth", ""},
{eModifierType_Curve, "CURVE", ICON_MOD_CURVE, "Curve", ""},
{eModifierType_Displace, "DISPLACE", ICON_MOD_DISPLACE, "Displace", ""},
{eModifierType_Hook, "HOOK", ICON_HOOK, "Hook", ""},
@@ -127,9 +136,130 @@ EnumPropertyItem modifier_triangulate_ngon_method_items[] = {
{0, NULL, 0, NULL, NULL}
};
+#ifndef RNA_RUNTIME
+/* use eWarp_Falloff_*** & eHook_Falloff_***, they're in sync */
+static EnumPropertyItem modifier_warp_falloff_items[] = {
+ {eWarp_Falloff_None, "NONE", 0, "No Falloff", ""},
+ {eWarp_Falloff_Curve, "CURVE", 0, "Curve", ""},
+ {eWarp_Falloff_Smooth, "SMOOTH", ICON_SMOOTHCURVE, "Smooth", ""},
+ {eWarp_Falloff_Sphere, "SPHERE", ICON_SPHERECURVE, "Sphere", ""},
+ {eWarp_Falloff_Root, "ROOT", ICON_ROOTCURVE, "Root", ""},
+ {eWarp_Falloff_InvSquare, "INVERSE_SQUARE", ICON_ROOTCURVE, "Inverse Square", ""},
+ {eWarp_Falloff_Sharp, "SHARP", ICON_SHARPCURVE, "Sharp", ""},
+ {eWarp_Falloff_Linear, "LINEAR", ICON_LINCURVE, "Linear", ""},
+ {eWarp_Falloff_Const, "CONSTANT", ICON_NOCURVE, "Constant", ""},
+ {0, NULL, 0, NULL, NULL}
+};
+#endif
+
+/* ***** Data Transfer ***** */
+
+EnumPropertyItem DT_method_vertex_items[] = {
+ {MREMAP_MODE_TOPOLOGY, "TOPOLOGY", 0, "Topology",
+ "Copy from identical topology meshes"},
+ {MREMAP_MODE_VERT_NEAREST, "NEAREST", 0, "Nearest vertex",
+ "Copy from closest vertex"},
+ {MREMAP_MODE_VERT_EDGE_NEAREST, "EDGE_NEAREST", 0, "Nearest Edge Vertex",
+ "Copy from closest vertex of closest edge"},
+ {MREMAP_MODE_VERT_EDGEINTERP_NEAREST, "EDGEINTERP_NEAREST", 0, "Nearest Edge Interpolated",
+ "Copy from interpolated values of vertices from closest point on closest edge"},
+ {MREMAP_MODE_VERT_POLY_NEAREST, "POLY_NEAREST", 0, "Nearest Face Vertex",
+ "Copy from closest vertex of closest face"},
+ {MREMAP_MODE_VERT_POLYINTERP_NEAREST, "POLYINTERP_NEAREST", 0, "Nearest Face Interpolated",
+ "Copy from interpolated values of vertices from closest point on closest face"},
+ {MREMAP_MODE_VERT_POLYINTERP_VNORPROJ, "POLYINTERP_VNORPROJ", 0, "Projected Face Interpolated",
+ "Copy from interpolated values of vertices from point on closest face hit by normal-projection"},
+ {0, NULL, 0, NULL, NULL}
+};
+
+EnumPropertyItem DT_method_edge_items[] = {
+ {MREMAP_MODE_TOPOLOGY, "TOPOLOGY", 0, "Topology",
+ "Copy from identical topology meshes"},
+ {MREMAP_MODE_EDGE_VERT_NEAREST, "VERT_NEAREST", 0, "Nearest Vertices",
+ "Copy from most similar edge (edge which vertices are the closest of destination edge’s ones)"},
+ {MREMAP_MODE_EDGE_NEAREST, "NEAREST", 0, "Nearest Edge",
+ "Copy from closest edge (using midpoints)"},
+ {MREMAP_MODE_EDGE_POLY_NEAREST, "POLY_NEAREST", 0, "Nearest Face Edge",
+ "Copy from closest edge of closest face (using midpoints)"},
+ {MREMAP_MODE_EDGE_EDGEINTERP_VNORPROJ, "EDGEINTERP_VNORPROJ", 0, "Projected Edge Interpolated",
+ "Interpolate all source edges hit by the projection of destination one along its own normal (from vertices)"},
+ {0, NULL, 0, NULL, NULL}
+};
+
+EnumPropertyItem DT_method_loop_items[] = {
+ {MREMAP_MODE_TOPOLOGY, "TOPOLOGY", 0, "Topology",
+ "Copy from identical topology meshes"},
+ {MREMAP_MODE_LOOP_NEAREST_LOOPNOR, "NEAREST_NORMAL", 0, "Nearest Corner And Best Matching Normal",
+ "Copy from nearest corner which has the best matching normal"},
+ {MREMAP_MODE_LOOP_NEAREST_POLYNOR, "NEAREST_POLYNOR", 0, "Nearest Corner And Best Matching Face Normal",
+ "Copy from nearest corner which has the face with the best matching normal to destination corner's face one"},
+ {MREMAP_MODE_LOOP_POLY_NEAREST, "NEAREST_POLY", 0, "Nearest Corner Of Nearest Face",
+ "Copy from nearest corner of nearest polygon"},
+ {MREMAP_MODE_LOOP_POLYINTERP_NEAREST, "POLYINTERP_NEAREST", 0, "Nearest Face Interpolated",
+ "Copy from interpolated corners of the nearest source polygon"},
+ {MREMAP_MODE_LOOP_POLYINTERP_LNORPROJ, "POLYINTERP_LNORPROJ", 0, "Projected Face Interpolated",
+ "Copy from interpolated corners of the source polygon hit by corner normal projection"},
+ {0, NULL, 0, NULL, NULL}
+};
+
+EnumPropertyItem DT_method_poly_items[] = {
+ {MREMAP_MODE_TOPOLOGY, "TOPOLOGY", 0, "Topology",
+ "Copy from identical topology meshes"},
+ {MREMAP_MODE_POLY_NEAREST, "NEAREST", 0, "Nearest Face",
+ "Copy from nearest polygon (using center points)"},
+ {MREMAP_MODE_POLY_NOR, "NORMAL", 0, "Best Normal-Matching",
+ "Copy from source polygon which normal is the closest to destination one"},
+ {MREMAP_MODE_POLY_POLYINTERP_PNORPROJ, "POLYINTERP_PNORPROJ", 0, "Projected Face Interpolated",
+ "Interpolate all source polygons intersected by the projection of destination one along its own normal"},
+ {0, NULL, 0, NULL, NULL}
+};
+
+EnumPropertyItem DT_mix_mode_items[] = {
+ {CDT_MIX_TRANSFER, "REPLACE", 0, "Replace",
+ "Overwrite all elements' data"},
+ {CDT_MIX_REPLACE_ABOVE_THRESHOLD, "ABOVE_THRESHOLD", 0, "Above Threshold",
+ "Only replace destination elements where data is above given threshold (exact behavior depends on data type)"},
+ {CDT_MIX_REPLACE_BELOW_THRESHOLD, "BELOW_THRESHOLD", 0, "Below Threshold",
+ "Only replace destination elements where data is below given threshold (exact behavior depends on data type)"},
+ {CDT_MIX_MIX, "MIX", 0, "Mix",
+ "Mix source value into destination one, using given threshold as factor"},
+ {CDT_MIX_ADD, "ADD", 0, "Add",
+ "Add source value to destination one, using given threshold as factor"},
+ {CDT_MIX_SUB, "SUB", 0, "Subtract",
+ "Subtract source value to destination one, using given threshold as factor"},
+ {CDT_MIX_MUL, "MUL", 0, "Multiply",
+ "Multiply source value to destination one, using given threshold as factor"},
+ /* etc. etc. */
+ {0, NULL, 0, NULL, NULL}
+};
+
+EnumPropertyItem DT_layers_select_src_items[] = {
+ {DT_LAYERS_ACTIVE_SRC, "ACTIVE", 0, "Active Layer",
+ "Only transfer active data layer"},
+ {DT_LAYERS_ALL_SRC, "ALL", 0, "All Layers",
+ "Transfer all data layers"},
+ {DT_LAYERS_VGROUP_SRC_BONE_SELECT, "BONE_SELECT", 0, "Selected Pose Bones",
+ "Transfer all vertex groups used by selected pose bones"},
+ {DT_LAYERS_VGROUP_SRC_BONE_DEFORM, "BONE_DEFORM", 0, "Deform Pose Bones",
+ "Transfer all vertex groups used by deform bones"},
+ {0, NULL, 0, NULL, NULL}
+};
+
+EnumPropertyItem DT_layers_select_dst_items[] = {
+ {DT_LAYERS_ACTIVE_DST, "ACTIVE", 0, "Active Layer",
+ "Affect active data layer of all targets"},
+ {DT_LAYERS_NAME_DST, "NAME", 0, "By Name",
+ "Match target data layers to affect by name"},
+ {DT_LAYERS_INDEX_DST, "INDEX", 0, "By Order",
+ "Match target data layers to affect by order (indices)"},
+ {0, NULL, 0, NULL, NULL}
+};
+
+
#ifdef RNA_RUNTIME
#include "DNA_particle_types.h"
+#include "DNA_curve_types.h"
#include "DNA_smoke_types.h"
#include "BKE_context.h"
@@ -244,6 +374,12 @@ static StructRNA *rna_Modifier_refine(struct PointerRNA *ptr)
return &RNA_LaplacianDeformModifier;
case eModifierType_Wireframe:
return &RNA_WireframeModifier;
+ case eModifierType_DataTransfer:
+ return &RNA_DataTransferModifier;
+ case eModifierType_NormalEdit:
+ return &RNA_NormalEditModifier;
+ case eModifierType_CorrectiveSmooth:
+ return &RNA_CorrectiveSmoothModifier;
/* Default */
case eModifierType_None:
case eModifierType_ShapeKey:
@@ -272,7 +408,7 @@ static void rna_Modifier_name_set(PointerRNA *ptr, const char *value)
}
/* fix all the animation data which may link to this */
- BKE_all_animdata_fix_paths_rename(NULL, "modifiers", oldname, md->name);
+ BKE_animdata_fix_paths_rename_all(NULL, "modifiers", oldname, md->name);
}
static char *rna_Modifier_path(PointerRNA *ptr)
@@ -309,7 +445,9 @@ RNA_MOD_VGROUP_NAME_SET(Armature, defgrp_name);
RNA_MOD_VGROUP_NAME_SET(Bevel, defgrp_name);
RNA_MOD_VGROUP_NAME_SET(Cast, defgrp_name);
RNA_MOD_VGROUP_NAME_SET(Curve, name);
+RNA_MOD_VGROUP_NAME_SET(DataTransfer, defgrp_name);
RNA_MOD_VGROUP_NAME_SET(Decimate, defgrp_name);
+RNA_MOD_VGROUP_NAME_SET(CorrectiveSmooth, defgrp_name);
RNA_MOD_VGROUP_NAME_SET(Displace, defgrp_name);
RNA_MOD_VGROUP_NAME_SET(Hook, name);
RNA_MOD_VGROUP_NAME_SET(LaplacianDeform, anchor_grp_name);
@@ -317,6 +455,7 @@ RNA_MOD_VGROUP_NAME_SET(LaplacianSmooth, defgrp_name);
RNA_MOD_VGROUP_NAME_SET(Lattice, name);
RNA_MOD_VGROUP_NAME_SET(Mask, vgroup);
RNA_MOD_VGROUP_NAME_SET(MeshDeform, defgrp_name);
+RNA_MOD_VGROUP_NAME_SET(NormalEdit, defgrp_name);
RNA_MOD_VGROUP_NAME_SET(Shrinkwrap, vgroup_name);
RNA_MOD_VGROUP_NAME_SET(SimpleDeform, vgroup_name);
RNA_MOD_VGROUP_NAME_SET(Smooth, defgrp_name);
@@ -399,9 +538,11 @@ RNA_MOD_OBJECT_SET(Array, curve_ob, OB_CURVE);
RNA_MOD_OBJECT_SET(Boolean, object, OB_MESH);
RNA_MOD_OBJECT_SET(Cast, object, OB_EMPTY);
RNA_MOD_OBJECT_SET(Curve, object, OB_CURVE);
+RNA_MOD_OBJECT_SET(DataTransfer, ob_source, OB_MESH);
RNA_MOD_OBJECT_SET(Lattice, object, OB_LATTICE);
RNA_MOD_OBJECT_SET(Mask, ob_arm, OB_ARMATURE);
RNA_MOD_OBJECT_SET(MeshDeform, object, OB_MESH);
+RNA_MOD_OBJECT_SET(NormalEdit, target, OB_EMPTY);
RNA_MOD_OBJECT_SET(Shrinkwrap, target, OB_MESH);
RNA_MOD_OBJECT_SET(Shrinkwrap, auxTarget, OB_MESH);
@@ -495,7 +636,7 @@ static void rna_MultiresModifier_filepath_set(PointerRNA *ptr, const char *value
Object *ob = (Object *)ptr->id.data;
CustomDataExternal *external = ((Mesh *)ob->data)->ldata.external;
- if (external && strcmp(external->filename, value)) {
+ if (external && !STREQ(external->filename, value)) {
BLI_strncpy(external->filename, value, sizeof(external->filename));
multires_force_external_reload(ob);
}
@@ -604,6 +745,326 @@ static int rna_LaplacianDeformModifier_is_bind_get(PointerRNA *ptr)
return ((lmd->flag & MOD_LAPLACIANDEFORM_BIND) && (lmd->cache_system != NULL));
}
+/* NOTE: Curve and array modifiers requires curve path to be evaluated,
+ * dependency graph will make sure that curve eval would create such a path,
+ * but if curve was already evaluated we might miss path.
+ *
+ * So what we do here is: if path was not calculated for target curve we
+ * tag it for update.
+ */
+
+static void rna_CurveModifier_dependency_update(Main *bmain, Scene *scene, PointerRNA *ptr)
+{
+ CurveModifierData *cmd = (CurveModifierData *)ptr->data;
+ rna_Modifier_update(bmain, scene, ptr);
+ DAG_relations_tag_update(bmain);
+ if (cmd->object != NULL) {
+ Curve *curve = cmd->object->data;
+ if ((curve->flag & CU_PATH) == 0) {
+ DAG_id_tag_update(&curve->id, OB_RECALC_DATA);
+ }
+ }
+}
+
+static void rna_ArrayModifier_dependency_update(Main *bmain, Scene *scene, PointerRNA *ptr)
+{
+ ArrayModifierData *amd = (ArrayModifierData *)ptr->data;
+ rna_Modifier_update(bmain, scene, ptr);
+ DAG_relations_tag_update(bmain);
+ if (amd->curve_ob != NULL) {
+ Curve *curve = amd->curve_ob->data;
+ if ((curve->flag & CU_PATH) == 0) {
+ DAG_id_tag_update(&curve->id, OB_RECALC_DATA);
+ }
+ }
+}
+
+
+static void rna_DataTransferModifier_use_data_update(Main *bmain, Scene *scene, PointerRNA *ptr)
+{
+ DataTransferModifierData *dtmd = (DataTransferModifierData *)ptr->data;
+
+ if (!(dtmd->flags & MOD_DATATRANSFER_USE_VERT)) {
+ dtmd->data_types &= ~DT_TYPE_VERT_ALL;
+ }
+ if (!(dtmd->flags & MOD_DATATRANSFER_USE_EDGE)) {
+ dtmd->data_types &= ~DT_TYPE_EDGE_ALL;
+ }
+ if (!(dtmd->flags & MOD_DATATRANSFER_USE_LOOP)) {
+ dtmd->data_types &= ~DT_TYPE_LOOP_ALL;
+ }
+ if (!(dtmd->flags & MOD_DATATRANSFER_USE_POLY)) {
+ dtmd->data_types &= ~DT_TYPE_POLY_ALL;
+ }
+
+ rna_Modifier_update(bmain, scene, ptr);
+}
+
+static void rna_DataTransferModifier_data_types_update(Main *bmain, Scene *scene, PointerRNA *ptr)
+{
+ DataTransferModifierData *dtmd = (DataTransferModifierData *)ptr->data;
+ const int item_types = BKE_object_data_transfer_get_dttypes_item_types(dtmd->data_types);
+
+ if (item_types & ME_VERT) {
+ dtmd->flags |= MOD_DATATRANSFER_USE_VERT;
+ }
+ if (item_types & ME_EDGE) {
+ dtmd->flags |= MOD_DATATRANSFER_USE_EDGE;
+ }
+ if (item_types & ME_LOOP) {
+ dtmd->flags |= MOD_DATATRANSFER_USE_LOOP;
+ }
+ if (item_types & ME_POLY) {
+ dtmd->flags |= MOD_DATATRANSFER_USE_POLY;
+ }
+
+ rna_Modifier_update(bmain, scene, ptr);
+}
+
+static EnumPropertyItem *rna_DataTransferModifier_layers_select_src_itemf(bContext *C, PointerRNA *ptr, PropertyRNA *prop, bool *r_free)
+{
+ DataTransferModifierData *dtmd = (DataTransferModifierData *)ptr->data;
+ EnumPropertyItem *item = NULL, tmp_item = {0};
+ int totitem = 0;
+
+ if (!C) { /* needed for docs and i18n tools */
+ return DT_layers_select_src_items;
+ }
+
+ /* No active here! */
+ RNA_enum_items_add_value(&item, &totitem, DT_layers_select_src_items, DT_LAYERS_ALL_SRC);
+
+ if (STREQ(RNA_property_identifier(prop), "layers_vgroup_select_src")) {
+ Object *ob_src = dtmd->ob_source;
+
+#if 0 /* XXX Don't think we want this in modifier version... */
+ if (BKE_object_pose_armature_get(ob_src)) {
+ RNA_enum_items_add_value(&item, &totitem, DT_layers_select_src_items, DT_LAYERS_VGROUP_SRC_BONE_SELECT);
+ RNA_enum_items_add_value(&item, &totitem, DT_layers_select_src_items, DT_LAYERS_VGROUP_SRC_BONE_DEFORM);
+ }
+#endif
+
+ if (ob_src) {
+ bDeformGroup *dg;
+ int i;
+
+ RNA_enum_item_add_separator(&item, &totitem);
+
+ for (i = 0, dg = ob_src->defbase.first; dg; i++, dg = dg->next) {
+ tmp_item.value = i;
+ tmp_item.identifier = tmp_item.name = dg->name;
+ RNA_enum_item_add(&item, &totitem, &tmp_item);
+ }
+ }
+ }
+ else if (STREQ(RNA_property_identifier(prop), "layers_shapekey_select_src")) {
+ /* TODO */
+ }
+ else if (STREQ(RNA_property_identifier(prop), "layers_uv_select_src")) {
+ Object *ob_src = dtmd->ob_source;
+
+ if (ob_src) {
+ DerivedMesh *dm_src;
+ CustomData *pdata;
+ int num_data, i;
+
+ /* XXX Is this OK? */
+ dm_src = mesh_get_derived_final(dtmd->modifier.scene, ob_src, CD_MASK_BAREMESH | CD_MTEXPOLY);
+ pdata = dm_src->getPolyDataLayout(dm_src);
+ num_data = CustomData_number_of_layers(pdata, CD_MTEXPOLY);
+
+ RNA_enum_item_add_separator(&item, &totitem);
+
+ for (i = 0; i < num_data; i++) {
+ tmp_item.value = i;
+ tmp_item.identifier = tmp_item.name = CustomData_get_layer_name(pdata, CD_MTEXPOLY, i);
+ RNA_enum_item_add(&item, &totitem, &tmp_item);
+ }
+ }
+ }
+ else if (STREQ(RNA_property_identifier(prop), "layers_vcol_select_src")) {
+ Object *ob_src = dtmd->ob_source;
+
+ if (ob_src) {
+ DerivedMesh *dm_src;
+ CustomData *ldata;
+ int num_data, i;
+
+ /* XXX Is this OK? */
+ dm_src = mesh_get_derived_final(dtmd->modifier.scene, ob_src, CD_MASK_BAREMESH | CD_MLOOPCOL);
+ ldata = dm_src->getLoopDataLayout(dm_src);
+ num_data = CustomData_number_of_layers(ldata, CD_MLOOPCOL);
+
+ RNA_enum_item_add_separator(&item, &totitem);
+
+ for (i = 0; i < num_data; i++) {
+ tmp_item.value = i;
+ tmp_item.identifier = tmp_item.name = CustomData_get_layer_name(ldata, CD_MLOOPCOL, i);
+ RNA_enum_item_add(&item, &totitem, &tmp_item);
+ }
+ }
+ }
+
+ RNA_enum_item_end(&item, &totitem);
+ *r_free = true;
+
+ return item;
+}
+
+static EnumPropertyItem *rna_DataTransferModifier_layers_select_dst_itemf(bContext *C, PointerRNA *ptr, PropertyRNA *prop, bool *r_free)
+{
+ DataTransferModifierData *dtmd = (DataTransferModifierData *)ptr->data;
+ EnumPropertyItem *item = NULL, tmp_item = {0};
+ int totitem = 0;
+
+ if (!C) { /* needed for docs and i18n tools */
+ return DT_layers_select_dst_items;
+ }
+
+ /* No active here! */
+ RNA_enum_items_add_value(&item, &totitem, DT_layers_select_dst_items, DT_LAYERS_NAME_DST);
+ RNA_enum_items_add_value(&item, &totitem, DT_layers_select_dst_items, DT_LAYERS_INDEX_DST);
+
+ if (STREQ(RNA_property_identifier(prop), "layers_vgroup_select_dst")) {
+ /* Only list destination layers if we have a single source! */
+ if (dtmd->layers_select_src[DT_MULTILAYER_INDEX_MDEFORMVERT] >= 0) {
+ Object *ob_dst = CTX_data_active_object(C); /* XXX Is this OK? */
+
+ if (ob_dst) {
+ bDeformGroup *dg;
+ int i;
+
+ RNA_enum_item_add_separator(&item, &totitem);
+
+ for (i = 0, dg = ob_dst->defbase.first; dg; i++, dg = dg->next) {
+ tmp_item.value = i;
+ tmp_item.identifier = tmp_item.name = dg->name;
+ RNA_enum_item_add(&item, &totitem, &tmp_item);
+ }
+ }
+ }
+ }
+ else if (STREQ(RNA_property_identifier(prop), "layers_shapekey_select_dst")) {
+ /* TODO */
+ }
+ else if (STREQ(RNA_property_identifier(prop), "layers_uv_select_dst")) {
+ /* Only list destination layers if we have a single source! */
+ if (dtmd->layers_select_src[DT_MULTILAYER_INDEX_UV] >= 0) {
+ Object *ob_dst = CTX_data_active_object(C); /* XXX Is this OK? */
+
+ if (ob_dst && ob_dst->data) {
+ Mesh *me_dst;
+ CustomData *pdata;
+ int num_data, i;
+
+ me_dst = ob_dst->data;
+ pdata = &me_dst->pdata;
+ num_data = CustomData_number_of_layers(pdata, CD_MTEXPOLY);
+
+ RNA_enum_item_add_separator(&item, &totitem);
+
+ for (i = 0; i < num_data; i++) {
+ tmp_item.value = i;
+ tmp_item.identifier = tmp_item.name = CustomData_get_layer_name(pdata, CD_MTEXPOLY, i);
+ RNA_enum_item_add(&item, &totitem, &tmp_item);
+ }
+ }
+ }
+ }
+ else if (STREQ(RNA_property_identifier(prop), "layers_vcol_select_dst")) {
+ /* Only list destination layers if we have a single source! */
+ if (dtmd->layers_select_src[DT_MULTILAYER_INDEX_VCOL] >= 0) {
+ Object *ob_dst = CTX_data_active_object(C); /* XXX Is this OK? */
+
+ if (ob_dst && ob_dst->data) {
+ Mesh *me_dst;
+ CustomData *ldata;
+ int num_data, i;
+
+ me_dst = ob_dst->data;
+ ldata = &me_dst->ldata;
+ num_data = CustomData_number_of_layers(ldata, CD_MLOOPCOL);
+
+ RNA_enum_item_add_separator(&item, &totitem);
+
+ for (i = 0; i < num_data; i++) {
+ tmp_item.value = i;
+ tmp_item.identifier = tmp_item.name = CustomData_get_layer_name(ldata, CD_MLOOPCOL, i);
+ RNA_enum_item_add(&item, &totitem, &tmp_item);
+ }
+ }
+ }
+ }
+
+
+ RNA_enum_item_end(&item, &totitem);
+ *r_free = true;
+
+ return item;
+}
+
+static EnumPropertyItem *rna_DataTransferModifier_mix_mode_itemf(bContext *C, PointerRNA *ptr, PropertyRNA *UNUSED(prop), bool *r_free)
+{
+ DataTransferModifierData *dtmd = (DataTransferModifierData *)ptr->data;
+ EnumPropertyItem *item = NULL;
+ int totitem = 0;
+
+ bool support_advanced_mixing, support_threshold;
+
+ if (!C) { /* needed for docs and i18n tools */
+ return DT_mix_mode_items;
+ }
+
+ RNA_enum_items_add_value(&item, &totitem, DT_mix_mode_items, CDT_MIX_TRANSFER);
+
+ BKE_object_data_transfer_get_dttypes_capacity(dtmd->data_types, &support_advanced_mixing, &support_threshold);
+
+ if (support_threshold) {
+ RNA_enum_items_add_value(&item, &totitem, DT_mix_mode_items, CDT_MIX_REPLACE_ABOVE_THRESHOLD);
+ RNA_enum_items_add_value(&item, &totitem, DT_mix_mode_items, CDT_MIX_REPLACE_BELOW_THRESHOLD);
+ }
+
+ if (support_advanced_mixing) {
+ RNA_enum_item_add_separator(&item, &totitem);
+ RNA_enum_items_add_value(&item, &totitem, DT_mix_mode_items, CDT_MIX_MIX);
+ RNA_enum_items_add_value(&item, &totitem, DT_mix_mode_items, CDT_MIX_ADD);
+ RNA_enum_items_add_value(&item, &totitem, DT_mix_mode_items, CDT_MIX_SUB);
+ RNA_enum_items_add_value(&item, &totitem, DT_mix_mode_items, CDT_MIX_MUL);
+ }
+
+ RNA_enum_item_end(&item, &totitem);
+ *r_free = true;
+
+ return item;
+}
+
+static void rna_CorrectiveSmoothModifier_update(Main *bmain, Scene *scene, PointerRNA *ptr)
+{
+ CorrectiveSmoothModifierData *csmd = (CorrectiveSmoothModifierData *)ptr->data;
+
+ MEM_SAFE_FREE(csmd->delta_cache);
+
+ rna_Modifier_update(bmain, scene, ptr);
+}
+
+static void rna_CorrectiveSmoothModifier_rest_source_update(Main *bmain, Scene *scene, PointerRNA *ptr)
+{
+ CorrectiveSmoothModifierData *csmd = (CorrectiveSmoothModifierData *)ptr->data;
+
+ if (csmd->rest_source != MOD_CORRECTIVESMOOTH_RESTSOURCE_BIND) {
+ MEM_SAFE_FREE(csmd->bind_coords);
+ csmd->bind_coords_num = 0;
+ }
+
+ rna_CorrectiveSmoothModifier_update(bmain, scene, ptr);
+}
+
+static int rna_CorrectiveSmoothModifier_is_bind_get(PointerRNA *ptr)
+{
+ CorrectiveSmoothModifierData *csmd = (CorrectiveSmoothModifierData *)ptr->data;
+ return (csmd->bind_coords != NULL);
+}
+
#else
static PropertyRNA *rna_def_property_subdivision_common(StructRNA *srna, const char type[])
@@ -658,6 +1119,13 @@ static void rna_def_modifier_subsurf(BlenderRNA *brna)
RNA_def_property_boolean_sdna(prop, NULL, "flags", eSubsurfModifierFlag_SubsurfUv);
RNA_def_property_ui_text(prop, "Subdivide UVs", "Use subsurf to subdivide UVs");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+#ifdef WITH_OPENSUBDIV
+ prop = RNA_def_property(srna, "use_opensubdiv", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "use_opensubdiv", 1);
+ RNA_def_property_ui_text(prop, "Use OpenSubdiv", "Use OpenSubdiv for the subdivisions (viewport only)");
+ RNA_def_property_update(prop, 0, "rna_Modifier_update");
+#endif
}
static void rna_def_modifier_generic_map_info(StructRNA *srna)
@@ -702,18 +1170,6 @@ static void rna_def_modifier_warp(BlenderRNA *brna)
StructRNA *srna;
PropertyRNA *prop;
- static EnumPropertyItem prop_falloff_items[] = {
- {eWarp_Falloff_None, "NONE", 0, "No Falloff", ""},
- {eWarp_Falloff_Curve, "CURVE", 0, "Curve", ""},
- {eWarp_Falloff_Smooth, "SMOOTH", ICON_SMOOTHCURVE, "Smooth", ""},
- {eWarp_Falloff_Sphere, "SPHERE", ICON_SPHERECURVE, "Sphere", ""},
- {eWarp_Falloff_Root, "ROOT", ICON_ROOTCURVE, "Root", ""},
- {eWarp_Falloff_Sharp, "SHARP", ICON_SHARPCURVE, "Sharp", ""},
- {eWarp_Falloff_Linear, "LINEAR", ICON_LINCURVE, "Linear", ""},
- {eWarp_Falloff_Const, "CONSTANT", ICON_NOCURVE, "Constant", ""},
- {0, NULL, 0, NULL, NULL}
- };
-
srna = RNA_def_struct(brna, "WarpModifier", "Modifier");
RNA_def_struct_ui_text(srna, "Warp Modifier", "Warp modifier");
RNA_def_struct_sdna(srna, "WarpModifierData");
@@ -736,9 +1192,9 @@ static void rna_def_modifier_warp(BlenderRNA *brna)
RNA_def_property_update(prop, 0, "rna_Modifier_update");
prop = RNA_def_property(srna, "falloff_type", PROP_ENUM, PROP_NONE);
- RNA_def_property_enum_items(prop, prop_falloff_items);
+ RNA_def_property_enum_items(prop, modifier_warp_falloff_items);
RNA_def_property_ui_text(prop, "Falloff Type", "");
- RNA_def_property_translation_context(prop, BLF_I18NCONTEXT_ID_CURVE); /* Abusing id_curve :/ */
+ RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_CURVE); /* Abusing id_curve :/ */
RNA_def_property_update(prop, 0, "rna_Modifier_update");
prop = RNA_def_property(srna, "falloff_radius", PROP_FLOAT, PROP_UNSIGNED | PROP_DISTANCE);
@@ -876,7 +1332,7 @@ static void rna_def_modifier_curve(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Object", "Curve object to deform with");
RNA_def_property_pointer_funcs(prop, NULL, "rna_CurveModifier_object_set", NULL, "rna_Curve_object_poll");
RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK);
- RNA_def_property_update(prop, 0, "rna_Modifier_dependency_update");
+ RNA_def_property_update(prop, 0, "rna_CurveModifier_dependency_update");
prop = RNA_def_property(srna, "vertex_group", PROP_STRING, PROP_NONE);
RNA_def_property_string_sdna(prop, NULL, "name");
@@ -984,7 +1440,7 @@ static void rna_def_modifier_mirror(BlenderRNA *brna)
RNA_def_property_float_sdna(prop, NULL, "tolerance");
RNA_def_property_range(prop, 0, FLT_MAX);
RNA_def_property_ui_range(prop, 0, 1, 0.01, 6);
- RNA_def_property_ui_text(prop, "Merge Limit", "Distance from axis within which mirrored vertices are merged");
+ RNA_def_property_ui_text(prop, "Merge Limit", "Distance within which mirrored vertices are merged");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
prop = RNA_def_property(srna, "mirror_object", PROP_POINTER, PROP_NONE);
@@ -1037,7 +1493,7 @@ static void rna_def_modifier_decimate(BlenderRNA *brna)
prop = RNA_def_property(srna, "angle_limit", PROP_FLOAT, PROP_ANGLE);
RNA_def_property_float_sdna(prop, NULL, "angle");
RNA_def_property_range(prop, 0, DEG2RAD(180));
- RNA_def_property_ui_range(prop, 0, DEG2RAD(180), 100, 2);
+ RNA_def_property_ui_range(prop, 0, DEG2RAD(180), 10, 2);
RNA_def_property_ui_text(prop, "Angle Limit", "Only dissolve angles below this (planar only)");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
@@ -1057,6 +1513,13 @@ static void rna_def_modifier_decimate(BlenderRNA *brna)
RNA_def_property_boolean_sdna(prop, NULL, "flag", MOD_DECIM_FLAG_TRIANGULATE);
RNA_def_property_ui_text(prop, "Triangulate", "Keep triangulated faces resulting from decimation (collapse only)");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ prop = RNA_def_property(srna, "vertex_group_factor", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "defgrp_factor");
+ RNA_def_property_range(prop, 0, 1000);
+ RNA_def_property_ui_range(prop, 0, 10, 1, 4);
+ RNA_def_property_ui_text(prop, "Factor", "Vertex group strength");
+ RNA_def_property_update(prop, 0, "rna_Modifier_update");
/* end collapse-only option */
/* (mode == MOD_DECIM_MODE_DISSOLVE) */
@@ -1268,15 +1731,28 @@ static void rna_def_modifier_hook(BlenderRNA *brna)
RNA_def_struct_sdna(srna, "HookModifierData");
RNA_def_struct_ui_icon(srna, ICON_HOOK);
- prop = RNA_def_property(srna, "falloff", PROP_FLOAT, PROP_DISTANCE);
+ prop = RNA_def_property(srna, "strength", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "force");
+ RNA_def_property_range(prop, 0, 1);
+ RNA_def_property_ui_text(prop, "Strength", "Relative force of the hook");
+ RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ prop = RNA_def_property(srna, "falloff_type", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_items(prop, modifier_warp_falloff_items); /* share the enum */
+ RNA_def_property_ui_text(prop, "Falloff Type", "");
+ RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_CURVE); /* Abusing id_curve :/ */
+ RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ prop = RNA_def_property(srna, "falloff_radius", PROP_FLOAT, PROP_DISTANCE);
+ RNA_def_property_float_sdna(prop, NULL, "falloff");
RNA_def_property_range(prop, 0, FLT_MAX);
RNA_def_property_ui_range(prop, 0, 100, 100, 2);
- RNA_def_property_ui_text(prop, "Falloff", "If not zero, the distance from the hook where influence ends");
+ RNA_def_property_ui_text(prop, "Radius", "If not zero, the distance from the hook where influence ends");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
- prop = RNA_def_property(srna, "force", PROP_FLOAT, PROP_NONE);
- RNA_def_property_range(prop, 0, 1);
- RNA_def_property_ui_text(prop, "Force", "Relative force of the hook");
+ prop = RNA_def_property(srna, "falloff_curve", PROP_POINTER, PROP_NONE);
+ RNA_def_property_pointer_sdna(prop, NULL, "curfalloff");
+ RNA_def_property_ui_text(prop, "Falloff Curve", "Custom Lamp Falloff Curve");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
prop = RNA_def_property(srna, "center", PROP_FLOAT, PROP_NONE);
@@ -1296,6 +1772,11 @@ static void rna_def_modifier_hook(BlenderRNA *brna)
"Name of Parent Bone for hook (if applicable), also recalculates and clears offset");
RNA_def_property_update(prop, 0, "rna_Modifier_dependency_update");
+ prop = RNA_def_property(srna, "use_falloff_uniform", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", MOD_HOOK_UNIFORM_SPACE);
+ RNA_def_property_ui_text(prop, "Uniform Falloff", "Compensate for non-uniform object scale");
+ RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
prop = RNA_def_property(srna, "vertex_group", PROP_STRING, PROP_NONE);
RNA_def_property_string_sdna(prop, NULL, "name");
RNA_def_property_ui_text(prop, "Vertex Group",
@@ -1399,7 +1880,7 @@ static void rna_def_modifier_array(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Curve", "Curve object to fit array length to");
RNA_def_property_pointer_funcs(prop, NULL, "rna_ArrayModifier_curve_ob_set", NULL, "rna_Curve_object_poll");
RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK);
- RNA_def_property_update(prop, 0, "rna_Modifier_dependency_update");
+ RNA_def_property_update(prop, 0, "rna_ArrayModifier_dependency_update");
/* Offset parameters */
prop = RNA_def_property(srna, "use_constant_offset", PROP_BOOLEAN, PROP_NONE);
@@ -1483,7 +1964,7 @@ static void rna_def_modifier_edgesplit(BlenderRNA *brna)
prop = RNA_def_property(srna, "split_angle", PROP_FLOAT, PROP_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_range(prop, 0.0f, DEG2RADF(180.0f), 10, 2);
RNA_def_property_ui_text(prop, "Split Angle", "Angle above which to split edges");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
@@ -1508,9 +1989,11 @@ static void rna_def_modifier_displace(BlenderRNA *brna)
{MOD_DISP_DIR_Y, "Y", 0, "Y", "Use the texture's intensity value to displace in the Y direction"},
{MOD_DISP_DIR_Z, "Z", 0, "Z", "Use the texture's intensity value to displace in the Z direction"},
{MOD_DISP_DIR_NOR, "NORMAL", 0, "Normal",
- "Use the texture's intensity value to displace in the normal direction"},
+ "Use the texture's intensity value to displace along the vertex normal"},
+ {MOD_DISP_DIR_CLNOR, "CUSTOM_NORMAL", 0, "Custom Normal",
+ "Use the texture's intensity value to displace along the (averaged) custom normal (falls back to vertex)"},
{MOD_DISP_DIR_RGB_XYZ, "RGB_TO_XYZ", 0, "RGB to XYZ",
- "Use the texture's RGB values to displace the mesh in the XYZ direction"},
+ "Use the texture's RGB values to displace the mesh in the XYZ direction"},
{0, NULL, 0, NULL, NULL}
};
@@ -1675,6 +2158,90 @@ static void rna_def_modifier_smooth(BlenderRNA *brna)
RNA_def_property_update(prop, 0, "rna_Modifier_update");
}
+
+static void rna_def_modifier_correctivesmooth(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ static EnumPropertyItem modifier_smooth_type_items[] = {
+ {MOD_CORRECTIVESMOOTH_SMOOTH_SIMPLE, "SIMPLE", 0, "Simple",
+ "Use the average of adjacent edge-vertices"},
+ {MOD_CORRECTIVESMOOTH_SMOOTH_LENGTH_WEIGHT, "LENGTH_WEIGHTED", 0, "Length Weight",
+ "Use the average of adjacent edge-vertices weighted by their length"},
+ {0, NULL, 0, NULL, NULL}
+ };
+
+ static EnumPropertyItem modifier_rest_source_items[] = {
+ {MOD_CORRECTIVESMOOTH_RESTSOURCE_ORCO, "ORCO", 0, "Original Coords",
+ "Use base mesh vert coords as the rest position"},
+ {MOD_CORRECTIVESMOOTH_RESTSOURCE_BIND, "BIND", 0, "Bind Coords",
+ "Use bind vert coords for rest position"},
+ {0, NULL, 0, NULL, NULL}
+ };
+
+ srna = RNA_def_struct(brna, "CorrectiveSmoothModifier", "Modifier");
+ RNA_def_struct_ui_text(srna, "Corrective Smooth Modifier", "Correct distortion caused by deformation");
+ RNA_def_struct_sdna(srna, "CorrectiveSmoothModifierData");
+ RNA_def_struct_ui_icon(srna, ICON_MOD_SMOOTH);
+
+ prop = RNA_def_property(srna, "factor", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "lambda");
+ RNA_def_property_range(prop, -FLT_MAX, FLT_MAX);
+ RNA_def_property_ui_range(prop, 0.0, 1.0, 5, 3);
+ RNA_def_property_ui_text(prop, "Lambda Factor", "Smooth factor effect");
+ RNA_def_property_update(prop, 0, "rna_CorrectiveSmoothModifier_update");
+
+ prop = RNA_def_property(srna, "iterations", PROP_INT, PROP_NONE);
+ RNA_def_property_int_sdna(prop, NULL, "repeat");
+ RNA_def_property_ui_range(prop, 0, 200, 1, -1);
+ RNA_def_property_ui_text(prop, "Repeat", "");
+ RNA_def_property_update(prop, 0, "rna_CorrectiveSmoothModifier_update");
+
+ prop = RNA_def_property(srna, "rest_source", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "rest_source");
+ RNA_def_property_enum_items(prop, modifier_rest_source_items);
+ RNA_def_property_ui_text(prop, "Rest Source", "Select the source of rest positions");
+ RNA_def_property_update(prop, 0, "rna_CorrectiveSmoothModifier_rest_source_update");
+
+ prop = RNA_def_property(srna, "smooth_type", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "smooth_type");
+ RNA_def_property_enum_items(prop, modifier_smooth_type_items);
+ RNA_def_property_ui_text(prop, "Smooth Type", "Method used for smoothing");
+ RNA_def_property_update(prop, 0, "rna_CorrectiveSmoothModifier_update");
+
+ prop = RNA_def_property(srna, "invert_vertex_group", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", MOD_CORRECTIVESMOOTH_INVERT_VGROUP);
+ RNA_def_property_ui_text(prop, "Invert", "Invert vertex group influence");
+ RNA_def_property_update(prop, 0, "rna_CorrectiveSmoothModifier_update");
+
+ prop = RNA_def_property(srna, "vertex_group", PROP_STRING, PROP_NONE);
+ RNA_def_property_string_sdna(prop, NULL, "defgrp_name");
+ RNA_def_property_ui_text(prop, "Vertex Group",
+ "Name of Vertex Group which determines influence of modifier per point");
+ RNA_def_property_string_funcs(prop, NULL, NULL, "rna_CorrectiveSmoothModifier_defgrp_name_set");
+ RNA_def_property_update(prop, 0, "rna_CorrectiveSmoothModifier_update");
+
+ prop = RNA_def_property(srna, "is_bind", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_ui_text(prop, "Bind current shape", "");
+ RNA_def_property_boolean_funcs(prop, "rna_CorrectiveSmoothModifier_is_bind_get", NULL);
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ prop = RNA_def_property(srna, "use_only_smooth", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", MOD_CORRECTIVESMOOTH_ONLY_SMOOTH);
+ RNA_def_property_ui_text(prop, "Only Smooth",
+ "Apply smoothing without reconstructing the surface");
+ RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ prop = RNA_def_property(srna, "use_pin_boundary", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", MOD_CORRECTIVESMOOTH_PIN_BOUNDARY);
+ RNA_def_property_ui_text(prop, "Pin Boundaries",
+ "Excludes boundary vertices from being smoothed");
+ RNA_def_property_update(prop, 0, "rna_CorrectiveSmoothModifier_update");
+}
+
+
static void rna_def_modifier_laplaciansmooth(BlenderRNA *brna)
{
StructRNA *srna;
@@ -1840,7 +2407,7 @@ static void rna_def_modifier_meshdeform(BlenderRNA *brna)
prop = RNA_def_property(srna, "object", PROP_POINTER, PROP_NONE);
RNA_def_property_ui_text(prop, "Object", "Mesh object to deform with");
- RNA_def_property_pointer_funcs(prop, NULL, "rna_MeshDeformModifier_object_set", NULL, NULL);
+ RNA_def_property_pointer_funcs(prop, NULL, "rna_MeshDeformModifier_object_set", NULL, "rna_Mesh_object_poll");
RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK);
RNA_def_property_update(prop, 0, "rna_Modifier_dependency_update");
@@ -1916,6 +2483,7 @@ static void rna_def_modifier_particleinstance(BlenderRNA *brna)
prop = RNA_def_property(srna, "object", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "ob");
+ RNA_def_property_pointer_funcs(prop, NULL, NULL, NULL, "rna_Mesh_object_poll");
RNA_def_property_ui_text(prop, "Object", "Object that has the particle system");
RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK);
RNA_def_property_update(prop, 0, "rna_Modifier_dependency_update");
@@ -2057,9 +2625,29 @@ static void rna_def_modifier_cloth(BlenderRNA *brna)
RNA_def_property_pointer_sdna(prop, NULL, "coll_parms");
RNA_def_property_ui_text(prop, "Cloth Collision Settings", "");
+ prop = RNA_def_property(srna, "solver_result", PROP_POINTER, PROP_NONE);
+ RNA_def_property_struct_type(prop, "ClothSolverResult");
+ RNA_def_property_pointer_sdna(prop, NULL, "solver_result");
+ RNA_def_property_ui_text(prop, "Solver Result", "");
+
prop = RNA_def_property(srna, "point_cache", PROP_POINTER, PROP_NONE);
RNA_def_property_flag(prop, PROP_NEVER_NULL);
RNA_def_property_ui_text(prop, "Point Cache", "");
+
+ prop = RNA_def_property(srna, "hair_grid_min", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "hair_grid_min");
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_property_ui_text(prop, "Hair Grid Minimum", "");
+
+ prop = RNA_def_property(srna, "hair_grid_max", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "hair_grid_max");
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_property_ui_text(prop, "Hair Grid Maximum", "");
+
+ prop = RNA_def_property(srna, "hair_grid_resolution", PROP_INT, PROP_NONE);
+ RNA_def_property_int_sdna(prop, NULL, "hair_grid_res");
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_property_ui_text(prop, "Hair Grid Resolution", "");
}
static void rna_def_modifier_smoke(BlenderRNA *brna)
@@ -2213,7 +2801,7 @@ static void rna_def_modifier_bevel(BlenderRNA *brna)
prop = RNA_def_property(srna, "angle_limit", PROP_FLOAT, PROP_ANGLE);
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_range(prop, 0.0f, DEG2RADF(180.0f), 10, 2);
RNA_def_property_ui_text(prop, "Angle", "Angle above which to bevel edges");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
@@ -2245,7 +2833,11 @@ static void rna_def_modifier_bevel(BlenderRNA *brna)
RNA_def_property_range(prop, -1, SHRT_MAX);
RNA_def_property_ui_text(prop, "Material", "Material index of generated faces, -1 for automatic");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
-
+
+ prop = RNA_def_property(srna, "loop_slide", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_negative_sdna(prop, NULL, "flags", MOD_BEVEL_EVEN_WIDTHS);
+ RNA_def_property_ui_text(prop, "Loop Slide", "Prefer sliding along edges to having even widths");
+ RNA_def_property_update(prop, 0, "rna_Modifier_update");
}
static void rna_def_modifier_shrinkwrap(BlenderRNA *brna)
@@ -2453,13 +3045,13 @@ static void rna_def_modifier_simpledeform(BlenderRNA *brna)
RNA_def_property_update(prop, 0, "rna_Modifier_update");
prop = RNA_def_property(srna, "origin", PROP_POINTER, PROP_NONE);
- RNA_def_property_ui_text(prop, "Origin", "Origin of modifier space coordinates");
+ RNA_def_property_ui_text(prop, "Origin", "Offset the origin and orientation of the deformation");
RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK);
RNA_def_property_update(prop, 0, "rna_Modifier_dependency_update");
prop = RNA_def_property(srna, "factor", PROP_FLOAT, PROP_NONE);
RNA_def_property_range(prop, -FLT_MAX, FLT_MAX);
- RNA_def_property_ui_range(prop, -10, 10, 1, 3);
+ RNA_def_property_ui_range(prop, -10.0, 10.0, 1.0, 3);
RNA_def_property_ui_text(prop, "Factor", "Amount to deform object");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
@@ -2467,7 +3059,7 @@ static void rna_def_modifier_simpledeform(BlenderRNA *brna)
RNA_def_property_float_sdna(prop, NULL, "factor");
RNA_def_property_range(prop, -FLT_MAX, FLT_MAX);
RNA_def_property_float_default(prop, DEG2RADF(45.0f));
- RNA_def_property_ui_range(prop, -M_PI, M_PI, DEG2RAD(1), 3);
+ RNA_def_property_ui_range(prop, DEG2RAD(-360.0), DEG2RAD(360.0), 10.0, 3);
RNA_def_property_ui_text(prop, "Angle", "Angle of deformation");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
@@ -2663,7 +3255,7 @@ static void rna_def_modifier_screw(BlenderRNA *brna)
RNA_def_property_update(prop, 0, "rna_Modifier_update");
prop = RNA_def_property(srna, "angle", PROP_FLOAT, PROP_ANGLE);
- RNA_def_property_ui_range(prop, -M_PI * 2, M_PI * 2, 2, -1);
+ RNA_def_property_ui_range(prop, -M_PI * 2, M_PI * 2, 10, -1);
RNA_def_property_range(prop, -FLT_MAX, FLT_MAX);
RNA_def_property_ui_text(prop, "Angle", "Angle of revolution");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
@@ -2747,24 +3339,24 @@ static void rna_def_modifier_uvwarp(BlenderRNA *brna)
prop = RNA_def_property(srna, "object_from", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "object_src");
- RNA_def_property_ui_text(prop, "Target", "Object defining offset");
+ RNA_def_property_ui_text(prop, "Object From", "Object defining offset");
RNA_def_property_flag(prop, PROP_EDITABLE);
RNA_def_property_update(prop, 0, "rna_Modifier_dependency_update");
prop = RNA_def_property(srna, "bone_from", PROP_STRING, PROP_NONE);
RNA_def_property_string_sdna(prop, NULL, "bone_src");
- RNA_def_property_ui_text(prop, "Sub-Target", "Bone defining offset");
+ RNA_def_property_ui_text(prop, "Bone From", "Bone defining offset");
RNA_def_property_update(prop, 0, "rna_Modifier_dependency_update");
prop = RNA_def_property(srna, "object_to", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "object_dst");
- RNA_def_property_ui_text(prop, "Target", "Object defining offset");
+ RNA_def_property_ui_text(prop, "Object To", "Object defining offset");
RNA_def_property_flag(prop, PROP_EDITABLE);
RNA_def_property_update(prop, 0, "rna_Modifier_dependency_update");
prop = RNA_def_property(srna, "bone_to", PROP_STRING, PROP_NONE);
RNA_def_property_string_sdna(prop, NULL, "bone_dst");
- RNA_def_property_ui_text(prop, "Sub-Target", "Bone defining offset");
+ RNA_def_property_ui_text(prop, "Bone To", "Bone defining offset");
RNA_def_property_update(prop, 0, "rna_Modifier_dependency_update");
prop = RNA_def_property(srna, "vertex_group", PROP_STRING, PROP_NONE);
@@ -2880,7 +3472,7 @@ static void rna_def_modifier_weightvgedit(BlenderRNA *brna)
prop = RNA_def_property(srna, "falloff_type", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, weightvg_edit_falloff_type_items);
RNA_def_property_ui_text(prop, "Falloff Type", "How weights are mapped to their new values");
- RNA_def_property_translation_context(prop, BLF_I18NCONTEXT_ID_CURVE); /* Abusing id_curve :/ */
+ RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_CURVE); /* Abusing id_curve :/ */
RNA_def_property_update(prop, 0, "rna_Modifier_update");
prop = RNA_def_property(srna, "use_add", PROP_BOOLEAN, PROP_NONE);
@@ -3086,7 +3678,7 @@ static void rna_def_modifier_weightvgproximity(BlenderRNA *brna)
prop = RNA_def_property(srna, "falloff_type", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, weightvg_proximity_falloff_type_items);
RNA_def_property_ui_text(prop, "Falloff Type", "How weights are mapped to their new values");
- RNA_def_property_translation_context(prop, BLF_I18NCONTEXT_ID_CURVE); /* Abusing id_curve :/ */
+ RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_CURVE); /* Abusing id_curve :/ */
RNA_def_property_update(prop, 0, "rna_Modifier_update");
/* Common masking properties. */
@@ -3664,6 +4256,323 @@ static void rna_def_modifier_wireframe(BlenderRNA *brna)
RNA_def_property_update(prop, 0, "rna_Modifier_update");
}
+static void rna_def_modifier_datatransfer(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ static EnumPropertyItem DT_layer_vert_items[] = {
+#if 0 /* XXX When SkinModifier is enabled, it seems to erase its own CD_MVERT_SKIN layer from final DM :( */
+ {DT_TYPE_SKIN, "SKIN", 0, "Skin Weight", "Transfer skin weights"},
+#endif
+ {DT_TYPE_BWEIGHT_VERT, "BEVEL_WEIGHT_VERT", 0, "Bevel Weight", "Transfer bevel weights"},
+ {0, NULL, 0, NULL, NULL}
+ };
+ static EnumPropertyItem DT_layer_vert_vgroup_items[] = {
+ {DT_TYPE_MDEFORMVERT, "VGROUP_WEIGHTS", 0, "Vertex Group(s)", "Transfer active or all vertex groups"},
+ {0, NULL, 0, NULL, NULL}
+ };
+#if 0 /* XXX For now, would like to finish/merge work from 2014 gsoc first. */
+ static EnumPropertyItem DT_layer_vert_shapekey_items[] = {
+ {DT_TYPE_SHAPEKEY, "SHAPEKEYS", 0, "Shapekey(s)", "Transfer active or all shape keys"},
+ {0, NULL, 0, NULL, NULL}
+ };
+#endif
+
+ static EnumPropertyItem DT_layer_edge_items[] = {
+ {DT_TYPE_SHARP_EDGE, "SHARP_EDGE", 0, "Sharp", "Transfer sharp mark"},
+ {DT_TYPE_SEAM, "SEAM", 0, "UV Seam", "Transfer UV seam mark"},
+ {DT_TYPE_CREASE, "CREASE", 0, "Subsurf Crease", "Transfer crease values"},
+ {DT_TYPE_BWEIGHT_EDGE, "BEVEL_WEIGHT_EDGE", 0, "Bevel Weight", "Transfer bevel weights"},
+ {DT_TYPE_FREESTYLE_EDGE, "FREESTYLE_EDGE", 0, "Freestyle Mark", "Transfer Freestyle edge mark"},
+ {0, NULL, 0, NULL, NULL}
+ };
+
+ static EnumPropertyItem DT_layer_loop_items[] = {
+ {DT_TYPE_LNOR, "CUSTOM_NORMAL", 0, "Custom Normals", "Transfer custom normals"},
+ {0, NULL, 0, NULL, NULL}
+ };
+ static EnumPropertyItem DT_layer_loop_vcol_items[] = {
+ {DT_TYPE_VCOL, "VCOL", 0, "VCol", "Vertex (face corners) colors"},
+ {0, NULL, 0, NULL, NULL}
+ };
+ static EnumPropertyItem DT_layer_loop_uv_items[] = {
+ {DT_TYPE_UV, "UV", 0, "UVs", "Transfer UV layers"},
+ {0, NULL, 0, NULL, NULL}
+ };
+
+ static EnumPropertyItem DT_layer_poly_items[] = {
+ {DT_TYPE_SHARP_FACE, "SMOOTH", 0, "Smooth", "Transfer flat/smooth mark"},
+ {DT_TYPE_FREESTYLE_FACE, "FREESTYLE_FACE", 0, "Freestyle Mark", "Transfer Freestyle face mark"},
+ {0, NULL, 0, NULL, NULL}
+ };
+
+ srna = RNA_def_struct(brna, "DataTransferModifier", "Modifier");
+ RNA_def_struct_ui_text(srna, "Data Transfer Modifier", "Modifier transferring some data from a source mesh");
+ RNA_def_struct_sdna(srna, "DataTransferModifierData");
+ RNA_def_struct_ui_icon(srna, ICON_MOD_DATA_TRANSFER);
+
+ prop = RNA_def_property(srna, "object", PROP_POINTER, PROP_NONE);
+ RNA_def_property_pointer_sdna(prop, NULL, "ob_source");
+ RNA_def_property_ui_text(prop, "Source Object", "Object to transfer data from");
+ RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK);
+ RNA_def_property_pointer_funcs(prop, NULL, "rna_DataTransferModifier_ob_source_set", NULL, "rna_Mesh_object_poll");
+ RNA_def_property_update(prop, 0, "rna_Modifier_dependency_update");
+
+ prop = RNA_def_boolean(srna, "use_object_transform", true, "Object Transform",
+ "Evaluate source and destination meshes in global space");
+ RNA_def_property_boolean_sdna(prop, NULL, "flags", MOD_DATATRANSFER_OBSRC_TRANSFORM);
+ RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ /* Generic, UI-only data types toggles. */
+ prop = RNA_def_boolean(srna, "use_vert_data", false, "Vertex Data", "Enable vertex data transfer");
+ RNA_def_property_boolean_sdna(prop, NULL, "flags", MOD_DATATRANSFER_USE_VERT);
+ RNA_def_property_update(prop, 0, "rna_DataTransferModifier_use_data_update");
+
+ prop = RNA_def_boolean(srna, "use_edge_data", false, "Edge Data", "Enable edge data transfer");
+ RNA_def_property_boolean_sdna(prop, NULL, "flags", MOD_DATATRANSFER_USE_EDGE);
+ RNA_def_property_update(prop, 0, "rna_DataTransferModifier_use_data_update");
+
+ prop = RNA_def_boolean(srna, "use_loop_data", false, "Face Corner Data", "Enable face corner data transfer");
+ RNA_def_property_boolean_sdna(prop, NULL, "flags", MOD_DATATRANSFER_USE_LOOP);
+ RNA_def_property_update(prop, 0, "rna_DataTransferModifier_use_data_update");
+
+ prop = RNA_def_boolean(srna, "use_poly_data", false, "Face Data", "Enable face data transfer");
+ RNA_def_property_boolean_sdna(prop, NULL, "flags", MOD_DATATRANSFER_USE_POLY);
+ RNA_def_property_update(prop, 0, "rna_DataTransferModifier_use_data_update");
+
+ /* Actual data types selection. */
+ prop = RNA_def_enum(srna, "data_types_verts", DT_layer_vert_items, 0, "Vertex Data Types",
+ "Which vertex data layers to transfer");
+ RNA_def_property_flag(prop, PROP_ENUM_FLAG);
+ RNA_def_property_enum_sdna(prop, NULL, "data_types");
+ RNA_def_property_update(prop, 0, "rna_DataTransferModifier_data_types_update");
+ prop = RNA_def_enum(srna, "data_types_verts_vgroup", DT_layer_vert_vgroup_items, 0, "Vertex Data Types",
+ "Which vertex data layers to transfer");
+ RNA_def_property_flag(prop, PROP_ENUM_FLAG);
+ RNA_def_property_enum_sdna(prop, NULL, "data_types");
+ RNA_def_property_update(prop, 0, "rna_DataTransferModifier_data_types_update");
+
+ prop = RNA_def_enum(srna, "data_types_edges", DT_layer_edge_items, 0, "Edge Data Types",
+ "Which edge data layers to transfer");
+ RNA_def_property_flag(prop, PROP_ENUM_FLAG);
+ RNA_def_property_enum_sdna(prop, NULL, "data_types");
+ RNA_def_property_update(prop, 0, "rna_DataTransferModifier_data_types_update");
+
+ prop = RNA_def_enum(srna, "data_types_loops", DT_layer_loop_items, 0, "Face Corner Data Types",
+ "Which face corner data layers to transfer");
+ RNA_def_property_flag(prop, PROP_ENUM_FLAG);
+ RNA_def_property_enum_sdna(prop, NULL, "data_types");
+ RNA_def_property_update(prop, 0, "rna_DataTransferModifier_data_types_update");
+ prop = RNA_def_enum(srna, "data_types_loops_vcol", DT_layer_loop_vcol_items, 0, "Face Corner Data Types",
+ "Which face corner data layers to transfer");
+ RNA_def_property_flag(prop, PROP_ENUM_FLAG);
+ RNA_def_property_enum_sdna(prop, NULL, "data_types");
+ RNA_def_property_update(prop, 0, "rna_DataTransferModifier_data_types_update");
+ prop = RNA_def_enum(srna, "data_types_loops_uv", DT_layer_loop_uv_items, 0, "Face Corner Data Types",
+ "Which face corner data layers to transfer");
+ RNA_def_property_flag(prop, PROP_ENUM_FLAG);
+ RNA_def_property_enum_sdna(prop, NULL, "data_types");
+ RNA_def_property_update(prop, 0, "rna_DataTransferModifier_data_types_update");
+
+ prop = RNA_def_enum(srna, "data_types_polys", DT_layer_poly_items, 0, "Poly Data Types",
+ "Which poly data layers to transfer");
+ RNA_def_property_flag(prop, PROP_ENUM_FLAG);
+ RNA_def_property_enum_sdna(prop, NULL, "data_types");
+ RNA_def_property_update(prop, 0, "rna_DataTransferModifier_data_types_update");
+
+ /* Mapping methods. */
+ prop = RNA_def_enum(srna, "vert_mapping", DT_method_vertex_items, MREMAP_MODE_VERT_NEAREST, "Vertex Mapping",
+ "Method used to map source vertices to destination ones");
+ RNA_def_property_enum_sdna(prop, NULL, "vmap_mode");
+ RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ prop = RNA_def_enum(srna, "edge_mapping", DT_method_edge_items, MREMAP_MODE_EDGE_NEAREST, "Edge Mapping",
+ "Method used to map source edges to destination ones");
+ RNA_def_property_enum_sdna(prop, NULL, "emap_mode");
+ RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ prop = RNA_def_enum(srna, "loop_mapping", DT_method_loop_items, MREMAP_MODE_LOOP_NEAREST_POLYNOR,
+ "Face Corner Mapping", "Method used to map source faces' corners to destination ones");
+ RNA_def_property_enum_sdna(prop, NULL, "lmap_mode");
+ RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ prop = RNA_def_enum(srna, "poly_mapping", DT_method_poly_items, MREMAP_MODE_POLY_NEAREST, "Face Mapping",
+ "Method used to map source faces to destination ones");
+ RNA_def_property_enum_sdna(prop, NULL, "pmap_mode");
+ RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ /* Mapping options and filtering. */
+ prop = RNA_def_boolean(srna, "use_max_distance", false, "Only Neighbor Geometry",
+ "Source elements must be closer than given distance from destination one");
+ RNA_def_property_boolean_sdna(prop, NULL, "flags", MOD_DATATRANSFER_MAP_MAXDIST);
+ RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ prop = RNA_def_float(srna, "max_distance", 1.0f, 0.0f, FLT_MAX, "Max Distance",
+ "Maximum allowed distance between source and destination element, for non-topology mappings",
+ 0.0f, 100.0f);
+ RNA_def_property_float_sdna(prop, NULL, "map_max_distance");
+ RNA_def_property_subtype(prop, PROP_DISTANCE);
+ RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ prop = RNA_def_float(srna, "ray_radius", 0.0f, 0.0f, FLT_MAX, "Ray Radius",
+ "'Width' of rays (especially useful when raycasting against vertices or edges)", 0.0f, 10.0f);
+ RNA_def_property_float_sdna(prop, NULL, "map_ray_radius");
+ RNA_def_property_subtype(prop, PROP_DISTANCE);
+ RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ prop = RNA_def_float(srna, "islands_precision", 0.0f, 0.0f, 1.0f, "Islands Handling Refinement",
+ "Factor controlling precision of islands handling "
+ "(typically, 0.1 should be enough, higher values can make things really slow)", 0.0f, 1.0f);
+ RNA_def_property_subtype(prop, PROP_DISTANCE);
+ RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ /* How to handle multi-layers types of data. */
+ prop = RNA_def_enum(srna, "layers_vgroup_select_src", DT_layers_select_src_items, DT_LAYERS_ALL_SRC,
+ "Source Layers Selection", "Which layers to transfer, in case of multi-layers types");
+ RNA_def_property_enum_sdna(prop, NULL, "layers_select_src[DT_MULTILAYER_INDEX_MDEFORMVERT]");
+ RNA_def_property_enum_funcs(prop, NULL, NULL, "rna_DataTransferModifier_layers_select_src_itemf");
+ RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+#if 0
+ prop = RNA_def_enum(srna, "layers_shapekey_select_src", DT_layers_select_src_items, DT_LAYERS_ALL_SRC,
+ "Source Layers Selection", "Which layers to transfer, in case of multi-layers types");
+ RNA_def_property_enum_sdna(prop, NULL, "layers_select_src[DT_MULTILAYER_INDEX_SHAPEKEY]");
+ RNA_def_property_enum_funcs(prop, NULL, NULL, "rna_DataTransferModifier_layers_select_src_itemf");
+ RNA_def_property_update(prop, 0, "rna_Modifier_update");
+#endif
+
+ prop = RNA_def_enum(srna, "layers_vcol_select_src", DT_layers_select_src_items, DT_LAYERS_ALL_SRC,
+ "Source Layers Selection", "Which layers to transfer, in case of multi-layers types");
+ RNA_def_property_enum_sdna(prop, NULL, "layers_select_src[DT_MULTILAYER_INDEX_VCOL]");
+ RNA_def_property_enum_funcs(prop, NULL, NULL, "rna_DataTransferModifier_layers_select_src_itemf");
+ RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ prop = RNA_def_enum(srna, "layers_uv_select_src", DT_layers_select_src_items, DT_LAYERS_ALL_SRC,
+ "Source Layers Selection", "Which layers to transfer, in case of multi-layers types");
+ RNA_def_property_enum_sdna(prop, NULL, "layers_select_src[DT_MULTILAYER_INDEX_UV]");
+ RNA_def_property_enum_funcs(prop, NULL, NULL, "rna_DataTransferModifier_layers_select_src_itemf");
+ RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ prop = RNA_def_enum(srna, "layers_vgroup_select_dst", DT_layers_select_dst_items, DT_LAYERS_NAME_DST,
+ "Destination Layers Matching", "How to match source and destination layers");
+ RNA_def_property_enum_sdna(prop, NULL, "layers_select_dst[DT_MULTILAYER_INDEX_MDEFORMVERT]");
+ RNA_def_property_enum_funcs(prop, NULL, NULL, "rna_DataTransferModifier_layers_select_dst_itemf");
+ RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+#if 0
+ prop = RNA_def_enum(srna, "layers_shapekey_select_dst", DT_layers_select_dst_items, DT_LAYERS_NAME_DST,
+ "Destination Layers Matching", "How to match source and destination layers");
+ RNA_def_property_enum_sdna(prop, NULL, "layers_select_dst[DT_MULTILAYER_INDEX_SHAPEKEY]");
+ RNA_def_property_enum_funcs(prop, NULL, NULL, "rna_DataTransferModifier_layers_select_dst_itemf");
+ RNA_def_property_update(prop, 0, "rna_Modifier_update");
+#endif
+
+ prop = RNA_def_enum(srna, "layers_vcol_select_dst", DT_layers_select_dst_items, DT_LAYERS_NAME_DST,
+ "Destination Layers Matching", "How to match source and destination layers");
+ RNA_def_property_enum_sdna(prop, NULL, "layers_select_dst[DT_MULTILAYER_INDEX_VCOL]");
+ RNA_def_property_enum_funcs(prop, NULL, NULL, "rna_DataTransferModifier_layers_select_dst_itemf");
+ RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ prop = RNA_def_enum(srna, "layers_uv_select_dst", DT_layers_select_dst_items, DT_LAYERS_NAME_DST,
+ "Destination Layers Matching", "How to match source and destination layers");
+ RNA_def_property_enum_sdna(prop, NULL, "layers_select_dst[DT_MULTILAYER_INDEX_UV]");
+ RNA_def_property_enum_funcs(prop, NULL, NULL, "rna_DataTransferModifier_layers_select_dst_itemf");
+ RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ /* Mix stuff */
+ prop = RNA_def_enum(srna, "mix_mode", DT_mix_mode_items, CDT_MIX_TRANSFER, "Mix Mode",
+ "How to affect destination elements with source values");
+ RNA_def_property_enum_funcs(prop, NULL, NULL, "rna_DataTransferModifier_mix_mode_itemf");
+ RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ prop = RNA_def_float(srna, "mix_factor", 1.0f, 0.0f, 1.0f, "Mix Factor",
+ "Factor to use when applying data to destination (exact behavior depends on mix mode)",
+ 0.0f, 1.0f);
+ RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ prop = RNA_def_string(srna, "vertex_group", NULL, MAX_VGROUP_NAME, "Vertex Group",
+ "Vertex group name for selecting the affected areas");
+ RNA_def_property_string_sdna(prop, NULL, "defgrp_name");
+ RNA_def_property_string_funcs(prop, NULL, NULL, "rna_DataTransferModifier_defgrp_name_set");
+ RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ prop = RNA_def_boolean(srna, "invert_vertex_group", false, "Invert", "Invert vertex group influence");
+ RNA_def_property_boolean_sdna(prop, NULL, "flags", MOD_DATATRANSFER_INVERT_VGROUP);
+ RNA_def_property_update(prop, 0, "rna_Modifier_update");
+}
+
+static void rna_def_modifier_normaledit(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ static EnumPropertyItem prop_mode_items[] = {
+ {MOD_NORMALEDIT_MODE_RADIAL, "RADIAL", 0, "Radial",
+ "From an ellipsoid (shape defined by the boundbox's dimensions, target is optional)"},
+ {MOD_NORMALEDIT_MODE_DIRECTIONAL, "DIRECTIONAL", 0, "Directional",
+ "Normals 'track' (point to) the target object"},
+ {0, NULL, 0, NULL, NULL}
+ };
+
+ static EnumPropertyItem prop_mix_mode_items[] = {
+ {MOD_NORMALEDIT_MIX_COPY, "COPY", 0, "Copy", "Copy new normals (overwrite existing)"},
+ {MOD_NORMALEDIT_MIX_ADD, "ADD", 0, "Add", "Copy sum of new and old normals"},
+ {MOD_NORMALEDIT_MIX_SUB, "SUB", 0, "Subtract", "Copy new normals minus old normals"},
+ {MOD_NORMALEDIT_MIX_MUL, "MUL", 0, "Multiply", "Copy product of old and new normals (*not* cross product)"},
+ {0, NULL, 0, NULL, NULL}
+ };
+
+ srna = RNA_def_struct(brna, "NormalEditModifier", "Modifier");
+ RNA_def_struct_ui_text(srna, "Normal Edit Modifier", "Modifier affecting/generating custom normals");
+ RNA_def_struct_sdna(srna, "NormalEditModifierData");
+ RNA_def_struct_ui_icon(srna, ICON_MOD_NORMALEDIT);
+
+ prop = RNA_def_property(srna, "mode", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_items(prop, prop_mode_items);
+ RNA_def_property_ui_text(prop, "Mode", "How to affect (generate) normals");
+ RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ prop = RNA_def_float_array(srna, "offset", 3, NULL, -FLT_MAX, FLT_MAX, "Offset",
+ "Offset from object's center", -100.0f, 100.0f);
+ RNA_def_property_subtype(prop, PROP_COORDS);
+ RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ prop = RNA_def_property(srna, "mix_mode", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_items(prop, prop_mix_mode_items);
+ RNA_def_property_ui_text(prop, "Mix Mode", "How to mix generated normals with existing ones");
+ RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ prop = RNA_def_float(srna, "mix_factor", 1.0f, 0.0f, 1.0f, "Mix Factor",
+ "How much of generated normals to mix with exiting ones", 0.0f, 1.0f);
+ RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ prop = RNA_def_property(srna, "vertex_group", PROP_STRING, PROP_NONE);
+ RNA_def_property_string_sdna(prop, NULL, "defgrp_name");
+ RNA_def_property_ui_text(prop, "Vertex Group", "Vertex group name for selecting/weighting the affected areas");
+ RNA_def_property_string_funcs(prop, NULL, NULL, "rna_NormalEditModifier_defgrp_name_set");
+ RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ prop = RNA_def_property(srna, "invert_vertex_group", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", MOD_NORMALEDIT_INVERT_VGROUP);
+ RNA_def_property_ui_text(prop, "Invert", "Invert vertex group influence");
+ RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ prop = RNA_def_property(srna, "target", PROP_POINTER, PROP_NONE);
+ RNA_def_property_ui_text(prop, "Target", "Target object used to affect normals");
+ RNA_def_property_pointer_funcs(prop, NULL, "rna_NormalEditModifier_target_set", NULL, NULL);
+ RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK);
+ RNA_def_property_update(prop, 0, "rna_Modifier_dependency_update");
+
+ prop = RNA_def_property(srna, "use_direction_parallel", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", MOD_NORMALEDIT_USE_DIRECTION_PARALLEL);
+ RNA_def_property_boolean_default(prop, true);
+ RNA_def_property_ui_text(prop, "Parallel Normals",
+ "Use same direction for all normals, from origin to target's center "
+ "(Directional mode only)");
+ RNA_def_property_update(prop, 0, "rna_Modifier_update");
+}
+
void RNA_def_modifier(BlenderRNA *brna)
{
StructRNA *srna;
@@ -3746,6 +4655,7 @@ void RNA_def_modifier(BlenderRNA *brna)
rna_def_modifier_displace(brna);
rna_def_modifier_uvproject(brna);
rna_def_modifier_smooth(brna);
+ rna_def_modifier_correctivesmooth(brna);
rna_def_modifier_cast(brna);
rna_def_modifier_meshdeform(brna);
rna_def_modifier_particlesystem(brna);
@@ -3777,6 +4687,8 @@ void RNA_def_modifier(BlenderRNA *brna)
rna_def_modifier_meshcache(brna);
rna_def_modifier_laplaciandeform(brna);
rna_def_modifier_wireframe(brna);
+ rna_def_modifier_datatransfer(brna);
+ rna_def_modifier_normaledit(brna);
}
#endif
diff --git a/source/blender/makesrna/intern/rna_movieclip.c b/source/blender/makesrna/intern/rna_movieclip.c
index 170856a3061..9ccde654af2 100644
--- a/source/blender/makesrna/intern/rna_movieclip.c
+++ b/source/blender/makesrna/intern/rna_movieclip.c
@@ -196,7 +196,7 @@ static void rna_def_movieclip_proxy(BlenderRNA *brna)
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
RNA_def_property_enum_items(prop, clip_tc_items);
RNA_def_property_ui_text(prop, "Timecode", "");
- RNA_def_property_update(prop, NC_MOVIECLIP | ND_DISPLAY, NULL);
+ RNA_def_property_update(prop, NC_MOVIECLIP | ND_DISPLAY, "rna_MovieClip_reload_update");
/* directory */
prop = RNA_def_property(srna, "directory", PROP_STRING, PROP_DIRPATH);
@@ -317,8 +317,8 @@ static void rna_def_movieclip(BlenderRNA *brna)
/* grease pencil */
prop = RNA_def_property(srna, "grease_pencil", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "gpd");
- RNA_def_property_flag(prop, PROP_EDITABLE);
RNA_def_property_struct_type(prop, "GreasePencil");
+ RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_REFCOUNT);
RNA_def_property_ui_text(prop, "Grease Pencil", "Grease pencil data for this movie clip");
RNA_def_property_update(prop, NC_MOVIECLIP | ND_DISPLAY, NULL);
diff --git a/source/blender/makesrna/intern/rna_nla.c b/source/blender/makesrna/intern/rna_nla.c
index 37de1d670f5..22d0144250e 100644
--- a/source/blender/makesrna/intern/rna_nla.c
+++ b/source/blender/makesrna/intern/rna_nla.c
@@ -52,6 +52,7 @@
#include "BKE_animsys.h"
#include "BKE_nla.h"
+#include "BKE_fcurve.h"
#include "ED_anim_api.h"
/* temp constant defined for these funcs only... */
@@ -106,6 +107,16 @@ static void rna_NlaStrip_transform_update(Main *UNUSED(bmain), Scene *UNUSED(sce
NlaStrip *strip = (NlaStrip *)ptr->data;
BKE_nlameta_flush_transforms(strip);
+
+ /* set the flag */
+ if ((strip->flag & NLASTRIP_FLAG_AUTO_BLENDS) && ptr->id.data) {
+ /* validate state to ensure that auto-blend gets applied immediately */
+ IdAdtTemplate *iat = (IdAdtTemplate *)ptr->id.data;
+
+ if (iat->adt) {
+ BKE_nla_validate_state(iat->adt);
+ }
+ }
}
static void rna_NlaStrip_start_frame_set(PointerRNA *ptr, float value)
@@ -333,6 +344,18 @@ static void rna_NlaStrip_animated_time_set(PointerRNA *ptr, int value)
data->flag &= ~NLASTRIP_FLAG_USR_TIME;
}
+static FCurve *rna_NlaStrip_fcurve_find(NlaStrip *strip, ReportList *reports, const char *data_path, int index)
+{
+ if (data_path[0] == '\0') {
+ BKE_report(reports, RPT_ERROR, "F-Curve data path empty, invalid argument");
+ return NULL;
+ }
+
+ /* Returns NULL if not found. */
+ return list_find_fcurve(&strip->fcurves, data_path, index);
+}
+
+
static NlaStrip *rna_NlaStrip_new(NlaTrack *track, bContext *C, ReportList *reports, const char *UNUSED(name),
int start, bAction *action)
{
@@ -455,6 +478,31 @@ EnumPropertyItem nla_mode_extend_items[] = {
{0, NULL, 0, NULL, NULL}
};
+static void rna_def_strip_fcurves(BlenderRNA *brna, PropertyRNA *cprop)
+{
+ StructRNA *srna;
+
+ FunctionRNA *func;
+ PropertyRNA *parm;
+
+ RNA_def_property_srna(cprop, "NlaStripFCurves");
+ srna = RNA_def_struct(brna, "NlaStripFCurves", NULL);
+ RNA_def_struct_sdna(srna, "NlaStrip");
+ RNA_def_struct_ui_text(srna, "NLA-Strip F-Curves", "Collection of NLA strip F-Curves");
+
+ /* Strip.fcurves.find(...) */
+ func = RNA_def_function(srna, "find", "rna_NlaStrip_fcurve_find");
+ RNA_def_function_ui_description(func, "Find an F-Curve. Note that this function performs a linear scan "
+ "of all F-Curves in the NLA strip.");
+ RNA_def_function_flag(func, FUNC_USE_REPORTS);
+ parm = RNA_def_string(func, "data_path", NULL, 0, "Data Path", "F-Curve data path");
+ RNA_def_property_flag(parm, PROP_REQUIRED);
+ RNA_def_int(func, "index", 0, 0, INT_MAX, "Index", "Array index", 0, INT_MAX);
+
+ parm = RNA_def_pointer(func, "fcurve", "FCurve", "", "The found F-Curve, or None if it doesn't exist");
+ RNA_def_function_return(func, parm);
+}
+
static void rna_def_nlastrip(BlenderRNA *brna)
{
StructRNA *srna;
@@ -508,7 +556,7 @@ static void rna_def_nlastrip(BlenderRNA *brna)
RNA_def_property_float_funcs(prop, NULL, "rna_NlaStrip_start_frame_set", NULL);
RNA_def_property_ui_text(prop, "Start Frame", "");
RNA_def_property_update(prop, 0, "rna_NlaStrip_transform_update");
-
+
prop = RNA_def_property(srna, "frame_end", PROP_FLOAT, PROP_TIME);
RNA_def_property_float_sdna(prop, NULL, "end");
RNA_def_property_float_funcs(prop, NULL, "rna_NlaStrip_end_frame_set", NULL);
@@ -550,13 +598,13 @@ static void rna_def_nlastrip(BlenderRNA *brna)
RNA_def_property_float_sdna(prop, NULL, "actstart");
RNA_def_property_float_funcs(prop, NULL, "rna_NlaStrip_action_start_frame_set", NULL);
RNA_def_property_ui_text(prop, "Action Start Frame", "First frame from action to use");
- RNA_def_property_update(prop, NC_ANIMATION | ND_NLA, NULL); /* this will do? */
+ RNA_def_property_update(prop, 0, "rna_NlaStrip_transform_update");
prop = RNA_def_property(srna, "action_frame_end", PROP_FLOAT, PROP_TIME);
RNA_def_property_float_sdna(prop, NULL, "actend");
RNA_def_property_float_funcs(prop, NULL, "rna_NlaStrip_action_end_frame_set", NULL);
RNA_def_property_ui_text(prop, "Action End Frame", "Last frame from action to use");
- RNA_def_property_update(prop, NC_ANIMATION | ND_NLA, NULL); /* this will do? */
+ RNA_def_property_update(prop, 0, "rna_NlaStrip_transform_update");
/* Action Reuse */
prop = RNA_def_property(srna, "repeat", PROP_FLOAT, PROP_NONE);
@@ -566,7 +614,7 @@ static void rna_def_nlastrip(BlenderRNA *brna)
* (minimum should still be > 0 though) if needed... */
RNA_def_property_range(prop, 0.1f, 1000.0f);
RNA_def_property_ui_text(prop, "Repeat", "Number of times to repeat the action range");
- RNA_def_property_update(prop, NC_ANIMATION | ND_NLA, NULL); /* this will do? */
+ RNA_def_property_update(prop, 0, "rna_NlaStrip_transform_update");
prop = RNA_def_property(srna, "scale", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "scale");
@@ -575,13 +623,15 @@ static void rna_def_nlastrip(BlenderRNA *brna)
* due to numeric errors */
RNA_def_property_range(prop, 0.0001f, 1000.0f);
RNA_def_property_ui_text(prop, "Scale", "Scaling factor for action");
- RNA_def_property_update(prop, NC_ANIMATION | ND_NLA, NULL); /* this will do? */
+ RNA_def_property_update(prop, 0, "rna_NlaStrip_transform_update");
/* Strip's F-Curves */
prop = RNA_def_property(srna, "fcurves", PROP_COLLECTION, PROP_NONE);
+ RNA_def_property_collection_sdna(prop, NULL, "fcurves", NULL);
RNA_def_property_struct_type(prop, "FCurve");
RNA_def_property_ui_text(prop, "F-Curves", "F-Curves for controlling the strip's influence and timing");
-
+ rna_def_strip_fcurves(brna, prop);
+
/* Strip's F-Modifiers */
prop = RNA_def_property(srna, "modifiers", PROP_COLLECTION, PROP_NONE);
RNA_def_property_struct_type(prop, "FModifier");
diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c
index e90de3631d6..8ebc3f03608 100644
--- a/source/blender/makesrna/intern/rna_nodetree.c
+++ b/source/blender/makesrna/intern/rna_nodetree.c
@@ -30,16 +30,15 @@
#include "BLI_listbase.h"
#include "BLI_math.h"
-#include "BLI_string.h"
#include "BLI_utildefines.h"
-#include "BLF_translation.h"
+#include "BLT_translation.h"
#include "DNA_material_types.h"
#include "DNA_mesh_types.h"
#include "DNA_node_types.h"
#include "DNA_object_types.h"
-#include "DNA_scene_types.h"
+#include "DNA_particle_types.h"
#include "DNA_text_types.h"
#include "DNA_texture_types.h"
@@ -48,7 +47,6 @@
#include "BKE_node.h"
#include "BKE_image.h"
#include "BKE_texture.h"
-#include "BKE_idprop.h"
#include "RNA_access.h"
#include "RNA_define.h"
@@ -64,6 +62,8 @@
#include "MEM_guardedalloc.h"
+#include "RE_render_ext.h"
+
EnumPropertyItem node_socket_in_out_items[] = {
{ SOCK_IN, "IN", 0, "Input", "" },
{ SOCK_OUT, "OUT", 0, "Output", "" },
@@ -112,25 +112,25 @@ EnumPropertyItem node_icon_items[] = {
#undef DEF_VICO
EnumPropertyItem node_math_items[] = {
- { 0, "ADD", 0, "Add", ""},
- { 1, "SUBTRACT", 0, "Subtract", ""},
- { 2, "MULTIPLY", 0, "Multiply", ""},
- { 3, "DIVIDE", 0, "Divide", ""},
- { 4, "SINE", 0, "Sine", ""},
- { 5, "COSINE", 0, "Cosine", ""},
- { 6, "TANGENT", 0, "Tangent", ""},
- { 7, "ARCSINE", 0, "Arcsine", ""},
- { 8, "ARCCOSINE", 0, "Arccosine", ""},
- { 9, "ARCTANGENT", 0, "Arctangent", ""},
- {10, "POWER", 0, "Power", ""},
- {11, "LOGARITHM", 0, "Logarithm", ""},
- {12, "MINIMUM", 0, "Minimum", ""},
- {13, "MAXIMUM", 0, "Maximum", ""},
- {14, "ROUND", 0, "Round", ""},
- {15, "LESS_THAN", 0, "Less Than", ""},
- {16, "GREATER_THAN", 0, "Greater Than", ""},
- {17, "MODULO", 0, "Modulo", ""},
- {18, "ABSOLUTE", 0, "Absolute", ""},
+ {NODE_MATH_ADD, "ADD", 0, "Add", ""},
+ {NODE_MATH_SUB, "SUBTRACT", 0, "Subtract", ""},
+ {NODE_MATH_MUL, "MULTIPLY", 0, "Multiply", ""},
+ {NODE_MATH_DIVIDE, "DIVIDE", 0, "Divide", ""},
+ {NODE_MATH_SIN, "SINE", 0, "Sine", ""},
+ {NODE_MATH_COS, "COSINE", 0, "Cosine", ""},
+ {NODE_MATH_TAN, "TANGENT", 0, "Tangent", ""},
+ {NODE_MATH_ASIN, "ARCSINE", 0, "Arcsine", ""},
+ {NODE_MATH_ACOS, "ARCCOSINE", 0, "Arccosine", ""},
+ {NODE_MATH_ATAN, "ARCTANGENT", 0, "Arctangent", ""},
+ {NODE_MATH_POW, "POWER", 0, "Power", ""},
+ {NODE_MATH_LOG, "LOGARITHM", 0, "Logarithm", ""},
+ {NODE_MATH_MIN, "MINIMUM", 0, "Minimum", ""},
+ {NODE_MATH_MAX, "MAXIMUM", 0, "Maximum", ""},
+ {NODE_MATH_ROUND, "ROUND", 0, "Round", ""},
+ {NODE_MATH_LESS, "LESS_THAN", 0, "Less Than", ""},
+ {NODE_MATH_GREATER, "GREATER_THAN", 0, "Greater Than", ""},
+ {NODE_MATH_MOD, "MODULO", 0, "Modulo", ""},
+ {NODE_MATH_ABS, "ABSOLUTE", 0, "Absolute", ""},
{0, NULL, 0, NULL, NULL}
};
@@ -792,6 +792,11 @@ static bNodeLink *rna_NodeTree_link_new(bNodeTree *ntree, ReportList *reports,
ret = nodeAddLink(ntree, fromnode, fromsock, tonode, tosock);
if (ret) {
+
+ /* not an issue from the UI, clear hidden from API to keep valid state. */
+ fromsock->flag &= ~SOCK_HIDDEN;
+ tosock->flag &= ~SOCK_HIDDEN;
+
if (tonode)
nodeUpdate(ntree, tonode);
@@ -1549,7 +1554,7 @@ static void rna_Node_name_set(PointerRNA *ptr, const char *value)
nodeUniqueName(ntree, node);
/* fix all the animation data which may link to this */
- BKE_all_animdata_fix_paths_rename(NULL, "nodes", oldname, node->name);
+ BKE_animdata_fix_paths_rename_all(NULL, "nodes", oldname, node->name);
}
static bNodeSocket *rna_Node_inputs_new(ID *id, bNode *node, ReportList *reports, const char *type, const char *name, const char *identifier)
@@ -1578,7 +1583,7 @@ static bNodeSocket *rna_Node_outputs_new(ID *id, bNode *node, ReportList *report
sock = nodeAddSocket(ntree, node, SOCK_OUT, type, identifier, name);
if (sock == NULL) {
- BKE_reportf(reports, RPT_ERROR, "Unable to create socket");
+ BKE_report(reports, RPT_ERROR, "Unable to create socket");
}
else {
ntreeUpdateTree(G.main, ntree);
@@ -2199,6 +2204,10 @@ static void rna_NodeSocketStandard_float_range(PointerRNA *ptr, float *min, floa
bNodeSocketValueFloat *dval = sock->default_value;
int subtype = sock->typeinfo->subtype;
+ if (dval->max < dval->min) {
+ dval->max = dval->min;
+ }
+
*min = (subtype == PROP_UNSIGNED ? 0.0f : -FLT_MAX);
*max = FLT_MAX;
*softmin = dval->min;
@@ -2211,6 +2220,10 @@ static void rna_NodeSocketStandard_int_range(PointerRNA *ptr, int *min, int *max
bNodeSocketValueInt *dval = sock->default_value;
int subtype = sock->typeinfo->subtype;
+ if (dval->max < dval->min) {
+ dval->max = dval->min;
+ }
+
*min = (subtype == PROP_UNSIGNED ? 0 : INT_MIN);
*max = INT_MAX;
*softmin = dval->min;
@@ -2222,6 +2235,10 @@ static void rna_NodeSocketStandard_vector_range(PointerRNA *ptr, float *min, flo
bNodeSocket *sock = ptr->data;
bNodeSocketValueVector *dval = sock->default_value;
+ if (dval->max < dval->min) {
+ dval->max = dval->min;
+ }
+
*min = -FLT_MAX;
*max = FLT_MAX;
*softmin = dval->min;
@@ -2246,8 +2263,13 @@ static void rna_NodeSocketStandard_value_update(struct bContext *C, PointerRNA *
nodeFindNode(ntree, sock, &node, NULL);
}
- if (node)
+ if (node) {
nodeSynchronizeID(node, true);
+
+ /* extra update for sockets that get synced to material */
+ if (node->id && ELEM(node->type, SH_NODE_MATERIAL, SH_NODE_MATERIAL_EXT))
+ WM_main_add_notifier(NC_MATERIAL | ND_SHADING_DRAW, node->id);
+ }
}
@@ -2604,6 +2626,70 @@ static EnumPropertyItem *rna_Node_image_layer_itemf(bContext *UNUSED(C), Pointer
return item;
}
+static int rna_Node_image_has_layers_get(PointerRNA *ptr)
+{
+ bNode *node = (bNode *)ptr->data;
+ Image *ima = (Image *)node->id;
+
+ if (!ima || !(ima->rr)) return 0;
+
+ return RE_layers_have_name(ima->rr);
+}
+
+static int rna_Node_image_has_views_get(PointerRNA *ptr)
+{
+ bNode *node = (bNode *)ptr->data;
+ Image *ima = (Image *)node->id;
+
+ if (!ima || !(ima->rr)) return 0;
+
+ return BLI_listbase_count_ex(&ima->rr->views, 2) > 1;
+}
+
+static EnumPropertyItem *renderresult_views_add_enum(RenderView *rv)
+{
+ EnumPropertyItem *item = NULL;
+ EnumPropertyItem tmp = {0, "ALL", 0, "All", ""};
+ int i = 1, totitem = 0;
+
+ /* option to use all views */
+ RNA_enum_item_add(&item, &totitem, &tmp);
+
+ while (rv) {
+ tmp.identifier = rv->name;
+ /* little trick: using space char instead empty string makes the item selectable in the dropdown */
+ if (rv->name[0] == '\0')
+ tmp.name = " ";
+ else
+ tmp.name = rv->name;
+ tmp.value = i++;
+ RNA_enum_item_add(&item, &totitem, &tmp);
+ rv = rv->next;
+ }
+
+ RNA_enum_item_end(&item, &totitem);
+
+ return item;
+}
+
+static EnumPropertyItem *rna_Node_image_view_itemf(bContext *UNUSED(C), PointerRNA *ptr,
+ PropertyRNA *UNUSED(prop), bool *free)
+{
+ bNode *node = (bNode *)ptr->data;
+ Image *ima = (Image *)node->id;
+ EnumPropertyItem *item = NULL;
+ RenderView *rv;
+
+ if (!ima || !(ima->rr)) return NULL;
+
+ rv = ima->rr->views.first;
+ item = renderresult_views_add_enum(rv);
+
+ *free = true;
+
+ return item;
+}
+
static EnumPropertyItem *rna_Node_scene_layer_itemf(bContext *UNUSED(C), PointerRNA *ptr,
PropertyRNA *UNUSED(prop), bool *r_free)
{
@@ -2689,7 +2775,7 @@ static void rna_Image_Node_update_id(Main *UNUSED(bmain), Scene *UNUSED(scene),
static void rna_Mapping_Node_update(Main *bmain, Scene *scene, PointerRNA *ptr)
{
bNode *node = ptr->data;
- init_tex_mapping(node->storage);
+ BKE_texture_mapping_init(node->storage);
rna_Node_update(bmain, scene, ptr);
}
@@ -2888,6 +2974,89 @@ static void rna_CompositorNodeScale_update(Main *bmain, Scene *scene, PointerRNA
rna_Node_update(bmain, scene, ptr);
}
+static PointerRNA rna_ShaderNodePointDensity_psys_get(PointerRNA *ptr)
+{
+ bNode *node = ptr->data;
+ NodeShaderTexPointDensity *shader_point_density = node->storage;
+ Object *ob = (Object *)node->id;
+ ParticleSystem *psys = NULL;
+ PointerRNA value;
+
+ if (ob && shader_point_density->particle_system) {
+ psys = BLI_findlink(&ob->particlesystem, shader_point_density->particle_system - 1);
+ }
+
+ RNA_pointer_create(&ob->id, &RNA_ParticleSystem, psys, &value);
+ return value;
+}
+
+static void rna_ShaderNodePointDensity_psys_set(PointerRNA *ptr, PointerRNA value)
+{
+ bNode *node = ptr->data;
+ NodeShaderTexPointDensity *shader_point_density = node->storage;
+ Object *ob = (Object *)node->id;
+
+ if (ob && value.id.data == ob) {
+ shader_point_density->particle_system = BLI_findindex(&ob->particlesystem, value.data) + 1;
+ }
+ else {
+ shader_point_density->particle_system = 0;
+ }
+}
+
+static int point_density_color_source_from_shader(NodeShaderTexPointDensity *shader_point_density)
+{
+ switch (shader_point_density->color_source) {
+ case SHD_POINTDENSITY_COLOR_PARTAGE: return TEX_PD_COLOR_PARTAGE;
+ case SHD_POINTDENSITY_COLOR_PARTSPEED: return TEX_PD_COLOR_PARTSPEED;
+ case SHD_POINTDENSITY_COLOR_PARTVEL: return TEX_PD_COLOR_PARTVEL;
+ default:
+ BLI_assert(!"Unknown color source");
+ return TEX_PD_COLOR_CONSTANT;
+ }
+}
+
+/* TODO(sergey): This function assumes allocated array was passed,
+ * works fine with Cycles via C++ RNA, but fails with call from python.
+ */
+void rna_ShaderNodePointDensity_density_calc(bNode *self, Scene *scene, int *length, float **values)
+{
+ NodeShaderTexPointDensity *shader_point_density = self->storage;
+ PointDensity pd;
+
+ *length = 4 * shader_point_density->resolution *
+ shader_point_density->resolution *
+ shader_point_density->resolution;
+
+ if (*values == NULL) {
+ *values = MEM_mallocN(sizeof(float) * (*length), "point density dynamic array");
+ }
+
+ /* Create PointDensity structure from node for sampling. */
+ BKE_texture_pointdensity_init_data(&pd);
+ pd.object = (Object *)self->id;
+ pd.radius = shader_point_density->radius;
+ if (shader_point_density->point_source == SHD_POINTDENSITY_SOURCE_PSYS) {
+ pd.source = TEX_PD_PSYS;
+ pd.psys = shader_point_density->particle_system;
+ pd.psys_cache_space = TEX_PD_OBJECTSPACE;
+ }
+ else {
+ BLI_assert(shader_point_density->point_source == SHD_POINTDENSITY_SOURCE_OBJECT);
+ pd.source = TEX_PD_OBJECT;
+ pd.ob_cache_space = TEX_PD_OBJECTSPACE;
+ }
+ pd.color_source = point_density_color_source_from_shader(shader_point_density);
+
+ /* Single-threaded sampling of the voxel domain. */
+ RE_sample_point_density(scene, &pd,
+ shader_point_density->resolution,
+ *values);
+
+ /* We're done, time to clean up. */
+ BKE_texture_pointdensity_free_data(&pd);
+}
+
#else
static EnumPropertyItem prop_image_layer_items[] = {
@@ -2895,6 +3064,11 @@ static EnumPropertyItem prop_image_layer_items[] = {
{0, NULL, 0, NULL, NULL}
};
+static EnumPropertyItem prop_image_view_items[] = {
+ { 0, "ALL", 0, "All", ""},
+ {0, NULL, 0, NULL, NULL}
+};
+
static EnumPropertyItem prop_scene_layer_items[] = {
{ 0, "PLACEHOLDER", 0, "Placeholder", ""},
{0, NULL, 0, NULL, NULL}
@@ -3026,6 +3200,13 @@ static void def_frame(StructRNA *srna)
{
PropertyRNA *prop;
+ prop = RNA_def_property(srna, "text", PROP_POINTER, PROP_NONE);
+ RNA_def_property_pointer_sdna(prop, NULL, "id");
+ RNA_def_property_struct_type(prop, "Text");
+ RNA_def_property_flag(prop, PROP_EDITABLE);
+ RNA_def_property_ui_text(prop, "Text", "");
+ RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
+
RNA_def_struct_sdna_from(srna, "NodeFrame", "storage");
prop = RNA_def_property(srna, "shrink", PROP_BOOLEAN, PROP_NONE);
@@ -3051,7 +3232,7 @@ static void def_math(StructRNA *srna)
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
prop = RNA_def_property(srna, "use_clamp", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "custom2", 1);
+ RNA_def_property_boolean_sdna(prop, NULL, "custom2", SHD_MATH_CLAMP);
RNA_def_property_ui_text(prop, "Clamp", "Clamp result of the node to 0..1 range");
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
}
@@ -3132,12 +3313,12 @@ static void def_mix_rgb(StructRNA *srna)
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
prop = RNA_def_property(srna, "use_alpha", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "custom2", 1);
+ RNA_def_property_boolean_sdna(prop, NULL, "custom2", SHD_MIXRGB_USE_ALPHA);
RNA_def_property_ui_text(prop, "Alpha", "Include alpha of second input in this operation");
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
prop = RNA_def_property(srna, "use_clamp", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "custom2", 2);
+ RNA_def_property_boolean_sdna(prop, NULL, "custom2", SHD_MIXRGB_CLAMP);
RNA_def_property_ui_text(prop, "Clamp", "Clamp result of the node to 0..1 range");
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
}
@@ -3215,6 +3396,8 @@ static void def_sh_mapping(StructRNA *srna)
{0, NULL, 0, NULL, NULL}
};
+ static float default_1[3] = {1.f, 1.f, 1.f};
+
PropertyRNA *prop;
RNA_def_struct_sdna_from(srna, "TexMapping", "storage");
@@ -3238,6 +3421,7 @@ static void def_sh_mapping(StructRNA *srna)
prop = RNA_def_property(srna, "scale", PROP_FLOAT, PROP_XYZ);
RNA_def_property_float_sdna(prop, NULL, "size");
+ RNA_def_property_float_array_default(prop, default_1);
RNA_def_property_flag(prop, PROP_PROPORTIONAL);
RNA_def_property_ui_text(prop, "Scale", "");
RNA_def_property_update(prop, 0, "rna_Mapping_Node_update");
@@ -3249,6 +3433,7 @@ static void def_sh_mapping(StructRNA *srna)
prop = RNA_def_property(srna, "max", PROP_FLOAT, PROP_XYZ);
RNA_def_property_float_sdna(prop, NULL, "max");
+ RNA_def_property_float_array_default(prop, default_1);
RNA_def_property_ui_text(prop, "Maximum", "Maximum value for clipping");
RNA_def_property_update(prop, 0, "rna_Mapping_Node_update");
@@ -3376,7 +3561,7 @@ static void def_sh_tex_environment(StructRNA *srna)
"Projection from an orthographic photo of a mirror ball"},
{0, NULL, 0, NULL, NULL}
};
-
+
PropertyRNA *prop;
prop = RNA_def_property(srna, "image", PROP_POINTER, PROP_NONE);
@@ -3391,6 +3576,7 @@ static void def_sh_tex_environment(StructRNA *srna)
prop = RNA_def_property(srna, "color_space", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, prop_color_space_items);
+ RNA_def_property_enum_default(prop, SHD_COLORSPACE_COLOR);
RNA_def_property_ui_text(prop, "Color Space", "Image file color space");
RNA_def_property_update(prop, 0, "rna_Node_update");
@@ -3419,10 +3605,14 @@ static void def_sh_tex_image(StructRNA *srna)
};
static const EnumPropertyItem prop_projection_items[] = {
- {SHD_PROJ_FLAT, "FLAT", 0, "Flat",
- "Image is projected flat using the X and Y coordinates of the texture vector"},
- {SHD_PROJ_BOX, "BOX", 0, "Box",
- "Image is projected using different components for each side of the object space bounding box"},
+ {SHD_PROJ_FLAT, "FLAT", 0, "Flat",
+ "Image is projected flat using the X and Y coordinates of the texture vector"},
+ {SHD_PROJ_BOX, "BOX", 0, "Box",
+ "Image is projected using different components for each side of the object space bounding box"},
+ {SHD_PROJ_SPHERE, "SPHERE", 0, "Sphere",
+ "Image is projected spherically using the Z axis as central"},
+ {SHD_PROJ_TUBE, "TUBE", 0, "Tube",
+ "Image is projected from the tube using the Z axis as central"},
{0, NULL, 0, NULL, NULL}
};
@@ -3432,12 +3622,19 @@ static void def_sh_tex_image(StructRNA *srna)
{SHD_INTERP_CLOSEST, "Closest", 0, "Closest",
"No interpolation (sample closest texel)"},
{SHD_INTERP_CUBIC, "Cubic", 0, "Cubic",
- "Cubic interpolation (OSL only)"},
+ "Cubic interpolation (CPU only)"},
{SHD_INTERP_SMART, "Smart", 0, "Smart",
"Bicubic when magnifying, else bilinear (OSL only)"},
{0, NULL, 0, NULL, NULL}
};
+ static EnumPropertyItem prop_image_extension[] = {
+ {SHD_IMAGE_EXTENSION_REPEAT, "REPEAT", 0, "Repeat", "Cause the image to repeat horizontally and vertically"},
+ {SHD_IMAGE_EXTENSION_EXTEND, "EXTEND", 0, "Extend", "Extend by repeating edge pixels of the image"},
+ {SHD_IMAGE_EXTENSION_CLIP, "CLIP", 0, "Clip", "Clip to image size and set exterior pixels as transparent"},
+ {0, NULL, 0, NULL, NULL}
+ };
+
PropertyRNA *prop;
prop = RNA_def_property(srna, "image", PROP_POINTER, PROP_NONE);
@@ -3452,6 +3649,7 @@ static void def_sh_tex_image(StructRNA *srna)
prop = RNA_def_property(srna, "color_space", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, prop_color_space_items);
+ RNA_def_property_enum_default(prop, SHD_COLORSPACE_COLOR);
RNA_def_property_ui_text(prop, "Color Space", "Image file color space");
RNA_def_property_update(prop, 0, "rna_Node_update");
@@ -3469,6 +3667,11 @@ static void def_sh_tex_image(StructRNA *srna)
RNA_def_property_ui_text(prop, "Projection Blend", "For box projection, amount of blend to use between sides");
RNA_def_property_update(prop, 0, "rna_Node_update");
+ prop = RNA_def_property(srna, "extension", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_items(prop, prop_image_extension);
+ RNA_def_property_ui_text(prop, "Extension", "How the image is extrapolated past its original bounds");
+ RNA_def_property_update(prop, 0, "rna_Node_update");
+
prop = RNA_def_property(srna, "image_user", PROP_POINTER, PROP_NONE);
RNA_def_property_flag(prop, PROP_NEVER_NULL);
RNA_def_property_pointer_sdna(prop, NULL, "iuser");
@@ -3631,7 +3834,14 @@ static void def_sh_tex_wave(StructRNA *srna)
static void def_sh_tex_coord(StructRNA *srna)
{
PropertyRNA *prop;
-
+
+ prop = RNA_def_property(srna, "object", PROP_POINTER, PROP_NONE);
+ RNA_def_property_pointer_sdna(prop, NULL, "id");
+ RNA_def_property_struct_type(prop, "Object");
+ RNA_def_property_flag(prop, PROP_EDITABLE);
+ RNA_def_property_ui_text(prop, "Object", "Use coordinates from this object (for object texture coordinates output)");
+ RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
+
prop = RNA_def_property(srna, "from_dupli", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "custom1", 1);
RNA_def_property_ui_text(prop, "From Dupli", "Use the parent of the dupli object if possible");
@@ -3685,6 +3895,103 @@ static void def_sh_tex_wireframe(StructRNA *srna)
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
}
+static void def_sh_tex_pointdensity(StructRNA *srna)
+{
+ PropertyRNA *prop;
+ FunctionRNA *func;
+
+ static EnumPropertyItem point_source_items[] = {
+ {SHD_POINTDENSITY_SOURCE_PSYS, "PARTICLE_SYSTEM", 0, "Particle System",
+ "Generate point density from a particle system"},
+ {SHD_POINTDENSITY_SOURCE_OBJECT, "OBJECT", 0, "Object Vertices",
+ "Generate point density from an object's vertices"},
+ {0, NULL, 0, NULL, NULL}
+ };
+
+ static const EnumPropertyItem prop_interpolation_items[] = {
+ {SHD_INTERP_CLOSEST, "Closest", 0, "Closest",
+ "No interpolation (sample closest texel)"},
+ {SHD_INTERP_LINEAR, "Linear", 0, "Linear",
+ "Linear interpolation"},
+ {SHD_INTERP_CUBIC, "Cubic", 0, "Cubic",
+ "Cubic interpolation (CPU only)"},
+ {0, NULL, 0, NULL, NULL}
+ };
+
+ static EnumPropertyItem space_items[] = {
+ {SHD_POINTDENSITY_SPACE_OBJECT, "OBJECT", 0, "Object Space", ""},
+ {SHD_POINTDENSITY_SPACE_WORLD, "WORLD", 0, "World Space", ""},
+ {0, NULL, 0, NULL, NULL}
+ };
+
+ static EnumPropertyItem color_source_items[] = {
+ {SHD_POINTDENSITY_COLOR_PARTAGE, "PARTICLE_AGE", 0, "Particle Age",
+ "Lifetime mapped as 0.0 - 1.0 intensity"},
+ {SHD_POINTDENSITY_COLOR_PARTSPEED, "PARTICLE_SPEED", 0, "Particle Speed",
+ "Particle speed (absolute magnitude of velocity) mapped as 0.0-1.0 intensity"},
+ {SHD_POINTDENSITY_COLOR_PARTVEL, "PARTICLE_VELOCITY", 0, "Particle Velocity",
+ "XYZ velocity mapped to RGB colors"},
+ {0, NULL, 0, NULL, NULL}
+ };
+
+ prop = RNA_def_property(srna, "object", PROP_POINTER, PROP_NONE);
+ RNA_def_property_pointer_sdna(prop, NULL, "id");
+ RNA_def_property_struct_type(prop, "Object");
+ RNA_def_property_flag(prop, PROP_EDITABLE);
+ RNA_def_property_ui_text(prop, "Object", "Object to take point data from");
+ RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
+
+ RNA_def_struct_sdna_from(srna, "NodeShaderTexPointDensity", "storage");
+
+ prop = RNA_def_property(srna, "point_source", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_items(prop, point_source_items);
+ RNA_def_property_ui_text(prop, "Point Source", "Point data to use as renderable point density");
+ RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
+
+ prop = RNA_def_property(srna, "particle_system", PROP_POINTER, PROP_NONE);
+ RNA_def_property_ui_text(prop, "Particle System", "Particle System to render as points");
+ RNA_def_property_struct_type(prop, "ParticleSystem");
+ RNA_def_property_pointer_funcs(prop, "rna_ShaderNodePointDensity_psys_get",
+ "rna_ShaderNodePointDensity_psys_set", NULL, NULL);
+ RNA_def_property_flag(prop, PROP_EDITABLE);
+ RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
+
+ prop = RNA_def_property(srna, "resolution", PROP_INT, PROP_NONE);
+ RNA_def_property_range(prop, 1, 32768);
+ RNA_def_property_ui_text(prop, "Resolution", "Resolution used by the texture holding the point density");
+ RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
+
+ prop = RNA_def_property(srna, "radius", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "radius");
+ RNA_def_property_range(prop, 0.001, FLT_MAX);
+ RNA_def_property_ui_text(prop, "Radius", "Radius from the shaded sample to look for points within");
+ RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
+
+ prop = RNA_def_property(srna, "space", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_items(prop, space_items);
+ RNA_def_property_ui_text(prop, "Space", "Coordinate system to calculate voxels in");
+ RNA_def_property_update(prop, 0, "rna_Node_update");
+
+ prop = RNA_def_property(srna, "interpolation", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_items(prop, prop_interpolation_items);
+ RNA_def_property_ui_text(prop, "Interpolation", "Texture interpolation");
+ RNA_def_property_update(prop, 0, "rna_Node_update");
+
+ prop = RNA_def_property(srna, "color_source", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "color_source");
+ RNA_def_property_enum_items(prop, color_source_items);
+ RNA_def_property_ui_text(prop, "Color Source", "Data to derive color results from");
+ RNA_def_property_update(prop, 0, "rna_Node_update");
+
+ func = RNA_def_function(srna, "calc_point_density", "rna_ShaderNodePointDensity_density_calc");
+ RNA_def_function_ui_description(func, "Calculate point density");
+ RNA_def_pointer(func, "scene", "Scene", "", "");
+ /* TODO, See how array size of 0 works, this shouldnt be used. */
+ prop = RNA_def_float_array(func, "rgba_values", 1, NULL, 0, 0, "", "RGBA Values", 0, 0);
+ RNA_def_property_flag(prop, PROP_DYNAMIC);
+ RNA_def_function_output(func, prop);
+}
+
static void def_glossy(StructRNA *srna)
{
PropertyRNA *prop;
@@ -4233,6 +4540,24 @@ static void def_node_image_user(StructRNA *srna)
RNA_def_property_flag(prop, PROP_ENUM_NO_TRANSLATE);
RNA_def_property_ui_text(prop, "Layer", "");
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_image_layer_update");
+
+ prop = RNA_def_property(srna, "has_layers", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_funcs(prop, "rna_Node_image_has_layers_get", NULL);
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_property_ui_text(prop, "Has Layers", "True if this image has any named layer");
+
+ prop = RNA_def_property(srna, "view", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "view");
+ RNA_def_property_enum_items(prop, prop_image_view_items);
+ RNA_def_property_enum_funcs(prop, NULL, NULL, "rna_Node_image_view_itemf");
+ RNA_def_property_flag(prop, PROP_ENUM_NO_TRANSLATE);
+ RNA_def_property_ui_text(prop, "View", "");
+ RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
+
+ prop = RNA_def_property(srna, "has_views", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_funcs(prop, "rna_Node_image_has_views_get", NULL);
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_property_ui_text(prop, "Has View", "True if this image has multiple views");
}
static void def_cmp_image(StructRNA *srna)
@@ -4449,7 +4774,7 @@ static void def_cmp_dilate_erode(StructRNA *srna)
RNA_def_property_enum_sdna(prop, NULL, "falloff");
RNA_def_property_enum_items(prop, proportional_falloff_curve_only_items);
RNA_def_property_ui_text(prop, "Falloff", "Falloff type the feather");
- RNA_def_property_translation_context(prop, BLF_I18NCONTEXT_ID_CURVE); /* Abusing id_curve :/ */
+ RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_CURVE); /* Abusing id_curve :/ */
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
}
@@ -4637,9 +4962,9 @@ static void def_cmp_color_spill(StructRNA *srna)
};
static EnumPropertyItem limit_channel_items[] = {
- {1, "R", 0, "R", "Limit by Red"},
- {2, "G", 0, "G", "Limit by Green"},
- {3, "B", 0, "B", "Limit by Blue"},
+ {0, "R", 0, "R", "Limit by Red"},
+ {1, "G", 0, "G", "Limit by Green"},
+ {2, "B", 0, "B", "Limit by Blue"},
{0, NULL, 0, NULL, NULL}
};
@@ -4957,7 +5282,7 @@ static void def_cmp_defocus(StructRNA *srna)
prop = RNA_def_property(srna, "f_stop", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "fstop");
RNA_def_property_range(prop, 0.0f, 128.0f);
- RNA_def_property_ui_text(prop, "fStop",
+ RNA_def_property_ui_text(prop, "F-stop",
"Amount of focal blur, 128=infinity=perfect focus, half the value doubles "
"the blur radius");
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
@@ -5714,7 +6039,7 @@ static void def_cmp_bokehblur(StructRNA *srna)
prop = RNA_def_property(srna, "f_stop", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "custom3");
RNA_def_property_range(prop, 0.0f, 128.0f);
- RNA_def_property_ui_text(prop, "fStop",
+ RNA_def_property_ui_text(prop, "F-stop",
"Amount of focal blur, 128=infinity=perfect focus, half the value doubles "
"the blur radius");
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
@@ -5781,6 +6106,16 @@ static void def_cmp_switch(StructRNA *srna)
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
}
+static void def_cmp_switch_view(StructRNA *srna)
+{
+ PropertyRNA *prop;
+
+ prop = RNA_def_property(srna, "check", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "custom1", 0);
+ RNA_def_property_ui_text(prop, "Switch", "Off: first socket, On: second socket");
+ RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
+}
+
static void def_cmp_colorcorrection(StructRNA *srna)
{
PropertyRNA *prop;
@@ -6096,7 +6431,7 @@ static void def_cmp_keying(StructRNA *srna)
RNA_def_property_enum_sdna(prop, NULL, "feather_falloff");
RNA_def_property_enum_items(prop, proportional_falloff_curve_only_items);
RNA_def_property_ui_text(prop, "Feather Falloff", "Falloff type the feather");
- RNA_def_property_translation_context(prop, BLF_I18NCONTEXT_ID_CURVE); /* Abusing id_curve :/ */
+ RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_CURVE); /* Abusing id_curve :/ */
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
prop = RNA_def_property(srna, "feather_distance", PROP_INT, PROP_NONE);
@@ -6201,6 +6536,21 @@ static void def_cmp_planetrackdeform(StructRNA *srna)
RNA_def_property_string_sdna(prop, NULL, "plane_track_name");
RNA_def_property_ui_text(prop, "Plane Track", "");
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
+
+ prop = RNA_def_property(srna, "use_motion_blur", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", CMP_NODEFLAG_PLANETRACKDEFORM_MOTION_BLUR);
+ 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);
+ RNA_def_property_range(prop, 1, CMP_NODE_PLANETRACKDEFORM_MBLUR_SAMPLES_MAX);
+ RNA_def_property_ui_text(prop, "Samples", "Number of motion blur samples");
+ RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
+
+ prop = RNA_def_property(srna, "motion_blur_shutter", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_range(prop, 0.0, 1.0f);
+ RNA_def_property_ui_text(prop, "Shutter", "Exposure for motion blur as a factor of FPS");
+ RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
}
static void def_cmp_sunbeams(StructRNA *srna)
@@ -6249,14 +6599,12 @@ static void def_tex_image(StructRNA *srna)
RNA_def_property_ui_text(prop, "Image", "");
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
- /* is this supposed to be exposed? not sure.. */
-#if 0
- prop = RNA_def_property(srna, "settings", PROP_POINTER, PROP_NONE);
+ prop = RNA_def_property(srna, "image_user", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "storage");
RNA_def_property_struct_type(prop, "ImageUser");
- RNA_def_property_ui_text(prop, "Settings", "");
+ RNA_def_property_ui_text(prop, "Image User",
+ "Parameters defining the image duration, offset and related settings");
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
-#endif
}
static void def_tex_bricks(StructRNA *srna)
@@ -7093,7 +7441,13 @@ static void rna_def_node(BlenderRNA *brna)
static EnumPropertyItem dummy_static_type_items[] = {
{NODE_CUSTOM, "CUSTOM", 0, "Custom", "Custom Node"},
{0, NULL, 0, NULL, NULL}};
-
+
+ static EnumPropertyItem node_shading_compatibilities[] = {
+ {NODE_OLD_SHADING, "OLD_SHADING", 0, "Old Shading", "Old shading system compatibility"},
+ {NODE_NEW_SHADING, "NEW_SHADING", 0, "New Shading", "New shading system compatibility"},
+ {0, NULL, 0, NULL, NULL}
+ };
+
srna = RNA_def_struct(brna, "Node", NULL);
RNA_def_struct_ui_text(srna, "Node", "Node in a node tree");
RNA_def_struct_sdna(srna, "bNode");
@@ -7233,6 +7587,12 @@ static void rna_def_node(BlenderRNA *brna)
parm = RNA_def_boolean(func, "result", false, "Result", "");
RNA_def_function_return(func, parm);
+ prop = RNA_def_property(srna, "shading_compatibility", PROP_ENUM, PROP_NONE);
+ RNA_def_property_flag(prop, PROP_ENUM_FLAG);
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_property_enum_sdna(prop, NULL, "typeinfo->compatibility");
+ RNA_def_property_enum_items(prop, node_shading_compatibilities);
+
/* registration */
prop = RNA_def_property(srna, "bl_idname", PROP_STRING, PROP_NONE);
RNA_def_property_string_sdna(prop, NULL, "typeinfo->idname");
@@ -7572,8 +7932,8 @@ static void rna_def_nodetree(BlenderRNA *brna)
/* Grease Pencil */
prop = RNA_def_property(srna, "grease_pencil", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "gpd");
- RNA_def_property_flag(prop, PROP_EDITABLE);
RNA_def_property_struct_type(prop, "GreasePencil");
+ RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_REFCOUNT);
RNA_def_property_ui_text(prop, "Grease Pencil Data", "Grease Pencil datablock");
RNA_def_property_update(prop, NC_NODE, NULL);
diff --git a/source/blender/makesrna/intern/rna_object.c b/source/blender/makesrna/intern/rna_object.c
index 690468a5278..54f1798b10c 100644
--- a/source/blender/makesrna/intern/rna_object.c
+++ b/source/blender/makesrna/intern/rna_object.c
@@ -42,10 +42,12 @@
#include "BLI_utildefines.h"
#include "BLI_listbase.h"
+#include "BKE_camera.h"
#include "BKE_paint.h"
#include "BKE_editmesh.h"
#include "BKE_group.h" /* needed for BKE_group_object_exists() */
-#include "BKE_object.h" /* Needed for BKE_object_matrix_local_get() */
+#include "BKE_object_deform.h"
+
#include "RNA_access.h"
#include "RNA_define.h"
#include "RNA_enum_types.h"
@@ -85,8 +87,6 @@ EnumPropertyItem object_empty_drawtype_items[] = {
static EnumPropertyItem parent_type_items[] = {
{PAROBJECT, "OBJECT", 0, "Object", "The object is parented to an object"},
- {PARCURVE, "CURVE", 0, "Curve", "The object is parented to a curve"},
- {PARKEY, "KEY", 0, "Key", ""},
{PARSKEL, "ARMATURE", 0, "Armature", ""},
{PARSKEL, "LATTICE", 0, "Lattice", "The object is parented to a lattice"}, /* PARSKEL reuse will give issues */
{PARVERT1, "VERTEX", 0, "Vertex", "The object is parented to a vertex"},
@@ -199,7 +199,6 @@ EnumPropertyItem object_axis_unsigned_items[] = {
#include "BKE_scene.h"
#include "BKE_deform.h"
-#include "ED_mesh.h"
#include "ED_object.h"
#include "ED_particle.h"
#include "ED_curve.h"
@@ -231,21 +230,21 @@ static void rna_Object_matrix_local_get(PointerRNA *ptr, float values[16])
static void rna_Object_matrix_local_set(PointerRNA *ptr, const float values[16])
{
Object *ob = ptr->id.data;
+ float local_mat[4][4];
- /* localspace matrix is truly relative to the parent, but parameters
- * stored in object are relative to parentinv matrix. Undo the parent
- * inverse part before updating obmat and calling apply_obmat() */
+ /* localspace matrix is truly relative to the parent, but parameters stored in object are
+ * relative to parentinv matrix. Undo the parent inverse part before applying it as local matrix. */
if (ob->parent) {
float invmat[4][4];
invert_m4_m4(invmat, ob->parentinv);
- mul_m4_m4m4(ob->obmat, invmat, (float(*)[4])values);
+ mul_m4_m4m4(local_mat, invmat, (float(*)[4])values);
}
else {
- copy_m4_m4(ob->obmat, (float(*)[4])values);
+ copy_m4_m4(local_mat, (float(*)[4])values);
}
- /* don't use compat so we get predictable rotation */
- BKE_object_apply_mat4(ob, ob->obmat, false, false);
+ /* don't use compat so we get predictable rotation, and do not use parenting either, because it's a local matrix! */
+ BKE_object_apply_mat4(ob, local_mat, false, false);
}
static void rna_Object_matrix_basis_get(PointerRNA *ptr, float values[16])
@@ -466,16 +465,13 @@ static EnumPropertyItem *rna_Object_parent_type_itemf(bContext *UNUSED(C), Point
if (ob->parent) {
Object *par = ob->parent;
- if (par->type == OB_CURVE) {
- RNA_enum_items_add_value(&item, &totitem, parent_type_items, PARCURVE);
- }
- else if (par->type == OB_LATTICE) {
+ if (par->type == OB_LATTICE) {
/* special hack: prevents this overriding others */
- RNA_enum_items_add_value(&item, &totitem, &parent_type_items[4], PARSKEL);
+ RNA_enum_items_add_value(&item, &totitem, &parent_type_items[2], PARSKEL);
}
else if (par->type == OB_ARMATURE) {
/* special hack: prevents this being overrided */
- RNA_enum_items_add_value(&item, &totitem, &parent_type_items[3], PARSKEL);
+ RNA_enum_items_add_value(&item, &totitem, &parent_type_items[1], PARSKEL);
RNA_enum_items_add_value(&item, &totitem, parent_type_items, PARBONE);
}
@@ -505,7 +501,9 @@ static EnumPropertyItem *rna_Object_collision_bounds_itemf(bContext *UNUSED(C),
EnumPropertyItem *item = NULL;
int totitem = 0;
- RNA_enum_items_add_value(&item, &totitem, collision_bounds_items, OB_BOUND_TRIANGLE_MESH);
+ if (ob->body_type != OB_BODY_TYPE_CHARACTER) {
+ RNA_enum_items_add_value(&item, &totitem, collision_bounds_items, OB_BOUND_TRIANGLE_MESH);
+ }
RNA_enum_items_add_value(&item, &totitem, collision_bounds_items, OB_BOUND_CONVEX_HULL);
if (ob->body_type != OB_BODY_TYPE_SOFT) {
@@ -583,7 +581,7 @@ static void rna_Object_active_vertex_group_index_range(PointerRNA *ptr, int *min
Object *ob = (Object *)ptr->id.data;
*min = 0;
- *max = max_ii(0, BLI_countlist(&ob->defbase) - 1);
+ *max = max_ii(0, BLI_listbase_count(&ob->defbase) - 1);
}
void rna_object_vgroup_name_index_get(PointerRNA *ptr, char *value, int index)
@@ -637,7 +635,7 @@ void rna_object_uvlayer_name_set(PointerRNA *ptr, const char *value, char *resul
for (a = 0; a < me->pdata.totlayer; a++) {
layer = &me->pdata.layers[a];
- if (layer->type == CD_MTEXPOLY && strcmp(layer->name, value) == 0) {
+ if (layer->type == CD_MTEXPOLY && STREQ(layer->name, value)) {
BLI_strncpy(result, value, maxlen);
return;
}
@@ -660,7 +658,7 @@ void rna_object_vcollayer_name_set(PointerRNA *ptr, const char *value, char *res
for (a = 0; a < me->fdata.totlayer; a++) {
layer = &me->fdata.layers[a];
- if (layer->type == CD_MCOL && strcmp(layer->name, value) == 0) {
+ if (layer->type == CD_MCOL && STREQ(layer->name, value)) {
BLI_strncpy(result, value, maxlen);
return;
}
@@ -712,7 +710,7 @@ static void rna_Object_active_material_set(PointerRNA *ptr, PointerRNA value)
Object *ob = (Object *)ptr->id.data;
DAG_id_tag_update(value.data, 0);
- assign_material(ob, value.data, ob->actcol, BKE_MAT_ASSIGN_USERPREF);
+ assign_material(ob, value.data, ob->actcol, BKE_MAT_ASSIGN_EXISTING);
}
static int rna_Object_active_material_editable(PointerRNA *ptr)
@@ -736,7 +734,7 @@ static void rna_Object_active_particle_system_index_range(PointerRNA *ptr, int *
{
Object *ob = (Object *)ptr->id.data;
*min = 0;
- *max = max_ii(0, BLI_countlist(&ob->particlesystem) - 1);
+ *max = max_ii(0, BLI_listbase_count(&ob->particlesystem) - 1);
}
static int rna_Object_active_particle_system_index_get(PointerRNA *ptr)
@@ -775,7 +773,7 @@ static void rna_Object_rotation_axis_angle_set(PointerRNA *ptr, const float *val
/* for now, assume that rotation mode is axis-angle */
ob->rotAngle = value[0];
- copy_v3_v3(ob->rotAxis, (float *)&value[1]);
+ copy_v3_v3(ob->rotAxis, &value[1]);
/* TODO: validate axis? */
}
@@ -884,7 +882,7 @@ static void rna_MaterialSlot_material_set(PointerRNA *ptr, PointerRNA value)
Object *ob = (Object *)ptr->id.data;
int index = (Material **)ptr->data - ob->mat;
- assign_material(ob, value.data, index + 1, BKE_MAT_ASSIGN_USERPREF);
+ assign_material(ob, value.data, index + 1, BKE_MAT_ASSIGN_EXISTING);
}
static int rna_MaterialSlot_link_get(PointerRNA *ptr)
@@ -941,8 +939,10 @@ static void rna_MaterialSlot_name_get(PointerRNA *ptr, char *str)
static void rna_MaterialSlot_update(Main *bmain, Scene *scene, PointerRNA *ptr)
{
rna_Object_internal_update(bmain, scene, ptr);
+
WM_main_add_notifier(NC_OBJECT | ND_OB_SHADING, ptr->id.data);
WM_main_add_notifier(NC_MATERIAL | ND_SHADING_LINKS, NULL);
+ DAG_relations_tag_update(bmain);
}
static char *rna_MaterialSlot_path(PointerRNA *ptr)
@@ -1003,7 +1003,7 @@ static int rna_GameObjectSettings_physics_type_get(PointerRNA *ptr)
static void rna_GameObjectSettings_physics_type_set(PointerRNA *ptr, int value)
{
Object *ob = (Object *)ptr->id.data;
- const int was_navmesh = (ob->gameflag & OB_NAVMESH);
+ const int gameflag_prev = ob->gameflag;
ob->body_type = value;
switch (ob->body_type) {
@@ -1061,7 +1061,7 @@ static void rna_GameObjectSettings_physics_type_set(PointerRNA *ptr, int value)
break;
}
- if (was_navmesh != (ob->gameflag & OB_NAVMESH)) {
+ if ((gameflag_prev & OB_NAVMESH) != (ob->gameflag & OB_NAVMESH)) {
if (ob->type == OB_MESH) {
/* this is needed to refresh the derived meshes draw func */
DAG_id_tag_update(ptr->id.data, OB_RECALC_DATA);
@@ -1134,7 +1134,7 @@ static void rna_GameObjectSettings_state_get(PointerRNA *ptr, int *values)
memset(values, 0, sizeof(int) * OB_MAX_STATES);
for (i = 0; i < OB_MAX_STATES; i++) {
- values[i] = (ob->state & (1 << i)) | all_states;
+ values[i] = (ob->state & (1 << i)) ? 1 : 0 | all_states;
}
}
@@ -1179,7 +1179,7 @@ static void rna_GameObjectSettings_col_group_get(PointerRNA *ptr, int *values)
int i;
for (i = 0; i < OB_MAX_COL_MASKS; i++) {
- values[i] = (ob->col_group & (1 << i));
+ values[i] = (ob->col_group & (1 << i)) != 0;
}
}
@@ -1208,7 +1208,7 @@ static void rna_GameObjectSettings_col_mask_get(PointerRNA *ptr, int *values)
int i;
for (i = 0; i < OB_MAX_COL_MASKS; i++) {
- values[i] = (ob->col_mask & (1 << i));
+ values[i] = (ob->col_mask & (1 << i)) != 0;
}
}
@@ -1240,7 +1240,7 @@ static void rna_Object_active_shape_key_index_range(PointerRNA *ptr, int *min, i
*min = 0;
if (key) {
- *max = BLI_countlist(&key->block) - 1;
+ *max = BLI_listbase_count(&key->block) - 1;
if (*max < 0) *max = 0;
}
else {
@@ -1381,14 +1381,14 @@ static void rna_Object_boundbox_get(PointerRNA *ptr, float *values)
memcpy(values, bb->vec, sizeof(bb->vec));
}
else {
- fill_vn_fl(values, sizeof(bb->vec) / sizeof(float), 0.0f);
+ copy_vn_fl(values, sizeof(bb->vec) / sizeof(float), 0.0f);
}
}
static bDeformGroup *rna_Object_vgroup_new(Object *ob, const char *name)
{
- bDeformGroup *defgroup = ED_vgroup_add_name(ob, name);
+ bDeformGroup *defgroup = BKE_object_defgroup_add_name(ob, name);
WM_main_add_notifier(NC_OBJECT | ND_DRAW, ob);
@@ -1403,7 +1403,7 @@ static void rna_Object_vgroup_remove(Object *ob, ReportList *reports, PointerRNA
return;
}
- ED_vgroup_delete(ob, defgroup);
+ BKE_object_defgroup_remove(ob, defgroup);
RNA_POINTER_INVALIDATE(defgroup_ptr);
WM_main_add_notifier(NC_OBJECT | ND_DRAW, ob);
@@ -1411,7 +1411,7 @@ static void rna_Object_vgroup_remove(Object *ob, ReportList *reports, PointerRNA
static void rna_Object_vgroup_clear(Object *ob)
{
- ED_vgroup_clear(ob);
+ BKE_object_defgroup_remove_all(ob);
WM_main_add_notifier(NC_OBJECT | ND_DRAW, ob);
}
@@ -1421,7 +1421,7 @@ static void rna_VertexGroup_vertex_add(ID *id, bDeformGroup *def, ReportList *re
{
Object *ob = (Object *)id;
- if (ED_vgroup_object_is_edit_mode(ob)) {
+ if (BKE_object_is_in_editmode_vgroup(ob)) {
BKE_report(reports, RPT_ERROR, "VertexGroup.add(): cannot be called while object is in edit mode");
return;
}
@@ -1436,7 +1436,7 @@ static void rna_VertexGroup_vertex_remove(ID *id, bDeformGroup *dg, ReportList *
{
Object *ob = (Object *)id;
- if (ED_vgroup_object_is_edit_mode(ob)) {
+ if (BKE_object_is_in_editmode_vgroup(ob)) {
BKE_report(reports, RPT_ERROR, "VertexGroup.remove(): cannot be called while object is in edit mode");
return;
}
@@ -1627,7 +1627,7 @@ static void rna_def_object_game_settings(BlenderRNA *brna)
{OB_BODY_TYPE_DYNAMIC, "DYNAMIC", 0, "Dynamic", "Linear physics"},
{OB_BODY_TYPE_RIGID, "RIGID_BODY", 0, "Rigid Body", "Linear and angular physics"},
{OB_BODY_TYPE_SOFT, "SOFT_BODY", 0, "Soft Body", "Soft body"},
- {OB_BODY_TYPE_OCCLUDER, "OCCLUDE", 0, "Occlude", "Occluder for optimizing scene rendering"},
+ {OB_BODY_TYPE_OCCLUDER, "OCCLUDER", 0, "Occluder", "Occluder for optimizing scene rendering"},
{OB_BODY_TYPE_SENSOR, "SENSOR", 0, "Sensor",
"Collision Sensor, detects static and dynamic objects but not the other "
"collision sensor objects"},
@@ -1680,6 +1680,7 @@ static void rna_def_object_game_settings(BlenderRNA *brna)
prop = RNA_def_property(srna, "physics_type", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "body_type");
RNA_def_property_enum_items(prop, body_type_items);
+ RNA_def_property_enum_default(prop, OB_BODY_TYPE_STATIC);
RNA_def_property_enum_funcs(prop, "rna_GameObjectSettings_physics_type_get",
"rna_GameObjectSettings_physics_type_set", NULL);
RNA_def_property_ui_text(prop, "Physics Type", "Select the type of physical representation");
@@ -1699,12 +1700,14 @@ static void rna_def_object_game_settings(BlenderRNA *brna)
prop = RNA_def_property(srna, "mass", PROP_FLOAT, PROP_NONE);
RNA_def_property_range(prop, 0.01, 10000.0);
+ RNA_def_property_float_default(prop, 1.0f);
RNA_def_property_ui_text(prop, "Mass", "Mass of the object");
prop = RNA_def_property(srna, "radius", PROP_FLOAT, PROP_NONE | PROP_UNIT_LENGTH);
RNA_def_property_float_sdna(prop, NULL, "inertia");
RNA_def_property_range(prop, 0.01f, FLT_MAX);
RNA_def_property_ui_range(prop, 0.01f, 10.0f, 1, 3);
+ RNA_def_property_float_default(prop, 1.0f);
RNA_def_property_ui_text(prop, "Radius", "Radius of bounding sphere and material physics");
RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, NULL);
@@ -1715,37 +1718,57 @@ static void rna_def_object_game_settings(BlenderRNA *brna)
prop = RNA_def_property(srna, "damping", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "damping");
RNA_def_property_range(prop, 0.0, 1.0);
+ RNA_def_property_float_default(prop, 0.04f);
RNA_def_property_ui_text(prop, "Damping", "General movement damping");
prop = RNA_def_property(srna, "rotation_damping", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "rdamping");
RNA_def_property_range(prop, 0.0, 1.0);
+ RNA_def_property_float_default(prop, 0.1f);
RNA_def_property_ui_text(prop, "Rotation Damping", "General rotation damping");
- prop = RNA_def_property(srna, "velocity_min", PROP_FLOAT, PROP_NONE);
+ prop = RNA_def_property(srna, "velocity_min", PROP_FLOAT, PROP_DISTANCE);
RNA_def_property_float_sdna(prop, NULL, "min_vel");
RNA_def_property_range(prop, 0.0, 1000.0);
- RNA_def_property_ui_text(prop, "Velocity Min", "Clamp velocity to this minimum speed (except when totally still)");
+ RNA_def_property_ui_text(prop, "Velocity Min", "Clamp velocity to this minimum speed (except when totally still), "
+ "in distance per second");
- prop = RNA_def_property(srna, "velocity_max", PROP_FLOAT, PROP_NONE);
+ prop = RNA_def_property(srna, "velocity_max", PROP_FLOAT, PROP_DISTANCE);
RNA_def_property_float_sdna(prop, NULL, "max_vel");
RNA_def_property_range(prop, 0.0, 1000.0);
- RNA_def_property_ui_text(prop, "Velocity Max", "Clamp velocity to this maximum speed");
+ RNA_def_property_ui_text(prop, "Velocity Max", "Clamp velocity to this maximum speed, "
+ "in distance per second");
+ prop = RNA_def_property(srna, "angular_velocity_min", PROP_FLOAT, PROP_ANGLE);
+ RNA_def_property_float_sdna(prop, NULL, "min_angvel");
+ RNA_def_property_range(prop, 0.0, 1000.0);
+ RNA_def_property_ui_text(prop, "Angular Velocity Min",
+ "Clamp angular velocity to this minimum speed (except when totally still), "
+ "in angle per second");
+
+ prop = RNA_def_property(srna, "angular_velocity_max", PROP_FLOAT, PROP_ANGLE);
+ RNA_def_property_float_sdna(prop, NULL, "max_angvel");
+ RNA_def_property_range(prop, 0.0, 1000.0);
+ RNA_def_property_ui_text(prop, "Angular Velocity Max", "Clamp angular velocity to this maximum speed, "
+ "in angle per second");
+
/* Character physics */
prop = RNA_def_property(srna, "step_height", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "step_height");
RNA_def_property_range(prop, 0.01, 1.0);
+ RNA_def_property_float_default(prop, 0.15f);
RNA_def_property_ui_text(prop, "Step Height", "Maximum height of steps the character can run over");
prop = RNA_def_property(srna, "jump_speed", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "jump_speed");
RNA_def_property_range(prop, 0.0, 1000.0);
+ RNA_def_property_float_default(prop, 10.0f);
RNA_def_property_ui_text(prop, "Jump Force", "Upward velocity applied to the character when jumping");
prop = RNA_def_property(srna, "fall_speed", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "fall_speed");
RNA_def_property_range(prop, 0.0, 1000.0);
+ RNA_def_property_float_default(prop, 55.0f);
RNA_def_property_ui_text(prop, "Fall Speed Max", "Maximum speed at which the character will fall");
/* Collision Masks */
@@ -1806,13 +1829,14 @@ static void rna_def_object_game_settings(BlenderRNA *brna)
prop = RNA_def_property(srna, "form_factor", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "formfactor");
RNA_def_property_range(prop, 0.0, 1.0);
+ RNA_def_property_float_default(prop, 0.4f);
RNA_def_property_ui_text(prop, "Form Factor", "Form factor scales the inertia tensor");
prop = RNA_def_property(srna, "use_anisotropic_friction", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "gameflag", OB_ANISOTROPIC_FRICTION);
RNA_def_property_ui_text(prop, "Anisotropic Friction", "Enable anisotropic friction");
- prop = RNA_def_property(srna, "friction_coefficients", PROP_FLOAT, PROP_NONE);
+ prop = RNA_def_property(srna, "friction_coefficients", PROP_FLOAT, PROP_XYZ);
RNA_def_property_float_sdna(prop, NULL, "anisotropicFriction");
RNA_def_property_range(prop, 0.0, 1.0);
RNA_def_property_ui_text(prop, "Friction Coefficients",
@@ -1828,7 +1852,7 @@ static void rna_def_object_game_settings(BlenderRNA *brna)
RNA_def_property_enum_sdna(prop, NULL, "collision_boundtype");
RNA_def_property_enum_items(prop, collision_bounds_items);
RNA_def_property_enum_funcs(prop, NULL, NULL, "rna_Object_collision_bounds_itemf");
- RNA_def_property_ui_text(prop, "Collision Bounds", "Select the collision type");
+ RNA_def_property_ui_text(prop, "Collision Shape", "Select the collision shape that better fits the object");
RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, NULL);
prop = RNA_def_property(srna, "use_collision_compound", PROP_BOOLEAN, PROP_NONE);
@@ -1838,6 +1862,7 @@ static void rna_def_object_game_settings(BlenderRNA *brna)
prop = RNA_def_property(srna, "collision_margin", PROP_FLOAT, PROP_NONE | PROP_UNIT_LENGTH);
RNA_def_property_float_sdna(prop, NULL, "margin");
RNA_def_property_range(prop, 0.0, 1.0);
+ RNA_def_property_float_default(prop, 0.04f);
RNA_def_property_ui_text(prop, "Collision Margin",
"Extra margin around object for collision detection, small amount required "
"for stability");
@@ -1853,6 +1878,7 @@ static void rna_def_object_game_settings(BlenderRNA *brna)
prop = RNA_def_property(srna, "obstacle_radius", PROP_FLOAT, PROP_NONE | PROP_UNIT_LENGTH);
RNA_def_property_float_sdna(prop, NULL, "obstacleRad");
RNA_def_property_range(prop, 0.0, 1000.0);
+ RNA_def_property_float_default(prop, 1.0f);
RNA_def_property_ui_text(prop, "Obstacle Radius", "Radius of object representation in obstacle simulation");
/* state */
@@ -2083,6 +2109,14 @@ static void rna_def_object_lodlevel(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Distance", "Distance to begin using this level of detail");
RNA_def_property_update(prop, NC_OBJECT | ND_LOD, "rna_Object_lod_distance_update");
+ prop = RNA_def_property(srna, "object_hysteresis_percentage", PROP_INT, PROP_PERCENTAGE);
+ RNA_def_property_int_sdna(prop, NULL, "obhysteresis");
+ RNA_def_property_range(prop, 0, 100);
+ RNA_def_property_ui_range(prop, 0, 100, 10, 1);
+ RNA_def_property_ui_text(prop, "Hysteresis %",
+ "Minimum distance change required to transition to the previous level of detail");
+ RNA_def_property_update(prop, NC_OBJECT | ND_LOD, NULL);
+
prop = RNA_def_property(srna, "object", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "source");
RNA_def_property_struct_type(prop, "Object");
@@ -2101,6 +2135,11 @@ static void rna_def_object_lodlevel(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Use Material", "Use the material from this object at this level of detail");
RNA_def_property_ui_icon(prop, ICON_MATERIAL, 0);
RNA_def_property_update(prop, NC_OBJECT | ND_LOD, NULL);
+
+ prop = RNA_def_property(srna, "use_object_hysteresis", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flags", OB_LOD_USE_HYST);
+ RNA_def_property_ui_text(prop, "Hysteresis Override", "Override LoD Hysteresis scene setting for this LoD level");
+ RNA_def_property_update(prop, NC_OBJECT | ND_LOD, NULL);
}
@@ -2426,7 +2465,9 @@ static void rna_def_object(BlenderRNA *brna)
prop = RNA_def_property(srna, "matrix_local", PROP_FLOAT, PROP_MATRIX);
RNA_def_property_multi_array(prop, 2, rna_matrix_dimsize_4x4);
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
- RNA_def_property_ui_text(prop, "Local Matrix", "Parent relative transformation matrix");
+ RNA_def_property_ui_text(prop, "Local Matrix", "Parent relative transformation matrix - "
+ "WARNING: Only takes into account 'Object' parenting, so e.g. in case of bone parenting "
+ "you get a matrix relative to the Armature object, not to the actual parent bone");
RNA_def_property_float_funcs(prop, "rna_Object_matrix_local_get", "rna_Object_matrix_local_set", NULL);
RNA_def_property_update(prop, NC_OBJECT | ND_TRANSFORM, NULL);
@@ -2726,16 +2767,16 @@ static void rna_def_object(BlenderRNA *brna)
/* Grease Pencil */
prop = RNA_def_property(srna, "grease_pencil", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "gpd");
- RNA_def_property_flag(prop, PROP_EDITABLE);
RNA_def_property_struct_type(prop, "GreasePencil");
+ RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_REFCOUNT);
RNA_def_property_ui_text(prop, "Grease Pencil Data", "Grease Pencil datablock");
RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, NULL);
/* pose */
prop = RNA_def_property(srna, "pose_library", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "poselib");
- RNA_def_property_flag(prop, PROP_EDITABLE);
RNA_def_property_struct_type(prop, "Action");
+ RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_REFCOUNT);
RNA_def_property_ui_text(prop, "Pose Library", "Action used as a pose library for armatures");
prop = RNA_def_property(srna, "pose", PROP_POINTER, PROP_NONE);
diff --git a/source/blender/makesrna/intern/rna_object_api.c b/source/blender/makesrna/intern/rna_object_api.c
index 831e5486236..a446f119132 100644
--- a/source/blender/makesrna/intern/rna_object_api.c
+++ b/source/blender/makesrna/intern/rna_object_api.c
@@ -87,6 +87,8 @@ static EnumPropertyItem space_items[] = {
#include "MEM_guardedalloc.h"
+#include "DEG_depsgraph.h"
+
/* Convert a given matrix from a space to another (using the object and/or a bone as reference). */
static void rna_Scene_mat_convert_space(Object *ob, ReportList *reports, bPoseChannel *pchan,
float *mat, float *mat_ret, int from, int to)
@@ -109,7 +111,29 @@ static void rna_Scene_mat_convert_space(Object *ob, ReportList *reports, bPoseCh
}
}
- BKE_constraint_mat_convertspace(ob, pchan, (float (*)[4])mat_ret, from, to);
+ BKE_constraint_mat_convertspace(ob, pchan, (float (*)[4])mat_ret, from, to, false);
+}
+
+static void rna_Object_calc_matrix_camera(
+ Object *ob, float mat_ret[16], int width, int height, float scalex, float scaley)
+{
+ CameraParams params;
+
+ /* setup parameters */
+ BKE_camera_params_init(&params);
+ BKE_camera_params_from_object(&params, ob);
+
+ /* compute matrix, viewplane, .. */
+ BKE_camera_params_compute_viewplane(&params, width, height, scalex, scaley);
+ BKE_camera_params_compute_matrix(&params);
+
+ copy_m4_m4((float (*)[4])mat_ret, params.winmat);
+}
+
+static void rna_Object_camera_fit_coords(
+ Object *ob, Scene *scene, int num_cos, float *cos, float co_ret[3], float *scale_ret)
+{
+ BKE_camera_view_frame_fit_to_coords(scene, (const float (*)[3])cos, num_cos / 3, ob, co_ret, scale_ret);
}
/* copied from Mesh_getFromObject and adapted to RNA interface */
@@ -151,7 +175,7 @@ static void dupli_render_particle_set(Scene *scene, Object *ob, int level, int e
/* this is to make sure we get render level duplis in groups:
* the derivedmesh must be created before init_render_mesh,
* since object_duplilist does dupliparticles before that */
- dm = mesh_create_derived_render(scene, ob, CD_MASK_BAREMESH | CD_MASK_MTFACE | CD_MASK_MCOL);
+ dm = mesh_create_derived_render(scene, ob, CD_MASK_BAREMESH | CD_MASK_MLOOPUV | CD_MASK_MLOOPCOL);
dm->release(dm);
for (psys = ob->particlesystem.first; psys; psys = psys->next)
@@ -169,8 +193,8 @@ static void dupli_render_particle_set(Scene *scene, Object *ob, int level, int e
static void rna_Object_create_duplilist(Object *ob, ReportList *reports, Scene *sce, int settings)
{
bool for_render = (settings == DAG_EVAL_RENDER);
- EvaluationContext eval_ctx = {0};
- eval_ctx.mode = settings;
+ EvaluationContext eval_ctx;
+ DEG_evaluation_context_init(&eval_ctx, settings);
if (!(ob->transflag & OB_DUPLI)) {
BKE_report(reports, RPT_ERROR, "Object does not have duplis");
@@ -203,10 +227,9 @@ static void rna_Object_free_duplilist(Object *ob)
static PointerRNA rna_Object_shape_key_add(Object *ob, bContext *C, ReportList *reports,
const char *name, int from_mix)
{
- Scene *scene = CTX_data_scene(C);
KeyBlock *kb = NULL;
- if ((kb = BKE_object_insert_shape_key(scene, ob, name, from_mix))) {
+ if ((kb = BKE_object_shapekey_insert(ob, name, from_mix))) {
PointerRNA keyptr;
RNA_pointer_create((ID *)ob->data, &RNA_ShapeKey, kb, &keyptr);
@@ -220,6 +243,29 @@ static PointerRNA rna_Object_shape_key_add(Object *ob, bContext *C, ReportList *
}
}
+static void rna_Object_shape_key_remove(
+ Object *ob, Main *bmain, ReportList *reports,
+ PointerRNA *kb_ptr)
+{
+ KeyBlock *kb = kb_ptr->data;
+ Key *key = BKE_key_from_object(ob);
+
+ if ((key == NULL) || BLI_findindex(&key->block, kb) == -1) {
+ BKE_reportf(reports, RPT_ERROR, "ShapeKey not found");
+ return;
+ }
+
+ if (!BKE_object_shapekey_remove(bmain, ob, kb)) {
+ BKE_reportf(reports, RPT_ERROR, "Could not remove ShapeKey");
+ return;
+ }
+
+ DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ WM_main_add_notifier(NC_OBJECT | ND_DRAW, ob);
+
+ RNA_POINTER_INVALIDATE(kb_ptr);
+}
+
static int rna_Object_is_visible(Object *ob, Scene *sce)
{
return !(ob->restrictflag & OB_RESTRICT_VIEW) && (ob->lay & sce->lay);
@@ -263,18 +309,10 @@ static void rna_Mesh_assign_verts_to_group(Object *ob, bDeformGroup *group, int
#endif
/* don't call inside a loop */
-static int dm_tessface_to_poly_index(DerivedMesh *dm, int tessface_index)
+static int dm_looptri_to_poly_index(DerivedMesh *dm, const MLoopTri *lt)
{
- if (tessface_index != ORIGINDEX_NONE) {
- /* double lookup */
- const int *index_mf_to_mpoly;
- if ((index_mf_to_mpoly = dm->getTessFaceDataArray(dm, CD_ORIGINDEX))) {
- const int *index_mp_to_orig = dm->getPolyDataArray(dm, CD_ORIGINDEX);
- return DM_origindex_mface_mpoly(index_mf_to_mpoly, index_mp_to_orig, tessface_index);
- }
- }
-
- return ORIGINDEX_NONE;
+ const int *index_mp_to_orig = dm->getPolyDataArray(dm, CD_ORIGINDEX);
+ return index_mp_to_orig ? index_mp_to_orig[lt->poly] : lt->poly;
}
static void rna_Object_ray_cast(Object *ob, ReportList *reports, float ray_start[3], float ray_end[3],
@@ -288,7 +326,7 @@ static void rna_Object_ray_cast(Object *ob, ReportList *reports, float ray_start
}
/* no need to managing allocation or freeing of the BVH data. this is generated and freed as needed */
- bvhtree_from_mesh_faces(&treeData, ob->derivedFinal, 0.0f, 4, 6);
+ bvhtree_from_mesh_looptri(&treeData, ob->derivedFinal, 0.0f, 4, 6);
/* may fail if the mesh has no faces, in that case the ray-cast misses */
if (treeData.tree != NULL) {
@@ -305,7 +343,7 @@ static void rna_Object_ray_cast(Object *ob, ReportList *reports, float ray_start
if (hit.dist <= dist) {
copy_v3_v3(r_location, hit.co);
copy_v3_v3(r_normal, hit.no);
- *index = dm_tessface_to_poly_index(ob->derivedFinal, hit.index);
+ *index = dm_looptri_to_poly_index(ob->derivedFinal, &treeData.looptri[hit.index]);
free_bvhtree_from_mesh(&treeData);
return;
}
@@ -330,7 +368,7 @@ static void rna_Object_closest_point_on_mesh(Object *ob, ReportList *reports, fl
}
/* no need to managing allocation or freeing of the BVH data. this is generated and freed as needed */
- bvhtree_from_mesh_faces(&treeData, ob->derivedFinal, 0.0f, 4, 6);
+ bvhtree_from_mesh_looptri(&treeData, ob->derivedFinal, 0.0f, 4, 6);
if (treeData.tree == NULL) {
BKE_reportf(reports, RPT_ERROR, "Object '%s' could not create internal data for finding nearest point",
@@ -346,7 +384,7 @@ static void rna_Object_closest_point_on_mesh(Object *ob, ReportList *reports, fl
if (BLI_bvhtree_find_nearest(treeData.tree, point_co, &nearest, treeData.nearest_callback, &treeData) != -1) {
copy_v3_v3(n_location, nearest.co);
copy_v3_v3(n_normal, nearest.no);
- *index = dm_tessface_to_poly_index(ob->derivedFinal, nearest.index);
+ *index = dm_looptri_to_poly_index(ob->derivedFinal, &treeData.looptri[nearest.index]);
free_bvhtree_from_mesh(&treeData);
return;
}
@@ -468,6 +506,35 @@ void RNA_api_object(StructRNA *srna)
parm = RNA_def_enum(func, "to_space", space_items, CONSTRAINT_SPACE_WORLD, "",
"The space to which you want to transform 'matrix'");
+ /* Camera-related operations */
+ func = RNA_def_function(srna, "calc_matrix_camera", "rna_Object_calc_matrix_camera");
+ RNA_def_function_ui_description(func, "Generate the camera projection matrix of this object "
+ "(mostly useful for Camera and Lamp types)");
+ parm = RNA_def_property(func, "result", PROP_FLOAT, PROP_MATRIX);
+ RNA_def_property_multi_array(parm, 2, rna_matrix_dimsize_4x4);
+ RNA_def_property_ui_text(parm, "", "The camera projection matrix");
+ RNA_def_function_output(func, parm);
+ parm = RNA_def_int(func, "x", 1, 0, INT_MAX, "", "Width of the render area", 0, 10000);
+ parm = RNA_def_int(func, "y", 1, 0, INT_MAX, "", "Height of the render area", 0, 10000);
+ parm = RNA_def_float(func, "scale_x", 1.0f, 1.0e-6f, FLT_MAX, "", "Width scaling factor", 1.0e-2f, 100.0f);
+ parm = RNA_def_float(func, "scale_y", 1.0f, 1.0e-6f, FLT_MAX, "", "height scaling factor", 1.0e-2f, 100.0f);
+
+ func = RNA_def_function(srna, "camera_fit_coords", "rna_Object_camera_fit_coords");
+ RNA_def_function_ui_description(func, "Compute the coordinate (and scale for ortho cameras) "
+ "given object should be to 'see' all given coordinates");
+ parm = RNA_def_pointer(func, "scene", "Scene", "", "Scene to get render size information from, if available");
+ RNA_def_property_flag(parm, PROP_REQUIRED);
+ parm = RNA_def_float_array(func, "coordinates", 1, NULL, -FLT_MAX, FLT_MAX, "", "Coordinates to fit in",
+ -FLT_MAX, FLT_MAX);
+ RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL | PROP_DYNAMIC);
+ parm = RNA_def_property(func, "co_return", PROP_FLOAT, PROP_XYZ);
+ RNA_def_property_array(parm, 3);
+ RNA_def_property_ui_text(parm, "", "The location to aim to be able to see all given points");
+ RNA_def_property_flag(parm, PROP_OUTPUT);
+ parm = RNA_def_property(func, "scale_return", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_ui_text(parm, "", "The ortho scale to aim to be able to see all given points (if relevant)");
+ RNA_def_property_flag(parm, PROP_OUTPUT);
+
/* mesh */
func = RNA_def_function(srna, "to_mesh", "rna_Object_to_mesh");
RNA_def_function_ui_description(func, "Create a Mesh datablock with modifiers applied");
@@ -505,14 +572,21 @@ void RNA_api_object(StructRNA *srna)
/* Shape key */
func = RNA_def_function(srna, "shape_key_add", "rna_Object_shape_key_add");
- RNA_def_function_ui_description(func, "Add shape key to an object");
+ RNA_def_function_ui_description(func, "Add shape key to this object");
RNA_def_function_flag(func, FUNC_USE_CONTEXT | FUNC_USE_REPORTS);
- RNA_def_string(func, "name", "Key", 0, "", "Unique name for the new keylock"); /* optional */
+ RNA_def_string(func, "name", "Key", 0, "", "Unique name for the new keyblock"); /* optional */
RNA_def_boolean(func, "from_mix", 1, "", "Create new shape from existing mix of shapes");
parm = RNA_def_pointer(func, "key", "ShapeKey", "", "New shape keyblock");
RNA_def_property_flag(parm, PROP_RNAPTR);
RNA_def_function_return(func, parm);
+ func = RNA_def_function(srna, "shape_key_remove", "rna_Object_shape_key_remove");
+ RNA_def_function_ui_description(func, "Remove a Shape Key from this object");
+ RNA_def_function_flag(func, FUNC_USE_MAIN | FUNC_USE_REPORTS);
+ parm = RNA_def_pointer(func, "key", "ShapeKey", "", "Keyblock to be removed");
+ RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL | PROP_RNAPTR);
+ RNA_def_property_clear_flag(parm, PROP_THICK_WRAP);
+
/* Ray Cast */
func = RNA_def_function(srna, "ray_cast", "rna_Object_ray_cast");
RNA_def_function_ui_description(func, "Cast a ray onto in object space");
@@ -539,7 +613,7 @@ void RNA_api_object(StructRNA *srna)
/* Nearest Point */
func = RNA_def_function(srna, "closest_point_on_mesh", "rna_Object_closest_point_on_mesh");
- RNA_def_function_ui_description(func, "Find the nearest point on the object");
+ RNA_def_function_ui_description(func, "Find the nearest point in object space");
RNA_def_function_flag(func, FUNC_USE_REPORTS);
/* location of point for test and max distance */
@@ -605,6 +679,9 @@ void RNA_api_object(StructRNA *srna)
RNA_def_function_ui_description(func, "Load the objects edit-mode data intp the object data");
parm = RNA_def_boolean(func, "result", 0, "", "Success");
RNA_def_function_return(func, parm);
+
+ func = RNA_def_function(srna, "cache_release", "BKE_object_free_caches");
+ RNA_def_function_ui_description(func, "Release memory used by caches associated with this object. Intended to be used by render engines only");
}
diff --git a/source/blender/makesrna/intern/rna_object_force.c b/source/blender/makesrna/intern/rna_object_force.c
index 8da869417ff..75becb341b9 100644
--- a/source/blender/makesrna/intern/rna_object_force.c
+++ b/source/blender/makesrna/intern/rna_object_force.c
@@ -190,7 +190,7 @@ static void rna_Cache_idname_change(Main *UNUSED(bmain), Scene *UNUSED(scene), P
for (pid = pidlist.first; pid; pid = pid->next) {
if (pid->cache == cache)
pid2 = pid;
- else if (cache->name[0] != '\0' && strcmp(cache->name, pid->cache->name) == 0) {
+ else if (cache->name[0] != '\0' && STREQ(cache->name, pid->cache->name)) {
/*TODO: report "name exists" to user */
BLI_strncpy(cache->name, cache->prev_name, sizeof(cache->name));
new_name = 0;
@@ -243,7 +243,7 @@ static void rna_Cache_active_point_cache_index_range(PointerRNA *ptr, int *min,
for (pid = pidlist.first; pid; pid = pid->next) {
if (pid->cache == cache) {
- *max = max_ii(0, BLI_countlist(pid->ptcaches) - 1);
+ *max = max_ii(0, BLI_listbase_count(pid->ptcaches) - 1);
break;
}
}
@@ -845,7 +845,7 @@ static void rna_def_pointcache(BlenderRNA *brna)
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_ui_text(prop, "Cache is outdated", "");
- prop = RNA_def_property(srna, "frames_skipped", PROP_BOOLEAN, PROP_NONE);
+ prop = RNA_def_property(srna, "is_frame_skip", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", PTCACHE_FRAMES_SKIPPED);
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
diff --git a/source/blender/makesrna/intern/rna_palette.c b/source/blender/makesrna/intern/rna_palette.c
new file mode 100644
index 00000000000..8cbb57fde2c
--- /dev/null
+++ b/source/blender/makesrna/intern/rna_palette.c
@@ -0,0 +1,181 @@
+/*
+ * ***** 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/makesrna/intern/rna_palette.c
+ * \ingroup RNA
+ */
+
+#include <stdlib.h>
+
+#include "BLI_utildefines.h"
+
+#include "RNA_define.h"
+#include "RNA_access.h"
+
+#include "rna_internal.h"
+
+#include "WM_types.h"
+
+#ifdef RNA_RUNTIME
+
+#include "DNA_brush_types.h"
+
+#include "BKE_paint.h"
+#include "BKE_report.h"
+
+static PaletteColor *rna_Palette_color_new(Palette *palette)
+{
+ PaletteColor *color = BKE_palette_color_add(palette);
+ return color;
+}
+
+static void rna_Palette_color_remove(Palette *palette, ReportList *reports, PointerRNA *color_ptr)
+{
+ PaletteColor *color = color_ptr->data;
+
+ if (BLI_findindex(&palette->colors, color) == -1) {
+ BKE_reportf(reports, RPT_ERROR, "Palette '%s' does not contain color given", palette->id.name + 2);
+ return;
+ }
+
+ BKE_palette_color_remove(palette, color);
+
+ RNA_POINTER_INVALIDATE(color_ptr);
+}
+
+static void rna_Palette_color_clear(Palette *palette)
+{
+ BKE_palette_clear(palette);
+}
+
+static PointerRNA rna_Palette_active_color_get(PointerRNA *ptr)
+{
+ Palette *palette = ptr->data;
+ PaletteColor *color;
+
+ color = BLI_findlink(&palette->colors, palette->active_color);
+
+ if (color)
+ return rna_pointer_inherit_refine(ptr, &RNA_PaletteColor, color);
+
+ return rna_pointer_inherit_refine(ptr, NULL, NULL);
+}
+
+static void rna_Palette_active_color_set(PointerRNA *ptr, PointerRNA value)
+{
+ Palette *palette = ptr->data;
+ PaletteColor *color = value.data;
+
+ /* -1 is ok for an unset index */
+ if (color == NULL)
+ palette->active_color = -1;
+ else
+ palette->active_color = BLI_findindex(&palette->colors, color);
+}
+
+#else
+
+/* palette.colors */
+static void rna_def_palettecolors(BlenderRNA *brna, PropertyRNA *cprop)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ FunctionRNA *func;
+ PropertyRNA *parm;
+
+ RNA_def_property_srna(cprop, "PaletteColors");
+ srna = RNA_def_struct(brna, "PaletteColors", NULL);
+ RNA_def_struct_sdna(srna, "Palette");
+ RNA_def_struct_ui_text(srna, "Palette Splines", "Collection of palette colors");
+
+ func = RNA_def_function(srna, "new", "rna_Palette_color_new");
+ RNA_def_function_ui_description(func, "Add a new color to the palette");
+ parm = RNA_def_pointer(func, "color", "PaletteColor", "", "The newly created color");
+ RNA_def_function_return(func, parm);
+
+ func = RNA_def_function(srna, "remove", "rna_Palette_color_remove");
+ RNA_def_function_ui_description(func, "Remove a color from the palette");
+ RNA_def_function_flag(func, FUNC_USE_REPORTS);
+ parm = RNA_def_pointer(func, "color", "PaletteColor", "", "The color to remove");
+ RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL | PROP_RNAPTR);
+ RNA_def_property_clear_flag(parm, PROP_THICK_WRAP);
+
+ func = RNA_def_function(srna, "clear", "rna_Palette_color_clear");
+ RNA_def_function_ui_description(func, "Remove all colors from the palette");
+
+ prop = RNA_def_property(srna, "active", PROP_POINTER, PROP_NONE);
+ RNA_def_property_struct_type(prop, "PaletteColor");
+ RNA_def_property_pointer_funcs(prop, "rna_Palette_active_color_get", "rna_Palette_active_color_set", NULL, NULL);
+ RNA_def_property_flag(prop, PROP_EDITABLE);
+ RNA_def_property_ui_text(prop, "Active Palette Color", "");
+}
+
+static void rna_def_palettecolor(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ srna = RNA_def_struct(brna, "PaletteColor", NULL);
+ RNA_def_struct_ui_text(srna, "Palette Color", "");
+
+ prop = RNA_def_property(srna, "color", PROP_FLOAT, PROP_COLOR_GAMMA);
+ RNA_def_property_range(prop, 0.0, 1.0);
+ RNA_def_property_float_sdna(prop, NULL, "rgb");
+ RNA_def_property_ui_text(prop, "Color", "");
+ RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL);
+
+ prop = RNA_def_property(srna, "strength", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_range(prop, 0.0, 1.0);
+ RNA_def_property_float_sdna(prop, NULL, "value");
+ RNA_def_property_ui_text(prop, "Value", "");
+ RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL);
+
+ prop = RNA_def_property(srna, "weight", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_range(prop, 0.0, 1.0);
+ RNA_def_property_float_sdna(prop, NULL, "value");
+ RNA_def_property_ui_text(prop, "Weight", "");
+ RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL);
+}
+
+static void rna_def_palette(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ srna = RNA_def_struct(brna, "Palette", "ID");
+ RNA_def_struct_ui_text(srna, "Palette", "");
+ RNA_def_struct_ui_icon(srna, ICON_COLOR);
+
+ prop = RNA_def_property(srna, "colors", PROP_COLLECTION, PROP_NONE);
+ RNA_def_property_struct_type(prop, "PaletteColor");
+ rna_def_palettecolors(brna, prop);
+}
+
+void RNA_def_palette(BlenderRNA *brna)
+{
+ /* *** Non-Animated *** */
+ RNA_define_animate_sdna(false);
+ rna_def_palettecolor(brna);
+ rna_def_palette(brna);
+ RNA_define_animate_sdna(true);
+}
+
+#endif
diff --git a/source/blender/makesrna/intern/rna_particle.c b/source/blender/makesrna/intern/rna_particle.c
index 113311383f4..6676e9dc1c4 100644
--- a/source/blender/makesrna/intern/rna_particle.c
+++ b/source/blender/makesrna/intern/rna_particle.c
@@ -45,7 +45,7 @@
#include "RNA_define.h"
#include "RNA_enum_types.h"
-#include "BLF_translation.h"
+#include "BLT_translation.h"
#include "rna_internal.h"
@@ -131,6 +131,7 @@ static EnumPropertyItem part_hair_ren_as_items[] = {
#include "BKE_context.h"
#include "BKE_cloth.h"
+#include "BKE_colortools.h"
#include "BKE_deform.h"
#include "BKE_depsgraph.h"
#include "BKE_DerivedMesh.h"
@@ -356,13 +357,15 @@ static void rna_ParticleSystem_co_hair(ParticleSystem *particlesystem, Object *o
return;
if (part->ren_as == PART_DRAW_PATH && particlesystem->pathcache)
- path_nbr = (int)pow(2.0, step_nbr);
+ path_nbr = 1 << step_nbr;
+ if (part->kink == PART_KINK_SPIRAL)
+ path_nbr += part->kink_extra_steps;
if (particle_no < totpart) {
if (path_nbr) {
cache = particlesystem->pathcache[particle_no];
- max_k = (int)cache->steps;
+ max_k = (int)cache->segments;
}
}
@@ -371,10 +374,10 @@ static void rna_ParticleSystem_co_hair(ParticleSystem *particlesystem, Object *o
if (path_nbr) {
cache = particlesystem->childcache[particle_no - totpart];
- if (cache->steps < 0)
+ if (cache->segments < 0)
max_k = 0;
else
- max_k = (int)cache->steps;
+ max_k = (int)cache->segments;
}
}
@@ -488,7 +491,7 @@ static int rna_ParticleSystem_tessfaceidx_on_emitter(ParticleSystem *particlesys
num = cpa->num;
if (part->childtype == PART_CHILD_FACES) {
- if (ELEM(PART_FROM_FACE, PART_FROM_FACE, PART_FROM_VOLUME)) {
+ if (ELEM(part->from, PART_FROM_FACE, PART_FROM_VOLUME)) {
if (num != DMCACHE_NOTFOUND && num < totface) {
*r_fuv = &cpa->fuv;
return num;
@@ -589,8 +592,14 @@ static void rna_ParticleSystem_set_resolution(ParticleSystem *particlesystem, Sc
particle_system_update(scene, object, particlesystem);
}
else {
- if (particlesystem->renderdata)
+ ParticleSystemModifierData *psmd = psys_get_modifier(object, particlesystem);
+
+ if (particlesystem->renderdata) {
psys_render_restore(object, particlesystem);
+ }
+
+ psmd->flag &= ~eParticleSystemFlag_psys_updated;
+ particle_system_update(scene, object, particlesystem);
}
}
@@ -639,6 +648,15 @@ static void rna_Particle_redo_child(Main *bmain, Scene *scene, PointerRNA *ptr)
particle_recalc(bmain, scene, ptr, PSYS_RECALC_CHILD);
}
+static void rna_Particle_cloth_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
+{
+ Object *ob = (Object *)ptr->id.data;
+
+ DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ WM_main_add_notifier(NC_OBJECT | ND_MODIFIER, ob);
+}
+
+
static ParticleSystem *rna_particle_system_for_target(Object *ob, ParticleTarget *target)
{
ParticleSystem *psys;
@@ -858,6 +876,32 @@ static int rna_PartSettings_is_fluid_get(PointerRNA *ptr)
return part->type == PART_FLUID;
}
+static void rna_ParticleSettings_use_clump_curve_update(Main *bmain, Scene *scene, PointerRNA *ptr)
+{
+ ParticleSettings *part = ptr->data;
+
+ if (part->child_flag & PART_CHILD_USE_CLUMP_CURVE) {
+ if (!part->clumpcurve) {
+ BKE_particlesettings_clump_curve_init(part);
+ }
+ }
+
+ rna_Particle_redo_child(bmain, scene, ptr);
+}
+
+static void rna_ParticleSettings_use_roughness_curve_update(Main *bmain, Scene *scene, PointerRNA *ptr)
+{
+ ParticleSettings *part = ptr->data;
+
+ if (part->child_flag & PART_CHILD_USE_ROUGH_CURVE) {
+ if (!part->roughcurve) {
+ BKE_particlesettings_rough_curve_init(part);
+ }
+ }
+
+ rna_Particle_redo_child(bmain, scene, ptr);
+}
+
static void rna_ParticleSystem_name_set(PointerRNA *ptr, const char *value)
{
Object *ob = ptr->id.data;
@@ -886,7 +930,7 @@ static void rna_ParticleSystem_active_particle_target_index_range(PointerRNA *pt
{
ParticleSystem *psys = (ParticleSystem *)ptr->data;
*min = 0;
- *max = max_ii(0, BLI_countlist(&psys->targets) - 1);
+ *max = max_ii(0, BLI_listbase_count(&psys->targets) - 1);
}
static int rna_ParticleSystem_active_particle_target_index_get(PointerRNA *ptr)
@@ -1009,7 +1053,7 @@ static void rna_ParticleDupliWeight_active_index_range(PointerRNA *ptr, int *min
{
ParticleSettings *part = (ParticleSettings *)ptr->id.data;
*min = 0;
- *max = max_ii(0, BLI_countlist(&part->dupliweights) - 1);
+ *max = max_ii(0, BLI_listbase_count(&part->dupliweights) - 1);
}
static int rna_ParticleDupliWeight_active_index_get(PointerRNA *ptr)
@@ -1770,9 +1814,14 @@ static void rna_def_particle_settings_mtex(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Clump", "Affect the child clumping");
RNA_def_property_update(prop, 0, "rna_Particle_reset");
- prop = RNA_def_property(srna, "use_map_kink", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "mapto", PAMAP_KINK);
- RNA_def_property_ui_text(prop, "Kink", "Affect the child kink");
+ prop = RNA_def_property(srna, "use_map_kink_amp", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "mapto", PAMAP_KINK_AMP);
+ RNA_def_property_ui_text(prop, "Kink Amplitude", "Affect the child kink amplitude");
+ RNA_def_property_update(prop, 0, "rna_Particle_redo_child");
+
+ prop = RNA_def_property(srna, "use_map_kink_freq", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "mapto", PAMAP_KINK_FREQ);
+ RNA_def_property_ui_text(prop, "Kink Frequency", "Affect the child kink frequency");
RNA_def_property_update(prop, 0, "rna_Particle_redo_child");
prop = RNA_def_property(srna, "use_map_rough", PROP_BOOLEAN, PROP_NONE);
@@ -1849,10 +1898,16 @@ static void rna_def_particle_settings_mtex(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Clump Factor", "Amount texture affects child clump");
RNA_def_property_update(prop, 0, "rna_Particle_redo_child");
- prop = RNA_def_property(srna, "kink_factor", PROP_FLOAT, PROP_NONE);
+ prop = RNA_def_property(srna, "kink_amp_factor", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "kinkampfac");
+ RNA_def_property_ui_range(prop, 0, 1, 10, 3);
+ RNA_def_property_ui_text(prop, "Kink Amplitude Factor", "Amount texture affects child kink amplitude");
+ RNA_def_property_update(prop, 0, "rna_Particle_redo_child");
+
+ prop = RNA_def_property(srna, "kink_freq_factor", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "kinkfac");
RNA_def_property_ui_range(prop, 0, 1, 10, 3);
- RNA_def_property_ui_text(prop, "Kink Factor", "Amount texture affects child kink");
+ RNA_def_property_ui_text(prop, "Kink Frequency Factor", "Amount texture affects child kink frequency");
RNA_def_property_update(prop, 0, "rna_Particle_redo_child");
prop = RNA_def_property(srna, "rough_factor", PROP_FLOAT, PROP_NONE);
@@ -1938,6 +1993,7 @@ static void rna_def_particle_settings(BlenderRNA *brna)
{PART_KINK_RADIAL, "RADIAL", 0, "Radial", ""},
{PART_KINK_WAVE, "WAVE", 0, "Wave", ""},
{PART_KINK_BRAID, "BRAID", 0, "Braid", ""},
+ {PART_KINK_SPIRAL, "SPIRAL", 0, "Spiral", ""},
{0, NULL, 0, NULL, NULL}
};
@@ -2170,6 +2226,16 @@ static void rna_def_particle_settings(BlenderRNA *brna)
RNA_def_property_update(prop, 0, "rna_Particle_reset");
/*draw flag*/
+ prop = RNA_def_property(srna, "show_guide_hairs", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "draw", PART_DRAW_GUIDE_HAIRS);
+ RNA_def_property_ui_text(prop, "Guide Hairs", "Show guide hairs");
+ RNA_def_property_update(prop, 0, "rna_Particle_redo");
+
+ prop = RNA_def_property(srna, "show_hair_grid", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "draw", PART_DRAW_HAIR_GRID);
+ RNA_def_property_ui_text(prop, "Guide Hairs", "Show guide hairs");
+ RNA_def_property_update(prop, 0, "rna_Particle_redo");
+
prop = RNA_def_property(srna, "show_velocity", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "draw", PART_DRAW_VEL);
RNA_def_property_ui_text(prop, "Velocity", "Show particle velocity");
@@ -2301,6 +2367,11 @@ static void rna_def_particle_settings(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Segments", "Number of hair segments");
RNA_def_property_update(prop, 0, "rna_Particle_reset");
+ prop = RNA_def_property(srna, "bending_random", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "bending_random");
+ RNA_def_property_range(prop, 0.0f, 1.0f);
+ RNA_def_property_ui_text(prop, "Random Bending Stiffness", "Random stiffness of hairs");
+ RNA_def_property_update(prop, 0, "rna_Particle_cloth_update");
/*TODO: not found in UI, readonly? */
prop = RNA_def_property(srna, "keys_step", PROP_INT, PROP_NONE);
@@ -2649,7 +2720,7 @@ static void rna_def_particle_settings(BlenderRNA *brna)
prop = RNA_def_property(srna, "phase_factor_random", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "randphasefac");
- RNA_def_property_range(prop, 0.0f, 1.0f);
+ RNA_def_property_range(prop, 0.0f, 2.0f);
RNA_def_property_ui_text(prop, "Random Phase", "Randomize rotation around the chosen orientation axis");
RNA_def_property_update(prop, 0, "rna_Particle_reset");
@@ -2766,6 +2837,29 @@ static void rna_def_particle_settings(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Shape", "Shape of clumping");
RNA_def_property_update(prop, 0, "rna_Particle_redo_child");
+ prop = RNA_def_property(srna, "use_clump_curve", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "child_flag", PART_CHILD_USE_CLUMP_CURVE);
+ RNA_def_property_ui_text(prop, "Use Clump Curve", "Use a curve to define clump tapering");
+ RNA_def_property_update(prop, 0, "rna_ParticleSettings_use_clump_curve_update");
+
+ prop = RNA_def_property(srna, "clump_curve", PROP_POINTER, PROP_NONE);
+ RNA_def_property_pointer_sdna(prop, NULL, "clumpcurve");
+ RNA_def_property_struct_type(prop, "CurveMapping");
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_property_ui_text(prop, "Clump Curve", "Curve defining clump tapering");
+ RNA_def_property_update(prop, 0, "rna_Particle_redo_child");
+
+ prop = RNA_def_property(srna, "use_clump_noise", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "child_flag", PART_CHILD_USE_CLUMP_NOISE);
+ RNA_def_property_ui_text(prop, "Use Clump Noise", "Create random clumps around the parent");
+ RNA_def_property_update(prop, 0, "rna_Particle_redo_child");
+
+ prop = RNA_def_property(srna, "clump_noise_size", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "clump_noise_size");
+ RNA_def_property_range(prop, 0.00001f, 100000.0f);
+ RNA_def_property_ui_range(prop, 0.01f, 10.0f, 0.1f, 3);
+ RNA_def_property_ui_text(prop, "Clump Noise Size", "Size of clump noise");
+ RNA_def_property_update(prop, 0, "rna_Particle_redo_child");
/* kink */
prop = RNA_def_property(srna, "kink_amplitude", PROP_FLOAT, PROP_NONE);
@@ -2781,6 +2875,12 @@ static void rna_def_particle_settings(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Amplitude Clump", "How much clump affects kink amplitude");
RNA_def_property_update(prop, 0, "rna_Particle_redo_child");
+ prop = RNA_def_property(srna, "kink_amplitude_random", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "kink_amp_random");
+ RNA_def_property_range(prop, 0.0f, 1.0f);
+ RNA_def_property_ui_text(prop, "Amplitude Random", "Random variation of the amplitude");
+ RNA_def_property_update(prop, 0, "rna_Particle_redo_child");
+
prop = RNA_def_property(srna, "kink_frequency", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "kink_freq");
RNA_def_property_range(prop, -100000.0f, 100000.0f);
@@ -2798,6 +2898,17 @@ static void rna_def_particle_settings(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Flatness", "How flat the hairs are");
RNA_def_property_update(prop, 0, "rna_Particle_redo_child");
+ prop = RNA_def_property(srna, "kink_extra_steps", PROP_INT, PROP_NONE);
+ RNA_def_property_range(prop, 1, INT_MAX);
+ RNA_def_property_ui_range(prop, 1, 100, 1, -1);
+ RNA_def_property_ui_text(prop, "Extra Steps", "Extra steps for resolution of special kink features");
+ RNA_def_property_update(prop, 0, "rna_Particle_redo_child");
+
+ prop = RNA_def_property(srna, "kink_axis_random", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_range(prop, 0.0f, 1.0f);
+ RNA_def_property_ui_text(prop, "Axis Random", "Random variation of the orientation");
+ RNA_def_property_update(prop, 0, "rna_Particle_redo_child");
+
/* rough */
prop = RNA_def_property(srna, "roughness_1", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "rough1");
@@ -2846,6 +2957,18 @@ static void rna_def_particle_settings(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Shape", "Shape of end point rough");
RNA_def_property_update(prop, 0, "rna_Particle_redo_child");
+ prop = RNA_def_property(srna, "use_roughness_curve", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "child_flag", PART_CHILD_USE_ROUGH_CURVE);
+ RNA_def_property_ui_text(prop, "Use Roughness Curve", "Use a curve to define roughness");
+ RNA_def_property_update(prop, 0, "rna_ParticleSettings_use_roughness_curve_update");
+
+ prop = RNA_def_property(srna, "roughness_curve", PROP_POINTER, PROP_NONE);
+ RNA_def_property_pointer_sdna(prop, NULL, "roughcurve");
+ RNA_def_property_struct_type(prop, "CurveMapping");
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_property_ui_text(prop, "Roughness Curve", "Curve defining roughness");
+ RNA_def_property_update(prop, 0, "rna_Particle_redo_child");
+
prop = RNA_def_property(srna, "child_length", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "clength");
RNA_def_property_range(prop, 0.0f, 1.0f);
diff --git a/source/blender/makesrna/intern/rna_pose.c b/source/blender/makesrna/intern/rna_pose.c
index 9f05d61eeff..27ff0a63e75 100644
--- a/source/blender/makesrna/intern/rna_pose.c
+++ b/source/blender/makesrna/intern/rna_pose.c
@@ -41,7 +41,7 @@
#include "BLI_math.h"
-#include "BLF_translation.h"
+#include "BLT_translation.h"
#include "WM_types.h"
@@ -109,8 +109,6 @@ EnumPropertyItem color_sets_items[] = {
#include "ED_object.h"
#include "ED_armature.h"
-#include "MEM_guardedalloc.h"
-
#include "WM_api.h"
#include "RNA_access.h"
@@ -179,6 +177,13 @@ void rna_ActionGroup_colorset_set(PointerRNA *ptr, int value)
}
}
+int rna_ActionGroup_is_custom_colorset_get(PointerRNA *ptr)
+{
+ bActionGroup *grp = ptr->data;
+
+ return (grp->customCol < 0);
+}
+
static void rna_BoneGroup_name_set(PointerRNA *ptr, const char *value)
{
Object *ob = ptr->id.data;
@@ -187,7 +192,7 @@ static void rna_BoneGroup_name_set(PointerRNA *ptr, const char *value)
/* copy the new name into the name slot */
BLI_strncpy_utf8(agrp->name, value, sizeof(agrp->name));
- BLI_uniquename(&ob->pose->agroups, agrp, CTX_DATA_(BLF_I18NCONTEXT_ID_ARMATURE, "Group"), '.',
+ BLI_uniquename(&ob->pose->agroups, agrp, CTX_DATA_(BLT_I18NCONTEXT_ID_ARMATURE, "Group"), '.',
offsetof(bActionGroup, name), sizeof(agrp->name));
}
@@ -224,7 +229,7 @@ static void rna_Pose_ik_solver_update(Main *bmain, Scene *UNUSED(scene), Pointer
Object *ob = ptr->id.data;
bPose *pose = ptr->data;
- pose->flag |= POSE_RECALC; /* checks & sorts pose channels */
+ BKE_pose_tag_recalc(bmain, pose); /* checks & sorts pose channels */
DAG_relations_tag_update(bmain);
BKE_pose_update_constraint_flags(pose);
@@ -251,7 +256,7 @@ static void rna_PoseChannel_rotation_axis_angle_set(PointerRNA *ptr, const float
/* for now, assume that rotation mode is axis-angle */
pchan->rotAngle = value[0];
- copy_v3_v3(pchan->rotAxis, (float *)&value[1]);
+ copy_v3_v3(pchan->rotAxis, &value[1]);
/* TODO: validate axis? */
}
@@ -349,7 +354,7 @@ static void rna_Itasc_update_rebuild(Main *bmain, Scene *scene, PointerRNA *ptr)
Object *ob = ptr->id.data;
bPose *pose = ob->pose;
- pose->flag |= POSE_RECALC; /* checks & sorts pose channels */
+ BKE_pose_tag_recalc(bmain, pose); /* checks & sorts pose channels */
rna_Itasc_update(bmain, scene, ptr);
}
@@ -414,7 +419,7 @@ static void rna_PoseChannel_bone_group_index_range(PointerRNA *ptr, int *min, in
bPose *pose = (ob) ? ob->pose : NULL;
*min = 0;
- *max = pose ? max_ii(0, BLI_countlist(&pose->agroups) - 1) : 0;
+ *max = pose ? max_ii(0, BLI_listbase_count(&pose->agroups) - 1) : 0;
}
static PointerRNA rna_Pose_active_bone_group_get(PointerRNA *ptr)
@@ -447,7 +452,7 @@ static void rna_Pose_active_bone_group_index_range(PointerRNA *ptr, int *min, in
bPose *pose = (bPose *)ptr->data;
*min = 0;
- *max = max_ii(0, BLI_countlist(&pose->agroups) - 1);
+ *max = max_ii(0, BLI_listbase_count(&pose->agroups) - 1);
}
#if 0
@@ -675,6 +680,11 @@ void rna_def_actionbone_group_common(StructRNA *srna, int update_flag, const cha
RNA_def_property_ui_text(prop, "Color Set", "Custom color set to use");
RNA_def_property_update(prop, update_flag, update_cb);
+ prop = RNA_def_property(srna, "is_custom_color_set", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_funcs(prop, "rna_ActionGroup_is_custom_colorset_get", NULL);
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_property_ui_text(prop, "Custom Color Set", "Color set is user-defined instead of a fixed theme color set");
+
/* TODO: editing the colors for this should result in changes to the color type... */
prop = RNA_def_property(srna, "colors", PROP_POINTER, PROP_NONE);
RNA_def_property_flag(prop, PROP_NEVER_NULL);
@@ -1052,6 +1062,17 @@ static void rna_def_pose_channel(BlenderRNA *brna)
RNA_def_property_editable_func(prop, "rna_PoseChannel_proxy_editable");
RNA_def_property_update(prop, NC_OBJECT | ND_POSE, "rna_Pose_update");
+ prop = RNA_def_property(srna, "custom_shape_scale", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "custom_scale");
+ RNA_def_property_range(prop, 0.0f, 1000.0f);
+ RNA_def_property_ui_text(prop, "Custom Shape Scale", "Adjust the size of the custom shape");
+ RNA_def_property_update(prop, NC_OBJECT | ND_POSE, "rna_Pose_update");
+
+ prop = RNA_def_property(srna, "use_custom_shape_bone_size", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_negative_sdna(prop, NULL, "drawflag", PCHAN_DRAW_NO_CUSTOM_BONE_SIZE);
+ RNA_def_property_ui_text(prop, "Use Bone Size", "Scale the custom object by the bone length");
+ RNA_def_property_update(prop, NC_OBJECT | ND_POSE, "rna_Pose_update");
+
prop = RNA_def_property(srna, "custom_shape_transform", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "custom_tx");
RNA_def_property_struct_type(prop, "PoseBone");
diff --git a/source/blender/makesrna/intern/rna_property.c b/source/blender/makesrna/intern/rna_property.c
index c6b8e89c282..454816d4e0a 100644
--- a/source/blender/makesrna/intern/rna_property.c
+++ b/source/blender/makesrna/intern/rna_property.c
@@ -28,6 +28,11 @@
#include <stdlib.h>
#include "DNA_property_types.h"
+#include "DNA_object_types.h"
+
+#include "BLI_path_util.h"
+
+#include "BLT_translation.h"
#include "RNA_define.h"
#include "RNA_enum_types.h"
@@ -97,9 +102,11 @@ static void rna_GameProperty_type_set(PointerRNA *ptr, int value)
static void rna_GameProperty_name_set(PointerRNA *ptr, const char *value)
{
- bProperty *prop = (bProperty *)(ptr->data);
+ Object *ob = ptr->id.data;
+ bProperty *prop = ptr->data;
BLI_strncpy_utf8(prop->name, value, sizeof(prop->name));
- BKE_bproperty_unique(NULL, prop, 1);
+
+ BLI_uniquename(&ob->prop, prop, DATA_("Property"), '.', offsetof(bProperty, name), sizeof(prop->name));
}
diff --git a/source/blender/makesrna/intern/rna_render.c b/source/blender/makesrna/intern/rna_render.c
index 284377d34f9..61eb2c69bfe 100644
--- a/source/blender/makesrna/intern/rna_render.c
+++ b/source/blender/makesrna/intern/rna_render.c
@@ -27,6 +27,7 @@
#include <stdlib.h>
#include "DNA_scene_types.h"
+#include "DNA_object_types.h"
#include "BLI_utildefines.h"
#include "BLI_path_util.h"
@@ -38,7 +39,6 @@
#include "RE_engine.h"
#include "RE_pipeline.h"
-#include "RE_engine.h"
EnumPropertyItem render_pass_type_items[] = {
@@ -71,6 +71,16 @@ EnumPropertyItem render_pass_type_items[] = {
{SCE_PASS_SUBSURFACE_DIRECT, "SUBSURFACE_DIRECT", 0, "Subsurface Direct", ""},
{SCE_PASS_SUBSURFACE_INDIRECT, "SUBSURFACE_INDIRECT", 0, "Subsurface Indirect", ""},
{SCE_PASS_SUBSURFACE_COLOR, "SUBSURFACE_COLOR", 0, "Subsurface Color", ""},
+#ifdef WITH_CYCLES_DEBUG
+ {SCE_PASS_DEBUG, "DEBUG", 0, "Pass used for render engine debugging", ""},
+#endif
+ {0, NULL, 0, NULL, NULL}
+};
+
+EnumPropertyItem render_pass_debug_type_items[] = {
+ {RENDER_PASS_DEBUG_BVH_TRAVERSAL_STEPS, "BVH_TRAVERSAL_STEPS", 0, "BVH Traversal Steps", ""},
+ {RENDER_PASS_DEBUG_BVH_TRAVERSED_INSTANCES, "BVH_TRAVERSED_INSTANCES", 0, "BVH Traversed Instances", ""},
+ {RENDER_PASS_DEBUG_RAY_BOUNCES, "RAY_BOUNCES", 0, "Ray Steps", ""},
{0, NULL, 0, NULL, NULL}
};
@@ -151,8 +161,10 @@ static void engine_render(RenderEngine *engine, struct Scene *scene)
RNA_parameter_list_free(&list);
}
-static void engine_bake(RenderEngine *engine, struct Scene *scene, struct Object *object, const int pass_type,
- const struct BakePixel *pixel_array, const int num_pixels, const int depth, void *result)
+static void engine_bake(RenderEngine *engine, struct Scene *scene,
+ struct Object *object, const int pass_type,
+ const int object_id, const struct BakePixel *pixel_array,
+ const int num_pixels, const int depth, void *result)
{
extern FunctionRNA rna_RenderEngine_bake_func;
PointerRNA ptr;
@@ -166,6 +178,7 @@ static void engine_bake(RenderEngine *engine, struct Scene *scene, struct Object
RNA_parameter_set_lookup(&list, "scene", &scene);
RNA_parameter_set_lookup(&list, "object", &object);
RNA_parameter_set_lookup(&list, "pass_type", &pass_type);
+ RNA_parameter_set_lookup(&list, "object_id", &object_id);
RNA_parameter_set_lookup(&list, "pixel_array", &pixel_array);
RNA_parameter_set_lookup(&list, "num_pixels", &num_pixels);
RNA_parameter_set_lookup(&list, "depth", &depth);
@@ -251,6 +264,7 @@ static StructRNA *rna_RenderEngine_register(Main *bmain, ReportList *reports, vo
/* setup dummy engine & engine type to store static properties in */
dummyengine.type = &dummyet;
+ dummyet.flag |= RE_USE_SHADING_NODES_CUSTOM;
RNA_pointer_create(NULL, &RNA_RenderEngine, &dummyengine, &dummyptr);
/* validate the python class */
@@ -265,7 +279,7 @@ static StructRNA *rna_RenderEngine_register(Main *bmain, ReportList *reports, vo
/* check if we have registered this engine type before, and remove it */
for (et = R_engines.first; et; et = et->next) {
- if (strcmp(et->idname, dummyet.idname) == 0) {
+ if (STREQ(et->idname, dummyet.idname)) {
if (et->ext.srna)
rna_RenderEngine_unregister(bmain, et->ext.srna);
break;
@@ -320,38 +334,35 @@ static PointerRNA rna_RenderEngine_render_get(PointerRNA *ptr)
}
}
-static void rna_RenderResult_layers_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
+static PointerRNA rna_RenderEngine_camera_override_get(PointerRNA *ptr)
{
- RenderResult *rr = (RenderResult *)ptr->data;
- rna_iterator_listbase_begin(iter, &rr->layers, NULL);
-}
+ RenderEngine *engine = (RenderEngine *)ptr->data;
-static void rna_RenderLayer_passes_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
-{
- RenderLayer *rl = (RenderLayer *)ptr->data;
- rna_iterator_listbase_begin(iter, &rl->passes, NULL);
+ if (engine->re) {
+ Object *cam = RE_GetCamera(engine->re);
+ return rna_pointer_inherit_refine(ptr, &RNA_Object, cam);
+ }
+ else {
+ return rna_pointer_inherit_refine(ptr, &RNA_Object, engine->camera_override);
+ }
}
-static int rna_RenderLayer_rect_get_length(PointerRNA *ptr, int length[RNA_MAX_ARRAY_DIMENSION])
+static void rna_RenderResult_views_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
{
- RenderLayer *rl = (RenderLayer *)ptr->data;
-
- length[0] = rl->rectx * rl->recty;
- length[1] = 4;
-
- return length[0] * length[1];
+ RenderResult *rr = (RenderResult *)ptr->data;
+ rna_iterator_listbase_begin(iter, &rr->views, NULL);
}
-static void rna_RenderLayer_rect_get(PointerRNA *ptr, float *values)
+static void rna_RenderResult_layers_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
{
- RenderLayer *rl = (RenderLayer *)ptr->data;
- memcpy(values, rl->rectf, sizeof(float) * rl->rectx * rl->recty * 4);
+ RenderResult *rr = (RenderResult *)ptr->data;
+ rna_iterator_listbase_begin(iter, &rr->layers, NULL);
}
-void rna_RenderLayer_rect_set(PointerRNA *ptr, const float *values)
+static void rna_RenderLayer_passes_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
{
RenderLayer *rl = (RenderLayer *)ptr->data;
- memcpy(rl->rectf, values, sizeof(float) * rl->rectx * rl->recty * 4);
+ rna_iterator_listbase_begin(iter, &rl->passes, NULL);
}
static int rna_RenderPass_rect_get_length(PointerRNA *ptr, int length[RNA_MAX_ARRAY_DIMENSION])
@@ -382,6 +393,11 @@ static PointerRNA rna_BakePixel_next_get(PointerRNA *ptr)
return rna_pointer_inherit_refine(ptr, &RNA_BakePixel, bp + 1);
}
+static RenderPass *rna_RenderPass_find_by_type(RenderLayer *rl, int passtype, const char *view)
+{
+ return RE_pass_find_by_type(rl, passtype, view);
+}
+
#else /* RNA_RUNTIME */
static void rna_def_render_engine(BlenderRNA *brna)
@@ -418,6 +434,8 @@ static void rna_def_render_engine(BlenderRNA *brna)
RNA_def_property_flag(prop, PROP_REQUIRED);
prop = RNA_def_enum(func, "pass_type", render_pass_type_items, 0, "Pass", "Pass to bake");
RNA_def_property_flag(prop, PROP_REQUIRED);
+ prop = RNA_def_int(func, "object_id", 0, 0, INT_MAX, "Object Id", "Id of the current object being baked in relation to the others", 0, INT_MAX);
+ RNA_def_property_flag(prop, PROP_REQUIRED);
prop = RNA_def_pointer(func, "pixel_array", "BakePixel", "", "");
RNA_def_property_flag(prop, PROP_REQUIRED);
prop = RNA_def_int(func, "num_pixels", 0, 0, INT_MAX, "Number of Pixels", "Size of the baking batch", 0, INT_MAX);
@@ -465,6 +483,7 @@ static void rna_def_render_engine(BlenderRNA *brna)
prop = RNA_def_int(func, "h", 0, 0, INT_MAX, "Height", "", 0, INT_MAX);
RNA_def_property_flag(prop, PROP_REQUIRED);
RNA_def_string(func, "layer", NULL, 0, "Layer", "Single layer to get render result for"); /* NULL ok here */
+ RNA_def_string(func, "view", NULL, 0, "View", "Single view to get render result for"); /* NULL ok here */
prop = RNA_def_pointer(func, "result", "RenderResult", "Result", "");
RNA_def_function_return(func, prop);
@@ -485,6 +504,22 @@ static void rna_def_render_engine(BlenderRNA *brna)
prop = RNA_def_boolean(func, "do_break", 0, "Break", "");
RNA_def_function_return(func, prop);
+ func = RNA_def_function(srna, "active_view_set", "RE_engine_active_view_set");
+ RNA_def_string(func, "view", NULL, 0, "View", "Single view to set as active"); /* NULL ok here */
+ RNA_def_property_flag(prop, PROP_REQUIRED);
+
+ func = RNA_def_function(srna, "camera_shift_x", "RE_engine_get_camera_shift_x");
+ prop = RNA_def_pointer(func, "camera", "Object", "", "");
+ RNA_def_property_flag(prop, PROP_REQUIRED);
+ prop = RNA_def_float(func, "shift_x", 0.0f, 0.0f, FLT_MAX, "Shift X", "", 0.0f, FLT_MAX);
+ RNA_def_function_return(func, prop);
+
+ func = RNA_def_function(srna, "camera_model_matrix", "RE_engine_get_camera_model_matrix");
+ prop = RNA_def_pointer(func, "camera", "Object", "", "");
+ RNA_def_property_flag(prop, PROP_REQUIRED);
+ prop = RNA_def_float_matrix(func, "r_model_matrix", 4, 4, NULL, 0.0f, 0.0f, "Model Matrix", "Normalized camera model matrix", 0.0f, 0.0f);
+ RNA_def_property_flag(prop, PROP_REQUIRED);
+
func = RNA_def_function(srna, "update_stats", "RE_engine_update_stats");
RNA_def_function_ui_description(func, "Update and signal to redraw render status text");
prop = RNA_def_string(func, "stats", NULL, 0, "Stats", "");
@@ -517,6 +552,11 @@ static void rna_def_render_engine(BlenderRNA *brna)
prop = RNA_def_string(func, "message", NULL, 0, "Report Message", "");
RNA_def_property_flag(prop, PROP_REQUIRED);
+ func = RNA_def_function(srna, "error_set", "RE_engine_set_error_message");
+ RNA_def_function_ui_description(func, "Set error message displaying after the render is finished");
+ prop = RNA_def_string(func, "message", NULL, 0, "Report Message", "");
+ RNA_def_property_flag(prop, PROP_REQUIRED);
+
func = RNA_def_function(srna, "bind_display_space_shader", "engine_bind_display_space_shader");
RNA_def_function_ui_description(func, "Bind GLSL fragment shader that converts linear colors to display space colors using scene color management settings");
prop = RNA_def_pointer(func, "scene", "Scene", "", "");
@@ -541,7 +581,7 @@ static void rna_def_render_engine(BlenderRNA *brna)
RNA_def_property_boolean_sdna(prop, NULL, "flag", RE_ENGINE_PREVIEW);
prop = RNA_def_property(srna, "camera_override", PROP_POINTER, PROP_NONE);
- RNA_def_property_pointer_sdna(prop, NULL, "camera_override");
+ RNA_def_property_pointer_funcs(prop, "rna_RenderEngine_camera_override_get", NULL, NULL, NULL);
RNA_def_property_struct_type(prop, "Object");
prop = RNA_def_property(srna, "layer_override", PROP_BOOLEAN, PROP_LAYER_MEMBER);
@@ -584,6 +624,10 @@ static void rna_def_render_engine(BlenderRNA *brna)
RNA_def_property_boolean_sdna(prop, NULL, "type->flag", RE_USE_PREVIEW);
RNA_def_property_flag(prop, PROP_REGISTER_OPTIONAL);
+ prop = RNA_def_property(srna, "bl_use_texture_preview", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "type->flag", RE_USE_TEXTURE_PREVIEW);
+ RNA_def_property_flag(prop, PROP_REGISTER_OPTIONAL);
+
prop = RNA_def_property(srna, "bl_use_postprocess", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_negative_sdna(prop, NULL, "type->flag", RE_USE_POSTPROCESS);
RNA_def_property_flag(prop, PROP_REGISTER_OPTIONAL);
@@ -592,6 +636,11 @@ static void rna_def_render_engine(BlenderRNA *brna)
RNA_def_property_boolean_sdna(prop, NULL, "type->flag", RE_USE_SHADING_NODES);
RNA_def_property_flag(prop, PROP_REGISTER_OPTIONAL);
+ prop = RNA_def_property(srna, "bl_use_shading_nodes_custom", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "type->flag", RE_USE_SHADING_NODES_CUSTOM);
+ RNA_def_property_boolean_default(prop, true);
+ RNA_def_property_flag(prop, PROP_REGISTER_OPTIONAL);
+
prop = RNA_def_property(srna, "bl_use_exclude_layers", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "type->flag", RE_USE_EXCLUDE_LAYERS);
RNA_def_property_flag(prop, PROP_REGISTER_OPTIONAL);
@@ -636,9 +685,56 @@ static void rna_def_render_result(BlenderRNA *brna)
"rna_iterator_listbase_end", "rna_iterator_listbase_get",
NULL, NULL, NULL, NULL);
+ parm = RNA_def_property(srna, "views", PROP_COLLECTION, PROP_NONE);
+ RNA_def_property_struct_type(parm, "RenderView");
+ RNA_def_property_collection_funcs(parm, "rna_RenderResult_views_begin", "rna_iterator_listbase_next",
+ "rna_iterator_listbase_end", "rna_iterator_listbase_get",
+ NULL, NULL, NULL, NULL);
+
+ RNA_define_verify_sdna(1);
+}
+
+static void rna_def_render_view(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ srna = RNA_def_struct(brna, "RenderView", NULL);
+ RNA_def_struct_ui_text(srna, "Render View", "");
+
+ RNA_define_verify_sdna(0);
+
+ prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE);
+ RNA_def_property_string_sdna(prop, NULL, "name");
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_struct_name_property(srna, prop);
+
RNA_define_verify_sdna(1);
}
+static void rna_def_render_passes(BlenderRNA *brna, PropertyRNA *cprop)
+{
+ StructRNA *srna;
+
+ FunctionRNA *func;
+ PropertyRNA *parm;
+
+ RNA_def_property_srna(cprop, "RenderPasses");
+ srna = RNA_def_struct(brna, "RenderPasses", NULL);
+ RNA_def_struct_sdna(srna, "RenderLayer");
+ RNA_def_struct_ui_text(srna, "Render Passes", "Collection of render passes");
+
+ func = RNA_def_function(srna, "find_by_type", "rna_RenderPass_find_by_type");
+ RNA_def_function_ui_description(func, "Get the render pass for a given type and view");
+ parm = RNA_def_enum(func, "pass_type", render_pass_type_items, SCE_PASS_COMBINED, "Pass", "");
+ RNA_def_property_flag(parm, PROP_REQUIRED);
+ parm = RNA_def_string(func, "view", NULL, 0, "View", "Render view to get pass from"); /* NULL ok here */
+ RNA_def_property_flag(parm, PROP_REQUIRED);
+ parm = RNA_def_pointer(func, "render_pass", "RenderPass", "", "The matching render pass");
+ RNA_def_function_return(func, parm);
+
+}
+
static void rna_def_render_layer(BlenderRNA *brna)
{
StructRNA *srna;
@@ -668,12 +764,7 @@ static void rna_def_render_layer(BlenderRNA *brna)
RNA_def_property_collection_funcs(prop, "rna_RenderLayer_passes_begin", "rna_iterator_listbase_next",
"rna_iterator_listbase_end", "rna_iterator_listbase_get",
NULL, NULL, NULL, NULL);
-
- prop = RNA_def_property(srna, "rect", PROP_FLOAT, PROP_NONE);
- RNA_def_property_flag(prop, PROP_DYNAMIC);
- RNA_def_property_multi_array(prop, 2, NULL);
- RNA_def_property_dynamic_array_funcs(prop, "rna_RenderLayer_rect_get_length");
- RNA_def_property_float_funcs(prop, "rna_RenderLayer_rect_get", "rna_RenderLayer_rect_set", NULL);
+ rna_def_render_passes(brna, prop);
RNA_define_verify_sdna(1);
}
@@ -712,6 +803,15 @@ static void rna_def_render_pass(BlenderRNA *brna)
RNA_def_property_dynamic_array_funcs(prop, "rna_RenderPass_rect_get_length");
RNA_def_property_float_funcs(prop, "rna_RenderPass_rect_get", "rna_RenderPass_rect_set", NULL);
+ prop = RNA_def_property(srna, "view_id", PROP_INT, PROP_NONE);
+ RNA_def_property_int_sdna(prop, NULL, "view_id");
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+
+ prop = RNA_def_property(srna, "debug_type", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "debug_type");
+ RNA_def_property_enum_items(prop, render_pass_debug_type_items);
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+
RNA_define_verify_sdna(1);
}
@@ -729,6 +829,10 @@ static void rna_def_render_bake_pixel(BlenderRNA *brna)
RNA_def_property_int_sdna(prop, NULL, "primitive_id");
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ prop = RNA_def_property(srna, "object_id", PROP_INT, PROP_NONE);
+ RNA_def_property_int_sdna(prop, NULL, "object_id");
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+
prop = RNA_def_property(srna, "uv", PROP_FLOAT, PROP_NONE);
RNA_def_property_array(prop, 2);
RNA_def_property_float_sdna(prop, NULL, "uv");
@@ -762,6 +866,7 @@ void RNA_def_render(BlenderRNA *brna)
{
rna_def_render_engine(brna);
rna_def_render_result(brna);
+ rna_def_render_view(brna);
rna_def_render_layer(brna);
rna_def_render_pass(brna);
rna_def_render_bake_pixel(brna);
diff --git a/source/blender/makesrna/intern/rna_rigidbody.c b/source/blender/makesrna/intern/rna_rigidbody.c
index 78cd8d4bad4..58a12f62644 100644
--- a/source/blender/makesrna/intern/rna_rigidbody.c
+++ b/source/blender/makesrna/intern/rna_rigidbody.c
@@ -94,6 +94,8 @@ static EnumPropertyItem rigidbody_mesh_source_items[] = {
#include "BKE_depsgraph.h"
#include "BKE_rigidbody.h"
+#include "WM_api.h"
+
#define RB_FLAG_SET(dest, value, flag) { \
if (value) \
dest |= flag; \
@@ -151,6 +153,15 @@ static void rna_RigidBodyOb_reset(Main *UNUSED(bmain), Scene *scene, PointerRNA
BKE_rigidbody_cache_reset(rbw);
}
+static void rna_RigidBodyOb_shape_update(Main *bmain, Scene *scene, PointerRNA *ptr)
+{
+ Object *ob = ptr->id.data;
+
+ rna_RigidBodyOb_reset(bmain, scene, ptr);
+
+ WM_main_add_notifier(NC_OBJECT | ND_DRAW, ob);
+}
+
static void rna_RigidBodyOb_shape_reset(Main *UNUSED(bmain), Scene *scene, PointerRNA *ptr)
{
RigidBodyWorld *rbw = scene->rigidbody_world;
@@ -633,8 +644,7 @@ static void rna_RigidBodyWorld_convex_sweep_test(
BKE_report(reports, RPT_ERROR, "Rigidbody world was not properly initialized, need to step the simulation first");
}
#else
- (void)rbw, (void)reports, (void)object, (void)ray_start, (void)ray_end;
- (void)r_location, (void)r_hitpoint, (void)r_normal, (void)r_hit;
+ UNUSED_VARS(rbw, reports, object, ray_start, ray_end, r_location, r_hitpoint, r_normal, r_hit);
#endif
}
@@ -797,7 +807,7 @@ static void rna_def_rigidbody_object(BlenderRNA *brna)
RNA_def_property_enum_funcs(prop, NULL, "rna_RigidBodyOb_shape_set", NULL);
RNA_def_property_ui_text(prop, "Collision Shape", "Collision Shape of object in Rigid Body Simulations");
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
- RNA_def_property_update(prop, NC_OBJECT | ND_POINTCACHE, "rna_RigidBodyOb_reset");
+ RNA_def_property_update(prop, NC_OBJECT | ND_POINTCACHE, "rna_RigidBodyOb_shape_update");
prop = RNA_def_property(srna, "kinematic", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", RBO_FLAG_KINEMATIC);
diff --git a/source/blender/makesrna/intern/rna_rna.c b/source/blender/makesrna/intern/rna_rna.c
index 8f2537105c1..4650e27f63e 100644
--- a/source/blender/makesrna/intern/rna_rna.c
+++ b/source/blender/makesrna/intern/rna_rna.c
@@ -105,7 +105,6 @@ EnumPropertyItem property_unit_items[] = {
#ifdef RNA_RUNTIME
#include "MEM_guardedalloc.h"
-#include "BLI_utildefines.h"
#include "BLI_ghash.h"
/* Struct */
@@ -179,7 +178,7 @@ static int rna_idproperty_known(CollectionPropertyIterator *iter, void *data)
* for the second loop where we go over unknown id properties */
do {
for (prop = ptype->cont.properties.first; prop; prop = prop->next)
- if ((prop->flag & PROP_BUILTIN) == 0 && strcmp(prop->identifier, idprop->name) == 0)
+ if ((prop->flag & PROP_BUILTIN) == 0 && STREQ(prop->identifier, idprop->name))
return 1;
} while ((ptype = ptype->base));
@@ -386,7 +385,7 @@ int rna_builtin_properties_lookup_string(PointerRNA *ptr, const char *key, Point
}
else {
for (prop = srna->cont.properties.first; prop; prop = prop->next) {
- if (!(prop->flag & PROP_BUILTIN) && strcmp(prop->identifier, key) == 0) {
+ if (!(prop->flag & PROP_BUILTIN) && STREQ(prop->identifier, key)) {
propptr.type = &RNA_Property;
propptr.data = prop;
@@ -408,7 +407,7 @@ int rna_builtin_properties_lookup_string(PointerRNA *ptr, const char *key, Point
if (group) {
for (idp = group->data.group.first; idp; idp = idp->next) {
- if (strcmp(idp->name, key) == 0) {
+ if (STREQ(idp->name, key)) {
propptr.type = &RNA_Property;
propptr.data = idp;
@@ -545,7 +544,7 @@ static int rna_Property_readonly_get(PointerRNA *ptr)
* data for introspection we only need to know if it can be edited so the
* flag is better for this */
/* return RNA_property_editable(ptr, prop); */
- return prop->flag & PROP_EDITABLE ? 0 : 1;
+ return (prop->flag & PROP_EDITABLE) == 0;
}
static int rna_Property_animatable_get(PointerRNA *ptr)
@@ -558,50 +557,50 @@ static int rna_Property_animatable_get(PointerRNA *ptr)
static int rna_Property_use_output_get(PointerRNA *ptr)
{
PropertyRNA *prop = (PropertyRNA *)ptr->data;
- return prop->flag & PROP_OUTPUT ? 1 : 0;
+ return (prop->flag & PROP_OUTPUT) != 0;
}
static int rna_Property_is_required_get(PointerRNA *ptr)
{
PropertyRNA *prop = (PropertyRNA *)ptr->data;
- return prop->flag & PROP_REQUIRED ? 1 : 0;
+ return (prop->flag & PROP_REQUIRED) != 0;
}
static int rna_Property_is_argument_optional_get(PointerRNA *ptr)
{
PropertyRNA *prop = (PropertyRNA *)ptr->data;
- return prop->flag & PROP_PYFUNC_OPTIONAL ? 1 : 0;
+ return (prop->flag & PROP_PYFUNC_OPTIONAL) != 0;
}
static int rna_Property_is_never_none_get(PointerRNA *ptr)
{
PropertyRNA *prop = (PropertyRNA *)ptr->data;
- return prop->flag & PROP_NEVER_NULL ? 1 : 0;
+ return (prop->flag & PROP_NEVER_NULL) != 0;
}
static int rna_Property_is_hidden_get(PointerRNA *ptr)
{
PropertyRNA *prop = (PropertyRNA *)ptr->data;
- return prop->flag & PROP_HIDDEN ? 1 : 0;
+ return (prop->flag & PROP_HIDDEN) != 0;
}
static int rna_Property_is_skip_save_get(PointerRNA *ptr)
{
PropertyRNA *prop = (PropertyRNA *)ptr->data;
- return prop->flag & PROP_SKIP_SAVE ? 1 : 0;
+ return (prop->flag & PROP_SKIP_SAVE) != 0;
}
static int rna_Property_is_enum_flag_get(PointerRNA *ptr)
{
PropertyRNA *prop = (PropertyRNA *)ptr->data;
- return prop->flag & PROP_ENUM_FLAG ? 1 : 0;
+ return (prop->flag & PROP_ENUM_FLAG) != 0;
}
static int rna_Property_is_library_editable_flag_get(PointerRNA *ptr)
{
PropertyRNA *prop = (PropertyRNA *)ptr->data;
- return prop->flag & PROP_LIB_EXCEPTION ? 1 : 0;
+ return (prop->flag & PROP_LIB_EXCEPTION) != 0;
}
static int rna_Property_array_length_get(PointerRNA *ptr)
@@ -611,22 +610,22 @@ static int rna_Property_array_length_get(PointerRNA *ptr)
return prop->totarraylength;
}
-static int rna_Property_registered_get(PointerRNA *ptr)
+static int rna_Property_is_registered_get(PointerRNA *ptr)
{
PropertyRNA *prop = (PropertyRNA *)ptr->data;
- return prop->flag & PROP_REGISTER;
+ return (prop->flag & PROP_REGISTER) != 0;
}
-static int rna_Property_registered_optional_get(PointerRNA *ptr)
+static int rna_Property_is_registered_optional_get(PointerRNA *ptr)
{
PropertyRNA *prop = (PropertyRNA *)ptr->data;
- return prop->flag & PROP_REGISTER_OPTIONAL;
+ return (prop->flag & PROP_REGISTER_OPTIONAL) != 0;
}
-static int rna_Property_runtime_get(PointerRNA *ptr)
+static int rna_Property_is_runtime_get(PointerRNA *ptr)
{
PropertyRNA *prop = (PropertyRNA *)ptr->data;
- return prop->flag & PROP_RUNTIME;
+ return (prop->flag & PROP_RUNTIME) != 0;
}
@@ -813,7 +812,7 @@ static EnumPropertyItem *rna_EnumProperty_default_itemf(bContext *C, PointerRNA
/* incompatible default attributes */
if ((prop_parent->flag & PROP_ENUM_FLAG) != (prop->flag & PROP_ENUM_FLAG)) {
- return NULL;
+ return DummyRNA_NULL_items;
}
if ((eprop->itemf == NULL) ||
@@ -984,7 +983,7 @@ static void rna_BlenderRNA_structs_begin(CollectionPropertyIterator *iter, Point
/* optional, for faster lookups */
static int rna_BlenderRNA_structs_length(PointerRNA *ptr)
{
- return BLI_countlist(&((BlenderRNA *)ptr->data)->structs);
+ return BLI_listbase_count(&((BlenderRNA *)ptr->data)->structs);
}
static int rna_BlenderRNA_structs_lookup_int(PointerRNA *ptr, int index, PointerRNA *r_ptr)
{
@@ -1002,7 +1001,7 @@ static int rna_BlenderRNA_structs_lookup_string(PointerRNA *ptr, const char *key
{
StructRNA *srna = ((BlenderRNA *)ptr->data)->structs.first;
for (; srna; srna = srna->cont.next) {
- if (key[0] == srna->identifier[0] && strcmp(key, srna->identifier) == 0) {
+ if (key[0] == srna->identifier[0] && STREQ(key, srna->identifier)) {
RNA_pointer_create(NULL, &RNA_Struct, srna, r_ptr);
return true;
}
@@ -1210,18 +1209,18 @@ static void rna_def_property(BlenderRNA *brna)
prop = RNA_def_property(srna, "is_registered", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
- RNA_def_property_boolean_funcs(prop, "rna_Property_registered_get", NULL);
+ RNA_def_property_boolean_funcs(prop, "rna_Property_is_registered_get", NULL);
RNA_def_property_ui_text(prop, "Registered", "Property is registered as part of type registration");
prop = RNA_def_property(srna, "is_registered_optional", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
- RNA_def_property_boolean_funcs(prop, "rna_Property_registered_optional_get", NULL);
+ RNA_def_property_boolean_funcs(prop, "rna_Property_is_registered_optional_get", NULL);
RNA_def_property_ui_text(prop, "Registered Optionally",
"Property is optionally registered as part of type registration");
prop = RNA_def_property(srna, "is_runtime", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
- RNA_def_property_boolean_funcs(prop, "rna_Property_runtime_get", NULL);
+ RNA_def_property_boolean_funcs(prop, "rna_Property_is_runtime_get", NULL);
RNA_def_property_ui_text(prop, "Runtime", "Property has been dynamically created at runtime");
prop = RNA_def_property(srna, "is_enum_flag", PROP_BOOLEAN, PROP_NONE);
diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c
index 682a7f4ee31..176c218e378 100644
--- a/source/blender/makesrna/intern/rna_scene.c
+++ b/source/blender/makesrna/intern/rna_scene.c
@@ -36,14 +36,16 @@
#include "DNA_userdef_types.h"
#include "DNA_world_types.h"
+#include "IMB_imbuf_types.h"
+
#include "BLI_math.h"
-#include "BLF_translation.h"
+#include "BLT_translation.h"
-#include "BKE_freestyle.h"
#include "BKE_editmesh.h"
#include "BKE_paint.h"
-#include "BKE_scene.h"
+
+#include "GPU_extensions.h"
#include "RNA_define.h"
#include "RNA_enum_types.h"
@@ -56,9 +58,7 @@
#ifdef WITH_QUICKTIME
# include "quicktime_export.h"
-# ifdef WITH_AUDASPACE
-# include "AUD_Space.h"
-# endif
+# include AUD_TYPES_H
#endif
#ifdef WITH_FFMPEG
@@ -82,6 +82,11 @@ EnumPropertyItem exr_codec_items[] = {
{R_IMF_EXR_CODEC_ZIP, "ZIP", 0, "ZIP (lossless)", ""},
{R_IMF_EXR_CODEC_PIZ, "PIZ", 0, "PIZ (lossless)", ""},
{R_IMF_EXR_CODEC_RLE, "RLE", 0, "RLE (lossless)", ""},
+ {R_IMF_EXR_CODEC_ZIPS, "ZIPS", 0, "ZIPS (lossless)", ""},
+ {R_IMF_EXR_CODEC_B44, "B44", 0, "B44 (lossy)", ""},
+ {R_IMF_EXR_CODEC_B44A, "B44A", 0, "B44A (lossy)", ""},
+ {R_IMF_EXR_CODEC_DWAA, "DWAA", 0, "DWAA (lossy)", ""},
+ {R_IMF_EXR_CODEC_DWAB, "DWAB", 0, "DWAB (lossy)", ""},
{0, NULL, 0, NULL, NULL}
};
#endif
@@ -112,6 +117,7 @@ EnumPropertyItem proportional_falloff_items[] = {
{PROP_SMOOTH, "SMOOTH", ICON_SMOOTHCURVE, "Smooth", "Smooth falloff"},
{PROP_SPHERE, "SPHERE", ICON_SPHERECURVE, "Sphere", "Spherical falloff"},
{PROP_ROOT, "ROOT", ICON_ROOTCURVE, "Root", "Root falloff"},
+ {PROP_INVSQUARE, "INVERSE_SQUARE", ICON_ROOTCURVE, "Inverse Square", "Inverse Square falloff"},
{PROP_SHARP, "SHARP", ICON_SHARPCURVE, "Sharp", "Sharp falloff"},
{PROP_LIN, "LINEAR", ICON_LINCURVE, "Linear", "Linear falloff"},
{PROP_CONST, "CONSTANT", ICON_NOCURVE, "Constant", "Constant falloff"},
@@ -124,6 +130,7 @@ EnumPropertyItem proportional_falloff_curve_only_items[] = {
{PROP_SMOOTH, "SMOOTH", ICON_SMOOTHCURVE, "Smooth", "Smooth falloff"},
{PROP_SPHERE, "SPHERE", ICON_SPHERECURVE, "Sphere", "Spherical falloff"},
{PROP_ROOT, "ROOT", ICON_ROOTCURVE, "Root", "Root falloff"},
+ {PROP_INVSQUARE, "INVERSE_SQUARE", ICON_ROOTCURVE, "Inverse Square", "Inverse Square falloff"},
{PROP_SHARP, "SHARP", ICON_SHARPCURVE, "Sharp", "Sharp falloff"},
{PROP_LIN, "LINEAR", ICON_LINCURVE, "Linear", "Linear falloff"},
{0, NULL, 0, NULL, NULL}
@@ -158,7 +165,7 @@ EnumPropertyItem snap_element_items[] = {
};
EnumPropertyItem snap_node_element_items[] = {
- {SCE_SNAP_MODE_GRID, "GRID", ICON_SNAP_INCREMENT, "Grid", "Snap to grid"},
+ {SCE_SNAP_MODE_GRID, "GRID", ICON_SNAP_GRID, "Grid", "Snap to grid"},
{SCE_SNAP_MODE_NODE_X, "NODE_X", ICON_SNAP_EDGE, "Node X", "Snap to left/right node border"},
{SCE_SNAP_MODE_NODE_Y, "NODE_Y", ICON_SNAP_EDGE, "Node Y", "Snap to top/bottom node border"},
{SCE_SNAP_MODE_NODE_XY, "NODE_XY", ICON_SNAP_EDGE, "Node X / Y", "Snap to any node border"},
@@ -209,13 +216,13 @@ EnumPropertyItem snap_uv_element_items[] = {
#endif
#ifdef WITH_OPENEXR
-# define R_IMF_ENUM_EXR_MULTI {R_IMF_IMTYPE_MULTILAYER, "OPEN_EXR_MULTILAYER", ICON_FILE_IMAGE, \
+# define R_IMF_ENUM_EXR_MULTILAYER {R_IMF_IMTYPE_MULTILAYER, "OPEN_EXR_MULTILAYER", ICON_FILE_IMAGE, \
"OpenEXR MultiLayer", \
"Output image in multilayer OpenEXR format"},
# define R_IMF_ENUM_EXR {R_IMF_IMTYPE_OPENEXR, "OPEN_EXR", ICON_FILE_IMAGE, "OpenEXR", \
"Output image in OpenEXR format"},
#else
-# define R_IMF_ENUM_EXR_MULTI
+# define R_IMF_ENUM_EXR_MULTILAYER
# define R_IMF_ENUM_EXR
#endif
@@ -244,7 +251,7 @@ EnumPropertyItem snap_uv_element_items[] = {
{0, "", 0, " ", NULL}, \
R_IMF_ENUM_CINEON \
R_IMF_ENUM_DPX \
- R_IMF_ENUM_EXR_MULTI \
+ R_IMF_ENUM_EXR_MULTILAYER \
R_IMF_ENUM_EXR \
R_IMF_ENUM_HDR \
R_IMF_ENUM_TIFF \
@@ -328,6 +335,62 @@ EnumPropertyItem bake_save_mode_items[] = {
{0, NULL, 0, NULL, NULL}
};
+#define R_IMF_VIEWS_ENUM_IND {R_IMF_VIEWS_INDIVIDUAL, "INDIVIDUAL", 0, "Individual", \
+ "Individual files for each view with the prefix as defined by the scene views"},
+#define R_IMF_VIEWS_ENUM_S3D {R_IMF_VIEWS_STEREO_3D, "STEREO_3D", 0, "Stereo 3D", \
+ "Single file with an encoded stereo pair"},
+#define R_IMF_VIEWS_ENUM_MV {R_IMF_VIEWS_MULTIVIEW, "MULTIVIEW", 0, "Multi-View", "Single file with all the views"},
+
+EnumPropertyItem views_format_items[] = {
+ R_IMF_VIEWS_ENUM_IND
+ R_IMF_VIEWS_ENUM_S3D
+ {0, NULL, 0, NULL, NULL}
+};
+
+EnumPropertyItem views_format_multilayer_items[] = {
+ R_IMF_VIEWS_ENUM_IND
+ R_IMF_VIEWS_ENUM_MV
+ {0, NULL, 0, NULL, NULL}
+};
+
+EnumPropertyItem views_format_multiview_items[] = {
+ R_IMF_VIEWS_ENUM_IND
+ R_IMF_VIEWS_ENUM_S3D
+ R_IMF_VIEWS_ENUM_MV
+ {0, NULL, 0, NULL, NULL}
+};
+
+#undef R_IMF_VIEWS_ENUM_IND
+#undef R_IMF_VIEWS_ENUM_S3D
+#undef R_IMF_VIEWS_ENUM_MV
+
+EnumPropertyItem stereo3d_display_items[] = {
+ {S3D_DISPLAY_ANAGLYPH, "ANAGLYPH", 0, "Anaglyph",
+ "Render views for left and right eyes as two differently filtered colors in a single image "
+ "(anaglyph glasses are required)"},
+ {S3D_DISPLAY_INTERLACE, "INTERLACE", 0, "Interlace",
+ "Render views for left and right eyes interlaced in a single image (3D-ready monitor is required)"},
+ {S3D_DISPLAY_PAGEFLIP, "TIMESEQUENTIAL", 0, "Time Sequential",
+ "Render alternate eyes (also known as page flip, quad buffer support in the graphic card is required)"},
+ {S3D_DISPLAY_SIDEBYSIDE, "SIDEBYSIDE", 0, "Side-by-Side", "Render views for left and right eyes side-by-side"},
+ {S3D_DISPLAY_TOPBOTTOM, "TOPBOTTOM", 0, "Top-Bottom", "Render views for left and right eyes one above another"},
+ {0, NULL, 0, NULL, NULL}
+};
+
+EnumPropertyItem stereo3d_anaglyph_type_items[] = {
+ {S3D_ANAGLYPH_REDCYAN, "RED_CYAN", 0, "Red-Cyan", ""},
+ {S3D_ANAGLYPH_GREENMAGENTA, "GREEN_MAGENTA", 0, "Green-Magenta", ""},
+ {S3D_ANAGLYPH_YELLOWBLUE, "YELLOW_BLUE", 0, "Yellow-Blue", ""},
+ {0, NULL, 0, NULL, NULL}
+};
+
+EnumPropertyItem stereo3d_interlace_type_items[] = {
+ {S3D_INTERLACE_ROW, "ROW_INTERLEAVED", 0, "Row Interleaved", ""},
+ {S3D_INTERLACE_COLUMN, "COLUMN_INTERLEAVED", 0, "Column Interleaved", ""},
+ {S3D_INTERLACE_CHECKERBOARD, "CHECKERBOARD_INTERLEAVED", 0, "Checkerboard Interleaved", ""},
+ {0, NULL, 0, NULL, NULL}
+};
+
#ifdef RNA_RUNTIME
#include "DNA_anim_types.h"
@@ -340,8 +403,6 @@ EnumPropertyItem bake_save_mode_items[] = {
#include "MEM_guardedalloc.h"
-#include "BLI_threads.h"
-
#include "BKE_brush.h"
#include "BKE_context.h"
#include "BKE_global.h"
@@ -351,7 +412,6 @@ EnumPropertyItem bake_save_mode_items[] = {
#include "BKE_pointcache.h"
#include "BKE_scene.h"
#include "BKE_depsgraph.h"
-#include "BKE_image.h"
#include "BKE_mesh.h"
#include "BKE_sound.h"
#include "BKE_screen.h"
@@ -359,8 +419,6 @@ EnumPropertyItem bake_save_mode_items[] = {
#include "BKE_animsys.h"
#include "BKE_freestyle.h"
-#include "WM_api.h"
-
#include "ED_info.h"
#include "ED_node.h"
#include "ED_view3d.h"
@@ -368,11 +426,13 @@ EnumPropertyItem bake_save_mode_items[] = {
#include "ED_keyframing.h"
#include "ED_image.h"
-#include "RE_engine.h"
+#ifdef WITH_FREESTYLE
+#include "FRS_freestyle.h"
+#endif
static void rna_SpaceImageEditor_uv_sculpt_update(Main *bmain, Scene *scene, PointerRNA *UNUSED(ptr))
{
- ED_space_image_uv_sculpt_update(bmain->wm.first, scene->toolsettings);
+ ED_space_image_uv_sculpt_update(bmain->wm.first, scene);
}
static int rna_Scene_object_bases_lookup_string(PointerRNA *ptr, const char *key, PointerRNA *r_ptr)
@@ -381,7 +441,7 @@ static int rna_Scene_object_bases_lookup_string(PointerRNA *ptr, const char *key
Base *base;
for (base = scene->base.first; base; base = base->next) {
- if (strncmp(base->object->id.name + 2, key, sizeof(base->object->id.name) - 2) == 0) {
+ if (STREQLEN(base->object->id.name + 2, key, sizeof(base->object->id.name) - 2)) {
*r_ptr = rna_pointer_inherit_refine(ptr, &RNA_ObjectBase, base);
return true;
}
@@ -418,6 +478,8 @@ static Base *rna_Scene_object_link(Scene *scene, bContext *C, ReportList *report
if (scene == scene_act)
ob->lay = base->lay;
+ /* TODO(sergey): Only update relations for the current scene. */
+ DAG_relations_tag_update(CTX_data_main(C));
DAG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
/* slows down importers too much, run scene.update() */
@@ -528,13 +590,13 @@ static void rna_Scene_layer_update(Main *bmain, Scene *scene, PointerRNA *ptr)
static void rna_Scene_fps_update(Main *UNUSED(bmain), Scene *scene, PointerRNA *UNUSED(ptr))
{
- sound_update_fps(scene);
+ BKE_sound_update_fps(scene);
BKE_sequencer_update_sound_bounds_all(scene);
}
static void rna_Scene_listener_update(Main *UNUSED(bmain), Scene *scene, PointerRNA *UNUSED(ptr))
{
- sound_update_scene_listener(scene);
+ BKE_sound_update_scene_listener(scene);
}
static void rna_Scene_volume_set(PointerRNA *ptr, float value)
@@ -543,7 +605,7 @@ static void rna_Scene_volume_set(PointerRNA *ptr, float value)
scene->audio.volume = value;
if (scene->sound_scene)
- sound_set_scene_volume(scene, value);
+ BKE_sound_set_scene_volume(scene, value);
}
static void rna_Scene_framelen_update(Main *UNUSED(bmain), Scene *scene, PointerRNA *UNUSED(ptr))
@@ -644,7 +706,7 @@ static void rna_Scene_preview_range_end_frame_set(PointerRNA *ptr, int value)
static void rna_Scene_frame_update(Main *bmain, Scene *UNUSED(current_scene), PointerRNA *ptr)
{
Scene *scene = (Scene *)ptr->id.data;
- sound_seek_scene(bmain, scene);
+ BKE_sound_seek_scene(bmain, scene);
}
static PointerRNA rna_Scene_active_keying_set_get(PointerRNA *ptr)
@@ -711,6 +773,26 @@ static void rna_Scene_all_keyingsets_next(CollectionPropertyIterator *iter)
iter->valid = (internal->link != NULL);
}
+static int rna_RenderSettings_stereoViews_skip(CollectionPropertyIterator *iter, void *UNUSED(data))
+{
+ ListBaseIterator *internal = &iter->internal.listbase;
+ SceneRenderView *srv = (SceneRenderView *)internal->link;
+
+ if ((STREQ(srv->name, STEREO_LEFT_NAME)) ||
+ (STREQ(srv->name, STEREO_RIGHT_NAME)))
+ {
+ return 0;
+ }
+
+ return 1;
+};
+
+static void rna_RenderSettings_stereoViews_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
+{
+ RenderData *rd = (RenderData *)ptr->data;
+ rna_iterator_listbase_begin(iter, &rd->views, rna_RenderSettings_stereoViews_skip);
+}
+
static char *rna_RenderSettings_path(PointerRNA *UNUSED(ptr))
{
return BLI_sprintfN("render");
@@ -733,7 +815,7 @@ static int rna_RenderSettings_threads_mode_get(PointerRNA *ptr)
return (rd->mode & R_FIXED_THREADS);
}
-static int rna_RenderSettings_is_movie_fomat_get(PointerRNA *ptr)
+static int rna_RenderSettings_is_movie_format_get(PointerRNA *ptr)
{
RenderData *rd = (RenderData *)ptr->data;
return BKE_imtype_is_movie(rd->im_format.imtype);
@@ -749,7 +831,7 @@ static int rna_RenderSettings_save_buffers_get(PointerRNA *ptr)
else if (!BKE_scene_use_new_shading_nodes(scene))
return (rd->scemode & (R_EXR_TILE_FILE | R_FULL_SAMPLE)) != 0;
else
- return (rd->scemode & R_EXR_TILE_FILE);
+ return (rd->scemode & R_EXR_TILE_FILE) != 0;
}
static int rna_RenderSettings_full_sample_get(PointerRNA *ptr)
@@ -813,8 +895,8 @@ static void rna_ImageFormatSettings_file_format_set(PointerRNA *ptr, int value)
}
}
-static EnumPropertyItem *rna_ImageFormatSettings_file_format_itemf(bContext *UNUSED(C), PointerRNA *ptr,
- PropertyRNA *UNUSED(prop), bool *UNUSED(r_free))
+static EnumPropertyItem *rna_ImageFormatSettings_file_format_itemf(
+ bContext *UNUSED(C), PointerRNA *ptr, PropertyRNA *UNUSED(prop), bool *UNUSED(r_free))
{
ID *id = ptr->id.data;
if (id && GS(id->name) == ID_SCE) {
@@ -825,8 +907,8 @@ static EnumPropertyItem *rna_ImageFormatSettings_file_format_itemf(bContext *UNU
}
}
-static EnumPropertyItem *rna_ImageFormatSettings_color_mode_itemf(bContext *UNUSED(C), PointerRNA *ptr,
- PropertyRNA *UNUSED(prop), bool *r_free)
+static EnumPropertyItem *rna_ImageFormatSettings_color_mode_itemf(
+ bContext *UNUSED(C), PointerRNA *ptr, PropertyRNA *UNUSED(prop), bool *r_free)
{
ImageFormatData *imf = (ImageFormatData *)ptr->data;
ID *id = ptr->id.data;
@@ -870,8 +952,8 @@ static EnumPropertyItem *rna_ImageFormatSettings_color_mode_itemf(bContext *UNUS
}
}
-static EnumPropertyItem *rna_ImageFormatSettings_color_depth_itemf(bContext *UNUSED(C), PointerRNA *ptr,
- PropertyRNA *UNUSED(prop), bool *r_free)
+static EnumPropertyItem *rna_ImageFormatSettings_color_depth_itemf(
+ bContext *UNUSED(C), PointerRNA *ptr, PropertyRNA *UNUSED(prop), bool *r_free)
{
ImageFormatData *imf = (ImageFormatData *)ptr->data;
@@ -933,12 +1015,60 @@ static EnumPropertyItem *rna_ImageFormatSettings_color_depth_itemf(bContext *UNU
}
}
+static EnumPropertyItem *rna_ImageFormatSettings_views_format_itemf(
+ bContext *UNUSED(C), PointerRNA *ptr, PropertyRNA *UNUSED(prop), bool *UNUSED(r_free))
+{
+ ImageFormatData *imf = (ImageFormatData *)ptr->data;
+
+ if (imf == NULL) {
+ return views_format_items;
+ }
+ else if (imf->imtype == R_IMF_IMTYPE_OPENEXR) {
+ return views_format_multiview_items;
+ }
+ else if (imf->imtype == R_IMF_IMTYPE_MULTILAYER) {
+ return views_format_multilayer_items;
+ }
+ else {
+ return views_format_items;
+ }
+}
+
+#ifdef WITH_OPENEXR
+ /* OpenEXR */
+
+static EnumPropertyItem *rna_ImageFormatSettings_exr_codec_itemf(
+ bContext *UNUSED(C), PointerRNA *ptr, PropertyRNA *UNUSED(prop), bool *r_free)
+{
+ ImageFormatData *imf = (ImageFormatData *)ptr->data;
+
+ EnumPropertyItem *item = NULL;
+ int i = 1, totitem = 0;
+
+ if (imf->depth == 16)
+ return exr_codec_items; /* All compression types are defined for halfs */
+
+ for (i = 0; i < R_IMF_EXR_CODEC_MAX; i++) {
+ if ((i == R_IMF_EXR_CODEC_B44 || i == R_IMF_EXR_CODEC_B44A)) {
+ continue; /* B44 and B44A are not defined for 32 bit floats */
+ }
+
+ RNA_enum_item_add(&item, &totitem, &exr_codec_items[i]);
+ }
+
+ RNA_enum_item_end(&item, &totitem);
+ *r_free = true;
+
+ return item;
+}
+
+#endif
static int rna_SceneRender_file_ext_length(PointerRNA *ptr)
{
RenderData *rd = (RenderData *)ptr->data;
char ext[8];
ext[0] = '\0';
- BKE_add_image_extension(ext, &rd->im_format);
+ BKE_image_path_ensure_ext_from_imformat(ext, &rd->im_format);
return strlen(ext);
}
@@ -946,7 +1076,7 @@ static void rna_SceneRender_file_ext_get(PointerRNA *ptr, char *str)
{
RenderData *rd = (RenderData *)ptr->data;
str[0] = '\0';
- BKE_add_image_extension(str, &rd->im_format);
+ BKE_image_path_ensure_ext_from_imformat(str, &rd->im_format);
}
#ifdef WITH_QUICKTIME
@@ -964,8 +1094,8 @@ static void rna_RenderSettings_qtcodecsettings_codecType_set(PointerRNA *ptr, in
settings->codecType = quicktime_videocodecType_from_rnatmpvalue(value);
}
-static EnumPropertyItem *rna_RenderSettings_qtcodecsettings_codecType_itemf(bContext *UNUSED(C), PointerRNA *UNUSED(ptr),
- PropertyRNA *UNUSED(prop), bool *r_free)
+static EnumPropertyItem *rna_RenderSettings_qtcodecsettings_codecType_itemf(
+ bContext *UNUSED(C), PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), bool *r_free)
{
EnumPropertyItem *item = NULL;
EnumPropertyItem tmp = {0, "", 0, "", ""};
@@ -1002,8 +1132,8 @@ static void rna_RenderSettings_qtcodecsettings_audiocodecType_set(PointerRNA *pt
settings->audiocodecType = quicktime_audiocodecType_from_rnatmpvalue(value);
}
-static EnumPropertyItem *rna_RenderSettings_qtcodecsettings_audiocodecType_itemf(bContext *UNUSED(C), PointerRNA *UNUSED(ptr),
- PropertyRNA *UNUSED(prop), bool *r_free)
+static EnumPropertyItem *rna_RenderSettings_qtcodecsettings_audiocodecType_itemf(
+ bContext *UNUSED(C), PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), bool *r_free)
{
EnumPropertyItem *item = NULL;
EnumPropertyItem tmp = {0, "", 0, "", ""};
@@ -1059,17 +1189,17 @@ static int rna_RenderSettings_active_layer_index_get(PointerRNA *ptr)
static void rna_RenderSettings_active_layer_index_set(PointerRNA *ptr, int value)
{
RenderData *rd = (RenderData *)ptr->data;
- int num_layers = BLI_countlist(&rd->layers);
+ int num_layers = BLI_listbase_count(&rd->layers);
rd->actlay = min_ff(value, num_layers - 1);
}
-static void rna_RenderSettings_active_layer_index_range(PointerRNA *ptr, int *min, int *max,
- int *UNUSED(softmin), int *UNUSED(softmax))
+static void rna_RenderSettings_active_layer_index_range(
+ PointerRNA *ptr, int *min, int *max, int *UNUSED(softmin), int *UNUSED(softmax))
{
RenderData *rd = (RenderData *)ptr->data;
*min = 0;
- *max = max_ii(0, BLI_countlist(&rd->layers) - 1);
+ *max = max_ii(0, BLI_listbase_count(&rd->layers) - 1);
}
static PointerRNA rna_RenderSettings_active_layer_get(PointerRNA *ptr)
@@ -1099,8 +1229,8 @@ static SceneRenderLayer *rna_RenderLayer_new(ID *id, RenderData *UNUSED(rd), con
return srl;
}
-static void rna_RenderLayer_remove(ID *id, RenderData *UNUSED(rd), Main *bmain, ReportList *reports,
- PointerRNA *srl_ptr)
+static void rna_RenderLayer_remove(
+ ID *id, RenderData *UNUSED(rd), Main *bmain, ReportList *reports, PointerRNA *srl_ptr)
{
SceneRenderLayer *srl = srl_ptr->data;
Scene *scene = (Scene *)id;
@@ -1117,6 +1247,70 @@ static void rna_RenderLayer_remove(ID *id, RenderData *UNUSED(rd), Main *bmain,
WM_main_add_notifier(NC_SCENE | ND_RENDER_OPTIONS, NULL);
}
+static int rna_RenderSettings_active_view_index_get(PointerRNA *ptr)
+{
+ RenderData *rd = (RenderData *)ptr->data;
+ return rd->actview;
+}
+
+static void rna_RenderSettings_active_view_index_set(PointerRNA *ptr, int value)
+{
+ RenderData *rd = (RenderData *)ptr->data;
+ rd->actview = value;
+}
+
+static void rna_RenderSettings_active_view_index_range(
+ PointerRNA *ptr, int *min, int *max, int *UNUSED(softmin), int *UNUSED(softmax))
+{
+ RenderData *rd = (RenderData *)ptr->data;
+
+ *min = 0;
+ *max = max_ii(0, BLI_listbase_count(&rd->views) - 1);
+}
+
+static PointerRNA rna_RenderSettings_active_view_get(PointerRNA *ptr)
+{
+ RenderData *rd = (RenderData *)ptr->data;
+ SceneRenderView *srv = BLI_findlink(&rd->views, rd->actview);
+
+ return rna_pointer_inherit_refine(ptr, &RNA_SceneRenderView, srv);
+}
+
+static void rna_RenderSettings_active_view_set(PointerRNA *ptr, PointerRNA value)
+{
+ RenderData *rd = (RenderData *)ptr->data;
+ SceneRenderView *srv = (SceneRenderView *)value.data;
+ const int index = BLI_findindex(&rd->views, srv);
+ if (index != -1) rd->actview = index;
+}
+
+static SceneRenderView *rna_RenderView_new(ID *id, RenderData *UNUSED(rd), const char *name)
+{
+ Scene *scene = (Scene *)id;
+ SceneRenderView *srv = BKE_scene_add_render_view(scene, name);
+
+ WM_main_add_notifier(NC_SCENE | ND_RENDER_OPTIONS, NULL);
+
+ return srv;
+}
+
+static void rna_RenderView_remove(
+ ID *id, RenderData *UNUSED(rd), Main *UNUSED(bmain), ReportList *reports, PointerRNA *srv_ptr)
+{
+ SceneRenderView *srv = srv_ptr->data;
+ Scene *scene = (Scene *)id;
+
+ if (!BKE_scene_remove_render_view(scene, srv)) {
+ BKE_reportf(reports, RPT_ERROR, "Render view '%s' could not be removed from scene '%s'",
+ srv->name, scene->id.name + 2);
+ return;
+ }
+
+ RNA_POINTER_INVALIDATE(srv_ptr);
+
+ WM_main_add_notifier(NC_SCENE | ND_RENDER_OPTIONS, NULL);
+}
+
static void rna_RenderSettings_engine_set(PointerRNA *ptr, int value)
{
RenderData *rd = (RenderData *)ptr->data;
@@ -1126,8 +1320,8 @@ static void rna_RenderSettings_engine_set(PointerRNA *ptr, int value)
BLI_strncpy_utf8(rd->engine, type->idname, sizeof(rd->engine));
}
-static EnumPropertyItem *rna_RenderSettings_engine_itemf(bContext *UNUSED(C), PointerRNA *UNUSED(ptr),
- PropertyRNA *UNUSED(prop), bool *r_free)
+static EnumPropertyItem *rna_RenderSettings_engine_itemf(
+ bContext *UNUSED(C), PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), bool *r_free)
{
RenderEngineType *type;
EnumPropertyItem *item = NULL;
@@ -1154,7 +1348,7 @@ static int rna_RenderSettings_engine_get(PointerRNA *ptr)
int a = 0;
for (type = R_engines.first; type; type = type->next, a++)
- if (strcmp(type->idname, rd->engine) == 0)
+ if (STREQ(type->idname, rd->engine))
return a;
return 0;
@@ -1179,6 +1373,13 @@ static void rna_Scene_freestyle_update(Main *UNUSED(bmain), Scene *UNUSED(scene)
DAG_id_tag_update(&scene->id, 0);
}
+static void rna_Scene_use_view_map_cache_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *UNUSED(ptr))
+{
+#ifdef WITH_FREESTYLE
+ FRS_free_view_map_cache();
+#endif
+}
+
static void rna_SceneRenderLayer_name_set(PointerRNA *ptr, const char *value)
{
Scene *scene = (Scene *)ptr->id.data;
@@ -1203,7 +1404,7 @@ static void rna_SceneRenderLayer_name_set(PointerRNA *ptr, const char *value)
}
/* fix all the animation data which may link to this */
- BKE_all_animdata_fix_paths_rename(NULL, "render.layers", oldname, rl->name);
+ BKE_animdata_fix_paths_rename_all(NULL, "render.layers", oldname, rl->name);
}
static char *rna_SceneRenderLayer_path(PointerRNA *ptr)
@@ -1215,9 +1416,37 @@ static char *rna_SceneRenderLayer_path(PointerRNA *ptr)
return BLI_sprintfN("render.layers[\"%s\"]", name_esc);
}
+static void rna_SceneRenderView_name_set(PointerRNA *ptr, const char *value)
+{
+ Scene *scene = (Scene *)ptr->id.data;
+ SceneRenderView *rv = (SceneRenderView *)ptr->data;
+ BLI_strncpy_utf8(rv->name, value, sizeof(rv->name));
+ BLI_uniquename(&scene->r.views, rv, DATA_("RenderView"), '.', offsetof(SceneRenderView, name), sizeof(rv->name));
+}
+
+static char *rna_SceneRenderView_path(PointerRNA *ptr)
+{
+ SceneRenderView *srv = (SceneRenderView *)ptr->data;
+ return BLI_sprintfN("render.views[\"%s\"]", srv->name);
+}
+
+static void rna_RenderSettings_views_format_set(PointerRNA *ptr, int value)
+{
+ RenderData *rd = (RenderData *)ptr->data;
+
+ if (rd->views_format == SCE_VIEWS_FORMAT_MULTIVIEW &&
+ value == SCE_VIEWS_FORMAT_STEREO_3D)
+ {
+ /* make sure the actview is visible */
+ if (rd->actview > 1) rd->actview = 1;
+ }
+
+ rd->views_format = value;
+}
+
static int rna_RenderSettings_multiple_engines_get(PointerRNA *UNUSED(ptr))
{
- return (BLI_countlist(&R_engines) > 1);
+ return (BLI_listbase_count(&R_engines) > 1);
}
static int rna_RenderSettings_use_shading_nodes_get(PointerRNA *ptr)
@@ -1232,8 +1461,8 @@ static int rna_RenderSettings_use_game_engine_get(PointerRNA *ptr)
RenderEngineType *type;
for (type = R_engines.first; type; type = type->next)
- if (strcmp(type->idname, rd->engine) == 0)
- return (type->flag & RE_GAME);
+ if (STREQ(type->idname, rd->engine))
+ return (type->flag & RE_GAME) != 0;
return 0;
}
@@ -1364,7 +1593,7 @@ static void rna_Scene_use_persistent_data_update(Main *UNUSED(bmain), Scene *UNU
static int rna_Scene_use_audio_get(PointerRNA *ptr)
{
Scene *scene = (Scene *)ptr->data;
- return scene->audio.flag & AUDIO_MUTE;
+ return (scene->audio.flag & AUDIO_MUTE) != 0;
}
static void rna_Scene_use_audio_set(PointerRNA *ptr, int value)
@@ -1376,7 +1605,7 @@ static void rna_Scene_use_audio_set(PointerRNA *ptr, int value)
else
scene->audio.flag &= ~AUDIO_MUTE;
- sound_mute_scene(scene, value);
+ BKE_sound_mute_scene(scene, value);
}
static int rna_Scene_sync_mode_get(PointerRNA *ptr)
@@ -1406,10 +1635,7 @@ static void rna_Scene_sync_mode_set(PointerRNA *ptr, int value)
static int rna_GameSettings_auto_start_get(PointerRNA *UNUSED(ptr))
{
- if (G.fileflags & G_FILE_AUTOPLAY)
- return 1;
-
- return 0;
+ return (G.fileflags & G_FILE_AUTOPLAY) != 0;
}
static void rna_GameSettings_auto_start_set(PointerRNA *UNUSED(ptr), int value)
@@ -1474,7 +1700,7 @@ static KeyingSet *rna_Scene_keying_set_new(Scene *sce, ReportList *reports, cons
ks = BKE_keyingset_add(&sce->keyingsets, idname, name, KEYINGSET_ABSOLUTE, 0);
if (ks) {
- sce->active_keyingset = BLI_countlist(&sce->keyingsets);
+ sce->active_keyingset = BLI_listbase_count(&sce->keyingsets);
return ks;
}
else {
@@ -1593,10 +1819,11 @@ static void rna_FreestyleLineSet_linestyle_set(PointerRNA *ptr, PointerRNA value
lineset->linestyle->id.us++;
}
-static FreestyleLineSet *rna_FreestyleSettings_lineset_add(ID *id, FreestyleSettings *config, const char *name)
+static FreestyleLineSet *rna_FreestyleSettings_lineset_add(
+ ID *id, FreestyleSettings *config, Main *bmain, const char *name)
{
Scene *scene = (Scene *)id;
- FreestyleLineSet *lineset = BKE_freestyle_lineset_add((FreestyleConfig *)config, name);
+ FreestyleLineSet *lineset = BKE_freestyle_lineset_add(bmain, (FreestyleConfig *)config, name);
DAG_id_tag_update(&scene->id, 0);
WM_main_add_notifier(NC_SCENE | ND_RENDER_OPTIONS, NULL);
@@ -1604,8 +1831,8 @@ static FreestyleLineSet *rna_FreestyleSettings_lineset_add(ID *id, FreestyleSett
return lineset;
}
-static void rna_FreestyleSettings_lineset_remove(ID *id, FreestyleSettings *config, ReportList *reports,
- PointerRNA *lineset_ptr)
+static void rna_FreestyleSettings_lineset_remove(
+ ID *id, FreestyleSettings *config, ReportList *reports, PointerRNA *lineset_ptr)
{
FreestyleLineSet *lineset = lineset_ptr->data;
Scene *scene = (Scene *)id;
@@ -1628,13 +1855,13 @@ static PointerRNA rna_FreestyleSettings_active_lineset_get(PointerRNA *ptr)
return rna_pointer_inherit_refine(ptr, &RNA_FreestyleLineSet, lineset);
}
-static void rna_FreestyleSettings_active_lineset_index_range(PointerRNA *ptr, int *min, int *max,
- int *UNUSED(softmin), int *UNUSED(softmax))
+static void rna_FreestyleSettings_active_lineset_index_range(
+ PointerRNA *ptr, int *min, int *max, int *UNUSED(softmin), int *UNUSED(softmax))
{
FreestyleConfig *config = (FreestyleConfig *)ptr->data;
*min = 0;
- *max = max_ii(0, BLI_countlist(&config->linesets) - 1);
+ *max = max_ii(0, BLI_listbase_count(&config->linesets) - 1);
}
static int rna_FreestyleSettings_active_lineset_index_get(PointerRNA *ptr)
@@ -1660,8 +1887,8 @@ static FreestyleModuleConfig *rna_FreestyleSettings_module_add(ID *id, Freestyle
return module;
}
-static void rna_FreestyleSettings_module_remove(ID *id, FreestyleSettings *config, ReportList *reports,
- PointerRNA *module_ptr)
+static void rna_FreestyleSettings_module_remove(
+ ID *id, FreestyleSettings *config, ReportList *reports, PointerRNA *module_ptr)
{
Scene *scene = (Scene *)id;
FreestyleModuleConfig *module = module_ptr->data;
@@ -1670,7 +1897,7 @@ static void rna_FreestyleSettings_module_remove(ID *id, FreestyleSettings *confi
if (module->script)
BKE_reportf(reports, RPT_ERROR, "Style module '%s' could not be removed", module->script->id.name + 2);
else
- BKE_reportf(reports, RPT_ERROR, "Style module could not be removed");
+ BKE_report(reports, RPT_ERROR, "Style module could not be removed");
return;
}
@@ -1680,6 +1907,66 @@ static void rna_FreestyleSettings_module_remove(ID *id, FreestyleSettings *confi
WM_main_add_notifier(NC_SCENE | ND_RENDER_OPTIONS, NULL);
}
+char *rna_GPUDOF_path(PointerRNA *ptr)
+{
+ /* if there is ID-data, resolve the path using the index instead of by name,
+ * since the name used is the name of the texture assigned, but the texture
+ * may be used multiple times in the same stack
+ */
+ if (ptr->id.data) {
+ if (GS(((ID *)ptr->id.data)->name) == ID_CA) {
+ return BLI_strdup("gpu_dof");
+ }
+ }
+
+ return BLI_strdup("");
+}
+
+static void rna_GPUFXSettings_fx_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
+{
+ GPUFXSettings *fx_settings = ptr->data;
+
+ BKE_screen_gpu_fx_validate(fx_settings);
+}
+
+static void rna_GPUDOFSettings_blades_set(PointerRNA *ptr, const int value)
+{
+ GPUDOFSettings *dofsettings = (GPUDOFSettings *)ptr->data;
+
+ if (value < 3 && dofsettings->num_blades > 2)
+ dofsettings->num_blades = 0;
+ else if (value > 0 && dofsettings->num_blades == 0)
+ dofsettings->num_blades = 3;
+ else
+ dofsettings->num_blades = value;
+}
+
+static void rna_Stereo3dFormat_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
+{
+ ID *id = ptr->id.data;
+
+ if (id && GS(id->name) == ID_IM) {
+ Image *ima = (Image *)id;
+ ImBuf *ibuf;
+ void *lock;
+
+ if ((ima->flag & IMA_IS_STEREO) == 0)
+ return;
+
+ ibuf = BKE_image_acquire_ibuf(ima, NULL, &lock);
+
+ if (ibuf) {
+ BKE_image_signal(ima, NULL, IMA_SIGNAL_FREE);
+ }
+ BKE_image_release_ibuf(ima, ibuf, lock);
+ }
+}
+
+static int rna_gpu_is_hq_supported_get(PointerRNA *UNUSED(ptr))
+{
+ return GPU_instanced_drawing_support() && GPU_geometry_shader_support();
+}
+
#else
static void rna_def_transform_orientation(BlenderRNA *brna)
@@ -1762,6 +2049,16 @@ static void rna_def_tool_settings(BlenderRNA *brna)
{WT_VGROUP_BONE_DEFORM_OFF, "OTHER_DEFORM", 0, "Other", "Vertex Groups assigned to non Deform Bones"},
{0, NULL, 0, NULL, NULL}
};
+
+ static EnumPropertyItem gpencil_source_3d_items[] = {
+ {GP_TOOL_SOURCE_SCENE, "SCENE", 0, "Scene",
+ "Grease Pencil data attached to the current scene is used, "
+ "unless the active object already has Grease Pencil data (i.e. for old files)"},
+ {GP_TOOL_SOURCE_OBJECT, "OBJECT", 0, "Object",
+ "Grease Pencil datablocks attached to the active object are used "
+ "(required using pre 2.73 add-ons, e.g. BSurfaces)"},
+ {0, NULL, 0, NULL, NULL}
+ };
srna = RNA_def_struct(brna, "ToolSettings", NULL);
@@ -1861,6 +2158,22 @@ static void rna_def_tool_settings(BlenderRNA *brna)
RNA_def_property_ui_icon(prop, ICON_PROP_OFF, 1);
RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL); /* header redraw */
+ prop = RNA_def_property(srna, "use_proportional_action", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "proportional_action", 0);
+ RNA_def_property_ui_text(prop, "Proportional Editing Actions", "Proportional editing in action editor");
+ RNA_def_property_ui_icon(prop, ICON_PROP_OFF, 1);
+ RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL); /* header redraw */
+
+ prop = RNA_def_property(srna, "use_proportional_fcurve", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "proportional_fcurve", 0);
+ RNA_def_property_ui_text(prop, "Proportional Editing FCurves", "Proportional editing in FCurve editor");
+ RNA_def_property_ui_icon(prop, ICON_PROP_OFF, 1);
+ RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL); /* header redraw */
+
+ prop = RNA_def_property(srna, "lock_markers", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "lock_markers", 0);
+ RNA_def_property_ui_text(prop, "Lock Markers", "Prevent marker editing");
+
prop = RNA_def_property(srna, "proportional_edit_falloff", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "prop_mode");
RNA_def_property_enum_items(prop, proportional_falloff_items);
@@ -1902,6 +2215,13 @@ static void rna_def_tool_settings(BlenderRNA *brna)
RNA_def_property_ui_icon(prop, ICON_SNAP_NORMAL, 0);
RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL); /* header redraw */
+ prop = RNA_def_property(srna, "use_snap_grid_absolute", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "snap_flag", SCE_SNAP_ABS_GRID);
+ RNA_def_property_ui_text(prop, "Absolute Grid Snap",
+ "Absolute grid alignment while translating (based on the pivot center)");
+ RNA_def_property_ui_icon(prop, ICON_SNAP_GRID, 0);
+ RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL); /* header redraw */
+
prop = RNA_def_property(srna, "snap_element", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "snap_mode");
RNA_def_property_enum_items(prop, snap_element_items);
@@ -1954,6 +2274,13 @@ static void rna_def_tool_settings(BlenderRNA *brna)
"Allow drawing multiple strokes at a time with Grease Pencil");
RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL); /* xxx: need toolbar to be redrawn... */
+ prop = RNA_def_property(srna, "grease_pencil_source", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_bitflag_sdna(prop, NULL, "gpencil_src");
+ RNA_def_property_enum_items(prop, gpencil_source_3d_items);
+ RNA_def_property_ui_text(prop, "Grease Pencil Source",
+ "Datablock where active Grease Pencil data is found from");
+ RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, NULL);
+
/* Auto Keying */
prop = RNA_def_property(srna, "use_keyframe_insert_auto", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "autokey_mode", AUTOKEY_ON);
@@ -2034,7 +2361,8 @@ static void rna_def_tool_settings(BlenderRNA *brna)
prop = RNA_def_property(srna, "use_etch_autoname", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "skgen_retarget_options", SK_RETARGET_AUTONAME);
- RNA_def_property_ui_text(prop, "Autoname Bones", "Automatically generate values to replace &N and &S suffix placeholders in template names");
+ RNA_def_property_ui_text(prop, "Autoname Bones",
+ "Automatically generate values to replace &N and &S suffix placeholders in template names");
prop = RNA_def_property(srna, "etch_number", PROP_STRING, PROP_NONE);
RNA_def_property_string_sdna(prop, NULL, "skgen_num_string");
@@ -2222,7 +2550,7 @@ static void rna_def_statvis(BlenderRNA *brna)
RNA_def_property_float_sdna(prop, NULL, "overhang_max");
RNA_def_property_float_default(prop, 0.5f);
RNA_def_property_range(prop, 0.0f, DEG2RADF(180.0f));
- RNA_def_property_ui_range(prop, 0.0f, DEG2RADF(180.0f), 0.001, 3);
+ RNA_def_property_ui_range(prop, 0.0f, DEG2RADF(180.0f), 10, 3);
RNA_def_property_ui_text(prop, "Overhang Max", "Maximum angle to display");
RNA_def_property_update(prop, 0, "rna_EditMesh_update");
@@ -2261,7 +2589,7 @@ static void rna_def_statvis(BlenderRNA *brna)
RNA_def_property_float_sdna(prop, NULL, "distort_min");
RNA_def_property_float_default(prop, 0.5f);
RNA_def_property_range(prop, 0.0f, DEG2RADF(180.0f));
- RNA_def_property_ui_range(prop, 0.0f, DEG2RADF(180.0f), 0.001, 3);
+ RNA_def_property_ui_range(prop, 0.0f, DEG2RADF(180.0f), 10, 3);
RNA_def_property_ui_text(prop, "Distort Min", "Minimum angle to display");
RNA_def_property_update(prop, 0, "rna_EditMesh_update");
@@ -2269,7 +2597,7 @@ static void rna_def_statvis(BlenderRNA *brna)
RNA_def_property_float_sdna(prop, NULL, "distort_max");
RNA_def_property_float_default(prop, 0.5f);
RNA_def_property_range(prop, 0.0f, DEG2RADF(180.0f));
- RNA_def_property_ui_range(prop, 0.0f, DEG2RADF(180.0f), 0.001, 3);
+ RNA_def_property_ui_range(prop, 0.0f, DEG2RADF(180.0f), 10, 3);
RNA_def_property_ui_text(prop, "Distort Max", "Maximum angle to display");
RNA_def_property_update(prop, 0, "rna_EditMesh_update");
@@ -2278,7 +2606,7 @@ static void rna_def_statvis(BlenderRNA *brna)
RNA_def_property_float_sdna(prop, NULL, "sharp_min");
RNA_def_property_float_default(prop, 0.5f);
RNA_def_property_range(prop, -DEG2RADF(180.0f), DEG2RADF(180.0f));
- RNA_def_property_ui_range(prop, -DEG2RADF(180.0f), DEG2RADF(180.0f), 0.001, 3);
+ RNA_def_property_ui_range(prop, -DEG2RADF(180.0f), DEG2RADF(180.0f), 10, 3);
RNA_def_property_ui_text(prop, "Distort Min", "Minimum angle to display");
RNA_def_property_update(prop, 0, "rna_EditMesh_update");
@@ -2286,7 +2614,7 @@ static void rna_def_statvis(BlenderRNA *brna)
RNA_def_property_float_sdna(prop, NULL, "sharp_max");
RNA_def_property_float_default(prop, 0.5f);
RNA_def_property_range(prop, -DEG2RADF(180.0f), DEG2RADF(180.0f));
- RNA_def_property_ui_range(prop, -DEG2RADF(180.0f), DEG2RADF(180.0f), 0.001, 3);
+ RNA_def_property_ui_range(prop, -DEG2RADF(180.0f), DEG2RADF(180.0f), 10, 3);
RNA_def_property_ui_text(prop, "Distort Max", "Maximum angle to display");
RNA_def_property_update(prop, 0, "rna_EditMesh_update");
}
@@ -2761,7 +3089,7 @@ static void rna_def_freestyle_linesets(BlenderRNA *brna, PropertyRNA *cprop)
func = RNA_def_function(srna, "new", "rna_FreestyleSettings_lineset_add");
RNA_def_function_ui_description(func, "Add a line set to scene render layer Freestyle settings");
- RNA_def_function_flag(func, FUNC_USE_SELF_ID);
+ RNA_def_function_flag(func, FUNC_USE_MAIN | FUNC_USE_SELF_ID);
parm = RNA_def_string(func, "name", "LineSet", 0, "", "New name for the line set (not unique)");
RNA_def_property_flag(parm, PROP_REQUIRED);
parm = RNA_def_pointer(func, "lineset", "FreestyleLineSet", "", "Newly created line set");
@@ -2922,12 +3250,14 @@ static void rna_def_freestyle_settings(BlenderRNA *brna)
prop = RNA_def_property(srna, "face_mark_condition", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_bitflag_sdna(prop, NULL, "flags");
RNA_def_property_enum_items(prop, face_mark_condition_items);
- RNA_def_property_ui_text(prop, "Face Mark Condition", "Specify a feature edge selection condition based on face marks");
+ RNA_def_property_ui_text(prop, "Face Mark Condition",
+ "Specify a feature edge selection condition based on face marks");
RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_Scene_freestyle_update");
prop = RNA_def_property(srna, "select_silhouette", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "edge_types", FREESTYLE_FE_SILHOUETTE);
- RNA_def_property_ui_text(prop, "Silhouette", "Select silhouettes (edges at the boundary of visible and hidden faces)");
+ RNA_def_property_ui_text(prop, "Silhouette",
+ "Select silhouettes (edges at the boundary of visible and hidden faces)");
RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_Scene_freestyle_update");
prop = RNA_def_property(srna, "select_border", PROP_BOOLEAN, PROP_NONE);
@@ -2937,12 +3267,14 @@ static void rna_def_freestyle_settings(BlenderRNA *brna)
prop = RNA_def_property(srna, "select_crease", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "edge_types", FREESTYLE_FE_CREASE);
- RNA_def_property_ui_text(prop, "Crease", "Select crease edges (those between two faces making an angle smaller than the Crease Angle)");
+ RNA_def_property_ui_text(prop, "Crease",
+ "Select crease edges (those between two faces making an angle smaller than the Crease Angle)");
RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_Scene_freestyle_update");
prop = RNA_def_property(srna, "select_ridge_valley", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "edge_types", FREESTYLE_FE_RIDGE_VALLEY);
- RNA_def_property_ui_text(prop, "Ridge & Valley", "Select ridges and valleys (boundary lines between convex and concave areas of surface)");
+ RNA_def_property_ui_text(prop, "Ridge & Valley",
+ "Select ridges and valleys (boundary lines between convex and concave areas of surface)");
RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_Scene_freestyle_update");
prop = RNA_def_property(srna, "select_suggestive_contour", PROP_BOOLEAN, PROP_NONE);
@@ -2962,7 +3294,8 @@ static void rna_def_freestyle_settings(BlenderRNA *brna)
prop = RNA_def_property(srna, "select_external_contour", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "edge_types", FREESTYLE_FE_EXTERNAL_CONTOUR);
- RNA_def_property_ui_text(prop, "External Contour", "Select external contours (outer silhouettes of occluding and occluded objects)");
+ RNA_def_property_ui_text(prop, "External Contour",
+ "Select external contours (outer silhouettes of occluding and occluded objects)");
RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_Scene_freestyle_update");
prop = RNA_def_property(srna, "select_edge_mark", PROP_BOOLEAN, PROP_NONE);
@@ -3109,6 +3442,12 @@ static void rna_def_freestyle_settings(BlenderRNA *brna)
"Enable advanced edge detection options (sphere radius and Kr derivative epsilon)");
RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_Scene_freestyle_update");
+ prop = RNA_def_property(srna, "use_view_map_cache", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flags", FREESTYLE_VIEW_MAP_CACHE);
+ RNA_def_property_ui_text(prop, "View Map Cache",
+ "Keep the computed view map and avoid re-calculating it if mesh geometry is unchanged");
+ RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_Scene_use_view_map_cache_update");
+
prop = RNA_def_property(srna, "sphere_radius", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "sphere_radius");
RNA_def_property_range(prop, 0.0, 1000.0);
@@ -3147,36 +3486,42 @@ static void rna_def_scene_game_recast_data(BlenderRNA *brna)
prop = RNA_def_property(srna, "cell_size", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "cellsize");
RNA_def_property_ui_range(prop, 0.1, 1, 1, 2);
+ RNA_def_property_float_default(prop, 0.3f);
RNA_def_property_ui_text(prop, "Cell Size", "Rasterized cell size");
RNA_def_property_update(prop, NC_SCENE, NULL);
prop = RNA_def_property(srna, "cell_height", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "cellheight");
RNA_def_property_ui_range(prop, 0.1, 1, 1, 2);
+ RNA_def_property_float_default(prop, 0.2f);
RNA_def_property_ui_text(prop, "Cell Height", "Rasterized cell height");
RNA_def_property_update(prop, NC_SCENE, NULL);
prop = RNA_def_property(srna, "agent_height", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "agentheight");
RNA_def_property_ui_range(prop, 0.1, 5, 1, 2);
+ RNA_def_property_float_default(prop, 2.0f);
RNA_def_property_ui_text(prop, "Agent Height", "Minimum height where the agent can still walk");
RNA_def_property_update(prop, NC_SCENE, NULL);
prop = RNA_def_property(srna, "agent_radius", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "agentradius");
RNA_def_property_ui_range(prop, 0.1, 5, 1, 2);
+ RNA_def_property_float_default(prop, 0.6f);
RNA_def_property_ui_text(prop, "Agent Radius", "Radius of the agent");
RNA_def_property_update(prop, NC_SCENE, NULL);
prop = RNA_def_property(srna, "climb_max", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "agentmaxclimb");
RNA_def_property_ui_range(prop, 0.1, 5, 1, 2);
+ RNA_def_property_float_default(prop, 0.9f);
RNA_def_property_ui_text(prop, "Max Climb", "Maximum height between grid cells the agent can climb");
RNA_def_property_update(prop, NC_SCENE, NULL);
prop = RNA_def_property(srna, "slope_max", PROP_FLOAT, PROP_ANGLE);
RNA_def_property_float_sdna(prop, NULL, "agentmaxslope");
- RNA_def_property_range(prop, 0, M_PI / 2);
+ RNA_def_property_range(prop, 0, M_PI_2);
+ RNA_def_property_float_default(prop, M_PI_4);
RNA_def_property_ui_text(prop, "Max Slope", "Maximum walkable slope angle");
RNA_def_property_update(prop, NC_SCENE, NULL);
@@ -3184,42 +3529,49 @@ static void rna_def_scene_game_recast_data(BlenderRNA *brna)
prop = RNA_def_property(srna, "region_min_size", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "regionminsize");
RNA_def_property_ui_range(prop, 0, 150, 1, 2);
+ RNA_def_property_float_default(prop, 8.0f);
RNA_def_property_ui_text(prop, "Min Region Size", "Minimum regions size (smaller regions will be deleted)");
RNA_def_property_update(prop, NC_SCENE, NULL);
prop = RNA_def_property(srna, "region_merge_size", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "regionmergesize");
RNA_def_property_ui_range(prop, 0, 150, 1, 2);
+ RNA_def_property_float_default(prop, 20.0f);
RNA_def_property_ui_text(prop, "Merged Region Size", "Minimum regions size (smaller regions will be merged)");
RNA_def_property_update(prop, NC_SCENE, NULL);
prop = RNA_def_property(srna, "edge_max_len", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "edgemaxlen");
RNA_def_property_ui_range(prop, 0, 50, 1, 2);
+ RNA_def_property_float_default(prop, 12.0f);
RNA_def_property_ui_text(prop, "Max Edge Length", "Maximum contour edge length");
RNA_def_property_update(prop, NC_SCENE, NULL);
prop = RNA_def_property(srna, "edge_max_error", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "edgemaxerror");
RNA_def_property_ui_range(prop, 0.1, 3.0, 1, 2);
+ RNA_def_property_float_default(prop, 1.3f);
RNA_def_property_ui_text(prop, "Max Edge Error", "Maximum distance error from contour to cells");
RNA_def_property_update(prop, NC_SCENE, NULL);
prop = RNA_def_property(srna, "verts_per_poly", PROP_INT, PROP_NONE);
RNA_def_property_int_sdna(prop, NULL, "vertsperpoly");
RNA_def_property_ui_range(prop, 3, 12, 1, -1);
+ RNA_def_property_int_default(prop, 6);
RNA_def_property_ui_text(prop, "Verts Per Poly", "Max number of vertices per polygon");
RNA_def_property_update(prop, NC_SCENE, NULL);
prop = RNA_def_property(srna, "sample_dist", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "detailsampledist");
RNA_def_property_ui_range(prop, 0.0, 16.0, 1, 2);
+ RNA_def_property_float_default(prop, 6.0f);
RNA_def_property_ui_text(prop, "Sample Distance", "Detail mesh sample spacing");
RNA_def_property_update(prop, NC_SCENE, NULL);
prop = RNA_def_property(srna, "sample_max_error", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "detailsamplemaxerror");
RNA_def_property_ui_range(prop, 0.0, 16.0, 1, 2);
+ RNA_def_property_float_default(prop, 1.0f);
RNA_def_property_ui_text(prop, "Max Sample Error", "Detail mesh simplification max sample error");
RNA_def_property_update(prop, NC_SCENE, NULL);
}
@@ -3431,12 +3783,14 @@ static void rna_def_scene_game_data(BlenderRNA *brna)
prop = RNA_def_property(srna, "resolution_x", PROP_INT, PROP_PIXEL);
RNA_def_property_int_sdna(prop, NULL, "xplay");
RNA_def_property_range(prop, 4, 10000);
+ RNA_def_property_int_default(prop, 640);
RNA_def_property_ui_text(prop, "Resolution X", "Number of horizontal pixels in the screen");
RNA_def_property_update(prop, NC_SCENE, NULL);
prop = RNA_def_property(srna, "resolution_y", PROP_INT, PROP_PIXEL);
RNA_def_property_int_sdna(prop, NULL, "yplay");
RNA_def_property_range(prop, 4, 10000);
+ RNA_def_property_int_default(prop, 480);
RNA_def_property_ui_text(prop, "Resolution Y", "Number of vertical pixels in the screen");
RNA_def_property_update(prop, NC_SCENE, NULL);
@@ -3453,12 +3807,14 @@ static void rna_def_scene_game_data(BlenderRNA *brna)
prop = RNA_def_property(srna, "depth", PROP_INT, PROP_UNSIGNED);
RNA_def_property_int_sdna(prop, NULL, "depth");
RNA_def_property_range(prop, 8, 32);
+ RNA_def_property_int_default(prop, 32);
RNA_def_property_ui_text(prop, "Bits", "Display bit depth of full screen display");
RNA_def_property_update(prop, NC_SCENE, NULL);
prop = RNA_def_property(srna, "exit_key", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "exitkey");
RNA_def_property_enum_items(prop, event_type_items);
+ RNA_def_property_enum_default(prop, ESCKEY);
RNA_def_property_enum_funcs(prop, NULL, "rna_GameSettings_exit_key_set", NULL);
RNA_def_property_ui_text(prop, "Exit Key", "The key that exits the Game Engine");
RNA_def_property_update(prop, NC_SCENE, NULL);
@@ -3473,6 +3829,7 @@ static void rna_def_scene_game_data(BlenderRNA *brna)
prop = RNA_def_property(srna, "frequency", PROP_INT, PROP_NONE);
RNA_def_property_int_sdna(prop, NULL, "freqplay");
RNA_def_property_range(prop, 4, 2000);
+ RNA_def_property_int_default(prop, 60);
RNA_def_property_ui_text(prop, "Freq", "Display clock frequency of fullscreen display");
RNA_def_property_update(prop, NC_SCENE, NULL);
@@ -3510,12 +3867,14 @@ static void rna_def_scene_game_data(BlenderRNA *brna)
prop = RNA_def_property(srna, "stereo_mode", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "stereomode");
RNA_def_property_enum_items(prop, stereo_modes_items);
+ RNA_def_property_enum_default(prop, STEREO_ANAGLYPH);
RNA_def_property_ui_text(prop, "Stereo Mode", "Stereographic techniques");
RNA_def_property_update(prop, NC_SCENE, NULL);
prop = RNA_def_property(srna, "stereo_eye_separation", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "eyeseparation");
RNA_def_property_range(prop, 0.01, 5.0);
+ RNA_def_property_float_default(prop, 0.1f);
RNA_def_property_ui_text(prop, "Eye Separation",
"Set the distance between the eyes - the camera focal distance/30 should be fine");
RNA_def_property_update(prop, NC_SCENE, NULL);
@@ -3530,18 +3889,21 @@ static void rna_def_scene_game_data(BlenderRNA *brna)
prop = RNA_def_property(srna, "dome_tessellation", PROP_INT, PROP_NONE);
RNA_def_property_int_sdna(prop, NULL, "dome.res");
RNA_def_property_ui_range(prop, 1, 8, 1, 1);
+ RNA_def_property_int_default(prop, 4);
RNA_def_property_ui_text(prop, "Tessellation", "Tessellation level - check the generated mesh in wireframe mode");
RNA_def_property_update(prop, NC_SCENE, NULL);
prop = RNA_def_property(srna, "dome_buffer_resolution", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "dome.resbuf");
RNA_def_property_ui_range(prop, 0.1, 1.0, 0.1, 2);
+ RNA_def_property_float_default(prop, 1.0f);
RNA_def_property_ui_text(prop, "Buffer Resolution", "Buffer Resolution - decrease it to increase speed");
RNA_def_property_update(prop, NC_SCENE, NULL);
prop = RNA_def_property(srna, "dome_angle", PROP_INT, PROP_NONE);
RNA_def_property_int_sdna(prop, NULL, "dome.angle");
RNA_def_property_ui_range(prop, 90, 250, 1, 1);
+ RNA_def_property_int_default(prop, 180);
RNA_def_property_ui_text(prop, "Angle", "Field of View of the Dome - it only works in mode Fisheye and Truncated");
RNA_def_property_update(prop, NC_SCENE, NULL);
@@ -3562,6 +3924,7 @@ static void rna_def_scene_game_data(BlenderRNA *brna)
prop = RNA_def_property(srna, "physics_engine", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "physicsEngine");
RNA_def_property_enum_items(prop, physics_engine_items);
+ RNA_def_property_enum_default(prop, WOPHY_BULLET);
RNA_def_property_ui_text(prop, "Physics Engine", "Physics engine used for physics simulation in the game engine");
RNA_def_property_update(prop, NC_SCENE, NULL);
@@ -3569,6 +3932,7 @@ static void rna_def_scene_game_data(BlenderRNA *brna)
RNA_def_property_float_sdna(prop, NULL, "gravity");
RNA_def_property_ui_range(prop, 0.0, 25.0, 1, 2);
RNA_def_property_range(prop, 0.0, 10000.0);
+ RNA_def_property_float_default(prop, 9.8f);
RNA_def_property_ui_text(prop, "Physics Gravity",
"Gravitational constant used for physics simulation in the game engine");
RNA_def_property_update(prop, NC_SCENE, NULL);
@@ -3576,6 +3940,7 @@ static void rna_def_scene_game_data(BlenderRNA *brna)
prop = RNA_def_property(srna, "occlusion_culling_resolution", PROP_INT, PROP_PIXEL);
RNA_def_property_int_sdna(prop, NULL, "occlusionRes");
RNA_def_property_range(prop, 128.0, 1024.0);
+ RNA_def_property_int_default(prop, 128);
RNA_def_property_ui_text(prop, "Occlusion Resolution",
"Size of the occlusion buffer, use higher value for better precision (slower)");
RNA_def_property_update(prop, NC_SCENE, NULL);
@@ -3584,6 +3949,7 @@ static void rna_def_scene_game_data(BlenderRNA *brna)
RNA_def_property_int_sdna(prop, NULL, "ticrate");
RNA_def_property_ui_range(prop, 1, 60, 1, 1);
RNA_def_property_range(prop, 1, 10000);
+ RNA_def_property_int_default(prop, 60);
RNA_def_property_ui_text(prop, "Frames Per Second",
"Nominal number of game frames per second "
"(physics fixed timestep = 1/fps, independently of actual frame rate)");
@@ -3591,8 +3957,9 @@ static void rna_def_scene_game_data(BlenderRNA *brna)
prop = RNA_def_property(srna, "logic_step_max", PROP_INT, PROP_NONE);
RNA_def_property_int_sdna(prop, NULL, "maxlogicstep");
- RNA_def_property_ui_range(prop, 1, 5, 1, 1);
- RNA_def_property_range(prop, 1, 5);
+ RNA_def_property_range(prop, 1, 10000);
+ RNA_def_property_ui_range(prop, 1, 50, 1, 1);
+ RNA_def_property_int_default(prop, 5);
RNA_def_property_ui_text(prop, "Max Logic Steps",
"Maximum number of logic frame per game frame if graphics slows down the game, "
"higher value allows better synchronization with physics");
@@ -3600,8 +3967,9 @@ static void rna_def_scene_game_data(BlenderRNA *brna)
prop = RNA_def_property(srna, "physics_step_max", PROP_INT, PROP_NONE);
RNA_def_property_int_sdna(prop, NULL, "maxphystep");
- RNA_def_property_ui_range(prop, 1, 5, 1, 1);
- RNA_def_property_range(prop, 1, 5);
+ RNA_def_property_range(prop, 1, 10000);
+ RNA_def_property_ui_range(prop, 1, 50, 1, 1);
+ RNA_def_property_int_default(prop, 5);
RNA_def_property_ui_text(prop, "Max Physics Steps",
"Maximum number of physics step per game frame if graphics slows down the game, "
"higher value allows physics to keep up with realtime");
@@ -3611,6 +3979,7 @@ static void rna_def_scene_game_data(BlenderRNA *brna)
RNA_def_property_int_sdna(prop, NULL, "physubstep");
RNA_def_property_range(prop, 1, 50);
RNA_def_property_ui_range(prop, 1, 5, 1, 1);
+ RNA_def_property_int_default(prop, 1);
RNA_def_property_ui_text(prop, "Physics Sub Steps",
"Number of simulation substep per physic timestep, "
"higher value give better physics precision");
@@ -3620,6 +3989,7 @@ static void rna_def_scene_game_data(BlenderRNA *brna)
RNA_def_property_float_sdna(prop, NULL, "lineardeactthreshold");
RNA_def_property_ui_range(prop, 0.001, 10000.0, 2, 3);
RNA_def_property_range(prop, 0.001, 10000.0);
+ RNA_def_property_float_default(prop, 0.8f);
RNA_def_property_ui_text(prop, "Deactivation Linear Threshold",
"Linear velocity that an object must be below before the deactivation timer can start");
RNA_def_property_update(prop, NC_SCENE, NULL);
@@ -3628,6 +3998,7 @@ static void rna_def_scene_game_data(BlenderRNA *brna)
RNA_def_property_float_sdna(prop, NULL, "angulardeactthreshold");
RNA_def_property_ui_range(prop, 0.001, 10000.0, 2, 3);
RNA_def_property_range(prop, 0.001, 10000.0);
+ RNA_def_property_float_default(prop, 1.0f);
RNA_def_property_ui_text(prop, "Deactivation Angular Threshold",
"Angular velocity that an object must be below before the deactivation timer can start");
RNA_def_property_update(prop, NC_SCENE, NULL);
@@ -3771,6 +4142,7 @@ static void rna_def_scene_game_data(BlenderRNA *brna)
prop = RNA_def_property(srna, "level_height", PROP_FLOAT, PROP_ACCELERATION);
RNA_def_property_float_sdna(prop, NULL, "levelHeight");
RNA_def_property_range(prop, 0.0f, 200.0f);
+ RNA_def_property_float_default(prop, 2.0f);
RNA_def_property_ui_text(prop, "Level height",
"Max difference in heights of obstacles to enable their interaction");
RNA_def_property_update(prop, NC_SCENE, NULL);
@@ -3788,8 +4160,150 @@ static void rna_def_scene_game_data(BlenderRNA *brna)
/* Nestled Data */
rna_def_scene_game_recast_data(brna);
+
+ /* LoD */
+ prop = RNA_def_property(srna, "use_scene_hysteresis", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "lodflag", SCE_LOD_USE_HYST);
+ RNA_def_property_ui_text(prop, "Hysteresis", "Use LoD Hysteresis setting for the scene");
+ RNA_def_property_update(prop, NC_SCENE, NULL);
+
+ prop = RNA_def_property(srna, "scene_hysteresis_percentage", PROP_INT, PROP_PERCENTAGE);
+ RNA_def_property_int_sdna(prop, NULL, "scehysteresis");
+ RNA_def_property_range(prop, 0, 100);
+ RNA_def_property_ui_range(prop, 0, 100, 10, 1);
+ RNA_def_property_int_default(prop, 10);
+ RNA_def_property_ui_text(prop, "Hysteresis %",
+ "Minimum distance change required to transition to the previous level of detail");
+ RNA_def_property_update(prop, NC_SCENE, NULL);
+}
+
+static void rna_def_gpu_dof_fx(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ srna = RNA_def_struct(brna, "GPUDOFSettings", NULL);
+ RNA_def_struct_ui_text(srna, "GPU DOF", "Settings for GPU based depth of field");
+ RNA_def_struct_ui_icon(srna, ICON_RENDERLAYERS);
+ RNA_def_struct_path_func(srna, "rna_GPUDOF_path");
+
+ prop = RNA_def_property(srna, "focus_distance", PROP_FLOAT, PROP_DISTANCE);
+ RNA_def_property_ui_text(prop, "Focus distance", "Viewport depth of field focus distance");
+ RNA_def_property_range(prop, 0.0f, FLT_MAX);
+ RNA_def_property_ui_range(prop, 0.0f, 5000.0f, 1, 2);
+ RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
+
+ prop = RNA_def_property(srna, "focal_length", PROP_FLOAT, PROP_DISTANCE_CAMERA);
+ RNA_def_property_ui_text(prop, "Focal Length", "Focal length for dof effect");
+ RNA_def_property_range(prop, 1.0f, FLT_MAX);
+ RNA_def_property_ui_range(prop, 1.0f, 5000.0f, 1, 2);
+ RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
+
+ prop = RNA_def_property(srna, "sensor", PROP_FLOAT, PROP_DISTANCE_CAMERA);
+ RNA_def_property_ui_text(prop, "Sensor", "Size of sensor");
+ RNA_def_property_range(prop, 1.0f, FLT_MAX);
+ RNA_def_property_ui_range(prop, 1.0f, 5000.0f, 1, 2);
+ RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
+
+ prop = RNA_def_property(srna, "fstop", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_ui_text(prop, "F-stop", "F-stop for dof effect");
+ RNA_def_property_range(prop, 0.0f, FLT_MAX);
+ RNA_def_property_ui_range(prop, 0.1f, 128.0f, 10, 1);
+ RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
+
+ prop = RNA_def_property(srna, "blades", PROP_INT, PROP_NONE);
+ RNA_def_property_int_sdna(prop, NULL, "num_blades");
+ RNA_def_property_ui_text(prop, "Blades", "Blades for dof effect");
+ RNA_def_property_range(prop, 0, 16);
+ RNA_def_property_int_funcs(prop, NULL, "rna_GPUDOFSettings_blades_set", NULL);
+ RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
+
+ prop = RNA_def_property(srna, "use_high_quality", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "high_quality", 1);
+ RNA_def_property_ui_text(prop, "High Quality", "Use high quality depth of field");
+ RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
+
+ prop = RNA_def_property(srna, "is_hq_supported", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_funcs(prop, "rna_gpu_is_hq_supported_get", NULL);
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_property_ui_text(prop, "High Quality", "Use high quality depth of field");
+ RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
}
+static void rna_def_gpu_ssao_fx(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ srna = RNA_def_struct(brna, "GPUSSAOSettings", NULL);
+ RNA_def_struct_ui_text(srna, "GPU SSAO", "Settings for GPU based screen space ambient occlusion");
+ RNA_def_struct_ui_icon(srna, ICON_RENDERLAYERS);
+
+ prop = RNA_def_property(srna, "factor", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_ui_text(prop, "Strength", "Strength of the SSAO effect");
+ RNA_def_property_range(prop, 0.0f, 250.0f);
+ RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
+
+ prop = RNA_def_property(srna, "distance_max", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_ui_text(prop, "Distance", "Distance of object that contribute to the SSAO effect");
+ RNA_def_property_range(prop, 0.0f, 100000.0f);
+ RNA_def_property_ui_range(prop, 0.0f, 100.0f, 1, 3);
+ RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
+
+ prop = RNA_def_property(srna, "attenuation", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_ui_text(prop, "Attenuation", "Attenuation constant");
+ RNA_def_property_range(prop, 1.0f, 100000.0f);
+ RNA_def_property_ui_range(prop, 1.0f, 100.0f, 1, 3);
+ RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
+
+ prop = RNA_def_property(srna, "samples", PROP_INT, PROP_NONE);
+ RNA_def_property_ui_text(prop, "Samples", "Number of samples");
+ RNA_def_property_range(prop, 1, 500);
+ RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
+
+ prop = RNA_def_property(srna, "color", PROP_FLOAT, PROP_COLOR_GAMMA);
+ RNA_def_property_ui_text(prop, "Color", "Color for screen space ambient occlusion effect");
+ RNA_def_property_range(prop, 0.0f, 1.0f);
+ RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
+}
+
+
+static void rna_def_gpu_fx(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ rna_def_gpu_ssao_fx(brna);
+ rna_def_gpu_dof_fx(brna);
+
+ srna = RNA_def_struct(brna, "GPUFXSettings", NULL);
+ RNA_def_struct_ui_text(srna, "GPU FX Settings", "Settings for GPU based compositing");
+ RNA_def_struct_ui_icon(srna, ICON_RENDERLAYERS);
+
+ prop = RNA_def_property(srna, "dof", PROP_POINTER, PROP_NONE);
+ RNA_def_property_flag(prop, PROP_NEVER_NULL);
+ RNA_def_property_struct_type(prop, "GPUDOFSettings");
+ RNA_def_property_ui_text(prop, "Depth Of Field settings", "");
+
+ prop = RNA_def_property(srna, "use_dof", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "fx_flag", GPU_FX_FLAG_DOF);
+ RNA_def_property_ui_text(prop, "Depth Of Field",
+ "Use depth of field on viewport using the values from active camera");
+ RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, "rna_GPUFXSettings_fx_update");
+
+
+ prop = RNA_def_property(srna, "ssao", PROP_POINTER, PROP_NONE);
+ RNA_def_property_flag(prop, PROP_NEVER_NULL);
+ RNA_def_property_struct_type(prop, "GPUSSAOSettings");
+ RNA_def_property_ui_text(prop, "Screen Space Ambient Occlusion settings", "");
+
+ prop = RNA_def_property(srna, "use_ssao", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "fx_flag", GPU_FX_FLAG_SSAO);
+ RNA_def_property_ui_text(prop, "SSAO", "Use screen space ambient occlusion of field on viewport");
+ RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, "rna_GPUFXSettings_fx_update");
+}
+
+
static void rna_def_scene_render_layer(BlenderRNA *brna)
{
StructRNA *srna;
@@ -3858,6 +4372,138 @@ static void rna_def_render_layers(BlenderRNA *brna, PropertyRNA *cprop)
RNA_def_property_clear_flag(parm, PROP_THICK_WRAP);
}
+/* Render Views - MultiView */
+static void rna_def_scene_render_view(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ srna = RNA_def_struct(brna, "SceneRenderView", NULL);
+ RNA_def_struct_ui_text(srna, "Scene Render View", "Render viewpoint for 3D stereo and multiview rendering");
+ RNA_def_struct_ui_icon(srna, ICON_RESTRICT_RENDER_OFF);
+ RNA_def_struct_path_func(srna, "rna_SceneRenderView_path");
+
+ prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE);
+ RNA_def_property_string_funcs(prop, NULL, NULL, "rna_SceneRenderView_name_set");
+ RNA_def_property_ui_text(prop, "Name", "Render view name");
+ RNA_def_struct_name_property(srna, prop);
+ RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
+
+ prop = RNA_def_property(srna, "file_suffix", PROP_STRING, PROP_NONE);
+ RNA_def_property_string_sdna(prop, NULL, "suffix");
+ RNA_def_property_ui_text(prop, "File Suffix", "Suffix added to the render images for this view");
+ RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
+
+ prop = RNA_def_property(srna, "camera_suffix", PROP_STRING, PROP_NONE);
+ RNA_def_property_string_sdna(prop, NULL, "suffix");
+ RNA_def_property_ui_text(prop, "Camera Suffix",
+ "Suffix to identify the cameras to use, and added to the render images for this view");
+ RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
+
+ prop = RNA_def_property(srna, "use", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_negative_sdna(prop, NULL, "viewflag", SCE_VIEW_DISABLE);
+ RNA_def_property_ui_text(prop, "Enabled", "Disable or enable the render view");
+ RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
+}
+
+static void rna_def_render_views(BlenderRNA *brna, PropertyRNA *cprop)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ FunctionRNA *func;
+ PropertyRNA *parm;
+
+ RNA_def_property_srna(cprop, "RenderViews");
+ srna = RNA_def_struct(brna, "RenderViews", NULL);
+ RNA_def_struct_sdna(srna, "RenderData");
+ RNA_def_struct_ui_text(srna, "Render Views", "Collection of render views");
+
+ prop = RNA_def_property(srna, "active_index", PROP_INT, PROP_UNSIGNED);
+ RNA_def_property_int_sdna(prop, NULL, "actview");
+ RNA_def_property_int_funcs(prop, "rna_RenderSettings_active_view_index_get",
+ "rna_RenderSettings_active_view_index_set",
+ "rna_RenderSettings_active_view_index_range");
+ RNA_def_property_ui_text(prop, "Active View Index", "Active index in render view array");
+ RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
+
+ prop = RNA_def_property(srna, "active", PROP_POINTER, PROP_NONE);
+ RNA_def_property_struct_type(prop, "SceneRenderView");
+ RNA_def_property_pointer_funcs(prop, "rna_RenderSettings_active_view_get",
+ "rna_RenderSettings_active_view_set", NULL, NULL);
+ RNA_def_property_flag(prop, PROP_EDITABLE | PROP_NEVER_NULL);
+ RNA_def_property_ui_text(prop, "Active Render View", "Active Render View");
+ RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
+
+ func = RNA_def_function(srna, "new", "rna_RenderView_new");
+ RNA_def_function_ui_description(func, "Add a render view to scene");
+ RNA_def_function_flag(func, FUNC_USE_SELF_ID);
+ parm = RNA_def_string(func, "name", "RenderView", 0, "", "New name for the marker (not unique)");
+ RNA_def_property_flag(parm, PROP_REQUIRED);
+ parm = RNA_def_pointer(func, "result", "SceneRenderView", "", "Newly created render view");
+ RNA_def_function_return(func, parm);
+
+ func = RNA_def_function(srna, "remove", "rna_RenderView_remove");
+ RNA_def_function_ui_description(func, "Remove a render view");
+ RNA_def_function_flag(func, FUNC_USE_MAIN | FUNC_USE_REPORTS | FUNC_USE_SELF_ID);
+ parm = RNA_def_pointer(func, "view", "SceneRenderView", "", "Render view to remove");
+ RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL | PROP_RNAPTR);
+ RNA_def_property_clear_flag(parm, PROP_THICK_WRAP);
+}
+
+static void rna_def_image_format_stereo3d_format(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ static EnumPropertyItem stereo3d_display_items[] = {
+ {S3D_DISPLAY_ANAGLYPH, "ANAGLYPH", 0, "Anaglyph",
+ "Render views for left and right eyes as two differently filtered colors in a single image "
+ "(anaglyph glasses are required)"},
+ {S3D_DISPLAY_INTERLACE, "INTERLACE", 0, "Interlace",
+ "Render views for left and right eyes interlaced in a single image (3D-ready monitor is required)"},
+ {S3D_DISPLAY_SIDEBYSIDE, "SIDEBYSIDE", 0, "Side-by-Side", "Render views for left and right eyes side-by-side"},
+ {S3D_DISPLAY_TOPBOTTOM, "TOPBOTTOM", 0, "Top-Bottom", "Render views for left and right eyes one above another"},
+ {0, NULL, 0, NULL, NULL}
+ };
+
+ srna = RNA_def_struct(brna, "Stereo3dFormat", NULL);
+ RNA_def_struct_sdna(srna, "Stereo3dFormat");
+ RNA_def_struct_clear_flag(srna, STRUCT_UNDO);
+ RNA_def_struct_ui_text(srna, "Stereo Output", "Settings for stereo output");
+
+ prop = RNA_def_property(srna, "display_mode", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "display_mode");
+ RNA_def_property_enum_items(prop, stereo3d_display_items);
+ RNA_def_property_ui_text(prop, "Stereo Mode", "");
+ RNA_def_property_update(prop, NC_IMAGE | ND_DISPLAY, "rna_Stereo3dFormat_update");
+
+ prop = RNA_def_property(srna, "anaglyph_type", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_items(prop, stereo3d_anaglyph_type_items);
+ RNA_def_property_ui_text(prop, "Anaglyph Type", "");
+ RNA_def_property_update(prop, NC_IMAGE | ND_DISPLAY, "rna_Stereo3dFormat_update");
+
+ prop = RNA_def_property(srna, "interlace_type", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_items(prop, stereo3d_interlace_type_items);
+ RNA_def_property_ui_text(prop, "Interlace Type", "");
+ RNA_def_property_update(prop, NC_IMAGE | ND_DISPLAY, "rna_Stereo3dFormat_update");
+
+ prop = RNA_def_property(srna, "use_interlace_swap", PROP_BOOLEAN, PROP_BOOLEAN);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", S3D_INTERLACE_SWAP);
+ RNA_def_property_ui_text(prop, "Swap Left/Right", "Swap left and right stereo channels");
+ RNA_def_property_update(prop, NC_IMAGE | ND_DISPLAY, "rna_Stereo3dFormat_update");
+
+ prop = RNA_def_property(srna, "use_sidebyside_crosseyed", PROP_BOOLEAN, PROP_BOOLEAN);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", S3D_SIDEBYSIDE_CROSSEYED);
+ RNA_def_property_ui_text(prop, "Cross-Eyed", "Right eye should see left image and vice-versa");
+ RNA_def_property_update(prop, NC_IMAGE | ND_DISPLAY, "rna_Stereo3dFormat_update");
+
+ prop = RNA_def_property(srna, "use_squeezed_frame", PROP_BOOLEAN, PROP_BOOLEAN);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", S3D_SQUEEZED_FRAME);
+ RNA_def_property_ui_text(prop, "Squeezed Frame", "Combine both views in a squeezed image");
+ RNA_def_property_update(prop, NC_IMAGE | ND_DISPLAY, "rna_Stereo3dFormat_update");
+}
+
/* use for render output and image save operator,
* note: there are some cases where the members act differently when this is
* used from a scene, video formats can only be selected for render output
@@ -3877,6 +4523,8 @@ static void rna_def_scene_image_format_data(BlenderRNA *brna)
StructRNA *srna;
PropertyRNA *prop;
+ rna_def_image_format_stereo3d_format(brna);
+
srna = RNA_def_struct(brna, "ImageFormatSettings", NULL);
RNA_def_struct_sdna(srna, "ImageFormatData");
RNA_def_struct_nested(brna, srna, "Scene");
@@ -3942,9 +4590,9 @@ static void rna_def_scene_image_format_data(BlenderRNA *brna)
prop = RNA_def_property(srna, "exr_codec", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "exr_codec");
RNA_def_property_enum_items(prop, exr_codec_items);
+ RNA_def_property_enum_funcs(prop, NULL, NULL, "rna_ImageFormatSettings_exr_codec_itemf");
RNA_def_property_ui_text(prop, "Codec", "Codec settings for OpenEXR");
RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
-
#endif
#ifdef WITH_OPENJPEG
@@ -3996,6 +4644,20 @@ static void rna_def_scene_image_format_data(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "G", "Log conversion gamma");
RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
+ /* multiview */
+ prop = RNA_def_property(srna, "views_format", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "views_format");
+ RNA_def_property_enum_items(prop, views_format_items);
+ RNA_def_property_enum_funcs(prop, NULL, NULL, "rna_ImageFormatSettings_views_format_itemf");
+ RNA_def_property_ui_text(prop, "Views Format", "Format of multiview media");
+ RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
+
+ prop = RNA_def_property(srna, "stereo_3d_format", PROP_POINTER, PROP_NONE);
+ RNA_def_property_pointer_sdna(prop, NULL, "stereo3d_format");
+ RNA_def_property_flag(prop, PROP_NEVER_NULL);
+ RNA_def_property_struct_type(prop, "Stereo3dFormat");
+ RNA_def_property_ui_text(prop, "Stereo 3D Format", "Settings for stereo 3d");
+
/* color management */
prop = RNA_def_property(srna, "view_settings", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "view_settings");
@@ -4166,7 +4828,7 @@ static void rna_def_scene_ffmpeg_settings(BlenderRNA *brna)
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
RNA_def_property_range(prop, 0.0f, 1.0f);
RNA_def_property_ui_text(prop, "Volume", "Audio volume");
- RNA_def_property_translation_context(prop, BLF_I18NCONTEXT_ID_SOUND);
+ RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_SOUND);
RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
#endif
@@ -4398,6 +5060,16 @@ static void rna_def_scene_render_data(BlenderRNA *brna)
"resolution to 480 pixels"},
{0, NULL, 0, NULL, NULL}};
+ static EnumPropertyItem views_format_items[] = {
+ {SCE_VIEWS_FORMAT_STEREO_3D, "STEREO_3D", 0, "Stereo 3D",
+ "Single stereo camera system, adjust the stereo settings in the camera panel"},
+ {SCE_VIEWS_FORMAT_MULTIVIEW, "MULTIVIEW", 0, "Multi-View",
+ "Multi camera system, adjust the cameras individually"},
+ {0, NULL, 0, NULL, NULL}
+ };
+
+
+
rna_def_scene_ffmpeg_settings(brna);
#ifdef WITH_QUICKTIME
rna_def_scene_quicktime_settings(brna);
@@ -4547,7 +5219,7 @@ static void rna_def_scene_render_data(BlenderRNA *brna)
RNA_def_property_enum_sdna(prop, NULL, "alphamode");
RNA_def_property_enum_items(prop, alpha_mode_items);
RNA_def_property_ui_text(prop, "Alpha Mode", "Representation of alpha information in the RGBA pixels");
- RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
+ RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_Scene_glsl_update");
prop = RNA_def_property(srna, "octree_resolution", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "ocres");
@@ -4609,47 +5281,48 @@ static void rna_def_scene_render_data(BlenderRNA *brna)
prop = RNA_def_property(srna, "use_shadows", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "mode", R_SHADOW);
RNA_def_property_ui_text(prop, "Shadows", "Calculate shadows while rendering");
- RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
+ RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_Scene_glsl_update");
prop = RNA_def_property(srna, "use_envmaps", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "mode", R_ENVMAP);
RNA_def_property_ui_text(prop, "Environment Maps", "Calculate environment maps while rendering");
- RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
+ RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_Scene_glsl_update");
prop = RNA_def_property(srna, "use_sss", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "mode", R_SSS);
RNA_def_property_ui_text(prop, "Subsurface Scattering", "Calculate sub-surface scattering in materials rendering");
- RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
+ RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_Scene_glsl_update");
prop = RNA_def_property(srna, "use_raytrace", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "mode", R_RAYTRACE);
RNA_def_property_ui_text(prop, "Raytracing",
"Pre-calculate the raytrace accelerator and render raytracing effects");
- RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
+ RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_Scene_glsl_update");
prop = RNA_def_property(srna, "use_textures", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_negative_sdna(prop, NULL, "scemode", R_NO_TEX);
RNA_def_property_ui_text(prop, "Textures", "Use textures to affect material properties");
- RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
+ RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_Scene_glsl_update");
prop = RNA_def_property(srna, "use_edge_enhance", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "mode", R_EDGE);
RNA_def_property_ui_text(prop, "Edge", "Create a toon outline around the edges of geometry");
- RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
+ RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_Scene_glsl_update");
prop = RNA_def_property(srna, "edge_threshold", PROP_INT, PROP_NONE);
RNA_def_property_int_sdna(prop, NULL, "edgeint");
RNA_def_property_range(prop, 0, 255);
RNA_def_property_ui_text(prop, "Edge Threshold", "Threshold for drawing outlines on geometry edges");
- RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
+ RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_Scene_glsl_update");
prop = RNA_def_property(srna, "edge_color", PROP_FLOAT, PROP_COLOR);
RNA_def_property_float_sdna(prop, NULL, "edgeR");
RNA_def_property_array(prop, 3);
RNA_def_property_ui_text(prop, "Edge Color", "Edge color");
- RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
+ RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_Scene_glsl_update");
prop = RNA_def_property(srna, "use_freestyle", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
RNA_def_property_boolean_sdna(prop, NULL, "mode", R_EDGE_FRS);
RNA_def_property_ui_text(prop, "Edge", "Draw stylized strokes using Freestyle");
RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_Scene_freestyle_update");
@@ -4707,7 +5380,7 @@ static void rna_def_scene_render_data(BlenderRNA *brna)
RNA_def_property_float_sdna(prop, NULL, "border.xmin");
RNA_def_property_range(prop, 0.0f, 1.0f);
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
- RNA_def_property_ui_text(prop, "Border Minimum X", "Minimum X value to for the render border");
+ RNA_def_property_ui_text(prop, "Border Minimum X", "Minimum X value for the render border");
RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
prop = RNA_def_property(srna, "border_min_y", PROP_FLOAT, PROP_NONE);
@@ -4785,7 +5458,7 @@ static void rna_def_scene_render_data(BlenderRNA *brna)
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
prop = RNA_def_property(srna, "is_movie_format", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_funcs(prop, "rna_RenderSettings_is_movie_fomat_get", NULL);
+ RNA_def_property_boolean_funcs(prop, "rna_RenderSettings_is_movie_format_get", NULL);
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_ui_text(prop, "Movie Format", "When true the format is a movie");
@@ -5013,9 +5686,14 @@ static void rna_def_scene_render_data(BlenderRNA *brna)
prop = RNA_def_property(srna, "use_stamp", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "stamp", R_STAMP_DRAW);
- RNA_def_property_ui_text(prop, "Render Stamp", "Render the stamp info text in the rendered image");
+ RNA_def_property_ui_text(prop, "Stamp Output", "Render the stamp info text in the rendered image");
RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
-
+
+ prop = RNA_def_property(srna, "use_stamp_strip_meta", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "stamp", R_STAMP_STRIPMETA);
+ RNA_def_property_ui_text(prop, "Strip Metadata", "Use metadata from the strips in the sequencer");
+ RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
+
prop = RNA_def_property(srna, "stamp_font_size", PROP_INT, PROP_NONE);
RNA_def_property_int_sdna(prop, NULL, "stamp_font_id");
RNA_def_property_range(prop, 8, 64);
@@ -5079,6 +5757,32 @@ static void rna_def_scene_render_data(BlenderRNA *brna)
RNA_def_property_ui_icon(prop, ICON_UNPINNED, 1);
RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
+ /* views (stereoscopy et al) */
+ prop = RNA_def_property(srna, "views", PROP_COLLECTION, PROP_NONE);
+ RNA_def_property_struct_type(prop, "SceneRenderView");
+ RNA_def_property_ui_text(prop, "Render Views", "");
+ rna_def_render_views(brna, prop);
+
+ prop = RNA_def_property(srna, "stereo_views", PROP_COLLECTION, PROP_NONE);
+ RNA_def_property_collection_sdna(prop, NULL, "views", NULL);
+ RNA_def_property_collection_funcs(prop, "rna_RenderSettings_stereoViews_begin", "rna_iterator_listbase_next",
+ "rna_iterator_listbase_end", "rna_iterator_listbase_get",
+ NULL, NULL, NULL, NULL);
+ RNA_def_property_struct_type(prop, "SceneRenderView");
+ RNA_def_property_ui_text(prop, "Render Views", "");
+
+ prop = RNA_def_property(srna, "use_multiview", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "scemode", R_MULTIVIEW);
+ RNA_def_property_ui_text(prop, "Multiple Views", "Use multiple views in the scene");
+ RNA_def_property_update(prop, NC_WINDOW, NULL);
+
+ prop = RNA_def_property(srna, "views_format", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_items(prop, views_format_items);
+ RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
+ RNA_def_property_ui_text(prop, "Setup Stereo Mode", "");
+ RNA_def_property_enum_funcs(prop, NULL, "rna_RenderSettings_views_format_set", NULL);
+ RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
+
/* engine */
prop = RNA_def_property(srna, "engine", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, engine_items);
@@ -5120,6 +5824,17 @@ static void rna_def_scene_render_data(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Simplify Child Particles", "Global child particles percentage");
RNA_def_property_update(prop, 0, "rna_Scene_simplify_update");
+ prop = RNA_def_property(srna, "simplify_subdivision_render", PROP_INT, PROP_UNSIGNED);
+ RNA_def_property_int_sdna(prop, NULL, "simplify_subsurf_render");
+ RNA_def_property_ui_range(prop, 0, 6, 1, -1);
+ RNA_def_property_ui_text(prop, "Simplify Subdivision", "Global maximum subdivision level during rendering");
+ RNA_def_property_update(prop, 0, "rna_Scene_simplify_update");
+
+ prop = RNA_def_property(srna, "simplify_child_particles_render", PROP_FLOAT, PROP_FACTOR);
+ RNA_def_property_float_sdna(prop, NULL, "simplify_particles_render");
+ RNA_def_property_ui_text(prop, "Simplify Child Particles", "Global child particles percentage during rendering");
+ RNA_def_property_update(prop, 0, "rna_Scene_simplify_update");
+
prop = RNA_def_property(srna, "simplify_shadow_samples", PROP_INT, PROP_UNSIGNED);
RNA_def_property_int_sdna(prop, NULL, "simplify_shadowsamples");
RNA_def_property_ui_range(prop, 1, 16, 1, -1);
@@ -5161,6 +5876,14 @@ static void rna_def_scene_render_data(BlenderRNA *brna)
RNA_def_property_struct_type(prop, "BakeSettings");
RNA_def_property_ui_text(prop, "Bake Data", "");
+ /* Debugging settings. */
+#ifdef WITH_CYCLES_DEBUG
+ prop = RNA_def_property(srna, "debug_pass_type", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_items(prop, render_pass_debug_type_items);
+ RNA_def_property_ui_text(prop, "Debug Pass Type", "Type of the debug pass to use");
+ RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
+#endif
+
/* Nestled Data */
/* *** Non-Animated *** */
RNA_define_animate_sdna(false);
@@ -5359,6 +6082,55 @@ static void rna_def_selected_uv_element(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Face Index", "");
}
+static void rna_def_display_safe_areas(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ static float default_title[2] = {0.035f, 0.035f};
+ static float default_action[2] = {0.1f, 0.05f};
+
+ static float default_title_center[2] = {0.175f, 0.05f};
+ static float default_action_center[2] = {0.15f, 0.05f};
+
+ srna = RNA_def_struct(brna, "DisplaySafeAreas", NULL);
+ RNA_def_struct_ui_text(srna, "Safe Areas", "Safe Areas used in 3D view and the VSE");
+ RNA_def_struct_sdna(srna, "DisplaySafeAreas");
+
+ /* SAFE AREAS */
+ prop = RNA_def_property(srna, "title", PROP_FLOAT, PROP_XYZ);
+ RNA_def_property_float_sdna(prop, NULL, "title");
+ RNA_def_property_array(prop, 2);
+ RNA_def_property_range(prop, 0.0f, 1.0f);
+ RNA_def_property_float_array_default(prop, default_title);
+ RNA_def_property_ui_text(prop, "Title Safe margins", "Safe area for text and graphics");
+ RNA_def_property_update(prop, NC_SCENE | ND_DRAW_RENDER_VIEWPORT, NULL);
+
+ prop = RNA_def_property(srna, "action", PROP_FLOAT, PROP_XYZ);
+ RNA_def_property_float_sdna(prop, NULL, "action");
+ RNA_def_property_array(prop, 2);
+ RNA_def_property_float_array_default(prop, default_action);
+ RNA_def_property_range(prop, 0.0f, 1.0f);
+ RNA_def_property_ui_text(prop, "Action Safe Margins", "Safe area for general elements");
+ RNA_def_property_update(prop, NC_SCENE | ND_DRAW_RENDER_VIEWPORT, NULL);
+
+
+ prop = RNA_def_property(srna, "title_center", PROP_FLOAT, PROP_XYZ);
+ RNA_def_property_float_sdna(prop, NULL, "title_center");
+ RNA_def_property_array(prop, 2);
+ RNA_def_property_float_array_default(prop, default_title_center);
+ RNA_def_property_range(prop, 0.0f, 1.0f);
+ RNA_def_property_ui_text(prop, "Center Title Safe Margins", "Safe area for text and graphics in a different aspect ratio");
+ RNA_def_property_update(prop, NC_SCENE | ND_DRAW_RENDER_VIEWPORT, NULL);
+
+ prop = RNA_def_property(srna, "action_center", PROP_FLOAT, PROP_XYZ);
+ RNA_def_property_float_sdna(prop, NULL, "action_center");
+ RNA_def_property_array(prop, 2);
+ RNA_def_property_float_array_default(prop, default_action_center);
+ RNA_def_property_range(prop, 0.0f, 1.0f);
+ RNA_def_property_ui_text(prop, "Center Action Safe Margins", "Safe area for general elements in a different aspect ratio");
+ RNA_def_property_update(prop, NC_SCENE | ND_DRAW_RENDER_VIEWPORT, NULL);
+}
void RNA_def_scene(BlenderRNA *brna)
@@ -5443,7 +6215,7 @@ void RNA_def_scene(BlenderRNA *brna)
RNA_def_property_boolean_sdna(prop, NULL, "lay", 1);
RNA_def_property_array(prop, 20);
RNA_def_property_boolean_funcs(prop, NULL, "rna_Scene_layer_set");
- RNA_def_property_ui_text(prop, "Layers", "Visible layers - Shift-Click to select multiple layers");
+ RNA_def_property_ui_text(prop, "Layers", "Visible layers - Shift-Click/Drag to select multiple layers");
RNA_def_property_update(prop, NC_SCENE | ND_LAYER, "rna_Scene_layer_update");
/* active layer */
@@ -5654,6 +6426,13 @@ void RNA_def_scene(BlenderRNA *brna)
RNA_def_property_struct_type(prop, "RenderSettings");
RNA_def_property_ui_text(prop, "Render Data", "");
+ /* Safe Areas */
+ prop = RNA_def_property(srna, "safe_areas", PROP_POINTER, PROP_NONE);
+ RNA_def_property_pointer_sdna(prop, NULL, "safe_areas");
+ RNA_def_property_flag(prop, PROP_NEVER_NULL);
+ RNA_def_property_struct_type(prop, "DisplaySafeAreas");
+ RNA_def_property_ui_text(prop, "Safe Areas", "");
+
/* Markers */
prop = RNA_def_property(srna, "timeline_markers", PROP_COLLECTION, PROP_NONE);
RNA_def_property_collection_sdna(prop, NULL, "markers", NULL);
@@ -5701,9 +6480,9 @@ void RNA_def_scene(BlenderRNA *brna)
prop = RNA_def_property(srna, "audio_volume", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "audio.volume");
- RNA_def_property_range(prop, 0.0f, 1.0f);
+ RNA_def_property_range(prop, 0.0f, 100.0f);
RNA_def_property_ui_text(prop, "Volume", "Audio volume");
- RNA_def_property_translation_context(prop, BLF_I18NCONTEXT_ID_SOUND);
+ RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_SOUND);
RNA_def_property_update(prop, NC_SCENE, NULL);
RNA_def_property_float_funcs(prop, NULL, "rna_Scene_volume_set", NULL);
@@ -5722,10 +6501,10 @@ void RNA_def_scene(BlenderRNA *brna)
/* Grease Pencil */
prop = RNA_def_property(srna, "grease_pencil", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "gpd");
- RNA_def_property_flag(prop, PROP_EDITABLE);
RNA_def_property_struct_type(prop, "GreasePencil");
+ RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_REFCOUNT);
RNA_def_property_ui_text(prop, "Grease Pencil Data", "Grease Pencil datablock");
- RNA_def_property_update(prop, NC_SCENE, NULL);
+ RNA_def_property_update(prop, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
/* Transform Orientations */
prop = RNA_def_property(srna, "orientations", PROP_COLLECTION, PROP_NONE);
@@ -5757,6 +6536,11 @@ void RNA_def_scene(BlenderRNA *brna)
RNA_def_property_struct_type(prop, "ColorManagedSequencerColorspaceSettings");
RNA_def_property_ui_text(prop, "Sequencer Color Space Settings", "Settings of color space sequencer is working in");
+ /* Dependency Graph */
+ prop = RNA_def_property(srna, "depsgraph", PROP_POINTER, PROP_NONE);
+ RNA_def_property_struct_type(prop, "Depsgraph");
+ RNA_def_property_ui_text(prop, "Dependency Graph", "Dependencies in the scene data");
+
/* Nestled Data */
/* *** Non-Animated *** */
RNA_define_animate_sdna(false);
@@ -5768,11 +6552,14 @@ void RNA_def_scene(BlenderRNA *brna)
rna_def_scene_game_data(brna);
rna_def_transform_orientation(brna);
rna_def_selected_uv_element(brna);
+ rna_def_display_safe_areas(brna);
RNA_define_animate_sdna(true);
/* *** Animated *** */
rna_def_scene_render_data(brna);
rna_def_scene_render_layer(brna);
-
+ rna_def_gpu_fx(brna);
+ rna_def_scene_render_view(brna);
+
/* Scene API */
RNA_api_scene(srna);
}
diff --git a/source/blender/makesrna/intern/rna_scene_api.c b/source/blender/makesrna/intern/rna_scene_api.c
index 84134e7cd3a..9d63dfe0f55 100644
--- a/source/blender/makesrna/intern/rna_scene_api.c
+++ b/source/blender/makesrna/intern/rna_scene_api.c
@@ -47,12 +47,14 @@
#include "BKE_animsys.h"
#include "BKE_depsgraph.h"
+#include "BKE_editmesh.h"
#include "BKE_global.h"
#include "BKE_image.h"
#include "BKE_scene.h"
#include "BKE_writeavi.h"
#include "ED_transform.h"
+#include "ED_uvedit.h"
#ifdef WITH_PYTHON
# include "BPY_extern.h"
@@ -90,6 +92,20 @@ static void rna_Scene_frame_set(Scene *scene, int frame, float subframe)
}
}
+static void rna_Scene_uvedit_aspect(Scene *scene, Object *ob, float *aspect)
+{
+ if ((ob->type == OB_MESH) && (ob->mode == OB_MODE_EDIT)) {
+ BMEditMesh *em;
+ em = BKE_editmesh_from_object(ob);
+ if (EDBM_mtexpoly_check(em)) {
+ ED_uvedit_get_aspect(scene, ob, em->bm, aspect, aspect + 1);
+ return;
+ }
+ }
+
+ aspect[0] = aspect[1] = 1.0f;
+}
+
static void rna_Scene_update_tagged(Scene *scene)
{
#ifdef WITH_PYTHON
@@ -103,13 +119,22 @@ static void rna_Scene_update_tagged(Scene *scene)
#endif
}
-static void rna_SceneRender_get_frame_path(RenderData *rd, int frame, char *name)
+static void rna_SceneRender_get_frame_path(RenderData *rd, int frame, int preview, const char *view, char *name)
{
- if (BKE_imtype_is_movie(rd->im_format.imtype))
- BKE_movie_filepath_get(name, rd);
- else
- BKE_makepicstring(name, rd->pic, G.main->name, (frame == INT_MIN) ? rd->cfra : frame,
- &rd->im_format, (rd->scemode & R_EXTENSION) != 0, true);
+ const char *suffix = BKE_scene_multiview_view_suffix_get(rd, view);
+
+ /* avoid NULL pointer */
+ if (!suffix)
+ suffix = "";
+
+ if (BKE_imtype_is_movie(rd->im_format.imtype)) {
+ BKE_movie_filepath_get(name, rd, preview != 0, suffix);
+ }
+ else {
+ BKE_image_path_from_imformat(
+ name, rd->pic, G.main->name, (frame == INT_MIN) ? rd->cfra : frame,
+ &rd->im_format, (rd->scemode & R_EXTENSION) != 0, true, suffix);
+ }
}
static void rna_Scene_ray_cast(Scene *scene, float ray_start[3], float ray_end[3],
@@ -191,6 +216,15 @@ void RNA_api_scene(StructRNA *srna)
RNA_def_function_ui_description(func,
"Update data tagged to be updated from previous access to data or operators");
+ func = RNA_def_function(srna, "uvedit_aspect", "rna_Scene_uvedit_aspect");
+ RNA_def_function_ui_description(func, "Get uv aspect for current object");
+ parm = RNA_def_pointer(func, "object", "Object", "", "Object");
+ RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL);
+
+ parm = RNA_def_float_vector(func, "result", 2, NULL, 0.0f, FLT_MAX, "", "aspect", 0.0f, FLT_MAX);
+ RNA_def_property_flag(parm, PROP_THICK_WRAP);
+ RNA_def_function_output(func, parm);
+
/* Ray Cast */
func = RNA_def_function(srna, "ray_cast", "rna_Scene_ray_cast");
RNA_def_function_ui_description(func, "Cast a ray onto in object space");
@@ -259,6 +293,10 @@ void RNA_api_scene_render(StructRNA *srna)
RNA_def_function_ui_description(func, "Return the absolute path to the filename to be written for a given frame");
RNA_def_int(func, "frame", INT_MIN, INT_MIN, INT_MAX, "",
"Frame number to use, if unset the current frame will be used", MINAFRAME, MAXFRAME);
+ parm = RNA_def_boolean(func, "preview", 0, "Preview", "Use preview range");
+ parm = RNA_def_string_file_path(func, "view", NULL, FILE_MAX, "View",
+ "The name of the view to use to replace the \"%\" chars");
+
parm = RNA_def_string_file_path(func, "filepath", NULL, FILE_MAX, "File Path",
"The resulting filepath from the scenes render settings");
RNA_def_property_flag(parm, PROP_THICK_WRAP); /* needed for string return value */
diff --git a/source/blender/makesrna/intern/rna_screen.c b/source/blender/makesrna/intern/rna_screen.c
index cf591dc7750..477a9dbca4f 100644
--- a/source/blender/makesrna/intern/rna_screen.c
+++ b/source/blender/makesrna/intern/rna_screen.c
@@ -110,13 +110,15 @@ static void rna_Screen_redraw_update(Main *UNUSED(bmain), Scene *UNUSED(scene),
static int rna_Screen_is_animation_playing_get(PointerRNA *UNUSED(ptr))
{
- return (ED_screen_animation_playing(G.main->wm.first) != NULL);
+ /* can be NULL on file load, T42619 */
+ wmWindowManager *wm = G.main->wm.first;
+ return wm ? (ED_screen_animation_playing(wm) != NULL) : 0;
}
static int rna_Screen_fullscreen_get(PointerRNA *ptr)
{
bScreen *sc = (bScreen *)ptr->data;
- return (sc->full != 0);
+ return (sc->state == SCREENMAXIMIZED);
}
/* UI compatible list: should not be needed, but for now we need to keep EMPTY
@@ -398,7 +400,7 @@ static void rna_def_screen(BlenderRNA *brna)
prop = RNA_def_property(srna, "show_fullscreen", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_boolean_funcs(prop, "rna_Screen_fullscreen_get", NULL);
- RNA_def_property_ui_text(prop, "Fullscreen", "An area is maximized, filling this screen");
+ RNA_def_property_ui_text(prop, "Maximize", "An area is maximized, filling this screen");
/* Define Anim Playback Areas */
prop = RNA_def_property(srna, "use_play_top_left_3d_editor", PROP_BOOLEAN, PROP_NONE);
@@ -411,6 +413,11 @@ static void rna_def_screen(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "All 3D View Editors", "");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_TIME, "rna_Screen_redraw_update");
+ prop = RNA_def_property(srna, "use_follow", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "redraws_flag", TIME_FOLLOW);
+ RNA_def_property_ui_text(prop, "Follow", "Follow current frame in editors");
+ RNA_def_property_update(prop, NC_SPACE | ND_SPACE_TIME, "rna_Screen_redraw_update");
+
prop = RNA_def_property(srna, "use_play_animation_editors", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "redraws_flag", TIME_ALL_ANIM_WIN);
RNA_def_property_ui_text(prop, "Animation Editors", "");
diff --git a/source/blender/makesrna/intern/rna_sculpt_paint.c b/source/blender/makesrna/intern/rna_sculpt_paint.c
index b5b938ca2db..3ec9944900a 100644
--- a/source/blender/makesrna/intern/rna_sculpt_paint.c
+++ b/source/blender/makesrna/intern/rna_sculpt_paint.c
@@ -289,9 +289,10 @@ static char *rna_ParticleBrush_path(PointerRNA *UNUSED(ptr))
static void rna_Paint_brush_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
{
- Brush *br = (Brush *)ptr->data;
+ Paint *paint = ptr->data;
+ Brush *br = paint->brush;
BKE_paint_invalidate_overlay_all();
- WM_main_add_notifier(NC_BRUSH | NA_EDITED, br);
+ WM_main_add_notifier(NC_BRUSH | NA_SELECTED, br);
}
static void rna_ImaPaint_viewport_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *UNUSED(ptr))
@@ -303,17 +304,32 @@ static void rna_ImaPaint_viewport_update(Main *UNUSED(bmain), Scene *UNUSED(scen
static void rna_ImaPaint_mode_update(Main *UNUSED(bmain), Scene *scene, PointerRNA *UNUSED(ptr))
{
Object *ob = OBACT;
-
- /* of course we need to invalidate here */
- BKE_texpaint_slots_refresh_object(scene, ob);
- /* we assume that changing the current mode will invalidate the uv layers so we need to refresh display */
- GPU_drawobject_free(ob->derivedFinal);
- WM_main_add_notifier(NC_GEOM | ND_DATA, &ob->id);
+ if (ob && ob->type == OB_MESH) {
+ /* of course we need to invalidate here */
+ BKE_texpaint_slots_refresh_object(scene, ob);
+
+ /* we assume that changing the current mode will invalidate the uv layers so we need to refresh display */
+ GPU_drawobject_free(ob->derivedFinal);
+ BKE_paint_proj_mesh_data_check(scene, ob, NULL, NULL, NULL, NULL);
+ WM_main_add_notifier(NC_OBJECT | ND_DRAW, NULL);
+ }
+}
+
+static void rna_ImaPaint_stencil_update(Main *UNUSED(bmain), Scene *scene, PointerRNA *UNUSED(ptr))
+{
+ Object *ob = OBACT;
+
+ if (ob && ob->type == OB_MESH) {
+ GPU_drawobject_free(ob->derivedFinal);
+ BKE_paint_proj_mesh_data_check(scene, ob, NULL, NULL, NULL, NULL);
+ WM_main_add_notifier(NC_OBJECT | ND_DRAW, NULL);
+ }
}
static void rna_ImaPaint_canvas_update(Main *bmain, Scene *scene, PointerRNA *UNUSED(ptr))
{
+ Object *ob = OBACT;
bScreen *sc;
Image *ima = scene->toolsettings->imapaint.canvas;
@@ -331,53 +347,19 @@ static void rna_ImaPaint_canvas_update(Main *bmain, Scene *scene, PointerRNA *UN
}
}
}
-
- WM_main_add_notifier(NC_OBJECT | ND_DRAW, NULL);
+
+ if (ob && ob->type == OB_MESH) {
+ GPU_drawobject_free(ob->derivedFinal);
+ BKE_paint_proj_mesh_data_check(scene, ob, NULL, NULL, NULL, NULL);
+ WM_main_add_notifier(NC_OBJECT | ND_DRAW, NULL);
+ }
}
-#else
-static void rna_def_palettecolor(BlenderRNA *brna)
+static int rna_ImaPaint_detect_data(ImagePaintSettings *imapaint)
{
- StructRNA *srna;
- PropertyRNA *prop;
-
- srna = RNA_def_struct(brna, "PaletteColor", NULL);
- RNA_def_struct_ui_text(srna, "Palette Color", "");
-
- prop = RNA_def_property(srna, "color", PROP_FLOAT, PROP_COLOR_GAMMA);
- RNA_def_property_range(prop, 0.0, 1.0);
- RNA_def_property_float_sdna(prop, NULL, "rgb");
- RNA_def_property_ui_text(prop, "Color", "");
- RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL);
-
- prop = RNA_def_property(srna, "strength", PROP_FLOAT, PROP_NONE);
- RNA_def_property_range(prop, 0.0, 1.0);
- RNA_def_property_float_sdna(prop, NULL, "value");
- RNA_def_property_ui_text(prop, "Value", "");
- RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL);
-
- prop = RNA_def_property(srna, "weight", PROP_FLOAT, PROP_NONE);
- RNA_def_property_range(prop, 0.0, 1.0);
- RNA_def_property_float_sdna(prop, NULL, "value");
- RNA_def_property_ui_text(prop, "Weight", "");
- RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL);
-}
-
-
-static void rna_def_palette(BlenderRNA *brna)
-{
- StructRNA *srna;
- PropertyRNA *prop;
-
- srna = RNA_def_struct(brna, "Palette", "ID");
- RNA_def_struct_ui_text(srna, "Palette", "");
- RNA_def_struct_ui_icon(srna, ICON_COLOR);
-
- prop = RNA_def_property(srna, "colors", PROP_COLLECTION, PROP_NONE);
- RNA_def_property_struct_type(prop, "PaletteColor");
- RNA_def_property_ui_text(prop, "Palette Color", "Colors that are part of this palette");
- RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL);
+ return imapaint->missing_data == 0;
}
+#else
static void rna_def_paint_curve(BlenderRNA *brna)
{
@@ -450,6 +432,39 @@ static void rna_def_paint(BlenderRNA *brna)
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, "cavity_curve", PROP_POINTER, PROP_NONE);
+ RNA_def_property_flag(prop, PROP_NEVER_NULL);
+ RNA_def_property_ui_text(prop, "Curve", "Editable cavity curve");
+ RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL);
+
+ prop = RNA_def_property(srna, "use_cavity", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flags", PAINT_USE_CAVITY_MASK);
+ RNA_def_property_ui_text(prop, "Cavity Mask", "Mask painting according to mesh geometry cavity");
+ RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL);
+
+ prop = RNA_def_property(srna, "tile_offset", PROP_FLOAT, PROP_XYZ);
+ RNA_def_property_float_sdna(prop, NULL, "tile_offset");
+ RNA_def_property_array(prop, 3);
+ RNA_def_property_range(prop, 0.01, FLT_MAX);
+ RNA_def_property_ui_range(prop, 0.01, 100, 1 * 100, 2);
+ RNA_def_property_ui_text(prop, "Tiling offset for the X Axis",
+ "Stride at which tiled strokes are copied");
+
+ prop = RNA_def_property(srna, "tile_x", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "symmetry_flags", PAINT_TILE_X);
+ RNA_def_property_ui_text(prop, "Tile X", "Tile along X axis");
+ RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL);
+
+ prop = RNA_def_property(srna, "tile_y", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "symmetry_flags", PAINT_TILE_Y);
+ RNA_def_property_ui_text(prop, "Tile Y", "Tile along Y axis");
+ RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL);
+
+ prop = RNA_def_property(srna, "tile_z", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "symmetry_flags", PAINT_TILE_Z);
+ RNA_def_property_ui_text(prop, "Tile Z", "Tile along Z axis");
+ RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL);
}
static void rna_def_sculpt(BlenderRNA *brna)
@@ -469,6 +484,8 @@ static void rna_def_sculpt(BlenderRNA *brna)
"Relative Detail", "Mesh detail is relative to the brush size and detail size"},
{SCULPT_DYNTOPO_DETAIL_CONSTANT, "CONSTANT", 0,
"Constant Detail", "Mesh detail is constant in object space according to detail size"},
+ {SCULPT_DYNTOPO_DETAIL_BRUSH, "BRUSH", 0,
+ "Brush Detail", "Mesh detail is relative to brush radius"},
{0, NULL, 0, NULL, NULL}
};
@@ -526,6 +543,11 @@ static void rna_def_sculpt(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Detail Size", "Maximum edge length for dynamic topology sculpting (in pixels)");
RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL);
+ prop = RNA_def_property(srna, "detail_percent", PROP_FLOAT, PROP_PERCENTAGE);
+ RNA_def_property_ui_range(prop, 0.5, 100.0, 10, 2);
+ RNA_def_property_ui_text(prop, "Detail Percentage", "Maximum edge length for dynamic topology sculpting (in brush percenage)");
+ RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL);
+
prop = RNA_def_property(srna, "constant_detail", PROP_FLOAT, PROP_PERCENTAGE);
RNA_def_property_range(prop, 0.001, 10000.0);
RNA_def_property_ui_range(prop, 0.1, 100.0, 10, 2);
@@ -614,6 +636,7 @@ static void rna_def_image_paint(BlenderRNA *brna)
{
StructRNA *srna;
PropertyRNA *prop;
+ FunctionRNA *func;
static EnumPropertyItem paint_type_items[] = {
{IMAGEPAINT_MODE_MATERIAL, "MATERIAL", 0,
@@ -627,6 +650,13 @@ static void rna_def_image_paint(BlenderRNA *brna)
RNA_def_struct_sdna(srna, "ImagePaintSettings");
RNA_def_struct_path_func(srna, "rna_ImagePaintSettings_path");
RNA_def_struct_ui_text(srna, "Image Paint", "Properties of image and texture painting mode");
+
+ /* functions */
+ func = RNA_def_function(srna, "detect_data", "rna_ImaPaint_detect_data");
+ RNA_def_function_ui_description(func, "Check if required texpaint data exist");
+
+ /* return type */
+ RNA_def_function_return(func, RNA_def_boolean(func, "ok", 1, "", ""));
/* booleans */
prop = RNA_def_property(srna, "use_occlude", PROP_BOOLEAN, PROP_NONE);
@@ -648,7 +678,7 @@ static void rna_def_image_paint(BlenderRNA *brna)
RNA_def_property_boolean_sdna(prop, NULL, "flag", IMAGEPAINT_PROJECT_LAYER_STENCIL);
RNA_def_property_ui_text(prop, "Stencil Layer", "Set the mask layer from the UV map buttons");
RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, "rna_ImaPaint_viewport_update");
-
+
prop = RNA_def_property(srna, "invert_stencil", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", IMAGEPAINT_PROJECT_LAYER_STENCIL_INV);
RNA_def_property_ui_text(prop, "Invert", "Invert the stencil layer");
@@ -658,7 +688,7 @@ static void rna_def_image_paint(BlenderRNA *brna)
RNA_def_property_pointer_sdna(prop, NULL, "stencil");
RNA_def_property_flag(prop, PROP_EDITABLE);
RNA_def_property_ui_text(prop, "Stencil Image", "Image used as stencil");
- RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, "rna_ImaPaint_viewport_update");
+ RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, "rna_ImaPaint_stencil_update");
prop = RNA_def_property(srna, "canvas", PROP_POINTER, PROP_NONE);
RNA_def_property_flag(prop, PROP_EDITABLE);
@@ -676,12 +706,17 @@ static void rna_def_image_paint(BlenderRNA *brna)
RNA_def_property_float_sdna(prop, NULL, "stencil_col");
RNA_def_property_ui_text(prop, "Stencil Color", "Stencil color in the viewport");
RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, "rna_ImaPaint_viewport_update");
+
+ prop = RNA_def_property(srna, "dither", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_range(prop, 0.0, 2.0);
+ RNA_def_property_ui_text(prop, "Dither", "Amount of dithering when painting on byte images");
+ RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL);
prop = RNA_def_property(srna, "use_clone_layer", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", IMAGEPAINT_PROJECT_LAYER_CLONE);
RNA_def_property_ui_text(prop, "Clone Map",
"Use another UV map as clone source, otherwise use the 3D cursor as the source");
- RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL);
+ RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, "rna_ImaPaint_viewport_update");
/* integers */
@@ -700,7 +735,32 @@ static void rna_def_image_paint(BlenderRNA *brna)
prop = RNA_def_property(srna, "mode", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, paint_type_items);
RNA_def_property_ui_text(prop, "Mode", "Mode of operation for projection painting");
- RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, "rna_ImaPaint_mode_update");
+ RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, "rna_ImaPaint_mode_update");
+
+ /* Missing data */
+ prop = RNA_def_property(srna, "missing_uvs", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "missing_data", IMAGEPAINT_MISSING_UVS);
+ RNA_def_property_ui_text(prop, "Missing UVs",
+ "A UV layer is missing on the mesh");
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+
+ prop = RNA_def_property(srna, "missing_materials", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "missing_data", IMAGEPAINT_MISSING_MATERIAL);
+ RNA_def_property_ui_text(prop, "Missing Materials",
+ "The mesh is missing materials");
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+
+ prop = RNA_def_property(srna, "missing_stencil", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "missing_data", IMAGEPAINT_MISSING_STENCIL);
+ RNA_def_property_ui_text(prop, "Missing Stencil",
+ "Image Painting does not have a stencil");
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+
+ prop = RNA_def_property(srna, "missing_texture", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "missing_data", IMAGEPAINT_MISSING_TEX);
+ RNA_def_property_ui_text(prop, "Missing Texture",
+ "Image Painting does not have a texture to paint on");
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
}
static void rna_def_particle_edit(BlenderRNA *brna)
@@ -830,6 +890,11 @@ static void rna_def_particle_edit(BlenderRNA *brna)
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_ui_text(prop, "Object", "The edited object");
+ prop = RNA_def_property(srna, "shape_object", PROP_POINTER, PROP_NONE);
+ RNA_def_property_flag(prop, PROP_EDITABLE);
+ RNA_def_property_ui_text(prop, "Shape Object", "Outer shape to use for tools");
+ RNA_def_property_pointer_funcs(prop, NULL, NULL, NULL, "rna_Mesh_object_poll");
+ RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_ParticleEdit_redo");
/* brush */
@@ -840,7 +905,7 @@ static void rna_def_particle_edit(BlenderRNA *brna)
prop = RNA_def_property(srna, "size", PROP_INT, PROP_PIXEL);
RNA_def_property_range(prop, 1, SHRT_MAX);
- RNA_def_property_ui_range(prop, 1, 100, 10, 3);
+ RNA_def_property_ui_range(prop, 1, MAX_BRUSH_PIXEL_RADIUS, 10, 3);
RNA_def_property_ui_text(prop, "Radius", "Radius of the brush in pixels");
prop = RNA_def_property(srna, "strength", PROP_FLOAT, PROP_FACTOR);
@@ -884,8 +949,6 @@ void RNA_def_sculpt_paint(BlenderRNA *brna)
{
/* *** Non-Animated *** */
RNA_define_animate_sdna(false);
- rna_def_palettecolor(brna);
- rna_def_palette(brna);
rna_def_paint_curve(brna);
rna_def_paint(brna);
rna_def_sculpt(brna);
diff --git a/source/blender/makesrna/intern/rna_sensor.c b/source/blender/makesrna/intern/rna_sensor.c
index 3944b59dff7..baf0ae3ccf5 100644
--- a/source/blender/makesrna/intern/rna_sensor.c
+++ b/source/blender/makesrna/intern/rna_sensor.c
@@ -33,7 +33,7 @@
#include "BLI_utildefines.h"
#include "BLI_math.h"
-#include "BLF_translation.h"
+#include "BLT_translation.h"
#include "RNA_define.h"
#include "RNA_enum_types.h"
@@ -107,14 +107,10 @@ static StructRNA *rna_Sensor_refine(struct PointerRNA *ptr)
static void rna_Sensor_name_set(PointerRNA *ptr, const char *value)
{
- bSensor *sens = (bSensor *)ptr->data;
-
+ Object *ob = ptr->id.data;
+ bSensor *sens = ptr->data;
BLI_strncpy_utf8(sens->name, value, sizeof(sens->name));
-
- if (ptr->id.data) {
- Object *ob = (Object *)ptr->id.data;
- BLI_uniquename(&ob->sensors, sens, DATA_("Sensor"), '.', offsetof(bSensor, name), sizeof(sens->name));
- }
+ BLI_uniquename(&ob->sensors, sens, DATA_("Sensor"), '.', offsetof(bSensor, name), sizeof(sens->name));
}
static void rna_Sensor_type_set(struct PointerRNA *ptr, int value)
@@ -246,11 +242,11 @@ static void rna_Sensor_Armature_update(Main *UNUSED(bmain), Scene *UNUSED(scene)
bPoseChannel *pchan;
bPose *pose = ob->pose;
for (pchan = pose->chanbase.first; pchan; pchan = pchan->next) {
- if (!strcmp(pchan->name, posechannel)) {
+ if (STREQ(pchan->name, posechannel)) {
/* found it, now look for constraint channel */
bConstraint *con;
for (con = pchan->constraints.first; con; con = con->next) {
- if (!strcmp(con->name, constraint)) {
+ if (STREQ(con->name, constraint)) {
/* found it, all ok */
return;
}
@@ -329,9 +325,11 @@ static void rna_def_sensor(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Pulse False Level", "Activate FALSE level triggering (pulse mode)");
RNA_def_property_update(prop, NC_LOGIC, NULL);
- prop = RNA_def_property(srna, "frequency", PROP_INT, PROP_NONE);
+ prop = RNA_def_property(srna, "tick_skip", PROP_INT, PROP_NONE);
RNA_def_property_int_sdna(prop, NULL, "freq");
- RNA_def_property_ui_text(prop, "Frequency", "Delay between repeated pulses(in logic tics, 0=no delay)");
+ RNA_def_property_ui_text(prop, "Skip",
+ "Number of logic ticks skipped between 2 active pulses "
+ "(0 = pulse every logic tick, 1 = skip 1 logic tick between pulses, etc.)");
RNA_def_property_range(prop, 0, 10000);
RNA_def_property_update(prop, NC_LOGIC, NULL);
@@ -406,8 +404,8 @@ static void rna_def_mouse_sensor(BlenderRNA *brna)
};
static const EnumPropertyItem prop_mouse_type_items[] = {
- {SENS_COLLISION_PROPERTY, "PROPERTY", ICON_LOGIC, "Property", "Use a material for ray intersections"},
- {SENS_COLLISION_MATERIAL, "MATERIAL", ICON_MATERIAL_DATA, "Material", "Use a property for ray intersections"},
+ {SENS_COLLISION_PROPERTY, "PROPERTY", ICON_LOGIC, "Property", "Use a property for ray intersections"},
+ {SENS_COLLISION_MATERIAL, "MATERIAL", ICON_MATERIAL_DATA, "Material", "Use a material for ray intersections"},
{0, NULL, 0, NULL, NULL}
};
@@ -462,7 +460,7 @@ static void rna_def_keyboard_sensor(BlenderRNA *brna)
RNA_def_property_enum_items(prop, event_type_items);
RNA_def_property_enum_funcs(prop, NULL, "rna_Sensor_keyboard_key_set", NULL);
RNA_def_property_ui_text(prop, "Key", "");
- RNA_def_property_translation_context(prop, BLF_I18NCONTEXT_ID_WINDOWMANAGER);
+ RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_WINDOWMANAGER);
RNA_def_property_update(prop, NC_LOGIC, NULL);
prop = RNA_def_property(srna, "modifier_key_1", PROP_ENUM, PROP_NONE);
@@ -740,8 +738,8 @@ static void rna_def_ray_sensor(BlenderRNA *brna)
};
static const EnumPropertyItem prop_ray_type_items[] = {
- {SENS_COLLISION_PROPERTY, "PROPERTY", ICON_LOGIC, "Property", "Use a material for ray intersections"},
- {SENS_COLLISION_MATERIAL, "MATERIAL", ICON_MATERIAL_DATA, "Material", "Use a property for ray intersections"},
+ {SENS_COLLISION_PROPERTY, "PROPERTY", ICON_LOGIC, "Property", "Use a property for ray intersections"},
+ {SENS_COLLISION_MATERIAL, "MATERIAL", ICON_MATERIAL_DATA, "Material", "Use a material for ray intersections"},
{0, NULL, 0, NULL, NULL}
};
diff --git a/source/blender/makesrna/intern/rna_sequencer.c b/source/blender/makesrna/intern/rna_sequencer.c
index 00f0a6ff487..2192eae9fe6 100644
--- a/source/blender/makesrna/intern/rna_sequencer.c
+++ b/source/blender/makesrna/intern/rna_sequencer.c
@@ -35,7 +35,7 @@
#include "BLI_math.h"
-#include "BLF_translation.h"
+#include "BLT_translation.h"
#include "BKE_animsys.h"
#include "BKE_global.h"
@@ -72,9 +72,9 @@ EnumPropertyItem sequence_modifier_type_items[] = {
#ifdef RNA_RUNTIME
#include "BKE_report.h"
+#include "BKE_idprop.h"
#include "WM_api.h"
-#include "WM_types.h"
#include "IMB_imbuf.h"
@@ -134,6 +134,14 @@ static void rna_SequenceEditor_sequences_all_begin(CollectionPropertyIterator *i
rna_iterator_listbase_begin(iter, &ed->seqbase, NULL);
}
+static void rna_SequenceEditor_update_cache(Main *UNUSED(bmain), Scene *scene, PointerRNA *UNUSED(ptr))
+{
+ Editing *ed = scene->ed;
+
+ BKE_sequencer_free_imbuf(scene, &ed->seqbase, false);
+}
+
+
static void rna_SequenceEditor_sequences_all_next(CollectionPropertyIterator *iter)
{
ListBaseIterator *internal = &iter->internal.listbase;
@@ -177,6 +185,11 @@ static void rna_SequenceEditor_elements_begin(CollectionPropertyIterator *iter,
rna_SequenceEditor_elements_length(ptr), 0, NULL);
}
+static void rna_Sequence_views_format_update(Main *bmain, Scene *scene, PointerRNA *ptr)
+{
+ rna_Sequence_update(bmain, scene, ptr);
+}
+
static void do_sequence_frame_change_update(Scene *scene, Sequence *seq)
{
Editing *ed = BKE_sequencer_editing_get(scene, false);
@@ -290,11 +303,14 @@ static void rna_Sequence_channel_set(PointerRNA *ptr, int value)
Scene *scene = (Scene *)ptr->id.data;
Editing *ed = BKE_sequencer_editing_get(scene, false);
ListBase *seqbase = BKE_sequence_seqbase(&ed->seqbase, seq);
-
- seq->machine = value;
+ /* check channel increment or decrement */
+ const int channel_delta = (value >= seq->machine) ? 1 : -1;
+ seq->machine = value;
+
if (BKE_sequence_test_overlap(seqbase, seq)) {
- BKE_sequence_base_shuffle(seqbase, seq, scene); /* XXX - BROKEN!, uses context seqbasep */
+ /* XXX - BROKEN!, uses context seqbasep */
+ BKE_sequence_base_shuffle_ex(seqbase, seq, scene, channel_delta);
}
BKE_sequencer_sort(scene);
}
@@ -310,18 +326,7 @@ static void rna_Sequence_frame_offset_range(PointerRNA *ptr, int *min, int *max,
static void rna_Sequence_use_proxy_set(PointerRNA *ptr, int value)
{
Sequence *seq = (Sequence *)ptr->data;
- if (value) {
- seq->flag |= SEQ_USE_PROXY;
- if (seq->strip->proxy == NULL) {
- seq->strip->proxy = MEM_callocN(sizeof(struct StripProxy), "StripProxy");
- seq->strip->proxy->quality = 90;
- seq->strip->proxy->build_tc_flags = SEQ_PROXY_TC_ALL;
- seq->strip->proxy->build_size_flags = SEQ_PROXY_IMAGE_SIZE_25;
- }
- }
- else {
- seq->flag ^= SEQ_USE_PROXY;
- }
+ BKE_sequencer_proxy_set(seq, value != 0);
}
static void rna_Sequence_use_translation_set(PointerRNA *ptr, int value)
@@ -484,7 +489,7 @@ static void rna_Sequence_name_set(PointerRNA *ptr, const char *value)
/* fix all the animation data which may link to this */
/* don't rename everywhere because these are per scene */
- /* BKE_all_animdata_fix_paths_rename(NULL, "sequence_editor.sequences_all", oldname, seq->name + 2); */
+ /* BKE_animdata_fix_paths_rename_all(NULL, "sequence_editor.sequences_all", oldname, seq->name + 2); */
adt = BKE_animdata_from_id(&scene->id);
if (adt)
BKE_animdata_fix_paths_rename(&scene->id, adt, NULL, "sequence_editor.sequences_all", oldname, seq->name + 2, 0, 0, 1);
@@ -541,6 +546,8 @@ static StructRNA *rna_Sequence_refine(struct PointerRNA *ptr)
return &RNA_SpeedControlSequence;
case SEQ_TYPE_GAUSSIAN_BLUR:
return &RNA_GaussianBlurSequence;
+ case SEQ_TYPE_TEXT:
+ return &RNA_TextSequence;
default:
return &RNA_Sequence;
}
@@ -564,6 +571,18 @@ static char *rna_Sequence_path(PointerRNA *ptr)
}
}
+static IDProperty *rna_Sequence_idprops(PointerRNA *ptr, bool create)
+{
+ Sequence *seq = ptr->data;
+
+ if (create && !seq->prop) {
+ IDPropertyTemplate val = {0};
+ seq->prop = IDP_New(IDP_GROUP, &val, "Sequence ID properties");
+ }
+
+ return seq->prop;
+}
+
static PointerRNA rna_SequenceEditor_meta_stack_get(CollectionPropertyIterator *iter)
{
ListBaseIterator *internal = &iter->internal.listbase;
@@ -585,8 +604,8 @@ static void rna_Sequence_filepath_set(PointerRNA *ptr, const char *value)
PointerRNA id_ptr;
RNA_id_pointer_create((ID *)seq->sound, &id_ptr);
RNA_string_set(&id_ptr, "filepath", value);
- sound_load(G.main, seq->sound);
- sound_update_scene_sound(seq->scene_sound, seq->sound);
+ BKE_sound_load(G.main, seq->sound);
+ BKE_sound_update_scene_sound(seq->scene_sound, seq->sound);
}
BLI_split_dirfile(value, seq->strip->dir, seq->strip->stripdata->name, sizeof(seq->strip->dir),
@@ -641,7 +660,7 @@ static void rna_Sequence_volume_set(PointerRNA *ptr, float value)
seq->volume = value;
if (seq->scene_sound)
- sound_set_scene_sound_volume(seq->scene_sound, value, (seq->flag & SEQ_AUDIO_VOLUME_ANIMATED) != 0);
+ BKE_sound_set_scene_sound_volume(seq->scene_sound, value, (seq->flag & SEQ_AUDIO_VOLUME_ANIMATED) != 0);
}
static void rna_Sequence_pitch_set(PointerRNA *ptr, float value)
@@ -650,7 +669,7 @@ static void rna_Sequence_pitch_set(PointerRNA *ptr, float value)
seq->pitch = value;
if (seq->scene_sound)
- sound_set_scene_sound_pitch(seq->scene_sound, value, (seq->flag & SEQ_AUDIO_PITCH_ANIMATED) != 0);
+ BKE_sound_set_scene_sound_pitch(seq->scene_sound, value, (seq->flag & SEQ_AUDIO_PITCH_ANIMATED) != 0);
}
static void rna_Sequence_pan_set(PointerRNA *ptr, float value)
@@ -659,7 +678,7 @@ static void rna_Sequence_pan_set(PointerRNA *ptr, float value)
seq->pan = value;
if (seq->scene_sound)
- sound_set_scene_sound_pan(seq->scene_sound, value, (seq->flag & SEQ_AUDIO_PAN_ANIMATED) != 0);
+ BKE_sound_set_scene_sound_pan(seq->scene_sound, value, (seq->flag & SEQ_AUDIO_PAN_ANIMATED) != 0);
}
@@ -791,7 +810,7 @@ static int colbalance_seq_cmp_cb(Sequence *seq, void *arg_pt)
return 1;
}
-static Sequence *sequence_get_by_colorbalance(Editing *ed, StripColorBalance *cb, SequenceModifierData **smd_r)
+static Sequence *sequence_get_by_colorbalance(Editing *ed, StripColorBalance *cb, SequenceModifierData **r_smd)
{
SequenceSearchData data;
@@ -802,7 +821,7 @@ static Sequence *sequence_get_by_colorbalance(Editing *ed, StripColorBalance *cb
/* irritating we need to search for our sequence! */
BKE_sequencer_base_recursive_apply(&ed->seqbase, colbalance_seq_cmp_cb, &data);
- *smd_r = data.smd;
+ *r_smd = data.smd;
return data.seq;
}
@@ -1187,6 +1206,10 @@ static void rna_def_strip_proxy(BlenderRNA *brna)
RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_SequenceProxy_update");
+ prop = RNA_def_property(srna, "use_overwrite", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_negative_sdna(prop, NULL, "build_flags", SEQ_PROXY_SKIP_EXISTING);
+ RNA_def_property_ui_text(prop, "Overwrite", "Overwrite existing proxy files when building");
+
prop = RNA_def_property(srna, "build_25", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "build_size_flags", SEQ_PROXY_IMAGE_SIZE_25);
RNA_def_property_ui_text(prop, "25%", "Build 25% proxy resolution");
@@ -1226,6 +1249,15 @@ static void rna_def_strip_proxy(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Timecode", "");
RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_tcindex_update");
+ prop = RNA_def_property(srna, "use_proxy_custom_directory", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "storage", SEQ_STORAGE_PROXY_CUSTOM_DIR);
+ RNA_def_property_ui_text(prop, "Proxy Custom Directory", "Use a custom directory to store data");
+ RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
+
+ prop = RNA_def_property(srna, "use_proxy_custom_file", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "storage", SEQ_STORAGE_PROXY_CUSTOM_FILE);
+ RNA_def_property_ui_text(prop, "Proxy Custom File", "Use a custom file to read proxy data from");
+ RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
}
static void rna_def_color_balance(BlenderRNA *brna)
@@ -1377,6 +1409,7 @@ static void rna_def_sequence(BlenderRNA *brna)
{SEQ_TYPE_MULTICAM, "MULTICAM", 0, "Multicam Selector", ""},
{SEQ_TYPE_ADJUSTMENT, "ADJUSTMENT", 0, "Adjustment Layer", ""},
{SEQ_TYPE_GAUSSIAN_BLUR, "GAUSSIAN_BLUR", 0, "Gaussian Blur", ""},
+ {SEQ_TYPE_TEXT, "TEXT", 0, "Text", ""},
{0, NULL, 0, NULL, NULL}
};
@@ -1384,6 +1417,7 @@ static void rna_def_sequence(BlenderRNA *brna)
RNA_def_struct_ui_text(srna, "Sequence", "Sequence strip in the sequence editor");
RNA_def_struct_refine_func(srna, "rna_Sequence_refine");
RNA_def_struct_path_func(srna, "rna_Sequence_path");
+ RNA_def_struct_idprops_func(srna, "rna_Sequence_idprops");
prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE);
RNA_def_property_string_funcs(prop, "rna_Sequence_name_get", "rna_Sequence_name_length", "rna_Sequence_name_set");
@@ -1396,7 +1430,7 @@ static void rna_def_sequence(BlenderRNA *brna)
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_enum_items(prop, seq_type_items);
RNA_def_property_ui_text(prop, "Type", "");
- RNA_def_property_translation_context(prop, BLF_I18NCONTEXT_ID_SEQUENCE);
+ RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_SEQUENCE);
RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
@@ -1503,7 +1537,7 @@ static void rna_def_sequence(BlenderRNA *brna)
prop = RNA_def_property(srna, "channel", PROP_INT, PROP_UNSIGNED);
RNA_def_property_int_sdna(prop, NULL, "machine");
- RNA_def_property_range(prop, 0, MAXSEQ - 1);
+ RNA_def_property_range(prop, 1, MAXSEQ);
RNA_def_property_ui_text(prop, "Channel", "Y position of the sequence strip");
RNA_def_property_int_funcs(prop, NULL, "rna_Sequence_channel_set", NULL); /* overlap test */
RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
@@ -1563,7 +1597,12 @@ static void rna_def_editor(BlenderRNA *brna)
{
StructRNA *srna;
PropertyRNA *prop;
-
+
+ static const EnumPropertyItem editing_storage_items[] = {
+ {0, "PER_STRIP", 0, "Per Strip", "Store proxies using per strip settings"},
+ {SEQ_EDIT_PROXY_DIR_STORAGE, "PROJECT", 0, "Project", "Store proxies using project directory"},
+ {0, NULL, 0, NULL, NULL}
+ };
srna = RNA_def_struct(brna, "SequenceEditor", NULL);
RNA_def_struct_ui_text(srna, "Sequence Editor", "Sequence editing data for a Scene datablock");
RNA_def_struct_ui_icon(srna, ICON_SEQUENCE);
@@ -1611,6 +1650,16 @@ static void rna_def_editor(BlenderRNA *brna)
RNA_def_property_int_funcs(prop, "rna_SequenceEditor_overlay_frame_get",
"rna_SequenceEditor_overlay_frame_set", NULL);
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_SEQUENCER, NULL);
+
+ prop = RNA_def_property(srna, "proxy_storage", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_items(prop, editing_storage_items);
+ RNA_def_property_ui_text(prop, "Proxy Storage", "How to store proxies for this project");
+ RNA_def_property_update(prop, NC_SPACE | ND_SPACE_SEQUENCER, "rna_SequenceEditor_update_cache");
+
+ prop = RNA_def_property(srna, "proxy_dir", PROP_STRING, PROP_DIRPATH);
+ RNA_def_property_string_sdna(prop, NULL, "proxy_dir");
+ RNA_def_property_ui_text(prop, "Proxy Directory", "");
+ RNA_def_property_update(prop, NC_SPACE | ND_SPACE_SEQUENCER, "rna_SequenceEditor_update_cache");
}
static void rna_def_filter_video(StructRNA *srna)
@@ -1706,16 +1755,6 @@ static void rna_def_proxy(StructRNA *srna)
prop = RNA_def_property(srna, "proxy", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "strip->proxy");
RNA_def_property_ui_text(prop, "Proxy", "");
-
- prop = RNA_def_property(srna, "use_proxy_custom_directory", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", SEQ_USE_PROXY_CUSTOM_DIR);
- RNA_def_property_ui_text(prop, "Proxy Custom Directory", "Use a custom directory to store data");
- RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
-
- prop = RNA_def_property(srna, "use_proxy_custom_file", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", SEQ_USE_PROXY_CUSTOM_FILE);
- RNA_def_property_ui_text(prop, "Proxy Custom File", "Use a custom file to read proxy data from");
- RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
}
static void rna_def_input(StructRNA *srna)
@@ -1802,6 +1841,24 @@ static void rna_def_image(BlenderRNA *brna)
"rna_SequenceEditor_elements_length", NULL, NULL, NULL);
RNA_api_sequence_elements(brna, prop);
+ /* multiview */
+ prop = RNA_def_property(srna, "use_multiview", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", SEQ_USE_VIEWS);
+ RNA_def_property_ui_text(prop, "Use Multi-View", "Use Multiple Views (when available)");
+ RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_views_format_update");
+
+ prop = RNA_def_property(srna, "views_format", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "views_format");
+ RNA_def_property_enum_items(prop, views_format_items);
+ RNA_def_property_ui_text(prop, "Views Format", "Mode to load image views");
+ RNA_def_property_update(prop, NC_IMAGE | ND_DISPLAY, "rna_Sequence_views_format_update");
+
+ prop = RNA_def_property(srna, "stereo_3d_format", PROP_POINTER, PROP_NONE);
+ RNA_def_property_pointer_sdna(prop, NULL, "stereo3d_format");
+ RNA_def_property_flag(prop, PROP_NEVER_NULL);
+ RNA_def_property_struct_type(prop, "Stereo3dFormat");
+ RNA_def_property_ui_text(prop, "Stereo 3D Format", "Settings for stereo 3d");
+
rna_def_filter_video(srna);
rna_def_proxy(srna);
rna_def_input(srna);
@@ -1846,6 +1903,11 @@ static void rna_def_scene(BlenderRNA *brna)
RNA_def_property_pointer_funcs(prop, NULL, NULL, NULL, "rna_Camera_object_poll");
RNA_def_property_ui_text(prop, "Camera Override", "Override the scenes active camera");
RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
+
+ prop = RNA_def_property(srna, "use_grease_pencil", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", SEQ_SCENE_NO_GPENCIL);
+ RNA_def_property_ui_text(prop, "Use Grease Pencil", "Show Grease Pencil strokes in OpenGL previews");
+ RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
rna_def_filter_video(srna);
rna_def_proxy(srna);
@@ -1888,6 +1950,24 @@ static void rna_def_movie(BlenderRNA *brna)
"rna_Sequence_filepath_set");
RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_filepath_update");
+ /* multiview */
+ prop = RNA_def_property(srna, "use_multiview", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", SEQ_USE_VIEWS);
+ RNA_def_property_ui_text(prop, "Use Multi-View", "Use Multiple Views (when available)");
+ RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_views_format_update");
+
+ prop = RNA_def_property(srna, "views_format", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "views_format");
+ RNA_def_property_enum_items(prop, views_format_items);
+ RNA_def_property_ui_text(prop, "Views Format", "Mode to load movie views");
+ RNA_def_property_update(prop, NC_IMAGE | ND_DISPLAY, "rna_Sequence_views_format_update");
+
+ prop = RNA_def_property(srna, "stereo_3d_format", PROP_POINTER, PROP_NONE);
+ RNA_def_property_pointer_sdna(prop, NULL, "stereo3d_format");
+ RNA_def_property_flag(prop, PROP_NEVER_NULL);
+ RNA_def_property_struct_type(prop, "Stereo3dFormat");
+ RNA_def_property_ui_text(prop, "Stereo 3D Format", "Settings for stereo 3d");
+
rna_def_filter_video(srna);
rna_def_proxy(srna);
rna_def_input(srna);
@@ -1956,7 +2036,7 @@ static void rna_def_sound(BlenderRNA *brna)
RNA_def_property_float_sdna(prop, NULL, "volume");
RNA_def_property_range(prop, 0.0f, 100.0f);
RNA_def_property_ui_text(prop, "Volume", "Playback volume of the sound");
- RNA_def_property_translation_context(prop, BLF_I18NCONTEXT_ID_SOUND);
+ RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_SOUND);
RNA_def_property_float_funcs(prop, NULL, "rna_Sequence_volume_set", NULL);
RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
@@ -1964,7 +2044,7 @@ static void rna_def_sound(BlenderRNA *brna)
RNA_def_property_float_sdna(prop, NULL, "pitch");
RNA_def_property_range(prop, 0.1f, 10.0f);
RNA_def_property_ui_text(prop, "Pitch", "Playback pitch of the sound");
- RNA_def_property_translation_context(prop, BLF_I18NCONTEXT_ID_SOUND);
+ RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_SOUND);
RNA_def_property_float_funcs(prop, NULL, "rna_Sequence_pitch_set", NULL);
RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
@@ -2225,6 +2305,67 @@ static void rna_def_gaussian_blur(StructRNA *srna)
RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
}
+static void rna_def_text(StructRNA *srna)
+{
+ static EnumPropertyItem text_align_x_items[] = {
+ {SEQ_TEXT_ALIGN_X_LEFT, "LEFT", 0, "Left", ""},
+ {SEQ_TEXT_ALIGN_X_CENTER, "CENTER", 0, "Center", ""},
+ {SEQ_TEXT_ALIGN_X_RIGHT, "RIGHT", 0, "Right", ""},
+ {0, NULL, 0, NULL, NULL}
+ };
+ static EnumPropertyItem text_align_y_items[] = {
+ {SEQ_TEXT_ALIGN_Y_TOP, "TOP", 0, "Top", ""},
+ {SEQ_TEXT_ALIGN_Y_CENTER, "CENTER", 0, "Center", ""},
+ {SEQ_TEXT_ALIGN_Y_BOTTOM, "BOTTOM", 0, "Bottom", ""},
+ {0, NULL, 0, NULL, NULL}
+ };
+
+ PropertyRNA *prop;
+
+ RNA_def_struct_sdna_from(srna, "TextVars", "effectdata");
+
+ prop = RNA_def_property(srna, "font_size", PROP_INT, PROP_UNSIGNED);
+ RNA_def_property_int_sdna(prop, NULL, "text_size");
+ RNA_def_property_ui_text(prop, "Size", "Size of the text");
+ RNA_def_property_ui_range(prop, 0.0f, 1000, 1, -1);
+ RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
+
+ prop = RNA_def_property(srna, "location", PROP_FLOAT, PROP_XYZ);
+ RNA_def_property_float_sdna(prop, NULL, "loc");
+ RNA_def_property_ui_text(prop, "Location", "Location of the text");
+ RNA_def_property_range(prop, -FLT_MAX, FLT_MAX);
+ RNA_def_property_ui_range(prop, 0.0, 1.0, 1, -1);
+ RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
+
+ prop = RNA_def_property(srna, "wrap_width", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "wrap_width");
+ RNA_def_property_ui_text(prop, "Wrap Width", "Word wrap width as factor, zero disables");
+ RNA_def_property_range(prop, 0, FLT_MAX);
+ RNA_def_property_ui_range(prop, 0.0, 1.0, 1, -1);
+ RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
+
+ prop = RNA_def_property(srna, "align_x", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "align");
+ RNA_def_property_enum_items(prop, text_align_x_items);
+ RNA_def_property_ui_text(prop, "Align X", "");
+ RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
+
+ prop = RNA_def_property(srna, "align_y", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "align_y");
+ RNA_def_property_enum_items(prop, text_align_y_items);
+ RNA_def_property_ui_text(prop, "Align Y", "");
+ RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
+
+ prop = RNA_def_property(srna, "text", PROP_STRING, PROP_NONE);
+ RNA_def_property_ui_text(prop, "Text", "Text that will be displayed");
+ RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
+
+ prop = RNA_def_property(srna, "use_shadow", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", SEQ_TEXT_SHADOW);
+ RNA_def_property_ui_text(prop, "Shadow", "Draw text with shadow");
+ RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
+}
+
static EffectInfo def_effects[] = {
{"AddSequence", "Add Sequence", "Add Sequence", NULL, 2},
{"AdjustmentSequence", "Adjustment Layer Sequence",
@@ -2249,6 +2390,8 @@ static EffectInfo def_effects[] = {
rna_def_wipe, 1},
{"GaussianBlurSequence", "Gaussian Blur Sequence", "Sequence strip creating a gaussian blur",
rna_def_gaussian_blur, 1},
+ {"TextSequence", "Text Sequence", "Sequence strip creating text",
+ rna_def_text, 0},
{"", "", "", NULL, 0}
};
diff --git a/source/blender/makesrna/intern/rna_sequencer_api.c b/source/blender/makesrna/intern/rna_sequencer_api.c
index 70370f1ae36..13fda02c7c8 100644
--- a/source/blender/makesrna/intern/rna_sequencer_api.c
+++ b/source/blender/makesrna/intern/rna_sequencer_api.c
@@ -42,8 +42,6 @@
//#include "DNA_anim_types.h"
#include "DNA_image_types.h"
-#include "DNA_scene_types.h"
-#include "DNA_sequence_types.h"
#include "DNA_mask_types.h"
#include "DNA_sound_types.h"
@@ -158,7 +156,7 @@ static Sequence *rna_Sequences_new_scene(ID *id, Editing *ed,
seq = alloc_generic_sequence(ed, name, frame_start, channel, SEQ_TYPE_SCENE, NULL);
seq->scene = sce_seq;
seq->len = sce_seq->r.efra - sce_seq->r.sfra + 1;
- seq->scene_sound = sound_scene_add_scene_sound(scene, seq, frame_start, frame_start + seq->len, 0);
+ seq->scene_sound = BKE_sound_scene_add_scene_sound(scene, seq, frame_start, frame_start + seq->len, 0);
id_us_plus((ID *)sce_seq);
BKE_sequence_calc_disp(scene, seq);
@@ -198,6 +196,7 @@ static Sequence *rna_Sequences_new_movie(ID *id, Editing *ed, ReportList *report
{
Scene *scene = (Scene *)id;
Sequence *seq;
+ StripAnim *sanim;
struct anim *an = openanim(file, IB_rect, 0, NULL);
@@ -207,7 +206,11 @@ static Sequence *rna_Sequences_new_movie(ID *id, Editing *ed, ReportList *report
}
seq = alloc_generic_sequence(ed, name, frame_start, channel, SEQ_TYPE_MOVIE, file);
- seq->anim = an;
+
+ sanim = MEM_mallocN(sizeof(StripAnim), "Strip Anim");
+ BLI_addtail(&seq->anims, sanim);
+ sanim->anim = an;
+
seq->anim_preseek = IMB_anim_get_preseek(an);
seq->len = IMB_anim_get_duration(an, IMB_TC_RECORD_RUN);
@@ -225,18 +228,19 @@ static Sequence *rna_Sequences_new_sound(ID *id, Editing *ed, Main *bmain, Repor
Scene *scene = (Scene *)id;
Sequence *seq;
- bSound *sound = sound_new_file(bmain, file);
+ bSound *sound = BKE_sound_new_file(bmain, file);
- if (sound == NULL || sound->playback_handle == NULL) {
+ if (sound->playback_handle == NULL) {
+ BKE_libblock_free(bmain, sound);
BKE_report(reports, RPT_ERROR, "Sequences.new_sound: unable to open sound file");
return NULL;
}
seq = alloc_generic_sequence(ed, name, frame_start, channel, SEQ_TYPE_SOUND_RAM, sound->name);
seq->sound = sound;
- seq->len = ceil((double)sound_get_length(sound) * FPS);
+ seq->len = ceil((double)BKE_sound_get_length(sound) * FPS);
- seq->scene_sound = sound_add_scene_sound(scene, seq, frame_start, frame_start + seq->len, 0);
+ seq->scene_sound = BKE_sound_add_scene_sound(scene, seq, frame_start, frame_start + seq->len, 0);
BKE_sequence_calc_disp(scene, seq);
@@ -313,6 +317,7 @@ static Sequence *rna_Sequences_new_effect(ID *id, Editing *ed, ReportList *repor
seq->flag |= SEQ_USE_EFFECT_DEFAULT_FADE;
+ BKE_sequence_calc(scene, seq);
BKE_sequence_calc_disp(scene, seq);
WM_main_add_notifier(NC_SCENE | ND_SEQUENCER, scene);
@@ -469,6 +474,7 @@ void RNA_api_sequences(BlenderRNA *brna, PropertyRNA *cprop)
{SEQ_TYPE_MULTICAM, "MULTICAM", 0, "Multicam Selector", ""},
{SEQ_TYPE_ADJUSTMENT, "ADJUSTMENT", 0, "Adjustment Layer", ""},
{SEQ_TYPE_GAUSSIAN_BLUR, "GAUSSIAN_BLUR", 0, "Gaussian Blur", ""},
+ {SEQ_TYPE_TEXT, "TEXT", 0, "Text", ""},
{0, NULL, 0, NULL, NULL}
};
@@ -484,8 +490,8 @@ void RNA_api_sequences(BlenderRNA *brna, PropertyRNA *cprop)
RNA_def_property_flag(parm, PROP_REQUIRED);
parm = RNA_def_pointer(func, "clip", "MovieClip", "", "Movie clip to add");
RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL);
- parm = RNA_def_int(func, "channel", 0, 0, MAXSEQ - 1, "Channel",
- "The channel for the new sequence", 0, MAXSEQ - 1);
+ parm = RNA_def_int(func, "channel", 0, 1, MAXSEQ, "Channel",
+ "The channel for the new sequence", 1, MAXSEQ);
RNA_def_property_flag(parm, PROP_REQUIRED);
parm = RNA_def_int(func, "frame_start", 0, -MAXFRAME, MAXFRAME, "",
"The start frame for the new sequence", -MAXFRAME, MAXFRAME);
@@ -501,8 +507,8 @@ void RNA_api_sequences(BlenderRNA *brna, PropertyRNA *cprop)
RNA_def_property_flag(parm, PROP_REQUIRED);
parm = RNA_def_pointer(func, "mask", "Mask", "", "Mask to add");
RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL);
- parm = RNA_def_int(func, "channel", 0, 0, MAXSEQ - 1, "Channel",
- "The channel for the new sequence", 0, MAXSEQ - 1);
+ parm = RNA_def_int(func, "channel", 0, 1, MAXSEQ, "Channel",
+ "The channel for the new sequence", 1, MAXSEQ);
RNA_def_property_flag(parm, PROP_REQUIRED);
parm = RNA_def_int(func, "frame_start", 0, -MAXFRAME, MAXFRAME, "",
"The start frame for the new sequence", -MAXFRAME, MAXFRAME);
@@ -518,8 +524,8 @@ void RNA_api_sequences(BlenderRNA *brna, PropertyRNA *cprop)
RNA_def_property_flag(parm, PROP_REQUIRED);
parm = RNA_def_pointer(func, "scene", "Scene", "", "Scene to add");
RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL);
- parm = RNA_def_int(func, "channel", 0, 0, MAXSEQ - 1, "Channel",
- "The channel for the new sequence", 0, MAXSEQ - 1);
+ parm = RNA_def_int(func, "channel", 0, 1, MAXSEQ, "Channel",
+ "The channel for the new sequence", 1, MAXSEQ);
RNA_def_property_flag(parm, PROP_REQUIRED);
parm = RNA_def_int(func, "frame_start", 0, -MAXFRAME, MAXFRAME, "",
"The start frame for the new sequence", -MAXFRAME, MAXFRAME);
@@ -535,8 +541,8 @@ void RNA_api_sequences(BlenderRNA *brna, PropertyRNA *cprop)
RNA_def_property_flag(parm, PROP_REQUIRED);
parm = RNA_def_string(func, "filepath", "File", 0, "", "Filepath to image");
RNA_def_property_flag(parm, PROP_REQUIRED);
- parm = RNA_def_int(func, "channel", 0, 0, MAXSEQ - 1, "Channel",
- "The channel for the new sequence", 0, MAXSEQ - 1);
+ parm = RNA_def_int(func, "channel", 0, 1, MAXSEQ, "Channel",
+ "The channel for the new sequence", 1, MAXSEQ);
RNA_def_property_flag(parm, PROP_REQUIRED);
parm = RNA_def_int(func, "frame_start", 0, -MAXFRAME, MAXFRAME, "",
"The start frame for the new sequence", -MAXFRAME, MAXFRAME);
@@ -552,8 +558,8 @@ void RNA_api_sequences(BlenderRNA *brna, PropertyRNA *cprop)
RNA_def_property_flag(parm, PROP_REQUIRED);
parm = RNA_def_string(func, "filepath", "File", 0, "", "Filepath to movie");
RNA_def_property_flag(parm, PROP_REQUIRED);
- parm = RNA_def_int(func, "channel", 0, 0, MAXSEQ - 1, "Channel",
- "The channel for the new sequence", 0, MAXSEQ - 1);
+ parm = RNA_def_int(func, "channel", 0, 1, MAXSEQ, "Channel",
+ "The channel for the new sequence", 1, MAXSEQ);
RNA_def_property_flag(parm, PROP_REQUIRED);
parm = RNA_def_int(func, "frame_start", 0, -MAXFRAME, MAXFRAME, "",
"The start frame for the new sequence", -MAXFRAME, MAXFRAME);
@@ -569,8 +575,8 @@ void RNA_api_sequences(BlenderRNA *brna, PropertyRNA *cprop)
RNA_def_property_flag(parm, PROP_REQUIRED);
parm = RNA_def_string(func, "filepath", "File", 0, "", "Filepath to movie");
RNA_def_property_flag(parm, PROP_REQUIRED);
- parm = RNA_def_int(func, "channel", 0, 0, MAXSEQ - 1, "Channel",
- "The channel for the new sequence", 0, MAXSEQ - 1);
+ parm = RNA_def_int(func, "channel", 0, 1, MAXSEQ, "Channel",
+ "The channel for the new sequence", 1, MAXSEQ);
RNA_def_property_flag(parm, PROP_REQUIRED);
parm = RNA_def_int(func, "frame_start", 0, -MAXFRAME, MAXFRAME, "",
"The start frame for the new sequence", -MAXFRAME, MAXFRAME);
@@ -587,8 +593,8 @@ void RNA_api_sequences(BlenderRNA *brna, PropertyRNA *cprop)
parm = RNA_def_enum(func, "type", seq_effect_items, 0, "Type",
"type for the new sequence");
RNA_def_property_flag(parm, PROP_REQUIRED);
- parm = RNA_def_int(func, "channel", 0, 0, MAXSEQ - 1, "Channel",
- "The channel for the new sequence", 0, MAXSEQ - 1);
+ parm = RNA_def_int(func, "channel", 0, 1, MAXSEQ, "Channel",
+ "The channel for the new sequence", 1, MAXSEQ);
/* don't use MAXFRAME since it makes importer scripts fail */
RNA_def_property_flag(parm, PROP_REQUIRED);
parm = RNA_def_int(func, "frame_start", 0, INT_MIN, INT_MAX, "",
diff --git a/source/blender/makesrna/intern/rna_smoke.c b/source/blender/makesrna/intern/rna_smoke.c
index 887670eb5ff..539f3c192be 100644
--- a/source/blender/makesrna/intern/rna_smoke.c
+++ b/source/blender/makesrna/intern/rna_smoke.c
@@ -165,6 +165,31 @@ static int rna_SmokeModifier_color_grid_get_length(PointerRNA *ptr, int length[R
return length[0];
}
+static int rna_SmokeModifier_velocity_grid_get_length(PointerRNA *ptr, int length[RNA_MAX_ARRAY_DIMENSION])
+{
+#ifdef WITH_SMOKE
+ SmokeDomainSettings *sds = (SmokeDomainSettings *)ptr->data;
+ float *vx = NULL;
+ float *vy = NULL;
+ float *vz = NULL;
+ int size = 0;
+
+ /* Velocity data is always low-resolution. */
+ if (sds->fluid) {
+ size = 3 * sds->res[0] * sds->res[1] * sds->res[2];
+ vx = smoke_get_velocity_x(sds->fluid);
+ vy = smoke_get_velocity_y(sds->fluid);
+ vz = smoke_get_velocity_z(sds->fluid);
+ }
+
+ length[0] = (vx && vy && vz) ? size : 0;
+#else
+ (void)ptr;
+ length[0] = 0;
+#endif
+ return length[0];
+}
+
static void rna_SmokeModifier_density_grid_get(PointerRNA *ptr, float *values)
{
#ifdef WITH_SMOKE
@@ -184,8 +209,34 @@ static void rna_SmokeModifier_density_grid_get(PointerRNA *ptr, float *values)
BLI_rw_mutex_unlock(sds->fluid_mutex);
#else
- (void)ptr;
- (void)values;
+ UNUSED_VARS(ptr, values);
+#endif
+}
+
+static void rna_SmokeModifier_velocity_grid_get(PointerRNA *ptr, float *values)
+{
+#ifdef WITH_SMOKE
+ SmokeDomainSettings *sds = (SmokeDomainSettings *)ptr->data;
+ int length[RNA_MAX_ARRAY_DIMENSION];
+ int size = rna_SmokeModifier_velocity_grid_get_length(ptr, length);
+ float *vx, *vy, *vz;
+ int i;
+
+ BLI_rw_mutex_lock(sds->fluid_mutex, THREAD_LOCK_READ);
+
+ vx = smoke_get_velocity_x(sds->fluid);
+ vy = smoke_get_velocity_y(sds->fluid);
+ vz = smoke_get_velocity_z(sds->fluid);
+
+ for (i = 0; i < size; i += 3) {
+ *(values++) = *(vx++);
+ *(values++) = *(vy++);
+ *(values++) = *(vz++);
+ }
+
+ BLI_rw_mutex_unlock(sds->fluid_mutex);
+#else
+ UNUSED_VARS(ptr, values);
#endif
}
@@ -211,8 +262,7 @@ static void rna_SmokeModifier_color_grid_get(PointerRNA *ptr, float *values)
BLI_rw_mutex_unlock(sds->fluid_mutex);
#else
- (void)ptr;
- memset(values, 0, 4 * sizeof(float));
+ UNUSED_VARS(ptr, values);
#endif
}
@@ -238,8 +288,7 @@ static void rna_SmokeModifier_flame_grid_get(PointerRNA *ptr, float *values)
BLI_rw_mutex_unlock(sds->fluid_mutex);
#else
- (void)ptr;
- (void)values;
+ UNUSED_VARS(ptr, values);
#endif
}
@@ -311,7 +360,7 @@ static void rna_def_smoke_domain_settings(BlenderRNA *brna)
prop = RNA_def_property(srna, "resolution_max", PROP_INT, PROP_NONE);
RNA_def_property_int_sdna(prop, NULL, "maxres");
- RNA_def_property_range(prop, 24, 512);
+ RNA_def_property_range(prop, 6, 512);
RNA_def_property_ui_range(prop, 24, 512, 2, -1);
RNA_def_property_ui_text(prop, "Max Res", "Maximal resolution used in the fluid domain");
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
@@ -453,6 +502,14 @@ static void rna_def_smoke_domain_settings(BlenderRNA *brna)
RNA_def_property_float_funcs(prop, "rna_SmokeModifier_density_grid_get", NULL, NULL);
RNA_def_property_ui_text(prop, "Density Grid", "Smoke density grid");
+ prop = RNA_def_property(srna, "velocity_grid", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_array(prop, 32);
+ RNA_def_property_flag(prop, PROP_DYNAMIC);
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_property_dynamic_array_funcs(prop, "rna_SmokeModifier_velocity_grid_get_length");
+ RNA_def_property_float_funcs(prop, "rna_SmokeModifier_velocity_grid_get", NULL, NULL);
+ RNA_def_property_ui_text(prop, "Velocity Grid", "Smoke velocity grid");
+
prop = RNA_def_property(srna, "flame_grid", PROP_FLOAT, PROP_NONE);
RNA_def_property_array(prop, 32);
RNA_def_property_flag(prop, PROP_DYNAMIC);
diff --git a/source/blender/makesrna/intern/rna_sound.c b/source/blender/makesrna/intern/rna_sound.c
index 206a72a01b0..25b3475c423 100644
--- a/source/blender/makesrna/intern/rna_sound.c
+++ b/source/blender/makesrna/intern/rna_sound.c
@@ -38,10 +38,11 @@
#include "BKE_sound.h"
#include "BKE_context.h"
+#include "BKE_sequencer.h"
static void rna_Sound_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr)
{
- sound_load(bmain, (bSound *)ptr->data);
+ BKE_sound_load(bmain, (bSound *)ptr->data);
}
static int rna_Sound_caching_get(PointerRNA *ptr)
@@ -54,14 +55,14 @@ static void rna_Sound_caching_set(PointerRNA *ptr, const int value)
{
bSound *sound = (bSound *)(ptr->data);
if (value)
- sound_cache(sound);
+ BKE_sound_cache(sound);
else
- sound_delete_cache(sound);
+ BKE_sound_delete_cache(sound);
}
-static void rna_Sound_caching_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr)
+static void rna_Sound_caching_update(Main *UNUSED(bmain), Scene *scene, PointerRNA *ptr)
{
- sound_update_sequencer(bmain, (bSound *)(ptr->data));
+ BKE_sequencer_update_sound(scene, (bSound *)(ptr->data));
}
#else
@@ -97,6 +98,8 @@ static void rna_def_sound(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Mono",
"If the file contains multiple audio channels they are rendered to a single one");
RNA_def_property_update(prop, 0, "rna_Sound_update");
+
+ RNA_api_sound(srna);
}
void RNA_def_sound(BlenderRNA *brna)
diff --git a/source/blender/makesrna/intern/rna_sound_api.c b/source/blender/makesrna/intern/rna_sound_api.c
new file mode 100644
index 00000000000..0164daa98d0
--- /dev/null
+++ b/source/blender/makesrna/intern/rna_sound_api.c
@@ -0,0 +1,73 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2015 by the Blender Foundation.
+ * All rights reserved.
+ *
+ * Contributor(s): Kevin Dietrich
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/makesrna/intern/rna_sound_api.c
+ * \ingroup RNA
+ */
+
+#include "DNA_packedFile_types.h"
+
+#include "RNA_define.h"
+#include "RNA_enum_types.h"
+
+#include "rna_internal.h"
+
+#ifdef RNA_RUNTIME
+
+#include "BKE_packedFile.h"
+
+static void rna_Sound_pack(bSound *sound, Main *bmain, ReportList *reports)
+{
+ sound->packedfile = newPackedFile(reports, sound->name, ID_BLEND_PATH(bmain, &sound->id));
+}
+
+static void rna_Sound_unpack(bSound *sound, Main *bmain, ReportList *reports, int method)
+{
+ if (!sound->packedfile) {
+ BKE_report(reports, RPT_ERROR, "Sound not packed");
+ }
+ else {
+ /* reports its own error on failure */
+ unpackSound(bmain, reports, sound, method);
+ }
+}
+
+#else
+
+void RNA_api_sound(StructRNA *srna)
+{
+ FunctionRNA *func;
+
+ func = RNA_def_function(srna, "pack", "rna_Sound_pack");
+ RNA_def_function_ui_description(func, "Pack the sound into the current blend file");
+ RNA_def_function_flag(func, FUNC_USE_REPORTS | FUNC_USE_MAIN);
+
+ func = RNA_def_function(srna, "unpack", "rna_Sound_unpack");
+ RNA_def_function_ui_description(func, "Unpack the sound to the samples filename");
+ RNA_def_function_flag(func, FUNC_USE_REPORTS | FUNC_USE_MAIN);
+ RNA_def_enum(func, "method", unpack_method_items, PF_USE_LOCAL, "method", "How to unpack");
+}
+
+#endif
diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c
index 5ca38aae9bc..cee98261e23 100644
--- a/source/blender/makesrna/intern/rna_space.c
+++ b/source/blender/makesrna/intern/rna_space.c
@@ -29,8 +29,9 @@
#include "MEM_guardedalloc.h"
-#include "BLF_translation.h"
+#include "BLT_translation.h"
+#include "BKE_image.h"
#include "BKE_key.h"
#include "BKE_movieclip.h"
#include "BKE_node.h"
@@ -87,6 +88,41 @@ EnumPropertyItem space_type_items[] = {
{0, NULL, 0, NULL, NULL}
};
+#define V3D_S3D_CAMERA_LEFT {STEREO_LEFT_ID, "LEFT", ICON_RESTRICT_RENDER_OFF, "Left", ""},
+#define V3D_S3D_CAMERA_RIGHT {STEREO_RIGHT_ID, "RIGHT", ICON_RESTRICT_RENDER_OFF, "Right", ""},
+#define V3D_S3D_CAMERA_S3D {STEREO_3D_ID, "S3D", ICON_CAMERA_STEREO, "3D", ""},
+#ifdef RNA_RUNTIME
+#define V3D_S3D_CAMERA_VIEWS {STEREO_MONO_ID, "MONO", ICON_RESTRICT_RENDER_OFF, "Views", ""},
+#endif
+
+static EnumPropertyItem stereo3d_camera_items[] = {
+ V3D_S3D_CAMERA_LEFT
+ V3D_S3D_CAMERA_RIGHT
+ V3D_S3D_CAMERA_S3D
+ {0, NULL, 0, NULL, NULL}
+};
+
+#ifdef RNA_RUNTIME
+static EnumPropertyItem multiview_camera_items[] = {
+ V3D_S3D_CAMERA_VIEWS
+ V3D_S3D_CAMERA_S3D
+ {0, NULL, 0, NULL, NULL}
+};
+#endif
+
+#undef V3D_S3D_CAMERA_LEFT
+#undef V3D_S3D_CAMERA_RIGHT
+#undef V3D_S3D_CAMERA_S3D
+#undef V3D_S3D_CAMERA_VIEWS
+
+#ifndef RNA_RUNTIME
+static EnumPropertyItem stereo3d_eye_items[] = {
+ {STEREO_LEFT_ID, "LEFT_EYE", ICON_NONE, "Left Eye"},
+ {STEREO_RIGHT_ID, "RIGHT_EYE", ICON_NONE, "Right Eye"},
+ {0, NULL, 0, NULL, NULL}
+};
+#endif
+
static EnumPropertyItem pivot_items_full[] = {
{V3D_CENTER, "BOUNDING_BOX_CENTER", ICON_ROTATE, "Bounding Box Center",
"Pivot around bounding box center of selected object(s)"},
@@ -183,10 +219,27 @@ static EnumPropertyItem buttons_texture_context_items[] = {
{0, NULL, 0, NULL, NULL}
};
+
+static EnumPropertyItem fileselectparams_recursion_level_items[] = {
+ {0, "NONE", 0, "None", "Only list current directory's content, with no recursion"},
+ {1, "BLEND", 0, "Blend File", "List .blend files' content"},
+ {2, "ALL_1", 0, "One Level", "List all sub-directories' content, one level of recursion"},
+ {3, "ALL_2", 0, "Two Levels", "List all sub-directories' content, two levels of recursion"},
+ {4, "ALL_3", 0, "Three Levels", "List all sub-directories' content, three levels of recursion"},
+ {0, NULL, 0, NULL, NULL}
+};
+
+EnumPropertyItem file_sort_items[] = {
+ {FILE_SORT_ALPHA, "FILE_SORT_ALPHA", ICON_SORTALPHA, "Sort alphabetically", "Sort the file list alphabetically"},
+ {FILE_SORT_EXTENSION, "FILE_SORT_EXTENSION", ICON_SORTBYEXT, "Sort by extension", "Sort the file list by extension/type"},
+ {FILE_SORT_TIME, "FILE_SORT_TIME", ICON_SORTTIME, "Sort by time", "Sort files by modification time"},
+ {FILE_SORT_SIZE, "FILE_SORT_SIZE", ICON_SORTSIZE, "Sort by size", "Sort files by size"},
+ {0, NULL, 0, NULL, NULL}
+};
+
#ifdef RNA_RUNTIME
#include "DNA_anim_types.h"
-#include "DNA_mask_types.h"
#include "DNA_scene_types.h"
#include "DNA_screen_types.h"
#include "DNA_userdef_types.h"
@@ -198,12 +251,14 @@ static EnumPropertyItem buttons_texture_context_items[] = {
#include "BKE_colortools.h"
#include "BKE_context.h"
#include "BKE_depsgraph.h"
+#include "BKE_nla.h"
#include "BKE_paint.h"
#include "BKE_scene.h"
#include "BKE_screen.h"
#include "BKE_icons.h"
#include "ED_buttons.h"
+#include "ED_fileselect.h"
#include "ED_image.h"
#include "ED_node.h"
#include "ED_screen.h"
@@ -266,13 +321,7 @@ static ScrArea *rna_area_from_space(PointerRNA *ptr)
{
bScreen *sc = (bScreen *)ptr->id.data;
SpaceLink *link = (SpaceLink *)ptr->data;
- ScrArea *sa;
-
- for (sa = sc->areabase.first; sa; sa = sa->next)
- if (BLI_findindex(&sa->spacedata, link) != -1)
- return sa;
-
- return NULL;
+ return BKE_screen_find_area_from_space(sc, link);
}
static void area_region_from_regiondata(bScreen *sc, void *regiondata, ScrArea **r_sa, ARegion **r_ar)
@@ -415,8 +464,8 @@ static void rna_SpaceView3D_lock_camera_and_layers_set(PointerRNA *ptr, int valu
/* seek for layact */
bit = 0;
while (bit < 32) {
- if (v3d->lay & (1 << bit)) {
- v3d->layact = 1 << bit;
+ if (v3d->lay & (1u << bit)) {
+ v3d->layact = (1u << bit);
break;
}
bit++;
@@ -485,7 +534,7 @@ static void rna_SpaceView3D_matcap_update(Main *UNUSED(bmain), Scene *UNUSED(sce
BKE_previewimg_free(&ma->preview);
if (ma->gpumaterial.first)
- GPU_material_free(ma);
+ GPU_material_free(&ma->gpumaterial);
WM_main_add_notifier(NC_MATERIAL | ND_SHADING_DRAW, ma);
}
@@ -495,8 +544,11 @@ static void rna_SpaceView3D_matcap_enable(Main *UNUSED(bmain), Scene *UNUSED(sce
{
View3D *v3d = (View3D *)(ptr->data);
- if (v3d->matcap_icon == 0)
+ if (v3d->matcap_icon < ICON_MATCAP_01 ||
+ v3d->matcap_icon > ICON_MATCAP_24)
+ {
v3d->matcap_icon = ICON_MATCAP_01;
+ }
}
static void rna_SpaceView3D_pivot_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr)
@@ -658,6 +710,17 @@ static EnumPropertyItem *rna_SpaceView3D_viewport_shade_itemf(bContext *UNUSED(C
return item;
}
+static EnumPropertyItem *rna_SpaceView3D_stereo3d_camera_itemf(bContext *UNUSED(C), PointerRNA *ptr,
+ PropertyRNA *UNUSED(prop), bool *UNUSED(r_free))
+{
+ Scene *scene = ((bScreen *)ptr->id.data)->scene;
+
+ if (scene->r.views_format == SCE_VIEWS_FORMAT_MULTIVIEW)
+ return multiview_camera_items;
+ else
+ return stereo3d_camera_items;
+}
+
/* Space Image Editor */
static PointerRNA rna_SpaceImageEditor_uvedit_get(PointerRNA *ptr)
@@ -667,7 +730,39 @@ static PointerRNA rna_SpaceImageEditor_uvedit_get(PointerRNA *ptr)
static void rna_SpaceImageEditor_mode_update(Main *bmain, Scene *scene, PointerRNA *UNUSED(ptr))
{
- ED_space_image_paint_update(bmain->wm.first, scene->toolsettings);
+ ED_space_image_paint_update(bmain->wm.first, scene);
+}
+
+
+static void rna_SpaceImageEditor_show_stereo_set(PointerRNA *ptr, int value)
+{
+ SpaceImage *sima = (SpaceImage *)(ptr->data);
+
+ if (value)
+ sima->iuser.flag |= IMA_SHOW_STEREO;
+ else
+ sima->iuser.flag &= ~IMA_SHOW_STEREO;
+}
+
+static int rna_SpaceImageEditor_show_stereo_get(PointerRNA *ptr)
+{
+ SpaceImage *sima = (SpaceImage *)(ptr->data);
+ return (sima->iuser.flag & IMA_SHOW_STEREO) != 0;
+}
+
+static void rna_SpaceImageEditor_show_stereo_update(Main *UNUSED(bmain), Scene *UNUSED(unused), PointerRNA *ptr)
+{
+ SpaceImage *sima = (SpaceImage *)(ptr->data);
+ Image *ima = sima->image;
+
+ if (ima) {
+ if (ima->rr) {
+ BKE_image_multilayer_index(ima->rr, &sima->iuser);
+ }
+ else {
+ BKE_image_multiview_index(ima, &sima->iuser);
+ }
+ }
}
static int rna_SpaceImageEditor_show_render_get(PointerRNA *ptr)
@@ -797,7 +892,25 @@ static void rna_SpaceImageEditor_cursor_location_set(PointerRNA *ptr, const floa
}
}
-static void rna_SpaceImageEditor_scopes_update(Main *UNUSED(bmain), Scene *scene, PointerRNA *ptr)
+static void rna_SpaceImageEditor_image_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
+{
+ SpaceImage *sima = (SpaceImage *)ptr->data;
+ Image *ima = sima->image;
+
+ /* make sure all the iuser settings are valid for the sima image */
+ if (ima) {
+ if (ima->rr) {
+ if (BKE_image_multilayer_index(sima->image->rr, &sima->iuser) == NULL) {
+ BKE_image_init_imageuser(sima->image, &sima->iuser);
+ }
+ }
+ else {
+ BKE_image_multiview_index(ima, &sima->iuser);
+ }
+ }
+}
+
+static void rna_SpaceImageEditor_scopes_update(struct bContext *C, struct PointerRNA *ptr)
{
SpaceImage *sima = (SpaceImage *)ptr->data;
ImBuf *ibuf;
@@ -805,7 +918,7 @@ static void rna_SpaceImageEditor_scopes_update(Main *UNUSED(bmain), Scene *scene
ibuf = ED_space_image_acquire_buffer(sima, &lock);
if (ibuf) {
- scopes_update(&sima->scopes, ibuf, &scene->view_settings, &scene->display_settings);
+ ED_space_image_scopes_update(C, sima, ibuf, true);
WM_main_add_notifier(NC_IMAGE, sima->image);
}
ED_space_image_release_buffer(sima, ibuf, lock);
@@ -818,6 +931,8 @@ static EnumPropertyItem *rna_SpaceImageEditor_pivot_itemf(bContext *UNUSED(C), P
{V3D_CENTER, "CENTER", ICON_ROTATE, "Bounding Box Center", ""},
{V3D_CENTROID, "MEDIAN", ICON_ROTATECENTER, "Median Point", ""},
{V3D_CURSOR, "CURSOR", ICON_CURSOR, "2D Cursor", ""},
+ {V3D_LOCAL, "INDIVIDUAL_ORIGINS", ICON_ROTATECOLLECTION,
+ "Individual Origins", "Pivot around each object's own origin"},
{0, NULL, 0, NULL, NULL}
};
@@ -856,7 +971,6 @@ static void rna_SpaceTextEditor_updateEdited(Main *UNUSED(bmain), Scene *UNUSED(
WM_main_add_notifier(NC_TEXT | NA_EDITED, st->text);
}
-
/* Space Properties */
/* note: this function exists only to avoid id refcounting */
@@ -1117,24 +1231,60 @@ static void rna_SpaceDopeSheetEditor_action_update(Main *UNUSED(bmain), Scene *s
if (saction->mode == SACTCONT_ACTION) {
/* TODO: context selector could help decide this with more control? */
- adt = BKE_id_add_animdata(&obact->id); /* this only adds if non-existant */
+ adt = BKE_animdata_add_id(&obact->id); /* this only adds if non-existent */
}
else if (saction->mode == SACTCONT_SHAPEKEY) {
Key *key = BKE_key_from_object(obact);
if (key)
- adt = BKE_id_add_animdata(&key->id); /* this only adds if non-existant */
+ adt = BKE_animdata_add_id(&key->id); /* this only adds if non-existent */
}
/* set action */
+ // FIXME: this overlaps a lot with the BKE_animdata_set_action() API method
if (adt) {
- /* fix id-count of action we're replacing */
- id_us_min(&adt->action->id);
-
- /* show new id-count of action we're replacing */
- adt->action = saction->action;
- id_us_plus(&adt->action->id);
+ /* Don't do anything if old and new actions are the same... */
+ if (adt->action != saction->action) {
+ /* NLA Tweak Mode needs special handling... */
+ if (adt->flag & ADT_NLA_EDIT_ON) {
+ /* Exit editmode first - we cannot change actions while in tweakmode
+ * NOTE: This will clear the action ref properly
+ */
+ BKE_nla_tweakmode_exit(adt);
+
+ /* Assign new action, and adjust the usercounts accordingly */
+ adt->action = saction->action;
+ id_us_plus((ID *)adt->action);
+ }
+ else {
+ /* Handle old action... */
+ if (adt->action) {
+ /* Fix id-count of action we're replacing */
+ id_us_min(&adt->action->id);
+
+ /* To prevent data loss (i.e. if users flip between actions using the Browse menu),
+ * stash this action if nothing else uses it.
+ *
+ * EXCEPTION:
+ * This callback runs when unlinking actions. In that case, we don't want to
+ * stash the action, as the user is signalling that they want to detach it.
+ * This can be reviewed again later, but it could get annoying if we keep these instead.
+ */
+ if ((adt->action->id.us <= 0) && (saction->action != NULL)) {
+ /* XXX: Things here get dodgy if this action is only partially completed,
+ * and the user then uses the browse menu to get back to this action,
+ * assigning it as the active action (i.e. the stash strip gets out of sync)
+ */
+ BKE_nla_action_stash(adt);
+ }
+ }
+
+ /* Assign new action, and adjust the usercounts accordingly */
+ adt->action = saction->action;
+ id_us_plus((ID *)adt->action);
+ }
+ }
- /* force update of animdata */
+ /* Force update of animdata */
adt->recalc |= ADT_RECALC_ANIM;
}
@@ -1214,6 +1364,19 @@ static void rna_BackgroundImage_opacity_set(PointerRNA *ptr, float value)
bgpic->blend = 1.0f - value;
}
+/* radius internally (expose as a distance value) */
+static float rna_BackgroundImage_size_get(PointerRNA *ptr)
+{
+ BGpic *bgpic = ptr->data;
+ return bgpic->size * 2.0f;
+}
+
+static void rna_BackgroundImage_size_set(PointerRNA *ptr, float value)
+{
+ BGpic *bgpic = ptr->data;
+ bgpic->size = value * 0.5f;
+}
+
static BGpic *rna_BackgroundImage_new(View3D *v3d)
{
BGpic *bgpic = ED_view3D_background_image_new(v3d);
@@ -1256,7 +1419,7 @@ static int rna_SpaceNodeEditor_node_tree_poll(PointerRNA *ptr, const PointerRNA
bNodeTree *ntree = (bNodeTree *)value.data;
/* node tree type must match the selected type in node editor */
- return (strcmp(snode->tree_idname, ntree->idname) == 0);
+ return (STREQ(snode->tree_idname, ntree->idname));
}
static void rna_SpaceNodeEditor_node_tree_update(const bContext *C, PointerRNA *UNUSED(ptr))
@@ -1375,6 +1538,302 @@ static void rna_SpaceClipEditor_view_type_update(Main *UNUSED(bmain), Scene *UNU
ED_area_tag_refresh(sa);
}
+/* File browser. */
+
+static int rna_FileSelectParams_use_lib_get(PointerRNA *ptr)
+{
+ FileSelectParams *params = ptr->data;
+
+ return params && (params->type == FILE_LOADLIB);
+}
+
+static EnumPropertyItem *rna_FileSelectParams_recursion_level_itemf(
+ bContext *UNUSED(C), PointerRNA *ptr, PropertyRNA *UNUSED(prop), bool *r_free)
+{
+ FileSelectParams *params = ptr->data;
+
+ if (params && params->type != FILE_LOADLIB) {
+ EnumPropertyItem *item = NULL;
+ int totitem = 0;
+
+ RNA_enum_items_add_value(&item, &totitem, fileselectparams_recursion_level_items, 0);
+ RNA_enum_items_add_value(&item, &totitem, fileselectparams_recursion_level_items, 2);
+ RNA_enum_items_add_value(&item, &totitem, fileselectparams_recursion_level_items, 3);
+ RNA_enum_items_add_value(&item, &totitem, fileselectparams_recursion_level_items, 4);
+
+ RNA_enum_item_end(&item, &totitem);
+ *r_free = true;
+
+ return item;
+ }
+
+ *r_free = false;
+ return fileselectparams_recursion_level_items;
+}
+
+static void rna_FileBrowser_FSMenuEntry_path_get(PointerRNA *ptr, char *value)
+{
+ char *path = ED_fsmenu_entry_get_path(ptr->data);
+
+ strcpy(value, path ? path : "");
+}
+
+static int rna_FileBrowser_FSMenuEntry_path_length(PointerRNA *ptr)
+{
+ char *path = ED_fsmenu_entry_get_path(ptr->data);
+
+ return (int)(path ? strlen(path) : 0);
+}
+
+static void rna_FileBrowser_FSMenuEntry_path_set(PointerRNA *ptr, const char *value)
+{
+ FSMenuEntry *fsm = ptr->data;
+
+ /* Note: this will write to file immediately.
+ * Not nice (and to be fixed ultimately), but acceptable in this case for now. */
+ ED_fsmenu_entry_set_path(fsm, value);
+}
+
+static void rna_FileBrowser_FSMenuEntry_name_get(PointerRNA *ptr, char *value)
+{
+ strcpy(value, ED_fsmenu_entry_get_name(ptr->data));
+}
+
+static int rna_FileBrowser_FSMenuEntry_name_length(PointerRNA *ptr)
+{
+ return (int)strlen(ED_fsmenu_entry_get_name(ptr->data));
+}
+
+static void rna_FileBrowser_FSMenuEntry_name_set(PointerRNA *ptr, const char *value)
+{
+ FSMenuEntry *fsm = ptr->data;
+
+ /* Note: this will write to file immediately.
+ * Not nice (and to be fixed ultimately), but acceptable in this case for now. */
+ ED_fsmenu_entry_set_name(fsm, value);
+}
+
+static int rna_FileBrowser_FSMenuEntry_name_get_editable(PointerRNA *ptr)
+{
+ FSMenuEntry *fsm = ptr->data;
+
+ return fsm->save;
+}
+
+static void rna_FileBrowser_FSMenu_next(CollectionPropertyIterator *iter)
+{
+ ListBaseIterator *internal = &iter->internal.listbase;
+
+ if (internal->skip) {
+ do {
+ internal->link = (Link *)(((FSMenuEntry *)(internal->link))->next);
+ iter->valid = (internal->link != NULL);
+ } while (iter->valid && internal->skip(iter, internal->link));
+ }
+ else {
+ internal->link = (Link *)(((FSMenuEntry *)(internal->link))->next);
+ iter->valid = (internal->link != NULL);
+ }
+}
+
+static void rna_FileBrowser_FSMenu_begin(CollectionPropertyIterator *iter, FSMenuCategory category)
+{
+ ListBaseIterator *internal = &iter->internal.listbase;
+
+ struct FSMenu *fsmenu = ED_fsmenu_get();
+ struct FSMenuEntry *fsmentry = ED_fsmenu_get_category(fsmenu, category);
+
+ internal->link = (fsmentry) ? (Link *)fsmentry : NULL;
+ internal->skip = NULL;
+
+ iter->valid = (internal->link != NULL);
+}
+
+static PointerRNA rna_FileBrowser_FSMenu_get(CollectionPropertyIterator *iter)
+{
+ ListBaseIterator *internal = &iter->internal.listbase;
+ PointerRNA r_ptr;
+
+ RNA_pointer_create(NULL, &RNA_FileBrowserFSMenuEntry, internal->link, &r_ptr);
+
+ return r_ptr;
+}
+
+static void rna_FileBrowser_FSMenu_end(CollectionPropertyIterator *UNUSED(iter))
+{
+}
+
+static void rna_FileBrowser_FSMenuSystem_data_begin(CollectionPropertyIterator *iter, PointerRNA *UNUSED(ptr))
+{
+ rna_FileBrowser_FSMenu_begin(iter, FS_CATEGORY_SYSTEM);
+}
+
+static int rna_FileBrowser_FSMenuSystem_data_length(PointerRNA *UNUSED(ptr))
+{
+ struct FSMenu *fsmenu = ED_fsmenu_get();
+
+ return ED_fsmenu_get_nentries(fsmenu, FS_CATEGORY_SYSTEM);
+}
+
+static void rna_FileBrowser_FSMenuSystemBookmark_data_begin(CollectionPropertyIterator *iter, PointerRNA *UNUSED(ptr))
+{
+ rna_FileBrowser_FSMenu_begin(iter, FS_CATEGORY_SYSTEM_BOOKMARKS);
+}
+
+static int rna_FileBrowser_FSMenuSystemBookmark_data_length(PointerRNA *UNUSED(ptr))
+{
+ struct FSMenu *fsmenu = ED_fsmenu_get();
+
+ return ED_fsmenu_get_nentries(fsmenu, FS_CATEGORY_SYSTEM_BOOKMARKS);
+}
+
+static void rna_FileBrowser_FSMenuBookmark_data_begin(CollectionPropertyIterator *iter, PointerRNA *UNUSED(ptr))
+{
+ rna_FileBrowser_FSMenu_begin(iter, FS_CATEGORY_BOOKMARKS);
+}
+
+static int rna_FileBrowser_FSMenuBookmark_data_length(PointerRNA *UNUSED(ptr))
+{
+ struct FSMenu *fsmenu = ED_fsmenu_get();
+
+ return ED_fsmenu_get_nentries(fsmenu, FS_CATEGORY_BOOKMARKS);
+}
+
+static void rna_FileBrowser_FSMenuRecent_data_begin(CollectionPropertyIterator *iter, PointerRNA *UNUSED(ptr))
+{
+ rna_FileBrowser_FSMenu_begin(iter, FS_CATEGORY_RECENT);
+}
+
+static int rna_FileBrowser_FSMenuRecent_data_length(PointerRNA *UNUSED(ptr))
+{
+ struct FSMenu *fsmenu = ED_fsmenu_get();
+
+ return ED_fsmenu_get_nentries(fsmenu, FS_CATEGORY_RECENT);
+}
+
+static int rna_FileBrowser_FSMenu_active_get(PointerRNA *ptr, const FSMenuCategory category)
+{
+ SpaceFile *sf = ptr->data;
+ int actnr = -1;
+
+ switch (category) {
+ case FS_CATEGORY_SYSTEM:
+ actnr = sf->systemnr;
+ break;
+ case FS_CATEGORY_SYSTEM_BOOKMARKS:
+ actnr = sf->system_bookmarknr;
+ break;
+ case FS_CATEGORY_BOOKMARKS:
+ actnr = sf->bookmarknr;
+ break;
+ case FS_CATEGORY_RECENT:
+ actnr = sf->recentnr;
+ break;
+ }
+
+ return actnr;
+}
+
+static void rna_FileBrowser_FSMenu_active_set(PointerRNA *ptr, int value, const FSMenuCategory category)
+{
+ SpaceFile *sf = ptr->data;
+ struct FSMenu *fsmenu = ED_fsmenu_get();
+ FSMenuEntry *fsm = ED_fsmenu_get_entry(fsmenu, category, value);
+
+ if (fsm && sf->params) {
+ switch (category) {
+ case FS_CATEGORY_SYSTEM:
+ sf->systemnr = value;
+ break;
+ case FS_CATEGORY_SYSTEM_BOOKMARKS:
+ sf->system_bookmarknr = value;
+ break;
+ case FS_CATEGORY_BOOKMARKS:
+ sf->bookmarknr = value;
+ break;
+ case FS_CATEGORY_RECENT:
+ sf->recentnr = value;
+ break;
+ }
+
+ BLI_strncpy(sf->params->dir, fsm->path, sizeof(sf->params->dir));
+ }
+}
+
+static void rna_FileBrowser_FSMenu_active_range(
+ PointerRNA *UNUSED(ptr), int *min, int *max, int *softmin, int *softmax, const FSMenuCategory category)
+{
+ struct FSMenu *fsmenu = ED_fsmenu_get();
+
+ *min = *softmin = -1;
+ *max = *softmax = ED_fsmenu_get_nentries(fsmenu, category) - 1;
+}
+
+static void rna_FileBrowser_FSMenu_active_update(struct bContext *C, PointerRNA *UNUSED(ptr))
+{
+ ED_file_change_dir(C, true);
+}
+
+static int rna_FileBrowser_FSMenuSystem_active_get(PointerRNA *ptr)
+{
+ return rna_FileBrowser_FSMenu_active_get(ptr, FS_CATEGORY_SYSTEM);
+}
+
+static void rna_FileBrowser_FSMenuSystem_active_set(PointerRNA *ptr, int value)
+{
+ rna_FileBrowser_FSMenu_active_set(ptr, value, FS_CATEGORY_SYSTEM);
+}
+
+static void rna_FileBrowser_FSMenuSystem_active_range(PointerRNA *ptr, int *min, int *max, int *softmin, int *softmax)
+{
+ rna_FileBrowser_FSMenu_active_range(ptr, min, max, softmin, softmax, FS_CATEGORY_SYSTEM);
+}
+
+static int rna_FileBrowser_FSMenuSystemBookmark_active_get(PointerRNA *ptr)
+{
+ return rna_FileBrowser_FSMenu_active_get(ptr, FS_CATEGORY_SYSTEM_BOOKMARKS);
+}
+
+static void rna_FileBrowser_FSMenuSystemBookmark_active_set(PointerRNA *ptr, int value)
+{
+ rna_FileBrowser_FSMenu_active_set(ptr, value, FS_CATEGORY_SYSTEM_BOOKMARKS);
+}
+
+static void rna_FileBrowser_FSMenuSystemBookmark_active_range(PointerRNA *ptr, int *min, int *max, int *softmin, int *softmax)
+{
+ rna_FileBrowser_FSMenu_active_range(ptr, min, max, softmin, softmax, FS_CATEGORY_SYSTEM_BOOKMARKS);
+}
+
+static int rna_FileBrowser_FSMenuBookmark_active_get(PointerRNA *ptr)
+{
+ return rna_FileBrowser_FSMenu_active_get(ptr, FS_CATEGORY_BOOKMARKS);
+}
+
+static void rna_FileBrowser_FSMenuBookmark_active_set(PointerRNA *ptr, int value)
+{
+ rna_FileBrowser_FSMenu_active_set(ptr, value, FS_CATEGORY_BOOKMARKS);
+}
+
+static void rna_FileBrowser_FSMenuBookmark_active_range(PointerRNA *ptr, int *min, int *max, int *softmin, int *softmax)
+{
+ rna_FileBrowser_FSMenu_active_range(ptr, min, max, softmin, softmax, FS_CATEGORY_BOOKMARKS);
+}
+
+static int rna_FileBrowser_FSMenuRecent_active_get(PointerRNA *ptr)
+{
+ return rna_FileBrowser_FSMenu_active_get(ptr, FS_CATEGORY_RECENT);
+}
+
+static void rna_FileBrowser_FSMenuRecent_active_set(PointerRNA *ptr, int value)
+{
+ rna_FileBrowser_FSMenu_active_set(ptr, value, FS_CATEGORY_RECENT);
+}
+
+static void rna_FileBrowser_FSMenuRecent_active_range(PointerRNA *ptr, int *min, int *max, int *softmin, int *softmax)
+{
+ rna_FileBrowser_FSMenu_active_range(ptr, min, max, softmin, softmax, FS_CATEGORY_RECENT);
+}
+
#else
static EnumPropertyItem dt_uv_items[] = {
@@ -1518,6 +1977,11 @@ static void rna_def_space_image_uv(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Draw Other Objects", "Draw other selected objects that share the same image");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_IMAGE, NULL);
+ prop = RNA_def_property(srna, "show_metadata", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", SI_DRAW_METADATA);
+ RNA_def_property_ui_text(prop, "Show Metadata", "Draw metadata properties of the image");
+ RNA_def_property_update(prop, NC_SPACE | ND_SPACE_IMAGE, NULL);
+
prop = RNA_def_property(srna, "show_texpaint", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", SI_NO_DRAW_TEXPAINT);
RNA_def_property_ui_text(prop, "Draw Texture Paint UVs", "Draw overlay of texture paint uv layer");
@@ -1572,6 +2036,8 @@ static void rna_def_space_outliner(BlenderRNA *brna)
{SO_LIBRARIES, "LIBRARIES", 0, "Blender File", "Display data of current file and linked libraries"},
{SO_DATABLOCKS, "DATABLOCKS", 0, "Datablocks", "Display all raw datablocks"},
{SO_USERDEF, "USER_PREFERENCES", 0, "User Preferences", "Display the user preference datablocks"},
+ {SO_ID_ORPHANS, "ORPHAN_DATA", 0, "Orphan Data",
+ "Display datablocks which are unused and/or will be lost when the file is reloaded"},
{0, NULL, 0, NULL, NULL}
};
@@ -1588,6 +2054,7 @@ static void rna_def_space_outliner(BlenderRNA *brna)
prop = RNA_def_property(srna, "filter_text", PROP_STRING, PROP_NONE);
RNA_def_property_string_sdna(prop, NULL, "search_string");
RNA_def_property_ui_text(prop, "Display Filter", "Live search filtering string");
+ RNA_def_property_flag(prop, PROP_TEXTEDIT_UPDATE);
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_OUTLINER, NULL);
prop = RNA_def_property(srna, "use_filter_case_sensitive", PROP_BOOLEAN, PROP_NONE);
@@ -1599,7 +2066,12 @@ static void rna_def_space_outliner(BlenderRNA *brna)
RNA_def_property_boolean_sdna(prop, NULL, "search_flags", SO_FIND_COMPLETE);
RNA_def_property_ui_text(prop, "Complete Matches Only", "Only use complete matches of search string");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_OUTLINER, NULL);
-
+
+ prop = RNA_def_property(srna, "use_sort_alpha", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", SO_SKIP_SORT_ALPHA);
+ RNA_def_property_ui_text(prop, "Sort Alphabetically", "");
+ RNA_def_property_update(prop, NC_SPACE | ND_SPACE_OUTLINER, NULL);
+
prop = RNA_def_property(srna, "show_restrict_columns", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", SO_HIDE_RESTRICTCOLS);
RNA_def_property_ui_text(prop, "Show Restriction Columns", "Show column");
@@ -1696,12 +2168,28 @@ static void rna_def_background_image(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Y Offset", "Offset image vertically from the world origin");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
- prop = RNA_def_property(srna, "size", PROP_FLOAT, PROP_NONE);
+ prop = RNA_def_property(srna, "size", PROP_FLOAT, PROP_DISTANCE);
RNA_def_property_float_sdna(prop, NULL, "size");
- RNA_def_property_ui_text(prop, "Size", "Scaling factor for the background image");
+ RNA_def_property_float_funcs(prop, "rna_BackgroundImage_size_get", "rna_BackgroundImage_size_set", NULL);
+ RNA_def_property_ui_text(prop, "Size", "Size of the background image (ortho view only)");
RNA_def_property_range(prop, 0.0, FLT_MAX);
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
-
+
+ prop = RNA_def_property(srna, "rotation", PROP_FLOAT, PROP_EULER);
+ RNA_def_property_float_sdna(prop, NULL, "rotation");
+ RNA_def_property_ui_text(prop, "Rotation", "Rotation for the background image (ortho view only)");
+ RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
+
+ prop = RNA_def_property(srna, "use_flip_x", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", V3D_BGPIC_FLIP_X);
+ RNA_def_property_ui_text(prop, "Flip Horizontally", "Flip the background image horizontally");
+ RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
+
+ prop = RNA_def_property(srna, "use_flip_y", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", V3D_BGPIC_FLIP_Y);
+ RNA_def_property_ui_text(prop, "Flip Vertically", "Flip the background image vertically");
+ RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
+
prop = RNA_def_property(srna, "opacity", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "blend");
RNA_def_property_float_funcs(prop, "rna_BackgroundImage_opacity_get", "rna_BackgroundImage_opacity_set", NULL);
@@ -1839,7 +2327,6 @@ static void rna_def_space_view3d(BlenderRNA *brna)
{0, NULL, 0, NULL, NULL}
};
-
srna = RNA_def_struct(brna, "SpaceView3D", "Space");
RNA_def_struct_sdna(srna, "View3D");
RNA_def_struct_ui_text(srna, "3D View Space", "3D View space data");
@@ -1862,7 +2349,7 @@ static void rna_def_space_view3d(BlenderRNA *brna)
prop = RNA_def_property(srna, "render_border_min_x", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "render_border.xmin");
RNA_def_property_range(prop, 0.0f, 1.0f);
- RNA_def_property_ui_text(prop, "Border Minimum X", "Minimum X value to for the render border");
+ RNA_def_property_ui_text(prop, "Border Minimum X", "Minimum X value for the render border");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
prop = RNA_def_property(srna, "render_border_min_y", PROP_FLOAT, PROP_NONE);
@@ -1917,7 +2404,7 @@ static void rna_def_space_view3d(BlenderRNA *brna)
RNA_def_property_float_funcs(prop, "rna_View3D_CursorLocation_get", "rna_View3D_CursorLocation_set", NULL);
RNA_def_property_ui_text(prop, "3D Cursor Location",
"3D cursor location for this view (dependent on local view setting)");
- RNA_def_property_ui_range(prop, -10000.0, 10000.0, 10, 4);
+ RNA_def_property_ui_range(prop, -10000.0, 10000.0, 1, RNA_TRANSLATION_PREC_DEFAULT);
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
prop = RNA_def_property(srna, "lens", PROP_FLOAT, PROP_UNIT_CAMERA);
@@ -1944,6 +2431,7 @@ static void rna_def_space_view3d(BlenderRNA *brna)
RNA_def_property_float_sdna(prop, NULL, "grid");
RNA_def_property_ui_text(prop, "Grid Scale", "Distance between 3D View grid lines");
RNA_def_property_range(prop, 0.0f, FLT_MAX);
+ RNA_def_property_ui_range(prop, 0.001f, 1000.0f, 0.1f, 3);
RNA_def_property_float_default(prop, 1.0f);
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
@@ -2040,6 +2528,11 @@ static void rna_def_space_view3d(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Only Render", "Display only objects which will be rendered");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
+ prop = RNA_def_property(srna, "show_world", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag3", V3D_SHOW_WORLD);
+ RNA_def_property_ui_text(prop, "World Background", "Display world colors in the background");
+ RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
+
prop = RNA_def_property(srna, "use_occlude_geometry", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", V3D_ZBUF_SELECT);
RNA_def_property_ui_text(prop, "Occlude Geometry", "Limit selection to visible (clipped with depth buffer)");
@@ -2175,6 +2668,52 @@ static void rna_def_space_view3d(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Matcap", "Image to use for Material Capture, active objects only");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, "rna_SpaceView3D_matcap_update");
+ prop = RNA_def_property(srna, "fx_settings", PROP_POINTER, PROP_NONE);
+ RNA_def_property_ui_text(prop, "FX Options", "Options used for real time compositing");
+ RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
+
+ /* Stereo Settings */
+ prop = RNA_def_property(srna, "stereo_3d_eye", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "multiview_eye");
+ RNA_def_property_enum_items(prop, stereo3d_eye_items);
+ RNA_def_property_enum_funcs(prop, NULL, NULL, "rna_SpaceView3D_stereo3d_camera_itemf");
+ RNA_def_property_ui_text(prop, "Stereo Eye", "Current stereo eye being drawn");
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+
+ prop = RNA_def_property(srna, "stereo_3d_camera", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "stereo3d_camera");
+ RNA_def_property_enum_items(prop, stereo3d_camera_items);
+ RNA_def_property_enum_funcs(prop, NULL, NULL, "rna_SpaceView3D_stereo3d_camera_itemf");
+ RNA_def_property_ui_text(prop, "Camera", "");
+ RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
+
+ prop = RNA_def_property(srna, "show_stereo_3d_cameras", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "stereo3d_flag", V3D_S3D_DISPCAMERAS);
+ RNA_def_property_ui_text(prop, "Cameras", "Show the left and right cameras");
+ RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
+
+ prop = RNA_def_property(srna, "show_stereo_3d_convergence_plane", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "stereo3d_flag", V3D_S3D_DISPPLANE);
+ RNA_def_property_ui_text(prop, "Plane", "Show the stereo 3d convergence plane");
+ RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
+
+ prop = RNA_def_property(srna, "stereo_3d_convergence_plane_alpha", PROP_FLOAT, PROP_FACTOR);
+ RNA_def_property_float_sdna(prop, NULL, "stereo3d_convergence_alpha");
+ RNA_def_property_ui_text(prop, "Plane Alpha", "Opacity (alpha) of the convergence plane");
+ RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
+
+ prop = RNA_def_property(srna, "show_stereo_3d_volume", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "stereo3d_flag", V3D_S3D_DISPVOLUME);
+ RNA_def_property_ui_text(prop, "Volume", "Show the stereo 3d frustum volume");
+ RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
+
+ prop = RNA_def_property(srna, "stereo_3d_volume_alpha", PROP_FLOAT, PROP_FACTOR);
+ RNA_def_property_float_sdna(prop, NULL, "stereo3d_volume_alpha");
+ RNA_def_property_ui_text(prop, "Volume Alpha", "Opacity (alpha) of the cameras' frustum volume");
+ RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
+
+ /* *** Animated *** */
+ RNA_define_animate_sdna(true);
/* region */
srna = RNA_def_struct(brna, "RegionView3D", NULL);
@@ -2200,13 +2739,20 @@ static void rna_def_space_view3d(BlenderRNA *brna)
RNA_def_property_float_sdna(prop, NULL, "persmat");
RNA_def_property_clear_flag(prop, PROP_EDITABLE); /* XXX: for now, it's too risky for users to do this */
RNA_def_property_multi_array(prop, 2, rna_matrix_dimsize_4x4);
- RNA_def_property_ui_text(prop, "Perspective Matrix", "Current perspective matrix of the 3D region");
+ RNA_def_property_ui_text(prop, "Perspective Matrix",
+ "Current perspective matrix (``window_matrix * view_matrix``)");
+
+ prop = RNA_def_property(srna, "window_matrix", PROP_FLOAT, PROP_MATRIX);
+ RNA_def_property_float_sdna(prop, NULL, "winmat");
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_property_multi_array(prop, 2, rna_matrix_dimsize_4x4);
+ RNA_def_property_ui_text(prop, "Window Matrix", "Current window matrix");
prop = RNA_def_property(srna, "view_matrix", PROP_FLOAT, PROP_MATRIX);
RNA_def_property_float_sdna(prop, NULL, "viewmat");
RNA_def_property_multi_array(prop, 2, rna_matrix_dimsize_4x4);
RNA_def_property_float_funcs(prop, NULL, "rna_RegionView3D_view_matrix_set", NULL);
- RNA_def_property_ui_text(prop, "View Matrix", "Current view matrix of the 3D region");
+ RNA_def_property_ui_text(prop, "View Matrix", "Current view matrix");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
prop = RNA_def_property(srna, "view_perspective", PROP_ENUM, PROP_NONE);
@@ -2341,7 +2887,7 @@ static void rna_def_space_image(BlenderRNA *brna)
RNA_def_property_pointer_funcs(prop, NULL, "rna_SpaceImageEditor_image_set", NULL, NULL);
RNA_def_property_ui_text(prop, "Image", "Image displayed and edited in this space");
RNA_def_property_flag(prop, PROP_EDITABLE);
- RNA_def_property_update(prop, NC_GEOM | ND_DATA, NULL); /* is handled in image editor too */
+ RNA_def_property_update(prop, NC_GEOM | ND_DATA, "rna_SpaceImageEditor_image_update"); /* is handled in image editor too */
prop = RNA_def_property(srna, "image_user", PROP_POINTER, PROP_NONE);
RNA_def_property_flag(prop, PROP_NEVER_NULL);
@@ -2354,6 +2900,7 @@ static void rna_def_space_image(BlenderRNA *brna)
RNA_def_property_pointer_sdna(prop, NULL, "scopes");
RNA_def_property_struct_type(prop, "Scopes");
RNA_def_property_ui_text(prop, "Scopes", "Scopes to visualize image statistics");
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_IMAGE, "rna_SpaceImageEditor_scopes_update");
prop = RNA_def_property(srna, "use_image_pin", PROP_BOOLEAN, PROP_NONE);
@@ -2392,6 +2939,12 @@ static void rna_def_space_image(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Draw Channels", "Channels of the image to draw");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_IMAGE, NULL);
+ prop = RNA_def_property(srna, "show_stereo_3d", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_funcs(prop, "rna_SpaceImageEditor_show_stereo_get", "rna_SpaceImageEditor_show_stereo_set");
+ RNA_def_property_ui_text(prop, "Show Stereo", "Display the image in Stereo 3D");
+ RNA_def_property_ui_icon(prop, ICON_CAMERA_STEREO, 0);
+ RNA_def_property_update(prop, NC_SPACE | ND_SPACE_IMAGE, "rna_SpaceImageEditor_show_stereo_update");
+
/* uv */
prop = RNA_def_property(srna, "uv_editor", PROP_POINTER, PROP_NONE);
RNA_def_property_flag(prop, PROP_NEVER_NULL);
@@ -2424,8 +2977,8 @@ static void rna_def_space_image(BlenderRNA *brna)
/* grease pencil */
prop = RNA_def_property(srna, "grease_pencil", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "gpd");
- RNA_def_property_flag(prop, PROP_EDITABLE);
RNA_def_property_struct_type(prop, "GreasePencil");
+ RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_REFCOUNT);
RNA_def_property_ui_text(prop, "Grease Pencil", "Grease pencil data for this space");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_IMAGE, NULL);
@@ -2508,6 +3061,16 @@ static void rna_def_space_sequencer(BlenderRNA *brna)
{0, NULL, 0, NULL, NULL}
};
+ static EnumPropertyItem waveform_type_draw_items[] = {
+ {SEQ_NO_WAVEFORMS, "NO_WAVEFORMS", 0, "Waveforms Off",
+ "No waveforms drawn for any sound strips"},
+ {SEQ_ALL_WAVEFORMS, "ALL_WAVEFORMS", 0, "Waveforms On",
+ "Waveforms drawn for all sound strips"},
+ {0, "DEFAULT_WAVEFORMS", 0, "Use Strip Option",
+ "Waveforms drawn according to strip setting"},
+ {0, NULL, 0, NULL, NULL}
+ };
+
srna = RNA_def_struct(brna, "SpaceSequenceEditor", "Space");
RNA_def_struct_sdna(srna, "SpaceSeq");
RNA_def_struct_ui_text(srna, "Space Sequence Editor", "Sequence editor space data");
@@ -2548,11 +3111,21 @@ static void rna_def_space_sequencer(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Separate Colors", "Separate color channels in preview");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_SEQUENCER, NULL);
- prop = RNA_def_property(srna, "show_safe_margin", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", SEQ_DRAW_SAFE_MARGINS);
- RNA_def_property_ui_text(prop, "Safe Margin", "Draw title safe margins in preview");
+ prop = RNA_def_property(srna, "show_safe_areas", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", SEQ_SHOW_SAFE_MARGINS);
+ RNA_def_property_ui_text(prop, "Safe Areas", "Show TV title safe and action safe areas in preview");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_SEQUENCER, NULL);
-
+
+ prop = RNA_def_property(srna, "show_safe_center", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", SEQ_SHOW_SAFE_CENTER);
+ RNA_def_property_ui_text(prop, "Center-Cut Safe Areas", "Show safe areas to fit content in a different aspect ratio");
+ RNA_def_property_update(prop, NC_SPACE | ND_SPACE_SEQUENCER, NULL);
+
+ prop = RNA_def_property(srna, "show_metadata", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", SEQ_SHOW_METADATA);
+ RNA_def_property_ui_text(prop, "Show Metadata", "Show metadata of first visible strip");
+ RNA_def_property_update(prop, NC_SPACE | ND_SPACE_SEQUENCER, NULL);
+
prop = RNA_def_property(srna, "show_seconds", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", SEQ_DRAWFRAMES);
RNA_def_property_ui_text(prop, "Show Seconds", "Show timing in seconds not frames");
@@ -2577,6 +3150,12 @@ static void rna_def_space_sequencer(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Draw Channels", "Channels of the preview to draw");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_SEQUENCER, NULL);
+ prop = RNA_def_property(srna, "waveform_draw_type", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_bitflag_sdna(prop, NULL, "flag");
+ RNA_def_property_enum_items(prop, waveform_type_draw_items);
+ RNA_def_property_ui_text(prop, "Waveform Drawing", "How Waveforms are drawn");
+ RNA_def_property_update(prop, NC_SPACE | ND_SPACE_SEQUENCER, NULL);
+
prop = RNA_def_property(srna, "draw_overexposed", PROP_INT, PROP_NONE);
RNA_def_property_int_sdna(prop, NULL, "zebra");
RNA_def_property_ui_text(prop, "Show Overexposed", "Show overexposed areas with zebra stripes");
@@ -2593,8 +3172,8 @@ static void rna_def_space_sequencer(BlenderRNA *brna)
/* grease pencil */
prop = RNA_def_property(srna, "grease_pencil", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "gpd");
- RNA_def_property_flag(prop, PROP_EDITABLE);
RNA_def_property_struct_type(prop, "GreasePencil");
+ RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_REFCOUNT);
RNA_def_property_ui_text(prop, "Grease Pencil", "Grease pencil data for this space");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_SEQUENCER, NULL);
@@ -2603,6 +3182,16 @@ static void rna_def_space_sequencer(BlenderRNA *brna)
RNA_def_property_enum_items(prop, overlay_type_items);
RNA_def_property_ui_text(prop, "Overlay Type", "Overlay draw type");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_SEQUENCER, NULL);
+
+ prop = RNA_def_property(srna, "show_backdrop", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "draw_flag", SEQ_DRAW_BACKDROP);
+ RNA_def_property_ui_text(prop, "Use Backdrop", "Display result under strips");
+ RNA_def_property_update(prop, NC_SPACE | ND_SPACE_SEQUENCER, NULL);
+
+ prop = RNA_def_property(srna, "show_strip_offset", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "draw_flag", SEQ_DRAW_OFFSET_EXT);
+ RNA_def_property_ui_text(prop, "Show Offsets", "Display strip in/out offsets");
+ RNA_def_property_update(prop, NC_SPACE | ND_SPACE_SEQUENCER, NULL);
}
static void rna_def_space_text(BlenderRNA *brna)
@@ -2670,14 +3259,15 @@ static void rna_def_space_text(BlenderRNA *brna)
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_TEXT, NULL);
prop = RNA_def_property(srna, "top", PROP_INT, PROP_NONE);
- RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_int_sdna(prop, NULL, "top");
+ RNA_def_property_range(prop, 0, INT_MAX);
RNA_def_property_ui_text(prop, "Top Line", "Top line visible");
+ RNA_def_property_update(prop, NC_SPACE | ND_SPACE_TEXT, NULL);
prop = RNA_def_property(srna, "visible_lines", PROP_INT, PROP_NONE);
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_int_sdna(prop, NULL, "viewlines");
- RNA_def_property_ui_text(prop, "Top Line", "Amount of lines that can be visible in current editor");
+ RNA_def_property_ui_text(prop, "Visible Lines", "Amount of lines that can be visible in current editor");
/* functionality options */
prop = RNA_def_property(srna, "use_overwrite", PROP_BOOLEAN, PROP_NONE);
@@ -2715,6 +3305,8 @@ static void rna_def_space_text(BlenderRNA *brna)
RNA_def_property_string_sdna(prop, NULL, "replacestr");
RNA_def_property_ui_text(prop, "Replace Text", "Text to replace selected text with using the replace tool");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_TEXT, NULL);
+
+ RNA_api_space_text(srna);
}
static void rna_def_space_dopesheet(BlenderRNA *brna)
@@ -2779,7 +3371,8 @@ static void rna_def_space_dopesheet(BlenderRNA *brna)
prop = RNA_def_property(srna, "show_group_colors", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", SACTION_NODRAWGCOLORS);
RNA_def_property_ui_text(prop, "Show Group Colors",
- "Draw groups and channels with colors matching their corresponding groups");
+ "Draw groups and channels with colors matching their corresponding groups "
+ "(pose bones only currently)");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_DOPESHEET, NULL);
/* editing */
@@ -2934,14 +3527,12 @@ static void rna_def_space_graph(BlenderRNA *brna)
RNA_def_property_enum_items(prop, autosnap_items);
RNA_def_property_ui_text(prop, "Auto Snap", "Automatic time snapping settings for transformations");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_GRAPH, NULL);
-
+
/* readonly state info */
prop = RNA_def_property(srna, "has_ghost_curves", PROP_BOOLEAN, PROP_NONE);
- /* XXX: hack to make this compile, since this property doesn't actually exist*/
- RNA_def_property_boolean_sdna(prop, NULL, "flag", 0);
RNA_def_property_boolean_funcs(prop, "rna_SpaceGraphEditor_has_ghost_curves_get", NULL);
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_ui_text(prop, "Has Ghost Curves", "Graph Editor instance has some ghost curves stored");
- RNA_def_property_update(prop, NC_SPACE | ND_SPACE_GRAPH, NULL);
/* nromalize curves */
prop = RNA_def_property(srna, "use_normalization", PROP_BOOLEAN, PROP_NONE);
@@ -3077,14 +3668,13 @@ static void rna_def_console_line(BlenderRNA *brna)
srna = RNA_def_struct(brna, "ConsoleLine", NULL);
RNA_def_struct_ui_text(srna, "Console Input", "Input line for the interactive console");
- /* XXX using non-inited "prop", uh? RNA_def_property_update(prop, NC_SPACE|ND_SPACE_CONSOLE, NULL); */
prop = RNA_def_property(srna, "body", PROP_STRING, PROP_NONE);
RNA_def_property_string_funcs(prop, "rna_ConsoleLine_body_get", "rna_ConsoleLine_body_length",
"rna_ConsoleLine_body_set");
RNA_def_property_ui_text(prop, "Line", "Text in the line");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_CONSOLE, NULL);
- RNA_def_property_translation_context(prop, BLF_I18NCONTEXT_ID_TEXT);
+ RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_TEXT);
prop = RNA_def_property(srna, "current_character", PROP_INT, PROP_NONE); /* copied from text editor */
RNA_def_property_int_sdna(prop, NULL, "cursor");
@@ -3151,16 +3741,69 @@ static void rna_def_fileselect_params(BlenderRNA *brna)
{0, NULL, 0, NULL, NULL}
};
- static EnumPropertyItem file_sort_items[] = {
- {FILE_SORT_ALPHA, "FILE_SORT_ALPHA", ICON_SORTALPHA, "Sort alphabetically",
- "Sort the file list alphabetically"},
- {FILE_SORT_EXTENSION, "FILE_SORT_EXTENSION", ICON_SORTBYEXT, "Sort by extension",
- "Sort the file list by extension"},
- {FILE_SORT_TIME, "FILE_SORT_TIME", ICON_SORTTIME, "Sort by time", "Sort files by modification time"},
- {FILE_SORT_SIZE, "FILE_SORT_SIZE", ICON_SORTSIZE, "Sort by size", "Sort files by size"},
+ static EnumPropertyItem thumbnail_size_items[] = {
+ {32, "TINY", 0, "Tiny", ""},
+ {64, "SMALL", 0, "Small", ""},
+ {128, "NORMAL", 0, "Normal", ""},
+ {256, "LARGE", 0, "Large", ""},
+ {0, NULL, 0, NULL, NULL}
+ };
+
+ static EnumPropertyItem file_filter_idtypes_items[] = {
+ {FILTER_ID_AC, "ACTION", ICON_ANIM_DATA, "Actions", "Show/hide Action datablocks"},
+ {FILTER_ID_AR, "ARMATURE", ICON_ARMATURE_DATA, "Armatures", "Show/hide Armature datablocks"},
+ {FILTER_ID_BR, "BRUSH", ICON_BRUSH_DATA, "Brushes", "Show/hide Brushes datablocks"},
+ {FILTER_ID_CA, "CAMERA", ICON_CAMERA_DATA, "Cameras", "Show/hide Camera datablocks"},
+ {FILTER_ID_CU, "CURVE", ICON_CURVE_DATA, "Curves", "Show/hide Curve datablocks"},
+ {FILTER_ID_GD, "GREASE_PENCIL", ICON_GREASEPENCIL, "Grease Pencil", "Show/hide Grease pencil datablocks"},
+ {FILTER_ID_GR, "GROUP", ICON_GROUP, "Groups", "Show/hide Group datablocks"},
+ {FILTER_ID_IM, "IMAGE", ICON_IMAGE_DATA, "Images", "Show/hide Image datablocks"},
+ {FILTER_ID_LA, "LAMP", ICON_LAMP_DATA, "Lamps", "Show/hide Lamp datablocks"},
+ {FILTER_ID_LS, "LINESTYLE", ICON_LINE_DATA,
+ "Freestyle Linestyles", "Show/hide Freestyle's Line Style datablocks"},
+ {FILTER_ID_LT, "LATTICE", ICON_LATTICE_DATA, "Lattices", "Show/hide Lattice datablocks"},
+ {FILTER_ID_MA, "MATERIAL", ICON_MATERIAL_DATA, "Materials", "Show/hide Material datablocks"},
+ {FILTER_ID_MB, "METABALL", ICON_META_DATA, "Metaballs", "Show/hide Metaball datablocks"},
+ {FILTER_ID_MC, "MOVIE_CLIP", ICON_CLIP, "Movie Clips", "Show/hide Movie Clip datablocks"},
+ {FILTER_ID_ME, "MESH", ICON_MESH_DATA, "Meshes", "Show/hide Mesh datablocks"},
+ {FILTER_ID_MSK, "MASK", ICON_MOD_MASK, "Masks", "Show/hide Mask datablocks"},
+ {FILTER_ID_NT, "NODE_TREE", ICON_NODETREE, "Node Trees", "Show/hide Node Tree datablocks"},
+ {FILTER_ID_OB, "OBJECT", ICON_OBJECT_DATA, "Objects", "Show/hide Object datablocks"},
+ {FILTER_ID_PA, "PARTICLE_SETTINGS", ICON_PARTICLE_DATA,
+ "Particles Settings", "Show/hide Particle Settings datablocks"},
+ {FILTER_ID_PAL, "PALETTE", ICON_COLOR, "Palettes", "Show/hide Palette datablocks"},
+ {FILTER_ID_PC, "PAINT_CURVE", ICON_CURVE_BEZCURVE, "Paint Curves", "Show/hide Paint Curve datablocks"},
+ {FILTER_ID_SCE, "SCENE", ICON_SCENE_DATA, "Scenes", "Show/hide Scene datablocks"},
+ {FILTER_ID_SPK, "SPEAKER", ICON_SPEAKER, "Speakers", "Show/hide Speaker datablocks"},
+ {FILTER_ID_SO, "SOUND", ICON_SOUND, "Sounds", "Show/hide Sound datablocks"},
+ {FILTER_ID_TE, "TEXTURE", ICON_TEXTURE_DATA, "Textures", "Show/hide Texture datablocks"},
+ {FILTER_ID_TXT, "TEXT", ICON_TEXT, "Texts", "Show/hide Text datablocks"},
+ {FILTER_ID_VF, "FONT", ICON_FONT_DATA, "Fonts", "Show/hide Font datablocks"},
+ {FILTER_ID_WO, "WORLD", ICON_WORLD_DATA, "Worlds", "Show/hide World datablocks"},
{0, NULL, 0, NULL, NULL}
};
+ static EnumPropertyItem file_filter_idcategories_items[] = {
+ {FILTER_ID_SCE,
+ "SCENE", ICON_SCENE_DATA, "Scenes", "Show/hide scenes"},
+ {FILTER_ID_AC,
+ "ANIMATION", ICON_ANIM_DATA, "Animations", "Show/hide animation data"},
+ {FILTER_ID_OB | FILTER_ID_GR,
+ "OBJECT", ICON_GROUP, "Objects & Groups", "Show/hide objects and groups"},
+ {FILTER_ID_AR | FILTER_ID_CU | FILTER_ID_LT | FILTER_ID_MB | FILTER_ID_ME,
+ "GEOMETRY", ICON_MESH_DATA, "Geometry", "Show/hide meshes, curves, lattice, armatures and metaballs data"},
+ {FILTER_ID_LS | FILTER_ID_MA | FILTER_ID_NT | FILTER_ID_TE,
+ "SHADING", ICON_MATERIAL_DATA, "Shading",
+ "Show/hide materials, nodetrees, textures and Freestyle's linestyles"},
+ {FILTER_ID_IM | FILTER_ID_MC | FILTER_ID_MSK | FILTER_ID_SO,
+ "IMAGE", ICON_IMAGE_DATA, "Images & Sounds", "Show/hide images, movie clips, sounds and masks"},
+ {FILTER_ID_CA | FILTER_ID_LA | FILTER_ID_SPK | FILTER_ID_WO,
+ "ENVIRONMENT", ICON_WORLD_DATA, "Environment", "Show/hide worlds, lamps, cameras and speakers"},
+ {FILTER_ID_BR | FILTER_ID_GD | FILTER_ID_PA | FILTER_ID_PAL | FILTER_ID_PC | FILTER_ID_TXT | FILTER_ID_VF,
+ "MISC", ICON_GREASEPENCIL, "Miscellaneous", "Show/hide other data types"},
+ {0, NULL, 0, NULL, NULL}
+ };
+
srna = RNA_def_struct(brna, "FileSelectParams", NULL);
RNA_def_struct_ui_text(srna, "File Select Parameters", "File Select Parameters");
@@ -3179,12 +3822,23 @@ static void rna_def_fileselect_params(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "File Name", "Active file in the file browser");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_FILE_PARAMS, NULL);
+ prop = RNA_def_property(srna, "use_library_browsing", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_ui_text(prop, "Library Browser", "Whether we may browse blender files' content or not");
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_property_boolean_funcs(prop, "rna_FileSelectParams_use_lib_get", NULL);
+
prop = RNA_def_property(srna, "display_type", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "display");
RNA_def_property_enum_items(prop, file_display_items);
RNA_def_property_ui_text(prop, "Display Mode", "Display mode for the file list");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_FILE_PARAMS, NULL);
+ prop = RNA_def_property(srna, "recursion_level", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_items(prop, fileselectparams_recursion_level_items);
+ RNA_def_property_enum_funcs(prop, NULL, NULL, "rna_FileSelectParams_recursion_level_itemf");
+ RNA_def_property_ui_text(prop, "Recursion", "Numbers of dirtree levels to show simultaneously");
+ RNA_def_property_update(prop, NC_SPACE | ND_SPACE_FILE_PARAMS, NULL);
+
prop = RNA_def_property(srna, "use_filter", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", FILE_FILTER);
RNA_def_property_ui_text(prop, "Filter Files", "Enable filtering of files");
@@ -3202,64 +3856,131 @@ static void rna_def_fileselect_params(BlenderRNA *brna)
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_FILE_PARAMS, NULL);
prop = RNA_def_property(srna, "use_filter_image", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "filter", IMAGEFILE);
+ RNA_def_property_boolean_sdna(prop, NULL, "filter", FILE_TYPE_IMAGE);
RNA_def_property_ui_text(prop, "Filter Images", "Show image files");
RNA_def_property_ui_icon(prop, ICON_FILE_IMAGE, 0);
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_FILE_PARAMS, NULL);
prop = RNA_def_property(srna, "use_filter_blender", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "filter", BLENDERFILE);
+ RNA_def_property_boolean_sdna(prop, NULL, "filter", FILE_TYPE_BLENDER);
RNA_def_property_ui_text(prop, "Filter Blender", "Show .blend files");
RNA_def_property_ui_icon(prop, ICON_FILE_BLEND, 0);
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_FILE_PARAMS, NULL);
prop = RNA_def_property(srna, "use_filter_backup", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "filter", BLENDERFILE_BACKUP);
+ RNA_def_property_boolean_sdna(prop, NULL, "filter", FILE_TYPE_BLENDER_BACKUP);
RNA_def_property_ui_text(prop, "Filter BlenderBackup files", "Show .blend1, .blend2, etc. files");
RNA_def_property_ui_icon(prop, ICON_FILE_BACKUP, 0);
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_FILE_PARAMS, NULL);
prop = RNA_def_property(srna, "use_filter_movie", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "filter", MOVIEFILE);
+ RNA_def_property_boolean_sdna(prop, NULL, "filter", FILE_TYPE_MOVIE);
RNA_def_property_ui_text(prop, "Filter Movies", "Show movie files");
RNA_def_property_ui_icon(prop, ICON_FILE_MOVIE, 0);
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_FILE_PARAMS, NULL);
prop = RNA_def_property(srna, "use_filter_script", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "filter", PYSCRIPTFILE);
+ RNA_def_property_boolean_sdna(prop, NULL, "filter", FILE_TYPE_PYSCRIPT);
RNA_def_property_ui_text(prop, "Filter Script", "Show script files");
RNA_def_property_ui_icon(prop, ICON_FILE_SCRIPT, 0);
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_FILE_PARAMS, NULL);
prop = RNA_def_property(srna, "use_filter_font", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "filter", FTFONTFILE);
+ RNA_def_property_boolean_sdna(prop, NULL, "filter", FILE_TYPE_FTFONT);
RNA_def_property_ui_text(prop, "Filter Fonts", "Show font files");
RNA_def_property_ui_icon(prop, ICON_FILE_FONT, 0);
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_FILE_PARAMS, NULL);
prop = RNA_def_property(srna, "use_filter_sound", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "filter", SOUNDFILE);
+ RNA_def_property_boolean_sdna(prop, NULL, "filter", FILE_TYPE_SOUND);
RNA_def_property_ui_text(prop, "Filter Sound", "Show sound files");
RNA_def_property_ui_icon(prop, ICON_FILE_SOUND, 0);
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_FILE_PARAMS, NULL);
prop = RNA_def_property(srna, "use_filter_text", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "filter", TEXTFILE);
+ RNA_def_property_boolean_sdna(prop, NULL, "filter", FILE_TYPE_TEXT);
RNA_def_property_ui_text(prop, "Filter Text", "Show text files");
RNA_def_property_ui_icon(prop, ICON_FILE_TEXT, 0);
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_FILE_PARAMS, NULL);
prop = RNA_def_property(srna, "use_filter_folder", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "filter", FOLDERFILE);
+ RNA_def_property_boolean_sdna(prop, NULL, "filter", FILE_TYPE_FOLDER);
RNA_def_property_ui_text(prop, "Filter Folder", "Show folders");
RNA_def_property_ui_icon(prop, ICON_FILE_FOLDER, 0);
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_FILE_PARAMS, NULL);
-
+
+ prop = RNA_def_property(srna, "use_filter_blendid", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "filter", FILE_TYPE_BLENDERLIB);
+ RNA_def_property_ui_text(prop, "Filter Blender IDs", "Show .blend files items (objects, materials, etc.)");
+ RNA_def_property_ui_icon(prop, ICON_BLENDER, 0);
+ RNA_def_property_update(prop, NC_SPACE | ND_SPACE_FILE_PARAMS, NULL);
+
+ prop = RNA_def_property(srna, "filter_id", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "filter_id");
+ RNA_def_property_enum_items(prop, file_filter_idtypes_items);
+ RNA_def_property_flag(prop, PROP_ENUM_FLAG);
+ RNA_def_property_ui_text(prop, "Filter ID types", "Which ID types to show/hide, when browsing a library");
+ RNA_def_property_update(prop, NC_SPACE | ND_SPACE_FILE_PARAMS, NULL);
+
+ prop = RNA_def_property(srna, "filter_id_category", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "filter_id");
+ RNA_def_property_enum_items(prop, file_filter_idcategories_items);
+ RNA_def_property_flag(prop, PROP_ENUM_FLAG);
+ RNA_def_property_ui_text(prop, "Filter ID categories", "Which ID categories to show/hide, when browsing a library");
+ RNA_def_property_update(prop, NC_SPACE | ND_SPACE_FILE_PARAMS, NULL);
+
prop = RNA_def_property(srna, "filter_glob", PROP_STRING, PROP_NONE);
RNA_def_property_string_sdna(prop, NULL, "filter_glob");
RNA_def_property_ui_text(prop, "Extension Filter", "");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_FILE_LIST, NULL);
+ prop = RNA_def_property(srna, "filter_search", PROP_STRING, PROP_NONE);
+ RNA_def_property_string_sdna(prop, NULL, "filter_search");
+ RNA_def_property_ui_text(prop, "Name Filter", "Filter by name, supports '*' wildcard");
+ RNA_def_property_flag(prop, PROP_TEXTEDIT_UPDATE);
+ RNA_def_property_update(prop, NC_SPACE | ND_SPACE_FILE_LIST, NULL);
+
+ prop = RNA_def_property(srna, "thumbnail_size", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "thumbnail_size");
+ RNA_def_property_enum_items(prop, thumbnail_size_items);
+ RNA_def_property_ui_text(prop, "Thumbnails Size", "Change the size of the thumbnails");
+ RNA_def_property_update(prop, NC_SPACE | ND_SPACE_FILE_LIST, NULL);
+}
+
+static void rna_def_filemenu_entry(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ srna = RNA_def_struct(brna, "FileBrowserFSMenuEntry", NULL);
+ RNA_def_struct_sdna(srna, "FSMenuEntry");
+ RNA_def_struct_ui_text(srna, "File Select Parameters", "File Select Parameters");
+
+ prop = RNA_def_property(srna, "path", PROP_STRING, PROP_FILEPATH);
+ RNA_def_property_string_sdna(prop, NULL, "path");
+ RNA_def_property_string_funcs(prop, "rna_FileBrowser_FSMenuEntry_path_get",
+ "rna_FileBrowser_FSMenuEntry_path_length",
+ "rna_FileBrowser_FSMenuEntry_path_set");
+ RNA_def_property_ui_text(prop, "Path", "");
+
+ prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE);
+ RNA_def_property_string_sdna(prop, NULL, "name");
+ RNA_def_property_string_funcs(prop, "rna_FileBrowser_FSMenuEntry_name_get",
+ "rna_FileBrowser_FSMenuEntry_name_length",
+ "rna_FileBrowser_FSMenuEntry_name_set");
+ RNA_def_property_editable_func(prop, "rna_FileBrowser_FSMenuEntry_name_get_editable");
+ RNA_def_property_ui_text(prop, "Name", "");
+ RNA_def_struct_name_property(srna, prop);
+
+ prop = RNA_def_property(srna, "use_save", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "save", 1);
+ RNA_def_property_ui_text(prop, "Save", "Whether this path is saved in bookmarks, or generated from OS");
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+
+ prop = RNA_def_property(srna, "is_valid", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "valid", 1);
+ RNA_def_property_ui_text(prop, "Valid", "Whether this path is currently reachable");
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
}
static void rna_def_space_filebrowser(BlenderRNA *brna)
@@ -3284,6 +4005,67 @@ static void rna_def_space_filebrowser(BlenderRNA *brna)
prop = RNA_def_property(srna, "operator", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "op");
RNA_def_property_ui_text(prop, "Active Operator", "");
+
+ /* bookmarks, recent files etc. */
+ prop = RNA_def_collection(srna, "system_folders", "FileBrowserFSMenuEntry", "System Folders",
+ "System's folders (usually root, available hard drives, etc)");
+ RNA_def_property_collection_funcs(prop, "rna_FileBrowser_FSMenuSystem_data_begin", "rna_FileBrowser_FSMenu_next",
+ "rna_FileBrowser_FSMenu_end", "rna_FileBrowser_FSMenu_get",
+ "rna_FileBrowser_FSMenuSystem_data_length", NULL, NULL, NULL);
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+
+ prop = RNA_def_int(srna, "system_folders_active", -1, -1, INT_MAX, "Active System Folder",
+ "Index of active system folder (-1 if none)", -1, INT_MAX);
+ RNA_def_property_int_sdna(prop, NULL, "systemnr");
+ RNA_def_property_int_funcs(prop, "rna_FileBrowser_FSMenuSystem_active_get",
+ "rna_FileBrowser_FSMenuSystem_active_set", "rna_FileBrowser_FSMenuSystem_active_range");
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
+ RNA_def_property_update(prop, NC_SPACE | ND_SPACE_FILE_PARAMS, "rna_FileBrowser_FSMenu_active_update");
+
+ prop = RNA_def_collection(srna, "system_bookmarks", "FileBrowserFSMenuEntry", "System Bookmarks",
+ "System's bookmarks");
+ RNA_def_property_collection_funcs(prop, "rna_FileBrowser_FSMenuSystemBookmark_data_begin", "rna_FileBrowser_FSMenu_next",
+ "rna_FileBrowser_FSMenu_end", "rna_FileBrowser_FSMenu_get",
+ "rna_FileBrowser_FSMenuSystemBookmark_data_length", NULL, NULL, NULL);
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+
+ prop = RNA_def_int(srna, "system_bookmarks_active", -1, -1, INT_MAX, "Active System Bookmark",
+ "Index of active system bookmark (-1 if none)", -1, INT_MAX);
+ RNA_def_property_int_sdna(prop, NULL, "system_bookmarknr");
+ RNA_def_property_int_funcs(prop, "rna_FileBrowser_FSMenuSystemBookmark_active_get",
+ "rna_FileBrowser_FSMenuSystemBookmark_active_set", "rna_FileBrowser_FSMenuSystemBookmark_active_range");
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
+ RNA_def_property_update(prop, NC_SPACE | ND_SPACE_FILE_PARAMS, "rna_FileBrowser_FSMenu_active_update");
+
+ prop = RNA_def_collection(srna, "bookmarks", "FileBrowserFSMenuEntry", "Bookmarks",
+ "User's bookmarks");
+ RNA_def_property_collection_funcs(prop, "rna_FileBrowser_FSMenuBookmark_data_begin", "rna_FileBrowser_FSMenu_next",
+ "rna_FileBrowser_FSMenu_end", "rna_FileBrowser_FSMenu_get",
+ "rna_FileBrowser_FSMenuBookmark_data_length", NULL, NULL, NULL);
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+
+ prop = RNA_def_int(srna, "bookmarks_active", -1, -1, INT_MAX, "Active Bookmark",
+ "Index of active bookmark (-1 if none)", -1, INT_MAX);
+ RNA_def_property_int_sdna(prop, NULL, "bookmarknr");
+ RNA_def_property_int_funcs(prop, "rna_FileBrowser_FSMenuBookmark_active_get",
+ "rna_FileBrowser_FSMenuBookmark_active_set", "rna_FileBrowser_FSMenuBookmark_active_range");
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
+ RNA_def_property_update(prop, NC_SPACE | ND_SPACE_FILE_PARAMS, "rna_FileBrowser_FSMenu_active_update");
+
+ prop = RNA_def_collection(srna, "recent_folders", "FileBrowserFSMenuEntry", "Recent Folders",
+ "");
+ RNA_def_property_collection_funcs(prop, "rna_FileBrowser_FSMenuRecent_data_begin", "rna_FileBrowser_FSMenu_next",
+ "rna_FileBrowser_FSMenu_end", "rna_FileBrowser_FSMenu_get",
+ "rna_FileBrowser_FSMenuRecent_data_length", NULL, NULL, NULL);
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+
+ prop = RNA_def_int(srna, "recent_folders_active", -1, -1, INT_MAX, "Active Recent Folder",
+ "Index of active recent folder (-1 if none)", -1, INT_MAX);
+ RNA_def_property_int_sdna(prop, NULL, "recentnr");
+ RNA_def_property_int_funcs(prop, "rna_FileBrowser_FSMenuRecent_active_get",
+ "rna_FileBrowser_FSMenuRecent_active_set", "rna_FileBrowser_FSMenuRecent_active_range");
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
+ RNA_def_property_update(prop, NC_SPACE | ND_SPACE_FILE_PARAMS, "rna_FileBrowser_FSMenu_active_update");
}
static void rna_def_space_info(BlenderRNA *brna)
@@ -3344,6 +4126,7 @@ static void rna_def_space_userpref(BlenderRNA *brna)
prop = RNA_def_property(srna, "filter_text", PROP_STRING, PROP_NONE);
RNA_def_property_string_sdna(prop, NULL, "filter");
+ RNA_def_property_flag(prop, PROP_TEXTEDIT_UPDATE);
RNA_def_property_ui_text(prop, "Filter", "Search term for filtering in the UI");
}
@@ -3437,6 +4220,12 @@ static void rna_def_space_node(BlenderRNA *brna)
{0, NULL, 0, NULL, NULL}
};
+ static EnumPropertyItem insert_ofs_dir_items[] = {
+ {SNODE_INSERTOFS_DIR_RIGHT, "RIGHT", 0, "Right"},
+ {SNODE_INSERTOFS_DIR_LEFT, "LEFT", 0, "Left"},
+ {0, NULL, 0, NULL, NULL}
+ };
+
static EnumPropertyItem dummy_items[] = {
{0, "DUMMY", 0, "", ""},
{0, NULL, 0, NULL, NULL}};
@@ -3550,6 +4339,20 @@ static void rna_def_space_node(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Cursor Location", "Location for adding new nodes");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_NODE_VIEW, NULL);
+ /* insert offset (called "Auto-offset" in UI) */
+ prop = RNA_def_property(srna, "use_insert_offset", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", SNODE_SKIP_INSOFFSET);
+ RNA_def_property_ui_text(prop, "Auto-offset", "Automatically offset the following or previous nodes in a "
+ "chain when inserting a new node");
+ RNA_def_property_ui_icon(prop, ICON_NODE_INSERT_ON, 1);
+ RNA_def_property_update(prop, NC_SPACE | ND_SPACE_NODE_VIEW, NULL);
+
+ prop = RNA_def_property(srna, "insert_offset_direction", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_bitflag_sdna(prop, NULL, "insert_ofs_dir");
+ RNA_def_property_enum_items(prop, insert_ofs_dir_items);
+ RNA_def_property_ui_text(prop, "Auto-offset Direction", "Direction to offset nodes on insertion");
+ RNA_def_property_update(prop, NC_SPACE | ND_SPACE_NODE_VIEW, NULL);
+
RNA_api_space_node(srna);
}
@@ -3686,7 +4489,7 @@ static void rna_def_space_clip(BlenderRNA *brna)
RNA_def_property_enum_sdna(prop, NULL, "view");
RNA_def_property_enum_items(prop, view_items);
RNA_def_property_ui_text(prop, "View", "Type of the clip editor view");
- RNA_def_property_translation_context(prop, BLF_I18NCONTEXT_ID_MOVIECLIP);
+ RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_MOVIECLIP);
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_CLIP, "rna_SpaceClipEditor_view_type_update");
/* show pattern */
@@ -3751,6 +4554,11 @@ static void rna_def_space_clip(BlenderRNA *brna)
RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", SC_HIDE_DISABLED);
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_CLIP, NULL);
+ prop = RNA_def_property(srna, "show_metadata", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", SC_SHOW_METADATA);
+ RNA_def_property_ui_text(prop, "Show Metadata", "Show metadata of clip");
+ RNA_def_property_update(prop, NC_SPACE | ND_SPACE_CLIP, NULL);
+
/* scopes */
prop = RNA_def_property(srna, "scopes", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "scopes");
@@ -3867,7 +4675,7 @@ static void rna_def_space_clip(BlenderRNA *brna)
RNA_def_property_enum_sdna(prop, NULL, "gpencil_src");
RNA_def_property_enum_items(prop, gpencil_source_items);
RNA_def_property_ui_text(prop, "Grease Pencil Source", "Where the grease pencil comes from");
- RNA_def_property_translation_context(prop, BLF_I18NCONTEXT_ID_MOVIECLIP);
+ RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_MOVIECLIP);
RNA_def_property_update(prop, NC_MOVIECLIP | ND_DISPLAY, NULL);
/* pivot point */
@@ -3886,6 +4694,7 @@ void RNA_def_space(BlenderRNA *brna)
rna_def_space_sequencer(brna);
rna_def_space_text(brna);
rna_def_fileselect_params(brna);
+ rna_def_filemenu_entry(brna);
rna_def_space_filebrowser(brna);
rna_def_space_outliner(brna);
rna_def_background_image(brna);
diff --git a/source/blender/makesrna/intern/rna_space_api.c b/source/blender/makesrna/intern/rna_space_api.c
index aed77378241..3cfbd798ad6 100644
--- a/source/blender/makesrna/intern/rna_space_api.c
+++ b/source/blender/makesrna/intern/rna_space_api.c
@@ -31,6 +31,8 @@
#ifdef RNA_RUNTIME
+#include "ED_text.h"
+
static void rna_RegionView3D_update(ID *id, RegionView3D *rv3d)
{
bScreen *sc = (bScreen *)id;
@@ -49,6 +51,19 @@ static void rna_RegionView3D_update(ID *id, RegionView3D *rv3d)
}
}
+static void rna_SpaceTextEditor_region_location_from_cursor(
+ ID *id, SpaceText *st,
+ int line, int column, int r_pixel_pos[2])
+{
+ bScreen *sc = (bScreen *)id;
+ ScrArea *sa = BKE_screen_find_area_from_space(sc, (SpaceLink *)st);
+ if (sa) {
+ ARegion *ar = BKE_area_find_region_type(sa, RGN_TYPE_WINDOW);
+ const int cursor_co[2] = {line, column};
+ ED_text_region_location_from_cursor(st, ar, cursor_co, r_pixel_pos);
+ }
+}
+
#else
void RNA_api_region_view3d(StructRNA *srna)
@@ -74,4 +89,20 @@ void RNA_api_space_node(StructRNA *srna)
RNA_def_property_flag(parm, PROP_REQUIRED);
}
+void RNA_api_space_text(StructRNA *srna)
+{
+ FunctionRNA *func;
+ PropertyRNA *parm;
+
+ func = RNA_def_function(srna, "region_location_from_cursor", "rna_SpaceTextEditor_region_location_from_cursor");
+ RNA_def_function_ui_description(func, "Retrieve the region position from the given line and character position");
+ RNA_def_function_flag(func, FUNC_USE_SELF_ID);
+ parm = RNA_def_int(func, "line", 0, INT_MIN, INT_MAX, "Line", "Line index", 0, INT_MAX);
+ RNA_def_property_flag(parm, PROP_REQUIRED);
+ parm = RNA_def_int(func, "column", 0, INT_MIN, INT_MAX, "Column", "Column index", 0, INT_MAX);
+ RNA_def_property_flag(parm, PROP_REQUIRED);
+ parm = RNA_def_int_array(func, "result", 2, NULL, -1, INT_MAX, "", "Region coordinates", -1, INT_MAX);
+ RNA_def_function_output(func, parm);
+}
+
#endif
diff --git a/source/blender/makesrna/intern/rna_speaker.c b/source/blender/makesrna/intern/rna_speaker.c
index d237dcffc96..31a4e672983 100644
--- a/source/blender/makesrna/intern/rna_speaker.c
+++ b/source/blender/makesrna/intern/rna_speaker.c
@@ -35,7 +35,7 @@
#include "DNA_speaker_types.h"
#include "DNA_sound_types.h"
-#include "BLF_translation.h"
+#include "BLT_translation.h"
#ifdef RNA_RUNTIME
@@ -62,7 +62,7 @@ static void rna_def_speaker(BlenderRNA *brna)
RNA_def_property_boolean_sdna(prop, NULL, "flag", SPK_MUTED);
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
RNA_def_property_ui_text(prop, "Mute", "Mute the speaker");
- RNA_def_property_translation_context(prop, BLF_I18NCONTEXT_ID_SOUND);
+ RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_SOUND);
/* RNA_def_property_update(prop, 0, "rna_Speaker_update"); */
prop = RNA_def_property(srna, "relative", PROP_BOOLEAN, PROP_NONE);
@@ -142,14 +142,14 @@ static void rna_def_speaker(BlenderRNA *brna)
prop = RNA_def_property(srna, "volume", PROP_FLOAT, PROP_NONE);
RNA_def_property_range(prop, 0.0f, 1.0f);
RNA_def_property_ui_text(prop, "Volume", "How loud the sound is");
- RNA_def_property_translation_context(prop, BLF_I18NCONTEXT_ID_SOUND);
+ RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_SOUND);
/* RNA_def_property_float_funcs(prop, NULL, "rna_Speaker_volume_set", NULL); */
/* RNA_def_property_update(prop, 0, "rna_Speaker_update"); */
prop = RNA_def_property(srna, "pitch", PROP_FLOAT, PROP_NONE);
RNA_def_property_range(prop, 0.1f, 10.0f);
RNA_def_property_ui_text(prop, "Pitch", "Playback pitch of the sound");
- RNA_def_property_translation_context(prop, BLF_I18NCONTEXT_ID_SOUND);
+ RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_SOUND);
/* RNA_def_property_float_funcs(prop, NULL, "rna_Speaker_pitch_set", NULL); */
/* RNA_def_property_update(prop, 0, "rna_Speaker_update"); */
diff --git a/source/blender/makesrna/intern/rna_test.c b/source/blender/makesrna/intern/rna_test.c
index 867e6dcd8ff..46299799966 100644
--- a/source/blender/makesrna/intern/rna_test.c
+++ b/source/blender/makesrna/intern/rna_test.c
@@ -61,7 +61,7 @@
(void)0
#define DEF_GET_SET(type, arr) \
- void rna_Test_ ## arr ## _get(PointerRNA *ptr, type * values) \
+ void rna_Test_ ## arr ## _get(PointerRNA *ptr, type * values) \
{ \
memcpy(values, arr, sizeof(arr)); \
} \
@@ -70,10 +70,10 @@
{ \
memcpy(arr, values, sizeof(arr)); \
} \
- (void)0
+ ((void)0)
#define DEF_GET_SET_LEN(arr, max) \
- static int rna_Test_ ## arr ## _get_length(PointerRNA * ptr) \
+ static int rna_Test_ ## arr ## _get_length(PointerRNA * ptr) \
{ \
return arr ## _len; \
} \
@@ -87,7 +87,7 @@
\
return 1; \
} \
- (void)0
+ ((void)0)
DEF_VARS(float, f);
DEF_VARS(int, i);
diff --git a/source/blender/makesrna/intern/rna_text.c b/source/blender/makesrna/intern/rna_text.c
index 46477007962..fb9d447850a 100644
--- a/source/blender/makesrna/intern/rna_text.c
+++ b/source/blender/makesrna/intern/rna_text.c
@@ -30,7 +30,7 @@
#include "MEM_guardedalloc.h"
-#include "BLF_translation.h"
+#include "BLT_translation.h"
#include "BKE_text.h"
@@ -139,7 +139,7 @@ static void rna_def_text_line(BlenderRNA *brna)
RNA_def_property_string_funcs(prop, "rna_TextLine_body_get", "rna_TextLine_body_length", "rna_TextLine_body_set");
RNA_def_property_ui_text(prop, "Line", "Text in the line");
RNA_def_property_update(prop, NC_TEXT | NA_EDITED, NULL);
- RNA_def_property_translation_context(prop, BLF_I18NCONTEXT_ID_TEXT);
+ RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_TEXT);
}
static void rna_def_text(BlenderRNA *brna)
diff --git a/source/blender/makesrna/intern/rna_texture.c b/source/blender/makesrna/intern/rna_texture.c
index f098a659671..726744782ed 100644
--- a/source/blender/makesrna/intern/rna_texture.c
+++ b/source/blender/makesrna/intern/rna_texture.c
@@ -119,6 +119,7 @@ static EnumPropertyItem blend_type_items[] = {
#include "BKE_main.h"
#include "ED_node.h"
+#include "ED_render.h"
static StructRNA *rna_Texture_refine(struct PointerRNA *ptr)
{
@@ -180,7 +181,7 @@ static void rna_Texture_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *pt
static void rna_Texture_mapping_update(Main *bmain, Scene *scene, PointerRNA *ptr)
{
TexMapping *texmap = ptr->data;
- init_tex_mapping(texmap);
+ BKE_texture_mapping_init(texmap);
rna_Texture_update(bmain, scene, ptr);
}
@@ -221,7 +222,7 @@ static void rna_Texture_type_set(PointerRNA *ptr, int value)
{
Tex *tex = (Tex *)ptr->data;
- tex_set_type(tex, value);
+ BKE_texture_type_set(tex, value);
}
void rna_TextureSlot_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
@@ -439,13 +440,13 @@ static void rna_ImageTexture_mipmap_set(PointerRNA *ptr, int value)
else tex->imaflag &= ~TEX_MIPMAP;
}
-static void rna_Envmap_source_update(Main *bmain, Scene *scene, PointerRNA *ptr)
+static void rna_Envmap_update_generic(Main *bmain, Scene *scene, PointerRNA *ptr)
{
Tex *tex = ptr->id.data;
-
- if (tex->env)
- BKE_free_envmapdata(tex->env);
-
+ if (tex->env) {
+ ED_preview_kill_jobs(bmain->wm.first, bmain);
+ BKE_texture_envmap_free_data(tex->env);
+ }
rna_Texture_update(bmain, scene, ptr);
}
@@ -803,7 +804,7 @@ static void rna_def_environment_map(BlenderRNA *brna)
RNA_def_property_enum_sdna(prop, NULL, "stype");
RNA_def_property_enum_items(prop, prop_source_items);
RNA_def_property_ui_text(prop, "Source", "");
- RNA_def_property_update(prop, 0, "rna_Envmap_source_update");
+ RNA_def_property_update(prop, 0, "rna_Envmap_update_generic");
prop = RNA_def_property(srna, "viewpoint_object", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "object");
@@ -1391,7 +1392,7 @@ static void rna_def_texture_environment_map(BlenderRNA *brna)
RNA_def_property_struct_type(prop, "Image");
RNA_def_property_flag(prop, PROP_EDITABLE);
RNA_def_property_ui_text(prop, "Image", "Source image file to read the environment map from");
- RNA_def_property_update(prop, 0, "rna_Texture_update");
+ RNA_def_property_update(prop, 0, "rna_Envmap_update_generic");
prop = RNA_def_property(srna, "image_user", PROP_POINTER, PROP_NEVER_NULL);
RNA_def_property_pointer_sdna(prop, NULL, "iuser");
@@ -1848,6 +1849,7 @@ static void rna_def_texture_voxeldata(BlenderRNA *brna)
{TEX_VD_IMAGE_SEQUENCE, "IMAGE_SEQUENCE", 0, "Image Sequence",
"Generate voxels from a sequence of image slices"},
{TEX_VD_SMOKE, "SMOKE", 0, "Smoke", "Render voxels from a Blender smoke simulation"},
+ {TEX_VD_HAIR, "HAIR", 0, "Hair", "Render voxels from a Blender hair simulation"},
{0, NULL, 0, NULL, NULL}
};
@@ -1866,6 +1868,14 @@ static void rna_def_texture_voxeldata(BlenderRNA *brna)
{0, NULL, 0, NULL, NULL}
};
+ static EnumPropertyItem hair_type_items[] = {
+ {TEX_VD_HAIRDENSITY, "HAIRDENSITY", 0, "Density", "Use hair density as texture data"},
+ {TEX_VD_HAIRRESTDENSITY, "HAIRRESTDENSITY", 0, "Rest Density", "Use hair rest density as texture data"},
+ {TEX_VD_HAIRVELOCITY, "HAIRVELOCITY", 0, "Velocity", "Use hair velocity as texture data"},
+ {TEX_VD_HAIRENERGY, "HAIRENERGY", 0, "Energy", "Use potential hair energy as texture data"},
+ {0, NULL, 0, NULL, NULL}
+ };
+
srna = RNA_def_struct(brna, "VoxelData", NULL);
RNA_def_struct_sdna(srna, "VoxelData");
RNA_def_struct_ui_text(srna, "VoxelData", "Voxel data settings");
@@ -1883,6 +1893,12 @@ static void rna_def_texture_voxeldata(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Source", "Simulation value to be used as a texture");
RNA_def_property_update(prop, 0, "rna_Texture_voxeldata_update");
+ prop = RNA_def_property(srna, "hair_data_type", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "hair_type");
+ RNA_def_property_enum_items(prop, hair_type_items);
+ RNA_def_property_ui_text(prop, "Source", "Simulation value to be used as a texture");
+ RNA_def_property_update(prop, 0, "rna_Texture_voxeldata_update");
+
prop = RNA_def_property(srna, "extension", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "extend");
RNA_def_property_enum_items(prop, voxeldata_extension);
diff --git a/source/blender/makesrna/intern/rna_texture_api.c b/source/blender/makesrna/intern/rna_texture_api.c
index 695a3e0548e..a27ba6ea06d 100644
--- a/source/blender/makesrna/intern/rna_texture_api.c
+++ b/source/blender/makesrna/intern/rna_texture_api.c
@@ -60,7 +60,7 @@ static void clear_envmap(struct EnvMap *env, bContext *C)
Main *bmain = CTX_data_main(C);
Tex *tex;
- BKE_free_envmapdata(env);
+ BKE_texture_envmap_free_data(env);
for (tex = bmain->tex.first; tex; tex = tex->id.next)
if (tex->env == env) {
@@ -74,7 +74,7 @@ static void texture_evaluate(struct Tex *tex, float value[3], float r_color[4])
TexResult texres = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0, NULL};
/* TODO(sergey): always use color management now. */
- multitex_ext(tex, value, NULL, NULL, 1, &texres, NULL, true);
+ multitex_ext(tex, value, NULL, NULL, 1, &texres, NULL, true, false);
r_color[0] = texres.tr;
r_color[1] = texres.tg;
diff --git a/source/blender/makesrna/intern/rna_tracking.c b/source/blender/makesrna/intern/rna_tracking.c
index 899da62d9d3..5a70d47a19a 100644
--- a/source/blender/makesrna/intern/rna_tracking.c
+++ b/source/blender/makesrna/intern/rna_tracking.c
@@ -1435,8 +1435,8 @@ static void rna_def_trackingTrack(BlenderRNA *brna)
/* grease pencil */
prop = RNA_def_property(srna, "grease_pencil", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "gpd");
- RNA_def_property_flag(prop, PROP_EDITABLE);
RNA_def_property_struct_type(prop, "GreasePencil");
+ RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_REFCOUNT);
RNA_def_property_ui_text(prop, "Grease Pencil", "Grease pencil data for this track");
RNA_def_property_update(prop, NC_MOVIECLIP | ND_DISPLAY, NULL);
diff --git a/source/blender/makesrna/intern/rna_ui.c b/source/blender/makesrna/intern/rna_ui.c
index 92c5530202b..2595771bece 100644
--- a/source/blender/makesrna/intern/rna_ui.c
+++ b/source/blender/makesrna/intern/rna_ui.c
@@ -29,7 +29,7 @@
#include "DNA_screen_types.h"
-#include "BLF_translation.h"
+#include "BLT_translation.h"
#include "BKE_idprop.h"
@@ -199,7 +199,7 @@ static StructRNA *rna_Panel_register(Main *bmain, ReportList *reports, void *dat
RNA_pointer_create(NULL, &RNA_Panel, &dummypanel, &dummyptr);
/* We have to set default context! Else we get a void string... */
- strcpy(dummypt.translation_context, BLF_I18NCONTEXT_DEFAULT_BPYRNA);
+ strcpy(dummypt.translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
/* validate the python class */
if (validate(&dummyptr, data, have_function) != 0)
@@ -221,7 +221,7 @@ static StructRNA *rna_Panel_register(Main *bmain, ReportList *reports, void *dat
/* check if we have registered this panel type before, and remove it */
for (pt = art->paneltypes.first; pt; pt = pt->next) {
- if (strcmp(pt->idname, dummypt.idname) == 0) {
+ if (STREQ(pt->idname, dummypt.idname)) {
if (pt->ext.srna)
rna_Panel_unregister(bmain, pt->ext.srna);
else
@@ -587,7 +587,7 @@ static StructRNA *rna_Header_register(Main *bmain, ReportList *reports, void *da
/* check if we have registered this header type before, and remove it */
for (ht = art->headertypes.first; ht; ht = ht->next) {
- if (strcmp(ht->idname, dummyht.idname) == 0) {
+ if (STREQ(ht->idname, dummyht.idname)) {
if (ht->ext.srna)
rna_Header_unregister(bmain, ht->ext.srna);
break;
@@ -700,7 +700,7 @@ static StructRNA *rna_Menu_register(Main *bmain, ReportList *reports, void *data
RNA_pointer_create(NULL, &RNA_Menu, &dummymenu, &dummymtr);
/* We have to set default context! Else we get a void string... */
- strcpy(dummymt.translation_context, BLF_I18NCONTEXT_DEFAULT_BPYRNA);
+ strcpy(dummymt.translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
/* validate the python class */
if (validate(&dummymtr, data, have_function) != 0)
@@ -936,7 +936,7 @@ static void rna_def_panel(BlenderRNA *brna)
RNA_def_struct_sdna(srna, "Panel");
RNA_def_struct_refine_func(srna, "rna_Panel_refine");
RNA_def_struct_register_funcs(srna, "rna_Panel_register", "rna_Panel_unregister", NULL);
- RNA_def_struct_translation_context(srna, BLF_I18NCONTEXT_DEFAULT_BPYRNA);
+ RNA_def_struct_translation_context(srna, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
/* poll */
func = RNA_def_function(srna, "poll", NULL);
@@ -986,7 +986,7 @@ static void rna_def_panel(BlenderRNA *brna)
prop = RNA_def_property(srna, "bl_translation_context", PROP_STRING, PROP_NONE);
RNA_def_property_string_sdna(prop, NULL, "type->translation_context");
- RNA_def_property_string_default(prop, BLF_I18NCONTEXT_DEFAULT_BPYRNA);
+ RNA_def_property_string_default(prop, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
RNA_def_property_flag(prop, PROP_REGISTER_OPTIONAL);
RNA_define_verify_sdna(true);
@@ -1062,6 +1062,7 @@ static void rna_def_uilist(BlenderRNA *brna)
prop = RNA_def_property(srna, "filter_name", PROP_STRING, PROP_NONE);
RNA_def_property_string_sdna(prop, NULL, "filter_byname");
+ RNA_def_property_flag(prop, PROP_TEXTEDIT_UPDATE);
RNA_def_property_ui_text(prop, "Filter by Name", "Only show items matching this name (use '*' as wildcard)");
prop = RNA_def_property(srna, "use_filter_invert", PROP_BOOLEAN, PROP_NONE);
@@ -1205,7 +1206,7 @@ static void rna_def_menu(BlenderRNA *brna)
RNA_def_struct_sdna(srna, "Menu");
RNA_def_struct_refine_func(srna, "rna_Menu_refine");
RNA_def_struct_register_funcs(srna, "rna_Menu_register", "rna_Menu_unregister", NULL);
- RNA_def_struct_translation_context(srna, BLF_I18NCONTEXT_DEFAULT_BPYRNA);
+ RNA_def_struct_translation_context(srna, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
/* poll */
func = RNA_def_function(srna, "poll", NULL);
@@ -1246,7 +1247,7 @@ static void rna_def_menu(BlenderRNA *brna)
prop = RNA_def_property(srna, "bl_translation_context", PROP_STRING, PROP_NONE);
RNA_def_property_string_sdna(prop, NULL, "type->translation_context");
- RNA_def_property_string_default(prop, BLF_I18NCONTEXT_DEFAULT_BPYRNA);
+ RNA_def_property_string_default(prop, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
RNA_def_property_flag(prop, PROP_REGISTER_OPTIONAL);
prop = RNA_def_property(srna, "bl_description", PROP_STRING, PROP_NONE);
diff --git a/source/blender/makesrna/intern/rna_ui_api.c b/source/blender/makesrna/intern/rna_ui_api.c
index b13bdedaffd..81b6a77f683 100644
--- a/source/blender/makesrna/intern/rna_ui_api.c
+++ b/source/blender/makesrna/intern/rna_ui_api.c
@@ -34,7 +34,7 @@
#include "BLI_utildefines.h"
-#include "BLF_translation.h"
+#include "BLT_translation.h"
#include "RNA_define.h"
#include "RNA_enum_types.h"
@@ -64,13 +64,13 @@ static const char *rna_translate_ui_text(const char *text, const char *text_ctxt
int translate)
{
/* Also return text if UI labels translation is disabled. */
- if (!text || !text[0] || !translate || !BLF_translate_iface()) {
+ if (!text || !text[0] || !translate || !BLT_translate_iface()) {
return text;
}
/* If a text_ctxt is specified, use it! */
if (text_ctxt && text_ctxt[0]) {
- return BLF_pgettext(text_ctxt, text);
+ return BLT_pgettext(text_ctxt, text);
}
/* Else, if an RNA type or property is specified, use its context. */
@@ -82,17 +82,17 @@ static const char *rna_translate_ui_text(const char *text, const char *text_ctxt
* if default context is not suitable.
*/
if (prop) {
- return BLF_pgettext(RNA_property_translation_context(prop), text);
+ return BLT_pgettext(RNA_property_translation_context(prop), text);
}
#else
(void)prop;
#endif
if (type) {
- return BLF_pgettext(RNA_struct_translation_context(type), text);
+ return BLT_pgettext(RNA_struct_translation_context(type), text);
}
/* Else, default context! */
- return BLF_pgettext(BLF_I18NCONTEXT_DEFAULT, text);
+ return BLT_pgettext(BLT_I18NCONTEXT_DEFAULT, text);
}
static void rna_uiItemR(uiLayout *layout, PointerRNA *ptr, const char *propname, const char *name, const char *text_ctxt,
@@ -137,9 +137,7 @@ static void rna_uiItemMenuEnumR(uiLayout *layout, struct PointerRNA *ptr, const
/* Get translated name (label). */
name = rna_translate_ui_text(name, text_ctxt, NULL, prop, translate);
-
- /* XXX This will search property again :( */
- uiItemMenuEnumR(layout, ptr, propname, name, icon);
+ uiItemMenuEnumR_prop(layout, ptr, prop, name, icon);
}
static void rna_uiItemEnumR_string(uiLayout *layout, struct PointerRNA *ptr, const char *propname, const char *value,
@@ -178,7 +176,7 @@ static void rna_uiItemPointerR(uiLayout *layout, struct PointerRNA *ptr, const c
}
static PointerRNA rna_uiItemO(uiLayout *layout, const char *opname, const char *name, const char *text_ctxt,
- int translate, int icon, int emboss)
+ int translate, int icon, int emboss, int icon_value)
{
wmOperatorType *ot;
int flag;
@@ -192,6 +190,10 @@ static PointerRNA rna_uiItemO(uiLayout *layout, const char *opname, const char *
/* Get translated name (label). */
name = rna_translate_ui_text(name, text_ctxt, ot->srna, NULL, translate);
+ if (icon_value && !icon) {
+ icon = icon_value;
+ }
+
flag = UI_ITEM_O_RETURN_PROPS;
flag |= (emboss) ? 0 : UI_ITEM_R_NO_BG;
@@ -229,11 +231,15 @@ static void rna_uiItemL(uiLayout *layout, const char *name, const char *text_ctx
}
static void rna_uiItemM(uiLayout *layout, bContext *C, const char *menuname, const char *name, const char *text_ctxt,
- int translate, int icon)
+ int translate, int icon, int icon_value)
{
/* Get translated name (label). */
name = rna_translate_ui_text(name, text_ctxt, NULL, NULL, translate);
+ if (icon_value && !icon) {
+ icon = icon_value;
+ }
+
uiItemM(layout, C, menuname, name, icon);
}
@@ -293,7 +299,7 @@ static const char *rna_ui_get_enum_name(bContext *C, PointerRNA *ptr, const char
if (items) {
for (item = items; item->identifier; item++) {
- if (item->identifier[0] && strcmp(item->identifier, identifier) == 0) {
+ if (item->identifier[0] && STREQ(item->identifier, identifier)) {
name = item->name;
break;
}
@@ -324,7 +330,7 @@ static const char *rna_ui_get_enum_description(bContext *C, PointerRNA *ptr, con
if (items) {
for (item = items; item->identifier; item++) {
- if (item->identifier[0] && strcmp(item->identifier, identifier) == 0) {
+ if (item->identifier[0] && STREQ(item->identifier, identifier)) {
desc = item->description;
break;
}
@@ -354,7 +360,7 @@ static int rna_ui_get_enum_icon(bContext *C, PointerRNA *ptr, const char *propna
if (items) {
for (item = items; item->identifier; item++) {
- if (item->identifier[0] && strcmp(item->identifier, identifier) == 0) {
+ if (item->identifier[0] && STREQ(item->identifier, identifier)) {
icon = item->icon;
break;
}
@@ -523,9 +529,7 @@ void RNA_api_ui_layout(StructRNA *srna)
"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()...)");
+ RNA_def_property_ui_text(parm, "Icon Value", "Override automatic icon of the item");
func = RNA_def_function(srna, "props_enum", "uiItemsEnumR");
api_ui_item_rna_common(func);
@@ -551,6 +555,8 @@ void RNA_api_ui_layout(StructRNA *srna)
func = RNA_def_function(srna, "operator", "rna_uiItemO");
api_ui_item_op_common(func);
RNA_def_boolean(func, "emboss", true, "", "Draw the button itself, just the icon/text");
+ parm = RNA_def_property(func, "icon_value", PROP_INT, PROP_UNSIGNED);
+ RNA_def_property_ui_text(parm, "Icon Value", "Override automatic icon of the item");
parm = RNA_def_pointer(func, "properties", "OperatorProperties", "",
"Operator properties to fill in, return when 'properties' is set to true");
RNA_def_property_flag(parm, PROP_REQUIRED | PROP_RNAPTR);
@@ -615,15 +621,15 @@ void RNA_api_ui_layout(StructRNA *srna)
RNA_def_function_ui_description(func, "Item. Display text and/or icon in the layout");
api_ui_item_common(func);
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()...)");
+ RNA_def_property_ui_text(parm, "Icon Value", "Override automatic icon of the item");
func = RNA_def_function(srna, "menu", "rna_uiItemM");
RNA_def_function_flag(func, FUNC_USE_CONTEXT);
parm = RNA_def_string(func, "menu", NULL, 0, "", "Identifier of the menu");
api_ui_item_common(func);
RNA_def_property_flag(parm, PROP_REQUIRED);
+ 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");
func = RNA_def_function(srna, "separator", "uiItemS");
RNA_def_function_ui_description(func, "Item. Inserts empty space into the layout between items");
@@ -676,14 +682,14 @@ void RNA_api_ui_layout(StructRNA *srna)
func = RNA_def_function(srna, "template_modifier", "uiTemplateModifier");
RNA_def_function_flag(func, FUNC_USE_CONTEXT);
- RNA_def_function_ui_description(func, "Layout . Generates the UI layout for modifiers");
+ RNA_def_function_ui_description(func, "Generates the UI layout for modifiers");
parm = RNA_def_pointer(func, "data", "Modifier", "", "Modifier data");
RNA_def_property_flag(parm, PROP_REQUIRED | PROP_RNAPTR | PROP_NEVER_NULL);
parm = RNA_def_pointer(func, "layout", "UILayout", "", "Sub-layout to put items in");
RNA_def_function_return(func, parm);
func = RNA_def_function(srna, "template_constraint", "uiTemplateConstraint");
- RNA_def_function_ui_description(func, "Layout . Generates the UI layout for constraints");
+ RNA_def_function_ui_description(func, "Generates the UI layout for constraints");
parm = RNA_def_pointer(func, "data", "Constraint", "", "Constraint data");
RNA_def_property_flag(parm, PROP_REQUIRED | PROP_RNAPTR | PROP_NEVER_NULL);
parm = RNA_def_pointer(func, "layout", "UILayout", "", "Sub-layout to put items in");
@@ -713,11 +719,13 @@ void RNA_api_ui_layout(StructRNA *srna)
RNA_def_function_ui_description(func, "Item. A color ramp widget");
api_ui_item_rna_common(func);
RNA_def_boolean(func, "expand", false, "", "Expand button to show more detail");
-
+
func = RNA_def_function(srna, "template_icon_view", "uiTemplateIconView");
RNA_def_function_ui_description(func, "Enum. Large widget showing Icon previews");
api_ui_item_rna_common(func);
-
+ RNA_def_boolean(func, "show_labels", false, "", "Show enum label in preview buttons");
+ RNA_def_float(func, "scale", 5.0f, 1.0f, 100.0f, "Scale", "Scale the icon size (by the button size)", 1.0f, 100.0f);
+
func = RNA_def_function(srna, "template_histogram", "uiTemplateHistogram");
RNA_def_function_ui_description(func, "Item. A histogramm widget to analyze imaga data");
api_ui_item_rna_common(func);
@@ -766,6 +774,7 @@ void RNA_api_ui_layout(StructRNA *srna)
parm = RNA_def_pointer(func, "image_user", "ImageUser", "", "");
RNA_def_property_flag(parm, PROP_REQUIRED | PROP_RNAPTR | PROP_NEVER_NULL);
RNA_def_boolean(func, "compact", false, "", "Use more compact layout");
+ RNA_def_boolean(func, "multiview", false, "", "Expose Multi-View options");
func = RNA_def_function(srna, "template_image_settings", "uiTemplateImageSettings");
RNA_def_function_ui_description(func, "User interface for setting image format options");
@@ -773,6 +782,16 @@ void RNA_api_ui_layout(StructRNA *srna)
RNA_def_property_flag(parm, PROP_REQUIRED | PROP_RNAPTR | PROP_NEVER_NULL);
RNA_def_boolean(func, "color_management", false, "", "Show color management settings");
+ func = RNA_def_function(srna, "template_image_stereo_3d", "uiTemplateImageStereo3d");
+ RNA_def_function_ui_description(func, "User interface for setting image stereo 3d options");
+ parm = RNA_def_pointer(func, "stereo_3d_format", "Stereo3dFormat", "", "");
+ RNA_def_property_flag(parm, PROP_REQUIRED | PROP_RNAPTR | PROP_NEVER_NULL);
+
+ func = RNA_def_function(srna, "template_image_views", "uiTemplateImageViews");
+ RNA_def_function_ui_description(func, "User interface for setting image views output options");
+ parm = RNA_def_pointer(func, "image_settings", "ImageFormatSettings", "", "");
+ RNA_def_property_flag(parm, PROP_REQUIRED | PROP_RNAPTR | PROP_NEVER_NULL);
+
func = RNA_def_function(srna, "template_movieclip", "uiTemplateMovieClip");
RNA_def_function_ui_description(func, "Item(s). User interface for selecting movie clips and their source paths");
RNA_def_function_flag(func, FUNC_USE_CONTEXT);
@@ -820,6 +839,8 @@ void RNA_api_ui_layout(StructRNA *srna)
parm = RNA_def_string(func, "active_propname", NULL, 0, "",
"Identifier of the integer property in active_data, index of the active item");
RNA_def_property_flag(parm, PROP_REQUIRED);
+ RNA_def_string(func, "item_dyntip_propname", NULL, 0, "",
+ "Identifier of a string property in items, to use as tooltip content");
RNA_def_int(func, "rows", 5, 0, INT_MAX, "", "Default and minimum number of rows to display", 0, INT_MAX);
RNA_def_int(func, "maxrows", 5, 0, INT_MAX, "", "Default maximum number of rows to display", 0, INT_MAX);
RNA_def_enum(func, "type", uilist_layout_type_items, UILST_LAYOUT_DEFAULT, "Type", "Type of layout to use");
diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c
index aa378955fb0..f2e62e6f559 100644
--- a/source/blender/makesrna/intern/rna_userdef.c
+++ b/source/blender/makesrna/intern/rna_userdef.c
@@ -35,6 +35,8 @@
#include "BLI_utildefines.h"
+#include "BKE_appdir.h"
+#include "BKE_DerivedMesh.h"
#include "BKE_sound.h"
#include "BKE_addon.h"
@@ -47,7 +49,8 @@
#include "WM_api.h"
#include "WM_types.h"
-#include "BLF_translation.h"
+#include "BLT_lang.h"
+#include "GPU_buffers.h"
#ifdef WITH_CYCLES
static EnumPropertyItem compute_device_type_items[] = {
@@ -58,6 +61,19 @@ static EnumPropertyItem compute_device_type_items[] = {
};
#endif
+#ifdef WITH_OPENSUBDIV
+static EnumPropertyItem opensubdiv_compute_type_items[] = {
+ {USER_OPENSUBDIV_COMPUTE_NONE, "NONE", 0, "None", ""},
+ {USER_OPENSUBDIV_COMPUTE_CPU, "CPU", 0, "CPU", ""},
+ {USER_OPENSUBDIV_COMPUTE_OPENMP, "OPENMP", 0, "OpenMP", ""},
+ {USER_OPENSUBDIV_COMPUTE_OPENCL, "OPENCL", 0, "OpenCL", ""},
+ {USER_OPENSUBDIV_COMPUTE_CUDA, "CUDA", 0, "CUDA", ""},
+ {USER_OPENSUBDIV_COMPUTE_GLSL_TRANSFORM_FEEDBACK, "GLSL_TRANSFORM_FEEDBACL", 0, "GLSL Transform Feedback", ""},
+ {USER_OPENSUBDIV_COMPUTE_GLSL_COMPUTE, "GLSL_COMPUTE", 0, "GLSL Compute", ""},
+ { 0, NULL, 0, NULL, NULL}
+};
+#endif
+
static EnumPropertyItem audio_device_items[] = {
{0, "NONE", 0, "None", "Null device - there will be no audio output"},
#ifdef WITH_SDL
@@ -84,11 +100,12 @@ EnumPropertyItem navigation_mode_items[] = {
#include "DNA_screen_types.h"
#include "BKE_blender.h"
-#include "BKE_DerivedMesh.h"
#include "BKE_depsgraph.h"
#include "BKE_global.h"
#include "BKE_main.h"
#include "BKE_idprop.h"
+#include "BKE_pbvh.h"
+#include "BKE_paint.h"
#include "GPU_draw.h"
#include "GPU_select.h"
@@ -102,7 +119,14 @@ EnumPropertyItem navigation_mode_items[] = {
#include "CCL_api.h"
-#include "BKE_addon.h"
+#ifdef WITH_OPENSUBDIV
+# include "opensubdiv_capi.h"
+#endif
+
+#ifdef WITH_SDL_DYNLOAD
+# include "sdlew.h"
+#endif
+
static void rna_userdef_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *UNUSED(ptr))
{
@@ -120,13 +144,42 @@ static void rna_userdef_dpi_update(Main *UNUSED(bmain), Scene *UNUSED(scene), Po
WM_main_add_notifier(NC_SCREEN | NA_EDITED, NULL); /* refresh region sizes */
}
+static void rna_userdef_virtual_pixel_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *UNUSED(ptr))
+{
+ /* font's are stored at each DPI level, without this we can easy load 100's of fonts */
+ BLF_cache_clear();
+
+ BKE_userdef_state();
+ WM_main_add_notifier(NC_WINDOW, NULL); /* full redraw */
+ WM_main_add_notifier(NC_SCREEN | NA_EDITED, NULL); /* refresh region sizes */
+}
+
static void rna_userdef_language_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *UNUSED(ptr))
{
BLF_cache_clear();
- BLF_lang_set(NULL);
+ BLT_lang_set(NULL);
UI_reinit_font();
}
+static void update_cb(PBVHNode *node, void *UNUSED(rebuild))
+{
+ BKE_pbvh_node_mark_rebuild_draw(node);
+}
+
+static void rna_userdef_vbo_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *UNUSED(ptr))
+{
+ Object *ob;
+
+ for (ob = bmain->object.first; ob; ob = ob->id.next) {
+ GPU_drawobject_free(ob->derivedFinal);
+
+ if (ob->sculpt && ob->sculpt->pbvh) {
+ BKE_pbvh_search_callback(ob->sculpt->pbvh, NULL, NULL, update_cb, NULL);
+ }
+ }
+ GPU_buffer_multires_free(false);
+}
+
static void rna_userdef_show_manipulator_update(Main *bmain, Scene *scene, PointerRNA *ptr)
{
UserDef *userdef = (UserDef *)ptr->data;
@@ -199,6 +252,14 @@ static void rna_userdef_gl_use_16bit_textures(Main *bmain, Scene *scene, Pointer
rna_userdef_update(bmain, scene, ptr);
}
+static void rna_userdef_undo_steps_set(PointerRNA *ptr, int value)
+{
+ UserDef *userdef = (UserDef *)ptr->data;
+
+ /* Do not allow 1 undo steps, useless and breaks undo/redo process (see T42531). */
+ userdef->undosteps = (value == 1) ? 2 : value;
+}
+
static void rna_userdef_select_mouse_set(PointerRNA *ptr, int value)
{
UserDef *userdef = (UserDef *)ptr->data;
@@ -236,6 +297,12 @@ static void rna_userdef_autokeymode_set(PointerRNA *ptr, int value)
}
}
+static void rna_userdef_ndof_deadzone_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
+{
+ UserDef *userdef = ptr->data;
+ WM_ndof_deadzone_set(userdef->ndof_deadzone);
+}
+
static void rna_userdef_timecode_style_set(PointerRNA *ptr, int value)
{
UserDef *userdef = (UserDef *)ptr->data;
@@ -297,7 +364,7 @@ static PointerRNA rna_UserDef_system_get(PointerRNA *ptr)
static void rna_UserDef_audio_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *UNUSED(ptr))
{
- sound_init(bmain);
+ BKE_sound_init(bmain);
}
static void rna_Userdef_memcache_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *UNUSED(ptr))
@@ -392,7 +459,7 @@ static void rna_userdef_pathcompare_remove(ReportList *reports, PointerRNA *path
static void rna_userdef_temp_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *UNUSED(ptr))
{
- BLI_temp_dir_init(U.tempdir);
+ BKE_tempdir_init(U.tempdir);
}
static void rna_userdef_text_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *UNUSED(ptr))
@@ -489,47 +556,110 @@ static EnumPropertyItem *rna_userdef_compute_device_itemf(bContext *UNUSED(C), P
}
#endif
+#ifdef WITH_OPENSUBDIV
+static EnumPropertyItem *rna_userdef_opensubdiv_compute_type_itemf(bContext *UNUSED(C), PointerRNA *UNUSED(ptr),
+ PropertyRNA *UNUSED(prop), bool *r_free)
+{
+ EnumPropertyItem *item = NULL;
+ int totitem = 0;
+ int evaluators = openSubdiv_getAvailableEvaluators();
+
+ RNA_enum_items_add_value(&item, &totitem, opensubdiv_compute_type_items, USER_OPENSUBDIV_COMPUTE_NONE);
+
+#define APPEND_COMPUTE(compute) \
+ if (evaluators & OPENSUBDIV_EVALUATOR_## compute) { \
+ RNA_enum_items_add_value(&item, &totitem, opensubdiv_compute_type_items, USER_OPENSUBDIV_COMPUTE_ ## compute); \
+ } ((void)0)
+
+ APPEND_COMPUTE(CPU);
+ APPEND_COMPUTE(OPENMP);
+ APPEND_COMPUTE(OPENCL);
+ APPEND_COMPUTE(CUDA);
+ APPEND_COMPUTE(GLSL_TRANSFORM_FEEDBACK);
+ APPEND_COMPUTE(GLSL_COMPUTE);
+
+#undef APPEND_COMPUTE
+
+ RNA_enum_item_end(&item, &totitem);
+ *r_free = true;
+
+ return item;
+}
+
+static void rna_userdef_opensubdiv_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *UNUSED(ptr))
+{
+ Object *object;
+
+ for (object = bmain->object.first;
+ object;
+ object = object->id.next)
+ {
+ if (object->derivedFinal != NULL &&
+ object->derivedFinal->type == DM_TYPE_CCGDM)
+ {
+ DAG_id_tag_update(&object->id, OB_RECALC_OB);
+ }
+ }
+}
+
+#endif
+
static EnumPropertyItem *rna_userdef_audio_device_itemf(bContext *UNUSED(C), PointerRNA *UNUSED(ptr),
PropertyRNA *UNUSED(prop), bool *r_free)
{
-#ifdef WITH_JACK
- int jack_supported = sound_is_jack_supported();
+ int index = 0;
+ int totitem = 0;
+ EnumPropertyItem *item = NULL;
- if (jack_supported) {
- return audio_device_items;
- }
- else {
- int index = 0;
- int totitem = 0;
- EnumPropertyItem *item = NULL;
+#ifdef WITH_SYSTEM_AUDASPACE
+ int i;
- /* NONE */
- RNA_enum_item_add(&item, &totitem, &audio_device_items[index++]);
+ char **names = BKE_sound_get_device_names();
+
+ for (i = 0; names[i]; i++) {
+ EnumPropertyItem new_item = {i, names[i], 0, names[i], names[i]};
+ RNA_enum_item_add(&item, &totitem, &new_item);
+ }
+#else
+ /* NONE */
+ RNA_enum_item_add(&item, &totitem, &audio_device_items[index++]);
#ifdef WITH_SDL
- RNA_enum_item_add(&item, &totitem, &audio_device_items[index++]);
+# ifdef WITH_SDL_DYNLOAD
+ if (sdlewInit() == SDLEW_SUCCESS)
+# endif
+ {
+ RNA_enum_item_add(&item, &totitem, &audio_device_items[index]);
+ }
+ index++;
#endif
#ifdef WITH_OPENAL
- RNA_enum_item_add(&item, &totitem, &audio_device_items[index++]);
+ RNA_enum_item_add(&item, &totitem, &audio_device_items[index++]);
#endif
- RNA_enum_item_end(&item, &totitem);
- *r_free = true;
-
- return item;
+#ifdef WITH_JACK
+ if (BKE_sound_is_jack_supported()) {
+ RNA_enum_item_add(&item, &totitem, &audio_device_items[index]);
}
-#else
- (void)r_free;
- return audio_device_items;
+ index++;
#endif
+#endif
+
+ /* may be unused */
+ UNUSED_VARS(index, audio_device_items);
+
+ RNA_enum_item_end(&item, &totitem);
+ *r_free = true;
+
+ return item;
}
#ifdef WITH_INTERNATIONAL
static EnumPropertyItem *rna_lang_enum_properties_itemf(bContext *UNUSED(C), PointerRNA *UNUSED(ptr),
PropertyRNA *UNUSED(prop), bool *UNUSED(r_free))
{
- return BLF_RNA_lang_enum_properties();
+ return BLT_lang_RNA_enum_properties();
}
#endif
@@ -1008,6 +1138,12 @@ static void rna_def_userdef_theme_ui(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Icon Alpha", "Transparency of icons in the interface, to reduce contrast");
RNA_def_property_update(prop, 0, "rna_userdef_update");
+ prop = RNA_def_property(srna, "widget_emboss", PROP_FLOAT, PROP_COLOR_GAMMA);
+ RNA_def_property_float_sdna(prop, NULL, "widget_emboss");
+ RNA_def_property_array(prop, 4);
+ RNA_def_property_ui_text(prop, "Widget Emboss", "Color of the 1px shadow line underlying widgets");
+ RNA_def_property_update(prop, 0, "rna_userdef_update");
+
/* axis */
prop = RNA_def_property(srna, "axis_x", PROP_FLOAT, PROP_COLOR_GAMMA);
RNA_def_property_float_sdna(prop, NULL, "xaxis");
@@ -1447,6 +1583,26 @@ static void rna_def_userdef_theme_spaces_curves(StructRNA *srna, bool incl_nurbs
}
}
+static void rna_def_userdef_theme_spaces_gpencil(StructRNA *srna)
+{
+ PropertyRNA *prop;
+
+ prop = RNA_def_property(srna, "gp_vertex", PROP_FLOAT, PROP_COLOR_GAMMA);
+ RNA_def_property_array(prop, 3);
+ RNA_def_property_ui_text(prop, "Grease Pencil Vertex", "");
+ RNA_def_property_update(prop, 0, "rna_userdef_update");
+
+ prop = RNA_def_property(srna, "gp_vertex_select", PROP_FLOAT, PROP_COLOR_GAMMA);
+ RNA_def_property_array(prop, 3);
+ RNA_def_property_ui_text(prop, "Grease Pencil Vertex Select", "");
+ RNA_def_property_update(prop, 0, "rna_userdef_update");
+
+ prop = RNA_def_property(srna, "gp_vertex_size", PROP_INT, PROP_NONE);
+ RNA_def_property_range(prop, 1, 10);
+ RNA_def_property_ui_text(prop, "Grease Pencil Vertex Size", "");
+ RNA_def_property_update(prop, 0, "rna_userdef_update");
+}
+
static void rna_def_userdef_theme_space_view3d(BlenderRNA *brna)
{
StructRNA *srna;
@@ -1475,6 +1631,8 @@ static void rna_def_userdef_theme_space_view3d(BlenderRNA *brna)
RNA_def_property_array(prop, 3);
RNA_def_property_ui_text(prop, "Wire Edit", "");
RNA_def_property_update(prop, 0, "rna_userdef_update");
+
+ rna_def_userdef_theme_spaces_gpencil(srna);
prop = RNA_def_property(srna, "lamp", PROP_FLOAT, PROP_COLOR_GAMMA);
RNA_def_property_array(prop, 4);
@@ -1619,6 +1777,11 @@ static void rna_def_userdef_theme_space_view3d(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Skin Root", "");
RNA_def_property_update(prop, 0, "rna_userdef_update");
+ prop = RNA_def_property(srna, "clipping_border_3d", PROP_FLOAT, PROP_COLOR_GAMMA);
+ RNA_def_property_array(prop, 4);
+ RNA_def_property_ui_text(prop, "Clipping Border", "");
+ RNA_def_property_update(prop, 0, "rna_userdef_update");
+
rna_def_userdef_theme_spaces_paint_curves(srna);
}
@@ -2005,6 +2168,8 @@ static void rna_def_userdef_theme_space_node(BlenderRNA *brna)
rna_def_userdef_theme_spaces_main(srna);
rna_def_userdef_theme_spaces_list_main(srna);
+
+ rna_def_userdef_theme_spaces_gpencil(srna);
prop = RNA_def_property(srna, "node_selected", PROP_FLOAT, PROP_COLOR_GAMMA);
RNA_def_property_float_sdna(prop, NULL, "select");
@@ -2024,6 +2189,12 @@ static void rna_def_userdef_theme_space_node(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Wires", "");
RNA_def_property_update(prop, 0, "rna_userdef_update");
+ prop = RNA_def_property(srna, "wire_inner", PROP_FLOAT, PROP_COLOR_GAMMA);
+ RNA_def_property_float_sdna(prop, NULL, "syntaxr");
+ RNA_def_property_array(prop, 3);
+ RNA_def_property_ui_text(prop, "Wire Color", "");
+ RNA_def_property_update(prop, 0, "rna_userdef_update");
+
prop = RNA_def_property(srna, "wire_select", PROP_FLOAT, PROP_COLOR_GAMMA);
RNA_def_property_float_sdna(prop, NULL, "edge_select");
RNA_def_property_array(prop, 3);
@@ -2203,6 +2374,18 @@ static void rna_def_userdef_theme_space_time(BlenderRNA *brna)
RNA_def_property_array(prop, 3);
RNA_def_property_ui_text(prop, "Current Frame", "");
RNA_def_property_update(prop, 0, "rna_userdef_update");
+
+ prop = RNA_def_property(srna, "time_keyframe", PROP_FLOAT, PROP_COLOR_GAMMA);
+ RNA_def_property_float_sdna(prop, NULL, "time_keyframe");
+ RNA_def_property_array(prop, 3);
+ RNA_def_property_ui_text(prop, "Keyframe", "Base color for keyframe indicator lines");
+ RNA_def_property_update(prop, 0, "rna_userdef_update");
+
+ prop = RNA_def_property(srna, "time_grease_pencil", PROP_FLOAT, PROP_COLOR_GAMMA);
+ RNA_def_property_float_sdna(prop, NULL, "time_gp_keyframe");
+ RNA_def_property_array(prop, 3);
+ RNA_def_property_ui_text(prop, "Grease Pencil", "Color of Grease Pencil keyframes");
+ RNA_def_property_update(prop, 0, "rna_userdef_update");
}
static void rna_def_userdef_theme_space_image(BlenderRNA *brna)
@@ -2218,8 +2401,10 @@ static void rna_def_userdef_theme_space_image(BlenderRNA *brna)
RNA_def_struct_ui_text(srna, "Theme Image Editor", "Theme settings for the Image Editor");
rna_def_userdef_theme_spaces_main(srna);
+ rna_def_userdef_theme_spaces_gpencil(srna);
rna_def_userdef_theme_spaces_vertex(srna);
rna_def_userdef_theme_spaces_face(srna);
+
prop = RNA_def_property(srna, "editmesh_active", PROP_FLOAT, PROP_COLOR_GAMMA);
RNA_def_property_array(prop, 4);
@@ -2296,6 +2481,18 @@ static void rna_def_userdef_theme_space_image(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Current Frame", "");
RNA_def_property_update(prop, 0, "rna_userdef_update");
+ prop = RNA_def_property(srna, "metadatabg", PROP_FLOAT, PROP_COLOR_GAMMA);
+ RNA_def_property_float_sdna(prop, NULL, "metadatabg");
+ RNA_def_property_array(prop, 3);
+ RNA_def_property_ui_text(prop, "Metadata Background", "");
+ RNA_def_property_update(prop, 0, "rna_userdef_update");
+
+ prop = RNA_def_property(srna, "metadatatext", PROP_FLOAT, PROP_COLOR_GAMMA);
+ RNA_def_property_float_sdna(prop, NULL, "metadatatext");
+ RNA_def_property_array(prop, 3);
+ RNA_def_property_ui_text(prop, "Metadata Text", "");
+ RNA_def_property_update(prop, 0, "rna_userdef_update");
+
rna_def_userdef_theme_spaces_curves(srna, false, false, false, true);
rna_def_userdef_theme_spaces_paint_curves(srna);
@@ -2314,6 +2511,7 @@ static void rna_def_userdef_theme_space_seq(BlenderRNA *brna)
RNA_def_struct_ui_text(srna, "Theme Sequence Editor", "Theme settings for the Sequence Editor");
rna_def_userdef_theme_spaces_main(srna);
+ rna_def_userdef_theme_spaces_gpencil(srna);
prop = RNA_def_property(srna, "grid", PROP_FLOAT, PROP_COLOR_GAMMA);
RNA_def_property_array(prop, 3);
@@ -2397,6 +2595,18 @@ static void rna_def_userdef_theme_space_seq(BlenderRNA *brna)
RNA_def_property_array(prop, 3);
RNA_def_property_ui_text(prop, "Preview Background", "");
RNA_def_property_update(prop, 0, "rna_userdef_update");
+
+ prop = RNA_def_property(srna, "metadatabg", PROP_FLOAT, PROP_COLOR_GAMMA);
+ RNA_def_property_float_sdna(prop, NULL, "metadatabg");
+ RNA_def_property_array(prop, 3);
+ RNA_def_property_ui_text(prop, "Metadata Background", "");
+ RNA_def_property_update(prop, 0, "rna_userdef_update");
+
+ prop = RNA_def_property(srna, "metadatatext", PROP_FLOAT, PROP_COLOR_GAMMA);
+ RNA_def_property_float_sdna(prop, NULL, "metadatatext");
+ RNA_def_property_array(prop, 3);
+ RNA_def_property_ui_text(prop, "Metadata Text", "");
+ RNA_def_property_update(prop, 0, "rna_userdef_update");
}
static void rna_def_userdef_theme_space_action(BlenderRNA *brna)
@@ -2725,6 +2935,8 @@ static void rna_def_userdef_theme_space_clip(BlenderRNA *brna)
rna_def_userdef_theme_spaces_main(srna);
rna_def_userdef_theme_spaces_list_main(srna);
+
+ rna_def_userdef_theme_spaces_gpencil(srna);
prop = RNA_def_property(srna, "marker_outline", PROP_FLOAT, PROP_COLOR_GAMMA);
RNA_def_property_float_sdna(prop, NULL, "marker_outline");
@@ -2774,11 +2986,6 @@ static void rna_def_userdef_theme_space_clip(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Path After", "Color of path after current frame");
RNA_def_property_update(prop, 0, "rna_userdef_update");
- prop = RNA_def_property(srna, "grid", PROP_FLOAT, PROP_COLOR_GAMMA);
- RNA_def_property_array(prop, 3);
- RNA_def_property_ui_text(prop, "Grid", "");
- RNA_def_property_update(prop, 0, "rna_userdef_update");
-
prop = RNA_def_property(srna, "frame_current", PROP_FLOAT, PROP_COLOR_GAMMA);
RNA_def_property_float_sdna(prop, NULL, "cframe");
RNA_def_property_array(prop, 3);
@@ -3151,7 +3358,14 @@ static void rna_def_userdef_view(BlenderRNA *brna)
"Direct conversion of frame numbers to seconds"},
{0, NULL, 0, NULL, NULL}
};
-
+
+ static EnumPropertyItem zoom_frame_modes[] = {
+ {ZOOM_FRAME_MODE_KEEP_RANGE, "KEEP_RANGE", 0, "Keep Range", ""},
+ {ZOOM_FRAME_MODE_SECONDS, "SECONDS", 0, "Seconds", ""},
+ {ZOOM_FRAME_MODE_KEYFRAMES, "KEYFRAMES", 0, "Keyframes", ""},
+ {0, NULL, 0, NULL, NULL}
+ };
+
PropertyRNA *prop;
StructRNA *srna;
@@ -3240,10 +3454,20 @@ static void rna_def_userdef_view(BlenderRNA *brna)
RNA_def_property_range(prop, 0, 1000);
RNA_def_property_ui_text(prop, "Threshold", "Distance from center needed before a selection can be made");
+ prop = RNA_def_property(srna, "pie_menu_confirm", PROP_INT, PROP_PIXEL);
+ RNA_def_property_range(prop, 0, 1000);
+ RNA_def_property_ui_text(prop, "Confirm Threshold",
+ "Distance threshold after which selection is made (zero to disable)");
+
prop = RNA_def_property(srna, "use_quit_dialog", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "uiflag", USER_QUIT_PROMPT);
RNA_def_property_ui_text(prop, "Prompt Quit",
- "Asks for confirmation when quitting through the window close button");
+ "Ask for confirmation when quitting through the window close button");
+
+ prop = RNA_def_property(srna, "use_gl_warn_support", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_negative_sdna(prop, NULL, "uiflag2", USER_OPENGL_NO_WARN_SUPPORT);
+ RNA_def_property_ui_text(prop, "Warn On Deprecated OpenGL",
+ "Pop up a warning when an old OpenGL version is detected");
/* Toolbox click-hold delay */
prop = RNA_def_property(srna, "open_left_mouse_delay", PROP_INT, PROP_NONE);
@@ -3330,8 +3554,8 @@ static void rna_def_userdef_view(BlenderRNA *brna)
RNA_def_property_range(prop, 0, 1000);
RNA_def_property_ui_text(prop, "Smooth View", "Time to animate the view in milliseconds, zero to disable");
- prop = RNA_def_property(srna, "rotation_angle", PROP_INT, PROP_NONE);
- RNA_def_property_int_sdna(prop, NULL, "pad_rot_angle");
+ prop = RNA_def_property(srna, "rotation_angle", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "pad_rot_angle");
RNA_def_property_range(prop, 0, 90);
RNA_def_property_ui_text(prop, "Rotation Angle", "Rotation step for numerical pad keys (2 4 6 8)");
@@ -3383,6 +3607,22 @@ static void rna_def_userdef_view(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "TimeCode Style",
"Format of Time Codes displayed when not displaying timing in terms of frames");
RNA_def_property_update(prop, 0, "rna_userdef_update");
+
+ prop = RNA_def_property(srna, "view_frame_type", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_items(prop, zoom_frame_modes);
+ RNA_def_property_enum_sdna(prop, NULL, "view_frame_type");
+ RNA_def_property_ui_text(prop, "Zoom To Frame Type", "How zooming to frame focuses around current frame");
+
+ prop = RNA_def_property(srna, "view_frame_keyframes", PROP_INT, PROP_NONE);
+ RNA_def_property_range(prop, 1, 500);
+ RNA_def_property_ui_text(prop, "Zoom Keyframes",
+ "Keyframes around cursor that we zoom around");
+
+ prop = RNA_def_property(srna, "view_frame_seconds", PROP_FLOAT, PROP_TIME);
+ RNA_def_property_range(prop, 0.0, 10000.0);
+ RNA_def_property_ui_text(prop, "Zoom Seconds",
+ "Seconds around cursor that we zoom around");
+
}
static void rna_def_userdef_edit(BlenderRNA *brna)
@@ -3442,7 +3682,8 @@ static void rna_def_userdef_edit(BlenderRNA *brna)
/* Undo */
prop = RNA_def_property(srna, "undo_steps", PROP_INT, PROP_NONE);
RNA_def_property_int_sdna(prop, NULL, "undosteps");
- RNA_def_property_range(prop, 0, 64);
+ RNA_def_property_range(prop, 0, 256);
+ RNA_def_property_int_funcs(prop, NULL, "rna_userdef_undo_steps_set", NULL);
RNA_def_property_ui_text(prop, "Undo Steps", "Number of undo steps available (smaller values conserve memory)");
prop = RNA_def_property(srna, "undo_memory_limit", PROP_INT, PROP_NONE);
@@ -3502,7 +3743,7 @@ static void rna_def_userdef_edit(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "New Interpolation Type",
"Interpolation mode used for first keyframe on newly added F-Curves "
"(subsequent keyframes take interpolation from preceding keyframe)");
-
+
prop = RNA_def_property(srna, "keyframe_new_handle_type", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, keyframe_handle_type_items);
RNA_def_property_enum_sdna(prop, NULL, "keyhandles_new");
@@ -3549,7 +3790,7 @@ static void rna_def_userdef_edit(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Grease Pencil Eraser Radius", "Radius of eraser 'brush'");
- prop = RNA_def_property(srna, "grease_pencil_default_color", PROP_FLOAT, PROP_COLOR);
+ prop = RNA_def_property(srna, "grease_pencil_default_color", PROP_FLOAT, PROP_COLOR_GAMMA);
RNA_def_property_float_sdna(prop, NULL, "gpencil_new_layer_col");
RNA_def_property_array(prop, 4);
RNA_def_property_ui_text(prop, "Grease Pencil Default Color", "Color of new Grease Pencil layers");
@@ -3610,6 +3851,12 @@ static void rna_def_userdef_edit(BlenderRNA *brna)
prop = RNA_def_property(srna, "use_duplicate_particle", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "dupflag", USER_DUP_PSYS);
RNA_def_property_ui_text(prop, "Duplicate Particle", "Causes particle systems to be duplicated with the object");
+
+ /* currently only used for insert offset (aka auto-offset), maybe also be useful for later stuff though */
+ prop = RNA_def_property(srna, "node_margin", PROP_INT, PROP_NONE);
+ RNA_def_property_int_sdna(prop, NULL, "node_margin");
+ RNA_def_property_ui_text(prop, "Auto-offset Margin", "Minimum distance between nodes for Auto-offsetting nodes");
+ RNA_def_property_update(prop, 0, "rna_userdef_update");
}
static void rna_def_userdef_system(BlenderRNA *brna)
@@ -3743,6 +3990,12 @@ static void rna_def_userdef_system(BlenderRNA *brna)
{0, NULL, 0, NULL, NULL}
};
+ static EnumPropertyItem virtual_pixel_mode_items[] = {
+ {VIRTUAL_PIXEL_NATIVE, "NATIVE", 0, "Native", "Use native pixel size of the display"},
+ {VIRTUAL_PIXEL_DOUBLE, "DOUBLE", 0, "Double", "Use double the native pixel size of the display"},
+ {0, NULL, 0, NULL, NULL}
+ };
+
srna = RNA_def_struct(brna, "UserPreferencesSystem", NULL);
RNA_def_struct_sdna(srna, "UserDef");
RNA_def_struct_nested(brna, srna, "UserPreferences");
@@ -3762,6 +4015,17 @@ static void rna_def_userdef_system(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "DPI", "Font size and resolution for display");
RNA_def_property_update(prop, 0, "rna_userdef_dpi_update");
+ prop = RNA_def_property(srna, "virtual_pixel_mode", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "virtual_pixel");
+ RNA_def_property_enum_items(prop, virtual_pixel_mode_items);
+ RNA_def_property_ui_text(prop, "Virtual Pixel Mode", "Modify the pixel size for hi-res devices");
+ RNA_def_property_update(prop, 0, "rna_userdef_virtual_pixel_update");
+
+ prop = RNA_def_property(srna, "pixel_size", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_property_float_sdna(prop, NULL, "pixelsize");
+ RNA_def_property_ui_text(prop, "Pixel Size", "");
+
prop = RNA_def_property(srna, "font_path_ui", PROP_STRING, PROP_FILEPATH);
RNA_def_property_string_sdna(prop, NULL, "font_path_ui");
RNA_def_property_ui_text(prop, "Interface Font", "Path to interface font");
@@ -3903,7 +4167,7 @@ static void rna_def_userdef_system(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "VBOs",
"Use Vertex Buffer Objects (or Vertex Arrays, if unsupported) for viewport rendering");
/* this isn't essential but nice to check if VBO draws any differently */
- RNA_def_property_update(prop, NC_WINDOW, NULL);
+ RNA_def_property_update(prop, NC_WINDOW, "rna_userdef_vbo_update");
prop = RNA_def_property(srna, "anisotropic_filter", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "anisotropic_filter");
@@ -4008,8 +4272,8 @@ static void rna_def_userdef_system(BlenderRNA *brna)
RNA_def_property_boolean_sdna(prop, NULL, "uiflag2", USER_REGION_OVERLAP);
RNA_def_property_ui_text(prop, "Region Overlap",
"Draw tool/property regions over the main region, when using Triple Buffer");
- RNA_def_property_update(prop, 0, "rna_userdef_dpi_update");
-
+ RNA_def_property_update(prop, 0, "rna_userdef_dpi_update");
+
#ifdef WITH_CYCLES
prop = RNA_def_property(srna, "compute_device_type", PROP_ENUM, PROP_NONE);
RNA_def_property_flag(prop, PROP_ENUM_NO_CONTEXT);
@@ -4026,6 +4290,16 @@ static void rna_def_userdef_system(BlenderRNA *brna)
RNA_def_property_enum_funcs(prop, "rna_userdef_compute_device_get", NULL, "rna_userdef_compute_device_itemf");
RNA_def_property_ui_text(prop, "Compute Device", "Device to use for computation");
#endif
+
+#ifdef WITH_OPENSUBDIV
+ prop = RNA_def_property(srna, "opensubdiv_compute_type", PROP_ENUM, PROP_NONE);
+ RNA_def_property_flag(prop, PROP_ENUM_NO_CONTEXT);
+ RNA_def_property_enum_sdna(prop, NULL, "opensubdiv_compute_type");
+ RNA_def_property_enum_items(prop, opensubdiv_compute_type_items);
+ RNA_def_property_enum_funcs(prop, NULL, NULL, "rna_userdef_opensubdiv_compute_type_itemf");
+ RNA_def_property_ui_text(prop, "OpenSubdiv Compute Type", "Type of computer back-end used with OpenSubdiv");
+ RNA_def_property_update(prop, NC_SPACE | ND_SPACE_PROPERTIES, "rna_userdef_opensubdiv_update");
+#endif
}
static void rna_def_userdef_input(BlenderRNA *brna)
@@ -4143,6 +4417,11 @@ static void rna_def_userdef_input(BlenderRNA *brna)
RNA_def_property_range(prop, 0.01f, 40.0f);
RNA_def_property_ui_text(prop, "Orbit Sensitivity", "Overall sensitivity of the 3D Mouse for orbiting");
+ prop = RNA_def_property(srna, "ndof_deadzone", PROP_FLOAT, PROP_FACTOR);
+ RNA_def_property_range(prop, 0.0f, 1.0f);
+ RNA_def_property_ui_text(prop, "Deadzone", "Deadzone of the 3D Mouse");
+ RNA_def_property_update(prop, 0, "rna_userdef_ndof_deadzone_update");
+
prop = RNA_def_property(srna, "ndof_pan_yz_swap_axis", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "ndof_flag", NDOF_PAN_YZ_SWAP_AXIS);
RNA_def_property_ui_text(prop, "Y/Z Swap Axis",
@@ -4366,7 +4645,7 @@ static void rna_def_userdef_filepaths(BlenderRNA *brna)
prop = RNA_def_property(srna, "use_auto_save_temporary_files", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", USER_AUTOSAVE);
RNA_def_property_ui_text(prop, "Auto Save Temporary Files",
- "Automatic saving of temporary files in temp directory, uses process ID");
+ "Automatic saving of temporary files in temp directory, uses process ID (Sculpt or edit mode data won't be saved!')");
RNA_def_property_update(prop, 0, "rna_userdef_autosave_update");
prop = RNA_def_property(srna, "auto_save_time", PROP_INT, PROP_NONE);
@@ -4400,18 +4679,18 @@ static void rna_def_userdef_addon_collection(BlenderRNA *brna, PropertyRNA *cpro
RNA_def_property_srna(cprop, "Addons");
srna = RNA_def_struct(brna, "Addons", NULL);
RNA_def_struct_clear_flag(srna, STRUCT_UNDO);
- RNA_def_struct_ui_text(srna, "User Addons", "Collection of addons");
+ RNA_def_struct_ui_text(srna, "User Add-ons", "Collection of add-ons");
func = RNA_def_function(srna, "new", "rna_userdef_addon_new");
RNA_def_function_flag(func, FUNC_NO_SELF);
- RNA_def_function_ui_description(func, "Add a new addon");
+ RNA_def_function_ui_description(func, "Add a new add-on");
/* return type */
parm = RNA_def_pointer(func, "addon", "Addon", "", "Addon datablock");
RNA_def_function_return(func, parm);
func = RNA_def_function(srna, "remove", "rna_userdef_addon_remove");
RNA_def_function_flag(func, FUNC_NO_SELF | FUNC_USE_REPORTS);
- RNA_def_function_ui_description(func, "Remove addon");
+ RNA_def_function_ui_description(func, "Remove add-on");
parm = RNA_def_pointer(func, "addon", "Addon", "", "Addon to remove");
RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL | PROP_RNAPTR);
RNA_def_property_clear_flag(parm, PROP_THICK_WRAP);
@@ -4452,7 +4731,7 @@ void RNA_def_userdef(BlenderRNA *brna)
{USER_SECTION_INTERFACE, "INTERFACE", 0, "Interface", ""},
{USER_SECTION_EDIT, "EDITING", 0, "Editing", ""},
{USER_SECTION_INPUT, "INPUT", 0, "Input", ""},
- {USER_SECTION_ADDONS, "ADDONS", 0, "Addons", ""},
+ {USER_SECTION_ADDONS, "ADDONS", 0, "Add-ons", ""},
{USER_SECTION_THEME, "THEMES", 0, "Themes", ""},
{USER_SECTION_FILE, "FILES", 0, "File", ""},
{USER_SECTION_SYSTEM, "SYSTEM", 0, "System", ""},
diff --git a/source/blender/makesrna/intern/rna_vfont.c b/source/blender/makesrna/intern/rna_vfont.c
index f24f94282b6..0879f4d355d 100644
--- a/source/blender/makesrna/intern/rna_vfont.c
+++ b/source/blender/makesrna/intern/rna_vfont.c
@@ -84,6 +84,8 @@ void RNA_def_vfont(BlenderRNA *brna)
prop = RNA_def_property(srna, "packed_file", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "packedfile");
RNA_def_property_ui_text(prop, "Packed File", "");
+
+ RNA_api_vfont(srna);
}
#endif
diff --git a/source/blender/makesrna/intern/rna_vfont_api.c b/source/blender/makesrna/intern/rna_vfont_api.c
new file mode 100644
index 00000000000..d92e75daf0a
--- /dev/null
+++ b/source/blender/makesrna/intern/rna_vfont_api.c
@@ -0,0 +1,73 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2015 by the Blender Foundation.
+ * All rights reserved.
+ *
+ * Contributor(s): Kevin Dietrich
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/makesrna/intern/rna_vfont_api.c
+ * \ingroup RNA
+ */
+
+#include "DNA_packedFile_types.h"
+
+#include "RNA_define.h"
+#include "RNA_enum_types.h"
+
+#include "rna_internal.h"
+
+#ifdef RNA_RUNTIME
+
+#include "BKE_packedFile.h"
+
+static void rna_VectorFont_pack(VFont *vfont, Main *bmain, ReportList *reports)
+{
+ vfont->packedfile = newPackedFile(reports, vfont->name, ID_BLEND_PATH(bmain, &vfont->id));
+}
+
+static void rna_VectorFont_unpack(VFont *vfont, ReportList *reports, int method)
+{
+ if (!vfont->packedfile) {
+ BKE_report(reports, RPT_ERROR, "Font not packed");
+ }
+ else {
+ /* reports its own error on failure */
+ unpackVFont(reports, vfont, method);
+ }
+}
+
+#else
+
+void RNA_api_vfont(StructRNA *srna)
+{
+ FunctionRNA *func;
+
+ func = RNA_def_function(srna, "pack", "rna_VectorFont_pack");
+ RNA_def_function_ui_description(func, "Pack the font into the current blend file");
+ RNA_def_function_flag(func, FUNC_USE_REPORTS | FUNC_USE_MAIN);
+
+ func = RNA_def_function(srna, "unpack", "rna_VectorFont_unpack");
+ RNA_def_function_ui_description(func, "Unpack the font to the samples filename");
+ RNA_def_function_flag(func, FUNC_USE_REPORTS);
+ RNA_def_enum(func, "method", unpack_method_items, PF_USE_LOCAL, "method", "How to unpack");
+}
+
+#endif
diff --git a/source/blender/makesrna/intern/rna_wm.c b/source/blender/makesrna/intern/rna_wm.c
index 7513a687978..aa4bfe0462e 100644
--- a/source/blender/makesrna/intern/rna_wm.c
+++ b/source/blender/makesrna/intern/rna_wm.c
@@ -33,7 +33,7 @@
#include "BLI_utildefines.h"
-#include "BLF_translation.h"
+#include "BLT_translation.h"
#include "RNA_access.h"
#include "RNA_define.h"
@@ -168,34 +168,34 @@ static EnumPropertyItem event_ndof_type_items[] = {
/* not returned: CAPSLOCKKEY, UNKNOWNKEY */
EnumPropertyItem event_type_items[] = {
-
+ /* Note we abuse 'tooltip' message here to store a 'compact' form of some (too) long names. */
{0, "NONE", 0, "", ""},
- {LEFTMOUSE, "LEFTMOUSE", 0, "Left Mouse", ""},
- {MIDDLEMOUSE, "MIDDLEMOUSE", 0, "Middle Mouse", ""},
- {RIGHTMOUSE, "RIGHTMOUSE", 0, "Right Mouse", ""},
- {BUTTON4MOUSE, "BUTTON4MOUSE", 0, "Button4 Mouse", ""},
- {BUTTON5MOUSE, "BUTTON5MOUSE", 0, "Button5 Mouse", ""},
- {BUTTON6MOUSE, "BUTTON6MOUSE", 0, "Button6 Mouse", ""},
- {BUTTON7MOUSE, "BUTTON7MOUSE", 0, "Button7 Mouse", ""},
- {ACTIONMOUSE, "ACTIONMOUSE", 0, "Action Mouse", ""},
- {SELECTMOUSE, "SELECTMOUSE", 0, "Select Mouse", ""},
+ {LEFTMOUSE, "LEFTMOUSE", 0, "Left Mouse", "LMB"},
+ {MIDDLEMOUSE, "MIDDLEMOUSE", 0, "Middle Mouse", "MMB"},
+ {RIGHTMOUSE, "RIGHTMOUSE", 0, "Right Mouse", "RMB"},
+ {BUTTON4MOUSE, "BUTTON4MOUSE", 0, "Button4 Mouse", "MB4"},
+ {BUTTON5MOUSE, "BUTTON5MOUSE", 0, "Button5 Mouse", "MB5"},
+ {BUTTON6MOUSE, "BUTTON6MOUSE", 0, "Button6 Mouse", "MB6"},
+ {BUTTON7MOUSE, "BUTTON7MOUSE", 0, "Button7 Mouse", "MB7"},
+ {ACTIONMOUSE, "ACTIONMOUSE", 0, "Action Mouse", "MBA"},
+ {SELECTMOUSE, "SELECTMOUSE", 0, "Select Mouse", "MBS"},
{0, "", 0, NULL, NULL},
- {MOUSEMOVE, "MOUSEMOVE", 0, "Mouse Move", ""},
- {INBETWEEN_MOUSEMOVE, "INBETWEEN_MOUSEMOVE", 0, "In-between Move", ""},
- {MOUSEPAN, "TRACKPADPAN", 0, "Mouse/Trackpad Pan", ""},
- {MOUSEZOOM, "TRACKPADZOOM", 0, "Mouse/Trackpad Zoom", ""},
- {MOUSEROTATE, "MOUSEROTATE", 0, "Mouse/Trackpad Rotate", ""},
+ {MOUSEMOVE, "MOUSEMOVE", 0, "Mouse Move", "MsMov"},
+ {INBETWEEN_MOUSEMOVE, "INBETWEEN_MOUSEMOVE", 0, "In-between Move", "MsSubMov"},
+ {MOUSEPAN, "TRACKPADPAN", 0, "Mouse/Trackpad Pan", "MsPan"},
+ {MOUSEZOOM, "TRACKPADZOOM", 0, "Mouse/Trackpad Zoom", "MsZoom"},
+ {MOUSEROTATE, "MOUSEROTATE", 0, "Mouse/Trackpad Rotate", "MsRot"},
{0, "", 0, NULL, NULL},
- {WHEELUPMOUSE, "WHEELUPMOUSE", 0, "Wheel Up", ""},
- {WHEELDOWNMOUSE, "WHEELDOWNMOUSE", 0, "Wheel Down", ""},
- {WHEELINMOUSE, "WHEELINMOUSE", 0, "Wheel In", ""},
- {WHEELOUTMOUSE, "WHEELOUTMOUSE", 0, "Wheel Out", ""},
+ {WHEELUPMOUSE, "WHEELUPMOUSE", 0, "Wheel Up", "WhUp"},
+ {WHEELDOWNMOUSE, "WHEELDOWNMOUSE", 0, "Wheel Down", "WhDown"},
+ {WHEELINMOUSE, "WHEELINMOUSE", 0, "Wheel In", "WhIn"},
+ {WHEELOUTMOUSE, "WHEELOUTMOUSE", 0, "Wheel Out", "WhOut"},
{0, "", 0, NULL, NULL},
- {EVT_TWEAK_L, "EVT_TWEAK_L", 0, "Tweak Left", ""},
- {EVT_TWEAK_M, "EVT_TWEAK_M", 0, "Tweak Middle", ""},
- {EVT_TWEAK_R, "EVT_TWEAK_R", 0, "Tweak Right", ""},
- {EVT_TWEAK_A, "EVT_TWEAK_A", 0, "Tweak Action", ""},
- {EVT_TWEAK_S, "EVT_TWEAK_S", 0, "Tweak Select", ""},
+ {EVT_TWEAK_L, "EVT_TWEAK_L", 0, "Tweak Left", "TwkL"},
+ {EVT_TWEAK_M, "EVT_TWEAK_M", 0, "Tweak Middle", "TwkM"},
+ {EVT_TWEAK_R, "EVT_TWEAK_R", 0, "Tweak Right", "TwkR"},
+ {EVT_TWEAK_A, "EVT_TWEAK_A", 0, "Tweak Action", "TwkA"},
+ {EVT_TWEAK_S, "EVT_TWEAK_S", 0, "Tweak Select", "TwkS"},
{0, "", 0, NULL, NULL},
{AKEY, "A", 0, "A", ""},
{BKEY, "B", 0, "B", ""},
@@ -235,22 +235,22 @@ EnumPropertyItem event_type_items[] = {
{EIGHTKEY, "EIGHT", 0, "8", ""},
{NINEKEY, "NINE", 0, "9", ""},
{0, "", 0, NULL, NULL},
- {LEFTCTRLKEY, "LEFT_CTRL", 0, "Left Ctrl", ""},
- {LEFTALTKEY, "LEFT_ALT", 0, "Left Alt", ""},
- {LEFTSHIFTKEY, "LEFT_SHIFT", 0, "Left Shift", ""},
- {RIGHTALTKEY, "RIGHT_ALT", 0, "Right Alt", ""},
- {RIGHTCTRLKEY, "RIGHT_CTRL", 0, "Right Ctrl", ""},
- {RIGHTSHIFTKEY, "RIGHT_SHIFT", 0, "Right Shift", ""},
+ {LEFTCTRLKEY, "LEFT_CTRL", 0, "Left Ctrl", "CtrlL"},
+ {LEFTALTKEY, "LEFT_ALT", 0, "Left Alt", "AltL"},
+ {LEFTSHIFTKEY, "LEFT_SHIFT", 0, "Left Shift", "ShiftL"},
+ {RIGHTALTKEY, "RIGHT_ALT", 0, "Right Alt", "AltR"},
+ {RIGHTCTRLKEY, "RIGHT_CTRL", 0, "Right Ctrl", "CtrlR"},
+ {RIGHTSHIFTKEY, "RIGHT_SHIFT", 0, "Right Shift", "ShiftR"},
{0, "", 0, NULL, NULL},
- {OSKEY, "OSKEY", 0, "OS Key", ""},
+ {OSKEY, "OSKEY", 0, "OS Key", "Cmd"},
{GRLESSKEY, "GRLESS", 0, "Grless", ""},
{ESCKEY, "ESC", 0, "Esc", ""},
{TABKEY, "TAB", 0, "Tab", ""},
- {RETKEY, "RET", 0, "Return", ""},
- {SPACEKEY, "SPACE", 0, "Spacebar", ""},
+ {RETKEY, "RET", 0, "Return", "Enter"},
+ {SPACEKEY, "SPACE", 0, "Spacebar", "Space"},
{LINEFEEDKEY, "LINE_FEED", 0, "Line Feed", ""},
- {BACKSPACEKEY, "BACK_SPACE", 0, "Back Space", ""},
- {DELKEY, "DEL", 0, "Delete", ""},
+ {BACKSPACEKEY, "BACK_SPACE", 0, "Back Space", "BkSpace"},
+ {DELKEY, "DEL", 0, "Delete", "Del"},
{SEMICOLONKEY, "SEMI_COLON", 0, ";", ""},
{PERIODKEY, "PERIOD", 0, ".", ""},
{COMMAKEY, "COMMA", 0, ",", ""},
@@ -262,26 +262,26 @@ EnumPropertyItem event_type_items[] = {
{EQUALKEY, "EQUAL", 0, "=", ""},
{LEFTBRACKETKEY, "LEFT_BRACKET", 0, "[", ""},
{RIGHTBRACKETKEY, "RIGHT_BRACKET", 0, "]", ""},
- {LEFTARROWKEY, "LEFT_ARROW", 0, "Left Arrow", ""},
- {DOWNARROWKEY, "DOWN_ARROW", 0, "Down Arrow", ""},
- {RIGHTARROWKEY, "RIGHT_ARROW", 0, "Right Arrow", ""},
- {UPARROWKEY, "UP_ARROW", 0, "Up Arrow", ""},
- {PAD2, "NUMPAD_2", 0, "Numpad 2", ""},
- {PAD4, "NUMPAD_4", 0, "Numpad 4", ""},
- {PAD6, "NUMPAD_6", 0, "Numpad 6", ""},
- {PAD8, "NUMPAD_8", 0, "Numpad 8", ""},
- {PAD1, "NUMPAD_1", 0, "Numpad 1", ""},
- {PAD3, "NUMPAD_3", 0, "Numpad 3", ""},
- {PAD5, "NUMPAD_5", 0, "Numpad 5", ""},
- {PAD7, "NUMPAD_7", 0, "Numpad 7", ""},
- {PAD9, "NUMPAD_9", 0, "Numpad 9", ""},
- {PADPERIOD, "NUMPAD_PERIOD", 0, "Numpad .", ""},
- {PADSLASHKEY, "NUMPAD_SLASH", 0, "Numpad /", ""},
- {PADASTERKEY, "NUMPAD_ASTERIX", 0, "Numpad *", ""},
- {PAD0, "NUMPAD_0", 0, "Numpad 0", ""},
- {PADMINUS, "NUMPAD_MINUS", 0, "Numpad -", ""},
- {PADENTER, "NUMPAD_ENTER", 0, "Numpad Enter", ""},
- {PADPLUSKEY, "NUMPAD_PLUS", 0, "Numpad +", ""},
+ {LEFTARROWKEY, "LEFT_ARROW", 0, "Left Arrow", "â†"},
+ {DOWNARROWKEY, "DOWN_ARROW", 0, "Down Arrow", "↓"},
+ {RIGHTARROWKEY, "RIGHT_ARROW", 0, "Right Arrow", "→"},
+ {UPARROWKEY, "UP_ARROW", 0, "Up Arrow", "↑"},
+ {PAD2, "NUMPAD_2", 0, "Numpad 2", "Pad2"},
+ {PAD4, "NUMPAD_4", 0, "Numpad 4", "Pad4"},
+ {PAD6, "NUMPAD_6", 0, "Numpad 6", "Pad6"},
+ {PAD8, "NUMPAD_8", 0, "Numpad 8", "Pad8"},
+ {PAD1, "NUMPAD_1", 0, "Numpad 1", "Pad1"},
+ {PAD3, "NUMPAD_3", 0, "Numpad 3", "Pad3"},
+ {PAD5, "NUMPAD_5", 0, "Numpad 5", "Pad5"},
+ {PAD7, "NUMPAD_7", 0, "Numpad 7", "Pad7"},
+ {PAD9, "NUMPAD_9", 0, "Numpad 9", "Pad9"},
+ {PADPERIOD, "NUMPAD_PERIOD", 0, "Numpad .", "Pad."},
+ {PADSLASHKEY, "NUMPAD_SLASH", 0, "Numpad /", "Pad/"},
+ {PADASTERKEY, "NUMPAD_ASTERIX", 0, "Numpad *", "Pad*"},
+ {PAD0, "NUMPAD_0", 0, "Numpad 0", "Pad0"},
+ {PADMINUS, "NUMPAD_MINUS", 0, "Numpad -", "Pad-"},
+ {PADENTER, "NUMPAD_ENTER", 0, "Numpad Enter", "PadEnter"},
+ {PADPLUSKEY, "NUMPAD_PLUS", 0, "Numpad +", "Pad+"},
{F1KEY, "F1", 0, "F1", ""},
{F2KEY, "F2", 0, "F2", ""},
{F3KEY, "F3", 0, "F3", ""},
@@ -302,75 +302,75 @@ EnumPropertyItem event_type_items[] = {
{F18KEY, "F18", 0, "F18", ""},
{F19KEY, "F19", 0, "F19", ""},
{PAUSEKEY, "PAUSE", 0, "Pause", ""},
- {INSERTKEY, "INSERT", 0, "Insert", ""},
+ {INSERTKEY, "INSERT", 0, "Insert", "Ins"},
{HOMEKEY, "HOME", 0, "Home", ""},
- {PAGEUPKEY, "PAGE_UP", 0, "Page Up", ""},
- {PAGEDOWNKEY, "PAGE_DOWN", 0, "Page Down", ""},
+ {PAGEUPKEY, "PAGE_UP", 0, "Page Up", "PgUp"},
+ {PAGEDOWNKEY, "PAGE_DOWN", 0, "Page Down", "PgDown"},
{ENDKEY, "END", 0, "End", ""},
{0, "", 0, NULL, NULL},
- {MEDIAPLAY, "MEDIA_PLAY", 0, "Media Play/Pause", ""},
- {MEDIASTOP, "MEDIA_STOP", 0, "Media Stop", ""},
- {MEDIAFIRST, "MEDIA_FIRST", 0, "Media First", ""},
- {MEDIALAST, "MEDIA_LAST", 0, "Media Last", ""},
+ {MEDIAPLAY, "MEDIA_PLAY", 0, "Media Play/Pause", ">/||"},
+ {MEDIASTOP, "MEDIA_STOP", 0, "Media Stop", "Stop"},
+ {MEDIAFIRST, "MEDIA_FIRST", 0, "Media First", "|<<"},
+ {MEDIALAST, "MEDIA_LAST", 0, "Media Last", ">>|"},
{0, "", 0, NULL, NULL},
- {KM_TEXTINPUT, "TEXTINPUT", 0, "Text Input", ""},
+ {KM_TEXTINPUT, "TEXTINPUT", 0, "Text Input", "TxtIn"},
{0, "", 0, NULL, NULL},
{WINDEACTIVATE, "WINDOW_DEACTIVATE", 0, "Window Deactivate", ""},
- {TIMER, "TIMER", 0, "Timer", ""},
- {TIMER0, "TIMER0", 0, "Timer 0", ""},
- {TIMER1, "TIMER1", 0, "Timer 1", ""},
- {TIMER2, "TIMER2", 0, "Timer 2", ""},
- {TIMERJOBS, "TIMER_JOBS", 0, "Timer Jobs", ""},
- {TIMERAUTOSAVE, "TIMER_AUTOSAVE", 0, "Timer Autosave", ""},
- {TIMERREPORT, "TIMER_REPORT", 0, "Timer Report", ""},
- {TIMERREGION, "TIMERREGION", 0, "Timer Region", ""},
+ {TIMER, "TIMER", 0, "Timer", "Tmr"},
+ {TIMER0, "TIMER0", 0, "Timer 0", "Tmr0"},
+ {TIMER1, "TIMER1", 0, "Timer 1", "Tmr1"},
+ {TIMER2, "TIMER2", 0, "Timer 2", "Tmr2"},
+ {TIMERJOBS, "TIMER_JOBS", 0, "Timer Jobs", "TmrJob"},
+ {TIMERAUTOSAVE, "TIMER_AUTOSAVE", 0, "Timer Autosave", "TmrSave"},
+ {TIMERREPORT, "TIMER_REPORT", 0, "Timer Report", "TmrReport"},
+ {TIMERREGION, "TIMERREGION", 0, "Timer Region", "TmrReg"},
{0, "", 0, NULL, NULL},
- {NDOF_MOTION, "NDOF_MOTION", 0, "NDOF Motion", ""},
+ {NDOF_MOTION, "NDOF_MOTION", 0, "NDOF Motion", "NdofMov"},
/* buttons on all 3dconnexion devices */
- {NDOF_BUTTON_MENU, "NDOF_BUTTON_MENU", 0, "NDOF Menu", ""},
- {NDOF_BUTTON_FIT, "NDOF_BUTTON_FIT", 0, "NDOF Fit", ""},
+ {NDOF_BUTTON_MENU, "NDOF_BUTTON_MENU", 0, "NDOF Menu", "NdofMenu"},
+ {NDOF_BUTTON_FIT, "NDOF_BUTTON_FIT", 0, "NDOF Fit", "NdofFit"},
/* view buttons */
- {NDOF_BUTTON_TOP, "NDOF_BUTTON_TOP", 0, "NDOF Top", ""},
- {NDOF_BUTTON_BOTTOM, "NDOF_BUTTON_BOTTOM", 0, "NDOF Bottom", ""},
- {NDOF_BUTTON_LEFT, "NDOF_BUTTON_LEFT", 0, "NDOF Left", ""},
- {NDOF_BUTTON_RIGHT, "NDOF_BUTTON_RIGHT", 0, "NDOF Right", ""},
- {NDOF_BUTTON_FRONT, "NDOF_BUTTON_FRONT", 0, "NDOF Front", ""},
- {NDOF_BUTTON_BACK, "NDOF_BUTTON_BACK", 0, "NDOF Back", ""},
+ {NDOF_BUTTON_TOP, "NDOF_BUTTON_TOP", 0, "NDOF Top", "Ndof↑"},
+ {NDOF_BUTTON_BOTTOM, "NDOF_BUTTON_BOTTOM", 0, "NDOF Bottom", "Ndof↓"},
+ {NDOF_BUTTON_LEFT, "NDOF_BUTTON_LEFT", 0, "NDOF Left", "Ndofâ†"},
+ {NDOF_BUTTON_RIGHT, "NDOF_BUTTON_RIGHT", 0, "NDOF Right", "Ndof→"},
+ {NDOF_BUTTON_FRONT, "NDOF_BUTTON_FRONT", 0, "NDOF Front", "NdofFront"},
+ {NDOF_BUTTON_BACK, "NDOF_BUTTON_BACK", 0, "NDOF Back", "NdofBack"},
/* more views */
- {NDOF_BUTTON_ISO1, "NDOF_BUTTON_ISO1", 0, "NDOF Isometric 1", ""},
- {NDOF_BUTTON_ISO2, "NDOF_BUTTON_ISO2", 0, "NDOF Isometric 2", ""},
+ {NDOF_BUTTON_ISO1, "NDOF_BUTTON_ISO1", 0, "NDOF Isometric 1", "NdofIso1"},
+ {NDOF_BUTTON_ISO2, "NDOF_BUTTON_ISO2", 0, "NDOF Isometric 2", "NdofIso2"},
/* 90 degree rotations */
- {NDOF_BUTTON_ROLL_CW, "NDOF_BUTTON_ROLL_CW", 0, "NDOF Roll CW", ""},
- {NDOF_BUTTON_ROLL_CCW, "NDOF_BUTTON_ROLL_CCW", 0, "NDOF Roll CCW", ""},
- {NDOF_BUTTON_SPIN_CW, "NDOF_BUTTON_SPIN_CW", 0, "NDOF Spin CW", ""},
- {NDOF_BUTTON_SPIN_CCW, "NDOF_BUTTON_SPIN_CCW", 0, "NDOF Spin CCW", ""},
- {NDOF_BUTTON_TILT_CW, "NDOF_BUTTON_TILT_CW", 0, "NDOF Tilt CW", ""},
- {NDOF_BUTTON_TILT_CCW, "NDOF_BUTTON_TILT_CCW", 0, "NDOF Tilt CCW", ""},
+ {NDOF_BUTTON_ROLL_CW, "NDOF_BUTTON_ROLL_CW", 0, "NDOF Roll CW", "NdofRCW"},
+ {NDOF_BUTTON_ROLL_CCW, "NDOF_BUTTON_ROLL_CCW", 0, "NDOF Roll CCW", "NdofRCCW"},
+ {NDOF_BUTTON_SPIN_CW, "NDOF_BUTTON_SPIN_CW", 0, "NDOF Spin CW", "NdofSCW"},
+ {NDOF_BUTTON_SPIN_CCW, "NDOF_BUTTON_SPIN_CCW", 0, "NDOF Spin CCW", "NdofSCCW"},
+ {NDOF_BUTTON_TILT_CW, "NDOF_BUTTON_TILT_CW", 0, "NDOF Tilt CW", "NdofTCW"},
+ {NDOF_BUTTON_TILT_CCW, "NDOF_BUTTON_TILT_CCW", 0, "NDOF Tilt CCW", "NdofTCCW"},
/* device control */
- {NDOF_BUTTON_ROTATE, "NDOF_BUTTON_ROTATE", 0, "NDOF Rotate", ""},
- {NDOF_BUTTON_PANZOOM, "NDOF_BUTTON_PANZOOM", 0, "NDOF Pan/Zoom", ""},
- {NDOF_BUTTON_DOMINANT, "NDOF_BUTTON_DOMINANT", 0, "NDOF Dominant", ""},
- {NDOF_BUTTON_PLUS, "NDOF_BUTTON_PLUS", 0, "NDOF Plus", ""},
- {NDOF_BUTTON_MINUS, "NDOF_BUTTON_MINUS", 0, "NDOF Minus", ""},
+ {NDOF_BUTTON_ROTATE, "NDOF_BUTTON_ROTATE", 0, "NDOF Rotate", "NdofRot"},
+ {NDOF_BUTTON_PANZOOM, "NDOF_BUTTON_PANZOOM", 0, "NDOF Pan/Zoom", "NdofPanZoom"},
+ {NDOF_BUTTON_DOMINANT, "NDOF_BUTTON_DOMINANT", 0, "NDOF Dominant", "NdofDom"},
+ {NDOF_BUTTON_PLUS, "NDOF_BUTTON_PLUS", 0, "NDOF Plus", "Ndof+"},
+ {NDOF_BUTTON_MINUS, "NDOF_BUTTON_MINUS", 0, "NDOF Minus", "Ndof-"},
/* keyboard emulation */
- {NDOF_BUTTON_ESC, "NDOF_BUTTON_ESC", 0, "NDOF Esc"},
- {NDOF_BUTTON_ALT, "NDOF_BUTTON_ALT", 0, "NDOF Alt"},
- {NDOF_BUTTON_SHIFT, "NDOF_BUTTON_SHIFT", 0, "NDOF Shift"},
- {NDOF_BUTTON_CTRL, "NDOF_BUTTON_CTRL", 0, "NDOF Ctrl"},
+ {NDOF_BUTTON_ESC, "NDOF_BUTTON_ESC", 0, "NDOF Esc", "NdofEsc"},
+ {NDOF_BUTTON_ALT, "NDOF_BUTTON_ALT", 0, "NDOF Alt", "NdofAlt"},
+ {NDOF_BUTTON_SHIFT, "NDOF_BUTTON_SHIFT", 0, "NDOF Shift", "NdofShift"},
+ {NDOF_BUTTON_CTRL, "NDOF_BUTTON_CTRL", 0, "NDOF Ctrl", "NdofCtrl"},
/* general-purpose buttons */
- {NDOF_BUTTON_1, "NDOF_BUTTON_1", 0, "NDOF Button 1", ""},
- {NDOF_BUTTON_2, "NDOF_BUTTON_2", 0, "NDOF Button 2", ""},
- {NDOF_BUTTON_3, "NDOF_BUTTON_3", 0, "NDOF Button 3", ""},
- {NDOF_BUTTON_4, "NDOF_BUTTON_4", 0, "NDOF Button 4", ""},
- {NDOF_BUTTON_5, "NDOF_BUTTON_5", 0, "NDOF Button 5", ""},
- {NDOF_BUTTON_6, "NDOF_BUTTON_6", 0, "NDOF Button 6", ""},
- {NDOF_BUTTON_7, "NDOF_BUTTON_7", 0, "NDOF Button 7", ""},
- {NDOF_BUTTON_8, "NDOF_BUTTON_8", 0, "NDOF Button 8", ""},
- {NDOF_BUTTON_9, "NDOF_BUTTON_9", 0, "NDOF Button 9", ""},
- {NDOF_BUTTON_10, "NDOF_BUTTON_10", 0, "NDOF Button 10", ""},
- {NDOF_BUTTON_A, "NDOF_BUTTON_A", 0, "NDOF Button A", ""},
- {NDOF_BUTTON_B, "NDOF_BUTTON_B", 0, "NDOF Button B", ""},
- {NDOF_BUTTON_C, "NDOF_BUTTON_C", 0, "NDOF Button C", ""},
+ {NDOF_BUTTON_1, "NDOF_BUTTON_1", 0, "NDOF Button 1", "NdofB1"},
+ {NDOF_BUTTON_2, "NDOF_BUTTON_2", 0, "NDOF Button 2", "NdofB2"},
+ {NDOF_BUTTON_3, "NDOF_BUTTON_3", 0, "NDOF Button 3", "NdofB3"},
+ {NDOF_BUTTON_4, "NDOF_BUTTON_4", 0, "NDOF Button 4", "NdofB4"},
+ {NDOF_BUTTON_5, "NDOF_BUTTON_5", 0, "NDOF Button 5", "NdofB5"},
+ {NDOF_BUTTON_6, "NDOF_BUTTON_6", 0, "NDOF Button 6", "NdofB6"},
+ {NDOF_BUTTON_7, "NDOF_BUTTON_7", 0, "NDOF Button 7", "NdofB7"},
+ {NDOF_BUTTON_8, "NDOF_BUTTON_8", 0, "NDOF Button 8", "NdofB8"},
+ {NDOF_BUTTON_9, "NDOF_BUTTON_9", 0, "NDOF Button 9", "NdofB9"},
+ {NDOF_BUTTON_10, "NDOF_BUTTON_10", 0, "NDOF Button 10", "NdofB10"},
+ {NDOF_BUTTON_A, "NDOF_BUTTON_A", 0, "NDOF Button A", "NdofBA"},
+ {NDOF_BUTTON_B, "NDOF_BUTTON_B", 0, "NDOF Button B", "NdofBB"},
+ {NDOF_BUTTON_C, "NDOF_BUTTON_C", 0, "NDOF Button C", "NdofBC"},
{0, NULL, 0, NULL, NULL}
};
@@ -414,7 +414,7 @@ static EnumPropertyItem operator_flag_items[] = {
{OPTYPE_UNDO, "UNDO", 0, "Undo", "Push an undo event (needed for operator redo)"},
{OPTYPE_BLOCKING, "BLOCKING", 0, "Blocking", "Block anything else from using the cursor"},
{OPTYPE_MACRO, "MACRO", 0, "Macro", "Use to check if an operator is a macro"},
- {OPTYPE_GRAB_POINTER, "GRAB_POINTER", 0, "Grab Pointer",
+ {OPTYPE_GRAB_CURSOR, "GRAB_CURSOR", 0, "Grab Pointer",
"Use so the operator grabs the mouse focus, enables wrapping when continuous grab "
"is enabled"},
{OPTYPE_PRESET, "PRESET", 0, "Preset", "Display a preset button with the operators settings"},
@@ -429,6 +429,7 @@ EnumPropertyItem operator_return_items[] = {
{OPERATOR_FINISHED, "FINISHED", 0, "Finished", "When the operator is complete, operator exits"},
/* used as a flag */
{OPERATOR_PASS_THROUGH, "PASS_THROUGH", 0, "Pass Through", "Do nothing and pass the event on"},
+ {OPERATOR_INTERFACE, "INTERFACE", 0, "Interface", "Handled but not executed (popup menus)"},
{0, NULL, 0, NULL, NULL}
};
@@ -510,6 +511,11 @@ static int rna_Operator_has_reports_get(PointerRNA *ptr)
return (op->reports && op->reports->list.first);
}
+static PointerRNA rna_Operator_options_get(PointerRNA *ptr)
+{
+ return rna_pointer_inherit_refine(ptr, &RNA_OperatorOptions, ptr->data);
+}
+
static PointerRNA rna_Operator_properties_get(PointerRNA *ptr)
{
wmOperator *op = (wmOperator *)ptr->data;
@@ -525,21 +531,21 @@ static PointerRNA rna_OperatorMacro_properties_get(PointerRNA *ptr)
static void rna_Event_ascii_get(PointerRNA *ptr, char *value)
{
- wmEvent *event = (wmEvent *)ptr->data;
+ const wmEvent *event = ptr->data;
value[0] = event->ascii;
value[1] = '\0';
}
static int rna_Event_ascii_length(PointerRNA *ptr)
{
- wmEvent *event = (wmEvent *)ptr->data;
+ const wmEvent *event = ptr->data;
return (event->ascii) ? 1 : 0;
}
static void rna_Event_unicode_get(PointerRNA *ptr, char *value)
{
/* utf8 buf isn't \0 terminated */
- wmEvent *event = (wmEvent *)ptr->data;
+ const wmEvent *event = ptr->data;
size_t len = 0;
if (event->utf8_buf[0]) {
@@ -555,7 +561,7 @@ static void rna_Event_unicode_get(PointerRNA *ptr, char *value)
static int rna_Event_unicode_length(PointerRNA *ptr)
{
- wmEvent *event = (wmEvent *)ptr->data;
+ const wmEvent *event = ptr->data;
if (event->utf8_buf[0]) {
/* invalid value is checked on assignment so we don't need to account for this */
return BLI_str_utf8_size(event->utf8_buf);
@@ -567,13 +573,13 @@ static int rna_Event_unicode_length(PointerRNA *ptr)
static float rna_Event_pressure_get(PointerRNA *ptr)
{
- wmEvent *event = ptr->data;
+ const wmEvent *event = ptr->data;
return WM_event_tablet_data(event, NULL, NULL);
}
static int rna_Event_is_tablet_get(PointerRNA *ptr)
{
- wmEvent *event = ptr->data;
+ const wmEvent *event = ptr->data;
return WM_event_is_tablet(event);
}
@@ -586,7 +592,7 @@ static void rna_Event_tilt_get(PointerRNA *ptr, float *values)
static PointerRNA rna_PopupMenu_layout_get(PointerRNA *ptr)
{
struct uiPopupMenu *pup = ptr->data;
- uiLayout *layout = uiPupMenuLayout(pup);
+ uiLayout *layout = UI_popup_menu_layout(pup);
PointerRNA rptr;
RNA_pointer_create(ptr->id.data, &RNA_UILayout, layout, &rptr);
@@ -597,7 +603,7 @@ static PointerRNA rna_PopupMenu_layout_get(PointerRNA *ptr)
static PointerRNA rna_PieMenu_layout_get(PointerRNA *ptr)
{
struct uiPieMenu *pie = ptr->data;
- uiLayout *layout = uiPieMenuLayout(pie);
+ uiLayout *layout = UI_pie_menu_layout(pie);
PointerRNA rptr;
RNA_pointer_create(ptr->id.data, &RNA_UILayout, layout, &rptr);
@@ -609,6 +615,11 @@ static void rna_Window_screen_set(PointerRNA *ptr, PointerRNA value)
{
wmWindow *win = (wmWindow *)ptr->data;
+ /* disallow ID-browsing away from temp screens */
+ if (win->screen->temp) {
+ return;
+ }
+
if (value.data == NULL)
return;
@@ -761,7 +772,7 @@ static EnumPropertyItem *rna_KeyMapItem_propvalue_itemf(bContext *C, PointerRNA
return keymap_propvalue_items; /* ERROR */
}
-static int rna_KeyMapItem_any_getf(PointerRNA *ptr)
+static int rna_KeyMapItem_any_get(PointerRNA *ptr)
{
wmKeyMapItem *kmi = (wmKeyMapItem *)ptr->data;
@@ -777,7 +788,7 @@ static int rna_KeyMapItem_any_getf(PointerRNA *ptr)
}
}
-static void rna_KeyMapItem_any_setf(PointerRNA *ptr, int value)
+static void rna_KeyMapItem_any_set(PointerRNA *ptr, int value)
{
wmKeyMapItem *kmi = (wmKeyMapItem *)ptr->data;
@@ -789,6 +800,29 @@ static void rna_KeyMapItem_any_setf(PointerRNA *ptr, int value)
}
}
+static int rna_KeyMapItem_shift_get(PointerRNA *ptr)
+{
+ wmKeyMapItem *kmi = (wmKeyMapItem *)ptr->data;
+ return kmi->shift != 0;
+}
+
+static int rna_KeyMapItem_ctrl_get(PointerRNA *ptr)
+{
+ wmKeyMapItem *kmi = (wmKeyMapItem *)ptr->data;
+ return kmi->ctrl != 0;
+}
+
+static int rna_KeyMapItem_alt_get(PointerRNA *ptr)
+{
+ wmKeyMapItem *kmi = (wmKeyMapItem *)ptr->data;
+ return kmi->alt != 0;
+}
+
+static int rna_KeyMapItem_oskey_get(PointerRNA *ptr)
+{
+ wmKeyMapItem *kmi = (wmKeyMapItem *)ptr->data;
+ return kmi->oskey != 0;
+}
static PointerRNA rna_WindowManager_active_keyconfig_get(PointerRNA *ptr)
{
@@ -834,7 +868,7 @@ static void rna_wmKeyMapItem_idname_set(PointerRNA *ptr, const char *value)
WM_operator_bl_idname(idname, value);
- if (strcmp(idname, kmi->idname) != 0) {
+ if (!STREQ(idname, kmi->idname)) {
BLI_strncpy(kmi->idname, idname, sizeof(kmi->idname));
WM_keymap_properties_reset(kmi, NULL);
@@ -1115,7 +1149,7 @@ static StructRNA *rna_Operator_register(Main *bmain, ReportList *reports, void *
/* clear in case they are left unset */
_operator_idname[0] = _operator_name[0] = _operator_descr[0] = '\0';
/* We have to set default op context! */
- strcpy(_operator_ctxt, BLF_I18NCONTEXT_OPERATOR_DEFAULT);
+ strcpy(_operator_ctxt, BLT_I18NCONTEXT_OPERATOR_DEFAULT);
/* validate the python class */
if (validate(&dummyotr, data, have_function) != 0)
@@ -1242,7 +1276,7 @@ static StructRNA *rna_MacroOperator_register(Main *bmain, ReportList *reports, v
/* clear in case they are left unset */
_operator_idname[0] = _operator_name[0] = _operator_descr[0] = '\0';
/* We have to set default op context! */
- strcpy(_operator_ctxt, BLF_I18NCONTEXT_OPERATOR_DEFAULT);
+ strcpy(_operator_ctxt, BLT_I18NCONTEXT_OPERATOR_DEFAULT);
/* validate the python class */
if (validate(&dummyotr, data, have_function) != 0)
@@ -1366,6 +1400,33 @@ static void rna_KeyMapItem_update(Main *UNUSED(bmain), Scene *UNUSED(scene), Poi
#else /* RNA_RUNTIME */
+/**
+ * expose ``Operator.options`` as its own type so we can control each flags use (some are read-only).
+ */
+static void rna_def_operator_options_runtime(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ srna = RNA_def_struct(brna, "OperatorOptions", NULL);
+ RNA_def_struct_ui_text(srna, "Operator Options", "Runtime options");
+ RNA_def_struct_sdna(srna, "wmOperator");
+
+ prop = RNA_def_property(srna, "is_grab_cursor", PROP_BOOLEAN, PROP_BOOLEAN);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", OP_IS_MODAL_GRAB_CURSOR);
+ RNA_def_property_ui_text(prop, "Grab Cursor", "True when the cursor is grabbed");
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+
+ prop = RNA_def_property(srna, "is_invoke", PROP_BOOLEAN, PROP_BOOLEAN);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", OP_IS_INVOKE);
+ RNA_def_property_ui_text(prop, "Invoke", "True when invoked (even if only the execute callbacks available)");
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+
+ prop = RNA_def_property(srna, "use_cursor_region", PROP_BOOLEAN, PROP_BOOLEAN);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", OP_IS_MODAL_CURSOR_REGION);
+ RNA_def_property_ui_text(prop, "Focus Region", "Enable to use the region under the cursor for modal execution");
+}
+
static void rna_def_operator(BlenderRNA *brna)
{
StructRNA *srna;
@@ -1378,7 +1439,7 @@ static void rna_def_operator(BlenderRNA *brna)
#ifdef WITH_PYTHON
RNA_def_struct_register_funcs(srna, "rna_Operator_register", "rna_Operator_unregister", "rna_Operator_instance");
#endif
- RNA_def_struct_translation_context(srna, BLF_I18NCONTEXT_OPERATOR_DEFAULT);
+ RNA_def_struct_translation_context(srna, BLT_I18NCONTEXT_OPERATOR_DEFAULT);
prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE);
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
@@ -1400,6 +1461,12 @@ static void rna_def_operator(BlenderRNA *brna)
prop = RNA_def_property(srna, "layout", PROP_POINTER, PROP_NONE);
RNA_def_property_struct_type(prop, "UILayout");
+ prop = RNA_def_property(srna, "options", PROP_POINTER, PROP_NONE);
+ RNA_def_property_flag(prop, PROP_NEVER_NULL);
+ RNA_def_property_struct_type(prop, "OperatorOptions");
+ RNA_def_property_pointer_funcs(prop, "rna_Operator_options_get", NULL, NULL, NULL);
+ RNA_def_property_ui_text(prop, "Options", "Runtime options");
+
/* Registration */
prop = RNA_def_property(srna, "bl_idname", PROP_STRING, PROP_NONE);
RNA_def_property_string_sdna(prop, NULL, "type->idname");
@@ -1421,7 +1488,7 @@ static void rna_def_operator(BlenderRNA *brna)
RNA_def_property_string_sdna(prop, NULL, "type->translation_context");
RNA_def_property_string_maxlength(prop, RNA_DYN_DESCR_MAX); /* else it uses the pointer size! */
RNA_def_property_string_funcs(prop, NULL, NULL, "rna_Operator_bl_translation_context_set");
- RNA_def_property_string_default(prop, BLF_I18NCONTEXT_OPERATOR_DEFAULT);
+ RNA_def_property_string_default(prop, BLT_I18NCONTEXT_OPERATOR_DEFAULT);
RNA_def_property_flag(prop, PROP_REGISTER_OPTIONAL);
RNA_def_property_clear_flag(prop, PROP_NEVER_NULL); /* check for NULL */
@@ -1439,6 +1506,11 @@ static void rna_def_operator(BlenderRNA *brna)
RNA_def_property_flag(prop, PROP_REGISTER_OPTIONAL | PROP_ENUM_FLAG);
RNA_def_property_ui_text(prop, "Options", "Options for this operator type");
+ prop = RNA_def_property(srna, "macros", PROP_COLLECTION, PROP_NONE);
+ RNA_def_property_collection_sdna(prop, NULL, "macro", NULL);
+ RNA_def_property_struct_type(prop, "Macro");
+ RNA_def_property_ui_text(prop, "Macros", "");
+
RNA_api_operator(srna);
srna = RNA_def_struct(brna, "OperatorProperties", NULL);
@@ -1461,7 +1533,7 @@ static void rna_def_macro_operator(BlenderRNA *brna)
RNA_def_struct_register_funcs(srna, "rna_MacroOperator_register", "rna_Operator_unregister",
"rna_Operator_instance");
#endif
- RNA_def_struct_translation_context(srna, BLF_I18NCONTEXT_OPERATOR_DEFAULT);
+ RNA_def_struct_translation_context(srna, BLT_I18NCONTEXT_OPERATOR_DEFAULT);
prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE);
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
@@ -1494,7 +1566,7 @@ static void rna_def_macro_operator(BlenderRNA *brna)
RNA_def_property_string_sdna(prop, NULL, "type->translation_context");
RNA_def_property_string_maxlength(prop, RNA_DYN_DESCR_MAX); /* else it uses the pointer size! */
RNA_def_property_string_funcs(prop, NULL, NULL, "rna_Operator_bl_translation_context_set");
- RNA_def_property_string_default(prop, BLF_I18NCONTEXT_OPERATOR_DEFAULT);
+ RNA_def_property_string_default(prop, BLT_I18NCONTEXT_OPERATOR_DEFAULT);
RNA_def_property_flag(prop, PROP_REGISTER_OPTIONAL);
RNA_def_property_clear_flag(prop, PROP_NEVER_NULL); /* check for NULL */
@@ -1747,6 +1819,37 @@ static void rna_def_piemenu(BlenderRNA *brna)
RNA_define_verify_sdna(1); /* not in sdna */
}
+static void rna_def_window_stereo3d(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ srna = RNA_def_struct(brna, "Stereo3dDisplay", NULL);
+ RNA_def_struct_sdna(srna, "Stereo3dFormat");
+ RNA_def_struct_clear_flag(srna, STRUCT_UNDO);
+ RNA_def_struct_ui_text(srna, "Stereo 3D Display", "Settings for stereo 3D display");
+
+ prop = RNA_def_property(srna, "display_mode", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_items(prop, stereo3d_display_items);
+ RNA_def_property_ui_text(prop, "Display Mode", "");
+
+ prop = RNA_def_property(srna, "anaglyph_type", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_items(prop, stereo3d_anaglyph_type_items);
+ RNA_def_property_ui_text(prop, "Anaglyph Type", "");
+
+ prop = RNA_def_property(srna, "interlace_type", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_items(prop, stereo3d_interlace_type_items);
+ RNA_def_property_ui_text(prop, "Interlace Type", "");
+
+ prop = RNA_def_property(srna, "use_interlace_swap", PROP_BOOLEAN, PROP_BOOLEAN);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", S3D_INTERLACE_SWAP);
+ RNA_def_property_ui_text(prop, "Swap Left/Right", "Swap left and right stereo channels");
+
+ prop = RNA_def_property(srna, "use_sidebyside_crosseyed", PROP_BOOLEAN, PROP_BOOLEAN);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", S3D_SIDEBYSIDE_CROSSEYED);
+ RNA_def_property_ui_text(prop, "Cross-Eyed", "Right eye should see left image and vice-versa");
+}
+
static void rna_def_window(BlenderRNA *brna)
{
StructRNA *srna;
@@ -1756,6 +1859,8 @@ static void rna_def_window(BlenderRNA *brna)
RNA_def_struct_ui_text(srna, "Window", "Open window");
RNA_def_struct_sdna(srna, "wmWindow");
+ rna_def_window_stereo3d(brna);
+
prop = RNA_def_property(srna, "screen", PROP_POINTER, PROP_NONE);
RNA_def_property_flag(prop, PROP_NEVER_NULL);
RNA_def_property_struct_type(prop, "Screen");
@@ -1785,6 +1890,12 @@ static void rna_def_window(BlenderRNA *brna)
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_ui_text(prop, "Height", "Window height");
+ prop = RNA_def_property(srna, "stereo_3d_display", PROP_POINTER, PROP_NONE);
+ RNA_def_property_pointer_sdna(prop, NULL, "stereo3d_format");
+ RNA_def_property_flag(prop, PROP_NEVER_NULL);
+ RNA_def_property_struct_type(prop, "Stereo3dDisplay");
+ RNA_def_property_ui_text(prop, "Stereo 3D Display", "Settings for stereo 3d display");
+
RNA_api_window(srna);
}
@@ -2027,12 +2138,13 @@ static void rna_def_keyconfig(BlenderRNA *brna)
RNA_def_property_update(prop, 0, "rna_KeyMapItem_update");
prop = RNA_def_property(srna, "any", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_funcs(prop, "rna_KeyMapItem_any_getf", "rna_KeyMapItem_any_setf");
+ RNA_def_property_boolean_funcs(prop, "rna_KeyMapItem_any_get", "rna_KeyMapItem_any_set");
RNA_def_property_ui_text(prop, "Any", "Any modifier keys pressed");
RNA_def_property_update(prop, 0, "rna_KeyMapItem_update");
prop = RNA_def_property(srna, "shift", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "shift", 0);
+ RNA_def_property_boolean_funcs(prop, "rna_KeyMapItem_shift_get", NULL);
/* RNA_def_property_enum_sdna(prop, NULL, "shift"); */
/* RNA_def_property_enum_items(prop, keymap_modifiers_items); */
RNA_def_property_ui_text(prop, "Shift", "Shift key pressed");
@@ -2040,6 +2152,7 @@ static void rna_def_keyconfig(BlenderRNA *brna)
prop = RNA_def_property(srna, "ctrl", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "ctrl", 0);
+ RNA_def_property_boolean_funcs(prop, "rna_KeyMapItem_ctrl_get", NULL);
/* RNA_def_property_enum_sdna(prop, NULL, "ctrl"); */
/* RNA_def_property_enum_items(prop, keymap_modifiers_items); */
RNA_def_property_ui_text(prop, "Ctrl", "Control key pressed");
@@ -2047,6 +2160,7 @@ static void rna_def_keyconfig(BlenderRNA *brna)
prop = RNA_def_property(srna, "alt", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "alt", 0);
+ RNA_def_property_boolean_funcs(prop, "rna_KeyMapItem_alt_get", NULL);
/* RNA_def_property_enum_sdna(prop, NULL, "alt"); */
/* RNA_def_property_enum_items(prop, keymap_modifiers_items); */
RNA_def_property_ui_text(prop, "Alt", "Alt key pressed");
@@ -2054,6 +2168,7 @@ static void rna_def_keyconfig(BlenderRNA *brna)
prop = RNA_def_property(srna, "oskey", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "oskey", 0);
+ RNA_def_property_boolean_funcs(prop, "rna_KeyMapItem_oskey_get", NULL);
/* RNA_def_property_enum_sdna(prop, NULL, "oskey"); */
/* RNA_def_property_enum_items(prop, keymap_modifiers_items); */
RNA_def_property_ui_text(prop, "OS Key", "Operating system key pressed");
@@ -2102,6 +2217,7 @@ static void rna_def_keyconfig(BlenderRNA *brna)
void RNA_def_wm(BlenderRNA *brna)
{
rna_def_operator(brna);
+ rna_def_operator_options_runtime(brna);
rna_def_operator_utils(brna);
rna_def_operator_filelist_element(brna);
rna_def_macro_operator(brna);
diff --git a/source/blender/makesrna/intern/rna_wm_api.c b/source/blender/makesrna/intern/rna_wm_api.c
index ad638f2187c..e819d331124 100644
--- a/source/blender/makesrna/intern/rna_wm_api.c
+++ b/source/blender/makesrna/intern/rna_wm_api.c
@@ -298,7 +298,7 @@ static PointerRNA rna_PupMenuBegin(bContext *C, const char *title, int icon)
PointerRNA r_ptr;
void *data;
- data = (void *)uiPupMenuBegin(C, title, icon);
+ data = (void *)UI_popup_menu_begin(C, title, icon);
RNA_pointer_create(NULL, &RNA_UIPopupMenu, data, &r_ptr);
@@ -307,7 +307,7 @@ static PointerRNA rna_PupMenuBegin(bContext *C, const char *title, int icon)
static void rna_PupMenuEnd(bContext *C, PointerRNA *handle)
{
- uiPupMenuEnd(C, handle->data);
+ UI_popup_menu_end(C, handle->data);
}
/* pie menu wrapper */
@@ -316,7 +316,7 @@ static PointerRNA rna_PieMenuBegin(bContext *C, const char *title, int icon, Poi
PointerRNA r_ptr;
void *data;
- data = (void *)uiPieMenuBegin(C, title, icon, event->data);
+ data = (void *)UI_pie_menu_begin(C, title, icon, event->data);
RNA_pointer_create(NULL, &RNA_UIPieMenu, data, &r_ptr);
@@ -325,7 +325,7 @@ static PointerRNA rna_PieMenuBegin(bContext *C, const char *title, int icon, Poi
static void rna_PieMenuEnd(bContext *C, PointerRNA *handle)
{
- uiPieMenuEnd(C, handle->data);
+ UI_pie_menu_end(C, handle->data);
}
#else
@@ -462,7 +462,7 @@ void RNA_api_wm(StructRNA *srna)
rna_generic_op_invoke(func, WM_GEN_INVOKE_EVENT | WM_GEN_INVOKE_RETURN);
- /* wrap uiPupMenuBegin */
+ /* wrap UI_popup_menu_begin */
func = RNA_def_function(srna, "pupmenu_begin__internal", "rna_PupMenuBegin");
RNA_def_function_flag(func, FUNC_NO_SELF | FUNC_USE_CONTEXT);
parm = RNA_def_string(func, "title", NULL, 0, "", "");
@@ -474,7 +474,7 @@ void RNA_api_wm(StructRNA *srna)
RNA_def_property_flag(parm, PROP_RNAPTR | PROP_NEVER_NULL);
RNA_def_function_return(func, parm);
- /* wrap uiPupMenuEnd */
+ /* wrap UI_popup_menu_end */
func = RNA_def_function(srna, "pupmenu_end__internal", "rna_PupMenuEnd");
RNA_def_function_flag(func, FUNC_NO_SELF | FUNC_USE_CONTEXT);
parm = RNA_def_pointer(func, "menu", "UIPopupMenu", "", "");
diff --git a/source/blender/makesrna/intern/rna_world.c b/source/blender/makesrna/intern/rna_world.c
index f63350ea0ae..3f55ad9c668 100644
--- a/source/blender/makesrna/intern/rna_world.c
+++ b/source/blender/makesrna/intern/rna_world.c
@@ -89,9 +89,10 @@ static void rna_World_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerR
World *wo = ptr->id.data;
DAG_id_tag_update(&wo->id, 0);
- WM_main_add_notifier(NC_WORLD, wo);
+ WM_main_add_notifier(NC_WORLD | ND_WORLD, wo);
}
+#if 0
static void rna_World_draw_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
{
World *wo = ptr->id.data;
@@ -99,6 +100,7 @@ static void rna_World_draw_update(Main *UNUSED(bmain), Scene *UNUSED(scene), Poi
DAG_id_tag_update(&wo->id, 0);
WM_main_add_notifier(NC_WORLD | ND_WORLD_DRAW, wo);
}
+#endif
/* so camera mist limits redraw */
static void rna_World_draw_mist_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
@@ -403,13 +405,13 @@ static void rna_def_world_mist(BlenderRNA *brna)
prop = RNA_def_property(srna, "use_mist", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "mode", WO_MIST);
RNA_def_property_ui_text(prop, "Use Mist", "Occlude objects with the environment color as they are further away");
- RNA_def_property_update(prop, 0, "rna_World_draw_update");
+ RNA_def_property_update(prop, 0, "rna_World_draw_mist_update");
prop = RNA_def_property(srna, "intensity", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "misi");
RNA_def_property_range(prop, 0, 1);
RNA_def_property_ui_text(prop, "Minimum", "Overall minimum intensity of the mist effect");
- RNA_def_property_update(prop, 0, "rna_World_update");
+ RNA_def_property_update(prop, 0, "rna_World_draw_mist_update");
prop = RNA_def_property(srna, "start", PROP_FLOAT, PROP_DISTANCE);
RNA_def_property_float_sdna(prop, NULL, "miststa");
@@ -435,7 +437,7 @@ static void rna_def_world_mist(BlenderRNA *brna)
RNA_def_property_enum_sdna(prop, NULL, "mistype");
RNA_def_property_enum_items(prop, falloff_items);
RNA_def_property_ui_text(prop, "Falloff", "Type of transition used to fade mist");
- RNA_def_property_update(prop, 0, "rna_World_update");
+ RNA_def_property_update(prop, 0, "rna_World_draw_mist_update");
}
void RNA_def_world(BlenderRNA *brna)
@@ -460,8 +462,7 @@ void RNA_def_world(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Horizon Color", "Color at the horizon");
/* RNA_def_property_update(prop, 0, "rna_World_update"); */
/* render-only uses this */
- RNA_def_property_update(prop, NC_WORLD | ND_WORLD_DRAW, "rna_World_update");
-
+ RNA_def_property_update(prop, 0, "rna_World_draw_mist_update");
prop = RNA_def_property(srna, "zenith_color", PROP_FLOAT, PROP_COLOR);
RNA_def_property_float_sdna(prop, NULL, "zenr");
@@ -473,7 +474,7 @@ void RNA_def_world(BlenderRNA *brna)
RNA_def_property_float_sdna(prop, NULL, "ambr");
RNA_def_property_array(prop, 3);
RNA_def_property_ui_text(prop, "Ambient Color", "Ambient color of the world");
- RNA_def_property_update(prop, 0, "rna_World_update");
+ RNA_def_property_update(prop, 0, "rna_World_draw_mist_update");
/* exp, range */
prop = RNA_def_property(srna, "exposure", PROP_FLOAT, PROP_NONE);
diff --git a/source/blender/modifiers/CMakeLists.txt b/source/blender/modifiers/CMakeLists.txt
index 71c84fd1e8a..ad230dede24 100644
--- a/source/blender/modifiers/CMakeLists.txt
+++ b/source/blender/modifiers/CMakeLists.txt
@@ -30,6 +30,7 @@ set(INC
../blenkernel
../blenlib
../blenfont
+ ../depsgraph
../makesdna
../makesrna
../bmesh
@@ -40,7 +41,6 @@ set(INC
set(INC_SYS
${ZLIB_INCLUDE_DIRS}
- ${GLEW_INCLUDE_PATH}
)
set(SRC
@@ -52,7 +52,9 @@ set(SRC
intern/MOD_cast.c
intern/MOD_cloth.c
intern/MOD_collision.c
+ intern/MOD_correctivesmooth.c
intern/MOD_curve.c
+ intern/MOD_datatransfer.c
intern/MOD_decimate.c
intern/MOD_displace.c
intern/MOD_dynamicpaint.c
@@ -73,6 +75,7 @@ set(SRC
intern/MOD_mirror.c
intern/MOD_multires.c
intern/MOD_none.c
+ intern/MOD_normal_edit.c
intern/MOD_ocean.c
intern/MOD_particleinstance.c
intern/MOD_particlesystem.c
@@ -148,4 +151,8 @@ if(WITH_OPENNL)
)
endif()
+if(WITH_OPENSUBDIV)
+ add_definitions(-DWITH_OPENSUBDIV)
+endif()
+
blender_add_lib(bf_modifiers "${SRC}" "${INC}" "${INC_SYS}")
diff --git a/source/blender/modifiers/MOD_modifiertypes.h b/source/blender/modifiers/MOD_modifiertypes.h
index 9c7c21cc839..a5d96759952 100644
--- a/source/blender/modifiers/MOD_modifiertypes.h
+++ b/source/blender/modifiers/MOD_modifiertypes.h
@@ -81,6 +81,9 @@ extern ModifierTypeInfo modifierType_UVWarp;
extern ModifierTypeInfo modifierType_MeshCache;
extern ModifierTypeInfo modifierType_LaplacianDeform;
extern ModifierTypeInfo modifierType_Wireframe;
+extern ModifierTypeInfo modifierType_DataTransfer;
+extern ModifierTypeInfo modifierType_NormalEdit;
+extern ModifierTypeInfo modifierType_CorrectiveSmooth;
/* MOD_util.c */
void modifier_type_init(ModifierTypeInfo *types[]);
diff --git a/source/blender/modifiers/SConscript b/source/blender/modifiers/SConscript
index c112f525398..7be295aa1a0 100644
--- a/source/blender/modifiers/SConscript
+++ b/source/blender/modifiers/SConscript
@@ -34,13 +34,13 @@ incs = [
'./intern',
'#/intern/guardedalloc',
'#/intern/elbeem/extern',
- '#/extern/glew/include',
'#/intern/opennl/extern',
'../render/extern/include',
'../bmesh',
'../include',
'../blenlib',
'../blenfont',
+ '../depsgraph',
'../makesdna',
'../makesrna',
'../blenkernel',
@@ -53,6 +53,9 @@ defs = []
if env['WITH_BF_BOOLEAN']:
incs.append('#/extern/carve')
defs.append('WITH_MOD_BOOLEAN')
+else:
+ from os import path
+ sources.remove(path.join('intern', 'MOD_boolean_util.c'))
if env['WITH_BF_REMESH']:
incs.append('#/intern/dualcon')
@@ -73,7 +76,10 @@ if env['WITH_BF_GAMEENGINE']:
if env['WITH_BF_INTERNATIONAL']:
defs.append('WITH_INTERNATIONAL')
-
+
+if env['WITH_BF_OPENSUBDIV']:
+ defs.append('WITH_OPENSUBDIV')
+
if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'linuxcross', 'win64-vc', 'win64-mingw'):
incs.append(env['BF_PTHREADS_INC'])
diff --git a/source/blender/modifiers/intern/MOD_armature.c b/source/blender/modifiers/intern/MOD_armature.c
index a4248df5ea1..9ce31cebb66 100644
--- a/source/blender/modifiers/intern/MOD_armature.c
+++ b/source/blender/modifiers/intern/MOD_armature.c
@@ -100,6 +100,7 @@ static void foreachObjectLink(
}
static void updateDepgraph(ModifierData *md, DagForest *forest,
+ struct Main *UNUSED(bmain),
struct Scene *UNUSED(scene),
Object *UNUSED(ob),
DagNode *obNode)
@@ -114,6 +115,18 @@ static void updateDepgraph(ModifierData *md, DagForest *forest,
}
}
+static void updateDepsgraph(ModifierData *md,
+ struct Main *UNUSED(bmain),
+ struct Scene *UNUSED(scene),
+ Object *UNUSED(ob),
+ struct DepsNodeHandle *node)
+{
+ ArmatureModifierData *amd = (ArmatureModifierData *)md;
+ if (amd->object != NULL) {
+ DEG_add_object_relation(node, amd->object, DEG_OB_COMP_EVAL_POSE, "Armature Modifier");
+ }
+}
+
static void deformVerts(ModifierData *md, Object *ob,
DerivedMesh *derivedData,
float (*vertexCos)[3],
@@ -207,6 +220,7 @@ ModifierTypeInfo modifierType_Armature = {
/* freeData */ NULL,
/* isDisabled */ isDisabled,
/* updateDepgraph */ updateDepgraph,
+ /* updateDepsgraph */ updateDepsgraph,
/* dependsOnTime */ NULL,
/* dependsOnNormals */ NULL,
/* foreachObjectLink */ foreachObjectLink,
diff --git a/source/blender/modifiers/intern/MOD_array.c b/source/blender/modifiers/intern/MOD_array.c
index 66796480542..efb77f73ec9 100644
--- a/source/blender/modifiers/intern/MOD_array.c
+++ b/source/blender/modifiers/intern/MOD_array.c
@@ -102,7 +102,9 @@ static void foreachObjectLink(
}
static void updateDepgraph(ModifierData *md, DagForest *forest,
- struct Scene *UNUSED(scene), Object *UNUSED(ob), DagNode *obNode)
+ struct Main *UNUSED(bmain),
+ struct Scene *UNUSED(scene),
+ Object *UNUSED(ob), DagNode *obNode)
{
ArrayModifierData *amd = (ArrayModifierData *) md;
@@ -133,6 +135,28 @@ static void updateDepgraph(ModifierData *md, DagForest *forest,
}
}
+static void updateDepsgraph(ModifierData *md,
+ struct Main *UNUSED(bmain),
+ struct Scene *scene,
+ Object *UNUSED(ob),
+ struct DepsNodeHandle *node)
+{
+ ArrayModifierData *amd = (ArrayModifierData *)md;
+ if (amd->start_cap != NULL) {
+ DEG_add_object_relation(node, amd->start_cap, DEG_OB_COMP_TRANSFORM, "Hook Modifier Start Cap");
+ }
+ if (amd->end_cap != NULL) {
+ DEG_add_object_relation(node, amd->end_cap, DEG_OB_COMP_TRANSFORM, "Hook Modifier End Cap");
+ }
+ if (amd->curve_ob) {
+ DEG_add_object_relation(node, amd->end_cap, DEG_OB_COMP_GEOMETRY, "Hook Modifier Curve");
+ DEG_add_special_eval_flag(scene->depsgraph, &amd->curve_ob->id, DAG_EVAL_NEED_CURVE_PATH);
+ }
+ if (amd->offset_ob != NULL) {
+ DEG_add_object_relation(node, amd->offset_ob, DEG_OB_COMP_TRANSFORM, "Hook Modifier Offset");
+ }
+}
+
static float vertarray_size(const MVert *mvert, int numVerts, int axis)
{
int i;
@@ -167,8 +191,8 @@ typedef struct SortVertsElem {
static int svert_sum_cmp(const void *e1, const void *e2)
{
- const SortVertsElem *sv1 = (SortVertsElem *)e1;
- const SortVertsElem *sv2 = (SortVertsElem *)e2;
+ const SortVertsElem *sv1 = e1;
+ const SortVertsElem *sv2 = e2;
if (sv1->sum_co > sv2->sum_co) return 1;
else if (sv1->sum_co < sv2->sum_co) return -1;
@@ -201,7 +225,7 @@ static void dm_mvert_map_doubles(
const float dist,
const bool with_follow)
{
- const float dist3 = (M_SQRT3 + 0.00005f) * dist; /* Just above sqrt(3) */
+ const float dist3 = ((float)M_SQRT3 + 0.00005f) * dist; /* Just above sqrt(3) */
int i_source, i_target, i_target_low_bound, target_end, source_end;
SortVertsElem *sorted_verts_target, *sorted_verts_source;
SortVertsElem *sve_source, *sve_target, *sve_target_low_bound;
@@ -323,8 +347,8 @@ static void dm_merge_transform(
/* needed for subsurf so arrays are allocated */
cap_dm->getVertArray(cap_dm);
cap_dm->getEdgeArray(cap_dm);
- cap_dm->getNumLoops(cap_dm);
- cap_dm->getNumPolys(cap_dm);
+ cap_dm->getLoopArray(cap_dm);
+ cap_dm->getPolyArray(cap_dm);
DM_copy_vert_data(cap_dm, result, 0, cap_verts_index, cap_nverts);
DM_copy_edge_data(cap_dm, result, 0, cap_edges_index, cap_nedges);
@@ -362,22 +386,22 @@ static void dm_merge_transform(
/* set origindex */
index_orig = result->getVertDataArray(result, CD_ORIGINDEX);
if (index_orig) {
- fill_vn_i(index_orig + cap_verts_index, cap_nverts, ORIGINDEX_NONE);
+ copy_vn_i(index_orig + cap_verts_index, cap_nverts, ORIGINDEX_NONE);
}
index_orig = result->getEdgeDataArray(result, CD_ORIGINDEX);
if (index_orig) {
- fill_vn_i(index_orig + cap_edges_index, cap_nedges, ORIGINDEX_NONE);
+ copy_vn_i(index_orig + cap_edges_index, cap_nedges, ORIGINDEX_NONE);
}
index_orig = result->getPolyDataArray(result, CD_ORIGINDEX);
if (index_orig) {
- fill_vn_i(index_orig + cap_polys_index, cap_npolys, ORIGINDEX_NONE);
+ copy_vn_i(index_orig + cap_polys_index, cap_npolys, ORIGINDEX_NONE);
}
index_orig = result->getLoopDataArray(result, CD_ORIGINDEX);
if (index_orig) {
- fill_vn_i(index_orig + cap_loops_index, cap_nloops, ORIGINDEX_NONE);
+ copy_vn_i(index_orig + cap_loops_index, cap_nloops, ORIGINDEX_NONE);
}
}
@@ -404,8 +428,11 @@ static DerivedMesh *arrayModifier_doArray(
int *full_doubles_map = NULL;
int tot_doubles;
- const bool use_merge = amd->flags & MOD_ARR_MERGE;
+ const bool use_merge = (amd->flags & MOD_ARR_MERGE) != 0;
const bool use_recalc_normals = (dm->dirty & DM_DIRTY_NORMALS) || use_merge;
+ const bool use_offset_ob = ((amd->offset_type & MOD_ARR_OFF_OBJ) && amd->offset_ob);
+ /* allow pole vertices to be used by many faces */
+ const bool with_follow = use_offset_ob;
int start_cap_nverts = 0, start_cap_nedges = 0, start_cap_npolys = 0, start_cap_nloops = 0;
int end_cap_nverts = 0, end_cap_nedges = 0, end_cap_npolys = 0, end_cap_nloops = 0;
@@ -454,7 +481,7 @@ static DerivedMesh *arrayModifier_doArray(
offset[3][j] += amd->scale[j] * vertarray_size(src_mvert, chunk_nverts, j);
}
- if ((amd->offset_type & MOD_ARR_OFF_OBJ) && (amd->offset_ob)) {
+ if (use_offset_ob) {
float obinv[4][4];
float result_mat[4][4];
@@ -496,7 +523,7 @@ static DerivedMesh *arrayModifier_doArray(
if (dist > eps) {
/* this gives length = first copy start to last copy end
* add a tiny offset for floating point rounding errors */
- count = (length + eps) / dist;
+ count = (length + eps) / dist + 1;
}
else {
/* if the offset has no translation, just make one copy */
@@ -520,7 +547,7 @@ static DerivedMesh *arrayModifier_doArray(
if (use_merge) {
/* Will need full_doubles_map for handling merge */
full_doubles_map = MEM_mallocN(sizeof(int) * result_nverts, "mod array doubles map");
- fill_vn_i(full_doubles_map, result_nverts, -1);
+ copy_vn_i(full_doubles_map, result_nverts, -1);
}
/* copy customdata to original geometry */
@@ -606,10 +633,15 @@ static DerivedMesh *arrayModifier_doArray(
int target = full_doubles_map[prev_chunk_index];
if (target != -1) {
target += chunk_nverts; /* translate mapping */
- /* The rule here is to not follow mapping to chunk N-2, which could be too far
- * so if target vertex was itself mapped, then this vertex is not mapped */
if (full_doubles_map[target] != -1) {
- target = -1;
+ if (with_follow) {
+ target = full_doubles_map[target];
+ }
+ else {
+ /* The rule here is to not follow mapping to chunk N-2, which could be too far
+ * so if target vertex was itself mapped, then this vertex is not mapped */
+ target = -1;
+ }
}
}
full_doubles_map[this_chunk_index] = target;
@@ -624,7 +656,7 @@ static DerivedMesh *arrayModifier_doArray(
c * chunk_nverts,
chunk_nverts,
amd->merge_dist,
- false);
+ with_follow);
}
}
}
@@ -644,7 +676,7 @@ static DerivedMesh *arrayModifier_doArray(
first_chunk_start,
first_chunk_nverts,
amd->merge_dist,
- false);
+ with_follow);
}
/* start capping */
@@ -699,19 +731,17 @@ static DerivedMesh *arrayModifier_doArray(
}
/* done capping */
- /* In case org dm has dirty normals, or we made some merging, mark normals as dirty in new dm!
- * TODO: we may need to set other dirty flags as well?
- */
- if (use_recalc_normals) {
- result->dirty |= DM_DIRTY_NORMALS;
- }
-
/* Handle merging */
tot_doubles = 0;
if (use_merge) {
for (i = 0; i < result_nverts; i++) {
if (full_doubles_map[i] != -1) {
- tot_doubles++;
+ if (i == full_doubles_map[i]) {
+ full_doubles_map[i] = -1;
+ }
+ else {
+ tot_doubles++;
+ }
}
}
if (tot_doubles > 0) {
@@ -719,6 +749,14 @@ static DerivedMesh *arrayModifier_doArray(
}
MEM_freeN(full_doubles_map);
}
+
+ /* In case org dm has dirty normals, or we made some merging, mark normals as dirty in new dm!
+ * TODO: we may need to set other dirty flags as well?
+ */
+ if (use_recalc_normals) {
+ result->dirty |= DM_DIRTY_NORMALS;
+ }
+
return result;
}
@@ -755,6 +793,7 @@ ModifierTypeInfo modifierType_Array = {
/* freeData */ NULL,
/* isDisabled */ NULL,
/* updateDepgraph */ updateDepgraph,
+ /* updateDepsgraph */ updateDepsgraph,
/* dependsOnTime */ NULL,
/* dependsOnNormals */ NULL,
/* foreachObjectLink */ foreachObjectLink,
diff --git a/source/blender/modifiers/intern/MOD_bevel.c b/source/blender/modifiers/intern/MOD_bevel.c
index 2de3220e683..5874029ae08 100644
--- a/source/blender/modifiers/intern/MOD_bevel.c
+++ b/source/blender/modifiers/intern/MOD_bevel.c
@@ -112,6 +112,7 @@ static DerivedMesh *applyModifier(ModifierData *md, struct Object *ob,
const bool do_clamp = !(bmd->flags & MOD_BEVEL_OVERLAP_OK);
const int offset_type = bmd->val_flags;
const int mat = CLAMPIS(bmd->mat, -1, ob->totcol - 1);
+ const bool loop_slide = (bmd->flags & MOD_BEVEL_EVEN_WIDTHS) == 0;
bm = DM_to_bmesh(dm, true);
if ((bmd->lim_flags & MOD_BEVEL_VGROUP) && bmd->defgrp_name[0])
@@ -121,7 +122,12 @@ static DerivedMesh *applyModifier(ModifierData *md, struct Object *ob,
BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
if (!BM_vert_is_manifold(v))
continue;
- if (vgroup != -1) {
+ if (bmd->lim_flags & MOD_BEVEL_WEIGHT) {
+ weight = BM_elem_float_data_get(&bm->vdata, v, CD_BWEIGHT);
+ if (weight == 0.0f)
+ continue;
+ }
+ else if (vgroup != -1) {
weight = defvert_array_find_weight_safe(dvert, BM_elem_index_get(v), vgroup);
/* Check is against 0.5 rather than != 0.0 because cascaded bevel modifiers will
* interpolate weights for newly created vertices, and may cause unexpected "selection" */
@@ -168,7 +174,7 @@ static DerivedMesh *applyModifier(ModifierData *md, struct Object *ob,
BM_mesh_bevel(bm, bmd->value, offset_type, bmd->res, bmd->profile,
vertex_only, bmd->lim_flags & MOD_BEVEL_WEIGHT, do_clamp,
- dvert, vgroup, mat);
+ dvert, vgroup, mat, loop_slide);
result = CDDM_from_bmesh(bm, true);
@@ -208,6 +214,7 @@ ModifierTypeInfo modifierType_Bevel = {
/* freeData */ NULL,
/* isDisabled */ NULL,
/* updateDepgraph */ NULL,
+ /* updateDepsgraph */ NULL,
/* dependsOnTime */ NULL,
/* dependsOnNormals */ dependsOnNormals,
/* foreachObjectLink */ NULL,
diff --git a/source/blender/modifiers/intern/MOD_boolean.c b/source/blender/modifiers/intern/MOD_boolean.c
index 49c0c091dee..eb54a3c4e9c 100644
--- a/source/blender/modifiers/intern/MOD_boolean.c
+++ b/source/blender/modifiers/intern/MOD_boolean.c
@@ -39,8 +39,6 @@
#include "BLI_utildefines.h"
-#include "BLF_translation.h"
-
#include "BKE_cdderivedmesh.h"
#include "BKE_modifier.h"
@@ -49,8 +47,6 @@
#include "MOD_boolean_util.h"
#include "MOD_util.h"
-#include "PIL_time.h"
-
static void copyData(ModifierData *md, ModifierData *target)
{
#if 0
@@ -78,6 +74,7 @@ static void foreachObjectLink(
}
static void updateDepgraph(ModifierData *md, DagForest *forest,
+ struct Main *UNUSED(bmain),
struct Scene *UNUSED(scene),
Object *UNUSED(ob),
DagNode *obNode)
@@ -92,6 +89,21 @@ static void updateDepgraph(ModifierData *md, DagForest *forest,
}
}
+static void updateDepsgraph(ModifierData *md,
+ struct Main *UNUSED(bmain),
+ struct Scene *UNUSED(scene),
+ Object *ob,
+ struct DepsNodeHandle *node)
+{
+ BooleanModifierData *bmd = (BooleanModifierData *)md;
+ if (bmd->object != NULL) {
+ DEG_add_object_relation(node, bmd->object, DEG_OB_COMP_TRANSFORM, "Boolean Modifier");
+ DEG_add_object_relation(node, bmd->object, DEG_OB_COMP_GEOMETRY, "Boolean Modifier");
+ }
+ /* We need own transformation as well. */
+ DEG_add_object_relation(node, ob, DEG_OB_COMP_TRANSFORM, "Boolean Modifier");
+}
+
#ifdef WITH_MOD_BOOLEAN
static DerivedMesh *get_quick_derivedMesh(DerivedMesh *derivedData, DerivedMesh *dm, int operation)
{
@@ -196,6 +208,7 @@ ModifierTypeInfo modifierType_Boolean = {
/* freeData */ NULL,
/* isDisabled */ isDisabled,
/* updateDepgraph */ updateDepgraph,
+ /* updateDepsgraph */ updateDepsgraph,
/* dependsOnTime */ NULL,
/* dependsOnNormals */ NULL,
/* foreachObjectLink */ foreachObjectLink,
diff --git a/source/blender/modifiers/intern/MOD_boolean_util.c b/source/blender/modifiers/intern/MOD_boolean_util.c
index 6e62a21ec4c..061b1198f7e 100644
--- a/source/blender/modifiers/intern/MOD_boolean_util.c
+++ b/source/blender/modifiers/intern/MOD_boolean_util.c
@@ -365,14 +365,6 @@ BLI_INLINE MPoly *which_mpoly(ExportMeshData *export_data, int which_mesh)
return mpoly;
}
-static void allocate_custom_layers(CustomData *data, int type, int num_elements, int num_layers)
-{
- int i;
- for (i = 0; i < num_layers; i++) {
- CustomData_add_layer(data, type, CD_DEFAULT, NULL, num_elements);
- }
-}
-
/* Create new external mesh */
static void exporter_InitGeomArrays(ExportMeshData *export_data,
int num_verts, int num_edges,
@@ -392,24 +384,15 @@ static void exporter_InitGeomArrays(ExportMeshData *export_data,
export_data->mloop = dm->getLoopArray(dm);
export_data->mpoly = dm->getPolyArray(dm);
- /* Allocate layers for UV layers and vertex colors.
- * Without this interpolation of those data will not happen.
- */
- allocate_custom_layers(&dm->loopData, CD_MLOOPCOL, num_loops,
- CustomData_number_of_layers(&dm_left->loopData, CD_MLOOPCOL));
- allocate_custom_layers(&dm->loopData, CD_MLOOPUV, num_loops,
- CustomData_number_of_layers(&dm_left->loopData, CD_MLOOPUV));
-
- allocate_custom_layers(&dm->loopData, CD_MLOOPCOL, num_loops,
- CustomData_number_of_layers(&dm_right->loopData, CD_MLOOPCOL));
- allocate_custom_layers(&dm->loopData, CD_MLOOPUV, num_loops,
- CustomData_number_of_layers(&dm_right->loopData, CD_MLOOPUV));
-
/* Merge custom data layers from operands.
*
* Will only create custom data layers for all the layers which appears in
* the operand. Data for those layers will not be allocated or initialized.
*/
+
+ CustomData_merge(&dm_left->loopData, &dm->loopData, merge_mask, CD_DEFAULT, num_loops);
+ CustomData_merge(&dm_right->loopData, &dm->loopData, merge_mask, CD_DEFAULT, num_loops);
+
CustomData_merge(&dm_left->polyData, &dm->polyData, merge_mask, CD_DEFAULT, num_polys);
CustomData_merge(&dm_right->polyData, &dm->polyData, merge_mask, CD_DEFAULT, num_polys);
diff --git a/source/blender/modifiers/intern/MOD_boolean_util.h b/source/blender/modifiers/intern/MOD_boolean_util.h
index 04d76d45652..00d7c37b266 100644
--- a/source/blender/modifiers/intern/MOD_boolean_util.h
+++ b/source/blender/modifiers/intern/MOD_boolean_util.h
@@ -33,9 +33,7 @@
#ifndef __MOD_BOOLEAN_UTIL_H__
#define __MOD_BOOLEAN_UTIL_H__
-struct Scene;
struct Object;
-struct Base;
struct DerivedMesh;
/* Performs a boolean between two mesh objects, it is assumed that both objects
diff --git a/source/blender/modifiers/intern/MOD_build.c b/source/blender/modifiers/intern/MOD_build.c
index f6ade2bf303..507fad466a3 100644
--- a/source/blender/modifiers/intern/MOD_build.c
+++ b/source/blender/modifiers/intern/MOD_build.c
@@ -40,16 +40,16 @@
#include "BLI_math_vector.h"
#include "BLI_ghash.h"
-#include "DNA_scene_types.h"
#include "DNA_meshdata_types.h"
#include "BKE_cdderivedmesh.h"
-#include "BKE_mesh.h"
#include "BKE_modifier.h"
#include "BKE_particle.h"
#include "BKE_scene.h"
-#include "MOD_util.h"
+#ifdef _OPENMP
+# include "BKE_mesh.h" /* BKE_MESH_OMP_LIMIT */
+#endif
static void initData(ModifierData *md)
{
@@ -86,7 +86,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *UNUSED(ob),
float frac;
MPoly *mpoly_dst;
MLoop *ml_dst, *ml_src /*, *mloop_dst */;
- GHashIterator *hashIter;
+ GHashIterator gh_iter;
/* maps vert indices in old mesh to indices in new mesh */
GHash *vertHash = BLI_ghash_int_new("build ve apply gh");
/* maps edge indices in new mesh to indices in old mesh */
@@ -131,6 +131,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *UNUSED(ob),
MPoly *mpoly, *mp;
MLoop *ml, *mloop;
MEdge *medge;
+ uintptr_t hash_num, hash_num_alt;
if (bmd->flag & MOD_BUILD_FLAG_RANDOMIZE) {
BLI_array_randomize(faceMap, sizeof(*faceMap),
@@ -142,40 +143,44 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *UNUSED(ob),
*/
mpoly = mpoly_src;
mloop = mloop_src;
+ hash_num = 0;
for (i = 0; i < numFaces_dst; i++) {
mp = mpoly + faceMap[i];
ml = mloop + mp->loopstart;
for (j = 0; j < mp->totloop; j++, ml++) {
- if (!BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(ml->v)))
- BLI_ghash_insert(vertHash, SET_INT_IN_POINTER(ml->v),
- SET_INT_IN_POINTER(BLI_ghash_size(vertHash)));
+ void **val_p;
+ if (!BLI_ghash_ensure_p(vertHash, SET_INT_IN_POINTER(ml->v), &val_p)) {
+ *val_p = (void *)hash_num;
+ hash_num++;
+ }
}
-
+
numLoops_dst += mp->totloop;
}
+ BLI_assert(hash_num == BLI_ghash_size(vertHash));
/* get the set of edges that will be in the new mesh (i.e. all edges
* that have both verts in the new mesh)
*/
medge = medge_src;
- for (i = 0; i < numEdge_src; i++) {
+ hash_num = 0;
+ hash_num_alt = 0;
+ for (i = 0; i < numEdge_src; i++, hash_num_alt++) {
MEdge *me = medge + i;
if (BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(me->v1)) &&
BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(me->v2)))
{
- j = BLI_ghash_size(edgeHash);
-
- BLI_ghash_insert(edgeHash, SET_INT_IN_POINTER(j),
- SET_INT_IN_POINTER(i));
- BLI_ghash_insert(edgeHash2, SET_INT_IN_POINTER(i),
- SET_INT_IN_POINTER(j));
+ BLI_ghash_insert(edgeHash, (void *)hash_num, (void *)hash_num_alt);
+ BLI_ghash_insert(edgeHash2, (void *)hash_num_alt, (void *)hash_num);
+ hash_num++;
}
}
}
else if (numEdges_dst) {
MEdge *medge, *me;
+ uintptr_t hash_num;
if (bmd->flag & MOD_BUILD_FLAG_RANDOMIZE)
BLI_array_randomize(edgeMap, sizeof(*edgeMap),
@@ -185,17 +190,22 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *UNUSED(ob),
* mapped to the new indices
*/
medge = medge_src;
+ hash_num = 0;
+ BLI_assert(hash_num == BLI_ghash_size(vertHash));
for (i = 0; i < numEdges_dst; i++) {
+ void **val_p;
me = medge + edgeMap[i];
- if (!BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(me->v1))) {
- BLI_ghash_insert(vertHash, SET_INT_IN_POINTER(me->v1),
- SET_INT_IN_POINTER(BLI_ghash_size(vertHash)));
+ if (!BLI_ghash_ensure_p(vertHash, SET_INT_IN_POINTER(me->v1), &val_p)) {
+ *val_p = (void *)hash_num;
+ hash_num++;
}
- if (!BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(me->v2))) {
- BLI_ghash_insert(vertHash, SET_INT_IN_POINTER(me->v2), SET_INT_IN_POINTER(BLI_ghash_size(vertHash)));
+ if (!BLI_ghash_ensure_p(vertHash, SET_INT_IN_POINTER(me->v2), &val_p)) {
+ *val_p = (void *)hash_num;
+ hash_num++;
}
}
+ BLI_assert(hash_num == BLI_ghash_size(vertHash));
/* get the set of edges that will be in the new mesh */
for (i = 0; i < numEdges_dst; i++) {
@@ -230,15 +240,11 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *UNUSED(ob),
BLI_ghash_size(edgeHash), 0, numLoops_dst, numFaces_dst);
/* copy the vertices across */
- for (hashIter = BLI_ghashIterator_new(vertHash);
- BLI_ghashIterator_done(hashIter) == false;
- BLI_ghashIterator_step(hashIter)
- )
- {
+ GHASH_ITER (gh_iter, vertHash) {
MVert source;
MVert *dest;
- int oldIndex = GET_INT_FROM_POINTER(BLI_ghashIterator_getKey(hashIter));
- int newIndex = GET_INT_FROM_POINTER(BLI_ghashIterator_getValue(hashIter));
+ int oldIndex = GET_INT_FROM_POINTER(BLI_ghashIterator_getKey(&gh_iter));
+ int newIndex = GET_INT_FROM_POINTER(BLI_ghashIterator_getValue(&gh_iter));
source = mvert_src[oldIndex];
dest = CDDM_get_vert(result, newIndex);
@@ -246,7 +252,6 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *UNUSED(ob),
DM_copy_vert_data(dm, result, oldIndex, newIndex, 1);
*dest = source;
}
- BLI_ghashIterator_free(hashIter);
/* copy the edges across, remapping indices */
for (i = 0; i < BLI_ghash_size(edgeHash); i++) {
@@ -324,6 +329,7 @@ ModifierTypeInfo modifierType_Build = {
/* freeData */ NULL,
/* isDisabled */ NULL,
/* updateDepgraph */ NULL,
+ /* updateDepsgraph */ NULL,
/* dependsOnTime */ dependsOnTime,
/* dependsOnNormals */ NULL,
/* foreachObjectLink */ NULL,
diff --git a/source/blender/modifiers/intern/MOD_cast.c b/source/blender/modifiers/intern/MOD_cast.c
index c4654287cfc..7c3d65a5c9a 100644
--- a/source/blender/modifiers/intern/MOD_cast.c
+++ b/source/blender/modifiers/intern/MOD_cast.c
@@ -106,6 +106,7 @@ static void foreachObjectLink(
}
static void updateDepgraph(ModifierData *md, DagForest *forest,
+ struct Main *UNUSED(bmain),
struct Scene *UNUSED(scene),
Object *UNUSED(ob),
DagNode *obNode)
@@ -120,6 +121,18 @@ static void updateDepgraph(ModifierData *md, DagForest *forest,
}
}
+static void updateDepsgraph(ModifierData *md,
+ struct Main *UNUSED(bmain),
+ struct Scene *UNUSED(scene),
+ Object *UNUSED(ob),
+ struct DepsNodeHandle *node)
+{
+ CastModifierData *cmd = (CastModifierData *)md;
+ if (cmd->object != NULL) {
+ DEG_add_object_relation(node, cmd->object, DEG_OB_COMP_TRANSFORM, "Cast Modifier");
+ }
+}
+
static void sphere_do(
CastModifierData *cmd, Object *ob, DerivedMesh *dm,
float (*vertexCos)[3], int numVerts)
@@ -499,6 +512,7 @@ ModifierTypeInfo modifierType_Cast = {
/* freeData */ NULL,
/* isDisabled */ isDisabled,
/* updateDepgraph */ updateDepgraph,
+ /* updateDepsgraph */ updateDepsgraph,
/* dependsOnTime */ NULL,
/* dependsOnNormals */ NULL,
/* foreachObjectLink */ foreachObjectLink,
diff --git a/source/blender/modifiers/intern/MOD_cloth.c b/source/blender/modifiers/intern/MOD_cloth.c
index 1561fd1a981..dac0e516e0d 100644
--- a/source/blender/modifiers/intern/MOD_cloth.c
+++ b/source/blender/modifiers/intern/MOD_cloth.c
@@ -46,6 +46,7 @@
#include "BKE_cloth.h"
#include "BKE_cdderivedmesh.h"
+#include "BKE_effect.h"
#include "BKE_global.h"
#include "BKE_key.h"
#include "BKE_modifier.h"
@@ -97,7 +98,7 @@ static void deformVerts(ModifierData *md, Object *ob, DerivedMesh *derivedData,
if (derivedData == NULL && clmd->sim_parms->shapekey_rest) {
KeyBlock *kb = BKE_keyblock_from_key(BKE_key_from_object(ob),
clmd->sim_parms->shapekey_rest);
- if (kb->data != NULL) {
+ if (kb && kb->data != NULL) {
float (*layerorco)[3];
if (!(layerorco = DM_get_vert_data_layer(dm, CD_CLOTH_ORCO))) {
DM_add_vert_layer(dm, CD_CLOTH_ORCO, CD_CALLOC, NULL);
@@ -110,14 +111,14 @@ static void deformVerts(ModifierData *md, Object *ob, DerivedMesh *derivedData,
CDDM_apply_vert_coords(dm, vertexCos);
- DM_ensure_tessface(dm); /* BMESH - UNTIL MODIFIER IS UPDATED FOR MPoly */
-
clothModifier_do(clmd, md->scene, ob, dm, vertexCos);
dm->release(dm);
}
-static void updateDepgraph(ModifierData *md, DagForest *forest, Scene *scene, Object *ob, DagNode *obNode)
+static void updateDepgraph(ModifierData *md, DagForest *forest,
+ struct Main *UNUSED(bmain),
+ Scene *scene, Object *ob, DagNode *obNode)
{
ClothModifierData *clmd = (ClothModifierData *) md;
@@ -137,6 +138,27 @@ static void updateDepgraph(ModifierData *md, DagForest *forest, Scene *scene, Ob
}
}
+static void updateDepsgraph(ModifierData *md,
+ struct Main *UNUSED(bmain),
+ struct Scene *scene,
+ Object *ob,
+ struct DepsNodeHandle *node)
+{
+ ClothModifierData *clmd = (ClothModifierData *)md;
+ if (clmd != NULL) {
+ Base *base;
+ for (base = scene->base.first; base; base = base->next) {
+ Object *ob1 = base->object;
+ if (ob1 != ob) {
+ CollisionModifierData *coll_clmd = (CollisionModifierData *)modifiers_findByType(ob1, eModifierType_Collision);
+ if (coll_clmd) {
+ DEG_add_object_relation(node, ob1, DEG_OB_COMP_TRANSFORM, "Cloth Modifier");
+ }
+ }
+ }
+ }
+}
+
static CustomDataMask requiredDataMask(Object *UNUSED(ob), ModifierData *md)
{
CustomDataMask dataMask = 0;
@@ -175,6 +197,8 @@ static void copyData(ModifierData *md, ModifierData *target)
tclmd->point_cache = BKE_ptcache_add(&tclmd->ptcaches);
tclmd->point_cache->step = 1;
tclmd->clothObject = NULL;
+ tclmd->hairdata = NULL;
+ tclmd->solver_result = NULL;
}
static bool dependsOnTime(ModifierData *UNUSED(md))
@@ -202,6 +226,12 @@ static void freeData(ModifierData *md)
BKE_ptcache_free_list(&clmd->ptcaches);
clmd->point_cache = NULL;
+
+ if (clmd->hairdata)
+ MEM_freeN(clmd->hairdata);
+
+ if (clmd->solver_result)
+ MEM_freeN(clmd->solver_result);
}
}
@@ -240,6 +270,7 @@ ModifierTypeInfo modifierType_Cloth = {
/* freeData */ freeData,
/* isDisabled */ NULL,
/* updateDepgraph */ updateDepgraph,
+ /* updateDepsgraph */ updateDepsgraph,
/* dependsOnTime */ dependsOnTime,
/* dependsOnNormals */ NULL,
/* foreachObjectLink */ NULL,
diff --git a/source/blender/modifiers/intern/MOD_collision.c b/source/blender/modifiers/intern/MOD_collision.c
index 8f6c533ae4c..bebfbbe9a80 100644
--- a/source/blender/modifiers/intern/MOD_collision.c
+++ b/source/blender/modifiers/intern/MOD_collision.c
@@ -32,7 +32,6 @@
* \ingroup modifiers
*/
-
#include "DNA_object_types.h"
#include "DNA_meshdata_types.h"
@@ -49,8 +48,6 @@
#include "BKE_pointcache.h"
#include "BKE_scene.h"
-#include "MOD_util.h"
-
static void initData(ModifierData *md)
{
CollisionModifierData *collmd = (CollisionModifierData *) md;
@@ -61,7 +58,8 @@ static void initData(ModifierData *md)
collmd->current_xnew = NULL;
collmd->current_v = NULL;
collmd->time_x = collmd->time_xnew = -1000;
- collmd->numverts = 0;
+ collmd->mvert_num = 0;
+ collmd->tri_num = 0;
collmd->bvhtree = NULL;
}
@@ -70,30 +68,25 @@ static void freeData(ModifierData *md)
CollisionModifierData *collmd = (CollisionModifierData *) md;
if (collmd) {
- if (collmd->bvhtree)
+ if (collmd->bvhtree) {
BLI_bvhtree_free(collmd->bvhtree);
- if (collmd->x)
- MEM_freeN(collmd->x);
- if (collmd->xnew)
- MEM_freeN(collmd->xnew);
- if (collmd->current_x)
- MEM_freeN(collmd->current_x);
- if (collmd->current_xnew)
- MEM_freeN(collmd->current_xnew);
- if (collmd->current_v)
- MEM_freeN(collmd->current_v);
- if (collmd->mfaces)
- MEM_freeN(collmd->mfaces);
-
- collmd->x = NULL;
- collmd->xnew = NULL;
- collmd->current_x = NULL;
- collmd->current_xnew = NULL;
- collmd->current_v = NULL;
+ collmd->bvhtree = NULL;
+ }
+
+ MEM_SAFE_FREE(collmd->x);
+ MEM_SAFE_FREE(collmd->xnew);
+ MEM_SAFE_FREE(collmd->current_x);
+ MEM_SAFE_FREE(collmd->current_xnew);
+ MEM_SAFE_FREE(collmd->current_v);
+
+ if (collmd->tri) {
+ MEM_freeN((void *)collmd->tri);
+ collmd->tri = NULL;
+ }
+
collmd->time_x = collmd->time_xnew = -1000;
- collmd->numverts = 0;
- collmd->bvhtree = NULL;
- collmd->mfaces = NULL;
+ collmd->mvert_num = 0;
+ collmd->tri_num = 0;
}
}
@@ -123,7 +116,7 @@ static void deformVerts(ModifierData *md, Object *ob,
if (dm) {
float current_time = 0;
- unsigned int numverts = 0;
+ unsigned int mvert_num = 0;
CDDM_apply_vert_coords(dm, vertexCos);
CDDM_calc_normals(dm);
@@ -133,19 +126,20 @@ static void deformVerts(ModifierData *md, Object *ob,
if (G.debug_value > 0)
printf("current_time %f, collmd->time_xnew %f\n", current_time, collmd->time_xnew);
- numverts = dm->getNumVerts(dm);
+ mvert_num = dm->getNumVerts(dm);
if (current_time > collmd->time_xnew) {
unsigned int i;
/* check if mesh has changed */
- if (collmd->x && (numverts != collmd->numverts))
+ if (collmd->x && (mvert_num != collmd->mvert_num))
freeData((ModifierData *)collmd);
if (collmd->time_xnew == -1000) { /* first time */
+
collmd->x = dm->dupVertArray(dm); /* frame start position */
- for (i = 0; i < numverts; i++) {
+ for (i = 0; i < mvert_num; i++) {
/* we save global positions */
mul_m4_v3(ob->obmat, collmd->x[i].co);
}
@@ -155,56 +149,75 @@ static void deformVerts(ModifierData *md, Object *ob,
collmd->current_xnew = MEM_dupallocN(collmd->x); // inter-frame
collmd->current_v = MEM_dupallocN(collmd->x); // inter-frame
- collmd->numverts = numverts;
+ collmd->mvert_num = mvert_num;
- DM_ensure_tessface(dm); /* BMESH - UNTIL MODIFIER IS UPDATED FOR MPoly */
+ DM_ensure_looptri(dm);
+
+ collmd->tri_num = dm->getNumLoopTri(dm);
+ {
+ const MLoop *mloop = dm->getLoopArray(dm);
+ const MLoopTri *looptri = dm->getLoopTriArray(dm);
+ MVertTri *tri = MEM_mallocN(sizeof(*tri) * collmd->tri_num, __func__);
+ DM_verttri_from_looptri(tri, mloop, looptri, collmd->tri_num);
+ collmd->tri = tri;
+ }
- collmd->mfaces = dm->dupTessFaceArray(dm);
- collmd->numfaces = dm->getNumTessFaces(dm);
-
/* create bounding box hierarchy */
- collmd->bvhtree = bvhtree_build_from_mvert(collmd->mfaces, collmd->numfaces, collmd->x, numverts, ob->pd->pdef_sboft);
+ collmd->bvhtree = bvhtree_build_from_mvert(
+ collmd->x,
+ collmd->tri, collmd->tri_num,
+ ob->pd->pdef_sboft);
collmd->time_x = collmd->time_xnew = current_time;
}
- else if (numverts == collmd->numverts) {
+ else if (mvert_num == collmd->mvert_num) {
/* put positions to old positions */
tempVert = collmd->x;
collmd->x = collmd->xnew;
collmd->xnew = tempVert;
collmd->time_x = collmd->time_xnew;
- memcpy(collmd->xnew, dm->getVertArray(dm), numverts * sizeof(MVert));
+ memcpy(collmd->xnew, dm->getVertArray(dm), mvert_num * sizeof(MVert));
- for (i = 0; i < numverts; i++) {
+ for (i = 0; i < mvert_num; i++) {
/* we save global positions */
mul_m4_v3(ob->obmat, collmd->xnew[i].co);
}
- memcpy(collmd->current_xnew, collmd->x, numverts * sizeof(MVert));
- memcpy(collmd->current_x, collmd->x, numverts * sizeof(MVert));
+ memcpy(collmd->current_xnew, collmd->x, mvert_num * sizeof(MVert));
+ memcpy(collmd->current_x, collmd->x, mvert_num * sizeof(MVert));
/* check if GUI setting has changed for bvh */
if (collmd->bvhtree) {
if (ob->pd->pdef_sboft != BLI_bvhtree_getepsilon(collmd->bvhtree)) {
BLI_bvhtree_free(collmd->bvhtree);
- collmd->bvhtree = bvhtree_build_from_mvert(collmd->mfaces, collmd->numfaces, collmd->current_x, numverts, ob->pd->pdef_sboft);
+ collmd->bvhtree = bvhtree_build_from_mvert(
+ collmd->current_x,
+ collmd->tri, collmd->tri_num,
+ ob->pd->pdef_sboft);
}
}
/* happens on file load (ONLY when i decomment changes in readfile.c) */
if (!collmd->bvhtree) {
- collmd->bvhtree = bvhtree_build_from_mvert(collmd->mfaces, collmd->numfaces, collmd->current_x, numverts, ob->pd->pdef_sboft);
+ collmd->bvhtree = bvhtree_build_from_mvert(
+ collmd->current_x,
+ collmd->tri, collmd->tri_num,
+ ob->pd->pdef_sboft);
}
else {
/* recalc static bounding boxes */
- bvhtree_update_from_mvert(collmd->bvhtree, collmd->mfaces, collmd->numfaces, collmd->current_x, collmd->current_xnew, collmd->numverts, 1);
+ bvhtree_update_from_mvert(
+ collmd->bvhtree,
+ collmd->current_x, collmd->current_xnew,
+ collmd->tri, collmd->tri_num,
+ true);
}
collmd->time_xnew = current_time;
}
- else if (numverts != collmd->numverts) {
+ else if (mvert_num != collmd->mvert_num) {
freeData((ModifierData *)collmd);
}
@@ -213,7 +226,7 @@ static void deformVerts(ModifierData *md, Object *ob,
freeData((ModifierData *)collmd);
}
else {
- if (numverts != collmd->numverts) {
+ if (mvert_num != collmd->mvert_num) {
freeData((ModifierData *)collmd);
}
}
@@ -244,6 +257,7 @@ ModifierTypeInfo modifierType_Collision = {
/* freeData */ freeData,
/* isDisabled */ NULL,
/* updateDepgraph */ NULL,
+ /* updateDepsgraph */ NULL,
/* dependsOnTime */ dependsOnTime,
/* dependsOnNormals */ NULL,
/* foreachObjectLink */ NULL,
diff --git a/source/blender/modifiers/intern/MOD_correctivesmooth.c b/source/blender/modifiers/intern/MOD_correctivesmooth.c
new file mode 100644
index 00000000000..d5b4daca3b7
--- /dev/null
+++ b/source/blender/modifiers/intern/MOD_correctivesmooth.c
@@ -0,0 +1,769 @@
+/*
+* ***** 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) 2015 by the Blender Foundation.
+* All rights reserved.
+*
+* Contributor(s): Jack Simpson,
+* Campbell Barton
+*
+* ***** END GPL LICENSE BLOCK *****
+*
+*/
+
+/** \file blender/modifiers/intern/MOD_correctivesmooth.c
+ * \ingroup modifiers
+ *
+ * Method of smoothing deformation, also known as 'delta-mush'.
+ */
+
+#include "DNA_scene_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_object_types.h"
+#include "DNA_mesh_types.h"
+
+#include "BLI_math.h"
+#include "BLI_utildefines.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "BKE_cdderivedmesh.h"
+#include "BKE_deform.h"
+#include "BKE_mesh.h"
+#include "BKE_editmesh.h"
+
+#include "MOD_modifiertypes.h"
+#include "MOD_util.h"
+
+#include "BLI_strict_flags.h"
+
+
+// #define DEBUG_TIME
+
+#include "PIL_time.h"
+#ifdef DEBUG_TIME
+# include "PIL_time_utildefines.h"
+#endif
+
+/* minor optimization, calculate this inline */
+#define USE_TANGENT_CALC_INLINE
+
+static void initData(ModifierData *md)
+{
+ CorrectiveSmoothModifierData *csmd = (CorrectiveSmoothModifierData *)md;
+
+ csmd->bind_coords = NULL;
+ csmd->bind_coords_num = 0;
+
+ csmd->lambda = 0.5f;
+ csmd->repeat = 5;
+ csmd->flag = 0;
+ csmd->smooth_type = MOD_CORRECTIVESMOOTH_SMOOTH_SIMPLE;
+
+ csmd->defgrp_name[0] = '\0';
+
+ csmd->delta_cache = NULL;
+}
+
+
+static void copyData(ModifierData *md, ModifierData *target)
+{
+ CorrectiveSmoothModifierData *csmd = (CorrectiveSmoothModifierData *)md;
+ CorrectiveSmoothModifierData *tcsmd = (CorrectiveSmoothModifierData *)target;
+
+ modifier_copyData_generic(md, target);
+
+ if (csmd->bind_coords) {
+ tcsmd->bind_coords = MEM_dupallocN(csmd->bind_coords);
+ }
+
+ tcsmd->delta_cache = NULL;
+ tcsmd->delta_cache_num = 0;
+}
+
+
+static void freeBind(CorrectiveSmoothModifierData *csmd)
+{
+ MEM_SAFE_FREE(csmd->bind_coords);
+ MEM_SAFE_FREE(csmd->delta_cache);
+
+ csmd->bind_coords_num = 0;
+}
+
+
+static void freeData(ModifierData *md)
+{
+ CorrectiveSmoothModifierData *csmd = (CorrectiveSmoothModifierData *)md;
+ freeBind(csmd);
+}
+
+
+static CustomDataMask requiredDataMask(Object *UNUSED(ob), ModifierData *md)
+{
+ CorrectiveSmoothModifierData *csmd = (CorrectiveSmoothModifierData *)md;
+ CustomDataMask dataMask = 0;
+ /* ask for vertex groups if we need them */
+ if (csmd->defgrp_name[0]) {
+ dataMask |= CD_MASK_MDEFORMVERT;
+ }
+ return dataMask;
+}
+
+
+/* check individual weights for changes and cache values */
+static void dm_get_weights(
+ MDeformVert *dvert, const int defgrp_index,
+ const unsigned int numVerts, const bool use_invert_vgroup,
+ float *smooth_weights)
+{
+ unsigned int i;
+
+ for (i = 0; i < numVerts; i++, dvert++) {
+ const float w = defvert_find_weight(dvert, defgrp_index);
+
+ if (use_invert_vgroup == false) {
+ smooth_weights[i] = w;
+ }
+ else {
+ smooth_weights[i] = 1.0f - w;
+ }
+ }
+}
+
+
+static void dm_get_boundaries(DerivedMesh *dm, float *smooth_weights)
+{
+ const MPoly *mpoly = dm->getPolyArray(dm);
+ const MLoop *mloop = dm->getLoopArray(dm);
+ const MEdge *medge = dm->getEdgeArray(dm);
+ unsigned int mpoly_num, medge_num, i;
+ unsigned short *boundaries;
+
+ mpoly_num = (unsigned int)dm->getNumPolys(dm);
+ medge_num = (unsigned int)dm->getNumEdges(dm);
+
+ boundaries = MEM_callocN(medge_num * sizeof(*boundaries), __func__);
+
+ /* count the number of adjacent faces */
+ for (i = 0; i < mpoly_num; i++) {
+ const MPoly *p = &mpoly[i];
+ const int totloop = p->totloop;
+ int j;
+ for (j = 0; j < totloop; j++) {
+ boundaries[mloop[p->loopstart + j].e]++;
+ }
+ }
+
+ for (i = 0; i < medge_num; i++) {
+ if (boundaries[i] == 1) {
+ smooth_weights[medge[i].v1] = 0.0f;
+ smooth_weights[medge[i].v2] = 0.0f;
+ }
+ }
+
+ MEM_freeN(boundaries);
+}
+
+
+/* -------------------------------------------------------------------- */
+/* Simple Weighted Smoothing
+ *
+ * (average of surrounding verts)
+ */
+static void smooth_iter__simple(
+ CorrectiveSmoothModifierData *csmd, DerivedMesh *dm,
+ float (*vertexCos)[3], unsigned int numVerts,
+ const float *smooth_weights,
+ unsigned int iterations)
+{
+ const float lambda = csmd->lambda;
+ unsigned int i;
+
+ const unsigned int numEdges = (unsigned int)dm->getNumEdges(dm);
+ const MEdge *edges = dm->getEdgeArray(dm);
+ float *vertex_edge_count_div;
+
+ struct SmoothingData_Simple {
+ float delta[3];
+ } *smooth_data = MEM_callocN((size_t)numVerts * sizeof(*smooth_data), __func__);
+
+ vertex_edge_count_div = MEM_callocN((size_t)numVerts * sizeof(float), __func__);
+
+ /* calculate as floats to avoid int->float conversion in #smooth_iter */
+ for (i = 0; i < numEdges; i++) {
+ vertex_edge_count_div[edges[i].v1] += 1.0f;
+ vertex_edge_count_div[edges[i].v2] += 1.0f;
+ }
+
+ /* a little confusing, but we can include 'lambda' and smoothing weight
+ * here to avoid multiplying for every iteration */
+ if (smooth_weights == NULL) {
+ for (i = 0; i < numVerts; i++) {
+ vertex_edge_count_div[i] =
+ lambda * (vertex_edge_count_div[i] ? (1.0f / vertex_edge_count_div[i]) : 1.0f);
+ }
+ }
+ else {
+ for (i = 0; i < numVerts; i++) {
+ vertex_edge_count_div[i] =
+ smooth_weights[i] * lambda * (vertex_edge_count_div[i] ? (1.0f / vertex_edge_count_div[i]) : 1.0f);
+ }
+ }
+
+ /* -------------------------------------------------------------------- */
+ /* Main Smoothing Loop */
+
+ while (iterations--) {
+ for (i = 0; i < numEdges; i++) {
+ struct SmoothingData_Simple *sd_v1;
+ struct SmoothingData_Simple *sd_v2;
+ float edge_dir[3];
+
+ sub_v3_v3v3(edge_dir, vertexCos[edges[i].v2], vertexCos[edges[i].v1]);
+
+ sd_v1 = &smooth_data[edges[i].v1];
+ sd_v2 = &smooth_data[edges[i].v2];
+
+ add_v3_v3(sd_v1->delta, edge_dir);
+ sub_v3_v3(sd_v2->delta, edge_dir);
+ }
+
+
+ for (i = 0; i < numVerts; i++) {
+ struct SmoothingData_Simple *sd = &smooth_data[i];
+ madd_v3_v3fl(vertexCos[i], sd->delta, vertex_edge_count_div[i]);
+ /* zero for the next iteration (saves memset on entire array) */
+ memset(sd, 0, sizeof(*sd));
+ }
+ }
+
+ MEM_freeN(vertex_edge_count_div);
+ MEM_freeN(smooth_data);
+}
+
+
+/* -------------------------------------------------------------------- */
+/* Edge-Length Weighted Smoothing
+ */
+static void smooth_iter__length_weight(
+ CorrectiveSmoothModifierData *csmd, DerivedMesh *dm,
+ float (*vertexCos)[3], unsigned int numVerts,
+ const float *smooth_weights,
+ unsigned int iterations)
+{
+ const float eps = FLT_EPSILON * 10.0f;
+ const unsigned int numEdges = (unsigned int)dm->getNumEdges(dm);
+ /* note: the way this smoothing method works, its approx half as strong as the simple-smooth,
+ * and 2.0 rarely spikes, double the value for consistent behavior. */
+ const float lambda = csmd->lambda * 2.0f;
+ const MEdge *edges = dm->getEdgeArray(dm);
+ float *vertex_edge_count;
+ unsigned int i;
+
+ struct SmoothingData_Weighted {
+ float delta[3];
+ float edge_length_sum;
+ } *smooth_data = MEM_callocN((size_t)numVerts * sizeof(*smooth_data), __func__);
+
+
+ /* calculate as floats to avoid int->float conversion in #smooth_iter */
+ vertex_edge_count = MEM_callocN((size_t)numVerts * sizeof(float), __func__);
+ for (i = 0; i < numEdges; i++) {
+ vertex_edge_count[edges[i].v1] += 1.0f;
+ vertex_edge_count[edges[i].v2] += 1.0f;
+ }
+
+
+ /* -------------------------------------------------------------------- */
+ /* Main Smoothing Loop */
+
+ while (iterations--) {
+ for (i = 0; i < numEdges; i++) {
+ struct SmoothingData_Weighted *sd_v1;
+ struct SmoothingData_Weighted *sd_v2;
+ float edge_dir[3];
+ float edge_dist;
+
+ sub_v3_v3v3(edge_dir, vertexCos[edges[i].v2], vertexCos[edges[i].v1]);
+ edge_dist = len_v3(edge_dir);
+
+ /* weight by distance */
+ mul_v3_fl(edge_dir, edge_dist);
+
+
+ sd_v1 = &smooth_data[edges[i].v1];
+ sd_v2 = &smooth_data[edges[i].v2];
+
+ add_v3_v3(sd_v1->delta, edge_dir);
+ sub_v3_v3(sd_v2->delta, edge_dir);
+
+ sd_v1->edge_length_sum += edge_dist;
+ sd_v2->edge_length_sum += edge_dist;
+ }
+
+ if (smooth_weights == NULL) {
+ /* fast-path */
+ for (i = 0; i < numVerts; i++) {
+ struct SmoothingData_Weighted *sd = &smooth_data[i];
+ /* divide by sum of all neighbour distances (weighted) and amount of neighbours, (mean average) */
+ const float div = sd->edge_length_sum * vertex_edge_count[i];
+ if (div > eps) {
+#if 0
+ /* first calculate the new location */
+ mul_v3_fl(sd->delta, 1.0f / div);
+ /* then interpolate */
+ madd_v3_v3fl(vertexCos[i], sd->delta, lambda);
+#else
+ /* do this in one step */
+ madd_v3_v3fl(vertexCos[i], sd->delta, lambda / div);
+#endif
+ }
+ /* zero for the next iteration (saves memset on entire array) */
+ memset(sd, 0, sizeof(*sd));
+ }
+ }
+ else {
+ for (i = 0; i < numVerts; i++) {
+ struct SmoothingData_Weighted *sd = &smooth_data[i];
+ const float div = sd->edge_length_sum * vertex_edge_count[i];
+ if (div > eps) {
+ const float lambda_w = lambda * smooth_weights[i];
+ madd_v3_v3fl(vertexCos[i], sd->delta, lambda_w / div);
+ }
+
+ memset(sd, 0, sizeof(*sd));
+ }
+ }
+ }
+
+ MEM_freeN(vertex_edge_count);
+ MEM_freeN(smooth_data);
+}
+
+
+static void smooth_iter(
+ CorrectiveSmoothModifierData *csmd, DerivedMesh *dm,
+ float (*vertexCos)[3], unsigned int numVerts,
+ const float *smooth_weights,
+ unsigned int iterations)
+{
+ switch (csmd->smooth_type) {
+ case MOD_CORRECTIVESMOOTH_SMOOTH_LENGTH_WEIGHT:
+ smooth_iter__length_weight(csmd, dm, vertexCos, numVerts, smooth_weights, iterations);
+ break;
+
+ /* case MOD_CORRECTIVESMOOTH_SMOOTH_SIMPLE: */
+ default:
+ smooth_iter__simple(csmd, dm, vertexCos, numVerts, smooth_weights, iterations);
+ break;
+ }
+}
+
+static void smooth_verts(
+ CorrectiveSmoothModifierData *csmd, DerivedMesh *dm,
+ MDeformVert *dvert, const int defgrp_index,
+ float (*vertexCos)[3], unsigned int numVerts)
+{
+ float *smooth_weights = NULL;
+
+ if (dvert || (csmd->flag & MOD_CORRECTIVESMOOTH_PIN_BOUNDARY)) {
+
+ smooth_weights = MEM_mallocN(numVerts * sizeof(float), __func__);
+
+ if (dvert) {
+ dm_get_weights(
+ dvert, defgrp_index,
+ numVerts, (csmd->flag & MOD_CORRECTIVESMOOTH_INVERT_VGROUP) != 0,
+ smooth_weights);
+ }
+ else {
+ copy_vn_fl(smooth_weights, (int)numVerts, 1.0f);
+ }
+
+ if (csmd->flag & MOD_CORRECTIVESMOOTH_PIN_BOUNDARY) {
+ dm_get_boundaries(dm, smooth_weights);
+ }
+ }
+
+ smooth_iter(csmd, dm, vertexCos, numVerts, smooth_weights, (unsigned int)csmd->repeat);
+
+ if (smooth_weights) {
+ MEM_freeN(smooth_weights);
+ }
+}
+
+/**
+ * finalize after accumulation.
+ */
+static void calc_tangent_ortho(float ts[3][3])
+{
+ float v_tan_a[3], v_tan_b[3];
+ float t_vec_a[3], t_vec_b[3];
+
+ normalize_v3(ts[2]);
+
+ copy_v3_v3(v_tan_a, ts[0]);
+ copy_v3_v3(v_tan_b, ts[1]);
+
+ cross_v3_v3v3(ts[1], ts[2], v_tan_a);
+ mul_v3_fl(ts[1], dot_v3v3(ts[1], v_tan_b) < 0.0f ? -1.0f : 1.0f);
+
+ /* orthognalise tangent */
+ mul_v3_v3fl(t_vec_a, ts[2], dot_v3v3(ts[2], v_tan_a));
+ sub_v3_v3v3(ts[0], v_tan_a, t_vec_a);
+
+ /* orthognalise bitangent */
+ mul_v3_v3fl(t_vec_a, ts[2], dot_v3v3(ts[2], ts[1]));
+ mul_v3_v3fl(t_vec_b, ts[0], dot_v3v3(ts[0], ts[1]) / dot_v3v3(v_tan_a, v_tan_a));
+ sub_v3_v3(ts[1], t_vec_a);
+ sub_v3_v3(ts[1], t_vec_b);
+
+ normalize_v3(ts[0]);
+ normalize_v3(ts[1]);
+}
+
+/**
+ * accumulate edge-vectors from all polys.
+ */
+static void calc_tangent_loop_accum(
+ const float v_dir_prev[3],
+ const float v_dir_next[3],
+ float r_tspace[3][3])
+{
+ add_v3_v3v3(r_tspace[1], v_dir_prev, v_dir_next);
+
+ if (compare_v3v3(v_dir_prev, v_dir_next, FLT_EPSILON * 10.0f) == false) {
+ const float weight = fabsf(acosf(dot_v3v3(v_dir_next, v_dir_prev)));
+ float nor[3];
+
+ cross_v3_v3v3(nor, v_dir_prev, v_dir_next);
+ normalize_v3(nor);
+
+ cross_v3_v3v3(r_tspace[0], r_tspace[1], nor);
+
+ mul_v3_fl(nor, weight);
+ /* accumulate weighted normals */
+ add_v3_v3(r_tspace[2], nor);
+ }
+}
+
+
+static void calc_tangent_spaces(
+ DerivedMesh *dm, float (*vertexCos)[3],
+ float (*r_tangent_spaces)[3][3])
+{
+ const unsigned int mpoly_num = (unsigned int)dm->getNumPolys(dm);
+#ifndef USE_TANGENT_CALC_INLINE
+ const unsigned int mvert_num = (unsigned int)dm->getNumVerts(dm);
+#endif
+ const MPoly *mpoly = dm->getPolyArray(dm);
+ const MLoop *mloop = dm->getLoopArray(dm);
+ unsigned int i;
+
+ for (i = 0; i < mpoly_num; i++) {
+ const MPoly *mp = &mpoly[i];
+ const MLoop *l_next = &mloop[mp->loopstart];
+ const MLoop *l_term = l_next + mp->totloop;
+ const MLoop *l_prev = l_term - 2;
+ const MLoop *l_curr = l_term - 1;
+
+ /* loop directions */
+ float v_dir_prev[3], v_dir_next[3];
+
+ /* needed entering the loop */
+ sub_v3_v3v3(v_dir_prev, vertexCos[l_prev->v], vertexCos[l_curr->v]);
+ normalize_v3(v_dir_prev);
+
+ for (;
+ l_next != l_term;
+ l_prev = l_curr, l_curr = l_next, l_next++)
+ {
+ float (*ts)[3] = r_tangent_spaces[l_curr->v];
+
+ /* re-use the previous value */
+#if 0
+ sub_v3_v3v3(v_dir_prev, vertexCos[l_prev->v], vertexCos[l_curr->v]);
+ normalize_v3(v_dir_prev);
+#endif
+ sub_v3_v3v3(v_dir_next, vertexCos[l_curr->v], vertexCos[l_next->v]);
+ normalize_v3(v_dir_next);
+
+ calc_tangent_loop_accum(v_dir_prev, v_dir_next, ts);
+
+ copy_v3_v3(v_dir_prev, v_dir_next);
+ }
+ }
+
+ /* do inline */
+#ifndef USE_TANGENT_CALC_INLINE
+ for (i = 0; i < mvert_num; i++) {
+ float (*ts)[3] = r_tangent_spaces[i];
+ calc_tangent_ortho(ts);
+ }
+#endif
+}
+
+/**
+ * This calculates #CorrectiveSmoothModifierData.delta_cache
+ * It's not run on every update (during animation for example).
+ */
+static void calc_deltas(
+ CorrectiveSmoothModifierData *csmd, DerivedMesh *dm,
+ MDeformVert *dvert, const int defgrp_index,
+ const float (*rest_coords)[3], unsigned int numVerts)
+{
+ float (*smooth_vertex_coords)[3] = MEM_dupallocN(rest_coords);
+ float (*tangent_spaces)[3][3];
+ unsigned int i;
+
+ tangent_spaces = MEM_callocN((size_t)(numVerts) * sizeof(float[3][3]), __func__);
+
+ if (csmd->delta_cache_num != numVerts) {
+ MEM_SAFE_FREE(csmd->delta_cache);
+ }
+
+ /* allocate deltas if they have not yet been allocated, otheriwse we will just write over them */
+ if (!csmd->delta_cache) {
+ csmd->delta_cache_num = numVerts;
+ csmd->delta_cache = MEM_mallocN((size_t)numVerts * sizeof(float[3]), __func__);
+ }
+
+ smooth_verts(csmd, dm, dvert, defgrp_index, smooth_vertex_coords, numVerts);
+
+ calc_tangent_spaces(dm, smooth_vertex_coords, tangent_spaces);
+
+ for (i = 0; i < numVerts; i++) {
+ float imat[3][3], delta[3];
+
+#ifdef USE_TANGENT_CALC_INLINE
+ calc_tangent_ortho(tangent_spaces[i]);
+#endif
+
+ sub_v3_v3v3(delta, rest_coords[i], smooth_vertex_coords[i]);
+ if (UNLIKELY(!invert_m3_m3(imat, tangent_spaces[i]))) {
+ transpose_m3_m3(imat, tangent_spaces[i]);
+ }
+ mul_v3_m3v3(csmd->delta_cache[i], imat, delta);
+ }
+
+ MEM_freeN(tangent_spaces);
+ MEM_freeN(smooth_vertex_coords);
+}
+
+
+static void correctivesmooth_modifier_do(
+ ModifierData *md, Object *ob, DerivedMesh *dm,
+ float (*vertexCos)[3], unsigned int numVerts,
+ struct BMEditMesh *em)
+{
+ CorrectiveSmoothModifierData *csmd = (CorrectiveSmoothModifierData *)md;
+
+ const bool force_delta_cache_update =
+ /* XXX, take care! if mesh data its self changes we need to forcefully recalculate deltas */
+ ((csmd->rest_source == MOD_CORRECTIVESMOOTH_RESTSOURCE_ORCO) &&
+ (((ID *)ob->data)->flag & LIB_ID_RECALC));
+
+ bool use_only_smooth = (csmd->flag & MOD_CORRECTIVESMOOTH_ONLY_SMOOTH) != 0;
+ MDeformVert *dvert = NULL;
+ int defgrp_index;
+
+ modifier_get_vgroup(ob, dm, csmd->defgrp_name, &dvert, &defgrp_index);
+
+ /* if rest bind_coords not are defined, set them (only run during bind) */
+ if ((csmd->rest_source == MOD_CORRECTIVESMOOTH_RESTSOURCE_BIND) &&
+ /* signal to recalculate, whoever sets MUST also free bind coords */
+ (csmd->bind_coords_num == (unsigned int)-1))
+ {
+ BLI_assert(csmd->bind_coords == NULL);
+ csmd->bind_coords = MEM_dupallocN(vertexCos);
+ csmd->bind_coords_num = numVerts;
+ BLI_assert(csmd->bind_coords != NULL);
+ }
+
+ if (UNLIKELY(use_only_smooth)) {
+ smooth_verts(csmd, dm, dvert, defgrp_index, vertexCos, numVerts);
+ return;
+ }
+
+ if ((csmd->rest_source == MOD_CORRECTIVESMOOTH_RESTSOURCE_BIND) && (csmd->bind_coords == NULL)) {
+ modifier_setError(md, "Bind data required");
+ goto error;
+ }
+
+ /* If the number of verts has changed, the bind is invalid, so we do nothing */
+ if (csmd->rest_source == MOD_CORRECTIVESMOOTH_RESTSOURCE_BIND) {
+ if (csmd->bind_coords_num != numVerts) {
+ modifier_setError(md, "Bind vertex count mismatch: %u to %u", csmd->bind_coords_num, numVerts);
+ goto error;
+ }
+ }
+ else {
+ /* MOD_CORRECTIVESMOOTH_RESTSOURCE_ORCO */
+ if (ob->type != OB_MESH) {
+ modifier_setError(md, "Object is not a mesh");
+ goto error;
+ }
+ else {
+ unsigned int me_numVerts = (unsigned int)((em) ? em->bm->totvert : ((Mesh *)ob->data)->totvert);
+
+ if (me_numVerts != numVerts) {
+ modifier_setError(md, "Original vertex count mismatch: %u to %u", me_numVerts, numVerts);
+ goto error;
+ }
+ }
+ }
+
+ /* check to see if our deltas are still valid */
+ if (!csmd->delta_cache || (csmd->delta_cache_num != numVerts) || force_delta_cache_update) {
+ const float (*rest_coords)[3];
+ bool is_rest_coords_alloc = false;
+
+ if (csmd->rest_source == MOD_CORRECTIVESMOOTH_RESTSOURCE_BIND) {
+ /* caller needs to do sanity check here */
+ csmd->bind_coords_num = numVerts;
+ rest_coords = (const float (*)[3])csmd->bind_coords;
+ }
+ else {
+ int me_numVerts;
+ rest_coords = (const float (*)[3]) ((em) ?
+ BKE_editmesh_vertexCos_get_orco(em, &me_numVerts) :
+ BKE_mesh_vertexCos_get(ob->data, &me_numVerts));
+
+ BLI_assert((unsigned int)me_numVerts == numVerts);
+ is_rest_coords_alloc = true;
+ }
+
+#ifdef DEBUG_TIME
+ TIMEIT_START(corrective_smooth_deltas);
+#endif
+
+ calc_deltas(csmd, dm, dvert, defgrp_index, rest_coords, numVerts);
+
+#ifdef DEBUG_TIME
+ TIMEIT_END(corrective_smooth_deltas);
+#endif
+ if (is_rest_coords_alloc) {
+ MEM_freeN((void *)rest_coords);
+ }
+ }
+
+ if (csmd->rest_source == MOD_CORRECTIVESMOOTH_RESTSOURCE_BIND) {
+ /* this could be a check, but at this point it _must_ be valid */
+ BLI_assert(csmd->bind_coords_num == numVerts && csmd->delta_cache);
+ }
+
+
+#ifdef DEBUG_TIME
+ TIMEIT_START(corrective_smooth);
+#endif
+
+ /* do the actual delta mush */
+ smooth_verts(csmd, dm, dvert, defgrp_index, vertexCos, numVerts);
+
+ {
+ unsigned int i;
+
+ float (*tangent_spaces)[3][3];
+
+ /* calloc, since values are accumulated */
+ tangent_spaces = MEM_callocN((size_t)numVerts * sizeof(float[3][3]), __func__);
+
+ calc_tangent_spaces(dm, vertexCos, tangent_spaces);
+
+ for (i = 0; i < numVerts; i++) {
+ float delta[3];
+
+#ifdef USE_TANGENT_CALC_INLINE
+ calc_tangent_ortho(tangent_spaces[i]);
+#endif
+
+ mul_v3_m3v3(delta, tangent_spaces[i], csmd->delta_cache[i]);
+ add_v3_v3(vertexCos[i], delta);
+ }
+
+ MEM_freeN(tangent_spaces);
+ }
+
+#ifdef DEBUG_TIME
+ TIMEIT_END(corrective_smooth);
+#endif
+
+ return;
+
+ /* when the modifier fails to execute */
+error:
+ MEM_SAFE_FREE(csmd->delta_cache);
+ csmd->delta_cache_num = 0;
+
+}
+
+
+static void deformVerts(
+ ModifierData *md, Object *ob, DerivedMesh *derivedData,
+ float (*vertexCos)[3], int numVerts, ModifierApplyFlag UNUSED(flag))
+{
+ DerivedMesh *dm = get_dm(ob, NULL, derivedData, NULL, false, false);
+
+ correctivesmooth_modifier_do(md, ob, dm, vertexCos, (unsigned int)numVerts, NULL);
+
+ if (dm != 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);
+
+ correctivesmooth_modifier_do(md, ob, dm, vertexCos, (unsigned int)numVerts, editData);
+
+ if (dm != derivedData) {
+ dm->release(dm);
+ }
+}
+
+
+ModifierTypeInfo modifierType_CorrectiveSmooth = {
+ /* name */ "CorrectiveSmooth",
+ /* structName */ "CorrectiveSmoothModifierData",
+ /* structSize */ sizeof(CorrectiveSmoothModifierData),
+ /* type */ eModifierTypeType_OnlyDeform,
+ /* flags */ eModifierTypeFlag_AcceptsMesh |
+ eModifierTypeFlag_SupportsEditmode,
+
+ /* copyData */ copyData,
+ /* deformVerts */ deformVerts,
+ /* deformMatrices */ NULL,
+ /* deformVertsEM */ deformVertsEM,
+ /* deformMatricesEM */ NULL,
+ /* applyModifier */ NULL,
+ /* applyModifierEM */ NULL,
+ /* initData */ initData,
+ /* requiredDataMask */ requiredDataMask,
+ /* freeData */ freeData,
+ /* isDisabled */ NULL,
+ /* updateDepgraph */ NULL,
+ /* updateDepsgraph */ NULL,
+ /* dependsOnTime */ NULL,
+ /* dependsOnNormals */ NULL,
+ /* foreachObjectLink */ NULL,
+ /* foreachIDLink */ NULL,
+ /* foreachTexLink */ NULL,
+};
diff --git a/source/blender/modifiers/intern/MOD_curve.c b/source/blender/modifiers/intern/MOD_curve.c
index fbc72cef0e8..1488296caf9 100644
--- a/source/blender/modifiers/intern/MOD_curve.c
+++ b/source/blender/modifiers/intern/MOD_curve.c
@@ -32,7 +32,6 @@
* \ingroup modifiers
*/
-
#include <string.h>
#include "DNA_scene_types.h"
@@ -46,8 +45,8 @@
#include "BKE_modifier.h"
#include "depsgraph_private.h"
+#include "DEG_depsgraph_build.h"
-#include "MOD_util.h"
static void initData(ModifierData *md)
{
@@ -94,6 +93,7 @@ static void foreachObjectLink(
}
static void updateDepgraph(ModifierData *md, DagForest *forest,
+ struct Main *UNUSED(bmain),
Scene *UNUSED(scene),
Object *UNUSED(ob),
DagNode *obNode)
@@ -109,6 +109,25 @@ static void updateDepgraph(ModifierData *md, DagForest *forest,
}
}
+static void updateDepsgraph(ModifierData *md,
+ struct Main *UNUSED(bmain),
+ struct Scene *scene,
+ Object *UNUSED(ob),
+ struct DepsNodeHandle *node)
+{
+ CurveModifierData *cmd = (CurveModifierData *)md;
+ if (cmd->object != NULL) {
+ /* TODO(sergey): Need to do the same eval_flags trick for path
+ * as happening in legacy depsgraph callback.
+ */
+ /* TODO(sergey): Currently path is evaluated as a part of modifier stack,
+ * might be changed in the future.
+ */
+ DEG_add_object_relation(node, cmd->object, DEG_OB_COMP_GEOMETRY, "Curve Modifier");
+ DEG_add_special_eval_flag(scene->depsgraph, &cmd->object->id, DAG_EVAL_NEED_CURVE_PATH);
+ }
+}
+
static void deformVerts(ModifierData *md, Object *ob,
DerivedMesh *derivedData,
float (*vertexCos)[3],
@@ -157,6 +176,7 @@ ModifierTypeInfo modifierType_Curve = {
/* freeData */ NULL,
/* isDisabled */ isDisabled,
/* updateDepgraph */ updateDepgraph,
+ /* updateDepsgraph */ updateDepsgraph,
/* dependsOnTime */ NULL,
/* dependsOnNormals */ NULL,
/* foreachObjectLink */ foreachObjectLink,
diff --git a/source/blender/modifiers/intern/MOD_datatransfer.c b/source/blender/modifiers/intern/MOD_datatransfer.c
new file mode 100644
index 00000000000..85e9b4ee185
--- /dev/null
+++ b/source/blender/modifiers/intern/MOD_datatransfer.c
@@ -0,0 +1,265 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2014 Blender Foundation.
+ * All rights reserved.
+ *
+ * Contributor(s): None yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ *
+ */
+
+/** \file blender/modifiers/intern/MOD_datatransfer.c
+ * \ingroup modifiers
+ */
+
+#include "BLI_utildefines.h"
+#include "BLI_math.h"
+
+#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_modifier_types.h"
+#include "DNA_object_types.h"
+
+#include "BKE_customdata.h"
+#include "BKE_cdderivedmesh.h"
+#include "BKE_data_transfer.h"
+#include "BKE_DerivedMesh.h"
+#include "BKE_library.h"
+#include "BKE_mesh_mapping.h"
+#include "BKE_mesh_remap.h"
+#include "BKE_modifier.h"
+#include "BKE_report.h"
+
+#include "MEM_guardedalloc.h"
+#include "MOD_util.h"
+
+#include "depsgraph_private.h"
+
+/**************************************
+ * Modifiers functions. *
+ **************************************/
+static void initData(ModifierData *md)
+{
+ DataTransferModifierData *dtmd = (DataTransferModifierData *) md;
+ int i;
+
+ dtmd->ob_source = NULL;
+ dtmd->data_types = 0;
+
+ dtmd->vmap_mode = MREMAP_MODE_VERT_NEAREST;
+ dtmd->emap_mode = MREMAP_MODE_EDGE_NEAREST;
+ dtmd->lmap_mode = MREMAP_MODE_LOOP_NEAREST_POLYNOR;
+ dtmd->pmap_mode = MREMAP_MODE_POLY_NEAREST;
+
+ dtmd->map_max_distance = 1.0f;
+ dtmd->map_ray_radius = 0.0f;
+
+ for (i = 0; i < DT_MULTILAYER_INDEX_MAX; i++) {
+ dtmd->layers_select_src[i] = DT_LAYERS_ALL_SRC;
+ dtmd->layers_select_dst[i] = DT_LAYERS_NAME_DST;
+ }
+
+ dtmd->mix_mode = CDT_MIX_TRANSFER;
+ dtmd->mix_factor = 1.0f;
+ dtmd->defgrp_name[0] = '\0';
+
+ dtmd->flags = MOD_DATATRANSFER_OBSRC_TRANSFORM;
+}
+
+static CustomDataMask requiredDataMask(Object *UNUSED(ob), ModifierData *md)
+{
+ DataTransferModifierData *dtmd = (DataTransferModifierData *) md;
+ CustomDataMask dataMask = 0;
+
+ if (dtmd->defgrp_name[0]) {
+ /* We need vertex groups! */
+ dataMask |= CD_MASK_MDEFORMVERT;
+ }
+
+ dataMask |= BKE_object_data_transfer_dttypes_to_cdmask(dtmd->data_types);
+
+ return dataMask;
+}
+
+static bool dependsOnNormals(ModifierData *md)
+{
+ DataTransferModifierData *dtmd = (DataTransferModifierData *) md;
+ int item_types = BKE_object_data_transfer_get_dttypes_item_types(dtmd->data_types);
+
+ if ((item_types & ME_VERT) && (dtmd->vmap_mode & (MREMAP_USE_NORPROJ | MREMAP_USE_NORMAL))) {
+ return true;
+ }
+ if ((item_types & ME_EDGE) && (dtmd->emap_mode & (MREMAP_USE_NORPROJ | MREMAP_USE_NORMAL))) {
+ return true;
+ }
+ if ((item_types & ME_LOOP) && (dtmd->lmap_mode & (MREMAP_USE_NORPROJ | MREMAP_USE_NORMAL))) {
+ return true;
+ }
+ if ((item_types & ME_POLY) && (dtmd->pmap_mode & (MREMAP_USE_NORPROJ | MREMAP_USE_NORMAL))) {
+ return true;
+ }
+
+ return false;
+}
+
+static void foreachObjectLink(ModifierData *md, Object *ob,
+ void (*walk)(void *userData, Object *ob, Object **obpoin),
+ void *userData)
+{
+ DataTransferModifierData *dtmd = (DataTransferModifierData *) md;
+ walk(userData, ob, &dtmd->ob_source);
+}
+
+static void foreachIDLink(ModifierData *md, Object *ob, IDWalkFunc walk, void *userData)
+{
+ foreachObjectLink(md, ob, (ObjectWalkFunc)walk, userData);
+}
+
+static void updateDepgraph(ModifierData *md, DagForest *forest,
+ struct Main *UNUSED(bmain),
+ struct Scene *UNUSED(scene),
+ Object *UNUSED(ob), DagNode *obNode)
+{
+ DataTransferModifierData *dtmd = (DataTransferModifierData *) md;
+ DagNode *curNode;
+
+ if (dtmd->ob_source) {
+ curNode = dag_get_node(forest, dtmd->ob_source);
+
+ dag_add_relation(forest, curNode, obNode, DAG_RL_DATA_DATA | DAG_RL_OB_DATA,
+ "DataTransfer Modifier");
+ }
+}
+
+static void updateDepsgraph(ModifierData *md,
+ struct Main *UNUSED(bmain),
+ struct Scene *UNUSED(scene),
+ Object *UNUSED(ob),
+ struct DepsNodeHandle *node)
+{
+ DataTransferModifierData *dtmd = (DataTransferModifierData *) md;
+ if (dtmd->ob_source != NULL) {
+ DEG_add_object_relation(node, dtmd->ob_source, DEG_OB_COMP_GEOMETRY, "DataTransfer Modifier");
+ }
+}
+
+static bool isDisabled(ModifierData *md, int UNUSED(useRenderParams))
+{
+ DataTransferModifierData *dtmd = (DataTransferModifierData *) md;
+ /* If no source object, bypass. */
+ return (dtmd->ob_source == NULL);
+}
+
+#define HIGH_POLY_WARNING 10000
+#define DT_TYPES_AFFECT_MESH ( \
+ DT_TYPE_BWEIGHT_VERT | \
+ DT_TYPE_BWEIGHT_EDGE | DT_TYPE_CREASE | DT_TYPE_SHARP_EDGE | \
+ DT_TYPE_LNOR | \
+ DT_TYPE_SHARP_FACE \
+)
+
+static DerivedMesh *applyModifier(ModifierData *md, Object *ob, DerivedMesh *derivedData,
+ ModifierApplyFlag UNUSED(flag))
+{
+ DataTransferModifierData *dtmd = (DataTransferModifierData *) md;
+ DerivedMesh *dm = derivedData;
+ ReportList reports;
+
+ /* Only used to check wehther we are operating on org data or not... */
+ Mesh *me = ob->data;
+ MVert *mvert;
+
+ const bool invert_vgroup = (dtmd->flags & MOD_DATATRANSFER_INVERT_VGROUP) != 0;
+
+ const float max_dist = (dtmd->flags & MOD_DATATRANSFER_MAP_MAXDIST) ? dtmd->map_max_distance : FLT_MAX;
+
+ SpaceTransform space_transform_data;
+ SpaceTransform *space_transform = (dtmd->flags & MOD_DATATRANSFER_OBSRC_TRANSFORM) ? &space_transform_data : NULL;
+
+ if (space_transform) {
+ BLI_SPACE_TRANSFORM_SETUP(space_transform, ob, dtmd->ob_source);
+ }
+
+ mvert = dm->getVertArray(dm);
+ if ((me->mvert == mvert) && (dtmd->data_types & DT_TYPES_AFFECT_MESH)) {
+ /* We need to duplicate data here, otherwise setting custom normals, edges' shaprness, etc., could
+ * modify org mesh, see T43671. */
+ dm = CDDM_copy(dm);
+ }
+
+ BKE_reports_init(&reports, RPT_STORE);
+
+ /* Note: no islands precision for now here. */
+ BKE_object_data_transfer_dm(md->scene, dtmd->ob_source, ob, dm, dtmd->data_types, false,
+ dtmd->vmap_mode, dtmd->emap_mode, dtmd->lmap_mode, dtmd->pmap_mode,
+ space_transform, false, max_dist, dtmd->map_ray_radius, 0.0f,
+ dtmd->layers_select_src, dtmd->layers_select_dst,
+ dtmd->mix_mode, dtmd->mix_factor, dtmd->defgrp_name, invert_vgroup, &reports);
+
+ if (BKE_reports_contain(&reports, RPT_ERROR)) {
+ modifier_setError(md, "%s", BKE_reports_string(&reports, RPT_ERROR));
+ }
+ else if (dm->getNumVerts(dm) > HIGH_POLY_WARNING || ((Mesh *)(dtmd->ob_source->data))->totvert > HIGH_POLY_WARNING) {
+ modifier_setError(md, "You are using a rather high poly as source or destination, computation might be slow");
+ }
+
+ return dm;
+}
+
+#undef HIGH_POLY_WARNING
+#undef DT_TYPES_AFFECT_MESH
+
+static void copyData(ModifierData *md, ModifierData *target)
+{
+#if 0
+ DataTransferModifierData *dtmd = (DecimateModifierData *) md;
+ DataTransferModifierData *tdtmd = (DecimateModifierData *) target;
+#endif
+ modifier_copyData_generic(md, target);
+}
+
+ModifierTypeInfo modifierType_DataTransfer = {
+ /* name */ "DataTransfer",
+ /* structName */ "DataTransferModifierData",
+ /* structSize */ sizeof(DataTransferModifierData),
+ /* type */ eModifierTypeType_NonGeometrical,
+ /* flags */ eModifierTypeFlag_AcceptsMesh |
+ eModifierTypeFlag_SupportsMapping |
+ eModifierTypeFlag_SupportsEditmode |
+ eModifierTypeFlag_UsesPreview,
+
+ /* copyData */ copyData,
+ /* deformVerts */ NULL,
+ /* deformMatrices */ NULL,
+ /* deformVertsEM */ NULL,
+ /* deformMatricesEM */ NULL,
+ /* applyModifier */ applyModifier,
+ /* applyModifierEM */ NULL,
+ /* initData */ initData,
+ /* requiredDataMask */ requiredDataMask,
+ /* freeData */ NULL,
+ /* isDisabled */ isDisabled,
+ /* updateDepgraph */ updateDepgraph,
+ /* updateDepsgraph */ updateDepsgraph,
+ /* dependsOnTime */ NULL,
+ /* dependsOnNormals */ dependsOnNormals,
+ /* foreachObjectLink */ foreachObjectLink,
+ /* foreachIDLink */ foreachIDLink,
+ /* foreachTexLink */ NULL,
+};
diff --git a/source/blender/modifiers/intern/MOD_decimate.c b/source/blender/modifiers/intern/MOD_decimate.c
index b844b9e3bde..14468ab7c12 100644
--- a/source/blender/modifiers/intern/MOD_decimate.c
+++ b/source/blender/modifiers/intern/MOD_decimate.c
@@ -35,17 +35,12 @@
#include "DNA_object_types.h"
#include "BLI_math.h"
-#include "BLI_string.h"
#include "BLI_utildefines.h"
-#include "BLF_translation.h"
-
#include "MEM_guardedalloc.h"
-#include "BKE_mesh.h"
#include "BKE_modifier.h"
#include "BKE_deform.h"
-#include "BKE_particle.h"
#include "BKE_cdderivedmesh.h"
#include "bmesh.h"
@@ -66,6 +61,7 @@ static void initData(ModifierData *md)
dmd->percent = 1.0;
dmd->angle = DEG2RADF(5.0f);
+ dmd->defgrp_factor = 1.0;
}
static void copyData(ModifierData *md, ModifierData *target)
@@ -83,7 +79,9 @@ static CustomDataMask requiredDataMask(Object *UNUSED(ob), ModifierData *md)
CustomDataMask dataMask = 0;
/* ask for vertexgroups if we need them */
- if (dmd->defgrp_name[0]) dataMask |= CD_MASK_MDEFORMVERT;
+ if (dmd->defgrp_name[0] && (dmd->defgrp_factor > 0.0f)) {
+ dataMask |= CD_MASK_MDEFORMVERT;
+ }
return dataMask;
}
@@ -135,7 +133,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
}
if (dmd->mode == MOD_DECIM_MODE_COLLAPSE) {
- if (dmd->defgrp_name[0]) {
+ if (dmd->defgrp_name[0] && (dmd->defgrp_factor > 0.0f)) {
MDeformVert *dvert;
int defgrp_index;
@@ -149,14 +147,12 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
if (dmd->flag & MOD_DECIM_FLAG_INVERT_VGROUP) {
for (i = 0; i < vert_tot; i++) {
- const float f = 1.0f - defvert_find_weight(&dvert[i], defgrp_index);
- vweights[i] = f > BM_MESH_DECIM_WEIGHT_EPS ? (1.0f / f) : BM_MESH_DECIM_WEIGHT_MAX;
+ vweights[i] = 1.0f - defvert_find_weight(&dvert[i], defgrp_index);
}
}
else {
for (i = 0; i < vert_tot; i++) {
- const float f = defvert_find_weight(&dvert[i], defgrp_index);
- vweights[i] = f > BM_MESH_DECIM_WEIGHT_EPS ? (1.0f / f) : BM_MESH_DECIM_WEIGHT_MAX;
+ vweights[i] = defvert_find_weight(&dvert[i], defgrp_index);
}
}
}
@@ -168,8 +164,8 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
switch (dmd->mode) {
case MOD_DECIM_MODE_COLLAPSE:
{
- const int do_triangulate = (dmd->flag & MOD_DECIM_FLAG_TRIANGULATE) != 0;
- BM_mesh_decimate_collapse(bm, dmd->percent, vweights, do_triangulate);
+ const bool do_triangulate = (dmd->flag & MOD_DECIM_FLAG_TRIANGULATE) != 0;
+ BM_mesh_decimate_collapse(bm, dmd->percent, vweights, dmd->defgrp_factor, do_triangulate);
break;
}
case MOD_DECIM_MODE_UNSUBDIV:
@@ -179,7 +175,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
}
case MOD_DECIM_MODE_DISSOLVE:
{
- const int do_dissolve_boundaries = (dmd->flag & MOD_DECIM_FLAG_ALL_BOUNDARY_VERTS) != 0;
+ const bool do_dissolve_boundaries = (dmd->flag & MOD_DECIM_FLAG_ALL_BOUNDARY_VERTS) != 0;
BM_mesh_decimate_dissolve(bm, dmd->angle, do_dissolve_boundaries, (BMO_Delimit)dmd->delimit);
break;
}
@@ -229,6 +225,7 @@ ModifierTypeInfo modifierType_Decimate = {
/* freeData */ NULL,
/* isDisabled */ NULL,
/* updateDepgraph */ NULL,
+ /* updateDepsgraph */ NULL,
/* dependsOnTime */ NULL,
/* dependsOnNormals */ NULL,
/* foreachObjectLink */ NULL,
diff --git a/source/blender/modifiers/intern/MOD_displace.c b/source/blender/modifiers/intern/MOD_displace.c
index a23873fcd8a..b20d7d8a3a9 100644
--- a/source/blender/modifiers/intern/MOD_displace.c
+++ b/source/blender/modifiers/intern/MOD_displace.c
@@ -37,10 +37,11 @@
#include "DNA_object_types.h"
#include "BLI_utildefines.h"
-
+#include "BLI_math.h"
#include "BKE_cdderivedmesh.h"
#include "BKE_library.h"
+#include "BKE_mesh.h"
#include "BKE_modifier.h"
#include "BKE_texture.h"
#include "BKE_deform.h"
@@ -98,6 +99,10 @@ static CustomDataMask requiredDataMask(Object *UNUSED(ob), ModifierData *md)
/* ask for UV coordinates if we need them */
if (dmd->texmapping == MOD_DISP_MAP_UV) dataMask |= CD_MASK_MTFACE;
+ if (dmd->direction == MOD_DISP_DIR_CLNOR) {
+ dataMask |= CD_MASK_CUSTOMLOOPNORMAL;
+ }
+
return dataMask;
}
@@ -116,7 +121,7 @@ static bool dependsOnTime(ModifierData *md)
static bool dependsOnNormals(ModifierData *md)
{
DisplaceModifierData *dmd = (DisplaceModifierData *)md;
- return (dmd->direction == MOD_DISP_DIR_NOR);
+ return ELEM(dmd->direction, MOD_DISP_DIR_NOR, MOD_DISP_DIR_CLNOR);
}
static void foreachObjectLink(ModifierData *md, Object *ob,
@@ -150,6 +155,7 @@ static bool isDisabled(ModifierData *md, int UNUSED(useRenderParams))
}
static void updateDepgraph(ModifierData *md, DagForest *forest,
+ struct Main *UNUSED(bmain),
struct Scene *UNUSED(scene),
Object *UNUSED(ob),
DagNode *obNode)
@@ -170,6 +176,21 @@ static void updateDepgraph(ModifierData *md, DagForest *forest,
}
+static void updateDepsgraph(ModifierData *md,
+ struct Main *UNUSED(bmain),
+ struct Scene *UNUSED(scene),
+ Object *ob,
+ struct DepsNodeHandle *node)
+{
+ DisplaceModifierData *dmd = (DisplaceModifierData *)md;
+ if (dmd->map_object != NULL && dmd->texmapping == MOD_DISP_MAP_OBJECT) {
+ DEG_add_object_relation(node, dmd->map_object, DEG_OB_COMP_TRANSFORM, "Displace Modifier");
+ }
+ if (dmd->texmapping == MOD_DISP_MAP_GLOBAL) {
+ DEG_add_object_relation(node, ob, DEG_OB_COMP_TRANSFORM, "Displace Modifier");
+ }
+}
+
/* dm must be a CDDerivedMesh */
static void displaceModifier_do(
DisplaceModifierData *dmd, Object *ob,
@@ -178,10 +199,12 @@ static void displaceModifier_do(
int i;
MVert *mvert;
MDeformVert *dvert;
+ int direction = dmd->direction;
int defgrp_index;
float (*tex_co)[3];
float weight = 1.0f; /* init value unused but some compilers may complain */
const float delta_fixed = 1.0f - dmd->midlevel; /* when no texture is used, we fallback to white */
+ float (*vert_clnors)[3] = NULL;
if (!dmd->texture && dmd->direction == MOD_DISP_DIR_RGB_XYZ) return;
if (dmd->strength == 0.0f) return;
@@ -200,6 +223,26 @@ static void displaceModifier_do(
tex_co = NULL;
}
+ if (direction == MOD_DISP_DIR_CLNOR) {
+ CustomData *ldata = dm->getLoopDataLayout(dm);
+
+ if (CustomData_has_layer(ldata, CD_CUSTOMLOOPNORMAL)) {
+ float (*clnors)[3] = NULL;
+
+ if ((dm->dirty & DM_DIRTY_NORMALS) || !CustomData_has_layer(ldata, CD_NORMAL)) {
+ dm->calcLoopNormals(dm, true, (float)M_PI);
+ }
+
+ clnors = CustomData_get_layer(ldata, CD_NORMAL);
+ vert_clnors = MEM_mallocN(sizeof(*vert_clnors) * (size_t)numVerts, __func__);
+ BKE_mesh_normals_loop_to_vertex(numVerts, dm->getLoopArray(dm), dm->getNumLoops(dm),
+ (const float (*)[3])clnors, vert_clnors);
+ }
+ else {
+ direction = MOD_DISP_DIR_NOR;
+ }
+ }
+
for (i = 0; i < numVerts; i++) {
TexResult texres;
float strength = dmd->strength;
@@ -224,7 +267,7 @@ static void displaceModifier_do(
delta *= strength;
CLAMP(delta, -10000, 10000);
- switch (dmd->direction) {
+ switch (direction) {
case MOD_DISP_DIR_X:
vertexCos[i][0] += delta;
break;
@@ -244,12 +287,19 @@ static void displaceModifier_do(
vertexCos[i][1] += delta * (mvert[i].no[1] / 32767.0f);
vertexCos[i][2] += delta * (mvert[i].no[2] / 32767.0f);
break;
+ case MOD_DISP_DIR_CLNOR:
+ madd_v3_v3fl(vertexCos[i], vert_clnors[i], delta);
+ break;
}
}
if (tex_co) {
MEM_freeN(tex_co);
}
+
+ if (vert_clnors) {
+ MEM_freeN(vert_clnors);
+ }
}
static void deformVerts(ModifierData *md, Object *ob,
@@ -301,6 +351,7 @@ ModifierTypeInfo modifierType_Displace = {
/* freeData */ freeData,
/* isDisabled */ isDisabled,
/* updateDepgraph */ updateDepgraph,
+ /* updateDepsgraph */ updateDepsgraph,
/* dependsOnTime */ dependsOnTime,
/* dependsOnNormals */ dependsOnNormals,
/* foreachObjectLink */ foreachObjectLink,
diff --git a/source/blender/modifiers/intern/MOD_dynamicpaint.c b/source/blender/modifiers/intern/MOD_dynamicpaint.c
index 838ceb5cfe0..f1b6ceb070c 100644
--- a/source/blender/modifiers/intern/MOD_dynamicpaint.c
+++ b/source/blender/modifiers/intern/MOD_dynamicpaint.c
@@ -28,7 +28,6 @@
#include <stddef.h>
#include "DNA_dynamicpaint_types.h"
-#include "DNA_meshdata_types.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
@@ -39,8 +38,7 @@
#include "BKE_modifier.h"
#include "depsgraph_private.h"
-
-#include "MOD_util.h"
+#include "DEG_depsgraph_build.h"
static void initData(ModifierData *md)
@@ -78,24 +76,24 @@ static CustomDataMask requiredDataMask(Object *UNUSED(ob), ModifierData *md)
if (surface->format == MOD_DPAINT_SURFACE_F_IMAGESEQ ||
surface->init_color_type == MOD_DPAINT_INITIAL_TEXTURE)
{
- dataMask |= (1 << CD_MTFACE);
+ dataMask |= CD_MASK_MLOOPUV | CD_MASK_MTEXPOLY;
}
/* mcol */
if (surface->type == MOD_DPAINT_SURFACE_T_PAINT ||
surface->init_color_type == MOD_DPAINT_INITIAL_VERTEXCOLOR)
{
- dataMask |= (1 << CD_MCOL);
+ dataMask |= CD_MASK_MLOOPCOL;
}
/* CD_MDEFORMVERT */
if (surface->type == MOD_DPAINT_SURFACE_T_WEIGHT) {
- dataMask |= (1 << CD_MDEFORMVERT);
+ dataMask |= CD_MASK_MDEFORMVERT;
}
}
}
if (pmd->brush) {
if (pmd->brush->flags & MOD_DPAINT_USE_MATERIAL) {
- dataMask |= (1 << CD_MTFACE);
+ dataMask |= CD_MASK_MLOOPUV | CD_MASK_MTEXPOLY;
}
}
return dataMask;
@@ -115,6 +113,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
}
static void updateDepgraph(ModifierData *md, DagForest *forest,
+ struct Main *UNUSED(bmain),
struct Scene *scene,
Object *ob,
DagNode *obNode)
@@ -137,6 +136,26 @@ static void updateDepgraph(ModifierData *md, DagForest *forest,
}
}
+static void updateDepsgraph(ModifierData *md,
+ struct Main *UNUSED(bmain),
+ struct Scene *scene,
+ Object *ob,
+ struct DepsNodeHandle *node)
+{
+ DynamicPaintModifierData *pmd = (DynamicPaintModifierData *)md;
+ /* Add relation from canvases to all brush objects. */
+ if (pmd->canvas != NULL) {
+ Base *base = scene->base.first;
+ for (; base; base = base->next) {
+ DynamicPaintModifierData *pmd2 =
+ (DynamicPaintModifierData *)modifiers_findByType(base->object, eModifierType_DynamicPaint);
+ if (pmd2 && pmd2->brush && ob != base->object) {
+ DEG_add_object_relation(node, base->object, DEG_OB_COMP_TRANSFORM, "Dynamic Paint Brush");
+ }
+ }
+ }
+}
+
static bool dependsOnTime(ModifierData *UNUSED(md))
{
return true;
@@ -189,6 +208,7 @@ ModifierTypeInfo modifierType_DynamicPaint = {
/* freeData */ freeData,
/* isDisabled */ NULL,
/* updateDepgraph */ updateDepgraph,
+ /* updateDepsgraph */ updateDepsgraph,
/* dependsOnTime */ dependsOnTime,
/* dependsOnNormals */ NULL,
/* foreachObjectLink */ NULL,
diff --git a/source/blender/modifiers/intern/MOD_edgesplit.c b/source/blender/modifiers/intern/MOD_edgesplit.c
index fa29921b325..4441edb299b 100644
--- a/source/blender/modifiers/intern/MOD_edgesplit.c
+++ b/source/blender/modifiers/intern/MOD_edgesplit.c
@@ -158,6 +158,7 @@ ModifierTypeInfo modifierType_EdgeSplit = {
/* freeData */ NULL,
/* isDisabled */ NULL,
/* updateDepgraph */ NULL,
+ /* updateDepsgraph */ NULL,
/* dependsOnTime */ NULL,
/* dependsOnNormals */ NULL,
/* foreachObjectLink */ NULL,
diff --git a/source/blender/modifiers/intern/MOD_explode.c b/source/blender/modifiers/intern/MOD_explode.c
index d3c7e7d4779..d57ace8d7fe 100644
--- a/source/blender/modifiers/intern/MOD_explode.c
+++ b/source/blender/modifiers/intern/MOD_explode.c
@@ -54,7 +54,6 @@
#include "MEM_guardedalloc.h"
-#include "MOD_util.h"
static void initData(ModifierData *md)
{
@@ -772,7 +771,7 @@ static DerivedMesh *cutEdges(ExplodeModifierData *emd, DerivedMesh *dm)
for (i = 0; i < curdupface; i++) {
mf = CDDM_get_tessface(splitdm, i);
- test_index_face(mf, &splitdm->faceData, i, (mf->flag & ME_FACE_SEL ? 4 : 3));
+ test_index_face(mf, &splitdm->faceData, i, ((mf->flag & ME_FACE_SEL) ? 4 : 3));
}
BLI_edgehash_free(edgehash, NULL);
@@ -862,7 +861,7 @@ static DerivedMesh *explodeMesh(ExplodeModifierData *emd,
BLI_edgehashIterator_free(ehi);
/* the final duplicated vertices */
- explode = CDDM_from_template(dm, totdup, 0, totface - delface, 0, 0);
+ explode = CDDM_from_template_ex(dm, totdup, 0, totface - delface, 0, 0, CD_MASK_DERIVEDMESH | CD_MASK_FACECORNERS);
mtface = CustomData_get_layer_named(&explode->faceData, CD_MTFACE, emd->uvname);
/*dupvert = CDDM_get_verts(explode);*/
@@ -892,7 +891,7 @@ static DerivedMesh *explodeMesh(ExplodeModifierData *emd,
/* get particle */
pa = pars + ed_v2;
- psys_get_birth_coordinates(&sim, pa, &birth, 0, 0);
+ psys_get_birth_coords(&sim, pa, &birth, 0, 0);
state.time = cfra;
psys_get_particle_state(&sim, ed_v2, &state, 1);
@@ -1059,6 +1058,7 @@ ModifierTypeInfo modifierType_Explode = {
/* freeData */ freeData,
/* isDisabled */ NULL,
/* updateDepgraph */ NULL,
+ /* updateDepsgraph */ NULL,
/* dependsOnTime */ dependsOnTime,
/* dependsOnNormals */ NULL,
/* foreachObjectLink */ NULL,
diff --git a/source/blender/modifiers/intern/MOD_fluidsim.c b/source/blender/modifiers/intern/MOD_fluidsim.c
index d3c56b8d7f7..c202c5e1cb4 100644
--- a/source/blender/modifiers/intern/MOD_fluidsim.c
+++ b/source/blender/modifiers/intern/MOD_fluidsim.c
@@ -44,8 +44,8 @@
#include "BKE_modifier.h"
#include "depsgraph_private.h"
+#include "DEG_depsgraph_build.h"
-#include "MOD_util.h"
#include "MOD_fluidsim_util.h"
#include "MEM_guardedalloc.h"
@@ -72,6 +72,9 @@ static void copyData(ModifierData *md, ModifierData *target)
MEM_freeN(tfluidmd->fss);
tfluidmd->fss = MEM_dupallocN(fluidmd->fss);
+ if (tfluidmd->fss && (tfluidmd->fss->meshVelocities != NULL)) {
+ tfluidmd->fss->meshVelocities = MEM_dupallocN(tfluidmd->fss->meshVelocities);
+ }
}
@@ -98,7 +101,8 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
}
static void updateDepgraph(
- ModifierData *md, DagForest *forest, Scene *scene,
+ ModifierData *md, DagForest *forest,
+ struct Main *UNUSED(bmain), Scene *scene,
Object *ob, DagNode *obNode)
{
FluidsimModifierData *fluidmd = (FluidsimModifierData *) md;
@@ -123,6 +127,32 @@ static void updateDepgraph(
}
}
+static void updateDepsgraph(ModifierData *md,
+ struct Main *UNUSED(bmain),
+ struct Scene *scene,
+ Object *ob,
+ struct DepsNodeHandle *node)
+{
+ FluidsimModifierData *fluidmd = (FluidsimModifierData *) md;
+ if (fluidmd && fluidmd->fss) {
+ if (fluidmd->fss->type == OB_FLUIDSIM_DOMAIN) {
+ Base *base;
+ for (base = scene->base.first; base; base = base->next) {
+ Object *ob1 = base->object;
+ if (ob1 != ob) {
+ FluidsimModifierData *fluidmdtmp =
+ (FluidsimModifierData *)modifiers_findByType(ob1, eModifierType_Fluidsim);
+
+ /* Only put dependencies from NON-DOMAIN fluids in here. */
+ if (fluidmdtmp && fluidmdtmp->fss && (fluidmdtmp->fss->type != OB_FLUIDSIM_DOMAIN)) {
+ DEG_add_object_relation(node, ob1, DEG_OB_COMP_TRANSFORM, "Fluidsim Object");
+ }
+ }
+ }
+ }
+ }
+}
+
static bool dependsOnTime(ModifierData *UNUSED(md))
{
return true;
@@ -151,6 +181,7 @@ ModifierTypeInfo modifierType_Fluidsim = {
/* freeData */ freeData,
/* isDisabled */ NULL,
/* updateDepgraph */ updateDepgraph,
+ /* updateDepsgraph */ updateDepsgraph,
/* dependsOnTime */ dependsOnTime,
/* dependsOnNormals */ NULL,
/* foreachObjectLink */ NULL,
diff --git a/source/blender/modifiers/intern/MOD_hook.c b/source/blender/modifiers/intern/MOD_hook.c
index f6d7c03df32..3a10fabbb8e 100644
--- a/source/blender/modifiers/intern/MOD_hook.c
+++ b/source/blender/modifiers/intern/MOD_hook.c
@@ -43,6 +43,7 @@
#include "BKE_cdderivedmesh.h"
#include "BKE_modifier.h"
#include "BKE_deform.h"
+#include "BKE_colortools.h"
#include "depsgraph_private.h"
@@ -55,6 +56,9 @@ static void initData(ModifierData *md)
HookModifierData *hmd = (HookModifierData *) md;
hmd->force = 1.0;
+ hmd->curfalloff = curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f);
+ hmd->falloff_type = eHook_Falloff_Smooth;
+ hmd->flag = 0;
}
static void copyData(ModifierData *md, ModifierData *target)
@@ -64,6 +68,8 @@ static void copyData(ModifierData *md, ModifierData *target)
modifier_copyData_generic(md, target);
+ thmd->curfalloff = curvemapping_copy(hmd->curfalloff);
+
thmd->indexar = MEM_dupallocN(hmd->indexar);
}
@@ -83,6 +89,8 @@ static void freeData(ModifierData *md)
{
HookModifierData *hmd = (HookModifierData *) md;
+ curvemapping_free(hmd->curfalloff);
+
if (hmd->indexar) MEM_freeN(hmd->indexar);
}
@@ -104,6 +112,7 @@ static void foreachObjectLink(
}
static void updateDepgraph(ModifierData *md, DagForest *forest,
+ struct Main *UNUSED(bmain),
struct Scene *UNUSED(scene),
Object *UNUSED(ob),
DagNode *obNode)
@@ -120,32 +129,191 @@ static void updateDepgraph(ModifierData *md, DagForest *forest,
}
}
-static float hook_falloff(const float co_1[3], const float co_2[3], const float falloff_squared, float fac)
+static void updateDepsgraph(ModifierData *md,
+ struct Main *UNUSED(bmain),
+ struct Scene *UNUSED(scene),
+ Object *UNUSED(ob),
+ struct DepsNodeHandle *node)
{
- if (falloff_squared) {
- float len_squared = len_squared_v3v3(co_1, co_2);
- if (len_squared > falloff_squared) {
- return 0.0f;
+ HookModifierData *hmd = (HookModifierData *)md;
+ if (hmd->object != NULL) {
+ if (hmd->subtarget[0]) {
+ /* TODO(sergey): Hpw do we add relation to bone here? */
+ //DEG_add_object_relation(node, hmd->object, DEG_OB_COMP_EVAL_POSE, "Hook Modifier");
+ DEG_add_bone_relation(node, hmd->object, hmd->subtarget, DEG_OB_COMP_BONE, "Hook Modifier");
}
- else if (len_squared > 0.0f) {
- return fac * (1.0f - (len_squared / falloff_squared));
+ else {
+ DEG_add_object_relation(node, hmd->object, DEG_OB_COMP_TRANSFORM, "Hook Modifier");
}
}
+}
+
+struct HookData_cb {
+ float (*vertexCos)[3];
+
+ MDeformVert *dvert;
+ int defgrp_index;
+
+ struct CurveMapping *curfalloff;
+
+ char falloff_type;
+ float falloff;
+ float falloff_sq;
+ float fac_orig;
+
+ unsigned int use_falloff : 1;
+ unsigned int use_uniform : 1;
+
+ float cent[3];
+
+ float mat_uniform[3][3];
+ float mat[4][4];
+};
+
+static float hook_falloff(
+ const struct HookData_cb *hd,
+ const float len_sq)
+{
+ BLI_assert(hd->falloff_sq);
+ if (len_sq > hd->falloff_sq) {
+ return 0.0f;
+ }
+ else if (len_sq > 0.0f) {
+ float fac;
+
+ if (hd->falloff_type == eHook_Falloff_Const) {
+ fac = 1.0f;
+ goto finally;
+ }
+ else if (hd->falloff_type == eHook_Falloff_InvSquare) {
+ /* avoid sqrt below */
+ fac = 1.0f - (len_sq / hd->falloff_sq);
+ goto finally;
+ }
- return fac;
+ fac = 1.0f - (sqrtf(len_sq) / hd->falloff);
+
+ /* closely match PROP_SMOOTH and similar */
+ switch (hd->falloff_type) {
+#if 0
+ case eHook_Falloff_None:
+ fac = 1.0f;
+ break;
+#endif
+ case eHook_Falloff_Curve:
+ fac = curvemapping_evaluateF(hd->curfalloff, 0, fac);
+ break;
+ case eHook_Falloff_Sharp:
+ fac = fac * fac;
+ break;
+ case eHook_Falloff_Smooth:
+ fac = 3.0f * fac * fac - 2.0f * fac * fac * fac;
+ break;
+ case eHook_Falloff_Root:
+ fac = sqrtf(fac);
+ break;
+ case eHook_Falloff_Linear:
+ /* pass */
+ break;
+#if 0
+ case eHook_Falloff_Const:
+ fac = 1.0f;
+ break;
+#endif
+ case eHook_Falloff_Sphere:
+ fac = sqrtf(2 * fac - fac * fac);
+ break;
+#if 0
+ case eHook_Falloff_InvSquare:
+ fac = fac * (2.0f - fac);
+ break;
+#endif
+ }
+
+finally:
+ return fac * hd->fac_orig;
+ }
+ else {
+ return hd->fac_orig;
+ }
+}
+
+static void hook_co_apply(struct HookData_cb *hd, const int j)
+{
+ float *co = hd->vertexCos[j];
+ float fac;
+
+ if (hd->use_falloff) {
+ float len_sq;
+
+ if (hd->use_uniform) {
+ float co_uniform[3];
+ mul_v3_m3v3(co_uniform, hd->mat_uniform, co);
+ len_sq = len_squared_v3v3(hd->cent, co_uniform);
+ }
+ else {
+ len_sq = len_squared_v3v3(hd->cent, co);
+ }
+
+ fac = hook_falloff(hd, len_sq);
+ }
+ else {
+ fac = hd->fac_orig;
+ }
+
+ if (fac) {
+ if (hd->dvert) {
+ fac *= defvert_find_weight(&hd->dvert[j], hd->defgrp_index);
+ }
+
+ if (fac) {
+ float co_tmp[3];
+ mul_v3_m4v3(co_tmp, hd->mat, co);
+ interp_v3_v3v3(co, co, co_tmp, fac);
+ }
+ }
}
static void deformVerts_do(HookModifierData *hmd, Object *ob, DerivedMesh *dm,
float (*vertexCos)[3], int numVerts)
{
bPoseChannel *pchan = BKE_pose_channel_find_name(hmd->object->pose, hmd->subtarget);
- float vec[3], mat[4][4], dmat[4][4];
+ float dmat[4][4];
int i, *index_pt;
- const float falloff_squared = hmd->falloff * hmd->falloff; /* for faster comparisons */
-
- MDeformVert *dvert;
- int defgrp_index, max_dvert;
+ struct HookData_cb hd;
+ if (hmd->curfalloff == NULL) {
+ /* should never happen, but bad lib linking could cause it */
+ hmd->curfalloff = curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f);
+ }
+
+ if (hmd->curfalloff) {
+ curvemapping_initialize(hmd->curfalloff);
+ }
+
+ /* Generic data needed for applying per-vertex calculations (initialize all members) */
+ hd.vertexCos = vertexCos;
+ modifier_get_vgroup(ob, dm, hmd->name, &hd.dvert, &hd.defgrp_index);
+
+ hd.curfalloff = hmd->curfalloff;
+
+ hd.falloff_type = hmd->falloff_type;
+ hd.falloff = (hmd->falloff_type == eHook_Falloff_None) ? 0.0f : hmd->falloff;
+ hd.falloff_sq = SQUARE(hd.falloff);
+ hd.fac_orig = hmd->force;
+
+ hd.use_falloff = (hd.falloff_sq != 0.0f);
+ hd.use_uniform = (hmd->flag & MOD_HOOK_UNIFORM_SPACE) != 0;
+
+ if (hd.use_uniform) {
+ copy_m3_m4(hd.mat_uniform, hmd->parentinv);
+ mul_v3_m3v3(hd.cent, hd.mat_uniform, hmd->cent);
+ }
+ else {
+ unit_m3(hd.mat_uniform); /* unused */
+ copy_v3_v3(hd.cent, hmd->cent);
+ }
+
/* get world-space matrix of target, corrected for the space the verts are in */
if (hmd->subtarget[0] && pchan) {
/* bone target if there's a matching pose-channel */
@@ -156,10 +324,9 @@ static void deformVerts_do(HookModifierData *hmd, Object *ob, DerivedMesh *dm,
copy_m4_m4(dmat, hmd->object->obmat);
}
invert_m4_m4(ob->imat, ob->obmat);
- mul_m4_series(mat, ob->imat, dmat, hmd->parentinv);
+ mul_m4_series(hd.mat, ob->imat, dmat, hmd->parentinv);
+ /* --- done with 'hd' init --- */
- modifier_get_vgroup(ob, dm, hmd->name, &dvert, &defgrp_index);
- max_dvert = (dvert) ? numVerts : 0;
/* Regarding index range checking below.
*
@@ -168,13 +335,11 @@ static void deformVerts_do(HookModifierData *hmd, Object *ob, DerivedMesh *dm,
* indices that are out of range because old blender did
* not correct them on exit editmode. - zr
*/
-
+
if (hmd->force == 0.0f) {
/* do nothing, avoid annoying checks in the loop */
}
else if (hmd->indexar) { /* vertex indices? */
- const float fac_orig = hmd->force;
- float fac;
const int *origindex_ar;
/* if DerivedMesh is present and has original index data, use it */
@@ -185,16 +350,7 @@ static void deformVerts_do(HookModifierData *hmd, Object *ob, DerivedMesh *dm,
for (j = 0; j < numVerts; j++) {
if (origindex_ar[j] == *index_pt) {
- float *co = vertexCos[j];
- if ((fac = hook_falloff(hmd->cent, co, falloff_squared, fac_orig))) {
- if (dvert)
- fac *= defvert_find_weight(dvert + j, defgrp_index);
-
- if (fac) {
- mul_v3_m4v3(vec, mat, co);
- interp_v3_v3v3(co, co, vec, fac);
- }
- }
+ hook_co_apply(&hd, j);
}
}
}
@@ -203,34 +359,14 @@ static void deformVerts_do(HookModifierData *hmd, Object *ob, DerivedMesh *dm,
else { /* missing dm or ORIGINDEX */
for (i = 0, index_pt = hmd->indexar; i < hmd->totindex; i++, index_pt++) {
if (*index_pt < numVerts) {
- float *co = vertexCos[*index_pt];
- if ((fac = hook_falloff(hmd->cent, co, falloff_squared, fac_orig))) {
- if (dvert)
- fac *= defvert_find_weight(dvert + (*index_pt), defgrp_index);
-
- if (fac) {
- mul_v3_m4v3(vec, mat, co);
- interp_v3_v3v3(co, co, vec, fac);
- }
- }
+ hook_co_apply(&hd, *index_pt);
}
}
}
}
- else if (dvert) { /* vertex group hook */
- const float fac_orig = hmd->force;
-
- for (i = 0; i < max_dvert; i++, dvert++) {
- float fac;
- float *co = vertexCos[i];
-
- if ((fac = hook_falloff(hmd->cent, co, falloff_squared, fac_orig))) {
- fac *= defvert_find_weight(dvert, defgrp_index);
- if (fac) {
- mul_v3_m4v3(vec, mat, co);
- interp_v3_v3v3(co, co, vec, fac);
- }
- }
+ else if (hd.dvert) { /* vertex group hook */
+ for (i = 0; i < numVerts; i++) {
+ hook_co_apply(&hd, i);
}
}
}
@@ -286,6 +422,7 @@ ModifierTypeInfo modifierType_Hook = {
/* freeData */ freeData,
/* isDisabled */ isDisabled,
/* updateDepgraph */ updateDepgraph,
+ /* updateDepsgraph */ updateDepsgraph,
/* dependsOnTime */ NULL,
/* dependsOnNormals */ NULL,
/* foreachObjectLink */ foreachObjectLink,
diff --git a/source/blender/modifiers/intern/MOD_laplaciandeform.c b/source/blender/modifiers/intern/MOD_laplaciandeform.c
index ffadcda3e8c..8b0ca7f99fb 100644
--- a/source/blender/modifiers/intern/MOD_laplaciandeform.c
+++ b/source/blender/modifiers/intern/MOD_laplaciandeform.c
@@ -63,14 +63,14 @@ typedef struct LaplacianSystem {
bool has_solution;
int total_verts;
int total_edges;
- int total_faces;
+ int total_tris;
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 */
- unsigned int (*faces)[4]; /* Copy of MFace (tessface) v1-v4 */
+ unsigned int (*tris)[3]; /* Copy of MLoopTri (tesselation triangle) v1-v3 */
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 */
@@ -90,15 +90,16 @@ static LaplacianSystem *newLaplacianSystem(void)
sys->total_verts = 0;
sys->total_edges = 0;
sys->total_anchors = 0;
- sys->total_faces = 0;
+ sys->total_tris = 0;
sys->repeat = 1;
sys->anchor_grp_name[0] = '\0';
return sys;
}
-static LaplacianSystem *initLaplacianSystem(int totalVerts, int totalEdges, int totalFaces, int totalAnchors,
- const char defgrpName[64], int iterations)
+static LaplacianSystem *initLaplacianSystem(
+ int totalVerts, int totalEdges, int totalTris, int totalAnchors,
+ const char defgrpName[64], int iterations)
{
LaplacianSystem *sys = newLaplacianSystem();
@@ -106,14 +107,14 @@ static LaplacianSystem *initLaplacianSystem(int totalVerts, int totalEdges, int
sys->has_solution = false;
sys->total_verts = totalVerts;
sys->total_edges = totalEdges;
- sys->total_faces = totalFaces;
+ sys->total_tris = totalTris;
sys->total_anchors = totalAnchors;
sys->repeat = iterations;
BLI_strncpy(sys->anchor_grp_name, defgrpName, sizeof(sys->anchor_grp_name));
sys->co = MEM_mallocN(sizeof(float[3]) * totalVerts, "DeformCoordinates");
sys->no = MEM_callocN(sizeof(float[3]) * totalVerts, "DeformNormals");
sys->delta = MEM_callocN(sizeof(float[3]) * totalVerts, "DeformDeltas");
- sys->faces = MEM_mallocN(sizeof(int[4]) * totalFaces, "DeformFaces");
+ sys->tris = MEM_mallocN(sizeof(int[3]) * totalTris, "DeformFaces");
sys->index_anchors = MEM_mallocN(sizeof(int) * (totalAnchors), "DeformAnchors");
sys->unit_verts = MEM_callocN(sizeof(int) * totalVerts, "DeformUnitVerts");
return sys;
@@ -124,7 +125,7 @@ static void deleteLaplacianSystem(LaplacianSystem *sys)
MEM_SAFE_FREE(sys->co);
MEM_SAFE_FREE(sys->no);
MEM_SAFE_FREE(sys->delta);
- MEM_SAFE_FREE(sys->faces);
+ MEM_SAFE_FREE(sys->tris);
MEM_SAFE_FREE(sys->index_anchors);
MEM_SAFE_FREE(sys->unit_verts);
MEM_SAFE_FREE(sys->ringf_indices);
@@ -139,21 +140,18 @@ static void deleteLaplacianSystem(LaplacianSystem *sys)
}
static void createFaceRingMap(
- const int mvert_tot, const MFace *mface, const int mface_tot,
- MeshElemMap **r_map, int **r_indices)
+ const int mvert_tot, const MLoopTri *mlooptri, const int mtri_tot,
+ const MLoop *mloop, MeshElemMap **r_map, int **r_indices)
{
int i, j, totalr = 0;
int *indices, *index_iter;
MeshElemMap *map = MEM_callocN(sizeof(MeshElemMap) * mvert_tot, "DeformRingMap");
- const MFace *mf;
-
- for (i = 0, mf = mface; i < mface_tot; i++, mf++) {
- bool has_4_vert;
+ const MLoopTri *mlt;
- has_4_vert = mf->v4 ? 1 : 0;
+ for (i = 0, mlt = mlooptri; i < mtri_tot; i++, mlt++) {
- for (j = 0; j < (has_4_vert ? 4 : 3); j++) {
- const unsigned int v_index = (*(&mf->v1 + j));
+ for (j = 0; j < 3; j++) {
+ const unsigned int v_index = mloop[mlt->tri[j]].v;
map[v_index].count++;
totalr++;
}
@@ -165,13 +163,9 @@ static void createFaceRingMap(
index_iter += map[i].count;
map[i].count = 0;
}
- for (i = 0, mf = mface; i < mface_tot; i++, mf++) {
- bool has_4_vert;
-
- has_4_vert = mf->v4 ? 1 : 0;
-
- for (j = 0; j < (has_4_vert ? 4 : 3); j++) {
- const unsigned int v_index = (*(&mf->v1 + j));
+ for (i = 0, mlt = mlooptri; i < mtri_tot; i++, mlt++) {
+ for (j = 0; j < 3; j++) {
+ const unsigned int v_index = mloop[mlt->tri[j]].v;
map[v_index].indices[map[v_index].count] = i;
map[v_index].count++;
}
@@ -245,85 +239,53 @@ static void createVertRingMap(
*/
static void initLaplacianMatrix(LaplacianSystem *sys)
{
- float v1[3], v2[3], v3[3], v4[3], no[3];
- float w2, w3, w4;
- int i, j, fi;
- bool has_4_vert;
- unsigned int idv1, idv2, idv3, idv4;
-
- for (fi = 0; fi < sys->total_faces; fi++) {
- const unsigned int *vidf = sys->faces[fi];
-
- idv1 = vidf[0];
- idv2 = vidf[1];
- idv3 = vidf[2];
- idv4 = vidf[3];
-
- 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]);
- add_v3_v3(sys->no[idv4], no);
- i = 4;
- }
- else {
- normal_tri_v3(no, sys->co[idv1], sys->co[idv2], sys->co[idv3]);
- i = 3;
- }
- add_v3_v3(sys->no[idv1], no);
- add_v3_v3(sys->no[idv2], no);
- add_v3_v3(sys->no[idv3], no);
-
- for (j = 0; j < i; j++) {
- idv1 = vidf[j];
- idv2 = vidf[(j + 1) % i];
- idv3 = vidf[(j + 2) % i];
- idv4 = has_4_vert ? vidf[(j + 3) % i] : 0;
-
- copy_v3_v3(v1, sys->co[idv1]);
- copy_v3_v3(v2, sys->co[idv2]);
- copy_v3_v3(v3, sys->co[idv3]);
- if (has_4_vert) {
- copy_v3_v3(v4, sys->co[idv4]);
- }
+ float no[3];
+ float w2, w3;
+ int i = 3, j, ti;
+ int idv[3];
- if (has_4_vert) {
+ for (ti = 0; ti < sys->total_tris; ti++) {
+ const unsigned int *vidt = sys->tris[ti];
+ const float *co[3];
- w2 = (cotangent_tri_weight_v3(v4, v1, v2) + cotangent_tri_weight_v3(v3, v1, v2)) / 2.0f;
- w3 = (cotangent_tri_weight_v3(v2, v3, v1) + cotangent_tri_weight_v3(v4, v1, v3)) / 2.0f;
- w4 = (cotangent_tri_weight_v3(v2, v4, v1) + cotangent_tri_weight_v3(v3, v4, v1)) / 2.0f;
+ co[0] = sys->co[vidt[0]];
+ co[1] = sys->co[vidt[1]];
+ co[2] = sys->co[vidt[2]];
- sys->delta[idv1][0] -= v4[0] * w4;
- sys->delta[idv1][1] -= v4[1] * w4;
- sys->delta[idv1][2] -= v4[2] * w4;
+ normal_tri_v3(no, UNPACK3(co));
+ add_v3_v3(sys->no[vidt[0]], no);
+ add_v3_v3(sys->no[vidt[1]], no);
+ add_v3_v3(sys->no[vidt[2]], no);
- nlRightHandSideAdd(0, idv1, -v4[0] * w4);
- nlRightHandSideAdd(1, idv1, -v4[1] * w4);
- nlRightHandSideAdd(2, idv1, -v4[2] * w4);
+ for (j = 0; j < 3; j++) {
+ const float *v1, *v2, *v3;
- nlMatrixAdd(idv1, idv4, -w4);
- }
- else {
- w2 = cotangent_tri_weight_v3(v3, v1, v2);
- w3 = cotangent_tri_weight_v3(v2, v3, v1);
- w4 = 0.0f;
- }
+ idv[0] = vidt[j];
+ idv[1] = vidt[(j + 1) % i];
+ idv[2] = vidt[(j + 2) % i];
+
+ v1 = sys->co[idv[0]];
+ v2 = sys->co[idv[1]];
+ v3 = sys->co[idv[2]];
- sys->delta[idv1][0] += v1[0] * (w2 + w3 + w4);
- sys->delta[idv1][1] += v1[1] * (w2 + w3 + w4);
- sys->delta[idv1][2] += v1[2] * (w2 + w3 + w4);
+ w2 = cotangent_tri_weight_v3(v3, v1, v2);
+ w3 = cotangent_tri_weight_v3(v2, v3, v1);
- sys->delta[idv1][0] -= v2[0] * w2;
- sys->delta[idv1][1] -= v2[1] * w2;
- sys->delta[idv1][2] -= v2[2] * w2;
+ sys->delta[idv[0]][0] += v1[0] * (w2 + w3);
+ sys->delta[idv[0]][1] += v1[1] * (w2 + w3);
+ sys->delta[idv[0]][2] += v1[2] * (w2 + w3);
- sys->delta[idv1][0] -= v3[0] * w3;
- sys->delta[idv1][1] -= v3[1] * w3;
- sys->delta[idv1][2] -= v3[2] * w3;
+ sys->delta[idv[0]][0] -= v2[0] * w2;
+ sys->delta[idv[0]][1] -= v2[1] * w2;
+ sys->delta[idv[0]][2] -= v2[2] * w2;
- nlMatrixAdd(idv1, idv2, -w2);
- nlMatrixAdd(idv1, idv3, -w3);
- nlMatrixAdd(idv1, idv1, w2 + w3 + w4);
+ sys->delta[idv[0]][0] -= v3[0] * w3;
+ sys->delta[idv[0]][1] -= v3[1] * w3;
+ sys->delta[idv[0]][2] -= v3[2] * w3;
+ nlMatrixAdd(idv[0], idv[1], -w2);
+ nlMatrixAdd(idv[0], idv[2], -w3);
+ nlMatrixAdd(idv[0], idv[0], w2 + w3);
}
}
}
@@ -357,8 +319,8 @@ static void rotateDifferentialCoordinates(LaplacianSystem *sys)
{
float alpha, beta, gamma;
float pj[3], ni[3], di[3];
- float uij[3], dun[3], e2[3], pi[3], fni[3], vn[4][3];
- int i, j, lvin, num_fni, k, fi;
+ float uij[3], dun[3], e2[3], pi[3], fni[3], vn[3][3];
+ int i, j, num_fni, k, fi;
int *fidn;
for (i = 0; i < sys->total_verts; i++) {
@@ -385,9 +347,8 @@ static void rotateDifferentialCoordinates(LaplacianSystem *sys)
for (fi = 0; fi < num_fni; fi++) {
const unsigned int *vin;
fidn = sys->ringf_map[i].indices;
- vin = sys->faces[fidn[fi]];
- lvin = vin[3] ? 4 : 3;
- for (j = 0; j < lvin; j++) {
+ vin = sys->tris[fidn[fi]];
+ for (j = 0; j < 3; j++) {
vn[j][0] = nlGetVariable(0, vin[j]);
vn[j][1] = nlGetVariable(1, vin[j]);
vn[j][2] = nlGetVariable(2, vin[j]);
@@ -396,12 +357,7 @@ 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]);
- }
+ normal_tri_v3(fni, UNPACK3(vn));
add_v3_v3(ni, fni);
}
@@ -600,9 +556,12 @@ static void initSystem(LaplacianDeformModifierData *lmd, Object *ob, DerivedMesh
MDeformVert *dvert = NULL;
MDeformVert *dv = NULL;
LaplacianSystem *sys;
+
if (isValidVertexGroup(lmd, ob, dm)) {
int *index_anchors = MEM_mallocN(sizeof(int) * numVerts, __func__); /* over-alloc */
- MFace *tessface;
+ const MLoopTri *mlooptri;
+ const MLoop *mloop;
+
STACK_DECLARE(index_anchors);
STACK_INIT(index_anchors, numVerts);
@@ -617,9 +576,9 @@ static void initSystem(LaplacianDeformModifierData *lmd, Object *ob, DerivedMesh
STACK_PUSH(index_anchors, i);
}
}
- DM_ensure_tessface(dm);
+ DM_ensure_looptri(dm);
total_anchors = STACK_SIZE(index_anchors);
- lmd->cache_system = initLaplacianSystem(numVerts, dm->getNumEdges(dm), dm->getNumTessFaces(dm),
+ lmd->cache_system = initLaplacianSystem(numVerts, dm->getNumEdges(dm), dm->getNumLoopTri(dm),
total_anchors, lmd->anchor_grp_name, lmd->repeat);
sys = (LaplacianSystem *)lmd->cache_system;
memcpy(sys->index_anchors, index_anchors, sizeof(int) * total_anchors);
@@ -630,17 +589,20 @@ static void initSystem(LaplacianDeformModifierData *lmd, Object *ob, DerivedMesh
lmd->total_verts = numVerts;
createFaceRingMap(
- dm->getNumVerts(dm), dm->getTessFaceArray(dm), dm->getNumTessFaces(dm),
- &sys->ringf_map, &sys->ringf_indices);
+ dm->getNumVerts(dm), dm->getLoopTriArray(dm), dm->getNumLoopTri(dm),
+ dm->getLoopArray(dm), &sys->ringf_map, &sys->ringf_indices);
createVertRingMap(
dm->getNumVerts(dm), dm->getEdgeArray(dm), dm->getNumEdges(dm),
&sys->ringv_map, &sys->ringv_indices);
- tessface = dm->getTessFaceArray(dm);
+ mlooptri = dm->getLoopTriArray(dm);
+ mloop = dm->getLoopArray(dm);
- for (i = 0; i < sys->total_faces; i++) {
- memcpy(&sys->faces[i], &tessface[i].v1, sizeof(*sys->faces));
+ for (i = 0; i < sys->total_tris; i++) {
+ sys->tris[i][0] = mloop[mlooptri[i].tri[0]].v;
+ sys->tris[i][1] = mloop[mlooptri[i].tri[1]].v;
+ sys->tris[i][2] = mloop[mlooptri[i].tri[2]].v;
}
}
}
@@ -767,7 +729,7 @@ static void LaplacianDeformModifier_do(
LaplacianDeformModifierData *lmd, Object *ob, DerivedMesh *dm,
float (*vertexCos)[3], int numVerts)
{
- (void)lmd, (void)ob, (void)dm, (void)vertexCos, (void)numVerts;
+ UNUSED_VARS(lmd, ob, dm, vertexCos, numVerts);
}
#endif /* WITH_OPENNL */
@@ -862,6 +824,7 @@ ModifierTypeInfo modifierType_LaplacianDeform = {
/* freeData */ freeData,
/* isDisabled */ isDisabled,
/* updateDepgraph */ NULL,
+ /* updateDepsgraph */ NULL,
/* dependsOnTime */ NULL,
/* dependsOnNormals */ NULL,
/* foreachObjectLink */ NULL,
diff --git a/source/blender/modifiers/intern/MOD_laplaciansmooth.c b/source/blender/modifiers/intern/MOD_laplaciansmooth.c
index 9ba0bfc7ce9..f04e092b39e 100644
--- a/source/blender/modifiers/intern/MOD_laplaciansmooth.c
+++ b/source/blender/modifiers/intern/MOD_laplaciansmooth.c
@@ -41,7 +41,6 @@
#include "BKE_deform.h"
#include "BKE_modifier.h"
-#include "MOD_modifiertypes.h"
#include "MOD_util.h"
#ifdef WITH_OPENNL
@@ -60,7 +59,8 @@ struct BLaplacianSystem {
float *vlengths; /* Total sum of lengths(edges) per vertice*/
float *vweights; /* Total sum of weights per vertice*/
int numEdges; /* Number of edges*/
- int numFaces; /* Number of faces*/
+ int numLoops; /* Number of edges*/
+ int numPolys; /* Number of faces*/
int numVerts; /* Number of verts*/
short *numNeFa; /* Number of neighboors faces around vertice*/
short *numNeEd; /* Number of neighboors Edges around vertice*/
@@ -68,8 +68,9 @@ struct BLaplacianSystem {
/* Pointers to data*/
float (*vertexCos)[3];
- MFace *mfaces;
- MEdge *medges;
+ const MPoly *mpoly;
+ const MLoop *mloop;
+ const MEdge *medges;
NLContext *context;
/*Data*/
@@ -80,12 +81,10 @@ typedef struct BLaplacianSystem LaplacianSystem;
static CustomDataMask required_data_mask(Object *ob, ModifierData *md);
static bool is_disabled(ModifierData *md, int useRenderParams);
-static float average_area_quad_v3(float *v1, float *v2, float *v3, float *v4);
-static float compute_volume(float (*vertexCos)[3], MFace *mfaces, int numFaces);
-static LaplacianSystem *init_laplacian_system(int a_numEdges, int a_numFaces, int a_numVerts);
+static float compute_volume(const float center[3], float (*vertexCos)[3], const MPoly *mpoly, int numPolys, const MLoop *mloop);
+static LaplacianSystem *init_laplacian_system(int a_numEdges, int a_numPolys, int a_numLoops, int a_numVerts);
static void copy_data(ModifierData *md, ModifierData *target);
static void delete_laplacian_system(LaplacianSystem *sys);
-static void delete_void_pointer(void *data);
static void fill_laplacian_matrix(LaplacianSystem *sys);
static void init_data(ModifierData *md);
static void init_laplacian_matrix(LaplacianSystem *sys);
@@ -93,28 +92,23 @@ static void memset_laplacian_system(LaplacianSystem *sys, int val);
static void volume_preservation(LaplacianSystem *sys, float vini, float vend, short flag);
static void validate_solution(LaplacianSystem *sys, short flag, float lambda, float lambda_border);
-static void delete_void_pointer(void *data)
-{
- if (data) {
- MEM_freeN(data);
- }
-}
-
static void delete_laplacian_system(LaplacianSystem *sys)
{
- delete_void_pointer(sys->eweights);
- delete_void_pointer(sys->fweights);
- delete_void_pointer(sys->numNeEd);
- delete_void_pointer(sys->numNeFa);
- delete_void_pointer(sys->ring_areas);
- delete_void_pointer(sys->vlengths);
- delete_void_pointer(sys->vweights);
- delete_void_pointer(sys->zerola);
+ MEM_SAFE_FREE(sys->eweights);
+ MEM_SAFE_FREE(sys->fweights);
+ MEM_SAFE_FREE(sys->numNeEd);
+ MEM_SAFE_FREE(sys->numNeFa);
+ MEM_SAFE_FREE(sys->ring_areas);
+ MEM_SAFE_FREE(sys->vlengths);
+ MEM_SAFE_FREE(sys->vweights);
+ MEM_SAFE_FREE(sys->zerola);
+
if (sys->context) {
nlDeleteContext(sys->context);
}
sys->vertexCos = NULL;
- sys->mfaces = NULL;
+ sys->mpoly = NULL;
+ sys->mloop = NULL;
sys->medges = NULL;
MEM_freeN(sys);
}
@@ -122,7 +116,7 @@ static void delete_laplacian_system(LaplacianSystem *sys)
static void memset_laplacian_system(LaplacianSystem *sys, int val)
{
memset(sys->eweights, val, sizeof(float) * sys->numEdges);
- memset(sys->fweights, val, sizeof(float) * sys->numFaces * 3);
+ memset(sys->fweights, val, sizeof(float[3]) * sys->numLoops);
memset(sys->numNeEd, val, sizeof(short) * sys->numVerts);
memset(sys->numNeFa, val, sizeof(short) * sys->numVerts);
memset(sys->ring_areas, val, sizeof(float) * sys->numVerts);
@@ -131,105 +125,54 @@ static void memset_laplacian_system(LaplacianSystem *sys, int val)
memset(sys->zerola, val, sizeof(short) * sys->numVerts);
}
-static LaplacianSystem *init_laplacian_system(int a_numEdges, int a_numFaces, int a_numVerts)
+static LaplacianSystem *init_laplacian_system(int a_numEdges, int a_numPolys, int a_numLoops, int a_numVerts)
{
LaplacianSystem *sys;
sys = MEM_callocN(sizeof(LaplacianSystem), "ModLaplSmoothSystem");
sys->numEdges = a_numEdges;
- sys->numFaces = a_numFaces;
+ sys->numPolys = a_numPolys;
+ sys->numLoops = a_numLoops;
sys->numVerts = a_numVerts;
- sys->eweights = MEM_callocN(sizeof(float) * sys->numEdges, "ModLaplSmoothEWeight");
- if (!sys->eweights) {
- delete_laplacian_system(sys);
- return NULL;
- }
-
- sys->fweights = MEM_callocN(sizeof(float) * 3 * sys->numFaces, "ModLaplSmoothFWeight");
- if (!sys->fweights) {
- delete_laplacian_system(sys);
- return NULL;
- }
-
- sys->numNeEd = MEM_callocN(sizeof(short) * sys->numVerts, "ModLaplSmoothNumNeEd");
- if (!sys->numNeEd) {
- delete_laplacian_system(sys);
- return NULL;
- }
-
- sys->numNeFa = MEM_callocN(sizeof(short) * sys->numVerts, "ModLaplSmoothNumNeFa");
- if (!sys->numNeFa) {
- delete_laplacian_system(sys);
- return NULL;
- }
-
- sys->ring_areas = MEM_callocN(sizeof(float) * sys->numVerts, "ModLaplSmoothRingAreas");
- if (!sys->ring_areas) {
- delete_laplacian_system(sys);
- return NULL;
- }
-
- sys->vlengths = MEM_callocN(sizeof(float) * sys->numVerts, "ModLaplSmoothVlengths");
- if (!sys->vlengths) {
- delete_laplacian_system(sys);
- return NULL;
- }
-
- sys->vweights = MEM_callocN(sizeof(float) * sys->numVerts, "ModLaplSmoothVweights");
- if (!sys->vweights) {
- delete_laplacian_system(sys);
- return NULL;
- }
-
- sys->zerola = MEM_callocN(sizeof(short) * sys->numVerts, "ModLaplSmoothZeloa");
- if (!sys->zerola) {
- delete_laplacian_system(sys);
- return NULL;
- }
+ sys->eweights = MEM_callocN(sizeof(float) * sys->numEdges, __func__);
+ sys->fweights = MEM_callocN(sizeof(float[3]) * sys->numLoops, __func__);
+ sys->numNeEd = MEM_callocN(sizeof(short) * sys->numVerts, __func__);
+ sys->numNeFa = MEM_callocN(sizeof(short) * sys->numVerts, __func__);
+ sys->ring_areas = MEM_callocN(sizeof(float) * sys->numVerts, __func__);
+ sys->vlengths = MEM_callocN(sizeof(float) * sys->numVerts, __func__);
+ sys->vweights = MEM_callocN(sizeof(float) * sys->numVerts, __func__);
+ sys->zerola = MEM_callocN(sizeof(short) * sys->numVerts, __func__);
return sys;
}
-static float average_area_quad_v3(float *v1, float *v2, float *v3, float *v4)
-{
- float areaq;
- areaq = area_tri_v3(v1, v2, v3) + area_tri_v3(v1, v2, v4) + area_tri_v3(v1, v3, v4);
- return areaq / 2.0f;
-}
-
-static float compute_volume(float (*vertexCos)[3], MFace *mfaces, int numFaces)
+static float compute_volume(
+ const float center[3], float (*vertexCos)[3],
+ const MPoly *mpoly, int numPolys, const MLoop *mloop)
{
- float vol = 0.0f;
- float x1, y1, z1, x2, y2, z2, x3, y3, z3, x4, y4, z4;
int i;
- float *vf[4];
- for (i = 0; i < numFaces; i++) {
- vf[0] = vertexCos[mfaces[i].v1];
- vf[1] = vertexCos[mfaces[i].v2];
- vf[2] = vertexCos[mfaces[i].v3];
-
- x1 = vf[0][0];
- y1 = vf[0][1];
- z1 = vf[0][2];
-
- x2 = vf[1][0];
- y2 = vf[1][1];
- z2 = vf[1][2];
-
- x3 = vf[2][0];
- y3 = vf[2][1];
- z3 = vf[2][2];
-
-
- vol += (1.0f / 6.0f) * (x2 * y3 * z1 + x3 * y1 * z2 - x1 * y3 * z2 - x2 * y1 * z3 + x1 * y2 * z3 - x3 * y2 * z1);
- if ((&mfaces[i])->v4) {
- vf[3] = vertexCos[mfaces[i].v4];
- x4 = vf[3][0];
- y4 = vf[3][1];
- z4 = vf[3][2];
- vol += (1.0f / 6.0f) * (x1 * y3 * z4 - x1 * y4 * z3 - x3 * y1 * z4 + x3 * z1 * y4 + y1 * x4 * z3 - x4 * y3 * z1);
+ float vol = 0.0f;
+
+ for (i = 0; i < numPolys; i++) {
+ const MPoly *mp = &mpoly[i];
+ const MLoop *l_first = &mloop[mp->loopstart];
+ const MLoop *l_prev = l_first + 1;
+ const MLoop *l_curr = l_first + 2;
+ const MLoop *l_term = l_first + mp->totloop;
+
+
+ for (;
+ l_curr != l_term;
+ l_prev = l_curr, l_curr++)
+ {
+ vol += volume_tetrahedron_signed_v3(
+ center,
+ vertexCos[l_first->v],
+ vertexCos[l_prev->v],
+ vertexCos[l_curr->v]);
}
}
+
return fabsf(vol);
}
@@ -257,12 +200,12 @@ static void volume_preservation(LaplacianSystem *sys, float vini, float vend, sh
static void init_laplacian_matrix(LaplacianSystem *sys)
{
- float *v1, *v2, *v3, *v4;
- float w1, w2, w3, w4;
+ float *v1, *v2;
+ float w1, w2, w3;
float areaf;
- int i, j;
- unsigned int idv1, idv2, idv3, idv4, idv[4];
- bool has_4_vert;
+ int i;
+ unsigned int idv1, idv2;
+
for (i = 0; i < sys->numEdges; i++) {
idv1 = sys->medges[i].v1;
idv2 = sys->medges[i].v2;
@@ -283,86 +226,46 @@ static void init_laplacian_matrix(LaplacianSystem *sys)
sys->eweights[i] = w1;
}
- for (i = 0; i < sys->numFaces; i++) {
- has_4_vert = ((&sys->mfaces[i])->v4) ? 1 : 0;
-
- idv1 = sys->mfaces[i].v1;
- idv2 = sys->mfaces[i].v2;
- idv3 = sys->mfaces[i].v3;
- idv4 = has_4_vert ? sys->mfaces[i].v4 : 0;
-
- sys->numNeFa[idv1] += 1;
- sys->numNeFa[idv2] += 1;
- sys->numNeFa[idv3] += 1;
- if (has_4_vert) sys->numNeFa[idv4] += 1;
- v1 = sys->vertexCos[idv1];
- v2 = sys->vertexCos[idv2];
- v3 = sys->vertexCos[idv3];
- v4 = has_4_vert ? sys->vertexCos[idv4] : NULL;
-
- if (has_4_vert) {
- areaf = area_quad_v3(v1, v2, v3, sys->vertexCos[sys->mfaces[i].v4]);
- }
- else {
- areaf = area_tri_v3(v1, v2, v3);
- }
- if (fabsf(areaf) < sys->min_area) {
- sys->zerola[idv1] = 1;
- sys->zerola[idv2] = 1;
- sys->zerola[idv3] = 1;
- if (has_4_vert) sys->zerola[idv4] = 1;
- }
-
- if (has_4_vert) {
- sys->ring_areas[idv1] += average_area_quad_v3(v1, v2, v3, v4);
- sys->ring_areas[idv2] += average_area_quad_v3(v2, v3, v4, v1);
- sys->ring_areas[idv3] += average_area_quad_v3(v3, v4, v1, v2);
- sys->ring_areas[idv4] += average_area_quad_v3(v4, v1, v2, v3);
- }
- else {
- sys->ring_areas[idv1] += areaf;
- sys->ring_areas[idv2] += areaf;
- sys->ring_areas[idv3] += areaf;
- }
+ for (i = 0; i < sys->numPolys; i++) {
+ const MPoly *mp = &sys->mpoly[i];
+ const MLoop *l_next = &sys->mloop[mp->loopstart];
+ const MLoop *l_term = l_next + mp->totloop;
+ const MLoop *l_prev = l_term - 2;
+ const MLoop *l_curr = l_term - 1;
- if (has_4_vert) {
+ for (;
+ l_next != l_term;
+ l_prev = l_curr, l_curr = l_next, l_next++)
+ {
+ const float *v_prev = sys->vertexCos[l_prev->v];
+ const float *v_curr = sys->vertexCos[l_curr->v];
+ const float *v_next = sys->vertexCos[l_next->v];
+ const unsigned int l_curr_index = l_curr - sys->mloop;
- idv[0] = idv1;
- idv[1] = idv2;
- idv[2] = idv3;
- idv[3] = idv4;
+ sys->numNeFa[l_curr->v] += 1;
- for (j = 0; j < 4; j++) {
- idv1 = idv[j];
- idv2 = idv[(j + 1) % 4];
- idv3 = idv[(j + 2) % 4];
- idv4 = idv[(j + 3) % 4];
+ areaf = area_tri_v3(v_prev, v_curr, v_next);
- v1 = sys->vertexCos[idv1];
- v2 = sys->vertexCos[idv2];
- v3 = sys->vertexCos[idv3];
- v4 = sys->vertexCos[idv4];
+ if (areaf < sys->min_area) {
+ sys->zerola[l_curr->v] = 1;
+ }
- w2 = cotangent_tri_weight_v3(v4, v1, v2) + cotangent_tri_weight_v3(v3, v1, v2);
- w3 = cotangent_tri_weight_v3(v2, v3, v1) + cotangent_tri_weight_v3(v4, v1, v3);
- w4 = cotangent_tri_weight_v3(v2, v4, v1) + cotangent_tri_weight_v3(v3, v4, v1);
+ sys->ring_areas[l_prev->v] += areaf;
+ sys->ring_areas[l_curr->v] += areaf;
+ sys->ring_areas[l_next->v] += areaf;
- sys->vweights[idv1] += (w2 + w3 + w4) / 4.0f;
- }
- }
- else {
- w1 = cotangent_tri_weight_v3(v1, v2, v3) / 2.0f;
- w2 = cotangent_tri_weight_v3(v2, v3, v1) / 2.0f;
- w3 = cotangent_tri_weight_v3(v3, v1, v2) / 2.0f;
+ w1 = cotangent_tri_weight_v3(v_curr, v_next, v_prev) / 2.0f;
+ w2 = cotangent_tri_weight_v3(v_next, v_prev, v_curr) / 2.0f;
+ w3 = cotangent_tri_weight_v3(v_prev, v_curr, v_next) / 2.0f;
- sys->fweights[i][0] = sys->fweights[i][0] + w1;
- sys->fweights[i][1] = sys->fweights[i][1] + w2;
- sys->fweights[i][2] = sys->fweights[i][2] + w3;
+ sys->fweights[l_curr_index][0] += w1;
+ sys->fweights[l_curr_index][1] += w2;
+ sys->fweights[l_curr_index][2] += w3;
- sys->vweights[idv1] = sys->vweights[idv1] + w2 + w3;
- sys->vweights[idv2] = sys->vweights[idv2] + w1 + w3;
- sys->vweights[idv3] = sys->vweights[idv3] + w1 + w2;
+ sys->vweights[l_curr->v] += w2 + w3;
+ sys->vweights[l_next->v] += w1 + w3;
+ sys->vweights[l_prev->v] += w1 + w2;
}
}
for (i = 0; i < sys->numEdges; i++) {
@@ -379,62 +282,34 @@ static void init_laplacian_matrix(LaplacianSystem *sys)
static void fill_laplacian_matrix(LaplacianSystem *sys)
{
- float *v1, *v2, *v3, *v4;
- float w2, w3, w4;
- int i, j;
- bool has_4_vert;
- unsigned int idv1, idv2, idv3, idv4, idv[4];
-
- for (i = 0; i < sys->numFaces; i++) {
- idv1 = sys->mfaces[i].v1;
- idv2 = sys->mfaces[i].v2;
- idv3 = sys->mfaces[i].v3;
- has_4_vert = ((&sys->mfaces[i])->v4) ? 1 : 0;
-
- if (has_4_vert) {
- idv[0] = sys->mfaces[i].v1;
- idv[1] = sys->mfaces[i].v2;
- idv[2] = sys->mfaces[i].v3;
- idv[3] = sys->mfaces[i].v4;
- for (j = 0; j < 4; j++) {
- idv1 = idv[j];
- idv2 = idv[(j + 1) % 4];
- idv3 = idv[(j + 2) % 4];
- idv4 = idv[(j + 3) % 4];
-
- v1 = sys->vertexCos[idv1];
- v2 = sys->vertexCos[idv2];
- v3 = sys->vertexCos[idv3];
- v4 = sys->vertexCos[idv4];
-
- w2 = cotangent_tri_weight_v3(v4, v1, v2) + cotangent_tri_weight_v3(v3, v1, v2);
- w3 = cotangent_tri_weight_v3(v2, v3, v1) + cotangent_tri_weight_v3(v4, v1, v3);
- w4 = cotangent_tri_weight_v3(v2, v4, v1) + cotangent_tri_weight_v3(v3, v4, v1);
-
- w2 = w2 / 4.0f;
- w3 = w3 / 4.0f;
- w4 = w4 / 4.0f;
-
- if (sys->numNeEd[idv1] == sys->numNeFa[idv1] && sys->zerola[idv1] == 0) {
- nlMatrixAdd(idv1, idv2, w2 * sys->vweights[idv1]);
- nlMatrixAdd(idv1, idv3, w3 * sys->vweights[idv1]);
- nlMatrixAdd(idv1, idv4, w4 * sys->vweights[idv1]);
- }
- }
- }
- else {
+ int i;
+ unsigned int idv1, idv2;
+
+ for (i = 0; i < sys->numPolys; i++) {
+ const MPoly *mp = &sys->mpoly[i];
+ const MLoop *l_next = &sys->mloop[mp->loopstart];
+ const MLoop *l_term = l_next + mp->totloop;
+ const MLoop *l_prev = l_term - 2;
+ const MLoop *l_curr = l_term - 1;
+
+ for (;
+ l_next != l_term;
+ l_prev = l_curr, l_curr = l_next, l_next++)
+ {
+ const unsigned int l_curr_index = l_curr - sys->mloop;
+
/* Is ring if number of faces == number of edges around vertice*/
- if (sys->numNeEd[idv1] == sys->numNeFa[idv1] && sys->zerola[idv1] == 0) {
- nlMatrixAdd(idv1, idv2, sys->fweights[i][2] * sys->vweights[idv1]);
- nlMatrixAdd(idv1, idv3, sys->fweights[i][1] * sys->vweights[idv1]);
+ if (sys->numNeEd[l_curr->v] == sys->numNeFa[l_curr->v] && sys->zerola[l_curr->v] == 0) {
+ nlMatrixAdd(l_curr->v, l_next->v, sys->fweights[l_curr_index][2] * sys->vweights[l_curr->v]);
+ nlMatrixAdd(l_curr->v, l_prev->v, sys->fweights[l_curr_index][1] * sys->vweights[l_curr->v]);
}
- if (sys->numNeEd[idv2] == sys->numNeFa[idv2] && sys->zerola[idv2] == 0) {
- nlMatrixAdd(idv2, idv1, sys->fweights[i][2] * sys->vweights[idv2]);
- nlMatrixAdd(idv2, idv3, sys->fweights[i][0] * sys->vweights[idv2]);
+ if (sys->numNeEd[l_next->v] == sys->numNeFa[l_next->v] && sys->zerola[l_next->v] == 0) {
+ nlMatrixAdd(l_next->v, l_curr->v, sys->fweights[l_curr_index][2] * sys->vweights[l_next->v]);
+ nlMatrixAdd(l_next->v, l_prev->v, sys->fweights[l_curr_index][0] * sys->vweights[l_next->v]);
}
- if (sys->numNeEd[idv3] == sys->numNeFa[idv3] && sys->zerola[idv3] == 0) {
- nlMatrixAdd(idv3, idv1, sys->fweights[i][1] * sys->vweights[idv3]);
- nlMatrixAdd(idv3, idv2, sys->fweights[i][0] * sys->vweights[idv3]);
+ if (sys->numNeEd[l_prev->v] == sys->numNeFa[l_prev->v] && sys->zerola[l_prev->v] == 0) {
+ nlMatrixAdd(l_prev->v, l_curr->v, sys->fweights[l_curr_index][1] * sys->vweights[l_prev->v]);
+ nlMatrixAdd(l_prev->v, l_next->v, sys->fweights[l_curr_index][0] * sys->vweights[l_prev->v]);
}
}
}
@@ -461,24 +336,24 @@ static void validate_solution(LaplacianSystem *sys, short flag, float lambda, fl
float vini, vend;
if (flag & MOD_LAPLACIANSMOOTH_PRESERVE_VOLUME) {
- vini = compute_volume(sys->vertexCos, sys->mfaces, sys->numFaces);
+ vini = compute_volume(sys->vert_centroid, sys->vertexCos, sys->mpoly, sys->numPolys, sys->mloop);
}
for (i = 0; i < sys->numVerts; i++) {
if (sys->zerola[i] == 0) {
lam = sys->numNeEd[i] == sys->numNeFa[i] ? (lambda >= 0.0f ? 1.0f : -1.0f) : (lambda_border >= 0.0f ? 1.0f : -1.0f);
if (flag & MOD_LAPLACIANSMOOTH_X) {
- sys->vertexCos[i][0] += lam * (nlGetVariable(0, i) - sys->vertexCos[i][0]);
+ sys->vertexCos[i][0] += lam * ((float)nlGetVariable(0, i) - sys->vertexCos[i][0]);
}
if (flag & MOD_LAPLACIANSMOOTH_Y) {
- sys->vertexCos[i][1] += lam * (nlGetVariable(1, i) - sys->vertexCos[i][1]);
+ sys->vertexCos[i][1] += lam * ((float)nlGetVariable(1, i) - sys->vertexCos[i][1]);
}
if (flag & MOD_LAPLACIANSMOOTH_Z) {
- sys->vertexCos[i][2] += lam * (nlGetVariable(2, i) - sys->vertexCos[i][2]);
+ sys->vertexCos[i][2] += lam * ((float)nlGetVariable(2, i) - sys->vertexCos[i][2]);
}
}
}
if (flag & MOD_LAPLACIANSMOOTH_PRESERVE_VOLUME) {
- vend = compute_volume(sys->vertexCos, sys->mfaces, sys->numFaces);
+ vend = compute_volume(sys->vert_centroid, sys->vertexCos, sys->mpoly, sys->numPolys, sys->mloop);
volume_preservation(sys, vini, vend, flag);
}
}
@@ -494,14 +369,13 @@ static void laplaciansmoothModifier_do(
int i, iter;
int defgrp_index;
- DM_ensure_tessface(dm);
-
- sys = init_laplacian_system(dm->getNumEdges(dm), dm->getNumTessFaces(dm), numVerts);
+ sys = init_laplacian_system(dm->getNumEdges(dm), dm->getNumPolys(dm), dm->getNumLoops(dm), numVerts);
if (!sys) {
return;
}
- sys->mfaces = dm->getTessFaceArray(dm);
+ sys->mpoly = dm->getPolyArray(dm);
+ sys->mloop = dm->getLoopArray(dm);
sys->medges = dm->getEdgeArray(dm);
sys->vertexCos = vertexCos;
sys->min_area = 0.00001f;
@@ -613,7 +487,7 @@ static void laplaciansmoothModifier_do(
LaplacianSmoothModifierData *smd, Object *ob, DerivedMesh *dm,
float (*vertexCos)[3], int numVerts)
{
- (void)smd, (void)ob, (void)dm, (void)vertexCos, (void)numVerts;
+ UNUSED_VARS(smd, ob, dm, vertexCos, numVerts);
}
#endif /* WITH_OPENNL */
@@ -717,6 +591,7 @@ ModifierTypeInfo modifierType_LaplacianSmooth = {
/* freeData */ NULL,
/* isDisabled */ is_disabled,
/* updateDepgraph */ NULL,
+ /* updateDepsgraph */ NULL,
/* dependsOnTime */ NULL,
/* dependsOnNormals */ NULL,
/* foreachObjectLink */ NULL,
diff --git a/source/blender/modifiers/intern/MOD_lattice.c b/source/blender/modifiers/intern/MOD_lattice.c
index e4a359a93e2..52a4f441b63 100644
--- a/source/blender/modifiers/intern/MOD_lattice.c
+++ b/source/blender/modifiers/intern/MOD_lattice.c
@@ -38,7 +38,6 @@
#include "DNA_object_types.h"
#include "BLI_utildefines.h"
-#include "BLI_string.h"
#include "BKE_cdderivedmesh.h"
#include "BKE_lattice.h"
@@ -93,6 +92,7 @@ static void foreachObjectLink(
}
static void updateDepgraph(ModifierData *md, DagForest *forest,
+ struct Main *UNUSED(bmain),
struct Scene *UNUSED(scene),
Object *UNUSED(ob),
DagNode *obNode)
@@ -107,6 +107,20 @@ static void updateDepgraph(ModifierData *md, DagForest *forest,
}
}
+static void updateDepsgraph(ModifierData *md,
+ struct Main *UNUSED(bmain),
+ struct Scene *UNUSED(scene),
+ Object *object,
+ struct DepsNodeHandle *node)
+{
+ LatticeModifierData *lmd = (LatticeModifierData *)md;
+ if (lmd->object != NULL) {
+ DEG_add_object_relation(node, lmd->object, DEG_OB_COMP_GEOMETRY, "Lattice Modifier");
+ DEG_add_object_relation(node, lmd->object, DEG_OB_COMP_TRANSFORM, "Lattice Modifier");
+ }
+ DEG_add_object_relation(node, object, DEG_OB_COMP_TRANSFORM, "Lattice Modifier");
+}
+
static void deformVerts(ModifierData *md, Object *ob,
DerivedMesh *derivedData,
float (*vertexCos)[3],
@@ -155,6 +169,7 @@ ModifierTypeInfo modifierType_Lattice = {
/* freeData */ NULL,
/* isDisabled */ isDisabled,
/* updateDepgraph */ updateDepgraph,
+ /* updateDepsgraph */ updateDepsgraph,
/* dependsOnTime */ NULL,
/* dependsOnNormals */ NULL,
/* foreachObjectLink */ foreachObjectLink,
diff --git a/source/blender/modifiers/intern/MOD_mask.c b/source/blender/modifiers/intern/MOD_mask.c
index 838336a8f8a..06fbab65d7b 100644
--- a/source/blender/modifiers/intern/MOD_mask.c
+++ b/source/blender/modifiers/intern/MOD_mask.c
@@ -50,8 +50,9 @@
#include "BKE_deform.h"
#include "depsgraph_private.h"
+#include "DEG_depsgraph_build.h"
-#include "MOD_util.h"
+#include "BLI_strict_flags.h"
static void copyData(ModifierData *md, ModifierData *target)
{
@@ -77,6 +78,7 @@ static void foreachObjectLink(
}
static void updateDepgraph(ModifierData *md, DagForest *forest,
+ struct Main *UNUSED(bmain),
struct Scene *UNUSED(scene),
Object *UNUSED(ob),
DagNode *obNode)
@@ -93,6 +95,22 @@ static void updateDepgraph(ModifierData *md, DagForest *forest,
}
}
+static void updateDepsgraph(ModifierData *md,
+ struct Main *UNUSED(bmain),
+ struct Scene *UNUSED(scene),
+ Object *UNUSED(ob),
+ struct DepsNodeHandle *node)
+{
+ MaskModifierData *mmd = (MaskModifierData *)md;
+ if (mmd->ob_arm) {
+ bArmature *arm = (bArmature *)mmd->ob_arm->data;
+ /* Tag relationship in depsgraph, but also on the armature. */
+ /* TODO(sergey): Is it a proper relation here? */
+ DEG_add_object_relation(node, mmd->ob_arm, DEG_OB_COMP_TRANSFORM, "Mask Modifier");
+ arm->flag |= ARM_HAS_VIZ_DEPS;
+ }
+}
+
static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
DerivedMesh *dm,
ModifierApplyFlag UNUSED(flag))
@@ -101,20 +119,21 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
const bool found_test = (mmd->flag & MOD_MASK_INV) == 0;
DerivedMesh *result = NULL;
GHash *vertHash = NULL, *edgeHash, *polyHash;
- GHashIterator *hashIter;
+ GHashIterator gh_iter;
MDeformVert *dvert, *dv;
int numPolys = 0, numLoops = 0, numEdges = 0, numVerts = 0;
int maxVerts, maxEdges, maxPolys;
int i;
- MPoly *mpoly;
- MLoop *mloop;
-
- MPoly *mpoly_new;
- MLoop *mloop_new;
- MEdge *medge_new;
- MVert *mvert_new;
+ const MVert *mvert_src;
+ const MEdge *medge_src;
+ const MPoly *mpoly_src;
+ const MLoop *mloop_src;
+ MPoly *mpoly_dst;
+ MLoop *mloop_dst;
+ MEdge *medge_dst;
+ MVert *mvert_dst;
int *loop_mapping;
@@ -150,7 +169,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
bDeformGroup *def;
bool *bone_select_array;
int bone_select_tot = 0;
- const int defbase_tot = BLI_countlist(&ob->defbase);
+ const int defbase_tot = BLI_listbase_count(&ob->defbase);
/* check that there is armature object with bones to use, otherwise return original mesh */
if (ELEM(NULL, oba, oba->pose, ob->defbase.first))
@@ -160,7 +179,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
* - each cell is a boolean saying whether bone corresponding to the ith group is selected
* - groups that don't match a bone are treated as not existing (along with the corresponding ungrouped verts)
*/
- bone_select_array = MEM_mallocN(defbase_tot * sizeof(char), "mask array");
+ bone_select_array = MEM_mallocN((size_t)defbase_tot * sizeof(char), "mask array");
for (i = 0, def = ob->defbase.first; def; def = def->next, i++) {
pchan = BKE_pose_channel_find_name(oba->pose, def->name);
@@ -176,7 +195,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
/* verthash gives mapping from original vertex indices to the new indices (including selected matches only)
* key = oldindex, value = newindex
*/
- vertHash = BLI_ghash_int_new("mask vert gh");
+ vertHash = BLI_ghash_int_new_ex("mask vert gh", (unsigned int)maxVerts);
/* add vertices which exist in vertexgroups into vertHash for filtering
* - dv = for each vertex, what vertexgroups does it belong to
@@ -219,7 +238,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
return dm;
/* hashes for quickly providing a mapping from old to new - use key=oldindex, value=newindex */
- vertHash = BLI_ghash_int_new("mask vert2 bh");
+ vertHash = BLI_ghash_int_new_ex("mask vert2 bh", (unsigned int)maxVerts);
/* add vertices which exist in vertexgroup into ghash for filtering */
for (i = 0, dv = dvert; i < maxVerts; i++, dv++) {
@@ -235,37 +254,39 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
}
/* hashes for quickly providing a mapping from old to new - use key=oldindex, value=newindex */
- edgeHash = BLI_ghash_int_new("mask ed2 gh");
- polyHash = BLI_ghash_int_new("mask fa2 gh");
-
- mpoly = dm->getPolyArray(dm);
- mloop = dm->getLoopArray(dm);
+ edgeHash = BLI_ghash_int_new_ex("mask ed2 gh", (unsigned int)maxEdges);
+ polyHash = BLI_ghash_int_new_ex("mask fa2 gh", (unsigned int)maxPolys);
+
+ mvert_src = dm->getVertArray(dm);
+ medge_src = dm->getEdgeArray(dm);
+ mpoly_src = dm->getPolyArray(dm);
+ mloop_src = dm->getLoopArray(dm);
- loop_mapping = MEM_callocN(sizeof(int) * maxPolys, "mask loopmap"); /* overalloc, assume all polys are seen */
+ /* overalloc, assume all polys are seen */
+ loop_mapping = MEM_mallocN(sizeof(int) * (size_t)maxPolys, "mask loopmap");
/* loop over edges and faces, and do the same thing to
* ensure that they only reference existing verts
*/
for (i = 0; i < maxEdges; i++) {
- MEdge me;
- dm->getEdge(dm, i, &me);
+ const MEdge *me = &medge_src[i];
/* only add if both verts will be in new mesh */
- if (BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(me.v1)) &&
- BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(me.v2)))
+ if (BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(me->v1)) &&
+ BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(me->v2)))
{
BLI_ghash_insert(edgeHash, SET_INT_IN_POINTER(i), SET_INT_IN_POINTER(numEdges));
numEdges++;
}
}
for (i = 0; i < maxPolys; i++) {
- MPoly *mp = &mpoly[i];
- MLoop *ml = mloop + mp->loopstart;
+ const MPoly *mp_src = &mpoly_src[i];
+ const MLoop *ml_src = &mloop_src[mp_src->loopstart];
bool ok = true;
int j;
- for (j = 0; j < mp->totloop; j++, ml++) {
- if (!BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(ml->v))) {
+ for (j = 0; j < mp_src->totloop; j++, ml_src++) {
+ if (!BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(ml_src->v))) {
ok = false;
break;
}
@@ -276,7 +297,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
BLI_ghash_insert(polyHash, SET_INT_IN_POINTER(i), SET_INT_IN_POINTER(numPolys));
loop_mapping[numPolys] = numLoops;
numPolys++;
- numLoops += mp->totloop;
+ numLoops += mp_src->totloop;
}
}
@@ -286,78 +307,64 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
*/
result = CDDM_from_template(dm, numVerts, numEdges, 0, numLoops, numPolys);
- mpoly_new = CDDM_get_polys(result);
- mloop_new = CDDM_get_loops(result);
- medge_new = CDDM_get_edges(result);
- mvert_new = CDDM_get_verts(result);
-
+ mpoly_dst = CDDM_get_polys(result);
+ mloop_dst = CDDM_get_loops(result);
+ medge_dst = CDDM_get_edges(result);
+ mvert_dst = CDDM_get_verts(result);
+
/* using ghash-iterators, map data into new mesh */
/* vertices */
- for (hashIter = BLI_ghashIterator_new(vertHash);
- BLI_ghashIterator_done(hashIter) == false;
- BLI_ghashIterator_step(hashIter))
- {
- MVert source;
- MVert *dest;
- int oldIndex = GET_INT_FROM_POINTER(BLI_ghashIterator_getKey(hashIter));
- int newIndex = GET_INT_FROM_POINTER(BLI_ghashIterator_getValue(hashIter));
+ GHASH_ITER (gh_iter, vertHash) {
+ const MVert *v_src;
+ MVert *v_dst;
+ const int i_src = GET_INT_FROM_POINTER(BLI_ghashIterator_getKey(&gh_iter));
+ const int i_dst = GET_INT_FROM_POINTER(BLI_ghashIterator_getValue(&gh_iter));
- dm->getVert(dm, oldIndex, &source);
- dest = &mvert_new[newIndex];
-
- DM_copy_vert_data(dm, result, oldIndex, newIndex, 1);
- *dest = source;
+ v_src = &mvert_src[i_src];
+ v_dst = &mvert_dst[i_dst];
+
+ *v_dst = *v_src;
+ DM_copy_vert_data(dm, result, i_src, i_dst, 1);
}
- BLI_ghashIterator_free(hashIter);
/* edges */
- for (hashIter = BLI_ghashIterator_new(edgeHash);
- BLI_ghashIterator_done(hashIter) == false;
- BLI_ghashIterator_step(hashIter))
- {
- MEdge source;
- MEdge *dest;
- int oldIndex = GET_INT_FROM_POINTER(BLI_ghashIterator_getKey(hashIter));
- int newIndex = GET_INT_FROM_POINTER(BLI_ghashIterator_getValue(hashIter));
+ GHASH_ITER (gh_iter, edgeHash) {
+ const MEdge *e_src;
+ MEdge *e_dst;
+ const int i_src = GET_INT_FROM_POINTER(BLI_ghashIterator_getKey(&gh_iter));
+ const int i_dst = GET_INT_FROM_POINTER(BLI_ghashIterator_getValue(&gh_iter));
- dm->getEdge(dm, oldIndex, &source);
- dest = &medge_new[newIndex];
-
- source.v1 = GET_INT_FROM_POINTER(BLI_ghash_lookup(vertHash, SET_INT_IN_POINTER(source.v1)));
- source.v2 = GET_INT_FROM_POINTER(BLI_ghash_lookup(vertHash, SET_INT_IN_POINTER(source.v2)));
-
- DM_copy_edge_data(dm, result, oldIndex, newIndex, 1);
- *dest = source;
+ e_src = &medge_src[i_src];
+ e_dst = &medge_dst[i_dst];
+
+ DM_copy_edge_data(dm, result, i_src, i_dst, 1);
+ *e_dst = *e_src;
+ e_dst->v1 = GET_UINT_FROM_POINTER(BLI_ghash_lookup(vertHash, SET_UINT_IN_POINTER(e_src->v1)));
+ e_dst->v2 = GET_UINT_FROM_POINTER(BLI_ghash_lookup(vertHash, SET_UINT_IN_POINTER(e_src->v2)));
}
- BLI_ghashIterator_free(hashIter);
/* faces */
- for (hashIter = BLI_ghashIterator_new(polyHash);
- BLI_ghashIterator_done(hashIter) == false;
- BLI_ghashIterator_step(hashIter))
- {
- int oldIndex = GET_INT_FROM_POINTER(BLI_ghashIterator_getKey(hashIter));
- int newIndex = GET_INT_FROM_POINTER(BLI_ghashIterator_getValue(hashIter));
- MPoly *source = &mpoly[oldIndex];
- MPoly *dest = &mpoly_new[newIndex];
- int oldLoopIndex = source->loopstart;
- int newLoopIndex = loop_mapping[newIndex];
- MLoop *source_loop = &mloop[oldLoopIndex];
- MLoop *dest_loop = &mloop_new[newLoopIndex];
+ GHASH_ITER (gh_iter, polyHash) {
+ const int i_src = GET_INT_FROM_POINTER(BLI_ghashIterator_getKey(&gh_iter));
+ const int i_dst = GET_INT_FROM_POINTER(BLI_ghashIterator_getValue(&gh_iter));
+ const MPoly *mp_src = &mpoly_src[i_src];
+ MPoly *mp_dst = &mpoly_dst[i_dst];
+ const int i_ml_src = mp_src->loopstart;
+ const int i_ml_dst = loop_mapping[i_dst];
+ const MLoop *ml_src = &mloop_src[i_ml_src];
+ MLoop *ml_dst = &mloop_dst[i_ml_dst];
- DM_copy_poly_data(dm, result, oldIndex, newIndex, 1);
- DM_copy_loop_data(dm, result, oldLoopIndex, newLoopIndex, source->totloop);
-
- *dest = *source;
- dest->loopstart = newLoopIndex;
- for (i = 0; i < source->totloop; i++) {
- dest_loop[i].v = GET_INT_FROM_POINTER(BLI_ghash_lookup(vertHash, SET_INT_IN_POINTER(source_loop[i].v)));
- dest_loop[i].e = GET_INT_FROM_POINTER(BLI_ghash_lookup(edgeHash, SET_INT_IN_POINTER(source_loop[i].e)));
+ DM_copy_poly_data(dm, result, i_src, i_dst, 1);
+ DM_copy_loop_data(dm, result, i_ml_src, i_ml_dst, mp_src->totloop);
+
+ *mp_dst = *mp_src;
+ mp_dst->loopstart = i_ml_dst;
+ for (i = 0; i < mp_src->totloop; i++) {
+ ml_dst[i].v = GET_UINT_FROM_POINTER(BLI_ghash_lookup(vertHash, SET_UINT_IN_POINTER(ml_src[i].v)));
+ ml_dst[i].e = GET_UINT_FROM_POINTER(BLI_ghash_lookup(edgeHash, SET_UINT_IN_POINTER(ml_src[i].e)));
}
}
- BLI_ghashIterator_free(hashIter);
-
MEM_freeN(loop_mapping);
/* why is this needed? - campbell */
@@ -395,6 +402,7 @@ ModifierTypeInfo modifierType_Mask = {
/* freeData */ NULL,
/* isDisabled */ NULL,
/* updateDepgraph */ updateDepgraph,
+ /* updateDepsgraph */ updateDepsgraph,
/* dependsOnTime */ NULL,
/* dependsOnNormals */ NULL,
/* foreachObjectLink */ foreachObjectLink,
diff --git a/source/blender/modifiers/intern/MOD_meshcache.c b/source/blender/modifiers/intern/MOD_meshcache.c
index 925d9691892..92926ed9424 100644
--- a/source/blender/modifiers/intern/MOD_meshcache.c
+++ b/source/blender/modifiers/intern/MOD_meshcache.c
@@ -48,8 +48,6 @@
#include "MOD_modifiertypes.h"
-#include "MOD_util.h"
-
static void initData(ModifierData *md)
{
MeshCacheModifierData *mcmd = (MeshCacheModifierData *)md;
@@ -315,6 +313,7 @@ ModifierTypeInfo modifierType_MeshCache = {
/* freeData */ NULL,
/* isDisabled */ isDisabled,
/* updateDepgraph */ NULL,
+ /* updateDepsgraph */ NULL,
/* dependsOnTime */ dependsOnTime,
/* dependsOnNormals */ NULL,
/* foreachObjectLink */ NULL,
diff --git a/source/blender/modifiers/intern/MOD_meshcache_pc2.c b/source/blender/modifiers/intern/MOD_meshcache_pc2.c
index 3ef0ee54886..219eae4ecca 100644
--- a/source/blender/modifiers/intern/MOD_meshcache_pc2.c
+++ b/source/blender/modifiers/intern/MOD_meshcache_pc2.c
@@ -31,7 +31,6 @@
#include "BLI_sys_types.h"
#include "BLI_utildefines.h"
#include "BLI_fileops.h"
-#include "BLI_math.h"
#ifdef __BIG_ENDIAN__
# include "BLI_endian_switch.h"
#endif
@@ -58,7 +57,7 @@ static bool meshcache_read_pc2_head(FILE *fp, const int verts_tot,
return false;
}
- if (strcmp(pc2_head->header, "POINTCACHE2") != 0) {
+ if (!STREQ(pc2_head->header, "POINTCACHE2")) {
*err_str = "Invalid header";
return false;
}
diff --git a/source/blender/modifiers/intern/MOD_meshcache_util.h b/source/blender/modifiers/intern/MOD_meshcache_util.h
index f3b5f43009d..241806f49e1 100644
--- a/source/blender/modifiers/intern/MOD_meshcache_util.h
+++ b/source/blender/modifiers/intern/MOD_meshcache_util.h
@@ -27,8 +27,6 @@
#ifndef __MOD_MESHCACHE_UTIL_H__
#define __MOD_MESHCACHE_UTIL_H__
-struct MPoly;
-struct MLoop;
/* MOD_meshcache_mdd.c */
bool MOD_meshcache_read_mdd_index(FILE *fp,
diff --git a/source/blender/modifiers/intern/MOD_meshdeform.c b/source/blender/modifiers/intern/MOD_meshdeform.c
index 959bbdcbca9..5bd33d2a49f 100644
--- a/source/blender/modifiers/intern/MOD_meshdeform.c
+++ b/source/blender/modifiers/intern/MOD_meshdeform.c
@@ -37,10 +37,9 @@
#include "DNA_scene_types.h"
#include "BLI_math.h"
+#include "BLI_task.h"
#include "BLI_utildefines.h"
-#include "BLF_translation.h"
-
#include "BKE_cdderivedmesh.h"
#include "BKE_global.h"
#include "BKE_modifier.h"
@@ -53,6 +52,9 @@
#include "MOD_util.h"
+#ifdef __SSE2__
+# include <emmintrin.h>
+#endif
static void initData(ModifierData *md)
{
@@ -80,9 +82,16 @@ static void copyData(ModifierData *md, ModifierData *target)
MeshDeformModifierData *mmd = (MeshDeformModifierData *) md;
MeshDeformModifierData *tmmd = (MeshDeformModifierData *) target;
- tmmd->gridsize = mmd->gridsize;
- tmmd->flag = mmd->flag;
- tmmd->object = mmd->object;
+ *tmmd = *mmd;
+
+ if (mmd->bindinfluences) tmmd->bindinfluences = MEM_dupallocN(mmd->bindinfluences);
+ if (mmd->bindoffsets) tmmd->bindoffsets = MEM_dupallocN(mmd->bindoffsets);
+ if (mmd->bindcagecos) tmmd->bindcagecos = MEM_dupallocN(mmd->bindcagecos);
+ if (mmd->dyngrid) tmmd->dyngrid = MEM_dupallocN(mmd->dyngrid);
+ if (mmd->dyninfluences) tmmd->dyninfluences = MEM_dupallocN(mmd->dyninfluences);
+ if (mmd->dynverts) tmmd->dynverts = MEM_dupallocN(mmd->dynverts);
+ if (mmd->bindweights) tmmd->dynverts = MEM_dupallocN(mmd->bindweights); /* deprecated */
+ if (mmd->bindcos) tmmd->dynverts = MEM_dupallocN(mmd->bindcos); /* deprecated */
}
static CustomDataMask requiredDataMask(Object *UNUSED(ob), ModifierData *md)
@@ -114,6 +123,7 @@ static void foreachObjectLink(
}
static void updateDepgraph(ModifierData *md, DagForest *forest,
+ struct Main *UNUSED(bmain),
struct Scene *UNUSED(scene),
Object *UNUSED(ob),
DagNode *obNode)
@@ -129,15 +139,32 @@ static void updateDepgraph(ModifierData *md, DagForest *forest,
}
}
+static void updateDepsgraph(ModifierData *md,
+ struct Main *UNUSED(bmain),
+ struct Scene *UNUSED(scene),
+ Object *UNUSED(ob),
+ struct DepsNodeHandle *node)
+{
+ MeshDeformModifierData *mmd = (MeshDeformModifierData *)md;
+ if (mmd->object != NULL) {
+ /* TODO(sergey): Do we need transform component here? */
+ DEG_add_object_relation(node, mmd->object, DEG_OB_COMP_GEOMETRY, "Mesh Deform Modifier");
+ }
+}
+
static float meshdeform_dynamic_bind(MeshDeformModifierData *mmd, float (*dco)[3], float vec[3])
{
MDefCell *cell;
MDefInfluence *inf;
- float gridvec[3], dvec[3], ivec[3], co[3], wx, wy, wz;
+ float gridvec[3], dvec[3], ivec[3], wx, wy, wz;
float weight, cageweight, totweight, *cageco;
int i, j, a, x, y, z, size;
+#ifdef __SSE2__
+ __m128 co = _mm_setzero_ps();
+#else
+ float co[3] = {0.0f, 0.0f, 0.0f};
+#endif
- zero_v3(co);
totweight = 0.0f;
size = mmd->dyngridsize;
@@ -169,18 +196,100 @@ static float meshdeform_dynamic_bind(MeshDeformModifierData *mmd, float (*dco)[3
for (j = 0; j < cell->totinfluence; j++, inf++) {
cageco = dco[inf->vertex];
cageweight = weight * inf->weight;
+#ifdef __SSE2__
+ {
+ __m128 cageweight_r = _mm_set1_ps(cageweight);
+ /* This will load one extra element, this is ok because
+ * we ignore that part of register anyway.
+ */
+ __m128 cageco_r = _mm_loadu_ps(cageco);
+ co = _mm_add_ps(co,
+ _mm_mul_ps(cageco_r, cageweight_r));
+ }
+#else
co[0] += cageweight * cageco[0];
co[1] += cageweight * cageco[1];
co[2] += cageweight * cageco[2];
+#endif
totweight += cageweight;
}
}
+#ifdef __SSE2__
+ copy_v3_v3(vec, (float *)&co);
+#else
copy_v3_v3(vec, co);
+#endif
return totweight;
}
+typedef struct MeshdeformUserdata {
+ /*const*/ MeshDeformModifierData *mmd;
+ const MDeformVert *dvert;
+ /*const*/ float (*dco)[3];
+ int defgrp_index;
+ float (*vertexCos)[3];
+ float (*cagemat)[4];
+ float (*icagemat)[3];
+} MeshdeformUserdata;
+
+static void meshdeform_vert_task(void * userdata, int iter)
+{
+ MeshdeformUserdata *data = userdata;
+ /*const*/ MeshDeformModifierData *mmd = data->mmd;
+ const MDeformVert *dvert = data->dvert;
+ const int defgrp_index = data->defgrp_index;
+ const int *offsets = mmd->bindoffsets;
+ const MDefInfluence *influences = mmd->bindinfluences;
+ /*const*/ float (*dco)[3] = data->dco;
+ float (*vertexCos)[3] = data->vertexCos;
+ float co[3];
+ float weight, totweight, fac = 1.0f;
+
+ if (mmd->flag & MOD_MDEF_DYNAMIC_BIND)
+ if (!mmd->dynverts[iter])
+ return;
+
+ if (dvert) {
+ fac = defvert_find_weight(&dvert[iter], defgrp_index);
+
+ if (mmd->flag & MOD_MDEF_INVERT_VGROUP) {
+ fac = 1.0f - fac;
+ }
+
+ if (fac <= 0.0f) {
+ return;
+ }
+ }
+
+ if (mmd->flag & MOD_MDEF_DYNAMIC_BIND) {
+ /* transform coordinate into cage's local space */
+ mul_v3_m4v3(co, data->cagemat, vertexCos[iter]);
+ totweight = meshdeform_dynamic_bind(mmd, dco, co);
+ }
+ else {
+ int a;
+ totweight = 0.0f;
+ zero_v3(co);
+
+ for (a = offsets[iter]; a < offsets[iter + 1]; a++) {
+ weight = influences[a].weight;
+ madd_v3_v3fl(co, dco[influences[a].vertex], weight);
+ totweight += weight;
+ }
+ }
+
+ if (totweight > 0.0f) {
+ mul_v3_fl(co, fac / totweight);
+ mul_m3_v3(data->icagemat, co);
+ if (G.debug_value != 527)
+ add_v3_v3(vertexCos[iter], co);
+ else
+ copy_v3_v3(vertexCos[iter], co);
+ }
+}
+
static void meshdeformModifier_do(
ModifierData *md, Object *ob, DerivedMesh *dm,
float (*vertexCos)[3], int numVerts)
@@ -188,12 +297,11 @@ static void meshdeformModifier_do(
MeshDeformModifierData *mmd = (MeshDeformModifierData *) md;
DerivedMesh *tmpdm, *cagedm;
MDeformVert *dvert = NULL;
- MDefInfluence *influences;
- const int *offsets;
float imat[4][4], cagemat[4][4], iobmat[4][4], icagemat[3][3], cmat[4][4];
- float weight, totweight, fac, co[3], (*dco)[3], (*bindcagecos)[3];
- int a, b, totvert, totcagevert, defgrp_index;
+ float co[3], (*dco)[3], (*bindcagecos)[3];
+ int a, totvert, totcagevert, defgrp_index;
float (*cagecos)[3];
+ MeshdeformUserdata data;
if (!mmd->object || (!mmd->bindcagecos && !mmd->bindfunc))
return;
@@ -210,7 +318,7 @@ static void meshdeformModifier_do(
*/
if (mmd->object == md->scene->obedit) {
BMEditMesh *em = BKE_editmesh_from_object(mmd->object);
- tmpdm = editbmesh_get_derived_cage_and_final(md->scene, mmd->object, em, &cagedm, 0);
+ tmpdm = editbmesh_get_derived_cage_and_final(md->scene, mmd->object, em, 0, &cagedm);
if (tmpdm)
tmpdm->release(tmpdm);
}
@@ -273,11 +381,13 @@ static void meshdeformModifier_do(
/* setup deformation data */
cagedm->getVertCos(cagedm, cagecos);
- influences = mmd->bindinfluences;
- offsets = mmd->bindoffsets;
bindcagecos = (float(*)[3])mmd->bindcagecos;
- dco = MEM_callocN(sizeof(*dco) * totcagevert, "MDefDco");
+ /* We allocate 1 element extra to make it possible to
+ * load the values to SSE registers, which are float4.
+ */
+ dco = MEM_callocN(sizeof(*dco) * (totcagevert + 1), "MDefDco");
+ zero_v3(dco[totcagevert]);
for (a = 0; a < totcagevert; a++) {
/* get cage vertex in world space with binding transform */
copy_v3_v3(co, cagecos[a]);
@@ -293,51 +403,17 @@ static void meshdeformModifier_do(
modifier_get_vgroup(ob, dm, mmd->defgrp_name, &dvert, &defgrp_index);
- /* do deformation */
- fac = 1.0f;
-
- for (b = 0; b < totvert; b++) {
- if (mmd->flag & MOD_MDEF_DYNAMIC_BIND)
- if (!mmd->dynverts[b])
- continue;
-
- if (dvert) {
- fac = defvert_find_weight(&dvert[b], defgrp_index);
-
- if (mmd->flag & MOD_MDEF_INVERT_VGROUP) {
- fac = 1.0f - fac;
- }
-
- if (fac <= 0.0f) {
- continue;
- }
- }
-
- if (mmd->flag & MOD_MDEF_DYNAMIC_BIND) {
- /* transform coordinate into cage's local space */
- mul_v3_m4v3(co, cagemat, vertexCos[b]);
- totweight = meshdeform_dynamic_bind(mmd, dco, co);
- }
- else {
- totweight = 0.0f;
- zero_v3(co);
-
- for (a = offsets[b]; a < offsets[b + 1]; a++) {
- weight = influences[a].weight;
- madd_v3_v3fl(co, dco[influences[a].vertex], weight);
- totweight += weight;
- }
- }
+ /* Initialize data to be pass to the for body function. */
+ data.mmd = mmd;
+ data.dvert = dvert;
+ data.dco = dco;
+ data.defgrp_index = defgrp_index;
+ data.vertexCos = vertexCos;
+ data.cagemat = cagemat;
+ data.icagemat = icagemat;
- if (totweight > 0.0f) {
- mul_v3_fl(co, fac / totweight);
- mul_m3_v3(icagemat, co);
- if (G.debug_value != 527)
- add_v3_v3(vertexCos[b], co);
- else
- copy_v3_v3(vertexCos[b], co);
- }
- }
+ /* Do deformation. */
+ BLI_task_parallel_range(0, totvert, &data, meshdeform_vert_task);
/* release cage derivedmesh */
MEM_freeN(dco);
@@ -458,6 +534,7 @@ ModifierTypeInfo modifierType_MeshDeform = {
/* freeData */ freeData,
/* isDisabled */ isDisabled,
/* updateDepgraph */ updateDepgraph,
+ /* updateDepsgraph */ updateDepsgraph,
/* dependsOnTime */ NULL,
/* dependsOnNormals */ NULL,
/* foreachObjectLink */ foreachObjectLink,
diff --git a/source/blender/modifiers/intern/MOD_mirror.c b/source/blender/modifiers/intern/MOD_mirror.c
index 5de4a76dcbe..3e10fa1d77d 100644
--- a/source/blender/modifiers/intern/MOD_mirror.c
+++ b/source/blender/modifiers/intern/MOD_mirror.c
@@ -42,10 +42,10 @@
#include "BKE_modifier.h"
#include "BKE_deform.h"
-#include "bmesh.h"
-
#include "MEM_guardedalloc.h"
+
#include "depsgraph_private.h"
+#include "DEG_depsgraph_build.h"
static void initData(ModifierData *md)
{
@@ -75,6 +75,7 @@ static void foreachObjectLink(ModifierData *md, Object *ob,
}
static void updateDepgraph(ModifierData *md, DagForest *forest,
+ struct Main *UNUSED(bmain),
struct Scene *UNUSED(scene),
Object *UNUSED(ob),
DagNode *obNode)
@@ -84,9 +85,21 @@ static void updateDepgraph(ModifierData *md, DagForest *forest,
if (mmd->mirror_ob) {
DagNode *latNode = dag_get_node(forest, mmd->mirror_ob);
- dag_add_relation(forest, latNode, obNode,
- DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Mirror Modifier");
+ dag_add_relation(forest, latNode, obNode, DAG_RL_OB_DATA, "Mirror Modifier");
+ }
+}
+
+static void updateDepsgraph(ModifierData *md,
+ struct Main *UNUSED(bmain),
+ struct Scene *UNUSED(scene),
+ Object *ob,
+ struct DepsNodeHandle *node)
+{
+ MirrorModifierData *mmd = (MirrorModifierData *)md;
+ if (mmd->mirror_ob != NULL) {
+ DEG_add_object_relation(node, mmd->mirror_ob, DEG_OB_COMP_TRANSFORM, "Mirror Modifier");
}
+ DEG_add_object_relation(node, ob, DEG_OB_COMP_TRANSFORM, "Mirror Modifier");
}
static DerivedMesh *doMirrorOnAxis(MirrorModifierData *mmd,
@@ -95,7 +108,7 @@ static DerivedMesh *doMirrorOnAxis(MirrorModifierData *mmd,
int axis)
{
const float tolerance_sq = mmd->tolerance * mmd->tolerance;
- const int do_vtargetmap = !(mmd->flag & MOD_MIR_NO_MERGE);
+ const bool do_vtargetmap = (mmd->flag & MOD_MIR_NO_MERGE) == 0;
int tot_vtargetmap = 0; /* total merge vertices */
DerivedMesh *result;
@@ -362,6 +375,7 @@ ModifierTypeInfo modifierType_Mirror = {
/* freeData */ NULL,
/* isDisabled */ NULL,
/* updateDepgraph */ updateDepgraph,
+ /* updateDepsgraph */ updateDepsgraph,
/* dependsOnTime */ NULL,
/* dependsOnNormals */ NULL,
/* foreachObjectLink */ foreachObjectLink,
diff --git a/source/blender/modifiers/intern/MOD_multires.c b/source/blender/modifiers/intern/MOD_multires.c
index deae10b5bcb..90ad1bdfdc2 100644
--- a/source/blender/modifiers/intern/MOD_multires.c
+++ b/source/blender/modifiers/intern/MOD_multires.c
@@ -44,11 +44,8 @@
#include "BKE_mesh.h"
#include "BKE_multires.h"
#include "BKE_modifier.h"
-#include "BKE_paint.h"
#include "BKE_subsurf.h"
-#include "MOD_util.h"
-
static void initData(ModifierData *md)
{
MultiresModifierData *mmd = (MultiresModifierData *)md;
@@ -165,6 +162,7 @@ ModifierTypeInfo modifierType_Multires = {
/* freeData */ NULL,
/* isDisabled */ NULL,
/* updateDepgraph */ NULL,
+ /* updateDepsgraph */ NULL,
/* dependsOnTime */ NULL,
/* dependsOnNormals */ NULL,
/* foreachObjectLink */ NULL,
diff --git a/source/blender/modifiers/intern/MOD_none.c b/source/blender/modifiers/intern/MOD_none.c
index 579f65a9c50..d9d9ba2966d 100644
--- a/source/blender/modifiers/intern/MOD_none.c
+++ b/source/blender/modifiers/intern/MOD_none.c
@@ -68,6 +68,7 @@ ModifierTypeInfo modifierType_None = {
/* freeData */ NULL,
/* isDisabled */ isDisabled,
/* updateDepgraph */ NULL,
+ /* updateDepsgraph */ NULL,
/* dependsOnTime */ NULL,
/* dependsOnNormals */ NULL,
/* foreachObjectLink */ NULL,
diff --git a/source/blender/modifiers/intern/MOD_normal_edit.c b/source/blender/modifiers/intern/MOD_normal_edit.c
new file mode 100644
index 00000000000..87d75c6f1a7
--- /dev/null
+++ b/source/blender/modifiers/intern/MOD_normal_edit.c
@@ -0,0 +1,529 @@
+/*
+ * ***** 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): Bastien Montagne
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ *
+ */
+
+/** \file blender/modifiers/intern/MOD_normal_edit.c
+ * \ingroup modifiers
+ */
+
+#include <string.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_object_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_mesh_types.h"
+
+#include "BLI_math.h"
+#include "BLI_utildefines.h"
+#include "BLI_bitmap.h"
+
+#include "BKE_cdderivedmesh.h"
+#include "BKE_mesh.h"
+#include "BKE_deform.h"
+
+#include "depsgraph_private.h"
+
+#include "MOD_util.h"
+
+
+static void generate_vert_coordinates(
+ DerivedMesh *dm, Object *ob, Object *ob_center, const float offset[3],
+ const int num_verts, float (*r_cos)[3], float r_size[3])
+{
+ float min_co[3], max_co[3];
+ float diff[3];
+ bool do_diff = false;
+
+ INIT_MINMAX(min_co, max_co);
+
+ dm->getVertCos(dm, r_cos);
+
+ /* Get size (i.e. deformation of the spheroid generating normals), either from target object, or own geometry. */
+ if (ob_center) {
+ /* Not we are not interested in signs here - they are even troublesome actually, due to security clamping! */
+ abs_v3_v3(r_size, ob_center->size);
+ }
+ else {
+ minmax_v3v3_v3_array(min_co, max_co, r_cos, num_verts);
+ /* Set size. */
+ sub_v3_v3v3(r_size, max_co, min_co);
+ }
+
+ /* Error checks - we do not want one or more of our sizes to be null! */
+ if (is_zero_v3(r_size)) {
+ r_size[0] = r_size[1] = r_size[2] = 1.0f;
+ }
+ else {
+ CLAMP_MIN(r_size[0], FLT_EPSILON);
+ CLAMP_MIN(r_size[1], FLT_EPSILON);
+ CLAMP_MIN(r_size[2], FLT_EPSILON);
+ }
+
+ if (ob_center) {
+ float inv_obmat[4][4];
+
+ /* Translate our coordinates so that center of ob_center is at (0, 0, 0). */
+ /* Get ob_center (world) coordinates in ob local coordinates.
+ * No need to take into accound ob_center's space here, see T44027. */
+ invert_m4_m4(inv_obmat, ob->obmat);
+ mul_v3_m4v3(diff, inv_obmat, ob_center->obmat[3]);
+ negate_v3(diff);
+
+ do_diff = true;
+ }
+ else if (!is_zero_v3(offset)) {
+ negate_v3_v3(diff, offset);
+
+ do_diff = true;
+ }
+ /* Else, no need to change coordinates! */
+
+ if (do_diff) {
+ int i = num_verts;
+ while (i--) {
+ add_v3_v3(r_cos[i], diff);
+ }
+ }
+}
+
+/* Note this modifies nos_new in-place. */
+static void mix_normals(
+ const float mix_factor, MDeformVert *dvert, const int defgrp_index, const bool use_invert_vgroup,
+ const short mix_mode,
+ const int num_verts, MLoop *mloop, float (*nos_old)[3], float (*nos_new)[3], const int num_loops)
+{
+ /* Mix with org normals... */
+ float *facs = NULL, *wfac;
+ float (*no_new)[3], (*no_old)[3];
+ int i;
+
+ if (dvert) {
+ facs = MEM_mallocN(sizeof(*facs) * (size_t)num_loops, __func__);
+ BKE_defvert_extract_vgroup_to_loopweights(
+ dvert, defgrp_index, num_verts, mloop, num_loops, facs, use_invert_vgroup);
+ }
+
+ for (i = num_loops, no_new = nos_new, no_old = nos_old, wfac = facs; i--; no_new++, no_old++, wfac++) {
+ const float fac = facs ? *wfac * mix_factor : mix_factor;
+
+ switch (mix_mode) {
+ case MOD_NORMALEDIT_MIX_ADD:
+ add_v3_v3(*no_new, *no_old);
+ normalize_v3(*no_new);
+ break;
+ case MOD_NORMALEDIT_MIX_SUB:
+ sub_v3_v3(*no_new, *no_old);
+ normalize_v3(*no_new);
+ break;
+ case MOD_NORMALEDIT_MIX_MUL:
+ mul_v3_v3(*no_new, *no_old);
+ normalize_v3(*no_new);
+ break;
+ case MOD_NORMALEDIT_MIX_COPY:
+ break;
+ }
+ interp_v3_v3v3_slerp_safe(*no_new, *no_old, *no_new, fac);
+ }
+
+ MEM_SAFE_FREE(facs);
+}
+
+static void normalEditModifier_do_radial(
+ NormalEditModifierData *smd, Object *ob, DerivedMesh *dm,
+ short (*clnors)[2], float (*loopnors)[3], float (*polynors)[3],
+ const short mix_mode, const float mix_factor,
+ MDeformVert *dvert, const int defgrp_index, const bool use_invert_vgroup,
+ MVert *mvert, const int num_verts, MEdge *medge, const int num_edges,
+ MLoop *mloop, const int num_loops, MPoly *mpoly, const int num_polys)
+{
+ int i;
+
+ float (*cos)[3] = MEM_mallocN(sizeof(*cos) * num_verts, __func__);
+ float (*nos)[3] = MEM_mallocN(sizeof(*nos) * num_loops, __func__);
+ float size[3];
+
+ BLI_bitmap *done_verts = BLI_BITMAP_NEW((size_t)num_verts, __func__);
+
+ generate_vert_coordinates(dm, ob, smd->target, smd->offset, num_verts, cos, size);
+
+ /**
+ * size gives us our spheroid coefficients ``(A, B, C)``.
+ * Then, we want to find out for each vert its (a, b, c) triple (proportional to (A, B, C) one).
+ *
+ * Ellipsoid basic equation: ``(x^2/a^2) + (y^2/b^2) + (z^2/c^2) = 1.``
+ * Since we want to find (a, b, c) matching this equation and proportional to (A, B, C), we can do:
+ * <pre>
+ * m = B / A
+ * n = C / A
+ * </pre>
+ *
+ * hence:
+ * <pre>
+ * (x^2/a^2) + (y^2/b^2) + (z^2/c^2) = 1
+ * -> b^2*c^2*x^2 + a^2*c^2*y^2 + a^2*b^2*z^2 = a^2*b^2*c^2
+ * b = ma
+ * c = na
+ * -> m^2*a^2*n^2*a^2*x^2 + a^2*n^2*a^2*y^2 + a^2*m^2*a^2*z^2 = a^2*m^2*a^2*n^2*a^2
+ * -> m^2*n^2*a^4*x^2 + n^2*a^4*y^2 + m^2*a^4*z^2 = m^2*n^2*a^6
+ * -> a^2 = (m^2*n^2*x^2 + n^2y^2 + m^2z^2) / (m^2*n^2) = x^2 + (y^2 / m^2) + (z^2 / n^2)
+ * -> b^2 = (m^2*n^2*x^2 + n^2y^2 + m^2z^2) / (n^2) = (m^2 * x^2) + y^2 + (m^2 * z^2 / n^2)
+ * -> c^2 = (m^2*n^2*x^2 + n^2y^2 + m^2z^2) / (m^2) = (n^2 * x^2) + (n^2 * y^2 / m^2) + z^2
+ * </pre>
+ *
+ * All we have to do now is compute normal of the spheroid at that point:
+ * <pre>
+ * n = (x / a^2, y / b^2, z / c^2)
+ * </pre>
+ * And we are done!
+ */
+ {
+ const float a = size[0], b = size[1], c = size[2];
+ const float m2 = (b * b) / (a * a);
+ const float n2 = (c * c) / (a * a);
+
+ MLoop *ml;
+ float (*no)[3];
+
+ /* We reuse cos to now store the ellipsoid-normal of the verts! */
+ for (i = num_loops, ml = mloop, no = nos; i-- ; ml++, no++) {
+ const int vidx = ml->v;
+ float *co = cos[vidx];
+
+ if (!BLI_BITMAP_TEST(done_verts, vidx)) {
+ const float x2 = co[0] * co[0];
+ const float y2 = co[1] * co[1];
+ const float z2 = co[2] * co[2];
+ const float a2 = x2 + (y2 / m2) + (z2 / n2);
+ const float b2 = (m2 * x2) + y2 + (m2 * z2 / n2);
+ const float c2 = (n2 * x2) + (n2 * y2 / m2) + z2;
+
+ co[0] /= a2;
+ co[1] /= b2;
+ co[2] /= c2;
+ normalize_v3(co);
+
+ BLI_BITMAP_ENABLE(done_verts, vidx);
+ }
+ copy_v3_v3(*no, co);
+ }
+ }
+
+ if (loopnors) {
+ mix_normals(mix_factor, dvert, defgrp_index, use_invert_vgroup,
+ mix_mode, num_verts, mloop, loopnors, nos, num_loops);
+ }
+
+ BKE_mesh_normals_loop_custom_set(mvert, num_verts, medge, num_edges, mloop, nos, num_loops,
+ mpoly, (const float(*)[3])polynors, num_polys, clnors);
+
+ MEM_freeN(cos);
+ MEM_freeN(nos);
+ MEM_freeN(done_verts);
+}
+
+static void normalEditModifier_do_directional(
+ NormalEditModifierData *smd, Object *ob, DerivedMesh *dm,
+ short (*clnors)[2], float (*loopnors)[3], float (*polynors)[3],
+ const short mix_mode, const float mix_factor,
+ MDeformVert *dvert, const int defgrp_index, const bool use_invert_vgroup,
+ MVert *mvert, const int num_verts, MEdge *medge, const int num_edges,
+ MLoop *mloop, const int num_loops, MPoly *mpoly, const int num_polys)
+{
+ const bool use_parallel_normals = (smd->flag & MOD_NORMALEDIT_USE_DIRECTION_PARALLEL) != 0;
+
+ float (*cos)[3] = MEM_mallocN(sizeof(*cos) * num_verts, __func__);
+ float (*nos)[3] = MEM_mallocN(sizeof(*nos) * num_loops, __func__);
+
+ float target_co[3];
+ int i;
+
+ dm->getVertCos(dm, cos);
+
+ /* Get target's center coordinates in ob local coordinates. */
+ {
+ float mat[4][4];
+
+ invert_m4_m4(mat, ob->obmat);
+ mul_m4_m4m4(mat, mat, smd->target->obmat);
+ copy_v3_v3(target_co, mat[3]);
+ }
+
+ if (use_parallel_normals) {
+ float no[3];
+
+ sub_v3_v3v3(no, target_co, smd->offset);
+ normalize_v3(no);
+
+ for (i = num_loops; i--; ) {
+ copy_v3_v3(nos[i], no);
+ }
+ }
+ else {
+ BLI_bitmap *done_verts = BLI_BITMAP_NEW((size_t)num_verts, __func__);
+ MLoop *ml;
+ float (*no)[3];
+
+ /* We reuse cos to now store the 'to target' normal of the verts! */
+ for (i = num_loops, no = nos, ml = mloop; i--; no++, ml++) {
+ const int vidx = ml->v;
+ float *co = cos[vidx];
+
+ if (!BLI_BITMAP_TEST(done_verts, vidx)) {
+ sub_v3_v3v3(co, target_co, co);
+ normalize_v3(co);
+
+ BLI_BITMAP_ENABLE(done_verts, vidx);
+ }
+
+ copy_v3_v3(*no, co);
+ }
+
+ MEM_freeN(done_verts);
+ }
+
+ if (loopnors) {
+ mix_normals(mix_factor, dvert, defgrp_index, use_invert_vgroup,
+ mix_mode, num_verts, mloop, loopnors, nos, num_loops);
+ }
+
+ BKE_mesh_normals_loop_custom_set(mvert, num_verts, medge, num_edges, mloop, nos, num_loops,
+ mpoly, (const float(*)[3])polynors, num_polys, clnors);
+
+ MEM_freeN(cos);
+ MEM_freeN(nos);
+}
+
+static bool is_valid_target(NormalEditModifierData *smd)
+{
+ if (smd->mode == MOD_NORMALEDIT_MODE_RADIAL) {
+ return true;
+ }
+ else if ((smd->mode == MOD_NORMALEDIT_MODE_DIRECTIONAL) && smd->target) {
+ return true;
+ }
+ modifier_setError((ModifierData *)smd, "Invalid target settings");
+ return false;
+}
+
+static DerivedMesh *normalEditModifier_do(NormalEditModifierData *smd, Object *ob, DerivedMesh *dm)
+{
+ Mesh *me = ob->data;
+
+ const int num_verts = dm->getNumVerts(dm);
+ const int num_edges = dm->getNumEdges(dm);
+ const int num_loops = dm->getNumLoops(dm);
+ const int num_polys = dm->getNumPolys(dm);
+ MVert *mvert;
+ MEdge *medge;
+ MLoop *mloop;
+ MPoly *mpoly;
+
+ const bool use_invert_vgroup = ((smd->flag & MOD_NORMALEDIT_INVERT_VGROUP) != 0);
+ const bool use_current_clnors = !((smd->mix_mode == MOD_NORMALEDIT_MIX_COPY) &&
+ (smd->mix_factor == 1.0f) &&
+ (smd->defgrp_name[0] == '\0'));
+
+ int defgrp_index;
+ MDeformVert *dvert;
+
+ float (*loopnors)[3] = NULL;
+ short (*clnors)[2];
+
+ float (*polynors)[3];
+ bool free_polynors = false;
+
+ /* Do not run that modifier at all if autosmooth is disabled! */
+ if (!is_valid_target(smd) || !num_loops) {
+ return dm;
+ }
+
+ if (!(me->flag & ME_AUTOSMOOTH)) {
+ modifier_setError((ModifierData *)smd, "Enable 'Auto Smooth' option in mesh settings");
+ return dm;
+ }
+
+ medge = dm->getEdgeArray(dm);
+ if (me->medge == medge) {
+ /* We need to duplicate data here, otherwise setting custom normals (which may also affect sharp edges) could
+ * modify org mesh, see T43671. */
+ dm = CDDM_copy(dm);
+ medge = dm->getEdgeArray(dm);
+ }
+ mvert = dm->getVertArray(dm);
+ mloop = dm->getLoopArray(dm);
+ mpoly = dm->getPolyArray(dm);
+
+ if (use_current_clnors) {
+ dm->calcLoopNormals(dm, true, me->smoothresh);
+ loopnors = dm->getLoopDataArray(dm, CD_NORMAL);
+ }
+
+ clnors = CustomData_duplicate_referenced_layer(&dm->loopData, CD_CUSTOMLOOPNORMAL, num_loops);
+ if (!clnors) {
+ DM_add_loop_layer(dm, CD_CUSTOMLOOPNORMAL, CD_CALLOC, NULL);
+ clnors = dm->getLoopDataArray(dm, CD_CUSTOMLOOPNORMAL);
+ }
+
+ polynors = dm->getPolyDataArray(dm, CD_NORMAL);
+ if (!polynors) {
+ polynors = MEM_mallocN(sizeof(*polynors) * num_polys, __func__);
+ BKE_mesh_calc_normals_poly(mvert, num_verts, mloop, mpoly, num_loops, num_polys, polynors, false);
+ free_polynors = true;
+ }
+
+ modifier_get_vgroup(ob, dm, smd->defgrp_name, &dvert, &defgrp_index);
+
+ if (smd->mode == MOD_NORMALEDIT_MODE_RADIAL) {
+ normalEditModifier_do_radial(
+ smd, ob, dm, clnors, loopnors, polynors,
+ smd->mix_mode, smd->mix_factor, dvert, defgrp_index, use_invert_vgroup,
+ mvert, num_verts, medge, num_edges, mloop, num_loops, mpoly, num_polys);
+ }
+ else if (smd->mode == MOD_NORMALEDIT_MODE_DIRECTIONAL) {
+ normalEditModifier_do_directional(
+ smd, ob, dm, clnors, loopnors, polynors,
+ smd->mix_mode, smd->mix_factor, dvert, defgrp_index, use_invert_vgroup,
+ mvert, num_verts, medge, num_edges, mloop, num_loops, mpoly, num_polys);
+ }
+
+ if (free_polynors) {
+ MEM_freeN(polynors);
+ }
+
+ return dm;
+}
+
+static void initData(ModifierData *md)
+{
+ NormalEditModifierData *smd = (NormalEditModifierData *)md;
+
+ smd->mode = MOD_NORMALEDIT_MODE_RADIAL;
+
+ smd->mix_mode = MOD_NORMALEDIT_MIX_COPY;
+ smd->mix_factor = 1.0f;
+}
+
+static void copyData(ModifierData *md, ModifierData *target)
+{
+ modifier_copyData_generic(md, target);
+}
+
+static CustomDataMask requiredDataMask(Object *UNUSED(ob), ModifierData *md)
+{
+ NormalEditModifierData *smd = (NormalEditModifierData *)md;
+ CustomDataMask dataMask = CD_CUSTOMLOOPNORMAL;
+
+ /* Ask for vertexgroups if we need them. */
+ if (smd->defgrp_name[0]) {
+ dataMask |= (CD_MASK_MDEFORMVERT);
+ }
+
+ return dataMask;
+}
+
+static bool dependsOnNormals(ModifierData *UNUSED(md))
+{
+ return true;
+}
+
+static void foreachObjectLink(ModifierData *md, Object *ob, ObjectWalkFunc walk, void *userData)
+{
+ NormalEditModifierData *smd = (NormalEditModifierData *) md;
+
+ walk(userData, ob, &smd->target);
+}
+
+static void foreachIDLink(ModifierData *md, Object *ob, IDWalkFunc walk, void *userData)
+{
+ NormalEditModifierData *smd = (NormalEditModifierData *) md;
+
+ walk(userData, ob, (ID **)&smd->target);
+}
+
+static bool isDisabled(ModifierData *md, int UNUSED(useRenderParams))
+{
+ NormalEditModifierData *smd = (NormalEditModifierData *)md;
+
+ return !is_valid_target(smd);
+}
+
+static void updateDepgraph(ModifierData *md, DagForest *forest,
+ struct Main *UNUSED(bmain),
+ struct Scene *UNUSED(scene),
+ Object *UNUSED(ob), DagNode *obNode)
+{
+ NormalEditModifierData *smd = (NormalEditModifierData *) md;
+
+ if (smd->target) {
+ DagNode *Node = dag_get_node(forest, smd->target);
+
+ dag_add_relation(forest, Node, obNode, DAG_RL_OB_DATA, "NormalEdit Modifier");
+ }
+}
+
+static void updateDepsgraph(ModifierData *md,
+ struct Main *UNUSED(bmain),
+ struct Scene *UNUSED(scene),
+ Object *UNUSED(ob),
+ struct DepsNodeHandle *node)
+{
+ NormalEditModifierData *smd = (NormalEditModifierData *) md;
+ if (smd->target) {
+ DEG_add_object_relation(node, smd->target, DEG_OB_COMP_GEOMETRY, "NormalEdit Modifier");
+ }
+}
+
+static DerivedMesh *applyModifier(ModifierData *md, Object *ob, DerivedMesh *dm, ModifierApplyFlag UNUSED(flag))
+{
+ return normalEditModifier_do((NormalEditModifierData *)md, ob, dm);
+}
+
+ModifierTypeInfo modifierType_NormalEdit = {
+ /* name */ "Set Split Normals",
+ /* structName */ "NormalEditModifierData",
+ /* structSize */ sizeof(NormalEditModifierData),
+ /* type */ eModifierTypeType_Constructive,
+ /* flags */ eModifierTypeFlag_AcceptsMesh |
+ eModifierTypeFlag_AcceptsCVs |
+ eModifierTypeFlag_SupportsMapping |
+ eModifierTypeFlag_SupportsEditmode |
+ eModifierTypeFlag_EnableInEditmode,
+ /* copyData */ copyData,
+ /* deformVerts */ NULL,
+ /* deformMatrices */ NULL,
+ /* deformVertsEM */ NULL,
+ /* deformMatricesEM */ NULL,
+ /* applyModifier */ applyModifier,
+ /* applyModifierEM */ NULL,
+ /* initData */ initData,
+ /* requiredDataMask */ requiredDataMask,
+ /* freeData */ NULL,
+ /* isDisabled */ isDisabled,
+ /* updateDepgraph */ updateDepgraph,
+ /* updateDepsgraph */ updateDepsgraph,
+ /* dependsOnTime */ NULL,
+ /* dependsOnNormals */ dependsOnNormals,
+ /* foreachObjectLink */ foreachObjectLink,
+ /* foreachIDLink */ foreachIDLink,
+ /* foreachTexLink */ NULL,
+};
diff --git a/source/blender/modifiers/intern/MOD_ocean.c b/source/blender/modifiers/intern/MOD_ocean.c
index a324702a6ae..913c2f25c15 100644
--- a/source/blender/modifiers/intern/MOD_ocean.c
+++ b/source/blender/modifiers/intern/MOD_ocean.c
@@ -43,21 +43,19 @@
#include "BKE_modifier.h"
#include "BKE_ocean.h"
-#include "MOD_util.h"
-
#ifdef WITH_OCEANSIM
static void init_cache_data(Object *ob, struct OceanModifierData *omd)
{
const char *relbase = modifier_path_relbase(ob);
- omd->oceancache = BKE_init_ocean_cache(omd->cachepath, relbase,
+ omd->oceancache = BKE_ocean_init_cache(omd->cachepath, relbase,
omd->bakestart, omd->bakeend, omd->wave_scale,
omd->chop_amount, omd->foam_coverage, omd->foam_fade, omd->resolution);
}
static void clear_cache_data(struct OceanModifierData *omd)
{
- BKE_free_ocean_cache(omd->oceancache);
+ BKE_ocean_free_cache(omd->oceancache);
omd->oceancache = NULL;
omd->cached = false;
}
@@ -74,8 +72,8 @@ static void init_ocean_modifier(struct OceanModifierData *omd)
do_normals = (omd->flag & MOD_OCEAN_GENERATE_NORMALS);
do_jacobian = (omd->flag & MOD_OCEAN_GENERATE_FOAM);
- BKE_free_ocean_data(omd->ocean);
- BKE_init_ocean(omd->ocean, omd->resolution * omd->resolution, omd->resolution * omd->resolution,
+ BKE_ocean_free_data(omd->ocean);
+ BKE_ocean_init(omd->ocean, omd->resolution * omd->resolution, omd->resolution * omd->resolution,
omd->spatial_size, omd->spatial_size,
omd->wind_velocity, omd->smallest_wave, 1.0, omd->wave_direction, omd->damp, omd->wave_alignment,
omd->depth, omd->time,
@@ -87,7 +85,7 @@ static void simulate_ocean_modifier(struct OceanModifierData *omd)
{
if (!omd || !omd->ocean) return;
- BKE_simulate_ocean(omd->ocean, omd->time, omd->wave_scale, omd->chop_amount);
+ BKE_ocean_simulate(omd->ocean, omd->time, omd->wave_scale, omd->chop_amount);
}
#endif /* WITH_OCEANSIM */
@@ -135,7 +133,7 @@ static void initData(ModifierData *md)
omd->foam_fade = 0.98;
omd->foamlayername[0] = '\0'; /* layer name empty by default */
- omd->ocean = BKE_add_ocean();
+ omd->ocean = BKE_ocean_add();
init_ocean_modifier(omd);
simulate_ocean_modifier(omd);
#else /* WITH_OCEANSIM */
@@ -149,9 +147,9 @@ static void freeData(ModifierData *md)
#ifdef WITH_OCEANSIM
OceanModifierData *omd = (OceanModifierData *) md;
- BKE_free_ocean(omd->ocean);
+ BKE_ocean_free(omd->ocean);
if (omd->oceancache)
- BKE_free_ocean_cache(omd->oceancache);
+ BKE_ocean_free_cache(omd->oceancache);
#else /* WITH_OCEANSIM */
/* unused */
(void)md;
@@ -197,7 +195,7 @@ static void copyData(ModifierData *md, ModifierData *target)
tomd->bakeend = omd->bakeend;
tomd->oceancache = NULL;
- tomd->ocean = BKE_add_ocean();
+ tomd->ocean = BKE_ocean_add();
init_ocean_modifier(tomd);
simulate_ocean_modifier(tomd);
#else /* WITH_OCEANSIM */
@@ -428,7 +426,7 @@ static DerivedMesh *doOcean(ModifierData *md, Object *ob,
/* update modifier */
if (omd->refresh & MOD_OCEAN_REFRESH_ADD)
- omd->ocean = BKE_add_ocean();
+ omd->ocean = BKE_ocean_add();
if (omd->refresh & MOD_OCEAN_REFRESH_RESET)
init_ocean_modifier(omd);
if (omd->refresh & MOD_OCEAN_REFRESH_CLEAR_CACHE)
@@ -439,7 +437,7 @@ static DerivedMesh *doOcean(ModifierData *md, Object *ob,
/* do ocean simulation */
if (omd->cached == true) {
if (!omd->oceancache) init_cache_data(ob, omd);
- BKE_simulate_ocean_cache(omd->oceancache, md->scene->r.cfra);
+ BKE_ocean_simulate_cache(omd->oceancache, md->scene->r.cfra);
}
else {
simulate_ocean_modifier(omd);
@@ -582,6 +580,7 @@ ModifierTypeInfo modifierType_Ocean = {
/* freeData */ freeData,
/* isDisabled */ NULL,
/* updateDepgraph */ NULL,
+ /* updateDepsgraph */ NULL,
/* dependsOnTime */ NULL,
/* dependsOnNormals */ dependsOnNormals,
/* foreachObjectLink */ NULL,
diff --git a/source/blender/modifiers/intern/MOD_particleinstance.c b/source/blender/modifiers/intern/MOD_particleinstance.c
index 7aa81d6a003..cb6234d50b7 100644
--- a/source/blender/modifiers/intern/MOD_particleinstance.c
+++ b/source/blender/modifiers/intern/MOD_particleinstance.c
@@ -43,15 +43,15 @@
#include "BLI_utildefines.h"
#include "BKE_cdderivedmesh.h"
+#include "BKE_effect.h"
+#include "BKE_global.h"
#include "BKE_lattice.h"
#include "BKE_modifier.h"
#include "BKE_particle.h"
#include "BKE_pointcache.h"
-#include "MOD_util.h"
-
#include "depsgraph_private.h"
-
+#include "DEG_depsgraph_build.h"
static void initData(ModifierData *md)
{
@@ -111,6 +111,7 @@ static bool isDisabled(ModifierData *md, int useRenderParams)
static void updateDepgraph(ModifierData *md, DagForest *forest,
+ struct Main *UNUSED(bmain),
struct Scene *UNUSED(scene),
Object *UNUSED(ob),
DagNode *obNode)
@@ -126,6 +127,18 @@ static void updateDepgraph(ModifierData *md, DagForest *forest,
}
}
+static void updateDepsgraph(ModifierData *md,
+ struct Main *UNUSED(bmain),
+ struct Scene *UNUSED(scene),
+ Object *UNUSED(ob),
+ struct DepsNodeHandle *node)
+{
+ ParticleInstanceModifierData *pimd = (ParticleInstanceModifierData *) md;
+ if (pimd->ob != NULL) {
+ DEG_add_object_relation(node, pimd->ob, DEG_OB_COMP_TRANSFORM, "Particle Instance Modifier");
+ }
+}
+
static void foreachObjectLink(ModifierData *md, Object *ob,
ObjectWalkFunc walk, void *userData)
{
@@ -185,7 +198,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
int maxvert, maxpoly, maxloop, totpart = 0, first_particle = 0;
int k, p, p_skip;
short track = ob->trackflag % 3, trackneg, axis = pimd->axis;
- float max_co = 0.0, min_co = 0.0, temp_co[3], cross[3];
+ float max_co = 0.0, min_co = 0.0, temp_co[3];
float *size = NULL;
trackneg = ((ob->trackflag > 2) ? 1 : 0);
@@ -278,6 +291,9 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
orig_mloop = dm->getLoopArray(dm);
for (p = 0, p_skip = 0; p < totpart; p++) {
+ float prev_dir[3];
+ float frame[4]; /* frame orientation quaternion */
+
/* skip particle? */
if (particle_skip(pimd, psys, p))
continue;
@@ -323,19 +339,55 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
normalize_v3(state.vel);
- /* TODO: incremental rotations somehow */
+ /* Incrementally Rotating Frame (Bishop Frame) */
+ if (k == 0) {
+ float hairmat[4][4];
+ float mat[3][3];
+
+ if (first_particle + p < psys->totpart)
+ pa = psys->particles + first_particle + p;
+ else {
+ ChildParticle *cpa = psys->child + (p - psys->totpart);
+ pa = psys->particles + cpa->parent;
+ }
+ psys_mat_hair_to_global(sim.ob, sim.psmd->dm, sim.psys->part->from, pa, hairmat);
+ copy_m3_m4(mat, hairmat);
+ /* to quaternion */
+ mat3_to_quat(frame, mat);
+
+ /* note: direction is same as normal vector currently,
+ * but best to keep this separate so the frame can be
+ * rotated later if necessary
+ */
+ copy_v3_v3(prev_dir, state.vel);
+ }
+ else {
+ float rot[4];
+
+ /* incrementally rotate along bend direction */
+ rotation_between_vecs_to_quat(rot, prev_dir, state.vel);
+ mul_qt_qtqt(frame, rot, frame);
+
+ copy_v3_v3(prev_dir, state.vel);
+ }
+
+ copy_qt_qt(state.rot, frame);
+#if 0
+ /* Absolute Frame (Frenet Frame) */
if (state.vel[axis] < -0.9999f || state.vel[axis] > 0.9999f) {
unit_qt(state.rot);
}
else {
+ float cross[3];
float temp[3] = {0.0f, 0.0f, 0.0f};
temp[axis] = 1.0f;
-
+
cross_v3_v3v3(cross, temp, state.vel);
-
+
/* state.vel[axis] is the only component surviving from a dot product with the axis */
axis_angle_to_quat(state.rot, cross, saacos(state.vel[axis]));
}
+#endif
}
else {
state.time = -1.0;
@@ -408,6 +460,7 @@ ModifierTypeInfo modifierType_ParticleInstance = {
/* freeData */ NULL,
/* isDisabled */ isDisabled,
/* updateDepgraph */ updateDepgraph,
+ /* updateDepsgraph */ updateDepsgraph,
/* dependsOnTime */ NULL,
/* dependsOnNormals */ NULL,
/* foreachObjectLink */ foreachObjectLink,
diff --git a/source/blender/modifiers/intern/MOD_particlesystem.c b/source/blender/modifiers/intern/MOD_particlesystem.c
index a41fbb03462..de1b11eddd9 100644
--- a/source/blender/modifiers/intern/MOD_particlesystem.c
+++ b/source/blender/modifiers/intern/MOD_particlesystem.c
@@ -85,37 +85,7 @@ static void copyData(ModifierData *md, ModifierData *target)
static CustomDataMask requiredDataMask(Object *UNUSED(ob), ModifierData *md)
{
ParticleSystemModifierData *psmd = (ParticleSystemModifierData *) md;
- CustomDataMask dataMask = 0;
- MTex *mtex;
- int i;
-
- if (!psmd->psys->part)
- return 0;
-
- for (i = 0; i < MAX_MTEX; i++) {
- mtex = psmd->psys->part->mtex[i];
- if (mtex && mtex->mapto && (mtex->texco & TEXCO_UV))
- dataMask |= CD_MASK_MTFACE;
- }
-
- if (psmd->psys->part->tanfac != 0.0f)
- dataMask |= CD_MASK_MTFACE;
-
- /* ask for vertexgroups if we need them */
- for (i = 0; i < PSYS_TOT_VG; i++) {
- if (psmd->psys->vgroup[i]) {
- dataMask |= CD_MASK_MDEFORMVERT;
- break;
- }
- }
-
- /* particles only need this if they are after a non deform modifier, and
- * the modifier stack will only create them in that case. */
- dataMask |= CD_MASK_ORIGSPACE_MLOOP | CD_MASK_ORIGINDEX;
-
- dataMask |= CD_MASK_ORCO;
-
- return dataMask;
+ return psys_emitter_customdata_mask(psmd->psys);
}
/* saves the current emitter state for a particle system and calculates particles */
@@ -236,6 +206,7 @@ ModifierTypeInfo modifierType_ParticleSystem = {
/* freeData */ freeData,
/* isDisabled */ NULL,
/* updateDepgraph */ NULL,
+ /* updateDepsgraph */ NULL,
/* dependsOnTime */ NULL,
/* dependsOnNormals */ NULL,
/* foreachObjectLink */ NULL,
diff --git a/source/blender/modifiers/intern/MOD_remesh.c b/source/blender/modifiers/intern/MOD_remesh.c
index 6d76dc51ac7..b85898c07e9 100644
--- a/source/blender/modifiers/intern/MOD_remesh.c
+++ b/source/blender/modifiers/intern/MOD_remesh.c
@@ -78,9 +78,11 @@ static void init_dualcon_mesh(DualConInput *mesh, DerivedMesh *dm)
mesh->co_stride = sizeof(MVert);
mesh->totco = dm->getNumVerts(dm);
- mesh->faces = (void *)dm->getTessFaceArray(dm);
- mesh->face_stride = sizeof(MFace);
- mesh->totface = dm->getNumTessFaces(dm);
+ mesh->mloop = (void *)dm->getLoopArray(dm);
+ mesh->loop_stride = sizeof(MLoop);
+ mesh->looptri = (void *)dm->getLoopTriArray(dm);
+ mesh->tri_stride = sizeof(MLoopTri);
+ mesh->tottri = dm->getNumLoopTri(dm);
INIT_MINMAX(mesh->min, mesh->max);
dm->getMinMax(dm, mesh->min, mesh->max);
@@ -152,8 +154,6 @@ static DerivedMesh *applyModifier(ModifierData *md,
DualConFlags flags = 0;
DualConMode mode = 0;
- DM_ensure_tessface(dm); /* BMESH - UNTIL MODIFIER IS UPDATED FOR MPoly */
-
rmd = (RemeshModifierData *)md;
init_dualcon_mesh(&input, dm);
@@ -232,6 +232,7 @@ ModifierTypeInfo modifierType_Remesh = {
/* freeData */ NULL,
/* isDisabled */ NULL,
/* updateDepgraph */ NULL,
+ /* updateDepsgraph */ NULL,
/* dependsOnTime */ NULL,
/* dependsOnNormals */ NULL,
/* foreachObjectLink */ NULL,
diff --git a/source/blender/modifiers/intern/MOD_screw.c b/source/blender/modifiers/intern/MOD_screw.c
index 5900baaf537..db65f4431e4 100644
--- a/source/blender/modifiers/intern/MOD_screw.c
+++ b/source/blender/modifiers/intern/MOD_screw.c
@@ -46,6 +46,8 @@
#include "BKE_cdderivedmesh.h"
#include "depsgraph_private.h"
+#include "DEG_depsgraph_build.h"
+
#include "MOD_modifiertypes.h"
#include "MEM_guardedalloc.h"
@@ -138,15 +140,15 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
DerivedMesh *dm = derivedData;
DerivedMesh *result;
ScrewModifierData *ltmd = (ScrewModifierData *) md;
- const int useRenderParams = flag & MOD_APPLY_RENDER;
+ const bool use_render_params = (flag & MOD_APPLY_RENDER) != 0;
int *origindex;
int mpoly_index = 0;
unsigned int step;
unsigned int i, j;
unsigned int i1, i2;
- unsigned int step_tot = useRenderParams ? ltmd->render_steps : ltmd->steps;
- const bool do_flip = ltmd->flag & MOD_SCREW_NORMAL_FLIP ? 1 : 0;
+ unsigned int step_tot = use_render_params ? ltmd->render_steps : ltmd->steps;
+ const bool do_flip = (ltmd->flag & MOD_SCREW_NORMAL_FLIP) != 0;
const int quad_ord[4] = {
do_flip ? 3 : 0,
@@ -156,9 +158,9 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
};
const int quad_ord_ofs[4] = {
do_flip ? 2 : 0,
- do_flip ? 1 : 1,
+ 1,
do_flip ? 0 : 2,
- do_flip ? 3 : 3,
+ 3,
};
unsigned int maxVerts = 0, maxEdges = 0, maxPolys = 0;
@@ -764,7 +766,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
}
/* we wont be looping on this data again so copy normals here */
- if (angle < 0.0f)
+ if ((angle < 0.0f) != do_flip)
negate_v3(vc->no);
normalize_v3(vc->no);
@@ -1058,6 +1060,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
static void updateDepgraph(ModifierData *md, DagForest *forest,
+ struct Main *UNUSED(bmain),
struct Scene *UNUSED(scene),
Object *UNUSED(ob),
DagNode *obNode)
@@ -1073,6 +1076,18 @@ static void updateDepgraph(ModifierData *md, DagForest *forest,
}
}
+static void updateDepsgraph(ModifierData *md,
+ struct Main *UNUSED(bmain),
+ struct Scene *UNUSED(scene),
+ Object *UNUSED(ob),
+ struct DepsNodeHandle *node)
+{
+ ScrewModifierData *ltmd = (ScrewModifierData *)md;
+ if (ltmd->ob_axis != NULL) {
+ DEG_add_object_relation(node, ltmd->ob_axis, DEG_OB_COMP_TRANSFORM, "Screw Modifier");
+ }
+}
+
static void foreachObjectLink(
ModifierData *md, Object *ob,
void (*walk)(void *userData, Object *ob, Object **obpoin),
@@ -1106,6 +1121,7 @@ ModifierTypeInfo modifierType_Screw = {
/* freeData */ NULL,
/* isDisabled */ NULL,
/* updateDepgraph */ updateDepgraph,
+ /* updateDepsgraph */ updateDepsgraph,
/* dependsOnTime */ NULL,
/* dependsOnNormals */ NULL,
/* foreachObjectLink */ foreachObjectLink,
diff --git a/source/blender/modifiers/intern/MOD_shapekey.c b/source/blender/modifiers/intern/MOD_shapekey.c
index 45725d1c453..a543aac74b9 100644
--- a/source/blender/modifiers/intern/MOD_shapekey.c
+++ b/source/blender/modifiers/intern/MOD_shapekey.c
@@ -44,7 +44,7 @@
#include "MOD_modifiertypes.h"
-static void deformVerts(ModifierData *md, Object *ob,
+static void deformVerts(ModifierData *UNUSED(md), Object *ob,
DerivedMesh *UNUSED(derivedData),
float (*vertexCos)[3],
int numVerts,
@@ -54,8 +54,9 @@ static void deformVerts(ModifierData *md, Object *ob,
if (key && key->block.first) {
int deformedVerts_tot;
- BKE_key_evaluate_object_ex(md->scene, ob, &deformedVerts_tot,
- (float *)vertexCos, sizeof(*vertexCos) * numVerts);
+ BKE_key_evaluate_object_ex(
+ ob, &deformedVerts_tot,
+ (float *)vertexCos, sizeof(*vertexCos) * numVerts);
}
}
@@ -137,6 +138,7 @@ ModifierTypeInfo modifierType_ShapeKey = {
/* freeData */ NULL,
/* isDisabled */ NULL,
/* updateDepgraph */ NULL,
+ /* updateDepsgraph */ NULL,
/* dependsOnTime */ NULL,
/* dependsOnNormals */ NULL,
/* foreachObjectLink */ NULL,
diff --git a/source/blender/modifiers/intern/MOD_shrinkwrap.c b/source/blender/modifiers/intern/MOD_shrinkwrap.c
index 229f4911ab4..91be0c40059 100644
--- a/source/blender/modifiers/intern/MOD_shrinkwrap.c
+++ b/source/blender/modifiers/intern/MOD_shrinkwrap.c
@@ -38,7 +38,6 @@
#include "DNA_object_types.h"
#include "BLI_math.h"
-#include "BLI_string.h"
#include "BLI_utildefines.h"
#include "BKE_cdderivedmesh.h"
@@ -144,6 +143,7 @@ static void deformVertsEM(ModifierData *md, Object *ob, struct BMEditMesh *editD
}
static void updateDepgraph(ModifierData *md, DagForest *forest,
+ struct Main *UNUSED(bmain),
struct Scene *UNUSED(scene),
Object *UNUSED(ob),
DagNode *obNode)
@@ -159,6 +159,23 @@ static void updateDepgraph(ModifierData *md, DagForest *forest,
DAG_RL_OB_DATA | DAG_RL_DATA_DATA, "Shrinkwrap Modifier");
}
+static void updateDepsgraph(ModifierData *md,
+ struct Main *UNUSED(bmain),
+ struct Scene *UNUSED(scene),
+ Object *UNUSED(ob),
+ struct DepsNodeHandle *node)
+{
+ ShrinkwrapModifierData *smd = (ShrinkwrapModifierData *)md;
+ if (smd->target != NULL) {
+ DEG_add_object_relation(node, smd->target, DEG_OB_COMP_TRANSFORM, "Shrinkwrap Modifier");
+ DEG_add_object_relation(node, smd->target, DEG_OB_COMP_GEOMETRY, "Shrinkwrap Modifier");
+ }
+ if (smd->auxTarget != NULL) {
+ DEG_add_object_relation(node, smd->auxTarget, DEG_OB_COMP_TRANSFORM, "Shrinkwrap Modifier");
+ DEG_add_object_relation(node, smd->auxTarget, DEG_OB_COMP_GEOMETRY, "Shrinkwrap Modifier");
+ }
+}
+
static bool dependsOnNormals(ModifierData *md)
{
ShrinkwrapModifierData *smd = (ShrinkwrapModifierData *)md;
@@ -191,6 +208,7 @@ ModifierTypeInfo modifierType_Shrinkwrap = {
/* freeData */ NULL,
/* isDisabled */ isDisabled,
/* updateDepgraph */ updateDepgraph,
+ /* updateDepsgraph */ updateDepsgraph,
/* dependsOnTime */ NULL,
/* dependsOnNormals */ dependsOnNormals,
/* foreachObjectLink */ foreachObjectLink,
diff --git a/source/blender/modifiers/intern/MOD_simpledeform.c b/source/blender/modifiers/intern/MOD_simpledeform.c
index 3314196b776..706a296f5a1 100644
--- a/source/blender/modifiers/intern/MOD_simpledeform.c
+++ b/source/blender/modifiers/intern/MOD_simpledeform.c
@@ -244,8 +244,6 @@ static void SimpleDeformModifier_do(SimpleDeformModifierData *smd, struct Object
}
-
-
/* SimpleDeform */
static void initData(ModifierData *md)
{
@@ -289,6 +287,7 @@ static void foreachObjectLink(ModifierData *md, Object *ob,
}
static void updateDepgraph(ModifierData *md, DagForest *forest,
+ struct Main *UNUSED(bmain),
struct Scene *UNUSED(scene),
Object *UNUSED(ob),
DagNode *obNode)
@@ -299,6 +298,18 @@ static void updateDepgraph(ModifierData *md, DagForest *forest,
dag_add_relation(forest, dag_get_node(forest, smd->origin), obNode, DAG_RL_OB_DATA, "SimpleDeform Modifier");
}
+static void updateDepsgraph(ModifierData *md,
+ struct Main *UNUSED(bmain),
+ struct Scene *UNUSED(scene),
+ Object *UNUSED(ob),
+ struct DepsNodeHandle *node)
+{
+ SimpleDeformModifierData *smd = (SimpleDeformModifierData *)md;
+ if (smd->origin != NULL) {
+ DEG_add_object_relation(node, smd->origin, DEG_OB_COMP_TRANSFORM, "SimpleDeform Modifier");
+ }
+}
+
static void deformVerts(ModifierData *md, Object *ob,
DerivedMesh *derivedData,
float (*vertexCos)[3],
@@ -363,6 +374,7 @@ ModifierTypeInfo modifierType_SimpleDeform = {
/* freeData */ NULL,
/* isDisabled */ NULL,
/* updateDepgraph */ updateDepgraph,
+ /* updateDepsgraph */ updateDepsgraph,
/* dependsOnTime */ NULL,
/* dependsOnNormals */ NULL,
/* foreachObjectLink */ foreachObjectLink,
diff --git a/source/blender/modifiers/intern/MOD_skin.c b/source/blender/modifiers/intern/MOD_skin.c
index 1e422806d80..1b8b29666e2 100644
--- a/source/blender/modifiers/intern/MOD_skin.c
+++ b/source/blender/modifiers/intern/MOD_skin.c
@@ -79,8 +79,6 @@
#include "bmesh.h"
-#include "MOD_util.h"
-
typedef struct {
float mat[3][3];
/* Vert that edge is pointing away from, no relation to
@@ -106,6 +104,9 @@ typedef struct Frame {
/* Merge to target frame/corner (no merge if frame is null) */
struct Frame *frame;
int corner;
+ /* checked to avoid chaining.
+ * (merging when we're already been referenced), see T39775 */
+ unsigned int is_target : 1;
} merge[4];
/* For hull frames, whether each vertex is detached or not */
@@ -251,6 +252,7 @@ static bool build_hull(SkinOutput *so, Frame **frames, int totframe)
/* Apply face attributes to hull output */
BMO_ITER (f, &oiter, op.slots_out, "geom.out", BM_FACE) {
+ BM_face_normal_update(f);
if (so->smd->flag & MOD_SKIN_SMOOTH_SHADING)
BM_elem_flag_enable(f, BM_ELEM_SMOOTH);
f->mat_nr = so->mat_nr;
@@ -328,8 +330,7 @@ static bool build_hull(SkinOutput *so, Frame **frames, int totframe)
return true;
#else
- (void)so, (void)frames, (void)totframe;
- (void)skin_frame_find_contained_faces;
+ UNUSED_VARS(so, frames, totframe, skin_frame_find_contained_faces);
return false;
#endif
}
@@ -365,7 +366,7 @@ static void merge_frame_corners(Frame **frames, int totframe)
/* Compare with each corner of all other frames... */
for (l = 0; l < 4; l++) {
- if (frames[k]->merge[l].frame)
+ if (frames[k]->merge[l].frame || frames[k]->merge[l].is_target)
continue;
/* Some additional concerns that could be checked
@@ -395,6 +396,7 @@ static void merge_frame_corners(Frame **frames, int totframe)
frames[k]->merge[l].frame = frames[i];
frames[k]->merge[l].corner = j;
+ frames[i]->merge[j].is_target = true;
/* Can't merge another corner into the same
* frame corner, so move on to frame k+1 */
@@ -963,28 +965,57 @@ static void add_poly(SkinOutput *so,
BLI_assert(v1 && v2 && v3);
f = BM_face_create_verts(so->bm, verts, v4 ? 4 : 3, NULL, BM_CREATE_NO_DOUBLE, true);
+ BM_face_normal_update(f);
if (so->smd->flag & MOD_SKIN_SMOOTH_SHADING)
BM_elem_flag_enable(f, BM_ELEM_SMOOTH);
f->mat_nr = so->mat_nr;
}
-static void connect_frames(SkinOutput *so,
- BMVert *frame1[4],
-BMVert *frame2[4])
+static void connect_frames(
+ SkinOutput *so,
+ BMVert *frame1[4],
+ BMVert *frame2[4])
{
BMVert *q[4][4] = {{frame2[0], frame2[1], frame1[1], frame1[0]},
{frame2[1], frame2[2], frame1[2], frame1[1]},
{frame2[2], frame2[3], frame1[3], frame1[2]},
{frame2[3], frame2[0], frame1[0], frame1[3]}};
- float p[3], no[3];
- int i, swap;
+ int i;
+ bool swap;
/* Check if frame normals need swap */
- sub_v3_v3v3(p, q[3][0]->co, q[0][0]->co);
- normal_quad_v3(no,
- q[0][0]->co, q[0][1]->co,
- q[0][2]->co, q[0][3]->co);
- swap = dot_v3v3(no, p) > 0;
+#if 0
+ {
+ /* simple method, works mostly */
+ float p[3], no[3];
+ sub_v3_v3v3(p, q[3][0]->co, q[0][0]->co);
+ normal_quad_v3(no,
+ q[0][0]->co, q[0][1]->co,
+ q[0][2]->co, q[0][3]->co);
+ swap = dot_v3v3(no, p) > 0;
+ }
+#else
+ {
+ /* comprehensive method, accumulate flipping of all faces */
+ float cent_sides[4][3];
+ float cent[3];
+ float dot = 0.0f;
+
+ for (i = 0; i < 4; i++) {
+ mid_v3_v3v3v3v3(cent_sides[i], UNPACK4_EX(, q[i], ->co));
+ }
+ mid_v3_v3v3v3v3(cent, UNPACK4(cent_sides));
+
+ for (i = 0; i < 4; i++) {
+ float p[3], no[3];
+ normal_quad_v3(no, UNPACK4_EX(, q[i], ->co));
+ sub_v3_v3v3(p, cent, cent_sides[i]);
+ dot += dot_v3v3(no, p);
+ }
+
+ swap = dot > 0;
+ }
+#endif
for (i = 0; i < 4; i++) {
if (swap)
@@ -1117,7 +1148,7 @@ static BMFace *collapse_face_corners(BMesh *bm, BMFace *f, int n,
orig_verts[i] = NULL;
}
else if (orig_verts[i] &&
- !BM_vert_in_face(vf, orig_verts[i]))
+ !BM_vert_in_face(orig_verts[i], vf))
{
wrong_face = true;
break;
@@ -1263,7 +1294,7 @@ static void skin_fix_hole_no_good_verts(BMesh *bm, Frame *frame, BMFace *split_f
BMO_op_callf(bm, BMO_FLAG_DEFAULTS,
"subdivide_edges edges=%he cuts=%i quad_corner_type=%i",
- BM_ELEM_TAG, 1, SUBD_STRAIGHT_CUT);
+ BM_ELEM_TAG, 1, SUBD_CORNER_STRAIGHT_CUT);
}
else if (split_face->len > 4) {
/* Maintain a dynamic vert array containing the split_face's
@@ -1396,6 +1427,9 @@ static void hull_merge_triangles(SkinOutput *so, const SkinModifierData *smd)
if (adj[0]->len == 3 && adj[1]->len == 3) {
BMVert *quad[4];
+ BLI_assert(BM_face_is_normal_valid(adj[0]));
+ BLI_assert(BM_face_is_normal_valid(adj[1]));
+
/* Construct quad using the two triangles adjacent to
* the edge */
quad_from_tris(e, adj, quad);
@@ -1758,6 +1792,9 @@ static BMesh *build_skin(SkinNode *skin_nodes,
skin_output_connections(&so, skin_nodes, medge, totedge);
hull_merge_triangles(&so, smd);
+ bmesh_edit_end(so.bm, 0);
+ BMO_pop(so.bm);
+
return so.bm;
}
@@ -1768,7 +1805,7 @@ static void skin_set_orig_indices(DerivedMesh *dm)
totpoly = dm->getNumPolys(dm);
orig = CustomData_add_layer(&dm->polyData, CD_ORIGINDEX,
CD_CALLOC, NULL, totpoly);
- fill_vn_i(orig, totpoly, ORIGINDEX_NONE);
+ copy_vn_i(orig, totpoly, ORIGINDEX_NONE);
}
/*
@@ -1819,7 +1856,6 @@ static DerivedMesh *base_skin(DerivedMesh *origdm,
result = CDDM_from_bmesh(bm, false);
BM_mesh_free(bm);
- CDDM_calc_edges(result);
result->dirty |= DM_DIRTY_NORMALS;
skin_set_orig_indices(result);
@@ -1905,6 +1941,7 @@ ModifierTypeInfo modifierType_Skin = {
/* freeData */ NULL,
/* isDisabled */ NULL,
/* updateDepgraph */ NULL,
+ /* updateDepsgraph */ NULL,
/* dependsOnTime */ NULL,
/* dependsOnNormals */ NULL,
/* foreachObjectLink */ NULL,
diff --git a/source/blender/modifiers/intern/MOD_smoke.c b/source/blender/modifiers/intern/MOD_smoke.c
index fcd4cc96410..657c4e09d96 100644
--- a/source/blender/modifiers/intern/MOD_smoke.c
+++ b/source/blender/modifiers/intern/MOD_smoke.c
@@ -47,13 +47,13 @@
#include "BKE_cdderivedmesh.h"
+#include "BKE_library.h"
+#include "BKE_main.h"
#include "BKE_modifier.h"
#include "BKE_smoke.h"
#include "depsgraph_private.h"
-
-#include "MOD_util.h"
-
+#include "DEG_depsgraph_build.h"
static void initData(ModifierData *md)
{
@@ -117,7 +117,65 @@ static bool dependsOnTime(ModifierData *UNUSED(md))
return true;
}
+static void update_depsgraph_flow_coll_object(DagForest *forest,
+ DagNode *obNode,
+ Object *object2)
+{
+ SmokeModifierData *smd;
+ if ((object2->id.flag & LIB_DOIT) == 0) {
+ return;
+ }
+ object2->id.flag &= ~LIB_DOIT;
+ smd = (SmokeModifierData *)modifiers_findByType(object2, eModifierType_Smoke);
+ if (smd && (((smd->type & MOD_SMOKE_TYPE_FLOW) && smd->flow) ||
+ ((smd->type & MOD_SMOKE_TYPE_COLL) && smd->coll)))
+ {
+ DagNode *curNode = dag_get_node(forest, object2);
+ dag_add_relation(forest, curNode, obNode, DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Smoke Flow/Coll");
+ }
+ if ((object2->transflag & OB_DUPLIGROUP) && object2->dup_group) {
+ GroupObject *go;
+ for (go = object2->dup_group->gobject.first;
+ go != NULL;
+ go = go->next)
+ {
+ if (go->ob == NULL) {
+ continue;
+ }
+ update_depsgraph_flow_coll_object(forest, obNode, go->ob);
+ }
+ }
+}
+
+static void update_depsgraph_field_source_object(DagForest *forest,
+ DagNode *obNode,
+ Object *object,
+ Object *object2)
+{
+ if ((object2->id.flag & LIB_DOIT) == 0) {
+ return;
+ }
+ object2->id.flag &= ~LIB_DOIT;
+ if (object2->pd && object2->pd->forcefield == PFIELD_SMOKEFLOW && object2->pd->f_source == object) {
+ DagNode *node2 = dag_get_node(forest, object2);
+ dag_add_relation(forest, obNode, node2, DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Field Source Object");
+ }
+ if ((object2->transflag & OB_DUPLIGROUP) && object2->dup_group) {
+ GroupObject *go;
+ for (go = object2->dup_group->gobject.first;
+ go != NULL;
+ go = go->next)
+ {
+ if (go->ob == NULL) {
+ continue;
+ }
+ update_depsgraph_field_source_object(forest, obNode, object, go->ob);
+ }
+ }
+}
+
static void updateDepgraph(ModifierData *md, DagForest *forest,
+ struct Main *bmain,
struct Scene *scene, struct Object *ob,
DagNode *obNode)
{
@@ -155,23 +213,122 @@ static void updateDepgraph(ModifierData *md, DagForest *forest,
}
}
else {
+ BKE_main_id_tag_listbase(&bmain->object, true);
base = scene->base.first;
for (; base; base = base->next) {
- SmokeModifierData *smd2 = (SmokeModifierData *)modifiers_findByType(base->object, eModifierType_Smoke);
+ update_depsgraph_flow_coll_object(forest, obNode, base->object);
+ }
+ }
+ /* add relation to all "smoke flow" force fields */
+ base = scene->base.first;
+ BKE_main_id_tag_listbase(&bmain->object, true);
+ for (; base; base = base->next) {
+ update_depsgraph_field_source_object(forest, obNode, ob, base->object);
+ }
+ }
+}
- if (smd2 && (((smd2->type & MOD_SMOKE_TYPE_FLOW) && smd2->flow) || ((smd2->type & MOD_SMOKE_TYPE_COLL) && smd2->coll))) {
- DagNode *curNode = dag_get_node(forest, base->object);
- dag_add_relation(forest, curNode, obNode, DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Smoke Flow/Coll");
+static void update_depsgraph_flow_coll_object_new(struct DepsNodeHandle *node,
+ Object *object2)
+{
+ SmokeModifierData *smd;
+ if ((object2->id.flag & LIB_DOIT) == 0) {
+ return;
+ }
+ object2->id.flag &= ~LIB_DOIT;
+ smd = (SmokeModifierData *)modifiers_findByType(object2, eModifierType_Smoke);
+ if (smd && (((smd->type & MOD_SMOKE_TYPE_FLOW) && smd->flow) ||
+ ((smd->type & MOD_SMOKE_TYPE_COLL) && smd->coll)))
+ {
+ DEG_add_object_relation(node, object2, DEG_OB_COMP_TRANSFORM, "Smoke Flow/Coll");
+ DEG_add_object_relation(node, object2, DEG_OB_COMP_GEOMETRY, "Smoke Flow/Coll");
+ }
+ if ((object2->transflag & OB_DUPLIGROUP) && object2->dup_group) {
+ GroupObject *go;
+ for (go = object2->dup_group->gobject.first;
+ go != NULL;
+ go = go->next)
+ {
+ if (go->ob == NULL) {
+ continue;
+ }
+ update_depsgraph_flow_coll_object_new(node, go->ob);
+ }
+ }
+}
+
+static void update_depsgraph_field_source_object_new(struct DepsNodeHandle *node,
+ Object *object,
+ Object *object2)
+{
+ if ((object2->id.flag & LIB_DOIT) == 0) {
+ return;
+ }
+ object2->id.flag &= ~LIB_DOIT;
+ if (object2->pd && object2->pd->forcefield == PFIELD_SMOKEFLOW && object2->pd->f_source == object) {
+ DEG_add_object_relation(node, object2, DEG_OB_COMP_TRANSFORM, "Field Source Object");
+ DEG_add_object_relation(node, object2, DEG_OB_COMP_GEOMETRY, "Field Source Object");
+ }
+ if ((object2->transflag & OB_DUPLIGROUP) && object2->dup_group) {
+ GroupObject *go;
+ for (go = object2->dup_group->gobject.first;
+ go != NULL;
+ go = go->next)
+ {
+ if (go->ob == NULL) {
+ continue;
+ }
+ update_depsgraph_field_source_object_new(node, object, go->ob);
+ }
+ }
+}
+
+static void updateDepsgraph(ModifierData *md,
+ struct Main *bmain,
+ struct Scene *scene,
+ Object *ob,
+ struct DepsNodeHandle *node)
+{
+ SmokeModifierData *smd = (SmokeModifierData *)md;
+ Base *base;
+ if (smd && (smd->type & MOD_SMOKE_TYPE_DOMAIN) && smd->domain) {
+ if (smd->domain->fluid_group || smd->domain->coll_group) {
+ GroupObject *go = NULL;
+ if (smd->domain->fluid_group != NULL) {
+ for (go = smd->domain->fluid_group->gobject.first; go; go = go->next) {
+ if (go->ob != NULL) {
+ SmokeModifierData *smd2 = (SmokeModifierData *)modifiers_findByType(go->ob, eModifierType_Smoke);
+ /* Check for initialized smoke object. */
+ if (smd2 && (smd2->type & MOD_SMOKE_TYPE_FLOW) && smd2->flow) {
+ DEG_add_object_relation(node, go->ob, DEG_OB_COMP_TRANSFORM, "Smoke Flow");
+ }
+ }
+ }
+ }
+ if (smd->domain->coll_group != NULL) {
+ for (go = smd->domain->coll_group->gobject.first; go; go = go->next) {
+ if (go->ob != NULL) {
+ SmokeModifierData *smd2 = (SmokeModifierData *)modifiers_findByType(go->ob, eModifierType_Smoke);
+ /* Check for initialized smoke object. */
+ if (smd2 && (smd2->type & MOD_SMOKE_TYPE_COLL) && smd2->coll) {
+ DEG_add_object_relation(node, go->ob, DEG_OB_COMP_TRANSFORM, "Smoke Coll");
+ }
+ }
}
}
}
+ else {
+ BKE_main_id_tag_listbase(&bmain->object, true);
+ base = scene->base.first;
+ for (; base; base = base->next) {
+ update_depsgraph_flow_coll_object_new(node, base->object);
+ }
+ }
/* add relation to all "smoke flow" force fields */
base = scene->base.first;
+ BKE_main_id_tag_listbase(&bmain->object, true);
for (; base; base = base->next) {
- if (base->object->pd && base->object->pd->forcefield == PFIELD_SMOKEFLOW && base->object->pd->f_source == ob) {
- DagNode *node2 = dag_get_node(forest, base->object);
- dag_add_relation(forest, obNode, node2, DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Field Source Object");
- }
+ update_depsgraph_field_source_object_new(node, ob, base->object);
}
}
}
@@ -217,6 +374,7 @@ ModifierTypeInfo modifierType_Smoke = {
/* freeData */ freeData,
/* isDisabled */ NULL,
/* updateDepgraph */ updateDepgraph,
+ /* updateDepsgraph */ updateDepsgraph,
/* dependsOnTime */ dependsOnTime,
/* dependsOnNormals */ NULL,
/* foreachObjectLink */ NULL,
diff --git a/source/blender/modifiers/intern/MOD_smooth.c b/source/blender/modifiers/intern/MOD_smooth.c
index d1ad8f1fcfc..d45c8528510 100644
--- a/source/blender/modifiers/intern/MOD_smooth.c
+++ b/source/blender/modifiers/intern/MOD_smooth.c
@@ -262,6 +262,7 @@ ModifierTypeInfo modifierType_Smooth = {
/* freeData */ NULL,
/* isDisabled */ isDisabled,
/* updateDepgraph */ NULL,
+ /* updateDepsgraph */ NULL,
/* dependsOnTime */ NULL,
/* dependsOnNormals */ NULL,
/* foreachObjectLink */ NULL,
diff --git a/source/blender/modifiers/intern/MOD_softbody.c b/source/blender/modifiers/intern/MOD_softbody.c
index 5f5347a46b0..d958badc33c 100644
--- a/source/blender/modifiers/intern/MOD_softbody.c
+++ b/source/blender/modifiers/intern/MOD_softbody.c
@@ -80,6 +80,7 @@ ModifierTypeInfo modifierType_Softbody = {
/* freeData */ NULL,
/* isDisabled */ NULL,
/* updateDepgraph */ NULL,
+ /* updateDepsgraph */ NULL,
/* dependsOnTime */ dependsOnTime,
/* dependsOnNormals */ NULL,
/* foreachObjectLink */ NULL,
diff --git a/source/blender/modifiers/intern/MOD_solidify.c b/source/blender/modifiers/intern/MOD_solidify.c
index 813ef285058..ca2dcfec3a3 100644
--- a/source/blender/modifiers/intern/MOD_solidify.c
+++ b/source/blender/modifiers/intern/MOD_solidify.c
@@ -220,7 +220,7 @@ static DerivedMesh *applyModifier(
const unsigned int numEdges = (unsigned int)dm->getNumEdges(dm);
const unsigned int numFaces = (unsigned int)dm->getNumPolys(dm);
const unsigned int numLoops = (unsigned int)dm->getNumLoops(dm);
- unsigned int newLoops = 0, newFaces = 0, newEdges = 0, newVerts = 0;
+ unsigned int newLoops = 0, newFaces = 0, newEdges = 0, newVerts = 0, rimVerts = 0;
/* only use material offsets if we have 2 or more materials */
const short mat_nr_max = ob->totcol > 1 ? ob->totcol - 1 : 0;
@@ -255,7 +255,7 @@ static DerivedMesh *applyModifier(
/* weights */
MDeformVert *dvert;
- const int defgrp_invert = ((smd->flag & MOD_SOLIDIFY_VGROUP_INV) != 0);
+ const bool defgrp_invert = (smd->flag & MOD_SOLIDIFY_VGROUP_INV) != 0;
int defgrp_index;
/* array size is doubled in case of using a shell */
@@ -298,7 +298,7 @@ static DerivedMesh *applyModifier(
/* save doing 2 loops here... */
#if 0
- fill_vn_i(edge_users, numEdges, INVALID_UNUSED);
+ copy_vn_i(edge_users, numEdges, INVALID_UNUSED);
#endif
for (eidx = 0, ed = orig_medge; eidx < numEdges; eidx++, ed++) {
@@ -343,7 +343,7 @@ static DerivedMesh *applyModifier(
if (BLI_BITMAP_TEST(orig_mvert_tag, i)) {
old_vert_arr[i] = STACK_SIZE(new_vert_arr);
STACK_PUSH(new_vert_arr, i);
- newEdges++;
+ rimVerts++;
}
else {
old_vert_arr[i] = INVALID_UNUSED;
@@ -353,16 +353,26 @@ static DerivedMesh *applyModifier(
MEM_freeN(orig_mvert_tag);
}
+ if (do_shell == false) {
+ /* only add rim vertices */
+ newVerts = rimVerts;
+ /* each extruded face needs an opposite edge */
+ newEdges = newFaces;
+ }
+ else {
+ /* (stride == 2) in this case, so no need to add newVerts/newEdges */
+ BLI_assert(newVerts == 0);
+ BLI_assert(newEdges == 0);
+ }
+
if (smd->flag & MOD_SOLIDIFY_NORMAL_CALC) {
vert_nors = MEM_callocN(sizeof(float) * (size_t)numVerts * 3, "mod_solid_vno_hq");
dm_calc_normal(dm, face_nors, vert_nors);
}
- newVerts = do_shell ? 0 : newEdges;
-
result = CDDM_from_template(dm,
(int)((numVerts * stride) + newVerts),
- (int)((numEdges * stride) + newEdges + newVerts), 0,
+ (int)((numEdges * stride) + newEdges + rimVerts), 0,
(int)((numLoops * stride) + newLoops),
(int)((numFaces * stride) + newFaces));
@@ -495,7 +505,7 @@ static DerivedMesh *applyModifier(
unsigned int i;
vert_lens = MEM_mallocN(sizeof(float) * numVerts, "vert_lens");
- fill_vn_fl(vert_lens, (int)numVerts, FLT_MAX);
+ copy_vn_fl(vert_lens, (int)numVerts, FLT_MAX);
for (i = 0; i < numEdges; i++) {
const float ed_len_sq = len_squared_v3v3(mvert[medge[i].v1].co, mvert[medge[i].v2].co);
vert_lens[medge[i].v1] = min_ff(vert_lens[medge[i].v1], ed_len_sq);
@@ -659,10 +669,10 @@ static DerivedMesh *applyModifier(
}
if (do_clamp) {
- float *vert_lens_sq = MEM_callocN(sizeof(float) * numVerts, "vert_lens");
+ float *vert_lens_sq = MEM_mallocN(sizeof(float) * numVerts, "vert_lens");
const float offset = fabsf(smd->offset) * smd->offset_clamp;
const float offset_sq = offset * offset;
- fill_vn_fl(vert_lens_sq, (int)numVerts, FLT_MAX);
+ copy_vn_fl(vert_lens_sq, (int)numVerts, FLT_MAX);
for (i = 0; i < numEdges; i++) {
const float ed_len = len_squared_v3v3(mvert[medge[i].v1].co, mvert[medge[i].v2].co);
vert_lens_sq[medge[i].v1] = min_ff(vert_lens_sq[medge[i].v1], ed_len);
@@ -759,9 +769,9 @@ static DerivedMesh *applyModifier(
/* add faces & edges */
origindex_edge = result->getEdgeDataArray(result, CD_ORIGINDEX);
- ed = &medge[(numEdges * stride) + newVerts]; /* start after copied edges */
- orig_ed = &origindex_edge[(numEdges * stride) + newVerts];
- for (i = 0; i < newEdges; i++, ed++, orig_ed++) {
+ ed = &medge[(numEdges * stride) + newEdges]; /* start after copied edges */
+ orig_ed = &origindex_edge[(numEdges * stride) + newEdges];
+ for (i = 0; i < rimVerts; i++, ed++, orig_ed++) {
ed->v1 = new_vert_arr[i];
ed->v2 = (do_shell ? new_vert_arr[i] : i) + numVerts;
ed->flag |= ME_EDGEDRAW;
@@ -816,26 +826,26 @@ static DerivedMesh *applyModifier(
ml[j++].e = eidx;
ml[j].v = ed->v2;
- ml[j++].e = (numEdges * stride) + old_vert_arr[ed->v2] + newVerts;
+ ml[j++].e = (numEdges * stride) + old_vert_arr[ed->v2] + newEdges;
ml[j].v = (do_shell ? ed->v2 : old_vert_arr[ed->v2]) + numVerts;
ml[j++].e = (do_shell ? eidx : i) + numEdges;
ml[j].v = (do_shell ? ed->v1 : old_vert_arr[ed->v1]) + numVerts;
- ml[j++].e = (numEdges * stride) + old_vert_arr[ed->v1] + newVerts;
+ ml[j++].e = (numEdges * stride) + old_vert_arr[ed->v1] + newEdges;
}
else {
ml[j].v = ed->v2;
ml[j++].e = eidx;
ml[j].v = ed->v1;
- ml[j++].e = (numEdges * stride) + old_vert_arr[ed->v1] + newVerts;
+ ml[j++].e = (numEdges * stride) + old_vert_arr[ed->v1] + newEdges;
ml[j].v = (do_shell ? ed->v1 : old_vert_arr[ed->v1]) + numVerts;
ml[j++].e = (do_shell ? eidx : i) + numEdges;
ml[j].v = (do_shell ? ed->v2 : old_vert_arr[ed->v2]) + numVerts;
- ml[j++].e = (numEdges * stride) + old_vert_arr[ed->v2] + newVerts;
+ ml[j++].e = (numEdges * stride) + old_vert_arr[ed->v2] + newEdges;
}
origindex_edge[ml[j - 3].e] = ORIGINDEX_NONE;
@@ -877,7 +887,7 @@ static DerivedMesh *applyModifier(
#ifdef SOLIDIFY_SIDE_NORMALS
if (do_side_normals) {
ed = medge + (numEdges * stride);
- for (i = 0; i < newEdges; i++, ed++) {
+ for (i = 0; i < rimVerts; i++, ed++) {
float nor_cpy[3];
short *nor_short;
int k;
@@ -951,6 +961,7 @@ ModifierTypeInfo modifierType_Solidify = {
/* freeData */ NULL,
/* isDisabled */ NULL,
/* updateDepgraph */ NULL,
+ /* updateDepsgraph */ NULL,
/* dependsOnTime */ NULL,
/* dependsOnNormals */ dependsOnNormals,
/* foreachObjectLink */ NULL,
diff --git a/source/blender/modifiers/intern/MOD_subsurf.c b/source/blender/modifiers/intern/MOD_subsurf.c
index f17858264f8..cbd7bc97768 100644
--- a/source/blender/modifiers/intern/MOD_subsurf.c
+++ b/source/blender/modifiers/intern/MOD_subsurf.c
@@ -38,10 +38,15 @@
#include "DNA_scene_types.h"
#include "DNA_object_types.h"
+#ifdef WITH_OPENSUBDIV
+# include "DNA_userdef_types.h"
+#endif
+
#include "BLI_utildefines.h"
#include "BKE_cdderivedmesh.h"
+#include "BKE_depsgraph.h"
#include "BKE_scene.h"
#include "BKE_subsurf.h"
@@ -88,7 +93,7 @@ static bool isDisabled(ModifierData *md, int useRenderParams)
SubsurfModifierData *smd = (SubsurfModifierData *) md;
int levels = (useRenderParams) ? smd->renderLevels : smd->levels;
- return get_render_subsurf_level(&md->scene->r, levels) == 0;
+ return get_render_subsurf_level(&md->scene->r, levels, useRenderParams != 0) == 0;
}
static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
@@ -101,17 +106,45 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
const bool useRenderParams = (flag & MOD_APPLY_RENDER) != 0;
const bool isFinalCalc = (flag & MOD_APPLY_USECACHE) != 0;
+#ifdef WITH_OPENSUBDIV
+ const bool allow_gpu = (flag & MOD_APPLY_ALLOW_GPU) != 0;
+ const bool do_cddm_convert = useRenderParams || (!isFinalCalc && !smd->use_opensubdiv);
+#else
+ const bool do_cddm_convert = useRenderParams || !isFinalCalc;
+#endif
+
if (useRenderParams)
subsurf_flags |= SUBSURF_USE_RENDER_PARAMS;
if (isFinalCalc)
subsurf_flags |= SUBSURF_IS_FINAL_CALC;
if (ob->mode & OB_MODE_EDIT)
subsurf_flags |= SUBSURF_IN_EDIT_MODE;
-
+
+#ifdef WITH_OPENSUBDIV
+ /* TODO(sergey): Not entirely correct, modifiers on top of subsurf
+ * could be disabled.
+ */
+ if (md->next == NULL &&
+ allow_gpu &&
+ do_cddm_convert == false &&
+ smd->use_opensubdiv)
+ {
+ if (U.opensubdiv_compute_type == USER_OPENSUBDIV_COMPUTE_NONE) {
+ modifier_setError(md, "OpenSubdiv is disabled in User Preferences");
+ }
+ else if ((DAG_get_eval_flags_for_object(md->scene, ob) & DAG_EVAL_NEED_CPU) == 0) {
+ subsurf_flags |= SUBSURF_USE_GPU_BACKEND;
+ }
+ else {
+ modifier_setError(md, "OpenSubdiv is disabled due to dependencies");
+ }
+ }
+#endif
+
result = subsurf_make_derived_from_derived(derivedData, smd, NULL, subsurf_flags);
result->cd_flag = derivedData->cd_flag;
-
- if (useRenderParams || !isFinalCalc) {
+
+ if (do_cddm_convert) {
DerivedMesh *cddm = CDDM_copy(result);
result->release(result);
result = cddm;
@@ -129,12 +162,30 @@ static DerivedMesh *applyModifierEM(ModifierData *md, Object *UNUSED(ob),
DerivedMesh *result;
/* 'orco' using editmode flags would cause cache to be used twice in editbmesh_calc_modifiers */
SubsurfFlags ss_flags = (flag & MOD_APPLY_ORCO) ? 0 : (SUBSURF_FOR_EDIT_MODE | SUBSURF_IN_EDIT_MODE);
+#ifdef WITH_OPENSUBDIV
+ const bool allow_gpu = (flag & MOD_APPLY_ALLOW_GPU) != 0;
+ if (md->next == NULL && allow_gpu && smd->use_opensubdiv) {
+ modifier_setError(md, "OpenSubdiv is not supported in edit mode");
+ }
+#endif
result = subsurf_make_derived_from_derived(derivedData, smd, NULL, ss_flags);
return result;
}
+static bool dependsOnNormals(ModifierData *md)
+{
+#ifdef WITH_OPENSUBDIV
+ SubsurfModifierData *smd = (SubsurfModifierData *) md;
+ if (smd->use_opensubdiv && md->next == NULL) {
+ return true;
+ }
+#else
+ UNUSED_VARS(md);
+#endif
+ return false;
+}
ModifierTypeInfo modifierType_Subsurf = {
/* name */ "Subsurf",
@@ -159,8 +210,9 @@ ModifierTypeInfo modifierType_Subsurf = {
/* freeData */ freeData,
/* isDisabled */ isDisabled,
/* updateDepgraph */ NULL,
+ /* updateDepsgraph */ NULL,
/* dependsOnTime */ NULL,
- /* dependsOnNormals */ NULL,
+ /* dependsOnNormals */ dependsOnNormals,
/* foreachObjectLink */ NULL,
/* foreachIDLink */ NULL,
/* foreachTexLink */ NULL,
diff --git a/source/blender/modifiers/intern/MOD_surface.c b/source/blender/modifiers/intern/MOD_surface.c
index 1c462f12f9f..ff5e5f643a7 100644
--- a/source/blender/modifiers/intern/MOD_surface.c
+++ b/source/blender/modifiers/intern/MOD_surface.c
@@ -158,8 +158,8 @@ static void deformVerts(ModifierData *md, Object *ob,
else
surmd->bvhtree = MEM_callocN(sizeof(BVHTreeFromMesh), "BVHTreeFromMesh");
- if (surmd->dm->getNumTessFaces(surmd->dm))
- bvhtree_from_mesh_faces(surmd->bvhtree, surmd->dm, 0.0, 2, 6);
+ if (surmd->dm->getNumPolys(surmd->dm))
+ bvhtree_from_mesh_looptri(surmd->bvhtree, surmd->dm, 0.0, 2, 6);
else
bvhtree_from_mesh_edges(surmd->bvhtree, surmd->dm, 0.0, 2, 6);
}
@@ -186,6 +186,7 @@ ModifierTypeInfo modifierType_Surface = {
/* freeData */ freeData,
/* isDisabled */ NULL,
/* updateDepgraph */ NULL,
+ /* updateDepsgraph */ NULL,
/* dependsOnTime */ dependsOnTime,
/* dependsOnNormals */ NULL,
/* foreachObjectLink */ NULL,
diff --git a/source/blender/modifiers/intern/MOD_triangulate.c b/source/blender/modifiers/intern/MOD_triangulate.c
index 4cae3d662db..194a46b6f28 100644
--- a/source/blender/modifiers/intern/MOD_triangulate.c
+++ b/source/blender/modifiers/intern/MOD_triangulate.c
@@ -31,7 +31,6 @@
#include "BKE_cdderivedmesh.h"
#include "BKE_modifier.h"
-#include "BKE_editmesh.h"
#include "bmesh.h"
#include "bmesh_tools.h"
@@ -120,6 +119,7 @@ ModifierTypeInfo modifierType_Triangulate = {
/* freeData */ NULL,
/* isDisabled */ NULL,
/* updateDepgraph */ NULL,
+ /* updateDepsgraph */ NULL,
/* dependsOnTime */ NULL,
/* dependsOnNormals */ NULL,
/* foreachObjectLink */ NULL,
diff --git a/source/blender/modifiers/intern/MOD_util.c b/source/blender/modifiers/intern/MOD_util.c
index 829c2b88995..be6f7af7791 100644
--- a/source/blender/modifiers/intern/MOD_util.c
+++ b/source/blender/modifiers/intern/MOD_util.c
@@ -32,7 +32,6 @@
#include <string.h>
-#include "DNA_curve_types.h"
#include "DNA_image_types.h"
#include "DNA_meshdata_types.h"
#include "DNA_modifier_types.h"
@@ -48,8 +47,6 @@
#include "BKE_image.h"
#include "BKE_lattice.h"
#include "BKE_mesh.h"
-#include "BKE_displist.h"
-#include "BKE_scene.h"
#include "BKE_modifier.h"
@@ -58,13 +55,11 @@
#include "MEM_guardedalloc.h"
-#include "RE_shader_ext.h"
-
#ifdef OPENNL_THREADING_HACK
#include "BLI_threads.h"
#endif
-void modifier_init_texture(Scene *scene, Tex *tex)
+void modifier_init_texture(const Scene *scene, Tex *tex)
{
if (!tex)
return;
@@ -164,8 +159,8 @@ DerivedMesh *get_cddm(Object *ob, struct BMEditMesh *em, DerivedMesh *dm, float
if (dm) {
if (dm->type != DM_TYPE_CDDM) {
dm = CDDM_copy(dm);
- CDDM_apply_vert_coords(dm, vertexCos);
}
+ CDDM_apply_vert_coords(dm, vertexCos);
if (use_normals) {
DM_ensure_normals(dm);
@@ -309,5 +304,8 @@ void modifier_type_init(ModifierTypeInfo *types[])
INIT_TYPE(MeshCache);
INIT_TYPE(LaplacianDeform);
INIT_TYPE(Wireframe);
+ INIT_TYPE(DataTransfer);
+ INIT_TYPE(NormalEdit);
+ INIT_TYPE(CorrectiveSmooth);
#undef INIT_TYPE
}
diff --git a/source/blender/modifiers/intern/MOD_util.h b/source/blender/modifiers/intern/MOD_util.h
index cb851a51c64..b74ff9c2a25 100644
--- a/source/blender/modifiers/intern/MOD_util.h
+++ b/source/blender/modifiers/intern/MOD_util.h
@@ -31,16 +31,16 @@
/* so modifier types match their defines */
#include "MOD_modifiertypes.h"
-struct CustomData;
+#include "DEG_depsgraph_build.h"
+
struct DerivedMesh;
struct MDeformVert;
struct ModifierData;
struct Object;
struct Scene;
struct Tex;
-struct TexResult;
-void modifier_init_texture(struct Scene *scene, struct Tex *texture);
+void modifier_init_texture(const struct Scene *scene, struct Tex *texture);
void get_texture_coords(struct MappingInfoModifierData *dmd, struct Object *ob, struct DerivedMesh *dm,
float (*co)[3], float (*texco)[3], int numVerts);
void modifier_vgroup_cache(struct ModifierData *md, float (*vertexCos)[3]);
diff --git a/source/blender/modifiers/intern/MOD_uvproject.c b/source/blender/modifiers/intern/MOD_uvproject.c
index 2ff93efdb86..1b1474ee666 100644
--- a/source/blender/modifiers/intern/MOD_uvproject.c
+++ b/source/blender/modifiers/intern/MOD_uvproject.c
@@ -49,10 +49,11 @@
#include "BKE_DerivedMesh.h"
#include "MOD_modifiertypes.h"
-#include "MOD_util.h"
#include "MEM_guardedalloc.h"
+
#include "depsgraph_private.h"
+#include "DEG_depsgraph_build.h"
static void initData(ModifierData *md)
{
@@ -105,6 +106,7 @@ static void foreachIDLink(ModifierData *md, Object *ob,
}
static void updateDepgraph(ModifierData *md, DagForest *forest,
+ struct Main *UNUSED(bmain),
struct Scene *UNUSED(scene),
Object *UNUSED(ob),
DagNode *obNode)
@@ -122,6 +124,21 @@ static void updateDepgraph(ModifierData *md, DagForest *forest,
}
}
+static void updateDepsgraph(ModifierData *md,
+ struct Main *UNUSED(bmain),
+ struct Scene *UNUSED(scene),
+ Object *UNUSED(ob),
+ struct DepsNodeHandle *node)
+{
+ UVProjectModifierData *umd = (UVProjectModifierData *)md;
+ int i;
+ for (i = 0; i < umd->num_projectors; ++i) {
+ if (umd->projectors[i] != NULL) {
+ DEG_add_object_relation(node, umd->projectors[i], DEG_OB_COMP_TRANSFORM, "UV Project Modifier");
+ }
+ }
+}
+
typedef struct Projector {
Object *ob; /* object this projector is derived from */
float projmat[4][4]; /* projection matrix */
@@ -139,7 +156,7 @@ static DerivedMesh *uvprojectModifier_do(UVProjectModifierData *umd,
Image *image = umd->image;
MPoly *mpoly, *mp;
MLoop *mloop;
- int override_image = ((umd->flags & MOD_UVPROJECT_OVERRIDEIMAGE) != 0);
+ const bool override_image = (umd->flags & MOD_UVPROJECT_OVERRIDEIMAGE) != 0;
Projector projectors[MOD_UVPROJECT_MAXPROJECTORS];
int num_projectors = 0;
char uvname[MAX_CUSTOMDATA_LAYER_NAME];
@@ -369,6 +386,7 @@ ModifierTypeInfo modifierType_UVProject = {
/* freeData */ NULL,
/* isDisabled */ NULL,
/* updateDepgraph */ updateDepgraph,
+ /* updateDepsgraph */ updateDepsgraph,
/* dependsOnTime */ NULL,
/* dependsOnNormals */ NULL,
/* foreachObjectLink */ foreachObjectLink,
diff --git a/source/blender/modifiers/intern/MOD_uvwarp.c b/source/blender/modifiers/intern/MOD_uvwarp.c
index f5ff30e35d9..3c4ca66485d 100644
--- a/source/blender/modifiers/intern/MOD_uvwarp.c
+++ b/source/blender/modifiers/intern/MOD_uvwarp.c
@@ -218,6 +218,7 @@ static void uv_warp_deps_object_bone(DagForest *forest, DagNode *obNode,
}
static void updateDepgraph(ModifierData *md, DagForest *forest,
+ struct Main *UNUSED(bmain),
struct Scene *UNUSED(scene),
Object *UNUSED(ob),
DagNode *obNode)
@@ -228,6 +229,30 @@ static void updateDepgraph(ModifierData *md, DagForest *forest,
uv_warp_deps_object_bone(forest, obNode, umd->object_dst, umd->bone_dst);
}
+static void uv_warp_deps_object_bone_new(struct DepsNodeHandle *node,
+ Object *object,
+ const char *bonename)
+{
+ if (object != NULL) {
+ if (bonename[0])
+ DEG_add_object_relation(node, object, DEG_OB_COMP_EVAL_POSE, "UVWarp Modifier");
+ else
+ DEG_add_object_relation(node, object, DEG_OB_COMP_TRANSFORM, "UVWarp Modifier");
+ }
+}
+
+static void updateDepsgraph(ModifierData *md,
+ struct Main *UNUSED(bmain),
+ struct Scene *UNUSED(scene),
+ Object *UNUSED(ob),
+ struct DepsNodeHandle *node)
+{
+ UVWarpModifierData *umd = (UVWarpModifierData *) md;
+
+ uv_warp_deps_object_bone_new(node, umd->object_src, umd->bone_src);
+ uv_warp_deps_object_bone_new(node, umd->object_dst, umd->bone_dst);
+}
+
ModifierTypeInfo modifierType_UVWarp = {
/* name */ "UVWarp",
/* structName */ "UVWarpModifierData",
@@ -248,6 +273,7 @@ ModifierTypeInfo modifierType_UVWarp = {
/* freeData */ NULL,
/* isDisabled */ NULL,
/* updateDepgraph */ updateDepgraph,
+ /* updateDepsgraph */ updateDepsgraph,
/* dependsOnTime */ NULL,
/* dependsOnNormals */ NULL,
/* foreachObjectLink */ foreachObjectLink,
diff --git a/source/blender/modifiers/intern/MOD_warp.c b/source/blender/modifiers/intern/MOD_warp.c
index f6714e79401..ae2dbd4a37c 100644
--- a/source/blender/modifiers/intern/MOD_warp.c
+++ b/source/blender/modifiers/intern/MOD_warp.c
@@ -136,7 +136,9 @@ static void foreachTexLink(ModifierData *md, Object *ob, TexWalkFunc walk, void
walk(userData, ob, md, "texture");
}
-static void updateDepgraph(ModifierData *md, DagForest *forest, struct Scene *UNUSED(scene),
+static void updateDepgraph(ModifierData *md, DagForest *forest,
+ struct Main *UNUSED(bmain),
+ struct Scene *UNUSED(scene),
Object *UNUSED(ob), DagNode *obNode)
{
WarpModifierData *wmd = (WarpModifierData *) md;
@@ -155,6 +157,22 @@ static void updateDepgraph(ModifierData *md, DagForest *forest, struct Scene *UN
}
}
+static void updateDepsgraph(ModifierData *md,
+ struct Main *UNUSED(bmain),
+ struct Scene *UNUSED(scene),
+ Object *UNUSED(ob),
+ struct DepsNodeHandle *node)
+{
+ WarpModifierData *wmd = (WarpModifierData *) md;
+ if (wmd->object_from != NULL && wmd->object_to != NULL) {
+ DEG_add_object_relation(node, wmd->object_from, DEG_OB_COMP_TRANSFORM, "Warp Modifier from");
+ DEG_add_object_relation(node, wmd->object_to, DEG_OB_COMP_TRANSFORM, "Warp Modifier to");
+ }
+ if ((wmd->texmapping == MOD_DISP_MAP_OBJECT) && wmd->map_object != NULL) {
+ DEG_add_object_relation(node, wmd->map_object, DEG_OB_COMP_TRANSFORM, "Warp Modifier map");
+ }
+}
+
static void warpModifier_do(WarpModifierData *wmd, Object *ob,
DerivedMesh *dm, float (*vertexCos)[3], int numVerts)
{
@@ -167,6 +185,7 @@ static void warpModifier_do(WarpModifierData *wmd, Object *ob,
float tmat[4][4];
+ const float falloff_radius_sq = SQUARE(wmd->falloff_radius);
float strength = wmd->strength;
float fac = 1.0f, weight;
int i;
@@ -179,6 +198,9 @@ static void warpModifier_do(WarpModifierData *wmd, Object *ob,
return;
modifier_get_vgroup(ob, dm, wmd->defgrp_name, &dvert, &defgrp_index);
+ if (dvert == NULL) {
+ defgrp_index = -1;
+ }
if (wmd->curfalloff == NULL) /* should never happen, but bad lib linking could cause it */
wmd->curfalloff = curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f);
@@ -222,17 +244,15 @@ static void warpModifier_do(WarpModifierData *wmd, Object *ob,
float *co = vertexCos[i];
if (wmd->falloff_type == eWarp_Falloff_None ||
- ((fac = len_v3v3(co, mat_from[3])) < wmd->falloff_radius &&
- (fac = (wmd->falloff_radius - fac) / wmd->falloff_radius)))
+ ((fac = len_squared_v3v3(co, mat_from[3])) < falloff_radius_sq &&
+ (fac = (wmd->falloff_radius - sqrtf(fac)) / wmd->falloff_radius)))
{
/* skip if no vert group found */
- if (dvert && defgrp_index != -1) {
+ if (defgrp_index != -1) {
dv = &dvert[i];
-
- if (dv) {
- weight = defvert_find_weight(dv, defgrp_index) * strength;
- if (weight <= 0.0f) /* Should never occure... */
- continue;
+ weight = defvert_find_weight(dv, defgrp_index) * strength;
+ if (weight <= 0.0f) {
+ continue;
}
}
@@ -263,6 +283,9 @@ static void warpModifier_do(WarpModifierData *wmd, Object *ob,
case eWarp_Falloff_Sphere:
fac = sqrtf(2 * fac - fac * fac);
break;
+ case eWarp_Falloff_InvSquare:
+ fac = fac * (2.0f - fac);
+ break;
}
fac *= weight;
@@ -274,27 +297,29 @@ static void warpModifier_do(WarpModifierData *wmd, Object *ob,
fac *= texres.tin;
}
- /* into the 'from' objects space */
- mul_m4_v3(mat_from_inv, co);
+ if (fac != 0.0f) {
+ /* into the 'from' objects space */
+ mul_m4_v3(mat_from_inv, co);
- if (fac >= 1.0f) {
- mul_m4_v3(mat_final, co);
- }
- else if (fac > 0.0f) {
- if (wmd->flag & MOD_WARP_VOLUME_PRESERVE) {
- /* interpolate the matrix for nicer locations */
- blend_m4_m4m4(tmat, mat_unit, mat_final, fac);
- mul_m4_v3(tmat, co);
+ if (fac == 1.0f) {
+ mul_m4_v3(mat_final, co);
}
else {
- float tvec[3];
- mul_v3_m4v3(tvec, mat_final, co);
- interp_v3_v3v3(co, co, tvec, fac);
+ if (wmd->flag & MOD_WARP_VOLUME_PRESERVE) {
+ /* interpolate the matrix for nicer locations */
+ blend_m4_m4m4(tmat, mat_unit, mat_final, fac);
+ mul_m4_v3(tmat, co);
+ }
+ else {
+ float tvec[3];
+ mul_v3_m4v3(tvec, mat_final, co);
+ interp_v3_v3v3(co, co, tvec, fac);
+ }
}
- }
- /* out of the 'from' objects space */
- mul_m4_v3(mat_from, co);
+ /* out of the 'from' objects space */
+ mul_m4_v3(mat_from, co);
+ }
}
}
@@ -363,6 +388,7 @@ ModifierTypeInfo modifierType_Warp = {
/* freeData */ freeData,
/* isDisabled */ isDisabled,
/* updateDepgraph */ updateDepgraph,
+ /* updateDepsgraph */ updateDepsgraph,
/* dependsOnTime */ dependsOnTime,
/* dependsOnNormals */ NULL,
/* foreachObjectLink */ foreachObjectLink,
diff --git a/source/blender/modifiers/intern/MOD_wave.c b/source/blender/modifiers/intern/MOD_wave.c
index 47e4c502a90..5b98f221489 100644
--- a/source/blender/modifiers/intern/MOD_wave.c
+++ b/source/blender/modifiers/intern/MOD_wave.c
@@ -131,6 +131,7 @@ static void foreachTexLink(ModifierData *md, Object *ob,
}
static void updateDepgraph(ModifierData *md, DagForest *forest,
+ struct Main *UNUSED(bmain),
Scene *UNUSED(scene),
Object *UNUSED(ob),
DagNode *obNode)
@@ -152,6 +153,21 @@ static void updateDepgraph(ModifierData *md, DagForest *forest,
}
}
+static void updateDepsgraph(ModifierData *md,
+ struct Main *UNUSED(bmain),
+ struct Scene *UNUSED(scene),
+ Object *UNUSED(ob),
+ struct DepsNodeHandle *node)
+{
+ WaveModifierData *wmd = (WaveModifierData *)md;
+ if (wmd->objectcenter != NULL) {
+ DEG_add_object_relation(node, wmd->objectcenter, DEG_OB_COMP_TRANSFORM, "Wave Modifier");
+ }
+ if (wmd->map_object != NULL) {
+ DEG_add_object_relation(node, wmd->map_object, DEG_OB_COMP_TRANSFORM, "Wave Modifier");
+ }
+}
+
static CustomDataMask requiredDataMask(Object *UNUSED(ob), ModifierData *md)
{
WaveModifierData *wmd = (WaveModifierData *)md;
@@ -380,6 +396,7 @@ ModifierTypeInfo modifierType_Wave = {
/* freeData */ freeData,
/* isDisabled */ NULL,
/* updateDepgraph */ updateDepgraph,
+ /* updateDepsgraph */ updateDepsgraph,
/* dependsOnTime */ dependsOnTime,
/* dependsOnNormals */ NULL,
/* foreachObjectLink */ foreachObjectLink,
diff --git a/source/blender/modifiers/intern/MOD_weightvg_util.c b/source/blender/modifiers/intern/MOD_weightvg_util.c
index 744b6b62c2a..da7230ed5af 100644
--- a/source/blender/modifiers/intern/MOD_weightvg_util.c
+++ b/source/blender/modifiers/intern/MOD_weightvg_util.c
@@ -34,7 +34,6 @@
#include "BLI_utildefines.h"
#include "DNA_color_types.h" /* CurveMapping. */
-#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
#include "DNA_modifier_types.h"
#include "DNA_object_types.h"
@@ -43,11 +42,9 @@
#include "BKE_cdderivedmesh.h"
#include "BKE_colortools.h" /* CurveMapping. */
#include "BKE_deform.h"
-#include "BKE_mesh.h"
#include "BKE_modifier.h"
#include "BKE_texture.h" /* Texture masking. */
-#include "depsgraph_private.h"
#include "MEM_guardedalloc.h"
#include "MOD_util.h"
#include "MOD_weightvg_util.h"
@@ -235,8 +232,6 @@ void weightvg_do_mask(int num, const int *indices, float *org_w, const float *ne
}
-
-
/* Applies weights to given vgroup (defgroup), and optionally add/remove vertices from the group.
* If dws is not NULL, it must be an array of MDeformWeight pointers of same length as weights (and
* defgrp_idx can then have any value).
@@ -252,7 +247,7 @@ void weightvg_update_vg(MDeformVert *dvert, int defgrp_idx, MDeformWeight **dws,
for (i = 0; i < num; i++) {
float w = weights[i];
MDeformVert *dv = &dvert[indices ? indices[i] : i];
- MDeformWeight *dw = dws ? dws[i] : defvert_find_index(dv, defgrp_idx);
+ MDeformWeight *dw = dws ? dws[i] : ((defgrp_idx >= 0) ? defvert_find_index(dv, defgrp_idx) : NULL);
/* Never allow weights out of [0.0, 1.0] range. */
CLAMP(w, 0.0f, 1.0f);
diff --git a/source/blender/modifiers/intern/MOD_weightvgedit.c b/source/blender/modifiers/intern/MOD_weightvgedit.c
index f36abcceae0..cba077a2f8d 100644
--- a/source/blender/modifiers/intern/MOD_weightvgedit.c
+++ b/source/blender/modifiers/intern/MOD_weightvgedit.c
@@ -34,7 +34,6 @@
#include "BLI_rand.h"
#include "DNA_color_types.h" /* CurveMapping. */
-#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
#include "DNA_modifier_types.h"
#include "DNA_object_types.h"
@@ -47,8 +46,9 @@
#include "BKE_texture.h" /* Texture masking. */
#include "depsgraph_private.h"
+#include "DEG_depsgraph_build.h"
+
#include "MEM_guardedalloc.h"
-#include "MOD_util.h"
#include "MOD_weightvg_util.h"
/**************************************
@@ -144,7 +144,9 @@ static void foreachTexLink(ModifierData *md, Object *ob, TexWalkFunc walk, void
walk(userData, ob, md, "mask_texture");
}
-static void updateDepgraph(ModifierData *md, DagForest *forest, struct Scene *UNUSED(scene),
+static void updateDepgraph(ModifierData *md, DagForest *forest,
+ struct Main *UNUSED(bmain),
+ struct Scene *UNUSED(scene),
Object *UNUSED(ob), DagNode *obNode)
{
WeightVGEditModifierData *wmd = (WeightVGEditModifierData *) md;
@@ -162,6 +164,21 @@ static void updateDepgraph(ModifierData *md, DagForest *forest, struct Scene *UN
"WeightVGEdit Modifier");
}
+static void updateDepsgraph(ModifierData *md,
+ struct Main *UNUSED(bmain),
+ struct Scene *UNUSED(scene),
+ Object *ob,
+ struct DepsNodeHandle *node)
+{
+ WeightVGEditModifierData *wmd = (WeightVGEditModifierData *)md;
+ if (wmd->mask_tex_map_obj != NULL && wmd->mask_tex_mapping == MOD_DISP_MAP_OBJECT) {
+ DEG_add_object_relation(node, wmd->mask_tex_map_obj, DEG_OB_COMP_TRANSFORM, "WeightVGEdit Modifier");
+ }
+ if (wmd->mask_tex_mapping == MOD_DISP_MAP_GLOBAL) {
+ DEG_add_object_relation(node, ob, DEG_OB_COMP_TRANSFORM, "WeightVGEdit Modifier");
+ }
+}
+
static bool isDisabled(ModifierData *md, int UNUSED(useRenderParams))
{
WeightVGEditModifierData *wmd = (WeightVGEditModifierData *) md;
@@ -292,6 +309,7 @@ ModifierTypeInfo modifierType_WeightVGEdit = {
/* freeData */ freeData,
/* isDisabled */ isDisabled,
/* updateDepgraph */ updateDepgraph,
+ /* updateDepsgraph */ updateDepsgraph,
/* dependsOnTime */ dependsOnTime,
/* dependsOnNormals */ NULL,
/* foreachObjectLink */ foreachObjectLink,
diff --git a/source/blender/modifiers/intern/MOD_weightvgmix.c b/source/blender/modifiers/intern/MOD_weightvgmix.c
index bdc1099d682..0649998e42d 100644
--- a/source/blender/modifiers/intern/MOD_weightvgmix.c
+++ b/source/blender/modifiers/intern/MOD_weightvgmix.c
@@ -43,8 +43,9 @@
#include "BKE_texture.h" /* Texture masking. */
#include "depsgraph_private.h"
+#include "DEG_depsgraph_build.h"
+
#include "MEM_guardedalloc.h"
-#include "MOD_util.h"
#include "MOD_weightvg_util.h"
@@ -192,7 +193,9 @@ static void foreachTexLink(ModifierData *md, Object *ob, TexWalkFunc walk, void
walk(userData, ob, md, "mask_texture");
}
-static void updateDepgraph(ModifierData *md, DagForest *forest, struct Scene *UNUSED(scene),
+static void updateDepgraph(ModifierData *md, DagForest *forest,
+ struct Main *UNUSED(bmain),
+ struct Scene *UNUSED(scene),
Object *UNUSED(ob), DagNode *obNode)
{
WeightVGMixModifierData *wmd = (WeightVGMixModifierData *) md;
@@ -210,6 +213,21 @@ static void updateDepgraph(ModifierData *md, DagForest *forest, struct Scene *UN
"WeightVGMix Modifier");
}
+static void updateDepsgraph(ModifierData *md,
+ struct Main *UNUSED(bmain),
+ struct Scene *UNUSED(scene),
+ Object *ob,
+ struct DepsNodeHandle *node)
+{
+ WeightVGMixModifierData *wmd = (WeightVGMixModifierData *) md;
+ if (wmd->mask_tex_map_obj != NULL && wmd->mask_tex_mapping == MOD_DISP_MAP_OBJECT) {
+ DEG_add_object_relation(node, wmd->mask_tex_map_obj, DEG_OB_COMP_TRANSFORM, "WeightVGMix Modifier");
+ }
+ if (wmd->mask_tex_mapping == MOD_DISP_MAP_GLOBAL) {
+ DEG_add_object_relation(node, ob, DEG_OB_COMP_TRANSFORM, "WeightVGMix Modifier");
+ }
+}
+
static bool isDisabled(ModifierData *md, int UNUSED(useRenderParams))
{
WeightVGMixModifierData *wmd = (WeightVGMixModifierData *) md;
@@ -233,7 +251,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, DerivedMesh *der
int i;
/* Flags. */
#if 0
- int do_prev = (wmd->modifier.mode & eModifierMode_DoWeightPreview);
+ const bool do_prev = (wmd->modifier.mode & eModifierMode_DoWeightPreview) != 0;
#endif
/* Get number of verts. */
@@ -249,7 +267,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, DerivedMesh *der
defgrp_index = defgroup_name_index(ob, wmd->defgrp_name_a);
if (defgrp_index == -1)
return dm;
- /* Get seconf vgroup idx from its name, if given. */
+ /* Get second vgroup idx from its name, if given. */
if (wmd->defgrp_name_b[0] != (char)0) {
defgrp_index_other = defgroup_name_index(ob, wmd->defgrp_name_b);
if (defgrp_index_other == -1)
@@ -280,7 +298,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, DerivedMesh *der
MDeformWeight *dw = defvert_find_index(&dvert[i], defgrp_index);
if (dw) {
tdw1[numIdx] = dw;
- tdw2[numIdx] = defvert_find_index(&dvert[i], defgrp_index_other);
+ tdw2[numIdx] = (defgrp_index_other >= 0) ? defvert_find_index(&dvert[i], defgrp_index_other) : NULL;
tidx[numIdx++] = i;
}
}
@@ -288,7 +306,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, DerivedMesh *der
case MOD_WVG_SET_B:
/* All vertices in second vgroup. */
for (i = 0; i < numVerts; i++) {
- MDeformWeight *dw = defvert_find_index(&dvert[i], defgrp_index_other);
+ MDeformWeight *dw = (defgrp_index_other >= 0) ? defvert_find_index(&dvert[i], defgrp_index_other) : NULL;
if (dw) {
tdw1[numIdx] = defvert_find_index(&dvert[i], defgrp_index);
tdw2[numIdx] = dw;
@@ -300,7 +318,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, DerivedMesh *der
/* All vertices in one vgroup or the other. */
for (i = 0; i < numVerts; i++) {
MDeformWeight *adw = defvert_find_index(&dvert[i], defgrp_index);
- MDeformWeight *bdw = defvert_find_index(&dvert[i], defgrp_index_other);
+ MDeformWeight *bdw = (defgrp_index_other >= 0) ? defvert_find_index(&dvert[i], defgrp_index_other) : NULL;
if (adw || bdw) {
tdw1[numIdx] = adw;
tdw2[numIdx] = bdw;
@@ -312,7 +330,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, DerivedMesh *der
/* All vertices in both vgroups. */
for (i = 0; i < numVerts; i++) {
MDeformWeight *adw = defvert_find_index(&dvert[i], defgrp_index);
- MDeformWeight *bdw = defvert_find_index(&dvert[i], defgrp_index_other);
+ MDeformWeight *bdw = (defgrp_index_other >= 0) ? defvert_find_index(&dvert[i], defgrp_index_other) : NULL;
if (adw && bdw) {
tdw1[numIdx] = adw;
tdw2[numIdx] = bdw;
@@ -325,7 +343,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, DerivedMesh *der
/* Use all vertices. */
for (i = 0; i < numVerts; i++) {
tdw1[i] = defvert_find_index(&dvert[i], defgrp_index);
- tdw2[i] = defvert_find_index(&dvert[i], defgrp_index_other);
+ tdw2[i] = (defgrp_index_other >= 0) ? defvert_find_index(&dvert[i], defgrp_index_other) : NULL;
}
numIdx = -1;
break;
@@ -421,6 +439,7 @@ ModifierTypeInfo modifierType_WeightVGMix = {
/* freeData */ freeData,
/* isDisabled */ isDisabled,
/* updateDepgraph */ updateDepgraph,
+ /* updateDepsgraph */ updateDepsgraph,
/* dependsOnTime */ dependsOnTime,
/* dependsOnNormals */ NULL,
/* foreachObjectLink */ foreachObjectLink,
diff --git a/source/blender/modifiers/intern/MOD_weightvgproximity.c b/source/blender/modifiers/intern/MOD_weightvgproximity.c
index 71d4742980e..08d7d77c74e 100644
--- a/source/blender/modifiers/intern/MOD_weightvgproximity.c
+++ b/source/blender/modifiers/intern/MOD_weightvgproximity.c
@@ -46,8 +46,9 @@
#include "BKE_texture.h" /* Texture masking. */
#include "depsgraph_private.h"
+#include "DEG_depsgraph_build.h"
+
#include "MEM_guardedalloc.h"
-#include "MOD_util.h"
#include "MOD_weightvg_util.h"
// #define USE_TIMEIT
@@ -97,7 +98,7 @@ static void get_vert2geom_distance(int numVerts, float (*v_cos)[3],
}
if (dist_f) {
/* Create a bvh-tree of the given target's faces. */
- bvhtree_from_mesh_faces(&treeData_f, target, 0.0, 2, 6);
+ bvhtree_from_mesh_looptri(&treeData_f, target, 0.0, 2, 6);
if (treeData_f.tree == NULL) {
OUT_OF_MEMORY();
return;
@@ -108,12 +109,8 @@ static void get_vert2geom_distance(int numVerts, float (*v_cos)[3],
nearest_v.index = nearest_e.index = nearest_f.index = -1;
/*nearest_v.dist = nearest_e.dist = nearest_f.dist = FLT_MAX;*/
/* Find the nearest vert/edge/face. */
-#ifndef __APPLE__
-#pragma omp parallel for default(none) private(i) firstprivate(nearest_v, nearest_e, nearest_f) \
- shared(treeData_v, treeData_e, treeData_f, numVerts, v_cos, dist_v, dist_e, \
- dist_f, loc2trgt) \
- schedule(static)
-#endif
+#pragma omp parallel for default(shared) private(i) firstprivate(nearest_v, nearest_e, nearest_f) \
+ schedule(static) if (numVerts > 10000)
for (i = 0; i < numVerts; i++) {
float tmp_co[3];
@@ -313,7 +310,9 @@ static void foreachTexLink(ModifierData *md, Object *ob, TexWalkFunc walk, void
walk(userData, ob, md, "mask_texture");
}
-static void updateDepgraph(ModifierData *md, DagForest *forest, struct Scene *UNUSED(scene),
+static void updateDepgraph(ModifierData *md, DagForest *forest,
+ struct Main *UNUSED(bmain),
+ struct Scene *UNUSED(scene),
Object *UNUSED(ob), DagNode *obNode)
{
WeightVGProximityModifierData *wmd = (WeightVGProximityModifierData *) md;
@@ -337,6 +336,24 @@ static void updateDepgraph(ModifierData *md, DagForest *forest, struct Scene *UN
"WeightVGProximity Modifier");
}
+static void updateDepsgraph(ModifierData *md,
+ struct Main *UNUSED(bmain),
+ struct Scene *UNUSED(scene),
+ Object *ob,
+ struct DepsNodeHandle *node)
+{
+ WeightVGProximityModifierData *wmd = (WeightVGProximityModifierData *)md;
+ if (wmd->proximity_ob_target != NULL) {
+ DEG_add_object_relation(node, wmd->proximity_ob_target, DEG_OB_COMP_TRANSFORM, "WeightVGProximity Modifier");
+ }
+ if (wmd->mask_tex_map_obj != NULL && wmd->mask_tex_mapping == MOD_DISP_MAP_OBJECT) {
+ DEG_add_object_relation(node, wmd->mask_tex_map_obj, DEG_OB_COMP_TRANSFORM, "WeightVGProximity Modifier");
+ }
+ if (wmd->mask_tex_mapping == MOD_DISP_MAP_GLOBAL) {
+ DEG_add_object_relation(node, ob, DEG_OB_COMP_TRANSFORM, "WeightVGProximity Modifier");
+ }
+}
+
static bool isDisabled(ModifierData *md, int UNUSED(useRenderParams))
{
WeightVGProximityModifierData *wmd = (WeightVGProximityModifierData *) md;
@@ -365,7 +382,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, DerivedMesh *der
int i;
/* Flags. */
#if 0
- int do_prev = (wmd->modifier.mode & eModifierMode_DoWeightPreview);
+ const bool do_prev = (wmd->modifier.mode & eModifierMode_DoWeightPreview) != 0;
#endif
#ifdef USE_TIMEIT
@@ -565,6 +582,7 @@ ModifierTypeInfo modifierType_WeightVGProximity = {
/* freeData */ freeData,
/* isDisabled */ isDisabled,
/* updateDepgraph */ updateDepgraph,
+ /* updateDepsgraph */ updateDepsgraph,
/* dependsOnTime */ dependsOnTime,
/* dependsOnNormals */ NULL,
/* foreachObjectLink */ foreachObjectLink,
diff --git a/source/blender/modifiers/intern/MOD_wireframe.c b/source/blender/modifiers/intern/MOD_wireframe.c
index 76986583ef5..fe21757d5c2 100644
--- a/source/blender/modifiers/intern/MOD_wireframe.c
+++ b/source/blender/modifiers/intern/MOD_wireframe.c
@@ -23,20 +23,14 @@
* \ingroup modifiers
*/
-#include "MEM_guardedalloc.h"
-
#include "DNA_object_types.h"
-#include "DNA_meshdata_types.h"
-#include "BLI_math.h"
#include "BLI_utildefines.h"
-#include "BLI_string.h"
#include "BKE_cdderivedmesh.h"
#include "BKE_deform.h"
#include "MOD_modifiertypes.h"
-#include "MOD_util.h"
#include "bmesh.h"
#include "tools/bmesh_wireframe.h"
@@ -60,7 +54,7 @@ static void copyData(ModifierData *md, ModifierData *target)
static bool isDisabled(ModifierData *UNUSED(md), int UNUSED(useRenderParams))
{
- return 0;
+ return false;
}
static CustomDataMask requiredDataMask(Object *UNUSED(ob), ModifierData *md)
@@ -75,7 +69,12 @@ static CustomDataMask requiredDataMask(Object *UNUSED(ob), ModifierData *md)
}
-static DerivedMesh *WireframeModifier_do( WireframeModifierData *wmd, Object *ob, DerivedMesh *dm)
+static bool dependsOnNormals(ModifierData *UNUSED(md))
+{
+ return true;
+}
+
+static DerivedMesh *WireframeModifier_do(WireframeModifierData *wmd, Object *ob, DerivedMesh *dm)
{
DerivedMesh *result;
BMesh *bm;
@@ -134,8 +133,9 @@ ModifierTypeInfo modifierType_Wireframe = {
/* freeData */ NULL,
/* isDisabled */ isDisabled,
/* updateDepgraph */ NULL,
+ /* updateDepsgraph */ NULL,
/* dependsOnTime */ NULL,
- /* dependsOnNormals */ NULL,
+ /* dependsOnNormals */ dependsOnNormals,
/* foreachObjectLink */ NULL,
/* foreachIDLink */ NULL,
/* foreachTexLink */ NULL,
diff --git a/source/blender/nodes/CMakeLists.txt b/source/blender/nodes/CMakeLists.txt
index 2293415aef0..d20881df150 100644
--- a/source/blender/nodes/CMakeLists.txt
+++ b/source/blender/nodes/CMakeLists.txt
@@ -29,15 +29,16 @@ set(INC
intern
shader
texture
- ../blenfont
../blenkernel
../blenlib
+ ../blentranslation
../gpu
../imbuf
../makesdna
../makesrna
../render/extern/include
../../../intern/guardedalloc
+ ../../../intern/glew-mx
)
set(INC_SYS
@@ -121,6 +122,7 @@ set(SRC
composite/nodes/node_composite_boxmask.c
composite/nodes/node_composite_ellipsemask.c
composite/nodes/node_composite_switch.c
+ composite/nodes/node_composite_switchview.c
composite/nodes/node_composite_colorcorrection.c
composite/nodes/node_composite_pixelate.c
@@ -198,6 +200,7 @@ set(SRC
shader/nodes/node_shader_tex_magic.c
shader/nodes/node_shader_tex_musgrave.c
shader/nodes/node_shader_tex_noise.c
+ shader/nodes/node_shader_tex_pointdensity.c
shader/nodes/node_shader_tex_sky.c
shader/nodes/node_shader_tex_voronoi.c
shader/nodes/node_shader_tex_wave.c
@@ -279,8 +282,14 @@ if(WITH_COMPOSITOR)
add_definitions(-DWITH_COMPOSITOR)
endif()
+add_definitions(${GL_DEFINITIONS})
+
if(WITH_FREESTYLE)
add_definitions(-DWITH_FREESTYLE)
endif()
+if(WITH_CYCLES AND WITH_CYCLES_DEBUG)
+ add_definitions(-DWITH_CYCLES_DEBUG)
+endif()
+
blender_add_lib(bf_nodes "${SRC}" "${INC}" "${INC_SYS}")
diff --git a/source/blender/nodes/NOD_composite.h b/source/blender/nodes/NOD_composite.h
index 961fdbfc0fb..0215db1dd55 100644
--- a/source/blender/nodes/NOD_composite.h
+++ b/source/blender/nodes/NOD_composite.h
@@ -133,6 +133,7 @@ void register_node_type_cmp_ellipsemask(void);
void register_node_type_cmp_bokehimage(void);
void register_node_type_cmp_bokehblur(void);
void register_node_type_cmp_switch(void);
+void register_node_type_cmp_switch_view(void);
void register_node_type_cmp_pixelate(void);
void register_node_type_cmp_trackpos(void);
void register_node_type_cmp_planetrackdeform(void);
diff --git a/source/blender/nodes/NOD_shader.h b/source/blender/nodes/NOD_shader.h
index 595a3b12bc6..4c0047f1d58 100644
--- a/source/blender/nodes/NOD_shader.h
+++ b/source/blender/nodes/NOD_shader.h
@@ -75,6 +75,7 @@ void register_node_type_sh_sepxyz(void);
void register_node_type_sh_combxyz(void);
void register_node_type_sh_hue_sat(void);
void register_node_type_sh_tex_brick(void);
+void register_node_type_sh_tex_pointdensity(void);
void register_node_type_sh_attribute(void);
void register_node_type_sh_geometry(void);
diff --git a/source/blender/nodes/NOD_socket.h b/source/blender/nodes/NOD_socket.h
index 81230456193..5c8875593e7 100644
--- a/source/blender/nodes/NOD_socket.h
+++ b/source/blender/nodes/NOD_socket.h
@@ -43,7 +43,6 @@
struct bNodeTree;
struct bNode;
-struct bNodeStack;
struct bNodeSocket *node_add_socket_from_template(struct bNodeTree *ntree, struct bNode *node, struct bNodeSocketTemplate *stemp, int in_out);
diff --git a/source/blender/nodes/NOD_static_types.h b/source/blender/nodes/NOD_static_types.h
index 166fa29fca0..9e1a0c926fa 100644
--- a/source/blender/nodes/NOD_static_types.h
+++ b/source/blender/nodes/NOD_static_types.h
@@ -71,7 +71,7 @@ DefNode( ShaderNode, SH_NODE_OUTPUT_LAMP, def_sh_output, "OU
DefNode( ShaderNode, SH_NODE_OUTPUT_WORLD, def_sh_output, "OUTPUT_WORLD", OutputWorld, "World Output", "" )
DefNode( ShaderNode, SH_NODE_OUTPUT_LINESTYLE, def_sh_output_linestyle,"OUTPUT_LINESTYLE", OutputLineStyle, "Line Style Output", "" )
DefNode( ShaderNode, SH_NODE_FRESNEL, 0, "FRESNEL", Fresnel, "Fresnel", "" )
-DefNode( ShaderNode, SH_NODE_LAYER_WEIGHT, 0, "LAYER_WEIGHT", LayerWeight, "Layer Weight", "" )
+DefNode( ShaderNode, SH_NODE_LAYER_WEIGHT, 0, "LAYER_WEIGHT", LayerWeight, "Layer Weight", "" )
DefNode( ShaderNode, SH_NODE_MIX_SHADER, 0, "MIX_SHADER", MixShader, "Mix Shader", "" )
DefNode( ShaderNode, SH_NODE_ADD_SHADER, 0, "ADD_SHADER", AddShader, "Add Shader", "" )
DefNode( ShaderNode, SH_NODE_ATTRIBUTE, def_sh_attribute, "ATTRIBUTE", Attribute, "Attribute", "" )
@@ -116,6 +116,7 @@ DefNode( ShaderNode, SH_NODE_TEX_MUSGRAVE, def_sh_tex_musgrave, "TE
DefNode( ShaderNode, SH_NODE_TEX_VORONOI, def_sh_tex_voronoi, "TEX_VORONOI", TexVoronoi, "Voronoi Texture", "" )
DefNode( ShaderNode, SH_NODE_TEX_CHECKER, def_sh_tex_checker, "TEX_CHECKER", TexChecker, "Checker Texture", "" )
DefNode( ShaderNode, SH_NODE_TEX_BRICK, def_sh_tex_brick, "TEX_BRICK", TexBrick, "Brick Texture", "" )
+DefNode( ShaderNode, SH_NODE_TEX_POINTDENSITY, def_sh_tex_pointdensity,"TEX_POINTDENSITY", TexPointDensity, "Point Density", "" )
DefNode( ShaderNode, SH_NODE_TEX_COORD, def_sh_tex_coord, "TEX_COORD", TexCoord, "Texture Coordinate","" )
DefNode( ShaderNode, SH_NODE_VECT_TRANSFORM, def_sh_vect_transform, "VECT_TRANSFORM", VectorTransform, "Vector Transform", "" )
DefNode( ShaderNode, SH_NODE_SEPHSV, 0, "SEPHSV", SeparateHSV, "Separate HSV", "" )
@@ -202,13 +203,14 @@ DefNode( CompositorNode, CMP_NODE_MASK_ELLIPSE, def_cmp_ellipsemask, "ELLIP
DefNode( CompositorNode, CMP_NODE_BOKEHIMAGE, def_cmp_bokehimage, "BOKEHIMAGE", BokehImage, "Bokeh Image", "" )
DefNode( CompositorNode, CMP_NODE_BOKEHBLUR, def_cmp_bokehblur, "BOKEHBLUR", BokehBlur, "Bokeh Blur", "" )
DefNode( CompositorNode, CMP_NODE_SWITCH, def_cmp_switch, "SWITCH", Switch, "Switch", "" )
+DefNode( CompositorNode, CMP_NODE_SWITCH_VIEW, def_cmp_switch_view, "VIEWSWITCH", SwitchView, "View Switch", "" )
DefNode( CompositorNode, CMP_NODE_COLORCORRECTION,def_cmp_colorcorrection,"COLORCORRECTION",ColorCorrection, "Color Correction", "" )
DefNode( CompositorNode, CMP_NODE_MASK, def_cmp_mask, "MASK", Mask, "Mask", "" )
DefNode( CompositorNode, CMP_NODE_KEYINGSCREEN, def_cmp_keyingscreen, "KEYINGSCREEN", KeyingScreen, "Keying Screen", "" )
DefNode( CompositorNode, CMP_NODE_KEYING, def_cmp_keying, "KEYING", Keying, "Keying", "" )
DefNode( CompositorNode, CMP_NODE_TRACKPOS, def_cmp_trackpos, "TRACKPOS", TrackPos, "Track Position", "" )
DefNode( CompositorNode, CMP_NODE_PIXELATE, 0, "PIXELATE", Pixelate, "Pixelate", "" )
-DefNode( CompositorNode, CMP_NODE_PLANETRACKDEFORM,def_cmp_planetrackdeform,"PLANETRACKDEFORM",PlaneTrackDeform,"Plane Track Deform","" )
+DefNode( CompositorNode, CMP_NODE_PLANETRACKDEFORM,def_cmp_planetrackdeform,"PLANETRACKDEFORM",PlaneTrackDeform,"Plane Track Deform","" )
DefNode( CompositorNode, CMP_NODE_CORNERPIN, 0, "CORNERPIN", CornerPin, "Corner Pin", "" )
DefNode( CompositorNode, CMP_NODE_SUNBEAMS, def_cmp_sunbeams, "SUNBEAMS", SunBeams, "Sun Beams", "" )
diff --git a/source/blender/nodes/SConscript b/source/blender/nodes/SConscript
index becf6e79d44..ad500725812 100644
--- a/source/blender/nodes/SConscript
+++ b/source/blender/nodes/SConscript
@@ -39,21 +39,22 @@ incs = [
'./shader',
'./texture',
'#/intern/guardedalloc',
- '#/extern/glew/include',
- '../blenfont',
+ env['BF_GLEW_INC'],
+ '#/intern/glew-mx',
'../blenkernel',
'../blenlib',
+ '../blentranslation',
'../gpu',
'../imbuf',
'../makesdna',
'../makesrna',
'../render/extern/include',
- env['BF_OPENGL_INC'],
env['BF_ZLIB_INC'],
]
incs = ' '.join(incs)
-defs = []
+defs = []
+defs += env['BF_GL_DEFINITIONS']
if env['WITH_BF_PYTHON']:
incs += ' ' + env['BF_PYTHON_INC']
@@ -75,6 +76,9 @@ if env['WITH_BF_COMPOSITOR']:
if env['WITH_BF_FREESTYLE']:
defs.append('WITH_FREESTYLE')
+if env['WITH_BF_CYCLES'] and env['WITH_BF_CYCLES_DEBUG']:
+ defs.append('WITH_CYCLES_DEBUG')
+
env.BlenderLib ( libname = 'bf_nodes', sources = sources, includes = Split(incs), defines = defs, libtype=['core','player'], priority = [190,105] )
env.BlenderLib ( libname = 'bf_cmpnodes', sources = cmpsources, includes = Split(incs), defines = defs, libtype=['core','player'], priority = [175,101] )
env.BlenderLib ( libname = 'bf_shdnodes', sources = shdsources, includes = Split(incs), defines = defs, libtype=['core','player'], priority = [175,101] )
diff --git a/source/blender/nodes/composite/node_composite_tree.c b/source/blender/nodes/composite/node_composite_tree.c
index 6d5b85da569..cb565bd5491 100644
--- a/source/blender/nodes/composite/node_composite_tree.c
+++ b/source/blender/nodes/composite/node_composite_tree.c
@@ -36,11 +36,8 @@
#include "DNA_scene_types.h"
#include "DNA_node_types.h"
-#include "BLI_listbase.h"
+#include "BLT_translation.h"
-#include "BLF_translation.h"
-
-#include "BKE_colortools.h"
#include "BKE_context.h"
#include "BKE_global.h"
#include "BKE_main.h"
@@ -50,8 +47,6 @@
#include "node_common.h"
#include "node_util.h"
-#include "PIL_time.h"
-
#include "RNA_access.h"
#include "NOD_composite.h"
@@ -231,16 +226,16 @@ void *COM_linker_hack = NULL;
void ntreeCompositExecTree(Scene *scene, bNodeTree *ntree, RenderData *rd, int rendering, int do_preview,
const ColorManagedViewSettings *view_settings,
- const ColorManagedDisplaySettings *display_settings)
+ const ColorManagedDisplaySettings *display_settings,
+ const char *view_name)
{
#ifdef WITH_COMPOSITOR
- COM_execute(rd, scene, ntree, rendering, view_settings, display_settings);
+ COM_execute(rd, scene, ntree, rendering, view_settings, display_settings, view_name);
#else
- (void)scene, (void)ntree, (void)rd, (void)rendering, (void)do_preview;
- (void)view_settings, (void)display_settings;
+ UNUSED_VARS(scene, ntree, rd, rendering, view_settings, display_settings, view_name);
#endif
- (void)do_preview;
+ UNUSED_VARS(do_preview);
}
/* *********************************************** */
diff --git a/source/blender/nodes/composite/node_composite_util.c b/source/blender/nodes/composite/node_composite_util.c
index 8e279cf6d68..bbfb07a316d 100644
--- a/source/blender/nodes/composite/node_composite_util.c
+++ b/source/blender/nodes/composite/node_composite_util.c
@@ -43,7 +43,7 @@ void cmp_node_update_default(bNodeTree *UNUSED(ntree), bNode *node)
for (sock = node->outputs.first; sock; sock = sock->next) {
if (sock->cache) {
//free_compbuf(sock->cache);
- //sock->cache= NULL;
+ //sock->cache = NULL;
}
}
node->need_exec = 1;
diff --git a/source/blender/nodes/composite/node_composite_util.h b/source/blender/nodes/composite/node_composite_util.h
index 3f9cfc03089..2dac0cc639a 100644
--- a/source/blender/nodes/composite/node_composite_util.h
+++ b/source/blender/nodes/composite/node_composite_util.h
@@ -40,7 +40,7 @@
#include "BLI_math.h"
#include "BLI_blenlib.h"
-#include "BLF_translation.h"
+#include "BLT_translation.h"
#include "BKE_colortools.h"
#include "BKE_image.h"
diff --git a/source/blender/nodes/composite/nodes/node_composite_boxmask.c b/source/blender/nodes/composite/nodes/node_composite_boxmask.c
index 9cb0f1c75c7..0390eb43da0 100644
--- a/source/blender/nodes/composite/nodes/node_composite_boxmask.c
+++ b/source/blender/nodes/composite/nodes/node_composite_boxmask.c
@@ -66,7 +66,3 @@ void register_node_type_cmp_boxmask(void)
nodeRegisterType(&ntype);
}
-
-
-
-
diff --git a/source/blender/nodes/composite/nodes/node_composite_colorbalance.c b/source/blender/nodes/composite/nodes/node_composite_colorbalance.c
index 65f2391983e..70e52d432cd 100644
--- a/source/blender/nodes/composite/nodes/node_composite_colorbalance.c
+++ b/source/blender/nodes/composite/nodes/node_composite_colorbalance.c
@@ -29,11 +29,8 @@
* \ingroup cmpnodes
*/
-
-
#include "node_composite_util.h"
-
/* ******************* Color Balance ********************************* */
static bNodeSocketTemplate cmp_node_colorbalance_in[] = {
{SOCK_FLOAT, 1, N_("Fac"), 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, PROP_FACTOR},
diff --git a/source/blender/nodes/composite/nodes/node_composite_common.c b/source/blender/nodes/composite/nodes/node_composite_common.c
index 36c12693bdf..75e7fa8fbac 100644
--- a/source/blender/nodes/composite/nodes/node_composite_common.c
+++ b/source/blender/nodes/composite/nodes/node_composite_common.c
@@ -35,7 +35,6 @@
#include "node_composite_util.h"
#include "NOD_common.h"
#include "node_common.h"
-#include "node_exec.h"
#include "BKE_node.h"
diff --git a/source/blender/nodes/composite/nodes/node_composite_composite.c b/source/blender/nodes/composite/nodes/node_composite_composite.c
index 41d417c2cb4..be9ed457150 100644
--- a/source/blender/nodes/composite/nodes/node_composite_composite.c
+++ b/source/blender/nodes/composite/nodes/node_composite_composite.c
@@ -31,10 +31,6 @@
#include "node_composite_util.h"
-#include "BKE_context.h"
-
-#include "RNA_access.h"
-
/* **************** COMPOSITE ******************** */
static bNodeSocketTemplate cmp_node_composite_in[] = {
{ SOCK_RGBA, 1, N_("Image"), 0.0f, 0.0f, 0.0f, 1.0f},
diff --git a/source/blender/nodes/composite/nodes/node_composite_defocus.c b/source/blender/nodes/composite/nodes/node_composite_defocus.c
index ef670b760c2..a3311755717 100644
--- a/source/blender/nodes/composite/nodes/node_composite_defocus.c
+++ b/source/blender/nodes/composite/nodes/node_composite_defocus.c
@@ -33,10 +33,6 @@
#include <limits.h>
-#include "BKE_context.h"
-
-#include "RNA_access.h"
-
/* ************ qdn: Defocus node ****************** */
static bNodeSocketTemplate cmp_node_defocus_in[] = {
{ SOCK_RGBA, 1, N_("Image"), 1.0f, 1.0f, 1.0f, 1.0f},
diff --git a/source/blender/nodes/composite/nodes/node_composite_image.c b/source/blender/nodes/composite/nodes/node_composite_image.c
index 659e582dc1d..4f02c106569 100644
--- a/source/blender/nodes/composite/nodes/node_composite_image.c
+++ b/source/blender/nodes/composite/nodes/node_composite_image.c
@@ -39,7 +39,9 @@
#include "BKE_global.h"
#include "BKE_main.h"
-#include "RNA_access.h"
+#ifdef WITH_CYCLES_DEBUG
+# include "RE_pipeline.h"
+#endif
/* **************** IMAGE (and RenderResult, multilayer image) ******************** */
@@ -75,6 +77,9 @@ static bNodeSocketTemplate cmp_node_rlayers_out[] = {
{ SOCK_RGBA, 0, N_("Subsurface Direct"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
{ SOCK_RGBA, 0, N_("Subsurface Indirect"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
{ SOCK_RGBA, 0, N_("Subsurface Color"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
+#ifdef WITH_CYCLES_DEBUG
+ { SOCK_RGBA, 0, N_("Debug"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
+#endif
{ -1, 0, "" }
};
@@ -162,6 +167,10 @@ static void cmp_node_image_add_render_pass_outputs(bNodeTree *ntree, bNode *node
cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_SUBSURFACE_INDIRECT, RRES_OUT_SUBSURFACE_INDIRECT);
if (passflag & SCE_PASS_SUBSURFACE_COLOR)
cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_SUBSURFACE_COLOR, RRES_OUT_SUBSURFACE_COLOR);
+
+#ifdef WITH_CYCLES_DEBUG
+ cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_DEBUG, RRES_OUT_DEBUG);
+#endif
}
static void cmp_node_image_add_multilayer_outputs(bNodeTree *ntree, bNode *node, RenderLayer *rl)
@@ -170,20 +179,35 @@ static void cmp_node_image_add_multilayer_outputs(bNodeTree *ntree, bNode *node,
NodeImageLayer *sockdata;
RenderPass *rpass;
int index;
+ int passflag = 0;
for (rpass = rl->passes.first, index = 0; rpass; rpass = rpass->next, ++index) {
int type;
if (rpass->channels == 1)
type = SOCK_FLOAT;
else
type = SOCK_RGBA;
-
- sock = nodeAddStaticSocket(ntree, node, SOCK_OUT, type, PROP_NONE, rpass->name, rpass->name);
+
+ /* we only need one socket per type */
+ if (passflag & rpass->passtype)
+ continue;
+
+ passflag |= rpass->passtype;
+
+ sock = nodeAddStaticSocket(ntree, node, SOCK_OUT, type, PROP_NONE, rpass->internal_name, rpass->internal_name);
/* extra socket info */
sockdata = MEM_callocN(sizeof(NodeImageLayer), "node image layer");
sock->storage = sockdata;
sockdata->pass_index = index;
sockdata->pass_flag = rpass->passtype;
+
+ if (rpass->passtype == SCE_PASS_COMBINED) {
+ sock = nodeAddStaticSocket(ntree, node, SOCK_OUT, SOCK_FLOAT, PROP_NONE, "Alpha", "Alpha");
+ sockdata = MEM_callocN(sizeof(NodeImageLayer), "node image layer");
+ sock->storage = sockdata;
+ sockdata->pass_index = index;
+ sockdata->pass_flag = rpass->passtype;
+ }
}
}
@@ -367,8 +391,12 @@ void register_node_type_cmp_image(void)
static void set_output_visible(bNode *node, int passflag, int index, int pass)
{
bNodeSocket *sock = BLI_findlink(&node->outputs, index);
+ bool pass_enabled = ((passflag & pass) != 0);
+#ifdef WITH_CYCLES_DEBUG
+ pass_enabled |= (pass == SCE_PASS_DEBUG);
+#endif
/* clear the SOCK_HIDDEN flag as well, in case a socket was hidden before */
- if (passflag & pass)
+ if (pass_enabled)
sock->flag &= ~(SOCK_HIDDEN | SOCK_UNAVAIL);
else
sock->flag |= SOCK_UNAVAIL;
@@ -427,6 +455,10 @@ void node_cmp_rlayers_force_hidden_passes(bNode *node)
set_output_visible(node, passflag, RRES_OUT_SUBSURFACE_DIRECT, SCE_PASS_SUBSURFACE_DIRECT);
set_output_visible(node, passflag, RRES_OUT_SUBSURFACE_INDIRECT, SCE_PASS_SUBSURFACE_INDIRECT);
set_output_visible(node, passflag, RRES_OUT_SUBSURFACE_COLOR, SCE_PASS_SUBSURFACE_COLOR);
+
+#ifdef WITH_CYCLES_DEBUG
+ set_output_visible(node, passflag, RRES_OUT_DEBUG, SCE_PASS_DEBUG);
+#endif
}
static void node_composit_init_rlayers(const bContext *C, PointerRNA *ptr)
@@ -441,7 +473,7 @@ static void node_composit_init_rlayers(const bContext *C, PointerRNA *ptr)
static int node_composit_poll_rlayers(bNodeType *UNUSED(ntype), bNodeTree *ntree)
{
- if (strcmp(ntree->idname, "CompositorNodeTree") == 0) {
+ if (STREQ(ntree->idname, "CompositorNodeTree")) {
Scene *scene;
/* XXX ugly: check if ntree is a local scene node tree.
diff --git a/source/blender/nodes/composite/nodes/node_composite_keying.c b/source/blender/nodes/composite/nodes/node_composite_keying.c
index 6b5def1ea93..6dd2bcc9002 100644
--- a/source/blender/nodes/composite/nodes/node_composite_keying.c
+++ b/source/blender/nodes/composite/nodes/node_composite_keying.c
@@ -30,16 +30,12 @@
* \ingroup cmpnodes
*/
-#include "BLF_translation.h"
+#include "BLT_translation.h"
#include "DNA_movieclip_types.h"
-#include "BKE_movieclip.h"
-
-#include "BLI_listbase.h"
#include "BLI_math_base.h"
#include "BLI_math_color.h"
-#include "BLI_voronoi.h"
#include "node_composite_util.h"
diff --git a/source/blender/nodes/composite/nodes/node_composite_keyingscreen.c b/source/blender/nodes/composite/nodes/node_composite_keyingscreen.c
index 9965b55e088..0cdf15c0412 100644
--- a/source/blender/nodes/composite/nodes/node_composite_keyingscreen.c
+++ b/source/blender/nodes/composite/nodes/node_composite_keyingscreen.c
@@ -30,16 +30,10 @@
* \ingroup cmpnodes
*/
-#include "BLF_translation.h"
-
#include "DNA_movieclip_types.h"
-#include "BKE_movieclip.h"
-
-#include "BLI_listbase.h"
#include "BLI_math_base.h"
#include "BLI_math_color.h"
-#include "BLI_voronoi.h"
#include "node_composite_util.h"
diff --git a/source/blender/nodes/composite/nodes/node_composite_mapValue.c b/source/blender/nodes/composite/nodes/node_composite_mapValue.c
index 22d16e93879..35096d57a4e 100644
--- a/source/blender/nodes/composite/nodes/node_composite_mapValue.c
+++ b/source/blender/nodes/composite/nodes/node_composite_mapValue.c
@@ -44,7 +44,7 @@ static bNodeSocketTemplate cmp_node_map_value_out[] = {
static void node_composit_init_map_value(bNodeTree *UNUSED(ntree), bNode *node)
{
- node->storage = add_tex_mapping(TEXMAP_TYPE_POINT);
+ node->storage = BKE_texture_mapping_add(TEXMAP_TYPE_POINT);
}
void register_node_type_cmp_map_value(void)
diff --git a/source/blender/nodes/composite/nodes/node_composite_mask.c b/source/blender/nodes/composite/nodes/node_composite_mask.c
index 83cea47db1b..dd05d5d83ad 100644
--- a/source/blender/nodes/composite/nodes/node_composite_mask.c
+++ b/source/blender/nodes/composite/nodes/node_composite_mask.c
@@ -30,12 +30,8 @@
* \ingroup cmpnodes
*/
-#include "BLF_translation.h"
-
#include "DNA_mask_types.h"
-#include "BKE_mask.h"
-
#include "node_composite_util.h"
/* **************** Translate ******************** */
diff --git a/source/blender/nodes/composite/nodes/node_composite_movieclip.c b/source/blender/nodes/composite/nodes/node_composite_movieclip.c
index fc0d8060644..0fece9dd4f6 100644
--- a/source/blender/nodes/composite/nodes/node_composite_movieclip.c
+++ b/source/blender/nodes/composite/nodes/node_composite_movieclip.c
@@ -30,13 +30,10 @@
* \ingroup cmpnodes
*/
-
#include "node_composite_util.h"
#include "BKE_context.h"
-#include "RNA_access.h"
-
static bNodeSocketTemplate cmp_node_movieclip_out[] = {
{ SOCK_RGBA, 0, N_("Image")},
{ SOCK_FLOAT, 0, N_("Alpha")},
diff --git a/source/blender/nodes/composite/nodes/node_composite_moviedistortion.c b/source/blender/nodes/composite/nodes/node_composite_moviedistortion.c
index 1d411aafe68..9c54009d2f1 100644
--- a/source/blender/nodes/composite/nodes/node_composite_moviedistortion.c
+++ b/source/blender/nodes/composite/nodes/node_composite_moviedistortion.c
@@ -34,8 +34,6 @@
#include "BKE_context.h"
-#include "RNA_access.h"
-
/* **************** Translate ******************** */
static bNodeSocketTemplate cmp_node_moviedistortion_in[] = {
diff --git a/source/blender/nodes/composite/nodes/node_composite_outputFile.c b/source/blender/nodes/composite/nodes/node_composite_outputFile.c
index 76101409ba7..7d1087435c2 100644
--- a/source/blender/nodes/composite/nodes/node_composite_outputFile.c
+++ b/source/blender/nodes/composite/nodes/node_composite_outputFile.c
@@ -40,9 +40,6 @@
#include "node_composite_util.h"
-#include "IMB_imbuf.h"
-#include "IMB_imbuf_types.h"
-
#include "intern/openexr/openexr_multi.h"
@@ -130,7 +127,7 @@ bNodeSocket *ntreeCompositOutputFileAddSocket(bNodeTree *ntree, bNode *node, con
BKE_imformat_defaults(&sockdata->format);
/* use node data format by default */
sockdata->use_node_format = true;
-
+
nimf->active_input = BLI_findindex(&node->inputs, sock);
return sock;
@@ -140,7 +137,7 @@ int ntreeCompositOutputFileRemoveActiveSocket(bNodeTree *ntree, bNode *node)
{
NodeImageMultiFile *nimf = node->storage;
bNodeSocket *sock = BLI_findlink(&node->inputs, nimf->active_input);
- int totinputs = BLI_countlist(&node->inputs);
+ int totinputs = BLI_listbase_count(&node->inputs);
if (!sock)
return 0;
@@ -192,7 +189,7 @@ static void init_output_file(const bContext *C, PointerRNA *ptr)
}
else
BKE_imformat_defaults(&nimf->format);
-
+
/* add one socket by default */
ntreeCompositOutputFileAddSocket(ntree, node, "Image", format);
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_planetrackdeform.c b/source/blender/nodes/composite/nodes/node_composite_planetrackdeform.c
index 7a15d6364dc..415427c360f 100644
--- a/source/blender/nodes/composite/nodes/node_composite_planetrackdeform.c
+++ b/source/blender/nodes/composite/nodes/node_composite_planetrackdeform.c
@@ -47,7 +47,8 @@ static bNodeSocketTemplate cmp_node_planetrackdeform_out[] = {
static void init(bNodeTree *UNUSED(ntree), bNode *node)
{
NodePlaneTrackDeformData *data = MEM_callocN(sizeof(NodePlaneTrackDeformData), "node plane track deform data");
-
+ data->motion_blur_samples = 16;
+ data->motion_blur_shutter = 0.5f;
node->storage = data;
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_stabilize2d.c b/source/blender/nodes/composite/nodes/node_composite_stabilize2d.c
index 28e2a2a205b..00791c278ae 100644
--- a/source/blender/nodes/composite/nodes/node_composite_stabilize2d.c
+++ b/source/blender/nodes/composite/nodes/node_composite_stabilize2d.c
@@ -30,13 +30,10 @@
* \ingroup cmpnodes
*/
-
#include "node_composite_util.h"
#include "BKE_context.h"
-#include "RNA_access.h"
-
/* **************** Translate ******************** */
static bNodeSocketTemplate cmp_node_stabilize2d_in[] = {
diff --git a/source/blender/nodes/composite/nodes/node_composite_switchview.c b/source/blender/nodes/composite/nodes/node_composite_switchview.c
new file mode 100644
index 00000000000..d805cf4d87f
--- /dev/null
+++ b/source/blender/nodes/composite/nodes/node_composite_switchview.c
@@ -0,0 +1,153 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2006 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s):
+ * Dalai Felinto
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/nodes/composite/nodes/node_composite_switchview.c
+ * \ingroup cmpnodes
+ */
+
+#include "BKE_context.h"
+#include "../node_composite_util.h"
+
+/* **************** SWITCH VIEW ******************** */
+static bNodeSocketTemplate cmp_node_switch_view_out[] = {
+ { SOCK_RGBA, 0, N_("Image"), 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
+ { -1, 0, "" }
+};
+
+static bNodeSocket *ntreeCompositSwitchViewAddSocket(bNodeTree *ntree, bNode *node, const char *name)
+{
+ bNodeSocket *sock = nodeAddStaticSocket(ntree, node, SOCK_IN, SOCK_RGBA, PROP_NONE, NULL, name);
+ return sock;
+}
+
+static void cmp_node_switch_view_sanitycheck(bNodeTree *ntree, bNode *node)
+{
+ bNodeSocket *sock;
+
+ if (!BLI_listbase_is_empty(&node->inputs))
+ return;
+
+ sock = ntreeCompositSwitchViewAddSocket(ntree, node, "No View");
+ sock->flag |= SOCK_HIDDEN;
+}
+
+static void cmp_node_switch_view_update(bNodeTree *ntree, bNode *node)
+{
+ bNodeSocket *sock;
+ SceneRenderView *srv;
+ Scene *scene = (Scene *)node->id;
+
+ /* only update when called from the operator button */
+ if (node->update != NODE_UPDATE_OPERATOR)
+ return;
+
+ if (scene == NULL) {
+ nodeRemoveAllSockets(ntree, node);
+ /* make sure there is always one socket */
+ cmp_node_switch_view_sanitycheck(ntree, node);
+ return;
+ }
+
+ /* remove the views that were removed */
+ sock = node->inputs.last;
+ while (sock) {
+ srv = BLI_findstring(&scene->r.views, sock->name, offsetof(SceneRenderView, name));
+
+ if (srv == NULL) {
+ bNodeSocket *sock_del = sock;
+ sock = sock->prev;
+ nodeRemoveSocket(ntree, node, sock_del);
+ }
+ else {
+ if (srv->viewflag & SCE_VIEW_DISABLE)
+ sock->flag |= SOCK_HIDDEN;
+ else
+ sock->flag &= ~SOCK_HIDDEN;
+
+ sock = sock->prev;
+ }
+ }
+
+ /* add the new views */
+ for (srv = scene->r.views.first; srv; srv = srv->next) {
+ sock = BLI_findstring(&node->inputs, srv->name, offsetof(bNodeSocket, name));
+
+ if (sock == NULL)
+ sock = ntreeCompositSwitchViewAddSocket(ntree, node, srv->name);
+
+ if (srv->viewflag & SCE_VIEW_DISABLE)
+ sock->flag |= SOCK_HIDDEN;
+ else
+ sock->flag &= ~SOCK_HIDDEN;
+ }
+
+ /* make sure there is always one socket */
+ cmp_node_switch_view_sanitycheck(ntree, node);
+}
+
+static void init_switch_view(const bContext *C, PointerRNA *ptr)
+{
+ Scene *scene = CTX_data_scene(C);
+ bNodeTree *ntree = ptr->id.data;
+ bNode *node = ptr->data;
+ SceneRenderView *srv;
+ bNodeSocket *sock;
+ int nr;
+
+ /* store scene for updates */
+ node->id = (ID *)scene;
+
+ if (scene) {
+ RenderData *rd = &scene->r;
+
+ for (nr = 0, srv = rd->views.first; srv; srv = srv->next, nr++) {
+ sock = ntreeCompositSwitchViewAddSocket(ntree, node, srv->name);
+
+ if ((srv->viewflag & SCE_VIEW_DISABLE))
+ sock->flag |= SOCK_HIDDEN;
+ }
+ }
+
+ /* make sure there is always one socket */
+ cmp_node_switch_view_sanitycheck(ntree, node);
+}
+
+/* custom1 = mix type */
+void register_node_type_cmp_switch_view(void)
+{
+ static bNodeType ntype;
+
+ cmp_node_type_base(&ntype, CMP_NODE_SWITCH_VIEW, "Switch View", NODE_CLASS_CONVERTOR, 0);
+ node_type_socket_templates(&ntype, NULL, cmp_node_switch_view_out);
+
+ ntype.initfunc_api = init_switch_view;
+
+ node_type_update(&ntype, cmp_node_switch_view_update, NULL);
+
+ nodeRegisterType(&ntype);
+}
diff --git a/source/blender/nodes/intern/node_common.c b/source/blender/nodes/intern/node_common.c
index c58c9c902ec..12cd93e418b 100644
--- a/source/blender/nodes/intern/node_common.c
+++ b/source/blender/nodes/intern/node_common.c
@@ -29,7 +29,6 @@
* \ingroup nodes
*/
-
#include <string.h>
#include <stddef.h>
@@ -39,21 +38,22 @@
#include "BLI_string.h"
#include "BLI_utildefines.h"
-#include "BLF_translation.h"
+#include "BLT_translation.h"
#include "BKE_node.h"
-#include "RNA_access.h"
#include "RNA_types.h"
#include "MEM_guardedalloc.h"
#include "node_common.h"
#include "node_util.h"
-#include "node_exec.h"
-#include "NOD_socket.h"
#include "NOD_common.h"
+enum {
+ REFINE_FORWARD = 1 << 0,
+ REFINE_BACKWARD = 1 << 1,
+};
/**** Group ****/
@@ -255,7 +255,7 @@ void register_node_type_reroute(void)
nodeRegisterType(ntype);
}
-static void node_reroute_inherit_type_recursive(bNodeTree *ntree, bNode *node)
+static void node_reroute_inherit_type_recursive(bNodeTree *ntree, bNode *node, int flag)
{
bNodeSocket *input = node->inputs.first;
bNodeSocket *output = node->outputs.first;
@@ -279,11 +279,14 @@ static void node_reroute_inherit_type_recursive(bNodeTree *ntree, bNode *node)
if (nodeLinkIsHidden(link))
continue;
- if (tonode == node && fromnode->type == NODE_REROUTE && !fromnode->done)
- node_reroute_inherit_type_recursive(ntree, fromnode);
-
- if (fromnode == node && tonode->type == NODE_REROUTE && !tonode->done)
- node_reroute_inherit_type_recursive(ntree, tonode);
+ if (flag & REFINE_FORWARD) {
+ if (tonode == node && fromnode->type == NODE_REROUTE && !fromnode->done)
+ node_reroute_inherit_type_recursive(ntree, fromnode, REFINE_FORWARD);
+ }
+ if (flag & REFINE_BACKWARD) {
+ if (fromnode == node && tonode->type == NODE_REROUTE && !tonode->done)
+ node_reroute_inherit_type_recursive(ntree, tonode, REFINE_BACKWARD);
+ }
}
/* determine socket type from unambiguous input/output connection if possible */
@@ -333,7 +336,7 @@ void ntree_update_reroute_nodes(bNodeTree *ntree)
for (node = ntree->nodes.first; node; node = node->next)
if (node->type == NODE_REROUTE && !node->done)
- node_reroute_inherit_type_recursive(ntree, node);
+ node_reroute_inherit_type_recursive(ntree, node, REFINE_FORWARD | REFINE_BACKWARD);
}
static bool node_is_connected_to_output_recursive(bNodeTree *ntree, bNode *node)
diff --git a/source/blender/nodes/intern/node_socket.c b/source/blender/nodes/intern/node_socket.c
index 2ac1a2c85f3..01c642b063d 100644
--- a/source/blender/nodes/intern/node_socket.c
+++ b/source/blender/nodes/intern/node_socket.c
@@ -41,7 +41,6 @@
#include "BKE_node.h"
#include "RNA_access.h"
-#include "RNA_define.h"
#include "RNA_types.h"
#include "MEM_guardedalloc.h"
@@ -109,7 +108,7 @@ static bNodeSocket *verify_socket_template(bNodeTree *ntree, bNode *node, int in
bNodeSocket *sock;
for (sock = socklist->first; sock; sock = sock->next) {
- if (strncmp(sock->name, stemp->name, NODE_MAXSTR) == 0)
+ if (STREQLEN(sock->name, stemp->name, NODE_MAXSTR))
break;
}
if (sock) {
diff --git a/source/blender/nodes/intern/node_util.c b/source/blender/nodes/intern/node_util.c
index cc8249b0f57..046188f8508 100644
--- a/source/blender/nodes/intern/node_util.c
+++ b/source/blender/nodes/intern/node_util.c
@@ -38,7 +38,7 @@
#include "BLI_string.h"
#include "BLI_utildefines.h"
-#include "BLF_translation.h"
+#include "BLT_translation.h"
#include "BKE_colortools.h"
#include "BKE_node.h"
diff --git a/source/blender/nodes/shader/node_shader_tree.c b/source/blender/nodes/shader/node_shader_tree.c
index 299172ae4cc..c4ec55c8d06 100644
--- a/source/blender/nodes/shader/node_shader_tree.c
+++ b/source/blender/nodes/shader/node_shader_tree.c
@@ -41,16 +41,13 @@
#include "DNA_linestyle_types.h"
#include "BLI_listbase.h"
-#include "BLI_math.h"
#include "BLI_threads.h"
#include "BLI_utildefines.h"
-#include "BLF_translation.h"
+#include "BLT_translation.h"
#include "BKE_context.h"
-#include "BKE_global.h"
#include "BKE_linestyle.h"
-#include "BKE_main.h"
#include "BKE_node.h"
#include "BKE_scene.h"
@@ -70,9 +67,10 @@ static int shader_tree_poll(const bContext *C, bNodeTreeType *UNUSED(treetype))
Scene *scene = CTX_data_scene(C);
/* allow empty engine string too, this is from older versions that didn't have registerable engines yet */
return (scene->r.engine[0] == '\0' ||
- STREQ(scene->r.engine, "BLENDER_RENDER") ||
- STREQ(scene->r.engine, "BLENDER_GAME") ||
- STREQ(scene->r.engine, "CYCLES"));
+ STREQ(scene->r.engine, RE_engine_id_BLENDER_RENDER) ||
+ STREQ(scene->r.engine, RE_engine_id_BLENDER_GAME) ||
+ STREQ(scene->r.engine, RE_engine_id_CYCLES) ||
+ !BKE_scene_use_shading_nodes_custom(scene));
}
static void shader_get_from_context(const bContext *C, bNodeTreeType *UNUSED(treetype), bNodeTree **r_ntree, ID **r_id, ID **r_from)
diff --git a/source/blender/nodes/shader/node_shader_util.h b/source/blender/nodes/shader/node_shader_util.h
index 8a79603fab4..2f96bdbe3df 100644
--- a/source/blender/nodes/shader/node_shader_util.h
+++ b/source/blender/nodes/shader/node_shader_util.h
@@ -69,7 +69,7 @@
#include "NOD_shader.h"
#include "node_util.h"
-#include "BLF_translation.h"
+#include "BLT_translation.h"
#include "IMB_imbuf_types.h"
#include "IMB_imbuf.h"
diff --git a/source/blender/nodes/shader/nodes/node_shader_background.c b/source/blender/nodes/shader/nodes/node_shader_background.c
index 2478fb4d38c..b387529e456 100644
--- a/source/blender/nodes/shader/nodes/node_shader_background.c
+++ b/source/blender/nodes/shader/nodes/node_shader_background.c
@@ -40,6 +40,11 @@ static bNodeSocketTemplate sh_node_background_out[] = {
{ -1, 0, "" }
};
+static int node_shader_gpu_background(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
+{
+ return GPU_stack_link(mat, "node_background", in, out, GPU_builtin(GPU_VIEW_NORMAL));
+}
+
/* node type definition */
void register_node_type_sh_background(void)
{
@@ -50,6 +55,7 @@ void register_node_type_sh_background(void)
node_type_socket_templates(&ntype, sh_node_background_in, sh_node_background_out);
node_type_init(&ntype, NULL);
node_type_storage(&ntype, "", NULL, NULL);
+ node_type_gpu(&ntype, node_shader_gpu_background);
nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_bsdf_anisotropic.c b/source/blender/nodes/shader/nodes/node_shader_bsdf_anisotropic.c
index b9c94fc3aee..8dda7b0859b 100644
--- a/source/blender/nodes/shader/nodes/node_shader_bsdf_anisotropic.c
+++ b/source/blender/nodes/shader/nodes/node_shader_bsdf_anisotropic.c
@@ -51,8 +51,8 @@ static void node_shader_init_anisotropic(bNodeTree *UNUSED(ntree), bNode *node)
static int node_shader_gpu_bsdf_anisotropic(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
- if (!in[3].link)
- in[3].link = GPU_builtin(GPU_VIEW_NORMAL);
+ if (!in[4].link)
+ in[4].link = GPU_builtin(GPU_VIEW_NORMAL);
return GPU_stack_link(mat, "node_bsdf_anisotropic", in, out);
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_bump.c b/source/blender/nodes/shader/nodes/node_shader_bump.c
index 3ce01ce03bf..3146454f26d 100644
--- a/source/blender/nodes/shader/nodes/node_shader_bump.c
+++ b/source/blender/nodes/shader/nodes/node_shader_bump.c
@@ -29,11 +29,8 @@
* \ingroup shdnodes
*/
-
-
#include "node_shader_util.h"
-
/* **************** BUMP ******************** */
static bNodeSocketTemplate sh_node_bump_in[] = {
{ SOCK_FLOAT, 1, N_("Strength"), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR},
@@ -50,7 +47,10 @@ static bNodeSocketTemplate sh_node_bump_out[] = {
static int gpu_shader_bump(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
- return GPU_stack_link(mat, "node_bump", in, out, GPU_builtin(GPU_VIEW_NORMAL));
+ if (!in[3].link)
+ in[3].link = GPU_builtin(GPU_VIEW_NORMAL);
+
+ return GPU_stack_link(mat, "node_bump", in, out);
}
/* node type definition */
diff --git a/source/blender/nodes/shader/nodes/node_shader_gamma.c b/source/blender/nodes/shader/nodes/node_shader_gamma.c
index 9956fd712c8..0264abe451f 100644
--- a/source/blender/nodes/shader/nodes/node_shader_gamma.c
+++ b/source/blender/nodes/shader/nodes/node_shader_gamma.c
@@ -41,6 +41,18 @@ static bNodeSocketTemplate sh_node_gamma_out[] = {
{ -1, 0, "" }
};
+static void node_shader_exec_gamma(void *UNUSED(data), int UNUSED(thread), bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), bNodeStack **in, bNodeStack **out)
+{
+ float col[3];
+ float gamma;
+ nodestack_get_vec(col, SOCK_VECTOR, in[0]);
+ nodestack_get_vec(&gamma, SOCK_FLOAT, in[1]);
+
+ out[0]->vec[0] = col[0] > 0.0f ? powf(col[0], gamma) : col[0];
+ out[0]->vec[1] = col[1] > 0.0f ? powf(col[1], gamma) : col[1];
+ out[0]->vec[2] = col[2] > 0.0f ? powf(col[2], gamma) : col[2];
+}
+
static int node_shader_gpu_gamma(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
return GPU_stack_link(mat, "node_gamma", in, out);
@@ -51,10 +63,11 @@ void register_node_type_sh_gamma(void)
static bNodeType ntype;
sh_node_type_base(&ntype, SH_NODE_GAMMA, "Gamma", NODE_CLASS_OP_COLOR, 0);
- node_type_compatibility(&ntype, NODE_NEW_SHADING);
+ node_type_compatibility(&ntype, NODE_OLD_SHADING | NODE_NEW_SHADING);
node_type_socket_templates(&ntype, sh_node_gamma_in, sh_node_gamma_out);
node_type_init(&ntype, NULL);
node_type_storage(&ntype, "", NULL, NULL);
+ node_type_exec(&ntype, NULL, NULL, node_shader_exec_gamma);
node_type_gpu(&ntype, node_shader_gpu_gamma);
nodeRegisterType(&ntype);
diff --git a/source/blender/nodes/shader/nodes/node_shader_geom.c b/source/blender/nodes/shader/nodes/node_shader_geom.c
index 7c598f92bed..cd52c4e2547 100644
--- a/source/blender/nodes/shader/nodes/node_shader_geom.c
+++ b/source/blender/nodes/shader/nodes/node_shader_geom.c
@@ -63,7 +63,7 @@ static void node_shader_exec_geom(void *data, int UNUSED(thread), bNode *node, b
if (ngeo->uvname[0]) {
/* find uv map by name */
for (i = 0; i < shi->totuv; i++) {
- if (strcmp(shi->uv[i].name, ngeo->uvname) == 0) {
+ if (STREQ(shi->uv[i].name, ngeo->uvname)) {
suv = &shi->uv[i];
break;
}
@@ -84,14 +84,14 @@ static void node_shader_exec_geom(void *data, int UNUSED(thread), bNode *node, b
if (ngeo->colname[0]) {
for (i = 0; i < shi->totcol; i++) {
- if (strcmp(shi->col[i].name, ngeo->colname) == 0) {
+ if (STREQ(shi->col[i].name, ngeo->colname)) {
scol = &shi->col[i];
break;
}
}
}
- copy_v3_v3(out[GEOM_OUT_VCOL]->vec, scol->col);
+ srgb_to_linearrgb_v3_v3(out[GEOM_OUT_VCOL]->vec, scol->col);
out[GEOM_OUT_VCOL]->vec[3] = scol->col[3];
out[GEOM_OUT_VCOL_ALPHA]->vec[0] = scol->col[3];
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_geometry.c b/source/blender/nodes/shader/nodes/node_shader_geometry.c
index 01851b51c27..553ea65154f 100644
--- a/source/blender/nodes/shader/nodes/node_shader_geometry.c
+++ b/source/blender/nodes/shader/nodes/node_shader_geometry.c
@@ -37,6 +37,7 @@ static bNodeSocketTemplate sh_node_geometry_out[] = {
{ SOCK_VECTOR, 0, N_("Incoming"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
{ SOCK_VECTOR, 0, N_("Parametric"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
{ SOCK_FLOAT, 0, N_("Backfacing"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
+ { SOCK_FLOAT, 0, N_("Pointiness"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
{ -1, 0, "" }
};
diff --git a/source/blender/nodes/shader/nodes/node_shader_lamp.c b/source/blender/nodes/shader/nodes/node_shader_lamp.c
index adf53ba9b52..3b000d49822 100644
--- a/source/blender/nodes/shader/nodes/node_shader_lamp.c
+++ b/source/blender/nodes/shader/nodes/node_shader_lamp.c
@@ -62,11 +62,11 @@ static int gpu_shader_lamp(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(
{
if (node->id) {
GPULamp *lamp = GPU_lamp_from_blender(GPU_material_scene(mat), (Object *)node->id, NULL);
- GPUNodeLink *col, *lv, *dist, *visifac, *shadow;
+ GPUNodeLink *col, *lv, *dist, *visifac, *shadow, *energy;
- visifac = GPU_lamp_get_data(mat, lamp, &col, &lv, &dist, &shadow);
+ visifac = GPU_lamp_get_data(mat, lamp, &col, &lv, &dist, &shadow, &energy);
- return GPU_stack_link(mat, "lamp", in, out, col, lv, dist, shadow, visifac);
+ return GPU_stack_link(mat, "lamp", in, out, col, energy, lv, dist, shadow, visifac);
}
return 0;
diff --git a/source/blender/nodes/shader/nodes/node_shader_mapping.c b/source/blender/nodes/shader/nodes/node_shader_mapping.c
index cff4a039602..2af6e19565b 100644
--- a/source/blender/nodes/shader/nodes/node_shader_mapping.c
+++ b/source/blender/nodes/shader/nodes/node_shader_mapping.c
@@ -71,7 +71,7 @@ static void node_shader_exec_mapping(void *UNUSED(data), int UNUSED(thread), bNo
static void node_shader_init_mapping(bNodeTree *UNUSED(ntree), bNode *node)
{
- node->storage = add_tex_mapping(TEXMAP_TYPE_POINT);
+ node->storage = BKE_texture_mapping_add(TEXMAP_TYPE_POINT);
}
static int gpu_shader_mapping(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
diff --git a/source/blender/nodes/shader/nodes/node_shader_material.c b/source/blender/nodes/shader/nodes/node_shader_material.c
index 79d66495ad7..41e44a64376 100644
--- a/source/blender/nodes/shader/nodes/node_shader_material.c
+++ b/source/blender/nodes/shader/nodes/node_shader_material.c
@@ -36,7 +36,7 @@
static bNodeSocketTemplate sh_node_material_in[] = {
{ SOCK_RGBA, 1, N_("Color"), 0.0f, 0.0f, 0.0f, 1.0f},
{ SOCK_RGBA, 1, N_("Spec"), 0.0f, 0.0f, 0.0f, 1.0f},
- { SOCK_FLOAT, 1, N_("Refl"), 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, PROP_NONE},
+ { SOCK_FLOAT, 1, N_("DiffuseIntensity"), 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, PROP_NONE},
{ SOCK_VECTOR, 1, N_("Normal"), 0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f, PROP_DIRECTION},
{ -1, 0, "" }
};
@@ -53,13 +53,13 @@ static bNodeSocketTemplate sh_node_material_out[] = {
static bNodeSocketTemplate sh_node_material_ext_in[] = {
{ SOCK_RGBA, 1, N_("Color"), 0.0f, 0.0f, 0.0f, 1.0f},
{ SOCK_RGBA, 1, N_("Spec"), 0.0f, 0.0f, 0.0f, 1.0f},
- { SOCK_FLOAT, 1, N_("Refl"), 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, PROP_NONE},
+ { SOCK_FLOAT, 1, N_("DiffuseIntensity"), 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, PROP_NONE},
{ SOCK_VECTOR, 1, N_("Normal"), 0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f, PROP_DIRECTION},
{ SOCK_RGBA, 1, N_("Mirror"), 0.0f, 0.0f, 0.0f, 1.0f},
{ SOCK_FLOAT, 1, N_("Ambient"), 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, PROP_NONE},
{ SOCK_FLOAT, 1, N_("Emit"), 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, PROP_UNSIGNED},
{ SOCK_FLOAT, 1, N_("SpecTra"), 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, PROP_NONE},
- { SOCK_FLOAT, 1, N_("Ray Mirror"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_NONE},
+ { SOCK_FLOAT, 1, N_("Reflectivity"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_NONE},
{ SOCK_FLOAT, 1, N_("Alpha"), 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, PROP_UNSIGNED},
{ SOCK_FLOAT, 1, N_("Translucency"), 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, PROP_NONE},
{ -1, 0, "" }
@@ -267,6 +267,8 @@ static int gpu_shader_material(GPUMaterial *mat, bNode *node, bNodeExecData *UNU
shi.amb = gpu_get_input_link(&in[MAT_IN_AMB]);
if (hasinput[MAT_IN_EMIT])
shi.emit = gpu_get_input_link(&in[MAT_IN_EMIT]);
+ if (hasinput[MAT_IN_SPECTRA])
+ shi.spectra = gpu_get_input_link(&in[MAT_IN_SPECTRA]);
if (hasinput[MAT_IN_ALPHA])
shi.alpha = gpu_get_input_link(&in[MAT_IN_ALPHA]);
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_math.c b/source/blender/nodes/shader/nodes/node_shader_math.c
index dc5971909d2..2a1e936570d 100644
--- a/source/blender/nodes/shader/nodes/node_shader_math.c
+++ b/source/blender/nodes/shader/nodes/node_shader_math.c
@@ -54,16 +54,16 @@ static void node_shader_exec_math(void *UNUSED(data), int UNUSED(thread), bNode
switch (node->custom1) {
- case 0: /* Add */
+ case NODE_MATH_ADD:
r = a + b;
break;
- case 1: /* Subtract */
+ case NODE_MATH_SUB:
r = a - b;
break;
- case 2: /* Multiply */
+ case NODE_MATH_MUL:
r = a * b;
break;
- case 3: /* Divide */
+ case NODE_MATH_DIVIDE:
{
if (b == 0) /* We don't want to divide by zero. */
r = 0.0;
@@ -71,7 +71,7 @@ static void node_shader_exec_math(void *UNUSED(data), int UNUSED(thread), bNode
r = a / b;
break;
}
- case 4: /* Sine */
+ case NODE_MATH_SIN:
{
if (in[0]->hasinput || !in[1]->hasinput) /* This one only takes one input, so we've got to choose. */
r = sinf(a);
@@ -79,7 +79,7 @@ static void node_shader_exec_math(void *UNUSED(data), int UNUSED(thread), bNode
r = sinf(b);
break;
}
- case 5: /* Cosine */
+ case NODE_MATH_COS:
{
if (in[0]->hasinput || !in[1]->hasinput) /* This one only takes one input, so we've got to choose. */
r = cosf(a);
@@ -87,7 +87,7 @@ static void node_shader_exec_math(void *UNUSED(data), int UNUSED(thread), bNode
r = cosf(b);
break;
}
- case 6: /* Tangent */
+ case NODE_MATH_TAN:
{
if (in[0]->hasinput || !in[1]->hasinput) /* This one only takes one input, so we've got to choose. */
r = tanf(a);
@@ -95,7 +95,7 @@ static void node_shader_exec_math(void *UNUSED(data), int UNUSED(thread), bNode
r = tanf(b);
break;
}
- case 7: /* Arc-Sine */
+ case NODE_MATH_ASIN:
{
if (in[0]->hasinput || !in[1]->hasinput) { /* This one only takes one input, so we've got to choose. */
/* Can't do the impossible... */
@@ -113,7 +113,7 @@ static void node_shader_exec_math(void *UNUSED(data), int UNUSED(thread), bNode
}
break;
}
- case 8: /* Arc-Cosine */
+ case NODE_MATH_ACOS:
{
if (in[0]->hasinput || !in[1]->hasinput) { /* This one only takes one input, so we've got to choose. */
/* Can't do the impossible... */
@@ -131,7 +131,7 @@ static void node_shader_exec_math(void *UNUSED(data), int UNUSED(thread), bNode
}
break;
}
- case 9: /* Arc-Tangent */
+ case NODE_MATH_ATAN:
{
if (in[0]->hasinput || !in[1]->hasinput) /* This one only takes one input, so we've got to choose. */
r = atan(a);
@@ -139,7 +139,7 @@ static void node_shader_exec_math(void *UNUSED(data), int UNUSED(thread), bNode
r = atan(b);
break;
}
- case 10: /* Power */
+ case NODE_MATH_POW:
{
/* Only raise negative numbers by full integers */
if (a >= 0) {
@@ -159,7 +159,7 @@ static void node_shader_exec_math(void *UNUSED(data), int UNUSED(thread), bNode
break;
}
- case 11: /* Logarithm */
+ case NODE_MATH_LOG:
{
/* Don't want any imaginary numbers... */
if (a > 0 && b > 0)
@@ -168,7 +168,7 @@ static void node_shader_exec_math(void *UNUSED(data), int UNUSED(thread), bNode
r = 0.0;
break;
}
- case 12: /* Minimum */
+ case NODE_MATH_MIN:
{
if (a < b)
r = a;
@@ -176,7 +176,7 @@ static void node_shader_exec_math(void *UNUSED(data), int UNUSED(thread), bNode
r = b;
break;
}
- case 13: /* Maximum */
+ case NODE_MATH_MAX:
{
if (a > b)
r = a;
@@ -184,7 +184,7 @@ static void node_shader_exec_math(void *UNUSED(data), int UNUSED(thread), bNode
r = b;
break;
}
- case 14: /* Round */
+ case NODE_MATH_ROUND:
{
if (in[0]->hasinput || !in[1]->hasinput) /* This one only takes one input, so we've got to choose. */
r = (a < 0) ? (int)(a - 0.5f) : (int)(a + 0.5f);
@@ -192,7 +192,7 @@ static void node_shader_exec_math(void *UNUSED(data), int UNUSED(thread), bNode
r = (b < 0) ? (int)(b - 0.5f) : (int)(b + 0.5f);
break;
}
- case 15: /* Less Than */
+ case NODE_MATH_LESS:
{
if (a < b)
r = 1.0f;
@@ -200,7 +200,7 @@ static void node_shader_exec_math(void *UNUSED(data), int UNUSED(thread), bNode
r = 0.0f;
break;
}
- case 16: /* Greater Than */
+ case NODE_MATH_GREATER:
{
if (a > b)
r = 1.0f;
@@ -208,7 +208,7 @@ static void node_shader_exec_math(void *UNUSED(data), int UNUSED(thread), bNode
r = 0.0f;
break;
}
- case 17: /* Modulo */
+ case NODE_MATH_MOD:
{
if (b == 0.0f)
r = 0.0f;
@@ -216,44 +216,49 @@ static void node_shader_exec_math(void *UNUSED(data), int UNUSED(thread), bNode
r = fmod(a, b);
break;
}
- case 18: /* Absolute */
+ case NODE_MATH_ABS:
{
r = fabsf(a);
break;
}
}
-
+ if (node->custom2 & SHD_MATH_CLAMP) {
+ CLAMP(r, 0.0f, 1.0f);
+ }
out[0]->vec[0] = r;
}
static int gpu_shader_math(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
- static const char *names[] = {"math_add", "math_subtract", "math_multiply",
- "math_divide", "math_sine", "math_cosine", "math_tangent", "math_asin",
- "math_acos", "math_atan", "math_pow", "math_log", "math_min", "math_max",
- "math_round", "math_less_than", "math_greater_than", "math_modulo", "math_absolute"};
+ static const char *names[] = {
+ "math_add", "math_subtract", "math_multiply",
+ "math_divide", "math_sine", "math_cosine", "math_tangent", "math_asin",
+ "math_acos", "math_atan", "math_pow", "math_log", "math_min", "math_max",
+ "math_round", "math_less_than", "math_greater_than", "math_modulo", "math_abs",
+ };
switch (node->custom1) {
- case 0:
- case 1:
- case 2:
- case 3:
- case 10:
- case 11:
- case 12:
- case 13:
- case 15:
- case 16:
- case 17:
+ case NODE_MATH_ADD:
+ case NODE_MATH_SUB:
+ case NODE_MATH_MUL:
+ case NODE_MATH_DIVIDE:
+ case NODE_MATH_POW:
+ case NODE_MATH_LOG:
+ case NODE_MATH_MIN:
+ case NODE_MATH_MAX:
+ case NODE_MATH_LESS:
+ case NODE_MATH_GREATER:
+ case NODE_MATH_MOD:
GPU_stack_link(mat, names[node->custom1], in, out);
break;
- case 4:
- case 5:
- case 6:
- case 7:
- case 8:
- case 9:
- case 14:
+ case NODE_MATH_SIN:
+ case NODE_MATH_COS:
+ case NODE_MATH_TAN:
+ case NODE_MATH_ASIN:
+ case NODE_MATH_ACOS:
+ case NODE_MATH_ATAN:
+ case NODE_MATH_ROUND:
+ case NODE_MATH_ABS:
if (in[0].hasinput || !in[1].hasinput) {
/* use only first item and terminator */
GPUNodeStack tmp_in[2];
@@ -272,7 +277,13 @@ static int gpu_shader_math(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(
default:
return 0;
}
-
+
+ if (node->custom2 & SHD_MATH_CLAMP) {
+ float min[3] = {0.0f, 0.0f, 0.0f};
+ float max[3] = {1.0f, 1.0f, 1.0f};
+ GPU_link(mat, "clamp_val", out[0].link, GPU_uniform(min), GPU_uniform(max), &out[0].link);
+ }
+
return 1;
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_mixRgb.c b/source/blender/nodes/shader/nodes/node_shader_mixRgb.c
index 2da51c19ef8..f911fa058dc 100644
--- a/source/blender/nodes/shader/nodes/node_shader_mixRgb.c
+++ b/source/blender/nodes/shader/nodes/node_shader_mixRgb.c
@@ -59,6 +59,9 @@ static void node_shader_exec_mix_rgb(void *UNUSED(data), int UNUSED(thread), bNo
nodestack_get_vec(vec, SOCK_VECTOR, in[2]);
ramp_blend(node->custom1, col, fac, vec);
+ if (node->custom2 & SHD_MIXRGB_CLAMP) {
+ CLAMP3(col, 0.0f, 1.0f);
+ }
copy_v3_v3(out[0]->vec, col);
}
@@ -68,8 +71,13 @@ static int gpu_shader_mix_rgb(GPUMaterial *mat, bNode *node, bNodeExecData *UNUS
"mix_screen", "mix_div", "mix_diff", "mix_dark", "mix_light",
"mix_overlay", "mix_dodge", "mix_burn", "mix_hue", "mix_sat",
"mix_val", "mix_color", "mix_soft", "mix_linear"};
-
- return GPU_stack_link(mat, names[node->custom1], in, out);
+ int ret = GPU_stack_link(mat, names[node->custom1], in, out);
+ if (ret && node->custom2 & SHD_MIXRGB_CLAMP) {
+ float min[3] = {0.0f, 0.0f, 0.0f};
+ float max[3] = {1.0f, 1.0f, 1.0f};
+ GPU_link(mat, "clamp_vec3", out[0].link, GPU_uniform(min), GPU_uniform(max), &out[0].link);
+ }
+ return ret;
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_normal.c b/source/blender/nodes/shader/nodes/node_shader_normal.c
index fcd738f0b15..092fc201aa7 100644
--- a/source/blender/nodes/shader/nodes/node_shader_normal.c
+++ b/source/blender/nodes/shader/nodes/node_shader_normal.c
@@ -61,12 +61,12 @@ static void node_shader_exec_normal(void *UNUSED(data), int UNUSED(thread), bNod
static int gpu_shader_normal(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
GPUNodeLink *vec = GPU_uniform(out[0].vec);
- int ret = GPU_stack_link(mat, "normal", in, out, vec);
- if (ret && GPU_material_use_new_shading_nodes(mat)) {
- float fac[3] = {1.0f, 0.0f, 0.0f};
- GPU_link(mat, "invert", GPU_uniform(fac), out[1].link, &out[1].link);
+ if (GPU_material_use_new_shading_nodes(mat)) {
+ return GPU_stack_link(mat, "normal_new_shading", in, out, vec);
+ }
+ else {
+ return GPU_stack_link(mat, "normal", in, out, vec);
}
- return ret;
}
void register_node_type_sh_normal(void)
diff --git a/source/blender/nodes/shader/nodes/node_shader_object_info.c b/source/blender/nodes/shader/nodes/node_shader_object_info.c
index a862c621248..d1905246fd4 100644
--- a/source/blender/nodes/shader/nodes/node_shader_object_info.c
+++ b/source/blender/nodes/shader/nodes/node_shader_object_info.c
@@ -30,10 +30,10 @@
/* **************** OUTPUT ******************** */
static bNodeSocketTemplate sh_node_object_info_out[] = {
- { SOCK_VECTOR, 0, N_("Location"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
- { SOCK_FLOAT, 0, N_("Object Index"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
- { SOCK_FLOAT, 0, N_("Material Index"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
- { SOCK_FLOAT, 0, N_("Random"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
+ { SOCK_VECTOR, 0, N_("Location"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
+ { SOCK_FLOAT, 0, N_("Object Index"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
+ { SOCK_FLOAT, 0, N_("Material Index"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
+ { SOCK_FLOAT, 0, N_("Random"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
{ -1, 0, "" }
};
diff --git a/source/blender/nodes/shader/nodes/node_shader_output_world.c b/source/blender/nodes/shader/nodes/node_shader_output_world.c
index c8e47c47c5f..ad7389fd56e 100644
--- a/source/blender/nodes/shader/nodes/node_shader_output_world.c
+++ b/source/blender/nodes/shader/nodes/node_shader_output_world.c
@@ -35,6 +35,16 @@ static bNodeSocketTemplate sh_node_output_world_in[] = {
{ -1, 0, "" }
};
+static int node_shader_gpu_output_world(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
+{
+ GPUNodeLink *outlink;
+
+ GPU_stack_link(mat, "node_output_world", in, out, &outlink);
+ GPU_material_output_link(mat, outlink);
+
+ return 1;
+}
+
/* node type definition */
void register_node_type_sh_output_world(void)
{
@@ -45,7 +55,8 @@ void register_node_type_sh_output_world(void)
node_type_socket_templates(&ntype, sh_node_output_world_in, NULL);
node_type_init(&ntype, NULL);
node_type_storage(&ntype, "", NULL, NULL);
-
+ node_type_gpu(&ntype, node_shader_gpu_output_world);
+
/* Do not allow muting output node. */
node_type_internal_links(&ntype, NULL);
diff --git a/source/blender/nodes/shader/nodes/node_shader_particle_info.c b/source/blender/nodes/shader/nodes/node_shader_particle_info.c
index 05f7301776f..6cc8de322af 100644
--- a/source/blender/nodes/shader/nodes/node_shader_particle_info.c
+++ b/source/blender/nodes/shader/nodes/node_shader_particle_info.c
@@ -26,6 +26,7 @@
*/
#include "../node_shader_util.h"
+#include "RE_shader_ext.h"
static bNodeSocketTemplate outputs[] = {
{ SOCK_FLOAT, 0, "Index" },
@@ -40,6 +41,22 @@ static bNodeSocketTemplate outputs[] = {
{ SOCK_VECTOR, 0, "Angular Velocity" },
{ -1, 0, "" }
};
+static void node_shader_exec_particle_info(void *data, int UNUSED(thread), bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), bNodeStack **UNUSED(in), bNodeStack **out)
+{
+ ShadeInput *shi = ((ShaderCallData *)data)->shi;
+
+ RE_instance_get_particle_info(shi->obi, out[0]->vec, out[1]->vec, out[2]->vec, out[3]->vec, out[4]->vec, out[5]->vec, out[6]->vec);
+}
+
+static int gpu_shader_particle_info(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
+{
+
+ return GPU_stack_link(mat, "particle_info", in, out,
+ GPU_builtin(GPU_PARTICLE_SCALAR_PROPS),
+ GPU_builtin(GPU_PARTICLE_LOCATION),
+ GPU_builtin(GPU_PARTICLE_VELOCITY),
+ GPU_builtin(GPU_PARTICLE_ANG_VELOCITY));
+}
/* node type definition */
void register_node_type_sh_particle_info(void)
@@ -47,8 +64,10 @@ void register_node_type_sh_particle_info(void)
static bNodeType ntype;
sh_node_type_base(&ntype, SH_NODE_PARTICLE_INFO, "Particle Info", NODE_CLASS_INPUT, 0);
- node_type_compatibility(&ntype, NODE_NEW_SHADING);
+ node_type_compatibility(&ntype, NODE_NEW_SHADING | NODE_OLD_SHADING);
node_type_socket_templates(&ntype, NULL, outputs);
+ node_type_exec(&ntype, NULL, NULL, node_shader_exec_particle_info);
+ node_type_gpu(&ntype, gpu_shader_particle_info);
nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_script.c b/source/blender/nodes/shader/nodes/node_shader_script.c
index d5ed38297da..f640dd5ea13 100644
--- a/source/blender/nodes/shader/nodes/node_shader_script.c
+++ b/source/blender/nodes/shader/nodes/node_shader_script.c
@@ -31,8 +31,6 @@
#include "node_shader_util.h"
-#include "BKE_idprop.h"
-
/* **************** Script ******************** */
static void init(bNodeTree *UNUSED(ntree), bNode *node)
diff --git a/source/blender/nodes/shader/nodes/node_shader_sepcombXYZ.c b/source/blender/nodes/shader/nodes/node_shader_sepcombXYZ.c
index 605a3b9faa3..6375dcc8782 100644
--- a/source/blender/nodes/shader/nodes/node_shader_sepcombXYZ.c
+++ b/source/blender/nodes/shader/nodes/node_shader_sepcombXYZ.c
@@ -65,9 +65,9 @@ void register_node_type_sh_sepxyz(void)
/* **************** COMBINE XYZ ******************** */
static bNodeSocketTemplate sh_node_combxyz_in[] = {
- { SOCK_FLOAT, 1, N_("X"), 0.0f, 0.0f, 0.0f, 1.0f, -10000.0f, 10000.0f, PROP_UNSIGNED},
- { SOCK_FLOAT, 1, N_("Y"), 0.0f, 0.0f, 0.0f, 1.0f, -10000.0f, 10000.0f, PROP_UNSIGNED},
- { SOCK_FLOAT, 1, N_("Z"), 0.0f, 0.0f, 0.0f, 1.0f, -10000.0f, 10000.0f, PROP_UNSIGNED},
+ { SOCK_FLOAT, 1, N_("X"), 0.0f, 0.0f, 0.0f, 1.0f, -10000.0f, 10000.0f},
+ { SOCK_FLOAT, 1, N_("Y"), 0.0f, 0.0f, 0.0f, 1.0f, -10000.0f, 10000.0f},
+ { SOCK_FLOAT, 1, N_("Z"), 0.0f, 0.0f, 0.0f, 1.0f, -10000.0f, 10000.0f},
{ -1, 0, "" }
};
static bNodeSocketTemplate sh_node_combxyz_out[] = {
diff --git a/source/blender/nodes/shader/nodes/node_shader_subsurface_scattering.c b/source/blender/nodes/shader/nodes/node_shader_subsurface_scattering.c
index fd864f1c7c6..8c83fa47815 100644
--- a/source/blender/nodes/shader/nodes/node_shader_subsurface_scattering.c
+++ b/source/blender/nodes/shader/nodes/node_shader_subsurface_scattering.c
@@ -51,7 +51,7 @@ static void node_shader_init_subsurface_scattering(bNodeTree *UNUSED(ntree), bNo
node->custom1 = SHD_SUBSURFACE_CUBIC;
/*for (sock = node->inputs.first; sock; sock = sock->next) {
- if (strcmp(sock->name, "Sharpness") == 0) {
+ if (STREQ(sock->name, "Sharpness")) {
bNodeSocketValueFloat *dval = sock->default_value;
dval->value = 0.0f;
}
@@ -60,8 +60,8 @@ static void node_shader_init_subsurface_scattering(bNodeTree *UNUSED(ntree), bNo
static int node_shader_gpu_subsurface_scattering(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
- if (!in[1].link)
- in[1].link = GPU_builtin(GPU_VIEW_NORMAL);
+ if (!in[5].link)
+ in[5].link = GPU_builtin(GPU_VIEW_NORMAL);
return GPU_stack_link(mat, "node_subsurface_scattering", in, out);
}
@@ -72,7 +72,7 @@ static void node_shader_update_subsurface_scattering(bNodeTree *UNUSED(ntree), b
int falloff = node->custom1;
for (sock = node->inputs.first; sock; sock = sock->next) {
- if (strcmp(sock->name, "Sharpness") == 0) {
+ if (STREQ(sock->name, "Sharpness")) {
if (falloff == SHD_SUBSURFACE_CUBIC)
sock->flag &= ~SOCK_UNAVAIL;
else
diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_brick.c b/source/blender/nodes/shader/nodes/node_shader_tex_brick.c
index f75f6a654d1..569eaf5ff9b 100644
--- a/source/blender/nodes/shader/nodes/node_shader_tex_brick.c
+++ b/source/blender/nodes/shader/nodes/node_shader_tex_brick.c
@@ -51,8 +51,8 @@ static bNodeSocketTemplate sh_node_tex_brick_out[] = {
static void node_shader_init_tex_brick(bNodeTree *UNUSED(ntree), bNode *node)
{
NodeTexBrick *tex = MEM_callocN(sizeof(NodeTexBrick), "NodeTexBrick");
- default_tex_mapping(&tex->base.tex_mapping, TEXMAP_TYPE_POINT);
- default_color_mapping(&tex->base.color_mapping);
+ BKE_texture_mapping_default(&tex->base.tex_mapping, TEXMAP_TYPE_POINT);
+ BKE_texture_colormapping_default(&tex->base.color_mapping);
tex->offset = 0.5f;
tex->squash = 1.0f;
diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_checker.c b/source/blender/nodes/shader/nodes/node_shader_tex_checker.c
index 30e51c7cb7d..b7498df1706 100644
--- a/source/blender/nodes/shader/nodes/node_shader_tex_checker.c
+++ b/source/blender/nodes/shader/nodes/node_shader_tex_checker.c
@@ -46,8 +46,8 @@ static bNodeSocketTemplate sh_node_tex_checker_out[] = {
static void node_shader_init_tex_checker(bNodeTree *UNUSED(ntree), bNode *node)
{
NodeTexChecker *tex = MEM_callocN(sizeof(NodeTexChecker), "NodeTexChecker");
- default_tex_mapping(&tex->base.tex_mapping, TEXMAP_TYPE_POINT);
- default_color_mapping(&tex->base.color_mapping);
+ BKE_texture_mapping_default(&tex->base.tex_mapping, TEXMAP_TYPE_POINT);
+ BKE_texture_colormapping_default(&tex->base.color_mapping);
node->storage = tex;
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_coord.c b/source/blender/nodes/shader/nodes/node_shader_tex_coord.c
index 781b1bb5a93..be393582a42 100644
--- a/source/blender/nodes/shader/nodes/node_shader_tex_coord.c
+++ b/source/blender/nodes/shader/nodes/node_shader_tex_coord.c
@@ -46,10 +46,20 @@ static int node_shader_gpu_tex_coord(GPUMaterial *mat, bNode *UNUSED(node), bNod
{
GPUNodeLink *orco = GPU_attribute(CD_ORCO, "");
GPUNodeLink *mtface = GPU_attribute(CD_MTFACE, "");
-
- return GPU_stack_link(mat, "node_tex_coord", in, out,
- GPU_builtin(GPU_VIEW_POSITION), GPU_builtin(GPU_VIEW_NORMAL),
- GPU_builtin(GPU_INVERSE_VIEW_MATRIX), GPU_builtin(GPU_INVERSE_OBJECT_MATRIX), orco, mtface);
+ GPUMatType type = GPU_Material_get_type(mat);
+
+ if (type == GPU_MATERIAL_TYPE_MESH) {
+ return GPU_stack_link(mat, "node_tex_coord", in, out,
+ GPU_builtin(GPU_VIEW_POSITION), GPU_builtin(GPU_VIEW_NORMAL),
+ GPU_builtin(GPU_INVERSE_VIEW_MATRIX), GPU_builtin(GPU_INVERSE_OBJECT_MATRIX),
+ GPU_builtin(GPU_CAMERA_TEXCO_FACTORS), orco, mtface);
+ }
+ else {
+ return GPU_stack_link(mat, "node_tex_coord_background", in, out,
+ GPU_builtin(GPU_VIEW_POSITION), GPU_builtin(GPU_VIEW_NORMAL),
+ GPU_builtin(GPU_INVERSE_VIEW_MATRIX), GPU_builtin(GPU_INVERSE_OBJECT_MATRIX),
+ GPU_builtin(GPU_CAMERA_TEXCO_FACTORS), orco, mtface);
+ }
}
/* node type definition */
diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_environment.c b/source/blender/nodes/shader/nodes/node_shader_tex_environment.c
index dcb3ef3c8a0..2b43667a009 100644
--- a/source/blender/nodes/shader/nodes/node_shader_tex_environment.c
+++ b/source/blender/nodes/shader/nodes/node_shader_tex_environment.c
@@ -27,8 +27,6 @@
#include "../node_shader_util.h"
-#include "IMB_colormanagement.h"
-
/* **************** OUTPUT ******************** */
static bNodeSocketTemplate sh_node_tex_environment_in[] = {
@@ -44,8 +42,8 @@ static bNodeSocketTemplate sh_node_tex_environment_out[] = {
static void node_shader_init_tex_environment(bNodeTree *UNUSED(ntree), bNode *node)
{
NodeTexEnvironment *tex = MEM_callocN(sizeof(NodeTexEnvironment), "NodeTexEnvironment");
- default_tex_mapping(&tex->base.tex_mapping, TEXMAP_TYPE_POINT);
- default_color_mapping(&tex->base.color_mapping);
+ BKE_texture_mapping_default(&tex->base.tex_mapping, TEXMAP_TYPE_POINT);
+ BKE_texture_colormapping_default(&tex->base.color_mapping);
tex->color_space = SHD_COLORSPACE_COLOR;
tex->projection = SHD_PROJ_EQUIRECTANGULAR;
tex->iuser.frames = 1;
@@ -67,13 +65,22 @@ static int node_shader_gpu_tex_environment(GPUMaterial *mat, bNode *node, bNodeE
if (!ima)
return GPU_stack_link(mat, "node_tex_environment_empty", in, out);
- if (!in[0].link)
- in[0].link = GPU_builtin(GPU_VIEW_POSITION);
-
+ if (!in[0].link) {
+ GPUMatType type = GPU_Material_get_type(mat);
+
+ if (type == GPU_MATERIAL_TYPE_MESH)
+ in[0].link = GPU_builtin(GPU_VIEW_POSITION);
+ else
+ GPU_link(mat, "background_transform_to_world", GPU_builtin(GPU_VIEW_POSITION), &in[0].link);
+ }
+
node_shader_gpu_tex_mapping(mat, node, in, out);
- ret = GPU_stack_link(mat, "node_tex_environment", in, out, GPU_image(ima, iuser, isdata));
-
+ if (tex->projection == SHD_PROJ_EQUIRECTANGULAR)
+ ret = GPU_stack_link(mat, "node_tex_environment_equirectangular", in, out, GPU_image(ima, iuser, isdata));
+ else
+ ret = GPU_stack_link(mat, "node_tex_environment_mirror_ball", in, out, GPU_image(ima, iuser, isdata));
+
if (ret) {
ImBuf *ibuf = BKE_image_acquire_ibuf(ima, iuser, NULL);
if (ibuf && (ibuf->colormanage_flag & IMB_COLORMANAGE_IS_DATA) == 0 &&
diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_gradient.c b/source/blender/nodes/shader/nodes/node_shader_tex_gradient.c
index e11591ab5ce..24916e8f013 100644
--- a/source/blender/nodes/shader/nodes/node_shader_tex_gradient.c
+++ b/source/blender/nodes/shader/nodes/node_shader_tex_gradient.c
@@ -43,8 +43,8 @@ static bNodeSocketTemplate sh_node_tex_gradient_out[] = {
static void node_shader_init_tex_gradient(bNodeTree *UNUSED(ntree), bNode *node)
{
NodeTexGradient *tex = MEM_callocN(sizeof(NodeTexGradient), "NodeTexGradient");
- default_tex_mapping(&tex->base.tex_mapping, TEXMAP_TYPE_POINT);
- default_color_mapping(&tex->base.color_mapping);
+ BKE_texture_mapping_default(&tex->base.tex_mapping, TEXMAP_TYPE_POINT);
+ BKE_texture_colormapping_default(&tex->base.color_mapping);
tex->gradient_type = SHD_BLEND_LINEAR;
node->storage = tex;
diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_image.c b/source/blender/nodes/shader/nodes/node_shader_tex_image.c
index 0a11ee4a9b6..f87e792399b 100644
--- a/source/blender/nodes/shader/nodes/node_shader_tex_image.c
+++ b/source/blender/nodes/shader/nodes/node_shader_tex_image.c
@@ -27,8 +27,6 @@
#include "../node_shader_util.h"
-#include "IMB_colormanagement.h"
-
/* **************** OUTPUT ******************** */
static bNodeSocketTemplate sh_node_tex_image_in[] = {
@@ -45,8 +43,8 @@ static bNodeSocketTemplate sh_node_tex_image_out[] = {
static void node_shader_init_tex_image(bNodeTree *UNUSED(ntree), bNode *node)
{
NodeTexImage *tex = MEM_callocN(sizeof(NodeTexImage), "NodeTexImage");
- default_tex_mapping(&tex->base.tex_mapping, TEXMAP_TYPE_POINT);
- default_color_mapping(&tex->base.color_mapping);
+ BKE_texture_mapping_default(&tex->base.tex_mapping, TEXMAP_TYPE_POINT);
+ BKE_texture_colormapping_default(&tex->base.color_mapping);
tex->color_space = SHD_COLORSPACE_COLOR;
tex->iuser.frames = 1;
tex->iuser.sfra = 1;
diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_magic.c b/source/blender/nodes/shader/nodes/node_shader_tex_magic.c
index de2daeb8ee1..80904e376bc 100644
--- a/source/blender/nodes/shader/nodes/node_shader_tex_magic.c
+++ b/source/blender/nodes/shader/nodes/node_shader_tex_magic.c
@@ -45,8 +45,8 @@ static bNodeSocketTemplate sh_node_tex_magic_out[] = {
static void node_shader_init_tex_magic(bNodeTree *UNUSED(ntree), bNode *node)
{
NodeTexMagic *tex = MEM_callocN(sizeof(NodeTexMagic), "NodeTexMagic");
- default_tex_mapping(&tex->base.tex_mapping, TEXMAP_TYPE_POINT);
- default_color_mapping(&tex->base.color_mapping);
+ BKE_texture_mapping_default(&tex->base.tex_mapping, TEXMAP_TYPE_POINT);
+ BKE_texture_colormapping_default(&tex->base.color_mapping);
tex->depth = 2;
node->storage = tex;
diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_musgrave.c b/source/blender/nodes/shader/nodes/node_shader_tex_musgrave.c
index 75566773ea2..825ba7eb3c1 100644
--- a/source/blender/nodes/shader/nodes/node_shader_tex_musgrave.c
+++ b/source/blender/nodes/shader/nodes/node_shader_tex_musgrave.c
@@ -49,8 +49,8 @@ static bNodeSocketTemplate sh_node_tex_musgrave_out[] = {
static void node_shader_init_tex_musgrave(bNodeTree *UNUSED(ntree), bNode *node)
{
NodeTexMusgrave *tex = MEM_callocN(sizeof(NodeTexMusgrave), "NodeTexMusgrave");
- default_tex_mapping(&tex->base.tex_mapping, TEXMAP_TYPE_POINT);
- default_color_mapping(&tex->base.color_mapping);
+ BKE_texture_mapping_default(&tex->base.tex_mapping, TEXMAP_TYPE_POINT);
+ BKE_texture_colormapping_default(&tex->base.color_mapping);
tex->musgrave_type = SHD_MUSGRAVE_FBM;
node->storage = tex;
diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_noise.c b/source/blender/nodes/shader/nodes/node_shader_tex_noise.c
index 601a31dff00..d806140694e 100644
--- a/source/blender/nodes/shader/nodes/node_shader_tex_noise.c
+++ b/source/blender/nodes/shader/nodes/node_shader_tex_noise.c
@@ -46,8 +46,8 @@ static bNodeSocketTemplate sh_node_tex_noise_out[] = {
static void node_shader_init_tex_noise(bNodeTree *UNUSED(ntree), bNode *node)
{
NodeTexNoise *tex = MEM_callocN(sizeof(NodeTexNoise), "NodeTexNoise");
- default_tex_mapping(&tex->base.tex_mapping, TEXMAP_TYPE_POINT);
- default_color_mapping(&tex->base.color_mapping);
+ BKE_texture_mapping_default(&tex->base.tex_mapping, TEXMAP_TYPE_POINT);
+ BKE_texture_colormapping_default(&tex->base.color_mapping);
node->storage = tex;
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_pointdensity.c b/source/blender/nodes/shader/nodes/node_shader_tex_pointdensity.c
new file mode 100644
index 00000000000..6205b0fa11f
--- /dev/null
+++ b/source/blender/nodes/shader/nodes/node_shader_tex_pointdensity.c
@@ -0,0 +1,76 @@
+/*
+ * ***** 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) 2015 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Sergey Sharybin.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include "../node_shader_util.h"
+
+/* **************** OUTPUT ******************** */
+
+static bNodeSocketTemplate sh_node_tex_pointdensity_in[] = {
+ {SOCK_VECTOR, 1, N_("Vector"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_NONE, SOCK_HIDE_VALUE},
+ {-1, 0, ""}
+};
+
+static bNodeSocketTemplate sh_node_tex_pointdensity_out[] = {
+ {SOCK_RGBA, 0, N_("Color"), 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
+ {SOCK_FLOAT, 0, N_("Density"), 0.0f, 0.0f, 0.0f, 0.0f, -10000.0f, 10000.0f},
+ {-1, 0, ""}
+};
+
+static void node_shader_init_tex_pointdensity(bNodeTree *UNUSED(ntree),
+ bNode *node)
+{
+ NodeShaderTexPointDensity *point_density =
+ MEM_callocN(sizeof(NodeShaderTexPointDensity), "new pd node");
+ point_density->resolution = 100;
+ point_density->radius = 0.3f;
+ point_density->space = SHD_POINTDENSITY_SPACE_OBJECT;
+ point_density->color_source = SHD_POINTDENSITY_COLOR_PARTAGE;
+ node->storage = point_density;
+}
+
+/* node type definition */
+void register_node_type_sh_tex_pointdensity(void)
+{
+ static bNodeType ntype;
+
+ sh_node_type_base(&ntype,
+ SH_NODE_TEX_POINTDENSITY,
+ "Point Density",
+ NODE_CLASS_TEXTURE,
+ 0);
+ node_type_compatibility(&ntype, NODE_NEW_SHADING);
+ node_type_socket_templates(&ntype,
+ sh_node_tex_pointdensity_in,
+ sh_node_tex_pointdensity_out);
+ node_type_init(&ntype, node_shader_init_tex_pointdensity);
+ node_type_storage(&ntype,
+ "NodeShaderTexPointDensity",
+ node_free_standard_storage,
+ node_copy_standard_storage);
+
+ nodeRegisterType(&ntype);
+}
diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_sky.c b/source/blender/nodes/shader/nodes/node_shader_tex_sky.c
index 51cca0df851..495c78ca929 100644
--- a/source/blender/nodes/shader/nodes/node_shader_tex_sky.c
+++ b/source/blender/nodes/shader/nodes/node_shader_tex_sky.c
@@ -42,8 +42,8 @@ static bNodeSocketTemplate sh_node_tex_sky_out[] = {
static void node_shader_init_tex_sky(bNodeTree *UNUSED(ntree), bNode *node)
{
NodeTexSky *tex = MEM_callocN(sizeof(NodeTexSky), "NodeTexSky");
- default_tex_mapping(&tex->base.tex_mapping, TEXMAP_TYPE_POINT);
- default_color_mapping(&tex->base.color_mapping);
+ BKE_texture_mapping_default(&tex->base.tex_mapping, TEXMAP_TYPE_POINT);
+ BKE_texture_colormapping_default(&tex->base.color_mapping);
tex->sun_direction[0] = 0.0f;
tex->sun_direction[1] = 0.0f;
tex->sun_direction[2] = 1.0f;
diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_voronoi.c b/source/blender/nodes/shader/nodes/node_shader_tex_voronoi.c
index 5eba5f3f59d..88596a4a72f 100644
--- a/source/blender/nodes/shader/nodes/node_shader_tex_voronoi.c
+++ b/source/blender/nodes/shader/nodes/node_shader_tex_voronoi.c
@@ -44,8 +44,8 @@ static bNodeSocketTemplate sh_node_tex_voronoi_out[] = {
static void node_shader_init_tex_voronoi(bNodeTree *UNUSED(ntree), bNode *node)
{
NodeTexVoronoi *tex = MEM_callocN(sizeof(NodeTexVoronoi), "NodeTexVoronoi");
- default_tex_mapping(&tex->base.tex_mapping, TEXMAP_TYPE_POINT);
- default_color_mapping(&tex->base.color_mapping);
+ BKE_texture_mapping_default(&tex->base.tex_mapping, TEXMAP_TYPE_POINT);
+ BKE_texture_colormapping_default(&tex->base.color_mapping);
tex->coloring = SHD_VORONOI_INTENSITY;
node->storage = tex;
diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_wave.c b/source/blender/nodes/shader/nodes/node_shader_tex_wave.c
index ef79aac0d32..100510641e8 100644
--- a/source/blender/nodes/shader/nodes/node_shader_tex_wave.c
+++ b/source/blender/nodes/shader/nodes/node_shader_tex_wave.c
@@ -47,8 +47,8 @@ static bNodeSocketTemplate sh_node_tex_wave_out[] = {
static void node_shader_init_tex_wave(bNodeTree *UNUSED(ntree), bNode *node)
{
NodeTexWave *tex = MEM_callocN(sizeof(NodeTexWave), "NodeTexWave");
- default_tex_mapping(&tex->base.tex_mapping, TEXMAP_TYPE_POINT);
- default_color_mapping(&tex->base.color_mapping);
+ BKE_texture_mapping_default(&tex->base.tex_mapping, TEXMAP_TYPE_POINT);
+ BKE_texture_colormapping_default(&tex->base.color_mapping);
tex->wave_type = SHD_WAVE_BANDS;
node->storage = tex;
diff --git a/source/blender/nodes/shader/nodes/node_shader_texture.c b/source/blender/nodes/shader/nodes/node_shader_texture.c
index d02d72563ba..5cdbaf444f8 100644
--- a/source/blender/nodes/shader/nodes/node_shader_texture.c
+++ b/source/blender/nodes/shader/nodes/node_shader_texture.c
@@ -29,11 +29,8 @@
* \ingroup shdnodes
*/
-
#include "DNA_texture_types.h"
-#include "IMB_colormanagement.h"
-
#include "node_shader_util.h"
/* **************** TEXTURE ******************** */
diff --git a/source/blender/nodes/shader/nodes/node_shader_uvAlongStroke.c b/source/blender/nodes/shader/nodes/node_shader_uvAlongStroke.c
index 48eb4cadba4..67342e1e836 100644
--- a/source/blender/nodes/shader/nodes/node_shader_uvAlongStroke.c
+++ b/source/blender/nodes/shader/nodes/node_shader_uvAlongStroke.c
@@ -27,8 +27,6 @@
#include "../node_shader_util.h"
-#include "DNA_customdata_types.h"
-
/* **************** OUTPUT ******************** */
static bNodeSocketTemplate sh_node_uvalongstroke_out[] = {
diff --git a/source/blender/nodes/shader/nodes/node_shader_valToRgb.c b/source/blender/nodes/shader/nodes/node_shader_valToRgb.c
index fa5d9b43ee7..72942cce9c5 100644
--- a/source/blender/nodes/shader/nodes/node_shader_valToRgb.c
+++ b/source/blender/nodes/shader/nodes/node_shader_valToRgb.c
@@ -31,6 +31,7 @@
#include "node_shader_util.h"
+#include "IMB_colormanagement.h"
/* **************** VALTORGB ******************** */
static bNodeSocketTemplate sh_node_valtorgb_in[] = {
@@ -106,7 +107,7 @@ static void node_shader_exec_rgbtobw(void *UNUSED(data), int UNUSED(thread), bNo
float col[3];
nodestack_get_vec(col, SOCK_VECTOR, in[0]);
- out[0]->vec[0] = rgb_to_bw(col);
+ out[0]->vec[0] = IMB_colormanagement_get_luminance(col);
}
static int gpu_shader_rgbtobw(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
diff --git a/source/blender/nodes/shader/nodes/node_shader_vectMath.c b/source/blender/nodes/shader/nodes/node_shader_vectMath.c
index f2ea2faa5a7..45a11c5f799 100644
--- a/source/blender/nodes/shader/nodes/node_shader_vectMath.c
+++ b/source/blender/nodes/shader/nodes/node_shader_vectMath.c
@@ -29,11 +29,8 @@
* \ingroup shdnodes
*/
-
-
#include "node_shader_util.h"
-
/* **************** VECTOR MATH ******************** */
static bNodeSocketTemplate sh_node_vect_math_in[] = {
{ SOCK_VECTOR, 1, N_("Vector"), 0.5f, 0.5f, 0.5f, 1.0f, -10000.0f, 10000.0f, PROP_NONE},
@@ -59,14 +56,14 @@ static void node_shader_exec_vect_math(void *UNUSED(data), int UNUSED(thread), b
out[0]->vec[1] = vec1[1] + vec2[1];
out[0]->vec[2] = vec1[2] + vec2[2];
- out[1]->vec[0] = (fabsf(out[0]->vec[0]) + fabsf(out[0]->vec[0]) + fabsf(out[0]->vec[0])) / 3;
+ out[1]->vec[0] = (fabsf(out[0]->vec[0]) + fabsf(out[0]->vec[1]) + fabsf(out[0]->vec[2])) / 3.0f;
}
else if (node->custom1 == 1) { /* Subtract */
out[0]->vec[0] = vec1[0] - vec2[0];
out[0]->vec[1] = vec1[1] - vec2[1];
out[0]->vec[2] = vec1[2] - vec2[2];
- out[1]->vec[0] = (fabsf(out[0]->vec[0]) + fabsf(out[0]->vec[0]) + fabsf(out[0]->vec[0])) / 3;
+ out[1]->vec[0] = (fabsf(out[0]->vec[0]) + fabsf(out[0]->vec[1]) + fabsf(out[0]->vec[2])) / 3.0f;
}
else if (node->custom1 == 2) { /* Average */
out[0]->vec[0] = vec1[0] + vec2[0];
diff --git a/source/blender/nodes/texture/node_texture_tree.c b/source/blender/nodes/texture/node_texture_tree.c
index 1b790f87faf..714665c303b 100644
--- a/source/blender/nodes/texture/node_texture_tree.c
+++ b/source/blender/nodes/texture/node_texture_tree.c
@@ -40,12 +40,10 @@
#include "BLI_threads.h"
#include "BLI_utildefines.h"
-#include "BLF_translation.h"
+#include "BLT_translation.h"
#include "BKE_context.h"
-#include "BKE_global.h"
#include "BKE_linestyle.h"
-#include "BKE_main.h"
#include "BKE_node.h"
#include "BKE_paint.h"
@@ -57,7 +55,6 @@
#include "RNA_access.h"
-#include "RE_pipeline.h"
#include "RE_shader_ext.h"
@@ -339,7 +336,7 @@ int ntreeTexExecTree(
data.osatex = osatex;
data.target = texres;
data.do_preview = preview;
- data.do_manage = (shi) ? shi->do_manage : 0;
+ data.do_manage = (shi) ? shi->do_manage : true;
data.thread = thread;
data.which_output = which_output;
data.cfra = cfra;
diff --git a/source/blender/nodes/texture/node_texture_util.h b/source/blender/nodes/texture/node_texture_util.h
index eb81bcd6949..0410a9d4b33 100644
--- a/source/blender/nodes/texture/node_texture_util.h
+++ b/source/blender/nodes/texture/node_texture_util.h
@@ -67,9 +67,7 @@
#include "node_util.h"
#include "NOD_texture.h"
-#include "NOD_texture.h"
-
-#include "BLF_translation.h"
+#include "BLT_translation.h"
#include "IMB_imbuf_types.h"
#include "IMB_imbuf.h"
diff --git a/source/blender/nodes/texture/nodes/node_texture_math.c b/source/blender/nodes/texture/nodes/node_texture_math.c
index 94e778e10fb..19bc16fb82d 100644
--- a/source/blender/nodes/texture/nodes/node_texture_math.c
+++ b/source/blender/nodes/texture/nodes/node_texture_math.c
@@ -53,16 +53,16 @@ static void valuefn(float *out, TexParams *p, bNode *node, bNodeStack **in, shor
switch (node->custom1) {
- case 0: /* Add */
+ case NODE_MATH_ADD:
*out = in0 + in1;
break;
- case 1: /* Subtract */
+ case NODE_MATH_SUB:
*out = in0 - in1;
break;
- case 2: /* Multiply */
+ case NODE_MATH_MUL:
*out = in0 * in1;
break;
- case 3: /* Divide */
+ case NODE_MATH_DIVIDE:
{
if (in1 == 0) /* We don't want to divide by zero. */
*out = 0.0;
@@ -70,22 +70,22 @@ static void valuefn(float *out, TexParams *p, bNode *node, bNodeStack **in, shor
*out = in0 / in1;
break;
}
- case 4: /* Sine */
+ case NODE_MATH_SIN:
{
*out = sinf(in0);
break;
}
- case 5: /* Cosine */
+ case NODE_MATH_COS:
{
*out = cosf(in0);
break;
}
- case 6: /* Tangent */
+ case NODE_MATH_TAN:
{
*out = tanf(in0);
break;
}
- case 7: /* Arc-Sine */
+ case NODE_MATH_ASIN:
{
/* Can't do the impossible... */
if (in0 <= 1 && in0 >= -1)
@@ -94,7 +94,7 @@ static void valuefn(float *out, TexParams *p, bNode *node, bNodeStack **in, shor
*out = 0.0;
break;
}
- case 8: /* Arc-Cosine */
+ case NODE_MATH_ACOS:
{
/* Can't do the impossible... */
if (in0 <= 1 && in0 >= -1)
@@ -103,12 +103,12 @@ static void valuefn(float *out, TexParams *p, bNode *node, bNodeStack **in, shor
*out = 0.0;
break;
}
- case 9: /* Arc-Tangent */
+ case NODE_MATH_ATAN:
{
*out = atan(in0);
break;
}
- case 10: /* Power */
+ case NODE_MATH_POW:
{
/* Only raise negative numbers by full integers */
if (in0 >= 0) {
@@ -125,7 +125,7 @@ static void valuefn(float *out, TexParams *p, bNode *node, bNodeStack **in, shor
}
break;
}
- case 11: /* Logarithm */
+ case NODE_MATH_LOG:
{
/* Don't want any imaginary numbers... */
if (in0 > 0 && in1 > 0)
@@ -134,7 +134,7 @@ static void valuefn(float *out, TexParams *p, bNode *node, bNodeStack **in, shor
*out = 0.0;
break;
}
- case 12: /* Minimum */
+ case NODE_MATH_MIN:
{
if (in0 < in1)
*out = in0;
@@ -142,7 +142,7 @@ static void valuefn(float *out, TexParams *p, bNode *node, bNodeStack **in, shor
*out = in1;
break;
}
- case 13: /* Maximum */
+ case NODE_MATH_MAX:
{
if (in0 > in1)
*out = in0;
@@ -150,13 +150,13 @@ static void valuefn(float *out, TexParams *p, bNode *node, bNodeStack **in, shor
*out = in1;
break;
}
- case 14: /* Round */
+ case NODE_MATH_ROUND:
{
*out = (in0 < 0) ? (int)(in0 - 0.5f) : (int)(in0 + 0.5f);
break;
}
- case 15: /* Less Than */
+ case NODE_MATH_LESS:
{
if (in0 < in1)
*out = 1.0f;
@@ -165,7 +165,7 @@ static void valuefn(float *out, TexParams *p, bNode *node, bNodeStack **in, shor
break;
}
- case 16: /* Greater Than */
+ case NODE_MATH_GREATER:
{
if (in0 > in1)
*out = 1.0f;
@@ -174,7 +174,7 @@ static void valuefn(float *out, TexParams *p, bNode *node, bNodeStack **in, shor
break;
}
- case 17: /* Modulo */
+ case NODE_MATH_MOD:
{
if (in1 == 0.0f)
*out = 0.0f;
@@ -183,7 +183,7 @@ static void valuefn(float *out, TexParams *p, bNode *node, bNodeStack **in, shor
break;
}
- case 18: /* Absolute */
+ case NODE_MATH_ABS:
{
*out = fabsf(in0);
break;
@@ -195,6 +195,10 @@ static void valuefn(float *out, TexParams *p, bNode *node, bNodeStack **in, shor
break;
}
}
+
+ if (node->custom2 & SHD_MATH_CLAMP) {
+ CLAMP(*out, 0.0f, 1.0f);
+ }
}
static void exec(void *data, int UNUSED(thread), bNode *node, bNodeExecData *execdata, bNodeStack **in, bNodeStack **out)
diff --git a/source/blender/nodes/texture/nodes/node_texture_proc.c b/source/blender/nodes/texture/nodes/node_texture_proc.c
index b49ec1fd503..0be5f875a23 100644
--- a/source/blender/nodes/texture/nodes/node_texture_proc.c
+++ b/source/blender/nodes/texture/nodes/node_texture_proc.c
@@ -286,7 +286,7 @@ static void init(bNodeTree *UNUSED(ntree), bNode *node)
Tex *tex = MEM_callocN(sizeof(Tex), "Tex");
node->storage = tex;
- default_tex(tex);
+ BKE_texture_default(tex);
tex->type = node->type - TEX_NODE_PROC;
if (tex->type == TEX_WOOD)
diff --git a/source/blender/nodes/texture/nodes/node_texture_valToRgb.c b/source/blender/nodes/texture/nodes/node_texture_valToRgb.c
index 7f8adab2da5..a49d82d27a9 100644
--- a/source/blender/nodes/texture/nodes/node_texture_valToRgb.c
+++ b/source/blender/nodes/texture/nodes/node_texture_valToRgb.c
@@ -32,6 +32,7 @@
#include "node_texture_util.h"
#include "NOD_texture.h"
+#include "IMB_colormanagement.h"
/* **************** VALTORGB ******************** */
static bNodeSocketTemplate valtorgb_in[] = {
@@ -91,7 +92,7 @@ static void rgbtobw_valuefn(float *out, TexParams *p, bNode *UNUSED(node), bNode
{
float cin[4];
tex_input_rgba(cin, in[0], p, thread);
- *out = rgb_to_bw(cin);
+ *out = IMB_colormanagement_get_luminance(cin);
}
static void rgbtobw_exec(void *data, int UNUSED(thread), bNode *node, bNodeExecData *execdata, bNodeStack **in, bNodeStack **out)
diff --git a/source/blender/physics/BPH_mass_spring.h b/source/blender/physics/BPH_mass_spring.h
new file mode 100644
index 00000000000..c650d83c927
--- /dev/null
+++ b/source/blender/physics/BPH_mass_spring.h
@@ -0,0 +1,67 @@
+/*
+ * ***** 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) Blender Foundation
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Lukas Toenne
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/physics/BPH_mass_spring.h
+ * \ingroup bph
+ */
+
+#ifndef __BPH_MASS_SPRING_H__
+#define __BPH_MASS_SPRING_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct Implicit_Data;
+struct Object;
+struct ClothModifierData;
+struct ListBase;
+struct VoxelData;
+
+typedef enum eMassSpringSolverStatus {
+ BPH_SOLVER_SUCCESS = (1 << 0),
+ BPH_SOLVER_NUMERICAL_ISSUE = (1 << 1),
+ BPH_SOLVER_NO_CONVERGENCE = (1 << 2),
+ BPH_SOLVER_INVALID_INPUT = (1 << 3),
+} eMassSpringSolverStatus;
+
+struct Implicit_Data *BPH_mass_spring_solver_create(int numverts, int numsprings);
+void BPH_mass_spring_solver_free(struct Implicit_Data *id);
+int BPH_mass_spring_solver_numvert(struct Implicit_Data *id);
+
+int BPH_cloth_solver_init(struct Object *ob, struct ClothModifierData *clmd);
+void BPH_cloth_solver_free(struct ClothModifierData *clmd);
+int BPH_cloth_solve(struct Object *ob, float frame, struct ClothModifierData *clmd, struct ListBase *effectors);
+void BKE_cloth_solver_set_positions(struct ClothModifierData *clmd);
+
+bool BPH_cloth_solver_get_texture_data(struct Object *ob, struct ClothModifierData *clmd, struct VoxelData *vd);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/source/blender/physics/CMakeLists.txt b/source/blender/physics/CMakeLists.txt
new file mode 100644
index 00000000000..08ff1faca49
--- /dev/null
+++ b/source/blender/physics/CMakeLists.txt
@@ -0,0 +1,53 @@
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# The Original Code is Copyright (C) 2014, Blender Foundation
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): Lukas Toenne
+#
+# ***** END GPL LICENSE BLOCK *****
+
+set(INC
+ .
+ intern
+ ../blenlib
+ ../blenkernel
+ ../imbuf
+ ../makesdna
+ ../../../intern/guardedalloc
+ ../../../extern/Eigen3
+)
+
+set(INC_SYS
+
+)
+
+set(SRC
+ intern/BPH_mass_spring.cpp
+ intern/ConstrainedConjugateGradient.h
+ intern/hair_volume.cpp
+ intern/implicit.h
+ intern/implicit_blender.c
+ intern/implicit_eigen.cpp
+ intern/eigen_utils.h
+
+ BPH_mass_spring.h
+)
+
+blender_add_lib(bf_physics "${SRC}" "${INC}" "${INC_SYS}")
diff --git a/source/blender/physics/SConscript b/source/blender/physics/SConscript
new file mode 100644
index 00000000000..c8165886cab
--- /dev/null
+++ b/source/blender/physics/SConscript
@@ -0,0 +1,44 @@
+#!/usr/bin/env python
+#
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# The Original Code is Copyright (C) 2011, Blender Foundation
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): Jeroen Bakker, Monique Dewanchand, Blender Developers Fund.
+#
+# ***** END GPL LICENSE BLOCK *****
+
+Import ('env')
+defs = []
+
+sources = env.Glob('intern/*.cpp') + env.Glob('intern/*.c')
+
+incs = [
+ '.',
+ 'intern',
+ '../blenlib',
+ '../blenkernel',
+ '../imbuf',
+ '../makesdna',
+ '../../../intern/guardedalloc',
+ '../../../extern/Eigen3',
+ ]
+
+env.BlenderLib('bf_physics', sources, incs, defines=defs, libtype=['core', 'player'], priority=[180, 190])
diff --git a/source/blender/physics/intern/BPH_mass_spring.cpp b/source/blender/physics/intern/BPH_mass_spring.cpp
new file mode 100644
index 00000000000..30a8478e0e4
--- /dev/null
+++ b/source/blender/physics/intern/BPH_mass_spring.cpp
@@ -0,0 +1,1117 @@
+/*
+ * ***** 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) Blender Foundation
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Lukas Toenne
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/physics/intern/BPH_mass_spring.cpp
+ * \ingroup bph
+ */
+
+extern "C" {
+#include "MEM_guardedalloc.h"
+
+#include "DNA_cloth_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_object_force.h"
+#include "DNA_object_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_modifier_types.h"
+
+#include "BLI_math.h"
+#include "BLI_linklist.h"
+#include "BLI_utildefines.h"
+
+#include "BKE_cloth.h"
+#include "BKE_collision.h"
+#include "BKE_effect.h"
+}
+
+#include "BPH_mass_spring.h"
+#include "implicit.h"
+
+static float I3[3][3] = {{1.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {0.0, 0.0, 1.0}};
+
+/* Number of off-diagonal non-zero matrix blocks.
+ * Basically there is one of these for each vertex-vertex interaction.
+ */
+static int cloth_count_nondiag_blocks(Cloth *cloth)
+{
+ LinkNode *link;
+ int nondiag = 0;
+
+ for (link = cloth->springs; link; link = link->next) {
+ ClothSpring *spring = (ClothSpring *)link->link;
+ switch (spring->type) {
+ case CLOTH_SPRING_TYPE_BENDING_ANG:
+ /* angular bending combines 3 vertices */
+ nondiag += 3;
+ break;
+
+ default:
+ /* all other springs depend on 2 vertices only */
+ nondiag += 1;
+ break;
+ }
+ }
+
+ return nondiag;
+}
+
+int BPH_cloth_solver_init(Object *UNUSED(ob), ClothModifierData *clmd)
+{
+ Cloth *cloth = clmd->clothObject;
+ ClothVertex *verts = cloth->verts;
+ const float ZERO[3] = {0.0f, 0.0f, 0.0f};
+ Implicit_Data *id;
+ unsigned int i, nondiag;
+
+ nondiag = cloth_count_nondiag_blocks(cloth);
+ cloth->implicit = id = BPH_mass_spring_solver_create(cloth->mvert_num, nondiag);
+
+ for (i = 0; i < cloth->mvert_num; i++) {
+ BPH_mass_spring_set_vertex_mass(id, i, verts[i].mass);
+ }
+
+ for (i = 0; i < cloth->mvert_num; i++) {
+ BPH_mass_spring_set_motion_state(id, i, verts[i].x, ZERO);
+ }
+
+ return 1;
+}
+
+void BPH_cloth_solver_free(ClothModifierData *clmd)
+{
+ Cloth *cloth = clmd->clothObject;
+
+ if (cloth->implicit) {
+ BPH_mass_spring_solver_free(cloth->implicit);
+ cloth->implicit = NULL;
+ }
+}
+
+void BKE_cloth_solver_set_positions(ClothModifierData *clmd)
+{
+ Cloth *cloth = clmd->clothObject;
+ ClothVertex *verts = cloth->verts;
+ unsigned int mvert_num = cloth->mvert_num, i;
+ ClothHairData *cloth_hairdata = clmd->hairdata;
+ Implicit_Data *id = cloth->implicit;
+
+ for (i = 0; i < mvert_num; i++) {
+ if (cloth_hairdata) {
+ ClothHairData *root = &cloth_hairdata[i];
+ BPH_mass_spring_set_rest_transform(id, i, root->rot);
+ }
+ else
+ BPH_mass_spring_set_rest_transform(id, i, I3);
+
+ BPH_mass_spring_set_motion_state(id, i, verts[i].x, verts[i].v);
+ }
+}
+
+static bool collision_response(ClothModifierData *clmd, CollisionModifierData *collmd, CollPair *collpair, float dt, float restitution, float r_impulse[3])
+{
+ Cloth *cloth = clmd->clothObject;
+ int index = collpair->ap1;
+ bool result = false;
+
+ float v1[3], v2_old[3], v2_new[3], v_rel_old[3], v_rel_new[3];
+ float epsilon2 = BLI_bvhtree_getepsilon(collmd->bvhtree);
+
+ float margin_distance = (float)collpair->distance - epsilon2;
+ float mag_v_rel;
+
+ zero_v3(r_impulse);
+
+ if (margin_distance > 0.0f)
+ return false; /* XXX tested before already? */
+
+ /* only handle static collisions here */
+ if ( collpair->flag & COLLISION_IN_FUTURE )
+ return false;
+
+ /* velocity */
+ copy_v3_v3(v1, cloth->verts[index].v);
+ collision_get_collider_velocity(v2_old, v2_new, collmd, collpair);
+ /* relative velocity = velocity of the cloth point relative to the collider */
+ sub_v3_v3v3(v_rel_old, v1, v2_old);
+ sub_v3_v3v3(v_rel_new, v1, v2_new);
+ /* normal component of the relative velocity */
+ mag_v_rel = dot_v3v3(v_rel_old, collpair->normal);
+
+ /* only valid when moving toward the collider */
+ if (mag_v_rel < -ALMOST_ZERO) {
+ float v_nor_old, v_nor_new;
+ float v_tan_old[3], v_tan_new[3];
+ float bounce, repulse;
+
+ /* Collision response based on
+ * "Simulating Complex Hair with Robust Collision Handling" (Choe, Choi, Ko, ACM SIGGRAPH 2005)
+ * http://graphics.snu.ac.kr/publications/2005-choe-HairSim/Choe_2005_SCA.pdf
+ */
+
+ v_nor_old = mag_v_rel;
+ v_nor_new = dot_v3v3(v_rel_new, collpair->normal);
+
+ madd_v3_v3v3fl(v_tan_old, v_rel_old, collpair->normal, -v_nor_old);
+ madd_v3_v3v3fl(v_tan_new, v_rel_new, collpair->normal, -v_nor_new);
+
+ bounce = -v_nor_old * restitution;
+
+ repulse = -margin_distance / dt; /* base repulsion velocity in normal direction */
+ /* XXX this clamping factor is quite arbitrary ...
+ * not sure if there is a more scientific approach, but seems to give good results
+ */
+ CLAMP(repulse, 0.0f, 4.0f * bounce);
+
+ if (margin_distance < -epsilon2) {
+ mul_v3_v3fl(r_impulse, collpair->normal, max_ff(repulse, bounce) - v_nor_new);
+ }
+ else {
+ bounce = 0.0f;
+ mul_v3_v3fl(r_impulse, collpair->normal, repulse - v_nor_new);
+ }
+
+ result = true;
+ }
+
+ return result;
+}
+
+/* Init constraint matrix
+ * This is part of the modified CG method suggested by Baraff/Witkin in
+ * "Large Steps in Cloth Simulation" (Siggraph 1998)
+ */
+static void cloth_setup_constraints(ClothModifierData *clmd, ColliderContacts *contacts, int totcolliders, float dt)
+{
+ Cloth *cloth = clmd->clothObject;
+ Implicit_Data *data = cloth->implicit;
+ ClothVertex *verts = cloth->verts;
+ int mvert_num = cloth->mvert_num;
+ int i, j, v;
+
+ const float ZERO[3] = {0.0f, 0.0f, 0.0f};
+
+ BPH_mass_spring_clear_constraints(data);
+
+ for (v = 0; v < mvert_num; v++) {
+ if (verts[v].flags & CLOTH_VERT_FLAG_PINNED) {
+ /* pinned vertex constraints */
+ BPH_mass_spring_add_constraint_ndof0(data, v, ZERO); /* velocity is defined externally */
+ }
+
+ verts[v].impulse_count = 0;
+ }
+
+ for (i = 0; i < totcolliders; ++i) {
+ ColliderContacts *ct = &contacts[i];
+ for (j = 0; j < ct->totcollisions; ++j) {
+ CollPair *collpair = &ct->collisions[j];
+// float restitution = (1.0f - clmd->coll_parms->damping) * (1.0f - ct->ob->pd->pdef_sbdamp);
+ float restitution = 0.0f;
+ int v = collpair->face1;
+ float impulse[3];
+
+ /* pinned verts handled separately */
+ if (verts[v].flags & CLOTH_VERT_FLAG_PINNED)
+ continue;
+
+ /* XXX cheap way of avoiding instability from multiple collisions in the same step
+ * this should eventually be supported ...
+ */
+ if (verts[v].impulse_count > 0)
+ continue;
+
+ /* calculate collision response */
+ if (!collision_response(clmd, ct->collmd, collpair, dt, restitution, impulse))
+ continue;
+
+ BPH_mass_spring_add_constraint_ndof2(data, v, collpair->normal, impulse);
+ ++verts[v].impulse_count;
+ }
+ }
+}
+
+/* computes where the cloth would be if it were subject to perfectly stiff edges
+ * (edge distance constraints) in a lagrangian solver. then add forces to help
+ * guide the implicit solver to that state. this function is called after
+ * collisions*/
+static int UNUSED_FUNCTION(cloth_calc_helper_forces)(Object *UNUSED(ob), ClothModifierData *clmd, float (*initial_cos)[3], float UNUSED(step), float dt)
+{
+ Cloth *cloth= clmd->clothObject;
+ float (*cos)[3] = (float (*)[3])MEM_callocN(sizeof(float[3]) * cloth->mvert_num, "cos cloth_calc_helper_forces");
+ float *masses = (float *)MEM_callocN(sizeof(float) * cloth->mvert_num, "cos cloth_calc_helper_forces");
+ LinkNode *node;
+ ClothSpring *spring;
+ ClothVertex *cv;
+ int i, steps;
+
+ cv = cloth->verts;
+ for (i = 0; i < cloth->mvert_num; i++, cv++) {
+ copy_v3_v3(cos[i], cv->tx);
+
+ if (cv->goal == 1.0f || len_squared_v3v3(initial_cos[i], cv->tx) != 0.0f) {
+ masses[i] = 1e+10;
+ }
+ else {
+ masses[i] = cv->mass;
+ }
+ }
+
+ steps = 55;
+ for (i=0; i<steps; i++) {
+ for (node=cloth->springs; node; node=node->next) {
+ /* ClothVertex *cv1, *cv2; */ /* UNUSED */
+ int v1, v2;
+ float len, c, l, vec[3];
+
+ spring = (ClothSpring *)node->link;
+ if (spring->type != CLOTH_SPRING_TYPE_STRUCTURAL && spring->type != CLOTH_SPRING_TYPE_SHEAR)
+ continue;
+
+ v1 = spring->ij; v2 = spring->kl;
+ /* cv1 = cloth->verts + v1; */ /* UNUSED */
+ /* cv2 = cloth->verts + v2; */ /* UNUSED */
+ len = len_v3v3(cos[v1], cos[v2]);
+
+ sub_v3_v3v3(vec, cos[v1], cos[v2]);
+ normalize_v3(vec);
+
+ c = (len - spring->restlen);
+ if (c == 0.0f)
+ continue;
+
+ l = c / ((1.0f / masses[v1]) + (1.0f / masses[v2]));
+
+ mul_v3_fl(vec, -(1.0f / masses[v1]) * l);
+ add_v3_v3(cos[v1], vec);
+
+ sub_v3_v3v3(vec, cos[v2], cos[v1]);
+ normalize_v3(vec);
+
+ mul_v3_fl(vec, -(1.0f / masses[v2]) * l);
+ add_v3_v3(cos[v2], vec);
+ }
+ }
+
+ cv = cloth->verts;
+ for (i = 0; i < cloth->mvert_num; i++, cv++) {
+ float vec[3];
+
+ /*compute forces*/
+ sub_v3_v3v3(vec, cos[i], cv->tx);
+ mul_v3_fl(vec, cv->mass*dt*20.0f);
+ add_v3_v3(cv->tv, vec);
+ //copy_v3_v3(cv->tx, cos[i]);
+ }
+
+ MEM_freeN(cos);
+ MEM_freeN(masses);
+
+ return 1;
+}
+
+BLI_INLINE void cloth_calc_spring_force(ClothModifierData *clmd, ClothSpring *s, float time)
+{
+ Cloth *cloth = clmd->clothObject;
+ ClothSimSettings *parms = clmd->sim_parms;
+ Implicit_Data *data = cloth->implicit;
+ ClothVertex *verts = cloth->verts;
+
+ bool no_compress = parms->flags & CLOTH_SIMSETTINGS_FLAG_NO_SPRING_COMPRESS;
+
+ zero_v3(s->f);
+ zero_m3(s->dfdx);
+ zero_m3(s->dfdv);
+
+ s->flags &= ~CLOTH_SPRING_FLAG_NEEDED;
+
+ // calculate force of structural + shear springs
+ if ((s->type & CLOTH_SPRING_TYPE_STRUCTURAL) || (s->type & CLOTH_SPRING_TYPE_SHEAR) || (s->type & CLOTH_SPRING_TYPE_SEWING) ) {
+#ifdef CLOTH_FORCE_SPRING_STRUCTURAL
+ float k, scaling;
+
+ s->flags |= CLOTH_SPRING_FLAG_NEEDED;
+
+ scaling = parms->structural + s->stiffness * fabsf(parms->max_struct - parms->structural);
+ k = scaling / (parms->avg_spring_len + FLT_EPSILON);
+
+ if (s->type & CLOTH_SPRING_TYPE_SEWING) {
+ // TODO: verify, half verified (couldn't see error)
+ // sewing springs usually have a large distance at first so clamp the force so we don't get tunnelling through colission objects
+ BPH_mass_spring_force_spring_linear(data, s->ij, s->kl, s->restlen, k, parms->Cdis, no_compress, parms->max_sewing, s->f, s->dfdx, s->dfdv);
+ }
+ else {
+ BPH_mass_spring_force_spring_linear(data, s->ij, s->kl, s->restlen, k, parms->Cdis, no_compress, 0.0f, s->f, s->dfdx, s->dfdv);
+ }
+#endif
+ }
+ else if (s->type & CLOTH_SPRING_TYPE_GOAL) {
+#ifdef CLOTH_FORCE_SPRING_GOAL
+ float goal_x[3], goal_v[3];
+ float k, scaling;
+
+ s->flags |= CLOTH_SPRING_FLAG_NEEDED;
+
+ // current_position = xold + t * (newposition - xold)
+ interp_v3_v3v3(goal_x, verts[s->ij].xold, verts[s->ij].xconst, time);
+ sub_v3_v3v3(goal_v, verts[s->ij].xconst, verts[s->ij].xold); // distance covered over dt==1
+
+ scaling = parms->goalspring + s->stiffness * fabsf(parms->max_struct - parms->goalspring);
+ k = verts[s->ij].goal * scaling / (parms->avg_spring_len + FLT_EPSILON);
+
+ BPH_mass_spring_force_spring_goal(data, s->ij, goal_x, goal_v, k, parms->goalfrict * 0.01f, s->f, s->dfdx, s->dfdv);
+#endif
+ }
+ else if (s->type & CLOTH_SPRING_TYPE_BENDING) { /* calculate force of bending springs */
+#ifdef CLOTH_FORCE_SPRING_BEND
+ float kb, cb, scaling;
+
+ s->flags |= CLOTH_SPRING_FLAG_NEEDED;
+
+ scaling = parms->bending + s->stiffness * fabsf(parms->max_bend - parms->bending);
+ kb = scaling / (20.0f * (parms->avg_spring_len + FLT_EPSILON));
+
+ // Fix for [#45084] for cloth stiffness must have cb proportional to kb
+ cb = kb * parms->bending_damping;
+
+ BPH_mass_spring_force_spring_bending(data, s->ij, s->kl, s->restlen, kb, cb, s->f, s->dfdx, s->dfdv);
+#endif
+ }
+ else if (s->type & CLOTH_SPRING_TYPE_BENDING_ANG) {
+#ifdef CLOTH_FORCE_SPRING_BEND
+ float kb, cb, scaling;
+
+ s->flags |= CLOTH_SPRING_FLAG_NEEDED;
+
+ /* XXX WARNING: angular bending springs for hair apply stiffness factor as an overall factor, unlike cloth springs!
+ * this is crap, but needed due to cloth/hair mixing ...
+ * max_bend factor is not even used for hair, so ...
+ */
+ scaling = s->stiffness * parms->bending;
+ kb = scaling / (20.0f * (parms->avg_spring_len + FLT_EPSILON));
+
+ // Fix for [#45084] for cloth stiffness must have cb proportional to kb
+ cb = kb * parms->bending_damping;
+
+ /* XXX assuming same restlen for ij and jk segments here, this can be done correctly for hair later */
+ BPH_mass_spring_force_spring_bending_angular(data, s->ij, s->kl, s->mn, s->target, kb, cb);
+
+#if 0
+ {
+ float x_kl[3], x_mn[3], v[3], d[3];
+
+ BPH_mass_spring_get_motion_state(data, s->kl, x_kl, v);
+ BPH_mass_spring_get_motion_state(data, s->mn, x_mn, v);
+
+ BKE_sim_debug_data_add_dot(clmd->debug_data, x_kl, 0.9, 0.9, 0.9, "target", 7980, s->kl);
+ BKE_sim_debug_data_add_line(clmd->debug_data, x_kl, x_mn, 0.8, 0.8, 0.8, "target", 7981, s->kl);
+
+ copy_v3_v3(d, s->target);
+ BKE_sim_debug_data_add_vector(clmd->debug_data, x_kl, d, 0.8, 0.8, 0.2, "target", 7982, s->kl);
+
+// copy_v3_v3(d, s->target_ij);
+// BKE_sim_debug_data_add_vector(clmd->debug_data, x, d, 1, 0.4, 0.4, "target", 7983, s->kl);
+ }
+#endif
+#endif
+ }
+}
+
+static void hair_get_boundbox(ClothModifierData *clmd, float gmin[3], float gmax[3])
+{
+ Cloth *cloth = clmd->clothObject;
+ Implicit_Data *data = cloth->implicit;
+ unsigned int looptri_num = cloth->tri_num;
+ int i;
+
+ INIT_MINMAX(gmin, gmax);
+ for (i = 0; i < looptri_num; i++) {
+ float x[3];
+ BPH_mass_spring_get_motion_state(data, i, x, NULL);
+ DO_MINMAX(x, gmin, gmax);
+ }
+}
+
+static void cloth_calc_force(ClothModifierData *clmd, float UNUSED(frame), ListBase *effectors, float time)
+{
+ /* Collect forces and derivatives: F, dFdX, dFdV */
+ Cloth *cloth = clmd->clothObject;
+ Implicit_Data *data = cloth->implicit;
+ unsigned int i = 0;
+ float drag = clmd->sim_parms->Cvi * 0.01f; /* viscosity of air scaled in percent */
+ float gravity[3] = {0.0f, 0.0f, 0.0f};
+ const MVertTri *tri = cloth->tri;
+ unsigned int mvert_num = cloth->mvert_num;
+ ClothVertex *vert;
+
+#ifdef CLOTH_FORCE_GRAVITY
+ /* global acceleration (gravitation) */
+ if (clmd->scene->physics_settings.flag & PHYS_GLOBAL_GRAVITY) {
+ /* scale gravity force */
+ mul_v3_v3fl(gravity, clmd->scene->physics_settings.gravity, 0.001f * clmd->sim_parms->effector_weights->global_gravity);
+ }
+ vert = cloth->verts;
+ for (i = 0; i < cloth->mvert_num; i++, vert++) {
+ BPH_mass_spring_force_gravity(data, i, vert->mass, gravity);
+ }
+#endif
+
+ /* cloth_calc_volume_force(clmd); */
+
+#ifdef CLOTH_FORCE_DRAG
+ BPH_mass_spring_force_drag(data, drag);
+#endif
+
+ /* handle external forces like wind */
+ if (effectors) {
+ /* cache per-vertex forces to avoid redundant calculation */
+ float (*winvec)[3] = (float (*)[3])MEM_callocN(sizeof(float[3]) * mvert_num, "effector forces");
+ for (i = 0; i < cloth->mvert_num; i++) {
+ float x[3], v[3];
+ EffectedPoint epoint;
+
+ BPH_mass_spring_get_motion_state(data, i, x, v);
+ pd_point_from_loc(clmd->scene, x, v, i, &epoint);
+ pdDoEffectors(effectors, NULL, clmd->sim_parms->effector_weights, &epoint, winvec[i], NULL);
+ }
+
+ for (i = 0; i < cloth->tri_num; i++) {
+ const MVertTri *vt = &tri[i];
+ BPH_mass_spring_force_face_wind(data, vt->tri[0], vt->tri[1], vt->tri[2], winvec);
+ }
+
+ /* Hair has only edges */
+ if (cloth->tri_num == 0) {
+#if 0
+ ClothHairData *hairdata = clmd->hairdata;
+ ClothHairData *hair_ij, *hair_kl;
+
+ for (LinkNode *link = cloth->springs; link; link = link->next) {
+ ClothSpring *spring = (ClothSpring *)link->link;
+ if (spring->type == CLOTH_SPRING_TYPE_STRUCTURAL) {
+ if (hairdata) {
+ hair_ij = &hairdata[spring->ij];
+ hair_kl = &hairdata[spring->kl];
+ BPH_mass_spring_force_edge_wind(data, spring->ij, spring->kl, hair_ij->radius, hair_kl->radius, winvec);
+ }
+ else
+ BPH_mass_spring_force_edge_wind(data, spring->ij, spring->kl, 1.0f, 1.0f, winvec);
+ }
+ }
+#else
+ ClothHairData *hairdata = clmd->hairdata;
+
+ vert = cloth->verts;
+ for (i = 0; i < cloth->mvert_num; i++, vert++) {
+ if (hairdata) {
+ ClothHairData *hair = &hairdata[i];
+ BPH_mass_spring_force_vertex_wind(data, i, hair->radius, winvec);
+ }
+ else
+ BPH_mass_spring_force_vertex_wind(data, i, 1.0f, winvec);
+ }
+ }
+#endif
+
+ MEM_freeN(winvec);
+ }
+
+ // calculate spring forces
+ for (LinkNode *link = cloth->springs; link; link = link->next) {
+ ClothSpring *spring = (ClothSpring *)link->link;
+ // only handle active springs
+ if (!(spring->flags & CLOTH_SPRING_FLAG_DEACTIVATE))
+ cloth_calc_spring_force(clmd, spring, time);
+ }
+}
+
+/* returns vertexes' motion state */
+BLI_INLINE void cloth_get_grid_location(Implicit_Data *data, float cell_scale, const float cell_offset[3],
+ int index, float x[3], float v[3])
+{
+ BPH_mass_spring_get_position(data, index, x);
+ BPH_mass_spring_get_new_velocity(data, index, v);
+
+ mul_v3_fl(x, cell_scale);
+ add_v3_v3(x, cell_offset);
+}
+
+/* returns next spring forming a continous hair sequence */
+BLI_INLINE LinkNode *hair_spring_next(LinkNode *spring_link)
+{
+ ClothSpring *spring = (ClothSpring *)spring_link->link;
+ LinkNode *next = spring_link->next;
+ if (next) {
+ ClothSpring *next_spring = (ClothSpring *)next->link;
+ if (next_spring->type == CLOTH_SPRING_TYPE_STRUCTURAL && next_spring->kl == spring->ij)
+ return next;
+ }
+ return NULL;
+}
+
+/* XXX this is nasty: cloth meshes do not explicitly store
+ * the order of hair segments!
+ * We have to rely on the spring build function for now,
+ * which adds structural springs in reverse order:
+ * (3,4), (2,3), (1,2)
+ * This is currently the only way to figure out hair geometry inside this code ...
+ */
+static LinkNode *cloth_continuum_add_hair_segments(HairGrid *grid, const float cell_scale, const float cell_offset[3], Cloth *cloth, LinkNode *spring_link)
+{
+ Implicit_Data *data = cloth->implicit;
+ LinkNode *next_spring_link = NULL; /* return value */
+ ClothSpring *spring1, *spring2, *spring3;
+ // ClothVertex *verts = cloth->verts;
+ // ClothVertex *vert3, *vert4;
+ float x1[3], v1[3], x2[3], v2[3], x3[3], v3[3], x4[3], v4[3];
+ float dir1[3], dir2[3], dir3[3];
+
+ spring1 = NULL;
+ spring2 = NULL;
+ spring3 = (ClothSpring *)spring_link->link;
+
+ zero_v3(x1); zero_v3(v1);
+ zero_v3(dir1);
+ zero_v3(x2); zero_v3(v2);
+ zero_v3(dir2);
+
+ // vert3 = &verts[spring3->kl];
+ cloth_get_grid_location(data, cell_scale, cell_offset, spring3->kl, x3, v3);
+ // vert4 = &verts[spring3->ij];
+ cloth_get_grid_location(data, cell_scale, cell_offset, spring3->ij, x4, v4);
+ sub_v3_v3v3(dir3, x4, x3);
+ normalize_v3(dir3);
+
+ while (spring_link) {
+ /* move on */
+ spring1 = spring2;
+ spring2 = spring3;
+
+ // vert3 = vert4;
+
+ copy_v3_v3(x1, x2); copy_v3_v3(v1, v2);
+ copy_v3_v3(x2, x3); copy_v3_v3(v2, v3);
+ copy_v3_v3(x3, x4); copy_v3_v3(v3, v4);
+
+ copy_v3_v3(dir1, dir2);
+ copy_v3_v3(dir2, dir3);
+
+ /* read next segment */
+ next_spring_link = spring_link->next;
+ spring_link = hair_spring_next(spring_link);
+
+ if (spring_link) {
+ spring3 = (ClothSpring *)spring_link->link;
+ // vert4 = &verts[spring3->ij];
+ cloth_get_grid_location(data, cell_scale, cell_offset, spring3->ij, x4, v4);
+ sub_v3_v3v3(dir3, x4, x3);
+ normalize_v3(dir3);
+ }
+ else {
+ spring3 = NULL;
+ // vert4 = NULL;
+ zero_v3(x4); zero_v3(v4);
+ zero_v3(dir3);
+ }
+
+ BPH_hair_volume_add_segment(grid, x1, v1, x2, v2, x3, v3, x4, v4,
+ spring1 ? dir1 : NULL,
+ dir2,
+ spring3 ? dir3 : NULL);
+ }
+
+ return next_spring_link;
+}
+
+static void cloth_continuum_fill_grid(HairGrid *grid, Cloth *cloth)
+{
+#if 0
+ Implicit_Data *data = cloth->implicit;
+ int mvert_num = cloth->mvert_num;
+ ClothVertex *vert;
+ int i;
+
+ for (i = 0, vert = cloth->verts; i < mvert_num; i++, vert++) {
+ float x[3], v[3];
+
+ cloth_get_vertex_motion_state(data, vert, x, v);
+ BPH_hair_volume_add_vertex(grid, x, v);
+ }
+#else
+ LinkNode *link;
+ float cellsize, gmin[3], cell_scale, cell_offset[3];
+
+ /* scale and offset for transforming vertex locations into grid space
+ * (cell size is 0..1, gmin becomes origin)
+ */
+ BPH_hair_volume_grid_geometry(grid, &cellsize, NULL, gmin, NULL);
+ cell_scale = cellsize > 0.0f ? 1.0f / cellsize : 0.0f;
+ mul_v3_v3fl(cell_offset, gmin, cell_scale);
+ negate_v3(cell_offset);
+
+ link = cloth->springs;
+ while (link) {
+ ClothSpring *spring = (ClothSpring *)link->link;
+ if (spring->type == CLOTH_SPRING_TYPE_STRUCTURAL)
+ link = cloth_continuum_add_hair_segments(grid, cell_scale, cell_offset, cloth, link);
+ else
+ link = link->next;
+ }
+#endif
+ BPH_hair_volume_normalize_vertex_grid(grid);
+}
+
+static void cloth_continuum_step(ClothModifierData *clmd, float dt)
+{
+ ClothSimSettings *parms = clmd->sim_parms;
+ Cloth *cloth = clmd->clothObject;
+ Implicit_Data *data = cloth->implicit;
+ int mvert_num = cloth->mvert_num;
+ ClothVertex *vert;
+
+ const float fluid_factor = 0.95f; /* blend between PIC and FLIP methods */
+ float smoothfac = parms->velocity_smooth;
+ /* XXX FIXME arbitrary factor!!! this should be based on some intuitive value instead,
+ * like number of hairs per cell and time decay instead of "strength"
+ */
+ float density_target = parms->density_target;
+ float density_strength = parms->density_strength;
+ float gmin[3], gmax[3];
+ int i;
+
+ /* clear grid info */
+ zero_v3_int(clmd->hair_grid_res);
+ zero_v3(clmd->hair_grid_min);
+ zero_v3(clmd->hair_grid_max);
+ clmd->hair_grid_cellsize = 0.0f;
+
+ hair_get_boundbox(clmd, gmin, gmax);
+
+ /* gather velocities & density */
+ if (smoothfac > 0.0f || density_strength > 0.0f) {
+ HairGrid *grid = BPH_hair_volume_create_vertex_grid(clmd->sim_parms->voxel_cell_size, gmin, gmax);
+
+ cloth_continuum_fill_grid(grid, cloth);
+
+ /* main hair continuum solver */
+ BPH_hair_volume_solve_divergence(grid, dt, density_target, density_strength);
+
+ for (i = 0, vert = cloth->verts; i < mvert_num; i++, vert++) {
+ float x[3], v[3], nv[3];
+
+ /* calculate volumetric velocity influence */
+ BPH_mass_spring_get_position(data, i, x);
+ BPH_mass_spring_get_new_velocity(data, i, v);
+
+ BPH_hair_volume_grid_velocity(grid, x, v, fluid_factor, nv);
+
+ interp_v3_v3v3(nv, v, nv, smoothfac);
+
+ /* apply on hair data */
+ BPH_mass_spring_set_new_velocity(data, i, nv);
+ }
+
+ /* store basic grid info in the modifier data */
+ BPH_hair_volume_grid_geometry(grid, &clmd->hair_grid_cellsize, clmd->hair_grid_res, clmd->hair_grid_min, clmd->hair_grid_max);
+
+#if 0 /* DEBUG hair velocity vector field */
+ {
+ const int size = 64;
+ int i, j;
+ float offset[3], a[3], b[3];
+ const int axis = 0;
+ const float shift = 0.0f;
+
+ copy_v3_v3(offset, clmd->hair_grid_min);
+ zero_v3(a);
+ zero_v3(b);
+
+ offset[axis] = shift * clmd->hair_grid_cellsize;
+ a[(axis+1) % 3] = clmd->hair_grid_max[(axis+1) % 3] - clmd->hair_grid_min[(axis+1) % 3];
+ b[(axis+2) % 3] = clmd->hair_grid_max[(axis+2) % 3] - clmd->hair_grid_min[(axis+2) % 3];
+
+ BKE_sim_debug_data_clear_category(clmd->debug_data, "grid velocity");
+ for (j = 0; j < size; ++j) {
+ for (i = 0; i < size; ++i) {
+ float x[3], v[3], gvel[3], gvel_smooth[3], gdensity;
+
+ madd_v3_v3v3fl(x, offset, a, (float)i / (float)(size-1));
+ madd_v3_v3fl(x, b, (float)j / (float)(size-1));
+ zero_v3(v);
+
+ BPH_hair_volume_grid_interpolate(grid, x, &gdensity, gvel, gvel_smooth, NULL, NULL);
+
+// BKE_sim_debug_data_add_circle(clmd->debug_data, x, gdensity, 0.7, 0.3, 1, "grid density", i, j, 3111);
+ if (!is_zero_v3(gvel) || !is_zero_v3(gvel_smooth)) {
+ float dvel[3];
+ sub_v3_v3v3(dvel, gvel_smooth, gvel);
+// BKE_sim_debug_data_add_vector(clmd->debug_data, x, gvel, 0.4, 0, 1, "grid velocity", i, j, 3112);
+// BKE_sim_debug_data_add_vector(clmd->debug_data, x, gvel_smooth, 0.6, 1, 1, "grid velocity", i, j, 3113);
+ BKE_sim_debug_data_add_vector(clmd->debug_data, x, dvel, 0.4, 1, 0.7, "grid velocity", i, j, 3114);
+#if 0
+ if (gdensity > 0.0f) {
+ float col0[3] = {0.0, 0.0, 0.0};
+ float col1[3] = {0.0, 1.0, 0.0};
+ float col[3];
+
+ interp_v3_v3v3(col, col0, col1, CLAMPIS(gdensity * clmd->sim_parms->density_strength, 0.0, 1.0));
+// BKE_sim_debug_data_add_circle(clmd->debug_data, x, gdensity * clmd->sim_parms->density_strength, 0, 1, 0.4, "grid velocity", i, j, 3115);
+// BKE_sim_debug_data_add_dot(clmd->debug_data, x, col[0], col[1], col[2], "grid velocity", i, j, 3115);
+ BKE_sim_debug_data_add_circle(clmd->debug_data, x, 0.01f, col[0], col[1], col[2], "grid velocity", i, j, 3115);
+ }
+#endif
+ }
+ }
+ }
+ }
+#endif
+
+ BPH_hair_volume_free_vertex_grid(grid);
+ }
+}
+
+#if 0
+static void cloth_calc_volume_force(ClothModifierData *clmd)
+{
+ ClothSimSettings *parms = clmd->sim_parms;
+ Cloth *cloth = clmd->clothObject;
+ Implicit_Data *data = cloth->implicit;
+ int mvert_num = cloth->mvert_num;
+ ClothVertex *vert;
+
+ /* 2.0f is an experimental value that seems to give good results */
+ float smoothfac = 2.0f * parms->velocity_smooth;
+ float collfac = 2.0f * parms->collider_friction;
+ float pressfac = parms->pressure;
+ float minpress = parms->pressure_threshold;
+ float gmin[3], gmax[3];
+ int i;
+
+ hair_get_boundbox(clmd, gmin, gmax);
+
+ /* gather velocities & density */
+ if (smoothfac > 0.0f || pressfac > 0.0f) {
+ HairVertexGrid *vertex_grid = BPH_hair_volume_create_vertex_grid(clmd->sim_parms->voxel_res, gmin, gmax);
+
+ vert = cloth->verts;
+ for (i = 0; i < mvert_num; i++, vert++) {
+ float x[3], v[3];
+
+ if (vert->solver_index < 0) {
+ copy_v3_v3(x, vert->x);
+ copy_v3_v3(v, vert->v);
+ }
+ else {
+ BPH_mass_spring_get_motion_state(data, vert->solver_index, x, v);
+ }
+ BPH_hair_volume_add_vertex(vertex_grid, x, v);
+ }
+ BPH_hair_volume_normalize_vertex_grid(vertex_grid);
+
+ vert = cloth->verts;
+ for (i = 0; i < mvert_num; i++, vert++) {
+ float x[3], v[3], f[3], dfdx[3][3], dfdv[3][3];
+
+ if (vert->solver_index < 0)
+ continue;
+
+ /* calculate volumetric forces */
+ BPH_mass_spring_get_motion_state(data, vert->solver_index, x, v);
+ BPH_hair_volume_vertex_grid_forces(vertex_grid, x, v, smoothfac, pressfac, minpress, f, dfdx, dfdv);
+ /* apply on hair data */
+ BPH_mass_spring_force_extern(data, vert->solver_index, f, dfdx, dfdv);
+ }
+
+ BPH_hair_volume_free_vertex_grid(vertex_grid);
+ }
+}
+#endif
+
+/* old collision stuff for cloth, use for continuity
+ * until a good replacement is ready
+ */
+static void cloth_collision_solve_extra(Object *ob, ClothModifierData *clmd, ListBase *effectors, float frame, float step, float dt)
+{
+ Cloth *cloth = clmd->clothObject;
+ Implicit_Data *id = cloth->implicit;
+ ClothVertex *verts = cloth->verts;
+ int mvert_num = cloth->mvert_num;
+ const float spf = (float)clmd->sim_parms->stepsPerFrame / clmd->sim_parms->timescale;
+
+ bool do_extra_solve;
+ int i;
+
+ if (!(clmd->coll_parms->flags & CLOTH_COLLSETTINGS_FLAG_ENABLED))
+ return;
+ if (!clmd->clothObject->bvhtree)
+ return;
+
+ // update verts to current positions
+ for (i = 0; i < mvert_num; i++) {
+ BPH_mass_spring_get_new_position(id, i, verts[i].tx);
+
+ sub_v3_v3v3(verts[i].tv, verts[i].tx, verts[i].txold);
+ copy_v3_v3(verts[i].v, verts[i].tv);
+ }
+
+#if 0 /* unused */
+ for (i=0, cv=cloth->verts; i<cloth->mvert_num; i++, cv++) {
+ copy_v3_v3(initial_cos[i], cv->tx);
+ }
+#endif
+
+ // call collision function
+ // TODO: check if "step" or "step+dt" is correct - dg
+ do_extra_solve = cloth_bvh_objcollision(ob, clmd, step / clmd->sim_parms->timescale, dt / clmd->sim_parms->timescale);
+
+ // copy corrected positions back to simulation
+ for (i = 0; i < mvert_num; i++) {
+ float curx[3];
+ BPH_mass_spring_get_position(id, i, curx);
+ // correct velocity again, just to be sure we had to change it due to adaptive collisions
+ sub_v3_v3v3(verts[i].tv, verts[i].tx, curx);
+ }
+
+ if (do_extra_solve) {
+// cloth_calc_helper_forces(ob, clmd, initial_cos, step/clmd->sim_parms->timescale, dt/clmd->sim_parms->timescale);
+
+ for (i = 0; i < mvert_num; i++) {
+
+ float newv[3];
+
+ if ((clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL) && (verts [i].flags & CLOTH_VERT_FLAG_PINNED))
+ continue;
+
+ BPH_mass_spring_set_new_position(id, i, verts[i].tx);
+ mul_v3_v3fl(newv, verts[i].tv, spf);
+ BPH_mass_spring_set_new_velocity(id, i, newv);
+ }
+ }
+
+ // X = Xnew;
+ BPH_mass_spring_apply_result(id);
+
+ if (do_extra_solve) {
+ ImplicitSolverResult result;
+
+ /* initialize forces to zero */
+ BPH_mass_spring_clear_forces(id);
+
+ // calculate forces
+ cloth_calc_force(clmd, frame, effectors, step);
+
+ // calculate new velocity and position
+ BPH_mass_spring_solve_velocities(id, dt, &result);
+// cloth_record_result(clmd, &result, clmd->sim_parms->stepsPerFrame);
+
+ /* note: positions are advanced only once in the main solver step! */
+
+ BPH_mass_spring_apply_result(id);
+ }
+}
+
+static void cloth_clear_result(ClothModifierData *clmd)
+{
+ ClothSolverResult *sres = clmd->solver_result;
+
+ sres->status = 0;
+ sres->max_error = sres->min_error = sres->avg_error = 0.0f;
+ sres->max_iterations = sres->min_iterations = 0;
+ sres->avg_iterations = 0.0f;
+}
+
+static void cloth_record_result(ClothModifierData *clmd, ImplicitSolverResult *result, int steps)
+{
+ ClothSolverResult *sres = clmd->solver_result;
+
+ if (sres->status) { /* already initialized ? */
+ /* error only makes sense for successful iterations */
+ if (result->status == BPH_SOLVER_SUCCESS) {
+ sres->min_error = min_ff(sres->min_error, result->error);
+ sres->max_error = max_ff(sres->max_error, result->error);
+ sres->avg_error += result->error / (float)steps;
+ }
+
+ sres->min_iterations = min_ii(sres->min_iterations, result->iterations);
+ sres->max_iterations = max_ii(sres->max_iterations, result->iterations);
+ sres->avg_iterations += (float)result->iterations / (float)steps;
+ }
+ else {
+ /* error only makes sense for successful iterations */
+ if (result->status == BPH_SOLVER_SUCCESS) {
+ sres->min_error = sres->max_error = result->error;
+ sres->avg_error += result->error / (float)steps;
+ }
+
+ sres->min_iterations = sres->max_iterations = result->iterations;
+ sres->avg_iterations += (float)result->iterations / (float)steps;
+ }
+
+ sres->status |= result->status;
+}
+
+int BPH_cloth_solve(Object *ob, float frame, ClothModifierData *clmd, ListBase *effectors)
+{
+ /* Hair currently is a cloth sim in disguise ...
+ * Collision detection and volumetrics work differently then.
+ * Bad design, TODO
+ */
+ const bool is_hair = (clmd->hairdata != NULL);
+
+ unsigned int i=0;
+ float step=0.0f, tf=clmd->sim_parms->timescale;
+ Cloth *cloth = clmd->clothObject;
+ ClothVertex *verts = cloth->verts/*, *cv*/;
+ unsigned int mvert_num = cloth->mvert_num;
+ float dt = clmd->sim_parms->timescale / clmd->sim_parms->stepsPerFrame;
+ Implicit_Data *id = cloth->implicit;
+ ColliderContacts *contacts = NULL;
+ int totcolliders = 0;
+
+ BKE_sim_debug_data_clear_category("collision");
+
+ if (!clmd->solver_result)
+ clmd->solver_result = (ClothSolverResult *)MEM_callocN(sizeof(ClothSolverResult), "cloth solver result");
+ cloth_clear_result(clmd);
+
+ if (clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL) { /* do goal stuff */
+ for (i = 0; i < mvert_num; i++) {
+ // update velocities with constrained velocities from pinned verts
+ if (verts[i].flags & CLOTH_VERT_FLAG_PINNED) {
+ float v[3];
+ sub_v3_v3v3(v, verts[i].xconst, verts[i].xold);
+ // mul_v3_fl(v, clmd->sim_parms->stepsPerFrame);
+ BPH_mass_spring_set_velocity(id, i, v);
+ }
+ }
+ }
+
+ while (step < tf) {
+ ImplicitSolverResult result;
+
+ /* copy velocities for collision */
+ for (i = 0; i < mvert_num; i++) {
+ BPH_mass_spring_get_motion_state(id, i, NULL, verts[i].tv);
+ copy_v3_v3(verts[i].v, verts[i].tv);
+ }
+
+ if (is_hair) {
+ /* determine contact points */
+ if (clmd->coll_parms->flags & CLOTH_COLLSETTINGS_FLAG_ENABLED) {
+ cloth_find_point_contacts(ob, clmd, 0.0f, tf, &contacts, &totcolliders);
+ }
+
+ /* setup vertex constraints for pinned vertices and contacts */
+ cloth_setup_constraints(clmd, contacts, totcolliders, dt);
+ }
+ else {
+ /* setup vertex constraints for pinned vertices */
+ cloth_setup_constraints(clmd, NULL, 0, dt);
+ }
+
+ /* initialize forces to zero */
+ BPH_mass_spring_clear_forces(id);
+
+ // damping velocity for artistic reasons
+ // this is a bad way to do it, should be removed imo - lukas_t
+ if (clmd->sim_parms->vel_damping != 1.0f) {
+ for (i = 0; i < mvert_num; i++) {
+ float v[3];
+ BPH_mass_spring_get_motion_state(id, i, NULL, v);
+ mul_v3_fl(v, clmd->sim_parms->vel_damping);
+ BPH_mass_spring_set_velocity(id, i, v);
+ }
+ }
+
+ // calculate forces
+ cloth_calc_force(clmd, frame, effectors, step);
+
+ // calculate new velocity and position
+ BPH_mass_spring_solve_velocities(id, dt, &result);
+ cloth_record_result(clmd, &result, clmd->sim_parms->stepsPerFrame);
+
+ if (is_hair) {
+ cloth_continuum_step(clmd, dt);
+ }
+
+ BPH_mass_spring_solve_positions(id, dt);
+
+ if (!is_hair) {
+ cloth_collision_solve_extra(ob, clmd, effectors, frame, step, dt);
+ }
+
+ BPH_mass_spring_apply_result(id);
+
+ /* move pinned verts to correct position */
+ for (i = 0; i < mvert_num; i++) {
+ if (clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL) {
+ if (verts[i].flags & CLOTH_VERT_FLAG_PINNED) {
+ float x[3];
+ interp_v3_v3v3(x, verts[i].xold, verts[i].xconst, step + dt);
+ BPH_mass_spring_set_position(id, i, x);
+ }
+ }
+
+ BPH_mass_spring_get_motion_state(id, i, verts[i].txold, NULL);
+ }
+
+ /* free contact points */
+ if (contacts) {
+ cloth_free_contacts(contacts, totcolliders);
+ }
+
+ step += dt;
+ }
+
+ /* copy results back to cloth data */
+ for (i = 0; i < mvert_num; i++) {
+ BPH_mass_spring_get_motion_state(id, i, verts[i].x, verts[i].v);
+ copy_v3_v3(verts[i].txold, verts[i].x);
+ }
+
+ return 1;
+}
+
+bool BPH_cloth_solver_get_texture_data(Object *UNUSED(ob), ClothModifierData *clmd, VoxelData *vd)
+{
+ Cloth *cloth = clmd->clothObject;
+ HairGrid *grid;
+ float gmin[3], gmax[3];
+
+ if (!clmd->clothObject || !clmd->clothObject->implicit)
+ return false;
+
+ hair_get_boundbox(clmd, gmin, gmax);
+
+ grid = BPH_hair_volume_create_vertex_grid(clmd->sim_parms->voxel_cell_size, gmin, gmax);
+ cloth_continuum_fill_grid(grid, cloth);
+
+ BPH_hair_volume_get_texture_data(grid, vd);
+
+ BPH_hair_volume_free_vertex_grid(grid);
+
+ return true;
+}
diff --git a/source/blender/physics/intern/ConstrainedConjugateGradient.h b/source/blender/physics/intern/ConstrainedConjugateGradient.h
new file mode 100644
index 00000000000..2d4389f6766
--- /dev/null
+++ b/source/blender/physics/intern/ConstrainedConjugateGradient.h
@@ -0,0 +1,294 @@
+
+#ifndef EIGEN_CONSTRAINEDCG_H
+#define EIGEN_CONSTRAINEDCG_H
+
+#include <Eigen/Core>
+
+namespace Eigen {
+
+namespace internal {
+
+/** \internal Low-level conjugate gradient algorithm
+ * \param mat The matrix A
+ * \param rhs The right hand side vector b
+ * \param x On input and initial solution, on output the computed solution.
+ * \param precond A preconditioner being able to efficiently solve for an
+ * approximation of Ax=b (regardless of b)
+ * \param iters On input the max number of iteration, on output the number of performed iterations.
+ * \param tol_error On input the tolerance error, on output an estimation of the relative error.
+ */
+template<typename MatrixType, typename Rhs, typename Dest, typename FilterMatrixType, typename Preconditioner>
+EIGEN_DONT_INLINE
+void constrained_conjugate_gradient(const MatrixType& mat, const Rhs& rhs, Dest& x,
+ const FilterMatrixType &filter,
+ const Preconditioner& precond, int& iters,
+ typename Dest::RealScalar& tol_error)
+{
+ using std::sqrt;
+ using std::abs;
+ typedef typename Dest::RealScalar RealScalar;
+ typedef typename Dest::Scalar Scalar;
+ typedef Matrix<Scalar,Dynamic,1> VectorType;
+
+ RealScalar tol = tol_error;
+ int maxIters = iters;
+
+ int n = mat.cols();
+
+ VectorType residual = filter * (rhs - mat * x); //initial residual
+
+ RealScalar rhsNorm2 = (filter * rhs).squaredNorm();
+ if(rhsNorm2 == 0)
+ {
+ /* XXX TODO set constrained result here */
+ x.setZero();
+ iters = 0;
+ tol_error = 0;
+ return;
+ }
+ RealScalar threshold = tol*tol*rhsNorm2;
+ RealScalar residualNorm2 = residual.squaredNorm();
+ if (residualNorm2 < threshold)
+ {
+ iters = 0;
+ tol_error = sqrt(residualNorm2 / rhsNorm2);
+ return;
+ }
+
+ VectorType p(n);
+ p = filter * precond.solve(residual); //initial search direction
+
+ VectorType z(n), tmp(n);
+ RealScalar absNew = numext::real(residual.dot(p)); // the square of the absolute value of r scaled by invM
+ int i = 0;
+ while(i < maxIters)
+ {
+ tmp.noalias() = filter * (mat * p); // the bottleneck of the algorithm
+
+ Scalar alpha = absNew / p.dot(tmp); // the amount we travel on dir
+ x += alpha * p; // update solution
+ residual -= alpha * tmp; // update residue
+
+ residualNorm2 = residual.squaredNorm();
+ if(residualNorm2 < threshold)
+ break;
+
+ z = precond.solve(residual); // approximately solve for "A z = residual"
+
+ RealScalar absOld = absNew;
+ absNew = numext::real(residual.dot(z)); // update the absolute value of r
+ RealScalar beta = absNew / absOld; // calculate the Gram-Schmidt value used to create the new search direction
+ p = filter * (z + beta * p); // update search direction
+ i++;
+ }
+ tol_error = sqrt(residualNorm2 / rhsNorm2);
+ iters = i;
+}
+
+}
+
+#if 0 /* unused */
+template<typename MatrixType>
+struct MatrixFilter
+{
+ MatrixFilter() :
+ m_cmat(NULL)
+ {
+ }
+
+ MatrixFilter(const MatrixType &cmat) :
+ m_cmat(&cmat)
+ {
+ }
+
+ void setMatrix(const MatrixType &cmat) { m_cmat = &cmat; }
+
+ template <typename VectorType>
+ void apply(VectorType v) const
+ {
+ v = (*m_cmat) * v;
+ }
+
+protected:
+ const MatrixType *m_cmat;
+};
+#endif
+
+template< typename _MatrixType, int _UpLo=Lower,
+ typename _FilterMatrixType = _MatrixType,
+ typename _Preconditioner = DiagonalPreconditioner<typename _MatrixType::Scalar> >
+class ConstrainedConjugateGradient;
+
+namespace internal {
+
+template< typename _MatrixType, int _UpLo, typename _FilterMatrixType, typename _Preconditioner>
+struct traits<ConstrainedConjugateGradient<_MatrixType,_UpLo,_FilterMatrixType,_Preconditioner> >
+{
+ typedef _MatrixType MatrixType;
+ typedef _FilterMatrixType FilterMatrixType;
+ typedef _Preconditioner Preconditioner;
+};
+
+}
+
+/** \ingroup IterativeLinearSolvers_Module
+ * \brief A conjugate gradient solver for sparse self-adjoint problems with additional constraints
+ *
+ * This class allows to solve for A.x = b sparse linear problems using a conjugate gradient algorithm.
+ * The sparse matrix A must be selfadjoint. The vectors x and b can be either dense or sparse.
+ *
+ * \tparam _MatrixType the type of the sparse matrix A, can be a dense or a sparse matrix.
+ * \tparam _UpLo the triangular part that will be used for the computations. It can be Lower
+ * or Upper. Default is Lower.
+ * \tparam _Preconditioner the type of the preconditioner. Default is DiagonalPreconditioner
+ *
+ * The maximal number of iterations and tolerance value can be controlled via the setMaxIterations()
+ * and setTolerance() methods. The defaults are the size of the problem for the maximal number of iterations
+ * and NumTraits<Scalar>::epsilon() for the tolerance.
+ *
+ * This class can be used as the direct solver classes. Here is a typical usage example:
+ * \code
+ * int n = 10000;
+ * VectorXd x(n), b(n);
+ * SparseMatrix<double> A(n,n);
+ * // fill A and b
+ * ConjugateGradient<SparseMatrix<double> > cg;
+ * cg.compute(A);
+ * x = cg.solve(b);
+ * std::cout << "#iterations: " << cg.iterations() << std::endl;
+ * std::cout << "estimated error: " << cg.error() << std::endl;
+ * // update b, and solve again
+ * x = cg.solve(b);
+ * \endcode
+ *
+ * By default the iterations start with x=0 as an initial guess of the solution.
+ * One can control the start using the solveWithGuess() method. Here is a step by
+ * step execution example starting with a random guess and printing the evolution
+ * of the estimated error:
+ * * \code
+ * x = VectorXd::Random(n);
+ * cg.setMaxIterations(1);
+ * int i = 0;
+ * do {
+ * x = cg.solveWithGuess(b,x);
+ * std::cout << i << " : " << cg.error() << std::endl;
+ * ++i;
+ * } while (cg.info()!=Success && i<100);
+ * \endcode
+ * Note that such a step by step excution is slightly slower.
+ *
+ * \sa class SimplicialCholesky, DiagonalPreconditioner, IdentityPreconditioner
+ */
+template< typename _MatrixType, int _UpLo, typename _FilterMatrixType, typename _Preconditioner>
+class ConstrainedConjugateGradient : public IterativeSolverBase<ConstrainedConjugateGradient<_MatrixType,_UpLo,_FilterMatrixType,_Preconditioner> >
+{
+ typedef IterativeSolverBase<ConstrainedConjugateGradient> Base;
+ using Base::mp_matrix;
+ using Base::m_error;
+ using Base::m_iterations;
+ using Base::m_info;
+ using Base::m_isInitialized;
+public:
+ typedef _MatrixType MatrixType;
+ typedef typename MatrixType::Scalar Scalar;
+ typedef typename MatrixType::Index Index;
+ typedef typename MatrixType::RealScalar RealScalar;
+ typedef _FilterMatrixType FilterMatrixType;
+ typedef _Preconditioner Preconditioner;
+
+ enum {
+ UpLo = _UpLo
+ };
+
+public:
+
+ /** Default constructor. */
+ ConstrainedConjugateGradient() : Base() {}
+
+ /** Initialize the solver with matrix \a A for further \c Ax=b solving.
+ *
+ * This constructor is a shortcut for the default constructor followed
+ * by a call to compute().
+ *
+ * \warning this class stores a reference to the matrix A as well as some
+ * precomputed values that depend on it. Therefore, if \a A is changed
+ * this class becomes invalid. Call compute() to update it with the new
+ * matrix A, or modify a copy of A.
+ */
+ ConstrainedConjugateGradient(const MatrixType& A) : Base(A) {}
+
+ ~ConstrainedConjugateGradient() {}
+
+ FilterMatrixType &filter() { return m_filter; }
+ const FilterMatrixType &filter() const { return m_filter; }
+
+ /** \returns the solution x of \f$ A x = b \f$ using the current decomposition of A
+ * \a x0 as an initial solution.
+ *
+ * \sa compute()
+ */
+ template<typename Rhs,typename Guess>
+ inline const internal::solve_retval_with_guess<ConstrainedConjugateGradient, Rhs, Guess>
+ solveWithGuess(const MatrixBase<Rhs>& b, const Guess& x0) const
+ {
+ eigen_assert(m_isInitialized && "ConjugateGradient is not initialized.");
+ eigen_assert(Base::rows()==b.rows()
+ && "ConjugateGradient::solve(): invalid number of rows of the right hand side matrix b");
+ return internal::solve_retval_with_guess
+ <ConstrainedConjugateGradient, Rhs, Guess>(*this, b.derived(), x0);
+ }
+
+ /** \internal */
+ template<typename Rhs,typename Dest>
+ void _solveWithGuess(const Rhs& b, Dest& x) const
+ {
+ m_iterations = Base::maxIterations();
+ m_error = Base::m_tolerance;
+
+ for(int j=0; j<b.cols(); ++j)
+ {
+ m_iterations = Base::maxIterations();
+ m_error = Base::m_tolerance;
+
+ typename Dest::ColXpr xj(x,j);
+ internal::constrained_conjugate_gradient(mp_matrix->template selfadjointView<UpLo>(), b.col(j), xj, m_filter,
+ Base::m_preconditioner, m_iterations, m_error);
+ }
+
+ m_isInitialized = true;
+ m_info = m_error <= Base::m_tolerance ? Success : NoConvergence;
+ }
+
+ /** \internal */
+ template<typename Rhs,typename Dest>
+ void _solve(const Rhs& b, Dest& x) const
+ {
+ x.setOnes();
+ _solveWithGuess(b,x);
+ }
+
+protected:
+ FilterMatrixType m_filter;
+};
+
+
+namespace internal {
+
+template<typename _MatrixType, int _UpLo, typename _Filter, typename _Preconditioner, typename Rhs>
+struct solve_retval<ConstrainedConjugateGradient<_MatrixType,_UpLo,_Filter,_Preconditioner>, Rhs>
+ : solve_retval_base<ConstrainedConjugateGradient<_MatrixType,_UpLo,_Filter,_Preconditioner>, Rhs>
+{
+ typedef ConstrainedConjugateGradient<_MatrixType,_UpLo,_Filter,_Preconditioner> Dec;
+ EIGEN_MAKE_SOLVE_HELPERS(Dec,Rhs)
+
+ template<typename Dest> void evalTo(Dest& dst) const
+ {
+ dec()._solve(rhs(),dst);
+ }
+};
+
+} // end namespace internal
+
+} // end namespace Eigen
+
+#endif // EIGEN_CONSTRAINEDCG_H
diff --git a/source/blender/physics/intern/eigen_utils.h b/source/blender/physics/intern/eigen_utils.h
new file mode 100644
index 00000000000..e4a4f306aeb
--- /dev/null
+++ b/source/blender/physics/intern/eigen_utils.h
@@ -0,0 +1,230 @@
+/*
+ * ***** 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) Blender Foundation
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Lukas Toenne
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __EIGEN_UTILS_H__
+#define __EIGEN_UTILS_H__
+
+/** \file blender/physics/intern/eigen_utils.h
+ * \ingroup bph
+ */
+
+#ifdef __GNUC__
+# pragma GCC diagnostic push
+/* XXX suppress verbose warnings in eigen */
+# pragma GCC diagnostic ignored "-Wlogical-op"
+#endif
+
+#include <Eigen/Sparse>
+#include <Eigen/src/Core/util/DisableStupidWarnings.h>
+
+#ifdef __GNUC__
+# pragma GCC diagnostic pop
+#endif
+
+#include "BLI_utildefines.h"
+
+
+typedef float Scalar;
+
+/* slightly extended Eigen vector class
+ * with conversion to/from plain C float array
+ */
+class Vector3 : public Eigen::Vector3f {
+public:
+ typedef float *ctype;
+
+ Vector3()
+ {
+ }
+
+ Vector3(const ctype &v)
+ {
+ for (int k = 0; k < 3; ++k)
+ coeffRef(k) = v[k];
+ }
+
+ Vector3& operator = (const ctype &v)
+ {
+ for (int k = 0; k < 3; ++k)
+ coeffRef(k) = v[k];
+ return *this;
+ }
+
+ operator ctype()
+ {
+ return data();
+ }
+};
+
+/* slightly extended Eigen matrix class
+ * with conversion to/from plain C float array
+ */
+class Matrix3 : public Eigen::Matrix3f {
+public:
+ typedef float (*ctype)[3];
+
+ Matrix3()
+ {
+ }
+
+ Matrix3(const ctype &v)
+ {
+ for (int k = 0; k < 3; ++k)
+ for (int l = 0; l < 3; ++l)
+ coeffRef(l, k) = v[k][l];
+ }
+
+ Matrix3& operator = (const ctype &v)
+ {
+ for (int k = 0; k < 3; ++k)
+ for (int l = 0; l < 3; ++l)
+ coeffRef(l, k) = v[k][l];
+ return *this;
+ }
+
+ operator ctype()
+ {
+ return (ctype)data();
+ }
+};
+
+typedef Eigen::VectorXf lVector;
+
+/* Extension of dense Eigen vectors,
+ * providing 3-float block access for blenlib math functions
+ */
+class lVector3f : public Eigen::VectorXf {
+public:
+ typedef Eigen::VectorXf base_t;
+
+ lVector3f()
+ {
+ }
+
+ template <typename T>
+ lVector3f& operator = (T rhs)
+ {
+ base_t::operator=(rhs);
+ return *this;
+ }
+
+ float* v3(int vertex)
+ {
+ return &coeffRef(3 * vertex);
+ }
+
+ const float* v3(int vertex) const
+ {
+ return &coeffRef(3 * vertex);
+ }
+};
+
+typedef Eigen::Triplet<Scalar> Triplet;
+typedef std::vector<Triplet> TripletList;
+
+typedef Eigen::SparseMatrix<Scalar> lMatrix;
+
+/* Constructor type that provides more convenient handling of Eigen triplets
+ * for efficient construction of sparse 3x3 block matrices.
+ * This should be used for building lMatrix instead of writing to such lMatrix directly (which is very inefficient).
+ * After all elements have been defined using the set() method, the actual matrix can be filled using construct().
+ */
+struct lMatrix3fCtor {
+ lMatrix3fCtor()
+ {
+ }
+
+ void reset()
+ {
+ m_trips.clear();
+ }
+
+ void reserve(int numverts)
+ {
+ /* reserve for diagonal entries */
+ m_trips.reserve(numverts * 9);
+ }
+
+ void add(int i, int j, const Matrix3 &m)
+ {
+ i *= 3;
+ j *= 3;
+ for (int k = 0; k < 3; ++k)
+ for (int l = 0; l < 3; ++l)
+ m_trips.push_back(Triplet(i + k, j + l, m.coeff(l, k)));
+ }
+
+ void sub(int i, int j, const Matrix3 &m)
+ {
+ i *= 3;
+ j *= 3;
+ for (int k = 0; k < 3; ++k)
+ for (int l = 0; l < 3; ++l)
+ m_trips.push_back(Triplet(i + k, j + l, -m.coeff(l, k)));
+ }
+
+ inline void construct(lMatrix &m)
+ {
+ m.setFromTriplets(m_trips.begin(), m_trips.end());
+ m_trips.clear();
+ }
+
+private:
+ TripletList m_trips;
+};
+
+typedef Eigen::ConjugateGradient<lMatrix, Eigen::Lower, Eigen::DiagonalPreconditioner<Scalar> > ConjugateGradient;
+
+using Eigen::ComputationInfo;
+
+BLI_INLINE void print_lvector(const lVector3f &v)
+{
+ for (int i = 0; i < v.rows(); ++i) {
+ if (i > 0 && i % 3 == 0)
+ printf("\n");
+
+ printf("%f,\n", v[i]);
+ }
+}
+
+BLI_INLINE void print_lmatrix(const lMatrix &m)
+{
+ for (int j = 0; j < m.rows(); ++j) {
+ if (j > 0 && j % 3 == 0)
+ printf("\n");
+
+ for (int i = 0; i < m.cols(); ++i) {
+ if (i > 0 && i % 3 == 0)
+ printf(" ");
+
+ implicit_print_matrix_elem(m.coeff(j, i));
+ }
+ printf("\n");
+ }
+}
+
+#endif
diff --git a/source/blender/physics/intern/hair_volume.cpp b/source/blender/physics/intern/hair_volume.cpp
new file mode 100644
index 00000000000..d79cf7d8c31
--- /dev/null
+++ b/source/blender/physics/intern/hair_volume.cpp
@@ -0,0 +1,1154 @@
+/*
+ * ***** 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) Blender Foundation
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Janne Karhu, Lukas Toenne
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/physics/intern/hair_volume.cpp
+ * \ingroup bph
+ */
+
+#include "MEM_guardedalloc.h"
+
+extern "C" {
+#include "BLI_math.h"
+#include "BLI_utildefines.h"
+
+#include "DNA_texture_types.h"
+
+#include "BKE_effect.h"
+}
+
+#include "implicit.h"
+#include "eigen_utils.h"
+
+/* ================ Volumetric Hair Interaction ================
+ * adapted from
+ *
+ * Volumetric Methods for Simulation and Rendering of Hair
+ * (Petrovic, Henne, Anderson, Pixar Technical Memo #06-08, Pixar Animation Studios)
+ *
+ * as well as
+ *
+ * "Detail Preserving Continuum Simulation of Straight Hair"
+ * (McAdams, Selle 2009)
+ */
+
+/* Note about array indexing:
+ * Generally the arrays here are one-dimensional.
+ * The relation between 3D indices and the array offset is
+ * offset = x + res_x * y + res_x * res_y * z
+ */
+
+static float I[3][3] = {{1, 0, 0}, {0, 1, 0}, {0, 0, 1}};
+
+BLI_INLINE int floor_int(float value)
+{
+ return value > 0.0f ? (int)value : ((int)value) - 1;
+}
+
+BLI_INLINE float floor_mod(float value)
+{
+ return value - floorf(value);
+}
+
+BLI_INLINE int hair_grid_size(const int res[3])
+{
+ return res[0] * res[1] * res[2];
+}
+
+typedef struct HairGridVert {
+ int samples;
+ float velocity[3];
+ float density;
+
+ float velocity_smooth[3];
+} HairGridVert;
+
+typedef struct HairGrid {
+ HairGridVert *verts;
+ int res[3];
+ float gmin[3], gmax[3];
+ float cellsize, inv_cellsize;
+} HairGrid;
+
+#define HAIR_GRID_INDEX_AXIS(vec, res, gmin, scale, axis) ( min_ii( max_ii( (int)((vec[axis] - gmin[axis]) * scale), 0), res[axis]-2 ) )
+
+BLI_INLINE int hair_grid_offset(const float vec[3], const int res[3], const float gmin[3], float scale)
+{
+ int i, j, k;
+ i = HAIR_GRID_INDEX_AXIS(vec, res, gmin, scale, 0);
+ j = HAIR_GRID_INDEX_AXIS(vec, res, gmin, scale, 1);
+ k = HAIR_GRID_INDEX_AXIS(vec, res, gmin, scale, 2);
+ return i + (j + k*res[1])*res[0];
+}
+
+BLI_INLINE int hair_grid_interp_weights(const int res[3], const float gmin[3], float scale, const float vec[3], float uvw[3])
+{
+ int i, j, k, offset;
+
+ i = HAIR_GRID_INDEX_AXIS(vec, res, gmin, scale, 0);
+ j = HAIR_GRID_INDEX_AXIS(vec, res, gmin, scale, 1);
+ k = HAIR_GRID_INDEX_AXIS(vec, res, gmin, scale, 2);
+ offset = i + (j + k*res[1])*res[0];
+
+ uvw[0] = (vec[0] - gmin[0]) * scale - (float)i;
+ uvw[1] = (vec[1] - gmin[1]) * scale - (float)j;
+ uvw[2] = (vec[2] - gmin[2]) * scale - (float)k;
+
+// BLI_assert(0.0f <= uvw[0] && uvw[0] <= 1.0001f);
+// BLI_assert(0.0f <= uvw[1] && uvw[1] <= 1.0001f);
+// BLI_assert(0.0f <= uvw[2] && uvw[2] <= 1.0001f);
+
+ return offset;
+}
+
+BLI_INLINE void hair_grid_interpolate(const HairGridVert *grid, const int res[3], const float gmin[3], float scale, const float vec[3],
+ float *density, float velocity[3], float vel_smooth[3], float density_gradient[3], float velocity_gradient[3][3])
+{
+ HairGridVert data[8];
+ float uvw[3], muvw[3];
+ int res2 = res[1] * res[0];
+ int offset;
+
+ offset = hair_grid_interp_weights(res, gmin, scale, vec, uvw);
+ muvw[0] = 1.0f - uvw[0];
+ muvw[1] = 1.0f - uvw[1];
+ muvw[2] = 1.0f - uvw[2];
+
+ data[0] = grid[offset ];
+ data[1] = grid[offset +1];
+ data[2] = grid[offset +res[0] ];
+ data[3] = grid[offset +res[0]+1];
+ data[4] = grid[offset+res2 ];
+ data[5] = grid[offset+res2 +1];
+ data[6] = grid[offset+res2+res[0] ];
+ data[7] = grid[offset+res2+res[0]+1];
+
+ if (density) {
+ *density = muvw[2]*( muvw[1]*( muvw[0]*data[0].density + uvw[0]*data[1].density ) +
+ uvw[1]*( muvw[0]*data[2].density + uvw[0]*data[3].density ) ) +
+ uvw[2]*( muvw[1]*( muvw[0]*data[4].density + uvw[0]*data[5].density ) +
+ uvw[1]*( muvw[0]*data[6].density + uvw[0]*data[7].density ) );
+ }
+
+ if (velocity) {
+ int k;
+ for (k = 0; k < 3; ++k) {
+ velocity[k] = muvw[2]*( muvw[1]*( muvw[0]*data[0].velocity[k] + uvw[0]*data[1].velocity[k] ) +
+ uvw[1]*( muvw[0]*data[2].velocity[k] + uvw[0]*data[3].velocity[k] ) ) +
+ uvw[2]*( muvw[1]*( muvw[0]*data[4].velocity[k] + uvw[0]*data[5].velocity[k] ) +
+ uvw[1]*( muvw[0]*data[6].velocity[k] + uvw[0]*data[7].velocity[k] ) );
+ }
+ }
+
+ if (vel_smooth) {
+ int k;
+ for (k = 0; k < 3; ++k) {
+ vel_smooth[k] = muvw[2]*( muvw[1]*( muvw[0]*data[0].velocity_smooth[k] + uvw[0]*data[1].velocity_smooth[k] ) +
+ uvw[1]*( muvw[0]*data[2].velocity_smooth[k] + uvw[0]*data[3].velocity_smooth[k] ) ) +
+ uvw[2]*( muvw[1]*( muvw[0]*data[4].velocity_smooth[k] + uvw[0]*data[5].velocity_smooth[k] ) +
+ uvw[1]*( muvw[0]*data[6].velocity_smooth[k] + uvw[0]*data[7].velocity_smooth[k] ) );
+ }
+ }
+
+ if (density_gradient) {
+ density_gradient[0] = muvw[1] * muvw[2] * ( data[0].density - data[1].density ) +
+ uvw[1] * muvw[2] * ( data[2].density - data[3].density ) +
+ muvw[1] * uvw[2] * ( data[4].density - data[5].density ) +
+ uvw[1] * uvw[2] * ( data[6].density - data[7].density );
+
+ density_gradient[1] = muvw[2] * muvw[0] * ( data[0].density - data[2].density ) +
+ uvw[2] * muvw[0] * ( data[4].density - data[6].density ) +
+ muvw[2] * uvw[0] * ( data[1].density - data[3].density ) +
+ uvw[2] * uvw[0] * ( data[5].density - data[7].density );
+
+ density_gradient[2] = muvw[2] * muvw[0] * ( data[0].density - data[4].density ) +
+ uvw[2] * muvw[0] * ( data[1].density - data[5].density ) +
+ muvw[2] * uvw[0] * ( data[2].density - data[6].density ) +
+ uvw[2] * uvw[0] * ( data[3].density - data[7].density );
+ }
+
+ if (velocity_gradient) {
+ /* XXX TODO */
+ zero_m3(velocity_gradient);
+ }
+}
+
+void BPH_hair_volume_vertex_grid_forces(HairGrid *grid, const float x[3], const float v[3],
+ float smoothfac, float pressurefac, float minpressure,
+ float f[3], float dfdx[3][3], float dfdv[3][3])
+{
+ float gdensity, gvelocity[3], ggrad[3], gvelgrad[3][3], gradlen;
+
+ hair_grid_interpolate(grid->verts, grid->res, grid->gmin, grid->inv_cellsize, x, &gdensity, gvelocity, NULL, ggrad, gvelgrad);
+
+ zero_v3(f);
+ sub_v3_v3(gvelocity, v);
+ mul_v3_v3fl(f, gvelocity, smoothfac);
+
+ gradlen = normalize_v3(ggrad) - minpressure;
+ if (gradlen > 0.0f) {
+ mul_v3_fl(ggrad, gradlen);
+ madd_v3_v3fl(f, ggrad, pressurefac);
+ }
+
+ zero_m3(dfdx);
+
+ sub_m3_m3m3(dfdv, gvelgrad, I);
+ mul_m3_fl(dfdv, smoothfac);
+}
+
+void BPH_hair_volume_grid_interpolate(HairGrid *grid, const float x[3],
+ float *density, float velocity[3], float velocity_smooth[3], float density_gradient[3], float velocity_gradient[3][3])
+{
+ hair_grid_interpolate(grid->verts, grid->res, grid->gmin, grid->inv_cellsize, x, density, velocity, velocity_smooth, density_gradient, velocity_gradient);
+}
+
+void BPH_hair_volume_grid_velocity(HairGrid *grid, const float x[3], const float v[3],
+ float fluid_factor,
+ float r_v[3])
+{
+ float gdensity, gvelocity[3], gvel_smooth[3], ggrad[3], gvelgrad[3][3];
+ float v_pic[3], v_flip[3];
+
+ hair_grid_interpolate(grid->verts, grid->res, grid->gmin, grid->inv_cellsize, x, &gdensity, gvelocity, gvel_smooth, ggrad, gvelgrad);
+
+ /* velocity according to PIC method (Particle-in-Cell) */
+ copy_v3_v3(v_pic, gvel_smooth);
+
+ /* velocity according to FLIP method (Fluid-Implicit-Particle) */
+ sub_v3_v3v3(v_flip, gvel_smooth, gvelocity);
+ add_v3_v3(v_flip, v);
+
+ interp_v3_v3v3(r_v, v_pic, v_flip, fluid_factor);
+}
+
+void BPH_hair_volume_grid_clear(HairGrid *grid)
+{
+ const int size = hair_grid_size(grid->res);
+ int i;
+ for (i = 0; i < size; ++i) {
+ zero_v3(grid->verts[i].velocity);
+ zero_v3(grid->verts[i].velocity_smooth);
+ grid->verts[i].density = 0.0f;
+ grid->verts[i].samples = 0;
+ }
+}
+
+BLI_INLINE bool hair_grid_point_valid(const float vec[3], float gmin[3], float gmax[3])
+{
+ return !(vec[0] < gmin[0] || vec[1] < gmin[1] || vec[2] < gmin[2] ||
+ vec[0] > gmax[0] || vec[1] > gmax[1] || vec[2] > gmax[2]);
+}
+
+BLI_INLINE float dist_tent_v3f3(const float a[3], float x, float y, float z)
+{
+ float w = (1.0f - fabsf(a[0] - x)) * (1.0f - fabsf(a[1] - y)) * (1.0f - fabsf(a[2] - z));
+ return w;
+}
+
+BLI_INLINE float weights_sum(const float weights[8])
+{
+ float totweight = 0.0f;
+ int i;
+ for (i = 0; i < 8; ++i)
+ totweight += weights[i];
+ return totweight;
+}
+
+/* returns the grid array offset as well to avoid redundant calculation */
+BLI_INLINE int hair_grid_weights(const int res[3], const float gmin[3], float scale, const float vec[3], float weights[8])
+{
+ int i, j, k, offset;
+ float uvw[3];
+
+ i = HAIR_GRID_INDEX_AXIS(vec, res, gmin, scale, 0);
+ j = HAIR_GRID_INDEX_AXIS(vec, res, gmin, scale, 1);
+ k = HAIR_GRID_INDEX_AXIS(vec, res, gmin, scale, 2);
+ offset = i + (j + k*res[1])*res[0];
+
+ uvw[0] = (vec[0] - gmin[0]) * scale;
+ uvw[1] = (vec[1] - gmin[1]) * scale;
+ uvw[2] = (vec[2] - gmin[2]) * scale;
+
+ weights[0] = dist_tent_v3f3(uvw, (float)i , (float)j , (float)k );
+ weights[1] = dist_tent_v3f3(uvw, (float)(i+1), (float)j , (float)k );
+ weights[2] = dist_tent_v3f3(uvw, (float)i , (float)(j+1), (float)k );
+ weights[3] = dist_tent_v3f3(uvw, (float)(i+1), (float)(j+1), (float)k );
+ weights[4] = dist_tent_v3f3(uvw, (float)i , (float)j , (float)(k+1));
+ weights[5] = dist_tent_v3f3(uvw, (float)(i+1), (float)j , (float)(k+1));
+ weights[6] = dist_tent_v3f3(uvw, (float)i , (float)(j+1), (float)(k+1));
+ weights[7] = dist_tent_v3f3(uvw, (float)(i+1), (float)(j+1), (float)(k+1));
+
+// BLI_assert(fabsf(weights_sum(weights) - 1.0f) < 0.0001f);
+
+ return offset;
+}
+
+BLI_INLINE void grid_to_world(HairGrid *grid, float vecw[3], const float vec[3])
+{
+ copy_v3_v3(vecw, vec);
+ mul_v3_fl(vecw, grid->cellsize);
+ add_v3_v3(vecw, grid->gmin);
+}
+
+void BPH_hair_volume_add_vertex(HairGrid *grid, const float x[3], const float v[3])
+{
+ const int res[3] = { grid->res[0], grid->res[1], grid->res[2] };
+ float weights[8];
+ int di, dj, dk;
+ int offset;
+
+ if (!hair_grid_point_valid(x, grid->gmin, grid->gmax))
+ return;
+
+ offset = hair_grid_weights(res, grid->gmin, grid->inv_cellsize, x, weights);
+
+ for (di = 0; di < 2; ++di) {
+ for (dj = 0; dj < 2; ++dj) {
+ for (dk = 0; dk < 2; ++dk) {
+ int voffset = offset + di + (dj + dk*res[1])*res[0];
+ int iw = di + dj*2 + dk*4;
+
+ grid->verts[voffset].density += weights[iw];
+ madd_v3_v3fl(grid->verts[voffset].velocity, v, weights[iw]);
+ }
+ }
+ }
+}
+
+#if 0
+BLI_INLINE void hair_volume_eval_grid_vertex(HairGridVert *vert, const float loc[3], float radius, float dist_scale,
+ const float x2[3], const float v2[3], const float x3[3], const float v3[3])
+{
+ float closest[3], lambda, dist, weight;
+
+ lambda = closest_to_line_v3(closest, loc, x2, x3);
+ dist = len_v3v3(closest, loc);
+
+ weight = (radius - dist) * dist_scale;
+
+ if (weight > 0.0f) {
+ float vel[3];
+
+ interp_v3_v3v3(vel, v2, v3, lambda);
+ madd_v3_v3fl(vert->velocity, vel, weight);
+ vert->density += weight;
+ vert->samples += 1;
+ }
+}
+
+BLI_INLINE int major_axis_v3(const float v[3])
+{
+ const float a = fabsf(v[0]);
+ const float b = fabsf(v[1]);
+ const float c = fabsf(v[2]);
+ return a > b ? (a > c ? 0 : 2) : (b > c ? 1 : 2);
+}
+
+BLI_INLINE void hair_volume_add_segment_2D(HairGrid *grid,
+ const float UNUSED(x1[3]), const float UNUSED(v1[3]), const float x2[3], const float v2[3],
+ const float x3[3], const float v3[3], const float UNUSED(x4[3]), const float UNUSED(v4[3]),
+ const float UNUSED(dir1[3]), const float dir2[3], const float UNUSED(dir3[3]),
+ int resj, int resk, int jmin, int jmax, int kmin, int kmax,
+ HairGridVert *vert, int stride_j, int stride_k, const float loc[3], int axis_j, int axis_k,
+ int debug_i)
+{
+ const float radius = 1.5f;
+ const float dist_scale = grid->inv_cellsize;
+
+ int j, k;
+
+ /* boundary checks to be safe */
+ CLAMP_MIN(jmin, 0);
+ CLAMP_MAX(jmax, resj-1);
+ CLAMP_MIN(kmin, 0);
+ CLAMP_MAX(kmax, resk-1);
+
+ HairGridVert *vert_j = vert + jmin * stride_j;
+ float loc_j[3] = { loc[0], loc[1], loc[2] };
+ loc_j[axis_j] += (float)jmin;
+ for (j = jmin; j <= jmax; ++j, vert_j += stride_j, loc_j[axis_j] += 1.0f) {
+
+ HairGridVert *vert_k = vert_j + kmin * stride_k;
+ float loc_k[3] = { loc_j[0], loc_j[1], loc_j[2] };
+ loc_k[axis_k] += (float)kmin;
+ for (k = kmin; k <= kmax; ++k, vert_k += stride_k, loc_k[axis_k] += 1.0f) {
+
+ hair_volume_eval_grid_vertex(vert_k, loc_k, radius, dist_scale, x2, v2, x3, v3);
+
+#if 0
+ {
+ float wloc[3], x2w[3], x3w[3];
+ grid_to_world(grid, wloc, loc_k);
+ grid_to_world(grid, x2w, x2);
+ grid_to_world(grid, x3w, x3);
+
+ if (vert_k->samples > 0)
+ BKE_sim_debug_data_add_circle(wloc, 0.01f, 1.0, 1.0, 0.3, "grid", 2525, debug_i, j, k);
+
+ if (grid->debug_value) {
+ BKE_sim_debug_data_add_dot(wloc, 1, 0, 0, "grid", 93, debug_i, j, k);
+ BKE_sim_debug_data_add_dot(x2w, 0.1, 0.1, 0.7, "grid", 649, debug_i, j, k);
+ BKE_sim_debug_data_add_line(wloc, x2w, 0.3, 0.8, 0.3, "grid", 253, debug_i, j, k);
+ BKE_sim_debug_data_add_line(wloc, x3w, 0.8, 0.3, 0.3, "grid", 254, debug_i, j, k);
+// BKE_sim_debug_data_add_circle(x2w, len_v3v3(wloc, x2w), 0.2, 0.7, 0.2, "grid", 255, i, j, k);
+ }
+ }
+#endif
+ }
+ }
+}
+
+/* Uses a variation of Bresenham's algorithm for rasterizing a 3D grid with a line segment.
+ *
+ * The radius of influence around a segment is assumed to be at most 2*cellsize,
+ * i.e. only cells containing the segment and their direct neighbors are examined.
+ *
+ *
+ */
+void BPH_hair_volume_add_segment(HairGrid *grid,
+ const float x1[3], const float v1[3], const float x2[3], const float v2[3],
+ const float x3[3], const float v3[3], const float x4[3], const float v4[3],
+ const float dir1[3], const float dir2[3], const float dir3[3])
+{
+ const int res[3] = { grid->res[0], grid->res[1], grid->res[2] };
+
+ /* find the primary direction from the major axis of the direction vector */
+ const int axis0 = major_axis_v3(dir2);
+ const int axis1 = (axis0 + 1) % 3;
+ const int axis2 = (axis0 + 2) % 3;
+
+ /* vertex buffer offset factors along cardinal axes */
+ const int strides[3] = { 1, res[0], res[0] * res[1] };
+ const int stride0 = strides[axis0];
+ const int stride1 = strides[axis1];
+ const int stride2 = strides[axis2];
+
+ /* increment of secondary directions per step in the primary direction
+ * note: we always go in the positive direction along axis0, so the sign can be inverted
+ */
+ const float inc1 = dir2[axis1] / dir2[axis0];
+ const float inc2 = dir2[axis2] / dir2[axis0];
+
+ /* start/end points, so increment along axis0 is always positive */
+ const float *start = x2[axis0] < x3[axis0] ? x2 : x3;
+ const float *end = x2[axis0] < x3[axis0] ? x3 : x2;
+ const float start0 = start[axis0], start1 = start[axis1], start2 = start[axis2];
+ const float end0 = end[axis0];
+
+ /* range along primary direction */
+ const int imin = max_ii(floor_int(start[axis0]) - 1, 0);
+ const int imax = min_ii(floor_int(end[axis0]) + 2, res[axis0]-1);
+
+ float h = 0.0f;
+ HairGridVert *vert0;
+ float loc0[3];
+ int j0, k0, j0_prev, k0_prev;
+ int i;
+
+ for (i = imin; i <= imax; ++i) {
+ float shift1, shift2; /* fraction of a full cell shift [0.0, 1.0) */
+ int jmin, jmax, kmin, kmax;
+
+ h = CLAMPIS((float)i, start0, end0);
+
+ shift1 = start1 + (h - start0) * inc1;
+ shift2 = start2 + (h - start0) * inc2;
+
+ j0_prev = j0;
+ j0 = floor_int(shift1);
+
+ k0_prev = k0;
+ k0 = floor_int(shift2);
+
+ if (i > imin) {
+ jmin = min_ii(j0, j0_prev);
+ jmax = max_ii(j0, j0_prev);
+ kmin = min_ii(k0, k0_prev);
+ kmax = max_ii(k0, k0_prev);
+ }
+ else {
+ jmin = jmax = j0;
+ kmin = kmax = k0;
+ }
+
+ vert0 = grid->verts + i * stride0;
+ loc0[axis0] = (float)i;
+ loc0[axis1] = 0.0f;
+ loc0[axis2] = 0.0f;
+
+ hair_volume_add_segment_2D(grid, x1, v1, x2, v2, x3, v3, x4, v4, dir1, dir2, dir3,
+ res[axis1], res[axis2], jmin-1, jmax+2, kmin-1, kmax+2,
+ vert0, stride1, stride2, loc0, axis1, axis2,
+ i);
+ }
+}
+#else
+BLI_INLINE void hair_volume_eval_grid_vertex_sample(HairGridVert *vert, const float loc[3], float radius, float dist_scale,
+ const float x[3], const float v[3])
+{
+ float dist, weight;
+
+ dist = len_v3v3(x, loc);
+
+ weight = (radius - dist) * dist_scale;
+
+ if (weight > 0.0f) {
+ madd_v3_v3fl(vert->velocity, v, weight);
+ vert->density += weight;
+ vert->samples += 1;
+ }
+}
+
+/* XXX simplified test implementation using a series of discrete sample along the segment,
+ * instead of finding the closest point for all affected grid vertices.
+ */
+void BPH_hair_volume_add_segment(HairGrid *grid,
+ const float UNUSED(x1[3]), const float UNUSED(v1[3]), const float x2[3], const float v2[3],
+ const float x3[3], const float v3[3], const float UNUSED(x4[3]), const float UNUSED(v4[3]),
+ const float UNUSED(dir1[3]), const float UNUSED(dir2[3]), const float UNUSED(dir3[3]))
+{
+ const float radius = 1.5f;
+ const float dist_scale = grid->inv_cellsize;
+
+ const int res[3] = { grid->res[0], grid->res[1], grid->res[2] };
+ const int stride[3] = { 1, res[0], res[0] * res[1] };
+ const int num_samples = 10;
+
+ int s;
+
+ for (s = 0; s < num_samples; ++s) {
+ float x[3], v[3];
+ int i, j, k;
+
+ float f = (float)s / (float)(num_samples-1);
+ interp_v3_v3v3(x, x2, x3, f);
+ interp_v3_v3v3(v, v2, v3, f);
+
+ int imin = max_ii(floor_int(x[0]) - 2, 0);
+ int imax = min_ii(floor_int(x[0]) + 2, res[0]-1);
+ int jmin = max_ii(floor_int(x[1]) - 2, 0);
+ int jmax = min_ii(floor_int(x[1]) + 2, res[1]-1);
+ int kmin = max_ii(floor_int(x[2]) - 2, 0);
+ int kmax = min_ii(floor_int(x[2]) + 2, res[2]-1);
+
+ for (k = kmin; k <= kmax; ++k) {
+ for (j = jmin; j <= jmax; ++j) {
+ for (i = imin; i <= imax; ++i) {
+ float loc[3] = { (float)i, (float)j, (float)k };
+ HairGridVert *vert = grid->verts + i * stride[0] + j * stride[1] + k * stride[2];
+
+ hair_volume_eval_grid_vertex_sample(vert, loc, radius, dist_scale, x, v);
+ }
+ }
+ }
+ }
+}
+#endif
+
+void BPH_hair_volume_normalize_vertex_grid(HairGrid *grid)
+{
+ int i, size = hair_grid_size(grid->res);
+ /* divide velocity with density */
+ for (i = 0; i < size; i++) {
+ float density = grid->verts[i].density;
+ if (density > 0.0f)
+ mul_v3_fl(grid->verts[i].velocity, 1.0f/density);
+ }
+}
+
+static const float density_threshold = 0.001f; /* cells with density below this are considered empty */
+
+/* Contribution of target density pressure to the laplacian in the pressure poisson equation.
+ * This is based on the model found in
+ * "Two-way Coupled SPH and Particle Level Set Fluid Simulation" (Losasso et al., 2008)
+ */
+BLI_INLINE float hair_volume_density_divergence(float density, float target_density, float strength)
+{
+ if (density > density_threshold && density > target_density)
+ return strength * logf(target_density / density);
+ else
+ return 0.0f;
+}
+
+bool BPH_hair_volume_solve_divergence(HairGrid *grid, float /*dt*/, float target_density, float target_strength)
+{
+ const float flowfac = grid->cellsize;
+ const float inv_flowfac = 1.0f / grid->cellsize;
+
+ /*const int num_cells = hair_grid_size(grid->res);*/
+ const int res[3] = { grid->res[0], grid->res[1], grid->res[2] };
+ const int resA[3] = { grid->res[0] + 2, grid->res[1] + 2, grid->res[2] + 2 };
+
+ const int stride0 = 1;
+ const int stride1 = grid->res[0];
+ const int stride2 = grid->res[1] * grid->res[0];
+ const int strideA0 = 1;
+ const int strideA1 = grid->res[0] + 2;
+ const int strideA2 = (grid->res[1] + 2) * (grid->res[0] + 2);
+
+ const int num_cells = res[0] * res[1] * res[2];
+ const int num_cellsA = (res[0] + 2) * (res[1] + 2) * (res[2] + 2);
+
+ HairGridVert *vert_start = grid->verts - (stride0 + stride1 + stride2);
+ HairGridVert *vert;
+ int i, j, k;
+
+#define MARGIN_i0 (i < 1)
+#define MARGIN_j0 (j < 1)
+#define MARGIN_k0 (k < 1)
+#define MARGIN_i1 (i >= resA[0]-1)
+#define MARGIN_j1 (j >= resA[1]-1)
+#define MARGIN_k1 (k >= resA[2]-1)
+
+#define NEIGHBOR_MARGIN_i0 (i < 2)
+#define NEIGHBOR_MARGIN_j0 (j < 2)
+#define NEIGHBOR_MARGIN_k0 (k < 2)
+#define NEIGHBOR_MARGIN_i1 (i >= resA[0]-2)
+#define NEIGHBOR_MARGIN_j1 (j >= resA[1]-2)
+#define NEIGHBOR_MARGIN_k1 (k >= resA[2]-2)
+
+ BLI_assert(num_cells >= 1);
+
+ /* Calculate divergence */
+ lVector B(num_cellsA);
+ for (k = 0; k < resA[2]; ++k) {
+ for (j = 0; j < resA[1]; ++j) {
+ for (i = 0; i < resA[0]; ++i) {
+ int u = i * strideA0 + j * strideA1 + k * strideA2;
+ bool is_margin = MARGIN_i0 || MARGIN_i1 || MARGIN_j0 || MARGIN_j1 || MARGIN_k0 || MARGIN_k1;
+
+ if (is_margin) {
+ B[u] = 0.0f;
+ continue;
+ }
+
+ vert = vert_start + i * stride0 + j * stride1 + k * stride2;
+
+ const float *v0 = vert->velocity;
+ float dx = 0.0f, dy = 0.0f, dz = 0.0f;
+ if (!NEIGHBOR_MARGIN_i0)
+ dx += v0[0] - (vert - stride0)->velocity[0];
+ if (!NEIGHBOR_MARGIN_i1)
+ dx += (vert + stride0)->velocity[0] - v0[0];
+ if (!NEIGHBOR_MARGIN_j0)
+ dy += v0[1] - (vert - stride1)->velocity[1];
+ if (!NEIGHBOR_MARGIN_j1)
+ dy += (vert + stride1)->velocity[1] - v0[1];
+ if (!NEIGHBOR_MARGIN_k0)
+ dz += v0[2] - (vert - stride2)->velocity[2];
+ if (!NEIGHBOR_MARGIN_k1)
+ dz += (vert + stride2)->velocity[2] - v0[2];
+
+ float divergence = -0.5f * flowfac * (dx + dy + dz);
+
+ /* adjustment term for target density */
+ float target = hair_volume_density_divergence(vert->density, target_density, target_strength);
+
+ /* B vector contains the finite difference approximation of the velocity divergence.
+ * Note: according to the discretized Navier-Stokes equation the rhs vector
+ * and resulting pressure gradient should be multiplied by the (inverse) density;
+ * however, this is already included in the weighting of hair velocities on the grid!
+ */
+ B[u] = divergence - target;
+
+#if 0
+ {
+ float wloc[3], loc[3];
+ float col0[3] = {0.0, 0.0, 0.0};
+ float colp[3] = {0.0, 1.0, 1.0};
+ float coln[3] = {1.0, 0.0, 1.0};
+ float col[3];
+ float fac;
+
+ loc[0] = (float)(i - 1);
+ loc[1] = (float)(j - 1);
+ loc[2] = (float)(k - 1);
+ grid_to_world(grid, wloc, loc);
+
+ if (divergence > 0.0f) {
+ fac = CLAMPIS(divergence * target_strength, 0.0, 1.0);
+ interp_v3_v3v3(col, col0, colp, fac);
+ }
+ else {
+ fac = CLAMPIS(-divergence * target_strength, 0.0, 1.0);
+ interp_v3_v3v3(col, col0, coln, fac);
+ }
+ if (fac > 0.05f)
+ BKE_sim_debug_data_add_circle(grid->debug_data, wloc, 0.01f, col[0], col[1], col[2], "grid", 5522, i, j, k);
+ }
+#endif
+ }
+ }
+ }
+
+ /* Main Poisson equation system:
+ * This is derived from the discretezation of the Poisson equation
+ * div(grad(p)) = div(v)
+ *
+ * The finite difference approximation yields the linear equation system described here:
+ * http://en.wikipedia.org/wiki/Discrete_Poisson_equation
+ */
+ lMatrix A(num_cellsA, num_cellsA);
+ /* Reserve space for the base equation system (without boundary conditions).
+ * Each column contains a factor 6 on the diagonal
+ * and up to 6 factors -1 on other places.
+ */
+ A.reserve(Eigen::VectorXi::Constant(num_cellsA, 7));
+
+ for (k = 0; k < resA[2]; ++k) {
+ for (j = 0; j < resA[1]; ++j) {
+ for (i = 0; i < resA[0]; ++i) {
+ int u = i * strideA0 + j * strideA1 + k * strideA2;
+ bool is_margin = MARGIN_i0 || MARGIN_i1 || MARGIN_j0 || MARGIN_j1 || MARGIN_k0 || MARGIN_k1;
+
+ vert = vert_start + i * stride0 + j * stride1 + k * stride2;
+ if (!is_margin && vert->density > density_threshold) {
+ int neighbors_lo = 0;
+ int neighbors_hi = 0;
+ int non_solid_neighbors = 0;
+ int neighbor_lo_index[3];
+ int neighbor_hi_index[3];
+ int n;
+
+ /* check for upper bounds in advance
+ * to get the correct number of neighbors,
+ * needed for the diagonal element
+ */
+ if (!NEIGHBOR_MARGIN_k0 && (vert - stride2)->density > density_threshold)
+ neighbor_lo_index[neighbors_lo++] = u - strideA2;
+ if (!NEIGHBOR_MARGIN_j0 && (vert - stride1)->density > density_threshold)
+ neighbor_lo_index[neighbors_lo++] = u - strideA1;
+ if (!NEIGHBOR_MARGIN_i0 && (vert - stride0)->density > density_threshold)
+ neighbor_lo_index[neighbors_lo++] = u - strideA0;
+ if (!NEIGHBOR_MARGIN_i1 && (vert + stride0)->density > density_threshold)
+ neighbor_hi_index[neighbors_hi++] = u + strideA0;
+ if (!NEIGHBOR_MARGIN_j1 && (vert + stride1)->density > density_threshold)
+ neighbor_hi_index[neighbors_hi++] = u + strideA1;
+ if (!NEIGHBOR_MARGIN_k1 && (vert + stride2)->density > density_threshold)
+ neighbor_hi_index[neighbors_hi++] = u + strideA2;
+
+ /*int liquid_neighbors = neighbors_lo + neighbors_hi;*/
+ non_solid_neighbors = 6;
+
+ for (n = 0; n < neighbors_lo; ++n)
+ A.insert(neighbor_lo_index[n], u) = -1.0f;
+ A.insert(u, u) = (float)non_solid_neighbors;
+ for (n = 0; n < neighbors_hi; ++n)
+ A.insert(neighbor_hi_index[n], u) = -1.0f;
+ }
+ else {
+ A.insert(u, u) = 1.0f;
+ }
+ }
+ }
+ }
+
+ ConjugateGradient cg;
+ cg.setMaxIterations(100);
+ cg.setTolerance(0.01f);
+
+ cg.compute(A);
+
+ lVector p = cg.solve(B);
+
+ if (cg.info() == Eigen::Success) {
+ /* Calculate velocity = grad(p) */
+ for (k = 0; k < resA[2]; ++k) {
+ for (j = 0; j < resA[1]; ++j) {
+ for (i = 0; i < resA[0]; ++i) {
+ int u = i * strideA0 + j * strideA1 + k * strideA2;
+ bool is_margin = MARGIN_i0 || MARGIN_i1 || MARGIN_j0 || MARGIN_j1 || MARGIN_k0 || MARGIN_k1;
+ if (is_margin)
+ continue;
+
+ vert = vert_start + i * stride0 + j * stride1 + k * stride2;
+ if (vert->density > density_threshold) {
+ float p_left = p[u - strideA0];
+ float p_right = p[u + strideA0];
+ float p_down = p[u - strideA1];
+ float p_up = p[u + strideA1];
+ float p_bottom = p[u - strideA2];
+ float p_top = p[u + strideA2];
+
+ /* finite difference estimate of pressure gradient */
+ float dvel[3];
+ dvel[0] = p_right - p_left;
+ dvel[1] = p_up - p_down;
+ dvel[2] = p_top - p_bottom;
+ mul_v3_fl(dvel, -0.5f * inv_flowfac);
+
+ /* pressure gradient describes velocity delta */
+ add_v3_v3v3(vert->velocity_smooth, vert->velocity, dvel);
+ }
+ else {
+ zero_v3(vert->velocity_smooth);
+ }
+ }
+ }
+ }
+
+#if 0
+ {
+ int axis = 0;
+ float offset = 0.0f;
+
+ int slice = (offset - grid->gmin[axis]) / grid->cellsize;
+
+ for (k = 0; k < resA[2]; ++k) {
+ for (j = 0; j < resA[1]; ++j) {
+ for (i = 0; i < resA[0]; ++i) {
+ int u = i * strideA0 + j * strideA1 + k * strideA2;
+ bool is_margin = MARGIN_i0 || MARGIN_i1 || MARGIN_j0 || MARGIN_j1 || MARGIN_k0 || MARGIN_k1;
+ if (i != slice)
+ continue;
+
+ vert = vert_start + i * stride0 + j * stride1 + k * stride2;
+
+ float wloc[3], loc[3];
+ float col0[3] = {0.0, 0.0, 0.0};
+ float colp[3] = {0.0, 1.0, 1.0};
+ float coln[3] = {1.0, 0.0, 1.0};
+ float col[3];
+ float fac;
+
+ loc[0] = (float)(i - 1);
+ loc[1] = (float)(j - 1);
+ loc[2] = (float)(k - 1);
+ grid_to_world(grid, wloc, loc);
+
+ float pressure = p[u];
+ if (pressure > 0.0f) {
+ fac = CLAMPIS(pressure * grid->debug1, 0.0, 1.0);
+ interp_v3_v3v3(col, col0, colp, fac);
+ }
+ else {
+ fac = CLAMPIS(-pressure * grid->debug1, 0.0, 1.0);
+ interp_v3_v3v3(col, col0, coln, fac);
+ }
+ if (fac > 0.05f)
+ BKE_sim_debug_data_add_circle(grid->debug_data, wloc, 0.01f, col[0], col[1], col[2], "grid", 5533, i, j, k);
+
+ if (!is_margin) {
+ float dvel[3];
+ sub_v3_v3v3(dvel, vert->velocity_smooth, vert->velocity);
+// BKE_sim_debug_data_add_vector(grid->debug_data, wloc, dvel, 1, 1, 1, "grid", 5566, i, j, k);
+ }
+
+ if (!is_margin) {
+ float d = CLAMPIS(vert->density * grid->debug2, 0.0f, 1.0f);
+ float col0[3] = {0.3, 0.3, 0.3};
+ float colp[3] = {0.0, 0.0, 1.0};
+ float col[3];
+
+ interp_v3_v3v3(col, col0, colp, d);
+// if (d > 0.05f)
+// BKE_sim_debug_data_add_dot(grid->debug_data, wloc, col[0], col[1], col[2], "grid", 5544, i, j, k);
+ }
+ }
+ }
+ }
+ }
+#endif
+
+ return true;
+ }
+ else {
+ /* Clear result in case of error */
+ for (i = 0, vert = grid->verts; i < num_cells; ++i, ++vert) {
+ zero_v3(vert->velocity_smooth);
+ }
+
+ return false;
+ }
+}
+
+#if 0 /* XXX weighting is incorrect, disabled for now */
+/* Velocity filter kernel
+ * See http://en.wikipedia.org/wiki/Filter_%28large_eddy_simulation%29
+ */
+
+BLI_INLINE void hair_volume_filter_box_convolute(HairVertexGrid *grid, float invD, const int kernel_size[3], int i, int j, int k)
+{
+ int res = grid->res;
+ int p, q, r;
+ int minp = max_ii(i - kernel_size[0], 0), maxp = min_ii(i + kernel_size[0], res-1);
+ int minq = max_ii(j - kernel_size[1], 0), maxq = min_ii(j + kernel_size[1], res-1);
+ int minr = max_ii(k - kernel_size[2], 0), maxr = min_ii(k + kernel_size[2], res-1);
+ int offset, kernel_offset, kernel_dq, kernel_dr;
+ HairGridVert *verts;
+ float *vel_smooth;
+
+ offset = i + (j + k*res)*res;
+ verts = grid->verts;
+ vel_smooth = verts[offset].velocity_smooth;
+
+ kernel_offset = minp + (minq + minr*res)*res;
+ kernel_dq = res;
+ kernel_dr = res * res;
+ for (r = minr; r <= maxr; ++r) {
+ for (q = minq; q <= maxq; ++q) {
+ for (p = minp; p <= maxp; ++p) {
+
+ madd_v3_v3fl(vel_smooth, verts[kernel_offset].velocity, invD);
+
+ kernel_offset += 1;
+ }
+ kernel_offset += kernel_dq;
+ }
+ kernel_offset += kernel_dr;
+ }
+}
+
+void BPH_hair_volume_vertex_grid_filter_box(HairVertexGrid *grid, int kernel_size)
+{
+ int size = hair_grid_size(grid->res);
+ int kernel_sizev[3] = {kernel_size, kernel_size, kernel_size};
+ int tot;
+ float invD;
+ int i, j, k;
+
+ if (kernel_size <= 0)
+ return;
+
+ tot = kernel_size * 2 + 1;
+ invD = 1.0f / (float)(tot*tot*tot);
+
+ /* clear values for convolution */
+ for (i = 0; i < size; ++i) {
+ zero_v3(grid->verts[i].velocity_smooth);
+ }
+
+ for (i = 0; i < grid->res; ++i) {
+ for (j = 0; j < grid->res; ++j) {
+ for (k = 0; k < grid->res; ++k) {
+ hair_volume_filter_box_convolute(grid, invD, kernel_sizev, i, j, k);
+ }
+ }
+ }
+
+ /* apply as new velocity */
+ for (i = 0; i < size; ++i) {
+ copy_v3_v3(grid->verts[i].velocity, grid->verts[i].velocity_smooth);
+ }
+}
+#endif
+
+HairGrid *BPH_hair_volume_create_vertex_grid(float cellsize, const float gmin[3], const float gmax[3])
+{
+ float scale;
+ float extent[3];
+ int resmin[3], resmax[3], res[3];
+ float gmin_margin[3], gmax_margin[3];
+ int size;
+ HairGrid *grid;
+ int i;
+
+ /* sanity check */
+ if (cellsize <= 0.0f)
+ cellsize = 1.0f;
+ scale = 1.0f / cellsize;
+
+ sub_v3_v3v3(extent, gmax, gmin);
+ for (i = 0; i < 3; ++i) {
+ resmin[i] = floor_int(gmin[i] * scale);
+ resmax[i] = floor_int(gmax[i] * scale) + 1;
+
+ /* add margin of 1 cell */
+ resmin[i] -= 1;
+ resmax[i] += 1;
+
+ res[i] = resmax[i] - resmin[i] + 1;
+ /* sanity check: avoid null-sized grid */
+ if (res[i] < 4) {
+ res[i] = 4;
+ resmax[i] = resmin[i] + 4;
+ }
+ /* sanity check: avoid too large grid size */
+ if (res[i] > MAX_HAIR_GRID_RES) {
+ res[i] = MAX_HAIR_GRID_RES;
+ resmax[i] = resmin[i] + MAX_HAIR_GRID_RES;
+ }
+
+ gmin_margin[i] = (float)resmin[i] * cellsize;
+ gmax_margin[i] = (float)resmax[i] * cellsize;
+ }
+ size = hair_grid_size(res);
+
+ grid = (HairGrid *)MEM_callocN(sizeof(HairGrid), "hair grid");
+ grid->res[0] = res[0];
+ grid->res[1] = res[1];
+ grid->res[2] = res[2];
+ copy_v3_v3(grid->gmin, gmin_margin);
+ copy_v3_v3(grid->gmax, gmax_margin);
+ grid->cellsize = cellsize;
+ grid->inv_cellsize = scale;
+ grid->verts = (HairGridVert *)MEM_callocN(sizeof(HairGridVert) * size, "hair voxel data");
+
+ return grid;
+}
+
+void BPH_hair_volume_free_vertex_grid(HairGrid *grid)
+{
+ if (grid) {
+ if (grid->verts)
+ MEM_freeN(grid->verts);
+ MEM_freeN(grid);
+ }
+}
+
+void BPH_hair_volume_grid_geometry(HairGrid *grid, float *cellsize, int res[3], float gmin[3], float gmax[3])
+{
+ if (cellsize) *cellsize = grid->cellsize;
+ if (res) copy_v3_v3_int(res, grid->res);
+ if (gmin) copy_v3_v3(gmin, grid->gmin);
+ if (gmax) copy_v3_v3(gmax, grid->gmax);
+}
+
+#if 0
+static HairGridVert *hair_volume_create_collision_grid(ClothModifierData *clmd, lfVector *lX, unsigned int numverts)
+{
+ int res = hair_grid_res;
+ int size = hair_grid_size(res);
+ HairGridVert *collgrid;
+ ListBase *colliders;
+ ColliderCache *col = NULL;
+ float gmin[3], gmax[3], scale[3];
+ /* 2.0f is an experimental value that seems to give good results */
+ float collfac = 2.0f * clmd->sim_parms->collider_friction;
+ unsigned int v = 0;
+ int i = 0;
+
+ hair_volume_get_boundbox(lX, numverts, gmin, gmax);
+ hair_grid_get_scale(res, gmin, gmax, scale);
+
+ collgrid = MEM_mallocN(sizeof(HairGridVert) * size, "hair collider voxel data");
+
+ /* initialize grid */
+ for (i = 0; i < size; ++i) {
+ zero_v3(collgrid[i].velocity);
+ collgrid[i].density = 0.0f;
+ }
+
+ /* gather colliders */
+ colliders = get_collider_cache(clmd->scene, NULL, NULL);
+ if (colliders && collfac > 0.0f) {
+ for (col = colliders->first; col; col = col->next) {
+ MVert *loc0 = col->collmd->x;
+ MVert *loc1 = col->collmd->xnew;
+ float vel[3];
+ float weights[8];
+ int di, dj, dk;
+
+ for (v=0; v < col->collmd->numverts; v++, loc0++, loc1++) {
+ int offset;
+
+ if (!hair_grid_point_valid(loc1->co, gmin, gmax))
+ continue;
+
+ offset = hair_grid_weights(res, gmin, scale, lX[v], weights);
+
+ sub_v3_v3v3(vel, loc1->co, loc0->co);
+
+ for (di = 0; di < 2; ++di) {
+ for (dj = 0; dj < 2; ++dj) {
+ for (dk = 0; dk < 2; ++dk) {
+ int voffset = offset + di + (dj + dk*res)*res;
+ int iw = di + dj*2 + dk*4;
+
+ collgrid[voffset].density += weights[iw];
+ madd_v3_v3fl(collgrid[voffset].velocity, vel, weights[iw]);
+ }
+ }
+ }
+ }
+ }
+ }
+ free_collider_cache(&colliders);
+
+ /* divide velocity with density */
+ for (i = 0; i < size; i++) {
+ float density = collgrid[i].density;
+ if (density > 0.0f)
+ mul_v3_fl(collgrid[i].velocity, 1.0f/density);
+ }
+
+ return collgrid;
+}
+#endif
+
+bool BPH_hair_volume_get_texture_data(HairGrid *grid, VoxelData *vd)
+{
+ int totres, i;
+ int depth;
+
+ vd->resol[0] = grid->res[0];
+ vd->resol[1] = grid->res[1];
+ vd->resol[2] = grid->res[2];
+
+ totres = hair_grid_size(grid->res);
+
+ if (vd->hair_type == TEX_VD_HAIRVELOCITY) {
+ depth = 4;
+ vd->data_type = TEX_VD_RGBA_PREMUL;
+ }
+ else {
+ depth = 1;
+ vd->data_type = TEX_VD_INTENSITY;
+ }
+
+ if (totres > 0) {
+ vd->dataset = (float *)MEM_mapallocN(sizeof(float) * depth * (totres), "hair volume texture data");
+
+ for (i = 0; i < totres; ++i) {
+ switch (vd->hair_type) {
+ case TEX_VD_HAIRDENSITY:
+ vd->dataset[i] = grid->verts[i].density;
+ break;
+
+ case TEX_VD_HAIRRESTDENSITY:
+ vd->dataset[i] = 0.0f; // TODO
+ break;
+
+ case TEX_VD_HAIRVELOCITY: {
+ vd->dataset[i + 0*totres] = grid->verts[i].velocity[0];
+ vd->dataset[i + 1*totres] = grid->verts[i].velocity[1];
+ vd->dataset[i + 2*totres] = grid->verts[i].velocity[2];
+ vd->dataset[i + 3*totres] = len_v3(grid->verts[i].velocity);
+ break;
+ }
+ case TEX_VD_HAIRENERGY:
+ vd->dataset[i] = 0.0f; // TODO
+ break;
+ }
+ }
+ }
+ else {
+ vd->dataset = NULL;
+ }
+
+ return true;
+}
diff --git a/source/blender/physics/intern/implicit.h b/source/blender/physics/intern/implicit.h
new file mode 100644
index 00000000000..d1a75ca5297
--- /dev/null
+++ b/source/blender/physics/intern/implicit.h
@@ -0,0 +1,184 @@
+/*
+ * ***** 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) Blender Foundation
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Lukas Toenne
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __IMPLICIT_H__
+#define __IMPLICIT_H__
+
+/** \file implicit.h
+ * \ingroup bph
+ */
+
+#include "stdio.h"
+
+#include "BLI_utildefines.h"
+
+#include "BKE_collision.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+//#define IMPLICIT_SOLVER_EIGEN
+#define IMPLICIT_SOLVER_BLENDER
+
+#define CLOTH_ROOT_FRAME /* enable use of root frame coordinate transform */
+
+#define CLOTH_FORCE_GRAVITY
+#define CLOTH_FORCE_DRAG
+#define CLOTH_FORCE_SPRING_STRUCTURAL
+#define CLOTH_FORCE_SPRING_BEND
+#define CLOTH_FORCE_SPRING_GOAL
+#define CLOTH_FORCE_EFFECTORS
+
+//#define IMPLICIT_PRINT_SOLVER_INPUT_OUTPUT
+
+//#define IMPLICIT_ENABLE_EIGEN_DEBUG
+
+struct Implicit_Data;
+
+typedef struct ImplicitSolverResult {
+ int status;
+
+ int iterations;
+ float error;
+} ImplicitSolverResult;
+
+BLI_INLINE void implicit_print_matrix_elem(float v)
+{
+ printf("%-8.3f", v);
+}
+
+void BPH_mass_spring_set_vertex_mass(struct Implicit_Data *data, int index, float mass);
+void BPH_mass_spring_set_rest_transform(struct Implicit_Data *data, int index, float rot[3][3]);
+
+void BPH_mass_spring_set_motion_state(struct Implicit_Data *data, int index, const float x[3], const float v[3]);
+void BPH_mass_spring_set_position(struct Implicit_Data *data, int index, const float x[3]);
+void BPH_mass_spring_set_velocity(struct Implicit_Data *data, int index, const float v[3]);
+void BPH_mass_spring_get_motion_state(struct Implicit_Data *data, int index, float x[3], float v[3]);
+void BPH_mass_spring_get_position(struct Implicit_Data *data, int index, float x[3]);
+
+/* access to modified motion state during solver step */
+void BPH_mass_spring_get_new_position(struct Implicit_Data *data, int index, float x[3]);
+void BPH_mass_spring_set_new_position(struct Implicit_Data *data, int index, const float x[3]);
+void BPH_mass_spring_get_new_velocity(struct Implicit_Data *data, int index, float v[3]);
+void BPH_mass_spring_set_new_velocity(struct Implicit_Data *data, int index, const float v[3]);
+
+void BPH_mass_spring_clear_constraints(struct Implicit_Data *data);
+void BPH_mass_spring_add_constraint_ndof0(struct Implicit_Data *data, int index, const float dV[3]);
+void BPH_mass_spring_add_constraint_ndof1(struct Implicit_Data *data, int index, const float c1[3], const float c2[3], const float dV[3]);
+void BPH_mass_spring_add_constraint_ndof2(struct Implicit_Data *data, int index, const float c1[3], const float dV[3]);
+
+bool BPH_mass_spring_solve_velocities(struct Implicit_Data *data, float dt, struct ImplicitSolverResult *result);
+bool BPH_mass_spring_solve_positions(struct Implicit_Data *data, float dt);
+void BPH_mass_spring_apply_result(struct Implicit_Data *data);
+
+/* Clear the force vector at the beginning of the time step */
+void BPH_mass_spring_clear_forces(struct Implicit_Data *data);
+/* Fictitious forces introduced by moving coordinate systems */
+void BPH_mass_spring_force_reference_frame(struct Implicit_Data *data, int index, const float acceleration[3], const float omega[3], const float domega_dt[3], float mass);
+/* Simple uniform gravity force */
+void BPH_mass_spring_force_gravity(struct Implicit_Data *data, int index, float mass, const float g[3]);
+/* Global drag force (velocity damping) */
+void BPH_mass_spring_force_drag(struct Implicit_Data *data, float drag);
+/* Custom external force */
+void BPH_mass_spring_force_extern(struct Implicit_Data *data, int i, const float f[3], float dfdx[3][3], float dfdv[3][3]);
+/* Wind force, acting on a face */
+void BPH_mass_spring_force_face_wind(struct Implicit_Data *data, int v1, int v2, int v3, const float (*winvec)[3]);
+/* Wind force, acting on an edge */
+void BPH_mass_spring_force_edge_wind(struct Implicit_Data *data, int v1, int v2, float radius1, float radius2, const float (*winvec)[3]);
+/* Wind force, acting on a vertex */
+void BPH_mass_spring_force_vertex_wind(struct Implicit_Data *data, int v, float radius, const float (*winvec)[3]);
+/* Linear spring force between two points */
+bool BPH_mass_spring_force_spring_linear(struct Implicit_Data *data, int i, int j, float restlen,
+ float stiffness, float damping, bool no_compress, float clamp_force,
+ float r_f[3], float r_dfdx[3][3], float r_dfdv[3][3]);
+/* Bending force, forming a triangle at the base of two structural springs */
+bool BPH_mass_spring_force_spring_bending(struct Implicit_Data *data, int i, int j, float restlen,
+ float kb, float cb,
+ float r_f[3], float r_dfdx[3][3], float r_dfdv[3][3]);
+/* Angular bending force based on local target vectors */
+bool BPH_mass_spring_force_spring_bending_angular(struct Implicit_Data *data, int i, int j, int k,
+ const float target[3], float stiffness, float damping);
+/* Global goal spring */
+bool BPH_mass_spring_force_spring_goal(struct Implicit_Data *data, int i, const float goal_x[3], const float goal_v[3],
+ float stiffness, float damping,
+ float r_f[3], float r_dfdx[3][3], float r_dfdv[3][3]);
+
+/* ======== Hair Volumetric Forces ======== */
+
+struct HairGrid;
+
+struct VoxelData;
+
+#define MAX_HAIR_GRID_RES 256
+
+struct HairGrid *BPH_hair_volume_create_vertex_grid(float cellsize, const float gmin[3], const float gmax[3]);
+void BPH_hair_volume_free_vertex_grid(struct HairGrid *grid);
+void BPH_hair_volume_grid_geometry(struct HairGrid *grid, float *cellsize, int res[3], float gmin[3], float gmax[3]);
+
+void BPH_hair_volume_grid_clear(struct HairGrid *grid);
+void BPH_hair_volume_add_vertex(struct HairGrid *grid, const float x[3], const float v[3]);
+void BPH_hair_volume_add_segment(struct HairGrid *grid,
+ const float x1[3], const float v1[3], const float x2[3], const float v2[3],
+ const float x3[3], const float v3[3], const float x4[3], const float v4[3],
+ const float dir1[3], const float dir2[3], const float dir3[3]);
+
+void BPH_hair_volume_normalize_vertex_grid(struct HairGrid *grid);
+
+bool BPH_hair_volume_solve_divergence(struct HairGrid *grid, float dt, float target_density, float target_strength);
+#if 0 /* XXX weighting is incorrect, disabled for now */
+void BPH_hair_volume_vertex_grid_filter_box(struct HairVertexGrid *grid, int kernel_size);
+#endif
+
+void BPH_hair_volume_grid_interpolate(struct HairGrid *grid, const float x[3],
+ float *density, float velocity[3], float velocity_smooth[3],
+ float density_gradient[3], float velocity_gradient[3][3]);
+
+/* Effect of fluid simulation grid on velocities.
+ * fluid_factor controls blending between PIC (Particle-in-Cell)
+ * and FLIP (Fluid-Implicit-Particle) methods (0 = only PIC, 1 = only FLIP)
+ */
+void BPH_hair_volume_grid_velocity(struct HairGrid *grid, const float x[3], const float v[3],
+ float fluid_factor,
+ float r_v[3]);
+/* XXX Warning: expressing grid effects on velocity as a force is not very stable,
+ * due to discontinuities in interpolated values!
+ * Better use hybrid approaches such as described in
+ * "Detail Preserving Continuum Simulation of Straight Hair"
+ * (McAdams, Selle 2009)
+ */
+void BPH_hair_volume_vertex_grid_forces(struct HairGrid *grid, const float x[3], const float v[3],
+ float smoothfac, float pressurefac, float minpressure,
+ float f[3], float dfdx[3][3], float dfdv[3][3]);
+
+bool BPH_hair_volume_get_texture_data(struct HairGrid *grid, struct VoxelData *vd);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/source/blender/physics/intern/implicit_blender.c b/source/blender/physics/intern/implicit_blender.c
new file mode 100644
index 00000000000..0fd2a1f35cc
--- /dev/null
+++ b/source/blender/physics/intern/implicit_blender.c
@@ -0,0 +1,2019 @@
+/*
+ * ***** 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) Blender Foundation
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/physics/intern/implicit_blender.c
+ * \ingroup bph
+ */
+
+#include "implicit.h"
+
+#ifdef IMPLICIT_SOLVER_BLENDER
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_scene_types.h"
+#include "DNA_object_types.h"
+#include "DNA_object_force.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_texture_types.h"
+
+#include "BLI_math.h"
+#include "BLI_linklist.h"
+#include "BLI_utildefines.h"
+
+#include "BKE_cloth.h"
+#include "BKE_collision.h"
+#include "BKE_effect.h"
+#include "BKE_global.h"
+
+#include "BPH_mass_spring.h"
+
+#ifdef __GNUC__
+# pragma GCC diagnostic ignored "-Wtype-limits"
+#endif
+
+#ifdef _OPENMP
+# define CLOTH_OPENMP_LIMIT 512
+#endif
+
+#if 0 /* debug timing */
+#ifdef _WIN32
+#include <windows.h>
+static LARGE_INTEGER _itstart, _itend;
+static LARGE_INTEGER ifreq;
+static void itstart(void)
+{
+ static int first = 1;
+ if (first) {
+ QueryPerformanceFrequency(&ifreq);
+ first = 0;
+ }
+ QueryPerformanceCounter(&_itstart);
+}
+static void itend(void)
+{
+ QueryPerformanceCounter(&_itend);
+}
+double itval(void)
+{
+ return ((double)_itend.QuadPart -
+ (double)_itstart.QuadPart)/((double)ifreq.QuadPart);
+}
+#else
+#include <sys/time.h>
+// intrinsics need better compile flag checking
+// #include <xmmintrin.h>
+// #include <pmmintrin.h>
+// #include <pthread.h>
+
+static struct timeval _itstart, _itend;
+static struct timezone itz;
+static void itstart(void)
+{
+ gettimeofday(&_itstart, &itz);
+}
+static void itend(void)
+{
+ gettimeofday(&_itend, &itz);
+}
+static double itval(void)
+{
+ double t1, t2;
+ t1 = (double)_itstart.tv_sec + (double)_itstart.tv_usec/(1000*1000);
+ t2 = (double)_itend.tv_sec + (double)_itend.tv_usec/(1000*1000);
+ return t2-t1;
+}
+#endif
+#endif /* debug timing */
+
+static float I[3][3] = {{1, 0, 0}, {0, 1, 0}, {0, 0, 1}};
+static float ZERO[3][3] = {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}};
+
+/*
+#define C99
+#ifdef C99
+#defineDO_INLINE inline
+#else
+#defineDO_INLINE static
+#endif
+*/
+struct Cloth;
+
+//////////////////////////////////////////
+/* fast vector / matrix library, enhancements are welcome :) -dg */
+/////////////////////////////////////////
+
+/* DEFINITIONS */
+typedef float lfVector[3];
+typedef struct fmatrix3x3 {
+ float m[3][3]; /* 3x3 matrix */
+ unsigned int c, r; /* column and row number */
+ /* int pinned; // is this vertex allowed to move? */
+ float n1, n2, n3; /* three normal vectors for collision constrains */
+ unsigned int vcount; /* vertex count */
+ unsigned int scount; /* spring count */
+} fmatrix3x3;
+
+///////////////////////////
+// float[3] vector
+///////////////////////////
+/* simple vector code */
+/* STATUS: verified */
+DO_INLINE void mul_fvector_S(float to[3], float from[3], float scalar)
+{
+ to[0] = from[0] * scalar;
+ to[1] = from[1] * scalar;
+ to[2] = from[2] * scalar;
+}
+/* simple v^T * v product ("outer product") */
+/* STATUS: HAS TO BE verified (*should* work) */
+DO_INLINE void mul_fvectorT_fvector(float to[3][3], float vectorA[3], float vectorB[3])
+{
+ mul_fvector_S(to[0], vectorB, vectorA[0]);
+ mul_fvector_S(to[1], vectorB, vectorA[1]);
+ mul_fvector_S(to[2], vectorB, vectorA[2]);
+}
+/* simple v^T * v product with scalar ("outer product") */
+/* STATUS: HAS TO BE verified (*should* work) */
+DO_INLINE void mul_fvectorT_fvectorS(float to[3][3], float vectorA[3], float vectorB[3], float aS)
+{
+ mul_fvectorT_fvector(to, vectorA, vectorB);
+
+ mul_fvector_S(to[0], to[0], aS);
+ mul_fvector_S(to[1], to[1], aS);
+ mul_fvector_S(to[2], to[2], aS);
+}
+
+#if 0
+/* printf vector[3] on console: for debug output */
+static void print_fvector(float m3[3])
+{
+ printf("%f\n%f\n%f\n\n", m3[0], m3[1], m3[2]);
+}
+
+///////////////////////////
+// long float vector float (*)[3]
+///////////////////////////
+/* print long vector on console: for debug output */
+DO_INLINE void print_lfvector(float (*fLongVector)[3], unsigned int verts)
+{
+ unsigned int i = 0;
+ for (i = 0; i < verts; i++) {
+ print_fvector(fLongVector[i]);
+ }
+}
+#endif
+
+/* create long vector */
+DO_INLINE lfVector *create_lfvector(unsigned int verts)
+{
+ /* TODO: check if memory allocation was successful */
+ return (lfVector *)MEM_callocN(verts * sizeof(lfVector), "cloth_implicit_alloc_vector");
+ // return (lfVector *)cloth_aligned_malloc(&MEMORY_BASE, verts * sizeof(lfVector));
+}
+/* delete long vector */
+DO_INLINE void del_lfvector(float (*fLongVector)[3])
+{
+ if (fLongVector != NULL) {
+ MEM_freeN(fLongVector);
+ // cloth_aligned_free(&MEMORY_BASE, fLongVector);
+ }
+}
+/* copy long vector */
+DO_INLINE void cp_lfvector(float (*to)[3], float (*from)[3], unsigned int verts)
+{
+ memcpy(to, from, verts * sizeof(lfVector));
+}
+/* init long vector with float[3] */
+DO_INLINE void init_lfvector(float (*fLongVector)[3], float vector[3], unsigned int verts)
+{
+ unsigned int i = 0;
+ for (i = 0; i < verts; i++) {
+ copy_v3_v3(fLongVector[i], vector);
+ }
+}
+/* zero long vector with float[3] */
+DO_INLINE void zero_lfvector(float (*to)[3], unsigned int verts)
+{
+ memset(to, 0.0f, verts * sizeof(lfVector));
+}
+/* multiply long vector with scalar*/
+DO_INLINE void mul_lfvectorS(float (*to)[3], float (*fLongVector)[3], float scalar, unsigned int verts)
+{
+ unsigned int i = 0;
+
+ for (i = 0; i < verts; i++) {
+ mul_fvector_S(to[i], fLongVector[i], scalar);
+ }
+}
+/* multiply long vector with scalar*/
+/* A -= B * float */
+DO_INLINE void submul_lfvectorS(float (*to)[3], float (*fLongVector)[3], float scalar, unsigned int verts)
+{
+ unsigned int i = 0;
+ for (i = 0; i < verts; i++) {
+ VECSUBMUL(to[i], fLongVector[i], scalar);
+ }
+}
+/* dot product for big vector */
+DO_INLINE float dot_lfvector(float (*fLongVectorA)[3], float (*fLongVectorB)[3], unsigned int verts)
+{
+ long i = 0;
+ float temp = 0.0;
+// XXX brecht, disabled this for now (first schedule line was already disabled),
+// due to non-commutative nature of floating point ops this makes the sim give
+// different results each time you run it!
+// schedule(guided, 2)
+//#pragma omp parallel for reduction(+: temp) if (verts > CLOTH_OPENMP_LIMIT)
+ for (i = 0; i < (long)verts; i++) {
+ temp += dot_v3v3(fLongVectorA[i], fLongVectorB[i]);
+ }
+ return temp;
+}
+/* A = B + C --> for big vector */
+DO_INLINE void add_lfvector_lfvector(float (*to)[3], float (*fLongVectorA)[3], float (*fLongVectorB)[3], unsigned int verts)
+{
+ unsigned int i = 0;
+
+ for (i = 0; i < verts; i++) {
+ VECADD(to[i], fLongVectorA[i], fLongVectorB[i]);
+ }
+
+}
+/* A = B + C * float --> for big vector */
+DO_INLINE void add_lfvector_lfvectorS(float (*to)[3], float (*fLongVectorA)[3], float (*fLongVectorB)[3], float bS, unsigned int verts)
+{
+ unsigned int i = 0;
+
+ for (i = 0; i < verts; i++) {
+ VECADDS(to[i], fLongVectorA[i], fLongVectorB[i], bS);
+
+ }
+}
+/* A = B * float + C * float --> for big vector */
+DO_INLINE void add_lfvectorS_lfvectorS(float (*to)[3], float (*fLongVectorA)[3], float aS, float (*fLongVectorB)[3], float bS, unsigned int verts)
+{
+ unsigned int i = 0;
+
+ for (i = 0; i < verts; i++) {
+ VECADDSS(to[i], fLongVectorA[i], aS, fLongVectorB[i], bS);
+ }
+}
+/* A = B - C * float --> for big vector */
+DO_INLINE void sub_lfvector_lfvectorS(float (*to)[3], float (*fLongVectorA)[3], float (*fLongVectorB)[3], float bS, unsigned int verts)
+{
+ unsigned int i = 0;
+ for (i = 0; i < verts; i++) {
+ VECSUBS(to[i], fLongVectorA[i], fLongVectorB[i], bS);
+ }
+
+}
+/* A = B - C --> for big vector */
+DO_INLINE void sub_lfvector_lfvector(float (*to)[3], float (*fLongVectorA)[3], float (*fLongVectorB)[3], unsigned int verts)
+{
+ unsigned int i = 0;
+
+ for (i = 0; i < verts; i++) {
+ sub_v3_v3v3(to[i], fLongVectorA[i], fLongVectorB[i]);
+ }
+
+}
+///////////////////////////
+// 3x3 matrix
+///////////////////////////
+#if 0
+/* printf 3x3 matrix on console: for debug output */
+static void print_fmatrix(float m3[3][3])
+{
+ printf("%f\t%f\t%f\n", m3[0][0], m3[0][1], m3[0][2]);
+ printf("%f\t%f\t%f\n", m3[1][0], m3[1][1], m3[1][2]);
+ printf("%f\t%f\t%f\n\n", m3[2][0], m3[2][1], m3[2][2]);
+}
+
+static void print_sparse_matrix(fmatrix3x3 *m)
+{
+ if (m) {
+ unsigned int i;
+ for (i = 0; i < m[0].vcount + m[0].scount; i++) {
+ printf("%d:\n", i);
+ print_fmatrix(m[i].m);
+ }
+ }
+}
+#endif
+
+#if 0
+static void print_lvector(lfVector *v, int numverts)
+{
+ int i;
+ for (i = 0; i < numverts; ++i) {
+ if (i > 0)
+ printf("\n");
+
+ printf("%f,\n", v[i][0]);
+ printf("%f,\n", v[i][1]);
+ printf("%f,\n", v[i][2]);
+ }
+}
+#endif
+
+#if 0
+static void print_bfmatrix(fmatrix3x3 *m)
+{
+ int tot = m[0].vcount + m[0].scount;
+ int size = m[0].vcount * 3;
+ float *t = MEM_callocN(sizeof(float) * size*size, "bfmatrix");
+ int q, i, j;
+
+ for (q = 0; q < tot; ++q) {
+ int k = 3 * m[q].r;
+ int l = 3 * m[q].c;
+
+ for (j = 0; j < 3; ++j) {
+ for (i = 0; i < 3; ++i) {
+// if (t[k + i + (l + j) * size] != 0.0f) {
+// printf("warning: overwriting value at %d, %d\n", m[q].r, m[q].c);
+// }
+ if (k == l) {
+ t[k + i + (k + j) * size] += m[q].m[i][j];
+ }
+ else {
+ t[k + i + (l + j) * size] += m[q].m[i][j];
+ t[l + j + (k + i) * size] += m[q].m[j][i];
+ }
+ }
+ }
+ }
+
+ for (j = 0; j < size; ++j) {
+ if (j > 0 && j % 3 == 0)
+ printf("\n");
+
+ for (i = 0; i < size; ++i) {
+ if (i > 0 && i % 3 == 0)
+ printf(" ");
+
+ implicit_print_matrix_elem(t[i + j * size]);
+ }
+ printf("\n");
+ }
+
+ MEM_freeN(t);
+}
+#endif
+
+/* copy 3x3 matrix */
+DO_INLINE void cp_fmatrix(float to[3][3], float from[3][3])
+{
+ // memcpy(to, from, sizeof (float) * 9);
+ copy_v3_v3(to[0], from[0]);
+ copy_v3_v3(to[1], from[1]);
+ copy_v3_v3(to[2], from[2]);
+}
+
+/* copy 3x3 matrix */
+DO_INLINE void initdiag_fmatrixS(float to[3][3], float aS)
+{
+ cp_fmatrix(to, ZERO);
+
+ to[0][0] = aS;
+ to[1][1] = aS;
+ to[2][2] = aS;
+}
+
+#if 0
+/* calculate determinant of 3x3 matrix */
+DO_INLINE float det_fmatrix(float m[3][3])
+{
+ return m[0][0]*m[1][1]*m[2][2] + m[1][0]*m[2][1]*m[0][2] + m[0][1]*m[1][2]*m[2][0] -
+ m[0][0]*m[1][2]*m[2][1] - m[0][1]*m[1][0]*m[2][2] - m[2][0]*m[1][1]*m[0][2];
+}
+
+DO_INLINE void inverse_fmatrix(float to[3][3], float from[3][3])
+{
+ unsigned int i, j;
+ float d;
+
+ if ((d=det_fmatrix(from)) == 0) {
+ printf("can't build inverse");
+ exit(0);
+ }
+ for (i=0;i<3;i++) {
+ for (j=0;j<3;j++) {
+ int i1=(i+1)%3;
+ int i2=(i+2)%3;
+ int j1=(j+1)%3;
+ int j2=(j+2)%3;
+ // reverse indexs i&j to take transpose
+ to[j][i] = (from[i1][j1]*from[i2][j2]-from[i1][j2]*from[i2][j1])/d;
+ /*
+ if (i==j)
+ to[i][j] = 1.0f / from[i][j];
+ else
+ to[i][j] = 0;
+ */
+ }
+ }
+
+}
+#endif
+
+/* 3x3 matrix multiplied by a scalar */
+/* STATUS: verified */
+DO_INLINE void mul_fmatrix_S(float matrix[3][3], float scalar)
+{
+ mul_fvector_S(matrix[0], matrix[0], scalar);
+ mul_fvector_S(matrix[1], matrix[1], scalar);
+ mul_fvector_S(matrix[2], matrix[2], scalar);
+}
+
+/* a vector multiplied by a 3x3 matrix */
+/* STATUS: verified */
+DO_INLINE void mul_fvector_fmatrix(float *to, float *from, float matrix[3][3])
+{
+ to[0] = matrix[0][0]*from[0] + matrix[1][0]*from[1] + matrix[2][0]*from[2];
+ to[1] = matrix[0][1]*from[0] + matrix[1][1]*from[1] + matrix[2][1]*from[2];
+ to[2] = matrix[0][2]*from[0] + matrix[1][2]*from[1] + matrix[2][2]*from[2];
+}
+
+/* 3x3 matrix multiplied by a vector */
+/* STATUS: verified */
+DO_INLINE void mul_fmatrix_fvector(float *to, float matrix[3][3], float from[3])
+{
+ to[0] = dot_v3v3(matrix[0], from);
+ to[1] = dot_v3v3(matrix[1], from);
+ to[2] = dot_v3v3(matrix[2], from);
+}
+/* 3x3 matrix addition with 3x3 matrix */
+DO_INLINE void add_fmatrix_fmatrix(float to[3][3], float matrixA[3][3], float matrixB[3][3])
+{
+ VECADD(to[0], matrixA[0], matrixB[0]);
+ VECADD(to[1], matrixA[1], matrixB[1]);
+ VECADD(to[2], matrixA[2], matrixB[2]);
+}
+/* A -= B*x + C*y (3x3 matrix sub-addition with 3x3 matrix) */
+DO_INLINE void subadd_fmatrixS_fmatrixS(float to[3][3], float matrixA[3][3], float aS, float matrixB[3][3], float bS)
+{
+ VECSUBADDSS(to[0], matrixA[0], aS, matrixB[0], bS);
+ VECSUBADDSS(to[1], matrixA[1], aS, matrixB[1], bS);
+ VECSUBADDSS(to[2], matrixA[2], aS, matrixB[2], bS);
+}
+/* A = B - C (3x3 matrix subtraction with 3x3 matrix) */
+DO_INLINE void sub_fmatrix_fmatrix(float to[3][3], float matrixA[3][3], float matrixB[3][3])
+{
+ sub_v3_v3v3(to[0], matrixA[0], matrixB[0]);
+ sub_v3_v3v3(to[1], matrixA[1], matrixB[1]);
+ sub_v3_v3v3(to[2], matrixA[2], matrixB[2]);
+}
+/////////////////////////////////////////////////////////////////
+// special functions
+/////////////////////////////////////////////////////////////////
+/* 3x3 matrix multiplied+added by a vector */
+/* STATUS: verified */
+DO_INLINE void muladd_fmatrix_fvector(float to[3], float matrix[3][3], float from[3])
+{
+ to[0] += dot_v3v3(matrix[0], from);
+ to[1] += dot_v3v3(matrix[1], from);
+ to[2] += dot_v3v3(matrix[2], from);
+}
+
+BLI_INLINE void outerproduct(float r[3][3], const float a[3], const float b[3])
+{
+ mul_v3_v3fl(r[0], a, b[0]);
+ mul_v3_v3fl(r[1], a, b[1]);
+ mul_v3_v3fl(r[2], a, b[2]);
+}
+
+BLI_INLINE void cross_m3_v3m3(float r[3][3], const float v[3], float m[3][3])
+{
+ cross_v3_v3v3(r[0], v, m[0]);
+ cross_v3_v3v3(r[1], v, m[1]);
+ cross_v3_v3v3(r[2], v, m[2]);
+}
+
+BLI_INLINE void cross_v3_identity(float r[3][3], const float v[3])
+{
+ r[0][0] = 0.0f; r[1][0] = v[2]; r[2][0] = -v[1];
+ r[0][1] = -v[2]; r[1][1] = 0.0f; r[2][1] = v[0];
+ r[0][2] = v[1]; r[1][2] = -v[0]; r[2][2] = 0.0f;
+}
+
+BLI_INLINE void madd_m3_m3fl(float r[3][3], float m[3][3], float f)
+{
+ r[0][0] += m[0][0] * f;
+ r[0][1] += m[0][1] * f;
+ r[0][2] += m[0][2] * f;
+ r[1][0] += m[1][0] * f;
+ r[1][1] += m[1][1] * f;
+ r[1][2] += m[1][2] * f;
+ r[2][0] += m[2][0] * f;
+ r[2][1] += m[2][1] * f;
+ r[2][2] += m[2][2] * f;
+}
+
+BLI_INLINE void madd_m3_m3m3fl(float r[3][3], float a[3][3], float b[3][3], float f)
+{
+ r[0][0] = a[0][0] + b[0][0] * f;
+ r[0][1] = a[0][1] + b[0][1] * f;
+ r[0][2] = a[0][2] + b[0][2] * f;
+ r[1][0] = a[1][0] + b[1][0] * f;
+ r[1][1] = a[1][1] + b[1][1] * f;
+ r[1][2] = a[1][2] + b[1][2] * f;
+ r[2][0] = a[2][0] + b[2][0] * f;
+ r[2][1] = a[2][1] + b[2][1] * f;
+ r[2][2] = a[2][2] + b[2][2] * f;
+}
+/////////////////////////////////////////////////////////////////
+
+///////////////////////////
+// SPARSE SYMMETRIC big matrix with 3x3 matrix entries
+///////////////////////////
+/* printf a big matrix on console: for debug output */
+#if 0
+static void print_bfmatrix(fmatrix3x3 *m3)
+{
+ unsigned int i = 0;
+
+ for (i = 0; i < m3[0].vcount + m3[0].scount; i++)
+ {
+ print_fmatrix(m3[i].m);
+ }
+}
+#endif
+
+BLI_INLINE void init_fmatrix(fmatrix3x3 *matrix, int r, int c)
+{
+ matrix->r = r;
+ matrix->c = c;
+}
+
+/* create big matrix */
+DO_INLINE fmatrix3x3 *create_bfmatrix(unsigned int verts, unsigned int springs)
+{
+ // TODO: check if memory allocation was successful */
+ fmatrix3x3 *temp = (fmatrix3x3 *)MEM_callocN(sizeof(fmatrix3x3) * (verts + springs), "cloth_implicit_alloc_matrix");
+ int i;
+
+ temp[0].vcount = verts;
+ temp[0].scount = springs;
+
+ /* vertex part of the matrix is diagonal blocks */
+ for (i = 0; i < verts; ++i) {
+ init_fmatrix(temp + i, i, i);
+ }
+
+ return temp;
+}
+/* delete big matrix */
+DO_INLINE void del_bfmatrix(fmatrix3x3 *matrix)
+{
+ if (matrix != NULL) {
+ MEM_freeN(matrix);
+ }
+}
+
+/* copy big matrix */
+DO_INLINE void cp_bfmatrix(fmatrix3x3 *to, fmatrix3x3 *from)
+{
+ // TODO bounds checking
+ memcpy(to, from, sizeof(fmatrix3x3) * (from[0].vcount+from[0].scount));
+}
+
+/* init big matrix */
+// slow in parallel
+DO_INLINE void init_bfmatrix(fmatrix3x3 *matrix, float m3[3][3])
+{
+ unsigned int i;
+
+ for (i = 0; i < matrix[0].vcount+matrix[0].scount; i++) {
+ cp_fmatrix(matrix[i].m, m3);
+ }
+}
+
+/* init the diagonal of big matrix */
+// slow in parallel
+DO_INLINE void initdiag_bfmatrix(fmatrix3x3 *matrix, float m3[3][3])
+{
+ unsigned int i, j;
+ float tmatrix[3][3] = {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}};
+
+ for (i = 0; i < matrix[0].vcount; i++) {
+ cp_fmatrix(matrix[i].m, m3);
+ }
+ for (j = matrix[0].vcount; j < matrix[0].vcount+matrix[0].scount; j++) {
+ cp_fmatrix(matrix[j].m, tmatrix);
+ }
+}
+
+/* SPARSE SYMMETRIC multiply big matrix with long vector*/
+/* STATUS: verified */
+DO_INLINE void mul_bfmatrix_lfvector( float (*to)[3], fmatrix3x3 *from, lfVector *fLongVector)
+{
+ unsigned int i = 0;
+ unsigned int vcount = from[0].vcount;
+ lfVector *temp = create_lfvector(vcount);
+
+ zero_lfvector(to, vcount);
+
+#pragma omp parallel sections private(i) if (vcount > CLOTH_OPENMP_LIMIT)
+ {
+#pragma omp section
+ {
+ for (i = from[0].vcount; i < from[0].vcount+from[0].scount; i++) {
+ muladd_fmatrix_fvector(to[from[i].c], from[i].m, fLongVector[from[i].r]);
+ }
+ }
+#pragma omp section
+ {
+ for (i = 0; i < from[0].vcount+from[0].scount; i++) {
+ muladd_fmatrix_fvector(temp[from[i].r], from[i].m, fLongVector[from[i].c]);
+ }
+ }
+ }
+ add_lfvector_lfvector(to, to, temp, from[0].vcount);
+
+ del_lfvector(temp);
+
+
+}
+
+/* SPARSE SYMMETRIC sub big matrix with big matrix*/
+/* A -= B * float + C * float --> for big matrix */
+/* VERIFIED */
+DO_INLINE void subadd_bfmatrixS_bfmatrixS( fmatrix3x3 *to, fmatrix3x3 *from, float aS, fmatrix3x3 *matrix, float bS)
+{
+ unsigned int i = 0;
+
+ /* process diagonal elements */
+ for (i = 0; i < matrix[0].vcount+matrix[0].scount; i++) {
+ subadd_fmatrixS_fmatrixS(to[i].m, from[i].m, aS, matrix[i].m, bS);
+ }
+
+}
+
+///////////////////////////////////////////////////////////////////
+// simulator start
+///////////////////////////////////////////////////////////////////
+
+typedef struct Implicit_Data {
+ /* inputs */
+ fmatrix3x3 *bigI; /* identity (constant) */
+ fmatrix3x3 *tfm; /* local coordinate transform */
+ fmatrix3x3 *M; /* masses */
+ lfVector *F; /* forces */
+ fmatrix3x3 *dFdV, *dFdX; /* force jacobians */
+ int num_blocks; /* number of off-diagonal blocks (springs) */
+
+ /* motion state data */
+ lfVector *X, *Xnew; /* positions */
+ lfVector *V, *Vnew; /* velocities */
+
+ /* internal solver data */
+ lfVector *B; /* B for A*dV = B */
+ fmatrix3x3 *A; /* A for A*dV = B */
+
+ lfVector *dV; /* velocity change (solution of A*dV = B) */
+ lfVector *z; /* target velocity in constrained directions */
+ fmatrix3x3 *S; /* filtering matrix for constraints */
+ fmatrix3x3 *P, *Pinv; /* pre-conditioning matrix */
+} Implicit_Data;
+
+Implicit_Data *BPH_mass_spring_solver_create(int numverts, int numsprings)
+{
+ Implicit_Data *id = (Implicit_Data *)MEM_callocN(sizeof(Implicit_Data), "implicit vecmat");
+
+ /* process diagonal elements */
+ id->tfm = create_bfmatrix(numverts, 0);
+ id->A = create_bfmatrix(numverts, numsprings);
+ id->dFdV = create_bfmatrix(numverts, numsprings);
+ id->dFdX = create_bfmatrix(numverts, numsprings);
+ id->S = create_bfmatrix(numverts, 0);
+ id->Pinv = create_bfmatrix(numverts, numsprings);
+ id->P = create_bfmatrix(numverts, numsprings);
+ id->bigI = create_bfmatrix(numverts, numsprings); // TODO 0 springs
+ id->M = create_bfmatrix(numverts, numsprings);
+ id->X = create_lfvector(numverts);
+ id->Xnew = create_lfvector(numverts);
+ id->V = create_lfvector(numverts);
+ id->Vnew = create_lfvector(numverts);
+ id->F = create_lfvector(numverts);
+ id->B = create_lfvector(numverts);
+ id->dV = create_lfvector(numverts);
+ id->z = create_lfvector(numverts);
+
+ initdiag_bfmatrix(id->bigI, I);
+
+ return id;
+}
+
+void BPH_mass_spring_solver_free(Implicit_Data *id)
+{
+ del_bfmatrix(id->tfm);
+ del_bfmatrix(id->A);
+ del_bfmatrix(id->dFdV);
+ del_bfmatrix(id->dFdX);
+ del_bfmatrix(id->S);
+ del_bfmatrix(id->P);
+ del_bfmatrix(id->Pinv);
+ del_bfmatrix(id->bigI);
+ del_bfmatrix(id->M);
+
+ del_lfvector(id->X);
+ del_lfvector(id->Xnew);
+ del_lfvector(id->V);
+ del_lfvector(id->Vnew);
+ del_lfvector(id->F);
+ del_lfvector(id->B);
+ del_lfvector(id->dV);
+ del_lfvector(id->z);
+
+ MEM_freeN(id);
+}
+
+/* ==== Transformation from/to root reference frames ==== */
+
+BLI_INLINE void world_to_root_v3(Implicit_Data *data, int index, float r[3], const float v[3])
+{
+ copy_v3_v3(r, v);
+ mul_transposed_m3_v3(data->tfm[index].m, r);
+}
+
+BLI_INLINE void root_to_world_v3(Implicit_Data *data, int index, float r[3], const float v[3])
+{
+ mul_v3_m3v3(r, data->tfm[index].m, v);
+}
+
+BLI_INLINE void world_to_root_m3(Implicit_Data *data, int index, float r[3][3], float m[3][3])
+{
+ float trot[3][3];
+ copy_m3_m3(trot, data->tfm[index].m);
+ transpose_m3(trot);
+ mul_m3_m3m3(r, trot, m);
+}
+
+BLI_INLINE void root_to_world_m3(Implicit_Data *data, int index, float r[3][3], float m[3][3])
+{
+ mul_m3_m3m3(r, data->tfm[index].m, m);
+}
+
+/* ================================ */
+
+DO_INLINE void filter(lfVector *V, fmatrix3x3 *S)
+{
+ unsigned int i=0;
+
+ for (i = 0; i < S[0].vcount; i++) {
+ mul_m3_v3(S[i].m, V[S[i].r]);
+ }
+}
+
+#if 0 /* this version of the CG algorithm does not work very well with partial constraints (where S has non-zero elements) */
+static int cg_filtered(lfVector *ldV, fmatrix3x3 *lA, lfVector *lB, lfVector *z, fmatrix3x3 *S)
+{
+ // Solves for unknown X in equation AX=B
+ unsigned int conjgrad_loopcount=0, conjgrad_looplimit=100;
+ float conjgrad_epsilon=0.0001f /* , conjgrad_lasterror=0 */ /* UNUSED */;
+ lfVector *q, *d, *tmp, *r;
+ float s, starget, a, s_prev;
+ unsigned int numverts = lA[0].vcount;
+ q = create_lfvector(numverts);
+ d = create_lfvector(numverts);
+ tmp = create_lfvector(numverts);
+ r = create_lfvector(numverts);
+
+ // zero_lfvector(ldV, CLOTHPARTICLES);
+ filter(ldV, S);
+
+ add_lfvector_lfvector(ldV, ldV, z, numverts);
+
+ // r = B - Mul(tmp, A, X); // just use B if X known to be zero
+ cp_lfvector(r, lB, numverts);
+ mul_bfmatrix_lfvector(tmp, lA, ldV);
+ sub_lfvector_lfvector(r, r, tmp, numverts);
+
+ filter(r, S);
+
+ cp_lfvector(d, r, numverts);
+
+ s = dot_lfvector(r, r, numverts);
+ starget = s * sqrtf(conjgrad_epsilon);
+
+ while (s>starget && conjgrad_loopcount < conjgrad_looplimit) {
+ // Mul(q, A, d); // q = A*d;
+ mul_bfmatrix_lfvector(q, lA, d);
+
+ filter(q, S);
+
+ a = s/dot_lfvector(d, q, numverts);
+
+ // X = X + d*a;
+ add_lfvector_lfvectorS(ldV, ldV, d, a, numverts);
+
+ // r = r - q*a;
+ sub_lfvector_lfvectorS(r, r, q, a, numverts);
+
+ s_prev = s;
+ s = dot_lfvector(r, r, numverts);
+
+ //d = r+d*(s/s_prev);
+ add_lfvector_lfvectorS(d, r, d, (s/s_prev), numverts);
+
+ filter(d, S);
+
+ conjgrad_loopcount++;
+ }
+ /* conjgrad_lasterror = s; */ /* UNUSED */
+
+ del_lfvector(q);
+ del_lfvector(d);
+ del_lfvector(tmp);
+ del_lfvector(r);
+ // printf("W/O conjgrad_loopcount: %d\n", conjgrad_loopcount);
+
+ return conjgrad_loopcount<conjgrad_looplimit; // true means we reached desired accuracy in given time - ie stable
+}
+#endif
+
+static int cg_filtered(lfVector *ldV, fmatrix3x3 *lA, lfVector *lB, lfVector *z, fmatrix3x3 *S, ImplicitSolverResult *result)
+{
+ // Solves for unknown X in equation AX=B
+ unsigned int conjgrad_loopcount=0, conjgrad_looplimit=100;
+ float conjgrad_epsilon=0.01f;
+
+ unsigned int numverts = lA[0].vcount;
+ lfVector *fB = create_lfvector(numverts);
+ lfVector *AdV = create_lfvector(numverts);
+ lfVector *r = create_lfvector(numverts);
+ lfVector *c = create_lfvector(numverts);
+ lfVector *q = create_lfvector(numverts);
+ lfVector *s = create_lfvector(numverts);
+ float bnorm2, delta_new, delta_old, delta_target, alpha;
+
+ cp_lfvector(ldV, z, numverts);
+
+ /* d0 = filter(B)^T * P * filter(B) */
+ cp_lfvector(fB, lB, numverts);
+ filter(fB, S);
+ bnorm2 = dot_lfvector(fB, fB, numverts);
+ delta_target = conjgrad_epsilon*conjgrad_epsilon * bnorm2;
+
+ /* r = filter(B - A * dV) */
+ mul_bfmatrix_lfvector(AdV, lA, ldV);
+ sub_lfvector_lfvector(r, lB, AdV, numverts);
+ filter(r, S);
+
+ /* c = filter(P^-1 * r) */
+ cp_lfvector(c, r, numverts);
+ filter(c, S);
+
+ /* delta = r^T * c */
+ delta_new = dot_lfvector(r, c, numverts);
+
+#ifdef IMPLICIT_PRINT_SOLVER_INPUT_OUTPUT
+ printf("==== A ====\n");
+ print_bfmatrix(lA);
+ printf("==== z ====\n");
+ print_lvector(z, numverts);
+ printf("==== B ====\n");
+ print_lvector(lB, numverts);
+ printf("==== S ====\n");
+ print_bfmatrix(S);
+#endif
+
+ while (delta_new > delta_target && conjgrad_loopcount < conjgrad_looplimit) {
+ mul_bfmatrix_lfvector(q, lA, c);
+ filter(q, S);
+
+ alpha = delta_new / dot_lfvector(c, q, numverts);
+
+ add_lfvector_lfvectorS(ldV, ldV, c, alpha, numverts);
+
+ add_lfvector_lfvectorS(r, r, q, -alpha, numverts);
+
+ /* s = P^-1 * r */
+ cp_lfvector(s, r, numverts);
+ delta_old = delta_new;
+ delta_new = dot_lfvector(r, s, numverts);
+
+ add_lfvector_lfvectorS(c, s, c, delta_new / delta_old, numverts);
+ filter(c, S);
+
+ conjgrad_loopcount++;
+ }
+
+#ifdef IMPLICIT_PRINT_SOLVER_INPUT_OUTPUT
+ printf("==== dV ====\n");
+ print_lvector(ldV, numverts);
+ printf("========\n");
+#endif
+
+ del_lfvector(fB);
+ del_lfvector(AdV);
+ del_lfvector(r);
+ del_lfvector(c);
+ del_lfvector(q);
+ del_lfvector(s);
+ // printf("W/O conjgrad_loopcount: %d\n", conjgrad_loopcount);
+
+ result->status = conjgrad_loopcount < conjgrad_looplimit ? BPH_SOLVER_SUCCESS : BPH_SOLVER_NO_CONVERGENCE;
+ result->iterations = conjgrad_loopcount;
+ result->error = bnorm2 > 0.0f ? sqrtf(delta_new / bnorm2) : 0.0f;
+
+ return conjgrad_loopcount < conjgrad_looplimit; // true means we reached desired accuracy in given time - ie stable
+}
+
+#if 0
+// block diagonalizer
+DO_INLINE void BuildPPinv(fmatrix3x3 *lA, fmatrix3x3 *P, fmatrix3x3 *Pinv)
+{
+ unsigned int i = 0;
+
+ // Take only the diagonal blocks of A
+// #pragma omp parallel for private(i) if (lA[0].vcount > CLOTH_OPENMP_LIMIT)
+ for (i = 0; i<lA[0].vcount; i++) {
+ // block diagonalizer
+ cp_fmatrix(P[i].m, lA[i].m);
+ inverse_fmatrix(Pinv[i].m, P[i].m);
+
+ }
+}
+/*
+// version 1.3
+static int cg_filtered_pre(lfVector *dv, fmatrix3x3 *lA, lfVector *lB, lfVector *z, fmatrix3x3 *S, fmatrix3x3 *P, fmatrix3x3 *Pinv)
+{
+ unsigned int numverts = lA[0].vcount, iterations = 0, conjgrad_looplimit=100;
+ float delta0 = 0, deltaNew = 0, deltaOld = 0, alpha = 0;
+ float conjgrad_epsilon=0.0001; // 0.2 is dt for steps=5
+ lfVector *r = create_lfvector(numverts);
+ lfVector *p = create_lfvector(numverts);
+ lfVector *s = create_lfvector(numverts);
+ lfVector *h = create_lfvector(numverts);
+
+ BuildPPinv(lA, P, Pinv);
+
+ filter(dv, S);
+ add_lfvector_lfvector(dv, dv, z, numverts);
+
+ mul_bfmatrix_lfvector(r, lA, dv);
+ sub_lfvector_lfvector(r, lB, r, numverts);
+ filter(r, S);
+
+ mul_prevfmatrix_lfvector(p, Pinv, r);
+ filter(p, S);
+
+ deltaNew = dot_lfvector(r, p, numverts);
+
+ delta0 = deltaNew * sqrt(conjgrad_epsilon);
+
+ // itstart();
+
+ while ((deltaNew > delta0) && (iterations < conjgrad_looplimit))
+ {
+ iterations++;
+
+ mul_bfmatrix_lfvector(s, lA, p);
+ filter(s, S);
+
+ alpha = deltaNew / dot_lfvector(p, s, numverts);
+
+ add_lfvector_lfvectorS(dv, dv, p, alpha, numverts);
+
+ add_lfvector_lfvectorS(r, r, s, -alpha, numverts);
+
+ mul_prevfmatrix_lfvector(h, Pinv, r);
+ filter(h, S);
+
+ deltaOld = deltaNew;
+
+ deltaNew = dot_lfvector(r, h, numverts);
+
+ add_lfvector_lfvectorS(p, h, p, deltaNew / deltaOld, numverts);
+
+ filter(p, S);
+
+ }
+
+ // itend();
+ // printf("cg_filtered_pre time: %f\n", (float)itval());
+
+ del_lfvector(h);
+ del_lfvector(s);
+ del_lfvector(p);
+ del_lfvector(r);
+
+ printf("iterations: %d\n", iterations);
+
+ return iterations<conjgrad_looplimit;
+}
+*/
+// version 1.4
+static int cg_filtered_pre(lfVector *dv, fmatrix3x3 *lA, lfVector *lB, lfVector *z, fmatrix3x3 *S, fmatrix3x3 *P, fmatrix3x3 *Pinv, fmatrix3x3 *bigI)
+{
+ unsigned int numverts = lA[0].vcount, iterations = 0, conjgrad_looplimit=100;
+ float delta0 = 0, deltaNew = 0, deltaOld = 0, alpha = 0, tol = 0;
+ lfVector *r = create_lfvector(numverts);
+ lfVector *p = create_lfvector(numverts);
+ lfVector *s = create_lfvector(numverts);
+ lfVector *h = create_lfvector(numverts);
+ lfVector *bhat = create_lfvector(numverts);
+ lfVector *btemp = create_lfvector(numverts);
+
+ BuildPPinv(lA, P, Pinv);
+
+ initdiag_bfmatrix(bigI, I);
+ sub_bfmatrix_Smatrix(bigI, bigI, S);
+
+ // x = Sx_0+(I-S)z
+ filter(dv, S);
+ add_lfvector_lfvector(dv, dv, z, numverts);
+
+ // b_hat = S(b-A(I-S)z)
+ mul_bfmatrix_lfvector(r, lA, z);
+ mul_bfmatrix_lfvector(bhat, bigI, r);
+ sub_lfvector_lfvector(bhat, lB, bhat, numverts);
+
+ // r = S(b-Ax)
+ mul_bfmatrix_lfvector(r, lA, dv);
+ sub_lfvector_lfvector(r, lB, r, numverts);
+ filter(r, S);
+
+ // p = SP^-1r
+ mul_prevfmatrix_lfvector(p, Pinv, r);
+ filter(p, S);
+
+ // delta0 = bhat^TP^-1bhat
+ mul_prevfmatrix_lfvector(btemp, Pinv, bhat);
+ delta0 = dot_lfvector(bhat, btemp, numverts);
+
+ // deltaNew = r^TP
+ deltaNew = dot_lfvector(r, p, numverts);
+
+ /*
+ filter(dv, S);
+ add_lfvector_lfvector(dv, dv, z, numverts);
+
+ mul_bfmatrix_lfvector(r, lA, dv);
+ sub_lfvector_lfvector(r, lB, r, numverts);
+ filter(r, S);
+
+ mul_prevfmatrix_lfvector(p, Pinv, r);
+ filter(p, S);
+
+ deltaNew = dot_lfvector(r, p, numverts);
+
+ delta0 = deltaNew * sqrt(conjgrad_epsilon);
+ */
+
+ // itstart();
+
+ tol = (0.01*0.2);
+
+ while ((deltaNew > delta0*tol*tol) && (iterations < conjgrad_looplimit))
+ {
+ iterations++;
+
+ mul_bfmatrix_lfvector(s, lA, p);
+ filter(s, S);
+
+ alpha = deltaNew / dot_lfvector(p, s, numverts);
+
+ add_lfvector_lfvectorS(dv, dv, p, alpha, numverts);
+
+ add_lfvector_lfvectorS(r, r, s, -alpha, numverts);
+
+ mul_prevfmatrix_lfvector(h, Pinv, r);
+ filter(h, S);
+
+ deltaOld = deltaNew;
+
+ deltaNew = dot_lfvector(r, h, numverts);
+
+ add_lfvector_lfvectorS(p, h, p, deltaNew / deltaOld, numverts);
+
+ filter(p, S);
+
+ }
+
+ // itend();
+ // printf("cg_filtered_pre time: %f\n", (float)itval());
+
+ del_lfvector(btemp);
+ del_lfvector(bhat);
+ del_lfvector(h);
+ del_lfvector(s);
+ del_lfvector(p);
+ del_lfvector(r);
+
+ // printf("iterations: %d\n", iterations);
+
+ return iterations<conjgrad_looplimit;
+}
+#endif
+
+bool BPH_mass_spring_solve_velocities(Implicit_Data *data, float dt, ImplicitSolverResult *result)
+{
+ unsigned int numverts = data->dFdV[0].vcount;
+
+ lfVector *dFdXmV = create_lfvector(numverts);
+ zero_lfvector(data->dV, numverts);
+
+ cp_bfmatrix(data->A, data->M);
+
+ subadd_bfmatrixS_bfmatrixS(data->A, data->dFdV, dt, data->dFdX, (dt*dt));
+
+ mul_bfmatrix_lfvector(dFdXmV, data->dFdX, data->V);
+
+ add_lfvectorS_lfvectorS(data->B, data->F, dt, dFdXmV, (dt*dt), numverts);
+
+ // itstart();
+
+ cg_filtered(data->dV, data->A, data->B, data->z, data->S, result); /* conjugate gradient algorithm to solve Ax=b */
+ // cg_filtered_pre(id->dV, id->A, id->B, id->z, id->S, id->P, id->Pinv, id->bigI);
+
+ // itend();
+ // printf("cg_filtered calc time: %f\n", (float)itval());
+
+ // advance velocities
+ add_lfvector_lfvector(data->Vnew, data->V, data->dV, numverts);
+
+ del_lfvector(dFdXmV);
+
+ return result->status == BPH_SOLVER_SUCCESS;
+}
+
+bool BPH_mass_spring_solve_positions(Implicit_Data *data, float dt)
+{
+ int numverts = data->M[0].vcount;
+
+ // advance positions
+ add_lfvector_lfvectorS(data->Xnew, data->X, data->Vnew, dt, numverts);
+
+ return true;
+}
+
+void BPH_mass_spring_apply_result(Implicit_Data *data)
+{
+ int numverts = data->M[0].vcount;
+ cp_lfvector(data->X, data->Xnew, numverts);
+ cp_lfvector(data->V, data->Vnew, numverts);
+}
+
+void BPH_mass_spring_set_vertex_mass(Implicit_Data *data, int index, float mass)
+{
+ unit_m3(data->M[index].m);
+ mul_m3_fl(data->M[index].m, mass);
+}
+
+void BPH_mass_spring_set_rest_transform(Implicit_Data *data, int index, float tfm[3][3])
+{
+#ifdef CLOTH_ROOT_FRAME
+ copy_m3_m3(data->tfm[index].m, tfm);
+#else
+ unit_m3(data->tfm[index].m);
+ (void)tfm;
+#endif
+}
+
+void BPH_mass_spring_set_motion_state(Implicit_Data *data, int index, const float x[3], const float v[3])
+{
+ world_to_root_v3(data, index, data->X[index], x);
+ world_to_root_v3(data, index, data->V[index], v);
+}
+
+void BPH_mass_spring_set_position(Implicit_Data *data, int index, const float x[3])
+{
+ world_to_root_v3(data, index, data->X[index], x);
+}
+
+void BPH_mass_spring_set_velocity(Implicit_Data *data, int index, const float v[3])
+{
+ world_to_root_v3(data, index, data->V[index], v);
+}
+
+void BPH_mass_spring_get_motion_state(struct Implicit_Data *data, int index, float x[3], float v[3])
+{
+ if (x) root_to_world_v3(data, index, x, data->X[index]);
+ if (v) root_to_world_v3(data, index, v, data->V[index]);
+}
+
+void BPH_mass_spring_get_position(struct Implicit_Data *data, int index, float x[3])
+{
+ root_to_world_v3(data, index, x, data->X[index]);
+}
+
+void BPH_mass_spring_get_new_position(struct Implicit_Data *data, int index, float x[3])
+{
+ root_to_world_v3(data, index, x, data->Xnew[index]);
+}
+
+void BPH_mass_spring_set_new_position(struct Implicit_Data *data, int index, const float x[3])
+{
+ world_to_root_v3(data, index, data->Xnew[index], x);
+}
+
+void BPH_mass_spring_get_new_velocity(struct Implicit_Data *data, int index, float v[3])
+{
+ root_to_world_v3(data, index, v, data->Vnew[index]);
+}
+
+void BPH_mass_spring_set_new_velocity(struct Implicit_Data *data, int index, const float v[3])
+{
+ world_to_root_v3(data, index, data->Vnew[index], v);
+}
+
+/* -------------------------------- */
+
+static int BPH_mass_spring_add_block(Implicit_Data *data, int v1, int v2)
+{
+ int s = data->M[0].vcount + data->num_blocks; /* index from array start */
+ BLI_assert(s < data->M[0].vcount + data->M[0].scount);
+ ++data->num_blocks;
+
+ /* tfm and S don't have spring entries (diagonal blocks only) */
+ init_fmatrix(data->bigI + s, v1, v2);
+ init_fmatrix(data->M + s, v1, v2);
+ init_fmatrix(data->dFdX + s, v1, v2);
+ init_fmatrix(data->dFdV + s, v1, v2);
+ init_fmatrix(data->A + s, v1, v2);
+ init_fmatrix(data->P + s, v1, v2);
+ init_fmatrix(data->Pinv + s, v1, v2);
+
+ return s;
+}
+
+void BPH_mass_spring_clear_constraints(Implicit_Data *data)
+{
+ int i, numverts = data->S[0].vcount;
+ for (i = 0; i < numverts; ++i) {
+ unit_m3(data->S[i].m);
+ zero_v3(data->z[i]);
+ }
+}
+
+void BPH_mass_spring_add_constraint_ndof0(Implicit_Data *data, int index, const float dV[3])
+{
+ zero_m3(data->S[index].m);
+
+ world_to_root_v3(data, index, data->z[index], dV);
+}
+
+void BPH_mass_spring_add_constraint_ndof1(Implicit_Data *data, int index, const float c1[3], const float c2[3], const float dV[3])
+{
+ float m[3][3], p[3], q[3], u[3], cmat[3][3];
+
+ world_to_root_v3(data, index, p, c1);
+ mul_fvectorT_fvector(cmat, p, p);
+ sub_m3_m3m3(m, I, cmat);
+
+ world_to_root_v3(data, index, q, c2);
+ mul_fvectorT_fvector(cmat, q, q);
+ sub_m3_m3m3(m, m, cmat);
+
+ /* XXX not sure but multiplication should work here */
+ copy_m3_m3(data->S[index].m, m);
+// mul_m3_m3m3(data->S[index].m, data->S[index].m, m);
+
+ world_to_root_v3(data, index, u, dV);
+ add_v3_v3(data->z[index], u);
+}
+
+void BPH_mass_spring_add_constraint_ndof2(Implicit_Data *data, int index, const float c1[3], const float dV[3])
+{
+ float m[3][3], p[3], u[3], cmat[3][3];
+
+ world_to_root_v3(data, index, p, c1);
+ mul_fvectorT_fvector(cmat, p, p);
+ sub_m3_m3m3(m, I, cmat);
+
+ copy_m3_m3(data->S[index].m, m);
+// mul_m3_m3m3(data->S[index].m, data->S[index].m, m);
+
+ world_to_root_v3(data, index, u, dV);
+ add_v3_v3(data->z[index], u);
+}
+
+void BPH_mass_spring_clear_forces(Implicit_Data *data)
+{
+ int numverts = data->M[0].vcount;
+ zero_lfvector(data->F, numverts);
+ init_bfmatrix(data->dFdX, ZERO);
+ init_bfmatrix(data->dFdV, ZERO);
+
+ data->num_blocks = 0;
+}
+
+void BPH_mass_spring_force_reference_frame(Implicit_Data *data, int index, const float acceleration[3], const float omega[3], const float domega_dt[3], float mass)
+{
+#ifdef CLOTH_ROOT_FRAME
+ float acc[3], w[3], dwdt[3];
+ float f[3], dfdx[3][3], dfdv[3][3];
+ float euler[3], coriolis[3], centrifugal[3], rotvel[3];
+ float deuler[3][3], dcoriolis[3][3], dcentrifugal[3][3], drotvel[3][3];
+
+ world_to_root_v3(data, index, acc, acceleration);
+ world_to_root_v3(data, index, w, omega);
+ world_to_root_v3(data, index, dwdt, domega_dt);
+
+ cross_v3_v3v3(euler, dwdt, data->X[index]);
+ cross_v3_v3v3(coriolis, w, data->V[index]);
+ mul_v3_fl(coriolis, 2.0f);
+ cross_v3_v3v3(rotvel, w, data->X[index]);
+ cross_v3_v3v3(centrifugal, w, rotvel);
+
+ sub_v3_v3v3(f, acc, euler);
+ sub_v3_v3(f, coriolis);
+ sub_v3_v3(f, centrifugal);
+
+ mul_v3_fl(f, mass); /* F = m * a */
+
+ cross_v3_identity(deuler, dwdt);
+ cross_v3_identity(dcoriolis, w);
+ mul_m3_fl(dcoriolis, 2.0f);
+ cross_v3_identity(drotvel, w);
+ cross_m3_v3m3(dcentrifugal, w, drotvel);
+
+ add_m3_m3m3(dfdx, deuler, dcentrifugal);
+ negate_m3(dfdx);
+ mul_m3_fl(dfdx, mass);
+
+ copy_m3_m3(dfdv, dcoriolis);
+ negate_m3(dfdv);
+ mul_m3_fl(dfdv, mass);
+
+ add_v3_v3(data->F[index], f);
+ add_m3_m3m3(data->dFdX[index].m, data->dFdX[index].m, dfdx);
+ add_m3_m3m3(data->dFdV[index].m, data->dFdV[index].m, dfdv);
+#else
+ (void)data;
+ (void)index;
+ (void)acceleration;
+ (void)omega;
+ (void)domega_dt;
+#endif
+}
+
+void BPH_mass_spring_force_gravity(Implicit_Data *data, int index, float mass, const float g[3])
+{
+ /* force = mass * acceleration (in this case: gravity) */
+ float f[3];
+ world_to_root_v3(data, index, f, g);
+ mul_v3_fl(f, mass);
+
+ add_v3_v3(data->F[index], f);
+}
+
+void BPH_mass_spring_force_drag(Implicit_Data *data, float drag)
+{
+ int i, numverts = data->M[0].vcount;
+ for (i = 0; i < numverts; i++) {
+ float tmp[3][3];
+
+ /* NB: uses root space velocity, no need to transform */
+ madd_v3_v3fl(data->F[i], data->V[i], -drag);
+
+ copy_m3_m3(tmp, I);
+ mul_m3_fl(tmp, -drag);
+ add_m3_m3m3(data->dFdV[i].m, data->dFdV[i].m, tmp);
+ }
+}
+
+void BPH_mass_spring_force_extern(struct Implicit_Data *data, int i, const float f[3], float dfdx[3][3], float dfdv[3][3])
+{
+ float tf[3], tdfdx[3][3], tdfdv[3][3];
+ world_to_root_v3(data, i, tf, f);
+ world_to_root_m3(data, i, tdfdx, dfdx);
+ world_to_root_m3(data, i, tdfdv, dfdv);
+
+ add_v3_v3(data->F[i], tf);
+ add_m3_m3m3(data->dFdX[i].m, data->dFdX[i].m, tdfdx);
+ add_m3_m3m3(data->dFdV[i].m, data->dFdV[i].m, tdfdv);
+}
+
+static float calc_nor_area_tri(float nor[3], const float v1[3], const float v2[3], const float v3[3])
+{
+ float n1[3], n2[3];
+
+ sub_v3_v3v3(n1, v1, v2);
+ sub_v3_v3v3(n2, v2, v3);
+
+ cross_v3_v3v3(nor, n1, n2);
+ return normalize_v3(nor);
+}
+
+/* XXX does not support force jacobians yet, since the effector system does not provide them either */
+void BPH_mass_spring_force_face_wind(Implicit_Data *data, int v1, int v2, int v3, const float (*winvec)[3])
+{
+ const float effector_scale = 0.02f;
+ float win[3], nor[3], area;
+ float factor;
+
+ /* calculate face normal and area */
+ area = calc_nor_area_tri(nor, data->X[v1], data->X[v2], data->X[v3]);
+ factor = effector_scale * area / 3.0f;
+
+ world_to_root_v3(data, v1, win, winvec[v1]);
+ madd_v3_v3fl(data->F[v1], nor, factor * dot_v3v3(win, nor));
+
+ world_to_root_v3(data, v2, win, winvec[v2]);
+ madd_v3_v3fl(data->F[v2], nor, factor * dot_v3v3(win, nor));
+
+ world_to_root_v3(data, v3, win, winvec[v3]);
+ madd_v3_v3fl(data->F[v3], nor, factor * dot_v3v3(win, nor));
+}
+
+static void edge_wind_vertex(const float dir[3], float length, float radius, const float wind[3], float f[3], float UNUSED(dfdx[3][3]), float UNUSED(dfdv[3][3]))
+{
+ const float density = 0.01f; /* XXX arbitrary value, corresponds to effect of air density */
+ float cos_alpha, sin_alpha, cross_section;
+ float windlen = len_v3(wind);
+
+ if (windlen == 0.0f) {
+ zero_v3(f);
+ return;
+ }
+
+ /* angle of wind direction to edge */
+ cos_alpha = dot_v3v3(wind, dir) / windlen;
+ sin_alpha = sqrtf(1.0f - cos_alpha * cos_alpha);
+ cross_section = radius * ((float)M_PI * radius * sin_alpha + length * cos_alpha);
+
+ mul_v3_v3fl(f, wind, density * cross_section);
+}
+
+void BPH_mass_spring_force_edge_wind(Implicit_Data *data, int v1, int v2, float radius1, float radius2, const float (*winvec)[3])
+{
+ float win[3], dir[3], length;
+ float f[3], dfdx[3][3], dfdv[3][3];
+
+ sub_v3_v3v3(dir, data->X[v1], data->X[v2]);
+ length = normalize_v3(dir);
+
+ world_to_root_v3(data, v1, win, winvec[v1]);
+ edge_wind_vertex(dir, length, radius1, win, f, dfdx, dfdv);
+ add_v3_v3(data->F[v1], f);
+
+ world_to_root_v3(data, v2, win, winvec[v2]);
+ edge_wind_vertex(dir, length, radius2, win, f, dfdx, dfdv);
+ add_v3_v3(data->F[v2], f);
+}
+
+void BPH_mass_spring_force_vertex_wind(Implicit_Data *data, int v, float UNUSED(radius), const float (*winvec)[3])
+{
+ const float density = 0.01f; /* XXX arbitrary value, corresponds to effect of air density */
+
+ float wind[3];
+ float f[3];
+
+ world_to_root_v3(data, v, wind, winvec[v]);
+ mul_v3_v3fl(f, wind, density);
+ add_v3_v3(data->F[v], f);
+}
+
+BLI_INLINE void dfdx_spring(float to[3][3], const float dir[3], float length, float L, float k)
+{
+ // dir is unit length direction, rest is spring's restlength, k is spring constant.
+ //return ( (I-outerprod(dir, dir))*Min(1.0f, rest/length) - I) * -k;
+ outerproduct(to, dir, dir);
+ sub_m3_m3m3(to, I, to);
+
+ mul_m3_fl(to, (L/length));
+ sub_m3_m3m3(to, to, I);
+ mul_m3_fl(to, k);
+}
+
+/* unused */
+#if 0
+BLI_INLINE void dfdx_damp(float to[3][3], const float dir[3], float length, const float vel[3], float rest, float damping)
+{
+ // inner spring damping vel is the relative velocity of the endpoints.
+ // return (I-outerprod(dir, dir)) * (-damping * -(dot(dir, vel)/Max(length, rest)));
+ mul_fvectorT_fvector(to, dir, dir);
+ sub_fmatrix_fmatrix(to, I, to);
+ mul_fmatrix_S(to, (-damping * -(dot_v3v3(dir, vel)/MAX2(length, rest))));
+}
+#endif
+
+BLI_INLINE void dfdv_damp(float to[3][3], const float dir[3], float damping)
+{
+ // derivative of force wrt velocity
+ outerproduct(to, dir, dir);
+ mul_m3_fl(to, -damping);
+}
+
+BLI_INLINE float fb(float length, float L)
+{
+ float x = length / L;
+ float xx = x * x;
+ float xxx = xx * x;
+ float xxxx = xxx * x;
+ return (-11.541f * xxxx + 34.193f * xxx - 39.083f * xx + 23.116f * x - 9.713f);
+}
+
+BLI_INLINE float fbderiv(float length, float L)
+{
+ float x = length/L;
+ float xx = x * x;
+ float xxx = xx * x;
+ return (-46.164f * xxx + 102.579f * xx - 78.166f * x + 23.116f);
+}
+
+BLI_INLINE float fbstar(float length, float L, float kb, float cb)
+{
+ float tempfb_fl = kb * fb(length, L);
+ float fbstar_fl = cb * (length - L);
+
+ if (tempfb_fl < fbstar_fl)
+ return fbstar_fl;
+ else
+ return tempfb_fl;
+}
+
+// function to calculae bending spring force (taken from Choi & Co)
+BLI_INLINE float fbstar_jacobi(float length, float L, float kb, float cb)
+{
+ float tempfb_fl = kb * fb(length, L);
+ float fbstar_fl = cb * (length - L);
+
+ if (tempfb_fl < fbstar_fl) {
+ return -cb;
+ }
+ else {
+ return -kb * fbderiv(length, L);
+ }
+}
+
+/* calculate elonglation */
+BLI_INLINE bool spring_length(Implicit_Data *data, int i, int j, float r_extent[3], float r_dir[3], float *r_length, float r_vel[3])
+{
+ sub_v3_v3v3(r_extent, data->X[j], data->X[i]);
+ sub_v3_v3v3(r_vel, data->V[j], data->V[i]);
+ *r_length = len_v3(r_extent);
+
+ if (*r_length > ALMOST_ZERO) {
+ /*
+ if (length>L) {
+ if ((clmd->sim_parms->flags & CSIMSETT_FLAG_TEARING_ENABLED) &&
+ ( ((length-L)*100.0f/L) > clmd->sim_parms->maxspringlen )) {
+ // cut spring!
+ s->flags |= CSPRING_FLAG_DEACTIVATE;
+ return false;
+ }
+ }
+ */
+ mul_v3_v3fl(r_dir, r_extent, 1.0f/(*r_length));
+ }
+ else {
+ zero_v3(r_dir);
+ }
+
+ return true;
+}
+
+BLI_INLINE void apply_spring(Implicit_Data *data, int i, int j, const float f[3], float dfdx[3][3], float dfdv[3][3])
+{
+ int block_ij = BPH_mass_spring_add_block(data, i, j);
+
+ add_v3_v3(data->F[i], f);
+ sub_v3_v3(data->F[j], f);
+
+ add_m3_m3m3(data->dFdX[i].m, data->dFdX[i].m, dfdx);
+ add_m3_m3m3(data->dFdX[j].m, data->dFdX[j].m, dfdx);
+ sub_m3_m3m3(data->dFdX[block_ij].m, data->dFdX[block_ij].m, dfdx);
+
+ add_m3_m3m3(data->dFdV[i].m, data->dFdV[i].m, dfdv);
+ add_m3_m3m3(data->dFdV[j].m, data->dFdV[j].m, dfdv);
+ sub_m3_m3m3(data->dFdV[block_ij].m, data->dFdV[block_ij].m, dfdv);
+}
+
+bool BPH_mass_spring_force_spring_linear(Implicit_Data *data, int i, int j, float restlen,
+ float stiffness, float damping, bool no_compress, float clamp_force,
+ float r_f[3], float r_dfdx[3][3], float r_dfdv[3][3])
+{
+ float extent[3], length, dir[3], vel[3];
+
+ // calculate elonglation
+ spring_length(data, i, j, extent, dir, &length, vel);
+
+ if (length > restlen || no_compress) {
+ float stretch_force, f[3], dfdx[3][3], dfdv[3][3];
+
+ stretch_force = stiffness * (length - restlen);
+ if (clamp_force > 0.0f && stretch_force > clamp_force) {
+ stretch_force = clamp_force;
+ }
+ mul_v3_v3fl(f, dir, stretch_force);
+
+ // Ascher & Boxman, p.21: Damping only during elonglation
+ // something wrong with it...
+ madd_v3_v3fl(f, dir, damping * dot_v3v3(vel, dir));
+
+ dfdx_spring(dfdx, dir, length, restlen, stiffness);
+ dfdv_damp(dfdv, dir, damping);
+
+ apply_spring(data, i, j, f, dfdx, dfdv);
+
+ if (r_f) copy_v3_v3(r_f, f);
+ if (r_dfdx) copy_m3_m3(r_dfdx, dfdx);
+ if (r_dfdv) copy_m3_m3(r_dfdv, dfdv);
+
+ return true;
+ }
+ else {
+ if (r_f) zero_v3(r_f);
+ if (r_dfdx) zero_m3(r_dfdx);
+ if (r_dfdv) zero_m3(r_dfdv);
+
+ return false;
+ }
+}
+
+/* See "Stable but Responsive Cloth" (Choi, Ko 2005) */
+bool BPH_mass_spring_force_spring_bending(Implicit_Data *data, int i, int j, float restlen,
+ float kb, float cb,
+ float r_f[3], float r_dfdx[3][3], float r_dfdv[3][3])
+{
+ float extent[3], length, dir[3], vel[3];
+
+ // calculate elonglation
+ spring_length(data, i, j, extent, dir, &length, vel);
+
+ if (length < restlen) {
+ float f[3], dfdx[3][3], dfdv[3][3];
+
+ mul_v3_v3fl(f, dir, fbstar(length, restlen, kb, cb));
+
+ outerproduct(dfdx, dir, dir);
+ mul_m3_fl(dfdx, fbstar_jacobi(length, restlen, kb, cb));
+
+ /* XXX damping not supported */
+ zero_m3(dfdv);
+
+ apply_spring(data, i, j, f, dfdx, dfdv);
+
+ if (r_f) copy_v3_v3(r_f, f);
+ if (r_dfdx) copy_m3_m3(r_dfdx, dfdx);
+ if (r_dfdv) copy_m3_m3(r_dfdv, dfdv);
+
+ return true;
+ }
+ else {
+ if (r_f) zero_v3(r_f);
+ if (r_dfdx) zero_m3(r_dfdx);
+ if (r_dfdv) zero_m3(r_dfdv);
+
+ return false;
+ }
+}
+
+/* Jacobian of a direction vector.
+ * Basically the part of the differential orthogonal to the direction,
+ * inversely proportional to the length of the edge.
+ *
+ * dD_ij/dx_i = -dD_ij/dx_j = (D_ij * D_ij^T - I) / len_ij
+ */
+BLI_INLINE void spring_grad_dir(Implicit_Data *data, int i, int j, float edge[3], float dir[3], float grad_dir[3][3])
+{
+ float length;
+
+ sub_v3_v3v3(edge, data->X[j], data->X[i]);
+ length = normalize_v3_v3(dir, edge);
+
+ if (length > ALMOST_ZERO) {
+ outerproduct(grad_dir, dir, dir);
+ sub_m3_m3m3(grad_dir, I, grad_dir);
+ mul_m3_fl(grad_dir, 1.0f / length);
+ }
+ else {
+ zero_m3(grad_dir);
+ }
+}
+
+BLI_INLINE void spring_angbend_forces(Implicit_Data *data, int i, int j, int k,
+ const float goal[3],
+ float stiffness, float damping,
+ int q, const float dx[3], const float dv[3],
+ float r_f[3])
+{
+ float edge_ij[3], dir_ij[3];
+ float edge_jk[3], dir_jk[3];
+ float vel_ij[3], vel_jk[3], vel_ortho[3];
+ float f_bend[3], f_damp[3];
+ float fk[3];
+ float dist[3];
+
+ zero_v3(fk);
+
+ sub_v3_v3v3(edge_ij, data->X[j], data->X[i]);
+ if (q == i) sub_v3_v3(edge_ij, dx);
+ if (q == j) add_v3_v3(edge_ij, dx);
+ normalize_v3_v3(dir_ij, edge_ij);
+
+ sub_v3_v3v3(edge_jk, data->X[k], data->X[j]);
+ if (q == j) sub_v3_v3(edge_jk, dx);
+ if (q == k) add_v3_v3(edge_jk, dx);
+ normalize_v3_v3(dir_jk, edge_jk);
+
+ sub_v3_v3v3(vel_ij, data->V[j], data->V[i]);
+ if (q == i) sub_v3_v3(vel_ij, dv);
+ if (q == j) add_v3_v3(vel_ij, dv);
+
+ sub_v3_v3v3(vel_jk, data->V[k], data->V[j]);
+ if (q == j) sub_v3_v3(vel_jk, dv);
+ if (q == k) add_v3_v3(vel_jk, dv);
+
+ /* bending force */
+ sub_v3_v3v3(dist, goal, edge_jk);
+ mul_v3_v3fl(f_bend, dist, stiffness);
+
+ add_v3_v3(fk, f_bend);
+
+ /* damping force */
+ madd_v3_v3v3fl(vel_ortho, vel_jk, dir_jk, -dot_v3v3(vel_jk, dir_jk));
+ mul_v3_v3fl(f_damp, vel_ortho, damping);
+
+ sub_v3_v3(fk, f_damp);
+
+ copy_v3_v3(r_f, fk);
+}
+
+/* Finite Differences method for estimating the jacobian of the force */
+BLI_INLINE void spring_angbend_estimate_dfdx(Implicit_Data *data, int i, int j, int k,
+ const float goal[3],
+ float stiffness, float damping,
+ int q, float dfdx[3][3])
+{
+ const float delta = 0.00001f; // TODO find a good heuristic for this
+ float dvec_null[3][3], dvec_pos[3][3], dvec_neg[3][3];
+ float f[3];
+ int a, b;
+
+ zero_m3(dvec_null);
+ unit_m3(dvec_pos);
+ mul_m3_fl(dvec_pos, delta * 0.5f);
+ copy_m3_m3(dvec_neg, dvec_pos);
+ negate_m3(dvec_neg);
+
+ /* XXX TODO offset targets to account for position dependency */
+
+ for (a = 0; a < 3; ++a) {
+ spring_angbend_forces(data, i, j, k, goal, stiffness, damping,
+ q, dvec_pos[a], dvec_null[a], f);
+ copy_v3_v3(dfdx[a], f);
+
+ spring_angbend_forces(data, i, j, k, goal, stiffness, damping,
+ q, dvec_neg[a], dvec_null[a], f);
+ sub_v3_v3(dfdx[a], f);
+
+ for (b = 0; b < 3; ++b) {
+ dfdx[a][b] /= delta;
+ }
+ }
+}
+
+/* Finite Differences method for estimating the jacobian of the force */
+BLI_INLINE void spring_angbend_estimate_dfdv(Implicit_Data *data, int i, int j, int k,
+ const float goal[3],
+ float stiffness, float damping,
+ int q, float dfdv[3][3])
+{
+ const float delta = 0.00001f; // TODO find a good heuristic for this
+ float dvec_null[3][3], dvec_pos[3][3], dvec_neg[3][3];
+ float f[3];
+ int a, b;
+
+ zero_m3(dvec_null);
+ unit_m3(dvec_pos);
+ mul_m3_fl(dvec_pos, delta * 0.5f);
+ copy_m3_m3(dvec_neg, dvec_pos);
+ negate_m3(dvec_neg);
+
+ /* XXX TODO offset targets to account for position dependency */
+
+ for (a = 0; a < 3; ++a) {
+ spring_angbend_forces(data, i, j, k, goal, stiffness, damping,
+ q, dvec_null[a], dvec_pos[a], f);
+ copy_v3_v3(dfdv[a], f);
+
+ spring_angbend_forces(data, i, j, k, goal, stiffness, damping,
+ q, dvec_null[a], dvec_neg[a], f);
+ sub_v3_v3(dfdv[a], f);
+
+ for (b = 0; b < 3; ++b) {
+ dfdv[a][b] /= delta;
+ }
+ }
+}
+
+/* Angular spring that pulls the vertex toward the local target
+ * See "Artistic Simulation of Curly Hair" (Pixar technical memo #12-03a)
+ */
+bool BPH_mass_spring_force_spring_bending_angular(Implicit_Data *data, int i, int j, int k,
+ const float target[3], float stiffness, float damping)
+{
+ float goal[3];
+ float fj[3], fk[3];
+ float dfj_dxi[3][3], dfj_dxj[3][3], dfk_dxi[3][3], dfk_dxj[3][3], dfk_dxk[3][3];
+ float dfj_dvi[3][3], dfj_dvj[3][3], dfk_dvi[3][3], dfk_dvj[3][3], dfk_dvk[3][3];
+
+ const float vecnull[3] = {0.0f, 0.0f, 0.0f};
+
+ int block_ij = BPH_mass_spring_add_block(data, i, j);
+ int block_jk = BPH_mass_spring_add_block(data, j, k);
+ int block_ik = BPH_mass_spring_add_block(data, i, k);
+
+ world_to_root_v3(data, j, goal, target);
+
+ spring_angbend_forces(data, i, j, k, goal, stiffness, damping, k, vecnull, vecnull, fk);
+ negate_v3_v3(fj, fk); /* counterforce */
+
+ spring_angbend_estimate_dfdx(data, i, j, k, goal, stiffness, damping, i, dfk_dxi);
+ spring_angbend_estimate_dfdx(data, i, j, k, goal, stiffness, damping, j, dfk_dxj);
+ spring_angbend_estimate_dfdx(data, i, j, k, goal, stiffness, damping, k, dfk_dxk);
+ copy_m3_m3(dfj_dxi, dfk_dxi); negate_m3(dfj_dxi);
+ copy_m3_m3(dfj_dxj, dfk_dxj); negate_m3(dfj_dxj);
+
+ spring_angbend_estimate_dfdv(data, i, j, k, goal, stiffness, damping, i, dfk_dvi);
+ spring_angbend_estimate_dfdv(data, i, j, k, goal, stiffness, damping, j, dfk_dvj);
+ spring_angbend_estimate_dfdv(data, i, j, k, goal, stiffness, damping, k, dfk_dvk);
+ copy_m3_m3(dfj_dvi, dfk_dvi); negate_m3(dfj_dvi);
+ copy_m3_m3(dfj_dvj, dfk_dvj); negate_m3(dfj_dvj);
+
+ /* add forces and jacobians to the solver data */
+
+ add_v3_v3(data->F[j], fj);
+ add_v3_v3(data->F[k], fk);
+
+ add_m3_m3m3(data->dFdX[j].m, data->dFdX[j].m, dfj_dxj);
+ add_m3_m3m3(data->dFdX[k].m, data->dFdX[k].m, dfk_dxk);
+
+ add_m3_m3m3(data->dFdX[block_ij].m, data->dFdX[block_ij].m, dfj_dxi);
+ add_m3_m3m3(data->dFdX[block_jk].m, data->dFdX[block_jk].m, dfk_dxj);
+ add_m3_m3m3(data->dFdX[block_ik].m, data->dFdX[block_ik].m, dfk_dxi);
+
+ add_m3_m3m3(data->dFdV[j].m, data->dFdV[j].m, dfj_dvj);
+ add_m3_m3m3(data->dFdV[k].m, data->dFdV[k].m, dfk_dvk);
+
+ add_m3_m3m3(data->dFdV[block_ij].m, data->dFdV[block_ij].m, dfj_dvi);
+ add_m3_m3m3(data->dFdV[block_jk].m, data->dFdV[block_jk].m, dfk_dvj);
+ add_m3_m3m3(data->dFdV[block_ik].m, data->dFdV[block_ik].m, dfk_dvi);
+
+
+ /* XXX analytical calculation of derivatives below is incorrect.
+ * This proved to be difficult, but for now just using the finite difference method for
+ * estimating the jacobians should be sufficient.
+ */
+#if 0
+ float edge_ij[3], dir_ij[3], grad_dir_ij[3][3];
+ float edge_jk[3], dir_jk[3], grad_dir_jk[3][3];
+ float dist[3], vel_jk[3], vel_jk_ortho[3], projvel[3];
+ float target[3];
+ float tmp[3][3];
+ float fi[3], fj[3], fk[3];
+ float dfi_dxi[3][3], dfj_dxi[3][3], dfj_dxj[3][3], dfk_dxi[3][3], dfk_dxj[3][3], dfk_dxk[3][3];
+ float dfdvi[3][3];
+
+ // TESTING
+ damping = 0.0f;
+
+ zero_v3(fi);
+ zero_v3(fj);
+ zero_v3(fk);
+ zero_m3(dfi_dxi);
+ zero_m3(dfj_dxi);
+ zero_m3(dfk_dxi);
+ zero_m3(dfk_dxj);
+ zero_m3(dfk_dxk);
+
+ /* jacobian of direction vectors */
+ spring_grad_dir(data, i, j, edge_ij, dir_ij, grad_dir_ij);
+ spring_grad_dir(data, j, k, edge_jk, dir_jk, grad_dir_jk);
+
+ sub_v3_v3v3(vel_jk, data->V[k], data->V[j]);
+
+ /* bending force */
+ mul_v3_v3fl(target, dir_ij, restlen);
+ sub_v3_v3v3(dist, target, edge_jk);
+ mul_v3_v3fl(fk, dist, stiffness);
+
+ /* damping force */
+ madd_v3_v3v3fl(vel_jk_ortho, vel_jk, dir_jk, -dot_v3v3(vel_jk, dir_jk));
+ madd_v3_v3fl(fk, vel_jk_ortho, damping);
+
+ /* XXX this only holds true as long as we assume straight rest shape!
+ * eventually will become a bit more involved since the opposite segment
+ * gets its own target, under condition of having equal torque on both sides.
+ */
+ copy_v3_v3(fi, fk);
+
+ /* counterforce on the middle point */
+ sub_v3_v3(fj, fi);
+ sub_v3_v3(fj, fk);
+
+ /* === derivatives === */
+
+ madd_m3_m3fl(dfk_dxi, grad_dir_ij, stiffness * restlen);
+
+ madd_m3_m3fl(dfk_dxj, grad_dir_ij, -stiffness * restlen);
+ madd_m3_m3fl(dfk_dxj, I, stiffness);
+
+ madd_m3_m3fl(dfk_dxk, I, -stiffness);
+
+ copy_m3_m3(dfi_dxi, dfk_dxk);
+ negate_m3(dfi_dxi);
+
+ /* dfj_dfi == dfi_dfj due to symmetry,
+ * dfi_dfj == dfk_dfj due to fi == fk
+ * XXX see comment above on future bent rest shapes
+ */
+ copy_m3_m3(dfj_dxi, dfk_dxj);
+
+ /* dfj_dxj == -(dfi_dxj + dfk_dxj) due to fj == -(fi + fk) */
+ sub_m3_m3m3(dfj_dxj, dfj_dxj, dfj_dxi);
+ sub_m3_m3m3(dfj_dxj, dfj_dxj, dfk_dxj);
+
+ /* add forces and jacobians to the solver data */
+ add_v3_v3(data->F[i], fi);
+ add_v3_v3(data->F[j], fj);
+ add_v3_v3(data->F[k], fk);
+
+ add_m3_m3m3(data->dFdX[i].m, data->dFdX[i].m, dfi_dxi);
+ add_m3_m3m3(data->dFdX[j].m, data->dFdX[j].m, dfj_dxj);
+ add_m3_m3m3(data->dFdX[k].m, data->dFdX[k].m, dfk_dxk);
+
+ add_m3_m3m3(data->dFdX[block_ij].m, data->dFdX[block_ij].m, dfj_dxi);
+ add_m3_m3m3(data->dFdX[block_jk].m, data->dFdX[block_jk].m, dfk_dxj);
+ add_m3_m3m3(data->dFdX[block_ik].m, data->dFdX[block_ik].m, dfk_dxi);
+#endif
+
+ return true;
+}
+
+bool BPH_mass_spring_force_spring_goal(Implicit_Data *data, int i, const float goal_x[3], const float goal_v[3],
+ float stiffness, float damping,
+ float r_f[3], float r_dfdx[3][3], float r_dfdv[3][3])
+{
+ float root_goal_x[3], root_goal_v[3], extent[3], length, dir[3], vel[3];
+ float f[3], dfdx[3][3], dfdv[3][3];
+
+ /* goal is in world space */
+ world_to_root_v3(data, i, root_goal_x, goal_x);
+ world_to_root_v3(data, i, root_goal_v, goal_v);
+
+ sub_v3_v3v3(extent, root_goal_x, data->X[i]);
+ sub_v3_v3v3(vel, root_goal_v, data->V[i]);
+ length = normalize_v3_v3(dir, extent);
+
+ if (length > ALMOST_ZERO) {
+ mul_v3_v3fl(f, dir, stiffness * length);
+
+ // Ascher & Boxman, p.21: Damping only during elonglation
+ // something wrong with it...
+ madd_v3_v3fl(f, dir, damping * dot_v3v3(vel, dir));
+
+ dfdx_spring(dfdx, dir, length, 0.0f, stiffness);
+ dfdv_damp(dfdv, dir, damping);
+
+ add_v3_v3(data->F[i], f);
+ add_m3_m3m3(data->dFdX[i].m, data->dFdX[i].m, dfdx);
+ add_m3_m3m3(data->dFdV[i].m, data->dFdV[i].m, dfdv);
+
+ if (r_f) copy_v3_v3(r_f, f);
+ if (r_dfdx) copy_m3_m3(r_dfdx, dfdx);
+ if (r_dfdv) copy_m3_m3(r_dfdv, dfdv);
+
+ return true;
+ }
+ else {
+ if (r_f) zero_v3(r_f);
+ if (r_dfdx) zero_m3(r_dfdx);
+ if (r_dfdv) zero_m3(r_dfdv);
+
+ return false;
+ }
+}
+
+#endif /* IMPLICIT_SOLVER_BLENDER */
diff --git a/source/blender/physics/intern/implicit_eigen.cpp b/source/blender/physics/intern/implicit_eigen.cpp
new file mode 100644
index 00000000000..64a75083f72
--- /dev/null
+++ b/source/blender/physics/intern/implicit_eigen.cpp
@@ -0,0 +1,1346 @@
+/*
+ * ***** 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) Blender Foundation
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Lukas Toenne
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/physics/intern/implicit_eigen.cpp
+ * \ingroup bph
+ */
+
+#include "implicit.h"
+
+#ifdef IMPLICIT_SOLVER_EIGEN
+
+//#define USE_EIGEN_CORE
+#define USE_EIGEN_CONSTRAINED_CG
+
+#ifdef __GNUC__
+# pragma GCC diagnostic push
+/* XXX suppress verbose warnings in eigen */
+# pragma GCC diagnostic ignored "-Wlogical-op"
+#endif
+
+#ifndef IMPLICIT_ENABLE_EIGEN_DEBUG
+#ifdef NDEBUG
+#define IMPLICIT_NDEBUG
+#endif
+#define NDEBUG
+#endif
+
+#include <Eigen/Sparse>
+#include <Eigen/src/Core/util/DisableStupidWarnings.h>
+
+#ifdef USE_EIGEN_CONSTRAINED_CG
+#include <intern/ConstrainedConjugateGradient.h>
+#endif
+
+#ifndef IMPLICIT_ENABLE_EIGEN_DEBUG
+#ifndef IMPLICIT_NDEBUG
+#undef NDEBUG
+#else
+#undef IMPLICIT_NDEBUG
+#endif
+#endif
+
+#ifdef __GNUC__
+# pragma GCC diagnostic pop
+#endif
+
+#include "MEM_guardedalloc.h"
+
+extern "C" {
+#include "DNA_scene_types.h"
+#include "DNA_object_types.h"
+#include "DNA_object_force.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_texture_types.h"
+
+#include "BLI_math.h"
+#include "BLI_linklist.h"
+#include "BLI_utildefines.h"
+
+#include "BKE_cloth.h"
+#include "BKE_collision.h"
+#include "BKE_effect.h"
+#include "BKE_global.h"
+
+#include "BPH_mass_spring.h"
+}
+
+typedef float Scalar;
+
+static float I[3][3] = {{1, 0, 0}, {0, 1, 0}, {0, 0, 1}};
+
+/* slightly extended Eigen vector class
+ * with conversion to/from plain C float array
+ */
+class fVector : public Eigen::Vector3f {
+public:
+ typedef float *ctype;
+
+ fVector()
+ {
+ }
+
+ fVector(const ctype &v)
+ {
+ for (int k = 0; k < 3; ++k)
+ coeffRef(k) = v[k];
+ }
+
+ fVector& operator = (const ctype &v)
+ {
+ for (int k = 0; k < 3; ++k)
+ coeffRef(k) = v[k];
+ return *this;
+ }
+
+ operator ctype()
+ {
+ return data();
+ }
+};
+
+/* slightly extended Eigen matrix class
+ * with conversion to/from plain C float array
+ */
+class fMatrix : public Eigen::Matrix3f {
+public:
+ typedef float (*ctype)[3];
+
+ fMatrix()
+ {
+ }
+
+ fMatrix(const ctype &v)
+ {
+ for (int k = 0; k < 3; ++k)
+ for (int l = 0; l < 3; ++l)
+ coeffRef(l, k) = v[k][l];
+ }
+
+ fMatrix& operator = (const ctype &v)
+ {
+ for (int k = 0; k < 3; ++k)
+ for (int l = 0; l < 3; ++l)
+ coeffRef(l, k) = v[k][l];
+ return *this;
+ }
+
+ operator ctype()
+ {
+ return (ctype)data();
+ }
+};
+
+/* Extension of dense Eigen vectors,
+ * providing 3-float block access for blenlib math functions
+ */
+class lVector : public Eigen::VectorXf {
+public:
+ typedef Eigen::VectorXf base_t;
+
+ lVector()
+ {
+ }
+
+ template <typename T>
+ lVector& operator = (T rhs)
+ {
+ base_t::operator=(rhs);
+ return *this;
+ }
+
+ float* v3(int vertex)
+ {
+ return &coeffRef(3 * vertex);
+ }
+
+ const float* v3(int vertex) const
+ {
+ return &coeffRef(3 * vertex);
+ }
+};
+
+typedef Eigen::Triplet<Scalar> Triplet;
+typedef std::vector<Triplet> TripletList;
+
+typedef Eigen::SparseMatrix<Scalar> lMatrix;
+
+/* Constructor type that provides more convenient handling of Eigen triplets
+ * for efficient construction of sparse 3x3 block matrices.
+ * This should be used for building lMatrix instead of writing to such lMatrix directly (which is very inefficient).
+ * After all elements have been defined using the set() method, the actual matrix can be filled using construct().
+ */
+struct lMatrixCtor {
+ lMatrixCtor()
+ {
+ }
+
+ void reset()
+ {
+ m_trips.clear();
+ }
+
+ void reserve(int numverts)
+ {
+ /* reserve for diagonal entries */
+ m_trips.reserve(numverts * 9);
+ }
+
+ void add(int i, int j, const fMatrix &m)
+ {
+ i *= 3;
+ j *= 3;
+ for (int k = 0; k < 3; ++k)
+ for (int l = 0; l < 3; ++l)
+ m_trips.push_back(Triplet(i + k, j + l, m.coeff(l, k)));
+ }
+
+ void sub(int i, int j, const fMatrix &m)
+ {
+ i *= 3;
+ j *= 3;
+ for (int k = 0; k < 3; ++k)
+ for (int l = 0; l < 3; ++l)
+ m_trips.push_back(Triplet(i + k, j + l, -m.coeff(l, k)));
+ }
+
+ inline void construct(lMatrix &m)
+ {
+ m.setFromTriplets(m_trips.begin(), m_trips.end());
+ m_trips.clear();
+ }
+
+private:
+ TripletList m_trips;
+};
+
+#ifdef USE_EIGEN_CORE
+typedef Eigen::ConjugateGradient<lMatrix, Eigen::Lower, Eigen::DiagonalPreconditioner<Scalar> > ConjugateGradient;
+#endif
+#ifdef USE_EIGEN_CONSTRAINED_CG
+typedef Eigen::ConstrainedConjugateGradient<lMatrix, Eigen::Lower, lMatrix,
+ Eigen::DiagonalPreconditioner<Scalar> >
+ ConstraintConjGrad;
+#endif
+using Eigen::ComputationInfo;
+
+static void print_lvector(const lVector &v)
+{
+ for (int i = 0; i < v.rows(); ++i) {
+ if (i > 0 && i % 3 == 0)
+ printf("\n");
+
+ printf("%f,\n", v[i]);
+ }
+}
+
+static void print_lmatrix(const lMatrix &m)
+{
+ for (int j = 0; j < m.rows(); ++j) {
+ if (j > 0 && j % 3 == 0)
+ printf("\n");
+
+ for (int i = 0; i < m.cols(); ++i) {
+ if (i > 0 && i % 3 == 0)
+ printf(" ");
+
+ implicit_print_matrix_elem(m.coeff(j, i));
+ }
+ printf("\n");
+ }
+}
+
+BLI_INLINE void lMatrix_reserve_elems(lMatrix &m, int num)
+{
+ m.reserve(Eigen::VectorXi::Constant(m.cols(), num));
+}
+
+BLI_INLINE float *lVector_v3(lVector &v, int vertex)
+{
+ return v.data() + 3 * vertex;
+}
+
+BLI_INLINE const float *lVector_v3(const lVector &v, int vertex)
+{
+ return v.data() + 3 * vertex;
+}
+
+#if 0
+BLI_INLINE void triplets_m3(TripletList &tlist, float m[3][3], int i, int j)
+{
+ i *= 3;
+ j *= 3;
+ for (int l = 0; l < 3; ++l) {
+ for (int k = 0; k < 3; ++k) {
+ tlist.push_back(Triplet(i + k, j + l, m[k][l]));
+ }
+ }
+}
+
+BLI_INLINE void triplets_m3fl(TripletList &tlist, float m[3][3], int i, int j, float factor)
+{
+ i *= 3;
+ j *= 3;
+ for (int l = 0; l < 3; ++l) {
+ for (int k = 0; k < 3; ++k) {
+ tlist.push_back(Triplet(i + k, j + l, m[k][l] * factor));
+ }
+ }
+}
+
+BLI_INLINE void lMatrix_add_triplets(lMatrix &r, const TripletList &tlist)
+{
+ lMatrix t(r.rows(), r.cols());
+ t.setFromTriplets(tlist.begin(), tlist.end());
+ r += t;
+}
+
+BLI_INLINE void lMatrix_madd_triplets(lMatrix &r, const TripletList &tlist, float f)
+{
+ lMatrix t(r.rows(), r.cols());
+ t.setFromTriplets(tlist.begin(), tlist.end());
+ r += f * t;
+}
+
+BLI_INLINE void lMatrix_sub_triplets(lMatrix &r, const TripletList &tlist)
+{
+ lMatrix t(r.rows(), r.cols());
+ t.setFromTriplets(tlist.begin(), tlist.end());
+ r -= t;
+}
+#endif
+
+BLI_INLINE void outerproduct(float r[3][3], const float a[3], const float b[3])
+{
+ mul_v3_v3fl(r[0], a, b[0]);
+ mul_v3_v3fl(r[1], a, b[1]);
+ mul_v3_v3fl(r[2], a, b[2]);
+}
+
+BLI_INLINE void cross_m3_v3m3(float r[3][3], const float v[3], float m[3][3])
+{
+ cross_v3_v3v3(r[0], v, m[0]);
+ cross_v3_v3v3(r[1], v, m[1]);
+ cross_v3_v3v3(r[2], v, m[2]);
+}
+
+BLI_INLINE void cross_v3_identity(float r[3][3], const float v[3])
+{
+ r[0][0] = 0.0f; r[1][0] = v[2]; r[2][0] = -v[1];
+ r[0][1] = -v[2]; r[1][1] = 0.0f; r[2][1] = v[0];
+ r[0][2] = v[1]; r[1][2] = -v[0]; r[2][2] = 0.0f;
+}
+
+BLI_INLINE void madd_m3_m3fl(float r[3][3], float m[3][3], float f)
+{
+ r[0][0] += m[0][0] * f;
+ r[0][1] += m[0][1] * f;
+ r[0][2] += m[0][2] * f;
+ r[1][0] += m[1][0] * f;
+ r[1][1] += m[1][1] * f;
+ r[1][2] += m[1][2] * f;
+ r[2][0] += m[2][0] * f;
+ r[2][1] += m[2][1] * f;
+ r[2][2] += m[2][2] * f;
+}
+
+BLI_INLINE void madd_m3_m3m3fl(float r[3][3], float a[3][3], float b[3][3], float f)
+{
+ r[0][0] = a[0][0] + b[0][0] * f;
+ r[0][1] = a[0][1] + b[0][1] * f;
+ r[0][2] = a[0][2] + b[0][2] * f;
+ r[1][0] = a[1][0] + b[1][0] * f;
+ r[1][1] = a[1][1] + b[1][1] * f;
+ r[1][2] = a[1][2] + b[1][2] * f;
+ r[2][0] = a[2][0] + b[2][0] * f;
+ r[2][1] = a[2][1] + b[2][1] * f;
+ r[2][2] = a[2][2] + b[2][2] * f;
+}
+
+struct Implicit_Data {
+ typedef std::vector<fMatrix> fMatrixVector;
+
+ Implicit_Data(int numverts)
+ {
+ resize(numverts);
+ }
+
+ void resize(int numverts)
+ {
+ this->numverts = numverts;
+ int tot = 3 * numverts;
+
+ M.resize(tot, tot);
+ F.resize(tot);
+ dFdX.resize(tot, tot);
+ dFdV.resize(tot, tot);
+
+ tfm.resize(numverts, I);
+
+ X.resize(tot);
+ Xnew.resize(tot);
+ V.resize(tot);
+ Vnew.resize(tot);
+
+ A.resize(tot, tot);
+ B.resize(tot);
+
+ dV.resize(tot);
+ z.resize(tot);
+ S.resize(tot, tot);
+
+ iM.reserve(numverts);
+ idFdX.reserve(numverts);
+ idFdV.reserve(numverts);
+ iS.reserve(numverts);
+ }
+
+ int numverts;
+
+ /* inputs */
+ lMatrix M; /* masses */
+ lVector F; /* forces */
+ lMatrix dFdX, dFdV; /* force jacobians */
+
+ fMatrixVector tfm; /* local coordinate transform */
+
+ /* motion state data */
+ lVector X, Xnew; /* positions */
+ lVector V, Vnew; /* velocities */
+
+ /* internal solver data */
+ lVector B; /* B for A*dV = B */
+ lMatrix A; /* A for A*dV = B */
+
+ lVector dV; /* velocity change (solution of A*dV = B) */
+ lVector z; /* target velocity in constrained directions */
+ lMatrix S; /* filtering matrix for constraints */
+
+ /* temporary constructors */
+ lMatrixCtor iM; /* masses */
+ lMatrixCtor idFdX, idFdV; /* force jacobians */
+ lMatrixCtor iS; /* filtering matrix for constraints */
+};
+
+Implicit_Data *BPH_mass_spring_solver_create(int numverts, int numsprings)
+{
+ Implicit_Data *id = new Implicit_Data(numverts);
+ return id;
+}
+
+void BPH_mass_spring_solver_free(Implicit_Data *id)
+{
+ if (id)
+ delete id;
+}
+
+int BPH_mass_spring_solver_numvert(Implicit_Data *id)
+{
+ if (id)
+ return id->numverts;
+ else
+ return 0;
+}
+
+/* ==== Transformation from/to root reference frames ==== */
+
+BLI_INLINE void world_to_root_v3(Implicit_Data *data, int index, float r[3], const float v[3])
+{
+ copy_v3_v3(r, v);
+ mul_transposed_m3_v3(data->tfm[index], r);
+}
+
+BLI_INLINE void root_to_world_v3(Implicit_Data *data, int index, float r[3], const float v[3])
+{
+ mul_v3_m3v3(r, data->tfm[index], v);
+}
+
+BLI_INLINE void world_to_root_m3(Implicit_Data *data, int index, float r[3][3], float m[3][3])
+{
+ float trot[3][3];
+ copy_m3_m3(trot, data->tfm[index]);
+ transpose_m3(trot);
+ mul_m3_m3m3(r, trot, m);
+}
+
+BLI_INLINE void root_to_world_m3(Implicit_Data *data, int index, float r[3][3], float m[3][3])
+{
+ mul_m3_m3m3(r, data->tfm[index], m);
+}
+
+/* ================================ */
+
+bool BPH_mass_spring_solve_velocities(Implicit_Data *data, float dt, ImplicitSolverResult *result)
+{
+#ifdef USE_EIGEN_CORE
+ typedef ConjugateGradient solver_t;
+#endif
+#ifdef USE_EIGEN_CONSTRAINED_CG
+ typedef ConstraintConjGrad solver_t;
+#endif
+
+ data->iM.construct(data->M);
+ data->idFdX.construct(data->dFdX);
+ data->idFdV.construct(data->dFdV);
+ data->iS.construct(data->S);
+
+ solver_t cg;
+ cg.setMaxIterations(100);
+ cg.setTolerance(0.01f);
+
+#ifdef USE_EIGEN_CONSTRAINED_CG
+ cg.filter() = data->S;
+#endif
+
+ data->A = data->M - dt * data->dFdV - dt*dt * data->dFdX;
+ cg.compute(data->A);
+
+ data->B = dt * data->F + dt*dt * data->dFdX * data->V;
+
+#ifdef IMPLICIT_PRINT_SOLVER_INPUT_OUTPUT
+ printf("==== A ====\n");
+ print_lmatrix(id->A);
+ printf("==== z ====\n");
+ print_lvector(id->z);
+ printf("==== B ====\n");
+ print_lvector(id->B);
+ printf("==== S ====\n");
+ print_lmatrix(id->S);
+#endif
+
+#ifdef USE_EIGEN_CORE
+ data->dV = cg.solve(data->B);
+#endif
+#ifdef USE_EIGEN_CONSTRAINED_CG
+ data->dV = cg.solveWithGuess(data->B, data->z);
+#endif
+
+#ifdef IMPLICIT_PRINT_SOLVER_INPUT_OUTPUT
+ printf("==== dV ====\n");
+ print_lvector(id->dV);
+ printf("========\n");
+#endif
+
+ data->Vnew = data->V + data->dV;
+
+ switch (cg.info()) {
+ case Eigen::Success: result->status = BPH_SOLVER_SUCCESS; break;
+ case Eigen::NoConvergence: result->status = BPH_SOLVER_NO_CONVERGENCE; break;
+ case Eigen::InvalidInput: result->status = BPH_SOLVER_INVALID_INPUT; break;
+ case Eigen::NumericalIssue: result->status = BPH_SOLVER_NUMERICAL_ISSUE; break;
+ }
+
+ result->iterations = cg.iterations();
+ result->error = cg.error();
+
+ return cg.info() == Eigen::Success;
+}
+
+bool BPH_mass_spring_solve_positions(Implicit_Data *data, float dt)
+{
+ data->Xnew = data->X + data->Vnew * dt;
+ return true;
+}
+
+/* ================================ */
+
+void BPH_mass_spring_apply_result(Implicit_Data *data)
+{
+ data->X = data->Xnew;
+ data->V = data->Vnew;
+}
+
+void BPH_mass_spring_set_vertex_mass(Implicit_Data *data, int index, float mass)
+{
+ float m[3][3];
+ copy_m3_m3(m, I);
+ mul_m3_fl(m, mass);
+ data->iM.add(index, index, m);
+}
+
+void BPH_mass_spring_set_rest_transform(Implicit_Data *data, int index, float tfm[3][3])
+{
+#ifdef CLOTH_ROOT_FRAME
+ copy_m3_m3(data->tfm[index], tfm);
+#else
+ unit_m3(data->tfm[index]);
+ (void)tfm;
+#endif
+}
+
+void BPH_mass_spring_set_motion_state(Implicit_Data *data, int index, const float x[3], const float v[3])
+{
+ world_to_root_v3(data, index, data->X.v3(index), x);
+ world_to_root_v3(data, index, data->V.v3(index), v);
+}
+
+void BPH_mass_spring_set_position(Implicit_Data *data, int index, const float x[3])
+{
+ world_to_root_v3(data, index, data->X.v3(index), x);
+}
+
+void BPH_mass_spring_set_velocity(Implicit_Data *data, int index, const float v[3])
+{
+ world_to_root_v3(data, index, data->V.v3(index), v);
+}
+
+void BPH_mass_spring_get_motion_state(struct Implicit_Data *data, int index, float x[3], float v[3])
+{
+ if (x) root_to_world_v3(data, index, x, data->X.v3(index));
+ if (v) root_to_world_v3(data, index, v, data->V.v3(index));
+}
+
+void BPH_mass_spring_get_position(struct Implicit_Data *data, int index, float x[3])
+{
+ root_to_world_v3(data, index, x, data->X.v3(index));
+}
+
+void BPH_mass_spring_get_new_velocity(Implicit_Data *data, int index, float v[3])
+{
+ root_to_world_v3(data, index, v, data->V.v3(index));
+}
+
+void BPH_mass_spring_set_new_velocity(Implicit_Data *data, int index, const float v[3])
+{
+ world_to_root_v3(data, index, data->V.v3(index), v);
+}
+
+void BPH_mass_spring_clear_constraints(Implicit_Data *data)
+{
+ int numverts = data->numverts;
+ for (int i = 0; i < numverts; ++i) {
+ data->iS.add(i, i, I);
+ zero_v3(data->z.v3(i));
+ }
+}
+
+void BPH_mass_spring_add_constraint_ndof0(Implicit_Data *data, int index, const float dV[3])
+{
+ data->iS.sub(index, index, I);
+
+ world_to_root_v3(data, index, data->z.v3(index), dV);
+}
+
+void BPH_mass_spring_add_constraint_ndof1(Implicit_Data *data, int index, const float c1[3], const float c2[3], const float dV[3])
+{
+ float m[3][3], p[3], q[3], u[3], cmat[3][3];
+
+ world_to_root_v3(data, index, p, c1);
+ outerproduct(cmat, p, p);
+ copy_m3_m3(m, cmat);
+
+ world_to_root_v3(data, index, q, c2);
+ outerproduct(cmat, q, q);
+ add_m3_m3m3(m, m, cmat);
+
+ /* XXX not sure but multiplication should work here */
+ data->iS.sub(index, index, m);
+// mul_m3_m3m3(data->S[index].m, data->S[index].m, m);
+
+ world_to_root_v3(data, index, u, dV);
+ add_v3_v3(data->z.v3(index), u);
+}
+
+void BPH_mass_spring_add_constraint_ndof2(Implicit_Data *data, int index, const float c1[3], const float dV[3])
+{
+ float m[3][3], p[3], u[3], cmat[3][3];
+
+ world_to_root_v3(data, index, p, c1);
+ outerproduct(cmat, p, p);
+ copy_m3_m3(m, cmat);
+
+ data->iS.sub(index, index, m);
+// mul_m3_m3m3(data->S[index].m, data->S[index].m, m);
+
+ world_to_root_v3(data, index, u, dV);
+ add_v3_v3(data->z.v3(index), u);
+}
+
+void BPH_mass_spring_clear_forces(Implicit_Data *data)
+{
+ data->F.setZero();
+ data->dFdX.setZero();
+ data->dFdV.setZero();
+}
+
+void BPH_mass_spring_force_reference_frame(Implicit_Data *data, int index, const float acceleration[3], const float omega[3], const float domega_dt[3], float mass)
+{
+#ifdef CLOTH_ROOT_FRAME
+ float acc[3], w[3], dwdt[3];
+ float f[3], dfdx[3][3], dfdv[3][3];
+ float euler[3], coriolis[3], centrifugal[3], rotvel[3];
+ float deuler[3][3], dcoriolis[3][3], dcentrifugal[3][3], drotvel[3][3];
+
+ world_to_root_v3(data, index, acc, acceleration);
+ world_to_root_v3(data, index, w, omega);
+ world_to_root_v3(data, index, dwdt, domega_dt);
+
+ cross_v3_v3v3(euler, dwdt, data->X.v3(index));
+ cross_v3_v3v3(coriolis, w, data->V.v3(index));
+ mul_v3_fl(coriolis, 2.0f);
+ cross_v3_v3v3(rotvel, w, data->X.v3(index));
+ cross_v3_v3v3(centrifugal, w, rotvel);
+
+ sub_v3_v3v3(f, acc, euler);
+ sub_v3_v3(f, coriolis);
+ sub_v3_v3(f, centrifugal);
+
+ mul_v3_fl(f, mass); /* F = m * a */
+
+ cross_v3_identity(deuler, dwdt);
+ cross_v3_identity(dcoriolis, w);
+ mul_m3_fl(dcoriolis, 2.0f);
+ cross_v3_identity(drotvel, w);
+ cross_m3_v3m3(dcentrifugal, w, drotvel);
+
+ add_m3_m3m3(dfdx, deuler, dcentrifugal);
+ negate_m3(dfdx);
+ mul_m3_fl(dfdx, mass);
+
+ copy_m3_m3(dfdv, dcoriolis);
+ negate_m3(dfdv);
+ mul_m3_fl(dfdv, mass);
+
+ add_v3_v3(data->F.v3(index), f);
+ data->idFdX.add(index, index, dfdx);
+ data->idFdV.add(index, index, dfdv);
+#else
+ (void)data;
+ (void)index;
+ (void)acceleration;
+ (void)omega;
+ (void)domega_dt;
+#endif
+}
+
+void BPH_mass_spring_force_gravity(Implicit_Data *data, int index, float mass, const float g[3])
+{
+ /* force = mass * acceleration (in this case: gravity) */
+ float f[3];
+ world_to_root_v3(data, index, f, g);
+ mul_v3_fl(f, mass);
+
+ add_v3_v3(data->F.v3(index), f);
+}
+
+void BPH_mass_spring_force_drag(Implicit_Data *data, float drag)
+{
+ int numverts = data->numverts;
+ for (int i = 0; i < numverts; i++) {
+ float tmp[3][3];
+
+ /* NB: uses root space velocity, no need to transform */
+ madd_v3_v3fl(data->F.v3(i), data->V.v3(i), -drag);
+
+ copy_m3_m3(tmp, I);
+ mul_m3_fl(tmp, -drag);
+ data->idFdV.add(i, i, tmp);
+ }
+}
+
+void BPH_mass_spring_force_extern(struct Implicit_Data *data, int i, const float f[3], float dfdx[3][3], float dfdv[3][3])
+{
+ float tf[3], tdfdx[3][3], tdfdv[3][3];
+ world_to_root_v3(data, i, tf, f);
+ world_to_root_m3(data, i, tdfdx, dfdx);
+ world_to_root_m3(data, i, tdfdv, dfdv);
+
+ add_v3_v3(data->F.v3(i), tf);
+ data->idFdX.add(i, i, tdfdx);
+ data->idFdV.add(i, i, tdfdv);
+}
+
+static float calc_nor_area_tri(float nor[3], const float v1[3], const float v2[3], const float v3[3])
+{
+ float n1[3], n2[3];
+
+ sub_v3_v3v3(n1, v1, v2);
+ sub_v3_v3v3(n2, v2, v3);
+
+ cross_v3_v3v3(nor, n1, n2);
+ return normalize_v3(nor);
+}
+
+/* XXX does not support force jacobians yet, since the effector system does not provide them either */
+void BPH_mass_spring_force_face_wind(Implicit_Data *data, int v1, int v2, int v3, const float (*winvec)[3])
+{
+ const float effector_scale = 0.02f;
+ float win[3], nor[3], area;
+ float factor;
+
+ // calculate face normal and area
+ area = calc_nor_area_tri(nor, data->X.v3(v1), data->X.v3(v2), data->X.v3(v3));
+ factor = effector_scale * area / 3.0f;
+
+ world_to_root_v3(data, v1, win, winvec[v1]);
+ madd_v3_v3fl(data->F.v3(v1), nor, factor * dot_v3v3(win, nor));
+
+ world_to_root_v3(data, v2, win, winvec[v2]);
+ madd_v3_v3fl(data->F.v3(v2), nor, factor * dot_v3v3(win, nor));
+
+ world_to_root_v3(data, v3, win, winvec[v3]);
+ madd_v3_v3fl(data->F.v3(v3), nor, factor * dot_v3v3(win, nor));
+}
+
+void BPH_mass_spring_force_edge_wind(Implicit_Data *data, int v1, int v2, const float (*winvec)[3])
+{
+ const float effector_scale = 0.01;
+ float win[3], dir[3], nor[3], length;
+
+ sub_v3_v3v3(dir, data->X.v3(v1), data->X.v3(v2));
+ length = normalize_v3(dir);
+
+ world_to_root_v3(data, v1, win, winvec[v1]);
+ madd_v3_v3v3fl(nor, win, dir, -dot_v3v3(win, dir));
+ madd_v3_v3fl(data->F.v3(v1), nor, effector_scale * length);
+
+ world_to_root_v3(data, v2, win, winvec[v2]);
+ madd_v3_v3v3fl(nor, win, dir, -dot_v3v3(win, dir));
+ madd_v3_v3fl(data->F.v3(v2), nor, effector_scale * length);
+}
+
+BLI_INLINE void dfdx_spring(float to[3][3], const float dir[3], float length, float L, float k)
+{
+ // dir is unit length direction, rest is spring's restlength, k is spring constant.
+ //return ( (I-outerprod(dir, dir))*Min(1.0f, rest/length) - I) * -k;
+ outerproduct(to, dir, dir);
+ sub_m3_m3m3(to, I, to);
+
+ mul_m3_fl(to, (L/length));
+ sub_m3_m3m3(to, to, I);
+ mul_m3_fl(to, k);
+}
+
+/* unused */
+#if 0
+BLI_INLINE void dfdx_damp(float to[3][3], const float dir[3], float length, const float vel[3], float rest, float damping)
+{
+ // inner spring damping vel is the relative velocity of the endpoints.
+ // return (I-outerprod(dir, dir)) * (-damping * -(dot(dir, vel)/Max(length, rest)));
+ mul_fvectorT_fvector(to, dir, dir);
+ sub_fmatrix_fmatrix(to, I, to);
+ mul_fmatrix_S(to, (-damping * -(dot_v3v3(dir, vel)/MAX2(length, rest))));
+}
+#endif
+
+BLI_INLINE void dfdv_damp(float to[3][3], const float dir[3], float damping)
+{
+ // derivative of force wrt velocity
+ outerproduct(to, dir, dir);
+ mul_m3_fl(to, -damping);
+}
+
+BLI_INLINE float fb(float length, float L)
+{
+ float x = length / L;
+ return (-11.541f * powf(x, 4) + 34.193f * powf(x, 3) - 39.083f * powf(x, 2) + 23.116f * x - 9.713f);
+}
+
+BLI_INLINE float fbderiv(float length, float L)
+{
+ float x = length/L;
+
+ return (-46.164f * powf(x, 3) + 102.579f * powf(x, 2) - 78.166f * x + 23.116f);
+}
+
+BLI_INLINE float fbstar(float length, float L, float kb, float cb)
+{
+ float tempfb_fl = kb * fb(length, L);
+ float fbstar_fl = cb * (length - L);
+
+ if (tempfb_fl < fbstar_fl)
+ return fbstar_fl;
+ else
+ return tempfb_fl;
+}
+
+// function to calculae bending spring force (taken from Choi & Co)
+BLI_INLINE float fbstar_jacobi(float length, float L, float kb, float cb)
+{
+ float tempfb_fl = kb * fb(length, L);
+ float fbstar_fl = cb * (length - L);
+
+ if (tempfb_fl < fbstar_fl) {
+ return -cb;
+ }
+ else {
+ return -kb * fbderiv(length, L);
+ }
+}
+
+/* calculate elonglation */
+BLI_INLINE bool spring_length(Implicit_Data *data, int i, int j, float r_extent[3], float r_dir[3], float *r_length, float r_vel[3])
+{
+ sub_v3_v3v3(r_extent, data->X.v3(j), data->X.v3(i));
+ sub_v3_v3v3(r_vel, data->V.v3(j), data->V.v3(i));
+ *r_length = len_v3(r_extent);
+
+ if (*r_length > ALMOST_ZERO) {
+ /*
+ if (length>L) {
+ if ((clmd->sim_parms->flags & CSIMSETT_FLAG_TEARING_ENABLED) &&
+ ( ((length-L)*100.0f/L) > clmd->sim_parms->maxspringlen )) {
+ // cut spring!
+ s->flags |= CSPRING_FLAG_DEACTIVATE;
+ return false;
+ }
+ }
+ */
+ mul_v3_v3fl(r_dir, r_extent, 1.0f/(*r_length));
+ }
+ else {
+ zero_v3(r_dir);
+ }
+
+ return true;
+}
+
+BLI_INLINE void apply_spring(Implicit_Data *data, int i, int j, const float f[3], float dfdx[3][3], float dfdv[3][3])
+{
+ add_v3_v3(data->F.v3(i), f);
+ sub_v3_v3(data->F.v3(j), f);
+
+ data->idFdX.add(i, i, dfdx);
+ data->idFdX.add(j, j, dfdx);
+ data->idFdX.sub(i, j, dfdx);
+ data->idFdX.sub(j, i, dfdx);
+
+ data->idFdV.add(i, i, dfdv);
+ data->idFdV.add(j, j, dfdv);
+ data->idFdV.sub(i, j, dfdv);
+ data->idFdV.sub(j, i, dfdv);
+}
+
+bool BPH_mass_spring_force_spring_linear(Implicit_Data *data, int i, int j, float restlen,
+ float stiffness, float damping, bool no_compress, float clamp_force,
+ float r_f[3], float r_dfdx[3][3], float r_dfdv[3][3])
+{
+ float extent[3], length, dir[3], vel[3];
+
+ // calculate elonglation
+ spring_length(data, i, j, extent, dir, &length, vel);
+
+ if (length > restlen || no_compress) {
+ float stretch_force, f[3], dfdx[3][3], dfdv[3][3];
+
+ stretch_force = stiffness * (length - restlen);
+ if (clamp_force > 0.0f && stretch_force > clamp_force) {
+ stretch_force = clamp_force;
+ }
+ mul_v3_v3fl(f, dir, stretch_force);
+
+ // Ascher & Boxman, p.21: Damping only during elonglation
+ // something wrong with it...
+ madd_v3_v3fl(f, dir, damping * dot_v3v3(vel, dir));
+
+ dfdx_spring(dfdx, dir, length, restlen, stiffness);
+ dfdv_damp(dfdv, dir, damping);
+
+ apply_spring(data, i, j, f, dfdx, dfdv);
+
+ if (r_f) copy_v3_v3(r_f, f);
+ if (r_dfdx) copy_m3_m3(r_dfdx, dfdx);
+ if (r_dfdv) copy_m3_m3(r_dfdv, dfdv);
+
+ return true;
+ }
+ else {
+ if (r_f) zero_v3(r_f);
+ if (r_dfdx) zero_m3(r_dfdx);
+ if (r_dfdv) zero_m3(r_dfdv);
+
+ return false;
+ }
+}
+
+/* See "Stable but Responsive Cloth" (Choi, Ko 2005) */
+bool BPH_mass_spring_force_spring_bending(Implicit_Data *data, int i, int j, float restlen,
+ float kb, float cb,
+ float r_f[3], float r_dfdx[3][3], float r_dfdv[3][3])
+{
+ float extent[3], length, dir[3], vel[3];
+
+ // calculate elonglation
+ spring_length(data, i, j, extent, dir, &length, vel);
+
+ if (length < restlen) {
+ float f[3], dfdx[3][3], dfdv[3][3];
+
+ mul_v3_v3fl(f, dir, fbstar(length, restlen, kb, cb));
+
+ outerproduct(dfdx, dir, dir);
+ mul_m3_fl(dfdx, fbstar_jacobi(length, restlen, kb, cb));
+
+ /* XXX damping not supported */
+ zero_m3(dfdv);
+
+ apply_spring(data, i, j, f, dfdx, dfdv);
+
+ if (r_f) copy_v3_v3(r_f, f);
+ if (r_dfdx) copy_m3_m3(r_dfdx, dfdx);
+ if (r_dfdv) copy_m3_m3(r_dfdv, dfdv);
+
+ return true;
+ }
+ else {
+ if (r_f) zero_v3(r_f);
+ if (r_dfdx) zero_m3(r_dfdx);
+ if (r_dfdv) zero_m3(r_dfdv);
+
+ return false;
+ }
+}
+
+/* Jacobian of a direction vector.
+ * Basically the part of the differential orthogonal to the direction,
+ * inversely proportional to the length of the edge.
+ *
+ * dD_ij/dx_i = -dD_ij/dx_j = (D_ij * D_ij^T - I) / len_ij
+ */
+BLI_INLINE void spring_grad_dir(Implicit_Data *data, int i, int j, float edge[3], float dir[3], float grad_dir[3][3])
+{
+ float length;
+
+ sub_v3_v3v3(edge, data->X.v3(j), data->X.v3(i));
+ length = normalize_v3_v3(dir, edge);
+
+ if (length > ALMOST_ZERO) {
+ outerproduct(grad_dir, dir, dir);
+ sub_m3_m3m3(grad_dir, I, grad_dir);
+ mul_m3_fl(grad_dir, 1.0f / length);
+ }
+ else {
+ zero_m3(grad_dir);
+ }
+}
+
+BLI_INLINE void spring_angbend_forces(Implicit_Data *data, int i, int j, int k,
+ const float goal[3],
+ float stiffness, float damping,
+ int q, const float dx[3], const float dv[3],
+ float r_f[3])
+{
+ float edge_ij[3], dir_ij[3];
+ float edge_jk[3], dir_jk[3];
+ float vel_ij[3], vel_jk[3], vel_ortho[3];
+ float f_bend[3], f_damp[3];
+ float fk[3];
+ float dist[3];
+
+ zero_v3(fk);
+
+ sub_v3_v3v3(edge_ij, data->X.v3(j), data->X.v3(i));
+ if (q == i) sub_v3_v3(edge_ij, dx);
+ if (q == j) add_v3_v3(edge_ij, dx);
+ normalize_v3_v3(dir_ij, edge_ij);
+
+ sub_v3_v3v3(edge_jk, data->X.v3(k), data->X.v3(j));
+ if (q == j) sub_v3_v3(edge_jk, dx);
+ if (q == k) add_v3_v3(edge_jk, dx);
+ normalize_v3_v3(dir_jk, edge_jk);
+
+ sub_v3_v3v3(vel_ij, data->V.v3(j), data->V.v3(i));
+ if (q == i) sub_v3_v3(vel_ij, dv);
+ if (q == j) add_v3_v3(vel_ij, dv);
+
+ sub_v3_v3v3(vel_jk, data->V.v3(k), data->V.v3(j));
+ if (q == j) sub_v3_v3(vel_jk, dv);
+ if (q == k) add_v3_v3(vel_jk, dv);
+
+ /* bending force */
+ sub_v3_v3v3(dist, goal, edge_jk);
+ mul_v3_v3fl(f_bend, dist, stiffness);
+
+ add_v3_v3(fk, f_bend);
+
+ /* damping force */
+ madd_v3_v3v3fl(vel_ortho, vel_jk, dir_jk, -dot_v3v3(vel_jk, dir_jk));
+ mul_v3_v3fl(f_damp, vel_ortho, damping);
+
+ sub_v3_v3(fk, f_damp);
+
+ copy_v3_v3(r_f, fk);
+}
+
+/* Finite Differences method for estimating the jacobian of the force */
+BLI_INLINE void spring_angbend_estimate_dfdx(Implicit_Data *data, int i, int j, int k,
+ const float goal[3],
+ float stiffness, float damping,
+ int q, float dfdx[3][3])
+{
+ const float delta = 0.00001f; // TODO find a good heuristic for this
+ float dvec_null[3][3], dvec_pos[3][3], dvec_neg[3][3];
+ float f[3];
+ int a, b;
+
+ zero_m3(dvec_null);
+ unit_m3(dvec_pos);
+ mul_m3_fl(dvec_pos, delta * 0.5f);
+ copy_m3_m3(dvec_neg, dvec_pos);
+ negate_m3(dvec_neg);
+
+ /* XXX TODO offset targets to account for position dependency */
+
+ for (a = 0; a < 3; ++a) {
+ spring_angbend_forces(data, i, j, k, goal, stiffness, damping,
+ q, dvec_pos[a], dvec_null[a], f);
+ copy_v3_v3(dfdx[a], f);
+
+ spring_angbend_forces(data, i, j, k, goal, stiffness, damping,
+ q, dvec_neg[a], dvec_null[a], f);
+ sub_v3_v3(dfdx[a], f);
+
+ for (b = 0; b < 3; ++b) {
+ dfdx[a][b] /= delta;
+ }
+ }
+}
+
+/* Finite Differences method for estimating the jacobian of the force */
+BLI_INLINE void spring_angbend_estimate_dfdv(Implicit_Data *data, int i, int j, int k,
+ const float goal[3],
+ float stiffness, float damping,
+ int q, float dfdv[3][3])
+{
+ const float delta = 0.00001f; // TODO find a good heuristic for this
+ float dvec_null[3][3], dvec_pos[3][3], dvec_neg[3][3];
+ float f[3];
+ int a, b;
+
+ zero_m3(dvec_null);
+ unit_m3(dvec_pos);
+ mul_m3_fl(dvec_pos, delta * 0.5f);
+ copy_m3_m3(dvec_neg, dvec_pos);
+ negate_m3(dvec_neg);
+
+ /* XXX TODO offset targets to account for position dependency */
+
+ for (a = 0; a < 3; ++a) {
+ spring_angbend_forces(data, i, j, k, goal, stiffness, damping,
+ q, dvec_null[a], dvec_pos[a], f);
+ copy_v3_v3(dfdv[a], f);
+
+ spring_angbend_forces(data, i, j, k, goal, stiffness, damping,
+ q, dvec_null[a], dvec_neg[a], f);
+ sub_v3_v3(dfdv[a], f);
+
+ for (b = 0; b < 3; ++b) {
+ dfdv[a][b] /= delta;
+ }
+ }
+}
+
+/* Angular spring that pulls the vertex toward the local target
+ * See "Artistic Simulation of Curly Hair" (Pixar technical memo #12-03a)
+ */
+bool BPH_mass_spring_force_spring_bending_angular(Implicit_Data *data, int i, int j, int k,
+ const float target[3], float stiffness, float damping)
+{
+ float goal[3];
+ float fj[3], fk[3];
+ float dfj_dxi[3][3], dfj_dxj[3][3], dfk_dxi[3][3], dfk_dxj[3][3], dfk_dxk[3][3];
+ float dfj_dvi[3][3], dfj_dvj[3][3], dfk_dvi[3][3], dfk_dvj[3][3], dfk_dvk[3][3];
+
+ const float vecnull[3] = {0.0f, 0.0f, 0.0f};
+
+ world_to_root_v3(data, j, goal, target);
+
+ spring_angbend_forces(data, i, j, k, goal, stiffness, damping, k, vecnull, vecnull, fk);
+ negate_v3_v3(fj, fk); /* counterforce */
+
+ spring_angbend_estimate_dfdx(data, i, j, k, goal, stiffness, damping, i, dfk_dxi);
+ spring_angbend_estimate_dfdx(data, i, j, k, goal, stiffness, damping, j, dfk_dxj);
+ spring_angbend_estimate_dfdx(data, i, j, k, goal, stiffness, damping, k, dfk_dxk);
+ copy_m3_m3(dfj_dxi, dfk_dxi); negate_m3(dfj_dxi);
+ copy_m3_m3(dfj_dxj, dfk_dxj); negate_m3(dfj_dxj);
+
+ spring_angbend_estimate_dfdv(data, i, j, k, goal, stiffness, damping, i, dfk_dvi);
+ spring_angbend_estimate_dfdv(data, i, j, k, goal, stiffness, damping, j, dfk_dvj);
+ spring_angbend_estimate_dfdv(data, i, j, k, goal, stiffness, damping, k, dfk_dvk);
+ copy_m3_m3(dfj_dvi, dfk_dvi); negate_m3(dfj_dvi);
+ copy_m3_m3(dfj_dvj, dfk_dvj); negate_m3(dfj_dvj);
+
+ /* add forces and jacobians to the solver data */
+
+ add_v3_v3(data->F.v3(j), fj);
+ add_v3_v3(data->F.v3(k), fk);
+
+ data->idFdX.add(j, j, dfj_dxj);
+ data->idFdX.add(k, k, dfk_dxk);
+
+ data->idFdX.add(i, j, dfj_dxi);
+ data->idFdX.add(j, i, dfj_dxi);
+ data->idFdX.add(j, k, dfk_dxj);
+ data->idFdX.add(k, j, dfk_dxj);
+ data->idFdX.add(i, k, dfk_dxi);
+ data->idFdX.add(k, i, dfk_dxi);
+
+ data->idFdV.add(j, j, dfj_dvj);
+ data->idFdV.add(k, k, dfk_dvk);
+
+ data->idFdV.add(i, j, dfj_dvi);
+ data->idFdV.add(j, i, dfj_dvi);
+ data->idFdV.add(j, k, dfk_dvj);
+ data->idFdV.add(k, j, dfk_dvj);
+ data->idFdV.add(i, k, dfk_dvi);
+ data->idFdV.add(k, i, dfk_dvi);
+
+ /* XXX analytical calculation of derivatives below is incorrect.
+ * This proved to be difficult, but for now just using the finite difference method for
+ * estimating the jacobians should be sufficient.
+ */
+#if 0
+ float edge_ij[3], dir_ij[3], grad_dir_ij[3][3];
+ float edge_jk[3], dir_jk[3], grad_dir_jk[3][3];
+ float dist[3], vel_jk[3], vel_jk_ortho[3], projvel[3];
+ float target[3];
+ float tmp[3][3];
+ float fi[3], fj[3], fk[3];
+ float dfi_dxi[3][3], dfj_dxi[3][3], dfj_dxj[3][3], dfk_dxi[3][3], dfk_dxj[3][3], dfk_dxk[3][3];
+ float dfdvi[3][3];
+
+ // TESTING
+ damping = 0.0f;
+
+ zero_v3(fi);
+ zero_v3(fj);
+ zero_v3(fk);
+ zero_m3(dfi_dxi);
+ zero_m3(dfj_dxi);
+ zero_m3(dfk_dxi);
+ zero_m3(dfk_dxj);
+ zero_m3(dfk_dxk);
+
+ /* jacobian of direction vectors */
+ spring_grad_dir(data, i, j, edge_ij, dir_ij, grad_dir_ij);
+ spring_grad_dir(data, j, k, edge_jk, dir_jk, grad_dir_jk);
+
+ sub_v3_v3v3(vel_jk, data->V[k], data->V[j]);
+
+ /* bending force */
+ mul_v3_v3fl(target, dir_ij, restlen);
+ sub_v3_v3v3(dist, target, edge_jk);
+ mul_v3_v3fl(fk, dist, stiffness);
+
+ /* damping force */
+ madd_v3_v3v3fl(vel_jk_ortho, vel_jk, dir_jk, -dot_v3v3(vel_jk, dir_jk));
+ madd_v3_v3fl(fk, vel_jk_ortho, damping);
+
+ /* XXX this only holds true as long as we assume straight rest shape!
+ * eventually will become a bit more involved since the opposite segment
+ * gets its own target, under condition of having equal torque on both sides.
+ */
+ copy_v3_v3(fi, fk);
+
+ /* counterforce on the middle point */
+ sub_v3_v3(fj, fi);
+ sub_v3_v3(fj, fk);
+
+ /* === derivatives === */
+
+ madd_m3_m3fl(dfk_dxi, grad_dir_ij, stiffness * restlen);
+
+ madd_m3_m3fl(dfk_dxj, grad_dir_ij, -stiffness * restlen);
+ madd_m3_m3fl(dfk_dxj, I, stiffness);
+
+ madd_m3_m3fl(dfk_dxk, I, -stiffness);
+
+ copy_m3_m3(dfi_dxi, dfk_dxk);
+ negate_m3(dfi_dxi);
+
+ /* dfj_dfi == dfi_dfj due to symmetry,
+ * dfi_dfj == dfk_dfj due to fi == fk
+ * XXX see comment above on future bent rest shapes
+ */
+ copy_m3_m3(dfj_dxi, dfk_dxj);
+
+ /* dfj_dxj == -(dfi_dxj + dfk_dxj) due to fj == -(fi + fk) */
+ sub_m3_m3m3(dfj_dxj, dfj_dxj, dfj_dxi);
+ sub_m3_m3m3(dfj_dxj, dfj_dxj, dfk_dxj);
+
+ /* add forces and jacobians to the solver data */
+ add_v3_v3(data->F[i], fi);
+ add_v3_v3(data->F[j], fj);
+ add_v3_v3(data->F[k], fk);
+
+ add_m3_m3m3(data->dFdX[i].m, data->dFdX[i].m, dfi_dxi);
+ add_m3_m3m3(data->dFdX[j].m, data->dFdX[j].m, dfj_dxj);
+ add_m3_m3m3(data->dFdX[k].m, data->dFdX[k].m, dfk_dxk);
+
+ add_m3_m3m3(data->dFdX[block_ij].m, data->dFdX[block_ij].m, dfj_dxi);
+ add_m3_m3m3(data->dFdX[block_jk].m, data->dFdX[block_jk].m, dfk_dxj);
+ add_m3_m3m3(data->dFdX[block_ik].m, data->dFdX[block_ik].m, dfk_dxi);
+#endif
+
+ return true;
+}
+
+bool BPH_mass_spring_force_spring_goal(Implicit_Data *data, int i, const float goal_x[3], const float goal_v[3],
+ float stiffness, float damping,
+ float r_f[3], float r_dfdx[3][3], float r_dfdv[3][3])
+{
+ float root_goal_x[3], root_goal_v[3], extent[3], length, dir[3], vel[3];
+ float f[3], dfdx[3][3], dfdv[3][3];
+
+ /* goal is in world space */
+ world_to_root_v3(data, i, root_goal_x, goal_x);
+ world_to_root_v3(data, i, root_goal_v, goal_v);
+
+ sub_v3_v3v3(extent, root_goal_x, data->X.v3(i));
+ sub_v3_v3v3(vel, root_goal_v, data->V.v3(i));
+ length = normalize_v3_v3(dir, extent);
+
+ if (length > ALMOST_ZERO) {
+ mul_v3_v3fl(f, dir, stiffness * length);
+
+ // Ascher & Boxman, p.21: Damping only during elonglation
+ // something wrong with it...
+ madd_v3_v3fl(f, dir, damping * dot_v3v3(vel, dir));
+
+ dfdx_spring(dfdx, dir, length, 0.0f, stiffness);
+ dfdv_damp(dfdv, dir, damping);
+
+ add_v3_v3(data->F.v3(i), f);
+ data->idFdX.add(i, i, dfdx);
+ data->idFdV.add(i, i, dfdv);
+
+ if (r_f) copy_v3_v3(r_f, f);
+ if (r_dfdx) copy_m3_m3(r_dfdx, dfdx);
+ if (r_dfdv) copy_m3_m3(r_dfdv, dfdv);
+
+ return true;
+ }
+ else {
+ if (r_f) zero_v3(r_f);
+ if (r_dfdx) zero_m3(r_dfdx);
+ if (r_dfdv) zero_m3(r_dfdv);
+
+ return false;
+ }
+}
+
+#endif /* IMPLICIT_SOLVER_EIGEN */
diff --git a/source/blender/python/BPY_extern.h b/source/blender/python/BPY_extern.h
index a5cf0b94c62..815beebb159 100644
--- a/source/blender/python/BPY_extern.h
+++ b/source/blender/python/BPY_extern.h
@@ -86,6 +86,7 @@ void BPY_driver_reset(void);
float BPY_driver_exec(struct ChannelDriver *driver, const float evaltime);
int BPY_button_exec(struct bContext *C, const char *expr, double *value, const bool verbose);
+int BPY_string_exec_ex(struct bContext *C, const char *expr, bool use_eval);
int BPY_string_exec(struct bContext *C, const char *expr);
void BPY_DECREF(void *pyob_ptr); /* Py_DECREF() */
diff --git a/source/blender/python/SConscript b/source/blender/python/SConscript
index a5b52a3dd63..79c53760302 100644
--- a/source/blender/python/SConscript
+++ b/source/blender/python/SConscript
@@ -33,9 +33,10 @@ incs = [
'.',
'#/intern/guardedalloc',
'#/intern/memutil',
- '#/extern/glew/include',
- '#/intern/audaspace/intern',
+ env['BF_GLEW_INC'],
+ '#/intern/glew-mx',
'#/intern/cycles/blender',
+ '../blentranslation',
'../blenfont',
'../blenkernel',
'../blenlib',
@@ -62,7 +63,8 @@ sources = env.Glob('bmesh/*.c')
env.BlenderLib( libname = 'bf_python_bmesh', sources = Split(sources), includes = Split(incs), defines = defs, libtype = ['core','player'], priority = [362,165])
# generic
-defs = ['GLEW_STATIC']
+defs = []
+defs += env['BF_GL_DEFINITIONS']
if is_debug:
defs.append('_DEBUG')
@@ -80,6 +82,7 @@ env.BlenderLib( libname = 'bf_python_mathutils', sources = Split(sources), inclu
# bpy
defs = []
+defs += env['BF_GL_DEFINITIONS']
if is_debug:
defs.append('_DEBUG')
@@ -90,8 +93,8 @@ if env['WITH_BF_PYTHON_SAFETY']:
if env['BF_BUILDINFO']:
defs.append('BUILD_DATE')
-
-# Audaspace is always on currently
+if env['WITH_BF_AUDASPACE']:
+ defs += env['BF_AUDASPACE_DEF']
if env['WITH_BF_BULLET']:
defs.append('WITH_BULLET')
@@ -158,6 +161,11 @@ if env['WITH_BF_OPENAL']:
if env['WITH_BF_SDL']:
defs.append('WITH_SDL')
+ incs += ' ' + env['BF_SDL_INC']
+
+ if env['WITH_BF_SDL_DYNLOAD']:
+ defs.append('WITH_SDL_DYNLOAD')
+ incs += ' #extern/sdlew/include'
if env['WITH_BF_JACK']:
defs.append('WITH_JACK')
diff --git a/source/blender/python/bmesh/bmesh_py_api.c b/source/blender/python/bmesh/bmesh_py_api.c
index bc14e1ac3a6..7c5d1961849 100644
--- a/source/blender/python/bmesh/bmesh_py_api.c
+++ b/source/blender/python/bmesh/bmesh_py_api.c
@@ -108,7 +108,7 @@ PyDoc_STRVAR(bpy_bm_update_edit_mesh_doc,
" :type mesh: :class:`bpy.types.Mesh`\n"
" :arg tessface: Option to recalculate n-gon tessellation.\n"
" :type tessface: boolean\n"
-" :arg destructive: Use when grometry has been added or removed.\n"
+" :arg destructive: Use when geometry has been added or removed.\n"
" :type destructive: boolean\n"
);
static PyObject *bpy_bm_update_edit_mesh(PyObject *UNUSED(self), PyObject *args, PyObject *kw)
@@ -116,11 +116,14 @@ static PyObject *bpy_bm_update_edit_mesh(PyObject *UNUSED(self), PyObject *args,
static const char *kwlist[] = {"mesh", "tessface", "destructive", NULL};
PyObject *py_me;
Mesh *me;
- int do_tessface = true;
- int is_destructive = true;
-
- if (!PyArg_ParseTupleAndKeywords(args, kw, "O|ii:update_edit_mesh", (char **)kwlist,
- &py_me, &do_tessface, &is_destructive))
+ bool do_tessface = true;
+ bool is_destructive = true;
+
+ if (!PyArg_ParseTupleAndKeywords(
+ args, kw, "O|O&O&:update_edit_mesh", (char **)kwlist,
+ &py_me,
+ PyC_ParseBool, &do_tessface,
+ PyC_ParseBool, &is_destructive))
{
return NULL;
}
diff --git a/source/blender/python/bmesh/bmesh_py_geometry.c b/source/blender/python/bmesh/bmesh_py_geometry.c
index 4cd0a3951b3..f67bf29c94d 100644
--- a/source/blender/python/bmesh/bmesh_py_geometry.c
+++ b/source/blender/python/bmesh/bmesh_py_geometry.c
@@ -43,13 +43,13 @@
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"
+" Tests if the projection of a point is inside a face (using the face's 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"
+" :return: True when the projection of the point is in the face.\n"
" :rtype: bool\n"
);
static PyObject *bpy_bm_geometry_intersect_face_point(BPy_BMFace *UNUSED(self), PyObject *args)
diff --git a/source/blender/python/bmesh/bmesh_py_ops.c b/source/blender/python/bmesh/bmesh_py_ops.c
index 4fc0160bbd6..ee96c859858 100644
--- a/source/blender/python/bmesh/bmesh_py_ops.c
+++ b/source/blender/python/bmesh/bmesh_py_ops.c
@@ -37,17 +37,12 @@
#include "MEM_guardedalloc.h"
-#include "../generic/py_capi_utils.h"
#include "bmesh.h"
#include "bmesh_py_ops_call.h"
#include "bmesh_py_ops.h" /* own include */
-#include "bmesh_py_types.h"
-
-#include "bmesh_py_utils.h"
-
/* bmesh operator 'bmesh.ops.*' callable types
* ******************************************* */
static PyTypeObject bmesh_op_Type;
diff --git a/source/blender/python/bmesh/bmesh_py_ops_call.c b/source/blender/python/bmesh/bmesh_py_ops_call.c
index 9c9b69186ab..1dc70c3d288 100644
--- a/source/blender/python/bmesh/bmesh_py_ops_call.c
+++ b/source/blender/python/bmesh/bmesh_py_ops_call.c
@@ -27,7 +27,7 @@
* \ingroup pybmesh
*
* This file provides __call__ aka BPy_BMO_call for
- * the bmesh operatorand has been given its own file
+ * the bmesh operator and has been given its own file
* because argument conversion is involved.
*/
@@ -39,11 +39,11 @@
#include "bmesh.h"
-#include "bmesh_py_ops.h"
#include "bmesh_py_ops_call.h" /* own include */
#include "bmesh_py_types.h"
-#include "bmesh_py_utils.h"
+
+#include "../generic/python_utildefines.h"
static int bpy_bm_op_as_py_error(BMesh *bm)
{
@@ -69,9 +69,10 @@ static int bpy_bm_op_as_py_error(BMesh *bm)
* \param htype Test \a value matches this type.
* \param descr Description text.
*/
-static int bpy_slot_from_py_elem_check(BPy_BMElem *value, BMesh *bm, const char htype,
- /* for error messages */
- const char *opname, const char *slot_name, const char *descr)
+static int bpy_slot_from_py_elem_check(
+ BPy_BMElem *value, BMesh *bm, const char htype,
+ /* for error messages */
+ const char *opname, const char *slot_name, const char *descr)
{
if (!BPy_BMElem_Check(value) ||
!(value->ele->head.htype & htype))
@@ -107,10 +108,11 @@ static int bpy_slot_from_py_elem_check(BPy_BMElem *value, BMesh *bm, const char
* \param htype_bmo The type(s) supported by the target slot.
* \param descr Description text.
*/
-static int bpy_slot_from_py_elemseq_check(BPy_BMGeneric *value, BMesh *bm,
- const char htype_py, const char htype_bmo,
- /* for error messages */
- const char *opname, const char *slot_name, const char *descr)
+static int bpy_slot_from_py_elemseq_check(
+ BPy_BMGeneric *value, BMesh *bm,
+ const char htype_py, const char htype_bmo,
+ /* for error messages */
+ const char *opname, const char *slot_name, const char *descr)
{
if (value->bm == NULL) {
PyErr_Format(PyExc_TypeError,
@@ -142,9 +144,10 @@ static int bpy_slot_from_py_elemseq_check(BPy_BMGeneric *value, BMesh *bm,
/**
* Use for giving py args to an operator.
*/
-static int bpy_slot_from_py(BMesh *bm, BMOperator *bmop, BMOpSlot *slot, PyObject *value,
- /* the are just for exception messages */
- const char *opname, const char *slot_name)
+static int bpy_slot_from_py(
+ BMesh *bm, BMOperator *bmop, BMOpSlot *slot, PyObject *value,
+ /* the are just for exception messages */
+ const char *opname, const char *slot_name)
{
switch (slot->slot_type) {
case BMO_OP_SLOT_BOOL:
@@ -507,7 +510,7 @@ static int bpy_slot_from_py(BMesh *bm, BMOperator *bmop, BMOpSlot *slot, PyObjec
return -1;
}
}
- /* fall-through */
+ break;
}
default:
/* TODO --- many others */
@@ -542,20 +545,20 @@ static PyObject *bpy_slot_to_py(BMesh *bm, BMOpSlot *slot)
item = PyFloat_FromDouble((double)BMO_SLOT_AS_FLOAT(slot));
break;
case BMO_OP_SLOT_MAT:
- item = Matrix_CreatePyObject((float *)BMO_SLOT_AS_MATRIX(slot), 4, 4, Py_NEW, NULL);
+ item = Matrix_CreatePyObject((float *)BMO_SLOT_AS_MATRIX(slot), 4, 4, NULL);
break;
case BMO_OP_SLOT_VEC:
- item = Vector_CreatePyObject(BMO_SLOT_AS_VECTOR(slot), slot->len, Py_NEW, NULL);
+ item = Vector_CreatePyObject(BMO_SLOT_AS_VECTOR(slot), slot->len, NULL);
break;
case BMO_OP_SLOT_PTR:
BLI_assert(0); /* currently we don't have any pointer return values in use */
- item = (Py_INCREF(Py_None), Py_None);
+ item = Py_INCREF_RET(Py_None);
break;
case BMO_OP_SLOT_ELEMENT_BUF:
{
if (slot->slot_subtype.elem & BMO_OP_SLOT_SUBTYPE_ELEM_IS_SINGLE) {
BMHeader *ele = BMO_slot_buffer_get_single(slot);
- item = ele ? BPy_BMElem_CreatePyObject(bm, ele) : (Py_INCREF(Py_None), Py_None);
+ item = ele ? BPy_BMElem_CreatePyObject(bm, ele) : Py_INCREF_RET(Py_None);
}
else {
const int size = slot->len;
@@ -666,7 +669,7 @@ static PyObject *bpy_slot_to_py(BMesh *bm, BMOpSlot *slot)
}
case BMO_OP_SLOT_SUBTYPE_MAP_INTERNAL:
/* can't convert from these */
- item = (Py_INCREF(Py_None), Py_None);
+ item = Py_INCREF_RET(Py_None);
break;
}
break;
@@ -745,7 +748,7 @@ PyObject *BPy_BMO_call(BPy_BMeshOpFunc *self, PyObject *args, PyObject *kw)
ret = NULL; /* exception raised above */
}
else if (bmop.slots_out[0].slot_name == NULL) {
- ret = (Py_INCREF(Py_None), Py_None);
+ ret = Py_INCREF_RET(Py_None);
}
else {
/* build return value */
@@ -761,7 +764,7 @@ PyObject *BPy_BMO_call(BPy_BMeshOpFunc *self, PyObject *args, PyObject *kw)
/* this function doesn't throw exceptions */
item = bpy_slot_to_py(bm, slot);
if (item == NULL) {
- item = (Py_INCREF(Py_None), Py_None);
+ item = Py_INCREF_RET(Py_None);
}
#if 1
diff --git a/source/blender/python/bmesh/bmesh_py_types.c b/source/blender/python/bmesh/bmesh_py_types.c
index a31345cd7f5..bf773d3d9c3 100644
--- a/source/blender/python/bmesh/bmesh_py_types.c
+++ b/source/blender/python/bmesh/bmesh_py_types.c
@@ -27,9 +27,8 @@
* \ingroup pybmesh
*/
-#include <Python.h>
-
#include "BLI_math.h"
+#include "BLI_sort.h"
#include "DNA_mesh_types.h"
#include "DNA_object_types.h"
@@ -41,9 +40,12 @@
#include "bmesh.h"
+#include <Python.h>
+
#include "../mathutils/mathutils.h"
#include "../generic/py_capi_utils.h"
+#include "../generic/python_utildefines.h"
#include "bmesh_py_types.h" /* own include */
#include "bmesh_py_types_select.h"
@@ -78,6 +80,8 @@ PyC_FlagSet bpy_bm_htype_all_flags[] = {
{0, NULL}
};
+#define BPY_BM_HFLAG_ALL_STR "('SELECT', 'HIDE', 'SEAM', 'SMOOTH', 'TAG')"
+
PyC_FlagSet bpy_bm_hflag_all_flags[] = {
{BM_ELEM_SELECT, "SELECT"},
{BM_ELEM_HIDDEN, "HIDE"},
@@ -342,7 +346,7 @@ PyDoc_STRVAR(bpy_bmvert_co_doc,
static PyObject *bpy_bmvert_co_get(BPy_BMVert *self)
{
BPY_BM_CHECK_OBJ(self);
- return Vector_CreatePyObject(self->v->co, 3, Py_WRAP, NULL);
+ return Vector_CreatePyObject_wrap(self->v->co, 3, NULL);
}
static int bpy_bmvert_co_set(BPy_BMVert *self, PyObject *value)
@@ -364,7 +368,7 @@ PyDoc_STRVAR(bpy_bmvert_normal_doc,
static PyObject *bpy_bmvert_normal_get(BPy_BMVert *self)
{
BPY_BM_CHECK_OBJ(self);
- return Vector_CreatePyObject(self->v->no, 3, Py_WRAP, NULL);
+ return Vector_CreatePyObject_wrap(self->v->no, 3, NULL);
}
static int bpy_bmvert_normal_set(BPy_BMVert *self, PyObject *value)
@@ -468,7 +472,7 @@ PyDoc_STRVAR(bpy_bmface_normal_doc,
static PyObject *bpy_bmface_normal_get(BPy_BMFace *self)
{
BPY_BM_CHECK_OBJ(self);
- return Vector_CreatePyObject(self->f->no, 3, Py_WRAP, NULL);
+ return Vector_CreatePyObject_wrap(self->f->no, 3, NULL);
}
static int bpy_bmface_normal_set(BPy_BMFace *self, PyObject *value)
@@ -940,16 +944,22 @@ static PyObject *bpy_bmesh_from_object(BPy_BMesh *self, PyObject *args)
Object *ob;
struct Scene *scene;
BMesh *bm;
- int use_deform = true;
- int use_render = false;
- int use_cage = false;
- int use_fnorm = true;
+ bool use_deform = true;
+ bool use_render = false;
+ bool use_cage = false;
+ bool use_fnorm = true;
DerivedMesh *dm;
const int mask = CD_MASK_BMESH;
BPY_BM_CHECK_OBJ(self);
- if (!PyArg_ParseTuple(args, "OO|iiii:from_object", &py_object, &py_scene, &use_render, &use_cage, &use_fnorm) ||
+ if (!PyArg_ParseTuple(
+ args, "OO|O&O&O&O&:from_object",
+ &py_object, &py_scene,
+ PyC_ParseBool, &use_deform,
+ PyC_ParseBool, &use_render,
+ PyC_ParseBool, &use_cage,
+ PyC_ParseBool, &use_fnorm) ||
!(ob = PyC_RNA_AsPointer(py_object, "Object")) ||
!(scene = PyC_RNA_AsPointer(py_scene, "Scene")))
{
@@ -1041,14 +1051,18 @@ static PyObject *bpy_bmesh_from_mesh(BPy_BMesh *self, PyObject *args, PyObject *
BMesh *bm;
PyObject *py_mesh;
Mesh *me;
- int use_fnorm = true;
- int use_shape_key = false;
+ bool use_fnorm = true;
+ bool use_shape_key = false;
int shape_key_index = 0;
BPY_BM_CHECK_OBJ(self);
- if (!PyArg_ParseTupleAndKeywords(args, kw, "O|iii:from_mesh", (char **)kwlist,
- &py_mesh, &use_fnorm, &use_shape_key, &shape_key_index) ||
+ if (!PyArg_ParseTupleAndKeywords(
+ args, kw, "O|O&O&i:from_mesh", (char **)kwlist,
+ &py_mesh,
+ PyC_ParseBool, &use_fnorm,
+ PyC_ParseBool, &use_shape_key,
+ &shape_key_index) ||
!(me = PyC_RNA_AsPointer(py_mesh, "Mesh")))
{
return NULL;
@@ -1127,7 +1141,7 @@ PyDoc_STRVAR(bpy_bmesh_transform_doc,
"\n"
" :arg matrix: transform matrix.\n"
" :type matrix: 4x4 :class:`mathutils.Matrix`\n"
-" :arg filter: set of values in ('SELECT', 'HIDE', 'SEAM', 'SMOOTH', 'TAG').\n"
+" :arg filter: set of values in " BPY_BM_HFLAG_ALL_STR ".\n"
" :type filter: set\n"
);
static PyObject *bpy_bmesh_transform(BPy_BMElem *self, PyObject *args, PyObject *kw)
@@ -1421,17 +1435,44 @@ static PyObject *bpy_bmvert_copy_from_face_interp(BPy_BMVert *self, PyObject *ar
PyDoc_STRVAR(bpy_bmvert_calc_edge_angle_doc,
-".. method:: calc_vert_angle()\n"
+".. method:: calc_edge_angle(fallback=None)\n"
"\n"
" Return the angle between this vert's two connected edges.\n"
"\n"
+" :arg fallback: return this when the vert doesn't have 2 edges\n"
+" (instead of raising a :exc:`ValueError`).\n"
+" :type fallback: any\n"
" :return: Angle between edges in radians.\n"
" :rtype: float\n"
);
-static PyObject *bpy_bmvert_calc_edge_angle(BPy_BMVert *self)
+static PyObject *bpy_bmvert_calc_edge_angle(BPy_BMVert *self, PyObject *args)
{
+ const float angle_invalid = -1.0f;
+ float angle;
+ PyObject *fallback = NULL;
+
BPY_BM_CHECK_OBJ(self);
- return PyFloat_FromDouble(BM_vert_calc_edge_angle(self->v));
+
+ if (!PyArg_ParseTuple(args, "|O:calc_edge_angle", &fallback))
+ return NULL;
+
+ angle = BM_vert_calc_edge_angle_ex(self->v, angle_invalid);
+
+ if (angle == angle_invalid) {
+ /* avoid exception */
+ if (fallback) {
+ Py_INCREF(fallback);
+ return fallback;
+ }
+ else {
+ PyErr_SetString(PyExc_ValueError,
+ "BMVert.calc_edge_angle(): "
+ "vert doesn't use 2 edges");
+ return NULL;
+ }
+ }
+
+ return PyFloat_FromDouble(angle);
}
PyDoc_STRVAR(bpy_bmvert_calc_shell_factor_doc,
@@ -1481,27 +1522,81 @@ static PyObject *bpy_bmedge_calc_length(BPy_BMEdge *self)
}
PyDoc_STRVAR(bpy_bmedge_calc_face_angle_doc,
-".. method:: calc_face_angle()\n"
+".. method:: calc_face_angle(fallback=None)\n"
"\n"
+" :arg fallback: return this when the edge doesn't have 2 faces\n"
+" (instead of raising a :exc:`ValueError`).\n"
+" :type fallback: any\n"
" :return: The angle between 2 connected faces in radians.\n"
" :rtype: float\n"
);
-static PyObject *bpy_bmedge_calc_face_angle(BPy_BMEdge *self)
+static PyObject *bpy_bmedge_calc_face_angle(BPy_BMEdge *self, PyObject *args)
{
+ const float angle_invalid = -1.0f;
+ float angle;
+ PyObject *fallback = NULL;
+
BPY_BM_CHECK_OBJ(self);
- return PyFloat_FromDouble(BM_edge_calc_face_angle(self->e));
+
+ if (!PyArg_ParseTuple(args, "|O:calc_face_angle", &fallback))
+ return NULL;
+
+ angle = BM_edge_calc_face_angle_ex(self->e, angle_invalid);
+
+ if (angle == angle_invalid) {
+ /* avoid exception */
+ if (fallback) {
+ Py_INCREF(fallback);
+ return fallback;
+ }
+ else {
+ PyErr_SetString(PyExc_ValueError,
+ "BMEdge.calc_face_angle(): "
+ "edge doesn't use 2 faces");
+ return NULL;
+ }
+ }
+
+ return PyFloat_FromDouble(angle);
}
PyDoc_STRVAR(bpy_bmedge_calc_face_angle_signed_doc,
-".. method:: calc_face_angle_signed()\n"
+".. method:: calc_face_angle_signed(fallback=None)\n"
"\n"
+" :arg fallback: return this when the edge doesn't have 2 faces\n"
+" (instead of raising a :exc:`ValueError`).\n"
+" :type fallback: any\n"
" :return: The angle between 2 connected faces in radians (negative for concave join).\n"
" :rtype: float\n"
);
-static PyObject *bpy_bmedge_calc_face_angle_signed(BPy_BMEdge *self)
+static PyObject *bpy_bmedge_calc_face_angle_signed(BPy_BMEdge *self, PyObject *args)
{
+ const float angle_invalid = -FLT_MAX;
+ float angle;
+ PyObject *fallback = NULL;
+
BPY_BM_CHECK_OBJ(self);
- return PyFloat_FromDouble(BM_edge_calc_face_angle_signed(self->e));
+
+ if (!PyArg_ParseTuple(args, "|O:calc_face_angle_signed", &fallback))
+ return NULL;
+
+ angle = BM_edge_calc_face_angle_signed_ex(self->e, angle_invalid);
+
+ if (angle == angle_invalid) {
+ /* avoid exception */
+ if (fallback) {
+ Py_INCREF(fallback);
+ return fallback;
+ }
+ else {
+ PyErr_SetString(PyExc_ValueError,
+ "BMEdge.calc_face_angle_signed(): "
+ "edge doesn't use 2 faces");
+ return NULL;
+ }
+ }
+
+ return PyFloat_FromDouble(angle);
}
PyDoc_STRVAR(bpy_bmedge_calc_tangent_doc,
@@ -1530,7 +1625,7 @@ static PyObject *bpy_bmedge_calc_tangent(BPy_BMEdge *self, PyObject *args)
BPY_BM_CHECK_OBJ(py_loop);
/* no need to check if they are from the same mesh or even connected */
BM_edge_calc_face_tangent(self->e, py_loop->l, vec);
- return Vector_CreatePyObject(vec, 3, Py_NEW, NULL);
+ return Vector_CreatePyObject(vec, 3, NULL);
}
}
@@ -1602,12 +1697,14 @@ PyDoc_STRVAR(bpy_bmface_copy_from_face_interp_doc,
static PyObject *bpy_bmface_copy_from_face_interp(BPy_BMFace *self, PyObject *args)
{
BPy_BMFace *py_face = NULL;
- int do_vertex = true;
+ bool do_vertex = true;
BPY_BM_CHECK_OBJ(self);
- if (!PyArg_ParseTuple(args, "O!|i:BMFace.copy_from_face_interp",
- &BPy_BMFace_Type, &py_face, &do_vertex))
+ if (!PyArg_ParseTuple(
+ args, "O!|O&:BMFace.copy_from_face_interp",
+ &BPy_BMFace_Type, &py_face,
+ PyC_ParseBool, &do_vertex))
{
return NULL;
}
@@ -1640,16 +1737,17 @@ static PyObject *bpy_bmface_copy(BPy_BMFace *self, PyObject *args, PyObject *kw)
static const char *kwlist[] = {"verts", "edges", NULL};
BMesh *bm = self->bm;
- int do_verts = true;
- int do_edges = true;
+ bool do_verts = true;
+ bool do_edges = true;
BMFace *f_cpy;
BPY_BM_CHECK_OBJ(self);
- if (!PyArg_ParseTupleAndKeywords(args, kw,
- "|ii:BMFace.copy",
- (char **)kwlist,
- &do_verts, &do_edges))
+ if (!PyArg_ParseTupleAndKeywords(
+ args, kw,
+ "|O&O&:BMFace.copy", (char **)kwlist,
+ PyC_ParseBool, &do_verts,
+ PyC_ParseBool, &do_edges))
{
return NULL;
}
@@ -1711,7 +1809,7 @@ static PyObject *bpy_bmface_calc_center_mean(BPy_BMFace *self)
BPY_BM_CHECK_OBJ(self);
BM_face_calc_center_mean(self->f, cent);
- return Vector_CreatePyObject(cent, 3, Py_NEW, NULL);
+ return Vector_CreatePyObject(cent, 3, NULL);
}
PyDoc_STRVAR(bpy_bmface_calc_center_mean_weighted_doc,
@@ -1728,7 +1826,7 @@ static PyObject *bpy_bmface_calc_center_mean_weighted(BPy_BMFace *self)
BPY_BM_CHECK_OBJ(self);
BM_face_calc_center_mean_weighted(self->f, cent);
- return Vector_CreatePyObject(cent, 3, Py_NEW, NULL);
+ return Vector_CreatePyObject(cent, 3, NULL);
}
PyDoc_STRVAR(bpy_bmface_calc_center_bounds_doc,
@@ -1745,7 +1843,7 @@ static PyObject *bpy_bmface_calc_center_bounds(BPy_BMFace *self)
BPY_BM_CHECK_OBJ(self);
BM_face_calc_center_bounds(self->f, cent);
- return Vector_CreatePyObject(cent, 3, Py_NEW, NULL);
+ return Vector_CreatePyObject(cent, 3, NULL);
}
@@ -1797,14 +1895,16 @@ PyDoc_STRVAR(bpy_bmloop_copy_from_face_interp_doc,
static PyObject *bpy_bmloop_copy_from_face_interp(BPy_BMLoop *self, PyObject *args)
{
BPy_BMFace *py_face = NULL;
- int do_vertex = true;
- int do_multires = true;
+ bool do_vertex = true;
+ bool do_multires = true;
BPY_BM_CHECK_OBJ(self);
- if (!PyArg_ParseTuple(args, "O!|ii:BMLoop.copy_from_face_interp",
- &BPy_BMFace_Type, &py_face,
- &do_vertex, &do_multires))
+ if (!PyArg_ParseTuple(
+ args, "O!|O&O&:BMLoop.copy_from_face_interp",
+ &BPy_BMFace_Type, &py_face,
+ PyC_ParseBool, &do_vertex,
+ PyC_ParseBool, &do_multires))
{
return NULL;
}
@@ -1849,7 +1949,7 @@ static PyObject *bpy_bmloop_calc_normal(BPy_BMLoop *self)
float vec[3];
BPY_BM_CHECK_OBJ(self);
BM_loop_calc_face_normal(self->l, vec);
- return Vector_CreatePyObject(vec, 3, Py_NEW, NULL);
+ return Vector_CreatePyObject(vec, 3, NULL);
}
PyDoc_STRVAR(bpy_bmloop_calc_tangent_doc,
@@ -1866,7 +1966,7 @@ static PyObject *bpy_bmloop_calc_tangent(BPy_BMLoop *self)
float vec[3];
BPY_BM_CHECK_OBJ(self);
BM_loop_calc_face_tangent(self->l, vec);
- return Vector_CreatePyObject(vec, 3, Py_NEW, NULL);
+ return Vector_CreatePyObject(vec, 3, NULL);
}
/* Vert Seq
@@ -2311,6 +2411,22 @@ static PyObject *bpy_bmelemseq_index_update(BPy_BMElemSeq *self)
Py_RETURN_NONE;
}
+PyDoc_STRVAR(bpy_bmelemseq_ensure_lookup_table_doc,
+".. method:: ensure_lookup_table()\n"
+"\n"
+" Ensure internal data needed for int subscription is initialized with verts/edges/faces, eg ``bm.verts[index]``.\n"
+"\n"
+" This needs to be called again after adding/removing data in this sequence."
+);
+static PyObject *bpy_bmelemseq_ensure_lookup_table(BPy_BMElemSeq *self)
+{
+ BPY_BM_CHECK_OBJ(self);
+
+ BM_mesh_elem_table_ensure(self->bm, bm_iter_itype_htype_map[self->itype]);
+
+ Py_RETURN_NONE;
+}
+
PyDoc_STRVAR(bpy_bmelemseq_sort_doc,
".. method:: sort(key=None, reverse=False)\n"
"\n"
@@ -2327,6 +2443,9 @@ PyDoc_STRVAR(bpy_bmelemseq_sort_doc,
" When the 'key' argument is not provided, the elements are reordered following their current index value.\n"
" In particular this can be used by setting indices manually before calling this method.\n"
"\n"
+" .. warning::\n"
+"\n"
+" Existing references to the N'th element, will continue to point the data at that index.\n"
);
/* Use a static variable here because there is the need to sort some array
@@ -2340,10 +2459,10 @@ PyDoc_STRVAR(bpy_bmelemseq_sort_doc,
* Note: the functions below assumes the keys array has been allocated and it
* has enough elements to complete the task.
*/
-static double *keys = NULL;
-static int bpy_bmelemseq_sort_cmp_by_keys_ascending(const void *index1_v, const void *index2_v)
+static int bpy_bmelemseq_sort_cmp_by_keys_ascending(const void *index1_v, const void *index2_v, void *keys_v)
{
+ const double *keys = keys_v;
const int *index1 = (int *)index1_v;
const int *index2 = (int *)index2_v;
@@ -2352,16 +2471,16 @@ static int bpy_bmelemseq_sort_cmp_by_keys_ascending(const void *index1_v, const
else return 0;
}
-static int bpy_bmelemseq_sort_cmp_by_keys_descending(const void *index1_v, const void *index2_v)
+static int bpy_bmelemseq_sort_cmp_by_keys_descending(const void *index1_v, const void *index2_v, void *keys_v)
{
- return -bpy_bmelemseq_sort_cmp_by_keys_ascending(index1_v, index2_v);
+ return -bpy_bmelemseq_sort_cmp_by_keys_ascending(index1_v, index2_v, keys_v);
}
static PyObject *bpy_bmelemseq_sort(BPy_BMElemSeq *self, PyObject *args, PyObject *kw)
{
static const char *kwlist[] = {"key", "reverse", NULL};
PyObject *keyfunc = NULL; /* optional */
- int do_reverse = false; /* optional */
+ bool do_reverse = false; /* optional */
const char htype = bm_iter_itype_htype_map[self->itype];
int n_elem;
@@ -2369,9 +2488,10 @@ static PyObject *bpy_bmelemseq_sort(BPy_BMElemSeq *self, PyObject *args, PyObjec
BMIter iter;
BMElem *ele;
+ double *keys;
int *elem_idx;
unsigned int *elem_map_idx;
- int (*elem_idx_compare_by_keys)(const void *, const void *);
+ int (*elem_idx_compare_by_keys)(const void *, const void *, void *);
unsigned int *vert_idx = NULL;
unsigned int *edge_idx = NULL;
@@ -2383,10 +2503,11 @@ static PyObject *bpy_bmelemseq_sort(BPy_BMElemSeq *self, PyObject *args, PyObjec
BPY_BM_CHECK_OBJ(self);
if (args != NULL) {
- if (!PyArg_ParseTupleAndKeywords(args, kw,
- "|Oi:BMElemSeq.sort",
- (char **)kwlist,
- &keyfunc, &do_reverse))
+ if (!PyArg_ParseTupleAndKeywords(
+ args, kw,
+ "|OO&:BMElemSeq.sort", (char **)kwlist,
+ &keyfunc,
+ PyC_ParseBool, &do_reverse))
{
return NULL;
}
@@ -2461,7 +2582,7 @@ static PyObject *bpy_bmelemseq_sort(BPy_BMElemSeq *self, PyObject *args, PyObjec
else
elem_idx_compare_by_keys = bpy_bmelemseq_sort_cmp_by_keys_ascending;
- qsort(elem_idx, n_elem, sizeof(*elem_idx), elem_idx_compare_by_keys);
+ BLI_qsort_r(elem_idx, n_elem, sizeof(*elem_idx), elem_idx_compare_by_keys, keys);
elem_map_idx = PyMem_MALLOC(sizeof(*elem_map_idx) * n_elem);
if (elem_map_idx == NULL) {
@@ -2537,7 +2658,7 @@ static struct PyMethodDef bpy_bmvert_methods[] = {
{"copy_from_face_interp", (PyCFunction)bpy_bmvert_copy_from_face_interp, METH_VARARGS, bpy_bmvert_copy_from_face_interp_doc},
{"copy_from_vert_interp", (PyCFunction)bpy_bmvert_copy_from_vert_interp, METH_VARARGS, bpy_bmvert_copy_from_vert_interp_doc},
- {"calc_vert_angle", (PyCFunction)bpy_bmvert_calc_edge_angle, METH_NOARGS, bpy_bmvert_calc_edge_angle_doc},
+ {"calc_edge_angle", (PyCFunction)bpy_bmvert_calc_edge_angle, METH_VARARGS, bpy_bmvert_calc_edge_angle_doc},
{"calc_shell_factor", (PyCFunction)bpy_bmvert_calc_shell_factor, METH_NOARGS, bpy_bmvert_calc_shell_factor_doc},
{"normal_update", (PyCFunction)bpy_bmvert_normal_update, METH_NOARGS, bpy_bmvert_normal_update_doc},
@@ -2553,8 +2674,8 @@ static struct PyMethodDef bpy_bmedge_methods[] = {
{"other_vert", (PyCFunction)bpy_bmedge_other_vert, METH_O, bpy_bmedge_other_vert_doc},
{"calc_length", (PyCFunction)bpy_bmedge_calc_length, METH_NOARGS, bpy_bmedge_calc_length_doc},
- {"calc_face_angle", (PyCFunction)bpy_bmedge_calc_face_angle, METH_NOARGS, bpy_bmedge_calc_face_angle_doc},
- {"calc_face_angle_signed", (PyCFunction)bpy_bmedge_calc_face_angle_signed, METH_NOARGS, bpy_bmedge_calc_face_angle_signed_doc},
+ {"calc_face_angle", (PyCFunction)bpy_bmedge_calc_face_angle, METH_VARARGS, bpy_bmedge_calc_face_angle_doc},
+ {"calc_face_angle_signed", (PyCFunction)bpy_bmedge_calc_face_angle_signed, METH_VARARGS, bpy_bmedge_calc_face_angle_signed_doc},
{"calc_tangent", (PyCFunction)bpy_bmedge_calc_tangent, METH_VARARGS, bpy_bmedge_calc_tangent_doc},
{"normal_update", (PyCFunction)bpy_bmedge_normal_update, METH_NOARGS, bpy_bmedge_normal_update_doc},
@@ -2605,6 +2726,7 @@ static struct PyMethodDef bpy_bmvertseq_methods[] = {
/* odd function, initializes index values */
{"index_update", (PyCFunction)bpy_bmelemseq_index_update, METH_NOARGS, bpy_bmelemseq_index_update_doc},
+ {"ensure_lookup_table", (PyCFunction)bpy_bmelemseq_ensure_lookup_table, METH_NOARGS, bpy_bmelemseq_ensure_lookup_table_doc},
{"sort", (PyCFunction)bpy_bmelemseq_sort, METH_VARARGS | METH_KEYWORDS, bpy_bmelemseq_sort_doc},
{NULL, NULL, 0, NULL}
};
@@ -2617,6 +2739,7 @@ static struct PyMethodDef bpy_bmedgeseq_methods[] = {
/* odd function, initializes index values */
{"index_update", (PyCFunction)bpy_bmelemseq_index_update, METH_NOARGS, bpy_bmelemseq_index_update_doc},
+ {"ensure_lookup_table", (PyCFunction)bpy_bmelemseq_ensure_lookup_table, METH_NOARGS, bpy_bmelemseq_ensure_lookup_table_doc},
{"sort", (PyCFunction)bpy_bmelemseq_sort, METH_VARARGS | METH_KEYWORDS, bpy_bmelemseq_sort_doc},
{NULL, NULL, 0, NULL}
};
@@ -2629,6 +2752,7 @@ static struct PyMethodDef bpy_bmfaceseq_methods[] = {
/* odd function, initializes index values */
{"index_update", (PyCFunction)bpy_bmelemseq_index_update, METH_NOARGS, bpy_bmelemseq_index_update_doc},
+ {"ensure_lookup_table", (PyCFunction)bpy_bmelemseq_ensure_lookup_table, METH_NOARGS, bpy_bmelemseq_ensure_lookup_table_doc},
{"sort", (PyCFunction)bpy_bmelemseq_sort, METH_VARARGS | METH_KEYWORDS, bpy_bmelemseq_sort_doc},
{NULL, NULL, 0, NULL}
};
@@ -2725,9 +2849,43 @@ static PyObject *bpy_bmelemseq_subscript_int(BPy_BMElemSeq *self, int keynum)
if (keynum < 0) keynum += bpy_bmelemseq_length(self); /* only get length on negative value, may loop entire seq */
if (keynum >= 0) {
- BMHeader *ele = BM_iter_at_index(self->bm, self->itype, self->py_ele ? self->py_ele->ele : NULL, keynum);
- if (ele) {
- return BPy_BMElem_CreatePyObject(self->bm, ele);
+ if (self->itype <= BM_FACES_OF_MESH) {
+ if ((self->bm->elem_table_dirty & bm_iter_itype_htype_map[self->itype]) == 0) {
+ BMHeader *ele = NULL;
+ switch (self->itype) {
+ case BM_VERTS_OF_MESH:
+ if (keynum < self->bm->totvert) {
+ ele = (BMHeader *)self->bm->vtable[keynum];
+ }
+ break;
+ case BM_EDGES_OF_MESH:
+ if (keynum < self->bm->totedge) {
+ ele = (BMHeader *)self->bm->etable[keynum];
+ }
+ break;
+ case BM_FACES_OF_MESH:
+ if (keynum < self->bm->totface) {
+ ele = (BMHeader *)self->bm->ftable[keynum];
+ }
+ break;
+ }
+ if (ele) {
+ return BPy_BMElem_CreatePyObject(self->bm, ele);
+ }
+ /* fall through to index error below */
+ }
+ else {
+ PyErr_SetString(PyExc_IndexError,
+ "BMElemSeq[index]: outdated internal index table, "
+ "run ensure_lookup_table() first");
+ return NULL;
+ }
+ }
+ else {
+ BMHeader *ele = BM_iter_at_index(self->bm, self->itype, self->py_ele ? self->py_ele->ele : NULL, keynum);
+ if (ele) {
+ return BPy_BMElem_CreatePyObject(self->bm, ele);
+ }
}
}
@@ -2743,7 +2901,6 @@ static PyObject *bpy_bmelemseq_subscript_slice(BPy_BMElemSeq *self, Py_ssize_t s
bool ok;
PyObject *list;
- PyObject *item;
BMHeader *ele;
BPY_BM_CHECK_OBJ(self);
@@ -2768,9 +2925,7 @@ static PyObject *bpy_bmelemseq_subscript_slice(BPy_BMElemSeq *self, Py_ssize_t s
/* add items until stop */
while ((ele = BM_iter_step(&iter))) {
- item = BPy_BMElem_CreatePyObject(self->bm, ele);
- PyList_Append(list, item);
- Py_DECREF(item);
+ PyList_APPEND(list, BPy_BMElem_CreatePyObject(self->bm, ele));
count++;
if (count == stop) {
@@ -3119,17 +3274,17 @@ static PyObject *bpy_bmloop_repr(BPy_BMLoop *self)
/* Types
* ===== */
-PyTypeObject BPy_BMesh_Type = {{{0}}};
-PyTypeObject BPy_BMVert_Type = {{{0}}};
-PyTypeObject BPy_BMEdge_Type = {{{0}}};
-PyTypeObject BPy_BMFace_Type = {{{0}}};
-PyTypeObject BPy_BMLoop_Type = {{{0}}};
-PyTypeObject BPy_BMElemSeq_Type = {{{0}}};
-PyTypeObject BPy_BMVertSeq_Type = {{{0}}};
-PyTypeObject BPy_BMEdgeSeq_Type = {{{0}}};
-PyTypeObject BPy_BMFaceSeq_Type = {{{0}}};
-PyTypeObject BPy_BMLoopSeq_Type = {{{0}}};
-PyTypeObject BPy_BMIter_Type = {{{0}}};
+PyTypeObject BPy_BMesh_Type;
+PyTypeObject BPy_BMVert_Type;
+PyTypeObject BPy_BMEdge_Type;
+PyTypeObject BPy_BMFace_Type;
+PyTypeObject BPy_BMLoop_Type;
+PyTypeObject BPy_BMElemSeq_Type;
+PyTypeObject BPy_BMVertSeq_Type;
+PyTypeObject BPy_BMEdgeSeq_Type;
+PyTypeObject BPy_BMFaceSeq_Type;
+PyTypeObject BPy_BMLoopSeq_Type;
+PyTypeObject BPy_BMIter_Type;
@@ -3625,105 +3780,121 @@ void bpy_bm_generic_invalidate(BPy_BMGeneric *self)
*
* The 'bm_r' value is assigned when empty, and used when set.
*/
-void *BPy_BMElem_PySeq_As_Array(BMesh **r_bm, PyObject *seq, Py_ssize_t min, Py_ssize_t max, Py_ssize_t *r_size,
- const char htype,
- const bool do_unique_check, const bool do_bm_check,
- const char *error_prefix)
+void *BPy_BMElem_PySeq_As_Array_FAST(
+ BMesh **r_bm, PyObject *seq_fast, Py_ssize_t min, Py_ssize_t max, Py_ssize_t *r_size,
+ const char htype,
+ const bool do_unique_check, const bool do_bm_check,
+ const char *error_prefix)
{
BMesh *bm = (r_bm && *r_bm) ? *r_bm : NULL;
- PyObject *seq_fast;
+ PyObject **seq_fast_items = PySequence_Fast_ITEMS(seq_fast);
+ const Py_ssize_t seq_len = PySequence_Fast_GET_SIZE(seq_fast);
+ Py_ssize_t i;
+
+ BPy_BMElem *item;
+ BMElem **alloc;
+
*r_size = 0;
- if (!(seq_fast = PySequence_Fast(seq, error_prefix))) {
+ if (seq_len < min || seq_len > max) {
+ PyErr_Format(PyExc_TypeError,
+ "%s: sequence incorrect size, expected [%d - %d], given %d",
+ error_prefix, min, max, seq_len);
return NULL;
}
- else {
- Py_ssize_t seq_len;
- Py_ssize_t i;
- BPy_BMElem *item;
- BMElem **alloc;
+ /* from now on, use goto */
+ alloc = PyMem_MALLOC(seq_len * sizeof(BPy_BMElem **));
- seq_len = PySequence_Fast_GET_SIZE(seq_fast);
+ for (i = 0; i < seq_len; i++) {
+ item = (BPy_BMElem *)seq_fast_items[i];
- if (seq_len < min || seq_len > max) {
+ if (!BPy_BMElem_CheckHType(Py_TYPE(item), htype)) {
PyErr_Format(PyExc_TypeError,
- "%s: sequence incorrect size, expected [%d - %d], given %d",
- error_prefix, min, max, seq_len);
- return NULL;
+ "%s: expected %.200s, not '%.200s'",
+ error_prefix, BPy_BMElem_StringFromHType(htype), Py_TYPE(item)->tp_name);
+ goto err_cleanup;
+ }
+ else if (!BPY_BM_IS_VALID(item)) {
+ PyErr_Format(PyExc_TypeError,
+ "%s: %d %s has been removed",
+ error_prefix, i, Py_TYPE(item)->tp_name);
+ goto err_cleanup;
+ }
+ /* trick so we can ensure all items have the same mesh,
+ * and allows us to pass the 'bm' as NULL. */
+ else if (do_bm_check && (bm && bm != item->bm)) {
+ PyErr_Format(PyExc_ValueError,
+ "%s: %d %s is from another mesh",
+ error_prefix, i, BPy_BMElem_StringFromHType(htype));
+ goto err_cleanup;
}
+ if (bm == NULL) {
+ bm = item->bm;
+ }
- /* from now on, use goto */
- alloc = PyMem_MALLOC(seq_len * sizeof(BPy_BMElem **));
-
- for (i = 0; i < seq_len; i++) {
- item = (BPy_BMElem *)PySequence_Fast_GET_ITEM(seq_fast, i);
+ alloc[i] = item->ele;
- if (!BPy_BMElem_CheckHType(Py_TYPE(item), htype)) {
- PyErr_Format(PyExc_TypeError,
- "%s: expected %.200s, not '%.200s'",
- error_prefix, BPy_BMElem_StringFromHType(htype), Py_TYPE(item)->tp_name);
- goto err_cleanup;
- }
- else if (!BPY_BM_IS_VALID(item)) {
- PyErr_Format(PyExc_TypeError,
- "%s: %d %s has been removed",
- error_prefix, i, Py_TYPE(item)->tp_name);
- goto err_cleanup;
- }
- /* trick so we can ensure all items have the same mesh,
- * and allows us to pass the 'bm' as NULL. */
- else if (do_bm_check && (bm && bm != item->bm)) {
- PyErr_Format(PyExc_ValueError,
- "%s: %d %s is from another mesh",
- error_prefix, i, BPy_BMElem_StringFromHType(htype));
- goto err_cleanup;
- }
+ if (do_unique_check) {
+ BM_elem_flag_enable(item->ele, BM_ELEM_INTERNAL_TAG);
+ }
+ }
- if (bm == NULL) {
- bm = item->bm;
+ if (do_unique_check) {
+ /* check for double verts! */
+ bool ok = true;
+ for (i = 0; i < seq_len; i++) {
+ if (UNLIKELY(BM_elem_flag_test(alloc[i], BM_ELEM_INTERNAL_TAG) == false)) {
+ ok = false;
}
- alloc[i] = item->ele;
+ /* ensure we don't leave this enabled */
+ BM_elem_flag_disable(alloc[i], BM_ELEM_INTERNAL_TAG);
+ }
- if (do_unique_check) {
- BM_elem_flag_enable(item->ele, BM_ELEM_INTERNAL_TAG);
- }
+ if (ok == false) {
+ PyErr_Format(PyExc_ValueError,
+ "%s: found the same %.200s used multiple times",
+ error_prefix, BPy_BMElem_StringFromHType(htype));
+ goto err_cleanup;
}
+ }
- if (do_unique_check) {
- /* check for double verts! */
- bool ok = true;
- for (i = 0; i < seq_len; i++) {
- if (UNLIKELY(BM_elem_flag_test(alloc[i], BM_ELEM_INTERNAL_TAG) == false)) {
- ok = false;
- }
+ *r_size = seq_len;
+ if (r_bm) *r_bm = bm;
+ return alloc;
- /* ensure we don't leave this enabled */
- BM_elem_flag_disable(alloc[i], BM_ELEM_INTERNAL_TAG);
- }
+err_cleanup:
+ PyMem_FREE(alloc);
+ return NULL;
- if (ok == false) {
- PyErr_Format(PyExc_ValueError,
- "%s: found the same %.200s used multiple times",
- error_prefix, BPy_BMElem_StringFromHType(htype));
- goto err_cleanup;
- }
- }
+}
- Py_DECREF(seq_fast);
- *r_size = seq_len;
- if (r_bm) *r_bm = bm;
- return alloc;
+void *BPy_BMElem_PySeq_As_Array(
+ BMesh **r_bm, PyObject *seq, Py_ssize_t min, Py_ssize_t max, Py_ssize_t *r_size,
+ const char htype,
+ const bool do_unique_check, const bool do_bm_check,
+ const char *error_prefix)
+{
+ PyObject *seq_fast;
+ PyObject *ret;
-err_cleanup:
- Py_DECREF(seq_fast);
- PyMem_FREE(alloc);
+ if (!(seq_fast = PySequence_Fast(seq, error_prefix))) {
return NULL;
}
+
+ ret = BPy_BMElem_PySeq_As_Array_FAST(
+ r_bm, seq_fast, min, max, r_size,
+ htype,
+ do_unique_check, do_bm_check,
+ error_prefix);
+
+ Py_DECREF(seq_fast);
+ return ret;
}
+
PyObject *BPy_BMElem_Array_As_Tuple(BMesh *bm, BMHeader **elem, Py_ssize_t elem_len)
{
Py_ssize_t i;
diff --git a/source/blender/python/bmesh/bmesh_py_types.h b/source/blender/python/bmesh/bmesh_py_types.h
index a2c2c312e71..e6f0976965c 100644
--- a/source/blender/python/bmesh/bmesh_py_types.h
+++ b/source/blender/python/bmesh/bmesh_py_types.h
@@ -158,10 +158,16 @@ PyObject *BPy_BMIter_CreatePyObject(BMesh *bm);
PyObject *BPy_BMElem_CreatePyObject(BMesh *bm, BMHeader *ele); /* just checks type and creates v/e/f/l */
-void *BPy_BMElem_PySeq_As_Array(BMesh **r_bm, PyObject *seq, Py_ssize_t min, Py_ssize_t max, Py_ssize_t *r_size,
- const char htype,
- const bool do_unique_check, const bool do_bm_check,
- const char *error_prefix);
+void *BPy_BMElem_PySeq_As_Array_FAST(
+ BMesh **r_bm, PyObject *seq_fast, Py_ssize_t min, Py_ssize_t max, Py_ssize_t *r_size,
+ const char htype,
+ const bool do_unique_check, const bool do_bm_check,
+ const char *error_prefix);
+void *BPy_BMElem_PySeq_As_Array(
+ BMesh **r_bm, PyObject *seq, Py_ssize_t min, Py_ssize_t max, Py_ssize_t *r_size,
+ const char htype,
+ const bool do_unique_check, const bool do_bm_check,
+ const char *error_prefix);
PyObject *BPy_BMElem_Array_As_Tuple(BMesh *bm, BMHeader **elem, Py_ssize_t elem_len);
PyObject *BPy_BMVert_Array_As_Tuple(BMesh *bm, BMVert **elem, Py_ssize_t elem_len);
@@ -198,16 +204,17 @@ int bpy_bm_generic_valid_check_source(BMesh *bm_source, const char *error_prefi
#define BPY_BM_IS_VALID(obj) (LIKELY((obj)->bm != NULL))
-#define BM_ITER_BPY_BM_SEQ(ele, iter, bpy_bmelemseq) \
- for (ele = BM_iter_new(iter, \
- (bpy_bmelemseq)->bm, \
- (bpy_bmelemseq)->itype, \
- (bpy_bmelemseq)->py_ele ? \
- ((BPy_BMElem *)(bpy_bmelemseq)->py_ele)->ele : \
- NULL \
- ); \
- ele; \
- ele = BM_iter_step(iter))
+#define BM_ITER_BPY_BM_SEQ(ele, iter, bpy_bmelemseq) \
+ for (BM_CHECK_TYPE_ELEM_ASSIGN(ele) = BM_iter_new( \
+ iter, \
+ (bpy_bmelemseq)->bm, \
+ (bpy_bmelemseq)->itype, \
+ (bpy_bmelemseq)->py_ele ? \
+ ((BPy_BMElem *)(bpy_bmelemseq)->py_ele)->ele : \
+ NULL \
+ ); \
+ ele; \
+ BM_CHECK_TYPE_ELEM_ASSIGN(ele) = BM_iter_step(iter))
#ifdef __PY_CAPI_UTILS_H__
diff --git a/source/blender/python/bmesh/bmesh_py_types_customdata.c b/source/blender/python/bmesh/bmesh_py_types_customdata.c
index 6ecb01a8528..908f6b5a734 100644
--- a/source/blender/python/bmesh/bmesh_py_types_customdata.c
+++ b/source/blender/python/bmesh/bmesh_py_types_customdata.c
@@ -42,6 +42,7 @@
#include "bmesh_py_types_meshdata.h"
#include "../mathutils/mathutils.h"
+#include "../generic/python_utildefines.h"
#include "BKE_customdata.h"
@@ -115,6 +116,9 @@ PyDoc_STRVAR(bpy_bmlayeraccess_collection__color_doc,
PyDoc_STRVAR(bpy_bmlayeraccess_collection__skin_doc,
"Accessor for skin layer.\n\ntype: :class:`BMLayerCollection`"
);
+PyDoc_STRVAR(bpy_bmlayeraccess_collection__paint_mask_doc,
+"Accessor for paint mask layer.\n\ntype: :class:`BMLayerCollection`"
+);
#ifdef WITH_FREESTYLE
PyDoc_STRVAR(bpy_bmlayeraccess_collection__freestyle_edge_doc,
"Accessor for Freestyle edge layer.\n\ntype: :class:`BMLayerCollection`"
@@ -145,10 +149,9 @@ static PyObject *bpy_bmlayercollection_active_get(BPy_BMLayerItem *self, void *U
BPY_BM_CHECK_OBJ(self);
data = bpy_bm_customdata_get(self->bm, self->htype);
- index = CustomData_get_active_layer_index(data, self->type); /* absolute */
+ index = CustomData_get_active_layer(data, self->type); /* type relative */
if (index != -1) {
- index -= CustomData_get_layer_index(data, self->type); /* make relative */
return BPy_BMLayerItem_CreatePyObject(self->bm, self->htype, self->type, index);
}
else {
@@ -195,6 +198,7 @@ static PyGetSetDef bpy_bmlayeraccess_vert_getseters[] = {
{(char *)"shape", (getter)bpy_bmlayeraccess_collection_get, (setter)NULL, (char *)bpy_bmlayeraccess_collection__shape_doc, (void *)CD_SHAPEKEY},
{(char *)"bevel_weight", (getter)bpy_bmlayeraccess_collection_get, (setter)NULL, (char *)bpy_bmlayeraccess_collection__bevel_weight_doc, (void *)CD_BWEIGHT},
{(char *)"skin", (getter)bpy_bmlayeraccess_collection_get, (setter)NULL, (char *)bpy_bmlayeraccess_collection__skin_doc, (void *)CD_MVERT_SKIN},
+ {(char *)"paint_mask", (getter)bpy_bmlayeraccess_collection_get, (setter)NULL, (char *)bpy_bmlayeraccess_collection__paint_mask_doc, (void *)CD_PAINT_MASK},
{NULL, NULL, NULL, NULL, NULL} /* Sentinel */
};
@@ -325,15 +329,12 @@ static PyObject *bpy_bmlayercollection_verify(BPy_BMLayerCollection *self)
data = bpy_bm_customdata_get(self->bm, self->htype);
- index = CustomData_get_layer_index(data, self->type);
+ index = CustomData_get_active_layer(data, self->type); /* type relative */
if (index == -1) {
BM_data_layer_add(self->bm, data, self->type);
index = 0;
}
- else {
- index = CustomData_get_active_layer_index(data, self->type) - index; /* make relative */
- }
BLI_assert(index >= 0);
@@ -483,8 +484,9 @@ static PyObject *bpy_bmlayercollection_items(BPy_BMLayerCollection *self)
for (i = 0; tot-- > 0; index++) {
item = PyTuple_New(2);
- PyTuple_SET_ITEM(item, 0, PyUnicode_FromString(data->layers[index].name));
- PyTuple_SET_ITEM(item, 1, BPy_BMLayerItem_CreatePyObject(self->bm, self->htype, self->type, index));
+ PyTuple_SET_ITEMS(item,
+ PyUnicode_FromString(data->layers[index].name),
+ BPy_BMLayerItem_CreatePyObject(self->bm, self->htype, self->type, i));
PyList_SET_ITEM(ret, i++, item);
}
@@ -517,7 +519,7 @@ static PyObject *bpy_bmlayercollection_values(BPy_BMLayerCollection *self)
ret = PyList_New(tot);
for (i = 0; tot-- > 0; index++) {
- item = BPy_BMLayerItem_CreatePyObject(self->bm, self->htype, self->type, index);
+ item = BPy_BMLayerItem_CreatePyObject(self->bm, self->htype, self->type, i);
PyList_SET_ITEM(ret, i++, item);
}
@@ -551,15 +553,14 @@ static PyObject *bpy_bmlayercollection_get(BPy_BMLayerCollection *self, PyObject
int index;
data = bpy_bm_customdata_get(self->bm, self->htype);
- index = CustomData_get_named_layer_index(data, self->type, key); /* absolute index */
+ index = CustomData_get_named_layer(data, self->type, key); /* type relative */
if (index != -1) {
- index -= CustomData_get_layer_index(data, self->type); /* make relative */
return BPy_BMLayerItem_CreatePyObject(self->bm, self->htype, self->type, index);
}
}
- return Py_INCREF(def), def;
+ return Py_INCREF_RET(def);
}
static struct PyMethodDef bpy_bmlayeritem_methods[] = {
@@ -601,10 +602,9 @@ static PyObject *bpy_bmlayercollection_subscript_str(BPy_BMLayerCollection *self
BPY_BM_CHECK_OBJ(self);
data = bpy_bm_customdata_get(self->bm, self->htype);
- index = CustomData_get_named_layer_index(data, self->type, keyname); /* absolute */
+ index = CustomData_get_named_layer(data, self->type, keyname); /* type relative */
if (index != -1) {
- index -= CustomData_get_layer_index(data, self->type); /* make relative */
return BPy_BMLayerItem_CreatePyObject(self->bm, self->htype, self->type, index);
}
else {
@@ -785,12 +785,12 @@ PyDoc_STRVAR(bpy_bmlayeritem_type_doc,
);
-PyTypeObject BPy_BMLayerAccessVert_Type = {{{0}}}; /* bm.verts.layers */
-PyTypeObject BPy_BMLayerAccessEdge_Type = {{{0}}}; /* bm.edges.layers */
-PyTypeObject BPy_BMLayerAccessFace_Type = {{{0}}}; /* bm.faces.layers */
-PyTypeObject BPy_BMLayerAccessLoop_Type = {{{0}}}; /* bm.loops.layers */
-PyTypeObject BPy_BMLayerCollection_Type = {{{0}}}; /* bm.loops.layers.uv */
-PyTypeObject BPy_BMLayerItem_Type = {{{0}}}; /* bm.loops.layers.uv["UVMap"] */
+PyTypeObject BPy_BMLayerAccessVert_Type; /* bm.verts.layers */
+PyTypeObject BPy_BMLayerAccessEdge_Type; /* bm.edges.layers */
+PyTypeObject BPy_BMLayerAccessFace_Type; /* bm.faces.layers */
+PyTypeObject BPy_BMLayerAccessLoop_Type; /* bm.loops.layers */
+PyTypeObject BPy_BMLayerCollection_Type; /* bm.loops.layers.uv */
+PyTypeObject BPy_BMLayerItem_Type; /* bm.loops.layers.uv["UVMap"] */
PyObject *BPy_BMLayerAccess_CreatePyObject(BMesh *bm, const char htype)
@@ -982,6 +982,7 @@ PyObject *BPy_BMLayerItem_GetItem(BPy_BMElem *py_ele, BPy_BMLayerItem *py_layer)
break;
}
case CD_PROP_FLT:
+ case CD_PAINT_MASK:
{
ret = PyFloat_FromDouble(*(float *)value);
break;
@@ -1014,7 +1015,7 @@ PyObject *BPy_BMLayerItem_GetItem(BPy_BMElem *py_ele, BPy_BMLayerItem *py_layer)
}
case CD_SHAPEKEY:
{
- ret = Vector_CreatePyObject((float *)value, 3, Py_WRAP, NULL);
+ ret = Vector_CreatePyObject_wrap((float *)value, 3, NULL);
break;
}
case CD_BWEIGHT:
@@ -1059,6 +1060,7 @@ int BPy_BMLayerItem_SetItem(BPy_BMElem *py_ele, BPy_BMLayerItem *py_layer, PyObj
break;
}
case CD_PROP_FLT:
+ case CD_PAINT_MASK:
{
float tmp_val = PyFloat_AsDouble(py_value);
if (UNLIKELY(tmp_val == -1 && PyErr_Occurred())) {
diff --git a/source/blender/python/bmesh/bmesh_py_types_meshdata.c b/source/blender/python/bmesh/bmesh_py_types_meshdata.c
index 3512dc76cef..92c11a03433 100644
--- a/source/blender/python/bmesh/bmesh_py_types_meshdata.c
+++ b/source/blender/python/bmesh/bmesh_py_types_meshdata.c
@@ -45,6 +45,8 @@
#include "bmesh_py_types_meshdata.h"
+#include "../generic/python_utildefines.h"
+
/* Mesh BMTexPoly
* ************** */
@@ -97,7 +99,7 @@ static PyGetSetDef bpy_bmtexpoly_getseters[] = {
{NULL, NULL, NULL, NULL, NULL} /* Sentinel */
};
-static PyTypeObject BPy_BMTexPoly_Type = {{{0}}}; /* bm.loops.layers.uv.active */
+static PyTypeObject BPy_BMTexPoly_Type; /* bm.loops.layers.uv.active */
static void bm_init_types_bmtexpoly(void)
{
@@ -150,7 +152,7 @@ PyDoc_STRVAR(bpy_bmloopuv_uv_doc,
);
static PyObject *bpy_bmloopuv_uv_get(BPy_BMLoopUV *self, void *UNUSED(closure))
{
- return Vector_CreatePyObject(self->data->uv, 2, Py_WRAP, NULL);
+ return Vector_CreatePyObject_wrap(self->data->uv, 2, NULL);
}
static int bpy_bmloopuv_uv_set(BPy_BMLoopUV *self, PyObject *value, void *UNUSED(closure))
@@ -210,7 +212,7 @@ static PyGetSetDef bpy_bmloopuv_getseters[] = {
{NULL, NULL, NULL, NULL, NULL} /* Sentinel */
};
-PyTypeObject BPy_BMLoopUV_Type = {{{0}}}; /* bm.loops.layers.uv.active */
+PyTypeObject BPy_BMLoopUV_Type; /* bm.loops.layers.uv.active */
static void bm_init_types_bmloopuv(void)
{
@@ -263,7 +265,7 @@ PyDoc_STRVAR(bpy_bmvertskin_radius_doc,
);
static PyObject *bpy_bmvertskin_radius_get(BPy_BMVertSkin *self, void *UNUSED(closure))
{
- return Vector_CreatePyObject(self->data->radius, 2, Py_WRAP, NULL);
+ return Vector_CreatePyObject_wrap(self->data->radius, 2, NULL);
}
static int bpy_bmvertskin_radius_set(BPy_BMVertSkin *self, PyObject *value, void *UNUSED(closure))
@@ -319,7 +321,7 @@ static PyGetSetDef bpy_bmvertskin_getseters[] = {
{NULL, NULL, NULL, NULL, NULL} /* Sentinel */
};
-static PyTypeObject BPy_BMVertSkin_Type = {{{0}}}; /* bm.loops.layers.uv.active */
+static PyTypeObject BPy_BMVertSkin_Type; /* bm.loops.layers.uv.active */
static void bm_init_types_bmvertskin(void)
{
@@ -369,7 +371,7 @@ PyObject *BPy_BMVertSkin_CreatePyObject(struct MVertSkin *mvertskin)
static void mloopcol_to_float(const MLoopCol *mloopcol, float r_col[3])
{
- rgb_uchar_to_float(r_col, (unsigned char *)&mloopcol->r);
+ rgb_uchar_to_float(r_col, (const unsigned char *)&mloopcol->r);
}
static void mloopcol_from_float(MLoopCol *mloopcol, const float col[3])
@@ -684,10 +686,9 @@ static PyObject *bpy_bmdeformvert_items(BPy_BMDeformVert *self)
ret = PyList_New(self->data->totweight);
for (i = 0; i < self->data->totweight; i++, dw++) {
item = PyTuple_New(2);
-
- PyTuple_SET_ITEM(item, 0, PyLong_FromLong(dw->def_nr));
- PyTuple_SET_ITEM(item, 1, PyFloat_FromDouble(dw->weight));
-
+ PyTuple_SET_ITEMS(item,
+ PyLong_FromLong(dw->def_nr),
+ PyFloat_FromDouble(dw->weight));
PyList_SET_ITEM(ret, i, item);
}
@@ -721,7 +722,7 @@ static PyObject *bpy_bmdeformvert_get(BPy_BMDeformVert *self, PyObject *args)
return PyFloat_FromDouble(dw->weight);
}
else {
- return Py_INCREF(def), def;
+ return Py_INCREF_RET(def);
}
}
}
@@ -749,7 +750,7 @@ static struct PyMethodDef bpy_bmdeformvert_methods[] = {
{NULL, NULL, 0, NULL}
};
-PyTypeObject BPy_BMDeformVert_Type = {{{0}}}; /* bm.loops.layers.uv.active */
+PyTypeObject BPy_BMDeformVert_Type; /* bm.loops.layers.uv.active */
static void bm_init_types_bmdvert(void)
{
diff --git a/source/blender/python/bmesh/bmesh_py_types_select.c b/source/blender/python/bmesh/bmesh_py_types_select.c
index 3c72112e7ce..a2dceb2a877 100644
--- a/source/blender/python/bmesh/bmesh_py_types_select.c
+++ b/source/blender/python/bmesh/bmesh_py_types_select.c
@@ -43,11 +43,8 @@
#include "bmesh_py_types.h"
#include "bmesh_py_types_select.h"
-
-
#include "../generic/py_capi_utils.h"
-
-#include "bmesh_py_api.h" /* own include */
+#include "../generic/python_utildefines.h"
PyDoc_STRVAR(bpy_bmeditselseq_active_doc,
"The last selected element or None (read-only).\n\n:type: :class:`BMVert`, :class:`BMEdge` or :class:`BMFace`"
@@ -165,7 +162,7 @@ static Py_ssize_t bpy_bmeditselseq_length(BPy_BMEditSelSeq *self)
{
BPY_BM_CHECK_INT(self);
- return BLI_countlist(&self->bm->selected);
+ return BLI_listbase_count(&self->bm->selected);
}
static PyObject *bpy_bmeditselseq_subscript_int(BPy_BMEditSelSeq *self, int keynum)
@@ -197,7 +194,6 @@ static PyObject *bpy_bmeditselseq_subscript_slice(BPy_BMEditSelSeq *self, Py_ssi
bool ok;
PyObject *list;
- PyObject *item;
BMEditSelection *ese;
BPY_BM_CHECK_OBJ(self);
@@ -222,9 +218,7 @@ static PyObject *bpy_bmeditselseq_subscript_slice(BPy_BMEditSelSeq *self, Py_ssi
/* add items until stop */
while ((ese = ese->next)) {
- item = BPy_BMElem_CreatePyObject(self->bm, &ese->ele->head);
- PyList_Append(list, item);
- Py_DECREF(item);
+ PyList_APPEND(list, BPy_BMElem_CreatePyObject(self->bm, &ese->ele->head));
count++;
if (count == stop) {
@@ -348,8 +342,8 @@ static PyObject *bpy_bmeditseliter_next(BPy_BMEditSelIter *self)
}
}
-PyTypeObject BPy_BMEditSelSeq_Type = {{{0}}};
-PyTypeObject BPy_BMEditSelIter_Type = {{{0}}};
+PyTypeObject BPy_BMEditSelSeq_Type;
+PyTypeObject BPy_BMEditSelIter_Type;
PyObject *BPy_BMEditSel_CreatePyObject(BMesh *bm)
diff --git a/source/blender/python/bmesh/bmesh_py_utils.c b/source/blender/python/bmesh/bmesh_py_utils.c
index 7088036245a..379aafa5918 100644
--- a/source/blender/python/bmesh/bmesh_py_utils.c
+++ b/source/blender/python/bmesh/bmesh_py_utils.c
@@ -42,6 +42,9 @@
#include "bmesh_py_types.h"
#include "bmesh_py_utils.h" /* own include */
+#include "../generic/py_capi_utils.h"
+#include "../generic/python_utildefines.h"
+
PyDoc_STRVAR(bpy_bm_utils_vert_collapse_edge_doc,
".. method:: vert_collapse_edge(vert, edge)\n"
@@ -82,7 +85,7 @@ static PyObject *bpy_bm_utils_vert_collapse_edge(PyObject *UNUSED(self), PyObjec
return NULL;
}
- if (BM_vert_edge_count(py_vert->v) > 2) {
+ if (BM_vert_edge_count_is_over(py_vert->v, 2)) {
PyErr_SetString(PyExc_ValueError,
"vert_collapse_edge(vert, edge): vert has more than 2 connected edges");
return NULL;
@@ -148,7 +151,7 @@ static PyObject *bpy_bm_utils_vert_collapse_faces(PyObject *UNUSED(self), PyObje
return NULL;
}
- if (BM_vert_edge_count(py_vert->v) > 2) {
+ if (BM_vert_edge_count_is_over(py_vert->v, 2)) {
PyErr_SetString(PyExc_ValueError,
"vert_collapse_faces(vert, edge): vert has more than 2 connected edges");
return NULL;
@@ -251,8 +254,9 @@ static PyObject *bpy_bm_utils_vert_splice(PyObject *UNUSED(self), PyObject *args
}
/* should always succeed */
- ok = BM_vert_splice(bm, py_vert->v, py_vert_target->v);
+ ok = BM_vert_splice(bm, py_vert_target->v, py_vert->v);
BLI_assert(ok == true);
+ UNUSED_VARS_NDEBUG(ok);
Py_RETURN_NONE;
}
@@ -304,7 +308,7 @@ static PyObject *bpy_bm_utils_vert_separate(PyObject *UNUSED(self), PyObject *ar
return NULL;
}
- BM_vert_separate(bm, py_vert->v, &elem, &elem_len, edge_array, edge_array_len);
+ BM_vert_separate(bm, py_vert->v, edge_array, edge_array_len, false, &elem, &elem_len);
/* return collected verts */
ret = BPy_BMVert_Array_As_Tuple(bm, elem, elem_len);
MEM_freeN(elem);
@@ -365,8 +369,9 @@ static PyObject *bpy_bm_utils_edge_split(PyObject *UNUSED(self), PyObject *args)
if (v_new && e_new) {
PyObject *ret = PyTuple_New(2);
- PyTuple_SET_ITEM(ret, 0, BPy_BMEdge_CreatePyObject(bm, e_new));
- PyTuple_SET_ITEM(ret, 1, BPy_BMVert_CreatePyObject(bm, v_new));
+ PyTuple_SET_ITEMS(ret,
+ BPy_BMEdge_CreatePyObject(bm, e_new),
+ BPy_BMVert_CreatePyObject(bm, v_new));
return ret;
}
else {
@@ -393,14 +398,15 @@ PyDoc_STRVAR(bpy_bm_utils_edge_rotate_doc,
static PyObject *bpy_bm_utils_edge_rotate(PyObject *UNUSED(self), PyObject *args)
{
BPy_BMEdge *py_edge;
- int do_ccw = false;
+ bool do_ccw = false;
BMesh *bm;
BMEdge *e_new = NULL;
- if (!PyArg_ParseTuple(args, "O!|i:edge_rotate",
- &BPy_BMEdge_Type, &py_edge,
- &do_ccw))
+ if (!PyArg_ParseTuple(
+ args, "O!|O&:edge_rotate",
+ &BPy_BMEdge_Type, &py_edge,
+ PyC_ParseBool, &do_ccw))
{
return NULL;
}
@@ -451,7 +457,7 @@ static PyObject *bpy_bm_utils_face_split(PyObject *UNUSED(self), PyObject *args,
/* optional */
PyObject *py_coords = NULL;
- int edge_exists = true;
+ bool edge_exists = true;
BPy_BMEdge *py_edge_example = NULL;
float *coords;
@@ -462,13 +468,15 @@ static PyObject *bpy_bm_utils_face_split(PyObject *UNUSED(self), PyObject *args,
BMLoop *l_new = NULL;
BMLoop *l_a, *l_b;
- if (!PyArg_ParseTupleAndKeywords(args, kw, "O!O!O!|OiO!:face_split", (char **)kwlist,
- &BPy_BMFace_Type, &py_face,
- &BPy_BMVert_Type, &py_vert_a,
- &BPy_BMVert_Type, &py_vert_b,
- &py_coords,
- &edge_exists,
- &BPy_BMEdge_Type, &py_edge_example))
+ if (!PyArg_ParseTupleAndKeywords(
+ args, kw,
+ "O!O!O!|OO&O!:face_split", (char **)kwlist,
+ &BPy_BMFace_Type, &py_face,
+ &BPy_BMVert_Type, &py_vert_a,
+ &BPy_BMVert_Type, &py_vert_b,
+ &py_coords,
+ PyC_ParseBool, &edge_exists,
+ &BPy_BMEdge_Type, &py_edge_example))
{
return NULL;
}
@@ -524,8 +532,9 @@ static PyObject *bpy_bm_utils_face_split(PyObject *UNUSED(self), PyObject *args,
if (f_new && l_new) {
PyObject *ret = PyTuple_New(2);
- PyTuple_SET_ITEM(ret, 0, BPy_BMFace_CreatePyObject(bm, f_new));
- PyTuple_SET_ITEM(ret, 1, BPy_BMLoop_CreatePyObject(bm, l_new));
+ PyTuple_SET_ITEMS(ret,
+ BPy_BMFace_CreatePyObject(bm, f_new),
+ BPy_BMLoop_CreatePyObject(bm, l_new));
return ret;
}
else {
@@ -627,9 +636,13 @@ static PyObject *bpy_bm_utils_face_join(PyObject *UNUSED(self), PyObject *args)
BMFace **face_array;
Py_ssize_t face_seq_len = 0;
BMFace *f_new;
- int do_remove = true;
+ bool do_remove = true;
- if (!PyArg_ParseTuple(args, "O|i:face_join", &py_face_array, &do_remove)) {
+ if (!PyArg_ParseTuple(
+ args, "O|i:face_join",
+ &py_face_array,
+ PyC_ParseBool, &do_remove))
+ {
return NULL;
}
@@ -665,7 +678,7 @@ PyDoc_STRVAR(bpy_bm_utils_face_vert_separate_doc,
" :type face: :class:`bmesh.types.BMFace`\n"
" :arg vert: A vertex in the face to separate.\n"
" :type vert: :class:`bmesh.types.BMVert`\n"
-" :return vert: The newly created vertex or None of failure.\n"
+" :return vert: The newly created vertex or None on failure.\n"
" :rtype vert: :class:`bmesh.types.BMVert`\n"
"\n"
" .. note::\n"
@@ -744,9 +757,9 @@ PyDoc_STRVAR(bpy_bm_utils_loop_separate_doc,
"\n"
" Rip a vertex in a face away and add a new vertex.\n"
"\n"
-" :arg loop: The to separate.\n"
-" :type loop: :class:`bmesh.types.BMFace`\n"
-" :return vert: The newly created vertex or None of failure.\n"
+" :arg loop: The loop to separate.\n"
+" :type loop: :class:`bmesh.types.BMLoop`\n"
+" :return vert: The newly created vertex or None on failure.\n"
" :rtype vert: :class:`bmesh.types.BMVert`\n"
);
static PyObject *bpy_bm_utils_loop_separate(PyObject *UNUSED(self), BPy_BMLoop *value)
diff --git a/source/blender/python/generic/CMakeLists.txt b/source/blender/python/generic/CMakeLists.txt
index aec2faa89e6..df611e00d00 100644
--- a/source/blender/python/generic/CMakeLists.txt
+++ b/source/blender/python/generic/CMakeLists.txt
@@ -22,8 +22,10 @@ set(INC
.
../../blenkernel
../../blenlib
+ ../../gpu
../../makesdna
../../../../intern/guardedalloc
+ ../../../../intern/glew-mx
)
set(INC_SYS
@@ -44,8 +46,11 @@ set(SRC
bpy_internal_import.h
idprop_py_api.h
py_capi_utils.h
+
+ # header-only
+ python_utildefines.h
)
-add_definitions(-DGLEW_STATIC)
+add_definitions(${GL_DEFINITIONS})
blender_add_lib(bf_python_ext "${SRC}" "${INC}" "${INC_SYS}")
diff --git a/source/blender/python/generic/bgl.c b/source/blender/python/generic/bgl.c
index b8dcf9d8491..cd6ef3f16a4 100644
--- a/source/blender/python/generic/bgl.c
+++ b/source/blender/python/generic/bgl.c
@@ -32,11 +32,408 @@
#include <Python.h>
-#include "bgl.h" /*This must come first */
-#include <GL/glew.h>
+#include "BLI_utildefines.h"
+
+#include "GPU_glew.h"
#include "MEM_guardedalloc.h"
-#include "BLI_utildefines.h"
+#include "bgl.h"
+
+
+/* -------------------------------------------------------------------- */
+
+/** \name Local utility defines for wrapping OpenGL
+ * \{ */
+
+/*@ By golly George! It looks like fancy pants macro time!!! */
+
+
+/* TYPE_str is the string to pass to Py_ArgParse (for the format) */
+/* TYPE_var is the name to pass to the GL function */
+/* TYPE_ref is the pointer to pass to Py_ArgParse (to store in) */
+/* TYPE_def is the C initialization of the variable */
+
+#define void_str ""
+#define void_var(num)
+#define void_ref(num) &bgl_var##num
+#define void_def(num) char bgl_var##num
+
+#if 0
+#define buffer_str "O!"
+#define buffer_var(number) (bgl_buffer##number)->buf.asvoid
+#define buffer_ref(number) &BGL_bufferType, &bgl_buffer##number
+#define buffer_def(number) Buffer *bgl_buffer##number
+#endif
+
+/* GL Pointer fields, handled by buffer type */
+/* GLdoubleP, GLfloatP, GLintP, GLuintP, GLshortP, GLsizeiP, GLcharP */
+
+#define GLbooleanP_str "O!"
+#define GLbooleanP_var(number) (bgl_buffer##number)->buf.asvoid
+#define GLbooleanP_ref(number) &BGL_bufferType, &bgl_buffer##number
+#define GLbooleanP_def(number) Buffer *bgl_buffer##number
+
+#define GLbyteP_str "O!"
+#define GLbyteP_var(number) (bgl_buffer##number)->buf.asvoid
+#define GLbyteP_ref(number) &BGL_bufferType, &bgl_buffer##number
+#define GLbyteP_def(number) Buffer *bgl_buffer##number
+
+#define GLubyteP_str "O!"
+#define GLubyteP_var(number) (bgl_buffer##number)->buf.asvoid
+#define GLubyteP_ref(number) &BGL_bufferType, &bgl_buffer##number
+#define GLubyteP_def(number) Buffer *bgl_buffer##number
+
+#define GLintP_str "O!"
+#define GLintP_var(number) (bgl_buffer##number)->buf.asvoid
+#define GLintP_ref(number) &BGL_bufferType, &bgl_buffer##number
+#define GLintP_def(number) Buffer *bgl_buffer##number
+
+#define GLint64P_str "O!"
+#define GLint64P_var(number) (bgl_buffer##number)->buf.asvoid
+#define GLint64P_ref(number) &BGL_bufferType, &bgl_buffer##number
+#define GLint64P_def(number) Buffer *bgl_buffer##number
+
+#define GLenumP_str "O!"
+#define GLenumP_var(number) (bgl_buffer##number)->buf.asvoid
+#define GLenumP_ref(number) &BGL_bufferType, &bgl_buffer##number
+#define GLenumP_def(number) Buffer *bgl_buffer##number
+
+#define GLuintP_str "O!"
+#define GLuintP_var(number) (bgl_buffer##number)->buf.asvoid
+#define GLuintP_ref(number) &BGL_bufferType, &bgl_buffer##number
+#define GLuintP_def(number) Buffer *bgl_buffer##number
+
+#if 0
+#define GLuint64P_str "O!"
+#define GLuint64P_var(number) (bgl_buffer##number)->buf.asvoid
+#define GLuint64P_ref(number) &BGL_bufferType, &bgl_buffer##number
+#define GLuint64P_def(number) Buffer *bgl_buffer##number
+#endif
+
+#define GLshortP_str "O!"
+#define GLshortP_var(number) (bgl_buffer##number)->buf.asvoid
+#define GLshortP_ref(number) &BGL_bufferType, &bgl_buffer##number
+#define GLshortP_def(number) Buffer *bgl_buffer##number
+
+#define GLushortP_str "O!"
+#define GLushortP_var(number) (bgl_buffer##number)->buf.asvoid
+#define GLushortP_ref(number) &BGL_bufferType, &bgl_buffer##number
+#define GLushortP_def(number) Buffer *bgl_buffer##number
+
+#define GLfloatP_str "O!"
+#define GLfloatP_var(number) (bgl_buffer##number)->buf.asvoid
+#define GLfloatP_ref(number) &BGL_bufferType, &bgl_buffer##number
+#define GLfloatP_def(number) Buffer *bgl_buffer##number
+
+#define GLdoubleP_str "O!"
+#define GLdoubleP_var(number) (bgl_buffer##number)->buf.asvoid
+#define GLdoubleP_ref(number) &BGL_bufferType, &bgl_buffer##number
+#define GLdoubleP_def(number) Buffer *bgl_buffer##number
+
+#if 0
+#define GLclampfP_str "O!"
+#define GLclampfP_var(number) (bgl_buffer##number)->buf.asvoid
+#define GLclampfP_ref(number) &BGL_bufferType, &bgl_buffer##number
+#define GLclampfP_def(number) Buffer *bgl_buffer##number
+#endif
+
+#define GLvoidP_str "O!"
+#define GLvoidP_var(number) (bgl_buffer##number)->buf.asvoid
+#define GLvoidP_ref(number) &BGL_bufferType, &bgl_buffer##number
+#define GLvoidP_def(number) Buffer *bgl_buffer##number
+
+#define GLsizeiP_str "O!"
+#define GLsizeiP_var(number) (bgl_buffer##number)->buf.asvoid
+#define GLsizeiP_ref(number) &BGL_bufferType, &bgl_buffer##number
+#define GLsizeiP_def(number) Buffer *bgl_buffer##number
+
+#define GLcharP_str "O!"
+#define GLcharP_var(number) (bgl_buffer##number)->buf.asvoid
+#define GLcharP_ref(number) &BGL_bufferType, &bgl_buffer##number
+#define GLcharP_def(number) Buffer *bgl_buffer##number
+
+#if 0
+#define buffer_str "O!"
+#define buffer_var(number) (bgl_buffer##number)->buf.asvoid
+#define buffer_ref(number) &BGL_bufferType, &bgl_buffer##number
+#define buffer_def(number) Buffer *bgl_buffer##number
+#endif
+
+/*@The standard GL typedefs are used as prototypes, we can't
+ * use the GL type directly because Py_ArgParse expects normal
+ * C types.
+ *
+ * Py_ArgParse doesn't grok writing into unsigned variables,
+ * so we use signed everything (even stuff that should be unsigned.
+ */
+
+/* typedef unsigned int GLenum; */
+#define GLenum_str "i"
+#define GLenum_var(num) bgl_var##num
+#define GLenum_ref(num) &bgl_var##num
+#define GLenum_def(num) /* unsigned */ int GLenum_var(num)
+
+/* typedef unsigned int GLboolean; */
+#define GLboolean_str "b"
+#define GLboolean_var(num) bgl_var##num
+#define GLboolean_ref(num) &bgl_var##num
+#define GLboolean_def(num) /* unsigned */ char GLboolean_var(num)
+
+/* typedef unsigned int GLbitfield; */
+#define GLbitfield_str "i"
+#define GLbitfield_var(num) bgl_var##num
+#define GLbitfield_ref(num) &bgl_var##num
+#define GLbitfield_def(num) /* unsigned */ int GLbitfield_var(num)
+
+/* typedef signed char GLbyte; */
+#define GLbyte_str "b"
+#define GLbyte_var(num) bgl_var##num
+#define GLbyte_ref(num) &bgl_var##num
+#define GLbyte_def(num) signed char GLbyte_var(num)
+
+/* typedef short GLshort; */
+#define GLshort_str "h"
+#define GLshort_var(num) bgl_var##num
+#define GLshort_ref(num) &bgl_var##num
+#define GLshort_def(num) short GLshort_var(num)
+
+/* typedef int GLint; */
+#define GLint_str "i"
+#define GLint_var(num) bgl_var##num
+#define GLint_ref(num) &bgl_var##num
+#define GLint_def(num) int GLint_var(num)
+
+/* typedef int GLsizei; */
+#define GLsizei_str "n"
+#define GLsizei_var(num) bgl_var##num
+#define GLsizei_ref(num) &bgl_var##num
+#define GLsizei_def(num) size_t GLsizei_var(num)
+
+/* typedef int GLsizeiptr; */
+#define GLsizeiptr_str "n"
+#define GLsizeiptr_var(num) bgl_var##num
+#define GLsizeiptr_ref(num) &bgl_var##num
+#define GLsizeiptr_def(num) size_t GLsizeiptr_var(num)
+
+/* typedef int GLintptr; */
+#define GLintptr_str "n"
+#define GLintptr_var(num) bgl_var##num
+#define GLintptr_ref(num) &bgl_var##num
+#define GLintptr_def(num) size_t GLintptr_var(num)
+
+/* typedef unsigned char GLubyte; */
+#define GLubyte_str "B"
+#define GLubyte_var(num) bgl_var##num
+#define GLubyte_ref(num) &bgl_var##num
+#define GLubyte_def(num) /* unsigned */ char GLubyte_var(num)
+
+/* typedef unsigned short GLushort; */
+#define GLushort_str "H"
+#define GLushort_var(num) bgl_var##num
+#define GLushort_ref(num) &bgl_var##num
+#define GLushort_def(num) /* unsigned */ short GLushort_var(num)
+
+/* typedef unsigned int GLuint; */
+#define GLuint_str "I"
+#define GLuint_var(num) bgl_var##num
+#define GLuint_ref(num) &bgl_var##num
+#define GLuint_def(num) /* unsigned */ int GLuint_var(num)
+
+/* typedef unsigned int GLuint64; */
+#if 0
+#define GLuint64_str "Q"
+#define GLuint64_var(num) bgl_var##num
+#define GLuint64_ref(num) &bgl_var##num
+#define GLuint64_def(num) /* unsigned */ int GLuint64_var(num)
+#endif
+
+/* typedef unsigned int GLsync; */
+#if 0
+#define GLsync_str "I"
+#define GLsync_var(num) bgl_var##num
+#define GLsync_ref(num) &bgl_var##num
+#define GLsync_def(num) /* unsigned */ int GLsync_var(num)
+#endif
+
+/* typedef float GLfloat; */
+#define GLfloat_str "f"
+#define GLfloat_var(num) bgl_var##num
+#define GLfloat_ref(num) &bgl_var##num
+#define GLfloat_def(num) float GLfloat_var(num)
+
+/* typedef char *GLstring; */
+#define GLstring_str "s"
+#define GLstring_var(number) bgl_var##number
+#define GLstring_ref(number) &bgl_var##number
+#define GLstring_def(number) char *GLstring_var(number)
+
+/* typedef float GLclampf; */
+#if 0
+#define GLclampf_str "f"
+#define GLclampf_var(num) bgl_var##num
+#define GLclampf_ref(num) &bgl_var##num
+#define GLclampf_def(num) float GLclampf_var(num)
+#endif
+
+/* typedef double GLdouble; */
+#define GLdouble_str "d"
+#define GLdouble_var(num) bgl_var##num
+#define GLdouble_ref(num) &bgl_var##num
+#define GLdouble_def(num) double GLdouble_var(num)
+
+/* typedef double GLclampd; */
+#if 0
+#define GLclampd_str "d"
+#define GLclampd_var(num) bgl_var##num
+#define GLclampd_ref(num) &bgl_var##num
+#define GLclampd_def(num) double GLclampd_var(num)
+#endif
+
+#define _arg_def1(a1) \
+ a1##_def(1)
+#define _arg_def2(a1, a2) \
+ _arg_def1(a1); a2##_def(2)
+#define _arg_def3(a1, a2, a3) \
+ _arg_def2(a1, a2); a3##_def(3)
+#define _arg_def4(a1, a2, a3, a4) \
+ _arg_def3(a1, a2, a3); a4##_def(4)
+#define _arg_def5(a1, a2, a3, a4, a5) \
+ _arg_def4(a1, a2, a3, a4); a5##_def(5)
+#define _arg_def6(a1, a2, a3, a4, a5, a6) \
+ _arg_def5(a1, a2, a3, a4, a5); a6##_def(6)
+#define _arg_def7(a1, a2, a3, a4, a5, a6, a7) \
+ _arg_def6(a1, a2, a3, a4, a5, a6); a7##_def(7)
+#define _arg_def8(a1, a2, a3, a4, a5, a6, a7, a8) \
+ _arg_def7(a1, a2, a3, a4, a5, a6, a7); a8##_def(8)
+#define _arg_def9(a1, a2, a3, a4, a5, a6, a7, a8, a9) \
+ _arg_def8(a1, a2, a3, a4, a5, a6, a7, a8); a9##_def(9)
+#define _arg_def10(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10) \
+ _arg_def9(a1, a2, a3, a4, a5, a6, a7, a8, a9); a10##_def(10)
+#define _arg_def11(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11) \
+ _arg_def10(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10); a11##_def(11)
+#define arg_def(...) VA_NARGS_CALL_OVERLOAD(_arg_def, __VA_ARGS__)
+
+#define _arg_var1(a1) \
+ a1##_var(1)
+#define _arg_var2(a1, a2) \
+ _arg_var1(a1), a2##_var(2)
+#define _arg_var3(a1, a2, a3) \
+ _arg_var2(a1, a2), a3##_var(3)
+#define _arg_var4(a1, a2, a3, a4) \
+ _arg_var3(a1, a2, a3), a4##_var(4)
+#define _arg_var5(a1, a2, a3, a4, a5) \
+ _arg_var4(a1, a2, a3, a4), a5##_var(5)
+#define _arg_var6(a1, a2, a3, a4, a5, a6) \
+ _arg_var5(a1, a2, a3, a4, a5), a6##_var(6)
+#define _arg_var7(a1, a2, a3, a4, a5, a6, a7) \
+ _arg_var6(a1, a2, a3, a4, a5, a6), a7##_var(7)
+#define _arg_var8(a1, a2, a3, a4, a5, a6, a7, a8) \
+ _arg_var7(a1, a2, a3, a4, a5, a6, a7), a8##_var(8)
+#define _arg_var9(a1, a2, a3, a4, a5, a6, a7, a8, a9) \
+ _arg_var8(a1, a2, a3, a4, a5, a6, a7, a8), a9##_var(9)
+#define _arg_var10(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10) \
+ _arg_var9(a1, a2, a3, a4, a5, a6, a7, a8, a9), a10##_var(10)
+#define _arg_var11(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11) \
+ _arg_var10(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10), a11##_var(11)
+#define arg_var(...) VA_NARGS_CALL_OVERLOAD(_arg_var, __VA_ARGS__)
+
+#define _arg_ref1(a1) \
+ a1##_ref(1)
+#define _arg_ref2(a1, a2) \
+ _arg_ref1(a1), a2##_ref(2)
+#define _arg_ref3(a1, a2, a3) \
+ _arg_ref2(a1, a2), a3##_ref(3)
+#define _arg_ref4(a1, a2, a3, a4) \
+ _arg_ref3(a1, a2, a3), a4##_ref(4)
+#define _arg_ref5(a1, a2, a3, a4, a5) \
+ _arg_ref4(a1, a2, a3, a4), a5##_ref(5)
+#define _arg_ref6(a1, a2, a3, a4, a5, a6) \
+ _arg_ref5(a1, a2, a3, a4, a5), a6##_ref(6)
+#define _arg_ref7(a1, a2, a3, a4, a5, a6, a7) \
+ _arg_ref6(a1, a2, a3, a4, a5, a6), a7##_ref(7)
+#define _arg_ref8(a1, a2, a3, a4, a5, a6, a7, a8) \
+ _arg_ref7(a1, a2, a3, a4, a5, a6, a7), a8##_ref(8)
+#define _arg_ref9(a1, a2, a3, a4, a5, a6, a7, a8, a9) \
+ _arg_ref8(a1, a2, a3, a4, a5, a6, a7, a8), a9##_ref(9)
+#define _arg_ref10(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10) \
+ _arg_ref9(a1, a2, a3, a4, a5, a6, a7, a8, a9), a10##_ref(10)
+#define _arg_ref11(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11) \
+ _arg_ref10(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10), a11##_ref(11)
+#define arg_ref(...) VA_NARGS_CALL_OVERLOAD(_arg_ref, __VA_ARGS__)
+
+#define _arg_str1(a1) \
+ a1##_str
+#define _arg_str2(a1, a2) \
+ _arg_str1(a1) a2##_str
+#define _arg_str3(a1, a2, a3) \
+ _arg_str2(a1, a2) a3##_str
+#define _arg_str4(a1, a2, a3, a4) \
+ _arg_str3(a1, a2, a3) a4##_str
+#define _arg_str5(a1, a2, a3, a4, a5) \
+ _arg_str4(a1, a2, a3, a4) a5##_str
+#define _arg_str6(a1, a2, a3, a4, a5, a6) \
+ _arg_str5(a1, a2, a3, a4, a5) a6##_str
+#define _arg_str7(a1, a2, a3, a4, a5, a6, a7) \
+ _arg_str6(a1, a2, a3, a4, a5, a6) a7##_str
+#define _arg_str8(a1, a2, a3, a4, a5, a6, a7, a8) \
+ _arg_str7(a1, a2, a3, a4, a5, a6, a7) a8##_str
+#define _arg_str9(a1, a2, a3, a4, a5, a6, a7, a8, a9) \
+ _arg_str8(a1, a2, a3, a4, a5, a6, a7, a8) a9##_str
+#define _arg_str10(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10) \
+ _arg_str9(a1, a2, a3, a4, a5, a6, a7, a8, a9) a10##_str
+#define _arg_str11(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11) \
+ _arg_str10(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10) a11##_str
+#define arg_str(...) VA_NARGS_CALL_OVERLOAD(_arg_str, __VA_ARGS__)
+
+#define ret_def_void
+#define ret_set_void
+#define ret_ret_void return Py_INCREF(Py_None), Py_None
+
+#define ret_def_GLint int ret_int
+#define ret_set_GLint ret_int =
+#define ret_ret_GLint return PyLong_FromLong(ret_int)
+
+#define ret_def_GLuint unsigned int ret_uint
+#define ret_set_GLuint ret_uint =
+#define ret_ret_GLuint return PyLong_FromLong((long) ret_uint)
+
+#if 0
+#define ret_def_GLsizei size_t ret_size_t
+#define ret_set_GLsizei ret_size_t =
+#define ret_ret_GLsizei return PyLong_FromSsize_t(ret_size_t)
+#endif
+
+#if 0
+#define ret_def_GLsync unsigned int ret_sync
+#define ret_set_GLsync ret_sync =
+#define ret_ret_GLsync return PyLong_FromLong((long) ret_sync)
+#endif
+
+#define ret_def_GLenum unsigned int ret_uint
+#define ret_set_GLenum ret_uint =
+#define ret_ret_GLenum return PyLong_FromLong((long) ret_uint)
+
+#define ret_def_GLboolean unsigned char ret_bool
+#define ret_set_GLboolean ret_bool =
+#define ret_ret_GLboolean return PyLong_FromLong((long) ret_bool)
+
+#define ret_def_GLstring const unsigned char *ret_str
+#define ret_set_GLstring ret_str =
+
+#define ret_ret_GLstring \
+ if (ret_str) { \
+ return PyUnicode_FromString((const char *)ret_str); \
+ } \
+ else { \
+ PyErr_SetString(PyExc_AttributeError, "could not get opengl string"); \
+ return NULL; \
+ } \
+
+/** \} */
+
+
+/* -------------------------------------------------------------------- */
+/* Forward Declarations */
static PyObject *Buffer_new(PyTypeObject *type, PyObject *args, PyObject *kwds);
static PyObject *Method_ShaderSource(PyObject *self, PyObject *args);
@@ -51,6 +448,38 @@ static int Buffer_ass_slice(Buffer *self, int begin, int end, PyObject *seq);
static PyObject *Buffer_subscript(Buffer *self, PyObject *item);
static int Buffer_ass_subscript(Buffer *self, PyObject *item, PyObject *value);
+
+/* -------------------------------------------------------------------- */
+
+/** \name Utility Functions
+ * \{ */
+
+
+int BGL_typeSize(int type)
+{
+ switch (type) {
+ case GL_BYTE:
+ return sizeof(char);
+ case GL_SHORT:
+ return sizeof(short);
+ case GL_INT:
+ return sizeof(int);
+ case GL_FLOAT:
+ return sizeof(float);
+ case GL_DOUBLE:
+ return sizeof(double);
+ }
+ return -1;
+}
+
+/** \} */
+
+
+/* -------------------------------------------------------------------- */
+
+/** \name Buffer API
+ * \{ */
+
static PySequenceMethods Buffer_SeqMethods = {
(lenfunc) Buffer_len, /*sq_length */
(binaryfunc) NULL, /*sq_concat */
@@ -201,54 +630,13 @@ PyTypeObject BGL_bufferType = {
NULL /*tp_del*/
};
-#define BGL_Wrap(nargs, funcname, ret, arg_list) \
-static PyObject *Method_##funcname (PyObject *UNUSED(self), PyObject *args) \
-{ \
- arg_def##nargs arg_list; \
- ret_def_##ret; \
- if (!PyArg_ParseTuple(args, \
- arg_str##nargs arg_list, \
- arg_ref##nargs arg_list)) \
- { \
- return NULL; \
- } \
- ret_set_##ret gl##funcname (arg_var##nargs arg_list); \
- ret_ret_##ret; \
-}
-
-#define BGLU_Wrap(nargs, funcname, ret, arg_list) \
-static PyObject *Method_##funcname (PyObject *UNUSED(self), PyObject *args) \
-{ \
- arg_def##nargs arg_list; \
- ret_def_##ret; \
- if (!PyArg_ParseTuple(args, \
- arg_str##nargs arg_list, \
- arg_ref##nargs arg_list)) \
- { \
- return NULL; \
- } \
- ret_set_##ret glu##funcname (arg_var##nargs arg_list); \
- ret_ret_##ret; \
-}
-
-/********/
-int BGL_typeSize(int type)
-{
- switch (type) {
- case GL_BYTE:
- return sizeof(char);
- case GL_SHORT:
- return sizeof(short);
- case GL_INT:
- return sizeof(int);
- case GL_FLOAT:
- return sizeof(float);
- case GL_DOUBLE:
- return sizeof(double);
- }
- return -1;
-}
-
+/**
+ * Create a buffer object
+ *
+ * \param dimensions: An array of ndimensions integers representing the size of each dimension.
+ * \param initbuffer: When not NULL holds a contiguous buffer
+ * with the correct format from which the buffer will be initialized
+ */
Buffer *BGL_MakeBuffer(int type, int ndimensions, int *dimensions, void *initbuffer)
{
Buffer *buffer;
@@ -362,7 +750,7 @@ static PyObject *Buffer_new(PyTypeObject *UNUSED(type), PyObject *args, PyObject
return (PyObject *)buffer;
}
-/*@ Buffer sequence methods */
+/* Buffer sequence methods */
static int Buffer_len(Buffer *self)
{
@@ -607,768 +995,659 @@ static PyObject *Buffer_repr(Buffer *self)
return repr;
}
+/** \} */
-BGL_Wrap(2, Accum, void, (GLenum, GLfloat))
-BGL_Wrap(1, ActiveTexture, void, (GLenum))
-BGL_Wrap(2, AlphaFunc, void, (GLenum, GLclampf))
-BGL_Wrap(3, AreTexturesResident, GLboolean, (GLsizei, GLuintP, GLbooleanP))
-BGL_Wrap(2, AttachShader, void, (GLuint, GLuint))
-BGL_Wrap(1, Begin, void, (GLenum))
-BGL_Wrap(2, BindTexture, void, (GLenum, GLuint))
-BGL_Wrap(7, Bitmap, void, (GLsizei, GLsizei, GLfloat,
- GLfloat, GLfloat, GLfloat, GLubyteP))
-BGL_Wrap(2, BlendFunc, void, (GLenum, GLenum))
-BGL_Wrap(1, CallList, void, (GLuint))
-BGL_Wrap(3, CallLists, void, (GLsizei, GLenum, GLvoidP))
-BGL_Wrap(1, Clear, void, (GLbitfield))
-BGL_Wrap(4, ClearAccum, void, (GLfloat, GLfloat, GLfloat, GLfloat))
-BGL_Wrap(4, ClearColor, void, (GLclampf, GLclampf, GLclampf, GLclampf))
-BGL_Wrap(1, ClearDepth, void, (GLclampd))
-BGL_Wrap(1, ClearIndex, void, (GLfloat))
-BGL_Wrap(1, ClearStencil, void, (GLint))
-BGL_Wrap(2, ClipPlane, void, (GLenum, GLdoubleP))
-BGL_Wrap(3, Color3b, void, (GLbyte, GLbyte, GLbyte))
-BGL_Wrap(1, Color3bv, void, (GLbyteP))
-BGL_Wrap(3, Color3d, void, (GLdouble, GLdouble, GLdouble))
-BGL_Wrap(1, Color3dv, void, (GLdoubleP))
-BGL_Wrap(3, Color3f, void, (GLfloat, GLfloat, GLfloat))
-BGL_Wrap(1, Color3fv, void, (GLfloatP))
-BGL_Wrap(3, Color3i, void, (GLint, GLint, GLint))
-BGL_Wrap(1, Color3iv, void, (GLintP))
-BGL_Wrap(3, Color3s, void, (GLshort, GLshort, GLshort))
-BGL_Wrap(1, Color3sv, void, (GLshortP))
-BGL_Wrap(3, Color3ub, void, (GLubyte, GLubyte, GLubyte))
-BGL_Wrap(1, Color3ubv, void, (GLubyteP))
-BGL_Wrap(3, Color3ui, void, (GLuint, GLuint, GLuint))
-BGL_Wrap(1, Color3uiv, void, (GLuintP))
-BGL_Wrap(3, Color3us, void, (GLushort, GLushort, GLushort))
-BGL_Wrap(1, Color3usv, void, (GLushortP))
-BGL_Wrap(4, Color4b, void, (GLbyte, GLbyte, GLbyte, GLbyte))
-BGL_Wrap(1, Color4bv, void, (GLbyteP))
-BGL_Wrap(4, Color4d, void, (GLdouble, GLdouble, GLdouble, GLdouble))
-BGL_Wrap(1, Color4dv, void, (GLdoubleP))
-BGL_Wrap(4, Color4f, void, (GLfloat, GLfloat, GLfloat, GLfloat))
-BGL_Wrap(1, Color4fv, void, (GLfloatP))
-BGL_Wrap(4, Color4i, void, (GLint, GLint, GLint, GLint))
-BGL_Wrap(1, Color4iv, void, (GLintP))
-BGL_Wrap(4, Color4s, void, (GLshort, GLshort, GLshort, GLshort))
-BGL_Wrap(1, Color4sv, void, (GLshortP))
-BGL_Wrap(4, Color4ub, void, (GLubyte, GLubyte, GLubyte, GLubyte))
-BGL_Wrap(1, Color4ubv, void, (GLubyteP))
-BGL_Wrap(4, Color4ui, void, (GLuint, GLuint, GLuint, GLuint))
-BGL_Wrap(1, Color4uiv, void, (GLuintP))
-BGL_Wrap(4, Color4us, void, (GLushort, GLushort, GLushort, GLushort))
-BGL_Wrap(1, Color4usv, void, (GLushortP))
-BGL_Wrap(4, ColorMask, void, (GLboolean, GLboolean, GLboolean, GLboolean))
-BGL_Wrap(2, ColorMaterial, void, (GLenum, GLenum))
-BGL_Wrap(1, CompileShader, void, (GLuint))
-BGL_Wrap(5, CopyPixels, void, (GLint, GLint, GLsizei, GLsizei, GLenum))
-BGL_Wrap(8, CopyTexImage2D, void, (GLenum, GLint, GLenum, GLint, GLint, GLsizei, GLsizei, GLint))
-BGL_Wrap(1, CreateProgram, GLuint, (void))
-BGL_Wrap(1, CreateShader, GLuint, (GLenum))
-BGL_Wrap(1, CullFace, void, (GLenum))
-BGL_Wrap(2, DeleteLists, void, (GLuint, GLsizei))
-BGL_Wrap(1, DeleteProgram, void, (GLuint))
-BGL_Wrap(1, DeleteShader, void, (GLuint))
-BGL_Wrap(2, DeleteTextures, void, (GLsizei, GLuintP))
-BGL_Wrap(1, DepthFunc, void, (GLenum))
-BGL_Wrap(1, DepthMask, void, (GLboolean))
-BGL_Wrap(2, DepthRange, void, (GLclampd, GLclampd))
-BGL_Wrap(2, DetachShader, void, (GLuint, GLuint))
-BGL_Wrap(1, Disable, void, (GLenum))
-BGL_Wrap(1, DrawBuffer, void, (GLenum))
-BGL_Wrap(5, DrawPixels, void, (GLsizei, GLsizei, GLenum, GLenum, GLvoidP))
-BGL_Wrap(1, EdgeFlag, void, (GLboolean))
-BGL_Wrap(1, EdgeFlagv, void, (GLbooleanP))
-BGL_Wrap(1, Enable, void, (GLenum))
-BGL_Wrap(1, End, void, (void))
-BGL_Wrap(1, EndList, void, (void))
-BGL_Wrap(1, EvalCoord1d, void, (GLdouble))
-BGL_Wrap(1, EvalCoord1dv, void, (GLdoubleP))
-BGL_Wrap(1, EvalCoord1f, void, (GLfloat))
-BGL_Wrap(1, EvalCoord1fv, void, (GLfloatP))
-BGL_Wrap(2, EvalCoord2d, void, (GLdouble, GLdouble))
-BGL_Wrap(1, EvalCoord2dv, void, (GLdoubleP))
-BGL_Wrap(2, EvalCoord2f, void, (GLfloat, GLfloat))
-BGL_Wrap(1, EvalCoord2fv, void, (GLfloatP))
-BGL_Wrap(3, EvalMesh1, void, (GLenum, GLint, GLint))
-BGL_Wrap(5, EvalMesh2, void, (GLenum, GLint, GLint, GLint, GLint))
-BGL_Wrap(1, EvalPoint1, void, (GLint))
-BGL_Wrap(2, EvalPoint2, void, (GLint, GLint))
-BGL_Wrap(3, FeedbackBuffer, void, (GLsizei, GLenum, GLfloatP))
-BGL_Wrap(1, Finish, void, (void))
-BGL_Wrap(1, Flush, void, (void))
-BGL_Wrap(2, Fogf, void, (GLenum, GLfloat))
-BGL_Wrap(2, Fogfv, void, (GLenum, GLfloatP))
-BGL_Wrap(2, Fogi, void, (GLenum, GLint))
-BGL_Wrap(2, Fogiv, void, (GLenum, GLintP))
-BGL_Wrap(1, FrontFace, void, (GLenum))
-BGL_Wrap(6, Frustum, void, (GLdouble, GLdouble,
- GLdouble, GLdouble, GLdouble, GLdouble))
-BGL_Wrap(1, GenLists, GLuint, (GLsizei))
-BGL_Wrap(2, GenTextures, void, (GLsizei, GLuintP))
-BGL_Wrap(4, GetAttachedShaders, void, (GLuint, GLsizei, GLsizeiP, GLuintP))
-BGL_Wrap(2, GetBooleanv, void, (GLenum, GLbooleanP))
-BGL_Wrap(2, GetClipPlane, void, (GLenum, GLdoubleP))
-BGL_Wrap(2, GetDoublev, void, (GLenum, GLdoubleP))
-BGL_Wrap(1, GetError, GLenum, (void))
-BGL_Wrap(2, GetFloatv, void, (GLenum, GLfloatP))
-BGL_Wrap(2, GetIntegerv, void, (GLenum, GLintP))
-BGL_Wrap(3, GetLightfv, void, (GLenum, GLenum, GLfloatP))
-BGL_Wrap(3, GetLightiv, void, (GLenum, GLenum, GLintP))
-BGL_Wrap(3, GetMapdv, void, (GLenum, GLenum, GLdoubleP))
-BGL_Wrap(3, GetMapfv, void, (GLenum, GLenum, GLfloatP))
-BGL_Wrap(3, GetMapiv, void, (GLenum, GLenum, GLintP))
-BGL_Wrap(3, GetMaterialfv, void, (GLenum, GLenum, GLfloatP))
-BGL_Wrap(3, GetMaterialiv, void, (GLenum, GLenum, GLintP))
-BGL_Wrap(2, GetPixelMapfv, void, (GLenum, GLfloatP))
-BGL_Wrap(2, GetPixelMapuiv, void, (GLenum, GLuintP))
-BGL_Wrap(2, GetPixelMapusv, void, (GLenum, GLushortP))
-BGL_Wrap(1, GetPolygonStipple, void, (GLubyteP))
-BGL_Wrap(4, GetProgramInfoLog, void, (GLuint, GLsizei, GLsizeiP, GLcharP))
-BGL_Wrap(3, GetProgramiv, void, (GLuint, GLenum, GLintP))
-BGL_Wrap(4, GetShaderInfoLog, void, (GLuint, GLsizei, GLsizeiP, GLcharP))
-BGL_Wrap(3, GetShaderiv, void, (GLuint, GLenum, GLintP))
-BGL_Wrap(4, GetShaderSource, void, (GLuint, GLsizei, GLsizeiP, GLcharP))
-BGL_Wrap(1, GetString, GLstring, (GLenum))
-BGL_Wrap(3, GetTexEnvfv, void, (GLenum, GLenum, GLfloatP))
-BGL_Wrap(3, GetTexEnviv, void, (GLenum, GLenum, GLintP))
-BGL_Wrap(3, GetTexGendv, void, (GLenum, GLenum, GLdoubleP))
-BGL_Wrap(3, GetTexGenfv, void, (GLenum, GLenum, GLfloatP))
-BGL_Wrap(3, GetTexGeniv, void, (GLenum, GLenum, GLintP))
-BGL_Wrap(5, GetTexImage, void, (GLenum, GLint, GLenum, GLenum, GLvoidP))
-BGL_Wrap(4, GetTexLevelParameterfv, void, (GLenum, GLint, GLenum, GLfloatP))
-BGL_Wrap(4, GetTexLevelParameteriv, void, (GLenum, GLint, GLenum, GLintP))
-BGL_Wrap(3, GetTexParameterfv, void, (GLenum, GLenum, GLfloatP))
-BGL_Wrap(3, GetTexParameteriv, void, (GLenum, GLenum, GLintP))
-BGL_Wrap(2, GetUniformLocation, GLint, (GLuint, GLstring))
-BGL_Wrap(2, Hint, void, (GLenum, GLenum))
-BGL_Wrap(1, IndexMask, void, (GLuint))
-BGL_Wrap(1, Indexd, void, (GLdouble))
-BGL_Wrap(1, Indexdv, void, (GLdoubleP))
-BGL_Wrap(1, Indexf, void, (GLfloat))
-BGL_Wrap(1, Indexfv, void, (GLfloatP))
-BGL_Wrap(1, Indexi, void, (GLint))
-BGL_Wrap(1, Indexiv, void, (GLintP))
-BGL_Wrap(1, Indexs, void, (GLshort))
-BGL_Wrap(1, Indexsv, void, (GLshortP))
-BGL_Wrap(1, InitNames, void, (void))
-BGL_Wrap(1, IsEnabled, GLboolean, (GLenum))
-BGL_Wrap(1, IsList, GLboolean, (GLuint))
-BGL_Wrap(1, IsProgram, GLboolean, (GLuint))
-BGL_Wrap(1, IsShader, GLboolean, (GLuint))
-BGL_Wrap(1, IsTexture, GLboolean, (GLuint))
-BGL_Wrap(2, LightModelf, void, (GLenum, GLfloat))
-BGL_Wrap(2, LightModelfv, void, (GLenum, GLfloatP))
-BGL_Wrap(2, LightModeli, void, (GLenum, GLint))
-BGL_Wrap(2, LightModeliv, void, (GLenum, GLintP))
-BGL_Wrap(3, Lightf, void, (GLenum, GLenum, GLfloat))
-BGL_Wrap(3, Lightfv, void, (GLenum, GLenum, GLfloatP))
-BGL_Wrap(3, Lighti, void, (GLenum, GLenum, GLint))
-BGL_Wrap(3, Lightiv, void, (GLenum, GLenum, GLintP))
-BGL_Wrap(2, LineStipple, void, (GLint, GLushort))
-BGL_Wrap(1, LineWidth, void, (GLfloat))
-BGL_Wrap(1, LinkProgram, void, (GLuint))
-BGL_Wrap(1, ListBase, void, (GLuint))
-BGL_Wrap(1, LoadIdentity, void, (void))
-BGL_Wrap(1, LoadMatrixd, void, (GLdoubleP))
-BGL_Wrap(1, LoadMatrixf, void, (GLfloatP))
-BGL_Wrap(1, LoadName, void, (GLuint))
-BGL_Wrap(1, LogicOp, void, (GLenum))
-BGL_Wrap(6, Map1d, void, (GLenum, GLdouble, GLdouble,
- GLint, GLint, GLdoubleP))
-BGL_Wrap(6, Map1f, void, (GLenum, GLfloat, GLfloat,
- GLint, GLint, GLfloatP))
-BGL_Wrap(10, Map2d, void, (GLenum, GLdouble, GLdouble,
- GLint, GLint, GLdouble, GLdouble, GLint, GLint, GLdoubleP))
-BGL_Wrap(10, Map2f, void, (GLenum, GLfloat, GLfloat,
- GLint, GLint, GLfloat, GLfloat, GLint, GLint, GLfloatP))
-BGL_Wrap(3, MapGrid1d, void, (GLint, GLdouble, GLdouble))
-BGL_Wrap(3, MapGrid1f, void, (GLint, GLfloat, GLfloat))
-BGL_Wrap(6, MapGrid2d, void, (GLint, GLdouble, GLdouble,
- GLint, GLdouble, GLdouble))
-BGL_Wrap(6, MapGrid2f, void, (GLint, GLfloat, GLfloat,
- GLint, GLfloat, GLfloat))
-BGL_Wrap(3, Materialf, void, (GLenum, GLenum, GLfloat))
-BGL_Wrap(3, Materialfv, void, (GLenum, GLenum, GLfloatP))
-BGL_Wrap(3, Materiali, void, (GLenum, GLenum, GLint))
-BGL_Wrap(3, Materialiv, void, (GLenum, GLenum, GLintP))
-BGL_Wrap(1, MatrixMode, void, (GLenum))
-BGL_Wrap(1, MultMatrixd, void, (GLdoubleP))
-BGL_Wrap(1, MultMatrixf, void, (GLfloatP))
-BGL_Wrap(2, NewList, void, (GLuint, GLenum))
-BGL_Wrap(3, Normal3b, void, (GLbyte, GLbyte, GLbyte))
-BGL_Wrap(1, Normal3bv, void, (GLbyteP))
-BGL_Wrap(3, Normal3d, void, (GLdouble, GLdouble, GLdouble))
-BGL_Wrap(1, Normal3dv, void, (GLdoubleP))
-BGL_Wrap(3, Normal3f, void, (GLfloat, GLfloat, GLfloat))
-BGL_Wrap(1, Normal3fv, void, (GLfloatP))
-BGL_Wrap(3, Normal3i, void, (GLint, GLint, GLint))
-BGL_Wrap(1, Normal3iv, void, (GLintP))
-BGL_Wrap(3, Normal3s, void, (GLshort, GLshort, GLshort))
-BGL_Wrap(1, Normal3sv, void, (GLshortP))
-BGL_Wrap(6, Ortho, void, (GLdouble, GLdouble,
- GLdouble, GLdouble, GLdouble, GLdouble))
-BGL_Wrap(1, PassThrough, void, (GLfloat))
-BGL_Wrap(3, PixelMapfv, void, (GLenum, GLint, GLfloatP))
-BGL_Wrap(3, PixelMapuiv, void, (GLenum, GLint, GLuintP))
-BGL_Wrap(3, PixelMapusv, void, (GLenum, GLint, GLushortP))
-BGL_Wrap(2, PixelStoref, void, (GLenum, GLfloat))
-BGL_Wrap(2, PixelStorei, void, (GLenum, GLint))
-BGL_Wrap(2, PixelTransferf, void, (GLenum, GLfloat))
-BGL_Wrap(2, PixelTransferi, void, (GLenum, GLint))
-BGL_Wrap(2, PixelZoom, void, (GLfloat, GLfloat))
-BGL_Wrap(1, PointSize, void, (GLfloat))
-BGL_Wrap(2, PolygonMode, void, (GLenum, GLenum))
-BGL_Wrap(2, PolygonOffset, void, (GLfloat, GLfloat))
-BGL_Wrap(1, PolygonStipple, void, (GLubyteP))
-BGL_Wrap(1, PopAttrib, void, (void))
-BGL_Wrap(1, PopClientAttrib, void, (void))
-BGL_Wrap(1, PopMatrix, void, (void))
-BGL_Wrap(1, PopName, void, (void))
-BGL_Wrap(3, PrioritizeTextures, void, (GLsizei, GLuintP, GLclampfP))
-BGL_Wrap(1, PushAttrib, void, (GLbitfield))
-BGL_Wrap(1, PushClientAttrib, void, (GLbitfield))
-BGL_Wrap(1, PushMatrix, void, (void))
-BGL_Wrap(1, PushName, void, (GLuint))
-BGL_Wrap(2, RasterPos2d, void, (GLdouble, GLdouble))
-BGL_Wrap(1, RasterPos2dv, void, (GLdoubleP))
-BGL_Wrap(2, RasterPos2f, void, (GLfloat, GLfloat))
-BGL_Wrap(1, RasterPos2fv, void, (GLfloatP))
-BGL_Wrap(2, RasterPos2i, void, (GLint, GLint))
-BGL_Wrap(1, RasterPos2iv, void, (GLintP))
-BGL_Wrap(2, RasterPos2s, void, (GLshort, GLshort))
-BGL_Wrap(1, RasterPos2sv, void, (GLshortP))
-BGL_Wrap(3, RasterPos3d, void, (GLdouble, GLdouble, GLdouble))
-BGL_Wrap(1, RasterPos3dv, void, (GLdoubleP))
-BGL_Wrap(3, RasterPos3f, void, (GLfloat, GLfloat, GLfloat))
-BGL_Wrap(1, RasterPos3fv, void, (GLfloatP))
-BGL_Wrap(3, RasterPos3i, void, (GLint, GLint, GLint))
-BGL_Wrap(1, RasterPos3iv, void, (GLintP))
-BGL_Wrap(3, RasterPos3s, void, (GLshort, GLshort, GLshort))
-BGL_Wrap(1, RasterPos3sv, void, (GLshortP))
-BGL_Wrap(4, RasterPos4d, void, (GLdouble, GLdouble, GLdouble, GLdouble))
-BGL_Wrap(1, RasterPos4dv, void, (GLdoubleP))
-BGL_Wrap(4, RasterPos4f, void, (GLfloat, GLfloat, GLfloat, GLfloat))
-BGL_Wrap(1, RasterPos4fv, void, (GLfloatP))
-BGL_Wrap(4, RasterPos4i, void, (GLint, GLint, GLint, GLint))
-BGL_Wrap(1, RasterPos4iv, void, (GLintP))
-BGL_Wrap(4, RasterPos4s, void, (GLshort, GLshort, GLshort, GLshort))
-BGL_Wrap(1, RasterPos4sv, void, (GLshortP))
-BGL_Wrap(1, ReadBuffer, void, (GLenum))
-BGL_Wrap(7, ReadPixels, void, (GLint, GLint, GLsizei,
- GLsizei, GLenum, GLenum, GLvoidP))
-BGL_Wrap(4, Rectd, void, (GLdouble, GLdouble, GLdouble, GLdouble))
-BGL_Wrap(2, Rectdv, void, (GLdoubleP, GLdoubleP))
-BGL_Wrap(4, Rectf, void, (GLfloat, GLfloat, GLfloat, GLfloat))
-BGL_Wrap(2, Rectfv, void, (GLfloatP, GLfloatP))
-BGL_Wrap(4, Recti, void, (GLint, GLint, GLint, GLint))
-BGL_Wrap(2, Rectiv, void, (GLintP, GLintP))
-BGL_Wrap(4, Rects, void, (GLshort, GLshort, GLshort, GLshort))
-BGL_Wrap(2, Rectsv, void, (GLshortP, GLshortP))
-BGL_Wrap(1, RenderMode, GLint, (GLenum))
-BGL_Wrap(4, Rotated, void, (GLdouble, GLdouble, GLdouble, GLdouble))
-BGL_Wrap(4, Rotatef, void, (GLfloat, GLfloat, GLfloat, GLfloat))
-BGL_Wrap(3, Scaled, void, (GLdouble, GLdouble, GLdouble))
-BGL_Wrap(3, Scalef, void, (GLfloat, GLfloat, GLfloat))
-BGL_Wrap(4, Scissor, void, (GLint, GLint, GLsizei, GLsizei))
-BGL_Wrap(2, SelectBuffer, void, (GLsizei, GLuintP))
-BGL_Wrap(1, ShadeModel, void, (GLenum))
-BGL_Wrap(3, StencilFunc, void, (GLenum, GLint, GLuint))
-BGL_Wrap(1, StencilMask, void, (GLuint))
-BGL_Wrap(3, StencilOp, void, (GLenum, GLenum, GLenum))
-BGL_Wrap(1, TexCoord1d, void, (GLdouble))
-BGL_Wrap(1, TexCoord1dv, void, (GLdoubleP))
-BGL_Wrap(1, TexCoord1f, void, (GLfloat))
-BGL_Wrap(1, TexCoord1fv, void, (GLfloatP))
-BGL_Wrap(1, TexCoord1i, void, (GLint))
-BGL_Wrap(1, TexCoord1iv, void, (GLintP))
-BGL_Wrap(1, TexCoord1s, void, (GLshort))
-BGL_Wrap(1, TexCoord1sv, void, (GLshortP))
-BGL_Wrap(2, TexCoord2d, void, (GLdouble, GLdouble))
-BGL_Wrap(1, TexCoord2dv, void, (GLdoubleP))
-BGL_Wrap(2, TexCoord2f, void, (GLfloat, GLfloat))
-BGL_Wrap(1, TexCoord2fv, void, (GLfloatP))
-BGL_Wrap(2, TexCoord2i, void, (GLint, GLint))
-BGL_Wrap(1, TexCoord2iv, void, (GLintP))
-BGL_Wrap(2, TexCoord2s, void, (GLshort, GLshort))
-BGL_Wrap(1, TexCoord2sv, void, (GLshortP))
-BGL_Wrap(3, TexCoord3d, void, (GLdouble, GLdouble, GLdouble))
-BGL_Wrap(1, TexCoord3dv, void, (GLdoubleP))
-BGL_Wrap(3, TexCoord3f, void, (GLfloat, GLfloat, GLfloat))
-BGL_Wrap(1, TexCoord3fv, void, (GLfloatP))
-BGL_Wrap(3, TexCoord3i, void, (GLint, GLint, GLint))
-BGL_Wrap(1, TexCoord3iv, void, (GLintP))
-BGL_Wrap(3, TexCoord3s, void, (GLshort, GLshort, GLshort))
-BGL_Wrap(1, TexCoord3sv, void, (GLshortP))
-BGL_Wrap(4, TexCoord4d, void, (GLdouble, GLdouble, GLdouble, GLdouble))
-BGL_Wrap(1, TexCoord4dv, void, (GLdoubleP))
-BGL_Wrap(4, TexCoord4f, void, (GLfloat, GLfloat, GLfloat, GLfloat))
-BGL_Wrap(1, TexCoord4fv, void, (GLfloatP))
-BGL_Wrap(4, TexCoord4i, void, (GLint, GLint, GLint, GLint))
-BGL_Wrap(1, TexCoord4iv, void, (GLintP))
-BGL_Wrap(4, TexCoord4s, void, (GLshort, GLshort, GLshort, GLshort))
-BGL_Wrap(1, TexCoord4sv, void, (GLshortP))
-BGL_Wrap(3, TexEnvf, void, (GLenum, GLenum, GLfloat))
-BGL_Wrap(3, TexEnvfv, void, (GLenum, GLenum, GLfloatP))
-BGL_Wrap(3, TexEnvi, void, (GLenum, GLenum, GLint))
-BGL_Wrap(3, TexEnviv, void, (GLenum, GLenum, GLintP))
-BGL_Wrap(3, TexGend, void, (GLenum, GLenum, GLdouble))
-BGL_Wrap(3, TexGendv, void, (GLenum, GLenum, GLdoubleP))
-BGL_Wrap(3, TexGenf, void, (GLenum, GLenum, GLfloat))
-BGL_Wrap(3, TexGenfv, void, (GLenum, GLenum, GLfloatP))
-BGL_Wrap(3, TexGeni, void, (GLenum, GLenum, GLint))
-BGL_Wrap(3, TexGeniv, void, (GLenum, GLenum, GLintP))
-BGL_Wrap(8, TexImage1D, void, (GLenum, GLint, GLint,
- GLsizei, GLint, GLenum, GLenum, GLvoidP))
-BGL_Wrap(9, TexImage2D, void, (GLenum, GLint, GLint,
- GLsizei, GLsizei, GLint, GLenum, GLenum, GLvoidP))
-BGL_Wrap(3, TexParameterf, void, (GLenum, GLenum, GLfloat))
-BGL_Wrap(3, TexParameterfv, void, (GLenum, GLenum, GLfloatP))
-BGL_Wrap(3, TexParameteri, void, (GLenum, GLenum, GLint))
-BGL_Wrap(3, TexParameteriv, void, (GLenum, GLenum, GLintP))
-BGL_Wrap(3, Translated, void, (GLdouble, GLdouble, GLdouble))
-BGL_Wrap(3, Translatef, void, (GLfloat, GLfloat, GLfloat))
-BGL_Wrap(2, Uniform1f, void, (GLint, GLfloat))
-BGL_Wrap(3, Uniform2f, void, (GLint, GLfloat, GLfloat))
-BGL_Wrap(4, Uniform3f, void, (GLint, GLfloat, GLfloat, GLfloat))
-BGL_Wrap(5, Uniform4f, void, (GLint, GLfloat, GLfloat, GLfloat, GLfloat))
-BGL_Wrap(3, Uniform1fv, void, (GLint, GLsizei, GLfloatP))
-BGL_Wrap(3, Uniform2fv, void, (GLint, GLsizei, GLfloatP))
-BGL_Wrap(3, Uniform3fv, void, (GLint, GLsizei, GLfloatP))
-BGL_Wrap(3, Uniform4fv, void, (GLint, GLsizei, GLfloatP))
-BGL_Wrap(2, Uniform1i, void, (GLint, GLint))
-BGL_Wrap(3, Uniform2i, void, (GLint, GLint, GLint))
-BGL_Wrap(4, Uniform3i, void, (GLint, GLint, GLint, GLint))
-BGL_Wrap(5, Uniform4i, void, (GLint, GLint, GLint, GLint, GLint))
-BGL_Wrap(3, Uniform1iv, void, (GLint, GLsizei, GLintP))
-BGL_Wrap(3, Uniform2iv, void, (GLint, GLsizei, GLintP))
-BGL_Wrap(3, Uniform3iv, void, (GLint, GLsizei, GLintP))
-BGL_Wrap(3, Uniform4iv, void, (GLint, GLsizei, GLintP))
-BGL_Wrap(4, UniformMatrix2fv, void, (GLint, GLsizei, GLboolean, GLfloatP))
-BGL_Wrap(4, UniformMatrix3fv, void, (GLint, GLsizei, GLboolean, GLfloatP))
-BGL_Wrap(4, UniformMatrix4fv, void, (GLint, GLsizei, GLboolean, GLfloatP))
-BGL_Wrap(4, UniformMatrix2x3fv, void, (GLint, GLsizei, GLboolean, GLfloatP))
-BGL_Wrap(4, UniformMatrix3x2fv, void, (GLint, GLsizei, GLboolean, GLfloatP))
-BGL_Wrap(4, UniformMatrix2x4fv, void, (GLint, GLsizei, GLboolean, GLfloatP))
-BGL_Wrap(4, UniformMatrix4x2fv, void, (GLint, GLsizei, GLboolean, GLfloatP))
-BGL_Wrap(4, UniformMatrix3x4fv, void, (GLint, GLsizei, GLboolean, GLfloatP))
-BGL_Wrap(4, UniformMatrix4x3fv, void, (GLint, GLsizei, GLboolean, GLfloatP))
-BGL_Wrap(1, UseProgram, void, (GLuint))
-BGL_Wrap(1, ValidateProgram, void, (GLuint))
-BGL_Wrap(2, Vertex2d, void, (GLdouble, GLdouble))
-BGL_Wrap(1, Vertex2dv, void, (GLdoubleP))
-BGL_Wrap(2, Vertex2f, void, (GLfloat, GLfloat))
-BGL_Wrap(1, Vertex2fv, void, (GLfloatP))
-BGL_Wrap(2, Vertex2i, void, (GLint, GLint))
-BGL_Wrap(1, Vertex2iv, void, (GLintP))
-BGL_Wrap(2, Vertex2s, void, (GLshort, GLshort))
-BGL_Wrap(1, Vertex2sv, void, (GLshortP))
-BGL_Wrap(3, Vertex3d, void, (GLdouble, GLdouble, GLdouble))
-BGL_Wrap(1, Vertex3dv, void, (GLdoubleP))
-BGL_Wrap(3, Vertex3f, void, (GLfloat, GLfloat, GLfloat))
-BGL_Wrap(1, Vertex3fv, void, (GLfloatP))
-BGL_Wrap(3, Vertex3i, void, (GLint, GLint, GLint))
-BGL_Wrap(1, Vertex3iv, void, (GLintP))
-BGL_Wrap(3, Vertex3s, void, (GLshort, GLshort, GLshort))
-BGL_Wrap(1, Vertex3sv, void, (GLshortP))
-BGL_Wrap(4, Vertex4d, void, (GLdouble, GLdouble, GLdouble, GLdouble))
-BGL_Wrap(1, Vertex4dv, void, (GLdoubleP))
-BGL_Wrap(4, Vertex4f, void, (GLfloat, GLfloat, GLfloat, GLfloat))
-BGL_Wrap(1, Vertex4fv, void, (GLfloatP))
-BGL_Wrap(4, Vertex4i, void, (GLint, GLint, GLint, GLint))
-BGL_Wrap(1, Vertex4iv, void, (GLintP))
-BGL_Wrap(4, Vertex4s, void, (GLshort, GLshort, GLshort, GLshort))
-BGL_Wrap(1, Vertex4sv, void, (GLshortP))
-BGL_Wrap(4, Viewport, void, (GLint, GLint, GLsizei, GLsizei))
-BGLU_Wrap(4, Perspective, void, (GLdouble, GLdouble, GLdouble, GLdouble))
-BGLU_Wrap(9, LookAt, void, (GLdouble, GLdouble, GLdouble, GLdouble, GLdouble, GLdouble, GLdouble, GLdouble, GLdouble))
-BGLU_Wrap(4, Ortho2D, void, (GLdouble, GLdouble, GLdouble, GLdouble))
-BGLU_Wrap(5, PickMatrix, void, (GLdouble, GLdouble, GLdouble, GLdouble, GLintP))
-BGLU_Wrap(9, Project, GLint, (GLdouble, GLdouble, GLdouble, GLdoubleP, GLdoubleP, GLintP, GLdoubleP, GLdoubleP, GLdoubleP))
-BGLU_Wrap(9, UnProject, GLint, (GLdouble, GLdouble, GLdouble, GLdoubleP, GLdoubleP, GLintP, GLdoubleP, GLdoubleP, GLdoubleP))
-
-#undef MethodDef
-#define MethodDef(func) {"gl"#func, Method_##func, METH_VARARGS, "no string"}
-#define MethodDefu(func) {"glu"#func, Method_##func, METH_VARARGS, "no string"}
-/* So that MethodDef(Accum) becomes:
- * {"glAccum", Method_Accumfunc, METH_VARARGS} */
-static struct PyMethodDef BGL_methods[] = {
+/* -------------------------------------------------------------------- */
+
+/** \name OpenGL API Wrapping
+ * \{ */
-/* #ifndef __APPLE__ */
- MethodDef(Accum),
- MethodDef(ActiveTexture),
- MethodDef(AlphaFunc),
- MethodDef(AreTexturesResident),
- MethodDef(AttachShader),
- MethodDef(Begin),
- MethodDef(BindTexture),
- MethodDef(Bitmap),
- MethodDef(BlendFunc),
- MethodDef(CallList),
- MethodDef(CallLists),
- MethodDef(Clear),
- MethodDef(ClearAccum),
- MethodDef(ClearColor),
- MethodDef(ClearDepth),
- MethodDef(ClearIndex),
- MethodDef(ClearStencil),
- MethodDef(ClipPlane),
- MethodDef(Color3b),
- MethodDef(Color3bv),
- MethodDef(Color3d),
- MethodDef(Color3dv),
- MethodDef(Color3f),
- MethodDef(Color3fv),
- MethodDef(Color3i),
- MethodDef(Color3iv),
- MethodDef(Color3s),
- MethodDef(Color3sv),
- MethodDef(Color3ub),
- MethodDef(Color3ubv),
- MethodDef(Color3ui),
- MethodDef(Color3uiv),
- MethodDef(Color3us),
- MethodDef(Color3usv),
- MethodDef(Color4b),
- MethodDef(Color4bv),
- MethodDef(Color4d),
- MethodDef(Color4dv),
- MethodDef(Color4f),
- MethodDef(Color4fv),
- MethodDef(Color4i),
- MethodDef(Color4iv),
- MethodDef(Color4s),
- MethodDef(Color4sv),
- MethodDef(Color4ub),
- MethodDef(Color4ubv),
- MethodDef(Color4ui),
- MethodDef(Color4uiv),
- MethodDef(Color4us),
- MethodDef(Color4usv),
- MethodDef(ColorMask),
- MethodDef(ColorMaterial),
- MethodDef(CompileShader),
- MethodDef(CopyPixels),
- MethodDef(CopyTexImage2D),
- MethodDef(CreateProgram),
- MethodDef(CreateShader),
- MethodDef(CullFace),
- MethodDef(DeleteLists),
- MethodDef(DeleteProgram),
- MethodDef(DeleteShader),
- MethodDef(DeleteTextures),
- MethodDef(DepthFunc),
- MethodDef(DepthMask),
- MethodDef(DepthRange),
- MethodDef(DetachShader),
- MethodDef(Disable),
- MethodDef(DrawBuffer),
- MethodDef(DrawPixels),
- MethodDef(EdgeFlag),
- MethodDef(EdgeFlagv),
- MethodDef(Enable),
- MethodDef(End),
- MethodDef(EndList),
- MethodDef(EvalCoord1d),
- MethodDef(EvalCoord1dv),
- MethodDef(EvalCoord1f),
- MethodDef(EvalCoord1fv),
- MethodDef(EvalCoord2d),
- MethodDef(EvalCoord2dv),
- MethodDef(EvalCoord2f),
- MethodDef(EvalCoord2fv),
- MethodDef(EvalMesh1),
- MethodDef(EvalMesh2),
- MethodDef(EvalPoint1),
- MethodDef(EvalPoint2),
- MethodDef(FeedbackBuffer),
- MethodDef(Finish),
- MethodDef(Flush),
- MethodDef(Fogf),
- MethodDef(Fogfv),
- MethodDef(Fogi),
- MethodDef(Fogiv),
- MethodDef(FrontFace),
- MethodDef(Frustum),
- MethodDef(GenLists),
- MethodDef(GenTextures),
- MethodDef(GetAttachedShaders),
- MethodDef(GetBooleanv),
- MethodDef(GetClipPlane),
- MethodDef(GetDoublev),
- MethodDef(GetError),
- MethodDef(GetFloatv),
- MethodDef(GetIntegerv),
- MethodDef(GetLightfv),
- MethodDef(GetLightiv),
- MethodDef(GetMapdv),
- MethodDef(GetMapfv),
- MethodDef(GetMapiv),
- MethodDef(GetMaterialfv),
- MethodDef(GetMaterialiv),
- MethodDef(GetPixelMapfv),
- MethodDef(GetPixelMapuiv),
- MethodDef(GetPixelMapusv),
- MethodDef(GetPolygonStipple),
- MethodDef(GetProgramInfoLog),
- MethodDef(GetProgramiv),
- MethodDef(GetShaderInfoLog),
- MethodDef(GetShaderiv),
- MethodDef(GetShaderSource),
- MethodDef(GetString),
- MethodDef(GetTexEnvfv),
- MethodDef(GetTexEnviv),
- MethodDef(GetTexGendv),
- MethodDef(GetTexGenfv),
- MethodDef(GetTexGeniv),
- MethodDef(GetTexImage),
- MethodDef(GetTexLevelParameterfv),
- MethodDef(GetTexLevelParameteriv),
- MethodDef(GetTexParameterfv),
- MethodDef(GetTexParameteriv),
- MethodDef(GetUniformLocation),
- MethodDef(Hint),
- MethodDef(IndexMask),
- MethodDef(Indexd),
- MethodDef(Indexdv),
- MethodDef(Indexf),
- MethodDef(Indexfv),
- MethodDef(Indexi),
- MethodDef(Indexiv),
- MethodDef(Indexs),
- MethodDef(Indexsv),
- MethodDef(InitNames),
- MethodDef(IsEnabled),
- MethodDef(IsList),
- MethodDef(IsProgram),
- MethodDef(IsShader),
- MethodDef(IsTexture),
- MethodDef(LightModelf),
- MethodDef(LightModelfv),
- MethodDef(LightModeli),
- MethodDef(LightModeliv),
- MethodDef(Lightf),
- MethodDef(Lightfv),
- MethodDef(Lighti),
- MethodDef(Lightiv),
- MethodDef(LineStipple),
- MethodDef(LineWidth),
- MethodDef(LinkProgram),
- MethodDef(ListBase),
- MethodDef(LoadIdentity),
- MethodDef(LoadMatrixd),
- MethodDef(LoadMatrixf),
- MethodDef(LoadName),
- MethodDef(LogicOp),
- MethodDef(Map1d),
- MethodDef(Map1f),
- MethodDef(Map2d),
- MethodDef(Map2f),
- MethodDef(MapGrid1d),
- MethodDef(MapGrid1f),
- MethodDef(MapGrid2d),
- MethodDef(MapGrid2f),
- MethodDef(Materialf),
- MethodDef(Materialfv),
- MethodDef(Materiali),
- MethodDef(Materialiv),
- MethodDef(MatrixMode),
- MethodDef(MultMatrixd),
- MethodDef(MultMatrixf),
- MethodDef(NewList),
- MethodDef(Normal3b),
- MethodDef(Normal3bv),
- MethodDef(Normal3d),
- MethodDef(Normal3dv),
- MethodDef(Normal3f),
- MethodDef(Normal3fv),
- MethodDef(Normal3i),
- MethodDef(Normal3iv),
- MethodDef(Normal3s),
- MethodDef(Normal3sv),
- MethodDef(Ortho),
- MethodDef(PassThrough),
- MethodDef(PixelMapfv),
- MethodDef(PixelMapuiv),
- MethodDef(PixelMapusv),
- MethodDef(PixelStoref),
- MethodDef(PixelStorei),
- MethodDef(PixelTransferf),
- MethodDef(PixelTransferi),
- MethodDef(PixelZoom),
- MethodDef(PointSize),
- MethodDef(PolygonMode),
- MethodDef(PolygonOffset),
- MethodDef(PolygonStipple),
- MethodDef(PopAttrib),
- MethodDef(PopClientAttrib),
- MethodDef(PopMatrix),
- MethodDef(PopName),
- MethodDef(PrioritizeTextures),
- MethodDef(PushAttrib),
- MethodDef(PushClientAttrib),
- MethodDef(PushMatrix),
- MethodDef(PushName),
- MethodDef(RasterPos2d),
- MethodDef(RasterPos2dv),
- MethodDef(RasterPos2f),
- MethodDef(RasterPos2fv),
- MethodDef(RasterPos2i),
- MethodDef(RasterPos2iv),
- MethodDef(RasterPos2s),
- MethodDef(RasterPos2sv),
- MethodDef(RasterPos3d),
- MethodDef(RasterPos3dv),
- MethodDef(RasterPos3f),
- MethodDef(RasterPos3fv),
- MethodDef(RasterPos3i),
- MethodDef(RasterPos3iv),
- MethodDef(RasterPos3s),
- MethodDef(RasterPos3sv),
- MethodDef(RasterPos4d),
- MethodDef(RasterPos4dv),
- MethodDef(RasterPos4f),
- MethodDef(RasterPos4fv),
- MethodDef(RasterPos4i),
- MethodDef(RasterPos4iv),
- MethodDef(RasterPos4s),
- MethodDef(RasterPos4sv),
- MethodDef(ReadBuffer),
- MethodDef(ReadPixels),
- MethodDef(Rectd),
- MethodDef(Rectdv),
- MethodDef(Rectf),
- MethodDef(Rectfv),
- MethodDef(Recti),
- MethodDef(Rectiv),
- MethodDef(Rects),
- MethodDef(Rectsv),
- MethodDef(RenderMode),
- MethodDef(Rotated),
- MethodDef(Rotatef),
- MethodDef(Scaled),
- MethodDef(Scalef),
- MethodDef(Scissor),
- MethodDef(SelectBuffer),
- MethodDef(ShadeModel),
- MethodDef(ShaderSource),
- MethodDef(StencilFunc),
- MethodDef(StencilMask),
- MethodDef(StencilOp),
- MethodDef(TexCoord1d),
- MethodDef(TexCoord1dv),
- MethodDef(TexCoord1f),
- MethodDef(TexCoord1fv),
- MethodDef(TexCoord1i),
- MethodDef(TexCoord1iv),
- MethodDef(TexCoord1s),
- MethodDef(TexCoord1sv),
- MethodDef(TexCoord2d),
- MethodDef(TexCoord2dv),
- MethodDef(TexCoord2f),
- MethodDef(TexCoord2fv),
- MethodDef(TexCoord2i),
- MethodDef(TexCoord2iv),
- MethodDef(TexCoord2s),
- MethodDef(TexCoord2sv),
- MethodDef(TexCoord3d),
- MethodDef(TexCoord3dv),
- MethodDef(TexCoord3f),
- MethodDef(TexCoord3fv),
- MethodDef(TexCoord3i),
- MethodDef(TexCoord3iv),
- MethodDef(TexCoord3s),
- MethodDef(TexCoord3sv),
- MethodDef(TexCoord4d),
- MethodDef(TexCoord4dv),
- MethodDef(TexCoord4f),
- MethodDef(TexCoord4fv),
- MethodDef(TexCoord4i),
- MethodDef(TexCoord4iv),
- MethodDef(TexCoord4s),
- MethodDef(TexCoord4sv),
- MethodDef(TexEnvf),
- MethodDef(TexEnvfv),
- MethodDef(TexEnvi),
- MethodDef(TexEnviv),
- MethodDef(TexGend),
- MethodDef(TexGendv),
- MethodDef(TexGenf),
- MethodDef(TexGenfv),
- MethodDef(TexGeni),
- MethodDef(TexGeniv),
- MethodDef(TexImage1D),
- MethodDef(TexImage2D),
- MethodDef(TexParameterf),
- MethodDef(TexParameterfv),
- MethodDef(TexParameteri),
- MethodDef(TexParameteriv),
- MethodDef(Translated),
- MethodDef(Translatef),
- MethodDef(Uniform1f),
- MethodDef(Uniform2f),
- MethodDef(Uniform3f),
- MethodDef(Uniform4f),
- MethodDef(Uniform1fv),
- MethodDef(Uniform2fv),
- MethodDef(Uniform3fv),
- MethodDef(Uniform4fv),
- MethodDef(Uniform1i),
- MethodDef(Uniform2i),
- MethodDef(Uniform3i),
- MethodDef(Uniform4i),
- MethodDef(Uniform1iv),
- MethodDef(Uniform2iv),
- MethodDef(Uniform3iv),
- MethodDef(Uniform4iv),
- MethodDef(UniformMatrix2fv),
- MethodDef(UniformMatrix3fv),
- MethodDef(UniformMatrix4fv),
- MethodDef(UniformMatrix2x3fv),
- MethodDef(UniformMatrix3x2fv),
- MethodDef(UniformMatrix2x4fv),
- MethodDef(UniformMatrix4x2fv),
- MethodDef(UniformMatrix3x4fv),
- MethodDef(UniformMatrix4x3fv),
- MethodDef(UseProgram),
- MethodDef(ValidateProgram),
- MethodDef(Vertex2d),
- MethodDef(Vertex2dv),
- MethodDef(Vertex2f),
- MethodDef(Vertex2fv),
- MethodDef(Vertex2i),
- MethodDef(Vertex2iv),
- MethodDef(Vertex2s),
- MethodDef(Vertex2sv),
- MethodDef(Vertex3d),
- MethodDef(Vertex3dv),
- MethodDef(Vertex3f),
- MethodDef(Vertex3fv),
- MethodDef(Vertex3i),
- MethodDef(Vertex3iv),
- MethodDef(Vertex3s),
- MethodDef(Vertex3sv),
- MethodDef(Vertex4d),
- MethodDef(Vertex4dv),
- MethodDef(Vertex4f),
- MethodDef(Vertex4fv),
- MethodDef(Vertex4i),
- MethodDef(Vertex4iv),
- MethodDef(Vertex4s),
- MethodDef(Vertex4sv),
- MethodDef(Viewport),
+#define BGL_Wrap(funcname, ret, arg_list) \
+static PyObject *Method_##funcname (PyObject *UNUSED(self), PyObject *args) \
+{ \
+ arg_def arg_list; \
+ ret_def_##ret; \
+ if (!PyArg_ParseTuple(args, arg_str arg_list, arg_ref arg_list)) { \
+ return NULL; \
+ } \
+ ret_set_##ret gl##funcname (arg_var arg_list); \
+ ret_ret_##ret; \
+}
+
+#define BGLU_Wrap(funcname, ret, arg_list) \
+static PyObject *Method_##funcname (PyObject *UNUSED(self), PyObject *args) \
+{ \
+ arg_def arg_list; \
+ ret_def_##ret; \
+ if (!PyArg_ParseTuple(args, arg_str arg_list, arg_ref arg_list)) { \
+ return NULL; \
+ } \
+ ret_set_##ret glu##funcname (arg_var arg_list); \
+ ret_ret_##ret; \
+}
+
+/* GL_VERSION_1_0 */
+BGL_Wrap(Accum, void, (GLenum, GLfloat))
+BGL_Wrap(AlphaFunc, void, (GLenum, GLfloat))
+BGL_Wrap(Begin, void, (GLenum))
+BGL_Wrap(Bitmap, void, (GLsizei, GLsizei, GLfloat, GLfloat, GLfloat, GLfloat, GLubyteP))
+BGL_Wrap(BlendFunc, void, (GLenum, GLenum))
+BGL_Wrap(CallList, void, (GLuint))
+BGL_Wrap(CallLists, void, (GLsizei, GLenum, GLvoidP))
+BGL_Wrap(Clear, void, (GLbitfield))
+BGL_Wrap(ClearAccum, void, (GLfloat, GLfloat, GLfloat, GLfloat))
+BGL_Wrap(ClearColor, void, (GLfloat, GLfloat, GLfloat, GLfloat))
+BGL_Wrap(ClearDepth, void, (GLdouble))
+BGL_Wrap(ClearIndex, void, (GLfloat))
+BGL_Wrap(ClearStencil, void, (GLint))
+BGL_Wrap(ClipPlane, void, (GLenum, GLdoubleP))
+BGL_Wrap(Color3b, void, (GLbyte, GLbyte, GLbyte))
+BGL_Wrap(Color3bv, void, (GLbyteP))
+BGL_Wrap(Color3d, void, (GLdouble, GLdouble, GLdouble))
+BGL_Wrap(Color3dv, void, (GLdoubleP))
+BGL_Wrap(Color3f, void, (GLfloat, GLfloat, GLfloat))
+BGL_Wrap(Color3fv, void, (GLfloatP))
+BGL_Wrap(Color3i, void, (GLint, GLint, GLint))
+BGL_Wrap(Color3iv, void, (GLintP))
+BGL_Wrap(Color3s, void, (GLshort, GLshort, GLshort))
+BGL_Wrap(Color3sv, void, (GLshortP))
+BGL_Wrap(Color3ub, void, (GLubyte, GLubyte, GLubyte))
+BGL_Wrap(Color3ubv, void, (GLubyteP))
+BGL_Wrap(Color3ui, void, (GLuint, GLuint, GLuint))
+BGL_Wrap(Color3uiv, void, (GLuintP))
+BGL_Wrap(Color3us, void, (GLushort, GLushort, GLushort))
+BGL_Wrap(Color3usv, void, (GLushortP))
+BGL_Wrap(Color4b, void, (GLbyte, GLbyte, GLbyte, GLbyte))
+BGL_Wrap(Color4bv, void, (GLbyteP))
+BGL_Wrap(Color4d, void, (GLdouble, GLdouble, GLdouble, GLdouble))
+BGL_Wrap(Color4dv, void, (GLdoubleP))
+BGL_Wrap(Color4f, void, (GLfloat, GLfloat, GLfloat, GLfloat))
+BGL_Wrap(Color4fv, void, (GLfloatP))
+BGL_Wrap(Color4i, void, (GLint, GLint, GLint, GLint))
+BGL_Wrap(Color4iv, void, (GLintP))
+BGL_Wrap(Color4s, void, (GLshort, GLshort, GLshort, GLshort))
+BGL_Wrap(Color4sv, void, (GLshortP))
+BGL_Wrap(Color4ub, void, (GLubyte, GLubyte, GLubyte, GLubyte))
+BGL_Wrap(Color4ubv, void, (GLubyteP))
+BGL_Wrap(Color4ui, void, (GLuint, GLuint, GLuint, GLuint))
+BGL_Wrap(Color4uiv, void, (GLuintP))
+BGL_Wrap(Color4us, void, (GLushort, GLushort, GLushort, GLushort))
+BGL_Wrap(Color4usv, void, (GLushortP))
+BGL_Wrap(ColorMask, void, (GLboolean, GLboolean, GLboolean, GLboolean))
+BGL_Wrap(ColorMaterial, void, (GLenum, GLenum))
+BGL_Wrap(CopyPixels, void, (GLint, GLint, GLsizei, GLsizei, GLenum))
+BGL_Wrap(CullFace, void, (GLenum))
+BGL_Wrap(DeleteLists, void, (GLuint, GLsizei))
+BGL_Wrap(DepthFunc, void, (GLenum))
+BGL_Wrap(DepthMask, void, (GLboolean))
+BGL_Wrap(DepthRange, void, (GLdouble, GLdouble))
+BGL_Wrap(Disable, void, (GLenum))
+BGL_Wrap(DrawBuffer, void, (GLenum))
+BGL_Wrap(DrawPixels, void, (GLsizei, GLsizei, GLenum, GLenum, GLvoidP))
+BGL_Wrap(EdgeFlag, void, (GLboolean))
+BGL_Wrap(EdgeFlagv, void, (GLbooleanP))
+BGL_Wrap(Enable, void, (GLenum))
+BGL_Wrap(End, void, (void))
+BGL_Wrap(EndList, void, (void))
+BGL_Wrap(EvalCoord1d, void, (GLdouble))
+BGL_Wrap(EvalCoord1dv, void, (GLdoubleP))
+BGL_Wrap(EvalCoord1f, void, (GLfloat))
+BGL_Wrap(EvalCoord1fv, void, (GLfloatP))
+BGL_Wrap(EvalCoord2d, void, (GLdouble, GLdouble))
+BGL_Wrap(EvalCoord2dv, void, (GLdoubleP))
+BGL_Wrap(EvalCoord2f, void, (GLfloat, GLfloat))
+BGL_Wrap(EvalCoord2fv, void, (GLfloatP))
+BGL_Wrap(EvalMesh1, void, (GLenum, GLint, GLint))
+BGL_Wrap(EvalMesh2, void, (GLenum, GLint, GLint, GLint, GLint))
+BGL_Wrap(EvalPoint1, void, (GLint))
+BGL_Wrap(EvalPoint2, void, (GLint, GLint))
+BGL_Wrap(FeedbackBuffer, void, (GLsizei, GLenum, GLfloatP))
+BGL_Wrap(Finish, void, (void))
+BGL_Wrap(Flush, void, (void))
+BGL_Wrap(Fogf, void, (GLenum, GLfloat))
+BGL_Wrap(Fogfv, void, (GLenum, GLfloatP))
+BGL_Wrap(Fogi, void, (GLenum, GLint))
+BGL_Wrap(Fogiv, void, (GLenum, GLintP))
+BGL_Wrap(FrontFace, void, (GLenum))
+BGL_Wrap(Frustum, void, (GLdouble, GLdouble, GLdouble, GLdouble, GLdouble, GLdouble))
+BGL_Wrap(GenLists, GLuint, (GLsizei))
+BGL_Wrap(GetBooleanv, void, (GLenum, GLbooleanP))
+BGL_Wrap(GetClipPlane, void, (GLenum, GLdoubleP))
+BGL_Wrap(GetDoublev, void, (GLenum, GLdoubleP))
+BGL_Wrap(GetError, GLenum, (void))
+BGL_Wrap(GetFloatv, void, (GLenum, GLfloatP))
+BGL_Wrap(GetIntegerv, void, (GLenum, GLintP))
+BGL_Wrap(GetLightfv, void, (GLenum, GLenum, GLfloatP))
+BGL_Wrap(GetLightiv, void, (GLenum, GLenum, GLintP))
+BGL_Wrap(GetMapdv, void, (GLenum, GLenum, GLdoubleP))
+BGL_Wrap(GetMapfv, void, (GLenum, GLenum, GLfloatP))
+BGL_Wrap(GetMapiv, void, (GLenum, GLenum, GLintP))
+BGL_Wrap(GetMaterialfv, void, (GLenum, GLenum, GLfloatP))
+BGL_Wrap(GetMaterialiv, void, (GLenum, GLenum, GLintP))
+BGL_Wrap(GetPixelMapfv, void, (GLenum, GLfloatP))
+BGL_Wrap(GetPixelMapuiv, void, (GLenum, GLuintP))
+BGL_Wrap(GetPixelMapusv, void, (GLenum, GLushortP))
+BGL_Wrap(GetPolygonStipple, void, (GLubyteP))
+BGL_Wrap(GetString, GLstring, (GLenum))
+BGL_Wrap(GetTexEnvfv, void, (GLenum, GLenum, GLfloatP))
+BGL_Wrap(GetTexEnviv, void, (GLenum, GLenum, GLintP))
+BGL_Wrap(GetTexGendv, void, (GLenum, GLenum, GLdoubleP))
+BGL_Wrap(GetTexGenfv, void, (GLenum, GLenum, GLfloatP))
+BGL_Wrap(GetTexGeniv, void, (GLenum, GLenum, GLintP))
+BGL_Wrap(GetTexImage, void, (GLenum, GLint, GLenum, GLenum, GLvoidP))
+BGL_Wrap(GetTexLevelParameterfv, void, (GLenum, GLint, GLenum, GLfloatP))
+BGL_Wrap(GetTexLevelParameteriv, void, (GLenum, GLint, GLenum, GLintP))
+BGL_Wrap(GetTexParameterfv, void, (GLenum, GLenum, GLfloatP))
+BGL_Wrap(GetTexParameteriv, void, (GLenum, GLenum, GLintP))
+BGL_Wrap(Hint, void, (GLenum, GLenum))
+BGL_Wrap(IndexMask, void, (GLuint))
+BGL_Wrap(Indexd, void, (GLdouble))
+BGL_Wrap(Indexdv, void, (GLdoubleP))
+BGL_Wrap(Indexf, void, (GLfloat))
+BGL_Wrap(Indexfv, void, (GLfloatP))
+BGL_Wrap(Indexi, void, (GLint))
+BGL_Wrap(Indexiv, void, (GLintP))
+BGL_Wrap(Indexs, void, (GLshort))
+BGL_Wrap(Indexsv, void, (GLshortP))
+BGL_Wrap(InitNames, void, (void))
+BGL_Wrap(IsEnabled, GLboolean, (GLenum))
+BGL_Wrap(IsList, GLboolean, (GLuint))
+BGL_Wrap(LightModelf, void, (GLenum, GLfloat))
+BGL_Wrap(LightModelfv, void, (GLenum, GLfloatP))
+BGL_Wrap(LightModeli, void, (GLenum, GLint))
+BGL_Wrap(LightModeliv, void, (GLenum, GLintP))
+BGL_Wrap(Lightf, void, (GLenum, GLenum, GLfloat))
+BGL_Wrap(Lightfv, void, (GLenum, GLenum, GLfloatP))
+BGL_Wrap(Lighti, void, (GLenum, GLenum, GLint))
+BGL_Wrap(Lightiv, void, (GLenum, GLenum, GLintP))
+BGL_Wrap(LineStipple, void, (GLint, GLushort))
+BGL_Wrap(LineWidth, void, (GLfloat))
+BGL_Wrap(ListBase, void, (GLuint))
+BGL_Wrap(LoadIdentity, void, (void))
+BGL_Wrap(LoadMatrixd, void, (GLdoubleP))
+BGL_Wrap(LoadMatrixf, void, (GLfloatP))
+BGL_Wrap(LoadName, void, (GLuint))
+BGL_Wrap(LogicOp, void, (GLenum))
+BGL_Wrap(Map1d, void, (GLenum, GLdouble, GLdouble, GLint, GLint, GLdoubleP))
+BGL_Wrap(Map1f, void, (GLenum, GLfloat, GLfloat, GLint, GLint, GLfloatP))
+BGL_Wrap(Map2d, void, (GLenum, GLdouble, GLdouble, GLint, GLint, GLdouble, GLdouble, GLint, GLint, GLdoubleP))
+BGL_Wrap(Map2f, void, (GLenum, GLfloat, GLfloat, GLint, GLint, GLfloat, GLfloat, GLint, GLint, GLfloatP))
+BGL_Wrap(MapGrid1d, void, (GLint, GLdouble, GLdouble))
+BGL_Wrap(MapGrid1f, void, (GLint, GLfloat, GLfloat))
+BGL_Wrap(MapGrid2d, void, (GLint, GLdouble, GLdouble, GLint, GLdouble, GLdouble))
+BGL_Wrap(MapGrid2f, void, (GLint, GLfloat, GLfloat, GLint, GLfloat, GLfloat))
+BGL_Wrap(Materialf, void, (GLenum, GLenum, GLfloat))
+BGL_Wrap(Materialfv, void, (GLenum, GLenum, GLfloatP))
+BGL_Wrap(Materiali, void, (GLenum, GLenum, GLint))
+BGL_Wrap(Materialiv, void, (GLenum, GLenum, GLintP))
+BGL_Wrap(MatrixMode, void, (GLenum))
+BGL_Wrap(MultMatrixd, void, (GLdoubleP))
+BGL_Wrap(MultMatrixf, void, (GLfloatP))
+BGL_Wrap(NewList, void, (GLuint, GLenum))
+BGL_Wrap(Normal3b, void, (GLbyte, GLbyte, GLbyte))
+BGL_Wrap(Normal3bv, void, (GLbyteP))
+BGL_Wrap(Normal3d, void, (GLdouble, GLdouble, GLdouble))
+BGL_Wrap(Normal3dv, void, (GLdoubleP))
+BGL_Wrap(Normal3f, void, (GLfloat, GLfloat, GLfloat))
+BGL_Wrap(Normal3fv, void, (GLfloatP))
+BGL_Wrap(Normal3i, void, (GLint, GLint, GLint))
+BGL_Wrap(Normal3iv, void, (GLintP))
+BGL_Wrap(Normal3s, void, (GLshort, GLshort, GLshort))
+BGL_Wrap(Normal3sv, void, (GLshortP))
+BGL_Wrap(Ortho, void, (GLdouble, GLdouble, GLdouble, GLdouble, GLdouble, GLdouble))
+BGL_Wrap(PassThrough, void, (GLfloat))
+BGL_Wrap(PixelMapfv, void, (GLenum, GLsizei, GLfloatP))
+BGL_Wrap(PixelMapuiv, void, (GLenum, GLsizei, GLuintP))
+BGL_Wrap(PixelMapusv, void, (GLenum, GLsizei, GLushortP))
+BGL_Wrap(PixelStoref, void, (GLenum, GLfloat))
+BGL_Wrap(PixelStorei, void, (GLenum, GLint))
+BGL_Wrap(PixelTransferf, void, (GLenum, GLfloat))
+BGL_Wrap(PixelTransferi, void, (GLenum, GLint))
+BGL_Wrap(PixelZoom, void, (GLfloat, GLfloat))
+BGL_Wrap(PointSize, void, (GLfloat))
+BGL_Wrap(PolygonMode, void, (GLenum, GLenum))
+BGL_Wrap(PolygonStipple, void, (GLubyteP))
+BGL_Wrap(PopAttrib, void, (void))
+BGL_Wrap(PopMatrix, void, (void))
+BGL_Wrap(PopName, void, (void))
+BGL_Wrap(PushAttrib, void, (GLbitfield))
+BGL_Wrap(PushMatrix, void, (void))
+BGL_Wrap(PushName, void, (GLuint))
+BGL_Wrap(RasterPos2d, void, (GLdouble, GLdouble))
+BGL_Wrap(RasterPos2dv, void, (GLdoubleP))
+BGL_Wrap(RasterPos2f, void, (GLfloat, GLfloat))
+BGL_Wrap(RasterPos2fv, void, (GLfloatP))
+BGL_Wrap(RasterPos2i, void, (GLint, GLint))
+BGL_Wrap(RasterPos2iv, void, (GLintP))
+BGL_Wrap(RasterPos2s, void, (GLshort, GLshort))
+BGL_Wrap(RasterPos2sv, void, (GLshortP))
+BGL_Wrap(RasterPos3d, void, (GLdouble, GLdouble, GLdouble))
+BGL_Wrap(RasterPos3dv, void, (GLdoubleP))
+BGL_Wrap(RasterPos3f, void, (GLfloat, GLfloat, GLfloat))
+BGL_Wrap(RasterPos3fv, void, (GLfloatP))
+BGL_Wrap(RasterPos3i, void, (GLint, GLint, GLint))
+BGL_Wrap(RasterPos3iv, void, (GLintP))
+BGL_Wrap(RasterPos3s, void, (GLshort, GLshort, GLshort))
+BGL_Wrap(RasterPos3sv, void, (GLshortP))
+BGL_Wrap(RasterPos4d, void, (GLdouble, GLdouble, GLdouble, GLdouble))
+BGL_Wrap(RasterPos4dv, void, (GLdoubleP))
+BGL_Wrap(RasterPos4f, void, (GLfloat, GLfloat, GLfloat, GLfloat))
+BGL_Wrap(RasterPos4fv, void, (GLfloatP))
+BGL_Wrap(RasterPos4i, void, (GLint, GLint, GLint, GLint))
+BGL_Wrap(RasterPos4iv, void, (GLintP))
+BGL_Wrap(RasterPos4s, void, (GLshort, GLshort, GLshort, GLshort))
+BGL_Wrap(RasterPos4sv, void, (GLshortP))
+BGL_Wrap(ReadBuffer, void, (GLenum))
+BGL_Wrap(ReadPixels, void, (GLint, GLint, GLsizei, GLsizei, GLenum, GLenum, GLvoidP))
+BGL_Wrap(Rectd, void, (GLdouble, GLdouble, GLdouble, GLdouble))
+BGL_Wrap(Rectdv, void, (GLdoubleP, GLdoubleP))
+BGL_Wrap(Rectf, void, (GLfloat, GLfloat, GLfloat, GLfloat))
+BGL_Wrap(Rectfv, void, (GLfloatP, GLfloatP))
+BGL_Wrap(Recti, void, (GLint, GLint, GLint, GLint))
+BGL_Wrap(Rectiv, void, (GLintP, GLintP))
+BGL_Wrap(Rects, void, (GLshort, GLshort, GLshort, GLshort))
+BGL_Wrap(Rectsv, void, (GLshortP, GLshortP))
+BGL_Wrap(RenderMode, GLint, (GLenum))
+BGL_Wrap(Rotated, void, (GLdouble, GLdouble, GLdouble, GLdouble))
+BGL_Wrap(Rotatef, void, (GLfloat, GLfloat, GLfloat, GLfloat))
+BGL_Wrap(Scaled, void, (GLdouble, GLdouble, GLdouble))
+BGL_Wrap(Scalef, void, (GLfloat, GLfloat, GLfloat))
+BGL_Wrap(Scissor, void, (GLint, GLint, GLsizei, GLsizei))
+BGL_Wrap(SelectBuffer, void, (GLsizei, GLuintP))
+BGL_Wrap(ShadeModel, void, (GLenum))
+BGL_Wrap(StencilFunc, void, (GLenum, GLint, GLuint))
+BGL_Wrap(StencilMask, void, (GLuint))
+BGL_Wrap(StencilOp, void, (GLenum, GLenum, GLenum))
+BGL_Wrap(TexCoord1d, void, (GLdouble))
+BGL_Wrap(TexCoord1dv, void, (GLdoubleP))
+BGL_Wrap(TexCoord1f, void, (GLfloat))
+BGL_Wrap(TexCoord1fv, void, (GLfloatP))
+BGL_Wrap(TexCoord1i, void, (GLint))
+BGL_Wrap(TexCoord1iv, void, (GLintP))
+BGL_Wrap(TexCoord1s, void, (GLshort))
+BGL_Wrap(TexCoord1sv, void, (GLshortP))
+BGL_Wrap(TexCoord2d, void, (GLdouble, GLdouble))
+BGL_Wrap(TexCoord2dv, void, (GLdoubleP))
+BGL_Wrap(TexCoord2f, void, (GLfloat, GLfloat))
+BGL_Wrap(TexCoord2fv, void, (GLfloatP))
+BGL_Wrap(TexCoord2i, void, (GLint, GLint))
+BGL_Wrap(TexCoord2iv, void, (GLintP))
+BGL_Wrap(TexCoord2s, void, (GLshort, GLshort))
+BGL_Wrap(TexCoord2sv, void, (GLshortP))
+BGL_Wrap(TexCoord3d, void, (GLdouble, GLdouble, GLdouble))
+BGL_Wrap(TexCoord3dv, void, (GLdoubleP))
+BGL_Wrap(TexCoord3f, void, (GLfloat, GLfloat, GLfloat))
+BGL_Wrap(TexCoord3fv, void, (GLfloatP))
+BGL_Wrap(TexCoord3i, void, (GLint, GLint, GLint))
+BGL_Wrap(TexCoord3iv, void, (GLintP))
+BGL_Wrap(TexCoord3s, void, (GLshort, GLshort, GLshort))
+BGL_Wrap(TexCoord3sv, void, (GLshortP))
+BGL_Wrap(TexCoord4d, void, (GLdouble, GLdouble, GLdouble, GLdouble))
+BGL_Wrap(TexCoord4dv, void, (GLdoubleP))
+BGL_Wrap(TexCoord4f, void, (GLfloat, GLfloat, GLfloat, GLfloat))
+BGL_Wrap(TexCoord4fv, void, (GLfloatP))
+BGL_Wrap(TexCoord4i, void, (GLint, GLint, GLint, GLint))
+BGL_Wrap(TexCoord4iv, void, (GLintP))
+BGL_Wrap(TexCoord4s, void, (GLshort, GLshort, GLshort, GLshort))
+BGL_Wrap(TexCoord4sv, void, (GLshortP))
+BGL_Wrap(TexEnvf, void, (GLenum, GLenum, GLfloat))
+BGL_Wrap(TexEnvfv, void, (GLenum, GLenum, GLfloatP))
+BGL_Wrap(TexEnvi, void, (GLenum, GLenum, GLint))
+BGL_Wrap(TexEnviv, void, (GLenum, GLenum, GLintP))
+BGL_Wrap(TexGend, void, (GLenum, GLenum, GLdouble))
+BGL_Wrap(TexGendv, void, (GLenum, GLenum, GLdoubleP))
+BGL_Wrap(TexGenf, void, (GLenum, GLenum, GLfloat))
+BGL_Wrap(TexGenfv, void, (GLenum, GLenum, GLfloatP))
+BGL_Wrap(TexGeni, void, (GLenum, GLenum, GLint))
+BGL_Wrap(TexGeniv, void, (GLenum, GLenum, GLintP))
+BGL_Wrap(TexImage1D, void, (GLenum, GLint, GLint, GLsizei, GLint, GLenum, GLenum, GLvoidP))
+BGL_Wrap(TexImage2D, void, (GLenum, GLint, GLint, GLsizei, GLsizei, GLint, GLenum, GLenum, GLvoidP))
+BGL_Wrap(TexParameterf, void, (GLenum, GLenum, GLfloat))
+BGL_Wrap(TexParameterfv, void, (GLenum, GLenum, GLfloatP))
+BGL_Wrap(TexParameteri, void, (GLenum, GLenum, GLint))
+BGL_Wrap(TexParameteriv, void, (GLenum, GLenum, GLintP))
+BGL_Wrap(Translated, void, (GLdouble, GLdouble, GLdouble))
+BGL_Wrap(Translatef, void, (GLfloat, GLfloat, GLfloat))
+BGL_Wrap(Vertex2d, void, (GLdouble, GLdouble))
+BGL_Wrap(Vertex2dv, void, (GLdoubleP))
+BGL_Wrap(Vertex2f, void, (GLfloat, GLfloat))
+BGL_Wrap(Vertex2fv, void, (GLfloatP))
+BGL_Wrap(Vertex2i, void, (GLint, GLint))
+BGL_Wrap(Vertex2iv, void, (GLintP))
+BGL_Wrap(Vertex2s, void, (GLshort, GLshort))
+BGL_Wrap(Vertex2sv, void, (GLshortP))
+BGL_Wrap(Vertex3d, void, (GLdouble, GLdouble, GLdouble))
+BGL_Wrap(Vertex3dv, void, (GLdoubleP))
+BGL_Wrap(Vertex3f, void, (GLfloat, GLfloat, GLfloat))
+BGL_Wrap(Vertex3fv, void, (GLfloatP))
+BGL_Wrap(Vertex3i, void, (GLint, GLint, GLint))
+BGL_Wrap(Vertex3iv, void, (GLintP))
+BGL_Wrap(Vertex3s, void, (GLshort, GLshort, GLshort))
+BGL_Wrap(Vertex3sv, void, (GLshortP))
+BGL_Wrap(Vertex4d, void, (GLdouble, GLdouble, GLdouble, GLdouble))
+BGL_Wrap(Vertex4dv, void, (GLdoubleP))
+BGL_Wrap(Vertex4f, void, (GLfloat, GLfloat, GLfloat, GLfloat))
+BGL_Wrap(Vertex4fv, void, (GLfloatP))
+BGL_Wrap(Vertex4i, void, (GLint, GLint, GLint, GLint))
+BGL_Wrap(Vertex4iv, void, (GLintP))
+BGL_Wrap(Vertex4s, void, (GLshort, GLshort, GLshort, GLshort))
+BGL_Wrap(Vertex4sv, void, (GLshortP))
+BGL_Wrap(Viewport, void, (GLint, GLint, GLsizei, GLsizei))
+
+
+/* GL_VERSION_1_1 */
+BGL_Wrap(AreTexturesResident, GLboolean, (GLsizei, GLuintP, GLbooleanP))
+BGL_Wrap(ArrayElement, void, (GLint))
+BGL_Wrap(BindTexture, void, (GLenum, GLuint))
+BGL_Wrap(ColorPointer, void, (GLint, GLenum, GLsizei, GLvoidP))
+BGL_Wrap(CopyTexImage1D, void, (GLenum, GLint, GLenum, GLint, GLint, GLsizei, GLint))
+BGL_Wrap(CopyTexImage2D, void, (GLenum, GLint, GLenum, GLint, GLint, GLsizei, GLsizei, GLint))
+BGL_Wrap(CopyTexSubImage1D, void, (GLenum, GLint, GLint, GLint, GLint, GLsizei))
+BGL_Wrap(CopyTexSubImage2D, void, (GLenum, GLint, GLint, GLint, GLint, GLint, GLsizei, GLsizei))
+BGL_Wrap(DeleteTextures, void, (GLsizei, GLuintP))
+BGL_Wrap(DisableClientState, void, (GLenum))
+BGL_Wrap(DrawArrays, void, (GLenum, GLint, GLsizei))
+BGL_Wrap(DrawElements, void, (GLenum, GLsizei, GLenum, GLvoidP))
+BGL_Wrap(EdgeFlagPointer, void, (GLsizei, GLvoidP))
+BGL_Wrap(EnableClientState, void, (GLenum))
+BGL_Wrap(GenTextures, void, (GLsizei, GLuintP))
+BGL_Wrap(GetPointerv, void, (GLenum, GLvoidP))
+BGL_Wrap(IndexPointer, void, (GLenum, GLsizei, GLvoidP))
+BGL_Wrap(Indexub, void, (GLubyte))
+BGL_Wrap(Indexubv, void, (GLubyteP))
+BGL_Wrap(InterleavedArrays, void, (GLenum, GLsizei, GLvoidP))
+BGL_Wrap(IsTexture, GLboolean, (GLuint))
+BGL_Wrap(NormalPointer, void, (GLenum, GLsizei, GLvoidP))
+BGL_Wrap(PolygonOffset, void, (GLfloat, GLfloat))
+BGL_Wrap(PopClientAttrib, void, (void))
+BGL_Wrap(PrioritizeTextures, void, (GLsizei, GLuintP, GLfloatP))
+BGL_Wrap(PushClientAttrib, void, (GLbitfield))
+BGL_Wrap(TexCoordPointer, void, (GLint, GLenum, GLsizei, GLvoidP))
+BGL_Wrap(TexSubImage1D, void, (GLenum, GLint, GLint, GLsizei, GLenum, GLenum, GLvoidP))
+BGL_Wrap(TexSubImage2D, void, (GLenum, GLint, GLint, GLint, GLsizei, GLsizei, GLenum, GLenum, GLvoidP))
+BGL_Wrap(VertexPointer, void, (GLint, GLenum, GLsizei, GLvoidP))
+
+
+/* GL_VERSION_1_2 */
+BGL_Wrap(CopyTexSubImage3D, void, (GLenum, GLint, GLint, GLint, GLint, GLint, GLint, GLsizei, GLsizei))
+BGL_Wrap(DrawRangeElements, void, (GLenum, GLuint, GLuint, GLsizei, GLenum, GLvoidP))
+BGL_Wrap(TexImage3D, void, (GLenum, GLint, GLint, GLsizei, GLsizei, GLsizei, GLint, GLenum, GLenum, GLvoidP))
+BGL_Wrap(TexSubImage3D, void, (GLenum, GLint, GLint, GLint, GLint, GLsizei, GLsizei, GLsizei, GLenum, GLenum, GLvoidP))
+
+
+/* GL_VERSION_1_3 */
+BGL_Wrap(ActiveTexture, void, (GLenum))
+BGL_Wrap(ClientActiveTexture, void, (GLenum))
+BGL_Wrap(CompressedTexImage1D, void, (GLenum, GLint, GLenum, GLsizei, GLint, GLsizei, GLvoidP))
+BGL_Wrap(CompressedTexImage2D, void, (GLenum, GLint, GLenum, GLsizei, GLsizei, GLint, GLsizei, GLvoidP))
+BGL_Wrap(CompressedTexImage3D, void, (GLenum, GLint, GLenum, GLsizei, GLsizei, GLsizei, GLint, GLsizei, GLvoidP))
+BGL_Wrap(CompressedTexSubImage1D, void, (GLenum, GLint, GLint, GLsizei, GLenum, GLsizei, GLvoidP))
+BGL_Wrap(CompressedTexSubImage2D, void, (GLenum, GLint, GLint, GLint, GLsizei, GLsizei, GLenum, GLsizei, GLvoidP))
+BGL_Wrap(CompressedTexSubImage3D, void, (GLenum, GLint, GLint, GLint, GLint, GLsizei, GLsizei, GLsizei, GLenum, GLsizei, GLvoidP))
+BGL_Wrap(GetCompressedTexImage, void, (GLenum, GLint, GLvoidP))
+BGL_Wrap(LoadTransposeMatrixd, void, (GLdoubleP))
+BGL_Wrap(LoadTransposeMatrixf, void, (GLfloatP))
+BGL_Wrap(MultTransposeMatrixd, void, (GLdoubleP))
+BGL_Wrap(MultTransposeMatrixf, void, (GLfloatP))
+BGL_Wrap(MultiTexCoord1d, void, (GLenum, GLdouble))
+BGL_Wrap(MultiTexCoord1dv, void, (GLenum, GLdoubleP))
+BGL_Wrap(MultiTexCoord1f, void, (GLenum, GLfloat))
+BGL_Wrap(MultiTexCoord1fv, void, (GLenum, GLfloatP))
+BGL_Wrap(MultiTexCoord1i, void, (GLenum, GLint))
+BGL_Wrap(MultiTexCoord1iv, void, (GLenum, GLintP))
+BGL_Wrap(MultiTexCoord1s, void, (GLenum, GLshort))
+BGL_Wrap(MultiTexCoord1sv, void, (GLenum, GLshortP))
+BGL_Wrap(MultiTexCoord2d, void, (GLenum, GLdouble, GLdouble))
+BGL_Wrap(MultiTexCoord2dv, void, (GLenum, GLdoubleP))
+BGL_Wrap(MultiTexCoord2f, void, (GLenum, GLfloat, GLfloat))
+BGL_Wrap(MultiTexCoord2fv, void, (GLenum, GLfloatP))
+BGL_Wrap(MultiTexCoord2i, void, (GLenum, GLint, GLint))
+BGL_Wrap(MultiTexCoord2iv, void, (GLenum, GLintP))
+BGL_Wrap(MultiTexCoord2s, void, (GLenum, GLshort, GLshort))
+BGL_Wrap(MultiTexCoord2sv, void, (GLenum, GLshortP))
+BGL_Wrap(MultiTexCoord3d, void, (GLenum, GLdouble, GLdouble, GLdouble))
+BGL_Wrap(MultiTexCoord3dv, void, (GLenum, GLdoubleP))
+BGL_Wrap(MultiTexCoord3f, void, (GLenum, GLfloat, GLfloat, GLfloat))
+BGL_Wrap(MultiTexCoord3fv, void, (GLenum, GLfloatP))
+BGL_Wrap(MultiTexCoord3i, void, (GLenum, GLint, GLint, GLint))
+BGL_Wrap(MultiTexCoord3iv, void, (GLenum, GLintP))
+BGL_Wrap(MultiTexCoord3s, void, (GLenum, GLshort, GLshort, GLshort))
+BGL_Wrap(MultiTexCoord3sv, void, (GLenum, GLshortP))
+BGL_Wrap(MultiTexCoord4d, void, (GLenum, GLdouble, GLdouble, GLdouble, GLdouble))
+BGL_Wrap(MultiTexCoord4dv, void, (GLenum, GLdoubleP))
+BGL_Wrap(MultiTexCoord4f, void, (GLenum, GLfloat, GLfloat, GLfloat, GLfloat))
+BGL_Wrap(MultiTexCoord4fv, void, (GLenum, GLfloatP))
+BGL_Wrap(MultiTexCoord4i, void, (GLenum, GLint, GLint, GLint, GLint))
+BGL_Wrap(MultiTexCoord4iv, void, (GLenum, GLintP))
+BGL_Wrap(MultiTexCoord4s, void, (GLenum, GLshort, GLshort, GLshort, GLshort))
+BGL_Wrap(MultiTexCoord4sv, void, (GLenum, GLshortP))
+BGL_Wrap(SampleCoverage, void, (GLfloat, GLboolean))
+
+
+/* GL_VERSION_1_4 */
+BGL_Wrap(BlendColor, void, (GLfloat, GLfloat, GLfloat, GLfloat))
+BGL_Wrap(BlendEquation, void, (GLenum))
+
+
+/* GL_VERSION_1_5 */
+BGL_Wrap(BeginQuery, void, (GLenum, GLuint))
+BGL_Wrap(BindBuffer, void, (GLenum, GLuint))
+BGL_Wrap(BufferData, void, (GLenum, GLsizeiptr, GLvoidP, GLenum))
+BGL_Wrap(BufferSubData, void, (GLenum, GLintptr, GLsizeiptr, GLvoidP))
+BGL_Wrap(DeleteBuffers, void, (GLsizei, GLuintP))
+BGL_Wrap(DeleteQueries, void, (GLsizei, GLuintP))
+BGL_Wrap(EndQuery, void, (GLenum))
+BGL_Wrap(GenBuffers, void, (GLsizei, GLuintP))
+BGL_Wrap(GenQueries, void, (GLsizei, GLuintP))
+BGL_Wrap(GetBufferParameteriv, void, (GLenum, GLenum, GLintP))
+BGL_Wrap(GetBufferPointerv, void, (GLenum, GLenum, GLvoidP))
+BGL_Wrap(GetBufferSubData, void, (GLenum, GLintptr, GLsizeiptr, GLvoidP))
+BGL_Wrap(GetQueryObjectiv, void, (GLuint, GLenum, GLintP))
+BGL_Wrap(GetQueryObjectuiv, void, (GLuint, GLenum, GLuintP))
+BGL_Wrap(GetQueryiv, void, (GLenum, GLenum, GLintP))
+BGL_Wrap(IsBuffer, GLboolean, (GLuint))
+BGL_Wrap(IsQuery, GLboolean, (GLuint))
+BGL_Wrap(MapBuffer, void, (GLenum, GLenum))
+BGL_Wrap(UnmapBuffer, GLboolean, (GLenum))
+
+
+/* GL_VERSION_2_0 */
+BGL_Wrap(AttachShader, void, (GLuint, GLuint))
+BGL_Wrap(BindAttribLocation, void, (GLuint, GLuint, GLstring))
+BGL_Wrap(BlendEquationSeparate, void, (GLenum, GLenum))
+BGL_Wrap(CompileShader, void, (GLuint))
+BGL_Wrap(CreateProgram, GLuint, (void))
+BGL_Wrap(CreateShader, GLuint, (GLenum))
+BGL_Wrap(DeleteProgram, void, (GLuint))
+BGL_Wrap(DeleteShader, void, (GLuint))
+BGL_Wrap(DetachShader, void, (GLuint, GLuint))
+BGL_Wrap(DisableVertexAttribArray, void, (GLuint))
+BGL_Wrap(DrawBuffers, void, (GLsizei, GLenumP))
+BGL_Wrap(EnableVertexAttribArray, void, (GLuint))
+BGL_Wrap(GetActiveAttrib, void, (GLuint, GLuint, GLsizei, GLsizeiP, GLintP, GLenumP, GLcharP))
+BGL_Wrap(GetActiveUniform, void, (GLuint, GLuint, GLsizei, GLsizeiP, GLintP, GLenumP, GLcharP))
+BGL_Wrap(GetAttachedShaders, void, (GLuint, GLsizei, GLsizeiP, GLuintP))
+BGL_Wrap(GetAttribLocation, GLint, (GLuint, GLstring))
+BGL_Wrap(GetProgramInfoLog, void, (GLuint, GLsizei, GLsizeiP, GLcharP))
+BGL_Wrap(GetProgramiv, void, (GLuint, GLenum, GLintP))
+BGL_Wrap(GetShaderInfoLog, void, (GLuint, GLsizei, GLsizeiP, GLcharP))
+BGL_Wrap(GetShaderSource, void, (GLuint, GLsizei, GLsizeiP, GLcharP))
+BGL_Wrap(GetShaderiv, void, (GLuint, GLenum, GLintP))
+BGL_Wrap(GetUniformLocation, GLint, (GLuint, GLstring))
+BGL_Wrap(GetUniformfv, void, (GLuint, GLint, GLfloatP))
+BGL_Wrap(GetUniformiv, void, (GLuint, GLint, GLintP))
+BGL_Wrap(GetVertexAttribPointerv, void, (GLuint, GLenum, GLvoidP))
+BGL_Wrap(GetVertexAttribdv, void, (GLuint, GLenum, GLdoubleP))
+BGL_Wrap(GetVertexAttribfv, void, (GLuint, GLenum, GLfloatP))
+BGL_Wrap(GetVertexAttribiv, void, (GLuint, GLenum, GLintP))
+BGL_Wrap(IsProgram, GLboolean, (GLuint))
+BGL_Wrap(IsShader, GLboolean, (GLuint))
+BGL_Wrap(LinkProgram, void, (GLuint))
+BGL_Wrap(StencilFuncSeparate, void, (GLenum, GLenum, GLint, GLuint))
+BGL_Wrap(StencilMaskSeparate, void, (GLenum, GLuint))
+BGL_Wrap(StencilOpSeparate, void, (GLenum, GLenum, GLenum, GLenum))
+BGL_Wrap(Uniform1f, void, (GLint, GLfloat))
+BGL_Wrap(Uniform1fv, void, (GLint, GLsizei, GLfloatP))
+BGL_Wrap(Uniform1i, void, (GLint, GLint))
+BGL_Wrap(Uniform1iv, void, (GLint, GLsizei, GLintP))
+BGL_Wrap(Uniform2f, void, (GLint, GLfloat, GLfloat))
+BGL_Wrap(Uniform2fv, void, (GLint, GLsizei, GLfloatP))
+BGL_Wrap(Uniform2i, void, (GLint, GLint, GLint))
+BGL_Wrap(Uniform2iv, void, (GLint, GLsizei, GLintP))
+BGL_Wrap(Uniform3f, void, (GLint, GLfloat, GLfloat, GLfloat))
+BGL_Wrap(Uniform3fv, void, (GLint, GLsizei, GLfloatP))
+BGL_Wrap(Uniform3i, void, (GLint, GLint, GLint, GLint))
+BGL_Wrap(Uniform3iv, void, (GLint, GLsizei, GLintP))
+BGL_Wrap(Uniform4f, void, (GLint, GLfloat, GLfloat, GLfloat, GLfloat))
+BGL_Wrap(Uniform4fv, void, (GLint, GLsizei, GLfloatP))
+BGL_Wrap(Uniform4i, void, (GLint, GLint, GLint, GLint, GLint))
+BGL_Wrap(Uniform4iv, void, (GLint, GLsizei, GLintP))
+BGL_Wrap(UniformMatrix2fv, void, (GLint, GLsizei, GLboolean, GLfloatP))
+BGL_Wrap(UniformMatrix3fv, void, (GLint, GLsizei, GLboolean, GLfloatP))
+BGL_Wrap(UniformMatrix4fv, void, (GLint, GLsizei, GLboolean, GLfloatP))
+BGL_Wrap(UseProgram, void, (GLuint))
+BGL_Wrap(ValidateProgram, void, (GLuint))
+BGL_Wrap(VertexAttrib1d, void, (GLuint, GLdouble))
+BGL_Wrap(VertexAttrib1dv, void, (GLuint, GLdoubleP))
+BGL_Wrap(VertexAttrib1f, void, (GLuint, GLfloat))
+BGL_Wrap(VertexAttrib1fv, void, (GLuint, GLfloatP))
+BGL_Wrap(VertexAttrib1s, void, (GLuint, GLshort))
+BGL_Wrap(VertexAttrib1sv, void, (GLuint, GLshortP))
+BGL_Wrap(VertexAttrib2d, void, (GLuint, GLdouble, GLdouble))
+BGL_Wrap(VertexAttrib2dv, void, (GLuint, GLdoubleP))
+BGL_Wrap(VertexAttrib2f, void, (GLuint, GLfloat, GLfloat))
+BGL_Wrap(VertexAttrib2fv, void, (GLuint, GLfloatP))
+BGL_Wrap(VertexAttrib2s, void, (GLuint, GLshort, GLshort))
+BGL_Wrap(VertexAttrib2sv, void, (GLuint, GLshortP))
+BGL_Wrap(VertexAttrib3d, void, (GLuint, GLdouble, GLdouble, GLdouble))
+BGL_Wrap(VertexAttrib3dv, void, (GLuint, GLdoubleP))
+BGL_Wrap(VertexAttrib3f, void, (GLuint, GLfloat, GLfloat, GLfloat))
+BGL_Wrap(VertexAttrib3fv, void, (GLuint, GLfloatP))
+BGL_Wrap(VertexAttrib3s, void, (GLuint, GLshort, GLshort, GLshort))
+BGL_Wrap(VertexAttrib3sv, void, (GLuint, GLshortP))
+BGL_Wrap(VertexAttrib4Nbv, void, (GLuint, GLbyteP))
+BGL_Wrap(VertexAttrib4Niv, void, (GLuint, GLintP))
+BGL_Wrap(VertexAttrib4Nsv, void, (GLuint, GLshortP))
+BGL_Wrap(VertexAttrib4Nub, void, (GLuint, GLubyte, GLubyte, GLubyte, GLubyte))
+BGL_Wrap(VertexAttrib4Nubv, void, (GLuint, GLubyteP))
+BGL_Wrap(VertexAttrib4Nuiv, void, (GLuint, GLuintP))
+BGL_Wrap(VertexAttrib4Nusv, void, (GLuint, GLushortP))
+BGL_Wrap(VertexAttrib4bv, void, (GLuint, GLbyteP))
+BGL_Wrap(VertexAttrib4d, void, (GLuint, GLdouble, GLdouble, GLdouble, GLdouble))
+BGL_Wrap(VertexAttrib4dv, void, (GLuint, GLdoubleP))
+BGL_Wrap(VertexAttrib4f, void, (GLuint, GLfloat, GLfloat, GLfloat, GLfloat))
+BGL_Wrap(VertexAttrib4fv, void, (GLuint, GLfloatP))
+BGL_Wrap(VertexAttrib4iv, void, (GLuint, GLintP))
+BGL_Wrap(VertexAttrib4s, void, (GLuint, GLshort, GLshort, GLshort, GLshort))
+BGL_Wrap(VertexAttrib4sv, void, (GLuint, GLshortP))
+BGL_Wrap(VertexAttrib4ubv, void, (GLuint, GLubyteP))
+BGL_Wrap(VertexAttrib4uiv, void, (GLuint, GLuintP))
+BGL_Wrap(VertexAttrib4usv, void, (GLuint, GLushortP))
+BGL_Wrap(VertexAttribPointer, void, (GLuint, GLint, GLenum, GLboolean, GLsizei, GLvoidP))
+
+
+/* GL_VERSION_2_1 */
+BGL_Wrap(UniformMatrix2x3fv, void, (GLint, GLsizei, GLboolean, GLfloatP))
+BGL_Wrap(UniformMatrix2x4fv, void, (GLint, GLsizei, GLboolean, GLfloatP))
+BGL_Wrap(UniformMatrix3x2fv, void, (GLint, GLsizei, GLboolean, GLfloatP))
+BGL_Wrap(UniformMatrix3x4fv, void, (GLint, GLsizei, GLboolean, GLfloatP))
+BGL_Wrap(UniformMatrix4x2fv, void, (GLint, GLsizei, GLboolean, GLfloatP))
+BGL_Wrap(UniformMatrix4x3fv, void, (GLint, GLsizei, GLboolean, GLfloatP))
+
+
+/* GL_VERSION_3_0 */
+BGL_Wrap(BindVertexArray, void, (GLuint))
+BGL_Wrap(DeleteVertexArrays, void, (GLsizei, GLuintP))
+BGL_Wrap(GenVertexArrays, void, (GLsizei, GLuintP))
+BGL_Wrap(IsVertexArray, GLboolean, (GLuint))
+
+
+/* GL_VERSION_3_1 */
+BGL_Wrap(BindBufferBase, void, (GLenum, GLuint, GLuint))
+BGL_Wrap(BindBufferRange, void, (GLenum, GLuint, GLuint, GLintptr, GLsizeiptr))
+BGL_Wrap(GetActiveUniformBlockName, void, (GLuint, GLuint, GLsizei, GLsizeiP, GLcharP))
+BGL_Wrap(GetActiveUniformBlockiv, void, (GLuint, GLuint, GLenum, GLintP))
+BGL_Wrap(GetActiveUniformName, void, (GLuint, GLuint, GLsizei, GLsizeiP, GLcharP))
+BGL_Wrap(GetActiveUniformsiv, void, (GLuint, GLsizei, GLuintP, GLenum, GLintP))
+BGL_Wrap(GetIntegeri_v, void, (GLenum, GLuint, GLintP))
+BGL_Wrap(GetUniformBlockIndex, GLuint, (GLuint, GLstring))
+BGL_Wrap(GetUniformIndices, void, (GLuint, GLsizei, GLcharP, GLuintP))
+BGL_Wrap(UniformBlockBinding, void, (GLuint, GLuint, GLuint))
+
+
+/* GL_VERSION_3_2 */
+BGL_Wrap(FramebufferTexture, void, (GLenum, GLenum, GLuint, GLint))
+BGL_Wrap(GetBufferParameteri64v, void, (GLenum, GLenum, GLint64P))
+BGL_Wrap(GetInteger64i_v, void, (GLenum, GLuint, GLint64P))
+BGL_Wrap(GetMultisamplefv, void, (GLenum, GLuint, GLfloatP))
+BGL_Wrap(SampleMaski, void, (GLuint, GLbitfield))
+BGL_Wrap(TexImage2DMultisample, void, (GLenum, GLsizei, GLenum, GLsizei, GLsizei, GLboolean))
+BGL_Wrap(TexImage3DMultisample, void, (GLenum, GLsizei, GLenum, GLsizei, GLsizei, GLsizei, GLboolean))
+
+
+/* GL_VERSION_3_3 */
+BGL_Wrap(ColorP3ui, void, (GLenum, GLuint))
+BGL_Wrap(ColorP3uiv, void, (GLenum, GLuintP))
+BGL_Wrap(ColorP4ui, void, (GLenum, GLuint))
+BGL_Wrap(ColorP4uiv, void, (GLenum, GLuintP))
+BGL_Wrap(MultiTexCoordP1ui, void, (GLenum, GLenum, GLuint))
+BGL_Wrap(MultiTexCoordP1uiv, void, (GLenum, GLenum, GLuintP))
+BGL_Wrap(MultiTexCoordP2ui, void, (GLenum, GLenum, GLuint))
+BGL_Wrap(MultiTexCoordP2uiv, void, (GLenum, GLenum, GLuintP))
+BGL_Wrap(MultiTexCoordP3ui, void, (GLenum, GLenum, GLuint))
+BGL_Wrap(MultiTexCoordP3uiv, void, (GLenum, GLenum, GLuintP))
+BGL_Wrap(MultiTexCoordP4ui, void, (GLenum, GLenum, GLuint))
+BGL_Wrap(MultiTexCoordP4uiv, void, (GLenum, GLenum, GLuintP))
+BGL_Wrap(NormalP3ui, void, (GLenum, GLuint))
+BGL_Wrap(NormalP3uiv, void, (GLenum, GLuintP))
+BGL_Wrap(SecondaryColorP3ui, void, (GLenum, GLuint))
+BGL_Wrap(SecondaryColorP3uiv, void, (GLenum, GLuintP))
+BGL_Wrap(TexCoordP1ui, void, (GLenum, GLuint))
+BGL_Wrap(TexCoordP1uiv, void, (GLenum, GLuintP))
+BGL_Wrap(TexCoordP2ui, void, (GLenum, GLuint))
+BGL_Wrap(TexCoordP2uiv, void, (GLenum, GLuintP))
+BGL_Wrap(TexCoordP3ui, void, (GLenum, GLuint))
+BGL_Wrap(TexCoordP3uiv, void, (GLenum, GLuintP))
+BGL_Wrap(TexCoordP4ui, void, (GLenum, GLuint))
+BGL_Wrap(TexCoordP4uiv, void, (GLenum, GLuintP))
+BGL_Wrap(VertexP2ui, void, (GLenum, GLuint))
+BGL_Wrap(VertexP2uiv, void, (GLenum, GLuintP))
+BGL_Wrap(VertexP3ui, void, (GLenum, GLuint))
+BGL_Wrap(VertexP3uiv, void, (GLenum, GLuintP))
+BGL_Wrap(VertexP4ui, void, (GLenum, GLuint))
+BGL_Wrap(VertexP4uiv, void, (GLenum, GLuintP))
+
+
+BGLU_Wrap(Perspective, void, (GLdouble, GLdouble, GLdouble, GLdouble))
+BGLU_Wrap(LookAt, void, (GLdouble, GLdouble, GLdouble, GLdouble, GLdouble, GLdouble, GLdouble, GLdouble, GLdouble))
+BGLU_Wrap(Ortho2D, void, (GLdouble, GLdouble, GLdouble, GLdouble))
+BGLU_Wrap(PickMatrix, void, (GLdouble, GLdouble, GLdouble, GLdouble, GLintP))
+BGLU_Wrap(Project, GLint, (GLdouble, GLdouble, GLdouble, GLdoubleP, GLdoubleP, GLintP, GLdoubleP, GLdoubleP, GLdoubleP))
+BGLU_Wrap(UnProject, GLint, (GLdouble, GLdouble, GLdouble, GLdoubleP, GLdoubleP, GLintP, GLdoubleP, GLdoubleP, GLdoubleP))
+
+/** \} */
+
+
+/* -------------------------------------------------------------------- */
+
+/** \name Module Definition
+ * \{ */
+
+#define MethodDefu(func) {"glu"#func, Method_##func, METH_VARARGS, NULL}
+
+static struct PyMethodDef BGL_methods[] = {
MethodDefu(Perspective),
MethodDefu(LookAt),
MethodDefu(Ortho2D),
MethodDefu(PickMatrix),
MethodDefu(Project),
MethodDefu(UnProject),
-/* #endif */
{NULL, NULL, 0, NULL}
};
+#undef MethodDefu
+
static struct PyModuleDef BGL_module_def = {
PyModuleDef_HEAD_INIT,
"bgl", /* m_name */
@@ -1381,13 +1660,36 @@ static struct PyModuleDef BGL_module_def = {
NULL, /* m_free */
};
-static void expp_addconst_int(PyObject *dict, const char *name, int value)
+static void py_module_dict_add_int(PyObject *dict, const char *name, int value)
{
PyObject *item;
PyDict_SetItemString(dict, name, item = PyLong_FromLong(value));
Py_DECREF(item);
}
+static void py_module_dict_add_int64(PyObject *dict, const char *name, int64_t value)
+{
+ PyObject *item;
+ PyDict_SetItemString(dict, name, item = PyLong_FromLongLong(value));
+ Py_DECREF(item);
+}
+
+static void py_module_dict_add_method(PyObject *submodule, PyObject *dict, PyMethodDef *method_def, bool is_valid)
+{
+ if (is_valid) {
+ PyObject *m;
+ m = PyCFunction_NewEx(method_def, NULL, submodule);
+ PyDict_SetItemString(dict, method_def->ml_name, m);
+ Py_DECREF(m);
+ }
+ else {
+ PyDict_SetItemString(dict, method_def->ml_name, Py_None);
+ }
+}
+
+/* TODO, expose to users */
+static bool use_deprecated = true;
+
PyObject *BPyInit_bgl(void)
{
PyObject *submodule, *dict;
@@ -1400,517 +1702,1971 @@ PyObject *BPyInit_bgl(void)
PyModule_AddObject(submodule, "Buffer", (PyObject *)&BGL_bufferType);
Py_INCREF((PyObject *)&BGL_bufferType);
-#define EXPP_ADDCONST(x) expp_addconst_int(dict, #x, x)
-
- EXPP_ADDCONST(GL_CURRENT_BIT);
- EXPP_ADDCONST(GL_POINT_BIT);
- EXPP_ADDCONST(GL_LINE_BIT);
- EXPP_ADDCONST(GL_POLYGON_BIT);
- EXPP_ADDCONST(GL_POLYGON_STIPPLE_BIT);
- EXPP_ADDCONST(GL_PIXEL_MODE_BIT);
- EXPP_ADDCONST(GL_LIGHTING_BIT);
- EXPP_ADDCONST(GL_FOG_BIT);
- EXPP_ADDCONST(GL_DEPTH_BUFFER_BIT);
- EXPP_ADDCONST(GL_ACCUM_BUFFER_BIT);
- EXPP_ADDCONST(GL_STENCIL_BUFFER_BIT);
- EXPP_ADDCONST(GL_VIEWPORT_BIT);
- EXPP_ADDCONST(GL_TRANSFORM_BIT);
- EXPP_ADDCONST(GL_ENABLE_BIT);
- EXPP_ADDCONST(GL_COLOR_BUFFER_BIT);
- EXPP_ADDCONST(GL_HINT_BIT);
- EXPP_ADDCONST(GL_EVAL_BIT);
- EXPP_ADDCONST(GL_LIST_BIT);
- EXPP_ADDCONST(GL_TEXTURE_BIT);
- EXPP_ADDCONST(GL_SCISSOR_BIT);
- EXPP_ADDCONST(GL_ALL_ATTRIB_BITS);
- EXPP_ADDCONST(GL_CLIENT_ALL_ATTRIB_BITS);
-
- EXPP_ADDCONST(GL_FALSE);
- EXPP_ADDCONST(GL_TRUE);
-
- EXPP_ADDCONST(GL_POINTS);
- EXPP_ADDCONST(GL_LINES);
- EXPP_ADDCONST(GL_LINE_LOOP);
- EXPP_ADDCONST(GL_LINE_STRIP);
- EXPP_ADDCONST(GL_TRIANGLES);
- EXPP_ADDCONST(GL_TRIANGLE_STRIP);
- EXPP_ADDCONST(GL_TRIANGLE_FAN);
- EXPP_ADDCONST(GL_QUADS);
- EXPP_ADDCONST(GL_QUAD_STRIP);
- EXPP_ADDCONST(GL_POLYGON);
-
- EXPP_ADDCONST(GL_ACCUM);
- EXPP_ADDCONST(GL_LOAD);
- EXPP_ADDCONST(GL_RETURN);
- EXPP_ADDCONST(GL_MULT);
- EXPP_ADDCONST(GL_ADD);
-
- EXPP_ADDCONST(GL_NEVER);
- EXPP_ADDCONST(GL_LESS);
- EXPP_ADDCONST(GL_EQUAL);
- EXPP_ADDCONST(GL_LEQUAL);
- EXPP_ADDCONST(GL_GREATER);
- EXPP_ADDCONST(GL_NOTEQUAL);
- EXPP_ADDCONST(GL_GEQUAL);
- EXPP_ADDCONST(GL_ALWAYS);
-
- EXPP_ADDCONST(GL_ZERO);
- EXPP_ADDCONST(GL_ONE);
- EXPP_ADDCONST(GL_SRC_COLOR);
- EXPP_ADDCONST(GL_ONE_MINUS_SRC_COLOR);
- EXPP_ADDCONST(GL_SRC_ALPHA);
- EXPP_ADDCONST(GL_ONE_MINUS_SRC_ALPHA);
- EXPP_ADDCONST(GL_DST_ALPHA);
- EXPP_ADDCONST(GL_ONE_MINUS_DST_ALPHA);
-
- EXPP_ADDCONST(GL_DST_COLOR);
- EXPP_ADDCONST(GL_ONE_MINUS_DST_COLOR);
- EXPP_ADDCONST(GL_SRC_ALPHA_SATURATE);
-
- EXPP_ADDCONST(GL_NONE);
- EXPP_ADDCONST(GL_FRONT_LEFT);
- EXPP_ADDCONST(GL_FRONT_RIGHT);
- EXPP_ADDCONST(GL_BACK_LEFT);
- EXPP_ADDCONST(GL_BACK_RIGHT);
- EXPP_ADDCONST(GL_FRONT);
- EXPP_ADDCONST(GL_BACK);
- EXPP_ADDCONST(GL_LEFT);
- EXPP_ADDCONST(GL_RIGHT);
- EXPP_ADDCONST(GL_FRONT_AND_BACK);
- EXPP_ADDCONST(GL_AUX0);
- EXPP_ADDCONST(GL_AUX1);
- EXPP_ADDCONST(GL_AUX2);
- EXPP_ADDCONST(GL_AUX3);
-
- EXPP_ADDCONST(GL_NO_ERROR);
- EXPP_ADDCONST(GL_INVALID_ENUM);
- EXPP_ADDCONST(GL_INVALID_VALUE);
- EXPP_ADDCONST(GL_INVALID_OPERATION);
- EXPP_ADDCONST(GL_STACK_OVERFLOW);
- EXPP_ADDCONST(GL_STACK_UNDERFLOW);
- EXPP_ADDCONST(GL_OUT_OF_MEMORY);
-
- EXPP_ADDCONST(GL_2D);
- EXPP_ADDCONST(GL_3D);
- EXPP_ADDCONST(GL_3D_COLOR);
- EXPP_ADDCONST(GL_3D_COLOR_TEXTURE);
- EXPP_ADDCONST(GL_4D_COLOR_TEXTURE);
-
- EXPP_ADDCONST(GL_PASS_THROUGH_TOKEN);
- EXPP_ADDCONST(GL_POINT_TOKEN);
- EXPP_ADDCONST(GL_LINE_TOKEN);
- EXPP_ADDCONST(GL_POLYGON_TOKEN);
- EXPP_ADDCONST(GL_BITMAP_TOKEN);
- EXPP_ADDCONST(GL_DRAW_PIXEL_TOKEN);
- EXPP_ADDCONST(GL_COPY_PIXEL_TOKEN);
- EXPP_ADDCONST(GL_LINE_RESET_TOKEN);
-
- EXPP_ADDCONST(GL_EXP);
- EXPP_ADDCONST(GL_EXP2);
-
- EXPP_ADDCONST(GL_CW);
- EXPP_ADDCONST(GL_CCW);
-
- EXPP_ADDCONST(GL_COEFF);
- EXPP_ADDCONST(GL_ORDER);
- EXPP_ADDCONST(GL_DOMAIN);
-
- EXPP_ADDCONST(GL_PIXEL_MAP_I_TO_I);
- EXPP_ADDCONST(GL_PIXEL_MAP_S_TO_S);
- EXPP_ADDCONST(GL_PIXEL_MAP_I_TO_R);
- EXPP_ADDCONST(GL_PIXEL_MAP_I_TO_G);
- EXPP_ADDCONST(GL_PIXEL_MAP_I_TO_B);
- EXPP_ADDCONST(GL_PIXEL_MAP_I_TO_A);
- EXPP_ADDCONST(GL_PIXEL_MAP_R_TO_R);
- EXPP_ADDCONST(GL_PIXEL_MAP_G_TO_G);
- EXPP_ADDCONST(GL_PIXEL_MAP_B_TO_B);
- EXPP_ADDCONST(GL_PIXEL_MAP_A_TO_A);
-
- EXPP_ADDCONST(GL_CURRENT_COLOR);
- EXPP_ADDCONST(GL_CURRENT_INDEX);
- EXPP_ADDCONST(GL_CURRENT_NORMAL);
- EXPP_ADDCONST(GL_CURRENT_TEXTURE_COORDS);
- EXPP_ADDCONST(GL_CURRENT_RASTER_COLOR);
- EXPP_ADDCONST(GL_CURRENT_RASTER_INDEX);
- EXPP_ADDCONST(GL_CURRENT_RASTER_TEXTURE_COORDS);
- EXPP_ADDCONST(GL_CURRENT_RASTER_POSITION);
- EXPP_ADDCONST(GL_CURRENT_RASTER_POSITION_VALID);
- EXPP_ADDCONST(GL_CURRENT_RASTER_DISTANCE);
- EXPP_ADDCONST(GL_POINT_SMOOTH);
- EXPP_ADDCONST(GL_POINT_SIZE);
- EXPP_ADDCONST(GL_POINT_SIZE_RANGE);
- EXPP_ADDCONST(GL_POINT_SIZE_GRANULARITY);
- EXPP_ADDCONST(GL_LINE_SMOOTH);
- EXPP_ADDCONST(GL_LINE_WIDTH);
- EXPP_ADDCONST(GL_LINE_WIDTH_RANGE);
- EXPP_ADDCONST(GL_LINE_WIDTH_GRANULARITY);
- EXPP_ADDCONST(GL_LINE_STIPPLE);
- EXPP_ADDCONST(GL_LINE_STIPPLE_PATTERN);
- EXPP_ADDCONST(GL_LINE_STIPPLE_REPEAT);
- EXPP_ADDCONST(GL_LIST_MODE);
- EXPP_ADDCONST(GL_MAX_LIST_NESTING);
- EXPP_ADDCONST(GL_LIST_BASE);
- EXPP_ADDCONST(GL_LIST_INDEX);
- EXPP_ADDCONST(GL_POLYGON_MODE);
- EXPP_ADDCONST(GL_POLYGON_SMOOTH);
- EXPP_ADDCONST(GL_POLYGON_STIPPLE);
- EXPP_ADDCONST(GL_EDGE_FLAG);
- EXPP_ADDCONST(GL_CULL_FACE);
- EXPP_ADDCONST(GL_CULL_FACE_MODE);
- EXPP_ADDCONST(GL_FRONT_FACE);
- EXPP_ADDCONST(GL_LIGHTING);
- EXPP_ADDCONST(GL_LIGHT_MODEL_LOCAL_VIEWER);
- EXPP_ADDCONST(GL_LIGHT_MODEL_TWO_SIDE);
- EXPP_ADDCONST(GL_LIGHT_MODEL_AMBIENT);
- EXPP_ADDCONST(GL_SHADE_MODEL);
- EXPP_ADDCONST(GL_COLOR_MATERIAL_FACE);
- EXPP_ADDCONST(GL_COLOR_MATERIAL_PARAMETER);
- EXPP_ADDCONST(GL_COLOR_MATERIAL);
- EXPP_ADDCONST(GL_FOG);
- EXPP_ADDCONST(GL_FOG_INDEX);
- EXPP_ADDCONST(GL_FOG_DENSITY);
- EXPP_ADDCONST(GL_FOG_START);
- EXPP_ADDCONST(GL_FOG_END);
- EXPP_ADDCONST(GL_FOG_MODE);
- EXPP_ADDCONST(GL_FOG_COLOR);
- EXPP_ADDCONST(GL_DEPTH_RANGE);
- EXPP_ADDCONST(GL_DEPTH_TEST);
- EXPP_ADDCONST(GL_DEPTH_WRITEMASK);
- EXPP_ADDCONST(GL_DEPTH_CLEAR_VALUE);
- EXPP_ADDCONST(GL_DEPTH_FUNC);
- EXPP_ADDCONST(GL_ACCUM_CLEAR_VALUE);
- EXPP_ADDCONST(GL_STENCIL_TEST);
- EXPP_ADDCONST(GL_STENCIL_CLEAR_VALUE);
- EXPP_ADDCONST(GL_STENCIL_FUNC);
- EXPP_ADDCONST(GL_STENCIL_VALUE_MASK);
- EXPP_ADDCONST(GL_STENCIL_FAIL);
- EXPP_ADDCONST(GL_STENCIL_PASS_DEPTH_FAIL);
- EXPP_ADDCONST(GL_STENCIL_PASS_DEPTH_PASS);
- EXPP_ADDCONST(GL_STENCIL_REF);
- EXPP_ADDCONST(GL_STENCIL_WRITEMASK);
- EXPP_ADDCONST(GL_MATRIX_MODE);
- EXPP_ADDCONST(GL_NORMALIZE);
- EXPP_ADDCONST(GL_VIEWPORT);
- EXPP_ADDCONST(GL_MODELVIEW_STACK_DEPTH);
- EXPP_ADDCONST(GL_PROJECTION_STACK_DEPTH);
- EXPP_ADDCONST(GL_TEXTURE_STACK_DEPTH);
- EXPP_ADDCONST(GL_MODELVIEW_MATRIX);
- EXPP_ADDCONST(GL_PROJECTION_MATRIX);
- EXPP_ADDCONST(GL_TEXTURE_MATRIX);
- EXPP_ADDCONST(GL_ATTRIB_STACK_DEPTH);
- EXPP_ADDCONST(GL_ALPHA_TEST);
- EXPP_ADDCONST(GL_ALPHA_TEST_FUNC);
- EXPP_ADDCONST(GL_ALPHA_TEST_REF);
- EXPP_ADDCONST(GL_DITHER);
- EXPP_ADDCONST(GL_BLEND_DST);
- EXPP_ADDCONST(GL_BLEND_SRC);
- EXPP_ADDCONST(GL_BLEND);
- EXPP_ADDCONST(GL_LOGIC_OP_MODE);
- EXPP_ADDCONST(GL_LOGIC_OP);
- EXPP_ADDCONST(GL_AUX_BUFFERS);
- EXPP_ADDCONST(GL_DRAW_BUFFER);
- EXPP_ADDCONST(GL_READ_BUFFER);
- EXPP_ADDCONST(GL_SCISSOR_BOX);
- EXPP_ADDCONST(GL_SCISSOR_TEST);
- EXPP_ADDCONST(GL_INDEX_CLEAR_VALUE);
- EXPP_ADDCONST(GL_INDEX_WRITEMASK);
- EXPP_ADDCONST(GL_COLOR_CLEAR_VALUE);
- EXPP_ADDCONST(GL_COLOR_WRITEMASK);
- EXPP_ADDCONST(GL_INDEX_MODE);
- EXPP_ADDCONST(GL_RGBA_MODE);
- EXPP_ADDCONST(GL_DOUBLEBUFFER);
- EXPP_ADDCONST(GL_STEREO);
- EXPP_ADDCONST(GL_RENDER_MODE);
- EXPP_ADDCONST(GL_PERSPECTIVE_CORRECTION_HINT);
- EXPP_ADDCONST(GL_POINT_SMOOTH_HINT);
- EXPP_ADDCONST(GL_LINE_SMOOTH_HINT);
- EXPP_ADDCONST(GL_POLYGON_SMOOTH_HINT);
- EXPP_ADDCONST(GL_FOG_HINT);
- EXPP_ADDCONST(GL_TEXTURE_GEN_S);
- EXPP_ADDCONST(GL_TEXTURE_GEN_T);
- EXPP_ADDCONST(GL_TEXTURE_GEN_R);
- EXPP_ADDCONST(GL_TEXTURE_GEN_Q);
- EXPP_ADDCONST(GL_PIXEL_MAP_I_TO_I_SIZE);
- EXPP_ADDCONST(GL_PIXEL_MAP_S_TO_S_SIZE);
- EXPP_ADDCONST(GL_PIXEL_MAP_I_TO_R_SIZE);
- EXPP_ADDCONST(GL_PIXEL_MAP_I_TO_G_SIZE);
- EXPP_ADDCONST(GL_PIXEL_MAP_I_TO_B_SIZE);
- EXPP_ADDCONST(GL_PIXEL_MAP_I_TO_A_SIZE);
- EXPP_ADDCONST(GL_PIXEL_MAP_R_TO_R_SIZE);
- EXPP_ADDCONST(GL_PIXEL_MAP_G_TO_G_SIZE);
- EXPP_ADDCONST(GL_PIXEL_MAP_B_TO_B_SIZE);
- EXPP_ADDCONST(GL_PIXEL_MAP_A_TO_A_SIZE);
- EXPP_ADDCONST(GL_UNPACK_SWAP_BYTES);
- EXPP_ADDCONST(GL_UNPACK_LSB_FIRST);
- EXPP_ADDCONST(GL_UNPACK_ROW_LENGTH);
- EXPP_ADDCONST(GL_UNPACK_SKIP_ROWS);
- EXPP_ADDCONST(GL_UNPACK_SKIP_PIXELS);
- EXPP_ADDCONST(GL_UNPACK_ALIGNMENT);
- EXPP_ADDCONST(GL_PACK_SWAP_BYTES);
- EXPP_ADDCONST(GL_PACK_LSB_FIRST);
- EXPP_ADDCONST(GL_PACK_ROW_LENGTH);
- EXPP_ADDCONST(GL_PACK_SKIP_ROWS);
- EXPP_ADDCONST(GL_PACK_SKIP_PIXELS);
- EXPP_ADDCONST(GL_PACK_ALIGNMENT);
- EXPP_ADDCONST(GL_MAP_COLOR);
- EXPP_ADDCONST(GL_MAP_STENCIL);
- EXPP_ADDCONST(GL_INDEX_SHIFT);
- EXPP_ADDCONST(GL_INDEX_OFFSET);
- EXPP_ADDCONST(GL_RED_SCALE);
- EXPP_ADDCONST(GL_RED_BIAS);
- EXPP_ADDCONST(GL_ZOOM_X);
- EXPP_ADDCONST(GL_ZOOM_Y);
- EXPP_ADDCONST(GL_GREEN_SCALE);
- EXPP_ADDCONST(GL_GREEN_BIAS);
- EXPP_ADDCONST(GL_BLUE_SCALE);
- EXPP_ADDCONST(GL_BLUE_BIAS);
- EXPP_ADDCONST(GL_ALPHA_SCALE);
- EXPP_ADDCONST(GL_ALPHA_BIAS);
- EXPP_ADDCONST(GL_DEPTH_SCALE);
- EXPP_ADDCONST(GL_DEPTH_BIAS);
- EXPP_ADDCONST(GL_MAX_EVAL_ORDER);
- EXPP_ADDCONST(GL_MAX_LIGHTS);
- EXPP_ADDCONST(GL_MAX_CLIP_PLANES);
- EXPP_ADDCONST(GL_MAX_TEXTURE_SIZE);
- EXPP_ADDCONST(GL_MAX_PIXEL_MAP_TABLE);
- EXPP_ADDCONST(GL_MAX_ATTRIB_STACK_DEPTH);
- EXPP_ADDCONST(GL_MAX_MODELVIEW_STACK_DEPTH);
- EXPP_ADDCONST(GL_MAX_NAME_STACK_DEPTH);
- EXPP_ADDCONST(GL_MAX_PROJECTION_STACK_DEPTH);
- EXPP_ADDCONST(GL_MAX_TEXTURE_STACK_DEPTH);
- EXPP_ADDCONST(GL_MAX_VIEWPORT_DIMS);
- EXPP_ADDCONST(GL_SUBPIXEL_BITS);
- EXPP_ADDCONST(GL_INDEX_BITS);
- EXPP_ADDCONST(GL_RED_BITS);
- EXPP_ADDCONST(GL_GREEN_BITS);
- EXPP_ADDCONST(GL_BLUE_BITS);
- EXPP_ADDCONST(GL_ALPHA_BITS);
- EXPP_ADDCONST(GL_DEPTH_BITS);
- EXPP_ADDCONST(GL_STENCIL_BITS);
- EXPP_ADDCONST(GL_ACCUM_RED_BITS);
- EXPP_ADDCONST(GL_ACCUM_GREEN_BITS);
- EXPP_ADDCONST(GL_ACCUM_BLUE_BITS);
- EXPP_ADDCONST(GL_ACCUM_ALPHA_BITS);
- EXPP_ADDCONST(GL_NAME_STACK_DEPTH);
- EXPP_ADDCONST(GL_AUTO_NORMAL);
- EXPP_ADDCONST(GL_MAP1_COLOR_4);
- EXPP_ADDCONST(GL_MAP1_INDEX);
- EXPP_ADDCONST(GL_MAP1_NORMAL);
- EXPP_ADDCONST(GL_MAP1_TEXTURE_COORD_1);
- EXPP_ADDCONST(GL_MAP1_TEXTURE_COORD_2);
- EXPP_ADDCONST(GL_MAP1_TEXTURE_COORD_3);
- EXPP_ADDCONST(GL_MAP1_TEXTURE_COORD_4);
- EXPP_ADDCONST(GL_MAP1_VERTEX_3);
- EXPP_ADDCONST(GL_MAP1_VERTEX_4);
- EXPP_ADDCONST(GL_MAP2_COLOR_4);
- EXPP_ADDCONST(GL_MAP2_INDEX);
- EXPP_ADDCONST(GL_MAP2_NORMAL);
- EXPP_ADDCONST(GL_MAP2_TEXTURE_COORD_1);
- EXPP_ADDCONST(GL_MAP2_TEXTURE_COORD_2);
- EXPP_ADDCONST(GL_MAP2_TEXTURE_COORD_3);
- EXPP_ADDCONST(GL_MAP2_TEXTURE_COORD_4);
- EXPP_ADDCONST(GL_MAP2_VERTEX_3);
- EXPP_ADDCONST(GL_MAP2_VERTEX_4);
- EXPP_ADDCONST(GL_MAP1_GRID_DOMAIN);
- EXPP_ADDCONST(GL_MAP1_GRID_SEGMENTS);
- EXPP_ADDCONST(GL_MAP2_GRID_DOMAIN);
- EXPP_ADDCONST(GL_MAP2_GRID_SEGMENTS);
- EXPP_ADDCONST(GL_TEXTURE_1D);
- EXPP_ADDCONST(GL_TEXTURE_2D);
-
- EXPP_ADDCONST(GL_TEXTURE_WIDTH);
- EXPP_ADDCONST(GL_TEXTURE_HEIGHT);
- EXPP_ADDCONST(GL_TEXTURE_COMPONENTS);
- EXPP_ADDCONST(GL_TEXTURE_BORDER_COLOR);
- EXPP_ADDCONST(GL_TEXTURE_BORDER);
-
- EXPP_ADDCONST(GL_DONT_CARE);
- EXPP_ADDCONST(GL_FASTEST);
- EXPP_ADDCONST(GL_NICEST);
-
- EXPP_ADDCONST(GL_AMBIENT);
- EXPP_ADDCONST(GL_DIFFUSE);
- EXPP_ADDCONST(GL_SPECULAR);
- EXPP_ADDCONST(GL_POSITION);
- EXPP_ADDCONST(GL_SPOT_DIRECTION);
- EXPP_ADDCONST(GL_SPOT_EXPONENT);
- EXPP_ADDCONST(GL_SPOT_CUTOFF);
- EXPP_ADDCONST(GL_CONSTANT_ATTENUATION);
- EXPP_ADDCONST(GL_LINEAR_ATTENUATION);
- EXPP_ADDCONST(GL_QUADRATIC_ATTENUATION);
-
- EXPP_ADDCONST(GL_COMPILE);
- EXPP_ADDCONST(GL_COMPILE_AND_EXECUTE);
-
- EXPP_ADDCONST(GL_BYTE);
- EXPP_ADDCONST(GL_UNSIGNED_BYTE);
- EXPP_ADDCONST(GL_SHORT);
- EXPP_ADDCONST(GL_UNSIGNED_SHORT);
- EXPP_ADDCONST(GL_INT);
- EXPP_ADDCONST(GL_UNSIGNED_INT);
- EXPP_ADDCONST(GL_FLOAT);
- EXPP_ADDCONST(GL_DOUBLE);
- EXPP_ADDCONST(GL_2_BYTES);
- EXPP_ADDCONST(GL_3_BYTES);
- EXPP_ADDCONST(GL_4_BYTES);
-
- EXPP_ADDCONST(GL_CLEAR);
- EXPP_ADDCONST(GL_AND);
- EXPP_ADDCONST(GL_AND_REVERSE);
- EXPP_ADDCONST(GL_COPY);
- EXPP_ADDCONST(GL_AND_INVERTED);
- EXPP_ADDCONST(GL_NOOP);
- EXPP_ADDCONST(GL_XOR);
- EXPP_ADDCONST(GL_OR);
- EXPP_ADDCONST(GL_NOR);
- EXPP_ADDCONST(GL_EQUIV);
- EXPP_ADDCONST(GL_INVERT);
- EXPP_ADDCONST(GL_OR_REVERSE);
- EXPP_ADDCONST(GL_COPY_INVERTED);
- EXPP_ADDCONST(GL_OR_INVERTED);
- EXPP_ADDCONST(GL_NAND);
- EXPP_ADDCONST(GL_SET);
-
- EXPP_ADDCONST(GL_EMISSION);
- EXPP_ADDCONST(GL_SHININESS);
- EXPP_ADDCONST(GL_AMBIENT_AND_DIFFUSE);
- EXPP_ADDCONST(GL_COLOR_INDEXES);
-
- EXPP_ADDCONST(GL_MODELVIEW);
- EXPP_ADDCONST(GL_PROJECTION);
- EXPP_ADDCONST(GL_TEXTURE);
-
- EXPP_ADDCONST(GL_COLOR);
- EXPP_ADDCONST(GL_DEPTH);
- EXPP_ADDCONST(GL_STENCIL);
-
- EXPP_ADDCONST(GL_COLOR_INDEX);
- EXPP_ADDCONST(GL_STENCIL_INDEX);
- EXPP_ADDCONST(GL_DEPTH_COMPONENT);
- EXPP_ADDCONST(GL_RED);
- EXPP_ADDCONST(GL_GREEN);
- EXPP_ADDCONST(GL_BLUE);
- EXPP_ADDCONST(GL_ALPHA);
- EXPP_ADDCONST(GL_RGB);
- EXPP_ADDCONST(GL_RGBA);
- EXPP_ADDCONST(GL_LUMINANCE);
- EXPP_ADDCONST(GL_LUMINANCE_ALPHA);
-
- EXPP_ADDCONST(GL_BITMAP);
-
- EXPP_ADDCONST(GL_POINT);
- EXPP_ADDCONST(GL_LINE);
- EXPP_ADDCONST(GL_FILL);
-
- EXPP_ADDCONST(GL_RENDER);
- EXPP_ADDCONST(GL_FEEDBACK);
- EXPP_ADDCONST(GL_SELECT);
-
- EXPP_ADDCONST(GL_FLAT);
- EXPP_ADDCONST(GL_SMOOTH);
-
- EXPP_ADDCONST(GL_KEEP);
- EXPP_ADDCONST(GL_REPLACE);
- EXPP_ADDCONST(GL_INCR);
- EXPP_ADDCONST(GL_DECR);
-
- EXPP_ADDCONST(GL_VENDOR);
- EXPP_ADDCONST(GL_RENDERER);
- EXPP_ADDCONST(GL_VERSION);
- EXPP_ADDCONST(GL_EXTENSIONS);
-
- EXPP_ADDCONST(GL_S);
- EXPP_ADDCONST(GL_T);
- EXPP_ADDCONST(GL_R);
- EXPP_ADDCONST(GL_Q);
-
- EXPP_ADDCONST(GL_MODULATE);
- EXPP_ADDCONST(GL_DECAL);
-
- EXPP_ADDCONST(GL_TEXTURE_ENV_MODE);
- EXPP_ADDCONST(GL_TEXTURE_ENV_COLOR);
-
- EXPP_ADDCONST(GL_TEXTURE_ENV);
-
- EXPP_ADDCONST(GL_EYE_LINEAR);
- EXPP_ADDCONST(GL_OBJECT_LINEAR);
- EXPP_ADDCONST(GL_SPHERE_MAP);
-
- EXPP_ADDCONST(GL_TEXTURE_GEN_MODE);
- EXPP_ADDCONST(GL_OBJECT_PLANE);
- EXPP_ADDCONST(GL_EYE_PLANE);
-
- EXPP_ADDCONST(GL_NEAREST);
- EXPP_ADDCONST(GL_LINEAR);
-
- EXPP_ADDCONST(GL_NEAREST_MIPMAP_NEAREST);
- EXPP_ADDCONST(GL_LINEAR_MIPMAP_NEAREST);
- EXPP_ADDCONST(GL_NEAREST_MIPMAP_LINEAR);
- EXPP_ADDCONST(GL_LINEAR_MIPMAP_LINEAR);
-
- EXPP_ADDCONST(GL_TEXTURE_MAG_FILTER);
- EXPP_ADDCONST(GL_TEXTURE_MIN_FILTER);
- EXPP_ADDCONST(GL_TEXTURE_WRAP_S);
- EXPP_ADDCONST(GL_TEXTURE_WRAP_T);
-
- EXPP_ADDCONST(GL_CLAMP);
- EXPP_ADDCONST(GL_REPEAT);
-
- EXPP_ADDCONST(GL_CLIP_PLANE0);
- EXPP_ADDCONST(GL_CLIP_PLANE1);
- EXPP_ADDCONST(GL_CLIP_PLANE2);
- EXPP_ADDCONST(GL_CLIP_PLANE3);
- EXPP_ADDCONST(GL_CLIP_PLANE4);
- EXPP_ADDCONST(GL_CLIP_PLANE5);
-
- EXPP_ADDCONST(GL_LIGHT0);
- EXPP_ADDCONST(GL_LIGHT1);
- EXPP_ADDCONST(GL_LIGHT2);
- EXPP_ADDCONST(GL_LIGHT3);
- EXPP_ADDCONST(GL_LIGHT4);
- EXPP_ADDCONST(GL_LIGHT5);
- EXPP_ADDCONST(GL_LIGHT6);
- EXPP_ADDCONST(GL_LIGHT7);
-
- EXPP_ADDCONST(GL_POLYGON_OFFSET_UNITS);
- EXPP_ADDCONST(GL_POLYGON_OFFSET_POINT);
- EXPP_ADDCONST(GL_POLYGON_OFFSET_LINE);
- EXPP_ADDCONST(GL_POLYGON_OFFSET_FILL);
- EXPP_ADDCONST(GL_POLYGON_OFFSET_FACTOR);
-
- EXPP_ADDCONST(GL_TEXTURE_PRIORITY);
- EXPP_ADDCONST(GL_TEXTURE_RESIDENT);
- EXPP_ADDCONST(GL_TEXTURE_BINDING_1D);
- EXPP_ADDCONST(GL_TEXTURE_BINDING_2D);
-
- EXPP_ADDCONST(GL_VERTEX_SHADER);
- EXPP_ADDCONST(GL_FRAGMENT_SHADER);
- EXPP_ADDCONST(GL_COMPILE_STATUS);
- EXPP_ADDCONST(GL_ACTIVE_TEXTURE);
-
- EXPP_ADDCONST(GL_TEXTURE0);
- EXPP_ADDCONST(GL_TEXTURE1);
- EXPP_ADDCONST(GL_TEXTURE2);
- EXPP_ADDCONST(GL_TEXTURE3);
- EXPP_ADDCONST(GL_TEXTURE4);
- EXPP_ADDCONST(GL_TEXTURE5);
- EXPP_ADDCONST(GL_TEXTURE6);
- EXPP_ADDCONST(GL_TEXTURE7);
- EXPP_ADDCONST(GL_TEXTURE8);
-
- EXPP_ADDCONST(GL_MAX_TEXTURE_UNITS);
-
- EXPP_ADDCONST(GL_DEPTH_COMPONENT32);
- EXPP_ADDCONST(GL_TEXTURE_COMPARE_MODE);
-
- EXPP_ADDCONST(GL_MAX_VARYING_FLOATS);
- EXPP_ADDCONST(GL_MAX_VERTEX_ATTRIBS);
- EXPP_ADDCONST(GL_MAX_VARYING_FLOATS);
- EXPP_ADDCONST(GL_MAX_VERTEX_UNIFORM_COMPONENTS);
- EXPP_ADDCONST(GL_MAX_FRAGMENT_UNIFORM_COMPONENTS);
- EXPP_ADDCONST(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS);
- EXPP_ADDCONST(GL_MAX_TEXTURE_IMAGE_UNITS);
- EXPP_ADDCONST(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS);
+/* needed since some function pointers won't be NULL */
+#ifdef __GNUC__
+# pragma GCC diagnostic ignored "-Waddress"
+#endif
+
+#define PY_MOD_ADD_METHOD(func) \
+ { \
+ static PyMethodDef method_def = {"gl"#func, Method_##func, METH_VARARGS}; \
+ py_module_dict_add_method(submodule, dict, &method_def, (gl##func != NULL)); \
+ } ((void)0)
+
+ /* GL_VERSION_1_0 */
+ {
+ PY_MOD_ADD_METHOD(BlendFunc);
+ PY_MOD_ADD_METHOD(Clear);
+ PY_MOD_ADD_METHOD(ClearColor);
+ PY_MOD_ADD_METHOD(ClearDepth);
+ PY_MOD_ADD_METHOD(ClearStencil);
+ PY_MOD_ADD_METHOD(ColorMask);
+ PY_MOD_ADD_METHOD(CullFace);
+ PY_MOD_ADD_METHOD(DepthFunc);
+ PY_MOD_ADD_METHOD(DepthMask);
+ PY_MOD_ADD_METHOD(DepthRange);
+ PY_MOD_ADD_METHOD(Disable);
+ PY_MOD_ADD_METHOD(DrawBuffer);
+ PY_MOD_ADD_METHOD(Enable);
+ PY_MOD_ADD_METHOD(Finish);
+ PY_MOD_ADD_METHOD(Flush);
+ PY_MOD_ADD_METHOD(FrontFace);
+ PY_MOD_ADD_METHOD(GetBooleanv);
+ PY_MOD_ADD_METHOD(GetDoublev);
+ PY_MOD_ADD_METHOD(GetError);
+ PY_MOD_ADD_METHOD(GetFloatv);
+ PY_MOD_ADD_METHOD(GetIntegerv);
+ PY_MOD_ADD_METHOD(GetString);
+ PY_MOD_ADD_METHOD(GetTexImage);
+ PY_MOD_ADD_METHOD(GetTexLevelParameterfv);
+ PY_MOD_ADD_METHOD(GetTexLevelParameteriv);
+ PY_MOD_ADD_METHOD(GetTexParameterfv);
+ PY_MOD_ADD_METHOD(GetTexParameteriv);
+ PY_MOD_ADD_METHOD(Hint);
+ PY_MOD_ADD_METHOD(IsEnabled);
+ PY_MOD_ADD_METHOD(LineWidth);
+ PY_MOD_ADD_METHOD(LogicOp);
+ PY_MOD_ADD_METHOD(PixelStoref);
+ PY_MOD_ADD_METHOD(PixelStorei);
+ PY_MOD_ADD_METHOD(PointSize);
+ PY_MOD_ADD_METHOD(PolygonMode);
+ PY_MOD_ADD_METHOD(ReadBuffer);
+ PY_MOD_ADD_METHOD(ReadPixels);
+ PY_MOD_ADD_METHOD(Scissor);
+ PY_MOD_ADD_METHOD(StencilFunc);
+ PY_MOD_ADD_METHOD(StencilMask);
+ PY_MOD_ADD_METHOD(StencilOp);
+ PY_MOD_ADD_METHOD(TexImage1D);
+ PY_MOD_ADD_METHOD(TexImage2D);
+ PY_MOD_ADD_METHOD(TexParameterf);
+ PY_MOD_ADD_METHOD(TexParameterfv);
+ PY_MOD_ADD_METHOD(TexParameteri);
+ PY_MOD_ADD_METHOD(TexParameteriv);
+ PY_MOD_ADD_METHOD(Viewport);
+ }
+ /* adding in GL_VERSION_1_0 removed from core profile */
+ if (use_deprecated == true) {
+ PY_MOD_ADD_METHOD(Accum);
+ PY_MOD_ADD_METHOD(AlphaFunc);
+ PY_MOD_ADD_METHOD(Begin);
+ PY_MOD_ADD_METHOD(Bitmap);
+ PY_MOD_ADD_METHOD(CallList);
+ PY_MOD_ADD_METHOD(CallLists);
+ PY_MOD_ADD_METHOD(ClearAccum);
+ PY_MOD_ADD_METHOD(ClearIndex);
+ PY_MOD_ADD_METHOD(ClipPlane);
+ PY_MOD_ADD_METHOD(Color3b);
+ PY_MOD_ADD_METHOD(Color3bv);
+ PY_MOD_ADD_METHOD(Color3d);
+ PY_MOD_ADD_METHOD(Color3dv);
+ PY_MOD_ADD_METHOD(Color3f);
+ PY_MOD_ADD_METHOD(Color3fv);
+ PY_MOD_ADD_METHOD(Color3i);
+ PY_MOD_ADD_METHOD(Color3iv);
+ PY_MOD_ADD_METHOD(Color3s);
+ PY_MOD_ADD_METHOD(Color3sv);
+ PY_MOD_ADD_METHOD(Color3ub);
+ PY_MOD_ADD_METHOD(Color3ubv);
+ PY_MOD_ADD_METHOD(Color3ui);
+ PY_MOD_ADD_METHOD(Color3uiv);
+ PY_MOD_ADD_METHOD(Color3us);
+ PY_MOD_ADD_METHOD(Color3usv);
+ PY_MOD_ADD_METHOD(Color4b);
+ PY_MOD_ADD_METHOD(Color4bv);
+ PY_MOD_ADD_METHOD(Color4d);
+ PY_MOD_ADD_METHOD(Color4dv);
+ PY_MOD_ADD_METHOD(Color4f);
+ PY_MOD_ADD_METHOD(Color4fv);
+ PY_MOD_ADD_METHOD(Color4i);
+ PY_MOD_ADD_METHOD(Color4iv);
+ PY_MOD_ADD_METHOD(Color4s);
+ PY_MOD_ADD_METHOD(Color4sv);
+ PY_MOD_ADD_METHOD(Color4ub);
+ PY_MOD_ADD_METHOD(Color4ubv);
+ PY_MOD_ADD_METHOD(Color4ui);
+ PY_MOD_ADD_METHOD(Color4uiv);
+ PY_MOD_ADD_METHOD(Color4us);
+ PY_MOD_ADD_METHOD(Color4usv);
+ PY_MOD_ADD_METHOD(ColorMaterial);
+ PY_MOD_ADD_METHOD(CopyPixels);
+ PY_MOD_ADD_METHOD(DeleteLists);
+ PY_MOD_ADD_METHOD(DrawPixels);
+ PY_MOD_ADD_METHOD(EdgeFlag);
+ PY_MOD_ADD_METHOD(EdgeFlagv);
+ PY_MOD_ADD_METHOD(End);
+ PY_MOD_ADD_METHOD(EndList);
+ PY_MOD_ADD_METHOD(EvalCoord1d);
+ PY_MOD_ADD_METHOD(EvalCoord1dv);
+ PY_MOD_ADD_METHOD(EvalCoord1f);
+ PY_MOD_ADD_METHOD(EvalCoord1fv);
+ PY_MOD_ADD_METHOD(EvalCoord2d);
+ PY_MOD_ADD_METHOD(EvalCoord2dv);
+ PY_MOD_ADD_METHOD(EvalCoord2f);
+ PY_MOD_ADD_METHOD(EvalCoord2fv);
+ PY_MOD_ADD_METHOD(EvalMesh1);
+ PY_MOD_ADD_METHOD(EvalMesh2);
+ PY_MOD_ADD_METHOD(EvalPoint1);
+ PY_MOD_ADD_METHOD(EvalPoint2);
+ PY_MOD_ADD_METHOD(FeedbackBuffer);
+ PY_MOD_ADD_METHOD(Fogf);
+ PY_MOD_ADD_METHOD(Fogfv);
+ PY_MOD_ADD_METHOD(Fogi);
+ PY_MOD_ADD_METHOD(Fogiv);
+ PY_MOD_ADD_METHOD(Frustum);
+ PY_MOD_ADD_METHOD(GenLists);
+ PY_MOD_ADD_METHOD(GetClipPlane);
+ PY_MOD_ADD_METHOD(GetLightfv);
+ PY_MOD_ADD_METHOD(GetLightiv);
+ PY_MOD_ADD_METHOD(GetMapdv);
+ PY_MOD_ADD_METHOD(GetMapfv);
+ PY_MOD_ADD_METHOD(GetMapiv);
+ PY_MOD_ADD_METHOD(GetMaterialfv);
+ PY_MOD_ADD_METHOD(GetMaterialiv);
+ PY_MOD_ADD_METHOD(GetPixelMapfv);
+ PY_MOD_ADD_METHOD(GetPixelMapuiv);
+ PY_MOD_ADD_METHOD(GetPixelMapusv);
+ PY_MOD_ADD_METHOD(GetPolygonStipple);
+ PY_MOD_ADD_METHOD(GetTexEnvfv);
+ PY_MOD_ADD_METHOD(GetTexEnviv);
+ PY_MOD_ADD_METHOD(GetTexGendv);
+ PY_MOD_ADD_METHOD(GetTexGenfv);
+ PY_MOD_ADD_METHOD(GetTexGeniv);
+ PY_MOD_ADD_METHOD(IndexMask);
+ PY_MOD_ADD_METHOD(Indexd);
+ PY_MOD_ADD_METHOD(Indexdv);
+ PY_MOD_ADD_METHOD(Indexf);
+ PY_MOD_ADD_METHOD(Indexfv);
+ PY_MOD_ADD_METHOD(Indexi);
+ PY_MOD_ADD_METHOD(Indexiv);
+ PY_MOD_ADD_METHOD(Indexs);
+ PY_MOD_ADD_METHOD(Indexsv);
+ PY_MOD_ADD_METHOD(InitNames);
+ PY_MOD_ADD_METHOD(IsList);
+ PY_MOD_ADD_METHOD(LightModelf);
+ PY_MOD_ADD_METHOD(LightModelfv);
+ PY_MOD_ADD_METHOD(LightModeli);
+ PY_MOD_ADD_METHOD(LightModeliv);
+ PY_MOD_ADD_METHOD(Lightf);
+ PY_MOD_ADD_METHOD(Lightfv);
+ PY_MOD_ADD_METHOD(Lighti);
+ PY_MOD_ADD_METHOD(Lightiv);
+ PY_MOD_ADD_METHOD(LineStipple);
+ PY_MOD_ADD_METHOD(ListBase);
+ PY_MOD_ADD_METHOD(LoadIdentity);
+ PY_MOD_ADD_METHOD(LoadMatrixd);
+ PY_MOD_ADD_METHOD(LoadMatrixf);
+ PY_MOD_ADD_METHOD(LoadName);
+ PY_MOD_ADD_METHOD(Map1d);
+ PY_MOD_ADD_METHOD(Map1f);
+ PY_MOD_ADD_METHOD(Map2d);
+ PY_MOD_ADD_METHOD(Map2f);
+ PY_MOD_ADD_METHOD(MapGrid1d);
+ PY_MOD_ADD_METHOD(MapGrid1f);
+ PY_MOD_ADD_METHOD(MapGrid2d);
+ PY_MOD_ADD_METHOD(MapGrid2f);
+ PY_MOD_ADD_METHOD(Materialf);
+ PY_MOD_ADD_METHOD(Materialfv);
+ PY_MOD_ADD_METHOD(Materiali);
+ PY_MOD_ADD_METHOD(Materialiv);
+ PY_MOD_ADD_METHOD(MatrixMode);
+ PY_MOD_ADD_METHOD(MultMatrixd);
+ PY_MOD_ADD_METHOD(MultMatrixf);
+ PY_MOD_ADD_METHOD(NewList);
+ PY_MOD_ADD_METHOD(Normal3b);
+ PY_MOD_ADD_METHOD(Normal3bv);
+ PY_MOD_ADD_METHOD(Normal3d);
+ PY_MOD_ADD_METHOD(Normal3dv);
+ PY_MOD_ADD_METHOD(Normal3f);
+ PY_MOD_ADD_METHOD(Normal3fv);
+ PY_MOD_ADD_METHOD(Normal3i);
+ PY_MOD_ADD_METHOD(Normal3iv);
+ PY_MOD_ADD_METHOD(Normal3s);
+ PY_MOD_ADD_METHOD(Normal3sv);
+ PY_MOD_ADD_METHOD(Ortho);
+ PY_MOD_ADD_METHOD(PassThrough);
+ PY_MOD_ADD_METHOD(PixelMapfv);
+ PY_MOD_ADD_METHOD(PixelMapuiv);
+ PY_MOD_ADD_METHOD(PixelMapusv);
+ PY_MOD_ADD_METHOD(PixelTransferf);
+ PY_MOD_ADD_METHOD(PixelTransferi);
+ PY_MOD_ADD_METHOD(PixelZoom);
+ PY_MOD_ADD_METHOD(PolygonStipple);
+ PY_MOD_ADD_METHOD(PopAttrib);
+ PY_MOD_ADD_METHOD(PopMatrix);
+ PY_MOD_ADD_METHOD(PopName);
+ PY_MOD_ADD_METHOD(PushAttrib);
+ PY_MOD_ADD_METHOD(PushMatrix);
+ PY_MOD_ADD_METHOD(PushName);
+ PY_MOD_ADD_METHOD(RasterPos2d);
+ PY_MOD_ADD_METHOD(RasterPos2dv);
+ PY_MOD_ADD_METHOD(RasterPos2f);
+ PY_MOD_ADD_METHOD(RasterPos2fv);
+ PY_MOD_ADD_METHOD(RasterPos2i);
+ PY_MOD_ADD_METHOD(RasterPos2iv);
+ PY_MOD_ADD_METHOD(RasterPos2s);
+ PY_MOD_ADD_METHOD(RasterPos2sv);
+ PY_MOD_ADD_METHOD(RasterPos3d);
+ PY_MOD_ADD_METHOD(RasterPos3dv);
+ PY_MOD_ADD_METHOD(RasterPos3f);
+ PY_MOD_ADD_METHOD(RasterPos3fv);
+ PY_MOD_ADD_METHOD(RasterPos3i);
+ PY_MOD_ADD_METHOD(RasterPos3iv);
+ PY_MOD_ADD_METHOD(RasterPos3s);
+ PY_MOD_ADD_METHOD(RasterPos3sv);
+ PY_MOD_ADD_METHOD(RasterPos4d);
+ PY_MOD_ADD_METHOD(RasterPos4dv);
+ PY_MOD_ADD_METHOD(RasterPos4f);
+ PY_MOD_ADD_METHOD(RasterPos4fv);
+ PY_MOD_ADD_METHOD(RasterPos4i);
+ PY_MOD_ADD_METHOD(RasterPos4iv);
+ PY_MOD_ADD_METHOD(RasterPos4s);
+ PY_MOD_ADD_METHOD(RasterPos4sv);
+ PY_MOD_ADD_METHOD(Rectd);
+ PY_MOD_ADD_METHOD(Rectdv);
+ PY_MOD_ADD_METHOD(Rectf);
+ PY_MOD_ADD_METHOD(Rectfv);
+ PY_MOD_ADD_METHOD(Recti);
+ PY_MOD_ADD_METHOD(Rectiv);
+ PY_MOD_ADD_METHOD(Rects);
+ PY_MOD_ADD_METHOD(Rectsv);
+ PY_MOD_ADD_METHOD(RenderMode);
+ PY_MOD_ADD_METHOD(Rotated);
+ PY_MOD_ADD_METHOD(Rotatef);
+ PY_MOD_ADD_METHOD(Scaled);
+ PY_MOD_ADD_METHOD(Scalef);
+ PY_MOD_ADD_METHOD(SelectBuffer);
+ PY_MOD_ADD_METHOD(ShadeModel);
+ PY_MOD_ADD_METHOD(TexCoord1d);
+ PY_MOD_ADD_METHOD(TexCoord1dv);
+ PY_MOD_ADD_METHOD(TexCoord1f);
+ PY_MOD_ADD_METHOD(TexCoord1fv);
+ PY_MOD_ADD_METHOD(TexCoord1i);
+ PY_MOD_ADD_METHOD(TexCoord1iv);
+ PY_MOD_ADD_METHOD(TexCoord1s);
+ PY_MOD_ADD_METHOD(TexCoord1sv);
+ PY_MOD_ADD_METHOD(TexCoord2d);
+ PY_MOD_ADD_METHOD(TexCoord2dv);
+ PY_MOD_ADD_METHOD(TexCoord2f);
+ PY_MOD_ADD_METHOD(TexCoord2fv);
+ PY_MOD_ADD_METHOD(TexCoord2i);
+ PY_MOD_ADD_METHOD(TexCoord2iv);
+ PY_MOD_ADD_METHOD(TexCoord2s);
+ PY_MOD_ADD_METHOD(TexCoord2sv);
+ PY_MOD_ADD_METHOD(TexCoord3d);
+ PY_MOD_ADD_METHOD(TexCoord3dv);
+ PY_MOD_ADD_METHOD(TexCoord3f);
+ PY_MOD_ADD_METHOD(TexCoord3fv);
+ PY_MOD_ADD_METHOD(TexCoord3i);
+ PY_MOD_ADD_METHOD(TexCoord3iv);
+ PY_MOD_ADD_METHOD(TexCoord3s);
+ PY_MOD_ADD_METHOD(TexCoord3sv);
+ PY_MOD_ADD_METHOD(TexCoord4d);
+ PY_MOD_ADD_METHOD(TexCoord4dv);
+ PY_MOD_ADD_METHOD(TexCoord4f);
+ PY_MOD_ADD_METHOD(TexCoord4fv);
+ PY_MOD_ADD_METHOD(TexCoord4i);
+ PY_MOD_ADD_METHOD(TexCoord4iv);
+ PY_MOD_ADD_METHOD(TexCoord4s);
+ PY_MOD_ADD_METHOD(TexCoord4sv);
+ PY_MOD_ADD_METHOD(TexEnvf);
+ PY_MOD_ADD_METHOD(TexEnvfv);
+ PY_MOD_ADD_METHOD(TexEnvi);
+ PY_MOD_ADD_METHOD(TexEnviv);
+ PY_MOD_ADD_METHOD(TexGend);
+ PY_MOD_ADD_METHOD(TexGendv);
+ PY_MOD_ADD_METHOD(TexGenf);
+ PY_MOD_ADD_METHOD(TexGenfv);
+ PY_MOD_ADD_METHOD(TexGeni);
+ PY_MOD_ADD_METHOD(TexGeniv);
+ PY_MOD_ADD_METHOD(Translated);
+ PY_MOD_ADD_METHOD(Translatef);
+ PY_MOD_ADD_METHOD(Vertex2d);
+ PY_MOD_ADD_METHOD(Vertex2dv);
+ PY_MOD_ADD_METHOD(Vertex2f);
+ PY_MOD_ADD_METHOD(Vertex2fv);
+ PY_MOD_ADD_METHOD(Vertex2i);
+ PY_MOD_ADD_METHOD(Vertex2iv);
+ PY_MOD_ADD_METHOD(Vertex2s);
+ PY_MOD_ADD_METHOD(Vertex2sv);
+ PY_MOD_ADD_METHOD(Vertex3d);
+ PY_MOD_ADD_METHOD(Vertex3dv);
+ PY_MOD_ADD_METHOD(Vertex3f);
+ PY_MOD_ADD_METHOD(Vertex3fv);
+ PY_MOD_ADD_METHOD(Vertex3i);
+ PY_MOD_ADD_METHOD(Vertex3iv);
+ PY_MOD_ADD_METHOD(Vertex3s);
+ PY_MOD_ADD_METHOD(Vertex3sv);
+ PY_MOD_ADD_METHOD(Vertex4d);
+ PY_MOD_ADD_METHOD(Vertex4dv);
+ PY_MOD_ADD_METHOD(Vertex4f);
+ PY_MOD_ADD_METHOD(Vertex4fv);
+ PY_MOD_ADD_METHOD(Vertex4i);
+ PY_MOD_ADD_METHOD(Vertex4iv);
+ PY_MOD_ADD_METHOD(Vertex4s);
+ PY_MOD_ADD_METHOD(Vertex4sv);
+ }
+
+
+ /* GL_VERSION_1_1 */
+ {
+ PY_MOD_ADD_METHOD(BindTexture);
+ PY_MOD_ADD_METHOD(CopyTexImage1D);
+ PY_MOD_ADD_METHOD(CopyTexImage2D);
+ PY_MOD_ADD_METHOD(CopyTexSubImage1D);
+ PY_MOD_ADD_METHOD(CopyTexSubImage2D);
+ PY_MOD_ADD_METHOD(DeleteTextures);
+ PY_MOD_ADD_METHOD(DrawArrays);
+ PY_MOD_ADD_METHOD(DrawElements);
+ PY_MOD_ADD_METHOD(GenTextures);
+ PY_MOD_ADD_METHOD(IsTexture);
+ PY_MOD_ADD_METHOD(PolygonOffset);
+ PY_MOD_ADD_METHOD(TexSubImage1D);
+ PY_MOD_ADD_METHOD(TexSubImage2D);
+ }
+ /* adding in GL_VERSION_1_1 removed from core profile */
+ if (use_deprecated == true) {
+ PY_MOD_ADD_METHOD(AreTexturesResident);
+ PY_MOD_ADD_METHOD(ArrayElement);
+ PY_MOD_ADD_METHOD(ColorPointer);
+ PY_MOD_ADD_METHOD(DisableClientState);
+ PY_MOD_ADD_METHOD(EdgeFlagPointer);
+ PY_MOD_ADD_METHOD(EnableClientState);
+ PY_MOD_ADD_METHOD(GetPointerv);
+ PY_MOD_ADD_METHOD(IndexPointer);
+ PY_MOD_ADD_METHOD(Indexub);
+ PY_MOD_ADD_METHOD(Indexubv);
+ PY_MOD_ADD_METHOD(InterleavedArrays);
+ PY_MOD_ADD_METHOD(NormalPointer);
+ PY_MOD_ADD_METHOD(PopClientAttrib);
+ PY_MOD_ADD_METHOD(PrioritizeTextures);
+ PY_MOD_ADD_METHOD(PushClientAttrib);
+ PY_MOD_ADD_METHOD(TexCoordPointer);
+ PY_MOD_ADD_METHOD(VertexPointer);
+ }
+
+
+ /* GL_VERSION_1_2 */
+ {
+ PY_MOD_ADD_METHOD(CopyTexSubImage3D);
+ PY_MOD_ADD_METHOD(DrawRangeElements);
+ PY_MOD_ADD_METHOD(TexImage3D);
+ PY_MOD_ADD_METHOD(TexSubImage3D);
+ }
+
+
+ /* GL_VERSION_1_3 */
+ {
+ PY_MOD_ADD_METHOD(ActiveTexture);
+ PY_MOD_ADD_METHOD(CompressedTexImage1D);
+ PY_MOD_ADD_METHOD(CompressedTexImage2D);
+ PY_MOD_ADD_METHOD(CompressedTexImage3D);
+ PY_MOD_ADD_METHOD(CompressedTexSubImage1D);
+ PY_MOD_ADD_METHOD(CompressedTexSubImage2D);
+ PY_MOD_ADD_METHOD(CompressedTexSubImage3D);
+ PY_MOD_ADD_METHOD(GetCompressedTexImage);
+ PY_MOD_ADD_METHOD(SampleCoverage);
+ }
+ /* adding in GL_VERSION_1_3 removed from core profile */
+ if (use_deprecated == true) {
+ PY_MOD_ADD_METHOD(ClientActiveTexture);
+ PY_MOD_ADD_METHOD(LoadTransposeMatrixd);
+ PY_MOD_ADD_METHOD(LoadTransposeMatrixf);
+ PY_MOD_ADD_METHOD(MultTransposeMatrixd);
+ PY_MOD_ADD_METHOD(MultTransposeMatrixf);
+ PY_MOD_ADD_METHOD(MultiTexCoord1d);
+ PY_MOD_ADD_METHOD(MultiTexCoord1dv);
+ PY_MOD_ADD_METHOD(MultiTexCoord1f);
+ PY_MOD_ADD_METHOD(MultiTexCoord1fv);
+ PY_MOD_ADD_METHOD(MultiTexCoord1i);
+ PY_MOD_ADD_METHOD(MultiTexCoord1iv);
+ PY_MOD_ADD_METHOD(MultiTexCoord1s);
+ PY_MOD_ADD_METHOD(MultiTexCoord1sv);
+ PY_MOD_ADD_METHOD(MultiTexCoord2d);
+ PY_MOD_ADD_METHOD(MultiTexCoord2dv);
+ PY_MOD_ADD_METHOD(MultiTexCoord2f);
+ PY_MOD_ADD_METHOD(MultiTexCoord2fv);
+ PY_MOD_ADD_METHOD(MultiTexCoord2i);
+ PY_MOD_ADD_METHOD(MultiTexCoord2iv);
+ PY_MOD_ADD_METHOD(MultiTexCoord2s);
+ PY_MOD_ADD_METHOD(MultiTexCoord2sv);
+ PY_MOD_ADD_METHOD(MultiTexCoord3d);
+ PY_MOD_ADD_METHOD(MultiTexCoord3dv);
+ PY_MOD_ADD_METHOD(MultiTexCoord3f);
+ PY_MOD_ADD_METHOD(MultiTexCoord3fv);
+ PY_MOD_ADD_METHOD(MultiTexCoord3i);
+ PY_MOD_ADD_METHOD(MultiTexCoord3iv);
+ PY_MOD_ADD_METHOD(MultiTexCoord3s);
+ PY_MOD_ADD_METHOD(MultiTexCoord3sv);
+ PY_MOD_ADD_METHOD(MultiTexCoord4d);
+ PY_MOD_ADD_METHOD(MultiTexCoord4dv);
+ PY_MOD_ADD_METHOD(MultiTexCoord4f);
+ PY_MOD_ADD_METHOD(MultiTexCoord4fv);
+ PY_MOD_ADD_METHOD(MultiTexCoord4i);
+ PY_MOD_ADD_METHOD(MultiTexCoord4iv);
+ PY_MOD_ADD_METHOD(MultiTexCoord4s);
+ PY_MOD_ADD_METHOD(MultiTexCoord4sv);
+ }
+
+
+ /* GL_VERSION_1_4 */
+ {
+ PY_MOD_ADD_METHOD(BlendColor);
+ PY_MOD_ADD_METHOD(BlendEquation);
+ }
+
+
+ /* GL_VERSION_1_5 */
+ {
+ PY_MOD_ADD_METHOD(BeginQuery);
+ PY_MOD_ADD_METHOD(BindBuffer);
+ PY_MOD_ADD_METHOD(BufferData);
+ PY_MOD_ADD_METHOD(BufferSubData);
+ PY_MOD_ADD_METHOD(DeleteBuffers);
+ PY_MOD_ADD_METHOD(DeleteQueries);
+ PY_MOD_ADD_METHOD(EndQuery);
+ PY_MOD_ADD_METHOD(GenBuffers);
+ PY_MOD_ADD_METHOD(GenQueries);
+ PY_MOD_ADD_METHOD(GetBufferParameteriv);
+ PY_MOD_ADD_METHOD(GetBufferPointerv);
+ PY_MOD_ADD_METHOD(GetBufferSubData);
+ PY_MOD_ADD_METHOD(GetQueryObjectiv);
+ PY_MOD_ADD_METHOD(GetQueryObjectuiv);
+ PY_MOD_ADD_METHOD(GetQueryiv);
+ PY_MOD_ADD_METHOD(IsBuffer);
+ PY_MOD_ADD_METHOD(IsQuery);
+ PY_MOD_ADD_METHOD(MapBuffer);
+ PY_MOD_ADD_METHOD(UnmapBuffer);
+ }
+
+
+ /* GL_VERSION_2_0 */
+ {
+ PY_MOD_ADD_METHOD(AttachShader);
+ PY_MOD_ADD_METHOD(BindAttribLocation);
+ PY_MOD_ADD_METHOD(BlendEquationSeparate);
+ PY_MOD_ADD_METHOD(CompileShader);
+ PY_MOD_ADD_METHOD(CreateProgram);
+ PY_MOD_ADD_METHOD(CreateShader);
+ PY_MOD_ADD_METHOD(DeleteProgram);
+ PY_MOD_ADD_METHOD(DeleteShader);
+ PY_MOD_ADD_METHOD(DetachShader);
+ PY_MOD_ADD_METHOD(DisableVertexAttribArray);
+ PY_MOD_ADD_METHOD(DrawBuffers);
+ PY_MOD_ADD_METHOD(EnableVertexAttribArray);
+ PY_MOD_ADD_METHOD(GetActiveAttrib);
+ PY_MOD_ADD_METHOD(GetActiveUniform);
+ PY_MOD_ADD_METHOD(GetAttachedShaders);
+ PY_MOD_ADD_METHOD(GetAttribLocation);
+ PY_MOD_ADD_METHOD(GetProgramInfoLog);
+ PY_MOD_ADD_METHOD(GetProgramiv);
+ PY_MOD_ADD_METHOD(GetShaderInfoLog);
+ PY_MOD_ADD_METHOD(GetShaderSource);
+ PY_MOD_ADD_METHOD(GetShaderiv);
+ PY_MOD_ADD_METHOD(GetUniformLocation);
+ PY_MOD_ADD_METHOD(GetUniformfv);
+ PY_MOD_ADD_METHOD(GetUniformiv);
+ PY_MOD_ADD_METHOD(GetVertexAttribPointerv);
+ PY_MOD_ADD_METHOD(GetVertexAttribdv);
+ PY_MOD_ADD_METHOD(GetVertexAttribfv);
+ PY_MOD_ADD_METHOD(GetVertexAttribiv);
+ PY_MOD_ADD_METHOD(IsProgram);
+ PY_MOD_ADD_METHOD(IsShader);
+ PY_MOD_ADD_METHOD(LinkProgram);
+ PY_MOD_ADD_METHOD(ShaderSource);
+ PY_MOD_ADD_METHOD(StencilFuncSeparate);
+ PY_MOD_ADD_METHOD(StencilMaskSeparate);
+ PY_MOD_ADD_METHOD(StencilOpSeparate);
+ PY_MOD_ADD_METHOD(Uniform1f);
+ PY_MOD_ADD_METHOD(Uniform1fv);
+ PY_MOD_ADD_METHOD(Uniform1i);
+ PY_MOD_ADD_METHOD(Uniform1iv);
+ PY_MOD_ADD_METHOD(Uniform2f);
+ PY_MOD_ADD_METHOD(Uniform2fv);
+ PY_MOD_ADD_METHOD(Uniform2i);
+ PY_MOD_ADD_METHOD(Uniform2iv);
+ PY_MOD_ADD_METHOD(Uniform3f);
+ PY_MOD_ADD_METHOD(Uniform3fv);
+ PY_MOD_ADD_METHOD(Uniform3i);
+ PY_MOD_ADD_METHOD(Uniform3iv);
+ PY_MOD_ADD_METHOD(Uniform4f);
+ PY_MOD_ADD_METHOD(Uniform4fv);
+ PY_MOD_ADD_METHOD(Uniform4i);
+ PY_MOD_ADD_METHOD(Uniform4iv);
+ PY_MOD_ADD_METHOD(UniformMatrix2fv);
+ PY_MOD_ADD_METHOD(UniformMatrix3fv);
+ PY_MOD_ADD_METHOD(UniformMatrix4fv);
+ PY_MOD_ADD_METHOD(UseProgram);
+ PY_MOD_ADD_METHOD(ValidateProgram);
+ PY_MOD_ADD_METHOD(VertexAttrib1d);
+ PY_MOD_ADD_METHOD(VertexAttrib1dv);
+ PY_MOD_ADD_METHOD(VertexAttrib1f);
+ PY_MOD_ADD_METHOD(VertexAttrib1fv);
+ PY_MOD_ADD_METHOD(VertexAttrib1s);
+ PY_MOD_ADD_METHOD(VertexAttrib1sv);
+ PY_MOD_ADD_METHOD(VertexAttrib2d);
+ PY_MOD_ADD_METHOD(VertexAttrib2dv);
+ PY_MOD_ADD_METHOD(VertexAttrib2f);
+ PY_MOD_ADD_METHOD(VertexAttrib2fv);
+ PY_MOD_ADD_METHOD(VertexAttrib2s);
+ PY_MOD_ADD_METHOD(VertexAttrib2sv);
+ PY_MOD_ADD_METHOD(VertexAttrib3d);
+ PY_MOD_ADD_METHOD(VertexAttrib3dv);
+ PY_MOD_ADD_METHOD(VertexAttrib3f);
+ PY_MOD_ADD_METHOD(VertexAttrib3fv);
+ PY_MOD_ADD_METHOD(VertexAttrib3s);
+ PY_MOD_ADD_METHOD(VertexAttrib3sv);
+ PY_MOD_ADD_METHOD(VertexAttrib4Nbv);
+ PY_MOD_ADD_METHOD(VertexAttrib4Niv);
+ PY_MOD_ADD_METHOD(VertexAttrib4Nsv);
+ PY_MOD_ADD_METHOD(VertexAttrib4Nub);
+ PY_MOD_ADD_METHOD(VertexAttrib4Nubv);
+ PY_MOD_ADD_METHOD(VertexAttrib4Nuiv);
+ PY_MOD_ADD_METHOD(VertexAttrib4Nusv);
+ PY_MOD_ADD_METHOD(VertexAttrib4bv);
+ PY_MOD_ADD_METHOD(VertexAttrib4d);
+ PY_MOD_ADD_METHOD(VertexAttrib4dv);
+ PY_MOD_ADD_METHOD(VertexAttrib4f);
+ PY_MOD_ADD_METHOD(VertexAttrib4fv);
+ PY_MOD_ADD_METHOD(VertexAttrib4iv);
+ PY_MOD_ADD_METHOD(VertexAttrib4s);
+ PY_MOD_ADD_METHOD(VertexAttrib4sv);
+ PY_MOD_ADD_METHOD(VertexAttrib4ubv);
+ PY_MOD_ADD_METHOD(VertexAttrib4uiv);
+ PY_MOD_ADD_METHOD(VertexAttrib4usv);
+ PY_MOD_ADD_METHOD(VertexAttribPointer);
+ }
+
+
+ /* GL_VERSION_2_1 */
+ {
+ PY_MOD_ADD_METHOD(UniformMatrix2x3fv);
+ PY_MOD_ADD_METHOD(UniformMatrix2x4fv);
+ PY_MOD_ADD_METHOD(UniformMatrix3x2fv);
+ PY_MOD_ADD_METHOD(UniformMatrix3x4fv);
+ PY_MOD_ADD_METHOD(UniformMatrix4x2fv);
+ PY_MOD_ADD_METHOD(UniformMatrix4x3fv);
+ }
+
+
+ /* GL_VERSION_3_0 */
+ {
+ PY_MOD_ADD_METHOD(BindVertexArray);
+ PY_MOD_ADD_METHOD(DeleteVertexArrays);
+ PY_MOD_ADD_METHOD(GenVertexArrays);
+ PY_MOD_ADD_METHOD(IsVertexArray);
+ }
+
+
+ /* GL_VERSION_3_1 */
+ {
+ PY_MOD_ADD_METHOD(BindBufferBase);
+ PY_MOD_ADD_METHOD(BindBufferRange);
+ PY_MOD_ADD_METHOD(GetActiveUniformBlockName);
+ PY_MOD_ADD_METHOD(GetActiveUniformBlockiv);
+ PY_MOD_ADD_METHOD(GetActiveUniformName);
+ PY_MOD_ADD_METHOD(GetActiveUniformsiv);
+ PY_MOD_ADD_METHOD(GetIntegeri_v);
+ PY_MOD_ADD_METHOD(GetUniformBlockIndex);
+ PY_MOD_ADD_METHOD(GetUniformIndices);
+ PY_MOD_ADD_METHOD(UniformBlockBinding);
+ }
+
+
+ /* GL_VERSION_3_2 */
+ {
+ PY_MOD_ADD_METHOD(FramebufferTexture);
+ PY_MOD_ADD_METHOD(GetBufferParameteri64v);
+ PY_MOD_ADD_METHOD(GetInteger64i_v);
+ PY_MOD_ADD_METHOD(GetMultisamplefv);
+ PY_MOD_ADD_METHOD(SampleMaski);
+ PY_MOD_ADD_METHOD(TexImage2DMultisample);
+ PY_MOD_ADD_METHOD(TexImage3DMultisample);
+ }
+
+
+ /* GL_VERSION_3_3 */
+ {
+ PY_MOD_ADD_METHOD(ColorP3ui);
+ PY_MOD_ADD_METHOD(ColorP3uiv);
+ PY_MOD_ADD_METHOD(ColorP4ui);
+ PY_MOD_ADD_METHOD(ColorP4uiv);
+ PY_MOD_ADD_METHOD(MultiTexCoordP1ui);
+ PY_MOD_ADD_METHOD(MultiTexCoordP1uiv);
+ PY_MOD_ADD_METHOD(MultiTexCoordP2ui);
+ PY_MOD_ADD_METHOD(MultiTexCoordP2uiv);
+ PY_MOD_ADD_METHOD(MultiTexCoordP3ui);
+ PY_MOD_ADD_METHOD(MultiTexCoordP3uiv);
+ PY_MOD_ADD_METHOD(MultiTexCoordP4ui);
+ PY_MOD_ADD_METHOD(MultiTexCoordP4uiv);
+ PY_MOD_ADD_METHOD(NormalP3ui);
+ PY_MOD_ADD_METHOD(NormalP3uiv);
+ PY_MOD_ADD_METHOD(SecondaryColorP3ui);
+ PY_MOD_ADD_METHOD(SecondaryColorP3uiv);
+ PY_MOD_ADD_METHOD(TexCoordP1ui);
+ PY_MOD_ADD_METHOD(TexCoordP1uiv);
+ PY_MOD_ADD_METHOD(TexCoordP2ui);
+ PY_MOD_ADD_METHOD(TexCoordP2uiv);
+ PY_MOD_ADD_METHOD(TexCoordP3ui);
+ PY_MOD_ADD_METHOD(TexCoordP3uiv);
+ PY_MOD_ADD_METHOD(TexCoordP4ui);
+ PY_MOD_ADD_METHOD(TexCoordP4uiv);
+ PY_MOD_ADD_METHOD(VertexP2ui);
+ PY_MOD_ADD_METHOD(VertexP2uiv);
+ PY_MOD_ADD_METHOD(VertexP3ui);
+ PY_MOD_ADD_METHOD(VertexP3uiv);
+ PY_MOD_ADD_METHOD(VertexP4ui);
+ PY_MOD_ADD_METHOD(VertexP4uiv);
+ }
+
+#define PY_DICT_ADD_INT(x) py_module_dict_add_int(dict, #x, x)
+#define PY_DICT_ADD_INT64(x) py_module_dict_add_int64(dict, #x, x)
+
+ /* GL_VERSION_1_1 */
+ {
+ PY_DICT_ADD_INT(GL_ALPHA);
+ PY_DICT_ADD_INT(GL_ALWAYS);
+ PY_DICT_ADD_INT(GL_AND);
+ PY_DICT_ADD_INT(GL_AND_INVERTED);
+ PY_DICT_ADD_INT(GL_AND_REVERSE);
+ PY_DICT_ADD_INT(GL_BACK);
+ PY_DICT_ADD_INT(GL_BACK_LEFT);
+ PY_DICT_ADD_INT(GL_BACK_RIGHT);
+ PY_DICT_ADD_INT(GL_BLEND);
+ PY_DICT_ADD_INT(GL_BLEND_DST);
+ PY_DICT_ADD_INT(GL_BLEND_SRC);
+ PY_DICT_ADD_INT(GL_BLUE);
+ PY_DICT_ADD_INT(GL_BYTE);
+ PY_DICT_ADD_INT(GL_CCW);
+ PY_DICT_ADD_INT(GL_CLEAR);
+ PY_DICT_ADD_INT(GL_COLOR);
+ PY_DICT_ADD_INT(GL_COLOR_BUFFER_BIT);
+ PY_DICT_ADD_INT(GL_COLOR_CLEAR_VALUE);
+ PY_DICT_ADD_INT(GL_COLOR_LOGIC_OP);
+ PY_DICT_ADD_INT(GL_COLOR_WRITEMASK);
+ PY_DICT_ADD_INT(GL_COPY);
+ PY_DICT_ADD_INT(GL_COPY_INVERTED);
+ PY_DICT_ADD_INT(GL_CULL_FACE);
+ PY_DICT_ADD_INT(GL_CULL_FACE_MODE);
+ PY_DICT_ADD_INT(GL_CW);
+ PY_DICT_ADD_INT(GL_DECR);
+ PY_DICT_ADD_INT(GL_DEPTH);
+ PY_DICT_ADD_INT(GL_DEPTH_BUFFER_BIT);
+ PY_DICT_ADD_INT(GL_DEPTH_CLEAR_VALUE);
+ PY_DICT_ADD_INT(GL_DEPTH_COMPONENT);
+ PY_DICT_ADD_INT(GL_DEPTH_FUNC);
+ PY_DICT_ADD_INT(GL_DEPTH_RANGE);
+ PY_DICT_ADD_INT(GL_DEPTH_TEST);
+ PY_DICT_ADD_INT(GL_DEPTH_WRITEMASK);
+ PY_DICT_ADD_INT(GL_DITHER);
+ PY_DICT_ADD_INT(GL_DONT_CARE);
+ PY_DICT_ADD_INT(GL_DOUBLE);
+ PY_DICT_ADD_INT(GL_DOUBLEBUFFER);
+ PY_DICT_ADD_INT(GL_DRAW_BUFFER);
+ PY_DICT_ADD_INT(GL_DST_ALPHA);
+ PY_DICT_ADD_INT(GL_DST_COLOR);
+ PY_DICT_ADD_INT(GL_EQUAL);
+ PY_DICT_ADD_INT(GL_EQUIV);
+ PY_DICT_ADD_INT(GL_EXTENSIONS);
+ PY_DICT_ADD_INT(GL_FALSE);
+ PY_DICT_ADD_INT(GL_FASTEST);
+ PY_DICT_ADD_INT(GL_FILL);
+ PY_DICT_ADD_INT(GL_FLOAT);
+ PY_DICT_ADD_INT(GL_FRONT);
+ PY_DICT_ADD_INT(GL_FRONT_AND_BACK);
+ PY_DICT_ADD_INT(GL_FRONT_FACE);
+ PY_DICT_ADD_INT(GL_FRONT_LEFT);
+ PY_DICT_ADD_INT(GL_FRONT_RIGHT);
+ PY_DICT_ADD_INT(GL_GEQUAL);
+ PY_DICT_ADD_INT(GL_GREATER);
+ PY_DICT_ADD_INT(GL_GREEN);
+ PY_DICT_ADD_INT(GL_INCR);
+ PY_DICT_ADD_INT(GL_INT);
+ PY_DICT_ADD_INT(GL_INVALID_ENUM);
+ PY_DICT_ADD_INT(GL_INVALID_OPERATION);
+ PY_DICT_ADD_INT(GL_INVALID_VALUE);
+ PY_DICT_ADD_INT(GL_INVERT);
+ PY_DICT_ADD_INT(GL_KEEP);
+ PY_DICT_ADD_INT(GL_LEFT);
+ PY_DICT_ADD_INT(GL_LEQUAL);
+ PY_DICT_ADD_INT(GL_LESS);
+ PY_DICT_ADD_INT(GL_LINE);
+ PY_DICT_ADD_INT(GL_LINEAR);
+ PY_DICT_ADD_INT(GL_LINEAR_MIPMAP_LINEAR);
+ PY_DICT_ADD_INT(GL_LINEAR_MIPMAP_NEAREST);
+ PY_DICT_ADD_INT(GL_LINES);
+ PY_DICT_ADD_INT(GL_LINE_LOOP);
+ PY_DICT_ADD_INT(GL_LINE_SMOOTH);
+ PY_DICT_ADD_INT(GL_LINE_SMOOTH_HINT);
+ PY_DICT_ADD_INT(GL_LINE_STRIP);
+ PY_DICT_ADD_INT(GL_LINE_WIDTH);
+ PY_DICT_ADD_INT(GL_LINE_WIDTH_GRANULARITY);
+ PY_DICT_ADD_INT(GL_LINE_WIDTH_RANGE);
+ PY_DICT_ADD_INT(GL_LOGIC_OP_MODE);
+ PY_DICT_ADD_INT(GL_MAX_TEXTURE_SIZE);
+ PY_DICT_ADD_INT(GL_MAX_VIEWPORT_DIMS);
+ PY_DICT_ADD_INT(GL_NAND);
+ PY_DICT_ADD_INT(GL_NEAREST);
+ PY_DICT_ADD_INT(GL_NEAREST_MIPMAP_LINEAR);
+ PY_DICT_ADD_INT(GL_NEAREST_MIPMAP_NEAREST);
+ PY_DICT_ADD_INT(GL_NEVER);
+ PY_DICT_ADD_INT(GL_NICEST);
+ PY_DICT_ADD_INT(GL_NONE);
+ PY_DICT_ADD_INT(GL_NOOP);
+ PY_DICT_ADD_INT(GL_NOR);
+ PY_DICT_ADD_INT(GL_NOTEQUAL);
+ PY_DICT_ADD_INT(GL_NO_ERROR);
+ PY_DICT_ADD_INT(GL_ONE);
+ PY_DICT_ADD_INT(GL_ONE_MINUS_DST_ALPHA);
+ PY_DICT_ADD_INT(GL_ONE_MINUS_DST_COLOR);
+ PY_DICT_ADD_INT(GL_ONE_MINUS_SRC_ALPHA);
+ PY_DICT_ADD_INT(GL_ONE_MINUS_SRC_COLOR);
+ PY_DICT_ADD_INT(GL_OR);
+ PY_DICT_ADD_INT(GL_OR_INVERTED);
+ PY_DICT_ADD_INT(GL_OR_REVERSE);
+ PY_DICT_ADD_INT(GL_OUT_OF_MEMORY);
+ PY_DICT_ADD_INT(GL_PACK_ALIGNMENT);
+ PY_DICT_ADD_INT(GL_PACK_LSB_FIRST);
+ PY_DICT_ADD_INT(GL_PACK_ROW_LENGTH);
+ PY_DICT_ADD_INT(GL_PACK_SKIP_PIXELS);
+ PY_DICT_ADD_INT(GL_PACK_SKIP_ROWS);
+ PY_DICT_ADD_INT(GL_PACK_SWAP_BYTES);
+ PY_DICT_ADD_INT(GL_POINT);
+ PY_DICT_ADD_INT(GL_POINTS);
+ PY_DICT_ADD_INT(GL_POINT_SIZE);
+ PY_DICT_ADD_INT(GL_POINT_SIZE_GRANULARITY);
+ PY_DICT_ADD_INT(GL_POINT_SIZE_RANGE);
+ PY_DICT_ADD_INT(GL_POLYGON_MODE);
+ PY_DICT_ADD_INT(GL_POLYGON_OFFSET_FACTOR);
+ PY_DICT_ADD_INT(GL_POLYGON_OFFSET_FILL);
+ PY_DICT_ADD_INT(GL_POLYGON_OFFSET_LINE);
+ PY_DICT_ADD_INT(GL_POLYGON_OFFSET_POINT);
+ PY_DICT_ADD_INT(GL_POLYGON_OFFSET_UNITS);
+ PY_DICT_ADD_INT(GL_POLYGON_SMOOTH);
+ PY_DICT_ADD_INT(GL_POLYGON_SMOOTH_HINT);
+ PY_DICT_ADD_INT(GL_PROXY_TEXTURE_1D);
+ PY_DICT_ADD_INT(GL_PROXY_TEXTURE_2D);
+ PY_DICT_ADD_INT(GL_R3_G3_B2);
+ PY_DICT_ADD_INT(GL_READ_BUFFER);
+ PY_DICT_ADD_INT(GL_RED);
+ PY_DICT_ADD_INT(GL_RENDERER);
+ PY_DICT_ADD_INT(GL_REPEAT);
+ PY_DICT_ADD_INT(GL_REPLACE);
+ PY_DICT_ADD_INT(GL_RGB);
+ PY_DICT_ADD_INT(GL_RGB10);
+ PY_DICT_ADD_INT(GL_RGB10_A2);
+ PY_DICT_ADD_INT(GL_RGB12);
+ PY_DICT_ADD_INT(GL_RGB16);
+ PY_DICT_ADD_INT(GL_RGB4);
+ PY_DICT_ADD_INT(GL_RGB5);
+ PY_DICT_ADD_INT(GL_RGB5_A1);
+ PY_DICT_ADD_INT(GL_RGB8);
+ PY_DICT_ADD_INT(GL_RGBA);
+ PY_DICT_ADD_INT(GL_RGBA12);
+ PY_DICT_ADD_INT(GL_RGBA16);
+ PY_DICT_ADD_INT(GL_RGBA2);
+ PY_DICT_ADD_INT(GL_RGBA4);
+ PY_DICT_ADD_INT(GL_RGBA8);
+ PY_DICT_ADD_INT(GL_RIGHT);
+ PY_DICT_ADD_INT(GL_SCISSOR_BOX);
+ PY_DICT_ADD_INT(GL_SCISSOR_TEST);
+ PY_DICT_ADD_INT(GL_SET);
+ PY_DICT_ADD_INT(GL_SHORT);
+ PY_DICT_ADD_INT(GL_SRC_ALPHA);
+ PY_DICT_ADD_INT(GL_SRC_ALPHA_SATURATE);
+ PY_DICT_ADD_INT(GL_SRC_COLOR);
+ PY_DICT_ADD_INT(GL_STENCIL);
+ PY_DICT_ADD_INT(GL_STENCIL_BUFFER_BIT);
+ PY_DICT_ADD_INT(GL_STENCIL_CLEAR_VALUE);
+ PY_DICT_ADD_INT(GL_STENCIL_FAIL);
+ PY_DICT_ADD_INT(GL_STENCIL_FUNC);
+ PY_DICT_ADD_INT(GL_STENCIL_INDEX);
+ PY_DICT_ADD_INT(GL_STENCIL_PASS_DEPTH_FAIL);
+ PY_DICT_ADD_INT(GL_STENCIL_PASS_DEPTH_PASS);
+ PY_DICT_ADD_INT(GL_STENCIL_REF);
+ PY_DICT_ADD_INT(GL_STENCIL_TEST);
+ PY_DICT_ADD_INT(GL_STENCIL_VALUE_MASK);
+ PY_DICT_ADD_INT(GL_STENCIL_WRITEMASK);
+ PY_DICT_ADD_INT(GL_STEREO);
+ PY_DICT_ADD_INT(GL_SUBPIXEL_BITS);
+ PY_DICT_ADD_INT(GL_TEXTURE);
+ PY_DICT_ADD_INT(GL_TEXTURE_1D);
+ PY_DICT_ADD_INT(GL_TEXTURE_2D);
+ PY_DICT_ADD_INT(GL_TEXTURE_ALPHA_SIZE);
+ PY_DICT_ADD_INT(GL_TEXTURE_BINDING_1D);
+ PY_DICT_ADD_INT(GL_TEXTURE_BINDING_2D);
+ PY_DICT_ADD_INT(GL_TEXTURE_BLUE_SIZE);
+ PY_DICT_ADD_INT(GL_TEXTURE_BORDER_COLOR);
+ PY_DICT_ADD_INT(GL_TEXTURE_GREEN_SIZE);
+ PY_DICT_ADD_INT(GL_TEXTURE_HEIGHT);
+ PY_DICT_ADD_INT(GL_TEXTURE_INTERNAL_FORMAT);
+ PY_DICT_ADD_INT(GL_TEXTURE_MAG_FILTER);
+ PY_DICT_ADD_INT(GL_TEXTURE_MIN_FILTER);
+ PY_DICT_ADD_INT(GL_TEXTURE_RED_SIZE);
+ PY_DICT_ADD_INT(GL_TEXTURE_WIDTH);
+ PY_DICT_ADD_INT(GL_TEXTURE_WRAP_S);
+ PY_DICT_ADD_INT(GL_TEXTURE_WRAP_T);
+ PY_DICT_ADD_INT(GL_TRIANGLES);
+ PY_DICT_ADD_INT(GL_TRIANGLE_FAN);
+ PY_DICT_ADD_INT(GL_TRIANGLE_STRIP);
+ PY_DICT_ADD_INT(GL_TRUE);
+ PY_DICT_ADD_INT(GL_UNPACK_ALIGNMENT);
+ PY_DICT_ADD_INT(GL_UNPACK_LSB_FIRST);
+ PY_DICT_ADD_INT(GL_UNPACK_ROW_LENGTH);
+ PY_DICT_ADD_INT(GL_UNPACK_SKIP_PIXELS);
+ PY_DICT_ADD_INT(GL_UNPACK_SKIP_ROWS);
+ PY_DICT_ADD_INT(GL_UNPACK_SWAP_BYTES);
+ PY_DICT_ADD_INT(GL_UNSIGNED_BYTE);
+ PY_DICT_ADD_INT(GL_UNSIGNED_INT);
+ PY_DICT_ADD_INT(GL_UNSIGNED_SHORT);
+ PY_DICT_ADD_INT(GL_VENDOR);
+ PY_DICT_ADD_INT(GL_VERSION);
+ PY_DICT_ADD_INT(GL_VIEWPORT);
+ PY_DICT_ADD_INT(GL_XOR);
+ PY_DICT_ADD_INT(GL_ZERO);
+ }
+ /* adding in GL_VERSION_1_1 removed from core profile */
+ if (use_deprecated == true) {
+ PY_DICT_ADD_INT(GL_2D);
+ PY_DICT_ADD_INT(GL_2_BYTES);
+ PY_DICT_ADD_INT(GL_3D);
+ PY_DICT_ADD_INT(GL_3D_COLOR);
+ PY_DICT_ADD_INT(GL_3D_COLOR_TEXTURE);
+ PY_DICT_ADD_INT(GL_3_BYTES);
+ PY_DICT_ADD_INT(GL_4D_COLOR_TEXTURE);
+ PY_DICT_ADD_INT(GL_4_BYTES);
+ PY_DICT_ADD_INT(GL_ACCUM);
+ PY_DICT_ADD_INT(GL_ACCUM_ALPHA_BITS);
+ PY_DICT_ADD_INT(GL_ACCUM_BLUE_BITS);
+ PY_DICT_ADD_INT(GL_ACCUM_BUFFER_BIT);
+ PY_DICT_ADD_INT(GL_ACCUM_CLEAR_VALUE);
+ PY_DICT_ADD_INT(GL_ACCUM_GREEN_BITS);
+ PY_DICT_ADD_INT(GL_ACCUM_RED_BITS);
+ PY_DICT_ADD_INT(GL_ADD);
+ PY_DICT_ADD_INT(GL_ALL_ATTRIB_BITS);
+ PY_DICT_ADD_INT(GL_ALPHA12);
+ PY_DICT_ADD_INT(GL_ALPHA16);
+ PY_DICT_ADD_INT(GL_ALPHA4);
+ PY_DICT_ADD_INT(GL_ALPHA8);
+ PY_DICT_ADD_INT(GL_ALPHA_BIAS);
+ PY_DICT_ADD_INT(GL_ALPHA_BITS);
+ PY_DICT_ADD_INT(GL_ALPHA_SCALE);
+ PY_DICT_ADD_INT(GL_ALPHA_TEST);
+ PY_DICT_ADD_INT(GL_ALPHA_TEST_FUNC);
+ PY_DICT_ADD_INT(GL_ALPHA_TEST_REF);
+ PY_DICT_ADD_INT(GL_AMBIENT);
+ PY_DICT_ADD_INT(GL_AMBIENT_AND_DIFFUSE);
+ PY_DICT_ADD_INT(GL_ATTRIB_STACK_DEPTH);
+ PY_DICT_ADD_INT(GL_AUTO_NORMAL);
+ PY_DICT_ADD_INT(GL_AUX0);
+ PY_DICT_ADD_INT(GL_AUX1);
+ PY_DICT_ADD_INT(GL_AUX2);
+ PY_DICT_ADD_INT(GL_AUX3);
+ PY_DICT_ADD_INT(GL_AUX_BUFFERS);
+ PY_DICT_ADD_INT(GL_BITMAP);
+ PY_DICT_ADD_INT(GL_BITMAP_TOKEN);
+ PY_DICT_ADD_INT(GL_BLUE_BIAS);
+ PY_DICT_ADD_INT(GL_BLUE_BITS);
+ PY_DICT_ADD_INT(GL_BLUE_SCALE);
+ PY_DICT_ADD_INT(GL_C3F_V3F);
+ PY_DICT_ADD_INT(GL_C4F_N3F_V3F);
+ PY_DICT_ADD_INT(GL_C4UB_V2F);
+ PY_DICT_ADD_INT(GL_C4UB_V3F);
+ PY_DICT_ADD_INT(GL_CLAMP);
+ PY_DICT_ADD_INT(GL_CLIENT_ALL_ATTRIB_BITS);
+ PY_DICT_ADD_INT(GL_CLIENT_ATTRIB_STACK_DEPTH);
+ PY_DICT_ADD_INT(GL_CLIENT_PIXEL_STORE_BIT);
+ PY_DICT_ADD_INT(GL_CLIENT_VERTEX_ARRAY_BIT);
+ PY_DICT_ADD_INT(GL_CLIP_PLANE0);
+ PY_DICT_ADD_INT(GL_CLIP_PLANE1);
+ PY_DICT_ADD_INT(GL_CLIP_PLANE2);
+ PY_DICT_ADD_INT(GL_CLIP_PLANE3);
+ PY_DICT_ADD_INT(GL_CLIP_PLANE4);
+ PY_DICT_ADD_INT(GL_CLIP_PLANE5);
+ PY_DICT_ADD_INT(GL_COEFF);
+ PY_DICT_ADD_INT(GL_COLOR_ARRAY);
+ PY_DICT_ADD_INT(GL_COLOR_ARRAY_POINTER);
+ PY_DICT_ADD_INT(GL_COLOR_ARRAY_SIZE);
+ PY_DICT_ADD_INT(GL_COLOR_ARRAY_STRIDE);
+ PY_DICT_ADD_INT(GL_COLOR_ARRAY_TYPE);
+ PY_DICT_ADD_INT(GL_COLOR_INDEX);
+ PY_DICT_ADD_INT(GL_COLOR_INDEXES);
+ PY_DICT_ADD_INT(GL_COLOR_MATERIAL);
+ PY_DICT_ADD_INT(GL_COLOR_MATERIAL_FACE);
+ PY_DICT_ADD_INT(GL_COLOR_MATERIAL_PARAMETER);
+ PY_DICT_ADD_INT(GL_COMPILE);
+ PY_DICT_ADD_INT(GL_COMPILE_AND_EXECUTE);
+ PY_DICT_ADD_INT(GL_CONSTANT_ATTENUATION);
+ PY_DICT_ADD_INT(GL_COPY_PIXEL_TOKEN);
+ PY_DICT_ADD_INT(GL_CURRENT_BIT);
+ PY_DICT_ADD_INT(GL_CURRENT_COLOR);
+ PY_DICT_ADD_INT(GL_CURRENT_INDEX);
+ PY_DICT_ADD_INT(GL_CURRENT_NORMAL);
+ PY_DICT_ADD_INT(GL_CURRENT_RASTER_COLOR);
+ PY_DICT_ADD_INT(GL_CURRENT_RASTER_DISTANCE);
+ PY_DICT_ADD_INT(GL_CURRENT_RASTER_INDEX);
+ PY_DICT_ADD_INT(GL_CURRENT_RASTER_POSITION);
+ PY_DICT_ADD_INT(GL_CURRENT_RASTER_POSITION_VALID);
+ PY_DICT_ADD_INT(GL_CURRENT_RASTER_TEXTURE_COORDS);
+ PY_DICT_ADD_INT(GL_CURRENT_TEXTURE_COORDS);
+ PY_DICT_ADD_INT(GL_DECAL);
+ PY_DICT_ADD_INT(GL_DEPTH_BIAS);
+ PY_DICT_ADD_INT(GL_DEPTH_BITS);
+ PY_DICT_ADD_INT(GL_DEPTH_SCALE);
+ PY_DICT_ADD_INT(GL_DIFFUSE);
+ PY_DICT_ADD_INT(GL_DOMAIN);
+ PY_DICT_ADD_INT(GL_DRAW_PIXEL_TOKEN);
+ PY_DICT_ADD_INT(GL_EDGE_FLAG);
+ PY_DICT_ADD_INT(GL_EDGE_FLAG_ARRAY);
+ PY_DICT_ADD_INT(GL_EDGE_FLAG_ARRAY_POINTER);
+ PY_DICT_ADD_INT(GL_EDGE_FLAG_ARRAY_STRIDE);
+ PY_DICT_ADD_INT(GL_EMISSION);
+ PY_DICT_ADD_INT(GL_ENABLE_BIT);
+ PY_DICT_ADD_INT(GL_EVAL_BIT);
+ PY_DICT_ADD_INT(GL_EXP);
+ PY_DICT_ADD_INT(GL_EXP2);
+ PY_DICT_ADD_INT(GL_EYE_LINEAR);
+ PY_DICT_ADD_INT(GL_EYE_PLANE);
+ PY_DICT_ADD_INT(GL_FEEDBACK);
+ PY_DICT_ADD_INT(GL_FEEDBACK_BUFFER_POINTER);
+ PY_DICT_ADD_INT(GL_FEEDBACK_BUFFER_SIZE);
+ PY_DICT_ADD_INT(GL_FEEDBACK_BUFFER_TYPE);
+ PY_DICT_ADD_INT(GL_FLAT);
+ PY_DICT_ADD_INT(GL_FOG);
+ PY_DICT_ADD_INT(GL_FOG_BIT);
+ PY_DICT_ADD_INT(GL_FOG_COLOR);
+ PY_DICT_ADD_INT(GL_FOG_DENSITY);
+ PY_DICT_ADD_INT(GL_FOG_END);
+ PY_DICT_ADD_INT(GL_FOG_HINT);
+ PY_DICT_ADD_INT(GL_FOG_INDEX);
+ PY_DICT_ADD_INT(GL_FOG_MODE);
+ PY_DICT_ADD_INT(GL_FOG_START);
+ PY_DICT_ADD_INT(GL_GREEN_BIAS);
+ PY_DICT_ADD_INT(GL_GREEN_BITS);
+ PY_DICT_ADD_INT(GL_GREEN_SCALE);
+ PY_DICT_ADD_INT(GL_HINT_BIT);
+ PY_DICT_ADD_INT(GL_INDEX_ARRAY);
+ PY_DICT_ADD_INT(GL_INDEX_ARRAY_POINTER);
+ PY_DICT_ADD_INT(GL_INDEX_ARRAY_STRIDE);
+ PY_DICT_ADD_INT(GL_INDEX_ARRAY_TYPE);
+ PY_DICT_ADD_INT(GL_INDEX_BITS);
+ PY_DICT_ADD_INT(GL_INDEX_CLEAR_VALUE);
+ PY_DICT_ADD_INT(GL_INDEX_LOGIC_OP);
+ PY_DICT_ADD_INT(GL_INDEX_MODE);
+ PY_DICT_ADD_INT(GL_INDEX_OFFSET);
+ PY_DICT_ADD_INT(GL_INDEX_SHIFT);
+ PY_DICT_ADD_INT(GL_INDEX_WRITEMASK);
+ PY_DICT_ADD_INT(GL_INTENSITY);
+ PY_DICT_ADD_INT(GL_INTENSITY12);
+ PY_DICT_ADD_INT(GL_INTENSITY16);
+ PY_DICT_ADD_INT(GL_INTENSITY4);
+ PY_DICT_ADD_INT(GL_INTENSITY8);
+ PY_DICT_ADD_INT(GL_LIGHT0);
+ PY_DICT_ADD_INT(GL_LIGHT1);
+ PY_DICT_ADD_INT(GL_LIGHT2);
+ PY_DICT_ADD_INT(GL_LIGHT3);
+ PY_DICT_ADD_INT(GL_LIGHT4);
+ PY_DICT_ADD_INT(GL_LIGHT5);
+ PY_DICT_ADD_INT(GL_LIGHT6);
+ PY_DICT_ADD_INT(GL_LIGHT7);
+ PY_DICT_ADD_INT(GL_LIGHTING);
+ PY_DICT_ADD_INT(GL_LIGHTING_BIT);
+ PY_DICT_ADD_INT(GL_LIGHT_MODEL_AMBIENT);
+ PY_DICT_ADD_INT(GL_LIGHT_MODEL_LOCAL_VIEWER);
+ PY_DICT_ADD_INT(GL_LIGHT_MODEL_TWO_SIDE);
+ PY_DICT_ADD_INT(GL_LINEAR_ATTENUATION);
+ PY_DICT_ADD_INT(GL_LINE_BIT);
+ PY_DICT_ADD_INT(GL_LINE_RESET_TOKEN);
+ PY_DICT_ADD_INT(GL_LINE_STIPPLE);
+ PY_DICT_ADD_INT(GL_LINE_STIPPLE_PATTERN);
+ PY_DICT_ADD_INT(GL_LINE_STIPPLE_REPEAT);
+ PY_DICT_ADD_INT(GL_LINE_TOKEN);
+ PY_DICT_ADD_INT(GL_LIST_BASE);
+ PY_DICT_ADD_INT(GL_LIST_BIT);
+ PY_DICT_ADD_INT(GL_LIST_INDEX);
+ PY_DICT_ADD_INT(GL_LIST_MODE);
+ PY_DICT_ADD_INT(GL_LOAD);
+ PY_DICT_ADD_INT(GL_LOGIC_OP);
+ PY_DICT_ADD_INT(GL_LUMINANCE);
+ PY_DICT_ADD_INT(GL_LUMINANCE12);
+ PY_DICT_ADD_INT(GL_LUMINANCE12_ALPHA12);
+ PY_DICT_ADD_INT(GL_LUMINANCE12_ALPHA4);
+ PY_DICT_ADD_INT(GL_LUMINANCE16);
+ PY_DICT_ADD_INT(GL_LUMINANCE16_ALPHA16);
+ PY_DICT_ADD_INT(GL_LUMINANCE4);
+ PY_DICT_ADD_INT(GL_LUMINANCE4_ALPHA4);
+ PY_DICT_ADD_INT(GL_LUMINANCE6_ALPHA2);
+ PY_DICT_ADD_INT(GL_LUMINANCE8);
+ PY_DICT_ADD_INT(GL_LUMINANCE8_ALPHA8);
+ PY_DICT_ADD_INT(GL_LUMINANCE_ALPHA);
+ PY_DICT_ADD_INT(GL_MAP1_COLOR_4);
+ PY_DICT_ADD_INT(GL_MAP1_GRID_DOMAIN);
+ PY_DICT_ADD_INT(GL_MAP1_GRID_SEGMENTS);
+ PY_DICT_ADD_INT(GL_MAP1_INDEX);
+ PY_DICT_ADD_INT(GL_MAP1_NORMAL);
+ PY_DICT_ADD_INT(GL_MAP1_TEXTURE_COORD_1);
+ PY_DICT_ADD_INT(GL_MAP1_TEXTURE_COORD_2);
+ PY_DICT_ADD_INT(GL_MAP1_TEXTURE_COORD_3);
+ PY_DICT_ADD_INT(GL_MAP1_TEXTURE_COORD_4);
+ PY_DICT_ADD_INT(GL_MAP1_VERTEX_3);
+ PY_DICT_ADD_INT(GL_MAP1_VERTEX_4);
+ PY_DICT_ADD_INT(GL_MAP2_COLOR_4);
+ PY_DICT_ADD_INT(GL_MAP2_GRID_DOMAIN);
+ PY_DICT_ADD_INT(GL_MAP2_GRID_SEGMENTS);
+ PY_DICT_ADD_INT(GL_MAP2_INDEX);
+ PY_DICT_ADD_INT(GL_MAP2_NORMAL);
+ PY_DICT_ADD_INT(GL_MAP2_TEXTURE_COORD_1);
+ PY_DICT_ADD_INT(GL_MAP2_TEXTURE_COORD_2);
+ PY_DICT_ADD_INT(GL_MAP2_TEXTURE_COORD_3);
+ PY_DICT_ADD_INT(GL_MAP2_TEXTURE_COORD_4);
+ PY_DICT_ADD_INT(GL_MAP2_VERTEX_3);
+ PY_DICT_ADD_INT(GL_MAP2_VERTEX_4);
+ PY_DICT_ADD_INT(GL_MAP_COLOR);
+ PY_DICT_ADD_INT(GL_MAP_STENCIL);
+ PY_DICT_ADD_INT(GL_MATRIX_MODE);
+ PY_DICT_ADD_INT(GL_MAX_ATTRIB_STACK_DEPTH);
+ PY_DICT_ADD_INT(GL_MAX_CLIENT_ATTRIB_STACK_DEPTH);
+ PY_DICT_ADD_INT(GL_MAX_CLIP_PLANES);
+ PY_DICT_ADD_INT(GL_MAX_EVAL_ORDER);
+ PY_DICT_ADD_INT(GL_MAX_LIGHTS);
+ PY_DICT_ADD_INT(GL_MAX_LIST_NESTING);
+ PY_DICT_ADD_INT(GL_MAX_MODELVIEW_STACK_DEPTH);
+ PY_DICT_ADD_INT(GL_MAX_NAME_STACK_DEPTH);
+ PY_DICT_ADD_INT(GL_MAX_PIXEL_MAP_TABLE);
+ PY_DICT_ADD_INT(GL_MAX_PROJECTION_STACK_DEPTH);
+ PY_DICT_ADD_INT(GL_MAX_TEXTURE_STACK_DEPTH);
+ PY_DICT_ADD_INT(GL_MODELVIEW);
+ PY_DICT_ADD_INT(GL_MODELVIEW_MATRIX);
+ PY_DICT_ADD_INT(GL_MODELVIEW_STACK_DEPTH);
+ PY_DICT_ADD_INT(GL_MODULATE);
+ PY_DICT_ADD_INT(GL_MULT);
+ PY_DICT_ADD_INT(GL_N3F_V3F);
+ PY_DICT_ADD_INT(GL_NAME_STACK_DEPTH);
+ PY_DICT_ADD_INT(GL_NORMALIZE);
+ PY_DICT_ADD_INT(GL_NORMAL_ARRAY);
+ PY_DICT_ADD_INT(GL_NORMAL_ARRAY_POINTER);
+ PY_DICT_ADD_INT(GL_NORMAL_ARRAY_STRIDE);
+ PY_DICT_ADD_INT(GL_NORMAL_ARRAY_TYPE);
+ PY_DICT_ADD_INT(GL_OBJECT_LINEAR);
+ PY_DICT_ADD_INT(GL_OBJECT_PLANE);
+ PY_DICT_ADD_INT(GL_ORDER);
+ PY_DICT_ADD_INT(GL_PASS_THROUGH_TOKEN);
+ PY_DICT_ADD_INT(GL_PERSPECTIVE_CORRECTION_HINT);
+ PY_DICT_ADD_INT(GL_PIXEL_MAP_A_TO_A);
+ PY_DICT_ADD_INT(GL_PIXEL_MAP_A_TO_A_SIZE);
+ PY_DICT_ADD_INT(GL_PIXEL_MAP_B_TO_B);
+ PY_DICT_ADD_INT(GL_PIXEL_MAP_B_TO_B_SIZE);
+ PY_DICT_ADD_INT(GL_PIXEL_MAP_G_TO_G);
+ PY_DICT_ADD_INT(GL_PIXEL_MAP_G_TO_G_SIZE);
+ PY_DICT_ADD_INT(GL_PIXEL_MAP_I_TO_A);
+ PY_DICT_ADD_INT(GL_PIXEL_MAP_I_TO_A_SIZE);
+ PY_DICT_ADD_INT(GL_PIXEL_MAP_I_TO_B);
+ PY_DICT_ADD_INT(GL_PIXEL_MAP_I_TO_B_SIZE);
+ PY_DICT_ADD_INT(GL_PIXEL_MAP_I_TO_G);
+ PY_DICT_ADD_INT(GL_PIXEL_MAP_I_TO_G_SIZE);
+ PY_DICT_ADD_INT(GL_PIXEL_MAP_I_TO_I);
+ PY_DICT_ADD_INT(GL_PIXEL_MAP_I_TO_I_SIZE);
+ PY_DICT_ADD_INT(GL_PIXEL_MAP_I_TO_R);
+ PY_DICT_ADD_INT(GL_PIXEL_MAP_I_TO_R_SIZE);
+ PY_DICT_ADD_INT(GL_PIXEL_MAP_R_TO_R);
+ PY_DICT_ADD_INT(GL_PIXEL_MAP_R_TO_R_SIZE);
+ PY_DICT_ADD_INT(GL_PIXEL_MAP_S_TO_S);
+ PY_DICT_ADD_INT(GL_PIXEL_MAP_S_TO_S_SIZE);
+ PY_DICT_ADD_INT(GL_PIXEL_MODE_BIT);
+ PY_DICT_ADD_INT(GL_POINT_BIT);
+ PY_DICT_ADD_INT(GL_POINT_SMOOTH);
+ PY_DICT_ADD_INT(GL_POINT_SMOOTH_HINT);
+ PY_DICT_ADD_INT(GL_POINT_TOKEN);
+ PY_DICT_ADD_INT(GL_POLYGON);
+ PY_DICT_ADD_INT(GL_POLYGON_BIT);
+ PY_DICT_ADD_INT(GL_POLYGON_STIPPLE);
+ PY_DICT_ADD_INT(GL_POLYGON_STIPPLE_BIT);
+ PY_DICT_ADD_INT(GL_POLYGON_TOKEN);
+ PY_DICT_ADD_INT(GL_POSITION);
+ PY_DICT_ADD_INT(GL_PROJECTION);
+ PY_DICT_ADD_INT(GL_PROJECTION_MATRIX);
+ PY_DICT_ADD_INT(GL_PROJECTION_STACK_DEPTH);
+ PY_DICT_ADD_INT(GL_Q);
+ PY_DICT_ADD_INT(GL_QUADRATIC_ATTENUATION);
+ PY_DICT_ADD_INT(GL_QUADS);
+ PY_DICT_ADD_INT(GL_QUAD_STRIP);
+ PY_DICT_ADD_INT(GL_R);
+ PY_DICT_ADD_INT(GL_RED_BIAS);
+ PY_DICT_ADD_INT(GL_RED_BITS);
+ PY_DICT_ADD_INT(GL_RED_SCALE);
+ PY_DICT_ADD_INT(GL_RENDER);
+ PY_DICT_ADD_INT(GL_RENDER_MODE);
+ PY_DICT_ADD_INT(GL_RETURN);
+ PY_DICT_ADD_INT(GL_RGBA_MODE);
+ PY_DICT_ADD_INT(GL_S);
+ PY_DICT_ADD_INT(GL_SCISSOR_BIT);
+ PY_DICT_ADD_INT(GL_SELECT);
+ PY_DICT_ADD_INT(GL_SELECTION_BUFFER_POINTER);
+ PY_DICT_ADD_INT(GL_SELECTION_BUFFER_SIZE);
+ PY_DICT_ADD_INT(GL_SHADE_MODEL);
+ PY_DICT_ADD_INT(GL_SHININESS);
+ PY_DICT_ADD_INT(GL_SMOOTH);
+ PY_DICT_ADD_INT(GL_SPECULAR);
+ PY_DICT_ADD_INT(GL_SPHERE_MAP);
+ PY_DICT_ADD_INT(GL_SPOT_CUTOFF);
+ PY_DICT_ADD_INT(GL_SPOT_DIRECTION);
+ PY_DICT_ADD_INT(GL_SPOT_EXPONENT);
+ PY_DICT_ADD_INT(GL_STACK_OVERFLOW);
+ PY_DICT_ADD_INT(GL_STACK_UNDERFLOW);
+ PY_DICT_ADD_INT(GL_STENCIL_BITS);
+ PY_DICT_ADD_INT(GL_T);
+ PY_DICT_ADD_INT(GL_T2F_C3F_V3F);
+ PY_DICT_ADD_INT(GL_T2F_C4F_N3F_V3F);
+ PY_DICT_ADD_INT(GL_T2F_C4UB_V3F);
+ PY_DICT_ADD_INT(GL_T2F_N3F_V3F);
+ PY_DICT_ADD_INT(GL_T2F_V3F);
+ PY_DICT_ADD_INT(GL_T4F_C4F_N3F_V4F);
+ PY_DICT_ADD_INT(GL_T4F_V4F);
+ PY_DICT_ADD_INT(GL_TEXTURE_BIT);
+ PY_DICT_ADD_INT(GL_TEXTURE_BORDER);
+ PY_DICT_ADD_INT(GL_TEXTURE_COMPONENTS);
+ PY_DICT_ADD_INT(GL_TEXTURE_COORD_ARRAY);
+ PY_DICT_ADD_INT(GL_TEXTURE_COORD_ARRAY_POINTER);
+ PY_DICT_ADD_INT(GL_TEXTURE_COORD_ARRAY_SIZE);
+ PY_DICT_ADD_INT(GL_TEXTURE_COORD_ARRAY_STRIDE);
+ PY_DICT_ADD_INT(GL_TEXTURE_COORD_ARRAY_TYPE);
+ PY_DICT_ADD_INT(GL_TEXTURE_ENV);
+ PY_DICT_ADD_INT(GL_TEXTURE_ENV_COLOR);
+ PY_DICT_ADD_INT(GL_TEXTURE_ENV_MODE);
+ PY_DICT_ADD_INT(GL_TEXTURE_GEN_MODE);
+ PY_DICT_ADD_INT(GL_TEXTURE_GEN_Q);
+ PY_DICT_ADD_INT(GL_TEXTURE_GEN_R);
+ PY_DICT_ADD_INT(GL_TEXTURE_GEN_S);
+ PY_DICT_ADD_INT(GL_TEXTURE_GEN_T);
+ PY_DICT_ADD_INT(GL_TEXTURE_INTENSITY_SIZE);
+ PY_DICT_ADD_INT(GL_TEXTURE_LUMINANCE_SIZE);
+ PY_DICT_ADD_INT(GL_TEXTURE_MATRIX);
+ PY_DICT_ADD_INT(GL_TEXTURE_PRIORITY);
+ PY_DICT_ADD_INT(GL_TEXTURE_RESIDENT);
+ PY_DICT_ADD_INT(GL_TEXTURE_STACK_DEPTH);
+ PY_DICT_ADD_INT(GL_TRANSFORM_BIT);
+ PY_DICT_ADD_INT(GL_V2F);
+ PY_DICT_ADD_INT(GL_V3F);
+ PY_DICT_ADD_INT(GL_VERTEX_ARRAY);
+ PY_DICT_ADD_INT(GL_VERTEX_ARRAY_POINTER);
+ PY_DICT_ADD_INT(GL_VERTEX_ARRAY_SIZE);
+ PY_DICT_ADD_INT(GL_VERTEX_ARRAY_STRIDE);
+ PY_DICT_ADD_INT(GL_VERTEX_ARRAY_TYPE);
+ PY_DICT_ADD_INT(GL_VIEWPORT_BIT);
+ PY_DICT_ADD_INT(GL_ZOOM_X);
+ PY_DICT_ADD_INT(GL_ZOOM_Y);
+ }
+
+
+ /* GL_VERSION_1_2 */
+ {
+ PY_DICT_ADD_INT(GL_ALIASED_LINE_WIDTH_RANGE);
+ PY_DICT_ADD_INT(GL_BGR);
+ PY_DICT_ADD_INT(GL_BGRA);
+ PY_DICT_ADD_INT(GL_CLAMP_TO_EDGE);
+ PY_DICT_ADD_INT(GL_MAX_3D_TEXTURE_SIZE);
+ PY_DICT_ADD_INT(GL_MAX_ELEMENTS_INDICES);
+ PY_DICT_ADD_INT(GL_MAX_ELEMENTS_VERTICES);
+ PY_DICT_ADD_INT(GL_PACK_IMAGE_HEIGHT);
+ PY_DICT_ADD_INT(GL_PACK_SKIP_IMAGES);
+ PY_DICT_ADD_INT(GL_PROXY_TEXTURE_3D);
+ PY_DICT_ADD_INT(GL_SMOOTH_LINE_WIDTH_GRANULARITY);
+ PY_DICT_ADD_INT(GL_SMOOTH_LINE_WIDTH_RANGE);
+ PY_DICT_ADD_INT(GL_SMOOTH_POINT_SIZE_GRANULARITY);
+ PY_DICT_ADD_INT(GL_SMOOTH_POINT_SIZE_RANGE);
+ PY_DICT_ADD_INT(GL_TEXTURE_3D);
+ PY_DICT_ADD_INT(GL_TEXTURE_BASE_LEVEL);
+ PY_DICT_ADD_INT(GL_TEXTURE_BINDING_3D);
+ PY_DICT_ADD_INT(GL_TEXTURE_DEPTH);
+ PY_DICT_ADD_INT(GL_TEXTURE_MAX_LEVEL);
+ PY_DICT_ADD_INT(GL_TEXTURE_MAX_LOD);
+ PY_DICT_ADD_INT(GL_TEXTURE_MIN_LOD);
+ PY_DICT_ADD_INT(GL_TEXTURE_WRAP_R);
+ PY_DICT_ADD_INT(GL_UNPACK_IMAGE_HEIGHT);
+ PY_DICT_ADD_INT(GL_UNPACK_SKIP_IMAGES);
+ PY_DICT_ADD_INT(GL_UNSIGNED_BYTE_2_3_3_REV);
+ PY_DICT_ADD_INT(GL_UNSIGNED_BYTE_3_3_2);
+ PY_DICT_ADD_INT(GL_UNSIGNED_INT_10_10_10_2);
+ PY_DICT_ADD_INT(GL_UNSIGNED_INT_2_10_10_10_REV);
+ PY_DICT_ADD_INT(GL_UNSIGNED_INT_8_8_8_8);
+ PY_DICT_ADD_INT(GL_UNSIGNED_INT_8_8_8_8_REV);
+ PY_DICT_ADD_INT(GL_UNSIGNED_SHORT_1_5_5_5_REV);
+ PY_DICT_ADD_INT(GL_UNSIGNED_SHORT_4_4_4_4);
+ PY_DICT_ADD_INT(GL_UNSIGNED_SHORT_4_4_4_4_REV);
+ PY_DICT_ADD_INT(GL_UNSIGNED_SHORT_5_5_5_1);
+ PY_DICT_ADD_INT(GL_UNSIGNED_SHORT_5_6_5);
+ PY_DICT_ADD_INT(GL_UNSIGNED_SHORT_5_6_5_REV);
+ }
+ /* adding in GL_VERSION_1_2 removed from core profile */
+ if (use_deprecated == true) {
+ PY_DICT_ADD_INT(GL_ALIASED_POINT_SIZE_RANGE);
+ PY_DICT_ADD_INT(GL_LIGHT_MODEL_COLOR_CONTROL);
+ PY_DICT_ADD_INT(GL_RESCALE_NORMAL);
+ PY_DICT_ADD_INT(GL_SEPARATE_SPECULAR_COLOR);
+ PY_DICT_ADD_INT(GL_SINGLE_COLOR);
+ }
+
+
+ /* GL_VERSION_1_3 */
+ {
+ PY_DICT_ADD_INT(GL_ACTIVE_TEXTURE);
+ PY_DICT_ADD_INT(GL_CLAMP_TO_BORDER);
+ PY_DICT_ADD_INT(GL_COMPRESSED_RGB);
+ PY_DICT_ADD_INT(GL_COMPRESSED_RGBA);
+ PY_DICT_ADD_INT(GL_COMPRESSED_TEXTURE_FORMATS);
+ PY_DICT_ADD_INT(GL_MAX_CUBE_MAP_TEXTURE_SIZE);
+ PY_DICT_ADD_INT(GL_MULTISAMPLE);
+ PY_DICT_ADD_INT(GL_NUM_COMPRESSED_TEXTURE_FORMATS);
+ PY_DICT_ADD_INT(GL_PROXY_TEXTURE_CUBE_MAP);
+ PY_DICT_ADD_INT(GL_SAMPLES);
+ PY_DICT_ADD_INT(GL_SAMPLE_ALPHA_TO_COVERAGE);
+ PY_DICT_ADD_INT(GL_SAMPLE_ALPHA_TO_ONE);
+ PY_DICT_ADD_INT(GL_SAMPLE_BUFFERS);
+ PY_DICT_ADD_INT(GL_SAMPLE_COVERAGE);
+ PY_DICT_ADD_INT(GL_SAMPLE_COVERAGE_INVERT);
+ PY_DICT_ADD_INT(GL_SAMPLE_COVERAGE_VALUE);
+ PY_DICT_ADD_INT(GL_TEXTURE0);
+ PY_DICT_ADD_INT(GL_TEXTURE1);
+ PY_DICT_ADD_INT(GL_TEXTURE10);
+ PY_DICT_ADD_INT(GL_TEXTURE11);
+ PY_DICT_ADD_INT(GL_TEXTURE12);
+ PY_DICT_ADD_INT(GL_TEXTURE13);
+ PY_DICT_ADD_INT(GL_TEXTURE14);
+ PY_DICT_ADD_INT(GL_TEXTURE15);
+ PY_DICT_ADD_INT(GL_TEXTURE16);
+ PY_DICT_ADD_INT(GL_TEXTURE17);
+ PY_DICT_ADD_INT(GL_TEXTURE18);
+ PY_DICT_ADD_INT(GL_TEXTURE19);
+ PY_DICT_ADD_INT(GL_TEXTURE2);
+ PY_DICT_ADD_INT(GL_TEXTURE20);
+ PY_DICT_ADD_INT(GL_TEXTURE21);
+ PY_DICT_ADD_INT(GL_TEXTURE22);
+ PY_DICT_ADD_INT(GL_TEXTURE23);
+ PY_DICT_ADD_INT(GL_TEXTURE24);
+ PY_DICT_ADD_INT(GL_TEXTURE25);
+ PY_DICT_ADD_INT(GL_TEXTURE26);
+ PY_DICT_ADD_INT(GL_TEXTURE27);
+ PY_DICT_ADD_INT(GL_TEXTURE28);
+ PY_DICT_ADD_INT(GL_TEXTURE29);
+ PY_DICT_ADD_INT(GL_TEXTURE3);
+ PY_DICT_ADD_INT(GL_TEXTURE30);
+ PY_DICT_ADD_INT(GL_TEXTURE31);
+ PY_DICT_ADD_INT(GL_TEXTURE4);
+ PY_DICT_ADD_INT(GL_TEXTURE5);
+ PY_DICT_ADD_INT(GL_TEXTURE6);
+ PY_DICT_ADD_INT(GL_TEXTURE7);
+ PY_DICT_ADD_INT(GL_TEXTURE8);
+ PY_DICT_ADD_INT(GL_TEXTURE9);
+ PY_DICT_ADD_INT(GL_TEXTURE_BINDING_CUBE_MAP);
+ PY_DICT_ADD_INT(GL_TEXTURE_COMPRESSED);
+ PY_DICT_ADD_INT(GL_TEXTURE_COMPRESSED_IMAGE_SIZE);
+ PY_DICT_ADD_INT(GL_TEXTURE_COMPRESSION_HINT);
+ PY_DICT_ADD_INT(GL_TEXTURE_CUBE_MAP);
+ PY_DICT_ADD_INT(GL_TEXTURE_CUBE_MAP_NEGATIVE_X);
+ PY_DICT_ADD_INT(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y);
+ PY_DICT_ADD_INT(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z);
+ PY_DICT_ADD_INT(GL_TEXTURE_CUBE_MAP_POSITIVE_X);
+ PY_DICT_ADD_INT(GL_TEXTURE_CUBE_MAP_POSITIVE_Y);
+ PY_DICT_ADD_INT(GL_TEXTURE_CUBE_MAP_POSITIVE_Z);
+ }
+ /* adding in GL_VERSION_1_3 removed from core profile */
+ if (use_deprecated == true) {
+ PY_DICT_ADD_INT(GL_ADD_SIGNED);
+ PY_DICT_ADD_INT(GL_CLIENT_ACTIVE_TEXTURE);
+ PY_DICT_ADD_INT(GL_COMBINE);
+ PY_DICT_ADD_INT(GL_COMBINE_ALPHA);
+ PY_DICT_ADD_INT(GL_COMBINE_RGB);
+ PY_DICT_ADD_INT(GL_COMPRESSED_ALPHA);
+ PY_DICT_ADD_INT(GL_COMPRESSED_INTENSITY);
+ PY_DICT_ADD_INT(GL_COMPRESSED_LUMINANCE);
+ PY_DICT_ADD_INT(GL_COMPRESSED_LUMINANCE_ALPHA);
+ PY_DICT_ADD_INT(GL_CONSTANT);
+ PY_DICT_ADD_INT(GL_DOT3_RGB);
+ PY_DICT_ADD_INT(GL_DOT3_RGBA);
+ PY_DICT_ADD_INT(GL_INTERPOLATE);
+ PY_DICT_ADD_INT(GL_MAX_TEXTURE_UNITS);
+ PY_DICT_ADD_INT(GL_MULTISAMPLE_BIT);
+ PY_DICT_ADD_INT(GL_NORMAL_MAP);
+ PY_DICT_ADD_INT(GL_OPERAND0_ALPHA);
+ PY_DICT_ADD_INT(GL_OPERAND0_RGB);
+ PY_DICT_ADD_INT(GL_OPERAND1_ALPHA);
+ PY_DICT_ADD_INT(GL_OPERAND1_RGB);
+ PY_DICT_ADD_INT(GL_OPERAND2_ALPHA);
+ PY_DICT_ADD_INT(GL_OPERAND2_RGB);
+ PY_DICT_ADD_INT(GL_PREVIOUS);
+ PY_DICT_ADD_INT(GL_PRIMARY_COLOR);
+ PY_DICT_ADD_INT(GL_REFLECTION_MAP);
+ PY_DICT_ADD_INT(GL_RGB_SCALE);
+ PY_DICT_ADD_INT(GL_SOURCE0_ALPHA);
+ PY_DICT_ADD_INT(GL_SOURCE0_RGB);
+ PY_DICT_ADD_INT(GL_SOURCE1_ALPHA);
+ PY_DICT_ADD_INT(GL_SOURCE1_RGB);
+ PY_DICT_ADD_INT(GL_SOURCE2_ALPHA);
+ PY_DICT_ADD_INT(GL_SOURCE2_RGB);
+ PY_DICT_ADD_INT(GL_SUBTRACT);
+ PY_DICT_ADD_INT(GL_TRANSPOSE_COLOR_MATRIX);
+ PY_DICT_ADD_INT(GL_TRANSPOSE_MODELVIEW_MATRIX);
+ PY_DICT_ADD_INT(GL_TRANSPOSE_PROJECTION_MATRIX);
+ PY_DICT_ADD_INT(GL_TRANSPOSE_TEXTURE_MATRIX);
+ }
+
+
+ /* GL_VERSION_1_4 */
+ {
+ PY_DICT_ADD_INT(GL_BLEND_DST_ALPHA);
+ PY_DICT_ADD_INT(GL_BLEND_DST_RGB);
+ PY_DICT_ADD_INT(GL_BLEND_SRC_ALPHA);
+ PY_DICT_ADD_INT(GL_BLEND_SRC_RGB);
+ PY_DICT_ADD_INT(GL_CONSTANT_ALPHA);
+ PY_DICT_ADD_INT(GL_CONSTANT_COLOR);
+ PY_DICT_ADD_INT(GL_DECR_WRAP);
+ PY_DICT_ADD_INT(GL_DEPTH_COMPONENT16);
+ PY_DICT_ADD_INT(GL_DEPTH_COMPONENT24);
+ PY_DICT_ADD_INT(GL_DEPTH_COMPONENT32);
+ PY_DICT_ADD_INT(GL_FUNC_ADD);
+ PY_DICT_ADD_INT(GL_FUNC_REVERSE_SUBTRACT);
+ PY_DICT_ADD_INT(GL_FUNC_SUBTRACT);
+ PY_DICT_ADD_INT(GL_INCR_WRAP);
+ PY_DICT_ADD_INT(GL_MAX);
+ PY_DICT_ADD_INT(GL_MAX_TEXTURE_LOD_BIAS);
+ PY_DICT_ADD_INT(GL_MIN);
+ PY_DICT_ADD_INT(GL_MIRRORED_REPEAT);
+ PY_DICT_ADD_INT(GL_ONE_MINUS_CONSTANT_ALPHA);
+ PY_DICT_ADD_INT(GL_ONE_MINUS_CONSTANT_COLOR);
+ PY_DICT_ADD_INT(GL_POINT_FADE_THRESHOLD_SIZE);
+ PY_DICT_ADD_INT(GL_TEXTURE_COMPARE_FUNC);
+ PY_DICT_ADD_INT(GL_TEXTURE_COMPARE_MODE);
+ PY_DICT_ADD_INT(GL_TEXTURE_DEPTH_SIZE);
+ PY_DICT_ADD_INT(GL_TEXTURE_LOD_BIAS);
+ }
+ /* adding in GL_VERSION_1_4 removed from core profile */
+ if (use_deprecated == true) {
+ PY_DICT_ADD_INT(GL_COLOR_SUM);
+ PY_DICT_ADD_INT(GL_COMPARE_R_TO_TEXTURE);
+ PY_DICT_ADD_INT(GL_CURRENT_FOG_COORDINATE);
+ PY_DICT_ADD_INT(GL_CURRENT_SECONDARY_COLOR);
+ PY_DICT_ADD_INT(GL_DEPTH_TEXTURE_MODE);
+ PY_DICT_ADD_INT(GL_FOG_COORDINATE);
+ PY_DICT_ADD_INT(GL_FOG_COORDINATE_ARRAY);
+ PY_DICT_ADD_INT(GL_FOG_COORDINATE_ARRAY_POINTER);
+ PY_DICT_ADD_INT(GL_FOG_COORDINATE_ARRAY_STRIDE);
+ PY_DICT_ADD_INT(GL_FOG_COORDINATE_ARRAY_TYPE);
+ PY_DICT_ADD_INT(GL_FOG_COORDINATE_SOURCE);
+ PY_DICT_ADD_INT(GL_FRAGMENT_DEPTH);
+ PY_DICT_ADD_INT(GL_GENERATE_MIPMAP);
+ PY_DICT_ADD_INT(GL_GENERATE_MIPMAP_HINT);
+ PY_DICT_ADD_INT(GL_POINT_DISTANCE_ATTENUATION);
+ PY_DICT_ADD_INT(GL_POINT_SIZE_MAX);
+ PY_DICT_ADD_INT(GL_POINT_SIZE_MIN);
+ PY_DICT_ADD_INT(GL_SECONDARY_COLOR_ARRAY);
+ PY_DICT_ADD_INT(GL_SECONDARY_COLOR_ARRAY_POINTER);
+ PY_DICT_ADD_INT(GL_SECONDARY_COLOR_ARRAY_SIZE);
+ PY_DICT_ADD_INT(GL_SECONDARY_COLOR_ARRAY_STRIDE);
+ PY_DICT_ADD_INT(GL_SECONDARY_COLOR_ARRAY_TYPE);
+ PY_DICT_ADD_INT(GL_TEXTURE_FILTER_CONTROL);
+ }
+
+
+ /* GL_VERSION_1_5 */
+ {
+ PY_DICT_ADD_INT(GL_ARRAY_BUFFER);
+ PY_DICT_ADD_INT(GL_ARRAY_BUFFER_BINDING);
+ PY_DICT_ADD_INT(GL_BUFFER_ACCESS);
+ PY_DICT_ADD_INT(GL_BUFFER_MAPPED);
+ PY_DICT_ADD_INT(GL_BUFFER_MAP_POINTER);
+ PY_DICT_ADD_INT(GL_BUFFER_SIZE);
+ PY_DICT_ADD_INT(GL_BUFFER_USAGE);
+ PY_DICT_ADD_INT(GL_CURRENT_QUERY);
+ PY_DICT_ADD_INT(GL_DYNAMIC_COPY);
+ PY_DICT_ADD_INT(GL_DYNAMIC_DRAW);
+ PY_DICT_ADD_INT(GL_DYNAMIC_READ);
+ PY_DICT_ADD_INT(GL_ELEMENT_ARRAY_BUFFER);
+ PY_DICT_ADD_INT(GL_ELEMENT_ARRAY_BUFFER_BINDING);
+ PY_DICT_ADD_INT(GL_QUERY_COUNTER_BITS);
+ PY_DICT_ADD_INT(GL_QUERY_RESULT);
+ PY_DICT_ADD_INT(GL_QUERY_RESULT_AVAILABLE);
+ PY_DICT_ADD_INT(GL_READ_ONLY);
+ PY_DICT_ADD_INT(GL_READ_WRITE);
+ PY_DICT_ADD_INT(GL_SAMPLES_PASSED);
+ PY_DICT_ADD_INT(GL_SRC1_ALPHA);
+ PY_DICT_ADD_INT(GL_STATIC_COPY);
+ PY_DICT_ADD_INT(GL_STATIC_DRAW);
+ PY_DICT_ADD_INT(GL_STATIC_READ);
+ PY_DICT_ADD_INT(GL_STREAM_COPY);
+ PY_DICT_ADD_INT(GL_STREAM_DRAW);
+ PY_DICT_ADD_INT(GL_STREAM_READ);
+ PY_DICT_ADD_INT(GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING);
+ PY_DICT_ADD_INT(GL_WRITE_ONLY);
+ }
+ /* adding in GL_VERSION_1_5 removed from core profile */
+ if (use_deprecated == true) {
+ PY_DICT_ADD_INT(GL_COLOR_ARRAY_BUFFER_BINDING);
+ PY_DICT_ADD_INT(GL_CURRENT_FOG_COORD);
+ PY_DICT_ADD_INT(GL_EDGE_FLAG_ARRAY_BUFFER_BINDING);
+ PY_DICT_ADD_INT(GL_FOG_COORD);
+ PY_DICT_ADD_INT(GL_FOG_COORDINATE_ARRAY_BUFFER_BINDING);
+ PY_DICT_ADD_INT(GL_FOG_COORD_ARRAY);
+ PY_DICT_ADD_INT(GL_FOG_COORD_ARRAY_BUFFER_BINDING);
+ PY_DICT_ADD_INT(GL_FOG_COORD_ARRAY_POINTER);
+ PY_DICT_ADD_INT(GL_FOG_COORD_ARRAY_STRIDE);
+ PY_DICT_ADD_INT(GL_FOG_COORD_ARRAY_TYPE);
+ PY_DICT_ADD_INT(GL_FOG_COORD_SRC);
+ PY_DICT_ADD_INT(GL_INDEX_ARRAY_BUFFER_BINDING);
+ PY_DICT_ADD_INT(GL_NORMAL_ARRAY_BUFFER_BINDING);
+ PY_DICT_ADD_INT(GL_SECONDARY_COLOR_ARRAY_BUFFER_BINDING);
+ PY_DICT_ADD_INT(GL_SRC0_ALPHA);
+ PY_DICT_ADD_INT(GL_SRC0_RGB);
+ PY_DICT_ADD_INT(GL_SRC1_RGB);
+ PY_DICT_ADD_INT(GL_SRC2_ALPHA);
+ PY_DICT_ADD_INT(GL_SRC2_RGB);
+ PY_DICT_ADD_INT(GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING);
+ PY_DICT_ADD_INT(GL_VERTEX_ARRAY_BUFFER_BINDING);
+ PY_DICT_ADD_INT(GL_WEIGHT_ARRAY_BUFFER_BINDING);
+ }
+
+
+ /* GL_VERSION_2_0 */
+ {
+ PY_DICT_ADD_INT(GL_ACTIVE_ATTRIBUTES);
+ PY_DICT_ADD_INT(GL_ACTIVE_ATTRIBUTE_MAX_LENGTH);
+ PY_DICT_ADD_INT(GL_ACTIVE_UNIFORMS);
+ PY_DICT_ADD_INT(GL_ACTIVE_UNIFORM_MAX_LENGTH);
+ PY_DICT_ADD_INT(GL_ATTACHED_SHADERS);
+ PY_DICT_ADD_INT(GL_BLEND_EQUATION_ALPHA);
+ PY_DICT_ADD_INT(GL_BLEND_EQUATION_RGB);
+ PY_DICT_ADD_INT(GL_BOOL);
+ PY_DICT_ADD_INT(GL_BOOL_VEC2);
+ PY_DICT_ADD_INT(GL_BOOL_VEC3);
+ PY_DICT_ADD_INT(GL_BOOL_VEC4);
+ PY_DICT_ADD_INT(GL_COMPILE_STATUS);
+ PY_DICT_ADD_INT(GL_CURRENT_PROGRAM);
+ PY_DICT_ADD_INT(GL_CURRENT_VERTEX_ATTRIB);
+ PY_DICT_ADD_INT(GL_DELETE_STATUS);
+ PY_DICT_ADD_INT(GL_DRAW_BUFFER0);
+ PY_DICT_ADD_INT(GL_DRAW_BUFFER1);
+ PY_DICT_ADD_INT(GL_DRAW_BUFFER10);
+ PY_DICT_ADD_INT(GL_DRAW_BUFFER11);
+ PY_DICT_ADD_INT(GL_DRAW_BUFFER12);
+ PY_DICT_ADD_INT(GL_DRAW_BUFFER13);
+ PY_DICT_ADD_INT(GL_DRAW_BUFFER14);
+ PY_DICT_ADD_INT(GL_DRAW_BUFFER15);
+ PY_DICT_ADD_INT(GL_DRAW_BUFFER2);
+ PY_DICT_ADD_INT(GL_DRAW_BUFFER3);
+ PY_DICT_ADD_INT(GL_DRAW_BUFFER4);
+ PY_DICT_ADD_INT(GL_DRAW_BUFFER5);
+ PY_DICT_ADD_INT(GL_DRAW_BUFFER6);
+ PY_DICT_ADD_INT(GL_DRAW_BUFFER7);
+ PY_DICT_ADD_INT(GL_DRAW_BUFFER8);
+ PY_DICT_ADD_INT(GL_DRAW_BUFFER9);
+ PY_DICT_ADD_INT(GL_FLOAT_MAT2);
+ PY_DICT_ADD_INT(GL_FLOAT_MAT3);
+ PY_DICT_ADD_INT(GL_FLOAT_MAT4);
+ PY_DICT_ADD_INT(GL_FLOAT_VEC2);
+ PY_DICT_ADD_INT(GL_FLOAT_VEC3);
+ PY_DICT_ADD_INT(GL_FLOAT_VEC4);
+ PY_DICT_ADD_INT(GL_FRAGMENT_SHADER);
+ PY_DICT_ADD_INT(GL_FRAGMENT_SHADER_DERIVATIVE_HINT);
+ PY_DICT_ADD_INT(GL_INFO_LOG_LENGTH);
+ PY_DICT_ADD_INT(GL_INT_VEC2);
+ PY_DICT_ADD_INT(GL_INT_VEC3);
+ PY_DICT_ADD_INT(GL_INT_VEC4);
+ PY_DICT_ADD_INT(GL_LINK_STATUS);
+ PY_DICT_ADD_INT(GL_LOWER_LEFT);
+ PY_DICT_ADD_INT(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS);
+ PY_DICT_ADD_INT(GL_MAX_DRAW_BUFFERS);
+ PY_DICT_ADD_INT(GL_MAX_FRAGMENT_UNIFORM_COMPONENTS);
+ PY_DICT_ADD_INT(GL_MAX_TEXTURE_IMAGE_UNITS);
+ PY_DICT_ADD_INT(GL_MAX_VARYING_FLOATS);
+ PY_DICT_ADD_INT(GL_MAX_VERTEX_ATTRIBS);
+ PY_DICT_ADD_INT(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS);
+ PY_DICT_ADD_INT(GL_MAX_VERTEX_UNIFORM_COMPONENTS);
+ PY_DICT_ADD_INT(GL_POINT_SPRITE_COORD_ORIGIN);
+ PY_DICT_ADD_INT(GL_SAMPLER_1D);
+ PY_DICT_ADD_INT(GL_SAMPLER_1D_SHADOW);
+ PY_DICT_ADD_INT(GL_SAMPLER_2D);
+ PY_DICT_ADD_INT(GL_SAMPLER_2D_SHADOW);
+ PY_DICT_ADD_INT(GL_SAMPLER_3D);
+ PY_DICT_ADD_INT(GL_SAMPLER_CUBE);
+ PY_DICT_ADD_INT(GL_SHADER_SOURCE_LENGTH);
+ PY_DICT_ADD_INT(GL_SHADER_TYPE);
+ PY_DICT_ADD_INT(GL_SHADING_LANGUAGE_VERSION);
+ PY_DICT_ADD_INT(GL_STENCIL_BACK_FAIL);
+ PY_DICT_ADD_INT(GL_STENCIL_BACK_FUNC);
+ PY_DICT_ADD_INT(GL_STENCIL_BACK_PASS_DEPTH_FAIL);
+ PY_DICT_ADD_INT(GL_STENCIL_BACK_PASS_DEPTH_PASS);
+ PY_DICT_ADD_INT(GL_STENCIL_BACK_REF);
+ PY_DICT_ADD_INT(GL_STENCIL_BACK_VALUE_MASK);
+ PY_DICT_ADD_INT(GL_STENCIL_BACK_WRITEMASK);
+ PY_DICT_ADD_INT(GL_UPPER_LEFT);
+ PY_DICT_ADD_INT(GL_VALIDATE_STATUS);
+ PY_DICT_ADD_INT(GL_VERTEX_ATTRIB_ARRAY_ENABLED);
+ PY_DICT_ADD_INT(GL_VERTEX_ATTRIB_ARRAY_NORMALIZED);
+ PY_DICT_ADD_INT(GL_VERTEX_ATTRIB_ARRAY_POINTER);
+ PY_DICT_ADD_INT(GL_VERTEX_ATTRIB_ARRAY_SIZE);
+ PY_DICT_ADD_INT(GL_VERTEX_ATTRIB_ARRAY_STRIDE);
+ PY_DICT_ADD_INT(GL_VERTEX_ATTRIB_ARRAY_TYPE);
+ PY_DICT_ADD_INT(GL_VERTEX_PROGRAM_POINT_SIZE);
+ PY_DICT_ADD_INT(GL_VERTEX_SHADER);
+ }
+ /* adding in GL_VERSION_2_0 removed from core profile */
+ if (use_deprecated == true) {
+ PY_DICT_ADD_INT(GL_COORD_REPLACE);
+ PY_DICT_ADD_INT(GL_MAX_TEXTURE_COORDS);
+ PY_DICT_ADD_INT(GL_POINT_SPRITE);
+ PY_DICT_ADD_INT(GL_VERTEX_PROGRAM_TWO_SIDE);
+ }
+
+
+ /* GL_VERSION_2_1 */
+ {
+ PY_DICT_ADD_INT(GL_COMPRESSED_SRGB);
+ PY_DICT_ADD_INT(GL_COMPRESSED_SRGB_ALPHA);
+ PY_DICT_ADD_INT(GL_FLOAT_MAT2x3);
+ PY_DICT_ADD_INT(GL_FLOAT_MAT2x4);
+ PY_DICT_ADD_INT(GL_FLOAT_MAT3x2);
+ PY_DICT_ADD_INT(GL_FLOAT_MAT3x4);
+ PY_DICT_ADD_INT(GL_FLOAT_MAT4x2);
+ PY_DICT_ADD_INT(GL_FLOAT_MAT4x3);
+ PY_DICT_ADD_INT(GL_PIXEL_PACK_BUFFER);
+ PY_DICT_ADD_INT(GL_PIXEL_PACK_BUFFER_BINDING);
+ PY_DICT_ADD_INT(GL_PIXEL_UNPACK_BUFFER);
+ PY_DICT_ADD_INT(GL_PIXEL_UNPACK_BUFFER_BINDING);
+ PY_DICT_ADD_INT(GL_SRGB);
+ PY_DICT_ADD_INT(GL_SRGB8);
+ PY_DICT_ADD_INT(GL_SRGB8_ALPHA8);
+ PY_DICT_ADD_INT(GL_SRGB_ALPHA);
+ }
+ /* adding in GL_VERSION_2_1 removed from core profile */
+ if (use_deprecated == true) {
+ PY_DICT_ADD_INT(GL_COMPRESSED_SLUMINANCE);
+ PY_DICT_ADD_INT(GL_COMPRESSED_SLUMINANCE_ALPHA);
+ PY_DICT_ADD_INT(GL_CURRENT_RASTER_SECONDARY_COLOR);
+ PY_DICT_ADD_INT(GL_SLUMINANCE);
+ PY_DICT_ADD_INT(GL_SLUMINANCE8);
+ PY_DICT_ADD_INT(GL_SLUMINANCE8_ALPHA8);
+ PY_DICT_ADD_INT(GL_SLUMINANCE_ALPHA);
+ }
+
+ /* GL_VERSION_3_0 */
+ {
+ PY_DICT_ADD_INT(GL_BGRA_INTEGER);
+ PY_DICT_ADD_INT(GL_BGR_INTEGER);
+ PY_DICT_ADD_INT(GL_BLUE_INTEGER);
+ PY_DICT_ADD_INT(GL_BUFFER_ACCESS_FLAGS);
+ PY_DICT_ADD_INT(GL_BUFFER_MAP_LENGTH);
+ PY_DICT_ADD_INT(GL_BUFFER_MAP_OFFSET);
+ PY_DICT_ADD_INT(GL_CLAMP_READ_COLOR);
+ PY_DICT_ADD_INT(GL_CLIP_DISTANCE0);
+ PY_DICT_ADD_INT(GL_CLIP_DISTANCE1);
+ PY_DICT_ADD_INT(GL_CLIP_DISTANCE2);
+ PY_DICT_ADD_INT(GL_CLIP_DISTANCE3);
+ PY_DICT_ADD_INT(GL_CLIP_DISTANCE4);
+ PY_DICT_ADD_INT(GL_CLIP_DISTANCE5);
+#if 0
+ PY_DICT_ADD_INT(GL_CLIP_DISTANCE6);
+ PY_DICT_ADD_INT(GL_CLIP_DISTANCE7);
+#endif
+ PY_DICT_ADD_INT(GL_COLOR_ATTACHMENT0);
+ PY_DICT_ADD_INT(GL_COLOR_ATTACHMENT1);
+ PY_DICT_ADD_INT(GL_COLOR_ATTACHMENT2);
+ PY_DICT_ADD_INT(GL_COLOR_ATTACHMENT3);
+ PY_DICT_ADD_INT(GL_COLOR_ATTACHMENT4);
+ PY_DICT_ADD_INT(GL_COLOR_ATTACHMENT5);
+ PY_DICT_ADD_INT(GL_COLOR_ATTACHMENT6);
+ PY_DICT_ADD_INT(GL_COLOR_ATTACHMENT7);
+ PY_DICT_ADD_INT(GL_COLOR_ATTACHMENT8);
+ PY_DICT_ADD_INT(GL_COLOR_ATTACHMENT9);
+ PY_DICT_ADD_INT(GL_COLOR_ATTACHMENT10);
+ PY_DICT_ADD_INT(GL_COLOR_ATTACHMENT11);
+ PY_DICT_ADD_INT(GL_COLOR_ATTACHMENT12);
+ PY_DICT_ADD_INT(GL_COLOR_ATTACHMENT13);
+ PY_DICT_ADD_INT(GL_COLOR_ATTACHMENT14);
+ PY_DICT_ADD_INT(GL_COLOR_ATTACHMENT15);
+#if 0
+ PY_DICT_ADD_INT(GL_COLOR_ATTACHMENT16);
+ PY_DICT_ADD_INT(GL_COLOR_ATTACHMENT17);
+ PY_DICT_ADD_INT(GL_COLOR_ATTACHMENT18);
+ PY_DICT_ADD_INT(GL_COLOR_ATTACHMENT19);
+ PY_DICT_ADD_INT(GL_COLOR_ATTACHMENT20);
+ PY_DICT_ADD_INT(GL_COLOR_ATTACHMENT21);
+ PY_DICT_ADD_INT(GL_COLOR_ATTACHMENT22);
+ PY_DICT_ADD_INT(GL_COLOR_ATTACHMENT23);
+ PY_DICT_ADD_INT(GL_COLOR_ATTACHMENT24);
+ PY_DICT_ADD_INT(GL_COLOR_ATTACHMENT25);
+ PY_DICT_ADD_INT(GL_COLOR_ATTACHMENT26);
+ PY_DICT_ADD_INT(GL_COLOR_ATTACHMENT27);
+ PY_DICT_ADD_INT(GL_COLOR_ATTACHMENT28);
+ PY_DICT_ADD_INT(GL_COLOR_ATTACHMENT29);
+ PY_DICT_ADD_INT(GL_COLOR_ATTACHMENT30);
+ PY_DICT_ADD_INT(GL_COLOR_ATTACHMENT31);
+#endif
+ PY_DICT_ADD_INT(GL_COMPARE_REF_TO_TEXTURE);
+ PY_DICT_ADD_INT(GL_COMPRESSED_RED);
+ PY_DICT_ADD_INT(GL_COMPRESSED_RED_RGTC1);
+ PY_DICT_ADD_INT(GL_COMPRESSED_RG);
+ PY_DICT_ADD_INT(GL_COMPRESSED_RG_RGTC2);
+ PY_DICT_ADD_INT(GL_COMPRESSED_SIGNED_RED_RGTC1);
+ PY_DICT_ADD_INT(GL_COMPRESSED_SIGNED_RG_RGTC2);
+ PY_DICT_ADD_INT(GL_CONTEXT_FLAGS);
+ PY_DICT_ADD_INT(GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT);
+ PY_DICT_ADD_INT(GL_DEPTH24_STENCIL8);
+ PY_DICT_ADD_INT(GL_DEPTH32F_STENCIL8);
+ PY_DICT_ADD_INT(GL_DEPTH_ATTACHMENT);
+ PY_DICT_ADD_INT(GL_DEPTH_COMPONENT32F);
+ PY_DICT_ADD_INT(GL_DEPTH_STENCIL);
+ PY_DICT_ADD_INT(GL_DEPTH_STENCIL_ATTACHMENT);
+ PY_DICT_ADD_INT(GL_DRAW_FRAMEBUFFER);
+ PY_DICT_ADD_INT(GL_DRAW_FRAMEBUFFER_BINDING);
+ PY_DICT_ADD_INT(GL_FIXED_ONLY);
+ PY_DICT_ADD_INT(GL_FLOAT_32_UNSIGNED_INT_24_8_REV);
+ PY_DICT_ADD_INT(GL_FRAMEBUFFER);
+ PY_DICT_ADD_INT(GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE);
+ PY_DICT_ADD_INT(GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE);
+ PY_DICT_ADD_INT(GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING);
+ PY_DICT_ADD_INT(GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE);
+ PY_DICT_ADD_INT(GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE);
+ PY_DICT_ADD_INT(GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE);
+ PY_DICT_ADD_INT(GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME);
+ PY_DICT_ADD_INT(GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE);
+ PY_DICT_ADD_INT(GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE);
+ PY_DICT_ADD_INT(GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE);
+ PY_DICT_ADD_INT(GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE);
+ PY_DICT_ADD_INT(GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER);
+ PY_DICT_ADD_INT(GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL);
+ PY_DICT_ADD_INT(GL_FRAMEBUFFER_BINDING);
+ PY_DICT_ADD_INT(GL_FRAMEBUFFER_COMPLETE);
+ PY_DICT_ADD_INT(GL_FRAMEBUFFER_DEFAULT);
+ PY_DICT_ADD_INT(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT);
+ PY_DICT_ADD_INT(GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER);
+ PY_DICT_ADD_INT(GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT);
+ PY_DICT_ADD_INT(GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE);
+ PY_DICT_ADD_INT(GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER);
+ PY_DICT_ADD_INT(GL_FRAMEBUFFER_SRGB);
+ PY_DICT_ADD_INT(GL_FRAMEBUFFER_UNDEFINED);
+ PY_DICT_ADD_INT(GL_FRAMEBUFFER_UNSUPPORTED);
+ PY_DICT_ADD_INT(GL_GREEN_INTEGER);
+ PY_DICT_ADD_INT(GL_HALF_FLOAT);
+ PY_DICT_ADD_INT(GL_INDEX);
+ PY_DICT_ADD_INT(GL_INTERLEAVED_ATTRIBS);
+ PY_DICT_ADD_INT(GL_INT_SAMPLER_1D);
+ PY_DICT_ADD_INT(GL_INT_SAMPLER_1D_ARRAY);
+ PY_DICT_ADD_INT(GL_INT_SAMPLER_2D);
+ PY_DICT_ADD_INT(GL_INT_SAMPLER_2D_ARRAY);
+ PY_DICT_ADD_INT(GL_INT_SAMPLER_3D);
+ PY_DICT_ADD_INT(GL_INT_SAMPLER_CUBE);
+ PY_DICT_ADD_INT(GL_INVALID_FRAMEBUFFER_OPERATION);
+ PY_DICT_ADD_INT(GL_MAJOR_VERSION);
+ PY_DICT_ADD_INT(GL_MAP_FLUSH_EXPLICIT_BIT);
+ PY_DICT_ADD_INT(GL_MAP_INVALIDATE_BUFFER_BIT);
+ PY_DICT_ADD_INT(GL_MAP_INVALIDATE_RANGE_BIT);
+ PY_DICT_ADD_INT(GL_MAP_READ_BIT);
+ PY_DICT_ADD_INT(GL_MAP_UNSYNCHRONIZED_BIT);
+ PY_DICT_ADD_INT(GL_MAP_WRITE_BIT);
+ PY_DICT_ADD_INT(GL_MAX_ARRAY_TEXTURE_LAYERS);
+ PY_DICT_ADD_INT(GL_MAX_CLIP_DISTANCES);
+ PY_DICT_ADD_INT(GL_MAX_COLOR_ATTACHMENTS);
+ PY_DICT_ADD_INT(GL_MAX_PROGRAM_TEXEL_OFFSET);
+ PY_DICT_ADD_INT(GL_MAX_RENDERBUFFER_SIZE);
+ PY_DICT_ADD_INT(GL_MAX_SAMPLES);
+ PY_DICT_ADD_INT(GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS);
+ PY_DICT_ADD_INT(GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS);
+ PY_DICT_ADD_INT(GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS);
+ PY_DICT_ADD_INT(GL_MAX_VARYING_COMPONENTS);
+ PY_DICT_ADD_INT(GL_MINOR_VERSION);
+ PY_DICT_ADD_INT(GL_MIN_PROGRAM_TEXEL_OFFSET);
+ PY_DICT_ADD_INT(GL_NUM_EXTENSIONS);
+ PY_DICT_ADD_INT(GL_PRIMITIVES_GENERATED);
+ PY_DICT_ADD_INT(GL_PROXY_TEXTURE_1D_ARRAY);
+ PY_DICT_ADD_INT(GL_PROXY_TEXTURE_2D_ARRAY);
+ PY_DICT_ADD_INT(GL_QUERY_BY_REGION_NO_WAIT);
+ PY_DICT_ADD_INT(GL_QUERY_BY_REGION_WAIT);
+ PY_DICT_ADD_INT(GL_QUERY_NO_WAIT);
+ PY_DICT_ADD_INT(GL_QUERY_WAIT);
+ PY_DICT_ADD_INT(GL_R11F_G11F_B10F);
+ PY_DICT_ADD_INT(GL_R16);
+ PY_DICT_ADD_INT(GL_R16F);
+ PY_DICT_ADD_INT(GL_R16I);
+ PY_DICT_ADD_INT(GL_R16UI);
+ PY_DICT_ADD_INT(GL_R32F);
+ PY_DICT_ADD_INT(GL_R32I);
+ PY_DICT_ADD_INT(GL_R32UI);
+ PY_DICT_ADD_INT(GL_R8);
+ PY_DICT_ADD_INT(GL_R8I);
+ PY_DICT_ADD_INT(GL_R8UI);
+ PY_DICT_ADD_INT(GL_RASTERIZER_DISCARD);
+ PY_DICT_ADD_INT(GL_READ_FRAMEBUFFER);
+ PY_DICT_ADD_INT(GL_READ_FRAMEBUFFER_BINDING);
+ PY_DICT_ADD_INT(GL_RED_INTEGER);
+ PY_DICT_ADD_INT(GL_RENDERBUFFER);
+ PY_DICT_ADD_INT(GL_RENDERBUFFER_ALPHA_SIZE);
+ PY_DICT_ADD_INT(GL_RENDERBUFFER_BINDING);
+ PY_DICT_ADD_INT(GL_RENDERBUFFER_BLUE_SIZE);
+ PY_DICT_ADD_INT(GL_RENDERBUFFER_DEPTH_SIZE);
+ PY_DICT_ADD_INT(GL_RENDERBUFFER_GREEN_SIZE);
+ PY_DICT_ADD_INT(GL_RENDERBUFFER_HEIGHT);
+ PY_DICT_ADD_INT(GL_RENDERBUFFER_INTERNAL_FORMAT);
+ PY_DICT_ADD_INT(GL_RENDERBUFFER_RED_SIZE);
+ PY_DICT_ADD_INT(GL_RENDERBUFFER_SAMPLES);
+ PY_DICT_ADD_INT(GL_RENDERBUFFER_STENCIL_SIZE);
+ PY_DICT_ADD_INT(GL_RENDERBUFFER_WIDTH);
+ PY_DICT_ADD_INT(GL_RG);
+ PY_DICT_ADD_INT(GL_RG16);
+ PY_DICT_ADD_INT(GL_RG16F);
+ PY_DICT_ADD_INT(GL_RG16I);
+ PY_DICT_ADD_INT(GL_RG16UI);
+ PY_DICT_ADD_INT(GL_RG32F);
+ PY_DICT_ADD_INT(GL_RG32I);
+ PY_DICT_ADD_INT(GL_RG32UI);
+ PY_DICT_ADD_INT(GL_RG8);
+ PY_DICT_ADD_INT(GL_RG8I);
+ PY_DICT_ADD_INT(GL_RG8UI);
+ PY_DICT_ADD_INT(GL_RGB16F);
+ PY_DICT_ADD_INT(GL_RGB16I);
+ PY_DICT_ADD_INT(GL_RGB16UI);
+ PY_DICT_ADD_INT(GL_RGB32F);
+ PY_DICT_ADD_INT(GL_RGB32I);
+ PY_DICT_ADD_INT(GL_RGB32UI);
+ PY_DICT_ADD_INT(GL_RGB8I);
+ PY_DICT_ADD_INT(GL_RGB8UI);
+ PY_DICT_ADD_INT(GL_RGB9_E5);
+ PY_DICT_ADD_INT(GL_RGBA16F);
+ PY_DICT_ADD_INT(GL_RGBA16I);
+ PY_DICT_ADD_INT(GL_RGBA16UI);
+ PY_DICT_ADD_INT(GL_RGBA32F);
+ PY_DICT_ADD_INT(GL_RGBA32I);
+ PY_DICT_ADD_INT(GL_RGBA32UI);
+ PY_DICT_ADD_INT(GL_RGBA8I);
+ PY_DICT_ADD_INT(GL_RGBA8UI);
+ PY_DICT_ADD_INT(GL_RGBA_INTEGER);
+ PY_DICT_ADD_INT(GL_RGB_INTEGER);
+ PY_DICT_ADD_INT(GL_RG_INTEGER);
+ PY_DICT_ADD_INT(GL_SAMPLER_1D_ARRAY);
+ PY_DICT_ADD_INT(GL_SAMPLER_1D_ARRAY_SHADOW);
+ PY_DICT_ADD_INT(GL_SAMPLER_2D_ARRAY);
+ PY_DICT_ADD_INT(GL_SAMPLER_2D_ARRAY_SHADOW);
+ PY_DICT_ADD_INT(GL_SAMPLER_CUBE_SHADOW);
+ PY_DICT_ADD_INT(GL_SEPARATE_ATTRIBS);
+ PY_DICT_ADD_INT(GL_STENCIL_ATTACHMENT);
+ PY_DICT_ADD_INT(GL_STENCIL_INDEX1);
+ PY_DICT_ADD_INT(GL_STENCIL_INDEX16);
+ PY_DICT_ADD_INT(GL_STENCIL_INDEX4);
+ PY_DICT_ADD_INT(GL_STENCIL_INDEX8);
+ PY_DICT_ADD_INT(GL_TEXTURE_1D_ARRAY);
+ PY_DICT_ADD_INT(GL_TEXTURE_2D_ARRAY);
+ PY_DICT_ADD_INT(GL_TEXTURE_ALPHA_TYPE);
+ PY_DICT_ADD_INT(GL_TEXTURE_BINDING_1D_ARRAY);
+ PY_DICT_ADD_INT(GL_TEXTURE_BINDING_2D_ARRAY);
+ PY_DICT_ADD_INT(GL_TEXTURE_BLUE_TYPE);
+ PY_DICT_ADD_INT(GL_TEXTURE_DEPTH_TYPE);
+ PY_DICT_ADD_INT(GL_TEXTURE_GREEN_TYPE);
+ PY_DICT_ADD_INT(GL_TEXTURE_RED_TYPE);
+ PY_DICT_ADD_INT(GL_TEXTURE_SHARED_SIZE);
+ PY_DICT_ADD_INT(GL_TEXTURE_STENCIL_SIZE);
+ PY_DICT_ADD_INT(GL_TRANSFORM_FEEDBACK_BUFFER);
+ PY_DICT_ADD_INT(GL_TRANSFORM_FEEDBACK_BUFFER_BINDING);
+ PY_DICT_ADD_INT(GL_TRANSFORM_FEEDBACK_BUFFER_MODE);
+ PY_DICT_ADD_INT(GL_TRANSFORM_FEEDBACK_BUFFER_SIZE);
+ PY_DICT_ADD_INT(GL_TRANSFORM_FEEDBACK_BUFFER_START);
+ PY_DICT_ADD_INT(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN);
+ PY_DICT_ADD_INT(GL_TRANSFORM_FEEDBACK_VARYINGS);
+ PY_DICT_ADD_INT(GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH);
+ PY_DICT_ADD_INT(GL_UNSIGNED_INT_10F_11F_11F_REV);
+ PY_DICT_ADD_INT(GL_UNSIGNED_INT_24_8);
+ PY_DICT_ADD_INT(GL_UNSIGNED_INT_5_9_9_9_REV);
+ PY_DICT_ADD_INT(GL_UNSIGNED_INT_SAMPLER_1D);
+ PY_DICT_ADD_INT(GL_UNSIGNED_INT_SAMPLER_1D_ARRAY);
+ PY_DICT_ADD_INT(GL_UNSIGNED_INT_SAMPLER_2D);
+ PY_DICT_ADD_INT(GL_UNSIGNED_INT_SAMPLER_2D_ARRAY);
+ PY_DICT_ADD_INT(GL_UNSIGNED_INT_SAMPLER_3D);
+ PY_DICT_ADD_INT(GL_UNSIGNED_INT_SAMPLER_CUBE);
+ PY_DICT_ADD_INT(GL_UNSIGNED_INT_VEC2);
+ PY_DICT_ADD_INT(GL_UNSIGNED_INT_VEC3);
+ PY_DICT_ADD_INT(GL_UNSIGNED_INT_VEC4);
+ PY_DICT_ADD_INT(GL_UNSIGNED_NORMALIZED);
+ PY_DICT_ADD_INT(GL_VERTEX_ARRAY_BINDING);
+ PY_DICT_ADD_INT(GL_VERTEX_ATTRIB_ARRAY_INTEGER);
+ }
+ /* adding in GL_VERSION_3_0 removed from core profile */
+ if (use_deprecated == true) {
+ PY_DICT_ADD_INT(GL_ALPHA_INTEGER);
+ PY_DICT_ADD_INT(GL_CLAMP_FRAGMENT_COLOR);
+ PY_DICT_ADD_INT(GL_CLAMP_VERTEX_COLOR);
+ PY_DICT_ADD_INT(GL_TEXTURE_INTENSITY_TYPE);
+ PY_DICT_ADD_INT(GL_TEXTURE_LUMINANCE_TYPE);
+ }
+
+ /* GL_VERSION_3_1 */
+ {
+ PY_DICT_ADD_INT(GL_ACTIVE_UNIFORM_BLOCKS);
+ PY_DICT_ADD_INT(GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH);
+ PY_DICT_ADD_INT(GL_COPY_READ_BUFFER);
+ PY_DICT_ADD_INT(GL_COPY_WRITE_BUFFER);
+ PY_DICT_ADD_INT(GL_INT_SAMPLER_2D_RECT);
+ PY_DICT_ADD_INT(GL_INT_SAMPLER_BUFFER);
+ PY_DICT_ADD_INT(GL_INVALID_INDEX);
+ PY_DICT_ADD_INT(GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS);
+ PY_DICT_ADD_INT(GL_MAX_COMBINED_GEOMETRY_UNIFORM_COMPONENTS);
+ PY_DICT_ADD_INT(GL_MAX_COMBINED_UNIFORM_BLOCKS);
+ PY_DICT_ADD_INT(GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS);
+ PY_DICT_ADD_INT(GL_MAX_FRAGMENT_UNIFORM_BLOCKS);
+ PY_DICT_ADD_INT(GL_MAX_GEOMETRY_UNIFORM_BLOCKS);
+ PY_DICT_ADD_INT(GL_MAX_RECTANGLE_TEXTURE_SIZE);
+ PY_DICT_ADD_INT(GL_MAX_TEXTURE_BUFFER_SIZE);
+ PY_DICT_ADD_INT(GL_MAX_UNIFORM_BLOCK_SIZE);
+ PY_DICT_ADD_INT(GL_MAX_UNIFORM_BUFFER_BINDINGS);
+ PY_DICT_ADD_INT(GL_MAX_VERTEX_UNIFORM_BLOCKS);
+ PY_DICT_ADD_INT(GL_PRIMITIVE_RESTART);
+ PY_DICT_ADD_INT(GL_PRIMITIVE_RESTART_INDEX);
+ PY_DICT_ADD_INT(GL_PROXY_TEXTURE_RECTANGLE);
+ PY_DICT_ADD_INT(GL_R16_SNORM);
+ PY_DICT_ADD_INT(GL_R8_SNORM);
+ PY_DICT_ADD_INT(GL_RG16_SNORM);
+ PY_DICT_ADD_INT(GL_RG8_SNORM);
+ PY_DICT_ADD_INT(GL_RGB16_SNORM);
+ PY_DICT_ADD_INT(GL_RGB8_SNORM);
+ PY_DICT_ADD_INT(GL_RGBA16_SNORM);
+ PY_DICT_ADD_INT(GL_RGBA8_SNORM);
+ PY_DICT_ADD_INT(GL_SAMPLER_2D_RECT);
+ PY_DICT_ADD_INT(GL_SAMPLER_2D_RECT_SHADOW);
+ PY_DICT_ADD_INT(GL_SAMPLER_BUFFER);
+ PY_DICT_ADD_INT(GL_SIGNED_NORMALIZED);
+ PY_DICT_ADD_INT(GL_TEXTURE_BINDING_BUFFER);
+ PY_DICT_ADD_INT(GL_TEXTURE_BINDING_RECTANGLE);
+ PY_DICT_ADD_INT(GL_TEXTURE_BUFFER);
+ PY_DICT_ADD_INT(GL_TEXTURE_BUFFER_DATA_STORE_BINDING);
+ PY_DICT_ADD_INT(GL_TEXTURE_RECTANGLE);
+ PY_DICT_ADD_INT(GL_UNIFORM_ARRAY_STRIDE);
+ PY_DICT_ADD_INT(GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS);
+ PY_DICT_ADD_INT(GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES);
+ PY_DICT_ADD_INT(GL_UNIFORM_BLOCK_BINDING);
+ PY_DICT_ADD_INT(GL_UNIFORM_BLOCK_DATA_SIZE);
+ PY_DICT_ADD_INT(GL_UNIFORM_BLOCK_INDEX);
+ PY_DICT_ADD_INT(GL_UNIFORM_BLOCK_NAME_LENGTH);
+ PY_DICT_ADD_INT(GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER);
+ PY_DICT_ADD_INT(GL_UNIFORM_BLOCK_REFERENCED_BY_GEOMETRY_SHADER);
+ PY_DICT_ADD_INT(GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER);
+ PY_DICT_ADD_INT(GL_UNIFORM_BUFFER);
+ PY_DICT_ADD_INT(GL_UNIFORM_BUFFER_BINDING);
+ PY_DICT_ADD_INT(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT);
+ PY_DICT_ADD_INT(GL_UNIFORM_BUFFER_SIZE);
+ PY_DICT_ADD_INT(GL_UNIFORM_BUFFER_START);
+ PY_DICT_ADD_INT(GL_UNIFORM_IS_ROW_MAJOR);
+ PY_DICT_ADD_INT(GL_UNIFORM_MATRIX_STRIDE);
+ PY_DICT_ADD_INT(GL_UNIFORM_NAME_LENGTH);
+ PY_DICT_ADD_INT(GL_UNIFORM_OFFSET);
+ PY_DICT_ADD_INT(GL_UNIFORM_SIZE);
+ PY_DICT_ADD_INT(GL_UNIFORM_TYPE);
+ PY_DICT_ADD_INT(GL_UNSIGNED_INT_SAMPLER_2D_RECT);
+ PY_DICT_ADD_INT(GL_UNSIGNED_INT_SAMPLER_BUFFER);
+ }
+
+
+ /* GL_VERSION_3_2 */
+ {
+ PY_DICT_ADD_INT(GL_ALREADY_SIGNALED);
+ PY_DICT_ADD_INT(GL_CONDITION_SATISFIED);
+ PY_DICT_ADD_INT(GL_CONTEXT_COMPATIBILITY_PROFILE_BIT);
+ PY_DICT_ADD_INT(GL_CONTEXT_CORE_PROFILE_BIT);
+ PY_DICT_ADD_INT(GL_CONTEXT_PROFILE_MASK);
+ PY_DICT_ADD_INT(GL_DEPTH_CLAMP);
+ PY_DICT_ADD_INT(GL_FIRST_VERTEX_CONVENTION);
+ PY_DICT_ADD_INT(GL_FRAMEBUFFER_ATTACHMENT_LAYERED);
+ PY_DICT_ADD_INT(GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS);
+ PY_DICT_ADD_INT(GL_GEOMETRY_INPUT_TYPE);
+ PY_DICT_ADD_INT(GL_GEOMETRY_OUTPUT_TYPE);
+ PY_DICT_ADD_INT(GL_GEOMETRY_SHADER);
+ PY_DICT_ADD_INT(GL_GEOMETRY_VERTICES_OUT);
+ PY_DICT_ADD_INT(GL_INT_SAMPLER_2D_MULTISAMPLE);
+ PY_DICT_ADD_INT(GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY);
+ PY_DICT_ADD_INT(GL_LAST_VERTEX_CONVENTION);
+ PY_DICT_ADD_INT(GL_LINES_ADJACENCY);
+ PY_DICT_ADD_INT(GL_LINE_STRIP_ADJACENCY);
+ PY_DICT_ADD_INT(GL_MAX_COLOR_TEXTURE_SAMPLES);
+ PY_DICT_ADD_INT(GL_MAX_DEPTH_TEXTURE_SAMPLES);
+ PY_DICT_ADD_INT(GL_MAX_FRAGMENT_INPUT_COMPONENTS);
+ PY_DICT_ADD_INT(GL_MAX_GEOMETRY_INPUT_COMPONENTS);
+ PY_DICT_ADD_INT(GL_MAX_GEOMETRY_OUTPUT_COMPONENTS);
+ PY_DICT_ADD_INT(GL_MAX_GEOMETRY_OUTPUT_VERTICES);
+ PY_DICT_ADD_INT(GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS);
+ PY_DICT_ADD_INT(GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS);
+ PY_DICT_ADD_INT(GL_MAX_GEOMETRY_UNIFORM_COMPONENTS);
+ PY_DICT_ADD_INT(GL_MAX_INTEGER_SAMPLES);
+ PY_DICT_ADD_INT(GL_MAX_SAMPLE_MASK_WORDS);
+ PY_DICT_ADD_INT(GL_MAX_SERVER_WAIT_TIMEOUT);
+ PY_DICT_ADD_INT(GL_MAX_VERTEX_OUTPUT_COMPONENTS);
+ PY_DICT_ADD_INT(GL_OBJECT_TYPE);
+ PY_DICT_ADD_INT(GL_PROGRAM_POINT_SIZE);
+ PY_DICT_ADD_INT(GL_PROVOKING_VERTEX);
+ PY_DICT_ADD_INT(GL_PROXY_TEXTURE_2D_MULTISAMPLE);
+ PY_DICT_ADD_INT(GL_PROXY_TEXTURE_2D_MULTISAMPLE_ARRAY);
+ PY_DICT_ADD_INT(GL_QUADS_FOLLOW_PROVOKING_VERTEX_CONVENTION);
+ PY_DICT_ADD_INT(GL_SAMPLER_2D_MULTISAMPLE);
+ PY_DICT_ADD_INT(GL_SAMPLER_2D_MULTISAMPLE_ARRAY);
+ PY_DICT_ADD_INT(GL_SAMPLE_MASK);
+ PY_DICT_ADD_INT(GL_SAMPLE_MASK_VALUE);
+ PY_DICT_ADD_INT(GL_SAMPLE_POSITION);
+ PY_DICT_ADD_INT(GL_SIGNALED);
+ PY_DICT_ADD_INT(GL_SYNC_CONDITION);
+ PY_DICT_ADD_INT(GL_SYNC_FENCE);
+ PY_DICT_ADD_INT(GL_SYNC_FLAGS);
+ PY_DICT_ADD_INT(GL_SYNC_FLUSH_COMMANDS_BIT);
+ PY_DICT_ADD_INT(GL_SYNC_GPU_COMMANDS_COMPLETE);
+ PY_DICT_ADD_INT(GL_SYNC_STATUS);
+ PY_DICT_ADD_INT(GL_TEXTURE_2D_MULTISAMPLE);
+ PY_DICT_ADD_INT(GL_TEXTURE_2D_MULTISAMPLE_ARRAY);
+ PY_DICT_ADD_INT(GL_TEXTURE_BINDING_2D_MULTISAMPLE);
+ PY_DICT_ADD_INT(GL_TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY);
+ PY_DICT_ADD_INT(GL_TEXTURE_CUBE_MAP_SEAMLESS);
+ PY_DICT_ADD_INT(GL_TEXTURE_FIXED_SAMPLE_LOCATIONS);
+ PY_DICT_ADD_INT(GL_TEXTURE_SAMPLES);
+ PY_DICT_ADD_INT(GL_TIMEOUT_EXPIRED);
+ PY_DICT_ADD_INT64(GL_TIMEOUT_IGNORED);
+ PY_DICT_ADD_INT(GL_TRIANGLES_ADJACENCY);
+ PY_DICT_ADD_INT(GL_TRIANGLE_STRIP_ADJACENCY);
+ PY_DICT_ADD_INT(GL_UNSIGNALED);
+ PY_DICT_ADD_INT(GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE);
+ PY_DICT_ADD_INT(GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY);
+ PY_DICT_ADD_INT(GL_WAIT_FAILED);
+ }
+
+ /* GL_VERSION_3_3 */
+ {
+ PY_DICT_ADD_INT(GL_ANY_SAMPLES_PASSED);
+ PY_DICT_ADD_INT(GL_INT_2_10_10_10_REV);
+ PY_DICT_ADD_INT(GL_MAX_DUAL_SOURCE_DRAW_BUFFERS);
+ PY_DICT_ADD_INT(GL_ONE_MINUS_SRC1_ALPHA);
+ PY_DICT_ADD_INT(GL_ONE_MINUS_SRC1_COLOR);
+ PY_DICT_ADD_INT(GL_RGB10_A2UI);
+ PY_DICT_ADD_INT(GL_SAMPLER_BINDING);
+ PY_DICT_ADD_INT(GL_SRC1_COLOR);
+ PY_DICT_ADD_INT(GL_TEXTURE_SWIZZLE_A);
+ PY_DICT_ADD_INT(GL_TEXTURE_SWIZZLE_B);
+ PY_DICT_ADD_INT(GL_TEXTURE_SWIZZLE_G);
+ PY_DICT_ADD_INT(GL_TEXTURE_SWIZZLE_R);
+ PY_DICT_ADD_INT(GL_TEXTURE_SWIZZLE_RGBA);
+ PY_DICT_ADD_INT(GL_TIMESTAMP);
+ PY_DICT_ADD_INT(GL_TIME_ELAPSED);
+ PY_DICT_ADD_INT(GL_VERTEX_ATTRIB_ARRAY_DIVISOR);
+ }
return submodule;
}
@@ -1928,3 +3684,5 @@ static PyObject *Method_ShaderSource(PyObject *UNUSED(self), PyObject *args)
return Py_INCREF(Py_None), Py_None;
}
+
+/** \} */ \ No newline at end of file
diff --git a/source/blender/python/generic/bgl.h b/source/blender/python/generic/bgl.h
index 70a607bc311..b27a4d6a0a4 100644
--- a/source/blender/python/generic/bgl.h
+++ b/source/blender/python/generic/bgl.h
@@ -24,28 +24,20 @@
* \ingroup pygen
*/
-
-/* This is the Blender.BGL part of opy_draw.c, from the old bpython/intern
- * dir, with minor changes to adapt it to the new Python implementation.
- * The BGL submodule "wraps" OpenGL functions and constants, allowing script
- * writers to make OpenGL calls in their Python scripts for Blender. The
- * more important original comments are marked with an @ symbol. */
-
#ifndef __BGL_H__
#define __BGL_H__
PyObject *BPyInit_bgl(void);
-/*@ Create a buffer object */
-/*@ dimensions is an array of ndimensions integers representing the size of each dimension */
-/*@ initbuffer if not NULL holds a contiguous buffer with the correct format from which the buffer will be initialized */
struct _Buffer *BGL_MakeBuffer(int type, int ndimensions, int *dimensions, void *initbuffer);
-/*@ Return the size of buffer element, type must be one of GL_BYTE, GL_SHORT, GL_INT, GL_FLOAT or GL_DOUBLE */
-/*@ returns -1 otherwise */
+
int BGL_typeSize(int type);
-/*@ Buffer Object */
-/*@ For Python access to OpenGL functions requiring a pointer. */
+/**
+ * Buffer Object
+ *
+ * For Python access to OpenGL functions requiring a pointer.
+ */
typedef struct _Buffer {
PyObject_VAR_HEAD
PyObject *parent;
@@ -65,289 +57,7 @@ typedef struct _Buffer {
} buf;
} Buffer;
-/*@ The type object */
+/** The type object */
extern PyTypeObject BGL_bufferType;
-/*@ By golly George! It looks like fancy pants macro time!!! */
-
-#if 0 /* unused so far */
-#define int_str "i"
-#define int_var(number) bgl_int##number
-#define int_ref(number) &bgl_int##number
-#define int_def(number) int int_var(number)
-
-#define float_str "f"
-#define float_var(number) bgl_float##number
-#define float_ref(number) &bgl_float##number
-#define float_def(number) float float_var(number)
-#endif
-
-/* TYPE_str is the string to pass to Py_ArgParse (for the format) */
-/* TYPE_var is the name to pass to the GL function */
-/* TYPE_ref is the pointer to pass to Py_ArgParse (to store in) */
-/* TYPE_def is the C initialization of the variable */
-
-#define void_str ""
-#define void_var(num)
-#define void_ref(num) &bgl_var##num
-#define void_def(num) char bgl_var##num
-
-#define buffer_str "O!"
-#define buffer_var(number) (bgl_buffer##number)->buf.asvoid
-#define buffer_ref(number) &BGL_bufferType, &bgl_buffer##number
-#define buffer_def(number) Buffer *bgl_buffer##number
-
-/* GL Pointer fields, handled by buffer type */
-/* GLdoubleP, GLfloatP, GLintP, GLuintP, GLshortP, GLsizeiP, GLcharP */
-
-#define GLbooleanP_str "O!"
-#define GLbooleanP_var(number) (bgl_buffer##number)->buf.asvoid
-#define GLbooleanP_ref(number) &BGL_bufferType, &bgl_buffer##number
-#define GLbooleanP_def(number) Buffer *bgl_buffer##number
-
-#define GLbyteP_str "O!"
-#define GLbyteP_var(number) (bgl_buffer##number)->buf.asvoid
-#define GLbyteP_ref(number) &BGL_bufferType, &bgl_buffer##number
-#define GLbyteP_def(number) Buffer *bgl_buffer##number
-
-#define GLubyteP_str "O!"
-#define GLubyteP_var(number) (bgl_buffer##number)->buf.asvoid
-#define GLubyteP_ref(number) &BGL_bufferType, &bgl_buffer##number
-#define GLubyteP_def(number) Buffer *bgl_buffer##number
-
-#define GLintP_str "O!"
-#define GLintP_var(number) (bgl_buffer##number)->buf.asvoid
-#define GLintP_ref(number) &BGL_bufferType, &bgl_buffer##number
-#define GLintP_def(number) Buffer *bgl_buffer##number
-
-#define GLuintP_str "O!"
-#define GLuintP_var(number) (bgl_buffer##number)->buf.asvoid
-#define GLuintP_ref(number) &BGL_bufferType, &bgl_buffer##number
-#define GLuintP_def(number) Buffer *bgl_buffer##number
-
-#define GLshortP_str "O!"
-#define GLshortP_var(number) (bgl_buffer##number)->buf.asvoid
-#define GLshortP_ref(number) &BGL_bufferType, &bgl_buffer##number
-#define GLshortP_def(number) Buffer *bgl_buffer##number
-
-#define GLushortP_str "O!"
-#define GLushortP_var(number) (bgl_buffer##number)->buf.asvoid
-#define GLushortP_ref(number) &BGL_bufferType, &bgl_buffer##number
-#define GLushortP_def(number) Buffer *bgl_buffer##number
-
-#define GLfloatP_str "O!"
-#define GLfloatP_var(number) (bgl_buffer##number)->buf.asvoid
-#define GLfloatP_ref(number) &BGL_bufferType, &bgl_buffer##number
-#define GLfloatP_def(number) Buffer *bgl_buffer##number
-
-#define GLdoubleP_str "O!"
-#define GLdoubleP_var(number) (bgl_buffer##number)->buf.asvoid
-#define GLdoubleP_ref(number) &BGL_bufferType, &bgl_buffer##number
-#define GLdoubleP_def(number) Buffer *bgl_buffer##number
-
-#define GLclampfP_str "O!"
-#define GLclampfP_var(number) (bgl_buffer##number)->buf.asvoid
-#define GLclampfP_ref(number) &BGL_bufferType, &bgl_buffer##number
-#define GLclampfP_def(number) Buffer *bgl_buffer##number
-
-#define GLvoidP_str "O!"
-#define GLvoidP_var(number) (bgl_buffer##number)->buf.asvoid
-#define GLvoidP_ref(number) &BGL_bufferType, &bgl_buffer##number
-#define GLvoidP_def(number) Buffer *bgl_buffer##number
-
-#define GLsizeiP_str "O!"
-#define GLsizeiP_var(number) (bgl_buffer##number)->buf.asvoid
-#define GLsizeiP_ref(number) &BGL_bufferType, &bgl_buffer##number
-#define GLsizeiP_def(number) Buffer *bgl_buffer##number
-
-#define GLcharP_str "O!"
-#define GLcharP_var(number) (bgl_buffer##number)->buf.asvoid
-#define GLcharP_ref(number) &BGL_bufferType, &bgl_buffer##number
-#define GLcharP_def(number) Buffer *bgl_buffer##number
-
-#define buffer_str "O!"
-#define buffer_var(number) (bgl_buffer##number)->buf.asvoid
-#define buffer_ref(number) &BGL_bufferType, &bgl_buffer##number
-#define buffer_def(number) Buffer *bgl_buffer##number
-
-/*@The standard GL typedefs are used as prototypes, we can't
- * use the GL type directly because Py_ArgParse expects normal
- * C types.
- *
- * Py_ArgParse doesn't grok writing into unsigned variables,
- * so we use signed everything (even stuff that should be unsigned.
- */
-
-/* typedef unsigned int GLenum; */
-#define GLenum_str "i"
-#define GLenum_var(num) bgl_var##num
-#define GLenum_ref(num) &bgl_var##num
-#define GLenum_def(num) /* unsigned */ int GLenum_var(num)
-
-/* typedef unsigned int GLboolean; */
-#define GLboolean_str "b"
-#define GLboolean_var(num) bgl_var##num
-#define GLboolean_ref(num) &bgl_var##num
-#define GLboolean_def(num) /* unsigned */ char GLboolean_var(num)
-
-/* typedef unsigned int GLbitfield; */
-#define GLbitfield_str "i"
-#define GLbitfield_var(num) bgl_var##num
-#define GLbitfield_ref(num) &bgl_var##num
-#define GLbitfield_def(num) /* unsigned */ int GLbitfield_var(num)
-
-/* typedef signed char GLbyte; */
-#define GLbyte_str "b"
-#define GLbyte_var(num) bgl_var##num
-#define GLbyte_ref(num) &bgl_var##num
-#define GLbyte_def(num) signed char GLbyte_var(num)
-
-/* typedef short GLshort; */
-#define GLshort_str "h"
-#define GLshort_var(num) bgl_var##num
-#define GLshort_ref(num) &bgl_var##num
-#define GLshort_def(num) short GLshort_var(num)
-
-/* typedef int GLint; */
-#define GLint_str "i"
-#define GLint_var(num) bgl_var##num
-#define GLint_ref(num) &bgl_var##num
-#define GLint_def(num) int GLint_var(num)
-
-/* typedef int GLsizei; */
-#define GLsizei_str "i"
-#define GLsizei_var(num) bgl_var##num
-#define GLsizei_ref(num) &bgl_var##num
-#define GLsizei_def(num) int GLsizei_var(num)
-
-/* typedef unsigned char GLubyte; */
-#define GLubyte_str "B"
-#define GLubyte_var(num) bgl_var##num
-#define GLubyte_ref(num) &bgl_var##num
-#define GLubyte_def(num) /* unsigned */ char GLubyte_var(num)
-
-/* typedef unsigned short GLushort; */
-#define GLushort_str "H"
-#define GLushort_var(num) bgl_var##num
-#define GLushort_ref(num) &bgl_var##num
-#define GLushort_def(num) /* unsigned */ short GLushort_var(num)
-
-/* typedef unsigned int GLuint; */
-#define GLuint_str "I"
-#define GLuint_var(num) bgl_var##num
-#define GLuint_ref(num) &bgl_var##num
-#define GLuint_def(num) /* unsigned */ int GLuint_var(num)
-
-/* typedef float GLfloat; */
-#define GLfloat_str "f"
-#define GLfloat_var(num) bgl_var##num
-#define GLfloat_ref(num) &bgl_var##num
-#define GLfloat_def(num) float GLfloat_var(num)
-
-/* typedef char *GLstring; */
-#define GLstring_str "s"
-#define GLstring_var(number) bgl_var##number
-#define GLstring_ref(number) &bgl_var##number
-#define GLstring_def(number) char *GLstring_var(number)
-
-/* typedef float GLclampf; */
-#define GLclampf_str "f"
-#define GLclampf_var(num) bgl_var##num
-#define GLclampf_ref(num) &bgl_var##num
-#define GLclampf_def(num) float GLclampf_var(num)
-
-/* typedef double GLdouble; */
-#define GLdouble_str "d"
-#define GLdouble_var(num) bgl_var##num
-#define GLdouble_ref(num) &bgl_var##num
-#define GLdouble_def(num) double GLdouble_var(num)
-
-/* typedef double GLclampd; */
-#define GLclampd_str "d"
-#define GLclampd_var(num) bgl_var##num
-#define GLclampd_ref(num) &bgl_var##num
-#define GLclampd_def(num) double GLclampd_var(num)
-
-/* typedef void GLvoid; */
-/* #define GLvoid_str "" */
-/* #define GLvoid_var(num) bgl_var##num */
-/* #define GLvoid_ref(num) &bgl_var##num */
-/* #define GLvoid_def(num) char bgl_var##num */
-
-#define arg_def1(a1) a1##_def(1)
-#define arg_def2(a1, a2) arg_def1(a1); a2##_def(2)
-#define arg_def3(a1, a2, a3) arg_def2(a1, a2); a3##_def(3)
-#define arg_def4(a1, a2, a3, a4) arg_def3(a1, a2, a3); a4##_def(4)
-#define arg_def5(a1, a2, a3, a4, a5) arg_def4(a1, a2, a3, a4); a5##_def(5)
-#define arg_def6(a1, a2, a3, a4, a5, a6)arg_def5(a1, a2, a3, a4, a5); a6##_def(6)
-#define arg_def7(a1, a2, a3, a4, a5, a6, a7)arg_def6(a1, a2, a3, a4, a5, a6); a7##_def(7)
-#define arg_def8(a1, a2, a3, a4, a5, a6, a7, a8)arg_def7(a1, a2, a3, a4, a5, a6, a7); a8##_def(8)
-#define arg_def9(a1, a2, a3, a4, a5, a6, a7, a8, a9)arg_def8(a1, a2, a3, a4, a5, a6, a7, a8); a9##_def(9)
-#define arg_def10(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10)arg_def9(a1, a2, a3, a4, a5, a6, a7, a8, a9); a10##_def(10)
-
-#define arg_var1(a1) a1##_var(1)
-#define arg_var2(a1, a2) arg_var1(a1), a2##_var(2)
-#define arg_var3(a1, a2, a3) arg_var2(a1, a2), a3##_var(3)
-#define arg_var4(a1, a2, a3, a4) arg_var3(a1, a2, a3), a4##_var(4)
-#define arg_var5(a1, a2, a3, a4, a5) arg_var4(a1, a2, a3, a4), a5##_var(5)
-#define arg_var6(a1, a2, a3, a4, a5, a6)arg_var5(a1, a2, a3, a4, a5), a6##_var(6)
-#define arg_var7(a1, a2, a3, a4, a5, a6, a7)arg_var6(a1, a2, a3, a4, a5, a6), a7##_var(7)
-#define arg_var8(a1, a2, a3, a4, a5, a6, a7, a8)arg_var7(a1, a2, a3, a4, a5, a6, a7), a8##_var(8)
-#define arg_var9(a1, a2, a3, a4, a5, a6, a7, a8, a9)arg_var8(a1, a2, a3, a4, a5, a6, a7, a8), a9##_var(9)
-#define arg_var10(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10)arg_var9(a1, a2, a3, a4, a5, a6, a7, a8, a9), a10##_var(10)
-
-#define arg_ref1(a1) a1##_ref(1)
-#define arg_ref2(a1, a2) arg_ref1(a1), a2##_ref(2)
-#define arg_ref3(a1, a2, a3) arg_ref2(a1, a2), a3##_ref(3)
-#define arg_ref4(a1, a2, a3, a4) arg_ref3(a1, a2, a3), a4##_ref(4)
-#define arg_ref5(a1, a2, a3, a4, a5) arg_ref4(a1, a2, a3, a4), a5##_ref(5)
-#define arg_ref6(a1, a2, a3, a4, a5, a6)arg_ref5(a1, a2, a3, a4, a5), a6##_ref(6)
-#define arg_ref7(a1, a2, a3, a4, a5, a6, a7)arg_ref6(a1, a2, a3, a4, a5, a6), a7##_ref(7)
-#define arg_ref8(a1, a2, a3, a4, a5, a6, a7, a8)arg_ref7(a1, a2, a3, a4, a5, a6, a7), a8##_ref(8)
-#define arg_ref9(a1, a2, a3, a4, a5, a6, a7, a8, a9)arg_ref8(a1, a2, a3, a4, a5, a6, a7, a8), a9##_ref(9)
-#define arg_ref10(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10)arg_ref9(a1, a2, a3, a4, a5, a6, a7, a8, a9), a10##_ref(10)
-
-#define arg_str1(a1) a1##_str
-#define arg_str2(a1, a2) arg_str1(a1) a2##_str
-#define arg_str3(a1, a2, a3) arg_str2(a1, a2) a3##_str
-#define arg_str4(a1, a2, a3, a4) arg_str3(a1, a2, a3) a4##_str
-#define arg_str5(a1, a2, a3, a4, a5) arg_str4(a1, a2, a3, a4) a5##_str
-#define arg_str6(a1, a2, a3, a4, a5, a6)arg_str5(a1, a2, a3, a4, a5) a6##_str
-#define arg_str7(a1, a2, a3, a4, a5, a6, a7)arg_str6(a1, a2, a3, a4, a5, a6) a7##_str
-#define arg_str8(a1, a2, a3, a4, a5, a6, a7, a8)arg_str7(a1, a2, a3, a4, a5, a6, a7) a8##_str
-#define arg_str9(a1, a2, a3, a4, a5, a6, a7, a8, a9)arg_str8(a1, a2, a3, a4, a5, a6, a7, a8) a9##_str
-#define arg_str10(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10)arg_str9(a1, a2, a3, a4, a5, a6, a7, a8, a9) a10##_str
-
-#define ret_def_void
-#define ret_set_void
-#define ret_ret_void return Py_INCREF(Py_None), Py_None
-
-#define ret_def_GLint int ret_int
-#define ret_set_GLint ret_int =
-#define ret_ret_GLint return PyLong_FromLong(ret_int)
-
-#define ret_def_GLuint unsigned int ret_uint
-#define ret_set_GLuint ret_uint =
-#define ret_ret_GLuint return PyLong_FromLong((long) ret_uint)
-
-#define ret_def_GLenum unsigned int ret_uint
-#define ret_set_GLenum ret_uint =
-#define ret_ret_GLenum return PyLong_FromLong((long) ret_uint)
-
-#define ret_def_GLboolean unsigned char ret_bool
-#define ret_set_GLboolean ret_bool =
-#define ret_ret_GLboolean return PyLong_FromLong((long) ret_bool)
-
-#define ret_def_GLstring const unsigned char *ret_str
-#define ret_set_GLstring ret_str =
-
-#define ret_ret_GLstring \
- if (ret_str) { \
- return PyUnicode_FromString((const char *)ret_str); \
- } \
- else { \
- PyErr_SetString(PyExc_AttributeError, "could not get opengl string"); \
- return NULL; \
- } \
-
#endif /* __BGL_H__ */
diff --git a/source/blender/python/generic/blf_py_api.c b/source/blender/python/generic/blf_py_api.c
index 655542e320a..0dfff9b4a7b 100644
--- a/source/blender/python/generic/blf_py_api.c
+++ b/source/blender/python/generic/blf_py_api.c
@@ -33,6 +33,9 @@
#include "BLI_utildefines.h"
+#include "python_utildefines.h"
+
+
PyDoc_STRVAR(py_blf_position_doc,
".. function:: position(fontid, x, y, z)\n"
"\n"
@@ -183,8 +186,9 @@ static PyObject *py_blf_dimensions(PyObject *UNUSED(self), PyObject *args)
BLF_width_and_height(fontid, text, INT_MAX, &r_width, &r_height);
ret = PyTuple_New(2);
- PyTuple_SET_ITEM(ret, 0, PyFloat_FromDouble(r_width));
- PyTuple_SET_ITEM(ret, 1, PyFloat_FromDouble(r_height));
+ PyTuple_SET_ITEMS(ret,
+ PyFloat_FromDouble(r_width),
+ PyFloat_FromDouble(r_height));
return ret;
}
@@ -217,6 +221,29 @@ static PyObject *py_blf_clipping(PyObject *UNUSED(self), PyObject *args)
Py_RETURN_NONE;
}
+PyDoc_STRVAR(py_blf_word_wrap_doc,
+".. function:: word_wrap(fontid, wrap_width)\n"
+"\n"
+" Set the wrap width, enable/disable using WORD_WRAP.\n"
+"\n"
+" :arg fontid: The id of the typeface as returned by :func:`blf.load`, for default font use 0.\n"
+" :type fontid: int\n"
+" :arg wrap_width: The width (in pixels) to wrap words at.\n"
+" :type wrap_width: int\n"
+);
+static PyObject *py_blf_word_wrap(PyObject *UNUSED(self), PyObject *args)
+{
+ int wrap_width;
+ int fontid;
+
+ if (!PyArg_ParseTuple(args, "ii:blf.word_wrap", &fontid, &wrap_width))
+ return NULL;
+
+ BLF_wordwrap(fontid, wrap_width);
+
+ Py_RETURN_NONE;
+}
+
PyDoc_STRVAR(py_blf_disable_doc,
".. function:: disable(fontid, option)\n"
"\n"
@@ -389,6 +416,7 @@ static PyMethodDef BLF_methods[] = {
{"aspect", (PyCFunction) py_blf_aspect, METH_VARARGS, py_blf_aspect_doc},
{"blur", (PyCFunction) py_blf_blur, METH_VARARGS, py_blf_blur_doc},
{"clipping", (PyCFunction) py_blf_clipping, METH_VARARGS, py_blf_clipping_doc},
+ {"word_wrap", (PyCFunction) py_blf_word_wrap, METH_VARARGS, py_blf_word_wrap_doc},
{"disable", (PyCFunction) py_blf_disable, METH_VARARGS, py_blf_disable_doc},
{"dimensions", (PyCFunction) py_blf_dimensions, METH_VARARGS, py_blf_dimensions_doc},
{"draw", (PyCFunction) py_blf_draw, METH_VARARGS, py_blf_draw_doc},
@@ -428,6 +456,7 @@ PyObject *BPyInit_blf(void)
PyModule_AddIntConstant(submodule, "CLIPPING", BLF_CLIPPING);
PyModule_AddIntConstant(submodule, "SHADOW", BLF_SHADOW);
PyModule_AddIntConstant(submodule, "KERNING_DEFAULT", BLF_KERNING_DEFAULT);
+ PyModule_AddIntConstant(submodule, "WORD_WRAP", BLF_WORD_WRAP);
return submodule;
}
diff --git a/source/blender/python/generic/bpy_internal_import.c b/source/blender/python/generic/bpy_internal_import.c
index 2d19fdb87b3..ed2752d8372 100644
--- a/source/blender/python/generic/bpy_internal_import.c
+++ b/source/blender/python/generic/bpy_internal_import.c
@@ -81,7 +81,7 @@ void bpy_import_init(PyObject *builtins)
/* move reload here
* XXX, use import hooks */
- mod = PyImport_ImportModuleLevel("imp", NULL, NULL, NULL, 0);
+ mod = PyImport_ImportModuleLevel("importlib", NULL, NULL, NULL, 0);
if (mod) {
PyObject *mod_dict = PyModule_GetDict(mod);
@@ -93,7 +93,7 @@ void bpy_import_init(PyObject *builtins)
Py_DECREF(mod);
}
else {
- BLI_assert(!"unable to load 'imp' module.");
+ BLI_assert(!"unable to load 'importlib' module.");
}
}
@@ -265,7 +265,7 @@ PyObject *bpy_text_reimport(PyObject *module, int *found)
}
/* make into a module */
- return PyImport_ExecCodeModule((char *)name, text->compiled);
+ return PyImport_ExecCodeModule(name, text->compiled);
}
diff --git a/source/blender/python/generic/idprop_py_api.c b/source/blender/python/generic/idprop_py_api.c
index 8c9e84af8ed..db8ed072722 100644
--- a/source/blender/python/generic/idprop_py_api.c
+++ b/source/blender/python/generic/idprop_py_api.c
@@ -33,16 +33,17 @@
#include "idprop_py_api.h"
-
#include "BKE_idprop.h"
-
#define USE_STRING_COERCE
#ifdef USE_STRING_COERCE
#include "py_capi_utils.h"
#endif
+#include "python_utildefines.h"
+
+
/*********************** ID Property Main Wrapper Stuff ***************/
/* ----------------------------------------------------------------------------
@@ -296,14 +297,16 @@ static PyObject *BPy_IDGroup_Map_GetItem(BPy_IDProperty *self, PyObject *item)
}
/* returns NULL on success, error string on failure */
-static int idp_sequence_type(PyObject *seq_fast)
+static char idp_sequence_type(PyObject *seq_fast)
{
+ PyObject **seq_fast_items = PySequence_Fast_ITEMS(seq_fast);
PyObject *item;
- int type = IDP_INT;
+ char type = IDP_INT;
Py_ssize_t i, len = PySequence_Fast_GET_SIZE(seq_fast);
+
for (i = 0; i < len; i++) {
- item = PySequence_Fast_GET_ITEM(seq_fast, i);
+ item = seq_fast_items[i];
if (PyFloat_Check(item)) {
if (type == IDP_IDPARRAY) { /* mixed dict/int */
return -1;
@@ -376,7 +379,7 @@ bool BPy_IDProperty_Map_ValidateAndCreate(PyObject *name_obj, IDProperty *group,
else if (PyUnicode_Check(ob)) {
#ifdef USE_STRING_COERCE
PyObject *value_coerce = NULL;
- val.string.str = (char *)PyC_UnicodeAsByte(ob, &value_coerce);
+ val.string.str = PyC_UnicodeAsByte(ob, &value_coerce);
val.string.subtype = IDP_STRING_SUB_UTF8;
prop = IDP_New(IDP_STRING, &val, name);
Py_XDECREF(value_coerce);
@@ -395,15 +398,18 @@ bool BPy_IDProperty_Map_ValidateAndCreate(PyObject *name_obj, IDProperty *group,
//prop->subtype = IDP_STRING_SUB_BYTE;
}
else if (PySequence_Check(ob)) {
- PyObject *ob_seq_fast = PySequence_Fast(ob, "py -> idprop");
+ PyObject *ob_seq_fast;
+ PyObject **ob_seq_fast_items;
PyObject *item;
int i;
- if (ob_seq_fast == NULL) {
+ if (!(ob_seq_fast = PySequence_Fast(ob, "py -> idprop"))) {
return false;
}
- if ((val.array.type = idp_sequence_type(ob_seq_fast)) == -1) {
+ ob_seq_fast_items = PySequence_Fast_ITEMS(ob_seq_fast);
+
+ if ((val.array.type = idp_sequence_type(ob_seq_fast)) == (char)-1) {
Py_DECREF(ob_seq_fast);
PyErr_SetString(PyExc_TypeError, "only floats, ints and dicts are allowed in ID property arrays");
return false;
@@ -423,7 +429,7 @@ bool BPy_IDProperty_Map_ValidateAndCreate(PyObject *name_obj, IDProperty *group,
prop = IDP_New(IDP_ARRAY, &val, name);
prop_data = IDP_Array(prop);
for (i = 0; i < val.array.len; i++) {
- item = PySequence_Fast_GET_ITEM(ob_seq_fast, i);
+ item = ob_seq_fast_items[i];
if (((prop_data[i] = PyFloat_AsDouble(item)) == -1.0) && PyErr_Occurred()) {
Py_DECREF(ob_seq_fast);
return false;
@@ -437,7 +443,7 @@ bool BPy_IDProperty_Map_ValidateAndCreate(PyObject *name_obj, IDProperty *group,
prop = IDP_New(IDP_ARRAY, &val, name);
prop_data = IDP_Array(prop);
for (i = 0; i < val.array.len; i++) {
- item = PySequence_Fast_GET_ITEM(ob_seq_fast, i);
+ item = ob_seq_fast_items[i];
if (((prop_data[i] = _PyLong_AsInt(item)) == -1) && PyErr_Occurred()) {
Py_DECREF(ob_seq_fast);
return false;
@@ -449,7 +455,7 @@ bool BPy_IDProperty_Map_ValidateAndCreate(PyObject *name_obj, IDProperty *group,
{
prop = IDP_NewIDPArray(name);
for (i = 0; i < val.array.len; i++) {
- item = PySequence_Fast_GET_ITEM(ob_seq_fast, i);
+ item = ob_seq_fast_items[i];
if (BPy_IDProperty_Map_ValidateAndCreate(NULL, prop, item) == false) {
Py_DECREF(ob_seq_fast);
@@ -510,7 +516,26 @@ bool BPy_IDProperty_Map_ValidateAndCreate(PyObject *name_obj, IDProperty *group,
MEM_freeN(prop);
}
else {
- IDP_ReplaceInGroup(group, prop);
+ IDProperty *prop_exist;
+
+ /* avoid freeing when types match in case they are referenced by the UI, see: T37073
+ * obviously this isn't a complete solution, but helps for common cases. */
+ prop_exist = IDP_GetPropertyFromGroup(group, prop->name);
+ if ((prop_exist != NULL) &&
+ (prop_exist->type == prop->type) &&
+ (prop_exist->subtype == prop->subtype))
+ {
+ /* Preserve prev/next links!!! See T42593. */
+ prop->prev = prop_exist->prev;
+ prop->next = prop_exist->next;
+
+ IDP_FreeProperty(prop_exist);
+ *prop_exist = *prop;
+ MEM_freeN(prop);
+ }
+ else {
+ IDP_ReplaceInGroup_ex(group, prop, prop_exist);
+ }
}
return true;
@@ -727,10 +752,9 @@ static void BPy_IDGroup_CorrectListLen(IDProperty *prop, PyObject *seq, int len,
printf("%s: ID Property Error found and corrected!\n", func);
- /*fill rest of list with valid references to None*/
+ /* fill rest of list with valid references to None */
for (j = len; j < prop->len; j++) {
- Py_INCREF(Py_None);
- PyList_SET_ITEM(seq, j, Py_None);
+ PyList_SET_ITEM(seq, j, Py_INCREF_RET(Py_None));
}
/*set correct group length*/
@@ -789,8 +813,9 @@ PyObject *BPy_Wrap_GetItems(ID *id, IDProperty *prop)
for (i = 0, loop = prop->data.group.first; loop; loop = loop->next, i++) {
PyObject *item = PyTuple_New(2);
- PyTuple_SET_ITEM(item, 0, PyUnicode_FromString(loop->name));
- PyTuple_SET_ITEM(item, 1, BPy_IDGroup_WrapData(id, loop, prop));
+ PyTuple_SET_ITEMS(item,
+ PyUnicode_FromString(loop->name),
+ BPy_IDGroup_WrapData(id, loop, prop));
PyList_SET_ITEM(seq, i, item);
}
@@ -1387,8 +1412,9 @@ static PyObject *BPy_Group_Iter_Next(BPy_IDGroup_Iter *self)
if (self->mode == IDPROP_ITER_ITEMS) {
ret = PyTuple_New(2);
- PyTuple_SET_ITEM(ret, 0, PyUnicode_FromString(cur->name));
- PyTuple_SET_ITEM(ret, 1, BPy_IDGroup_WrapData(self->group->id, cur, self->group->prop));
+ PyTuple_SET_ITEMS(ret,
+ PyUnicode_FromString(cur->name),
+ BPy_IDGroup_WrapData(self->group->id, cur, self->group->prop));
return ret;
}
else {
diff --git a/source/blender/python/generic/py_capi_utils.c b/source/blender/python/generic/py_capi_utils.c
index 36ae30ada22..78be5e558db 100644
--- a/source/blender/python/generic/py_capi_utils.c
+++ b/source/blender/python/generic/py_capi_utils.c
@@ -29,6 +29,11 @@
* BLI_string_utf8() for unicode conversion.
*/
+/* TODO, resolve linking errors on win32 */
+#ifndef _WIN32
+/* needed for Py3.6+ to access Py_PyThreadState_Current */
+#define Py_BUILD_CORE
+#endif
#include <Python.h>
#include <frameobject.h>
@@ -37,6 +42,8 @@
#include "py_capi_utils.h"
+#include "python_utildefines.h"
+
/* only for BLI_strncpy_wchar_from_utf8, should replace with py funcs but too late in release now */
#include "BLI_string_utf8.h"
@@ -46,21 +53,17 @@
#endif
/* array utility function */
-int PyC_AsArray(void *array, PyObject *value, const Py_ssize_t length,
- const PyTypeObject *type, const bool is_double, const char *error_prefix)
+int PyC_AsArray_FAST(
+ void *array, PyObject *value_fast, const Py_ssize_t length,
+ const PyTypeObject *type, const bool is_double, const char *error_prefix)
{
- PyObject *value_fast;
- Py_ssize_t value_len;
+ const Py_ssize_t value_len = PySequence_Fast_GET_SIZE(value_fast);
+ PyObject **value_fast_items = PySequence_Fast_ITEMS(value_fast);
Py_ssize_t i;
- if (!(value_fast = PySequence_Fast(value, error_prefix))) {
- return -1;
- }
-
- value_len = PySequence_Fast_GET_SIZE(value_fast);
+ BLI_assert(PyList_Check(value_fast) || PyTuple_Check(value_fast));
if (value_len != length) {
- Py_DECREF(value);
PyErr_Format(PyExc_TypeError,
"%.200s: invalid sequence length. expected %d, got %d",
error_prefix, length, value_len);
@@ -72,13 +75,13 @@ int PyC_AsArray(void *array, PyObject *value, const Py_ssize_t length,
if (is_double) {
double *array_double = array;
for (i = 0; i < length; i++) {
- array_double[i] = PyFloat_AsDouble(PySequence_Fast_GET_ITEM(value_fast, i));
+ array_double[i] = PyFloat_AsDouble(value_fast_items[i]);
}
}
else {
float *array_float = array;
for (i = 0; i < length; i++) {
- array_float[i] = PyFloat_AsDouble(PySequence_Fast_GET_ITEM(value_fast, i));
+ array_float[i] = PyFloat_AsDouble(value_fast_items[i]);
}
}
}
@@ -86,25 +89,22 @@ int PyC_AsArray(void *array, PyObject *value, const Py_ssize_t length,
/* could use is_double for 'long int' but no use now */
int *array_int = array;
for (i = 0; i < length; i++) {
- array_int[i] = PyLong_AsLong(PySequence_Fast_GET_ITEM(value_fast, i));
+ array_int[i] = PyLong_AsLong(value_fast_items[i]);
}
}
else if (type == &PyBool_Type) {
int *array_bool = array;
for (i = 0; i < length; i++) {
- array_bool[i] = (PyLong_AsLong(PySequence_Fast_GET_ITEM(value_fast, i)) != 0);
+ array_bool[i] = (PyLong_AsLong(value_fast_items[i]) != 0);
}
}
else {
- Py_DECREF(value_fast);
PyErr_Format(PyExc_TypeError,
"%s: internal error %s is invalid",
error_prefix, type->tp_name);
return -1;
}
- Py_DECREF(value_fast);
-
if (PyErr_Occurred()) {
PyErr_Format(PyExc_TypeError,
"%s: one or more items could not be used as a %s",
@@ -115,6 +115,22 @@ int PyC_AsArray(void *array, PyObject *value, const Py_ssize_t length,
return 0;
}
+int PyC_AsArray(
+ void *array, PyObject *value, const Py_ssize_t length,
+ const PyTypeObject *type, const bool is_double, const char *error_prefix)
+{
+ PyObject *value_fast;
+ int ret;
+
+ if (!(value_fast = PySequence_Fast(value, error_prefix))) {
+ return -1;
+ }
+
+ ret = PyC_AsArray_FAST(array, value_fast, length, type, is_double, error_prefix);
+ Py_DECREF(value_fast);
+ return ret;
+}
+
/* array utility function */
PyObject *PyC_FromArray(const void *array, int length, const PyTypeObject *type,
const bool is_double, const char *error_prefix)
@@ -178,6 +194,17 @@ void PyC_Tuple_Fill(PyObject *tuple, PyObject *value)
}
}
+void PyC_List_Fill(PyObject *list, PyObject *value)
+{
+ unsigned int tot = PyList_GET_SIZE(list);
+ unsigned int i;
+
+ for (i = 0; i < tot; i++) {
+ PyList_SET_ITEM(list, i, value);
+ Py_INCREF(value);
+ }
+}
+
/* for debugging */
void PyC_ObSpit(const char *name, PyObject *var)
{
@@ -465,6 +492,34 @@ error_cleanup:
}
#endif
+PyObject *PyC_ExceptionBuffer_Simple(void)
+{
+ PyObject *string_io_buf;
+
+ PyObject *error_type, *error_value, *error_traceback;
+
+ if (!PyErr_Occurred())
+ return NULL;
+
+ PyErr_Fetch(&error_type, &error_value, &error_traceback);
+
+ if (error_value == NULL) {
+ return NULL;
+ }
+
+ string_io_buf = PyObject_Str(error_value);
+ /* Python does this too */
+ if (UNLIKELY(string_io_buf == NULL)) {
+ string_io_buf = PyUnicode_FromFormat(
+ "<unprintable %s object>", Py_TYPE(error_value)->tp_name);
+ }
+
+ PyErr_Restore(error_type, error_value, error_traceback);
+
+ PyErr_Print();
+ PyErr_Clear();
+ return string_io_buf;
+}
/* string conversion, escape non-unicode chars, coerce must be set to NULL */
const char *PyC_UnicodeAsByte(PyObject *py_str, PyObject **coerce)
@@ -568,7 +623,7 @@ void PyC_MainModule_Restore(PyObject *main_mod)
Py_XDECREF(main_mod);
}
-/* must be called before Py_Initialize, expects output of BLI_get_folder(BLENDER_PYTHON, NULL) */
+/* must be called before Py_Initialize, expects output of BKE_appdir_folder_id(BLENDER_PYTHON, NULL) */
void PyC_SetHomePath(const char *py_path_bundle)
{
if (py_path_bundle == NULL) {
@@ -616,6 +671,7 @@ void PyC_SetHomePath(const char *py_path_bundle)
bool PyC_IsInterpreterActive(void)
{
+ /* expanded PyThreadState_GET which won't throw an exception */
return (((PyThreadState *)_Py_atomic_load_relaxed(&_PyThreadState_Current)) != NULL);
}
@@ -664,8 +720,7 @@ void PyC_RunQuicky(const char *filepath, int n, ...)
PyErr_Print();
PyErr_Clear();
- PyList_SET_ITEM(values, i, Py_None); /* hold user */
- Py_INCREF(Py_None);
+ PyList_SET_ITEM(values, i, Py_INCREF_RET(Py_None)); /* hold user */
sizes[i] = 0;
}
@@ -975,3 +1030,21 @@ int PyC_RunString_AsNumber(const char *expr, double *value, const char *filename
return error_ret;
}
+
+/**
+ * Use with PyArg_ParseTuple's "O&" formatting.
+ */
+int PyC_ParseBool(PyObject *o, void *p)
+{
+ bool *bool_p = p;
+ long value;
+ if (((value = PyLong_AsLong(o)) == -1) || !ELEM(value, 0, 1)) {
+ PyErr_Format(PyExc_ValueError,
+ "expected a bool or int (0/1), got %s",
+ Py_TYPE(o)->tp_name);
+ return 0;
+ }
+
+ *bool_p = value ? true : false;
+ return 1;
+}
diff --git a/source/blender/python/generic/py_capi_utils.h b/source/blender/python/generic/py_capi_utils.h
index 559a8e15678..0ebc06ce2fa 100644
--- a/source/blender/python/generic/py_capi_utils.h
+++ b/source/blender/python/generic/py_capi_utils.h
@@ -32,16 +32,22 @@ void PyC_ObSpit(const char *name, PyObject *var);
void PyC_LineSpit(void);
void PyC_StackSpit(void);
PyObject * PyC_ExceptionBuffer(void);
+PyObject * PyC_ExceptionBuffer_Simple(void);
PyObject * PyC_Object_GetAttrStringArgs(PyObject *o, Py_ssize_t n, ...);
PyObject * PyC_FrozenSetFromStrings(const char **strings);
PyObject * PyC_Err_Format_Prefix(PyObject *exception_type_prefix, const char *format, ...);
void PyC_FileAndNum(const char **filename, int *lineno);
void PyC_FileAndNum_Safe(const char **filename, int *lineno); /* checks python is running */
-int PyC_AsArray(void *array, PyObject *value, const Py_ssize_t length,
- const PyTypeObject *type, const bool is_double, const char *error_prefix);
+int PyC_AsArray_FAST(
+ void *array, PyObject *value_fast, const Py_ssize_t length,
+ const PyTypeObject *type, const bool is_double, const char *error_prefix);
+int PyC_AsArray(
+ void *array, PyObject *value, const Py_ssize_t length,
+ const PyTypeObject *type, const bool is_double, const char *error_prefix);
PyObject * PyC_FromArray(const void *array, int length, const PyTypeObject *type,
const bool is_double, const char *error_prefix);
void PyC_Tuple_Fill(PyObject *tuple, PyObject *value);
+void PyC_List_Fill(PyObject *list, PyObject *value);
/* follow http://www.python.org/dev/peps/pep-0383/ */
PyObject * PyC_UnicodeFromByte(const char *str);
@@ -75,4 +81,6 @@ PyObject *PyC_FlagSet_FromBitfield(PyC_FlagSet *items, int flag);
int PyC_RunString_AsNumber(const char *expr, double *value, const char *filename);
+int PyC_ParseBool(PyObject *o, void *p);
+
#endif /* __PY_CAPI_UTILS_H__ */
diff --git a/source/blender/python/generic/python_utildefines.h b/source/blender/python/generic/python_utildefines.h
new file mode 100644
index 00000000000..f7d3e7a8b4a
--- /dev/null
+++ b/source/blender/python/generic/python_utildefines.h
@@ -0,0 +1,60 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/python/generic/python_utildefines.h
+ * \ingroup pygen
+ * \brief header-only utilities
+ * \note light addition to Python.h, use py_capi_utils.h for larger features.
+ */
+
+#ifndef __PYTHON_UTILDEFINES_H__
+#define __PYTHON_UTILDEFINES_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define PyTuple_SET_ITEMS(op_arg, ...) \
+{ \
+ PyTupleObject *op = (PyTupleObject *)op_arg; \
+ PyObject **ob_items = op->ob_item; \
+ CHECK_TYPE_ANY(op_arg, PyObject *, PyTupleObject *); \
+ BLI_assert(_VA_NARGS_COUNT(__VA_ARGS__) == PyTuple_GET_SIZE(op)); \
+ ARRAY_SET_ITEMS(ob_items, __VA_ARGS__); \
+} (void)0
+
+/* wrap Py_INCREF & return the result,
+ * use sparingly to avoid comma operator or temp var assignment */
+BLI_INLINE PyObject *Py_INCREF_RET(PyObject *op) { Py_INCREF(op); return op; }
+
+/* append & transfer ownership to the list, avoids inline Py_DECREF all over (which is quite a large macro) */
+BLI_INLINE int PyList_APPEND(PyObject *op, PyObject *v)
+{
+ int ret = PyList_Append(op, v);
+ Py_DecRef(v);
+ return ret;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __PYTHON_UTILDEFINES_H__ */
+
diff --git a/source/blender/python/intern/CMakeLists.txt b/source/blender/python/intern/CMakeLists.txt
index 70b4df7d6fe..cd2a9fd8584 100644
--- a/source/blender/python/intern/CMakeLists.txt
+++ b/source/blender/python/intern/CMakeLists.txt
@@ -25,12 +25,13 @@
set(INC
..
- ../../blenfont
../../blenkernel
../../blenlib
../../blenloader
+ ../../blentranslation
../../editors/include
../../gpu
+ ../../imbuf
../../makesdna
../../makesrna
../../windowmanager
@@ -47,11 +48,12 @@ set(SRC
gpu.c
bpy.c
bpy_app.c
- bpy_app_ffmpeg.c
bpy_app_build_options.c
+ bpy_app_ffmpeg.c
bpy_app_handlers.c
bpy_app_ocio.c
bpy_app_oiio.c
+ bpy_app_sdl.c
bpy_app_translations.c
bpy_driver.c
bpy_interface.c
@@ -68,17 +70,19 @@ set(SRC
bpy_rna_callback.c
bpy_traceback.c
bpy_util.c
+ bpy_utils_previews.c
bpy_utils_units.c
stubs.c
gpu.h
bpy.h
bpy_app.h
- bpy_app_ffmpeg.h
bpy_app_build_options.h
+ bpy_app_ffmpeg.h
bpy_app_handlers.h
bpy_app_ocio.h
bpy_app_oiio.h
+ bpy_app_sdl.h
bpy_app_translations.h
bpy_driver.h
bpy_intern_string.h
@@ -92,6 +96,7 @@ set(SRC
bpy_rna_callback.h
bpy_traceback.h
bpy_util.h
+ bpy_utils_previews.h
bpy_utils_units.h
../BPY_extern.h
)
@@ -210,9 +215,19 @@ if(WITH_OPENAL)
endif()
if(WITH_SDL)
+ list(APPEND INC_SYS
+ ${SDL_INCLUDE_DIR}
+ )
add_definitions(-DWITH_SDL)
endif()
+if(WITH_SDL_DYNLOAD)
+ list(APPEND INC
+ ../../../../extern/sdlew/include
+ )
+ add_definitions(-DWITH_SDL_DYNLOAD)
+endif()
+
if(WITH_JACK)
add_definitions(-DWITH_JACK)
endif()
@@ -260,5 +275,6 @@ if(WITH_PLAYER)
add_definitions(-DWITH_PLAYER)
endif()
+add_definitions(${GL_DEFINITIONS})
blender_add_lib(bf_python "${SRC}" "${INC}" "${INC_SYS}")
diff --git a/source/blender/python/intern/bpy.c b/source/blender/python/intern/bpy.c
index 134e718bce5..fa2ad3a4803 100644
--- a/source/blender/python/intern/bpy.c
+++ b/source/blender/python/intern/bpy.c
@@ -31,10 +31,9 @@
#include <Python.h>
#include "BLI_utildefines.h"
-#include "BLI_path_util.h"
#include "BLI_string.h"
-#include "BKE_main.h"
+#include "BKE_appdir.h"
#include "BKE_global.h" /* XXX, G.main only */
#include "BKE_blender.h"
#include "BKE_bpath.h"
@@ -49,18 +48,14 @@
#include "bpy_props.h"
#include "bpy_library.h"
#include "bpy_operator.h"
+#include "bpy_utils_previews.h"
#include "bpy_utils_units.h"
#include "../generic/py_capi_utils.h"
-
-#include "MEM_guardedalloc.h"
+#include "../generic/python_utildefines.h"
/* external util modules */
#include "../generic/idprop_py_api.h"
-#include "../generic/bgl.h"
-#include "../generic/blf_py_api.h"
-#include "../generic/blf_py_api.h"
-#include "../mathutils/mathutils.h"
#ifdef WITH_FREESTYLE
# include "BPy_Freestyle.h"
@@ -82,11 +77,11 @@ static PyObject *bpy_script_paths(PyObject *UNUSED(self))
PyObject *item;
const char *path;
- path = BLI_get_folder(BLENDER_SYSTEM_SCRIPTS, NULL);
+ path = BKE_appdir_folder_id(BLENDER_SYSTEM_SCRIPTS, NULL);
item = PyC_UnicodeFromByte(path ? path : "");
BLI_assert(item != NULL);
PyTuple_SET_ITEM(ret, 0, item);
- path = BLI_get_folder(BLENDER_USER_SCRIPTS, NULL);
+ path = BKE_appdir_folder_id(BLENDER_USER_SCRIPTS, NULL);
item = PyC_UnicodeFromByte(path ? path : "");
BLI_assert(item != NULL);
PyTuple_SET_ITEM(ret, 1, item);
@@ -96,10 +91,7 @@ static PyObject *bpy_script_paths(PyObject *UNUSED(self))
static bool bpy_blend_paths_visit_cb(void *userdata, char *UNUSED(path_dst), const char *path_src)
{
- PyObject *list = (PyObject *)userdata;
- PyObject *item = PyC_UnicodeFromByte(path_src);
- PyList_Append(list, item);
- Py_DECREF(item);
+ PyList_APPEND((PyObject *)userdata, PyC_UnicodeFromByte(path_src));
return false; /* never edits the path */
}
@@ -122,13 +114,16 @@ static PyObject *bpy_blend_paths(PyObject *UNUSED(self), PyObject *args, PyObjec
int flag = 0;
PyObject *list;
- int absolute = false;
- int packed = false;
- int local = false;
+ bool absolute = false;
+ bool packed = false;
+ bool local = false;
static const char *kwlist[] = {"absolute", "packed", "local", NULL};
- if (!PyArg_ParseTupleAndKeywords(args, kw, "|iii:blend_paths",
- (char **)kwlist, &absolute, &packed, &local))
+ if (!PyArg_ParseTupleAndKeywords(
+ args, kw, "|O&O&O&:blend_paths", (char **)kwlist,
+ PyC_ParseBool, &absolute,
+ PyC_ParseBool, &packed,
+ PyC_ParseBool, &local))
{
return NULL;
}
@@ -168,11 +163,11 @@ static PyObject *bpy_user_resource(PyObject *UNUSED(self), PyObject *args, PyObj
return NULL;
}
- /* same logic as BLI_get_folder_create(), but best leave it up to the script author to create */
- path = BLI_get_folder(folder_id, subdir);
+ /* same logic as BKE_appdir_folder_id_create(), but best leave it up to the script author to create */
+ path = BKE_appdir_folder_id(folder_id, subdir);
if (!path)
- path = BLI_get_user_folder_notest(folder_id, subdir);
+ path = BKE_appdir_folder_id_user_notest(folder_id, subdir);
return PyC_UnicodeFromByte(path ? path : "");
}
@@ -211,7 +206,7 @@ static PyObject *bpy_resource_path(PyObject *UNUSED(self), PyObject *args, PyObj
return NULL;
}
- path = BLI_get_folder_version(folder_id, (major * 100) + minor, false);
+ path = BKE_appdir_folder_id_version(folder_id, (major * 100) + minor, false);
return PyC_UnicodeFromByte(path ? path : "");
}
@@ -296,7 +291,7 @@ void BPy_init_modules(void)
PyObject *mod;
/* Needs to be first since this dir is needed for future modules */
- const char * const modpath = BLI_get_folder(BLENDER_SYSTEM_SCRIPTS, "modules");
+ const char * const modpath = BKE_appdir_folder_id(BLENDER_SYSTEM_SCRIPTS, "modules");
if (modpath) {
// printf("bpy: found module path '%s'.\n", modpath);
PyObject *sys_path = PySys_GetObject("path"); /* borrow */
@@ -339,6 +334,7 @@ void BPy_init_modules(void)
PyModule_AddObject(mod, "ops", BPY_operator_module());
PyModule_AddObject(mod, "app", BPY_app_struct());
PyModule_AddObject(mod, "_utils_units", BPY_utils_units());
+ PyModule_AddObject(mod, "_utils_previews", BPY_utils_previews_module());
/* bpy context */
RNA_pointer_create(NULL, &RNA_Context, (void *)BPy_GetContext(), &ctx_ptr);
diff --git a/source/blender/python/intern/bpy_app.c b/source/blender/python/intern/bpy_app.c
index 16cdd44ce38..90d97cad880 100644
--- a/source/blender/python/intern/bpy_app.c
+++ b/source/blender/python/intern/bpy_app.c
@@ -36,6 +36,7 @@
#include "bpy_app_ffmpeg.h"
#include "bpy_app_ocio.h"
#include "bpy_app_oiio.h"
+#include "bpy_app_sdl.h"
#include "bpy_app_build_options.h"
#include "bpy_app_translations.h"
@@ -44,13 +45,17 @@
#include "bpy_driver.h"
#include "BLI_utildefines.h"
-#include "BLI_path_util.h"
+#include "BKE_appdir.h"
#include "BKE_blender.h"
#include "BKE_global.h"
-#include "structseq.h"
+
+#include "DNA_ID.h"
+
+#include "UI_interface_icons.h"
#include "../generic/py_capi_utils.h"
+#include "../generic/python_utildefines.h"
#ifdef BUILD_DATE
extern char build_date[];
@@ -97,6 +102,7 @@ static PyStructSequence_Field app_info_fields[] = {
{(char *)"ffmpeg", (char *)"FFmpeg library information backend"},
{(char *)"ocio", (char *)"OpenColorIO library information backend"},
{(char *)"oiio", (char *)"OpenImageIO library information backend"},
+ {(char *)"sdl", (char *)"SDL 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"},
@@ -135,7 +141,7 @@ static PyObject *make_app_info(void)
SetStrItem(STRINGIFY(BLENDER_VERSION_CHAR));
SetStrItem(STRINGIFY(BLENDER_VERSION_CYCLE));
- SetStrItem(BLI_program_path());
+ SetStrItem(BKE_appdir_program_path());
SetObjItem(PyBool_FromLong(G.background));
/* build info, use bytes since we can't assume _any_ encoding:
@@ -173,6 +179,7 @@ static PyObject *make_app_info(void)
SetObjItem(BPY_app_ffmpeg_struct());
SetObjItem(BPY_app_ocio_struct());
SetObjItem(BPY_app_oiio_struct());
+ SetObjItem(BPY_app_sdl_struct());
SetObjItem(BPY_app_build_options_struct());
SetObjItem(BPY_app_handlers_struct());
SetObjItem(BPY_app_translations_struct());
@@ -217,6 +224,33 @@ static int bpy_app_debug_set(PyObject *UNUSED(self), PyObject *value, void *clos
return 0;
}
+
+
+PyDoc_STRVAR(bpy_app_binary_path_python_doc,
+"String, the path to the python executable (read-only)"
+);
+static PyObject *bpy_app_binary_path_python_get(PyObject *UNUSED(self), void *UNUSED(closure))
+{
+ /* refcount is held in BlenderAppType.tp_dict */
+ static PyObject *ret = NULL;
+
+ if (ret == NULL) {
+ /* only run once */
+ char fullpath[1024];
+ BKE_appdir_program_python_search(
+ fullpath, sizeof(fullpath),
+ PY_MAJOR_VERSION, PY_MINOR_VERSION);
+ ret = PyC_UnicodeFromByte(fullpath);
+ PyDict_SetItemString(BlenderAppType.tp_dict, "binary_path_python", ret);
+ }
+ else {
+ Py_INCREF(ret);
+ }
+
+ return ret;
+
+}
+
PyDoc_STRVAR(bpy_app_debug_value_doc,
"Int, number which can be set to non-zero values for testing purposes"
);
@@ -250,7 +284,7 @@ PyDoc_STRVAR(bpy_app_tempdir_doc,
);
static PyObject *bpy_app_tempdir_get(PyObject *UNUSED(self), void *UNUSED(closure))
{
- return PyC_UnicodeFromByte(BLI_temp_dir_session());
+ return PyC_UnicodeFromByte(BKE_tempdir_session());
}
PyDoc_STRVAR(bpy_app_driver_dict_doc,
@@ -265,8 +299,15 @@ static PyObject *bpy_app_driver_dict_get(PyObject *UNUSED(self), void *UNUSED(cl
}
}
- Py_INCREF(bpy_pydriver_Dict);
- return bpy_pydriver_Dict;
+ return Py_INCREF_RET(bpy_pydriver_Dict);
+}
+
+PyDoc_STRVAR(bpy_app_preview_render_size_doc,
+"Reference size for icon/preview renders (read-only)"
+);
+static PyObject *bpy_app_preview_render_size_get(PyObject *UNUSED(self), void *closure)
+{
+ return PyLong_FromLong((long)UI_preview_render_size(GET_INT_FROM_POINTER(closure)));
}
static PyObject *bpy_app_autoexec_fail_message_get(PyObject *UNUSED(self), void *UNUSED(closure))
@@ -284,11 +325,18 @@ static PyGetSetDef bpy_app_getsets[] = {
{(char *)"debug_handlers", bpy_app_debug_get, bpy_app_debug_set, (char *)bpy_app_debug_doc, (void *)G_DEBUG_HANDLERS},
{(char *)"debug_wm", bpy_app_debug_get, bpy_app_debug_set, (char *)bpy_app_debug_doc, (void *)G_DEBUG_WM},
{(char *)"debug_depsgraph", bpy_app_debug_get, bpy_app_debug_set, (char *)bpy_app_debug_doc, (void *)G_DEBUG_DEPSGRAPH},
+ {(char *)"debug_simdata", bpy_app_debug_get, bpy_app_debug_set, (char *)bpy_app_debug_doc, (void *)G_DEBUG_SIMDATA},
+ {(char *)"debug_gpumem", bpy_app_debug_get, bpy_app_debug_set, (char *)bpy_app_debug_doc, (void *)G_DEBUG_GPU_MEM},
+
+ {(char *)"binary_path_python", bpy_app_binary_path_python_get, NULL, (char *)bpy_app_binary_path_python_doc, NULL},
{(char *)"debug_value", bpy_app_debug_value_get, bpy_app_debug_value_set, (char *)bpy_app_debug_value_doc, NULL},
{(char *)"tempdir", bpy_app_tempdir_get, NULL, (char *)bpy_app_tempdir_doc, NULL},
{(char *)"driver_namespace", bpy_app_driver_dict_get, NULL, (char *)bpy_app_driver_dict_doc, NULL},
+ {(char *)"render_icon_size", bpy_app_preview_render_size_get, NULL, (char *)bpy_app_preview_render_size_doc, (void *)ICON_SIZE_ICON},
+ {(char *)"render_preview_size", bpy_app_preview_render_size_get, NULL, (char *)bpy_app_preview_render_size_doc, (void *)ICON_SIZE_PREVIEW},
+
/* security */
{(char *)"autoexec_fail", bpy_app_global_flag_get, NULL, NULL, (void *)G_SCRIPT_AUTOEXEC_FAIL},
{(char *)"autoexec_fail_quiet", bpy_app_global_flag_get, NULL, NULL, (void *)G_SCRIPT_AUTOEXEC_FAIL_QUIET},
diff --git a/source/blender/python/intern/bpy_app_build_options.c b/source/blender/python/intern/bpy_app_build_options.c
index 022713558d7..975d76ca42d 100644
--- a/source/blender/python/intern/bpy_app_build_options.c
+++ b/source/blender/python/intern/bpy_app_build_options.c
@@ -57,6 +57,7 @@ static PyStructSequence_Field app_builtopts_info_fields[] = {
{(char *)"international", NULL},
{(char *)"openal", NULL},
{(char *)"sdl", NULL},
+ {(char *)"sdl_dynload", NULL},
{(char *)"jack", NULL},
{(char *)"libmv", NULL},
{(char *)"mod_boolean", NULL},
@@ -230,6 +231,12 @@ static PyObject *make_builtopts_info(void)
SetObjIncref(Py_False);
#endif
+#ifdef WITH_SDL_DYNLOAD
+ SetObjIncref(Py_True);
+#else
+ SetObjIncref(Py_False);
+#endif
+
#ifdef WITH_JACK
SetObjIncref(Py_True);
#else
diff --git a/source/blender/python/intern/bpy_app_handlers.c b/source/blender/python/intern/bpy_app_handlers.c
index 41ca2d49ed6..6a8b0b065c2 100644
--- a/source/blender/python/intern/bpy_app_handlers.c
+++ b/source/blender/python/intern/bpy_app_handlers.c
@@ -37,6 +37,8 @@
#include "bpy_rna.h"
#include "bpy_app_handlers.h"
+#include "../generic/python_utildefines.h"
+
#include "BPY_extern.h"
void bpy_app_generic_callback(struct Main *main, struct ID *id, void *arg);
@@ -44,23 +46,24 @@ void bpy_app_generic_callback(struct Main *main, struct ID *id, void *arg);
static PyTypeObject BlenderAppCbType;
static PyStructSequence_Field app_cb_info_fields[] = {
- {(char *)"frame_change_pre", (char *)"Callback list - on frame change for playback and rendering (before)"},
- {(char *)"frame_change_post", (char *)"Callback list - on frame change for playback and rendering (after)"},
- {(char *)"render_pre", (char *)"Callback list - on render (before)"},
- {(char *)"render_post", (char *)"Callback list - on render (after)"},
- {(char *)"render_stats", (char *)"Callback list - on printing render statistics"},
- {(char *)"render_init", (char *)"Callback list - on initialization of a render job"},
- {(char *)"render_complete", (char *)"Callback list - on completion of render job"},
- {(char *)"render_cancel", (char *)"Callback list - on canceling a render job"},
- {(char *)"load_pre", (char *)"Callback list - on loading a new blend file (before)"},
- {(char *)"load_post", (char *)"Callback list - on loading a new blend file (after)"},
- {(char *)"save_pre", (char *)"Callback list - on saving a blend file (before)"},
- {(char *)"save_post", (char *)"Callback list - on saving a blend file (after)"},
- {(char *)"scene_update_pre", (char *)"Callback list - on updating the scenes data (before)"},
- {(char *)"scene_update_post", (char *)"Callback list - on updating the scenes data (after)"},
- {(char *)"game_pre", (char *)"Callback list - on starting the game engine"},
- {(char *)"game_post", (char *)"Callback list - on ending the game engine"},
- {(char *)"version_update", (char *)"Callback list - on ending the versioning code"},
+ {(char *)"frame_change_pre", (char *)"on frame change for playback and rendering (before)"},
+ {(char *)"frame_change_post", (char *)"on frame change for playback and rendering (after)"},
+ {(char *)"render_pre", (char *)"on render (before)"},
+ {(char *)"render_post", (char *)"on render (after)"},
+ {(char *)"render_write", (char *)"on writing a render frame (directly after the frame is written)"},
+ {(char *)"render_stats", (char *)"on printing render statistics"},
+ {(char *)"render_init", (char *)"on initialization of a render job"},
+ {(char *)"render_complete", (char *)"on completion of render job"},
+ {(char *)"render_cancel", (char *)"on canceling a render job"},
+ {(char *)"load_pre", (char *)"on loading a new blend file (before)"},
+ {(char *)"load_post", (char *)"on loading a new blend file (after)"},
+ {(char *)"save_pre", (char *)"on saving a blend file (before)"},
+ {(char *)"save_post", (char *)"on saving a blend file (after)"},
+ {(char *)"scene_update_pre", (char *)"on updating the scenes data (before)"},
+ {(char *)"scene_update_post", (char *)"on updating the scenes data (after)"},
+ {(char *)"game_pre", (char *)"on starting the game engine"},
+ {(char *)"game_post", (char *)"on ending the game engine"},
+ {(char *)"version_update", (char *)"on ending the versioning code"},
/* sets the permanent tag */
# define APP_CB_OTHER_FIELDS 1
@@ -71,7 +74,7 @@ static PyStructSequence_Field app_cb_info_fields[] = {
static PyStructSequence_Desc app_cb_info_desc = {
(char *)"bpy.app.handlers", /* name */
- (char *)"This module contains callbacks", /* doc */
+ (char *)"This module contains callback lists", /* doc */
app_cb_info_fields, /* fields */
ARRAY_SIZE(app_cb_info_fields) - 1
};
@@ -240,8 +243,11 @@ PyObject *BPY_app_handlers_struct(void)
void BPY_app_handlers_reset(const short do_all)
{
+ PyGILState_STATE gilstate;
int pos = 0;
+ gilstate = PyGILState_Ensure();
+
if (do_all) {
for (pos = 0; pos < BLI_CB_EVT_TOT; pos++) {
/* clear list */
@@ -279,6 +285,8 @@ void BPY_app_handlers_reset(const short do_all)
Py_DECREF(perm_id_str);
}
+
+ PyGILState_Release(gilstate);
}
/* the actual callback - not necessarily called from py */
@@ -300,8 +308,7 @@ void bpy_app_generic_callback(struct Main *UNUSED(main), struct ID *id, void *ar
PyTuple_SET_ITEM(args, 0, pyrna_struct_CreatePyObject(&id_ptr));
}
else {
- PyTuple_SET_ITEM(args, 0, Py_None);
- Py_INCREF(Py_None);
+ PyTuple_SET_ITEM(args, 0, Py_INCREF_RET(Py_None));
}
/* Iterate the list and run the callbacks
diff --git a/source/blender/python/intern/bpy_app_sdl.c b/source/blender/python/intern/bpy_app_sdl.c
new file mode 100644
index 00000000000..c91595b5900
--- /dev/null
+++ b/source/blender/python/intern/bpy_app_sdl.c
@@ -0,0 +1,136 @@
+/*
+ * ***** 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, Sybren A. Stuvel
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/python/intern/bpy_app_sdl.c
+ * \ingroup pythonintern
+ */
+
+#include <Python.h>
+#include "BLI_utildefines.h"
+
+#include "bpy_app_sdl.h"
+
+#ifdef WITH_SDL
+# include "SDL.h"
+# ifdef WITH_SDL_DYNLOAD
+# include "sdlew.h"
+# endif
+#endif
+
+static PyTypeObject BlenderAppSDLType;
+
+static PyStructSequence_Field app_sdl_info_fields[] = {
+ {(char *)"supported", (char *)("Boolean, True when Blender is built with SDL support")},
+ {(char *)"version", (char *)("The SDL version as a tuple of 3 numbers")},
+ {(char *)"version_string", (char *)("The SDL version formatted as a string")},
+ {(char *)"available", (char *)("Boolean, True when SDL is available. This is False when "
+ "either *supported* is False, or *dynload* is True and "
+ "Blender cannot find the correct library.")},
+ {NULL}
+};
+
+static PyStructSequence_Desc app_sdl_info_desc = {
+ (char *)"bpy.app.sdl", /* name */
+ (char *)"This module contains information about SDL blender is linked against", /* doc */
+ app_sdl_info_fields, /* fields */
+ ARRAY_SIZE(app_sdl_info_fields) - 1
+};
+
+static PyObject *make_sdl_info(void)
+{
+ PyObject *sdl_info;
+ int pos = 0;
+#ifdef WITH_SDL
+ bool sdl_available = false;
+ SDL_version version = {0, 0, 0};
+#endif
+
+ sdl_info = PyStructSequence_New(&BlenderAppSDLType);
+ if (sdl_info == NULL) {
+ return NULL;
+ }
+
+#define SetStrItem(str) \
+ PyStructSequence_SET_ITEM(sdl_info, pos++, PyUnicode_FromString(str))
+
+#define SetObjItem(obj) \
+ PyStructSequence_SET_ITEM(sdl_info, pos++, obj)
+
+#ifdef WITH_SDL
+ SetObjItem(PyBool_FromLong(1));
+
+# ifdef WITH_SDL_DYNLOAD
+ if (sdlewInit() == SDLEW_SUCCESS) {
+ SDL_GetVersion(&version);
+ sdl_available = true;
+ }
+# else // WITH_SDL_DYNLOAD=OFF
+ sdl_available = true;
+# if SDL_MAJOR_VERSION >= 2
+ SDL_GetVersion(&version);
+# else
+ SDL_VERSION(&version);
+# endif
+# endif
+
+ SetObjItem(Py_BuildValue("(iii)", version.major, version.minor, version.patch));
+ if (sdl_available) {
+ SetObjItem(PyUnicode_FromFormat("%d.%d.%d", version.major, version.minor, version.patch));
+ }
+ else {
+ SetStrItem("Unknown");
+ }
+ SetObjItem(PyBool_FromLong(sdl_available));
+
+#else // WITH_SDL=OFF
+ SetObjItem(PyBool_FromLong(0));
+ SetObjItem(Py_BuildValue("(iii)", 0, 0, 0));
+ SetStrItem("Unknown");
+ SetObjItem(PyBool_FromLong(0));
+#endif
+
+ if (PyErr_Occurred()) {
+ Py_CLEAR(sdl_info);
+ return NULL;
+ }
+
+#undef SetStrItem
+#undef SetObjItem
+
+ return sdl_info;
+}
+
+PyObject *BPY_app_sdl_struct(void)
+{
+ PyObject *ret;
+
+ PyStructSequence_InitType(&BlenderAppSDLType, &app_sdl_info_desc);
+
+ ret = make_sdl_info();
+
+ /* prevent user from creating new instances */
+ BlenderAppSDLType.tp_init = NULL;
+ BlenderAppSDLType.tp_new = NULL;
+ BlenderAppSDLType.tp_hash = (hashfunc)_Py_HashPointer; /* without this we can't do set(sys.modules) [#29635] */
+
+ return ret;
+}
diff --git a/source/blender/compositor/intern/COM_ChannelInfo.cpp b/source/blender/python/intern/bpy_app_sdl.h
index 557075cdc80..e826a59de70 100644
--- a/source/blender/compositor/intern/COM_ChannelInfo.cpp
+++ b/source/blender/python/intern/bpy_app_sdl.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2011, Blender Foundation.
+ * ***** BEGIN GPL LICENSE BLOCK *****
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -15,21 +15,18 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
- * Contributor:
- * Jeroen Bakker
- * Monique Dewanchand
+ * Contributor(s): Sergey Sharybin, Sybren A. Stuvel
+ *
+ * ***** END GPL LICENSE BLOCK *****
*/
-#include "COM_ChannelInfo.h"
-#include "COM_defines.h"
-#include <stdio.h>
-
-/**
- * @brief create new ChannelInfo instance and sets the defaults.
+/** \file blender/python/intern/bpy_app_sdl.h
+ * \ingroup pythonintern
*/
-ChannelInfo::ChannelInfo()
-{
- this->m_number = 0;
- this->m_premultiplied = true;
- this->m_type = COM_CT_UNUSED;
-}
+
+#ifndef __BPY_APP_SDL_H__
+#define __BPY_APP_SDL_H__
+
+PyObject *BPY_app_sdl_struct(void);
+
+#endif /* __BPY_APP_SDL_H__ */
diff --git a/source/blender/python/intern/bpy_app_translations.c b/source/blender/python/intern/bpy_app_translations.c
index 0114e8e65e4..dfff67e6ca1 100644
--- a/source/blender/python/intern/bpy_app_translations.c
+++ b/source/blender/python/intern/bpy_app_translations.c
@@ -41,14 +41,14 @@
#include "MEM_guardedalloc.h"
-#include "BLF_translation.h"
+#include "BLT_translation.h"
+#include "BLT_lang.h"
#include "RNA_types.h"
-#include "RNA_access.h"
+#include "../generic/python_utildefines.h"
-typedef struct
-{
+typedef struct {
PyObject_HEAD
/* The string used to separate context from actual message in PY_TRANSLATE RNA props. */
const char *context_separator;
@@ -74,7 +74,7 @@ typedef struct GHashKey {
static GHashKey *_ghashutil_keyalloc(const void *msgctxt, const void *msgid)
{
GHashKey *key = MEM_mallocN(sizeof(GHashKey), "Py i18n GHashKey");
- key->msgctxt = BLI_strdup(BLF_is_default_context(msgctxt) ? BLF_I18NCONTEXT_DEFAULT_BPYRNA : msgctxt);
+ key->msgctxt = BLI_strdup(BLT_is_default_context(msgctxt) ? BLT_I18NCONTEXT_DEFAULT_BPYRNA : msgctxt);
key->msgid = BLI_strdup(msgid);
return key;
}
@@ -134,7 +134,7 @@ static void _build_translations_cache(PyObject *py_messages, const char *locale)
/* For each py dict, we'll search for full locale, then language+country, then language+variant,
* then only language keys... */
- BLF_locale_explode(locale, &language, NULL, NULL, &language_country, &language_variant);
+ BLT_lang_locale_explode(locale, &language, NULL, NULL, &language_country, &language_variant);
/* Clear the cached ghash if needed, and create a new one. */
_clear_translations_cache();
@@ -191,7 +191,7 @@ static void _build_translations_cache(PyObject *py_messages, const char *locale)
else {
PyObject *tmp = PyTuple_GET_ITEM(pykey, 0);
if (tmp == Py_None) {
- msgctxt = BLF_I18NCONTEXT_DEFAULT_BPYRNA;
+ msgctxt = BLT_I18NCONTEXT_DEFAULT_BPYRNA;
}
else if (PyUnicode_Check(tmp)) {
msgctxt = _PyUnicode_AsString(tmp);
@@ -242,12 +242,9 @@ static void _build_translations_cache(PyObject *py_messages, const char *locale)
}
/* Clean up! */
- if (language)
- MEM_freeN(language);
- if (language_country)
- MEM_freeN(language_country);
- if (language_variant)
- MEM_freeN(language_variant);
+ MEM_SAFE_FREE(language);
+ MEM_SAFE_FREE(language_country);
+ MEM_SAFE_FREE(language_variant);
}
const char *BPY_app_translations_py_pgettext(const char *msgctxt, const char *msgid)
@@ -262,8 +259,8 @@ const char *BPY_app_translations_py_pgettext(const char *msgctxt, const char *ms
if (!_translations)
return msgid;
- tmp = BLF_lang_get();
- if (strcmp(tmp, locale) || !_translations_cache) {
+ tmp = BLT_lang_get();
+ if (!STREQ(tmp, locale) || !_translations_cache) {
PyGILState_STATE _py_state;
BLI_strncpy(locale, tmp, STATIC_LOCALE_SIZE);
@@ -383,10 +380,10 @@ static PyObject *app_translations_py_messages_unregister(BlenderAppTranslations
static PyTypeObject BlenderAppTranslationsContextsType;
-static BLF_i18n_contexts_descriptor _contexts[] = BLF_I18NCONTEXTS_DESC;
+static BLT_i18n_contexts_descriptor _contexts[] = BLT_I18NCONTEXTS_DESC;
/* These fields are just empty placeholders, actual values get set in app_translations_struct().
- * This allows us to avoid many handwriting, and above all, to keep all context definition stuff in BLF_translation.h!
+ * This allows us to avoid many handwriting, and above all, to keep all context definition stuff in BLT_translation.h!
*/
static PyStructSequence_Field
app_translations_contexts_fields[ARRAY_SIZE(_contexts)] = {{NULL}};
@@ -401,7 +398,7 @@ static PyStructSequence_Desc app_translations_contexts_desc = {
static PyObject *app_translations_contexts_make(void)
{
PyObject *translations_contexts;
- BLF_i18n_contexts_descriptor *ctxt;
+ BLT_i18n_contexts_descriptor *ctxt;
int pos = 0;
translations_contexts = PyStructSequence_New(&BlenderAppTranslationsContextsType);
@@ -410,7 +407,7 @@ static PyObject *app_translations_contexts_make(void)
}
#define SetObjString(item) PyStructSequence_SET_ITEM(translations_contexts, pos++, PyUnicode_FromString((item)))
-#define SetObjNone() Py_INCREF(Py_None); PyStructSequence_SET_ITEM(translations_contexts, pos++, Py_None)
+#define SetObjNone() PyStructSequence_SET_ITEM(translations_contexts, pos++, Py_INCREF_RET(Py_None))
for (ctxt = _contexts; ctxt->c_id; ctxt++) {
if (ctxt->value) {
@@ -430,11 +427,11 @@ static PyObject *app_translations_contexts_make(void)
/***** Main BlenderAppTranslations Py object definition *****/
PyDoc_STRVAR(app_translations_contexts_doc,
- "A named tuple containing all pre-defined translation contexts.\n"
- "\n"
- ".. warning::\n"
- " Never use a (new) context starting with \"" BLF_I18NCONTEXT_DEFAULT_BPYRNA "\", it would be internally \n"
- " assimilated as the default one!\n"
+"A named tuple containing all pre-defined translation contexts.\n"
+"\n"
+".. warning::\n"
+" Never use a (new) context starting with \"" BLT_I18NCONTEXT_DEFAULT_BPYRNA "\", it would be internally \n"
+" assimilated as the default one!\n"
);
PyDoc_STRVAR(app_translations_contexts_C_to_py_doc,
@@ -450,12 +447,12 @@ static PyMemberDef app_translations_members[] = {
};
PyDoc_STRVAR(app_translations_locale_doc,
- "The actual locale currently in use (will always return a void string when Blender is built without "
- "internationalization support)."
+"The actual locale currently in use (will always return a void string when Blender is built without "
+"internationalization support)."
);
static PyObject *app_translations_locale_get(PyObject *UNUSED(self), void *UNUSED(userdata))
{
- return PyUnicode_FromString(BLF_lang_get());
+ return PyUnicode_FromString(BLT_lang_get());
}
/* Note: defining as getter, as (even if quite unlikely), this *may* change during runtime... */
@@ -463,7 +460,7 @@ PyDoc_STRVAR(app_translations_locales_doc, "All locales currently known by Blend
static PyObject *app_translations_locales_get(PyObject *UNUSED(self), void *UNUSED(userdata))
{
PyObject *ret;
- EnumPropertyItem *it, *items = BLF_RNA_lang_enum_properties();
+ EnumPropertyItem *it, *items = BLT_lang_RNA_enum_properties();
int num_locales = 0, pos = 0;
if (items) {
@@ -508,7 +505,7 @@ static PyObject *_py_pgettext(PyObject *args, PyObject *kw, const char *(*_pgett
return NULL;
}
- return PyUnicode_FromString((*_pgettext)(msgctxt ? msgctxt : BLF_I18NCONTEXT_DEFAULT, msgid));
+ return PyUnicode_FromString((*_pgettext)(msgctxt ? msgctxt : BLT_I18NCONTEXT_DEFAULT, msgid));
#else
PyObject *msgid, *msgctxt;
(void)_pgettext;
@@ -520,9 +517,7 @@ static PyObject *_py_pgettext(PyObject *args, PyObject *kw, const char *(*_pgett
return NULL;
}
- Py_INCREF(msgid);
-
- return msgid;
+ return Py_INCREF_RET(msgid);
#endif
}
@@ -533,7 +528,7 @@ PyDoc_STRVAR(app_translations_pgettext_doc,
"\n"
" .. note::\n"
" The ``(msgid, msgctxt)`` parameters order has been switched compared to gettext function, to allow\n"
-" single-parameter calls (context then defaults to BLF_I18NCONTEXT_DEFAULT).\n"
+" single-parameter calls (context then defaults to BLT_I18NCONTEXT_DEFAULT).\n"
"\n"
" .. note::\n"
" You should really rarely need to use this function in regular addon code, as all translation should be\n"
@@ -545,14 +540,14 @@ PyDoc_STRVAR(app_translations_pgettext_doc,
"\n"
" :arg msgid: The string to translate.\n"
" :type msgid: string\n"
-" :arg msgctxt: The translation context (defaults to BLF_I18NCONTEXT_DEFAULT).\n"
+" :arg msgctxt: The translation context (defaults to BLT_I18NCONTEXT_DEFAULT).\n"
" :type msgctxt: string or None\n"
" :return: The translated string (or msgid if no translation was found).\n"
"\n"
);
static PyObject *app_translations_pgettext(BlenderAppTranslations *UNUSED(self), PyObject *args, PyObject *kw)
{
- return _py_pgettext(args, kw, BLF_pgettext);
+ return _py_pgettext(args, kw, BLT_pgettext);
}
PyDoc_STRVAR(app_translations_pgettext_iface_doc,
@@ -565,14 +560,14 @@ PyDoc_STRVAR(app_translations_pgettext_iface_doc,
"\n"
" :arg msgid: The string to translate.\n"
" :type msgid: string\n"
-" :arg msgctxt: The translation context (defaults to BLF_I18NCONTEXT_DEFAULT).\n"
+" :arg msgctxt: The translation context (defaults to BLT_I18NCONTEXT_DEFAULT).\n"
" :type msgctxt: string or None\n"
" :return: The translated string (or msgid if no translation was found).\n"
"\n"
);
static PyObject *app_translations_pgettext_iface(BlenderAppTranslations *UNUSED(self), PyObject *args, PyObject *kw)
{
- return _py_pgettext(args, kw, BLF_translate_do_iface);
+ return _py_pgettext(args, kw, BLT_translate_do_iface);
}
PyDoc_STRVAR(app_translations_pgettext_tip_doc,
@@ -585,14 +580,14 @@ PyDoc_STRVAR(app_translations_pgettext_tip_doc,
"\n"
" :arg msgid: The string to translate.\n"
" :type msgid: string\n"
-" :arg msgctxt: The translation context (defaults to BLF_I18NCONTEXT_DEFAULT).\n"
+" :arg msgctxt: The translation context (defaults to BLT_I18NCONTEXT_DEFAULT).\n"
" :type msgctxt: string or None\n"
" :return: The translated string (or msgid if no translation was found).\n"
"\n"
);
static PyObject *app_translations_pgettext_tip(BlenderAppTranslations *UNUSED(self), PyObject *args, PyObject *kw)
{
- return _py_pgettext(args, kw, BLF_translate_do_tooltip);
+ return _py_pgettext(args, kw, BLT_translate_do_tooltip);
}
PyDoc_STRVAR(app_translations_pgettext_data_doc,
@@ -605,14 +600,14 @@ PyDoc_STRVAR(app_translations_pgettext_data_doc,
"\n"
" :arg msgid: The string to translate.\n"
" :type msgid: string\n"
-" :arg msgctxt: The translation context (defaults to BLF_I18NCONTEXT_DEFAULT).\n"
+" :arg msgctxt: The translation context (defaults to BLT_I18NCONTEXT_DEFAULT).\n"
" :type msgctxt: string or None\n"
" :return: The translated string (or ``msgid`` if no translation was found).\n"
"\n"
);
static PyObject *app_translations_pgettext_data(BlenderAppTranslations *UNUSED(self), PyObject *args, PyObject *kw)
{
- return _py_pgettext(args, kw, BLF_translate_do_new_dataname);
+ return _py_pgettext(args, kw, BLT_translate_do_new_dataname);
}
PyDoc_STRVAR(app_translations_locale_explode_doc,
@@ -632,6 +627,7 @@ PyDoc_STRVAR(app_translations_locale_explode_doc,
);
static PyObject *app_translations_locale_explode(BlenderAppTranslations *UNUSED(self), PyObject *args, PyObject *kw)
{
+ PyObject *ret_tuple;
static const char *kwlist[] = {"locale", NULL};
const char *locale;
char *language, *country, *variant, *language_country, *language_variant;
@@ -640,9 +636,17 @@ static PyObject *app_translations_locale_explode(BlenderAppTranslations *UNUSED(
return NULL;
}
- BLF_locale_explode(locale, &language, &country, &variant, &language_country, &language_variant);
+ BLT_lang_locale_explode(locale, &language, &country, &variant, &language_country, &language_variant);
- return Py_BuildValue("sssss", language, country, variant, language_country, language_variant);
+ ret_tuple = Py_BuildValue("sssss", language, country, variant, language_country, language_variant);
+
+ MEM_SAFE_FREE(language);
+ MEM_SAFE_FREE(country);
+ MEM_SAFE_FREE(variant);
+ MEM_SAFE_FREE(language_country);
+ MEM_SAFE_FREE(language_variant);
+
+ return ret_tuple;
}
static PyMethodDef app_translations_methods[] = {
@@ -672,7 +676,7 @@ static PyObject *app_translations_new(PyTypeObject *type, PyObject *UNUSED(args)
_translations = (BlenderAppTranslations *)type->tp_alloc(type, 0);
if (_translations) {
PyObject *py_ctxts;
- BLF_i18n_contexts_descriptor *ctxt;
+ BLT_i18n_contexts_descriptor *ctxt;
_translations->contexts = app_translations_contexts_make();
@@ -792,7 +796,7 @@ PyObject *BPY_app_translations_struct(void)
/* Let's finalize our contexts structseq definition! */
{
- BLF_i18n_contexts_descriptor *ctxt;
+ BLT_i18n_contexts_descriptor *ctxt;
PyStructSequence_Field *desc;
/* We really populate the contexts' fields here! */
@@ -817,3 +821,12 @@ PyObject *BPY_app_translations_struct(void)
return ret;
}
+
+void BPY_app_translations_end(void)
+{
+ /* Incase the object remains in a module's namespace, see T44127. */
+#ifdef WITH_INTERNATIONAL
+ _clear_translations_cache();
+#endif
+}
+
diff --git a/source/blender/python/intern/bpy_app_translations.h b/source/blender/python/intern/bpy_app_translations.h
index 704307574d0..e04c2484ecc 100644
--- a/source/blender/python/intern/bpy_app_translations.h
+++ b/source/blender/python/intern/bpy_app_translations.h
@@ -28,5 +28,6 @@
#define __BPY_APP_TRANSLATIONS_H__
PyObject *BPY_app_translations_struct(void);
+void BPY_app_translations_end(void);
#endif /* __BPY_APP_TRANSLATIONS_H__ */
diff --git a/source/blender/python/intern/bpy_driver.c b/source/blender/python/intern/bpy_driver.c
index b51de01103c..df848f6b60c 100644
--- a/source/blender/python/intern/bpy_driver.c
+++ b/source/blender/python/intern/bpy_driver.c
@@ -245,7 +245,7 @@ float BPY_driver_exec(ChannelDriver *driver, const float evaltime)
expr_vars = PyTuple_GET_ITEM(((PyObject *)driver->expr_comp), 1);
Py_XDECREF(expr_vars);
- expr_vars = PyTuple_New(BLI_countlist(&driver->variables));
+ expr_vars = PyTuple_New(BLI_listbase_count(&driver->variables));
PyTuple_SET_ITEM(((PyObject *)driver->expr_comp), 1, expr_vars);
for (dvar = driver->variables.first, i = 0; dvar; dvar = dvar->next) {
diff --git a/source/blender/python/intern/bpy_interface.c b/source/blender/python/intern/bpy_interface.c
index ddfbfecc46e..61477d0bd56 100644
--- a/source/blender/python/intern/bpy_interface.c
+++ b/source/blender/python/intern/bpy_interface.c
@@ -61,8 +61,11 @@
#include "bpy_traceback.h"
#include "bpy_intern_string.h"
+#include "bpy_app_translations.h"
+
#include "DNA_text_types.h"
+#include "BKE_appdir.h"
#include "BKE_context.h"
#include "BKE_text.h"
#include "BKE_main.h"
@@ -243,11 +246,11 @@ void BPY_python_start(int argc, const char **argv)
{
#ifndef WITH_PYTHON_MODULE
PyThreadState *py_tstate = NULL;
- const char *py_path_bundle = BLI_get_folder(BLENDER_SYSTEM_PYTHON, NULL);
+ const char *py_path_bundle = BKE_appdir_folder_id(BLENDER_SYSTEM_PYTHON, NULL);
/* not essential but nice to set our name */
static wchar_t program_path_wchar[FILE_MAX]; /* python holds a reference */
- BLI_strncpy_wchar_from_utf8(program_path_wchar, BLI_program_path(), ARRAY_SIZE(program_path_wchar));
+ BLI_strncpy_wchar_from_utf8(program_path_wchar, BKE_appdir_program_path(), ARRAY_SIZE(program_path_wchar));
Py_SetProgramName(program_path_wchar);
/* must run before python initializes */
@@ -357,6 +360,9 @@ void BPY_python_end(void)
bpy_intern_string_exit();
+ /* bpy.app modules that need cleanup */
+ BPY_app_translations_end();
+
#ifndef WITH_PYTHON_MODULE
BPY_atexit_unregister(); /* without this we get recursive calls to WM_exit */
@@ -420,7 +426,7 @@ static void python_script_error_jump_text(struct Text *text)
typedef struct {
PyObject_HEAD
PyObject *md_dict;
- /* ommit other values, we only want the dict. */
+ /* omit other values, we only want the dict. */
} PyModuleObject;
#endif
@@ -485,7 +491,9 @@ static int python_script_exec(bContext *C, const char *fn, struct Text *text,
* incompatible'.
* So now we load the script file data to a buffer */
{
- const char *pystring = "with open(__file__, 'r') as f: exec(f.read())";
+ const char *pystring =
+ "ns = globals().copy()\n"
+ "with open(__file__, 'rb') as f: exec(compile(f.read(), __file__, 'exec'), ns)";
fclose(fp);
@@ -589,7 +597,7 @@ int BPY_button_exec(bContext *C, const char *expr, double *value, const bool ver
if (error_ret) {
if (verbose) {
- BPy_errors_to_report(CTX_wm_reports(C));
+ BPy_errors_to_report_ex(CTX_wm_reports(C), false, false);
}
else {
PyErr_Clear();
@@ -601,7 +609,7 @@ int BPY_button_exec(bContext *C, const char *expr, double *value, const bool ver
return error_ret;
}
-int BPY_string_exec(bContext *C, const char *expr)
+int BPY_string_exec_ex(bContext *C, const char *expr, bool use_eval)
{
PyGILState_STATE gilstate;
PyObject *main_mod = NULL;
@@ -624,7 +632,7 @@ int BPY_string_exec(bContext *C, const char *expr)
bmain_back = bpy_import_main_get();
bpy_import_main_set(CTX_data_main(C));
- retval = PyRun_String(expr, Py_eval_input, py_dict, py_dict);
+ retval = PyRun_String(expr, use_eval ? Py_eval_input : Py_file_input, py_dict, py_dict);
bpy_import_main_set(bmain_back);
@@ -644,6 +652,10 @@ int BPY_string_exec(bContext *C, const char *expr)
return error_ret;
}
+int BPY_string_exec(bContext *C, const char *expr)
+{
+ return BPY_string_exec_ex(C, expr, true);
+}
void BPY_modules_load_user(bContext *C)
{
@@ -732,9 +744,11 @@ int BPY_context_member_get(bContext *C, const char *member, bContextDataResult *
}
else {
int len = PySequence_Fast_GET_SIZE(seq_fast);
+ PyObject **seq_fast_items = PySequence_Fast_ITEMS(seq_fast);
int i;
+
for (i = 0; i < len; i++) {
- PyObject *list_item = PySequence_Fast_GET_ITEM(seq_fast, i);
+ PyObject *list_item = seq_fast_items[i];
if (BPy_StructRNA_Check(list_item)) {
#if 0
@@ -778,7 +792,6 @@ int BPY_context_member_get(bContext *C, const char *member, bContextDataResult *
}
#ifdef WITH_PYTHON_MODULE
-#include "BLI_fileops.h"
/* TODO, reloading the module isn't functional at the moment. */
static void bpy_module_free(void *mod);
@@ -830,7 +843,7 @@ static void bpy_module_delay_init(PyObject *bpy_proxy)
static void dealloc_obj_dealloc(PyObject *self);
-static PyTypeObject dealloc_obj_Type = {{{0}}};
+static PyTypeObject dealloc_obj_Type;
/* use our own dealloc so we can free a property if we use one */
static void dealloc_obj_dealloc(PyObject *self)
diff --git a/source/blender/python/intern/bpy_library.c b/source/blender/python/intern/bpy_library.c
index 3d7d08024c7..a5879f11e51 100644
--- a/source/blender/python/intern/bpy_library.c
+++ b/source/blender/python/intern/bpy_library.c
@@ -53,6 +53,9 @@
#include "bpy_util.h"
#include "bpy_library.h"
+#include "../generic/py_capi_utils.h"
+#include "../generic/python_utildefines.h"
+
/* nifty feature. swap out strings for RNA data */
#define USE_RNA_DATABLOCKS
@@ -187,10 +190,17 @@ static PyObject *bpy_lib_load(PyObject *UNUSED(self), PyObject *args, PyObject *
static const char *kwlist[] = {"filepath", "link", "relative", NULL};
BPy_Library *ret;
const char *filename = NULL;
- int is_rel = 0, is_link = 0;
-
- if (!PyArg_ParseTupleAndKeywords(args, kwds, "s|ii:load", (char **)kwlist, &filename, &is_link, &is_rel))
+ bool is_rel = false, is_link = false;
+
+ if (!PyArg_ParseTupleAndKeywords(
+ args, kwds,
+ "s|O&O&:load", (char **)kwlist,
+ &filename,
+ PyC_ParseBool, &is_link,
+ PyC_ParseBool, &is_rel))
+ {
return NULL;
+ }
ret = PyObject_New(BPy_Library, &bpy_lib_Type);
@@ -274,10 +284,9 @@ static PyObject *bpy_lib_enter(BPy_Library *self, PyObject *UNUSED(args))
/* return pair */
ret = PyTuple_New(2);
-
- PyTuple_SET_ITEM(ret, 0, (PyObject *)self_from);
-
- PyTuple_SET_ITEM(ret, 1, (PyObject *)self);
+ PyTuple_SET_ITEMS(ret,
+ (PyObject *)self_from,
+ (PyObject *)self);
Py_INCREF(self);
BKE_reports_clear(&reports);
@@ -362,8 +371,7 @@ static PyObject *bpy_lib_exit(BPy_Library *self, PyObject *UNUSED(args))
/* just warn for now */
/* err = -1; */
#ifdef USE_RNA_DATABLOCKS
- item = Py_None;
- Py_INCREF(item);
+ item = Py_INCREF_RET(Py_None);
#endif
}
@@ -375,8 +383,7 @@ static PyObject *bpy_lib_exit(BPy_Library *self, PyObject *UNUSED(args))
PyErr_Clear();
#ifdef USE_RNA_DATABLOCKS
- item = Py_None;
- Py_INCREF(item);
+ item = Py_INCREF_RET(Py_None);
#endif
}
diff --git a/source/blender/python/intern/bpy_operator.c b/source/blender/python/intern/bpy_operator.c
index 1e97d7aeada..7cccc204088 100644
--- a/source/blender/python/intern/bpy_operator.c
+++ b/source/blender/python/intern/bpy_operator.c
@@ -36,6 +36,7 @@
#include "RNA_types.h"
#include "BLI_utildefines.h"
+#include "BLI_listbase.h"
#include "BLI_string.h"
#include "BPY_extern.h"
@@ -44,6 +45,8 @@
#include "bpy_rna.h" /* for setting arg props only - pyrna_py_to_prop() */
#include "bpy_util.h"
#include "../generic/bpy_internal_import.h"
+#include "../generic/py_capi_utils.h"
+#include "../generic/python_utildefines.h"
#include "RNA_access.h"
#include "RNA_enum_types.h"
@@ -99,7 +102,7 @@ static PyObject *pyop_poll(PyObject *UNUSED(self), PyObject *args)
char *enum_str = BPy_enum_as_string(operator_context_items);
PyErr_Format(PyExc_TypeError,
"Calling operator \"bpy.ops.%s.poll\" error, "
- "expected a string enum in (%.200s)",
+ "expected a string enum in (%s)",
opname, enum_str);
MEM_freeN(enum_str);
return NULL;
@@ -127,9 +130,8 @@ static PyObject *pyop_poll(PyObject *UNUSED(self), PyObject *args)
/* restore with original context dict, probably NULL but need this for nested operator calls */
Py_XDECREF(context_dict);
CTX_py_dict_set(C, (void *)context_dict_back);
-
- Py_INCREF(ret);
- return ret;
+
+ return Py_INCREF_RET(ret);
}
static PyObject *pyop_call(PyObject *UNUSED(self), PyObject *args)
@@ -186,7 +188,7 @@ static PyObject *pyop_call(PyObject *UNUSED(self), PyObject *args)
char *enum_str = BPy_enum_as_string(operator_context_items);
PyErr_Format(PyExc_TypeError,
"Calling operator \"bpy.ops.%s\" error, "
- "expected a string enum in (%.200s)",
+ "expected a string enum in (%s)",
opname, enum_str);
MEM_freeN(enum_str);
return NULL;
@@ -251,12 +253,10 @@ static PyObject *pyop_call(PyObject *UNUSED(self), PyObject *args)
error_val = BPy_reports_to_error(reports, PyExc_RuntimeError, false);
/* operator output is nice to have in the terminal/console too */
- if (reports->list.first) {
- char *report_str = BKE_reports_string(reports, 0); /* all reports */
-
- if (report_str) {
- PySys_WriteStdout("%s\n", report_str);
- MEM_freeN(report_str);
+ if (!BLI_listbase_is_empty(&reports->list)) {
+ Report *report;
+ for (report = reports->list.first; report; report = report->next) {
+ PySys_WriteStdout("%s: %s\n", report->typestr, report->message);
}
}
@@ -312,8 +312,8 @@ static PyObject *pyop_as_string(PyObject *UNUSED(self), PyObject *args)
const char *opname;
PyObject *kw = NULL; /* optional args */
- int all_args = 1;
- int macro_args = 1;
+ bool all_args = true;
+ bool macro_args = true;
int error_val = 0;
char *buf = NULL;
@@ -326,8 +326,14 @@ static PyObject *pyop_as_string(PyObject *UNUSED(self), PyObject *args)
return NULL;
}
- if (!PyArg_ParseTuple(args, "s|O!ii:_bpy.ops.as_string", &opname, &PyDict_Type, &kw, &all_args, &macro_args))
+ if (!PyArg_ParseTuple(
+ args, "s|O!O&O&:_bpy.ops.as_string",
+ &opname, &PyDict_Type, &kw,
+ PyC_ParseBool, &all_args,
+ PyC_ParseBool, &macro_args))
+ {
return NULL;
+ }
ot = WM_operatortype_find(opname, true);
@@ -367,17 +373,17 @@ static PyObject *pyop_as_string(PyObject *UNUSED(self), PyObject *args)
static PyObject *pyop_dir(PyObject *UNUSED(self))
{
- GHashIterator *iter = WM_operatortype_iter();
- PyObject *list = PyList_New(0), *name;
+ GHashIterator iter;
+ PyObject *list;
+ int i;
- for ( ; !BLI_ghashIterator_done(iter); BLI_ghashIterator_step(iter)) {
- wmOperatorType *ot = BLI_ghashIterator_getValue(iter);
+ WM_operatortype_iter(&iter);
+ list = PyList_New(BLI_ghash_size(iter.gh));
- name = PyUnicode_FromString(ot->idname);
- PyList_Append(list, name);
- Py_DECREF(name);
+ for (i = 0; !BLI_ghashIterator_done(&iter); BLI_ghashIterator_step(&iter), i++) {
+ wmOperatorType *ot = BLI_ghashIterator_getValue(&iter);
+ PyList_SET_ITEM(list, i, PyUnicode_FromString(ot->idname));
}
- BLI_ghashIterator_free(iter);
return list;
}
diff --git a/source/blender/python/intern/bpy_props.c b/source/blender/python/intern/bpy_props.c
index 9a8c3d89e8d..19ded7fb4f3 100644
--- a/source/blender/python/intern/bpy_props.c
+++ b/source/blender/python/intern/bpy_props.c
@@ -64,10 +64,12 @@ static EnumPropertyItem property_flag_items[] = {
{PROP_ANIMATABLE, "ANIMATABLE", 0, "Animatable", ""},
{PROP_LIB_EXCEPTION, "LIBRARY_EDITABLE", 0, "Library Editable", ""},
{PROP_PROPORTIONAL, "PROPORTIONAL", 0, "Adjust values proportionally to eachother", ""},
+ {PROP_TEXTEDIT_UPDATE, "TEXTEDIT_UPDATE", 0, "Update on every keystroke in textedit 'mode'", ""},
{0, NULL, 0, NULL, NULL}};
#define BPY_PROPDEF_OPTIONS_DOC \
-" :arg options: Enumerator in ['HIDDEN', 'SKIP_SAVE', 'ANIMATABLE', 'LIBRARY_EDITABLE', 'PROPORTIONAL'].\n" \
+" :arg options: Enumerator in ['HIDDEN', 'SKIP_SAVE', 'ANIMATABLE', 'LIBRARY_EDITABLE', 'PROPORTIONAL'," \
+ "'TEXTEDIT_UPDATE'].\n" \
" :type options: set\n" \
static EnumPropertyItem property_flag_enum_items[] = {
@@ -192,6 +194,19 @@ static void printf_func_error(PyObject *py_func)
);
}
+static void bpy_prop_assign_flag(PropertyRNA *prop, const int flag)
+{
+ const int flag_mask = ((PROP_ANIMATABLE) & ~flag);
+
+ if (flag) {
+ RNA_def_property_flag(prop, flag);
+ }
+
+ if (flag_mask) {
+ RNA_def_property_clear_flag(prop, flag_mask);
+ }
+}
+
/* operators and classes use this so it can store the args given but defer
* running it until the operator runs where these values are used to setup
* the default args for that operator instance */
@@ -1304,6 +1319,7 @@ static EnumPropertyItem *enum_items_from_py(PyObject *seq_fast, PyObject *def, i
EnumPropertyItem *items;
PyObject *item;
const Py_ssize_t seq_len = PySequence_Fast_GET_SIZE(seq_fast);
+ PyObject **seq_fast_items = PySequence_Fast_ITEMS(seq_fast);
Py_ssize_t totbuf = 0;
int i;
short def_used = 0;
@@ -1351,7 +1367,7 @@ static EnumPropertyItem *enum_items_from_py(PyObject *seq_fast, PyObject *def, i
Py_ssize_t name_str_size;
Py_ssize_t desc_str_size;
- item = PySequence_Fast_GET_ITEM(seq_fast, i);
+ item = seq_fast_items[i];
if ((PyTuple_CheckExact(item)) &&
(item_size = PyTuple_GET_SIZE(item)) &&
@@ -1361,7 +1377,8 @@ static EnumPropertyItem *enum_items_from_py(PyObject *seq_fast, PyObject *def, i
(tmp.description = _PyUnicode_AsStringAndSize(PyTuple_GET_ITEM(item, 2), &desc_str_size)) &&
/* TODO, number isn't ensured to be unique from the script author */
(item_size != 4 || py_long_as_int(PyTuple_GET_ITEM(item, 3), &tmp.value) != -1) &&
- (item_size != 5 || ((tmp_icon = _PyUnicode_AsString(PyTuple_GET_ITEM(item, 3))) &&
+ (item_size != 5 || ((py_long_as_int(PyTuple_GET_ITEM(item, 3), &tmp.icon) != -1 ||
+ (tmp_icon = _PyUnicode_AsString(PyTuple_GET_ITEM(item, 3)))) &&
py_long_as_int(PyTuple_GET_ITEM(item, 4), &tmp.value) != -1)))
{
if (is_enum_flag) {
@@ -1465,15 +1482,26 @@ static EnumPropertyItem *bpy_prop_enum_itemf_cb(struct bContext *C, PointerRNA *
EnumPropertyItem *eitems = NULL;
int err = 0;
- bpy_context_set(C, &gilstate);
+ if (C) {
+ bpy_context_set(C, &gilstate);
+ }
+ else {
+ gilstate = PyGILState_Ensure();
+ }
args = PyTuple_New(2);
self = pyrna_struct_as_instance(ptr);
PyTuple_SET_ITEM(args, 0, self);
/* now get the context */
- PyTuple_SET_ITEM(args, 1, (PyObject *)bpy_context_module);
- Py_INCREF(bpy_context_module);
+ if (C) {
+ PyTuple_SET_ITEM(args, 1, (PyObject *)bpy_context_module);
+ Py_INCREF(bpy_context_module);
+ }
+ else {
+ PyTuple_SET_ITEM(args, 1, Py_None);
+ Py_INCREF(Py_None);
+ }
items = PyObject_CallObject(py_func, args);
@@ -1514,8 +1542,13 @@ static EnumPropertyItem *bpy_prop_enum_itemf_cb(struct bContext *C, PointerRNA *
eitems = DummyRNA_NULL_items;
}
+ if (C) {
+ bpy_context_clear(C, &gilstate);
+ }
+ else {
+ PyGILState_Release(gilstate);
+ }
- bpy_context_clear(C, &gilstate);
return eitems;
}
@@ -1918,7 +1951,7 @@ static PyObject *BPy_BoolProperty(PyObject *self, PyObject *args, PyObject *kw)
"options", "subtype", "update", "get", "set", NULL};
const char *id = NULL, *name = NULL, *description = "";
int id_len;
- int def = 0;
+ bool def = false;
PropertyRNA *prop;
PyObject *pyopts = NULL;
int opts = 0;
@@ -1929,9 +1962,9 @@ static PyObject *BPy_BoolProperty(PyObject *self, PyObject *args, PyObject *kw)
PyObject *set_cb = NULL;
if (!PyArg_ParseTupleAndKeywords(args, kw,
- "s#|ssiO!sOOO:BoolProperty",
+ "s#|ssO&O!sOOO:BoolProperty",
(char **)kwlist, &id, &id_len,
- &name, &description, &def,
+ &name, &description, PyC_ParseBool, &def,
&PySet_Type, &pyopts, &pysubtype,
&update_cb, &get_cb, &set_cb))
{
@@ -1955,10 +1988,7 @@ static PyObject *BPy_BoolProperty(PyObject *self, PyObject *args, PyObject *kw)
RNA_def_property_ui_text(prop, name ? name : id, description);
if (pyopts) {
- if (opts & PROP_HIDDEN) RNA_def_property_flag(prop, PROP_HIDDEN);
- if ((opts & PROP_ANIMATABLE) == 0) RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
- if (opts & PROP_SKIP_SAVE) RNA_def_property_flag(prop, PROP_SKIP_SAVE);
- if (opts & PROP_LIB_EXCEPTION) RNA_def_property_flag(prop, PROP_LIB_EXCEPTION);
+ bpy_prop_assign_flag(prop, opts);
}
bpy_prop_callback_assign_update(prop, update_cb);
bpy_prop_callback_assign_boolean(prop, get_cb, set_cb);
@@ -2054,10 +2084,7 @@ static PyObject *BPy_BoolVectorProperty(PyObject *self, PyObject *args, PyObject
RNA_def_property_ui_text(prop, name ? name : id, description);
if (pyopts) {
- if (opts & PROP_HIDDEN) RNA_def_property_flag(prop, PROP_HIDDEN);
- if ((opts & PROP_ANIMATABLE) == 0) RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
- if (opts & PROP_SKIP_SAVE) RNA_def_property_flag(prop, PROP_SKIP_SAVE);
- if (opts & PROP_LIB_EXCEPTION) RNA_def_property_flag(prop, PROP_LIB_EXCEPTION);
+ bpy_prop_assign_flag(prop, opts);
}
bpy_prop_callback_assign_update(prop, update_cb);
bpy_prop_callback_assign_boolean_array(prop, get_cb, set_cb);
@@ -2151,10 +2178,7 @@ static PyObject *BPy_IntProperty(PyObject *self, PyObject *args, PyObject *kw)
RNA_def_property_ui_range(prop, MAX2(soft_min, min), MIN2(soft_max, max), step, 3);
if (pyopts) {
- if (opts & PROP_HIDDEN) RNA_def_property_flag(prop, PROP_HIDDEN);
- if ((opts & PROP_ANIMATABLE) == 0) RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
- if (opts & PROP_SKIP_SAVE) RNA_def_property_flag(prop, PROP_SKIP_SAVE);
- if (opts & PROP_LIB_EXCEPTION) RNA_def_property_flag(prop, PROP_LIB_EXCEPTION);
+ bpy_prop_assign_flag(prop, opts);
}
bpy_prop_callback_assign_update(prop, update_cb);
bpy_prop_callback_assign_int(prop, get_cb, set_cb);
@@ -2266,10 +2290,7 @@ static PyObject *BPy_IntVectorProperty(PyObject *self, PyObject *args, PyObject
RNA_def_property_ui_range(prop, MAX2(soft_min, min), MIN2(soft_max, max), step, 3);
if (pyopts) {
- if (opts & PROP_HIDDEN) RNA_def_property_flag(prop, PROP_HIDDEN);
- if ((opts & PROP_ANIMATABLE) == 0) RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
- if (opts & PROP_SKIP_SAVE) RNA_def_property_flag(prop, PROP_SKIP_SAVE);
- if (opts & PROP_LIB_EXCEPTION) RNA_def_property_flag(prop, PROP_LIB_EXCEPTION);
+ bpy_prop_assign_flag(prop, opts);
}
bpy_prop_callback_assign_update(prop, update_cb);
bpy_prop_callback_assign_int_array(prop, get_cb, set_cb);
@@ -2377,10 +2398,7 @@ static PyObject *BPy_FloatProperty(PyObject *self, PyObject *args, PyObject *kw)
RNA_def_property_ui_range(prop, MAX2(soft_min, min), MIN2(soft_max, max), step, precision);
if (pyopts) {
- if (opts & PROP_HIDDEN) RNA_def_property_flag(prop, PROP_HIDDEN);
- if ((opts & PROP_ANIMATABLE) == 0) RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
- if (opts & PROP_SKIP_SAVE) RNA_def_property_flag(prop, PROP_SKIP_SAVE);
- if (opts & PROP_LIB_EXCEPTION) RNA_def_property_flag(prop, PROP_LIB_EXCEPTION);
+ bpy_prop_assign_flag(prop, opts);
}
bpy_prop_callback_assign_update(prop, update_cb);
bpy_prop_callback_assign_float(prop, get_cb, set_cb);
@@ -2504,10 +2522,7 @@ static PyObject *BPy_FloatVectorProperty(PyObject *self, PyObject *args, PyObjec
RNA_def_property_ui_range(prop, MAX2(soft_min, min), MIN2(soft_max, max), step, precision);
if (pyopts) {
- if (opts & PROP_HIDDEN) RNA_def_property_flag(prop, PROP_HIDDEN);
- if ((opts & PROP_ANIMATABLE) == 0) RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
- if (opts & PROP_SKIP_SAVE) RNA_def_property_flag(prop, PROP_SKIP_SAVE);
- if (opts & PROP_LIB_EXCEPTION) RNA_def_property_flag(prop, PROP_LIB_EXCEPTION);
+ bpy_prop_assign_flag(prop, opts);
}
bpy_prop_callback_assign_update(prop, update_cb);
bpy_prop_callback_assign_float_array(prop, get_cb, set_cb);
@@ -2590,10 +2605,7 @@ static PyObject *BPy_StringProperty(PyObject *self, PyObject *args, PyObject *kw
RNA_def_property_ui_text(prop, name ? name : id, description);
if (pyopts) {
- if (opts & PROP_HIDDEN) RNA_def_property_flag(prop, PROP_HIDDEN);
- if ((opts & PROP_ANIMATABLE) == 0) RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
- if (opts & PROP_SKIP_SAVE) RNA_def_property_flag(prop, PROP_SKIP_SAVE);
- if (opts & PROP_LIB_EXCEPTION) RNA_def_property_flag(prop, PROP_LIB_EXCEPTION);
+ bpy_prop_assign_flag(prop, opts);
}
bpy_prop_callback_assign_update(prop, update_cb);
bpy_prop_callback_assign_string(prop, get_cb, set_cb);
@@ -2606,7 +2618,7 @@ PyDoc_STRVAR(BPy_EnumProperty_doc,
".. function:: EnumProperty(items, "
"name=\"\", "
"description=\"\", "
- "default=\"\", "
+ "default=None, "
"options={'ANIMATABLE'}, "
"update=None, "
"get=None, "
@@ -2618,12 +2630,12 @@ PyDoc_STRVAR(BPy_EnumProperty_doc,
" [(identifier, name, description, icon, number), ...] where the identifier is used\n"
" for python access and other values are used for the interface.\n"
" The three first elements of the tuples are mandatory.\n"
-" The forth one is either the (unique!) number id of the item or, if followed by a fith element \n"
-" (which must be the numid), an icon string identifier.\n"
+" The forth one is either the (unique!) number id of the item or, if followed by a fith element\n"
+" (which must be the numid), an icon string identifier or integer icon value (e.g. returned by icon()...).\n"
" Note the item is optional.\n"
" For dynamic values a callback can be passed which returns a list in\n"
" the same format as the static list.\n"
-" This function must take 2 arguments (self, context)\n"
+" This function must take 2 arguments (self, context), **context may be None**.\n"
" WARNING: There is a known bug with using a callback,\n"
" Python must keep a reference to the strings returned or Blender will crash.\n"
" :type items: sequence of string tuples or a function\n"
@@ -2631,6 +2643,8 @@ BPY_PROPDEF_NAME_DOC
BPY_PROPDEF_DESC_DOC
" :arg default: The default value for this enum, a string from the identifiers used in *items*.\n"
" If the *ENUM_FLAG* option is used this must be a set of such string identifiers instead.\n"
+" WARNING: It shall not be specified (or specified to its default *None* value) for dynamic enums\n"
+" (i.e. if a callback function is given as *items* parameter).\n"
" :type default: string or set\n"
BPY_PROPDEF_OPTIONS_ENUM_DOC
BPY_PROPDEF_UPDATE_DOC
@@ -2682,6 +2696,12 @@ static PyObject *BPy_EnumProperty(PyObject *self, PyObject *args, PyObject *kw)
return NULL;
}
+ if (def == Py_None) {
+ /* This allows to get same behavior when explicitly passing None as default value,
+ * and not defining a default value at all! */
+ def = NULL;
+ }
+
/* items can be a list or a callable */
if (PyFunction_Check(items)) { /* don't use PyCallable_Check because we need the function code for errors */
PyCodeObject *f_code = (PyCodeObject *)PyFunction_GET_CODE(items);
@@ -2722,10 +2742,7 @@ static PyObject *BPy_EnumProperty(PyObject *self, PyObject *args, PyObject *kw)
else prop = RNA_def_enum(srna, id, eitems, defvalue, name ? name : id, description);
if (pyopts) {
- if (opts & PROP_HIDDEN) RNA_def_property_flag(prop, PROP_HIDDEN);
- if ((opts & PROP_ANIMATABLE) == 0) RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
- if (opts & PROP_SKIP_SAVE) RNA_def_property_flag(prop, PROP_SKIP_SAVE);
- if (opts & PROP_LIB_EXCEPTION) RNA_def_property_flag(prop, PROP_LIB_EXCEPTION);
+ bpy_prop_assign_flag(prop, opts);
}
bpy_prop_callback_assign_update(prop, update_cb);
bpy_prop_callback_assign_enum(prop, get_cb, set_cb, (is_itemf ? items : NULL));
@@ -2828,10 +2845,7 @@ static PyObject *BPy_PointerProperty(PyObject *self, PyObject *args, PyObject *k
prop = RNA_def_pointer_runtime(srna, id, ptype, name ? name : id, description);
if (pyopts) {
- if (opts & PROP_HIDDEN) RNA_def_property_flag(prop, PROP_HIDDEN);
- if ((opts & PROP_ANIMATABLE) == 0) RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
- if (opts & PROP_SKIP_SAVE) RNA_def_property_flag(prop, PROP_SKIP_SAVE);
- if (opts & PROP_LIB_EXCEPTION) RNA_def_property_flag(prop, PROP_LIB_EXCEPTION);
+ bpy_prop_assign_flag(prop, opts);
}
bpy_prop_callback_assign_update(prop, update_cb);
RNA_def_property_duplicate_pointers(srna, prop);
@@ -2885,10 +2899,7 @@ static PyObject *BPy_CollectionProperty(PyObject *self, PyObject *args, PyObject
prop = RNA_def_collection_runtime(srna, id, ptype, name ? name : id, description);
if (pyopts) {
- if (opts & PROP_HIDDEN) RNA_def_property_flag(prop, PROP_HIDDEN);
- if ((opts & PROP_ANIMATABLE) == 0) RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
- if (opts & PROP_SKIP_SAVE) RNA_def_property_flag(prop, PROP_SKIP_SAVE);
- if (opts & PROP_LIB_EXCEPTION) RNA_def_property_flag(prop, PROP_LIB_EXCEPTION);
+ bpy_prop_assign_flag(prop, opts);
}
RNA_def_property_duplicate_pointers(srna, prop);
}
@@ -2972,9 +2983,10 @@ static struct PyMethodDef props_methods[] = {
static struct PyModuleDef props_module = {
PyModuleDef_HEAD_INIT,
"bpy.props",
- "This module defines properties to extend blenders internal data, the result of these functions"
- " is used to assign properties to classes registered with blender and can't be used directly.\n"
- ".. warning:: All parameters to these functions must be passed as keywords.",
+ "This module defines properties to extend Blender's internal data. The result of these functions"
+ " is used to assign properties to classes registered with Blender and can't be used directly.\n"
+ "\n"
+ ".. warning:: All parameters to these functions must be passed as keywords.\n",
-1, /* multiple "initialization" just copies the module dict. */
props_methods,
NULL, NULL, NULL, NULL
diff --git a/source/blender/python/intern/bpy_rna.c b/source/blender/python/intern/bpy_rna.c
index f6e97d6a2d8..5414c4e4204 100644
--- a/source/blender/python/intern/bpy_rna.c
+++ b/source/blender/python/intern/bpy_rna.c
@@ -53,10 +53,6 @@
#include "bpy_intern_string.h"
#ifdef USE_PYRNA_INVALIDATE_WEAKREF
-# include "MEM_guardedalloc.h"
-#endif
-
-#ifdef USE_PYRNA_INVALIDATE_WEAKREF
# include "BLI_ghash.h"
#endif
@@ -76,10 +72,7 @@
#include "../generic/idprop_py_api.h" /* for IDprop lookups */
#include "../generic/py_capi_utils.h"
-
-#ifdef WITH_INTERNATIONAL
-# include "BLF_translation.h"
-#endif
+#include "../generic/python_utildefines.h"
#define USE_PEDANTIC_WRITE
#define USE_MATHUTILS
@@ -180,7 +173,7 @@ static GHash *id_weakref_pool_get(ID *id)
if (weakinfo_hash == NULL) {
/* we're using a ghash as a set, could use libHX's HXMAP_SINGULAR but would be an extra dep. */
weakinfo_hash = BLI_ghash_ptr_new("rna_id");
- BLI_ghash_insert(id_weakref_pool, (void *)id, weakinfo_hash);
+ BLI_ghash_insert(id_weakref_pool, id, weakinfo_hash);
}
return weakinfo_hash;
@@ -206,7 +199,7 @@ static void id_weakref_pool_add(ID *id, BPy_DummyPointerRNA *pyrna)
Py_DECREF(weakref_cb_py); /* function owned by the weakref now */
/* important to add at the end, since first removal looks at the end */
- BLI_ghash_insert(weakinfo_hash, (void *)weakref, id); /* using a hash table as a set, all 'id's are the same */
+ BLI_ghash_insert(weakinfo_hash, weakref, id); /* using a hash table as a set, all 'id's are the same */
/* weakinfo_hash owns the weakref */
}
@@ -641,7 +634,7 @@ PyObject *pyrna_math_object_from_array(PointerRNA *ptr, PropertyRNA *prop)
case PROP_ALL_VECTOR_SUBTYPES:
if (len >= 2 && len <= 4) {
if (is_thick) {
- ret = Vector_CreatePyObject(NULL, len, Py_NEW, NULL);
+ ret = Vector_CreatePyObject(NULL, len, NULL);
RNA_property_float_get_array(ptr, prop, ((VectorObject *)ret)->vec);
}
else {
@@ -654,7 +647,7 @@ PyObject *pyrna_math_object_from_array(PointerRNA *ptr, PropertyRNA *prop)
case PROP_MATRIX:
if (len == 16) {
if (is_thick) {
- ret = Matrix_CreatePyObject(NULL, 4, 4, Py_NEW, NULL);
+ ret = Matrix_CreatePyObject(NULL, 4, 4, NULL);
RNA_property_float_get_array(ptr, prop, ((MatrixObject *)ret)->matrix);
}
else {
@@ -665,7 +658,7 @@ PyObject *pyrna_math_object_from_array(PointerRNA *ptr, PropertyRNA *prop)
}
else if (len == 9) {
if (is_thick) {
- ret = Matrix_CreatePyObject(NULL, 3, 3, Py_NEW, NULL);
+ ret = Matrix_CreatePyObject(NULL, 3, 3, NULL);
RNA_property_float_get_array(ptr, prop, ((MatrixObject *)ret)->matrix);
}
else {
@@ -683,7 +676,7 @@ PyObject *pyrna_math_object_from_array(PointerRNA *ptr, PropertyRNA *prop)
PropertyRNA *prop_eul_order = NULL;
short order = pyrna_rotation_euler_order_get(ptr, &prop_eul_order, EULER_ORDER_XYZ);
- ret = Euler_CreatePyObject(NULL, order, Py_NEW, NULL); /* TODO, get order from RNA */
+ ret = Euler_CreatePyObject(NULL, order, NULL); /* TODO, get order from RNA */
RNA_property_float_get_array(ptr, prop, ((EulerObject *)ret)->eul);
}
else {
@@ -695,7 +688,7 @@ PyObject *pyrna_math_object_from_array(PointerRNA *ptr, PropertyRNA *prop)
}
else if (len == 4) {
if (is_thick) {
- ret = Quaternion_CreatePyObject(NULL, Py_NEW, NULL);
+ ret = Quaternion_CreatePyObject(NULL, NULL);
RNA_property_float_get_array(ptr, prop, ((QuaternionObject *)ret)->quat);
}
else {
@@ -709,7 +702,7 @@ PyObject *pyrna_math_object_from_array(PointerRNA *ptr, PropertyRNA *prop)
case PROP_COLOR_GAMMA:
if (len == 3) { /* color */
if (is_thick) {
- ret = Color_CreatePyObject(NULL, Py_NEW, NULL);
+ ret = Color_CreatePyObject(NULL, NULL);
RNA_property_float_get_array(ptr, prop, ((ColorObject *)ret)->col);
}
else {
@@ -809,7 +802,7 @@ static PyObject *pyrna_struct_richcmp(PyObject *a, PyObject *b, int op)
return NULL;
}
- return Py_INCREF(res), res;
+ return Py_INCREF_RET(res);
}
static PyObject *pyrna_prop_richcmp(PyObject *a, PyObject *b, int op)
@@ -839,7 +832,7 @@ static PyObject *pyrna_prop_richcmp(PyObject *a, PyObject *b, int op)
return NULL;
}
- return Py_INCREF(res), res;
+ return Py_INCREF_RET(res);
}
/*----------------------repr--------------------------------------------*/
@@ -995,15 +988,16 @@ static PyObject *pyrna_prop_repr(BPy_PropertyRNA *self)
path = RNA_path_from_ID_to_property(&self->ptr, self->prop);
if (path) {
+ const char *data_delim = (path[0] == '[') ? "" : ".";
if (GS(id->name) == ID_NT) { /* nodetree paths are not accurate */
ret = PyUnicode_FromFormat("bpy.data...%s",
path);
}
else {
- ret = PyUnicode_FromFormat("bpy.data.%s[%R].%s",
+ ret = PyUnicode_FromFormat("bpy.data.%s[%R]%s%s",
BKE_idcode_to_name_plural(GS(id->name)),
tmp_str,
- path);
+ data_delim, path);
}
MEM_freeN((void *)path);
@@ -1833,25 +1827,23 @@ static int pyrna_py_to_prop(PointerRNA *ptr, PropertyRNA *prop, void *data, PyOb
RNA_property_pointer_set(ptr, prop, param->ptr);
}
else {
+ raise_error = true;
+ }
+ }
+
+ if (raise_error) {
+ if (pyrna_struct_validity_check(param) == -1) {
+ /* error set */
+ }
+ else {
PointerRNA tmp;
RNA_pointer_create(NULL, ptr_type, NULL, &tmp);
PyErr_Format(PyExc_TypeError,
- "%.200s %.200s.%.200s expected a %.200s type. not %.200s",
+ "%.200s %.200s.%.200s expected a %.200s type, not %.200s",
error_prefix, RNA_struct_identifier(ptr->type),
RNA_property_identifier(prop), RNA_struct_identifier(tmp.type),
RNA_struct_identifier(param->ptr.type));
- Py_XDECREF(value_new); return -1;
}
- }
-
- if (raise_error) {
- PointerRNA tmp;
- RNA_pointer_create(NULL, ptr_type, NULL, &tmp);
- PyErr_Format(PyExc_TypeError,
- "%.200s %.200s.%.200s expected a %.200s type, not %.200s",
- error_prefix, RNA_struct_identifier(ptr->type),
- RNA_property_identifier(prop), RNA_struct_identifier(tmp.type),
- RNA_struct_identifier(param->ptr.type));
Py_XDECREF(value_new); return -1;
}
}
@@ -2305,8 +2297,7 @@ static PyObject *pyrna_prop_collection_subscript_slice(BPy_PropertyRNA *self, Py
RNA_property_collection_next(&rna_macro_iter))
{
item = pyrna_struct_CreatePyObject(&rna_macro_iter.ptr);
- PyList_Append(list, item);
- Py_DECREF(item);
+ PyList_APPEND(list, item);
count++;
if (count == stop) {
@@ -2647,6 +2638,7 @@ static int prop_subscript_ass_array_slice(PointerRNA *ptr, PropertyRNA *prop,
int start, int stop, int length, PyObject *value_orig)
{
PyObject *value;
+ PyObject **value_items;
int count;
void *values_alloc = NULL;
int ret = 0;
@@ -2668,6 +2660,7 @@ static int prop_subscript_ass_array_slice(PointerRNA *ptr, PropertyRNA *prop,
return -1;
}
+ value_items = PySequence_Fast_ITEMS(value);
switch (RNA_property_type(prop)) {
case PROP_FLOAT:
{
@@ -2683,7 +2676,7 @@ static int prop_subscript_ass_array_slice(PointerRNA *ptr, PropertyRNA *prop,
RNA_property_float_get_array(ptr, prop, values);
for (count = start; count < stop; count++) {
- fval = PyFloat_AsDouble(PySequence_Fast_GET_ITEM(value, count - start));
+ fval = PyFloat_AsDouble(value_items[count - start]);
CLAMP(fval, min, max);
values[count] = fval;
}
@@ -2703,7 +2696,7 @@ static int prop_subscript_ass_array_slice(PointerRNA *ptr, PropertyRNA *prop,
RNA_property_boolean_get_array(ptr, prop, values);
for (count = start; count < stop; count++)
- values[count] = PyLong_AsLong(PySequence_Fast_GET_ITEM(value, count - start));
+ values[count] = PyLong_AsLong(value_items[count - start]);
if (PyErr_Occurred()) ret = -1;
else RNA_property_boolean_set_array(ptr, prop, values);
@@ -2724,7 +2717,7 @@ static int prop_subscript_ass_array_slice(PointerRNA *ptr, PropertyRNA *prop,
RNA_property_int_get_array(ptr, prop, values);
for (count = start; count < stop; count++) {
- ival = PyLong_AsLong(PySequence_Fast_GET_ITEM(value, count - start));
+ ival = PyLong_AsLong(value_items[count - start]);
CLAMP(ival, min, max);
values[count] = ival;
}
@@ -3188,6 +3181,34 @@ static PyObject *pyrna_struct_is_property_hidden(BPy_StructRNA *self, PyObject *
return PyBool_FromLong(RNA_property_flag(prop) & PROP_HIDDEN);
}
+PyDoc_STRVAR(pyrna_struct_is_property_readonly_doc,
+".. method:: is_property_readonly(property)\n"
+"\n"
+" Check if a property is readonly.\n"
+"\n"
+" :return: True when the property is readonly (not writable).\n"
+" :rtype: boolean\n"
+);
+static PyObject *pyrna_struct_is_property_readonly(BPy_StructRNA *self, PyObject *args)
+{
+ PropertyRNA *prop;
+ const char *name;
+
+ PYRNA_STRUCT_CHECK_OBJ(self);
+
+ if (!PyArg_ParseTuple(args, "s:is_property_readonly", &name))
+ return NULL;
+
+ if ((prop = RNA_struct_find_property(&self->ptr, name)) == NULL) {
+ PyErr_Format(PyExc_TypeError,
+ "%.200s.is_property_readonly(\"%.200s\") not found",
+ RNA_struct_identifier(self->ptr.type), name);
+ return NULL;
+ }
+
+ return PyBool_FromLong(!RNA_property_editable(&self->ptr, prop));
+}
+
PyDoc_STRVAR(pyrna_struct_path_resolve_doc,
".. method:: path_resolve(path, coerce=True)\n"
"\n"
@@ -3337,7 +3358,7 @@ static PyObject *pyrna_prop_path_from_id(BPy_PropertyRNA *self)
PyDoc_STRVAR(pyrna_prop_as_bytes_doc,
".. method:: as_bytes()\n"
"\n"
-" Returns this string property as a byte rather then a python string.\n"
+" Returns this string property as a byte rather than a python string.\n"
"\n"
" :return: The string as bytes.\n"
" :rtype: bytes\n"
@@ -3368,6 +3389,21 @@ static PyObject *pyrna_prop_as_bytes(BPy_PropertyRNA *self)
}
}
+PyDoc_STRVAR(pyrna_prop_update_doc,
+".. method:: update()\n"
+"\n"
+" Execute the properties update callback.\n"
+"\n"
+" .. note::\n"
+" This is called when assigning a property,\n"
+" however in rare cases its useful to call explicitly.\n"
+);
+static PyObject *pyrna_prop_update(BPy_PropertyRNA *self)
+{
+ RNA_property_update(BPy_GetContext(), &self->ptr, self->prop);
+ Py_RETURN_NONE;
+}
+
PyDoc_STRVAR(pyrna_struct_type_recast_doc,
".. method:: type_recast()\n"
"\n"
@@ -3430,7 +3466,6 @@ static void pyrna_dir_members_py(PyObject *list, PyObject *self)
static void pyrna_dir_members_rna(PyObject *list, PointerRNA *ptr)
{
- PyObject *pystring;
const char *idname;
/* for looping over attrs and funcs */
@@ -3446,10 +3481,7 @@ static void pyrna_dir_members_rna(PyObject *list, PointerRNA *ptr)
FunctionRNA *func = itemptr.data;
if (RNA_function_defined(func)) {
idname = RNA_function_identifier(itemptr.data);
-
- pystring = PyUnicode_FromString(idname);
- PyList_Append(list, pystring);
- Py_DECREF(pystring);
+ PyList_APPEND(list, PyUnicode_FromString(idname));
}
}
RNA_PROP_END;
@@ -3469,9 +3501,7 @@ static void pyrna_dir_members_rna(PyObject *list, PointerRNA *ptr)
nameptr = RNA_struct_name_get_alloc(&itemptr, name, sizeof(name), &namelen);
if (nameptr) {
- pystring = PyUnicode_FromStringAndSize(nameptr, namelen);
- PyList_Append(list, pystring);
- Py_DECREF(pystring);
+ PyList_APPEND(list, PyUnicode_FromStringAndSize(nameptr, namelen));
if (name != nameptr) {
MEM_freeN(nameptr);
@@ -3486,7 +3516,6 @@ static void pyrna_dir_members_rna(PyObject *list, PointerRNA *ptr)
static PyObject *pyrna_struct_dir(BPy_StructRNA *self)
{
PyObject *ret;
- PyObject *pystring;
PYRNA_STRUCT_CHECK_OBJ(self);
@@ -3505,9 +3534,7 @@ static PyObject *pyrna_struct_dir(BPy_StructRNA *self)
LinkData *link;
for (link = lb.first; link; link = link->next) {
- pystring = PyUnicode_FromString(link->data);
- PyList_Append(ret, pystring);
- Py_DECREF(pystring);
+ PyList_APPEND(ret, PyUnicode_FromString(link->data));
}
BLI_freelistN(&lb);
@@ -3587,14 +3614,11 @@ static PyObject *pyrna_struct_getattro(BPy_StructRNA *self, PyObject *pyname)
case CTX_DATA_TYPE_COLLECTION:
{
CollectionPointerLink *link;
- PyObject *linkptr;
ret = PyList_New(0);
for (link = newlb.first; link; link = link->next) {
- linkptr = pyrna_struct_CreatePyObject(&link->ptr);
- PyList_Append(ret, linkptr);
- Py_DECREF(linkptr);
+ PyList_APPEND(ret, pyrna_struct_CreatePyObject(&link->ptr));
}
break;
}
@@ -4101,7 +4125,6 @@ PyDoc_STRVAR(pyrna_prop_collection_keys_doc,
static PyObject *pyrna_prop_collection_keys(BPy_PropertyRNA *self)
{
PyObject *ret = PyList_New(0);
- PyObject *item;
char name[256], *nameptr;
int namelen;
@@ -4110,11 +4133,7 @@ static PyObject *pyrna_prop_collection_keys(BPy_PropertyRNA *self)
nameptr = RNA_struct_name_get_alloc(&itemptr, name, sizeof(name), &namelen);
if (nameptr) {
- /* add to python list */
- item = PyUnicode_FromStringAndSize(nameptr, namelen);
- PyList_Append(ret, item);
- Py_DECREF(item);
- /* done */
+ PyList_APPEND(ret, PyUnicode_FromStringAndSize(nameptr, namelen));
if (name != nameptr) {
MEM_freeN(nameptr);
@@ -4160,8 +4179,7 @@ static PyObject *pyrna_prop_collection_items(BPy_PropertyRNA *self)
}
PyTuple_SET_ITEM(item, 1, pyrna_struct_CreatePyObject(&itemptr));
- PyList_Append(ret, item);
- Py_DECREF(item);
+ PyList_APPEND(ret, item);
i++;
}
@@ -4227,7 +4245,7 @@ static PyObject *pyrna_struct_get(BPy_StructRNA *self, PyObject *args)
}
}
- return Py_INCREF(def), def;
+ return Py_INCREF_RET(def);
}
PyDoc_STRVAR(pyrna_struct_as_pointer_doc,
@@ -4289,7 +4307,7 @@ static PyObject *pyrna_prop_collection_get(BPy_PropertyRNA *self, PyObject *args
Py_TYPE(key_ob)->tp_name);
}
- return Py_INCREF(def), def;
+ return Py_INCREF_RET(def);
}
PyDoc_STRVAR(pyrna_prop_collection_find_doc,
@@ -4698,6 +4716,7 @@ static struct PyMethodDef pyrna_struct_methods[] = {
{"is_property_set", (PyCFunction)pyrna_struct_is_property_set, METH_VARARGS, pyrna_struct_is_property_set_doc},
{"property_unset", (PyCFunction)pyrna_struct_property_unset, METH_VARARGS, pyrna_struct_property_unset_doc},
{"is_property_hidden", (PyCFunction)pyrna_struct_is_property_hidden, METH_VARARGS, pyrna_struct_is_property_hidden_doc},
+ {"is_property_readonly", (PyCFunction)pyrna_struct_is_property_readonly, METH_VARARGS, pyrna_struct_is_property_readonly_doc},
{"path_resolve", (PyCFunction)pyrna_struct_path_resolve, METH_VARARGS, pyrna_struct_path_resolve_doc},
{"path_from_id", (PyCFunction)pyrna_struct_path_from_id, METH_VARARGS, pyrna_struct_path_from_id_doc},
{"type_recast", (PyCFunction)pyrna_struct_type_recast, METH_NOARGS, pyrna_struct_type_recast_doc},
@@ -4718,6 +4737,7 @@ static struct PyMethodDef pyrna_struct_methods[] = {
static struct PyMethodDef pyrna_prop_methods[] = {
{"path_from_id", (PyCFunction)pyrna_prop_path_from_id, METH_NOARGS, pyrna_prop_path_from_id_doc},
{"as_bytes", (PyCFunction)pyrna_prop_as_bytes, METH_NOARGS, pyrna_prop_as_bytes_doc},
+ {"update", (PyCFunction)pyrna_prop_update, METH_NOARGS, pyrna_prop_update_doc},
{"__dir__", (PyCFunction)pyrna_prop_dir, METH_NOARGS, NULL},
{NULL, NULL, 0, NULL}
};
@@ -4802,8 +4822,7 @@ static PyObject *pyrna_prop_new(PyTypeObject *type, PyObject *args, PyObject *UN
return NULL;
if (type == Py_TYPE(base)) {
- Py_INCREF(base);
- return (PyObject *)base;
+ return Py_INCREF_RET((PyObject *)base);
}
else if (PyType_IsSubtype(type, &pyrna_prop_Type)) {
BPy_PropertyRNA *ret = (BPy_PropertyRNA *) type->tp_alloc(type, 0);
@@ -4855,15 +4874,15 @@ static PyObject *pyrna_param_to_py(PointerRNA *ptr, PropertyRNA *prop, void *dat
switch (RNA_property_subtype(prop)) {
#ifdef USE_MATHUTILS
case PROP_ALL_VECTOR_SUBTYPES:
- ret = Vector_CreatePyObject(data, len, Py_NEW, NULL);
+ ret = Vector_CreatePyObject(data, len, NULL);
break;
case PROP_MATRIX:
if (len == 16) {
- ret = Matrix_CreatePyObject(data, 4, 4, Py_NEW, NULL);
+ ret = Matrix_CreatePyObject(data, 4, 4, NULL);
break;
}
else if (len == 9) {
- ret = Matrix_CreatePyObject(data, 3, 3, Py_NEW, NULL);
+ ret = Matrix_CreatePyObject(data, 3, 3, NULL);
break;
}
/* fall-through */
@@ -4971,14 +4990,11 @@ static PyObject *pyrna_param_to_py(PointerRNA *ptr, PropertyRNA *prop, void *dat
{
ListBase *lb = (ListBase *)data;
CollectionPointerLink *link;
- PyObject *linkptr;
ret = PyList_New(0);
for (link = lb->first; link; link = link->next) {
- linkptr = pyrna_struct_CreatePyObject(&link->ptr);
- PyList_Append(ret, linkptr);
- Py_DECREF(linkptr);
+ PyList_APPEND(ret, pyrna_struct_CreatePyObject(&link->ptr));
}
break;
@@ -5142,9 +5158,7 @@ static PyObject *pyrna_func_call(BPy_FunctionRNA *self, PyObject *args, PyObject
#ifdef DEBUG_STRING_FREE
if (item) {
if (PyUnicode_Check(item)) {
- item = PyUnicode_FromString(_PyUnicode_AsString(item));
- PyList_Append(string_free_ls, item);
- Py_DECREF(item);
+ PyList_APPEND(string_free_ls, PyUnicode_FromString(_PyUnicode_AsString(item)));
}
}
#endif
@@ -5240,7 +5254,7 @@ static PyObject *pyrna_func_call(BPy_FunctionRNA *self, PyObject *args, PyObject
good_args_str = BLI_dynstr_get_cstring(good_args);
PyErr_Format(PyExc_TypeError,
- "%.200s.%.200s(): was called with invalid keyword arguments(s) (%s), expected (%s)",
+ "%.200s.%.200s(): was called with invalid keyword argument(s) (%s), expected (%s)",
RNA_struct_identifier(self_ptr->type), RNA_function_identifier(self_func),
bad_args_str, good_args_str);
@@ -6287,7 +6301,7 @@ static PyObject *pyrna_srna_Subtype(StructRNA *srna)
/* arg[1] (bases=...) */
PyTuple_SET_ITEM(args, 1, item = PyTuple_New(1));
- PyTuple_SET_ITEM(item, 0, py_base); Py_INCREF(py_base);
+ PyTuple_SET_ITEM(item, 0, Py_INCREF_RET(py_base));
/* arg[2] (dict=...) */
@@ -6601,7 +6615,6 @@ static PyObject *pyrna_basetype_dir(BPy_BaseTypeRNA *self)
{
PyObject *list;
#if 0
- PyObject *name;
PyMethodDef *meth;
#endif
@@ -6609,9 +6622,7 @@ static PyObject *pyrna_basetype_dir(BPy_BaseTypeRNA *self)
#if 0 /* for now only contains __dir__ */
for (meth = pyrna_basetype_methods; meth->ml_name; meth++) {
- name = PyUnicode_FromString(meth->ml_name);
- PyList_Append(list, name);
- Py_DECREF(name);
+ PyList_APPEND(list, PyUnicode_FromString(meth->ml_name));
}
#endif
return list;
@@ -6622,7 +6633,6 @@ static PyObject *pyrna_basetype_dir(BPy_BaseTypeRNA *self)
static PyObject *pyrna_basetype_dir(BPy_BaseTypeRNA *self)
{
PyObject *ret = PyList_New(0);
- PyObject *item;
RNA_PROP_BEGIN (&self->ptr, itemptr, self->prop)
{
@@ -6634,9 +6644,7 @@ static PyObject *pyrna_basetype_dir(BPy_BaseTypeRNA *self)
}
else {
/* add to python list */
- item = PyUnicode_FromString(RNA_struct_identifier(srna));
- PyList_Append(ret, item);
- Py_DECREF(item);
+ PyList_APPEND(ret, PyUnicode_FromString(RNA_struct_identifier(srna)));
}
}
RNA_PROP_END;
@@ -7457,8 +7465,14 @@ static void bpy_class_free(void *pyob_ptr)
PyGILState_Release(gilstate);
}
+/**
+ * \note This isn't essential to run on startup, since subtypes will lazy initialize.
+ * But keep running in debug mode so we get immediate notification of bad class hierarchy
+ * or any errors in "bpy_types.py" at load time, so errors don't go unnoticed.
+ */
void pyrna_alloc_types(void)
{
+#ifdef DEBUG
PyGILState_STATE gilstate;
PointerRNA ptr;
@@ -7486,6 +7500,7 @@ void pyrna_alloc_types(void)
RNA_PROP_END;
PyGILState_Release(gilstate);
+#endif /* DEBUG */
}
diff --git a/source/blender/python/intern/bpy_rna_anim.c b/source/blender/python/intern/bpy_rna_anim.c
index ed51ba5bd1f..ced7d6a5c1c 100644
--- a/source/blender/python/intern/bpy_rna_anim.c
+++ b/source/blender/python/intern/bpy_rna_anim.c
@@ -53,6 +53,8 @@
#include "bpy_util.h"
#include "bpy_rna_anim.h"
+#include "../generic/python_utildefines.h"
+
/* for keyframes and drivers */
static int pyrna_struct_anim_args_parse(
PointerRNA *ptr, const char *error_prefix, const char *path,
@@ -329,16 +331,13 @@ PyObject *pyrna_struct_driver_add(BPy_StructRNA *self, PyObject *args)
FCurve *fcu;
PointerRNA tptr;
- PyObject *item;
if (index == -1) { /* all, use a list */
int i = 0;
ret = PyList_New(0);
while ((fcu = list_find_fcurve(&adt->drivers, path_full, i++))) {
RNA_pointer_create(id, &RNA_FCurve, fcu, &tptr);
- item = pyrna_struct_CreatePyObject(&tptr);
- PyList_Append(ret, item);
- Py_DECREF(item);
+ PyList_APPEND(ret, pyrna_struct_CreatePyObject(&tptr));
}
}
else {
diff --git a/source/blender/python/intern/bpy_util.c b/source/blender/python/intern/bpy_util.c
index 93183a4f320..ee827c06e14 100644
--- a/source/blender/python/intern/bpy_util.c
+++ b/source/blender/python/intern/bpy_util.c
@@ -39,7 +39,7 @@
#include "BKE_report.h"
#include "BKE_context.h"
-#include "BLF_translation.h"
+#include "BLT_translation.h"
#include "../generic/py_capi_utils.h"
@@ -82,14 +82,9 @@ short BPy_reports_to_error(ReportList *reports, PyObject *exception, const bool
}
-short BPy_errors_to_report(ReportList *reports)
+bool BPy_errors_to_report_ex(ReportList *reports, const bool use_full, const bool use_location)
{
PyObject *pystring;
- PyObject *pystring_format = NULL; /* workaround, see below */
- const char *cstring;
-
- const char *filename;
- int lineno;
if (!PyErr_Occurred())
return 1;
@@ -101,31 +96,56 @@ short BPy_errors_to_report(ReportList *reports)
return 1;
}
- pystring = PyC_ExceptionBuffer();
+ if (use_full) {
+ pystring = PyC_ExceptionBuffer();
+ }
+ else {
+ pystring = PyC_ExceptionBuffer_Simple();
+ }
if (pystring == NULL) {
BKE_report(reports, RPT_ERROR, "Unknown py-exception, could not convert");
return 0;
}
-
- PyC_FileAndNum(&filename, &lineno);
- if (filename == NULL)
- filename = "<unknown location>";
-
- cstring = _PyUnicode_AsString(pystring);
+
+ if (use_location) {
+ const char *filename;
+ int lineno;
+
+ PyObject *pystring_format; /* workaround, see below */
+ const char *cstring;
+
+ PyC_FileAndNum(&filename, &lineno);
+ if (filename == NULL) {
+ filename = "<unknown location>";
+ }
#if 0 /* ARG!. workaround for a bug in blenders use of vsnprintf */
- BKE_reportf(reports, RPT_ERROR, "%s\nlocation: %s:%d\n", cstring, filename, lineno);
+ BKE_reportf(reports, RPT_ERROR, "%s\nlocation: %s:%d\n", _PyUnicode_AsString(pystring), filename, lineno);
#else
- pystring_format = PyUnicode_FromFormat(TIP_("%s\nlocation: %s:%d\n"), cstring, filename, lineno);
- cstring = _PyUnicode_AsString(pystring_format);
- BKE_report(reports, RPT_ERROR, cstring);
+ pystring_format = PyUnicode_FromFormat(
+ TIP_("%s\nlocation: %s:%d\n"),
+ _PyUnicode_AsString(pystring), filename, lineno);
+
+ cstring = _PyUnicode_AsString(pystring_format);
+ BKE_report(reports, RPT_ERROR, cstring);
+
+ /* not exactly needed. just for testing */
+ fprintf(stderr, TIP_("%s\nlocation: %s:%d\n"), cstring, filename, lineno);
+
+ Py_DECREF(pystring_format); /* workaround */
#endif
+ }
+ else {
+ BKE_report(reports, RPT_ERROR, _PyUnicode_AsString(pystring));
+ }
- /* not exactly needed. just for testing */
- fprintf(stderr, TIP_("%s\nlocation: %s:%d\n"), cstring, filename, lineno);
Py_DECREF(pystring);
- Py_DECREF(pystring_format); /* workaround */
return 1;
}
+
+bool BPy_errors_to_report(ReportList *reports)
+{
+ return BPy_errors_to_report_ex(reports, true, true);
+} \ No newline at end of file
diff --git a/source/blender/python/intern/bpy_util.h b/source/blender/python/intern/bpy_util.h
index d19696aa230..1ae00a7fb02 100644
--- a/source/blender/python/intern/bpy_util.h
+++ b/source/blender/python/intern/bpy_util.h
@@ -40,7 +40,8 @@ char *BPy_enum_as_string(struct EnumPropertyItem *item);
/* error reporting */
short BPy_reports_to_error(struct ReportList *reports, PyObject *exception, const bool clear);
-short BPy_errors_to_report(struct ReportList *reports);
+bool BPy_errors_to_report_ex(struct ReportList *reports, const bool use_full, const bool use_location);
+bool BPy_errors_to_report(struct ReportList *reports);
/* TODO - find a better solution! */
struct bContext *BPy_GetContext(void);
diff --git a/source/blender/python/intern/bpy_utils_previews.c b/source/blender/python/intern/bpy_utils_previews.c
new file mode 100644
index 00000000000..fed7c7210de
--- /dev/null
+++ b/source/blender/python/intern/bpy_utils_previews.c
@@ -0,0 +1,188 @@
+/*
+ * ***** 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): Bastien Montagne
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/python/intern/bpy_utils_previews.c
+ * \ingroup pythonintern
+ *
+ * This file defines a singleton py object accessed via 'bpy.utils.previews',
+ * which exposes low-level API for custom previews/icons.
+ * It is replaced in final API by an higher-level python wrapper, that handles previews by addon,
+ * and automatically release them on deletion.
+ */
+
+#include <Python.h>
+#include <structmember.h>
+
+#include "BLI_utildefines.h"
+
+#include "RNA_types.h"
+#include "RNA_access.h"
+
+#include "BPY_extern.h"
+#include "bpy_utils_previews.h"
+#include "bpy_rna.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "IMB_imbuf.h"
+#include "IMB_imbuf_types.h"
+#include "IMB_thumbs.h"
+
+#include "BKE_icons.h"
+
+#include "DNA_ID.h"
+
+#include "../generic/python_utildefines.h"
+
+#define STR_SOURCE_TYPES "'IMAGE', 'MOVIE', 'BLEND', 'FONT'"
+
+PyDoc_STRVAR(bpy_utils_previews_new_doc,
+".. method:: new(name)\n"
+"\n"
+" Generate a new empty preview, or return existing one matching ``name``.\n"
+"\n"
+" :arg name: The name (unique id) identifying the preview.\n"
+" :type name: string\n"
+" :return: The Preview matching given name, or a new empty one.\n"
+" :rtype: :class:`bpy.types.ImagePreview`\n"
+);
+static PyObject *bpy_utils_previews_new(PyObject *UNUSED(self), PyObject *args)
+{
+ char *name;
+ PreviewImage *prv;
+ PointerRNA ptr;
+
+ if (!PyArg_ParseTuple(args, "s:new", &name)) {
+ return NULL;
+ }
+
+ prv = BKE_previewimg_cached_ensure(name);
+ RNA_pointer_create(NULL, &RNA_ImagePreview, prv, &ptr);
+
+ return pyrna_struct_CreatePyObject(&ptr);
+}
+
+PyDoc_STRVAR(bpy_utils_previews_load_doc,
+".. method:: load(name, filepath, filetype, force_reload=False)\n"
+"\n"
+" Generate a new preview from given file path, or return existing one matching ``name``.\n"
+"\n"
+" :arg name: The name (unique id) identifying the preview.\n"
+" :type name: string\n"
+" :arg filepath: The file path to generate the preview from.\n"
+" :type filepath: string\n"
+" :arg filetype: The type of file, needed to generate the preview in [" STR_SOURCE_TYPES "].\n"
+" :type filetype: string\n"
+" :arg force_reload: If True, force running thumbnail manager even if preview already exists in cache.\n"
+" :type force_reload: bool\n"
+" :return: The Preview matching given name, or a new empty one.\n"
+" :rtype: :class:`bpy.types.ImagePreview`\n"
+);
+static PyObject *bpy_utils_previews_load(PyObject *UNUSED(self), PyObject *args)
+{
+ char *name, *path, *path_type_s;
+ int path_type, force_reload = false;
+
+ PreviewImage *prv;
+ PointerRNA ptr;
+
+ if (!PyArg_ParseTuple( args, "sss|p:load", &name, &path, &path_type_s, &force_reload)) {
+ return NULL;
+ }
+
+ if (STREQ(path_type_s, "IMAGE")) {
+ path_type = THB_SOURCE_IMAGE;
+ }
+ else if (STREQ(path_type_s, "MOVIE")) {
+ path_type = THB_SOURCE_MOVIE;
+ }
+ else if (STREQ(path_type_s, "BLEND")) {
+ path_type = THB_SOURCE_BLEND;
+ }
+ else if (STREQ(path_type_s, "FONT")) {
+ path_type = THB_SOURCE_FONT;
+ }
+ else {
+ PyErr_Format(PyExc_ValueError,
+ "load: invalid '%s' filetype, only [" STR_SOURCE_TYPES "] "
+ "are supported", path_type_s);
+ return NULL;
+ }
+
+ prv = BKE_previewimg_cached_thumbnail_read(name, path, path_type, force_reload);
+ RNA_pointer_create(NULL, &RNA_ImagePreview, prv, &ptr);
+
+ return pyrna_struct_CreatePyObject(&ptr);
+}
+
+PyDoc_STRVAR(bpy_utils_previews_release_doc,
+".. method:: release(name)\n"
+"\n"
+" Release (free) a previously created preview.\n"
+"\n"
+"\n"
+" :arg name: The name (unique id) identifying the preview.\n"
+" :type name: string\n"
+);
+static PyObject *bpy_utils_previews_release(PyObject *UNUSED(self), PyObject *args)
+{
+ char *name;
+
+ if (!PyArg_ParseTuple(args, "s:release", &name)) {
+ return NULL;
+ }
+
+ BKE_previewimg_cached_release(name);
+
+ Py_RETURN_NONE;
+}
+
+static struct PyMethodDef bpy_utils_previews_methods[] = {
+ /* Can't use METH_KEYWORDS alone, see http://bugs.python.org/issue11587 */
+ {"new", (PyCFunction)bpy_utils_previews_new, METH_VARARGS, bpy_utils_previews_new_doc},
+ {"load", (PyCFunction)bpy_utils_previews_load, METH_VARARGS, bpy_utils_previews_load_doc},
+ {"release", (PyCFunction)bpy_utils_previews_release, METH_VARARGS, bpy_utils_previews_release_doc},
+ {NULL, NULL, 0, NULL}
+};
+
+PyDoc_STRVAR(bpy_utils_previews_doc,
+"This object contains basic static methods to handle cached (non-ID) previews in Blender\n"
+"(low-level API, not exposed to final users)."
+);
+static struct PyModuleDef bpy_utils_previews_module = {
+ PyModuleDef_HEAD_INIT,
+ "bpy._utils_previews",
+ bpy_utils_previews_doc,
+ 0,
+ bpy_utils_previews_methods,
+ NULL, NULL, NULL, NULL
+};
+
+
+PyObject *BPY_utils_previews_module(void)
+{
+ PyObject *submodule;
+
+ submodule = PyModule_Create(&bpy_utils_previews_module);
+
+ return submodule;
+}
diff --git a/source/blender/python/intern/bpy_utils_previews.h b/source/blender/python/intern/bpy_utils_previews.h
new file mode 100644
index 00000000000..3d7ade04b9f
--- /dev/null
+++ b/source/blender/python/intern/bpy_utils_previews.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): Bastien Montagne
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/python/intern/bpy_utils_previews.h
+ * \ingroup pythonintern
+ */
+
+#ifndef __BPY_UTILS_PREVIEWS_H__
+#define __BPY_UTILS_PREVIEWS_H__
+
+PyObject *BPY_utils_previews_module(void);
+
+#endif /* __BPY_UTILS_PREVIEWS_H__ */
diff --git a/source/blender/python/intern/bpy_utils_units.c b/source/blender/python/intern/bpy_utils_units.c
index cdbd57bcebe..057df4ccd41 100644
--- a/source/blender/python/intern/bpy_utils_units.c
+++ b/source/blender/python/intern/bpy_utils_units.c
@@ -35,9 +35,7 @@
#include "BLI_utildefines.h"
#include "BLI_string.h"
-#include "BLI_ghash.h"
-#include "BPY_extern.h"
#include "bpy_utils_units.h"
#include "../generic/py_capi_utils.h"
@@ -157,18 +155,18 @@ static bool bpyunits_validate(const char *usys_str, const char *ucat_str, int *r
}
PyDoc_STRVAR(bpyunits_to_value_doc,
-".. method:: to_value(unit_system, unit_category, str_input, [str_ref_unit=None])\n"
+".. method:: to_value(unit_system, unit_category, str_input, str_ref_unit=None)\n"
"\n"
" Convert a given input string into a float value.\n"
"\n"
" :arg unit_system: The unit system, from :attr:`bpy.utils.units.systems`.\n"
" :type unit_system: string\n"
-" :arg unit_category: The category of data we are converting (length, area, rotation, etc.), "
+" :arg unit_category: The category of data we are converting (length, area, rotation, etc.),\n"
" from :attr:`bpy.utils.units.categories`.\n"
" :type unit_category: string\n"
" :arg str_input: The string to convert to a float value.\n"
" :type str_input: string\n"
-" :arg str_ref_unit: A reference string from which to extract a default unit, if none is found in :arg:`str_input`.\n"
+" :arg str_ref_unit: A reference string from which to extract a default unit, if none is found in ``str_input``.\n"
" :type str_ref_unit: string or None\n"
" :return: The converted/interpreted value.\n"
" :rtype: float\n"
@@ -223,13 +221,13 @@ static PyObject *bpyunits_to_value(PyObject *UNUSED(self), PyObject *args, PyObj
}
PyDoc_STRVAR(bpyunits_to_string_doc,
-".. method:: to_string(unit_system, unit_category, value, [precision=3, [split_unit=False, [compatible_unit=False]]])\n"
+".. method:: to_string(unit_system, unit_category, value, precision=3, split_unit=False, compatible_unit=False)\n"
"\n"
" Convert a given input float value into a string with units.\n"
"\n"
" :arg unit_system: The unit system, from :attr:`bpy.utils.units.systems`.\n"
" :type unit_system: string\n"
-" :arg unit_category: The category of data we are converting (length, area, rotation, etc.), "
+" :arg unit_category: The category of data we are converting (length, area, rotation, etc.),\n"
" from :attr:`bpy.utils.units.categories`.\n"
" :type unit_category: string\n"
" :arg value: The value to convert to a string.\n"
@@ -251,12 +249,17 @@ static PyObject *bpyunits_to_string(PyObject *UNUSED(self), PyObject *args, PyOb
char *usys_str = NULL, *ucat_str = NULL;
double value = 0.0;
- int precision = 3, split_unit = false, compatible_unit = false;
+ int precision = 3;
+ bool split_unit = false, compatible_unit = false;
int usys, ucat;
- if (!PyArg_ParseTupleAndKeywords(args, kw, "ssd|ipp:bpy.utils.units.to_string", (char **)kwlist,
- &usys_str, &ucat_str, &value, &precision, &split_unit, &compatible_unit))
+ if (!PyArg_ParseTupleAndKeywords(
+ args, kw,
+ "ssd|iO&O&:bpy.utils.units.to_string", (char **)kwlist,
+ &usys_str, &ucat_str, &value, &precision,
+ PyC_ParseBool, &split_unit,
+ PyC_ParseBool, &compatible_unit))
{
return NULL;
}
diff --git a/source/blender/python/intern/gpu.c b/source/blender/python/intern/gpu.c
index 26e3bde57a3..a7ece10f06c 100644
--- a/source/blender/python/intern/gpu.c
+++ b/source/blender/python/intern/gpu.c
@@ -40,7 +40,6 @@
#include <Python.h>
#include "DNA_scene_types.h"
-#include "DNA_image_types.h"
#include "DNA_material_types.h"
#include "DNA_ID.h"
#include "DNA_customdata_types.h"
@@ -80,22 +79,70 @@ static PyObject *PyInit_gpu(void)
if (m == NULL)
return NULL;
+
+ /* Take care to update docs when editing: 'doc/python_api/rst/gpu.rst' */
+
+
+ /* -------------------------------------------------------------------- */
+ /* GPUDynamicType */
+
+ /* device constant groups */
+ PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_GROUP_MISC);
+ PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_GROUP_LAMP);
+ PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_GROUP_OBJECT);
+ PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_GROUP_SAMPLER);
+ PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_GROUP_MIST);
+ PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_GROUP_WORLD);
+ PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_GROUP_MAT);
+
/* device constants */
+ PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_NONE);
+ /* GPU_DYNAMIC_GROUP_OBJECT */
PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_OBJECT_VIEWMAT);
PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_OBJECT_MAT);
PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_OBJECT_VIEWIMAT);
PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_OBJECT_IMAT);
PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_OBJECT_COLOR);
PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_OBJECT_AUTOBUMPSCALE);
+ /* GPU_DYNAMIC_GROUP_LAMP */
PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_LAMP_DYNVEC);
PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_LAMP_DYNCO);
PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_LAMP_DYNIMAT);
PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_LAMP_DYNPERSMAT);
PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_LAMP_DYNENERGY);
PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_LAMP_DYNCOL);
+ PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_LAMP_ATT1);
+ PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_LAMP_ATT2);
+ PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_LAMP_DISTANCE);
+ PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_LAMP_SPOTSIZE);
+ PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_LAMP_SPOTBLEND);
+ /* GPU_DYNAMIC_GROUP_SAMPLER */
PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_SAMPLER_2DBUFFER);
PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_SAMPLER_2DIMAGE);
PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_SAMPLER_2DSHADOW);
+ /* GPU_DYNAMIC_GROUP_MIST */
+ PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_MIST_ENABLE);
+ PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_MIST_START);
+ PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_MIST_DISTANCE);
+ PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_MIST_INTENSITY);
+ PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_MIST_TYPE);
+ PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_MIST_COLOR);
+ /* GPU_DYNAMIC_GROUP_WORLD */
+ PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_HORIZON_COLOR);
+ PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_AMBIENT_COLOR);
+ /* GPU_DYNAMIC_GROUP_MAT */
+ PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_MAT_DIFFRGB);
+ PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_MAT_REF);
+ PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_MAT_SPECRGB);
+ PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_MAT_SPEC);
+ PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_MAT_HARD);
+ PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_MAT_EMIT);
+ PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_MAT_AMB);
+ PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_MAT_ALPHA);
+
+
+ /* -------------------------------------------------------------------- */
+ /* GPUDataType */
PY_MODULE_ADD_CONSTANT(m, GPU_DATA_1I);
PY_MODULE_ADD_CONSTANT(m, GPU_DATA_1F);
@@ -106,6 +153,12 @@ static PyObject *PyInit_gpu(void)
PY_MODULE_ADD_CONSTANT(m, GPU_DATA_16F);
PY_MODULE_ADD_CONSTANT(m, GPU_DATA_4UB);
+
+ /* -------------------------------------------------------------------- */
+ /* CustomDataType
+ *
+ * Intentionally only include the subset used by the GPU API.
+ */
PY_MODULE_ADD_CONSTANT(m, CD_MTFACE);
PY_MODULE_ADD_CONSTANT(m, CD_ORCO);
PY_MODULE_ADD_CONSTANT(m, CD_TANGENT);
@@ -200,7 +253,7 @@ static PyObject *GPU_export_shader(PyObject *UNUSED(self), PyObject *args, PyObj
if (shader->vertex) {
PY_DICT_ADD_STRING(result, shader, vertex);
}
- seq = PyList_New(BLI_countlist(&shader->uniforms));
+ seq = PyList_New(BLI_listbase_count(&shader->uniforms));
for (i = 0, uniform = shader->uniforms.first; uniform; uniform = uniform->next, i++) {
dict = PyDict_New();
PY_DICT_ADD_STRING(dict, uniform, varname);
@@ -229,7 +282,7 @@ static PyObject *GPU_export_shader(PyObject *UNUSED(self), PyObject *args, PyObj
PyDict_SetItemString(result, "uniforms", seq);
Py_DECREF(seq);
- seq = PyList_New(BLI_countlist(&shader->attributes));
+ seq = PyList_New(BLI_listbase_count(&shader->attributes));
for (i = 0, attribute = shader->attributes.first; attribute; attribute = attribute->next, i++) {
dict = PyDict_New();
PY_DICT_ADD_STRING(dict, attribute, varname);
diff --git a/source/blender/python/mathutils/CMakeLists.txt b/source/blender/python/mathutils/CMakeLists.txt
index 133b8d3895c..f70f893aeac 100644
--- a/source/blender/python/mathutils/CMakeLists.txt
+++ b/source/blender/python/mathutils/CMakeLists.txt
@@ -22,6 +22,7 @@ set(INC
.
../../blenlib
../../blenkernel
+ ../../bmesh
../../makesdna
../../../../intern/guardedalloc
)
@@ -37,7 +38,9 @@ set(SRC
mathutils_Matrix.c
mathutils_Quaternion.c
mathutils_Vector.c
+ mathutils_bvhtree.c
mathutils_geometry.c
+ mathutils_interpolate.c
mathutils_kdtree.c
mathutils_noise.c
@@ -47,7 +50,9 @@ set(SRC
mathutils_Matrix.h
mathutils_Quaternion.h
mathutils_Vector.h
+ mathutils_bvhtree.h
mathutils_geometry.h
+ mathutils_interpolate.h
mathutils_kdtree.h
mathutils_noise.h
)
diff --git a/source/blender/python/mathutils/mathutils.c b/source/blender/python/mathutils/mathutils.c
index 349f8483fb0..635090869ea 100644
--- a/source/blender/python/mathutils/mathutils.c
+++ b/source/blender/python/mathutils/mathutils.c
@@ -31,12 +31,25 @@
#include "BLI_math.h"
#include "BLI_utildefines.h"
+#include "../generic/python_utildefines.h"
+
#ifndef MATH_STANDALONE
# include "BLI_dynstr.h"
#endif
PyDoc_STRVAR(M_Mathutils_doc,
-"This module provides access to matrices, eulers, quaternions and vectors."
+"This module provides access to the math classes:\n"
+"\n"
+"- :class:`Color`,\n"
+"- :class:`Euler`,\n"
+"- :class:`Matrix`,\n"
+"- :class:`Quaternion`,\n"
+"- :class:`Vector`,\n"
+"\n"
+".. note::\n"
+"\n"
+" Classes, methods and attributes that accept vectors also accept other numeric sequences,\n"
+" such as tuples, lists."
);
static int mathutils_array_parse_fast(float *array,
int size,
@@ -44,33 +57,67 @@ static int mathutils_array_parse_fast(float *array,
const char *error_prefix)
{
PyObject *item;
+ PyObject **value_fast_items = PySequence_Fast_ITEMS(value_fast);
int i;
i = size;
do {
i--;
- if (((array[i] = PyFloat_AsDouble((item = PySequence_Fast_GET_ITEM(value_fast, i)))) == -1.0f) &&
+ if (((array[i] = PyFloat_AsDouble((item = value_fast_items[i]))) == -1.0f) &&
PyErr_Occurred())
{
PyErr_Format(PyExc_TypeError,
"%.200s: sequence index %d expected a number, "
"found '%.200s' type, ",
error_prefix, i, Py_TYPE(item)->tp_name);
- Py_DECREF(value_fast);
- return -1;
+ size = -1;
+ break;
}
} while (i);
- Py_XDECREF(value_fast);
return size;
}
-/* helper functionm returns length of the 'value', -1 on error */
+/**
+ * helper function that returns a Python ``__hash__``.
+ *
+ * \note consistent with the equivalent tuple of floats (CPython's 'tuplehash')
+ */
+Py_hash_t mathutils_array_hash(const float *array, size_t array_len)
+{
+ int i;
+ Py_uhash_t x; /* Unsigned for defined overflow behavior. */
+ Py_hash_t y;
+ Py_uhash_t mult;
+ Py_ssize_t len;
+
+ mult = _PyHASH_MULTIPLIER;
+ len = array_len;
+ x = 0x345678UL;
+ i = 0;
+ while (--len >= 0) {
+ y = _Py_HashDouble((double)(array[i++]));
+ if (y == -1)
+ return -1;
+ x = (x ^ y) * mult;
+ /* the cast might truncate len; that doesn't change hash stability */
+ mult += (Py_hash_t)(82520UL + len + len);
+ }
+ x += 97531UL;
+ if (x == (Py_uhash_t)-1)
+ x = -2;
+ return x;
+}
+
+/* helper function returns length of the 'value', -1 on error */
int mathutils_array_parse(float *array, int array_min, int array_max, PyObject *value, const char *error_prefix)
{
+ const unsigned int flag = array_max;
int size;
+ array_max &= ~MU_ARRAY_FLAGS;
+
#if 1 /* approx 6x speedup for mathutils types */
if ((size = VectorObject_Check(value) ? ((VectorObject *)value)->size : 0) ||
@@ -82,6 +129,10 @@ int mathutils_array_parse(float *array, int array_min, int array_max, PyObject *
return -1;
}
+ if (flag & MU_ARRAY_SPILL) {
+ CLAMP_MAX(size, array_max);
+ }
+
if (size > array_max || size < array_min) {
if (array_max == array_min) {
PyErr_Format(PyExc_ValueError,
@@ -97,7 +148,6 @@ int mathutils_array_parse(float *array, int array_min, int array_max, PyObject *
}
memcpy(array, ((BaseMathObject *)value)->data, size * sizeof(float));
- return size;
}
else
#endif
@@ -112,6 +162,10 @@ int mathutils_array_parse(float *array, int array_min, int array_max, PyObject *
size = PySequence_Fast_GET_SIZE(value_fast);
+ if (flag & MU_ARRAY_SPILL) {
+ CLAMP_MAX(size, array_max);
+ }
+
if (size > array_max || size < array_min) {
if (array_max == array_min) {
PyErr_Format(PyExc_ValueError,
@@ -127,8 +181,20 @@ int mathutils_array_parse(float *array, int array_min, int array_max, PyObject *
return -1;
}
- return mathutils_array_parse_fast(array, size, value_fast, error_prefix);
+ size = mathutils_array_parse_fast(array, size, value_fast, error_prefix);
+ Py_DECREF(value_fast);
+ }
+
+ if (size != -1) {
+ if (flag & MU_ARRAY_ZERO) {
+ int size_left = array_max - size;
+ if (size_left) {
+ memset(&array[size], 0, sizeof(float) * size_left);
+ }
+ }
}
+
+ return size;
}
/* on error, -1 is returned and no allocation is made */
@@ -174,6 +240,7 @@ int mathutils_array_parse_alloc(float **array, int array_min, PyObject *value, c
size = PySequence_Fast_GET_SIZE(value_fast);
if (size < array_min) {
+ Py_DECREF(value_fast);
PyErr_Format(PyExc_ValueError,
"%.200s: sequence size is %d, expected > %d",
error_prefix, size, array_min);
@@ -183,6 +250,7 @@ int mathutils_array_parse_alloc(float **array, int array_min, PyObject *value, c
*array = PyMem_Malloc(size * sizeof(float));
ret = mathutils_array_parse_fast(*array, size, value_fast, error_prefix);
+ Py_DECREF(value_fast);
if (ret == -1) {
PyMem_Free(*array);
@@ -195,7 +263,8 @@ int mathutils_array_parse_alloc(float **array, int array_min, PyObject *value, c
/* parse an array of vectors */
int mathutils_array_parse_alloc_v(float **array, int array_dim, PyObject *value, const char *error_prefix)
{
- PyObject *value_fast = NULL;
+ PyObject *value_fast;
+ const int array_dim_flag = array_dim;
int i, size;
/* non list/tuple cases */
@@ -207,14 +276,17 @@ int mathutils_array_parse_alloc_v(float **array, int array_dim, PyObject *value,
size = PySequence_Fast_GET_SIZE(value_fast);
if (size != 0) {
+ PyObject **value_fast_items = PySequence_Fast_ITEMS(value_fast);
float *fp;
+ array_dim &= ~MU_ARRAY_FLAGS;
+
fp = *array = PyMem_Malloc(size * array_dim * sizeof(float));
for (i = 0; i < size; i++, fp += array_dim) {
- PyObject *item = PySequence_Fast_GET_ITEM(value, i);
+ PyObject *item = value_fast_items[i];
- if (mathutils_array_parse(fp, array_dim, array_dim, item, error_prefix) == -1) {
+ if (mathutils_array_parse(fp, array_dim, array_dim_flag, item, error_prefix) == -1) {
PyMem_Free(*array);
*array = NULL;
size = -1;
@@ -280,6 +352,15 @@ int mathutils_any_to_rotmat(float rmat[3][3], PyObject *value, const char *error
/* Utility functions */
/* LomontRRDCompare4, Ever Faster Float Comparisons by Randy Dillon */
+/* XXX We may want to use 'safer' BLI's compare_ff_relative ultimately?
+ * LomontRRDCompare4() is an optimized version of Dawson's AlmostEqual2sComplement() (see [1] and [2]).
+ * Dawson himself now claims this is not a 'safe' thing to do (pushing ULP method beyond its limits),
+ * an recommends using work from [3] instead, which is done in BLI func...
+ *
+ * [1] http://www.randydillon.org/Papers/2007/everfast.htm
+ * [2] http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm
+ * [3] https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/ instead
+ */
#define SIGNMASK(i) (-(int)(((unsigned int)(i)) >> 31))
int EXPP_FloatsAreEqual(float af, float bf, int maxDiff)
@@ -335,7 +416,7 @@ int mathutils_deepcopy_args_check(PyObject *args)
/* Mathutils Callbacks */
/* for mathutils internal use only, eventually should re-alloc but to start with we only have a few users */
-#define MATHUTILS_TOT_CB 16
+#define MATHUTILS_TOT_CB 17
static Mathutils_Callback *mathutils_callbacks[MATHUTILS_TOT_CB] = {NULL};
unsigned char Mathutils_RegisterCallback(Mathutils_Callback *cb)
@@ -415,19 +496,59 @@ int _BaseMathObject_WriteIndexCallback(BaseMathObject *self, int index)
return -1;
}
+void _BaseMathObject_RaiseFrozenExc(const BaseMathObject *self)
+{
+ PyErr_Format(PyExc_TypeError,
+ "%s is frozen (immutable)",
+ Py_TYPE(self)->tp_name);
+}
+
+void _BaseMathObject_RaiseNotFrozenExc(const BaseMathObject *self)
+{
+ PyErr_Format(PyExc_TypeError,
+ "%s is not frozen (mutable), call freeze first",
+ Py_TYPE(self)->tp_name);
+}
+
/* BaseMathObject generic functions for all mathutils types */
char BaseMathObject_owner_doc[] = "The item this is wrapping or None (read-only).";
PyObject *BaseMathObject_owner_get(BaseMathObject *self, void *UNUSED(closure))
{
PyObject *ret = self->cb_user ? self->cb_user : Py_None;
- Py_INCREF(ret);
- return ret;
+ return Py_INCREF_RET(ret);
}
char BaseMathObject_is_wrapped_doc[] = "True when this object wraps external data (read-only).\n\n:type: boolean";
PyObject *BaseMathObject_is_wrapped_get(BaseMathObject *self, void *UNUSED(closure))
{
- return PyBool_FromLong((self->wrapped == Py_WRAP) ? 1 : 0);
+ return PyBool_FromLong((self->flag & BASE_MATH_FLAG_IS_WRAP) != 0);
+}
+
+char BaseMathObject_is_frozen_doc[] = "True when this object has been frozen (read-only).\n\n:type: boolean";
+PyObject *BaseMathObject_is_frozen_get(BaseMathObject *self, void *UNUSED(closure))
+{
+ return PyBool_FromLong((self->flag & BASE_MATH_FLAG_IS_FROZEN) != 0);
+}
+
+char BaseMathObject_freeze_doc[] =
+".. function:: freeze()\n"
+"\n"
+" Make this object immutable.\n"
+"\n"
+" After this the object can be hashed, used in dictionaries & sets.\n"
+"\n"
+" :return: An instance of this object.\n"
+;
+PyObject *BaseMathObject_freeze(BaseMathObject *self)
+{
+ if (self->flag & BASE_MATH_FLAG_IS_WRAP) {
+ PyErr_SetString(PyExc_TypeError, "Cannot freeze wrapped data");
+ return NULL;
+ }
+
+ self->flag |= BASE_MATH_FLAG_IS_FROZEN;
+
+ return Py_INCREF_RET((PyObject *)self);
}
int BaseMathObject_traverse(BaseMathObject *self, visitproc visit, void *arg)
@@ -445,7 +566,7 @@ int BaseMathObject_clear(BaseMathObject *self)
void BaseMathObject_dealloc(BaseMathObject *self)
{
/* only free non wrapped */
- if (self->wrapped != Py_WRAP) {
+ if ((self->flag & BASE_MATH_FLAG_IS_WRAP) == 0) {
PyMem_Free(self->data);
}
@@ -477,7 +598,9 @@ static struct PyModuleDef M_Mathutils_module_def = {
/* submodules only */
#include "mathutils_geometry.h"
+#include "mathutils_interpolate.h"
#ifndef MATH_STANDALONE
+# include "mathutils_bvhtree.h"
# include "mathutils_kdtree.h"
# include "mathutils_noise.h"
#endif
@@ -518,12 +641,24 @@ PyMODINIT_FUNC PyInit_mathutils(void)
PyDict_SetItemString(sys_modules, PyModule_GetName(submodule), submodule);
Py_INCREF(submodule);
+ PyModule_AddObject(mod, "interpolate", (submodule = PyInit_mathutils_interpolate()));
+ /* XXX, python doesnt do imports with this usefully yet
+ * 'from mathutils.geometry import PolyFill'
+ * ...fails without this. */
+ PyDict_SetItemString(sys_modules, PyModule_GetName(submodule), submodule);
+ Py_INCREF(submodule);
+
#ifndef MATH_STANDALONE
/* Noise submodule */
PyModule_AddObject(mod, "noise", (submodule = PyInit_mathutils_noise()));
PyDict_SetItemString(sys_modules, PyModule_GetName(submodule), submodule);
Py_INCREF(submodule);
+ /* BVHTree submodule */
+ PyModule_AddObject(mod, "bvhtree", (submodule = PyInit_mathutils_bvhtree()));
+ PyDict_SetItemString(sys_modules, PyModule_GetName(submodule), submodule);
+ Py_INCREF(submodule);
+
/* KDTree submodule */
PyModule_AddObject(mod, "kdtree", (submodule = PyInit_mathutils_kdtree()));
PyDict_SetItemString(sys_modules, PyModule_GetName(submodule), submodule);
diff --git a/source/blender/python/mathutils/mathutils.h b/source/blender/python/mathutils/mathutils.h
index eb25d9bff07..6ac75565c66 100644
--- a/source/blender/python/mathutils/mathutils.h
+++ b/source/blender/python/mathutils/mathutils.h
@@ -29,11 +29,25 @@
/* Can cast different mathutils types to this, use for generic funcs */
+#include "BLI_compiler_attrs.h"
+
struct DynStr;
extern char BaseMathObject_is_wrapped_doc[];
+extern char BaseMathObject_is_frozen_doc[];
extern char BaseMathObject_owner_doc[];
+#define BASE_MATH_NEW(struct_name, root_type, base_type) \
+ (struct_name *)((base_type ? (base_type)->tp_alloc(base_type, 0) : _PyObject_GC_New(&(root_type))));
+
+
+/* BaseMathObject.flag */
+enum {
+ BASE_MATH_FLAG_IS_WRAP = (1 << 0),
+ BASE_MATH_FLAG_IS_FROZEN = (1 << 1),
+};
+#define BASE_MATH_FLAG_DEFAULT 0
+
#define BASE_MATH_MEMBERS(_data) \
PyObject_VAR_HEAD \
float *_data; /* array of data (alias), wrapped status depends on wrapped status */ \
@@ -42,7 +56,7 @@ extern char BaseMathObject_owner_doc[];
unsigned char cb_type; /* which user funcs do we adhere to, RNA, GameObject, etc */ \
unsigned char cb_subtype; /* subtype: location, rotation... \
* to avoid defining many new functions for every attribute of the same type */ \
- unsigned char wrapped /* wrapped data type? */ \
+ unsigned char flag /* wrapped data type? */ \
typedef struct {
BASE_MATH_MEMBERS(data);
@@ -57,6 +71,10 @@ typedef struct {
PyObject *BaseMathObject_owner_get(BaseMathObject *self, void *);
PyObject *BaseMathObject_is_wrapped_get(BaseMathObject *self, void *);
+PyObject *BaseMathObject_is_frozen_get(BaseMathObject *self, void *);
+
+extern char BaseMathObject_freeze_doc[];
+PyObject *BaseMathObject_freeze(BaseMathObject *self);
int BaseMathObject_traverse(BaseMathObject *self, visitproc visit, void *arg);
int BaseMathObject_clear(BaseMathObject *self);
@@ -67,9 +85,6 @@ PyMODINIT_FUNC PyInit_mathutils(void);
int EXPP_FloatsAreEqual(float A, float B, int floatSteps);
int EXPP_VectorsAreEqual(const float *vecA, const float *vecB, int size, int floatSteps);
-#define Py_NEW 1
-#define Py_WRAP 2
-
typedef struct Mathutils_Callback Mathutils_Callback;
typedef int (*BaseMathCheckFunc)(BaseMathObject *); /* checks the user is still valid */
@@ -93,15 +108,35 @@ int _BaseMathObject_WriteCallback(BaseMathObject *self);
int _BaseMathObject_ReadIndexCallback(BaseMathObject *self, int index);
int _BaseMathObject_WriteIndexCallback(BaseMathObject *self, int index);
+void _BaseMathObject_RaiseFrozenExc(const BaseMathObject *self);
+void _BaseMathObject_RaiseNotFrozenExc(const BaseMathObject *self);
+
/* since this is called so often avoid where possible */
#define BaseMath_ReadCallback(_self) \
- (((_self)->cb_user ? _BaseMathObject_ReadCallback((BaseMathObject *)_self):0))
+ (((_self)->cb_user ? _BaseMathObject_ReadCallback((BaseMathObject *)_self) : 0))
#define BaseMath_WriteCallback(_self) \
- (((_self)->cb_user ?_BaseMathObject_WriteCallback((BaseMathObject *)_self):0))
+ (((_self)->cb_user ?_BaseMathObject_WriteCallback((BaseMathObject *)_self) : 0))
#define BaseMath_ReadIndexCallback(_self, _index) \
- (((_self)->cb_user ? _BaseMathObject_ReadIndexCallback((BaseMathObject *)_self, _index):0))
+ (((_self)->cb_user ? _BaseMathObject_ReadIndexCallback((BaseMathObject *)_self, _index) : 0))
#define BaseMath_WriteIndexCallback(_self, _index) \
- (((_self)->cb_user ? _BaseMathObject_WriteIndexCallback((BaseMathObject *)_self, _index):0))
+ (((_self)->cb_user ? _BaseMathObject_WriteIndexCallback((BaseMathObject *)_self, _index) : 0))
+
+/* support BASE_MATH_FLAG_IS_FROZEN */
+#define BaseMath_ReadCallback_ForWrite(_self) \
+ (UNLIKELY((_self)->flag & BASE_MATH_FLAG_IS_FROZEN) ? \
+ (_BaseMathObject_RaiseFrozenExc((BaseMathObject *)_self), -1) : (BaseMath_ReadCallback(_self)))
+
+#define BaseMath_ReadIndexCallback_ForWrite(_self, _index) \
+ (UNLIKELY((_self)->flag & BASE_MATH_FLAG_IS_FROZEN) ? \
+ (_BaseMathObject_RaiseFrozenExc((BaseMathObject *)_self), -1) : (BaseMath_ReadIndexCallback(_self, _index)))
+
+#define BaseMath_Prepare_ForWrite(_self) \
+ (UNLIKELY((_self)->flag & BASE_MATH_FLAG_IS_FROZEN) ? \
+ (_BaseMathObject_RaiseFrozenExc((BaseMathObject *)_self), -1) : 0)
+
+#define BaseMathObject_Prepare_ForHash(_self) \
+ (UNLIKELY(((_self)->flag & BASE_MATH_FLAG_IS_FROZEN) == 0) ? \
+ (_BaseMathObject_RaiseNotFrozenExc((BaseMathObject *)_self), -1) : 0)
/* utility func */
int mathutils_array_parse(float *array, int array_min, int array_max, PyObject *value, const char *error_prefix);
@@ -109,6 +144,16 @@ int mathutils_array_parse_alloc(float **array, int array_min, PyObject *value, c
int mathutils_array_parse_alloc_v(float **array, int array_dim, PyObject *value, const char *error_prefix);
int mathutils_any_to_rotmat(float rmat[3][3], PyObject *value, const char *error_prefix);
+Py_hash_t mathutils_array_hash(const float *float_array, size_t array_len);
+
+/* zero remaining unused elements of the array */
+#define MU_ARRAY_ZERO (1u << 30)
+/* ignore larger py sequences than requested (just use first elements),
+ * handy when using 3d vectors as 2d */
+#define MU_ARRAY_SPILL (1u << 31)
+
+#define MU_ARRAY_FLAGS (MU_ARRAY_ZERO | MU_ARRAY_SPILL)
+
int column_vector_multiplication(float rvec[4], VectorObject *vec, MatrixObject *mat);
#ifndef MATH_STANDALONE
diff --git a/source/blender/python/mathutils/mathutils_Color.c b/source/blender/python/mathutils/mathutils_Color.c
index aee2b9e9711..add8c2451ff 100644
--- a/source/blender/python/mathutils/mathutils_Color.c
+++ b/source/blender/python/mathutils/mathutils_Color.c
@@ -32,6 +32,8 @@
#include "BLI_math.h"
#include "BLI_utildefines.h"
+#include "../generic/python_utildefines.h"
+
#ifndef MATH_STANDALONE
# include "BLI_dynstr.h"
#endif
@@ -64,7 +66,7 @@ static PyObject *Color_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
"more than a single arg given");
return NULL;
}
- return Color_CreatePyObject(col, Py_NEW, type);
+ return Color_CreatePyObject(col, type);
}
/* -----------------------------METHODS---------------------------- */
@@ -107,7 +109,7 @@ static PyObject *Color_copy(ColorObject *self)
if (BaseMath_ReadCallback(self) == -1)
return NULL;
- return Color_CreatePyObject(self->col, Py_NEW, Py_TYPE(self));
+ return Color_CreatePyObject(self->col, Py_TYPE(self));
}
static PyObject *Color_deepcopy(ColorObject *self, PyObject *args)
{
@@ -187,7 +189,18 @@ static PyObject *Color_richcmpr(PyObject *a, PyObject *b, int op)
return NULL;
}
- return Py_INCREF(res), res;
+ return Py_INCREF_RET(res);
+}
+
+static Py_hash_t Color_hash(ColorObject *self)
+{
+ if (BaseMath_ReadCallback(self) == -1)
+ return -1;
+
+ if (BaseMathObject_Prepare_ForHash(self) == -1)
+ return -1;
+
+ return mathutils_array_hash(self->col, COLOR_SIZE);
}
/* ---------------------SEQUENCE PROTOCOLS------------------------ */
@@ -220,8 +233,12 @@ static PyObject *Color_item(ColorObject *self, int i)
/* sequence accessor (set) */
static int Color_ass_item(ColorObject *self, int i, PyObject *value)
{
- float f = PyFloat_AsDouble(value);
+ float f;
+
+ if (BaseMath_Prepare_ForWrite(self) == -1)
+ return -1;
+ f = PyFloat_AsDouble(value);
if (f == -1 && PyErr_Occurred()) { /* parsed item not a number */
PyErr_SetString(PyExc_TypeError,
"color[item] = x: "
@@ -273,7 +290,7 @@ static int Color_ass_slice(ColorObject *self, int begin, int end, PyObject *seq)
int i, size;
float col[COLOR_SIZE];
- if (BaseMath_ReadCallback(self) == -1)
+ if (BaseMath_ReadCallback_ForWrite(self) == -1)
return -1;
CLAMP(begin, 0, COLOR_SIZE);
@@ -411,7 +428,7 @@ static PyObject *Color_add(PyObject *v1, PyObject *v2)
add_vn_vnvn(col, color1->col, color2->col, COLOR_SIZE);
- return Color_CreatePyObject(col, Py_NEW, Py_TYPE(v1));
+ return Color_CreatePyObject(col, Py_TYPE(v1));
}
/* addition in-place: obj += obj */
@@ -429,7 +446,7 @@ static PyObject *Color_iadd(PyObject *v1, PyObject *v2)
color1 = (ColorObject *)v1;
color2 = (ColorObject *)v2;
- if (BaseMath_ReadCallback(color1) == -1 || BaseMath_ReadCallback(color2) == -1)
+ if (BaseMath_ReadCallback_ForWrite(color1) == -1 || BaseMath_ReadCallback(color2) == -1)
return NULL;
add_vn_vn(color1->col, color2->col, COLOR_SIZE);
@@ -460,7 +477,7 @@ static PyObject *Color_sub(PyObject *v1, PyObject *v2)
sub_vn_vnvn(col, color1->col, color2->col, COLOR_SIZE);
- return Color_CreatePyObject(col, Py_NEW, Py_TYPE(v1));
+ return Color_CreatePyObject(col, Py_TYPE(v1));
}
/* subtraction in-place: obj -= obj */
@@ -478,7 +495,7 @@ static PyObject *Color_isub(PyObject *v1, PyObject *v2)
color1 = (ColorObject *)v1;
color2 = (ColorObject *)v2;
- if (BaseMath_ReadCallback(color1) == -1 || BaseMath_ReadCallback(color2) == -1)
+ if (BaseMath_ReadCallback_ForWrite(color1) == -1 || BaseMath_ReadCallback(color2) == -1)
return NULL;
sub_vn_vn(color1->col, color2->col, COLOR_SIZE);
@@ -492,7 +509,7 @@ static PyObject *color_mul_float(ColorObject *color, const float scalar)
{
float tcol[COLOR_SIZE];
mul_vn_vn_fl(tcol, color->col, COLOR_SIZE, scalar);
- return Color_CreatePyObject(tcol, Py_NEW, Py_TYPE(color));
+ return Color_CreatePyObject(tcol, Py_TYPE(color));
}
@@ -577,7 +594,7 @@ static PyObject *Color_imul(PyObject *v1, PyObject *v2)
ColorObject *color = (ColorObject *)v1;
float scalar;
- if (BaseMath_ReadCallback(color) == -1)
+ if (BaseMath_ReadCallback_ForWrite(color) == -1)
return NULL;
/* only support color *= float */
@@ -603,7 +620,7 @@ static PyObject *Color_idiv(PyObject *v1, PyObject *v2)
ColorObject *color = (ColorObject *)v1;
float scalar;
- if (BaseMath_ReadCallback(color) == -1)
+ if (BaseMath_ReadCallback_ForWrite(color) == -1)
return NULL;
/* only support color /= float */
@@ -639,7 +656,7 @@ static PyObject *Color_neg(ColorObject *self)
return NULL;
negate_vn_vn(tcol, self->col, COLOR_SIZE);
- return Color_CreatePyObject(tcol, Py_NEW, Py_TYPE(self));
+ return Color_CreatePyObject(tcol, Py_TYPE(self));
}
@@ -726,7 +743,7 @@ static int Color_channel_hsv_set(ColorObject *self, PyObject *value, void *type)
return -1;
}
- if (BaseMath_ReadCallback(self) == -1)
+ if (BaseMath_ReadCallback_ForWrite(self) == -1)
return -1;
rgb_to_hsv_v(self->col, hsv);
@@ -753,9 +770,10 @@ static PyObject *Color_hsv_get(ColorObject *self, void *UNUSED(closure))
rgb_to_hsv(self->col[0], self->col[1], self->col[2], &(hsv[0]), &(hsv[1]), &(hsv[2]));
ret = PyTuple_New(3);
- PyTuple_SET_ITEM(ret, 0, PyFloat_FromDouble(hsv[0]));
- PyTuple_SET_ITEM(ret, 1, PyFloat_FromDouble(hsv[1]));
- PyTuple_SET_ITEM(ret, 2, PyFloat_FromDouble(hsv[2]));
+ PyTuple_SET_ITEMS(ret,
+ PyFloat_FromDouble(hsv[0]),
+ PyFloat_FromDouble(hsv[1]),
+ PyFloat_FromDouble(hsv[2]));
return ret;
}
@@ -766,6 +784,9 @@ static int Color_hsv_set(ColorObject *self, PyObject *value, void *UNUSED(closur
if (mathutils_array_parse(hsv, 3, 3, value, "mathutils.Color.hsv = value") == -1)
return -1;
+ if (BaseMath_Prepare_ForWrite(self) == -1)
+ return -1;
+
CLAMP(hsv[0], 0.0f, 1.0f);
CLAMP(hsv[1], 0.0f, 1.0f);
CLAMP(hsv[2], 0.0f, 1.0f);
@@ -793,6 +814,7 @@ static PyGetSetDef Color_getseters[] = {
{(char *)"hsv", (getter)Color_hsv_get, (setter)Color_hsv_set, (char *)Color_hsv_doc, (void *)0},
{(char *)"is_wrapped", (getter)BaseMathObject_is_wrapped_get, (setter)NULL, BaseMathObject_is_wrapped_doc, NULL},
+ {(char *)"is_frozen", (getter)BaseMathObject_is_frozen_get, (setter)NULL, BaseMathObject_is_frozen_doc, NULL},
{(char *)"owner", (getter)BaseMathObject_owner_get, (setter)NULL, BaseMathObject_owner_doc, NULL},
{NULL, NULL, NULL, NULL, NULL} /* Sentinel */
};
@@ -803,12 +825,20 @@ static struct PyMethodDef Color_methods[] = {
{"copy", (PyCFunction) Color_copy, METH_NOARGS, Color_copy_doc},
{"__copy__", (PyCFunction) Color_copy, METH_NOARGS, Color_copy_doc},
{"__deepcopy__", (PyCFunction) Color_deepcopy, METH_VARARGS, Color_copy_doc},
+
+ /* base-math methods */
+ {"freeze", (PyCFunction)BaseMathObject_freeze, METH_NOARGS, BaseMathObject_freeze_doc},
{NULL, NULL, 0, NULL}
};
/* ------------------PY_OBECT DEFINITION-------------------------- */
PyDoc_STRVAR(color_doc,
-"This object gives access to Colors in Blender."
+".. class:: Color(rgb)\n"
+"\n"
+" This object gives access to Colors in Blender.\n"
+"\n"
+" :param rgb: (r, g, b) color values\n"
+" :type rgb: 3d vector\n"
);
PyTypeObject color_Type = {
PyVarObject_HEAD_INIT(NULL, 0)
@@ -824,7 +854,7 @@ PyTypeObject color_Type = {
&Color_NumMethods, /* tp_as_number */
&Color_SeqMethods, /* tp_as_sequence */
&Color_AsMapping, /* tp_as_mapping */
- NULL, /* tp_hash */
+ (hashfunc)Color_hash, /* tp_hash */
NULL, /* tp_call */
#ifndef MATH_STANDALONE
(reprfunc) Color_str, /* tp_str */
@@ -862,40 +892,60 @@ PyTypeObject color_Type = {
NULL, /* tp_weaklist */
NULL /* tp_del */
};
-/* ------------------------Color_CreatePyObject (internal)------------- */
-/* creates a new color object */
-/* pass Py_WRAP - if vector is a WRAPPER for data allocated by BLENDER
- * (i.e. it was allocated elsewhere by MEM_mallocN())
- * pass Py_NEW - if vector is not a WRAPPER and managed by PYTHON
- * (i.e. it must be created here with PyMEM_malloc())*/
-PyObject *Color_CreatePyObject(float col[3], int type, PyTypeObject *base_type)
+
+PyObject *Color_CreatePyObject(
+ const float col[3],
+ PyTypeObject *base_type)
{
ColorObject *self;
+ float *col_alloc;
- self = base_type ? (ColorObject *)base_type->tp_alloc(base_type, 0) :
- (ColorObject *)PyObject_GC_New(ColorObject, &color_Type);
+ col_alloc = PyMem_Malloc(COLOR_SIZE * sizeof(float));
+ if (UNLIKELY(col_alloc == NULL)) {
+ PyErr_SetString(PyExc_MemoryError,
+ "Color(): "
+ "problem allocating data");
+ return NULL;
+ }
+ self = BASE_MATH_NEW(ColorObject, color_Type, base_type);
if (self) {
+ self->col = col_alloc;
+
/* init callbacks as NULL */
self->cb_user = NULL;
self->cb_type = self->cb_subtype = 0;
- if (type == Py_WRAP) {
- self->col = col;
- self->wrapped = Py_WRAP;
- }
- else if (type == Py_NEW) {
- self->col = PyMem_Malloc(COLOR_SIZE * sizeof(float));
- if (col)
- copy_v3_v3(self->col, col);
- else
- zero_v3(self->col);
-
- self->wrapped = Py_NEW;
- }
- else {
- Py_FatalError("Color(): invalid type!");
- }
+ /* NEW */
+ if (col)
+ copy_v3_v3(self->col, col);
+ else
+ zero_v3(self->col);
+
+ self->flag = BASE_MATH_FLAG_DEFAULT;
+ }
+ else {
+ PyMem_Free(col_alloc);
+ }
+
+ return (PyObject *)self;
+}
+
+PyObject *Color_CreatePyObject_wrap(
+ float col[3],
+ PyTypeObject *base_type)
+{
+ ColorObject *self;
+
+ self = BASE_MATH_NEW(ColorObject, color_Type, base_type);
+ if (self) {
+ /* init callbacks as NULL */
+ self->cb_user = NULL;
+ self->cb_type = self->cb_subtype = 0;
+
+ /* WRAP */
+ self->col = col;
+ self->flag = BASE_MATH_FLAG_DEFAULT | BASE_MATH_FLAG_IS_WRAP;
}
return (PyObject *)self;
@@ -904,7 +954,7 @@ PyObject *Color_CreatePyObject(float col[3], int type, PyTypeObject *base_type)
PyObject *Color_CreatePyObject_cb(PyObject *cb_user,
unsigned char cb_type, unsigned char cb_subtype)
{
- ColorObject *self = (ColorObject *)Color_CreatePyObject(NULL, Py_NEW, NULL);
+ ColorObject *self = (ColorObject *)Color_CreatePyObject(NULL, NULL);
if (self) {
Py_INCREF(cb_user);
self->cb_user = cb_user;
diff --git a/source/blender/python/mathutils/mathutils_Color.h b/source/blender/python/mathutils/mathutils_Color.h
index 193d30a2b6f..1290f73da62 100644
--- a/source/blender/python/mathutils/mathutils_Color.h
+++ b/source/blender/python/mathutils/mathutils_Color.h
@@ -42,8 +42,17 @@ typedef struct {
* blender (stored in blend_data). This is an either/or struct not both*/
/* prototypes */
-PyObject *Color_CreatePyObject(float col[3], int type, PyTypeObject *base_type);
-PyObject *Color_CreatePyObject_cb(PyObject *cb_user,
- unsigned char cb_type, unsigned char cb_subtype);
+PyObject *Color_CreatePyObject(
+ const float col[3],
+ PyTypeObject *base_type
+ ) ATTR_WARN_UNUSED_RESULT;
+PyObject *Color_CreatePyObject_wrap(
+ float col[3],
+ PyTypeObject *base_type
+ ) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1);
+PyObject *Color_CreatePyObject_cb(
+ PyObject *cb_user,
+ unsigned char cb_type, unsigned char cb_subtype
+ ) ATTR_WARN_UNUSED_RESULT;
#endif /* __MATHUTILS_COLOR_H__ */
diff --git a/source/blender/python/mathutils/mathutils_Euler.c b/source/blender/python/mathutils/mathutils_Euler.c
index f6d124938a4..54adc826af7 100644
--- a/source/blender/python/mathutils/mathutils_Euler.c
+++ b/source/blender/python/mathutils/mathutils_Euler.c
@@ -31,6 +31,7 @@
#include "BLI_math.h"
#include "BLI_utildefines.h"
+#include "../generic/python_utildefines.h"
#ifndef MATH_STANDALONE
# include "BLI_dynstr.h"
@@ -70,7 +71,7 @@ static PyObject *Euler_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
return NULL;
break;
}
- return Euler_CreatePyObject(eul, order, Py_NEW, type);
+ return Euler_CreatePyObject(eul, order, type);
}
/* internal use, assume read callback is done */
@@ -150,7 +151,7 @@ static PyObject *Euler_to_quaternion(EulerObject *self)
eulO_to_quat(quat, self->eul, self->order);
- return Quaternion_CreatePyObject(quat, Py_NEW, NULL);
+ return Quaternion_CreatePyObject(quat, NULL);
}
/* return a matrix representation of the euler */
@@ -171,7 +172,7 @@ static PyObject *Euler_to_matrix(EulerObject *self)
eulO_to_mat3((float (*)[3])mat, self->eul, self->order);
- return Matrix_CreatePyObject(mat, 3, 3, Py_NEW, NULL);
+ return Matrix_CreatePyObject(mat, 3, 3, NULL);
}
PyDoc_STRVAR(Euler_zero_doc,
@@ -181,6 +182,9 @@ PyDoc_STRVAR(Euler_zero_doc,
);
static PyObject *Euler_zero(EulerObject *self)
{
+ if (BaseMath_Prepare_ForWrite(self) == -1)
+ return NULL;
+
zero_v3(self->eul);
if (BaseMath_WriteCallback(self) == -1)
@@ -219,7 +223,7 @@ static PyObject *Euler_rotate_axis(EulerObject *self, PyObject *args)
return NULL;
}
- if (BaseMath_ReadCallback(self) == -1)
+ if (BaseMath_ReadCallback_ForWrite(self) == -1)
return NULL;
@@ -233,7 +237,7 @@ static PyObject *Euler_rotate_axis(EulerObject *self, PyObject *args)
PyDoc_STRVAR(Euler_rotate_doc,
".. method:: rotate(other)\n"
"\n"
-" Rotates the euler a by another mathutils value.\n"
+" Rotates the euler by another mathutils value.\n"
"\n"
" :arg other: rotation component of mathutils value\n"
" :type other: :class:`Euler`, :class:`Quaternion` or :class:`Matrix`\n"
@@ -242,7 +246,7 @@ static PyObject *Euler_rotate(EulerObject *self, PyObject *value)
{
float self_rmat[3][3], other_rmat[3][3], rmat[3][3];
- if (BaseMath_ReadCallback(self) == -1)
+ if (BaseMath_ReadCallback_ForWrite(self) == -1)
return NULL;
if (mathutils_any_to_rotmat(other_rmat, value, "euler.rotate(value)") == -1)
@@ -269,7 +273,7 @@ static PyObject *Euler_make_compatible(EulerObject *self, PyObject *value)
{
float teul[EULER_SIZE];
- if (BaseMath_ReadCallback(self) == -1)
+ if (BaseMath_ReadCallback_ForWrite(self) == -1)
return NULL;
if (mathutils_array_parse(teul, EULER_SIZE, EULER_SIZE, value,
@@ -304,7 +308,7 @@ static PyObject *Euler_copy(EulerObject *self)
if (BaseMath_ReadCallback(self) == -1)
return NULL;
- return Euler_CreatePyObject(self->eul, self->order, Py_NEW, Py_TYPE(self));
+ return Euler_CreatePyObject(self->eul, self->order, Py_TYPE(self));
}
static PyObject *Euler_deepcopy(EulerObject *self, PyObject *args)
{
@@ -382,7 +386,18 @@ static PyObject *Euler_richcmpr(PyObject *a, PyObject *b, int op)
return NULL;
}
- return Py_INCREF(res), res;
+ return Py_INCREF_RET(res);
+}
+
+static Py_hash_t Euler_hash(EulerObject *self)
+{
+ if (BaseMath_ReadCallback(self) == -1)
+ return -1;
+
+ if (BaseMathObject_Prepare_ForHash(self) == -1)
+ return -1;
+
+ return mathutils_array_hash(self->eul, EULER_SIZE);
}
/* ---------------------SEQUENCE PROTOCOLS------------------------ */
@@ -415,8 +430,12 @@ static PyObject *Euler_item(EulerObject *self, int i)
/* sequence accessor (set) */
static int Euler_ass_item(EulerObject *self, int i, PyObject *value)
{
- float f = PyFloat_AsDouble(value);
+ float f;
+
+ if (BaseMath_Prepare_ForWrite(self) == -1)
+ return -1;
+ f = PyFloat_AsDouble(value);
if (f == -1 && PyErr_Occurred()) { /* parsed item not a number */
PyErr_SetString(PyExc_TypeError,
"euler[attribute] = x: "
@@ -469,7 +488,7 @@ static int Euler_ass_slice(EulerObject *self, int begin, int end, PyObject *seq)
int i, size;
float eul[EULER_SIZE];
- if (BaseMath_ReadCallback(self) == -1)
+ if (BaseMath_ReadCallback_ForWrite(self) == -1)
return -1;
CLAMP(begin, 0, EULER_SIZE);
@@ -614,12 +633,18 @@ static PyObject *Euler_order_get(EulerObject *self, void *UNUSED(closure))
static int Euler_order_set(EulerObject *self, PyObject *value, void *UNUSED(closure))
{
- const char *order_str = _PyUnicode_AsString(value);
- short order = euler_order_from_string(order_str, "euler.order");
+ const char *order_str;
+ short order;
- if (order == -1)
+ if (BaseMath_Prepare_ForWrite(self) == -1)
return -1;
+ if (((order_str = _PyUnicode_AsString(value)) == NULL) ||
+ ((order = euler_order_from_string(order_str, "euler.order")) == -1))
+ {
+ return -1;
+ }
+
self->order = order;
(void)BaseMath_WriteCallback(self); /* order can be written back */
return 0;
@@ -635,6 +660,7 @@ static PyGetSetDef Euler_getseters[] = {
{(char *)"order", (getter)Euler_order_get, (setter)Euler_order_set, Euler_order_doc, (void *)NULL},
{(char *)"is_wrapped", (getter)BaseMathObject_is_wrapped_get, (setter)NULL, BaseMathObject_is_wrapped_doc, NULL},
+ {(char *)"is_frozen", (getter)BaseMathObject_is_frozen_get, (setter)NULL, BaseMathObject_is_frozen_doc, NULL},
{(char *)"owner", (getter)BaseMathObject_owner_get, (setter)NULL, BaseMathObject_owner_doc, NULL},
{NULL, NULL, NULL, NULL, NULL} /* Sentinel */
};
@@ -651,12 +677,22 @@ static struct PyMethodDef Euler_methods[] = {
{"copy", (PyCFunction) Euler_copy, METH_NOARGS, Euler_copy_doc},
{"__copy__", (PyCFunction) Euler_copy, METH_NOARGS, Euler_copy_doc},
{"__deepcopy__", (PyCFunction) Euler_deepcopy, METH_VARARGS, Euler_copy_doc},
+
+ /* base-math methods */
+ {"freeze", (PyCFunction)BaseMathObject_freeze, METH_NOARGS, BaseMathObject_freeze_doc},
{NULL, NULL, 0, NULL}
};
/* ------------------PY_OBECT DEFINITION-------------------------- */
PyDoc_STRVAR(euler_doc,
-"This object gives access to Eulers in Blender."
+".. class:: Euler(angles, order='XYZ')\n"
+"\n"
+" This object gives access to Eulers in Blender.\n"
+"\n"
+" :param angles: Three angles, in radians.\n"
+" :type angles: 3d vector\n"
+" :param order: Optional order of the angles, a permutation of ``XYZ``.\n"
+" :type order: str\n"
);
PyTypeObject euler_Type = {
PyVarObject_HEAD_INIT(NULL, 0)
@@ -672,7 +708,7 @@ PyTypeObject euler_Type = {
NULL, /* tp_as_number */
&Euler_SeqMethods, /* tp_as_sequence */
&Euler_AsMapping, /* tp_as_mapping */
- NULL, /* tp_hash */
+ (hashfunc)Euler_hash, /* tp_hash */
NULL, /* tp_call */
#ifndef MATH_STANDALONE
(reprfunc) Euler_str, /* tp_str */
@@ -710,53 +746,74 @@ PyTypeObject euler_Type = {
NULL, /* tp_weaklist */
NULL /* tp_del */
};
-/* ------------------------Euler_CreatePyObject (internal)------------- */
-/* creates a new euler object */
-/* pass Py_WRAP - if vector is a WRAPPER for data allocated by BLENDER
- * (i.e. it was allocated elsewhere by MEM_mallocN())
- * pass Py_NEW - if vector is not a WRAPPER and managed by PYTHON
- * (i.e. it must be created here with PyMEM_malloc())*/
-PyObject *Euler_CreatePyObject(float eul[3], const short order, int type, PyTypeObject *base_type)
+
+
+PyObject *Euler_CreatePyObject(
+ const float eul[3], const short order,
+ PyTypeObject *base_type)
{
EulerObject *self;
+ float *eul_alloc;
- self = base_type ? (EulerObject *)base_type->tp_alloc(base_type, 0) :
- (EulerObject *)PyObject_GC_New(EulerObject, &euler_Type);
+ eul_alloc = PyMem_Malloc(EULER_SIZE * sizeof(float));
+ if (UNLIKELY(eul_alloc == NULL)) {
+ PyErr_SetString(PyExc_MemoryError,
+ "Euler(): "
+ "problem allocating data");
+ return NULL;
+ }
+ self = BASE_MATH_NEW(EulerObject, euler_Type, base_type);
if (self) {
+ self->eul = eul_alloc;
+
/* init callbacks as NULL */
self->cb_user = NULL;
self->cb_type = self->cb_subtype = 0;
- if (type == Py_WRAP) {
- self->eul = eul;
- self->wrapped = Py_WRAP;
- }
- else if (type == Py_NEW) {
- self->eul = PyMem_Malloc(EULER_SIZE * sizeof(float));
- if (eul) {
- copy_v3_v3(self->eul, eul);
- }
- else {
- zero_v3(self->eul);
- }
-
- self->wrapped = Py_NEW;
+ if (eul) {
+ copy_v3_v3(self->eul, eul);
}
else {
- Py_FatalError("Euler(): invalid type!");
+ zero_v3(self->eul);
}
+ self->flag = BASE_MATH_FLAG_DEFAULT;
+ self->order = order;
+ }
+ else {
+ PyMem_Free(eul_alloc);
+ }
+
+ return (PyObject *)self;
+}
+
+PyObject *Euler_CreatePyObject_wrap(
+ float eul[3], const short order,
+ PyTypeObject *base_type)
+{
+ EulerObject *self;
+
+ self = BASE_MATH_NEW(EulerObject, euler_Type, base_type);
+ if (self) {
+ /* init callbacks as NULL */
+ self->cb_user = NULL;
+ self->cb_type = self->cb_subtype = 0;
+
+ self->eul = eul;
+ self->flag = BASE_MATH_FLAG_DEFAULT | BASE_MATH_FLAG_IS_WRAP;
+
self->order = order;
}
return (PyObject *)self;
}
-PyObject *Euler_CreatePyObject_cb(PyObject *cb_user, const short order,
- unsigned char cb_type, unsigned char cb_subtype)
+PyObject *Euler_CreatePyObject_cb(
+ PyObject *cb_user, const short order,
+ unsigned char cb_type, unsigned char cb_subtype)
{
- EulerObject *self = (EulerObject *)Euler_CreatePyObject(NULL, order, Py_NEW, NULL);
+ EulerObject *self = (EulerObject *)Euler_CreatePyObject(NULL, order, NULL);
if (self) {
Py_INCREF(cb_user);
self->cb_user = cb_user;
diff --git a/source/blender/python/mathutils/mathutils_Euler.h b/source/blender/python/mathutils/mathutils_Euler.h
index 62fb83ef234..744f39faed1 100644
--- a/source/blender/python/mathutils/mathutils_Euler.h
+++ b/source/blender/python/mathutils/mathutils_Euler.h
@@ -43,9 +43,18 @@ typedef struct {
* blender (stored in blend_data). This is an either/or struct not both */
/* prototypes */
-PyObject *Euler_CreatePyObject(float eul[3], const short order, int type, PyTypeObject *base_type);
-PyObject *Euler_CreatePyObject_cb(PyObject *cb_user, const short order,
- unsigned char cb_type, unsigned char cb_subtype);
+PyObject *Euler_CreatePyObject(
+ const float eul[3], const short order,
+ PyTypeObject *base_type
+ ) ATTR_WARN_UNUSED_RESULT;
+PyObject *Euler_CreatePyObject_wrap(
+ float eul[3], const short order,
+ PyTypeObject *base_type
+ ) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1);
+PyObject *Euler_CreatePyObject_cb(
+ PyObject *cb_user, const short order,
+ unsigned char cb_type, unsigned char cb_subtype
+ ) ATTR_WARN_UNUSED_RESULT;
short euler_order_from_string(const char *str, const char *error_prefix);
diff --git a/source/blender/python/mathutils/mathutils_Matrix.c b/source/blender/python/mathutils/mathutils_Matrix.c
index 282f29b4934..41baa9b089f 100644
--- a/source/blender/python/mathutils/mathutils_Matrix.c
+++ b/source/blender/python/mathutils/mathutils_Matrix.c
@@ -32,6 +32,8 @@
#include "BLI_math.h"
#include "BLI_utildefines.h"
+#include "../generic/python_utildefines.h"
+
#ifndef MATH_STANDALONE
# include "BLI_string.h"
# include "BLI_dynstr.h"
@@ -109,7 +111,7 @@ static int mathutils_matrix_row_set(BaseMathObject *bmo, int row)
MatrixObject *self = (MatrixObject *)bmo->cb_user;
int col;
- if (BaseMath_ReadCallback(self) == -1)
+ if (BaseMath_ReadCallback_ForWrite(self) == -1)
return -1;
if (!matrix_row_vector_check(self, (VectorObject *)bmo, row))
return -1;
@@ -139,7 +141,7 @@ static int mathutils_matrix_row_set_index(BaseMathObject *bmo, int row, int col)
{
MatrixObject *self = (MatrixObject *)bmo->cb_user;
- if (BaseMath_ReadCallback(self) == -1)
+ if (BaseMath_ReadCallback_ForWrite(self) == -1)
return -1;
if (!matrix_row_vector_check(self, (VectorObject *)bmo, row))
return -1;
@@ -198,7 +200,7 @@ static int mathutils_matrix_col_set(BaseMathObject *bmo, int col)
int num_row;
int row;
- if (BaseMath_ReadCallback(self) == -1)
+ if (BaseMath_ReadCallback_ForWrite(self) == -1)
return -1;
if (!matrix_col_vector_check(self, (VectorObject *)bmo, col))
return -1;
@@ -231,7 +233,7 @@ static int mathutils_matrix_col_set_index(BaseMathObject *bmo, int col, int row)
{
MatrixObject *self = (MatrixObject *)bmo->cb_user;
- if (BaseMath_ReadCallback(self) == -1)
+ if (BaseMath_ReadCallback_ForWrite(self) == -1)
return -1;
if (!matrix_col_vector_check(self, (VectorObject *)bmo, col))
return -1;
@@ -284,7 +286,7 @@ static int mathutils_matrix_translation_set(BaseMathObject *bmo, int col)
MatrixObject *self = (MatrixObject *)bmo->cb_user;
int row;
- if (BaseMath_ReadCallback(self) == -1)
+ if (BaseMath_ReadCallback_ForWrite(self) == -1)
return -1;
for (row = 0; row < 3; row++) {
@@ -310,7 +312,7 @@ static int mathutils_matrix_translation_set_index(BaseMathObject *bmo, int col,
{
MatrixObject *self = (MatrixObject *)bmo->cb_user;
- if (BaseMath_ReadCallback(self) == -1)
+ if (BaseMath_ReadCallback_ForWrite(self) == -1)
return -1;
MATRIX_ITEM(self, row, col) = bmo->data[row];
@@ -344,7 +346,7 @@ static PyObject *Matrix_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
switch (PyTuple_GET_SIZE(args)) {
case 0:
- return Matrix_CreatePyObject(NULL, 4, 4, Py_NEW, type);
+ return Matrix_CreatePyObject(NULL, 4, 4, type);
case 1:
{
PyObject *arg = PyTuple_GET_ITEM(args, 0);
@@ -363,7 +365,7 @@ static PyObject *Matrix_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
if (num_col >= 2 && num_col <= 4) {
/* sane row & col size, new matrix and assign as slice */
- PyObject *matrix = Matrix_CreatePyObject(NULL, num_col, num_row, Py_NEW, type);
+ PyObject *matrix = Matrix_CreatePyObject(NULL, num_col, num_row, type);
if (Matrix_ass_slice((MatrixObject *)matrix, 0, INT_MAX, arg) == 0) {
return matrix;
}
@@ -444,7 +446,7 @@ static PyObject *C_Matrix_Identity(PyObject *cls, PyObject *args)
return NULL;
}
- return Matrix_CreatePyObject(NULL, matSize, matSize, Py_NEW, (PyTypeObject *)cls);
+ return Matrix_CreatePyObject(NULL, matSize, matSize, (PyTypeObject *)cls);
}
PyDoc_STRVAR(C_Matrix_Rotation_doc,
@@ -535,7 +537,7 @@ static PyObject *C_Matrix_Rotation(PyObject *cls, PyObject *args)
matrix_3x3_as_4x4(mat);
}
/* pass to matrix creation */
- return Matrix_CreatePyObject(mat, matSize, matSize, Py_NEW, (PyTypeObject *)cls);
+ return Matrix_CreatePyObject(mat, matSize, matSize, (PyTypeObject *)cls);
}
@@ -558,7 +560,7 @@ static PyObject *C_Matrix_Translation(PyObject *cls, PyObject *value)
if (mathutils_array_parse(mat[3], 3, 4, value, "mathutils.Matrix.Translation(vector), invalid vector arg") == -1)
return NULL;
- return Matrix_CreatePyObject(&mat[0][0], 4, 4, Py_NEW, (PyTypeObject *)cls);
+ return Matrix_CreatePyObject(&mat[0][0], 4, 4, (PyTypeObject *)cls);
}
/* ----------------------------------mathutils.Matrix.Scale() ------------- */
/* mat is a 1D array of floats - row[0][0], row[0][1], row[1][0], etc. */
@@ -650,7 +652,7 @@ static PyObject *C_Matrix_Scale(PyObject *cls, PyObject *args)
matrix_3x3_as_4x4(mat);
}
/* pass to matrix creation */
- return Matrix_CreatePyObject(mat, matSize, matSize, Py_NEW, (PyTypeObject *)cls);
+ return Matrix_CreatePyObject(mat, matSize, matSize, (PyTypeObject *)cls);
}
/* ----------------------------------mathutils.Matrix.OrthoProjection() --- */
/* mat is a 1D array of floats - row[0][0], row[0][1], row[1][0], etc. */
@@ -771,7 +773,7 @@ static PyObject *C_Matrix_OrthoProjection(PyObject *cls, PyObject *args)
matrix_3x3_as_4x4(mat);
}
/* pass to matrix creation */
- return Matrix_CreatePyObject(mat, matSize, matSize, Py_NEW, (PyTypeObject *)cls);
+ return Matrix_CreatePyObject(mat, matSize, matSize, (PyTypeObject *)cls);
}
PyDoc_STRVAR(C_Matrix_Shear_doc,
@@ -841,7 +843,7 @@ static PyObject *C_Matrix_Shear(PyObject *cls, PyObject *args)
/* 3 or 4, apply as 3x3, resize later if needed */
float factor[2];
- if (mathutils_array_parse(factor, 2, 2, fac, "Matrix.Shear()") < 0) {
+ if (mathutils_array_parse(factor, 2, 2, fac, "Matrix.Shear()") == -1) {
return NULL;
}
@@ -874,7 +876,7 @@ static PyObject *C_Matrix_Shear(PyObject *cls, PyObject *args)
matrix_3x3_as_4x4(mat);
}
/* pass to matrix creation */
- return Matrix_CreatePyObject(mat, matSize, matSize, Py_NEW, (PyTypeObject *)cls);
+ return Matrix_CreatePyObject(mat, matSize, matSize, (PyTypeObject *)cls);
}
void matrix_as_3x3(float mat[3][3], MatrixObject *self)
@@ -893,6 +895,19 @@ static void matrix_copy(MatrixObject *mat_dst, const MatrixObject *mat_src)
memcpy(mat_dst->matrix, mat_src->matrix, sizeof(float) * (mat_dst->num_col * mat_dst->num_row));
}
+/* transposes memory layout, rol/col's don't have to match */
+static void matrix_transpose_internal(float mat_dst_fl[], const MatrixObject *mat_src)
+{
+ unsigned short col, row;
+ unsigned int i = 0;
+
+ for (row = 0; row < mat_src->num_row; row++) {
+ for (col = 0; col < mat_src->num_col; col++) {
+ mat_dst_fl[i++] = MATRIX_ITEM(mat_src, row, col);
+ }
+ }
+}
+
/* assumes rowsize == colsize is checked and the read callback has run */
static float matrix_determinant_internal(const MatrixObject *self)
{
@@ -1078,7 +1093,7 @@ static PyObject *Matrix_to_quaternion(MatrixObject *self)
mat4_to_quat(quat, (float (*)[4])self->matrix);
}
- return Quaternion_CreatePyObject(quat, Py_NEW, NULL);
+ return Quaternion_CreatePyObject(quat, NULL);
}
/*---------------------------matrix.toEuler() --------------------*/
@@ -1152,7 +1167,7 @@ static PyObject *Matrix_to_euler(MatrixObject *self, PyObject *args)
else mat3_to_eulO(eul, order, mat);
}
- return Euler_CreatePyObject(eul, order, Py_NEW, NULL);
+ return Euler_CreatePyObject(eul, order, NULL);
}
PyDoc_STRVAR(Matrix_resize_4x4_doc,
@@ -1165,7 +1180,7 @@ static PyObject *Matrix_resize_4x4(MatrixObject *self)
float mat[4][4];
int col;
- if (self->wrapped == Py_WRAP) {
+ if (self->flag & BASE_MATH_FLAG_IS_WRAP) {
PyErr_SetString(PyExc_ValueError,
"Matrix.resize_4x4(): "
"cannot resize wrapped data - make a copy and resize that");
@@ -1214,12 +1229,12 @@ static PyObject *Matrix_to_4x4(MatrixObject *self)
return NULL;
if (self->num_row == 4 && self->num_col == 4) {
- return Matrix_CreatePyObject(self->matrix, 4, 4, Py_NEW, Py_TYPE(self));
+ return Matrix_CreatePyObject(self->matrix, 4, 4, Py_TYPE(self));
}
else if (self->num_row == 3 && self->num_col == 3) {
float mat[4][4];
copy_m4_m3(mat, (float (*)[3])self->matrix);
- return Matrix_CreatePyObject((float *)mat, 4, 4, Py_NEW, Py_TYPE(self));
+ return Matrix_CreatePyObject((float *)mat, 4, 4, Py_TYPE(self));
}
/* TODO, 2x2 matrix */
@@ -1252,15 +1267,15 @@ static PyObject *Matrix_to_3x3(MatrixObject *self)
matrix_as_3x3(mat, self);
- return Matrix_CreatePyObject((float *)mat, 3, 3, Py_NEW, Py_TYPE(self));
+ return Matrix_CreatePyObject((float *)mat, 3, 3, Py_TYPE(self));
}
PyDoc_STRVAR(Matrix_to_translation_doc,
".. method:: to_translation()\n"
"\n"
-" Return a the translation part of a 4 row matrix.\n"
+" Return the translation part of a 4 row matrix.\n"
"\n"
-" :return: Return a the translation of a matrix.\n"
+" :return: Return the translation of a matrix.\n"
" :rtype: :class:`Vector`\n"
);
static PyObject *Matrix_to_translation(MatrixObject *self)
@@ -1275,15 +1290,15 @@ static PyObject *Matrix_to_translation(MatrixObject *self)
return NULL;
}
- return Vector_CreatePyObject(MATRIX_COL_PTR(self, 3), 3, Py_NEW, NULL);
+ return Vector_CreatePyObject(MATRIX_COL_PTR(self, 3), 3, NULL);
}
PyDoc_STRVAR(Matrix_to_scale_doc,
".. method:: to_scale()\n"
"\n"
-" Return a the scale part of a 3x3 or 4x4 matrix.\n"
+" Return the scale part of a 3x3 or 4x4 matrix.\n"
"\n"
-" :return: Return a the scale of a matrix.\n"
+" :return: Return the scale of a matrix.\n"
" :rtype: :class:`Vector`\n"
"\n"
" .. note:: This method does not return negative a scale on any axis because it is not possible to obtain this data from the matrix alone.\n"
@@ -1310,7 +1325,7 @@ static PyObject *Matrix_to_scale(MatrixObject *self)
/* compatible mat4_to_loc_rot_size */
mat3_to_rot_size(rot, size, mat);
- return Vector_CreatePyObject(size, 3, Py_NEW, NULL);
+ return Vector_CreatePyObject(size, 3, NULL);
}
/*---------------------------matrix.invert() ---------------------*/
@@ -1383,7 +1398,7 @@ PyDoc_STRVAR(Matrix_invert_doc,
);
static PyObject *Matrix_invert(MatrixObject *self, PyObject *args)
{
- if (BaseMath_ReadCallback(self) == -1)
+ if (BaseMath_ReadCallback_ForWrite(self) == -1)
return NULL;
if (matrix_invert_is_compat(self) == false) {
@@ -1423,8 +1438,8 @@ PyDoc_STRVAR(Matrix_inverted_doc,
"\n"
" Return an inverted copy of the matrix.\n"
"\n"
-" :arg fallback: return this value when the inverse can't be calculated\n"
-" (instead of raising a :exc:`ValueError` exception).\n"
+" :arg fallback: return this when the inverse can't be calculated\n"
+" (instead of raising a :exc:`ValueError`).\n"
" :type fallback: any\n"
" :return: the inverted matrix or fallback when given.\n"
" :rtype: :class:`Matrix`\n"
@@ -1464,7 +1479,7 @@ static PyObject *Matrix_inverted(MatrixObject *self, PyObject *args)
static PyObject *Matrix_inverted_noargs(MatrixObject *self)
{
- if (BaseMath_ReadCallback(self) == -1)
+ if (BaseMath_ReadCallback_ForWrite(self) == -1)
return NULL;
if (matrix_invert_is_compat(self) == false) {
@@ -1494,7 +1509,7 @@ PyDoc_STRVAR(Matrix_invert_safe_doc,
);
static PyObject *Matrix_invert_safe(MatrixObject *self)
{
- if (BaseMath_ReadCallback(self) == -1)
+ if (BaseMath_ReadCallback_ForWrite(self) == -1)
return NULL;
if (matrix_invert_is_compat(self) == false) {
@@ -1545,7 +1560,7 @@ PyDoc_STRVAR(Matrix_adjugate_doc,
);
static PyObject *Matrix_adjugate(MatrixObject *self)
{
- if (BaseMath_ReadCallback(self) == -1)
+ if (BaseMath_ReadCallback_ForWrite(self) == -1)
return NULL;
if (self->num_col != self->num_row) {
@@ -1589,7 +1604,7 @@ static PyObject *Matrix_adjugated(MatrixObject *self)
PyDoc_STRVAR(Matrix_rotate_doc,
".. method:: rotate(other)\n"
"\n"
-" Rotates the matrix a by another mathutils value.\n"
+" Rotates the matrix by another mathutils value.\n"
"\n"
" :arg other: rotation component of mathutils value\n"
" :type other: :class:`Euler`, :class:`Quaternion` or :class:`Matrix`\n"
@@ -1600,7 +1615,7 @@ static PyObject *Matrix_rotate(MatrixObject *self, PyObject *value)
{
float self_rmat[3][3], other_rmat[3][3], rmat[3][3];
- if (BaseMath_ReadCallback(self) == -1)
+ if (BaseMath_ReadCallback_ForWrite(self) == -1)
return NULL;
if (mathutils_any_to_rotmat(other_rmat, value, "matrix.rotate(value)") == -1)
@@ -1653,10 +1668,10 @@ static PyObject *Matrix_decompose(MatrixObject *self)
mat3_to_quat(quat, rot);
ret = PyTuple_New(3);
- PyTuple_SET_ITEM(ret, 0, Vector_CreatePyObject(loc, 3, Py_NEW, NULL));
- PyTuple_SET_ITEM(ret, 1, Quaternion_CreatePyObject(quat, Py_NEW, NULL));
- PyTuple_SET_ITEM(ret, 2, Vector_CreatePyObject(size, 3, Py_NEW, NULL));
-
+ PyTuple_SET_ITEMS(ret,
+ Vector_CreatePyObject(loc, 3, NULL),
+ Quaternion_CreatePyObject(quat, NULL),
+ Vector_CreatePyObject(size, 3, NULL));
return ret;
}
@@ -1706,7 +1721,7 @@ static PyObject *Matrix_lerp(MatrixObject *self, PyObject *args)
return NULL;
}
- return Matrix_CreatePyObject(mat, self->num_col, self->num_row, Py_NEW, Py_TYPE(self));
+ return Matrix_CreatePyObject(mat, self->num_col, self->num_row, Py_TYPE(self));
}
/*---------------------------matrix.determinant() ----------------*/
@@ -1715,7 +1730,7 @@ PyDoc_STRVAR(Matrix_determinant_doc,
"\n"
" Return the determinant of a matrix.\n"
"\n"
-" :return: Return a the determinant of a matrix.\n"
+" :return: Return the determinant of a matrix.\n"
" :rtype: float\n"
"\n"
" .. seealso:: <http://en.wikipedia.org/wiki/Determinant>\n"
@@ -1744,7 +1759,7 @@ PyDoc_STRVAR(Matrix_transpose_doc,
);
static PyObject *Matrix_transpose(MatrixObject *self)
{
- if (BaseMath_ReadCallback(self) == -1)
+ if (BaseMath_ReadCallback_ForWrite(self) == -1)
return NULL;
if (self->num_col != self->num_row) {
@@ -1791,7 +1806,7 @@ PyDoc_STRVAR(Matrix_normalize_doc,
);
static PyObject *Matrix_normalize(MatrixObject *self)
{
- if (BaseMath_ReadCallback(self) == -1)
+ if (BaseMath_ReadCallback_ForWrite(self) == -1)
return NULL;
if (self->num_col != self->num_row) {
@@ -1836,19 +1851,37 @@ PyDoc_STRVAR(Matrix_zero_doc,
"\n"
" Set all the matrix values to zero.\n"
"\n"
-" :return: an instance of itself\n"
" :rtype: :class:`Matrix`\n"
);
static PyObject *Matrix_zero(MatrixObject *self)
{
- fill_vn_fl(self->matrix, self->num_col * self->num_row, 0.0f);
+ if (BaseMath_Prepare_ForWrite(self) == -1)
+ return NULL;
+
+ copy_vn_fl(self->matrix, self->num_col * self->num_row, 0.0f);
if (BaseMath_WriteCallback(self) == -1)
return NULL;
Py_RETURN_NONE;
+
}
/*---------------------------matrix.identity(() ------------------*/
+static void matrix_identity_internal(MatrixObject *self)
+{
+ BLI_assert((self->num_col == self->num_row) && (self->num_row <= 4));
+
+ if (self->num_col == 2) {
+ unit_m2((float (*)[2])self->matrix);
+ }
+ else if (self->num_col == 3) {
+ unit_m3((float (*)[3])self->matrix);
+ }
+ else {
+ unit_m4((float (*)[4])self->matrix);
+ }
+}
+
PyDoc_STRVAR(Matrix_identity_doc,
".. method:: identity()\n"
"\n"
@@ -1861,7 +1894,7 @@ PyDoc_STRVAR(Matrix_identity_doc,
);
static PyObject *Matrix_identity(MatrixObject *self)
{
- if (BaseMath_ReadCallback(self) == -1)
+ if (BaseMath_ReadCallback_ForWrite(self) == -1)
return NULL;
if (self->num_col != self->num_row) {
@@ -1871,15 +1904,7 @@ static PyObject *Matrix_identity(MatrixObject *self)
return NULL;
}
- if (self->num_col == 2) {
- unit_m2((float (*)[2])self->matrix);
- }
- else if (self->num_col == 3) {
- unit_m3((float (*)[3])self->matrix);
- }
- else {
- unit_m4((float (*)[4])self->matrix);
- }
+ matrix_identity_internal(self);
if (BaseMath_WriteCallback(self) == -1)
return NULL;
@@ -1891,7 +1916,7 @@ static PyObject *Matrix_identity(MatrixObject *self)
static PyObject *Matrix_copy_notest(MatrixObject *self, const float *matrix)
{
- return Matrix_CreatePyObject((float *)matrix, self->num_col, self->num_row, Py_NEW, Py_TYPE(self));
+ return Matrix_CreatePyObject((float *)matrix, self->num_col, self->num_row, Py_TYPE(self));
}
PyDoc_STRVAR(Matrix_copy_doc,
@@ -2025,7 +2050,22 @@ static PyObject *Matrix_richcmpr(PyObject *a, PyObject *b, int op)
return NULL;
}
- return Py_INCREF(res), res;
+ return Py_INCREF_RET(res);
+}
+
+static Py_hash_t Matrix_hash(MatrixObject *self)
+{
+ float mat[SQUARE(MATRIX_MAX_DIM)];
+
+ if (BaseMath_ReadCallback(self) == -1)
+ return -1;
+
+ if (BaseMathObject_Prepare_ForHash(self) == -1)
+ return -1;
+
+ matrix_transpose_internal(mat, self);
+
+ return mathutils_array_hash(mat, self->num_row * self->num_col);
}
/*---------------------SEQUENCE PROTOCOLS------------------------
@@ -2040,7 +2080,7 @@ static int Matrix_len(MatrixObject *self)
* the wrapped vector gives direct access to the matrix data */
static PyObject *Matrix_item_row(MatrixObject *self, int row)
{
- if (BaseMath_ReadCallback(self) == -1)
+ if (BaseMath_ReadCallback_ForWrite(self) == -1)
return NULL;
if (row < 0 || row >= self->num_row) {
@@ -2054,7 +2094,7 @@ static PyObject *Matrix_item_row(MatrixObject *self, int row)
/* same but column access */
static PyObject *Matrix_item_col(MatrixObject *self, int col)
{
- if (BaseMath_ReadCallback(self) == -1)
+ if (BaseMath_ReadCallback_ForWrite(self) == -1)
return NULL;
if (col < 0 || col >= self->num_col) {
@@ -2073,7 +2113,7 @@ static int Matrix_ass_item_row(MatrixObject *self, int row, PyObject *value)
{
int col;
float vec[MATRIX_MAX_DIM];
- if (BaseMath_ReadCallback(self) == -1)
+ if (BaseMath_ReadCallback_ForWrite(self) == -1)
return -1;
if (row >= self->num_row || row < 0) {
@@ -2082,7 +2122,7 @@ static int Matrix_ass_item_row(MatrixObject *self, int row, PyObject *value)
return -1;
}
- if (mathutils_array_parse(vec, self->num_col, self->num_col, value, "matrix[i] = value assignment") < 0) {
+ if (mathutils_array_parse(vec, self->num_col, self->num_col, value, "matrix[i] = value assignment") == -1) {
return -1;
}
@@ -2098,7 +2138,7 @@ static int Matrix_ass_item_col(MatrixObject *self, int col, PyObject *value)
{
int row;
float vec[MATRIX_MAX_DIM];
- if (BaseMath_ReadCallback(self) == -1)
+ if (BaseMath_ReadCallback_ForWrite(self) == -1)
return -1;
if (col >= self->num_col || col < 0) {
@@ -2107,7 +2147,7 @@ static int Matrix_ass_item_col(MatrixObject *self, int col, PyObject *value)
return -1;
}
- if (mathutils_array_parse(vec, self->num_row, self->num_row, value, "matrix[i] = value assignment") < 0) {
+ if (mathutils_array_parse(vec, self->num_row, self->num_row, value, "matrix[i] = value assignment") == -1) {
return -1;
}
@@ -2148,9 +2188,9 @@ static PyObject *Matrix_slice(MatrixObject *self, int begin, int end)
* sequence slice (set)*/
static int Matrix_ass_slice(MatrixObject *self, int begin, int end, PyObject *value)
{
- PyObject *value_fast = NULL;
+ PyObject *value_fast;
- if (BaseMath_ReadCallback(self) == -1)
+ if (BaseMath_ReadCallback_ForWrite(self) == -1)
return -1;
CLAMP(begin, 0, self->num_row);
@@ -2163,6 +2203,7 @@ static int Matrix_ass_slice(MatrixObject *self, int begin, int end, PyObject *va
return -1;
}
else {
+ PyObject **value_fast_items = PySequence_Fast_ITEMS(value_fast);
const int size = end - begin;
int row, col;
float mat[MATRIX_MAX_DIM * MATRIX_MAX_DIM];
@@ -2181,11 +2222,12 @@ static int Matrix_ass_slice(MatrixObject *self, int begin, int end, PyObject *va
/* parse sub items */
for (row = begin; row < end; row++) {
/* parse each sub sequence */
- PyObject *item = PySequence_Fast_GET_ITEM(value_fast, row - begin);
+ PyObject *item = value_fast_items[row - begin];
if (mathutils_array_parse(vec, self->num_col, self->num_col, item,
- "matrix[begin:end] = value assignment") < 0)
+ "matrix[begin:end] = value assignment") == -1)
{
+ Py_DECREF(value_fast);
return -1;
}
@@ -2233,7 +2275,7 @@ static PyObject *Matrix_add(PyObject *m1, PyObject *m2)
add_vn_vnvn(mat, mat1->matrix, mat2->matrix, mat1->num_col * mat1->num_row);
- return Matrix_CreatePyObject(mat, mat1->num_col, mat1->num_row, Py_NEW, Py_TYPE(mat1));
+ return Matrix_CreatePyObject(mat, mat1->num_col, mat1->num_row, Py_TYPE(mat1));
}
/*------------------------obj - obj------------------------------
* subtraction */
@@ -2265,7 +2307,7 @@ static PyObject *Matrix_sub(PyObject *m1, PyObject *m2)
sub_vn_vnvn(mat, mat1->matrix, mat2->matrix, mat1->num_col * mat1->num_row);
- return Matrix_CreatePyObject(mat, mat1->num_col, mat1->num_row, Py_NEW, Py_TYPE(mat1));
+ return Matrix_CreatePyObject(mat, mat1->num_col, mat1->num_row, Py_TYPE(mat1));
}
/*------------------------obj * obj------------------------------
* multiplication */
@@ -2273,7 +2315,7 @@ static PyObject *matrix_mul_float(MatrixObject *mat, const float scalar)
{
float tmat[MATRIX_MAX_DIM * MATRIX_MAX_DIM];
mul_vn_vn_fl(tmat, mat->matrix, mat->num_col * mat->num_row, scalar);
- return Matrix_CreatePyObject(tmat, mat->num_col, mat->num_row, Py_NEW, Py_TYPE(mat));
+ return Matrix_CreatePyObject(tmat, mat->num_col, mat->num_row, Py_TYPE(mat));
}
static PyObject *Matrix_mul(PyObject *m1, PyObject *m2)
@@ -2317,7 +2359,7 @@ static PyObject *Matrix_mul(PyObject *m1, PyObject *m2)
}
}
- return Matrix_CreatePyObject(mat, mat2->num_col, mat1->num_row, Py_NEW, Py_TYPE(mat1));
+ return Matrix_CreatePyObject(mat, mat2->num_col, mat1->num_row, Py_TYPE(mat1));
}
else if (mat2) {
/*FLOAT/INT * MATRIX */
@@ -2343,7 +2385,7 @@ static PyObject *Matrix_mul(PyObject *m1, PyObject *m2)
vec_size = mat1->num_row;
}
- return Vector_CreatePyObject(tvec, vec_size, Py_NEW, Py_TYPE(m2));
+ return Vector_CreatePyObject(tvec, vec_size, Py_TYPE(m2));
}
/*FLOAT/INT * MATRIX */
else if (((scalar = PyFloat_AsDouble(m2)) == -1.0f && PyErr_Occurred()) == 0) {
@@ -2516,7 +2558,7 @@ static int Matrix_translation_set(MatrixObject *self, PyObject *value, void *UNU
{
float tvec[3];
- if (BaseMath_ReadCallback(self) == -1)
+ if (BaseMath_ReadCallback_ForWrite(self) == -1)
return -1;
/*must be 4x4 square matrix*/
@@ -2652,6 +2694,7 @@ static PyGetSetDef Matrix_getseters[] = {
{(char *)"is_orthogonal", (getter)Matrix_is_orthogonal_get, (setter)NULL, Matrix_is_orthogonal_doc, NULL},
{(char *)"is_orthogonal_axis_vectors", (getter)Matrix_is_orthogonal_axis_vectors_get, (setter)NULL, Matrix_is_orthogonal_axis_vectors_doc, NULL},
{(char *)"is_wrapped", (getter)BaseMathObject_is_wrapped_get, (setter)NULL, BaseMathObject_is_wrapped_doc, NULL},
+ {(char *)"is_frozen", (getter)BaseMathObject_is_frozen_get, (setter)NULL, BaseMathObject_is_frozen_doc, NULL},
{(char *)"owner", (getter)BaseMathObject_owner_get, (setter)NULL, BaseMathObject_owner_doc, NULL},
{NULL, NULL, NULL, NULL, NULL} /* Sentinel */
};
@@ -2695,6 +2738,9 @@ static struct PyMethodDef Matrix_methods[] = {
{"__copy__", (PyCFunction) Matrix_copy, METH_NOARGS, Matrix_copy_doc},
{"__deepcopy__", (PyCFunction) Matrix_deepcopy, METH_VARARGS, Matrix_copy_doc},
+ /* base-math methods */
+ {"freeze", (PyCFunction)BaseMathObject_freeze, METH_NOARGS, BaseMathObject_freeze_doc},
+
/* class methods */
{"Identity", (PyCFunction) C_Matrix_Identity, METH_VARARGS | METH_CLASS, C_Matrix_Identity_doc},
{"Rotation", (PyCFunction) C_Matrix_Rotation, METH_VARARGS | METH_CLASS, C_Matrix_Rotation_doc},
@@ -2707,7 +2753,14 @@ static struct PyMethodDef Matrix_methods[] = {
/*------------------PY_OBECT DEFINITION--------------------------*/
PyDoc_STRVAR(matrix_doc,
-"This object gives access to Matrices in Blender."
+".. class:: Matrix([rows])\n"
+"\n"
+" This object gives access to Matrices in Blender, supporting square and rectangular\n"
+" matrices from 2x2 up to 4x4.\n"
+"\n"
+" :param rows: Sequence of rows.\n"
+" When ommitted, a 4x4 identity matrix is constructed.\n"
+" :type rows: 2d number sequence\n"
);
PyTypeObject matrix_Type = {
PyVarObject_HEAD_INIT(NULL, 0)
@@ -2723,7 +2776,7 @@ PyTypeObject matrix_Type = {
&Matrix_NumMethods, /*tp_as_number*/
&Matrix_SeqMethods, /*tp_as_sequence*/
&Matrix_AsMapping, /*tp_as_mapping*/
- NULL, /*tp_hash*/
+ (hashfunc)Matrix_hash, /*tp_hash*/
NULL, /*tp_call*/
#ifndef MATH_STANDALONE
(reprfunc) Matrix_str, /*tp_str*/
@@ -2762,15 +2815,13 @@ PyTypeObject matrix_Type = {
NULL /*tp_del*/
};
-/* pass Py_WRAP - if vector is a WRAPPER for data allocated by BLENDER
- * (i.e. it was allocated elsewhere by MEM_mallocN())
- * pass Py_NEW - if vector is not a WRAPPER and managed by PYTHON
- * (i.e. it must be created here with PyMEM_malloc()) */
-PyObject *Matrix_CreatePyObject(float *mat,
- const unsigned short num_col, const unsigned short num_row,
- int type, PyTypeObject *base_type)
+PyObject *Matrix_CreatePyObject(
+ const float *mat,
+ const unsigned short num_col, const unsigned short num_row,
+ PyTypeObject *base_type)
{
MatrixObject *self;
+ float *mat_alloc;
/* matrix objects can be any 2-4row x 2-4col matrix */
if (num_col < 2 || num_col > 4 || num_row < 2 || num_row > 4) {
@@ -2780,10 +2831,17 @@ PyObject *Matrix_CreatePyObject(float *mat,
return NULL;
}
- self = base_type ? (MatrixObject *)base_type->tp_alloc(base_type, 0) :
- (MatrixObject *)PyObject_GC_New(MatrixObject, &matrix_Type);
+ mat_alloc = PyMem_Malloc(num_col * num_row * sizeof(float));
+ if (UNLIKELY(mat_alloc == NULL)) {
+ PyErr_SetString(PyExc_MemoryError,
+ "Matrix(): "
+ "problem allocating data");
+ return NULL;
+ }
+ self = BASE_MATH_NEW(MatrixObject, matrix_Type, base_type);
if (self) {
+ self->matrix = mat_alloc;
self->num_col = num_col;
self->num_row = num_row;
@@ -2791,37 +2849,52 @@ PyObject *Matrix_CreatePyObject(float *mat,
self->cb_user = NULL;
self->cb_type = self->cb_subtype = 0;
- if (type == Py_WRAP) {
- self->matrix = mat;
- self->wrapped = Py_WRAP;
+ if (mat) { /*if a float array passed*/
+ memcpy(self->matrix, mat, num_col * num_row * sizeof(float));
}
- else if (type == Py_NEW) {
- self->matrix = PyMem_Malloc(num_col * num_row * sizeof(float));
- if (self->matrix == NULL) { /*allocation failure*/
- PyErr_SetString(PyExc_MemoryError,
- "Matrix(): "
- "problem allocating pointer space");
- return NULL;
- }
-
- if (mat) { /*if a float array passed*/
- memcpy(self->matrix, mat, num_col * num_row * sizeof(float));
- }
- else if (num_col == num_row) {
- /* or if no arguments are passed return identity matrix for square matrices */
- PyObject *ret_dummy = Matrix_identity(self);
- Py_DECREF(ret_dummy);
- }
- else {
- /* otherwise zero everything */
- memset(self->matrix, 0, num_col * num_row * sizeof(float));
- }
- self->wrapped = Py_NEW;
+ else if (num_col == num_row) {
+ /* or if no arguments are passed return identity matrix for square matrices */
+ matrix_identity_internal(self);
}
else {
- Py_FatalError("Matrix(): invalid type!");
- return NULL;
+ /* otherwise zero everything */
+ memset(self->matrix, 0, num_col * num_row * sizeof(float));
}
+ self->flag = BASE_MATH_FLAG_DEFAULT;
+ }
+ else {
+ PyMem_Free(mat_alloc);
+ }
+
+ return (PyObject *)self;
+}
+
+PyObject *Matrix_CreatePyObject_wrap(
+ float *mat,
+ const unsigned short num_col, const unsigned short num_row,
+ PyTypeObject *base_type)
+{
+ MatrixObject *self;
+
+ /* matrix objects can be any 2-4row x 2-4col matrix */
+ if (num_col < 2 || num_col > 4 || num_row < 2 || num_row > 4) {
+ PyErr_SetString(PyExc_RuntimeError,
+ "Matrix(): "
+ "row and column sizes must be between 2 and 4");
+ return NULL;
+ }
+
+ self = BASE_MATH_NEW(MatrixObject, matrix_Type, base_type);
+ if (self) {
+ self->num_col = num_col;
+ self->num_row = num_row;
+
+ /* init callbacks as NULL */
+ self->cb_user = NULL;
+ self->cb_type = self->cb_subtype = 0;
+
+ self->matrix = mat;
+ self->flag = BASE_MATH_FLAG_DEFAULT | BASE_MATH_FLAG_IS_WRAP;
}
return (PyObject *) self;
}
@@ -2830,7 +2903,7 @@ PyObject *Matrix_CreatePyObject_cb(PyObject *cb_user,
const unsigned short num_col, const unsigned short num_row,
unsigned char cb_type, unsigned char cb_subtype)
{
- MatrixObject *self = (MatrixObject *)Matrix_CreatePyObject(NULL, num_col, num_row, Py_NEW, NULL);
+ MatrixObject *self = (MatrixObject *)Matrix_CreatePyObject(NULL, num_col, num_row, NULL);
if (self) {
Py_INCREF(cb_user);
self->cb_user = cb_user;
diff --git a/source/blender/python/mathutils/mathutils_Matrix.h b/source/blender/python/mathutils/mathutils_Matrix.h
index f94af9e540e..9ae5a4bd61d 100644
--- a/source/blender/python/mathutils/mathutils_Matrix.h
+++ b/source/blender/python/mathutils/mathutils_Matrix.h
@@ -61,12 +61,21 @@ typedef struct {
* blender (stored in blend_data). This is an either/or struct not both */
/* prototypes */
-PyObject *Matrix_CreatePyObject(float *mat,
- const unsigned short num_col, const unsigned short num_row,
- int type, PyTypeObject *base_type);
-PyObject *Matrix_CreatePyObject_cb(PyObject *user,
- const unsigned short num_col, const unsigned short num_row,
- unsigned char cb_type, unsigned char cb_subtype);
+PyObject *Matrix_CreatePyObject(
+ const float *mat,
+ const unsigned short num_col, const unsigned short num_row,
+ PyTypeObject *base_type
+ ) ATTR_WARN_UNUSED_RESULT;
+PyObject *Matrix_CreatePyObject_wrap(
+ float *mat,
+ const unsigned short num_col, const unsigned short num_row,
+ PyTypeObject *base_type
+ ) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1);
+PyObject *Matrix_CreatePyObject_cb(
+ PyObject *user,
+ const unsigned short num_col, const unsigned short num_row,
+ unsigned char cb_type, unsigned char cb_subtype
+ ) ATTR_WARN_UNUSED_RESULT;
extern unsigned char mathutils_matrix_row_cb_index; /* default */
extern unsigned char mathutils_matrix_col_cb_index;
diff --git a/source/blender/python/mathutils/mathutils_Quaternion.c b/source/blender/python/mathutils/mathutils_Quaternion.c
index ae3476f5802..1752be6e306 100644
--- a/source/blender/python/mathutils/mathutils_Quaternion.c
+++ b/source/blender/python/mathutils/mathutils_Quaternion.c
@@ -32,6 +32,8 @@
#include "BLI_math.h"
#include "BLI_utildefines.h"
+#include "../generic/python_utildefines.h"
+
#ifndef MATH_STANDALONE
# include "BLI_dynstr.h"
#endif
@@ -121,7 +123,7 @@ static PyObject *Quaternion_to_euler(QuaternionObject *self, PyObject *args)
else quat_to_eulO(eul, order, tquat);
}
- return Euler_CreatePyObject(eul, order, Py_NEW, NULL);
+ return Euler_CreatePyObject(eul, order, NULL);
}
PyDoc_STRVAR(Quaternion_to_matrix_doc,
@@ -140,7 +142,7 @@ static PyObject *Quaternion_to_matrix(QuaternionObject *self)
return NULL;
quat_to_mat3((float (*)[3])mat, self->quat);
- return Matrix_CreatePyObject(mat, 3, 3, Py_NEW, NULL);
+ return Matrix_CreatePyObject(mat, 3, 3, NULL);
}
PyDoc_STRVAR(Quaternion_to_axis_angle_doc,
@@ -169,11 +171,36 @@ static PyObject *Quaternion_to_axis_angle(QuaternionObject *self)
quat__axis_angle_sanitize(axis, &angle);
ret = PyTuple_New(2);
- PyTuple_SET_ITEM(ret, 0, Vector_CreatePyObject(axis, 3, Py_NEW, NULL));
- PyTuple_SET_ITEM(ret, 1, PyFloat_FromDouble(angle));
+ PyTuple_SET_ITEMS(ret,
+ Vector_CreatePyObject(axis, 3, NULL),
+ PyFloat_FromDouble(angle));
return ret;
}
+PyDoc_STRVAR(Quaternion_to_exponential_map_doc,
+".. method:: to_exponential_map()\n"
+"\n"
+" Return the exponential map representation of the quaternion.\n"
+"\n"
+" This representation consist of the rotation axis multiplied by the rotation angle."
+" Such a representation is useful for interpolation between multiple orientations.\n"
+"\n"
+" :return: exponential map.\n"
+" :rtype: :class:`Vector` of size 3\n"
+"\n"
+" To convert back to a quaternion, pass it to the :class:`Quaternion` constructor.\n"
+);
+static PyObject *Quaternion_to_exponential_map(QuaternionObject *self)
+{
+ float expmap[3];
+
+ if (BaseMath_ReadCallback(self) == -1)
+ return NULL;
+
+ quat_to_expmap(expmap, self->quat);
+ return Vector_CreatePyObject(expmap, 3, NULL);
+}
+
PyDoc_STRVAR(Quaternion_cross_doc,
".. method:: cross(other)\n"
"\n"
@@ -198,7 +225,7 @@ static PyObject *Quaternion_cross(QuaternionObject *self, PyObject *value)
}
mul_qt_qtqt(quat, self->quat, tquat);
- return Quaternion_CreatePyObject(quat, Py_NEW, Py_TYPE(self));
+ return Quaternion_CreatePyObject(quat, Py_TYPE(self));
}
PyDoc_STRVAR(Quaternion_dot_doc,
@@ -252,7 +279,7 @@ static PyObject *Quaternion_rotation_difference(QuaternionObject *self, PyObject
rotation_between_quats_to_quat(quat, self->quat, tquat);
- return Quaternion_CreatePyObject(quat, Py_NEW, Py_TYPE(self));
+ return Quaternion_CreatePyObject(quat, Py_TYPE(self));
}
PyDoc_STRVAR(Quaternion_slerp_doc,
@@ -297,13 +324,13 @@ static PyObject *Quaternion_slerp(QuaternionObject *self, PyObject *args)
interp_qt_qtqt(quat, self->quat, tquat, fac);
- return Quaternion_CreatePyObject(quat, Py_NEW, Py_TYPE(self));
+ return Quaternion_CreatePyObject(quat, Py_TYPE(self));
}
PyDoc_STRVAR(Quaternion_rotate_doc,
".. method:: rotate(other)\n"
"\n"
-" Rotates the quaternion a by another mathutils value.\n"
+" Rotates the quaternion by another mathutils value.\n"
"\n"
" :arg other: rotation component of mathutils value\n"
" :type other: :class:`Euler`, :class:`Quaternion` or :class:`Matrix`\n"
@@ -313,7 +340,7 @@ static PyObject *Quaternion_rotate(QuaternionObject *self, PyObject *value)
float self_rmat[3][3], other_rmat[3][3], rmat[3][3];
float tquat[4], length;
- if (BaseMath_ReadCallback(self) == -1)
+ if (BaseMath_ReadCallback_ForWrite(self) == -1)
return NULL;
if (mathutils_any_to_rotmat(other_rmat, value, "Quaternion.rotate(value)") == -1)
@@ -331,7 +358,8 @@ static PyObject *Quaternion_rotate(QuaternionObject *self, PyObject *value)
}
/* ----------------------------Quaternion.normalize()---------------- */
-/* normalize the axis of rotation of [theta, vector] */
+/* Normalize the quaternion. This may change the angle as well as the
+ * rotation axis, as all of (w, x, y, z) are scaled. */
PyDoc_STRVAR(Quaternion_normalize_doc,
".. function:: normalize()\n"
"\n"
@@ -339,7 +367,7 @@ PyDoc_STRVAR(Quaternion_normalize_doc,
);
static PyObject *Quaternion_normalize(QuaternionObject *self)
{
- if (BaseMath_ReadCallback(self) == -1)
+ if (BaseMath_ReadCallback_ForWrite(self) == -1)
return NULL;
normalize_qt(self->quat);
@@ -367,7 +395,7 @@ PyDoc_STRVAR(Quaternion_invert_doc,
);
static PyObject *Quaternion_invert(QuaternionObject *self)
{
- if (BaseMath_ReadCallback(self) == -1)
+ if (BaseMath_ReadCallback_ForWrite(self) == -1)
return NULL;
invert_qt(self->quat);
@@ -393,12 +421,11 @@ PyDoc_STRVAR(Quaternion_identity_doc,
"\n"
" Set the quaternion to an identity quaternion.\n"
"\n"
-" :return: an instance of itself.\n"
" :rtype: :class:`Quaternion`\n"
);
static PyObject *Quaternion_identity(QuaternionObject *self)
{
- if (BaseMath_ReadCallback(self) == -1)
+ if (BaseMath_ReadCallback_ForWrite(self) == -1)
return NULL;
unit_qt(self->quat);
@@ -412,12 +439,11 @@ PyDoc_STRVAR(Quaternion_negate_doc,
"\n"
" Set the quaternion to its negative.\n"
"\n"
-" :return: an instance of itself.\n"
" :rtype: :class:`Quaternion`\n"
);
static PyObject *Quaternion_negate(QuaternionObject *self)
{
- if (BaseMath_ReadCallback(self) == -1)
+ if (BaseMath_ReadCallback_ForWrite(self) == -1)
return NULL;
mul_qt_fl(self->quat, -1.0f);
@@ -433,7 +459,7 @@ PyDoc_STRVAR(Quaternion_conjugate_doc,
);
static PyObject *Quaternion_conjugate(QuaternionObject *self)
{
- if (BaseMath_ReadCallback(self) == -1)
+ if (BaseMath_ReadCallback_ForWrite(self) == -1)
return NULL;
conjugate_qt(self->quat);
@@ -470,7 +496,7 @@ static PyObject *Quaternion_copy(QuaternionObject *self)
if (BaseMath_ReadCallback(self) == -1)
return NULL;
- return Quaternion_CreatePyObject(self->quat, Py_NEW, Py_TYPE(self));
+ return Quaternion_CreatePyObject(self->quat, Py_TYPE(self));
}
static PyObject *Quaternion_deepcopy(QuaternionObject *self, PyObject *args)
{
@@ -546,7 +572,18 @@ static PyObject *Quaternion_richcmpr(PyObject *a, PyObject *b, int op)
return NULL;
}
- return Py_INCREF(res), res;
+ return Py_INCREF_RET(res);
+}
+
+static Py_hash_t Quaternion_hash(QuaternionObject *self)
+{
+ if (BaseMath_ReadCallback(self) == -1)
+ return -1;
+
+ if (BaseMathObject_Prepare_ForHash(self) == -1)
+ return -1;
+
+ return mathutils_array_hash(self->quat, QUAT_SIZE);
}
/* ---------------------SEQUENCE PROTOCOLS------------------------ */
@@ -579,8 +616,14 @@ static PyObject *Quaternion_item(QuaternionObject *self, int i)
/* sequence accessor (set) */
static int Quaternion_ass_item(QuaternionObject *self, int i, PyObject *ob)
{
- float scalar = (float)PyFloat_AsDouble(ob);
- if (scalar == -1.0f && PyErr_Occurred()) { /* parsed item not a number */
+ float f;
+
+ if (BaseMath_Prepare_ForWrite(self) == -1)
+ return -1;
+
+ f = (float)PyFloat_AsDouble(ob);
+
+ if (f == -1.0f && PyErr_Occurred()) { /* parsed item not a number */
PyErr_SetString(PyExc_TypeError,
"quaternion[index] = x: "
"assigned value not a number");
@@ -595,7 +638,7 @@ static int Quaternion_ass_item(QuaternionObject *self, int i, PyObject *ob)
"array assignment index out of range");
return -1;
}
- self->quat[i] = scalar;
+ self->quat[i] = f;
if (BaseMath_WriteIndexCallback(self, i) == -1)
return -1;
@@ -631,7 +674,7 @@ static int Quaternion_ass_slice(QuaternionObject *self, int begin, int end, PyOb
int i, size;
float quat[QUAT_SIZE];
- if (BaseMath_ReadCallback(self) == -1)
+ if (BaseMath_ReadCallback_ForWrite(self) == -1)
return -1;
CLAMP(begin, 0, QUAT_SIZE);
@@ -750,7 +793,7 @@ static PyObject *Quaternion_add(PyObject *q1, PyObject *q2)
return NULL;
add_qt_qtqt(quat, quat1->quat, quat2->quat, 1.0f);
- return Quaternion_CreatePyObject(quat, Py_NEW, Py_TYPE(q1));
+ return Quaternion_CreatePyObject(quat, Py_TYPE(q1));
}
/* ------------------------obj - obj------------------------------ */
/* subtraction */
@@ -778,7 +821,7 @@ static PyObject *Quaternion_sub(PyObject *q1, PyObject *q2)
quat[x] = quat1->quat[x] - quat2->quat[x];
}
- return Quaternion_CreatePyObject(quat, Py_NEW, Py_TYPE(q1));
+ return Quaternion_CreatePyObject(quat, Py_TYPE(q1));
}
static PyObject *quat_mul_float(QuaternionObject *quat, const float scalar)
@@ -786,7 +829,7 @@ static PyObject *quat_mul_float(QuaternionObject *quat, const float scalar)
float tquat[4];
copy_qt_qt(tquat, quat->quat);
mul_qt_fl(tquat, scalar);
- return Quaternion_CreatePyObject(tquat, Py_NEW, Py_TYPE(quat));
+ return Quaternion_CreatePyObject(tquat, Py_TYPE(quat));
}
/*------------------------obj * obj------------------------------
@@ -809,7 +852,7 @@ static PyObject *Quaternion_mul(PyObject *q1, PyObject *q2)
if (quat1 && quat2) { /* QUAT * QUAT (cross product) */
mul_qt_qtqt(quat, quat1->quat, quat2->quat);
- return Quaternion_CreatePyObject(quat, Py_NEW, Py_TYPE(q1));
+ return Quaternion_CreatePyObject(quat, Py_TYPE(q1));
}
/* the only case this can happen (for a supported type is "FLOAT * QUAT") */
else if (quat2) { /* FLOAT * QUAT */
@@ -837,7 +880,7 @@ static PyObject *Quaternion_mul(PyObject *q1, PyObject *q2)
copy_v3_v3(tvec, vec2->vec);
mul_qt_v3(quat1->quat, tvec);
- return Vector_CreatePyObject(tvec, 3, Py_NEW, Py_TYPE(vec2));
+ return Vector_CreatePyObject(tvec, 3, Py_TYPE(vec2));
}
/* QUAT * FLOAT */
else if ((((scalar = PyFloat_AsDouble(q2)) == -1.0f && PyErr_Occurred()) == 0)) {
@@ -865,7 +908,7 @@ static PyObject *Quaternion_neg(QuaternionObject *self)
return NULL;
negate_v4_v4(tquat, self->quat);
- return Quaternion_CreatePyObject(tquat, Py_NEW, Py_TYPE(self));
+ return Quaternion_CreatePyObject(tquat, Py_TYPE(self));
}
@@ -978,7 +1021,7 @@ static int Quaternion_angle_set(QuaternionObject *self, PyObject *value, void *U
float axis[3], angle_dummy;
float angle;
- if (BaseMath_ReadCallback(self) == -1)
+ if (BaseMath_ReadCallback_ForWrite(self) == -1)
return -1;
len = normalize_qt_qt(tquat, self->quat);
@@ -1023,7 +1066,7 @@ static PyObject *Quaternion_axis_vector_get(QuaternionObject *self, void *UNUSED
quat__axis_angle_sanitize(axis, NULL);
- return Vector_CreatePyObject(axis, 3, Py_NEW, NULL);
+ return Vector_CreatePyObject(axis, 3, NULL);
}
static int Quaternion_axis_vector_set(QuaternionObject *self, PyObject *value, void *UNUSED(closure))
@@ -1034,7 +1077,7 @@ static int Quaternion_axis_vector_set(QuaternionObject *self, PyObject *value, v
float axis[3];
float angle;
- if (BaseMath_ReadCallback(self) == -1)
+ if (BaseMath_ReadCallback_ForWrite(self) == -1)
return -1;
len = normalize_qt_qt(tquat, self->quat);
@@ -1075,9 +1118,24 @@ static PyObject *Quaternion_new(PyTypeObject *type, PyObject *args, PyObject *kw
case 0:
break;
case 1:
- if (mathutils_array_parse(quat, QUAT_SIZE, QUAT_SIZE, seq, "mathutils.Quaternion()") == -1)
+ {
+ int size;
+
+ if ((size = mathutils_array_parse(quat, 3, QUAT_SIZE, seq, "mathutils.Quaternion()")) == -1) {
return NULL;
+ }
+
+ if (size == 4) {
+ /* 4d: Quaternion (common case) */
+ }
+ else {
+ /* 3d: Interpret as exponential map */
+ BLI_assert(size == 3);
+ expmap_to_quat(quat, quat);
+ }
+
break;
+ }
case 2:
{
float axis[3];
@@ -1089,7 +1147,7 @@ static PyObject *Quaternion_new(PyTypeObject *type, PyObject *args, PyObject *kw
/* PyArg_ParseTuple assures no more than 2 */
}
}
- return Quaternion_CreatePyObject(quat, Py_NEW, type);
+ return Quaternion_CreatePyObject(quat, type);
}
static PyObject *quat__apply_to_copy(PyNoArgsFunction quat_func, QuaternionObject *self)
@@ -1154,6 +1212,7 @@ static struct PyMethodDef Quaternion_methods[] = {
{"to_euler", (PyCFunction) Quaternion_to_euler, METH_VARARGS, Quaternion_to_euler_doc},
{"to_matrix", (PyCFunction) Quaternion_to_matrix, METH_NOARGS, Quaternion_to_matrix_doc},
{"to_axis_angle", (PyCFunction) Quaternion_to_axis_angle, METH_NOARGS, Quaternion_to_axis_angle_doc},
+ {"to_exponential_map", (PyCFunction) Quaternion_to_exponential_map, METH_NOARGS, Quaternion_to_exponential_map_doc},
/* operation between 2 or more types */
{"cross", (PyCFunction) Quaternion_cross, METH_O, Quaternion_cross_doc},
@@ -1162,6 +1221,9 @@ static struct PyMethodDef Quaternion_methods[] = {
{"slerp", (PyCFunction) Quaternion_slerp, METH_VARARGS, Quaternion_slerp_doc},
{"rotate", (PyCFunction) Quaternion_rotate, METH_O, Quaternion_rotate_doc},
+ /* base-math methods */
+ {"freeze", (PyCFunction)BaseMathObject_freeze, METH_NOARGS, BaseMathObject_freeze_doc},
+
{"copy", (PyCFunction) Quaternion_copy, METH_NOARGS, Quaternion_copy_doc},
{"__copy__", (PyCFunction) Quaternion_copy, METH_NOARGS, Quaternion_copy_doc},
{"__deepcopy__", (PyCFunction) Quaternion_deepcopy, METH_VARARGS, Quaternion_copy_doc},
@@ -1180,13 +1242,36 @@ static PyGetSetDef Quaternion_getseters[] = {
{(char *)"angle", (getter)Quaternion_angle_get, (setter)Quaternion_angle_set, Quaternion_angle_doc, NULL},
{(char *)"axis", (getter)Quaternion_axis_vector_get, (setter)Quaternion_axis_vector_set, Quaternion_axis_vector_doc, NULL},
{(char *)"is_wrapped", (getter)BaseMathObject_is_wrapped_get, (setter)NULL, BaseMathObject_is_wrapped_doc, NULL},
+ {(char *)"is_frozen", (getter)BaseMathObject_is_frozen_get, (setter)NULL, BaseMathObject_is_frozen_doc, NULL},
{(char *)"owner", (getter)BaseMathObject_owner_get, (setter)NULL, BaseMathObject_owner_doc, NULL},
{NULL, NULL, NULL, NULL, NULL} /* Sentinel */
};
/* ------------------PY_OBECT DEFINITION-------------------------- */
PyDoc_STRVAR(quaternion_doc,
-"This object gives access to Quaternions in Blender."
+".. class:: Quaternion([seq, [angle]])\n"
+"\n"
+" This object gives access to Quaternions in Blender.\n"
+"\n"
+" :param seq: size 3 or 4\n"
+" :type seq: :class:`Vector`\n"
+" :param angle: rotation angle, in radians\n"
+" :type angle: float\n"
+"\n"
+" The constructor takes arguments in various forms:\n"
+"\n"
+" (), *no args*\n"
+" Create an identity quaternion\n"
+" (*wxyz*)\n"
+" Create a quaternion from a ``(w, x, y, z)`` vector.\n"
+" (*exponential_map*)\n"
+" Create a quaternion from a 3d exponential map vector.\n"
+"\n"
+" .. seealso:: :meth:`to_exponential_map`\n"
+" (*axis, angle*)\n"
+" Create a quaternion representing a rotation of *angle* radians over *axis*.\n"
+"\n"
+" .. seealso:: :meth:`to_axis_angle`\n"
);
PyTypeObject quaternion_Type = {
PyVarObject_HEAD_INIT(NULL, 0)
@@ -1202,7 +1287,7 @@ PyTypeObject quaternion_Type = {
&Quaternion_NumMethods, /* tp_as_number */
&Quaternion_SeqMethods, /* tp_as_sequence */
&Quaternion_AsMapping, /* tp_as_mapping */
- NULL, /* tp_hash */
+ (hashfunc)Quaternion_hash, /* tp_hash */
NULL, /* tp_call */
#ifndef MATH_STANDALONE
(reprfunc) Quaternion_str, /* tp_str */
@@ -1240,41 +1325,60 @@ PyTypeObject quaternion_Type = {
NULL, /* tp_weaklist */
NULL, /* tp_del */
};
-/* ------------------------Quaternion_CreatePyObject (internal)------------- */
-/* creates a new quaternion object */
-/*pass Py_WRAP - if vector is a WRAPPER for data allocated by BLENDER
- * (i.e. it was allocated elsewhere by MEM_mallocN())
- * pass Py_NEW - if vector is not a WRAPPER and managed by PYTHON
- * (i.e. it must be created here with PyMEM_malloc())*/
-PyObject *Quaternion_CreatePyObject(float quat[4], int type, PyTypeObject *base_type)
+
+PyObject *Quaternion_CreatePyObject(
+ const float quat[4],
+ PyTypeObject *base_type)
{
QuaternionObject *self;
+ float *quat_alloc;
- self = base_type ? (QuaternionObject *)base_type->tp_alloc(base_type, 0) :
- (QuaternionObject *)PyObject_GC_New(QuaternionObject, &quaternion_Type);
+ quat_alloc = PyMem_Malloc(QUAT_SIZE * sizeof(float));
+ if (UNLIKELY(quat_alloc == NULL)) {
+ PyErr_SetString(PyExc_MemoryError,
+ "Quaternion(): "
+ "problem allocating data");
+ return NULL;
+ }
+ self = BASE_MATH_NEW(QuaternionObject, quaternion_Type, base_type);
if (self) {
+ self->quat = quat_alloc;
/* init callbacks as NULL */
self->cb_user = NULL;
self->cb_type = self->cb_subtype = 0;
- if (type == Py_WRAP) {
- self->quat = quat;
- self->wrapped = Py_WRAP;
- }
- else if (type == Py_NEW) {
- self->quat = PyMem_Malloc(QUAT_SIZE * sizeof(float));
- if (!quat) { /* new empty */
- unit_qt(self->quat);
- }
- else {
- copy_qt_qt(self->quat, quat);
- }
- self->wrapped = Py_NEW;
+ /* NEW */
+ if (!quat) { /* new empty */
+ unit_qt(self->quat);
}
else {
- Py_FatalError("Quaternion(): invalid type!");
+ copy_qt_qt(self->quat, quat);
}
+ self->flag = BASE_MATH_FLAG_DEFAULT;
+ }
+ else {
+ PyMem_Free(quat_alloc);
+ }
+
+ return (PyObject *)self;
+}
+
+PyObject *Quaternion_CreatePyObject_wrap(
+ float quat[4],
+ PyTypeObject *base_type)
+{
+ QuaternionObject *self;
+
+ self = BASE_MATH_NEW(QuaternionObject, quaternion_Type, base_type);
+ if (self) {
+ /* init callbacks as NULL */
+ self->cb_user = NULL;
+ self->cb_type = self->cb_subtype = 0;
+
+ /* WRAP */
+ self->quat = quat;
+ self->flag = BASE_MATH_FLAG_DEFAULT | BASE_MATH_FLAG_IS_WRAP;
}
return (PyObject *) self;
}
@@ -1282,7 +1386,7 @@ PyObject *Quaternion_CreatePyObject(float quat[4], int type, PyTypeObject *base_
PyObject *Quaternion_CreatePyObject_cb(PyObject *cb_user,
unsigned char cb_type, unsigned char cb_subtype)
{
- QuaternionObject *self = (QuaternionObject *)Quaternion_CreatePyObject(NULL, Py_NEW, NULL);
+ QuaternionObject *self = (QuaternionObject *)Quaternion_CreatePyObject(NULL, NULL);
if (self) {
Py_INCREF(cb_user);
self->cb_user = cb_user;
diff --git a/source/blender/python/mathutils/mathutils_Quaternion.h b/source/blender/python/mathutils/mathutils_Quaternion.h
index 36036c6d3fa..66ee3362906 100644
--- a/source/blender/python/mathutils/mathutils_Quaternion.h
+++ b/source/blender/python/mathutils/mathutils_Quaternion.h
@@ -40,8 +40,17 @@ typedef struct {
* blender (stored in blend_data). This is an either/or struct not both */
/* prototypes */
-PyObject *Quaternion_CreatePyObject(float quat[4], int type, PyTypeObject *base_type);
-PyObject *Quaternion_CreatePyObject_cb(PyObject *cb_user,
- unsigned char cb_type, unsigned char cb_subtype);
+PyObject *Quaternion_CreatePyObject(
+ const float quat[4],
+ PyTypeObject *base_type
+ ) ATTR_WARN_UNUSED_RESULT;
+PyObject *Quaternion_CreatePyObject_wrap(
+ float quat[4],
+ PyTypeObject *base_type
+ ) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1);
+PyObject *Quaternion_CreatePyObject_cb(
+ PyObject *cb_user,
+ unsigned char cb_type, unsigned char cb_subtype
+ ) ATTR_WARN_UNUSED_RESULT;
#endif /* __MATHUTILS_QUATERNION_H__ */
diff --git a/source/blender/python/mathutils/mathutils_Vector.c b/source/blender/python/mathutils/mathutils_Vector.c
index 15a9860be0a..3d7a505eb12 100644
--- a/source/blender/python/mathutils/mathutils_Vector.c
+++ b/source/blender/python/mathutils/mathutils_Vector.c
@@ -76,7 +76,7 @@ static PyObject *Vector_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
return NULL;
}
- fill_vn_fl(vec, size, 0.0f);
+ copy_vn_fl(vec, size, 0.0f);
break;
case 1:
if ((size = mathutils_array_parse_alloc(&vec, 2, PyTuple_GET_ITEM(args, 0), "mathutils.Vector()")) == -1) {
@@ -142,7 +142,7 @@ static PyObject *C_Vector_Fill(PyObject *cls, PyObject *args)
return NULL;
}
- fill_vn_fl(vec, size, fill);
+ copy_vn_fl(vec, size, fill);
return Vector_CreatePyObject_alloc(vec, size, (PyTypeObject *)cls);
}
@@ -336,7 +336,10 @@ PyDoc_STRVAR(Vector_zero_doc,
);
static PyObject *Vector_zero(VectorObject *self)
{
- fill_vn_fl(self->vec, self->size, 0.0f);
+ if (BaseMath_Prepare_ForWrite(self) == -1)
+ return NULL;
+
+ copy_vn_fl(self->vec, self->size, 0.0f);
if (BaseMath_WriteCallback(self) == -1)
return NULL;
@@ -357,7 +360,7 @@ PyDoc_STRVAR(Vector_normalize_doc,
static PyObject *Vector_normalize(VectorObject *self)
{
int size = (self->size == 4 ? 3 : self->size);
- if (BaseMath_ReadCallback(self) == -1)
+ if (BaseMath_ReadCallback_ForWrite(self) == -1)
return NULL;
normalize_vn(self->vec, size);
@@ -387,7 +390,7 @@ static PyObject *Vector_resize(VectorObject *self, PyObject *value)
{
int size;
- if (self->wrapped == Py_WRAP) {
+ if (self->flag & BASE_MATH_FLAG_IS_WRAP) {
PyErr_SetString(PyExc_TypeError,
"Vector.resize(): "
"cannot resize wrapped data - only python vectors");
@@ -423,7 +426,7 @@ static PyObject *Vector_resize(VectorObject *self, PyObject *value)
/* If the vector has increased in length, set all new elements to 0.0f */
if (size > self->size) {
- fill_vn_fl(self->vec + self->size, size - self->size, 0.0f);
+ copy_vn_fl(self->vec + self->size, size - self->size, 0.0f);
}
self->size = size;
@@ -462,7 +465,7 @@ static PyObject *Vector_resized(VectorObject *self, PyObject *value)
return NULL;
}
- fill_vn_fl(vec, size, 0.0f);
+ copy_vn_fl(vec, size, 0.0f);
memcpy(vec, self->vec, self->size * sizeof(float));
return Vector_CreatePyObject_alloc(vec, size, NULL);
@@ -475,7 +478,7 @@ PyDoc_STRVAR(Vector_resize_2d_doc,
);
static PyObject *Vector_resize_2d(VectorObject *self)
{
- if (self->wrapped == Py_WRAP) {
+ if (self->flag & BASE_MATH_FLAG_IS_WRAP) {
PyErr_SetString(PyExc_TypeError,
"Vector.resize_2d(): "
"cannot resize wrapped data - only python vectors");
@@ -507,7 +510,7 @@ PyDoc_STRVAR(Vector_resize_3d_doc,
);
static PyObject *Vector_resize_3d(VectorObject *self)
{
- if (self->wrapped == Py_WRAP) {
+ if (self->flag & BASE_MATH_FLAG_IS_WRAP) {
PyErr_SetString(PyExc_TypeError,
"Vector.resize_3d(): "
"cannot resize wrapped data - only python vectors");
@@ -542,7 +545,7 @@ PyDoc_STRVAR(Vector_resize_4d_doc,
);
static PyObject *Vector_resize_4d(VectorObject *self)
{
- if (self->wrapped == Py_WRAP) {
+ if (self->flag & BASE_MATH_FLAG_IS_WRAP) {
PyErr_SetString(PyExc_TypeError,
"Vector.resize_4d(): "
"cannot resize wrapped data - only python vectors");
@@ -586,7 +589,7 @@ static PyObject *Vector_to_2d(VectorObject *self)
if (BaseMath_ReadCallback(self) == -1)
return NULL;
- return Vector_CreatePyObject(self->vec, 2, Py_NEW, Py_TYPE(self));
+ return Vector_CreatePyObject(self->vec, 2, Py_TYPE(self));
}
PyDoc_STRVAR(Vector_to_3d_doc,
".. method:: to_3d()\n"
@@ -604,7 +607,7 @@ static PyObject *Vector_to_3d(VectorObject *self)
return NULL;
memcpy(tvec, self->vec, sizeof(float) * MIN2(self->size, 3));
- return Vector_CreatePyObject(tvec, 3, Py_NEW, Py_TYPE(self));
+ return Vector_CreatePyObject(tvec, 3, Py_TYPE(self));
}
PyDoc_STRVAR(Vector_to_4d_doc,
".. method:: to_4d()\n"
@@ -622,7 +625,7 @@ static PyObject *Vector_to_4d(VectorObject *self)
return NULL;
memcpy(tvec, self->vec, sizeof(float) * MIN2(self->size, 4));
- return Vector_CreatePyObject(tvec, 4, Py_NEW, Py_TYPE(self));
+ return Vector_CreatePyObject(tvec, 4, Py_TYPE(self));
}
PyDoc_STRVAR(Vector_to_tuple_doc,
@@ -797,7 +800,7 @@ static PyObject *Vector_to_track_quat(VectorObject *self, PyObject *args)
vec_to_quat(quat, vec, track, up);
- return Quaternion_CreatePyObject(quat, Py_NEW, NULL);
+ return Quaternion_CreatePyObject(quat, NULL);
}
PyDoc_STRVAR(Vector_orthogonal_doc,
@@ -829,7 +832,7 @@ static PyObject *Vector_orthogonal(VectorObject *self)
else
ortho_v2_v2(vec, self->vec);
- return Vector_CreatePyObject(vec, self->size, Py_NEW, Py_TYPE(self));
+ return Vector_CreatePyObject(vec, self->size, Py_TYPE(self));
}
@@ -877,7 +880,7 @@ static PyObject *Vector_reflect(VectorObject *self, PyObject *value)
normalize_v3(mirror);
reflect_v3_v3v3(reflect, vec, mirror);
- return Vector_CreatePyObject(reflect, self->size, Py_NEW, Py_TYPE(self));
+ return Vector_CreatePyObject(reflect, self->size, Py_TYPE(self));
}
PyDoc_STRVAR(Vector_cross_doc,
@@ -910,7 +913,7 @@ static PyObject *Vector_cross(VectorObject *self, PyObject *value)
return NULL;
if (self->size == 3) {
- ret = Vector_CreatePyObject(NULL, 3, Py_NEW, Py_TYPE(self));
+ ret = Vector_CreatePyObject(NULL, 3, Py_TYPE(self));
cross_v3_v3v3(((VectorObject *)ret)->vec, self->vec, tvec);
}
else {
@@ -954,13 +957,11 @@ PyDoc_STRVAR(Vector_angle_doc,
"\n"
" :arg other: another vector to compare the angle with\n"
" :type other: :class:`Vector`\n"
-" :arg fallback: return this value when the angle can't be calculated\n"
-" (zero length vector)\n"
+" :arg fallback: return this when the angle can't be calculated (zero length vector),\n"
+" (instead of raising a :exc:`ValueError`).\n"
" :type fallback: any\n"
" :return: angle in radians or fallback when given\n"
" :rtype: float\n"
-"\n"
-" .. note:: Zero length vectors raise an :exc:`ValueError`.\n"
);
static PyObject *Vector_angle(VectorObject *self, PyObject *args)
{
@@ -1018,13 +1019,11 @@ PyDoc_STRVAR(Vector_angle_signed_doc,
"\n"
" :arg other: another vector to compare the angle with\n"
" :type other: :class:`Vector`\n"
-" :arg fallback: return this value when the angle can't be calculated\n"
-" (zero length vector)\n"
+" :arg fallback: return this when the angle can't be calculated (zero length vector),\n"
+" (instead of raising a :exc:`ValueError`).\n"
" :type fallback: any\n"
" :return: angle in radians or fallback when given\n"
" :rtype: float\n"
-"\n"
-" .. note:: Zero length vectors raise an :exc:`ValueError`.\n"
);
static PyObject *Vector_angle_signed(VectorObject *self, PyObject *args)
{
@@ -1102,7 +1101,7 @@ static PyObject *Vector_rotation_difference(VectorObject *self, PyObject *value)
rotation_between_vecs_to_quat(quat, vec_a, vec_b);
- return Quaternion_CreatePyObject(quat, Py_NEW, NULL);
+ return Quaternion_CreatePyObject(quat, NULL);
}
PyDoc_STRVAR(Vector_project_doc,
@@ -1123,9 +1122,6 @@ static PyObject *Vector_project(VectorObject *self, PyObject *value)
double dot = 0.0f, dot2 = 0.0f;
int x;
- if (BaseMath_ReadCallback(self) == -1)
- return NULL;
-
if (mathutils_array_parse(tvec, size, size, value, "Vector.project(other), invalid 'other' arg") == -1)
return NULL;
@@ -1148,7 +1144,7 @@ static PyObject *Vector_project(VectorObject *self, PyObject *value)
for (x = 0; x < size; x++) {
vec[x] = (float)dot * tvec[x];
}
- return Vector_CreatePyObject(vec, size, Py_NEW, Py_TYPE(self));
+ return Vector_CreatePyObject(vec, size, Py_TYPE(self));
}
PyDoc_STRVAR(Vector_lerp_doc,
@@ -1167,9 +1163,8 @@ static PyObject *Vector_lerp(VectorObject *self, PyObject *args)
{
const int size = self->size;
PyObject *value = NULL;
- float fac, ifac;
- float *tvec, *vec;
- int x;
+ float fac;
+ float *tvec;
if (!PyArg_ParseTuple(args, "Of:lerp", &value, &fac))
return NULL;
@@ -1182,23 +1177,9 @@ static PyObject *Vector_lerp(VectorObject *self, PyObject *args)
return NULL;
}
- vec = PyMem_Malloc(size * sizeof(float));
- if (vec == NULL) {
- PyErr_SetString(PyExc_MemoryError,
- "Vector.lerp(): "
- "problem allocating pointer space");
- return NULL;
- }
-
- ifac = 1.0f - fac;
-
- for (x = 0; x < size; x++) {
- vec[x] = (ifac * self->vec[x]) + (fac * tvec[x]);
- }
-
- PyMem_Free(tvec);
+ interp_vn_vn(tvec, self->vec, 1.0f - fac, size);
- return Vector_CreatePyObject_alloc(vec, size, Py_TYPE(self));
+ return Vector_CreatePyObject_alloc(tvec, size, Py_TYPE(self));
}
PyDoc_STRVAR(Vector_slerp_doc,
@@ -1210,8 +1191,8 @@ PyDoc_STRVAR(Vector_slerp_doc,
" :type other: :class:`Vector`\n"
" :arg factor: The interpolation value typically in [0.0, 1.0].\n"
" :type factor: float\n"
-" :arg fallback: return this value when the vector can't be calculated\n"
-" (zero length vector or direct opposites)\n"
+" :arg fallback: return this when the vector can't be calculated (zero length vector or direct opposites),\n"
+" (instead of raising a :exc:`ValueError`).\n"
" :type fallback: any\n"
" :return: The interpolated vector.\n"
" :rtype: :class:`Vector`\n"
@@ -1287,7 +1268,7 @@ static PyObject *Vector_slerp(VectorObject *self, PyObject *args)
ret_vec[x] = (w[0] * self_vec[x]) + (w[1] * other_vec[x]);
}
- return Vector_CreatePyObject(ret_vec, size, Py_NEW, Py_TYPE(self));
+ return Vector_CreatePyObject(ret_vec, size, Py_TYPE(self));
}
PyDoc_STRVAR(Vector_rotate_doc,
@@ -1302,7 +1283,7 @@ static PyObject *Vector_rotate(VectorObject *self, PyObject *value)
{
float other_rmat[3][3];
- if (BaseMath_ReadCallback(self) == -1)
+ if (BaseMath_ReadCallback_ForWrite(self) == -1)
return NULL;
if (mathutils_any_to_rotmat(other_rmat, value, "Vector.rotate(value)") == -1)
@@ -1336,7 +1317,7 @@ static PyObject *Vector_copy(VectorObject *self)
if (BaseMath_ReadCallback(self) == -1)
return NULL;
- return Vector_CreatePyObject(self->vec, self->size, Py_NEW, Py_TYPE(self));
+ return Vector_CreatePyObject(self->vec, self->size, Py_TYPE(self));
}
static PyObject *Vector_deepcopy(VectorObject *self, PyObject *args)
{
@@ -1420,6 +1401,10 @@ static PyObject *Vector_item(VectorObject *self, int i)
static int vector_ass_item_internal(VectorObject *self, int i, PyObject *value, const bool is_attr)
{
float scalar;
+
+ if (BaseMath_Prepare_ForWrite(self) == -1)
+ return -1;
+
if ((scalar = PyFloat_AsDouble(value)) == -1.0f && PyErr_Occurred()) { /* parsed item not a number */
PyErr_SetString(PyExc_TypeError,
"vector[index] = x: "
@@ -1481,7 +1466,7 @@ static int Vector_ass_slice(VectorObject *self, int begin, int end, PyObject *se
int size = 0;
float *vec = NULL;
- if (BaseMath_ReadCallback(self) == -1)
+ if (BaseMath_ReadCallback_ForWrite(self) == -1)
return -1;
CLAMP(begin, 0, self->size);
@@ -1540,8 +1525,7 @@ static PyObject *Vector_add(PyObject *v1, PyObject *v2)
}
vec = PyMem_Malloc(vec1->size * sizeof(float));
-
- if (vec == NULL) { /*allocation failure*/
+ if (vec == NULL) {
PyErr_SetString(PyExc_MemoryError,
"Vector(): "
"problem allocating pointer space");
@@ -1575,7 +1559,7 @@ static PyObject *Vector_iadd(PyObject *v1, PyObject *v2)
return NULL;
}
- if (BaseMath_ReadCallback(vec1) == -1 || BaseMath_ReadCallback(vec2) == -1)
+ if (BaseMath_ReadCallback_ForWrite(vec1) == -1 || BaseMath_ReadCallback(vec2) == -1)
return NULL;
add_vn_vn(vec1->vec, vec2->vec, vec1->size);
@@ -1612,8 +1596,7 @@ static PyObject *Vector_sub(PyObject *v1, PyObject *v2)
}
vec = PyMem_Malloc(vec1->size * sizeof(float));
-
- if (vec == NULL) { /*allocation failure*/
+ if (vec == NULL) {
PyErr_SetString(PyExc_MemoryError,
"Vector(): "
"problem allocating pointer space");
@@ -1647,7 +1630,7 @@ static PyObject *Vector_isub(PyObject *v1, PyObject *v2)
return NULL;
}
- if (BaseMath_ReadCallback(vec1) == -1 || BaseMath_ReadCallback(vec2) == -1)
+ if (BaseMath_ReadCallback_ForWrite(vec1) == -1 || BaseMath_ReadCallback(vec2) == -1)
return NULL;
sub_vn_vn(vec1->vec, vec2->vec, vec1->size);
@@ -1705,8 +1688,7 @@ int column_vector_multiplication(float r_vec[MAX_DIMENSIONS], VectorObject *vec,
static PyObject *vector_mul_float(VectorObject *vec, const float scalar)
{
float *tvec = PyMem_Malloc(vec->size * sizeof(float));
-
- if (tvec == NULL) { /*allocation failure*/
+ if (tvec == NULL) {
PyErr_SetString(PyExc_MemoryError,
"vec * float: "
"problem allocating pointer space");
@@ -1765,7 +1747,7 @@ static PyObject *Vector_mul(PyObject *v1, PyObject *v2)
vec_size = ((MatrixObject *)v2)->num_col;
}
- return Vector_CreatePyObject(tvec, vec_size, Py_NEW, Py_TYPE(vec1));
+ return Vector_CreatePyObject(tvec, vec_size, Py_TYPE(vec1));
}
else if (QuaternionObject_Check(v2)) {
/* VEC * QUAT */
@@ -1791,7 +1773,7 @@ static PyObject *Vector_mul(PyObject *v1, PyObject *v2)
copy_v3_v3(tvec, vec1->vec);
mul_qt_v3(quat2->quat, tvec);
- return Vector_CreatePyObject(tvec, 3, Py_NEW, Py_TYPE(vec1));
+ return Vector_CreatePyObject(tvec, 3, Py_TYPE(vec1));
#endif
/* ------ to be removed ------*/
}
@@ -1821,7 +1803,7 @@ static PyObject *Vector_imul(PyObject *v1, PyObject *v2)
VectorObject *vec = (VectorObject *)v1;
float scalar;
- if (BaseMath_ReadCallback(vec) == -1)
+ if (BaseMath_ReadCallback_ForWrite(vec) == -1)
return NULL;
/* only support vec*=float and vec*=mat
@@ -1923,7 +1905,7 @@ static PyObject *Vector_div(PyObject *v1, PyObject *v2)
vec = PyMem_Malloc(vec1->size * sizeof(float));
- if (vec == NULL) { /*allocation failure*/
+ if (vec == NULL) {
PyErr_SetString(PyExc_MemoryError,
"vec / value: "
"problem allocating pointer space");
@@ -1941,7 +1923,7 @@ static PyObject *Vector_idiv(PyObject *v1, PyObject *v2)
float scalar;
VectorObject *vec1 = (VectorObject *)v1;
- if (BaseMath_ReadCallback(vec1) == -1)
+ if (BaseMath_ReadCallback_ForWrite(vec1) == -1)
return NULL;
if ((scalar = PyFloat_AsDouble(v2)) == -1.0f && PyErr_Occurred()) { /* parsed item not a number */
@@ -2065,6 +2047,17 @@ static PyObject *Vector_richcmpr(PyObject *objectA, PyObject *objectB, int compa
}
}
+static Py_hash_t Vector_hash(VectorObject *self)
+{
+ if (BaseMath_ReadCallback(self) == -1)
+ return -1;
+
+ if (BaseMathObject_Prepare_ForHash(self) == -1)
+ return -1;
+
+ return mathutils_array_hash(self->vec, self->size);
+}
+
/*-----------------PROTCOL DECLARATIONS--------------------------*/
static PySequenceMethods Vector_SeqMethods = {
(lenfunc) Vector_len, /* sq_length */
@@ -2228,7 +2221,7 @@ static int Vector_length_set(VectorObject *self, PyObject *value)
{
double dot = 0.0f, param;
- if (BaseMath_ReadCallback(self) == -1)
+ if (BaseMath_ReadCallback_ForWrite(self) == -1)
return -1;
if ((param = PyFloat_AsDouble(value)) == -1.0 && PyErr_Occurred()) {
@@ -2243,7 +2236,7 @@ static int Vector_length_set(VectorObject *self, PyObject *value)
return -1;
}
if (param == 0.0) {
- fill_vn_fl(self->vec, self->size, 0.0f);
+ copy_vn_fl(self->vec, self->size, 0.0f);
return 0;
}
@@ -2308,7 +2301,7 @@ static PyObject *Vector_swizzle_get(VectorObject *self, void *closure)
axis_to++;
}
- return Vector_CreatePyObject(vec, axis_to, Py_NEW, Py_TYPE(self));
+ return Vector_CreatePyObject(vec, axis_to, Py_TYPE(self));
}
/* Set the items of this vector using a swizzle.
@@ -2334,7 +2327,7 @@ static int Vector_swizzle_set(VectorObject *self, PyObject *value, void *closure
float tvec[MAX_DIMENSIONS];
float vec_assign[MAX_DIMENSIONS];
- if (BaseMath_ReadCallback(self) == -1)
+ if (BaseMath_ReadCallback_ForWrite(self) == -1)
return -1;
/* Check that the closure can be used with this vector: even 2D vectors have
@@ -2415,6 +2408,7 @@ static PyGetSetDef Vector_getseters[] = {
{(char *)"length_squared", (getter)Vector_length_squared_get, (setter)NULL, Vector_length_squared_doc, NULL},
{(char *)"magnitude", (getter)Vector_length_get, (setter)Vector_length_set, Vector_length_doc, NULL},
{(char *)"is_wrapped", (getter)BaseMathObject_is_wrapped_get, (setter)NULL, BaseMathObject_is_wrapped_doc, NULL},
+ {(char *)"is_frozen", (getter)BaseMathObject_is_frozen_get, (setter)NULL, BaseMathObject_is_frozen_doc, NULL},
{(char *)"owner", (getter)BaseMathObject_owner_get, (setter)NULL, BaseMathObject_owner_doc, NULL},
/* autogenerated swizzle attrs, see python script below */
@@ -2893,6 +2887,9 @@ static struct PyMethodDef Vector_methods[] = {
{"slerp", (PyCFunction) Vector_slerp, METH_VARARGS, Vector_slerp_doc},
{"rotate", (PyCFunction) Vector_rotate, METH_O, Vector_rotate_doc},
+ /* base-math methods */
+ {"freeze", (PyCFunction)BaseMathObject_freeze, METH_NOARGS, BaseMathObject_freeze_doc},
+
{"copy", (PyCFunction) Vector_copy, METH_NOARGS, Vector_copy_doc},
{"__copy__", (PyCFunction) Vector_copy, METH_NOARGS, NULL},
{"__deepcopy__", (PyCFunction) Vector_deepcopy, METH_VARARGS, NULL},
@@ -2907,7 +2904,12 @@ static struct PyMethodDef Vector_methods[] = {
*/
PyDoc_STRVAR(vector_doc,
-"This object gives access to Vectors in Blender."
+".. class:: Vector(seq)\n"
+"\n"
+" This object gives access to Vectors in Blender.\n"
+"\n"
+" :param seq: Components of the vector, must be a sequence of at least two\n"
+" :type seq: sequence of numbers\n"
);
PyTypeObject vector_Type = {
PyVarObject_HEAD_INIT(NULL, 0)
@@ -2933,7 +2935,7 @@ PyTypeObject vector_Type = {
/* More standard operations (here for binary compatibility) */
- NULL, /* hashfunc tp_hash; */
+ (hashfunc)Vector_hash, /* hashfunc tp_hash; */
NULL, /* ternaryfunc tp_call; */
#ifndef MATH_STANDALONE
(reprfunc)Vector_str, /* reprfunc tp_str; */
@@ -2994,15 +2996,12 @@ PyTypeObject vector_Type = {
NULL
};
-/*------------------------Vector_CreatePyObject (internal)-------------
- * creates a new vector object
- * pass Py_WRAP - if vector is a WRAPPER for data allocated by BLENDER
- * (i.e. it was allocated elsewhere by MEM_mallocN())
- * pass Py_NEW - if vector is not a WRAPPER and managed by PYTHON
- * (i.e. it must be created here with PyMEM_malloc())*/
-PyObject *Vector_CreatePyObject(float *vec, const int size, const int type, PyTypeObject *base_type)
+PyObject *Vector_CreatePyObject(
+ const float *vec, const int size,
+ PyTypeObject *base_type)
{
VectorObject *self;
+ float *vec_alloc;
if (size < 2) {
PyErr_SetString(PyExc_RuntimeError,
@@ -3010,44 +3009,72 @@ PyObject *Vector_CreatePyObject(float *vec, const int size, const int type, PyTy
return NULL;
}
- self = base_type ? (VectorObject *)base_type->tp_alloc(base_type, 0) :
- (VectorObject *)PyObject_GC_New(VectorObject, &vector_Type);
+ vec_alloc = PyMem_Malloc(size * sizeof(float));
+ if (UNLIKELY(vec_alloc == NULL)) {
+ PyErr_SetString(PyExc_MemoryError,
+ "Vector(): "
+ "problem allocating data");
+ return NULL;
+ }
+ self = BASE_MATH_NEW(VectorObject, vector_Type, base_type);
if (self) {
+ self->vec = vec_alloc;
self->size = size;
/* init callbacks as NULL */
self->cb_user = NULL;
self->cb_type = self->cb_subtype = 0;
- if (type == Py_WRAP) {
- self->vec = vec;
- self->wrapped = Py_WRAP;
+ if (vec) {
+ memcpy(self->vec, vec, size * sizeof(float));
}
- else if (type == Py_NEW) {
- self->vec = PyMem_Malloc(size * sizeof(float));
- if (vec) {
- memcpy(self->vec, vec, size * sizeof(float));
+ else { /* new empty */
+ copy_vn_fl(self->vec, size, 0.0f);
+ if (size == 4) { /* do the homogeneous thing */
+ self->vec[3] = 1.0f;
}
- else { /* new empty */
- fill_vn_fl(self->vec, size, 0.0f);
- if (size == 4) { /* do the homogeneous thing */
- self->vec[3] = 1.0f;
- }
- }
- self->wrapped = Py_NEW;
- }
- else {
- Py_FatalError("Vector(): invalid type!");
}
+ self->flag = BASE_MATH_FLAG_DEFAULT;
+ }
+ else {
+ PyMem_Free(vec_alloc);
+ }
+
+ return (PyObject *)self;
+}
+
+PyObject *Vector_CreatePyObject_wrap(
+ float *vec, const int size,
+ PyTypeObject *base_type)
+{
+ VectorObject *self;
+
+ if (size < 2) {
+ PyErr_SetString(PyExc_RuntimeError,
+ "Vector(): invalid size");
+ return NULL;
+ }
+
+ self = BASE_MATH_NEW(VectorObject, vector_Type, base_type);
+ if (self) {
+ self->size = size;
+
+ /* init callbacks as NULL */
+ self->cb_user = NULL;
+ self->cb_type = self->cb_subtype = 0;
+
+ self->vec = vec;
+ self->flag = BASE_MATH_FLAG_DEFAULT | BASE_MATH_FLAG_IS_WRAP;
}
return (PyObject *) self;
}
-PyObject *Vector_CreatePyObject_cb(PyObject *cb_user, int size, unsigned char cb_type, unsigned char cb_subtype)
+PyObject *Vector_CreatePyObject_cb(
+ PyObject *cb_user, int size,
+ unsigned char cb_type, unsigned char cb_subtype)
{
- float dummy[4] = {0.0, 0.0, 0.0, 0.0}; /* dummy init vector, callbacks will be used on access */
- VectorObject *self = (VectorObject *)Vector_CreatePyObject(dummy, size, Py_NEW, NULL);
+ VectorObject *self = (VectorObject *)Vector_CreatePyObject(NULL, size, NULL);
if (self) {
Py_INCREF(cb_user);
self->cb_user = cb_user;
@@ -3059,11 +3086,15 @@ PyObject *Vector_CreatePyObject_cb(PyObject *cb_user, int size, unsigned char cb
return (PyObject *)self;
}
-PyObject *Vector_CreatePyObject_alloc(const float *vec, const int size, PyTypeObject *base_type)
+PyObject *Vector_CreatePyObject_alloc(
+ float *vec, const int size,
+ PyTypeObject *base_type)
{
- VectorObject *vect_ob;
- vect_ob = (VectorObject *)Vector_CreatePyObject((float *)vec, size, Py_WRAP, base_type);
- vect_ob->wrapped = Py_NEW;
+ VectorObject *self;
+ self = (VectorObject *)Vector_CreatePyObject_wrap(vec, size, base_type);
+ if (self) {
+ self->flag = BASE_MATH_FLAG_DEFAULT;
+ }
- return (PyObject *)vect_ob;
+ return (PyObject *)self;
}
diff --git a/source/blender/python/mathutils/mathutils_Vector.h b/source/blender/python/mathutils/mathutils_Vector.h
index 2074270670a..74ca3336f4b 100644
--- a/source/blender/python/mathutils/mathutils_Vector.h
+++ b/source/blender/python/mathutils/mathutils_Vector.h
@@ -34,13 +34,25 @@ extern PyTypeObject vector_Type;
typedef struct {
BASE_MATH_MEMBERS(vec);
- int size; /* vec size 2,3 or 4 */
+ int size; /* vec size 2 or more */
} VectorObject;
/*prototypes*/
-PyObject *Vector_CreatePyObject(float *vec, const int size, const int type, PyTypeObject *base_type);
-PyObject *Vector_CreatePyObject_cb(PyObject *user, int size,
- unsigned char cb_type, unsigned char subtype);
-PyObject *Vector_CreatePyObject_alloc(const float *vec, const int size, PyTypeObject *base_type);
+PyObject *Vector_CreatePyObject(
+ const float *vec, const int size,
+ PyTypeObject *base_type
+ ) ATTR_WARN_UNUSED_RESULT;
+PyObject *Vector_CreatePyObject_wrap(
+ float *vec, const int size,
+ PyTypeObject *base_type
+ ) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1);
+PyObject *Vector_CreatePyObject_cb(
+ PyObject *user, int size,
+ unsigned char cb_type, unsigned char subtype
+ ) ATTR_WARN_UNUSED_RESULT;
+PyObject *Vector_CreatePyObject_alloc(
+ float *vec, const int size,
+ PyTypeObject *base_type
+ ) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1);
#endif /* __MATHUTILS_VECTOR_H__ */
diff --git a/source/blender/python/mathutils/mathutils_bvhtree.c b/source/blender/python/mathutils/mathutils_bvhtree.c
new file mode 100644
index 00000000000..bf06b889e25
--- /dev/null
+++ b/source/blender/python/mathutils/mathutils_bvhtree.c
@@ -0,0 +1,1233 @@
+/*
+ * ***** 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): Lukas Toenne, Campbell Barton
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/python/mathutils/mathutils_bvhtree.c
+ * \ingroup mathutils
+ *
+ * This file defines the 'mathutils.bvhtree' module, a general purpose module to access
+ * blenders bvhtree for mesh surface nearest-element search and ray casting.
+ */
+
+#include <Python.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_utildefines.h"
+#include "BLI_kdopbvh.h"
+#include "BLI_polyfill2d.h"
+#include "BLI_math.h"
+#include "BLI_ghash.h"
+#include "BLI_memarena.h"
+
+#include "BKE_bvhutils.h"
+
+#include "../generic/py_capi_utils.h"
+#include "../generic/python_utildefines.h"
+
+#include "mathutils.h"
+#include "mathutils_bvhtree.h" /* own include */
+
+#ifndef MATH_STANDALONE
+#include "DNA_object_types.h"
+
+#include "BKE_customdata.h"
+#include "BKE_DerivedMesh.h"
+#include "BKE_editmesh_bvh.h"
+
+#include "bmesh.h"
+
+#include "../bmesh/bmesh_py_types.h"
+#endif /* MATH_STANDALONE */
+
+
+#include "BLI_strict_flags.h"
+
+
+/* -------------------------------------------------------------------- */
+
+/** \name Docstring (snippets)
+ * \{ */
+
+#define PYBVH_FIND_GENERIC_DISTANCE_DOC \
+" :arg distance: Maximum distance threshold.\n" \
+" :type distance: float\n"
+
+#define PYBVH_FIND_GENERIC_RETURN_DOC \
+" :return: Returns a tuple (:class:`Vector` location, :class:`Vector` normal, int index, float distance),\n" \
+" Values will all be None if no hit is found.\n" \
+" :rtype: :class:`tuple`\n"
+
+#define PYBVH_FROM_GENERIC_EPSILON_DOC \
+" :arg epsilon: Increase the threshold for detecting overlap and raycast hits.\n" \
+" :type epsilon: float\n"
+
+/** \} */
+
+/* sqrt(FLT_MAX) */
+#define PYBVH_MAX_DIST_STR "1.84467e+19"
+static const float max_dist_default = 1.844674352395373e+19f;
+
+static const char PY_BVH_TREE_TYPE_DEFAULT = 4;
+static const char PY_BVH_AXIS_DEFAULT = 6;
+
+typedef struct {
+ PyObject_HEAD
+ BVHTree *tree;
+ float epsilon;
+
+ float (*coords)[3];
+ unsigned int (*tris)[3];
+ unsigned int coords_len, tris_len;
+
+ /* Optional members */
+ /* aligned with 'tris' */
+ int *orig_index;
+ /* aligned with array that 'orig_index' points to */
+ float (*orig_normal)[3];
+} PyBVHTree;
+
+
+/* -------------------------------------------------------------------- */
+
+/** \name Utility helper functions
+ * \{ */
+
+static PyObject *bvhtree_CreatePyObject(
+ BVHTree *tree, float epsilon,
+
+ float (*coords)[3], unsigned int coords_len,
+ unsigned int (*tris)[3], unsigned int tris_len,
+
+ /* optional arrays */
+ int *orig_index, float (*orig_normal)[3])
+{
+ PyBVHTree *result = PyObject_New(PyBVHTree, &PyBVHTree_Type);
+
+ result->tree = tree;
+ result->epsilon = epsilon;
+
+ result->coords = coords;
+ result->tris = tris;
+ result->coords_len = coords_len;
+ result->tris_len = tris_len;
+
+ result->orig_index = orig_index;
+ result->orig_normal = orig_normal;
+
+ return (PyObject *)result;
+}
+
+/** \} */
+
+
+/* -------------------------------------------------------------------- */
+
+/** \name BVHTreeRayHit to Python utilities
+ * \{ */
+
+static void py_bvhtree_raycast_to_py_tuple(const BVHTreeRayHit *hit, PyObject *py_retval)
+{
+ BLI_assert(hit->index >= 0);
+ BLI_assert(PyTuple_GET_SIZE(py_retval) == 4);
+
+ PyTuple_SET_ITEMS(py_retval,
+ Vector_CreatePyObject(hit->co, 3, NULL),
+ Vector_CreatePyObject(hit->no, 3, NULL),
+ PyLong_FromLong(hit->index),
+ PyFloat_FromDouble(hit->dist));
+
+}
+
+static PyObject *py_bvhtree_raycast_to_py(const BVHTreeRayHit *hit)
+{
+ PyObject *py_retval = PyTuple_New(4);
+
+ py_bvhtree_raycast_to_py_tuple(hit, py_retval);
+
+ return py_retval;
+}
+
+static PyObject *py_bvhtree_raycast_to_py_none(void)
+{
+ PyObject *py_retval = PyTuple_New(4);
+
+ PyC_Tuple_Fill(py_retval, Py_None);
+
+ return py_retval;
+}
+
+#if 0
+static PyObject *py_bvhtree_raycast_to_py_and_check(const BVHTreeRayHit *hit)
+{
+ PyObject *py_retval;
+
+ py_retval = PyTuple_New(4);
+
+ if (hit->index != -1) {
+ py_bvhtree_raycast_to_py_tuple(hit, py_retval);
+ }
+ else {
+ PyC_Tuple_Fill(py_retval, Py_None);
+ }
+
+ return py_retval;
+}
+#endif
+
+/** \} */
+
+
+/* -------------------------------------------------------------------- */
+
+/** \name BVHTreeNearest to Python utilities
+ * \{ */
+
+static void py_bvhtree_nearest_to_py_tuple(const BVHTreeNearest *nearest, PyObject *py_retval)
+{
+ BLI_assert(nearest->index >= 0);
+ BLI_assert(PyTuple_GET_SIZE(py_retval) == 4);
+
+ PyTuple_SET_ITEMS(py_retval,
+ Vector_CreatePyObject(nearest->co, 3, NULL),
+ Vector_CreatePyObject(nearest->no, 3, NULL),
+ PyLong_FromLong(nearest->index),
+ PyFloat_FromDouble(sqrtf(nearest->dist_sq)));
+
+}
+
+static PyObject *py_bvhtree_nearest_to_py(const BVHTreeNearest *nearest)
+{
+ PyObject *py_retval = PyTuple_New(4);
+
+ py_bvhtree_nearest_to_py_tuple(nearest, py_retval);
+
+ return py_retval;
+}
+
+static PyObject *py_bvhtree_nearest_to_py_none(void)
+{
+ PyObject *py_retval = PyTuple_New(4);
+
+ PyC_Tuple_Fill(py_retval, Py_None);
+
+ return py_retval;
+}
+
+#if 0
+static PyObject *py_bvhtree_nearest_to_py_and_check(const BVHTreeNearest *nearest)
+{
+ PyObject *py_retval;
+
+ py_retval = PyTuple_New(4);
+
+ if (nearest->index != -1) {
+ py_bvhtree_nearest_to_py_tuple(nearest, py_retval);
+ }
+ else {
+ PyC_Tuple_Fill(py_retval, Py_None);
+ }
+
+ return py_retval;
+}
+#endif
+
+/** \} */
+
+static void py_bvhtree__tp_dealloc(PyBVHTree *self)
+{
+ if (self->tree) {
+ BLI_bvhtree_free(self->tree);
+ }
+
+ MEM_SAFE_FREE(self->coords);
+ MEM_SAFE_FREE(self->tris);
+
+ MEM_SAFE_FREE(self->orig_index);
+ MEM_SAFE_FREE(self->orig_normal);
+
+ Py_TYPE(self)->tp_free((PyObject *)self);
+}
+
+
+/* -------------------------------------------------------------------- */
+
+/** \name Methods
+ * \{ */
+
+static void py_bvhtree_raycast_cb(void *userdata, int index, const BVHTreeRay *ray, BVHTreeRayHit *hit)
+{
+ const PyBVHTree *self = userdata;
+
+ const float (*coords)[3] = (const float (*)[3])self->coords;
+ const unsigned int *tri = self->tris[index];
+ const float *tri_co[3] = {coords[tri[0]], coords[tri[1]], coords[tri[2]]};
+ float dist;
+
+ if (self->epsilon == 0.0f) {
+ dist = bvhtree_ray_tri_intersection(ray, hit->dist, UNPACK3(tri_co));
+ }
+ else {
+ dist = bvhtree_sphereray_tri_intersection(ray, self->epsilon, hit->dist, UNPACK3(tri_co));
+ }
+
+ if (dist >= 0 && dist < hit->dist) {
+ hit->index = self->orig_index ? self->orig_index[index] : index;
+ hit->dist = dist;
+ madd_v3_v3v3fl(hit->co, ray->origin, ray->direction, dist);
+ if (self->orig_normal) {
+ copy_v3_v3(hit->no, self->orig_normal[hit->index]);
+ }
+ else {
+ normal_tri_v3(hit->no, UNPACK3(tri_co));
+ }
+ }
+}
+
+static void py_bvhtree_nearest_point_cb(void *userdata, int index, const float co[3], BVHTreeNearest *nearest)
+{
+ PyBVHTree *self = userdata;
+
+ const float (*coords)[3] = (const float (*)[3])self->coords;
+ const unsigned int *tri = self->tris[index];
+ const float *tri_co[3] = {coords[tri[0]], coords[tri[1]], coords[tri[2]]};
+ float nearest_tmp[3], dist_sq;
+
+ closest_on_tri_to_point_v3(nearest_tmp, co, UNPACK3(tri_co));
+ dist_sq = len_squared_v3v3(co, nearest_tmp);
+
+ if (dist_sq < nearest->dist_sq) {
+ nearest->index = self->orig_index ? self->orig_index[index] : index;
+ nearest->dist_sq = dist_sq;
+ copy_v3_v3(nearest->co, nearest_tmp);
+ if (self->orig_normal) {
+ copy_v3_v3(nearest->no, self->orig_normal[nearest->index]);
+ }
+ else {
+ normal_tri_v3(nearest->no, UNPACK3(tri_co));
+ }
+ }
+}
+
+PyDoc_STRVAR(py_bvhtree_ray_cast_doc,
+".. method:: ray_cast(co, direction, distance=sys.float_info.max)\n"
+"\n"
+" Cast a ray onto the mesh.\n"
+"\n"
+" :arg co: Start location of the ray in object space.\n"
+" :type co: :class:`Vector`\n"
+" :arg direction: Direction of the ray in object space.\n"
+" :type direction: :class:`Vector`\n"
+PYBVH_FIND_GENERIC_DISTANCE_DOC
+PYBVH_FIND_GENERIC_RETURN_DOC
+);
+static PyObject *py_bvhtree_ray_cast(PyBVHTree *self, PyObject *args)
+{
+ const char *error_prefix = "ray_cast";
+ float co[3], direction[3];
+ float max_dist = FLT_MAX;
+ BVHTreeRayHit hit;
+
+ /* parse args */
+ {
+ PyObject *py_co, *py_direction;
+
+ if (!PyArg_ParseTuple(
+ args, (char *)"OO|f:ray_cast",
+ &py_co, &py_direction, max_dist))
+ {
+ return NULL;
+ }
+
+ if ((mathutils_array_parse(co, 2, 3 | MU_ARRAY_ZERO, py_co, error_prefix) == -1) ||
+ (mathutils_array_parse(direction, 2, 3 | MU_ARRAY_ZERO, py_direction, error_prefix) == -1))
+ {
+ return NULL;
+ }
+
+ normalize_v3(direction);
+ }
+
+ hit.dist = max_dist;
+ hit.index = -1;
+
+ /* may fail if the mesh has no faces, in that case the ray-cast misses */
+ if (self->tree) {
+ if (BLI_bvhtree_ray_cast(
+ self->tree, co, direction, 0.0f, &hit,
+ py_bvhtree_raycast_cb, self) != -1)
+ {
+ return py_bvhtree_raycast_to_py(&hit);
+ }
+ }
+
+ return py_bvhtree_raycast_to_py_none();
+}
+
+PyDoc_STRVAR(py_bvhtree_find_nearest_doc,
+".. method:: find_nearest(co, distance=" PYBVH_MAX_DIST_STR ")\n"
+"\n"
+" Find the nearest element to a point.\n"
+"\n"
+" :arg co: Find nearest element to this point.\n"
+" :type co: :class:`Vector`\n"
+PYBVH_FIND_GENERIC_DISTANCE_DOC
+PYBVH_FIND_GENERIC_RETURN_DOC
+);
+static PyObject *py_bvhtree_find_nearest(PyBVHTree *self, PyObject *args)
+{
+ const char *error_prefix = "find_nearest";
+ float co[3];
+ float max_dist = max_dist_default;
+
+ BVHTreeNearest nearest;
+
+ /* parse args */
+ {
+ PyObject *py_co;
+
+ if (!PyArg_ParseTuple(
+ args, (char *)"O|f:find_nearest",
+ &py_co, &max_dist))
+ {
+ return NULL;
+ }
+
+ if (mathutils_array_parse(co, 2, 3 | MU_ARRAY_ZERO, py_co, error_prefix) == -1) {
+ return NULL;
+ }
+ }
+
+ nearest.index = -1;
+ nearest.dist_sq = max_dist * max_dist;
+
+ /* may fail if the mesh has no faces, in that case the ray-cast misses */
+ if (self->tree) {
+ if (BLI_bvhtree_find_nearest(
+ self->tree, co, &nearest,
+ py_bvhtree_nearest_point_cb, self) != -1)
+ {
+ return py_bvhtree_nearest_to_py(&nearest);
+ }
+ }
+
+ return py_bvhtree_nearest_to_py_none();
+}
+
+BLI_INLINE unsigned int overlap_hash(const void *overlap_v)
+{
+ const BVHTreeOverlap *overlap = overlap_v;
+ /* same constants as edge-hash */
+ return (((unsigned int)overlap->indexA * 65) ^ ((unsigned int)overlap->indexA * 31));
+}
+
+BLI_INLINE bool overlap_cmp(const void *a_v, const void *b_v)
+{
+ const BVHTreeOverlap *a = a_v;
+ const BVHTreeOverlap *b = b_v;
+ return (memcmp(a, b, sizeof(*a)) != 0);
+}
+
+struct PyBVHTree_OverlapData {
+ PyBVHTree *tree_pair[2];
+ float epsilon;
+};
+
+static bool py_bvhtree_overlap_cb(void *userdata, int index_a, int index_b, int UNUSED(thread))
+{
+ struct PyBVHTree_OverlapData *data = userdata;
+ PyBVHTree *tree_a = data->tree_pair[0];
+ PyBVHTree *tree_b = data->tree_pair[1];
+ const unsigned int *tri_a = tree_a->tris[index_a];
+ const unsigned int *tri_b = tree_b->tris[index_b];
+ const float *tri_a_co[3] = {tree_a->coords[tri_a[0]], tree_a->coords[tri_a[1]], tree_a->coords[tri_a[2]]};
+ const float *tri_b_co[3] = {tree_b->coords[tri_b[0]], tree_b->coords[tri_b[1]], tree_b->coords[tri_b[2]]};
+ float ix_pair[2][3];
+ int verts_shared = 0;
+
+ if (tree_a == tree_b) {
+ if (UNLIKELY(index_a == index_b)) {
+ return false;
+ }
+
+ verts_shared = (
+ ELEM(tri_a_co[0], UNPACK3(tri_b_co)) +
+ ELEM(tri_a_co[1], UNPACK3(tri_b_co)) +
+ ELEM(tri_a_co[2], UNPACK3(tri_b_co)));
+
+ /* if 2 points are shared, bail out */
+ if (verts_shared >= 2) {
+ return false;
+ }
+ }
+
+ return (isect_tri_tri_epsilon_v3(UNPACK3(tri_a_co), UNPACK3(tri_b_co), ix_pair[0], ix_pair[1], data->epsilon) &&
+ ((verts_shared == 0) || (len_squared_v3v3(ix_pair[0], ix_pair[1]) > data->epsilon)));
+}
+
+PyDoc_STRVAR(py_bvhtree_overlap_doc,
+".. method:: overlap(other_tree)\n"
+"\n"
+" Find overlapping indices between 2 trees.\n"
+"\n"
+" :arg other_tree: Other tree to preform overlap test on.\n"
+" :type other_tree: :class:`BVHTree`\n"
+" :return: Returns a list of unique index pairs,"
+" the first index referencing this tree, the second referencing the **other_tree**.\n"
+" :rtype: :class:`list`\n"
+);
+static PyObject *py_bvhtree_overlap(PyBVHTree *self, PyBVHTree *other)
+{
+ struct PyBVHTree_OverlapData data;
+ BVHTreeOverlap *overlap;
+ unsigned int overlap_len = 0;
+ PyObject *ret;
+
+ if (!PyBVHTree_CheckExact(other)) {
+ PyErr_SetString(PyExc_ValueError, "Expected a BVHTree argument");
+ return NULL;
+ }
+
+ data.tree_pair[0] = self;
+ data.tree_pair[1] = other;
+ data.epsilon = max_ff(self->epsilon, other->epsilon);
+
+ overlap = BLI_bvhtree_overlap(self->tree, other->tree, &overlap_len, py_bvhtree_overlap_cb, &data);
+
+ ret = PyList_New(0);
+
+ if (overlap == NULL) {
+ /* pass */
+ }
+ else {
+ bool use_unique = (self->orig_index || other->orig_index);
+ GSet *pair_test = use_unique ? BLI_gset_new_ex(overlap_hash, overlap_cmp, __func__, overlap_len) : NULL;
+ /* simple case, no index remapping */
+ unsigned int i;
+
+ for (i = 0; i < overlap_len; i++) {
+ PyObject *item;
+ if (use_unique) {
+ if (self->orig_index) {
+ overlap[i].indexA = self->orig_index[overlap[i].indexA];
+ }
+ if (other->orig_index) {
+ overlap[i].indexB = other->orig_index[overlap[i].indexB];
+ }
+
+ /* skip if its already added */
+ if (!BLI_gset_add(pair_test, &overlap[i])) {
+ continue;
+ }
+ }
+
+ item = PyTuple_New(2);
+ PyTuple_SET_ITEMS(item,
+ PyLong_FromLong(overlap[i].indexA),
+ PyLong_FromLong(overlap[i].indexB));
+
+ PyList_Append(ret, item);
+ Py_DECREF(item);
+ }
+
+ if (pair_test) {
+ BLI_gset_free(pair_test, NULL);
+ }
+ }
+
+ if (overlap) {
+ MEM_freeN(overlap);
+ }
+
+ return ret;
+}
+
+/** \} */
+
+
+/* -------------------------------------------------------------------- */
+
+/** \name Class Methods
+ * \{ */
+
+PyDoc_STRVAR(C_BVHTree_FromPolygons_doc,
+".. classmethod:: FromPolygons(vertices, polygons, all_triangles=False, epsilon=0.0)\n"
+"\n"
+" BVH tree constructed geometry passed in as arguments.\n"
+"\n"
+" :arg vertices: float triplets each representing ``(x, y, z)``\n"
+" :type vertices: float triplet sequence\n"
+" :arg polygons: Sequence of polyugons, each containing indices to the vertices argument.\n"
+" :type polygons: Sequence of sequences containing ints\n"
+" :arg all_triangles: Use when all **polygons** are triangles for more efficient conversion.\n"
+" :type all_triangles: bool\n"
+PYBVH_FROM_GENERIC_EPSILON_DOC
+);
+static PyObject *C_BVHTree_FromPolygons(PyObject *UNUSED(cls), PyObject *args, PyObject *kwargs)
+{
+ const char *error_prefix = "BVHTree.FromPolygons";
+ const char *keywords[] = {"vertices", "polygons", "all_triangles", "epsilon", NULL};
+
+ PyObject *py_coords, *py_tris;
+ PyObject *py_coords_fast = NULL, *py_tris_fast = NULL;
+
+ MemArena *poly_arena = NULL;
+ MemArena *pf_arena = NULL;
+
+ float (*coords)[3] = NULL;
+ unsigned int (*tris)[3] = NULL;
+ unsigned int coords_len, tris_len;
+ float epsilon = 0.0f;
+ bool all_triangles = false;
+
+ /* when all_triangles is False */
+ int *orig_index = NULL;
+ float (*orig_normal)[3] = NULL;
+
+ unsigned int i;
+ bool valid = true;
+
+
+ if (!PyArg_ParseTupleAndKeywords(
+ args, kwargs, (char *)"OO|$O&f:BVHTree.FromPolygons", (char **)keywords,
+ &py_coords, &py_tris,
+ PyC_ParseBool, &all_triangles,
+ &epsilon))
+ {
+ return NULL;
+ }
+
+ if (!(py_coords_fast = PySequence_Fast(py_coords, error_prefix)) ||
+ !(py_tris_fast = PySequence_Fast(py_tris, error_prefix)))
+ {
+ Py_XDECREF(py_coords_fast);
+ return NULL;
+ }
+
+ if (valid) {
+ PyObject **py_coords_fast_items = PySequence_Fast_ITEMS(py_coords_fast);
+ coords_len = (unsigned int)PySequence_Fast_GET_SIZE(py_coords_fast);
+ coords = MEM_mallocN((size_t)coords_len * sizeof(*coords), __func__);
+
+ for (i = 0; i < coords_len; i++) {
+ PyObject *py_vert = py_coords_fast_items[i];
+
+ if (mathutils_array_parse(coords[i], 3, 3, py_vert, "BVHTree vertex: ") == -1) {
+ valid = false;
+ break;
+ }
+ }
+ }
+
+ if (valid == false) {
+ /* pass */
+ }
+ else if (all_triangles) {
+ /* all triangles, simple case */
+ PyObject **py_tris_fast_items = PySequence_Fast_ITEMS(py_tris_fast);
+ tris_len = (unsigned int)PySequence_Fast_GET_SIZE(py_tris_fast);
+ tris = MEM_mallocN((size_t)tris_len * sizeof(*tris), __func__);
+
+ for (i = 0; i < tris_len; i++) {
+ PyObject *py_tricoords = py_tris_fast_items[i];
+ PyObject *py_tricoords_fast;
+ PyObject **py_tricoords_fast_items;
+ unsigned int *tri = tris[i];
+ int j;
+
+ if (!(py_tricoords_fast = PySequence_Fast(py_tricoords, error_prefix))) {
+ valid = false;
+ break;
+ }
+
+ if (PySequence_Fast_GET_SIZE(py_tricoords_fast) != 3) {
+ Py_DECREF(py_tricoords_fast);
+ PyErr_Format(PyExc_ValueError,
+ "%s: non triangle found at index %d with length of %d",
+ error_prefix, i, PySequence_Fast_GET_SIZE(py_tricoords_fast));
+ valid = false;
+ break;
+ }
+
+ py_tricoords_fast_items = PySequence_Fast_ITEMS(py_tricoords_fast);
+
+ for (j = 0; j < 3; j++) {
+ tri[j] = (unsigned int)_PyLong_AsInt(py_tricoords_fast_items[j]);
+ if (UNLIKELY(tri[j] >= (unsigned int)coords_len)) {
+ PyErr_Format(PyExc_ValueError,
+ "%s: index %d must be less than %d",
+ error_prefix, tri[j], coords_len);
+
+ /* decref below */
+ valid = false;
+ break;
+ }
+ }
+
+ Py_DECREF(py_tricoords_fast);
+ }
+ }
+ else {
+ /* ngon support (much more involved) */
+ const unsigned int polys_len = (unsigned int)PySequence_Fast_GET_SIZE(py_tris_fast);
+ struct PolyLink {
+ struct PolyLink *next;
+ unsigned int len;
+ unsigned int poly[0];
+ } *plink_first = NULL, **p_plink_prev = &plink_first, *plink = NULL;
+ int poly_index;
+
+ tris_len = 0;
+
+ poly_arena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__);
+
+ for (i = 0; i < polys_len; i++) {
+ PyObject *py_tricoords = PySequence_Fast_GET_ITEM(py_tris_fast, i);
+ PyObject *py_tricoords_fast;
+ PyObject **py_tricoords_fast_items;
+ unsigned int py_tricoords_len;
+ unsigned int j;
+
+ if (!(py_tricoords_fast = PySequence_Fast(py_tricoords, error_prefix))) {
+ valid = false;
+ break;
+ }
+
+ py_tricoords_len = (unsigned int)PySequence_Fast_GET_SIZE(py_tricoords_fast);
+ py_tricoords_fast_items = PySequence_Fast_ITEMS(py_tricoords_fast);
+
+ plink = BLI_memarena_alloc(poly_arena, sizeof(*plink) + (sizeof(int) * (size_t)py_tricoords_len));
+
+ plink->len = (unsigned int)py_tricoords_len;
+ *p_plink_prev = plink;
+ p_plink_prev = &plink->next;
+
+ for (j = 0; j < py_tricoords_len; j++) {
+ plink->poly[j] = (unsigned int)_PyLong_AsInt(py_tricoords_fast_items[j]);
+ if (UNLIKELY(plink->poly[j] >= (unsigned int)coords_len)) {
+ PyErr_Format(PyExc_ValueError,
+ "%s: index %d must be less than %d",
+ error_prefix, plink->poly[j], coords_len);
+
+ Py_DECREF(py_tricoords_fast);
+ valid = false;
+ break;
+ }
+ }
+
+ if (py_tricoords_len >= 3) {
+ tris_len += (py_tricoords_len - 2);
+ }
+ }
+ *p_plink_prev = NULL;
+
+ /* all ngon's are parsed, now tessellate */
+
+ pf_arena = BLI_memarena_new(BLI_POLYFILL_ARENA_SIZE, __func__);
+ tris = MEM_mallocN(sizeof(*tris) * (size_t)tris_len, __func__);
+
+ orig_index = MEM_mallocN(sizeof(*orig_index) * (size_t)tris_len, __func__);
+ orig_normal = MEM_mallocN(sizeof(*orig_normal) * (size_t)polys_len, __func__);
+
+ for (plink = plink_first, poly_index = 0, i = 0; plink; plink = plink->next, poly_index++) {
+ if (plink->len == 3) {
+ unsigned int *tri = tris[i];
+ memcpy(tri, plink->poly, sizeof(unsigned int[3]));
+ orig_index[i] = poly_index;
+ normal_tri_v3(orig_normal[poly_index], coords[tri[0]], coords[tri[1]], coords[tri[2]]);
+ i++;
+ }
+ else if (plink->len > 3) {
+ float (*proj_coords)[2] = BLI_memarena_alloc(pf_arena, sizeof(*proj_coords) * plink->len);
+ float *normal = orig_normal[poly_index];
+ const float *co_prev;
+ const float *co_curr;
+ float axis_mat[3][3];
+ unsigned int (*tris_offset)[3] = &tris[i];
+ unsigned int j;
+
+ /* calc normal and setup 'proj_coords' */
+ zero_v3(normal);
+ co_prev = coords[plink->poly[plink->len - 1]];
+ for (j = 0; j < plink->len; j++) {
+ co_curr = coords[plink->poly[j]];
+ add_newell_cross_v3_v3v3(normal, co_prev, co_curr);
+ co_prev = co_curr;
+ }
+ normalize_v3(normal);
+
+ axis_dominant_v3_to_m3_negate(axis_mat, normal);
+
+ for (j = 0; j < plink->len; j++) {
+ mul_v2_m3v3(proj_coords[i], axis_mat, coords[plink->poly[j]]);
+ }
+
+ BLI_polyfill_calc_arena((const float (*)[2])proj_coords, plink->len, 1, tris_offset, pf_arena);
+
+ j = plink->len - 2;
+ while (j--) {
+ unsigned int *tri = tris_offset[j];
+ /* remap to global indices */
+ tri[0] = plink->poly[tri[0]];
+ tri[1] = plink->poly[tri[1]];
+ tri[2] = plink->poly[tri[2]];
+
+ orig_index[i] = poly_index;
+ i++;
+ }
+
+ BLI_memarena_clear(pf_arena);
+ }
+ else {
+ zero_v3(orig_normal[poly_index]);
+ }
+ }
+ }
+
+ Py_DECREF(py_coords_fast);
+ Py_DECREF(py_tris_fast);
+
+ if (pf_arena) {
+ BLI_memarena_free(pf_arena);
+ }
+
+ if (poly_arena) {
+ BLI_memarena_free(poly_arena);
+ }
+
+ if (valid) {
+ BVHTree *tree;
+
+ tree = BLI_bvhtree_new((int)tris_len, epsilon, PY_BVH_TREE_TYPE_DEFAULT, PY_BVH_AXIS_DEFAULT);
+ if (tree) {
+ for (i = 0; i < tris_len; i++) {
+ float co[3][3];
+
+ copy_v3_v3(co[0], coords[tris[i][0]]);
+ copy_v3_v3(co[1], coords[tris[i][1]]);
+ copy_v3_v3(co[2], coords[tris[i][2]]);
+
+ BLI_bvhtree_insert(tree, (int)i, co[0], 3);
+ }
+
+ BLI_bvhtree_balance(tree);
+ }
+
+ return bvhtree_CreatePyObject(
+ tree, epsilon,
+ coords, coords_len,
+ tris, tris_len,
+ orig_index, orig_normal);
+ }
+ else {
+ if (coords)
+ MEM_freeN(coords);
+ if (tris)
+ MEM_freeN(tris);
+
+ return NULL;
+ }
+}
+
+
+#ifndef MATH_STANDALONE
+
+PyDoc_STRVAR(C_BVHTree_FromBMesh_doc,
+".. classmethod:: FromBMesh(bmesh, epsilon=0.0)\n"
+"\n"
+" BVH tree based on :class:`BMesh` data.\n"
+"\n"
+" :arg bmesh: BMesh data.\n"
+" :type bmesh: :class:`BMesh`\n"
+PYBVH_FROM_GENERIC_EPSILON_DOC
+);
+static PyObject *C_BVHTree_FromBMesh(PyObject *UNUSED(cls), PyObject *args, PyObject *kwargs)
+{
+ const char *keywords[] = {"bmesh", "epsilon", NULL};
+
+ BPy_BMesh *py_bm;
+
+ float (*coords)[3] = NULL;
+ unsigned int (*tris)[3] = NULL;
+ unsigned int coords_len, tris_len;
+ float epsilon = 0.0f;
+
+ BMesh *bm;
+ BMLoop *(*looptris)[3];
+
+ if (!PyArg_ParseTupleAndKeywords(
+ args, kwargs, (char *)"O!|$f:BVHTree.FromBMesh", (char **)keywords,
+ &BPy_BMesh_Type, &py_bm, &epsilon))
+ {
+ return NULL;
+ }
+
+ bm = py_bm->bm;
+
+ /* Get data for tessellation */
+ {
+ int tris_len_dummy;
+
+ coords_len = (unsigned int)bm->totvert;
+ tris_len = (unsigned int)poly_to_tri_count(bm->totface, bm->totloop);
+
+ coords = MEM_mallocN(sizeof(*coords) * (size_t)coords_len, __func__);
+ tris = MEM_mallocN(sizeof(*tris) * (size_t)tris_len, __func__);
+
+ looptris = MEM_mallocN(sizeof(*looptris) * (size_t)tris_len, __func__);
+
+ BM_bmesh_calc_tessellation(bm, looptris, &tris_len_dummy);
+ BLI_assert(tris_len_dummy == (int)tris_len);
+ }
+
+ {
+ BMIter iter;
+ BVHTree *tree;
+ unsigned int i;
+
+ int *orig_index = NULL;
+ float (*orig_normal)[3] = NULL;
+
+ tree = BLI_bvhtree_new((int)tris_len, epsilon, PY_BVH_TREE_TYPE_DEFAULT, PY_BVH_AXIS_DEFAULT);
+ if (tree) {
+ BMFace *f;
+ BMVert *v;
+
+ orig_index = MEM_mallocN(sizeof(*orig_index) * (size_t)tris_len, __func__);
+ orig_normal = MEM_mallocN(sizeof(*orig_normal) * (size_t)bm->totface, __func__);
+
+ BM_ITER_MESH_INDEX (v, &iter, bm, BM_VERTS_OF_MESH, i) {
+ copy_v3_v3(coords[i], v->co);
+ BM_elem_index_set(v, (int)i); /* set_inline */
+ }
+ BM_ITER_MESH_INDEX (f, &iter, bm, BM_FACES_OF_MESH, i) {
+ copy_v3_v3(orig_normal[i], f->no);
+ BM_elem_index_set(f, (int)i); /* set_inline */
+ }
+ bm->elem_index_dirty &= (char)~(BM_VERT | BM_FACE);
+
+ for (i = 0; i < tris_len; i++) {
+ float co[3][3];
+
+ tris[i][0] = (unsigned int)BM_elem_index_get(looptris[i][0]->v);
+ tris[i][1] = (unsigned int)BM_elem_index_get(looptris[i][1]->v);
+ tris[i][2] = (unsigned int)BM_elem_index_get(looptris[i][2]->v);
+
+ copy_v3_v3(co[0], coords[tris[i][0]]);
+ copy_v3_v3(co[1], coords[tris[i][1]]);
+ copy_v3_v3(co[2], coords[tris[i][2]]);
+
+ BLI_bvhtree_insert(tree, (int)i, co[0], 3);
+ orig_index[i] = BM_elem_index_get(looptris[i][0]->f);
+ }
+
+ BLI_bvhtree_balance(tree);
+ }
+
+ MEM_freeN(looptris);
+
+ return bvhtree_CreatePyObject(
+ tree, epsilon,
+ coords, coords_len,
+ tris, tris_len,
+ orig_index, orig_normal);
+ }
+}
+
+/* return various derived meshes based on requested settings */
+static DerivedMesh *bvh_get_derived_mesh(
+ const char *funcname, struct Scene *scene, Object *ob,
+ bool use_deform, bool use_render, bool use_cage)
+{
+ /* we only need minimum mesh data for topology and vertex locations */
+ CustomDataMask mask = CD_MASK_BAREMESH;
+
+ /* Write the display mesh into the dummy mesh */
+ if (use_deform) {
+ if (use_render) {
+ if (use_cage) {
+ PyErr_Format(PyExc_ValueError,
+ "%s(...): cage arg is unsupported when (render=True)", funcname);
+ return NULL;
+ }
+ else {
+ return mesh_create_derived_render(scene, ob, mask);
+ }
+ }
+ else {
+ if (use_cage) {
+ return mesh_get_derived_deform(scene, ob, mask); /* ob->derivedDeform */
+ }
+ else {
+ return mesh_get_derived_final(scene, ob, mask); /* ob->derivedFinal */
+ }
+ }
+ }
+ else {
+ /* !use_deform */
+ if (use_render) {
+ if (use_cage) {
+ PyErr_Format(PyExc_ValueError,
+ "%s(...): cage arg is unsupported when (render=True)", funcname);
+ return NULL;
+ }
+ else {
+ return mesh_create_derived_no_deform_render(scene, ob, NULL, mask);
+ }
+ }
+ else {
+ if (use_cage) {
+ PyErr_Format(PyExc_ValueError,
+ "%s(...): cage arg is unsupported when (deform=False, render=False)", funcname);
+ return NULL;
+ }
+ else {
+ return mesh_create_derived_no_deform(scene, ob, NULL, mask);
+ }
+ }
+ }
+}
+
+PyDoc_STRVAR(C_BVHTree_FromObject_doc,
+".. classmethod:: FromObject(object, scene, deform=True, render=False, cage=False, epsilon=0.0)\n"
+"\n"
+" BVH tree based on :class:`Object` data.\n"
+"\n"
+" :arg object: Object data.\n"
+" :type object: :class:`Object`\n"
+" :arg scene: Scene data to use for evaluating the mesh.\n"
+" :type scene: :class:`Scene`\n"
+" :arg deform: Use mesh with deformations.\n"
+" :type deform: bool\n"
+" :arg render: Use render settings.\n"
+" :type render: bool\n"
+" :arg cage: Use render settings.\n"
+" :type cage: bool\n"
+PYBVH_FROM_GENERIC_EPSILON_DOC
+);
+static PyObject *C_BVHTree_FromObject(PyObject *UNUSED(cls), PyObject *args, PyObject *kwargs)
+{
+ /* note, options here match 'bpy_bmesh_from_object' */
+ const char *keywords[] = {"object", "scene", "deform", "render", "cage", "epsilon", NULL};
+
+ PyObject *py_ob, *py_scene;
+ Object *ob;
+ struct Scene *scene;
+ DerivedMesh *dm;
+ bool use_deform = true;
+ bool use_render = false;
+ bool use_cage = false;
+
+ const MLoopTri *lt;
+ const MLoop *mloop;
+
+ float (*coords)[3] = NULL;
+ unsigned int (*tris)[3] = NULL;
+ unsigned int coords_len, tris_len;
+ float epsilon = 0.0f;
+
+ if (!PyArg_ParseTupleAndKeywords(
+ args, kwargs, (char *)"OO|$O&O&O&f:BVHTree.FromObject", (char **)keywords,
+ &py_ob, &py_scene,
+ PyC_ParseBool, &use_deform,
+ PyC_ParseBool, &use_render,
+ PyC_ParseBool, &use_cage,
+ &epsilon) ||
+ ((ob = PyC_RNA_AsPointer(py_ob, "Object")) == NULL) ||
+ ((scene = PyC_RNA_AsPointer(py_scene, "Scene")) == NULL))
+ {
+ return NULL;
+ }
+
+ dm = bvh_get_derived_mesh("BVHTree", scene, ob, use_deform, use_render, use_cage);
+ if (dm == NULL) {
+ return NULL;
+ }
+
+ /* Get data for tessellation */
+ {
+ DM_ensure_looptri(dm);
+ lt = dm->getLoopTriArray(dm);
+
+ tris_len = (unsigned int)dm->getNumLoopTri(dm);
+ coords_len = (unsigned int)dm->getNumVerts(dm);
+
+ coords = MEM_mallocN(sizeof(*coords) * (size_t)coords_len, __func__);
+ tris = MEM_mallocN(sizeof(*tris) * (size_t)tris_len, __func__);
+
+ dm->getVertCos(dm, coords);
+
+ mloop = dm->getLoopArray(dm);
+ }
+
+ {
+ BVHTree *tree;
+ unsigned int i;
+
+ int *orig_index = NULL;
+ float (*orig_normal)[3] = NULL;
+
+ tree = BLI_bvhtree_new((int)tris_len, epsilon, PY_BVH_TREE_TYPE_DEFAULT, PY_BVH_AXIS_DEFAULT);
+ if (tree) {
+ orig_index = MEM_mallocN(sizeof(*orig_index) * (size_t)tris_len, __func__);
+ orig_normal = dm->getPolyDataArray(dm, CD_NORMAL); /* can be NULL */
+ if (orig_normal) {
+ orig_normal = MEM_dupallocN(orig_normal);
+ }
+
+ for (i = 0; i < tris_len; i++, lt++) {
+ float co[3][3];
+
+ tris[i][0] = mloop[lt->tri[0]].v;
+ tris[i][1] = mloop[lt->tri[1]].v;
+ tris[i][2] = mloop[lt->tri[2]].v;
+
+ copy_v3_v3(co[0], coords[tris[i][0]]);
+ copy_v3_v3(co[1], coords[tris[i][1]]);
+ copy_v3_v3(co[2], coords[tris[i][2]]);
+
+ BLI_bvhtree_insert(tree, (int)i, co[0], 3);
+ orig_index[i] = (int)lt->poly;
+ }
+
+ BLI_bvhtree_balance(tree);
+ }
+
+ dm->release(dm);
+
+ return bvhtree_CreatePyObject(
+ tree, epsilon,
+ coords, coords_len,
+ tris, tris_len,
+ orig_index, orig_normal);
+ }
+}
+#endif /* MATH_STANDALONE */
+
+/** \} */
+
+
+/* -------------------------------------------------------------------- */
+
+/** \name Module & Type definition
+ * \{ */
+
+static PyMethodDef py_bvhtree_methods[] = {
+ {"ray_cast", (PyCFunction)py_bvhtree_ray_cast, METH_VARARGS, py_bvhtree_ray_cast_doc},
+ {"find", (PyCFunction)py_bvhtree_find_nearest, METH_VARARGS, py_bvhtree_find_nearest_doc},
+ {"overlap", (PyCFunction)py_bvhtree_overlap, METH_O, py_bvhtree_overlap_doc},
+
+ /* class methods */
+ {"FromPolygons", (PyCFunction) C_BVHTree_FromPolygons, METH_VARARGS | METH_KEYWORDS | METH_CLASS, C_BVHTree_FromPolygons_doc},
+#ifndef MATH_STANDALONE
+ {"FromBMesh", (PyCFunction) C_BVHTree_FromBMesh, METH_VARARGS | METH_KEYWORDS | METH_CLASS, C_BVHTree_FromBMesh_doc},
+ {"FromObject", (PyCFunction) C_BVHTree_FromObject, METH_VARARGS | METH_KEYWORDS | METH_CLASS, C_BVHTree_FromObject_doc},
+#endif
+ {NULL, NULL, 0, NULL}
+};
+
+PyTypeObject PyBVHTree_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "BVHTree", /* tp_name */
+ sizeof(PyBVHTree), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ /* methods */
+ (destructor)py_bvhtree__tp_dealloc, /* tp_dealloc */
+ NULL, /* tp_print */
+ NULL, /* tp_getattr */
+ NULL, /* tp_setattr */
+ NULL, /* tp_compare */
+ NULL, /* tp_repr */
+ NULL, /* tp_as_number */
+ NULL, /* tp_as_sequence */
+ NULL, /* tp_as_mapping */
+ NULL, /* tp_hash */
+ NULL, /* tp_call */
+ NULL, /* tp_str */
+ NULL, /* tp_getattro */
+ NULL, /* tp_setattro */
+ NULL, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT, /* tp_flags */
+ NULL, /* Documentation string */
+ NULL, /* tp_traverse */
+ NULL, /* tp_clear */
+ NULL, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ NULL, /* tp_iter */
+ NULL, /* tp_iternext */
+ py_bvhtree_methods, /* tp_methods */
+ NULL, /* tp_members */
+ NULL, /* tp_getset */
+ NULL, /* tp_base */
+ NULL, /* tp_dict */
+ NULL, /* tp_descr_get */
+ NULL, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ NULL, /* tp_init */
+ (allocfunc)PyType_GenericAlloc, /* tp_alloc */
+ (newfunc)PyType_GenericNew, /* tp_new */
+ (freefunc)0, /* tp_free */
+ NULL, /* tp_is_gc */
+ NULL, /* tp_bases */
+ NULL, /* tp_mro */
+ NULL, /* tp_cache */
+ NULL, /* tp_subclasses */
+ NULL, /* tp_weaklist */
+ (destructor) NULL /* tp_del */
+};
+
+/* -------------------------------------------------------------------- */
+/* Module definition */
+
+PyDoc_STRVAR(py_bvhtree_doc,
+"BVH tree structures for proximity searches and ray casts on geometry."
+);
+static struct PyModuleDef bvhtree_moduledef = {
+ PyModuleDef_HEAD_INIT,
+ "mathutils.bvhtree", /* m_name */
+ py_bvhtree_doc, /* m_doc */
+ 0, /* m_size */
+ NULL, /* m_methods */
+ NULL, /* m_reload */
+ NULL, /* m_traverse */
+ NULL, /* m_clear */
+ NULL /* m_free */
+};
+
+PyMODINIT_FUNC PyInit_mathutils_bvhtree(void)
+{
+ PyObject *m = PyModule_Create(&bvhtree_moduledef);
+
+ if (m == NULL) {
+ return NULL;
+ }
+
+ /* Register classes */
+ if (PyType_Ready(&PyBVHTree_Type) < 0) {
+ return NULL;
+ }
+
+ PyModule_AddObject(m, "BVHTree", (PyObject *)&PyBVHTree_Type);
+
+ return m;
+}
+
+/** \} */
diff --git a/source/blender/python/mathutils/mathutils_bvhtree.h b/source/blender/python/mathutils/mathutils_bvhtree.h
new file mode 100644
index 00000000000..634556d68f7
--- /dev/null
+++ b/source/blender/python/mathutils/mathutils_bvhtree.h
@@ -0,0 +1,36 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+
+/** \file blender/python/mathutils/mathutils_bvhtree.h
+ * \ingroup mathutils
+ */
+
+#ifndef __MATHUTILS_BVHTREE_H__
+#define __MATHUTILS_BVHTREE_H__
+
+PyMODINIT_FUNC PyInit_mathutils_bvhtree(void);
+
+extern PyTypeObject PyBVHTree_Type;
+
+#define PyBVHTree_Check(_v) PyObject_TypeCheck((_v), &PyBVHTree_Type)
+#define PyBVHTree_CheckExact(v) (Py_TYPE(v) == &PyBVHTree_Type)
+
+#endif /* __MATHUTILS_BVHTREE_H__ */
diff --git a/source/blender/python/mathutils/mathutils_geometry.c b/source/blender/python/mathutils/mathutils_geometry.c
index b4add0fc615..02247986558 100644
--- a/source/blender/python/mathutils/mathutils_geometry.c
+++ b/source/blender/python/mathutils/mathutils_geometry.c
@@ -43,6 +43,9 @@
#include "BLI_math.h"
#include "BLI_utildefines.h"
+#include "../generic/py_capi_utils.h"
+#include "../generic/python_utildefines.h"
+
/*-------------------------DOC STRINGS ---------------------------*/
PyDoc_STRVAR(M_Geometry_doc,
"The Blender geometry module"
@@ -72,48 +75,39 @@ PyDoc_STRVAR(M_Geometry_intersect_ray_tri_doc,
);
static PyObject *M_Geometry_intersect_ray_tri(PyObject *UNUSED(self), PyObject *args)
{
- VectorObject *ray, *ray_off, *vec1, *vec2, *vec3;
- float dir[3], orig[3], v1[3], v2[3], v3[3], e1[3], e2[3], pvec[3], tvec[3], qvec[3];
+ const char *error_prefix = "intersect_ray_tri";
+ PyObject *py_ray, *py_ray_off, *py_tri[3];
+ float dir[3], orig[3], tri[3][3], e1[3], e2[3], pvec[3], tvec[3], qvec[3];
float det, inv_det, u, v, t;
- int clip = 1;
-
- if (!PyArg_ParseTuple(args,
- "O!O!O!O!O!|i:intersect_ray_tri",
- &vector_Type, &vec1,
- &vector_Type, &vec2,
- &vector_Type, &vec3,
- &vector_Type, &ray,
- &vector_Type, &ray_off, &clip))
+ bool clip = true;
+ int i;
+
+ if (!PyArg_ParseTuple(
+ args, "OOOOO|O&:intersect_ray_tri",
+ UNPACK3_EX(&, py_tri, ),
+ &py_ray, &py_ray_off,
+ PyC_ParseBool, &clip))
{
return NULL;
}
- if (vec1->size != 3 || vec2->size != 3 || vec3->size != 3 || ray->size != 3 || ray_off->size != 3) {
- PyErr_SetString(PyExc_ValueError,
- "only 3D vectors for all parameters");
- return NULL;
- }
- if (BaseMath_ReadCallback(vec1) == -1 ||
- BaseMath_ReadCallback(vec2) == -1 ||
- BaseMath_ReadCallback(vec3) == -1 ||
- BaseMath_ReadCallback(ray) == -1 ||
- BaseMath_ReadCallback(ray_off) == -1)
+ if (((mathutils_array_parse(dir, 2, 3 | MU_ARRAY_SPILL | MU_ARRAY_ZERO, py_ray, error_prefix) != -1) &&
+ (mathutils_array_parse(orig, 2, 3 | MU_ARRAY_SPILL | MU_ARRAY_ZERO, py_ray_off, error_prefix) != -1)) == 0)
{
return NULL;
}
- copy_v3_v3(v1, vec1->vec);
- copy_v3_v3(v2, vec2->vec);
- copy_v3_v3(v3, vec3->vec);
+ for (i = 0; i < ARRAY_SIZE(tri); i++) {
+ if (mathutils_array_parse(tri[i], 2, 3 | MU_ARRAY_SPILL | MU_ARRAY_ZERO, py_tri[i], error_prefix) == -1) {
+ return NULL;
+ }
+ }
- copy_v3_v3(dir, ray->vec);
normalize_v3(dir);
- copy_v3_v3(orig, ray_off->vec);
-
/* find vectors for two edges sharing v1 */
- sub_v3_v3v3(e1, v2, v1);
- sub_v3_v3v3(e2, v3, v1);
+ sub_v3_v3v3(e1, tri[1], tri[0]);
+ sub_v3_v3v3(e2, tri[2], tri[0]);
/* begin calculating determinant - also used to calculated U parameter */
cross_v3_v3v3(pvec, dir, e2);
@@ -128,7 +122,7 @@ static PyObject *M_Geometry_intersect_ray_tri(PyObject *UNUSED(self), PyObject *
inv_det = 1.0f / det;
/* calculate distance from v1 to ray origin */
- sub_v3_v3v3(tvec, orig, v1);
+ sub_v3_v3v3(tvec, orig, tri[0]);
/* calculate U parameter and test bounds */
u = dot_v3v3(tvec, pvec) * inv_det;
@@ -149,10 +143,15 @@ static PyObject *M_Geometry_intersect_ray_tri(PyObject *UNUSED(self), PyObject *
/* calculate t, ray intersects triangle */
t = dot_v3v3(e2, qvec) * inv_det;
+ /* ray hit behind */
+ if (t < 0.0f) {
+ Py_RETURN_NONE;
+ }
+
mul_v3_fl(dir, t);
add_v3_v3v3(pvec, orig, dir);
- return Vector_CreatePyObject(pvec, 3, Py_NEW, NULL);
+ return Vector_CreatePyObject(pvec, 3, NULL);
}
/* Line-Line intersection using algorithm from mathworld.wolfram.com */
@@ -174,82 +173,45 @@ PyDoc_STRVAR(M_Geometry_intersect_line_line_doc,
);
static PyObject *M_Geometry_intersect_line_line(PyObject *UNUSED(self), PyObject *args)
{
+ const char *error_prefix = "intersect_line_line";
PyObject *tuple;
- VectorObject *vec1, *vec2, *vec3, *vec4;
- float v1[3], v2[3], v3[3], v4[3], i1[3], i2[3];
-
- if (!PyArg_ParseTuple(args, "O!O!O!O!:intersect_line_line",
- &vector_Type, &vec1,
- &vector_Type, &vec2,
- &vector_Type, &vec3,
- &vector_Type, &vec4))
+ PyObject *py_lines[4];
+ float lines[4][3], i1[3], i2[3];
+ int len;
+ int result;
+
+ if (!PyArg_ParseTuple(
+ args, "OOOO:intersect_line_line",
+ UNPACK4_EX(&, py_lines, )))
{
return NULL;
}
- if (vec1->size != vec2->size || vec1->size != vec3->size || vec3->size != vec2->size) {
- PyErr_SetString(PyExc_ValueError,
- "vectors must be of the same size");
- return NULL;
- }
-
- if (BaseMath_ReadCallback(vec1) == -1 ||
- BaseMath_ReadCallback(vec2) == -1 ||
- BaseMath_ReadCallback(vec3) == -1 ||
- BaseMath_ReadCallback(vec4) == -1)
+ if ((((len = mathutils_array_parse(lines[0], 2, 3 | MU_ARRAY_SPILL | MU_ARRAY_ZERO, py_lines[0], error_prefix)) != -1) &&
+ (mathutils_array_parse(lines[1], len, len | MU_ARRAY_SPILL | MU_ARRAY_ZERO, py_lines[1], error_prefix) != -1) &&
+ (mathutils_array_parse(lines[2], len, len | MU_ARRAY_SPILL | MU_ARRAY_ZERO, py_lines[2], error_prefix) != -1) &&
+ (mathutils_array_parse(lines[3], len, len | MU_ARRAY_SPILL | MU_ARRAY_ZERO, py_lines[3], error_prefix) != -1)) == 0)
{
return NULL;
}
- if (vec1->size == 3 || vec1->size == 2) {
- int result;
-
- if (vec1->size == 3) {
- copy_v3_v3(v1, vec1->vec);
- copy_v3_v3(v2, vec2->vec);
- copy_v3_v3(v3, vec3->vec);
- copy_v3_v3(v4, vec4->vec);
- }
- else {
- v1[0] = vec1->vec[0];
- v1[1] = vec1->vec[1];
- v1[2] = 0.0f;
-
- v2[0] = vec2->vec[0];
- v2[1] = vec2->vec[1];
- v2[2] = 0.0f;
-
- v3[0] = vec3->vec[0];
- v3[1] = vec3->vec[1];
- v3[2] = 0.0f;
-
- v4[0] = vec4->vec[0];
- v4[1] = vec4->vec[1];
- v4[2] = 0.0f;
- }
-
- result = isect_line_line_v3(v1, v2, v3, v4, i1, i2);
- /* The return-code isnt exposed,
- * this way we can check know how close the lines are. */
- if (result == 1) {
- closest_to_line_v3(i2, i1, v3, v4);
- }
+ result = isect_line_line_v3(UNPACK4(lines), i1, i2);
+ /* The return-code isnt exposed,
+ * this way we can check know how close the lines are. */
+ if (result == 1) {
+ closest_to_line_v3(i2, i1, lines[2], lines[3]);
+ }
- if (result == 0) {
- /* colinear */
- Py_RETURN_NONE;
- }
- else {
- tuple = PyTuple_New(2);
- PyTuple_SET_ITEM(tuple, 0, Vector_CreatePyObject(i1, vec1->size, Py_NEW, NULL));
- PyTuple_SET_ITEM(tuple, 1, Vector_CreatePyObject(i2, vec1->size, Py_NEW, NULL));
- return tuple;
- }
+ if (result == 0) {
+ /* collinear */
+ Py_RETURN_NONE;
}
else {
- PyErr_SetString(PyExc_ValueError,
- "2D/3D vectors only");
- return NULL;
+ tuple = PyTuple_New(2);
+ PyTuple_SET_ITEMS(tuple,
+ Vector_CreatePyObject(i1, len, NULL),
+ Vector_CreatePyObject(i2, len, NULL));
+ return tuple;
}
}
@@ -272,31 +234,30 @@ PyDoc_STRVAR(M_Geometry_intersect_sphere_sphere_2d_doc,
);
static PyObject *M_Geometry_intersect_sphere_sphere_2d(PyObject *UNUSED(self), PyObject *args)
{
+ const char *error_prefix = "intersect_sphere_sphere_2d";
PyObject *ret;
- VectorObject *vec_a, *vec_b;
- const float *v_a, *v_b;
+ PyObject *py_v_a, *py_v_b;
+ float v_a[2], v_b[2];
float rad_a, rad_b;
float v_ab[2];
float dist;
- if (!PyArg_ParseTuple(args, "O!fO!f:intersect_sphere_sphere_2d",
- &vector_Type, &vec_a, &rad_a,
- &vector_Type, &vec_b, &rad_b))
+ if (!PyArg_ParseTuple(
+ args, "OfOf:intersect_sphere_sphere_2d",
+ &py_v_a, &rad_a,
+ &py_v_b, &rad_b))
{
return NULL;
}
- if (BaseMath_ReadCallback(vec_a) == -1 ||
- BaseMath_ReadCallback(vec_b) == -1)
+ if (((mathutils_array_parse(v_a, 2, 2, py_v_a, error_prefix) != -1) &&
+ (mathutils_array_parse(v_b, 2, 2, py_v_b, error_prefix) != -1)) == 0)
{
return NULL;
}
ret = PyTuple_New(2);
- v_a = vec_a->vec;
- v_b = vec_b->vec;
-
sub_v2_v2v2(v_ab, v_b, v_a);
dist = len_v2(v_ab);
@@ -308,8 +269,9 @@ static PyObject *M_Geometry_intersect_sphere_sphere_2d(PyObject *UNUSED(self), P
(dist < FLT_EPSILON))
{
/* out of range */
- PyTuple_SET_ITEM(ret, 0, Py_None); Py_INCREF(Py_None);
- PyTuple_SET_ITEM(ret, 1, Py_None); Py_INCREF(Py_None);
+ PyTuple_SET_ITEMS(ret,
+ Py_INCREF_RET(Py_None),
+ Py_INCREF_RET(Py_None));
}
else {
const float dist_delta = ((rad_a * rad_a) - (rad_b * rad_b) + (dist * dist)) / (2.0f * dist);
@@ -326,94 +288,51 @@ static PyObject *M_Geometry_intersect_sphere_sphere_2d(PyObject *UNUSED(self), P
i2[0] = i_cent[0] - h * v_ab[1] / dist;
i2[1] = i_cent[1] + h * v_ab[0] / dist;
- PyTuple_SET_ITEM(ret, 0, Vector_CreatePyObject(i1, 2, Py_NEW, NULL));
- PyTuple_SET_ITEM(ret, 1, Vector_CreatePyObject(i2, 2, Py_NEW, NULL));
+ PyTuple_SET_ITEMS(ret,
+ Vector_CreatePyObject(i1, 2, NULL),
+ Vector_CreatePyObject(i2, 2, NULL));
}
return ret;
}
PyDoc_STRVAR(M_Geometry_normal_doc,
-".. function:: normal(v1, v2, v3, v4=None)\n"
+".. function:: normal(vectors)\n"
"\n"
-" Returns the normal of the 3D tri or quad.\n"
+" Returns the normal of a 3D polygon.\n"
"\n"
-" :arg v1: Point1\n"
-" :type v1: :class:`mathutils.Vector`\n"
-" :arg v2: Point2\n"
-" :type v2: :class:`mathutils.Vector`\n"
-" :arg v3: Point3\n"
-" :type v3: :class:`mathutils.Vector`\n"
-" :arg v4: Point4 (optional)\n"
-" :type v4: :class:`mathutils.Vector`\n"
+" :arg vectors: Vectors to calculate normals with\n"
+" :type vectors: sequence of 3 or more 3d vector\n"
" :rtype: :class:`mathutils.Vector`\n"
);
static PyObject *M_Geometry_normal(PyObject *UNUSED(self), PyObject *args)
{
- VectorObject *vec1, *vec2, *vec3, *vec4;
+ float (*coords)[3];
+ int coords_len;
float n[3];
+ PyObject *ret = NULL;
- if (PyTuple_GET_SIZE(args) == 3) {
- if (!PyArg_ParseTuple(args, "O!O!O!:normal",
- &vector_Type, &vec1,
- &vector_Type, &vec2,
- &vector_Type, &vec3))
- {
- return NULL;
- }
-
- if (vec1->size != vec2->size || vec1->size != vec3->size) {
- PyErr_SetString(PyExc_ValueError,
- "vectors must be of the same size");
- return NULL;
- }
- if (vec1->size < 3) {
- PyErr_SetString(PyExc_ValueError,
- "2D vectors unsupported");
- return NULL;
- }
-
- if (BaseMath_ReadCallback(vec1) == -1 ||
- BaseMath_ReadCallback(vec2) == -1 ||
- BaseMath_ReadCallback(vec3) == -1)
- {
- return NULL;
- }
-
- normal_tri_v3(n, vec1->vec, vec2->vec, vec3->vec);
+ /* use */
+ if (PyTuple_GET_SIZE(args) == 1) {
+ args = PyTuple_GET_ITEM(args, 0);
}
- else {
- if (!PyArg_ParseTuple(args, "O!O!O!O!:normal",
- &vector_Type, &vec1,
- &vector_Type, &vec2,
- &vector_Type, &vec3,
- &vector_Type, &vec4))
- {
- return NULL;
- }
- if (vec1->size != vec2->size || vec1->size != vec3->size || vec1->size != vec4->size) {
- PyErr_SetString(PyExc_ValueError,
- "vectors must be of the same size");
- return NULL;
- }
- if (vec1->size < 3) {
- PyErr_SetString(PyExc_ValueError,
- "2D vectors unsupported");
- return NULL;
- }
- if (BaseMath_ReadCallback(vec1) == -1 ||
- BaseMath_ReadCallback(vec2) == -1 ||
- BaseMath_ReadCallback(vec3) == -1 ||
- BaseMath_ReadCallback(vec4) == -1)
- {
- return NULL;
- }
+ if ((coords_len = mathutils_array_parse_alloc_v((float **)&coords, 3 | MU_ARRAY_SPILL, args, "normal")) == -1) {
+ return NULL;
+ }
- normal_quad_v3(n, vec1->vec, vec2->vec, vec3->vec, vec4->vec);
+ if (coords_len < 3) {
+ PyErr_SetString(PyExc_ValueError,
+ "Expected 3 or more vectors");
+ goto finally;
}
- return Vector_CreatePyObject(n, 3, Py_NEW, NULL);
+ normal_poly_v3(n, (const float (*)[3])coords, coords_len);
+ ret = Vector_CreatePyObject(n, 3, NULL);
+
+finally:
+ PyMem_Free(coords);
+ return ret;
}
/* --------------------------------- AREA FUNCTIONS-------------------- */
@@ -433,40 +352,26 @@ PyDoc_STRVAR(M_Geometry_area_tri_doc,
);
static PyObject *M_Geometry_area_tri(PyObject *UNUSED(self), PyObject *args)
{
- VectorObject *vec1, *vec2, *vec3;
-
- if (!PyArg_ParseTuple(args, "O!O!O!:area_tri",
- &vector_Type, &vec1,
- &vector_Type, &vec2,
- &vector_Type, &vec3))
+ const char *error_prefix = "area_tri";
+ PyObject *py_tri[3];
+ float tri[3][3];
+ int len;
+
+ if (!PyArg_ParseTuple(
+ args, "OOO:area_tri",
+ UNPACK3_EX(&, py_tri, )))
{
return NULL;
}
- if (vec1->size != vec2->size || vec1->size != vec3->size) {
- PyErr_SetString(PyExc_ValueError,
- "vectors must be of the same size");
- return NULL;
- }
-
- if (BaseMath_ReadCallback(vec1) == -1 ||
- BaseMath_ReadCallback(vec2) == -1 ||
- BaseMath_ReadCallback(vec3) == -1)
+ if ((((len = mathutils_array_parse(tri[0], 2, 3, py_tri[0], error_prefix)) != -1) &&
+ (mathutils_array_parse(tri[1], len, len, py_tri[1], error_prefix) != -1) &&
+ (mathutils_array_parse(tri[2], len, len, py_tri[2], error_prefix) != -1)) == 0)
{
return NULL;
}
- if (vec1->size == 3) {
- return PyFloat_FromDouble(area_tri_v3(vec1->vec, vec2->vec, vec3->vec));
- }
- else if (vec1->size == 2) {
- return PyFloat_FromDouble(area_tri_v2(vec1->vec, vec2->vec, vec3->vec));
- }
- else {
- PyErr_SetString(PyExc_ValueError,
- "only 2D,3D vectors are supported");
- return NULL;
- }
+ return PyFloat_FromDouble((len == 3 ? area_tri_v3 : area_tri_v2)(UNPACK3(tri)));
}
PyDoc_STRVAR(M_Geometry_volume_tetrahedron_doc,
@@ -486,33 +391,25 @@ PyDoc_STRVAR(M_Geometry_volume_tetrahedron_doc,
);
static PyObject *M_Geometry_volume_tetrahedron(PyObject *UNUSED(self), PyObject *args)
{
- VectorObject *vec1, *vec2, *vec3, *vec4;
+ const char *error_prefix = "volume_tetrahedron";
+ PyObject *py_tet[4];
+ float tet[4][3];
+ int i;
- if (!PyArg_ParseTuple(args, "O!O!O!O!:volume_tetrahedron",
- &vector_Type, &vec1,
- &vector_Type, &vec2,
- &vector_Type, &vec3,
- &vector_Type, &vec4))
+ if (!PyArg_ParseTuple(
+ args, "OOOO:volume_tetrahedron",
+ UNPACK4_EX(&, py_tet, )))
{
return NULL;
}
- if (vec1->size < 3 || vec2->size < 3 || vec3->size < 3 || vec4->size < 3) {
- PyErr_SetString(PyExc_ValueError,
- "geometry.volume_tetrahedron(...): "
- " can't use 2D Vectors");
- return NULL;
- }
-
- if (BaseMath_ReadCallback(vec1) == -1 ||
- BaseMath_ReadCallback(vec2) == -1 ||
- BaseMath_ReadCallback(vec3) == -1 ||
- BaseMath_ReadCallback(vec4) == -1)
- {
- return NULL;
+ for (i = 0; i < ARRAY_SIZE(tet); i++) {
+ if (mathutils_array_parse(tet[i], 3, 3 | MU_ARRAY_SPILL, py_tet[i], error_prefix) == -1) {
+ return NULL;
+ }
}
- return PyFloat_FromDouble(volume_tetrahedron_v3(vec1->vec, vec2->vec, vec3->vec, vec4->vec));
+ return PyFloat_FromDouble(volume_tetrahedron_v3(UNPACK4(tet)));
}
PyDoc_STRVAR(M_Geometry_intersect_line_line_2d_doc,
@@ -533,27 +430,27 @@ PyDoc_STRVAR(M_Geometry_intersect_line_line_2d_doc,
);
static PyObject *M_Geometry_intersect_line_line_2d(PyObject *UNUSED(self), PyObject *args)
{
- VectorObject *line_a1, *line_a2, *line_b1, *line_b2;
+ const char *error_prefix = "intersect_line_line_2d";
+ PyObject *py_lines[4];
+ float lines[4][2];
float vi[2];
- if (!PyArg_ParseTuple(args, "O!O!O!O!:intersect_line_line_2d",
- &vector_Type, &line_a1,
- &vector_Type, &line_a2,
- &vector_Type, &line_b1,
- &vector_Type, &line_b2))
+ int i;
+
+ if (!PyArg_ParseTuple(
+ args, "OOOO:intersect_line_line_2d",
+ UNPACK4_EX(&, py_lines, )))
{
return NULL;
}
-
- if (BaseMath_ReadCallback(line_a1) == -1 ||
- BaseMath_ReadCallback(line_a2) == -1 ||
- BaseMath_ReadCallback(line_b1) == -1 ||
- BaseMath_ReadCallback(line_b2) == -1)
- {
- return NULL;
+
+ for (i = 0; i < ARRAY_SIZE(lines); i++) {
+ if (mathutils_array_parse(lines[i], 2, 2 | MU_ARRAY_SPILL, py_lines[i], error_prefix) == -1) {
+ return NULL;
+ }
}
- if (isect_seg_seg_v2_point(line_a1->vec, line_a2->vec, line_b1->vec, line_b2->vec, vi) == 1) {
- return Vector_CreatePyObject(vi, 2, Py_NEW, NULL);
+ if (isect_seg_seg_v2_point(UNPACK4(lines), vi) == 1) {
+ return Vector_CreatePyObject(vi, 2, NULL);
}
else {
Py_RETURN_NONE;
@@ -580,38 +477,31 @@ PyDoc_STRVAR(M_Geometry_intersect_line_plane_doc,
);
static PyObject *M_Geometry_intersect_line_plane(PyObject *UNUSED(self), PyObject *args)
{
- VectorObject *line_a, *line_b, *plane_co, *plane_no;
+ const char *error_prefix = "intersect_line_plane";
+ PyObject *py_line_a, *py_line_b, *py_plane_co, *py_plane_no;
+ float line_a[3], line_b[3], plane_co[3], plane_no[3];
float isect[3];
- int no_flip = false;
-
- if (!PyArg_ParseTuple(args, "O!O!O!O!|i:intersect_line_plane",
- &vector_Type, &line_a,
- &vector_Type, &line_b,
- &vector_Type, &plane_co,
- &vector_Type, &plane_no,
- &no_flip))
- {
- return NULL;
- }
+ bool no_flip = false;
- if (BaseMath_ReadCallback(line_a) == -1 ||
- BaseMath_ReadCallback(line_b) == -1 ||
- BaseMath_ReadCallback(plane_co) == -1 ||
- BaseMath_ReadCallback(plane_no) == -1)
+ if (!PyArg_ParseTuple(
+ args, "OOOO|O&:intersect_line_plane",
+ &py_line_a, &py_line_b, &py_plane_co, &py_plane_no,
+ PyC_ParseBool, &no_flip))
{
return NULL;
}
- if (ELEM(2, line_a->size, line_b->size, plane_co->size, plane_no->size)) {
- PyErr_SetString(PyExc_ValueError,
- "geometry.intersect_line_plane(...): "
- " can't use 2D Vectors");
+ if (((mathutils_array_parse(line_a, 3, 3 | MU_ARRAY_SPILL, py_line_a, error_prefix) != -1) &&
+ (mathutils_array_parse(line_b, 3, 3 | MU_ARRAY_SPILL, py_line_b, error_prefix) != -1) &&
+ (mathutils_array_parse(plane_co, 3, 3 | MU_ARRAY_SPILL, py_plane_co, error_prefix) != -1) &&
+ (mathutils_array_parse(plane_no, 3, 3 | MU_ARRAY_SPILL, py_plane_no, error_prefix) != -1)) == 0)
+ {
return NULL;
}
/* TODO: implements no_flip */
- if (isect_line_plane_v3(isect, line_a->vec, line_b->vec, plane_co->vec, plane_no->vec) == 1) {
- return Vector_CreatePyObject(isect, 3, Py_NEW, NULL);
+ if (isect_line_plane_v3(isect, line_a, line_b, plane_co, plane_no) == 1) {
+ return Vector_CreatePyObject(isect, 3, NULL);
}
else {
Py_RETURN_NONE;
@@ -636,68 +526,63 @@ PyDoc_STRVAR(M_Geometry_intersect_plane_plane_doc,
);
static PyObject *M_Geometry_intersect_plane_plane(PyObject *UNUSED(self), PyObject *args)
{
+ const char *error_prefix = "intersect_plane_plane";
PyObject *ret, *ret_co, *ret_no;
- VectorObject *plane_a_co, *plane_a_no, *plane_b_co, *plane_b_no;
+ PyObject *py_plane_a_co, *py_plane_a_no, *py_plane_b_co, *py_plane_b_no;
+ float plane_a_co[3], plane_a_no[3], plane_b_co[3], plane_b_no[3];
+ float plane_a[4], plane_b[4];
float isect_co[3];
float isect_no[3];
- if (!PyArg_ParseTuple(args, "O!O!O!O!:intersect_plane_plane",
- &vector_Type, &plane_a_co,
- &vector_Type, &plane_a_no,
- &vector_Type, &plane_b_co,
- &vector_Type, &plane_b_no))
+ if (!PyArg_ParseTuple(
+ args, "OOOO:intersect_plane_plane",
+ &py_plane_a_co, &py_plane_a_no, &py_plane_b_co, &py_plane_b_no))
{
return NULL;
}
- if (BaseMath_ReadCallback(plane_a_co) == -1 ||
- BaseMath_ReadCallback(plane_a_no) == -1 ||
- BaseMath_ReadCallback(plane_b_co) == -1 ||
- BaseMath_ReadCallback(plane_b_no) == -1)
+ if (((mathutils_array_parse(plane_a_co, 3, 3 | MU_ARRAY_SPILL, py_plane_a_co, error_prefix) != -1) &&
+ (mathutils_array_parse(plane_a_no, 3, 3 | MU_ARRAY_SPILL, py_plane_a_no, error_prefix) != -1) &&
+ (mathutils_array_parse(plane_b_co, 3, 3 | MU_ARRAY_SPILL, py_plane_b_co, error_prefix) != -1) &&
+ (mathutils_array_parse(plane_b_no, 3, 3 | MU_ARRAY_SPILL, py_plane_b_no, error_prefix) != -1)) == 0)
{
return NULL;
}
- if (ELEM(2, plane_a_co->size, plane_a_no->size, plane_b_co->size, plane_b_no->size)) {
- PyErr_SetString(PyExc_ValueError,
- "geometry.intersect_plane_plane(...): "
- " can't use 2D Vectors");
- return NULL;
- }
+ plane_from_point_normal_v3(plane_a, plane_a_co, plane_a_no);
+ plane_from_point_normal_v3(plane_b, plane_b_co, plane_b_no);
- if (isect_plane_plane_v3(isect_co, isect_no,
- plane_a_co->vec, plane_a_no->vec,
- plane_b_co->vec, plane_b_no->vec))
+ if (isect_plane_plane_v3(
+ plane_a, plane_b,
+ isect_co, isect_no))
{
normalize_v3(isect_no);
- ret_co = Vector_CreatePyObject(isect_co, 3, Py_NEW, NULL);
- ret_no = Vector_CreatePyObject(isect_no, 3, Py_NEW, NULL);
+ ret_co = Vector_CreatePyObject(isect_co, 3, NULL);
+ ret_no = Vector_CreatePyObject(isect_no, 3, NULL);
}
else {
- ret_co = Py_None;
- ret_no = Py_None;
-
- Py_INCREF(ret_co);
- Py_INCREF(ret_no);
+ ret_co = Py_INCREF_RET(Py_None);
+ ret_no = Py_INCREF_RET(Py_None);
}
ret = PyTuple_New(2);
- PyTuple_SET_ITEM(ret, 0, ret_co);
- PyTuple_SET_ITEM(ret, 1, ret_no);
+ PyTuple_SET_ITEMS(ret,
+ ret_co,
+ ret_no);
return ret;
}
PyDoc_STRVAR(M_Geometry_intersect_line_sphere_doc,
".. function:: intersect_line_sphere(line_a, line_b, sphere_co, sphere_radius, clip=True)\n"
"\n"
-" Takes a lines (as 2 vectors), a sphere as a point and a radius and\n"
+" Takes a line (as 2 points) and a sphere (as a point and a radius) and\n"
" returns the intersection\n"
"\n"
-" :arg line_a: First point of the first line\n"
+" :arg line_a: First point of the line\n"
" :type line_a: :class:`mathutils.Vector`\n"
-" :arg line_b: Second point of the first line\n"
+" :arg line_b: Second point of the line\n"
" :type line_b: :class:`mathutils.Vector`\n"
" :arg sphere_co: The center of the sphere\n"
" :type sphere_co: :class:`mathutils.Vector`\n"
@@ -708,35 +593,29 @@ PyDoc_STRVAR(M_Geometry_intersect_line_sphere_doc,
);
static PyObject *M_Geometry_intersect_line_sphere(PyObject *UNUSED(self), PyObject *args)
{
- VectorObject *line_a, *line_b, *sphere_co;
+ const char *error_prefix = "intersect_line_sphere";
+ PyObject *py_line_a, *py_line_b, *py_sphere_co;
+ float line_a[3], line_b[3], sphere_co[3];
float sphere_radius;
- int clip = true;
+ bool clip = true;
float isect_a[3];
float isect_b[3];
- if (!PyArg_ParseTuple(args, "O!O!O!f|i:intersect_line_sphere",
- &vector_Type, &line_a,
- &vector_Type, &line_b,
- &vector_Type, &sphere_co,
- &sphere_radius, &clip))
+ if (!PyArg_ParseTuple(
+ args, "OOOf|O&:intersect_line_sphere",
+ &py_line_a, &py_line_b, &py_sphere_co, &sphere_radius,
+ PyC_ParseBool, &clip))
{
return NULL;
}
- if (BaseMath_ReadCallback(line_a) == -1 ||
- BaseMath_ReadCallback(line_b) == -1 ||
- BaseMath_ReadCallback(sphere_co) == -1)
+ if (((mathutils_array_parse(line_a, 3, 3 | MU_ARRAY_SPILL, py_line_a, error_prefix) != -1) &&
+ (mathutils_array_parse(line_b, 3, 3 | MU_ARRAY_SPILL, py_line_b, error_prefix) != -1) &&
+ (mathutils_array_parse(sphere_co, 3, 3 | MU_ARRAY_SPILL, py_sphere_co, error_prefix) != -1)) == 0)
{
return NULL;
}
-
- if (ELEM(2, line_a->size, line_b->size, sphere_co->size)) {
- PyErr_SetString(PyExc_ValueError,
- "geometry.intersect_line_sphere(...): "
- " can't use 2D Vectors");
- return NULL;
- }
else {
bool use_a = true;
bool use_b = true;
@@ -744,14 +623,14 @@ static PyObject *M_Geometry_intersect_line_sphere(PyObject *UNUSED(self), PyObje
PyObject *ret = PyTuple_New(2);
- switch (isect_line_sphere_v3(line_a->vec, line_b->vec, sphere_co->vec, sphere_radius, isect_a, isect_b)) {
+ switch (isect_line_sphere_v3(line_a, line_b, sphere_co, sphere_radius, isect_a, isect_b)) {
case 1:
- if (!(!clip || (((lambda = line_point_factor_v3(isect_a, line_a->vec, line_b->vec)) >= 0.0f) && (lambda <= 1.0f)))) use_a = false;
+ if (!(!clip || (((lambda = line_point_factor_v3(isect_a, line_a, line_b)) >= 0.0f) && (lambda <= 1.0f)))) use_a = false;
use_b = false;
break;
case 2:
- if (!(!clip || (((lambda = line_point_factor_v3(isect_a, line_a->vec, line_b->vec)) >= 0.0f) && (lambda <= 1.0f)))) use_a = false;
- if (!(!clip || (((lambda = line_point_factor_v3(isect_b, line_a->vec, line_b->vec)) >= 0.0f) && (lambda <= 1.0f)))) use_b = false;
+ if (!(!clip || (((lambda = line_point_factor_v3(isect_a, line_a, line_b)) >= 0.0f) && (lambda <= 1.0f)))) use_a = false;
+ if (!(!clip || (((lambda = line_point_factor_v3(isect_b, line_a, line_b)) >= 0.0f) && (lambda <= 1.0f)))) use_b = false;
break;
default:
use_a = false;
@@ -759,11 +638,9 @@ static PyObject *M_Geometry_intersect_line_sphere(PyObject *UNUSED(self), PyObje
break;
}
- if (use_a) { PyTuple_SET_ITEM(ret, 0, Vector_CreatePyObject(isect_a, 3, Py_NEW, NULL)); }
- else { PyTuple_SET_ITEM(ret, 0, Py_None); Py_INCREF(Py_None); }
-
- if (use_b) { PyTuple_SET_ITEM(ret, 1, Vector_CreatePyObject(isect_b, 3, Py_NEW, NULL)); }
- else { PyTuple_SET_ITEM(ret, 1, Py_None); Py_INCREF(Py_None); }
+ PyTuple_SET_ITEMS(ret,
+ use_a ? Vector_CreatePyObject(isect_a, 3, NULL) : Py_INCREF_RET(Py_None),
+ use_b ? Vector_CreatePyObject(isect_b, 3, NULL) : Py_INCREF_RET(Py_None));
return ret;
}
@@ -773,12 +650,12 @@ static PyObject *M_Geometry_intersect_line_sphere(PyObject *UNUSED(self), PyObje
PyDoc_STRVAR(M_Geometry_intersect_line_sphere_2d_doc,
".. function:: intersect_line_sphere_2d(line_a, line_b, sphere_co, sphere_radius, clip=True)\n"
"\n"
-" Takes a lines (as 2 vectors), a sphere as a point and a radius and\n"
+" Takes a line (as 2 points) and a sphere (as a point and a radius) and\n"
" returns the intersection\n"
"\n"
-" :arg line_a: First point of the first line\n"
+" :arg line_a: First point of the line\n"
" :type line_a: :class:`mathutils.Vector`\n"
-" :arg line_b: Second point of the first line\n"
+" :arg line_b: Second point of the line\n"
" :type line_b: :class:`mathutils.Vector`\n"
" :arg sphere_co: The center of the sphere\n"
" :type sphere_co: :class:`mathutils.Vector`\n"
@@ -789,25 +666,26 @@ PyDoc_STRVAR(M_Geometry_intersect_line_sphere_2d_doc,
);
static PyObject *M_Geometry_intersect_line_sphere_2d(PyObject *UNUSED(self), PyObject *args)
{
- VectorObject *line_a, *line_b, *sphere_co;
+ const char *error_prefix = "intersect_line_sphere_2d";
+ PyObject *py_line_a, *py_line_b, *py_sphere_co;
+ float line_a[2], line_b[2], sphere_co[2];
float sphere_radius;
- int clip = true;
+ bool clip = true;
float isect_a[2];
float isect_b[2];
- if (!PyArg_ParseTuple(args, "O!O!O!f|i:intersect_line_sphere_2d",
- &vector_Type, &line_a,
- &vector_Type, &line_b,
- &vector_Type, &sphere_co,
- &sphere_radius, &clip))
+ if (!PyArg_ParseTuple(
+ args, "OOOf|O&:intersect_line_sphere_2d",
+ &py_line_a, &py_line_b, &py_sphere_co, &sphere_radius,
+ PyC_ParseBool, &clip))
{
return NULL;
}
- if (BaseMath_ReadCallback(line_a) == -1 ||
- BaseMath_ReadCallback(line_b) == -1 ||
- BaseMath_ReadCallback(sphere_co) == -1)
+ if (((mathutils_array_parse(line_a, 2, 2 | MU_ARRAY_SPILL, py_line_a, error_prefix) != -1) &&
+ (mathutils_array_parse(line_b, 2, 2 | MU_ARRAY_SPILL, py_line_b, error_prefix) != -1) &&
+ (mathutils_array_parse(sphere_co, 2, 2 | MU_ARRAY_SPILL, py_sphere_co, error_prefix) != -1)) == 0)
{
return NULL;
}
@@ -818,14 +696,14 @@ static PyObject *M_Geometry_intersect_line_sphere_2d(PyObject *UNUSED(self), PyO
PyObject *ret = PyTuple_New(2);
- switch (isect_line_sphere_v2(line_a->vec, line_b->vec, sphere_co->vec, sphere_radius, isect_a, isect_b)) {
+ switch (isect_line_sphere_v2(line_a, line_b, sphere_co, sphere_radius, isect_a, isect_b)) {
case 1:
- if (!(!clip || (((lambda = line_point_factor_v2(isect_a, line_a->vec, line_b->vec)) >= 0.0f) && (lambda <= 1.0f)))) use_a = false;
+ if (!(!clip || (((lambda = line_point_factor_v2(isect_a, line_a, line_b)) >= 0.0f) && (lambda <= 1.0f)))) use_a = false;
use_b = false;
break;
case 2:
- if (!(!clip || (((lambda = line_point_factor_v2(isect_a, line_a->vec, line_b->vec)) >= 0.0f) && (lambda <= 1.0f)))) use_a = false;
- if (!(!clip || (((lambda = line_point_factor_v2(isect_b, line_a->vec, line_b->vec)) >= 0.0f) && (lambda <= 1.0f)))) use_b = false;
+ if (!(!clip || (((lambda = line_point_factor_v2(isect_a, line_a, line_b)) >= 0.0f) && (lambda <= 1.0f)))) use_a = false;
+ if (!(!clip || (((lambda = line_point_factor_v2(isect_b, line_a, line_b)) >= 0.0f) && (lambda <= 1.0f)))) use_b = false;
break;
default:
use_a = false;
@@ -833,11 +711,9 @@ static PyObject *M_Geometry_intersect_line_sphere_2d(PyObject *UNUSED(self), PyO
break;
}
- if (use_a) { PyTuple_SET_ITEM(ret, 0, Vector_CreatePyObject(isect_a, 2, Py_NEW, NULL)); }
- else { PyTuple_SET_ITEM(ret, 0, Py_None); Py_INCREF(Py_None); }
-
- if (use_b) { PyTuple_SET_ITEM(ret, 1, Vector_CreatePyObject(isect_b, 2, Py_NEW, NULL)); }
- else { PyTuple_SET_ITEM(ret, 1, Py_None); Py_INCREF(Py_None); }
+ PyTuple_SET_ITEMS(ret,
+ use_a ? Vector_CreatePyObject(isect_a, 2, NULL) : Py_INCREF_RET(Py_None),
+ use_b ? Vector_CreatePyObject(isect_b, 2, NULL) : Py_INCREF_RET(Py_None));
return ret;
}
@@ -858,43 +734,35 @@ PyDoc_STRVAR(M_Geometry_intersect_point_line_doc,
);
static PyObject *M_Geometry_intersect_point_line(PyObject *UNUSED(self), PyObject *args)
{
- VectorObject *pt, *line_1, *line_2;
- float pt_in[3], pt_out[3], l1[3], l2[3];
+ const char *error_prefix = "intersect_point_line";
+ PyObject *py_pt, *py_line_a, *py_line_b;
+ float pt[3], pt_out[3], line_a[3], line_b[3];
float lambda;
PyObject *ret;
int size = 2;
- if (!PyArg_ParseTuple(args, "O!O!O!:intersect_point_line",
- &vector_Type, &pt,
- &vector_Type, &line_1,
- &vector_Type, &line_2))
+ if (!PyArg_ParseTuple(
+ args, "OOO:intersect_point_line",
+ &py_pt, &py_line_a, &py_line_b))
{
return NULL;
}
- if (BaseMath_ReadCallback(pt) == -1 ||
- BaseMath_ReadCallback(line_1) == -1 ||
- BaseMath_ReadCallback(line_2) == -1)
+ /* accept 2d verts */
+ if ((((size = mathutils_array_parse(pt, 2, 3 | MU_ARRAY_SPILL | MU_ARRAY_ZERO, py_pt, error_prefix)) != -1) &&
+ (mathutils_array_parse(line_a, 2, 3 | MU_ARRAY_SPILL | MU_ARRAY_ZERO, py_line_a, error_prefix) != -1) &&
+ (mathutils_array_parse(line_b, 2, 3 | MU_ARRAY_SPILL | MU_ARRAY_ZERO, py_line_b, error_prefix) != -1)) == 0)
{
return NULL;
}
- /* accept 2d verts */
- if (pt->size >= 3) { copy_v3_v3(pt_in, pt->vec); size = 3; }
- else { copy_v2_v2(pt_in, pt->vec); pt_in[2] = 0.0f; }
-
- if (line_1->size >= 3) { copy_v3_v3(l1, line_1->vec); size = 3; }
- else { copy_v2_v2(l1, line_1->vec); l1[2] = 0.0f; }
-
- if (line_2->size >= 3) { copy_v3_v3(l2, line_2->vec); size = 3; }
- else { copy_v2_v2(l2, line_2->vec); l2[2] = 0.0f; }
-
/* do the calculation */
- lambda = closest_to_line_v3(pt_out, pt_in, l1, l2);
+ lambda = closest_to_line_v3(pt_out, pt, line_a, line_b);
ret = PyTuple_New(2);
- PyTuple_SET_ITEM(ret, 0, Vector_CreatePyObject(pt_out, size, Py_NEW, NULL));
- PyTuple_SET_ITEM(ret, 1, PyFloat_FromDouble(lambda));
+ PyTuple_SET_ITEMS(ret,
+ Vector_CreatePyObject(pt_out, size, NULL),
+ PyFloat_FromDouble(lambda));
return ret;
}
@@ -916,38 +784,30 @@ PyDoc_STRVAR(M_Geometry_intersect_point_tri_doc,
);
static PyObject *M_Geometry_intersect_point_tri(PyObject *UNUSED(self), PyObject *args)
{
- VectorObject *pt_vec, *tri_p1, *tri_p2, *tri_p3;
+ const char *error_prefix = "intersect_point_tri";
+ PyObject *py_pt, *py_tri[3];
+ float pt[3], tri[3][3];
float vi[3];
+ int i;
- if (!PyArg_ParseTuple(args, "O!O!O!O!:intersect_point_tri",
- &vector_Type, &pt_vec,
- &vector_Type, &tri_p1,
- &vector_Type, &tri_p2,
- &vector_Type, &tri_p3))
+ if (!PyArg_ParseTuple(
+ args, "OOOO:intersect_point_tri",
+ &py_pt, UNPACK3_EX(&, py_tri, )))
{
return NULL;
}
- if (BaseMath_ReadCallback(pt_vec) == -1 ||
- BaseMath_ReadCallback(tri_p1) == -1 ||
- BaseMath_ReadCallback(tri_p2) == -1 ||
- BaseMath_ReadCallback(tri_p3) == -1)
- {
+ if (mathutils_array_parse(pt, 2, 3 | MU_ARRAY_SPILL | MU_ARRAY_ZERO, py_pt, error_prefix) == -1) {
return NULL;
}
-
- if (pt_vec->size < 3 ||
- tri_p1->size < 3 ||
- tri_p2->size < 3 ||
- tri_p3->size < 3)
- {
- PyErr_SetString(PyExc_ValueError,
- "One of more of the vector arguments wasn't a 3D vector");
- return NULL;
+ for (i = 0; i < ARRAY_SIZE(tri); i++) {
+ if (mathutils_array_parse(tri[i], 2, 3 | MU_ARRAY_SPILL | MU_ARRAY_ZERO, py_tri[i], error_prefix) == -1) {
+ return NULL;
+ }
}
- if (isect_point_tri_v3(pt_vec->vec, tri_p1->vec, tri_p2->vec, tri_p3->vec, vi)) {
- return Vector_CreatePyObject(vi, 3, Py_NEW, NULL);
+ if (isect_point_tri_v3(pt, UNPACK3(tri), vi)) {
+ return Vector_CreatePyObject(vi, 3, NULL);
}
else {
Py_RETURN_NONE;
@@ -971,26 +831,28 @@ PyDoc_STRVAR(M_Geometry_intersect_point_tri_2d_doc,
);
static PyObject *M_Geometry_intersect_point_tri_2d(PyObject *UNUSED(self), PyObject *args)
{
- VectorObject *pt_vec, *tri_p1, *tri_p2, *tri_p3;
-
- if (!PyArg_ParseTuple(args, "O!O!O!O!:intersect_point_tri_2d",
- &vector_Type, &pt_vec,
- &vector_Type, &tri_p1,
- &vector_Type, &tri_p2,
- &vector_Type, &tri_p3))
+ const char *error_prefix = "intersect_point_tri_2d";
+ PyObject *py_pt, *py_tri[3];
+ float pt[2], tri[3][2];
+ int i;
+
+ if (!PyArg_ParseTuple(
+ args, "OOOO:intersect_point_tri_2d",
+ &py_pt, UNPACK3_EX(&, py_tri, )))
{
return NULL;
}
-
- if (BaseMath_ReadCallback(pt_vec) == -1 ||
- BaseMath_ReadCallback(tri_p1) == -1 ||
- BaseMath_ReadCallback(tri_p2) == -1 ||
- BaseMath_ReadCallback(tri_p3) == -1)
- {
+
+ if (mathutils_array_parse(pt, 2, 2 | MU_ARRAY_SPILL, py_pt, error_prefix) == -1) {
return NULL;
}
+ for (i = 0; i < ARRAY_SIZE(tri); i++) {
+ if (mathutils_array_parse(tri[i], 2, 2 | MU_ARRAY_SPILL, py_tri[i], error_prefix) == -1) {
+ return NULL;
+ }
+ }
- return PyLong_FromLong(isect_point_tri_v2(pt_vec->vec, tri_p1->vec, tri_p2->vec, tri_p3->vec));
+ return PyLong_FromLong(isect_point_tri_v2(pt, UNPACK3(tri)));
}
PyDoc_STRVAR(M_Geometry_intersect_point_quad_2d_doc,
@@ -998,7 +860,7 @@ PyDoc_STRVAR(M_Geometry_intersect_point_quad_2d_doc,
"\n"
" Takes 5 vectors (using only the x and y coordinates): one is the point and the next 4 define the quad, \n"
" only the x and y are used from the vectors. Returns 1 if the point is within the quad, otherwise 0.\n"
-" Works only with convex quads without singular edges."
+" Works only with convex quads without singular edges.\n"
"\n"
" :arg pt: Point\n"
" :type pt: :class:`mathutils.Vector`\n"
@@ -1014,28 +876,28 @@ PyDoc_STRVAR(M_Geometry_intersect_point_quad_2d_doc,
);
static PyObject *M_Geometry_intersect_point_quad_2d(PyObject *UNUSED(self), PyObject *args)
{
- VectorObject *pt_vec, *quad_p1, *quad_p2, *quad_p3, *quad_p4;
+ const char *error_prefix = "intersect_point_quad_2d";
+ PyObject *py_pt, *py_quad[4];
+ float pt[2], quad[4][2];
+ int i;
- if (!PyArg_ParseTuple(args, "O!O!O!O!O!:intersect_point_quad_2d",
- &vector_Type, &pt_vec,
- &vector_Type, &quad_p1,
- &vector_Type, &quad_p2,
- &vector_Type, &quad_p3,
- &vector_Type, &quad_p4))
+ if (!PyArg_ParseTuple(
+ args, "OOOOO:intersect_point_quad_2d",
+ &py_pt, UNPACK4_EX(&, py_quad, )))
{
return NULL;
}
- if (BaseMath_ReadCallback(pt_vec) == -1 ||
- BaseMath_ReadCallback(quad_p1) == -1 ||
- BaseMath_ReadCallback(quad_p2) == -1 ||
- BaseMath_ReadCallback(quad_p3) == -1 ||
- BaseMath_ReadCallback(quad_p4) == -1)
- {
+ if (mathutils_array_parse(pt, 2, 2 | MU_ARRAY_SPILL, py_pt, error_prefix) == -1) {
return NULL;
}
+ for (i = 0; i < ARRAY_SIZE(quad); i++) {
+ if (mathutils_array_parse(quad[i], 2, 2 | MU_ARRAY_SPILL, py_quad[i], error_prefix) == -1) {
+ return NULL;
+ }
+ }
- return PyLong_FromLong(isect_point_quad_v2(pt_vec->vec, quad_p1->vec, quad_p2->vec, quad_p3->vec, quad_p4->vec));
+ return PyLong_FromLong(isect_point_quad_v2(pt, UNPACK4(quad)));
}
PyDoc_STRVAR(M_Geometry_distance_point_to_plane_doc,
@@ -1054,35 +916,27 @@ PyDoc_STRVAR(M_Geometry_distance_point_to_plane_doc,
);
static PyObject *M_Geometry_distance_point_to_plane(PyObject *UNUSED(self), PyObject *args)
{
- VectorObject *pt, *plane_co, *plane_no;
+ const char *error_prefix = "distance_point_to_plane";
+ PyObject *py_pt, *py_plane_co, *py_plane_no;
+ float pt[3], plane_co[3], plane_no[3];
float plane[4];
- if (!PyArg_ParseTuple(args, "O!O!O!:distance_point_to_plane",
- &vector_Type, &pt,
- &vector_Type, &plane_co,
- &vector_Type, &plane_no))
- {
- return NULL;
- }
-
- if (pt->size != 3 ||
- plane_co->size != 3 ||
- plane_no->size != 3)
+ if (!PyArg_ParseTuple(
+ args, "OOO:distance_point_to_plane",
+ &py_pt, &py_plane_co, &py_plane_no))
{
- PyErr_SetString(PyExc_ValueError,
- "One of more of the vector arguments wasn't a 3D vector");
return NULL;
}
- if (BaseMath_ReadCallback(pt) == -1 ||
- BaseMath_ReadCallback(plane_co) == -1 ||
- BaseMath_ReadCallback(plane_no) == -1)
+ if (((mathutils_array_parse(pt, 3, 3 | MU_ARRAY_SPILL, py_pt, error_prefix) != -1) &&
+ (mathutils_array_parse(plane_co, 3, 3 | MU_ARRAY_SPILL, py_plane_co, error_prefix) != -1) &&
+ (mathutils_array_parse(plane_no, 3, 3 | MU_ARRAY_SPILL, py_plane_no, error_prefix) != -1)) == 0)
{
return NULL;
}
- plane_from_point_normal_v3(plane, plane_co->vec, plane_no->vec);
- return PyFloat_FromDouble(dist_signed_to_plane_v3(pt->vec, plane));
+ plane_from_point_normal_v3(plane, plane_co, plane_no);
+ return PyFloat_FromDouble(dist_signed_to_plane_v3(pt, plane));
}
PyDoc_STRVAR(M_Geometry_barycentric_transform_doc,
@@ -1109,53 +963,37 @@ PyDoc_STRVAR(M_Geometry_barycentric_transform_doc,
);
static PyObject *M_Geometry_barycentric_transform(PyObject *UNUSED(self), PyObject *args)
{
- VectorObject *vec_pt;
- VectorObject *vec_t1_tar, *vec_t2_tar, *vec_t3_tar;
- VectorObject *vec_t1_src, *vec_t2_src, *vec_t3_src;
- float vec[3];
-
- if (!PyArg_ParseTuple(args, "O!O!O!O!O!O!O!::barycentric_transform",
- &vector_Type, &vec_pt,
- &vector_Type, &vec_t1_src,
- &vector_Type, &vec_t2_src,
- &vector_Type, &vec_t3_src,
- &vector_Type, &vec_t1_tar,
- &vector_Type, &vec_t2_tar,
- &vector_Type, &vec_t3_tar))
- {
- return NULL;
- }
+ const char *error_prefix = "barycentric_transform";
+ PyObject *py_pt_src, *py_tri_src[3], *py_tri_dst[3];
+ float pt_src[3], pt_dst[3], tri_src[3][3], tri_dst[3][3];
+ int i;
- if (vec_pt->size != 3 ||
- vec_t1_src->size != 3 ||
- vec_t2_src->size != 3 ||
- vec_t3_src->size != 3 ||
- vec_t1_tar->size != 3 ||
- vec_t2_tar->size != 3 ||
- vec_t3_tar->size != 3)
+ if (!PyArg_ParseTuple(
+ args, "OOOOOOO:barycentric_transform",
+ &py_pt_src,
+ UNPACK3_EX(&, py_tri_src, ),
+ UNPACK3_EX(&, py_tri_dst, )))
{
- PyErr_SetString(PyExc_ValueError,
- "One of more of the vector arguments wasn't a 3D vector");
return NULL;
}
- if (BaseMath_ReadCallback(vec_pt) == -1 ||
- BaseMath_ReadCallback(vec_t1_src) == -1 ||
- BaseMath_ReadCallback(vec_t2_src) == -1 ||
- BaseMath_ReadCallback(vec_t3_src) == -1 ||
- BaseMath_ReadCallback(vec_t1_tar) == -1 ||
- BaseMath_ReadCallback(vec_t2_tar) == -1 ||
- BaseMath_ReadCallback(vec_t3_tar) == -1)
- {
+ if (mathutils_array_parse(pt_src, 3, 3 | MU_ARRAY_SPILL, py_pt_src, error_prefix) == -1) {
return NULL;
}
+ for (i = 0; i < ARRAY_SIZE(tri_src); i++) {
+ if (((mathutils_array_parse(tri_src[i], 3, 3 | MU_ARRAY_SPILL, py_tri_src[i], error_prefix) != -1) &&
+ (mathutils_array_parse(tri_dst[i], 3, 3 | MU_ARRAY_SPILL, py_tri_dst[i], error_prefix) != -1)) == 0)
+ {
+ return NULL;
+ }
+ }
transform_point_by_tri_v3(
- vec, vec_pt->vec,
- vec_t1_tar->vec, vec_t2_tar->vec, vec_t3_tar->vec,
- vec_t1_src->vec, vec_t2_src->vec, vec_t3_src->vec);
+ pt_dst, pt_src,
+ UNPACK3(tri_dst),
+ UNPACK3(tri_src));
- return Vector_CreatePyObject(vec, 3, Py_NEW, NULL);
+ return Vector_CreatePyObject(pt_dst, 3, NULL);
}
PyDoc_STRVAR(M_Geometry_points_in_planes_doc,
@@ -1175,8 +1013,9 @@ static PyObject *M_Geometry_points_in_planes(PyObject *UNUSED(self), PyObject *a
float (*planes)[4];
unsigned int planes_len;
- if (!PyArg_ParseTuple(args, "O:points_in_planes",
- &py_planes))
+ if (!PyArg_ParseTuple(
+ args, "O:points_in_planes",
+ &py_planes))
{
return NULL;
}
@@ -1228,10 +1067,7 @@ static PyObject *M_Geometry_points_in_planes(PyObject *UNUSED(self), PyObject *a
if (l == len) { /* ok */
/* python */
- PyObject *item = Vector_CreatePyObject(potentialVertex, 3, Py_NEW, NULL);
- PyList_Append(py_verts, item);
- Py_DECREF(item);
-
+ PyList_APPEND(py_verts, Vector_CreatePyObject(potentialVertex, 3, NULL));
planes_used[i] = planes_used[j] = planes_used[k] = true;
}
}
@@ -1247,17 +1083,16 @@ static PyObject *M_Geometry_points_in_planes(PyObject *UNUSED(self), PyObject *a
/* now make a list of used planes */
for (i = 0; i < len; i++) {
if (planes_used[i]) {
- PyObject *item = PyLong_FromLong(i);
- PyList_Append(py_plane_index, item);
- Py_DECREF(item);
+ PyList_APPEND(py_plane_index, PyLong_FromLong(i));
}
}
PyMem_Free(planes_used);
{
PyObject *ret = PyTuple_New(2);
- PyTuple_SET_ITEM(ret, 0, py_verts);
- PyTuple_SET_ITEM(ret, 1, py_plane_index);
+ PyTuple_SET_ITEMS(ret,
+ py_verts,
+ py_plane_index);
return ret;
}
}
@@ -1285,58 +1120,45 @@ PyDoc_STRVAR(M_Geometry_interpolate_bezier_doc,
);
static PyObject *M_Geometry_interpolate_bezier(PyObject *UNUSED(self), PyObject *args)
{
- VectorObject *vec_k1, *vec_h1, *vec_k2, *vec_h2;
+ const char *error_prefix = "interpolate_bezier";
+ PyObject *py_data[4];
+ float data[4][4] = {{0.0f}};
int resolu;
- int dims;
+ int dims = 0;
int i;
float *coord_array, *fp;
PyObject *list;
- float k1[4] = {0.0, 0.0, 0.0, 0.0};
- float h1[4] = {0.0, 0.0, 0.0, 0.0};
- float k2[4] = {0.0, 0.0, 0.0, 0.0};
- float h2[4] = {0.0, 0.0, 0.0, 0.0};
-
-
- if (!PyArg_ParseTuple(args, "O!O!O!O!i:interpolate_bezier",
- &vector_Type, &vec_k1,
- &vector_Type, &vec_h1,
- &vector_Type, &vec_h2,
- &vector_Type, &vec_k2, &resolu))
+ if (!PyArg_ParseTuple(
+ args, "OOOOi:interpolate_bezier",
+ UNPACK4_EX(&, py_data, ), &resolu))
{
return NULL;
}
+ for (i = 0; i < 4; i++) {
+ int dims_tmp;
+ if ((dims_tmp = mathutils_array_parse(data[i], 2, 3 | MU_ARRAY_SPILL | MU_ARRAY_ZERO, py_data[i], error_prefix)) == -1) {
+ return NULL;
+ }
+ dims = max_ii(dims, dims_tmp);
+ }
+
if (resolu <= 1) {
PyErr_SetString(PyExc_ValueError,
"resolution must be 2 or over");
return NULL;
}
- if (BaseMath_ReadCallback(vec_k1) == -1 ||
- BaseMath_ReadCallback(vec_h1) == -1 ||
- BaseMath_ReadCallback(vec_k2) == -1 ||
- BaseMath_ReadCallback(vec_h2) == -1)
- {
- return NULL;
- }
-
- dims = max_iiii(vec_k1->size, vec_h1->size, vec_h2->size, vec_k2->size);
-
- for (i = 0; i < vec_k1->size; i++) k1[i] = vec_k1->vec[i];
- for (i = 0; i < vec_h1->size; i++) h1[i] = vec_h1->vec[i];
- for (i = 0; i < vec_k2->size; i++) k2[i] = vec_k2->vec[i];
- for (i = 0; i < vec_h2->size; i++) h2[i] = vec_h2->vec[i];
-
- coord_array = MEM_callocN(dims * (resolu) * sizeof(float), "interpolate_bezier");
+ coord_array = MEM_callocN(dims * (resolu) * sizeof(float), error_prefix);
for (i = 0; i < dims; i++) {
- BKE_curve_forward_diff_bezier(k1[i], h1[i], h2[i], k2[i], coord_array + i, resolu - 1, sizeof(float) * dims);
+ BKE_curve_forward_diff_bezier(UNPACK4_EX(, data, [i]), coord_array + i, resolu - 1, sizeof(float) * dims);
}
list = PyList_New(resolu);
fp = coord_array;
for (i = 0; i < resolu; i++, fp = fp + dims) {
- PyList_SET_ITEM(list, i, Vector_CreatePyObject(fp, dims, Py_NEW, NULL));
+ PyList_SET_ITEM(list, i, Vector_CreatePyObject(fp, dims, NULL));
}
MEM_freeN(coord_array);
return list;
@@ -1576,8 +1398,9 @@ static PyObject *M_Geometry_box_pack_2d(PyObject *UNUSED(self), PyObject *boxlis
}
ret = PyTuple_New(2);
- PyTuple_SET_ITEM(ret, 0, PyFloat_FromDouble(tot_width));
- PyTuple_SET_ITEM(ret, 1, PyFloat_FromDouble(tot_height));
+ PyTuple_SET_ITEMS(ret,
+ PyFloat_FromDouble(tot_width),
+ PyFloat_FromDouble(tot_height));
return ret;
}
diff --git a/source/blender/python/mathutils/mathutils_interpolate.c b/source/blender/python/mathutils/mathutils_interpolate.c
new file mode 100644
index 00000000000..4d7841b906a
--- /dev/null
+++ b/source/blender/python/mathutils/mathutils_interpolate.c
@@ -0,0 +1,137 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributor(s): Lukas Toenne
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/python/mathutils/mathutils_interpolate.c
+ * \ingroup pymathutils
+ */
+
+
+#include <Python.h>
+
+#include "mathutils.h"
+#include "mathutils_interpolate.h"
+
+#include "BLI_math.h"
+#include "BLI_utildefines.h"
+
+#ifndef MATH_STANDALONE /* define when building outside blender */
+# include "MEM_guardedalloc.h"
+#endif
+
+/*-------------------------DOC STRINGS ---------------------------*/
+PyDoc_STRVAR(M_Interpolate_doc,
+"The Blender interpolate module"
+);
+
+/* ---------------------------------WEIGHT CALCULATION ----------------------- */
+
+#ifndef MATH_STANDALONE
+
+PyDoc_STRVAR(M_Interpolate_poly_3d_calc_doc,
+".. function:: poly_3d_calc(veclist, pt)\n"
+"\n"
+" Calculate barycentric weights for a point on a polygon.\n"
+"\n"
+" :arg veclist: list of vectors\n"
+" :arg pt: point"
+" :rtype: list of per-vector weights\n"
+);
+static PyObject *M_Interpolate_poly_3d_calc(PyObject *UNUSED(self), PyObject *args)
+{
+ float fp[3];
+ float (*vecs)[3];
+ Py_ssize_t len;
+
+ PyObject *point, *veclist, *ret;
+ int i;
+
+ if (!PyArg_ParseTuple(args, "OO!:interpolation_weights",
+ &veclist,
+ &vector_Type, &point))
+ {
+ return NULL;
+ }
+
+ if (BaseMath_ReadCallback((VectorObject *)point) == -1)
+ return NULL;
+
+ fp[0] = ((VectorObject *)point)->vec[0];
+ fp[1] = ((VectorObject *)point)->vec[1];
+ if (((VectorObject *)point)->size > 2)
+ fp[2] = ((VectorObject *)point)->vec[2];
+ else
+ fp[2] = 0.0f; /* if its a 2d vector then set the z to be zero */
+
+ len = mathutils_array_parse_alloc_v(((float **)&vecs), 3, veclist, "interpolation_weights");
+ if (len == -1) {
+ return NULL;
+ }
+
+ if (len) {
+ float *weights = MEM_mallocN(sizeof(float) * len, "interpolation weights");
+
+ interp_weights_poly_v3(weights, vecs, len, fp);
+
+ ret = PyList_New(len);
+ for (i = 0; i < len; i++) {
+ PyList_SET_ITEM(ret, i, PyFloat_FromDouble(weights[i]));
+ }
+
+ MEM_freeN(weights);
+
+ PyMem_Free(vecs);
+ }
+ else {
+ ret = PyList_New(0);
+ }
+
+ return ret;
+}
+
+#endif /* MATH_STANDALONE */
+
+
+static PyMethodDef M_Interpolate_methods[] = {
+#ifndef MATH_STANDALONE
+ {"poly_3d_calc", (PyCFunction) M_Interpolate_poly_3d_calc, METH_VARARGS, M_Interpolate_poly_3d_calc_doc},
+#endif
+ {NULL, NULL, 0, NULL}
+};
+
+static struct PyModuleDef M_Interpolate_module_def = {
+ PyModuleDef_HEAD_INIT,
+ "mathutils.interpolate", /* m_name */
+ M_Interpolate_doc, /* m_doc */
+ 0, /* m_size */
+ M_Interpolate_methods, /* m_methods */
+ NULL, /* m_reload */
+ NULL, /* m_traverse */
+ NULL, /* m_clear */
+ NULL, /* m_free */
+};
+
+/*----------------------------MODULE INIT-------------------------*/
+PyMODINIT_FUNC PyInit_mathutils_interpolate(void)
+{
+ PyObject *submodule = PyModule_Create(&M_Interpolate_module_def);
+ return submodule;
+}
diff --git a/source/blender/python/mathutils/mathutils_interpolate.h b/source/blender/python/mathutils/mathutils_interpolate.h
new file mode 100644
index 00000000000..1bbff6f3286
--- /dev/null
+++ b/source/blender/python/mathutils/mathutils_interpolate.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): Lukas Toenne
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __MATHUTILS_INTERPOLATE_H__
+#define __MATHUTILS_INTERPOLATE_H__
+
+/** \file blender/python/mathutils/mathutils_interpolate.h
+ * \ingroup pymathutils
+ */
+
+PyMODINIT_FUNC PyInit_mathutils_interpolate(void);
+
+#endif /* __MATHUTILS_INTERPOLATE_H__ */
diff --git a/source/blender/python/mathutils/mathutils_kdtree.c b/source/blender/python/mathutils/mathutils_kdtree.c
index 519778aea7d..199c2e02da4 100644
--- a/source/blender/python/mathutils/mathutils_kdtree.c
+++ b/source/blender/python/mathutils/mathutils_kdtree.c
@@ -35,6 +35,7 @@
#include "BLI_kdtree.h"
#include "../generic/py_capi_utils.h"
+#include "../generic/python_utildefines.h"
#include "mathutils.h"
#include "mathutils_kdtree.h" /* own include */
@@ -58,9 +59,10 @@ static void kdtree_nearest_to_py_tuple(const KDTreeNearest *nearest, PyObject *p
BLI_assert(nearest->index >= 0);
BLI_assert(PyTuple_GET_SIZE(py_retval) == 3);
- PyTuple_SET_ITEM(py_retval, 0, Vector_CreatePyObject((float *)nearest->co, 3, Py_NEW, NULL));
- PyTuple_SET_ITEM(py_retval, 1, PyLong_FromLong(nearest->index));
- PyTuple_SET_ITEM(py_retval, 2, PyFloat_FromDouble(nearest->dist));
+ PyTuple_SET_ITEMS(py_retval,
+ Vector_CreatePyObject((float *)nearest->co, 3, NULL),
+ PyLong_FromLong(nearest->index),
+ PyFloat_FromDouble(nearest->dist));
}
static PyObject *kdtree_nearest_to_py(const KDTreeNearest *nearest)
@@ -126,7 +128,7 @@ static void PyKDTree__tp_dealloc(PyKDTree *self)
}
PyDoc_STRVAR(py_kdtree_insert_doc,
-".. method:: insert(index, co)\n"
+".. method:: insert(co, index)\n"
"\n"
" Insert a point into the KDTree.\n"
"\n"
@@ -171,6 +173,10 @@ PyDoc_STRVAR(py_kdtree_balance_doc,
".. method:: balance()\n"
"\n"
" Balance the tree.\n"
+"\n"
+".. note::\n"
+"\n"
+" This builds the entire tree, avoid calling after each insertion.\n"
);
static PyObject *py_kdtree_balance(PyKDTree *self)
{
diff --git a/source/blender/python/mathutils/mathutils_noise.c b/source/blender/python/mathutils/mathutils_noise.c
index 8dfa7904300..f0449c23dcd 100644
--- a/source/blender/python/mathutils/mathutils_noise.c
+++ b/source/blender/python/mathutils/mathutils_noise.c
@@ -34,8 +34,6 @@
#include <Python.h>
-#include "structseq.h"
-
#include "BLI_math.h"
#include "BLI_noise.h"
#include "BLI_utildefines.h"
@@ -311,7 +309,7 @@ static PyObject *M_Noise_random_unit_vector(PyObject *UNUSED(self), PyObject *ar
norm = normalize_vn(vec, size);
}
- return Vector_CreatePyObject(vec, size, Py_NEW, NULL);
+ return Vector_CreatePyObject(vec, size, NULL);
}
/* This is dumb, most people will want a unit vector anyway, since this doesn't have uniform distribution over a sphere*/
#if 0
@@ -340,7 +338,7 @@ static PyObject *M_Noise_random_vector(PyObject *UNUSED(self), PyObject *args)
rand_vn(vec, size);
- return Vector_CreatePyObject(vec, size, Py_NEW, NULL);
+ return Vector_CreatePyObject(vec, size, NULL);
}
#endif
@@ -414,7 +412,7 @@ static PyObject *M_Noise_noise_vector(PyObject *UNUSED(self), PyObject *args)
noise_vector(vec[0], vec[1], vec[2], nb, r_vec);
- return Vector_CreatePyObject(r_vec, 3, Py_NEW, NULL);
+ return Vector_CreatePyObject(r_vec, 3, NULL);
}
PyDoc_STRVAR(M_Noise_turbulence_doc,
@@ -486,7 +484,7 @@ static PyObject *M_Noise_turbulence_vector(PyObject *UNUSED(self), PyObject *arg
return NULL;
vTurb(vec[0], vec[1], vec[2], oct, hd, nb, as, fs, r_vec);
- return Vector_CreatePyObject(r_vec, 3, Py_NEW, NULL);
+ return Vector_CreatePyObject(r_vec, 3, NULL);
}
/* F. Kenton Musgrave's fractal functions */
@@ -738,7 +736,7 @@ static PyObject *M_Noise_voronoi(PyObject *UNUSED(self), PyObject *args)
voronoi(vec[0], vec[1], vec[2], da, pa, me, dtype);
for (i = 0; i < 4; i++) {
- PyList_SET_ITEM(list, i, Vector_CreatePyObject(pa + 3 * i, 3, Py_NEW, NULL));
+ PyList_SET_ITEM(list, i, Vector_CreatePyObject(pa + 3 * i, 3, NULL));
}
return Py_BuildValue("[[ffff]O]", da[0], da[1], da[2], da[3], list);
@@ -790,7 +788,7 @@ static PyObject *M_Noise_cell_vector(PyObject *UNUSED(self), PyObject *args)
return NULL;
cellNoiseV(vec[0], vec[1], vec[2], r_vec);
- return Vector_CreatePyObject(r_vec, 3, Py_NEW, NULL);
+ return Vector_CreatePyObject(r_vec, 3, NULL);
}
static PyMethodDef M_Noise_methods[] = {
diff --git a/source/blender/quicktime/CMakeLists.txt b/source/blender/quicktime/CMakeLists.txt
index b0a8c92e559..f853c35457f 100644
--- a/source/blender/quicktime/CMakeLists.txt
+++ b/source/blender/quicktime/CMakeLists.txt
@@ -52,10 +52,11 @@ set(SRC
add_definitions(-DWITH_QUICKTIME)
if(WITH_AUDASPACE)
- list(APPEND INC
- ../../../intern/audaspace/intern
+ add_definitions(${AUDASPACE_DEFINITIONS})
+
+ list(APPEND INC_SYS
+ ${AUDASPACE_C_INCLUDE_DIRS}
)
- add_definitions(-DWITH_AUDASPACE)
endif()
blender_add_lib(bf_quicktime "${SRC}" "${INC}" "${INC_SYS}")
diff --git a/source/blender/quicktime/SConscript b/source/blender/quicktime/SConscript
index 9b367a434f2..746662ebf3e 100644
--- a/source/blender/quicktime/SConscript
+++ b/source/blender/quicktime/SConscript
@@ -44,8 +44,7 @@ incs = ['.',
'../imbuf',
'../imbuf/intern',
'../render/extern/include',
- '../editors/include',
- '#/intern/audaspace/intern']
+ '../editors/include']
incs.append(env['BF_QUICKTIME_INC'])
@@ -54,6 +53,10 @@ priorities = [200,235]
defs=['WITH_QUICKTIME']
+if env['WITH_BF_AUDASPACE']:
+ defs += env['BF_AUDASPACE_DEF']
+ incs.append(env['BF_AUDASPACE_C_INC'])
+
if env['C_COMPILER_ID'] == 'gcc' and env['CCVERSION'] >= '4.6': # always use default-Apple-gcc for objC language, gnu-compilers do not support it fully yet
env.BlenderLib ('bf_quicktime', sources=source_files, includes=incs, defines=defs, libtype=types, priority=priorities, cc_compilerchange='/usr/bin/gcc', cxx_compilerchange='/usr/bin/g++')
else:
diff --git a/source/blender/quicktime/apple/qtkit_export.m b/source/blender/quicktime/apple/qtkit_export.m
index 0c193df3861..9bc4ec444bb 100644
--- a/source/blender/quicktime/apple/qtkit_export.m
+++ b/source/blender/quicktime/apple/qtkit_export.m
@@ -35,7 +35,7 @@
#include "DNA_userdef_types.h"
#ifdef WITH_AUDASPACE
-# include "AUD_C-API.h"
+# include AUD_DEVICE_H
#endif
#include "BLI_utildefines.h"
@@ -98,8 +98,6 @@ typedef struct QuicktimeExport {
} QuicktimeExport;
-static struct QuicktimeExport *qtexport;
-
#define AUDIOOUTPUTBUFFERSIZE 65536
#pragma mark rna helper functions
@@ -219,10 +217,21 @@ static NSString *stringWithCodecType(int codecType)
return [NSString stringWithCString:str encoding:NSASCIIStringEncoding];
}
-void makeqtstring(RenderData *rd, char *string)
+void makeqtstring(RenderData *rd, char *string, bool preview)
{
+ int sfra, efra;
+
char txt[64];
+ if (preview) {
+ sfra = rd->psfra;
+ efra = rd->pefra;
+ }
+ else {
+ sfra = rd->sfra;
+ efra = rd->efra;
+ }
+
strcpy(string, rd->pic);
BLI_path_abs(string, G.main->name);
@@ -234,10 +243,21 @@ void makeqtstring(RenderData *rd, char *string)
}
}
-void filepath_qt(char *string, RenderData *rd)
+void filepath_qt(char *string, RenderData *rd, bool preview, const char *suffix)
{
+ int sfra, efra;
+
if (string == NULL) return;
+ if (preview) {
+ sfra = rd->psfra;
+ efra = rd->pefra;
+ }
+ else {
+ sfra = rd->sfra;
+ efra = rd->efra;
+ }
+
strcpy(string, rd->pic);
BLI_path_abs(string, G.main->name);
@@ -245,17 +265,32 @@ void filepath_qt(char *string, RenderData *rd)
if (rd->scemode & R_EXTENSION) {
if (!BLI_testextensie(string, ".mov")) {
- BLI_path_frame_range(string, rd->sfra, rd->efra, 4);
+ BLI_path_frame_range(string, sfra, efra, 4);
strcat(string, ".mov");
}
}
else {
if (BLI_path_frame_check_chars(string)) {
- BLI_path_frame_range(string, rd->sfra, rd->efra, 4);
+ BLI_path_frame_range(string, sfra, efra, 4);
}
}
+
+ BLI_path_suffix(string, FILE_MAX, suffix, "");
}
+void *context_create_qt(void)
+{
+ QuicktimeExport *qtexport = MEM_callocN(sizeof(QuicktimeExport), "QuicktimeExport");
+ return qtexport;
+}
+
+void context_free_qt(void *context_v)
+{
+ QuicktimeExport *qtexport = context_v;
+ if (qtexport) {
+ MEM_freeN(qtexport);
+ }
+}
#pragma mark audio export functions
@@ -280,12 +315,13 @@ static OSStatus write_cookie(AudioConverterRef converter, AudioFileID outfile)
}
/* AudioConverter input stream callback */
-static OSStatus AudioConverterInputCallback(AudioConverterRef inAudioConverter,
+static OSStatus AudioConverterInputCallback(AudioConverterRef inAudioConverter,
UInt32* ioNumberDataPackets,
AudioBufferList* ioData,
AudioStreamPacketDescription** outDataPacketDescription,
void* inUserData)
-{
+{
+ QuicktimeExport *qtexport = inUserData;
if (qtexport->audioTotalExportedFrames >= qtexport->audioLastFrame) { /* EOF */
*ioNumberDataPackets = 0;
return noErr;
@@ -299,8 +335,8 @@ static OSStatus AudioConverterInputCallback(AudioConverterRef inAudioConverter,
qtexport->audioTotalExportedFrames += *ioNumberDataPackets;
- AUD_readDevice(qtexport->audioInputDevice, (UInt8 *)qtexport->audioInputBuffer,
- qtexport->audioInputFormat.mFramesPerPacket * *ioNumberDataPackets);
+ AUD_Device_read(qtexport->audioInputDevice, (UInt8 *)qtexport->audioInputBuffer,
+ qtexport->audioInputFormat.mFramesPerPacket * *ioNumberDataPackets);
ioData->mBuffers[0].mDataByteSize = qtexport->audioInputFormat.mBytesPerPacket * *ioNumberDataPackets;
ioData->mBuffers[0].mData = qtexport->audioInputBuffer;
@@ -312,15 +348,26 @@ static OSStatus AudioConverterInputCallback(AudioConverterRef inAudioConverter,
#pragma mark export functions
-int start_qt(struct Scene *scene, struct RenderData *rd, int rectx, int recty, ReportList *reports)
+int start_qt(
+ void *context_v, struct Scene *scene, struct RenderData *rd, int UNUSED(rectx), int UNUSED(recty),
+ ReportList *reports, bool preview, const char *UNUSED(suffix))
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSError *error;
char name[1024];
int success = 1;
OSStatus err = noErr;
+ int sfra, efra;
+ QuicktimeExport *qtexport = context_v;
- if (qtexport == NULL) qtexport = MEM_callocN(sizeof(QuicktimeExport), "QuicktimeExport");
+ if (preview) {
+ sfra = rd->psfra;
+ efra = rd->pefra;
+ }
+ else {
+ sfra = rd->sfra;
+ efra = rd->efra;
+ }
[QTMovie enterQTKitOnThread];
@@ -330,9 +377,8 @@ int start_qt(struct Scene *scene, struct RenderData *rd, int rectx, int recty, R
success = 0;
}
else {
- makeqtstring(rd, name);
- qtexport->filename = [[NSString alloc] initWithCString:name
- encoding:[NSString defaultCStringEncoding]];
+ makeqtstring(rd, name, preview);
+ qtexport->filename = [[NSString alloc] initWithUTF8String:name];
qtexport->movie = nil;
qtexport->audioFile = NULL;
@@ -591,13 +637,13 @@ int start_qt(struct Scene *scene, struct RenderData *rd, int rectx, int recty, R
specs.format = U.audioformat;
specs.rate = U.audiorate;
qtexport->audioInputDevice = AUD_openReadDevice(specs);
- AUD_playDevice(qtexport->audioInputDevice, scene->sound_scene, rd->sfra * rd->frs_sec_base / rd->frs_sec);
+ AUD_playDevice(qtexport->audioInputDevice, scene->sound_scene, sfra * rd->frs_sec_base / rd->frs_sec);
qtexport->audioOutputPktPos = 0;
qtexport->audioTotalExportedFrames = 0;
qtexport->audioTotalSavedFrames = 0;
- qtexport->audioLastFrame = (rd->efra - rd->sfra) * qtexport->audioInputFormat.mSampleRate * rd->frs_sec_base / rd->frs_sec;
+ qtexport->audioLastFrame = (efra - sfra) * qtexport->audioInputFormat.mSampleRate * rd->frs_sec_base / rd->frs_sec;
}
}
}
@@ -607,7 +653,9 @@ int start_qt(struct Scene *scene, struct RenderData *rd, int rectx, int recty, R
return success;
}
-int append_qt(struct RenderData *rd, int start_frame, int frame, int *pixels, int rectx, int recty, ReportList *reports)
+int append_qt(
+ void *context_v, struct RenderData *rd, int start_frame, int frame, int *pixels, int rectx, int recty,
+ const char *UNUSED(suffix), ReportList *reports)
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSBitmapImageRep *blBitmapFormatImage;
@@ -615,6 +663,7 @@ int append_qt(struct RenderData *rd, int start_frame, int frame, int *pixels, in
OSStatus err = noErr;
unsigned char *from_Ptr,*to_Ptr;
int y,from_i,to_i;
+ QuicktimeExport *qtexport = context_v;
/* Create bitmap image rep in blender format (32bit RGBA) */
blBitmapFormatImage = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:NULL
@@ -654,7 +703,7 @@ int append_qt(struct RenderData *rd, int start_frame, int frame, int *pixels, in
UInt32 audioPacketsConverted;
// Upper limit on total exported audio frames for this particular video frame
- const UInt64 exportedAudioFrameLimit = (frame - rd->sfra) * qtexport->audioInputFormat.mSampleRate * rd->frs_sec_base / rd->frs_sec;
+ const UInt64 exportedAudioFrameLimit = (frame - start_frame) * qtexport->audioInputFormat.mSampleRate * rd->frs_sec_base / rd->frs_sec;
/* Append audio */
while (qtexport->audioTotalExportedFrames < exportedAudioFrameLimit) {
@@ -672,7 +721,7 @@ int append_qt(struct RenderData *rd, int start_frame, int frame, int *pixels, in
audioPacketsConverted = 1;
err = AudioConverterFillComplexBuffer(qtexport->audioConverter, AudioConverterInputCallback,
- NULL, &audioPacketsConverted, &qtexport->audioBufferList, qtexport->audioOutputPktDesc);
+ qtexport, &audioPacketsConverted, &qtexport->audioBufferList, qtexport->audioOutputPktDesc);
if (audioPacketsConverted) {
AudioFileWritePackets(qtexport->audioFile, false, qtexport->audioBufferList.mBuffers[0].mDataByteSize,
qtexport->audioOutputPktDesc, qtexport->audioOutputPktPos, &audioPacketsConverted, qtexport->audioOutputBuffer);
@@ -705,9 +754,11 @@ int append_qt(struct RenderData *rd, int start_frame, int frame, int *pixels, in
}
-void end_qt(void)
+void end_qt(void *context_v)
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+ QuicktimeExport *qtexport = context_v;
+
if (qtexport->movie) {
if (qtexport->audioFile)
@@ -740,7 +791,7 @@ void end_qt(void)
write_cookie(qtexport->audioConverter, qtexport->audioFile);
AudioConverterDispose(qtexport->audioConverter);
AudioFileClose(qtexport->audioFile);
- AUD_closeReadDevice(qtexport->audioInputDevice);
+ AUD_Device_free(qtexport->audioInputDevice);
qtexport->audioFile = NULL;
qtexport->audioInputDevice = NULL;
MEM_freeN(qtexport->audioInputBuffer);
@@ -798,11 +849,6 @@ void end_qt(void)
}
[QTMovie exitQTKitOnThread];
-
- if (qtexport) {
- MEM_freeN(qtexport);
- qtexport = NULL;
- }
[pool drain];
}
@@ -814,22 +860,26 @@ void free_qtcomponentdata(void)
void quicktime_verify_image_type(RenderData *rd, ImageFormatData *imf)
{
if (imf->imtype == R_IMF_IMTYPE_QUICKTIME) {
- if ((rd->qtcodecsettings.codecType<= 0) ||
- (rd->qtcodecsettings.codecSpatialQuality <0) ||
- (rd->qtcodecsettings.codecSpatialQuality > 100)) {
-
+ if ((rd->qtcodecsettings.codecType <= 0) ||
+ (rd->qtcodecsettings.codecSpatialQuality < 0) ||
+ (rd->qtcodecsettings.codecSpatialQuality > 100))
+ {
rd->qtcodecsettings.codecType = kJPEGCodecType;
- rd->qtcodecsettings.codecSpatialQuality = (codecHighQuality*100)/codecLosslessQuality;
+ rd->qtcodecsettings.codecSpatialQuality = (codecHighQuality * 100) / codecLosslessQuality;
}
if ((rd->qtcodecsettings.audioSampleRate < 21000) ||
- (rd->qtcodecsettings.audioSampleRate > 193000))
+ (rd->qtcodecsettings.audioSampleRate > 193000))
+ {
rd->qtcodecsettings.audioSampleRate = 48000;
+ }
- if (rd->qtcodecsettings.audioBitDepth == 0)
+ if (rd->qtcodecsettings.audioBitDepth == 0) {
rd->qtcodecsettings.audioBitDepth = AUD_FORMAT_S16;
+ }
- if (rd->qtcodecsettings.audioBitRate == 0)
+ if (rd->qtcodecsettings.audioBitRate == 0) {
rd->qtcodecsettings.audioBitRate = 256000;
+ }
}
}
diff --git a/source/blender/quicktime/apple/qtkit_import.m b/source/blender/quicktime/apple/qtkit_import.m
index 9318c896d7c..d42d0ee8ebb 100644
--- a/source/blender/quicktime/apple/qtkit_import.m
+++ b/source/blender/quicktime/apple/qtkit_import.m
@@ -88,6 +88,7 @@ int anim_is_quicktime(const char *name)
".swf",
".txt",
".mpg",
+ ".vob", /* disabled, vob is essential .mpg, don't handle */
".avi", /* wouldn't be appropriate ;) */
".mov", /* disabled, suboptimal decoding speed */
".mp4", /* disabled, suboptimal decoding speed */
diff --git a/source/blender/quicktime/quicktime_export.h b/source/blender/quicktime/quicktime_export.h
index a499cd462b7..8a10a4a05d6 100644
--- a/source/blender/quicktime/quicktime_export.h
+++ b/source/blender/quicktime/quicktime_export.h
@@ -54,12 +54,13 @@ struct ImageFormatData;
struct RenderData;
struct ReportList;
struct Scene;
-struct wmOperatorType;
-int start_qt(struct Scene *scene, struct RenderData *rd, int rectx, int recty, struct ReportList *reports); //for movie handle (BKE writeavi.c now)
-int append_qt(struct RenderData *rd, int start_frame, int frame, int *pixels, int rectx, int recty, struct ReportList *reports);
-void end_qt(void);
-void filepath_qt(char *string, struct RenderData *rd);
+int start_qt(void *context_v, struct Scene *scene, struct RenderData *rd, int rectx, int recty, struct ReportList *reports, bool preview, const char *suffix); //for movie handle (BKE writeavi.c now)
+int append_qt(void *context_v, struct RenderData *rd, int start_frame, int frame, int *pixels, int rectx, int recty, const char *suffix, struct ReportList *reports);
+void end_qt(void *context_v);
+void filepath_qt(char *string, struct RenderData *rd, bool preview, const char *suffix);
+void *context_create_qt(void);
+void context_free_qt(void *context_v);
/*RNA helper functions */
void quicktime_verify_image_type(struct RenderData *rd, struct ImageFormatData *imf); //used by RNA for defaults values init, if needed
@@ -76,7 +77,7 @@ int quicktime_rnatmpvalue_from_audiocodectype(int codecType);
int quicktime_audiocodecType_from_rnatmpvalue(int rnatmpvalue);
void free_qtcomponentdata(void);
-void makeqtstring(struct RenderData *rd, char *string); //for playanim.c
+void makeqtstring(struct RenderData *rd, char *string, bool preview); //for playanim.c
diff --git a/source/blender/render/CMakeLists.txt b/source/blender/render/CMakeLists.txt
index 8e326e770fc..9e40ab02ee4 100644
--- a/source/blender/render/CMakeLists.txt
+++ b/source/blender/render/CMakeLists.txt
@@ -27,12 +27,14 @@
set(INC
extern/include
intern/include
- ../blenfont
../blenkernel
../blenlib
+ ../blentranslation
../imbuf
+ ../depsgraph
../makesdna
../makesrna
+ ../physics
../../../intern/guardedalloc
../../../intern/mikktspace
../../../intern/smoke/extern
@@ -162,6 +164,10 @@ if(WITH_INTERNATIONAL)
add_definitions(-DWITH_INTERNATIONAL)
endif()
+if(WITH_CYCLES AND WITH_CYCLES_DEBUG)
+ add_definitions(-DWITH_CYCLES_DEBUG)
+endif()
+
if(APPLE)
# SSE math is enabled by default on x86_64
if(CMAKE_OSX_ARCHITECTURES MATCHES "i386")
diff --git a/source/blender/render/SConscript b/source/blender/render/SConscript
index 297e4fcecd4..16d9b4a832d 100644
--- a/source/blender/render/SConscript
+++ b/source/blender/render/SConscript
@@ -34,13 +34,14 @@ incs = [
'extern/include',
'intern/include',
'#/intern/guardedalloc',
- '../blenfont',
'../blenkernel',
'../blenlib',
+ '../blentranslation',
'../imbuf',
- '../include',
+ '../depsgraph',
'../makesdna',
'../makesrna',
+ '../physics',
'../../../intern/mikktspace',
'../../../intern/smoke/extern',
]
@@ -103,6 +104,9 @@ if env['WITH_BF_GAMEENGINE']:
if env['WITH_BF_INTERNATIONAL']:
defs.append('WITH_INTERNATIONAL')
+if env['WITH_BF_CYCLES'] and env['WITH_BF_CYCLES_DEBUG']:
+ defs.append('WITH_CYCLES_DEBUG')
+
if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'linuxcross', 'win64-vc', 'win64-mingw'):
incs += ' ' + env['BF_PTHREADS_INC']
diff --git a/source/blender/render/extern/include/RE_bake.h b/source/blender/render/extern/include/RE_bake.h
index 481da452529..0750ea1aa28 100644
--- a/source/blender/render/extern/include/RE_bake.h
+++ b/source/blender/render/extern/include/RE_bake.h
@@ -32,6 +32,7 @@
#ifndef __RE_BAKE_H__
#define __RE_BAKE_H__
+struct ImBuf;
struct Render;
struct Mesh;
@@ -49,29 +50,28 @@ typedef struct BakeImages {
} BakeImages;
typedef struct BakePixel {
- int primitive_id;
+ int primitive_id, object_id;
float uv[2];
float du_dx, du_dy;
float dv_dx, dv_dy;
} BakePixel;
typedef struct BakeHighPolyData {
- struct BakePixel *pixel_array;
struct Object *ob;
struct ModifierData *tri_mod;
struct Mesh *me;
char restrict_flag;
+ bool is_flip_object;
float obmat[4][4];
float imat[4][4];
- float rotmat[4][4];
} BakeHighPolyData;
/* external_engine.c */
bool RE_bake_has_engine(struct Render *re);
bool RE_bake_engine(
- struct Render *re, struct Object *object, const BakePixel pixel_array[],
+ struct Render *re, struct Object *object, const int object_id, const BakePixel pixel_array[],
const size_t num_pixels, const int depth, const ScenePassType pass_type, float result[]);
/* bake.c */
@@ -81,7 +81,7 @@ bool RE_bake_internal(
const size_t num_pixels, const int depth, const ScenePassType pass_type, float result[]);
bool RE_bake_pixels_populate_from_objects(
- struct Mesh *me_low, BakePixel pixel_array_from[],
+ struct Mesh *me_low, BakePixel pixel_array_from[], BakePixel pixel_array_to[],
BakeHighPolyData highpoly[], const int tot_highpoly, const size_t num_pixels, const bool is_custom_cage,
const float cage_extrusion, float mat_low[4][4], float mat_cage[4][4], struct Mesh *me_cage);
diff --git a/source/blender/render/extern/include/RE_engine.h b/source/blender/render/extern/include/RE_engine.h
index 24f8cbee401..4e48060c54f 100644
--- a/source/blender/render/extern/include/RE_engine.h
+++ b/source/blender/render/extern/include/RE_engine.h
@@ -60,6 +60,8 @@ struct BakePixel;
#define RE_USE_SHADING_NODES 16
#define RE_USE_EXCLUDE_LAYERS 32
#define RE_USE_SAVE_BUFFERS 64
+#define RE_USE_TEXTURE_PREVIEW 128
+#define RE_USE_SHADING_NODES_CUSTOM 256
/* RenderEngine.flag */
#define RE_ENGINE_ANIMATION 1
@@ -87,7 +89,7 @@ typedef struct RenderEngineType {
void (*update)(struct RenderEngine *engine, struct Main *bmain, struct Scene *scene);
void (*render)(struct RenderEngine *engine, struct Scene *scene);
- void (*bake)(struct RenderEngine *engine, struct Scene *scene, struct Object *object, const int pass_type, const struct BakePixel *pixel_array, const int num_pixels, const int depth, void *result);
+ void (*bake)(struct RenderEngine *engine, struct Scene *scene, struct Object *object, const int pass_type, const int object_id, const struct BakePixel *pixel_array, const int num_pixels, const int depth, void *result);
void (*view_update)(struct RenderEngine *engine, const struct bContext *context);
void (*view_draw)(struct RenderEngine *engine, const struct bContext *context);
@@ -134,15 +136,20 @@ void RE_engine_free(RenderEngine *engine);
void RE_layer_load_from_file(struct RenderLayer *layer, struct ReportList *reports, const char *filename, int x, int y);
void RE_result_load_from_file(struct RenderResult *result, struct ReportList *reports, const char *filename);
-struct RenderResult *RE_engine_begin_result(RenderEngine *engine, int x, int y, int w, int h, const char *layername);
+struct RenderResult *RE_engine_begin_result(RenderEngine *engine, int x, int y, int w, int h, const char *layername, const char *viewname);
void RE_engine_update_result(RenderEngine *engine, struct RenderResult *result);
void RE_engine_end_result(RenderEngine *engine, struct RenderResult *result, int cancel, int merge_results);
+void RE_engine_active_view_set(RenderEngine *engine, const char *viewname);
+float RE_engine_get_camera_shift_x(RenderEngine *engine, struct Object *camera);
+void RE_engine_get_camera_model_matrix(RenderEngine *engine, struct Object *camera, float *r_modelmat);
+
int RE_engine_test_break(RenderEngine *engine);
void RE_engine_update_stats(RenderEngine *engine, const char *stats, const char *info);
void RE_engine_update_progress(RenderEngine *engine, float progress);
void RE_engine_update_memory_stats(RenderEngine *engine, float mem_used, float mem_peak);
void RE_engine_report(RenderEngine *engine, int type, const char *msg);
+void RE_engine_set_error_message(RenderEngine *engine, const char *msg);
int RE_engine_render(struct Render *re, int do_all);
@@ -157,7 +164,7 @@ void RE_engines_exit(void);
RenderEngineType *RE_engines_find(const char *idname);
-void RE_engine_get_current_tiles(struct Render *re, int *total_tiles_r, rcti **tiles_r);
+rcti* RE_engine_get_current_tiles(struct Render *re, int *r_total_tiles, bool *r_needs_free);
struct RenderData *RE_engine_get_render_data(struct Render *re);
void RE_bake_engine_set_engine_parameters(struct Render *re, struct Main *bmain, struct Scene *scene);
diff --git a/source/blender/render/extern/include/RE_pipeline.h b/source/blender/render/extern/include/RE_pipeline.h
index 3b54de4c943..fd56c47c309 100644
--- a/source/blender/render/extern/include/RE_pipeline.h
+++ b/source/blender/render/extern/include/RE_pipeline.h
@@ -35,8 +35,10 @@
#include "DNA_listBase.h"
#include "DNA_vec_types.h"
+struct bMovieHandle;
struct bNodeTree;
struct Image;
+struct ImageFormatData;
struct Main;
struct NodeBlurData;
struct Object;
@@ -46,6 +48,8 @@ struct ReportList;
struct Scene;
struct SceneRenderLayer;
struct EnvMap;
+struct RenderResult;
+struct StampData;
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
/* this include is what is exposed of render to outside world */
@@ -65,6 +69,19 @@ typedef struct Render Render;
* and how it's converted
*/
+typedef struct RenderView {
+ struct RenderView *next, *prev;
+ char name[64]; /* EXR_VIEW_MAXNAME */
+
+ /* if this exists, result of composited layers */
+ float *rectf;
+ /* if this exists, result of composited layers */
+ float *rectz;
+ /* optional, 32 bits version of picture, used for sequencer, ogl render and image curves */
+ int *rect32;
+
+} RenderView;
+
typedef struct RenderPass {
struct RenderPass *next, *prev;
int passtype, channels;
@@ -72,11 +89,23 @@ typedef struct RenderPass {
char chan_id[8]; /* amount defined in openexr_multi.h */
float *rect;
int rectx, recty;
+
+ char internal_name[64]; /* EXR_PASS_MAXNAME */
+ char view[64]; /* EXR_VIEW_MAXNAME */
+ int view_id; /* quick lookup */
+
+ int debug_type;
} RenderPass;
+enum {
+ RENDER_PASS_DEBUG_BVH_TRAVERSAL_STEPS = 0,
+ RENDER_PASS_DEBUG_BVH_TRAVERSED_INSTANCES = 1,
+ RENDER_PASS_DEBUG_RAY_BOUNCES = 2,
+};
+
/* a renderlayer is a full image, but with all passes and samples */
/* size of the rects is defined in RenderResult */
-/* after render, the Combined pass is in rectf, for renderlayers read from files it is a real pass */
+/* after render, the Combined pass is in combined, for renderlayers read from files it is a real pass */
typedef struct RenderLayer {
struct RenderLayer *next, *prev;
@@ -87,8 +116,10 @@ typedef struct RenderLayer {
struct Material *mat_override;
struct Group *light_override;
-
- float *rectf; /* 4 float, standard rgba buffer (read not above!) */
+
+ /* MULTIVIEW_TODO: acolrect and scolrect are not supported by multiview at the moment.
+ * If they are really required they should be in RenderView instead */
+
float *acolrect; /* 4 float, optional transparent buffer, needs storage for display updates */
float *scolrect; /* 4 float, optional strand buffer, needs storage for display updates */
int *display_buffer; /* 4 char, optional color managed display buffer which is used when
@@ -109,6 +140,9 @@ typedef struct RenderResult {
int rectx, recty;
short crop, sample_nr;
+ /* the following rect32, rectf and rectz buffers are for temporary storage only, for RenderResult structs
+ * created in #RE_AcquireResultImage - which do not have RenderView */
+
/* optional, 32 bits version of picture, used for ogl render and image curves */
int *rect32;
/* if this exists, a copy of one of layers, or result of composited layers */
@@ -124,6 +158,9 @@ typedef struct RenderResult {
/* the main buffers */
ListBase layers;
+ /* multiView maps to a StringVector in OpenEXR */
+ ListBase views;
+
/* allowing live updates: */
volatile rcti renrect;
volatile RenderLayer *renlay;
@@ -139,7 +176,9 @@ typedef struct RenderResult {
/* render info text */
char *text;
-
+ char *error;
+
+ struct StampData *stamp_data;
} RenderResult;
@@ -168,6 +207,10 @@ void RE_InitRenderCB(struct Render *re);
void RE_FreeRender(struct Render *re);
/* only called on exit */
void RE_FreeAllRender(void);
+/* Free memory used by persistent data.
+ * Invoked when loading new file.
+ */
+void RE_FreeAllPersistentData(void);
/* only call on file load */
void RE_FreeAllRenderResults(void);
/* for external render engines that can keep persistent data */
@@ -178,16 +221,18 @@ void RE_FreeRenderResult(struct RenderResult *rr);
struct RenderResult *RE_AcquireResultRead(struct Render *re);
struct RenderResult *RE_AcquireResultWrite(struct Render *re);
void RE_ReleaseResult(struct Render *re);
-void RE_AcquireResultImage(struct Render *re, struct RenderResult *rr);
+void RE_AcquireResultImageViews(struct Render *re, struct RenderResult *rr);
+void RE_ReleaseResultImageViews(struct Render *re, struct RenderResult *rr);
+void RE_AcquireResultImage(struct Render *re, struct RenderResult *rr, const int view_id);
void RE_ReleaseResultImage(struct Render *re);
void RE_SwapResult(struct Render *re, struct RenderResult **rr);
struct RenderStats *RE_GetStats(struct Render *re);
void RE_ResultGet32(struct Render *re, unsigned int *rect);
-void RE_AcquiredResultGet32(struct Render *re, struct RenderResult *result, unsigned int *rect);
+void RE_AcquiredResultGet32(struct Render *re, struct RenderResult *result, unsigned int *rect, const int view_id);
struct RenderLayer *RE_GetRenderLayer(struct RenderResult *rr, const char *name);
-float *RE_RenderLayerGetPass(struct RenderLayer *rl, int passtype);
+float *RE_RenderLayerGetPass(volatile struct RenderLayer *rl, int passtype, const char *viewname);
/* obligatory initialize call, disprect is optional */
void RE_InitState(struct Render *re, struct Render *source, struct RenderData *rd,
@@ -198,6 +243,7 @@ void RE_ChangeModeFlag(struct Render *re, int flag, bool clear);
/* set up the viewplane/perspective matrix, three choices */
struct Object *RE_GetCamera(struct Render *re); /* return camera override if set */
+void RE_SetOverrideCamera(struct Render *re, struct Object *camera);
void RE_SetCamera(struct Render *re, struct Object *camera);
void RE_SetEnvmapCamera(struct Render *re, struct Object *cam_ob, float viewscale, float clipsta, float clipend);
void RE_SetWindow(struct Render *re, rctf *viewplane, float clipsta, float clipend);
@@ -227,6 +273,11 @@ void RE_init_threadcount(Render *re);
/* the main processor, assumes all was set OK! */
void RE_TileProcessor(struct Render *re);
+bool RE_WriteRenderViewsImage(struct ReportList *reports, struct RenderResult *rr, struct Scene *scene, const bool stamp, char *name);
+bool RE_WriteRenderViewsMovie(struct ReportList *reports, struct RenderResult *rr, struct Scene *scene, struct RenderData *rd,
+ struct bMovieHandle *mh, const size_t width, const size_t height, void **movie_ctx_arr,
+ const size_t totvideos, bool preview);
+
/* only RE_NewRender() needed, main Blender render calls */
void RE_BlenderFrame(struct Render *re, struct Main *bmain, struct Scene *scene,
struct SceneRenderLayer *srl, struct Object *camera_override,
@@ -238,6 +289,9 @@ void RE_RenderFreestyleStrokes(struct Render *re, struct Main *bmain, struct Sce
void RE_RenderFreestyleExternal(struct Render *re);
#endif
+void RE_SetActiveRenderView(struct Render *re, const char *viewname);
+const char *RE_GetActiveRenderView(struct Render *re);
+
/* error reporting */
void RE_SetReports(struct Render *re, struct ReportList *reports);
@@ -245,7 +299,7 @@ void RE_SetReports(struct Render *re, struct ReportList *reports);
void RE_PreviewRender(struct Render *re, struct Main *bmain, struct Scene *scene);
bool RE_ReadRenderResult(struct Scene *scene, struct Scene *scenode);
-bool RE_WriteRenderResult(struct ReportList *reports, RenderResult *rr, const char *filename, int compress);
+bool RE_WriteRenderResult(struct ReportList *reports, RenderResult *rr, const char *filename, struct ImageFormatData *imf, const bool multiview, const char *view);
struct RenderResult *RE_MultilayerConvert(void *exrhandle, const char *colorspace, bool predivide, int rectx, int recty);
extern const float default_envmap_layout[];
@@ -271,6 +325,10 @@ void RE_zbuf_accumulate_vecblur(struct NodeBlurData *nbd, int xsize, int ysize,
int RE_seq_render_active(struct Scene *scene, struct RenderData *rd);
+bool RE_layers_have_name(struct RenderResult *result);
+
+struct RenderPass *RE_pass_find_by_type(volatile struct RenderLayer *rl, int passtype, const char *viewname);
+
/* shaded view or baking options */
#define RE_BAKE_LIGHT 0 /* not listed in rna_scene.c -> can't be enabled! */
#define RE_BAKE_ALL 1
@@ -292,6 +350,7 @@ void RE_Database_Baking(struct Render *re, struct Main *bmain, struct Scene *sce
void RE_DataBase_GetView(struct Render *re, float mat[4][4]);
void RE_GetCameraWindow(struct Render *re, struct Object *camera, int frame, float mat[4][4]);
+void RE_GetCameraModelMatrix(struct Render *re, struct Object *camera, float r_mat[4][4]);
struct Scene *RE_GetScene(struct Render *re);
bool RE_force_single_renderlayer(struct Scene *scene);
@@ -299,5 +358,20 @@ bool RE_is_rendering_allowed(struct Scene *scene, struct Object *camera_override
bool RE_allow_render_generic_object(struct Object *ob);
+/******* defined in render_result.c *********/
+
+bool RE_HasFakeLayer(RenderResult *res);
+bool RE_RenderResult_is_stereo(RenderResult *res);
+struct RenderView *RE_RenderViewGetById(struct RenderResult *res, const int view_id);
+struct RenderView *RE_RenderViewGetByName(struct RenderResult *res, const char *viewname);
+
+/******* Debug pass helper functions *********/
+
+#ifdef WITH_CYCLES_DEBUG
+int RE_debug_pass_num_channels_get(int pass_type);
+const char *RE_debug_pass_name_get(int pass_type);
+int RE_debug_pass_type_get(struct Render *re);
+#endif
+
#endif /* __RE_PIPELINE_H__ */
diff --git a/source/blender/render/extern/include/RE_render_ext.h b/source/blender/render/extern/include/RE_render_ext.h
index eb861d440d8..6e1f128b7a5 100644
--- a/source/blender/render/extern/include/RE_render_ext.h
+++ b/source/blender/render/extern/include/RE_render_ext.h
@@ -39,13 +39,11 @@
/* called by meshtools */
struct DerivedMesh;
struct ImagePool;
-struct LinkNode;
struct MTex;
struct Scene;
-struct View3D;
/* particle.c, effect.c, editmesh_modes.c and brush.c, returns 1 if rgb, 0 otherwise */
-int externtex(struct MTex *mtex, const float vec[3], float *tin, float *tr, float *tg, float *tb, float *ta, const int thread, struct ImagePool *pool);
+int externtex(struct MTex *mtex, const float vec[3], float *tin, float *tr, float *tg, float *tb, float *ta, const int thread, struct ImagePool *pool, const bool skip_load_image);
/* particle.c */
void texture_rgb_blend(float in[3], const float tex[3], const float out[3], float fact, float facg, int blendtype);
@@ -58,8 +56,16 @@ void antialias_tagbuf(int xsize, int ysize, char *rectmove);
/* dynamicpaint.c */
struct Material *RE_init_sample_material(struct Material *orig_mat, struct Scene *scene);
void RE_free_sample_material(struct Material *mat);
-void RE_sample_material_color(struct Material *mat, float color[3], float *alpha, const float volume_co[3], const float surface_co[3],
- int face_index, short hit_quad, struct DerivedMesh *orcoDm, struct Object *ob);
+void RE_sample_material_color(
+ struct Material *mat, float color[3], float *alpha, const float volume_co[3], const float surface_co[3],
+ int tri_index, struct DerivedMesh *orcoDm, struct Object *ob);
+/* pointdensity.c */
+struct PointDensity;
+
+void RE_sample_point_density(struct Scene *scene, struct PointDensity *pd, int resolution, float *values);
+
+void RE_init_texture_rng(void);
+void RE_exit_texture_rng(void);
#endif /* __RE_RENDER_EXT_H__ */
diff --git a/source/blender/render/extern/include/RE_shader_ext.h b/source/blender/render/extern/include/RE_shader_ext.h
index da847d235f2..f78c0aa8cb2 100644
--- a/source/blender/render/extern/include/RE_shader_ext.h
+++ b/source/blender/render/extern/include/RE_shader_ext.h
@@ -86,12 +86,12 @@ struct ShadeInputCopy {
typedef struct ShadeInputUV {
float dxuv[3], dyuv[3], uv[3];
- char *name;
+ const char *name;
} ShadeInputUV;
typedef struct ShadeInputCol {
float col[4];
- char *name;
+ const char *name;
} ShadeInputCol;
/* localized renderloop data */
@@ -178,7 +178,7 @@ typedef struct ShadeInput {
int layflag, passflag, combinedflag;
struct Group *light_override;
struct Material *mat_override;
-
+
#ifdef RE_RAYCOUNTER
RayCounter raycounter;
#endif
@@ -198,14 +198,15 @@ 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);
+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, const bool skip_load_image);
/* nodes disabled */
-int multitex_ext_safe(struct Tex *tex, float texvec[3], struct TexResult *texres, struct ImagePool *pool, bool scene_color_manage);
+int multitex_ext_safe(struct Tex *tex, float texvec[3], struct TexResult *texres, struct ImagePool *pool, bool scene_color_manage, const bool skip_load_image);
/* only for internal node usage */
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]);
+void RE_instance_get_particle_info(struct ObjectInstanceRen *obi, float *index, float *age, float *lifetime, float co[3], float *size, float vel[3], float angvel[3]);
/* shaded view and bake */
struct Render;
diff --git a/source/blender/render/intern/include/envmap.h b/source/blender/render/intern/include/envmap.h
index c813e88c656..627e6c0e1e6 100644
--- a/source/blender/render/intern/include/envmap.h
+++ b/source/blender/render/intern/include/envmap.h
@@ -47,7 +47,7 @@ struct TexResult;
struct ImagePool;
void make_envmaps(struct Render *re);
-int envmaptex(struct Tex *tex, const float texvec[3], float dxt[3], float dyt[3], int osatex, struct TexResult *texres, struct ImagePool *pool);
+int envmaptex(struct Tex *tex, const float texvec[3], float dxt[3], float dyt[3], int osatex, struct TexResult *texres, struct ImagePool *pool, const bool skip_image_load);
void env_rotate_scene(struct Render *re, float mat[4][4], int do_rotate);
#endif /* __ENVMAP_H__ */
diff --git a/source/blender/render/intern/include/initrender.h b/source/blender/render/intern/include/initrender.h
index 1f11cdc6729..87e2d2519d5 100644
--- a/source/blender/render/intern/include/initrender.h
+++ b/source/blender/render/intern/include/initrender.h
@@ -33,7 +33,6 @@
#ifndef __INITRENDER_H__
#define __INITRENDER_H__
-struct Object;
/* Functions */
diff --git a/source/blender/render/intern/include/occlusion.h b/source/blender/render/intern/include/occlusion.h
index 2f3ac2a7bff..4a70d691436 100644
--- a/source/blender/render/intern/include/occlusion.h
+++ b/source/blender/render/intern/include/occlusion.h
@@ -35,11 +35,8 @@
struct Render;
struct ShadeInput;
-struct ShadeResult;
struct RenderPart;
struct ShadeSample;
-struct DerivedMesh;
-struct ObjectRen;
void make_occ_tree(struct Render *re);
void free_occ(struct Render *re);
diff --git a/source/blender/render/intern/include/pixelshading.h b/source/blender/render/intern/include/pixelshading.h
index faf8c5f54f5..8f23455564f 100644
--- a/source/blender/render/intern/include/pixelshading.h
+++ b/source/blender/render/intern/include/pixelshading.h
@@ -32,7 +32,6 @@
#ifndef __PIXELSHADING_H__
#define __PIXELSHADING_H__
-struct ImagePool;
/**
* Render the pixel at (x,y) for object ap. Apply the jitter mask.
diff --git a/source/blender/render/intern/include/pointdensity.h b/source/blender/render/intern/include/pointdensity.h
index e0c293e2473..1d1e808e8d3 100644
--- a/source/blender/render/intern/include/pointdensity.h
+++ b/source/blender/render/intern/include/pointdensity.h
@@ -37,10 +37,12 @@
* Make point density kd-trees for all point density textures in the scene
*/
+struct PointDensity;
struct Render;
struct TexResult;
-void cache_pointdensity(struct Render *re, struct Tex *tex);
+void free_pointdensity(struct PointDensity *pd);
+void cache_pointdensity(struct Render *re, struct PointDensity *pd);
void make_pointdensities(struct Render *re);
void free_pointdensities(struct Render *re);
int pointdensitytex(struct Tex *tex, const float texvec[3], struct TexResult *texres);
diff --git a/source/blender/render/intern/include/rayintersection.h b/source/blender/render/intern/include/rayintersection.h
index 9c0835af56f..3607e66a237 100644
--- a/source/blender/render/intern/include/rayintersection.h
+++ b/source/blender/render/intern/include/rayintersection.h
@@ -121,7 +121,7 @@ typedef struct Isect {
/* arbitrary, but can't use e.g. FLT_MAX because of precision issues */
#define RE_RAYTRACE_MAXDIST 1e15f
-#define RE_RAYTRACE_EPSILON -FLT_EPSILON
+#define RE_RAYTRACE_EPSILON 0.0f
#ifdef __cplusplus
}
diff --git a/source/blender/render/intern/include/render_result.h b/source/blender/render/intern/include/render_result.h
index 90ff69dbfbe..90ad0fa30d7 100644
--- a/source/blender/render/intern/include/render_result.h
+++ b/source/blender/render/intern/include/render_result.h
@@ -38,6 +38,7 @@
#define RR_USE_EXR 1
#define RR_ALL_LAYERS NULL
+#define RR_ALL_VIEWS NULL
struct ImBuf;
struct ListBase;
@@ -53,12 +54,15 @@ struct ColorManagedViewSettings;
/* New */
struct RenderResult *render_result_new(struct Render *re,
- struct rcti *partrct, int crop, int savebuffers, const char *layername);
+ struct rcti *partrct, int crop, int savebuffers, const char *layername, const char *viewname);
struct RenderResult *render_result_new_full_sample(struct Render *re,
- struct ListBase *lb, struct rcti *partrct, int crop, int savebuffers);
+ struct ListBase *lb, struct rcti *partrct, int crop, int savebuffers, const char *viewname);
struct RenderResult *render_result_new_from_exr(void *exrhandle, const char *colorspace, bool predivide, int rectx, int recty);
+void render_result_view_new(struct RenderResult *rr, const char *viewname);
+void render_result_views_new(struct RenderResult *rr, struct RenderData *rd);
+
/* Merge */
void render_result_merge(struct RenderResult *rr, struct RenderResult *rrpart);
@@ -75,10 +79,11 @@ void render_result_single_layer_end(struct Render *re);
/* EXR Tile File Render */
+void render_result_save_empty_result_tiles(struct Render *re);
void render_result_exr_file_begin(struct Render *re);
void render_result_exr_file_end(struct Render *re);
-void render_result_exr_file_merge(struct RenderResult *rr, struct RenderResult *rrpart);
+void render_result_exr_file_merge(struct RenderResult *rr, struct RenderResult *rrpart, const char *viewname);
void render_result_exr_file_path(struct Scene *scene, const char *layname, int sample, char *filepath);
int render_result_exr_file_read_sample(struct Render *re, int sample);
@@ -91,15 +96,19 @@ bool render_result_exr_file_cache_read(struct Render *re);
/* Combined Pixel Rect */
-struct ImBuf *render_result_rect_to_ibuf(struct RenderResult *rr, struct RenderData *rd);
+struct ImBuf *render_result_rect_to_ibuf(struct RenderResult *rr, struct RenderData *rd, const int view_id);
void render_result_rect_from_ibuf(struct RenderResult *rr, struct RenderData *rd,
- struct ImBuf *ibuf);
+ struct ImBuf *ibuf, const int view_id);
-void render_result_rect_fill_zero(struct RenderResult *rr);
+void render_result_rect_fill_zero(struct RenderResult *rr, const int view_id);
void render_result_rect_get_pixels(struct RenderResult *rr,
unsigned int *rect, int rectx, int recty,
const struct ColorManagedViewSettings *view_settings,
- const struct ColorManagedDisplaySettings *display_settings);
+ const struct ColorManagedDisplaySettings *display_settings,
+ const int view_id);
+
+void render_result_views_shallowcopy(struct RenderResult *dst, struct RenderResult *src);
+void render_result_views_shallowdelete(struct RenderResult *rr);
#endif /* __RENDER_RESULT_H__ */
diff --git a/source/blender/render/intern/include/render_types.h b/source/blender/render/intern/include/render_types.h
index b87b1e6f367..3569cb2c168 100644
--- a/source/blender/render/intern/include/render_types.h
+++ b/source/blender/render/intern/include/render_types.h
@@ -58,7 +58,6 @@ struct MemArena;
struct VertTableNode;
struct VlakTableNode;
struct GHash;
-struct RenderBuckets;
struct ObjectInstanceRen;
struct RayObject;
struct RayFace;
@@ -123,8 +122,7 @@ enum {
};
/* controls state of render, everything that's read-only during render stage */
-struct Render
-{
+struct Render {
struct Render *next, *prev;
char name[RE_MAXNAME];
int slot;
@@ -194,6 +192,7 @@ struct Render
struct Object *camera_override;
unsigned int lay, layer_override;
+ ThreadRWMutex partsmutex;
ListBase parts;
/* render engine */
@@ -275,6 +274,9 @@ struct Render
struct ImagePool *pool;
struct EvaluationContext *eval_ctx;
+
+ void **movie_ctx_arr;
+ char viewname[MAX_NAME];
};
/* ------------------------------------------------------------------------- */
@@ -365,6 +367,14 @@ typedef struct ObjectInstanceRen {
struct RayObject *raytree;
int transform_primitives;
+ /* Particle info */
+ float part_index;
+ float part_age;
+ float part_lifetime;
+ float part_size;
+ float part_co[3];
+ float part_vel[3];
+ float part_avel[3];
} ObjectInstanceRen;
/* ------------------------------------------------------------------------- */
@@ -388,7 +398,6 @@ struct halosort {
/* ------------------------------------------------------------------------- */
struct Material;
-struct MTFace;
struct ImagePool;
typedef struct RadFace {
@@ -424,6 +433,7 @@ typedef struct HaloRen {
unsigned int lay;
struct Material *mat;
struct ImagePool *pool;
+ bool skip_load_image;
} HaloRen;
/* ------------------------------------------------------------------------- */
diff --git a/source/blender/render/intern/include/rendercore.h b/source/blender/render/intern/include/rendercore.h
index 88b639c4ba9..308903c6c6d 100644
--- a/source/blender/render/intern/include/rendercore.h
+++ b/source/blender/render/intern/include/rendercore.h
@@ -34,14 +34,11 @@
#include "render_types.h"
-struct HaloRen;
struct ShadeInput;
struct ShadeResult;
struct World;
struct RenderPart;
struct RenderLayer;
-struct ObjectRen;
-struct ListBase;
struct RayObject;
/* ------------------------------------------------------------------------- */
diff --git a/source/blender/render/intern/include/shadbuf.h b/source/blender/render/intern/include/shadbuf.h
index 7c168baada7..ddf5de8d974 100644
--- a/source/blender/render/intern/include/shadbuf.h
+++ b/source/blender/render/intern/include/shadbuf.h
@@ -34,7 +34,6 @@
#include "render_types.h"
-struct ObjectRen;
/**
* Calculates shadowbuffers for a vector of shadow-giving lamps
@@ -57,8 +56,7 @@ void threaded_makeshadowbufs(struct Render *re);
float testshadowbuf(struct Render *re, struct ShadBuf *shb, const float rco[3], const float dxco[3], const float dyco[3], float inp, float mat_bias);
/**
- * Determines the shadow factor for lamp <lar>, between <p1>
- * and <p2>. (Which CS?)
+ * Determines the shadow factor for lamp \a lar, between \a p1 and \a p2. (Which CS?)
*/
float shadow_halo(LampRen *lar, const float p1[3], const float p2[3]);
diff --git a/source/blender/render/intern/include/shading.h b/source/blender/render/intern/include/shading.h
index 4f6e005d742..11dcc9d9e80 100644
--- a/source/blender/render/intern/include/shading.h
+++ b/source/blender/render/intern/include/shading.h
@@ -33,7 +33,6 @@ struct RenderLayer;
struct PixStr;
struct LampRen;
struct VlakRen;
-struct StrandSegment;
struct StrandPoint;
struct ObjectInstanceRen;
struct Isect;
diff --git a/source/blender/render/intern/include/sss.h b/source/blender/render/intern/include/sss.h
index 91a8b91e638..0952c6bff65 100644
--- a/source/blender/render/intern/include/sss.h
+++ b/source/blender/render/intern/include/sss.h
@@ -55,7 +55,6 @@ void scatter_tree_free(ScatterTree *tree);
struct Render;
struct Material;
-struct VlakRen;
void make_sss_tree(struct Render *re);
void sss_add_points(Render *re, float (*co)[3], float (*color)[3], float *area, int totpoint);
diff --git a/source/blender/render/intern/include/strand.h b/source/blender/render/intern/include/strand.h
index fdcce687f54..5687ef3c837 100644
--- a/source/blender/render/intern/include/strand.h
+++ b/source/blender/render/intern/include/strand.h
@@ -34,9 +34,6 @@ struct StrandBuffer;
struct ShadeSample;
struct StrandPart;
struct Render;
-struct RenderPart;
-struct RenderBuckets;
-struct RenderPrimitiveIterator;
struct ZSpan;
struct ObjectInstanceRen;
struct StrandSurface;
diff --git a/source/blender/render/intern/include/texture.h b/source/blender/render/intern/include/texture.h
index ff5004fd7f0..ed161e186b8 100644
--- a/source/blender/render/intern/include/texture.h
+++ b/source/blender/render/intern/include/texture.h
@@ -56,6 +56,11 @@
_hsv[1] *= tex->saturation; \
hsv_to_rgb(_hsv[0], _hsv[1], _hsv[2], \
&texres->tr, &texres->tg, &texres->tb); \
+ if ((tex->saturation > 1.0f) && !(tex->flag & TEX_NO_CLAMP)) { \
+ if (texres->tr < 0.0f) texres->tr= 0.0f; \
+ if (texres->tg < 0.0f) texres->tg= 0.0f; \
+ if (texres->tb < 0.0f) texres->tb= 0.0f; \
+ } \
} \
struct HaloRen;
@@ -81,8 +86,8 @@ void render_realtime_texture(struct ShadeInput *shi, struct Image *ima);
/* imagetexture.h */
-int imagewraposa(struct Tex *tex, struct Image *ima, struct ImBuf *ibuf, const float texvec[3], const float dxt[2], const float dyt[2], struct TexResult *texres, struct ImagePool *pool);
-int imagewrap(struct Tex *tex, struct Image *ima, struct ImBuf *ibuf, const float texvec[3], struct TexResult *texres, struct ImagePool *pool);
+int imagewraposa(struct Tex *tex, struct Image *ima, struct ImBuf *ibuf, const float texvec[3], const float dxt[2], const float dyt[2], struct TexResult *texres, struct ImagePool *pool, const bool skip_load_image);
+int imagewrap(struct Tex *tex, struct Image *ima, struct ImBuf *ibuf, const float texvec[3], struct TexResult *texres, struct ImagePool *pool, const bool skip_load_image);
void image_sample(struct Image *ima, float fx, float fy, float dx, float dy, float result[4], struct ImagePool *pool);
#endif /* __TEXTURE_H__ */
diff --git a/source/blender/render/intern/include/zbuf.h b/source/blender/render/intern/include/zbuf.h
index ec30c3241ab..cf804d75d70 100644
--- a/source/blender/render/intern/include/zbuf.h
+++ b/source/blender/render/intern/include/zbuf.h
@@ -36,7 +36,6 @@
struct RenderPart;
struct RenderLayer;
struct LampRen;
-struct VlakRen;
struct ListBase;
struct ZSpan;
struct APixstrand;
diff --git a/source/blender/render/intern/raytrace/rayobject_instance.cpp b/source/blender/render/intern/raytrace/rayobject_instance.cpp
index 01e592cba0c..d080ddcc375 100644
--- a/source/blender/render/intern/raytrace/rayobject_instance.cpp
+++ b/source/blender/render/intern/raytrace/rayobject_instance.cpp
@@ -197,7 +197,7 @@ static void RE_rayobject_instance_bb(RayObject *o, float *min, float *max)
//There must be a faster way than rotating all the 8 vertexs of the BB
for (i = 0; i < 8; i++) {
- for (j = 0; j < 3; j++) t[j] = i & (1 << j) ? M[j] : m[j];
+ for (j = 0; j < 3; j++) t[j] = (i & (1 << j)) ? M[j] : m[j];
mul_m4_v3(obj->target2global, t);
DO_MINMAX(t, min, max);
}
diff --git a/source/blender/render/intern/raytrace/rayobject_octree.cpp b/source/blender/render/intern/raytrace/rayobject_octree.cpp
index 6cbb0761358..b21197e728d 100644
--- a/source/blender/render/intern/raytrace/rayobject_octree.cpp
+++ b/source/blender/render/intern/raytrace/rayobject_octree.cpp
@@ -119,7 +119,8 @@ static RayObjectAPI octree_api =
/* within one octree node, a set of 3x15 bits defines a 'boundbox' to OR with */
#define OCVALRES 15
-#define BROW16(min, max) (((max) >= OCVALRES ? 0xFFFF : (1 << (max + 1)) - 1) - ((min > 0) ? ((1 << (min)) - 1) : 0))
+#define BROW16(min, max) \
+ (((max) >= OCVALRES ? 0xFFFF : (1 << ((max) + 1)) - 1) - (((min) > 0) ? ((1 << (min)) - 1) : 0))
static void calc_ocval_face(float *v1, float *v2, float *v3, float *v4, short x, short y, short z, OcVal *ov)
{
diff --git a/source/blender/render/intern/source/bake.c b/source/blender/render/intern/source/bake.c
index 15634c93491..0210bec5ab4 100644
--- a/source/blender/render/intern/source/bake.c
+++ b/source/blender/render/intern/source/bake.c
@@ -34,6 +34,7 @@
#include "MEM_guardedalloc.h"
#include "BLI_math.h"
+#include "BLI_rand.h"
#include "BLI_threads.h"
#include "BLI_utildefines.h"
@@ -54,8 +55,6 @@
#include "IMB_imbuf.h"
#include "IMB_colormanagement.h"
-#include "RE_bake.h"
-
/* local include */
#include "rayintersection.h"
#include "rayobject.h"
@@ -77,6 +76,8 @@ extern struct Render R;
typedef struct BakeShade {
+ int thread;
+
ShadeSample ssamp;
ObjectInstanceRen *obi;
VlakRen *vlr;
@@ -374,8 +375,8 @@ static void bake_displacement(void *handle, ShadeInput *UNUSED(shi), float dist,
bs->vcol->b = col[2];
}
else {
- const char *imcol = (char *)(bs->rect + bs->rectx * y + x);
- copy_v4_v4_char((char *)imcol, (char *)col);
+ char *imcol = (char *)(bs->rect + bs->rectx * y + x);
+ copy_v4_v4_char(imcol, (char *)col);
}
}
if (bs->rect_mask) {
@@ -613,6 +614,10 @@ static int get_next_bake_face(BakeShade *bs)
for (; obi; obi = obi->next, v = 0) {
obr = obi->obr;
+ /* only allow non instances here */
+ if (obr->flag & R_INSTANCEABLE)
+ continue;
+
for (; v < obr->totvlak; v++) {
vlr = RE_findOrAddVlak(obr, v);
@@ -735,6 +740,9 @@ static void bake_single_vertex(BakeShade *bs, VertRen *vert, float u, float v)
MLoopCol *basevcol;
MLoop *mloop;
+ /* per vertex fixed seed */
+ BLI_thread_srandom(bs->thread, vert->index);
+
origindex = RE_vertren_get_origindex(bs->obi->obr, vert, 0);
if (!origindex || *origindex == ORIGINDEX_NONE)
return;
@@ -809,6 +817,9 @@ static void shade_tface(BakeShade *bs)
Image *ima = tface->tpage;
float vec[4][2];
int a, i1, i2, i3;
+
+ /* per face fixed seed */
+ BLI_thread_srandom(bs->thread, vlr->index);
/* check valid zspan */
if (ima != bs->ima) {
@@ -982,8 +993,12 @@ int RE_bake_shade_all_selected(Render *re, int type, Object *actob, short *do_up
int a, vdone = false, result = BAKE_RESULT_OK;
bool use_mask = false;
bool use_displacement_buffer = false;
- bool do_manage = BKE_scene_check_color_management_enabled(re->scene);
-
+ bool do_manage = false;
+
+ if (ELEM(type, RE_BAKE_ALL, RE_BAKE_TEXTURE)) {
+ do_manage = BKE_scene_check_color_management_enabled(re->scene);
+ }
+
re->scene_color_manage = BKE_scene_check_color_management_enabled(re->scene);
/* initialize render global */
@@ -1031,6 +1046,8 @@ int RE_bake_shade_all_selected(Render *re, int type, Object *actob, short *do_up
/* get the threads running */
for (a = 0; a < re->r.threads; a++) {
+ handles[a].thread = a;
+
/* set defaults in handles */
handles[a].ssamp.shi[0].lay = re->lay;
diff --git a/source/blender/render/intern/source/bake_api.c b/source/blender/render/intern/source/bake_api.c
index 90deac2de32..dee75d43f36 100644
--- a/source/blender/render/intern/source/bake_api.c
+++ b/source/blender/render/intern/source/bake_api.c
@@ -30,10 +30,11 @@
*
* The Bake API is fully implemented with Python rna functions. The operator expects/call a function:
*
- * ``def bake(scene, object, pass_type, pixel_array, num_pixels, depth, result)``
+ * ``def bake(scene, object, pass_type, object_id, pixel_array, num_pixels, depth, result)``
* - scene: current scene (Python object)
* - object: object to render (Python object)
* - pass_type: pass to render (string, e.g., "COMBINED", "AO", "NORMAL", ...)
+ * - object_id: index of object to bake (to use with the pixel_array)
* - pixel_array: list of primitive ids and barycentric coordinates to bake(Python object, see bake_pixel)
* - num_pixels: size of pixel_array, number of pixels to bake (int)
* - depth: depth of pixels to return (int, assuming always 4 now)
@@ -45,17 +46,17 @@
*
* pixel_array is a Python object storing BakePixel elements:
*
- * <pre>
+ * \code{.c}
* struct BakePixel {
- * int primitive_id;
+ * int primitive_id, object_id;
* float uv[2];
* float du_dx, du_dy;
* float dv_dx, dv_dy;
* };
- * </pre>
+ * \endcode
*
* In python you have access to:
- * - ``primitive_id``, ``uv``, ``du_dx``, ``du_dy``, ``next``
+ * - ``primitive_id``, ``object_id``, ``uv``, ``du_dx``, ``du_dy``, ``next``
* - ``next()`` is a function that returns the next #BakePixel in the array.
*
* \note Pixels that should not be baked have ``primitive_id == -1``
@@ -63,6 +64,8 @@
* For a complete implementation example look at the Cycles Bake commit.
*/
+#include <limits.h>
+
#include "MEM_guardedalloc.h"
#include "BLI_math.h"
@@ -72,6 +75,7 @@
#include "BKE_cdderivedmesh.h"
#include "BKE_image.h"
#include "BKE_node.h"
+#include "BKE_mesh.h"
#include "IMB_imbuf_types.h"
#include "IMB_imbuf.h"
@@ -126,12 +130,16 @@ static void store_bake_pixel(void *handle, int x, int y, float u, float v)
pixel = &bd->pixel_array[i];
pixel->primitive_id = bd->primitive_id;
+ /* At this point object_id is always 0, since this function runs for the
+ * lowpoly mesh only. The object_id lookup indices are set afterwards. */
+
copy_v2_fl2(pixel->uv, u, v);
pixel->du_dx = bd->du_dx;
pixel->du_dy = bd->du_dy;
pixel->dv_dx = bd->dv_dx;
pixel->dv_dy = bd->dv_dy;
+ pixel->object_id = 0;
}
void RE_bake_mask_fill(const BakePixel pixel_array[], const size_t num_pixels, char *mask)
@@ -271,7 +279,7 @@ static void calc_barycentric_from_point(
* This function populates pixel_array and returns TRUE if things are correct
*/
static bool cast_ray_highpoly(
- BVHTreeFromMesh *treeData, TriTessFace *triangles[], BakeHighPolyData *highpoly,
+ BVHTreeFromMesh *treeData, TriTessFace *triangles[], BakePixel *pixel_array, BakeHighPolyData *highpoly,
const float co[3], const float dir[3], const int pixel_id, const int tot_highpoly,
const float du_dx, const float du_dy, const float dv_dx, const float dv_dy)
{
@@ -295,7 +303,7 @@ static bool cast_ray_highpoly(
mul_v3_m4v3(co_high, highpoly[i].imat, co);
/* rotates */
- mul_v3_m4v3(dir_high, highpoly[i].rotmat, dir);
+ mul_v3_mat3_m4v3(dir_high, highpoly[i].imat, dir);
normalize_v3(dir_high);
/* cast ray */
@@ -322,22 +330,22 @@ static bool cast_ray_highpoly(
}
}
- for (i = 0; i < tot_highpoly; i++) {
- if (hit_mesh == i) {
- calc_barycentric_from_point(triangles[i], hits[i].index, hits[i].co, &primitive_id, uv);
- highpoly[i].pixel_array[pixel_id].primitive_id = primitive_id;
- copy_v2_v2(highpoly[i].pixel_array[pixel_id].uv, uv);
-
- /* the differentials are relative to the UV/image space, so the highpoly differentials
- * are the same as the low poly differentials */
- highpoly[i].pixel_array[pixel_id].du_dx = du_dx;
- highpoly[i].pixel_array[pixel_id].du_dy = du_dy;
- highpoly[i].pixel_array[pixel_id].dv_dx = dv_dx;
- highpoly[i].pixel_array[pixel_id].dv_dy = dv_dy;
- }
- else {
- highpoly[i].pixel_array[pixel_id].primitive_id = -1;
- }
+ if (hit_mesh != -1) {
+ calc_barycentric_from_point(triangles[hit_mesh], hits[hit_mesh].index, hits[hit_mesh].co, &primitive_id, uv);
+ pixel_array[pixel_id].primitive_id = primitive_id;
+ pixel_array[pixel_id].object_id = hit_mesh;
+ copy_v2_v2(pixel_array[pixel_id].uv, uv);
+
+ /* the differentials are relative to the UV/image space, so the highpoly differentials
+ * are the same as the low poly differentials */
+ pixel_array[pixel_id].du_dx = du_dx;
+ pixel_array[pixel_id].du_dy = du_dy;
+ pixel_array[pixel_id].dv_dx = dv_dx;
+ pixel_array[pixel_id].dv_dy = dv_dy;
+ }
+ else {
+ pixel_array[pixel_id].primitive_id = -1;
+ pixel_array[pixel_id].object_id = -1;
}
MEM_freeN(hits);
@@ -352,99 +360,76 @@ static void mesh_calc_tri_tessface(
TriTessFace *triangles, Mesh *me, bool tangent, DerivedMesh *dm)
{
int i;
- int p_id;
- MFace *mface;
MVert *mvert;
TSpace *tspace;
float *precomputed_normals = NULL;
bool calculate_normal;
+ const int tottri = poly_to_tri_count(me->totpoly, me->totloop);
+ MLoopTri *looptri;
+ /* calculate normal for each polygon only once */
+ unsigned int mpoly_prev = UINT_MAX;
+ float no[3];
- mface = CustomData_get_layer(&me->fdata, CD_MFACE);
mvert = CustomData_get_layer(&me->vdata, CD_MVERT);
+ looptri = MEM_mallocN(sizeof(*looptri) * tottri, __func__);
if (tangent) {
DM_ensure_normals(dm);
- DM_add_tangent_layer(dm);
+ DM_calc_loop_tangents(dm);
- precomputed_normals = dm->getTessFaceDataArray(dm, CD_NORMAL);
+ precomputed_normals = dm->getPolyDataArray(dm, CD_NORMAL);
calculate_normal = precomputed_normals ? false : true;
- //mface = dm->getTessFaceArray(dm);
- //mvert = dm->getVertArray(dm);
-
- tspace = dm->getTessFaceDataArray(dm, CD_TANGENT);
+ tspace = dm->getLoopDataArray(dm, CD_TANGENT);
BLI_assert(tspace);
}
- p_id = -1;
- for (i = 0; i < me->totface; i++) {
- MFace *mf = &mface[i];
- TSpace *ts = tangent ? &tspace[i * 4] : NULL;
+ BKE_mesh_recalc_looptri(
+ me->mloop, me->mpoly,
+ me->mvert,
+ me->totloop, me->totpoly,
+ looptri);
- p_id++;
+ for (i = 0; i < tottri; i++) {
+ MLoopTri *lt = &looptri[i];
+ MPoly *mp = &me->mpoly[lt->poly];
- triangles[p_id].mverts[0] = &mvert[mf->v1];
- triangles[p_id].mverts[1] = &mvert[mf->v2];
- triangles[p_id].mverts[2] = &mvert[mf->v3];
- triangles[p_id].is_smooth = (mf->flag & ME_SMOOTH) != 0;
+ triangles[i].mverts[0] = &mvert[me->mloop[lt->tri[0]].v];
+ triangles[i].mverts[1] = &mvert[me->mloop[lt->tri[1]].v];
+ triangles[i].mverts[2] = &mvert[me->mloop[lt->tri[2]].v];
+ triangles[i].is_smooth = (mp->flag & ME_SMOOTH) != 0;
if (tangent) {
- triangles[p_id].tspace[0] = &ts[0];
- triangles[p_id].tspace[1] = &ts[1];
- triangles[p_id].tspace[2] = &ts[2];
+ triangles[i].tspace[0] = &tspace[lt->tri[0]];
+ triangles[i].tspace[1] = &tspace[lt->tri[1]];
+ triangles[i].tspace[2] = &tspace[lt->tri[2]];
if (calculate_normal) {
- if (mf->v4 != 0) {
- normal_quad_v3(triangles[p_id].normal,
- mvert[mf->v1].co,
- mvert[mf->v2].co,
- mvert[mf->v3].co,
- mvert[mf->v4].co);
- }
- else {
- normal_tri_v3(triangles[p_id].normal,
- triangles[p_id].mverts[0]->co,
- triangles[p_id].mverts[1]->co,
- triangles[p_id].mverts[2]->co);
+ if (lt->poly != mpoly_prev) {
+ const MPoly *mp = &me->mpoly[lt->poly];
+ BKE_mesh_calc_poly_normal(mp, &me->mloop[mp->loopstart], me->mvert, no);
+ mpoly_prev = lt->poly;
}
+ copy_v3_v3(triangles[i].normal, no);
}
else {
- copy_v3_v3(triangles[p_id].normal, &precomputed_normals[3 * i]);
- }
- }
-
- /* 4 vertices in the face */
- if (mf->v4 != 0) {
- p_id++;
-
- triangles[p_id].mverts[0] = &mvert[mf->v1];
- triangles[p_id].mverts[1] = &mvert[mf->v3];
- triangles[p_id].mverts[2] = &mvert[mf->v4];
- triangles[p_id].is_smooth = (mf->flag & ME_SMOOTH) != 0;
-
- if (tangent) {
- triangles[p_id].tspace[0] = &ts[0];
- triangles[p_id].tspace[1] = &ts[2];
- triangles[p_id].tspace[2] = &ts[3];
-
- /* same normal as the other "triangle" */
- copy_v3_v3(triangles[p_id].normal, triangles[p_id - 1].normal);
+ copy_v3_v3(triangles[i].normal, &precomputed_normals[lt->poly]);
}
}
}
- BLI_assert(p_id < me->totface * 2);
+ MEM_freeN(looptri);
}
bool RE_bake_pixels_populate_from_objects(
- struct Mesh *me_low, BakePixel pixel_array_from[],
+ struct Mesh *me_low, BakePixel pixel_array_from[], BakePixel pixel_array_to[],
BakeHighPolyData highpoly[], const int tot_highpoly, const size_t num_pixels, const bool is_custom_cage,
const float cage_extrusion, float mat_low[4][4], float mat_cage[4][4], struct Mesh *me_cage)
{
size_t i;
int primitive_id;
float u, v;
- float imat_low [4][4];
+ float imat_low[4][4];
bool is_cage = me_cage != NULL;
bool result = true;
@@ -488,6 +473,7 @@ bool RE_bake_pixels_populate_from_objects(
mesh_calc_tri_tessface(tris_high[i], highpoly[i].me, false, NULL);
dm_highpoly[i] = CDDM_from_mesh(highpoly[i].me);
+ DM_ensure_tessface(dm_highpoly[i]);
if (dm_highpoly[i]->getNumTessFaces(dm_highpoly[i]) != 0) {
/* Create a bvh-tree for each highpoly object */
@@ -508,10 +494,7 @@ bool RE_bake_pixels_populate_from_objects(
primitive_id = pixel_array_from[i].primitive_id;
if (primitive_id == -1) {
- int j;
- for (j = 0; j < tot_highpoly; j++) {
- highpoly[j].pixel_array[i].primitive_id = -1;
- }
+ pixel_array_to[i].primitive_id = -1;
continue;
}
@@ -530,7 +513,7 @@ bool RE_bake_pixels_populate_from_objects(
}
/* cast ray */
- if (!cast_ray_highpoly(treeData, tris_high, highpoly, co, dir, i, tot_highpoly,
+ if (!cast_ray_highpoly(treeData, tris_high, pixel_array_to, highpoly, co, dir, i, tot_highpoly,
pixel_array_from[i].du_dx, pixel_array_from[i].du_dy,
pixel_array_from[i].dv_dx, pixel_array_from[i].dv_dy)) {
/* if it fails mask out the original pixel array */
@@ -928,7 +911,6 @@ bool RE_bake_internal(
case SCE_PASS_UV:
{
return bake_uv(pixel_array, num_pixels, depth, result);
- break;
}
default:
break;
diff --git a/source/blender/render/intern/source/convertblender.c b/source/blender/render/intern/source/convertblender.c
index 69dd9607c3b..ee28c3b286f 100644
--- a/source/blender/render/intern/source/convertblender.c
+++ b/source/blender/render/intern/source/convertblender.c
@@ -44,7 +44,7 @@
# include "BLI_edgehash.h"
#endif
-#include "BLF_translation.h"
+#include "BLT_translation.h"
#include "DNA_material_types.h"
#include "DNA_curve_types.h"
@@ -82,9 +82,7 @@
#include "BKE_particle.h"
#include "BKE_scene.h"
-
#include "PIL_time.h"
-#include "IMB_imbuf_types.h"
#include "envmap.h"
#include "occlusion.h"
@@ -103,8 +101,6 @@
#include "zbuf.h"
#include "sunsky.h"
-#include "RE_render_ext.h"
-
/* 10 times larger than normal epsilon, test it on default nurbs sphere with ray_transp (for quad detection) */
/* or for checking vertex normal flips */
#define FLT_EPSILON10 1.19209290e-06F
@@ -134,6 +130,9 @@
/* ------------------------------------------------------------------------- */
+#define CD_MASK_RENDER_INTERNAL \
+ (CD_MASK_BAREMESH | CD_MASK_MFACE | CD_MASK_MTFACE | CD_MASK_MCOL)
+
static void split_v_renderfaces(ObjectRen *obr, int startvlak, int UNUSED(startvert), int UNUSED(usize), int vsize, int uIndex, int UNUSED(cyclu), int cyclv)
{
int vLen = vsize-1+(!!cyclv);
@@ -382,7 +381,7 @@ static void calc_vertexnormals(Render *UNUSED(re), ObjectRen *obr, bool do_verte
{
int a;
- /* clear all vertex normals */
+ /* clear all vertex normals */
if (do_vertex_normal) {
for (a=0; a<obr->totvert; a++) {
VertRen *ver= RE_findOrAddVert(obr, a);
@@ -390,8 +389,8 @@ static void calc_vertexnormals(Render *UNUSED(re), ObjectRen *obr, bool do_verte
}
}
- /* calculate cos of angles and point-masses, use as weight factor to
- * add face normal to vertex */
+ /* calculate cos of angles and point-masses, use as weight factor to
+ * add face normal to vertex */
for (a=0; a<obr->totvlak; a++) {
VlakRen *vlr= RE_findOrAddVlak(obr, a);
if (do_vertex_normal && vlr->flag & ME_SMOOTH) {
@@ -408,7 +407,7 @@ static void calc_vertexnormals(Render *UNUSED(re), ObjectRen *obr, bool do_verte
}
}
- /* do solid faces */
+ /* do solid faces */
for (a=0; a<obr->totvlak; a++) {
VlakRen *vlr= RE_findOrAddVlak(obr, a);
@@ -581,6 +580,17 @@ static void autosmooth(Render *UNUSED(re), ObjectRen *obr, float mat[4][4], shor
VlakRen *vlr;
int a, totvert;
+ float rot[3][3];
+
+ /* Note: For normals, we only want rotation, not scaling component.
+ * Negative scales (aka mirroring) give wrong results, see T44102. */
+ if (lnors) {
+ float mat3[3][3], size[3];
+
+ copy_m3_m4(mat3, mat);
+ mat3_to_rot_size(rot, size, mat3);
+ }
+
if (obr->totvert == 0)
return;
@@ -615,9 +625,8 @@ static void autosmooth(Render *UNUSED(re), ObjectRen *obr, float mat[4][4], shor
ver = RE_findOrAddVert(obr, a);
mul_m4_v3(mat, ver->co);
if (lnors) {
- mul_mat3_m4_v3(mat, ver->n);
+ mul_m3_v3(rot, ver->n);
negate_v3(ver->n);
- normalize_v3(ver->n);
}
}
for (a = 0; a < obr->totvlak; a++) {
@@ -1203,8 +1212,7 @@ static void particle_normal_ren(short ren_as, ParticleSettings *part, Render *re
sd->time = 0.0f;
sd->size = hasize;
- copy_v3_v3(vel, state->vel);
- mul_mat3_m4_v3(re->viewmat, vel);
+ mul_v3_mat3_m4v3(vel, re->viewmat, state->vel);
normalize_v3(vel);
if (part->draw & PART_DRAW_VEL_LENGTH)
@@ -1245,7 +1253,7 @@ static void get_particle_uvco_mcol(short from, DerivedMesh *dm, float *fuv, int
/* get uvco */
if (sd->uvco && ELEM(from, PART_FROM_FACE, PART_FROM_VOLUME)) {
for (i=0; i<sd->totuv; i++) {
- if (num != DMCACHE_NOTFOUND) {
+ if (!ELEM(num, DMCACHE_NOTFOUND, DMCACHE_ISCHILD)) {
MFace *mface = dm->getTessFaceData(dm, num, CD_MFACE);
MTFace *mtface = (MTFace*)CustomData_get_layer_n(&dm->faceData, CD_MTFACE, i);
mtface += num;
@@ -1262,7 +1270,7 @@ static void get_particle_uvco_mcol(short from, DerivedMesh *dm, float *fuv, int
/* get mcol */
if (sd->mcol && ELEM(from, PART_FROM_FACE, PART_FROM_VOLUME)) {
for (i=0; i<sd->totcol; i++) {
- if (num != DMCACHE_NOTFOUND) {
+ if (!ELEM(num, DMCACHE_NOTFOUND, DMCACHE_ISCHILD)) {
MFace *mface = dm->getTessFaceData(dm, num, CD_MFACE);
MCol *mc = (MCol*)CustomData_get_layer_n(&dm->faceData, CD_MCOL, i);
mc += num * 4;
@@ -1305,7 +1313,6 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem
int totchild=0, step_nbr;
int seed, path_nbr=0, orco1=0, num;
int totface;
- const char **uv_name = NULL;
const int *index_mf_to_mpoly = NULL;
const int *index_mp_to_orig = NULL;
@@ -1326,6 +1333,9 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem
if ((re->r.scemode & R_VIEWPORT_PREVIEW) && (ob->mode & OB_MODE_PARTICLE_EDIT))
return 0;
+ if (part->ren_as == PART_DRAW_BB && part->bb_ob == NULL && RE_GetCamera(re) == NULL)
+ return 0;
+
/* 2. start initializing things */
/* last possibility to bail out! */
@@ -1349,11 +1359,13 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem
if (re->r.scemode & R_VIEWPORT_PREVIEW) { /* preview render */
totchild = (int)((float)totchild * (float)part->disp / 100.0f);
- step_nbr = part->draw_step;
+ step_nbr = 1 << part->draw_step;
}
else {
- step_nbr = part->ren_step;
+ step_nbr = 1 << part->ren_step;
}
+ if (ELEM(part->kink, PART_KINK_SPIRAL))
+ step_nbr += part->kink_extra_steps;
psys->flag |= PSYS_DRAWING;
@@ -1427,8 +1439,7 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem
/* 2.5 setup matrices */
mul_m4_m4m4(mat, re->viewmat, ob->obmat);
invert_m4_m4(ob->imat, mat); /* need to be that way, for imat texture */
- copy_m3_m4(nmat, ob->imat);
- transpose_m3(nmat);
+ transpose_m3_m4(nmat, ob->imat);
if (psys->flag & PSYS_USE_IMAT) {
/* psys->imat is the original emitter's inverse matrix, ob->obmat is the duplicated object's matrix */
@@ -1438,7 +1449,7 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem
/* 2.6 setup strand rendering */
if (part->ren_as == PART_DRAW_PATH && psys->pathcache) {
- path_nbr=(int)pow(2.0, (double) step_nbr);
+ path_nbr = step_nbr;
if (path_nbr) {
if (!ELEM(ma->material_type, MA_TYPE_HALO, MA_TYPE_WIRE)) {
@@ -1557,7 +1568,7 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem
if (path_nbr) {
cache = psys->pathcache[a];
- max_k = (int)cache->steps;
+ max_k = (int)cache->segments;
}
if (totchild && (part->draw&PART_DRAW_PARENT)==0) continue;
@@ -1568,10 +1579,10 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem
if (path_nbr) {
cache = psys->childcache[a-totpart];
- if (cache->steps < 0)
+ if (cache->segments < 0)
continue;
- max_k = (int)cache->steps;
+ max_k = (int)cache->segments;
}
pa_time = psys_get_child_time(psys, cpa, cfra, &pa_birthtime, &pa_dietime);
@@ -1855,9 +1866,6 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem
if (sd.mcol)
MEM_freeN(sd.mcol);
- if (uv_name)
- MEM_freeN(uv_name);
-
if (states)
MEM_freeN(states);
@@ -2652,8 +2660,7 @@ static void init_render_curve(Render *re, ObjectRen *obr, int timeoffset)
negative_scale = is_negative_m4(mat);
/* local object -> world space transform for normals */
- copy_m4_m4(nmat, mat);
- transpose_m4(nmat);
+ transpose_m4_m4(nmat, mat);
invert_m4(nmat);
/* material array */
@@ -2731,12 +2738,13 @@ static void init_render_curve(Render *re, ObjectRen *obr, int timeoffset)
vlr->v4= NULL;
/* to prevent float accuracy issues, we calculate normal in local object space (not world) */
- if (area_tri_v3(co3, co2, co1)>FLT_EPSILON) {
- if (negative_scale)
- normal_tri_v3(tmp, co1, co2, co3);
- else
- normal_tri_v3(tmp, co3, co2, co1);
- add_v3_v3(n, tmp);
+ if (normal_tri_v3(tmp, co1, co2, co3) > FLT_EPSILON) {
+ if (negative_scale == false) {
+ add_v3_v3(n, tmp);
+ }
+ else {
+ sub_v3_v3(n, tmp);
+ }
}
vlr->mat= matar[ dl->col ];
@@ -3170,7 +3178,7 @@ static void init_render_mesh(Render *re, ObjectRen *obr, int timeoffset)
/* origindex currently used when using autosmooth, or baking to vertex colors. */
need_origindex = (do_autosmooth || ((re->flag & R_BAKING) && (re->r.bake_flag & R_BAKE_VCOL)));
- mask= CD_MASK_BAREMESH|CD_MASK_MTFACE|CD_MASK_MCOL;
+ mask = CD_MASK_RENDER_INTERNAL;
if (!timeoffset)
if (need_orco)
mask |= CD_MASK_ORCO;
@@ -3264,8 +3272,14 @@ static void init_render_mesh(Render *re, ObjectRen *obr, int timeoffset)
RE_set_customdata_names(obr, &dm->faceData);
/* add tangent layer if we need one */
- if (need_nmap_tangent!=0 && CustomData_get_layer_index(&dm->faceData, CD_TANGENT) == -1)
- DM_add_tangent_layer(dm);
+ if (need_nmap_tangent!=0 && CustomData_get_layer_index(&dm->faceData, CD_TANGENT) == -1) {
+ bool generate_data = false;
+ if (CustomData_get_layer_index(&dm->loopData, CD_TANGENT) == -1) {
+ dm->calcLoopTangents(dm);
+ generate_data = true;
+ }
+ DM_generate_tangent_tessface_data(dm, generate_data);
+ }
/* still to do for keys: the correct local texture coordinate */
@@ -3274,12 +3288,13 @@ static void init_render_mesh(Render *re, ObjectRen *obr, int timeoffset)
for (a1=0; (a1<ob->totcol || (a1==0 && ob->totcol==0)); a1++) {
ma= give_render_material(re, ob, a1+1);
-
+
/* test for 100% transparent */
ok = 1;
if ((ma->alpha == 0.0f) &&
(ma->spectra == 0.0f) &&
- (ma->filter == 0.0f) &&
+ /* No need to test filter here, it's only active with MA_RAYTRANSP and we check against it below. */
+ /* (ma->filter == 0.0f) && */
(ma->mode & MA_TRANSP) &&
(ma->mode & (MA_RAYTRANSP | MA_RAYMIRROR)) == 0)
{
@@ -3323,7 +3338,7 @@ static void init_render_mesh(Render *re, ObjectRen *obr, int timeoffset)
v2= mface->v2;
v3= reverse_verts==0 ? mface->v3 : mface->v1;
v4= mface->v4;
- flag= mface->flag & ME_SMOOTH;
+ flag = do_autosmooth ? ME_SMOOTH : mface->flag & ME_SMOOTH;
vlr= RE_findOrAddVlak(obr, obr->totvlak++);
vlr->v1= RE_findOrAddVert(obr, vertofs+v1);
@@ -3807,7 +3822,9 @@ static GroupObject *add_render_lamp(Render *re, Object *ob)
}
/* set flag for spothalo en initvars */
- if (la->type==LA_SPOT && (la->mode & LA_HALO) && (la->buftype != LA_SHADBUF_DEEP)) {
+ if ((la->type == LA_SPOT) && (la->mode & LA_HALO) &&
+ (!(la->mode & LA_SHAD_BUF) || la->buftype != LA_SHADBUF_DEEP))
+ {
if (la->haint>0.0f) {
re->flag |= R_LAMPHALO;
@@ -3826,7 +3843,7 @@ static GroupObject *add_render_lamp(Render *re, Object *ob)
lar->sh_invcampos[2]*= lar->sh_zfac;
/* halfway shadow buffer doesn't work for volumetric effects */
- if (lar->buftype == LA_SHADBUF_HALFWAY)
+ if (ELEM(lar->buftype, LA_SHADBUF_HALFWAY, LA_SHADBUF_DEEP))
lar->buftype = LA_SHADBUF_REGULAR;
}
@@ -3917,7 +3934,15 @@ static bool is_object_hidden(Render *re, Object *ob)
if (re->r.scemode & R_VIEWPORT_PREVIEW) {
/* Mesh deform cages and so on mess up the preview. To avoid the problem,
* viewport doesn't show mesh object if its draw type is bounding box or wireframe.
+ * Unless it's an active smoke domain!
*/
+ ModifierData *md = NULL;
+
+ if ((md = modifiers_findByType(ob, eModifierType_Smoke)) &&
+ (modifier_isEnabled(re->scene, md, eModifierMode_Realtime)))
+ {
+ return false;
+ }
return ELEM(ob->dt, OB_BOUNDBOX, OB_WIRE);
}
else {
@@ -4565,10 +4590,12 @@ static void init_render_object_data(Render *re, ObjectRen *obr, int timeoffset)
/* the emitter mesh wasn't rendered so the modifier stack wasn't
* evaluated with render settings */
DerivedMesh *dm;
+ const CustomDataMask mask = CD_MASK_RENDER_INTERNAL;
+
if (re->r.scemode & R_VIEWPORT_PREVIEW)
- dm = mesh_create_derived_view(re->scene, ob, CD_MASK_BAREMESH|CD_MASK_MTFACE|CD_MASK_MCOL);
+ dm = mesh_create_derived_view(re->scene, ob, mask);
else
- dm = mesh_create_derived_render(re->scene, ob, CD_MASK_BAREMESH|CD_MASK_MTFACE|CD_MASK_MCOL);
+ dm = mesh_create_derived_render(re->scene, ob, mask);
dm->release(dm);
}
@@ -4868,7 +4895,7 @@ static void dupli_render_particle_set(Render *re, Object *ob, int timeoffset, in
/* this is to make sure we get render level duplis in groups:
* the derivedmesh must be created before init_render_mesh,
* since object_duplilist does dupliparticles before that */
- dm = mesh_create_derived_render(re->scene, ob, CD_MASK_BAREMESH|CD_MASK_MTFACE|CD_MASK_MCOL);
+ dm = mesh_create_derived_render(re->scene, ob, CD_MASK_RENDER_INTERNAL);
dm->release(dm);
for (psys=ob->particlesystem.first; psys; psys=psys->next)
@@ -4988,8 +5015,10 @@ static void database_init_objects(Render *re, unsigned int renderlay, int nolamp
* system need to have render settings set for dupli particles */
dupli_render_particle_set(re, ob, timeoffset, 0, 1);
duplilist = object_duplilist(re->eval_ctx, re->scene, ob);
- duplilist_apply_data = duplilist_apply(ob, duplilist);
- dupli_render_particle_set(re, ob, timeoffset, 0, 0);
+ duplilist_apply_data = duplilist_apply(ob, NULL, duplilist);
+ /* postpone 'dupli_render_particle_set', since RE_addRenderInstance reads
+ * index values from 'dob->persistent_id[0]', referencing 'psys->child' which
+ * may be smaller once the particle system is restored, see: T45563. */
for (dob= duplilist->first, i = 0; dob; dob= dob->next, ++i) {
DupliExtraData *dob_extra = &duplilist_apply_data->extra[i];
@@ -5082,6 +5111,9 @@ static void database_init_objects(Render *re, unsigned int renderlay, int nolamp
if (re->test_break(re->tbh)) break;
}
+ /* restore particle system */
+ dupli_render_particle_set(re, ob, timeoffset, 0, false);
+
if (duplilist_apply_data) {
duplilist_restore(duplilist, duplilist_apply_data);
duplilist_free_apply_data(duplilist_apply_data);
@@ -5136,8 +5168,7 @@ void RE_Database_FromScene(Render *re, Main *bmain, Scene *scene, unsigned int l
re->totvlak=re->totvert=re->totstrand=re->totlamp=re->tothalo= 0;
re->lights.first= re->lights.last= NULL;
re->lampren.first= re->lampren.last= NULL;
-
- slurph_opt= 0;
+
re->i.partsdone = false; /* signal now in use for previewrender */
/* in localview, lamps are using normal layers, objects only local bits */
@@ -5156,8 +5187,7 @@ void RE_Database_FromScene(Render *re, Main *bmain, Scene *scene, unsigned int l
* above call to BKE_scene_update_for_newframe, fixes bug. [#22702].
* following calls don't depend on 'RE_SetCamera' */
RE_SetCamera(re, camera);
-
- normalize_m4_m4(mat, camera->obmat);
+ RE_GetCameraModelMatrix(re, camera, mat);
invert_m4(mat);
RE_SetView(re, mat);
@@ -5180,7 +5210,7 @@ void RE_Database_FromScene(Render *re, Main *bmain, Scene *scene, unsigned int l
/* still bad... doing all */
init_render_textures(re);
copy_v3_v3(amb, &re->wrld.ambr);
- init_render_materials(re->main, re->r.mode, amb);
+ init_render_materials(re->main, re->r.mode, amb, (re->r.scemode & R_BUTS_PREVIEW) == 0);
set_node_shader_lamp_loop(shade_material_loop);
/* MAKE RENDER DATA */
@@ -5199,8 +5229,6 @@ void RE_Database_FromScene(Render *re, Main *bmain, Scene *scene, unsigned int l
re->i.totlamp= re->totlamp;
re->stats_draw(re->sdh, &re->i);
}
-
- slurph_opt= 1;
}
void RE_Database_Preprocess(Render *re)
@@ -5240,7 +5268,7 @@ void RE_Database_Preprocess(Render *re)
}
if (!re->test_break(re->tbh))
- project_renderdata(re, projectverto, re->r.mode & R_PANORAMA, 0, 1);
+ project_renderdata(re, projectverto, (re->r.mode & R_PANORAMA) != 0, 0, 1);
/* Occlusion */
if ((re->wrld.mode & (WO_AMB_OCC|WO_ENV_LIGHT|WO_INDIRECT_LIGHT)) && !re->test_break(re->tbh))
@@ -5318,8 +5346,6 @@ static void database_fromscene_vectors(Render *re, Scene *scene, unsigned int la
re->totvlak=re->totvert=re->totstrand=re->totlamp=re->tothalo= 0;
re->i.totface=re->i.totvert=re->i.totstrand=re->i.totlamp=re->i.tothalo= 0;
re->lights.first= re->lights.last= NULL;
-
- slurph_opt= 0;
/* in localview, lamps are using normal layers, objects only local bits */
if (re->lay & 0xFF000000)
@@ -5331,7 +5357,8 @@ static void database_fromscene_vectors(Render *re, Scene *scene, unsigned int la
/* if no camera, viewmat should have been set! */
if (camera) {
- normalize_m4_m4(mat, camera->obmat);
+ RE_GetCameraModelMatrix(re, camera, mat);
+ normalize_m4(mat);
invert_m4(mat);
RE_SetView(re, mat);
}
@@ -5340,7 +5367,7 @@ static void database_fromscene_vectors(Render *re, Scene *scene, unsigned int la
database_init_objects(re, lay, 0, 0, NULL, timeoffset);
if (!re->test_break(re->tbh))
- project_renderdata(re, projectverto, re->r.mode & R_PANORAMA, 0, 1);
+ project_renderdata(re, projectverto, (re->r.mode & R_PANORAMA) != 0, 0, 1);
/* do this in end, particles for example need cfra */
scene->r.cfra -= timeoffset;
@@ -5842,9 +5869,11 @@ void RE_Database_Baking(Render *re, Main *bmain, Scene *scene, unsigned int lay,
/* renderdata setup and exceptions */
BLI_freelistN(&re->r.layers);
+ BLI_freelistN(&re->r.views);
re->r = scene->r;
BLI_duplicatelist(&re->r.layers, &scene->r.layers);
-
+ BLI_duplicatelist(&re->r.views, &scene->r.views);
+
RE_init_threadcount(re);
re->flag |= R_BAKING;
@@ -5912,7 +5941,7 @@ void RE_Database_Baking(Render *re, Main *bmain, Scene *scene, unsigned int lay,
init_render_textures(re);
copy_v3_v3(amb, &re->wrld.ambr);
- init_render_materials(re->main, re->r.mode, amb);
+ init_render_materials(re->main, re->r.mode, amb, true);
set_node_shader_lamp_loop(shade_material_loop);
diff --git a/source/blender/render/intern/source/envmap.c b/source/blender/render/intern/source/envmap.c
index 06be00a5a5e..b9b908f550b 100644
--- a/source/blender/render/intern/source/envmap.c
+++ b/source/blender/render/intern/source/envmap.c
@@ -37,7 +37,7 @@
#include "BLI_threads.h"
#include "BLI_utildefines.h"
-#include "BLF_translation.h"
+#include "BLT_translation.h"
#include "IMB_imbuf_types.h"
#include "IMB_imbuf.h" /* for rectcpy */
@@ -55,14 +55,10 @@
/* this module */
#include "render_types.h"
-#include "renderpipeline.h"
#include "envmap.h"
-#include "rendercore.h"
#include "renderdatabase.h"
#include "texture.h"
#include "zbuf.h"
-#include "initrender.h"
-
/* ------------------------------------------------------------------------- */
@@ -74,7 +70,7 @@ static void envmap_split_ima(EnvMap *env, ImBuf *ibuf)
BLI_lock_thread(LOCK_IMAGE);
if (env->cube[1] == NULL) {
- BKE_free_envmapdata(env);
+ BKE_texture_envmap_free_data(env);
dx = ibuf->y;
dx /= 2;
@@ -145,6 +141,7 @@ static Render *envmap_render_copy(Render *re, EnvMap *env)
envre->r = re->r;
envre->r.mode &= ~(R_BORDER | R_PANORAMA | R_ORTHO | R_MBLUR);
BLI_listbase_clear(&envre->r.layers);
+ BLI_listbase_clear(&envre->r.views);
envre->r.filtertype = 0;
envre->r.tilex = envre->r.xsch / 2;
envre->r.tiley = envre->r.ysch / 2;
@@ -499,9 +496,12 @@ static void render_envmap(Render *re, EnvMap *env)
RenderLayer *rl = envre->result->layers.first;
int y;
float *alpha;
-
+ float *rect;
+
+ /* envmap is rendered independently of multiview */
+ rect = RE_RenderLayerGetPass(rl, SCE_PASS_COMBINED, "");
ibuf = IMB_allocImBuf(envre->rectx, envre->recty, 24, IB_rect | IB_rectfloat);
- memcpy(ibuf->rect_float, rl->rectf, ibuf->channels * ibuf->x * ibuf->y * sizeof(float));
+ memcpy(ibuf->rect_float, rect, ibuf->channels * ibuf->x * ibuf->y * sizeof(float));
/* envmap renders without alpha */
alpha = ibuf->rect_float + 3;
@@ -515,7 +515,7 @@ static void render_envmap(Render *re, EnvMap *env)
}
- if (re->test_break(re->tbh)) BKE_free_envmapdata(env);
+ if (re->test_break(re->tbh)) BKE_texture_envmap_free_data(env);
else {
if (envre->r.mode & R_OSA) env->ok = ENV_OSA;
else env->ok = ENV_NORMAL;
@@ -576,13 +576,13 @@ void make_envmaps(Render *re)
if (env->ok) {
/* free when OSA, and old one isn't OSA */
if ((re->r.mode & R_OSA) && env->ok == ENV_NORMAL)
- BKE_free_envmapdata(env);
+ BKE_texture_envmap_free_data(env);
/* free when size larger */
else if (env->lastsize < re->r.size)
- BKE_free_envmapdata(env);
+ BKE_texture_envmap_free_data(env);
/* free when env is in recalcmode */
else if (env->recalc)
- BKE_free_envmapdata(env);
+ BKE_texture_envmap_free_data(env);
}
if (env->ok == 0 && depth == 0) env->recalc = 1;
@@ -698,7 +698,7 @@ static void set_dxtdyt(float r_dxt[3], float r_dyt[3], const float dxt[3], const
/* ------------------------------------------------------------------------- */
-int envmaptex(Tex *tex, const float texvec[3], float dxt[3], float dyt[3], int osatex, TexResult *texres, struct ImagePool *pool)
+int envmaptex(Tex *tex, const float texvec[3], float dxt[3], float dyt[3], int osatex, TexResult *texres, struct ImagePool *pool, const bool skip_load_image)
{
extern Render R; /* only in this call */
/* texvec should be the already reflected normal */
@@ -754,7 +754,7 @@ int envmaptex(Tex *tex, const float texvec[3], float dxt[3], float dyt[3], int o
mul_mat3_m4_v3(R.viewinv, dyt);
}
set_dxtdyt(dxts, dyts, dxt, dyt, face);
- imagewraposa(tex, NULL, ibuf, sco, dxts, dyts, texres, pool);
+ imagewraposa(tex, NULL, ibuf, sco, dxts, dyts, texres, pool, skip_load_image);
/* edges? */
@@ -771,7 +771,7 @@ int envmaptex(Tex *tex, const float texvec[3], float dxt[3], float dyt[3], int o
if (face != face1) {
ibuf = env->cube[face1];
set_dxtdyt(dxts, dyts, dxt, dyt, face1);
- imagewraposa(tex, NULL, ibuf, sco, dxts, dyts, &texr1, pool);
+ imagewraposa(tex, NULL, ibuf, sco, dxts, dyts, &texr1, pool, skip_load_image);
}
else texr1.tr = texr1.tg = texr1.tb = texr1.ta = 0.0;
@@ -784,7 +784,7 @@ int envmaptex(Tex *tex, const float texvec[3], float dxt[3], float dyt[3], int o
if (face != face1) {
ibuf = env->cube[face1];
set_dxtdyt(dxts, dyts, dxt, dyt, face1);
- imagewraposa(tex, NULL, ibuf, sco, dxts, dyts, &texr2, pool);
+ imagewraposa(tex, NULL, ibuf, sco, dxts, dyts, &texr2, pool, skip_load_image);
}
else texr2.tr = texr2.tg = texr2.tb = texr2.ta = 0.0;
@@ -800,7 +800,7 @@ int envmaptex(Tex *tex, const float texvec[3], float dxt[3], float dyt[3], int o
}
}
else {
- imagewrap(tex, NULL, ibuf, sco, texres, pool);
+ imagewrap(tex, NULL, ibuf, sco, texres, pool, skip_load_image);
}
return 1;
diff --git a/source/blender/render/intern/source/external_engine.c b/source/blender/render/intern/source/external_engine.c
index 54f142184e1..fef453efce2 100644
--- a/source/blender/render/intern/source/external_engine.c
+++ b/source/blender/render/intern/source/external_engine.c
@@ -36,19 +36,17 @@
#include "MEM_guardedalloc.h"
-#include "BLF_translation.h"
+#include "BLT_translation.h"
#include "BLI_listbase.h"
#include "BLI_string.h"
#include "BLI_utildefines.h"
+#include "BKE_camera.h"
#include "BKE_global.h"
#include "BKE_report.h"
#include "BKE_scene.h"
-#include "IMB_imbuf.h"
-#include "IMB_imbuf_types.h"
-
#include "RNA_access.h"
#ifdef WITH_PYTHON
@@ -184,7 +182,7 @@ static RenderPart *get_part_from_result(Render *re, RenderResult *result)
return NULL;
}
-RenderResult *RE_engine_begin_result(RenderEngine *engine, int x, int y, int w, int h, const char *layername)
+RenderResult *RE_engine_begin_result(RenderEngine *engine, int x, int y, int w, int h, const char *layername, const char *viewname)
{
Render *re = engine->re;
RenderResult *result;
@@ -207,7 +205,7 @@ RenderResult *RE_engine_begin_result(RenderEngine *engine, int x, int y, int w,
disprect.ymin = y;
disprect.ymax = y + h;
- result = render_result_new(re, &disprect, 0, RR_USE_MEM, layername);
+ result = render_result_new(re, &disprect, 0, RR_USE_MEM, layername, viewname);
/* todo: make this thread safe */
@@ -272,7 +270,7 @@ void RE_engine_end_result(RenderEngine *engine, RenderResult *result, int cancel
if (!cancel || merge_results) {
if (re->result->do_exr_tile) {
if (!cancel) {
- render_result_exr_file_merge(re->result, result);
+ render_result_exr_file_merge(re->result, result, re->viewname);
}
}
else if (!(re->test_break(re->tbh) && (re->r.scemode & R_BUTS_PREVIEW)))
@@ -358,28 +356,69 @@ void RE_engine_report(RenderEngine *engine, int type, const char *msg)
BKE_report(engine->reports, type, msg);
}
-void RE_engine_get_current_tiles(Render *re, int *total_tiles_r, rcti **tiles_r)
+void RE_engine_set_error_message(RenderEngine *engine, const char *msg)
+{
+ Render *re = engine->re;
+ if (re != NULL) {
+ RenderResult *rr = RE_AcquireResultRead(re);
+ if (rr->error != NULL) {
+ MEM_freeN(rr->error);
+ }
+ rr->error = BLI_strdup(msg);
+ RE_ReleaseResult(re);
+ }
+}
+
+void RE_engine_active_view_set(RenderEngine *engine, const char *viewname)
{
+ Render *re = engine->re;
+ RE_SetActiveRenderView(re, viewname);
+}
+
+float RE_engine_get_camera_shift_x(RenderEngine *engine, Object *camera)
+{
+ Render *re = engine->re;
+ return BKE_camera_multiview_shift_x(re ? &re->r : NULL, camera, re->viewname);
+}
+
+void RE_engine_get_camera_model_matrix(RenderEngine *engine, Object *camera, float *r_modelmat)
+{
+ Render *re = engine->re;
+ BKE_camera_multiview_model_matrix(re ? &re->r : NULL, camera, re->viewname, (float (*)[4])r_modelmat);
+}
+
+rcti* RE_engine_get_current_tiles(Render *re, int *r_total_tiles, bool *r_needs_free)
+{
+ static rcti tiles_static[BLENDER_MAX_THREADS];
+ const int allocation_step = BLENDER_MAX_THREADS;
RenderPart *pa;
int total_tiles = 0;
- rcti *tiles = NULL;
- int allocation_size = 0, allocation_step = BLENDER_MAX_THREADS;
+ rcti *tiles = tiles_static;
+ int allocation_size = BLENDER_MAX_THREADS;
+
+ BLI_rw_mutex_lock(&re->partsmutex, THREAD_LOCK_READ);
+
+ *r_needs_free = false;
if (re->engine && (re->engine->flag & RE_ENGINE_HIGHLIGHT_TILES) == 0) {
- *total_tiles_r = 0;
- *tiles_r = NULL;
- return;
+ *r_total_tiles = 0;
+ BLI_rw_mutex_unlock(&re->partsmutex);
+ return NULL;
}
for (pa = re->parts.first; pa; pa = pa->next) {
if (pa->status == PART_STATUS_IN_PROGRESS) {
if (total_tiles >= allocation_size) {
- if (tiles == NULL)
+ /* Just in case we're using crazy network rendering with more
+ * slaves as BLENDER_MAX_THREADS.
+ */
+ if (tiles == tiles_static)
tiles = MEM_mallocN(allocation_step * sizeof(rcti), "current engine tiles");
else
tiles = MEM_reallocN(tiles, (total_tiles + allocation_step) * sizeof(rcti));
allocation_size += allocation_step;
+ *r_needs_free = true;
}
tiles[total_tiles] = pa->disprect;
@@ -394,9 +433,9 @@ void RE_engine_get_current_tiles(Render *re, int *total_tiles_r, rcti **tiles_r)
total_tiles++;
}
}
-
- *total_tiles_r = total_tiles;
- *tiles_r = tiles;
+ BLI_rw_mutex_unlock(&re->partsmutex);
+ *r_total_tiles = total_tiles;
+ return tiles;
}
RenderData *RE_engine_get_render_data(Render *re)
@@ -415,6 +454,7 @@ void RE_bake_engine_set_engine_parameters(Render *re, Main *bmain, Scene *scene)
* but it potentially leaves unfreed memory blocks
* not sure how to fix this yet -- dfelinto */
BLI_listbase_clear(&re->r.layers);
+ BLI_listbase_clear(&re->r.views);
}
bool RE_bake_has_engine(Render *re)
@@ -424,13 +464,14 @@ bool RE_bake_has_engine(Render *re)
}
bool RE_bake_engine(
- Render *re, Object *object, const BakePixel pixel_array[],
+ Render *re, Object *object,
+ const int object_id, const BakePixel pixel_array[],
const size_t num_pixels, const int depth,
const ScenePassType pass_type, float result[])
{
RenderEngineType *type = RE_engines_find(re->r.engine);
RenderEngine *engine;
- int persistent_data = re->r.mode & R_PERSISTENT_DATA;
+ bool persistent_data = (re->r.mode & R_PERSISTENT_DATA) != 0;
/* set render info */
re->i.cfra = re->scene->r.cfra;
@@ -462,12 +503,14 @@ bool RE_bake_engine(
type->update(engine, re->main, re->scene);
if (type->bake)
- type->bake(engine, re->scene, object, pass_type, pixel_array, num_pixels, depth, result);
+ type->bake(engine, re->scene, object, pass_type, object_id, pixel_array, num_pixels, depth, result);
engine->tile_x = 0;
engine->tile_y = 0;
engine->flag &= ~RE_ENGINE_RENDERING;
+ BLI_rw_mutex_lock(&re->partsmutex, THREAD_LOCK_WRITE);
+
/* re->engine becomes zero if user changed active render engine during render */
if (!persistent_data || !re->engine) {
RE_engine_free(engine);
@@ -475,6 +518,7 @@ bool RE_bake_engine(
}
RE_parts_free(re);
+ BLI_rw_mutex_unlock(&re->partsmutex);
if (BKE_reports_contain(re->reports, RPT_ERROR))
G.is_break = true;
@@ -522,7 +566,7 @@ int RE_engine_render(Render *re, int do_all)
{
RenderEngineType *type = RE_engines_find(re->r.engine);
RenderEngine *engine;
- int persistent_data = re->r.mode & R_PERSISTENT_DATA;
+ bool persistent_data = (re->r.mode & R_PERSISTENT_DATA) != 0;
/* verify if we can render */
if (!type->render)
@@ -589,7 +633,7 @@ int RE_engine_render(Render *re, int do_all)
if ((type->flag & RE_USE_SAVE_BUFFERS) && (re->r.scemode & R_EXR_TILE_FILE))
savebuffers = RR_USE_EXR;
- re->result = render_result_new(re, &re->disprect, 0, savebuffers, RR_ALL_LAYERS);
+ re->result = render_result_new(re, &re->disprect, 0, savebuffers, RR_ALL_LAYERS, RR_ALL_VIEWS);
}
BLI_rw_mutex_unlock(&re->resultmutex);
@@ -653,6 +697,8 @@ int RE_engine_render(Render *re, int do_all)
render_result_free_list(&engine->fullresult, engine->fullresult.first);
+ BLI_rw_mutex_lock(&re->partsmutex, THREAD_LOCK_WRITE);
+
/* re->engine becomes zero if user changed active render engine during render */
if (!persistent_data || !re->engine) {
RE_engine_free(engine);
@@ -661,6 +707,7 @@ int RE_engine_render(Render *re, int do_all)
if (re->result->do_exr_tile) {
BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE);
+ render_result_save_empty_result_tiles(re);
render_result_exr_file_end(re);
BLI_rw_mutex_unlock(&re->resultmutex);
}
@@ -672,6 +719,7 @@ int RE_engine_render(Render *re, int do_all)
}
RE_parts_free(re);
+ BLI_rw_mutex_unlock(&re->partsmutex);
if (BKE_reports_contain(re->reports, RPT_ERROR))
G.is_break = true;
diff --git a/source/blender/render/intern/source/imagetexture.c b/source/blender/render/intern/source/imagetexture.c
index 12701099e18..b44c0135420 100644
--- a/source/blender/render/intern/source/imagetexture.c
+++ b/source/blender/render/intern/source/imagetexture.c
@@ -50,12 +50,10 @@
#include "BLI_threads.h"
#include "BLI_utildefines.h"
-#include "BKE_main.h"
#include "BKE_image.h"
#include "RE_render_ext.h"
-#include "renderpipeline.h"
#include "render_types.h"
#include "texture.h"
@@ -105,7 +103,7 @@ static void ibuf_get_color(float col[4], struct ImBuf *ibuf, int x, int y)
}
}
-int imagewrap(Tex *tex, Image *ima, ImBuf *ibuf, const float texvec[3], TexResult *texres, struct ImagePool *pool)
+int imagewrap(Tex *tex, Image *ima, ImBuf *ibuf, const float texvec[3], TexResult *texres, struct ImagePool *pool, const bool skip_load_image)
{
float fx, fy, val1, val2, val3;
int x, y, retval;
@@ -122,7 +120,7 @@ int imagewrap(Tex *tex, Image *ima, ImBuf *ibuf, const float texvec[3], TexResul
if (ima) {
/* hack for icon render */
- if ((R.r.scemode & R_NO_IMAGE_LOAD) && !BKE_image_has_loaded_ibuf(ima))
+ if (skip_load_image && !BKE_image_has_loaded_ibuf(ima))
return retval;
ibuf = BKE_image_pool_acquire_ibuf(ima, &tex->iuser, pool);
@@ -791,14 +789,6 @@ static void area_sample(TexResult *texr, ImBuf *ibuf, float fx, float fy, afdata
texr->ta = texr->talpha ? texr->ta*xsd : (clip ? cw*xsd : 1.f);
}
-/* test if a float value is 'nan'
- * there is a C99 function for this: isnan(), but blender seems to use C90 (according to gcc warns),
- * and may not be supported by other compilers either */
-/* TODO(sergey): Consider using isnan(), it's used in the other areas. */
-#ifndef ISNAN
-# define ISNAN(x) ((x) != (x))
-#endif
-
typedef struct ReadEWAData {
ImBuf *ibuf;
afdata_t *AFD;
@@ -922,7 +912,7 @@ static void image_mipmap_test(Tex *tex, ImBuf *ibuf)
}
-static int imagewraposa_aniso(Tex *tex, Image *ima, ImBuf *ibuf, const float texvec[3], float dxt[2], float dyt[2], TexResult *texres, struct ImagePool *pool)
+static int imagewraposa_aniso(Tex *tex, Image *ima, ImBuf *ibuf, const float texvec[3], float dxt[2], float dyt[2], TexResult *texres, struct ImagePool *pool, const bool skip_load_image)
{
TexResult texr;
float fx, fy, minx, maxx, miny, maxy;
@@ -952,7 +942,7 @@ static int imagewraposa_aniso(Tex *tex, Image *ima, ImBuf *ibuf, const float tex
if (ibuf==NULL && ima==NULL) return retval;
if (ima) { /* hack for icon render */
- if ((R.r.scemode & R_NO_IMAGE_LOAD) && !BKE_image_has_loaded_ibuf(ima)) {
+ if (skip_load_image && !BKE_image_has_loaded_ibuf(ima)) {
return retval;
}
ibuf = BKE_image_pool_acquire_ibuf(ima, &tex->iuser, pool);
@@ -1155,7 +1145,7 @@ static int imagewraposa_aniso(Tex *tex, Image *ima, ImBuf *ibuf, const float tex
ImBuf *previbuf, *curibuf;
float levf;
int maxlev;
- ImBuf *mipmaps[IB_MIPMAP_LEVELS + 1];
+ ImBuf *mipmaps[IMB_MIPMAP_LEVELS + 1];
/* modify ellipse minor axis if too eccentric, use for area sampling as well
* scaling dxt/dyt as done in pbrt is not the same
@@ -1195,7 +1185,7 @@ static int imagewraposa_aniso(Tex *tex, Image *ima, ImBuf *ibuf, const float tex
curmap = 0;
maxlev = 1;
mipmaps[0] = ibuf;
- while (curmap < IB_MIPMAP_LEVELS) {
+ while (curmap < IMB_MIPMAP_LEVELS) {
mipmaps[curmap + 1] = ibuf->mipmap[curmap];
if (ibuf->mipmap[curmap]) maxlev++;
curmap++;
@@ -1212,7 +1202,7 @@ static int imagewraposa_aniso(Tex *tex, Image *ima, ImBuf *ibuf, const float tex
if (tex->texfilter == TXF_FELINE) AFD.iProbes = 1;
}
else {
- const int lev = ISNAN(levf) ? 0 : (int)levf;
+ const int lev = isnan(levf) ? 0 : (int)levf;
curibuf = mipmaps[lev];
previbuf = mipmaps[lev + 1];
levf -= floorf(levf);
@@ -1348,7 +1338,7 @@ static int imagewraposa_aniso(Tex *tex, Image *ima, ImBuf *ibuf, const float tex
}
-int imagewraposa(Tex *tex, Image *ima, ImBuf *ibuf, const float texvec[3], const float DXT[2], const float DYT[2], TexResult *texres, struct ImagePool *pool)
+int imagewraposa(Tex *tex, Image *ima, ImBuf *ibuf, const float texvec[3], const float DXT[2], const float DYT[2], TexResult *texres, struct ImagePool *pool, const bool skip_load_image)
{
TexResult texr;
float fx, fy, minx, maxx, miny, maxy, dx, dy, dxt[2], dyt[2];
@@ -1362,7 +1352,7 @@ int imagewraposa(Tex *tex, Image *ima, ImBuf *ibuf, const float texvec[3], const
/* anisotropic filtering */
if (tex->texfilter != TXF_BOX)
- return imagewraposa_aniso(tex, ima, ibuf, texvec, dxt, dyt, texres, pool);
+ return imagewraposa_aniso(tex, ima, ibuf, texvec, dxt, dyt, texres, pool, skip_load_image);
texres->tin= texres->ta= texres->tr= texres->tg= texres->tb= 0.0f;
@@ -1375,7 +1365,7 @@ int imagewraposa(Tex *tex, Image *ima, ImBuf *ibuf, const float texvec[3], const
if (ima) {
/* hack for icon render */
- if ((R.r.scemode & R_NO_IMAGE_LOAD) && !BKE_image_has_loaded_ibuf(ima))
+ if (skip_load_image && !BKE_image_has_loaded_ibuf(ima))
return retval;
ibuf = BKE_image_pool_acquire_ibuf(ima, &tex->iuser, pool);
@@ -1595,7 +1585,7 @@ int imagewraposa(Tex *tex, Image *ima, ImBuf *ibuf, const float texvec[3], const
curmap= 0;
previbuf= curibuf= ibuf;
- while (curmap<IB_MIPMAP_LEVELS && ibuf->mipmap[curmap]) {
+ while (curmap < IMB_MIPMAP_LEVELS && ibuf->mipmap[curmap]) {
if (maxd < pixsize) break;
previbuf= curibuf;
curibuf= ibuf->mipmap[curmap];
diff --git a/source/blender/render/intern/source/initrender.c b/source/blender/render/intern/source/initrender.c
index 353ba5d5caa..970a3937657 100644
--- a/source/blender/render/intern/source/initrender.c
+++ b/source/blender/render/intern/source/initrender.c
@@ -36,8 +36,6 @@
#include "MEM_guardedalloc.h"
-#include "PIL_time.h"
-
#include "BLI_math.h"
#include "BLI_blenlib.h"
#include "BLI_jitter.h"
@@ -48,12 +46,8 @@
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
-
#include "BKE_camera.h"
-#include "IMB_imbuf_types.h"
-#include "IMB_imbuf.h"
-
#ifdef WITH_QUICKTIME
#include "quicktime_export.h"
#endif
@@ -62,10 +56,6 @@
#include "renderpipeline.h"
#include "render_types.h"
-#include "rendercore.h"
-#include "pixelshading.h"
-#include "zbuf.h"
-
/* Own includes */
#include "initrender.h"
@@ -164,8 +154,11 @@ float RE_filter_value(int type, float x)
return 1.0f - x;
case R_FILTER_GAUSS:
- x *= gaussfac;
- return (1.0f / expf(x * x) - 1.0f / expf(gaussfac * gaussfac * 2.25f));
+ {
+ const float two_gaussfac2 = 2.0f * gaussfac * gaussfac;
+ x *= 3.0f * gaussfac;
+ return 1.0f / sqrtf((float)M_PI * two_gaussfac2) * expf(-x*x / two_gaussfac2);
+ }
case R_FILTER_MITCH:
return filt_mitchell(x * gaussfac);
@@ -433,10 +426,10 @@ void make_sample_tables(Render *re)
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
-
struct Object *RE_GetCamera(Render *re)
{
- return re->camera_override ? re->camera_override : re->scene->camera;
+ Object *camera = re->camera_override ? re->camera_override : re->scene->camera;
+ return BKE_camera_multiview_render(re->scene, camera, re->viewname);
}
static void re_camera_params_get(Render *re, CameraParams *params, Object *cam_ob)
@@ -477,6 +470,16 @@ void RE_SetEnvmapCamera(Render *re, Object *cam_ob, float viewscale, float clips
re_camera_params_get(re, &params, cam_ob);
}
+void RE_SetOverrideCamera(Render *re, Object *camera)
+{
+ re->camera_override = camera;
+}
+
+static void re_camera_params_stereo3d(Render *re, CameraParams *params, Object *cam_ob)
+{
+ BKE_camera_multiview_params(&re->r, params, cam_ob, re->viewname);
+}
+
/* call this after InitState() */
/* per render, there's one persistent viewplane. Parts will set their own viewplanes */
void RE_SetCamera(Render *re, Object *cam_ob)
@@ -486,6 +489,7 @@ void RE_SetCamera(Render *re, Object *cam_ob)
/* setup parameters */
BKE_camera_params_init(&params);
BKE_camera_params_from_object(&params, cam_ob);
+ re_camera_params_stereo3d(re, &params, cam_ob);
params.use_fields = (re->r.mode & R_FIELDS);
params.field_second = (re->flag & R_SEC_FIELD);
@@ -512,6 +516,11 @@ void RE_GetCameraWindow(struct Render *re, struct Object *camera, int frame, flo
copy_m4_m4(mat, re->winmat);
}
+void RE_GetCameraModelMatrix(Render *re, struct Object *camera, float r_mat[4][4])
+{
+ BKE_camera_multiview_model_matrix(&re->r, camera, re->viewname, r_mat);
+}
+
/* ~~~~~~~~~~~~~~~~ part (tile) calculus ~~~~~~~~~~~~~~~~~~~~~~ */
diff --git a/source/blender/render/intern/source/multires_bake.c b/source/blender/render/intern/source/multires_bake.c
index 6ba85ea5329..dcc33b99742 100644
--- a/source/blender/render/intern/source/multires_bake.c
+++ b/source/blender/render/intern/source/multires_bake.c
@@ -45,6 +45,7 @@
#include "BKE_depsgraph.h"
#include "BKE_global.h"
#include "BKE_image.h"
+#include "BKE_mesh.h"
#include "BKE_multires.h"
#include "BKE_modifier.h"
#include "BKE_subsurf.h"
@@ -73,13 +74,15 @@ typedef struct MultiresBakeResult {
typedef struct {
MVert *mvert;
- MFace *mface;
- MTFace *mtface;
+ MPoly *mpoly;
+ MLoop *mloop;
+ MLoopUV *mloopuv;
+ const MLoopTri *mlooptri;
+ MTexPoly *mtpoly;
float *pvtangent;
const float *precomputed_normals;
int w, h;
- int face_index;
- int i0, i1, i2;
+ int tri_index;
DerivedMesh *lores_dm, *hires_dm;
int lvl;
void *thread_data;
@@ -102,12 +105,10 @@ typedef struct {
float *heights;
Image *ima;
DerivedMesh *ssdm;
- const int *orig_index_mf_to_mpoly;
const int *orig_index_mp_to_orig;
} MHeightBakeData;
typedef struct {
- const int *orig_index_mf_to_mpoly;
const int *orig_index_mp_to_orig;
} MNormalBakeData;
@@ -121,42 +122,26 @@ typedef struct {
RayObject *raytree;
RayFace *rayfaces;
- const int *orig_index_mf_to_mpoly;
const int *orig_index_mp_to_orig;
} MAOBakeData;
-static void multiresbake_get_normal(const MResolvePixelData *data, float norm[],const int face_num, const int vert_index)
+static void multiresbake_get_normal(const MResolvePixelData *data, float norm[],const int tri_num, const int vert_index)
{
- unsigned int indices[] = {data->mface[face_num].v1, data->mface[face_num].v2,
- data->mface[face_num].v3, data->mface[face_num].v4};
- const int smoothnormal = (data->mface[face_num].flag & ME_SMOOTH);
+ const int poly_index = data->mlooptri[tri_num].poly;
+ const MPoly *mp = &data->mpoly[poly_index];
+ const bool smoothnormal = (mp->flag & ME_SMOOTH) != 0;
if (!smoothnormal) { /* flat */
if (data->precomputed_normals) {
- copy_v3_v3(norm, &data->precomputed_normals[3 * face_num]);
+ copy_v3_v3(norm, &data->precomputed_normals[poly_index]);
}
else {
- float nor[3];
- const float *p0, *p1, *p2;
- const int iGetNrVerts = data->mface[face_num].v4 != 0 ? 4 : 3;
-
- p0 = data->mvert[indices[0]].co;
- p1 = data->mvert[indices[1]].co;
- p2 = data->mvert[indices[2]].co;
-
- if (iGetNrVerts == 4) {
- const float *p3 = data->mvert[indices[3]].co;
- normal_quad_v3(nor, p0, p1, p2, p3);
- }
- else {
- normal_tri_v3(nor, p0, p1, p2);
- }
-
- copy_v3_v3(norm, nor);
+ BKE_mesh_calc_poly_normal(mp, &data->mloop[mp->loopstart], data->mvert, norm);
}
}
else {
- const short *no = data->mvert[indices[vert_index]].no;
+ const int vi = data->mloop[data->mlooptri[tri_num].tri[vert_index]].v;
+ const short *no = data->mvert[vi].no;
normal_short_to_float_v3(norm, no);
normalize_v3(norm);
@@ -188,17 +173,13 @@ static void flush_pixel(const MResolvePixelData *data, const int x, const int y)
float u, v, w, sign;
int r;
- const int i0 = data->i0;
- const int i1 = data->i1;
- const int i2 = data->i2;
+ st0 = data->mloopuv[data->mlooptri[data->tri_index].tri[0]].uv;
+ st1 = data->mloopuv[data->mlooptri[data->tri_index].tri[1]].uv;
+ st2 = data->mloopuv[data->mlooptri[data->tri_index].tri[2]].uv;
- st0 = data->mtface[data->face_index].uv[i0];
- st1 = data->mtface[data->face_index].uv[i1];
- st2 = data->mtface[data->face_index].uv[i2];
-
- multiresbake_get_normal(data, no0, data->face_index, i0); /* can optimize these 3 into one call */
- multiresbake_get_normal(data, no1, data->face_index, i1);
- multiresbake_get_normal(data, no2, data->face_index, i2);
+ multiresbake_get_normal(data, no0, data->tri_index, 0); /* can optimize these 3 into one call */
+ multiresbake_get_normal(data, no1, data->tri_index, 1);
+ multiresbake_get_normal(data, no2, data->tri_index, 2);
resolve_tri_uv_v2(fUV, st, st0, st1, st2);
@@ -207,9 +188,9 @@ static void flush_pixel(const MResolvePixelData *data, const int x, const int y)
w = 1 - u - v;
if (data->pvtangent) {
- tang0 = data->pvtangent + data->face_index * 16 + i0 * 4;
- tang1 = data->pvtangent + data->face_index * 16 + i1 * 4;
- tang2 = data->pvtangent + data->face_index * 16 + i2 * 4;
+ tang0 = data->pvtangent + data->mlooptri[data->tri_index].tri[0] * 4;
+ tang1 = data->pvtangent + data->mlooptri[data->tri_index].tri[1] * 4;
+ tang2 = data->pvtangent + data->mlooptri[data->tri_index].tri[2] * 4;
/* the sign is the same at all face vertices for any non degenerate face.
* Just in case we clamp the interpolated value though. */
@@ -231,7 +212,7 @@ static void flush_pixel(const MResolvePixelData *data, const int x, const int y)
}
data->pass_data(data->lores_dm, data->hires_dm, data->thread_data, data->bake_data,
- data->ibuf, data->face_index, data->lvl, st, to_tang, x, y);
+ data->ibuf, data->tri_index, data->lvl, st, to_tang, x, y);
}
static void set_rast_triangle(const MBakeRast *bake_rast, const int x, const int y)
@@ -344,8 +325,8 @@ static int multiresbake_test_break(MultiresBakeRender *bkr)
/* **** Threading routines **** */
typedef struct MultiresBakeQueue {
- int cur_face;
- int tot_face;
+ int cur_tri;
+ int tot_tri;
SpinLock spin;
} MultiresBakeQueue;
@@ -364,7 +345,7 @@ typedef struct MultiresBakeThread {
float height_min, height_max;
} MultiresBakeThread;
-static int multires_bake_queue_next_face(MultiresBakeQueue *queue)
+static int multires_bake_queue_next_tri(MultiresBakeQueue *queue)
{
int face = -1;
@@ -373,9 +354,9 @@ static int multires_bake_queue_next_face(MultiresBakeQueue *queue)
*/
BLI_spin_lock(&queue->spin);
- if (queue->cur_face < queue->tot_face) {
- face = queue->cur_face;
- queue->cur_face++;
+ if (queue->cur_tri < queue->tot_tri) {
+ face = queue->cur_tri;
+ queue->cur_tri++;
}
BLI_spin_unlock(&queue->spin);
@@ -388,44 +369,28 @@ static void *do_multires_bake_thread(void *data_v)
MResolvePixelData *data = &handle->data;
MBakeRast *bake_rast = &handle->bake_rast;
MultiresBakeRender *bkr = handle->bkr;
- int f;
+ int tri_index;
- while ((f = multires_bake_queue_next_face(handle->queue)) >= 0) {
- MTFace *mtfate = &data->mtface[f];
- int verts[3][2], nr_tris, t;
+ while ((tri_index = multires_bake_queue_next_tri(handle->queue)) >= 0) {
+ const MLoopTri *lt = &data->mlooptri[tri_index];
+ MTexPoly *mtpoly = &data->mtpoly[lt->poly];
+ MLoopUV *mloopuv = data->mloopuv;
if (multiresbake_test_break(bkr))
break;
- if (mtfate->tpage != handle->image)
+ if (mtpoly->tpage != handle->image)
continue;
- data->face_index = f;
-
- /* might support other forms of diagonal splits later on such as
- * split by shortest diagonal.*/
- verts[0][0] = 0;
- verts[1][0] = 1;
- verts[2][0] = 2;
+ data->tri_index = tri_index;
- verts[0][1] = 0;
- verts[1][1] = 2;
- verts[2][1] = 3;
+ bake_rasterize(bake_rast, mloopuv[lt->tri[0]].uv, mloopuv[lt->tri[1]].uv, mloopuv[lt->tri[2]].uv);
- nr_tris = data->mface[f].v4 != 0 ? 2 : 1;
- for (t = 0; t < nr_tris; t++) {
- data->i0 = verts[0][t];
- data->i1 = verts[1][t];
- data->i2 = verts[2][t];
+ /* tag image buffer for refresh */
+ if (data->ibuf->rect_float)
+ data->ibuf->userflags |= IB_RECT_INVALID;
- bake_rasterize(bake_rast, mtfate->uv[data->i0], mtfate->uv[data->i1], mtfate->uv[data->i2]);
-
- /* tag image buffer for refresh */
- if (data->ibuf->rect_float)
- data->ibuf->userflags |= IB_RECT_INVALID;
-
- data->ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID;
- }
+ data->ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID;
/* update progress */
BLI_spin_lock(&handle->queue->spin);
@@ -435,7 +400,7 @@ static void *do_multires_bake_thread(void *data_v)
*bkr->do_update = true;
if (bkr->progress)
- *bkr->progress = ((float)bkr->baked_objects + (float)bkr->baked_faces / handle->queue->tot_face) / bkr->tot_obj;
+ *bkr->progress = ((float)bkr->baked_objects + (float)bkr->baked_faces / handle->queue->tot_tri) / bkr->tot_obj;
BLI_spin_unlock(&handle->queue->spin);
}
@@ -467,18 +432,21 @@ static void do_multires_bake(MultiresBakeRender *bkr, Image *ima, bool require_t
MInitBakeData initBakeData, MFreeBakeData freeBakeData, MultiresBakeResult *result)
{
DerivedMesh *dm = bkr->lores_dm;
+ const MLoopTri *mlooptri = dm->getLoopTriArray(dm);
const int lvl = bkr->lvl;
- const int tot_face = dm->getNumTessFaces(dm);
+ int tot_tri = dm->getNumLoopTri(dm);
- if (tot_face > 0) {
+ if (tot_tri > 0) {
MultiresBakeThread *handles;
MultiresBakeQueue queue;
ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL);
MVert *mvert = dm->getVertArray(dm);
- MFace *mface = dm->getTessFaceArray(dm);
- MTFace *mtface = dm->getTessFaceDataArray(dm, CD_MTFACE);
- const float *precomputed_normals = dm->getTessFaceDataArray(dm, CD_NORMAL);
+ MPoly *mpoly = dm->getPolyArray(dm);
+ MLoop *mloop = dm->getLoopArray(dm);
+ MLoopUV *mloopuv = dm->getLoopDataArray(dm, CD_MLOOPUV);
+ MTexPoly *mtpoly = dm->getPolyDataArray(dm, CD_MTEXPOLY);
+ const float *precomputed_normals = dm->getPolyDataArray(dm, CD_NORMAL);
float *pvtangent = NULL;
ListBase threads;
@@ -487,10 +455,10 @@ static void do_multires_bake(MultiresBakeRender *bkr, Image *ima, bool require_t
void *bake_data = NULL;
if (require_tangent) {
- if (CustomData_get_layer_index(&dm->faceData, CD_TANGENT) == -1)
- DM_add_tangent_layer(dm);
+ if (CustomData_get_layer_index(&dm->loopData, CD_TANGENT) == -1)
+ DM_calc_loop_tangents(dm);
- pvtangent = DM_get_tessface_data_layer(dm, CD_TANGENT);
+ pvtangent = DM_get_loop_data_layer(dm, CD_TANGENT);
}
/* all threads shares the same custom bake data */
@@ -505,8 +473,8 @@ static void do_multires_bake(MultiresBakeRender *bkr, Image *ima, bool require_t
init_ccgdm_arrays(bkr->hires_dm);
/* faces queue */
- queue.cur_face = 0;
- queue.tot_face = tot_face;
+ queue.cur_tri = 0;
+ queue.tot_tri = tot_tri;
BLI_spin_init(&queue.spin);
/* fill in threads handles */
@@ -517,9 +485,12 @@ static void do_multires_bake(MultiresBakeRender *bkr, Image *ima, bool require_t
handle->image = ima;
handle->queue = &queue;
- handle->data.mface = mface;
+ handle->data.mpoly = mpoly;
handle->data.mvert = mvert;
- handle->data.mtface = mtface;
+ handle->data.mloopuv = mloopuv;
+ handle->data.mlooptri = mlooptri;
+ handle->data.mtpoly = mtpoly;
+ handle->data.mloop = mloop;
handle->data.pvtangent = pvtangent;
handle->data.precomputed_normals = precomputed_normals; /* don't strictly need this */
handle->data.w = ibuf->x;
@@ -602,40 +573,48 @@ static void interp_bilinear_grid(CCGKey *key, CCGElem *grid, float crn_x, float
}
static void get_ccgdm_data(DerivedMesh *lodm, DerivedMesh *hidm,
- const int *index_mf_to_mpoly, const int *index_mp_to_orig,
- const int lvl, const int face_index, const float u, const float v, float co[3], float n[3])
+ const int *index_mp_to_orig,
+ const int lvl, const MLoopTri *lt, const float u, const float v, float co[3], float n[3])
{
- MFace mface;
CCGElem **grid_data;
CCGKey key;
float crn_x, crn_y;
int grid_size, S, face_side;
int *grid_offset, g_index;
-
- lodm->getTessFace(lodm, face_index, &mface);
+ int poly_index = lt->poly;
grid_size = hidm->getGridSize(hidm);
grid_data = hidm->getGridData(hidm);
grid_offset = hidm->getGridOffset(hidm);
hidm->getGridKey(hidm, &key);
- face_side = (grid_size << 1) - 1;
-
if (lvl == 0) {
- g_index = grid_offset[face_index];
- S = mdisp_rot_face_to_crn(mface.v4 ? 4 : 3, face_side, u * (face_side - 1), v * (face_side - 1), &crn_x, &crn_y);
+ MPoly *mpoly;
+ face_side = (grid_size << 1) - 1;
+
+ mpoly = lodm->getPolyArray(lodm) + poly_index;
+ g_index = grid_offset[poly_index];
+ S = mdisp_rot_face_to_crn(lodm->getVertArray(lodm), mpoly, lodm->getLoopArray(lodm), lt, face_side, u * (face_side - 1), v * (face_side - 1), &crn_x, &crn_y);
}
else {
- int side = (1 << (lvl - 1)) + 1;
- int grid_index = DM_origindex_mface_mpoly(index_mf_to_mpoly, index_mp_to_orig, face_index);
- int loc_offs = face_index % (1 << (2 * lvl));
- int cell_index = loc_offs % ((side - 1) * (side - 1));
- int cell_side = (grid_size - 1) / (side - 1);
- int row = cell_index / (side - 1);
- int col = cell_index % (side - 1);
-
- S = face_index / (1 << (2 * (lvl - 1))) - grid_offset[grid_index];
- g_index = grid_offset[grid_index];
+ /* number of faces per grid side */
+ int polys_per_grid_side = (1 << (lvl - 1));
+ /* get the original cage face index */
+ int cage_face_index = index_mp_to_orig ? index_mp_to_orig[poly_index] : poly_index;
+ /* local offset in total cage face grids
+ * (1 << (2 * lvl)) is number of all polys for one cage face */
+ int loc_cage_poly_offs = poly_index % (1 << (2 * lvl));
+ /* local offset in the vertex grid itself */
+ int cell_index = loc_cage_poly_offs % (polys_per_grid_side * polys_per_grid_side);
+ int cell_side = (grid_size - 1) / polys_per_grid_side;
+ /* row and column based on grid side */
+ int row = cell_index / polys_per_grid_side;
+ int col = cell_index % polys_per_grid_side;
+
+ /* S is the vertex whose grid we are examining */
+ S = poly_index / (1 << (2 * (lvl - 1))) - grid_offset[cage_face_index];
+ /* get offset of grid data for original cage face */
+ g_index = grid_offset[cage_face_index];
crn_y = (row * cell_side) + u * cell_side;
crn_x = (col * cell_side) + v * cell_side;
@@ -653,41 +632,40 @@ static void get_ccgdm_data(DerivedMesh *lodm, DerivedMesh *hidm,
/* mode = 0: interpolate normals,
* mode = 1: interpolate coord */
-static void interp_bilinear_mface(DerivedMesh *dm, MFace *mface, const float u, const float v, const int mode, float res[3])
+
+static void interp_bilinear_mpoly(DerivedMesh *dm, MLoop *mloop, MPoly *mpoly, const float u, const float v, const int mode, float res[3])
{
float data[4][3];
if (mode == 0) {
- dm->getVertNo(dm, mface->v1, data[0]);
- dm->getVertNo(dm, mface->v2, data[1]);
- dm->getVertNo(dm, mface->v3, data[2]);
- dm->getVertNo(dm, mface->v4, data[3]);
+ dm->getVertNo(dm, mloop[mpoly->loopstart].v, data[0]);
+ dm->getVertNo(dm, mloop[mpoly->loopstart + 1].v, data[1]);
+ dm->getVertNo(dm, mloop[mpoly->loopstart + 2].v, data[2]);
+ dm->getVertNo(dm, mloop[mpoly->loopstart + 3].v, data[3]);
}
else {
- dm->getVertCo(dm, mface->v1, data[0]);
- dm->getVertCo(dm, mface->v2, data[1]);
- dm->getVertCo(dm, mface->v3, data[2]);
- dm->getVertCo(dm, mface->v4, data[3]);
+ dm->getVertCo(dm, mloop[mpoly->loopstart].v, data[0]);
+ dm->getVertCo(dm, mloop[mpoly->loopstart + 1].v, data[1]);
+ dm->getVertCo(dm, mloop[mpoly->loopstart + 2].v, data[2]);
+ dm->getVertCo(dm, mloop[mpoly->loopstart + 3].v, data[3]);
}
interp_bilinear_quad_v3(data, u, v, res);
}
-/* mode = 0: interpolate normals,
- * mode = 1: interpolate coord */
-static void interp_barycentric_mface(DerivedMesh *dm, MFace *mface, const float u, const float v, const int mode, float res[3])
+static void interp_barycentric_mlooptri(DerivedMesh *dm, MLoop *mloop, const MLoopTri *lt, const float u, const float v, const int mode, float res[3])
{
float data[3][3];
if (mode == 0) {
- dm->getVertNo(dm, mface->v1, data[0]);
- dm->getVertNo(dm, mface->v2, data[1]);
- dm->getVertNo(dm, mface->v3, data[2]);
+ dm->getVertNo(dm, mloop[lt->tri[0]].v, data[0]);
+ dm->getVertNo(dm, mloop[lt->tri[1]].v, data[1]);
+ dm->getVertNo(dm, mloop[lt->tri[2]].v, data[2]);
}
else {
- dm->getVertCo(dm, mface->v1, data[0]);
- dm->getVertCo(dm, mface->v2, data[1]);
- dm->getVertCo(dm, mface->v3, data[2]);
+ dm->getVertCo(dm, mloop[lt->tri[0]].v, data[0]);
+ dm->getVertCo(dm, mloop[lt->tri[1]].v, data[1]);
+ dm->getVertCo(dm, mloop[lt->tri[2]].v, data[2]);
}
interp_barycentric_tri_v3(data, u, v, res);
@@ -728,7 +706,6 @@ static void *init_heights_data(MultiresBakeRender *bkr, Image *ima)
}
}
- height_data->orig_index_mf_to_mpoly = lodm->getTessFaceDataArray(lodm, CD_ORIGINDEX);
height_data->orig_index_mp_to_orig = lodm->getPolyDataArray(lodm, CD_ORIGINDEX);
BKE_image_release_ibuf(ima, ibuf, NULL);
@@ -753,52 +730,55 @@ static void free_heights_data(void *bake_data)
* mesh to make texture smoother) let's call this point p0 and n.
* - height wound be dot(n, p1-p0) */
static void apply_heights_callback(DerivedMesh *lores_dm, DerivedMesh *hires_dm, void *thread_data_v, void *bake_data,
- ImBuf *ibuf, const int face_index, const int lvl, const float st[2],
+ ImBuf *ibuf, const int tri_index, const int lvl, const float st[2],
float UNUSED(tangmat[3][3]), const int x, const int y)
{
- MTFace *mtface = CustomData_get_layer(&lores_dm->faceData, CD_MTFACE);
- MFace mface;
+ const MLoopTri *lt = lores_dm->getLoopTriArray(lores_dm) + tri_index;
+ MLoop *mloop = lores_dm->getLoopArray(lores_dm);
+ MPoly *mpoly = lores_dm->getPolyArray(lores_dm) + lt->poly;
+ MLoopUV *mloopuv = lores_dm->getLoopDataArray(lores_dm, CD_MLOOPUV);
MHeightBakeData *height_data = (MHeightBakeData *)bake_data;
MultiresBakeThread *thread_data = (MultiresBakeThread *) thread_data_v;
float uv[2], *st0, *st1, *st2, *st3;
int pixel = ibuf->x * y + x;
float vec[3], p0[3], p1[3], n[3], len;
- lores_dm->getTessFace(lores_dm, face_index, &mface);
-
- st0 = mtface[face_index].uv[0];
- st1 = mtface[face_index].uv[1];
- st2 = mtface[face_index].uv[2];
-
- if (mface.v4) {
- st3 = mtface[face_index].uv[3];
+ /* ideally we would work on triangles only, however, we rely on quads to get orthogonal
+ * coordinates for use in grid space (triangle barycentric is not orthogonal) */
+ if (mpoly->totloop == 4) {
+ st0 = mloopuv[mpoly->loopstart].uv;
+ st1 = mloopuv[mpoly->loopstart + 1].uv;
+ st2 = mloopuv[mpoly->loopstart + 2].uv;
+ st3 = mloopuv[mpoly->loopstart + 3].uv;
resolve_quad_uv_v2(uv, st, st0, st1, st2, st3);
}
- else
+ else {
+ st0 = mloopuv[lt->tri[0]].uv;
+ st1 = mloopuv[lt->tri[1]].uv;
+ st2 = mloopuv[lt->tri[2]].uv;
resolve_tri_uv_v2(uv, st, st0, st1, st2);
+ }
CLAMP(uv[0], 0.0f, 1.0f);
CLAMP(uv[1], 0.0f, 1.0f);
get_ccgdm_data(lores_dm, hires_dm,
- height_data->orig_index_mf_to_mpoly, height_data->orig_index_mp_to_orig,
- lvl, face_index, uv[0], uv[1], p1, NULL);
+ height_data->orig_index_mp_to_orig,
+ lvl, lt, uv[0], uv[1], p1, NULL);
if (height_data->ssdm) {
get_ccgdm_data(lores_dm, height_data->ssdm,
- height_data->orig_index_mf_to_mpoly, height_data->orig_index_mp_to_orig,
- 0, face_index, uv[0], uv[1], p0, n);
+ height_data->orig_index_mp_to_orig,
+ 0, lt, uv[0], uv[1], p0, n);
}
else {
- lores_dm->getTessFace(lores_dm, face_index, &mface);
-
- if (mface.v4) {
- interp_bilinear_mface(lores_dm, &mface, uv[0], uv[1], 1, p0);
- interp_bilinear_mface(lores_dm, &mface, uv[0], uv[1], 0, n);
+ if (mpoly->totloop == 4) {
+ interp_bilinear_mpoly(lores_dm, mloop, mpoly, uv[0], uv[1], 1, p0);
+ interp_bilinear_mpoly(lores_dm, mloop, mpoly, uv[0], uv[1], 0, n);
}
else {
- interp_barycentric_mface(lores_dm, &mface, uv[0], uv[1], 1, p0);
- interp_barycentric_mface(lores_dm, &mface, uv[0], uv[1], 0, n);
+ interp_barycentric_mlooptri(lores_dm, mloop, lt, uv[0], uv[1], 1, p0);
+ interp_barycentric_mlooptri(lores_dm, mloop, lt, uv[0], uv[1], 0, n);
}
}
@@ -831,7 +811,6 @@ static void *init_normal_data(MultiresBakeRender *bkr, Image *UNUSED(ima))
normal_data = MEM_callocN(sizeof(MNormalBakeData), "MultiresBake normalData");
- normal_data->orig_index_mf_to_mpoly = lodm->getTessFaceDataArray(lodm, CD_ORIGINDEX);
normal_data->orig_index_mp_to_orig = lodm->getPolyDataArray(lodm, CD_ORIGINDEX);
return (void *)normal_data;
@@ -850,35 +829,39 @@ static void free_normal_data(void *bake_data)
* - multiply it by tangmat
* - vector in color space would be norm(vec) /2 + (0.5, 0.5, 0.5) */
static void apply_tangmat_callback(DerivedMesh *lores_dm, DerivedMesh *hires_dm, void *UNUSED(thread_data),
- void *bake_data, ImBuf *ibuf, const int face_index, const int lvl,
+ void *bake_data, ImBuf *ibuf, const int tri_index, const int lvl,
const float st[2], float tangmat[3][3], const int x, const int y)
{
- MTFace *mtface = CustomData_get_layer(&lores_dm->faceData, CD_MTFACE);
- MFace mface;
+ const MLoopTri *lt = lores_dm->getLoopTriArray(lores_dm) + tri_index;
+ MPoly *mpoly = lores_dm->getPolyArray(lores_dm) + lt->poly;
+ MLoopUV *mloopuv = lores_dm->getLoopDataArray(lores_dm, CD_MLOOPUV);
MNormalBakeData *normal_data = (MNormalBakeData *)bake_data;
float uv[2], *st0, *st1, *st2, *st3;
int pixel = ibuf->x * y + x;
float n[3], vec[3], tmp[3] = {0.5, 0.5, 0.5};
- lores_dm->getTessFace(lores_dm, face_index, &mface);
-
- st0 = mtface[face_index].uv[0];
- st1 = mtface[face_index].uv[1];
- st2 = mtface[face_index].uv[2];
-
- if (mface.v4) {
- st3 = mtface[face_index].uv[3];
+ /* ideally we would work on triangles only, however, we rely on quads to get orthogonal
+ * coordinates for use in grid space (triangle barycentric is not orthogonal) */
+ if (mpoly->totloop == 4) {
+ st0 = mloopuv[mpoly->loopstart].uv;
+ st1 = mloopuv[mpoly->loopstart + 1].uv;
+ st2 = mloopuv[mpoly->loopstart + 2].uv;
+ st3 = mloopuv[mpoly->loopstart + 3].uv;
resolve_quad_uv_v2(uv, st, st0, st1, st2, st3);
}
- else
+ else {
+ st0 = mloopuv[lt->tri[0]].uv;
+ st1 = mloopuv[lt->tri[1]].uv;
+ st2 = mloopuv[lt->tri[2]].uv;
resolve_tri_uv_v2(uv, st, st0, st1, st2);
+ }
CLAMP(uv[0], 0.0f, 1.0f);
CLAMP(uv[1], 0.0f, 1.0f);
get_ccgdm_data(lores_dm, hires_dm,
- normal_data->orig_index_mf_to_mpoly, normal_data->orig_index_mp_to_orig,
- lvl, face_index, uv[0], uv[1], NULL, n);
+ normal_data->orig_index_mp_to_orig,
+ lvl, lt, uv[0], uv[1], NULL, n);
mul_v3_m3v3(vec, tangmat, n);
normalize_v3(vec);
@@ -1016,7 +999,6 @@ static void *init_ao_data(MultiresBakeRender *bkr, Image *UNUSED(ima))
ao_data->number_of_rays = bkr->number_of_rays;
ao_data->bias = bkr->bias;
- ao_data->orig_index_mf_to_mpoly = lodm->getTessFaceDataArray(lodm, CD_ORIGINDEX);
ao_data->orig_index_mp_to_orig = lodm->getPolyDataArray(lodm, CD_ORIGINDEX);
create_ao_raytree(bkr, ao_data);
@@ -1088,12 +1070,13 @@ static int trace_ao_ray(MAOBakeData *ao_data, float ray_start[3], float ray_dire
}
static void apply_ao_callback(DerivedMesh *lores_dm, DerivedMesh *hires_dm, void *UNUSED(thread_data),
- void *bake_data, ImBuf *ibuf, const int face_index, const int lvl,
+ void *bake_data, ImBuf *ibuf, const int tri_index, const int lvl,
const float st[2], float UNUSED(tangmat[3][3]), const int x, const int y)
{
+ const MLoopTri *lt = lores_dm->getLoopTriArray(lores_dm) + tri_index;
+ MPoly *mpoly = lores_dm->getPolyArray(lores_dm) + lt->poly;
+ MLoopUV *mloopuv = lores_dm->getLoopDataArray(lores_dm, CD_MLOOPUV);
MAOBakeData *ao_data = (MAOBakeData *) bake_data;
- MTFace *mtface = CustomData_get_layer(&lores_dm->faceData, CD_MTFACE);
- MFace mface;
int i, k, perm_offs;
float pos[3], nrm[3];
@@ -1104,25 +1087,28 @@ static void apply_ao_callback(DerivedMesh *lores_dm, DerivedMesh *hires_dm, void
int pixel = ibuf->x * y + x;
float uv[2], *st0, *st1, *st2, *st3;
- lores_dm->getTessFace(lores_dm, face_index, &mface);
-
- st0 = mtface[face_index].uv[0];
- st1 = mtface[face_index].uv[1];
- st2 = mtface[face_index].uv[2];
-
- if (mface.v4) {
- st3 = mtface[face_index].uv[3];
+ /* ideally we would work on triangles only, however, we rely on quads to get orthogonal
+ * coordinates for use in grid space (triangle barycentric is not orthogonal) */
+ if (mpoly->totloop == 4) {
+ st0 = mloopuv[mpoly->loopstart].uv;
+ st1 = mloopuv[mpoly->loopstart + 1].uv;
+ st2 = mloopuv[mpoly->loopstart + 2].uv;
+ st3 = mloopuv[mpoly->loopstart + 3].uv;
resolve_quad_uv_v2(uv, st, st0, st1, st2, st3);
}
- else
+ else {
+ st0 = mloopuv[lt->tri[0]].uv;
+ st1 = mloopuv[lt->tri[1]].uv;
+ st2 = mloopuv[lt->tri[2]].uv;
resolve_tri_uv_v2(uv, st, st0, st1, st2);
+ }
CLAMP(uv[0], 0.0f, 1.0f);
CLAMP(uv[1], 0.0f, 1.0f);
get_ccgdm_data(lores_dm, hires_dm,
- ao_data->orig_index_mf_to_mpoly, ao_data->orig_index_mp_to_orig,
- lvl, face_index, uv[0], uv[1], pos, nrm);
+ ao_data->orig_index_mp_to_orig,
+ lvl, lt, uv[0], uv[1], pos, nrm);
/* offset ray origin by user bias along normal */
for (i = 0; i < 3; i++)
@@ -1193,20 +1179,20 @@ static void apply_ao_callback(DerivedMesh *lores_dm, DerivedMesh *hires_dm, void
static void count_images(MultiresBakeRender *bkr)
{
- int a, totface;
+ int a, totpoly;
DerivedMesh *dm = bkr->lores_dm;
- MTFace *mtface = CustomData_get_layer(&dm->faceData, CD_MTFACE);
+ MTexPoly *mtexpoly = CustomData_get_layer(&dm->polyData, CD_MTEXPOLY);
BLI_listbase_clear(&bkr->image);
bkr->tot_image = 0;
- totface = dm->getNumTessFaces(dm);
+ totpoly = dm->getNumPolys(dm);
- for (a = 0; a < totface; a++)
- mtface[a].tpage->id.flag &= ~LIB_DOIT;
+ for (a = 0; a < totpoly; a++)
+ mtexpoly[a].tpage->id.flag &= ~LIB_DOIT;
- for (a = 0; a < totface; a++) {
- Image *ima = mtface[a].tpage;
+ for (a = 0; a < totpoly; a++) {
+ Image *ima = mtexpoly[a].tpage;
if ((ima->id.flag & LIB_DOIT) == 0) {
LinkData *data = BLI_genericNodeN(ima);
BLI_addtail(&bkr->image, data);
@@ -1215,8 +1201,8 @@ static void count_images(MultiresBakeRender *bkr)
}
}
- for (a = 0; a < totface; a++)
- mtface[a].tpage->id.flag &= ~LIB_DOIT;
+ for (a = 0; a < totpoly; a++)
+ mtexpoly[a].tpage->id.flag &= ~LIB_DOIT;
}
static void bake_images(MultiresBakeRender *bkr, MultiresBakeResult *result)
diff --git a/source/blender/render/intern/source/occlusion.c b/source/blender/render/intern/source/occlusion.c
index 0c6341fe9e5..c5c3b6bbf94 100644
--- a/source/blender/render/intern/source/occlusion.c
+++ b/source/blender/render/intern/source/occlusion.c
@@ -43,7 +43,7 @@
#include "BLI_threads.h"
#include "BLI_utildefines.h"
-#include "BLF_translation.h"
+#include "BLT_translation.h"
#include "BKE_node.h"
#include "BKE_scene.h"
@@ -56,9 +56,7 @@
#include "render_types.h"
#include "rendercore.h"
#include "renderdatabase.h"
-#include "pixelshading.h"
#include "shading.h"
-#include "zbuf.h"
/* ------------------------- Declarations --------------------------- */
@@ -476,9 +474,7 @@ static void occ_build_split(OcclusionTree *tree, int begin, int end, int *split)
if (tree->co[a][axis] > mid) {
enda--;
SWAP(OccFace, tree->face[a], tree->face[enda]);
- SWAP(float, tree->co[a][0], tree->co[enda][0]);
- SWAP(float, tree->co[a][1], tree->co[enda][1]);
- SWAP(float, tree->co[a][2], tree->co[enda][2]);
+ swap_v3_v3(tree->co[a], tree->co[enda]);
}
else
a++;
diff --git a/source/blender/render/intern/source/pipeline.c b/source/blender/render/intern/source/pipeline.c
index 2a07474a5dd..ad0856497c3 100644
--- a/source/blender/render/intern/source/pipeline.c
+++ b/source/blender/render/intern/source/pipeline.c
@@ -49,12 +49,13 @@
#include "BLI_listbase.h"
#include "BLI_string.h"
#include "BLI_path_util.h"
+#include "BLI_timecode.h"
#include "BLI_fileops.h"
#include "BLI_threads.h"
#include "BLI_rand.h"
#include "BLI_callbacks.h"
-#include "BLF_translation.h"
+#include "BLT_translation.h"
#include "BKE_animsys.h" /* <------ should this be here?, needed for sequencer update */
#include "BKE_camera.h"
@@ -70,6 +71,7 @@
#include "BKE_scene.h"
#include "BKE_sequencer.h"
#include "BKE_writeavi.h" /* <------ should be replaced once with generic movie module */
+#include "BKE_object.h"
#include "PIL_time.h"
#include "IMB_colormanagement.h"
@@ -83,6 +85,8 @@
# include "FRS_freestyle.h"
#endif
+#include "DEG_depsgraph.h"
+
/* internal */
#include "render_result.h"
#include "render_types.h"
@@ -90,7 +94,6 @@
#include "renderdatabase.h"
#include "rendercore.h"
#include "initrender.h"
-#include "shadbuf.h"
#include "pixelblending.h"
#include "zbuf.h"
@@ -132,7 +135,7 @@ Render R;
/* ********* alloc and free ******** */
-static int do_write_image_or_movie(Render *re, Main *bmain, Scene *scene, bMovieHandle *mh, const char *name_override);
+static int do_write_image_or_movie(Render *re, Main *bmain, Scene *scene, bMovieHandle *mh, const size_t totvideos, const char *name_override);
static volatile int g_break = 0;
static int thread_break(void *UNUSED(arg))
@@ -152,6 +155,7 @@ static void stats_background(void *UNUSED(arg), RenderStats *rs)
{
uintptr_t mem_in_use, mmap_in_use, peak_memory;
float megs_used_memory, mmap_used_memory, megs_peak_memory;
+ char info_time_str[32];
mem_in_use = MEM_get_memory_in_use();
mmap_in_use = MEM_get_mapped_memory_in_use();
@@ -169,8 +173,11 @@ static void stats_background(void *UNUSED(arg), RenderStats *rs)
if (rs->curblur)
fprintf(stdout, IFACE_("Blur %d "), rs->curblur);
+ BLI_timecode_string_from_time_simple(info_time_str, sizeof(info_time_str), PIL_check_seconds_timer() - rs->starttime);
+ fprintf(stdout, IFACE_("| Time:%s | "), info_time_str);
+
if (rs->infostr) {
- fprintf(stdout, "| %s", rs->infostr);
+ fprintf(stdout, "%s", rs->infostr);
}
else {
if (rs->tothalo)
@@ -180,6 +187,9 @@ static void stats_background(void *UNUSED(arg), RenderStats *rs)
fprintf(stdout, IFACE_("Sce: %s Ve:%d Fa:%d La:%d"), rs->scene_name, rs->totvert, rs->totface, rs->totlamp);
}
+ /* Flush stdout to be sure python callbacks are printing stuff after blender. */
+ fflush(stdout);
+
BLI_callback_exec(G.main, NULL, BLI_CB_EVT_RENDER_STATS);
fputc('\n', stdout);
@@ -191,14 +201,10 @@ void RE_FreeRenderResult(RenderResult *res)
render_result_free(res);
}
-float *RE_RenderLayerGetPass(RenderLayer *rl, int passtype)
+float *RE_RenderLayerGetPass(volatile RenderLayer *rl, int passtype, const char *viewname)
{
- RenderPass *rpass;
-
- for (rpass = rl->passes.first; rpass; rpass = rpass->next)
- if (rpass->passtype == passtype)
- return rpass->rect;
- return NULL;
+ RenderPass *rpass = RE_pass_find_by_type(rl, passtype, viewname);
+ return rpass ? rpass->rect : NULL;
}
RenderLayer *RE_GetRenderLayer(RenderResult *rr, const char *name)
@@ -257,7 +263,7 @@ Render *RE_GetRender(const char *name)
/* search for existing renders */
for (re = RenderGlobal.renderlist.first; re; re = re->next)
- if (strncmp(re->name, name, RE_MAXNAME) == 0)
+ if (STREQLEN(re->name, name, RE_MAXNAME))
break;
return re;
@@ -308,8 +314,71 @@ Scene *RE_GetScene(Render *re)
return NULL;
}
+/**
+ * Same as #RE_AcquireResultImage but creating the necessary views to store the result
+ * fill provided result struct with a copy of thew views of what is done so far the
+ * #RenderResult.views #ListBase needs to be freed after with #RE_ReleaseResultImageViews
+*/
+void RE_AcquireResultImageViews(Render *re, RenderResult *rr)
+{
+ memset(rr, 0, sizeof(RenderResult));
+
+ if (re) {
+ BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_READ);
+
+ if (re->result) {
+ RenderLayer *rl;
+ RenderView *rv, *rview;
+
+ rr->rectx = re->result->rectx;
+ rr->recty = re->result->recty;
+
+ /* creates a temporary duplication of views */
+ render_result_views_shallowcopy(rr, re->result);
+
+ rv = rr->views.first;
+
+ /* active layer */
+ rl = render_get_active_layer(re, re->result);
+
+ if (rl) {
+ if (rv->rectf == NULL) {
+ for (rview = (RenderView *)rr->views.first; rview; rview = rview->next) {
+ rview->rectf = RE_RenderLayerGetPass(rl, SCE_PASS_COMBINED, rview->name);
+ }
+ }
+
+ if (rv->rectz == NULL) {
+ for (rview = (RenderView *)rr->views.first; rview; rview = rview->next) {
+ rview->rectz = RE_RenderLayerGetPass(rl, SCE_PASS_Z, rview->name);
+ }
+ }
+ }
+
+ rr->have_combined = (rv->rectf != NULL);
+ rr->layers = re->result->layers;
+ rr->xof = re->disprect.xmin;
+ rr->yof = re->disprect.ymin;
+ rr->stamp_data = re->result->stamp_data;
+ }
+ }
+}
+
+/* clear temporary renderresult struct */
+void RE_ReleaseResultImageViews(Render *re, RenderResult *rr)
+{
+ if (re) {
+ if (rr) {
+ render_result_views_shallowdelete(rr);
+ }
+ BLI_rw_mutex_unlock(&re->resultmutex);
+ }
+}
+
/* fill provided result struct with what's currently active or done */
-void RE_AcquireResultImage(Render *re, RenderResult *rr)
+/* this RenderResult struct is the only exception to the rule of a RenderResult */
+/* always having at least one RenderView */
+void RE_AcquireResultImage(Render *re, RenderResult *rr, const int view_id)
{
memset(rr, 0, sizeof(RenderResult));
@@ -318,27 +387,33 @@ void RE_AcquireResultImage(Render *re, RenderResult *rr)
if (re->result) {
RenderLayer *rl;
+ RenderView *rv;
rr->rectx = re->result->rectx;
rr->recty = re->result->recty;
- rr->rectf = re->result->rectf;
- rr->rectz = re->result->rectz;
- rr->rect32 = re->result->rect32;
-
+ /* actview view */
+ rv = RE_RenderViewGetById(re->result, view_id);
+
+ rr->rectf = rv->rectf;
+ rr->rectz = rv->rectz;
+ rr->rect32 = rv->rect32;
+
/* active layer */
rl = render_get_active_layer(re, re->result);
if (rl) {
- if (rr->rectf == NULL)
- rr->rectf = rl->rectf;
- if (rr->rectz == NULL)
- rr->rectz = RE_RenderLayerGetPass(rl, SCE_PASS_Z);
+ if (rv->rectf == NULL)
+ rr->rectf = RE_RenderLayerGetPass(rl, SCE_PASS_COMBINED, rv->name);
+
+ if (rv->rectz == NULL)
+ rr->rectz = RE_RenderLayerGetPass(rl, SCE_PASS_Z, rv->name);
}
- rr->have_combined = (re->result->rectf != NULL);
+ rr->have_combined = (rv->rectf != NULL);
rr->layers = re->result->layers;
-
+ rr->views = re->result->views;
+
rr->xof = re->disprect.xmin;
rr->yof = re->disprect.ymin;
}
@@ -355,17 +430,18 @@ void RE_ReleaseResultImage(Render *re)
void RE_ResultGet32(Render *re, unsigned int *rect)
{
RenderResult rres;
-
- RE_AcquireResultImage(re, &rres);
- render_result_rect_get_pixels(&rres, rect, re->rectx, re->recty, &re->scene->view_settings, &re->scene->display_settings);
- RE_ReleaseResultImage(re);
+ const size_t view_id = BKE_scene_multiview_view_id_get(&re->r, re->viewname);
+
+ RE_AcquireResultImageViews(re, &rres);
+ render_result_rect_get_pixels(&rres, rect, re->rectx, re->recty, &re->scene->view_settings, &re->scene->display_settings, view_id);
+ RE_ReleaseResultImageViews(re, &rres);
}
/* caller is responsible for allocating rect in correct size! */
/* Only for acquired results, for lock */
-void RE_AcquiredResultGet32(Render *re, RenderResult *result, unsigned int *rect)
+void RE_AcquiredResultGet32(Render *re, RenderResult *result, unsigned int *rect, const int view_id)
{
- render_result_rect_get_pixels(result, rect, re->rectx, re->recty, &re->scene->view_settings, &re->scene->display_settings);
+ render_result_rect_get_pixels(result, rect, re->rectx, re->recty, &re->scene->view_settings, &re->scene->display_settings, view_id);
}
RenderStats *RE_GetStats(Render *re)
@@ -386,8 +462,8 @@ Render *RE_NewRender(const char *name)
BLI_addtail(&RenderGlobal.renderlist, re);
BLI_strncpy(re->name, name, RE_MAXNAME);
BLI_rw_mutex_init(&re->resultmutex);
- re->eval_ctx = MEM_callocN(sizeof(EvaluationContext), "re->eval_ctx");
- re->eval_ctx->mode = DAG_EVAL_RENDER;
+ BLI_rw_mutex_init(&re->partsmutex);
+ re->eval_ctx = DEG_evaluation_context_new(DAG_EVAL_RENDER);
}
RE_InitRenderCB(re);
@@ -424,9 +500,11 @@ void RE_FreeRender(Render *re)
RE_engine_free(re->engine);
BLI_rw_mutex_end(&re->resultmutex);
+ BLI_rw_mutex_end(&re->partsmutex);
BLI_freelistN(&re->r.layers);
-
+ BLI_freelistN(&re->r.views);
+
/* main dbase can already be invalid now, some database-free code checks it */
re->main = NULL;
re->scene = NULL;
@@ -455,6 +533,17 @@ void RE_FreeAllRender(void)
#endif
}
+void RE_FreeAllPersistentData(void)
+{
+ Render *re;
+ for (re = RenderGlobal.renderlist.first; re != NULL; re = re->next) {
+ if ((re->r.mode & R_PERSISTENT_DATA) != 0 && re->engine != NULL) {
+ RE_engine_free(re->engine);
+ re->engine = NULL;
+ }
+ }
+}
+
/* on file load, free all re */
void RE_FreeAllRenderResults(void)
{
@@ -492,6 +581,12 @@ static int check_mode_full_sample(RenderData *rd)
{
int scemode = rd->scemode;
+ if (!STREQ(rd->engine, RE_engine_id_BLENDER_RENDER) &&
+ !STREQ(rd->engine, RE_engine_id_BLENDER_GAME))
+ {
+ scemode &= ~R_FULL_SAMPLE;
+ }
+
if ((rd->mode & R_OSA) == 0)
scemode &= ~R_FULL_SAMPLE;
@@ -567,8 +662,10 @@ void RE_InitState(Render *re, Render *source, RenderData *rd,
/* copy render data and render layers for thread safety */
BLI_freelistN(&re->r.layers);
+ BLI_freelistN(&re->r.views);
re->r = *rd;
BLI_duplicatelist(&re->r.layers, &rd->layers);
+ BLI_duplicatelist(&re->r.views, &rd->views);
if (source) {
/* reuse border flags from source renderer */
@@ -659,6 +756,7 @@ void RE_InitState(Render *re, Render *source, RenderData *rd,
re->result = MEM_callocN(sizeof(RenderResult), "new render result");
re->result->rectx = re->rectx;
re->result->recty = re->recty;
+ render_result_view_new(re->result, "new temporary view");
}
if (re->r.scemode & R_VIEWPORT_PREVIEW)
@@ -676,18 +774,23 @@ void RE_InitState(Render *re, Render *source, RenderData *rd,
RE_init_threadcount(re);
}
+/* This function is only called by view3d rendering, which doesn't support
+ * multiview at the moment. so handle only one view here */
static void render_result_rescale(Render *re)
{
RenderResult *result = re->result;
+ RenderView *rv;
int x, y;
float scale_x, scale_y;
float *src_rectf;
- src_rectf = result->rectf;
+ rv = RE_RenderViewGetById(result, 0);
+ src_rectf = rv->rectf;
+
if (src_rectf == NULL) {
RenderLayer *rl = render_get_active_layer(re, re->result);
if (rl != NULL) {
- src_rectf = rl->rectf;
+ src_rectf = RE_RenderLayerGetPass(rl, SCE_PASS_COMBINED, NULL);
}
}
@@ -697,32 +800,34 @@ static void render_result_rescale(Render *re)
&re->disprect,
0,
RR_USE_MEM,
- RR_ALL_LAYERS);
-
- dst_rectf = re->result->rectf;
- if (dst_rectf == NULL) {
- RenderLayer *rl;
- rl = render_get_active_layer(re, re->result);
- if (rl != NULL) {
- dst_rectf = rl->rectf;
+ RR_ALL_LAYERS,
+ "");
+
+ if (re->result != NULL) {
+ dst_rectf = RE_RenderViewGetById(re->result, 0)->rectf;
+ if (dst_rectf == NULL) {
+ RenderLayer *rl;
+ rl = render_get_active_layer(re, re->result);
+ if (rl != NULL) {
+ dst_rectf = RE_RenderLayerGetPass(rl, SCE_PASS_COMBINED, NULL);
+ }
}
- }
- scale_x = (float) result->rectx / re->result->rectx;
- scale_y = (float) result->recty / re->result->recty;
- for (x = 0; x < re->result->rectx; ++x) {
- for (y = 0; y < re->result->recty; ++y) {
- int src_x = x * scale_x,
- src_y = y * scale_y;
- int dst_index = y * re->result->rectx + x,
- src_index = src_y * result->rectx + src_x;
- copy_v4_v4(dst_rectf + dst_index * 4,
- src_rectf + src_index * 4);
+ scale_x = (float) result->rectx / re->result->rectx;
+ scale_y = (float) result->recty / re->result->recty;
+ for (x = 0; x < re->result->rectx; ++x) {
+ for (y = 0; y < re->result->recty; ++y) {
+ int src_x = x * scale_x;
+ int src_y = y * scale_y;
+ int dst_index = y * re->result->rectx + x;
+ int src_index = src_y * result->rectx + src_x;
+ copy_v4_v4(dst_rectf + dst_index * 4,
+ src_rectf + src_index * 4);
+ }
}
}
+ render_result_free(result);
}
-
- render_result_free(result);
}
void RE_ChangeResolution(Render *re, int winx, int winy, rcti *disprect)
@@ -769,6 +874,10 @@ void render_update_anim_renderdata(Render *re, RenderData *rd)
/* render layers */
BLI_freelistN(&re->r.layers);
BLI_duplicatelist(&re->r.layers, &rd->layers);
+
+ /* render views */
+ BLI_freelistN(&re->r.views);
+ BLI_duplicatelist(&re->r.views, &rd->views);
}
void RE_SetWindow(Render *re, rctf *viewplane, float clipsta, float clipend)
@@ -901,9 +1010,9 @@ static void *do_part_thread(void *pa_v)
if (R.test_break(R.tbh) == 0) {
if (!R.sss_points && (R.r.scemode & R_FULL_SAMPLE))
- pa->result = render_result_new_full_sample(&R, &pa->fullresult, &pa->disprect, pa->crop, RR_USE_MEM);
+ pa->result = render_result_new_full_sample(&R, &pa->fullresult, &pa->disprect, pa->crop, RR_USE_MEM, R.viewname);
else
- pa->result = render_result_new(&R, &pa->disprect, pa->crop, RR_USE_MEM, RR_ALL_LAYERS);
+ pa->result = render_result_new(&R, &pa->disprect, pa->crop, RR_USE_MEM, RR_ALL_LAYERS, R.viewname);
/* Copy EXR tile settings, so pipeline knows whether this is a result
* for Save Buffers enabled rendering.
@@ -926,7 +1035,7 @@ static void *do_part_thread(void *pa_v)
/* merge too on break! */
if (R.result->do_exr_tile) {
- render_result_exr_file_merge(R.result, pa->result);
+ render_result_exr_file_merge(R.result, pa->result, R.viewname);
}
else if (render_display_update_enabled(&R)) {
/* on break, don't merge in result for preview renders, looks nicer */
@@ -1022,13 +1131,28 @@ static bool find_next_pano_slice(Render *re, int *slice, int *minx, rctf *viewpl
return found;
}
-static RenderPart *find_next_part(Render *re, int minx)
+typedef struct SortRenderPart {
+ RenderPart *pa;
+ long long int dist;
+} SortRenderPart;
+
+static int sort_render_part(const void *pa1, const void *pa2) {
+ const SortRenderPart *rpa1 = pa1;
+ const SortRenderPart *rpa2 = pa2;
+
+ if (rpa1->dist > rpa2->dist) return 1;
+ else if (rpa1->dist < rpa2->dist) return -1;
+
+ return 0;
+}
+
+static int sort_and_queue_parts(Render *re, int minx, ThreadQueue *workqueue)
{
- RenderPart *pa, *best = NULL;
+ RenderPart *pa;
/* long long int's needed because of overflow [#24414] */
long long int centx = re->winx / 2, centy = re->winy / 2, tot = 1;
- long long int mindist = (long long int)re->winx * (long long int)re->winy;
+ int totsort = 0;
/* find center of rendered parts, image center counts for 1 too */
for (pa = re->parts.first; pa; pa = pa->next) {
@@ -1037,31 +1161,48 @@ static RenderPart *find_next_part(Render *re, int minx)
centy += BLI_rcti_cent_y(&pa->disprect);
tot++;
}
+ else if (pa->status == PART_STATUS_NONE && pa->nr == 0) {
+ if (!(re->r.mode & R_PANORAMA) || pa->disprect.xmin == minx) {
+ totsort++;
+ }
+ }
}
centx /= tot;
centy /= tot;
- /* closest of the non-rendering parts */
- for (pa = re->parts.first; pa; pa = pa->next) {
- if (pa->status == PART_STATUS_NONE && pa->nr == 0) {
- long long int distx = centx - BLI_rcti_cent_x(&pa->disprect);
- long long int disty = centy - BLI_rcti_cent_y(&pa->disprect);
- distx = (long long int)sqrt(distx * distx + disty * disty);
- if (distx < mindist) {
- if (re->r.mode & R_PANORAMA) {
- if (pa->disprect.xmin == minx) {
- best = pa;
- mindist = distx;
- }
- }
- else {
- best = pa;
- mindist = distx;
+ if (totsort > 0) {
+ SortRenderPart *sortlist = MEM_mallocN(sizeof(*sortlist) * totsort, "renderpartsort");
+ long int i = 0;
+
+ /* prepare the list */
+ for (pa = re->parts.first; pa; pa = pa->next) {
+ if (pa->status == PART_STATUS_NONE && pa->nr == 0) {
+ if (!(re->r.mode & R_PANORAMA) || pa->disprect.xmin == minx) {
+ long long int distx = centx - BLI_rcti_cent_x(&pa->disprect);
+ long long int disty = centy - BLI_rcti_cent_y(&pa->disprect);
+ sortlist[i].dist = (long long int)sqrt(distx * distx + disty * disty);
+ sortlist[i].pa = pa;
+ i++;
}
}
}
+
+ /* Now sort it */
+ qsort(sortlist, totsort, sizeof(*sortlist), sort_render_part);
+
+ /* Finally flush it to the workqueue */
+ for (i = 0; i < totsort; i++) {
+ pa = sortlist[i].pa;
+ pa->nr = i + 1; /* for nicest part, and for stats */
+ BLI_thread_queue_push(workqueue, pa);
+ }
+
+ MEM_freeN(sortlist);
+
+ return totsort;
}
- return best;
+
+ return 0;
}
static void print_part_stats(Render *re, RenderPart *pa)
@@ -1106,16 +1247,23 @@ static void *do_render_thread(void *thread_v)
return NULL;
}
-static void threaded_tile_processor(Render *re)
+static void main_render_result_end(Render *re)
+{
+ if (re->result->do_exr_tile) {
+ BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE);
+ render_result_exr_file_end(re);
+ BLI_rw_mutex_unlock(&re->resultmutex);
+ }
+
+ if (re->r.scemode & R_EXR_CACHE_FILE) {
+ BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE);
+ render_result_exr_file_cache_write(re);
+ BLI_rw_mutex_unlock(&re->resultmutex);
+ }
+}
+
+static void main_render_result_new(Render *re)
{
- RenderThread thread[BLENDER_MAX_THREADS];
- ThreadQueue *workqueue, *donequeue;
- ListBase threads;
- RenderPart *pa;
- rctf viewplane = re->viewplane;
- double lastdraw, elapsed, redrawtime = 1.0f;
- int totpart = 0, minx = 0, slice = 0, a, wait;
-
BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE);
/* first step; free the entire render result, make new, and/or prepare exr buffer saving */
@@ -1123,25 +1271,38 @@ static void threaded_tile_processor(Render *re)
render_result_free(re->result);
if (re->sss_points && render_display_update_enabled(re))
- re->result = render_result_new(re, &re->disprect, 0, RR_USE_MEM, RR_ALL_LAYERS);
+ re->result = render_result_new(re, &re->disprect, 0, RR_USE_MEM, RR_ALL_LAYERS, RR_ALL_VIEWS);
else if (re->r.scemode & R_FULL_SAMPLE)
- re->result = render_result_new_full_sample(re, &re->fullresult, &re->disprect, 0, RR_USE_EXR);
+ re->result = render_result_new_full_sample(re, &re->fullresult, &re->disprect, 0, RR_USE_EXR, RR_ALL_VIEWS);
else
re->result = render_result_new(re, &re->disprect, 0,
- (re->r.scemode & R_EXR_TILE_FILE) ? RR_USE_EXR : RR_USE_MEM, RR_ALL_LAYERS);
+ (re->r.scemode & R_EXR_TILE_FILE) ? RR_USE_EXR : RR_USE_MEM, RR_ALL_LAYERS, RR_ALL_VIEWS);
}
BLI_rw_mutex_unlock(&re->resultmutex);
+
+ if (re->result) {
+ if (re->result->do_exr_tile) {
+ render_result_exr_file_begin(re);
+ }
+ }
+}
+
+static void threaded_tile_processor(Render *re)
+{
+ RenderThread thread[BLENDER_MAX_THREADS];
+ ThreadQueue *workqueue, *donequeue;
+ ListBase threads;
+ RenderPart *pa;
+ rctf viewplane = re->viewplane;
+ double lastdraw, elapsed, redrawtime = 1.0f;
+ int totpart = 0, minx = 0, slice = 0, a, wait;
if (re->result == NULL)
return;
/* warning; no return here without closing exr file */
-
RE_parts_init(re, true);
-
- if (re->result->do_exr_tile)
- render_result_exr_file_begin(re);
/* assuming no new data gets added to dbase... */
R = *re;
@@ -1156,11 +1317,7 @@ static void threaded_tile_processor(Render *re)
/* for panorama we loop over slices */
while (find_next_pano_slice(re, &slice, &minx, &viewplane)) {
/* gather parts into queue */
- while ((pa = find_next_part(re, minx))) {
- pa->nr = totpart + 1; /* for nicest part, and for stats */
- totpart++;
- BLI_thread_queue_push(workqueue, pa);
- }
+ totpart = sort_and_queue_parts(re, minx, workqueue);
BLI_thread_queue_nowait(workqueue);
@@ -1246,27 +1403,23 @@ static void threaded_tile_processor(Render *re)
BLI_thread_queue_free(donequeue);
BLI_thread_queue_free(workqueue);
-
- if (re->result->do_exr_tile) {
- BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE);
- render_result_exr_file_end(re);
- BLI_rw_mutex_unlock(&re->resultmutex);
- }
- if (re->r.scemode & R_EXR_CACHE_FILE) {
+ if (re->result->do_exr_tile) {
BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE);
- render_result_exr_file_cache_write(re);
+ render_result_save_empty_result_tiles(re);
BLI_rw_mutex_unlock(&re->resultmutex);
}
/* unset threadsafety */
g_break = 0;
-
+ BLI_rw_mutex_lock(&re->partsmutex, THREAD_LOCK_WRITE);
RE_parts_free(re);
+ BLI_rw_mutex_unlock(&re->partsmutex);
re->viewplane = viewplane; /* restore viewplane, modified by pano render */
}
#ifdef WITH_FREESTYLE
+static void init_freestyle(Render *re);
static void add_freestyle(Render *re, int render);
static void free_all_freestyle_renders(void);
#endif
@@ -1274,6 +1427,7 @@ static void free_all_freestyle_renders(void);
/* currently only called by preview renders and envmap */
void RE_TileProcessor(Render *re)
{
+ main_render_result_new(re);
threaded_tile_processor(re);
re->i.lastframetime = PIL_check_seconds_timer() - re->i.starttime;
@@ -1283,8 +1437,8 @@ void RE_TileProcessor(Render *re)
/* Freestyle */
if (re->r.mode & R_EDGE_FRS) {
if (!re->test_break(re->tbh)) {
+ init_freestyle(re);
add_freestyle(re, 1);
-
free_all_freestyle_renders();
re->i.lastframetime = PIL_check_seconds_timer() - re->i.starttime;
@@ -1299,6 +1453,7 @@ void RE_TileProcessor(Render *re)
static void do_render_3d(Render *re)
{
+ RenderView *rv;
int cfra_backup;
re->current_scene_update(re->suh, re->scene);
@@ -1315,40 +1470,55 @@ static void do_render_3d(Render *re)
BKE_scene_frame_set(re->scene, (double)re->scene->r.cfra + (double)re->mblur_offs + (double)re->field_offs);
- /* lock drawing in UI during data phase */
- if (re->draw_lock)
- re->draw_lock(re->dlh, 1);
-
- /* make render verts/faces/halos/lamps */
- if (render_scene_needs_vector(re)) {
- RE_Database_FromScene_Vectors(re, re->main, re->scene, re->lay);
- }
- else {
- RE_Database_FromScene(re, re->main, re->scene, re->lay, 1);
- RE_Database_Preprocess(re);
+ /* init main render result */
+ main_render_result_new(re);
+
+#ifdef WITH_FREESTYLE
+ if (re->r.mode & R_EDGE_FRS) {
+ init_freestyle(re);
}
+#endif
+
+ /* we need a new database for each view */
+ for (rv = re->result->views.first; rv; rv = rv->next) {
+ RE_SetActiveRenderView(re, rv->name);
+
+ /* lock drawing in UI during data phase */
+ if (re->draw_lock)
+ re->draw_lock(re->dlh, 1);
+
+ /* make render verts/faces/halos/lamps */
+ if (render_scene_needs_vector(re))
+ RE_Database_FromScene_Vectors(re, re->main, re->scene, re->lay);
+ else {
+ RE_Database_FromScene(re, re->main, re->scene, re->lay, 1);
+ RE_Database_Preprocess(re);
+ }
- /* clear UI drawing locks */
- if (re->draw_lock)
- re->draw_lock(re->dlh, 0);
+ /* clear UI drawing locks */
+ if (re->draw_lock)
+ re->draw_lock(re->dlh, 0);
- threaded_tile_processor(re);
+ threaded_tile_processor(re);
#ifdef WITH_FREESTYLE
- /* Freestyle */
- if (re->r.mode & R_EDGE_FRS)
- if (!re->test_break(re->tbh))
- add_freestyle(re, 1);
+ /* Freestyle */
+ if (re->r.mode & R_EDGE_FRS)
+ if (!re->test_break(re->tbh))
+ add_freestyle(re, 1);
#endif
- /* do left-over 3d post effects (flares) */
- if (re->flag & R_HALO)
- if (!re->test_break(re->tbh))
- add_halo_flare(re);
-
- /* free all render verts etc */
- RE_Database_Free(re);
-
+ /* do left-over 3d post effects (flares) */
+ if (re->flag & R_HALO)
+ if (!re->test_break(re->tbh))
+ add_halo_flare(re);
+
+ /* free all render verts etc */
+ RE_Database_Free(re);
+ }
+
+ main_render_result_end(re);
+
re->scene->r.cfra = cfra_backup;
re->scene->r.subframe = 0.f;
}
@@ -1421,19 +1591,13 @@ static void merge_renderresult_blur(RenderResult *rr, RenderResult *brr, float b
rl1 = brr->layers.first;
for (rl = rr->layers.first; rl && rl1; rl = rl->next, rl1 = rl1->next) {
-
- /* combined */
- if (rl->rectf && rl1->rectf) {
- if (key_alpha)
- addblur_rect_key(rr, rl->rectf, rl1->rectf, blurfac);
- else
- addblur_rect(rr, rl->rectf, rl1->rectf, blurfac, 4);
- }
-
/* passes are allocated in sync */
rpass1 = rl1->passes.first;
for (rpass = rl->passes.first; rpass && rpass1; rpass = rpass->next, rpass1 = rpass1->next) {
- addblur_rect(rr, rpass->rect, rpass1->rect, blurfac, rpass->channels);
+ if ((rpass->passtype & SCE_PASS_COMBINED) && key_alpha)
+ addblur_rect_key(rr, rpass->rect, rpass1->rect, blurfac);
+ else
+ addblur_rect(rr, rpass->rect, rpass1->rect, blurfac, rpass->channels);
}
}
}
@@ -1446,7 +1610,7 @@ static void do_render_blur_3d(Render *re)
int blur = re->r.mblur_samples;
/* create accumulation render result */
- rres = render_result_new(re, &re->disprect, 0, RR_USE_MEM, RR_ALL_LAYERS);
+ rres = render_result_new(re, &re->disprect, 0, RR_USE_MEM, RR_ALL_LAYERS, RR_ALL_VIEWS);
/* do the blur steps */
while (blur--) {
@@ -1508,10 +1672,6 @@ static void merge_renderresult_fields(RenderResult *rr, RenderResult *rr1, Rende
rl2 = rr2->layers.first;
for (rl = rr->layers.first; rl && rl1 && rl2; rl = rl->next, rl1 = rl1->next, rl2 = rl2->next) {
- /* combined */
- if (rl->rectf && rl1->rectf && rl2->rectf)
- interleave_rect(rr, rl->rectf, rl1->rectf, rl2->rectf, 4);
-
/* passes are allocated in sync */
rpass1 = rl1->passes.first;
rpass2 = rl2->passes.first;
@@ -1579,7 +1739,7 @@ static void do_render_fields_3d(Render *re)
re->disprect.ymax *= 2;
BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE);
- re->result = render_result_new(re, &re->disprect, 0, RR_USE_MEM, RR_ALL_LAYERS);
+ re->result = render_result_new(re, &re->disprect, 0, RR_USE_MEM, RR_ALL_LAYERS, RR_ALL_VIEWS);
if (rr2) {
if (re->r.mode & R_ODDFIELD)
@@ -1651,7 +1811,7 @@ static void do_render_fields_blur_3d(Render *re)
/* weak is: it chances disprect from border */
render_result_disprect_to_full_resolution(re);
- rres = render_result_new(re, &re->disprect, 0, RR_USE_MEM, RR_ALL_LAYERS);
+ rres = render_result_new(re, &re->disprect, 0, RR_USE_MEM, RR_ALL_LAYERS, RR_ALL_VIEWS);
render_result_merge(rres, re->result);
render_result_free(re->result);
@@ -1946,7 +2106,7 @@ static void ntree_render_scenes(Render *re)
}
/* bad call... need to think over proper method still */
-static void render_composit_stats(void *UNUSED(arg), char *str)
+static void render_composit_stats(void *UNUSED(arg), const char *str)
{
R.i.infostr = str;
R.stats_draw(R.sdh, &R.i);
@@ -1954,6 +2114,23 @@ static void render_composit_stats(void *UNUSED(arg), char *str)
}
#ifdef WITH_FREESTYLE
+/* init Freestyle renderer */
+static void init_freestyle(Render *re)
+{
+ re->freestyle_bmain = BKE_main_new();
+
+ /* We use the same window manager for freestyle bmain as
+ * real bmain uses. This is needed because freestyle's
+ * bmain could be used to tag scenes for update, which
+ * implies call of ED_render_scene_update in some cases
+ * and that function requires proper window manager
+ * to present (sergey)
+ */
+ re->freestyle_bmain->wm = re->main->wm;
+
+ FRS_init_stroke_renderer(re);
+}
+
/* invokes Freestyle stroke rendering */
static void add_freestyle(Render *re, int render)
{
@@ -1964,18 +2141,7 @@ static void add_freestyle(Render *re, int render)
actsrl = BLI_findlink(&re->r.layers, re->r.actlay);
- re->freestyle_bmain = BKE_main_new();
-
- /* We use the same window manager for freestyle bmain as
- * real bmain uses. This is needed because freestyle's
- * bmain could be used to tag scenes for update, which
- * implies call of ED_render_scene_update in some cases
- * and that function requires proper window manager
- * to present (sergey)
- */
- re->freestyle_bmain->wm = re->main->wm;
-
- FRS_init_stroke_rendering(re);
+ FRS_begin_stroke_rendering(re);
for (srl = (SceneRenderLayer *)re->r.layers.first; srl; srl = srl->next) {
if (do_link) {
@@ -1991,7 +2157,7 @@ static void add_freestyle(Render *re, int render)
}
}
- FRS_finish_stroke_rendering(re);
+ FRS_end_stroke_rendering(re);
/* restore the global R value (invalidated by nested execution of the internal renderer) */
R = *re;
@@ -2001,28 +2167,32 @@ static void add_freestyle(Render *re, int render)
static void composite_freestyle_renders(Render *re, int sample)
{
Render *freestyle_render;
+ RenderView *rv;
SceneRenderLayer *srl, *actsrl;
LinkData *link;
actsrl = BLI_findlink(&re->r.layers, re->r.actlay);
link = (LinkData *)re->freestyle_renders.first;
- for (srl= (SceneRenderLayer *)re->r.layers.first; srl; srl= srl->next) {
- if ((re->r.scemode & R_SINGLE_LAYER) && srl != actsrl)
- continue;
- if (FRS_is_freestyle_enabled(srl)) {
- freestyle_render = (Render *)link->data;
+ for (rv = re->result->views.first; rv; rv = rv->next) {
+ for (srl = (SceneRenderLayer *)re->r.layers.first; srl; srl = srl->next) {
+ if ((re->r.scemode & R_SINGLE_LAYER) && srl != actsrl)
+ continue;
- /* may be NULL in case of empty render layer */
- if (freestyle_render) {
- render_result_exr_file_read_sample(freestyle_render, sample);
- FRS_composite_result(re, srl, freestyle_render);
- RE_FreeRenderResult(freestyle_render->result);
- freestyle_render->result = NULL;
+ if (FRS_is_freestyle_enabled(srl)) {
+ freestyle_render = (Render *)link->data;
+
+ /* may be NULL in case of empty render layer */
+ if (freestyle_render) {
+ render_result_exr_file_read_sample(freestyle_render, sample);
+ FRS_composite_result(re, srl, freestyle_render);
+ RE_FreeRenderResult(freestyle_render->result);
+ freestyle_render->result = NULL;
+ }
}
+ link = link->next;
}
- link = link->next;
}
}
@@ -2049,7 +2219,7 @@ static void free_all_freestyle_renders(void)
/* detach the window manager from freestyle bmain (see comments
* in add_freestyle() for more detail)
*/
- re1->freestyle_bmain->wm.first = re1->freestyle_bmain->wm.last = NULL;
+ BLI_listbase_clear(&re1->freestyle_bmain->wm);
BKE_main_free(re1->freestyle_bmain);
re1->freestyle_bmain = NULL;
@@ -2058,11 +2228,14 @@ static void free_all_freestyle_renders(void)
}
#endif
-/* reads all buffers, calls optional composite, merges in first result->rectf */
+/* reads all buffers, calls optional composite, merges in first result->views rectf */
static void do_merge_fullsample(Render *re, bNodeTree *ntree)
{
+ ListBase *rectfs;
+ RenderView *rv;
float *rectf, filt[3][3];
int x, y, sample;
+ int nr, numviews;
/* interaction callbacks */
if (ntree) {
@@ -2077,9 +2250,18 @@ static void do_merge_fullsample(Render *re, bNodeTree *ntree)
/* filtmask needs it */
R = *re;
- /* we accumulate in here */
- rectf = MEM_mapallocN(re->rectx * re->recty * sizeof(float) * 4, "fullsample rgba");
-
+ /* temporary storage of the acccumulation buffers */
+ rectfs = MEM_callocN(sizeof(ListBase), "fullsample accumulation buffers");
+
+ numviews = BLI_listbase_count(&re->result->views);
+ for (nr = 0; nr < numviews; nr++) {
+ rv = MEM_callocN(sizeof(RenderView), "fullsample renderview");
+
+ /* we accumulate in here */
+ rv->rectf = MEM_mapallocN(re->rectx * re->recty * sizeof(float) * 4, "fullsample rgba");
+ BLI_addtail(rectfs, rv);
+ }
+
for (sample = 0; sample < re->r.osa; sample++) {
Scene *sce;
Render *re1;
@@ -2116,54 +2298,70 @@ static void do_merge_fullsample(Render *re, bNodeTree *ntree)
if (ntree) {
ntreeCompositTagRender(re->scene);
ntreeCompositTagAnimated(ntree);
-
- ntreeCompositExecTree(re->scene, ntree, &re->r, true, G.background == 0, &re->scene->view_settings, &re->scene->display_settings);
+
+ for (rv = re->result->views.first; rv; rv = rv->next) {
+ ntreeCompositExecTree(re->scene, ntree, &re->r, true, G.background == 0, &re->scene->view_settings, &re->scene->display_settings, rv->name);
+ }
}
-
- /* ensure we get either composited result or the active layer */
- RE_AcquireResultImage(re, &rres);
-
- /* accumulate with filter, and clip */
- mask = (1 << sample);
- mask_array(mask, filt);
- for (y = 0; y < re->recty; y++) {
- float *rf = rectf + 4 * y * re->rectx;
- float *col = rres.rectf + 4 * y * re->rectx;
-
- for (x = 0; x < re->rectx; x++, rf += 4, col += 4) {
- /* clamping to 1.0 is needed for correct AA */
- if (col[0] < 0.0f) col[0] = 0.0f; else if (col[0] > 1.0f) col[0] = 1.0f;
- if (col[1] < 0.0f) col[1] = 0.0f; else if (col[1] > 1.0f) col[1] = 1.0f;
- if (col[2] < 0.0f) col[2] = 0.0f; else if (col[2] > 1.0f) col[2] = 1.0f;
+ for (nr = 0, rv = rectfs->first; rv; rv = rv->next, nr++) {
+ rectf = rv->rectf;
+
+ /* ensure we get either composited result or the active layer */
+ RE_AcquireResultImage(re, &rres, nr);
+
+ /* accumulate with filter, and clip */
+ mask = (1 << sample);
+ mask_array(mask, filt);
+
+ for (y = 0; y < re->recty; y++) {
+ float *rf = rectf + 4 * y * re->rectx;
+ float *col = rres.rectf + 4 * y * re->rectx;
- add_filt_fmask_coord(filt, col, rf, re->rectx, re->recty, x, y);
+ for (x = 0; x < re->rectx; x++, rf += 4, col += 4) {
+ /* clamping to 1.0 is needed for correct AA */
+ CLAMP(col[0], 0.0f, 1.0f);
+ CLAMP(col[1], 0.0f, 1.0f);
+ CLAMP(col[2], 0.0f, 1.0f);
+
+ add_filt_fmask_coord(filt, col, rf, re->rectx, re->recty, x, y);
+ }
}
- }
- RE_ReleaseResultImage(re);
+ RE_ReleaseResultImage(re);
- /* show stuff */
- if (sample != re->osa - 1) {
- /* weak... the display callback wants an active renderlayer pointer... */
- re->result->renlay = render_get_active_layer(re, re->result);
- re->display_update(re->duh, re->result, NULL);
+ /* show stuff */
+ if (sample != re->osa - 1) {
+ /* weak... the display callback wants an active renderlayer pointer... */
+ re->result->renlay = render_get_active_layer(re, re->result);
+ RE_SetActiveRenderView(re, rv->name);
+ re->display_update(re->duh, re->result, NULL);
+ }
}
-
- if (re->test_break(re->tbh))
- break;
}
- /* clamp alpha and RGB to 0..1 and 0..inf, can go outside due to filter */
- for (y = 0; y < re->recty; y++) {
- float *rf = rectf + 4 * y * re->rectx;
+ for (nr = 0; nr < numviews; nr++) {
+ rectf = ((RenderView *)BLI_findlink(rectfs, nr))->rectf;
+
+ /* clamp alpha and RGB to 0..1 and 0..inf, can go outside due to filter */
+ for (y = 0; y < re->recty; y++) {
+ float *rf = rectf + 4 * y * re->rectx;
- for (x = 0; x < re->rectx; x++, rf += 4) {
- rf[0] = MAX2(rf[0], 0.0f);
- rf[1] = MAX2(rf[1], 0.0f);
- rf[2] = MAX2(rf[2], 0.0f);
- CLAMP(rf[3], 0.0f, 1.0f);
+ for (x = 0; x < re->rectx; x++, rf += 4) {
+ rf[0] = MAX2(rf[0], 0.0f);
+ rf[1] = MAX2(rf[1], 0.0f);
+ rf[2] = MAX2(rf[2], 0.0f);
+ CLAMP(rf[3], 0.0f, 1.0f);
+ }
}
+
+ /* store the final result */
+ BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE);
+ rv = RE_RenderViewGetById(re->result, nr);
+ if (rv->rectf)
+ MEM_freeN(rv->rectf);
+ rv->rectf = rectf;
+ BLI_rw_mutex_unlock(&re->resultmutex);
}
/* clear interaction callbacks */
@@ -2176,12 +2374,14 @@ static void do_merge_fullsample(Render *re, bNodeTree *ntree)
/* disable full sample print */
R.i.curfsa = 0;
-
- BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE);
- if (re->result->rectf)
- MEM_freeN(re->result->rectf);
- re->result->rectf = rectf;
- BLI_rw_mutex_unlock(&re->resultmutex);
+
+ /* garbage collection */
+ while (rectfs->first) {
+ RenderView *rv = rectfs->first;
+ BLI_remlink(rectfs, rv);
+ MEM_freeN(rv);
+ }
+ MEM_freeN(rectfs);
}
/* called externally, via compositor */
@@ -2234,8 +2434,10 @@ void RE_MergeFullSample(Render *re, Main *bmain, Scene *sce, bNodeTree *ntree)
re->display_clear(re->dch, re->result);
#ifdef WITH_FREESTYLE
- if (re->r.mode & R_EDGE_FRS)
+ if (re->r.mode & R_EDGE_FRS) {
+ init_freestyle(re);
add_freestyle(re, 0);
+ }
#endif
do_merge_fullsample(re, ntree);
@@ -2257,7 +2459,11 @@ static void do_render_composite_fields_blur_3d(Render *re)
if (composite_needs_render(re->scene, 1)) {
/* save memory... free all cached images */
ntreeFreeCache(ntree);
-
+
+ /* render the frames
+ * it could be optimized to render only the needed view
+ * but what if a scene has a different number of views
+ * than the main scene? */
do_render_fields_blur_3d(re);
}
else {
@@ -2270,7 +2476,7 @@ static void do_render_composite_fields_blur_3d(Render *re)
if ((re->r.mode & R_CROP) == 0) {
render_result_disprect_to_full_resolution(re);
}
- re->result = render_result_new(re, &re->disprect, 0, RR_USE_MEM, RR_ALL_LAYERS);
+ re->result = render_result_new(re, &re->disprect, 0, RR_USE_MEM, RR_ALL_LAYERS, RR_ALL_VIEWS);
BLI_rw_mutex_unlock(&re->resultmutex);
@@ -2308,6 +2514,8 @@ static void do_render_composite_fields_blur_3d(Render *re)
/* in case it was never initialized */
R.sdh = re->sdh;
R.stats_draw = re->stats_draw;
+ R.i.starttime = re->i.starttime;
+ R.i.cfra = re->i.cfra;
if (update_newframe)
BKE_scene_update_for_newframe(re->eval_ctx, re->main, re->scene, re->lay);
@@ -2315,7 +2523,10 @@ static void do_render_composite_fields_blur_3d(Render *re)
if (re->r.scemode & R_FULL_SAMPLE)
do_merge_fullsample(re, ntree);
else {
- ntreeCompositExecTree(re->scene, ntree, &re->r, true, G.background == 0, &re->scene->view_settings, &re->scene->display_settings);
+ RenderView *rv;
+ for (rv = re->result->views.first; rv; rv = rv->next) {
+ ntreeCompositExecTree(re->scene, ntree, &re->r, true, G.background == 0, &re->scene->view_settings, &re->scene->display_settings, rv->name);
+ }
}
ntree->stats_draw = NULL;
@@ -2340,11 +2551,17 @@ static void do_render_composite_fields_blur_3d(Render *re)
static void renderresult_stampinfo(Render *re)
{
RenderResult rres;
+ RenderView *rv;
+ int nr;
/* this is the basic trick to get the displayed float or char rect from render result */
- RE_AcquireResultImage(re, &rres);
- BKE_stamp_buf(re->scene, RE_GetCamera(re), (unsigned char *)rres.rect32, rres.rectf, rres.rectx, rres.recty, 4);
- RE_ReleaseResultImage(re);
+ nr = 0;
+ for (rv = re->result->views.first;rv;rv = rv->next, nr++) {
+ RE_SetActiveRenderView(re, rv->name);
+ RE_AcquireResultImage(re, &rres, nr);
+ BKE_image_stamp_buf(re->scene, RE_GetCamera(re), (unsigned char *)rres.rect32, rres.rectf, rres.rectx, rres.recty, 4);
+ RE_ReleaseResultImage(re);
+ }
}
int RE_seq_render_active(Scene *scene, RenderData *rd)
@@ -2368,10 +2585,13 @@ int RE_seq_render_active(Scene *scene, RenderData *rd)
static void do_render_seq(Render *re)
{
static int recurs_depth = 0;
- struct ImBuf *ibuf, *out;
+ struct ImBuf *out;
RenderResult *rr; /* don't assign re->result here as it might change during give_ibuf_seq */
int cfra = re->r.cfra;
SeqRenderData context;
+ size_t view_id, tot_views;
+ struct ImBuf **ibuf_arr;
+ int re_x, re_y;
re->i.cfra = cfra;
@@ -2385,48 +2605,82 @@ static void do_render_seq(Render *re)
if ((re->r.mode & R_BORDER) && (re->r.mode & R_CROP) == 0) {
/* if border rendering is used and cropping is disabled, final buffer should
* be as large as the whole frame */
- context = BKE_sequencer_new_render_data(re->eval_ctx, re->main, re->scene,
- re->winx, re->winy, 100);
+ re_x = re->winx;
+ re_y = re->winy;
}
else {
- context = BKE_sequencer_new_render_data(re->eval_ctx, re->main, re->scene,
- re->result->rectx, re->result->recty, 100);
+ re_x = re->result->rectx;
+ re_y = re->result->recty;
}
- out = BKE_sequencer_give_ibuf(&context, cfra, 0);
+ tot_views = BKE_scene_multiview_num_views_get(&re->r);
+ ibuf_arr = MEM_mallocN(sizeof(ImBuf *) * tot_views, "Sequencer Views ImBufs");
- if (out) {
- ibuf = IMB_dupImBuf(out);
- IMB_freeImBuf(out);
- BKE_sequencer_imbuf_from_sequencer_space(re->scene, ibuf);
- }
- else {
- ibuf = NULL;
- }
+ BKE_sequencer_new_render_data(
+ re->eval_ctx, re->main, re->scene,
+ re_x, re_y, 100,
+ &context);
- recurs_depth--;
+ /* the renderresult gets destroyed during the rendering, so we first collect all ibufs
+ * and then we populate the final renderesult */
+
+ for (view_id = 0; view_id < tot_views; view_id++) {
+ context.view_id = view_id;
+ out = BKE_sequencer_give_ibuf(&context, cfra, 0);
+
+ if (out) {
+ ibuf_arr[view_id] = IMB_dupImBuf(out);
+ IMB_metadata_copy(ibuf_arr[view_id], out);
+ IMB_freeImBuf(out);
+ BKE_sequencer_imbuf_from_sequencer_space(re->scene, ibuf_arr[view_id]);
+ }
+ else {
+ ibuf_arr[view_id] = NULL;
+ }
+ }
rr = re->result;
-
+
BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE);
+ render_result_views_new(rr, &re->r);
+ BLI_rw_mutex_unlock(&re->resultmutex);
- if (ibuf) {
- /* copy ibuf into combined pixel rect */
- render_result_rect_from_ibuf(rr, &re->r, ibuf);
-
- if (recurs_depth == 0) { /* with nested scenes, only free on toplevel... */
- Editing *ed = re->scene->ed;
- if (ed)
- BKE_sequencer_free_imbuf(re->scene, &ed->seqbase, true);
+ for (view_id = 0; view_id < tot_views; view_id++) {
+ RenderView *rv = RE_RenderViewGetById(rr, view_id);
+ BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE);
+
+ if (ibuf_arr[view_id]) {
+ /* copy ibuf into combined pixel rect */
+ render_result_rect_from_ibuf(rr, &re->r, ibuf_arr[view_id], view_id);
+
+ if (ibuf_arr[view_id]->metadata && (re->r.stamp & R_STAMP_STRIPMETA)) {
+ /* ensure render stamp info first */
+ BKE_render_result_stamp_info(NULL, NULL, rr, true);
+ BKE_stamp_info_from_imbuf(rr, ibuf_arr[view_id]);
+ }
+
+ if (recurs_depth == 0) { /* with nested scenes, only free on toplevel... */
+ Editing *ed = re->scene->ed;
+ if (ed)
+ BKE_sequencer_free_imbuf(re->scene, &ed->seqbase, true);
+ }
+ IMB_freeImBuf(ibuf_arr[view_id]);
}
- IMB_freeImBuf(ibuf);
- }
- else {
- /* render result is delivered empty in most cases, nevertheless we handle all cases */
- render_result_rect_fill_zero(rr);
+ else {
+ /* render result is delivered empty in most cases, nevertheless we handle all cases */
+ render_result_rect_fill_zero(rr, view_id);
+ }
+
+ BLI_rw_mutex_unlock(&re->resultmutex);
+
+ /* would mark display buffers as invalid */
+ RE_SetActiveRenderView(re, rv->name);
+ re->display_update(re->duh, re->result, NULL);
}
- BLI_rw_mutex_unlock(&re->resultmutex);
+ MEM_freeN(ibuf_arr);
+
+ recurs_depth--;
/* just in case this flag went missing at some point */
re->r.scemode |= R_DOSEQ;
@@ -2436,9 +2690,6 @@ static void do_render_seq(Render *re)
re->progress(re->prh, (float)(cfra - re->r.sfra) / (re->r.efra - re->r.sfra));
else
re->progress(re->prh, 1.0f);
-
- /* would mark display buffers as invalid */
- re->display_update(re->duh, re->result, NULL);
}
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
@@ -2446,6 +2697,9 @@ static void do_render_seq(Render *re)
/* main loop: doing sequence + fields + blur + 3d render + compositing */
static void do_render_all_options(Render *re)
{
+ Object *camera;
+ bool render_seq = false;
+
re->current_scene_update(re->suh, re->scene);
BKE_scene_camera_switch_update(re->scene);
@@ -2460,8 +2714,10 @@ static void do_render_all_options(Render *re)
}
else if (RE_seq_render_active(re->scene, &re->r)) {
/* note: do_render_seq() frees rect32 when sequencer returns float images */
- if (!re->test_break(re->tbh))
+ if (!re->test_break(re->tbh)) {
do_render_seq(re);
+ render_seq = true;
+ }
re->stats_draw(re->sdh, &re->i);
re->display_update(re->duh, re->result, NULL);
@@ -2479,6 +2735,12 @@ static void do_render_all_options(Render *re)
re->stats_draw(re->sdh, &re->i);
+ /* save render result stamp if needed */
+ camera = RE_GetCamera(re);
+ /* sequence rendering should have taken care of that already */
+ if (!(render_seq && (re->r.stamp & R_STAMP_STRIPMETA)))
+ BKE_render_result_stamp_info(re->scene, camera, re->result, false);
+
/* stamp image info here */
if ((re->r.stamp & R_STAMP_ALL) && (re->r.stamp & R_STAMP_DRAW)) {
renderresult_stampinfo(re);
@@ -2525,11 +2787,50 @@ static bool check_valid_compositing_camera(Scene *scene, Object *camera_override
}
}
+static bool check_valid_camera_multiview(Scene *scene, Object *camera, ReportList *reports)
+{
+ SceneRenderView *srv;
+ bool active_view = false;
+
+ if ((scene->r.scemode & R_MULTIVIEW) == 0)
+ return true;
+
+ for (srv = scene->r.views.first; srv; srv = srv->next) {
+ if (BKE_scene_multiview_is_render_view_active(&scene->r, srv)) {
+ active_view = true;
+
+ if (scene->r.views_format == SCE_VIEWS_FORMAT_MULTIVIEW) {
+ Object *view_camera;
+ view_camera = BKE_camera_multiview_render(scene, camera, srv->name);
+
+ if (view_camera == camera) {
+ /* if the suffix is not in the camera, means we are using the fallback camera */
+ if (!BLI_str_endswith(view_camera->id.name + 2, srv->suffix)) {
+ BKE_reportf(reports, RPT_ERROR, "Camera \"%s\" is not a multi-view camera",
+ camera->id.name + 2);
+ return false;
+ }
+ }
+ }
+ }
+ }
+
+ if (!active_view) {
+ BKE_reportf(reports, RPT_ERROR, "No active view found in scene \"%s\"", scene->id.name + 2);
+ return false;
+ }
+
+ return true;
+}
+
static int check_valid_camera(Scene *scene, Object *camera_override, ReportList *reports)
{
if (camera_override == NULL && scene->camera == NULL)
scene->camera = BKE_scene_camera_find(scene);
+ if (!check_valid_camera_multiview(scene, scene->camera, reports))
+ return false;
+
if (RE_seq_render_active(scene, &scene->r)) {
if (scene->ed) {
Sequence *seq = scene->ed->seqbase.first;
@@ -2547,6 +2848,8 @@ static int check_valid_camera(Scene *scene, Object *camera_override, ReportList
}
}
}
+ else if (!check_valid_camera_multiview(seq->scene, seq->scene_camera, reports))
+ return false;
}
seq = seq->next;
@@ -2711,6 +3014,17 @@ static void update_physics_cache(Render *re, Scene *scene, int UNUSED(anim_init)
BKE_ptcache_bake(&baker);
}
+
+void RE_SetActiveRenderView(Render *re, const char *viewname)
+{
+ BLI_strncpy(re->viewname, viewname, sizeof(re->viewname));
+}
+
+const char *RE_GetActiveRenderView(Render *re)
+{
+ return re->viewname;
+}
+
/* evaluating scene options for general Blender render */
static int render_initialize_from_main(Render *re, RenderData *rd, Main *bmain, Scene *scene, SceneRenderLayer *srl,
Object *camera_override, unsigned int lay_override, int anim, int anim_init)
@@ -2746,7 +3060,8 @@ static int render_initialize_from_main(Render *re, RenderData *rd, Main *bmain,
re->lay = lay_override ? lay_override : scene->lay;
re->layer_override = lay_override;
re->i.localview = (re->lay & 0xFF000000) != 0;
-
+ re->viewname[0] = '\0';
+
/* not too nice, but it survives anim-border render */
if (anim) {
render_update_anim_renderdata(re, &scene->r);
@@ -2818,15 +3133,19 @@ void RE_BlenderFrame(Render *re, Main *bmain, Scene *scene, SceneRenderLayer *sr
}
else {
char name[FILE_MAX];
- BKE_makepicstring(name, scene->r.pic, bmain->name, scene->r.cfra,
- &scene->r.im_format, (scene->r.scemode & R_EXTENSION) != 0, false);
+ BKE_image_path_from_imformat(
+ name, scene->r.pic, bmain->name, scene->r.cfra,
+ &scene->r.im_format, (scene->r.scemode & R_EXTENSION) != 0, false, NULL);
/* reports only used for Movie */
- do_write_image_or_movie(re, bmain, scene, NULL, name);
+ do_write_image_or_movie(re, bmain, scene, NULL, 0, name);
}
}
BLI_callback_exec(re->main, (ID *)scene, BLI_CB_EVT_RENDER_POST); /* keep after file save */
+ if (write_still) {
+ BLI_callback_exec(re->main, (ID *)scene, BLI_CB_EVT_RENDER_WRITE);
+ }
}
BLI_callback_exec(re->main, (ID *)scene, G.is_break ? BLI_CB_EVT_RENDER_CANCEL : BLI_CB_EVT_RENDER_COMPLETE);
@@ -2851,111 +3170,287 @@ void RE_RenderFreestyleExternal(Render *re)
if (!re->test_break(re->tbh)) {
RE_Database_FromScene(re, re->main, re->scene, re->lay, 1);
RE_Database_Preprocess(re);
+ init_freestyle(re);
add_freestyle(re, 1);
RE_Database_Free(re);
}
}
#endif
-static int do_write_image_or_movie(Render *re, Main *bmain, Scene *scene, bMovieHandle *mh, const char *name_override)
+bool RE_WriteRenderViewsImage(ReportList *reports, RenderResult *rr, Scene *scene, const bool stamp, char *name)
{
- char name[FILE_MAX];
- RenderResult rres;
- Object *camera = RE_GetCamera(re);
- double render_time;
- int ok = 1;
-
- RE_AcquireResultImage(re, &rres);
+ bool is_mono;
+ bool ok = true;
+ RenderData *rd = &scene->r;
- /* write movie or image */
- if (BKE_imtype_is_movie(scene->r.im_format.imtype)) {
- bool do_free = false;
- ImBuf *ibuf = render_result_rect_to_ibuf(&rres, &scene->r);
+ if (!rr)
+ return false;
- /* note; the way it gets 32 bits rects is weak... */
- if (ibuf->rect == NULL) {
- ibuf->rect = MEM_mapallocN(sizeof(int) * rres.rectx * rres.recty, "temp 32 bits rect");
- ibuf->mall |= IB_rect;
- RE_AcquiredResultGet32(re, &rres, ibuf->rect);
- do_free = true;
- }
+ is_mono = BLI_listbase_count_ex(&rr->views, 2) < 2;
+ if (ELEM(rd->im_format.imtype, R_IMF_IMTYPE_OPENEXR, R_IMF_IMTYPE_MULTILAYER) &&
+ rd->im_format.views_format == R_IMF_VIEWS_MULTIVIEW)
+ {
+ RE_WriteRenderResult(reports, rr, name, &rd->im_format, true, NULL);
+ printf("Saved: %s\n", name);
+ }
- IMB_colormanagement_imbuf_for_write(ibuf, true, false, &scene->view_settings,
- &scene->display_settings, &scene->r.im_format);
+ /* mono, legacy code */
+ else if (is_mono || (rd->im_format.views_format == R_IMF_VIEWS_INDIVIDUAL))
+ {
+ RenderView *rv;
+ size_t view_id;
+ char filepath[FILE_MAX];
- ok = mh->append_movie(&re->r, scene->r.sfra, scene->r.cfra, (int *) ibuf->rect,
- ibuf->x, ibuf->y, re->reports);
- if (do_free) {
- MEM_freeN(ibuf->rect);
- ibuf->rect = NULL;
- ibuf->mall &= ~IB_rect;
- }
+ BLI_strncpy(filepath, name, sizeof(filepath));
- /* imbuf knows which rects are not part of ibuf */
- IMB_freeImBuf(ibuf);
+ for (view_id = 0, rv = rr->views.first; rv; rv = rv->next, view_id++) {
+ if (!is_mono) {
+ BKE_scene_multiview_view_filepath_get(&scene->r, filepath, rv->name, name);
+ }
- printf("Append frame %d", scene->r.cfra);
- }
- else {
- if (name_override)
- BLI_strncpy(name, name_override, sizeof(name));
- else
- BKE_makepicstring(name, scene->r.pic, bmain->name, scene->r.cfra,
- &scene->r.im_format, (scene->r.scemode & R_EXTENSION) != 0, true);
-
- if (re->r.im_format.imtype == R_IMF_IMTYPE_MULTILAYER) {
- if (re->result) {
- RE_WriteRenderResult(re->reports, re->result, name, scene->r.im_format.exr_codec);
- printf("Saved: %s", name);
+ if (rd->im_format.imtype == R_IMF_IMTYPE_MULTILAYER) {
+ RE_WriteRenderResult(reports, rr, name, &rd->im_format, false, rv->name);
+ printf("Saved: %s\n", name);
+ }
+ else {
+ ImBuf *ibuf = render_result_rect_to_ibuf(rr, rd, view_id);
+
+ IMB_colormanagement_imbuf_for_write(ibuf, true, false, &scene->view_settings,
+ &scene->display_settings, &rd->im_format);
+
+ if (stamp) {
+ /* writes the name of the individual cameras */
+ ok = BKE_imbuf_write_stamp(scene, rr, ibuf, name, &rd->im_format);
+ }
+ else {
+ ok = BKE_imbuf_write(ibuf, name, &rd->im_format);
+ }
+
+ if (ok == false) {
+ printf("Render error: cannot save %s\n", name);
+ }
+ else printf("Saved: %s\n", name);
+
+ /* optional preview images for exr */
+ if (ok && rd->im_format.imtype == R_IMF_IMTYPE_OPENEXR && (rd->im_format.flag & R_IMF_FLAG_PREVIEW_JPG)) {
+ ImageFormatData imf = rd->im_format;
+ imf.imtype = R_IMF_IMTYPE_JPEG90;
+
+ if (BLI_testextensie(name, ".exr"))
+ name[strlen(name) - 4] = 0;
+ BKE_image_path_ensure_ext_from_imformat(name, &imf);
+ ibuf->planes = 24;
+
+ IMB_colormanagement_imbuf_for_write(ibuf, true, false, &scene->view_settings,
+ &scene->display_settings, &imf);
+
+ if (stamp) {
+ /* writes the name of the individual cameras */
+ ok = BKE_imbuf_write_stamp(scene, rr, ibuf, name, &imf);
+ }
+ else {
+ ok = BKE_imbuf_write(ibuf, name, &imf);
+ }
+ printf("Saved: %s\n", name);
+ }
+
+ /* imbuf knows which rects are not part of ibuf */
+ IMB_freeImBuf(ibuf);
}
}
+ }
+ else { /* R_IMF_VIEWS_STEREO_3D */
+ BLI_assert(scene->r.im_format.views_format == R_IMF_VIEWS_STEREO_3D);
+
+ if (rd->im_format.imtype == R_IMF_IMTYPE_MULTILAYER) {
+ printf("Stereo 3D not support for MultiLayer image: %s\n", name);
+ }
else {
- ImBuf *ibuf = render_result_rect_to_ibuf(&rres, &scene->r);
+ ImBuf *ibuf_arr[3] = {NULL};
+ const char *names[2] = {STEREO_LEFT_NAME, STEREO_RIGHT_NAME};
+ int i;
+
+ for (i = 0; i < 2; i++) {
+ int view_id = BLI_findstringindex(&rr->views, names[i], offsetof(RenderView, name));
+ ibuf_arr[i] = render_result_rect_to_ibuf(rr, rd, view_id);
+ IMB_colormanagement_imbuf_for_write(ibuf_arr[i], true, false, &scene->view_settings,
+ &scene->display_settings, &scene->r.im_format);
+ IMB_prepare_write_ImBuf(IMB_isfloat(ibuf_arr[i]), ibuf_arr[i]);
+ }
- IMB_colormanagement_imbuf_for_write(ibuf, true, false, &scene->view_settings,
- &scene->display_settings, &scene->r.im_format);
+ ibuf_arr[2] = IMB_stereo3d_ImBuf(&scene->r.im_format, ibuf_arr[0], ibuf_arr[1]);
- ok = BKE_imbuf_write_stamp(scene, camera, ibuf, name, &scene->r.im_format);
-
- if (ok == 0) {
+ if (stamp)
+ ok = BKE_imbuf_write_stamp(scene, rr, ibuf_arr[2], name, &rd->im_format);
+ else
+ ok = BKE_imbuf_write(ibuf_arr[2], name, &rd->im_format);
+
+ if (ok == false)
printf("Render error: cannot save %s\n", name);
- }
- else printf("Saved: %s", name);
-
+ else
+ printf("Saved: %s\n", name);
+
/* optional preview images for exr */
- if (ok && scene->r.im_format.imtype == R_IMF_IMTYPE_OPENEXR && (scene->r.im_format.flag & R_IMF_FLAG_PREVIEW_JPG)) {
- ImageFormatData imf = scene->r.im_format;
+ if (ok && rd->im_format.imtype == R_IMF_IMTYPE_OPENEXR &&
+ (rd->im_format.flag & R_IMF_FLAG_PREVIEW_JPG))
+ {
+ ImageFormatData imf = rd->im_format;
imf.imtype = R_IMF_IMTYPE_JPEG90;
if (BLI_testextensie(name, ".exr"))
name[strlen(name) - 4] = 0;
- BKE_add_image_extension(name, &imf);
- ibuf->planes = 24;
- IMB_colormanagement_imbuf_for_write(ibuf, true, false, &scene->view_settings,
+ BKE_image_path_ensure_ext_from_imformat(name, &imf);
+ ibuf_arr[2]->planes = 24;
+
+ IMB_colormanagement_imbuf_for_write(ibuf_arr[2], true, false, &scene->view_settings,
&scene->display_settings, &imf);
- BKE_imbuf_write_stamp(scene, camera, ibuf, name, &imf);
- printf("\nSaved: %s", name);
+ if (stamp)
+ ok = BKE_imbuf_write_stamp(scene, rr, ibuf_arr[2], name, &rd->im_format);
+ else
+ ok = BKE_imbuf_write(ibuf_arr[2], name, &imf);
+
+ printf("Saved: %s\n", name);
}
-
+
+ /* imbuf knows which rects are not part of ibuf */
+ for (i = 0; i < 3; i++) {
+ IMB_freeImBuf(ibuf_arr[i]);
+ }
+ }
+ }
+
+ return ok;
+}
+
+bool RE_WriteRenderViewsMovie(ReportList *reports, RenderResult *rr, Scene *scene, RenderData *rd, bMovieHandle *mh,
+ const size_t width, const size_t height, void **movie_ctx_arr, const size_t totvideos, bool preview)
+{
+ bool is_mono;
+ bool ok = true;
+
+ if (!rr)
+ return false;
+
+ is_mono = BLI_listbase_count_ex(&rr->views, 2) < 2;
+
+ if (is_mono || (scene->r.im_format.views_format == R_IMF_VIEWS_INDIVIDUAL)) {
+ size_t view_id;
+ for (view_id = 0; view_id < totvideos; view_id++) {
+ bool do_free = false;
+ const char *suffix = BKE_scene_multiview_view_id_suffix_get(&scene->r, view_id);
+ ImBuf *ibuf = render_result_rect_to_ibuf(rr, &scene->r, view_id);
+
+ /* note; the way it gets 32 bits rects is weak... */
+ if (ibuf->rect == NULL) {
+ ibuf->rect = MEM_mapallocN(sizeof(int) * rr->rectx * rr->recty, "temp 32 bits rect");
+ ibuf->mall |= IB_rect;
+ render_result_rect_get_pixels(rr, ibuf->rect, width, height, &scene->view_settings, &scene->display_settings, view_id);
+ do_free = true;
+ }
+
+ IMB_colormanagement_imbuf_for_write(ibuf, true, false, &scene->view_settings,
+ &scene->display_settings, &scene->r.im_format);
+
+ ok &= mh->append_movie(movie_ctx_arr[view_id], rd, preview ? scene->r.psfra : scene->r.sfra, scene->r.cfra,
+ (int *) ibuf->rect, ibuf->x, ibuf->y, suffix, reports);
+
+ if (do_free) {
+ MEM_freeN(ibuf->rect);
+ ibuf->rect = NULL;
+ ibuf->mall &= ~IB_rect;
+ }
+
/* imbuf knows which rects are not part of ibuf */
IMB_freeImBuf(ibuf);
}
+ printf("Append frame %d\n", scene->r.cfra);
+ }
+ else { /* R_IMF_VIEWS_STEREO_3D */
+ const char *names[2] = {STEREO_LEFT_NAME, STEREO_RIGHT_NAME};
+ ImBuf *ibuf_arr[3] = {NULL};
+ bool do_free[2] = {false, false};
+ size_t i;
+
+ BLI_assert((totvideos == 1) && (scene->r.im_format.views_format == R_IMF_VIEWS_STEREO_3D));
+
+ for (i = 0; i < 2; i++) {
+ int view_id = BLI_findstringindex(&rr->views, names[i], offsetof(RenderView, name));
+ ibuf_arr[i] = render_result_rect_to_ibuf(rr, &scene->r, view_id);
+
+ /* note; the way it gets 32 bits rects is weak... */
+ if (ibuf_arr[i]->rect == NULL) {
+ ibuf_arr[i]->rect = MEM_mapallocN(sizeof(int) * width * height, "temp 32 bits rect");
+ ibuf_arr[i]->mall |= IB_rect;
+ render_result_rect_get_pixels(rr, ibuf_arr[i]->rect, width, height, &scene->view_settings, &scene->display_settings, view_id);
+ do_free[i] = true;
+ }
+
+ IMB_colormanagement_imbuf_for_write(ibuf_arr[i], true, false, &scene->view_settings,
+ &scene->display_settings, &scene->r.im_format);
+ }
+
+ ibuf_arr[2] = IMB_stereo3d_ImBuf(&scene->r.im_format, ibuf_arr[0], ibuf_arr[1]);
+
+ ok = mh->append_movie(movie_ctx_arr[0], rd, preview ? scene->r.psfra : scene->r.sfra, scene->r.cfra, (int *) ibuf_arr[2]->rect,
+ ibuf_arr[2]->x, ibuf_arr[2]->y, "", reports);
+
+ for (i = 0; i < 2; i++) {
+ if (do_free[i]) {
+ MEM_freeN(ibuf_arr[i]->rect);
+ ibuf_arr[i]->rect = NULL;
+ ibuf_arr[i]->mall &= ~IB_rect;
+ }
+
+ /* imbuf knows which rects are not part of ibuf */
+ IMB_freeImBuf(ibuf_arr[i]);
+ }
+ }
+
+ return ok;
+}
+
+static int do_write_image_or_movie(Render *re, Main *bmain, Scene *scene, bMovieHandle *mh, const size_t totvideos, const char *name_override)
+{
+ char name[FILE_MAX];
+ RenderResult rres;
+ double render_time;
+ bool ok = true;
+
+ RE_AcquireResultImageViews(re, &rres);
+
+ /* write movie or image */
+ if (BKE_imtype_is_movie(scene->r.im_format.imtype)) {
+ RE_WriteRenderViewsMovie(re->reports, &rres, scene, &re->r, mh, re->rectx, re->recty, re->movie_ctx_arr, totvideos, false);
+ }
+ else {
+ if (name_override)
+ BLI_strncpy(name, name_override, sizeof(name));
+ else
+ BKE_image_path_from_imformat(
+ name, scene->r.pic, bmain->name, scene->r.cfra,
+ &scene->r.im_format, (scene->r.scemode & R_EXTENSION) != 0, true, NULL);
+
+ /* write images as individual images or stereo */
+ ok = RE_WriteRenderViewsImage(re->reports, &rres, scene, true, name);
}
- RE_ReleaseResultImage(re);
+ RE_ReleaseResultImageViews(re, &rres);
render_time = re->i.lastframetime;
re->i.lastframetime = PIL_check_seconds_timer() - re->i.starttime;
- BLI_timestr(re->i.lastframetime, name, sizeof(name));
+ BLI_timecode_string_from_time_simple(name, sizeof(name), re->i.lastframetime);
printf(" Time: %s", name);
-
+
+ /* Flush stdout to be sure python callbacks are printing stuff after blender. */
+ fflush(stdout);
+
BLI_callback_exec(G.main, NULL, BLI_CB_EVT_RENDER_STATS);
- BLI_timestr(re->i.lastframetime - render_time, name, sizeof(name));
+ BLI_timecode_string_from_time_simple(name, sizeof(name), re->i.lastframetime - render_time);
printf(" (Saving: %s)\n", name);
fputc('\n', stdout);
@@ -2964,20 +3459,51 @@ static int do_write_image_or_movie(Render *re, Main *bmain, Scene *scene, bMovie
return ok;
}
+static void get_videos_dimensions(Render *re, RenderData *rd, size_t *r_width, size_t *r_height)
+{
+ size_t width, height;
+ if (re->r.mode & R_BORDER) {
+ if ((re->r.mode & R_CROP) == 0) {
+ width = re->winx;
+ height = re->winy;
+ }
+ else {
+ width = re->rectx;
+ height = re->recty;
+ }
+ }
+ else {
+ width = re->rectx;
+ height = re->recty;
+ }
+
+ BKE_scene_multiview_videos_dimensions_get(rd, width, height, r_width, r_height);
+}
+
/* saves images to disk */
void RE_BlenderAnim(Render *re, Main *bmain, Scene *scene, Object *camera_override,
unsigned int lay_override, int sfra, int efra, int tfra)
{
RenderData rd = scene->r;
- bMovieHandle *mh = BKE_movie_handle_get(scene->r.im_format.imtype);
+ bMovieHandle *mh = NULL;
int cfrao = scene->r.cfra;
int nfra, totrendered = 0, totskipped = 0;
-
+ const size_t totvideos = BKE_scene_multiview_num_videos_get(&rd);
+ const bool is_movie = BKE_imtype_is_movie(scene->r.im_format.imtype);
+ const bool is_multiview_name = ((scene->r.scemode & R_MULTIVIEW) != 0 &&
+ (scene->r.im_format.views_format == R_IMF_VIEWS_INDIVIDUAL));
+
BLI_callback_exec(re->main, (ID *)scene, BLI_CB_EVT_RENDER_INIT);
/* do not fully call for each frame, it initializes & pops output window */
if (!render_initialize_from_main(re, &rd, bmain, scene, NULL, camera_override, lay_override, 0, 1))
return;
+
+ /* we don't support Frame Server and streaming of individual views */
+ if ((rd.im_format.imtype == R_IMF_IMTYPE_FRAMESERVER) && (totvideos > 1)) {
+ BKE_report(re->reports, RPT_ERROR, "Frame Server only support stereo output for multiview rendering");
+ return;
+ }
/* ugly global still... is to prevent renderwin events and signal subsurfs etc to make full resol */
/* is also set by caller renderwin.c */
@@ -2985,30 +3511,38 @@ void RE_BlenderAnim(Render *re, Main *bmain, Scene *scene, Object *camera_overri
re->flag |= R_ANIMATION;
- if (BKE_imtype_is_movie(scene->r.im_format.imtype)) {
- int width, height;
- if (re->r.mode & R_BORDER) {
- if ((re->r.mode & R_CROP) == 0) {
- width = re->winx;
- height = re->winy;
- }
- else {
- width = re->rectx;
- height = re->recty;
- }
- }
- else {
- width = re->rectx;
- height = re->recty;
+ if (is_movie) {
+ size_t i, width, height;
+
+ get_videos_dimensions(re, &rd, &width, &height);
+
+ mh = BKE_movie_handle_get(scene->r.im_format.imtype);
+ if (mh == NULL) {
+ BKE_report(re->reports, RPT_ERROR, "Movie format unsupported");
+ return;
}
- if (!mh->start_movie(scene, &re->r, width, height, re->reports))
- G.is_break = true;
+ re->movie_ctx_arr = MEM_mallocN(sizeof(void *) * totvideos, "Movies' Context");
+
+ for (i = 0; i < totvideos; i++) {
+ const char *suffix = BKE_scene_multiview_view_id_suffix_get(&re->r, i);
+
+ re->movie_ctx_arr[i] = mh->context_create();
+
+ if (!mh->start_movie(re->movie_ctx_arr[i], scene, &re->r, width, height, re->reports, false, suffix))
+ G.is_break = true;
+ }
}
- if (mh->get_next_frame) {
+ if (mh && mh->get_next_frame) {
+ /* MULTIVIEW_TODO:
+ * in case a new video format is added that implements get_next_frame multiview has to be addressed
+ * or the error throwing for R_IMF_IMTYPE_FRAMESERVER has to be extended for those cases as well
+ */
+ BLI_assert(totvideos < 2);
+
while (!(G.is_break == 1)) {
- int nf = mh->get_next_frame(&re->r, re->reports);
+ int nf = mh->get_next_frame(re->movie_ctx_arr[0], &re->r, re->reports);
if (nf >= 0 && nf >= scene->r.sfra && nf <= scene->r.efra) {
scene->r.cfra = re->r.cfra = nf;
@@ -3018,12 +3552,13 @@ void RE_BlenderAnim(Render *re, Main *bmain, Scene *scene, Object *camera_overri
totrendered++;
if (re->test_break(re->tbh) == 0) {
- if (!do_write_image_or_movie(re, bmain, scene, mh, NULL))
+ if (!do_write_image_or_movie(re, bmain, scene, mh, totvideos, NULL))
G.is_break = true;
}
if (G.is_break == false) {
BLI_callback_exec(re->main, (ID *)scene, BLI_CB_EVT_RENDER_POST); /* keep after file save */
+ BLI_callback_exec(re->main, (ID *)scene, BLI_CB_EVT_RENDER_WRITE);
}
}
else {
@@ -3060,19 +3595,67 @@ void RE_BlenderAnim(Render *re, Main *bmain, Scene *scene, Object *camera_overri
nfra += tfra;
/* Touch/NoOverwrite options are only valid for image's */
- if (BKE_imtype_is_movie(scene->r.im_format.imtype) == 0) {
+ if (is_movie == false) {
if (scene->r.mode & (R_NO_OVERWRITE | R_TOUCH))
- BKE_makepicstring(name, scene->r.pic, bmain->name, scene->r.cfra,
- &scene->r.im_format, (scene->r.scemode & R_EXTENSION) != 0, true);
+ BKE_image_path_from_imformat(
+ name, scene->r.pic, bmain->name, scene->r.cfra,
+ &scene->r.im_format, (scene->r.scemode & R_EXTENSION) != 0, true, NULL);
+
+ if (scene->r.mode & R_NO_OVERWRITE) {
+ if (!is_multiview_name) {
+ if (BLI_exists(name)) {
+ printf("skipping existing frame \"%s\"\n", name);
+ totskipped++;
+ continue;
+ }
+ }
+ else {
+ SceneRenderView *srv;
+ bool is_skip = false;
+ char filepath[FILE_MAX];
- if (scene->r.mode & R_NO_OVERWRITE && BLI_exists(name)) {
- printf("skipping existing frame \"%s\"\n", name);
- totskipped++;
- continue;
+ for (srv = scene->r.views.first; srv; srv = srv->next) {
+ if (!BKE_scene_multiview_is_render_view_active(&scene->r, srv))
+ continue;
+
+ BKE_scene_multiview_filepath_get(srv, name, filepath);
+
+ if (BLI_exists(filepath)) {
+ is_skip = true;
+ printf("skipping existing frame \"%s\" for view \"%s\"\n", filepath, srv->name);
+ }
+ }
+
+ if (is_skip) {
+ totskipped++;
+ continue;
+ }
+ }
}
- if (scene->r.mode & R_TOUCH && !BLI_exists(name)) {
- BLI_make_existing_file(name); /* makes the dir if its not there */
- BLI_file_touch(name);
+
+ if (scene->r.mode & R_TOUCH) {
+ if (!is_multiview_name) {
+ if (!BLI_exists(name)) {
+ BLI_make_existing_file(name); /* makes the dir if its not there */
+ BLI_file_touch(name);
+ }
+ }
+ else {
+ SceneRenderView *srv;
+ char filepath[FILE_MAX];
+
+ for (srv = scene->r.views.first; srv; srv = srv->next) {
+ if (!BKE_scene_multiview_is_render_view_active(&scene->r, srv))
+ continue;
+
+ BKE_scene_multiview_filepath_get(srv, name, filepath);
+
+ if (!BLI_exists(filepath)) {
+ BLI_make_existing_file(filepath); /* makes the dir if its not there */
+ BLI_file_touch(filepath);
+ }
+ }
+ }
}
}
@@ -3087,7 +3670,7 @@ void RE_BlenderAnim(Render *re, Main *bmain, Scene *scene, Object *camera_overri
if (re->test_break(re->tbh) == 0) {
if (!G.is_break)
- if (!do_write_image_or_movie(re, bmain, scene, mh, NULL))
+ if (!do_write_image_or_movie(re, bmain, scene, mh, totvideos, NULL))
G.is_break = true;
}
else
@@ -3095,9 +3678,30 @@ void RE_BlenderAnim(Render *re, Main *bmain, Scene *scene, Object *camera_overri
if (G.is_break == true) {
/* remove touched file */
- if (BKE_imtype_is_movie(scene->r.im_format.imtype) == 0) {
- if (scene->r.mode & R_TOUCH && BLI_exists(name) && BLI_file_size(name) == 0) {
- BLI_delete(name, false, false);
+ if (is_movie == false) {
+ if ((scene->r.mode & R_TOUCH)) {
+ if (!is_multiview_name) {
+ if ((BLI_file_size(name) == 0)) {
+ /* BLI_exists(name) is implicit */
+ BLI_delete(name, false, false);
+ }
+ }
+ else {
+ SceneRenderView *srv;
+ char filepath[FILE_MAX];
+
+ for (srv = scene->r.views.first; srv; srv = srv->next) {
+ if (!BKE_scene_multiview_is_render_view_active(&scene->r, srv))
+ continue;
+
+ BKE_scene_multiview_filepath_get(srv, name, filepath);
+
+ if ((BLI_file_size(filepath) == 0)) {
+ /* BLI_exists(filepath) is implicit */
+ BLI_delete(filepath, false, false);
+ }
+ }
+ }
}
}
@@ -3106,13 +3710,23 @@ void RE_BlenderAnim(Render *re, Main *bmain, Scene *scene, Object *camera_overri
if (G.is_break == false) {
BLI_callback_exec(re->main, (ID *)scene, BLI_CB_EVT_RENDER_POST); /* keep after file save */
+ BLI_callback_exec(re->main, (ID *)scene, BLI_CB_EVT_RENDER_WRITE);
}
}
}
/* end movie */
- if (BKE_imtype_is_movie(scene->r.im_format.imtype))
- mh->end_movie();
+ if (is_movie) {
+ size_t i;
+ for (i = 0; i < totvideos; i++) {
+ mh->end_movie(re->movie_ctx_arr[i]);
+ mh->context_free(re->movie_ctx_arr[i]);
+ }
+
+ if (re->movie_ctx_arr) {
+ MEM_freeN(re->movie_ctx_arr);
+ }
+ }
if (totskipped && totrendered == 0)
BKE_report(re->reports, RPT_INFO, "No frames rendered, skipped to not overwrite");
@@ -3210,13 +3824,22 @@ void RE_layer_load_from_file(RenderLayer *layer, ReportList *reports, const char
{
/* OCIO_TODO: assume layer was saved in defaule color space */
ImBuf *ibuf = IMB_loadiffname(filename, IB_rect, NULL);
+ RenderPass *rpass = NULL;
+
+ /* multiview: since the API takes no 'view', we use the first combined pass found */
+ for (rpass = layer->passes.first; rpass; rpass = rpass->next)
+ if (rpass->passtype == SCE_PASS_COMBINED)
+ break;
+
+ if (rpass == NULL)
+ BKE_reportf(reports, RPT_ERROR, "%s: no Combined pass found in the render layer '%s'", __func__, filename);
if (ibuf && (ibuf->rect || ibuf->rect_float)) {
if (ibuf->x == layer->rectx && ibuf->y == layer->recty) {
if (ibuf->rect_float == NULL)
IMB_float_from_rect(ibuf);
- memcpy(layer->rectf, ibuf->rect_float, sizeof(float) * 4 * layer->rectx * layer->recty);
+ memcpy(rpass->rect, ibuf->rect_float, sizeof(float) * 4 * layer->rectx * layer->recty);
}
else {
if ((ibuf->x - x >= layer->rectx) && (ibuf->y - y >= layer->recty)) {
@@ -3229,29 +3852,29 @@ void RE_layer_load_from_file(RenderLayer *layer, ReportList *reports, const char
if (ibuf_clip) {
IMB_rectcpy(ibuf_clip, ibuf, 0, 0, x, y, layer->rectx, layer->recty);
- memcpy(layer->rectf, ibuf_clip->rect_float, sizeof(float) * 4 * layer->rectx * layer->recty);
+ memcpy(rpass->rect, ibuf_clip->rect_float, sizeof(float) * 4 * layer->rectx * layer->recty);
IMB_freeImBuf(ibuf_clip);
}
else {
- BKE_reportf(reports, RPT_ERROR, "RE_result_rect_from_file: failed to allocate clip buffer '%s'", filename);
+ BKE_reportf(reports, RPT_ERROR, "%s: failed to allocate clip buffer '%s'", __func__, filename);
}
}
else {
- BKE_reportf(reports, RPT_ERROR, "RE_result_rect_from_file: incorrect dimensions for partial copy '%s'", filename);
+ BKE_reportf(reports, RPT_ERROR, "%s: incorrect dimensions for partial copy '%s'", __func__, filename);
}
}
IMB_freeImBuf(ibuf);
}
else {
- BKE_reportf(reports, RPT_ERROR, "RE_result_rect_from_file: failed to load '%s'", filename);
+ BKE_reportf(reports, RPT_ERROR, "%s: failed to load '%s'", __func__, filename);
}
}
void RE_result_load_from_file(RenderResult *result, ReportList *reports, const char *filename)
{
if (!render_result_exr_file_read_path(result, NULL, filename)) {
- BKE_reportf(reports, RPT_ERROR, "RE_result_rect_from_file: failed to load '%s'", filename);
+ BKE_reportf(reports, RPT_ERROR, "%s: failed to load '%s'", __func__, filename);
return;
}
}
@@ -3317,3 +3940,35 @@ bool RE_WriteEnvmapResult(struct ReportList *reports, Scene *scene, EnvMap *env,
}
}
+/* used in the interface to decide whether to show layers */
+bool RE_layers_have_name(struct RenderResult *rr)
+{
+ switch (BLI_listbase_count_ex(&rr->layers, 2)) {
+ case 0:
+ return false;
+ break;
+ case 1:
+ return (((RenderLayer *)rr->layers.first)->name[0] != '\0');
+ break;
+ default:
+ return true;
+ break;
+ }
+ return false;
+}
+
+RenderPass *RE_pass_find_by_type(volatile RenderLayer *rl, int passtype, const char *viewname)
+{
+ RenderPass *rp = NULL;
+
+ for (rp = rl->passes.last; rp; rp = rp->prev) {
+ if (rp->passtype == passtype) {
+
+ if (viewname == NULL || viewname[0] == '\0')
+ break;
+ else if (STREQ(rp->view, viewname))
+ break;
+ }
+ }
+ return rp;
+}
diff --git a/source/blender/render/intern/source/pixelblending.c b/source/blender/render/intern/source/pixelblending.c
index 460a6814f07..32fb196e1f3 100644
--- a/source/blender/render/intern/source/pixelblending.c
+++ b/source/blender/render/intern/source/pixelblending.c
@@ -38,7 +38,6 @@
/* own includes */
#include "render_types.h"
-#include "renderpipeline.h"
#include "pixelblending.h"
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
diff --git a/source/blender/render/intern/source/pixelshading.c b/source/blender/render/intern/source/pixelshading.c
index 014df802a78..104cde0a0b5 100644
--- a/source/blender/render/intern/source/pixelshading.c
+++ b/source/blender/render/intern/source/pixelshading.c
@@ -36,8 +36,6 @@
#include "BLI_utildefines.h"
/* External modules: */
-#include "IMB_imbuf_types.h"
-#include "IMB_imbuf.h"
#include "DNA_group_types.h"
#include "DNA_material_types.h"
@@ -51,14 +49,11 @@
/* own module */
#include "render_types.h"
-#include "renderpipeline.h"
#include "renderdatabase.h"
#include "texture.h"
-#include "pixelblending.h"
#include "rendercore.h"
#include "shadbuf.h"
#include "pixelshading.h"
-#include "shading.h"
#include "sunsky.h"
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
@@ -160,7 +155,7 @@ static void render_lighting_halo(HaloRen *har, float col_r[3])
x = max_ff(fabsf(lvrot[0]/lvrot[2]), fabsf(lvrot[1]/lvrot[2]));
/* 1.0/(sqrt(1+x*x)) is equivalent to cos(atan(x)) */
- inpr = 1.0 / (sqrtf(1.0f + x * x));
+ inpr = 1.0f / (sqrtf(1.0f + x * x));
}
else inpr= 0.0;
}
@@ -206,7 +201,7 @@ static void render_lighting_halo(HaloRen *har, float col_r[3])
/* dot product and reflectivity*/
- inp = 1.0 - fabsf(dot_v3v3(vn, lv));
+ inp = 1.0f - fabsf(dot_v3v3(vn, lv));
/* inp= cos(0.5*M_PI-acos(inp)); */
@@ -366,7 +361,7 @@ int shadeHaloFloat(HaloRen *har, float col[4], int zz,
else dist= dist/har->radsq;
if (har->type & HA_FLARECIRC) {
- dist = 0.5 + fabsf(dist - 0.5f);
+ dist = 0.5f + fabsf(dist - 0.5f);
}
if (har->hard>=30) {
diff --git a/source/blender/render/intern/source/pointdensity.c b/source/blender/render/intern/source/pointdensity.c
index ac2e85a33b3..b8d8cc37ae3 100644
--- a/source/blender/render/intern/source/pointdensity.c
+++ b/source/blender/render/intern/source/pointdensity.c
@@ -1,4 +1,4 @@
-/*
+/*
* ***** BEGIN GPL LICENSE BLOCK *****
*
* This program is free software; you can redistribute it and/or
@@ -40,11 +40,12 @@
#include "BLI_kdopbvh.h"
#include "BLI_utildefines.h"
-#include "BLF_translation.h"
+#include "BLT_translation.h"
#include "BKE_DerivedMesh.h"
#include "BKE_lattice.h"
#include "BKE_main.h"
+#include "BKE_object.h"
#include "BKE_particle.h"
#include "BKE_scene.h"
#include "BKE_texture.h"
@@ -55,39 +56,50 @@
#include "DNA_particle_types.h"
#include "render_types.h"
-#include "renderdatabase.h"
#include "texture.h"
#include "pointdensity.h"
+#include "RE_render_ext.h"
+
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
/* defined in pipeline.c, is hardcopy of active dynamic allocated Render */
/* only to be used here in this file, it's for speed */
extern struct Render R;
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
+static ThreadMutex sample_mutex = PTHREAD_MUTEX_INITIALIZER;
static int point_data_used(PointDensity *pd)
{
int pd_bitflag = 0;
-
+
if (pd->source == TEX_PD_PSYS) {
- if ((pd->noise_influence == TEX_PD_NOISE_VEL) || (pd->falloff_type == TEX_PD_FALLOFF_PARTICLE_VEL) || (pd->color_source == TEX_PD_COLOR_PARTVEL) || (pd->color_source == TEX_PD_COLOR_PARTSPEED))
+ if ((pd->noise_influence == TEX_PD_NOISE_VEL) ||
+ (pd->falloff_type == TEX_PD_FALLOFF_PARTICLE_VEL) ||
+ (pd->color_source == TEX_PD_COLOR_PARTVEL) ||
+ (pd->color_source == TEX_PD_COLOR_PARTSPEED))
+ {
pd_bitflag |= POINT_DATA_VEL;
- if ((pd->noise_influence == TEX_PD_NOISE_AGE) || (pd->color_source == TEX_PD_COLOR_PARTAGE) || (pd->falloff_type == TEX_PD_FALLOFF_PARTICLE_AGE))
+ }
+ if ((pd->noise_influence == TEX_PD_NOISE_AGE) ||
+ (pd->color_source == TEX_PD_COLOR_PARTAGE) ||
+ (pd->falloff_type == TEX_PD_FALLOFF_PARTICLE_AGE))
+ {
pd_bitflag |= POINT_DATA_LIFE;
+ }
}
-
+
return pd_bitflag;
}
-/* additional data stored alongside the point density BVH,
- * accessible by point index number to retrieve other information
+/* additional data stored alongside the point density BVH,
+ * accessible by point index number to retrieve other information
* such as particle velocity or lifetime */
static void alloc_point_data(PointDensity *pd, int total_particles, int point_data_used)
{
int data_size = 0;
-
+
if (point_data_used & POINT_DATA_VEL) {
/* store 3 channels of velocity data */
data_size += 3;
@@ -97,60 +109,70 @@ static void alloc_point_data(PointDensity *pd, int total_particles, int point_da
data_size += 1;
}
- if (data_size)
- pd->point_data = MEM_mallocN(sizeof(float)*data_size*total_particles, "particle point data");
+ if (data_size) {
+ pd->point_data = MEM_mallocN(sizeof(float) * data_size * total_particles,
+ "particle point data");
+ }
}
-static void pointdensity_cache_psys(Render *re, PointDensity *pd, Object *ob, ParticleSystem *psys)
+static void pointdensity_cache_psys(Scene *scene,
+ PointDensity *pd,
+ Object *ob,
+ ParticleSystem *psys,
+ float viewmat[4][4],
+ float winmat[4][4],
+ int winx, int winy)
{
- DerivedMesh* dm;
+ DerivedMesh *dm;
ParticleKey state;
ParticleCacheKey *cache;
- ParticleSimulationData sim= {NULL};
- ParticleData *pa=NULL;
- float cfra = BKE_scene_frame_get(re->scene);
+ ParticleSimulationData sim = {NULL};
+ ParticleData *pa = NULL;
+ float cfra = BKE_scene_frame_get(scene);
int i /*, childexists*/ /* UNUSED */;
- int total_particles, offset=0;
+ int total_particles, offset = 0;
int data_used = point_data_used(pd);
float partco[3];
- float obview[4][4];
-
+
/* init everything */
- if (!psys || !ob || !pd) return;
+ if (!psys || !ob || !pd) {
+ return;
+ }
- mul_m4_m4m4(obview, ob->obmat, re->viewinv);
-
/* Just to create a valid rendering context for particles */
- psys_render_set(ob, psys, re->viewmat, re->winmat, re->winx, re->winy, 0);
-
- dm = mesh_create_derived_render(re->scene, ob, CD_MASK_BAREMESH|CD_MASK_MTFACE|CD_MASK_MCOL);
-
+ psys_render_set(ob, psys, viewmat, winmat, winx, winy, 0);
+
+ dm = mesh_create_derived_render(scene, ob, CD_MASK_BAREMESH | CD_MASK_MTFACE | CD_MASK_MCOL);
+
if ( !psys_check_enabled(ob, psys)) {
psys_render_restore(ob, psys);
return;
}
-
- sim.scene= re->scene;
- sim.ob= ob;
- sim.psys= psys;
+
+ sim.scene = scene;
+ sim.ob = ob;
+ sim.psys = psys;
+ sim.psmd = psys_get_modifier(ob, psys);
/* in case ob->imat isn't up-to-date */
invert_m4_m4(ob->imat, ob->obmat);
-
- total_particles = psys->totpart+psys->totchild;
+
+ total_particles = psys->totpart + psys->totchild;
psys->lattice_deform_data = psys_create_lattice_deform_data(&sim);
-
+
pd->point_tree = BLI_bvhtree_new(total_particles, 0.0, 4, 6);
alloc_point_data(pd, total_particles, data_used);
pd->totpoints = total_particles;
- if (data_used & POINT_DATA_VEL) offset = pd->totpoints*3;
-
+ if (data_used & POINT_DATA_VEL) {
+ offset = pd->totpoints * 3;
+ }
+
#if 0 /* UNUSED */
if (psys->totchild > 0 && !(psys->part->draw & PART_DRAW_PARENT))
childexists = 1;
#endif
- for (i=0, pa=psys->particles; i < total_particles; i++, pa++) {
+ for (i = 0, pa = psys->particles; i < total_particles; i++, pa++) {
if (psys->part->type == PART_HAIR) {
/* hair particles */
@@ -161,7 +183,7 @@ static void pointdensity_cache_psys(Render *re, PointDensity *pd, Object *ob, Pa
else
continue;
- cache += cache->steps; /* use endpoint */
+ cache += cache->segments; /* use endpoint */
copy_v3_v3(state.co, cache->co);
zero_v3(state.vel);
@@ -176,19 +198,19 @@ static void pointdensity_cache_psys(Render *re, PointDensity *pd, Object *ob, Pa
if (data_used & POINT_DATA_LIFE) {
if (i < psys->totpart) {
- state.time = (cfra - pa->time)/pa->lifetime;
+ state.time = (cfra - pa->time) / pa->lifetime;
}
else {
- ChildParticle *cpa= (psys->child + i) - psys->totpart;
+ ChildParticle *cpa = (psys->child + i) - psys->totpart;
float pa_birthtime, pa_dietime;
-
+
state.time = psys_get_child_time(psys, cpa, cfra, &pa_birthtime, &pa_dietime);
}
}
}
copy_v3_v3(partco, state.co);
-
+
if (pd->psys_cache_space == TEX_PD_OBJECTSPACE)
mul_m4_v3(ob->imat, partco);
else if (pd->psys_cache_space == TEX_PD_OBJECTLOC) {
@@ -197,48 +219,50 @@ static void pointdensity_cache_psys(Render *re, PointDensity *pd, Object *ob, Pa
else {
/* TEX_PD_WORLDSPACE */
}
-
+
BLI_bvhtree_insert(pd->point_tree, i, partco, 1);
-
+
if (data_used & POINT_DATA_VEL) {
- pd->point_data[i*3 + 0] = state.vel[0];
- pd->point_data[i*3 + 1] = state.vel[1];
- pd->point_data[i*3 + 2] = state.vel[2];
+ pd->point_data[i * 3 + 0] = state.vel[0];
+ pd->point_data[i * 3 + 1] = state.vel[1];
+ pd->point_data[i * 3 + 2] = state.vel[2];
}
if (data_used & POINT_DATA_LIFE) {
pd->point_data[offset + i] = state.time;
}
}
-
+
BLI_bvhtree_balance(pd->point_tree);
dm->release(dm);
-
+
if (psys->lattice_deform_data) {
end_latt_deform(psys->lattice_deform_data);
psys->lattice_deform_data = NULL;
}
-
+
psys_render_restore(ob, psys);
}
-static void pointdensity_cache_object(Render *re, PointDensity *pd, Object *ob)
+static void pointdensity_cache_object(Scene *scene, PointDensity *pd, Object *ob)
{
int i;
DerivedMesh *dm;
MVert *mvert = NULL;
-
- dm = mesh_create_derived_render(re->scene, ob, CD_MASK_BAREMESH|CD_MASK_MTFACE|CD_MASK_MCOL);
- mvert= dm->getVertArray(dm); /* local object space */
-
- pd->totpoints= dm->getNumVerts(dm);
- if (pd->totpoints == 0) return;
+
+ dm = mesh_create_derived_render(scene, ob, CD_MASK_BAREMESH | CD_MASK_MTFACE | CD_MASK_MCOL);
+ mvert = dm->getVertArray(dm); /* local object space */
+
+ pd->totpoints = dm->getNumVerts(dm);
+ if (pd->totpoints == 0) {
+ return;
+ }
pd->point_tree = BLI_bvhtree_new(pd->totpoints, 0.0, 4, 6);
-
- for (i=0; i < pd->totpoints; i++, mvert++) {
+
+ for (i = 0; i < pd->totpoints; i++, mvert++) {
float co[3];
-
+
copy_v3_v3(co, mvert->co);
switch (pd->ob_cache_space) {
@@ -256,47 +280,60 @@ static void pointdensity_cache_object(Render *re, PointDensity *pd, Object *ob)
BLI_bvhtree_insert(pd->point_tree, i, co, 1);
}
-
+
BLI_bvhtree_balance(pd->point_tree);
dm->release(dm);
}
-void cache_pointdensity(Render *re, Tex *tex)
+
+static void cache_pointdensity_ex(Scene *scene,
+ PointDensity *pd,
+ float viewmat[4][4],
+ float winmat[4][4],
+ int winx, int winy)
{
- PointDensity *pd = tex->pd;
-
- if (!pd)
+ if (pd == NULL) {
return;
+ }
if (pd->point_tree) {
BLI_bvhtree_free(pd->point_tree);
pd->point_tree = NULL;
}
-
+
if (pd->source == TEX_PD_PSYS) {
Object *ob = pd->object;
ParticleSystem *psys;
- if (!ob || !pd->psys) return;
+ if (!ob || !pd->psys) {
+ return;
+ }
+
+ psys = BLI_findlink(&ob->particlesystem, pd->psys - 1);
+ if (!psys) {
+ return;
+ }
- psys= BLI_findlink(&ob->particlesystem, pd->psys-1);
- if (!psys) return;
-
- pointdensity_cache_psys(re, pd, ob, psys);
+ pointdensity_cache_psys(scene, pd, ob, psys, viewmat, winmat, winx, winy);
}
else if (pd->source == TEX_PD_OBJECT) {
Object *ob = pd->object;
if (ob && ob->type == OB_MESH)
- pointdensity_cache_object(re, pd, ob);
+ pointdensity_cache_object(scene, pd, ob);
}
}
-static void free_pointdensity(Render *UNUSED(re), Tex *tex)
+void cache_pointdensity(Render *re, PointDensity *pd)
{
- PointDensity *pd = tex->pd;
+ cache_pointdensity_ex(re->scene, pd, re->viewmat, re->winmat, re->winx, re->winy);
+}
+
+void free_pointdensity(PointDensity *pd)
+{
+ if (pd == NULL) {
+ return;
+ }
- if (!pd) return;
-
if (pd->point_tree) {
BLI_bvhtree_free(pd->point_tree);
pd->point_tree = NULL;
@@ -309,24 +346,23 @@ static void free_pointdensity(Render *UNUSED(re), Tex *tex)
pd->totpoints = 0;
}
-
-
void make_pointdensities(Render *re)
{
Tex *tex;
-
- if (re->scene->r.scemode & R_BUTS_PREVIEW)
+
+ if (re->scene->r.scemode & R_BUTS_PREVIEW) {
return;
-
+ }
+
re->i.infostr = IFACE_("Caching Point Densities");
re->stats_draw(re->sdh, &re->i);
- for (tex= re->main->tex.first; tex; tex= tex->id.next) {
- if (tex->id.us && tex->type==TEX_POINTDENSITY) {
- cache_pointdensity(re, tex);
+ for (tex = re->main->tex.first; tex != NULL; tex = tex->id.next) {
+ if (tex->id.us && tex->type == TEX_POINTDENSITY) {
+ cache_pointdensity(re, tex->pd);
}
}
-
+
re->i.infostr = NULL;
re->stats_draw(re->sdh, &re->i);
}
@@ -334,13 +370,13 @@ void make_pointdensities(Render *re)
void free_pointdensities(Render *re)
{
Tex *tex;
-
+
if (re->scene->r.scemode & R_BUTS_PREVIEW)
return;
-
- for (tex= re->main->tex.first; tex; tex= tex->id.next) {
- if (tex->id.us && tex->type==TEX_POINTDENSITY) {
- free_pointdensity(re, tex);
+
+ for (tex = re->main->tex.first; tex != NULL; tex = tex->id.next) {
+ if (tex->id.us && tex->type == TEX_POINTDENSITY) {
+ free_pointdensity(tex->pd);
}
}
}
@@ -365,20 +401,20 @@ static void accum_density(void *userdata, int index, float squared_dist)
PointDensityRangeData *pdr = (PointDensityRangeData *)userdata;
const float dist = (pdr->squared_radius - squared_dist) / pdr->squared_radius * 0.5f;
float density = 0.0f;
-
+
if (pdr->point_data_used & POINT_DATA_VEL) {
- pdr->vec[0] += pdr->point_data[index*3 + 0]; // * density;
- pdr->vec[1] += pdr->point_data[index*3 + 1]; // * density;
- pdr->vec[2] += pdr->point_data[index*3 + 2]; // * density;
+ pdr->vec[0] += pdr->point_data[index * 3 + 0]; // * density;
+ pdr->vec[1] += pdr->point_data[index * 3 + 1]; // * density;
+ pdr->vec[2] += pdr->point_data[index * 3 + 2]; // * density;
}
if (pdr->point_data_used & POINT_DATA_LIFE) {
*pdr->age += pdr->point_data[pdr->offset + index]; // * density;
}
-
+
if (pdr->falloff_type == TEX_PD_FALLOFF_STD)
density = dist;
else if (pdr->falloff_type == TEX_PD_FALLOFF_SMOOTH)
- density = 3.0f*dist*dist - 2.0f*dist*dist*dist;
+ density = 3.0f * dist * dist - 2.0f * dist * dist * dist;
else if (pdr->falloff_type == TEX_PD_FALLOFF_SOFT)
density = pow(dist, pdr->softness);
else if (pdr->falloff_type == TEX_PD_FALLOFF_CONSTANT)
@@ -387,30 +423,30 @@ static void accum_density(void *userdata, int index, float squared_dist)
density = sqrtf(dist);
else if (pdr->falloff_type == TEX_PD_FALLOFF_PARTICLE_AGE) {
if (pdr->point_data_used & POINT_DATA_LIFE)
- density = dist*MIN2(pdr->point_data[pdr->offset + index], 1.0f);
+ density = dist * MIN2(pdr->point_data[pdr->offset + index], 1.0f);
else
density = dist;
}
else if (pdr->falloff_type == TEX_PD_FALLOFF_PARTICLE_VEL) {
if (pdr->point_data_used & POINT_DATA_VEL)
- density = dist*len_v3(pdr->point_data + index*3)*pdr->velscale;
+ density = dist * len_v3(pdr->point_data + index * 3) * pdr->velscale;
else
density = dist;
}
-
+
if (pdr->density_curve && dist != 0.0f) {
curvemapping_initialize(pdr->density_curve);
- density = curvemapping_evaluateF(pdr->density_curve, 0, density/dist)*dist;
+ density = curvemapping_evaluateF(pdr->density_curve, 0, density / dist) * dist;
}
-
+
*pdr->density += density;
}
-static void init_pointdensityrangedata(PointDensity *pd, PointDensityRangeData *pdr,
+static void init_pointdensityrangedata(PointDensity *pd, PointDensityRangeData *pdr,
float *density, float *vec, float *age, struct CurveMapping *density_curve, float velscale)
{
- pdr->squared_radius = pd->radius*pd->radius;
+ pdr->squared_radius = pd->radius * pd->radius;
pdr->density = density;
pdr->point_data = pd->point_data;
pdr->falloff_type = pd->falloff_type;
@@ -419,63 +455,69 @@ static void init_pointdensityrangedata(PointDensity *pd, PointDensityRangeData *
pdr->softness = pd->falloff_softness;
pdr->noise_influence = pd->noise_influence;
pdr->point_data_used = point_data_used(pd);
- pdr->offset = (pdr->point_data_used & POINT_DATA_VEL)?pd->totpoints*3:0;
+ pdr->offset = (pdr->point_data_used & POINT_DATA_VEL) ? pd->totpoints * 3 : 0;
pdr->density_curve = density_curve;
pdr->velscale = velscale;
}
-int pointdensitytex(Tex *tex, const float texvec[3], TexResult *texres)
+static int pointdensity(PointDensity *pd,
+ const float texvec[3],
+ TexResult *texres,
+ float *r_age,
+ float r_vec[3])
{
int retval = TEX_INT;
- PointDensity *pd = tex->pd;
PointDensityRangeData pdr;
- float density=0.0f, age=0.0f, time=0.0f;
+ float density = 0.0f, age = 0.0f, time = 0.0f;
float vec[3] = {0.0f, 0.0f, 0.0f}, co[3];
- float col[4];
float turb, noise_fac;
- int num=0;
-
+ int num = 0;
+
texres->tin = 0.0f;
-
+
if ((!pd) || (!pd->point_tree))
return 0;
-
- init_pointdensityrangedata(pd, &pdr, &density, vec, &age,
- (pd->flag&TEX_PD_FALLOFF_CURVE ? pd->falloff_curve : NULL), pd->falloff_speed_scale*0.001f);
+
+ init_pointdensityrangedata(pd, &pdr, &density, vec, &age,
+ (pd->flag & TEX_PD_FALLOFF_CURVE ? pd->falloff_curve : NULL),
+ pd->falloff_speed_scale * 0.001f);
noise_fac = pd->noise_fac * 0.5f; /* better default */
-
+
copy_v3_v3(co, texvec);
-
+
if (point_data_used(pd)) {
/* does a BVH lookup to find accumulated density and additional point data *
* stores particle velocity vector in 'vec', and particle lifetime in 'time' */
num = BLI_bvhtree_range_query(pd->point_tree, co, pd->radius, accum_density, &pdr);
if (num > 0) {
age /= num;
- mul_v3_fl(vec, 1.0f/num);
+ mul_v3_fl(vec, 1.0f / num);
}
-
+
/* reset */
density = vec[0] = vec[1] = vec[2] = 0.0f;
}
-
+
if (pd->flag & TEX_PD_TURBULENCE) {
-
+
if (pd->noise_influence == TEX_PD_NOISE_AGE) {
- turb = BLI_gTurbulence(pd->noise_size, texvec[0]+age, texvec[1]+age, texvec[2]+age, pd->noise_depth, 0, pd->noise_basis);
+ turb = BLI_gTurbulence(pd->noise_size, texvec[0] + age, texvec[1] + age, texvec[2] + age,
+ pd->noise_depth, 0, pd->noise_basis);
}
else if (pd->noise_influence == TEX_PD_NOISE_TIME) {
time = R.r.cfra / (float)R.r.efra;
- turb = BLI_gTurbulence(pd->noise_size, texvec[0]+time, texvec[1]+time, texvec[2]+time, pd->noise_depth, 0, pd->noise_basis);
+ turb = BLI_gTurbulence(pd->noise_size, texvec[0] + time, texvec[1] + time, texvec[2] + time,
+ pd->noise_depth, 0, pd->noise_basis);
//turb = BLI_turbulence(pd->noise_size, texvec[0]+time, texvec[1]+time, texvec[2]+time, pd->noise_depth);
}
else {
- turb = BLI_gTurbulence(pd->noise_size, texvec[0]+vec[0], texvec[1]+vec[1], texvec[2]+vec[2], pd->noise_depth, 0, pd->noise_basis);
+ turb = BLI_gTurbulence(pd->noise_size, texvec[0] + vec[0], texvec[1] + vec[1], texvec[2] + vec[2],
+ pd->noise_depth, 0, pd->noise_basis);
}
turb -= 0.5f; /* re-center 0.0-1.0 range around 0 to prevent offsetting result */
-
+
/* now we have an offset coordinate to use for the density lookup */
co[0] = texvec[0] + noise_fac * turb;
co[1] = texvec[1] + noise_fac * turb;
@@ -486,17 +528,27 @@ int pointdensitytex(Tex *tex, const float texvec[3], TexResult *texres)
num = BLI_bvhtree_range_query(pd->point_tree, co, pd->radius, accum_density, &pdr);
if (num > 0) {
age /= num;
- mul_v3_fl(vec, 1.0f/num);
+ mul_v3_fl(vec, 1.0f / num);
}
-
+
texres->tin = density;
- BRICONT;
-
- if (pd->color_source == TEX_PD_COLOR_CONSTANT)
- return retval;
-
+ if (r_age != NULL) {
+ *r_age = age;
+ }
+ if (r_vec != NULL) {
+ copy_v3_v3(r_vec, vec);
+ }
+
+ return retval;
+}
+
+static int pointdensity_color(PointDensity *pd, TexResult *texres, float age, const float vec[3])
+{
+ int retval = 0;
+ float col[4];
+
retval |= TEX_RGB;
-
+
switch (pd->color_source) {
case TEX_PD_COLOR_PARTAGE:
if (pd->coba) {
@@ -511,7 +563,7 @@ int pointdensitytex(Tex *tex, const float texvec[3], TexResult *texres)
case TEX_PD_COLOR_PARTSPEED:
{
float speed = len_v3(vec) * pd->speed_scale;
-
+
if (pd->coba) {
if (do_colorband(pd->coba, speed, col)) {
texres->talpha = true;
@@ -524,8 +576,7 @@ int pointdensitytex(Tex *tex, const float texvec[3], TexResult *texres)
}
case TEX_PD_COLOR_PARTVEL:
texres->talpha = true;
- mul_v3_fl(vec, pd->speed_scale);
- copy_v3_v3(&texres->tr, vec);
+ mul_v3_v3fl(&texres->tr, vec, pd->speed_scale);
texres->ta = texres->tin;
break;
case TEX_PD_COLOR_CONSTANT:
@@ -533,13 +584,130 @@ int pointdensitytex(Tex *tex, const float texvec[3], TexResult *texres)
texres->tr = texres->tg = texres->tb = texres->ta = 1.0f;
break;
}
- BRICONTRGB;
return retval;
-
+}
+
+int pointdensitytex(Tex *tex, const float texvec[3], TexResult *texres)
+{
+ PointDensity *pd = tex->pd;
+ float age = 0.0f;
+ float vec[3] = {0.0f, 0.0f, 0.0f};
+ int retval = pointdensity(pd, texvec, texres, &age, vec);
+
+ BRICONT;
+
+ retval |= pointdensity_color(pd, texres, age, vec);
+ BRICONTRGB;
+
+ return retval;
+
#if 0
if (texres->nor!=NULL) {
texres->nor[0] = texres->nor[1] = texres->nor[2] = 0.0f;
}
#endif
}
+
+static void sample_dummy_point_density(int resolution, float *values)
+{
+ memset(values, 0, sizeof(float) * 4 * resolution * resolution * resolution);
+}
+
+static void particle_system_minmax(Object *object,
+ ParticleSystem *psys,
+ float radius,
+ float min[3], float max[3])
+{
+ ParticleSettings *part = psys->part;
+ float imat[4][4];
+ float size[3] = {radius, radius, radius};
+ PARTICLE_P;
+ INIT_MINMAX(min, max);
+ if (part->type == PART_HAIR) {
+ /* TOOD(sergey): Not supported currently. */
+ return;
+ }
+ invert_m4_m4(imat, object->obmat);
+ LOOP_PARTICLES {
+ float co_object[3], co_min[3], co_max[3];
+ mul_v3_m4v3(co_object, imat, pa->state.co);
+ sub_v3_v3v3(co_min, co_object, size);
+ add_v3_v3v3(co_max, co_object, size);
+ minmax_v3v3_v3(min, max, co_min);
+ minmax_v3v3_v3(min, max, co_max);
+ }
+}
+
+void RE_sample_point_density(Scene *scene, PointDensity *pd,
+ int resolution, float *values)
+{
+ const size_t resolution2 = resolution * resolution;
+ Object *object = pd->object;
+ size_t x, y, z;
+ float min[3], max[3], dim[3], mat[4][4];
+
+ if (object == NULL) {
+ sample_dummy_point_density(resolution, values);
+ return;
+ }
+
+ if (pd->source == TEX_PD_PSYS) {
+ ParticleSystem *psys;
+ if (pd->psys == 0) {
+ sample_dummy_point_density(resolution, values);
+ return;
+ }
+ psys = BLI_findlink(&object->particlesystem, pd->psys - 1);
+ if (psys == NULL) {
+ sample_dummy_point_density(resolution, values);
+ return;
+ }
+ particle_system_minmax(object, psys, pd->radius, min, max);
+ }
+ else {
+ float radius[3] = {pd->radius, pd->radius, pd->radius};
+ float *loc, *size;
+ BKE_object_obdata_texspace_get(pd->object, NULL, &loc, &size, NULL);
+ sub_v3_v3v3(min, loc, size);
+ add_v3_v3v3(max, loc, size);
+ /* Adjust texture space to include density points on the boundaries. */
+ sub_v3_v3(min, radius);
+ add_v3_v3(max, radius);
+ }
+
+ sub_v3_v3v3(dim, max, min);
+ if (dim[0] <= 0.0f || dim[1] <= 0.0f || dim[2] <= 0.0f) {
+ sample_dummy_point_density(resolution, values);
+ return;
+ }
+
+ /* Same matricies/resolution as dupli_render_particle_set(). */
+ unit_m4(mat);
+
+ BLI_mutex_lock(&sample_mutex);
+ cache_pointdensity_ex(scene, pd, mat, mat, 1, 1);
+ for (z = 0; z < resolution; ++z) {
+ for (y = 0; y < resolution; ++y) {
+ for (x = 0; x < resolution; ++x) {
+ size_t index = z * resolution2 + y * resolution + x;
+ float texvec[3];
+ float age, vec[3];
+ TexResult texres;
+
+ copy_v3_v3(texvec, min);
+ texvec[0] += dim[0] * (float)x / (float)resolution;
+ texvec[1] += dim[1] * (float)y / (float)resolution;
+ texvec[2] += dim[2] * (float)z / (float)resolution;
+
+ pointdensity(pd, texvec, &texres, &age, vec);
+ pointdensity_color(pd, &texres, age, vec);
+
+ copy_v3_v3(&values[index*4 + 0], &texres.tr);
+ values[index*4 + 3] = texres.tin;
+ }
+ }
+ }
+ free_pointdensity(pd);
+ BLI_mutex_unlock(&sample_mutex);
+}
diff --git a/source/blender/render/intern/source/rayshade.c b/source/blender/render/intern/source/rayshade.c
index 05e83f35179..900312ee984 100644
--- a/source/blender/render/intern/source/rayshade.c
+++ b/source/blender/render/intern/source/rayshade.c
@@ -27,7 +27,6 @@
* \ingroup render
*/
-
#include <stdio.h>
#include <math.h>
#include <string.h>
@@ -46,29 +45,22 @@
#include "BLI_rand.h"
#include "BLI_utildefines.h"
-#include "BLF_translation.h"
+#include "BLT_translation.h"
#include "BKE_node.h"
-
-#include "PIL_time.h"
-
#include "render_result.h"
#include "render_types.h"
-#include "renderpipeline.h"
#include "rendercore.h"
#include "renderdatabase.h"
-#include "pixelblending.h"
#include "pixelshading.h"
#include "shading.h"
-#include "texture.h"
#include "volumetric.h"
#include "rayintersection.h"
#include "rayobject.h"
#include "raycounter.h"
-
#define RAY_TRA 1
#define RAY_INSIDE 2
@@ -314,22 +306,23 @@ static void makeraytree_single(Render *re)
RayObject *raytree;
RayFace *face = NULL;
VlakPrimitive *vlakprimitive = NULL;
- int faces = 0, obs = 0, special = 0;
+ int faces = 0, special = 0;
- for (obi=re->instancetable.first; obi; obi=obi->next)
- if (is_raytraceable(re, obi)) {
- ObjectRen *obr = obi->obr;
- obs++;
-
- if (has_special_rayobject(re, obi)) {
- special++;
- }
- else {
- int v;
- for (v=0;v<obr->totvlak;v++) {
- VlakRen *vlr = obr->vlaknodes[v>>8].vlak + (v&255);
- if (is_raytraceable_vlr(re, vlr))
- faces++;
+ for (obi = re->instancetable.first; obi; obi = obi->next) {
+ if (is_raytraceable(re, obi)) {
+ ObjectRen *obr = obi->obr;
+
+ if (has_special_rayobject(re, obi)) {
+ special++;
+ }
+ else {
+ int v;
+ for (v = 0;v < obr->totvlak; v++) {
+ VlakRen *vlr = obr->vlaknodes[v >> 8].vlak + (v&255);
+ if (is_raytraceable_vlr(re, vlr)) {
+ faces++;
+ }
+ }
}
}
}
@@ -743,6 +736,7 @@ static void traceray(ShadeInput *origshi, ShadeResult *origshr, short depth, con
//shi.sample= 0; // memset above, so don't need this
shi.xs= origshi->xs;
shi.ys= origshi->ys;
+ shi.do_manage= origshi->do_manage;
shi.lay= origshi->lay;
shi.passflag= SCE_PASS_COMBINED; /* result of tracing needs no pass info */
shi.combinedflag= 0xFFFFFF; /* ray trace does all options */
@@ -802,7 +796,7 @@ static void traceray(ShadeInput *origshi, ShadeResult *origshr, short depth, con
traceray(origshi, origshr, depth-1, shi.co, shi.view, tracol, shi.obi, shi.vlr, 0);
f= shr.alpha; f1= 1.0f-f;
- nf= d * shi.mat->filter;
+ nf= (shi.mat->mode & MA_RAYTRANSP) ? d * shi.mat->filter : 0.0f;
fr= 1.0f+ nf*(shi.r-1.0f);
fg= 1.0f+ nf*(shi.g-1.0f);
fb= 1.0f+ nf*(shi.b-1.0f);
@@ -1281,7 +1275,7 @@ static float get_avg_speed(ShadeInput *shi)
post_x = (shi->winspeed[2] == PASS_VECTOR_MAX)?0.0f:shi->winspeed[2];
post_y = (shi->winspeed[3] == PASS_VECTOR_MAX)?0.0f:shi->winspeed[3];
- speedavg = (sqrtf(pre_x * pre_x + pre_y * pre_y) + sqrtf(post_x * post_x + post_y * post_y)) / 2.0;
+ speedavg = (sqrtf(pre_x * pre_x + pre_y * pre_y) + sqrtf(post_x * post_x + post_y * post_y)) / 2.0f;
return speedavg;
}
@@ -1299,7 +1293,7 @@ static void trace_refract(float col[4], ShadeInput *shi, ShadeResult *shr)
float v_refract[3], v_refract_new[3];
float sampcol[4], colsq[4];
- float blur = powf(1.0f - shi->mat->gloss_tra, 3);
+ float blur = pow3f(1.0f - shi->mat->gloss_tra);
short max_samples = shi->mat->samp_gloss_tra;
float adapt_thresh = shi->mat->adapt_thresh_tra;
@@ -1400,7 +1394,7 @@ static void trace_reflect(float col[3], ShadeInput *shi, ShadeResult *shr, float
float v_nor_new[3], v_reflect[3];
float sampcol[4], colsq[4];
- float blur = powf(1.0f - shi->mat->gloss_mir, 3);
+ float blur = pow3f(1.0f - shi->mat->gloss_mir);
short max_samples = shi->mat->samp_gloss_mir;
float adapt_thresh = shi->mat->adapt_thresh_mir;
float aniso = 1.0f - shi->mat->aniso_gloss_mir;
@@ -1562,7 +1556,7 @@ void ray_trace(ShadeInput *shi, ShadeResult *shr)
}
if (shi->combinedflag & SCE_PASS_REFLECT) {
- /* values in shr->spec can be greater then 1.0.
+ /* values in shr->spec can be greater than 1.0.
* In this case the mircol uses a zero blending factor, so ignoring it is ok.
* Fixes bug #18837 - when the spec is higher then 1.0,
* diff can become a negative color - Campbell */
@@ -1629,6 +1623,7 @@ static void ray_trace_shadow_tra(Isect *is, ShadeInput *origshi, int depth, int
shi.xs= origshi->xs;
shi.ys= origshi->ys;
+ shi.do_manage= origshi->do_manage;
shi.lay= origshi->lay;
shi.nodes= origshi->nodes;
@@ -1636,9 +1631,9 @@ static void ray_trace_shadow_tra(Isect *is, ShadeInput *origshi, int depth, int
shade_ray(is, &shi, &shr);
if (shi.mat->material_type == MA_TYPE_SURFACE) {
- const float d= (traflag & RAY_TRA) ?
- shade_by_transmission(is, &shi, &shr) :
- 1.0f;
+ const float d = (shi.mat->mode & MA_RAYTRANSP) ?
+ ((traflag & RAY_TRA) ? shade_by_transmission(is, &shi, &shr) : 1.0f) :
+ 0.0f;
/* mix colors based on shadfac (rgb + amount of light factor) */
addAlphaLight(col, shr.diff, shr.alpha, d*shi.mat->filter);
}
@@ -2371,9 +2366,9 @@ static void ray_shadow_jitter(ShadeInput *shi, LampRen *lar, const float lampco[
mul_m3_v3(lar->mat, vec);
/* set start and vec */
- isec->dir[0] = vec[0]+lampco[0]-isec->start[0];
- isec->dir[1] = vec[1]+lampco[1]-isec->start[1];
- isec->dir[2] = vec[2]+lampco[2]-isec->start[2];
+ isec->dir[0] = vec[0]+lampco[0]-shi->co[0];
+ isec->dir[1] = vec[1]+lampco[1]-shi->co[1];
+ isec->dir[2] = vec[2]+lampco[2]-shi->co[2];
RE_instance_rotate_ray_dir(shi->obi, isec);
diff --git a/source/blender/render/intern/source/render_result.c b/source/blender/render/intern/source/render_result.c
index d8410fbe257..27fc412e1cd 100644
--- a/source/blender/render/intern/source/render_result.c
+++ b/source/blender/render/intern/source/render_result.c
@@ -35,19 +35,21 @@
#include "MEM_guardedalloc.h"
+#include "BKE_appdir.h"
#include "BLI_utildefines.h"
#include "BLI_listbase.h"
-#include "BLI_md5.h"
+#include "BLI_hash_md5.h"
#include "BLI_path_util.h"
#include "BLI_rect.h"
#include "BLI_string.h"
-#include "BLI_system.h"
#include "BLI_threads.h"
#include "BKE_image.h"
#include "BKE_global.h"
#include "BKE_main.h"
#include "BKE_report.h"
+#include "BKE_camera.h"
+#include "BKE_scene.h"
#include "IMB_imbuf.h"
#include "IMB_imbuf_types.h"
@@ -60,14 +62,32 @@
/********************************** Free *************************************/
+static void render_result_views_free(RenderResult *res)
+{
+ while (res->views.first) {
+ RenderView *rv = res->views.first;
+ BLI_remlink(&res->views, rv);
+
+ if (rv->rect32)
+ MEM_freeN(rv->rect32);
+
+ if (rv->rectz)
+ MEM_freeN(rv->rectz);
+
+ if (rv->rectf)
+ MEM_freeN(rv->rectf);
+
+ MEM_freeN(rv);
+ }
+}
+
void render_result_free(RenderResult *res)
{
if (res == NULL) return;
while (res->layers.first) {
RenderLayer *rl = res->layers.first;
-
- if (rl->rectf) MEM_freeN(rl->rectf);
+
/* acolrect and scolrect are optionally allocated in shade_tile, only free here since it can be used for drawing */
if (rl->acolrect) MEM_freeN(rl->acolrect);
if (rl->scolrect) MEM_freeN(rl->scolrect);
@@ -82,7 +102,9 @@ void render_result_free(RenderResult *res)
BLI_remlink(&res->layers, rl);
MEM_freeN(rl);
}
-
+
+ render_result_views_free(res);
+
if (res->rect32)
MEM_freeN(res->rect32);
if (res->rectz)
@@ -91,7 +113,11 @@ void render_result_free(RenderResult *res)
MEM_freeN(res->rectf);
if (res->text)
MEM_freeN(res->text);
-
+ if (res->error)
+ MEM_freeN(res->error);
+ if (res->stamp_data)
+ MEM_freeN(res->stamp_data);
+
MEM_freeN(res);
}
@@ -110,13 +136,44 @@ void render_result_free_list(ListBase *lb, RenderResult *rr)
}
}
-/********************************* Names *************************************/
+/********************************* multiview *************************************/
-/* NOTE: OpenEXR only supports 32 chars for layer+pass names
- * In blender we now use max 10 chars for pass, max 20 for layer */
-static const char *get_pass_name(int passtype, int channel)
+/* create a new views Listbase in rr without duplicating the memory pointers */
+void render_result_views_shallowcopy(RenderResult *dst, RenderResult *src)
+{
+ RenderView *rview;
+
+ if (dst == NULL || src == NULL)
+ return;
+
+ for (rview = src->views.first; rview; rview = rview->next) {
+ RenderView *rv;
+
+ rv = MEM_mallocN(sizeof(RenderView), "new render view");
+ BLI_addtail(&dst->views, rv);
+
+ BLI_strncpy(rv->name, rview->name, sizeof(rv->name));
+ rv->rectf = rview->rectf;
+ rv->rectz = rview->rectz;
+ rv->rect32 = rview->rect32;
+ }
+}
+
+/* free the views created temporarily */
+void render_result_views_shallowdelete(RenderResult *rr)
+{
+ if (rr == NULL)
+ return;
+
+ while (rr->views.first) {
+ RenderView *rv = rr->views.first;
+ BLI_remlink(&rr->views, rv);
+ MEM_freeN(rv);
+ }
+}
+
+static const char *name_from_passtype(int passtype, int channel)
{
-
if (passtype == SCE_PASS_COMBINED) {
if (channel == -1) return "Combined";
if (channel == 0) return "Combined.R";
@@ -303,122 +360,151 @@ static const char *get_pass_name(int passtype, int channel)
static int passtype_from_name(const char *str)
{
-
- if (strcmp(str, "Combined") == 0)
+ if (STRPREFIX(str, "Combined"))
return SCE_PASS_COMBINED;
- if (strcmp(str, "Depth") == 0)
+ if (STRPREFIX(str, "Depth"))
return SCE_PASS_Z;
- if (strcmp(str, "Vector") == 0)
+ if (STRPREFIX(str, "Vector"))
return SCE_PASS_VECTOR;
- if (strcmp(str, "Normal") == 0)
+ if (STRPREFIX(str, "Normal"))
return SCE_PASS_NORMAL;
- if (strcmp(str, "UV") == 0)
+ if (STRPREFIX(str, "UV"))
return SCE_PASS_UV;
- if (strcmp(str, "Color") == 0)
+ if (STRPREFIX(str, "Color"))
return SCE_PASS_RGBA;
- if (strcmp(str, "Emit") == 0)
+ if (STRPREFIX(str, "Emit"))
return SCE_PASS_EMIT;
- if (strcmp(str, "Diffuse") == 0)
+ if (STRPREFIX(str, "Diffuse"))
return SCE_PASS_DIFFUSE;
- if (strcmp(str, "Spec") == 0)
+ if (STRPREFIX(str, "Spec"))
return SCE_PASS_SPEC;
- if (strcmp(str, "Shadow") == 0)
+ if (STRPREFIX(str, "Shadow"))
return SCE_PASS_SHADOW;
- if (strcmp(str, "AO") == 0)
+ if (STRPREFIX(str, "AO"))
return SCE_PASS_AO;
- if (strcmp(str, "Env") == 0)
+ if (STRPREFIX(str, "Env"))
return SCE_PASS_ENVIRONMENT;
- if (strcmp(str, "Indirect") == 0)
+ if (STRPREFIX(str, "Indirect"))
return SCE_PASS_INDIRECT;
- if (strcmp(str, "Reflect") == 0)
+ if (STRPREFIX(str, "Reflect"))
return SCE_PASS_REFLECT;
- if (strcmp(str, "Refract") == 0)
+ if (STRPREFIX(str, "Refract"))
return SCE_PASS_REFRACT;
- if (strcmp(str, "IndexOB") == 0)
+ if (STRPREFIX(str, "IndexOB"))
return SCE_PASS_INDEXOB;
- if (strcmp(str, "IndexMA") == 0)
+ if (STRPREFIX(str, "IndexMA"))
return SCE_PASS_INDEXMA;
- if (strcmp(str, "Mist") == 0)
+ if (STRPREFIX(str, "Mist"))
return SCE_PASS_MIST;
- if (strcmp(str, "RayHits") == 0)
+ if (STRPREFIX(str, "RayHits"))
return SCE_PASS_RAYHITS;
- if (strcmp(str, "DiffDir") == 0)
+ if (STRPREFIX(str, "DiffDir"))
return SCE_PASS_DIFFUSE_DIRECT;
- if (strcmp(str, "DiffInd") == 0)
+ if (STRPREFIX(str, "DiffInd"))
return SCE_PASS_DIFFUSE_INDIRECT;
- if (strcmp(str, "DiffCol") == 0)
+ if (STRPREFIX(str, "DiffCol"))
return SCE_PASS_DIFFUSE_COLOR;
- if (strcmp(str, "GlossDir") == 0)
+ if (STRPREFIX(str, "GlossDir"))
return SCE_PASS_GLOSSY_DIRECT;
- if (strcmp(str, "GlossInd") == 0)
+ if (STRPREFIX(str, "GlossInd"))
return SCE_PASS_GLOSSY_INDIRECT;
- if (strcmp(str, "GlossCol") == 0)
+ if (STRPREFIX(str, "GlossCol"))
return SCE_PASS_GLOSSY_COLOR;
- if (strcmp(str, "TransDir") == 0)
+ if (STRPREFIX(str, "TransDir"))
return SCE_PASS_TRANSM_DIRECT;
- if (strcmp(str, "TransInd") == 0)
+ if (STRPREFIX(str, "TransInd"))
return SCE_PASS_TRANSM_INDIRECT;
- if (strcmp(str, "TransCol") == 0)
+ if (STRPREFIX(str, "TransCol"))
return SCE_PASS_TRANSM_COLOR;
- if (strcmp(str, "SubsurfaceDir") == 0)
+ if (STRPREFIX(str, "SubsurfaceDir"))
return SCE_PASS_SUBSURFACE_DIRECT;
- if (strcmp(str, "SubsurfaceInd") == 0)
+ if (STRPREFIX(str, "SubsurfaceInd"))
return SCE_PASS_SUBSURFACE_INDIRECT;
- if (strcmp(str, "SubsurfaceCol") == 0)
+ if (STRPREFIX(str, "SubsurfaceCol"))
return SCE_PASS_SUBSURFACE_COLOR;
return 0;
}
+
+static void set_pass_name(char *passname, int passtype, int channel, const char *view)
+{
+ const char delims[] = {'.', '\0'};
+ const char *sep;
+ const char *token;
+ size_t len;
+
+ const char *passtype_name = name_from_passtype(passtype, channel);
+
+ if (view == NULL || view[0] == '\0') {
+ BLI_strncpy(passname, passtype_name, EXR_PASS_MAXNAME);
+ return;
+ }
+
+ len = BLI_str_rpartition(passtype_name, delims, &sep, &token);
+
+ if (sep) {
+ BLI_snprintf(passname, EXR_PASS_MAXNAME, "%.*s.%s.%s", (int)len, passtype_name, view, token);
+ }
+ else {
+ BLI_snprintf(passname, EXR_PASS_MAXNAME, "%s.%s", passtype_name, view);
+ }
+}
+
/********************************** New **************************************/
-static void render_layer_add_pass(RenderResult *rr, RenderLayer *rl, int channels, int passtype)
+static RenderPass *render_layer_add_pass(RenderResult *rr, RenderLayer *rl, int channels, int passtype, const char *viewname)
{
- const char *typestr = get_pass_name(passtype, 0);
+ const size_t view_id = BLI_findstringindex(&rr->views, viewname, offsetof(RenderView, name));
+ const char *typestr = name_from_passtype(passtype, -1);
RenderPass *rpass = MEM_callocN(sizeof(RenderPass), typestr);
- int rectsize = rr->rectx * rr->recty * channels;
+ size_t rectsize = ((size_t)rr->rectx) * rr->recty * channels;
BLI_addtail(&rl->passes, rpass);
rpass->passtype = passtype;
rpass->channels = channels;
rpass->rectx = rl->rectx;
rpass->recty = rl->recty;
- BLI_strncpy(rpass->name, get_pass_name(rpass->passtype, -1), sizeof(rpass->name));
+ rpass->view_id = view_id;
+
+ set_pass_name(rpass->name, rpass->passtype, -1, viewname);
+ BLI_strncpy(rpass->internal_name, typestr, sizeof(rpass->internal_name));
+ BLI_strncpy(rpass->view, viewname, sizeof(rpass->view));
if (rl->exrhandle) {
int a;
for (a = 0; a < channels; a++)
- IMB_exr_add_channel(rl->exrhandle, rl->name, get_pass_name(passtype, a), 0, 0, NULL);
+ IMB_exr_add_channel(rl->exrhandle, rl->name, name_from_passtype(passtype, a), viewname, 0, 0, NULL, false);
}
else {
float *rect;
@@ -438,18 +524,64 @@ static void render_layer_add_pass(RenderResult *rr, RenderLayer *rl, int channel
rect[x] = 10e10;
}
}
+ return rpass;
}
+#ifdef WITH_CYCLES_DEBUG
+const char *RE_debug_pass_name_get(int debug_type)
+{
+ switch (debug_type) {
+ case RENDER_PASS_DEBUG_BVH_TRAVERSAL_STEPS:
+ return "BVH Traversal Steps";
+ case RENDER_PASS_DEBUG_BVH_TRAVERSED_INSTANCES:
+ return "BVH Traversed Instances";
+ case RENDER_PASS_DEBUG_RAY_BOUNCES:
+ return "Ray Bounces";
+ }
+ return "Unknown";
+}
+
+int RE_debug_pass_num_channels_get(int UNUSED(debug_type))
+{
+ /* Only single case currently, might be handy for further debug passes. */
+ return 1;
+}
+
+static RenderPass *render_layer_add_debug_pass(RenderResult *rr,
+ RenderLayer *rl,
+ int pass_type,
+ int debug_type,
+ const char *view)
+{
+ const char *name = RE_debug_pass_name_get(debug_type);
+ int channels = RE_debug_pass_num_channels_get(debug_type);
+ RenderPass *rpass = render_layer_add_pass(rr, rl, channels, pass_type, view);
+ rpass->debug_type = debug_type;
+ BLI_strncpy(rpass->name,
+ name,
+ sizeof(rpass->name));
+ BLI_strncpy(rpass->internal_name, rpass->name, sizeof(rpass->internal_name));
+ return rpass;
+}
+
+int RE_debug_pass_type_get(Render *re)
+{
+ return re->r.debug_pass_type;
+}
+#endif
+
/* called by main render as well for parts */
/* will read info from Render *re to define layers */
/* called in threads */
/* re->winx,winy is coordinate space of entire image, partrct the part within */
-RenderResult *render_result_new(Render *re, rcti *partrct, int crop, int savebuffers, const char *layername)
+RenderResult *render_result_new(Render *re, rcti *partrct, int crop, int savebuffers, const char *layername, const char *viewname)
{
RenderResult *rr;
RenderLayer *rl;
+ RenderView *rv;
SceneRenderLayer *srl;
- int rectx, recty, nr;
+ int rectx, recty;
+ int nr;
rectx = BLI_rcti_size_x(partrct);
recty = BLI_rcti_size_y(partrct);
@@ -474,11 +606,13 @@ RenderResult *render_result_new(Render *re, rcti *partrct, int crop, int savebuf
rr->do_exr_tile = true;
}
+ render_result_views_new(rr, &re->r);
+
/* check renderdata for amount of layers */
for (nr = 0, srl = re->r.layers.first; srl; srl = srl->next, nr++) {
if (layername && layername[0])
- if (strcmp(srl->name, layername) != 0)
+ if (!STREQ(srl->name, layername))
continue;
if (re->r.scemode & R_SINGLE_LAYER) {
@@ -507,77 +641,90 @@ RenderResult *render_result_new(Render *re, rcti *partrct, int crop, int savebuf
if (rr->do_exr_tile) {
rl->display_buffer = MEM_mapallocN(rectx * recty * sizeof(unsigned int), "Combined display space rgba");
-
rl->exrhandle = IMB_exr_get_handle();
+ }
- IMB_exr_add_channel(rl->exrhandle, rl->name, "Combined.R", 0, 0, NULL);
- IMB_exr_add_channel(rl->exrhandle, rl->name, "Combined.G", 0, 0, NULL);
- IMB_exr_add_channel(rl->exrhandle, rl->name, "Combined.B", 0, 0, NULL);
- IMB_exr_add_channel(rl->exrhandle, rl->name, "Combined.A", 0, 0, NULL);
+ for (rv = rr->views.first; rv; rv = rv->next) {
+ const char *view = rv->name;
+
+ if (viewname && viewname[0])
+ if (!STREQ(view, viewname))
+ continue;
+
+ if (rr->do_exr_tile)
+ IMB_exr_add_view(rl->exrhandle, view);
+
+ /* a renderlayer should always have a Combined pass*/
+ render_layer_add_pass(rr, rl, 4, SCE_PASS_COMBINED, view);
+
+ if (srl->passflag & SCE_PASS_Z)
+ render_layer_add_pass(rr, rl, 1, SCE_PASS_Z, view);
+ if (srl->passflag & SCE_PASS_VECTOR)
+ render_layer_add_pass(rr, rl, 4, SCE_PASS_VECTOR, view);
+ if (srl->passflag & SCE_PASS_NORMAL)
+ render_layer_add_pass(rr, rl, 3, SCE_PASS_NORMAL, view);
+ if (srl->passflag & SCE_PASS_UV)
+ render_layer_add_pass(rr, rl, 3, SCE_PASS_UV, view);
+ if (srl->passflag & SCE_PASS_RGBA)
+ render_layer_add_pass(rr, rl, 4, SCE_PASS_RGBA, view);
+ if (srl->passflag & SCE_PASS_EMIT)
+ render_layer_add_pass(rr, rl, 3, SCE_PASS_EMIT, view);
+ if (srl->passflag & SCE_PASS_DIFFUSE)
+ render_layer_add_pass(rr, rl, 3, SCE_PASS_DIFFUSE, view);
+ if (srl->passflag & SCE_PASS_SPEC)
+ render_layer_add_pass(rr, rl, 3, SCE_PASS_SPEC, view);
+ if (srl->passflag & SCE_PASS_AO)
+ render_layer_add_pass(rr, rl, 3, SCE_PASS_AO, view);
+ if (srl->passflag & SCE_PASS_ENVIRONMENT)
+ render_layer_add_pass(rr, rl, 3, SCE_PASS_ENVIRONMENT, view);
+ if (srl->passflag & SCE_PASS_INDIRECT)
+ render_layer_add_pass(rr, rl, 3, SCE_PASS_INDIRECT, view);
+ if (srl->passflag & SCE_PASS_SHADOW)
+ render_layer_add_pass(rr, rl, 3, SCE_PASS_SHADOW, view);
+ if (srl->passflag & SCE_PASS_REFLECT)
+ render_layer_add_pass(rr, rl, 3, SCE_PASS_REFLECT, view);
+ if (srl->passflag & SCE_PASS_REFRACT)
+ render_layer_add_pass(rr, rl, 3, SCE_PASS_REFRACT, view);
+ if (srl->passflag & SCE_PASS_INDEXOB)
+ render_layer_add_pass(rr, rl, 1, SCE_PASS_INDEXOB, view);
+ if (srl->passflag & SCE_PASS_INDEXMA)
+ render_layer_add_pass(rr, rl, 1, SCE_PASS_INDEXMA, view);
+ if (srl->passflag & SCE_PASS_MIST)
+ render_layer_add_pass(rr, rl, 1, SCE_PASS_MIST, view);
+ if (rl->passflag & SCE_PASS_RAYHITS)
+ render_layer_add_pass(rr, rl, 4, SCE_PASS_RAYHITS, view);
+ if (srl->passflag & SCE_PASS_DIFFUSE_DIRECT)
+ render_layer_add_pass(rr, rl, 3, SCE_PASS_DIFFUSE_DIRECT, view);
+ if (srl->passflag & SCE_PASS_DIFFUSE_INDIRECT)
+ render_layer_add_pass(rr, rl, 3, SCE_PASS_DIFFUSE_INDIRECT, view);
+ if (srl->passflag & SCE_PASS_DIFFUSE_COLOR)
+ render_layer_add_pass(rr, rl, 3, SCE_PASS_DIFFUSE_COLOR, view);
+ if (srl->passflag & SCE_PASS_GLOSSY_DIRECT)
+ render_layer_add_pass(rr, rl, 3, SCE_PASS_GLOSSY_DIRECT, view);
+ if (srl->passflag & SCE_PASS_GLOSSY_INDIRECT)
+ render_layer_add_pass(rr, rl, 3, SCE_PASS_GLOSSY_INDIRECT, view);
+ if (srl->passflag & SCE_PASS_GLOSSY_COLOR)
+ render_layer_add_pass(rr, rl, 3, SCE_PASS_GLOSSY_COLOR, view);
+ if (srl->passflag & SCE_PASS_TRANSM_DIRECT)
+ render_layer_add_pass(rr, rl, 3, SCE_PASS_TRANSM_DIRECT, view);
+ if (srl->passflag & SCE_PASS_TRANSM_INDIRECT)
+ render_layer_add_pass(rr, rl, 3, SCE_PASS_TRANSM_INDIRECT, view);
+ if (srl->passflag & SCE_PASS_TRANSM_COLOR)
+ render_layer_add_pass(rr, rl, 3, SCE_PASS_TRANSM_COLOR, view);
+ if (srl->passflag & SCE_PASS_SUBSURFACE_DIRECT)
+ render_layer_add_pass(rr, rl, 3, SCE_PASS_SUBSURFACE_DIRECT, view);
+ if (srl->passflag & SCE_PASS_SUBSURFACE_INDIRECT)
+ render_layer_add_pass(rr, rl, 3, SCE_PASS_SUBSURFACE_INDIRECT, view);
+ if (srl->passflag & SCE_PASS_SUBSURFACE_COLOR)
+ render_layer_add_pass(rr, rl, 3, SCE_PASS_SUBSURFACE_COLOR, view);
+
+#ifdef WITH_CYCLES_DEBUG
+ if (BKE_scene_use_new_shading_nodes(re->scene)) {
+ render_layer_add_debug_pass(rr, rl, SCE_PASS_DEBUG,
+ re->r.debug_pass_type, view);
+ }
+#endif
}
- else
- rl->rectf = MEM_mapallocN(rectx * recty * sizeof(float) * 4, "Combined rgba");
-
- if (srl->passflag & SCE_PASS_Z)
- render_layer_add_pass(rr, rl, 1, SCE_PASS_Z);
- if (srl->passflag & SCE_PASS_VECTOR)
- render_layer_add_pass(rr, rl, 4, SCE_PASS_VECTOR);
- if (srl->passflag & SCE_PASS_NORMAL)
- render_layer_add_pass(rr, rl, 3, SCE_PASS_NORMAL);
- if (srl->passflag & SCE_PASS_UV)
- render_layer_add_pass(rr, rl, 3, SCE_PASS_UV);
- if (srl->passflag & SCE_PASS_RGBA)
- render_layer_add_pass(rr, rl, 4, SCE_PASS_RGBA);
- if (srl->passflag & SCE_PASS_EMIT)
- render_layer_add_pass(rr, rl, 3, SCE_PASS_EMIT);
- if (srl->passflag & SCE_PASS_DIFFUSE)
- render_layer_add_pass(rr, rl, 3, SCE_PASS_DIFFUSE);
- if (srl->passflag & SCE_PASS_SPEC)
- render_layer_add_pass(rr, rl, 3, SCE_PASS_SPEC);
- if (srl->passflag & SCE_PASS_AO)
- render_layer_add_pass(rr, rl, 3, SCE_PASS_AO);
- if (srl->passflag & SCE_PASS_ENVIRONMENT)
- render_layer_add_pass(rr, rl, 3, SCE_PASS_ENVIRONMENT);
- if (srl->passflag & SCE_PASS_INDIRECT)
- render_layer_add_pass(rr, rl, 3, SCE_PASS_INDIRECT);
- if (srl->passflag & SCE_PASS_SHADOW)
- render_layer_add_pass(rr, rl, 3, SCE_PASS_SHADOW);
- if (srl->passflag & SCE_PASS_REFLECT)
- render_layer_add_pass(rr, rl, 3, SCE_PASS_REFLECT);
- if (srl->passflag & SCE_PASS_REFRACT)
- render_layer_add_pass(rr, rl, 3, SCE_PASS_REFRACT);
- if (srl->passflag & SCE_PASS_INDEXOB)
- render_layer_add_pass(rr, rl, 1, SCE_PASS_INDEXOB);
- if (srl->passflag & SCE_PASS_INDEXMA)
- render_layer_add_pass(rr, rl, 1, SCE_PASS_INDEXMA);
- if (srl->passflag & SCE_PASS_MIST)
- render_layer_add_pass(rr, rl, 1, SCE_PASS_MIST);
- if (rl->passflag & SCE_PASS_RAYHITS)
- render_layer_add_pass(rr, rl, 4, SCE_PASS_RAYHITS);
- if (srl->passflag & SCE_PASS_DIFFUSE_DIRECT)
- render_layer_add_pass(rr, rl, 3, SCE_PASS_DIFFUSE_DIRECT);
- if (srl->passflag & SCE_PASS_DIFFUSE_INDIRECT)
- render_layer_add_pass(rr, rl, 3, SCE_PASS_DIFFUSE_INDIRECT);
- if (srl->passflag & SCE_PASS_DIFFUSE_COLOR)
- render_layer_add_pass(rr, rl, 3, SCE_PASS_DIFFUSE_COLOR);
- if (srl->passflag & SCE_PASS_GLOSSY_DIRECT)
- render_layer_add_pass(rr, rl, 3, SCE_PASS_GLOSSY_DIRECT);
- if (srl->passflag & SCE_PASS_GLOSSY_INDIRECT)
- render_layer_add_pass(rr, rl, 3, SCE_PASS_GLOSSY_INDIRECT);
- if (srl->passflag & SCE_PASS_GLOSSY_COLOR)
- render_layer_add_pass(rr, rl, 3, SCE_PASS_GLOSSY_COLOR);
- if (srl->passflag & SCE_PASS_TRANSM_DIRECT)
- render_layer_add_pass(rr, rl, 3, SCE_PASS_TRANSM_DIRECT);
- if (srl->passflag & SCE_PASS_TRANSM_INDIRECT)
- render_layer_add_pass(rr, rl, 3, SCE_PASS_TRANSM_INDIRECT);
- if (srl->passflag & SCE_PASS_TRANSM_COLOR)
- render_layer_add_pass(rr, rl, 3, SCE_PASS_TRANSM_COLOR);
- if (srl->passflag & SCE_PASS_SUBSURFACE_DIRECT)
- render_layer_add_pass(rr, rl, 3, SCE_PASS_SUBSURFACE_DIRECT);
- if (srl->passflag & SCE_PASS_SUBSURFACE_INDIRECT)
- render_layer_add_pass(rr, rl, 3, SCE_PASS_SUBSURFACE_INDIRECT);
- if (srl->passflag & SCE_PASS_SUBSURFACE_COLOR)
- render_layer_add_pass(rr, rl, 3, SCE_PASS_SUBSURFACE_COLOR);
}
/* sss, previewrender and envmap don't do layers, so we make a default one */
if (BLI_listbase_is_empty(&rr->layers) && !(layername && layername[0])) {
@@ -590,18 +737,23 @@ RenderResult *render_result_new(Render *re, rcti *partrct, int crop, int savebuf
/* duplicate code... */
if (rr->do_exr_tile) {
rl->display_buffer = MEM_mapallocN(rectx * recty * sizeof(unsigned int), "Combined display space rgba");
-
rl->exrhandle = IMB_exr_get_handle();
-
- IMB_exr_add_channel(rl->exrhandle, rl->name, "Combined.R", 0, 0, NULL);
- IMB_exr_add_channel(rl->exrhandle, rl->name, "Combined.G", 0, 0, NULL);
- IMB_exr_add_channel(rl->exrhandle, rl->name, "Combined.B", 0, 0, NULL);
- IMB_exr_add_channel(rl->exrhandle, rl->name, "Combined.A", 0, 0, NULL);
}
- else {
- rl->rectf = MEM_mapallocN(rectx * recty * sizeof(float) * 4, "Combined rgba");
+
+ for (rv = rr->views.first; rv; rv = rv->next) {
+ const char *view = rv->name;
+
+ if (viewname && viewname[0])
+ if (strcmp(view, viewname) != 0)
+ continue;
+
+ if (rr->do_exr_tile)
+ IMB_exr_add_view(rl->exrhandle, view);
+
+ /* a renderlayer should always have a Combined pass */
+ render_layer_add_pass(rr, rl, 4, SCE_PASS_COMBINED, view);
}
-
+
/* note, this has to be in sync with scene.c */
rl->lay = (1 << 20) - 1;
rl->layflag = 0x7FFF; /* solid ztra halo strand */
@@ -619,15 +771,15 @@ RenderResult *render_result_new(Render *re, rcti *partrct, int crop, int savebuf
}
/* allocate osa new results for samples */
-RenderResult *render_result_new_full_sample(Render *re, ListBase *lb, rcti *partrct, int crop, int savebuffers)
+RenderResult *render_result_new_full_sample(Render *re, ListBase *lb, rcti *partrct, int crop, int savebuffers, const char *viewname)
{
int a;
if (re->osa == 0)
- return render_result_new(re, partrct, crop, savebuffers, RR_ALL_LAYERS);
+ return render_result_new(re, partrct, crop, savebuffers, RR_ALL_LAYERS, viewname);
for (a = 0; a < re->osa; a++) {
- RenderResult *rr = render_result_new(re, partrct, crop, savebuffers, RR_ALL_LAYERS);
+ RenderResult *rr = render_result_new(re, partrct, crop, savebuffers, RR_ALL_LAYERS, viewname);
BLI_addtail(lb, rr);
rr->sample_nr = a;
}
@@ -648,28 +800,98 @@ static void *ml_addlayer_cb(void *base, const char *str)
return rl;
}
-static void ml_addpass_cb(void *UNUSED(base), void *lay, const char *str, float *rect, int totchan, const char *chan_id)
+static void ml_addpass_cb(void *base, void *lay, const char *str, float *rect, int totchan, const char *chan_id, const char *view)
{
+ RenderResult *rr = base;
RenderLayer *rl = lay;
RenderPass *rpass = MEM_callocN(sizeof(RenderPass), "loaded pass");
int a;
BLI_addtail(&rl->passes, rpass);
rpass->channels = totchan;
-
rpass->passtype = passtype_from_name(str);
if (rpass->passtype == 0) printf("unknown pass %s\n", str);
rl->passflag |= rpass->passtype;
- BLI_strncpy(rpass->name, str, EXR_PASS_MAXNAME);
/* channel id chars */
for (a = 0; a < totchan; a++)
rpass->chan_id[a] = chan_id[a];
-
+
rpass->rect = rect;
+ if (view[0] != '\0') {
+ BLI_snprintf(rpass->name, sizeof(rpass->name), "%s.%s", str, view);
+ rpass->view_id = BLI_findstringindex(&rr->views, view, offsetof(RenderView, name));
+ }
+ else {
+ BLI_strncpy(rpass->name, str, sizeof(rpass->name));
+ rpass->view_id = 0;
+ }
+
+ BLI_strncpy(rpass->view, view, sizeof(rpass->view));
+ BLI_strncpy(rpass->internal_name, str, sizeof(rpass->internal_name));
+}
+
+static void *ml_addview_cb(void *base, const char *str)
+{
+ RenderResult *rr = base;
+ RenderView *rv;
+
+ rv = MEM_callocN(sizeof(RenderView), "new render view");
+ BLI_strncpy(rv->name, str, EXR_VIEW_MAXNAME);
+
+ /* For stereo drawing we need to ensure:
+ * STEREO_LEFT_NAME == STEREO_LEFT_ID and
+ * STEREO_RIGHT_NAME == STEREO_RIGHT_ID */
+
+ if (STREQ(str, STEREO_LEFT_NAME)) {
+ BLI_addhead(&rr->views, rv);
+ }
+ else if (STREQ(str, STEREO_RIGHT_NAME)) {
+ RenderView *left_rv = BLI_findstring(&rr->views, STEREO_LEFT_NAME, offsetof(RenderView, name));
+
+ if (left_rv == NULL) {
+ BLI_addhead(&rr->views, rv);
+ }
+ else {
+ BLI_insertlinkafter(&rr->views, left_rv, rv);
+ }
+ }
+ else {
+ BLI_addtail(&rr->views, rv);
+ }
+
+ return rv;
}
-/* from imbuf, if a handle was returned we convert this to render result */
+static int order_render_passes(const void *a, const void *b)
+{
+ // 1 if a is after b
+ RenderPass *rpa = (RenderPass *) a;
+ RenderPass *rpb = (RenderPass *) b;
+
+ if (rpa->passtype > rpb->passtype)
+ return 1;
+ else if (rpa->passtype < rpb->passtype)
+ return 0;
+
+ /* they have the same type */
+ /* left first */
+ if (STREQ(rpa->view, STEREO_LEFT_NAME))
+ return 0;
+ else if (STREQ(rpb->view, STEREO_LEFT_NAME))
+ return 1;
+
+ /* right second */
+ if (STREQ(rpa->view, STEREO_RIGHT_NAME))
+ return 0;
+ else if (STREQ(rpb->view, STEREO_RIGHT_NAME))
+ return 1;
+
+ /* remaining in ascending id order */
+ return (rpa->view_id < rpb->view_id);
+}
+
+/* from imbuf, if a handle was returned and it's not a singlelayer multiview we convert this to render result */
RenderResult *render_result_new_from_exr(void *exrhandle, const char *colorspace, bool predivide, int rectx, int recty)
{
RenderResult *rr = MEM_callocN(sizeof(RenderResult), __func__);
@@ -680,12 +902,14 @@ RenderResult *render_result_new_from_exr(void *exrhandle, const char *colorspace
rr->rectx = rectx;
rr->recty = recty;
- IMB_exr_multilayer_convert(exrhandle, rr, ml_addlayer_cb, ml_addpass_cb);
+ IMB_exr_multilayer_convert(exrhandle, rr, ml_addview_cb, ml_addlayer_cb, ml_addpass_cb);
for (rl = rr->layers.first; rl; rl = rl->next) {
rl->rectx = rectx;
rl->recty = recty;
+ BLI_listbase_sort(&rl->passes, order_render_passes);
+
for (rpass = rl->passes.first; rpass; rpass = rpass->next) {
rpass->rectx = rectx;
rpass->recty = recty;
@@ -700,26 +924,56 @@ RenderResult *render_result_new_from_exr(void *exrhandle, const char *colorspace
return rr;
}
+void render_result_view_new(RenderResult *rr, const char *viewname)
+{
+ RenderView *rv = MEM_callocN(sizeof(RenderView), "new render view");
+ BLI_addtail(&rr->views, rv);
+ BLI_strncpy(rv->name, viewname, sizeof(rv->name));
+}
+
+void render_result_views_new(RenderResult *rr, RenderData *rd)
+{
+ SceneRenderView *srv;
+
+ /* clear previously existing views - for sequencer */
+ render_result_views_free(rr);
+
+ /* check renderdata for amount of views */
+ if ((rd->scemode & R_MULTIVIEW)) {
+ for (srv = rd->views.first; srv; srv = srv->next) {
+ if (BKE_scene_multiview_is_render_view_active(rd, srv) == false)
+ continue;
+ render_result_view_new(rr, srv->name);
+ }
+ }
+
+ /* we always need at least one view */
+ if (BLI_listbase_count_ex(&rr->views, 1) == 0) {
+ render_result_view_new(rr, "");
+ }
+}
+
/*********************************** Merge ***********************************/
static void do_merge_tile(RenderResult *rr, RenderResult *rrpart, float *target, float *tile, int pixsize)
{
- int y, ofs, copylen, tilex, tiley;
+ int y, tilex, tiley;
+ size_t ofs, copylen;
copylen = tilex = rrpart->rectx;
tiley = rrpart->recty;
if (rrpart->crop) { /* filters add pixel extra */
- tile += pixsize * (rrpart->crop + rrpart->crop * tilex);
+ tile += pixsize * (rrpart->crop + ((size_t)rrpart->crop) * tilex);
copylen = tilex - 2 * rrpart->crop;
tiley -= 2 * rrpart->crop;
- ofs = (rrpart->tilerect.ymin + rrpart->crop) * rr->rectx + (rrpart->tilerect.xmin + rrpart->crop);
+ ofs = (((size_t)rrpart->tilerect.ymin) + rrpart->crop) * rr->rectx + (rrpart->tilerect.xmin + rrpart->crop);
target += pixsize * ofs;
}
else {
- ofs = (rrpart->tilerect.ymin * rr->rectx + rrpart->tilerect.xmin);
+ ofs = (((size_t)rrpart->tilerect.ymin) * rr->rectx + rrpart->tilerect.xmin);
target += pixsize * ofs;
}
@@ -745,16 +999,19 @@ void render_result_merge(RenderResult *rr, RenderResult *rrpart)
for (rl = rr->layers.first; rl; rl = rl->next) {
rlp = RE_GetRenderLayer(rrpart, rl->name);
if (rlp) {
- /* combined */
- if (rl->rectf && rlp->rectf)
- do_merge_tile(rr, rrpart, rl->rectf, rlp->rectf, 4);
-
/* passes are allocated in sync */
for (rpass = rl->passes.first, rpassp = rlp->passes.first;
rpass && rpassp;
- rpass = rpass->next, rpassp = rpassp->next)
+ rpass = rpass->next)
{
+ /* renderresult have all passes, renderpart only the active view's passes */
+ if (strcmp(rpassp->name, rpass->name) != 0)
+ continue;
+
do_merge_tile(rr, rrpart, rpass->rect, rpassp->rect, rpass->channels);
+
+ /* manually get next render pass */
+ rpassp = rpassp->next;
}
}
}
@@ -763,7 +1020,7 @@ void render_result_merge(RenderResult *rr, RenderResult *rrpart)
/* for passes read from files, these have names stored */
static char *make_pass_name(RenderPass *rpass, int chan)
{
- static char name[16];
+ static char name[EXR_PASS_MAXNAME];
int len;
BLI_strncpy(name, rpass->name, EXR_PASS_MAXNAME);
@@ -775,55 +1032,111 @@ static char *make_pass_name(RenderPass *rpass, int chan)
return name;
}
-/* filename already made absolute */
-/* called from within UI, saves both rendered result as a file-read result */
-bool RE_WriteRenderResult(ReportList *reports, RenderResult *rr, const char *filename, int compress)
+/* called from within UI and render pipeline, saves both rendered result as a file-read result
+ * if multiview is true saves all views in a multiview exr
+ * else if view is not NULL saves single view
+ * else saves stereo3d
+ */
+bool RE_WriteRenderResult(ReportList *reports, RenderResult *rr, const char *filename, ImageFormatData *imf, const bool multiview, const char *view)
{
RenderLayer *rl;
RenderPass *rpass;
+ RenderView *rview;
void *exrhandle = IMB_exr_get_handle();
bool success;
-
- BLI_make_existing_file(filename);
-
- /* composite result */
- if (rr->rectf) {
- IMB_exr_add_channel(exrhandle, "Composite", "Combined.R", 4, 4 * rr->rectx, rr->rectf);
- IMB_exr_add_channel(exrhandle, "Composite", "Combined.G", 4, 4 * rr->rectx, rr->rectf + 1);
- IMB_exr_add_channel(exrhandle, "Composite", "Combined.B", 4, 4 * rr->rectx, rr->rectf + 2);
- IMB_exr_add_channel(exrhandle, "Composite", "Combined.A", 4, 4 * rr->rectx, rr->rectf + 3);
+ int a, nr;
+ const char *chan_view = NULL;
+ int compress = (imf ? imf->exr_codec : 0);
+ size_t width, height;
+
+ const bool is_mono = view && !multiview;
+ const bool use_half_float = (imf != NULL) ? (imf->depth == R_IMF_CHAN_DEPTH_16) : false;
+
+ width = rr->rectx;
+ height = rr->recty;
+
+ if (imf && imf->imtype == R_IMF_IMTYPE_OPENEXR && multiview) {
+ /* single layer OpenEXR */
+ const char *RGBAZ[] = {"R", "G", "B", "A", "Z"};
+ for (nr = 0, rview = rr->views.first; rview; rview = rview->next, nr++) {
+ IMB_exr_add_view(exrhandle, rview->name);
+
+ if (rview->rectf) {
+ for (a = 0; a < 4; a++) {
+ IMB_exr_add_channel(exrhandle, "", RGBAZ[a],
+ rview->name, 4, 4 * width, rview->rectf + a,
+ use_half_float);
+ }
+ if (rview->rectz) {
+ /* Z pass is always stored as float. */
+ IMB_exr_add_channel(exrhandle, "", RGBAZ[4],
+ rview->name, 1, width, rview->rectz,
+ false);
+ }
+ }
+ }
}
-
- /* add layers/passes and assign channels */
- for (rl = rr->layers.first; rl; rl = rl->next) {
-
- /* combined */
- if (rl->rectf) {
- int a, xstride = 4;
- for (a = 0; a < xstride; a++) {
- IMB_exr_add_channel(exrhandle, rl->name, get_pass_name(SCE_PASS_COMBINED, a),
- xstride, xstride * rr->rectx, rl->rectf + a);
+ else {
+ for (nr = 0, rview = rr->views.first; rview; rview = rview->next, nr++) {
+ if (is_mono) {
+ if (!STREQ(view, rview->name)) {
+ continue;
+ }
+ chan_view = "";
+ }
+ else {
+ /* if rendered only one view, we treat as a a non-view render */
+ chan_view = rview->name;
+ }
+
+ IMB_exr_add_view(exrhandle, rview->name);
+
+ if (rview->rectf) {
+ for (a = 0; a < 4; a++) {
+ IMB_exr_add_channel(exrhandle, "Composite", name_from_passtype(SCE_PASS_COMBINED, a),
+ chan_view, 4, 4 * width, rview->rectf + a,
+ use_half_float);
+ }
}
}
-
- /* passes are allocated in sync */
- for (rpass = rl->passes.first; rpass; rpass = rpass->next) {
- int a, xstride = rpass->channels;
- for (a = 0; a < xstride; a++) {
- if (rpass->passtype) {
- IMB_exr_add_channel(exrhandle, rl->name, get_pass_name(rpass->passtype, a),
- xstride, xstride * rr->rectx, rpass->rect + a);
+
+ /* add layers/passes and assign channels */
+ for (rl = rr->layers.first; rl; rl = rl->next) {
+
+ /* passes are allocated in sync */
+ for (rpass = rl->passes.first; rpass; rpass = rpass->next) {
+ const int xstride = rpass->channels;
+
+ if (is_mono) {
+ if (!STREQ(view, rpass->view)) {
+ continue;
+ }
+ chan_view = "";
}
else {
- IMB_exr_add_channel(exrhandle, rl->name, make_pass_name(rpass, a),
- xstride, xstride * rr->rectx, rpass->rect + a);
+ /* if rendered only one view, we treat as a a non-view render */
+ chan_view = (nr > 1 ? rpass->view :"");
+ }
+
+ for (a = 0; a < xstride; a++) {
+ if (rpass->passtype) {
+ IMB_exr_add_channel(exrhandle, rl->name, name_from_passtype(rpass->passtype, a), chan_view,
+ xstride, xstride * width, rpass->rect + a,
+ rpass->passtype == SCE_PASS_Z ? false : use_half_float);
+ }
+ else {
+ IMB_exr_add_channel(exrhandle, rl->name, make_pass_name(rpass, a), chan_view,
+ xstride, xstride * width, rpass->rect + a,
+ use_half_float);
+ }
}
}
}
}
- /* when the filename has no permissions, this can fail */
- if (IMB_exr_begin_write(exrhandle, filename, rr->rectx, rr->recty, compress)) {
+ BLI_make_existing_file(filename);
+
+ if (IMB_exr_begin_write(exrhandle, filename, width, height, compress, rr->stamp_data)) {
IMB_exr_write_channels(exrhandle);
success = true;
}
@@ -832,8 +1145,8 @@ bool RE_WriteRenderResult(ReportList *reports, RenderResult *rr, const char *fil
BKE_report(reports, RPT_ERROR, "Error writing render result (see console)");
success = false;
}
- IMB_exr_close(exrhandle);
+ IMB_exr_close(exrhandle);
return success;
}
@@ -894,7 +1207,7 @@ void render_result_single_layer_end(Render *re)
/************************* EXR Tile File Rendering ***************************/
-static void save_render_result_tile(RenderResult *rr, RenderResult *rrpart)
+static void save_render_result_tile(RenderResult *rr, RenderResult *rrpart, const char *viewname)
{
RenderLayer *rlp, *rl;
RenderPass *rpassp;
@@ -917,21 +1230,17 @@ static void save_render_result_tile(RenderResult *rr, RenderResult *rrpart)
else {
offs = 0;
}
-
- /* combined */
- if (rlp->rectf) {
- int a, xstride = 4;
- for (a = 0; a < xstride; a++) {
- IMB_exr_set_channel(rl->exrhandle, rlp->name, get_pass_name(SCE_PASS_COMBINED, a),
- xstride, xstride * rrpart->rectx, rlp->rectf + a + xstride * offs);
- }
- }
-
+
/* passes are allocated in sync */
for (rpassp = rlp->passes.first; rpassp; rpassp = rpassp->next) {
- int a, xstride = rpassp->channels;
+ const int xstride = rpassp->channels;
+ int a;
+ char passname[EXR_PASS_MAXNAME];
+
for (a = 0; a < xstride; a++) {
- IMB_exr_set_channel(rl->exrhandle, rlp->name, get_pass_name(rpassp->passtype, a),
+ set_pass_name(passname, rpassp->passtype, a, rpassp->view);
+
+ IMB_exr_set_channel(rl->exrhandle, rlp->name, passname,
xstride, xstride * rrpart->rectx, rpassp->rect + a + xstride * offs);
}
}
@@ -950,13 +1259,13 @@ static void save_render_result_tile(RenderResult *rr, RenderResult *rrpart)
continue;
}
- IMB_exrtile_write_channels(rl->exrhandle, partx, party, 0);
+ IMB_exrtile_write_channels(rl->exrhandle, partx, party, 0, viewname);
}
BLI_unlock_thread(LOCK_IMAGE);
}
-static void save_empty_result_tiles(Render *re)
+void render_result_save_empty_result_tiles(Render *re)
{
RenderPart *pa;
RenderResult *rr;
@@ -964,13 +1273,13 @@ static void save_empty_result_tiles(Render *re)
for (rr = re->result; rr; rr = rr->next) {
for (rl = rr->layers.first; rl; rl = rl->next) {
- IMB_exrtile_clear_channels(rl->exrhandle);
+ IMB_exr_clear_channels(rl->exrhandle);
for (pa = re->parts.first; pa; pa = pa->next) {
if (pa->status != PART_STATUS_READY) {
int party = pa->disprect.ymin - re->disprect.ymin + pa->crop;
int partx = pa->disprect.xmin - re->disprect.xmin + pa->crop;
- IMB_exrtile_write_channels(rl->exrhandle, partx, party, 0);
+ IMB_exrtile_write_channels(rl->exrhandle, partx, party, 0, re->viewname);
}
}
}
@@ -999,8 +1308,6 @@ void render_result_exr_file_end(Render *re)
RenderResult *rr;
RenderLayer *rl;
- save_empty_result_tiles(re);
-
for (rr = re->result; rr; rr = rr->next) {
for (rl = rr->layers.first; rl; rl = rl->next) {
IMB_exr_close(rl->exrhandle);
@@ -1017,18 +1324,18 @@ void render_result_exr_file_end(Render *re)
}
/* save part into exr file */
-void render_result_exr_file_merge(RenderResult *rr, RenderResult *rrpart)
+void render_result_exr_file_merge(RenderResult *rr, RenderResult *rrpart, const char *viewname)
{
for (; rr && rrpart; rr = rr->next, rrpart = rrpart->next)
- save_render_result_tile(rr, rrpart);
+ save_render_result_tile(rr, rrpart, viewname);
}
/* path to temporary exr file */
void render_result_exr_file_path(Scene *scene, const char *layname, int sample, char *filepath)
{
- char name[FILE_MAXFILE + MAX_ID_NAME + MAX_ID_NAME + 100], fi[FILE_MAXFILE];
+ char name[FILE_MAXFILE + MAX_ID_NAME + MAX_ID_NAME + 100];
+ const char *fi = BLI_path_basename(G.main->name);
- BLI_split_file_part(G.main->name, fi, sizeof(fi));
if (sample == 0) {
BLI_snprintf(name, sizeof(name), "%s_%s_%s.exr", fi, scene->id.name + 2, layname);
}
@@ -1036,7 +1343,10 @@ void render_result_exr_file_path(Scene *scene, const char *layname, int sample,
BLI_snprintf(name, sizeof(name), "%s_%s_%s%d.exr", fi, scene->id.name + 2, layname, sample);
}
- BLI_make_file_string("/", filepath, BLI_temp_dir_session(), name);
+ /* Make name safe for paths, see T43275. */
+ BLI_filename_make_safe(name);
+
+ BLI_make_file_string("/", filepath, BKE_tempdir_session(), name);
}
/* only for temp buffer, makes exact copy of render result */
@@ -1047,7 +1357,7 @@ int render_result_exr_file_read_sample(Render *re, int sample)
bool success = true;
RE_FreeRenderResult(re->result);
- re->result = render_result_new(re, &re->disprect, 0, RR_USE_MEM, RR_ALL_LAYERS);
+ re->result = render_result_new(re, &re->disprect, 0, RR_USE_MEM, RR_ALL_LAYERS, RR_ALL_VIEWS);
for (rl = re->result->layers.first; rl; rl = rl->next) {
render_result_exr_file_path(re->scene, rl->name, sample, str);
@@ -1088,23 +1398,20 @@ int render_result_exr_file_read_path(RenderResult *rr, RenderLayer *rl_single, c
for (rl = rr->layers.first; rl; rl = rl->next) {
if (rl_single && rl_single != rl)
continue;
-
- /* combined */
- if (rl->rectf) {
- int a, xstride = 4;
- for (a = 0; a < xstride; a++)
- IMB_exr_set_channel(exrhandle, rl->name, get_pass_name(SCE_PASS_COMBINED, a),
- xstride, xstride * rectx, rl->rectf + a);
- }
/* passes are allocated in sync */
for (rpass = rl->passes.first; rpass; rpass = rpass->next) {
- int a, xstride = rpass->channels;
- for (a = 0; a < xstride; a++)
- IMB_exr_set_channel(exrhandle, rl->name, get_pass_name(rpass->passtype, a),
+ const int xstride = rpass->channels;
+ int a;
+ char passname[EXR_PASS_MAXNAME];
+
+ for (a = 0; a < xstride; a++) {
+ set_pass_name(passname, rpass->passtype, a, rpass->view);
+ IMB_exr_set_channel(exrhandle, rl->name, passname,
xstride, xstride * rectx, rpass->rect + a);
+ }
- BLI_strncpy(rpass->name, get_pass_name(rpass->passtype, -1), sizeof(rpass->name));
+ set_pass_name(rpass->name, rpass->passtype, -1, rpass->view);
}
}
@@ -1124,17 +1431,17 @@ static void render_result_exr_file_cache_path(Scene *sce, const char *root, char
if (G.main->name[0]) {
BLI_split_dirfile(G.main->name, dirname, filename, sizeof(dirname), sizeof(filename));
BLI_replace_extension(filename, sizeof(filename), ""); /* strip '.blend' */
- md5_buffer(G.main->name, strlen(G.main->name), path_digest);
+ BLI_hash_md5_buffer(G.main->name, strlen(G.main->name), path_digest);
}
else {
- BLI_strncpy(dirname, BLI_temp_dir_base(), sizeof(dirname));
+ BLI_strncpy(dirname, BKE_tempdir_base(), sizeof(dirname));
BLI_strncpy(filename, "UNSAVED", sizeof(filename));
}
- md5_to_hexdigest(path_digest, path_hexdigest);
+ BLI_hash_md5_to_hexdigest(path_digest, path_hexdigest);
/* Default to *non-volatile* tmp dir. */
if (*root == '\0') {
- root = BLI_temp_dir_base();
+ root = BKE_tempdir_base();
}
BLI_snprintf(filename_full, sizeof(filename_full), "cached_RR_%s_%s_%s.exr",
@@ -1150,7 +1457,8 @@ void render_result_exr_file_cache_write(Render *re)
render_result_exr_file_cache_path(re->scene, root, str);
printf("Caching exr file, %dx%d, %s\n", rr->rectx, rr->recty, str);
- RE_WriteRenderResult(NULL, rr, str, 0);
+
+ RE_WriteRenderResult(NULL, rr, str, NULL, true, NULL);
}
/* For cache, makes exact copy of render result */
@@ -1160,7 +1468,7 @@ bool render_result_exr_file_cache_read(Render *re)
char *root = U.render_cachedir;
RE_FreeRenderResult(re->result);
- re->result = render_result_new(re, &re->disprect, 0, RR_USE_MEM, RR_ALL_LAYERS);
+ re->result = render_result_new(re, &re->disprect, 0, RR_USE_MEM, RR_ALL_LAYERS, RR_ALL_VIEWS);
/* First try cache. */
render_result_exr_file_cache_path(re->scene, root, str);
@@ -1175,15 +1483,16 @@ bool render_result_exr_file_cache_read(Render *re)
/*************************** Combined Pixel Rect *****************************/
-ImBuf *render_result_rect_to_ibuf(RenderResult *rr, RenderData *rd)
+ImBuf *render_result_rect_to_ibuf(RenderResult *rr, RenderData *rd, const int view_id)
{
ImBuf *ibuf = IMB_allocImBuf(rr->rectx, rr->recty, rd->im_format.planes, 0);
-
+ RenderView *rv = RE_RenderViewGetById(rr, view_id);
+
/* if not exists, BKE_imbuf_write makes one */
- ibuf->rect = (unsigned int *)rr->rect32;
- ibuf->rect_float = rr->rectf;
- ibuf->zbuf_float = rr->rectz;
-
+ ibuf->rect = (unsigned int *) rv->rect32;
+ ibuf->rect_float = rv->rectf;
+ ibuf->zbuf_float = rv->rectz;
+
/* float factor for random dither, imbuf takes care of it */
ibuf->dither = rd->dither_intensity;
@@ -1218,57 +1527,97 @@ ImBuf *render_result_rect_to_ibuf(RenderResult *rr, RenderData *rd)
return ibuf;
}
-void render_result_rect_from_ibuf(RenderResult *rr, RenderData *UNUSED(rd), ImBuf *ibuf)
+void render_result_rect_from_ibuf(RenderResult *rr, RenderData *UNUSED(rd), ImBuf *ibuf, const int view_id)
{
+ RenderView *rv = RE_RenderViewGetById(rr, view_id);
+
if (ibuf->rect_float) {
- if (!rr->rectf)
- rr->rectf = MEM_mallocN(4 * sizeof(float) * rr->rectx * rr->recty, "render_seq rectf");
+ if (!rv->rectf)
+ rv->rectf = MEM_mallocN(4 * sizeof(float) * rr->rectx * rr->recty, "render_seq rectf");
- memcpy(rr->rectf, ibuf->rect_float, 4 * sizeof(float) * rr->rectx * rr->recty);
+ memcpy(rv->rectf, ibuf->rect_float, 4 * sizeof(float) * rr->rectx * rr->recty);
/* TSK! Since sequence render doesn't free the *rr render result, the old rect32
* can hang around when sequence render has rendered a 32 bits one before */
- if (rr->rect32) {
- MEM_freeN(rr->rect32);
- rr->rect32 = NULL;
- }
+ MEM_SAFE_FREE(rv->rect32);
}
else if (ibuf->rect) {
- if (!rr->rect32)
- rr->rect32 = MEM_mallocN(sizeof(int) * rr->rectx * rr->recty, "render_seq rect");
+ if (!rv->rect32)
+ rv->rect32 = MEM_mallocN(sizeof(int) * rr->rectx * rr->recty, "render_seq rect");
- memcpy(rr->rect32, ibuf->rect, 4 * rr->rectx * rr->recty);
+ memcpy(rv->rect32, ibuf->rect, 4 * rr->rectx * rr->recty);
/* Same things as above, old rectf can hang around from previous render. */
- if (rr->rectf) {
- MEM_freeN(rr->rectf);
- rr->rectf = NULL;
- }
+ MEM_SAFE_FREE(rv->rectf);
}
}
-void render_result_rect_fill_zero(RenderResult *rr)
+void render_result_rect_fill_zero(RenderResult *rr, const int view_id)
{
- if (rr->rectf)
- memset(rr->rectf, 0, 4 * sizeof(float) * rr->rectx * rr->recty);
- else if (rr->rect32)
- memset(rr->rect32, 0, 4 * rr->rectx * rr->recty);
+ RenderView *rv = RE_RenderViewGetById(rr, view_id);
+
+ if (rv->rectf)
+ memset(rv->rectf, 0, 4 * sizeof(float) * rr->rectx * rr->recty);
+ else if (rv->rect32)
+ memset(rv->rect32, 0, 4 * rr->rectx * rr->recty);
else
- rr->rect32 = MEM_callocN(sizeof(int) * rr->rectx * rr->recty, "render_seq rect");
+ rv->rect32 = MEM_callocN(sizeof(int) * rr->rectx * rr->recty, "render_seq rect");
}
void render_result_rect_get_pixels(RenderResult *rr, unsigned int *rect, int rectx, int recty,
- const ColorManagedViewSettings *view_settings, const ColorManagedDisplaySettings *display_settings)
+ const ColorManagedViewSettings *view_settings, const ColorManagedDisplaySettings *display_settings,
+ const int view_id)
{
- if (rr->rect32) {
- memcpy(rect, rr->rect32, sizeof(int) * rr->rectx * rr->recty);
- }
- else if (rr->rectf) {
- IMB_display_buffer_transform_apply((unsigned char *) rect, rr->rectf, rr->rectx, rr->recty, 4,
+ RenderView *rv = RE_RenderViewGetById(rr, view_id);
+
+ if (rv->rect32)
+ memcpy(rect, rv->rect32, sizeof(int) * rr->rectx * rr->recty);
+ else if (rv->rectf)
+ IMB_display_buffer_transform_apply((unsigned char *) rect, rv->rectf, rr->rectx, rr->recty, 4,
view_settings, display_settings, true);
- }
else
/* else fill with black */
memset(rect, 0, sizeof(int) * rectx * recty);
}
+
+/*************************** multiview functions *****************************/
+
+bool RE_HasFakeLayer(RenderResult *res)
+{
+ RenderView *rv;
+
+ if (res == NULL)
+ return false;
+
+ rv = res->views.first;
+ if (rv == NULL)
+ return false;
+
+ return (rv->rect32 || rv->rectf);
+}
+
+bool RE_RenderResult_is_stereo(RenderResult *res)
+{
+ if (! BLI_findstring(&res->views, STEREO_LEFT_NAME, offsetof(RenderView, name)))
+ return false;
+
+ if (! BLI_findstring(&res->views, STEREO_RIGHT_NAME, offsetof(RenderView, name)))
+ return false;
+
+ return true;
+}
+
+RenderView *RE_RenderViewGetById(RenderResult *res, const int view_id)
+{
+ RenderView *rv = BLI_findlink(&res->views, view_id);
+ BLI_assert(res->views.first);
+ return rv ? rv : res->views.first;
+}
+
+RenderView *RE_RenderViewGetByName(RenderResult *res, const char *viewname)
+{
+ RenderView *rv = BLI_findstring(&res->views, viewname, offsetof(RenderView, name));
+ BLI_assert(res->views.first);
+ return rv ? rv : res->views.first;
+}
diff --git a/source/blender/render/intern/source/render_texture.c b/source/blender/render/intern/source/render_texture.c
index ae01779e814..b282ec0593e 100644
--- a/source/blender/render/intern/source/render_texture.c
+++ b/source/blender/render/intern/source/render_texture.c
@@ -48,7 +48,6 @@
#include "DNA_node_types.h"
#include "IMB_imbuf_types.h"
-#include "IMB_imbuf.h"
#include "IMB_colormanagement.h"
#include "BKE_image.h"
@@ -68,9 +67,7 @@
#include "envmap.h"
#include "pointdensity.h"
#include "voxeldata.h"
-#include "renderpipeline.h"
#include "render_types.h"
-#include "rendercore.h"
#include "shading.h"
#include "texture.h"
#include "texture_ocean.h"
@@ -85,8 +82,19 @@
extern struct Render R;
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
+static RNG_THREAD_ARRAY *random_tex_array;
+void RE_init_texture_rng(void)
+{
+ random_tex_array = BLI_rng_threaded_new();
+}
+
+void RE_exit_texture_rng(void)
+{
+ BLI_rng_threaded_free(random_tex_array);
+}
+
static void init_render_texture(Render *re, Tex *tex)
{
@@ -108,7 +116,7 @@ static void init_render_texture(Render *re, Tex *tex)
if (G.is_rendering && re) {
if (re->r.mode & R_ENVMAP)
if (tex->env->stype==ENV_ANIM)
- BKE_free_envmapdata(tex->env);
+ BKE_texture_envmap_free_data(tex->env);
}
}
}
@@ -212,10 +220,10 @@ static int blend(Tex *tex, const float texvec[3], TexResult *texres)
texres->tin= (2.0f+x+y)/4.0f;
}
else if (tex->stype==TEX_RAD) { /* radial */
- texres->tin = (atan2f(y, x) / (2 * M_PI) + 0.5f);
+ texres->tin = (atan2f(y, x) / (float)(2 * M_PI) + 0.5f);
}
else { /* sphere TEX_SPHERE */
- texres->tin = 1.0 - sqrtf(x * x + y * y + texvec[2] * texvec[2]);
+ texres->tin = 1.0f - sqrtf(x * x + y * y + texvec[2] * texvec[2]);
if (texres->tin<0.0f) texres->tin= 0.0f;
if (tex->stype==TEX_HALO) texres->tin*= texres->tin; /* halo */
}
@@ -266,7 +274,7 @@ static int clouds(Tex *tex, const float texvec[3], TexResult *texres)
/* creates a sine wave */
static float tex_sin(float a)
{
- a = 0.5 + 0.5 * sinf(a);
+ a = 0.5f + 0.5f * sinf(a);
return a;
}
@@ -709,19 +717,22 @@ static float voronoiTex(Tex *tex, const float texvec[3], TexResult *texres)
/* ------------------------------------------------------------------------- */
-static int texnoise(Tex *tex, TexResult *texres)
+static int texnoise(Tex *tex, TexResult *texres, int thread)
{
float div=3.0;
- int val, ran, loop;
+ int val, ran, loop, shift = 29;
- ran= BLI_rand();
- val= (ran & 3);
+ ran= BLI_rng_thread_rand(random_tex_array, thread);
loop= tex->noisedepth;
+
+ /* start from top bits since they have more variance */
+ val= ((ran >> shift) & 3);
+
while (loop--) {
- ran= (ran>>2);
- val*= (ran & 3);
- div*= 3.0f;
+ shift -= 2;
+ val *= ((ran >> shift) & 3);
+ div *= 3.0f;
}
texres->tin= ((float)val)/div;
@@ -1092,7 +1103,7 @@ static void do_2d_mapping(MTex *mtex, float texvec[3], VlakRen *vlr, const float
/* ************************************** */
-static int multitex(Tex *tex, float texvec[3], float dxt[3], float dyt[3], int osatex, TexResult *texres, const short thread, short which_output, struct ImagePool *pool)
+static int multitex(Tex *tex, float texvec[3], float dxt[3], float dyt[3], int osatex, TexResult *texres, const short thread, short which_output, struct ImagePool *pool, const bool skip_load_image)
{
float tmpvec[3];
int retval = 0; /* return value, int:0, col:1, nor:2, everything:3 */
@@ -1127,17 +1138,17 @@ static int multitex(Tex *tex, float texvec[3], float dxt[3], float dyt[3], int o
retval = stucci(tex, texvec, texres);
break;
case TEX_NOISE:
- retval = texnoise(tex, texres);
+ retval = texnoise(tex, texres, thread);
break;
case TEX_IMAGE:
- if (osatex) retval = imagewraposa(tex, tex->ima, NULL, texvec, dxt, dyt, texres, pool);
- else retval = imagewrap(tex, tex->ima, NULL, texvec, texres, pool);
+ if (osatex) retval = imagewraposa(tex, tex->ima, NULL, texvec, dxt, dyt, texres, pool, skip_load_image);
+ else retval = imagewrap(tex, tex->ima, NULL, texvec, texres, pool, skip_load_image);
if (tex->ima) {
BKE_image_tag_time(tex->ima);
}
break;
case TEX_ENVMAP:
- retval = envmaptex(tex, texvec, dxt, dyt, osatex, texres, pool);
+ retval = envmaptex(tex, texvec, dxt, dyt, osatex, texres, pool, skip_load_image);
break;
case TEX_MUSGRAVE:
/* newnoise: musgrave types */
@@ -1209,7 +1220,7 @@ static int multitex(Tex *tex, float texvec[3], float dxt[3], float dyt[3], int o
static int multitex_nodes_intern(Tex *tex, float texvec[3], float dxt[3], float dyt[3], int osatex, TexResult *texres,
const short thread, short which_output, ShadeInput *shi, MTex *mtex, struct ImagePool *pool,
- bool scene_color_manage)
+ bool scene_color_manage, const bool skip_load_image)
{
if (tex==NULL) {
memset(texres, 0, sizeof(TexResult));
@@ -1225,7 +1236,7 @@ static int multitex_nodes_intern(Tex *tex, float texvec[3], float dxt[3], float
if (mtex) {
/* we have mtex, use it for 2d mapping images only */
do_2d_mapping(mtex, texvec, shi->vlr, shi->facenor, dxt, dyt);
- rgbnor = multitex(tex, texvec, dxt, dyt, osatex, texres, thread, which_output, pool);
+ rgbnor = multitex(tex, texvec, dxt, dyt, osatex, texres, thread, which_output, pool, skip_load_image);
if (mtex->mapto & (MAP_COL+MAP_COLSPEC+MAP_COLMIR)) {
ImBuf *ibuf = BKE_image_pool_acquire_ibuf(tex->ima, &tex->iuser, pool);
@@ -1258,7 +1269,7 @@ static int multitex_nodes_intern(Tex *tex, float texvec[3], float dxt[3], float
}
do_2d_mapping(&localmtex, texvec_l, NULL, NULL, dxt_l, dyt_l);
- rgbnor = multitex(tex, texvec_l, dxt_l, dyt_l, osatex, texres, thread, which_output, pool);
+ rgbnor = multitex(tex, texvec_l, dxt_l, dyt_l, osatex, texres, thread, which_output, pool, skip_load_image);
{
ImBuf *ibuf = BKE_image_pool_acquire_ibuf(tex->ima, &tex->iuser, pool);
@@ -1274,7 +1285,7 @@ static int multitex_nodes_intern(Tex *tex, float texvec[3], float dxt[3], float
return rgbnor;
}
else {
- return multitex(tex, texvec, dxt, dyt, osatex, texres, thread, which_output, pool);
+ return multitex(tex, texvec, dxt, dyt, osatex, texres, thread, which_output, pool, skip_load_image);
}
}
@@ -1285,11 +1296,12 @@ int multitex_nodes(Tex *tex, float texvec[3], float dxt[3], float dyt[3], int os
const short thread, short which_output, ShadeInput *shi, MTex *mtex, struct ImagePool *pool)
{
return multitex_nodes_intern(tex, texvec, dxt, dyt, osatex, texres,
- thread, which_output, shi, mtex, pool, R.scene_color_manage);
+ thread, which_output, shi, mtex, pool, R.scene_color_manage,
+ (R.r.scemode & R_NO_IMAGE_LOAD) != 0);
}
/* this is called for surface shading */
-static int multitex_mtex(ShadeInput *shi, MTex *mtex, float texvec[3], float dxt[3], float dyt[3], TexResult *texres, struct ImagePool *pool)
+static int multitex_mtex(ShadeInput *shi, MTex *mtex, float texvec[3], float dxt[3], float dyt[3], TexResult *texres, struct ImagePool *pool, const bool skip_load_image)
{
Tex *tex = mtex->tex;
@@ -1300,7 +1312,7 @@ static int multitex_mtex(ShadeInput *shi, MTex *mtex, float texvec[3], float dxt
tex, mtex->which_output, R.r.cfra, (R.r.scemode & R_TEXNODE_PREVIEW) != 0, shi, mtex);
}
else {
- return multitex(mtex->tex, texvec, dxt, dyt, shi->osatex, texres, shi->thread, mtex->which_output, pool);
+ return multitex(mtex->tex, texvec, dxt, dyt, shi->osatex, texres, shi->thread, mtex->which_output, pool, skip_load_image);
}
}
@@ -1309,21 +1321,21 @@ static int multitex_mtex(ShadeInput *shi, MTex *mtex, float texvec[3], float dxt
*
* Use it for stuff which is out of render pipeline.
*/
-int multitex_ext(Tex *tex, float texvec[3], float dxt[3], float dyt[3], int osatex, TexResult *texres, struct ImagePool *pool, bool scene_color_manage)
+int multitex_ext(Tex *tex, float texvec[3], float dxt[3], float dyt[3], int osatex, TexResult *texres, struct ImagePool *pool, bool scene_color_manage, const bool skip_load_image)
{
- return multitex_nodes_intern(tex, texvec, dxt, dyt, osatex, texres, 0, 0, NULL, NULL, pool, scene_color_manage);
+ return multitex_nodes_intern(tex, texvec, dxt, dyt, osatex, texres, 0, 0, NULL, NULL, pool, scene_color_manage, skip_load_image);
}
/* extern-tex doesn't support nodes (ntreeBeginExec() can't be called when rendering is going on)\
*
* Use it for stuff which is out of render pipeline.
*/
-int multitex_ext_safe(Tex *tex, float texvec[3], TexResult *texres, struct ImagePool *pool, bool scene_color_manage)
+int multitex_ext_safe(Tex *tex, float texvec[3], TexResult *texres, struct ImagePool *pool, bool scene_color_manage, const bool skip_load_image)
{
int use_nodes= tex->use_nodes, retval;
tex->use_nodes = false;
- retval= multitex_nodes_intern(tex, texvec, NULL, NULL, 0, texres, 0, 0, NULL, NULL, pool, scene_color_manage);
+ retval= multitex_nodes_intern(tex, texvec, NULL, NULL, 0, texres, 0, 0, NULL, NULL, pool, scene_color_manage, skip_load_image);
tex->use_nodes= use_nodes;
return retval;
@@ -1336,7 +1348,7 @@ int multitex_ext_safe(Tex *tex, float texvec[3], TexResult *texres, struct Image
/* fact = texture strength, facg = button strength value */
void texture_rgb_blend(float in[3], const float tex[3], const float out[3], float fact, float facg, int blendtype)
{
- float facm, col;
+ float facm;
switch (blendtype) {
case MTEX_BLEND:
@@ -1423,13 +1435,10 @@ void texture_rgb_blend(float in[3], const float tex[3], const float out[3], floa
case MTEX_LIGHT:
fact*= facg;
-
- col= fact*tex[0];
- if (col > out[0]) in[0]= col; else in[0]= out[0];
- col= fact*tex[1];
- if (col > out[1]) in[1]= col; else in[1]= out[1];
- col= fact*tex[2];
- if (col > out[2]) in[2]= col; else in[2]= out[2];
+
+ in[0] = max_ff(fact * tex[0], out[0]);
+ in[1] = max_ff(fact * tex[1], out[1]);
+ in[2] = max_ff(fact * tex[2], out[2]);
break;
case MTEX_BLEND_HUE:
@@ -1707,7 +1716,7 @@ static void compatible_bump_uv_derivs(CompatibleBump *compat_bump, ShadeInput *s
static int compatible_bump_compute(CompatibleBump *compat_bump, ShadeInput *shi, MTex *mtex, Tex *tex, TexResult *texres,
float Tnor, const float co[3], const float dx[3], const float dy[3], float texvec[3], float dxt[3], float dyt[3],
- struct ImagePool *pool)
+ struct ImagePool *pool, const bool skip_load_image)
{
TexResult ttexr = {0, 0, 0, 0, 0, texres->talpha, NULL}; /* temp TexResult */
float tco[3], texv[3], cd, ud, vd, du, dv, idu, idv;
@@ -1760,7 +1769,7 @@ static int compatible_bump_compute(CompatibleBump *compat_bump, ShadeInput *shi,
/* center, main return value */
texco_mapping(shi, tex, mtex, co, dx, dy, texvec, dxt, dyt);
- rgbnor = multitex_mtex(shi, mtex, texvec, dxt, dyt, texres, pool);
+ rgbnor = multitex_mtex(shi, mtex, texvec, dxt, dyt, texres, pool, skip_load_image);
cd = fromrgb ? (texres->tr + texres->tg + texres->tb) / 3.0f : texres->tin;
if (mtex->texco == TEXCO_UV) {
@@ -1774,7 +1783,7 @@ static int compatible_bump_compute(CompatibleBump *compat_bump, ShadeInput *shi,
tco[1] = co[1] + compat_bump->dvdnu*du;
tco[2] = 0.f;
texco_mapping(shi, tex, mtex, tco, dx, dy, texv, dxt, dyt);
- multitex_mtex(shi, mtex, texv, dxt, dyt, &ttexr, pool);
+ multitex_mtex(shi, mtex, texv, dxt, dyt, &ttexr, pool, skip_load_image);
ud = idu*(cd - (fromrgb ? (ttexr.tr + ttexr.tg + ttexr.tb) / 3.0f : ttexr.tin));
/* +v val */
@@ -1782,7 +1791,7 @@ static int compatible_bump_compute(CompatibleBump *compat_bump, ShadeInput *shi,
tco[1] = co[1] + compat_bump->dvdnv*du;
tco[2] = 0.f;
texco_mapping(shi, tex, mtex, tco, dx, dy, texv, dxt, dyt);
- multitex_mtex(shi, mtex, texv, dxt, dyt, &ttexr, pool);
+ multitex_mtex(shi, mtex, texv, dxt, dyt, &ttexr, pool, skip_load_image);
vd = idu*(cd - (fromrgb ? (ttexr.tr + ttexr.tg + ttexr.tb) / 3.0f : ttexr.tin));
}
else {
@@ -1816,7 +1825,7 @@ static int compatible_bump_compute(CompatibleBump *compat_bump, ShadeInput *shi,
tco[1] = co[1] + tu[1]*du;
tco[2] = co[2] + tu[2]*du;
texco_mapping(shi, tex, mtex, tco, dx, dy, texv, dxt, dyt);
- multitex_mtex(shi, mtex, texv, dxt, dyt, &ttexr, pool);
+ multitex_mtex(shi, mtex, texv, dxt, dyt, &ttexr, pool, skip_load_image);
ud = idu*(cd - (fromrgb ? (ttexr.tr + ttexr.tg + ttexr.tb) / 3.0f : ttexr.tin));
/* +v val */
@@ -1824,7 +1833,7 @@ static int compatible_bump_compute(CompatibleBump *compat_bump, ShadeInput *shi,
tco[1] = co[1] + tv[1]*dv;
tco[2] = co[2] + tv[2]*dv;
texco_mapping(shi, tex, mtex, tco, dx, dy, texv, dxt, dyt);
- multitex_mtex(shi, mtex, texv, dxt, dyt, &ttexr, pool);
+ multitex_mtex(shi, mtex, texv, dxt, dyt, &ttexr, pool, skip_load_image);
vd = idv*(cd - (fromrgb ? (ttexr.tr + ttexr.tg + ttexr.tb) / 3.0f : ttexr.tin));
}
@@ -1866,7 +1875,8 @@ static void ntap_bump_init(NTapBump *ntap_bump)
static int ntap_bump_compute(NTapBump *ntap_bump, ShadeInput *shi, MTex *mtex, Tex *tex, TexResult *texres,
float Tnor, const float co[3], const float dx[3], const float dy[3],
- float texvec[3], float dxt[3], float dyt[3], struct ImagePool *pool)
+ float texvec[3], float dxt[3], float dyt[3], struct ImagePool *pool,
+ const bool skip_load_image)
{
TexResult ttexr = {0, 0, 0, 0, 0, texres->talpha, NULL}; /* temp TexResult */
@@ -1926,7 +1936,7 @@ static int ntap_bump_compute(NTapBump *ntap_bump, ShadeInput *shi, MTex *mtex, T
float dBdu, dBdv, auto_bump = 1.0f;
float s = 1; /* negate this if flipped texture coordinate */
texco_mapping(shi, tex, mtex, co, dx, dy, texvec, dxt, dyt);
- rgbnor = multitex_mtex(shi, mtex, texvec, dxt, dyt, texres, pool);
+ rgbnor = multitex_mtex(shi, mtex, texvec, dxt, dyt, texres, pool, skip_load_image);
if (shi->obr->ob->derivedFinal) {
auto_bump = shi->obr->ob->derivedFinal->auto_bump_scale;
@@ -1968,15 +1978,15 @@ static int ntap_bump_compute(NTapBump *ntap_bump, ShadeInput *shi, MTex *mtex, T
}
/* use texres for the center sample, set rgbnor */
- rgbnor = multitex_mtex(shi, mtex, STll, dxt, dyt, texres, pool);
- Hll = (fromrgb) ? rgb_to_grayscale(&texres->tr) : texres->tin;
+ rgbnor = multitex_mtex(shi, mtex, STll, dxt, dyt, texres, pool, skip_load_image);
+ Hll = (fromrgb) ? IMB_colormanagement_get_luminance(&texres->tr) : texres->tin;
/* use ttexr for the other 2 taps */
- multitex_mtex(shi, mtex, STlr, dxt, dyt, &ttexr, pool);
- Hlr = (fromrgb) ? rgb_to_grayscale(&ttexr.tr) : ttexr.tin;
+ multitex_mtex(shi, mtex, STlr, dxt, dyt, &ttexr, pool, skip_load_image);
+ Hlr = (fromrgb) ? IMB_colormanagement_get_luminance(&ttexr.tr) : ttexr.tin;
- multitex_mtex(shi, mtex, STul, dxt, dyt, &ttexr, pool);
- Hul = (fromrgb) ? rgb_to_grayscale(&ttexr.tr) : ttexr.tin;
+ multitex_mtex(shi, mtex, STul, dxt, dyt, &ttexr, pool, skip_load_image);
+ Hul = (fromrgb) ? IMB_colormanagement_get_luminance(&ttexr.tr) : ttexr.tin;
dHdx = Hscale*(Hlr - Hll);
dHdy = Hscale*(Hul - Hll);
@@ -2006,18 +2016,18 @@ static int ntap_bump_compute(NTapBump *ntap_bump, ShadeInput *shi, MTex *mtex, T
}
/* use texres for the center sample, set rgbnor */
- rgbnor = multitex_mtex(shi, mtex, STc, dxt, dyt, texres, pool);
- /* Hc = (fromrgb) ? rgb_to_grayscale(&texres->tr) : texres->tin; */ /* UNUSED */
+ rgbnor = multitex_mtex(shi, mtex, STc, dxt, dyt, texres, pool, skip_load_image);
+ /* Hc = (fromrgb) ? IMB_colormanagement_get_luminance(&texres->tr) : texres->tin; */ /* UNUSED */
/* use ttexr for the other taps */
- multitex_mtex(shi, mtex, STl, dxt, dyt, &ttexr, pool);
- Hl = (fromrgb) ? rgb_to_grayscale(&ttexr.tr) : ttexr.tin;
- multitex_mtex(shi, mtex, STr, dxt, dyt, &ttexr, pool);
- Hr = (fromrgb) ? rgb_to_grayscale(&ttexr.tr) : ttexr.tin;
- multitex_mtex(shi, mtex, STd, dxt, dyt, &ttexr, pool);
- Hd = (fromrgb) ? rgb_to_grayscale(&ttexr.tr) : ttexr.tin;
- multitex_mtex(shi, mtex, STu, dxt, dyt, &ttexr, pool);
- Hu = (fromrgb) ? rgb_to_grayscale(&ttexr.tr) : ttexr.tin;
+ multitex_mtex(shi, mtex, STl, dxt, dyt, &ttexr, pool, skip_load_image);
+ Hl = (fromrgb) ? IMB_colormanagement_get_luminance(&ttexr.tr) : ttexr.tin;
+ multitex_mtex(shi, mtex, STr, dxt, dyt, &ttexr, pool, skip_load_image);
+ Hr = (fromrgb) ? IMB_colormanagement_get_luminance(&ttexr.tr) : ttexr.tin;
+ multitex_mtex(shi, mtex, STd, dxt, dyt, &ttexr, pool, skip_load_image);
+ Hd = (fromrgb) ? IMB_colormanagement_get_luminance(&ttexr.tr) : ttexr.tin;
+ multitex_mtex(shi, mtex, STu, dxt, dyt, &ttexr, pool, skip_load_image);
+ Hu = (fromrgb) ? IMB_colormanagement_get_luminance(&ttexr.tr) : ttexr.tin;
dHdx = Hscale*(Hr - Hl);
dHdy = Hscale*(Hu - Hd);
@@ -2126,6 +2136,7 @@ static int ntap_bump_compute(NTapBump *ntap_bump, ShadeInput *shi, MTex *mtex, T
void do_material_tex(ShadeInput *shi, Render *re)
{
+ const bool skip_load_image = (R.r.scemode & R_NO_IMAGE_LOAD) != 0;
CompatibleBump compat_bump;
NTapBump ntap_bump;
MTex *mtex;
@@ -2238,7 +2249,7 @@ void do_material_tex(ShadeInput *shi, Render *re)
if (mtex->uvname[0] != 0) {
for (i = 0; i < shi->totuv; i++) {
- if (strcmp(shi->uv[i].name, mtex->uvname)==0) {
+ if (STREQ(shi->uv[i].name, mtex->uvname)) {
suv= &shi->uv[i];
break;
}
@@ -2294,27 +2305,27 @@ void do_material_tex(ShadeInput *shi, Render *re)
if (use_compat_bump) {
rgbnor = compatible_bump_compute(&compat_bump, shi, mtex, tex,
&texres, Tnor*stencilTin, co, dx, dy, texvec, dxt, dyt,
- re->pool);
+ re->pool, skip_load_image);
}
else if (use_ntap_bump) {
rgbnor = ntap_bump_compute(&ntap_bump, shi, mtex, tex,
&texres, Tnor*stencilTin, co, dx, dy, texvec, dxt, dyt,
- re->pool);
+ re->pool, skip_load_image);
}
else {
texco_mapping(shi, tex, mtex, co, dx, dy, texvec, dxt, dyt);
- rgbnor = multitex_mtex(shi, mtex, texvec, dxt, dyt, &texres, re->pool);
+ rgbnor = multitex_mtex(shi, mtex, texvec, dxt, dyt, &texres, re->pool, skip_load_image);
}
}
else {
texco_mapping(shi, tex, mtex, co, dx, dy, texvec, dxt, dyt);
- rgbnor = multitex_mtex(shi, mtex, texvec, dxt, dyt, &texres, re->pool);
+ rgbnor = multitex_mtex(shi, mtex, texvec, dxt, dyt, &texres, re->pool, skip_load_image);
}
/* texture output */
if ((rgbnor & TEX_RGB) && (mtex->texflag & MTEX_RGBTOINT)) {
- texres.tin = rgb_to_grayscale(&texres.tr);
+ texres.tin = IMB_colormanagement_get_luminance(&texres.tr);
rgbnor -= TEX_RGB;
}
if (mtex->texflag & MTEX_NEGATIVE) {
@@ -2420,7 +2431,7 @@ void do_material_tex(ShadeInput *shi, Render *re)
BKE_image_pool_release_ibuf(ima, ibuf, re->pool);
}
-
+
if (mtex->mapto & MAP_COL) {
float colfac= mtex->colfac*stencilTin;
texture_rgb_blend(&shi->r, tcol, &shi->r, texres.tin, colfac, mtex->blendtype);
@@ -2554,7 +2565,7 @@ void do_material_tex(ShadeInput *shi, Render *re)
}
if (rgbnor & TEX_RGB) {
- texres.tin = rgb_to_grayscale(&texres.tr);
+ texres.tin = IMB_colormanagement_get_luminance(&texres.tr);
}
factt= (0.5f-texres.tin)*mtex->dispfac*stencilTin; facmm= 1.0f-factt;
@@ -2582,7 +2593,7 @@ void do_material_tex(ShadeInput *shi, Render *re)
if (rgbnor & TEX_RGB) {
if (texres.talpha) texres.tin = texres.ta;
- else texres.tin = rgb_to_grayscale(&texres.tr);
+ else texres.tin = IMB_colormanagement_get_luminance(&texres.tr);
}
if (mtex->mapto & MAP_REF) {
@@ -2660,6 +2671,7 @@ void do_material_tex(ShadeInput *shi, Render *re)
void do_volume_tex(ShadeInput *shi, const float *xyz, int mapto_flag, float col_r[3], float *val, Render *re)
{
+ const bool skip_load_image = (re->r.scemode & R_NO_IMAGE_LOAD) != 0;
MTex *mtex;
Tex *tex;
TexResult texres= {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0, NULL};
@@ -2747,12 +2759,12 @@ void do_volume_tex(ShadeInput *shi, const float *xyz, int mapto_flag, float col_
else texvec[2]= mtex->size[2]*(mtex->ofs[2]);
}
- rgbnor = multitex(tex, texvec, NULL, NULL, 0, &texres, shi->thread, mtex->which_output, re->pool); /* NULL = dxt/dyt, 0 = shi->osatex - not supported */
+ rgbnor = multitex(tex, texvec, NULL, NULL, 0, &texres, shi->thread, mtex->which_output, re->pool, skip_load_image); /* NULL = dxt/dyt, 0 = shi->osatex - not supported */
/* texture output */
if ((rgbnor & TEX_RGB) && (mtex->texflag & MTEX_RGBTOINT)) {
- texres.tin = rgb_to_grayscale(&texres.tr);
+ texres.tin = IMB_colormanagement_get_luminance(&texres.tr);
rgbnor -= TEX_RGB;
}
if (mtex->texflag & MTEX_NEGATIVE) {
@@ -2821,7 +2833,7 @@ void do_volume_tex(ShadeInput *shi, const float *xyz, int mapto_flag, float col_
/* convert RGB to intensity if intensity info isn't provided */
if (rgbnor & TEX_RGB) {
if (texres.talpha) texres.tin = texres.ta;
- else texres.tin = rgb_to_grayscale(&texres.tr);
+ else texres.tin = IMB_colormanagement_get_luminance(&texres.tr);
}
if ((mapto_flag & MAP_EMISSION) && (mtex->mapto & MAP_EMISSION)) {
@@ -2858,6 +2870,7 @@ void do_volume_tex(ShadeInput *shi, const float *xyz, int mapto_flag, float col_
void do_halo_tex(HaloRen *har, float xn, float yn, float col_r[4])
{
+ const bool skip_load_image = har->skip_load_image;
MTex *mtex;
TexResult texres= {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0, NULL};
float texvec[3], dxt[3], dyt[3], fact, facm, dx;
@@ -2914,11 +2927,11 @@ void do_halo_tex(HaloRen *har, float xn, float yn, float col_r[4])
if (mtex->tex->type==TEX_IMAGE) do_2d_mapping(mtex, texvec, NULL, NULL, dxt, dyt);
- rgb = multitex(mtex->tex, texvec, dxt, dyt, osatex, &texres, 0, mtex->which_output, har->pool);
+ rgb = multitex(mtex->tex, texvec, dxt, dyt, osatex, &texres, 0, mtex->which_output, har->pool, skip_load_image);
/* texture output */
if (rgb && (mtex->texflag & MTEX_RGBTOINT)) {
- texres.tin = rgb_to_bw(&texres.tr);
+ texres.tin = IMB_colormanagement_get_luminance(&texres.tr);
rgb= 0;
}
if (mtex->texflag & MTEX_NEGATIVE) {
@@ -2990,7 +3003,7 @@ void do_halo_tex(HaloRen *har, float xn, float yn, float col_r[4])
texres.tin = texres.ta;
}
else {
- texres.tin = rgb_to_bw(&texres.tr);
+ texres.tin = IMB_colormanagement_get_luminance(&texres.tr);
}
}
@@ -3003,6 +3016,7 @@ void do_halo_tex(HaloRen *har, float xn, float yn, float col_r[4])
/* hor and zen are RGB vectors, blend is 1 float, should all be initialized */
void do_sky_tex(const float rco[3], float lo[3], const float dxyview[2], float hor[3], float zen[3], float *blend, int skyflag, short thread)
{
+ const bool skip_load_image = (R.r.scemode & R_NO_IMAGE_LOAD) != 0;
MTex *mtex;
Tex *tex;
TexResult texres= {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0, NULL};
@@ -3039,7 +3053,7 @@ void do_sky_tex(const float rco[3], float lo[3], const float dxyview[2], float h
switch (mtex->texco) {
case TEXCO_ANGMAP:
/* only works with texture being "real" */
- /* use saacos(), fixes bug [#22398], float precision caused lo[2] to be slightly less then -1.0 */
+ /* use saacos(), fixes bug [#22398], float precision caused lo[2] to be slightly less than -1.0 */
if (lo[0] || lo[1]) { /* check for zero case [#24807] */
fact= (1.0f/(float)M_PI)*saacos(lo[2])/(sqrtf(lo[0]*lo[0] + lo[1]*lo[1]));
tempvec[0]= lo[0]*fact;
@@ -3119,11 +3133,11 @@ void do_sky_tex(const float rco[3], float lo[3], const float dxyview[2], float h
/* texture */
if (tex->type==TEX_IMAGE) do_2d_mapping(mtex, texvec, NULL, NULL, dxt, dyt);
- rgb = multitex(mtex->tex, texvec, dxt, dyt, R.osa, &texres, thread, mtex->which_output, R.pool);
+ rgb = multitex(mtex->tex, texvec, dxt, dyt, R.osa, &texres, thread, mtex->which_output, R.pool, skip_load_image);
/* texture output */
if (rgb && (mtex->texflag & MTEX_RGBTOINT)) {
- texres.tin = rgb_to_bw(&texres.tr);
+ texres.tin = IMB_colormanagement_get_luminance(&texres.tr);
rgb= 0;
}
if (mtex->texflag & MTEX_NEGATIVE) {
@@ -3198,7 +3212,7 @@ void do_sky_tex(const float rco[3], float lo[3], const float dxyview[2], float h
}
}
if (mtex->mapto & WOMAP_BLEND) {
- if (rgb) texres.tin = rgb_to_bw(&texres.tr);
+ if (rgb) texres.tin = IMB_colormanagement_get_luminance(&texres.tr);
*blend= texture_value_blend(mtex->def_var, *blend, texres.tin, mtex->blendfac, mtex->blendtype);
}
@@ -3211,6 +3225,7 @@ void do_sky_tex(const float rco[3], float lo[3], const float dxyview[2], float h
void do_lamp_tex(LampRen *la, const float lavec[3], ShadeInput *shi, float col_r[3], int effect)
{
+ const bool skip_load_image = (R.r.scemode & R_NO_IMAGE_LOAD) != 0;
Object *ob;
MTex *mtex;
Tex *tex;
@@ -3334,11 +3349,11 @@ void do_lamp_tex(LampRen *la, const float lavec[3], ShadeInput *shi, float col_r
do_2d_mapping(mtex, texvec, NULL, NULL, dxt, dyt);
}
- rgb = multitex(tex, texvec, dxt, dyt, shi->osatex, &texres, shi->thread, mtex->which_output, R.pool);
+ rgb = multitex(tex, texvec, dxt, dyt, shi->osatex, &texres, shi->thread, mtex->which_output, R.pool, skip_load_image);
/* texture output */
if (rgb && (mtex->texflag & MTEX_RGBTOINT)) {
- texres.tin = rgb_to_bw(&texres.tr);
+ texres.tin = IMB_colormanagement_get_luminance(&texres.tr);
rgb= 0;
}
if (mtex->texflag & MTEX_NEGATIVE) {
@@ -3396,8 +3411,11 @@ void do_lamp_tex(LampRen *la, const float lavec[3], ShadeInput *shi, float col_r
col[0]= texres.tr*la->energy;
col[1]= texres.tg*la->energy;
col[2]= texres.tb*la->energy;
-
- texture_rgb_blend(col_r, col, col_r, texres.tin, mtex->colfac, mtex->blendtype);
+
+ if (effect & LA_SHAD_TEX)
+ texture_rgb_blend(col_r, col, col_r, texres.tin, mtex->shadowfac, mtex->blendtype);
+ else
+ texture_rgb_blend(col_r, col, col_r, texres.tin, mtex->colfac, mtex->blendtype);
}
}
}
@@ -3405,7 +3423,7 @@ void do_lamp_tex(LampRen *la, const float lavec[3], ShadeInput *shi, float col_r
/* ------------------------------------------------------------------------- */
-int externtex(MTex *mtex, const float vec[3], float *tin, float *tr, float *tg, float *tb, float *ta, const int thread, struct ImagePool *pool)
+int externtex(MTex *mtex, const float vec[3], float *tin, float *tr, float *tg, float *tb, float *ta, const int thread, struct ImagePool *pool, const bool skip_load_image)
{
Tex *tex;
TexResult texr;
@@ -3431,10 +3449,10 @@ int externtex(MTex *mtex, const float vec[3], float *tin, float *tr, float *tg,
do_2d_mapping(mtex, texvec, NULL, NULL, dxt, dyt);
}
- rgb = multitex(tex, texvec, dxt, dyt, 0, &texr, thread, mtex->which_output, pool);
+ rgb = multitex(tex, texvec, dxt, dyt, 0, &texr, thread, mtex->which_output, pool, skip_load_image);
if (rgb) {
- texr.tin = rgb_to_bw(&texr.tr);
+ texr.tin = IMB_colormanagement_get_luminance(&texr.tr);
}
else {
texr.tr= mtex->r;
@@ -3456,6 +3474,7 @@ int externtex(MTex *mtex, const float vec[3], float *tin, float *tr, float *tg,
void render_realtime_texture(ShadeInput *shi, Image *ima)
{
+ const bool skip_load_image = (R.r.scemode & R_NO_IMAGE_LOAD) != 0;
TexResult texr;
static Tex imatex[BLENDER_MAX_THREADS]; /* threadsafe */
static int firsttime= 1;
@@ -3471,7 +3490,7 @@ void render_realtime_texture(ShadeInput *shi, Image *ima)
if (firsttime) {
for (a=0; a<BLENDER_MAX_THREADS; a++) {
memset(&imatex[a], 0, sizeof(Tex));
- default_tex(&imatex[a]);
+ BKE_texture_default(&imatex[a]);
imatex[a].type= TEX_IMAGE;
}
@@ -3496,8 +3515,8 @@ void render_realtime_texture(ShadeInput *shi, Image *ima)
texr.nor= NULL;
- if (shi->osatex) imagewraposa(tex, ima, NULL, texvec, dx, dy, &texr, R.pool);
- else imagewrap(tex, ima, NULL, texvec, &texr, R.pool);
+ if (shi->osatex) imagewraposa(tex, ima, NULL, texvec, dx, dy, &texr, R.pool, skip_load_image);
+ else imagewrap(tex, ima, NULL, texvec, &texr, R.pool, skip_load_image);
shi->vcol[0]*= texr.tr;
shi->vcol[1]*= texr.tg;
@@ -3507,7 +3526,10 @@ void render_realtime_texture(ShadeInput *shi, Image *ima)
/* A modified part of shadeinput.c -> shade_input_set_uv()
* Used for sampling UV mapped texture color */
-static void textured_face_generate_uv(float *uv, const float normal[3], float *hit, float *v1, float *v2, float *v3)
+static void textured_face_generate_uv(
+ const float normal[3], const float hit[3],
+ const float v1[3], const float v2[3], const float v3[3],
+ float r_uv[2])
{
float detsh, t00, t10, t01, t11;
@@ -3524,12 +3546,12 @@ static void textured_face_generate_uv(float *uv, const float normal[3], float *h
t00*= detsh; t01*=detsh;
t10*=detsh; t11*=detsh;
- uv[0] = (hit[axis1]-v3[axis1])*t11-(hit[axis2]-v3[axis2])*t10;
- uv[1] = (hit[axis2]-v3[axis2])*t00-(hit[axis1]-v3[axis1])*t01;
+ r_uv[0] = (hit[axis1] - v3[axis1]) * t11 - (hit[axis2] - v3[axis2]) * t10;
+ r_uv[1] = (hit[axis2] - v3[axis2]) * t00 - (hit[axis1] - v3[axis1]) * t01;
/* u and v are in range -1 to 0, we allow a little bit extra but not too much, screws up speedvectors */
- CLAMP(uv[0], -2.0f, 1.0f);
- CLAMP(uv[1], -2.0f, 1.0f);
+ CLAMP(r_uv[0], -2.0f, 1.0f);
+ CLAMP(r_uv[1], -2.0f, 1.0f);
}
/* Generate an updated copy of material to use for color sampling. */
@@ -3592,7 +3614,7 @@ Material *RE_init_sample_material(Material *orig_mat, Scene *scene)
}
/* copy texture */
- tex= mtex->tex = localize_texture(cur_tex);
+ tex= mtex->tex = BKE_texture_localize(cur_tex);
/* update texture anims */
BKE_animsys_evaluate_animdata(scene, &tex->id, tex->adt, BKE_scene_frame_get(scene), ADT_RECALC_ANIM);
@@ -3609,7 +3631,7 @@ Material *RE_init_sample_material(Material *orig_mat, Scene *scene)
unit_m4(dummy_re.viewmat);
unit_m4(dummy_re.winmat);
dummy_re.winx = dummy_re.winy = 128;
- cache_pointdensity(&dummy_re, tex);
+ cache_pointdensity(&dummy_re, tex->pd);
}
/* update image sequences and movies */
@@ -3645,34 +3667,37 @@ void RE_free_sample_material(Material *mat)
MEM_freeN(mat);
}
-
-
/*
* Get material diffuse color and alpha (including linked textures) in given coordinates
*
* color,alpha : input/output color values
* volume_co : sample coordinate in global space. used by volumetric materials
* surface_co : sample surface coordinate in global space. used by "surface" materials
- * face_index : surface face index
- * hit_quad : whether point is on second "half" of a quad
+ * tri_index : surface tri index
* orcoDm : orco state derived mesh
*/
-void RE_sample_material_color(Material *mat, float color[3], float *alpha, const float volume_co[3], const float surface_co[3], int face_index, short hit_quad, DerivedMesh *orcoDm, Object *ob)
+void RE_sample_material_color(
+ Material *mat, float color[3], float *alpha, const float volume_co[3], const float surface_co[3],
+ int tri_index, DerivedMesh *orcoDm, Object *ob)
{
- MFace *mface;
int v1, v2, v3;
MVert *mvert;
+ MLoop *mloop;
+ const MLoopTri *mlooptri;
float uv[3], normal[3];
ShadeInput shi = {NULL};
Render re = {NULL};
/* Get face data */
mvert = orcoDm->getVertArray(orcoDm);
- mface = orcoDm->getTessFaceArray(orcoDm);
+ mloop = orcoDm->getLoopArray(orcoDm);
+ mlooptri = orcoDm->getLoopTriArray(orcoDm);
- if (!mvert || !mface || !mat) return;
- v1=mface[face_index].v1, v2=mface[face_index].v2, v3=mface[face_index].v3;
- if (hit_quad) { v2 = mface[face_index].v3; v3 = mface[face_index].v4; }
+ if (!mvert || !mlooptri || !mat) {
+ return;
+ }
+
+ v1=mloop[mlooptri[tri_index].tri[0]].v, v2=mloop[mlooptri[tri_index].tri[1]].v, v3=mloop[mlooptri[tri_index].tri[2]].v;
normal_tri_v3(normal, mvert[v1].co, mvert[v2].co, mvert[v3].co);
/* generate shadeinput with data required */
@@ -3689,7 +3714,7 @@ void RE_sample_material_color(Material *mat, float color[3], float *alpha, const
{
float l;
/* Get generated UV */
- textured_face_generate_uv(uv, normal, shi.co, mvert[v1].co, mvert[v2].co, mvert[v3].co);
+ textured_face_generate_uv(normal, shi.co, mvert[v1].co, mvert[v2].co, mvert[v3].co, uv);
l= 1.0f+uv[0]+uv[1];
/* calculate generated coordinate */
@@ -3699,35 +3724,37 @@ void RE_sample_material_color(Material *mat, float color[3], float *alpha, const
}
/* uv coordinates */
{
- int i, layers = CustomData_number_of_layers(&orcoDm->faceData, CD_MTFACE);
- int layer_index = CustomData_get_layer_index(&orcoDm->faceData, CD_MTFACE);
+ const int layers = CustomData_number_of_layers(&orcoDm->loopData, CD_MLOOPUV);
+ const int layer_index = CustomData_get_layer_index(&orcoDm->loopData, CD_MLOOPUV);
+ int i;
/* for every uv map set coords and name */
for (i=0; i<layers; i++) {
if (layer_index >= 0) {
const float *uv1, *uv2, *uv3;
+ const CustomData *data = &orcoDm->loopData;
+ const MLoopUV *mloopuv = data->layers[layer_index + i].data;
+ float uv[2];
float l;
- CustomData *data = &orcoDm->faceData;
- MTFace *tface = (MTFace *) data->layers[layer_index+i].data;
- float uv[3];
+
/* point layer name from actual layer data */
shi.uv[i].name = data->layers[i].name;
/* Get generated coordinates to calculate UV from */
- textured_face_generate_uv(uv, normal, shi.co, mvert[v1].co, mvert[v2].co, mvert[v3].co);
+ textured_face_generate_uv(normal, shi.co, mvert[v1].co, mvert[v2].co, mvert[v3].co, uv);
/* Get UV mapping coordinate */
l= 1.0f+uv[0]+uv[1];
-
- uv1= tface[face_index].uv[0];
- uv2= (hit_quad) ? tface[face_index].uv[2] : tface[face_index].uv[1];
- uv3= (hit_quad) ? tface[face_index].uv[3] : tface[face_index].uv[2];
-
+
+ uv1 = mloopuv[mlooptri[tri_index].tri[0]].uv;
+ uv2 = mloopuv[mlooptri[tri_index].tri[1]].uv;
+ uv3 = mloopuv[mlooptri[tri_index].tri[2]].uv;
+
shi.uv[i].uv[0]= -1.0f + 2.0f*(l*uv3[0]-uv[0]*uv1[0]-uv[1]*uv2[0]);
shi.uv[i].uv[1]= -1.0f + 2.0f*(l*uv3[1]-uv[0]*uv1[1]-uv[1]*uv2[1]);
shi.uv[i].uv[2]= 0.0f; /* texture.c assumes there are 3 coords */
}
}
/* active uv map */
- shi.actuv = CustomData_get_active_layer_index(&orcoDm->faceData, CD_MTFACE) - layer_index;
+ shi.actuv = CustomData_get_active_layer_index(&orcoDm->loopData, CD_MLOOPUV) - layer_index;
shi.totuv = layers;
}
diff --git a/source/blender/render/intern/source/rendercore.c b/source/blender/render/intern/source/rendercore.c
index a67140c6334..910ea16607e 100644
--- a/source/blender/render/intern/source/rendercore.c
+++ b/source/blender/render/intern/source/rendercore.c
@@ -50,15 +50,7 @@
#include "DNA_material_types.h"
#include "DNA_group_types.h"
-#include "BKE_main.h"
-
-#include "IMB_imbuf_types.h"
-#include "IMB_imbuf.h"
-#include "IMB_colormanagement.h"
-
/* local include */
-#include "rayintersection.h"
-#include "rayobject.h"
#include "renderpipeline.h"
#include "render_result.h"
#include "render_types.h"
@@ -71,8 +63,6 @@
#include "sss.h"
#include "zbuf.h"
-#include "PIL_time.h"
-
/* own include */
#include "rendercore.h"
@@ -191,8 +181,10 @@ static void halo_pixelstruct(HaloRen *har, RenderLayer **rlpp, int totsample, in
if (fullsample) {
for (sample=0; sample<totsample; sample++)
- if (ps->mask & (1 << sample))
- addalphaAddfacFloat(rlpp[sample]->rectf + od*4, col, har->add);
+ if (ps->mask & (1 << sample)) {
+ float *pass = RE_RenderLayerGetPass(rlpp[sample], SCE_PASS_COMBINED, R.viewname);
+ addalphaAddfacFloat(pass + od*4, col, har->add);
+ }
}
else {
fac= ((float)amountm)/(float)R.osa;
@@ -224,8 +216,10 @@ static void halo_pixelstruct(HaloRen *har, RenderLayer **rlpp, int totsample, in
if (fullsample) {
for (sample=0; sample<totsample; sample++)
- if (!(mask & (1 << sample)))
- addalphaAddfacFloat(rlpp[sample]->rectf + od*4, col, har->add);
+ if (!(mask & (1 << sample))) {
+ float *pass = RE_RenderLayerGetPass(rlpp[sample], SCE_PASS_COMBINED, R.viewname);
+ addalphaAddfacFloat(pass + od*4, col, har->add);
+ }
}
else {
col[0]= accol[0];
@@ -233,8 +227,10 @@ static void halo_pixelstruct(HaloRen *har, RenderLayer **rlpp, int totsample, in
col[2]= accol[2];
col[3]= accol[3];
- for (sample=0; sample<totsample; sample++)
- addalphaAddfacFloat(rlpp[sample]->rectf + od*4, col, har->add);
+ for (sample=0; sample<totsample; sample++) {
+ float *pass = RE_RenderLayerGetPass(rlpp[sample], SCE_PASS_COMBINED, R.viewname);
+ addalphaAddfacFloat(pass + od*4, col, har->add);
+ }
}
}
@@ -315,8 +311,10 @@ static void halo_tile(RenderPart *pa, RenderLayer *rl)
zz= calchalo_z(har, *rz);
if ((zz> har->zs) || (har->mat && (har->mat->mode & MA_HALO_SOFT))) {
if (shadeHaloFloat(har, col, zz, dist, xn, yn, har->flarec)) {
- for (sample=0; sample<totsample; sample++)
- addalphaAddfacFloat(rlpp[sample]->rectf + od*4, col, har->add);
+ for (sample=0; sample<totsample; sample++) {
+ float * rect= RE_RenderLayerGetPass(rlpp[sample], SCE_PASS_COMBINED, R.viewname);
+ addalphaAddfacFloat(rect + od*4, col, har->add);
+ }
}
}
}
@@ -369,7 +367,8 @@ static void lamphalo_tile(RenderPart *pa, RenderLayer *rl)
if (fullsample) {
for (sample=0; sample<totsample; sample++) {
if (ps->mask & (1 << sample)) {
- pass= rlpp[sample]->rectf + od*4;
+ pass = RE_RenderLayerGetPass(rlpp[sample], SCE_PASS_COMBINED, R.viewname);
+ pass += od * 4;
pass[0]+= col[0];
pass[1]+= col[1];
pass[2]+= col[2];
@@ -380,7 +379,8 @@ static void lamphalo_tile(RenderPart *pa, RenderLayer *rl)
}
else {
fac= ((float)count)/(float)R.osa;
- pass= rl->rectf + od*4;
+ pass = RE_RenderLayerGetPass(rl, SCE_PASS_COMBINED, R.viewname);
+ pass += od * 4;
pass[0]+= fac*col[0];
pass[1]+= fac*col[1];
pass[2]+= fac*col[2];
@@ -400,7 +400,9 @@ static void lamphalo_tile(RenderPart *pa, RenderLayer *rl)
if (fullsample) {
for (sample=0; sample<totsample; sample++) {
if (!(mask & (1 << sample))) {
- pass= rlpp[sample]->rectf + od*4;
+
+ pass = RE_RenderLayerGetPass(rlpp[sample], SCE_PASS_COMBINED, R.viewname);
+ pass += od * 4;
pass[0]+= col[0];
pass[1]+= col[1];
pass[2]+= col[2];
@@ -411,7 +413,8 @@ static void lamphalo_tile(RenderPart *pa, RenderLayer *rl)
}
else {
fac= ((float)R.osa-totsamp)/(float)R.osa;
- pass= rl->rectf + od*4;
+ pass = RE_RenderLayerGetPass(rl, SCE_PASS_COMBINED, R.viewname);
+ pass += od * 4;
pass[0]+= fac*col[0];
pass[1]+= fac*col[1];
pass[2]+= fac*col[2];
@@ -430,7 +433,8 @@ static void lamphalo_tile(RenderPart *pa, RenderLayer *rl)
renderspothalo(&shi, col, 1.0f);
for (sample=0; sample<totsample; sample++) {
- pass= rlpp[sample]->rectf + od*4;
+ pass = RE_RenderLayerGetPass(rlpp[sample], SCE_PASS_COMBINED, R.viewname);
+ pass += od * 4;
pass[0]+= col[0];
pass[1]+= col[1];
pass[2]+= col[2];
@@ -454,14 +458,14 @@ static void add_filt_passes(RenderLayer *rl, int curmask, int rectx, int offset,
{
RenderPass *rpass;
- /* combined rgb */
- add_filt_fmask(curmask, shr->combined, rl->rectf + 4*offset, rectx);
-
for (rpass= rl->passes.first; rpass; rpass= rpass->next) {
float *fp, *col= NULL;
int pixsize= 3;
switch (rpass->passtype) {
+ case SCE_PASS_COMBINED:
+ add_filt_fmask(curmask, shr->combined, rpass->rect + 4*offset, rectx);
+ break;
case SCE_PASS_Z:
fp= rpass->rect + offset;
*fp= shr->z;
@@ -544,9 +548,9 @@ static void add_filt_passes(RenderLayer *rl, int curmask, int rectx, int offset,
fp[2]= shr->winspeed[2];
fp[3]= shr->winspeed[3];
}
- }
- break;
+ break;
+ }
case SCE_PASS_RAYHITS:
/* */
col= shr->rayhits;
@@ -565,15 +569,16 @@ static void add_passes(RenderLayer *rl, int offset, ShadeInput *shi, ShadeResult
{
RenderPass *rpass;
float *fp;
-
- fp= rl->rectf + 4*offset;
- copy_v4_v4(fp, shr->combined);
-
+
for (rpass= rl->passes.first; rpass; rpass= rpass->next) {
float *col= NULL, uvcol[3];
int a, pixsize= 3;
switch (rpass->passtype) {
+ case SCE_PASS_COMBINED:
+ /* copy combined to use for preview */
+ copy_v4_v4(rpass->rect + 4*offset, shr->combined);
+ break;
case SCE_PASS_Z:
fp= rpass->rect + offset;
*fp= shr->z;
@@ -691,7 +696,8 @@ static void sky_tile(RenderPart *pa, RenderLayer *rl)
bool done = false;
for (sample= 0; sample<totsample; sample++) {
- float *pass= rlpp[sample]->rectf + od;
+ float *pass = RE_RenderLayerGetPass(rlpp[sample], SCE_PASS_COMBINED, R.viewname);
+ pass += od;
if (pass[3]<1.0f) {
@@ -752,8 +758,8 @@ static void atm_tile(RenderPart *pa, RenderLayer *rl)
int sample;
for (sample=0; sample<totsample; sample++) {
- const float *zrect= RE_RenderLayerGetPass(rlpp[sample], SCE_PASS_Z) + od;
- float *rgbrect = rlpp[sample]->rectf + 4*od;
+ const float *zrect = RE_RenderLayerGetPass(rlpp[sample], SCE_PASS_Z, R.viewname) + od;
+ float *rgbrect = RE_RenderLayerGetPass(rlpp[sample], SCE_PASS_COMBINED, R.viewname) + 4*od;
float rgb[3] = {0};
bool done = false;
@@ -988,8 +994,8 @@ static void clamp_alpha_rgb_range(RenderPart *pa, RenderLayer *rl)
return;
for (sample= 0; sample<totsample; sample++) {
- float *rectf= rlpp[sample]->rectf;
-
+ float *rectf = RE_RenderLayerGetPass(rlpp[sample], SCE_PASS_COMBINED, R.viewname);
+
for (y= pa->rectx*pa->recty; y>0; y--, rectf+=4) {
rectf[0] = MAX2(rectf[0], 0.0f);
rectf[1] = MAX2(rectf[1], 0.0f);
@@ -1070,7 +1076,7 @@ static void reset_sky_speed(RenderPart *pa, RenderLayer *rl)
totsample= get_sample_layers(pa, rl, rlpp);
for (sample= 0; sample<totsample; sample++) {
- fp= RE_RenderLayerGetPass(rlpp[sample], SCE_PASS_VECTOR);
+ fp= RE_RenderLayerGetPass(rlpp[sample], SCE_PASS_VECTOR, R.viewname);
if (fp==NULL) break;
for (a= 4*pa->rectx*pa->recty - 1; a>=0; a--)
@@ -1181,6 +1187,8 @@ void zbufshadeDA_tile(RenderPart *pa)
pa->rectp= MEM_mallocN(sizeof(int)*pa->rectx*pa->recty, "rectp");
pa->rectz= MEM_mallocN(sizeof(int)*pa->rectx*pa->recty, "rectz");
for (rl= rr->layers.first; rl; rl= rl->next) {
+ float *rect = RE_RenderLayerGetPass(rl, SCE_PASS_COMBINED, R.viewname);
+
if ((rl->layflag & SCE_LAY_ZMASK) && (rl->layflag & SCE_LAY_NEG_ZMASK))
pa->rectmask= MEM_mallocN(sizeof(int)*pa->rectx*pa->recty, "rectmask");
@@ -1221,7 +1229,7 @@ void zbufshadeDA_tile(RenderPart *pa)
if (R.flag & R_ZTRA || R.totstrand) {
if (rl->layflag & (SCE_LAY_ZTRA|SCE_LAY_STRAND)) {
if (pa->fullresult.first) {
- zbuffer_transp_shade(pa, rl, rl->rectf, &psmlist);
+ zbuffer_transp_shade(pa, rl, rect, &psmlist);
}
else {
unsigned short *ztramask, *solidmask= NULL; /* 16 bits, MAX_OSA */
@@ -1230,9 +1238,9 @@ void zbufshadeDA_tile(RenderPart *pa)
rl->acolrect= MEM_callocN(4*sizeof(float)*pa->rectx*pa->recty, "alpha layer");
/* swap for live updates, and it is used in zbuf.c!!! */
- SWAP(float *, rl->acolrect, rl->rectf);
- ztramask= zbuffer_transp_shade(pa, rl, rl->rectf, &psmlist);
- SWAP(float *, rl->acolrect, rl->rectf);
+ SWAP(float *, rl->acolrect, rect);
+ ztramask = zbuffer_transp_shade(pa, rl, rect, &psmlist);
+ SWAP(float *, rl->acolrect, rect);
/* zbuffer transp only returns ztramask if there's solid rendered */
if (ztramask)
@@ -1241,7 +1249,8 @@ void zbufshadeDA_tile(RenderPart *pa)
if (ztramask && solidmask) {
unsigned short *sps= solidmask, *spz= ztramask;
unsigned short fullmask= (1<<R.osa)-1;
- float *fcol= rl->rectf; float *acol= rl->acolrect;
+ float *fcol= rect;
+ float *acol= rl->acolrect;
int x;
for (x=pa->rectx*pa->recty; x>0; x--, acol+=4, fcol+=4, sps++, spz++) {
@@ -1252,7 +1261,8 @@ void zbufshadeDA_tile(RenderPart *pa)
}
}
else {
- float *fcol= rl->rectf; float *acol= rl->acolrect;
+ float *fcol= rect;
+ float *acol= rl->acolrect;
int x;
for (x=pa->rectx*pa->recty; x>0; x--, acol+=4, fcol+=4) {
addAlphaOverFloat(fcol, acol);
@@ -1275,7 +1285,7 @@ void zbufshadeDA_tile(RenderPart *pa)
/* extra layers */
if (rl->layflag & SCE_LAY_EDGE)
if (R.r.mode & R_EDGE)
- edge_enhance_add(pa, rl->rectf, edgerect);
+ edge_enhance_add(pa, rect, edgerect);
if (rl->passflag & SCE_PASS_VECTOR)
reset_sky_speed(pa, rl);
@@ -1329,6 +1339,7 @@ void zbufshade_tile(RenderPart *pa)
pa->rectz= MEM_mallocN(sizeof(int)*pa->rectx*pa->recty, "rectz");
for (rl= rr->layers.first; rl; rl= rl->next) {
+ float *rect= RE_RenderLayerGetPass(rl, SCE_PASS_COMBINED, R.viewname);
if ((rl->layflag & SCE_LAY_ZMASK) && (rl->layflag & SCE_LAY_NEG_ZMASK))
pa->rectmask= MEM_mallocN(sizeof(int)*pa->rectx*pa->recty, "rectmask");
@@ -1352,7 +1363,7 @@ void zbufshade_tile(RenderPart *pa)
rr->renlay= rl;
if (rl->layflag & SCE_LAY_SOLID) {
- const float *fcol= rl->rectf;
+ const float *fcol = rect;
const int *ro= pa->recto, *rp= pa->rectp, *rz= pa->rectz;
int x, y, offs=0, seed;
@@ -1415,11 +1426,11 @@ void zbufshade_tile(RenderPart *pa)
rl->acolrect= MEM_callocN(4*sizeof(float)*pa->rectx*pa->recty, "alpha layer");
/* swap for live updates */
- SWAP(float *, rl->acolrect, rl->rectf);
- zbuffer_transp_shade(pa, rl, rl->rectf, NULL);
- SWAP(float *, rl->acolrect, rl->rectf);
+ SWAP(float *, rl->acolrect, rect);
+ zbuffer_transp_shade(pa, rl, rect, NULL);
+ SWAP(float *, rl->acolrect, rect);
- fcol= rl->rectf; acol= rl->acolrect;
+ fcol= rect; acol= rl->acolrect;
for (x=pa->rectx*pa->recty; x>0; x--, acol+=4, fcol+=4) {
addAlphaOverFloat(fcol, acol);
}
@@ -1437,7 +1448,7 @@ void zbufshade_tile(RenderPart *pa)
if (!R.test_break(R.tbh)) {
if (rl->layflag & SCE_LAY_EDGE)
if (R.r.mode & R_EDGE)
- edge_enhance_add(pa, rl->rectf, edgerect);
+ edge_enhance_add(pa, rect, edgerect);
}
if (rl->passflag & SCE_PASS_VECTOR)
@@ -1611,7 +1622,8 @@ void zbufshade_sss_tile(RenderPart *pa)
VlakRen *vlr;
Material *mat= re->sss_mat;
float (*co)[3], (*color)[3], *area, *fcol;
- int x, y, seed, quad, totpoint, display = !(re->r.scemode & (R_BUTS_PREVIEW|R_VIEWPORT_PREVIEW));
+ int x, y, seed, quad, totpoint;
+ const bool display = (re->r.scemode & (R_BUTS_PREVIEW | R_VIEWPORT_PREVIEW)) == 0;
int *ro, *rz, *rp, *rbo, *rbz, *rbp, lay;
#if 0
PixStr *ps;
@@ -1664,7 +1676,7 @@ void zbufshade_sss_tile(RenderPart *pa)
return;
}
- fcol= rl->rectf;
+ fcol= RE_RenderLayerGetPass(rl, SCE_PASS_COMBINED, R.viewname);
co= MEM_mallocN(sizeof(float)*3*handle.totps, "SSSCo");
color= MEM_mallocN(sizeof(float)*3*handle.totps, "SSSColor");
@@ -1948,6 +1960,7 @@ void add_halo_flare(Render *re)
RenderLayer *rl;
HaloRen *har;
int a, mode;
+ float *rect;
/* for now, we get the first renderlayer in list with halos set */
for (rl= rr->layers.first; rl; rl= rl->next) {
@@ -1955,9 +1968,12 @@ void add_halo_flare(Render *re)
if ((rl->layflag & SCE_LAY_HALO) == 0)
continue;
- if (rl->rectf==NULL)
+
+ rect = RE_RenderLayerGetPass(rl, SCE_PASS_COMBINED, re->viewname);
+
+ if (rect==NULL)
continue;
-
+
mode= R.r.mode;
R.r.mode &= ~R_PANORAMA;
@@ -1968,7 +1984,7 @@ void add_halo_flare(Render *re)
if (har->flarec && (har->lay & rl->lay)) {
do_draw = true;
- renderflare(rr, rl->rectf, har);
+ renderflare(rr, rect, har);
}
}
diff --git a/source/blender/render/intern/source/renderdatabase.c b/source/blender/render/intern/source/renderdatabase.c
index 46c504aaabf..7a9b2d0903e 100644
--- a/source/blender/render/intern/source/renderdatabase.c
+++ b/source/blender/render/intern/source/renderdatabase.c
@@ -69,7 +69,8 @@
#include "DNA_material_types.h"
#include "DNA_meshdata_types.h"
-#include "DNA_texture_types.h"
+#include "DNA_texture_types.h"
+#include "DNA_particle_types.h"
#include "BKE_customdata.h"
#include "BKE_DerivedMesh.h"
@@ -78,11 +79,8 @@
#include "rayintersection.h"
#include "rayobject.h"
-#include "renderpipeline.h"
#include "render_types.h"
#include "renderdatabase.h"
-#include "texture.h"
-#include "strand.h"
#include "zbuf.h"
/* ------------------------------------------------------------------------- */
@@ -957,6 +955,7 @@ HaloRen *RE_inithalo(Render *re, ObjectRen *obr, Material *ma,
const float vec[3], const float vec1[3],
const float *orco, float hasize, float vectsize, int seed)
{
+ const bool skip_load_image = (re->r.scemode & R_NO_IMAGE_LOAD) != 0;
HaloRen *har;
MTex *mtex;
float tin, tr, tg, tb, ta;
@@ -1048,7 +1047,7 @@ HaloRen *RE_inithalo(Render *re, ObjectRen *obr, Material *ma,
}
}
- externtex(mtex, texvec, &tin, &tr, &tg, &tb, &ta, 0, re->pool);
+ externtex(mtex, texvec, &tin, &tr, &tg, &tb, &ta, 0, re->pool, skip_load_image);
yn= tin*mtex->colfac;
//zn= tin*mtex->alphafac;
@@ -1068,6 +1067,7 @@ HaloRen *RE_inithalo(Render *re, ObjectRen *obr, Material *ma,
}
har->pool = re->pool;
+ har->skip_load_image = (re->r.scemode & R_NO_IMAGE_LOAD) != 0;
return har;
}
@@ -1076,6 +1076,7 @@ HaloRen *RE_inithalo_particle(Render *re, ObjectRen *obr, DerivedMesh *dm, Mater
const float vec[3], const float vec1[3],
const float *orco, const float *uvco, float hasize, float vectsize, int seed, const float pa_co[3])
{
+ const bool skip_load_image = (re->r.scemode & R_NO_IMAGE_LOAD) != 0;
HaloRen *har;
MTex *mtex;
float tin, tr, tg, tb, ta;
@@ -1179,7 +1180,7 @@ HaloRen *RE_inithalo_particle(Render *re, ObjectRen *obr, DerivedMesh *dm, Mater
copy_v3_v3(texvec, orco);
}
- hasrgb = externtex(mtex, texvec, &tin, &tr, &tg, &tb, &ta, 0, re->pool);
+ hasrgb = externtex(mtex, texvec, &tin, &tr, &tg, &tb, &ta, 0, re->pool, skip_load_image);
//yn= tin*mtex->colfac;
//zn= tin*mtex->alphafac;
@@ -1223,6 +1224,7 @@ HaloRen *RE_inithalo_particle(Render *re, ObjectRen *obr, DerivedMesh *dm, Mater
}
har->pool = re->pool;
+ har->skip_load_image = (re->r.scemode & R_NO_IMAGE_LOAD) != 0;
return har;
}
@@ -1374,6 +1376,38 @@ ObjectInstanceRen *RE_addRenderInstance(Render *re, ObjectRen *obr, Object *ob,
obi->psysindex= psysindex;
obi->lay= lay;
+ /* Fill particle info */
+ if (obi->psysindex > 0) {
+ int psysindex = 1;
+ int index;
+ ParticleSystem *psys;
+ if (obi->par) {
+ for (psys = obi->par->particlesystem.first; psys; psys = psys->next) {
+ if (psysindex == obi->psysindex)
+ break;
+ ++psysindex;
+ }
+ if (psys) {
+ if (obi->index < psys->totpart)
+ index = obi->index;
+ else {
+ index = psys->child[obi->index - psys->totpart].parent;
+ }
+ if (index >= 0) {
+ ParticleData* p = &psys->particles[index];
+ obi->part_index = index;
+ obi->part_size = p->size;
+ obi->part_age = RE_GetStats(re)->cfra - p->time;
+ obi->part_lifetime = p->lifetime;
+
+ copy_v3_v3(obi->part_co, p->state.co);
+ copy_v3_v3(obi->part_vel, p->state.vel);
+ copy_v3_v3(obi->part_avel, p->state.ave);
+ }
+ }
+ }
+ }
+
if (mat) {
copy_m4_m4(obi->mat, mat);
copy_m3_m4(mat3, mat);
@@ -1387,6 +1421,18 @@ ObjectInstanceRen *RE_addRenderInstance(Render *re, ObjectRen *obr, Object *ob,
return obi;
}
+void RE_instance_get_particle_info(struct ObjectInstanceRen *obi, float *index, float *age, float *lifetime, float co[3], float *size, float vel[3], float angvel[3])
+{
+ *index = obi->part_index;
+ *age = obi->part_age;
+ *lifetime = obi->part_lifetime;
+ copy_v3_v3(co, obi->part_co);
+ *size = obi->part_size;
+ copy_v3_v3(vel, obi->part_vel);
+ copy_v3_v3(angvel, obi->part_avel);
+}
+
+
void RE_makeRenderInstances(Render *re)
{
ObjectInstanceRen *obi, *oldobi;
@@ -1394,7 +1440,7 @@ void RE_makeRenderInstances(Render *re)
int tot;
/* convert list of object instances to an array for index based lookup */
- tot= BLI_countlist(&re->instancetable);
+ tot= BLI_listbase_count(&re->instancetable);
re->objectinstance= MEM_callocN(sizeof(ObjectInstanceRen)*tot, "ObjectInstance");
re->totinstance= tot;
newlist.first= newlist.last= NULL;
diff --git a/source/blender/render/intern/source/shadbuf.c b/source/blender/render/intern/source/shadbuf.c
index 9d83ff1d7e8..0bd4815fb73 100644
--- a/source/blender/render/intern/source/shadbuf.c
+++ b/source/blender/render/intern/source/shadbuf.c
@@ -50,7 +50,6 @@
#include "PIL_time.h"
-#include "renderpipeline.h"
#include "render_types.h"
#include "renderdatabase.h"
#include "rendercore.h"
diff --git a/source/blender/render/intern/source/shadeinput.c b/source/blender/render/intern/source/shadeinput.c
index 7aca6b9ac87..08304533b95 100644
--- a/source/blender/render/intern/source/shadeinput.c
+++ b/source/blender/render/intern/source/shadeinput.c
@@ -39,6 +39,7 @@
#include "DNA_lamp_types.h"
#include "DNA_meshdata_types.h"
#include "DNA_material_types.h"
+#include "DNA_particle_types.h"
#include "BKE_scene.h"
@@ -46,11 +47,9 @@
/* local include */
#include "raycounter.h"
-#include "renderpipeline.h"
#include "render_types.h"
#include "renderdatabase.h"
#include "rendercore.h"
-#include "shadbuf.h"
#include "shading.h"
#include "strand.h"
#include "texture.h"
@@ -157,9 +156,10 @@ void shade_input_do_shade(ShadeInput *shi, ShadeResult *shr)
memset(&shi->raycounter, 0, sizeof(shi->raycounter));
#endif
- if (shi->mat->nodetree && shi->mat->use_nodes)
+ if (shi->mat->nodetree && shi->mat->use_nodes) {
compat = ntreeShaderExecTree(shi->mat->nodetree, shi, shr);
-
+ }
+
/* also run this when node shaders fail, due to incompatible shader nodes */
if (compat == false) {
/* copy all relevant material vars, note, keep this synced with render_types.h */
@@ -425,14 +425,11 @@ void shade_input_set_strand_texco(ShadeInput *shi, StrandRen *strand, StrandVert
}
if (texco & TEXCO_GLOB) {
- copy_v3_v3(shi->gl, shi->co);
- mul_m4_v3(R.viewinv, shi->gl);
+ mul_v3_m4v3(shi->gl, R.viewinv, shi->co);
if (shi->osatex) {
- copy_v3_v3(shi->dxgl, shi->dxco);
- mul_mat3_m4_v3(R.viewinv, shi->dxgl);
- copy_v3_v3(shi->dygl, shi->dyco);
- mul_mat3_m4_v3(R.viewinv, shi->dygl);
+ mul_v3_mat3_m4v3(shi->dxgl, R.viewinv, shi->dxco);
+ mul_v3_mat3_m4v3(shi->dygl, R.viewinv, shi->dyco);
}
}
@@ -635,7 +632,7 @@ void shade_input_calc_viewco(ShadeInput *shi, float x, float y, float z, float v
dyco[2] = 0.0f;
if (dxyview) {
- if (co[2] != 0.0f) fac = 1.0f / co[2]; else fac = 0.0f;
+ fac = (co[2] != 0.0f) ? (1.0f / co[2]) : 0.0f;
dxyview[0] = -R.viewdx * fac;
dxyview[1] = -R.viewdy * fac;
}
diff --git a/source/blender/render/intern/source/shadeoutput.c b/source/blender/render/intern/source/shadeoutput.c
index 6d6bba834ba..39dfa48d3f1 100644
--- a/source/blender/render/intern/source/shadeoutput.c
+++ b/source/blender/render/intern/source/shadeoutput.c
@@ -47,9 +47,7 @@
/* local include */
#include "occlusion.h"
-#include "renderpipeline.h"
#include "render_types.h"
-#include "pixelblending.h"
#include "rendercore.h"
#include "shadbuf.h"
#include "sss.h"
@@ -57,6 +55,8 @@
#include "shading.h" /* own include */
+#include "IMB_colormanagement.h"
+
/* could enable at some point but for now there are far too many conversions */
#ifdef __GNUC__
# pragma GCC diagnostic ignored "-Wdouble-promotion"
@@ -950,7 +950,7 @@ static void ramp_diffuse_result(float *diff, ShadeInput *shi)
if (ma->ramp_col) {
if (ma->rampin_col==MA_RAMP_IN_RESULT) {
- float fac = rgb_to_grayscale(diff);
+ float fac = IMB_colormanagement_get_luminance(diff);
do_colorband(ma->ramp_col, fac, col);
/* blending method */
@@ -962,7 +962,7 @@ static void ramp_diffuse_result(float *diff, ShadeInput *shi)
}
/* r,g,b denote energy, ramp is used with different values to make new material color */
-static void add_to_diffuse(float *diff, ShadeInput *shi, float is, float r, float g, float b)
+static void add_to_diffuse(float diff[3], const ShadeInput *shi, const float is, const float rgb[3])
{
Material *ma= shi->mat;
@@ -971,9 +971,9 @@ static void add_to_diffuse(float *diff, ShadeInput *shi, float is, float r, floa
/* MA_RAMP_IN_RESULT is exceptional */
if (ma->rampin_col==MA_RAMP_IN_RESULT) {
/* normal add */
- diff[0] += r * shi->r;
- diff[1] += g * shi->g;
- diff[2] += b * shi->b;
+ diff[0] += rgb[0] * shi->r;
+ diff[1] += rgb[1] * shi->g;
+ diff[2] += rgb[2] * shi->b;
}
else {
float colt[3], col[4];
@@ -982,40 +982,37 @@ static void add_to_diffuse(float *diff, ShadeInput *shi, float is, float r, floa
/* input */
switch (ma->rampin_col) {
case MA_RAMP_IN_ENERGY:
- /* should use 'rgb_to_grayscale' but we only have a vector version */
- fac= 0.3f*r + 0.58f*g + 0.12f*b;
+ fac = IMB_colormanagement_get_luminance(rgb);
break;
case MA_RAMP_IN_SHADER:
- fac= is;
+ fac = is;
break;
case MA_RAMP_IN_NOR:
- fac= shi->view[0]*shi->vn[0] + shi->view[1]*shi->vn[1] + shi->view[2]*shi->vn[2];
+ fac = dot_v3v3(shi->view, shi->vn);
break;
default:
- fac= 0.0f;
+ fac = 0.0f;
break;
}
do_colorband(ma->ramp_col, fac, col);
/* blending method */
- fac= col[3]*ma->rampfac_col;
- colt[0]= shi->r;
- colt[1]= shi->g;
- colt[2]= shi->b;
+ fac = col[3] * ma->rampfac_col;
+ copy_v3_v3(colt, &shi->r);
ramp_blend(ma->rampblend_col, colt, fac, col);
/* output to */
- diff[0] += r * colt[0];
- diff[1] += g * colt[1];
- diff[2] += b * colt[2];
+ diff[0] += rgb[0] * colt[0];
+ diff[1] += rgb[1] * colt[1];
+ diff[2] += rgb[2] * colt[2];
}
}
else {
- diff[0] += r * shi->r;
- diff[1] += g * shi->g;
- diff[2] += b * shi->b;
+ diff[0] += rgb[0] * shi->r;
+ diff[1] += rgb[1] * shi->g;
+ diff[2] += rgb[2] * shi->b;
}
}
@@ -1025,7 +1022,7 @@ static void ramp_spec_result(float spec_col[3], ShadeInput *shi)
if (ma->ramp_spec && (ma->rampin_spec==MA_RAMP_IN_RESULT)) {
float col[4];
- float fac = rgb_to_grayscale(spec_col);
+ float fac = IMB_colormanagement_get_luminance(spec_col);
do_colorband(ma->ramp_spec, fac, col);
@@ -1478,27 +1475,55 @@ static void shade_one_light(LampRen *lar, ShadeInput *shi, ShadeResult *shr, int
i*= shadfac[3];
shr->shad[3] = shadfac[3]; /* store this for possible check in troublesome cases */
}
+ else {
+ shr->shad[3] = 1.0f; /* No shadow at all! */
+ }
}
}
/* in case 'no diffuse' we still do most calculus, spec can be in shadow.*/
if (!(lar->mode & LA_NO_DIFF)) {
if (i>0.0f) {
- if (ma->mode & MA_SHADOW_TRA)
- add_to_diffuse(shr->shad, shi, is, i*shadfac[0]*lacol[0], i*shadfac[1]*lacol[1], i*shadfac[2]*lacol[2]);
- else
- add_to_diffuse(shr->shad, shi, is, i*lacol[0], i*lacol[1], i*lacol[2]);
+ if (ma->mode & MA_SHADOW_TRA) {
+ const float tcol[3] = {
+ i * shadfac[0] * lacol[0],
+ i * shadfac[1] * lacol[1],
+ i * shadfac[2] * lacol[2],
+ };
+ add_to_diffuse(shr->shad, shi, is, tcol);
+ }
+ else {
+ const float tcol[3] = {
+ i * lacol[0],
+ i * lacol[1],
+ i * lacol[2],
+ };
+ add_to_diffuse(shr->shad, shi, is, tcol);
+ }
}
/* add light for colored shadow */
if (i_noshad>i && !(lashdw[0]==0 && lashdw[1]==0 && lashdw[2]==0)) {
- add_to_diffuse(shr->shad, shi, is, lashdw[0]*(i_noshad-i)*lacol[0], lashdw[1]*(i_noshad-i)*lacol[1], lashdw[2]*(i_noshad-i)*lacol[2]);
+ const float tcol[3] = {
+ lashdw[0] * (i_noshad - i) * lacol[0],
+ lashdw[1] * (i_noshad - i) * lacol[1],
+ lashdw[2] * (i_noshad - i) * lacol[2],
+ };
+ add_to_diffuse(shr->shad, shi, is, tcol);
}
if (i_noshad>0.0f) {
- if (passflag & (SCE_PASS_DIFFUSE|SCE_PASS_SHADOW)) {
- add_to_diffuse(shr->diff, shi, is, i_noshad*lacol[0], i_noshad*lacol[1], i_noshad*lacol[2]);
+ if (passflag & (SCE_PASS_DIFFUSE|SCE_PASS_SHADOW) ||
+ ((passflag & SCE_PASS_COMBINED) && !(shi->combinedflag & SCE_PASS_SHADOW)))
+ {
+ const float tcol[3] = {
+ i_noshad * lacol[0],
+ i_noshad * lacol[1],
+ i_noshad * lacol[2]
+ };
+ add_to_diffuse(shr->diff, shi, is, tcol);
}
- else
+ else {
copy_v3_v3(shr->diff, shr->shad);
+ }
}
}
@@ -1618,10 +1643,10 @@ static void shade_lamp_loop_only_shadow(ShadeInput *shi, ShadeResult *shr)
if (shi->mat->shadowonly_flag == MA_SO_OLD) {
/* Old "Shadows Only" */
- accum+= (1.0f-visifac) + (visifac)*rgb_to_grayscale(shadfac)*shadfac[3];
+ accum+= (1.0f-visifac) + (visifac)*IMB_colormanagement_get_luminance(shadfac)*shadfac[3];
}
else {
- shaded += rgb_to_grayscale(shadfac)*shadfac[3] * visifac * lar->energy;
+ shaded += IMB_colormanagement_get_luminance(shadfac)*shadfac[3] * visifac * lar->energy;
if (shi->mat->shadowonly_flag == MA_SO_SHADOW) {
lightness += visifac * lar->energy;
@@ -1648,7 +1673,8 @@ static void shade_lamp_loop_only_shadow(ShadeInput *shi, ShadeResult *shr)
else { /* shadowonly_flag == MA_SO_SHADED */
/* Use shaded value */
accum = 1.0f - shaded;
- }}
+ }
+ }
shr->alpha= (shi->alpha)*(accum);
if (shr->alpha<0.0f) shr->alpha=0.0f;
@@ -1669,26 +1695,26 @@ static void shade_lamp_loop_only_shadow(ShadeInput *shi, ShadeResult *shr)
if (R.wrld.aomix==WO_AOADD) {
if (shi->mat->shadowonly_flag == MA_SO_OLD) {
- f= f*(1.0f - rgb_to_grayscale(shi->ao));
+ f= f*(1.0f - IMB_colormanagement_get_luminance(shi->ao));
shr->alpha= (shr->alpha + f)*f;
}
else {
- shr->alpha -= f*rgb_to_grayscale(shi->ao);
+ shr->alpha -= f*IMB_colormanagement_get_luminance(shi->ao);
if (shr->alpha<0.0f) shr->alpha=0.0f;
}
}
else /* AO Multiply */
- shr->alpha= (1.0f - f)*shr->alpha + f*(1.0f - (1.0f - shr->alpha)*rgb_to_grayscale(shi->ao));
+ shr->alpha= (1.0f - f)*shr->alpha + f*(1.0f - (1.0f - shr->alpha)*IMB_colormanagement_get_luminance(shi->ao));
}
if (R.wrld.mode & WO_ENV_LIGHT) {
if (shi->mat->shadowonly_flag == MA_SO_OLD) {
- f= R.wrld.ao_env_energy*shi->amb*(1.0f - rgb_to_grayscale(shi->env));
+ f= R.wrld.ao_env_energy*shi->amb*(1.0f - IMB_colormanagement_get_luminance(shi->env));
shr->alpha= (shr->alpha + f)*f;
}
else {
f= R.wrld.ao_env_energy*shi->amb;
- shr->alpha -= f*rgb_to_grayscale(shi->env);
+ shr->alpha -= f*IMB_colormanagement_get_luminance(shi->env);
if (shr->alpha<0.0f) shr->alpha=0.0f;
}
}
@@ -1714,7 +1740,7 @@ void shade_lamp_loop(ShadeInput *shi, ShadeResult *shr)
*/
const int color_passes =
SCE_PASS_COMBINED | SCE_PASS_RGBA | SCE_PASS_DIFFUSE | SCE_PASS_SPEC |
- SCE_PASS_REFLECT | SCE_PASS_NORMAL | SCE_PASS_REFRACT | SCE_PASS_EMIT;
+ SCE_PASS_REFLECT | SCE_PASS_NORMAL | SCE_PASS_REFRACT | SCE_PASS_EMIT | SCE_PASS_SHADOW;
Material *ma= shi->mat;
int passflag= shi->passflag;
@@ -1889,7 +1915,7 @@ void shade_lamp_loop(ShadeInput *shi, ShadeResult *shr)
}
if (shi->combinedflag & SCE_PASS_SHADOW)
- copy_v3_v3(shr->diffshad, shr->shad); /* note, no ';' ! */
+ copy_v3_v3(shr->diffshad, shr->shad);
else
copy_v3_v3(shr->diffshad, shr->diff);
@@ -2062,7 +2088,7 @@ float RE_lamp_get_data(ShadeInput *shi, Object *lamp_obj, float col[4], float lv
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)
+ if (STREQ(go->ob->id.name + 2, "Lamp.002"))
return lamp_get_data_internal(shi, go, col, lv, dist, shadow);
}
return 0.0f;
diff --git a/source/blender/render/intern/source/sss.c b/source/blender/render/intern/source/sss.c
index 7e9003aaee7..553710b4367 100644
--- a/source/blender/render/intern/source/sss.c
+++ b/source/blender/render/intern/source/sss.c
@@ -55,9 +55,8 @@
#include "BLI_ghash.h"
#include "BLI_memarena.h"
-#include "BLF_translation.h"
+#include "BLT_translation.h"
-#include "PIL_time.h"
#include "DNA_material_types.h"
@@ -68,11 +67,7 @@
/* this module */
#include "render_types.h"
-#include "rendercore.h"
-#include "renderdatabase.h"
-#include "shading.h"
#include "sss.h"
-#include "zbuf.h"
/* Generic Multiple Scattering API */
@@ -1036,14 +1031,12 @@ void make_sss_tree(Render *re)
void free_sss(Render *re)
{
if (re->sss_hash) {
- GHashIterator *it= BLI_ghashIterator_new(re->sss_hash);
+ GHashIterator gh_iter;
- while (!BLI_ghashIterator_done(it)) {
- sss_free_tree(BLI_ghashIterator_getValue(it));
- BLI_ghashIterator_step(it);
+ GHASH_ITER (gh_iter, re->sss_hash) {
+ sss_free_tree(BLI_ghashIterator_getValue(&gh_iter));
}
- BLI_ghashIterator_free(it);
BLI_ghash_free(re->sss_hash, NULL, NULL);
re->sss_hash= NULL;
}
diff --git a/source/blender/render/intern/source/strand.c b/source/blender/render/intern/source/strand.c
index 485680da76f..6b52d4aa419 100644
--- a/source/blender/render/intern/source/strand.c
+++ b/source/blender/render/intern/source/strand.c
@@ -47,11 +47,8 @@
#include "render_types.h"
-#include "initrender.h"
#include "rendercore.h"
#include "renderdatabase.h"
-#include "renderpipeline.h"
-#include "pixelblending.h"
#include "shading.h"
#include "strand.h"
#include "zbuf.h"
diff --git a/source/blender/render/intern/source/sunsky.c b/source/blender/render/intern/source/sunsky.c
index 1836b3f48a7..d4e53eb7305 100644
--- a/source/blender/render/intern/source/sunsky.c
+++ b/source/blender/render/intern/source/sunsky.c
@@ -254,14 +254,14 @@ void GetSkyXYZRadiance(struct SunSky *sunsky, float theta, float phi, float colo
float hfade = 1, nfade = 1;
- if (theta > (0.5f * (float)M_PI)) {
+ if (theta > (float)M_PI_2) {
hfade = 1.0f - (theta * (float)M_1_PI - 0.5f) * 2.0f;
hfade = hfade * hfade * (3.0f - 2.0f * hfade);
- theta = 0.5 * M_PI;
+ theta = M_PI_2;
}
- if (sunsky->theta > (0.5f * (float)M_PI)) {
- if (theta <= 0.5f * (float)M_PI) {
+ if (sunsky->theta > (float)M_PI_2) {
+ if (theta <= (float)M_PI_2) {
nfade = 1.0f - (0.5f - theta * (float)M_1_PI) * 2.0f;
nfade *= 1.0f - (sunsky->theta * (float)M_1_PI - 0.5f) * 2.0f;
nfade = nfade * nfade * (3.0f - 2.0f * nfade);
@@ -299,8 +299,7 @@ void GetSkyXYZRadiancef(struct SunSky *sunsky, const float varg[3], float color_
float theta, phi;
float v[3];
- copy_v3_v3(v, (float *)varg);
- normalize_v3(v);
+ normalize_v3_v3(v, varg);
if (v[2] < 0.001f) {
v[2] = 0.001f;
diff --git a/source/blender/render/intern/source/texture_ocean.c b/source/blender/render/intern/source/texture_ocean.c
index 55f4bf3794d..a932123243d 100644
--- a/source/blender/render/intern/source/texture_ocean.c
+++ b/source/blender/render/intern/source/texture_ocean.c
@@ -56,8 +56,6 @@ extern struct Render R;
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
-
-
/* ***** actual texture sampling ***** */
int ocean_texture(Tex *tex, const float texvec[2], TexResult *texres)
{
@@ -75,7 +73,7 @@ int ocean_texture(Tex *tex, const float texvec[2], TexResult *texres)
return 0;
}
else {
- const int do_normals = (omd->flag & MOD_OCEAN_GENERATE_NORMALS);
+ const bool do_normals = (omd->flag & MOD_OCEAN_GENERATE_NORMALS) != 0;
int cfra = R.r.cfra;
int retval = TEX_INT;
diff --git a/source/blender/render/intern/source/volume_precache.c b/source/blender/render/intern/source/volume_precache.c
index 6135a8761bb..78ede01d6c1 100644
--- a/source/blender/render/intern/source/volume_precache.c
+++ b/source/blender/render/intern/source/volume_precache.c
@@ -44,7 +44,7 @@
#include "BLI_voxel.h"
#include "BLI_utildefines.h"
-#include "BLF_translation.h"
+#include "BLT_translation.h"
#include "PIL_time.h"
diff --git a/source/blender/render/intern/source/volumetric.c b/source/blender/render/intern/source/volumetric.c
index d5c4c407bf6..2c0917243a3 100644
--- a/source/blender/render/intern/source/volumetric.c
+++ b/source/blender/render/intern/source/volumetric.c
@@ -41,6 +41,8 @@
#include "RE_shader_ext.h"
+#include "IMB_colormanagement.h"
+
#include "DNA_material_types.h"
#include "DNA_group_types.h"
#include "DNA_lamp_types.h"
@@ -504,7 +506,7 @@ static void vol_shade_one_lamp(struct ShadeInput *shi, const float co[3], const
if (shi->mat->vol.shadeflag & MA_VOL_RECV_EXT_SHADOW) {
mul_v3_fl(lacol, vol_get_shadow(shi, lar, co));
- if (rgb_to_luma_y(lacol) < 0.001f) return;
+ if (IMB_colormanagement_get_luminance(lacol) < 0.001f) return;
}
/* find minimum of volume bounds, or lamp coord */
@@ -538,7 +540,7 @@ static void vol_shade_one_lamp(struct ShadeInput *shi, const float co[3], const
}
}
- if (rgb_to_luma_y(lacol) < 0.001f) return;
+ if (IMB_colormanagement_get_luminance(lacol) < 0.001f) return;
normalize_v3(lv);
p = vol_get_phasefunc(shi, shi->mat->vol.asymmetry, view, lv);
@@ -620,7 +622,7 @@ static void volumeintegrate(struct ShadeInput *shi, float col[4], const float co
if (t0 > t1 * 0.25f) {
/* only use depth cutoff after we've traced a little way into the volume */
- if (rgb_to_luma_y(tr) < shi->mat->vol.depth_cutoff) break;
+ if (IMB_colormanagement_get_luminance(tr) < shi->mat->vol.depth_cutoff) break;
}
vol_get_emission(shi, emit_col, p);
@@ -649,7 +651,7 @@ static void volumeintegrate(struct ShadeInput *shi, float col[4], const float co
add_v3_v3(col, radiance);
/* alpha <-- transmission luminance */
- col[3] = 1.0f - rgb_to_luma_y(tr);
+ col[3] = 1.0f - IMB_colormanagement_get_luminance(tr);
}
/* the main entry point for volume shading */
@@ -790,7 +792,7 @@ void shade_volume_shadow(struct ShadeInput *shi, struct ShadeResult *shr, struct
copy_v3_v3(shr->combined, tr);
- shr->combined[3] = 1.0f - rgb_to_luma_y(tr);
+ shr->combined[3] = 1.0f - IMB_colormanagement_get_luminance(tr);
shr->alpha = shr->combined[3];
}
diff --git a/source/blender/render/intern/source/voxeldata.c b/source/blender/render/intern/source/voxeldata.c
index 50b5e392b3f..bb92a8f7e8a 100644
--- a/source/blender/render/intern/source/voxeldata.c
+++ b/source/blender/render/intern/source/voxeldata.c
@@ -46,27 +46,29 @@
#include "BLI_voxel.h"
#include "BLI_utildefines.h"
-#include "BLF_translation.h"
+#include "BLT_translation.h"
#include "IMB_imbuf.h"
#include "IMB_imbuf_types.h"
+#include "BKE_cloth.h"
#include "BKE_global.h"
#include "BKE_image.h"
#include "BKE_main.h"
#include "BKE_modifier.h"
#include "smoke_API.h"
+#include "BPH_mass_spring.h"
#include "DNA_texture_types.h"
#include "DNA_object_force.h"
#include "DNA_object_types.h"
+#include "DNA_particle_types.h"
#include "DNA_modifier_types.h"
#include "DNA_smoke_types.h"
#include "render_types.h"
-#include "renderdatabase.h"
#include "texture.h"
#include "voxeldata.h"
@@ -365,6 +367,27 @@ static void init_frame_smoke(VoxelData *vd, int cfra)
#endif
}
+static void init_frame_hair(VoxelData *vd, int UNUSED(cfra))
+{
+ Object *ob;
+ ModifierData *md;
+ bool found = false;
+
+ vd->dataset = NULL;
+ if (vd->object == NULL) return;
+ ob = vd->object;
+
+ if ((md = (ModifierData *)modifiers_findByType(ob, eModifierType_ParticleSystem))) {
+ ParticleSystemModifierData *pmd = (ParticleSystemModifierData *)md;
+
+ if (pmd->psys && pmd->psys->clmd) {
+ found |= BPH_cloth_solver_get_texture_data(ob, pmd->psys->clmd, vd);
+ }
+ }
+
+ vd->ok = found;
+}
+
void cache_voxeldata(Tex *tex, int scene_frame)
{
VoxelData *vd = tex->vd;
@@ -398,6 +421,9 @@ void cache_voxeldata(Tex *tex, int scene_frame)
case TEX_VD_SMOKE:
init_frame_smoke(vd, scene_frame);
return;
+ case TEX_VD_HAIR:
+ init_frame_hair(vd, scene_frame);
+ return;
case TEX_VD_BLENDERVOXEL:
BLI_path_abs(path, G.main->name);
if (!BLI_exists(path)) return;
diff --git a/source/blender/render/intern/source/zbuf.c b/source/blender/render/intern/source/zbuf.c
index 87e546ef24e..58ac34080b9 100644
--- a/source/blender/render/intern/source/zbuf.c
+++ b/source/blender/render/intern/source/zbuf.c
@@ -63,12 +63,10 @@
#include "pixelblending.h"
#include "render_result.h"
#include "render_types.h"
-#include "renderpipeline.h"
#include "renderdatabase.h"
#include "rendercore.h"
#include "shadbuf.h"
#include "shading.h"
-#include "sss.h"
#include "strand.h"
/* own includes */
@@ -332,8 +330,8 @@ static void zbuffillAc4(ZSpan *zspan, int obi, int zvlnr,
/* clipped */
if (zspan->minp2==NULL || zspan->maxp2==NULL) return;
- if (zspan->miny1 < zspan->miny2) my0= zspan->miny2; else my0= zspan->miny1;
- if (zspan->maxy1 > zspan->maxy2) my2= zspan->maxy2; else my2= zspan->maxy1;
+ my0 = max_ii(zspan->miny1, zspan->miny2);
+ my2 = min_ii(zspan->maxy1, zspan->maxy2);
if (my2<my0) return;
@@ -1075,8 +1073,8 @@ static void zbuffillGLinv4(ZSpan *zspan, int obi, int zvlnr,
/* clipped */
if (zspan->minp2==NULL || zspan->maxp2==NULL) return;
- if (zspan->miny1 < zspan->miny2) my0= zspan->miny2; else my0= zspan->miny1;
- if (zspan->maxy1 > zspan->maxy2) my2= zspan->maxy2; else my2= zspan->maxy1;
+ my0 = max_ii(zspan->miny1, zspan->miny2);
+ my2 = min_ii(zspan->maxy1, zspan->maxy2);
// printf("my %d %d\n", my0, my2);
if (my2<my0) return;
@@ -1198,8 +1196,8 @@ static void zbuffillGL4(ZSpan *zspan, int obi, int zvlnr,
/* clipped */
if (zspan->minp2==NULL || zspan->maxp2==NULL) return;
- if (zspan->miny1 < zspan->miny2) my0= zspan->miny2; else my0= zspan->miny1;
- if (zspan->maxy1 > zspan->maxy2) my2= zspan->maxy2; else my2= zspan->maxy1;
+ my0 = max_ii(zspan->miny1, zspan->miny2);
+ my2 = min_ii(zspan->maxy1, zspan->maxy2);
// printf("my %d %d\n", my0, my2);
if (my2<my0) return;
@@ -1326,8 +1324,8 @@ static void zbuffillGL_onlyZ(ZSpan *zspan, int UNUSED(obi), int UNUSED(zvlnr),
/* clipped */
if (zspan->minp2==NULL || zspan->maxp2==NULL) return;
- if (zspan->miny1 < zspan->miny2) my0= zspan->miny2; else my0= zspan->miny1;
- if (zspan->maxy1 > zspan->maxy2) my2= zspan->maxy2; else my2= zspan->maxy1;
+ my0 = max_ii(zspan->miny1, zspan->miny2);
+ my2 = min_ii(zspan->maxy1, zspan->maxy2);
// printf("my %d %d\n", my0, my2);
if (my2<my0) return;
@@ -1428,8 +1426,8 @@ void zspan_scanconvert_strand(ZSpan *zspan, void *handle, float *v1, float *v2,
/* clipped */
if (zspan->minp2==NULL || zspan->maxp2==NULL) return;
- if (zspan->miny1 < zspan->miny2) my0= zspan->miny2; else my0= zspan->miny1;
- if (zspan->maxy1 > zspan->maxy2) my2= zspan->maxy2; else my2= zspan->maxy1;
+ my0 = max_ii(zspan->miny1, zspan->miny2);
+ my2 = min_ii(zspan->maxy1, zspan->maxy2);
// printf("my %d %d\n", my0, my2);
if (my2<my0) return;
@@ -1515,7 +1513,7 @@ void zspan_scanconvert(ZSpan *zspan, void *handle, float *v1, float *v2, float *
float x0, y0, x1, y1, x2, y2, z0, z1, z2;
float u, v, uxd, uyd, vxd, vyd, uy0, vy0, xx1;
const float *span1, *span2;
- int x, y, sn1, sn2, rectx= zspan->rectx, my0, my2;
+ int i, j, x, y, sn1, sn2, rectx = zspan->rectx, my0, my2;
/* init */
zbuf_init_span(zspan);
@@ -1528,8 +1526,8 @@ void zspan_scanconvert(ZSpan *zspan, void *handle, float *v1, float *v2, float *
/* clipped */
if (zspan->minp2==NULL || zspan->maxp2==NULL) return;
- if (zspan->miny1 < zspan->miny2) my0= zspan->miny2; else my0= zspan->miny1;
- if (zspan->maxy1 > zspan->maxy2) my2= zspan->maxy2; else my2= zspan->maxy1;
+ my0 = max_ii(zspan->miny1, zspan->miny2);
+ my2 = min_ii(zspan->maxy1, zspan->maxy2);
// printf("my %d %d\n", my0, my2);
if (my2<my0) return;
@@ -1576,7 +1574,7 @@ void zspan_scanconvert(ZSpan *zspan, void *handle, float *v1, float *v2, float *
span2= zspan->span1+my2;
}
- for (y=my2; y>=my0; y--, span1--, span2--) {
+ for (i = 0, y = my2; y >= my0; i++, y--, span1--, span2--) {
sn1= floor(*span1);
sn2= floor(*span2);
@@ -1585,14 +1583,12 @@ void zspan_scanconvert(ZSpan *zspan, void *handle, float *v1, float *v2, float *
if (sn2>=rectx) sn2= rectx-1;
if (sn1<0) sn1= 0;
- u= (double)sn1*uxd + uy0;
- v= (double)sn1*vxd + vy0;
+ u = (((double)sn1 * uxd) + uy0) - (i * uyd);
+ v = (((double)sn1 * vxd) + vy0) - (i * vyd);
- for (x= sn1; x<=sn2; x++, u+=uxd, v+=vxd)
- func(handle, x, y, u, v);
-
- uy0 -= uyd;
- vy0 -= vyd;
+ for (j = 0, x = sn1; x <= sn2; j++, x++) {
+ func(handle, x, y, u + (j * uxd), v + (j * vxd));
+ }
}
}
@@ -2065,8 +2061,6 @@ static void zmask_rect(int *rectz, int *rectp, int xs, int ys, int neg)
}
-
-
/* ***************** ZBUFFER MAIN ROUTINES **************** */
void zbuffer_solid(RenderPart *pa, RenderLayer *rl, void(*fillfunc)(RenderPart *, ZSpan *, int, void *), void *data)
@@ -2083,8 +2077,8 @@ void zbuffer_solid(RenderPart *pa, RenderLayer *rl, void(*fillfunc)(RenderPart *
unsigned int lay= rl->lay, lay_zmask= rl->lay_zmask;
int i, v, zvlnr, zsample, samples, c1, c2, c3, c4=0;
short nofill=0, env=0, wire=0, zmaskpass=0;
- short all_z= (rl->layflag & SCE_LAY_ALL_Z) && !(rl->layflag & SCE_LAY_ZMASK);
- short neg_zmask= (rl->layflag & SCE_LAY_ZMASK) && (rl->layflag & SCE_LAY_NEG_ZMASK);
+ const bool all_z = (rl->layflag & SCE_LAY_ALL_Z) && !(rl->layflag & SCE_LAY_ZMASK);
+ const bool neg_zmask = (rl->layflag & SCE_LAY_ZMASK) && (rl->layflag & SCE_LAY_NEG_ZMASK);
zbuf_make_winmat(&R, winmat);
@@ -2486,8 +2480,8 @@ static void zbuffill_sss(ZSpan *zspan, int obi, int zvlnr,
/* clipped */
if (zspan->minp2==NULL || zspan->maxp2==NULL) return;
- if (zspan->miny1 < zspan->miny2) my0= zspan->miny2; else my0= zspan->miny1;
- if (zspan->maxy1 > zspan->maxy2) my2= zspan->maxy2; else my2= zspan->maxy1;
+ my0 = max_ii(zspan->miny1, zspan->miny2);
+ my2 = min_ii(zspan->maxy1, zspan->maxy2);
if (my2<my0) return;
@@ -2687,8 +2681,8 @@ static void zbuf_fill_in_rgba(ZSpan *zspan, DrawBufPixel *col, float *v1, float
/* clipped */
if (zspan->minp2==NULL || zspan->maxp2==NULL) return;
- if (zspan->miny1 < zspan->miny2) my0= zspan->miny2; else my0= zspan->miny1;
- if (zspan->maxy1 > zspan->maxy2) my2= zspan->maxy2; else my2= zspan->maxy1;
+ my0 = max_ii(zspan->miny1, zspan->miny2);
+ my2 = min_ii(zspan->maxy1, zspan->maxy2);
// printf("my %d %d\n", my0, my2);
if (my2<my0) return;
@@ -3965,7 +3959,7 @@ static void reset_sky_speedvectors(RenderPart *pa, RenderLayer *rl, float *rectf
float *fp, *col;
int a;
- fp= RE_RenderLayerGetPass(rl, SCE_PASS_VECTOR);
+ fp = RE_RenderLayerGetPass(rl, SCE_PASS_VECTOR, R.viewname);
if (fp==NULL) return;
col= rectf+3;
@@ -4058,9 +4052,10 @@ unsigned short *zbuffer_transp_shade(RenderPart *pa, RenderLayer *rl, float *pas
/* zero alpha pixels get speed vector max again */
if (addpassflag & SCE_PASS_VECTOR)
- if (rl->layflag & SCE_LAY_SOLID)
- reset_sky_speedvectors(pa, rl, rl->acolrect?rl->acolrect:rl->rectf); /* if acolrect is set we use it */
-
+ if (rl->layflag & SCE_LAY_SOLID) {
+ float *rect = RE_RenderLayerGetPass(rl, SCE_PASS_COMBINED, R.viewname);
+ reset_sky_speedvectors(pa, rl, rl->acolrect ? rl->acolrect : rect); /* if acolrect is set we use it */
+ }
/* filtered render, for now we assume only 1 filter size */
if (pa->crop) {
crop= 1;
@@ -4245,8 +4240,9 @@ unsigned short *zbuffer_transp_shade(RenderPart *pa, RenderLayer *rl, float *pas
alpha= samp_shr[a].combined[3];
if (alpha!=0.0f) {
RenderLayer *rl= ssamp.rlpp[a];
-
- addAlphaOverFloat(rl->rectf + 4*od, samp_shr[a].combined);
+
+ float *rect = RE_RenderLayerGetPass(rl, SCE_PASS_COMBINED, R.viewname);
+ addAlphaOverFloat(rect + 4 * od, samp_shr[a].combined);
add_transp_passes(rl, od, &samp_shr[a], alpha);
if (addpassflag & SCE_PASS_VECTOR)
diff --git a/source/blender/windowmanager/CMakeLists.txt b/source/blender/windowmanager/CMakeLists.txt
index 5f993297840..c5e8cbf1260 100644
--- a/source/blender/windowmanager/CMakeLists.txt
+++ b/source/blender/windowmanager/CMakeLists.txt
@@ -29,6 +29,7 @@ set(INC
../blenkernel
../blenlib
../blenloader
+ ../blentranslation
../compositor
../editors/include
../gpu
@@ -40,12 +41,12 @@ set(INC
../../gameengine/BlenderRoutines
../../../intern/ghost
../../../intern/guardedalloc
+ ../../../intern/glew-mx
../../../intern/memutil
)
set(INC_SYS
${ZLIB_INCLUDE_DIRS}
- ${OPENGL_INCLUDE_DIR}
${GLEW_INCLUDE_PATH}
)
@@ -64,6 +65,7 @@ set(SRC
intern/wm_operators.c
intern/wm_subwindow.c
intern/wm_window.c
+ intern/wm_stereo.c
WM_api.h
WM_keymap.h
@@ -78,7 +80,15 @@ set(SRC
wm_window.h
)
-add_definitions(-DGLEW_STATIC)
+if(WITH_AUDASPACE)
+ add_definitions(${AUDASPACE_DEFINITIONS})
+
+ list(APPEND INC_SYS
+ ${AUDASPACE_C_INCLUDE_DIRS}
+ )
+endif()
+
+add_definitions(${GL_DEFINITIONS})
if(WITH_INTERNATIONAL)
add_definitions(-DWITH_INTERNATIONAL)
@@ -107,6 +117,8 @@ endif()
if(WITH_HEADLESS)
add_definitions(-DWITH_HEADLESS)
+elseif(WITH_X11)
+ add_definitions(-DWITH_X11)
endif()
if(WITH_PYTHON)
@@ -128,12 +140,19 @@ if(WITH_BUILDINFO)
add_definitions(-DWITH_BUILDINFO)
endif()
-if(WIN322)
+if(WITH_OPENSUBDIV)
+ add_definitions(-DWITH_OPENSUBDIV)
list(APPEND INC
- ../../../intern/utfconv
+ ../../../intern/opensubdiv
)
endif()
+if(WIN32)
+ if(WITH_INPUT_IME)
+ add_definitions(-DWITH_INPUT_IME)
+ endif()
+endif()
+
if(WITH_COMPOSITOR)
add_definitions(-DWITH_COMPOSITOR)
endif()
diff --git a/source/blender/windowmanager/SConscript b/source/blender/windowmanager/SConscript
index 00d363e1539..ec1b265d800 100644
--- a/source/blender/windowmanager/SConscript
+++ b/source/blender/windowmanager/SConscript
@@ -36,11 +36,13 @@ incs = [
'#/intern/guardedalloc',
'#/intern/memutil',
'#/source/gameengine/BlenderRoutines',
- '#/extern/glew/include',
+ env['BF_GLEW_INC'],
+ '#/intern/glew-mx',
'../blenfont',
'../blenkernel',
'../blenlib',
'../blenloader',
+ '../blentranslation',
'../compositor',
'../editors/include',
'../gpu',
@@ -54,7 +56,8 @@ incs = [
]
incs = ' '.join(incs)
-defs = [ 'GLEW_STATIC' ]
+defs = []
+defs += env['BF_GL_DEFINITIONS']
if env['WITH_BF_PYTHON']:
defs.append('WITH_PYTHON')
@@ -64,11 +67,18 @@ if env['WITH_BF_COLLADA']:
if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'linuxcross', 'win64-vc', 'win64-mingw'):
incs += ' ' + env['BF_PTHREADS_INC']
- incs += ' ../../intern/utfconv'
if env['BF_BUILDINFO']:
defs.append('WITH_BUILDINFO')
+if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'win64-vc', 'win64-mingw'):
+ if env['WITH_BF_IME']:
+ defs.append('WITH_INPUT_IME')
+
+if env['WITH_BF_AUDASPACE']:
+ defs += env['BF_AUDASPACE_DEF']
+ incs += ' ' + env['BF_AUDASPACE_C_INC']
+
if env['WITH_BF_INTERNATIONAL']:
defs.append('WITH_INTERNATIONAL')
@@ -78,4 +88,11 @@ if env['WITH_BF_COMPOSITOR']:
if env['WITH_BF_PYTHON_SECURITY']:
defs.append("WITH_PYTHON_SECURITY")
+if env['OURPLATFORM'] in ('linux', 'openbsd3', 'sunos5', 'freebsd7', 'freebsd8', 'freebsd9', 'aix4', 'aix5'):
+ defs.append("WITH_X11")
+
+if env['WITH_BF_OPENSUBDIV']:
+ defs.append("WITH_OPENSUBDIV")
+ incs += ' #intern/opensubdiv'
+
env.BlenderLib ( 'bf_windowmanager', sources, Split(incs), defines=defs, libtype=['core'], priority=[5] )
diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h
index e1cd334637a..abbbe759858 100644
--- a/source/blender/windowmanager/WM_api.h
+++ b/source/blender/windowmanager/WM_api.h
@@ -47,18 +47,17 @@ extern "C" {
#endif
struct bContext;
+struct GHashIterator;
struct IDProperty;
struct wmEvent;
struct wmEventHandler;
struct wmGesture;
struct wmJob;
-struct wmNotifier;
struct wmOperatorType;
struct wmOperator;
struct rcti;
struct PointerRNA;
struct PropertyRNA;
-struct EnumPropertyItem;
struct MenuType;
struct wmDropBox;
struct wmDrag;
@@ -104,6 +103,7 @@ void WM_window_open_temp (struct bContext *C, struct rcti *position, int type);
/* returns true if draw method is triple buffer */
bool WM_is_draw_triple(struct wmWindow *win);
+bool WM_stereo3d_enabled(struct wmWindow *win, bool only_fullscreen_test);
/* files */
@@ -130,6 +130,7 @@ void WM_paint_cursor_end(struct wmWindowManager *wm, void *handle);
void WM_paint_cursor_tag_redraw(struct wmWindow *win, struct ARegion *ar);
void WM_cursor_warp (struct wmWindow *win, int x, int y);
+void WM_cursor_compatible_xy(wmWindow *win, int *x, int *y);
float WM_cursor_pressure (const struct wmWindow *win);
/* event map */
@@ -151,7 +152,7 @@ typedef void (*wmUIHandlerRemoveFunc)(struct bContext *C, void *userdata);
struct wmEventHandler *WM_event_add_ui_handler(
const struct bContext *C, ListBase *handlers,
wmUIHandlerFunc ui_handle, wmUIHandlerRemoveFunc ui_remove,
- void *userdata, const bool accept_dbl_click);
+ void *userdata, const char flag);
void WM_event_remove_ui_handler(
ListBase *handlers,
wmUIHandlerFunc ui_handle, wmUIHandlerRemoveFunc ui_remove,
@@ -165,28 +166,52 @@ void WM_event_free_ui_handler_all(
struct wmEventHandler *WM_event_add_modal_handler(struct bContext *C, struct wmOperator *op);
void WM_event_remove_handlers(struct bContext *C, ListBase *handlers);
+/* handler flag */
+enum {
+ WM_HANDLER_BLOCKING = (1 << 0), /* after this handler all others are ignored */
+ WM_HANDLER_ACCEPT_DBL_CLICK = (1 << 1), /* handler accepts double key press events */
+
+ /* internal */
+ WM_HANDLER_DO_FREE = (1 << 7), /* handler tagged to be freed in wm_handlers_do() */
+};
+
struct wmEventHandler *WM_event_add_dropbox_handler(ListBase *handlers, ListBase *dropboxes);
/* mouse */
void WM_event_add_mousemove(struct bContext *C);
bool WM_modal_tweak_exit(const struct wmEvent *event, int tweak_event);
+bool WM_event_is_absolute(const struct wmEvent *event);
+
+ /* 3D mouse */
+void WM_ndof_deadzone_set(float deadzone);
/* notifiers */
void WM_event_add_notifier(const struct bContext *C, unsigned int type, void *reference);
void WM_main_add_notifier(unsigned int type, void *reference);
void WM_main_remove_notifier_reference(const void *reference);
+void WM_main_remove_editor_id_reference(const struct ID *id);
/* reports */
+void WM_report_banner_show(const struct bContext *C);
void WM_report(const struct bContext *C, ReportType type, const char *message);
void WM_reportf(const struct bContext *C, ReportType type, const char *format, ...) ATTR_PRINTF_FORMAT(3, 4);
-void wm_event_add(struct wmWindow *win, const struct wmEvent *event_to_add);
-void wm_event_init_from_window(struct wmWindow *win, struct wmEvent *event);
+void wm_event_add_ex(
+ struct wmWindow *win, const struct wmEvent *event_to_add,
+ const struct wmEvent *event_to_add_after)
+ ATTR_NONNULL(1, 2);
+void wm_event_add(
+ struct wmWindow *win, const struct wmEvent *event_to_add)
+ ATTR_NONNULL(1, 2);
+
+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);
+struct wmTimer *WM_event_add_timer_notifier(struct wmWindowManager *wm, struct wmWindow *win, unsigned int type, double timestep);
void WM_event_remove_timer(struct wmWindowManager *wm, struct wmWindow *win, struct wmTimer *timer);
+void WM_event_remove_timer_notifier(struct wmWindowManager *wm, struct wmWindow *win, struct wmTimer *timer);
void WM_event_timer_sleep(struct wmWindowManager *wm, struct wmWindow *win, struct wmTimer *timer, bool do_sleep);
/* operator api, default callbacks */
@@ -223,12 +248,13 @@ void WM_operator_stack_clear(struct wmWindowManager *wm);
void WM_operator_handlers_clear(wmWindowManager *wm, struct wmOperatorType *ot);
struct wmOperatorType *WM_operatortype_find(const char *idname, bool quiet);
-struct GHashIterator *WM_operatortype_iter(void);
+void WM_operatortype_iter(struct GHashIterator *ghi);
void WM_operatortype_append(void (*opfunc)(struct wmOperatorType *));
void WM_operatortype_append_ptr(void (*opfunc)(struct wmOperatorType *, void *), void *userdata);
void WM_operatortype_append_macro_ptr(void (*opfunc)(struct wmOperatorType *, void *), void *userdata);
void WM_operatortype_remove_ptr(struct wmOperatorType *ot);
bool WM_operatortype_remove(const char *idname);
+void WM_operatortype_last_properties_clear_all(void);
struct wmOperatorType *WM_operatortype_append_macro(const char *idname, const char *name, const char *description, int flag);
struct wmOperatorTypeMacro *WM_operatortype_macro_define(struct wmOperatorType *ot, const char *idname);
@@ -253,7 +279,7 @@ 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_filesel(struct wmOperatorType *ot, int filter, short type, short action, short flag, short display, short sort);
void WM_operator_properties_border(struct wmOperatorType *ot);
void WM_operator_properties_border_to_rcti(struct wmOperator *op, struct rcti *rect);
void WM_operator_properties_border_to_rctf(struct wmOperator *op, rctf *rect);
@@ -266,6 +292,7 @@ void WM_operator_properties_select_action_simple(struct wmOperatorType *ot, int
bool WM_operator_check_ui_enabled(const struct bContext *C, const char *idname);
wmOperator *WM_operator_last_redo(const struct bContext *C);
+ID *WM_operator_drop_load_path(struct bContext *C, struct wmOperator *op, const short idcode);
bool WM_operator_last_properties_init(struct wmOperator *op);
bool WM_operator_last_properties_store(struct wmOperator *op);
@@ -368,7 +395,9 @@ void wmOrtho2_pixelspace(const float x, const float y);
/* utilities */
void WM_framebuffer_index_set(int index);
+void WM_framebuffer_index_get(int index, int *r_col);
int WM_framebuffer_to_index(unsigned int col);
+void WM_framebuffer_to_index_array(unsigned int *col, const unsigned int size);
/* threaded Jobs Manager */
enum {
@@ -389,12 +418,13 @@ enum {
WM_JOB_TYPE_OBJECT_SIM_FLUID,
WM_JOB_TYPE_OBJECT_BAKE_TEXTURE,
WM_JOB_TYPE_OBJECT_BAKE,
- WM_JOB_TYPE_FILESEL_THUMBNAIL,
+ WM_JOB_TYPE_FILESEL_READDIR,
WM_JOB_TYPE_CLIP_BUILD_PROXY,
WM_JOB_TYPE_CLIP_TRACK_MARKERS,
WM_JOB_TYPE_CLIP_SOLVE_CAMERA,
WM_JOB_TYPE_CLIP_PREFETCH,
WM_JOB_TYPE_SEQ_BUILD_PROXY,
+ WM_JOB_TYPE_SEQ_BUILD_PREVIEW,
/* add as needed, screencast, seq proxy build
* if having hard coded values is a problem */
};
@@ -458,6 +488,10 @@ void WM_event_ndof_to_quat(const struct wmNDOFMotionData *ndof, float q[4
float WM_event_tablet_data(const struct wmEvent *event, int *pen_flip, float tilt[2]);
bool WM_event_is_tablet(const struct wmEvent *event);
+#ifdef WITH_INPUT_IME
+bool WM_event_is_ime_switch(const struct wmEvent *event);
+#endif
+
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/windowmanager/WM_keymap.h b/source/blender/windowmanager/WM_keymap.h
index c6c7314e963..28a8340cd92 100644
--- a/source/blender/windowmanager/WM_keymap.h
+++ b/source/blender/windowmanager/WM_keymap.h
@@ -68,7 +68,7 @@ wmKeyMapItem *WM_keymap_add_menu_pie(struct wmKeyMap *keymap, const char *idname
int val, int modifier, int keymodifier);
bool WM_keymap_remove_item(struct wmKeyMap *keymap, struct wmKeyMapItem *kmi);
-int WM_keymap_item_to_string(wmKeyMapItem *kmi, char *str, const int len);
+int WM_keymap_item_to_string(wmKeyMapItem *kmi, const bool compact, const int len, char *r_str);
wmKeyMap *WM_keymap_list_find(ListBase *lb, const char *idname, int spaceid, int regionid);
wmKeyMap *WM_keymap_find(struct wmKeyConfig *keyconf, const char *idname, int spaceid, int regionid);
@@ -82,6 +82,14 @@ int WM_keymap_item_compare(struct wmKeyMapItem *k1, struct wmKeyMapItem *k2);
/* Modal Keymap */
+int WM_modalkeymap_items_to_string(
+ struct wmKeyMap *km, const int propvalue, const bool compact, const int len, char *r_str);
+int WM_modalkeymap_operator_items_to_string(
+ struct wmOperatorType *ot, const int propvalue, const bool compact, const int len, char *r_str);
+char *WM_modalkeymap_operator_items_to_string_buf(
+ struct wmOperatorType *ot, const int propvalue, const bool compact,
+ const int max_len, int *r_available_len, char **r_str);
+
wmKeyMap *WM_modalkeymap_add(struct wmKeyConfig *keyconf, const char *idname, struct EnumPropertyItem *items);
wmKeyMap *WM_modalkeymap_get(struct wmKeyConfig *keyconf, const char *idname);
wmKeyMapItem *WM_modalkeymap_add_item(struct wmKeyMap *km, int type, int val, int modifier, int keymodifier, int value);
@@ -98,13 +106,17 @@ int WM_keymap_map_type_get(struct wmKeyMapItem *kmi);
/* Key Event */
-const char *WM_key_event_string(short type);
+const char *WM_key_event_string(const short type, const bool compact);
+int WM_keymap_item_raw_to_string(
+ const short shift, const short ctrl, const short alt, const short oskey, const short keymodifier,
+ const short val, const short type, const bool compact, const int len, char *r_str);
int WM_key_event_operator_id(
const struct bContext *C, const char *opname, int opcontext,
- struct IDProperty *properties, const bool is_hotkey, struct wmKeyMap **keymap_r);
+ struct IDProperty *properties, const bool is_hotkey,
+ struct wmKeyMap **r_keymap);
char *WM_key_event_operator_string(
const struct bContext *C, const char *opname, int opcontext,
- struct IDProperty *properties, const bool is_strict, char *str, int len);
+ struct IDProperty *properties, const bool is_strict, int len, char *r_str);
const char *WM_bool_as_string(bool test);
diff --git a/source/blender/windowmanager/WM_types.h b/source/blender/windowmanager/WM_types.h
index ff252f0fc20..3c0e99bddd0 100644
--- a/source/blender/windowmanager/WM_types.h
+++ b/source/blender/windowmanager/WM_types.h
@@ -94,12 +94,12 @@
* </pre>
*
* A common way to get the space from the ScrArea:
- * <pre>
- * if (sa->spacetype == SPACE_VIEW3D) {
- * View3D *v3d = sa->spacedata.first;
- * ...
- * }
- * </pre>
+ * \code{.c}
+ * if (sa->spacetype == SPACE_VIEW3D) {
+ * View3D *v3d = sa->spacedata.first;
+ * ...
+ * }
+ * \endcode
*/
#ifdef __cplusplus
@@ -109,7 +109,6 @@ extern "C" {
struct bContext;
struct wmEvent;
struct wmWindowManager;
-struct uiLayout;
struct wmOperator;
struct ImBuf;
@@ -124,17 +123,22 @@ struct ImBuf;
/* ************** wmOperatorType ************************ */
/* flag */
-#define OPTYPE_REGISTER 1 /* register operators in stack after finishing */
-#define OPTYPE_UNDO 2 /* do undo push after after */
-#define OPTYPE_BLOCKING 4 /* let blender grab all input from the WM (X11) */
-#define OPTYPE_MACRO 8
-#define OPTYPE_GRAB_POINTER 16 /* grabs the cursor and optionally enables continuous cursor wrapping */
-#define OPTYPE_PRESET 32 /* show preset menu */
-#define OPTYPE_INTERNAL 64 /* some operators are mainly for internal use
- * and don't make sense to be accessed from the
- * search menu, even if poll() returns true.
- * currently only used for the search toolbox */
-#define OPTYPE_LOCK_BYPASS 128 /* Allow operator to run when interface is locked */
+enum {
+ OPTYPE_REGISTER = (1 << 0), /* register operators in stack after finishing */
+ OPTYPE_UNDO = (1 << 1), /* do undo push after after */
+ OPTYPE_BLOCKING = (1 << 2), /* let blender grab all input from the WM (X11) */
+ OPTYPE_MACRO = (1 << 3),
+ OPTYPE_GRAB_CURSOR = (1 << 4), /* grabs the cursor and optionally enables continuous cursor wrapping */
+ OPTYPE_PRESET = (1 << 5), /* show preset menu */
+
+ /* some operators are mainly for internal use
+ * and don't make sense to be accessed from the
+ * search menu, even if poll() returns true.
+ * currently only used for the search toolbox */
+ OPTYPE_INTERNAL = (1 << 6),
+
+ OPTYPE_LOCK_BYPASS = (1 << 7), /* Allow operator to run when interface is locked */
+};
/* context to call operator in for WM_operator_name_call */
/* rna_ui.c contains EnumPropertyItem's of these, keep in sync */
@@ -169,7 +173,7 @@ enum {
#define KM_OSKEY2 128
/* KM_MOD_ flags for wmKeyMapItem and wmEvent.alt/shift/oskey/ctrl */
-/* note that KM_ANY and false are used with these defines too */
+/* note that KM_ANY and KM_NOTHING are used with these defines too */
#define KM_MOD_FIRST 1
#define KM_MOD_SECOND 2
@@ -239,6 +243,7 @@ typedef struct wmNotifier {
#define NC_MASK (21<<24)
#define NC_GPENCIL (22<<24)
#define NC_LINESTYLE (23<<24)
+#define NC_CAMERA (24<<24)
/* data type, 256 entries is enough, it can overlap */
#define NOTE_DATA 0x00FF0000
@@ -297,6 +302,7 @@ typedef struct wmNotifier {
#define ND_POINTCACHE (28<<16)
#define ND_PARENT (29<<16)
#define ND_LOD (30<<16)
+#define ND_DRAW_RENDER_VIEWPORT (31<<16) /* for camera & sequencer viewport update, also /w NC_SCENE */
/* NC_MATERIAL Material */
#define ND_SHADING (30<<16)
@@ -324,6 +330,9 @@ typedef struct wmNotifier {
#define ND_NLA_ACTCHANGE (74<<16)
#define ND_FCURVES_ORDER (75<<16)
+ /* NC_GPENCIL */
+#define ND_GPENCIL_EDITMODE (85<<16)
+
/* NC_GEOM Geometry */
/* Mesh, Curve, MetaBall, Armature, .. */
#define ND_SELECT (90<<16)
@@ -352,6 +361,7 @@ typedef struct wmNotifier {
#define ND_SPACE_NODE_VIEW (17<<16)
#define ND_SPACE_CHANGED (18<<16) /*sent to a new editor type after it's replaced an old one*/
#define ND_SPACE_CLIP (19<<16)
+#define ND_SPACE_FILE_PREVIEW (20<<16)
/* subtype, 256 entries too */
#define NOTE_SUBTYPE 0x0000FF00
@@ -449,7 +459,7 @@ typedef struct wmEvent {
const char *keymap_idname;
/* tablet info, only use when the tablet is active */
- struct wmTabletData *tablet_data;
+ const struct wmTabletData *tablet_data;
/* custom data */
short custom; /* custom data type, stylus, 6dof, see wm_event_types.h */
@@ -554,9 +564,7 @@ typedef struct wmOperatorType {
/* pointer to modal keymap, do not free! */
struct wmKeyMap *modalkeymap;
- /* only used for operators defined with python
- * use to store pointers to python functions */
- void *pyop_data;
+ /* python needs the operator type as well */
int (*pyop_poll)(struct bContext *, struct wmOperatorType *ot) ATTR_WARN_UNUSED_RESULT;
/* RNA integration */
@@ -567,6 +575,24 @@ typedef struct wmOperatorType {
} wmOperatorType;
+#ifdef WITH_INPUT_IME
+/* *********** Input Method Editor (IME) *********** */
+
+/* similar to GHOST_TEventImeData */
+typedef struct wmIMEData {
+ size_t result_len, composite_len;
+
+ char *str_result; /* utf8 encoding */
+ char *str_composite; /* utf8 encoding */
+
+ int cursor_pos; /* cursor position in the IME composition. */
+ int sel_start; /* beginning of the selection */
+ int sel_end; /* end of the selection */
+
+ bool is_ime_composing;
+} wmIMEData;
+#endif
+
/* **************** Paint Cursor ******************* */
typedef void (*wmPaintCursorDraw)(struct bContext *C, int, int, void *customdata);
diff --git a/source/blender/windowmanager/intern/wm.c b/source/blender/windowmanager/intern/wm.c
index d05cc572c45..fe92d80c1bd 100644
--- a/source/blender/windowmanager/intern/wm.c
+++ b/source/blender/windowmanager/intern/wm.c
@@ -39,8 +39,6 @@
#include "DNA_windowmanager_types.h"
-#include "GHOST_C-api.h"
-
#include "MEM_guardedalloc.h"
#include "BLI_utildefines.h"
@@ -59,7 +57,6 @@
#include "WM_types.h"
#include "wm_window.h"
#include "wm_event_system.h"
-#include "wm_event_types.h"
#include "wm_draw.h"
#include "wm.h"
@@ -155,7 +152,7 @@ void wm_operator_register(bContext *C, wmOperator *op)
int tot;
BLI_addtail(&wm->operators, op);
- tot = BLI_countlist(&wm->operators);
+ tot = BLI_listbase_count(&wm->operators);
while (tot > MAX_OP_REGISTERED) {
wmOperator *opt = wm->operators.first;
@@ -231,7 +228,7 @@ uiListType *WM_uilisttype_find(const char *idname, bool quiet)
bool WM_uilisttype_add(uiListType *ult)
{
- BLI_ghash_insert(uilisttypes_hash, (void *)ult->idname, ult);
+ BLI_ghash_insert(uilisttypes_hash, ult->idname, ult);
return 1;
}
@@ -253,15 +250,14 @@ void WM_uilisttype_init(void)
void WM_uilisttype_free(void)
{
- GHashIterator *iter = BLI_ghashIterator_new(uilisttypes_hash);
+ GHashIterator gh_iter;
- for (; !BLI_ghashIterator_done(iter); BLI_ghashIterator_step(iter)) {
- uiListType *ult = BLI_ghashIterator_getValue(iter);
+ GHASH_ITER (gh_iter, uilisttypes_hash) {
+ uiListType *ult = BLI_ghashIterator_getValue(&gh_iter);
if (ult->ext.free) {
ult->ext.free(ult->ext.data);
}
}
- BLI_ghashIterator_free(iter);
BLI_ghash_free(uilisttypes_hash, NULL, MEM_freeN);
uilisttypes_hash = NULL;
@@ -289,7 +285,7 @@ MenuType *WM_menutype_find(const char *idname, bool quiet)
bool WM_menutype_add(MenuType *mt)
{
- BLI_ghash_insert(menutypes_hash, (void *)mt->idname, mt);
+ BLI_ghash_insert(menutypes_hash, mt->idname, mt);
return true;
}
@@ -312,15 +308,14 @@ void WM_menutype_init(void)
void WM_menutype_free(void)
{
- GHashIterator *iter = BLI_ghashIterator_new(menutypes_hash);
+ GHashIterator gh_iter;
- for (; !BLI_ghashIterator_done(iter); BLI_ghashIterator_step(iter)) {
- MenuType *mt = BLI_ghashIterator_getValue(iter);
+ GHASH_ITER (gh_iter, menutypes_hash) {
+ MenuType *mt = BLI_ghashIterator_getValue(&gh_iter);
if (mt->ext.free) {
mt->ext.free(mt->ext.data);
}
}
- BLI_ghashIterator_free(iter);
BLI_ghash_free(menutypes_hash, NULL, MEM_freeN);
menutypes_hash = NULL;
@@ -472,11 +467,13 @@ void wm_close_and_free(bContext *C, wmWindowManager *wm)
void wm_close_and_free_all(bContext *C, ListBase *wmlist)
{
+ Main *bmain = CTX_data_main(C);
wmWindowManager *wm;
while ((wm = wmlist->first)) {
wm_close_and_free(C, wm);
BLI_remlink(wmlist, wm);
+ BKE_libblock_free_data(bmain, &wm->id);
MEM_freeN(wm);
}
}
diff --git a/source/blender/windowmanager/intern/wm_cursors.c b/source/blender/windowmanager/intern/wm_cursors.c
index 68fd32cb450..d84b65847ca 100644
--- a/source/blender/windowmanager/intern/wm_cursors.c
+++ b/source/blender/windowmanager/intern/wm_cursors.c
@@ -313,21 +313,22 @@ void WM_cursor_time(wmWindow *win, int nr)
}
-/* ******************************************************************
- * Custom Cursor Description:
+/**
+ * Custom Cursor Description
+ * =========================
*
* Each bit represents a pixel, so 1 byte = 8 pixels,
* the bytes go Left to Right. Top to bottom
* the bits in a byte go right to left
* (ie; 0x01, 0x80 represents a line of 16 pix with the first and last pix set.)
*
- * A 0 in the bitmap = bg_color, a 1 fg_color
- * a 0 in the mask = transparent pix.
+ * - A 0 in the bitmap = bg_color, a 1 fg_color
+ * - a 0 in the mask = transparent pix.
*
* Until 32x32 cursors are supported on all platforms, the size of the
* small cursors MUST be 16x16.
*
- * Large cursors have a MAXSIZE of 32x32.
+ * Large cursors have a maximum size of 32x32.
*
* Other than that, the specified size of the cursors is just a guideline,
* However, the char array that defines the BM and MASK must be byte aligned.
@@ -335,18 +336,20 @@ void WM_cursor_time(wmWindow *win, int nr)
* (3 bytes = 17 bits rounded up to nearest whole byte). Pad extra bits
* in mask with 0's.
*
- * Setting big_bm = NULL disables the large version of the cursor.
+ * Setting `big_bm = NULL` disables the large version of the cursor.
*
- * *******************************************************************
+ * ----
*
* There is a nice Python GUI utility that can be used for drawing cursors in
* this format in the Blender source distribution, in
- * blender/source/tools/MakeCursor.py . Start it with $ python MakeCursor.py
- * It will copy its output to the console when you press 'Do it'.
+ * `./source/tools/utils/make_cursor_gui.py` .
*
+ * Start it with the command `python3 make_cursor_gui.py`
+ * It will copy its output to the console when you press 'Do it'.
*/
-/* Because defining a cursor mixes declarations and executable code
+/**
+ * Because defining a cursor mixes declarations and executable code
* each cursor needs it's own scoping block or it would be split up
* over several hundred lines of code. To enforce/document this better
* I define 2 pretty brain-dead macros so it's obvious what the extra "[]"
diff --git a/source/blender/windowmanager/intern/wm_dragdrop.c b/source/blender/windowmanager/intern/wm_dragdrop.c
index e5bba9285b4..3a53906a8e8 100644
--- a/source/blender/windowmanager/intern/wm_dragdrop.c
+++ b/source/blender/windowmanager/intern/wm_dragdrop.c
@@ -37,7 +37,7 @@
#include "MEM_guardedalloc.h"
-#include "BLF_translation.h"
+#include "BLT_translation.h"
#include "BLI_blenlib.h"
@@ -45,10 +45,8 @@
#include "BIF_glutil.h"
#include "BKE_context.h"
-#include "BKE_screen.h"
#include "IMB_imbuf_types.h"
-#include "IMB_imbuf.h"
#include "UI_interface.h"
#include "UI_interface_icons.h"
@@ -58,8 +56,6 @@
#include "WM_api.h"
#include "WM_types.h"
#include "wm_event_system.h"
-#include "wm.h"
-
/* ****************************************************** */
@@ -85,7 +81,7 @@ ListBase *WM_dropboxmap_find(const char *idname, int spaceid, int regionid)
for (dm = dropboxes.first; dm; dm = dm->next)
if (dm->spaceid == spaceid && dm->regionid == regionid)
- if (0 == strncmp(idname, dm->idname, KMAP_MAX_NAME))
+ if (STREQLEN(idname, dm->idname, KMAP_MAX_NAME))
return &dm->dropboxes;
dm = MEM_callocN(sizeof(struct wmDropBoxMap), "dropmap list");
@@ -271,16 +267,11 @@ 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 + 2 * padding, y + 4 * padding, padding);
-
- glColor4ub(255, 255, 255, 255);
- UI_DrawString(x + padding, y + padding, name);
+ const uiFontStyle *fstyle = UI_FSTYLE_WIDGET;
+ const unsigned char fg[4] = {255, 255, 255, 255};
+ const unsigned char bg[4] = {0, 0, 0, 50};
+
+ UI_fontstyle_draw_simple_backdrop(fstyle, x, y, name, fg, bg);
}
static const char *wm_drag_name(wmDrag *drag)
@@ -288,13 +279,12 @@ static const char *wm_drag_name(wmDrag *drag)
switch (drag->type) {
case WM_DRAG_ID:
{
- ID *id = (ID *)drag->poin;
+ ID *id = drag->poin;
return id->name + 2;
}
case WM_DRAG_PATH:
- return drag->path;
case WM_DRAG_NAME:
- return (char *)drag->path;
+ return drag->path;
}
return "";
}
@@ -315,6 +305,7 @@ static void drag_rect_minmax(rcti *rect, int x1, int y1, int x2, int y2)
/* if rect set, do not draw */
void wm_drags_draw(bContext *C, wmWindow *win, rcti *rect)
{
+ const uiFontStyle *fstyle = UI_FSTYLE_WIDGET;
wmWindowManager *wm = CTX_wm_manager(C);
wmDrag *drag;
const int winsize_y = WM_window_pixels_y(win);
@@ -330,7 +321,7 @@ 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 iconsize = UI_DPI_ICON_SIZE;
int padding = 4 * UI_DPI_FAC;
/* image or icon */
@@ -366,12 +357,12 @@ void wm_drags_draw(bContext *C, wmWindow *win, rcti *rect)
}
if (rect) {
- int w = UI_GetStringWidth(wm_drag_name(drag));
+ int w = UI_fontstyle_string_width(fstyle, wm_drag_name(drag));
drag_rect_minmax(rect, x, y, x + w, y + iconsize);
}
else {
glColor4ub(255, 255, 255, 255);
- UI_DrawString(x, y, wm_drag_name(drag));
+ UI_fontstyle_draw_simple(fstyle, x, y, wm_drag_name(drag));
}
/* operator name with roundbox */
@@ -387,14 +378,16 @@ void wm_drags_draw(bContext *C, wmWindow *win, rcti *rect)
else {
x = cursorx - 2 * padding;
- if (cursory + iconsize + iconsize < winsize_y)
- y = cursory + iconsize;
- else
- y = cursory - iconsize - 2 * UI_DPI_FAC;
+ if (cursory + iconsize + iconsize < winsize_y) {
+ y = (cursory + iconsize) + padding;
+ }
+ else {
+ y = (cursory - iconsize) - padding;
+ }
}
if (rect) {
- int w = UI_GetStringWidth(wm_drag_name(drag));
+ int w = UI_fontstyle_string_width(fstyle, wm_drag_name(drag));
drag_rect_minmax(rect, x, y, x + w, y + iconsize);
}
else
diff --git a/source/blender/windowmanager/intern/wm_draw.c b/source/blender/windowmanager/intern/wm_draw.c
index 2f20e8c234f..16fe9ca5142 100644
--- a/source/blender/windowmanager/intern/wm_draw.c
+++ b/source/blender/windowmanager/intern/wm_draw.c
@@ -32,7 +32,6 @@
#include <stdlib.h>
#include <string.h>
-#include <GL/glew.h>
#include "DNA_listBase.h"
#include "DNA_screen_types.h"
@@ -49,14 +48,17 @@
#include "BIF_gl.h"
#include "BKE_context.h"
+#include "BKE_image.h"
#include "GHOST_C-api.h"
+#include "ED_node.h"
#include "ED_view3d.h"
#include "ED_screen.h"
#include "GPU_draw.h"
#include "GPU_extensions.h"
+#include "GPU_glew.h"
#include "RE_engine.h"
@@ -165,6 +167,7 @@ static void wm_method_draw_full(bContext *C, wmWindow *win)
if (ar->swinid) {
CTX_wm_region_set(C, ar);
ED_region_do_draw(C, ar);
+ ar->do_draw = false;
wm_paintcursor_draw(C, ar);
CTX_wm_region_set(C, NULL);
}
@@ -175,12 +178,14 @@ static void wm_method_draw_full(bContext *C, wmWindow *win)
}
ED_screen_draw(win);
+ win->screen->do_draw = false;
/* draw overlapping regions */
for (ar = screen->regionbase.first; ar; ar = ar->next) {
if (ar->swinid) {
CTX_wm_menu_set(C, ar);
ED_region_do_draw(C, ar);
+ ar->do_draw = false;
CTX_wm_menu_set(C, NULL);
}
}
@@ -278,6 +283,7 @@ static void wm_method_draw_overlap_all(bContext *C, wmWindow *win, int exchange)
if (ar->do_draw) {
CTX_wm_region_set(C, ar);
ED_region_do_draw(C, ar);
+ ar->do_draw = false;
wm_paintcursor_draw(C, ar);
CTX_wm_region_set(C, NULL);
@@ -288,6 +294,7 @@ static void wm_method_draw_overlap_all(bContext *C, wmWindow *win, int exchange)
if (ar->swap == WIN_FRONT_OK) {
CTX_wm_region_set(C, ar);
ED_region_do_draw(C, ar);
+ ar->do_draw = false;
wm_paintcursor_draw(C, ar);
CTX_wm_region_set(C, NULL);
@@ -300,7 +307,7 @@ static void wm_method_draw_overlap_all(bContext *C, wmWindow *win, int exchange)
}
}
}
-
+
wm_area_mark_invalid_backbuf(sa);
CTX_wm_area_set(C, NULL);
}
@@ -308,6 +315,7 @@ static void wm_method_draw_overlap_all(bContext *C, wmWindow *win, int exchange)
/* after area regions so we can do area 'overlay' drawing */
if (screen->do_draw) {
ED_screen_draw(win);
+ win->screen->do_draw = false;
if (exchange)
screen->swap = WIN_FRONT_OK;
@@ -315,6 +323,7 @@ static void wm_method_draw_overlap_all(bContext *C, wmWindow *win, int exchange)
else if (exchange) {
if (screen->swap == WIN_FRONT_OK) {
ED_screen_draw(win);
+ win->screen->do_draw = false;
screen->swap = WIN_BOTH_OK;
}
else if (screen->swap == WIN_BACK_OK)
@@ -328,6 +337,7 @@ static void wm_method_draw_overlap_all(bContext *C, wmWindow *win, int exchange)
if (ar->swinid && ar->do_draw) {
CTX_wm_menu_set(C, ar);
ED_region_do_draw(C, ar);
+ ar->do_draw = false;
CTX_wm_menu_set(C, NULL);
}
}
@@ -360,15 +370,6 @@ static void wm_method_draw_damage(bContext *C, wmWindow *win)
/* used. if not, multiple smaller ones are used, with */
/* worst case wasted space being 23.4% for 3x3 textures */
-#define MAX_N_TEX 3
-
-typedef struct wmDrawTriple {
- GLuint bind[MAX_N_TEX * MAX_N_TEX];
- int x[MAX_N_TEX], y[MAX_N_TEX];
- int nx, ny;
- GLenum target;
-} wmDrawTriple;
-
static void split_width(int x, int n, int *splitx, int *nx)
{
int a, newnx, waste;
@@ -405,16 +406,13 @@ static void split_width(int x, int n, int *splitx, int *nx)
}
}
-static void wm_draw_triple_free(wmWindow *win)
+static void wm_draw_triple_free(wmDrawTriple *triple)
{
- if (win->drawdata) {
- wmDrawTriple *triple = win->drawdata;
+ if (triple) {
glDeleteTextures(triple->nx * triple->ny, triple->bind);
MEM_freeN(triple);
-
- win->drawdata = NULL;
}
}
@@ -499,7 +497,7 @@ static int wm_triple_gen_textures(wmWindow *win, wmDrawTriple *triple)
return 1;
}
-static void wm_triple_draw_textures(wmWindow *win, wmDrawTriple *triple, float alpha)
+void wm_triple_draw_textures(wmWindow *win, wmDrawTriple *triple, float alpha)
{
const int winsize_x = WM_window_pixels_x(win);
const int winsize_y = WM_window_pixels_y(win);
@@ -571,7 +569,7 @@ static void wm_triple_copy_textures(wmWindow *win, wmDrawTriple *triple)
glBindTexture(triple->target, 0);
}
-static void wm_draw_region_blend(wmWindow *win, ARegion *ar)
+static void wm_draw_region_blend(wmWindow *win, ARegion *ar, wmDrawTriple *triple)
{
float fac = ED_region_blend_factor(ar);
@@ -580,7 +578,7 @@ static void wm_draw_region_blend(wmWindow *win, ARegion *ar)
wmSubWindowScissorSet(win, win->screen->mainwin, &ar->winrct, true);
glEnable(GL_BLEND);
- wm_triple_draw_textures(win, win->drawdata, 1.0f - fac);
+ wm_triple_draw_textures(win, triple, 1.0f - fac);
glDisable(GL_BLEND);
}
}
@@ -589,29 +587,46 @@ static void wm_method_draw_triple(bContext *C, wmWindow *win)
{
wmWindowManager *wm = CTX_wm_manager(C);
wmDrawTriple *triple;
+ wmDrawData *dd, *dd_next, *drawdata = win->drawdata.first;
bScreen *screen = win->screen;
ScrArea *sa;
ARegion *ar;
- int copytex = 0;
+ int copytex = false;
- if (win->drawdata) {
+ if (drawdata && drawdata->triple) {
glClearColor(0, 0, 0, 0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
wmSubWindowSet(win, screen->mainwin);
- wm_triple_draw_textures(win, win->drawdata, 1.0f);
+ wm_triple_draw_textures(win, drawdata->triple, 1.0f);
}
else {
- win->drawdata = MEM_callocN(sizeof(wmDrawTriple), "wmDrawTriple");
+ /* we run it when we start OR when we turn stereo on */
+ if (drawdata == NULL) {
+ drawdata = MEM_callocN(sizeof(wmDrawData), "wmDrawData");
+ BLI_addhead(&win->drawdata, drawdata);
+ }
+
+ drawdata->triple = MEM_callocN(sizeof(wmDrawTriple), "wmDrawTriple");
- if (!wm_triple_gen_textures(win, win->drawdata)) {
+ if (!wm_triple_gen_textures(win, drawdata->triple)) {
wm_draw_triple_fail(C, win);
return;
}
}
- triple = win->drawdata;
+ /* it means stereo was just turned off */
+ /* note: we are removing all drawdatas that are not the first */
+ for (dd = drawdata->next; dd; dd = dd_next) {
+ dd_next = dd->next;
+
+ BLI_remlink(&win->drawdata, dd);
+ wm_draw_triple_free(dd->triple);
+ MEM_freeN(dd);
+ }
+
+ triple = drawdata->triple;
/* draw marked area regions */
for (sa = screen->areabase.first; sa; sa = sa->next) {
@@ -619,16 +634,17 @@ static void wm_method_draw_triple(bContext *C, wmWindow *win)
for (ar = sa->regionbase.first; ar; ar = ar->next) {
if (ar->swinid && ar->do_draw) {
-
- if (ar->overlap == 0) {
+
+ if (ar->overlap == false) {
CTX_wm_region_set(C, ar);
ED_region_do_draw(C, ar);
+ ar->do_draw = false;
CTX_wm_region_set(C, NULL);
- copytex = 1;
+ copytex = true;
}
}
}
-
+
wm_area_mark_invalid_backbuf(sa);
CTX_wm_area_set(C, NULL);
}
@@ -662,14 +678,15 @@ static void wm_method_draw_triple(bContext *C, wmWindow *win)
/* draw overlapping area regions (always like popups) */
for (sa = screen->areabase.first; sa; sa = sa->next) {
CTX_wm_area_set(C, sa);
-
+
for (ar = sa->regionbase.first; ar; ar = ar->next) {
if (ar->swinid && ar->overlap) {
CTX_wm_region_set(C, ar);
ED_region_do_draw(C, ar);
+ ar->do_draw = false;
CTX_wm_region_set(C, NULL);
-
- wm_draw_region_blend(win, ar);
+
+ wm_draw_region_blend(win, ar, triple);
}
}
@@ -678,12 +695,14 @@ static void wm_method_draw_triple(bContext *C, wmWindow *win)
/* after area regions so we can do area 'overlay' drawing */
ED_screen_draw(win);
+ win->screen->do_draw = false;
/* draw floating regions (menus) */
for (ar = screen->regionbase.first; ar; ar = ar->next) {
if (ar->swinid) {
CTX_wm_menu_set(C, ar);
ED_region_do_draw(C, ar);
+ ar->do_draw = false;
CTX_wm_menu_set(C, NULL);
}
}
@@ -691,13 +710,188 @@ static void wm_method_draw_triple(bContext *C, wmWindow *win)
/* always draw, not only when screen tagged */
if (win->gesture.first)
wm_gesture_draw(win);
-
+
/* needs pixel coords in screen */
if (wm->drags.first) {
wm_drags_draw(C, win, NULL);
}
}
+static void wm_method_draw_triple_multiview(bContext *C, wmWindow *win, StereoViews sview)
+{
+ wmWindowManager *wm = CTX_wm_manager(C);
+ wmDrawData *drawdata;
+ wmDrawTriple *triple_data, *triple_all;
+ bScreen *screen = win->screen;
+ ScrArea *sa;
+ ARegion *ar;
+ int copytex = false;
+ int id;
+
+ /* we store the triple_data in sequence to triple_all */
+ for (id = 0; id < 2; id++) {
+ drawdata = BLI_findlink(&win->drawdata, (sview * 2) + id);
+
+ if (drawdata && drawdata->triple) {
+ if (id == 0) {
+ glClearColor(0, 0, 0, 0);
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+ wmSubWindowSet(win, screen->mainwin);
+
+ wm_triple_draw_textures(win, drawdata->triple, 1.0f);
+ }
+ }
+ else {
+ /* we run it when we start OR when we turn stereo on */
+ if (drawdata == NULL) {
+ drawdata = MEM_callocN(sizeof(wmDrawData), "wmDrawData");
+ BLI_addtail(&win->drawdata, drawdata);
+ }
+
+ drawdata->triple = MEM_callocN(sizeof(wmDrawTriple), "wmDrawTriple");
+
+ if (!wm_triple_gen_textures(win, drawdata->triple)) {
+ wm_draw_triple_fail(C, win);
+ return;
+ }
+ }
+ }
+
+ triple_data = ((wmDrawData *) BLI_findlink(&win->drawdata, sview * 2))->triple;
+ triple_all = ((wmDrawData *) BLI_findlink(&win->drawdata, (sview * 2) + 1))->triple;
+
+ /* draw marked area regions */
+ for (sa = screen->areabase.first; sa; sa = sa->next) {
+ CTX_wm_area_set(C, sa);
+
+ switch (sa->spacetype) {
+ case SPACE_IMAGE:
+ {
+ SpaceImage *sima = sa->spacedata.first;
+ sima->iuser.multiview_eye = sview;
+ break;
+ }
+ case SPACE_VIEW3D:
+ {
+ View3D *v3d = sa->spacedata.first;
+ BGpic *bgpic = v3d->bgpicbase.first;
+ v3d->multiview_eye = sview;
+ if (bgpic) bgpic->iuser.multiview_eye = sview;
+ break;
+ }
+ case SPACE_NODE:
+ {
+ SpaceNode *snode = sa->spacedata.first;
+ if ((snode->flag & SNODE_BACKDRAW) && ED_node_is_compositor(snode)) {
+ Image *ima = BKE_image_verify_viewer(IMA_TYPE_COMPOSITE, "Viewer Node");
+ ima->eye = sview;
+ }
+ break;
+ }
+ case SPACE_SEQ:
+ {
+ SpaceSeq *sseq = sa->spacedata.first;
+ sseq->multiview_eye = sview;
+ break;
+ }
+ }
+
+ /* draw marked area regions */
+ for (ar = sa->regionbase.first; ar; ar = ar->next) {
+ if (ar->swinid && ar->do_draw) {
+
+ if (ar->overlap == false) {
+ CTX_wm_region_set(C, ar);
+ ED_region_do_draw(C, ar);
+
+ if (sview == STEREO_RIGHT_ID)
+ ar->do_draw = false;
+
+ CTX_wm_region_set(C, NULL);
+ copytex = true;
+ }
+ }
+ }
+
+ wm_area_mark_invalid_backbuf(sa);
+ CTX_wm_area_set(C, NULL);
+ }
+
+ if (copytex) {
+ wmSubWindowSet(win, screen->mainwin);
+
+ wm_triple_copy_textures(win, triple_data);
+ }
+
+ if (wm->paintcursors.first) {
+ for (sa = screen->areabase.first; sa; sa = sa->next) {
+ for (ar = sa->regionbase.first; ar; ar = ar->next) {
+ if (ar->swinid && ar->swinid == screen->subwinactive) {
+ CTX_wm_area_set(C, sa);
+ CTX_wm_region_set(C, ar);
+
+ /* make region ready for draw, scissor, pixelspace */
+ ED_region_set(C, ar);
+ wm_paintcursor_draw(C, ar);
+
+ CTX_wm_region_set(C, NULL);
+ CTX_wm_area_set(C, NULL);
+ }
+ }
+ }
+
+ wmSubWindowSet(win, screen->mainwin);
+ }
+
+ /* draw overlapping area regions (always like popups) */
+ for (sa = screen->areabase.first; sa; sa = sa->next) {
+ CTX_wm_area_set(C, sa);
+
+ for (ar = sa->regionbase.first; ar; ar = ar->next) {
+ if (ar->swinid && ar->overlap) {
+ CTX_wm_region_set(C, ar);
+ ED_region_do_draw(C, ar);
+ if (sview == STEREO_RIGHT_ID)
+ ar->do_draw = false;
+ CTX_wm_region_set(C, NULL);
+
+ wm_draw_region_blend(win, ar, triple_data);
+ }
+ }
+
+ CTX_wm_area_set(C, NULL);
+ }
+
+ /* after area regions so we can do area 'overlay' drawing */
+ ED_screen_draw(win);
+ if (sview == STEREO_RIGHT_ID)
+ win->screen->do_draw = false;
+
+ /* draw floating regions (menus) */
+ for (ar = screen->regionbase.first; ar; ar = ar->next) {
+ if (ar->swinid) {
+ CTX_wm_menu_set(C, ar);
+ ED_region_do_draw(C, ar);
+ if (sview == STEREO_RIGHT_ID)
+ ar->do_draw = false;
+ CTX_wm_menu_set(C, NULL);
+ }
+ }
+
+ /* always draw, not only when screen tagged */
+ if (win->gesture.first)
+ wm_gesture_draw(win);
+
+ /* needs pixel coords in screen */
+ if (wm->drags.first) {
+ wm_drags_draw(C, win, NULL);
+ }
+
+ /* copy the ui + overlays */
+ wmSubWindowSet(win, screen->mainwin);
+ wm_triple_copy_textures(win, triple_all);
+}
/****************** main update call **********************/
@@ -848,8 +1042,16 @@ void wm_draw_update(bContext *C)
wm_method_draw_overlap_all(C, win, 0);
else if (drawmethod == USER_DRAW_OVERLAP_FLIP)
wm_method_draw_overlap_all(C, win, 1);
- else // if (drawmethod == USER_DRAW_TRIPLE)
- wm_method_draw_triple(C, win);
+ else { /* USER_DRAW_TRIPLE */
+ if ((WM_stereo3d_enabled(win, false)) == false) {
+ wm_method_draw_triple(C, win);
+ }
+ else {
+ wm_method_draw_triple_multiview(C, win, STEREO_LEFT_ID);
+ wm_method_draw_triple_multiview(C, win, STEREO_RIGHT_ID);
+ wm_method_draw_stereo3d(C, win);
+ }
+ }
win->screen->do_draw_gesture = false;
win->screen->do_draw_paintcursor = false;
@@ -862,15 +1064,23 @@ void wm_draw_update(bContext *C)
}
}
+void wm_draw_data_free(wmWindow *win)
+{
+ wmDrawData *dd;
+
+ for (dd = win->drawdata.first; dd; dd = dd->next) {
+ wm_draw_triple_free(dd->triple);
+ }
+ BLI_freelistN(&win->drawdata);
+}
+
void wm_draw_window_clear(wmWindow *win)
{
bScreen *screen = win->screen;
ScrArea *sa;
ARegion *ar;
- int drawmethod = wm_automatic_draw_method(win);
- if (drawmethod == USER_DRAW_TRIPLE)
- wm_draw_triple_free(win);
+ wm_draw_data_free(win);
/* clear screen swap flags */
if (screen) {
diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c
index 2f8ee1ca141..187c11ef3da 100644
--- a/source/blender/windowmanager/intern/wm_event_system.c
+++ b/source/blender/windowmanager/intern/wm_event_system.c
@@ -32,7 +32,6 @@
* Also some operator reports utility functions.
*/
-
#include <stdlib.h>
#include <string.h>
@@ -69,7 +68,7 @@
#include "RNA_access.h"
-#include "BIF_gl.h"
+#include "GPU_debug.h"
#include "UI_interface.h"
@@ -81,7 +80,6 @@
#include "wm_window.h"
#include "wm_event_system.h"
#include "wm_event_types.h"
-#include "wm_draw.h"
#ifndef NDEBUG
# include "RNA_enum_types.h"
@@ -95,7 +93,7 @@ static int wm_operator_call_internal(bContext *C, wmOperatorType *ot, PointerRNA
/* ************ event management ************** */
-void wm_event_add(wmWindow *win, const wmEvent *event_to_add)
+void wm_event_add_ex(wmWindow *win, const wmEvent *event_to_add, const wmEvent *event_to_add_after)
{
wmEvent *event = MEM_mallocN(sizeof(wmEvent), "wmEvent");
@@ -103,7 +101,18 @@ void wm_event_add(wmWindow *win, const wmEvent *event_to_add)
update_tablet_data(win, event);
- BLI_addtail(&win->queue, event);
+ if (event_to_add_after == NULL) {
+ BLI_addtail(&win->queue, event);
+ }
+ else {
+ /* note, strictly speaking this breaks const-correctness, however we're only changing 'next' member */
+ BLI_insertlinkafter(&win->queue, (void *)event_to_add_after, event);
+ }
+}
+
+void wm_event_add(wmWindow *win, const wmEvent *event_to_add)
+{
+ wm_event_add_ex(win, event_to_add, NULL);
}
void wm_event_free(wmEvent *event)
@@ -122,7 +131,7 @@ void wm_event_free(wmEvent *event)
}
if (event->tablet_data) {
- MEM_freeN(event->tablet_data);
+ MEM_freeN((void *)event->tablet_data);
}
MEM_freeN(event);
@@ -216,6 +225,7 @@ void WM_main_remove_notifier_reference(const void *reference)
{
Main *bmain = G.main;
wmWindowManager *wm = bmain->wm.first;
+
if (wm) {
wmNotifier *note, *note_next;
@@ -231,6 +241,24 @@ void WM_main_remove_notifier_reference(const void *reference)
}
}
+void WM_main_remove_editor_id_reference(const ID *id)
+{
+ Main *bmain = G.main;
+ bScreen *sc;
+
+ for (sc = bmain->screen.first; sc; sc = sc->id.next) {
+ ScrArea *sa;
+
+ for (sa = sc->areabase.first; sa; sa = sa->next) {
+ SpaceLink *sl;
+
+ for (sl = sa->spacedata.first; sl; sl = sl->next) {
+ ED_spacedata_id_unref(sl, id);
+ }
+ }
+ }
+}
+
static void wm_notifier_clear(wmNotifier *note)
{
/* NULL the entire notifier, only leaving (next, prev) members intact */
@@ -269,7 +297,7 @@ void wm_event_do_notifiers(bContext *C)
if (note->category == NC_SCREEN) {
if (note->data == ND_SCREENBROWSE) {
/* free popup handlers only [#35434] */
- UI_remove_popup_handlers_all(C, &win->modalhandlers);
+ UI_popup_handlers_remove_all(C, &win->modalhandlers);
ED_screen_set(C, note->reference); // XXX hrms, think this over!
@@ -292,7 +320,7 @@ void wm_event_do_notifiers(bContext *C)
do_anim = true;
}
}
- if (ELEM(note->category, NC_SCENE, NC_OBJECT, NC_GEOM, NC_SCENE, NC_WM)) {
+ if (ELEM(note->category, NC_SCENE, NC_OBJECT, NC_GEOM, NC_WM)) {
ED_info_stats_clear(win->screen->scene);
WM_event_add_notifier(C, NC_SPACE | ND_SPACE_INFO, NULL);
}
@@ -534,30 +562,31 @@ void WM_event_print(const wmEvent *event)
RNA_enum_identifier(event_type_items, event->type, &type_id);
RNA_enum_identifier(event_value_items, event->val, &val_id);
- printf("wmEvent type:%d / %s, val:%d / %s, \n"
- " shift:%d, ctrl:%d, alt:%d, oskey:%d, keymodifier:%d, \n"
- " mouse:(%d,%d), ascii:'%c', utf8:'%.*s', "
- " keymap_idname:%s, pointer:%p\n",
+ printf("wmEvent type:%d / %s, val:%d / %s,\n"
+ " shift:%d, ctrl:%d, alt:%d, oskey:%d, keymodifier:%d,\n"
+ " mouse:(%d,%d), ascii:'%c', utf8:'%.*s', keymap_idname:%s, pointer:%p\n",
event->type, type_id, event->val, val_id,
event->shift, event->ctrl, event->alt, event->oskey, event->keymodifier,
event->x, event->y, event->ascii,
BLI_str_utf8_size(event->utf8_buf), event->utf8_buf,
- event->keymap_idname, (void *)event);
+ event->keymap_idname, (const void *)event);
if (ISNDOF(event->type)) {
const wmNDOFMotionData *ndof = event->customdata;
if (event->type == NDOF_MOTION) {
- printf(" ndof: rot: (%.4f %.4f %.4f),\n"
- " tx: (%.4f %.4f %.4f),\n"
- " dt: %.4f, progress: %d\n",
- UNPACK3(ndof->rvec),
- UNPACK3(ndof->tvec),
- ndof->dt, ndof->progress);
+ printf(" ndof: rot: (%.4f %.4f %.4f), tx: (%.4f %.4f %.4f), dt: %.4f, progress: %u\n",
+ UNPACK3(ndof->rvec), UNPACK3(ndof->tvec), ndof->dt, ndof->progress);
}
else {
/* ndof buttons printed already */
}
}
+
+ if (event->tablet_data) {
+ const wmTabletData *wmtab = event->tablet_data;
+ printf(" tablet: active: %d, pressure %.4f, tilt: (%.4f %.4f)\n",
+ wmtab->Active, wmtab->Pressure, wmtab->Xtilt, wmtab->Ytilt);
+ }
}
else {
printf("wmEvent - NULL\n");
@@ -566,26 +595,45 @@ void WM_event_print(const wmEvent *event)
#endif /* NDEBUG */
+/**
+ * Show the report in the info header.
+ */
+void WM_report_banner_show(const bContext *C)
+{
+ wmWindowManager *wm = CTX_wm_manager(C);
+ ReportList *wm_reports = CTX_wm_reports(C);
+ ReportTimerInfo *rti;
+
+ /* After adding reports to the global list, reset the report timer. */
+ WM_event_remove_timer(wm, NULL, wm_reports->reporttimer);
+
+ /* Records time since last report was added */
+ wm_reports->reporttimer = WM_event_add_timer(wm, CTX_wm_window(C), TIMERREPORT, 0.05);
+
+ rti = MEM_callocN(sizeof(ReportTimerInfo), "ReportTimerInfo");
+ wm_reports->reporttimer->customdata = rti;
+}
+
+bool WM_event_is_absolute(const wmEvent *event)
+{
+ return (event->tablet_data != NULL);
+}
+
+void WM_ndof_deadzone_set(float deadzone)
+{
+ GHOST_setNDOFDeadZone(deadzone);
+}
+
static void wm_add_reports(const bContext *C, ReportList *reports)
{
/* if the caller owns them, handle this */
if (reports->list.first && (reports->flag & RPT_OP_HOLD) == 0) {
-
- wmWindowManager *wm = CTX_wm_manager(C);
ReportList *wm_reports = CTX_wm_reports(C);
- ReportTimerInfo *rti;
/* add reports to the global list, otherwise they are not seen */
BLI_movelisttolist(&wm_reports->list, &reports->list);
-
- /* After adding reports to the global list, reset the report timer. */
- WM_event_remove_timer(wm, NULL, wm_reports->reporttimer);
-
- /* Records time since last report was added */
- wm_reports->reporttimer = WM_event_add_timer(wm, CTX_wm_window(C), TIMERREPORT, 0.05);
-
- rti = MEM_callocN(sizeof(ReportTimerInfo), "ReportTimerInfo");
- wm_reports->reporttimer->customdata = rti;
+
+ WM_report_banner_show(C);
}
}
@@ -621,7 +669,7 @@ static void wm_operator_reports(bContext *C, wmOperator *op, int retval, bool ca
{
if (caller_owns_reports == false) { /* popup */
if (op->reports->list.first) {
- /* FIXME, temp setting window, see other call to uiPupMenuReports for why */
+ /* FIXME, temp setting window, see other call to UI_popup_menu_reports for why */
wmWindow *win_prev = CTX_wm_window(C);
ScrArea *area_prev = CTX_wm_area(C);
ARegion *ar_prev = CTX_wm_region(C);
@@ -629,7 +677,7 @@ static void wm_operator_reports(bContext *C, wmOperator *op, int retval, bool ca
if (win_prev == NULL)
CTX_wm_window_set(C, CTX_wm_manager(C)->windows.first);
- uiPupMenuReports(C, op->reports);
+ UI_popup_menu_reports(C, op->reports);
CTX_wm_window_set(C, win_prev);
CTX_wm_area_set(C, area_prev);
@@ -661,7 +709,8 @@ static void wm_operator_reports(bContext *C, wmOperator *op, int retval, bool ca
wm_add_reports(C, op->reports);
}
-/* this function is mainly to check that the rules for freeing
+/**
+ * This function is mainly to check that the rules for freeing
* an operator are kept in sync.
*/
static bool wm_operator_register_check(wmWindowManager *wm, wmOperatorType *ot)
@@ -730,7 +779,7 @@ static int wm_operator_exec(bContext *C, wmOperator *op, const bool repeat, cons
/* XXX Disabled the repeat check to address part 2 of #31840.
* Carefully checked all calls to wm_operator_exec and WM_operator_repeat, don't see any reason
* why this was needed, but worth to note it in case something turns bad. (mont29) */
- if (retval & (OPERATOR_FINISHED | OPERATOR_CANCELLED)/* && repeat == 0 */)
+ if (retval & (OPERATOR_FINISHED | OPERATOR_CANCELLED) /* && repeat == 0 */)
wm_operator_reports(C, op, retval, false);
if (retval & OPERATOR_FINISHED) {
@@ -780,23 +829,29 @@ int WM_operator_call(bContext *C, wmOperator *op)
return WM_operator_call_ex(C, op, false);
}
-/* this is intended to be used when an invoke operator wants to call exec on its self
+/**
+ * This is intended to be used when an invoke operator wants to call exec on its self
* and is basically like running op->type->exec() directly, no poll checks no freeing,
- * since we assume whoever called invoke will take care of that */
+ * since we assume whoever called invoke will take care of that
+ */
int WM_operator_call_notest(bContext *C, wmOperator *op)
{
return wm_operator_exec_notest(C, op);
}
-/* do this operator again, put here so it can share above code */
+/**
+ * Execute this operator again, put here so it can share above code
+ */
int WM_operator_repeat(bContext *C, wmOperator *op)
{
return wm_operator_exec(C, op, true, true);
}
-/* true if WM_operator_repeat can run
+/**
+ * \return true if #WM_operator_repeat can run
* simple check for now but may become more involved.
- * To be sure the operator can run call WM_operator_poll(C, op->type) also, since this call
- * checks if WM_operator_repeat() can run at all, not that it WILL run at any time. */
+ * To be sure the operator can run call `WM_operator_poll(C, op->type)` also, since this call
+ * checks if WM_operator_repeat() can run at all, not that it WILL run at any time.
+ */
bool WM_operator_repeat_check(const bContext *UNUSED(C), wmOperator *op)
{
if (op->type->exec != NULL) {
@@ -871,7 +926,7 @@ static wmOperator *wm_operator_create(wmWindowManager *wm, wmOperatorType *ot,
break;
/* skip invalid properties */
- if (strcmp(RNA_property_identifier(prop), otmacro->idname) == 0) {
+ if (STREQ(RNA_property_identifier(prop), otmacro->idname)) {
wmOperatorType *otm = WM_operatortype_find(otmacro->idname, 0);
PointerRNA someptr = RNA_property_pointer_get(properties, prop);
wmOperator *opm = wm_operator_create(wm, otm, &someptr, NULL);
@@ -1002,8 +1057,9 @@ bool WM_operator_last_properties_store(wmOperator *UNUSED(op))
#endif
-static int wm_operator_invoke(bContext *C, wmOperatorType *ot, wmEvent *event,
- PointerRNA *properties, ReportList *reports, const bool poll_only)
+static int wm_operator_invoke(
+ bContext *C, wmOperatorType *ot, wmEvent *event,
+ PointerRNA *properties, ReportList *reports, const bool poll_only)
{
int retval = OPERATOR_PASS_THROUGH;
@@ -1082,13 +1138,16 @@ static int wm_operator_invoke(bContext *C, wmOperatorType *ot, wmEvent *event,
int bounds[4] = {-1, -1, -1, -1};
bool wrap;
- if (op->opm) {
+ if (event == NULL) {
+ wrap = false;
+ }
+ else if (op->opm) {
wrap = (U.uiflag & USER_CONTINUOUS_MOUSE) &&
- ((op->opm->flag & OP_GRAB_POINTER) || (op->opm->type->flag & OPTYPE_GRAB_POINTER));
+ ((op->opm->flag & OP_IS_MODAL_GRAB_CURSOR) || (op->opm->type->flag & OPTYPE_GRAB_CURSOR));
}
else {
wrap = (U.uiflag & USER_CONTINUOUS_MOUSE) &&
- ((op->flag & OP_GRAB_POINTER) || (ot->flag & OPTYPE_GRAB_POINTER));
+ ((op->flag & OP_IS_MODAL_GRAB_CURSOR) || (ot->flag & OPTYPE_GRAB_CURSOR));
}
/* exception, cont. grab in header is annoying */
@@ -1100,16 +1159,16 @@ static int wm_operator_invoke(bContext *C, wmOperatorType *ot, wmEvent *event,
}
if (wrap) {
- rcti *winrect = NULL;
+ const rcti *winrect = NULL;
ARegion *ar = CTX_wm_region(C);
ScrArea *sa = CTX_wm_area(C);
- if (ar && ar->regiontype == RGN_TYPE_WINDOW && event &&
+ if (ar && ar->regiontype == RGN_TYPE_WINDOW &&
BLI_rcti_isect_pt_v(&ar->winrct, &event->x))
{
winrect = &ar->winrct;
}
- else if (sa) {
+ else if (sa && BLI_rcti_isect_pt_v(&sa->totrct, &event->x)) {
winrect = &sa->totrct;
}
@@ -1138,12 +1197,15 @@ static int wm_operator_invoke(bContext *C, wmOperatorType *ot, wmEvent *event,
return retval;
}
-/* WM_operator_name_call is the main accessor function
+/**
+ * #WM_operator_name_call is the main accessor function
* this is for python to access since its done the operator lookup
*
- * invokes operator in context */
-static int wm_operator_call_internal(bContext *C, wmOperatorType *ot, PointerRNA *properties, ReportList *reports,
- const short context, const bool poll_only)
+ * invokes operator in context
+ */
+static int wm_operator_call_internal(
+ bContext *C, wmOperatorType *ot, PointerRNA *properties, ReportList *reports,
+ const short context, const bool poll_only)
{
wmEvent *event;
@@ -1152,7 +1214,7 @@ static int wm_operator_call_internal(bContext *C, wmOperatorType *ot, PointerRNA
CTX_wm_operator_poll_msg_set(C, NULL);
/* dummie test */
- if (ot && C) {
+ if (ot) {
wmWindow *window = CTX_wm_window(C);
switch (context) {
@@ -1283,13 +1345,16 @@ int WM_operator_name_call(bContext *C, const char *opstring, short context, Poin
return 0;
}
-/* Similar to WM_operator_name_call called with WM_OP_EXEC_DEFAULT context.
- * - wmOperatorType is used instead of operator name since python already has the operator type
- * - poll() must be called by python before this runs.
- * - reports can be passed to this function (so python can report them as exceptions)
+/**
+ * Similar to #WM_operator_name_call called with #WM_OP_EXEC_DEFAULT context.
+ *
+ * - #wmOperatorType is used instead of operator name since python already has the operator type.
+ * - `poll()` must be called by python before this runs.
+ * - reports can be passed to this function (so python can report them as exceptions).
*/
-int WM_operator_call_py(bContext *C, wmOperatorType *ot, short context,
- PointerRNA *properties, ReportList *reports, const bool is_undo)
+int WM_operator_call_py(
+ bContext *C, wmOperatorType *ot, short context,
+ PointerRNA *properties, ReportList *reports, const bool is_undo)
{
int retval = OPERATOR_CANCELLED;
@@ -1336,7 +1401,7 @@ void wm_event_free_handler(wmEventHandler *handler)
}
/* only set context when area/region is part of screen */
-static void wm_handler_op_context(bContext *C, wmEventHandler *handler)
+static void wm_handler_op_context(bContext *C, wmEventHandler *handler, const wmEvent *event)
{
bScreen *screen = CTX_wm_screen(C);
@@ -1357,10 +1422,27 @@ static void wm_handler_op_context(bContext *C, wmEventHandler *handler)
}
else {
ARegion *ar;
+ wmOperator *op = handler->op ? (handler->op->opm ? handler->op->opm : handler->op) : NULL;
CTX_wm_area_set(C, sa);
- for (ar = sa->regionbase.first; ar; ar = ar->next)
- if (ar == handler->op_region)
- break;
+
+ if (op && (op->flag & OP_IS_MODAL_CURSOR_REGION)) {
+ ar = BKE_area_find_region_xy(sa, handler->op_region_type, event->x, event->y);
+ if (ar) {
+ handler->op_region = ar;
+ }
+ }
+ else {
+ ar = NULL;
+ }
+
+ if (ar == NULL) {
+ for (ar = sa->regionbase.first; ar; ar = ar->next) {
+ if (ar == handler->op_region) {
+ break;
+ }
+ }
+ }
+
/* XXX no warning print here, after full-area and back regions are remade */
if (ar)
CTX_wm_region_set(C, ar);
@@ -1378,11 +1460,12 @@ void WM_event_remove_handlers(bContext *C, ListBase *handlers)
/* C is zero on freeing database, modal handlers then already were freed */
while ((handler = BLI_pophead(handlers))) {
if (handler->op) {
+ wmWindow *win = CTX_wm_window(C);
if (handler->op->type->cancel) {
ScrArea *area = CTX_wm_area(C);
ARegion *region = CTX_wm_region(C);
- wm_handler_op_context(C, handler);
+ wm_handler_op_context(C, handler, win->eventstate);
if (handler->op->type->flag & OPTYPE_UNDO)
wm->op_undo_depth++;
@@ -1396,7 +1479,7 @@ void WM_event_remove_handlers(bContext *C, ListBase *handlers)
CTX_wm_region_set(C, region);
}
- WM_cursor_grab_disable(CTX_wm_window(C), NULL);
+ WM_cursor_grab_disable(win, NULL);
WM_operator_free(handler->op);
}
else if (handler->ui_remove) {
@@ -1514,7 +1597,8 @@ static void wm_event_modalkeymap(const bContext *C, wmOperator *op, wmEvent *eve
}
}
-/* Check whether operator is allowed to run in case interface is locked,
+/**
+ * Check whether operator is allowed to run in case interface is locked,
* If interface is unlocked, will always return truth.
*/
static bool wm_operator_check_locked_interface(bContext *C, wmOperatorType *ot)
@@ -1568,7 +1652,7 @@ static int wm_handler_operator_call(bContext *C, ListBase *handlers, wmEventHand
ARegion *region = CTX_wm_region(C);
bool dbl_click_disabled = false;
- wm_handler_op_context(C, handler);
+ wm_handler_op_context(C, handler, event);
wm_region_mouse_co(C, event);
wm_event_modalkeymap(C, op, event, &dbl_click_disabled);
@@ -1663,7 +1747,6 @@ static int wm_handler_fileselect_do(bContext *C, ListBase *handlers, wmEventHand
int action = WM_HANDLER_CONTINUE;
switch (val) {
- case EVT_FILESELECT_OPEN:
case EVT_FILESELECT_FULL_OPEN:
{
ScrArea *sa;
@@ -1677,9 +1760,16 @@ static int wm_handler_fileselect_do(bContext *C, ListBase *handlers, wmEventHand
else {
sa = handler->op_area;
}
-
- if (val == EVT_FILESELECT_OPEN) {
+
+ if (sa->full) {
+ /* ensure the first area becomes the file browser, because the second one is the small
+ * top (info-)area which might be too small (in fullscreens we have max two areas) */
+ if (sa->prev) {
+ sa = sa->prev;
+ }
ED_area_newspace(C, sa, SPACE_FILE); /* 'sa' is modified in-place */
+ /* we already had a fullscreen here -> mark new space as a stacked fullscreen */
+ sa->flag |= AREA_FLAG_STACKED_FULLSCREEN;
}
else {
sa = ED_screen_full_newspace(C, sa, SPACE_FILE); /* sets context */
@@ -1703,24 +1793,26 @@ static int wm_handler_fileselect_do(bContext *C, ListBase *handlers, wmEventHand
case EVT_FILESELECT_CANCEL:
case EVT_FILESELECT_EXTERNAL_CANCEL:
{
- /* XXX validate area and region? */
- bScreen *screen = CTX_wm_screen(C);
-
/* remlink now, for load file case before removing*/
BLI_remlink(handlers, handler);
-
+
if (val != EVT_FILESELECT_EXTERNAL_CANCEL) {
- if (screen != handler->filescreen) {
- ED_screen_full_prevspace(C, CTX_wm_area(C));
+ ScrArea *sa = CTX_wm_area(C);
+ const SpaceLink *sl = sa->spacedata.first;
+ const bool was_prev_temp = (sl->next && sl->next->spacetype == SPACE_IMAGE);
+
+ if (sa->full) {
+ ED_screen_full_prevspace(C, sa, was_prev_temp);
}
+ /* user may have left fullscreen */
else {
- ED_area_prevspace(C, CTX_wm_area(C));
+ ED_area_prevspace(C, sa);
}
}
-
- wm_handler_op_context(C, handler);
- /* needed for uiPupMenuReports */
+ wm_handler_op_context(C, handler, CTX_wm_window(C)->eventstate);
+
+ /* needed for UI_popup_menu_reports */
if (val == EVT_FILESELECT_EXEC) {
int retval;
@@ -1752,7 +1844,7 @@ static int wm_handler_fileselect_do(bContext *C, ListBase *handlers, wmEventHand
CTX_wm_window_set(C, CTX_wm_manager(C)->windows.first);
BKE_report_print_level_set(handler->op->reports, RPT_WARNING);
- uiPupMenuReports(C, handler->op->reports);
+ UI_popup_menu_reports(C, handler->op->reports);
/* XXX - copied from 'wm_operator_finished()' */
/* add reports to the global list, otherwise they are not seen */
@@ -1844,7 +1936,7 @@ static int wm_action_not_handled(int action)
static int wm_handlers_do_intern(bContext *C, wmEvent *event, ListBase *handlers)
{
#ifndef NDEBUG
- const int do_debug_handler = (G.debug & G_DEBUG_HANDLERS) &&
+ const bool do_debug_handler = (G.debug & G_DEBUG_HANDLERS) &&
/* comment this out to flood the console! (if you really want to test) */
!ELEM(event->type, MOUSEMOVE, INBETWEEN_MOUSEMOVE)
;
@@ -1955,7 +2047,7 @@ static int wm_handlers_do_intern(bContext *C, wmEvent *event, ListBase *handlers
event->customdata = NULL;
event->custom = 0;
- WM_operator_name_call(C, drop->ot->idname, drop->opcontext, drop->ptr);
+ WM_operator_name_call_ptr(C, drop->ot, drop->opcontext, drop->ptr);
action |= WM_HANDLER_BREAK;
/* XXX fileread case */
@@ -2188,6 +2280,23 @@ static void wm_event_drag_test(wmWindowManager *wm, wmWindow *win, wmEvent *even
}
+/* filter out all events of the pie that spawned the last pie unless it's a release event */
+static bool wm_event_pie_filter(wmWindow *win, wmEvent *event)
+{
+ if (win->lock_pie_event && win->lock_pie_event == event->type) {
+ if (event->val == KM_RELEASE) {
+ win->lock_pie_event = EVENT_NONE;
+ return false;
+ }
+ else {
+ return true;
+ }
+ }
+ else {
+ return false;
+ }
+}
+
/* called in main loop */
/* goes over entire hierarchy: events -> window -> screen -> area -> region */
void wm_event_do_handlers(bContext *C)
@@ -2207,7 +2316,7 @@ void wm_event_do_handlers(bContext *C)
Scene *scene = win->screen->scene;
if (scene) {
- int is_playing_sound = sound_scene_playing(win->screen->scene);
+ int is_playing_sound = BKE_sound_scene_playing(win->screen->scene);
if (is_playing_sound != -1) {
bool is_playing_screen;
@@ -2224,7 +2333,7 @@ void wm_event_do_handlers(bContext *C)
}
if (is_playing_sound == 0) {
- const float time = sound_sync_scene(scene);
+ const float time = BKE_sound_sync_scene(scene);
if (finite(time)) {
int ncfra = time * (float)FPS + 0.5f;
if (ncfra != scene->r.cfra) {
@@ -2251,9 +2360,21 @@ void wm_event_do_handlers(bContext *C)
WM_event_print(event);
}
#endif
-
+
+ /* take care of pie event filter */
+ if (wm_event_pie_filter(win, event)) {
+#ifndef NDEBUG
+ if (G.debug & (G_DEBUG_HANDLERS | G_DEBUG_EVENTS) && !ELEM(event->type, MOUSEMOVE, INBETWEEN_MOUSEMOVE)) {
+ printf("\n%s: event filtered due to pie button pressed\n", __func__);
+ }
+#endif
+ BLI_remlink(&win->queue, event);
+ wm_event_free(event);
+ continue;
+ }
+
CTX_wm_window_set(C, win);
-
+
/* we let modal handlers get active area/region, also wm_paintcursor_test needs it */
CTX_wm_area_set(C, area_event_inside(C, &event->x));
CTX_wm_region_set(C, region_event_inside(C, &event->x));
@@ -2263,6 +2384,7 @@ void wm_event_do_handlers(bContext *C)
wm_region_mouse_co(C, event);
+
/* first we do priority handlers, modal + some limited keymaps */
action |= wm_handlers_do(C, event, &win->modalhandlers);
@@ -2293,6 +2415,19 @@ void wm_event_do_handlers(bContext *C)
}
for (sa = win->screen->areabase.first; sa; sa = sa->next) {
+ /* after restoring a screen from SCREENMAXIMIZED we have to wait
+ * with the screen handling till the region coordinates are updated */
+ if (win->screen->skip_handling == true) {
+ /* restore for the next iteration of wm_event_do_handlers */
+ win->screen->skip_handling = false;
+ break;
+ }
+
+ /* update azones if needed - done here because it needs to be independent from redraws */
+ if (sa->flag & AREA_FLAG_ACTIONZONES_UPDATE) {
+ ED_area_azones_update(sa, &event->x);
+ }
+
if (wm_event_inside_i(event, &sa->totrct)) {
CTX_wm_area_set(C, sa);
@@ -2354,7 +2489,7 @@ void wm_event_do_handlers(bContext *C)
/* XXX hrmf, this gives reliable previous mouse coord for area change, feels bad?
* doing it on ghost queue gives errors when mousemoves go over area borders */
- if (doit && win->screen && win->screen->subwinactive != win->screen->mainwin) {
+ if (doit && win->screen->subwinactive != win->screen->mainwin) {
win->eventstate->prevx = event->x;
win->eventstate->prevy = event->y;
//printf("win->eventstate->prev = %d %d\n", event->x, event->y);
@@ -2387,12 +2522,7 @@ void wm_event_do_handlers(bContext *C)
/* update key configuration after handling events */
WM_keyconfig_update(wm);
- if (G.debug) {
- GLenum error = glGetError();
- if (error != GL_NO_ERROR) {
- printf("GL error: %s\n", gluErrorString(error));
- }
- }
+ GPU_ASSERT_NO_GL_ERRORS("wm_event_do_handlers");
}
/* ********** filesector handling ************ */
@@ -2416,17 +2546,17 @@ void WM_event_fileselect_event(wmWindowManager *wm, void *ophandle, int eventval
/* operator is supposed to have a filled "path" property */
/* optional property: filetype (XXX enum?) */
-/* Idea is to keep a handler alive on window queue, owning the operator.
+/**
+ * The idea here is to keep a handler alive on window queue, owning the operator.
* The filewindow can send event to make it execute, thus ensuring
* executing happens outside of lower level queues, with UI refreshed.
- * Should also allow multiwin solutions */
-
+ * Should also allow multiwin solutions
+ */
void WM_event_add_fileselect(bContext *C, wmOperator *op)
{
wmEventHandler *handler, *handlernext;
wmWindowManager *wm = CTX_wm_manager(C);
wmWindow *win = CTX_wm_window(C);
- int full = 1; // XXX preset?
/* only allow 1 file selector open per window */
for (handler = win->modalhandlers.first; handler; handler = handlernext) {
@@ -2461,7 +2591,6 @@ void WM_event_add_fileselect(bContext *C, wmOperator *op)
handler->op = op;
handler->op_area = CTX_wm_area(C);
handler->op_region = CTX_wm_region(C);
- handler->filescreen = CTX_wm_screen(C);
BLI_addhead(&win->modalhandlers, handler);
@@ -2471,7 +2600,7 @@ void WM_event_add_fileselect(bContext *C, wmOperator *op)
op->type->check(C, op); /* ignore return value */
}
- WM_event_fileselect_event(wm, op, full ? EVT_FILESELECT_FULL_OPEN : EVT_FILESELECT_OPEN);
+ WM_event_fileselect_event(wm, op, EVT_FILESELECT_FULL_OPEN);
}
#if 0
@@ -2499,6 +2628,7 @@ wmEventHandler *WM_event_add_modal_handler(bContext *C, wmOperator *op)
handler->op_area = CTX_wm_area(C); /* means frozen screen context for modal handlers! */
handler->op_region = CTX_wm_region(C);
+ handler->op_region_type = handler->op_region ? handler->op_region->regiontype : -1;
BLI_addhead(&win->modalhandlers, handler);
@@ -2567,7 +2697,7 @@ void WM_event_remove_keymap_handler(ListBase *handlers, wmKeyMap *keymap)
wmEventHandler *WM_event_add_ui_handler(
const bContext *C, ListBase *handlers,
wmUIHandlerFunc ui_handle, wmUIHandlerRemoveFunc ui_remove,
- void *userdata, const bool accept_dbl_click)
+ void *userdata, const char flag)
{
wmEventHandler *handler = MEM_callocN(sizeof(wmEventHandler), "event ui handler");
handler->ui_handle = ui_handle;
@@ -2584,9 +2714,8 @@ wmEventHandler *WM_event_add_ui_handler(
handler->ui_menu = NULL;
}
- if (accept_dbl_click) {
- handler->flag |= WM_HANDLER_ACCEPT_DBL_CLICK;
- }
+ BLI_assert((flag & WM_HANDLER_DO_FREE) == 0);
+ handler->flag = flag;
BLI_addhead(handlers, handler);
@@ -2812,52 +2941,41 @@ static int convert_key(GHOST_TKey key)
static void wm_eventemulation(wmEvent *event)
{
- /* Store last mmb event value to make emulation work when modifier keys are released first. */
- static int mmb_emulated = 0; /* this should be in a data structure somwhere */
+ /* Store last mmb/rmb event value to make emulation work when modifier keys
+ * are released first. This really should be in a data structure somewhere. */
+ static int emulating_event = EVENT_NONE;
- /* middlemouse emulation */
+ /* middlemouse and rightmouse emulation */
if (U.flag & USER_TWOBUTTONMOUSE) {
if (event->type == LEFTMOUSE) {
if (event->val == KM_PRESS && event->alt) {
event->type = MIDDLEMOUSE;
event->alt = 0;
- mmb_emulated = 1;
- }
- else if (event->val == KM_RELEASE) {
- /* only send middle-mouse release if emulated */
- if (mmb_emulated) {
- event->type = MIDDLEMOUSE;
- event->alt = 0;
- }
- mmb_emulated = 0;
+ emulating_event = MIDDLEMOUSE;
}
- }
-
- }
-
#ifdef __APPLE__
-
- /* rightmouse emulation */
- if (U.flag & USER_TWOBUTTONMOUSE) {
- if (event->type == LEFTMOUSE) {
-
- if (event->val == KM_PRESS && event->oskey) {
+ else if (event->val == KM_PRESS && event->oskey) {
event->type = RIGHTMOUSE;
event->oskey = 0;
- mmb_emulated = 1;
+ emulating_event = RIGHTMOUSE;
}
+#endif
else if (event->val == KM_RELEASE) {
- if (mmb_emulated) {
- event->oskey = RIGHTMOUSE;
+ /* only send middle-mouse release if emulated */
+ if (emulating_event == MIDDLEMOUSE) {
+ event->type = MIDDLEMOUSE;
event->alt = 0;
}
- mmb_emulated = 0;
+ else if (emulating_event == RIGHTMOUSE) {
+ event->type = RIGHTMOUSE;
+ event->oskey = 0;
+ }
+ emulating_event = EVENT_NONE;
}
}
}
-#endif
/* numpad emulation */
if (U.flag & USER_NONUMPAD) {
@@ -3020,6 +3138,13 @@ static void wm_event_add_mousemove(wmWindow *win, const wmEvent *event)
void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, int UNUSED(time), void *customdata)
{
wmWindow *owin;
+
+ /* Having both, event and evt, can be highly confusing to work with, but is necessary for
+ * our current event system, so let's clear things up a bit:
+ * - data added to event only will be handled immediately, but will not be copied to the next event
+ * - data added to evt only stays, but is handled with the next event -> execution delay
+ * - data added to event and evt stays and is handled immediately
+ */
wmEvent event, *evt = win->eventstate;
/* initialize and copy state (only mouse x y and modifiers) */
@@ -3072,7 +3197,7 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, int U
event.x = evt->x = pd->x;
event.y = evt->y = pd->y;
- event.val = 0;
+ event.val = KM_NOTHING;
/* Use prevx/prevy so we can calculate the delta later */
event.prevx = event.x - pd->deltaX;
@@ -3160,6 +3285,7 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, int U
case GHOST_kEventKeyUp:
{
GHOST_TEventKeyData *kd = customdata;
+ short keymodifier = KM_NOTHING;
event.type = convert_key(kd->key);
event.ascii = kd->ascii;
memcpy(event.utf8_buf, kd->utf8_buf, sizeof(event.utf8_buf)); /* might be not null terminated*/
@@ -3200,28 +3326,38 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, int U
}
}
- /* modifiers assign to eventstate, so next event gets the modifer (makes modifier key events work) */
/* assigning both first and second is strange - campbell */
switch (event.type) {
- case LEFTSHIFTKEY: case RIGHTSHIFTKEY:
- evt->shift = (event.val == KM_PRESS) ?
- ((evt->ctrl || evt->alt || evt->oskey) ? (KM_MOD_FIRST | KM_MOD_SECOND) : KM_MOD_FIRST) :
- false;
+ case LEFTSHIFTKEY:
+ case RIGHTSHIFTKEY:
+ if (event.val == KM_PRESS) {
+ if (evt->ctrl || evt->alt || evt->oskey) keymodifier = (KM_MOD_FIRST | KM_MOD_SECOND);
+ else keymodifier = KM_MOD_FIRST;
+ }
+ event.shift = evt->shift = keymodifier;
break;
- case LEFTCTRLKEY: case RIGHTCTRLKEY:
- evt->ctrl = (event.val == KM_PRESS) ?
- ((evt->shift || evt->alt || evt->oskey) ? (KM_MOD_FIRST | KM_MOD_SECOND) : KM_MOD_FIRST) :
- false;
+ case LEFTCTRLKEY:
+ case RIGHTCTRLKEY:
+ if (event.val == KM_PRESS) {
+ if (evt->shift || evt->alt || evt->oskey) keymodifier = (KM_MOD_FIRST | KM_MOD_SECOND);
+ else keymodifier = KM_MOD_FIRST;
+ }
+ event.ctrl = evt->ctrl = keymodifier;
break;
- case LEFTALTKEY: case RIGHTALTKEY:
- evt->alt = (event.val == KM_PRESS) ?
- ((evt->ctrl || evt->shift || evt->oskey) ? (KM_MOD_FIRST | KM_MOD_SECOND) : KM_MOD_FIRST) :
- false;
+ case LEFTALTKEY:
+ case RIGHTALTKEY:
+ if (event.val == KM_PRESS) {
+ if (evt->ctrl || evt->shift || evt->oskey) keymodifier = (KM_MOD_FIRST | KM_MOD_SECOND);
+ else keymodifier = KM_MOD_FIRST;
+ }
+ event.alt = evt->alt = keymodifier;
break;
case OSKEY:
- evt->oskey = (event.val == KM_PRESS) ?
- ((evt->ctrl || evt->alt || evt->shift) ? (KM_MOD_FIRST | KM_MOD_SECOND) : KM_MOD_FIRST) :
- false;
+ if (event.val == KM_PRESS) {
+ if (evt->ctrl || evt->alt || evt->shift) keymodifier = (KM_MOD_FIRST | KM_MOD_SECOND);
+ else keymodifier = KM_MOD_FIRST;
+ }
+ event.oskey = evt->oskey = keymodifier;
break;
default:
if (event.val == KM_PRESS && event.keymodifier == 0)
@@ -3289,7 +3425,7 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, int U
event.type = TIMER;
event.custom = EVT_DATA_TIMER;
event.customdata = customdata;
- event.val = 0;
+ event.val = KM_NOTHING;
event.keymodifier = 0;
wm_event_add(win, &event);
@@ -3299,7 +3435,7 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, int U
case GHOST_kEventNDOFMotion:
{
event.type = NDOF_MOTION;
- event.val = 0;
+ event.val = KM_NOTHING;
attach_ndof_data(&event, customdata);
wm_event_add(win, &event);
@@ -3344,6 +3480,35 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, int U
break;
}
+#ifdef WITH_INPUT_IME
+ case GHOST_kEventImeCompositionStart:
+ {
+ event.val = KM_PRESS;
+ win->ime_data = customdata;
+ win->ime_data->is_ime_composing = true;
+ event.type = WM_IME_COMPOSITE_START;
+ wm_event_add(win, &event);
+ break;
+ }
+ case GHOST_kEventImeComposition:
+ {
+ event.val = KM_PRESS;
+ event.type = WM_IME_COMPOSITE_EVENT;
+ wm_event_add(win, &event);
+ break;
+ }
+ case GHOST_kEventImeCompositionEnd:
+ {
+ event.val = KM_PRESS;
+ if (win->ime_data) {
+ win->ime_data->is_ime_composing = false;
+ }
+ event.type = WM_IME_COMPOSITE_END;
+ wm_event_add(win, &event);
+ break;
+ }
+#endif /* WITH_INPUT_IME */
+
}
#if 0
@@ -3427,7 +3592,7 @@ float WM_event_tablet_data(const wmEvent *event, int *pen_flip, float tilt[2])
zero_v2(tilt);
if (event->tablet_data) {
- wmTabletData *wmtab = event->tablet_data;
+ const wmTabletData *wmtab = event->tablet_data;
erasor = (wmtab->Active == EVT_TABLET_ERASER);
if (wmtab->Active != EVT_TABLET_NONE) {
@@ -3450,5 +3615,13 @@ bool WM_event_is_tablet(const struct wmEvent *event)
return (event->tablet_data) ? true : false;
}
+#ifdef WITH_INPUT_IME
+/* most os using ctrl/oskey + space to switch ime, avoid added space */
+bool WM_event_is_ime_switch(const struct wmEvent *event)
+{
+ return event->val == KM_PRESS && event->type == SPACEKEY &&
+ (event->ctrl || event->oskey || event->shift || event->alt);
+}
+#endif
/** \} */
diff --git a/source/blender/windowmanager/intern/wm_files.c b/source/blender/windowmanager/intern/wm_files.c
index 832fef404e3..d08c6c59a7f 100644
--- a/source/blender/windowmanager/intern/wm_files.c
+++ b/source/blender/windowmanager/intern/wm_files.c
@@ -60,7 +60,7 @@
#include "BLI_system.h"
#include BLI_SYSTEM_PID_H
-#include "BLF_translation.h"
+#include "BLT_translation.h"
#include "DNA_object_types.h"
#include "DNA_space_types.h"
@@ -69,12 +69,14 @@
#include "DNA_screen_types.h"
#include "DNA_windowmanager_types.h"
+#include "BKE_appdir.h"
#include "BKE_utildefines.h"
#include "BKE_autoexec.h"
#include "BKE_blender.h"
#include "BKE_context.h"
#include "BKE_depsgraph.h"
#include "BKE_global.h"
+#include "BKE_library.h"
#include "BKE_main.h"
#include "BKE_packedFile.h"
#include "BKE_report.h"
@@ -96,8 +98,6 @@
#include "ED_view3d.h"
#include "ED_util.h"
-#include "RE_pipeline.h" /* only to report missing engine */
-
#include "GHOST_C-api.h"
#include "GHOST_Path-api.h"
@@ -106,6 +106,9 @@
#include "GPU_draw.h"
+/* only to report a missing engine */
+#include "RE_engine.h"
+
#ifdef WITH_PYTHON
#include "BPY_extern.h"
#endif
@@ -117,7 +120,11 @@
#include "wm_window.h"
#include "wm_event_system.h"
-static void write_history(void);
+static RecentFile *wm_file_history_find(const char *filepath);
+static void wm_history_file_free(RecentFile *recent);
+static void wm_history_file_update(void);
+static void wm_history_file_write(void);
+
/* To be able to read files without windows closing, opening, moving
* we try to prepare for worst case:
@@ -171,6 +178,28 @@ static void wm_window_match_init(bContext *C, ListBase *wmlist)
#endif
}
+static void wm_window_substitute_old(wmWindowManager *wm, wmWindow *oldwin, wmWindow *win)
+{
+ win->ghostwin = oldwin->ghostwin;
+ win->active = oldwin->active;
+ if (win->active)
+ wm->winactive = win;
+
+ if (!G.background) /* file loading in background mode still calls this */
+ GHOST_SetWindowUserData(win->ghostwin, win); /* pointer back */
+
+ oldwin->ghostwin = NULL;
+
+ win->eventstate = oldwin->eventstate;
+ oldwin->eventstate = NULL;
+
+ /* ensure proper screen rescaling */
+ win->sizex = oldwin->sizex;
+ win->sizey = oldwin->sizey;
+ win->posx = oldwin->posx;
+ win->posy = oldwin->posy;
+}
+
/* match old WM with new, 4 cases:
* 1- no current wm, no read wm: make new default
* 2- no current wm, but read wm: that's OK, do nothing
@@ -224,6 +253,8 @@ static void wm_window_match_do(bContext *C, ListBase *oldwmlist)
ED_screens_initialize(G.main->wm.first);
}
else {
+ bool has_match = false;
+
/* what if old was 3, and loaded 1? */
/* this code could move to setup_appdata */
oldwm = oldwmlist->first;
@@ -243,33 +274,27 @@ static void wm_window_match_do(bContext *C, ListBase *oldwmlist)
/* ensure making new keymaps and set space types */
wm->initialized = 0;
wm->winactive = NULL;
-
+
/* only first wm in list has ghostwins */
for (win = wm->windows.first; win; win = win->next) {
for (oldwin = oldwm->windows.first; oldwin; oldwin = oldwin->next) {
-
- if (oldwin->winid == win->winid) {
- win->ghostwin = oldwin->ghostwin;
- win->active = oldwin->active;
- if (win->active)
- wm->winactive = win;
- if (!G.background) /* file loading in background mode still calls this */
- GHOST_SetWindowUserData(win->ghostwin, win); /* pointer back */
+ if (oldwin->winid == win->winid) {
+ has_match = true;
- oldwin->ghostwin = NULL;
-
- win->eventstate = oldwin->eventstate;
- oldwin->eventstate = NULL;
-
- /* ensure proper screen rescaling */
- win->sizex = oldwin->sizex;
- win->sizey = oldwin->sizey;
- win->posx = oldwin->posx;
- win->posy = oldwin->posy;
+ wm_window_substitute_old(wm, oldwin, win);
}
}
}
+
+ /* make sure at least one window is kept open so we don't lose the context, check T42303 */
+ if (!has_match) {
+ oldwin = oldwm->windows.first;
+ win = wm->windows.first;
+
+ wm_window_substitute_old(wm, oldwin, win);
+ }
+
wm_close_and_free_all(C, oldwmlist);
}
}
@@ -284,7 +309,7 @@ static void wm_init_userdef(bContext *C, const bool from_memory)
UI_init_userdef();
MEM_CacheLimiter_set_maximum(((size_t)U.memcachelimit) * 1024 * 1024);
- sound_init(bmain);
+ BKE_sound_init(bmain);
/* needed so loading a file from the command line respects user-pref [#26156] */
BKE_BIT_TEST_SET(G.fileflags, U.flag & USER_FILENOUI, G_FILE_NO_UI);
@@ -301,7 +326,7 @@ static void wm_init_userdef(bContext *C, const bool from_memory)
}
/* update tempdir from user preferences */
- BLI_temp_dir_init(U.tempdir);
+ BKE_tempdir_init(U.tempdir);
BKE_userdef_state();
}
@@ -338,7 +363,7 @@ static int wm_read_exotic(Scene *UNUSED(scene), const char *name)
else {
len = gzread(gzfile, header, sizeof(header));
gzclose(gzfile);
- if (len == sizeof(header) && strncmp(header, "BLENDER", 7) == 0) {
+ if (len == sizeof(header) && STREQLEN(header, "BLENDER", 7)) {
retval = BKE_READ_EXOTIC_OK_BLEND;
}
else {
@@ -379,8 +404,93 @@ void WM_file_autoexec_init(const char *filepath)
}
}
+void wm_file_read_report(bContext *C)
+{
+ ReportList *reports = NULL;
+ Scene *sce;
+
+ for (sce = G.main->scene.first; sce; sce = sce->id.next) {
+ if (sce->r.engine[0] &&
+ BLI_findstring(&R_engines, sce->r.engine, offsetof(RenderEngineType, idname)) == NULL)
+ {
+ if (reports == NULL) {
+ reports = CTX_wm_reports(C);
+ }
+
+ BKE_reportf(reports, RPT_ERROR,
+ "Engine '%s' not available for scene '%s' "
+ "(an addon may need to be installed or enabled)",
+ sce->r.engine, sce->id.name + 2);
+ }
+ }
+
+ if (reports) {
+ if (!G.background) {
+ WM_report_banner_show(C);
+ }
+ }
+}
+
+/**
+ * Logic shared between #WM_file_read & #wm_homefile_read,
+ * updates to make after reading a file.
+ */
+static void wm_file_read_post(bContext *C, bool is_startup_file)
+{
+ bool addons_loaded = false;
+ CTX_wm_window_set(C, CTX_wm_manager(C)->windows.first);
+
+ ED_editors_init(C);
+ DAG_on_visible_update(CTX_data_main(C), true);
+
+#ifdef WITH_PYTHON
+ if (is_startup_file) {
+ /* possible python hasn't been initialized */
+ if (CTX_py_init_get(C)) {
+ /* sync addons, these may have changed from the defaults */
+ BPY_string_exec(C, "__import__('addon_utils').reset_all()");
+
+ BPY_python_reset(C);
+ addons_loaded = true;
+ }
+ }
+ else {
+ /* run any texts that were loaded in and flagged as modules */
+ BPY_python_reset(C);
+ addons_loaded = true;
+ }
+#endif /* WITH_PYTHON */
+
+ WM_operatortype_last_properties_clear_all();
+
+ /* important to do before NULL'ing the context */
+ BLI_callback_exec(CTX_data_main(C), NULL, BLI_CB_EVT_VERSION_UPDATE);
+ BLI_callback_exec(CTX_data_main(C), NULL, BLI_CB_EVT_LOAD_POST);
+
+ WM_event_add_notifier(C, NC_WM | ND_FILEREAD, NULL);
+
+ /* report any errors.
+ * currently disabled if addons aren't yet loaded */
+ if (addons_loaded) {
+ wm_file_read_report(C);
+ }
+
+ if (!G.background) {
+ /* in background mode this makes it hard to load
+ * a blend file and do anything since the screen
+ * won't be set to a valid value again */
+ CTX_wm_window_set(C, NULL); /* exits queues */
+ }
+
+// undo_editmode_clear();
+ BKE_undo_reset();
+ BKE_undo_write(C, "original"); /* save current state */
+}
+
bool WM_file_read(bContext *C, const char *filepath, ReportList *reports)
{
+ /* assume automated tasks with background, don't write recent file list */
+ const bool do_history = (G.background == false) && (CTX_wm_manager(C)->op_undo_depth == 0);
bool success = false;
int retval;
@@ -403,9 +513,6 @@ bool WM_file_read(bContext *C, const char *filepath, ReportList *reports)
int G_f = G.f;
ListBase wmbase;
- /* assume automated tasks with background, don't write recent file list */
- const bool do_history = (G.background == false) && (CTX_wm_manager(C)->op_undo_depth == 0);
-
/* put aside screens to match with persistent windows later */
/* also exit screens and editors */
wm_window_match_init(C, &wmbase);
@@ -440,60 +547,16 @@ bool WM_file_read(bContext *C, const char *filepath, ReportList *reports)
if (retval != BKE_READ_FILE_FAIL) {
if (do_history) {
- write_history();
- }
- }
-
-
- WM_event_add_notifier(C, NC_WM | ND_FILEREAD, NULL);
-// refresh_interface_font();
-
- CTX_wm_window_set(C, CTX_wm_manager(C)->windows.first);
-
- ED_editors_init(C);
- DAG_on_visible_update(CTX_data_main(C), true);
-
-#ifdef WITH_PYTHON
- /* run any texts that were loaded in and flagged as modules */
- BPY_python_reset(C);
-#endif
-
- /* important to do before NULL'ing the context */
- BLI_callback_exec(CTX_data_main(C), NULL, BLI_CB_EVT_VERSION_UPDATE);
- BLI_callback_exec(CTX_data_main(C), NULL, BLI_CB_EVT_LOAD_POST);
-
- if (!G.background) {
- /* in background mode this makes it hard to load
- * a blend file and do anything since the screen
- * won't be set to a valid value again */
- CTX_wm_window_set(C, NULL); /* exits queues */
- }
-
-#if 0
- /* gives popups on windows but not linux, bug in report API
- * but disable for now to stop users getting annoyed */
- /* TODO, make this show in header info window */
- {
- Scene *sce;
- for (sce = G.main->scene.first; sce; sce = sce->id.next) {
- if (sce->r.engine[0] &&
- BLI_findstring(&R_engines, sce->r.engine, offsetof(RenderEngineType, idname)) == NULL)
- {
- BKE_reportf(reports, RPT_ERROR, "Engine '%s' not available for scene '%s' "
- "(an addon may need to be installed or enabled)",
- sce->r.engine, sce->id.name + 2);
- }
+ wm_history_file_update();
}
}
-#endif
- BKE_reset_undo();
- BKE_write_undo(C, "original"); /* save current state */
+ wm_file_read_post(C, false);
success = true;
}
else if (retval == BKE_READ_EXOTIC_OK_OTHER)
- BKE_write_undo(C, "Import file");
+ BKE_undo_write(C, "Import file");
else if (retval == BKE_READ_EXOTIC_FAIL_OPEN) {
BKE_reportf(reports, RPT_ERROR, "Cannot read file '%s': %s", filepath,
errno ? strerror(errno) : TIP_("unable to open the file"));
@@ -509,6 +572,18 @@ bool WM_file_read(bContext *C, const char *filepath, ReportList *reports)
BLI_assert(!"invalid 'retval'");
}
+
+ if (success == false) {
+ /* remove from recent files list */
+ if (do_history) {
+ RecentFile *recent = wm_file_history_find(filepath);
+ if (recent) {
+ wm_history_file_free(recent);
+ wm_history_file_write();
+ }
+ }
+ }
+
WM_cursor_wait(0);
return success;
@@ -516,11 +591,13 @@ bool 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 */
-/* the optional paramater custom_file points to an alterntive startup page */
-/* custom_file can be NULL */
+/**
+ * called on startup, (context entirely filled with NULLs)
+ * or called for 'New File'
+ * both startup.blend and userpref.blend are checked
+ * the optional parameter custom_file points to an alternative startup page
+ * custom_file can be NULL
+ */
int wm_homefile_read(bContext *C, ReportList *reports, bool from_memory, const char *custom_file)
{
ListBase wmbase;
@@ -542,13 +619,17 @@ int wm_homefile_read(bContext *C, ReportList *reports, bool from_memory, const c
/* options exclude eachother */
BLI_assert((from_memory && custom_file) == 0);
+ if ((G.f & G_SCRIPT_OVERRIDE_PREF) == 0) {
+ BKE_BIT_TEST_SET(G.f, (U.flag & USER_SCRIPT_AUTOEXEC_DISABLE) == 0, G_SCRIPT_AUTOEXEC);
+ }
+
BLI_callback_exec(CTX_data_main(C), NULL, BLI_CB_EVT_LOAD_PRE);
UI_view2d_zoom_cache_reset();
G.relbase_valid = 0;
if (!from_memory) {
- const char * const cfgdir = BLI_get_folder(BLENDER_USER_CONFIG, NULL);
+ const char * const cfgdir = BKE_appdir_folder_id(BLENDER_USER_CONFIG, NULL);
if (custom_file) {
BLI_strncpy(startstr, custom_file, FILE_MAX);
@@ -594,7 +675,7 @@ int wm_homefile_read(bContext *C, ReportList *reports, bool from_memory, const c
if (BLI_listbase_is_empty(&wmbase)) {
wm_clear_default_size(C);
}
- BLI_temp_dir_init(U.tempdir);
+ BKE_tempdir_init(U.tempdir);
#ifdef WITH_PYTHON_SECURITY
/* use alternative setting for security nuts
@@ -632,42 +713,15 @@ int wm_homefile_read(bContext *C, ReportList *reports, bool from_memory, const c
G.save_over = 0; // start with save preference untitled.blend
G.fileflags &= ~G_FILE_AUTOPLAY; /* disable autoplay in startup.blend... */
-// refresh_interface_font();
-
-// undo_editmode_clear();
- BKE_reset_undo();
- BKE_write_undo(C, "original"); /* save current state */
-
- ED_editors_init(C);
- DAG_on_visible_update(CTX_data_main(C), true);
-
-#ifdef WITH_PYTHON
- if (CTX_py_init_get(C)) {
- /* sync addons, these may have changed from the defaults */
- BPY_string_exec(C, "__import__('addon_utils').reset_all()");
-
- BPY_python_reset(C);
- }
-#endif
-
- /* important to do before NULL'ing the context */
- BLI_callback_exec(CTX_data_main(C), NULL, BLI_CB_EVT_VERSION_UPDATE);
- BLI_callback_exec(CTX_data_main(C), NULL, BLI_CB_EVT_LOAD_POST);
-
- WM_event_add_notifier(C, NC_WM | ND_FILEREAD, NULL);
-
- /* in background mode the scene will stay NULL */
- if (!G.background) {
- CTX_wm_window_set(C, NULL); /* exits queues */
- }
+ wm_file_read_post(C, true);
return true;
}
-int wm_history_read_exec(bContext *UNUSED(C), wmOperator *UNUSED(op))
+int wm_history_file_read_exec(bContext *UNUSED(C), wmOperator *UNUSED(op))
{
ED_file_read_bookmarks();
- wm_read_history();
+ wm_history_file_read();
return OPERATOR_FINISHED;
}
@@ -698,14 +752,17 @@ int wm_homefile_read_exec(bContext *C, wmOperator *op)
return wm_homefile_read(C, op->reports, from_memory, filepath) ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
}
-void wm_read_history(void)
+/** \name WM History File API
+ * \{ */
+
+void wm_history_file_read(void)
{
char name[FILE_MAX];
LinkNode *l, *lines;
struct RecentFile *recent;
const char *line;
int num;
- const char * const cfgdir = BLI_get_folder(BLENDER_USER_CONFIG, NULL);
+ const char * const cfgdir = BKE_appdir_folder_id(BLENDER_USER_CONFIG, NULL);
if (!cfgdir) return;
@@ -718,7 +775,8 @@ void wm_read_history(void)
/* read list of recent opened files from recent-files.txt to memory */
for (l = lines, num = 0; l && (num < U.recent_files); l = l->next) {
line = l->link;
- if (line[0] && BLI_exists(line)) {
+ /* don't check if files exist, causes slow startup for remote/external drives */
+ if (line[0]) {
recent = (RecentFile *)MEM_mallocN(sizeof(RecentFile), "RecentFile");
BLI_addtail(&(G.recent_files), recent);
recent->filepath = BLI_strdup(line);
@@ -729,67 +787,100 @@ void wm_read_history(void)
BLI_file_free_lines(lines);
}
-static void write_history(void)
+static RecentFile *wm_history_file_new(const char *filepath)
+{
+ RecentFile *recent = MEM_mallocN(sizeof(RecentFile), "RecentFile");
+ recent->filepath = BLI_strdup(filepath);
+ return recent;
+}
+
+static void wm_history_file_free(RecentFile *recent)
+{
+ BLI_assert(BLI_findindex(&G.recent_files, recent) != -1);
+ MEM_freeN(recent->filepath);
+ BLI_freelinkN(&G.recent_files, recent);
+}
+
+static RecentFile *wm_file_history_find(const char *filepath)
+{
+ return BLI_findstring_ptr(&G.recent_files, filepath, offsetof(RecentFile, filepath));
+}
+
+/**
+ * Write #BLENDER_HISTORY_FILE as-is, without checking the environment
+ * (thats handled by #wm_history_file_update).
+ */
+static void wm_history_file_write(void)
{
- struct RecentFile *recent, *next_recent;
- char name[FILE_MAX];
const char *user_config_dir;
+ char name[FILE_MAX];
FILE *fp;
- int i;
- /* no write history for recovered startup files */
- if (G.main->name[0] == 0)
- return;
-
/* will be NULL in background mode */
- user_config_dir = BLI_get_folder_create(BLENDER_USER_CONFIG, NULL);
+ user_config_dir = BKE_appdir_folder_id_create(BLENDER_USER_CONFIG, NULL);
if (!user_config_dir)
return;
BLI_make_file_string("/", name, user_config_dir, BLENDER_HISTORY_FILE);
+ fp = BLI_fopen(name, "w");
+ if (fp) {
+ struct RecentFile *recent;
+ for (recent = G.recent_files.first; recent; recent = recent->next) {
+ fprintf(fp, "%s\n", recent->filepath);
+ }
+ fclose(fp);
+ }
+}
+
+/**
+ * Run after saving a file to refresh the #BLENDER_HISTORY_FILE list.
+ */
+static void wm_history_file_update(void)
+{
+ RecentFile *recent;
+
+ /* no write history for recovered startup files */
+ if (G.main->name[0] == 0)
+ return;
+
recent = G.recent_files.first;
/* refresh recent-files.txt of recent opened files, when current file was changed */
if (!(recent) || (BLI_path_cmp(recent->filepath, G.main->name) != 0)) {
- fp = BLI_fopen(name, "w");
- if (fp) {
- /* add current file to the beginning of list */
- recent = (RecentFile *)MEM_mallocN(sizeof(RecentFile), "RecentFile");
- recent->filepath = BLI_strdup(G.main->name);
- BLI_addhead(&(G.recent_files), recent);
- /* write current file to recent-files.txt */
- fprintf(fp, "%s\n", recent->filepath);
- recent = recent->next;
- i = 1;
- /* write rest of recent opened files to recent-files.txt */
- while ((i < U.recent_files) && (recent)) {
- /* this prevents to have duplicities in list */
- if (BLI_path_cmp(recent->filepath, G.main->name) != 0) {
- fprintf(fp, "%s\n", recent->filepath);
- recent = recent->next;
- }
- else {
- next_recent = recent->next;
- MEM_freeN(recent->filepath);
- BLI_freelinkN(&(G.recent_files), recent);
- recent = next_recent;
- }
- i++;
+
+ recent = wm_file_history_find(G.main->name);
+ if (recent) {
+ BLI_remlink(&G.recent_files, recent);
+ }
+ else {
+ RecentFile *recent_next;
+ for (recent = BLI_findlink(&G.recent_files, U.recent_files - 1); recent; recent = recent_next) {
+ recent_next = recent->next;
+ wm_history_file_free(recent);
}
- fclose(fp);
+ recent = wm_history_file_new(G.main->name);
}
+ /* add current file to the beginning of list */
+ BLI_addhead(&(G.recent_files), recent);
+
+ /* write current file to recent-files.txt */
+ wm_history_file_write();
+
/* also update most recent files on System */
GHOST_addToSystemRecentFiles(G.main->name);
}
}
+/** \} */
+
+
/* screen can be NULL */
-static ImBuf *blend_file_thumb(Scene *scene, bScreen *screen, int **thumb_pt)
+static ImBuf *blend_file_thumb(Scene *scene, bScreen *screen, BlendThumbnail **thumb_pt)
{
/* will be scaled down, but gives some nice oversampling */
ImBuf *ibuf;
- int *thumb;
+ BlendThumbnail *thumb;
char err_out[256] = "unknown";
/* screen if no camera found */
@@ -797,7 +888,11 @@ static ImBuf *blend_file_thumb(Scene *scene, bScreen *screen, int **thumb_pt)
ARegion *ar = NULL;
View3D *v3d = NULL;
- *thumb_pt = NULL;
+ /* In case we are given a valid thumbnail data, just generate image from it. */
+ if (*thumb_pt) {
+ thumb = *thumb_pt;
+ return BKE_main_thumbnail_to_imbuf(NULL, thumb);
+ }
/* scene can be NULL if running a script at startup and calling the save operator */
if (G.background || scene == NULL)
@@ -819,11 +914,11 @@ static ImBuf *blend_file_thumb(Scene *scene, bScreen *screen, int **thumb_pt)
if (scene->camera) {
ibuf = ED_view3d_draw_offscreen_imbuf_simple(scene, scene->camera,
BLEN_THUMB_SIZE * 2, BLEN_THUMB_SIZE * 2,
- IB_rect, OB_SOLID, false, false, R_ADDSKY, err_out);
+ IB_rect, OB_SOLID, false, false, false, R_ALPHAPREMUL, NULL, err_out);
}
else {
ibuf = ED_view3d_draw_offscreen_imbuf(scene, v3d, ar, BLEN_THUMB_SIZE * 2, BLEN_THUMB_SIZE * 2,
- IB_rect, false, R_ADDSKY, err_out);
+ IB_rect, false, R_ALPHAPREMUL, NULL, err_out);
}
if (ibuf) {
@@ -833,15 +928,9 @@ static ImBuf *blend_file_thumb(Scene *scene, bScreen *screen, int **thumb_pt)
IMB_scaleImBuf(ibuf, BLEN_THUMB_SIZE, BLEN_THUMB_SIZE);
/* add pretty overlay */
- IMB_overlayblend_thumb(ibuf->rect, ibuf->x, ibuf->y, aspect);
+ IMB_thumb_overlay_blend(ibuf->rect, ibuf->x, ibuf->y, aspect);
- /* first write into thumb buffer */
- thumb = MEM_mallocN(((2 + (BLEN_THUMB_SIZE * BLEN_THUMB_SIZE))) * sizeof(int), "write_file thumb");
-
- thumb[0] = BLEN_THUMB_SIZE;
- thumb[1] = BLEN_THUMB_SIZE;
-
- memcpy(thumb + 2, ibuf->rect, BLEN_THUMB_SIZE * BLEN_THUMB_SIZE * sizeof(int));
+ thumb = BKE_main_thumbnail_from_imbuf(NULL, ibuf);
}
else {
/* '*thumb_pt' needs to stay NULL to prevent a bad thumbnail from being handled */
@@ -880,25 +969,26 @@ int wm_file_write(bContext *C, const char *filepath, int fileflags, ReportList *
{
Library *li;
int len;
- int *thumb = NULL;
+ int ret = -1;
+ BlendThumbnail *thumb, *main_thumb;
ImBuf *ibuf_thumb = NULL;
len = strlen(filepath);
if (len == 0) {
BKE_report(reports, RPT_ERROR, "Path is empty, cannot save");
- return -1;
+ return ret;
}
if (len >= FILE_MAX) {
BKE_report(reports, RPT_ERROR, "Path too long, cannot save");
- return -1;
+ return ret;
}
/* Check if file write permission is ok */
if (BLI_exists(filepath) && !BLI_file_is_writable(filepath)) {
BKE_reportf(reports, RPT_ERROR, "Cannot save blend file, path '%s' is not writable", filepath);
- return -1;
+ return ret;
}
/* note: used to replace the file extension (to ensure '.blend'),
@@ -909,22 +999,25 @@ int wm_file_write(bContext *C, const char *filepath, int fileflags, ReportList *
for (li = G.main->library.first; li; li = li->id.next) {
if (BLI_path_cmp(li->filepath, filepath) == 0) {
BKE_reportf(reports, RPT_ERROR, "Cannot overwrite used library '%.240s'", filepath);
- return -1;
+ return ret;
}
}
+ /* Call pre-save callbacks befores writing preview, that way you can generate custom file thumbnail... */
+ BLI_callback_exec(G.main, NULL, BLI_CB_EVT_SAVE_PRE);
+
/* blend file thumbnail */
/* save before exit_editmode, otherwise derivedmeshes for shared data corrupt #27765) */
+ /* Main now can store a .blend thumbnail, usefull for background mode or thumbnail customization. */
+ main_thumb = thumb = CTX_data_main(C)->blen_thumb;
if ((U.flag & USER_SAVE_PREVIEWS) && BLI_thread_is_main()) {
ibuf_thumb = blend_file_thumb(CTX_data_scene(C), CTX_wm_screen(C), &thumb);
}
- BLI_callback_exec(G.main, NULL, BLI_CB_EVT_SAVE_PRE);
-
/* operator now handles overwrite checks */
if (G.fileflags & G_AUTOPACK) {
- packAll(G.main, reports);
+ packAll(G.main, reports, false);
}
/* don't forget not to return without! */
@@ -956,7 +1049,7 @@ int wm_file_write(bContext *C, const char *filepath, int fileflags, ReportList *
/* prevent background mode scripts from clobbering history */
if (!G.background) {
- write_history();
+ wm_history_file_update();
}
BLI_callback_exec(G.main, NULL, BLI_CB_EVT_SAVE_POST);
@@ -964,23 +1057,22 @@ int wm_file_write(bContext *C, const char *filepath, int fileflags, ReportList *
/* run this function after because the file cant be written before the blend is */
if (ibuf_thumb) {
IMB_thumb_delete(filepath, THB_FAIL); /* without this a failed thumb overrides */
- ibuf_thumb = IMB_thumb_create(filepath, THB_NORMAL, THB_SOURCE_BLEND, ibuf_thumb);
- IMB_freeImBuf(ibuf_thumb);
+ ibuf_thumb = IMB_thumb_create(filepath, THB_LARGE, THB_SOURCE_BLEND, ibuf_thumb);
}
- if (thumb) MEM_freeN(thumb);
+ ret = 0; /* Success. */
}
- else {
- if (ibuf_thumb) IMB_freeImBuf(ibuf_thumb);
- if (thumb) MEM_freeN(thumb);
-
- WM_cursor_wait(0);
- return -1;
+
+ if (ibuf_thumb) {
+ IMB_freeImBuf(ibuf_thumb);
+ }
+ if (thumb && thumb != main_thumb) {
+ MEM_freeN(thumb);
}
WM_cursor_wait(0);
-
- return 0;
+
+ return ret;
}
/**
@@ -993,6 +1085,8 @@ int wm_homefile_write_exec(bContext *C, wmOperator *op)
char filepath[FILE_MAX];
int fileflags;
+ BLI_callback_exec(G.main, NULL, BLI_CB_EVT_SAVE_PRE);
+
/* check current window and close it if temp */
if (win && win->screen->temp)
wm_window_close(C, wm, win);
@@ -1000,13 +1094,13 @@ int wm_homefile_write_exec(bContext *C, wmOperator *op)
/* update keymaps in user preferences */
WM_keyconfig_update(wm);
- BLI_make_file_string("/", filepath, BLI_get_folder_create(BLENDER_USER_CONFIG, NULL), BLENDER_STARTUP_FILE);
+ BLI_make_file_string("/", filepath, BKE_appdir_folder_id_create(BLENDER_USER_CONFIG, NULL), BLENDER_STARTUP_FILE);
printf("trying to save homefile at %s ", filepath);
ED_editors_flush_edits(C, false);
/* force save as regular blend file */
- fileflags = G.fileflags & ~(G_FILE_COMPRESS | G_FILE_AUTOPLAY | G_FILE_LOCK | G_FILE_SIGN | G_FILE_HISTORY);
+ fileflags = G.fileflags & ~(G_FILE_COMPRESS | G_FILE_AUTOPLAY | G_FILE_HISTORY);
if (BLO_write_file(CTX_data_main(C), filepath, fileflags | G_FILE_USERPREFS, op->reports, NULL) == 0) {
printf("fail\n");
@@ -1017,6 +1111,8 @@ int wm_homefile_write_exec(bContext *C, wmOperator *op)
G.save_over = 0;
+ BLI_callback_exec(G.main, NULL, BLI_CB_EVT_SAVE_POST);
+
return OPERATOR_FINISHED;
}
@@ -1029,7 +1125,7 @@ int wm_userpref_write_exec(bContext *C, wmOperator *op)
/* update keymaps in user preferences */
WM_keyconfig_update(wm);
- BLI_make_file_string("/", filepath, BLI_get_folder_create(BLENDER_USER_CONFIG, NULL), BLENDER_USERPREF_FILE);
+ BLI_make_file_string("/", filepath, BKE_appdir_folder_id_create(BLENDER_USER_CONFIG, NULL), BLENDER_USERPREF_FILE);
printf("trying to save userpref at %s ", filepath);
if (BKE_write_file_userdef(filepath, op->reports) == 0) {
@@ -1046,12 +1142,20 @@ int wm_userpref_write_exec(bContext *C, wmOperator *op)
void wm_autosave_location(char *filepath)
{
- char pidstr[32];
+ const int pid = abs(getpid());
+ char path[1024];
#ifdef WIN32
const char *savedir;
#endif
- BLI_snprintf(pidstr, sizeof(pidstr), "%d.blend", abs(getpid()));
+ if (G.main && G.relbase_valid) {
+ const char *basename = BLI_path_basename(G.main->name);
+ int len = strlen(basename) - 6;
+ BLI_snprintf(path, sizeof(path), "%.*s.blend", len, basename);
+ }
+ else {
+ BLI_snprintf(path, sizeof(path), "%d.blend", pid);
+ }
#ifdef WIN32
/* XXX Need to investigate how to handle default location of '/tmp/'
@@ -1062,14 +1166,14 @@ void wm_autosave_location(char *filepath)
* BLI_make_file_string will create string that has it most likely on C:\
* through get_default_root().
* If there is no C:\tmp autosave fails. */
- if (!BLI_exists(BLI_temp_dir_base())) {
- savedir = BLI_get_folder_create(BLENDER_USER_AUTOSAVE, NULL);
- BLI_make_file_string("/", filepath, savedir, pidstr);
+ if (!BLI_exists(BKE_tempdir_base())) {
+ savedir = BKE_appdir_folder_id_create(BLENDER_USER_AUTOSAVE, NULL);
+ BLI_make_file_string("/", filepath, savedir, path);
return;
}
#endif
- BLI_make_file_string("/", filepath, BLI_temp_dir_base(), pidstr);
+ BLI_make_file_string("/", filepath, BKE_tempdir_base(), path);
}
void WM_autosave_init(wmWindowManager *wm)
@@ -1098,8 +1202,6 @@ void wm_autosave_timer(const bContext *C, wmWindowManager *wm, wmTimer *UNUSED(w
}
}
- ED_editors_flush_edits(C, false);
-
wm_autosave_location(filepath);
if (U.uiflag & USER_GLOBALUNDO) {
@@ -1108,7 +1210,9 @@ void wm_autosave_timer(const bContext *C, wmWindowManager *wm, wmTimer *UNUSED(w
}
else {
/* save as regular blend file */
- int fileflags = G.fileflags & ~(G_FILE_COMPRESS | G_FILE_AUTOPLAY | G_FILE_LOCK | G_FILE_SIGN | G_FILE_HISTORY);
+ int fileflags = G.fileflags & ~(G_FILE_COMPRESS | G_FILE_AUTOPLAY | G_FILE_HISTORY);
+
+ ED_editors_flush_edits(C, false);
/* no error reporting to console */
BLO_write_file(CTX_data_main(C), filepath, fileflags, NULL, NULL);
@@ -1133,7 +1237,7 @@ void wm_autosave_delete(void)
if (BLI_exists(filename)) {
char str[FILE_MAX];
- BLI_make_file_string("/", str, BLI_temp_dir_base(), BLENDER_QUIT_FILE);
+ BLI_make_file_string("/", str, BKE_tempdir_base(), BLENDER_QUIT_FILE);
/* if global undo; remove tempsave, otherwise rename */
if (U.uiflag & USER_GLOBALUNDO) BLI_delete(filename, false, false);
diff --git a/source/blender/windowmanager/intern/wm_gesture.c b/source/blender/windowmanager/intern/wm_gesture.c
index 3e287a3907b..288e6711b56 100644
--- a/source/blender/windowmanager/intern/wm_gesture.c
+++ b/source/blender/windowmanager/intern/wm_gesture.c
@@ -49,12 +49,10 @@
#include "WM_types.h"
#include "wm.h"
-#include "wm_event_system.h"
#include "wm_subwindow.h"
#include "wm_draw.h"
-#include "BIF_gl.h"
#include "BIF_glutil.h"
diff --git a/source/blender/windowmanager/intern/wm_init_exit.c b/source/blender/windowmanager/intern/wm_init_exit.c
index b1f693502f6..ba4a807dbd7 100644
--- a/source/blender/windowmanager/intern/wm_init_exit.c
+++ b/source/blender/windowmanager/intern/wm_init_exit.c
@@ -40,9 +40,6 @@
#include "MEM_guardedalloc.h"
-#include "IMB_imbuf_types.h"
-#include "IMB_imbuf.h"
-
#include "DNA_scene_types.h"
#include "DNA_userdef_types.h"
#include "DNA_windowmanager_types.h"
@@ -54,18 +51,22 @@
#include "BLI_threads.h"
#include "BLI_utildefines.h"
+#include "BLO_writefile.h"
+
#include "BKE_blender.h"
#include "BKE_context.h"
#include "BKE_screen.h"
#include "BKE_DerivedMesh.h"
#include "BKE_global.h"
+#include "BKE_icons.h"
#include "BKE_library.h"
#include "BKE_main.h"
-#include "BKE_mball.h"
+#include "BKE_mball_tessellate.h"
#include "BKE_node.h"
#include "BKE_report.h"
#include "BKE_addon.h"
+#include "BKE_appdir.h"
#include "BKE_sequencer.h" /* free seq clipboard */
#include "BKE_material.h" /* clear_matcopybuf */
#include "BKE_tracking.h" /* free tracking clipboard */
@@ -96,6 +97,7 @@
#include "wm_window.h"
#include "ED_armature.h"
+#include "ED_gpencil.h"
#include "ED_keyframing.h"
#include "ED_node.h"
#include "ED_render.h"
@@ -105,16 +107,20 @@
#include "UI_interface.h"
#include "BLF_api.h"
-#include "BLF_translation.h"
+#include "BLT_lang.h"
#include "GPU_buffers.h"
-#include "GPU_extensions.h"
#include "GPU_draw.h"
+#include "GPU_init_exit.h"
#include "BKE_depsgraph.h"
#include "BKE_sound.h"
#include "COM_compositor.h"
+#ifdef WITH_OPENSUBDIV
+# include "opensubdiv_capi.h"
+#endif
+
static void wm_init_reports(bContext *C)
{
ReportList *reports = CTX_wm_reports(C);
@@ -148,10 +154,14 @@ void WM_init(bContext *C, int argc, const char **argv)
WM_menutype_init();
WM_uilisttype_init();
- set_free_windowmanager_cb(wm_close_and_free); /* library.c */
- set_free_notifier_reference_cb(WM_main_remove_notifier_reference); /* library.c */
- set_blender_test_break_cb(wm_window_testbreak); /* blender.c */
- DAG_editors_update_cb(ED_render_id_flush_update, ED_render_scene_update); /* depsgraph.c */
+ BKE_library_callback_free_window_manager_set(wm_close_and_free); /* library.c */
+ BKE_library_callback_free_notifier_reference_set(WM_main_remove_notifier_reference); /* library.c */
+ BKE_library_callback_free_editor_id_reference_set(WM_main_remove_editor_id_reference); /* library.c */
+ BKE_blender_callback_test_break_set(wm_window_testbreak); /* blender.c */
+ BKE_spacedata_callback_id_unref_set(ED_spacedata_id_unref); /* screen.c */
+ DAG_editors_update_cb(ED_render_id_flush_update,
+ ED_render_scene_update,
+ ED_render_scene_update_pre); /* depsgraph.c */
ED_spacetypes_init(); /* editors/space_api/spacetype.c */
@@ -159,15 +169,48 @@ void WM_init(bContext *C, int argc, const char **argv)
ED_node_init_butfuncs();
BLF_init(11, U.dpi); /* Please update source/gamengine/GamePlayer/GPG_ghost.cpp if you change this */
- BLF_lang_init();
+ BLT_lang_init();
/* Enforce loading the UI for the initial homefile */
G.fileflags &= ~G_FILE_NO_UI;
+ /* reports cant be initialized before the wm,
+ * but keep before file reading, since that may report errors */
+ wm_init_reports(C);
+
/* get the default database, plus a wm */
wm_homefile_read(C, NULL, G.factory_startup, NULL);
- BLF_lang_set(NULL);
+
+ BLT_lang_set(NULL);
+
+ if (!G.background) {
+ /* sets 3D mouse deadzone */
+ WM_ndof_deadzone_set(U.ndof_deadzone);
+
+ GPU_init();
+
+ GPU_set_mipmap(!(U.gameflags & USER_DISABLE_MIPMAP));
+ GPU_set_linear_mipmap(true);
+ GPU_set_anisotropic(U.anisotropic_filter);
+ GPU_set_gpu_mipmapping(U.use_gpu_mipmap);
+
+#ifdef WITH_OPENSUBDIV
+ openSubdiv_init();
+#endif
+
+ UI_init();
+ }
+ else {
+ /* Note: Currently only inits icons, which we now want in background mode too
+ * (scripts could use those in background processing...).
+ * In case we do more later, we may need to pass a 'background' flag.
+ * Called from 'UI_init' above */
+ BKE_icons_init(1);
+ }
+
+
+ ED_spacemacros_init();
/* note: there is a bug where python needs initializing before loading the
* startup.blend because it may contain PyDrivers. It also needs to be after
@@ -187,35 +230,20 @@ void WM_init(bContext *C, int argc, const char **argv)
(void)argv; /* unused */
#endif
- ED_spacemacros_init();
-
if (!G.background && !wm_start_with_console)
GHOST_toggleConsole(3);
- wm_init_reports(C); /* reports cant be initialized before the wm */
-
- if (!G.background) {
- GPU_extensions_init();
- GPU_set_mipmap(!(U.gameflags & USER_DISABLE_MIPMAP));
- GPU_set_anisotropic(U.anisotropic_filter);
- GPU_set_gpu_mipmapping(U.use_gpu_mipmap);
-
- UI_init();
- }
-
clear_matcopybuf();
ED_render_clear_mtex_copybuf();
// glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-
- ED_preview_init_dbase();
-
- wm_read_history();
+
+ wm_history_file_read();
/* allow a path of "", this is what happens when making a new file */
#if 0
if (G.main->name[0] == 0)
- BLI_make_file_string("/", G.main->name, BLI_getDefaultDocumentFolder(), "untitled.blend");
+ BLI_make_file_string("/", G.main->name, BKE_appdir_folder_default(), "untitled.blend");
#endif
BLI_strncpy(G.lib, G.main->name, FILE_MAX);
@@ -233,13 +261,24 @@ void WM_init(bContext *C, int argc, const char **argv)
/* that prevents loading both the kept session, and the file on the command line */
}
else {
+ /* note, logic here is from wm_file_read_post,
+ * call functions that depend on Python being initialized. */
+
/* normally 'wm_homefile_read' will do this,
* however python is not initialized when called from this function.
*
* unlikely any handlers are set but its possible,
* note that recovering the last session does its own callbacks. */
+ CTX_wm_window_set(C, CTX_wm_manager(C)->windows.first);
+
BLI_callback_exec(CTX_data_main(C), NULL, BLI_CB_EVT_VERSION_UPDATE);
BLI_callback_exec(CTX_data_main(C), NULL, BLI_CB_EVT_LOAD_POST);
+
+ wm_file_read_report(C);
+
+ if (!G.background) {
+ CTX_wm_window_set(C, NULL);
+ }
}
}
@@ -304,7 +343,7 @@ bool WM_init_game(bContext *C)
/* full screen the area */
if (!sa->full) {
- ED_screen_full_toggle(C, win, sa);
+ ED_screen_state_toggle(C, win, sa, SCREENMAXIMIZED);
}
/* Fullscreen */
@@ -325,7 +364,7 @@ bool WM_init_game(bContext *C)
WM_operator_name_call(C, "VIEW3D_OT_game_start", WM_OP_EXEC_DEFAULT, NULL);
- sound_exit();
+ BKE_sound_exit();
return true;
}
@@ -395,7 +434,7 @@ void WM_exit_ext(bContext *C, const bool do_python)
{
wmWindowManager *wm = C ? CTX_wm_manager(C) : NULL;
- sound_exit();
+ BKE_sound_exit();
/* first wrap up running stuff, we assume only the active WM is running */
/* modal handlers are on window level freed, others too? */
@@ -404,14 +443,21 @@ void WM_exit_ext(bContext *C, const bool do_python)
wmWindow *win;
if (!G.background) {
- if ((U.uiflag2 & USER_KEEP_SESSION) || BKE_undo_valid(NULL)) {
+ if ((U.uiflag2 & USER_KEEP_SESSION) || BKE_undo_is_valid(NULL)) {
/* save the undo state as quit.blend */
char filename[FILE_MAX];
-
- BLI_make_file_string("/", filename, BLI_temp_dir_base(), BLENDER_QUIT_FILE);
+ bool has_edited;
+ int fileflags = G.fileflags & ~(G_FILE_COMPRESS | G_FILE_AUTOPLAY | G_FILE_HISTORY);
- if (BKE_undo_save_file(filename))
+ BLI_make_file_string("/", filename, BKE_tempdir_base(), BLENDER_QUIT_FILE);
+
+ has_edited = ED_editors_flush_edits(C, false);
+
+ if ((has_edited && BLO_write_file(CTX_data_main(C), filename, fileflags, NULL, NULL)) ||
+ BKE_undo_save_file(filename))
+ {
printf("Saved session recovery to '%s'\n", filename);
+ }
}
}
@@ -467,6 +513,7 @@ void WM_exit_ext(bContext *C, const bool do_python)
free_anim_copybuf();
free_anim_drivers_copybuf();
free_fmodifiers_copybuf();
+ ED_gpencil_strokes_copybuf_free();
ED_clipboard_posebuf_free();
BKE_node_clipboard_clear();
@@ -475,7 +522,7 @@ void WM_exit_ext(bContext *C, const bool do_python)
#ifdef WITH_INTERNATIONAL
BLF_free_unifont();
BLF_free_unifont_mono();
- BLF_lang_free();
+ BLT_lang_free();
#endif
ANIM_keyingset_infos_exit();
@@ -499,13 +546,18 @@ void WM_exit_ext(bContext *C, const bool do_python)
(void)do_python;
#endif
+#ifdef WITH_OPENSUBDIV
+ openSubdiv_cleanup();
+#endif
+
if (!G.background) {
GPU_global_buffer_pool_free();
GPU_free_unused_buffers();
- GPU_extensions_exit();
+
+ GPU_exit();
}
- BKE_reset_undo();
+ BKE_undo_reset();
ED_file_exit(); /* for fsmenu */
@@ -526,12 +578,15 @@ void WM_exit_ext(bContext *C, const bool do_python)
BLI_threadapi_exit();
if (MEM_get_memory_blocks_in_use() != 0) {
- printf("Error: Not freed memory blocks: %d\n", MEM_get_memory_blocks_in_use());
+ size_t mem_in_use = MEM_get_memory_in_use() + MEM_get_memory_in_use();
+ printf("Error: Not freed memory blocks: %u, total unfreed memory %f MB\n",
+ MEM_get_memory_blocks_in_use(),
+ (double)mem_in_use / 1024 / 1024);
MEM_printmemlist();
}
wm_autosave_delete();
- BLI_temp_dir_session_purge();
+ BKE_tempdir_session_purge();
}
void WM_exit(bContext *C)
diff --git a/source/blender/windowmanager/intern/wm_jobs.c b/source/blender/windowmanager/intern/wm_jobs.c
index 74c504050ae..f8258d18c1a 100644
--- a/source/blender/windowmanager/intern/wm_jobs.c
+++ b/source/blender/windowmanager/intern/wm_jobs.c
@@ -45,8 +45,6 @@
#include "WM_api.h"
#include "WM_types.h"
-#include "wm_window.h"
-#include "wm_event_system.h"
#include "wm_event_types.h"
#include "wm.h"
@@ -159,8 +157,8 @@ static void wm_job_main_thread_yield(wmJob *wm_job, bool ending)
BLI_ticket_mutex_lock(wm_job->main_thread_mutex);
}
-/* finds:
- * if type or owner, compare for it, otherwise any matching job
+/**
+ * Finds if type or owner, compare for it, otherwise any matching job.
*/
static wmJob *wm_job_find(wmWindowManager *wm, void *owner, const int job_type)
{
@@ -187,9 +185,12 @@ static wmJob *wm_job_find(wmWindowManager *wm, void *owner, const int job_type)
/* ******************* public API ***************** */
-/* returns current or adds new job, but doesnt run it */
-/* every owner only gets a single job, adding a new one will stop running job and
- * when stopped it starts the new one */
+/**
+ * \return current job or adds new job, but doesnt run it.
+ *
+ * \note every owner only gets a single job,
+ * adding a new one will stop running job and when stopped it starts the new one.
+ */
wmJob *WM_jobs_get(wmWindowManager *wm, wmWindow *win, void *owner, const char *name, int flag, int job_type)
{
wmJob *wm_job = wm_job_find(wm, owner, job_type);
@@ -377,8 +378,10 @@ static void wm_jobs_test_suspend_stop(wmWindowManager *wm, wmJob *test)
// if (suspend) printf("job suspended: %s\n", test->name);
}
-/* if job running, the same owner gave it a new job */
-/* if different owner starts existing startjob, it suspends itself */
+/**
+ * if job running, the same owner gave it a new job.
+ * if different owner starts existing startjob, it suspends itself
+ */
void WM_jobs_start(wmWindowManager *wm, wmJob *wm_job)
{
if (wm_job->running) {
@@ -630,17 +633,22 @@ void wm_jobs_timer(const bContext *C, wmWindowManager *wm, wmTimer *wt)
}
}
- /* on file load 'winactive' can be NULL, possibly it should not happen but for now do a NULL check - campbell */
- if (wm->winactive) {
- /* if there are running jobs, set the global progress indicator */
- if (jobs_progress > 0) {
- float progress = total_progress / (float)jobs_progress;
- WM_progress_set(wm->winactive, progress);
- }
- else {
- WM_progress_clear(wm->winactive);
- }
+
+ /* if there are running jobs, set the global progress indicator */
+ if (jobs_progress > 0) {
+ wmWindow *win;
+ float progress = total_progress / (float)jobs_progress;
+
+ for (win = wm->windows.first; win; win = win->next)
+ WM_progress_set(win, progress);
+ }
+ else {
+ wmWindow *win;
+
+ for (win = wm->windows.first; win; win = win->next)
+ WM_progress_clear(win);
}
+
}
bool WM_jobs_has_running(wmWindowManager *wm)
diff --git a/source/blender/windowmanager/intern/wm_keymap.c b/source/blender/windowmanager/intern/wm_keymap.c
index 748303f9082..5098df2c0a6 100644
--- a/source/blender/windowmanager/intern/wm_keymap.c
+++ b/source/blender/windowmanager/intern/wm_keymap.c
@@ -42,6 +42,7 @@
#include "BLI_blenlib.h"
#include "BLI_utildefines.h"
+#include "BLI_math.h"
#include "BKE_context.h"
#include "BKE_idprop.h"
@@ -49,14 +50,13 @@
#include "BKE_main.h"
#include "BKE_screen.h"
-#include "BLF_translation.h"
+#include "BLT_translation.h"
#include "RNA_access.h"
#include "RNA_enum_types.h"
#include "WM_api.h"
#include "WM_types.h"
-#include "wm_window.h"
#include "wm_event_system.h"
#include "wm_event_types.h"
@@ -146,21 +146,15 @@ static void wm_keyconfig_properties_update_ot(ListBase *km_lb)
}
}
-static int wm_keymap_item_equals_result(wmKeyMapItem *a, wmKeyMapItem *b)
+static bool wm_keymap_item_equals_result(wmKeyMapItem *a, wmKeyMapItem *b)
{
- if (strcmp(a->idname, b->idname) != 0)
- return 0;
-
- if (!RNA_struct_equals(a->ptr, b->ptr, RNA_EQ_UNSET_MATCH_NONE))
- return 0;
-
- if ((a->flag & KMI_INACTIVE) != (b->flag & KMI_INACTIVE))
- return 0;
-
- return (a->propvalue == b->propvalue);
+ return (STREQ(a->idname, b->idname) &&
+ RNA_struct_equals(a->ptr, b->ptr, RNA_EQ_UNSET_MATCH_NONE) &&
+ (a->flag & KMI_INACTIVE) == (b->flag & KMI_INACTIVE) &&
+ a->propvalue == b->propvalue);
}
-static int wm_keymap_item_equals(wmKeyMapItem *a, wmKeyMapItem *b)
+static bool wm_keymap_item_equals(wmKeyMapItem *a, wmKeyMapItem *b)
{
return (wm_keymap_item_equals_result(a, b) &&
a->type == b->type &&
@@ -267,7 +261,7 @@ wmKeyConfig *WM_keyconfig_new_user(wmWindowManager *wm, const char *idname)
bool WM_keyconfig_remove(wmWindowManager *wm, wmKeyConfig *keyconf)
{
if (BLI_findindex(&wm->keyconfigs, keyconf) != -1) {
- if (strncmp(U.keyconfigstr, keyconf->idname, sizeof(U.keyconfigstr)) == 0) {
+ if (STREQLEN(U.keyconfigstr, keyconf->idname, sizeof(U.keyconfigstr))) {
BLI_strncpy(U.keyconfigstr, wm->defaultconf->idname, sizeof(U.keyconfigstr));
WM_keyconfig_update_tag(NULL, NULL);
}
@@ -422,7 +416,7 @@ wmKeyMapItem *WM_keymap_verify_item(wmKeyMap *keymap, const char *idname, int ty
wmKeyMapItem *kmi;
for (kmi = keymap->items.first; kmi; kmi = kmi->next)
- if (strncmp(kmi->idname, idname, OP_MAX_TYPENAME) == 0)
+ if (STREQLEN(kmi->idname, idname, OP_MAX_TYPENAME))
break;
if (kmi == NULL) {
kmi = MEM_callocN(sizeof(wmKeyMapItem), "keymap entry");
@@ -553,7 +547,7 @@ static void wm_keymap_diff(wmKeyMap *diff_km, wmKeyMap *from_km, wmKeyMap *to_km
if (to_kmi) {
orig_kmi = WM_keymap_item_find_id(orig_km, kmi->id);
- if (!orig_kmi)
+ if (!orig_kmi && addon_km)
orig_kmi = wm_keymap_find_item_equals(addon_km, kmi);
if (orig_kmi) {
@@ -589,8 +583,26 @@ static void wm_keymap_patch(wmKeyMap *km, wmKeyMap *diff_km)
/* add item */
if (kmdi->add_item) {
+ /* Do not re-add an already existing keymap item! See T42088. */
+ /* We seek only for exact copy here! See T42137. */
+ kmi_add = wm_keymap_find_item_equals(km, kmdi->add_item);
+
+ /* If kmi_add is same as kmi_remove (can happen in some cases, typically when we got kmi_remove
+ * from wm_keymap_find_item_equals_result()), no need to add or remove anything, see T45579. */
+ /* Note: This typically happens when we apply user-defined keymap diff to a base one that was exported
+ * with that customized keymap already. In that case:
+ * - wm_keymap_find_item_equals(km, kmdi->remove_item) finds nothing (because actual shortcut of
+ * current base does not match kmdi->remove_item any more).
+ * - wm_keymap_find_item_equals_result(km, kmdi->remove_item) finds the current kmi from
+ * base keymap (because it does exactly the same thing).
+ * - wm_keymap_find_item_equals(km, kmdi->add_item) finds the same kmi, since base keymap was
+ * exported with that user-defined shortcut already!
+ * Maybe we should rather keep user-defined keymaps specific to a given base one? */
+ if (kmi_add != NULL && kmi_add == kmi_remove) {
+ kmi_remove = NULL;
+ }
/* only if nothing to remove or item to remove found */
- if (!kmdi->remove_item || kmi_remove) {
+ else if (!kmi_add && (!kmdi->remove_item || kmi_remove)) {
kmi_add = wm_keymap_item_copy(kmdi->add_item);
kmi_add->flag |= KMI_USER_MODIFIED;
@@ -726,7 +738,7 @@ wmKeyMap *WM_keymap_list_find(ListBase *lb, const char *idname, int spaceid, int
for (km = lb->first; km; km = km->next)
if (km->spaceid == spaceid && km->regionid == regionid)
- if (0 == strncmp(idname, km->idname, KMAP_MAX_NAME))
+ if (STREQLEN(idname, km->idname, KMAP_MAX_NAME))
return km;
return NULL;
@@ -785,7 +797,7 @@ wmKeyMap *WM_modalkeymap_get(wmKeyConfig *keyconf, const char *idname)
for (km = keyconf->keymaps.first; km; km = km->next)
if (km->flag & KEYMAP_MODAL)
- if (0 == strncmp(idname, km->idname, KMAP_MAX_NAME))
+ if (STREQLEN(idname, km->idname, KMAP_MAX_NAME))
break;
return km;
@@ -824,12 +836,11 @@ wmKeyMapItem *WM_modalkeymap_add_item_str(wmKeyMap *km, int type, int val, int m
return kmi;
}
-wmKeyMapItem *WM_modalkeymap_find_propvalue(wmKeyMap *km, const int propvalue)
+static wmKeyMapItem *wm_modalkeymap_find_propvalue_iter(wmKeyMap *km, wmKeyMapItem *kmi, const int propvalue)
{
-
if (km->flag & KEYMAP_MODAL) {
- wmKeyMapItem *kmi;
- for (kmi = km->items.first; kmi; kmi = kmi->next) {
+ kmi = kmi ? kmi->next : km->items.first;
+ for (; kmi; kmi = kmi->next) {
if (kmi->propvalue == propvalue) {
return kmi;
}
@@ -842,6 +853,11 @@ wmKeyMapItem *WM_modalkeymap_find_propvalue(wmKeyMap *km, const int propvalue)
return NULL;
}
+wmKeyMapItem *WM_modalkeymap_find_propvalue(wmKeyMap *km, const int propvalue)
+{
+ return wm_modalkeymap_find_propvalue_iter(km, NULL, propvalue);
+}
+
void WM_modalkeymap_assign(wmKeyMap *km, const char *opname)
{
wmOperatorType *ot = WM_operatortype_find(opname, 0);
@@ -885,55 +901,156 @@ static void wm_user_modal_keymap_set_items(wmWindowManager *wm, wmKeyMap *km)
/* ***************** get string from key events **************** */
-const char *WM_key_event_string(short type)
+const char *WM_key_event_string(const short type, const bool compact)
{
const char *name = NULL;
- if (RNA_enum_name(event_type_items, (int)type, &name))
- return name;
-
+ /* We first try enum items' description (abused as shortname here), and fall back to usual name if empty. */
+ if ((compact && RNA_enum_description(event_type_items, (int)type, &name) && name[0]) ||
+ RNA_enum_name(event_type_items, (int)type, &name))
+ {
+ return IFACE_(name);
+ }
+
return "";
}
-int WM_keymap_item_to_string(wmKeyMapItem *kmi, char *str, const int len)
+/* TODO: also support (some) value, like e.g. double-click? */
+int WM_keymap_item_raw_to_string(
+ const short shift, const short ctrl, const short alt, const short oskey,
+ const short keymodifier, const short val, const short type, const bool compact,
+ const int len, char *r_str)
{
+#define ADD_SEP if (p != buf) *p++ = ' '; (void)0
+
char buf[128];
char *p = buf;
- buf[0] = 0;
+ buf[0] = '\0';
- if (kmi->shift == KM_ANY &&
- kmi->ctrl == KM_ANY &&
- kmi->alt == KM_ANY &&
- kmi->oskey == KM_ANY)
+ /* TODO: support order (KM_SHIFT vs. KM_SHIFT2) ? */
+ if (shift == KM_ANY &&
+ ctrl == KM_ANY &&
+ alt == KM_ANY &&
+ oskey == KM_ANY)
{
- p += BLI_strcpy_rlen(p, "Any ");
+ /* make it implicit in case of compact result expected. */
+ if (!compact) {
+ ADD_SEP;
+ p += BLI_strcpy_rlen(p, IFACE_("Any"));
+ }
}
else {
- if (kmi->shift)
- p += BLI_strcpy_rlen(p, "Shift ");
+ if (shift) {
+ ADD_SEP;
+ p += BLI_strcpy_rlen(p, IFACE_("Shift"));
+ }
- if (kmi->ctrl)
- p += BLI_strcpy_rlen(p, "Ctrl ");
+ if (ctrl) {
+ ADD_SEP;
+ p += BLI_strcpy_rlen(p, IFACE_("Ctrl"));
+ }
+
+ if (alt) {
+ ADD_SEP;
+ p += BLI_strcpy_rlen(p, IFACE_("Alt"));
+ }
- if (kmi->alt)
- p += BLI_strcpy_rlen(p, "Alt ");
+ if (oskey) {
+ ADD_SEP;
+ p += BLI_strcpy_rlen(p, IFACE_("Cmd"));
+ }
+ }
- if (kmi->oskey)
- p += BLI_strcpy_rlen(p, "Cmd ");
+ if (keymodifier) {
+ ADD_SEP;
+ p += BLI_strcpy_rlen(p, WM_key_event_string(keymodifier, compact));
}
-
- if (kmi->keymodifier) {
- p += BLI_strcpy_rlen(p, WM_key_event_string(kmi->keymodifier));
- p += BLI_strcpy_rlen(p, " ");
+
+ if (type) {
+ ADD_SEP;
+ if (val == KM_DBL_CLICK) {
+ p += BLI_strcpy_rlen(p, IFACE_("dbl-"));
+ }
+ p += BLI_strcpy_rlen(p, WM_key_event_string(type, compact));
+ }
+
+ /* We assume size of buf is enough to always store any possible shortcut, but let's add a debug check about it! */
+ BLI_assert(p - buf < sizeof(buf));
+
+ /* We need utf8 here, otherwise we may 'cut' some unicode chars like arrows... */
+ return BLI_strncpy_utf8_rlen(r_str, buf, len);
+
+#undef ADD_SEP
+}
+
+int WM_keymap_item_to_string(wmKeyMapItem *kmi, const bool compact, const int len, char *r_str)
+{
+ return WM_keymap_item_raw_to_string(
+ kmi->shift, kmi->ctrl, kmi->alt, kmi->oskey, kmi->keymodifier, kmi->val, kmi->type,
+ compact, len, r_str);
+}
+
+int WM_modalkeymap_items_to_string(
+ wmKeyMap *km, const int propvalue, const bool compact, const int len, char *r_str)
+{
+ int totlen = 0;
+ bool add_sep = false;
+
+ if (km) {
+ wmKeyMapItem *kmi;
+
+ /* Find all shortcuts related to that propvalue! */
+ for (kmi = WM_modalkeymap_find_propvalue(km, propvalue);
+ kmi && totlen < (len - 2);
+ kmi = wm_modalkeymap_find_propvalue_iter(km, kmi, propvalue))
+ {
+ if (add_sep) {
+ r_str[totlen++] = '/';
+ r_str[totlen] = '\0';
+ }
+ else {
+ add_sep = true;
+ }
+ totlen += WM_keymap_item_to_string(kmi, compact, len - totlen, &r_str[totlen]);
+ }
}
- p += BLI_strcpy_rlen(p, WM_key_event_string(kmi->type));
- return BLI_strncpy_rlen(str, buf, len);
+ return totlen;
+}
+
+int WM_modalkeymap_operator_items_to_string(
+ wmOperatorType *ot, const int propvalue, const bool compact, const int len, char *r_str)
+{
+ return WM_modalkeymap_items_to_string(ot->modalkeymap, propvalue, compact, len, r_str);
+}
+
+char *WM_modalkeymap_operator_items_to_string_buf(
+ wmOperatorType *ot, const int propvalue, const bool compact,
+ const int max_len, int *r_available_len, char **r_str)
+{
+ char *ret = *r_str;
+
+ if (*r_available_len > 1) {
+ int used_len = WM_modalkeymap_operator_items_to_string(
+ ot, propvalue, compact, min_ii(*r_available_len, max_len), ret) + 1;
+
+ *r_available_len -= used_len;
+ *r_str += used_len;
+ if (*r_available_len == 0) {
+ (*r_str)--; /* So that *str keeps pointing on a valid char, we'll stay on it anyway. */
+ }
+ }
+ else {
+ *ret = '\0';
+ }
+
+ return ret;
}
static wmKeyMapItem *wm_keymap_item_find_handlers(
const bContext *C, ListBase *handlers, const char *opname, int UNUSED(opcontext),
- IDProperty *properties, const bool is_strict, const bool is_hotkey, wmKeyMap **keymap_r)
+ IDProperty *properties, const bool is_strict, const bool is_hotkey,
+ wmKeyMap **r_keymap)
{
wmWindowManager *wm = CTX_wm_manager(C);
wmEventHandler *handler;
@@ -950,18 +1067,17 @@ static wmKeyMapItem *wm_keymap_item_find_handlers(
if (kmi->flag & KMI_INACTIVE)
continue;
- if (strcmp(kmi->idname, opname) == 0 && WM_key_event_string(kmi->type)[0]) {
+ if (STREQ(kmi->idname, opname) && WM_key_event_string(kmi->type, false)[0]) {
if (is_hotkey) {
if (!ISHOTKEY(kmi->type))
continue;
}
if (properties) {
-
/* example of debugging keymaps */
#if 0
if (kmi->ptr) {
- if (strcmp("MESH_OT_rip_move", opname) == 0) {
+ if (STREQ("MESH_OT_rip_move", opname)) {
printf("OPERATOR\n");
IDP_spit(properties);
printf("KEYMAP\n");
@@ -971,12 +1087,47 @@ static wmKeyMapItem *wm_keymap_item_find_handlers(
#endif
if (kmi->ptr && IDP_EqualsProperties_ex(properties, kmi->ptr->data, is_strict)) {
- if (keymap_r) *keymap_r = keymap;
+ if (r_keymap) *r_keymap = keymap;
return kmi;
}
+ /* Debug only, helps spotting mismatches between menu entries and shortcuts! */
+ else if (G.debug & G_DEBUG_WM) {
+ if (is_strict && kmi->ptr) {
+ wmOperatorType *ot = WM_operatortype_find(opname, true);
+ if (ot) {
+ /* make a copy of the properties and set unset ones to their default values. */
+ PointerRNA opptr;
+ IDProperty *properties_default = IDP_CopyProperty(kmi->ptr->data);
+
+ RNA_pointer_create(NULL, ot->srna, properties_default, &opptr);
+ WM_operator_properties_default(&opptr, true);
+
+ if (IDP_EqualsProperties_ex(properties, properties_default, is_strict)) {
+ char kmi_str[128];
+ WM_keymap_item_to_string(kmi, false, sizeof(kmi_str), kmi_str);
+ /* Note gievn properties could come from other things than menu entry... */
+ printf("%s: Some set values in menu entry match default op values, "
+ "this might not be desired!\n", opname);
+ printf("\tkm: '%s', kmi: '%s'\n", keymap->idname, kmi_str);
+#ifndef NDEBUG
+#ifdef WITH_PYTHON
+ printf("OPERATOR\n");
+ IDP_spit(properties);
+ printf("KEYMAP\n");
+ IDP_spit(kmi->ptr->data);
+#endif
+#endif
+ printf("\n");
+ }
+
+ IDP_FreeProperty(properties_default);
+ MEM_freeN(properties_default);
+ }
+ }
+ }
}
else {
- if (keymap_r) *keymap_r = keymap;
+ if (r_keymap) *r_keymap = keymap;
return kmi;
}
}
@@ -985,13 +1136,14 @@ static wmKeyMapItem *wm_keymap_item_find_handlers(
}
/* ensure un-initialized keymap is never used */
- if (keymap_r) *keymap_r = NULL;
+ if (r_keymap) *r_keymap = NULL;
return NULL;
}
static wmKeyMapItem *wm_keymap_item_find_props(
const bContext *C, const char *opname, int opcontext,
- IDProperty *properties, const bool is_strict, const bool is_hotkey, wmKeyMap **keymap_r)
+ IDProperty *properties, const bool is_strict, const bool is_hotkey,
+ wmKeyMap **r_keymap)
{
wmWindow *win = CTX_wm_window(C);
ScrArea *sa = CTX_wm_area(C);
@@ -1000,10 +1152,10 @@ static wmKeyMapItem *wm_keymap_item_find_props(
/* look into multiple handler lists to find the item */
if (win)
- found = wm_keymap_item_find_handlers(C, &win->handlers, opname, opcontext, properties, is_strict, is_hotkey, keymap_r);
+ found = wm_keymap_item_find_handlers(C, &win->handlers, opname, opcontext, properties, is_strict, is_hotkey, r_keymap);
if (sa && found == NULL)
- found = wm_keymap_item_find_handlers(C, &sa->handlers, opname, opcontext, properties, is_strict, is_hotkey, keymap_r);
+ found = wm_keymap_item_find_handlers(C, &sa->handlers, opname, opcontext, properties, is_strict, is_hotkey, r_keymap);
if (found == NULL) {
if (ELEM(opcontext, WM_OP_EXEC_REGION_WIN, WM_OP_INVOKE_REGION_WIN)) {
@@ -1012,7 +1164,7 @@ static wmKeyMapItem *wm_keymap_item_find_props(
ar = BKE_area_find_region_type(sa, RGN_TYPE_WINDOW);
if (ar)
- found = wm_keymap_item_find_handlers(C, &ar->handlers, opname, opcontext, properties, is_strict, is_hotkey, keymap_r);
+ found = wm_keymap_item_find_handlers(C, &ar->handlers, opname, opcontext, properties, is_strict, is_hotkey, r_keymap);
}
}
else if (ELEM(opcontext, WM_OP_EXEC_REGION_CHANNELS, WM_OP_INVOKE_REGION_CHANNELS)) {
@@ -1020,18 +1172,18 @@ static wmKeyMapItem *wm_keymap_item_find_props(
ar = BKE_area_find_region_type(sa, RGN_TYPE_CHANNELS);
if (ar)
- found = wm_keymap_item_find_handlers(C, &ar->handlers, opname, opcontext, properties, is_strict, is_hotkey, keymap_r);
+ found = wm_keymap_item_find_handlers(C, &ar->handlers, opname, opcontext, properties, is_strict, is_hotkey, r_keymap);
}
else if (ELEM(opcontext, WM_OP_EXEC_REGION_PREVIEW, WM_OP_INVOKE_REGION_PREVIEW)) {
if (!(ar && ar->regiontype == RGN_TYPE_PREVIEW))
ar = BKE_area_find_region_type(sa, RGN_TYPE_PREVIEW);
if (ar)
- found = wm_keymap_item_find_handlers(C, &ar->handlers, opname, opcontext, properties, is_strict, is_hotkey, keymap_r);
+ found = wm_keymap_item_find_handlers(C, &ar->handlers, opname, opcontext, properties, is_strict, is_hotkey, r_keymap);
}
else {
if (ar)
- found = wm_keymap_item_find_handlers(C, &ar->handlers, opname, opcontext, properties, is_strict, is_hotkey, keymap_r);
+ found = wm_keymap_item_find_handlers(C, &ar->handlers, opname, opcontext, properties, is_strict, is_hotkey, r_keymap);
}
}
@@ -1040,33 +1192,86 @@ static wmKeyMapItem *wm_keymap_item_find_props(
static wmKeyMapItem *wm_keymap_item_find(
const bContext *C, const char *opname, int opcontext,
- IDProperty *properties, const bool is_hotkey, const bool is_strict, wmKeyMap **keymap_r)
+ IDProperty *properties, const bool is_hotkey, bool is_strict,
+ wmKeyMap **r_keymap)
{
- wmKeyMapItem *found = wm_keymap_item_find_props(C, opname, opcontext, properties, is_strict, is_hotkey, keymap_r);
+ wmKeyMapItem *found;
+ /* XXX Hack! Macro operators in menu entry have their whole props defined, which is not the case for
+ * relevant keymap entries. Could be good to check and harmonize this, but for now always
+ * compare non-strict in this case.
+ */
+ wmOperatorType *ot = WM_operatortype_find(opname, true);
+ if (ot) {
+ is_strict = is_strict && ((ot->flag & OPTYPE_MACRO) == 0);
+ }
+
+ found = wm_keymap_item_find_props(C, opname, opcontext, properties, is_strict, is_hotkey, r_keymap);
+
+ /* This block is *only* useful in one case: when op uses an enum menu in its prop member
+ * (then, we want to rerun a comparison with that 'prop' unset). Note this remains brittle,
+ * since now any enum prop may be used in UI (specified by name), ot->prop is not so much used...
+ * Otherwise:
+ * * If non-strict, unset properties always match set ones in IDP_EqualsProperties_ex.
+ * * If strict, unset properties never match set ones in IDP_EqualsProperties_ex,
+ * and we do not want that to change (else we get things like T41757)!
+ * ...so in either case, re-running a comparison with unset props set to default is useless.
+ */
if (!found && properties) {
- wmOperatorType *ot = WM_operatortype_find(opname, true);
- if (ot) {
- /* make a copy of the properties and set any unset props
- * to their default values, so the ID property compare function succeeds */
+ if (ot && ot->prop) { /* XXX Shall we also check ot->prop is actually an enum? */
+ /* make a copy of the properties and unset the 'ot->prop' one if set. */
PointerRNA opptr;
- IDProperty *properties_default = IDP_CopyProperty(properties);
+ IDProperty *properties_temp = IDP_CopyProperty(properties);
- RNA_pointer_create(NULL, ot->srna, properties_default, &opptr);
+ RNA_pointer_create(NULL, ot->srna, properties_temp, &opptr);
- if (WM_operator_properties_default(&opptr, true) ||
- (!is_strict && ot->prop && RNA_property_is_set(&opptr, ot->prop)))
- {
- /* for operator that has enum menu, unset it so it always matches */
- if (!is_strict && ot->prop) {
- RNA_property_unset(&opptr, ot->prop);
- }
+ if (RNA_property_is_set(&opptr, ot->prop)) {
+ /* for operator that has enum menu, unset it so its value does not affect comparison result */
+ RNA_property_unset(&opptr, ot->prop);
- found = wm_keymap_item_find_props(C, opname, opcontext, properties_default, false, is_hotkey, keymap_r);
+ found = wm_keymap_item_find_props(C, opname, opcontext, properties_temp,
+ is_strict, is_hotkey, r_keymap);
}
- IDP_FreeProperty(properties_default);
- MEM_freeN(properties_default);
+ IDP_FreeProperty(properties_temp);
+ MEM_freeN(properties_temp);
+ }
+ }
+
+ /* Debug only, helps spotting mismatches between menu entries and shortcuts! */
+ if (G.debug & G_DEBUG_WM) {
+ if (!found && is_strict && properties) {
+ wmKeyMap *km;
+ wmKeyMapItem *kmi;
+ if (ot) {
+ /* make a copy of the properties and set unset ones to their default values. */
+ PointerRNA opptr;
+ IDProperty *properties_default = IDP_CopyProperty(properties);
+
+ RNA_pointer_create(NULL, ot->srna, properties_default, &opptr);
+ WM_operator_properties_default(&opptr, true);
+
+ kmi = wm_keymap_item_find_props(C, opname, opcontext, properties_default, is_strict, is_hotkey, &km);
+ if (kmi) {
+ char kmi_str[128];
+ WM_keymap_item_to_string(kmi, false, sizeof(kmi_str), kmi_str);
+ printf("%s: Some set values in keymap entry match default op values, "
+ "this might not be desired!\n", opname);
+ printf("\tkm: '%s', kmi: '%s'\n", km->idname, kmi_str);
+#ifndef NDEBUG
+#ifdef WITH_PYTHON
+ printf("OPERATOR\n");
+ IDP_spit(properties);
+ printf("KEYMAP\n");
+ IDP_spit(kmi->ptr->data);
+#endif
+#endif
+ printf("\n");
+ }
+
+ IDP_FreeProperty(properties_default);
+ MEM_freeN(properties_default);
+ }
}
}
@@ -1075,13 +1280,13 @@ static wmKeyMapItem *wm_keymap_item_find(
char *WM_key_event_operator_string(
const bContext *C, const char *opname, int opcontext,
- IDProperty *properties, const bool is_strict, char *str, int len)
+ IDProperty *properties, const bool is_strict, int len, char *r_str)
{
wmKeyMapItem *kmi = wm_keymap_item_find(C, opname, opcontext, properties, false, is_strict, NULL);
if (kmi) {
- WM_keymap_item_to_string(kmi, str, len);
- return str;
+ WM_keymap_item_to_string(kmi, false, len, r_str);
+ return r_str;
}
return NULL;
@@ -1089,9 +1294,10 @@ char *WM_key_event_operator_string(
int WM_key_event_operator_id(
const bContext *C, const char *opname, int opcontext,
- IDProperty *properties, const bool is_hotkey, wmKeyMap **keymap_r)
+ IDProperty *properties, const bool is_hotkey,
+ wmKeyMap **r_keymap)
{
- wmKeyMapItem *kmi = wm_keymap_item_find(C, opname, opcontext, properties, is_hotkey, true, keymap_r);
+ wmKeyMapItem *kmi = wm_keymap_item_find(C, opname, opcontext, properties, is_hotkey, true, r_keymap);
if (kmi)
return kmi->id;
@@ -1351,7 +1557,7 @@ void WM_keymap_restore_item_to_default(bContext *C, wmKeyMap *keymap, wmKeyMapIt
if (orig) {
/* restore to original */
- if (strcmp(orig->idname, kmi->idname) != 0) {
+ if (!STREQ(orig->idname, kmi->idname)) {
BLI_strncpy(kmi->idname, orig->idname, sizeof(kmi->idname));
WM_keymap_properties_reset(kmi, NULL);
}
diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c
index 415187ecf69..c9dd07208c1 100644
--- a/source/blender/windowmanager/intern/wm_operators.c
+++ b/source/blender/windowmanager/intern/wm_operators.c
@@ -38,8 +38,11 @@
#include <stdio.h>
#include <stddef.h>
#include <assert.h>
+#include <errno.h>
-#include "GHOST_C-api.h"
+#ifdef WIN32
+# include "GHOST_C-api.h"
+#endif
#include "MEM_guardedalloc.h"
@@ -51,38 +54,42 @@
#include "DNA_windowmanager_types.h"
#include "DNA_mesh_types.h" /* only for USE_BMESH_SAVE_AS_COMPAT */
-#include "BLF_translation.h"
+#include "BLT_translation.h"
#include "PIL_time.h"
#include "BLI_blenlib.h"
#include "BLI_dial.h"
#include "BLI_dynstr.h" /*for WM_operator_pystring */
+#include "BLI_linklist_stack.h"
#include "BLI_math.h"
#include "BLI_utildefines.h"
#include "BLI_ghash.h"
#include "BLO_readfile.h"
+#include "BKE_appdir.h"
#include "BKE_autoexec.h"
#include "BKE_blender.h"
#include "BKE_brush.h"
#include "BKE_context.h"
#include "BKE_depsgraph.h"
+#include "BKE_icons.h"
#include "BKE_idprop.h"
#include "BKE_image.h"
#include "BKE_library.h"
+#include "BKE_library_query.h"
#include "BKE_global.h"
#include "BKE_main.h"
#include "BKE_material.h"
#include "BKE_report.h"
#include "BKE_scene.h"
#include "BKE_screen.h" /* BKE_ST_MAXNAME */
+#include "BKE_unit.h"
#include "BKE_utildefines.h"
#include "BKE_idcode.h"
-#include "BIF_gl.h"
#include "BIF_glutil.h" /* for paint cursor */
#include "BLF_api.h"
@@ -90,15 +97,19 @@
#include "IMB_imbuf_types.h"
#include "IMB_imbuf.h"
+#include "ED_numinput.h"
#include "ED_screen.h"
#include "ED_util.h"
#include "ED_view3d.h"
+#include "GPU_material.h"
+
#include "RNA_access.h"
#include "RNA_define.h"
#include "RNA_enum_types.h"
#include "UI_interface.h"
+#include "UI_interface_icons.h"
#include "UI_resources.h"
#include "WM_api.h"
@@ -147,9 +158,9 @@ wmOperatorType *WM_operatortype_find(const char *idname, bool quiet)
}
/* caller must free */
-GHashIterator *WM_operatortype_iter(void)
+void WM_operatortype_iter(GHashIterator *ghi)
{
- return BLI_ghashIterator_new(global_ops_hash);
+ BLI_ghashIterator_init(ghi, global_ops_hash);
}
/* all ops in 1 list (for time being... needs evaluation later) */
@@ -160,7 +171,8 @@ void WM_operatortype_append(void (*opfunc)(wmOperatorType *))
ot = MEM_callocN(sizeof(wmOperatorType), "operatortype");
ot->srna = RNA_def_struct_ptr(&BLENDER_RNA, "", &RNA_OperatorProperties);
/* Set the default i18n context now, so that opfunc can redefine it if needed! */
- RNA_def_struct_translation_context(ot->srna, BLF_I18NCONTEXT_OPERATOR_DEFAULT);
+ RNA_def_struct_translation_context(ot->srna, BLT_I18NCONTEXT_OPERATOR_DEFAULT);
+ ot->translation_context = BLT_I18NCONTEXT_OPERATOR_DEFAULT;
opfunc(ot);
if (ot->name == NULL) {
@@ -182,7 +194,8 @@ void WM_operatortype_append_ptr(void (*opfunc)(wmOperatorType *, void *), void *
ot = MEM_callocN(sizeof(wmOperatorType), "operatortype");
ot->srna = RNA_def_struct_ptr(&BLENDER_RNA, "", &RNA_OperatorProperties);
/* Set the default i18n context now, so that opfunc can redefine it if needed! */
- RNA_def_struct_translation_context(ot->srna, BLF_I18NCONTEXT_OPERATOR_DEFAULT);
+ RNA_def_struct_translation_context(ot->srna, BLT_I18NCONTEXT_OPERATOR_DEFAULT);
+ ot->translation_context = BLT_I18NCONTEXT_OPERATOR_DEFAULT;
opfunc(ot, userdata);
RNA_def_struct_ui_text(ot->srna, ot->name, ot->description ? ot->description : UNDOCUMENTED_OPERATOR_TIP);
RNA_def_struct_identifier(ot->srna, ot->idname);
@@ -328,7 +341,9 @@ static int wm_macro_modal(bContext *C, wmOperator *op, const wmEvent *event)
* */
if (op->opm->type->flag & OPTYPE_BLOCKING) {
int bounds[4] = {-1, -1, -1, -1};
- int wrap = (U.uiflag & USER_CONTINUOUS_MOUSE) && ((op->opm->flag & OP_GRAB_POINTER) || (op->opm->type->flag & OPTYPE_GRAB_POINTER));
+ const bool wrap = (
+ (U.uiflag & USER_CONTINUOUS_MOUSE) &&
+ ((op->opm->flag & OP_IS_MODAL_GRAB_CURSOR) || (op->opm->type->flag & OPTYPE_GRAB_CURSOR)));
if (wrap) {
ARegion *ar = CTX_wm_region(C);
@@ -363,6 +378,7 @@ static void wm_macro_cancel(bContext *C, wmOperator *op)
wmOperatorType *WM_operatortype_append_macro(const char *idname, const char *name, const char *description, int flag)
{
wmOperatorType *ot;
+ const char *i18n_context;
if (WM_operatortype_find(idname, true)) {
printf("%s: macro error: operator %s exists\n", __func__, idname);
@@ -389,8 +405,9 @@ wmOperatorType *WM_operatortype_append_macro(const char *idname, const char *nam
RNA_def_struct_ui_text(ot->srna, ot->name, ot->description);
RNA_def_struct_identifier(ot->srna, ot->idname);
/* Use i18n context from ext.srna if possible (py operators). */
- RNA_def_struct_translation_context(ot->srna, ot->ext.srna ? RNA_struct_translation_context(ot->ext.srna) :
- BLF_I18NCONTEXT_OPERATOR_DEFAULT);
+ i18n_context = ot->ext.srna ? RNA_struct_translation_context(ot->ext.srna) : BLT_I18NCONTEXT_OPERATOR_DEFAULT;
+ RNA_def_struct_translation_context(ot->srna, i18n_context);
+ ot->translation_context = i18n_context;
BLI_ghash_insert(global_ops_hash, (void *)ot->idname, ot);
@@ -415,7 +432,8 @@ void WM_operatortype_append_macro_ptr(void (*opfunc)(wmOperatorType *, void *),
ot->description = UNDOCUMENTED_OPERATOR_TIP;
/* Set the default i18n context now, so that opfunc can redefine it if needed! */
- RNA_def_struct_translation_context(ot->srna, BLF_I18NCONTEXT_OPERATOR_DEFAULT);
+ RNA_def_struct_translation_context(ot->srna, BLT_I18NCONTEXT_OPERATOR_DEFAULT);
+ ot->translation_context = BLT_I18NCONTEXT_OPERATOR_DEFAULT;
opfunc(ot, userdata);
RNA_def_struct_ui_text(ot->srna, ot->name, ot->description);
@@ -475,7 +493,7 @@ void WM_operatortype_remove_ptr(wmOperatorType *ot)
if (ot->macro.first)
wm_operatortype_free_macro(ot);
- BLI_ghash_remove(global_ops_hash, (void *)ot->idname, NULL, NULL);
+ BLI_ghash_remove(global_ops_hash, ot->idname, NULL, NULL);
WM_keyconfig_update_operatortype();
@@ -494,6 +512,27 @@ bool WM_operatortype_remove(const char *idname)
return true;
}
+/**
+ * Remove memory of all previously executed tools.
+ */
+void WM_operatortype_last_properties_clear_all(void)
+{
+ GHashIterator iter;
+
+ for (WM_operatortype_iter(&iter);
+ (!BLI_ghashIterator_done(&iter));
+ (BLI_ghashIterator_step(&iter)))
+ {
+ wmOperatorType *ot = BLI_ghashIterator_getValue(&iter);
+
+ if (ot->last_properties) {
+ IDP_FreeProperty(ot->last_properties);
+ MEM_freeN(ot->last_properties);
+ ot->last_properties = NULL;
+ }
+ }
+}
+
/* SOME_OT_op -> some.op */
void WM_operator_py_idname(char *to, const char *from)
{
@@ -504,7 +543,7 @@ void WM_operator_py_idname(char *to, const char *from)
/* note, we use ascii tolower instead of system tolower, because the
* latter depends on the locale, and can lead to idname mismatch */
memcpy(to, from, sizeof(char) * ofs);
- BLI_ascii_strtolower(to, ofs);
+ BLI_str_tolower_ascii(to, ofs);
to[ofs] = '.';
BLI_strncpy(to + (ofs + 1), sep + 4, OP_MAX_TYPENAME - (ofs + 1));
@@ -525,7 +564,7 @@ void WM_operator_bl_idname(char *to, const char *from)
int ofs = (sep - from);
memcpy(to, from, sizeof(char) * ofs);
- BLI_ascii_strtoupper(to, ofs);
+ BLI_str_toupper_ascii(to, ofs);
strcpy(to + ofs, "_OT_");
strcpy(to + (ofs + 4), sep + 1);
}
@@ -538,12 +577,13 @@ void WM_operator_bl_idname(char *to, const char *from)
to[0] = 0;
}
-/* Print a string representation of the operator, with the args that it runs so python can run it again.
+/**
+ * Print a string representation of the operator, with the args that it runs so python can run it again.
*
* When calling from an existing wmOperator, better to use simple version:
- * WM_operator_pystring(C, op);
+ * `WM_operator_pystring(C, op);`
*
- * Note: both op and opptr may be NULL (op is only used for macro operators).
+ * \note Both \a op and \a opptr may be `NULL` (\a op is only used for macro operators).
*/
char *WM_operator_pystring_ex(bContext *C, wmOperator *op, const bool all_args, const bool macro_args,
wmOperatorType *ot, PointerRNA *opptr)
@@ -1052,12 +1092,13 @@ int WM_menu_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
return retval;
}
else {
- pup = uiPupMenuBegin(C, RNA_struct_ui_name(op->type->srna), ICON_NONE);
- layout = uiPupMenuLayout(pup);
+ pup = UI_popup_menu_begin(C, RNA_struct_ui_name(op->type->srna), ICON_NONE);
+ layout = UI_popup_menu_layout(pup);
/* set this so the default execution context is the same as submenus */
uiLayoutSetOperatorContext(layout, WM_OP_INVOKE_REGION_WIN);
uiItemsFullEnumO(layout, op->type->idname, RNA_property_identifier(prop), op->ptr->data, WM_OP_EXEC_REGION_WIN, 0);
- uiPupMenuEnd(C, pup);
+ UI_popup_menu_end(C, pup);
+ return OPERATOR_INTERFACE;
}
return OPERATOR_CANCELLED;
@@ -1074,19 +1115,19 @@ static uiBlock *wm_enum_search_menu(bContext *C, ARegion *ar, void *arg_op)
uiBut *but;
wmOperator *op = (wmOperator *)arg_op;
- block = uiBeginBlock(C, ar, "_popup", UI_EMBOSS);
- uiBlockSetFlag(block, UI_BLOCK_LOOP | UI_BLOCK_MOVEMOUSE_QUIT | UI_BLOCK_SEARCH_MENU);
+ block = UI_block_begin(C, ar, "_popup", UI_EMBOSS);
+ UI_block_flag_enable(block, UI_BLOCK_LOOP | UI_BLOCK_MOVEMOUSE_QUIT | UI_BLOCK_SEARCH_MENU);
#if 0 /* ok, this isn't so easy... */
- uiDefBut(block, LABEL, 0, RNA_struct_ui_name(op->type->srna), 10, 10, uiSearchBoxWidth(), UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
+ uiDefBut(block, UI_BTYPE_LABEL, 0, RNA_struct_ui_name(op->type->srna), 10, 10, UI_searchbox_size_x(), UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
#endif
but = uiDefSearchButO_ptr(block, op->type, op->ptr->data, search, 0, ICON_VIEWZOOM, sizeof(search),
- 10, 10, uiSearchBoxWidth(), UI_UNIT_Y, 0, 0, "");
+ 10, 10, UI_searchbox_size_x(), UI_UNIT_Y, 0, 0, "");
/* fake button, it holds space for search items */
- uiDefBut(block, LABEL, 0, "", 10, 10 - uiSearchBoxHeight(), uiSearchBoxWidth(), uiSearchBoxHeight(), NULL, 0, 0, 0, 0, NULL);
+ uiDefBut(block, UI_BTYPE_LABEL, 0, "", 10, 10 - UI_searchbox_size_y(), UI_searchbox_size_x(), UI_searchbox_size_y(), NULL, 0, 0, 0, 0, NULL);
- uiPopupBoundsBlock(block, 6, 0, -UI_UNIT_Y); /* move it downwards, mouse over button */
+ UI_block_bounds_set_popup(block, 6, 0, -UI_UNIT_Y); /* move it downwards, mouse over button */
wm_event_init_from_window(win, &event);
event.type = EVT_BUT_OPEN;
@@ -1101,8 +1142,8 @@ static uiBlock *wm_enum_search_menu(bContext *C, ARegion *ar, void *arg_op)
int WM_enum_search_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- uiPupBlock(C, wm_enum_search_menu, op);
- return OPERATOR_CANCELLED;
+ UI_popup_block_invoke(C, wm_enum_search_menu, op);
+ return OPERATOR_INTERFACE;
}
/* Can't be used as an invoke directly, needs message arg (can be NULL) */
@@ -1119,12 +1160,12 @@ int WM_operator_confirm_message_ex(bContext *C, wmOperator *op,
else
properties = NULL;
- pup = uiPupMenuBegin(C, title, icon);
- layout = uiPupMenuLayout(pup);
+ pup = UI_popup_menu_begin(C, title, icon);
+ layout = UI_popup_menu_layout(pup);
uiItemFullO_ptr(layout, op->type, message, ICON_NONE, properties, WM_OP_EXEC_REGION_WIN, 0);
- uiPupMenuEnd(C, pup);
+ UI_popup_menu_end(C, pup);
- return OPERATOR_CANCELLED;
+ return OPERATOR_INTERFACE;
}
int WM_operator_confirm_message(bContext *C, wmOperator *op, const char *message)
@@ -1156,7 +1197,7 @@ bool WM_operator_filesel_ensure_ext_imtype(wmOperator *op, const struct ImageFor
/* dont NULL check prop, this can only run on ops with a 'filepath' */
prop = RNA_struct_find_property(op->ptr, "filepath");
RNA_property_string_get(op->ptr, prop, filepath);
- if (BKE_add_image_extension(filepath, im_format)) {
+ if (BKE_image_path_ensure_ext_from_imformat(filepath, im_format)) {
RNA_property_string_set(op->ptr, prop, filepath);
/* note, we could check for and update 'filename' here,
* but so far nothing needs this. */
@@ -1166,7 +1207,7 @@ bool WM_operator_filesel_ensure_ext_imtype(wmOperator *op, const struct ImageFor
}
/* default properties for fileselect */
-void WM_operator_properties_filesel(wmOperatorType *ot, int filter, short type, short action, short flag, short display)
+void WM_operator_properties_filesel(wmOperatorType *ot, int filter, short type, short action, short flag, short display, short sort)
{
PropertyRNA *prop;
@@ -1178,7 +1219,6 @@ void WM_operator_properties_filesel(wmOperatorType *ot, int filter, short type,
{0, NULL, 0, NULL, NULL}
};
-
if (flag & WM_FILESEL_FILEPATH)
RNA_def_string_file_path(ot->srna, "filepath", NULL, FILE_MAX, "File Path", "Path to file");
@@ -1194,31 +1234,34 @@ void WM_operator_properties_filesel(wmOperatorType *ot, int filter, short type,
if (action == FILE_SAVE) {
/* note, this is only used to check if we should highlight the filename area red when the
* filepath is an existing file. */
- prop = RNA_def_boolean(ot->srna, "check_existing", 1, "Check Existing", "Check and warn on overwriting existing files");
+ prop = RNA_def_boolean(ot->srna, "check_existing", true, "Check Existing",
+ "Check and warn on overwriting existing files");
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
}
- prop = RNA_def_boolean(ot->srna, "filter_blender", (filter & BLENDERFILE), "Filter .blend files", "");
+ prop = RNA_def_boolean(ot->srna, "filter_blender", (filter & FILE_TYPE_BLENDER) != 0, "Filter .blend files", "");
+ RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
+ prop = RNA_def_boolean(ot->srna, "filter_backup", (filter & FILE_TYPE_BLENDER_BACKUP) != 0, "Filter .blend files", "");
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
- prop = RNA_def_boolean(ot->srna, "filter_backup", (filter & BLENDERFILE_BACKUP), "Filter .blend files", "");
+ prop = RNA_def_boolean(ot->srna, "filter_image", (filter & FILE_TYPE_IMAGE) != 0, "Filter image files", "");
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
- prop = RNA_def_boolean(ot->srna, "filter_image", (filter & IMAGEFILE), "Filter image files", "");
+ prop = RNA_def_boolean(ot->srna, "filter_movie", (filter & FILE_TYPE_MOVIE) != 0, "Filter movie files", "");
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
- prop = RNA_def_boolean(ot->srna, "filter_movie", (filter & MOVIEFILE), "Filter movie files", "");
+ prop = RNA_def_boolean(ot->srna, "filter_python", (filter & FILE_TYPE_PYSCRIPT) != 0, "Filter python files", "");
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
- prop = RNA_def_boolean(ot->srna, "filter_python", (filter & PYSCRIPTFILE), "Filter python files", "");
+ prop = RNA_def_boolean(ot->srna, "filter_font", (filter & FILE_TYPE_FTFONT) != 0, "Filter font files", "");
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
- prop = RNA_def_boolean(ot->srna, "filter_font", (filter & FTFONTFILE), "Filter font files", "");
+ prop = RNA_def_boolean(ot->srna, "filter_sound", (filter & FILE_TYPE_SOUND) != 0, "Filter sound files", "");
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
- prop = RNA_def_boolean(ot->srna, "filter_sound", (filter & SOUNDFILE), "Filter sound files", "");
+ prop = RNA_def_boolean(ot->srna, "filter_text", (filter & FILE_TYPE_TEXT) != 0, "Filter text files", "");
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
- prop = RNA_def_boolean(ot->srna, "filter_text", (filter & TEXTFILE), "Filter text files", "");
+ prop = RNA_def_boolean(ot->srna, "filter_btx", (filter & FILE_TYPE_BTX) != 0, "Filter btx files", "");
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
- prop = RNA_def_boolean(ot->srna, "filter_btx", (filter & BTXFILE), "Filter btx files", "");
+ prop = RNA_def_boolean(ot->srna, "filter_collada", (filter & FILE_TYPE_COLLADA) != 0, "Filter COLLADA files", "");
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
- prop = RNA_def_boolean(ot->srna, "filter_collada", (filter & COLLADAFILE), "Filter COLLADA files", "");
+ prop = RNA_def_boolean(ot->srna, "filter_folder", (filter & FILE_TYPE_FOLDER) != 0, "Filter folders", "");
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
- prop = RNA_def_boolean(ot->srna, "filter_folder", (filter & FOLDERFILE), "Filter folders", "");
+ prop = RNA_def_boolean(ot->srna, "filter_blenlib", (filter & FILE_TYPE_BLENDERLIB) != 0, "Filter Blender IDs", "");
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
prop = RNA_def_int(ot->srna, "filemode", type, FILE_LOADLIB, FILE_SPECIAL,
@@ -1229,8 +1272,19 @@ void WM_operator_properties_filesel(wmOperatorType *ot, int filter, short type,
if (flag & WM_FILESEL_RELPATH)
RNA_def_boolean(ot->srna, "relative_path", true, "Relative Path", "Select the file relative to the blend file");
+ if ((filter & FILE_TYPE_IMAGE) || (filter & FILE_TYPE_MOVIE)) {
+ prop = RNA_def_boolean(ot->srna, "show_multiview", 0, "Enable Multi-View", "");
+ RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
+ prop = RNA_def_boolean(ot->srna, "use_multiview", 0, "Use Multi-View", "");
+ RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
+ }
+
prop = RNA_def_enum(ot->srna, "display_type", file_display_items, display, "Display Type", "");
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
+
+ prop = RNA_def_enum(ot->srna, "sort_method", file_sort_items, sort, "File sorting mode", "");
+ RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
+
}
static void wm_operator_properties_select_action_ex(wmOperatorType *ot, int default_action,
@@ -1307,7 +1361,7 @@ void WM_operator_properties_gesture_border(wmOperatorType *ot, bool extend)
WM_operator_properties_border(ot);
if (extend) {
- RNA_def_boolean(ot->srna, "extend", 1, "Extend", "Extend selection instead of deselecting everything first");
+ RNA_def_boolean(ot->srna, "extend", true, "Extend", "Extend selection instead of deselecting everything first");
}
}
@@ -1315,11 +1369,12 @@ void WM_operator_properties_mouse_select(wmOperatorType *ot)
{
PropertyRNA *prop;
- prop = RNA_def_boolean(ot->srna, "extend", 0, "Extend", "Extend selection instead of deselecting everything first");
+ prop = RNA_def_boolean(ot->srna, "extend", false, "Extend",
+ "Extend selection instead of deselecting everything first");
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
- prop = RNA_def_boolean(ot->srna, "deselect", 0, "Deselect", "Remove from selection");
+ prop = RNA_def_boolean(ot->srna, "deselect", false, "Deselect", "Remove from selection");
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
- prop = RNA_def_boolean(ot->srna, "toggle", 0, "Toggle Selection", "Toggle the selection");
+ prop = RNA_def_boolean(ot->srna, "toggle", false, "Toggle Selection", "Toggle the selection");
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
@@ -1357,7 +1412,7 @@ bool WM_operator_check_ui_enabled(const bContext *C, const char *idname)
wmWindowManager *wm = CTX_wm_manager(C);
Scene *scene = CTX_data_scene(C);
- return !(ED_undo_valid(C, idname) == 0 || WM_jobs_test(wm, scene, WM_JOB_TYPE_ANY));
+ return !((ED_undo_is_valid(C, idname) == false) || WM_jobs_test(wm, scene, WM_JOB_TYPE_ANY));
}
wmOperator *WM_operator_last_redo(const bContext *C)
@@ -1373,6 +1428,64 @@ wmOperator *WM_operator_last_redo(const bContext *C)
return op;
}
+/**
+ * Use for drag & drop a path or name with operators invoke() function.
+ */
+ID *WM_operator_drop_load_path(struct bContext *C, wmOperator *op, const short idcode)
+{
+ ID *id = NULL;
+ /* check input variables */
+ if (RNA_struct_property_is_set(op->ptr, "filepath")) {
+ const bool is_relative_path = RNA_boolean_get(op->ptr, "relative_path");
+ char path[FILE_MAX];
+ bool exists = false;
+
+ RNA_string_get(op->ptr, "filepath", path);
+
+ errno = 0;
+
+ if (idcode == ID_IM) {
+ id = (ID *)BKE_image_load_exists_ex(path, &exists);
+ }
+ else {
+ BLI_assert(0);
+ }
+
+ if (!id) {
+ BKE_reportf(op->reports, RPT_ERROR, "Cannot read %s '%s': %s",
+ BKE_idcode_to_name(idcode), path,
+ errno ? strerror(errno) : TIP_("unsupported format"));
+ return NULL;
+ }
+
+ if (is_relative_path ) {
+ if (exists == false) {
+ Main *bmain = CTX_data_main(C);
+
+ if (idcode == ID_IM) {
+ BLI_path_rel(((Image *)id)->name, bmain->name);
+ }
+ else {
+ BLI_assert(0);
+ }
+ }
+ }
+ }
+ else if (RNA_struct_property_is_set(op->ptr, "name")) {
+ char name[MAX_ID_NAME - 2];
+ RNA_string_get(op->ptr, "name", name);
+ id = BKE_libblock_find_name(idcode, name);
+ if (!id) {
+ BKE_reportf(op->reports, RPT_ERROR, "%s '%s' not found",
+ BKE_idcode_to_name(idcode), name);
+ return NULL;
+ }
+ id_us_plus(id);
+ }
+
+ return id;
+}
+
static void wm_block_redo_cb(bContext *C, void *arg_op, int UNUSED(arg_event))
{
wmOperator *op = arg_op;
@@ -1404,19 +1517,20 @@ static uiBlock *wm_block_create_redo(bContext *C, ARegion *ar, void *arg_op)
wmOperator *op = arg_op;
uiBlock *block;
uiLayout *layout;
- uiStyle *style = UI_GetStyle();
+ uiStyle *style = UI_style_get();
int width = 15 * UI_UNIT_X;
- block = uiBeginBlock(C, ar, __func__, UI_EMBOSS);
- uiBlockClearFlag(block, UI_BLOCK_LOOP);
- uiBlockSetFlag(block, UI_BLOCK_KEEP_OPEN | UI_BLOCK_MOVEMOUSE_QUIT);
+ block = UI_block_begin(C, ar, __func__, UI_EMBOSS);
+ UI_block_flag_disable(block, UI_BLOCK_LOOP);
+ /* UI_BLOCK_NUMSELECT for layer buttons */
+ UI_block_flag_enable(block, UI_BLOCK_NUMSELECT | UI_BLOCK_KEEP_OPEN | UI_BLOCK_MOVEMOUSE_QUIT);
/* if register is not enabled, the operator gets freed on OPERATOR_FINISHED
* ui_apply_but_funcs_after calls ED_undo_operator_repeate_cb and crashes */
assert(op->type->flag & OPTYPE_REGISTER);
- uiBlockSetHandleFunc(block, wm_block_redo_cb, arg_op);
- layout = uiBlockLayout(block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, 0, 0, width, UI_UNIT_Y, 0, style);
+ UI_block_func_handle_set(block, wm_block_redo_cb, arg_op);
+ layout = UI_block_layout(block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, 0, 0, width, UI_UNIT_Y, 0, style);
if (op == WM_operator_last_redo(C))
if (!WM_operator_check_ui_enabled(C, op->type->name))
@@ -1431,7 +1545,7 @@ static uiBlock *wm_block_create_redo(bContext *C, ARegion *ar, void *arg_op)
uiLayoutOperatorButs(C, layout, op, NULL, 'H', UI_LAYOUT_OP_SHOW_TITLE);
}
- uiPopupBoundsBlock(block, 4, 0, 0);
+ UI_block_bounds_set_popup(block, 4, 0, 0);
return block;
}
@@ -1446,6 +1560,9 @@ typedef struct wmOpPopUp {
/* Only invoked by OK button in popups created with wm_block_dialog_create() */
static void dialog_exec_cb(bContext *C, void *arg1, void *arg2)
{
+ wmWindowManager *wm = CTX_wm_manager(C);
+ wmWindow *win = CTX_wm_window(C);
+
wmOpPopUp *data = arg1;
uiBlock *block = arg2;
@@ -1458,7 +1575,11 @@ static void dialog_exec_cb(bContext *C, void *arg1, void *arg2)
/* in this case, wm_operator_ui_popup_cancel wont run */
MEM_freeN(data);
- uiPupBlockClose(C, block);
+ /* check window before 'block->handle' incase the
+ * popup execution closed the window and freed the block. see T44688. */
+ if (BLI_findindex(&wm->windows, win) != -1) {
+ UI_popup_block_close(C, win, block);
+ }
}
static void dialog_check_cb(bContext *C, void *op_ptr, void *UNUSED(arg))
@@ -1482,23 +1603,23 @@ static uiBlock *wm_block_dialog_create(bContext *C, ARegion *ar, void *userData)
wmOperator *op = data->op;
uiBlock *block;
uiLayout *layout;
- uiStyle *style = UI_GetStyle();
+ uiStyle *style = UI_style_get();
- block = uiBeginBlock(C, ar, __func__, UI_EMBOSS);
- uiBlockClearFlag(block, UI_BLOCK_LOOP);
+ block = UI_block_begin(C, ar, __func__, UI_EMBOSS);
+ UI_block_flag_disable(block, UI_BLOCK_LOOP);
/* intentionally don't use 'UI_BLOCK_MOVEMOUSE_QUIT', some dialogues have many items
* where quitting by accident is very annoying */
- uiBlockSetFlag(block, UI_BLOCK_KEEP_OPEN);
+ UI_block_flag_enable(block, UI_BLOCK_KEEP_OPEN | UI_BLOCK_NUMSELECT);
- layout = uiBlockLayout(block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, 0, 0, data->width, data->height, 0, style);
+ layout = UI_block_layout(block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, 0, 0, data->width, data->height, 0, style);
- uiBlockSetFunc(block, dialog_check_cb, op, NULL);
+ UI_block_func_set(block, dialog_check_cb, op, NULL);
uiLayoutOperatorButs(C, layout, op, NULL, 'H', UI_LAYOUT_OP_SHOW_TITLE);
/* clear so the OK button is left alone */
- uiBlockSetFunc(block, NULL, NULL, NULL);
+ UI_block_func_set(block, NULL, NULL, NULL);
/* new column so as not to interfere with custom layouts [#26436] */
{
@@ -1509,12 +1630,12 @@ static uiBlock *wm_block_dialog_create(bContext *C, ARegion *ar, void *userData)
col = uiLayoutColumn(layout, false);
col_block = uiLayoutGetBlock(col);
/* Create OK button, the callback of which will execute op */
- btn = uiDefBut(col_block, BUT, 0, IFACE_("OK"), 0, -30, 0, UI_UNIT_Y, NULL, 0, 0, 0, 0, "");
- uiButSetFunc(btn, dialog_exec_cb, data, col_block);
+ btn = uiDefBut(col_block, UI_BTYPE_BUT, 0, IFACE_("OK"), 0, -30, 0, UI_UNIT_Y, NULL, 0, 0, 0, 0, "");
+ UI_but_func_set(btn, dialog_exec_cb, data, col_block);
}
/* center around the mouse */
- uiPopupBoundsBlock(block, 4, data->width / -2, data->height / 2);
+ UI_block_bounds_set_popup(block, 4, data->width / -2, data->height / 2);
return block;
}
@@ -1525,18 +1646,18 @@ static uiBlock *wm_operator_ui_create(bContext *C, ARegion *ar, void *userData)
wmOperator *op = data->op;
uiBlock *block;
uiLayout *layout;
- uiStyle *style = UI_GetStyle();
+ uiStyle *style = UI_style_get();
- block = uiBeginBlock(C, ar, __func__, UI_EMBOSS);
- uiBlockClearFlag(block, UI_BLOCK_LOOP);
- uiBlockSetFlag(block, UI_BLOCK_KEEP_OPEN | UI_BLOCK_MOVEMOUSE_QUIT);
+ block = UI_block_begin(C, ar, __func__, UI_EMBOSS);
+ UI_block_flag_disable(block, UI_BLOCK_LOOP);
+ UI_block_flag_enable(block, UI_BLOCK_KEEP_OPEN | UI_BLOCK_MOVEMOUSE_QUIT);
- layout = uiBlockLayout(block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, 0, 0, data->width, data->height, 0, style);
+ layout = UI_block_layout(block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, 0, 0, data->width, data->height, 0, style);
/* since ui is defined the auto-layout args are not used */
uiLayoutOperatorButs(C, layout, op, NULL, 'V', 0);
- uiPopupBoundsBlock(block, 4, 0, 0);
+ UI_block_bounds_set_popup(block, 4, 0, 0);
return block;
}
@@ -1577,14 +1698,14 @@ int WM_operator_ui_popup(bContext *C, wmOperator *op, int width, int height)
data->width = width;
data->height = height;
data->free_op = true; /* if this runs and gets registered we may want not to free it */
- uiPupBlockEx(C, wm_operator_ui_create, NULL, wm_operator_ui_popup_cancel, data);
+ UI_popup_block_ex(C, wm_operator_ui_create, NULL, wm_operator_ui_popup_cancel, data);
return OPERATOR_RUNNING_MODAL;
}
/**
* For use by #WM_operator_props_popup_call, #WM_operator_props_popup only.
*
- * \note operator menu needs undo flag enabled , for redo callback */
+ * \note operator menu needs undo flag enabled, for redo callback */
static int wm_operator_props_popup_ex(bContext *C, wmOperator *op,
const bool do_call, const bool do_redo)
{
@@ -1607,7 +1728,7 @@ static int wm_operator_props_popup_ex(bContext *C, wmOperator *op,
if (!do_redo || !(U.uiflag & USER_GLOBALUNDO))
return WM_operator_props_dialog_popup(C, op, 15 * UI_UNIT_X, UI_UNIT_Y);
- uiPupBlockEx(C, wm_block_create_redo, NULL, wm_block_redo_cancel_cb, op);
+ UI_popup_block_ex(C, wm_block_create_redo, NULL, wm_block_redo_cancel_cb, op);
if (do_call)
wm_block_redo_cb(C, op, 0);
@@ -1615,18 +1736,20 @@ static int wm_operator_props_popup_ex(bContext *C, wmOperator *op,
return OPERATOR_RUNNING_MODAL;
}
-/* Same as WM_operator_props_popup but don't use operator redo.
- * just wraps WM_operator_props_dialog_popup.
+/**
+ * Same as #WM_operator_props_popup but don't use operator redo.
+ * just wraps #WM_operator_props_dialog_popup.
*/
int WM_operator_props_popup_confirm(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
return wm_operator_props_popup_ex(C, op, false, false);
}
-/* Same as WM_operator_props_popup but call the operator first,
+/**
+ * Same as #WM_operator_props_popup but call the operator first,
* This way - the button values correspond to the result of the operator.
- * Without this, first access to a button will make the result jump,
- * see [#32452] */
+ * Without this, first access to a button will make the result jump, see T32452.
+ */
int WM_operator_props_popup_call(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
return wm_operator_props_popup_ex(C, op, true, true);
@@ -1647,7 +1770,7 @@ int WM_operator_props_dialog_popup(bContext *C, wmOperator *op, int width, int h
data->free_op = true; /* if this runs and gets registered we may want not to free it */
/* op is not executed until popup OK but is clicked */
- uiPupBlockEx(C, wm_block_dialog_create, wm_operator_ui_popup_ok, wm_operator_ui_popup_cancel, data);
+ UI_popup_block_ex(C, wm_block_dialog_create, wm_operator_ui_popup_ok, wm_operator_ui_popup_cancel, data);
return OPERATOR_RUNNING_MODAL;
}
@@ -1665,7 +1788,7 @@ int WM_operator_redo_popup(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
- uiPupBlock(C, wm_block_create_redo, op);
+ UI_popup_block_invoke(C, wm_block_create_redo, op);
return OPERATOR_CANCELLED;
}
@@ -1730,34 +1853,29 @@ static void WM_OT_operator_defaults(wmOperatorType *ot)
static void wm_block_splash_close(bContext *C, void *arg_block, void *UNUSED(arg))
{
- uiPupBlockClose(C, arg_block);
+ wmWindow *win = CTX_wm_window(C);
+ UI_popup_block_close(C, win, arg_block);
}
static uiBlock *wm_block_create_splash(bContext *C, ARegion *ar, void *arg_unused);
-/* XXX: hack to refresh splash screen with updated preset menu name,
- * since popup blocks don't get regenerated like panels do */
-static void wm_block_splash_refreshmenu(bContext *UNUSED(C), void *UNUSED(arg_block), void *UNUSED(arg))
+static void wm_block_splash_refreshmenu(bContext *C, void *UNUSED(arg_block), void *UNUSED(arg))
{
- /* ugh, causes crashes in other buttons, disabling for now until
- * a better fix */
-#if 0
- uiPupBlockClose(C, arg_block);
- uiPupBlock(C, wm_block_create_splash, NULL);
-#endif
+ ARegion *ar_menu = CTX_wm_menu(C);
+ ED_region_tag_refresh_ui(ar_menu);
}
static int wm_resource_check_prev(void)
{
- const char *res = BLI_get_folder_version(BLENDER_RESOURCE_PATH_USER, BLENDER_VERSION, true);
+ const char *res = BKE_appdir_folder_id_version(BLENDER_RESOURCE_PATH_USER, BLENDER_VERSION, true);
// if (res) printf("USER: %s\n", res);
#if 0 /* ignore the local folder */
if (res == NULL) {
/* with a local dir, copying old files isn't useful since local dir get priority for config */
- res = BLI_get_folder_version(BLENDER_RESOURCE_PATH_LOCAL, BLENDER_VERSION, true);
+ res = BKE_appdir_folder_id_version(BLENDER_RESOURCE_PATH_LOCAL, BLENDER_VERSION, true);
}
#endif
@@ -1766,7 +1884,7 @@ static int wm_resource_check_prev(void)
return false;
}
else {
- return (BLI_get_folder_version(BLENDER_RESOURCE_PATH_USER, BLENDER_VERSION - 1, true) != NULL);
+ return (BKE_appdir_folder_id_version(BLENDER_RESOURCE_PATH_USER, BLENDER_VERSION - 1, true) != NULL);
}
}
@@ -1775,7 +1893,7 @@ static uiBlock *wm_block_create_splash(bContext *C, ARegion *ar, void *UNUSED(ar
uiBlock *block;
uiBut *but;
uiLayout *layout, *split, *col;
- uiStyle *style = UI_GetStyle();
+ uiStyle *style = UI_style_get();
const struct RecentFile *recent;
int i;
MenuType *mt = WM_menutype_find("USERPREF_MT_splash", true);
@@ -1821,17 +1939,17 @@ static uiBlock *wm_block_create_splash(bContext *C, ARegion *ar, void *UNUSED(ar
}
#endif
- block = uiBeginBlock(C, ar, "_popup", UI_EMBOSS);
+ block = UI_block_begin(C, ar, "_popup", UI_EMBOSS);
/* note on UI_BLOCK_NO_WIN_CLIP, the window size is not always synchronized
* with the OS when the splash shows, window clipping in this case gives
* ugly results and clipping the splash isn't useful anyway, just disable it [#32938] */
- uiBlockSetFlag(block, UI_BLOCK_KEEP_OPEN | UI_BLOCK_NO_WIN_CLIP);
+ UI_block_flag_enable(block, UI_BLOCK_LOOP | UI_BLOCK_KEEP_OPEN | UI_BLOCK_NO_WIN_CLIP);
/* XXX splash scales with pixelsize, should become widget-units */
- but = uiDefBut(block, BUT_IMAGE, 0, "", 0, 0.5f * U.widget_unit, U.pixelsize * 501, U.pixelsize * 282, ibuf, 0.0, 0.0, 0, 0, ""); /* button owns the imbuf now */
- uiButSetFunc(but, wm_block_splash_close, block, NULL);
- uiBlockSetFunc(block, wm_block_splash_refreshmenu, block, NULL);
+ but = uiDefBut(block, UI_BTYPE_IMAGE, 0, "", 0, 0.5f * U.widget_unit, U.pixelsize * 501, U.pixelsize * 282, ibuf, 0.0, 0.0, 0, 0, ""); /* button owns the imbuf now */
+ UI_but_func_set(but, wm_block_splash_close, block, NULL);
+ UI_block_func_set(block, wm_block_splash_refreshmenu, block, NULL);
/* label for 'a' bugfix releases, or 'Release Candidate 1'...
* avoids recreating splash for version updates */
@@ -1849,32 +1967,32 @@ static uiBlock *wm_block_create_splash(bContext *C, ARegion *ar, void *UNUSED(ar
int w = 240;
/* hack to have text draw 'text_sel' */
- uiBlockSetEmboss(block, UI_EMBOSSN);
- but = uiDefBut(block, LABEL, 0, version_suffix, x * U.pixelsize, y * U.pixelsize, w * U.pixelsize, UI_UNIT_Y, NULL, 0, 0, 0, 0, NULL);
+ UI_block_emboss_set(block, UI_EMBOSS_NONE);
+ but = uiDefBut(block, UI_BTYPE_LABEL, 0, version_suffix, x * U.pixelsize, y * U.pixelsize, w * U.pixelsize, UI_UNIT_Y, NULL, 0, 0, 0, 0, NULL);
/* XXX, set internal flag - UI_SELECT */
- uiButSetFlag(but, 1);
- uiBlockSetEmboss(block, UI_EMBOSS);
+ UI_but_flag_enable(but, 1);
+ UI_block_emboss_set(block, UI_EMBOSS);
}
#ifdef WITH_BUILDINFO
if (build_commit_timestamp != 0) {
- uiDefBut(block, LABEL, 0, date_buf, U.pixelsize * 494 - date_width, U.pixelsize * 270, date_width, UI_UNIT_Y, NULL, 0, 0, 0, 0, NULL);
+ uiDefBut(block, UI_BTYPE_LABEL, 0, date_buf, U.pixelsize * 494 - date_width, U.pixelsize * 270, date_width, UI_UNIT_Y, NULL, 0, 0, 0, 0, NULL);
label_delta = 12;
}
- uiDefBut(block, LABEL, 0, hash_buf, U.pixelsize * 494 - hash_width, U.pixelsize * (270 - label_delta), hash_width, UI_UNIT_Y, NULL, 0, 0, 0, 0, NULL);
+ uiDefBut(block, UI_BTYPE_LABEL, 0, hash_buf, U.pixelsize * 494 - hash_width, U.pixelsize * (270 - label_delta), hash_width, UI_UNIT_Y, NULL, 0, 0, 0, 0, NULL);
if (!STREQ(build_branch, "master")) {
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, sizeof(branch_buf)) + 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);
+ uiDefBut(block, UI_BTYPE_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 */
- layout = uiBlockLayout(block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, 10, 2, U.pixelsize * 480, U.pixelsize * 110, 0, style);
+ layout = UI_block_layout(block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, 10, 2, U.pixelsize * 480, U.pixelsize * 110, 0, style);
- uiBlockSetEmboss(block, UI_EMBOSS);
+ UI_block_emboss_set(block, UI_EMBOSS);
/* show the splash menu (containing interaction presets), using python */
if (mt) {
Menu menu = {NULL};
@@ -1886,14 +2004,16 @@ static uiBlock *wm_block_create_splash(bContext *C, ARegion *ar, void *UNUSED(ar
// uiItemM(layout, C, "USERPREF_MT_keyconfigs", U.keyconfigstr, ICON_NONE);
}
- uiBlockSetEmboss(block, UI_EMBOSSP);
+ UI_block_emboss_set(block, UI_EMBOSS_PULLDOWN);
uiLayoutSetOperatorContext(layout, WM_OP_EXEC_REGION_WIN);
split = uiLayoutSplit(layout, 0.0f, false);
col = uiLayoutColumn(split, false);
uiItemL(col, IFACE_("Links"), ICON_NONE);
+#if 0
uiItemStringO(col, IFACE_("Support an Open Animation Movie"), ICON_URL, "WM_OT_url_open", "url",
- "http://cloud.blender.org/gooseberry");
+ "https://cloud.blender.org/join");
+#endif
uiItemStringO(col, IFACE_("Donations"), ICON_URL, "WM_OT_url_open", "url",
"http://www.blender.org/foundation/donation-payment/");
uiItemStringO(col, IFACE_("Credits"), ICON_URL, "WM_OT_url_open", "url",
@@ -1902,7 +2022,7 @@ static uiBlock *wm_block_create_splash(bContext *C, ARegion *ar, void *UNUSED(ar
BLENDER_VERSION / 100, BLENDER_VERSION % 100);
uiItemStringO(col, IFACE_("Release Log"), ICON_URL, "WM_OT_url_open", "url", url);
uiItemStringO(col, IFACE_("Manual"), ICON_URL, "WM_OT_url_open", "url",
- "http://wiki.blender.org/index.php/Doc:2.6/Manual");
+ "http://www.blender.org/manual");
uiItemStringO(col, IFACE_("Blender Website"), ICON_URL, "WM_OT_url_open", "url", "http://www.blender.org");
if (STREQ(STRINGIFY(BLENDER_VERSION_CYCLE), "release")) {
BLI_snprintf(url, sizeof(url), "http://www.blender.org/documentation/blender_python_api_%d_%d"
@@ -1935,14 +2055,22 @@ static uiBlock *wm_block_create_splash(bContext *C, ARegion *ar, void *UNUSED(ar
uiItemO(col, NULL, ICON_RECOVER_LAST, "WM_OT_recover_last_session");
uiItemL(col, "", ICON_NONE);
- uiCenteredBoundsBlock(block, 0);
+ mt = WM_menutype_find("USERPREF_MT_splash_footer", false);
+ if (mt) {
+ Menu menu = {NULL};
+ menu.layout = uiLayoutColumn(layout, false);
+ menu.type = mt;
+ mt->draw(C, &menu);
+ }
+
+ UI_block_bounds_set_centered(block, 0);
return block;
}
static int wm_splash_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *UNUSED(event))
{
- uiPupBlock(C, wm_block_create_splash, NULL);
+ UI_popup_block_invoke(C, wm_block_create_splash, NULL);
return OPERATOR_FINISHED;
}
@@ -1967,16 +2095,16 @@ static uiBlock *wm_block_search_menu(bContext *C, ARegion *ar, void *UNUSED(arg_
uiBlock *block;
uiBut *but;
- block = uiBeginBlock(C, ar, "_popup", UI_EMBOSS);
- uiBlockSetFlag(block, UI_BLOCK_LOOP | UI_BLOCK_MOVEMOUSE_QUIT | UI_BLOCK_SEARCH_MENU);
+ block = UI_block_begin(C, ar, "_popup", UI_EMBOSS);
+ UI_block_flag_enable(block, UI_BLOCK_LOOP | UI_BLOCK_MOVEMOUSE_QUIT | UI_BLOCK_SEARCH_MENU);
- but = uiDefSearchBut(block, search, 0, ICON_VIEWZOOM, sizeof(search), 10, 10, uiSearchBoxWidth(), UI_UNIT_Y, 0, 0, "");
- uiOperatorSearch_But(but);
+ but = uiDefSearchBut(block, search, 0, ICON_VIEWZOOM, sizeof(search), 10, 10, UI_searchbox_size_x(), UI_UNIT_Y, 0, 0, "");
+ UI_but_func_operator_search(but);
/* fake button, it holds space for search items */
- uiDefBut(block, LABEL, 0, "", 10, 10 - uiSearchBoxHeight(), uiSearchBoxWidth(), uiSearchBoxHeight(), NULL, 0, 0, 0, 0, NULL);
+ uiDefBut(block, UI_BTYPE_LABEL, 0, "", 10, 10 - UI_searchbox_size_y(), UI_searchbox_size_x(), UI_searchbox_size_y(), NULL, 0, 0, 0, 0, NULL);
- uiPopupBoundsBlock(block, 6, 0, -UI_UNIT_Y); /* move it downwards, mouse over button */
+ UI_block_bounds_set_popup(block, 6, 0, -UI_UNIT_Y); /* move it downwards, mouse over button */
wm_event_init_from_window(win, &event);
event.type = EVT_BUT_OPEN;
@@ -1995,9 +2123,9 @@ static int wm_search_menu_exec(bContext *UNUSED(C), wmOperator *UNUSED(op))
static int wm_search_menu_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- uiPupBlock(C, wm_block_search_menu, op);
+ UI_popup_block_invoke(C, wm_block_search_menu, op);
- return OPERATOR_CANCELLED;
+ return OPERATOR_INTERFACE;
}
/* op->poll */
@@ -2036,9 +2164,7 @@ static int wm_call_menu_exec(bContext *C, wmOperator *op)
char idname[BKE_ST_MAXNAME];
RNA_string_get(op->ptr, "name", idname);
- uiPupMenuInvoke(C, idname, op->reports);
-
- return OPERATOR_CANCELLED;
+ return UI_popup_menu_invoke(C, idname, op->reports);
}
static void WM_OT_call_menu(wmOperatorType *ot)
@@ -2060,9 +2186,7 @@ static int wm_call_pie_menu_invoke(bContext *C, wmOperator *op, const wmEvent *e
char idname[BKE_ST_MAXNAME];
RNA_string_get(op->ptr, "name", idname);
- uiPieMenuInvoke(C, idname, event);
-
- return OPERATOR_CANCELLED;
+ return UI_pie_menu_invoke(C, idname, event);
}
static int wm_call_pie_menu_exec(bContext *C, wmOperator *op)
@@ -2070,9 +2194,7 @@ static int wm_call_pie_menu_exec(bContext *C, wmOperator *op)
char idname[BKE_ST_MAXNAME];
RNA_string_get(op->ptr, "name", idname);
- uiPieMenuInvoke(C, idname, CTX_wm_window(C)->eventstate);
-
- return OPERATOR_CANCELLED;
+ return UI_pie_menu_invoke(C, idname, CTX_wm_window(C)->eventstate);
}
static void WM_OT_call_menu_pie(wmOperatorType *ot)
@@ -2098,7 +2220,7 @@ static int wm_operator_winactive_normal(bContext *C)
{
wmWindow *win = CTX_wm_window(C);
- if (win == NULL || win->screen == NULL || win->screen->full != SCREENNORMAL)
+ if (win == NULL || win->screen == NULL || win->screen->state != SCREENNORMAL)
return 0;
return 1;
@@ -2182,7 +2304,7 @@ static void WM_OT_read_history(wmOperatorType *ot)
ot->description = "Reloads history and bookmarks";
ot->invoke = WM_operator_confirm;
- ot->exec = wm_history_read_exec;
+ ot->exec = wm_history_file_read_exec;
/* this operator is only used for loading settings from a previous blender install */
ot->flag = OPTYPE_INTERNAL;
@@ -2208,7 +2330,7 @@ static void WM_OT_read_homefile(wmOperatorType *ot)
"Load user interface setup from the .blend file");
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
- /* ommit poll to run in background mode */
+ /* omit poll to run in background mode */
}
static void WM_OT_read_factory_settings(wmOperatorType *ot)
@@ -2219,7 +2341,7 @@ static void WM_OT_read_factory_settings(wmOperatorType *ot)
ot->invoke = WM_operator_confirm;
ot->exec = wm_homefile_read_exec;
- /* ommit poll to run in background mode */
+ /* omit poll to run in background mode */
}
/* *************** open file **************** */
@@ -2345,18 +2467,18 @@ static void wm_open_mainfile_ui(bContext *UNUSED(C), wmOperator *op)
struct FileRuntime *file_info = (struct FileRuntime *)&op->customdata;
uiLayout *layout = op->layout;
uiLayout *col = op->layout;
- const char *autoexec_text = NULL;
+ const char *autoexec_text;
uiItemR(layout, op->ptr, "load_ui", 0, NULL, ICON_NONE);
col = uiLayoutColumn(layout, false);
if (file_info->is_untrusted) {
- autoexec_text = "Trusted Source [Untrusted Path]";
+ autoexec_text = IFACE_("Trusted Source [Untrusted Path]");
uiLayoutSetActive(col, false);
uiLayoutSetEnabled(col, false);
}
else {
- autoexec_text = "Trusted Source";
+ autoexec_text = IFACE_("Trusted Source");
}
uiItemR(col, op->ptr, "use_scripts", 0, autoexec_text, ICON_NONE);
@@ -2372,10 +2494,10 @@ static void WM_OT_open_mainfile(wmOperatorType *ot)
ot->exec = wm_open_mainfile_exec;
ot->check = wm_open_mainfile_check;
ot->ui = wm_open_mainfile_ui;
- /* ommit window poll so this can work in background mode */
+ /* omit window poll so this can work in background mode */
- WM_operator_properties_filesel(ot, FOLDERFILE | BLENDERFILE, FILE_BLENDER, FILE_OPENFILE,
- WM_FILESEL_FILEPATH, FILE_DEFAULTDISPLAY);
+ WM_operator_properties_filesel(ot, FILE_TYPE_FOLDER | FILE_TYPE_BLENDER, FILE_BLENDER, FILE_OPENFILE,
+ WM_FILESEL_FILEPATH, FILE_DEFAULTDISPLAY, FILE_SORT_ALPHA);
RNA_def_boolean(ot->srna, "load_ui", true, "Load UI", "Load user interface setup in the .blend file");
RNA_def_boolean(ot->srna, "use_scripts", true, "Trusted Source",
@@ -2477,27 +2599,121 @@ static short wm_link_append_flag(wmOperator *op)
return flag;
}
-static int wm_link_append_exec(bContext *C, wmOperator *op)
+/* Helper.
+ * if `name` is non-NULL, we assume a single-item link/append.
+ * else if `*todo_libraries` is NULL we assume first-run.
+ */
+static void wm_link_append_do_libgroup(
+ bContext *C, wmOperator *op, const char *root, const char *libname, char *group, char *name,
+ const short flag, GSet **todo_libraries)
{
Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
- Main *mainl = NULL;
+ Main *mainl;
BlendHandle *bh;
Library *lib;
+
+ char path[FILE_MAX_LIBEXTRA], relname[FILE_MAX];
+ int idcode;
+ const bool is_first_run = (*todo_libraries == NULL);
+
+ BLI_assert(group);
+ idcode = BKE_idcode_from_name(group);
+
+ bh = BLO_blendhandle_from_file(libname, op->reports);
+
+ if (bh == NULL) {
+ /* unlikely since we just browsed it, but possible
+ * error reports will have been made by BLO_blendhandle_from_file() */
+ return;
+ }
+
+ /* here appending/linking starts */
+ mainl = BLO_library_append_begin(bmain, &bh, libname);
+ lib = mainl->curlib;
+ BLI_assert(lib);
+
+ if (mainl->versionfile < 250) {
+ BKE_reportf(op->reports, RPT_WARNING,
+ "Linking or appending from a very old .blend file format (%d.%d), no animation conversion will "
+ "be done! You may want to re-save your lib file with current Blender",
+ mainl->versionfile, mainl->subversionfile);
+ }
+
+ if (name) {
+ BLO_library_append_named_part_ex(C, mainl, &bh, name, idcode, flag);
+ }
+ else {
+ if (is_first_run) {
+ *todo_libraries = BLI_gset_new(BLI_ghashutil_strhash_p, BLI_ghashutil_strcmp, __func__);
+ }
+
+ RNA_BEGIN (op->ptr, itemptr, "files")
+ {
+ char curr_libname[FILE_MAX];
+ int curr_idcode;
+
+ RNA_string_get(&itemptr, "name", relname);
+
+ BLI_join_dirfile(path, sizeof(path), root, relname);
+
+ if (BLO_library_path_explode(path, curr_libname, &group, &name)) {
+ if (!group || !name) {
+ continue;
+ }
+
+ curr_idcode = BKE_idcode_from_name(group);
+
+ if ((idcode == curr_idcode) && (BLI_path_cmp(curr_libname, libname) == 0)) {
+ BLO_library_append_named_part_ex(C, mainl, &bh, name, idcode, flag);
+ }
+ else if (is_first_run) {
+ BLI_join_dirfile(path, sizeof(path), curr_libname, group);
+ if (!BLI_gset_haskey(*todo_libraries, path)) {
+ BLI_gset_insert(*todo_libraries, BLI_strdup(path));
+ }
+ }
+ }
+ }
+ RNA_END;
+ }
+ BLO_library_append_end(C, mainl, &bh, idcode, flag);
+
+ BLO_blendhandle_close(bh);
+
+ /* mark all library linked objects to be updated */
+ BKE_main_lib_objects_recalc_all(bmain);
+ IMB_colormanagement_check_file_config(bmain);
+
+ /* append, rather than linking */
+ if ((flag & FILE_LINK) == 0) {
+ BLI_assert(BLI_findindex(&bmain->library, lib) != -1);
+ BKE_library_make_local(bmain, lib, true);
+ }
+}
+
+static int wm_link_append_exec(bContext *C, wmOperator *op)
+{
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
PropertyRNA *prop;
- char name[FILE_MAX], dir[FILE_MAX], libname[FILE_MAX], group[BLO_GROUP_MAX];
- int idcode, totfiles = 0;
+ char path[FILE_MAX_LIBEXTRA], root[FILE_MAXDIR], libname[FILE_MAX], relname[FILE_MAX];
+ char *group, *name;
+ int totfiles = 0;
short flag;
- RNA_string_get(op->ptr, "filename", name);
- RNA_string_get(op->ptr, "directory", dir);
+ GSet *todo_libraries = NULL;
+
+ RNA_string_get(op->ptr, "filename", relname);
+ RNA_string_get(op->ptr, "directory", root);
+
+ BLI_join_dirfile(path, sizeof(path), root, relname);
/* test if we have a valid data */
- if (BLO_is_a_library(dir, libname, group) == 0) {
+ if (!BLO_library_path_explode(path, libname, &group, &name)) {
BKE_report(op->reports, RPT_ERROR, "Not a library");
return OPERATOR_CANCELLED;
}
- else if (group[0] == 0) {
+ else if (!group) {
BKE_report(op->reports, RPT_ERROR, "Nothing indicated");
return OPERATOR_CANCELLED;
}
@@ -2511,35 +2727,17 @@ static int wm_link_append_exec(bContext *C, wmOperator *op)
if (prop) {
totfiles = RNA_property_collection_length(op->ptr, prop);
if (totfiles == 0) {
- if (name[0] == '\0') {
+ if (!name) {
BKE_report(op->reports, RPT_ERROR, "Nothing indicated");
return OPERATOR_CANCELLED;
}
}
}
- else if (name[0] == '\0') {
+ else if (!name) {
BKE_report(op->reports, RPT_ERROR, "Nothing indicated");
return OPERATOR_CANCELLED;
}
- bh = BLO_blendhandle_from_file(libname, op->reports);
-
- if (bh == NULL) {
- /* unlikely since we just browsed it, but possible
- * error reports will have been made by BLO_blendhandle_from_file() */
- return OPERATOR_CANCELLED;
- }
-
-
- /* from here down, no error returns */
-
- idcode = BKE_idcode_from_name(group);
-
- /* now we have or selected, or an indicated file */
- if (RNA_boolean_get(op->ptr, "autoselect"))
- BKE_scene_base_deselect_all(scene);
-
-
flag = wm_link_append_flag(op);
/* sanity checks for flag */
@@ -2549,39 +2747,36 @@ static int wm_link_append_exec(bContext *C, wmOperator *op)
flag &= ~FILE_GROUP_INSTANCE;
}
+ /* from here down, no error returns */
+ /* now we have or selected, or an indicated file */
+ if (RNA_boolean_get(op->ptr, "autoselect"))
+ BKE_scene_base_deselect_all(scene);
+
/* tag everything, all untagged data can be made local
* its also generally useful to know what is new
*
* take extra care BKE_main_id_flag_all(LIB_LINK_TAG, false) is called after! */
BKE_main_id_flag_all(bmain, LIB_PRE_EXISTING, 1);
- /* here appending/linking starts */
- mainl = BLO_library_append_begin(bmain, &bh, libname);
- lib = mainl->curlib;
- BLI_assert(lib);
-
- if (totfiles == 0) {
- BLO_library_append_named_part_ex(C, mainl, &bh, name, idcode, flag);
+ if (totfiles != 0) {
+ name = NULL;
}
- else {
- RNA_BEGIN (op->ptr, itemptr, "files")
- {
- RNA_string_get(&itemptr, "name", name);
- BLO_library_append_named_part_ex(C, mainl, &bh, name, idcode, flag);
+
+ wm_link_append_do_libgroup(C, op, root, libname, group, name, flag, &todo_libraries);
+
+ if (todo_libraries) {
+ GSetIterator libs_it;
+
+ GSET_ITER(libs_it, todo_libraries) {
+ char *libpath = (char *)BLI_gsetIterator_getKey(&libs_it);
+
+ BLO_library_path_explode(libpath, libname, &group, NULL);
+
+ wm_link_append_do_libgroup(C, op, root, libname, group, NULL, flag, &todo_libraries);
}
- RNA_END;
- }
- BLO_library_append_end(C, mainl, &bh, idcode, flag);
-
- /* mark all library linked objects to be updated */
- BKE_main_lib_objects_recalc_all(bmain);
- IMB_colormanagement_check_file_config(bmain);
- /* append, rather than linking */
- if ((flag & FILE_LINK) == 0) {
- BLI_assert(BLI_findindex(&bmain->library, lib) != -1);
- BKE_library_make_local(bmain, lib, true);
+ BLI_gset_free(todo_libraries, MEM_freeN);
}
/* important we unset, otherwise these object wont
@@ -2590,11 +2785,12 @@ static int wm_link_append_exec(bContext *C, wmOperator *op)
/* recreate dependency graph to include new objects */
DAG_scene_relations_rebuild(bmain, scene);
-
- BLO_blendhandle_close(bh);
+
+ /* free gpu materials, some materials depend on existing objects, such as lamps so freeing correctly refreshes */
+ GPU_materials_free();
/* XXX TODO: align G.lib with other directory storage (like last opened image etc...) */
- BLI_strncpy(G.lib, dir, FILE_MAX);
+ BLI_strncpy(G.lib, root, FILE_MAX);
WM_event_add_notifier(C, NC_WINDOW, NULL);
@@ -2634,9 +2830,9 @@ static void WM_OT_link(wmOperatorType *ot)
ot->flag |= OPTYPE_UNDO;
WM_operator_properties_filesel(
- ot, FOLDERFILE | BLENDERFILE, FILE_LOADLIB, FILE_OPENFILE,
+ ot, FILE_TYPE_FOLDER | FILE_TYPE_BLENDER | FILE_TYPE_BLENDERLIB, FILE_LOADLIB, FILE_OPENFILE,
WM_FILESEL_FILEPATH | WM_FILESEL_DIRECTORY | WM_FILESEL_FILENAME | WM_FILESEL_RELPATH | WM_FILESEL_FILES,
- FILE_DEFAULTDISPLAY);
+ FILE_DEFAULTDISPLAY, FILE_SORT_ALPHA);
wm_link_append_properties_common(ot, true);
}
@@ -2654,9 +2850,9 @@ static void WM_OT_append(wmOperatorType *ot)
ot->flag |= OPTYPE_UNDO;
WM_operator_properties_filesel(
- ot, FOLDERFILE | BLENDERFILE, FILE_LOADLIB, FILE_OPENFILE,
+ ot, FILE_TYPE_FOLDER | FILE_TYPE_BLENDER | FILE_TYPE_BLENDERLIB, FILE_LOADLIB, FILE_OPENFILE,
WM_FILESEL_FILEPATH | WM_FILESEL_DIRECTORY | WM_FILESEL_FILENAME | WM_FILESEL_FILES,
- FILE_DEFAULTDISPLAY);
+ FILE_DEFAULTDISPLAY, FILE_SORT_ALPHA);
wm_link_append_properties_common(ot, false);
}
@@ -2667,7 +2863,7 @@ void WM_recover_last_session(bContext *C, ReportList *reports)
{
char filepath[FILE_MAX];
- BLI_make_file_string("/", filepath, BLI_temp_dir_base(), BLENDER_QUIT_FILE);
+ BLI_make_file_string("/", filepath, BKE_tempdir_base(), BLENDER_QUIT_FILE);
/* if reports==NULL, it's called directly without operator, we add a quick check here */
if (reports || BLI_exists(filepath)) {
G.fileflags |= G_FILE_RECOVER;
@@ -2746,8 +2942,8 @@ static void WM_OT_recover_auto_save(wmOperatorType *ot)
ot->exec = wm_recover_auto_save_exec;
ot->invoke = wm_recover_auto_save_invoke;
- WM_operator_properties_filesel(ot, BLENDERFILE, FILE_BLENDER, FILE_OPENFILE,
- WM_FILESEL_FILEPATH, FILE_LONGDISPLAY);
+ WM_operator_properties_filesel(ot, FILE_TYPE_BLENDER, FILE_BLENDER, FILE_OPENFILE,
+ WM_FILESEL_FILEPATH, FILE_LONGDISPLAY, FILE_SORT_TIME);
}
/* *************** save file as **************** */
@@ -2761,30 +2957,45 @@ static void wm_filepath_default(char *filepath)
static void save_set_compress(wmOperator *op)
{
- if (!RNA_struct_property_is_set(op->ptr, "compress")) {
- if (G.save_over) /* keep flag for existing file */
- RNA_boolean_set(op->ptr, "compress", G.fileflags & G_FILE_COMPRESS);
- else /* use userdef for new file */
- RNA_boolean_set(op->ptr, "compress", U.flag & USER_FILECOMPRESS);
+ PropertyRNA *prop;
+
+ prop = RNA_struct_find_property(op->ptr, "compress");
+ if (!RNA_property_is_set(op->ptr, prop)) {
+ if (G.save_over) { /* keep flag for existing file */
+ RNA_property_boolean_set(op->ptr, prop, (G.fileflags & G_FILE_COMPRESS) != 0);
+ }
+ else { /* use userdef for new file */
+ RNA_property_boolean_set(op->ptr, prop, (U.flag & USER_FILECOMPRESS) != 0);
+ }
}
}
-static int wm_save_as_mainfile_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
+static void save_set_filepath(wmOperator *op)
{
+ PropertyRNA *prop;
char name[FILE_MAX];
- save_set_compress(op);
-
- /* if not saved before, get the name of the most recently used .blend file */
- if (G.main->name[0] == 0 && G.recent_files.first) {
- struct RecentFile *recent = G.recent_files.first;
- BLI_strncpy(name, recent->filepath, FILE_MAX);
+ prop = RNA_struct_find_property(op->ptr, "filepath");
+ if (!RNA_property_is_set(op->ptr, prop)) {
+ /* if not saved before, get the name of the most recently used .blend file */
+ if (G.main->name[0] == 0 && G.recent_files.first) {
+ struct RecentFile *recent = G.recent_files.first;
+ BLI_strncpy(name, recent->filepath, FILE_MAX);
+ }
+ else {
+ BLI_strncpy(name, G.main->name, FILE_MAX);
+ }
+
+ wm_filepath_default(name);
+ RNA_property_string_set(op->ptr, prop, name);
}
- else
- BLI_strncpy(name, G.main->name, FILE_MAX);
-
- wm_filepath_default(name);
- RNA_string_set(op->ptr, "filepath", name);
+}
+
+static int wm_save_as_mainfile_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
+{
+
+ save_set_compress(op);
+ save_set_filepath(op);
WM_event_add_fileselect(C, op);
@@ -2824,6 +3035,8 @@ static int wm_save_as_mainfile_exec(bContext *C, wmOperator *op)
(RNA_struct_find_property(op->ptr, "use_mesh_compat") &&
RNA_boolean_get(op->ptr, "use_mesh_compat")),
G_FILE_MESH_COMPAT);
+#else
+# error "don't remove by accident"
#endif
if (wm_file_write(C, path, fileflags, op->reports) != 0)
@@ -2860,18 +3073,18 @@ static void WM_OT_save_as_mainfile(wmOperatorType *ot)
ot->invoke = wm_save_as_mainfile_invoke;
ot->exec = wm_save_as_mainfile_exec;
ot->check = blend_save_check;
- /* ommit window poll so this can work in background mode */
+ /* omit window poll so this can work in background mode */
- WM_operator_properties_filesel(ot, FOLDERFILE | BLENDERFILE, FILE_BLENDER, FILE_SAVE,
- WM_FILESEL_FILEPATH, FILE_DEFAULTDISPLAY);
- RNA_def_boolean(ot->srna, "compress", 0, "Compress", "Write compressed .blend file");
- RNA_def_boolean(ot->srna, "relative_remap", 1, "Remap Relative",
+ WM_operator_properties_filesel(ot, FILE_TYPE_FOLDER | FILE_TYPE_BLENDER, FILE_BLENDER, FILE_SAVE,
+ WM_FILESEL_FILEPATH, FILE_DEFAULTDISPLAY, FILE_SORT_ALPHA);
+ RNA_def_boolean(ot->srna, "compress", false, "Compress", "Write compressed .blend file");
+ RNA_def_boolean(ot->srna, "relative_remap", true, "Remap Relative",
"Remap relative paths when saving in a different directory");
- prop = RNA_def_boolean(ot->srna, "copy", 0, "Save Copy",
+ prop = RNA_def_boolean(ot->srna, "copy", false, "Save Copy",
"Save a copy of the actual working state but does not make saved file active");
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
#ifdef USE_BMESH_SAVE_AS_COMPAT
- RNA_def_boolean(ot->srna, "use_mesh_compat", 0, "Legacy Mesh Format",
+ RNA_def_boolean(ot->srna, "use_mesh_compat", false, "Legacy Mesh Format",
"Save using legacy mesh format (no ngons) - WARNING: only saves tris and quads, other ngons will "
"be lost (no implicit triangulation)");
#endif
@@ -2881,7 +3094,6 @@ static void WM_OT_save_as_mainfile(wmOperatorType *ot)
static int wm_save_mainfile_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- char name[FILE_MAX];
int ret;
/* cancel if no active window */
@@ -2889,18 +3101,7 @@ static int wm_save_mainfile_invoke(bContext *C, wmOperator *op, const wmEvent *U
return OPERATOR_CANCELLED;
save_set_compress(op);
-
- /* if not saved before, get the name of the most recently used .blend file */
- if (G.main->name[0] == 0 && G.recent_files.first) {
- struct RecentFile *recent = G.recent_files.first;
- BLI_strncpy(name, recent->filepath, FILE_MAX);
- }
- else
- BLI_strncpy(name, G.main->name, FILE_MAX);
-
- wm_filepath_default(name);
-
- RNA_string_set(op->ptr, "filepath", name);
+ save_set_filepath(op);
/* if we're saving for the first time and prefer relative paths - any existing paths will be absolute,
* enable the option to remap paths to avoid confusion [#37240] */
@@ -2912,8 +3113,11 @@ static int wm_save_mainfile_invoke(bContext *C, wmOperator *op, const wmEvent *U
}
if (G.save_over) {
- if (BLI_exists(name)) {
- ret = WM_operator_confirm_message_ex(C, op, IFACE_("Save Over?"), ICON_QUESTION, name);
+ char path[FILE_MAX];
+
+ RNA_string_get(op->ptr, "filepath", path);
+ if (BLI_exists(path)) {
+ ret = WM_operator_confirm_message_ex(C, op, IFACE_("Save Over?"), ICON_QUESTION, path);
}
else {
ret = wm_save_as_mainfile_exec(C, op);
@@ -2936,17 +3140,18 @@ static void WM_OT_save_mainfile(wmOperatorType *ot)
ot->invoke = wm_save_mainfile_invoke;
ot->exec = wm_save_as_mainfile_exec;
ot->check = blend_save_check;
- /* ommit window poll so this can work in background mode */
+ /* omit window poll so this can work in background mode */
- WM_operator_properties_filesel(ot, FOLDERFILE | BLENDERFILE, FILE_BLENDER, FILE_SAVE,
- WM_FILESEL_FILEPATH, FILE_DEFAULTDISPLAY);
- RNA_def_boolean(ot->srna, "compress", 0, "Compress", "Write compressed .blend file");
- RNA_def_boolean(ot->srna, "relative_remap", 0, "Remap Relative", "Remap relative paths when saving in a different directory");
+ WM_operator_properties_filesel(ot, FILE_TYPE_FOLDER | FILE_TYPE_BLENDER, FILE_BLENDER, FILE_SAVE,
+ WM_FILESEL_FILEPATH, FILE_DEFAULTDISPLAY, FILE_SORT_ALPHA);
+ RNA_def_boolean(ot->srna, "compress", false, "Compress", "Write compressed .blend file");
+ RNA_def_boolean(ot->srna, "relative_remap", false, "Remap Relative",
+ "Remap relative paths when saving in a different directory");
}
static void WM_OT_window_fullscreen_toggle(wmOperatorType *ot)
{
- ot->name = "Toggle Fullscreen";
+ ot->name = "Toggle Window Fullscreen";
ot->idname = "WM_OT_window_fullscreen_toggle";
ot->description = "Toggle the current window fullscreen";
@@ -2986,7 +3191,7 @@ static int wm_console_toggle_exec(bContext *UNUSED(C), wmOperator *UNUSED(op))
static void WM_OT_console_toggle(wmOperatorType *ot)
{
/* XXX Have to mark these for xgettext, as under linux they do not exists... */
- ot->name = CTX_N_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Toggle System Console");
+ ot->name = CTX_N_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Toggle System Console");
ot->idname = "WM_OT_console_toggle";
ot->description = N_("Toggle System Console");
@@ -3037,9 +3242,10 @@ void WM_paint_cursor_end(wmWindowManager *wm, void *handle)
/* **************** Border gesture *************** */
-/* Border gesture has two types:
- * 1) WM_GESTURE_CROSS_RECT: starts a cross, on mouse click it changes to border
- * 2) WM_GESTURE_RECT: starts immediate as a border, on mouse click or release it ends
+/**
+ * Border gesture has two types:
+ * -# #WM_GESTURE_CROSS_RECT: starts a cross, on mouse click it changes to border.
+ * -# #WM_GESTURE_RECT: starts immediate as a border, on mouse click or release it ends.
*
* It stores 4 values (xmin, xmax, ymin, ymax) and event it ended with (event_type)
*/
@@ -3064,14 +3270,16 @@ static int border_apply_rect(wmOperator *op)
static int border_apply(bContext *C, wmOperator *op, int gesture_mode)
{
+ PropertyRNA *prop;
+
int retval;
if (!border_apply_rect(op))
return 0;
/* XXX weak; border should be configured for this without reading event types */
- if (RNA_struct_find_property(op->ptr, "gesture_mode")) {
- RNA_int_set(op->ptr, "gesture_mode", gesture_mode);
+ if ((prop = RNA_struct_find_property(op->ptr, "gesture_mode"))) {
+ RNA_property_int_set(op->ptr, prop, gesture_mode);
}
retval = op->type->exec(C, op);
@@ -3336,7 +3544,10 @@ static void tweak_gesture_modal(bContext *C, const wmEvent *event)
tevent.type = EVT_TWEAK_M;
tevent.val = val;
/* mouse coords! */
- wm_event_add(window, &tevent);
+
+ /* important we add immediately after this event, so future mouse releases
+ * (which may be in the queue already), are handled in order, see T44740 */
+ wm_event_add_ex(window, &tevent, event);
WM_gesture_end(C, gesture); /* frees gesture itself, and unregisters from window */
}
@@ -3391,6 +3602,8 @@ void wm_tweakevent_test(bContext *C, wmEvent *event, int action)
int WM_gesture_lasso_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
+ PropertyRNA *prop;
+
op->customdata = WM_gesture_new(C, event, WM_GESTURE_LASSO);
/* add modal handler */
@@ -3398,8 +3611,8 @@ int WM_gesture_lasso_invoke(bContext *C, wmOperator *op, const wmEvent *event)
wm_gesture_tag_redraw(C);
- if (RNA_struct_find_property(op->ptr, "cursor")) {
- WM_cursor_modal_set(CTX_wm_window(C), RNA_int_get(op->ptr, "cursor"));
+ if ((prop = RNA_struct_find_property(op->ptr, "cursor"))) {
+ WM_cursor_modal_set(CTX_wm_window(C), RNA_property_int_get(op->ptr, prop));
}
return OPERATOR_RUNNING_MODAL;
@@ -3407,6 +3620,8 @@ int WM_gesture_lasso_invoke(bContext *C, wmOperator *op, const wmEvent *event)
int WM_gesture_lines_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
+ PropertyRNA *prop;
+
op->customdata = WM_gesture_new(C, event, WM_GESTURE_LINES);
/* add modal handler */
@@ -3414,8 +3629,8 @@ int WM_gesture_lines_invoke(bContext *C, wmOperator *op, const wmEvent *event)
wm_gesture_tag_redraw(C);
- if (RNA_struct_find_property(op->ptr, "cursor")) {
- WM_cursor_modal_set(CTX_wm_window(C), RNA_int_get(op->ptr, "cursor"));
+ if ((prop = RNA_struct_find_property(op->ptr, "cursor"))) {
+ WM_cursor_modal_set(CTX_wm_window(C), RNA_property_int_get(op->ptr, prop));
}
return OPERATOR_RUNNING_MODAL;
@@ -3621,6 +3836,8 @@ static int straightline_apply(bContext *C, wmOperator *op)
int WM_gesture_straightline_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
+ PropertyRNA *prop;
+
op->customdata = WM_gesture_new(C, event, WM_GESTURE_STRAIGHTLINE);
/* add modal handler */
@@ -3628,8 +3845,8 @@ int WM_gesture_straightline_invoke(bContext *C, wmOperator *op, const wmEvent *e
wm_gesture_tag_redraw(C);
- if (RNA_struct_find_property(op->ptr, "cursor")) {
- WM_cursor_modal_set(CTX_wm_window(C), RNA_int_get(op->ptr, "cursor"));
+ if ((prop = RNA_struct_find_property(op->ptr, "cursor"))) {
+ WM_cursor_modal_set(CTX_wm_window(C), RNA_property_int_get(op->ptr, prop));
}
return OPERATOR_RUNNING_MODAL;
@@ -3709,10 +3926,11 @@ void WM_OT_straightline_gesture(wmOperatorType *ot)
/* *********************** radial control ****************** */
-#define WM_RADIAL_CONTROL_DISPLAY_SIZE 200
-#define WM_RADIAL_CONTROL_DISPLAY_MIN_SIZE 35
+#define WM_RADIAL_CONTROL_DISPLAY_SIZE (200 * U.pixelsize)
+#define WM_RADIAL_CONTROL_DISPLAY_MIN_SIZE (35 * U.pixelsize)
#define WM_RADIAL_CONTROL_DISPLAY_WIDTH (WM_RADIAL_CONTROL_DISPLAY_SIZE - WM_RADIAL_CONTROL_DISPLAY_MIN_SIZE)
-#define WM_RADIAL_MAX_STR 6
+#define WM_RADIAL_CONTROL_HEADER_LENGTH 180
+#define WM_RADIAL_MAX_STR 10
typedef struct {
PropertyType type;
@@ -3729,8 +3947,24 @@ typedef struct {
ListBase orig_paintcursors;
bool use_secondary_tex;
void *cursor;
+ NumInput num_input;
} RadialControl;
+static void radial_control_update_header(wmOperator *op, bContext *C)
+{
+ RadialControl *rc = op->customdata;
+ char msg[WM_RADIAL_CONTROL_HEADER_LENGTH];
+ ScrArea *sa = CTX_wm_area(C);
+ Scene *scene = CTX_data_scene(C);
+
+ if (sa && hasNumInput(&rc->num_input)) {
+ char num_str[NUM_STR_REP_LEN];
+ outputNumInput(&rc->num_input, num_str, &scene->unit);
+ BLI_snprintf(msg, WM_RADIAL_CONTROL_HEADER_LENGTH, "%s: %s", RNA_property_ui_name(rc->prop), num_str);
+ ED_area_headerprint(sa, msg);
+ }
+}
+
static void radial_control_set_initial_mouse(RadialControl *rc, const wmEvent *event)
{
float d[2] = {0, 0};
@@ -3743,7 +3977,10 @@ static void radial_control_set_initial_mouse(RadialControl *rc, const wmEvent *e
case PROP_NONE:
case PROP_DISTANCE:
case PROP_PIXEL:
- d[0] = rc->initial_value;
+ d[0] = rc->initial_value * U.pixelsize;
+ break;
+ case PROP_PERCENTAGE:
+ d[0] = (rc->initial_value) / 100.0f * WM_RADIAL_CONTROL_DISPLAY_WIDTH + WM_RADIAL_CONTROL_DISPLAY_MIN_SIZE;
break;
case PROP_FACTOR:
d[0] = (1 - rc->initial_value) * WM_RADIAL_CONTROL_DISPLAY_WIDTH + WM_RADIAL_CONTROL_DISPLAY_MIN_SIZE;
@@ -3837,7 +4074,7 @@ static void radial_control_paint_cursor(bContext *C, int x, int y, void *customd
{
RadialControl *rc = customdata;
ARegion *ar = CTX_wm_region(C);
- uiStyle *style = UI_GetStyle();
+ uiStyle *style = UI_style_get();
const uiFontStyle *fstyle = &style->widget;
const int fontid = fstyle->uifont_id;
short fstyle_points = fstyle->points;
@@ -3851,8 +4088,17 @@ static void radial_control_paint_cursor(bContext *C, int x, int y, void *customd
case PROP_NONE:
case PROP_DISTANCE:
case PROP_PIXEL:
- r1 = rc->current_value;
- r2 = rc->initial_value;
+ r1 = rc->current_value * U.pixelsize;
+ r2 = rc->initial_value * U.pixelsize;
+ tex_radius = r1;
+ alpha = 0.75;
+ break;
+ case PROP_PERCENTAGE:
+ r1 = rc->current_value / 100.0f * WM_RADIAL_CONTROL_DISPLAY_WIDTH + WM_RADIAL_CONTROL_DISPLAY_MIN_SIZE;
+ r2 = tex_radius = WM_RADIAL_CONTROL_DISPLAY_SIZE;
+ rmin = WM_RADIAL_CONTROL_DISPLAY_MIN_SIZE;
+ BLI_snprintf(str, WM_RADIAL_MAX_STR, "%3.1f%%", rc->current_value);
+ strdrawlen = BLI_strlen_utf8(str);
tex_radius = r1;
alpha = 0.75;
break;
@@ -3877,11 +4123,6 @@ static void radial_control_paint_cursor(bContext *C, int x, int y, void *customd
break;
}
- /* adjust for DPI, like BKE_brush_size_get */
- r1 *= U.pixelsize;
- r2 *= U.pixelsize;
- tex_radius *= U.pixelsize;
-
/* Keep cursor in the original place */
x = rc->initial_mouse[0] - ar->winrct.xmin;
y = rc->initial_mouse[1] - ar->winrct.ymin;
@@ -3943,12 +4184,15 @@ typedef enum {
RC_PROP_REQUIRE_BOOL = 4,
} RCPropFlags;
-/* attempt to retrieve the rna pointer/property from an rna path;
- * returns 0 for failure, 1 for success, and also 1 if property is not
- * set */
-static int radial_control_get_path(PointerRNA *ctx_ptr, wmOperator *op,
- const char *name, PointerRNA *r_ptr,
- PropertyRNA **r_prop, int req_length, RCPropFlags flags)
+/**
+ * Attempt to retrieve the rna pointer/property from an rna path.
+ *
+ * \return 0 for failure, 1 for success, and also 1 if property is not set.
+ */
+static int radial_control_get_path(
+ PointerRNA *ctx_ptr, wmOperator *op,
+ const char *name, PointerRNA *r_ptr,
+ PropertyRNA **r_prop, int req_length, RCPropFlags flags)
{
PropertyRNA *unused_prop;
int len;
@@ -3989,7 +4233,7 @@ static int radial_control_get_path(PointerRNA *ctx_ptr, wmOperator *op,
PropertyType prop_type = RNA_property_type(*r_prop);
if (((flags & RC_PROP_REQUIRE_BOOL) && (prop_type != PROP_BOOLEAN)) ||
- ((flags & RC_PROP_REQUIRE_FLOAT) && prop_type != PROP_FLOAT))
+ ((flags & RC_PROP_REQUIRE_FLOAT) && (prop_type != PROP_FLOAT)))
{
MEM_freeN(str);
BKE_reportf(op->reports, RPT_ERROR, "Property from path '%s' is not a float", name);
@@ -4082,8 +4326,7 @@ static int radial_control_invoke(bContext *C, wmOperator *op, const wmEvent *eve
{
wmWindowManager *wm;
RadialControl *rc;
- int min_value_int, max_value_int, step_int;
- float step_float, precision;
+
if (!(op->customdata = rc = MEM_callocN(sizeof(RadialControl), "RadialControl")))
return OPERATOR_CANCELLED;
@@ -4096,31 +4339,50 @@ static int radial_control_invoke(bContext *C, wmOperator *op, const wmEvent *eve
/* get type, initial, min, and max values of the property */
switch ((rc->type = RNA_property_type(rc->prop))) {
case PROP_INT:
- rc->initial_value = RNA_property_int_get(&rc->ptr, rc->prop);
- RNA_property_int_ui_range(&rc->ptr, rc->prop, &min_value_int,
- &max_value_int, &step_int);
- rc->min_value = min_value_int;
- rc->max_value = max_value_int;
+ {
+ int value, min, max, step;
+
+ value = RNA_property_int_get(&rc->ptr, rc->prop);
+ RNA_property_int_ui_range(&rc->ptr, rc->prop, &min, &max, &step);
+
+ rc->initial_value = value;
+ rc->min_value = min_ii(value, min);
+ rc->max_value = max_ii(value, max);
break;
+ }
case PROP_FLOAT:
- rc->initial_value = RNA_property_float_get(&rc->ptr, rc->prop);
- RNA_property_float_ui_range(&rc->ptr, rc->prop, &rc->min_value,
- &rc->max_value, &step_float, &precision);
+ {
+ float value, min, max, step, precision;
+
+ value = RNA_property_float_get(&rc->ptr, rc->prop);
+ RNA_property_float_ui_range(&rc->ptr, rc->prop, &min, &max, &step, &precision);
+
+ rc->initial_value = value;
+ rc->min_value = min_ff(value, min);
+ rc->max_value = max_ff(value, max);
break;
+ }
default:
BKE_report(op->reports, RPT_ERROR, "Property must be an integer or a float");
MEM_freeN(rc);
return OPERATOR_CANCELLED;
}
+ /* initialize numerical input */
+ initNumInput(&rc->num_input);
+ rc->num_input.idx_max = 0;
+ rc->num_input.val_flag[0] |= NUM_NO_NEGATIVE;
+ rc->num_input.unit_sys = USER_UNIT_NONE;
+ rc->num_input.unit_type[0] = B_UNIT_LENGTH;
+
/* get subtype of property */
rc->subtype = RNA_property_subtype(rc->prop);
- if (!ELEM(rc->subtype, PROP_NONE, PROP_DISTANCE, PROP_FACTOR, PROP_ANGLE, PROP_PIXEL)) {
- BKE_report(op->reports, RPT_ERROR, "Property must be a none, distance, a factor, or an angle");
+ if (!ELEM(rc->subtype, PROP_NONE, PROP_DISTANCE, PROP_FACTOR, PROP_PERCENTAGE, PROP_ANGLE, PROP_PIXEL)) {
+ BKE_report(op->reports, RPT_ERROR, "Property must be a none, distance, factor, percentage, angle, or pixel");
MEM_freeN(rc);
return OPERATOR_CANCELLED;
}
-
+
rc->current_value = rc->initial_value;
radial_control_set_initial_mouse(rc, event);
radial_control_set_tex(rc);
@@ -4157,11 +4419,16 @@ static void radial_control_cancel(bContext *C, wmOperator *op)
{
RadialControl *rc = op->customdata;
wmWindowManager *wm = CTX_wm_manager(C);
+ ScrArea *sa = CTX_wm_area(C);
if (rc->dial) {
MEM_freeN(rc->dial);
rc->dial = NULL;
}
+
+ if (sa) {
+ ED_area_headerprint(sa, NULL);
+ }
WM_paint_cursor_end(wm, rc->cursor);
@@ -4181,129 +4448,190 @@ static void radial_control_cancel(bContext *C, wmOperator *op)
static int radial_control_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
RadialControl *rc = op->customdata;
- float new_value, dist, zoom[2];
+ float new_value, dist = 0.0f, zoom[2];
float delta[2], ret = OPERATOR_RUNNING_MODAL;
bool snap;
float angle_precision = 0.0f;
+ const bool has_numInput = hasNumInput(&rc->num_input);
+ bool handled = false;
+ float numValue;
/* TODO: fix hardcoded events */
snap = event->ctrl != 0;
- switch (event->type) {
- case MOUSEMOVE:
- if (rc->slow_mode) {
- if (rc->subtype == PROP_ANGLE) {
- float position[2] = {event->x, event->y};
-
- /* calculate the initial angle here first */
- delta[0] = rc->initial_mouse[0] - rc->slow_mouse[0];
- delta[1] = rc->initial_mouse[1] - rc->slow_mouse[1];
-
- /* precision angle gets calculated from dial and gets added later */
- angle_precision = -0.1f * BLI_dial_angle(rc->dial, position);
- }
- else {
- delta[0] = rc->initial_mouse[0] - rc->slow_mouse[0];
- delta[1] = rc->initial_mouse[1] - rc->slow_mouse[1];
-
- if (rc->zoom_prop) {
- RNA_property_float_get_array(&rc->zoom_ptr, rc->zoom_prop, zoom);
- delta[0] /= zoom[0];
- delta[1] /= zoom[1];
+ /* Modal numinput active, try to handle numeric inputs first... */
+ if (event->val == KM_PRESS && has_numInput && handleNumInput(C, &rc->num_input, event)) {
+ handled = true;
+ applyNumInput(&rc->num_input, &numValue);
+
+ if (rc->subtype == PROP_ANGLE) {
+ numValue = DEG2RADF(numValue);
+ numValue = fmod(numValue, 2.0f * (float)M_PI);
+ if (numValue < 0.0f)
+ numValue += 2.0f * (float)M_PI;
+ }
+
+ CLAMP(numValue, rc->min_value, rc->max_value);
+ new_value = numValue;
+
+ radial_control_set_value(rc, new_value);
+ rc->current_value = new_value;
+ radial_control_update_header(op, C);
+ return OPERATOR_RUNNING_MODAL;
+ }
+ else {
+ handled = false;
+ switch (event->type) {
+ case ESCKEY:
+ case RIGHTMOUSE:
+ /* canceled; restore original value */
+ radial_control_set_value(rc, rc->initial_value);
+ ret = OPERATOR_CANCELLED;
+ break;
+
+ case LEFTMOUSE:
+ case PADENTER:
+ case RETKEY:
+ /* done; value already set */
+ RNA_property_update(C, &rc->ptr, rc->prop);
+ ret = OPERATOR_FINISHED;
+ break;
+
+ case MOUSEMOVE:
+ if (!has_numInput) {
+ if (rc->slow_mode) {
+ if (rc->subtype == PROP_ANGLE) {
+ float position[2] = {event->x, event->y};
+
+ /* calculate the initial angle here first */
+ delta[0] = rc->initial_mouse[0] - rc->slow_mouse[0];
+ delta[1] = rc->initial_mouse[1] - rc->slow_mouse[1];
+
+ /* precision angle gets calculated from dial and gets added later */
+ angle_precision = -0.1f * BLI_dial_angle(rc->dial, position);
+ }
+ else {
+ delta[0] = rc->initial_mouse[0] - rc->slow_mouse[0];
+ delta[1] = rc->initial_mouse[1] - rc->slow_mouse[1];
+
+ if (rc->zoom_prop) {
+ RNA_property_float_get_array(&rc->zoom_ptr, rc->zoom_prop, zoom);
+ delta[0] /= zoom[0];
+ delta[1] /= zoom[1];
+ }
+
+ dist = len_v2(delta);
+
+ delta[0] = event->x - rc->slow_mouse[0];
+ delta[1] = event->y - rc->slow_mouse[1];
+
+ if (rc->zoom_prop) {
+ delta[0] /= zoom[0];
+ delta[1] /= zoom[1];
+ }
+
+ dist = dist + 0.1f * (delta[0] + delta[1]);
+ }
}
-
- dist = len_v2(delta);
-
- delta[0] = event->x - rc->slow_mouse[0];
- delta[1] = event->y - rc->slow_mouse[1];
-
- if (rc->zoom_prop) {
- delta[0] /= zoom[0];
- delta[1] /= zoom[1];
+ else {
+ delta[0] = rc->initial_mouse[0] - event->x;
+ delta[1] = rc->initial_mouse[1] - event->y;
+
+ if (rc->zoom_prop) {
+ RNA_property_float_get_array(&rc->zoom_ptr, rc->zoom_prop, zoom);
+ delta[0] /= zoom[0];
+ delta[1] /= zoom[1];
+ }
+
+ dist = len_v2(delta);
+ }
+
+ /* calculate new value and apply snapping */
+ switch (rc->subtype) {
+ case PROP_NONE:
+ case PROP_DISTANCE:
+ case PROP_PIXEL:
+ new_value = dist;
+ if (snap) new_value = ((int)new_value + 5) / 10 * 10;
+ new_value /= U.pixelsize;
+ break;
+ case PROP_PERCENTAGE:
+ new_value = ((dist - WM_RADIAL_CONTROL_DISPLAY_MIN_SIZE) / WM_RADIAL_CONTROL_DISPLAY_WIDTH) * 100.0f;
+ if (snap) new_value = ((int)(new_value + 2.5f)) / 5 * 5;
+ break;
+ case PROP_FACTOR:
+ new_value = (WM_RADIAL_CONTROL_DISPLAY_SIZE - dist) / WM_RADIAL_CONTROL_DISPLAY_WIDTH;
+ if (snap) new_value = ((int)ceil(new_value * 10.f) * 10.0f) / 100.f;
+ break;
+ case PROP_ANGLE:
+ new_value = atan2f(delta[1], delta[0]) + (float)M_PI + angle_precision;
+ new_value = fmod(new_value, 2.0f * (float)M_PI);
+ if (new_value < 0.0f)
+ new_value += 2.0f * (float)M_PI;
+ if (snap) new_value = DEG2RADF(((int)RAD2DEGF(new_value) + 5) / 10 * 10);
+ break;
+ default:
+ new_value = dist; /* dummy value, should this ever happen? - campbell */
+ break;
}
-
- dist = dist + 0.1f * (delta[0] + delta[1]);
+
+ /* clamp and update */
+ CLAMP(new_value, rc->min_value, rc->max_value);
+ radial_control_set_value(rc, new_value);
+ rc->current_value = new_value;
+ handled = true;
+ break;
}
- }
- else {
- delta[0] = rc->initial_mouse[0] - event->x;
- delta[1] = rc->initial_mouse[1] - event->y;
+ break;
- if (rc->zoom_prop) {
- RNA_property_float_get_array(&rc->zoom_ptr, rc->zoom_prop, zoom);
- delta[0] /= zoom[0];
- delta[1] /= zoom[1];
+ case LEFTSHIFTKEY:
+ case RIGHTSHIFTKEY:
+ {
+ if (event->val == KM_PRESS) {
+ rc->slow_mouse[0] = event->x;
+ rc->slow_mouse[1] = event->y;
+ rc->slow_mode = true;
+ if (rc->subtype == PROP_ANGLE) {
+ float initial_position[2] = {UNPACK2(rc->initial_mouse)};
+ float current_position[2] = {UNPACK2(rc->slow_mouse)};
+ rc->dial = BLI_dial_initialize(initial_position, 0.0f);
+ /* immediately set the position to get a an initial direction */
+ BLI_dial_angle(rc->dial, current_position);
+ }
+ handled = true;
}
-
- dist = len_v2(delta);
+ if (event->val == KM_RELEASE) {
+ rc->slow_mode = false;
+ handled = true;
+ if (rc->dial) {
+ MEM_freeN(rc->dial);
+ rc->dial = NULL;
+ }
+ }
+ break;
}
+ }
- /* calculate new value and apply snapping */
- switch (rc->subtype) {
- case PROP_NONE:
- case PROP_DISTANCE:
- case PROP_PIXEL:
- new_value = dist;
- if (snap) new_value = ((int)new_value + 5) / 10 * 10;
- break;
- case PROP_FACTOR:
- new_value = (WM_RADIAL_CONTROL_DISPLAY_SIZE - dist) / WM_RADIAL_CONTROL_DISPLAY_WIDTH;
- if (snap) new_value = ((int)ceil(new_value * 10.f) * 10.0f) / 100.f;
- break;
- case PROP_ANGLE:
- new_value = atan2f(delta[1], delta[0]) + M_PI + angle_precision;
- new_value = fmod(new_value, 2.0f * (float)M_PI);
- if (new_value < 0.0f)
- new_value += 2.0f * (float)M_PI;
- if (snap) new_value = DEG2RADF(((int)RAD2DEGF(new_value) + 5) / 10 * 10);
- break;
- default:
- new_value = dist; /* dummy value, should this ever happen? - campbell */
- break;
+ /* Modal numinput inactive, try to handle numeric inputs last... */
+ if (!handled && event->val == KM_PRESS && handleNumInput(C, &rc->num_input, event)) {
+ applyNumInput(&rc->num_input, &numValue);
+
+ if (rc->subtype == PROP_ANGLE) {
+ numValue = DEG2RADF(numValue);
+ numValue = fmod(numValue, 2.0f * (float)M_PI);
+ if (numValue < 0.0f)
+ numValue += 2.0f * (float)M_PI;
}
- /* clamp and update */
- CLAMP(new_value, rc->min_value, rc->max_value);
+ CLAMP(numValue, rc->min_value, rc->max_value);
+ new_value = numValue;
+
radial_control_set_value(rc, new_value);
- rc->current_value = new_value;
- break;
-
- case ESCKEY:
- case RIGHTMOUSE:
- /* canceled; restore original value */
- radial_control_set_value(rc, rc->initial_value);
- ret = OPERATOR_CANCELLED;
- break;
-
- case LEFTMOUSE:
- case PADENTER:
- /* done; value already set */
- RNA_property_update(C, &rc->ptr, rc->prop);
- ret = OPERATOR_FINISHED;
- break;
- case LEFTSHIFTKEY:
- case RIGHTSHIFTKEY:
- if (event->val == KM_PRESS) {
- rc->slow_mouse[0] = event->x;
- rc->slow_mouse[1] = event->y;
- rc->slow_mode = true;
- if (rc->subtype == PROP_ANGLE) {
- float initial_position[2] = {UNPACK2(rc->initial_mouse)};
- float current_position[2] = {UNPACK2(rc->slow_mouse)};
- rc->dial = BLI_dial_initialize(initial_position, 0.0f);
- /* immediately set the position to get a an initial direction */
- BLI_dial_angle(rc->dial, current_position);
- }
- }
- if (event->val == KM_RELEASE) {
- rc->slow_mode = false;
- if (rc->dial) {
- MEM_freeN(rc->dial);
- rc->dial = NULL;
- }
- }
- break;
+ rc->current_value = new_value;
+ radial_control_update_header(op, C);
+ return OPERATOR_RUNNING_MODAL;
+ }
}
ED_region_tag_redraw(CTX_wm_region(C));
@@ -4343,7 +4671,7 @@ static void WM_OT_radial_control(wmOperatorType *ot)
RNA_def_string(ot->srna, "image_id", NULL, 0, "Image ID", "Path of ID that is used to generate an image for the control");
- RNA_def_boolean(ot->srna, "secondary_tex", 0, "Secondary Texture", "Tweak brush secondary/mask texture");
+ RNA_def_boolean(ot->srna, "secondary_tex", false, "Secondary Texture", "Tweak brush secondary/mask texture");
}
/* ************************** timer for testing ***************** */
@@ -4363,110 +4691,137 @@ static void redraw_timer_window_swap(bContext *C)
CTX_wm_window_set(C, win); /* XXX context manipulation warning! */
}
+enum {
+ eRTDrawRegion = 0,
+ eRTDrawRegionSwap = 1,
+ eRTDrawWindow = 2,
+ eRTDrawWindowSwap = 3,
+ eRTAnimationStep = 4,
+ eRTAnimationPlay = 5,
+ eRTUndo = 6,
+};
+
static EnumPropertyItem redraw_timer_type_items[] = {
- {0, "DRAW", 0, "Draw Region", "Draw Region"},
- {1, "DRAW_SWAP", 0, "Draw Region + Swap", "Draw Region and Swap"},
- {2, "DRAW_WIN", 0, "Draw Window", "Draw Window"},
- {3, "DRAW_WIN_SWAP", 0, "Draw Window + Swap", "Draw Window and Swap"},
- {4, "ANIM_STEP", 0, "Anim Step", "Animation Steps"},
- {5, "ANIM_PLAY", 0, "Anim Play", "Animation Playback"},
- {6, "UNDO", 0, "Undo/Redo", "Undo/Redo"},
+ {eRTDrawRegion, "DRAW", 0, "Draw Region", "Draw Region"},
+ {eRTDrawRegionSwap, "DRAW_SWAP", 0, "Draw Region + Swap", "Draw Region and Swap"},
+ {eRTDrawWindow, "DRAW_WIN", 0, "Draw Window", "Draw Window"},
+ {eRTDrawWindowSwap, "DRAW_WIN_SWAP", 0, "Draw Window + Swap", "Draw Window and Swap"},
+ {eRTAnimationStep, "ANIM_STEP", 0, "Anim Step", "Animation Steps"},
+ {eRTAnimationPlay, "ANIM_PLAY", 0, "Anim Play", "Animation Playback"},
+ {eRTUndo, "UNDO", 0, "Undo/Redo", "Undo/Redo"},
{0, NULL, 0, NULL, NULL}
};
-static int redraw_timer_exec(bContext *C, wmOperator *op)
-{
- ARegion *ar = CTX_wm_region(C);
- double stime = PIL_check_seconds_timer();
- int type = RNA_enum_get(op->ptr, "type");
- int iter = RNA_int_get(op->ptr, "iterations");
- int a;
- float time;
- const char *infostr = "";
-
- WM_cursor_wait(1);
- for (a = 0; a < iter; a++) {
- if (type == 0) {
- if (ar)
- ED_region_do_draw(C, ar);
- }
- else if (type == 1) {
- wmWindow *win = CTX_wm_window(C);
- CTX_wm_menu_set(C, NULL);
-
- ED_region_tag_redraw(ar);
- wm_draw_update(C);
-
- CTX_wm_window_set(C, win); /* XXX context manipulation warning! */
+static void redraw_timer_step(
+ bContext *C, Main *bmain, Scene *scene,
+ wmWindow *win, ScrArea *sa, ARegion *ar,
+ const int type, const int cfra)
+{
+ if (type == eRTDrawRegion) {
+ if (ar) {
+ ED_region_do_draw(C, ar);
+ ar->do_draw = false;
}
- else if (type == 2) {
- wmWindow *win = CTX_wm_window(C);
- ScrArea *sa;
-
- ScrArea *sa_back = CTX_wm_area(C);
- ARegion *ar_back = CTX_wm_region(C);
+ }
+ else if (type == eRTDrawRegionSwap) {
+ CTX_wm_menu_set(C, NULL);
- CTX_wm_menu_set(C, NULL);
-
- for (sa = CTX_wm_screen(C)->areabase.first; sa; sa = sa->next) {
- ARegion *ar_iter;
- CTX_wm_area_set(C, sa);
-
- for (ar_iter = sa->regionbase.first; ar_iter; ar_iter = ar_iter->next) {
- if (ar_iter->swinid) {
- CTX_wm_region_set(C, ar_iter);
- ED_region_do_draw(C, ar_iter);
- }
+ ED_region_tag_redraw(ar);
+ wm_draw_update(C);
+
+ CTX_wm_window_set(C, win); /* XXX context manipulation warning! */
+ }
+ else if (type == eRTDrawWindow) {
+ ScrArea *sa_iter;
+
+ CTX_wm_menu_set(C, NULL);
+
+ for (sa_iter = win->screen->areabase.first; sa_iter; sa_iter = sa_iter->next) {
+ ARegion *ar_iter;
+ CTX_wm_area_set(C, sa_iter);
+
+ for (ar_iter = sa_iter->regionbase.first; ar_iter; ar_iter = ar_iter->next) {
+ if (ar_iter->swinid) {
+ CTX_wm_region_set(C, ar_iter);
+ ED_region_do_draw(C, ar_iter);
+ ar_iter->do_draw = false;
}
}
+ }
- CTX_wm_window_set(C, win); /* XXX context manipulation warning! */
+ CTX_wm_window_set(C, win); /* XXX context manipulation warning! */
+
+ CTX_wm_area_set(C, sa);
+ CTX_wm_region_set(C, ar);
+ }
+ else if (type == eRTDrawWindowSwap) {
+ redraw_timer_window_swap(C);
+ }
+ else if (type == eRTAnimationStep) {
+ scene->r.cfra += (cfra == scene->r.cfra) ? 1 : -1;
+ BKE_scene_update_for_newframe(bmain->eval_ctx, bmain, scene, scene->lay);
+ }
+ else if (type == eRTAnimationPlay) {
+ /* play anim, return on same frame as started with */
+ int tot = (scene->r.efra - scene->r.sfra) + 1;
+
+ while (tot--) {
+ /* todo, ability to escape! */
+ scene->r.cfra++;
+ if (scene->r.cfra > scene->r.efra)
+ scene->r.cfra = scene->r.sfra;
- CTX_wm_area_set(C, sa_back);
- CTX_wm_region_set(C, ar_back);
- }
- else if (type == 3) {
- redraw_timer_window_swap(C);
- }
- else if (type == 4) {
- Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
-
- if (a & 1) scene->r.cfra--;
- else scene->r.cfra++;
BKE_scene_update_for_newframe(bmain->eval_ctx, bmain, scene, scene->lay);
+ redraw_timer_window_swap(C);
}
- else if (type == 5) {
+ }
+ else { /* eRTUndo */
+ ED_undo_pop(C);
+ ED_undo_redo(C);
+ }
+}
+
+static int redraw_timer_exec(bContext *C, wmOperator *op)
+{
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+ wmWindow *win = CTX_wm_window(C);
+ ScrArea *sa = CTX_wm_area(C);
+ ARegion *ar = CTX_wm_region(C);
+ double time_start, time_delta;
+ const int type = RNA_enum_get(op->ptr, "type");
+ const int iter = RNA_int_get(op->ptr, "iterations");
+ const double time_limit = (double)RNA_float_get(op->ptr, "time_limit");
+ const int cfra = scene->r.cfra;
+ int a, iter_steps = 0;
+ const char *infostr = "";
+
+ WM_cursor_wait(1);
- /* play anim, return on same frame as started with */
- Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
- int tot = (scene->r.efra - scene->r.sfra) + 1;
+ time_start = PIL_check_seconds_timer();
- while (tot--) {
- /* todo, ability to escape! */
- scene->r.cfra++;
- if (scene->r.cfra > scene->r.efra)
- scene->r.cfra = scene->r.sfra;
+ for (a = 0; a < iter; a++) {
+ redraw_timer_step(C, bmain, scene, win, sa, ar, type, cfra);
+ iter_steps += 1;
- BKE_scene_update_for_newframe(bmain->eval_ctx, bmain, scene, scene->lay);
- redraw_timer_window_swap(C);
+ if (time_limit != 0.0) {
+ if ((PIL_check_seconds_timer() - time_start) > time_limit) {
+ break;
}
- }
- else { /* 6 */
- ED_undo_pop(C);
- ED_undo_redo(C);
+ a = 0;
}
}
- time = (float)((PIL_check_seconds_timer() - stime) * 1000);
+ time_delta = (PIL_check_seconds_timer() - time_start) * 1000;
RNA_enum_description(redraw_timer_type_items, type, &infostr);
WM_cursor_wait(0);
- BKE_reportf(op->reports, RPT_WARNING, "%d x %s: %.2f ms, average: %.4f", iter, infostr, time, time / iter);
+ BKE_reportf(op->reports, RPT_WARNING,
+ "%d x %s: %.4f ms, average: %.8f ms",
+ iter_steps, infostr, time_delta, time_delta / iter_steps);
return OPERATOR_FINISHED;
}
@@ -4481,8 +4836,10 @@ static void WM_OT_redraw_timer(wmOperatorType *ot)
ot->exec = redraw_timer_exec;
ot->poll = WM_operator_winactive;
- ot->prop = RNA_def_enum(ot->srna, "type", redraw_timer_type_items, 0, "Type", "");
+ ot->prop = RNA_def_enum(ot->srna, "type", redraw_timer_type_items, eRTDrawRegion, "Type", "");
RNA_def_int(ot->srna, "iterations", 10, 1, INT_MAX, "Iterations", "Number of times to redraw", 1, 1000);
+ RNA_def_float(ot->srna, "time_limit", 0.0, 0.0, FLT_MAX,
+ "Time Limit", "Seconds to run the test for (override iterations)", 0.0, 60.0);
}
@@ -4525,6 +4882,190 @@ static void WM_OT_dependency_relations(wmOperatorType *ot)
ot->exec = dependency_relations_exec;
}
+/* *************************** Mat/tex/etc. previews generation ************* */
+
+typedef struct PreviewsIDEnsureStack {
+ bContext *C;
+ Scene *scene;
+
+ BLI_LINKSTACK_DECLARE(id_stack, ID *);
+} PreviewsIDEnsureStack;
+
+static void previews_id_ensure(bContext *C, Scene *scene, ID *id)
+{
+ BLI_assert(ELEM(GS(id->name), ID_MA, ID_TE, ID_IM, ID_WO, ID_LA));
+
+ /* Only preview non-library datablocks, lib ones do not pertain to this .blend file!
+ * Same goes for ID with no user. */
+ if (!id->lib && (id->us != 0)) {
+ UI_id_icon_render(C, scene, id, false, false);
+ UI_id_icon_render(C, scene, id, true, false);
+ }
+}
+
+static bool previews_id_ensure_callback(void *todo_v, ID **idptr, int UNUSED(cd_flag))
+{
+ PreviewsIDEnsureStack *todo = todo_v;
+ ID *id = *idptr;
+
+ if (id && (id->flag & LIB_DOIT)) {
+ if (ELEM(GS(id->name), ID_MA, ID_TE, ID_IM, ID_WO, ID_LA)) {
+ previews_id_ensure(todo->C, todo->scene, id);
+ }
+ id->flag &= ~LIB_DOIT; /* Tag the ID as done in any case. */
+ BLI_LINKSTACK_PUSH(todo->id_stack, id);
+ }
+
+ return true;
+}
+
+static int previews_ensure_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ Main *bmain = CTX_data_main(C);
+ ListBase *lb[] = {&bmain->mat, &bmain->tex, &bmain->image, &bmain->world, &bmain->lamp, NULL};
+ PreviewsIDEnsureStack preview_id_stack;
+ Scene *scene;
+ ID *id;
+ int i;
+
+ /* We use LIB_DOIT to check whether we have already handled a given ID or not. */
+ BKE_main_id_flag_all(bmain, LIB_DOIT, true);
+
+ BLI_LINKSTACK_INIT(preview_id_stack.id_stack);
+
+ for (scene = bmain->scene.first; scene; scene = scene->id.next) {
+ preview_id_stack.scene = scene;
+ preview_id_stack.C = C;
+ id = (ID *)scene;
+
+ do {
+ /* This will loop over all IDs linked by current one, render icons for them if needed,
+ * and add them to 'todo' preview_id_stack. */
+ BKE_library_foreach_ID_link(id, previews_id_ensure_callback, &preview_id_stack, IDWALK_READONLY);
+ } while ((id = BLI_LINKSTACK_POP(preview_id_stack.id_stack)));
+ }
+
+ BLI_LINKSTACK_FREE(preview_id_stack.id_stack);
+
+ /* Check a last time for ID not used (fake users only, in theory), and
+ * do our best for those, using current scene... */
+ for (i = 0; lb[i]; i++) {
+ for (id = lb[i]->first; id; id = id->next) {
+ previews_id_ensure(C, NULL, id);
+ }
+ }
+
+ return OPERATOR_FINISHED;
+}
+
+static void WM_OT_previews_ensure(wmOperatorType *ot)
+{
+ ot->name = "Refresh DataBlock Previews";
+ ot->idname = "WM_OT_previews_ensure";
+ ot->description = "Ensure datablock previews are available and up-to-date "
+ "(to be saved in .blend file, only for some types like materials, textures, etc.)";
+
+ ot->exec = previews_ensure_exec;
+}
+
+/* *************************** Datablocks previews clear ************* */
+
+/* Only types supporting previews currently. */
+static EnumPropertyItem preview_id_type_items[] = {
+ {FILTER_ID_SCE, "SCENE", 0, "Scenes", ""},
+ {FILTER_ID_GR, "GROUP", 0, "Groups", ""},
+ {FILTER_ID_OB, "OBJECT", 0, "Objects", ""},
+ {FILTER_ID_MA, "MATERIAL", 0, "Materials", ""},
+ {FILTER_ID_LA, "LAMP", 0, "Lamps", ""},
+ {FILTER_ID_WO, "WORLD", 0, "Worlds", ""},
+ {FILTER_ID_TE, "TEXTURE", 0, "Textures", ""},
+ {FILTER_ID_IM, "IMAGE", 0, "Images", ""},
+#if 0 /* XXX TODO */
+ {FILTER_ID_BR, "BRUSH", 0, "Brushes", ""},
+#endif
+ {0, NULL, 0, NULL, NULL}
+};
+
+static int previews_clear_exec(bContext *C, wmOperator *op)
+{
+ Main *bmain = CTX_data_main(C);
+ ListBase *lb[] = {&bmain->object, &bmain->group,
+ &bmain->mat, &bmain->world, &bmain->lamp, &bmain->tex, &bmain->image, NULL};
+ int i;
+
+ const int id_filters = RNA_enum_get(op->ptr, "id_type");
+
+ for (i = 0; lb[i]; i++) {
+ ID *id = lb[i]->first;
+
+ if (!id) continue;
+
+// printf("%s: %d, %d, %d -> %d\n", id->name, GS(id->name), BKE_idcode_to_idfilter(GS(id->name)),
+// id_filters, BKE_idcode_to_idfilter(GS(id->name)) & id_filters);
+
+ if (!id || !(BKE_idcode_to_idfilter(GS(id->name)) & id_filters)) {
+ continue;
+ }
+
+ for (; id; id = id->next) {
+ PreviewImage *prv_img = BKE_previewimg_id_ensure(id);
+
+ BKE_previewimg_clear(prv_img);
+ }
+ }
+
+ return OPERATOR_FINISHED;
+}
+
+static void WM_OT_previews_clear(wmOperatorType *ot)
+{
+ ot->name = "Clear DataBlock Previews";
+ ot->idname = "WM_OT_previews_clear";
+ ot->description = "Clear datablock previews (only for some types like objects, materials, textures, etc.)";
+
+ ot->exec = previews_clear_exec;
+ ot->invoke = WM_menu_invoke;
+
+ ot->prop = RNA_def_enum_flag(ot->srna, "id_type", preview_id_type_items,
+ FILTER_ID_SCE | FILTER_ID_OB | FILTER_ID_GR |
+ FILTER_ID_MA | FILTER_ID_LA | FILTER_ID_WO | FILTER_ID_TE | FILTER_ID_IM,
+ "DataBlock Type", "Which datablock previews to clear");
+}
+
+/* *************************** Doc from UI ************* */
+
+static int doc_view_manual_ui_context_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ PointerRNA ptr_props;
+ char buf[512];
+ short retval = OPERATOR_CANCELLED;
+
+ if (UI_but_online_manual_id_from_active(C, buf, sizeof(buf))) {
+ WM_operator_properties_create(&ptr_props, "WM_OT_doc_view_manual");
+ RNA_string_set(&ptr_props, "doc_id", buf);
+
+ retval = WM_operator_name_call_ptr(
+ C, WM_operatortype_find("WM_OT_doc_view_manual", false),
+ WM_OP_EXEC_DEFAULT, &ptr_props);
+
+ WM_operator_properties_free(&ptr_props);
+ }
+
+ return retval;
+}
+
+static void WM_OT_doc_view_manual_ui_context(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "View Online Manual";
+ ot->idname = "WM_OT_doc_view_manual_ui_context";
+ ot->description = "View a context based online manual in a web browser";
+
+ /* callbacks */
+ ot->poll = ED_operator_regionactive;
+ ot->exec = doc_view_manual_ui_context_exec;
+}
+
/* ******************************************************* */
static void operatortype_ghash_free_cb(wmOperatorType *ot)
@@ -4544,6 +5085,37 @@ static void operatortype_ghash_free_cb(wmOperatorType *ot)
}
/* ******************************************************* */
+/* toggle 3D for current window, turning it fullscreen if needed */
+static void WM_OT_stereo3d_set(wmOperatorType *ot)
+{
+ PropertyRNA *prop;
+
+ ot->name = "Set Stereo 3D";
+ ot->idname = "WM_OT_set_stereo_3d";
+ ot->description = "Toggle 3D stereo support for current window (or change the display mode)";
+
+ ot->exec = wm_stereo3d_set_exec;
+ ot->invoke = wm_stereo3d_set_invoke;
+ ot->poll = WM_operator_winactive;
+ ot->ui = wm_stereo3d_set_draw;
+ ot->check = wm_stereo3d_set_check;
+ ot->cancel = wm_stereo3d_set_cancel;
+
+ prop = RNA_def_enum(ot->srna, "display_mode", stereo3d_display_items, S3D_DISPLAY_ANAGLYPH, "Display Mode", "");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+ prop = RNA_def_enum(ot->srna, "anaglyph_type", stereo3d_anaglyph_type_items, S3D_ANAGLYPH_REDCYAN, "Anaglyph Type", "");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+ prop = RNA_def_enum(ot->srna, "interlace_type", stereo3d_interlace_type_items, S3D_INTERLACE_ROW, "Interlace Type", "");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+ prop = RNA_def_boolean(ot->srna, "use_interlace_swap", false, "Swap Left/Right",
+ "Swap left and right stereo channels");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+ prop = RNA_def_boolean(ot->srna, "use_sidebyside_crosseyed", false, "Cross-Eyed",
+ "Right eye should see left image and vice-versa");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+}
+
+/* ******************************************************* */
/* called on initialize WM_exit() */
void wm_operatortype_free(void)
{
@@ -4585,9 +5157,13 @@ void wm_operatortype_init(void)
WM_operatortype_append(WM_OT_call_menu);
WM_operatortype_append(WM_OT_call_menu_pie);
WM_operatortype_append(WM_OT_radial_control);
+ WM_operatortype_append(WM_OT_stereo3d_set);
#if defined(WIN32)
WM_operatortype_append(WM_OT_console_toggle);
#endif
+ WM_operatortype_append(WM_OT_previews_ensure);
+ WM_operatortype_append(WM_OT_previews_clear);
+ WM_operatortype_append(WM_OT_doc_view_manual_ui_context);
}
/* circleselect-like modal operators */
@@ -4645,6 +5221,8 @@ static void gesture_circle_modal_keymap(wmKeyConfig *keyconf)
WM_modalkeymap_assign(keymap, "CLIP_OT_select_circle");
WM_modalkeymap_assign(keymap, "MASK_OT_select_circle");
WM_modalkeymap_assign(keymap, "NODE_OT_select_circle");
+ WM_modalkeymap_assign(keymap, "GPENCIL_OT_select_circle");
+ WM_modalkeymap_assign(keymap, "GRAPH_OT_select_circle");
}
@@ -4740,6 +5318,8 @@ static void gesture_border_modal_keymap(wmKeyConfig *keyconf)
WM_modalkeymap_assign(keymap, "VIEW3D_OT_render_border");
WM_modalkeymap_assign(keymap, "VIEW3D_OT_select_border");
WM_modalkeymap_assign(keymap, "VIEW3D_OT_zoom_border"); /* XXX TODO: zoom border should perhaps map rightmouse to zoom out instead of in+cancel */
+ WM_modalkeymap_assign(keymap, "IMAGE_OT_render_border");
+ WM_modalkeymap_assign(keymap, "GPENCIL_OT_select_border");
}
/* zoom to border modal operators */
@@ -4810,6 +5390,8 @@ void wm_window_keymap(wmKeyConfig *keyconf)
WM_keymap_verify_item(keymap, "WM_OT_window_fullscreen_toggle", F11KEY, KM_PRESS, KM_ALT, 0);
WM_keymap_add_item(keymap, "WM_OT_quit_blender", QKEY, KM_PRESS, KM_CTRL, 0);
+ WM_keymap_add_item(keymap, "WM_OT_doc_view_manual_ui_context", F1KEY, KM_PRESS, KM_ALT, 0);
+
/* debug/testing */
WM_keymap_verify_item(keymap, "WM_OT_redraw_timer", TKEY, KM_PRESS, KM_ALT | KM_CTRL, 0);
WM_keymap_verify_item(keymap, "WM_OT_debug_menu", DKEY, KM_PRESS, KM_ALT | KM_CTRL, 0);
diff --git a/source/blender/windowmanager/intern/wm_playanim.c b/source/blender/windowmanager/intern/wm_playanim.c
index 024135e73e9..bf30fd83736 100644
--- a/source/blender/windowmanager/intern/wm_playanim.c
+++ b/source/blender/windowmanager/intern/wm_playanim.c
@@ -69,10 +69,26 @@
#include "GHOST_C-api.h"
#include "BLF_api.h"
-#include "wm_event_types.h"
-
#include "WM_api.h" /* only for WM_main_playanim */
+#ifdef WITH_AUDASPACE
+# include AUD_DEVICE_H
+# include AUD_HANDLE_H
+# include AUD_SOUND_H
+# include AUD_SPECIAL_H
+
+static AUD_Sound *source = NULL;
+static AUD_Handle *playback_handle = NULL;
+static AUD_Handle *scrub_handle = NULL;
+static AUD_Device *audio_device = NULL;
+#endif
+
+/* simple limiter to avoid flooding memory */
+#define USE_FRAME_CACHE_LIMIT
+#ifdef USE_FRAME_CACHE_LIMIT
+# define PLAY_FRAME_CACHE_MAX 30
+#endif
+
struct PlayState;
static void playanim_window_zoom(struct PlayState *ps, const float zoom_offset);
@@ -92,12 +108,15 @@ typedef struct PlayState {
bool turbo;
bool pingpong;
bool noskip;
+ bool indicator;
bool sstep;
bool wait2;
bool stopped;
bool go;
/* waiting for images to load */
bool loading;
+ /* x/y image flip */
+ bool draw_flip[2];
int fstep;
@@ -160,14 +179,23 @@ static struct WindowStateGlobal {
eWS_Qual qual;
} g_WS = {NULL};
-static void playanim_window_get_size(int *width_r, int *height_r)
+static void playanim_window_get_size(int *r_width, int *r_height)
{
GHOST_RectangleHandle bounds = GHOST_GetClientBounds(g_WS.ghost_window);
- *width_r = GHOST_GetWidthRectangle(bounds);
- *height_r = GHOST_GetHeightRectangle(bounds);
+ *r_width = GHOST_GetWidthRectangle(bounds);
+ *r_height = GHOST_GetHeightRectangle(bounds);
GHOST_DisposeRectangle(bounds);
}
+static void playanim_gl_matrix(void)
+{
+ /* unified matrix, note it affects offset for drawing */
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ glOrtho(0.0f, 1.0f, 0.0f, 1.0f, -1.0f, 1.0f);
+ glMatrixMode(GL_MODELVIEW);
+}
+
/* implementation */
static void playanim_event_qual_update(void)
{
@@ -213,8 +241,17 @@ typedef struct PlayAnimPict {
} PlayAnimPict;
static struct ListBase picsbase = {NULL, NULL};
+/* frames in memory - store them here to for easy deallocation later */
static bool fromdisk = false;
static double ptottime = 0.0, swaptime = 0.04;
+#ifdef WITH_AUDASPACE
+static double fps_movie;
+#endif
+
+#ifdef USE_FRAME_CACHE_LIMIT
+static struct ListBase inmempicsbase = {NULL, NULL};
+static int added_images = 0;
+#endif
static PlayAnimPict *playanim_step(PlayAnimPict *playanim, int step)
{
@@ -245,7 +282,8 @@ static int pupdate_time(void)
static void playanim_toscreen(PlayState *ps, PlayAnimPict *picture, struct ImBuf *ibuf, int fontid, int fstep)
{
- float offsx, offsy;
+ float offs_x, offs_y;
+ float span_x, span_y;
if (ibuf == NULL) {
printf("%s: no ibuf for picture '%s'\n", __func__, picture ? picture->name : "<NIL>");
@@ -260,13 +298,17 @@ static void playanim_toscreen(PlayState *ps, PlayAnimPict *picture, struct ImBuf
GHOST_ActivateWindowDrawingContext(g_WS.ghost_window);
+ /* size within window */
+ span_x = (ps->zoom * ibuf->x) / (float)ps->win_x;
+ span_y = (ps->zoom * ibuf->y) / (float)ps->win_y;
+
/* offset within window */
- offsx = 0.5f * (((float)ps->win_x - ps->zoom * ibuf->x) / (float)ps->win_x);
- offsy = 0.5f * (((float)ps->win_y - ps->zoom * ibuf->y) / (float)ps->win_y);
+ offs_x = 0.5f * (1.0f - span_x);
+ offs_y = 0.5f * (1.0f - span_y);
- CLAMP(offsx, 0.0f, 1.0f);
- CLAMP(offsy, 0.0f, 1.0f);
- glRasterPos2f(offsx, offsy);
+ CLAMP(offs_x, 0.0f, 1.0f);
+ CLAMP(offs_y, 0.0f, 1.0f);
+ glRasterPos2f(offs_x, offs_y);
glClearColor(0.1, 0.1, 0.1, 0.0);
glClear(GL_COLOR_BUFFER_BIT);
@@ -276,9 +318,15 @@ static void playanim_toscreen(PlayState *ps, PlayAnimPict *picture, struct ImBuf
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- fdrawcheckerboard(offsx, offsy, offsx + (ps->zoom * ibuf->x) / (float)ps->win_x, offsy + (ps->zoom * ibuf->y) / (float)ps->win_y);
+ fdrawcheckerboard(offs_x, offs_y, offs_x + span_x, offs_y + span_y);
}
-
+
+ glRasterPos2f(offs_x + (ps->draw_flip[0] ? span_x : 0.0f),
+ offs_y + (ps->draw_flip[1] ? span_y : 0.0f));
+
+ glPixelZoom(ps->zoom * (ps->draw_flip[0] ? -1.0f : 1.0f),
+ ps->zoom * (ps->draw_flip[1] ? -1.0f : 1.0f));
+
glDrawPixels(ibuf->x, ibuf->y, GL_RGBA, GL_UNSIGNED_BYTE, ibuf->rect);
glDisable(GL_BLEND);
@@ -302,6 +350,30 @@ static void playanim_toscreen(PlayState *ps, PlayAnimPict *picture, struct ImBuf
BLF_draw(fontid, str, sizeof(str));
}
+ if (ps->indicator) {
+ float fac = ps->picture->frame / (double)(((PlayAnimPict *)picsbase.last)->frame - ((PlayAnimPict *)picsbase.first)->frame);
+
+ fac = 2.0f * fac - 1.0f;
+ glMatrixMode(GL_PROJECTION);
+ glPushMatrix();
+ glLoadIdentity();
+ glMatrixMode(GL_MODELVIEW);
+ glPushMatrix();
+ glLoadIdentity();
+
+ glColor4f(0.0f, 1.0f, 0.0f, 1.0f);
+
+ glBegin(GL_LINES);
+ glVertex2f(fac, -1.0f);
+ glVertex2f(fac, 1.0f);
+ glEnd();
+
+ glPopMatrix();
+ glMatrixMode(GL_PROJECTION);
+ glPopMatrix();
+ glMatrixMode(GL_MODELVIEW);
+ }
+
GHOST_SwapWindowBuffers(g_WS.ghost_window);
}
@@ -409,6 +481,7 @@ static void build_pict_list_ex(PlayState *ps, const char *first, int totframes,
picture->mem = mem;
picture->name = strdup(filepath);
+ picture->frame = count; /* not exact but should work for positioning */
close(file);
BLI_addtail(&picsbase, picture);
count++;
@@ -456,6 +529,76 @@ static void build_pict_list(PlayState *ps, const char *first, int totframes, int
ps->loading = false;
}
+static void update_sound_fps(void)
+{
+#ifdef WITH_AUDASPACE
+ if (playback_handle) {
+ /* swaptime stores the 1.0/fps ratio */
+ double speed = 1.0 / (swaptime * fps_movie);
+
+ AUD_Handle_setPitch(playback_handle, speed);
+ }
+#endif
+}
+
+static void change_frame(PlayState *ps, int cx)
+{
+ int sizex, sizey;
+ int i;
+
+ playanim_window_get_size(&sizex, &sizey);
+ ps->picture = picsbase.first;
+ /* TODO - store in ps direct? */
+ i = 0;
+ while (ps->picture) {
+ i++;
+ ps->picture = ps->picture->next;
+ }
+ i = (i * cx) / sizex;
+
+#ifdef WITH_AUDASPACE
+ if (scrub_handle) {
+ AUD_Handle_stop(scrub_handle);
+ scrub_handle = NULL;
+ }
+
+ if (playback_handle) {
+ AUD_Status status = AUD_Handle_getStatus(playback_handle);
+ if (status != AUD_STATUS_PLAYING) {
+ AUD_Handle_stop(playback_handle);
+ playback_handle = AUD_Device_play(audio_device, source, 1);
+ if (playback_handle) {
+ AUD_Handle_setPosition(playback_handle, i / fps_movie);
+ scrub_handle = AUD_pauseAfter(playback_handle, 1 / fps_movie);
+ }
+ update_sound_fps();
+ }
+ else {
+ AUD_Handle_setPosition(playback_handle, i / fps_movie);
+ scrub_handle = AUD_pauseAfter(playback_handle, 1 / fps_movie);
+ }
+ }
+ else if (source) {
+ playback_handle = AUD_Device_play(audio_device, source, 1);
+ if (playback_handle) {
+ AUD_Handle_setPosition(playback_handle, i / fps_movie);
+ scrub_handle = AUD_pauseAfter(playback_handle, 1 / fps_movie);
+ }
+ update_sound_fps();
+ }
+#endif
+
+ ps->picture = picsbase.first;
+ for (; i > 0; i--) {
+ if (ps->picture->next == NULL) break;
+ ps->picture = ps->picture->next;
+ }
+
+ ps->sstep = true;
+ ps->wait2 = false;
+ ps->next_frame = 0;
+}
+
static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr ps_void)
{
PlayState *ps = (PlayState *)ps_void;
@@ -469,7 +612,6 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr ps_void)
/* convert ghost event into value keyboard or mouse */
val = ELEM(type, GHOST_kEventKeyDown, GHOST_kEventButtonDown);
-
/* first check if we're busy loading files */
if (ps->loading) {
switch (type) {
@@ -515,47 +657,86 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr ps_void)
case GHOST_kKeyA:
if (val) ps->noskip = !ps->noskip;
break;
+ case GHOST_kKeyI:
+ if (val) ps->indicator = !ps->indicator;
+ break;
case GHOST_kKeyP:
if (val) ps->pingpong = !ps->pingpong;
break;
+ case GHOST_kKeyF:
+ {
+ if (val) {
+ int axis = (g_WS.qual & WS_QUAL_SHIFT) ? 1 : 0;
+ ps->draw_flip[axis] = !ps->draw_flip[axis];
+ }
+ break;
+ }
case GHOST_kKey1:
case GHOST_kKeyNumpad1:
- if (val) swaptime = ps->fstep / 60.0;
+ if (val) {
+ swaptime = ps->fstep / 60.0;
+ update_sound_fps();
+ }
break;
case GHOST_kKey2:
case GHOST_kKeyNumpad2:
- if (val) swaptime = ps->fstep / 50.0;
+ if (val) {
+ swaptime = ps->fstep / 50.0;
+ update_sound_fps();
+ }
break;
case GHOST_kKey3:
case GHOST_kKeyNumpad3:
- if (val) swaptime = ps->fstep / 30.0;
+ if (val) {
+ swaptime = ps->fstep / 30.0;
+ update_sound_fps();
+ }
break;
case GHOST_kKey4:
case GHOST_kKeyNumpad4:
- if (g_WS.qual & WS_QUAL_SHIFT)
+ if (g_WS.qual & WS_QUAL_SHIFT) {
swaptime = ps->fstep / 24.0;
- else
+ update_sound_fps();
+ }
+ else {
swaptime = ps->fstep / 25.0;
+ update_sound_fps();
+ }
break;
case GHOST_kKey5:
case GHOST_kKeyNumpad5:
- if (val) swaptime = ps->fstep / 20.0;
+ if (val) {
+ swaptime = ps->fstep / 20.0;
+ update_sound_fps();
+ }
break;
case GHOST_kKey6:
case GHOST_kKeyNumpad6:
- if (val) swaptime = ps->fstep / 15.0;
+ if (val) {
+ swaptime = ps->fstep / 15.0;
+ update_sound_fps();
+ }
break;
case GHOST_kKey7:
case GHOST_kKeyNumpad7:
- if (val) swaptime = ps->fstep / 12.0;
+ if (val) {
+ swaptime = ps->fstep / 12.0;
+ update_sound_fps();
+ }
break;
case GHOST_kKey8:
case GHOST_kKeyNumpad8:
- if (val) swaptime = ps->fstep / 10.0;
+ if (val) {
+ swaptime = ps->fstep / 10.0;
+ update_sound_fps();
+ }
break;
case GHOST_kKey9:
case GHOST_kKeyNumpad9:
- if (val) swaptime = ps->fstep / 6.0;
+ if (val) {
+ swaptime = ps->fstep / 6.0;
+ update_sound_fps();
+ }
break;
case GHOST_kKeyLeftArrow:
if (val) {
@@ -618,6 +799,7 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr ps_void)
}
else {
swaptime = ps->fstep / 5.0;
+ update_sound_fps();
}
}
break;
@@ -634,10 +816,63 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr ps_void)
}
}
break;
+
+ case GHOST_kKeySpace:
+ if (val) {
+ if (ps->wait2 || ps->sstep) {
+ ps->wait2 = ps->sstep = false;
+#ifdef WITH_AUDASPACE
+ {
+ PlayAnimPict *picture = picsbase.first;
+ /* TODO - store in ps direct? */
+ int i = 0;
+
+ while (picture && picture != ps->picture) {
+ i++;
+ picture = picture->next;
+ }
+ if (playback_handle)
+ AUD_Handle_stop(playback_handle);
+ playback_handle = AUD_Device_play(audio_device, source, 1);
+ if (playback_handle)
+ AUD_Handle_setPosition(playback_handle, i / fps_movie);
+ update_sound_fps();
+ }
+#endif
+ }
+ else {
+ ps->sstep = true;
+ ps->wait2 = true;
+#ifdef WITH_AUDASPACE
+ if (playback_handle) {
+ AUD_Handle_stop(playback_handle);
+ playback_handle = NULL;
+ }
+#endif
+ }
+ }
+ break;
case GHOST_kKeyEnter:
case GHOST_kKeyNumpadEnter:
if (val) {
ps->wait2 = ps->sstep = false;
+#ifdef WITH_AUDASPACE
+ {
+ PlayAnimPict *picture = picsbase.first;
+ /* TODO - store in ps direct? */
+ int i = 0;
+ while (picture && picture != ps->picture) {
+ i++;
+ picture = picture->next;
+ }
+ if (playback_handle)
+ AUD_Handle_stop(playback_handle);
+ playback_handle = AUD_Device_play(audio_device, source, 1);
+ if (playback_handle)
+ AUD_Handle_setPosition(playback_handle, i / fps_movie);
+ update_sound_fps();
+ }
+#endif
}
break;
case GHOST_kKeyPeriod:
@@ -649,6 +884,12 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr ps_void)
else {
ps->sstep = true;
ps->wait2 = !ps->wait2;
+#ifdef WITH_AUDASPACE
+ if (playback_handle) {
+ AUD_Handle_stop(playback_handle);
+ playback_handle = NULL;
+ }
+#endif
}
}
break;
@@ -660,7 +901,10 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr ps_void)
playanim_window_zoom(ps, 1.0f);
}
else {
- swaptime /= 1.1;
+ if (swaptime > ps->fstep / 60.0) {
+ swaptime /= 1.1;
+ update_sound_fps();
+ }
}
break;
}
@@ -672,7 +916,10 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr ps_void)
playanim_window_zoom(ps, -1.0f);
}
else {
- swaptime *= 1.1;
+ if (swaptime < ps->fstep / 5.0) {
+ swaptime *= 1.1;
+ update_sound_fps();
+ }
}
break;
}
@@ -698,8 +945,10 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr ps_void)
if (bd->button == GHOST_kButtonMaskLeft) {
if (type == GHOST_kEventButtonDown) {
- if (inside_window)
+ if (inside_window) {
g_WS.qual |= WS_QUAL_LMOUSE;
+ change_frame(ps, cx);
+ }
}
else
g_WS.qual &= ~WS_QUAL_LMOUSE;
@@ -725,31 +974,12 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr ps_void)
case GHOST_kEventCursorMove:
{
if (g_WS.qual & WS_QUAL_LMOUSE) {
- int sizex, sizey;
- int i;
-
GHOST_TEventCursorData *cd = GHOST_GetEventData(evt);
int cx, cy;
GHOST_ScreenToClient(g_WS.ghost_window, cd->x, cd->y, &cx, &cy);
- playanim_window_get_size(&sizex, &sizey);
- ps->picture = picsbase.first;
- /* TODO - store in ps direct? */
- i = 0;
- while (ps->picture) {
- i++;
- ps->picture = ps->picture->next;
- }
- i = (i * cx) / sizex;
- ps->picture = picsbase.first;
- for (; i > 0; i--) {
- if (ps->picture->next == NULL) break;
- ps->picture = ps->picture->next;
- }
- ps->sstep = true;
- ps->wait2 = false;
- ps->next_frame = 0;
+ change_frame(ps, cx);
}
break;
}
@@ -780,13 +1010,8 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr ps_void)
glViewport(0, 0, ps->win_x, ps->win_y);
glScissor(0, 0, ps->win_x, ps->win_y);
- /* unified matrix, note it affects offset for drawing */
- glMatrixMode(GL_PROJECTION);
- glLoadIdentity();
- glOrtho(0.0f, 1.0f, 0.0f, 1.0f, -1.0f, 1.0f);
- glMatrixMode(GL_MODELVIEW);
+ playanim_gl_matrix();
- glPixelZoom(ps->zoom, ps->zoom);
ptottime = 0.0;
playanim_toscreen(ps, ps->picture, ps->curframe_ibuf, ps->fontid, ps->fstep);
@@ -825,6 +1050,7 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr ps_void)
static void playanim_window_open(const char *title, int posx, int posy, int sizex, int sizey)
{
+ GHOST_GLSettings glsettings = {0};
GHOST_TUns32 scr_w, scr_h;
GHOST_GetMainDisplayDimensions(g_WS.ghost_system, &scr_w, &scr_h);
@@ -837,7 +1063,7 @@ static void playanim_window_open(const char *title, int posx, int posy, int size
/* could optionally start fullscreen */
GHOST_kWindowStateNormal,
GHOST_kDrawingContextTypeOpenGL,
- false /* no stereo */, false);
+ glsettings);
}
static void playanim_window_zoom(PlayState *ps, const float zoom_offset)
@@ -888,9 +1114,12 @@ static char *wm_main_playanim_intern(int argc, const char **argv)
ps.stopped = false;
ps.loading = false;
ps.picture = NULL;
+ ps.indicator = false;
ps.dropped_file[0] = 0;
ps.zoom = 1.0f;
/* resetmap = false */
+ ps.draw_flip[0] = false;
+ ps.draw_flip[1] = false;
ps.fstep = 1;
@@ -1008,11 +1237,7 @@ static char *wm_main_playanim_intern(int argc, const char **argv)
playanim_window_open("Blender:Anim", start_x, start_y, ibuf->x, ibuf->y);
- /* unified matrix, note it affects offset for drawing */
- glMatrixMode(GL_PROJECTION);
- glLoadIdentity();
- glOrtho(0.0f, 1.0f, 0.0f, 1.0f, -1.0f, 1.0f);
- glMatrixMode(GL_MODELVIEW);
+ playanim_gl_matrix();
}
GHOST_GetMainDisplayDimensions(g_WS.ghost_system, &maxwinx, &maxwiny);
@@ -1047,6 +1272,23 @@ static char *wm_main_playanim_intern(int argc, const char **argv)
build_pict_list(&ps, filepath, (efra - sfra) + 1, ps.fstep, ps.fontid);
+#ifdef WITH_AUDASPACE
+ source = AUD_Sound_file(filepath);
+ {
+ struct anim *anim_movie = ((struct PlayAnimPict *)picsbase.first)->anim;
+ if (anim_movie) {
+ short frs_sec = 25;
+ float frs_sec_base = 1.0;
+
+ IMB_anim_get_fps(anim_movie, &frs_sec, &frs_sec_base, true);
+
+ fps_movie = (double) frs_sec / (double) frs_sec_base;
+ /* enforce same fps for movie as sound */
+ swaptime = ps.fstep / fps_movie;
+ }
+ }
+#endif
+
for (i = 2; i < argc; i++) {
BLI_strncpy(filepath, argv[i], sizeof(filepath));
build_pict_list(&ps, filepath, (efra - sfra) + 1, ps.fstep, ps.fontid);
@@ -1086,6 +1328,13 @@ static char *wm_main_playanim_intern(int argc, const char **argv)
}
if (ptottime > 0.0) ptottime = 0.0;
+#ifdef WITH_AUDASPACE
+ if (playback_handle)
+ AUD_Handle_stop(playback_handle);
+ playback_handle = AUD_Device_play(audio_device, source, 1);
+ update_sound_fps();
+#endif
+
while (ps.picture) {
int hasevent;
#ifndef USE_IMB_CACHE
@@ -1108,11 +1357,39 @@ static char *wm_main_playanim_intern(int argc, const char **argv)
}
if (ibuf) {
+#ifdef USE_FRAME_CACHE_LIMIT
+ LinkData *node;
+#endif
#ifdef USE_IMB_CACHE
ps.picture->ibuf = ibuf;
#endif
+#ifdef USE_FRAME_CACHE_LIMIT
+ /* really basic memory conservation scheme. Keep frames in a fifo queue */
+ node = inmempicsbase.last;
+
+ while (node && added_images > PLAY_FRAME_CACHE_MAX) {
+ PlayAnimPict *pic = node->data;
+
+ if (pic->ibuf && pic->ibuf != ibuf) {
+ LinkData *node_tmp;
+ IMB_freeImBuf(pic->ibuf);
+ pic->ibuf = NULL;
+ node_tmp = node->prev;
+ BLI_freelinkN(&inmempicsbase, node);
+ added_images--;
+ node = node_tmp;
+ }
+ else {
+ node = node->prev;
+ }
+ }
+
+ BLI_addhead(&inmempicsbase, BLI_genericNodeN(ps.picture));
+ added_images++;
+#endif /* USE_FRAME_CACHE_LIMIT */
+
BLI_strncpy(ibuf->name, ps.picture->name, sizeof(ibuf->name));
/* why only windows? (from 2.4x) - campbell */
@@ -1219,6 +1496,22 @@ static char *wm_main_playanim_intern(int argc, const char **argv)
#endif
BLI_freelistN(&picsbase);
+ BLI_freelistN(&inmempicsbase);
+ added_images = 0;
+
+#ifdef WITH_AUDASPACE
+ if (playback_handle) {
+ AUD_Handle_stop(playback_handle);
+ playback_handle = NULL;
+ }
+ if (scrub_handle) {
+ AUD_Handle_stop(scrub_handle);
+ scrub_handle = NULL;
+ }
+ AUD_Sound_free(source);
+ source = NULL;
+#endif
+
#if 0 // XXX25
free_blender();
#else
@@ -1254,18 +1547,43 @@ static char *wm_main_playanim_intern(int argc, const char **argv)
void WM_main_playanim(int argc, const char **argv)
{
+ const char *argv_next[2];
bool looping = true;
+#ifdef WITH_AUDASPACE
+ {
+ AUD_DeviceSpecs specs;
+
+ specs.rate = AUD_RATE_44100;
+ specs.format = AUD_FORMAT_S16;
+ specs.channels = AUD_CHANNELS_STEREO;
+
+ AUD_initOnce();
+
+ if (!(audio_device = AUD_init("OpenAL", specs, 1024, "Blender"))) {
+ audio_device = AUD_init("Null", specs, 0, "Blender");
+ }
+ }
+#endif
+
while (looping) {
const char *filepath = wm_main_playanim_intern(argc, argv);
if (filepath) { /* use simple args */
- argv[1] = "-a";
- argv[2] = filepath;
- argc = 3;
+ argv_next[0] = argv[0];
+ argv_next[1] = filepath;
+ argc = 2;
+
+ /* continue with new args */
+ argv = argv_next;
}
else {
looping = false;
}
}
+
+#ifdef WITH_AUDASPACE
+ AUD_exit(audio_device);
+ AUD_exitOnce();
+#endif
}
diff --git a/source/blender/windowmanager/intern/wm_stereo.c b/source/blender/windowmanager/intern/wm_stereo.c
new file mode 100644
index 00000000000..98c45bfb6ea
--- /dev/null
+++ b/source/blender/windowmanager/intern/wm_stereo.c
@@ -0,0 +1,598 @@
+/*
+ * ***** 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) 2015 by Blender Foundation
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Dalai Felinto
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/windowmanager/intern/wm_stereo.c
+ * \ingroup wm
+ */
+
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "DNA_listBase.h"
+
+#include "RNA_access.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_listbase.h"
+#include "BLI_utildefines.h"
+
+#include "BIF_gl.h"
+
+#include "BKE_context.h"
+#include "BKE_global.h"
+#include "BKE_report.h"
+
+#include "GHOST_C-api.h"
+
+#include "ED_screen.h"
+
+#include "GPU_glew.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+#include "wm.h"
+#include "wm_draw.h" /* wmDrawTriple */
+#include "wm_window.h"
+
+#include "UI_interface.h"
+#include "UI_resources.h"
+
+static void wm_method_draw_stereo3d_pageflip(wmWindow *win)
+{
+ wmDrawData *drawdata;
+ int view;
+
+ for (view = 0; view < 2; view ++) {
+ drawdata = BLI_findlink(&win->drawdata, (view * 2) + 1);
+
+ if (view == STEREO_LEFT_ID)
+ glDrawBuffer(GL_BACK_LEFT);
+ else //STEREO_RIGHT_ID
+ glDrawBuffer(GL_BACK_RIGHT);
+
+ wm_triple_draw_textures(win, drawdata->triple, 1.0f);
+ }
+
+ glDrawBuffer(GL_BACK);
+}
+
+static GLuint left_interlace_mask[32];
+static GLuint right_interlace_mask[32];
+static enum eStereo3dInterlaceType interlace_prev_type = -1;
+static char interlace_prev_swap = -1;
+
+static void wm_interlace_masks_create(wmWindow *win)
+{
+ GLuint pattern;
+ char i;
+ bool swap = (win->stereo3d_format->flag & S3D_INTERLACE_SWAP) != 0;
+ enum eStereo3dInterlaceType interlace_type = win->stereo3d_format->interlace_type;
+
+ if (interlace_prev_type == interlace_type && interlace_prev_swap == swap)
+ return;
+
+ switch (interlace_type) {
+ case S3D_INTERLACE_ROW:
+ pattern = 0x00000000;
+ pattern = swap ? ~pattern : pattern;
+ for (i = 0; i < 32; i += 2) {
+ left_interlace_mask[i] = pattern;
+ right_interlace_mask[i] = ~pattern;
+ }
+ for (i = 1; i < 32; i += 2) {
+ left_interlace_mask[i] = ~pattern;
+ right_interlace_mask[i] = pattern;
+ }
+ break;
+ case S3D_INTERLACE_COLUMN:
+ pattern = 0x55555555;
+ pattern = swap ? ~pattern : pattern;
+ for (i = 0; i < 32; i++) {
+ left_interlace_mask[i] = pattern;
+ right_interlace_mask[i] = ~pattern;
+ }
+ break;
+ case S3D_INTERLACE_CHECKERBOARD:
+ default:
+ pattern = 0x55555555;
+ pattern = swap ? ~pattern : pattern;
+ for (i = 0; i < 32; i += 2) {
+ left_interlace_mask[i] = pattern;
+ right_interlace_mask[i] = ~pattern;
+ }
+ for (i = 1; i < 32; i += 2) {
+ left_interlace_mask[i] = ~pattern;
+ right_interlace_mask[i] = pattern;
+ }
+ break;
+ }
+ interlace_prev_type = interlace_type;
+ interlace_prev_swap = swap;
+}
+
+static void wm_method_draw_stereo3d_interlace(wmWindow *win)
+{
+ wmDrawData *drawdata;
+ int view;
+
+ wm_interlace_masks_create(win);
+
+ for (view = 0; view < 2; view ++) {
+ drawdata = BLI_findlink(&win->drawdata, (view * 2) + 1);
+
+ glEnable(GL_POLYGON_STIPPLE);
+ glPolygonStipple(view ? (GLubyte *) right_interlace_mask : (GLubyte *) left_interlace_mask);
+
+ wm_triple_draw_textures(win, drawdata->triple, 1.0f);
+ glDisable(GL_POLYGON_STIPPLE);
+ }
+}
+
+static void wm_method_draw_stereo3d_anaglyph(wmWindow *win)
+{
+ wmDrawData *drawdata;
+ int view, bit;
+
+ for (view = 0; view < 2; view ++) {
+ drawdata = BLI_findlink(&win->drawdata, (view * 2) + 1);
+
+ bit = view + 1;
+ switch (win->stereo3d_format->anaglyph_type) {
+ case S3D_ANAGLYPH_REDCYAN:
+ glColorMask((1&bit) ? GL_TRUE : GL_FALSE,
+ (2&bit) ? GL_TRUE : GL_FALSE,
+ (2&bit) ? GL_TRUE : GL_FALSE,
+ GL_FALSE);
+ break;
+ case S3D_ANAGLYPH_GREENMAGENTA:
+ glColorMask((2&bit) ? GL_TRUE : GL_FALSE,
+ (1&bit) ? GL_TRUE : GL_FALSE,
+ (2&bit) ? GL_TRUE : GL_FALSE,
+ GL_FALSE);
+ break;
+ case S3D_ANAGLYPH_YELLOWBLUE:
+ glColorMask((1&bit) ? GL_TRUE : GL_FALSE,
+ (1&bit) ? GL_TRUE : GL_FALSE,
+ (2&bit) ? GL_TRUE : GL_FALSE,
+ GL_FALSE);
+ break;
+ }
+
+ wm_triple_draw_textures(win, drawdata->triple, 1.0f);
+
+ glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
+ }
+}
+
+static void wm_method_draw_stereo3d_sidebyside(wmWindow *win)
+{
+ wmDrawData *drawdata;
+ wmDrawTriple *triple;
+ float halfx, halfy, ratiox, ratioy;
+ int x, y, offx, offy;
+ float alpha = 1.0f;
+ int view;
+ int soffx;
+ bool cross_eyed = (win->stereo3d_format->flag & S3D_SIDEBYSIDE_CROSSEYED) != 0;
+
+ for (view = 0; view < 2; view ++) {
+ drawdata = BLI_findlink(&win->drawdata, (view * 2) + 1);
+ triple = drawdata->triple;
+
+ soffx = WM_window_pixels_x(win) * 0.5f;
+ if (view == STEREO_LEFT_ID) {
+ if (!cross_eyed)
+ soffx = 0;
+ }
+ else { //RIGHT_LEFT_ID
+ if (cross_eyed)
+ soffx = 0;
+ }
+
+ glEnable(triple->target);
+
+ for (y = 0, offy = 0; y < triple->ny; offy += triple->y[y], y++) {
+ for (x = 0, offx = 0; x < triple->nx; offx += triple->x[x], x++) {
+ const int sizex = triple->x[x];
+ const int sizey = triple->y[y];
+
+ /* wmOrtho for the screen has this same offset */
+ ratiox = sizex;
+ ratioy = sizey;
+ halfx = GLA_PIXEL_OFS;
+ halfy = GLA_PIXEL_OFS;
+
+ /* texture rectangle has unnormalized coordinates */
+ if (triple->target == GL_TEXTURE_2D) {
+ ratiox /= triple->x[x];
+ ratioy /= triple->y[y];
+ halfx /= triple->x[x];
+ halfy /= triple->y[y];
+ }
+
+ glBindTexture(triple->target, triple->bind[x + y * triple->nx]);
+
+ glColor4f(1.0f, 1.0f, 1.0f, alpha);
+ glBegin(GL_QUADS);
+ glTexCoord2f(halfx, halfy);
+ glVertex2f(soffx + (offx * 0.5f), offy);
+
+ glTexCoord2f(ratiox + halfx, halfy);
+ glVertex2f(soffx + ((offx + sizex) * 0.5f), offy);
+
+ glTexCoord2f(ratiox + halfx, ratioy + halfy);
+ glVertex2f(soffx + ((offx + sizex) * 0.5f), offy + sizey);
+
+ glTexCoord2f(halfx, ratioy + halfy);
+ glVertex2f(soffx + (offx * 0.5f), offy + sizey);
+ glEnd();
+ }
+ }
+
+ glBindTexture(triple->target, 0);
+ glDisable(triple->target);
+ glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
+ }
+}
+
+static void wm_method_draw_stereo3d_topbottom(wmWindow *win)
+{
+ wmDrawData *drawdata;
+ wmDrawTriple *triple;
+ float halfx, halfy, ratiox, ratioy;
+ int x, y, offx, offy;
+ float alpha = 1.0f;
+ int view;
+ int soffy;
+
+ for (view = 0; view < 2; view ++) {
+ drawdata = BLI_findlink(&win->drawdata, (view * 2) + 1);
+ triple = drawdata->triple;
+
+ if (view == STEREO_LEFT_ID) {
+ soffy = WM_window_pixels_y(win) * 0.5f;
+ }
+ else { /* STEREO_RIGHT_ID */
+ soffy = 0;
+ }
+
+ glEnable(triple->target);
+
+ for (y = 0, offy = 0; y < triple->ny; offy += triple->y[y], y++) {
+ for (x = 0, offx = 0; x < triple->nx; offx += triple->x[x], x++) {
+ const int sizex = triple->x[x];
+ const int sizey = triple->y[y];
+
+ /* wmOrtho for the screen has this same offset */
+ ratiox = sizex;
+ ratioy = sizey;
+ halfx = GLA_PIXEL_OFS;
+ halfy = GLA_PIXEL_OFS;
+
+ /* texture rectangle has unnormalized coordinates */
+ if (triple->target == GL_TEXTURE_2D) {
+ ratiox /= triple->x[x];
+ ratioy /= triple->y[y];
+ halfx /= triple->x[x];
+ halfy /= triple->y[y];
+ }
+
+ glBindTexture(triple->target, triple->bind[x + y * triple->nx]);
+
+ glColor4f(1.0f, 1.0f, 1.0f, alpha);
+ glBegin(GL_QUADS);
+ glTexCoord2f(halfx, halfy);
+ glVertex2f(offx, soffy + (offy * 0.5f));
+
+ glTexCoord2f(ratiox + halfx, halfy);
+ glVertex2f(offx + sizex, soffy + (offy * 0.5f));
+
+ glTexCoord2f(ratiox + halfx, ratioy + halfy);
+ glVertex2f(offx + sizex, soffy + ((offy + sizey) * 0.5f));
+
+ glTexCoord2f(halfx, ratioy + halfy);
+ glVertex2f(offx, soffy + ((offy + sizey) * 0.5f));
+ glEnd();
+ }
+ }
+
+ glBindTexture(triple->target, 0);
+ glDisable(triple->target);
+ glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
+ }
+}
+
+void wm_method_draw_stereo3d(const bContext *UNUSED(C), wmWindow *win)
+{
+ switch (win->stereo3d_format->display_mode) {
+ case S3D_DISPLAY_ANAGLYPH:
+ wm_method_draw_stereo3d_anaglyph(win);
+ break;
+ case S3D_DISPLAY_INTERLACE:
+ wm_method_draw_stereo3d_interlace(win);
+ break;
+ case S3D_DISPLAY_PAGEFLIP:
+ wm_method_draw_stereo3d_pageflip(win);
+ break;
+ case S3D_DISPLAY_SIDEBYSIDE:
+ wm_method_draw_stereo3d_sidebyside(win);
+ break;
+ case S3D_DISPLAY_TOPBOTTOM:
+ wm_method_draw_stereo3d_topbottom(win);
+ break;
+ default:
+ break;
+ }
+}
+
+static bool wm_stereo3d_quadbuffer_supported(void)
+{
+ int gl_stereo = 0;
+ glGetBooleanv(GL_STEREO, (GLboolean *)&gl_stereo);
+ return gl_stereo != 0;
+}
+
+static bool wm_stereo3d_is_fullscreen_required(eStereoDisplayMode stereo_display)
+{
+ return ELEM(stereo_display,
+ S3D_DISPLAY_SIDEBYSIDE,
+ S3D_DISPLAY_TOPBOTTOM);
+}
+
+bool WM_stereo3d_enabled(wmWindow *win, bool skip_stereo3d_check)
+{
+ bScreen *screen = win->screen;
+
+ /* some 3d methods change the window arrangement, thus they shouldn't
+ * toggle on/off just because there is no 3d elements being drawn */
+ if (wm_stereo3d_is_fullscreen_required(win->stereo3d_format->display_mode)) {
+ return GHOST_GetWindowState(win->ghostwin) == GHOST_kWindowStateFullScreen;
+ }
+
+ if ((skip_stereo3d_check == false) && (ED_screen_stereo3d_required(screen) == false)) {
+ return false;
+ }
+
+ /* some 3d methods change the window arrangement, thus they shouldn't
+ * toggle on/off just because there is no 3d elements being drawn */
+ if (wm_stereo3d_is_fullscreen_required(win->stereo3d_format->display_mode)) {
+ return GHOST_GetWindowState(win->ghostwin) == GHOST_kWindowStateFullScreen;
+ }
+
+ return true;
+}
+
+/************************** Stereo 3D operator **********************************/
+typedef struct Stereo3dData {
+ Stereo3dFormat stereo3d_format;
+} Stereo3dData;
+
+static bool wm_stereo3d_set_properties(bContext *UNUSED(C), wmOperator *op)
+{
+ Stereo3dData *s3dd = op->customdata;
+ Stereo3dFormat *s3d = &s3dd->stereo3d_format;
+ PropertyRNA *prop;
+ bool is_set = false;
+
+ prop = RNA_struct_find_property(op->ptr, "display_mode");
+ if (RNA_property_is_set(op->ptr, prop)) {
+ s3d->display_mode = RNA_property_enum_get(op->ptr, prop);
+ is_set = true;
+ }
+
+ prop = RNA_struct_find_property(op->ptr, "anaglyph_type");
+ if (RNA_property_is_set(op->ptr, prop)) {
+ s3d->anaglyph_type = RNA_property_enum_get(op->ptr, prop);
+ is_set = true;
+ }
+
+ prop = RNA_struct_find_property(op->ptr, "interlace_type");
+ if (RNA_property_is_set(op->ptr, prop)) {
+ s3d->interlace_type = RNA_property_enum_get(op->ptr, prop);
+ is_set = true;
+ }
+
+ prop = RNA_struct_find_property(op->ptr, "use_interlace_swap");
+ if (RNA_property_is_set(op->ptr, prop)) {
+ if (RNA_property_boolean_get(op->ptr, prop))
+ s3d->flag |= S3D_INTERLACE_SWAP;
+ else
+ s3d->flag &= ~S3D_INTERLACE_SWAP;
+ is_set = true;
+ }
+
+ prop = RNA_struct_find_property(op->ptr, "use_sidebyside_crosseyed");
+ if (RNA_property_is_set(op->ptr, prop)) {
+ if (RNA_property_boolean_get(op->ptr, prop))
+ s3d->flag |= S3D_SIDEBYSIDE_CROSSEYED;
+ else
+ s3d->flag &= ~S3D_SIDEBYSIDE_CROSSEYED;
+ is_set = true;
+ }
+
+ return is_set;
+}
+
+static void wm_stereo3d_set_init(bContext *C, wmOperator *op)
+{
+ Stereo3dData *s3dd;
+ wmWindow *win = CTX_wm_window(C);
+
+ op->customdata = s3dd = MEM_callocN(sizeof(Stereo3dData), __func__);
+
+ /* store the original win stereo 3d settings in case of cancel */
+ s3dd->stereo3d_format = *win->stereo3d_format;
+}
+
+int wm_stereo3d_set_exec(bContext *C, wmOperator *op)
+{
+ wmWindowManager *wm = CTX_wm_manager(C);
+ wmWindow *win_src = CTX_wm_window(C);
+ wmWindow *win_dst = NULL;
+ const bool is_fullscreen = WM_window_is_fullscreen(win_src);
+ char prev_display_mode = win_src->stereo3d_format->display_mode;
+ Stereo3dData *s3dd;
+ bool ok = true;
+
+ if (G.background)
+ return OPERATOR_CANCELLED;
+
+ if (op->customdata == NULL) {
+ /* no invoke means we need to set the operator properties here */
+ wm_stereo3d_set_init(C, op);
+ wm_stereo3d_set_properties(C, op);
+ }
+
+ s3dd = op->customdata;
+ *win_src->stereo3d_format = s3dd->stereo3d_format;
+
+ if (prev_display_mode == S3D_DISPLAY_PAGEFLIP &&
+ prev_display_mode != win_src->stereo3d_format->display_mode)
+ {
+ /* in case the hardward supports pageflip but not the display */
+ if ((win_dst = wm_window_copy_test(C, win_src))) {
+ /* pass */
+ }
+ else {
+ BKE_report(op->reports, RPT_ERROR,
+ "Failed to create a window without quad-buffer support, you may experience flickering");
+ ok = false;
+ }
+ }
+ else if (win_src->stereo3d_format->display_mode == S3D_DISPLAY_PAGEFLIP) {
+ /* ED_screen_duplicate() can't handle other cases yet T44688 */
+ if (win_src->screen->state != SCREENNORMAL) {
+ BKE_report(op->reports, RPT_ERROR,
+ "Failed to switch to Time Sequential mode when in fullscreen");
+ ok = false;
+ }
+ /* pageflip requires a new window to be created with the proper OS flags */
+ else if ((win_dst = wm_window_copy_test(C, win_src))) {
+ if (wm_stereo3d_quadbuffer_supported()) {
+ BKE_report(op->reports, RPT_INFO, "Quad-buffer window successfully created");
+ }
+ else {
+ wm_window_close(C, wm, win_dst);
+ win_dst = NULL;
+ BKE_report(op->reports, RPT_ERROR, "Quad-buffer not supported by the system");
+ ok = false;
+ }
+ }
+ else {
+ BKE_report(op->reports, RPT_ERROR,
+ "Failed to create a window compatible with the time sequential display method");
+ ok = false;
+ }
+ }
+
+ if (wm_stereo3d_is_fullscreen_required(s3dd->stereo3d_format.display_mode)) {
+ if (!is_fullscreen) {
+ BKE_report(op->reports, RPT_INFO, "Stereo 3D Mode requires the window to be fullscreen");
+ }
+ }
+
+ MEM_freeN(op->customdata);
+
+ if (ok) {
+ if (win_dst) {
+ wm_window_close(C, wm, win_src);
+ }
+
+ WM_event_add_notifier(C, NC_WINDOW, NULL);
+ return OPERATOR_FINISHED;
+ }
+ else {
+ /* without this, the popup won't be freed freed properly T44688 */
+ CTX_wm_window_set(C, win_src);
+ win_src->stereo3d_format->display_mode = prev_display_mode;
+ return OPERATOR_CANCELLED;
+ }
+}
+
+int wm_stereo3d_set_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
+{
+ wm_stereo3d_set_init(C, op);
+
+ if (wm_stereo3d_set_properties(C, op))
+ return wm_stereo3d_set_exec(C, op);
+ else
+ return WM_operator_props_dialog_popup(C, op, 250, 100);
+}
+
+void wm_stereo3d_set_draw(bContext *UNUSED(C), wmOperator *op)
+{
+ Stereo3dData *s3dd = op->customdata;
+ PointerRNA stereo3d_format_ptr;
+ uiLayout *layout = op->layout;
+ uiLayout *col;
+
+ RNA_pointer_create(NULL, &RNA_Stereo3dDisplay, &s3dd->stereo3d_format, &stereo3d_format_ptr);
+
+ col = uiLayoutColumn(layout, false);
+ uiItemR(col, &stereo3d_format_ptr, "display_mode", 0, NULL, ICON_NONE);
+
+ switch (s3dd->stereo3d_format.display_mode) {
+ case S3D_DISPLAY_ANAGLYPH:
+ {
+ uiItemR(col, &stereo3d_format_ptr, "anaglyph_type", 0, NULL, ICON_NONE);
+ break;
+ }
+ case S3D_DISPLAY_INTERLACE:
+ {
+ uiItemR(col, &stereo3d_format_ptr, "interlace_type", 0, NULL, ICON_NONE);
+ uiItemR(col, &stereo3d_format_ptr, "use_interlace_swap", 0, NULL, ICON_NONE);
+ break;
+ }
+ case S3D_DISPLAY_SIDEBYSIDE:
+ {
+ uiItemR(col, &stereo3d_format_ptr, "use_sidebyside_crosseyed", 0, NULL, ICON_NONE);
+ /* fall-through */
+ }
+ case S3D_DISPLAY_PAGEFLIP:
+ case S3D_DISPLAY_TOPBOTTOM:
+ default:
+ {
+ break;
+ }
+ }
+}
+
+bool wm_stereo3d_set_check(bContext *UNUSED(C), wmOperator *UNUSED(op))
+{
+ /* the check function guarantees that the menu is updated to show the
+ * sub-options when an enum change (e.g., it shows the anaglyph options
+ * when anaglyph is on, and the interlace options when this is on */
+ return true;
+}
+
+void wm_stereo3d_set_cancel(bContext *UNUSED(C), wmOperator *op)
+{
+ MEM_freeN(op->customdata);
+ op->customdata = NULL;
+}
diff --git a/source/blender/windowmanager/intern/wm_subwindow.c b/source/blender/windowmanager/intern/wm_subwindow.c
index e26bcac9b1a..7dade62347c 100644
--- a/source/blender/windowmanager/intern/wm_subwindow.c
+++ b/source/blender/windowmanager/intern/wm_subwindow.c
@@ -45,21 +45,19 @@
#include "BLI_math.h"
#include "BLI_utildefines.h"
-#include "BKE_context.h"
-
#include "BIF_gl.h"
#include "GPU_extensions.h"
#include "WM_api.h"
#include "wm_subwindow.h"
-#include "wm_window.h"
-
-/* wmSubWindow stored in wmWindow... but not exposed outside this C file */
-/* it seems a bit redundant (area regions can store it too, but we keep it
- * because we can store all kind of future opengl fanciness here */
-/* we use indices and array because:
+/**
+ * \note #wmSubWindow stored in #wmWindow but not exposed outside this C file,
+ * it seems a bit redundant (area regions can store it too, but we keep it
+ * because we can store all kind of future opengl fanciness here.
+ *
+ * We use indices and array because:
* - index has safety, no pointers from this C file hanging around
* - fast lookups of indices with array, list would give overhead
* - old code used it this way...
@@ -368,7 +366,7 @@ static void wmOrtho2_offset(const float x, const float y, const float ofs)
*/
void wmOrtho2_region_pixelspace(const struct ARegion *ar)
{
- wmOrtho2_offset(ar->winx + 1, ar->winy + 1, -GLA_PIXEL_OFS);
+ wmOrtho2_offset(ar->winx, ar->winy, -0.01f);
}
void wmOrtho2_pixelspace(const float x, const float y)
@@ -461,25 +459,75 @@ void WM_framebuffer_index_set(int index)
cpack(col);
}
+void WM_framebuffer_index_get(int index, int *r_col)
+{
+ const int col = index_to_framebuffer(index);
+ char *c_col = (char *)r_col;
+ c_col[0] = (col & 0xFF); /* red */
+ c_col[1] = ((col >> 8) & 0xFF); /* green */
+ c_col[2] = ((col >> 16) & 0xFF); /* blue */
+ c_col[3] = 0xFF; /* alpha */
+}
+
+
+
+#define INDEX_FROM_BUF_8(col) (((col & 0xC00000) >> 18) + ((col & 0xC000) >> 12) + ((col & 0xC0) >> 6))
+#define INDEX_FROM_BUF_12(col) (((col & 0xF00000) >> 12) + ((col & 0xF000) >> 8) + ((col & 0xF0) >> 4))
+#define INDEX_FROM_BUF_15_16(col) (((col & 0xF80000) >> 9) + ((col & 0xF800) >> 6) + ((col & 0xF8) >> 3))
+#define INDEX_FROM_BUF_18(col) (((col & 0xFC0000) >> 6) + ((col & 0xFC00) >> 4) + ((col & 0xFC) >> 2))
+#define INDEX_FROM_BUF_24(col) (col & 0xFFFFFF)
+
int WM_framebuffer_to_index(unsigned int col)
{
- if (col == 0) return 0;
+ if (col == 0) {
+ return 0;
+ }
switch (GPU_color_depth()) {
- case 8:
- return ((col & 0xC00000) >> 18) + ((col & 0xC000) >> 12) + ((col & 0xC0) >> 6);
- case 12:
- return ((col & 0xF00000) >> 12) + ((col & 0xF000) >> 8) + ((col & 0xF0) >> 4);
+ case 8: return INDEX_FROM_BUF_8(col);
+ case 12: return INDEX_FROM_BUF_12(col);
case 15:
- case 16:
- return ((col & 0xF80000) >> 9) + ((col & 0xF800) >> 6) + ((col & 0xF8) >> 3);
- case 24:
- return col & 0xFFFFFF;
- default: // 18 bits...
- return ((col & 0xFC0000) >> 6) + ((col & 0xFC00) >> 4) + ((col & 0xFC) >> 2);
+ case 16: return INDEX_FROM_BUF_15_16(col);
+ case 24: return INDEX_FROM_BUF_24(col);
+ default: return INDEX_FROM_BUF_18(col);
}
}
+void WM_framebuffer_to_index_array(unsigned int *col, const unsigned int size)
+{
+#define INDEX_BUF_ARRAY(INDEX_FROM_BUF_BITS) \
+ for (i = size; i--; col++) { \
+ if ((c = *col)) { \
+ *col = INDEX_FROM_BUF_BITS(c); \
+ } \
+ } ((void)0)
+
+ if (size > 0) {
+ unsigned int i, c;
+
+ switch (GPU_color_depth()) {
+ case 8:
+ INDEX_BUF_ARRAY(INDEX_FROM_BUF_8);
+ break;
+ case 12:
+ INDEX_BUF_ARRAY(INDEX_FROM_BUF_12);
+ break;
+ case 15:
+ case 16:
+ INDEX_BUF_ARRAY(INDEX_FROM_BUF_15_16);
+ break;
+ case 24:
+ INDEX_BUF_ARRAY(INDEX_FROM_BUF_24);
+ break;
+ default:
+ INDEX_BUF_ARRAY(INDEX_FROM_BUF_18);
+ break;
+ }
+ }
+
+#undef INDEX_BUF_ARRAY
+}
+
/* ********** END MY WINDOW ************** */
diff --git a/source/blender/windowmanager/intern/wm_window.c b/source/blender/windowmanager/intern/wm_window.c
index 56e094891f5..0b0cedf5825 100644
--- a/source/blender/windowmanager/intern/wm_window.c
+++ b/source/blender/windowmanager/intern/wm_window.c
@@ -47,7 +47,7 @@
#include "BLI_blenlib.h"
#include "BLI_utildefines.h"
-#include "BLF_translation.h"
+#include "BLT_translation.h"
#include "BKE_blender.h"
#include "BKE_context.h"
@@ -55,7 +55,6 @@
#include "BKE_global.h"
#include "BKE_main.h"
-#include "BIF_gl.h"
#include "RNA_access.h"
@@ -74,8 +73,8 @@
#include "GPU_draw.h"
#include "GPU_extensions.h"
-
-#include "UI_interface.h"
+#include "GPU_init_exit.h"
+#include "GPU_glew.h"
/* for assert */
#ifndef NDEBUG
@@ -106,25 +105,25 @@ static struct WMInitStruct {
/* XXX this one should correctly check for apple top header...
* done for Cocoa : returns window contents (and not frame) max size*/
-void wm_get_screensize(int *width_r, int *height_r)
+void wm_get_screensize(int *r_width, int *r_height)
{
unsigned int uiwidth;
unsigned int uiheight;
GHOST_GetMainDisplayDimensions(g_system, &uiwidth, &uiheight);
- *width_r = uiwidth;
- *height_r = uiheight;
+ *r_width = uiwidth;
+ *r_height = uiheight;
}
/* size of all screens (desktop), useful since the mouse is bound by this */
-void wm_get_desktopsize(int *width_r, int *height_r)
+void wm_get_desktopsize(int *r_width, int *r_height)
{
unsigned int uiwidth;
unsigned int uiheight;
GHOST_GetAllDisplayDimensions(g_system, &uiwidth, &uiheight);
- *width_r = uiwidth;
- *height_r = uiheight;
+ *r_width = uiwidth;
+ *r_height = uiheight;
}
/* keeps offset and size within monitor bounds */
@@ -205,12 +204,13 @@ void wm_window_free(bContext *C, wmWindowManager *wm, wmWindow *win)
wm_event_free_all(win);
wm_subwindows_free(win);
-
- if (win->drawdata)
- MEM_freeN(win->drawdata);
-
+
+ wm_draw_data_free(win);
+
wm_ghostwindow_destroy(win);
-
+
+ MEM_freeN(win->stereo3d_format);
+
MEM_freeN(win);
}
@@ -235,32 +235,60 @@ wmWindow *wm_window_new(bContext *C)
BLI_addtail(&wm->windows, win);
win->winid = find_free_winid(wm);
+ win->stereo3d_format = MEM_callocN(sizeof(Stereo3dFormat), "Stereo 3D Format (window)");
+
return win;
}
/* part of wm_window.c api */
-wmWindow *wm_window_copy(bContext *C, wmWindow *winorig)
+wmWindow *wm_window_copy(bContext *C, wmWindow *win_src)
{
- wmWindow *win = wm_window_new(C);
+ wmWindow *win_dst = wm_window_new(C);
- win->posx = winorig->posx + 10;
- win->posy = winorig->posy;
- win->sizex = winorig->sizex;
- win->sizey = winorig->sizey;
+ win_dst->posx = win_src->posx + 10;
+ win_dst->posy = win_src->posy;
+ win_dst->sizex = win_src->sizex;
+ win_dst->sizey = win_src->sizey;
/* duplicate assigns to window */
- win->screen = ED_screen_duplicate(win, winorig->screen);
- BLI_strncpy(win->screenname, win->screen->id.name + 2, sizeof(win->screenname));
- win->screen->winid = win->winid;
+ win_dst->screen = ED_screen_duplicate(win_dst, win_src->screen);
+ BLI_strncpy(win_dst->screenname, win_dst->screen->id.name + 2, sizeof(win_dst->screenname));
+ win_dst->screen->winid = win_dst->winid;
- win->screen->do_refresh = true;
- win->screen->do_draw = true;
+ win_dst->screen->do_refresh = true;
+ win_dst->screen->do_draw = true;
- win->drawmethod = U.wmdrawmethod;
- win->drawdata = NULL;
-
- return win;
+ win_dst->drawmethod = U.wmdrawmethod;
+
+ BLI_listbase_clear(&win_dst->drawdata);
+
+ *win_dst->stereo3d_format = *win_src->stereo3d_format;
+
+ return win_dst;
+}
+
+/**
+ * A higher level version of copy that tests the new window can be added.
+ * (called from the operator directly)
+ */
+wmWindow *wm_window_copy_test(bContext *C, wmWindow *win_src)
+{
+ wmWindowManager *wm = CTX_wm_manager(C);
+ wmWindow *win_dst;
+
+ win_dst = wm_window_copy(C, win_src);
+
+ WM_check(C);
+
+ if (win_dst->ghostwin) {
+ WM_event_add_notifier(C, NC_WINDOW | NA_ADDED, NULL);
+ return win_dst;
+ }
+ else {
+ wm_window_close(C, wm, win_dst);
+ return NULL;
+ }
}
/* this is event from ghost, or exit-blender op */
@@ -319,8 +347,7 @@ void wm_window_title(wmWindowManager *wm, wmWindow *win)
/* nothing to do for 'temp' windows,
* because WM_window_open_temp always sets window title */
}
- else {
-
+ else if (win->ghostwin) {
/* this is set to 1 if you don't have startup.blend open */
if (G.save_over && G.main->name[0]) {
char str[sizeof(G.main->name) + 24];
@@ -339,10 +366,24 @@ void wm_window_title(wmWindowManager *wm, wmWindow *win)
}
}
+float wm_window_pixelsize(wmWindow *win)
+{
+ float pixelsize = GHOST_GetNativePixelSize(win->ghostwin);
+
+ switch (U.virtual_pixel) {
+ default:
+ case VIRTUAL_PIXEL_NATIVE:
+ return pixelsize;
+ case VIRTUAL_PIXEL_DOUBLE:
+ return 2.0f * pixelsize;
+ }
+}
+
/* belongs to below */
-static void wm_window_add_ghostwindow(const char *title, wmWindow *win)
+static void wm_window_add_ghostwindow(wmWindowManager *wm, const char *title, wmWindow *win)
{
GHOST_WindowHandle ghostwin;
+ GHOST_GLSettings glSettings = {0};
static int multisamples = -1;
int scr_w, scr_h, posy;
@@ -350,7 +391,20 @@ static void wm_window_add_ghostwindow(const char *title, wmWindow *win)
* mix it, either all windows have it, or none (tested in OSX opengl) */
if (multisamples == -1)
multisamples = U.ogl_multisamples;
-
+
+ glSettings.numOfAASamples = multisamples;
+
+ /* a new window is created when pageflip mode is required for a window */
+ if (win->stereo3d_format->display_mode == S3D_DISPLAY_PAGEFLIP)
+ glSettings.flags |= GHOST_glStereoVisual;
+
+ if (G.debug & G_DEBUG_GPU) {
+ glSettings.flags |= GHOST_glDebugContext;
+ }
+
+ if (!(U.uiflag2 & USER_OPENGL_NO_WARN_SUPPORT))
+ glSettings.flags |= GHOST_glWarnSupport;
+
wm_get_screensize(&scr_w, &scr_h);
posy = (scr_h - win->posy - win->sizey);
@@ -358,14 +412,16 @@ static void wm_window_add_ghostwindow(const char *title, wmWindow *win)
win->posx, posy, win->sizex, win->sizey,
(GHOST_TWindowState)win->windowstate,
GHOST_kDrawingContextTypeOpenGL,
- 0 /* no stereo */,
- multisamples /* AA */);
+ glSettings);
if (ghostwin) {
GHOST_RectangleHandle bounds;
+ /* the new window has already been made drawable upon creation */
+ wm->windrawable = win;
+
/* needed so we can detect the graphics card below */
- GPU_extensions_init();
+ GPU_init();
win->ghostwin = ghostwin;
GHOST_SetWindowUserData(ghostwin, win); /* pointer back */
@@ -397,7 +453,7 @@ static void wm_window_add_ghostwindow(const char *title, wmWindow *win)
/* displays with larger native pixels, like Macbook. Used to scale dpi with */
/* needed here, because it's used before it reads userdef */
- U.pixelsize = GHOST_GetNativePixelSize(win->ghostwin);
+ U.pixelsize = wm_window_pixelsize(win);
BKE_userdef_state();
wm_window_swap_buffers(win);
@@ -425,14 +481,13 @@ void wm_window_add_ghostwindows(wmWindowManager *wm)
if (wm_init_state.size_x == 0) {
wm_get_screensize(&wm_init_state.size_x, &wm_init_state.size_y);
- /* note!, this isnt quite correct, active screen maybe offset 1000s if PX,
- * we'd need a wm_get_screensize like function that gives offset,
- * in practice the window manager will likely move to the correct monitor */
- wm_init_state.start_x = 0;
- wm_init_state.start_y = 0;
+ /* note!, this isnt quite correct, active screen maybe offset 1000s if PX,
+ * we'd need a wm_get_screensize like function that gives offset,
+ * in practice the window manager will likely move to the correct monitor */
+ wm_init_state.start_x = 0;
+ wm_init_state.start_y = 0;
-
-#if !defined(__APPLE__) && !defined(WIN32) /* X11 */
+#ifdef WITH_X11 /* X11 */
/* X11, start maximized but use default sane size */
wm_init_state.size_x = min_ii(wm_init_state.size_x, WM_WIN_INIT_SIZE_X);
wm_init_state.size_y = min_ii(wm_init_state.size_y, WM_WIN_INIT_SIZE_Y);
@@ -461,7 +516,12 @@ void wm_window_add_ghostwindows(wmWindowManager *wm)
wm_init_state.override_flag &= ~WIN_OVERRIDE_WINSTATE;
}
- wm_window_add_ghostwindow("Blender", win);
+ /* without this, cursor restore may fail, T45456 */
+ if (win->cursor == 0) {
+ win->cursor = CURSOR_STD;
+ }
+
+ wm_window_add_ghostwindow(wm, "Blender", win);
}
/* happens after fileread */
if (win->eventstate == NULL)
@@ -499,8 +559,7 @@ wmWindow *WM_window_open(bContext *C, const rcti *rect)
win->sizey = BLI_rcti_size_y(rect);
win->drawmethod = U.wmdrawmethod;
- win->drawdata = NULL;
-
+
WM_check(C);
return win;
@@ -586,12 +645,12 @@ void WM_window_open_temp(bContext *C, rcti *position, int type)
/* operator callback */
int wm_window_duplicate_exec(bContext *C, wmOperator *UNUSED(op))
{
- wm_window_copy(C, CTX_wm_window(C));
- WM_check(C);
-
- WM_event_add_notifier(C, NC_WINDOW | NA_ADDED, NULL);
-
- return OPERATOR_FINISHED;
+ wmWindow *win_src = CTX_wm_window(C);
+ bool ok;
+
+ ok = (wm_window_copy_test(C, win_src) != NULL);
+
+ return ok ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
}
@@ -686,7 +745,7 @@ void wm_window_make_drawable(wmWindowManager *wm, wmWindow *win)
GHOST_ActivateWindowDrawingContext(win->ghostwin);
/* this can change per window */
- U.pixelsize = GHOST_GetNativePixelSize(win->ghostwin);
+ U.pixelsize = wm_window_pixelsize(win);
BKE_userdef_state();
}
}
@@ -958,9 +1017,12 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr C_void_ptr
#if defined(__APPLE__) || defined(WIN32)
/* OSX and Win32 don't return to the mainloop while resize */
- wm_event_do_handlers(C);
wm_event_do_notifiers(C);
wm_draw_update(C);
+
+ /* Warning! code above nulls 'C->wm.window', causing BGE to quit, see: T45699.
+ * Further, its easier to match behavior across platforms, so restore the window. */
+ CTX_wm_window_set(C, win);
#endif
}
}
@@ -1046,7 +1108,7 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr C_void_ptr
case GHOST_kEventNativeResolutionChange:
// printf("change, pixel size %f\n", GHOST_GetNativePixelSize(win->ghostwin));
- U.pixelsize = GHOST_GetNativePixelSize(win->ghostwin);
+ U.pixelsize = wm_window_pixelsize(win);
BKE_userdef_state();
WM_event_add_notifier(C, NC_SCREEN | NA_EDITED, NULL);
WM_event_add_notifier(C, NC_WINDOW | NA_EDITED, NULL);
@@ -1078,10 +1140,10 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr C_void_ptr
}
-/* This timer system only gives maximum 1 timer event per redraw cycle,
+/**
+ * This timer system only gives maximum 1 timer event per redraw cycle,
* to prevent queues to get overloaded.
- * Timer handlers should check for delta to decide if they just
- * update, or follow real time.
+ * Timer handlers should check for delta to decide if they just update, or follow real time.
* Timer handlers can also set duration to match frames passed
*/
static int wm_window_timer(const bContext *C)
@@ -1107,12 +1169,14 @@ static int wm_window_timer(const bContext *C)
wm_jobs_timer(C, wm, wt);
else if (wt->event_type == TIMERAUTOSAVE)
wm_autosave_timer(C, wm, wt);
+ else if (wt->event_type == TIMERNOTIFIER)
+ WM_main_add_notifier(GET_UINT_FROM_POINTER(wt->customdata), NULL);
else if (win) {
wmEvent event;
wm_event_init_from_window(win, &event);
event.type = wt->event_type;
- event.val = 0;
+ event.val = KM_NOTHING;
event.keymodifier = 0;
event.custom = EVT_DATA_TIMER;
event.customdata = wt;
@@ -1213,7 +1277,7 @@ void WM_event_timer_sleep(wmWindowManager *wm, wmWindow *UNUSED(win), wmTimer *t
wmTimer *WM_event_add_timer(wmWindowManager *wm, wmWindow *win, int event_type, double timestep)
{
wmTimer *wt = MEM_callocN(sizeof(wmTimer), "window timer");
-
+
wt->event_type = event_type;
wt->ltime = PIL_check_seconds_timer();
wt->ntime = wt->ltime + timestep;
@@ -1226,6 +1290,23 @@ wmTimer *WM_event_add_timer(wmWindowManager *wm, wmWindow *win, int event_type,
return wt;
}
+wmTimer *WM_event_add_timer_notifier(wmWindowManager *wm, wmWindow *win, unsigned int type, double timestep)
+{
+ wmTimer *wt = MEM_callocN(sizeof(wmTimer), "window timer");
+
+ wt->event_type = TIMERNOTIFIER;
+ wt->ltime = PIL_check_seconds_timer();
+ wt->ntime = wt->ltime + timestep;
+ wt->stime = wt->ltime;
+ wt->timestep = timestep;
+ wt->win = win;
+ wt->customdata = SET_UINT_IN_POINTER(type);
+
+ BLI_addtail(&wm->timers, wt);
+
+ return wt;
+}
+
void WM_event_remove_timer(wmWindowManager *wm, wmWindow *UNUSED(win), wmTimer *timer)
{
wmTimer *wt;
@@ -1258,6 +1339,12 @@ void WM_event_remove_timer(wmWindowManager *wm, wmWindow *UNUSED(win), wmTimer *
}
}
+void WM_event_remove_timer_notifier(wmWindowManager *wm, wmWindow *win, wmTimer *timer)
+{
+ timer->customdata = NULL;
+ WM_event_remove_timer(wm, win, timer);
+}
+
/* ******************* clipboard **************** */
static char *wm_clipboard_text_get_ex(bool selection, int *r_len,
@@ -1375,10 +1462,10 @@ void WM_progress_clear(wmWindow *win)
/* ************************************ */
-void wm_window_get_position(wmWindow *win, int *posx_r, int *posy_r)
+void wm_window_get_position(wmWindow *win, int *r_pos_x, int *r_pos_y)
{
- *posx_r = win->posx;
- *posy_r = win->posy;
+ *r_pos_x = win->posx;
+ *r_pos_y = win->posy;
}
void wm_window_set_size(wmWindow *win, int width, int height)
@@ -1413,9 +1500,9 @@ void wm_window_set_swap_interval (wmWindow *win, int interval)
GHOST_SetSwapInterval(win->ghostwin, interval);
}
-int wm_window_get_swap_interval (wmWindow *win)
+bool wm_window_get_swap_interval(wmWindow *win, int *intervalOut)
{
- return GHOST_GetSwapInterval(win->ghostwin);
+ return GHOST_GetSwapInterval(win->ghostwin, intervalOut);
}
@@ -1473,6 +1560,18 @@ void WM_cursor_warp(wmWindow *win, int x, int y)
}
/**
+ * Set x, y to values we can actually position the cursor to.
+ */
+void WM_cursor_compatible_xy(wmWindow *win, int *x, int *y)
+{
+ float f = GHOST_GetNativePixelSize(win->ghostwin);
+ if (f != 1.0f) {
+ *x = (int)(*x / f) * f;
+ *y = (int)(*y / f) * f;
+ }
+}
+
+/**
* Get the cursor pressure, in most cases you'll want to use wmTabletData from the event
*/
float WM_cursor_pressure(const struct wmWindow *win)
@@ -1509,3 +1608,21 @@ bool WM_window_is_fullscreen(wmWindow *win)
return win->windowstate == GHOST_kWindowStateFullScreen;
}
+
+#ifdef WITH_INPUT_IME
+/* note: keep in mind wm_window_IME_begin is also used to reposition the IME window */
+void wm_window_IME_begin(wmWindow *win, int x, int y, int w, int h, bool complete)
+{
+ BLI_assert(win);
+
+ GHOST_BeginIME(win->ghostwin, x, win->sizey - y, w, h, complete);
+}
+
+void wm_window_IME_end(wmWindow *win)
+{
+ BLI_assert(win && win->ime_data);
+
+ GHOST_EndIME(win->ghostwin);
+ win->ime_data = NULL;
+}
+#endif /* WITH_INPUT_IME */
diff --git a/source/blender/windowmanager/wm.h b/source/blender/windowmanager/wm.h
index de04129a0ef..2f06ddab1e8 100644
--- a/source/blender/windowmanager/wm.h
+++ b/source/blender/windowmanager/wm.h
@@ -76,6 +76,14 @@ void wm_autosave_delete(void);
void wm_autosave_read(bContext *C, struct ReportList *reports);
void wm_autosave_location(char *filepath);
+/* wm_stereo.c */
+void wm_method_draw_stereo3d(const bContext *C, wmWindow *win);
+int wm_stereo3d_set_exec(bContext *C, wmOperator *op);
+int wm_stereo3d_set_invoke(bContext *C, wmOperator *op, const wmEvent *event);
+void wm_stereo3d_set_draw(bContext *C, wmOperator *op);
+bool wm_stereo3d_set_check(bContext *C, wmOperator *op);
+void wm_stereo3d_set_cancel(bContext *C, wmOperator *op);
+
/* init operator properties */
void wm_open_init_load_ui(wmOperator *op, bool use_prefs);
void wm_open_init_use_scripts(wmOperator *op, bool use_prefs);
diff --git a/source/blender/windowmanager/wm_draw.h b/source/blender/windowmanager/wm_draw.h
index 3d72fe17c79..5dc52b2e4fb 100644
--- a/source/blender/windowmanager/wm_draw.h
+++ b/source/blender/windowmanager/wm_draw.h
@@ -32,6 +32,23 @@
#ifndef __WM_DRAW_H__
#define __WM_DRAW_H__
+#include "GPU_glew.h"
+
+
+#define MAX_N_TEX 3
+
+typedef struct wmDrawTriple {
+ GLuint bind[MAX_N_TEX * MAX_N_TEX];
+ int x[MAX_N_TEX], y[MAX_N_TEX];
+ int nx, ny;
+ GLenum target;
+} wmDrawTriple;
+
+typedef struct wmDrawData {
+ struct wmDrawData *next, *prev;
+ wmDrawTriple *triple;
+} wmDrawData;
+
struct bContext;
struct wmWindow;
struct ARegion;
@@ -43,5 +60,9 @@ void wm_draw_region_clear (struct wmWindow *win, struct ARegion *ar);
void wm_tag_redraw_overlay (struct wmWindow *win, struct ARegion *ar);
+void wm_triple_draw_textures (struct wmWindow *win, struct wmDrawTriple *triple, float alpha);
+
+void wm_draw_data_free (struct wmWindow *win);
+
#endif /* __WM_DRAW_H__ */
diff --git a/source/blender/windowmanager/wm_event_system.h b/source/blender/windowmanager/wm_event_system.h
index d1a94194108..efc01b1f8a8 100644
--- a/source/blender/windowmanager/wm_event_system.h
+++ b/source/blender/windowmanager/wm_event_system.h
@@ -45,8 +45,8 @@ struct ARegion;
typedef struct wmEventHandler {
struct wmEventHandler *next, *prev;
- int type; /* WM_HANDLER_DEFAULT, ... */
- int flag; /* WM_HANDLER_BLOCKING, ... */
+ char type; /* WM_HANDLER_DEFAULT, ... */
+ char flag; /* WM_HANDLER_BLOCKING, ... */
/* keymap handler */
wmKeyMap *keymap; /* pointer to builtin/custom keymaps */
@@ -56,6 +56,7 @@ typedef struct wmEventHandler {
wmOperator *op; /* for derived/modal handlers */
struct ScrArea *op_area; /* for derived/modal handlers */
struct ARegion *op_region; /* for derived/modal handlers */
+ short op_region_type; /* for derived/modal handlers */
/* ui handler */
wmUIHandlerFunc ui_handle; /* callback receiving events */
@@ -65,9 +66,6 @@ typedef struct wmEventHandler {
struct ARegion *ui_region; /* for derived/modal handlers */
struct ARegion *ui_menu; /* for derived/modal handlers */
- /* fileselect handler re-uses modal operator data */
- struct bScreen *filescreen; /* screen it started in, to validate exec */
-
/* drop box handler */
ListBase *dropboxes;
@@ -79,13 +77,6 @@ enum {
WM_HANDLER_FILESELECT
};
-/* handler flag */
-enum {
- WM_HANDLER_BLOCKING = (1 << 0), /* after this handler all others are ignored */
- WM_HANDLER_DO_FREE = (1 << 1), /* handler tagged to be freed in wm_handlers_do() */
- WM_HANDLER_ACCEPT_DBL_CLICK = (1 << 2), /* handler accepts double key press events */
-};
-
/* wm_event_system.c */
void wm_event_free_all (wmWindow *win);
void wm_event_free (wmEvent *event);
diff --git a/source/blender/windowmanager/wm_event_types.h b/source/blender/windowmanager/wm_event_types.h
index f50f98ed40c..390e769aa88 100644
--- a/source/blender/windowmanager/wm_event_types.h
+++ b/source/blender/windowmanager/wm_event_types.h
@@ -86,10 +86,19 @@ enum {
* paint and drawing tools however will want to handle these. */
INBETWEEN_MOUSEMOVE = 0x0011,
+/* IME event, GHOST_kEventImeCompositionStart in ghost */
+ WM_IME_COMPOSITE_START = 0x0014,
+/* IME event, GHOST_kEventImeComposition in ghost */
+ WM_IME_COMPOSITE_EVENT = 0x0015,
+/* IME event, GHOST_kEventImeCompositionEnd in ghost */
+ WM_IME_COMPOSITE_END = 0x0016,
+
/* *** Start of keyboard codes. *** */
/* standard keyboard.
* XXX from 0x0020 to 0x00ff, and 0x012c to 0x013f for function keys! */
+
+ /* NOTE: these values are saved in keymap files, do not change them but just add new ones */
AKEY = 0x0061, /* 'a' */
BKEY = 0x0062, /* 'b' */
CKEY = 0x0063, /* 'c' */
@@ -294,11 +303,16 @@ enum {
TIMERAUTOSAVE = 0x0115, /* timer event, autosave */
TIMERREPORT = 0x0116, /* timer event, reports */
TIMERREGION = 0x0117, /* timer event, region slide in/out */
+ TIMERNOTIFIER = 0x0118, /* timer event, notifier sender */
TIMERF = 0x011F, /* last timer */
/* Tweak, gestures: 0x500x, 0x501x */
EVT_ACTIONZONE_AREA = 0x5000,
EVT_ACTIONZONE_REGION = 0x5001,
+ EVT_ACTIONZONE_FULLSCREEN = 0x5011,
+
+ /* NOTE: these values are saved in keymap files, do not change them but just add new ones */
+
/* tweak events, for L M R mousebuttons */
EVT_TWEAK_L = 0x5002,
EVT_TWEAK_M = 0x5003,
@@ -308,6 +322,8 @@ enum {
EVT_TWEAK_S = 0x5006,
EVT_GESTURE = 0x5010,
+ /* 0x5011 is taken, see EVT_ACTIONZONE_FULLSCREEN */
+
/* Misc Blender internals: 0x502x */
EVT_FILESELECT = 0x5020,
EVT_BUT_OPEN = 0x5021,
@@ -354,10 +370,23 @@ enum {
(event_type >= LEFTCTRLKEY && event_type <= LEFTSHIFTKEY) == false && \
(event_type >= UNKNOWNKEY && event_type <= GRLESSKEY) == false)
+/* internal helpers*/
+#define _VA_IS_EVENT_MOD2(v, a) (CHECK_TYPE_INLINE(v, wmEvent *), \
+ ((v)->a))
+#define _VA_IS_EVENT_MOD3(v, a, b) \
+ (_VA_IS_EVENT_MOD2(v, a) || ((v)->b))
+#define _VA_IS_EVENT_MOD4(v, a, b, c) \
+ (_VA_IS_EVENT_MOD3(v, a, b) || ((v)->c))
+#define _VA_IS_EVENT_MOD5(v, a, b, c, d) \
+ (_VA_IS_EVENT_MOD4(v, a, b, c) || ((v)->d))
+
+/* reusable IS_EVENT_MOD(event, shift, ctrl, alt, oskey), macro */
+#define IS_EVENT_MOD(...) VA_NARGS_CALL_OVERLOAD(_VA_IS_EVENT_MOD, __VA_ARGS__)
/* ********** wmEvent.val ********** */
/* Gestures */
+/* NOTE: these values are saved in keymap files, do not change them but just add new ones */
enum {
/* value of tweaks and line gestures, note, KM_ANY (-1) works for this case too */
EVT_GESTURE_N = 1,
@@ -381,11 +410,10 @@ enum {
/* File select */
enum {
- EVT_FILESELECT_OPEN = 1,
- EVT_FILESELECT_FULL_OPEN = 2,
- EVT_FILESELECT_EXEC = 3,
- EVT_FILESELECT_CANCEL = 4,
- EVT_FILESELECT_EXTERNAL_CANCEL = 5,
+ EVT_FILESELECT_FULL_OPEN = 1,
+ EVT_FILESELECT_EXEC = 2,
+ EVT_FILESELECT_CANCEL = 3,
+ EVT_FILESELECT_EXTERNAL_CANCEL = 4,
};
/* Gesture */
diff --git a/source/blender/windowmanager/wm_files.h b/source/blender/windowmanager/wm_files.h
index 526696138a5..4b35f662a99 100644
--- a/source/blender/windowmanager/wm_files.h
+++ b/source/blender/windowmanager/wm_files.h
@@ -31,13 +31,14 @@
#ifndef __WM_FILES_H__
#define __WM_FILES_H__
-void wm_read_history(void);
+void wm_history_file_read(void);
+int wm_history_file_read_exec(bContext *C, wmOperator *op);
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, 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);
+void wm_file_read_report(bContext *C);
#endif /* __WM_FILES_H__ */
diff --git a/source/blender/windowmanager/wm_window.h b/source/blender/windowmanager/wm_window.h
index e0639b098a8..a104f6aba39 100644
--- a/source/blender/windowmanager/wm_window.h
+++ b/source/blender/windowmanager/wm_window.h
@@ -32,17 +32,18 @@
#ifndef __WM_WINDOW_H__
#define __WM_WINDOW_H__
-struct bScreen;
struct wmOperator;
/* *************** internal api ************** */
void wm_ghost_init (bContext *C);
void wm_ghost_exit(void);
-void wm_get_screensize(int *width_r, int *height_r);
-void wm_get_desktopsize(int *width_r, int *height_r);
+void wm_get_screensize(int *r_width, int *r_height);
+void wm_get_desktopsize(int *r_width, int *r_height);
wmWindow *wm_window_new (bContext *C);
+wmWindow *wm_window_copy (bContext *C, wmWindow *win_src);
+wmWindow *wm_window_copy_test (bContext *C, wmWindow *win_src);
void wm_window_free (bContext *C, wmWindowManager *wm, wmWindow *win);
void wm_window_close (bContext *C, wmWindowManager *wm, wmWindow *win);
@@ -56,17 +57,22 @@ void wm_window_make_drawable(wmWindowManager *wm, wmWindow *win);
void wm_window_raise (wmWindow *win);
void wm_window_lower (wmWindow *win);
void wm_window_set_size (wmWindow *win, int width, int height);
-void wm_window_get_position (wmWindow *win, int *posx_r, int *posy_r);
+void wm_window_get_position (wmWindow *win, int *r_pos_x, int *r_pos_y);
void wm_window_swap_buffers (wmWindow *win);
-void wm_window_set_swap_interval (wmWindow *win, int interval);
-int wm_window_get_swap_interval (wmWindow *win);
+void wm_window_set_swap_interval(wmWindow *win, int interval);
+bool wm_window_get_swap_interval(wmWindow *win, int *intervalOut);
-void wm_get_cursor_position (wmWindow *win, int *x, int *y);
+float wm_window_pixelsize(wmWindow *win);
-wmWindow *wm_window_copy (bContext *C, wmWindow *winorig);
+void wm_get_cursor_position (wmWindow *win, int *x, int *y);
void wm_window_testbreak (void);
+#ifdef WITH_INPUT_IME
+void wm_window_IME_begin (wmWindow *win, int x, int y, int w, int h, bool complete);
+void wm_window_IME_end (wmWindow *win);
+#endif
+
/* *************** window operators ************** */
int wm_window_duplicate_exec(bContext *C, struct wmOperator *op);
int wm_window_fullscreen_toggle_exec(bContext *C, struct wmOperator *op);
diff --git a/source/blenderplayer/CMakeLists.txt b/source/blenderplayer/CMakeLists.txt
index 188fb01d23d..af367467e00 100644
--- a/source/blenderplayer/CMakeLists.txt
+++ b/source/blenderplayer/CMakeLists.txt
@@ -56,6 +56,10 @@ if(WIN32 AND NOT UNIX)
add_executable(blenderplayer ${EXETYPE} bad_level_call_stubs/stubs.c ../icons/winblender.rc)
+ install(TARGETS blenderplayer
+ COMPONENT Blenderplayer
+ DESTINATION ".")
+
elseif(APPLE)
add_executable(blenderplayer ${EXETYPE} bad_level_call_stubs/stubs.c)
# setup Info.plist
@@ -69,6 +73,13 @@ elseif(APPLE)
else()
add_executable(blenderplayer bad_level_call_stubs/stubs.c)
+
+ if(NOT WITH_INSTALL_PORTABLE)
+ install(
+ TARGETS blenderplayer
+ DESTINATION bin
+ )
+ endif()
endif()
add_dependencies(blenderplayer makesdna)
@@ -95,6 +106,8 @@ endif()
bf_intern_ghostndof3dconnexion
bf_rna
bf_blenkernel
+ bf_depsgraph
+ bf_physics
bf_intern_rigidbody
bf_blenloader
ge_blen_routines
@@ -137,6 +150,7 @@ endif()
bf_dna
ge_videotex
bf_blenfont
+ bf_blentranslation
bf_intern_audaspace
blenkernel_blc
bf_bmesh
@@ -151,10 +165,13 @@ endif()
bf_intern_raskter
bf_intern_opencolorio
bf_intern_opennl
+ bf_intern_glew_mx
extern_rangetree
extern_wcwidth
extern_libmv
extern_glog
+ extern_sdlew
+ extern_eigen3
)
if(WITH_MOD_CLOTH_ELTOPO)
@@ -162,7 +179,7 @@ endif()
endif()
if(NOT WITH_SYSTEM_GLEW)
- list(APPEND BLENDER_SORTED_LIBS extern_glew)
+ list(APPEND BLENDER_SORTED_LIBS ${BLENDER_GLEW_LIBRARIES})
endif()
if(WITH_LZMA)
@@ -195,6 +212,10 @@ endif()
list(APPEND BLENDER_SORTED_LIBS bf_intern_locale)
endif()
+ if(WITH_OPENSUBDIV)
+ list(APPEND BLENDER_SORTED_LIBS bf_intern_opensubdiv)
+ endif()
+
foreach(SORTLIB ${BLENDER_SORTED_LIBS})
set(REMLIB ${SORTLIB})
foreach(SEARCHLIB ${BLENDER_LINK_LIBS})
diff --git a/source/blenderplayer/bad_level_call_stubs/stubs.c b/source/blenderplayer/bad_level_call_stubs/stubs.c
index 97e7d99c802..6d6489d6776 100644
--- a/source/blenderplayer/bad_level_call_stubs/stubs.c
+++ b/source/blenderplayer/bad_level_call_stubs/stubs.c
@@ -95,6 +95,7 @@ struct ScrArea;
struct SculptSession;
struct ShadeInput;
struct ShadeResult;
+struct SpaceButs;
struct SpaceClip;
struct SpaceImage;
struct SpaceNode;
@@ -142,6 +143,7 @@ struct wmWindowManager;
#include "../../intern/dualcon/dualcon.h"
#include "../../intern/elbeem/extern/elbeem.h"
#include "../blender/blenkernel/BKE_modifier.h"
+#include "../blender/blenkernel/BKE_paint.h"
#include "../blender/collada/collada.h"
#include "../blender/compositor/COM_compositor.h"
#include "../blender/editors/include/ED_armature.h"
@@ -162,12 +164,15 @@ struct wmWindowManager;
#include "../blender/editors/include/ED_render.h"
#include "../blender/editors/include/ED_screen.h"
#include "../blender/editors/include/ED_space_api.h"
+#include "../blender/editors/include/ED_text.h"
#include "../blender/editors/include/ED_transform.h"
+#include "../blender/editors/include/ED_uvedit.h"
#include "../blender/editors/include/ED_view3d.h"
#include "../blender/editors/include/UI_interface.h"
#include "../blender/editors/include/UI_interface_icons.h"
#include "../blender/editors/include/UI_resources.h"
#include "../blender/editors/include/UI_view2d.h"
+#include "../blender/freestyle/FRS_freestyle.h"
#include "../blender/python/BPY_extern.h"
#include "../blender/render/extern/include/RE_engine.h"
#include "../blender/render/extern/include/RE_pipeline.h"
@@ -215,10 +220,22 @@ void EDBM_mesh_load(struct Object *ob) RET_NONE
void EDBM_mesh_make(struct ToolSettings *ts, struct Object *ob) RET_NONE
void EDBM_mesh_normals_update(struct BMEditMesh *em) RET_NONE
void *g_system;
+bool EDBM_mtexpoly_check(struct BMEditMesh *em) RET_ZERO
-float *RE_RenderLayerGetPass(struct RenderLayer *rl, int passtype) RET_NULL
+float *RE_RenderLayerGetPass(volatile struct RenderLayer *rl, int passtype, const char *viewname) RET_NULL
float RE_filter_value(int type, float x) RET_ZERO
struct RenderLayer *RE_GetRenderLayer(struct RenderResult *rr, const char *name) RET_NULL
+void RE_init_texture_rng() RET_NONE
+void RE_exit_texture_rng() RET_NONE
+
+bool RE_layers_have_name(struct RenderResult *result) {STUB_ASSERT(0); return 0;}
+void RE_engine_active_view_set(struct RenderEngine *engine, const char *viewname) {STUB_ASSERT(0);}
+void RE_engine_get_camera_model_matrix(struct RenderEngine *engine, struct Object *camera, float *r_modelmat) {STUB_ASSERT(0);}
+float RE_engine_get_camera_shift_x(struct RenderEngine *engine, struct Object *camera) RET_ZERO
+void RE_SetActiveRenderView(struct Render *re, const char *viewname) {STUB_ASSERT(0);}
+
+struct RenderPass *RE_pass_find_by_type(volatile struct RenderLayer *rl, int passtype, const char *viewname) RET_NULL
+bool RE_HasFakeLayer(RenderResult *res) RET_ZERO
/* zbuf.c stub */
void antialias_tagbuf(int xsize, int ysize, char *rectmove) RET_NONE
@@ -229,22 +246,27 @@ void ibuf_sample(struct ImBuf *ibuf, float fx, float fy, float dx, float dy, flo
/* Freestyle */
bool ED_texture_context_check_linestyle(const struct bContext *C) RET_ZERO
+void FRS_free_view_map_cache(void) RET_NONE
/* texture.c */
-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) RET_ZERO
-int multitex_ext_safe(struct Tex *tex, float texvec[3], struct TexResult *texres, struct ImagePool *pool, bool scene_color_manage) RET_ZERO
+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, const bool skip_load_image) RET_ZERO
+int multitex_ext_safe(struct Tex *tex, float texvec[3], struct TexResult *texres, struct ImagePool *pool, bool scene_color_manage, const bool skip_load_image) RET_ZERO
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) RET_ZERO
struct Material *RE_init_sample_material(struct Material *orig_mat, struct Scene *scene) RET_NULL
void RE_free_sample_material(struct Material *mat) RET_NONE
-void RE_sample_material_color(struct Material *mat, float color[3], float *alpha, const float volume_co[3], const float surface_co[3],
- int face_index, short hit_quad, struct DerivedMesh *orcoDm, struct Object *ob) RET_NONE
-
+void RE_sample_material_color(
+ struct Material *mat, float color[3], float *alpha, const float volume_co[3], const float surface_co[3],
+ int tri_index, struct DerivedMesh *orcoDm, struct Object *ob) RET_NONE
/* nodes */
struct Render *RE_GetRender(const char *name) RET_NULL
+struct Object *RE_GetCamera(struct Render *re) RET_NULL
float RE_lamp_get_data(struct ShadeInput *shi, struct Object *lamp_obj, float col[4], float lv[3], float *dist, float shadow[4]) RET_ZERO
/* blenkernel */
+bool BKE_paint_proj_mesh_data_check(struct Scene *scene, struct Object *ob, bool *uvs, bool *mat, bool *tex, bool *stencil) RET_ZERO
+
+/* render */
void RE_FreeRenderResult(struct RenderResult *res) RET_NONE
void RE_FreeAllRenderResults(void) RET_NONE
struct RenderResult *RE_MultilayerConvert(void *exrhandle, const char *colorspace, bool predivide, int rectx, int recty) RET_NULL
@@ -252,7 +274,7 @@ struct Scene *RE_GetScene(struct Render *re) RET_NULL
void RE_Database_Free(struct Render *re) RET_NONE
void RE_FreeRender(struct Render *re) RET_NONE
void RE_DataBase_GetView(struct Render *re, float mat[4][4]) RET_NONE
-int externtex(struct MTex *mtex, const float vec[3], float *tin, float *tr, float *tg, float *tb, float *ta, const int thread, struct ImagePool *poold) RET_ZERO
+int externtex(struct MTex *mtex, const float vec[3], float *tin, float *tr, float *tg, float *tb, float *ta, const int thread, struct ImagePool *pool, const bool skip_load_image) RET_ZERO
float texture_value_blend(float tex, float out, float fact, float facg, int blendtype) RET_ZERO
void texture_rgb_blend(float in[3], const float tex[3], const float out[3], float fact, float facg, int blendtype) RET_NONE
const unsigned char stipple_quarttone[128];
@@ -286,12 +308,16 @@ void WM_cursor_modal_restore(struct wmWindow *win) RET_NONE
void WM_cursor_time(struct wmWindow *win, int nr) RET_NONE
void WM_cursor_warp(struct wmWindow *win, int x, int y) RET_NONE
+void WM_ndof_deadzone_set(float deadzone) RET_NONE
+
void WM_uilisttype_init(void) RET_NONE
struct uiListType *WM_uilisttype_find(const char *idname, bool quiet) RET_NULL
bool WM_uilisttype_add(struct uiListType *ult) RET_ZERO
void WM_uilisttype_freelink(struct uiListType *ult) RET_NONE
void WM_uilisttype_free(void) RET_NONE
+void WM_framebuffer_index_get(int index, int *r_col) RET_NONE
+
struct wmKeyMapItem *WM_keymap_item_find_id(struct wmKeyMap *keymap, int id) RET_NULL
int WM_enum_search_invoke(struct bContext *C, struct wmOperator *op, const struct wmEvent *event) RET_ZERO
void WM_event_add_notifier(const struct bContext *C, unsigned int type, void *reference) RET_NONE
@@ -327,9 +353,12 @@ struct ListBase *get_constraint_lb(struct Object *ob, struct bConstraint *con, s
bool ED_space_image_show_uvedit(struct SpaceImage *sima, struct Object *obedit) RET_ZERO
bool ED_space_image_show_render(struct SpaceImage *sima) RET_ZERO
bool ED_space_image_show_paint(struct SpaceImage *sima) RET_ZERO
-void ED_space_image_paint_update(struct wmWindowManager *wm, struct ToolSettings *settings) RET_NONE
+void ED_space_image_paint_update(struct wmWindowManager *wm, struct Scene *scene) RET_NONE
void ED_space_image_set(struct SpaceImage *sima, struct Scene *scene, struct Object *obedit, struct Image *ima) RET_NONE
-void ED_space_image_uv_sculpt_update(struct wmWindowManager *wm, struct ToolSettings *settings) RET_NONE
+void ED_space_image_uv_sculpt_update(struct wmWindowManager *wm, struct Scene *scene) RET_NONE
+void ED_space_image_scopes_update(const struct bContext *C, struct SpaceImage *sima, struct ImBuf *ibuf, bool use_view_settings) RET_NONE
+
+void ED_uvedit_get_aspect(struct Scene *scene, struct Object *ob, struct BMesh *em, float *aspx, float *aspy) RET_NONE
void ED_screen_set_scene(struct bContext *C, struct bScreen *screen, struct Scene *scene) RET_NONE
struct MovieClip *ED_space_clip_get_clip(struct SpaceClip *sc) RET_NULL
@@ -341,6 +370,16 @@ void ED_area_tag_redraw_regiontype(struct ScrArea *sa, int regiontype) RET_NONE
void ED_render_engine_changed(struct Main *bmain) RET_NONE
void ED_file_read_bookmarks(void) RET_NONE
+void ED_file_change_dir(struct bContext *C, const bool checkdir) RET_NONE
+void ED_preview_kill_jobs(struct wmWindowManager *wm, struct Main *bmain) RET_NONE
+struct FSMenu *ED_fsmenu_get(void) RET_NULL
+struct FSMenuEntry *ED_fsmenu_get_category(struct FSMenu *fsmenu, FSMenuCategory category) RET_NULL
+int ED_fsmenu_get_nentries(struct FSMenu *fsmenu, FSMenuCategory category) RET_ZERO
+struct FSMenuEntry *ED_fsmenu_get_entry(struct FSMenu *fsmenu, FSMenuCategory category, int index) RET_NULL
+char *ED_fsmenu_entry_get_path(struct FSMenuEntry *fsentry) RET_NULL
+void ED_fsmenu_entry_set_path(struct FSMenuEntry *fsentry, const char *name) RET_NONE
+char *ED_fsmenu_entry_get_name(struct FSMenuEntry *fsentry) RET_NULL
+void ED_fsmenu_entry_set_name(struct FSMenuEntry *fsentry, const char *name) RET_NONE
struct PTCacheEdit *PE_get_current(struct Scene *scene, struct Object *ob) RET_NULL
void PE_current_changed(struct Scene *scene, struct Object *ob) RET_NONE
@@ -365,7 +404,6 @@ int WM_keymap_map_type_get(struct wmKeyMapItem *kmi) RET_ZERO
/* rna editors */
-struct EditMesh;
struct FCurve *verify_fcurve(struct bAction *act, const char group[], struct PointerRNA *ptr, const char rna_path[], const int array_index, short add) RET_NULL
int insert_vert_fcurve(struct FCurve *fcu, float x, float y, short flag) RET_ZERO
@@ -380,7 +418,7 @@ short ANIM_validate_keyingset(struct bContext *C, struct ListBase *dsources, str
int ANIM_add_driver(struct ReportList *reports, struct ID *id, const char rna_path[], int array_index, short flag, int type) RET_ZERO
bool ANIM_remove_driver(struct ReportList *reports, struct ID *id, const char rna_path[], int array_index, short flag) RET_ZERO
void ED_space_image_release_buffer(struct SpaceImage *sima, struct ImBuf *ibuf, void *lock) RET_NONE
-struct ImBuf *ED_space_image_acquire_buffer(struct SpaceImage *sima, void **lock_r) RET_NULL
+struct ImBuf *ED_space_image_acquire_buffer(struct SpaceImage *sima, void **r_lock) RET_NULL
void ED_space_image_get_zoom(struct SpaceImage *sima, struct ARegion *ar, float *zoomx, float *zoomy) RET_NONE
const char *ED_info_stats_string(struct Scene *scene) RET_NULL
void ED_area_tag_redraw(struct ScrArea *sa) RET_NONE
@@ -436,7 +474,7 @@ void uiLayoutSetEnabled(uiLayout *layout, bool enabled) RET_NONE
void uiLayoutSetAlignment(uiLayout *layout, char alignment) RET_NONE
void uiLayoutSetScaleX(struct uiLayout *layout, float scale) RET_NONE
void uiLayoutSetScaleY(struct uiLayout *layout, float scale) RET_NONE
-void uiTemplateIconView(struct uiLayout *layout, struct PointerRNA *ptr, const char *propname) RET_NONE
+void uiTemplateIconView(struct uiLayout *layout, struct PointerRNA *ptr, const char *propname, int show_labels, float icon_scale) RET_NONE
void ED_base_object_free_and_unlink(struct Main *bmain, struct Scene *scene, struct Base *base) RET_NONE
void ED_mesh_update(struct Mesh *mesh, struct bContext *C, int calc_edges, int calc_tessface) RET_NONE
void ED_mesh_vertices_add(struct Mesh *mesh, struct ReportList *reports, int count) RET_NONE
@@ -452,14 +490,12 @@ int ED_mesh_uv_texture_add(struct Mesh *me, const char *name, const bool active_
bool ED_mesh_color_remove_named(struct Mesh *me, const char *name) RET_ZERO
bool ED_mesh_uv_texture_remove_named(struct Mesh *me, const char *name) RET_ZERO
void ED_object_constraint_dependency_update(struct Main *bmain, struct Object *ob) RET_NONE
+void ED_object_constraint_dependency_tag_update(struct Main *bmain, struct Object *ob, struct bConstraint *con) RET_NONE
void ED_object_constraint_update(struct Object *ob) RET_NONE
-struct bDeformGroup *ED_vgroup_add_name(struct Object *ob, const char *name) RET_NULL
+void ED_object_constraint_tag_update(struct Object *ob, struct bConstraint *con) RET_NONE
void ED_vgroup_vert_add(struct Object *ob, struct bDeformGroup *dg, int vertnum, float weight, int assignmode) RET_NONE
void ED_vgroup_vert_remove(struct Object *ob, struct bDeformGroup *dg, int vertnum) RET_NONE
float ED_vgroup_vert_weight(struct Object *ob, struct bDeformGroup *dg, int vertnum) RET_ZERO
-void ED_vgroup_delete(struct Object *ob, struct bDeformGroup *defgroup) RET_NONE
-void ED_vgroup_clear(struct Object *ob) RET_NONE
-bool ED_vgroup_object_is_edit_mode(struct Object *ob) RET_ZERO
int ED_mesh_mirror_topo_table(struct Object *ob, char mode) RET_ZERO
int ED_mesh_mirror_spatial_table(struct Object *ob, struct BMEditMesh *em, const float co[3], char mode) RET_ZERO
@@ -473,6 +509,8 @@ bool ED_texture_context_check_lamp(const struct bContext *C) RET_ZERO
bool ED_texture_context_check_particles(const struct bContext *C) RET_ZERO
bool ED_texture_context_check_others(const struct bContext *C) RET_ZERO
+bool ED_text_region_location_from_cursor(SpaceText *st, ARegion *ar, const int cursor_co[2], int r_pixel_co[2]) RET_ZERO
+
bool snapObjectsRayEx(struct Scene *scene, struct Base *base_act, struct View3D *v3d, struct ARegion *ar, struct Object *obedit, short snap_mode,
struct Object **r_ob, float r_obmat[4][4],
const float ray_start[3], const float ray_normal[3], float *r_ray_dist,
@@ -497,6 +535,7 @@ struct uiLayout *uiLayoutSplit(uiLayout *layout, float percentage, int align) RE
bool uiLayoutGetRedAlert(struct uiLayout *layout) RET_ZERO
void uiLayoutSetRedAlert(uiLayout *layout, bool redalert) RET_NONE
void uiItemsEnumR(uiLayout *layout, struct PointerRNA *ptr, const char *propname) RET_NONE
+void uiItemMenuEnumR_prop(uiLayout *layout, struct PointerRNA *ptr, PropertyRNA *prop, const char *name, int icon) RET_NONE
void uiItemMenuEnumR(uiLayout *layout, struct PointerRNA *ptr, const char *propname, const char *name, int icon) RET_NONE
void uiItemEnumR_string(uiLayout *layout, struct PointerRNA *ptr, const char *propname, const char *value, const char *name, int icon) RET_NONE
void uiItemPointerR(uiLayout *layout, struct PointerRNA *ptr, const char *propname, struct PointerRNA *searchptr, const char *searchpropname, const char *name, int icon) RET_NONE
@@ -533,12 +572,12 @@ void uiTemplateLayers(uiLayout *layout, struct PointerRNA *ptr, const char *prop
void uiTemplateImageLayers(struct uiLayout *layout, struct bContext *C, struct Image *ima, struct ImageUser *iuser) RET_NONE
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) RET_NONE
+ const char *item_dyntip_propname, int rows, int maxrows, int layout_type, int columns) RET_NONE
void uiTemplateRunningJobs(struct uiLayout *layout, struct bContext *C) RET_NONE
void uiTemplateOperatorSearch(struct uiLayout *layout) RET_NONE
void uiTemplateHeader3D(struct uiLayout *layout, struct bContext *C) RET_NONE
void uiTemplateEditModeSelection(struct uiLayout *layout, struct bContext *C) RET_NONE
-void uiTemplateImage(uiLayout *layout, struct bContext *C, struct PointerRNA *ptr, const char *propname, struct PointerRNA *userptr, int compact) RET_NONE
+void uiTemplateImage(uiLayout *layout, struct bContext *C, struct PointerRNA *ptr, const char *propname, struct PointerRNA *userptr, int compact, int multiview) RET_NONE
void uiTemplateColorPicker(uiLayout *layout, struct PointerRNA *ptr, const char *propname, int value_slider, int lock, int lock_luminosity, int cubic) RET_NONE
void uiTemplateHistogram(uiLayout *layout, struct PointerRNA *ptr, const char *propname) RET_NONE
void uiTemplateReportsBanner(uiLayout *layout, struct bContext *C) RET_NONE
@@ -559,20 +598,22 @@ void uiTemplateColormanagedViewSettings(struct uiLayout *layout, struct bContext
void uiTemplateComponentMenu(struct uiLayout *layout, struct PointerRNA *ptr, const char *propname, const char *name) RET_NONE
void uiTemplateNodeSocket(struct uiLayout *layout, struct bContext *C, float *color) RET_NONE
void uiTemplatePalette(struct uiLayout *layout, struct PointerRNA *ptr, const char *propname, int color) RET_NONE
+void uiTemplateImageStereo3d(struct uiLayout *layout, struct PointerRNA *stereo3d_format_ptr) RET_NONE
/* rna render */
-struct RenderResult *RE_engine_begin_result(RenderEngine *engine, int x, int y, int w, int h, const char *layername) RET_NULL
+struct RenderResult *RE_engine_begin_result(RenderEngine *engine, int x, int y, int w, int h, const char *layername, const char *viewname) RET_NULL
struct RenderResult *RE_AcquireResultRead(struct Render *re) RET_NULL
struct RenderResult *RE_AcquireResultWrite(struct Render *re) RET_NULL
struct RenderStats *RE_GetStats(struct Render *re) RET_NULL
struct RenderData *RE_engine_get_render_data(struct Render *re) RET_NULL
void RE_engine_update_result(struct RenderEngine *engine, struct RenderResult *result) RET_NONE
void RE_engine_update_progress(struct RenderEngine *engine, float progress) RET_NONE
+void RE_engine_set_error_message(RenderEngine *engine, const char *msg) RET_NONE
void RE_engine_end_result(RenderEngine *engine, struct RenderResult *result, int cancel, int merge_results) RET_NONE
void RE_engine_update_stats(RenderEngine *engine, const char *stats, const char *info) RET_NONE
void RE_layer_load_from_file(struct RenderLayer *layer, struct ReportList *reports, const char *filename, int x, int y) RET_NONE
void RE_result_load_from_file(struct RenderResult *result, struct ReportList *reports, const char *filename) RET_NONE
-void RE_AcquireResultImage(struct Render *re, struct RenderResult *rr) RET_NONE
+void RE_AcquireResultImage(struct Render *re, struct RenderResult *rr, const int view_id) RET_NONE
void RE_ReleaseResult(struct Render *re) RET_NONE
void RE_ReleaseResultImage(struct Render *re) RET_NONE
int RE_engine_test_break(struct RenderEngine *engine) RET_ZERO
@@ -586,10 +627,13 @@ void RE_engine_update_memory_stats(struct RenderEngine *engine, float mem_used,
struct RenderEngine *RE_engine_create(struct RenderEngineType *type) RET_NULL
void RE_engine_frame_set(struct RenderEngine *engine, int frame, float subframe) RET_NONE
void RE_FreePersistentData(void) RET_NONE
+void RE_sample_point_density(struct Scene *scene, struct PointDensity *pd, int resolution, float *values) RET_NONE;
+void RE_instance_get_particle_info(struct ObjectInstanceRen *obi, float *index, float *age, float *lifetime, float co[3], float *size, float vel[3], float angvel[3]) RET_NONE
+void RE_FreeAllPersistentData(void) RET_NONE
/* python */
struct wmOperatorType *WM_operatortype_find(const char *idname, bool quiet) RET_NULL
-struct GHashIterator *WM_operatortype_iter() RET_NULL
+void WM_operatortype_iter(struct GHashIterator *ghi) RET_NONE
struct wmOperatorTypeMacro *WM_operatortype_macro_define(struct wmOperatorType *ot, const char *idname) RET_NULL
int WM_operator_call_py(struct bContext *C, struct wmOperatorType *ot, short context, struct PointerRNA *properties, struct ReportList *reports, const bool is_undo) RET_ZERO
void WM_operatortype_remove_ptr(struct wmOperatorType *ot) RET_NONE
@@ -609,21 +653,22 @@ int WM_operator_ui_popup(struct bContext *C, struct wmOperator *op, int width, i
void update_autoflags_fcurve(struct FCurve *fcu, struct bContext *C, struct ReportList *reports, struct PointerRNA *ptr) RET_NONE
short insert_keyframe(struct ReportList *reports, struct ID *id, struct bAction *act, const char group[], const char rna_path[], int array_index, float cfra, short flag) RET_ZERO
short delete_keyframe(struct ReportList *reports, struct ID *id, struct bAction *act, const char group[], const char rna_path[], int array_index, float cfra, short flag) RET_ZERO
+struct bAction *verify_adt_action(struct ID *id, short add) RET_NULL
char *WM_operator_pystring_ex(struct bContext *C, struct wmOperator *op, const bool all_args, const bool macro_args, struct wmOperatorType *ot, struct PointerRNA *opptr) RET_NULL
char *WM_operator_pystring(struct bContext *C, struct wmOperator *op, const bool all_args, const bool macro_args) RET_NULL
struct wmKeyMapItem *WM_modalkeymap_add_item(struct wmKeyMap *km, int type, int val, int modifier, int keymodifier, int value) RET_NULL
struct wmKeyMapItem *WM_modalkeymap_add_item_str(struct wmKeyMap *km, int type, int val, int modifier, int keymodifier, const char *value) RET_NULL
struct wmKeyMap *WM_modalkeymap_add(struct wmKeyConfig *keyconf, const char *idname, struct EnumPropertyItem *items) RET_NULL
-struct uiPopupMenu *uiPupMenuBegin(struct bContext *C, const char *title, int icon) RET_NULL
-void uiPupMenuEnd(struct bContext *C, struct uiPopupMenu *head) RET_NONE
-struct uiLayout *uiPupMenuLayout(struct uiPopupMenu *head) RET_NULL
-struct uiLayout *uiPieMenuLayout(struct uiPieMenu *pie) RET_NULL
-void uiPieMenuInvoke(struct bContext *C, const char *idname, const struct wmEvent *event) RET_NONE
-struct uiPieMenu *uiPieMenuBegin(struct bContext *C, const char *title, int icon, const struct wmEvent *event) RET_NULL
-void uiPieMenuEnd(struct bContext *C, uiPieMenu *pie) RET_NONE
+struct uiPopupMenu *UI_popup_menu_begin(struct bContext *C, const char *title, int icon) RET_NULL
+void UI_popup_menu_end(struct bContext *C, struct uiPopupMenu *head) RET_NONE
+struct uiLayout *UI_popup_menu_layout(struct uiPopupMenu *head) RET_NULL
+struct uiLayout *UI_pie_menu_layout(struct uiPieMenu *pie) RET_NULL
+int UI_pie_menu_invoke(struct bContext *C, const char *idname, const struct wmEvent *event) RET_ZERO
+struct uiPieMenu *UI_pie_menu_begin(struct bContext *C, const char *title, int icon, const struct wmEvent *event) RET_NULL
+void UI_pie_menu_end(struct bContext *C, uiPieMenu *pie) RET_NONE
struct uiLayout *uiLayoutRadial(struct uiLayout *layout) RET_NULL
-void uiPieOperatorEnumInvoke(struct bContext *C, const char *title, const char *opname,
- const char *propname, const struct wmEvent *event) RET_NONE
+int UI_pie_menu_invoke_from_operator_enum(struct bContext *C, const char *title, const char *opname,
+ const char *propname, const struct wmEvent *event) RET_ZERO
/* RNA COLLADA dependency */
int collada_export(struct Scene *sce,
@@ -648,7 +693,7 @@ int collada_export(struct Scene *sce,
BC_export_transformation_type export_transformation_type,
int open_sim) RET_ZERO
-void ED_mesh_calc_tessface(struct Mesh *mesh) RET_NONE
+void ED_mesh_calc_tessface(struct Mesh *mesh, bool free_mpoly) RET_NONE
/* bpy/python internal api */
void operator_wrapper(struct wmOperatorType *ot, void *userdata) RET_NONE
@@ -686,6 +731,11 @@ struct CCLDeviceInfo *CCL_compute_device_list(int opencl) RET_NULL
/* compositor */
void COM_execute(RenderData *rd, Scene *scene, bNodeTree *editingtree, int rendering,
- const ColorManagedViewSettings *viewSettings, const ColorManagedDisplaySettings *displaySettings) RET_NONE
+ const ColorManagedViewSettings *viewSettings, const ColorManagedDisplaySettings *displaySettings,
+ const char *viewName) RET_NONE
+
+/*multiview*/
+bool RE_RenderResult_is_stereo(RenderResult *res) RET_ZERO
+void uiTemplateImageViews(uiLayout *layout, struct PointerRNA *imfptr) RET_NONE
#endif // WITH_GAMEENGINE
diff --git a/source/creator/CMakeLists.txt b/source/creator/CMakeLists.txt
index 35cbff33342..a3589175197 100644
--- a/source/creator/CMakeLists.txt
+++ b/source/creator/CMakeLists.txt
@@ -27,9 +27,11 @@ setup_libdirs()
blender_include_dirs(
../../intern/guardedalloc
+ ../../intern/glew-mx
../blender/blenlib
../blender/blenkernel
../blender/blenloader
+ ../blender/depsgraph
../blender/editors/include
../blender/makesrna
../blender/imbuf
@@ -39,6 +41,9 @@ blender_include_dirs(
../blender/windowmanager
)
+add_definitions(${GL_DEFINITIONS})
+blender_include_dirs("${GLEW_INCLUDE_PATH}")
+
if(WIN32)
blender_include_dirs(../../intern/utfconv)
endif()
@@ -77,6 +82,10 @@ if(WITH_GAMEENGINE)
endif()
if(WITH_SDL)
+ if(WITH_SDL_DYNLOAD)
+ add_definitions(-DWITH_SDL_DYNLOAD)
+ blender_include_dirs(../../extern/sdlew/include)
+ endif()
add_definitions(-DWITH_SDL)
endif()
@@ -156,20 +165,27 @@ if(WITH_BUILDINFO)
# except when used as an include path.
# include the output directory, where the buildinfo.h file is generated
- include_directories(${CMAKE_BINARY_DIR}/source/creator)
+ include_directories(${CMAKE_CURRENT_BINARY_DIR})
+
+
+ # XXX, "_buildinfo.h" is used twice here,
+ # because we rely on that file being detected as missing
+ # every build so that the real header "buildinfo.h" is updated.
+ #
+ # Keep this until we find a better way to resolve!
# a custom target that is always built
add_custom_target(buildinfo ALL
- DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/buildinfo.h)
+ DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/_buildinfo.h)
- # creates svnheader.h using cmake script
- add_custom_command(OUTPUT ${CMAKE_CURRENT_SOURCE_DIR}/buildinfo.h
+ # creates buildinfo.h using cmake script
+ add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/_buildinfo.h
COMMAND ${CMAKE_COMMAND}
-DSOURCE_DIR=${CMAKE_SOURCE_DIR}
-P ${CMAKE_SOURCE_DIR}/build_files/cmake/buildinfo.cmake)
# buildinfo.h is a generated file
- set_source_files_properties(${CMAKE_CURRENT_SOURCE_DIR}/buildinfo.h
+ set_source_files_properties(${CMAKE_CURRENT_BINARY_DIR}/buildinfo.h
PROPERTIES GENERATED TRUE
HEADER_FILE_ONLY TRUE)
@@ -207,6 +223,7 @@ if(WITH_PYTHON_MODULE)
set_target_properties(
blender
PROPERTIES
+ MACOSX_BUNDLE
LINK_FLAGS_RELEASE "${PLATFORM_LINKFLAGS}"
LINK_FLAGS_DEBUG "${PLATFORM_LINKFLAGS_DEBUG}"
)
@@ -230,23 +247,13 @@ if(WITH_BUILDINFO)
add_dependencies(blender buildinfo)
endif()
-# Post build steps for bundling/packaging.
-
-
-if(MSVC_IDE)
- # ${CMAKE_CFG_INTDIR} should replace \${BUILD_TYPE} when using add_command
- set(TARGETDIR ${EXECUTABLE_OUTPUT_PATH}/\${BUILD_TYPE})
-elseif(APPLE)
- set(TARGETDIR ${EXECUTABLE_OUTPUT_PATH}/\${BUILD_TYPE})
-else()
- set(TARGETDIR ${EXECUTABLE_OUTPUT_PATH})
-endif()
set(BLENDER_TEXT_FILES
${CMAKE_SOURCE_DIR}/release/text/GPL-license.txt
${CMAKE_SOURCE_DIR}/release/text/Python-license.txt
${CMAKE_SOURCE_DIR}/release/text/copyright.txt
- ${CMAKE_SOURCE_DIR}/release/text/readme.html
+ # generate this file
+ # ${CMAKE_SOURCE_DIR}/release/text/readme.html
${CMAKE_SOURCE_DIR}/release/datafiles/LICENSE-bfont.ttf.txt
)
@@ -262,24 +269,28 @@ endif()
# Platform Specific Var: TARGETDIR_VER
if(UNIX AND NOT APPLE)
- if(WITH_INSTALL_PORTABLE)
- set(TARGETDIR_VER ${TARGETDIR}/${BLENDER_VERSION})
+ if(WITH_PYTHON_MODULE)
+ if(WITH_INSTALL_PORTABLE)
+ set(TARGETDIR_VER ${BLENDER_VERSION})
+ else()
+ set(TARGETDIR_VER ${PYTHON_SITE_PACKAGES}/${BLENDER_VERSION})
+ endif()
else()
- if(WITH_PYTHON_MODULE)
- set(TARGETDIR_VER ${PYTHON_LIBPATH}/python${PYTHON_VERSION}/site-packages/${BLENDER_VERSION})
+ if(WITH_INSTALL_PORTABLE)
+ set(TARGETDIR_VER ${BLENDER_VERSION})
else()
- set(TARGETDIR_VER ${CMAKE_INSTALL_PREFIX}/share/blender/${BLENDER_VERSION})
+ set(TARGETDIR_VER share/blender/${BLENDER_VERSION})
endif()
endif()
elseif(WIN32)
- set(TARGETDIR_VER ${TARGETDIR}/${BLENDER_VERSION})
+ set(TARGETDIR_VER ${BLENDER_VERSION})
elseif(APPLE)
if(WITH_PYTHON_MODULE)
- set(TARGETDIR_VER ${TARGETDIR}/${BLENDER_VERSION})
+ set(TARGETDIR_VER ${BLENDER_VERSION})
else()
- set(TARGETDIR_VER ${TARGETDIR}/blender.app/Contents/Resources/${BLENDER_VERSION})
+ set(TARGETDIR_VER blender.app/Contents/Resources/${BLENDER_VERSION})
endif()
endif()
@@ -397,74 +408,74 @@ endif()
if(UNIX AND NOT APPLE)
if(NOT WITH_PYTHON_MODULE)
- install(
- CODE
- "
- execute_process(COMMAND
- ${CMAKE_SOURCE_DIR}/doc/manpage/blender.1.py
- ${TARGETDIR}/blender
- ${TARGETDIR}/blender.1)
- "
- )
+ if(WITH_DOC_MANPAGE)
+ add_custom_target(
+ blender_man_page ALL
+ COMMAND ${CMAKE_SOURCE_DIR}/doc/manpage/blender.1.py
+ ${EXECUTABLE_OUTPUT_PATH}/blender
+ ${CMAKE_CURRENT_BINARY_DIR}/blender.1)
+ add_dependencies(blender_man_page blender)
+ endif()
endif()
# there are a few differences between portable and system install
- if(WITH_INSTALL_PORTABLE)
+ if(WITH_PYTHON_MODULE)
+ if(WITH_INSTALL_PORTABLE)
+ install(
+ TARGETS blender
+ DESTINATION "."
+ )
+ else()
+ install(
+ TARGETS blender
+ LIBRARY DESTINATION ${PYTHON_SITE_PACKAGES}
+ )
+ endif()
+ # none of the other files are needed currently
+ elseif(WITH_INSTALL_PORTABLE)
install(
- FILES ${TARGETDIR}/blender.1
- DESTINATION ${TARGETDIR}
+ TARGETS blender
+ DESTINATION "."
)
+ if(WITH_DOC_MANPAGE)
+ install(
+ FILES ${CMAKE_CURRENT_BINARY_DIR}/blender.1
+ DESTINATION "."
+ )
+ endif()
install(
FILES
${CMAKE_SOURCE_DIR}/release/freedesktop/blender.desktop
${CMAKE_SOURCE_DIR}/release/freedesktop/icons/scalable/apps/blender.svg
- DESTINATION ${TARGETDIR}
+ DESTINATION "."
)
install(
PROGRAMS
${CMAKE_SOURCE_DIR}/release/bin/blender-thumbnailer.py
- DESTINATION ${TARGETDIR}
- )
-
- install(
- FILES ${BLENDER_TEXT_FILES}
- DESTINATION ${TARGETDIR}
+ DESTINATION "."
)
+ set(BLENDER_TEXT_FILES_DESTINATION ".")
else()
# main blender binary
- if(WITH_PYTHON_MODULE)
- install(
- TARGETS blender
- LIBRARY
- DESTINATION ${PYTHON_LIBPATH}/python${PYTHON_VERSION}/site-packages
- )
- else()
- install(
- PROGRAMS ${TARGETDIR}/blender
- DESTINATION ${CMAKE_INSTALL_PREFIX}/bin
- )
+ install(
+ TARGETS blender
+ DESTINATION bin
+ )
+ if(WITH_DOC_MANPAGE)
# manpage only with 'blender' binary
install(
- FILES ${TARGETDIR}/blender.1
- DESTINATION ${CMAKE_INSTALL_PREFIX}/share/man/man1
- )
- endif()
-
-
- if(WITH_GAMEENGINE AND WITH_PLAYER)
- install(
- PROGRAMS ${TARGETDIR}/blenderplayer
- DESTINATION ${CMAKE_INSTALL_PREFIX}/bin
+ FILES ${CMAKE_CURRENT_BINARY_DIR}/blender.1
+ DESTINATION share/man/man1
)
endif()
# misc files
install(
FILES ${CMAKE_SOURCE_DIR}/release/freedesktop/blender.desktop
- DESTINATION ${CMAKE_INSTALL_PREFIX}/share/applications
+ DESTINATION share/applications
)
install(
DIRECTORY
@@ -474,25 +485,28 @@ if(UNIX AND NOT APPLE)
${CMAKE_SOURCE_DIR}/release/freedesktop/icons/32x32
${CMAKE_SOURCE_DIR}/release/freedesktop/icons/48x48
${CMAKE_SOURCE_DIR}/release/freedesktop/icons/256x256
- DESTINATION ${CMAKE_INSTALL_PREFIX}/share/icons/hicolor
+ DESTINATION share/icons/hicolor
PATTERN "*.svg" EXCLUDE
)
install(
FILES ${CMAKE_SOURCE_DIR}/release/freedesktop/icons/scalable/apps/blender.svg
- DESTINATION ${CMAKE_INSTALL_PREFIX}/share/icons/hicolor/scalable/apps
+ DESTINATION share/icons/hicolor/scalable/apps
)
install(
PROGRAMS ${CMAKE_SOURCE_DIR}/release/bin/blender-thumbnailer.py
- DESTINATION ${CMAKE_INSTALL_PREFIX}/bin
- )
- install(
- FILES ${BLENDER_TEXT_FILES}
- DESTINATION ${CMAKE_INSTALL_PREFIX}/share/doc/blender
+ DESTINATION bin
)
+ set(BLENDER_TEXT_FILES_DESTINATION share/doc/blender)
endif()
if(WITH_PYTHON)
if(WITH_PYTHON_INSTALL)
+
+ install(
+ FILES ${PYTHON_EXECUTABLE}
+ DESTINATION ${TARGETDIR_VER}/python/bin
+ )
+
# on some platforms (like openSUSE) Python is linked
# to be used from lib64 folder.
# determine this from Python's libraries path
@@ -528,7 +542,7 @@ if(UNIX AND NOT APPLE)
)
# # doesnt work, todo
- # install(CODE "execute_process(COMMAND find ${TARGETDIR}/${BLENDER_VERSION}/python/lib/ -name '*.so' -exec strip -s {} '\;')")
+ # install(CODE "execute_process(COMMAND find ${CMAKE_INSTALL_PREFIX}/${BLENDER_VERSION}/python/lib/ -name '*.so' -exec strip -s {} '\;')")
if(WITH_PYTHON_INSTALL_NUMPY)
# Install to the same directory as the source, so debian-like
@@ -601,92 +615,122 @@ if(UNIX AND NOT APPLE)
endif()
elseif(WIN32)
- install(
- FILES ${BLENDER_TEXT_FILES}
- DESTINATION ${TARGETDIR}
- )
+ set(BLENDER_TEXT_FILES_DESTINATION ".")
if(WITH_PYTHON)
string(REPLACE "." "" _PYTHON_VERSION_NO_DOTS ${PYTHON_VERSION})
install(
FILES ${LIBDIR}/python/lib/python${_PYTHON_VERSION_NO_DOTS}.dll ${LIBDIR}/python/lib/sqlite3.dll
- DESTINATION ${TARGETDIR}
+ DESTINATION "."
CONFIGURATIONS Release;RelWithDebInfo;MinSizeRel
)
install(
FILES ${LIBDIR}/python/lib/python${_PYTHON_VERSION_NO_DOTS}_d.dll ${LIBDIR}/python/lib/sqlite3_d.dll
- DESTINATION ${TARGETDIR}
+ DESTINATION "."
CONFIGURATIONS Debug
)
if(WITH_PYTHON_INSTALL)
# note, as far as python is concerned 'RelWithDebInfo' is not debug since its without debug flags.
- # create the directory in multiple steps, so it actually gets created when it doesn't exist yet
- install(
- CODE
- "
- message(\"creating ${TARGETDIR_VER}/python/lib\")
- file(MAKE_DIRECTORY \"${TARGETDIR_VER}/python\")
- file(MAKE_DIRECTORY \"${TARGETDIR_VER}/python/lib\")
- message(\"done creating dir\")
- "
- )
+ install(DIRECTORY DESTINATION ${TARGETDIR_VER}/python)
+ install(DIRECTORY DESTINATION ${TARGETDIR_VER}/python/lib)
+
+ # WARNING: its important that 'CMAKE_INSTALL_CONFIG_NAME' is evaluated at build time
+ # and _NOT_ configuration time, when modifying the lines below,
+ # check it works in both Release & Debug mode.
+ #
+ # Edit with extreme care! - Campbell
+ # extract python
install(
CODE
"
- if(\"\${CMAKE_INSTALL_CONFIG_NAME}\" STREQUAL \"Debug\")
- execute_process(COMMAND \"${CMAKE_COMMAND}\" -E chdir \"${TARGETDIR_VER}/python/lib\"
- \"${CMAKE_COMMAND}\" -E tar xzfv \"${LIBDIR}/release/python${_PYTHON_VERSION_NO_DOTS}_d.tar.gz\")
+ message(STATUS \"Extracting Python to: \${CMAKE_INSTALL_PREFIX}/${BLENDER_VERSION}/python\")
+ if(\"\${CMAKE_INSTALL_CONFIG_NAME}\" MATCHES \"^([Dd][Ee][Bb][Uu][Gg])$\")
+ set(PYTHON_ZIP \"${LIBDIR}/release/python${_PYTHON_VERSION_NO_DOTS}_d.tar.gz\")
else()
- execute_process(COMMAND \"${CMAKE_COMMAND}\" -E chdir \"${TARGETDIR_VER}/python/lib\"
- \"${CMAKE_COMMAND}\" -E tar xzfv \"${LIBDIR}/release/python${_PYTHON_VERSION_NO_DOTS}.tar.gz\")
+ set(PYTHON_ZIP \"${LIBDIR}/release/python${_PYTHON_VERSION_NO_DOTS}.tar.gz\")
endif()
- "
- )
- if(WITH_PYTHON_INSTALL_NUMPY)
- install(
- CODE
- "
- execute_process(COMMAND \"${CMAKE_COMMAND}\" -E chdir \"${TARGETDIR_VER}/python/lib/site-packages\"
- \"${CMAKE_COMMAND}\" -E tar xzfv \"${LIBDIR}/release/python${_PYTHON_VERSION_NO_DOTS}_numpy_1.8.tar.gz\")
- "
+ execute_process(
+ COMMAND \${CMAKE_COMMAND} -E make_directory
+ \"\${CMAKE_INSTALL_PREFIX}/${BLENDER_VERSION}/python\"
+ COMMAND \${CMAKE_COMMAND} -E
+ chdir \"\${CMAKE_INSTALL_PREFIX}/${BLENDER_VERSION}/python\"
+ \${CMAKE_COMMAND} -E
+ tar xzfv \"\${PYTHON_ZIP}\"
)
- endif()
+ unset(PYTHON_ZIP)
+ "
+ )
# release/site-packages
install(
- CODE
- "
- execute_process(COMMAND \"${CMAKE_COMMAND}\" -E copy_directory
- ${LIBDIR}/release/site-packages
- \"${TARGETDIR_VER}/python/lib/site-packages\")
- "
+ DIRECTORY ${LIBDIR}/release/site-packages
+ DESTINATION ${BLENDER_VERSION}/python/lib
+ PATTERN ".svn" EXCLUDE
+ PATTERN "__pycache__" EXCLUDE # * any cache *
+ PATTERN "*.pyc" EXCLUDE # * any cache *
+ PATTERN "*.pyo" EXCLUDE # * any cache *)
)
+ if(WITH_PYTHON_INSTALL_NUMPY)
+ add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${BLENDER_VERSION}/python/lib/site-packages
+ COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_CURRENT_BINARY_DIR}/${BLENDER_VERSION}/python/lib/site-packages)
+
+ add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${BLENDER_VERSION}/python/lib/site-packages/numpy
+ COMMAND ${CMAKE_COMMAND} -E tar xzvf "${LIBDIR}/release/python${_PYTHON_VERSION_NO_DOTS}_numpy_1.9.tar.gz"
+ DEPENDS ${LIBDIR}/release/python${_PYTHON_VERSION_NO_DOTS}_numpy_1.9.tar.gz
+ ${CMAKE_CURRENT_BINARY_DIR}/${BLENDER_VERSION}/python/lib/site-packages
+ WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/${BLENDER_VERSION}/python/lib/site-packages)
+ add_custom_target(python_numpy ALL DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${BLENDER_VERSION}/python/lib/site-packages/numpy)
+ install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/${BLENDER_VERSION}/python/lib/site-packages/numpy
+ DESTINATION ${BLENDER_VERSION}/python/lib/site-packages)
+ endif()
+
- # doesnt work, todo
- # install(CODE "execute_process(COMMAND find ${TARGETDIR}/${BLENDER_VERSION}/python/lib/ -name '*.so' -exec strip -s {} '\;')")
+ # TODO(sergey): For unti we've got better way to deal with python binary
+ install(
+ FILES ${LIBDIR}/python/lib/python${_PYTHON_VERSION_NO_DOTS}.dll
+ DESTINATION ${BLENDER_VERSION}/python/bin
+ CONFIGURATIONS Release;RelWithDebInfo;MinSizeRel
+ )
+ install(
+ FILES ${LIBDIR}/python/lib/python${_PYTHON_VERSION_NO_DOTS}_d.dll
+ DESTINATION ${BLENDER_VERSION}/python/bin
+ CONFIGURATIONS Debug
+ )
endif()
unset(_PYTHON_VERSION_NO_DOTS)
endif()
+ # EGL Runtime Components
+ if(WITH_GL_EGL)
+ if(WIN32)
+ install(FILES "${OPENGLES_DLL}" DESTINATION ".")
+ install(FILES "${OPENGLES_EGL_DLL}" DESTINATION ".")
+
+ if(WITH_GL_ANGLE)
+ install(FILES "${D3DCOMPILER_DLL}" DESTINATION ".")
+ endif()
+ endif()
+ endif()
+
if(MSVC)
install(
FILES ${LIBDIR}/pthreads/lib/pthreadVC2.dll
- DESTINATION ${TARGETDIR}
+ DESTINATION "."
)
else()
#MinGW64 comes with own version. For portable builds it will probaly have to be copied to work
if(NOT WITH_MINGW64)
install(
FILES ${LIBDIR}/pthreads/lib/pthreadGC2.dll
- DESTINATION ${TARGETDIR}
+ DESTINATION "."
)
elseif(WITH_MINGW64)
install(
@@ -694,14 +738,14 @@ elseif(WIN32)
${LIBDIR}/binaries/libgcc_s_sjlj-1.dll
${LIBDIR}/binaries/libwinpthread-1.dll
${LIBDIR}/binaries/libstdc++-6.dll
- DESTINATION ${TARGETDIR}
+ DESTINATION "."
)
if(WITH_OPENMP)
install(
FILES
${LIBDIR}/binaries/libgomp-1.dll
- DESTINATION ${TARGETDIR}
+ DESTINATION "."
)
endif()
endif()
@@ -718,7 +762,7 @@ elseif(WIN32)
${LIBDIR}/ffmpeg/lib/swscale-2.dll
${LIBDIR}/ffmpeg/lib/swresample-0.dll
${LIBDIR}/ffmpeg/lib/xvidcore.dll
- DESTINATION ${TARGETDIR}
+ DESTINATION "."
)
else()
install(
@@ -728,7 +772,7 @@ elseif(WIN32)
${LIBDIR}/ffmpeg/lib/avdevice-55.dll
${LIBDIR}/ffmpeg/lib/avutil-52.dll
${LIBDIR}/ffmpeg/lib/swscale-2.dll
- DESTINATION ${TARGETDIR}
+ DESTINATION "."
)
endif()
endif()
@@ -736,7 +780,7 @@ elseif(WIN32)
if(WITH_CODEC_SNDFILE)
install(
FILES ${LIBDIR}/sndfile/lib/libsndfile-1.dll
- DESTINATION ${TARGETDIR}
+ DESTINATION "."
)
endif()
@@ -744,28 +788,37 @@ elseif(WIN32)
install(
FILES
${LIBDIR}/openal/lib/OpenAL32.dll
- ${LIBDIR}/openal/lib/wrap_oal.dll
- DESTINATION ${TARGETDIR}
+ DESTINATION "."
)
endif()
if(WITH_SDL)
install(
- FILES ${LIBDIR}/sdl/lib/SDL.dll
- DESTINATION ${TARGETDIR}
+ FILES ${LIBDIR}/sdl/lib/SDL2.dll
+ DESTINATION "."
+ )
+ endif()
+
+ if(WITH_SYSTEM_AUDASPACE)
+ install(
+ FILES
+ ${LIBDIR}/audaspace/lib/audaspace.dll
+ ${LIBDIR}/audaspace/lib/audaspace-c.dll
+ ${LIBDIR}/audaspace/lib/audaspace-py.dll
+ DESTINATION "."
)
endif()
if(NOT CMAKE_CL_64)
install(
FILES ${LIBDIR}/thumbhandler/lib/BlendThumb.dll
- DESTINATION ${TARGETDIR}
+ DESTINATION "."
)
endif()
install( # x86 builds can run on x64 Windows, so this is required at all times
FILES ${LIBDIR}/thumbhandler/lib/BlendThumb64.dll
- DESTINATION ${TARGETDIR}
+ DESTINATION "."
)
if(WITH_OPENCOLORIO)
@@ -774,13 +827,13 @@ elseif(WIN32)
install(
FILES
${OCIOBIN}/OpenColorIO.dll
- DESTINATION ${TARGETDIR}
+ DESTINATION "."
)
else()
install(
FILES
${OCIOBIN}/libOpenColorIO.dll
- DESTINATION ${TARGETDIR}
+ DESTINATION "."
)
endif()
endif()
@@ -808,41 +861,57 @@ elseif(APPLE)
set(OSX_APP_SOURCEDIR ${CMAKE_SOURCE_DIR}/release/darwin/blender.app)
# setup Info.plist
- execute_process(COMMAND date "+%Y-%m-%d" OUTPUT_VARIABLE BLENDER_DATE OUTPUT_STRIP_TRAILING_WHITESPACE)
+ execute_process(COMMAND date "+%Y-%m-%d"
+ OUTPUT_VARIABLE BLENDER_DATE
+ OUTPUT_STRIP_TRAILING_WHITESPACE)
set_target_properties(blender PROPERTIES
MACOSX_BUNDLE_INFO_PLIST ${OSX_APP_SOURCEDIR}/Contents/Info.plist
MACOSX_BUNDLE_SHORT_VERSION_STRING ${BLENDER_VERSION}
MACOSX_BUNDLE_LONG_VERSION_STRING "${BLENDER_VERSION} ${BLENDER_DATE}")
+ # Gather the date in finder-style
+ execute_process(COMMAND date "+%m/%d/%Y/%H:%M"
+ OUTPUT_VARIABLE SETFILE_DATE
+ OUTPUT_STRIP_TRAILING_WHITESPACE)
+
+ # Give the bundle actual creation/modification date
+ execute_process(COMMAND SetFile -d ${SETFILE_DATE} -m ${SETFILE_DATE} ${EXECUTABLE_OUTPUT_PATH}/blender.app)
- # install release and app files
install(
- FILES ${BLENDER_TEXT_FILES}
- DESTINATION ${TARGETDIR}
+ TARGETS blender
+ DESTINATION "."
)
+ # install release and app files
+ set(BLENDER_TEXT_FILES_DESTINATION ".")
+
install(
FILES ${OSX_APP_SOURCEDIR}/Contents/PkgInfo
- DESTINATION ${TARGETDIR}/blender.app/Contents
+ DESTINATION blender.app/Contents
)
install_dir(
${OSX_APP_SOURCEDIR}/Contents/Resources
- \${TARGETDIR}/blender.app/Contents/
+ blender.app/Contents/
)
if(WITH_OPENMP AND CMAKE_C_COMPILER_ID MATCHES "Clang" AND NOT ${CMAKE_C_COMPILER_VERSION} VERSION_LESS '3.4')
install(
FILES ${LIBDIR}/openmp/lib/libiomp5.dylib
- DESTINATION ${TARGETDIR}/blender.app/Contents/MacOS
+ DESTINATION blender.app/Contents/Resources/lib/
+ )
+ install(
+ FILES ${LIBDIR}/openmp/LICENSE.txt
+ DESTINATION "."
+ RENAME LICENSE-libiomp5.txt
)
endif()
if(WITH_LLVM AND NOT LLVM_STATIC)
install(
FILES ${LIBDIR}/llvm/lib/libLLVM-3.4.dylib
- DESTINATION ${TARGETDIR}/blender.app/Contents/MacOS
+ DESTINATION blender.app/Contents/MacOS
)
endif()
@@ -860,9 +929,10 @@ elseif(APPLE)
add_custom_command(
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/python
- COMMAND rm -rf ${CMAKE_CURRENT_BINARY_DIR}/python/
- COMMAND mkdir ${CMAKE_CURRENT_BINARY_DIR}/python/
- COMMAND unzip -q ${LIBDIR}/release/${PYTHON_ZIP} -d ${CMAKE_CURRENT_BINARY_DIR}/python/
+ COMMAND ${CMAKE_COMMAND} -E remove_directory "${CMAKE_CURRENT_BINARY_DIR}/python/"
+ COMMAND ${CMAKE_COMMAND} -E make_directory "${CMAKE_CURRENT_BINARY_DIR}/python/"
+ COMMAND ${CMAKE_COMMAND} -E chdir "${CMAKE_CURRENT_BINARY_DIR}/python/"
+ ${CMAKE_COMMAND} -E tar xzfv "${LIBDIR}/release/${PYTHON_ZIP}"
DEPENDS ${LIBDIR}/release/${PYTHON_ZIP})
add_dependencies(blender extractpyzip)
@@ -885,7 +955,7 @@ elseif(APPLE)
if(WITH_GAMEENGINE AND WITH_PLAYER)
set(OSX_APP_PLAYER_SOURCEDIR ${CMAKE_SOURCE_DIR}/release/darwin/blenderplayer.app)
set(PLAYER_SOURCEINFO ${OSX_APP_PLAYER_SOURCEDIR}/Contents/Info.plist)
- set(PLAYER_TARGETDIR_VER ${TARGETDIR}/blenderplayer.app/Contents/MacOS/${BLENDER_VERSION})
+ set(PLAYER_TARGETDIR_VER blenderplayer.app/Contents/Resources/${BLENDER_VERSION})
# important to make a clean install each time else old scripts get loaded.
@@ -894,23 +964,35 @@ elseif(APPLE)
"file(REMOVE_RECURSE ${PLAYER_TARGETDIR_VER})"
)
+ # Give the bundle actual creation/modification date
+ execute_process(COMMAND SetFile -d ${SETFILE_DATE} -m ${SETFILE_DATE} ${EXECUTABLE_OUTPUT_PATH}/blenderplayer.app)
+
install(
FILES ${OSX_APP_PLAYER_SOURCEDIR}/Contents/PkgInfo
- DESTINATION ${TARGETDIR}/blenderplayer.app/Contents
+ DESTINATION blenderplayer.app/Contents
)
install_dir(
${OSX_APP_PLAYER_SOURCEDIR}/Contents/Resources
- \${TARGETDIR}/blenderplayer.app/Contents/
+ blenderplayer.app/Contents/
)
+ if(WITH_OPENMP AND CMAKE_C_COMPILER_ID MATCHES "Clang" AND NOT ${CMAKE_C_COMPILER_VERSION} VERSION_LESS '3.4')
+ install(
+ FILES ${LIBDIR}/openmp/lib/libiomp5.dylib
+ DESTINATION blenderplayer.app/Contents/Resources/lib/
+ )
+ endif()
+
+
# python
if(WITH_PYTHON AND NOT WITH_PYTHON_FRAMEWORK)
add_custom_command(
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/python
- COMMAND rm -rf ${CMAKE_CURRENT_BINARY_DIR}/python/
- COMMAND mkdir ${CMAKE_CURRENT_BINARY_DIR}/python/
- COMMAND unzip -q ${LIBDIR}/release/${PYTHON_ZIP} -d ${CMAKE_CURRENT_BINARY_DIR}/python/
+ COMMAND ${CMAKE_COMMAND} -E remove_directory "${CMAKE_CURRENT_BINARY_DIR}/python/"
+ COMMAND ${CMAKE_COMMAND} -E make_directory "${CMAKE_CURRENT_BINARY_DIR}/python/"
+ COMMAND ${CMAKE_COMMAND} -E chdir "${CMAKE_CURRENT_BINARY_DIR}/python/"
+ ${CMAKE_COMMAND} -E tar xzfv "${LIBDIR}/release/${PYTHON_ZIP}"
DEPENDS ${LIBDIR}/release/${PYTHON_ZIP})
# copy extracted python files
@@ -927,12 +1009,33 @@ endif()
# -----------------------------------------------------------------------------
# Generic Install, for all targets
+if(DEFINED BLENDER_TEXT_FILES_DESTINATION)
+
+ install(
+ CODE
+ "
+ file(READ \"${CMAKE_SOURCE_DIR}/release/text/readme.html\" DATA_SRC)
+ string(REGEX REPLACE \"BLENDER_VERSION\" \"${BLENDER_VERSION}\" DATA_DST \"\${DATA_SRC}\")
+ file(WRITE \"\${CMAKE_BINARY_DIR}/release/text/readme.html\" \"\${DATA_DST}\")
+ unset(DATA_SRC)
+ unset(DATA_DST)
+ "
+ )
+ list(APPEND BLENDER_TEXT_FILES
+ ${CMAKE_BINARY_DIR}/release/text/readme.html
+ )
+ install(
+ FILES ${BLENDER_TEXT_FILES}
+ DESTINATION "${BLENDER_TEXT_FILES_DESTINATION}"
+ )
+endif()
# install more files specified elsewhere
delayed_do_install(${TARGETDIR_VER})
unset(BLENDER_TEXT_FILES)
+unset(BLENDER_TEXT_FILES_DESTINATION)
# -----------------------------------------------------------------------------
@@ -941,7 +1044,6 @@ unset(BLENDER_TEXT_FILES)
add_dependencies(blender makesdna)
setup_blender_sorted_libs()
-
target_link_libraries(blender ${BLENDER_SORTED_LIBS})
setup_liblinks(blender)
@@ -959,4 +1061,25 @@ if(WIN32 AND NOT WITH_PYTHON_MODULE)
set_target_properties(blender PROPERTIES OUTPUT_NAME blender-app)
set_target_properties(blender-launcher PROPERTIES OUTPUT_NAME blender)
+
+ install(TARGETS blender blender-launcher
+ COMPONENT Blender
+ DESTINATION ".")
+
+ if(MSVC12_REDIST_DIR)
+ if(CMAKE_CL_64)
+ set(_WIN_PLATFORM x64)
+ else()
+ set(_WIN_PLATFORM x86)
+ endif()
+ install(
+ FILES ${MSVC12_REDIST_DIR}/${_WIN_PLATFORM}/Microsoft.VC120.CRT/msvcp120.dll
+ ${MSVC12_REDIST_DIR}/${_WIN_PLATFORM}/Microsoft.VC120.CRT/msvcr120.dll
+ DESTINATION ".")
+ if(WITH_OPENMP)
+ install(
+ FILES ${MSVC12_REDIST_DIR}/${_WIN_PLATFORM}/Microsoft.VC120.OpenMP/vcomp120.dll
+ DESTINATION ".")
+ endif()
+ endif()
endif()
diff --git a/source/creator/blender.map b/source/creator/blender.map
index f583ddc1a89..359cbe0415f 100644
--- a/source/creator/blender.map
+++ b/source/creator/blender.map
@@ -18,5 +18,6 @@ local:
NumNamedVarArgParams;
X86CompilationCallback*;
*boost*;
+ *SDL*;
};
diff --git a/source/creator/creator.c b/source/creator/creator.c
index 3511c9dc2cb..86922c38ba0 100644
--- a/source/creator/creator.c
+++ b/source/creator/creator.c
@@ -41,20 +41,13 @@
#endif
#ifdef WIN32
-# if defined(_MSC_VER) && _MSC_VER >= 1800 && defined(_M_X64)
+# if defined(_MSC_VER) && defined(_M_X64)
# include <math.h> /* needed for _set_FMA3_enable */
# endif
# include <windows.h>
# include "utfconv.h"
#endif
-/* for backtrace */
-#if defined(__linux__) || defined(__APPLE__)
-# include <execinfo.h>
-#elif defined(_MSV_VER)
-# include <DbgHelp.h>
-#endif
-
#include <stdlib.h>
#include <stddef.h>
#include <string.h>
@@ -82,6 +75,7 @@
#include "DNA_scene_types.h"
#include "DNA_userdef_types.h"
+#include "BKE_appdir.h"
#include "BKE_blender.h"
#include "BKE_brush.h"
#include "BKE_context.h"
@@ -99,6 +93,8 @@
#include "BKE_image.h"
#include "BKE_particle.h"
+#include "DEG_depsgraph.h"
+
#include "IMB_imbuf.h" /* for IMB_init */
#ifdef WITH_PYTHON
@@ -107,6 +103,7 @@
#include "RE_engine.h"
#include "RE_pipeline.h"
+#include "RE_render_ext.h"
#include "ED_datafiles.h"
#include "ED_util.h"
@@ -153,6 +150,10 @@
# include "CCL_api.h"
#endif
+#ifdef WITH_SDL_DYNLOAD
+# include "sdlew.h"
+#endif
+
/* from buildinfo.c */
#ifdef BUILD_DATE
extern char build_date[];
@@ -196,12 +197,13 @@ static void setCallbacks(void);
#ifndef WITH_PYTHON_MODULE
static bool use_crash_handler = true;
+static bool use_abort_handler = true;
/* set breakpoints here when running in debug mode, useful to catch floating point errors */
#if defined(__linux__) || defined(_WIN32) || defined(OSX_SSE_FPE)
static void fpe_handler(int UNUSED(sig))
{
- // printf("SIGFPE trapped\n");
+ fprintf(stderr, "debug: SIGFPE trapped\n");
}
#endif
@@ -295,6 +297,7 @@ static int print_help(int UNUSED(argc), const char **UNUSED(argv), void *data)
BLI_argsPrintArgDoc(ba, "--python");
BLI_argsPrintArgDoc(ba, "--python-text");
+ BLI_argsPrintArgDoc(ba, "--python-expr");
BLI_argsPrintArgDoc(ba, "--python-console");
BLI_argsPrintArgDoc(ba, "--addons");
@@ -320,7 +323,9 @@ static int print_help(int UNUSED(argc), const char **UNUSED(argv), void *data)
BLI_argsPrintArgDoc(ba, "--debug-jobs");
BLI_argsPrintArgDoc(ba, "--debug-python");
BLI_argsPrintArgDoc(ba, "--debug-depsgraph");
+ BLI_argsPrintArgDoc(ba, "--debug-depsgraph-no-threads");
+ BLI_argsPrintArgDoc(ba, "--debug-gpumem");
BLI_argsPrintArgDoc(ba, "--debug-wm");
BLI_argsPrintArgDoc(ba, "--debug-all");
@@ -332,7 +337,6 @@ static int print_help(int UNUSED(argc), const char **UNUSED(argv), void *data)
printf("Misc Options:\n");
BLI_argsPrintArgDoc(ba, "--factory-startup");
printf("\n");
- BLI_argsPrintArgDoc(ba, "--env-system-config");
BLI_argsPrintArgDoc(ba, "--env-system-datafiles");
BLI_argsPrintArgDoc(ba, "--env-system-scripts");
BLI_argsPrintArgDoc(ba, "--env-system-python");
@@ -357,22 +361,27 @@ static int print_help(int UNUSED(argc), const char **UNUSED(argv), void *data)
printf("Other Options:\n");
BLI_argsPrintOtherDoc(ba);
+ printf("\n");
+ printf("Experimental features:\n");
+ BLI_argsPrintArgDoc(ba, "--enable-new-depsgraph");
+
printf("Argument Parsing:\n");
- printf("\targuments must be separated by white space. eg\n");
- printf("\t\t\"blender -ba test.blend\"\n");
+ printf("\tArguments must be separated by white space, eg:\n");
+ printf("\t# blender -ba test.blend\n");
printf("\t...will ignore the 'a'\n");
- printf("\t\t\"blender -b test.blend -f8\"\n");
- printf("\t...will ignore 8 because there is no space between the -f and the frame value\n\n");
+ printf("\t# blender -b test.blend -f8\n");
+ printf("\t...will ignore '8' because there is no space between the '-f' and the frame value\n\n");
printf("Argument Order:\n");
- printf("\targuments are executed in the order they are given. eg\n");
- printf("\t\t\"blender --background test.blend --render-frame 1 --render-output /tmp\"\n");
- printf("\t...will not render to /tmp because '--render-frame 1' renders before the output path is set\n");
- printf("\t\t\"blender --background --render-output /tmp test.blend --render-frame 1\"\n");
- printf("\t...will not render to /tmp because loading the blend file overwrites the render output that was set\n");
- printf("\t\t\"blender --background test.blend --render-output /tmp --render-frame 1\" works as expected.\n\n");
-
- printf("\nEnvironment Variables:\n");
+ printf("\tArguments are executed in the order they are given. eg:\n");
+ printf("\t# blender --background test.blend --render-frame 1 --render-output '/tmp'\n");
+ printf("\t...will not render to '/tmp' because '--render-frame 1' renders before the output path is set\n");
+ printf("\t# blender --background --render-output /tmp test.blend --render-frame 1\n");
+ printf("\t...will not render to '/tmp' because loading the blend file overwrites the render output that was set\n");
+ printf("\t# blender --background test.blend --render-output /tmp --render-frame 1\n");
+ printf("\t...works as expected.\n\n");
+
+ printf("Environment Variables:\n");
printf(" $BLENDER_USER_CONFIG Directory for user configuration files.\n");
printf(" $BLENDER_USER_SCRIPTS Directory for user scripts.\n");
printf(" $BLENDER_SYSTEM_SCRIPTS Directory for system wide scripts.\n");
@@ -394,6 +403,27 @@ static int print_help(int UNUSED(argc), const char **UNUSED(argv), void *data)
return 0;
}
+static int parse_relative_int(const char *str, int pos, int neg, int min, int max)
+{
+ int ret;
+
+ switch (*str) {
+ case '+':
+ ret = pos + atoi(str + 1);
+ break;
+ case '-':
+ ret = (neg - atoi(str + 1)) + 1;
+ break;
+ default:
+ ret = atoi(str);
+ break;
+ }
+
+ CLAMP(ret, min, max);
+
+ return ret;
+}
+
static int end_arguments(int UNUSED(argc), const char **UNUSED(argv), void *UNUSED(data))
{
return -1;
@@ -419,6 +449,12 @@ static int disable_crash_handler(int UNUSED(argc), const char **UNUSED(argv), vo
return 0;
}
+static int disable_abort_handler(int UNUSED(argc), const char **UNUSED(argv), void *UNUSED(data))
+{
+ use_abort_handler = false;
+ return 0;
+}
+
static int background_mode(int UNUSED(argc), const char **UNUSED(argv), void *UNUSED(data))
{
G.background = 1;
@@ -430,7 +466,7 @@ static int debug_mode(int UNUSED(argc), const char **UNUSED(argv), void *data)
G.debug |= G_DEBUG; /* std output printf's */
printf(BLEND_VERSION_STRING_FMT);
MEM_set_memory_debug();
-#ifdef DEBUG
+#ifndef NDEBUG
BLI_mempool_set_memory_debug();
#endif
@@ -510,73 +546,12 @@ static int set_fpe(int UNUSED(argc), const char **UNUSED(argv), void *UNUSED(dat
return 0;
}
-#if defined(__linux__) || defined(__APPLE__)
-
-/* Unix */
static void blender_crash_handler_backtrace(FILE *fp)
{
-#define SIZE 100
- void *buffer[SIZE];
- int nptrs;
- char **strings;
- int i;
-
fputs("\n# backtrace\n", fp);
-
- /* include a backtrace for good measure */
- nptrs = backtrace(buffer, SIZE);
- strings = backtrace_symbols(buffer, nptrs);
- for (i = 0; i < nptrs; i++) {
- fputs(strings[i], fp);
- fputc('\n', fp);
- }
-
- free(strings);
-#undef SIZE
-}
-
-#elif defined(_MSC_VER)
-
-static void blender_crash_handler_backtrace(FILE *fp)
-{
- (void)fp;
-
-#if 0
-#define MAXSYMBOL 256
- unsigned short i;
- void *stack[SIZE];
- unsigned short nframes;
- SYMBOL_INFO *symbolinfo;
- HANDLE process;
-
- process = GetCurrentProcess();
-
- SymInitialize(process, NULL, true);
-
- nframes = CaptureStackBackTrace(0, SIZE, stack, NULL);
- symbolinfo = MEM_callocN(sizeof(SYMBOL_INFO) + MAXSYMBOL * sizeof(char), "crash Symbol table");
- symbolinfo->MaxNameLen = MAXSYMBOL - 1;
- symbolinfo->SizeOfStruct = sizeof(SYMBOL_INFO);
-
- for (i = 0; i < nframes; i++) {
- SymFromAddr(process, ( DWORD64 )( stack[ i ] ), 0, symbolinfo);
-
- fprintf(fp, "%u: %s - 0x%0X\n", nframes - i - 1, symbolinfo->Name, symbolinfo->Address);
- }
-
- MEM_freeN(symbolinfo);
-#endif
-}
-
-#else /* non msvc/osx/linux */
-
-static void blender_crash_handler_backtrace(FILE *fp)
-{
- (void)fp;
+ BLI_system_backtrace(fp);
}
-#endif
-
static void blender_crash_handler(int signum)
{
@@ -585,7 +560,7 @@ static void blender_crash_handler(int signum)
char fname[FILE_MAX];
if (!G.main->name[0]) {
- BLI_make_file_string("/", fname, BLI_temp_dir_base(), "crash.blend");
+ BLI_make_file_string("/", fname, BKE_tempdir_base(), "crash.blend");
}
else {
BLI_strncpy(fname, G.main->name, sizeof(fname));
@@ -606,10 +581,10 @@ static void blender_crash_handler(int signum)
char fname[FILE_MAX];
if (!G.main->name[0]) {
- BLI_join_dirfile(fname, sizeof(fname), BLI_temp_dir_base(), "blender.crash.txt");
+ BLI_join_dirfile(fname, sizeof(fname), BKE_tempdir_base(), "blender.crash.txt");
}
else {
- BLI_join_dirfile(fname, sizeof(fname), BLI_temp_dir_base(), BLI_path_basename(G.main->name));
+ BLI_join_dirfile(fname, sizeof(fname), BKE_tempdir_base(), BLI_path_basename(G.main->name));
BLI_replace_extension(fname, sizeof(fname), ".crash.txt");
}
@@ -641,7 +616,7 @@ static void blender_crash_handler(int signum)
}
/* Delete content of temp dir! */
- BLI_temp_dir_session_purge();
+ BKE_tempdir_session_purge();
/* really crash */
signal(signum, SIG_DFL);
@@ -652,6 +627,97 @@ static void blender_crash_handler(int signum)
#endif
}
+#ifdef WIN32
+LONG WINAPI windows_exception_handler(EXCEPTION_POINTERS *ExceptionInfo)
+{
+ switch (ExceptionInfo->ExceptionRecord->ExceptionCode) {
+ case EXCEPTION_ACCESS_VIOLATION:
+ fputs("Error: EXCEPTION_ACCESS_VIOLATION\n", stderr);
+ break;
+ case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
+ fputs("Error: EXCEPTION_ARRAY_BOUNDS_EXCEEDED\n", stderr);
+ break;
+ case EXCEPTION_BREAKPOINT:
+ fputs("Error: EXCEPTION_BREAKPOINT\n", stderr);
+ break;
+ case EXCEPTION_DATATYPE_MISALIGNMENT:
+ fputs("Error: EXCEPTION_DATATYPE_MISALIGNMENT\n", stderr);
+ break;
+ case EXCEPTION_FLT_DENORMAL_OPERAND:
+ fputs("Error: EXCEPTION_FLT_DENORMAL_OPERAND\n", stderr);
+ break;
+ case EXCEPTION_FLT_DIVIDE_BY_ZERO:
+ fputs("Error: EXCEPTION_FLT_DIVIDE_BY_ZERO\n", stderr);
+ break;
+ case EXCEPTION_FLT_INEXACT_RESULT:
+ fputs("Error: EXCEPTION_FLT_INEXACT_RESULT\n", stderr);
+ break;
+ case EXCEPTION_FLT_INVALID_OPERATION:
+ fputs("Error: EXCEPTION_FLT_INVALID_OPERATION\n", stderr);
+ break;
+ case EXCEPTION_FLT_OVERFLOW:
+ fputs("Error: EXCEPTION_FLT_OVERFLOW\n", stderr);
+ break;
+ case EXCEPTION_FLT_STACK_CHECK:
+ fputs("Error: EXCEPTION_FLT_STACK_CHECK\n", stderr);
+ break;
+ case EXCEPTION_FLT_UNDERFLOW:
+ fputs("Error: EXCEPTION_FLT_UNDERFLOW\n", stderr);
+ break;
+ case EXCEPTION_ILLEGAL_INSTRUCTION:
+ fputs("Error: EXCEPTION_ILLEGAL_INSTRUCTION\n", stderr);
+ break;
+ case EXCEPTION_IN_PAGE_ERROR:
+ fputs("Error: EXCEPTION_IN_PAGE_ERROR\n", stderr);
+ break;
+ case EXCEPTION_INT_DIVIDE_BY_ZERO:
+ fputs("Error: EXCEPTION_INT_DIVIDE_BY_ZERO\n", stderr);
+ break;
+ case EXCEPTION_INT_OVERFLOW:
+ fputs("Error: EXCEPTION_INT_OVERFLOW\n", stderr);
+ break;
+ case EXCEPTION_INVALID_DISPOSITION:
+ fputs("Error: EXCEPTION_INVALID_DISPOSITION\n", stderr);
+ break;
+ case EXCEPTION_NONCONTINUABLE_EXCEPTION:
+ fputs("Error: EXCEPTION_NONCONTINUABLE_EXCEPTION\n", stderr);
+ break;
+ case EXCEPTION_PRIV_INSTRUCTION:
+ fputs("Error: EXCEPTION_PRIV_INSTRUCTION\n", stderr);
+ break;
+ case EXCEPTION_SINGLE_STEP:
+ fputs("Error: EXCEPTION_SINGLE_STEP\n", stderr);
+ break;
+ case EXCEPTION_STACK_OVERFLOW:
+ fputs("Error: EXCEPTION_STACK_OVERFLOW\n", stderr);
+ break;
+ default:
+ fputs("Error: Unrecognized Exception\n", stderr);
+ break;
+ }
+
+ fflush(stderr);
+
+ /* If this is a stack overflow then we can't walk the stack, so just show
+ * where the error happened */
+ if (EXCEPTION_STACK_OVERFLOW != ExceptionInfo->ExceptionRecord->ExceptionCode) {
+#ifdef NDEBUG
+ TerminateProcess(GetCurrentProcess(), SIGSEGV);
+#else
+ blender_crash_handler(SIGSEGV);
+#endif
+ }
+
+ return EXCEPTION_EXECUTE_HANDLER;
+}
+#endif
+
+
+static void blender_abort_handler(int UNUSED(signum))
+{
+ /* Delete content of temp dir! */
+ BKE_tempdir_session_purge();
+}
static int set_factory_startup(int UNUSED(argc), const char **UNUSED(argv), void *UNUSED(data))
{
@@ -779,7 +845,7 @@ static int no_glsl(int UNUSED(argc), const char **UNUSED(argv), void *UNUSED(dat
static int no_audio(int UNUSED(argc), const char **UNUSED(argv), void *UNUSED(data))
{
- sound_force_device(0);
+ BKE_sound_force_device("Null");
return 0;
}
@@ -790,7 +856,7 @@ static int set_audio(int argc, const char **argv, void *UNUSED(data))
exit(1);
}
- sound_force_device(sound_define_from_str(argv[1]));
+ BKE_sound_force_device(argv[1]);
return 1;
}
@@ -817,7 +883,7 @@ static int set_engine(int argc, const char **argv, void *data)
{
bContext *C = data;
if (argc >= 2) {
- if (!strcmp(argv[1], "help")) {
+ if (STREQ(argv[1], "help")) {
RenderEngineType *type = NULL;
printf("Blender Engine Listing:\n");
for (type = R_engines.first; type; type = type->next) {
@@ -835,6 +901,7 @@ static int set_engine(int argc, const char **argv, void *data)
}
else {
printf("\nError: engine not found '%s'\n", argv[1]);
+ exit(1);
}
}
else {
@@ -896,6 +963,13 @@ static int set_threads(int argc, const char **argv, void *UNUSED(data))
}
}
+static int depsgraph_use_new(int UNUSED(argc), const char **UNUSED(argv), void *UNUSED(data))
+{
+ printf("Using new dependency graph.\n");
+ DEG_depsgraph_switch_to_new();
+ return 0;
+}
+
static int set_verbosity(int argc, const char **argv, void *UNUSED(data))
{
if (argc > 1) {
@@ -986,11 +1060,12 @@ static int set_ge_parameters(int argc, const char **argv, void *data)
SYS_WriteCommandLineInt(syshandle, argv[a], 1);
#endif
/* doMipMap */
- if (!strcmp(argv[a], "nomipmap")) {
+ if (STREQ(argv[a], "nomipmap")) {
GPU_set_mipmap(0); //doMipMap = 0;
}
/* linearMipMap */
- if (!strcmp(argv[a], "linearmipmap")) {
+ if (STREQ(argv[a], "linearmipmap")) {
+ GPU_set_mipmap(1);
GPU_set_linear_mipmap(1); //linearMipMap = 1;
}
@@ -1013,23 +1088,11 @@ static int render_frame(int argc, const char **argv, void *data)
int frame;
ReportList reports;
- switch (*argv[1]) {
- case '+':
- frame = scene->r.sfra + atoi(argv[1] + 1);
- break;
- case '-':
- frame = (scene->r.efra - atoi(argv[1] + 1)) + 1;
- break;
- default:
- frame = atoi(argv[1]);
- break;
- }
+ frame = parse_relative_int(argv[1], scene->r.sfra, scene->r.efra, MINAFRAME, MAXFRAME);
BLI_begin_threaded_malloc();
BKE_reports_init(&reports, RPT_PRINT);
- frame = CLAMPIS(frame, MINAFRAME, MAXFRAME);
-
RE_SetReports(re, &reports);
RE_BlenderAnim(re, bmain, scene, NULL, scene->lay, frame, frame, scene->r.frame_step);
RE_SetReports(re, NULL);
@@ -1090,8 +1153,8 @@ static int set_start_frame(int argc, const char **argv, void *data)
Scene *scene = CTX_data_scene(C);
if (scene) {
if (argc > 1) {
- int frame = atoi(argv[1]);
- (scene->r.sfra) = CLAMPIS(frame, MINFRAME, MAXFRAME);
+ scene->r.sfra = parse_relative_int(argv[1], scene->r.sfra, scene->r.sfra - 1, MINAFRAME, MAXFRAME);
+
return 1;
}
else {
@@ -1111,8 +1174,7 @@ static int set_end_frame(int argc, const char **argv, void *data)
Scene *scene = CTX_data_scene(C);
if (scene) {
if (argc > 1) {
- int frame = atoi(argv[1]);
- (scene->r.efra) = CLAMPIS(frame, MINFRAME, MAXFRAME);
+ scene->r.efra = parse_relative_int(argv[1], scene->r.efra, scene->r.efra - 1, MINAFRAME, MAXFRAME);
return 1;
}
else {
@@ -1152,19 +1214,24 @@ static int set_skip_frame(int argc, const char **argv, void *data)
#define BPY_CTX_SETUP(_cmd) \
{ \
wmWindowManager *wm = CTX_wm_manager(C); \
- wmWindow *prevwin = CTX_wm_window(C); \
- Scene *prevscene = CTX_data_scene(C); \
- if (wm->windows.first) { \
+ Scene *scene_prev = CTX_data_scene(C); \
+ wmWindow *win_prev; \
+ const bool has_win = !BLI_listbase_is_empty(&wm->windows); \
+ if (has_win) { \
+ win_prev = CTX_wm_window(C); \
CTX_wm_window_set(C, wm->windows.first); \
- _cmd; \
- CTX_wm_window_set(C, prevwin); \
} \
else { \
fprintf(stderr, "Python script \"%s\" " \
"running with missing context data.\n", argv[1]); \
+ } \
+ { \
_cmd; \
} \
- CTX_data_scene_set(C, prevscene); \
+ if (has_win) { \
+ CTX_wm_window_set(C, win_prev); \
+ } \
+ CTX_data_scene_set(C, scene_prev); \
} (void)0 \
#endif /* WITH_PYTHON */
@@ -1190,7 +1257,7 @@ static int run_python_file(int argc, const char **argv, void *data)
return 0;
}
#else
- (void)argc; (void)argv; (void)data; /* unused */
+ UNUSED_VARS(argc, argv, data);
printf("This blender was built without python support\n");
return 0;
#endif /* WITH_PYTHON */
@@ -1220,7 +1287,28 @@ static int run_python_text(int argc, const char **argv, void *data)
return 0;
}
#else
- (void)argc; (void)argv; (void)data; /* unused */
+ UNUSED_VARS(argc, argv, data);
+ printf("This blender was built without python support\n");
+ return 0;
+#endif /* WITH_PYTHON */
+}
+
+static int run_python_expr(int argc, const char **argv, void *data)
+{
+#ifdef WITH_PYTHON
+ bContext *C = data;
+
+ /* workaround for scripts not getting a bpy.context.scene, causes internal errors elsewhere */
+ if (argc > 1) {
+ BPY_CTX_SETUP(BPY_string_exec_ex(C, argv[1], false));
+ return 1;
+ }
+ else {
+ printf("\nError: you must specify a Python expression after '%s'.\n", argv[0]);
+ return 0;
+ }
+#else
+ UNUSED_VARS(argc, argv, data);
printf("This blender was built without python support\n");
return 0;
#endif /* WITH_PYTHON */
@@ -1235,7 +1323,7 @@ static int run_python_console(int UNUSED(argc), const char **argv, void *data)
return 0;
#else
- (void)argv; (void)data; /* unused */
+ UNUSED_VARS(argv, data);
printf("This blender was built without python support\n");
return 0;
#endif /* WITH_PYTHON */
@@ -1246,14 +1334,21 @@ static int set_addons(int argc, const char **argv, void *data)
/* workaround for scripts not getting a bpy.context.scene, causes internal errors elsewhere */
if (argc > 1) {
#ifdef WITH_PYTHON
- const int slen = strlen(argv[1]) + 128;
+ const char script_str[] =
+ "from addon_utils import check, enable\n"
+ "for m in '%s'.split(','):\n"
+ " if check(m)[1] is False:\n"
+ " enable(m, persistent=True)";
+ const int slen = strlen(argv[1]) + (sizeof(script_str) - 2);
char *str = malloc(slen);
bContext *C = data;
- BLI_snprintf(str, slen, "[__import__('addon_utils').enable(i, default_set=False) for i in '%s'.split(',')]", argv[1]);
- BPY_CTX_SETUP(BPY_string_exec(C, str));
+ BLI_snprintf(str, slen, script_str, argv[1]);
+
+ BLI_assert(strlen(str) + 1 == slen);
+ BPY_CTX_SETUP(BPY_string_exec_ex(C, str, false));
free(str);
#else
- (void)argv; (void)data; /* unused */
+ UNUSED_VARS(argv, data);
#endif /* WITH_PYTHON */
return 1;
}
@@ -1279,53 +1374,74 @@ static int load_file(int UNUSED(argc), const char **argv, void *data)
BLI_path_cwd(filename);
if (G.background) {
+ Main *bmain;
+ wmWindowManager *wm;
int retval;
- BLI_callback_exec(CTX_data_main(C), NULL, BLI_CB_EVT_LOAD_PRE);
+ bmain = CTX_data_main(C);
+
+ BLI_callback_exec(bmain, NULL, BLI_CB_EVT_LOAD_PRE);
retval = BKE_read_file(C, filename, NULL);
- /* we successfully loaded a blend file, get sure that
- * pointcache works */
- if (retval != BKE_READ_FILE_FAIL) {
- wmWindowManager *wm = CTX_wm_manager(C);
- Main *bmain = CTX_data_main(C);
+ if (retval == BKE_READ_FILE_FAIL) {
+ /* failed to load file, stop processing arguments */
+ if (G.background) {
+ /* Set is_break if running in the background mode so
+ * blender will return non-zero exit code which then
+ * could be used in automated script to control how
+ * good or bad things are.
+ */
+ G.is_break = true;
+ }
+ return -1;
+ }
- /* special case, 2.4x files */
- if (wm == NULL && BLI_listbase_is_empty(&bmain->wm)) {
- extern void wm_add_default(bContext *C);
+ wm = CTX_wm_manager(C);
+ bmain = CTX_data_main(C);
- /* wm_add_default() needs the screen to be set. */
- CTX_wm_screen_set(C, bmain->screen.first);
- wm_add_default(C);
- }
+ /* special case, 2.4x files */
+ if (wm == NULL && BLI_listbase_is_empty(&bmain->wm)) {
+ extern void wm_add_default(bContext *C);
- CTX_wm_manager_set(C, NULL); /* remove wm to force check */
- WM_check(C);
- G.relbase_valid = 1;
- if (CTX_wm_manager(C) == NULL) CTX_wm_manager_set(C, wm); /* reset wm */
+ /* wm_add_default() needs the screen to be set. */
+ CTX_wm_screen_set(C, bmain->screen.first);
+ wm_add_default(C);
+ }
- /* WM_file_read would call normally */
- ED_editors_init(C);
- DAG_on_visible_update(bmain, true);
- BKE_scene_update_tagged(bmain->eval_ctx, bmain, CTX_data_scene(C));
+ CTX_wm_manager_set(C, NULL); /* remove wm to force check */
+ WM_check(C);
+ if (bmain->name[0]) {
+ G.save_over = 1;
+ G.relbase_valid = 1;
}
else {
- /* failed to load file, stop processing arguments */
- return -1;
+ G.save_over = 0;
+ G.relbase_valid = 0;
+ }
+
+ if (CTX_wm_manager(C) == NULL) {
+ CTX_wm_manager_set(C, wm); /* reset wm */
}
+ /* WM_file_read would call normally */
+ ED_editors_init(C);
+ DAG_on_visible_update(bmain, true);
+
/* WM_file_read() runs normally but since we're in background mode do here */
#ifdef WITH_PYTHON
/* run any texts that were loaded in and flagged as modules */
BPY_python_reset(C);
#endif
- BLI_callback_exec(CTX_data_main(C), NULL, BLI_CB_EVT_LOAD_POST);
+ BLI_callback_exec(bmain, NULL, BLI_CB_EVT_VERSION_UPDATE);
+ BLI_callback_exec(bmain, NULL, BLI_CB_EVT_LOAD_POST);
+
+ BKE_scene_update_tagged(bmain->eval_ctx, bmain, CTX_data_scene(C));
/* happens for the UI on file reading too (huh? (ton))*/
- // XXX BKE_reset_undo();
- // BKE_write_undo("original"); /* save current state */
+ // XXX BKE_undo_reset();
+ // BKE_undo_write("original"); /* save current state */
}
else {
/* we are not running in background mode here, but start blender in UI mode with
@@ -1346,15 +1462,17 @@ static void setupArguments(bContext *C, bArgs *ba, SYS_SystemHandle *syshandle)
{
static char output_doc[] = "<path>"
"\n\tSet the render path and file name."
- "\n\tUse // at the start of the path to"
- "\n\t\trender relative to the blend file."
- "\n\tThe # characters are replaced by the frame number, and used to define zero padding."
- "\n\t\tani_##_test.png becomes ani_01_test.png"
- "\n\t\ttest-######.png becomes test-000001.png"
- "\n\t\tWhen the filename does not contain #, The suffix #### is added to the filename"
- "\n\tThe frame number will be added at the end of the filename."
- "\n\t\teg: blender -b foobar.blend -o //render_ -F PNG -x 1 -a"
- "\n\t\t//render_ becomes //render_####, writing frames as //render_0001.png//";
+ "\n\tUse '//' at the start of the path to render relative to the blend file."
+ "\n"
+ "\n\tThe '#' characters are replaced by the frame number, and used to define zero padding."
+ "\n\t* 'ani_##_test.png' becomes 'ani_01_test.png'"
+ "\n\t* 'test-######.png' becomes 'test-000001.png'"
+ "\n"
+ "\n\tWhen the filename does not contain '#', The suffix '####' is added to the filename."
+ "\n"
+ "\n\tThe frame number will be added at the end of the filename, eg:"
+ "\n\t# blender -b foobar.blend -o //render_ -F PNG -x 1 -a"
+ "\n\t'//render_' becomes '//render_####', writing frames as '//render_0001.png'";
static char format_doc[] = "<format>"
"\n\tSet the render format, Valid options are..."
@@ -1379,14 +1497,14 @@ static void setupArguments(bContext *C, bArgs *ba, SYS_SystemHandle *syshandle)
"\n\t-g linearmipmap\t\tLinear Texture Mipmapping instead of Nearest (default)";
static char debug_doc[] = "\n\tTurn debugging on\n"
- "\n\t* Prints every operator call and their arguments"
+ "\n\t* Enables memory error detection"
"\n\t* Disables mouse grab (to interact with a debugger in some cases)"
- "\n\t* Keeps python sys.stdin rather than setting it to None";
+ "\n\t* Keeps Python's 'sys.stdin' rather than setting it to None";
//BLI_argsAdd(ba, pass, short_arg, long_arg, doc, cb, C);
/* end argument processing after -- */
- BLI_argsAdd(ba, -1, "--", NULL, "\n\tEnds option processing, following arguments passed unchanged. Access via python's sys.argv", end_arguments, NULL);
+ BLI_argsAdd(ba, -1, "--", NULL, "\n\tEnds option processing, following arguments passed unchanged. Access via Python's 'sys.argv'", end_arguments, NULL);
/* first pass: background mode, disable python and commands that exit after usage */
BLI_argsAdd(ba, 1, "-h", "--help", "\n\tPrint this help text and exit", print_help, ba);
@@ -1404,10 +1522,11 @@ static void setupArguments(bContext *C, bArgs *ba, SYS_SystemHandle *syshandle)
# define PY_DISABLE_AUTO ", (compiled as non-standard default)"
#endif
- BLI_argsAdd(ba, 1, "-y", "--enable-autoexec", "\n\tEnable automatic python script execution" PY_ENABLE_AUTO, enable_python, NULL);
- BLI_argsAdd(ba, 1, "-Y", "--disable-autoexec", "\n\tDisable automatic python script execution (pydrivers & startup scripts)" PY_DISABLE_AUTO, disable_python, NULL);
+ BLI_argsAdd(ba, 1, "-y", "--enable-autoexec", "\n\tEnable automatic Python script execution" PY_ENABLE_AUTO, enable_python, NULL);
+ BLI_argsAdd(ba, 1, "-Y", "--disable-autoexec", "\n\tDisable automatic Python script execution (pydrivers & startup scripts)" PY_DISABLE_AUTO, disable_python, NULL);
BLI_argsAdd(ba, 1, NULL, "--disable-crash-handler", "\n\tDisable the crash handler", disable_crash_handler, NULL);
+ BLI_argsAdd(ba, 1, NULL, "--disable-abort-handler", "\n\tDisable the abort handler", disable_abort_handler, NULL);
#undef PY_ENABLE_AUTO
#undef PY_DISABLE_AUTO
@@ -1426,10 +1545,10 @@ static void setupArguments(bContext *C, bArgs *ba, SYS_SystemHandle *syshandle)
BLI_argsAdd(ba, 1, NULL, "--debug-freestyle", "\n\tEnable debug/profiling messages from Freestyle rendering", debug_mode_generic, (void *)G_DEBUG_FREESTYLE);
#endif
- BLI_argsAdd(ba, 1, NULL, "--debug-python", "\n\tEnable debug messages for python", debug_mode_generic, (void *)G_DEBUG_PYTHON);
+ BLI_argsAdd(ba, 1, NULL, "--debug-python", "\n\tEnable debug messages for Python", debug_mode_generic, (void *)G_DEBUG_PYTHON);
BLI_argsAdd(ba, 1, NULL, "--debug-events", "\n\tEnable debug messages for the event system", debug_mode_generic, (void *)G_DEBUG_EVENTS);
BLI_argsAdd(ba, 1, NULL, "--debug-handlers", "\n\tEnable debug messages for event handling", debug_mode_generic, (void *)G_DEBUG_HANDLERS);
- BLI_argsAdd(ba, 1, NULL, "--debug-wm", "\n\tEnable debug messages for the window manager", debug_mode_generic, (void *)G_DEBUG_WM);
+ BLI_argsAdd(ba, 1, NULL, "--debug-wm", "\n\tEnable debug messages for the window manager, also prints every operator call", debug_mode_generic, (void *)G_DEBUG_WM);
BLI_argsAdd(ba, 1, NULL, "--debug-all", "\n\tEnable all debug messages (excludes libmv)", debug_mode_generic, (void *)G_DEBUG_ALL);
BLI_argsAdd(ba, 1, NULL, "--debug-fpe", "\n\tEnable floating point exceptions", set_fpe, NULL);
@@ -1444,11 +1563,16 @@ static void setupArguments(bContext *C, bArgs *ba, SYS_SystemHandle *syshandle)
BLI_argsAdd(ba, 1, NULL, "--debug-value", "<value>\n\tSet debug value of <value> on startup\n", set_debug_value, NULL);
BLI_argsAdd(ba, 1, NULL, "--debug-jobs", "\n\tEnable time profiling for background jobs.", debug_mode_generic, (void *)G_DEBUG_JOBS);
+ BLI_argsAdd(ba, 1, NULL, "--debug-gpu", "\n\tEnable gpu debug context and information for OpenGL 4.3+.", debug_mode_generic, (void *)G_DEBUG_GPU);
BLI_argsAdd(ba, 1, NULL, "--debug-depsgraph", "\n\tEnable debug messages from dependency graph", debug_mode_generic, (void *)G_DEBUG_DEPSGRAPH);
+ BLI_argsAdd(ba, 1, NULL, "--debug-depsgraph-no-threads", "\n\tSwitch dependency graph to a single threaded evaluation", debug_mode_generic, (void *)G_DEBUG_DEPSGRAPH_NO_THREADS);
+ BLI_argsAdd(ba, 1, NULL, "--debug-gpumem", "\n\tEnable GPU memory stats in status bar", debug_mode_generic, (void *)G_DEBUG_GPU_MEM);
+
+ BLI_argsAdd(ba, 1, NULL, "--enable-new-depsgraph", "\n\tUse new dependency graph", depsgraph_use_new, NULL);
BLI_argsAdd(ba, 1, NULL, "--verbose", "<verbose>\n\tSet logging verbosity level.", set_verbosity, NULL);
- BLI_argsAdd(ba, 1, NULL, "--factory-startup", "\n\tSkip reading the "STRINGIFY (BLENDER_STARTUP_FILE)" in the users home directory", set_factory_startup, NULL);
+ BLI_argsAdd(ba, 1, NULL, "--factory-startup", "\n\tSkip reading the " STRINGIFY(BLENDER_STARTUP_FILE) " in the users home directory", set_factory_startup, NULL);
/* TODO, add user env vars? */
BLI_argsAdd(ba, 1, NULL, "--env-system-datafiles", "\n\tSet the "STRINGIFY_ARG (BLENDER_SYSTEM_DATAFILES)" environment variable", set_env, NULL);
@@ -1475,11 +1599,12 @@ static void setupArguments(bContext *C, bArgs *ba, SYS_SystemHandle *syshandle)
BLI_argsAdd(ba, 4, "-f", "--render-frame", "<frame>\n\tRender frame <frame> and save it.\n\t+<frame> start frame relative, -<frame> end frame relative.", render_frame, C);
BLI_argsAdd(ba, 4, "-a", "--render-anim", "\n\tRender frames from start to end (inclusive)", render_animation, C);
BLI_argsAdd(ba, 4, "-S", "--scene", "<name>\n\tSet the active scene <name> for rendering", set_scene, C);
- BLI_argsAdd(ba, 4, "-s", "--frame-start", "<frame>\n\tSet start to frame <frame> (use before the -a argument)", set_start_frame, C);
- BLI_argsAdd(ba, 4, "-e", "--frame-end", "<frame>\n\tSet end to frame <frame> (use before the -a argument)", set_end_frame, C);
+ BLI_argsAdd(ba, 4, "-s", "--frame-start", "<frame>\n\tSet start to frame <frame>, supports +/- for relative frames too.", set_start_frame, C);
+ BLI_argsAdd(ba, 4, "-e", "--frame-end", "<frame>\n\tSet end to frame <frame>, supports +/- for relative frames too.", set_end_frame, C);
BLI_argsAdd(ba, 4, "-j", "--frame-jump", "<frames>\n\tSet number of frames to step forward after each rendered frame", set_skip_frame, C);
BLI_argsAdd(ba, 4, "-P", "--python", "<filename>\n\tRun the given Python script file", run_python_file, C);
BLI_argsAdd(ba, 4, NULL, "--python-text", "<name>\n\tRun the given Python script text block", run_python_text, C);
+ BLI_argsAdd(ba, 4, NULL, "--python-expr", "<expression>\n\tRun the given expression as a Python script", run_python_expr, C);
BLI_argsAdd(ba, 4, NULL, "--python-console", "\n\tRun blender with an interactive console", run_python_console, C);
BLI_argsAdd(ba, 4, NULL, "--addons", "\n\tComma separated list of addons (no spaces)", set_addons, C);
@@ -1513,13 +1638,13 @@ char **environ = NULL;
* or exit when running in background mode.
*/
int main(
- int argc,
+ int argc,
#ifdef WIN32
const char **UNUSED(argv_c)
#else
const char **argv
#endif
- )
+ )
{
bContext *C;
SYS_SystemHandle syshandle;
@@ -1529,25 +1654,32 @@ int main(
#endif
#ifdef WIN32
- /* FMA3 support in the 2013 CRT is broken on Vista and Windows 7 RTM (fixed in SP1). Just disable it. */
-# if defined(_MSC_VER) && _MSC_VER >= 1800 && defined(_M_X64)
- _set_FMA3_enable(0);
+ char **argv;
+ int argv_num;
+#endif
+
+ /* --- end declarations --- */
+
+
+#ifdef WIN32
+ /* FMA3 support in the 2013 CRT is broken on Vista and Windows 7 RTM (fixed in SP1). Just disable it. */
+# if defined(_MSC_VER) && defined(_M_X64)
+ _set_FMA3_enable(0);
# endif
/* Win32 Unicode Args */
/* NOTE: cannot use guardedalloc malloc here, as it's not yet initialized
* (it depends on the args passed in, which is what we're getting here!)
*/
- wchar_t **argv_16 = CommandLineToArgvW(GetCommandLineW(), &argc);
- char **argv = malloc(argc * sizeof(char *));
- int argci = 0;
-
- for (argci = 0; argci < argc; argci++) {
- argv[argci] = alloc_utf_8_from_16(argv_16[argci], 0);
+ {
+ wchar_t **argv_16 = CommandLineToArgvW(GetCommandLineW(), &argc);
+ argv = malloc(argc * sizeof(char *));
+ for (argv_num = 0; argv_num < argc; argv_num++) {
+ argv[argv_num] = alloc_utf_8_from_16(argv_16[argv_num], 0);
+ }
+ LocalFree(argv_16);
}
-
- LocalFree(argv_16);
-#endif
+#endif /* WIN32 */
/* NOTE: Special exception for guarded allocator type switch:
* we need to perform switch from lock-free to fully
@@ -1557,7 +1689,7 @@ int main(
int i;
for (i = 0; i < argc; i++) {
if (STREQ(argv[i], "--debug") || STREQ(argv[i], "-d") ||
- STREQ(argv[i], "--debug-memory"))
+ STREQ(argv[i], "--debug-memory") || STREQ(argv[i], "--debug-all"))
{
printf("Switching to fully guarded memory allocator.\n");
MEM_use_guarded_allocator();
@@ -1585,6 +1717,10 @@ int main(
}
#endif
+#ifdef WITH_SDL_DYNLOAD
+ sdlewInit();
+#endif
+
C = CTX_create();
#ifdef WITH_PYTHON_MODULE
@@ -1604,14 +1740,15 @@ int main(
#ifdef WITH_LIBMV
libmv_initLogging(argv[0]);
-#elif defined(WITH_CYCLES_DEBUG)
+#elif defined(WITH_CYCLES_LOGGING)
CCL_init_logging(argv[0]);
#endif
setCallbacks();
+
#if defined(__APPLE__) && !defined(WITH_PYTHON_MODULE)
/* patch to ignore argument finder gives us (pid?) */
- if (argc == 2 && strncmp(argv[1], "-psn_", 5) == 0) {
+ if (argc == 2 && STREQLEN(argv[1], "-psn_", 5)) {
extern int GHOST_HACK_getFirstFile(char buf[]);
static char firstfilebuf[512];
@@ -1622,15 +1759,14 @@ int main(
argv[1] = firstfilebuf;
}
}
-
#endif
-
+
#ifdef __FreeBSD__
fpsetmask(0);
#endif
/* initialize path to executable */
- BLI_init_program_path(argv[0]);
+ BKE_appdir_program_path_init(argv[0]);
BLI_threadapi_init();
@@ -1642,6 +1778,8 @@ int main(
DAG_init();
BKE_brush_system_init();
+ RE_init_texture_rng();
+
BLI_callback_global_init();
@@ -1659,9 +1797,18 @@ int main(
BLI_argsParse(ba, 1, NULL, NULL);
if (use_crash_handler) {
+#ifdef WIN32
+ SetUnhandledExceptionFilter(windows_exception_handler);
+#else
/* after parsing args */
signal(SIGSEGV, blender_crash_handler);
+#endif
+ }
+
+ if (use_abort_handler) {
+ signal(SIGABRT, blender_abort_handler);
}
+
#else
G.factory_startup = true; /* using preferences or user startup makes no sense for py-as-module */
(void)syshandle;
@@ -1694,7 +1841,7 @@ int main(
/* Initialize ffmpeg if built in, also needed for bg mode if videos are
* rendered via ffmpeg */
- sound_init_once();
+ BKE_sound_init_once();
init_def_material();
@@ -1707,7 +1854,7 @@ int main(
/* this is properly initialized with user defs, but this is default */
/* call after loading the startup.blend so we can read U.tempdir */
- BLI_temp_dir_init(U.tempdir);
+ BKE_tempdir_init(U.tempdir);
}
else {
#ifndef WITH_PYTHON_MODULE
@@ -1717,7 +1864,7 @@ int main(
WM_init(C, argc, (const char **)argv);
/* don't use user preferences temp dir */
- BLI_temp_dir_init(NULL);
+ BKE_tempdir_init(NULL);
}
#ifdef WITH_PYTHON
/**
@@ -1758,8 +1905,8 @@ int main(
#endif
#ifdef WIN32
- while (argci) {
- free(argv[--argci]);
+ while (argv_num) {
+ free(argv[--argv_num]);
}
free(argv);
argv = NULL;
diff --git a/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp b/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp
index c652532895f..91382669d5c 100644
--- a/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp
+++ b/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp
@@ -40,7 +40,7 @@
# pragma warning (disable:4786)
#endif
-#include "GL/glew.h"
+#include "glew-mx.h"
#include "KX_BlenderCanvas.h"
#include "KX_BlenderKeyboardDevice.h"
@@ -63,7 +63,7 @@
#include "BL_System.h"
#include "GPU_extensions.h"
-#include "Value.h"
+#include "EXP_Value.h"
extern "C" {
@@ -79,6 +79,7 @@ extern "C" {
#include "BKE_ipo.h"
#include "BKE_main.h"
#include "BKE_context.h"
+ #include "BKE_sound.h"
/* avoid c++ conflict with 'new' */
#define new _new
@@ -101,9 +102,7 @@ typedef void * wmUIHandlerRemoveFunc;
}
#ifdef WITH_AUDASPACE
-# include "AUD_C-API.h"
-# include "AUD_I3DDevice.h"
-# include "AUD_IDevice.h"
+# include AUD_DEVICE_H
#endif
static BlendFileData *load_game_data(char *filename)
@@ -280,8 +279,8 @@ extern "C" void StartKetsjiShell(struct bContext *C, struct ARegion *ar, rcti *c
bool nodepwarnings = (SYS_GetCommandLineInt(syshandle, "ignore_deprecation_warnings", 0) != 0);
#endif
// bool novertexarrays = (SYS_GetCommandLineInt(syshandle, "novertexarrays", 0) != 0);
- bool mouse_state = startscene->gm.flag & GAME_SHOW_MOUSE;
- bool restrictAnimFPS = startscene->gm.flag & GAME_RESTRICT_ANIM_UPDATES;
+ bool mouse_state = (startscene->gm.flag & GAME_SHOW_MOUSE) != 0;
+ bool restrictAnimFPS = (startscene->gm.flag & GAME_RESTRICT_ANIM_UPDATES) != 0;
short drawtype = v3d->drawtype;
@@ -299,7 +298,8 @@ extern "C" void StartKetsjiShell(struct bContext *C, struct ARegion *ar, rcti *c
canvas->SetMouseState(RAS_ICanvas::MOUSE_INVISIBLE);
// Setup vsync
- int previous_vsync = canvas->GetSwapInterval();
+ int previous_vsync = 0;
+ canvas->GetSwapInterval(previous_vsync);
if (startscene->gm.vsync == VSYNC_ADAPTIVE)
canvas->SetSwapInterval(-1);
else
@@ -445,7 +445,7 @@ extern "C" void StartKetsjiShell(struct bContext *C, struct ARegion *ar, rcti *c
rasterizer->SetEyeSeparation(scene->gm.eyeseparation);
}
- rasterizer->SetBackColor(scene->gm.framing.col[0], scene->gm.framing.col[1], scene->gm.framing.col[2], 0.0f);
+ rasterizer->SetBackColor(scene->gm.framing.col);
}
if (exitrequested != KX_EXIT_REQUEST_QUIT_GAME)
@@ -456,21 +456,13 @@ extern "C" void StartKetsjiShell(struct bContext *C, struct ARegion *ar, rcti *c
ketsjiengine->SetCameraOverrideUseOrtho((rv3d->persp == RV3D_ORTHO));
ketsjiengine->SetCameraOverrideProjectionMatrix(MT_CmMatrix4x4(rv3d->winmat));
ketsjiengine->SetCameraOverrideViewMatrix(MT_CmMatrix4x4(rv3d->viewmat));
- if (rv3d->persp == RV3D_ORTHO)
- {
- ketsjiengine->SetCameraOverrideClipping(v3d->near, v3d->far);
- }
- else
- {
- ketsjiengine->SetCameraOverrideClipping(v3d->near, v3d->far);
- }
+ ketsjiengine->SetCameraOverrideClipping(v3d->near, v3d->far);
ketsjiengine->SetCameraOverrideLens(v3d->lens);
}
// create a scene converter, create and convert the startingscene
KX_ISceneConverter* sceneconverter = new KX_BlenderSceneConverter(blenderdata, ketsjiengine);
ketsjiengine->SetSceneConverter(sceneconverter);
- sceneconverter->addInitFromFrame=false;
if (always_use_expand_framing)
sceneconverter->SetAlwaysUseExpandFraming(true);
@@ -509,13 +501,10 @@ extern "C" void StartKetsjiShell(struct bContext *C, struct ARegion *ar, rcti *c
ketsjiengine->InitDome(scene->gm.dome.res, scene->gm.dome.mode, scene->gm.dome.angle, scene->gm.dome.resbuf, scene->gm.dome.tilt, scene->gm.dome.warptext);
// initialize 3D Audio Settings
- AUD_I3DDevice* dev = AUD_get3DDevice();
- if (dev)
- {
- dev->setSpeedOfSound(scene->audio.speed_of_sound);
- dev->setDopplerFactor(scene->audio.doppler_factor);
- dev->setDistanceModel(AUD_DistanceModel(scene->audio.distance_model));
- }
+ AUD_Device* device = BKE_sound_get_device();
+ AUD_Device_setSpeedOfSound(device, scene->audio.speed_of_sound);
+ AUD_Device_setDopplerFactor(device, scene->audio.doppler_factor);
+ AUD_Device_setDistanceModel(device, AUD_DistanceModel(scene->audio.distance_model));
// from see blender.c:
// FIXME: this version patching should really be part of the file-reading code,
@@ -555,6 +544,10 @@ extern "C" void StartKetsjiShell(struct bContext *C, struct ARegion *ar, rcti *c
if (python_main) {
char *python_code = KX_GetPythonCode(blenderdata, python_main);
if (python_code) {
+ // Set python environement variable.
+ KX_SetActiveScene(startscene);
+ PHY_SetActiveEnvironment(startscene->GetPhysicsEnvironment());
+
ketsjinextframestate.ketsjiengine = ketsjiengine;
ketsjinextframestate.C = C;
ketsjinextframestate.win = win;
@@ -682,7 +675,7 @@ extern "C" void StartKetsjiShell(struct bContext *C, struct ARegion *ar, rcti *c
}
// stop all remaining playing sounds
- AUD_getDevice()->stopAll();
+ AUD_Device_stopAll(BKE_sound_get_device());
} while (exitrequested == KX_EXIT_REQUEST_RESTART_GAME || exitrequested == KX_EXIT_REQUEST_START_OTHER_GAME);
diff --git a/source/gameengine/BlenderRoutines/CMakeLists.txt b/source/gameengine/BlenderRoutines/CMakeLists.txt
index 73dbe005518..aaeb2e10462 100644
--- a/source/gameengine/BlenderRoutines/CMakeLists.txt
+++ b/source/gameengine/BlenderRoutines/CMakeLists.txt
@@ -24,6 +24,7 @@ set(INC
../../blender/makesrna
../../blender/windowmanager
../../../intern/container
+ ../../../intern/glew-mx
../../../intern/guardedalloc
../../../intern/string
)
@@ -52,13 +53,14 @@ set(SRC
KX_BlenderSystem.h
)
-add_definitions(-DGLEW_STATIC)
+add_definitions(${GL_DEFINITIONS})
if(WITH_AUDASPACE)
- list(APPEND INC
- ../../../intern/audaspace/intern
+ add_definitions(${AUDASPACE_DEFINITIONS})
+
+ list(APPEND INC_SYS
+ ${AUDASPACE_C_INCLUDE_DIRS}
)
- add_definitions(-DWITH_AUDASPACE)
endif()
if(WITH_CODEC_FFMPEG)
diff --git a/source/gameengine/BlenderRoutines/KX_BlenderCanvas.cpp b/source/gameengine/BlenderRoutines/KX_BlenderCanvas.cpp
index b3e0b4c3ea6..e37818678d6 100644
--- a/source/gameengine/BlenderRoutines/KX_BlenderCanvas.cpp
+++ b/source/gameengine/BlenderRoutines/KX_BlenderCanvas.cpp
@@ -29,7 +29,7 @@
* \ingroup blroutines
*/
-#include <GL/glew.h>
+#include "glew-mx.h"
#include "MEM_guardedalloc.h"
@@ -67,6 +67,7 @@ m_frame_rect(rect)
// area boundaries needed for mouse coordinates in Letterbox framing mode
m_area_left = ar->winrct.xmin;
m_area_top = ar->winrct.ymax;
+ m_frame = 1;
glGetIntegerv(GL_VIEWPORT, (GLint *)m_viewport);
}
@@ -91,9 +92,14 @@ void KX_BlenderCanvas::SetSwapInterval(int interval)
wm_window_set_swap_interval(m_win, interval);
}
-int KX_BlenderCanvas::GetSwapInterval()
+bool KX_BlenderCanvas::GetSwapInterval(int &intervalOut)
{
- return wm_window_get_swap_interval(m_win);
+ return wm_window_get_swap_interval(m_win, &intervalOut);
+}
+
+void KX_BlenderCanvas::GetDisplayDimensions(int &width, int &height)
+{
+ wm_get_screensize(&width, &height);
}
void KX_BlenderCanvas::ResizeWindow(int width, int height)
@@ -350,7 +356,9 @@ void KX_BlenderCanvas::MakeScreenShot(const char *filename)
char path[FILE_MAX];
BLI_strncpy(path, filename, sizeof(path));
BLI_path_abs(path, G.main->name);
- BKE_add_image_extension_from_type(path, im_format.imtype);
+ BLI_path_frame(path, m_frame, 0);
+ m_frame++;
+ BKE_image_path_ensure_ext_from_imtype(path, im_format.imtype);
/* create and save imbuf */
ImBuf *ibuf = IMB_allocImBuf(dumpsx, dumpsy, 24, 0);
diff --git a/source/gameengine/BlenderRoutines/KX_BlenderCanvas.h b/source/gameengine/BlenderRoutines/KX_BlenderCanvas.h
index 9ad80cb1737..817a667d783 100644
--- a/source/gameengine/BlenderRoutines/KX_BlenderCanvas.h
+++ b/source/gameengine/BlenderRoutines/KX_BlenderCanvas.h
@@ -82,10 +82,13 @@ public:
int interval
);
- int
+ bool
GetSwapInterval(
+ int &intervalOut
);
+ void GetDisplayDimensions(int &width, int &height);
+
void
ResizeWindow(
int width,
@@ -209,6 +212,7 @@ private:
RAS_Rect m_area_rect;
int m_area_left;
int m_area_top;
+ int m_frame;
#ifdef WITH_CXX_GUARDEDALLOC
diff --git a/source/gameengine/BlenderRoutines/SConscript b/source/gameengine/BlenderRoutines/SConscript
index 62d657189c5..ea14092943a 100644
--- a/source/gameengine/BlenderRoutines/SConscript
+++ b/source/gameengine/BlenderRoutines/SConscript
@@ -29,9 +29,8 @@ Import ('env')
sources = env.Glob('*.cpp')
-defs = [
- 'GLEW_STATIC',
- ]
+defs = []
+defs += env['BF_GL_DEFINITIONS']
incs = [
'.',
@@ -39,8 +38,8 @@ incs = [
'#intern/guardedalloc',
'#intern/string',
'#source/blender',
- '#extern/glew/include',
- '#intern/audaspace/intern',
+ env['BF_GLEW_INC'],
+ '#/intern/glew-mx',
'#intern/ghost/include',
'#intern/moto/include',
'#source/blender/blenfont',
@@ -68,6 +67,10 @@ incs = [
]
incs = ' '.join(incs)
+if env['WITH_BF_AUDASPACE']:
+ defs += env['BF_AUDASPACE_DEF']
+ incs += ' ' + env['BF_AUDASPACE_C_INC']
+
if env['WITH_BF_FFMPEG']:
defs.append('WITH_FFMPEG')
diff --git a/source/gameengine/CMakeLists.txt b/source/gameengine/CMakeLists.txt
index cf7895e98ea..62523175f46 100644
--- a/source/gameengine/CMakeLists.txt
+++ b/source/gameengine/CMakeLists.txt
@@ -23,6 +23,8 @@
#
# ***** END GPL LICENSE BLOCK *****
+remove_extra_strict_flags()
+
# there are too many inter-includes so best define here
if(WITH_PYTHON)
blender_include_dirs_sys("${PYTHON_INCLUDE_DIRS}")
diff --git a/source/gameengine/Converter/BL_ActionActuator.cpp b/source/gameengine/Converter/BL_ActionActuator.cpp
index 3dd013dfd63..d4cfeb2201a 100644
--- a/source/gameengine/Converter/BL_ActionActuator.cpp
+++ b/source/gameengine/Converter/BL_ActionActuator.cpp
@@ -49,8 +49,8 @@
#include "MT_Matrix4x4.h"
#include "BKE_action.h"
-#include "FloatValue.h"
-#include "PyObjectPlus.h"
+#include "EXP_FloatValue.h"
+#include "EXP_PyObjectPlus.h"
#include "KX_PyMath.h"
extern "C" {
@@ -90,7 +90,7 @@ BL_ActionActuator::BL_ActionActuator(SCA_IObject *gameobj,
m_stridelength(stride),
m_layer_weight(layer_weight),
m_playtype(playtype),
- m_blendmode(blend_mode),
+ m_blendmode(blend_mode),
m_priority(priority),
m_layer(layer),
m_ipo_flags(ipo_flags),
@@ -256,12 +256,14 @@ bool BL_ActionActuator::Update(double curtime, bool frame)
if ((m_flag & ACT_FLAG_PLAY_END) && (m_flag & ACT_FLAG_ACTIVE) && obj->IsActionDone(m_layer))
{
m_flag &= ~ACT_FLAG_ACTIVE;
- m_flag &= ~ACT_FLAG_ATTEMPT_PLAY;
- if (m_playtype == ACT_ACTION_PINGPONG)
+ if (m_playtype == ACT_ACTION_PINGPONG) {
m_flag ^= ACT_FLAG_REVERSE;
- else
+ }
+ else {
+ m_flag &= ~ACT_FLAG_ATTEMPT_PLAY;
return false;
+ }
}
// If a different action is playing, we've been overruled and are no longer active
@@ -320,8 +322,9 @@ bool BL_ActionActuator::Update(double curtime, bool frame)
case ACT_ACTION_FLIPPER:
// Convert into a play action and play back to the beginning
+ float temp = end;
end = start;
- start = obj->GetActionFrame(m_layer);
+ start = curr_action ? obj->GetActionFrame(m_layer) : temp;
obj->PlayAction(m_action->id.name+2, start, end, m_layer, m_priority, 0, BL_Action::ACT_MODE_PLAY, m_layer_weight, m_ipo_flags, 1.f, blendmode);
m_flag |= ACT_FLAG_PLAY_END;
diff --git a/source/gameengine/Converter/BL_ArmatureChannel.cpp b/source/gameengine/Converter/BL_ArmatureChannel.cpp
index cb33ff0e1e3..2b8dfd8f8d1 100644
--- a/source/gameengine/Converter/BL_ArmatureChannel.cpp
+++ b/source/gameengine/Converter/BL_ArmatureChannel.cpp
@@ -295,7 +295,7 @@ PyObject *BL_ArmatureChannel::py_attr_get_joint_rotation(void *self_v, const str
mul_v3_fl(joints,norm);
break;
}
- return Vector_CreatePyObject(joints, 3, Py_NEW, NULL);
+ return Vector_CreatePyObject(joints, 3, NULL);
}
int BL_ArmatureChannel::py_attr_set_joint_rotation(void *self_v, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
diff --git a/source/gameengine/Converter/BL_ArmatureChannel.h b/source/gameengine/Converter/BL_ArmatureChannel.h
index 51114c5df30..d349e6e9dae 100644
--- a/source/gameengine/Converter/BL_ArmatureChannel.h
+++ b/source/gameengine/Converter/BL_ArmatureChannel.h
@@ -35,7 +35,7 @@
#include "DNA_action_types.h"
#include "CTR_HashedPtr.h"
#include "CTR_Map.h"
-#include "PyObjectPlus.h"
+#include "EXP_PyObjectPlus.h"
class SCA_IObject;
class KX_GameObject;
diff --git a/source/gameengine/Converter/BL_ArmatureConstraint.cpp b/source/gameengine/Converter/BL_ArmatureConstraint.cpp
index e515574df8b..88d82e21d61 100644
--- a/source/gameengine/Converter/BL_ArmatureConstraint.cpp
+++ b/source/gameengine/Converter/BL_ArmatureConstraint.cpp
@@ -334,7 +334,7 @@ PyObject *BL_ArmatureConstraint::py_attr_getattr(void *self_v, const struct KX_P
}
switch (attr_order) {
case BCA_IKWEIGHT:
- return PyFloat_FromDouble((ikconstraint)?ikconstraint->weight : 0.0f);
+ return PyFloat_FromDouble(ikconstraint->weight);
case BCA_IKTYPE:
return PyLong_FromLong(ikconstraint->type);
case BCA_IKFLAG:
diff --git a/source/gameengine/Converter/BL_ArmatureConstraint.h b/source/gameengine/Converter/BL_ArmatureConstraint.h
index 98c2954baf4..1d9f7f0d548 100644
--- a/source/gameengine/Converter/BL_ArmatureConstraint.h
+++ b/source/gameengine/Converter/BL_ArmatureConstraint.h
@@ -35,7 +35,7 @@
#include "DNA_constraint_types.h"
#include "CTR_HashedPtr.h"
#include "CTR_Map.h"
-#include "PyObjectPlus.h"
+#include "EXP_PyObjectPlus.h"
class SCA_IObject;
class KX_GameObject;
diff --git a/source/gameengine/Converter/BL_ArmatureObject.cpp b/source/gameengine/Converter/BL_ArmatureObject.cpp
index 8d73e591113..74ebdbcf1b5 100644
--- a/source/gameengine/Converter/BL_ArmatureObject.cpp
+++ b/source/gameengine/Converter/BL_ArmatureObject.cpp
@@ -101,7 +101,7 @@ static void game_copy_pose(bPose **dst, bPose *src, int copy_constraint)
out->chanhash = NULL;
out->agroups.first= out->agroups.last= NULL;
out->ikdata = NULL;
- out->ikparam = MEM_dupallocN(src->ikparam);
+ out->ikparam = MEM_dupallocN(src->ikparam);
out->flag |= POSE_GAME_ENGINE;
BLI_duplicatelist(&out->chanbase, &src->chanbase);
@@ -230,10 +230,15 @@ BL_ArmatureObject::BL_ArmatureObject(
m_origObjArma = armature; // Keep a copy of the original armature so we can fix drivers later
m_objArma = BKE_object_copy(armature);
m_objArma->data = BKE_armature_copy((bArmature *)armature->data);
+ // During object replication ob->data is increase, we decrease it now because we get a copy.
+ id_us_min(&((bArmature *)m_origObjArma->data)->id);
m_pose = m_objArma->pose;
- // need this to get iTaSC working ok in the BGE
- m_pose->flag |= POSE_GAME_ENGINE;
+ // need this to get iTaSC working ok in the BGE
+ m_pose->flag |= POSE_GAME_ENGINE;
memcpy(m_obmat, m_objArma->obmat, sizeof(m_obmat));
+
+ // The side-effect of this method registers this object as "animatable" with the KX_Scene.
+ GetActionManager();
}
BL_ArmatureObject::~BL_ArmatureObject()
@@ -247,8 +252,10 @@ BL_ArmatureObject::~BL_ArmatureObject()
delete channel;
}
- if (m_objArma)
+ if (m_objArma) {
+ BKE_libblock_free(G.main, m_objArma->data);
BKE_libblock_free(G.main, m_objArma);
+ }
}
@@ -265,7 +272,7 @@ void BL_ArmatureObject::LoadConstraints(KX_BlenderSceneConverter* converter)
// get the persistent pose structure
bPoseChannel* pchan;
bConstraint* pcon;
- bConstraintTypeInfo* cti;
+ const bConstraintTypeInfo* cti;
Object* blendtarget;
KX_GameObject* gametarget;
KX_GameObject* gamesubtarget;
diff --git a/source/gameengine/Converter/BL_BlenderDataConversion.cpp b/source/gameengine/Converter/BL_BlenderDataConversion.cpp
index 87b64582e11..c74fd82a9f6 100644
--- a/source/gameengine/Converter/BL_BlenderDataConversion.cpp
+++ b/source/gameengine/Converter/BL_BlenderDataConversion.cpp
@@ -52,23 +52,13 @@
#include <algorithm>
#include "BL_BlenderDataConversion.h"
-#include "KX_BlenderScalarInterpolator.h"
-#include "RAS_IPolygonMaterial.h"
-
-// Expressions
-#include "ListValue.h"
-#include "IntValue.h"
-// Collision & Fuzzics LTD
+#include "MT_Transform.h"
+#include "MT_MinMax.h"
#include "PHY_Pro.h"
#include "PHY_IPhysicsEnvironment.h"
-#include "PHY_DynamicTypes.h"
-
-#include "KX_Scene.h"
-#include "KX_GameObject.h"
-#include "RAS_FramingManager.h"
#include "RAS_MeshObject.h"
#include "RAS_IRasterizer.h"
#include "RAS_ILightObject.h"
@@ -76,31 +66,27 @@
#include "KX_ConvertActuators.h"
#include "KX_ConvertControllers.h"
#include "KX_ConvertSensors.h"
-
#include "SCA_LogicManager.h"
-#include "SCA_EventManager.h"
#include "SCA_TimeEventManager.h"
+
+#include "KX_ClientObjectInfo.h"
+#include "KX_Scene.h"
+#include "KX_GameObject.h"
#include "KX_Light.h"
#include "KX_Camera.h"
-#include "KX_ClientObjectInfo.h"
#include "KX_EmptyObject.h"
#include "KX_FontObject.h"
-#include "MT_Point3.h"
-#include "MT_Transform.h"
-#include "MT_MinMax.h"
-#include "SCA_IInputDevice.h"
+
#include "RAS_TexMatrix.h"
#include "RAS_ICanvas.h"
-#include "RAS_MaterialBucket.h"
-//#include "KX_BlenderPolyMaterial.h"
#include "RAS_Polygon.h"
#include "RAS_TexVert.h"
#include "RAS_BucketManager.h"
+#include "RAS_IPolygonMaterial.h"
#include "BL_Material.h"
#include "KX_BlenderMaterial.h"
#include "BL_Texture.h"
-#include "DNA_action_types.h"
#include "BKE_main.h"
#include "BKE_global.h"
#include "BKE_object.h"
@@ -109,10 +95,10 @@
#include "BL_SkinDeformer.h"
#include "BL_MeshDeformer.h"
#include "KX_SoftBodyDeformer.h"
-//#include "BL_ArmatureController.h"
#include "BLI_utildefines.h"
#include "BLI_listbase.h"
-#include "BlenderWorldInfo.h"
+
+#include "KX_WorldInfo.h"
#include "KX_KetsjiEngine.h"
#include "KX_BlenderSceneConverter.h"
@@ -143,13 +129,14 @@
#include "DNA_sound_types.h"
#include "DNA_key_types.h"
#include "DNA_armature_types.h"
+#include "DNA_action_types.h"
#include "DNA_object_force.h"
+#include "DNA_constraint_types.h"
#include "MEM_guardedalloc.h"
#include "BKE_key.h"
#include "BKE_mesh.h"
-#include "MT_Point3.h"
#include "BLI_math.h"
@@ -170,29 +157,19 @@ extern Material defmaterial; /* material.c */
#include "KX_BlenderInputDevice.h"
#include "KX_ConvertProperties.h"
-#include "KX_HashedPtr.h"
-
-
-#include "KX_ScalarInterpolator.h"
-
-#include "KX_IpoConvert.h"
-#include "BL_System.h"
#include "SG_Node.h"
#include "SG_BBox.h"
#include "SG_Tree.h"
+#include "KX_SG_NodeRelationships.h"
+#include "KX_SG_BoneParentNodeRelationship.h"
#ifdef WITH_BULLET
#include "CcdPhysicsEnvironment.h"
#include "CcdGraphicController.h"
#endif
-#include "KX_MotionState.h"
-
-// This file defines relationships between parents and children
-// in the game engine.
-#include "KX_SG_NodeRelationships.h"
-#include "KX_SG_BoneParentNodeRelationship.h"
+#include "KX_MotionState.h"
#include "BL_ArmatureObject.h"
#include "BL_DeformableGameObject.h"
@@ -200,18 +177,9 @@ extern Material defmaterial; /* material.c */
#include "KX_NavMeshObject.h"
#include "KX_ObstacleSimulation.h"
-#ifdef __cplusplus
-extern "C" {
-#endif
-//XXX void update_for_newframe();
-//void BKE_scene_update_for_newframe(struct Scene *sce, unsigned int lay);
-//void do_all_data_ipos(void);
-#ifdef __cplusplus
-}
-#endif
-
#include "BLI_threads.h"
+
static bool default_light_mode = 0;
static std::map<int, SCA_IInputDevice::KX_EnumInputs> create_translate_table()
@@ -389,6 +357,11 @@ static std::map<int, SCA_IInputDevice::KX_EnumInputs> create_translate_table()
static std::map<int, SCA_IInputDevice::KX_EnumInputs> gReverseKeyTranslateTable = create_translate_table();
+SCA_IInputDevice::KX_EnumInputs ConvertKeyCode(int key_code)
+{
+ return gReverseKeyTranslateTable[key_code];
+}
+
static unsigned int KX_rgbaint2uint_new(unsigned int icol)
{
union
@@ -889,20 +862,20 @@ static bool ConvertMaterial(
// swap the material color, so MCol on bitmap font works
if (validmat && (use_vcol == false) && (mat->game.flag & GEMAT_TEXT))
{
- rgb[0] = KX_rgbaint2uint_new(rgb[0]);
- rgb[1] = KX_rgbaint2uint_new(rgb[1]);
- rgb[2] = KX_rgbaint2uint_new(rgb[2]);
- rgb[3] = KX_rgbaint2uint_new(rgb[3]);
+ material->rgb[0] = KX_rgbaint2uint_new(rgb[0]);
+ material->rgb[1] = KX_rgbaint2uint_new(rgb[1]);
+ material->rgb[2] = KX_rgbaint2uint_new(rgb[2]);
+ material->rgb[3] = KX_rgbaint2uint_new(rgb[3]);
}
if (validmat)
material->matname =(mat->id.name);
if (tface) {
- material->tface = *tface;
+ ME_MTEXFACE_CPY(&material->mtexpoly, tface);
}
else {
- memset(&material->tface, 0, sizeof(material->tface));
+ memset(&material->mtexpoly, 0, sizeof(material->mtexpoly));
}
material->material = mat;
return true;
@@ -986,8 +959,16 @@ RAS_MeshObject* BL_ConvertMesh(Mesh* mesh, Object* blenderobj, KX_Scene* scene,
int totface = dm->getNumTessFaces(dm);
const char *tfaceName = "";
+ /* needs to be rewritten for loopdata */
if (tface) {
- DM_add_tangent_layer(dm);
+ if (CustomData_get_layer_index(&dm->faceData, CD_TANGENT) == -1) {
+ bool generate_data = false;
+ if (CustomData_get_layer_index(&dm->loopData, CD_TANGENT) == -1) {
+ DM_calc_loop_tangents(dm);
+ generate_data = true;
+ }
+ DM_generate_tangent_tessface_data(dm, generate_data);
+ }
tangent = (float(*)[4])dm->getTessFaceDataArray(dm, CD_TANGENT);
}
@@ -1022,7 +1003,6 @@ RAS_MeshObject* BL_ConvertMesh(Mesh* mesh, Object* blenderobj, KX_Scene* scene,
meshobj->m_sharedvertex_map.resize(totvert);
Material* ma = 0;
- bool collider = true;
MT_Point2 uvs[4][RAS_TexVert::MAX_UNIT];
unsigned int rgb[4] = {0};
@@ -1092,29 +1072,19 @@ RAS_MeshObject* BL_ConvertMesh(Mesh* mesh, Object* blenderobj, KX_Scene* scene,
else
ma = mesh->mat ? mesh->mat[mface->mat_nr]:NULL;
- /* ckeck for texface since texface _only_ is used as a fallback */
- if (ma == NULL && tface == NULL) {
+ // Check for blender material
+ if (ma == NULL) {
ma= &defmaterial;
}
{
- bool visible = true;
- bool twoside = false;
RAS_MaterialBucket* bucket = material_from_mesh(ma, mface, tface, mcol, layers, lightlayer, rgb, uvs, tfaceName, scene, converter);
// set render flags
- if (ma)
- {
- visible = ((ma->game.flag & GEMAT_INVISIBLE)==0);
- twoside = ((ma->game.flag & GEMAT_BACKCULL)==0);
- collider = ((ma->game.flag & GEMAT_NOPHYSICS)==0);
- }
- else {
- visible = true;
- twoside = false;
- collider = true;
- }
+ bool visible = ((ma->game.flag & GEMAT_INVISIBLE)==0);
+ bool twoside = ((ma->game.flag & GEMAT_BACKCULL)==0);
+ bool collider = ((ma->game.flag & GEMAT_NOPHYSICS)==0);
/* mark face as flat, so vertices are split */
bool flat = (mface->flag & ME_SMOOTH) == 0;
@@ -1238,7 +1208,9 @@ static PHY_ShapeProps *CreateShapePropsFromBlenderObject(struct Object* blendero
// velocity clamping XXX
shapeProps->m_clamp_vel_min = blenderobject->min_vel;
shapeProps->m_clamp_vel_max = blenderobject->max_vel;
-
+ shapeProps->m_clamp_angvel_min = blenderobject->min_angvel;
+ shapeProps->m_clamp_angvel_max = blenderobject->max_angvel;
+
// Character physics properties
shapeProps->m_step_height = blenderobject->step_height;
shapeProps->m_jump_speed = blenderobject->jump_speed;
@@ -1374,8 +1346,8 @@ static void BL_CreatePhysicsObjectNew(KX_GameObject* gameobj,
if (!(blenderobject->gameflag & OB_COLLISION)) {
// Respond to all collisions so that Near sensors work on No Collision
// objects.
- gameobj->SetUserCollisionGroup(0xff);
- gameobj->SetUserCollisionMask(0xff);
+ gameobj->SetUserCollisionGroup(0xffff);
+ gameobj->SetUserCollisionMask(0xffff);
return;
}
@@ -1389,16 +1361,14 @@ static void BL_CreatePhysicsObjectNew(KX_GameObject* gameobj,
}
bool isCompoundChild = false;
- bool hasCompoundChildren = !parent && (blenderobject->gameflag & OB_CHILD);
+ bool hasCompoundChildren = !parent && (blenderobject->gameflag & OB_CHILD) && !(blenderobject->gameflag & OB_SOFT_BODY);
/* When the parent is not OB_DYNAMIC and has no OB_COLLISION then it gets no bullet controller
- * and cant be apart of the parents compound shape */
+ * and cant be apart of the parents compound shape, same goes for OB_SOFT_BODY */
if (parent && (parent->gameflag & (OB_DYNAMIC | OB_COLLISION))) {
-
- if ((parent->gameflag & OB_CHILD) != 0 && (blenderobject->gameflag & OB_CHILD))
- {
+ if( (parent->gameflag & OB_CHILD)!=0 && (blenderobject->gameflag & OB_CHILD) && !(parent->gameflag & OB_SOFT_BODY)) {
isCompoundChild = true;
- }
+ }
}
if (processCompoundChildren != isCompoundChild)
return;
@@ -1429,16 +1399,6 @@ static void BL_CreatePhysicsObjectNew(KX_GameObject* gameobj,
if ((blenderobject->gameflag & OB_RECORD_ANIMATION) != 0)
gameobj->SetRecordAnimation(true);
- // store materialname in auxinfo, needed for touchsensors
- if (meshobj)
- {
- const STR_String& matname=meshobj->GetMaterialName(0);
- gameobj->getClientInfo()->m_auxilary_info = (matname.Length() ? (void*)(matname.ReadPtr()+2) : NULL);
- } else
- {
- gameobj->getClientInfo()->m_auxilary_info = 0;
- }
-
delete shapeprops;
delete smmaterial;
if (dm) {
@@ -1499,7 +1459,7 @@ static KX_LightObject *gamelight_from_blamp(Object *ob, Lamp *la, unsigned int l
static KX_Camera *gamecamera_from_bcamera(Object *ob, KX_Scene *kxscene, KX_BlenderSceneConverter *converter)
{
Camera* ca = static_cast<Camera*>(ob->data);
- RAS_CameraData camdata(ca->lens, ca->ortho_scale, ca->sensor_x, ca->sensor_y, ca->sensor_fit, ca->clipsta, ca->clipend, ca->type == CAM_PERSP, ca->YF_dofdist);
+ RAS_CameraData camdata(ca->lens, ca->ortho_scale, ca->sensor_x, ca->sensor_y, ca->sensor_fit, ca->shiftx, ca->shifty, ca->clipsta, ca->clipend, ca->type == CAM_PERSP, ca->YF_dofdist);
KX_Camera *gamecamera;
gamecamera= new KX_Camera(kxscene, KX_Scene::m_callbacks, camdata);
@@ -1568,7 +1528,7 @@ static KX_GameObject *gameobject_from_blenderobject(
gameobj->AddMesh(meshobj);
// gather levels of detail
- if (BLI_countlist(&ob->lodlevels) > 1) {
+ if (BLI_listbase_count_ex(&ob->lodlevels, 2) > 1) {
LodLevel *lod = ((LodLevel*)ob->lodlevels.first)->next;
Mesh* lodmesh = mesh;
Object* lodmatob = ob;
@@ -1583,6 +1543,10 @@ static KX_GameObject *gameobject_from_blenderobject(
}
gameobj->AddLodMesh(BL_ConvertMesh(lodmesh, lodmatob, kxscene, converter, libloading));
}
+ if (blenderscene->gm.lodflag & SCE_LOD_USE_HYST) {
+ kxscene->SetLodHysteresis(true);
+ kxscene->SetLodHysteresisValue(blenderscene->gm.scehysteresis);
+ }
}
// for all objects: check whether they want to
@@ -1676,7 +1640,7 @@ static KX_GameObject *gameobject_from_blenderobject(
case OB_FONT:
{
- bool do_color_management = !(blenderscene->gm.flag & GAME_GLSL_NO_COLOR_MANAGEMENT);
+ bool do_color_management = BKE_scene_check_color_management_enabled(blenderscene);
/* font objects have no bounding box */
gameobj = new KX_FontObject(kxscene,KX_Scene::m_callbacks, rendertools, ob, do_color_management);
@@ -1711,9 +1675,6 @@ struct parentChildLink {
SG_Node* m_gamechildnode;
};
-#include "DNA_constraint_types.h"
-//XXX #include "BIF_editconstraint.h"
-
static bPoseChannel *get_active_posechannel2(Object *ob)
{
bArmature *arm= (bArmature*)ob->data;
@@ -1747,20 +1708,27 @@ static ListBase *get_active_constraints2(Object *ob)
return NULL;
}
-static void UNUSED_FUNCTION(RBJconstraints)(Object *ob)//not used
+static void UNUSED_FUNCTION(print_active_constraints2)(Object *ob) //not used, use to debug
{
- ListBase *conlist;
- bConstraint *curcon;
-
- conlist = get_active_constraints2(ob);
+ bConstraint* curcon;
+ ListBase* conlist = get_active_constraints2(ob);
if (conlist) {
for (curcon = (bConstraint *)conlist->first; curcon; curcon = (bConstraint *)curcon->next) {
-
printf("%i\n",curcon->type);
}
+ }
+}
+// Copy base layer to object layer like in BKE_scene_set_background
+static void blenderSceneSetBackground(Scene *blenderscene)
+{
+ Scene *it;
+ Base *base;
+ for (SETLOOPER(blenderscene, it, base)) {
+ base->object->lay = base->lay;
+ base->object->flag = base->flag;
}
}
@@ -1778,12 +1746,21 @@ static KX_GameObject* getGameOb(STR_String busc,CListValue* sumolist)
}
+static bool bl_isConstraintInList(KX_GameObject *gameobj, set<KX_GameObject*> convertedlist)
+{
+ set<KX_GameObject*>::iterator gobit;
+ for (gobit = convertedlist.begin(); gobit != convertedlist.end(); gobit++) {
+ if ((*gobit)->GetName() == gameobj->GetName())
+ return true;
+ }
+ return false;
+}
+
/* helper for BL_ConvertBlenderObjects, avoids code duplication
* note: all var names match args are passed from the caller */
static void bl_ConvertBlenderObject_Single(
KX_BlenderSceneConverter *converter,
- Scene *blenderscene, Object *blenderobject,
- vector<MT_Vector3> &inivel, vector<MT_Vector3> &iniang,
+ Object *blenderobject,
vector<parentChildLink> &vec_parent_child,
CListValue* logicbrick_conversionlist,
CListValue* objectlist, CListValue* inactivelist, CListValue* sumolist,
@@ -1792,10 +1769,6 @@ static void bl_ConvertBlenderObject_Single(
bool isInActiveLayer
)
{
- MT_Point3 posPrev;
- MT_Matrix3x3 angor;
- if (converter->addInitFromFrame) blenderscene->r.cfra=blenderscene->r.sfra;
-
MT_Point3 pos(
blenderobject->loc[0]+blenderobject->dloc[0],
blenderobject->loc[1]+blenderobject->dloc[1],
@@ -1809,35 +1782,6 @@ static void bl_ConvertBlenderObject_Single(
MT_Vector3 scale(blenderobject->size);
- if (converter->addInitFromFrame) {//rcruiz
- blenderscene->r.cfra=blenderscene->r.sfra-1;
- //XXX update_for_newframe();
- MT_Vector3 tmp=pos-MT_Point3(blenderobject->loc[0]+blenderobject->dloc[0],
- blenderobject->loc[1]+blenderobject->dloc[1],
- blenderobject->loc[2]+blenderobject->dloc[2]
- );
-
- float rotmatPrev[3][3];
- BKE_object_rot_to_mat3(blenderobject, rotmatPrev, false);
-
- float eulxyz[3], eulxyzPrev[3];
- mat3_to_eul(eulxyz, rotmat);
- mat3_to_eul(eulxyzPrev, rotmatPrev);
-
- double fps = (double) blenderscene->r.frs_sec/
- (double) blenderscene->r.frs_sec_base;
-
- tmp.scale(fps, fps, fps);
- inivel.push_back(tmp);
- tmp[0]=eulxyz[0]-eulxyzPrev[0];
- tmp[1]=eulxyz[1]-eulxyzPrev[1];
- tmp[2]=eulxyz[2]-eulxyzPrev[2];
- tmp.scale(fps, fps, fps);
- iniang.push_back(tmp);
- blenderscene->r.cfra=blenderscene->r.sfra;
- //XXX update_for_newframe();
- }
-
gameobj->NodeSetLocalPosition(pos);
gameobj->NodeSetLocalOrientation(rotation);
gameobj->NodeSetLocalScale(scale);
@@ -1850,7 +1794,7 @@ static void bl_ConvertBlenderObject_Single(
gameobj->SetName(blenderobject->id.name + 2);
// update children/parent hierarchy
- if ((blenderobject->parent != 0)&&(!converter->addInitFromFrame))
+ if (blenderobject->parent != 0)
{
// blender has an additional 'parentinverse' offset in each object
SG_Callbacks callback(NULL,NULL,NULL,KX_Scene::KX_ScenegraphUpdateFunc,KX_Scene::KX_ScenegraphRescheduleFunc);
@@ -1909,10 +1853,6 @@ static void bl_ConvertBlenderObject_Single(
logicbrick_conversionlist->Add(gameobj->AddRef());
- if (converter->addInitFromFrame) {
- posPrev=gameobj->NodeGetWorldPosition();
- angor=gameobj->NodeGetWorldOrientation();
- }
if (isInActiveLayer)
{
objectlist->Add(gameobj->AddRef());
@@ -1920,7 +1860,6 @@ static void bl_ConvertBlenderObject_Single(
gameobj->NodeUpdateGS(0);
gameobj->AddMeshUser();
-
}
else
{
@@ -1928,11 +1867,6 @@ static void bl_ConvertBlenderObject_Single(
//at the end of this function if it is not a root object
inactivelist->Add(gameobj->AddRef());
}
-
- if (converter->addInitFromFrame) {
- gameobj->NodeSetLocalPosition(posPrev);
- gameobj->NodeSetLocalOrientation(angor);
- }
}
@@ -1951,8 +1885,7 @@ void BL_ConvertBlenderObjects(struct Main* maggie,
#define BL_CONVERTBLENDEROBJECT_SINGLE \
bl_ConvertBlenderObject_Single(converter, \
- blenderscene, blenderobject, \
- inivel, iniang, \
+ blenderobject, \
vec_parent_child, \
logicbrick_conversionlist, \
objectlist, inactivelist, sumolist, \
@@ -1974,7 +1907,6 @@ void BL_ConvertBlenderObjects(struct Main* maggie,
RAS_FrameSettings::RAS_FrameType frame_type;
int aspect_width;
int aspect_height;
- vector<MT_Vector3> inivel,iniang;
set<Group*> grouplist; // list of groups to be converted
set<Object*> allblobj; // all objects converted
set<Object*> groupobj; // objects from groups (never in active layer)
@@ -1983,6 +1915,12 @@ void BL_ConvertBlenderObjects(struct Main* maggie,
// is not in a separate thread.
BL_Texture::GetMaxUnits();
+ /* We have to ensure that group definitions are only converted once
+ * push all converted group members to this set.
+ * This will happen when a group instance is made from a linked group instance
+ * and both are on the active layer. */
+ set<KX_GameObject*> convertedlist;
+
if (alwaysUseExpandFraming) {
frame_type = RAS_FrameSettings::e_frame_extend;
aspect_width = canvas->GetWidth();
@@ -2046,6 +1984,9 @@ void BL_ConvertBlenderObjects(struct Main* maggie,
}
SetDefaultLightMode(blenderscene);
+
+ blenderSceneSetBackground(blenderscene);
+
// Let's support scene set.
// Beware of name conflict in linked data, it will not crash but will create confusion
// in Python scripting and in certain actuators (replace mesh). Linked scene *should* have
@@ -2061,23 +2002,15 @@ void BL_ConvertBlenderObjects(struct Main* maggie,
rendertools,
converter,
libloading);
-
- bool isInActiveLayer = (blenderobject->lay & activeLayerBitInfo) !=0;
- bool addobj=true;
-
- if (converter->addInitFromFrame)
- if (!isInActiveLayer)
- addobj=false;
+ bool isInActiveLayer = (blenderobject->lay & activeLayerBitInfo) !=0;
if (gameobj)
{
- if (addobj)
- { /* macro calls object conversion funcs */
- BL_CONVERTBLENDEROBJECT_SINGLE;
+ /* macro calls object conversion funcs */
+ BL_CONVERTBLENDEROBJECT_SINGLE;
- if (gameobj->IsDupliGroup()) {
- grouplist.insert(blenderobject->dup_group);
- }
+ if (gameobj->IsDupliGroup()) {
+ grouplist.insert(blenderobject->dup_group);
}
/* Note about memory leak issues:
@@ -2121,22 +2054,16 @@ void BL_ConvertBlenderObjects(struct Main* maggie,
rendertools,
converter,
libloading);
-
- // this code is copied from above except that
- // object from groups are never in active layer
+
bool isInActiveLayer = false;
- bool addobj=true;
-
- if (converter->addInitFromFrame)
- if (!isInActiveLayer)
- addobj=false;
-
- if (gameobj)
- {
- if (addobj)
- { /* macro calls object conversion funcs */
- BL_CONVERTBLENDEROBJECT_SINGLE;
- }
+ if (gameobj) {
+ /* Insert object to the constraint game object list
+ * so we can check later if there is a instance in the scene or
+ * an instance and its actual group definition. */
+ convertedlist.insert((KX_GameObject*)gameobj->AddRef());
+
+ /* macro calls object conversion funcs */
+ BL_CONVERTBLENDEROBJECT_SINGLE;
if (gameobj->IsDupliGroup())
{
@@ -2146,7 +2073,6 @@ void BL_ConvertBlenderObjects(struct Main* maggie,
}
}
-
/* see comment above re: mem leaks */
gameobj->Release();
}
@@ -2260,8 +2186,6 @@ void BL_ConvertBlenderObjects(struct Main* maggie,
case PARSKEL: // skinned - ignore
break;
case PAROBJECT:
- case PARCURVE:
- case PARKEY:
case PARVERT3:
default:
// unhandled
@@ -2338,7 +2262,6 @@ void BL_ConvertBlenderObjects(struct Main* maggie,
}
bool processCompoundChildren = false;
-
// create physics information
for (i=0;i<sumolist->GetCount();i++)
{
@@ -2369,131 +2292,64 @@ void BL_ConvertBlenderObjects(struct Main* maggie,
int layerMask = (groupobj.find(blenderobject) == groupobj.end()) ? activeLayerBitInfo : 0;
BL_CreatePhysicsObjectNew(gameobj,blenderobject,meshobj,kxscene,layerMask,converter,processCompoundChildren);
}
-
- //set ini linearVel and int angularVel //rcruiz
- if (converter->addInitFromFrame)
- for (i=0;i<sumolist->GetCount();i++)
- {
- KX_GameObject* gameobj = (KX_GameObject*) sumolist->GetValue(i);
- if (gameobj->IsDynamic()) {
- gameobj->setLinearVelocity(inivel[i],false);
- gameobj->setAngularVelocity(iniang[i],false);
- }
-
-
- }
- // create physics joints
+ // create physics joints
for (i=0;i<sumolist->GetCount();i++)
{
- KX_GameObject* gameobj = (KX_GameObject*) sumolist->GetValue(i);
- struct Object* blenderobject = gameobj->GetBlenderObject();
- ListBase *conlist;
+ PHY_IPhysicsEnvironment *physEnv = kxscene->GetPhysicsEnvironment();
+ KX_GameObject *gameobj = (KX_GameObject *)sumolist->GetValue(i);
+ struct Object *blenderobject = gameobj->GetBlenderObject();
+ ListBase *conlist = get_active_constraints2(blenderobject);
bConstraint *curcon;
- conlist = get_active_constraints2(blenderobject);
- if ((gameobj->GetLayer()&activeLayerBitInfo)==0)
+ if (!conlist)
continue;
- if (conlist) {
- for (curcon = (bConstraint *)conlist->first; curcon; curcon = (bConstraint *)curcon->next) {
- if (curcon->type==CONSTRAINT_TYPE_RIGIDBODYJOINT) {
+ for (curcon = (bConstraint *)conlist->first; curcon; curcon = (bConstraint *)curcon->next) {
+ if (curcon->type != CONSTRAINT_TYPE_RIGIDBODYJOINT)
+ continue;
- bRigidBodyJointConstraint *dat=(bRigidBodyJointConstraint *)curcon->data;
+ bRigidBodyJointConstraint *dat = (bRigidBodyJointConstraint *)curcon->data;
+
+ /* Skip if no target or a child object is selected or constraints are deactivated */
+ if (!dat->tar || dat->child || (curcon->flag & CONSTRAINT_OFF))
+ continue;
- if (!dat->child && !(curcon->flag & CONSTRAINT_OFF)) {
+ /* Store constraints of grouped and instanced objects for all layers */
+ gameobj->AddConstraint(dat);
- PHY_IPhysicsController* physctr2 = 0;
+ /** if it's during libload we only add constraints in the object but
+ * doesn't create it. Constraint will be replicated later in scene->MergeScene
+ */
+ if (libloading)
+ continue;
- if (dat->tar)
- {
- KX_GameObject *gotar=getGameOb(dat->tar->id.name+2,sumolist);
- if (gotar && ((gotar->GetLayer()&activeLayerBitInfo)!=0) && gotar->GetPhysicsController())
- physctr2 = gotar->GetPhysicsController();
- }
+ /* Skipped already converted constraints.
+ * This will happen when a group instance is made from a linked group instance
+ * and both are on the active layer. */
+ if (bl_isConstraintInList(gameobj, convertedlist))
+ continue;
- if (gameobj->GetPhysicsController())
- {
- PHY_IPhysicsController* physctrl = gameobj->GetPhysicsController();
- //we need to pass a full constraint frame, not just axis
-
- //localConstraintFrameBasis
- MT_Matrix3x3 localCFrame(MT_Vector3(dat->axX,dat->axY,dat->axZ));
- MT_Vector3 axis0 = localCFrame.getColumn(0);
- MT_Vector3 axis1 = localCFrame.getColumn(1);
- MT_Vector3 axis2 = localCFrame.getColumn(2);
-
- int constraintId = kxscene->GetPhysicsEnvironment()->CreateConstraint(physctrl,physctr2,(PHY_ConstraintType)dat->type,(float)dat->pivX,
- (float)dat->pivY,(float)dat->pivZ,
- (float)axis0.x(),(float)axis0.y(),(float)axis0.z(),
- (float)axis1.x(),(float)axis1.y(),(float)axis1.z(),
- (float)axis2.x(),(float)axis2.y(),(float)axis2.z(),dat->flag);
- if (constraintId)
- {
- //if it is a generic 6DOF constraint, set all the limits accordingly
- if (dat->type == PHY_GENERIC_6DOF_CONSTRAINT)
- {
- int dof;
- int dofbit=1;
- for (dof=0;dof<6;dof++)
- {
- if (dat->flag & dofbit)
- {
- kxscene->GetPhysicsEnvironment()->SetConstraintParam(constraintId,dof,dat->minLimit[dof],dat->maxLimit[dof]);
- } else
- {
- //minLimit > maxLimit means free(disabled limit) for this degree of freedom
- kxscene->GetPhysicsEnvironment()->SetConstraintParam(constraintId,dof,1,-1);
- }
- dofbit<<=1;
- }
- }
- else if (dat->type == PHY_CONE_TWIST_CONSTRAINT)
- {
- int dof;
- int dofbit = 1<<3; // bitflag use_angular_limit_x
-
- for (dof=3;dof<6;dof++)
- {
- if (dat->flag & dofbit)
- {
- kxscene->GetPhysicsEnvironment()->SetConstraintParam(constraintId,dof,dat->minLimit[dof],dat->maxLimit[dof]);
- }
- else
- {
- //maxLimit < 0 means free(disabled limit) for this degree of freedom
- kxscene->GetPhysicsEnvironment()->SetConstraintParam(constraintId,dof,1,-1);
- }
- dofbit<<=1;
- }
- }
- else if (dat->type == PHY_LINEHINGE_CONSTRAINT)
- {
- int dof = 3; // dof for angular x
- int dofbit = 1<<3; // bitflag use_angular_limit_x
-
- if (dat->flag & dofbit)
- {
- kxscene->GetPhysicsEnvironment()->SetConstraintParam(constraintId,dof,
- dat->minLimit[dof],dat->maxLimit[dof]);
- } else
- {
- //minLimit > maxLimit means free(disabled limit) for this degree of freedom
- kxscene->GetPhysicsEnvironment()->SetConstraintParam(constraintId,dof,1,-1);
- }
- }
- }
- }
- }
- }
+ KX_GameObject *gotar = getGameOb(dat->tar->id.name + 2, sumolist);
+
+ if (gotar && (gotar->GetLayer()&activeLayerBitInfo) && gotar->GetPhysicsController() &&
+ (gameobj->GetLayer()&activeLayerBitInfo) && gameobj->GetPhysicsController())
+ {
+ physEnv->SetupObjectConstraints(gameobj, gotar, dat);
}
}
}
+ /* cleanup converted set of group objects */
+ set<KX_GameObject*>::iterator gobit;
+ for (gobit = convertedlist.begin(); gobit != convertedlist.end(); gobit++)
+ (*gobit)->Release();
+
+ convertedlist.clear();
sumolist->Release();
// convert world
- KX_WorldInfo* worldinfo = new BlenderWorldInfo(blenderscene, blenderscene->world);
+ KX_WorldInfo* worldinfo = new KX_WorldInfo(blenderscene, blenderscene->world);
converter->RegisterWorldInfo(worldinfo);
kxscene->SetWorldInfo(worldinfo);
@@ -2537,8 +2393,6 @@ void BL_ConvertBlenderObjects(struct Main* maggie,
}
}
-#define CONVERT_LOGIC
-#ifdef CONVERT_LOGIC
// convert logic bricks, sensors, controllers and actuators
for (i=0;i<logicbrick_conversionlist->GetCount();i++)
{
@@ -2573,8 +2427,6 @@ void BL_ConvertBlenderObjects(struct Main* maggie,
gameobj->ResetState();
}
-#endif //CONVERT_LOGIC
-
logicbrick_conversionlist->Release();
// Calculate the scene btree -
@@ -2601,7 +2453,3 @@ void BL_ConvertBlenderObjects(struct Main* maggie,
bucketmanager->OptimizeBuckets(distance);
}
-SCA_IInputDevice::KX_EnumInputs ConvertKeyCode(int key_code)
-{
- return gReverseKeyTranslateTable[key_code];
-}
diff --git a/source/gameengine/Converter/BL_BlenderDataConversion.h b/source/gameengine/Converter/BL_BlenderDataConversion.h
index 6bd77954b88..22210cc6035 100644
--- a/source/gameengine/Converter/BL_BlenderDataConversion.h
+++ b/source/gameengine/Converter/BL_BlenderDataConversion.h
@@ -34,7 +34,7 @@
#include "CTR_HashedPtr.h"
#include "STR_String.h"
-#include "KX_Python.h"
+#include "EXP_Python.h"
#include "KX_PhysicsEngineEnums.h"
#include "SCA_IInputDevice.h"
diff --git a/source/gameengine/Converter/BL_ModifierDeformer.cpp b/source/gameengine/Converter/BL_ModifierDeformer.cpp
index 71dc1bdec87..3bc07113ff6 100644
--- a/source/gameengine/Converter/BL_ModifierDeformer.cpp
+++ b/source/gameengine/Converter/BL_ModifierDeformer.cpp
@@ -186,6 +186,7 @@ bool BL_ModifierDeformer::Update(void)
m_dm->release(m_dm);
// HACK! use deformedOnly as a user counter
m_dm->deformedOnly = 1;
+ DM_update_materials(m_dm, blendobj);
/* update the graphic controller */
PHY_IGraphicController *ctrl = m_gameobj->GetGraphicController();
if (ctrl) {
diff --git a/source/gameengine/Converter/BL_ShapeActionActuator.cpp b/source/gameengine/Converter/BL_ShapeActionActuator.cpp
index 67712c683f9..e8f451213f5 100644
--- a/source/gameengine/Converter/BL_ShapeActionActuator.cpp
+++ b/source/gameengine/Converter/BL_ShapeActionActuator.cpp
@@ -48,8 +48,8 @@
#include "BLI_math.h"
#include "MT_Matrix4x4.h"
-#include "FloatValue.h"
-#include "PyObjectPlus.h"
+#include "EXP_FloatValue.h"
+#include "EXP_PyObjectPlus.h"
extern "C" {
#include "BKE_animsys.h"
diff --git a/source/gameengine/Converter/BL_SkinDeformer.cpp b/source/gameengine/Converter/BL_SkinDeformer.cpp
index e7137a5c379..950c1dcad11 100644
--- a/source/gameengine/Converter/BL_SkinDeformer.cpp
+++ b/source/gameengine/Converter/BL_SkinDeformer.cpp
@@ -200,12 +200,14 @@ void BL_SkinDeformer::BGEDeformVerts()
Object *par_arma = m_armobj->GetArmatureObject();
MDeformVert *dverts = m_bmesh->dvert;
bDeformGroup *dg;
- int defbase_tot = BLI_countlist(&m_objMesh->defbase);
+ int defbase_tot;
Eigen::Matrix4f pre_mat, post_mat, chan_mat, norm_chan_mat;
if (!dverts)
return;
+ defbase_tot = BLI_listbase_count(&m_objMesh->defbase);
+
if (m_dfnrToPC == NULL)
{
m_dfnrToPC = new bPoseChannel*[defbase_tot];
diff --git a/source/gameengine/Converter/BlenderWorldInfo.cpp b/source/gameengine/Converter/BlenderWorldInfo.cpp
deleted file mode 100644
index 75beb5d0e0e..00000000000
--- a/source/gameengine/Converter/BlenderWorldInfo.cpp
+++ /dev/null
@@ -1,200 +0,0 @@
-/*
- * ***** BEGIN GPL LICENSE BLOCK *****
- *
- * This program is free software; you can [0]istribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
- * All rights reserved.
- *
- * The Original Code is: all of this file.
- *
- * Contributor(s): none yet.
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-
-/** \file gameengine/Converter/BlenderWorldInfo.cpp
- * \ingroup bgeconv
- */
-
-
-#include <stdio.h> // printf()
-
-#include "BlenderWorldInfo.h"
-
-/* This little block needed for linking to Blender... */
-#ifdef WIN32
-#include "BLI_winstuff.h"
-#endif
-
-/* This list includes only data type definitions */
-#include "DNA_object_types.h"
-#include "DNA_material_types.h"
-#include "DNA_image_types.h"
-#include "DNA_lamp_types.h"
-#include "DNA_group_types.h"
-#include "DNA_scene_types.h"
-#include "DNA_camera_types.h"
-#include "DNA_property_types.h"
-#include "DNA_text_types.h"
-#include "DNA_sensor_types.h"
-#include "DNA_controller_types.h"
-#include "DNA_actuator_types.h"
-#include "DNA_mesh_types.h"
-#include "DNA_meshdata_types.h"
-#include "DNA_view3d_types.h"
-#include "DNA_world_types.h"
-#include "DNA_screen_types.h"
-
-#include "BLI_math.h"
-
-#include "BKE_global.h"
-#include "BKE_scene.h"
-/* end of blender include block */
-
-
-BlenderWorldInfo::BlenderWorldInfo(struct Scene *blenderscene, struct World *blenderworld)
-{
- if (blenderworld) {
- m_hasworld = true;
-
- // do we have mist?
- if ((blenderworld->mode) & WO_MIST) {
- m_hasmist = true;
- m_miststart = blenderworld->miststa;
- m_mistdistance = blenderworld->mistdist;
- copy_v3_v3(m_mistcolor, &blenderworld->horr);
- }
- else {
- m_hasmist = false;
- m_miststart = 0.0;
- m_mistdistance = 0.0;
- zero_v3(m_mistcolor);
- }
-
- copy_v3_v3(m_backgroundcolor, &blenderworld->horr);
- copy_v3_v3(m_ambientcolor, &blenderworld->ambr);
-
- if (BKE_scene_check_color_management_enabled(blenderscene)) {
- linearrgb_to_srgb_v3_v3(m_mistcolor, m_mistcolor);
- linearrgb_to_srgb_v3_v3(m_backgroundcolor, m_backgroundcolor);
- linearrgb_to_srgb_v3_v3(m_ambientcolor, m_ambientcolor);
- }
- }
- else {
- m_hasworld = false;
- }
-}
-
-BlenderWorldInfo::~BlenderWorldInfo()
-{
-}
-
-bool BlenderWorldInfo::hasWorld()
-{
- return m_hasworld;
-}
-
-bool BlenderWorldInfo::hasMist()
-{
- return m_hasmist;
-}
-
-float BlenderWorldInfo::getBackColorRed()
-{
- return m_backgroundcolor[0];
-}
-
-float BlenderWorldInfo::getBackColorGreen()
-{
- return m_backgroundcolor[1];
-}
-
-float BlenderWorldInfo::getBackColorBlue()
-{
- return m_backgroundcolor[2];
-}
-
-float BlenderWorldInfo::getAmbientColorRed()
-{
- return m_ambientcolor[0];
-}
-
-float BlenderWorldInfo::getAmbientColorGreen()
-{
- return m_ambientcolor[1];
-}
-
-float BlenderWorldInfo::getAmbientColorBlue()
-{
- return m_ambientcolor[2];
-}
-
-float BlenderWorldInfo::getMistStart()
-{
- return m_miststart;
-}
-
-float BlenderWorldInfo::getMistDistance()
-{
- return m_mistdistance;
-}
-
-float BlenderWorldInfo::getMistColorRed()
-{
- return m_mistcolor[0];
-}
-
-float BlenderWorldInfo::getMistColorGreen()
-{
- return m_mistcolor[1];
-}
-
-float BlenderWorldInfo::getMistColorBlue()
-{
- return m_mistcolor[2];
-}
-
-void BlenderWorldInfo::setBackColor(float r, float g, float b)
-{
- m_backgroundcolor[0] = r;
- m_backgroundcolor[1] = g;
- m_backgroundcolor[2] = b;
-}
-
-void BlenderWorldInfo::setMistStart(float d)
-{
- m_miststart = d;
-}
-
-void BlenderWorldInfo::setMistDistance(float d)
-{
- m_mistdistance = d;
-}
-
-void BlenderWorldInfo::setMistColorRed(float d)
-{
- m_mistcolor[0] = d;
-}
-
-void BlenderWorldInfo::setMistColorGreen(float d)
-{
- m_mistcolor[1] = d;
-}
-
-void BlenderWorldInfo::setMistColorBlue(float d)
-{
- m_mistcolor[2] = d;
-}
diff --git a/source/gameengine/Converter/BlenderWorldInfo.h b/source/gameengine/Converter/BlenderWorldInfo.h
deleted file mode 100644
index 2ac2d70b5d1..00000000000
--- a/source/gameengine/Converter/BlenderWorldInfo.h
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * ***** BEGIN GPL LICENSE BLOCK *****
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
- * All rights reserved.
- *
- * The Original Code is: all of this file.
- *
- * Contributor(s): none yet.
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-
-/** \file BlenderWorldInfo.h
- * \ingroup bgeconv
- */
-
-#ifndef __BLENDERWORLDINFO_H__
-#define __BLENDERWORLDINFO_H__
-#include "MT_CmMatrix4x4.h"
-#include "KX_WorldInfo.h"
-
-class BlenderWorldInfo : public KX_WorldInfo
-{
- bool m_hasworld;
- float m_backgroundcolor[3];
-
- bool m_hasmist;
- float m_miststart;
- float m_mistdistance;
- float m_mistcolor[3];
-
- float m_ambientcolor[3];
-
-public:
- BlenderWorldInfo(struct Scene *blenderscene, struct World *blenderworld);
- ~BlenderWorldInfo();
-
- bool hasWorld();
- bool hasMist();
- float getBackColorRed();
- float getBackColorGreen();
- float getBackColorBlue();
-
- float getAmbientColorRed();
- float getAmbientColorGreen();
- float getAmbientColorBlue();
-
- float getMistStart();
- float getMistDistance();
- float getMistColorRed();
- float getMistColorGreen();
- float getMistColorBlue();
-
- void setBackColor(float r, float g, float b);
- void setMistStart(float d);
- void setMistDistance(float d);
- void setMistColorRed(float d);
- void setMistColorGreen(float d);
- void setMistColorBlue(float d);
-
-
-#ifdef WITH_CXX_GUARDEDALLOC
- MEM_CXX_CLASS_ALLOC_FUNCS("GE:BlenderWorldInfo")
-#endif
-};
-
-#endif /* __BLENDERWORLDINFO_H__ */
diff --git a/source/gameengine/Converter/CMakeLists.txt b/source/gameengine/Converter/CMakeLists.txt
index 9c0d25e56ff..4db9fcebd06 100644
--- a/source/gameengine/Converter/CMakeLists.txt
+++ b/source/gameengine/Converter/CMakeLists.txt
@@ -56,7 +56,7 @@ set(INC
set(INC_SYS
../../../intern/moto/include
../../../extern/recastnavigation/Detour/Include
- ../../../extern/Eigen3
+ ${EIGEN3_INCLUDE_DIRS}
${PTHREADS_INCLUDE_DIRS}
${BOOST_INCLUDE_DIR}
)
@@ -74,7 +74,6 @@ set(SRC
BL_ShapeActionActuator.cpp
BL_ShapeDeformer.cpp
BL_SkinDeformer.cpp
- BlenderWorldInfo.cpp
KX_BlenderScalarInterpolator.cpp
KX_BlenderSceneConverter.cpp
KX_ConvertActuators.cpp
@@ -96,7 +95,6 @@ set(SRC
BL_ShapeActionActuator.h
BL_ShapeDeformer.h
BL_SkinDeformer.h
- BlenderWorldInfo.h
KX_BlenderScalarInterpolator.h
KX_BlenderSceneConverter.h
KX_ConvertActuators.h
@@ -115,10 +113,11 @@ if(WITH_BULLET)
endif()
if(WITH_AUDASPACE)
- list(APPEND INC
- ../../../intern/audaspace/intern
+ add_definitions(${AUDASPACE_DEFINITIONS})
+
+ list(APPEND INC_SYS
+ ${AUDASPACE_C_INCLUDE_DIRS}
)
- add_definitions(-DWITH_AUDASPACE)
endif()
blender_add_lib(ge_converter "${SRC}" "${INC}" "${INC_SYS}")
diff --git a/source/gameengine/Converter/KX_BlenderSceneConverter.cpp b/source/gameengine/Converter/KX_BlenderSceneConverter.cpp
index a20ebb3a081..9d01d3d5a39 100644
--- a/source/gameengine/Converter/KX_BlenderSceneConverter.cpp
+++ b/source/gameengine/Converter/KX_BlenderSceneConverter.cpp
@@ -58,7 +58,7 @@
#include "KX_LibLoadStatus.h"
#include "KX_BlenderScalarInterpolator.h"
#include "BL_BlenderDataConversion.h"
-#include "BlenderWorldInfo.h"
+#include "KX_WorldInfo.h"
/* This little block needed for linking to Blender... */
#ifdef WIN32
@@ -69,6 +69,7 @@
#include "DNA_scene_types.h"
#include "DNA_world_types.h"
#include "BKE_main.h"
+#include "BKE_fcurve.h"
#include "BLI_math.h"
@@ -87,6 +88,7 @@ extern "C"
#include "BKE_mesh.h" // BKE_mesh_copy
#include "DNA_space_types.h"
#include "DNA_anim_types.h"
+#include "DNA_action_types.h"
#include "RNA_define.h"
#include "../../blender/editors/include/ED_keyframing.h"
}
@@ -115,11 +117,9 @@ typedef struct ThreadInfo {
} ThreadInfo;
KX_BlenderSceneConverter::KX_BlenderSceneConverter(
- struct Main* maggie,
- class KX_KetsjiEngine* engine
- )
- : m_maggie(maggie),
- /*m_maggie_dyn(NULL),*/
+ Main *maggie,
+ KX_KetsjiEngine *engine)
+ :m_maggie(maggie),
m_ketsjiEngine(engine),
m_alwaysUseExpandFraming(false),
m_usemat(false),
@@ -132,13 +132,11 @@ KX_BlenderSceneConverter::KX_BlenderSceneConverter(
pthread_mutex_init(&m_threadinfo->merge_lock, NULL);
}
-
KX_BlenderSceneConverter::~KX_BlenderSceneConverter()
{
// clears meshes, and hashmaps from blender to gameengine data
- int i;
// delete sumoshapes
-
+
if (m_threadinfo) {
vector<pthread_t>::iterator pit = m_threadinfo->threads.begin();
while (pit != m_threadinfo->threads.end()) {
@@ -151,104 +149,83 @@ KX_BlenderSceneConverter::~KX_BlenderSceneConverter()
}
int numAdtLists = m_map_blender_to_gameAdtList.size();
- for (i=0; i<numAdtLists; i++) {
- BL_InterpolatorList *adtList= *m_map_blender_to_gameAdtList.at(i);
+ for (int i = 0; i < numAdtLists; i++) {
+ BL_InterpolatorList *adtList = *m_map_blender_to_gameAdtList.at(i);
delete (adtList);
}
- vector<pair<KX_Scene*,KX_WorldInfo*> >::iterator itw = m_worldinfos.begin();
+ vector<pair<KX_Scene *, KX_WorldInfo *> >::iterator itw = m_worldinfos.begin();
while (itw != m_worldinfos.end()) {
- delete (*itw).second;
+ delete itw->second;
itw++;
}
m_worldinfos.clear();
- vector<pair<KX_Scene*,RAS_IPolyMaterial*> >::iterator itp = m_polymaterials.begin();
+ vector<pair<KX_Scene *,RAS_IPolyMaterial *> >::iterator itp = m_polymaterials.begin();
while (itp != m_polymaterials.end()) {
- //m_polymat_cache.erase((*itp).second->GetBlenderMaterial());
- delete (*itp).second;
+ delete itp->second;
itp++;
}
m_polymaterials.clear();
// delete after RAS_IPolyMaterial
- vector<pair<KX_Scene*,BL_Material *> >::iterator itmat = m_materials.begin();
+ vector<pair<KX_Scene *,BL_Material *> >::iterator itmat = m_materials.begin();
while (itmat != m_materials.end()) {
- //m_mat_cache.erase((*itmat).second->material);
- delete (*itmat).second;
+ delete itmat->second;
itmat++;
}
m_materials.clear();
-
- vector<pair<KX_Scene*,RAS_MeshObject*> >::iterator itm = m_meshobjects.begin();
+ vector<pair<KX_Scene *,RAS_MeshObject *> >::iterator itm = m_meshobjects.begin();
while (itm != m_meshobjects.end()) {
- delete (*itm).second;
+ delete itm->second;
itm++;
}
m_meshobjects.clear();
-
/* free any data that was dynamically loaded */
- while (m_DynamicMaggie.size() != 0)
- {
+ while (m_DynamicMaggie.size() != 0) {
FreeBlendFile(m_DynamicMaggie[0]);
}
m_DynamicMaggie.clear();
}
-void KX_BlenderSceneConverter::SetNewFileName(const STR_String& filename)
+void KX_BlenderSceneConverter::SetNewFileName(const STR_String &filename)
{
m_newfilename = filename;
}
-
-
bool KX_BlenderSceneConverter::TryAndLoadNewFile()
{
bool result = false;
- // find the file
-/* if ()
- {
- result = true;
- }
- // if not, clear the newfilename
- else
- {
- m_newfilename = "";
- }
-*/
return result;
}
-Scene *KX_BlenderSceneConverter::GetBlenderSceneForName(const STR_String& name)
+Scene *KX_BlenderSceneConverter::GetBlenderSceneForName(const STR_String &name)
{
Scene *sce;
/**
* Find the specified scene by name, or NULL if nothing matches.
*/
- if ((sce= (Scene *)BLI_findstring(&m_maggie->scene, name.ReadPtr(), offsetof(ID, name) + 2)))
+ if ((sce = (Scene *)BLI_findstring(&m_maggie->scene, name.ReadPtr(), offsetof(ID, name) + 2)))
return sce;
- for (vector<Main*>::iterator it=m_DynamicMaggie.begin(); !(it==m_DynamicMaggie.end()); it++) {
- Main *main= *it;
+ for (vector<Main *>::iterator it=m_DynamicMaggie.begin(); !(it == m_DynamicMaggie.end()); it++) {
+ Main *main = *it;
if ((sce= (Scene *)BLI_findstring(&main->scene, name.ReadPtr(), offsetof(ID, name) + 2)))
return sce;
}
return NULL;
-
}
-void KX_BlenderSceneConverter::ConvertScene(class KX_Scene* destinationscene,
- class RAS_IRasterizer* rendertools,
- class RAS_ICanvas* canvas,
- bool libloading)
+void KX_BlenderSceneConverter::ConvertScene(KX_Scene *destinationscene, RAS_IRasterizer *rendertools,
+ RAS_ICanvas *canvas, bool libloading)
{
//find out which physics engine
Scene *blenderscene = destinationscene->GetBlenderScene();
@@ -264,13 +241,12 @@ void KX_BlenderSceneConverter::ConvertScene(class KX_Scene* destinationscene,
// when doing threaded conversion, so it's disabled for now.
// SG_SetActiveStage(SG_STAGE_CONVERTER);
- switch (blenderscene->gm.physicsEngine)
- {
+ switch (blenderscene->gm.physicsEngine) {
#ifdef WITH_BULLET
case WOPHY_BULLET:
{
SYS_SystemHandle syshandle = SYS_GetSystem(); /*unused*/
- int visualizePhysics = SYS_GetCommandLineInt(syshandle,"show_physics",0);
+ int visualizePhysics = SYS_GetCommandLineInt(syshandle, "show_physics", 0);
phy_env = CcdPhysicsEnvironment::Create(blenderscene, visualizePhysics);
physics_engine = UseBullet;
@@ -289,7 +265,8 @@ void KX_BlenderSceneConverter::ConvertScene(class KX_Scene* destinationscene,
destinationscene->SetPhysicsEnvironment(phy_env);
- BL_ConvertBlenderObjects(m_maggie,
+ BL_ConvertBlenderObjects(
+ m_maggie,
destinationscene,
m_ketsjiEngine,
physics_engine,
@@ -297,8 +274,7 @@ void KX_BlenderSceneConverter::ConvertScene(class KX_Scene* destinationscene,
canvas,
this,
m_alwaysUseExpandFraming,
- libloading
- );
+ libloading);
//These lookup are not needed during game
m_map_blender_to_gameactuator.clear();
@@ -324,30 +300,32 @@ void KX_BlenderSceneConverter::RemoveScene(KX_Scene *scene)
// delete the scene first as it will stop the use of entities
delete scene;
// delete the entities of this scene
- vector<pair<KX_Scene*,KX_WorldInfo*> >::iterator worldit;
+ vector<pair<KX_Scene *, KX_WorldInfo *> >::iterator worldit;
size = m_worldinfos.size();
- for (i=0, worldit=m_worldinfos.begin(); i<size; ) {
- if ((*worldit).first == scene) {
- delete (*worldit).second;
+ for (i = 0, worldit = m_worldinfos.begin(); i < size; ) {
+ if (worldit->first == scene) {
+ delete worldit->second;
*worldit = m_worldinfos.back();
m_worldinfos.pop_back();
size--;
- } else {
+ }
+ else {
i++;
worldit++;
}
}
- vector<pair<KX_Scene*,RAS_IPolyMaterial*> >::iterator polymit;
+ vector<pair<KX_Scene *, RAS_IPolyMaterial *> >::iterator polymit;
size = m_polymaterials.size();
- for (i=0, polymit=m_polymaterials.begin(); i<size; ) {
- if ((*polymit).first == scene) {
- m_polymat_cache[scene].erase((*polymit).second->GetBlenderMaterial());
- delete (*polymit).second;
+ for (i = 0, polymit = m_polymaterials.begin(); i < size; ) {
+ if (polymit->first == scene) {
+ m_polymat_cache[scene].erase(polymit->second->GetBlenderMaterial());
+ delete polymit->second;
*polymit = m_polymaterials.back();
m_polymaterials.pop_back();
size--;
- } else {
+ }
+ else {
i++;
polymit++;
}
@@ -355,16 +333,17 @@ void KX_BlenderSceneConverter::RemoveScene(KX_Scene *scene)
m_polymat_cache.erase(scene);
- vector<pair<KX_Scene*,BL_Material*> >::iterator matit;
+ vector<pair<KX_Scene *, BL_Material *> >::iterator matit;
size = m_materials.size();
- for (i=0, matit=m_materials.begin(); i<size; ) {
- if ((*matit).first == scene) {
- m_mat_cache[scene].erase((*matit).second->material);
- delete (*matit).second;
+ for (i = 0, matit = m_materials.begin(); i < size; ) {
+ if (matit->first == scene) {
+ m_mat_cache[scene].erase(matit->second->material);
+ delete matit->second;
*matit = m_materials.back();
m_materials.pop_back();
size--;
- } else {
+ }
+ else {
i++;
matit++;
}
@@ -372,15 +351,16 @@ void KX_BlenderSceneConverter::RemoveScene(KX_Scene *scene)
m_mat_cache.erase(scene);
- vector<pair<KX_Scene*,RAS_MeshObject*> >::iterator meshit;
+ vector<pair<KX_Scene *, RAS_MeshObject *> >::iterator meshit;
size = m_meshobjects.size();
- for (i=0, meshit=m_meshobjects.begin(); i<size; ) {
- if ((*meshit).first == scene) {
- delete (*meshit).second;
+ for (i = 0, meshit = m_meshobjects.begin(); i < size; ) {
+ if (meshit->first == scene) {
+ delete meshit->second;
*meshit = m_meshobjects.back();
m_meshobjects.pop_back();
size--;
- } else {
+ }
+ else {
i++;
meshit++;
}
@@ -423,43 +403,34 @@ bool KX_BlenderSceneConverter::GetCacheMaterials()
void KX_BlenderSceneConverter::RegisterBlenderMaterial(BL_Material *mat)
{
// First make sure we don't register the material twice
- vector<pair<KX_Scene*,BL_Material*> >::iterator it;
+ vector<pair<KX_Scene *, BL_Material *> >::iterator it;
for (it = m_materials.begin(); it != m_materials.end(); ++it)
if (it->second == mat)
return;
- m_materials.push_back(pair<KX_Scene*,BL_Material *>(m_currentScene,mat));
+ m_materials.push_back(pair<KX_Scene *, BL_Material *> (m_currentScene, mat));
}
-
-
-void KX_BlenderSceneConverter::SetAlwaysUseExpandFraming(
- bool to_what)
+void KX_BlenderSceneConverter::SetAlwaysUseExpandFraming(bool to_what)
{
m_alwaysUseExpandFraming= to_what;
}
-
-
-void KX_BlenderSceneConverter::RegisterGameObject(
- KX_GameObject *gameobject,
- struct Object *for_blenderobject)
+void KX_BlenderSceneConverter::RegisterGameObject(KX_GameObject *gameobject, Object *for_blenderobject)
{
/* only maintained while converting, freed during game runtime */
- m_map_blender_to_gameobject.insert(CHashedPtr(for_blenderobject),gameobject);
+ m_map_blender_to_gameobject.insert(CHashedPtr(for_blenderobject), gameobject);
}
/* only need to run this during conversion since
* m_map_blender_to_gameobject is freed after conversion */
-void KX_BlenderSceneConverter::UnregisterGameObject(
- KX_GameObject *gameobject)
+void KX_BlenderSceneConverter::UnregisterGameObject(KX_GameObject *gameobject)
{
- struct Object *bobp= gameobject->GetBlenderObject();
+ Object *bobp = gameobject->GetBlenderObject();
if (bobp) {
CHashedPtr bptr(bobp);
- KX_GameObject **gobp= m_map_blender_to_gameobject[bptr];
- if (gobp && *gobp == gameobject)
- {
+ KX_GameObject **gobp = m_map_blender_to_gameobject[bptr];
+ if (gobp && *gobp == gameobject) {
// also maintain m_map_blender_to_gameobject if the gameobject
// being removed is matching the blender object
m_map_blender_to_gameobject.remove(bptr);
@@ -467,47 +438,41 @@ void KX_BlenderSceneConverter::UnregisterGameObject(
}
}
-KX_GameObject *KX_BlenderSceneConverter::FindGameObject(
- struct Object *for_blenderobject)
+KX_GameObject *KX_BlenderSceneConverter::FindGameObject(Object *for_blenderobject)
{
- KX_GameObject **obp= m_map_blender_to_gameobject[CHashedPtr(for_blenderobject)];
-
- return obp?*obp:NULL;
+ KX_GameObject **obp = m_map_blender_to_gameobject[CHashedPtr(for_blenderobject)];
+
+ return obp ? *obp : NULL;
}
-void KX_BlenderSceneConverter::RegisterGameMesh(
- RAS_MeshObject *gamemesh,
- struct Mesh *for_blendermesh)
+void KX_BlenderSceneConverter::RegisterGameMesh(RAS_MeshObject *gamemesh, Mesh *for_blendermesh)
{
if (for_blendermesh) { /* dynamically loaded meshes we don't want to keep lookups for */
m_map_mesh_to_gamemesh.insert(CHashedPtr(for_blendermesh),gamemesh);
}
- m_meshobjects.push_back(pair<KX_Scene*,RAS_MeshObject*>(m_currentScene,gamemesh));
+ m_meshobjects.push_back(pair<KX_Scene *, RAS_MeshObject *> (m_currentScene,gamemesh));
}
-
-
-RAS_MeshObject *KX_BlenderSceneConverter::FindGameMesh(
- struct Mesh *for_blendermesh/*,
- unsigned int onlayer*/)
+RAS_MeshObject *KX_BlenderSceneConverter::FindGameMesh(Mesh *for_blendermesh)
{
- RAS_MeshObject** meshp = m_map_mesh_to_gamemesh[CHashedPtr(for_blendermesh)];
-
- if (meshp/* && onlayer==(*meshp)->GetLightLayer()*/) {
+ RAS_MeshObject **meshp = m_map_mesh_to_gamemesh[CHashedPtr(for_blendermesh)];
+
+ if (meshp) {
return *meshp;
- } else {
+ }
+ else {
return NULL;
}
-}
+}
void KX_BlenderSceneConverter::RegisterPolyMaterial(RAS_IPolyMaterial *polymat)
{
// First make sure we don't register the material twice
- vector<pair<KX_Scene*,RAS_IPolyMaterial*> >::iterator it;
+ vector<pair<KX_Scene *, RAS_IPolyMaterial *> >::iterator it;
for (it = m_polymaterials.begin(); it != m_polymaterials.end(); ++it)
if (it->second == polymat)
return;
- m_polymaterials.push_back(pair<KX_Scene*,RAS_IPolyMaterial*>(m_currentScene,polymat));
+ m_polymaterials.push_back(pair<KX_Scene *, RAS_IPolyMaterial *> (m_currentScene, polymat));
}
void KX_BlenderSceneConverter::CachePolyMaterial(KX_Scene *scene, Material *mat, RAS_IPolyMaterial *polymat)
@@ -516,128 +481,99 @@ void KX_BlenderSceneConverter::CachePolyMaterial(KX_Scene *scene, Material *mat,
m_polymat_cache[scene][mat] = polymat;
}
-RAS_IPolyMaterial *KX_BlenderSceneConverter::FindCachedPolyMaterial(KX_Scene *scene, struct Material *mat)
+RAS_IPolyMaterial *KX_BlenderSceneConverter::FindCachedPolyMaterial(KX_Scene *scene, Material *mat)
{
return (m_use_mat_cache) ? m_polymat_cache[scene][mat] : NULL;
}
-void KX_BlenderSceneConverter::CacheBlenderMaterial(KX_Scene *scene, struct Material *mat, BL_Material *blmat)
+void KX_BlenderSceneConverter::CacheBlenderMaterial(KX_Scene *scene, Material *mat, BL_Material *blmat)
{
if (m_use_mat_cache && mat)
m_mat_cache[scene][mat] = blmat;
}
-BL_Material *KX_BlenderSceneConverter::FindCachedBlenderMaterial(KX_Scene *scene, struct Material *mat)
+BL_Material *KX_BlenderSceneConverter::FindCachedBlenderMaterial(KX_Scene *scene, Material *mat)
{
return (m_use_mat_cache) ? m_mat_cache[scene][mat] : NULL;
}
-void KX_BlenderSceneConverter::RegisterInterpolatorList(
- BL_InterpolatorList *actList,
- struct bAction *for_act)
+void KX_BlenderSceneConverter::RegisterInterpolatorList(BL_InterpolatorList *actList, bAction *for_act)
{
m_map_blender_to_gameAdtList.insert(CHashedPtr(for_act), actList);
}
-
-
-BL_InterpolatorList *KX_BlenderSceneConverter::FindInterpolatorList(
- struct bAction *for_act)
+BL_InterpolatorList *KX_BlenderSceneConverter::FindInterpolatorList(bAction *for_act)
{
BL_InterpolatorList **listp = m_map_blender_to_gameAdtList[CHashedPtr(for_act)];
-
- return listp?*listp:NULL;
+ return listp ? *listp : NULL;
}
-
-
-void KX_BlenderSceneConverter::RegisterGameActuator(
- SCA_IActuator *act,
- struct bActuator *for_actuator)
+void KX_BlenderSceneConverter::RegisterGameActuator(SCA_IActuator *act, bActuator *for_actuator)
{
m_map_blender_to_gameactuator.insert(CHashedPtr(for_actuator), act);
}
-
-
-SCA_IActuator *KX_BlenderSceneConverter::FindGameActuator(
- struct bActuator *for_actuator)
+SCA_IActuator *KX_BlenderSceneConverter::FindGameActuator(bActuator *for_actuator)
{
SCA_IActuator **actp = m_map_blender_to_gameactuator[CHashedPtr(for_actuator)];
-
- return actp?*actp:NULL;
+ return actp ? *actp : NULL;
}
-
-
-void KX_BlenderSceneConverter::RegisterGameController(
- SCA_IController *cont,
- struct bController *for_controller)
+void KX_BlenderSceneConverter::RegisterGameController(SCA_IController *cont, bController *for_controller)
{
m_map_blender_to_gamecontroller.insert(CHashedPtr(for_controller), cont);
}
-
-
-SCA_IController *KX_BlenderSceneConverter::FindGameController(
- struct bController *for_controller)
+SCA_IController *KX_BlenderSceneConverter::FindGameController(bController *for_controller)
{
SCA_IController **contp = m_map_blender_to_gamecontroller[CHashedPtr(for_controller)];
-
- return contp?*contp:NULL;
+ return contp ? *contp : NULL;
}
-
-
-void KX_BlenderSceneConverter::RegisterWorldInfo(
- KX_WorldInfo *worldinfo)
+void KX_BlenderSceneConverter::RegisterWorldInfo(KX_WorldInfo *worldinfo)
{
- m_worldinfos.push_back(pair<KX_Scene*,KX_WorldInfo*>(m_currentScene,worldinfo));
+ m_worldinfos.push_back(pair<KX_Scene *, KX_WorldInfo *> (m_currentScene, worldinfo));
}
-void KX_BlenderSceneConverter::ResetPhysicsObjectsAnimationIpo(bool clearIpo)
+void KX_BlenderSceneConverter::ResetPhysicsObjectsAnimationIpo(bool clearIpo)
{
+ //TODO this entire function is deprecated, written for 2.4x
+ //the functionality should be rewritten, currently it does nothing
- KX_SceneList* scenes = m_ketsjiEngine->CurrentScenes();
+ KX_SceneList *scenes = m_ketsjiEngine->CurrentScenes();
int numScenes = scenes->size();
int i;
- for (i=0;i<numScenes;i++)
- {
- KX_Scene* scene = scenes->at(i);
- //PHY_IPhysicsEnvironment* physEnv = scene->GetPhysicsEnvironment();
- CListValue* parentList = scene->GetRootParentList();
+ for (i = 0; i < numScenes; i++) {
+ KX_Scene *scene = scenes->at(i);
+ CListValue *parentList = scene->GetRootParentList();
int numObjects = parentList->GetCount();
int g;
- for (g=0;g<numObjects;g++)
- {
- KX_GameObject* gameObj = (KX_GameObject*)parentList->GetValue(g);
+ for (g = 0; g < numObjects; g++) {
+ KX_GameObject *gameObj = (KX_GameObject *)parentList->GetValue(g);
if (gameObj->IsRecordAnimation()) {
-
- Object* blenderObject = gameObj->GetBlenderObject();
- if (blenderObject)
- {
+ Object *blenderObject = gameObj->GetBlenderObject();
+ if (blenderObject) {
#if 0
//erase existing ipo's
Ipo* ipo = blenderObject->ipo;//findIpoForName(blenderObject->id.name+2);
- if (ipo)
- { //clear the curve data
+ if (ipo) { //clear the curve data
if (clearIpo) {//rcruiz
IpoCurve *icu1;
-
+
int numCurves = 0;
for ( icu1 = (IpoCurve*)ipo->curve.first; icu1; ) {
-
+
IpoCurve* tmpicu = icu1;
-
+
/*int i;
BezTriple *bezt;
for ( bezt = tmpicu->bezt, i = 0; i < tmpicu->totvert; i++, bezt++) {
printf("(%f,%f,%f),(%f,%f,%f),(%f,%f,%f)\n",bezt->vec[0][0],bezt->vec[0][1],bezt->vec[0][2],bezt->vec[1][0],bezt->vec[1][1],bezt->vec[1][2],bezt->vec[2][0],bezt->vec[2][1],bezt->vec[2][2]);
}*/
-
+
icu1 = icu1->next;
numCurves++;
-
+
BLI_remlink( &( blenderObject->ipo->curve ), tmpicu );
if ( tmpicu->bezt )
MEM_freeN( tmpicu->bezt );
@@ -645,102 +581,52 @@ void KX_BlenderSceneConverter::ResetPhysicsObjectsAnimationIpo(bool clearIpo)
localDel_ipoCurve( tmpicu );
}
}
- } else
- { ipo = NULL; // XXX add_ipo(blenderObject->id.name+2, ID_OB);
+ }
+ else {
+ ipo = NULL; // XXX add_ipo(blenderObject->id.name+2, ID_OB);
blenderObject->ipo = ipo;
-
}
#endif
}
}
-
}
-
-
}
-
-
-
}
-void KX_BlenderSceneConverter::resetNoneDynamicObjectToIpo()
+void KX_BlenderSceneConverter::resetNoneDynamicObjectToIpo()
{
- if (addInitFromFrame) {
- KX_SceneList* scenes = m_ketsjiEngine->CurrentScenes();
- int numScenes = scenes->size();
- if (numScenes>=0) {
- KX_Scene* scene = scenes->at(0);
- CListValue* parentList = scene->GetRootParentList();
- for (int ix=0;ix<parentList->GetCount();ix++) {
- KX_GameObject* gameobj = (KX_GameObject*)parentList->GetValue(ix);
- if (!gameobj->IsRecordAnimation()) {
- Object* blenderobject = gameobj->GetBlenderObject();
- if (!blenderobject)
- continue;
- if (blenderobject->type==OB_ARMATURE)
- continue;
- float eu[3];
- mat4_to_eul(eu,blenderobject->obmat);
- MT_Point3 pos = MT_Point3(
- blenderobject->obmat[3][0],
- blenderobject->obmat[3][1],
- blenderobject->obmat[3][2]
- );
- MT_Vector3 eulxyz = MT_Vector3(
- eu[0],
- eu[1],
- eu[2]
- );
- MT_Vector3 scale = MT_Vector3(
- blenderobject->size[0],
- blenderobject->size[1],
- blenderobject->size[2]
- );
- gameobj->NodeSetLocalPosition(pos);
- gameobj->NodeSetLocalOrientation(MT_Matrix3x3(eulxyz));
- gameobj->NodeSetLocalScale(scale);
- gameobj->NodeUpdateGS(0);
- }
- }
- }
- }
+ //TODO the functionality should be rewritten
}
-
- ///this generates ipo curves for position, rotation, allowing to use game physics in animation
-void KX_BlenderSceneConverter::WritePhysicsObjectToAnimationIpo(int frameNumber)
+// this generates ipo curves for position, rotation, allowing to use game physics in animation
+void KX_BlenderSceneConverter::WritePhysicsObjectToAnimationIpo(int frameNumber)
{
-
- KX_SceneList* scenes = m_ketsjiEngine->CurrentScenes();
+ KX_SceneList *scenes = m_ketsjiEngine->CurrentScenes();
int numScenes = scenes->size();
int i;
- for (i=0;i<numScenes;i++)
- {
- KX_Scene* scene = scenes->at(i);
+ for (i = 0; i < numScenes; i++) {
+ KX_Scene *scene = scenes->at(i);
//PHY_IPhysicsEnvironment* physEnv = scene->GetPhysicsEnvironment();
- CListValue* parentList = scene->GetObjectList();
+ CListValue *parentList = scene->GetObjectList();
int numObjects = parentList->GetCount();
int g;
- for (g=0;g<numObjects;g++)
- {
- KX_GameObject* gameObj = (KX_GameObject*)parentList->GetValue(g);
- Object* blenderObject = gameObj->GetBlenderObject();
- if (blenderObject && blenderObject->parent==NULL && gameObj->IsRecordAnimation()) {
-
- if (blenderObject->adt==NULL)
- BKE_id_add_animdata(&blenderObject->id);
-
- if (blenderObject->adt)
- {
- const MT_Point3& position = gameObj->NodeGetWorldPosition();
+ for (g = 0; g < numObjects; g++) {
+ KX_GameObject *gameObj = (KX_GameObject *)parentList->GetValue(g);
+ Object *blenderObject = gameObj->GetBlenderObject();
+ if (blenderObject && blenderObject->parent == NULL && gameObj->IsRecordAnimation()) {
+ if (blenderObject->adt == NULL)
+ BKE_animdata_add_id(&blenderObject->id);
+
+ if (blenderObject->adt) {
+ const MT_Point3 &position = gameObj->NodeGetWorldPosition();
//const MT_Vector3& scale = gameObj->NodeGetWorldScaling();
- const MT_Matrix3x3& orn = gameObj->NodeGetWorldOrientation();
+ const MT_Matrix3x3 &orn = gameObj->NodeGetWorldOrientation();
position.getValue(blenderObject->loc);
float tmat[3][3];
- for (int r=0;r<3;r++)
- for (int c=0;c<3;c++)
+ for (int r = 0; r < 3; r++)
+ for (int c = 0; c < 3; c++)
tmat[r][c] = (float)orn[c][r];
mat3_to_compatible_eul(blenderObject->rot, blenderObject->rot, tmat);
@@ -825,31 +711,39 @@ void KX_BlenderSceneConverter::WritePhysicsObjectToAnimationIpo(int frameNumber)
}
}
-
-void KX_BlenderSceneConverter::TestHandlesPhysicsObjectToAnimationIpo()
+void KX_BlenderSceneConverter::TestHandlesPhysicsObjectToAnimationIpo()
{
-
- KX_SceneList* scenes = m_ketsjiEngine->CurrentScenes();
+ KX_SceneList *scenes = m_ketsjiEngine->CurrentScenes();
int numScenes = scenes->size();
int i;
- for (i=0;i<numScenes;i++)
- {
- KX_Scene* scene = scenes->at(i);
+ for (i = 0; i < numScenes; i++) {
+ KX_Scene *scene = scenes->at(i);
//PHY_IPhysicsEnvironment* physEnv = scene->GetPhysicsEnvironment();
- CListValue* parentList = scene->GetRootParentList();
+ CListValue *parentList = scene->GetRootParentList();
int numObjects = parentList->GetCount();
int g;
- for (g=0;g<numObjects;g++)
- {
- KX_GameObject* gameObj = (KX_GameObject*)parentList->GetValue(g);
+ for (g = 0; g < numObjects; g++) {
+ KX_GameObject *gameObj = (KX_GameObject *)parentList->GetValue(g);
if (gameObj->IsRecordAnimation()) {
+ Object *blenderObject = gameObj->GetBlenderObject();
+ if (blenderObject && blenderObject->adt) {
+ bAction *act = verify_adt_action(&blenderObject->id, false);
+ FCurve *fcu;
+
+ if (!act) {
+ continue;
+ }
+
+ /* for now, not much choice but to run this on all curves... */
+ for (fcu = (FCurve *)act->curves.first; fcu; fcu = fcu->next) {
+ /* Note: calling `sort_time_fcurve()` here is not needed, since
+ * all keys have been added in 'right' order. */
+ calchandles_fcurve(fcu);
+ }
#if 0
- Object* blenderObject = gameObj->GetBlenderObject();
- if (blenderObject && blenderObject->ipo)
- {
// XXX animato
Ipo* ipo = blenderObject->ipo;
-
+
//create the curves, if not existing
//testhandles_ipocurve checks for NULL
testhandles_ipocurve(findIpoCurve((IpoCurve *)ipo->curve.first,"LocX"));
@@ -858,8 +752,8 @@ void KX_BlenderSceneConverter::TestHandlesPhysicsObjectToAnimationIpo()
testhandles_ipocurve(findIpoCurve((IpoCurve *)ipo->curve.first,"RotX"));
testhandles_ipocurve(findIpoCurve((IpoCurve *)ipo->curve.first,"RotY"));
testhandles_ipocurve(findIpoCurve((IpoCurve *)ipo->curve.first,"RotZ"));
- }
#endif
+ }
}
}
}
@@ -872,14 +766,14 @@ PyObject *KX_BlenderSceneConverter::GetPyNamespace()
}
#endif
-vector<Main*> &KX_BlenderSceneConverter::GetMainDynamic()
+vector<Main *> &KX_BlenderSceneConverter::GetMainDynamic()
{
return m_DynamicMaggie;
}
-Main* KX_BlenderSceneConverter::GetMainDynamicPath(const char *path)
+Main *KX_BlenderSceneConverter::GetMainDynamicPath(const char *path)
{
- for (vector<Main*>::iterator it=m_DynamicMaggie.begin(); !(it==m_DynamicMaggie.end()); it++)
+ for (vector<Main *>::iterator it = m_DynamicMaggie.begin(); !(it == m_DynamicMaggie.end()); it++)
if (BLI_path_cmp((*it)->name, path) == 0)
return *it;
@@ -888,22 +782,21 @@ Main* KX_BlenderSceneConverter::GetMainDynamicPath(const char *path)
void KX_BlenderSceneConverter::MergeAsyncLoads()
{
- vector<KX_Scene*> *merge_scenes;
+ vector<KX_Scene *> *merge_scenes;
- vector<KX_LibLoadStatus*>::iterator mit;
- vector<KX_Scene*>::iterator sit;
+ vector<KX_LibLoadStatus *>::iterator mit;
+ vector<KX_Scene *>::iterator sit;
pthread_mutex_lock(&m_threadinfo->merge_lock);
- for (mit=m_mergequeue.begin(); mit!=m_mergequeue.end(); ++mit) {
- merge_scenes = (vector<KX_Scene*>*)(*mit)->GetData();
+ for (mit = m_mergequeue.begin(); mit != m_mergequeue.end(); ++mit) {
+ merge_scenes = (vector<KX_Scene *> *)(*mit)->GetData();
for (sit=merge_scenes->begin(); sit!=merge_scenes->end(); ++sit) {
(*mit)->GetMergeScene()->MergeScene(*sit);
delete (*sit);
}
-
delete merge_scenes;
(*mit)->SetData(NULL);
@@ -925,17 +818,17 @@ void KX_BlenderSceneConverter::AddScenesToMergeQueue(KX_LibLoadStatus *status)
static void *async_convert(void *ptr)
{
KX_Scene *new_scene = NULL;
- KX_LibLoadStatus *status = (KX_LibLoadStatus*)ptr;
- vector<Scene*> *scenes = (vector<Scene*>*)status->GetData();
- vector<KX_Scene*> *merge_scenes = new vector<KX_Scene*>(); // Deleted in MergeAsyncLoads
+ KX_LibLoadStatus *status = (KX_LibLoadStatus *)ptr;
+ vector<Scene *> *scenes = (vector<Scene *> *)status->GetData();
+ vector<KX_Scene *> *merge_scenes = new vector<KX_Scene *>(); // Deleted in MergeAsyncLoads
- for (unsigned int i=0; i<scenes->size(); ++i) {
+ for (unsigned int i = 0; i < scenes->size(); ++i) {
new_scene = status->GetEngine()->CreateScene((*scenes)[i], true);
if (new_scene)
merge_scenes->push_back(new_scene);
- status->AddProgress((1.f/scenes->size())*0.9f); // We'll call conversion 90% and merging 10% for now
+ status->AddProgress((1.0f / scenes->size()) * 0.9f); // We'll call conversion 90% and merging 10% for now
}
delete scenes;
@@ -962,28 +855,21 @@ KX_LibLoadStatus *KX_BlenderSceneConverter::LinkBlendFilePath(const char *filepa
return LinkBlendFile(bpy_openlib, filepath, group, scene_merge, err_str, options);
}
-static void load_datablocks(Main *main_newlib, BlendHandle *bpy_openlib, const char *path, int idcode)
+static void load_datablocks(Main *main_tmp, BlendHandle *bpy_openlib, const char *path, int idcode)
{
- Main *main_tmp= NULL; /* created only for linking, then freed */
LinkNode *names = NULL;
- short flag= 0; /* don't need any special options */
-
- /* here appending/linking starts */
- main_tmp = BLO_library_append_begin(main_newlib, &bpy_openlib, (char *)path);
int totnames_dummy;
- names = BLO_blendhandle_get_datablock_names( bpy_openlib, idcode, &totnames_dummy);
+ names = BLO_blendhandle_get_datablock_names(bpy_openlib, idcode, &totnames_dummy);
- int i=0;
- LinkNode *n= names;
+ int i = 0;
+ LinkNode *n = names;
while (n) {
BLO_library_append_named_part(main_tmp, &bpy_openlib, (char *)n->link, idcode);
- n= (LinkNode *)n->next;
+ n = (LinkNode *)n->next;
i++;
}
BLI_linklist_free(names, free); /* free linklist *and* each node's data */
-
- BLO_library_append_end(NULL, main_tmp, &bpy_openlib, idcode, flag);
}
KX_LibLoadStatus *KX_BlenderSceneConverter::LinkBlendFile(BlendHandle *bpy_openlib, const char *path, char *group, KX_Scene *scene_merge, char **err_str, short options)
@@ -996,42 +882,48 @@ KX_LibLoadStatus *KX_BlenderSceneConverter::LinkBlendFile(BlendHandle *bpy_openl
// TIMEIT_START(bge_link_blend_file);
KX_LibLoadStatus *status;
-
+
/* only scene and mesh supported right now */
- if (idcode!=ID_SCE && idcode!=ID_ME &&idcode!=ID_AC) {
+ if (idcode != ID_SCE && idcode != ID_ME && idcode != ID_AC) {
snprintf(err_local, sizeof(err_local), "invalid ID type given \"%s\"\n", group);
- *err_str= err_local;
+ *err_str = err_local;
BLO_blendhandle_close(bpy_openlib);
return NULL;
}
if (GetMainDynamicPath(path)) {
snprintf(err_local, sizeof(err_local), "blend file already open \"%s\"\n", path);
- *err_str= err_local;
+ *err_str = err_local;
BLO_blendhandle_close(bpy_openlib);
return NULL;
}
- if (bpy_openlib==NULL) {
+ if (bpy_openlib == NULL) {
snprintf(err_local, sizeof(err_local), "could not open blendfile \"%s\"\n", path);
- *err_str= err_local;
+ *err_str = err_local;
return NULL;
}
-
+
main_newlib = BKE_main_new();
BKE_reports_init(&reports, RPT_STORE);
- load_datablocks(main_newlib, bpy_openlib, path, idcode);
+ short flag = 0; /* don't need any special options */
+ /* created only for linking, then freed */
+ Main *main_tmp = BLO_library_append_begin(main_newlib, &bpy_openlib, (char *)path);
- if (idcode==ID_SCE && options & LIB_LOAD_LOAD_SCRIPTS) {
- load_datablocks(main_newlib, bpy_openlib, path, ID_TXT);
+ load_datablocks(main_tmp, bpy_openlib, path, idcode);
+
+ if (idcode == ID_SCE && options & LIB_LOAD_LOAD_SCRIPTS) {
+ load_datablocks(main_tmp, bpy_openlib, path, ID_TXT);
}
/* now do another round of linking for Scenes so all actions are properly loaded */
- if (idcode==ID_SCE && options & LIB_LOAD_LOAD_ACTIONS) {
- load_datablocks(main_newlib, bpy_openlib, path, ID_AC);
+ if (idcode == ID_SCE && options & LIB_LOAD_LOAD_ACTIONS) {
+ load_datablocks(main_tmp, bpy_openlib, path, ID_AC);
}
-
+
+ BLO_library_append_end(NULL, main_tmp, &bpy_openlib, idcode, flag);
+
BLO_blendhandle_close(bpy_openlib);
BKE_reports_clear(&reports);
@@ -1044,42 +936,43 @@ KX_LibLoadStatus *KX_BlenderSceneConverter::LinkBlendFile(BlendHandle *bpy_openl
status = new KX_LibLoadStatus(this, m_ketsjiEngine, scene_merge, path);
- if (idcode==ID_ME) {
+ if (idcode == ID_ME) {
/* Convert all new meshes into BGE meshes */
- ID* mesh;
+ ID *mesh;
- for (mesh= (ID *)main_newlib->mesh.first; mesh; mesh= (ID *)mesh->next ) {
+ for (mesh = (ID *)main_newlib->mesh.first; mesh; mesh = (ID *)mesh->next ) {
if (options & LIB_LOAD_VERBOSE)
- printf("MeshName: %s\n", mesh->name+2);
+ printf("MeshName: %s\n", mesh->name + 2);
RAS_MeshObject *meshobj = BL_ConvertMesh((Mesh *)mesh, NULL, scene_merge, this, false); // For now only use the libloading option for scenes, which need to handle materials/shaders
- scene_merge->GetLogicManager()->RegisterMeshName(meshobj->GetName(),meshobj);
+ scene_merge->GetLogicManager()->RegisterMeshName(meshobj->GetName(), meshobj);
}
}
- else if (idcode==ID_AC) {
+ else if (idcode == ID_AC) {
/* Convert all actions */
ID *action;
- for (action= (ID *)main_newlib->action.first; action; action= (ID *)action->next) {
+ for (action= (ID *)main_newlib->action.first; action; action = (ID *)action->next) {
if (options & LIB_LOAD_VERBOSE)
- printf("ActionName: %s\n", action->name+2);
- scene_merge->GetLogicManager()->RegisterActionName(action->name+2, action);
+ printf("ActionName: %s\n", action->name + 2);
+ scene_merge->GetLogicManager()->RegisterActionName(action->name + 2, action);
}
}
- else if (idcode==ID_SCE) {
+ else if (idcode == ID_SCE) {
/* Merge all new linked in scene into the existing one */
ID *scene;
// scenes gets deleted by the thread when it's done using it (look in async_convert())
- vector<Scene*> *scenes = (options & LIB_LOAD_ASYNC) ? new vector<Scene*>() : NULL;
+ vector<Scene *> *scenes = (options & LIB_LOAD_ASYNC) ? new vector<Scene *>() : NULL;
- for (scene= (ID *)main_newlib->scene.first; scene; scene= (ID *)scene->next ) {
+ for (scene = (ID *)main_newlib->scene.first; scene; scene = (ID *)scene->next ) {
if (options & LIB_LOAD_VERBOSE)
- printf("SceneName: %s\n", scene->name+2);
+ printf("SceneName: %s\n", scene->name + 2);
if (options & LIB_LOAD_ASYNC) {
- scenes->push_back((Scene*)scene);
- } else {
+ scenes->push_back((Scene *)scene);
+ }
+ else {
/* merge into the base scene */
- KX_Scene* other= m_ketsjiEngine->CreateScene((Scene *)scene, true);
+ KX_Scene* other = m_ketsjiEngine->CreateScene((Scene *)scene, true);
scene_merge->MergeScene(other);
// RemoveScene(other); // Don't run this, it frees the entire scene converter data, just delete the scene
@@ -1090,7 +983,7 @@ KX_LibLoadStatus *KX_BlenderSceneConverter::LinkBlendFile(BlendHandle *bpy_openl
if (options & LIB_LOAD_ASYNC) {
pthread_t id;
status->SetData(scenes);
- pthread_create(&id, NULL, &async_convert, (void*)status);
+ pthread_create(&id, NULL, &async_convert, (void *)status);
m_threadinfo->threads.push_back(id);
}
@@ -1104,17 +997,16 @@ KX_LibLoadStatus *KX_BlenderSceneConverter::LinkBlendFile(BlendHandle *bpy_openl
if (options & LIB_LOAD_LOAD_ACTIONS) {
ID *action;
- for (action= (ID *)main_newlib->action.first; action; action= (ID *)action->next) {
+ for (action = (ID *)main_newlib->action.first; action; action = (ID *)action->next) {
if (options & LIB_LOAD_VERBOSE)
- printf("ActionName: %s\n", action->name+2);
- scene_merge->GetLogicManager()->RegisterActionName(action->name+2, action);
+ printf("ActionName: %s\n", action->name + 2);
+ scene_merge->GetLogicManager()->RegisterActionName(action->name + 2, action);
}
}
}
if (!(options & LIB_LOAD_ASYNC))
status->Finish();
-
// TIMEIT_END(bge_link_blend_file);
@@ -1124,22 +1016,22 @@ KX_LibLoadStatus *KX_BlenderSceneConverter::LinkBlendFile(BlendHandle *bpy_openl
/* Note m_map_*** are all ok and don't need to be freed
* most are temp and NewRemoveObject frees m_map_gameobject_to_blender */
-bool KX_BlenderSceneConverter::FreeBlendFile(struct Main *maggie)
+bool KX_BlenderSceneConverter::FreeBlendFile(Main *maggie)
{
- int maggie_index= -1;
- int i=0;
+ int maggie_index = -1;
+ int i = 0;
- if (maggie==NULL)
+ if (maggie == NULL)
return false;
/* tag all false except the one we remove */
- for (vector<Main*>::iterator it=m_DynamicMaggie.begin(); !(it==m_DynamicMaggie.end()); it++) {
- Main *main= *it;
+ for (vector<Main *>::iterator it = m_DynamicMaggie.begin(); !(it == m_DynamicMaggie.end()); it++) {
+ Main *main = *it;
if (main != maggie) {
BKE_main_id_tag_all(main, false);
}
else {
- maggie_index= i;
+ maggie_index = i;
}
i++;
}
@@ -1151,15 +1043,12 @@ bool KX_BlenderSceneConverter::FreeBlendFile(struct Main *maggie)
m_DynamicMaggie.erase(m_DynamicMaggie.begin() + maggie_index);
BKE_main_id_tag_all(maggie, true);
-
/* free all tagged objects */
- KX_SceneList* scenes = m_ketsjiEngine->CurrentScenes();
+ KX_SceneList *scenes = m_ketsjiEngine->CurrentScenes();
int numScenes = scenes->size();
-
- for (int scene_idx=0;scene_idx<numScenes;scene_idx++)
- {
- KX_Scene* scene = scenes->at(scene_idx);
+ for (int scene_idx = 0; scene_idx < numScenes; scene_idx++) {
+ KX_Scene *scene = scenes->at(scene_idx);
if (IS_TAGGED(scene->GetBlenderScene())) {
m_ketsjiEngine->RemoveScene(scene->GetName());
m_mat_cache.erase(scene);
@@ -1168,16 +1057,13 @@ bool KX_BlenderSceneConverter::FreeBlendFile(struct Main *maggie)
numScenes--;
}
else {
-
/* in case the mesh might be refered to later */
{
- CTR_Map<STR_HashedString,void*> &mapStringToMeshes = scene->GetLogicManager()->GetMeshMap();
+ CTR_Map<STR_HashedString, void *> &mapStringToMeshes = scene->GetLogicManager()->GetMeshMap();
- for (int i=0; i<mapStringToMeshes.size(); i++)
- {
- RAS_MeshObject *meshobj= (RAS_MeshObject *) *mapStringToMeshes.at(i);
- if (meshobj && IS_TAGGED(meshobj->GetMesh()))
- {
+ for (int i = 0; i < mapStringToMeshes.size(); i++) {
+ RAS_MeshObject *meshobj = (RAS_MeshObject *) *mapStringToMeshes.at(i);
+ if (meshobj && IS_TAGGED(meshobj->GetMesh())) {
STR_HashedString mn = meshobj->GetName();
mapStringToMeshes.remove(mn);
m_map_mesh_to_gamemesh.remove(CHashedPtr(meshobj->GetMesh()));
@@ -1188,16 +1074,15 @@ bool KX_BlenderSceneConverter::FreeBlendFile(struct Main *maggie)
/* Now unregister actions */
{
- CTR_Map<STR_HashedString,void*> &mapStringToActions = scene->GetLogicManager()->GetActionMap();
+ CTR_Map<STR_HashedString, void *> &mapStringToActions = scene->GetLogicManager()->GetActionMap();
- for (int i=0; i<mapStringToActions.size(); i++)
- {
- ID *action= (ID*) *mapStringToActions.at(i);
+ for (int i = 0; i < mapStringToActions.size(); i++) {
+ ID *action = (ID*) *mapStringToActions.at(i);
- if (IS_TAGGED(action))
- {
- STR_HashedString an = action->name+2;
+ if (IS_TAGGED(action)) {
+ STR_HashedString an = action->name + 2;
mapStringToActions.remove(an);
+ m_map_blender_to_gameAdtList.remove(CHashedPtr(action));
i--;
}
}
@@ -1206,16 +1091,13 @@ bool KX_BlenderSceneConverter::FreeBlendFile(struct Main *maggie)
//scene->FreeTagged(); /* removed tagged objects and meshes*/
CListValue *obj_lists[] = {scene->GetObjectList(), scene->GetInactiveList(), NULL};
- for (int ob_ls_idx=0; obj_lists[ob_ls_idx]; ob_ls_idx++)
- {
- CListValue *obs= obj_lists[ob_ls_idx];
- RAS_MeshObject* mesh;
+ for (int ob_ls_idx = 0; obj_lists[ob_ls_idx]; ob_ls_idx++) {
+ CListValue *obs = obj_lists[ob_ls_idx];
+ RAS_MeshObject *mesh;
- for (int ob_idx = 0; ob_idx < obs->GetCount(); ob_idx++)
- {
- KX_GameObject* gameobj = (KX_GameObject*)obs->GetValue(ob_idx);
+ for (int ob_idx = 0; ob_idx < obs->GetCount(); ob_idx++) {
+ KX_GameObject *gameobj = (KX_GameObject*)obs->GetValue(ob_idx);
if (IS_TAGGED(gameobj->GetBlenderObject())) {
-
int size_before = obs->GetCount();
/* Eventually calls RemoveNodeDestructObject
@@ -1229,10 +1111,11 @@ bool KX_BlenderSceneConverter::FreeBlendFile(struct Main *maggie)
}
}
else {
+ gameobj->RemoveTaggedActions();
/* free the mesh, we could be referecing a linked one! */
- int mesh_index= gameobj->GetMeshCount();
+ int mesh_index = gameobj->GetMeshCount();
while (mesh_index--) {
- mesh= gameobj->GetMesh(mesh_index);
+ mesh = gameobj->GetMesh(mesh_index);
if (IS_TAGGED(mesh->GetMesh())) {
gameobj->RemoveMeshes(); /* XXX - slack, should only remove meshes that are library items but mostly objects only have 1 mesh */
break;
@@ -1250,11 +1133,9 @@ bool KX_BlenderSceneConverter::FreeBlendFile(struct Main *maggie)
}
/* make sure action actuators are not referencing tagged actions */
- for (unsigned int act_idx=0; act_idx<gameobj->GetActuators().size(); act_idx++)
- {
- if (gameobj->GetActuators()[act_idx]->IsType(SCA_IActuator::KX_ACT_ACTION))
- {
- BL_ActionActuator *act = (BL_ActionActuator*)gameobj->GetActuators()[act_idx];
+ for (unsigned int act_idx = 0; act_idx < gameobj->GetActuators().size(); act_idx++) {
+ if (gameobj->GetActuators()[act_idx]->IsType(SCA_IActuator::KX_ACT_ACTION)) {
+ BL_ActionActuator *act = (BL_ActionActuator *)gameobj->GetActuators()[act_idx];
if (IS_TAGGED(act->GetAction()))
act->SetAction(NULL);
}
@@ -1265,7 +1146,6 @@ bool KX_BlenderSceneConverter::FreeBlendFile(struct Main *maggie)
}
}
-
int size;
// delete the entities of this scene
@@ -1288,24 +1168,24 @@ bool KX_BlenderSceneConverter::FreeBlendFile(struct Main *maggie)
/* Worlds don't reference original blender data so we need to make a set from them */
- typedef std::set<KX_WorldInfo*> KX_WorldInfoSet;
+ typedef std::set<KX_WorldInfo *> KX_WorldInfoSet;
KX_WorldInfoSet worldset;
- for (int scene_idx=0;scene_idx<numScenes;scene_idx++)
- {
- KX_Scene* scene = scenes->at(scene_idx);
+ for (int scene_idx = 0; scene_idx < numScenes; scene_idx++) {
+ KX_Scene *scene = scenes->at(scene_idx);
if (scene->GetWorldInfo())
- worldset.insert( scene->GetWorldInfo() );
+ worldset.insert(scene->GetWorldInfo());
}
- vector<pair<KX_Scene*,KX_WorldInfo*> >::iterator worldit;
+ vector<pair<KX_Scene *, KX_WorldInfo *> >::iterator worldit;
size = m_worldinfos.size();
- for (i=0, worldit=m_worldinfos.begin(); i<size; ) {
- if ((*worldit).second && (worldset.count((*worldit).second)) == 0) {
- delete (*worldit).second;
+ for (i = 0, worldit = m_worldinfos.begin(); i < size;) {
+ if (worldit->second && (worldset.count(worldit->second)) == 0) {
+ delete worldit->second;
*worldit = m_worldinfos.back();
m_worldinfos.pop_back();
size--;
- } else {
+ }
+ else {
i++;
worldit++;
}
@@ -1313,87 +1193,76 @@ bool KX_BlenderSceneConverter::FreeBlendFile(struct Main *maggie)
worldset.clear();
/* done freeing the worlds */
-
-
-
- vector<pair<KX_Scene*,RAS_IPolyMaterial*> >::iterator polymit;
+ vector<pair<KX_Scene *, RAS_IPolyMaterial *> >::iterator polymit;
size = m_polymaterials.size();
+ for (i = 0, polymit = m_polymaterials.begin(); i < size; ) {
+ RAS_IPolyMaterial *mat = polymit->second;
+ Material *bmat = NULL;
-
- for (i=0, polymit=m_polymaterials.begin(); i<size; ) {
- RAS_IPolyMaterial *mat= (*polymit).second;
- Material *bmat= NULL;
-
- KX_BlenderMaterial *bl_mat = static_cast<KX_BlenderMaterial*>(mat);
- bmat= bl_mat->GetBlenderMaterial();
+ KX_BlenderMaterial *bl_mat = static_cast<KX_BlenderMaterial *>(mat);
+ bmat = bl_mat->GetBlenderMaterial();
if (IS_TAGGED(bmat)) {
/* only remove from bucket */
- ((*polymit).first)->GetBucketManager()->RemoveMaterial(mat);
+ polymit->first->GetBucketManager()->RemoveMaterial(mat);
}
i++;
polymit++;
}
-
-
- for (i=0, polymit=m_polymaterials.begin(); i<size; ) {
- RAS_IPolyMaterial *mat= (*polymit).second;
- Material *bmat= NULL;
+ for (i = 0, polymit = m_polymaterials.begin(); i < size; ) {
+ RAS_IPolyMaterial *mat = polymit->second;
+ Material *bmat = NULL;
KX_BlenderMaterial *bl_mat = static_cast<KX_BlenderMaterial*>(mat);
- bmat= bl_mat->GetBlenderMaterial();
-
- if (bmat) {
- //printf("FOUND MAT '%s' !!! ", ((ID*)bmat)->name+2);
- }
- else {
- //printf("LOST MAT !!!");
- }
+ bmat = bl_mat->GetBlenderMaterial();
if (IS_TAGGED(bmat)) {
- delete (*polymit).second;
+ // Remove the poly material coresponding to this Blender Material.
+ m_polymat_cache[polymit->first].erase(bmat);
+ delete polymit->second;
*polymit = m_polymaterials.back();
m_polymaterials.pop_back();
size--;
- //printf("tagged !\n");
} else {
i++;
polymit++;
- //printf("(un)tagged !\n");
}
}
- vector<pair<KX_Scene*,BL_Material*> >::iterator matit;
+ vector<pair<KX_Scene *, BL_Material *> >::iterator matit;
size = m_materials.size();
- for (i=0, matit=m_materials.begin(); i<size; ) {
- BL_Material *mat= (*matit).second;
+ for (i = 0, matit = m_materials.begin(); i < size; ) {
+ BL_Material *mat = matit->second;
if (IS_TAGGED(mat->material)) {
- delete (*matit).second;
+ // Remove the bl material coresponding to this Blender Material.
+ m_mat_cache[matit->first].erase(mat->material);
+ delete matit->second;
*matit = m_materials.back();
m_materials.pop_back();
size--;
- } else {
+ }
+ else {
i++;
matit++;
}
}
- vector<pair<KX_Scene*,RAS_MeshObject*> >::iterator meshit;
+ vector<pair<KX_Scene *, RAS_MeshObject *> >::iterator meshit;
RAS_BucketManager::BucketList::iterator bit;
list<RAS_MeshSlot>::iterator msit;
RAS_BucketManager::BucketList buckets;
size = m_meshobjects.size();
- for (i=0, meshit=m_meshobjects.begin(); i<size; ) {
- RAS_MeshObject *me= (*meshit).second;
+ for (i = 0, meshit = m_meshobjects.begin(); i < size;) {
+ RAS_MeshObject *me = meshit->second;
if (IS_TAGGED(me->GetMesh())) {
// Before deleting the mesh object, make sure the rasterizer is
// no longer referencing it.
buckets = meshit->first->GetBucketManager()->GetSolidBuckets();
- for (bit=buckets.begin(); bit!=buckets.end(); bit++) {
+ for (bit = buckets.begin(); bit != buckets.end(); bit++) {
msit = (*bit)->msBegin();
while (msit != (*bit)->msEnd()) {
@@ -1406,7 +1275,7 @@ bool KX_BlenderSceneConverter::FreeBlendFile(struct Main *maggie)
// And now the alpha buckets
buckets = meshit->first->GetBucketManager()->GetAlphaBuckets();
- for (bit=buckets.begin(); bit!=buckets.end(); bit++) {
+ for (bit = buckets.begin(); bit != buckets.end(); bit++) {
msit = (*bit)->msBegin();
while (msit != (*bit)->msEnd()) {
@@ -1418,11 +1287,12 @@ bool KX_BlenderSceneConverter::FreeBlendFile(struct Main *maggie)
}
// Now it should be safe to delete
- delete (*meshit).second;
+ delete meshit->second;
*meshit = m_meshobjects.back();
m_meshobjects.pop_back();
size--;
- } else {
+ }
+ else {
i++;
meshit++;
}
@@ -1449,24 +1319,23 @@ bool KX_BlenderSceneConverter::FreeBlendFile(const char *path)
bool KX_BlenderSceneConverter::MergeScene(KX_Scene *to, KX_Scene *from)
{
-
{
- vector<pair<KX_Scene*,KX_WorldInfo*> >::iterator itp = m_worldinfos.begin();
+ vector<pair<KX_Scene *, KX_WorldInfo *> >::iterator itp = m_worldinfos.begin();
while (itp != m_worldinfos.end()) {
- if ((*itp).first==from)
- (*itp).first= to;
+ if (itp->first == from)
+ itp->first = to;
itp++;
}
}
{
- vector<pair<KX_Scene*,RAS_IPolyMaterial*> >::iterator itp = m_polymaterials.begin();
+ vector<pair<KX_Scene *, RAS_IPolyMaterial *> >::iterator itp = m_polymaterials.begin();
while (itp != m_polymaterials.end()) {
- if ((*itp).first==from) {
- (*itp).first= to;
+ if (itp->first == from) {
+ itp->first = to;
/* also switch internal data */
- RAS_IPolyMaterial*mat= (*itp).second;
+ RAS_IPolyMaterial *mat = itp->second;
mat->Replace_IScene(to);
}
itp++;
@@ -1474,29 +1343,43 @@ bool KX_BlenderSceneConverter::MergeScene(KX_Scene *to, KX_Scene *from)
}
{
- vector<pair<KX_Scene*,RAS_MeshObject*> >::iterator itp = m_meshobjects.begin();
+ vector<pair<KX_Scene *, RAS_MeshObject *> >::iterator itp = m_meshobjects.begin();
while (itp != m_meshobjects.end()) {
- if ((*itp).first==from)
- (*itp).first= to;
+ if (itp->first == from)
+ itp->first = to;
itp++;
}
}
{
- vector<pair<KX_Scene*,BL_Material*> >::iterator itp = m_materials.begin();
+ vector<pair<KX_Scene *, BL_Material *> >::iterator itp = m_materials.begin();
while (itp != m_materials.end()) {
- if ((*itp).first==from)
- (*itp).first= to;
+ if (itp->first == from)
+ itp->first = to;
itp++;
}
}
-
+
+ MaterialCache::iterator matcacheit = m_mat_cache.find(from);
+ if (matcacheit != m_mat_cache.end()) {
+ // Merge cached BL_Material map.
+ m_mat_cache[to].insert(matcacheit->second.begin(), matcacheit->second.end());
+ m_mat_cache.erase(matcacheit);
+ }
+
+ PolyMaterialCache::iterator polymatcacheit = m_polymat_cache.find(from);
+ if (polymatcacheit != m_polymat_cache.end()) {
+ // Merge cached RAS_IPolyMaterial map.
+ m_polymat_cache[to].insert(polymatcacheit->second.begin(), polymatcacheit->second.end());
+ m_polymat_cache.erase(polymatcacheit);
+ }
+
return true;
}
/* This function merges a mesh from the current scene into another main
* it does not convert */
-RAS_MeshObject *KX_BlenderSceneConverter::ConvertMeshSpecial(KX_Scene* kx_scene, Main *maggie, const char *name)
+RAS_MeshObject *KX_BlenderSceneConverter::ConvertMeshSpecial(KX_Scene *kx_scene, Main *maggie, const char *name)
{
/* Find a mesh in the current main */
ID *me= static_cast<ID *>(BLI_findstring(&m_maggie->mesh, name, offsetof(ID, name) + 2));
@@ -1504,7 +1387,7 @@ RAS_MeshObject *KX_BlenderSceneConverter::ConvertMeshSpecial(KX_Scene* kx_scene,
if (me == NULL) {
// The mesh wasn't in the current main, try any dynamic (i.e., LibLoaded) ones
- vector<Main*>::iterator it;
+ vector<Main *>::iterator it;
for (it = GetMainDynamic().begin(); it != GetMainDynamic().end(); it++) {
me = static_cast<ID *>(BLI_findstring(&(*it)->mesh, name, offsetof(ID, name) + 2));
@@ -1514,12 +1397,12 @@ RAS_MeshObject *KX_BlenderSceneConverter::ConvertMeshSpecial(KX_Scene* kx_scene,
break;
}
}
-
- if (me==NULL) {
+
+ if (me == NULL) {
printf("Could not be found \"%s\"\n", name);
return NULL;
}
-
+
/* Watch this!, if its used in the original scene can cause big troubles */
if (me->us > 0) {
#ifdef DEBUG
@@ -1531,34 +1414,32 @@ RAS_MeshObject *KX_BlenderSceneConverter::ConvertMeshSpecial(KX_Scene* kx_scene,
BLI_remlink(&from_maggie->mesh, me); /* even if we made the copy it needs to be removed */
BLI_addtail(&maggie->mesh, me);
-
/* Must copy the materials this uses else we cant free them */
{
- Mesh *mesh= (Mesh *)me;
-
+ Mesh *mesh = (Mesh *)me;
+
/* ensure all materials are tagged */
- for (int i=0; i<mesh->totcol; i++)
+ for (int i = 0; i < mesh->totcol; i++) {
if (mesh->mat[i])
mesh->mat[i]->id.flag &= ~LIB_DOIT;
-
- for (int i=0; i<mesh->totcol; i++)
- {
- Material *mat_old= mesh->mat[i];
-
+ }
+
+ for (int i = 0; i < mesh->totcol; i++) {
+ Material *mat_old = mesh->mat[i];
+
/* if its tagged its a replaced material */
- if (mat_old && (mat_old->id.flag & LIB_DOIT)==0)
- {
- Material *mat_old= mesh->mat[i];
- Material *mat_new= BKE_material_copy( mat_old );
-
+ if (mat_old && (mat_old->id.flag & LIB_DOIT) == 0) {
+ Material *mat_old = mesh->mat[i];
+ Material *mat_new = BKE_material_copy(mat_old);
+
mat_new->id.flag |= LIB_DOIT;
mat_old->id.us--;
-
+
BLI_remlink(&G.main->mat, mat_new); // BKE_material_copy uses G.main, and there is no BKE_material_copy_ex
BLI_addtail(&maggie->mat, mat_new);
-
+
mesh->mat[i] = mat_new;
-
+
/* the same material may be used twice */
for (int j = i + 1; j < mesh->totcol; j++) {
if (mesh->mat[j] == mat_old) {
diff --git a/source/gameengine/Converter/KX_BlenderSceneConverter.h b/source/gameengine/Converter/KX_BlenderSceneConverter.h
index 3ae90301553..a40188d197d 100644
--- a/source/gameengine/Converter/KX_BlenderSceneConverter.h
+++ b/source/gameengine/Converter/KX_BlenderSceneConverter.h
@@ -32,7 +32,7 @@
#ifndef __KX_BLENDERSCENECONVERTER_H__
#define __KX_BLENDERSCENECONVERTER_H__
-#include "KX_HashedPtr.h"
+#include "EXP_HashedPtr.h"
#include "CTR_Map.h"
#include <stdio.h>
diff --git a/source/gameengine/Converter/KX_ConvertActuators.cpp b/source/gameengine/Converter/KX_ConvertActuators.cpp
index f6ed3366625..3b36e094a75 100644
--- a/source/gameengine/Converter/KX_ConvertActuators.cpp
+++ b/source/gameengine/Converter/KX_ConvertActuators.cpp
@@ -42,8 +42,7 @@
#include "KX_ConvertActuators.h"
#ifdef WITH_AUDASPACE
-# include "AUD_C-API.h"
-# include "AUD_ChannelMapperFactory.h"
+# include AUD_SOUND_H
#endif
// Actuators
@@ -75,7 +74,7 @@
#include "KX_Scene.h"
#include "KX_KetsjiEngine.h"
-#include "IntValue.h"
+#include "EXP_IntValue.h"
#include "KX_GameObject.h"
/* This little block needed for linking to Blender... */
@@ -385,7 +384,7 @@ void BL_ConvertActuators(const char* maggiename,
{
bSound* sound = soundact->sound;
bool is3d = soundact->flag & ACT_SND_3D_SOUND ? true : false;
- boost::shared_ptr<AUD_IFactory> snd_sound;
+ AUD_Sound* snd_sound = NULL;
KX_3DSoundSettings settings;
settings.cone_inner_angle = RAD2DEGF(soundact->sound3D.cone_inner_angle);
settings.cone_outer_angle = RAD2DEGF(soundact->sound3D.cone_outer_angle);
@@ -404,27 +403,12 @@ void BL_ConvertActuators(const char* maggiename,
}
else
{
- snd_sound = *reinterpret_cast<boost::shared_ptr<AUD_IFactory>*>(sound->playback_handle);
+ snd_sound = sound->playback_handle;
// if sound shall be 3D but isn't mono, we have to make it mono!
if (is3d)
{
- try
- {
- boost::shared_ptr<AUD_IReader> reader = snd_sound->createReader();
- if (reader->getSpecs().channels != AUD_CHANNELS_MONO)
- {
- AUD_DeviceSpecs specs;
- specs.channels = AUD_CHANNELS_MONO;
- specs.rate = AUD_RATE_INVALID;
- specs.format = AUD_FORMAT_INVALID;
- snd_sound = boost::shared_ptr<AUD_IFactory>(new AUD_ChannelMapperFactory(snd_sound, specs));
- }
- }
- catch(AUD_Exception&)
- {
- // sound cannot be played... ignore
- }
+ snd_sound = AUD_Sound_rechannel(snd_sound, AUD_CHANNELS_MONO);
}
}
KX_SoundActuator* tmpsoundact =
@@ -436,6 +420,10 @@ void BL_ConvertActuators(const char* maggiename,
settings,
soundActuatorType);
+ // if we made it mono, we have to free it
+ if(snd_sound != sound->playback_handle && snd_sound != NULL)
+ AUD_Sound_free(snd_sound);
+
tmpsoundact->SetName(bact->name);
baseact = tmpsoundact;
}
@@ -1087,11 +1075,12 @@ void BL_ConvertActuators(const char* maggiename,
bool enableVisualization = (stAct->flag & ACT_STEERING_ENABLEVISUALIZATION) !=0;
short facingMode = (stAct->flag & ACT_STEERING_AUTOMATICFACING) ? stAct->facingaxis : 0;
bool normalup = (stAct->flag & ACT_STEERING_NORMALUP) !=0;
+ bool lockzvel = (stAct->flag & ACT_STEERING_LOCKZVEL) !=0;
KX_SteeringActuator *tmpstact
= new KX_SteeringActuator(gameobj, mode, targetob, navmeshob,stAct->dist,
stAct->velocity, stAct->acceleration, stAct->turnspeed,
selfTerminated, stAct->updateTime,
- scene->GetObstacleSimulation(), facingMode, normalup, enableVisualization);
+ scene->GetObstacleSimulation(), facingMode, normalup, enableVisualization, lockzvel);
baseact = tmpstact;
break;
}
diff --git a/source/gameengine/Converter/KX_ConvertControllers.cpp b/source/gameengine/Converter/KX_ConvertControllers.cpp
index 0215b604fdd..e3697087ea9 100644
--- a/source/gameengine/Converter/KX_ConvertControllers.cpp
+++ b/source/gameengine/Converter/KX_ConvertControllers.cpp
@@ -34,7 +34,7 @@
#include "KX_BlenderSceneConverter.h"
#include "KX_ConvertControllers.h"
-#include "KX_Python.h"
+#include "EXP_Python.h"
// Controller
#include "SCA_ANDController.h"
@@ -48,7 +48,7 @@
#include "SCA_LogicManager.h"
#include "KX_GameObject.h"
-#include "IntValue.h"
+#include "EXP_IntValue.h"
/* This little block needed for linking to Blender... */
#ifdef WIN32
diff --git a/source/gameengine/Converter/KX_ConvertControllers.h b/source/gameengine/Converter/KX_ConvertControllers.h
index babe3e2e73f..2f93d70a6f9 100644
--- a/source/gameengine/Converter/KX_ConvertControllers.h
+++ b/source/gameengine/Converter/KX_ConvertControllers.h
@@ -32,7 +32,7 @@
#ifndef __KX_CONVERTCONTROLLERS_H__
#define __KX_CONVERTCONTROLLERS_H__
-#include "KX_Python.h"
+#include "EXP_Python.h"
void BL_ConvertControllers(
struct Object* blenderobject,
@@ -41,7 +41,7 @@ void BL_ConvertControllers(
int activeLayerBitInfo,
bool isInActiveLayer,
class KX_BlenderSceneConverter* converter,
- bool libloading
+ bool libloading
);
#endif /* __KX_CONVERTCONTROLLERS_H__ */
diff --git a/source/gameengine/Converter/KX_ConvertProperties.cpp b/source/gameengine/Converter/KX_ConvertProperties.cpp
index 3b4ba6886cb..2cb61207fb5 100644
--- a/source/gameengine/Converter/KX_ConvertProperties.cpp
+++ b/source/gameengine/Converter/KX_ConvertProperties.cpp
@@ -38,13 +38,13 @@
/* end of blender include block */
-#include "Value.h"
-#include "VectorValue.h"
-#include "BoolValue.h"
-#include "StringValue.h"
-#include "FloatValue.h"
+#include "EXP_Value.h"
+#include "EXP_VectorValue.h"
+#include "EXP_BoolValue.h"
+#include "EXP_StringValue.h"
+#include "EXP_FloatValue.h"
#include "KX_GameObject.h"
-#include "IntValue.h"
+#include "EXP_IntValue.h"
#include "SCA_TimeEventManager.h"
#include "SCA_IScene.h"
diff --git a/source/gameengine/Converter/KX_ConvertSensors.cpp b/source/gameengine/Converter/KX_ConvertSensors.cpp
index 0d706fcd924..79fd9cb9254 100644
--- a/source/gameengine/Converter/KX_ConvertSensors.cpp
+++ b/source/gameengine/Converter/KX_ConvertSensors.cpp
@@ -79,7 +79,7 @@
#include "SCA_LogicManager.h"
#include "KX_BlenderInputDevice.h"
#include "KX_Scene.h"
-#include "IntValue.h"
+#include "EXP_IntValue.h"
#include "KX_BlenderKeyboardDevice.h"
#include "RAS_ICanvas.h"
#include "PHY_IPhysicsEnvironment.h"
@@ -105,7 +105,7 @@ void BL_ConvertSensors(struct Object* blenderobject,
bSensor* sens = (bSensor*)blenderobject->sensors.first;
bool pos_pulsemode = false;
bool neg_pulsemode = false;
- int frequency = 0;
+ int skipped_ticks = 0;
bool invert = false;
bool level = false;
bool tap = false;
@@ -119,542 +119,542 @@ void BL_ConvertSensors(struct Object* blenderobject,
sens = (bSensor*)blenderobject->sensors.first;
while (sens) {
- SCA_ISensor* gamesensor=NULL;
- /* All sensors have a pulse toggle, frequency, and invert field. */
- /* These are extracted here, and set when the sensor is added to the */
- /* list. */
- pos_pulsemode = (sens->pulse & SENS_PULSE_REPEAT)!=0;
- neg_pulsemode = (sens->pulse & SENS_NEG_PULSE_MODE)!=0;
-
- frequency = sens->freq;
- invert = !(sens->invert == 0);
- level = !(sens->level == 0);
- tap = !(sens->tap == 0);
-
- switch (sens->type)
- {
- case SENS_ALWAYS:
- {
-
- SCA_EventManager* eventmgr = logicmgr->FindEventManager(SCA_EventManager::BASIC_EVENTMGR);
- if (eventmgr)
- {
- gamesensor = new SCA_AlwaysSensor(eventmgr, gameobj);
- }
-
- break;
- }
-
- case SENS_DELAY:
+ if (!(sens->flag & SENS_DEACTIVATE)) {
+ SCA_ISensor* gamesensor=NULL;
+ /* All sensors have a pulse toggle, skipped ticks parameter, and invert field. */
+ /* These are extracted here, and set when the sensor is added to the */
+ /* list. */
+ pos_pulsemode = (sens->pulse & SENS_PULSE_REPEAT)!=0;
+ neg_pulsemode = (sens->pulse & SENS_NEG_PULSE_MODE)!=0;
+
+ skipped_ticks = sens->freq;
+ invert = !(sens->invert == 0);
+ level = !(sens->level == 0);
+ tap = !(sens->tap == 0);
+
+ switch (sens->type)
{
- // we can reuse the Always event manager for the delay sensor
- SCA_EventManager* eventmgr = logicmgr->FindEventManager(SCA_EventManager::BASIC_EVENTMGR);
- if (eventmgr)
+ case SENS_ALWAYS:
{
- bDelaySensor* delaysensor = (bDelaySensor*)sens->data;
- gamesensor = new SCA_DelaySensor(eventmgr,
- gameobj,
- delaysensor->delay,
- delaysensor->duration,
- (delaysensor->flag & SENS_DELAY_REPEAT) != 0);
+
+ SCA_EventManager* eventmgr = logicmgr->FindEventManager(SCA_EventManager::BASIC_EVENTMGR);
+ if (eventmgr)
+ {
+ gamesensor = new SCA_AlwaysSensor(eventmgr, gameobj);
+ }
+
+ break;
}
- break;
- }
- case SENS_COLLISION:
- {
- SCA_EventManager* eventmgr = logicmgr->FindEventManager(SCA_EventManager::TOUCH_EVENTMGR);
- if (eventmgr)
+ case SENS_DELAY:
{
- // collision sensor can sense both materials and properties.
-
- bool bFindMaterial = false, bTouchPulse = false;
-
- bCollisionSensor* blendertouchsensor = (bCollisionSensor*)sens->data;
-
- bFindMaterial = (blendertouchsensor->mode & SENS_COLLISION_MATERIAL);
- bTouchPulse = (blendertouchsensor->mode & SENS_COLLISION_PULSE);
-
-
- const STR_String touchPropOrMatName = bFindMaterial ?
- blendertouchsensor->materialName : blendertouchsensor->name;
-
-
- if (gameobj->GetPhysicsController())
+ // we can reuse the Always event manager for the delay sensor
+ SCA_EventManager* eventmgr = logicmgr->FindEventManager(SCA_EventManager::BASIC_EVENTMGR);
+ if (eventmgr)
{
- gamesensor = new KX_TouchSensor(eventmgr,
+ bDelaySensor* delaysensor = (bDelaySensor*)sens->data;
+ gamesensor = new SCA_DelaySensor(eventmgr,
gameobj,
- bFindMaterial,
- bTouchPulse,
- touchPropOrMatName);
+ delaysensor->delay,
+ delaysensor->duration,
+ (delaysensor->flag & SENS_DELAY_REPEAT) != 0);
}
-
- }
-
- break;
- }
- case SENS_MESSAGE:
- {
- KX_NetworkEventManager* eventmgr = (KX_NetworkEventManager*)
- logicmgr->FindEventManager(SCA_EventManager::NETWORK_EVENTMGR);
- if (eventmgr) {
- bMessageSensor* msgSens = (bMessageSensor*) sens->data;
-
- /* Get our NetworkScene */
- NG_NetworkScene *NetworkScene = kxscene->GetNetworkScene();
- /* filter on the incoming subjects, might be empty */
- const STR_String subject = msgSens->subject;
-
- gamesensor = new KX_NetworkMessageSensor(
- eventmgr, // our eventmanager
- NetworkScene, // our NetworkScene
- gameobj, // the sensor controlling object
- subject); // subject to filter on
+ break;
}
- break;
- }
- case SENS_NEAR:
- {
-
- SCA_EventManager* eventmgr = logicmgr->FindEventManager(SCA_EventManager::TOUCH_EVENTMGR);
- if (eventmgr)
+
+ case SENS_COLLISION:
{
- bNearSensor* blendernearsensor = (bNearSensor*)sens->data;
- const STR_String nearpropertyname = (char *)blendernearsensor->name;
-
- //DT_ShapeHandle shape = DT_Sphere(0.0);
-
- // this sumoObject is not deleted by a gameobj, so delete it ourself
- // later (memleaks)!
- float radius = blendernearsensor->dist;
- const MT_Vector3& wpos = gameobj->NodeGetWorldPosition();
- bool bFindMaterial = false;
- PHY_IPhysicsController* physCtrl = kxscene->GetPhysicsEnvironment()->CreateSphereController(radius,wpos);
-
- //will be done in KX_TouchEventManager::RegisterSensor()
- //if (isInActiveLayer)
- // kxscene->GetPhysicsEnvironment()->addSensor(physCtrl);
-
-
-
- gamesensor = new KX_NearSensor(eventmgr,gameobj,
- blendernearsensor->dist,
- blendernearsensor->resetdist,
- bFindMaterial,
- nearpropertyname,
- physCtrl);
-
+ SCA_EventManager* eventmgr = logicmgr->FindEventManager(SCA_EventManager::TOUCH_EVENTMGR);
+ if (eventmgr)
+ {
+ // collision sensor can sense both materials and properties.
+
+ bool bFindMaterial = false, bTouchPulse = false;
+
+ bCollisionSensor* blendertouchsensor = (bCollisionSensor*)sens->data;
+
+ bFindMaterial = (blendertouchsensor->mode & SENS_COLLISION_MATERIAL);
+ bTouchPulse = (blendertouchsensor->mode & SENS_COLLISION_PULSE);
+
+
+ const STR_String touchPropOrMatName = bFindMaterial ?
+ blendertouchsensor->materialName : blendertouchsensor->name;
+
+
+ if (gameobj->GetPhysicsController())
+ {
+ gamesensor = new KX_TouchSensor(eventmgr,
+ gameobj,
+ bFindMaterial,
+ bTouchPulse,
+ touchPropOrMatName);
+ }
+
+ }
+
+ break;
}
- break;
- }
-
-
- case SENS_KEYBOARD:
- {
- /* temporary input device, for converting the code for the keyboard sensor */
-
- bKeyboardSensor* blenderkeybdsensor = (bKeyboardSensor*)sens->data;
- SCA_KeyboardManager* eventmgr = (SCA_KeyboardManager*) logicmgr->FindEventManager(SCA_EventManager::KEYBOARD_EVENTMGR);
- if (eventmgr)
+ case SENS_MESSAGE:
{
- gamesensor = new SCA_KeyboardSensor(eventmgr,
- ConvertKeyCode(blenderkeybdsensor->key),
- ConvertKeyCode(blenderkeybdsensor->qual),
- ConvertKeyCode(blenderkeybdsensor->qual2),
- (blenderkeybdsensor->type == SENS_ALL_KEYS),
- blenderkeybdsensor->targetName,
- blenderkeybdsensor->toggleName,
- gameobj,
- KX_KetsjiEngine::GetExitKey()); // blenderkeybdsensor->pad);
-
- }
-
- break;
- }
- case SENS_MOUSE:
- {
- int keytype = SCA_MouseSensor::KX_MOUSESENSORMODE_NODEF;
- int trackfocus = 0;
- bMouseSensor *bmouse = (bMouseSensor *)sens->data;
-
- /* There are two main types of mouse sensors. If there is
- * no focus-related behavior requested, we can make do
- * with a basic sensor. This cuts down memory usage and
- * gives a slight performance gain. */
-
- SCA_MouseManager *eventmgr
- = (SCA_MouseManager*) logicmgr->FindEventManager(SCA_EventManager::MOUSE_EVENTMGR);
- if (eventmgr) {
-
- /* Determine key mode. There is at most one active mode. */
- switch (bmouse->type) {
- case BL_SENS_MOUSE_LEFT_BUTTON:
- keytype = SCA_MouseSensor::KX_MOUSESENSORMODE_LEFTBUTTON;
- break;
- case BL_SENS_MOUSE_MIDDLE_BUTTON:
- keytype = SCA_MouseSensor::KX_MOUSESENSORMODE_MIDDLEBUTTON;
- break;
- case BL_SENS_MOUSE_RIGHT_BUTTON:
- keytype = SCA_MouseSensor::KX_MOUSESENSORMODE_RIGHTBUTTON;
- break;
- case BL_SENS_MOUSE_WHEEL_UP:
- keytype = SCA_MouseSensor::KX_MOUSESENSORMODE_WHEELUP;
- break;
- case BL_SENS_MOUSE_WHEEL_DOWN:
- keytype = SCA_MouseSensor::KX_MOUSESENSORMODE_WHEELDOWN;
- break;
- case BL_SENS_MOUSE_MOVEMENT:
- keytype = SCA_MouseSensor::KX_MOUSESENSORMODE_MOVEMENT;
- break;
- case BL_SENS_MOUSE_MOUSEOVER:
- trackfocus = 1;
- break;
- case BL_SENS_MOUSE_MOUSEOVER_ANY:
- trackfocus = 2;
- break;
-
- default:
- ; /* error */
+ KX_NetworkEventManager* eventmgr = (KX_NetworkEventManager*)
+ logicmgr->FindEventManager(SCA_EventManager::NETWORK_EVENTMGR);
+ if (eventmgr) {
+ bMessageSensor* msgSens = (bMessageSensor*) sens->data;
+
+ /* Get our NetworkScene */
+ NG_NetworkScene *NetworkScene = kxscene->GetNetworkScene();
+ /* filter on the incoming subjects, might be empty */
+ const STR_String subject = msgSens->subject;
+
+ gamesensor = new KX_NetworkMessageSensor(
+ eventmgr, // our eventmanager
+ NetworkScene, // our NetworkScene
+ gameobj, // the sensor controlling object
+ subject); // subject to filter on
}
-
- /* initial mouse position */
- int startx = canvas->GetWidth()/2;
- int starty = canvas->GetHeight()/2;
-
- if (!trackfocus) {
- /* plain, simple mouse sensor */
- gamesensor = new SCA_MouseSensor(eventmgr,
- startx,starty,
- keytype,
- gameobj);
- } else {
- /* give us a focus-aware sensor */
- bool bFindMaterial = (bmouse->mode & SENS_COLLISION_MATERIAL);
- bool bXRay = (bmouse->flag & SENS_RAY_XRAY);
- STR_String checkname = (bFindMaterial? bmouse->matname : bmouse->propname);
-
- gamesensor = new KX_MouseFocusSensor(eventmgr,
- startx,
- starty,
- keytype,
- trackfocus,
- (bmouse->flag & SENS_MOUSE_FOCUS_PULSE) ? true:false,
- checkname,
+ break;
+ }
+ case SENS_NEAR:
+ {
+
+ SCA_EventManager* eventmgr = logicmgr->FindEventManager(SCA_EventManager::TOUCH_EVENTMGR);
+ if (eventmgr)
+ {
+ bNearSensor* blendernearsensor = (bNearSensor*)sens->data;
+ const STR_String nearpropertyname = (char *)blendernearsensor->name;
+
+ //DT_ShapeHandle shape = DT_Sphere(0.0);
+
+ // this sumoObject is not deleted by a gameobj, so delete it ourself
+ // later (memleaks)!
+ float radius = blendernearsensor->dist;
+ const MT_Vector3& wpos = gameobj->NodeGetWorldPosition();
+ bool bFindMaterial = false;
+ PHY_IPhysicsController* physCtrl = kxscene->GetPhysicsEnvironment()->CreateSphereController(radius,wpos);
+
+ //will be done in KX_TouchEventManager::RegisterSensor()
+ //if (isInActiveLayer)
+ // kxscene->GetPhysicsEnvironment()->addSensor(physCtrl);
+
+
+
+ gamesensor = new KX_NearSensor(eventmgr,gameobj,
+ blendernearsensor->dist,
+ blendernearsensor->resetdist,
bFindMaterial,
- bXRay,
- kxscene,
- kxengine,
- gameobj);
+ nearpropertyname,
+ physCtrl);
+
}
- } else {
- // cout << "\n Could't find mouse event manager..."; - should throw an error here...
+ break;
}
- break;
- }
- case SENS_PROPERTY:
- {
- bPropertySensor* blenderpropsensor = (bPropertySensor*) sens->data;
- SCA_EventManager* eventmgr
- = logicmgr->FindEventManager(SCA_EventManager::BASIC_EVENTMGR);
- if (eventmgr)
+
+
+ case SENS_KEYBOARD:
{
- STR_String propname=blenderpropsensor->name;
- STR_String propval=blenderpropsensor->value;
- STR_String propmaxval=blenderpropsensor->maxvalue;
-
- SCA_PropertySensor::KX_PROPSENSOR_TYPE
- propchecktype = SCA_PropertySensor::KX_PROPSENSOR_NODEF;
-
- /* Better do an explicit conversion here! (was implicit */
- /* before...) */
- switch (blenderpropsensor->type) {
- case SENS_PROP_EQUAL:
- propchecktype = SCA_PropertySensor::KX_PROPSENSOR_EQUAL;
- break;
- case SENS_PROP_NEQUAL:
- propchecktype = SCA_PropertySensor::KX_PROPSENSOR_NOTEQUAL;
- break;
- case SENS_PROP_INTERVAL:
- propchecktype = SCA_PropertySensor::KX_PROPSENSOR_INTERVAL;
- break;
- case SENS_PROP_CHANGED:
- propchecktype = SCA_PropertySensor::KX_PROPSENSOR_CHANGED;
- break;
- case SENS_PROP_EXPRESSION:
- propchecktype = SCA_PropertySensor::KX_PROPSENSOR_EXPRESSION;
- /* error */
- break;
- case SENS_PROP_LESSTHAN:
- propchecktype = SCA_PropertySensor::KX_PROPSENSOR_LESSTHAN;
- break;
- case SENS_PROP_GREATERTHAN:
- propchecktype = SCA_PropertySensor::KX_PROPSENSOR_GREATERTHAN;
- break;
- default:
- ; /* error */
+ /* temporary input device, for converting the code for the keyboard sensor */
+
+ bKeyboardSensor* blenderkeybdsensor = (bKeyboardSensor*)sens->data;
+ SCA_KeyboardManager* eventmgr = (SCA_KeyboardManager*) logicmgr->FindEventManager(SCA_EventManager::KEYBOARD_EVENTMGR);
+ if (eventmgr)
+ {
+ gamesensor = new SCA_KeyboardSensor(eventmgr,
+ ConvertKeyCode(blenderkeybdsensor->key),
+ ConvertKeyCode(blenderkeybdsensor->qual),
+ ConvertKeyCode(blenderkeybdsensor->qual2),
+ (blenderkeybdsensor->type == SENS_ALL_KEYS),
+ blenderkeybdsensor->targetName,
+ blenderkeybdsensor->toggleName,
+ gameobj,
+ KX_KetsjiEngine::GetExitKey()); // blenderkeybdsensor->pad);
+
}
- gamesensor = new SCA_PropertySensor(eventmgr,gameobj,propname,propval,propmaxval,propchecktype);
+
+ break;
}
-
- break;
- }
- case SENS_ACTUATOR:
- {
- bActuatorSensor* blenderactsensor = (bActuatorSensor*) sens->data;
- // we will reuse the property event manager, there is nothing special with this sensor
- SCA_EventManager* eventmgr
- = logicmgr->FindEventManager(SCA_EventManager::ACTUATOR_EVENTMGR);
- if (eventmgr)
+ case SENS_MOUSE:
+ {
+ int keytype = SCA_MouseSensor::KX_MOUSESENSORMODE_NODEF;
+ int trackfocus = 0;
+ bMouseSensor *bmouse = (bMouseSensor *)sens->data;
+
+ /* There are two main types of mouse sensors. If there is
+ * no focus-related behavior requested, we can make do
+ * with a basic sensor. This cuts down memory usage and
+ * gives a slight performance gain. */
+
+ SCA_MouseManager *eventmgr
+ = (SCA_MouseManager*) logicmgr->FindEventManager(SCA_EventManager::MOUSE_EVENTMGR);
+ if (eventmgr) {
+
+ /* Determine key mode. There is at most one active mode. */
+ switch (bmouse->type) {
+ case BL_SENS_MOUSE_LEFT_BUTTON:
+ keytype = SCA_MouseSensor::KX_MOUSESENSORMODE_LEFTBUTTON;
+ break;
+ case BL_SENS_MOUSE_MIDDLE_BUTTON:
+ keytype = SCA_MouseSensor::KX_MOUSESENSORMODE_MIDDLEBUTTON;
+ break;
+ case BL_SENS_MOUSE_RIGHT_BUTTON:
+ keytype = SCA_MouseSensor::KX_MOUSESENSORMODE_RIGHTBUTTON;
+ break;
+ case BL_SENS_MOUSE_WHEEL_UP:
+ keytype = SCA_MouseSensor::KX_MOUSESENSORMODE_WHEELUP;
+ break;
+ case BL_SENS_MOUSE_WHEEL_DOWN:
+ keytype = SCA_MouseSensor::KX_MOUSESENSORMODE_WHEELDOWN;
+ break;
+ case BL_SENS_MOUSE_MOVEMENT:
+ keytype = SCA_MouseSensor::KX_MOUSESENSORMODE_MOVEMENT;
+ break;
+ case BL_SENS_MOUSE_MOUSEOVER:
+ trackfocus = 1;
+ break;
+ case BL_SENS_MOUSE_MOUSEOVER_ANY:
+ trackfocus = 2;
+ break;
+
+ default:
+ ; /* error */
+ }
+
+ /* initial mouse position */
+ int startx = canvas->GetWidth()/2;
+ int starty = canvas->GetHeight()/2;
+
+ if (!trackfocus) {
+ /* plain, simple mouse sensor */
+ gamesensor = new SCA_MouseSensor(eventmgr,
+ startx,starty,
+ keytype,
+ gameobj);
+ } else {
+ /* give us a focus-aware sensor */
+ bool bFindMaterial = (bmouse->mode & SENS_COLLISION_MATERIAL);
+ bool bXRay = (bmouse->flag & SENS_RAY_XRAY);
+ STR_String checkname = (bFindMaterial? bmouse->matname : bmouse->propname);
+
+ gamesensor = new KX_MouseFocusSensor(eventmgr,
+ startx,
+ starty,
+ keytype,
+ trackfocus,
+ (bmouse->flag & SENS_MOUSE_FOCUS_PULSE) ? true:false,
+ checkname,
+ bFindMaterial,
+ bXRay,
+ kxscene,
+ kxengine,
+ gameobj);
+ }
+ } else {
+ // cout << "\n Could't find mouse event manager..."; - should throw an error here...
+ }
+ break;
+ }
+ case SENS_PROPERTY:
{
- STR_String propname=blenderactsensor->name;
- gamesensor = new SCA_ActuatorSensor(eventmgr,gameobj,propname);
+ bPropertySensor* blenderpropsensor = (bPropertySensor*) sens->data;
+ SCA_EventManager* eventmgr
+ = logicmgr->FindEventManager(SCA_EventManager::BASIC_EVENTMGR);
+ if (eventmgr)
+ {
+ STR_String propname=blenderpropsensor->name;
+ STR_String propval=blenderpropsensor->value;
+ STR_String propmaxval=blenderpropsensor->maxvalue;
+
+ SCA_PropertySensor::KX_PROPSENSOR_TYPE
+ propchecktype = SCA_PropertySensor::KX_PROPSENSOR_NODEF;
+
+ /* Better do an explicit conversion here! (was implicit */
+ /* before...) */
+ switch (blenderpropsensor->type) {
+ case SENS_PROP_EQUAL:
+ propchecktype = SCA_PropertySensor::KX_PROPSENSOR_EQUAL;
+ break;
+ case SENS_PROP_NEQUAL:
+ propchecktype = SCA_PropertySensor::KX_PROPSENSOR_NOTEQUAL;
+ break;
+ case SENS_PROP_INTERVAL:
+ propchecktype = SCA_PropertySensor::KX_PROPSENSOR_INTERVAL;
+ break;
+ case SENS_PROP_CHANGED:
+ propchecktype = SCA_PropertySensor::KX_PROPSENSOR_CHANGED;
+ break;
+ case SENS_PROP_EXPRESSION:
+ propchecktype = SCA_PropertySensor::KX_PROPSENSOR_EXPRESSION;
+ /* error */
+ break;
+ case SENS_PROP_LESSTHAN:
+ propchecktype = SCA_PropertySensor::KX_PROPSENSOR_LESSTHAN;
+ break;
+ case SENS_PROP_GREATERTHAN:
+ propchecktype = SCA_PropertySensor::KX_PROPSENSOR_GREATERTHAN;
+ break;
+ default:
+ ; /* error */
+ }
+ gamesensor = new SCA_PropertySensor(eventmgr,gameobj,propname,propval,propmaxval,propchecktype);
+ }
+
+ break;
}
- break;
- }
-
- case SENS_ARMATURE:
- {
- bArmatureSensor* blenderarmsensor = (bArmatureSensor*) sens->data;
- // we will reuse the property event manager, there is nothing special with this sensor
- SCA_EventManager* eventmgr
- = logicmgr->FindEventManager(SCA_EventManager::BASIC_EVENTMGR);
- if (eventmgr)
+ case SENS_ACTUATOR:
{
- STR_String bonename=blenderarmsensor->posechannel;
- STR_String constraintname=blenderarmsensor->constraint;
- gamesensor = new KX_ArmatureSensor(eventmgr,gameobj,bonename,constraintname, blenderarmsensor->type, blenderarmsensor->value);
+ bActuatorSensor* blenderactsensor = (bActuatorSensor*) sens->data;
+ // we will reuse the property event manager, there is nothing special with this sensor
+ SCA_EventManager* eventmgr
+ = logicmgr->FindEventManager(SCA_EventManager::ACTUATOR_EVENTMGR);
+ if (eventmgr)
+ {
+ STR_String propname=blenderactsensor->name;
+ gamesensor = new SCA_ActuatorSensor(eventmgr,gameobj,propname);
+ }
+ break;
}
- break;
- }
- case SENS_RADAR:
- {
-
- SCA_EventManager* eventmgr = logicmgr->FindEventManager(SCA_EventManager::TOUCH_EVENTMGR);
- if (eventmgr)
+ case SENS_ARMATURE:
{
- bRadarSensor* blenderradarsensor = (bRadarSensor*) sens->data;
- const STR_String radarpropertyname = blenderradarsensor->name;
-
- int radaraxis = blenderradarsensor->axis;
-
- MT_Scalar coneheight = blenderradarsensor->range;
-
- // janco: the angle was doubled, so should I divide the factor in 2
- // 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(blenderradarsensor->angle * 0.5f);
- //MT_Scalar coneradius = coneheight * (factor / 2);
- MT_Scalar coneradius = coneheight * factor;
-
-
- // this sumoObject is not deleted by a gameobj, so delete it ourself
- // later (memleaks)!
- MT_Scalar smallmargin = 0.0;
- MT_Scalar largemargin = 0.0;
-
- bool bFindMaterial = false;
- PHY_IPhysicsController* ctrl = kxscene->GetPhysicsEnvironment()->CreateConeController((float)coneradius, (float)coneheight);
-
- gamesensor = new KX_RadarSensor(
- eventmgr,
- gameobj,
- ctrl,
- coneradius,
- coneheight,
- radaraxis,
- smallmargin,
- largemargin,
- bFindMaterial,
- radarpropertyname);
-
+ bArmatureSensor* blenderarmsensor = (bArmatureSensor*) sens->data;
+ // we will reuse the property event manager, there is nothing special with this sensor
+ SCA_EventManager* eventmgr
+ = logicmgr->FindEventManager(SCA_EventManager::BASIC_EVENTMGR);
+ if (eventmgr)
+ {
+ STR_String bonename=blenderarmsensor->posechannel;
+ STR_String constraintname=blenderarmsensor->constraint;
+ gamesensor = new KX_ArmatureSensor(eventmgr,gameobj,bonename,constraintname, blenderarmsensor->type, blenderarmsensor->value);
+ }
+ break;
}
-
- break;
- }
- case SENS_RAY:
- {
- bRaySensor* blenderraysensor = (bRaySensor*) sens->data;
-
- //blenderradarsensor->angle;
- SCA_EventManager* eventmgr = logicmgr->FindEventManager(SCA_EventManager::BASIC_EVENTMGR);
- if (eventmgr)
+
+ case SENS_RADAR:
{
- bool bFindMaterial = (blenderraysensor->mode & SENS_COLLISION_MATERIAL);
- bool bXRay = (blenderraysensor->mode & SENS_RAY_XRAY);
-
- STR_String checkname = (bFindMaterial? blenderraysensor->matname : blenderraysensor->propname);
-
- // don't want to get rays of length 0.0 or so
- double distance = (blenderraysensor->range < 0.01f ? 0.01f : blenderraysensor->range);
- int axis = blenderraysensor->axisflag;
-
-
- gamesensor = new KX_RaySensor(eventmgr,
- gameobj,
- checkname,
- bFindMaterial,
- bXRay,
- distance,
- axis,
- kxscene);
+ SCA_EventManager* eventmgr = logicmgr->FindEventManager(SCA_EventManager::TOUCH_EVENTMGR);
+ if (eventmgr)
+ {
+ bRadarSensor* blenderradarsensor = (bRadarSensor*) sens->data;
+ const STR_String radarpropertyname = blenderradarsensor->name;
+
+ int radaraxis = blenderradarsensor->axis;
+
+ MT_Scalar coneheight = blenderradarsensor->range;
+
+ // janco: the angle was doubled, so should I divide the factor in 2
+ // 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(blenderradarsensor->angle * 0.5f);
+ //MT_Scalar coneradius = coneheight * (factor / 2);
+ MT_Scalar coneradius = coneheight * factor;
+
+
+ // this sumoObject is not deleted by a gameobj, so delete it ourself
+ // later (memleaks)!
+ MT_Scalar smallmargin = 0.0;
+ MT_Scalar largemargin = 0.0;
+
+ bool bFindMaterial = false;
+ PHY_IPhysicsController* ctrl = kxscene->GetPhysicsEnvironment()->CreateConeController((float)coneradius, (float)coneheight);
+
+ gamesensor = new KX_RadarSensor(
+ eventmgr,
+ gameobj,
+ ctrl,
+ coneradius,
+ coneheight,
+ radaraxis,
+ smallmargin,
+ largemargin,
+ bFindMaterial,
+ radarpropertyname);
+
+ }
+
+ break;
}
- break;
- }
-
- case SENS_RANDOM:
- {
- bRandomSensor* blenderrndsensor = (bRandomSensor*) sens->data;
- // some files didn't write randomsensor, avoid crash now for NULL ptr's
- if (blenderrndsensor)
+ case SENS_RAY:
{
+ bRaySensor* blenderraysensor = (bRaySensor*) sens->data;
+
+ //blenderradarsensor->angle;
SCA_EventManager* eventmgr = logicmgr->FindEventManager(SCA_EventManager::BASIC_EVENTMGR);
if (eventmgr)
{
- int randomSeed = blenderrndsensor->seed;
- if (randomSeed == 0)
+ bool bFindMaterial = (blenderraysensor->mode & SENS_COLLISION_MATERIAL);
+ bool bXRay = (blenderraysensor->mode & SENS_RAY_XRAY);
+
+ STR_String checkname = (bFindMaterial? blenderraysensor->matname : blenderraysensor->propname);
+
+ // don't want to get rays of length 0.0 or so
+ double distance = (blenderraysensor->range < 0.01f ? 0.01f : blenderraysensor->range);
+ int axis = blenderraysensor->axisflag;
+
+
+ gamesensor = new KX_RaySensor(eventmgr,
+ gameobj,
+ checkname,
+ bFindMaterial,
+ bXRay,
+ distance,
+ axis,
+ kxscene);
+
+ }
+ break;
+ }
+
+ case SENS_RANDOM:
+ {
+ bRandomSensor* blenderrndsensor = (bRandomSensor*) sens->data;
+ // some files didn't write randomsensor, avoid crash now for NULL ptr's
+ if (blenderrndsensor)
+ {
+ SCA_EventManager* eventmgr = logicmgr->FindEventManager(SCA_EventManager::BASIC_EVENTMGR);
+ if (eventmgr)
{
- randomSeed = (int)(kxengine->GetRealTime()*100000.0);
- randomSeed ^= (intptr_t)blenderrndsensor;
+ int randomSeed = blenderrndsensor->seed;
+ if (randomSeed == 0)
+ {
+ randomSeed = (int)(kxengine->GetRealTime()*100000.0);
+ randomSeed ^= (intptr_t)blenderrndsensor;
+ }
+ gamesensor = new SCA_RandomSensor(eventmgr, gameobj, randomSeed);
}
- gamesensor = new SCA_RandomSensor(eventmgr, gameobj, randomSeed);
}
+ break;
}
- break;
- }
- case SENS_JOYSTICK:
- {
- int joysticktype = SCA_JoystickSensor::KX_JOYSENSORMODE_NODEF;
-
- bJoystickSensor* bjoy = (bJoystickSensor*) sens->data;
-
- SCA_JoystickManager *eventmgr
- = (SCA_JoystickManager*) logicmgr->FindEventManager(SCA_EventManager::JOY_EVENTMGR);
- if (eventmgr)
+ case SENS_JOYSTICK:
{
- int axis =0;
- int axisf =0;
- int button =0;
- int hat =0;
- int hatf =0;
- int prec =0;
-
- switch (bjoy->type) {
- case SENS_JOY_AXIS:
- axis = bjoy->axis;
- axisf = bjoy->axisf;
- prec = bjoy->precision;
- joysticktype = SCA_JoystickSensor::KX_JOYSENSORMODE_AXIS;
- break;
- case SENS_JOY_BUTTON:
- button = bjoy->button;
- joysticktype = SCA_JoystickSensor::KX_JOYSENSORMODE_BUTTON;
- break;
- case SENS_JOY_HAT:
- hat = bjoy->hat;
- hatf = bjoy->hatf;
- joysticktype = SCA_JoystickSensor::KX_JOYSENSORMODE_HAT;
- break;
- case SENS_JOY_AXIS_SINGLE:
- axis = bjoy->axis_single;
- prec = bjoy->precision;
- joysticktype = SCA_JoystickSensor::KX_JOYSENSORMODE_AXIS_SINGLE;
- break;
- default:
- printf("Error: bad case statement\n");
- break;
+ int joysticktype = SCA_JoystickSensor::KX_JOYSENSORMODE_NODEF;
+
+ bJoystickSensor* bjoy = (bJoystickSensor*) sens->data;
+
+ SCA_JoystickManager *eventmgr
+ = (SCA_JoystickManager*) logicmgr->FindEventManager(SCA_EventManager::JOY_EVENTMGR);
+ if (eventmgr)
+ {
+ int axis =0;
+ int axisf =0;
+ int button =0;
+ int hat =0;
+ int hatf =0;
+ int prec =0;
+
+ switch (bjoy->type) {
+ case SENS_JOY_AXIS:
+ axis = bjoy->axis;
+ axisf = bjoy->axisf;
+ prec = bjoy->precision;
+ joysticktype = SCA_JoystickSensor::KX_JOYSENSORMODE_AXIS;
+ break;
+ case SENS_JOY_BUTTON:
+ button = bjoy->button;
+ joysticktype = SCA_JoystickSensor::KX_JOYSENSORMODE_BUTTON;
+ break;
+ case SENS_JOY_HAT:
+ hat = bjoy->hat;
+ hatf = bjoy->hatf;
+ joysticktype = SCA_JoystickSensor::KX_JOYSENSORMODE_HAT;
+ break;
+ case SENS_JOY_AXIS_SINGLE:
+ axis = bjoy->axis_single;
+ prec = bjoy->precision;
+ joysticktype = SCA_JoystickSensor::KX_JOYSENSORMODE_AXIS_SINGLE;
+ break;
+ default:
+ printf("Error: bad case statement\n");
+ break;
+ }
+ gamesensor = new SCA_JoystickSensor(
+ eventmgr,
+ gameobj,
+ bjoy->joyindex,
+ joysticktype,
+ axis,axisf,
+ prec,
+ button,
+ hat,hatf,
+ (bjoy->flag & SENS_JOY_ANY_EVENT));
}
- gamesensor = new SCA_JoystickSensor(
- eventmgr,
- gameobj,
- bjoy->joyindex,
- joysticktype,
- axis,axisf,
- prec,
- button,
- hat,hatf,
- (bjoy->flag & SENS_JOY_ANY_EVENT));
- }
- else
+ else
+ {
+ printf("Error there was a problem finding the event manager\n");
+ }
+
+ break;
+ }
+ default:
{
- printf("Error there was a problem finding the event manager\n");
}
-
- break;
}
- default:
- {
- }
- }
- if (gamesensor && !(sens->flag & SENS_DEACTIVATE))
- {
- gamesensor->SetExecutePriority(executePriority++);
- STR_String uniquename = sens->name;
- uniquename += "#SENS#";
- uniqueint++;
- CIntValue* uniqueval = new CIntValue(uniqueint);
- uniquename += uniqueval->GetText();
- uniqueval->Release();
-
- /* Conversion succeeded, so we can set the generic props here. */
- gamesensor->SetPulseMode(pos_pulsemode,
- neg_pulsemode,
- frequency);
- gamesensor->SetInvert(invert);
- gamesensor->SetLevel(level);
- gamesensor->SetTap(tap);
- gamesensor->SetName(sens->name);
-
- gameobj->AddSensor(gamesensor);
-
- // only register to manager if it's in an active layer
- // Make registration dynamic: only when sensor is activated
- //if (isInActiveLayer)
- // gamesensor->RegisterToManager();
-
- gamesensor->ReserveController(sens->totlinks);
- for (int i=0;i<sens->totlinks;i++)
+ if (gamesensor)
{
- bController* linkedcont = (bController*) sens->links[i];
- if (linkedcont) {
- // If the controller is deactived doesn't register it
- if (!(linkedcont->flag & CONT_DEACTIVATE)) {
- SCA_IController* gamecont = converter->FindGameController(linkedcont);
-
- if (gamecont) {
- logicmgr->RegisterToSensor(gamecont,gamesensor);
- }
- else {
- printf("Warning, sensor \"%s\" could not find its controller "
- "(link %d of %d) from object \"%s\"\n"
- "\tthere has been an error converting the blender controller for the game engine,"
- "logic may be incorrect\n", sens->name, i+1, sens->totlinks, blenderobject->id.name+2);
+ gamesensor->SetExecutePriority(executePriority++);
+ STR_String uniquename = sens->name;
+ uniquename += "#SENS#";
+ uniqueint++;
+ CIntValue* uniqueval = new CIntValue(uniqueint);
+ uniquename += uniqueval->GetText();
+ uniqueval->Release();
+
+ /* Conversion succeeded, so we can set the generic props here. */
+ gamesensor->SetPulseMode(pos_pulsemode,
+ neg_pulsemode,
+ skipped_ticks);
+ gamesensor->SetInvert(invert);
+ gamesensor->SetLevel(level);
+ gamesensor->SetTap(tap);
+ gamesensor->SetName(sens->name);
+
+ gameobj->AddSensor(gamesensor);
+
+ // only register to manager if it's in an active layer
+ // Make registration dynamic: only when sensor is activated
+ //if (isInActiveLayer)
+ // gamesensor->RegisterToManager();
+
+ gamesensor->ReserveController(sens->totlinks);
+ for (int i=0;i<sens->totlinks;i++)
+ {
+ bController* linkedcont = (bController*) sens->links[i];
+ if (linkedcont) {
+ // If the controller is deactived doesn't register it
+ if (!(linkedcont->flag & CONT_DEACTIVATE)) {
+ SCA_IController* gamecont = converter->FindGameController(linkedcont);
+
+ if (gamecont) {
+ logicmgr->RegisterToSensor(gamecont,gamesensor);
+ }
+ else {
+ printf("Warning, sensor \"%s\" could not find its controller "
+ "(link %d of %d) from object \"%s\"\n"
+ "\tthere has been an error converting the blender controller for the game engine,"
+ "logic may be incorrect\n", sens->name, i+1, sens->totlinks, blenderobject->id.name+2);
+ }
}
}
+ else {
+ printf("Warning, sensor \"%s\" has lost a link to a controller "
+ "(link %d of %d) from object \"%s\"\n"
+ "\tpossible causes are partially appended objects or an error reading the file,"
+ "logic may be incorrect\n", sens->name, i+1, sens->totlinks, blenderobject->id.name+2);
+ }
}
- else {
- printf("Warning, sensor \"%s\" has lost a link to a controller "
- "(link %d of %d) from object \"%s\"\n"
- "\tpossible causes are partially appended objects or an error reading the file,"
- "logic may be incorrect\n", sens->name, i+1, sens->totlinks, blenderobject->id.name+2);
+ // special case: Keyboard sensor with no link
+ // this combination is usually used for key logging.
+ if (sens->type == SENS_KEYBOARD && sens->totlinks == 0) {
+ // Force the registration so that the sensor runs
+ gamesensor->IncLink();
}
+
+ // done with gamesensor
+ gamesensor->Release();
+
}
- // special case: Keyboard sensor with no link
- // this combination is usually used for key logging.
- if (sens->type == SENS_KEYBOARD && sens->totlinks == 0) {
- // Force the registration so that the sensor runs
- gamesensor->IncLink();
- }
-
- // done with gamesensor
- gamesensor->Release();
-
}
- else if (gamesensor)
- gamesensor->Release();
sens=sens->next;
}
diff --git a/source/gameengine/Converter/KX_LibLoadStatus.h b/source/gameengine/Converter/KX_LibLoadStatus.h
index 3da7329213b..bedf4498c96 100644
--- a/source/gameengine/Converter/KX_LibLoadStatus.h
+++ b/source/gameengine/Converter/KX_LibLoadStatus.h
@@ -27,7 +27,7 @@
#ifndef __KX_LIBLOADSTATUS_H__
#define __KX_LIBLOADSTATUS_H__
-#include "PyObjectPlus.h"
+#include "EXP_PyObjectPlus.h"
class KX_LibLoadStatus : public PyObjectPlus
{
diff --git a/source/gameengine/Converter/SConscript b/source/gameengine/Converter/SConscript
index affd4c94ed8..6336fcd3906 100644
--- a/source/gameengine/Converter/SConscript
+++ b/source/gameengine/Converter/SConscript
@@ -37,7 +37,6 @@ incs = [
'#intern/guardedalloc',
'#intern/string',
'#source/blender',
- '#intern/audaspace/intern',
'#intern/moto/include',
'#source/blender/blenkernel',
'#source/blender/blenlib',
@@ -79,6 +78,10 @@ if env['WITH_BF_PYTHON']:
incs += ' ' + env['BF_PYTHON_INC']
defs.append('WITH_PYTHON')
+if env['WITH_BF_AUDASPACE']:
+ defs += env['BF_AUDASPACE_DEF']
+ incs += ' ' + env['BF_AUDASPACE_C_INC']
+
if env['WITH_BF_CXX_GUARDEDALLOC']:
defs.append('WITH_CXX_GUARDEDALLOC')
diff --git a/source/gameengine/Expressions/CMakeLists.txt b/source/gameengine/Expressions/CMakeLists.txt
index 6907f314503..6ab4d3fdacc 100644
--- a/source/gameengine/Expressions/CMakeLists.txt
+++ b/source/gameengine/Expressions/CMakeLists.txt
@@ -36,47 +36,53 @@ set(INC_SYS
)
set(SRC
- BoolValue.cpp
- ConstExpr.cpp
- EXP_C-Api.cpp
- EmptyValue.cpp
- ErrorValue.cpp
- Expression.cpp
- FloatValue.cpp
- IdentifierExpr.cpp
- IfExpr.cpp
- InputParser.cpp
- IntValue.cpp
- KX_HashedPtr.cpp
- ListValue.cpp
- Operator1Expr.cpp
- Operator2Expr.cpp
- PyObjectPlus.cpp
- StringValue.cpp
- Value.cpp
- VectorValue.cpp
+ intern/BoolValue.cpp
+ intern/ConstExpr.cpp
+ intern/EmptyValue.cpp
+ intern/ErrorValue.cpp
+ intern/Expression.cpp
+ intern/FloatValue.cpp
+ intern/IdentifierExpr.cpp
+ intern/IfExpr.cpp
+ intern/InputParser.cpp
+ intern/IntValue.cpp
+ intern/HashedPtr.cpp
+ intern/ListValue.cpp
+ intern/Operator1Expr.cpp
+ intern/Operator2Expr.cpp
+ intern/PyObjectPlus.cpp
+ intern/StringValue.cpp
+ intern/Value.cpp
+ intern/VectorValue.cpp
- BoolValue.h
- ConstExpr.h
- EXP_C-Api.h
- EmptyValue.h
- ErrorValue.h
- Expression.h
- FloatValue.h
- IdentifierExpr.h
- IfExpr.h
- InputParser.h
- IntValue.h
- KX_HashedPtr.h
- KX_Python.h
- ListValue.h
- Operator1Expr.h
- Operator2Expr.h
- PyObjectPlus.h
- StringValue.h
- Value.h
- VectorValue.h
- VoidValue.h
+ EXP_BoolValue.h
+ EXP_ConstExpr.h
+ EXP_EmptyValue.h
+ EXP_ErrorValue.h
+ EXP_Expression.h
+ EXP_FloatValue.h
+ EXP_HashedPtr.h
+ EXP_IdentifierExpr.h
+ EXP_IfExpr.h
+ EXP_InputParser.h
+ EXP_IntValue.h
+ EXP_ListValue.h
+ EXP_Operator1Expr.h
+ EXP_Operator2Expr.h
+ EXP_PyObjectPlus.h
+ EXP_Python.h
+ EXP_StringValue.h
+ EXP_Value.h
+ EXP_VectorValue.h
+ EXP_VoidValue.h
)
+if(WITH_PYTHON)
+ list(APPEND SRC
+ intern/PythonCallBack.cpp
+
+ EXP_PythonCallBack.h
+ )
+endif()
+
blender_add_lib(ge_logic_expressions "${SRC}" "${INC}" "${INC_SYS}")
diff --git a/source/gameengine/Expressions/BoolValue.h b/source/gameengine/Expressions/EXP_BoolValue.h
index 161d6112f68..98ba1d75e52 100644
--- a/source/gameengine/Expressions/BoolValue.h
+++ b/source/gameengine/Expressions/EXP_BoolValue.h
@@ -12,14 +12,14 @@
*
*/
-/** \file BoolValue.h
+/** \file EXP_BoolValue.h
* \ingroup expressions
*/
-#ifndef __BOOLVALUE_H__
-#define __BOOLVALUE_H__
+#ifndef __EXP_BOOLVALUE_H__
+#define __EXP_BOOLVALUE_H__
-#include "Value.h"
+#include "EXP_Value.h"
/**
* Smart Boolean Value class.
@@ -62,4 +62,4 @@ private:
#endif
};
-#endif /* __BOOLVALUE_H__ */
+#endif /* __EXP_BOOLVALUE_H__ */
diff --git a/source/gameengine/Expressions/EXP_C-Api.cpp b/source/gameengine/Expressions/EXP_C-Api.cpp
deleted file mode 100644
index 2822fd8f6de..00000000000
--- a/source/gameengine/Expressions/EXP_C-Api.cpp
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
- * ***** BEGIN GPL LICENSE BLOCK *****
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
- * All rights reserved.
- *
- * The Original Code is: all of this file.
- *
- * Contributor(s): none yet.
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-
-/** \file gameengine/Expressions/EXP_C-Api.cpp
- * \ingroup expressions
- */
-
-#include "EXP_C-Api.h"
-#include "IntValue.h"
-#include "BoolValue.h"
-#include "StringValue.h"
-#include "ErrorValue.h"
-#include "InputParser.h"
-
-EXP_ValueHandle EXP_CreateInt(int innie)
-{
- return (EXP_ValueHandle) new CIntValue(innie);
-}
-
-
-
-EXP_ValueHandle EXP_CreateBool(int innie)
-{
- return (EXP_ValueHandle) new CBoolValue(innie!=0);
-}
-
-
-
-EXP_ValueHandle EXP_CreateString(const char* str)
-{
-
- return (EXP_ValueHandle) new CStringValue(str,"");
-}
-
-
-
-void EXP_SetName(EXP_ValueHandle inval,const char* newname)
-{
- ((CValue*) inval)->SetName(newname);
-}
-
-
-
-/* calculate expression from inputtext */
-EXP_ValueHandle EXP_ParseInput(const char* inputtext)
-{
- CValue* resultval=NULL;
- CParser parser;
- CExpression* expr = parser.ProcessText(inputtext);
- if (expr)
- {
- resultval = expr->Calculate();
- expr->Release();
- }
- else
- {
- resultval = new CErrorValue("couldn't parsetext");
- }
-
- return (EXP_ValueHandle) resultval;
-}
-
-
-
-void EXP_ReleaseValue(EXP_ValueHandle inval)
-{
- ((CValue*) inval)->Release();
-}
-
-
-
-int EXP_IsValid(EXP_ValueHandle inval)
-{
- return !((CValue*) inval)->IsError();
-}
-
-
-
-/* assign property 'propval' to 'destinationval' */
-void EXP_SetProperty(EXP_ValueHandle destinationval,
- const char *propname,
- EXP_ValueHandle propval)
-{
- ((CValue*) destinationval)->SetProperty(propname,(CValue*)propval);
-}
-
-
-
-const char* EXP_GetText(EXP_ValueHandle inval)
-{
- return ((CValue*) inval)->GetText();
-}
-
-
-
-EXP_ValueHandle EXP_GetProperty(EXP_ValueHandle inval,const char* propname)
-{
- return (EXP_ValueHandle) ((CValue*)inval)->GetProperty(propname);
-}
diff --git a/source/gameengine/Expressions/EXP_C-Api.h b/source/gameengine/Expressions/EXP_C-Api.h
deleted file mode 100644
index d73b0a209d4..00000000000
--- a/source/gameengine/Expressions/EXP_C-Api.h
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * ***** BEGIN GPL LICENSE BLOCK *****
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
- * All rights reserved.
- *
- * The Original Code is: all of this file.
- *
- * Contributor(s): none yet.
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-
-/** \file EXP_C-Api.h
- * \ingroup expressions
- */
-
-#ifndef __EXP_C_API_H__
-#define __EXP_C_API_H__
-
-#define EXP_DECLARE_HANDLE(name) typedef struct name##__ { int unused; } *name
-
-EXP_DECLARE_HANDLE(EXP_ValueHandle);
-EXP_DECLARE_HANDLE(EXP_ExpressionHandle);
-
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-extern EXP_ValueHandle EXP_CreateInt(int innie);
-extern EXP_ValueHandle EXP_CreateBool(int innie);
-extern EXP_ValueHandle EXP_CreateString(const char* str);
-extern void EXP_SetName(EXP_ValueHandle,const char* newname);
-
-/* calculate expression from inputtext */
-extern EXP_ValueHandle EXP_ParseInput(const char* inputtext);
-extern void EXP_ReleaseValue(EXP_ValueHandle);
-extern int EXP_IsValid(EXP_ValueHandle);
-
-/* assign property 'propval' to 'destinationval' */
-extern void EXP_SetProperty(EXP_ValueHandle destinationval, const char *propname, EXP_ValueHandle propval);
-
-/* returns NULL if property doesn't exist */
-extern EXP_ValueHandle EXP_GetProperty(EXP_ValueHandle inval,const char* propname);
-
-const char* EXP_GetText(EXP_ValueHandle);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* __EXP_C_API_H__ */
diff --git a/source/gameengine/Expressions/ConstExpr.h b/source/gameengine/Expressions/EXP_ConstExpr.h
index 768f2bbd10e..b4456dacdf3 100644
--- a/source/gameengine/Expressions/ConstExpr.h
+++ b/source/gameengine/Expressions/EXP_ConstExpr.h
@@ -12,15 +12,15 @@
*
*/
-/** \file ConstExpr.h
+/** \file EXP_ConstExpr.h
* \ingroup expressions
*/
-#ifndef __CONSTEXPR_H__
-#define __CONSTEXPR_H__
+#ifndef __EXP_CONSTEXPR_H__
+#define __EXP_CONSTEXPR_H__
-#include "Expression.h"
-#include "Value.h" // Added by ClassView
+#include "EXP_Expression.h"
+#include "EXP_Value.h" // Added by ClassView
class CConstExpr : public CExpression
{
@@ -51,4 +51,4 @@ private:
#endif
};
-#endif /* __CONSTEXPR_H__ */
+#endif /* __EXP_CONSTEXPR_H__ */
diff --git a/source/gameengine/Expressions/EmptyValue.h b/source/gameengine/Expressions/EXP_EmptyValue.h
index 88ef206f0f0..d23addb9f9f 100644
--- a/source/gameengine/Expressions/EmptyValue.h
+++ b/source/gameengine/Expressions/EXP_EmptyValue.h
@@ -12,14 +12,14 @@
*
*/
-/** \file EmptyValue.h
+/** \file EXP_EmptyValue.h
* \ingroup expressions
*/
-#ifndef __EMPTYVALUE_H__
-#define __EMPTYVALUE_H__
+#ifndef __EXP_EMPTYVALUE_H__
+#define __EXP_EMPTYVALUE_H__
-#include "Value.h"
+#include "EXP_Value.h"
class CListValue;
@@ -46,4 +46,4 @@ public:
#endif
};
-#endif /* __EMPTYVALUE_H__ */
+#endif /* __EXP_EMPTYVALUE_H__ */
diff --git a/source/gameengine/Expressions/ErrorValue.h b/source/gameengine/Expressions/EXP_ErrorValue.h
index 61c72151f40..a6f91ca200a 100644
--- a/source/gameengine/Expressions/ErrorValue.h
+++ b/source/gameengine/Expressions/EXP_ErrorValue.h
@@ -12,14 +12,14 @@
*
*/
-/** \file ErrorValue.h
+/** \file EXP_ErrorValue.h
* \ingroup expressions
*/
-#ifndef __ERRORVALUE_H__
-#define __ERRORVALUE_H__
+#ifndef __EXP_ERRORVALUE_H__
+#define __EXP_ERRORVALUE_H__
-#include "Value.h"
+#include "EXP_Value.h"
class CErrorValue : public CPropValue
{
@@ -44,4 +44,4 @@ private:
#endif
};
-#endif /* __ERRORVALUE_H__ */
+#endif /* __EXP_ERRORVALUE_H__ */
diff --git a/source/gameengine/Expressions/Expression.h b/source/gameengine/Expressions/EXP_Expression.h
index 9a4f1f93284..66a6e9476ff 100644
--- a/source/gameengine/Expressions/Expression.h
+++ b/source/gameengine/Expressions/EXP_Expression.h
@@ -12,14 +12,14 @@
*
*/
-/** \file Expression.h
+/** \file EXP_Expression.h
* \ingroup expressions
*/
-#ifndef __EXPRESSION_H__
-#define __EXPRESSION_H__
+#ifndef __EXP_EXPRESSION_H__
+#define __EXP_EXPRESSION_H__
-#include "Value.h"
+#include "EXP_Value.h"
//extern int gRefCountExpr; // only for debugging purposes (detect mem.leaks)
@@ -146,4 +146,4 @@ protected:
#endif
};
-#endif /* __EXPRESSION_H__ */
+#endif /* __EXP_EXPRESSION_H__ */
diff --git a/source/gameengine/Expressions/FloatValue.h b/source/gameengine/Expressions/EXP_FloatValue.h
index 379c3e951bc..3c16c57d16d 100644
--- a/source/gameengine/Expressions/FloatValue.h
+++ b/source/gameengine/Expressions/EXP_FloatValue.h
@@ -12,14 +12,14 @@
*
*/
-/** \file FloatValue.h
+/** \file EXP_FloatValue.h
* \ingroup expressions
*/
-#ifndef __FLOATVALUE_H__
-#define __FLOATVALUE_H__
+#ifndef __EXP_FLOATVALUE_H__
+#define __EXP_FLOATVALUE_H__
-#include "Value.h"
+#include "EXP_Value.h"
class CFloatValue : public CPropValue
{
@@ -55,4 +55,4 @@ protected:
#endif
};
-#endif /* __FLOATVALUE_H__ */
+#endif /* __EXP_FLOATVALUE_H__ */
diff --git a/source/gameengine/Expressions/KX_HashedPtr.h b/source/gameengine/Expressions/EXP_HashedPtr.h
index acd9d4daafa..7c7c5f6e5ec 100644
--- a/source/gameengine/Expressions/KX_HashedPtr.h
+++ b/source/gameengine/Expressions/EXP_HashedPtr.h
@@ -25,19 +25,17 @@
* ***** END GPL LICENSE BLOCK *****
*/
-/** \file KX_HashedPtr.h
+/** \file EXP_HashedPtr.h
* \ingroup expressions
*/
-#ifndef __KX_HASHEDPTR_H__
-#define __KX_HASHEDPTR_H__
+#ifndef __EXP_HASHEDPTR_H__
+#define __EXP_HASHEDPTR_H__
#ifdef WITH_CXX_GUARDEDALLOC
#include "MEM_guardedalloc.h"
#endif
-unsigned int KX_Hash(void *inDWord);
-
class CHashedPtr
{
void* m_valptr;
@@ -58,4 +56,4 @@ public:
#endif
};
-#endif /* __KX_HASHEDPTR_H__ */
+#endif /* __EXP_HASHEDPTR_H__ */
diff --git a/source/gameengine/Expressions/IdentifierExpr.h b/source/gameengine/Expressions/EXP_IdentifierExpr.h
index 26eb3691378..96ef3677cf3 100644
--- a/source/gameengine/Expressions/IdentifierExpr.h
+++ b/source/gameengine/Expressions/EXP_IdentifierExpr.h
@@ -25,14 +25,14 @@
* ***** END GPL LICENSE BLOCK *****
*/
-/** \file IdentifierExpr.h
+/** \file EXP_IdentifierExpr.h
* \ingroup expressions
*/
-#ifndef __IDENTIFIEREXPR_H__
-#define __IDENTIFIEREXPR_H__
+#ifndef __EXP_IDENTIFIEREXPR_H__
+#define __EXP_IDENTIFIEREXPR_H__
-#include "Expression.h"
+#include "EXP_Expression.h"
class CIdentifierExpr : public CExpression
{
@@ -56,4 +56,4 @@ public:
#endif
};
-#endif /* __IDENTIFIEREXPR_H__ */
+#endif /* __EXP_IDENTIFIEREXPR_H__ */
diff --git a/source/gameengine/Expressions/IfExpr.h b/source/gameengine/Expressions/EXP_IfExpr.h
index 80e35471d82..43b4b8faf53 100644
--- a/source/gameengine/Expressions/IfExpr.h
+++ b/source/gameengine/Expressions/EXP_IfExpr.h
@@ -12,14 +12,14 @@
*
*/
-/** \file IfExpr.h
+/** \file EXP_IfExpr.h
* \ingroup expressions
*/
-#ifndef __IFEXPR_H__
-#define __IFEXPR_H__
+#ifndef __EXP_IFEXPR_H__
+#define __EXP_IFEXPR_H__
-#include "Expression.h"
+#include "EXP_Expression.h"
class CIfExpr : public CExpression
{
@@ -51,4 +51,4 @@ public:
#endif
};
-#endif /* __IFEXPR_H__ */
+#endif /* __EXP_IFEXPR_H__ */
diff --git a/source/gameengine/Expressions/InputParser.h b/source/gameengine/Expressions/EXP_InputParser.h
index 50bb1ae2f6e..80471009a16 100644
--- a/source/gameengine/Expressions/InputParser.h
+++ b/source/gameengine/Expressions/EXP_InputParser.h
@@ -14,15 +14,15 @@
*
*/
-/** \file InputParser.h
+/** \file EXP_InputParser.h
* \ingroup expressions
*/
-#ifndef __INPUTPARSER_H__
-#define __INPUTPARSER_H__
+#ifndef __EXP_INPUTPARSER_H__
+#define __EXP_INPUTPARSER_H__
class CParser;
-#include "Expression.h"
+#include "EXP_Expression.h"
class CParser
@@ -114,5 +114,5 @@ private:
#endif
};
-#endif
+#endif /* __EXP_INPUTPARSER_H__ */
diff --git a/source/gameengine/Expressions/IntValue.h b/source/gameengine/Expressions/EXP_IntValue.h
index 6da975f4f7f..a1cd96a888e 100644
--- a/source/gameengine/Expressions/IntValue.h
+++ b/source/gameengine/Expressions/EXP_IntValue.h
@@ -12,15 +12,15 @@
*
*/
-/** \file IntValue.h
+/** \file EXP_IntValue.h
* \ingroup expressions
*/
-#ifndef __INTVALUE_H__
-#define __INTVALUE_H__
+#ifndef __EXP_INTVALUE_H__
+#define __EXP_INTVALUE_H__
-#include "Value.h"
+#include "EXP_Value.h"
typedef long long cInt;
@@ -70,4 +70,4 @@ private:
#endif
};
-#endif /* __INTVALUE_H__ */
+#endif /* __EXP_INTVALUE_H__ */
diff --git a/source/gameengine/Expressions/ListValue.h b/source/gameengine/Expressions/EXP_ListValue.h
index bb188179836..f5421066f62 100644
--- a/source/gameengine/Expressions/ListValue.h
+++ b/source/gameengine/Expressions/EXP_ListValue.h
@@ -12,14 +12,14 @@
*
*/
-/** \file ListValue.h
+/** \file EXP_ListValue.h
* \ingroup expressions
*/
-#ifndef __LISTVALUE_H__
-#define __LISTVALUE_H__
+#ifndef __EXP_LISTVALUE_H__
+#define __EXP_LISTVALUE_H__
-#include "Value.h"
+#include "EXP_Value.h"
class CListValue : public CPropValue
{
@@ -88,5 +88,5 @@ private:
bool m_bReleaseContents;
};
-#endif /* __LISTVALUE_H__ */
+#endif /* __EXP_LISTVALUE_H__ */
diff --git a/source/gameengine/Expressions/Operator1Expr.h b/source/gameengine/Expressions/EXP_Operator1Expr.h
index 3dd76f773f2..9a05ce9c0c4 100644
--- a/source/gameengine/Expressions/Operator1Expr.h
+++ b/source/gameengine/Expressions/EXP_Operator1Expr.h
@@ -12,14 +12,14 @@
*
*/
-/** \file Operator1Expr.h
+/** \file EXP_Operator1Expr.h
* \ingroup expressions
*/
-#ifndef __OPERATOR1EXPR_H__
-#define __OPERATOR1EXPR_H__
+#ifndef __EXP_OPERATOR1EXPR_H__
+#define __EXP_OPERATOR1EXPR_H__
-#include "Expression.h"
+#include "EXP_Expression.h"
class COperator1Expr : public CExpression
{
@@ -56,4 +56,4 @@ private:
#endif
};
-#endif /* __OPERATOR1EXPR_H__ */
+#endif /* __EXP_OPERATOR1EXPR_H__ */
diff --git a/source/gameengine/Expressions/Operator2Expr.h b/source/gameengine/Expressions/EXP_Operator2Expr.h
index 8c30b7cd634..cd7a492fde0 100644
--- a/source/gameengine/Expressions/Operator2Expr.h
+++ b/source/gameengine/Expressions/EXP_Operator2Expr.h
@@ -12,16 +12,16 @@
*
*/
-/** \file Operator2Expr.h
+/** \file EXP_Operator2Expr.h
* \ingroup expressions
*/
-#ifndef __OPERATOR2EXPR_H__
-#define __OPERATOR2EXPR_H__
+#ifndef __EXP_OPERATOR2EXPR_H__
+#define __EXP_OPERATOR2EXPR_H__
-#include "Expression.h"
-#include "Value.h" // Added by ClassView
+#include "EXP_Expression.h"
+#include "EXP_Value.h" // Added by ClassView
class COperator2Expr : public CExpression
{
@@ -62,5 +62,5 @@ private:
#endif
};
-#endif /* __OPERATOR2EXPR_H__ */
+#endif /* __EXP_OPERATOR2EXPR_H__ */
diff --git a/source/gameengine/Expressions/PyObjectPlus.h b/source/gameengine/Expressions/EXP_PyObjectPlus.h
index e2e7c248795..dd612a08494 100644
--- a/source/gameengine/Expressions/PyObjectPlus.h
+++ b/source/gameengine/Expressions/EXP_PyObjectPlus.h
@@ -25,12 +25,12 @@
* ***** END GPL LICENSE BLOCK *****
*/
-/** \file PyObjectPlus.h
+/** \file EXP_PyObjectPlus.h
* \ingroup expressions
*/
-#ifndef __PYOBJECTPLUS_H__
-#define __PYOBJECTPLUS_H__
+#ifndef __EXP_PYOBJECTPLUS_H__
+#define __EXP_PYOBJECTPLUS_H__
/* for now keep weakrefs optional */
#define USE_WEAKREFS
@@ -40,7 +40,7 @@
#error Must be compiled with C++
#endif
-#include "KX_Python.h"
+#include "EXP_Python.h"
#include "STR_String.h"
#include "MT_Vector3.h"
#include "SG_QList.h"
@@ -65,21 +65,21 @@ typedef struct {
#define ShowDeprecationWarning(old_way, new_way) \
{ \
static WarnLink wlink = {false, NULL}; \
- if ((m_ignore_deprecation_warnings || wlink.warn_done)==0) \
+ if ((PyObjectPlus::m_ignore_deprecation_warnings || wlink.warn_done)==0) \
{ \
- ShowDeprecationWarning_func(old_way, new_way); \
+ PyObjectPlus::ShowDeprecationWarning_func(old_way, new_way); \
\
- WarnLink *wlink_last= GetDeprecationWarningLinkLast(); \
+ WarnLink *wlink_last= PyObjectPlus::GetDeprecationWarningLinkLast(); \
wlink.warn_done = true; \
wlink.link = NULL; \
\
if(wlink_last) { \
wlink_last->link= (void *)&(wlink); \
- SetDeprecationWarningLinkLast(&(wlink)); \
+ PyObjectPlus::SetDeprecationWarningLinkLast(&(wlink)); \
} \
else { \
- SetDeprecationWarningFirst(&(wlink)); \
- SetDeprecationWarningLinkLast(&(wlink)); \
+ PyObjectPlus::SetDeprecationWarningFirst(&(wlink)); \
+ PyObjectPlus::SetDeprecationWarningLinkLast(&(wlink)); \
} \
} \
} \
@@ -111,6 +111,8 @@ typedef struct PyObjectPlus_Proxy {
/* Opposite of BGE_PROXY_REF */
#define BGE_PROXY_FROM_REF(_self) (((PyObjectPlus *)_self)->GetProxy())
+/* Same as 'BGE_PROXY_REF' but doesn't incref. */
+#define BGE_PROXY_FROM_REF_BORROW(_self) _bge_proxy_from_ref_borrow((void *)_self)
// This must be the first line of each
@@ -631,6 +633,16 @@ public:
#ifdef WITH_PYTHON
PyObject *PyUnicode_From_STR_String(const STR_String& str);
+
+inline PyObject *_bge_proxy_from_ref_borrow(void *self_v)
+{
+ PyObject *self_proxy = BGE_PROXY_FROM_REF(self_v);
+ /* this is typically _very_ bad practice,
+ * however we know the proxy is owned by 'self_v' */
+ self_proxy->ob_refcnt--;
+ return self_proxy;
+}
+
#endif
-#endif /* __PYOBJECTPLUS_H__ */
+#endif /* __EXP_PYOBJECTPLUS_H__ */
diff --git a/source/gameengine/Expressions/KX_Python.h b/source/gameengine/Expressions/EXP_Python.h
index 62dd9a13dd4..f904151085e 100644
--- a/source/gameengine/Expressions/KX_Python.h
+++ b/source/gameengine/Expressions/EXP_Python.h
@@ -25,12 +25,12 @@
* ***** END GPL LICENSE BLOCK *****
*/
-/** \file KX_Python.h
+/** \file EXP_Python.h
* \ingroup expressions
*/
-#ifndef __KX_PYTHON_H__
-#define __KX_PYTHON_H__
+#ifndef __EXP_PYTHON_H__
+#define __EXP_PYTHON_H__
//#define USE_DL_EXPORT
@@ -79,4 +79,4 @@
#undef toupper
#endif
-#endif /* __KX_PYTHON_H__ */
+#endif /* __EXP_PYTHON_H__ */
diff --git a/source/gameengine/Expressions/EXP_PythonCallBack.h b/source/gameengine/Expressions/EXP_PythonCallBack.h
new file mode 100644
index 00000000000..f0cbcac0c6f
--- /dev/null
+++ b/source/gameengine/Expressions/EXP_PythonCallBack.h
@@ -0,0 +1,40 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributor(s): Porteries Tristan.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file EXP_PythonCallBack.h
+ * \ingroup expressions
+ */
+
+#ifndef __EXP_PYTHON_CALLBACK_H__
+#define __EXP_PYTHON_CALLBACK_H__
+
+#include "EXP_Python.h"
+
+/** Execute each functions with at least one argument
+ * \param functionlist The python list which contains callbacks.
+ * \param arglist The first item in the tuple to execute callbacks (can be NULL for no arguments).
+ * \param minargcount The minimum of quantity of arguments possible.
+ * \param maxargcount The maximum of quantity of arguments possible.
+ */
+void RunPythonCallBackList(PyObject *functionlist, PyObject **arglist, unsigned int minargcount, unsigned int maxargcount);
+
+#endif // __EXP_PYTHON_CALLBACK_H__
diff --git a/source/gameengine/Expressions/StringValue.h b/source/gameengine/Expressions/EXP_StringValue.h
index cb60600ad88..ca59ebf1f82 100644
--- a/source/gameengine/Expressions/StringValue.h
+++ b/source/gameengine/Expressions/EXP_StringValue.h
@@ -12,14 +12,14 @@
*
*/
-/** \file StringValue.h
+/** \file EXP_StringValue.h
* \ingroup expressions
*/
-#ifndef __STRINGVALUE_H__
-#define __STRINGVALUE_H__
+#ifndef __EXP_STRINGVALUE_H__
+#define __EXP_STRINGVALUE_H__
-#include "Value.h"
+#include "EXP_Value.h"
class CStringValue : public CPropValue
{
@@ -58,4 +58,4 @@ private:
#endif
};
-#endif /* __STRINGVALUE_H__ */
+#endif /* __EXP_STRINGVALUE_H__ */
diff --git a/source/gameengine/Expressions/Value.h b/source/gameengine/Expressions/EXP_Value.h
index c7e9a40a059..014fc59405f 100644
--- a/source/gameengine/Expressions/Value.h
+++ b/source/gameengine/Expressions/EXP_Value.h
@@ -12,12 +12,12 @@
*
*/
-/** \file Value.h
+/** \file EXP_Value.h
* \ingroup expressions
*/
-#ifndef __VALUE_H__
-#define __VALUE_H__
+#ifndef __EXP_VALUE_H__
+#define __EXP_VALUE_H__
#ifdef _MSC_VER
# pragma warning (disable:4786)
@@ -159,7 +159,7 @@ public:
};
-#include "PyObjectPlus.h"
+#include "EXP_PyObjectPlus.h"
#ifdef WITH_PYTHON
#include "object.h"
#endif
@@ -429,4 +429,4 @@ protected:
#endif
};
-#endif /* __VALUE_H__ */
+#endif /* __EXP_VALUE_H__ */
diff --git a/source/gameengine/Expressions/VectorValue.h b/source/gameengine/Expressions/EXP_VectorValue.h
index 717fa68f6dc..d87d5097156 100644
--- a/source/gameengine/Expressions/VectorValue.h
+++ b/source/gameengine/Expressions/EXP_VectorValue.h
@@ -12,14 +12,14 @@
*
*/
-/** \file VectorValue.h
+/** \file EXP_VectorValue.h
* \ingroup expressions
*/
-#ifndef __VECTORVALUE_H__
-#define __VECTORVALUE_H__
+#ifndef __EXP_VECTORVALUE_H__
+#define __EXP_VECTORVALUE_H__
-#include "Value.h"
+#include "EXP_Value.h"
#define KX_X 0
#define KX_Y 1
@@ -91,4 +91,4 @@ protected:
#endif
};
-#endif /* __VECTORVALUE_H__ */
+#endif /* __EXP_VECTORVALUE_H__ */
diff --git a/source/gameengine/Expressions/VoidValue.h b/source/gameengine/Expressions/EXP_VoidValue.h
index 4f74910dd8a..8b2c29488d7 100644
--- a/source/gameengine/Expressions/VoidValue.h
+++ b/source/gameengine/Expressions/EXP_VoidValue.h
@@ -27,14 +27,14 @@
* ***** END GPL LICENSE BLOCK *****
*/
-/** \file VoidValue.h
+/** \file EXP_VoidValue.h
* \ingroup expressions
*/
-#ifndef __VOIDVALUE_H__
-#define __VOIDVALUE_H__
+#ifndef __EXP_VOIDVALUE_H__
+#define __EXP_VOIDVALUE_H__
-#include "Value.h"
+#include "EXP_Value.h"
//
// Void value, used to transport *any* type of data
@@ -78,4 +78,4 @@ public:
#endif
};
-#endif /* __VOIDVALUE_H__ */
+#endif /* __EXP_VOIDVALUE_H__ */
diff --git a/source/gameengine/Expressions/SConscript b/source/gameengine/Expressions/SConscript
index 48102e5ba3c..b66d36c2080 100644
--- a/source/gameengine/Expressions/SConscript
+++ b/source/gameengine/Expressions/SConscript
@@ -27,7 +27,7 @@
Import ('env')
-sources = env.Glob('*.cpp')
+sources = env.Glob('intern/*.cpp')
incs = [
'.',
diff --git a/source/gameengine/Expressions/BoolValue.cpp b/source/gameengine/Expressions/intern/BoolValue.cpp
index 9ff53395056..1523a9212ba 100644
--- a/source/gameengine/Expressions/BoolValue.cpp
+++ b/source/gameengine/Expressions/intern/BoolValue.cpp
@@ -16,10 +16,10 @@
*
*/
-#include "BoolValue.h"
-#include "StringValue.h"
-#include "ErrorValue.h"
-#include "VoidValue.h"
+#include "EXP_BoolValue.h"
+#include "EXP_StringValue.h"
+#include "EXP_ErrorValue.h"
+#include "EXP_VoidValue.h"
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
diff --git a/source/gameengine/Expressions/ConstExpr.cpp b/source/gameengine/Expressions/intern/ConstExpr.cpp
index c41cf5a54f5..597427ecfe5 100644
--- a/source/gameengine/Expressions/ConstExpr.cpp
+++ b/source/gameengine/Expressions/intern/ConstExpr.cpp
@@ -16,9 +16,9 @@
*
*/
-#include "Value.h" // for precompiled header
-#include "ConstExpr.h"
-#include "VectorValue.h"
+#include "EXP_Value.h" // for precompiled header
+#include "EXP_ConstExpr.h"
+#include "EXP_VectorValue.h"
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
diff --git a/source/gameengine/Expressions/EmptyValue.cpp b/source/gameengine/Expressions/intern/EmptyValue.cpp
index f8e72181ed7..9227626777d 100644
--- a/source/gameengine/Expressions/EmptyValue.cpp
+++ b/source/gameengine/Expressions/intern/EmptyValue.cpp
@@ -16,13 +16,13 @@
*
*/
-#include "EmptyValue.h"
-#include "IntValue.h"
-#include "FloatValue.h"
-#include "StringValue.h"
-#include "ErrorValue.h"
-#include "ListValue.h"
-#include "VoidValue.h"
+#include "EXP_EmptyValue.h"
+#include "EXP_IntValue.h"
+#include "EXP_FloatValue.h"
+#include "EXP_StringValue.h"
+#include "EXP_ErrorValue.h"
+#include "EXP_ListValue.h"
+#include "EXP_VoidValue.h"
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
diff --git a/source/gameengine/Expressions/ErrorValue.cpp b/source/gameengine/Expressions/intern/ErrorValue.cpp
index 46e09b9073f..c03ceb88073 100644
--- a/source/gameengine/Expressions/ErrorValue.cpp
+++ b/source/gameengine/Expressions/intern/ErrorValue.cpp
@@ -15,7 +15,7 @@
*
*/
-#include "ErrorValue.h"
+#include "EXP_ErrorValue.h"
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
diff --git a/source/gameengine/Expressions/Expression.cpp b/source/gameengine/Expressions/intern/Expression.cpp
index 2428df977d3..6a98a15aa12 100644
--- a/source/gameengine/Expressions/Expression.cpp
+++ b/source/gameengine/Expressions/intern/Expression.cpp
@@ -15,8 +15,8 @@
*
*/
-#include "Expression.h"
-#include "ErrorValue.h"
+#include "EXP_Expression.h"
+#include "EXP_ErrorValue.h"
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
diff --git a/source/gameengine/Expressions/FloatValue.cpp b/source/gameengine/Expressions/intern/FloatValue.cpp
index 4d6f3f467eb..0f86a429d81 100644
--- a/source/gameengine/Expressions/FloatValue.cpp
+++ b/source/gameengine/Expressions/intern/FloatValue.cpp
@@ -15,12 +15,12 @@
*
*/
-#include "FloatValue.h"
-#include "IntValue.h"
-#include "StringValue.h"
-#include "BoolValue.h"
-#include "ErrorValue.h"
-#include "VoidValue.h"
+#include "EXP_FloatValue.h"
+#include "EXP_IntValue.h"
+#include "EXP_StringValue.h"
+#include "EXP_BoolValue.h"
+#include "EXP_ErrorValue.h"
+#include "EXP_VoidValue.h"
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
diff --git a/source/gameengine/Expressions/KX_HashedPtr.cpp b/source/gameengine/Expressions/intern/HashedPtr.cpp
index bd42892cc8d..005ac16b231 100644
--- a/source/gameengine/Expressions/KX_HashedPtr.cpp
+++ b/source/gameengine/Expressions/intern/HashedPtr.cpp
@@ -30,16 +30,22 @@
*/
-#include "KX_HashedPtr.h"
+#include "EXP_HashedPtr.h"
-unsigned int KX_Hash(void *inDWord)
+
+CHashedPtr::CHashedPtr(void* val) : m_valptr(val)
+{
+}
+
+
+unsigned int CHashedPtr::hash() const
{
#if defined(_WIN64) && !defined(FREE_WINDOWS64)
- unsigned __int64 key = (unsigned __int64)inDWord;
+ unsigned __int64 key = (unsigned __int64)m_valptr;
#elif defined(FREE_WINDOWS64)
- unsigned long long key = (unsigned long long)inDWord;
+ unsigned long long key = (unsigned long long)m_valptr;
#else
- unsigned long key = (unsigned long)inDWord;
+ unsigned long key = (unsigned long)m_valptr;
#endif
key += ~(key << 16);
@@ -51,15 +57,3 @@ unsigned int KX_Hash(void *inDWord)
return (unsigned int)(key & 0xffffffff);
}
-
-
-CHashedPtr::CHashedPtr(void* val) : m_valptr(val)
-{
-}
-
-
-
-unsigned int CHashedPtr::hash() const
-{
- return KX_Hash(m_valptr);
-}
diff --git a/source/gameengine/Expressions/IdentifierExpr.cpp b/source/gameengine/Expressions/intern/IdentifierExpr.cpp
index c9e053574cd..8fbbf41cd63 100644
--- a/source/gameengine/Expressions/IdentifierExpr.cpp
+++ b/source/gameengine/Expressions/intern/IdentifierExpr.cpp
@@ -30,7 +30,7 @@
*/
-#include "IdentifierExpr.h"
+#include "EXP_IdentifierExpr.h"
CIdentifierExpr::CIdentifierExpr(const STR_String& identifier,CValue* id_context)
:m_identifier(identifier)
diff --git a/source/gameengine/Expressions/IfExpr.cpp b/source/gameengine/Expressions/intern/IfExpr.cpp
index 152ca8704ce..b4e2fe7315b 100644
--- a/source/gameengine/Expressions/IfExpr.cpp
+++ b/source/gameengine/Expressions/intern/IfExpr.cpp
@@ -15,10 +15,10 @@
*
*/
-#include "IfExpr.h"
-#include "EmptyValue.h"
-#include "ErrorValue.h"
-#include "BoolValue.h"
+#include "EXP_IfExpr.h"
+#include "EXP_EmptyValue.h"
+#include "EXP_ErrorValue.h"
+#include "EXP_BoolValue.h"
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
diff --git a/source/gameengine/Expressions/InputParser.cpp b/source/gameengine/Expressions/intern/InputParser.cpp
index 4ba3585455b..e8cc7fba284 100644
--- a/source/gameengine/Expressions/InputParser.cpp
+++ b/source/gameengine/Expressions/intern/InputParser.cpp
@@ -19,23 +19,23 @@
#include "MT_assert.h"
-#include "Value.h"
-#include "InputParser.h"
-#include "ErrorValue.h"
-#include "IntValue.h"
-#include "StringValue.h"
-#include "FloatValue.h"
-#include "BoolValue.h"
-#include "EmptyValue.h"
-#include "ConstExpr.h"
-#include "Operator2Expr.h"
-#include "Operator1Expr.h"
-#include "IdentifierExpr.h"
+#include "EXP_Value.h"
+#include "EXP_InputParser.h"
+#include "EXP_ErrorValue.h"
+#include "EXP_IntValue.h"
+#include "EXP_StringValue.h"
+#include "EXP_FloatValue.h"
+#include "EXP_BoolValue.h"
+#include "EXP_EmptyValue.h"
+#include "EXP_ConstExpr.h"
+#include "EXP_Operator2Expr.h"
+#include "EXP_Operator1Expr.h"
+#include "EXP_IdentifierExpr.h"
// this is disable at the moment, I expected a memleak from it, but the error-cleanup was the reason
// well, looks we don't need it anyway, until maybe the Curved Surfaces are integrated into CSG
// cool things like (IF(LOD==1,CCurvedValue,IF(LOD==2,CCurvedValue2)) etc...
-#include "IfExpr.h"
+#include "EXP_IfExpr.h"
#if (defined(WIN32) || defined(WIN64)) && !defined(FREE_WINDOWS)
#define strcasecmp _stricmp
diff --git a/source/gameengine/Expressions/IntValue.cpp b/source/gameengine/Expressions/intern/IntValue.cpp
index 82d2e94dbb0..25aff5b32ab 100644
--- a/source/gameengine/Expressions/IntValue.cpp
+++ b/source/gameengine/Expressions/intern/IntValue.cpp
@@ -17,12 +17,12 @@
#include <stdio.h>
-#include "IntValue.h"
-#include "ErrorValue.h"
-#include "FloatValue.h"
-#include "BoolValue.h"
-#include "StringValue.h"
-#include "VoidValue.h"
+#include "EXP_IntValue.h"
+#include "EXP_ErrorValue.h"
+#include "EXP_FloatValue.h"
+#include "EXP_BoolValue.h"
+#include "EXP_StringValue.h"
+#include "EXP_VoidValue.h"
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
diff --git a/source/gameengine/Expressions/ListValue.cpp b/source/gameengine/Expressions/intern/ListValue.cpp
index 75e3b490505..557ce7be300 100644
--- a/source/gameengine/Expressions/ListValue.cpp
+++ b/source/gameengine/Expressions/intern/ListValue.cpp
@@ -19,11 +19,11 @@
#include <stdio.h>
-#include "ListValue.h"
-#include "StringValue.h"
-#include "VoidValue.h"
+#include "EXP_ListValue.h"
+#include "EXP_StringValue.h"
+#include "EXP_VoidValue.h"
#include <algorithm>
-#include "BoolValue.h"
+#include "EXP_BoolValue.h"
#include "BLI_sys_types.h" /* for intptr_t support */
@@ -432,7 +432,7 @@ static PyObject *listvalue_buffer_concat(PyObject *self, PyObject *other)
for (i=0;i<numitems;i++)
{
- listitemval = listval->ConvertPythonToValue(PyList_GetItem(other,i), true, "cList + pyList: CListValue, ");
+ listitemval = listval->ConvertPythonToValue(PyList_GET_ITEM(other, i), true, "cList + pyList: CListValue, ");
if (listitemval) {
listval_new->SetValue(i+numitems_orig, listitemval);
@@ -583,7 +583,8 @@ PyObject *CListValue::Pyappend(PyObject *value)
return NULL;
if (!BGE_PROXY_PYOWNS(m_proxy)) {
- PyErr_SetString(PyExc_TypeError, "CList.append(i): this CValueList is used internally for the game engine and can't be modified");
+ PyErr_SetString(PyExc_TypeError,
+ "CList.append(i): internal values can't be modified");
return NULL;
}
@@ -594,6 +595,12 @@ PyObject *CListValue::Pyappend(PyObject *value)
PyObject *CListValue::Pyreverse()
{
+ if (!BGE_PROXY_PYOWNS(m_proxy)) {
+ PyErr_SetString(PyExc_TypeError,
+ "CList.reverse(): internal values can't be modified");
+ return NULL;
+ }
+
std::reverse(m_pValueArray.begin(),m_pValueArray.end());
Py_RETURN_NONE;
}
diff --git a/source/gameengine/Expressions/Operator1Expr.cpp b/source/gameengine/Expressions/intern/Operator1Expr.cpp
index b985f76825d..add0376f487 100644
--- a/source/gameengine/Expressions/Operator1Expr.cpp
+++ b/source/gameengine/Expressions/intern/Operator1Expr.cpp
@@ -15,8 +15,8 @@
*
*/
-#include "Operator1Expr.h"
-#include "EmptyValue.h"
+#include "EXP_Operator1Expr.h"
+#include "EXP_EmptyValue.h"
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
diff --git a/source/gameengine/Expressions/Operator2Expr.cpp b/source/gameengine/Expressions/intern/Operator2Expr.cpp
index b03d00e7f77..0a7f30b8cc8 100644
--- a/source/gameengine/Expressions/Operator2Expr.cpp
+++ b/source/gameengine/Expressions/intern/Operator2Expr.cpp
@@ -19,9 +19,9 @@
// have to do the trick
// when expression is cached, there will be a call to UpdateCalc() instead of Calc()
-#include "Operator2Expr.h"
-#include "StringValue.h"
-#include "VoidValue.h"
+#include "EXP_Operator2Expr.h"
+#include "EXP_StringValue.h"
+#include "EXP_VoidValue.h"
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
diff --git a/source/gameengine/Expressions/PyObjectPlus.cpp b/source/gameengine/Expressions/intern/PyObjectPlus.cpp
index c025d439fc0..de45bee76a7 100644
--- a/source/gameengine/Expressions/PyObjectPlus.cpp
+++ b/source/gameengine/Expressions/intern/PyObjectPlus.cpp
@@ -47,7 +47,7 @@
#include <stdlib.h>
#include <stddef.h>
-#include "PyObjectPlus.h"
+#include "EXP_PyObjectPlus.h"
#include "STR_String.h"
#include "MT_Vector3.h"
#include "MEM_guardedalloc.h"
@@ -80,7 +80,7 @@ void PyObjectPlus::ProcessReplica()
}
/* Sometimes we might want to manually invalidate a BGE type even if
- * it hasnt been released by the BGE, say for example when an object
+ * it hasn't been released by the BGE, say for example when an object
* is removed from a scene, accessing it may cause problems.
*
* In this case the current proxy is made invalid, disowned,
@@ -148,12 +148,18 @@ PyObject *PyObjectPlus::py_base_repr(PyObject *self) // This should be the ent
PyObject *PyObjectPlus::py_base_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
PyTypeObject *base_type;
- PyObjectPlus_Proxy *base = NULL;
- if (!PyArg_ParseTuple(args, "O:Base PyObjectPlus", &base))
+ /* one or more args is needed */
+ if (!PyTuple_GET_SIZE(args)) {
+ PyErr_SetString(PyExc_TypeError,
+ "Expected at least one argument");
return NULL;
+ }
+
+ PyObjectPlus_Proxy *base = (PyObjectPlus_Proxy *)PyTuple_GET_ITEM(args, 0);
- /* the 'base' PyObject may be subclassed (multiple times even)
+ /**
+ * the 'base' PyObject may be subclassed (multiple times even)
* we need to find the first C++ defined class to check 'type'
* is a subclass of the base arguments type.
*
@@ -162,12 +168,13 @@ PyObject *PyObjectPlus::py_base_new(PyTypeObject *type, PyObject *args, PyObject
* eg.
*
* # CustomOb is called 'type' in this C code
+ * \code{.py}
* class CustomOb(GameTypes.KX_GameObject):
* pass
*
* # this calls py_base_new(...), the type of 'CustomOb' is checked to be a subclass of the 'cont.owner' type
* ob = CustomOb(cont.owner)
- *
+ * \endcode
* */
base_type= Py_TYPE(base);
while (base_type && !BGE_PROXY_CHECK_TYPE(base_type))
@@ -418,7 +425,7 @@ PyObject *PyObjectPlus::py_get_attrdef(PyObject *self_py, const PyAttributeDef *
return NULL;
}
#ifdef USE_MATHUTILS
- return Vector_CreatePyObject(val, attrdef->m_imax, Py_NEW, NULL);
+ return Vector_CreatePyObject(val, attrdef->m_imax, NULL);
#else
PyObject *resultlist = PyList_New(attrdef->m_imax);
for (unsigned int i=0; i<attrdef->m_imax; i++)
@@ -435,7 +442,7 @@ PyObject *PyObjectPlus::py_get_attrdef(PyObject *self_py, const PyAttributeDef *
return NULL;
}
#ifdef USE_MATHUTILS
- return Matrix_CreatePyObject(val, attrdef->m_imin, attrdef->m_imax, Py_WRAP, NULL);
+ return Matrix_CreatePyObject_wrap(val, attrdef->m_imin, attrdef->m_imax, NULL);
#else
PyObject *collist = PyList_New(attrdef->m_imin);
for (unsigned int i=0; i<attrdef->m_imin; i++)
@@ -458,7 +465,7 @@ PyObject *PyObjectPlus::py_get_attrdef(PyObject *self_py, const PyAttributeDef *
#ifdef USE_MATHUTILS
float fval[3];
val->getValue(fval);
- return Vector_CreatePyObject(fval, 3, Py_NEW, NULL);
+ return Vector_CreatePyObject(fval, 3, NULL);
#else
PyObject *resultlist = PyList_New(3);
for (unsigned int i=0; i<3; i++)
diff --git a/source/gameengine/Expressions/intern/PythonCallBack.cpp b/source/gameengine/Expressions/intern/PythonCallBack.cpp
new file mode 100644
index 00000000000..3fb84569eca
--- /dev/null
+++ b/source/gameengine/Expressions/intern/PythonCallBack.cpp
@@ -0,0 +1,119 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributor(s): Porteries Tristan.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file gameengine/Expressions/intern/PythonCallBack.cpp
+ * \ingroup expressions
+ */
+
+#include "EXP_PythonCallBack.h"
+#include <iostream>
+#include <stdarg.h>
+
+#include "BLI_alloca.h"
+
+/** Check if a python value is a function and have the correct number of arguments.
+ * \param value The python value to check.
+ * \param minargcount The minimum of arguments possible.
+ * \param maxargcount The maximum of arguments possible.
+ * \param r_argcount The number of argument of this function, this variable will be
+ * changed in the function.
+ */
+static PyObject *CheckPythonFunction(PyObject *value, unsigned int minargcount, unsigned int maxargcount, unsigned int &r_argcount)
+{
+ if (PyMethod_Check(value)) {
+ PyCodeObject *code = ((PyCodeObject *)PyFunction_GET_CODE(PyMethod_GET_FUNCTION(value)));
+ // *args support
+ r_argcount = (code->co_flags & CO_VARARGS) ? maxargcount : (code->co_argcount - 1);
+ }
+ else if (PyFunction_Check(value)) {
+ PyCodeObject *code = ((PyCodeObject *)PyFunction_GET_CODE(value));
+ // *args support
+ r_argcount = (code->co_flags & CO_VARARGS) ? maxargcount : code->co_argcount;
+ }
+ else { // is not a methode or a function
+ PyErr_Format(PyExc_TypeError, "items must be functions or methodes, not %s",
+ Py_TYPE(value)->tp_name);
+ return NULL;
+ }
+
+ if (r_argcount < minargcount || r_argcount > maxargcount) {
+ // wrong number of arguments
+ PyErr_Format(PyExc_TypeError, "methode or function (%s) has invalid number of arguments (%i) must be between %i and %i",
+ Py_TYPE(value)->tp_name, r_argcount, minargcount, maxargcount);
+ return NULL;
+ }
+
+ return value;
+}
+
+/** Create a python tuple to call a python function
+ * \param argcount The lenght of the tuple.
+ * \param arglist The fully list of python arguments [size >= argcount].
+ */
+static PyObject *CreatePythonTuple(unsigned int argcount, PyObject **arglist)
+{
+ PyObject *tuple = PyTuple_New(argcount);
+
+ for (unsigned int i = 0; i < argcount; ++i) {
+ PyObject *item = arglist[i];
+ // increment reference and copy it in a new tuple
+ Py_INCREF(item);
+ PyTuple_SET_ITEM(tuple, i, item);
+ }
+
+ return tuple;
+}
+
+void RunPythonCallBackList(PyObject *functionlist, PyObject **arglist, unsigned int minargcount, unsigned int maxargcount)
+{
+ unsigned int size = PyList_Size(functionlist);
+ PyObject **argTuples = (PyObject **)BLI_array_alloca(argTuples, maxargcount - minargcount + 1);
+ memset(argTuples, 0, sizeof(PyObject *) * (maxargcount - minargcount + 1));
+
+ for (unsigned int i = 0; i < size; ++i) {
+ unsigned int funcargcount = 0;
+
+ PyObject *item = PyList_GET_ITEM(functionlist, i);
+ PyObject *func = CheckPythonFunction(item, minargcount, maxargcount, funcargcount);
+ if (!func) { // this item fails the check
+ PyErr_Print();
+ PyErr_Clear();
+ continue;
+ }
+
+ // get correct argument tuple.
+ PyObject *tuple = argTuples[funcargcount - minargcount];
+ if (!tuple)
+ argTuples[funcargcount - minargcount] = tuple = CreatePythonTuple(funcargcount, arglist);
+
+ PyObject *ret = PyObject_Call(func, tuple, NULL);
+ if (!ret) { // if ret is NULL this seems that the function doesn't work !
+ PyErr_Print();
+ PyErr_Clear();
+ }
+ else
+ Py_DECREF(ret);
+ }
+
+ for (unsigned int i = 0; i <= (maxargcount - minargcount); ++i)
+ Py_XDECREF(argTuples[i]);
+}
diff --git a/source/gameengine/Expressions/StringValue.cpp b/source/gameengine/Expressions/intern/StringValue.cpp
index 098949c9d7b..ddf61dc441c 100644
--- a/source/gameengine/Expressions/StringValue.cpp
+++ b/source/gameengine/Expressions/intern/StringValue.cpp
@@ -15,10 +15,10 @@
*
*/
-#include "StringValue.h"
-#include "BoolValue.h"
-#include "ErrorValue.h"
-#include "VoidValue.h"
+#include "EXP_StringValue.h"
+#include "EXP_BoolValue.h"
+#include "EXP_ErrorValue.h"
+#include "EXP_VoidValue.h"
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
diff --git a/source/gameengine/Expressions/Value.cpp b/source/gameengine/Expressions/intern/Value.cpp
index bdef2dbd5b0..f8796a76e76 100644
--- a/source/gameengine/Expressions/Value.cpp
+++ b/source/gameengine/Expressions/intern/Value.cpp
@@ -17,15 +17,15 @@
* purpose. It is provided "as is" without express or implied warranty.
*
*/
-#include "Value.h"
-#include "BoolValue.h"
-#include "FloatValue.h"
-#include "IntValue.h"
-#include "VectorValue.h"
-#include "VoidValue.h"
-#include "StringValue.h"
-#include "ErrorValue.h"
-#include "ListValue.h"
+#include "EXP_Value.h"
+#include "EXP_BoolValue.h"
+#include "EXP_FloatValue.h"
+#include "EXP_IntValue.h"
+#include "EXP_VectorValue.h"
+#include "EXP_VoidValue.h"
+#include "EXP_StringValue.h"
+#include "EXP_ErrorValue.h"
+#include "EXP_ListValue.h"
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
@@ -568,7 +568,7 @@ CValue *CValue::ConvertPythonToValue(PyObject *pyobj, const bool do_type_excepti
Py_ssize_t numitems = PyList_GET_SIZE(pyobj);
for (i=0;i<numitems;i++)
{
- PyObject *listitem = PyList_GetItem(pyobj,i); /* borrowed ref */
+ PyObject *listitem = PyList_GET_ITEM(pyobj,i); /* borrowed ref */
CValue* listitemval = ConvertPythonToValue(listitem, error_prefix);
if (listitemval)
{
diff --git a/source/gameengine/Expressions/VectorValue.cpp b/source/gameengine/Expressions/intern/VectorValue.cpp
index 6931ba2aa76..a3d44116317 100644
--- a/source/gameengine/Expressions/VectorValue.cpp
+++ b/source/gameengine/Expressions/intern/VectorValue.cpp
@@ -19,12 +19,12 @@
# pragma warning (disable:4786)
#endif
-#include "Value.h"
-#include "VectorValue.h"
-#include "ErrorValue.h"
+#include "EXP_Value.h"
+#include "EXP_VectorValue.h"
+#include "EXP_ErrorValue.h"
//#include "MatrixValue.h"
-#include "VoidValue.h"
-#include "StringValue.h"
+#include "EXP_VoidValue.h"
+#include "EXP_StringValue.h"
//#include "FactoryManager.h"
diff --git a/source/gameengine/GameLogic/Joystick/SCA_Joystick.cpp b/source/gameengine/GameLogic/Joystick/SCA_Joystick.cpp
index 6e379c91d0c..b03570e3c28 100644
--- a/source/gameengine/GameLogic/Joystick/SCA_Joystick.cpp
+++ b/source/gameengine/GameLogic/Joystick/SCA_Joystick.cpp
@@ -41,6 +41,10 @@
#include "BLI_path_util.h"
+#ifdef WITH_SDL
+# define SDL_CHECK(x) ((x) != (void *)0)
+#endif
+
SCA_Joystick::SCA_Joystick(short int index)
:
m_joyindex(index),
@@ -82,6 +86,9 @@ SCA_Joystick *SCA_Joystick::GetInstance( short int joyindex )
#ifndef WITH_SDL
return NULL;
#else /* WITH_SDL */
+ if (!SDL_CHECK(SDL_InitSubSystem)) {
+ return NULL;
+ }
if (joyindex < 0 || joyindex >= JOYINDEX_MAX) {
JOYSTICK_ECHO("Error-invalid joystick index: " << joyindex);
return NULL;
@@ -104,7 +111,11 @@ SCA_Joystick *SCA_Joystick::GetInstance( short int joyindex )
char *videodriver = getenv("SDL_VIDEODRIVER");
BLI_setenv("SDL_VIDEODRIVER", "dummy");
+#if SDL_VERSION_ATLEAST(2, 0, 0)
+ int success = (SDL_InitSubSystem(SDL_INIT_JOYSTICK) != -1 );
+#else
int success = (SDL_InitSubSystem(SDL_INIT_JOYSTICK | SDL_INIT_VIDEO) != -1 );
+#endif
BLI_setenv("SDL_VIDEODRIVER", videodriver);
# endif
@@ -116,7 +127,7 @@ SCA_Joystick *SCA_Joystick::GetInstance( short int joyindex )
m_joynum = SDL_NumJoysticks();
- for (i=0; i<JOYINDEX_MAX; i++) {
+ for (i = 0; i < m_joynum; i++) {
m_instance[i] = new SCA_Joystick(i);
m_instance[i]->CreateJoystickDevice();
}
@@ -135,8 +146,10 @@ void SCA_Joystick::ReleaseInstance()
if (--m_refCount == 0)
{
#ifdef WITH_SDL
- int i;
- for (i=0; i<JOYINDEX_MAX; i++) {
+ if (!SDL_CHECK(SDL_QuitSubSystem)) {
+ return;
+ }
+ for (int i = 0; i < m_joynum; i++) {
if (m_instance[i]) {
m_instance[i]->DestroyJoystickDevice();
delete m_instance[i];
@@ -147,11 +160,11 @@ void SCA_Joystick::ReleaseInstance()
/* The video subsystem is required for joystick input to work. However,
* when GHOST is running under SDL, video is freed elsewhere.
* Do this once only. */
-# ifdef WITH_GHOST_SDL
+#if SDL_VERSION_ATLEAST(2, 0, 0)
SDL_QuitSubSystem(SDL_INIT_JOYSTICK);
-# else
+#else
SDL_QuitSubSystem(SDL_INIT_JOYSTICK | SDL_INIT_VIDEO);
-# endif
+#endif
#endif /* WITH_SDL */
}
}
@@ -191,6 +204,9 @@ bool SCA_Joystick::aAxisIsPositive(int axis_single)
bool SCA_Joystick::aAnyButtonPressIsPositive(void)
{
#ifdef WITH_SDL
+ if (!SDL_CHECK(SDL_JoystickGetButton)) {
+ return false;
+ }
/* this is needed for the "all events" option
* so we know if there are no buttons pressed */
for (int i=0; i<m_buttonmax; i++)
@@ -206,7 +222,7 @@ bool SCA_Joystick::aButtonPressIsPositive(int button)
return false;
#else
bool result;
- SDL_JoystickGetButton(m_private->m_joystick, button)? result = true:result = false;
+ result = SDL_CHECK(SDL_JoystickGetButton) && SDL_JoystickGetButton(m_private->m_joystick, button);
return result;
#endif
}
@@ -218,7 +234,7 @@ bool SCA_Joystick::aButtonReleaseIsPositive(int button)
return false;
#else
bool result;
- SDL_JoystickGetButton(m_private->m_joystick, button)? result = false : result = true;
+ result = !(SDL_CHECK(SDL_JoystickGetButton) && SDL_JoystickGetButton(m_private->m_joystick, button));
return result;
#endif
}
@@ -253,7 +269,7 @@ bool SCA_Joystick::CreateJoystickDevice(void)
m_axismax = m_buttonmax = m_hatmax = 0;
return false;
#else /* WITH_SDL */
- if (m_isinit == false) {
+ if (m_isinit == false && SDL_CHECK(SDL_JoystickOpen)) {
if (m_joyindex>=m_joynum) {
/* don't print a message, because this is done anyway */
//JOYSTICK_ECHO("Joystick-Error: " << SDL_NumJoysticks() << " avaiable joystick(s)");
@@ -293,9 +309,9 @@ 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_CHECK(SDL_JoystickGetAttached) && SDL_JoystickGetAttached(m_private->m_joystick))
#else
- if (SDL_JoystickOpened(m_joyindex))
+ if (SDL_CHECK(SDL_JoystickOpened) && SDL_JoystickOpened(m_joyindex))
#endif
{
JOYSTICK_ECHO("Closing-joystick " << m_joyindex);
@@ -309,13 +325,16 @@ void SCA_Joystick::DestroyJoystickDevice(void)
int SCA_Joystick::Connected(void)
{
#ifdef WITH_SDL
- if (m_isinit
+ if (m_isinit &&
#if SDL_VERSION_ATLEAST(2, 0, 0)
- && SDL_JoystickGetAttached(m_private->m_joystick))
+ SDL_CHECK(SDL_JoystickGetAttached) && SDL_JoystickGetAttached(m_private->m_joystick)
#else
- && SDL_JoystickOpened(m_joyindex))
+ SDL_CHECK(SDL_JoystickOpened) && SDL_JoystickOpened(m_joyindex)
#endif
+ )
+ {
return 1;
+ }
#endif
return 0;
}
@@ -353,9 +372,9 @@ const char *SCA_Joystick::GetName()
{
#ifdef WITH_SDL
#if SDL_VERSION_ATLEAST(2, 0, 0)
- return SDL_JoystickName(m_private->m_joystick);
+ return (SDL_CHECK(SDL_JoystickName)) ? SDL_JoystickName(m_private->m_joystick) : "";
#else
- return SDL_JoystickName(m_joyindex);
+ return (SDL_CHECK(SDL_JoystickName)) ? SDL_JoystickName(m_joyindex) : "";
#endif
#else /* WITH_SDL */
return "";
diff --git a/source/gameengine/GameLogic/Joystick/SCA_JoystickEvents.cpp b/source/gameengine/GameLogic/Joystick/SCA_JoystickEvents.cpp
index 2911b3b1a14..0033c137eb6 100644
--- a/source/gameengine/GameLogic/Joystick/SCA_JoystickEvents.cpp
+++ b/source/gameengine/GameLogic/Joystick/SCA_JoystickEvents.cpp
@@ -36,6 +36,9 @@
#include "SCA_Joystick.h"
#include "SCA_JoystickPrivate.h"
+#ifdef _MSC_VER
+# include <cstdio> /* printf */
+#endif
#ifdef WITH_SDL
void SCA_Joystick::OnAxisMotion(SDL_Event* sdl_event)
@@ -82,7 +85,11 @@ void SCA_Joystick::OnNothing(SDL_Event* sdl_event)
void SCA_Joystick::HandleEvents(void)
{
SDL_Event sdl_event;
-
+
+ if (SDL_PollEvent == (void*)0) {
+ return;
+ }
+
int i;
for (i=0; i<m_joynum; i++) { /* could use JOYINDEX_MAX but no reason to */
if (SCA_Joystick::m_instance[i])
@@ -117,6 +124,12 @@ void SCA_Joystick::HandleEvents(void)
SCA_Joystick::m_instance[sdl_event.jball.which]->OnBallMotion(&sdl_event);
break;
#endif
+#if SDL_VERSION_ATLEAST(2, 0, 0)
+ case SDL_JOYDEVICEADDED:
+ case SDL_JOYDEVICEREMOVED:
+ /* pass */
+ break;
+#endif
default:
printf("SCA_Joystick::HandleEvents, Unknown SDL event (%d), this should not happen\n", sdl_event.type);
break;
diff --git a/source/gameengine/GameLogic/SCA_ANDController.cpp b/source/gameengine/GameLogic/SCA_ANDController.cpp
index 3c60f2b8847..2cb7406779c 100644
--- a/source/gameengine/GameLogic/SCA_ANDController.cpp
+++ b/source/gameengine/GameLogic/SCA_ANDController.cpp
@@ -36,7 +36,7 @@
#include "SCA_ANDController.h"
#include "SCA_ISensor.h"
#include "SCA_LogicManager.h"
-#include "BoolValue.h"
+#include "EXP_BoolValue.h"
/* ------------------------------------------------------------------------- */
/* Native functions */
diff --git a/source/gameengine/GameLogic/SCA_ExpressionController.cpp b/source/gameengine/GameLogic/SCA_ExpressionController.cpp
index d1c7b58a52c..ef058e215d6 100644
--- a/source/gameengine/GameLogic/SCA_ExpressionController.cpp
+++ b/source/gameengine/GameLogic/SCA_ExpressionController.cpp
@@ -36,8 +36,8 @@
#include "SCA_ExpressionController.h"
#include "SCA_ISensor.h"
#include "SCA_LogicManager.h"
-#include "BoolValue.h"
-#include "InputParser.h"
+#include "EXP_BoolValue.h"
+#include "EXP_InputParser.h"
#include "MT_Transform.h" // for fuzzyZero
#include <stdio.h>
diff --git a/source/gameengine/GameLogic/SCA_IController.cpp b/source/gameengine/GameLogic/SCA_IController.cpp
index f922e617367..2bb04fe7be0 100644
--- a/source/gameengine/GameLogic/SCA_IController.cpp
+++ b/source/gameengine/GameLogic/SCA_IController.cpp
@@ -36,7 +36,7 @@
#include "SCA_LogicManager.h"
#include "SCA_IActuator.h"
#include "SCA_ISensor.h"
-#include "PyObjectPlus.h"
+#include "EXP_PyObjectPlus.h"
#include "../Ketsji/KX_PythonSeq.h" /* not nice, only need for KX_PythonSeq_CreatePyObject */
#include <stdio.h>
diff --git a/source/gameengine/GameLogic/SCA_IController.h b/source/gameengine/GameLogic/SCA_IController.h
index 1bc6b60bf1e..4ec872c2316 100644
--- a/source/gameengine/GameLogic/SCA_IController.h
+++ b/source/gameengine/GameLogic/SCA_IController.h
@@ -33,7 +33,7 @@
#define __SCA_ICONTROLLER_H__
#include "SCA_ILogicBrick.h"
-#include "PyObjectPlus.h"
+#include "EXP_PyObjectPlus.h"
/**
* Use of SG_DList element: none
diff --git a/source/gameengine/GameLogic/SCA_IInputDevice.h b/source/gameengine/GameLogic/SCA_IInputDevice.h
index 23346c29601..d4cd66fb564 100644
--- a/source/gameengine/GameLogic/SCA_IInputDevice.h
+++ b/source/gameengine/GameLogic/SCA_IInputDevice.h
@@ -25,7 +25,7 @@
* ***** END GPL LICENSE BLOCK *****
*/
-/** \file SCA_IController.h
+/** \file SCA_IInputDevice.h
* \ingroup gamelogic
* \brief Interface for input devices. The defines for keyboard/system/mouse events
* here are for internal use in the KX module.
diff --git a/source/gameengine/GameLogic/SCA_ILogicBrick.cpp b/source/gameengine/GameLogic/SCA_ILogicBrick.cpp
index 34fa1c98a73..72a0b392447 100644
--- a/source/gameengine/GameLogic/SCA_ILogicBrick.cpp
+++ b/source/gameengine/GameLogic/SCA_ILogicBrick.cpp
@@ -33,7 +33,7 @@
#include <stddef.h>
#include "SCA_ILogicBrick.h"
-#include "PyObjectPlus.h"
+#include "EXP_PyObjectPlus.h"
SCA_LogicManager* SCA_ILogicBrick::m_sCurrentLogicManager = NULL;
diff --git a/source/gameengine/GameLogic/SCA_ILogicBrick.h b/source/gameengine/GameLogic/SCA_ILogicBrick.h
index dc0aa4ce331..a3725789227 100644
--- a/source/gameengine/GameLogic/SCA_ILogicBrick.h
+++ b/source/gameengine/GameLogic/SCA_ILogicBrick.h
@@ -32,9 +32,9 @@
#ifndef __SCA_ILOGICBRICK_H__
#define __SCA_ILOGICBRICK_H__
-#include "Value.h"
+#include "EXP_Value.h"
#include "SCA_IObject.h"
-#include "BoolValue.h"
+#include "EXP_BoolValue.h"
#include "CTR_Map.h"
#include "CTR_HashedPtr.h"
diff --git a/source/gameengine/GameLogic/SCA_IObject.cpp b/source/gameengine/GameLogic/SCA_IObject.cpp
index ab9e2781001..526e695e792 100644
--- a/source/gameengine/GameLogic/SCA_IObject.cpp
+++ b/source/gameengine/GameLogic/SCA_IObject.cpp
@@ -37,7 +37,7 @@
#include "SCA_IController.h"
#include "SCA_IActuator.h"
#include "MT_Point3.h"
-#include "ListValue.h"
+#include "EXP_ListValue.h"
MT_Point3 SCA_IObject::m_sDummy=MT_Point3(0,0,0);
SG_QList SCA_IObject::m_activeBookmarkedControllers;
diff --git a/source/gameengine/GameLogic/SCA_IObject.h b/source/gameengine/GameLogic/SCA_IObject.h
index 365e2b0c853..29a21fd8708 100644
--- a/source/gameengine/GameLogic/SCA_IObject.h
+++ b/source/gameengine/GameLogic/SCA_IObject.h
@@ -24,7 +24,7 @@
*
* ***** END GPL LICENSE BLOCK *****
*/
-/** \file SCA_IController.h
+/** \file SCA_IObject.h
* \ingroup gamelogic
* \brief An abstract object that has some logic, python scripting and
* reference counting Note: transformation stuff has been moved to
@@ -34,7 +34,7 @@
#ifndef __SCA_IOBJECT_H__
#define __SCA_IOBJECT_H__
-#include "Value.h"
+#include "EXP_Value.h"
#include <vector>
class SCA_IObject;
@@ -221,6 +221,7 @@ public:
OBJ_ARMATURE=0,
OBJ_CAMERA=1,
OBJ_LIGHT=2,
+ OBJ_TEXT=3
} ObjectTypes;
};
diff --git a/source/gameengine/GameLogic/SCA_IScene.cpp b/source/gameengine/GameLogic/SCA_IScene.cpp
index 3ca4b6607b3..a4c905096d7 100644
--- a/source/gameengine/GameLogic/SCA_IScene.cpp
+++ b/source/gameengine/GameLogic/SCA_IScene.cpp
@@ -31,7 +31,7 @@
#include "SCA_IScene.h"
-#include "Value.h"
+#include "EXP_Value.h"
SCA_DebugProp::SCA_DebugProp(): m_obj(NULL)
{
@@ -114,7 +114,7 @@ void SCA_IScene::RemoveDebugProperty(class CValue *gameobj,
const STR_String &name)
{
vector<SCA_DebugProp*>::iterator it = m_debugList.begin();
- while(it != m_debugList.end()) {
+ while (it != m_debugList.end()) {
STR_String debugname = (*it)->m_name;
CValue *debugobj = (*it)->m_obj;
diff --git a/source/gameengine/GameLogic/SCA_ISensor.cpp b/source/gameengine/GameLogic/SCA_ISensor.cpp
index 1cb17af8325..66dd69f93c4 100644
--- a/source/gameengine/GameLogic/SCA_ISensor.cpp
+++ b/source/gameengine/GameLogic/SCA_ISensor.cpp
@@ -67,7 +67,7 @@ SCA_ISensor::SCA_ISensor(SCA_IObject* gameobj,
m_neg_ticks = 0;
m_pos_pulsemode = false;
m_neg_pulsemode = false;
- m_pulse_frequency = 0;
+ m_skipped_ticks = 0;
m_state = false;
m_prev_state = false;
@@ -102,11 +102,11 @@ bool SCA_ISensor::IsPositiveTrigger()
void SCA_ISensor::SetPulseMode(bool posmode,
bool negmode,
- int freq)
+ int skippedticks)
{
m_pos_pulsemode = posmode;
m_neg_pulsemode = negmode;
- m_pulse_frequency = freq;
+ m_skipped_ticks = skippedticks;
}
void SCA_ISensor::SetInvert(bool inv)
@@ -263,7 +263,7 @@ void SCA_ISensor::Activate(class SCA_LogicManager* logicmgr)
* not set :( */
if (m_pos_pulsemode) {
m_pos_ticks++;
- if (m_pos_ticks > m_pulse_frequency) {
+ if (m_pos_ticks > m_skipped_ticks) {
if ( m_state )
{
ActivateControllers(logicmgr);
@@ -276,7 +276,7 @@ void SCA_ISensor::Activate(class SCA_LogicManager* logicmgr)
if (m_neg_pulsemode && !m_tap)
{
m_neg_ticks++;
- if (m_neg_ticks > m_pulse_frequency) {
+ if (m_neg_ticks > m_skipped_ticks) {
if (!m_state )
{
ActivateControllers(logicmgr);
@@ -367,7 +367,7 @@ PyMethodDef SCA_ISensor::Methods[] = {
PyAttributeDef SCA_ISensor::Attributes[] = {
KX_PYATTRIBUTE_BOOL_RW("usePosPulseMode",SCA_ISensor,m_pos_pulsemode),
KX_PYATTRIBUTE_BOOL_RW("useNegPulseMode",SCA_ISensor,m_neg_pulsemode),
- KX_PYATTRIBUTE_INT_RW("frequency",0,100000,true,SCA_ISensor,m_pulse_frequency),
+ KX_PYATTRIBUTE_INT_RW("skippedTicks",0,100000,true,SCA_ISensor,m_skipped_ticks),
KX_PYATTRIBUTE_BOOL_RW("invert",SCA_ISensor,m_invert),
KX_PYATTRIBUTE_BOOL_RW_CHECK("level",SCA_ISensor,m_level,pyattr_check_level),
KX_PYATTRIBUTE_BOOL_RW_CHECK("tap",SCA_ISensor,m_tap,pyattr_check_tap),
@@ -376,6 +376,7 @@ PyAttributeDef SCA_ISensor::Attributes[] = {
KX_PYATTRIBUTE_RO_FUNCTION("status", SCA_ISensor, pyattr_get_status),
KX_PYATTRIBUTE_RO_FUNCTION("pos_ticks", SCA_ISensor, pyattr_get_posTicks),
KX_PYATTRIBUTE_RO_FUNCTION("neg_ticks", SCA_ISensor, pyattr_get_negTicks),
+ KX_PYATTRIBUTE_RW_FUNCTION("frequency", SCA_ISensor, pyattr_get_frequency, pyattr_set_frequency),
{ NULL } //Sentinel
};
@@ -444,6 +445,27 @@ int SCA_ISensor::pyattr_check_tap(void *self_v, const KX_PYATTRIBUTE_DEF *attrde
self->m_level = false;
return 0;
}
+
+PyObject *SCA_ISensor::pyattr_get_frequency(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+{
+ SCA_ISensor *self = static_cast<SCA_ISensor*>(self_v);
+ ShowDeprecationWarning("SCA_ISensor.frequency", "SCA_ISensor.skippedTicks");
+ return PyLong_FromLong(self->m_skipped_ticks);
+}
+
+int SCA_ISensor::pyattr_set_frequency(void *self_v, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
+{
+ SCA_ISensor *self = static_cast<SCA_ISensor*>(self_v);
+ ShowDeprecationWarning("SCA_ISensor.frequency", "SCA_ISensor.skippedTicks");
+ if (PyLong_Check(value)) {
+ self->m_skipped_ticks = PyLong_AsLong(value);
+ return PY_SET_ATTR_SUCCESS;
+ }
+ else {
+ PyErr_SetString(PyExc_TypeError, "sensor.frequency = int: Sensor, expected an integer");
+ return PY_SET_ATTR_FAIL;
+ }
+}
#endif // WITH_PYTHON
/* eof */
diff --git a/source/gameengine/GameLogic/SCA_ISensor.h b/source/gameengine/GameLogic/SCA_ISensor.h
index 091aa675741..1e82f3ab11f 100644
--- a/source/gameengine/GameLogic/SCA_ISensor.h
+++ b/source/gameengine/GameLogic/SCA_ISensor.h
@@ -25,7 +25,7 @@
* ***** END GPL LICENSE BLOCK *****
*/
-/** \file SCA_IController.h
+/** \file SCA_ISensor.h
* \ingroup gamelogic
* \brief Interface Class for all logic Sensors. Implements
* pulsemode and pulsefrequency, and event suppression.
@@ -57,8 +57,8 @@ protected:
/** Pulse negative pulses? */
bool m_neg_pulsemode;
- /** Repeat frequency in pulse mode. */
- int m_pulse_frequency;
+ /** Number of skipped ticks between two active pulses. */
+ int m_skipped_ticks;
/** Number of ticks since the last positive pulse. */
int m_pos_ticks;
@@ -125,7 +125,7 @@ public:
*/
void SetPulseMode(bool posmode,
bool negmode,
- int freq);
+ int skippedticks);
/** Set inversion of pulses on or off. */
void SetInvert(bool inv);
@@ -201,6 +201,8 @@ public:
static PyObject* pyattr_get_status(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
static PyObject* pyattr_get_posTicks(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
static PyObject* pyattr_get_negTicks(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+ static PyObject* pyattr_get_frequency(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+ static int pyattr_set_frequency(void *self_v, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
static int pyattr_check_level(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
static int pyattr_check_tap(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
diff --git a/source/gameengine/GameLogic/SCA_JoystickSensor.cpp b/source/gameengine/GameLogic/SCA_JoystickSensor.cpp
index 3cae3bcf160..56df9692e72 100644
--- a/source/gameengine/GameLogic/SCA_JoystickSensor.cpp
+++ b/source/gameengine/GameLogic/SCA_JoystickSensor.cpp
@@ -35,7 +35,7 @@
#include "SCA_EventManager.h"
#include "SCA_LogicManager.h"
-#include "PyObjectPlus.h"
+#include "EXP_PyObjectPlus.h"
#include <stdio.h>
#include <stddef.h>
@@ -351,8 +351,8 @@ PyObject *SCA_JoystickSensor::pyattr_get_axis_values(void *self_v, const KX_PYAT
SCA_JoystickSensor* self = static_cast<SCA_JoystickSensor*>(self_v);
SCA_Joystick *joy = ((SCA_JoystickManager *)self->m_eventmgr)->GetJoystickDevice(self->m_joyindex);
- int axis_index= joy->GetNumberOfAxes();
- PyObject *list= PyList_New(axis_index);
+ int axis_index = (joy ? joy->GetNumberOfAxes() : 0);
+ PyObject *list = PyList_New(axis_index);
while (axis_index--) {
PyList_SET_ITEM(list, axis_index, PyLong_FromLong(joy->GetAxisPosition(axis_index)));
@@ -371,7 +371,7 @@ PyObject *SCA_JoystickSensor::pyattr_get_axis_single(void *self_v, const KX_PYAT
return NULL;
}
- return PyLong_FromLong(joy->GetAxisPosition(self->m_axis-1));
+ return PyLong_FromLong(joy ? joy->GetAxisPosition(self->m_axis - 1) : 0);
}
PyObject *SCA_JoystickSensor::pyattr_get_hat_values(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
@@ -379,8 +379,8 @@ PyObject *SCA_JoystickSensor::pyattr_get_hat_values(void *self_v, const KX_PYATT
SCA_JoystickSensor* self = static_cast<SCA_JoystickSensor*>(self_v);
SCA_Joystick *joy = ((SCA_JoystickManager *)self->m_eventmgr)->GetJoystickDevice(self->m_joyindex);
- int hat_index= joy->GetNumberOfHats();
- PyObject *list= PyList_New(hat_index);
+ int hat_index = (joy ? joy->GetNumberOfHats() : 0);
+ PyObject *list = PyList_New(hat_index);
while (hat_index--) {
PyList_SET_ITEM(list, hat_index, PyLong_FromLong(joy->GetHat(hat_index)));
@@ -394,7 +394,7 @@ PyObject *SCA_JoystickSensor::pyattr_get_hat_single(void *self_v, const KX_PYATT
SCA_JoystickSensor* self = static_cast<SCA_JoystickSensor*>(self_v);
SCA_Joystick *joy = ((SCA_JoystickManager *)self->m_eventmgr)->GetJoystickDevice(self->m_joyindex);
- return PyLong_FromLong(joy->GetHat(self->m_hat-1));
+ return PyLong_FromLong(joy ? joy->GetHat(self->m_hat - 1) : 0);
}
PyObject *SCA_JoystickSensor::pyattr_get_num_axis(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
diff --git a/source/gameengine/GameLogic/SCA_KeyboardManager.cpp b/source/gameengine/GameLogic/SCA_KeyboardManager.cpp
index edf1f300fba..778ba9e9a2c 100644
--- a/source/gameengine/GameLogic/SCA_KeyboardManager.cpp
+++ b/source/gameengine/GameLogic/SCA_KeyboardManager.cpp
@@ -33,10 +33,10 @@
*/
-#include "BoolValue.h"
+#include "EXP_BoolValue.h"
#include "SCA_KeyboardManager.h"
#include "SCA_KeyboardSensor.h"
-#include "IntValue.h"
+#include "EXP_IntValue.h"
#include <vector>
SCA_KeyboardManager::SCA_KeyboardManager(SCA_LogicManager* logicmgr,
diff --git a/source/gameengine/GameLogic/SCA_KeyboardSensor.cpp b/source/gameengine/GameLogic/SCA_KeyboardSensor.cpp
index cc203880f94..414a685d358 100644
--- a/source/gameengine/GameLogic/SCA_KeyboardSensor.cpp
+++ b/source/gameengine/GameLogic/SCA_KeyboardSensor.cpp
@@ -36,7 +36,7 @@
#include "SCA_KeyboardSensor.h"
#include "SCA_KeyboardManager.h"
#include "SCA_LogicManager.h"
-#include "StringValue.h"
+#include "EXP_StringValue.h"
#include "SCA_IInputDevice.h"
extern "C" {
@@ -511,6 +511,7 @@ PyObject *SCA_KeyboardSensor::pyattr_get_events(void *self_v, const KX_PYATTRIBU
PyList_SET_ITEM(keypair,0,PyLong_FromLong(i));
PyList_SET_ITEM(keypair,1,PyLong_FromLong(inevent.m_status));
PyList_Append(resultlist,keypair);
+ Py_DECREF(keypair);
}
}
return resultlist;
diff --git a/source/gameengine/GameLogic/SCA_KeyboardSensor.h b/source/gameengine/GameLogic/SCA_KeyboardSensor.h
index c9d55280fb7..51d7756bd1f 100644
--- a/source/gameengine/GameLogic/SCA_KeyboardSensor.h
+++ b/source/gameengine/GameLogic/SCA_KeyboardSensor.h
@@ -34,7 +34,7 @@
#define __SCA_KEYBOARDSENSOR_H__
#include "SCA_ISensor.h"
-#include "BoolValue.h"
+#include "EXP_BoolValue.h"
#include <list>
/**
diff --git a/source/gameengine/GameLogic/SCA_LogicManager.cpp b/source/gameengine/GameLogic/SCA_LogicManager.cpp
index adf57dec278..978f6d6b836 100644
--- a/source/gameengine/GameLogic/SCA_LogicManager.cpp
+++ b/source/gameengine/GameLogic/SCA_LogicManager.cpp
@@ -30,7 +30,7 @@
* \ingroup gamelogic
*/
-#include "Value.h"
+#include "EXP_Value.h"
#include "SCA_LogicManager.h"
#include "SCA_ISensor.h"
#include "SCA_IController.h"
diff --git a/source/gameengine/GameLogic/SCA_LogicManager.h b/source/gameengine/GameLogic/SCA_LogicManager.h
index 4d8c20065b5..7319bb537dd 100644
--- a/source/gameengine/GameLogic/SCA_LogicManager.h
+++ b/source/gameengine/GameLogic/SCA_LogicManager.h
@@ -24,7 +24,7 @@
*
* ***** END GPL LICENSE BLOCK *****
*/
-/** \file SCA_IController.h
+/** \file SCA_LogicManager.h
* \ingroup gamelogic
* \brief Regulates the top-level logic behavior for one scene.
*/
@@ -43,10 +43,10 @@
#include "CTR_Map.h"
#include "STR_HashedString.h"
-#include "Value.h"
+#include "EXP_Value.h"
#include "SG_QList.h"
-#include "KX_HashedPtr.h"
+#include "EXP_HashedPtr.h"
using namespace std;
typedef std::list<class SCA_IController*> controllerlist;
diff --git a/source/gameengine/GameLogic/SCA_MouseManager.cpp b/source/gameengine/GameLogic/SCA_MouseManager.cpp
index 6d05b862c2d..51c03d1e350 100644
--- a/source/gameengine/GameLogic/SCA_MouseManager.cpp
+++ b/source/gameengine/GameLogic/SCA_MouseManager.cpp
@@ -40,10 +40,10 @@
# pragma warning( disable:4786 )
#endif
-#include "BoolValue.h"
+#include "EXP_BoolValue.h"
#include "SCA_MouseManager.h"
#include "SCA_MouseSensor.h"
-#include "IntValue.h"
+#include "EXP_IntValue.h"
#include "RAS_ICanvas.h"
diff --git a/source/gameengine/GameLogic/SCA_MouseSensor.cpp b/source/gameengine/GameLogic/SCA_MouseSensor.cpp
index a7cf4963f04..2479e859dea 100644
--- a/source/gameengine/GameLogic/SCA_MouseSensor.cpp
+++ b/source/gameengine/GameLogic/SCA_MouseSensor.cpp
@@ -41,7 +41,7 @@
#include "SCA_MouseManager.h"
#include "SCA_LogicManager.h"
#include "SCA_IInputDevice.h"
-#include "ConstExpr.h"
+#include "EXP_ConstExpr.h"
#include <iostream>
/* ------------------------------------------------------------------------- */
diff --git a/source/gameengine/GameLogic/SCA_MouseSensor.h b/source/gameengine/GameLogic/SCA_MouseSensor.h
index 8d05a548681..2660aaeacb5 100644
--- a/source/gameengine/GameLogic/SCA_MouseSensor.h
+++ b/source/gameengine/GameLogic/SCA_MouseSensor.h
@@ -34,7 +34,7 @@
#define __SCA_MOUSESENSOR_H__
#include "SCA_ISensor.h"
-#include "BoolValue.h"
+#include "EXP_BoolValue.h"
#include "SCA_IInputDevice.h"
class SCA_MouseSensor : public SCA_ISensor
diff --git a/source/gameengine/GameLogic/SCA_NANDController.cpp b/source/gameengine/GameLogic/SCA_NANDController.cpp
index c78ce77f9fb..6a00c110e2b 100644
--- a/source/gameengine/GameLogic/SCA_NANDController.cpp
+++ b/source/gameengine/GameLogic/SCA_NANDController.cpp
@@ -36,7 +36,7 @@
#include "SCA_NANDController.h"
#include "SCA_ISensor.h"
#include "SCA_LogicManager.h"
-#include "BoolValue.h"
+#include "EXP_BoolValue.h"
/* ------------------------------------------------------------------------- */
/* Native functions */
diff --git a/source/gameengine/GameLogic/SCA_NORController.cpp b/source/gameengine/GameLogic/SCA_NORController.cpp
index e7fb6437feb..fb09617e060 100644
--- a/source/gameengine/GameLogic/SCA_NORController.cpp
+++ b/source/gameengine/GameLogic/SCA_NORController.cpp
@@ -36,7 +36,7 @@
#include "SCA_NORController.h"
#include "SCA_ISensor.h"
#include "SCA_LogicManager.h"
-#include "BoolValue.h"
+#include "EXP_BoolValue.h"
/* ------------------------------------------------------------------------- */
/* Native functions */
diff --git a/source/gameengine/GameLogic/SCA_ORController.cpp b/source/gameengine/GameLogic/SCA_ORController.cpp
index b147f8e6bf6..8a59bdf1b89 100644
--- a/source/gameengine/GameLogic/SCA_ORController.cpp
+++ b/source/gameengine/GameLogic/SCA_ORController.cpp
@@ -36,7 +36,7 @@
#include "SCA_ORController.h"
#include "SCA_ISensor.h"
#include "SCA_LogicManager.h"
-#include "BoolValue.h"
+#include "EXP_BoolValue.h"
/* ------------------------------------------------------------------------- */
/* Native functions */
diff --git a/source/gameengine/GameLogic/SCA_PropertyActuator.cpp b/source/gameengine/GameLogic/SCA_PropertyActuator.cpp
index ea1b2a2bce3..f2907ca6361 100644
--- a/source/gameengine/GameLogic/SCA_PropertyActuator.cpp
+++ b/source/gameengine/GameLogic/SCA_PropertyActuator.cpp
@@ -36,9 +36,9 @@
#include <stddef.h>
#include "SCA_PropertyActuator.h"
-#include "InputParser.h"
-#include "Operator2Expr.h"
-#include "ConstExpr.h"
+#include "EXP_InputParser.h"
+#include "EXP_Operator2Expr.h"
+#include "EXP_ConstExpr.h"
/* ------------------------------------------------------------------------- */
/* Native functions */
diff --git a/source/gameengine/GameLogic/SCA_PropertySensor.cpp b/source/gameengine/GameLogic/SCA_PropertySensor.cpp
index 6f34f8710c1..82f3bee86b2 100644
--- a/source/gameengine/GameLogic/SCA_PropertySensor.cpp
+++ b/source/gameengine/GameLogic/SCA_PropertySensor.cpp
@@ -37,14 +37,14 @@
#include <iostream>
#include "SCA_PropertySensor.h"
-#include "Operator2Expr.h"
-#include "ConstExpr.h"
-#include "InputParser.h"
-#include "StringValue.h"
+#include "EXP_Operator2Expr.h"
+#include "EXP_ConstExpr.h"
+#include "EXP_InputParser.h"
+#include "EXP_StringValue.h"
#include "SCA_EventManager.h"
#include "SCA_LogicManager.h"
-#include "BoolValue.h"
-#include "FloatValue.h"
+#include "EXP_BoolValue.h"
+#include "EXP_FloatValue.h"
#include <stdio.h>
SCA_PropertySensor::SCA_PropertySensor(SCA_EventManager* eventmgr,
@@ -265,13 +265,8 @@ bool SCA_PropertySensor::CheckPropertyCondition()
//the concept of Edge and Level triggering has unwanted effect for KX_PROPSENSOR_CHANGED
//see Game Engine bugtracker [ #3809 ]
- if (m_checktype != KX_PROPSENSOR_CHANGED)
- {
- m_recentresult=result;
- } else
- {
- m_recentresult=result;//true;
- }
+ m_recentresult = result;
+
return result;
}
diff --git a/source/gameengine/GameLogic/SCA_PythonController.cpp b/source/gameengine/GameLogic/SCA_PythonController.cpp
index 8c3ce38276e..fa30e3a5caf 100644
--- a/source/gameengine/GameLogic/SCA_PythonController.cpp
+++ b/source/gameengine/GameLogic/SCA_PythonController.cpp
@@ -39,7 +39,7 @@
#include "SCA_LogicManager.h"
#include "SCA_ISensor.h"
#include "SCA_IActuator.h"
-#include "PyObjectPlus.h"
+#include "EXP_PyObjectPlus.h"
#ifdef WITH_PYTHON
#include "compile.h"
@@ -470,7 +470,7 @@ void SCA_PythonController::Trigger(SCA_LogicManager* logicmgr)
PyObject *SCA_PythonController::PyActivate(PyObject *value)
{
if (m_sCurrentController != this) {
- PyErr_SetString(PyExc_SystemError, "Cannot add an actuator from a non-active controller");
+ PyErr_SetString(PyExc_SystemError, "Cannot activate an actuator from a non-active controller");
return NULL;
}
@@ -485,7 +485,7 @@ PyObject *SCA_PythonController::PyActivate(PyObject *value)
PyObject *SCA_PythonController::PyDeActivate(PyObject *value)
{
if (m_sCurrentController != this) {
- PyErr_SetString(PyExc_SystemError, "Cannot add an actuator from a non-active controller");
+ PyErr_SetString(PyExc_SystemError, "Cannot deactivate an actuator from a non-active controller");
return NULL;
}
diff --git a/source/gameengine/GameLogic/SCA_PythonController.h b/source/gameengine/GameLogic/SCA_PythonController.h
index d2549318c2e..11241da9117 100644
--- a/source/gameengine/GameLogic/SCA_PythonController.h
+++ b/source/gameengine/GameLogic/SCA_PythonController.h
@@ -35,7 +35,7 @@
#include "SCA_IController.h"
#include "SCA_LogicManager.h"
-#include "BoolValue.h"
+#include "EXP_BoolValue.h"
#include <vector>
diff --git a/source/gameengine/GameLogic/SCA_PythonJoystick.h b/source/gameengine/GameLogic/SCA_PythonJoystick.h
index 15c6285aed5..ecde00d28b9 100644
--- a/source/gameengine/GameLogic/SCA_PythonJoystick.h
+++ b/source/gameengine/GameLogic/SCA_PythonJoystick.h
@@ -27,7 +27,7 @@
#ifndef __SCA_PYTHONJOYSTICK_H__
#define __SCA_PYTHONJOYSTICK_H__
-#include "PyObjectPlus.h"
+#include "EXP_PyObjectPlus.h"
class SCA_PythonJoystick : public PyObjectPlus
{
diff --git a/source/gameengine/GameLogic/SCA_PythonKeyboard.h b/source/gameengine/GameLogic/SCA_PythonKeyboard.h
index 53068f38e6a..3cbe250378c 100644
--- a/source/gameengine/GameLogic/SCA_PythonKeyboard.h
+++ b/source/gameengine/GameLogic/SCA_PythonKeyboard.h
@@ -27,7 +27,7 @@
#ifndef __SCA_PYTHONKEYBOARD_H__
#define __SCA_PYTHONKEYBOARD_H__
-#include "PyObjectPlus.h"
+#include "EXP_PyObjectPlus.h"
class SCA_PythonKeyboard : public PyObjectPlus
{
diff --git a/source/gameengine/GameLogic/SCA_PythonMouse.h b/source/gameengine/GameLogic/SCA_PythonMouse.h
index bc6e65f07a8..6dde90b3482 100644
--- a/source/gameengine/GameLogic/SCA_PythonMouse.h
+++ b/source/gameengine/GameLogic/SCA_PythonMouse.h
@@ -27,7 +27,7 @@
#ifndef __SCA_PYTHONMOUSE_H__
#define __SCA_PYTHONMOUSE_H__
-#include "PyObjectPlus.h"
+#include "EXP_PyObjectPlus.h"
class SCA_PythonMouse : public PyObjectPlus
{
diff --git a/source/gameengine/GameLogic/SCA_RandomActuator.cpp b/source/gameengine/GameLogic/SCA_RandomActuator.cpp
index db6b4a63423..8d75be9089d 100644
--- a/source/gameengine/GameLogic/SCA_RandomActuator.cpp
+++ b/source/gameengine/GameLogic/SCA_RandomActuator.cpp
@@ -36,9 +36,9 @@
#include <stddef.h>
#include <math.h>
-#include "BoolValue.h"
-#include "IntValue.h"
-#include "FloatValue.h"
+#include "EXP_BoolValue.h"
+#include "EXP_IntValue.h"
+#include "EXP_FloatValue.h"
#include "SCA_IActuator.h"
#include "SCA_RandomActuator.h"
#include "MT_Transform.h"
diff --git a/source/gameengine/GameLogic/SCA_RandomSensor.cpp b/source/gameengine/GameLogic/SCA_RandomSensor.cpp
index 4e93556453a..8f2dc8d80f5 100644
--- a/source/gameengine/GameLogic/SCA_RandomSensor.cpp
+++ b/source/gameengine/GameLogic/SCA_RandomSensor.cpp
@@ -39,7 +39,7 @@
#include "SCA_EventManager.h"
#include "SCA_RandomEventManager.h"
#include "SCA_LogicManager.h"
-#include "ConstExpr.h"
+#include "EXP_ConstExpr.h"
#include <iostream>
/* ------------------------------------------------------------------------- */
@@ -107,7 +107,7 @@ bool SCA_RandomSensor::Evaluate()
bool evaluateResult = false;
- if (++m_interval > m_pulse_frequency) {
+ if (++m_interval > m_skipped_ticks) {
bool drawResult = false;
m_interval = 0;
if (m_iteration > 31) {
diff --git a/source/gameengine/GameLogic/SCA_RandomSensor.h b/source/gameengine/GameLogic/SCA_RandomSensor.h
index 628562b77e6..66107b7b74b 100644
--- a/source/gameengine/GameLogic/SCA_RandomSensor.h
+++ b/source/gameengine/GameLogic/SCA_RandomSensor.h
@@ -34,7 +34,7 @@
#define __SCA_RANDOMSENSOR_H__
#include "SCA_ISensor.h"
-#include "BoolValue.h"
+#include "EXP_BoolValue.h"
#include "SCA_RandomNumberGenerator.h"
class SCA_RandomSensor : public SCA_ISensor
diff --git a/source/gameengine/GameLogic/SCA_TimeEventManager.cpp b/source/gameengine/GameLogic/SCA_TimeEventManager.cpp
index 5aa6fdc8625..c56a1496823 100644
--- a/source/gameengine/GameLogic/SCA_TimeEventManager.cpp
+++ b/source/gameengine/GameLogic/SCA_TimeEventManager.cpp
@@ -38,7 +38,7 @@
#include "SCA_TimeEventManager.h"
#include "SCA_LogicManager.h"
-#include "FloatValue.h"
+#include "EXP_FloatValue.h"
SCA_TimeEventManager::SCA_TimeEventManager(SCA_LogicManager* logicmgr)
: SCA_EventManager(NULL, TIME_EVENTMGR)
diff --git a/source/gameengine/GameLogic/SCA_TimeEventManager.h b/source/gameengine/GameLogic/SCA_TimeEventManager.h
index 4c929dca23c..38d7e3fc4d4 100644
--- a/source/gameengine/GameLogic/SCA_TimeEventManager.h
+++ b/source/gameengine/GameLogic/SCA_TimeEventManager.h
@@ -33,7 +33,7 @@
#define __SCA_TIMEEVENTMANAGER_H__
#include "SCA_EventManager.h"
-#include "Value.h"
+#include "EXP_Value.h"
#include <vector>
using namespace std;
diff --git a/source/gameengine/GameLogic/SCA_XNORController.cpp b/source/gameengine/GameLogic/SCA_XNORController.cpp
index 2cfc32a6d40..f97d11cabf3 100644
--- a/source/gameengine/GameLogic/SCA_XNORController.cpp
+++ b/source/gameengine/GameLogic/SCA_XNORController.cpp
@@ -36,7 +36,7 @@
#include "SCA_XNORController.h"
#include "SCA_ISensor.h"
#include "SCA_LogicManager.h"
-#include "BoolValue.h"
+#include "EXP_BoolValue.h"
/* ------------------------------------------------------------------------- */
/* Native functions */
diff --git a/source/gameengine/GameLogic/SCA_XORController.cpp b/source/gameengine/GameLogic/SCA_XORController.cpp
index eaa1825e5b6..bb1ea822bd8 100644
--- a/source/gameengine/GameLogic/SCA_XORController.cpp
+++ b/source/gameengine/GameLogic/SCA_XORController.cpp
@@ -36,7 +36,7 @@
#include "SCA_XORController.h"
#include "SCA_ISensor.h"
#include "SCA_LogicManager.h"
-#include "BoolValue.h"
+#include "EXP_BoolValue.h"
/* ------------------------------------------------------------------------- */
/* Native functions */
diff --git a/source/gameengine/GamePlayer/common/CMakeLists.txt b/source/gameengine/GamePlayer/common/CMakeLists.txt
index fd73b4efb53..e6c980de566 100644
--- a/source/gameengine/GamePlayer/common/CMakeLists.txt
+++ b/source/gameengine/GamePlayer/common/CMakeLists.txt
@@ -47,6 +47,7 @@ set(INC
../../../blender/makesdna
../../../../intern/container
../../../../intern/ghost
+ ../../../../intern/glew-mx
../../../../intern/guardedalloc
../../../../intern/string
)
@@ -69,6 +70,6 @@ set(SRC
GPC_MouseDevice.h
)
-add_definitions(-DGLEW_STATIC)
+add_definitions(${GL_DEFINITIONS})
blender_add_lib_nolist(ge_player_common "${SRC}" "${INC}" "${INC_SYS}")
diff --git a/source/gameengine/GamePlayer/common/GPC_Canvas.cpp b/source/gameengine/GamePlayer/common/GPC_Canvas.cpp
index be7cf6629f0..52c4d13c638 100644
--- a/source/gameengine/GamePlayer/common/GPC_Canvas.cpp
+++ b/source/gameengine/GamePlayer/common/GPC_Canvas.cpp
@@ -69,6 +69,7 @@ GPC_Canvas::GPC_Canvas(
m_displayarea.m_y1 = 0;
m_displayarea.m_x2 = width;
m_displayarea.m_y2 = height;
+ m_frame = 1;
glGetIntegerv(GL_VIEWPORT, (GLint*)m_viewport);
}
@@ -180,7 +181,9 @@ MakeScreenShot(
char path[FILE_MAX];
BLI_strncpy(path, filename, sizeof(path));
BLI_path_abs(path, G.main->name);
- BKE_add_image_extension_from_type(path, im_format.imtype);
+ BLI_path_frame(path, m_frame, 0);
+ m_frame++;
+ BKE_image_path_ensure_ext_from_imtype(path, im_format.imtype);
// create and save imbuf
ImBuf *ibuf = IMB_allocImBuf(GetWidth(), GetHeight(), 24, 0);
diff --git a/source/gameengine/GamePlayer/common/GPC_Canvas.h b/source/gameengine/GamePlayer/common/GPC_Canvas.h
index bd50066a212..34cc9759a08 100644
--- a/source/gameengine/GamePlayer/common/GPC_Canvas.h
+++ b/source/gameengine/GamePlayer/common/GPC_Canvas.h
@@ -40,7 +40,7 @@
# include <windows.h>
#endif /* WIN32 */
-#include "GL/glew.h"
+#include "glew-mx.h"
#include <map>
@@ -56,6 +56,8 @@ protected:
/** Rect that defines the area used for rendering,
* relative to the context */
RAS_Rect m_displayarea;
+ /** Frame counter for screenshots */
+ int m_frame;
int m_viewport[4];
@@ -69,6 +71,8 @@ public:
virtual void ResizeWindow(int width, int height) {}
+ virtual void GetDisplayDimensions(int &width, int &height) {}
+
/**
* \section Methods inherited from abstract base class RAS_ICanvas.
*/
diff --git a/source/gameengine/GamePlayer/common/SConscript b/source/gameengine/GamePlayer/common/SConscript
index e30c2eb5859..dc105491c98 100644
--- a/source/gameengine/GamePlayer/common/SConscript
+++ b/source/gameengine/GamePlayer/common/SConscript
@@ -64,12 +64,12 @@ incs = [
'#source/blender/misc',
'#source/blender/blenloader',
'#source/blender/gpu',
- '#extern/glew/include',
+ env['BF_GLEW_INC'],
+ '#/intern/glew-mx',
]
-defs = [
- 'GLEW_STATIC',
- ]
+defs = []
+defs += env['BF_GL_DEFINITIONS']
if env['WITH_BF_PYTHON']:
incs.extend(Split(env['BF_PYTHON_INC']))
diff --git a/source/gameengine/GamePlayer/ghost/CMakeLists.txt b/source/gameengine/GamePlayer/ghost/CMakeLists.txt
index df752799c2c..283f222115c 100644
--- a/source/gameengine/GamePlayer/ghost/CMakeLists.txt
+++ b/source/gameengine/GamePlayer/ghost/CMakeLists.txt
@@ -42,12 +42,14 @@ set(INC
../../../blender/blenkernel
../../../blender/blenlib
../../../blender/blenloader
+ ../../../blender/blentranslation
../../../blender/gpu
../../../blender/imbuf
../../../blender/makesdna
../../../blender/makesrna
../../../../intern/container
../../../../intern/ghost
+ ../../../../intern/glew-mx
../../../../intern/guardedalloc
../../../../intern/string
../../../../intern/memutil
@@ -73,7 +75,7 @@ set(SRC
GPG_System.h
)
-add_definitions(-DGLEW_STATIC)
+add_definitions(${GL_DEFINITIONS})
if(WITH_CODEC_FFMPEG)
add_definitions(-DWITH_FFMPEG)
@@ -84,10 +86,18 @@ if(WITH_INTERNATIONAL)
endif()
if(WITH_AUDASPACE)
+ add_definitions(${AUDASPACE_DEFINITIONS})
+
+ list(APPEND INC_SYS
+ ${AUDASPACE_C_INCLUDE_DIRS}
+ )
+endif()
+
+if(WITH_SDL AND WITH_SDL_DYNLOAD)
list(APPEND INC
- ../../../../intern/audaspace/intern
+ ../../../../extern/sdlew/include
)
- add_definitions(-DWITH_AUDASPACE)
+ add_definitions(-DWITH_SDL_DYNLOAD)
endif()
blender_add_lib_nolist(ge_player_ghost "${SRC}" "${INC}" "${INC_SYS}")
diff --git a/source/gameengine/GamePlayer/ghost/GPG_Application.cpp b/source/gameengine/GamePlayer/ghost/GPG_Application.cpp
index b85d4b40ca8..2b357f43031 100644
--- a/source/gameengine/GamePlayer/ghost/GPG_Application.cpp
+++ b/source/gameengine/GamePlayer/ghost/GPG_Application.cpp
@@ -36,8 +36,9 @@
# include <windows.h>
#endif
-#include "GL/glew.h"
+#include "glew-mx.h"
#include "GPU_extensions.h"
+#include "GPU_init_exit.h"
#include "GPG_Application.h"
#include "BL_BlenderDataConversion.h"
@@ -99,9 +100,7 @@ extern "C"
#include "GHOST_Rect.h"
#ifdef WITH_AUDASPACE
-# include "AUD_C-API.h"
-# include "AUD_I3DDevice.h"
-# include "AUD_IDevice.h"
+# include AUD_DEVICE_H
#endif
static void frameTimerProc(GHOST_ITimerTask* task, GHOST_TUns64 time);
@@ -113,6 +112,7 @@ GPG_Application::GPG_Application(GHOST_ISystem* system)
: m_startSceneName(""),
m_startScene(0),
m_maggie(0),
+ m_kxStartScene(NULL),
m_exitRequested(0),
m_system(system),
m_mainWindow(0),
@@ -249,9 +249,15 @@ bool GPG_Application::startScreenSaverPreview(
int windowWidth = rc.right - rc.left;
int windowHeight = rc.bottom - rc.top;
STR_String title = "";
-
+ GHOST_GLSettings glSettings = {0};
+
+ if (stereoVisual) {
+ glSettings.flags |= GHOST_glStereoVisual;
+ }
+ glSettings.numOfAASamples = samples;
+
m_mainWindow = fSystem->createWindow(title, 0, 0, windowWidth, windowHeight, GHOST_kWindowStateMinimized,
- GHOST_kDrawingContextTypeOpenGL, stereoVisual, samples);
+ GHOST_kDrawingContextTypeOpenGL, glSettings);
if (!m_mainWindow) {
printf("error: could not create main window\n");
exit(-1);
@@ -322,11 +328,16 @@ bool GPG_Application::startWindow(
const int stereoMode,
const GHOST_TUns16 samples)
{
+ GHOST_GLSettings glSettings = {0};
bool success;
// Create the main window
//STR_String title ("Blender Player - GHOST");
+ if (stereoVisual)
+ glSettings.flags |= GHOST_glStereoVisual;
+ glSettings.numOfAASamples = samples;
+
m_mainWindow = fSystem->createWindow(title, windowLeft, windowTop, windowWidth, windowHeight, GHOST_kWindowStateNormal,
- GHOST_kDrawingContextTypeOpenGL, stereoVisual, false, samples);
+ GHOST_kDrawingContextTypeOpenGL, glSettings);
if (!m_mainWindow) {
printf("error: could not create main window\n");
exit(-1);
@@ -353,10 +364,16 @@ bool GPG_Application::startEmbeddedWindow(
const GHOST_TUns16 samples)
{
GHOST_TWindowState state = GHOST_kWindowStateNormal;
+ GHOST_GLSettings glSettings = {0};
+
+ if (stereoVisual)
+ glSettings.flags |= GHOST_glStereoVisual;
+ glSettings.numOfAASamples = samples;
+
if (parentWindow != 0)
state = GHOST_kWindowStateEmbedded;
m_mainWindow = fSystem->createWindow(title, 0, 0, 0, 0, state,
- GHOST_kDrawingContextTypeOpenGL, stereoVisual, false, samples, parentWindow);
+ GHOST_kDrawingContextTypeOpenGL, glSettings, parentWindow);
if (!m_mainWindow) {
printf("error: could not create main window\n");
@@ -545,7 +562,7 @@ bool GPG_Application::initEngine(GHOST_IWindow* window, const int stereoMode)
{
if (!m_engineInitialized)
{
- GPU_extensions_init();
+ GPU_init();
bgl::InitExtensions(true);
// get and set the preferences
@@ -566,7 +583,7 @@ bool GPG_Application::initEngine(GHOST_IWindow* window, const int stereoMode)
bool frameRate = (SYS_GetCommandLineInt(syshandle, "show_framerate", 0) != 0);
bool useLists = (SYS_GetCommandLineInt(syshandle, "displaylists", gm->flag & GAME_DISPLAY_LISTS) != 0) && GPU_display_list_support();
bool nodepwarnings = (SYS_GetCommandLineInt(syshandle, "ignore_deprecation_warnings", 1) != 0);
- bool restrictAnimFPS = gm->flag & GAME_RESTRICT_ANIM_UPDATES;
+ bool restrictAnimFPS = (gm->flag & GAME_RESTRICT_ANIM_UPDATES) != 0;
if (GLEW_ARB_multitexture && GLEW_VERSION_1_1)
m_blendermat = (SYS_GetCommandLineInt(syshandle, "blender_material", 1) != 0);
@@ -618,7 +635,7 @@ bool GPG_Application::initEngine(GHOST_IWindow* window, const int stereoMode)
if (!m_networkdevice)
goto initFailed;
- sound_init(m_maggie);
+ BKE_sound_init(m_maggie);
// create a ketsjisystem (only needed for timing and stuff)
m_kxsystem = new GPG_System (m_system);
@@ -654,7 +671,7 @@ bool GPG_Application::initEngine(GHOST_IWindow* window, const int stereoMode)
return m_engineInitialized;
initFailed:
- sound_exit();
+ BKE_sound_exit();
delete m_kxsystem;
delete m_networkdevice;
delete m_mouse;
@@ -698,7 +715,7 @@ bool GPG_Application::startEngine(void)
m_sceneconverter = new KX_BlenderSceneConverter(m_maggie, m_ketsjiengine);
if (m_sceneconverter)
{
- STR_String startscenename = m_startSceneName.Ptr();
+ STR_String m_kxStartScenename = m_startSceneName.Ptr();
m_ketsjiengine->SetSceneConverter(m_sceneconverter);
// if (always_use_expand_framing)
@@ -710,17 +727,17 @@ bool GPG_Application::startEngine(void)
if (m_startScene->gm.flag & GAME_NO_MATERIAL_CACHING)
m_sceneconverter->SetCacheMaterials(false);
- KX_Scene* startscene = new KX_Scene(m_keyboard,
+ m_kxStartScene = new KX_Scene(m_keyboard,
m_mouse,
m_networkdevice,
- startscenename,
+ m_kxStartScenename,
m_startScene,
m_canvas);
#ifdef WITH_PYTHON
// some python things
PyObject *gameLogic, *gameLogic_keys;
- setupGamePython(m_ketsjiengine, startscene, m_maggie, NULL, &gameLogic, &gameLogic_keys, m_argc, m_argv);
+ setupGamePython(m_ketsjiengine, m_kxStartScene, m_maggie, NULL, &gameLogic, &gameLogic_keys, m_argc, m_argv);
#endif // WITH_PYTHON
//initialize Dome Settings
@@ -728,13 +745,10 @@ bool GPG_Application::startEngine(void)
m_ketsjiengine->InitDome(m_startScene->gm.dome.res, m_startScene->gm.dome.mode, m_startScene->gm.dome.angle, m_startScene->gm.dome.resbuf, m_startScene->gm.dome.tilt, m_startScene->gm.dome.warptext);
// initialize 3D Audio Settings
- AUD_I3DDevice* dev = AUD_get3DDevice();
- if (dev)
- {
- dev->setSpeedOfSound(m_startScene->audio.speed_of_sound);
- dev->setDopplerFactor(m_startScene->audio.doppler_factor);
- dev->setDistanceModel(AUD_DistanceModel(m_startScene->audio.distance_model));
- }
+ AUD_Device* device = BKE_sound_get_device();
+ AUD_Device_setSpeedOfSound(device, m_startScene->audio.speed_of_sound);
+ AUD_Device_setDopplerFactor(device, m_startScene->audio.doppler_factor);
+ AUD_Device_setDistanceModel(device, AUD_DistanceModel(m_startScene->audio.distance_model));
#ifdef WITH_PYTHON
// Set the GameLogic.globalDict from marshal'd data, so we can
@@ -742,10 +756,10 @@ bool GPG_Application::startEngine(void)
loadGamePythonConfig(m_pyGlobalDictString, m_pyGlobalDictString_Length);
#endif
m_sceneconverter->ConvertScene(
- startscene,
+ m_kxStartScene,
m_rasterizer,
m_canvas);
- m_ketsjiengine->AddScene(startscene);
+ m_ketsjiengine->AddScene(m_kxStartScene);
// Create a timer that is used to kick the engine
if (!m_frameTimer) {
@@ -758,7 +772,7 @@ bool GPG_Application::startEngine(void)
// Set the animation playback rate for ipo's and actions
// the framerate below should patch with FPS macro defined in blendef.h
// Could be in StartEngine set the framerate, we need the scene to do this
- Scene *scene= startscene->GetBlenderScene(); // needed for macro
+ Scene *scene= m_kxStartScene->GetBlenderScene(); // needed for macro
m_ketsjiengine->SetAnimFrameRate(FPS);
}
@@ -829,7 +843,7 @@ void GPG_Application::exitEngine()
if (!m_engineInitialized)
return;
- sound_exit();
+ BKE_sound_exit();
if (m_ketsjiengine)
{
stopEngine();
@@ -867,7 +881,7 @@ void GPG_Application::exitEngine()
m_canvas = 0;
}
- GPU_extensions_exit();
+ GPU_exit();
#ifdef WITH_PYTHON
// Call this after we're sure nothing needs Python anymore (e.g., destructors)
diff --git a/source/gameengine/GamePlayer/ghost/GPG_Application.h b/source/gameengine/GamePlayer/ghost/GPG_Application.h
index 2d21b50e664..b6f545c2de8 100644
--- a/source/gameengine/GamePlayer/ghost/GPG_Application.h
+++ b/source/gameengine/GamePlayer/ghost/GPG_Application.h
@@ -40,6 +40,7 @@
#include "KX_KetsjiEngine.h"
class KX_KetsjiEngine;
+class KX_Scene;
class KX_ISceneConverter;
class NG_LoopBackNetworkDeviceInterface;
class RAS_IRasterizer;
@@ -83,6 +84,12 @@ public:
int getExitRequested(void);
const STR_String& getExitString(void);
GlobalSettings* getGlobalSettings(void);
+
+ inline KX_Scene *GetStartScene() const
+ {
+ return m_kxStartScene;
+ }
+
bool StartGameEngine(int stereoMode);
void StopGameEngine();
void EngineNextFrame();
@@ -118,6 +125,7 @@ protected:
STR_String m_startSceneName;
struct Scene* m_startScene;
struct Main* m_maggie;
+ KX_Scene *m_kxStartScene;
/* Exit state. */
int m_exitRequested;
diff --git a/source/gameengine/GamePlayer/ghost/GPG_Canvas.cpp b/source/gameengine/GamePlayer/ghost/GPG_Canvas.cpp
index 35c7c62a67d..09eb1691dae 100644
--- a/source/gameengine/GamePlayer/ghost/GPG_Canvas.cpp
+++ b/source/gameengine/GamePlayer/ghost/GPG_Canvas.cpp
@@ -113,12 +113,24 @@ void GPG_Canvas::SetSwapInterval(int interval)
m_window->setSwapInterval(interval);
}
-int GPG_Canvas::GetSwapInterval()
+bool GPG_Canvas::GetSwapInterval(int& intervalOut)
{
if (m_window)
- return m_window->getSwapInterval();
+ return (bool)m_window->getSwapInterval(intervalOut);
- return 0;
+ return false;
+}
+
+void GPG_Canvas::GetDisplayDimensions(int &width, int &height)
+ {
+ unsigned int uiwidth;
+ unsigned int uiheight;
+
+ GHOST_ISystem *system = GHOST_ISystem::getSystem();
+ system->getMainDisplayDimensions(uiwidth, uiheight);
+
+ width = uiwidth;
+ height = uiheight;
}
void GPG_Canvas::ResizeWindow(int width, int height)
diff --git a/source/gameengine/GamePlayer/ghost/GPG_Canvas.h b/source/gameengine/GamePlayer/ghost/GPG_Canvas.h
index 6e1f86cac0e..18afbf6cd9e 100644
--- a/source/gameengine/GamePlayer/ghost/GPG_Canvas.h
+++ b/source/gameengine/GamePlayer/ghost/GPG_Canvas.h
@@ -56,13 +56,15 @@ public:
virtual void SetMouseState(RAS_MouseState mousestate);
virtual void SwapBuffers();
virtual void SetSwapInterval(int interval);
- virtual int GetSwapInterval();
+ virtual bool GetSwapInterval(int& intervalOut);
virtual int GetMouseX(int x) { return x; }
virtual int GetMouseY(int y) { return y; }
virtual float GetMouseNormalizedX(int x);
virtual float GetMouseNormalizedY(int y);
+ virtual void GetDisplayDimensions(int &width, int &height);
+
virtual void ResizeWindow(int width, int height);
virtual void SetFullScreen(bool enable);
virtual bool GetFullScreen();
diff --git a/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp b/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp
index b6456b105c8..23d5b89f140 100644
--- a/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp
+++ b/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp
@@ -43,6 +43,7 @@
#include "KX_KetsjiEngine.h"
#include "KX_PythonInit.h"
#include "KX_PythonMain.h"
+#include "KX_PyConstraintBinding.h" // for PHY_SetActiveEnvironment
/**********************************
* Begin Blender include block
@@ -64,6 +65,7 @@ extern "C"
#include "BLO_readfile.h"
#include "BLO_runtime.h"
+#include "BKE_appdir.h"
#include "BKE_blender.h"
#include "BKE_depsgraph.h"
#include "BKE_global.h"
@@ -73,17 +75,21 @@ extern "C"
#include "BKE_report.h"
#include "BKE_library.h"
#include "BKE_modifier.h"
+#include "BKE_material.h"
#include "BKE_text.h"
#include "BKE_sound.h"
#include "IMB_imbuf.h"
#include "IMB_moviecache.h"
+#ifdef __APPLE__
int GHOST_HACK_getFirstFile(char buf[]);
+#endif
// For BLF
#include "BLF_api.h"
-#include "BLF_translation.h"
+#include "BLT_translation.h"
+#include "BLT_lang.h"
extern int datatoc_bfont_ttf_size;
extern char datatoc_bfont_ttf[];
extern int datatoc_bmonofont_ttf_size;
@@ -116,6 +122,10 @@ extern char datatoc_bmonofont_ttf[];
#endif // !defined(DEBUG)
#endif // WIN32
+#ifdef WITH_SDL_DYNLOAD
+# include "sdlew.h"
+#endif
+
const int kMinWindowWidth = 100;
const int kMinWindowHeight = 100;
@@ -299,7 +309,7 @@ static void get_filename(int argc, char **argv, char *filename)
if (GHOST_HACK_getFirstFile(firstfilebuf)) {
BLI_strncpy(filename, firstfilebuf, FILE_MAX);
}
- }
+ }
}
srclen -= ::strlen("MacOS/blenderplayer");
@@ -429,8 +439,13 @@ int main(int argc, char** argv)
signal (SIGFPE, SIG_IGN);
#endif /* __alpha__ */
#endif /* __linux__ */
- BLI_init_program_path(argv[0]);
- BLI_temp_dir_init(NULL);
+
+#ifdef WITH_SDL_DYNLOAD
+ sdlewInit();
+#endif
+
+ BKE_appdir_program_path_init(argv[0]);
+ BKE_tempdir_init(NULL);
// We don't use threads directly in the BGE, but we need to call this so things like
// freeing up GPU_Textures works correctly.
@@ -459,8 +474,8 @@ int main(int argc, char** argv)
// Setup builtin font for BLF (mostly copied from creator.c, wm_init_exit.c and interface_style.c)
BLF_init(11, U.dpi);
- BLF_lang_init();
- BLF_lang_set("");
+ BLT_lang_init();
+ BLT_lang_set("");
BLF_load_mem("default", (unsigned char*)datatoc_bfont_ttf, datatoc_bfont_ttf_size);
if (blf_mono_font == -1)
@@ -505,9 +520,12 @@ int main(int argc, char** argv)
// enable fast mipmap generation
U.use_gpu_mipmap = 1;
- sound_init_once();
+ BKE_sound_init_once();
+
+ // Initialize a default material for meshes without materials.
+ init_def_material();
- set_free_windowmanager_cb(wm_free);
+ BKE_library_callback_free_window_manager_set(wm_free);
/* if running blenderplayer the last argument can't be parsed since it has to be the filename. else it is bundled */
isBlenderPlayer = !BLO_is_a_runtime(argv[0]);
@@ -583,7 +601,7 @@ int main(int argc, char** argv)
i++;
G.debug |= G_DEBUG;
MEM_set_memory_debug();
-#ifdef DEBUG
+#ifndef NDEBUG
BLI_mempool_set_memory_debug();
#endif
break;
@@ -811,14 +829,6 @@ int main(int argc, char** argv)
if (scr_saver_mode != SCREEN_SAVER_MODE_CONFIGURATION)
#endif
{
-
- if (SYS_GetCommandLineInt(syshandle, "nomipmap", 0)) {
- GPU_set_mipmap(0);
- }
-
- GPU_set_anisotropic(U.anisotropic_filter);
- GPU_set_gpu_mipmapping(U.use_gpu_mipmap);
-
// Create the system
if (GHOST_ISystem::createSystem() == GHOST_kSuccess) {
GHOST_ISystem* system = GHOST_ISystem::getSystem();
@@ -877,7 +887,7 @@ int main(int argc, char** argv)
}
}
else {
- bfd = load_game_data(BLI_program_path(), filename[0]? filename: NULL);
+ bfd = load_game_data(BKE_appdir_program_path(), filename[0]? filename: NULL);
}
#if defined(DEBUG)
@@ -1041,6 +1051,13 @@ int main(int argc, char** argv)
else
app.startWindow(title, windowLeft, windowTop, windowWidth, windowHeight,
stereoWindow, stereomode, aasamples);
+
+ if (SYS_GetCommandLineInt(syshandle, "nomipmap", 0)) {
+ GPU_set_mipmap(0);
+ }
+
+ GPU_set_anisotropic(U.anisotropic_filter);
+ GPU_set_gpu_mipmapping(U.use_gpu_mipmap);
}
}
}
@@ -1064,6 +1081,11 @@ int main(int argc, char** argv)
char *python_code = KX_GetPythonCode(maggie, python_main);
if (python_code) {
#ifdef WITH_PYTHON
+ // Set python environement variable.
+ KX_Scene *startscene = app.GetStartScene();
+ KX_SetActiveScene(startscene);
+ PHY_SetActiveEnvironment(startscene->GetPhysicsEnvironment());
+
gpg_nextframestate.system = system;
gpg_nextframestate.app = &app;
gpg_nextframestate.gs = &gs;
@@ -1125,7 +1147,7 @@ int main(int argc, char** argv)
#ifdef WITH_INTERNATIONAL
BLF_free_unifont();
BLF_free_unifont_mono();
- BLF_lang_free();
+ BLT_lang_free();
#endif
IMB_exit();
@@ -1142,7 +1164,7 @@ int main(int argc, char** argv)
MEM_printmemlist();
}
- BLI_temp_dir_session_purge();
+ BKE_tempdir_session_purge();
return error ? -1 : 0;
}
diff --git a/source/gameengine/GamePlayer/ghost/SConscript b/source/gameengine/GamePlayer/ghost/SConscript
index 3e8ab3d0dd7..be9f50f40fb 100644
--- a/source/gameengine/GamePlayer/ghost/SConscript
+++ b/source/gameengine/GamePlayer/ghost/SConscript
@@ -44,7 +44,6 @@ incs = [
'#intern/memutil',
'#intern/moto/include',
'#intern/container',
- '#intern/audaspace/intern',
'#source/gameengine/Rasterizer/RAS_OpenGLRasterizer',
'#source/gameengine/BlenderRoutines',
'#source/gameengine/Converter',
@@ -53,6 +52,7 @@ incs = [
'#source/blender/blenfont',
'#source/blender/blenlib',
'#source/blender/blenkernel',
+ '#source/blender/blentranslation',
'#source/blender',
'#source/blender/include',
'#source/blender/makesdna',
@@ -68,24 +68,32 @@ incs = [
'#source/blender/misc',
'#source/blender/blenloader',
'#source/blender/gpu',
- '#extern/glew/include',
+ env['BF_GLEW_INC'],
+ '#/intern/glew-mx',
]
incs.append(env['BF_PTHREADS_INC'])
incs.append(env['BF_BOOST_INC'])
-defs = [
- 'GLEW_STATIC',
- ]
+defs = []
+defs += env['BF_GL_DEFINITIONS']
if env['WITH_BF_PYTHON']:
incs += Split(env['BF_PYTHON_INC'])
defs.append('WITH_PYTHON')
+if env['WITH_BF_AUDASPACE']:
+ defs += env['BF_AUDASPACE_DEF']
+ incs.append(env['BF_AUDASPACE_C_INC'])
+
if env['WITH_BF_FFMPEG']:
defs.append('WITH_FFMPEG')
if env['WITH_BF_INTERNATIONAL']:
defs.append('WITH_INTERNATIONAL')
+if env['WITH_BF_SDL'] and env['WITH_BF_SDL_DYNLOAD']:
+ defs.append('WITH_SDL_DYNLOAD')
+ incs += ['#extern/sdlew/include']
+
env.BlenderLib (libname='ge_player_ghost', sources=source_files, includes = incs, defines = defs, libtype=['player'],priority=[0], cxx_compileflags=env['BGE_CXXFLAGS'])
diff --git a/source/gameengine/Ketsji/BL_Action.cpp b/source/gameengine/Ketsji/BL_Action.cpp
index a50c07a486a..12a1caee221 100644
--- a/source/gameengine/Ketsji/BL_Action.cpp
+++ b/source/gameengine/Ketsji/BL_Action.cpp
@@ -49,6 +49,7 @@ extern "C" {
// Needed for material IPOs
#include "BKE_material.h"
#include "DNA_material_types.h"
+#include "DNA_scene_types.h"
}
#include "MEM_guardedalloc.h"
@@ -162,6 +163,14 @@ bool BL_Action::Play(const char* name,
m_obj->GetSGNode()->AddSGController(sg_contr);
sg_contr->SetObject(m_obj->GetSGNode());
+ // World
+ sg_contr = BL_CreateWorldIPO(m_action, kxscene->GetBlenderScene()->world, kxscene->GetSceneConverter());
+ if (sg_contr) {
+ m_sg_contr_list.push_back(sg_contr);
+ m_obj->GetSGNode()->AddSGController(sg_contr);
+ sg_contr->SetObject(m_obj->GetSGNode());
+ }
+
// Try obcolor
sg_contr = BL_CreateObColorIPO(m_action, m_obj, kxscene->GetSceneConverter());
if (sg_contr) {
@@ -292,6 +301,18 @@ float BL_Action::GetFrame()
return m_localtime;
}
+const char *BL_Action::GetName()
+{
+ if (m_action != NULL) {
+ return m_action->id.name + 2;
+ }
+ else {
+ return "";
+ }
+
+
+}
+
void BL_Action::SetFrame(float frame)
{
// Clamp the frame to the start and end frame
diff --git a/source/gameengine/Ketsji/BL_Action.h b/source/gameengine/Ketsji/BL_Action.h
index dd1cd1f69ff..379dd52df5b 100644
--- a/source/gameengine/Ketsji/BL_Action.h
+++ b/source/gameengine/Ketsji/BL_Action.h
@@ -112,6 +112,8 @@ public:
// Accessors
float GetFrame();
+ const char *GetName();
+
struct bAction *GetAction();
// Mutators
diff --git a/source/gameengine/Ketsji/BL_ActionManager.cpp b/source/gameengine/Ketsji/BL_ActionManager.cpp
index 07adce73b4a..9e4690548d3 100644
--- a/source/gameengine/Ketsji/BL_ActionManager.cpp
+++ b/source/gameengine/Ketsji/BL_ActionManager.cpp
@@ -26,9 +26,13 @@
#include "BL_Action.h"
#include "BL_ActionManager.h"
+#include "DNA_ID.h"
+
+#define IS_TAGGED(_id) ((_id) && (((ID *)_id)->flag & LIB_DOIT))
BL_ActionManager::BL_ActionManager(class KX_GameObject *obj):
- m_obj(obj)
+ m_obj(obj),
+ m_prevUpdate(-1.0f)
{
}
@@ -64,6 +68,12 @@ float BL_ActionManager::GetActionFrame(short layer)
return action ? action->GetFrame() : 0.f;
}
+const char *BL_ActionManager::GetActionName(short layer)
+{
+ BL_Action *action = GetAction(layer);
+ return action ? action->GetName() : "";
+}
+
void BL_ActionManager::SetActionFrame(short layer, float frame)
{
BL_Action *action = GetAction(layer);
@@ -122,6 +132,18 @@ void BL_ActionManager::StopAction(short layer)
if (action) action->Stop();
}
+void BL_ActionManager::RemoveTaggedActions()
+{
+ for (BL_ActionMap::iterator it = m_layers.begin(); it != m_layers.end();) {
+ if (IS_TAGGED(it->second->GetAction())) {
+ delete it->second;
+ m_layers.erase(it++);
+ }
+ else
+ ++it;
+ }
+}
+
bool BL_ActionManager::IsActionDone(short layer)
{
BL_Action *action = GetAction(layer);
@@ -131,6 +153,10 @@ bool BL_ActionManager::IsActionDone(short layer)
void BL_ActionManager::Update(float curtime)
{
+ if (m_prevUpdate == curtime)
+ return;
+ m_prevUpdate = curtime;
+
BL_ActionMap::iterator it;
for (it = m_layers.begin(); it != m_layers.end(); )
{
diff --git a/source/gameengine/Ketsji/BL_ActionManager.h b/source/gameengine/Ketsji/BL_ActionManager.h
index 5b340257881..97d6d88cf22 100644
--- a/source/gameengine/Ketsji/BL_ActionManager.h
+++ b/source/gameengine/Ketsji/BL_ActionManager.h
@@ -20,7 +20,7 @@
* ***** END GPL LICENSE BLOCK *****
*/
-/** \file BL_ActionManager.cpp
+/** \file BL_ActionManager.h
* \ingroup ketsji
*/
@@ -51,6 +51,9 @@ private:
class KX_GameObject* m_obj;
BL_ActionMap m_layers;
+ // The last update time to avoid double animation update.
+ float m_prevUpdate;
+
/**
* Check if an action exists
*/
@@ -82,6 +85,11 @@ public:
float GetActionFrame(short layer);
/**
+ * Gets the name of the current action
+ */
+ const char *GetActionName(short layer);
+
+ /**
* Sets the current frame of an action
*/
void SetActionFrame(short layer, float frame);
@@ -107,6 +115,11 @@ public:
void StopAction(short layer);
/**
+ * Remove playing tagged actions.
+ */
+ void RemoveTaggedActions();
+
+ /**
* Check if an action has finished playing
*/
bool IsActionDone(short layer);
diff --git a/source/gameengine/Ketsji/BL_BlenderShader.cpp b/source/gameengine/Ketsji/BL_BlenderShader.cpp
index bcdef85bc8a..b5151615f3b 100644
--- a/source/gameengine/Ketsji/BL_BlenderShader.cpp
+++ b/source/gameengine/Ketsji/BL_BlenderShader.cpp
@@ -62,7 +62,7 @@ BL_BlenderShader::~BL_BlenderShader()
void BL_BlenderShader::ReloadMaterial()
{
- mGPUMat = (mMat) ? GPU_material_from_blender(mBlenderScene, mMat) : NULL;
+ mGPUMat = (mMat) ? GPU_material_from_blender(mBlenderScene, mMat, false) : NULL;
}
void BL_BlenderShader::SetProg(bool enable, double time, RAS_IRasterizer* rasty)
@@ -77,7 +77,7 @@ void BL_BlenderShader::SetProg(bool enable, double time, RAS_IRasterizer* rasty)
view.getValue((float*)viewmat);
viewinv.getValue((float*)viewinvmat);
- GPU_material_bind(mGPUMat, mLightLayer, mBlenderScene->lay, time, 1, viewmat, viewinvmat, false);
+ GPU_material_bind(mGPUMat, mLightLayer, mBlenderScene->lay, time, 1, viewmat, viewinvmat, NULL, false);
}
else
GPU_material_unbind(mGPUMat);
@@ -168,7 +168,7 @@ void BL_BlenderShader::Update(const RAS_MeshSlot & ms, RAS_IRasterizer* rasty )
obcol[0] = obcol[1] = obcol[2] = obcol[3] = 1.0f;
float auto_bump_scale = ms.m_pDerivedMesh!=0 ? ms.m_pDerivedMesh->auto_bump_scale : 1.0f;
- GPU_material_bind_uniforms(gpumat, obmat, obcol, auto_bump_scale);
+ GPU_material_bind_uniforms(gpumat, obmat, obcol, auto_bump_scale, NULL);
mAlphaBlend = GPU_material_alpha_blend(gpumat, obcol);
}
diff --git a/source/gameengine/Ketsji/BL_Material.cpp b/source/gameengine/Ketsji/BL_Material.cpp
index 006c1f7202c..4f707e6267f 100644
--- a/source/gameengine/Ketsji/BL_Material.cpp
+++ b/source/gameengine/Ketsji/BL_Material.cpp
@@ -47,10 +47,10 @@ BL_Material::BL_Material()
void BL_Material::Initialize()
{
- rgb[0] = 0;
- rgb[1] = 0;
- rgb[2] = 0;
- rgb[3] = 0;
+ rgb[0] = 0xFFFFFFFFL;
+ rgb[1] = 0xFFFFFFFFL;
+ rgb[2] = 0xFFFFFFFFL;
+ rgb[3] = 0xFFFFFFFFL;
IdMode = 0;
ras_mode = 0;
glslmat = 0;
@@ -69,7 +69,7 @@ void BL_Material::Initialize()
alpha = 1.f;
emit = 0.f;
material = 0;
- memset(&tface, 0, sizeof(tface));
+ memset(&mtexpoly, 0, sizeof(mtexpoly));
materialindex = 0;
amb=0.5f;
num_enabled = 0;
diff --git a/source/gameengine/Ketsji/BL_Material.h b/source/gameengine/Ketsji/BL_Material.h
index 83f9b601e0d..9207a41f56d 100644
--- a/source/gameengine/Ketsji/BL_Material.h
+++ b/source/gameengine/Ketsji/BL_Material.h
@@ -84,7 +84,7 @@ public:
Material* material;
- MTFace tface; /* copy of the derived meshes tface */
+ MTexPoly mtexpoly; /* copy of the derived meshes tface */
Image* img[MAXTEX];
EnvMap* cubemap[MAXTEX];
diff --git a/source/gameengine/Ketsji/BL_Shader.cpp b/source/gameengine/Ketsji/BL_Shader.cpp
index 872ac19351d..a59c3686a18 100644
--- a/source/gameengine/Ketsji/BL_Shader.cpp
+++ b/source/gameengine/Ketsji/BL_Shader.cpp
@@ -22,7 +22,7 @@
* \ingroup ketsji
*/
-#include "GL/glew.h"
+#include "glew-mx.h"
#include <iostream>
#include "BL_Shader.h"
diff --git a/source/gameengine/Ketsji/BL_Shader.h b/source/gameengine/Ketsji/BL_Shader.h
index 4c671d0c9a3..e3dc4b19773 100644
--- a/source/gameengine/Ketsji/BL_Shader.h
+++ b/source/gameengine/Ketsji/BL_Shader.h
@@ -6,7 +6,7 @@
#ifndef __BL_SHADER_H__
#define __BL_SHADER_H__
-#include "PyObjectPlus.h"
+#include "EXP_PyObjectPlus.h"
#include "BL_Material.h"
#include "BL_Texture.h"
// --
diff --git a/source/gameengine/Ketsji/BL_Texture.cpp b/source/gameengine/Ketsji/BL_Texture.cpp
index 1578c745b9f..8f717c05c0f 100644
--- a/source/gameengine/Ketsji/BL_Texture.cpp
+++ b/source/gameengine/Ketsji/BL_Texture.cpp
@@ -22,7 +22,7 @@
* \ingroup ketsji
*/
-#include "GL/glew.h"
+#include "glew-mx.h"
#include <iostream>
#include <map>
@@ -170,7 +170,7 @@ bool BL_Texture::InitFromImage(int unit, Image *img, bool mipmap)
glGenTextures(1, (GLuint*)&mTexture);
#ifdef WITH_DDS
- if (ibuf->ftype & DDS)
+ if (ibuf->ftype == IMB_FTYPE_DDS)
InitGLCompressedTex(ibuf, mipmap);
else
InitGLTex(ibuf->rect, ibuf->x, ibuf->y, mipmap);
@@ -203,9 +203,21 @@ void BL_Texture::InitGLTex(unsigned int *pix,int x,int y,bool mipmap)
glBindTexture(GL_TEXTURE_2D, mTexture );
if ( mipmap ) {
+ int i;
+ ImBuf *ibuf;
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- gluBuild2DMipmaps( GL_TEXTURE_2D, GL_RGBA, x, y, GL_RGBA, GL_UNSIGNED_BYTE, pix );
+
+ ibuf = IMB_allocFromBuffer(pix, NULL, x, y);
+
+ IMB_makemipmap(ibuf, true);
+
+ for (i = 0; i < ibuf->miptot; i++) {
+ ImBuf *mip = IMB_getmipmap(ibuf, i);
+
+ glTexImage2D(GL_TEXTURE_2D, i, GL_RGBA, mip->x, mip->y, 0, GL_RGBA, GL_UNSIGNED_BYTE, mip->rect);
+ }
+ IMB_freeImBuf(ibuf);
}
else {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
@@ -239,26 +251,34 @@ void BL_Texture::InitNonPow2Tex(unsigned int *pix,int x,int y,bool mipmap)
int nx= power_of_2_min_i(x);
int ny= power_of_2_min_i(y);
- unsigned int *newPixels = (unsigned int *)malloc(nx*ny*sizeof(unsigned int));
-
- gluScaleImage(GL_RGBA, x, y, GL_UNSIGNED_BYTE, pix, nx,ny, GL_UNSIGNED_BYTE, newPixels);
+ ImBuf *ibuf = IMB_allocFromBuffer(pix, NULL, x, y);
+ IMB_scaleImBuf(ibuf, nx, ny);
+
glBindTexture(GL_TEXTURE_2D, mTexture );
if ( mipmap ) {
+ int i;
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- gluBuild2DMipmaps( GL_TEXTURE_2D, GL_RGBA, nx, ny, GL_RGBA, GL_UNSIGNED_BYTE, newPixels );
+
+ IMB_makemipmap(ibuf, true);
+
+ for (i = 0; i < ibuf->miptot; i++) {
+ ImBuf *mip = IMB_getmipmap(ibuf, i);
+
+ glTexImage2D(GL_TEXTURE_2D, i, GL_RGBA, mip->x, mip->y, 0, GL_RGBA, GL_UNSIGNED_BYTE, mip->rect);
+ }
}
else {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, nx, ny, 0, GL_RGBA, GL_UNSIGNED_BYTE, newPixels );
+ glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, nx, ny, 0, GL_RGBA, GL_UNSIGNED_BYTE, ibuf->rect );
}
if (GLEW_EXT_texture_filter_anisotropic)
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, GPU_get_anisotropic());
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
- free(newPixels);
+ IMB_freeImBuf(ibuf);
}
@@ -400,13 +420,16 @@ unsigned int BL_Texture::GetTextureType() const
int BL_Texture::GetMaxUnits()
{
if (g_max_units < 0) {
- GLint unit;
- if (GLEW_ARB_multitexture) {
+ GLint unit = 0;
+
+ if (GPU_glsl_support()) {
+ glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS_ARB, &unit);
+ }
+ else if (GLEW_ARB_multitexture) {
glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &unit);
- g_max_units = (MAXTEX>=unit)?unit:MAXTEX;
- } else {
- g_max_units = 0;
}
+
+ g_max_units = (MAXTEX >= unit) ? unit : MAXTEX;
}
return g_max_units;
diff --git a/source/gameengine/Ketsji/CMakeLists.txt b/source/gameengine/Ketsji/CMakeLists.txt
index 03d1524b310..2607e2bb4b7 100644
--- a/source/gameengine/Ketsji/CMakeLists.txt
+++ b/source/gameengine/Ketsji/CMakeLists.txt
@@ -49,6 +49,7 @@ set(INC
../../blender/python/generic
../../blender/python/mathutils
../../../intern/container
+ ../../../intern/glew-mx
../../../intern/guardedalloc
../../../intern/string
)
@@ -229,7 +230,7 @@ set(SRC
)
-add_definitions(-DGLEW_STATIC)
+add_definitions(${GL_DEFINITIONS})
if(WITH_IMAGE_DDS)
add_definitions(-DWITH_DDS)
@@ -247,11 +248,12 @@ if(WITH_CODEC_FFMPEG)
endif()
if(WITH_AUDASPACE)
- list(APPEND INC
- ../../../intern/audaspace/intern
- ../../../intern/audaspace/FX
+ add_definitions(${AUDASPACE_DEFINITIONS})
+
+ list(APPEND INC_SYS
+ ${AUDASPACE_C_INCLUDE_DIRS}
+ ${AUDASPACE_PY_INCLUDE_DIRS}
)
- add_definitions(-DWITH_AUDASPACE)
endif()
if(WITH_BULLET)
diff --git a/source/gameengine/Ketsji/KXNetwork/CMakeLists.txt b/source/gameengine/Ketsji/KXNetwork/CMakeLists.txt
index 0c661cf2c87..cfc6ded4e65 100644
--- a/source/gameengine/Ketsji/KXNetwork/CMakeLists.txt
+++ b/source/gameengine/Ketsji/KXNetwork/CMakeLists.txt
@@ -30,6 +30,7 @@ set(INC
../../GameLogic
../../Network
../../SceneGraph
+ ../../../blender/blenlib
../../../../intern/container
../../../../intern/string
)
diff --git a/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.cpp b/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.cpp
index 6260596159d..1fadd9382e0 100644
--- a/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.cpp
+++ b/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.cpp
@@ -39,9 +39,9 @@
#include "NG_NetworkScene.h"
#include "NG_NetworkObject.h"
#include "SCA_IObject.h"
-#include "InputParser.h"
-#include "ListValue.h"
-#include "StringValue.h"
+#include "EXP_InputParser.h"
+#include "EXP_ListValue.h"
+#include "EXP_StringValue.h"
#ifdef NAN_NET_DEBUG
#include <iostream>
diff --git a/source/gameengine/Ketsji/KXNetwork/SConscript b/source/gameengine/Ketsji/KXNetwork/SConscript
index 355dcc4f78f..ab03e03e74d 100644
--- a/source/gameengine/Ketsji/KXNetwork/SConscript
+++ b/source/gameengine/Ketsji/KXNetwork/SConscript
@@ -39,6 +39,7 @@ incs = [
'#source/gameengine/Ketsji',
'#source/gameengine/Network',
'#source/gameengine/SceneGraph',
+ '../../../blender/blenlib',
]
incs = ' '.join(incs)
diff --git a/source/gameengine/Ketsji/KX_BlenderMaterial.cpp b/source/gameengine/Ketsji/KX_BlenderMaterial.cpp
index 9ebdfea6156..d85d33d9834 100644
--- a/source/gameengine/Ketsji/KX_BlenderMaterial.cpp
+++ b/source/gameengine/Ketsji/KX_BlenderMaterial.cpp
@@ -22,7 +22,7 @@
* \ingroup ketsji
*/
-#include "GL/glew.h"
+#include "glew-mx.h"
#include "KX_BlenderMaterial.h"
#include "BL_Material.h"
@@ -30,6 +30,7 @@
#include "KX_Light.h"
#include "KX_GameObject.h"
#include "KX_MeshProxy.h"
+#include "KX_PyMath.h"
#include "MT_Vector3.h"
#include "MT_Vector4.h"
@@ -52,6 +53,7 @@
#include "BKE_mesh.h"
// ------------------------------------
#include "BLI_utildefines.h"
+#include "BLI_math.h"
#define spit(x) std::cout << x << std::endl;
@@ -94,6 +96,21 @@ void KX_BlenderMaterial::Initialize(
((data->ras_mode &TEX)),
game
);
+ Material *ma = data->material;
+
+ // Save material data to restore on exit
+ mSavedData.r = ma->r;
+ mSavedData.g = ma->g;
+ mSavedData.b = ma->b;
+ mSavedData.a = ma->alpha;
+ mSavedData.specr = ma->specr;
+ mSavedData.specg = ma->specg;
+ mSavedData.specb = ma->specb;
+ mSavedData.spec = ma->spec;
+ mSavedData.ref = ma->ref;
+ mSavedData.hardness = ma->har;
+ mSavedData.emit = ma->emit;
+
mMaterial = data;
mShader = 0;
mBlenderShader = 0;
@@ -124,16 +141,30 @@ void KX_BlenderMaterial::Initialize(
KX_BlenderMaterial::~KX_BlenderMaterial()
{
+ Material *ma = mMaterial->material;
+ // Restore Blender material data
+ ma->r = mSavedData.r;
+ ma->g = mSavedData.g;
+ ma->b = mSavedData.b;
+ ma->alpha = mSavedData.a;
+ ma->specr = mSavedData.specr;
+ ma->specg = mSavedData.specg;
+ ma->specb = mSavedData.specb;
+ ma->spec = mSavedData.spec;
+ ma->ref = mSavedData.ref;
+ ma->har = mSavedData.hardness;
+ ma->emit = mSavedData.emit;
+
// cleanup work
if (mConstructed)
// clean only if material was actually used
OnExit();
}
-MTFace* KX_BlenderMaterial::GetMTFace() const
+MTexPoly *KX_BlenderMaterial::GetMTexPoly() const
{
// fonts on polys
- return &mMaterial->tface;
+ return &mMaterial->mtexpoly;
}
unsigned int* KX_BlenderMaterial::GetMCol() const
@@ -160,7 +191,7 @@ Material *KX_BlenderMaterial::GetBlenderMaterial() const
Image *KX_BlenderMaterial::GetBlenderImage() const
{
- return mMaterial->tface.tpage;
+ return mMaterial->mtexpoly.tpage;
}
Scene* KX_BlenderMaterial::GetBlenderScene() const
@@ -793,17 +824,19 @@ void KX_BlenderMaterial::UpdateIPO(
)
{
// only works one deep now
- mMaterial->speccolor[0] = (float)(specrgb)[0];
- mMaterial->speccolor[1] = (float)(specrgb)[1];
- mMaterial->speccolor[2] = (float)(specrgb)[2];
- mMaterial->matcolor[0] = (float)(rgba[0]);
- mMaterial->matcolor[1] = (float)(rgba[1]);
- mMaterial->matcolor[2] = (float)(rgba[2]);
- mMaterial->alpha = (float)(alpha);
- mMaterial->hard = (float)(hard);
- mMaterial->emit = (float)(emit);
- mMaterial->spec_f = (float)(spec);
- mMaterial->ref = (float)(ref);
+
+ // GLSL Multitexture Input
+ mMaterial->material->specr = mMaterial->speccolor[0] = (float)(specrgb)[0];
+ mMaterial->material->specg = mMaterial->speccolor[1] = (float)(specrgb)[1];
+ mMaterial->material->specb = mMaterial->speccolor[2] = (float)(specrgb)[2];
+ mMaterial->material->r = mMaterial->matcolor[0] = (float)(rgba[0]);
+ mMaterial->material->g = mMaterial->matcolor[1] = (float)(rgba[1]);
+ mMaterial->material->b = mMaterial->matcolor[2] = (float)(rgba[2]);
+ mMaterial->material->alpha = mMaterial->alpha = (float)(rgba[3]);
+ mMaterial->material->har = mMaterial->hard = (float)(hard);
+ mMaterial->material->emit = mMaterial->emit = (float)(emit);
+ mMaterial->material->spec = mMaterial->spec_f = (float)(spec);
+ mMaterial->material->ref = mMaterial->ref = (float)(ref);
}
void KX_BlenderMaterial::Replace_IScene(SCA_IScene *val)
@@ -813,6 +846,11 @@ void KX_BlenderMaterial::Replace_IScene(SCA_IScene *val)
OnConstruction();
}
+BL_Material *KX_BlenderMaterial::GetBLMaterial()
+{
+ return mMaterial;
+}
+
void KX_BlenderMaterial::SetBlenderGLSLShader()
{
if (!mBlenderShader)
@@ -824,6 +862,111 @@ void KX_BlenderMaterial::SetBlenderGLSLShader()
}
}
+#ifdef USE_MATHUTILS
+
+#define MATHUTILS_COL_CB_MATERIAL_SPECULAR_COLOR 1
+#define MATHUTILS_COL_CB_MATERIAL_DIFFUSE_COLOR 2
+
+static unsigned char mathutils_kxblendermaterial_color_cb_index = -1; /* index for our callbacks */
+
+static int mathutils_kxblendermaterial_generic_check(BaseMathObject *bmo)
+{
+ KX_BlenderMaterial *self = static_cast<KX_BlenderMaterial *>BGE_PROXY_REF(bmo->cb_user);
+ if (!self)
+ return -1;
+
+ return 0;
+}
+
+static int mathutils_kxblendermaterial_color_get(BaseMathObject *bmo, int subtype)
+{
+ KX_BlenderMaterial *self = static_cast<KX_BlenderMaterial*>BGE_PROXY_REF(bmo->cb_user);
+ if (!self)
+ return -1;
+
+ switch (subtype) {
+ case MATHUTILS_COL_CB_MATERIAL_DIFFUSE_COLOR:
+ {
+ copy_v3_v3(bmo->data, self->GetBLMaterial()->matcolor);
+ break;
+ }
+ case MATHUTILS_COL_CB_MATERIAL_SPECULAR_COLOR:
+ {
+ copy_v3_v3(bmo->data, self->GetBLMaterial()->speccolor);
+ break;
+ }
+ }
+
+ return 0;
+}
+
+static int mathutils_kxblendermaterial_color_set(BaseMathObject *bmo, int subtype)
+{
+ KX_BlenderMaterial *self = static_cast<KX_BlenderMaterial *>BGE_PROXY_REF(bmo->cb_user);
+ if (!self)
+ return -1;
+
+ switch (subtype) {
+ case MATHUTILS_COL_CB_MATERIAL_DIFFUSE_COLOR:
+ {
+ BL_Material *mat = self->GetBLMaterial();
+ copy_v3_v3(mat->matcolor, bmo->data);
+ mat->material->r = bmo->data[0];
+ mat->material->g = bmo->data[1];
+ mat->material->b = bmo->data[2];
+ break;
+ }
+ case MATHUTILS_COL_CB_MATERIAL_SPECULAR_COLOR:
+ {
+ BL_Material *mat = self->GetBLMaterial();
+ copy_v3_v3(mat->speccolor, bmo->data);
+ mat->material->specr = bmo->data[0];
+ mat->material->specg = bmo->data[1];
+ mat->material->specb = bmo->data[2];
+ break;
+ }
+ }
+
+ return 0;
+}
+
+static int mathutils_kxblendermaterial_color_get_index(BaseMathObject *bmo, int subtype, int index)
+{
+ /* lazy, avoid repeteing the case statement */
+ if (mathutils_kxblendermaterial_color_get(bmo, subtype) == -1)
+ return -1;
+ return 0;
+}
+
+static int mathutils_kxblendermaterial_color_set_index(BaseMathObject *bmo, int subtype, int index)
+{
+ float f = bmo->data[index];
+
+ /* lazy, avoid repeateing the case statement */
+ if (mathutils_kxblendermaterial_color_get(bmo, subtype) == -1)
+ return -1;
+
+ bmo->data[index] = f;
+ return mathutils_kxblendermaterial_color_set(bmo, subtype);
+}
+
+static Mathutils_Callback mathutils_kxblendermaterial_color_cb = {
+ mathutils_kxblendermaterial_generic_check,
+ mathutils_kxblendermaterial_color_get,
+ mathutils_kxblendermaterial_color_set,
+ mathutils_kxblendermaterial_color_get_index,
+ mathutils_kxblendermaterial_color_set_index
+};
+
+
+void KX_BlenderMaterial_Mathutils_Callback_Init()
+{
+ // register mathutils callbacks, ok to run more than once.
+ mathutils_kxblendermaterial_color_cb_index = Mathutils_RegisterCallback(&mathutils_kxblendermaterial_color_cb);
+}
+
+#endif // USE_MATHUTILS
+
#ifdef WITH_PYTHON
PyMethodDef KX_BlenderMaterial::Methods[] =
@@ -838,6 +981,14 @@ PyAttributeDef KX_BlenderMaterial::Attributes[] = {
KX_PYATTRIBUTE_RO_FUNCTION("shader", KX_BlenderMaterial, pyattr_get_shader),
KX_PYATTRIBUTE_RO_FUNCTION("material_index", KX_BlenderMaterial, pyattr_get_materialIndex),
KX_PYATTRIBUTE_RW_FUNCTION("blending", KX_BlenderMaterial, pyattr_get_blending, pyattr_set_blending),
+ KX_PYATTRIBUTE_RW_FUNCTION("alpha", KX_BlenderMaterial, pyattr_get_alpha, pyattr_set_alpha),
+ KX_PYATTRIBUTE_RW_FUNCTION("hardness", KX_BlenderMaterial, pyattr_get_hardness, pyattr_set_hardness),
+ KX_PYATTRIBUTE_RW_FUNCTION("specularIntensity", KX_BlenderMaterial, pyattr_get_specular_intensity, pyattr_set_specular_intensity),
+ KX_PYATTRIBUTE_RW_FUNCTION("specularColor", KX_BlenderMaterial, pyattr_get_specular_color, pyattr_set_specular_color),
+ KX_PYATTRIBUTE_RW_FUNCTION("diffuseIntensity", KX_BlenderMaterial, pyattr_get_diffuse_intensity, pyattr_set_diffuse_intensity),
+ KX_PYATTRIBUTE_RW_FUNCTION("diffuseColor", KX_BlenderMaterial, pyattr_get_diffuse_color, pyattr_set_diffuse_color),
+ KX_PYATTRIBUTE_RW_FUNCTION("emit", KX_BlenderMaterial, pyattr_get_emit, pyattr_set_emit),
+
{ NULL } //Sentinel
};
@@ -882,6 +1033,170 @@ PyObject *KX_BlenderMaterial::pyattr_get_blending(void *self_v, const KX_PYATTRI
return Py_BuildValue("(ll)", (long int)bfunc[0], (long int)bfunc[1]);
}
+PyObject *KX_BlenderMaterial::pyattr_get_alpha(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+{
+ KX_BlenderMaterial *self = static_cast<KX_BlenderMaterial *>(self_v);
+ return PyFloat_FromDouble(self->GetBLMaterial()->alpha);
+}
+
+int KX_BlenderMaterial::pyattr_set_alpha(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
+{
+ KX_BlenderMaterial *self = static_cast<KX_BlenderMaterial *>(self_v);
+ float val = PyFloat_AsDouble(value);
+
+ if (val == -1 && PyErr_Occurred()) {
+ PyErr_Format(PyExc_AttributeError, "material.%s = float: KX_BlenderMaterial, expected a float", attrdef->m_name);
+ return PY_SET_ATTR_FAIL;
+ }
+
+ CLAMP(val, 0.0f, 1.0f);
+
+ BL_Material *mat = self->GetBLMaterial();
+ mat->alpha = mat->material->alpha = val;
+ return PY_SET_ATTR_SUCCESS;
+}
+PyObject *KX_BlenderMaterial::pyattr_get_hardness(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+{
+ KX_BlenderMaterial *self = static_cast<KX_BlenderMaterial *>(self_v);
+ return PyLong_FromLong(self->GetBLMaterial()->hard);
+}
+
+int KX_BlenderMaterial::pyattr_set_hardness(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
+{
+ KX_BlenderMaterial *self = static_cast<KX_BlenderMaterial *>(self_v);
+ int val = PyLong_AsLong(value);
+
+ if (val == -1 && PyErr_Occurred()) {
+ PyErr_Format(PyExc_AttributeError, "material.%s = int: KX_BlenderMaterial, expected a int", attrdef->m_name);
+ return PY_SET_ATTR_FAIL;
+ }
+
+ CLAMP(val, 1, 511);
+
+ BL_Material *mat = self->GetBLMaterial();
+ mat->hard = mat->material->har = val;
+ return PY_SET_ATTR_SUCCESS;
+}
+
+PyObject *KX_BlenderMaterial::pyattr_get_specular_intensity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+{
+ KX_BlenderMaterial *self = static_cast<KX_BlenderMaterial *>(self_v);
+ return PyFloat_FromDouble(self->GetBLMaterial()->spec_f);
+}
+
+int KX_BlenderMaterial::pyattr_set_specular_intensity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
+{
+ KX_BlenderMaterial *self = static_cast<KX_BlenderMaterial *>(self_v);
+ float val = PyFloat_AsDouble(value);
+
+ if (val == -1 && PyErr_Occurred()) {
+ PyErr_Format(PyExc_AttributeError, "material.%s = float: KX_BlenderMaterial, expected a float", attrdef->m_name);
+ return PY_SET_ATTR_FAIL;
+ }
+
+ CLAMP(val, 0.0f, 1.0f);
+
+ BL_Material *mat = self->GetBLMaterial();
+ mat->spec_f = mat->material->spec = val;
+ return PY_SET_ATTR_SUCCESS;
+}
+
+PyObject *KX_BlenderMaterial::pyattr_get_specular_color(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+{
+#ifdef USE_MATHUTILS
+ return Color_CreatePyObject_cb(BGE_PROXY_FROM_REF(self_v), mathutils_kxblendermaterial_color_cb_index, MATHUTILS_COL_CB_MATERIAL_SPECULAR_COLOR);
+#else
+ KX_BlenderMaterial *self = static_cast<KX_BlenderMaterial *>(self_v);
+ return PyColorFromVector(MT_Vector3(self->GetBLMaterial()->speccolor));
+#endif
+}
+
+int KX_BlenderMaterial::pyattr_set_specular_color(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
+{
+ KX_BlenderMaterial *self = static_cast<KX_BlenderMaterial *>(self_v);
+ MT_Vector3 color;
+ if (!PyVecTo(value, color))
+ return PY_SET_ATTR_FAIL;
+
+ BL_Material *mat = self->GetBLMaterial();
+ color.getValue(mat->speccolor);
+ mat->material->specr = color[0];
+ mat->material->specg = color[1];
+ mat->material->specb = color[2];
+ return PY_SET_ATTR_SUCCESS;
+}
+
+PyObject *KX_BlenderMaterial::pyattr_get_diffuse_intensity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+{
+ KX_BlenderMaterial *self = static_cast<KX_BlenderMaterial *>(self_v);
+ return PyFloat_FromDouble(self->GetBLMaterial()->ref);
+}
+
+int KX_BlenderMaterial::pyattr_set_diffuse_intensity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
+{
+ KX_BlenderMaterial *self = static_cast<KX_BlenderMaterial *>(self_v);
+ float val = PyFloat_AsDouble(value);
+
+ if (val == -1 && PyErr_Occurred()) {
+ PyErr_Format(PyExc_AttributeError, "material.%s = float: KX_BlenderMaterial, expected a float", attrdef->m_name);
+ return PY_SET_ATTR_FAIL;
+ }
+
+ CLAMP(val, 0.0f, 1.0f);
+
+ BL_Material *mat = self->GetBLMaterial();
+ mat->ref = mat->material->ref = val;
+ return PY_SET_ATTR_SUCCESS;
+}
+
+PyObject *KX_BlenderMaterial::pyattr_get_diffuse_color(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+{
+#ifdef USE_MATHUTILS
+ return Color_CreatePyObject_cb(BGE_PROXY_FROM_REF(self_v), mathutils_kxblendermaterial_color_cb_index, MATHUTILS_COL_CB_MATERIAL_DIFFUSE_COLOR);
+#else
+ KX_BlenderMaterial *self = static_cast<KX_BlenderMaterial *>(self_v);
+ return PyColorFromVector(MT_Vector3(self->GetBLMaterial()->matcolor));
+#endif
+}
+
+int KX_BlenderMaterial::pyattr_set_diffuse_color(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
+{
+ KX_BlenderMaterial *self = static_cast<KX_BlenderMaterial *>(self_v);
+ MT_Vector3 color;
+ if (!PyVecTo(value, color))
+ return PY_SET_ATTR_FAIL;
+
+ BL_Material *mat = self->GetBLMaterial();
+ color.getValue(mat->matcolor);
+ mat->material->r = color[0];
+ mat->material->g = color[1];
+ mat->material->b = color[2];
+ return PY_SET_ATTR_SUCCESS;
+}
+
+PyObject *KX_BlenderMaterial::pyattr_get_emit(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+{
+ KX_BlenderMaterial *self = static_cast<KX_BlenderMaterial *>(self_v);
+ return PyFloat_FromDouble(self->GetBLMaterial()->emit);
+}
+
+int KX_BlenderMaterial::pyattr_set_emit(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
+{
+ KX_BlenderMaterial *self = static_cast<KX_BlenderMaterial *>(self_v);
+ float val = PyFloat_AsDouble(value);
+
+ if (val == -1 && PyErr_Occurred()) {
+ PyErr_Format(PyExc_AttributeError, "material.%s = float: KX_BlenderMaterial, expected a float", attrdef->m_name);
+ return PY_SET_ATTR_FAIL;
+ }
+
+ CLAMP(val, 0.0f, 2.0f);
+
+ BL_Material *mat = self->GetBLMaterial();
+ mat->emit = mat->material->emit = val;
+ return PY_SET_ATTR_SUCCESS;
+}
+
int KX_BlenderMaterial::pyattr_set_blending(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
{
KX_BlenderMaterial* self = static_cast<KX_BlenderMaterial*>(self_v);
diff --git a/source/gameengine/Ketsji/KX_BlenderMaterial.h b/source/gameengine/Ketsji/KX_BlenderMaterial.h
index b7c64215eaf..df089cb7f99 100644
--- a/source/gameengine/Ketsji/KX_BlenderMaterial.h
+++ b/source/gameengine/Ketsji/KX_BlenderMaterial.h
@@ -15,7 +15,7 @@
#include "BL_Shader.h"
#include "BL_BlenderShader.h"
-#include "PyObjectPlus.h"
+#include "EXP_PyObjectPlus.h"
#include "MT_Vector3.h"
#include "MT_Vector4.h"
@@ -30,6 +30,11 @@
struct MTFace;
class KX_Scene;
+
+#ifdef USE_MATHUTILS
+void KX_BlenderMaterial_Mathutils_Callback_Init(void);
+#endif
+
class KX_BlenderMaterial : public PyObjectPlus, public RAS_IPolyMaterial
{
Py_Header
@@ -79,7 +84,7 @@ public:
Material* GetBlenderMaterial() const;
Image* GetBlenderImage() const;
- MTFace* GetMTFace() const;
+ MTexPoly *GetMTexPoly() const;
unsigned int* GetMCol() const;
BL_Texture * getTex (unsigned int idx) {
return (idx < MAXTEX) ? mTextures + idx : NULL;
@@ -99,6 +104,8 @@ public:
virtual void Replace_IScene(SCA_IScene *val);
+ BL_Material *GetBLMaterial();
+
#ifdef WITH_PYTHON
// --------------------------------
virtual PyObject *py_repr(void) { return PyUnicode_From_STR_String(mMaterial->matname); }
@@ -107,6 +114,20 @@ public:
static PyObject *pyattr_get_materialIndex(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
static PyObject *pyattr_get_blending(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
static int pyattr_set_blending(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
+ static PyObject *pyattr_get_alpha(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+ static int pyattr_set_alpha(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
+ static PyObject *pyattr_get_hardness(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+ static int pyattr_set_hardness(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
+ static PyObject *pyattr_get_specular_intensity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+ static int pyattr_set_specular_intensity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
+ static PyObject *pyattr_get_specular_color(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+ static int pyattr_set_specular_color(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
+ static PyObject *pyattr_get_diffuse_intensity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+ static int pyattr_set_diffuse_intensity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
+ static PyObject *pyattr_get_diffuse_color(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+ static int pyattr_set_diffuse_color(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
+ static PyObject *pyattr_get_emit(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+ static int pyattr_set_emit(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
KX_PYMETHOD_DOC(KX_BlenderMaterial, getShader);
KX_PYMETHOD_DOC(KX_BlenderMaterial, getMaterialIndex);
@@ -134,6 +155,15 @@ private:
bool mConstructed; // if false, don't clean on exit
int mLightLayer;
+ struct {
+ float r, g, b, a;
+ float specr, specg, specb;
+ float spec;
+ float ref;
+ float hardness;
+ float emit;
+ } mSavedData;
+
void InitTextures();
void SetBlenderGLSLShader();
diff --git a/source/gameengine/Ketsji/KX_Camera.cpp b/source/gameengine/Ketsji/KX_Camera.cpp
index 4ab768e4240..644c71a68e4 100644
--- a/source/gameengine/Ketsji/KX_Camera.cpp
+++ b/source/gameengine/Ketsji/KX_Camera.cpp
@@ -31,11 +31,11 @@
*/
-#include "GL/glew.h"
+#include "glew-mx.h"
#include "KX_Camera.h"
#include "KX_Scene.h"
#include "KX_PythonInit.h"
-#include "KX_Python.h"
+#include "EXP_Python.h"
#include "KX_PyMath.h"
#include "RAS_ICanvas.h"
@@ -224,6 +224,22 @@ short KX_Camera::GetSensorFit() const
return m_camdata.m_sensor_fit;
}
+/**
+ * Gets the horizontal shift of the sensor - for camera matching.
+ */
+float KX_Camera::GetShiftHorizontal() const
+{
+ return m_camdata.m_shift_x;
+}
+
+/**
+ * Gets the vertical shift of the sensor - for camera matching.
+ */
+float KX_Camera::GetShiftVertical() const
+{
+ return m_camdata.m_shift_y;
+}
+
float KX_Camera::GetCameraNear() const
{
return m_camdata.m_clipstart;
@@ -463,6 +479,7 @@ bool KX_Camera::GetFrustumCulling() const
void KX_Camera::EnableViewport(bool viewport)
{
+ InvalidateProjectionMatrix(false); // We need to reset projection matrix
m_camdata.m_viewport = viewport;
}
@@ -528,7 +545,9 @@ PyAttributeDef KX_Camera::Attributes[] = {
KX_PYATTRIBUTE_RW_FUNCTION("ortho_scale", KX_Camera, pyattr_get_ortho_scale, pyattr_set_ortho_scale),
KX_PYATTRIBUTE_RW_FUNCTION("near", KX_Camera, pyattr_get_near, pyattr_set_near),
KX_PYATTRIBUTE_RW_FUNCTION("far", KX_Camera, pyattr_get_far, pyattr_set_far),
-
+ KX_PYATTRIBUTE_RW_FUNCTION("shift_x", KX_Camera, pyattr_get_shift_x, pyattr_set_shift_x),
+ KX_PYATTRIBUTE_RW_FUNCTION("shift_y", KX_Camera, pyattr_get_shift_y, pyattr_set_shift_y),
+
KX_PYATTRIBUTE_RW_FUNCTION("useViewport", KX_Camera, pyattr_get_use_viewport, pyattr_set_use_viewport),
KX_PYATTRIBUTE_RW_FUNCTION("projection_matrix", KX_Camera, pyattr_get_projection_matrix, pyattr_set_projection_matrix),
@@ -747,7 +766,7 @@ int KX_Camera::pyattr_set_lens(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef,
KX_Camera* self = static_cast<KX_Camera*>(self_v);
float param = PyFloat_AsDouble(value);
if (param == -1) {
- PyErr_SetString(PyExc_AttributeError, "camera.lens = float: KX_Camera, expected a float greater then zero");
+ PyErr_SetString(PyExc_AttributeError, "camera.lens = float: KX_Camera, expected a float greater than zero");
return PY_SET_ATTR_FAIL;
}
@@ -772,7 +791,7 @@ int KX_Camera::pyattr_set_fov(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, P
KX_Camera* self = static_cast<KX_Camera*>(self_v);
float fov = PyFloat_AsDouble(value);
if (fov <= 0.0) {
- PyErr_SetString(PyExc_AttributeError, "camera.fov = float: KX_Camera, expected a float greater then zero");
+ PyErr_SetString(PyExc_AttributeError, "camera.fov = float: KX_Camera, expected a float greater than zero");
return PY_SET_ATTR_FAIL;
}
@@ -796,7 +815,7 @@ int KX_Camera::pyattr_set_ortho_scale(void *self_v, const KX_PYATTRIBUTE_DEF *at
KX_Camera* self = static_cast<KX_Camera*>(self_v);
float param = PyFloat_AsDouble(value);
if (param == -1) {
- PyErr_SetString(PyExc_AttributeError, "camera.ortho_scale = float: KX_Camera, expected a float greater then zero");
+ PyErr_SetString(PyExc_AttributeError, "camera.ortho_scale = float: KX_Camera, expected a float greater than zero");
return PY_SET_ATTR_FAIL;
}
@@ -816,7 +835,7 @@ int KX_Camera::pyattr_set_near(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef,
KX_Camera* self = static_cast<KX_Camera*>(self_v);
float param = PyFloat_AsDouble(value);
if (param == -1) {
- PyErr_SetString(PyExc_AttributeError, "camera.near = float: KX_Camera, expected a float greater then zero");
+ PyErr_SetString(PyExc_AttributeError, "camera.near = float: KX_Camera, expected a float greater than zero");
return PY_SET_ATTR_FAIL;
}
@@ -836,7 +855,7 @@ int KX_Camera::pyattr_set_far(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, P
KX_Camera* self = static_cast<KX_Camera*>(self_v);
float param = PyFloat_AsDouble(value);
if (param == -1) {
- PyErr_SetString(PyExc_AttributeError, "camera.far = float: KX_Camera, expected a float greater then zero");
+ PyErr_SetString(PyExc_AttributeError, "camera.far = float: KX_Camera, expected a float greater than zero");
return PY_SET_ATTR_FAIL;
}
@@ -845,6 +864,45 @@ int KX_Camera::pyattr_set_far(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, P
return PY_SET_ATTR_SUCCESS;
}
+PyObject *KX_Camera::pyattr_get_shift_x(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+{
+ KX_Camera* self = static_cast<KX_Camera*>(self_v);
+ return PyFloat_FromDouble(self->m_camdata.m_shift_x);
+}
+
+int KX_Camera::pyattr_set_shift_x(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
+{
+ KX_Camera* self = static_cast<KX_Camera*>(self_v);
+ float param = PyFloat_AsDouble(value);
+ if (param == -1) {
+ PyErr_SetString(PyExc_AttributeError, "camera.shift_x = float: KX_Camera, expected a float greater than zero");
+ return PY_SET_ATTR_FAIL;
+ }
+
+ self->m_camdata.m_shift_x = param;
+ self->m_set_projection_matrix = false;
+ return PY_SET_ATTR_SUCCESS;
+}
+
+PyObject *KX_Camera::pyattr_get_shift_y(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+{
+ KX_Camera* self = static_cast<KX_Camera*>(self_v);
+ return PyFloat_FromDouble(self->m_camdata.m_shift_y);
+}
+
+int KX_Camera::pyattr_set_shift_y(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
+{
+ KX_Camera* self = static_cast<KX_Camera*>(self_v);
+ float param = PyFloat_AsDouble(value);
+ if (param == -1) {
+ PyErr_SetString(PyExc_AttributeError, "camera.shift_y = float: KX_Camera, expected a float greater than zero");
+ return PY_SET_ATTR_FAIL;
+ }
+
+ self->m_camdata.m_shift_y = param;
+ self->m_set_projection_matrix = false;
+ return PY_SET_ATTR_SUCCESS;
+}
PyObject *KX_Camera::pyattr_get_use_viewport(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
@@ -885,7 +943,7 @@ int KX_Camera::pyattr_set_projection_matrix(void *self_v, const KX_PYATTRIBUTE_D
PyObject *KX_Camera::pyattr_get_modelview_matrix(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
KX_Camera* self = static_cast<KX_Camera*>(self_v);
- return PyObjectFrom(self->GetModelviewMatrix());
+ return PyObjectFrom(self->GetWorldToCamera());
}
PyObject *KX_Camera::pyattr_get_camera_to_world(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
@@ -994,7 +1052,7 @@ KX_PYMETHODDEF_DOC_O(KX_Camera, getScreenPosition,
GLdouble modelmatrix[16];
GLdouble projmatrix[16];
- MT_Matrix4x4 m_modelmatrix = this->GetModelviewMatrix();
+ MT_Matrix4x4 m_modelmatrix = this->GetWorldToCamera();
MT_Matrix4x4 m_projmatrix = this->GetProjectionMatrix();
m_modelmatrix.getValue(modelmatrix);
@@ -1037,7 +1095,7 @@ KX_PYMETHODDEF_DOC_VARARGS(KX_Camera, getScreenVect,
GLdouble modelmatrix[16];
GLdouble projmatrix[16];
- MT_Matrix4x4 m_modelmatrix = this->GetModelviewMatrix();
+ MT_Matrix4x4 m_modelmatrix = this->GetWorldToCamera();
MT_Matrix4x4 m_projmatrix = this->GetProjectionMatrix();
m_modelmatrix.getValue(modelmatrix);
diff --git a/source/gameengine/Ketsji/KX_Camera.h b/source/gameengine/Ketsji/KX_Camera.h
index 454c4a54ec1..8addf0b7aed 100644
--- a/source/gameengine/Ketsji/KX_Camera.h
+++ b/source/gameengine/Ketsji/KX_Camera.h
@@ -40,7 +40,7 @@
#include "MT_Vector3.h"
#include "MT_Point3.h"
#include "KX_GameObject.h"
-#include "IntValue.h"
+#include "EXP_IntValue.h"
#include "RAS_CameraData.h"
#ifdef WITH_PYTHON
@@ -192,7 +192,7 @@ public:
void InvalidateProjectionMatrix(bool valid = false);
/** Gets the modelview matrix that is used by the rasterizer.
- * \warning If the Camera is a dynamic object then this method may return garbage. Use GetCameraToWorld() instead.
+ * \warning If the Camera is a dynamic object then this method may return garbage. Use GetWorldToCamera() instead.
*/
const MT_Matrix4x4& GetModelviewMatrix() const;
@@ -206,6 +206,10 @@ public:
float GetSensorHeight() const;
/** Gets the mode FOV is calculating from sensor dimensions */
short GetSensorFit() const;
+ /** Gets the horizontal shift of the sensor - for camera matching */
+ float GetShiftHorizontal() const;
+ /** Gets the vertical shift of the sensor - for camera matching */
+ float GetShiftVertical() const;
/** Gets the near clip distance. */
float GetCameraNear() const;
/** Gets the far clip distance. */
@@ -306,7 +310,11 @@ public:
static int pyattr_set_near(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
static PyObject* pyattr_get_far(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
static int pyattr_set_far(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
-
+ static PyObject* pyattr_get_shift_x(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+ static int pyattr_set_shift_x(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
+ static PyObject* pyattr_get_shift_y(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+ static int pyattr_set_shift_y(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
+
static PyObject* pyattr_get_use_viewport(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
static int pyattr_set_use_viewport(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
diff --git a/source/gameengine/Ketsji/KX_CameraActuator.cpp b/source/gameengine/Ketsji/KX_CameraActuator.cpp
index acf30b4866c..f065e3f0001 100644
--- a/source/gameengine/Ketsji/KX_CameraActuator.cpp
+++ b/source/gameengine/Ketsji/KX_CameraActuator.cpp
@@ -40,7 +40,7 @@
#include <float.h>
#include "KX_GameObject.h"
-#include "PyObjectPlus.h"
+#include "EXP_PyObjectPlus.h"
/* ------------------------------------------------------------------------- */
/* Native functions */
@@ -288,19 +288,23 @@ bool KX_CameraActuator::Update(double curtime, bool frame)
from[1] += fac * fp1[1];
from[2] += fac * fp1[2];
- /* alleen alstie ervoor ligt: cross testen en loodrechte bijtellen */
+ /* only for it lies: cross test and perpendicular bites up */
if (inp < 0.0f) {
- if (fp1[0] * fp2[1] - fp1[1] * fp2[0] > 0.0f) {
+ /* Don't do anything if the cross product is too small.
+ * The camera up-axis becomes unstable and starts to oscillate.
+ * The 0.01f threshold is arbitrary but seems to work well in practice. */
+ float cross = fp1[0] * fp2[1] - fp1[1] * fp2[0];
+ if (cross > 0.01f) {
from[0] -= fac * fp1[1];
from[1] += fac * fp1[0];
}
- else {
+ else if (cross < -0.01f) {
from[0] += fac * fp1[1];
from[1] -= fac * fp1[0];
}
}
- /* CONSTRAINT 5: minimum / maximum afstand */
+ /* CONSTRAINT 5: minimum / maximum distance */
rc[0] = (lookat[0]-from[0]);
rc[1] = (lookat[1]-from[1]);
@@ -323,7 +327,7 @@ bool KX_CameraActuator::Update(double curtime, bool frame)
}
- /* CONSTRAINT 7: track to schaduw */
+ /* CONSTRAINT 7: track to floor below actor */
rc[0] = (lookat[0]-from[0]);
rc[1] = (lookat[1]-from[1]);
rc[2] = (lookat[2]-from[2]);
diff --git a/source/gameengine/Ketsji/KX_CharacterWrapper.h b/source/gameengine/Ketsji/KX_CharacterWrapper.h
index d4d8f195102..dd7ba680ec7 100644
--- a/source/gameengine/Ketsji/KX_CharacterWrapper.h
+++ b/source/gameengine/Ketsji/KX_CharacterWrapper.h
@@ -6,7 +6,7 @@
#ifndef __KX_CHARACTERWRAPPER_H__
#define __KX_CHARACTERWRAPPER_H__
-#include "Value.h"
+#include "EXP_Value.h"
#include "PHY_DynamicTypes.h"
class PHY_ICharacter;
diff --git a/source/gameengine/Ketsji/KX_ClientObjectInfo.h b/source/gameengine/Ketsji/KX_ClientObjectInfo.h
index e947eb4be6d..81ae5b58009 100644
--- a/source/gameengine/Ketsji/KX_ClientObjectInfo.h
+++ b/source/gameengine/Ketsji/KX_ClientObjectInfo.h
@@ -52,19 +52,16 @@ struct KX_ClientObjectInfo
OBACTORSENSOR
} m_type;
KX_GameObject* m_gameobject;
- void* m_auxilary_info;
std::list<SCA_ISensor*> m_sensors;
public:
- KX_ClientObjectInfo(KX_GameObject *gameobject, clienttype type = STATIC, void *auxilary_info = NULL) :
+ KX_ClientObjectInfo(KX_GameObject *gameobject, clienttype type = STATIC) :
m_type(type),
- m_gameobject(gameobject),
- m_auxilary_info(auxilary_info)
+ m_gameobject(gameobject)
{}
KX_ClientObjectInfo(const KX_ClientObjectInfo &copy) :
m_type(copy.m_type),
- m_gameobject(copy.m_gameobject),
- m_auxilary_info(copy.m_auxilary_info)
+ m_gameobject(copy.m_gameobject)
{
}
diff --git a/source/gameengine/Ketsji/KX_ConstraintActuator.cpp b/source/gameengine/Ketsji/KX_ConstraintActuator.cpp
index e5662b54b83..e07660cef72 100644
--- a/source/gameengine/Ketsji/KX_ConstraintActuator.cpp
+++ b/source/gameengine/Ketsji/KX_ConstraintActuator.cpp
@@ -41,6 +41,7 @@
#include "KX_GameObject.h"
#include "KX_RayCast.h"
#include "KX_PythonInit.h" // KX_GetActiveScene
+#include "RAS_MeshObject.h"
#include <stdio.h>
@@ -129,15 +130,17 @@ bool KX_ConstraintActuator::RayHit(KX_ClientObjectInfo *client, KX_RayCast *resu
}
else
{
- if (m_option & KX_ACT_CONSTRAINT_MATERIAL)
- {
- if (client->m_auxilary_info)
- {
- bFound = !strcmp(m_property.Ptr(), ((char*)client->m_auxilary_info));
+ if (m_option & KX_ACT_CONSTRAINT_MATERIAL) {
+ for (unsigned int i = 0; i < m_hitObject->GetMeshCount(); ++i) {
+ RAS_MeshObject *meshObj = m_hitObject->GetMesh(i);
+ for (unsigned int j = 0; j < meshObj->NumMaterials(); ++j) {
+ bFound = strcmp(m_property.ReadPtr(), meshObj->GetMaterialName(j).ReadPtr() + 2) == 0;
+ if (bFound)
+ break;
+ }
}
}
- else
- {
+ else {
bFound = m_hitObject->GetProperty(m_property) != NULL;
}
}
diff --git a/source/gameengine/Ketsji/KX_ConstraintWrapper.cpp b/source/gameengine/Ketsji/KX_ConstraintWrapper.cpp
index 29d92762285..2f32b5e3216 100644
--- a/source/gameengine/Ketsji/KX_ConstraintWrapper.cpp
+++ b/source/gameengine/Ketsji/KX_ConstraintWrapper.cpp
@@ -30,7 +30,7 @@
*/
-#include "PyObjectPlus.h"
+#include "EXP_PyObjectPlus.h"
#include "KX_ConstraintWrapper.h"
#include "PHY_IPhysicsEnvironment.h"
diff --git a/source/gameengine/Ketsji/KX_ConstraintWrapper.h b/source/gameengine/Ketsji/KX_ConstraintWrapper.h
index b7124c76439..5e20b7a9aca 100644
--- a/source/gameengine/Ketsji/KX_ConstraintWrapper.h
+++ b/source/gameengine/Ketsji/KX_ConstraintWrapper.h
@@ -32,7 +32,7 @@
#ifndef __KX_CONSTRAINTWRAPPER_H__
#define __KX_CONSTRAINTWRAPPER_H__
-#include "Value.h"
+#include "EXP_Value.h"
#include "PHY_DynamicTypes.h"
class KX_ConstraintWrapper : public PyObjectPlus
diff --git a/source/gameengine/Ketsji/KX_Dome.cpp b/source/gameengine/Ketsji/KX_Dome.cpp
index c7f7f586865..07bed647b29 100644
--- a/source/gameengine/Ketsji/KX_Dome.cpp
+++ b/source/gameengine/Ketsji/KX_Dome.cpp
@@ -41,7 +41,7 @@
#include "RAS_CameraData.h"
#include "BLI_math.h"
-#include "GL/glew.h"
+#include "glew-mx.h"
// constructor
KX_Dome::KX_Dome (
@@ -2044,7 +2044,9 @@ void KX_Dome::RenderDomeFrame(KX_Scene* scene, KX_Camera* cam, int i)
cam->NodeUpdateGS(0.f);
scene->CalculateVisibleMeshes(m_rasterizer,cam);
- scene->UpdateAnimations(m_engine->GetFrameTime());
+
+ m_engine->UpdateAnimations(scene);
+
scene->RenderBuckets(camtrans, m_rasterizer);
}
diff --git a/source/gameengine/Ketsji/KX_Dome.h b/source/gameengine/Ketsji/KX_Dome.h
index a7e798a3944..420565e62f6 100644
--- a/source/gameengine/Ketsji/KX_Dome.h
+++ b/source/gameengine/Ketsji/KX_Dome.h
@@ -38,7 +38,7 @@
#include "RAS_IRasterizer.h"
#include "KX_KetsjiEngine.h"
-#include "GL/glew.h"
+#include "glew-mx.h"
#include <vector>
#include "MEM_guardedalloc.h"
diff --git a/source/gameengine/Ketsji/KX_FontObject.cpp b/source/gameengine/Ketsji/KX_FontObject.cpp
index 9789a8294ee..420f1f7eb98 100644
--- a/source/gameengine/Ketsji/KX_FontObject.cpp
+++ b/source/gameengine/Ketsji/KX_FontObject.cpp
@@ -35,7 +35,7 @@
#include "KX_Scene.h"
#include "KX_PythonInit.h"
#include "BLI_math.h"
-#include "StringValue.h"
+#include "EXP_StringValue.h"
#include "RAS_IRasterizer.h"
/* paths needed for font load */
@@ -118,7 +118,6 @@ CValue* KX_FontObject::GetReplica()
void KX_FontObject::ProcessReplica()
{
KX_GameObject::ProcessReplica();
- KX_GetActiveScene()->AddFont(this);
}
int GetFontId(VFont *vfont)
diff --git a/source/gameengine/Ketsji/KX_FontObject.h b/source/gameengine/Ketsji/KX_FontObject.h
index 209ab6ca69f..bf70eedfde6 100644
--- a/source/gameengine/Ketsji/KX_FontObject.h
+++ b/source/gameengine/Ketsji/KX_FontObject.h
@@ -54,6 +54,7 @@ public:
*/
virtual CValue* GetReplica();
virtual void ProcessReplica();
+ virtual int GetGameObjectType() { return OBJ_TEXT; }
protected:
std::vector<STR_String> m_text;
diff --git a/source/gameengine/Ketsji/KX_GameActuator.cpp b/source/gameengine/Ketsji/KX_GameActuator.cpp
index c6087ac676d..a23af680104 100644
--- a/source/gameengine/Ketsji/KX_GameActuator.cpp
+++ b/source/gameengine/Ketsji/KX_GameActuator.cpp
@@ -178,6 +178,11 @@ bool KX_GameActuator::Update()
// obtain file size:
fseek (fp , 0 , SEEK_END);
marshal_length = ftell(fp);
+ if (marshal_length == -1) {
+ printf("warning: could not read position of '%s'\n", mashal_path);
+ fclose(fp);
+ break;
+ }
rewind(fp);
marshal_buffer = (char*) malloc (sizeof(char)*marshal_length);
diff --git a/source/gameengine/Ketsji/KX_GameObject.cpp b/source/gameengine/Ketsji/KX_GameObject.cpp
index c681e0842c4..c3da80bc14f 100644
--- a/source/gameengine/Ketsji/KX_GameObject.cpp
+++ b/source/gameengine/Ketsji/KX_GameObject.cpp
@@ -36,14 +36,6 @@
# pragma warning( disable:4786 )
#endif
-#if defined(_WIN64) && !defined(FREE_WINDOWS64)
-typedef unsigned __int64 uint_ptr;
-#elif defined(FREE_WINDOWS64)
-typedef unsigned long long uint_ptr;
-#else
-typedef unsigned long uint_ptr;
-#endif
-
#include "RAS_IPolygonMaterial.h"
#include "KX_BlenderMaterial.h"
#include "KX_GameObject.h"
@@ -55,6 +47,7 @@ typedef unsigned long uint_ptr;
#include "KX_MeshProxy.h"
#include "KX_PolyProxy.h"
#include <stdio.h> // printf
+#include <climits> // USHRT_MAX
#include "SG_Controller.h"
#include "PHY_IGraphicController.h"
#include "SG_Node.h"
@@ -76,7 +69,13 @@ typedef unsigned long uint_ptr;
#include "BL_ActionManager.h"
#include "BL_Action.h"
-#include "PyObjectPlus.h" /* python stuff */
+#include "EXP_PyObjectPlus.h" /* python stuff */
+#include "BLI_utildefines.h"
+
+#ifdef WITH_PYTHON
+# include "EXP_PythonCallBack.h"
+# include "python_utildefines.h"
+#endif
// This file defines relationships between parents and children
// in the game engine.
@@ -97,9 +96,10 @@ KX_GameObject::KX_GameObject(
: SCA_IObject(),
m_bDyna(false),
m_layer(0),
+ m_currentLodLevel(0),
+ m_previousLodLevel(0),
m_pBlenderObject(NULL),
m_pBlenderGroupObject(NULL),
- m_bSuspendDynamics(false),
m_bUseObjectColor(false),
m_bIsNegativeScaling(false),
m_objectColor(1.0, 1.0, 1.0, 1.0),
@@ -297,6 +297,21 @@ void KX_GameObject::SetDupliGroupObject(KX_GameObject* obj)
m_pDupliGroupObject = obj;
}
+void KX_GameObject::AddConstraint(bRigidBodyJointConstraint *cons)
+{
+ m_constraints.push_back(cons);
+}
+
+std::vector<bRigidBodyJointConstraint*> KX_GameObject::GetConstraints()
+{
+ return m_constraints;
+}
+
+void KX_GameObject::ClearConstraints()
+{
+ m_constraints.clear();
+}
+
KX_GameObject* KX_GameObject::GetParent()
{
KX_GameObject* result = NULL;
@@ -454,6 +469,11 @@ void KX_GameObject::StopAction(short layer)
GetActionManager()->StopAction(layer);
}
+void KX_GameObject::RemoveTaggedActions()
+{
+ GetActionManager()->RemoveTaggedActions();
+}
+
bool KX_GameObject::IsActionDone(short layer)
{
return GetActionManager()->IsActionDone(layer);
@@ -474,6 +494,11 @@ float KX_GameObject::GetActionFrame(short layer)
return GetActionManager()->GetActionFrame(layer);
}
+const char *KX_GameObject::GetActionName(short layer)
+{
+ return GetActionManager()->GetActionName(layer);
+}
+
void KX_GameObject::SetActionFrame(short layer, float frame)
{
GetActionManager()->SetActionFrame(layer, frame);
@@ -551,13 +576,26 @@ void KX_GameObject::ActivateGraphicController(bool recurse)
}
}
-void KX_GameObject::SetUserCollisionGroup(short group)
+void KX_GameObject::SetUserCollisionGroup(unsigned short group)
{
m_userCollisionGroup = group;
+ if (m_pPhysicsController)
+ m_pPhysicsController->RefreshCollisions();
}
-void KX_GameObject::SetUserCollisionMask(short mask)
+void KX_GameObject::SetUserCollisionMask(unsigned short mask)
{
m_userCollisionMask = mask;
+ if (m_pPhysicsController)
+ m_pPhysicsController->RefreshCollisions();
+}
+
+unsigned short KX_GameObject::GetUserCollisionGroup()
+{
+ return m_userCollisionGroup;
+}
+unsigned short KX_GameObject::GetUserCollisionMask()
+{
+ return m_userCollisionMask;
}
bool KX_GameObject::CheckCollision(KX_GameObject* other)
@@ -575,6 +613,46 @@ CValue* KX_GameObject::GetReplica()
return replica;
}
+bool KX_GameObject::IsDynamicsSuspended() const
+{
+ if (m_pPhysicsController)
+ return m_pPhysicsController->IsSuspended();
+ return false;
+}
+
+float KX_GameObject::getLinearDamping() const
+{
+ if (m_pPhysicsController)
+ return m_pPhysicsController->GetLinearDamping();
+ return 0;
+}
+
+float KX_GameObject::getAngularDamping() const
+{
+ if (m_pPhysicsController)
+ return m_pPhysicsController->GetAngularDamping();
+ return 0;
+}
+
+void KX_GameObject::setLinearDamping(float damping)
+{
+ if (m_pPhysicsController)
+ m_pPhysicsController->SetLinearDamping(damping);
+}
+
+
+void KX_GameObject::setAngularDamping(float damping)
+{
+ if (m_pPhysicsController)
+ m_pPhysicsController->SetAngularDamping(damping);
+}
+
+
+void KX_GameObject::setDamping(float linear, float angular)
+{
+ if (m_pPhysicsController)
+ m_pPhysicsController->SetDamping(linear, angular);
+}
void KX_GameObject::ApplyForce(const MT_Vector3& force,bool local)
@@ -741,35 +819,74 @@ void KX_GameObject::AddLodMesh(RAS_MeshObject* mesh)
m_lodmeshes.push_back(mesh);
}
+
+static float calcHysteresis(KX_Scene *kxscene, LodLevel *lod)
+{
+ float hystvariance = 0.0f;
+
+ if (!kxscene->IsActivedLodHysteresis())
+ return hystvariance;
+
+ short hysteresis = 0;
+ // if exists, LoD level hysteresis will override scene hysteresis
+ if (lod->next->flags & OB_LOD_USE_HYST)
+ hysteresis = lod->next->obhysteresis;
+ else
+ hysteresis = kxscene->GetLodHysteresisValue();
+
+ return hystvariance = MT_abs(lod->next->distance - lod->distance) * hysteresis / 100;
+}
+
void KX_GameObject::UpdateLod(MT_Vector3 &cam_pos)
{
// Handle dupligroups
- if (this->m_pInstanceObjects) {
- KX_GameObject * instob;
- int count = this->m_pInstanceObjects->GetCount();
+ if (m_pInstanceObjects) {
+ KX_GameObject *instob;
+ int count = m_pInstanceObjects->GetCount();
for (int i = 0; i < count; i++) {
- instob = (KX_GameObject*)this->m_pInstanceObjects->GetValue(i);
+ instob = (KX_GameObject*)m_pInstanceObjects->GetValue(i);
instob->UpdateLod(cam_pos);
}
}
- if (this->m_lodmeshes.empty()) return;
+ if (m_lodmeshes.empty())
+ return;
- MT_Vector3 delta = this->NodeGetWorldPosition() - cam_pos;
+ MT_Vector3 delta = NodeGetWorldPosition() - cam_pos;
float distance2 = delta.length2();
int level = 0;
- Object *bob = this->GetBlenderObject();
- LodLevel *lod = (LodLevel*) bob->lodlevels.first;
+ float hystvariance = 0.0f;
+ Object *bob = GetBlenderObject();
+ LodLevel *lod = (LodLevel *)bob->lodlevels.first;
+ KX_Scene *kxscene = GetScene();
+
for (; lod; lod = lod->next, level++) {
- if (!lod->source || lod->source->type != OB_MESH) level--;
- if (!lod->next || lod->next->distance * lod->next->distance > distance2) break;
- }
+ if (!lod->source || lod->source->type != OB_MESH)
+ level--;
- RAS_MeshObject *mesh = this->m_lodmeshes[level];
+ if (!lod->next)
+ break;
+
+ if (level == m_previousLodLevel || level == (m_previousLodLevel + 1)) {
+ hystvariance = calcHysteresis(kxscene, lod);
+ float newdistance = lod->next->distance + hystvariance;
+ if (newdistance * newdistance > distance2)
+ break;
+ }
+ else if (level == (m_previousLodLevel - 1)) {
+ hystvariance = calcHysteresis(kxscene, lod);
+ float newdistance = lod->next->distance - hystvariance;
+ if (newdistance * newdistance > distance2)
+ break;
+ }
+ }
- if (mesh != this->m_meshes[0]) {
- this->GetScene()->ReplaceMesh(this, mesh, true, false);
+ RAS_MeshObject *mesh = m_lodmeshes[level];
+ m_currentLodLevel = level;
+ if (mesh != m_meshes[0]) {
+ m_previousLodLevel = level;
+ GetScene()->ReplaceMesh(this, mesh, true, false);
}
}
@@ -930,27 +1047,6 @@ KX_GameObject::SetVisible(
}
}
-bool KX_GameObject::GetCulled()
-{
- // If we're set to not cull, double-check with
- // the mesh slots first. This is kind of nasty, but
- // it allows us to get proper culling information.
- if (!m_bCulled)
- {
- SG_QList::iterator<RAS_MeshSlot> mit(m_meshSlots);
- for (mit.begin(); !mit.end(); ++mit)
- {
- if ((*mit)->m_bCulled)
- {
- m_bCulled = true;
- break;
- }
- }
- }
-
- return m_bCulled;
-}
-
static void setOccluder_recursive(SG_Node* node, bool v)
{
NodeList& children = node->GetSGChildren();
@@ -1486,36 +1582,27 @@ void KX_GameObject::RegisterCollisionCallbacks()
pe->AddSensor(spc);
}
}
-void KX_GameObject::RunCollisionCallbacks(KX_GameObject *collider)
+void KX_GameObject::RunCollisionCallbacks(KX_GameObject *collider, const MT_Vector3 &point, const MT_Vector3 &normal)
{
- #ifdef WITH_PYTHON
- Py_ssize_t len;
- PyObject* collision_callbacks = m_collisionCallbacks;
-
- if (collision_callbacks && (len=PyList_GET_SIZE(collision_callbacks)))
- {
- PyObject* args = Py_BuildValue("(O)", collider->GetProxy()); // save python creating each call
- PyObject *func;
- PyObject *ret;
+#ifdef WITH_PYTHON
+ if (!m_collisionCallbacks || PyList_GET_SIZE(m_collisionCallbacks) == 0)
+ return;
- // Iterate the list and run the callbacks
- for (Py_ssize_t pos=0; pos < len; pos++)
- {
- func = PyList_GET_ITEM(collision_callbacks, pos);
- ret = PyObject_Call(func, args, NULL);
+ /** Current logic controller is set by each python logic bricks before run,
+ * but if no python logic brick ran the logic manager can be wrong
+ * (if the user use muti scenes) and it will cause problems with function
+ * ConvertPythonToGameObject which use the current logic manager for object's name.
+ * Note: the scene is already set in logic frame loop.
+ */
+ SCA_ILogicBrick::m_sCurrentLogicManager = GetScene()->GetLogicManager();
- if (ret == NULL) {
- PyErr_Print();
- PyErr_Clear();
- }
- else {
- Py_DECREF(ret);
- }
- }
+ PyObject *args[] = {collider->GetProxy(), PyObjectFrom(point), PyObjectFrom(normal)};
+ RunPythonCallBackList(m_collisionCallbacks, args, 1, ARRAY_SIZE(args));
- Py_DECREF(args);
+ for (unsigned int i = 0; i < ARRAY_SIZE(args); ++i) {
+ Py_DECREF(args[i]);
}
- #endif
+#endif
}
/* Suspend/ resume: for the dynamic behavior, there is a simple
@@ -1529,7 +1616,8 @@ void KX_GameObject::Resume(void)
{
if (m_suspended) {
SCA_IObject::Resume();
- if (GetPhysicsController())
+ // Child objects must be static, so we block changing to dynamic
+ if (GetPhysicsController() && !GetParent())
GetPhysicsController()->RestoreDynamics();
m_suspended = false;
@@ -1587,9 +1675,11 @@ CListValue* KX_GameObject::GetChildrenRecursive()
KX_Scene* KX_GameObject::GetScene()
{
SG_Node* node = this->GetSGNode();
- KX_Scene* scene = static_cast<KX_Scene*>(node->GetSGClientInfo());
-
- return scene;
+ if (node == NULL) {
+ // this happens for object in non active layers, rely on static scene then
+ return KX_GetActiveScene();
+ }
+ return static_cast<KX_Scene*>(node->GetSGClientInfo());
}
/* ---------------------------------------------------------------------
@@ -1823,7 +1913,7 @@ static Mathutils_Callback mathutils_kxgameob_matrix_cb = {
void KX_GameObject_Mathutils_Callback_Init(void)
{
- // register mathutils callbacks, ok to run more then once.
+ // register mathutils callbacks, ok to run more than once.
mathutils_kxgameob_vector_cb_index= Mathutils_RegisterCallback(&mathutils_kxgameob_vector_cb);
mathutils_kxgameob_matrix_cb_index= Mathutils_RegisterCallback(&mathutils_kxgameob_matrix_cb);
}
@@ -1842,10 +1932,11 @@ PyMethodDef KX_GameObject::Methods[] = {
{"getAngularVelocity", (PyCFunction) KX_GameObject::sPyGetAngularVelocity, METH_VARARGS},
{"setAngularVelocity", (PyCFunction) KX_GameObject::sPySetAngularVelocity, METH_VARARGS},
{"getVelocity", (PyCFunction) KX_GameObject::sPyGetVelocity, METH_VARARGS},
+ {"setDamping", (PyCFunction) KX_GameObject::sPySetDamping, METH_VARARGS},
{"getReactionForce", (PyCFunction) KX_GameObject::sPyGetReactionForce, METH_NOARGS},
{"alignAxisToVect",(PyCFunction) KX_GameObject::sPyAlignAxisToVect, METH_VARARGS},
{"getAxisVect",(PyCFunction) KX_GameObject::sPyGetAxisVect, METH_O},
- {"suspendDynamics", (PyCFunction)KX_GameObject::sPySuspendDynamics,METH_NOARGS},
+ {"suspendDynamics", (PyCFunction)KX_GameObject::sPySuspendDynamics, METH_VARARGS},
{"restoreDynamics", (PyCFunction)KX_GameObject::sPyRestoreDynamics,METH_NOARGS},
{"enableRigidBody", (PyCFunction)KX_GameObject::sPyEnableRigidBody,METH_NOARGS},
{"disableRigidBody", (PyCFunction)KX_GameObject::sPyDisableRigidBody,METH_NOARGS},
@@ -1873,6 +1964,7 @@ PyMethodDef KX_GameObject::Methods[] = {
KX_PYMETHODTABLE_KEYWORDS(KX_GameObject, playAction),
KX_PYMETHODTABLE(KX_GameObject, stopAction),
KX_PYMETHODTABLE(KX_GameObject, getActionFrame),
+ KX_PYMETHODTABLE(KX_GameObject, getActionName),
KX_PYMETHODTABLE(KX_GameObject, setActionFrame),
KX_PYMETHODTABLE(KX_GameObject, isPlayingAction),
@@ -1883,6 +1975,7 @@ PyMethodDef KX_GameObject::Methods[] = {
};
PyAttributeDef KX_GameObject::Attributes[] = {
+ KX_PYATTRIBUTE_INT_RO("currentLodLevel", KX_GameObject, m_currentLodLevel),
KX_PYATTRIBUTE_RO_FUNCTION("name", KX_GameObject, pyattr_get_name),
KX_PYATTRIBUTE_RO_FUNCTION("parent", KX_GameObject, pyattr_get_parent),
KX_PYATTRIBUTE_RO_FUNCTION("groupMembers", KX_GameObject, pyattr_get_group_members),
@@ -1890,8 +1983,11 @@ PyAttributeDef KX_GameObject::Attributes[] = {
KX_PYATTRIBUTE_RO_FUNCTION("scene", KX_GameObject, pyattr_get_scene),
KX_PYATTRIBUTE_RO_FUNCTION("life", KX_GameObject, pyattr_get_life),
KX_PYATTRIBUTE_RW_FUNCTION("mass", KX_GameObject, pyattr_get_mass, pyattr_set_mass),
+ KX_PYATTRIBUTE_RO_FUNCTION("isSuspendDynamics", KX_GameObject, pyattr_get_is_suspend_dynamics),
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("angularVelocityMin", KX_GameObject, pyattr_get_ang_vel_min, pyattr_set_ang_vel_min),
+ KX_PYATTRIBUTE_RW_FUNCTION("angularVelocityMax", KX_GameObject, pyattr_get_ang_vel_max, pyattr_set_ang_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),
@@ -1901,6 +1997,8 @@ PyAttributeDef KX_GameObject::Attributes[] = {
KX_PYATTRIBUTE_RW_FUNCTION("scaling", KX_GameObject, pyattr_get_worldScaling, pyattr_set_localScaling),
KX_PYATTRIBUTE_RW_FUNCTION("timeOffset",KX_GameObject, pyattr_get_timeOffset,pyattr_set_timeOffset),
KX_PYATTRIBUTE_RW_FUNCTION("collisionCallbacks", KX_GameObject, pyattr_get_collisionCallbacks, pyattr_set_collisionCallbacks),
+ KX_PYATTRIBUTE_RW_FUNCTION("collisionGroup", KX_GameObject, pyattr_get_collisionGroup, pyattr_set_collisionGroup),
+ KX_PYATTRIBUTE_RW_FUNCTION("collisionMask", KX_GameObject, pyattr_get_collisionMask, pyattr_set_collisionMask),
KX_PYATTRIBUTE_RW_FUNCTION("state", KX_GameObject, pyattr_get_state, pyattr_set_state),
KX_PYATTRIBUTE_RO_FUNCTION("meshes", KX_GameObject, pyattr_get_meshes),
KX_PYATTRIBUTE_RW_FUNCTION("localOrientation",KX_GameObject,pyattr_get_localOrientation,pyattr_set_localOrientation),
@@ -1917,6 +2015,8 @@ PyAttributeDef KX_GameObject::Attributes[] = {
KX_PYATTRIBUTE_RW_FUNCTION("angularVelocity", KX_GameObject, pyattr_get_localAngularVelocity, pyattr_set_worldAngularVelocity),
KX_PYATTRIBUTE_RW_FUNCTION("localAngularVelocity", KX_GameObject, pyattr_get_localAngularVelocity, pyattr_set_localAngularVelocity),
KX_PYATTRIBUTE_RW_FUNCTION("worldAngularVelocity", KX_GameObject, pyattr_get_worldAngularVelocity, pyattr_set_worldAngularVelocity),
+ KX_PYATTRIBUTE_RW_FUNCTION("linearDamping", KX_GameObject, pyattr_get_linearDamping, pyattr_set_linearDamping),
+ KX_PYATTRIBUTE_RW_FUNCTION("angularDamping", KX_GameObject, pyattr_get_angularDamping, pyattr_set_angularDamping),
KX_PYATTRIBUTE_RO_FUNCTION("children", KX_GameObject, pyattr_get_children),
KX_PYATTRIBUTE_RO_FUNCTION("childrenRecursive", KX_GameObject, pyattr_get_children_recursive),
KX_PYATTRIBUTE_RO_FUNCTION("attrDict", KX_GameObject, pyattr_get_attrDict),
@@ -2245,6 +2345,56 @@ int KX_GameObject::pyattr_set_collisionCallbacks(void *self_v, const KX_PYATTRIB
return PY_SET_ATTR_SUCCESS;
}
+PyObject *KX_GameObject::pyattr_get_collisionGroup(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+{
+ KX_GameObject* self = static_cast<KX_GameObject*>(self_v);
+ return PyLong_FromLong(self->GetUserCollisionGroup());
+}
+
+int KX_GameObject::pyattr_set_collisionGroup(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
+{
+ KX_GameObject* self = static_cast<KX_GameObject*>(self_v);
+ int val = PyLong_AsLong(value);
+
+ if (val == -1 && PyErr_Occurred()) {
+ PyErr_SetString(PyExc_TypeError, "gameOb.collisionGroup = int: KX_GameObject, expected an int bit field");
+ return PY_SET_ATTR_FAIL;
+ }
+
+ if (val < 0 || val > USHRT_MAX) {
+ PyErr_Format(PyExc_AttributeError, "gameOb.collisionGroup = int: KX_GameObject, expected a int bit field between 0 and %i", USHRT_MAX);
+ return PY_SET_ATTR_FAIL;
+ }
+
+ self->SetUserCollisionGroup(val);
+ return PY_SET_ATTR_SUCCESS;
+}
+
+PyObject *KX_GameObject::pyattr_get_collisionMask(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+{
+ KX_GameObject* self = static_cast<KX_GameObject*>(self_v);
+ return PyLong_FromLong(self->GetUserCollisionMask());
+}
+
+int KX_GameObject::pyattr_set_collisionMask(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
+{
+ KX_GameObject* self = static_cast<KX_GameObject*>(self_v);
+ int val = PyLong_AsLong(value);
+
+ if (val == -1 && PyErr_Occurred()) {
+ PyErr_SetString(PyExc_TypeError, "gameOb.collisionMask = int: KX_GameObject, expected an int bit field");
+ return PY_SET_ATTR_FAIL;
+ }
+
+ if (val < 0 || val > USHRT_MAX) {
+ PyErr_Format(PyExc_AttributeError, "gameOb.collisionMask = int: KX_GameObject, expected a int bit field between 0 and %i", USHRT_MAX);
+ return PY_SET_ATTR_FAIL;
+ }
+
+ self->SetUserCollisionMask(val);
+ return PY_SET_ATTR_SUCCESS;
+}
+
PyObject* KX_GameObject::pyattr_get_scene(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
KX_GameObject *self = static_cast<KX_GameObject*>(self_v);
@@ -2301,6 +2451,19 @@ int KX_GameObject::pyattr_set_mass(void *self_v, const KX_PYATTRIBUTE_DEF *attrd
return PY_SET_ATTR_SUCCESS;
}
+PyObject *KX_GameObject::pyattr_get_is_suspend_dynamics(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+{
+ KX_GameObject* self = static_cast<KX_GameObject*>(self_v);
+
+ // Only objects with a physics controller can be suspended
+ if (!self->GetPhysicsController()) {
+ PyErr_SetString(PyExc_AttributeError, "This object has not Physics Controller");
+ return NULL;
+ }
+
+ return PyBool_FromLong(self->IsDynamicsSuspended());
+}
+
PyObject *KX_GameObject::pyattr_get_lin_vel_min(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
KX_GameObject* self = static_cast<KX_GameObject*>(self_v);
@@ -2347,6 +2510,54 @@ int KX_GameObject::pyattr_set_lin_vel_max(void *self_v, const KX_PYATTRIBUTE_DEF
return PY_SET_ATTR_SUCCESS;
}
+PyObject *KX_GameObject::pyattr_get_ang_vel_min(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+{
+ KX_GameObject *self = static_cast<KX_GameObject*>(self_v);
+ PHY_IPhysicsController *spc = self->GetPhysicsController();
+ return PyFloat_FromDouble(spc ? spc->GetAngularVelocityMin() : 0.0f);
+}
+
+int KX_GameObject::pyattr_set_ang_vel_min(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
+{
+ KX_GameObject *self = static_cast<KX_GameObject*>(self_v);
+ PHY_IPhysicsController *spc = self->GetPhysicsController();
+ MT_Scalar val = PyFloat_AsDouble(value);
+ if (val < 0.0f) { /* also accounts for non float */
+ PyErr_SetString(PyExc_AttributeError,
+ "gameOb.angularVelocityMin = float: KX_GameObject, expected a nonnegative float");
+ return PY_SET_ATTR_FAIL;
+ }
+
+ if (spc)
+ spc->SetAngularVelocityMin(val);
+
+ return PY_SET_ATTR_SUCCESS;
+}
+
+PyObject *KX_GameObject::pyattr_get_ang_vel_max(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+{
+ KX_GameObject *self = static_cast<KX_GameObject*>(self_v);
+ PHY_IPhysicsController *spc = self->GetPhysicsController();
+ return PyFloat_FromDouble(spc ? spc->GetAngularVelocityMax() : 0.0f);
+}
+
+int KX_GameObject::pyattr_set_ang_vel_max(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
+{
+ KX_GameObject *self = static_cast<KX_GameObject*>(self_v);
+ PHY_IPhysicsController *spc = self->GetPhysicsController();
+ MT_Scalar val = PyFloat_AsDouble(value);
+ if (val < 0.0f) { /* also accounts for non float */
+ PyErr_SetString(PyExc_AttributeError,
+ "gameOb.angularVelocityMax = float: KX_GameObject, expected a nonnegative float");
+ return PY_SET_ATTR_FAIL;
+ }
+
+ if (spc)
+ spc->SetAngularVelocityMax(val);
+
+ return PY_SET_ATTR_SUCCESS;
+}
+
PyObject *KX_GameObject::pyattr_get_visible(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
@@ -2393,7 +2604,9 @@ int KX_GameObject::pyattr_set_record_animation(void *self_v, const KX_PYATTRIBUT
PyObject *KX_GameObject::pyattr_get_worldPosition(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
#ifdef USE_MATHUTILS
- return Vector_CreatePyObject_cb(BGE_PROXY_FROM_REF(self_v), 3, mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_POS_GLOBAL);
+ return Vector_CreatePyObject_cb(
+ BGE_PROXY_FROM_REF_BORROW(self_v), 3,
+ mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_POS_GLOBAL);
#else
KX_GameObject* self = static_cast<KX_GameObject*>(self_v);
return PyObjectFrom(self->NodeGetWorldPosition());
@@ -2415,7 +2628,9 @@ int KX_GameObject::pyattr_set_worldPosition(void *self_v, const KX_PYATTRIBUTE_D
PyObject *KX_GameObject::pyattr_get_localPosition(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
#ifdef USE_MATHUTILS
- return Vector_CreatePyObject_cb(BGE_PROXY_FROM_REF(self_v), 3, mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_POS_LOCAL);
+ return Vector_CreatePyObject_cb(
+ BGE_PROXY_FROM_REF_BORROW(self_v), 3,
+ mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_POS_LOCAL);
#else
KX_GameObject* self = static_cast<KX_GameObject*>(self_v);
return PyObjectFrom(self->NodeGetLocalPosition());
@@ -2437,7 +2652,9 @@ int KX_GameObject::pyattr_set_localPosition(void *self_v, const KX_PYATTRIBUTE_D
PyObject *KX_GameObject::pyattr_get_localInertia(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
#ifdef USE_MATHUTILS
- return Vector_CreatePyObject_cb(BGE_PROXY_FROM_REF(self_v), 3, mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_INERTIA_LOCAL);
+ return Vector_CreatePyObject_cb(
+ BGE_PROXY_FROM_REF_BORROW(self_v), 3,
+ mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_INERTIA_LOCAL);
#else
KX_GameObject* self = static_cast<KX_GameObject*>(self_v);
if (self->GetPhysicsController1())
@@ -2449,7 +2666,9 @@ PyObject *KX_GameObject::pyattr_get_localInertia(void *self_v, const KX_PYATTRIB
PyObject *KX_GameObject::pyattr_get_worldOrientation(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
#ifdef USE_MATHUTILS
- return Matrix_CreatePyObject_cb(BGE_PROXY_FROM_REF(self_v), 3, 3, mathutils_kxgameob_matrix_cb_index, MATHUTILS_MAT_CB_ORI_GLOBAL);
+ return Matrix_CreatePyObject_cb(
+ BGE_PROXY_FROM_REF_BORROW(self_v), 3, 3,
+ mathutils_kxgameob_matrix_cb_index, MATHUTILS_MAT_CB_ORI_GLOBAL);
#else
KX_GameObject* self = static_cast<KX_GameObject*>(self_v);
return PyObjectFrom(self->NodeGetWorldOrientation());
@@ -2474,7 +2693,9 @@ int KX_GameObject::pyattr_set_worldOrientation(void *self_v, const KX_PYATTRIBUT
PyObject *KX_GameObject::pyattr_get_localOrientation(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
#ifdef USE_MATHUTILS
- return Matrix_CreatePyObject_cb(BGE_PROXY_FROM_REF(self_v), 3, 3, mathutils_kxgameob_matrix_cb_index, MATHUTILS_MAT_CB_ORI_LOCAL);
+ return Matrix_CreatePyObject_cb(
+ BGE_PROXY_FROM_REF_BORROW(self_v), 3, 3,
+ mathutils_kxgameob_matrix_cb_index, MATHUTILS_MAT_CB_ORI_LOCAL);
#else
KX_GameObject* self = static_cast<KX_GameObject*>(self_v);
return PyObjectFrom(self->NodeGetLocalOrientation());
@@ -2498,7 +2719,9 @@ int KX_GameObject::pyattr_set_localOrientation(void *self_v, const KX_PYATTRIBUT
PyObject *KX_GameObject::pyattr_get_worldScaling(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
#ifdef USE_MATHUTILS
- return Vector_CreatePyObject_cb(BGE_PROXY_FROM_REF(self_v), 3, mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_SCALE_GLOBAL);
+ return Vector_CreatePyObject_cb(
+ BGE_PROXY_FROM_REF_BORROW(self_v), 3,
+ mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_SCALE_GLOBAL);
#else
KX_GameObject* self = static_cast<KX_GameObject*>(self_v);
return PyObjectFrom(self->NodeGetWorldScaling());
@@ -2520,7 +2743,9 @@ int KX_GameObject::pyattr_set_worldScaling(void *self_v, const KX_PYATTRIBUTE_DE
PyObject *KX_GameObject::pyattr_get_localScaling(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
#ifdef USE_MATHUTILS
- return Vector_CreatePyObject_cb(BGE_PROXY_FROM_REF(self_v), 3, mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_SCALE_LOCAL);
+ return Vector_CreatePyObject_cb(
+ BGE_PROXY_FROM_REF_BORROW(self_v), 3,
+ mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_SCALE_LOCAL);
#else
KX_GameObject* self = static_cast<KX_GameObject*>(self_v);
return PyObjectFrom(self->NodeGetLocalScaling());
@@ -2622,7 +2847,9 @@ int KX_GameObject::pyattr_set_worldTransform(void *self_v, const KX_PYATTRIBUTE_
PyObject *KX_GameObject::pyattr_get_worldLinearVelocity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
#ifdef USE_MATHUTILS
- return Vector_CreatePyObject_cb(BGE_PROXY_FROM_REF(self_v), 3, mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_LINVEL_GLOBAL);
+ return Vector_CreatePyObject_cb(
+ BGE_PROXY_FROM_REF_BORROW(self_v), 3,
+ mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_LINVEL_GLOBAL);
#else
KX_GameObject* self = static_cast<KX_GameObject*>(self_v);
return PyObjectFrom(GetLinearVelocity(false));
@@ -2644,7 +2871,9 @@ int KX_GameObject::pyattr_set_worldLinearVelocity(void *self_v, const KX_PYATTRI
PyObject *KX_GameObject::pyattr_get_localLinearVelocity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
#ifdef USE_MATHUTILS
- return Vector_CreatePyObject_cb(BGE_PROXY_FROM_REF(self_v), 3, mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_LINVEL_LOCAL);
+ return Vector_CreatePyObject_cb(
+ BGE_PROXY_FROM_REF_BORROW(self_v), 3,
+ mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_LINVEL_LOCAL);
#else
KX_GameObject* self = static_cast<KX_GameObject*>(self_v);
return PyObjectFrom(GetLinearVelocity(true));
@@ -2666,7 +2895,9 @@ int KX_GameObject::pyattr_set_localLinearVelocity(void *self_v, const KX_PYATTRI
PyObject *KX_GameObject::pyattr_get_worldAngularVelocity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
#ifdef USE_MATHUTILS
- return Vector_CreatePyObject_cb(BGE_PROXY_FROM_REF(self_v), 3, mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_ANGVEL_GLOBAL);
+ return Vector_CreatePyObject_cb(
+ BGE_PROXY_FROM_REF_BORROW(self_v), 3,
+ mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_ANGVEL_GLOBAL);
#else
KX_GameObject* self = static_cast<KX_GameObject*>(self_v);
return PyObjectFrom(GetAngularVelocity(false));
@@ -2688,7 +2919,9 @@ int KX_GameObject::pyattr_set_worldAngularVelocity(void *self_v, const KX_PYATTR
PyObject *KX_GameObject::pyattr_get_localAngularVelocity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
#ifdef USE_MATHUTILS
- return Vector_CreatePyObject_cb(BGE_PROXY_FROM_REF(self_v), 3, mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_ANGVEL_LOCAL);
+ return Vector_CreatePyObject_cb(
+ BGE_PROXY_FROM_REF_BORROW(self_v), 3,
+ mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_ANGVEL_LOCAL);
#else
KX_GameObject* self = static_cast<KX_GameObject*>(self_v);
return PyObjectFrom(GetAngularVelocity(true));
@@ -2707,6 +2940,34 @@ int KX_GameObject::pyattr_set_localAngularVelocity(void *self_v, const KX_PYATTR
return PY_SET_ATTR_SUCCESS;
}
+PyObject *KX_GameObject::pyattr_get_linearDamping(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+{
+ KX_GameObject* self = static_cast<KX_GameObject*>(self_v);
+ return PyFloat_FromDouble(self->getLinearDamping());
+}
+
+int KX_GameObject::pyattr_set_linearDamping(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
+{
+ KX_GameObject* self = static_cast<KX_GameObject*>(self_v);
+ float val = PyFloat_AsDouble(value);
+ self->setLinearDamping(val);
+ return PY_SET_ATTR_SUCCESS;
+}
+
+PyObject *KX_GameObject::pyattr_get_angularDamping(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+{
+ KX_GameObject* self = static_cast<KX_GameObject*>(self_v);
+ return PyFloat_FromDouble(self->getAngularDamping());
+}
+
+int KX_GameObject::pyattr_set_angularDamping(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
+{
+ KX_GameObject* self = static_cast<KX_GameObject*>(self_v);
+ float val = PyFloat_AsDouble(value);
+ self->setAngularDamping(val);
+ return PY_SET_ATTR_SUCCESS;
+}
+
PyObject *KX_GameObject::pyattr_get_timeOffset(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
@@ -2781,7 +3042,9 @@ PyObject *KX_GameObject::pyattr_get_meshes(void *self_v, const KX_PYATTRIBUTE_DE
PyObject *KX_GameObject::pyattr_get_obcolor(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
#ifdef USE_MATHUTILS
- return Vector_CreatePyObject_cb(BGE_PROXY_FROM_REF(self_v), 4, mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_OBJECT_COLOR);
+ return Vector_CreatePyObject_cb(
+ BGE_PROXY_FROM_REF_BORROW(self_v), 4,
+ mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_OBJECT_COLOR);
#else
KX_GameObject* self = static_cast<KX_GameObject*>(self_v);
return PyObjectFrom(self->GetObjectColor());
@@ -3003,6 +3266,18 @@ PyObject *KX_GameObject::PySetAngularVelocity(PyObject *args)
return NULL;
}
+PyObject *KX_GameObject::PySetDamping(PyObject *args)
+{
+ float linear;
+ float angular;
+
+ if (!PyArg_ParseTuple(args,"ff|i:setDamping", &linear, &angular))
+ return NULL;
+
+ setDamping(linear, angular);
+ Py_RETURN_NONE;
+}
+
PyObject *KX_GameObject::PySetVisible(PyObject *args)
{
int visible, recursive = 0;
@@ -3147,10 +3422,16 @@ PyObject *KX_GameObject::PyApplyImpulse(PyObject *args)
-PyObject *KX_GameObject::PySuspendDynamics()
+PyObject *KX_GameObject::PySuspendDynamics(PyObject *args)
{
+ bool ghost = false;
+
+ if (!PyArg_ParseTuple(args, "|b", &ghost))
+ return NULL;
+
if (GetPhysicsController())
- GetPhysicsController()->SuspendDynamics();
+ GetPhysicsController()->SuspendDynamics(ghost);
+
Py_RETURN_NONE;
}
@@ -3158,7 +3439,8 @@ PyObject *KX_GameObject::PySuspendDynamics()
PyObject *KX_GameObject::PyRestoreDynamics()
{
- if (GetPhysicsController())
+ // Child objects must be static, so we block changing to dynamic
+ if (GetPhysicsController() && !GetParent())
GetPhysicsController()->RestoreDynamics();
Py_RETURN_NONE;
}
@@ -3200,12 +3482,12 @@ PyObject *KX_GameObject::PyGetAxisVect(PyObject *value)
PyObject *KX_GameObject::PyGetPhysicsId()
{
PHY_IPhysicsController* ctrl = GetPhysicsController();
- uint_ptr physid=0;
+ unsigned long long physid = 0;
if (ctrl)
{
- physid= (uint_ptr)ctrl;
+ physid = (unsigned long long)ctrl;
}
- return PyLong_FromLong((long)physid);
+ return PyLong_FromUnsignedLongLong(physid);
}
PyObject *KX_GameObject::PyGetPropertyNames()
@@ -3648,7 +3930,7 @@ KX_PYMETHODDEF_DOC(KX_GameObject, stopAction,
"stopAction(layer=0)\n"
"Stop playing the action on the given layer\n")
{
- short layer=0;
+ short layer = 0;
if (!PyArg_ParseTuple(args, "|h:stopAction", &layer))
return NULL;
@@ -3664,7 +3946,7 @@ KX_PYMETHODDEF_DOC(KX_GameObject, getActionFrame,
"getActionFrame(layer=0)\n"
"Gets the current frame of the action playing in the supplied layer\n")
{
- short layer=0;
+ short layer = 0;
if (!PyArg_ParseTuple(args, "|h:getActionFrame", &layer))
return NULL;
@@ -3674,11 +3956,25 @@ KX_PYMETHODDEF_DOC(KX_GameObject, getActionFrame,
return PyFloat_FromDouble(GetActionFrame(layer));
}
+KX_PYMETHODDEF_DOC(KX_GameObject, getActionName,
+ "getActionName(layer=0)\n"
+ "Gets the name of the current action playing in the supplied layer\n")
+{
+ short layer = 0;
+
+ if (!PyArg_ParseTuple(args, "|h:getActionName", &layer))
+ return NULL;
+
+ layer_check(layer, "getActionName");
+
+ return PyUnicode_FromString(GetActionName(layer));
+}
+
KX_PYMETHODDEF_DOC(KX_GameObject, setActionFrame,
"setActionFrame(frame, layer=0)\n"
"Set the current frame of the action playing in the supplied layer\n")
{
- short layer=0;
+ short layer = 0;
float frame;
if (!PyArg_ParseTuple(args, "f|h:setActionFrame", &frame, &layer))
@@ -3695,7 +3991,7 @@ KX_PYMETHODDEF_DOC(KX_GameObject, isPlayingAction,
"isPlayingAction(layer=0)\n"
"Checks to see if there is an action playing in the given layer\n")
{
- short layer=0;
+ short layer = 0;
if (!PyArg_ParseTuple(args, "|h:isPlayingAction", &layer))
return NULL;
@@ -3793,11 +4089,11 @@ bool ConvertPythonToGameObject(PyObject *value, KX_GameObject **object, bool py_
}
}
- if ( PyObject_TypeCheck(value, &KX_GameObject::Type) ||
- PyObject_TypeCheck(value, &KX_LightObject::Type) ||
- PyObject_TypeCheck(value, &KX_Camera::Type) ||
- PyObject_TypeCheck(value, &KX_FontObject::Type) ||
- PyObject_TypeCheck(value, &KX_NavMeshObject::Type))
+ if (PyObject_TypeCheck(value, &KX_GameObject::Type) ||
+ PyObject_TypeCheck(value, &KX_LightObject::Type) ||
+ PyObject_TypeCheck(value, &KX_Camera::Type) ||
+ PyObject_TypeCheck(value, &KX_FontObject::Type) ||
+ PyObject_TypeCheck(value, &KX_NavMeshObject::Type))
{
*object = static_cast<KX_GameObject*>BGE_PROXY_REF(value);
diff --git a/source/gameengine/Ketsji/KX_GameObject.h b/source/gameengine/Ketsji/KX_GameObject.h
index d4fa4851696..c10802a83b2 100644
--- a/source/gameengine/Ketsji/KX_GameObject.h
+++ b/source/gameengine/Ketsji/KX_GameObject.h
@@ -40,7 +40,7 @@
#include <stddef.h>
-#include "ListValue.h"
+#include "EXP_ListValue.h"
#include "SCA_IObject.h"
#include "SG_Node.h"
#include "MT_Transform.h"
@@ -49,6 +49,7 @@
#include "CTR_HashedPtr.h"
#include "KX_Scene.h"
#include "KX_KetsjiEngine.h" /* for m_anim_framerate */
+#include "DNA_constraint_types.h" /* for constraint replication */
#include "DNA_object_types.h"
#include "SCA_LogicManager.h" /* for ConvertPythonToGameObject to search object names */
@@ -88,18 +89,19 @@ protected:
int m_layer;
std::vector<RAS_MeshObject*> m_meshes;
std::vector<RAS_MeshObject*> m_lodmeshes;
+ int m_currentLodLevel;
+ short m_previousLodLevel;
SG_QList m_meshSlots; // head of mesh slots of this
struct Object* m_pBlenderObject;
struct Object* m_pBlenderGroupObject;
- bool m_bSuspendDynamics;
bool m_bUseObjectColor;
bool m_bIsNegativeScaling;
MT_Vector4 m_objectColor;
// Bit fields for user control over physics collisions
- short m_userCollisionGroup;
- short m_userCollisionMask;
+ unsigned short m_userCollisionGroup;
+ unsigned short m_userCollisionMask;
// visible = user setting
// culled = while rendering, depending on camera
@@ -116,6 +118,7 @@ protected:
SG_Node* m_pSGNode;
MT_CmMatrix4x4 m_OpenGL_4x4Matrix;
+ std::vector<bRigidBodyJointConstraint*> m_constraints;
KX_ObstacleSimulation* m_pObstacleSimulation;
@@ -192,6 +195,14 @@ public:
void
UpdateBlenderObjectMatrix(Object* blendobj=NULL);
+ /**
+ * Used for constraint replication for group instances.
+ * The list of constraints is filled during data conversion.
+ */
+ void AddConstraint(bRigidBodyJointConstraint *cons);
+ std::vector<bRigidBodyJointConstraint*> GetConstraints();
+ void ClearConstraints();
+
/**
* Get a pointer to the game object that is the parent of
* this object. Or NULL if there is no parent. The returned
@@ -266,6 +277,11 @@ public:
float GetActionFrame(short layer);
/**
+ * Gets the name of the current action
+ */
+ const char *GetActionName(short layer);
+
+ /**
* Sets the current frame of an action
*/
void SetActionFrame(short layer, float frame);
@@ -291,6 +307,11 @@ public:
void StopAction(short layer);
/**
+ * Remove playing tagged actions.
+ */
+ void RemoveTaggedActions();
+
+ /**
* Check if an action has finished playing
*/
bool IsActionDone(short layer);
@@ -506,8 +527,17 @@ public:
*/
void ActivateGraphicController(bool recurse);
- void SetUserCollisionGroup(short filter);
- void SetUserCollisionMask(short mask);
+ /** Set the object's collison group
+ * \param filter The group bitfield
+ */
+ void SetUserCollisionGroup(unsigned short filter);
+
+ /** Set the object's collison mask
+ * \param filter The mask bitfield
+ */
+ void SetUserCollisionMask(unsigned short mask);
+ unsigned short GetUserCollisionGroup();
+ unsigned short GetUserCollisionMask();
/**
* Extra broadphase check for user controllable collisions
*/
@@ -607,6 +637,8 @@ public:
return m_bDyna;
}
+ bool IsDynamicsSuspended() const;
+
/**
* Should we record animation for this object?
*/
@@ -684,6 +716,12 @@ public:
bool local
);
+ virtual float getLinearDamping() const;
+ virtual float getAngularDamping() const;
+ virtual void setLinearDamping(float damping);
+ virtual void setAngularDamping(float damping);
+ virtual void setDamping(float linear, float angular);
+
/**
* Update the physics object transform based upon the current SG_Node
* position.
@@ -852,10 +890,10 @@ public:
/**
* Was this object culled?
*/
- bool
+ inline bool
GetCulled(
void
- );
+ ) { return m_bCulled; }
/**
* Set culled flag of this object
@@ -886,7 +924,7 @@ public:
* Change the layer of the object (when it is added in another layer
* than the original layer)
*/
- void
+ virtual void
SetLayer(
int l
);
@@ -913,7 +951,7 @@ public:
void RegisterCollisionCallbacks();
void UnregisterCollisionCallbacks();
- void RunCollisionCallbacks(KX_GameObject *collider);
+ void RunCollisionCallbacks(KX_GameObject *collider, const MT_Vector3 &point, const MT_Vector3 &normal);
/**
* Stop making progress
*/
@@ -965,6 +1003,7 @@ public:
KX_PYMETHOD_VARARGS(KX_GameObject,GetAngularVelocity);
KX_PYMETHOD_VARARGS(KX_GameObject,SetAngularVelocity);
KX_PYMETHOD_VARARGS(KX_GameObject,GetVelocity);
+ KX_PYMETHOD_VARARGS(KX_GameObject,SetDamping);
KX_PYMETHOD_NOARGS(KX_GameObject,GetReactionForce);
@@ -976,7 +1015,7 @@ public:
KX_PYMETHOD_O(KX_GameObject,SetState);
KX_PYMETHOD_VARARGS(KX_GameObject,AlignAxisToVect);
KX_PYMETHOD_O(KX_GameObject,GetAxisVect);
- KX_PYMETHOD_NOARGS(KX_GameObject,SuspendDynamics);
+ KX_PYMETHOD_VARARGS(KX_GameObject,SuspendDynamics);
KX_PYMETHOD_NOARGS(KX_GameObject,RestoreDynamics);
KX_PYMETHOD_NOARGS(KX_GameObject,EnableRigidBody);
KX_PYMETHOD_NOARGS(KX_GameObject,DisableRigidBody);
@@ -1003,6 +1042,7 @@ public:
KX_PYMETHOD_DOC(KX_GameObject, playAction);
KX_PYMETHOD_DOC(KX_GameObject, stopAction);
KX_PYMETHOD_DOC(KX_GameObject, getActionFrame);
+ KX_PYMETHOD_DOC(KX_GameObject, getActionName);
KX_PYMETHOD_DOC(KX_GameObject, setActionFrame);
KX_PYMETHOD_DOC(KX_GameObject, isPlayingAction);
@@ -1020,10 +1060,15 @@ public:
static PyObject* pyattr_get_life(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
static PyObject* pyattr_get_mass(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
static int pyattr_set_mass(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
+ static PyObject* pyattr_get_is_suspend_dynamics(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
static PyObject* pyattr_get_lin_vel_min(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
static int pyattr_set_lin_vel_min(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
static PyObject* pyattr_get_lin_vel_max(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
static int pyattr_set_lin_vel_max(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
+ static PyObject* pyattr_get_ang_vel_min(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+ static int pyattr_set_ang_vel_min(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
+ static PyObject* pyattr_get_ang_vel_max(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+ static int pyattr_set_ang_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);
@@ -1066,10 +1111,18 @@ public:
static int pyattr_set_obcolor(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
static PyObject* pyattr_get_collisionCallbacks(void *selv_v, const KX_PYATTRIBUTE_DEF *attrdef);
static int pyattr_set_collisionCallbacks(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
+ static PyObject* pyattr_get_collisionGroup(void *selv_v, const KX_PYATTRIBUTE_DEF *attrdef);
+ static int pyattr_set_collisionGroup(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
+ static PyObject* pyattr_get_collisionMask(void *selv_v, const KX_PYATTRIBUTE_DEF *attrdef);
+ static int pyattr_set_collisionMask(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
static PyObject* pyattr_get_debug(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
static int pyattr_set_debug(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
static PyObject* pyattr_get_debugRecursive(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
static int pyattr_set_debugRecursive(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
+ static PyObject* pyattr_get_linearDamping(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+ static int pyattr_set_linearDamping(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
+ static PyObject* pyattr_get_angularDamping(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+ static int pyattr_set_angularDamping(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
/* Experimental! */
static PyObject* pyattr_get_sensors(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
diff --git a/source/gameengine/Ketsji/KX_ISceneConverter.h b/source/gameengine/Ketsji/KX_ISceneConverter.h
index a07d4b2195c..2e1c16c6e32 100644
--- a/source/gameengine/Ketsji/KX_ISceneConverter.h
+++ b/source/gameengine/Ketsji/KX_ISceneConverter.h
@@ -33,7 +33,7 @@
#define __KX_ISCENECONVERTER_H__
#include "STR_String.h"
-#include "KX_Python.h"
+#include "EXP_Python.h"
#ifdef WITH_CXX_GUARDEDALLOC
#include "MEM_guardedalloc.h"
@@ -45,8 +45,8 @@ class KX_ISceneConverter
{
public:
- KX_ISceneConverter() :addInitFromFrame(false) {}//this addInitFromFrame is a back hack, todo remove
- virtual ~KX_ISceneConverter () {};
+ KX_ISceneConverter() {}
+ virtual ~KX_ISceneConverter () {}
/*
* scenename: name of the scene to be converted,
@@ -59,7 +59,7 @@ public:
class RAS_IRasterizer* rendertools,
class RAS_ICanvas* canvas,
bool libloading=false)=0;
-
+
virtual void RemoveScene(class KX_Scene *scene)=0;
// handle any pending merges from asynchronous loads
@@ -69,11 +69,9 @@ public:
virtual void SetNewFileName(const STR_String& filename) = 0;
virtual bool TryAndLoadNewFile() = 0;
- bool addInitFromFrame;//rcruiz
virtual void ResetPhysicsObjectsAnimationIpo(bool clearIpo) = 0;
-
///this generates ipo curves for position, rotation, allowing to use game physics in animation
virtual void WritePhysicsObjectToAnimationIpo(int frameNumber) = 0;
virtual void TestHandlesPhysicsObjectToAnimationIpo() = 0;
diff --git a/source/gameengine/Ketsji/KX_IpoActuator.cpp b/source/gameengine/Ketsji/KX_IpoActuator.cpp
index 1597d7f8809..ec7a4146b7d 100644
--- a/source/gameengine/Ketsji/KX_IpoActuator.cpp
+++ b/source/gameengine/Ketsji/KX_IpoActuator.cpp
@@ -36,7 +36,7 @@
#include "KX_IpoActuator.h"
#include "KX_GameObject.h"
-#include "FloatValue.h"
+#include "EXP_FloatValue.h"
#include "KX_KetsjiEngine.h"
diff --git a/source/gameengine/Ketsji/KX_IpoConvert.cpp b/source/gameengine/Ketsji/KX_IpoConvert.cpp
index 57130bf57b2..7b00760ee7b 100644
--- a/source/gameengine/Ketsji/KX_IpoConvert.cpp
+++ b/source/gameengine/Ketsji/KX_IpoConvert.cpp
@@ -269,52 +269,80 @@ SG_Controller *BL_CreateCameraIPO(struct bAction *action, KX_GameObject* camera
return ipocontr;
}
-void BL_ConvertWorldIpos(struct World* blenderworld,KX_BlenderSceneConverter *converter)
-{
-
- if (blenderworld->adt) {
- KX_WorldIpoController* ipocontr = new KX_WorldIpoController();
-
-// Erwin, hook up the world ipo controller here
-// Gino: hook it up to what ?
-// is there a userinterface element for that ?
-// for now, we have some new python hooks to access the data, for a work-around
-
- ipocontr->m_mist_start = blenderworld->miststa;
- ipocontr->m_mist_dist = blenderworld->mistdist;
- ipocontr->m_mist_rgb[0] = blenderworld->horr;
- ipocontr->m_mist_rgb[1] = blenderworld->horg;
- ipocontr->m_mist_rgb[2] = blenderworld->horb;
+SG_Controller * BL_CreateWorldIPO( bAction *action, struct World *blenderworld, KX_BlenderSceneConverter *converter )
+{
+ KX_WorldIpoController *ipocontr = NULL;
- BL_InterpolatorList *adtList= GetAdtList(blenderworld->adt->action, converter);
+ if (blenderworld) {
+ BL_InterpolatorList *adtList = GetAdtList(action, converter);
- // For each active channel in the adtList add an
- // interpolator to the game object.
-
+ // For each active channel in the adtList add an interpolator to the game object.
KX_IInterpolator *interpolator;
KX_IScalarInterpolator *interp;
-
+
+ for (int i=0; i<3; i++) {
+ if ((interp = adtList->GetScalarInterpolator("ambient_color", i))) {
+ if (!ipocontr) {
+ ipocontr = new KX_WorldIpoController();
+ }
+ interpolator = new KX_ScalarInterpolator(&ipocontr->m_ambi_rgb[i], interp);
+ ipocontr->AddInterpolator(interpolator);
+ ipocontr->SetModifyAmbientColor(true);
+ }
+ }
+
for (int i=0; i<3; i++) {
if ((interp = adtList->GetScalarInterpolator("horizon_color", i))) {
- interpolator= new KX_ScalarInterpolator(&ipocontr->m_mist_rgb[i], interp);
+ if (!ipocontr) {
+ ipocontr = new KX_WorldIpoController();
+ }
+ interpolator = new KX_ScalarInterpolator(&ipocontr->m_hori_rgb[i], interp);
ipocontr->AddInterpolator(interpolator);
- ipocontr->SetModifyMistColor(true);
+ ipocontr->SetModifyHorizonColor(true);
}
}
- if ((interp = adtList->GetScalarInterpolator("mist.depth", 0))) {
- interpolator= new KX_ScalarInterpolator(&ipocontr->m_mist_dist, interp);
+ if ((interp = adtList->GetScalarInterpolator("mist_settings.start", 0))) {
+ if (!ipocontr) {
+ ipocontr = new KX_WorldIpoController();
+ }
+ interpolator = new KX_ScalarInterpolator(&ipocontr->m_mist_start, interp);
+ ipocontr->AddInterpolator(interpolator);
+ ipocontr->SetModifyMistStart(true);
+ }
+
+ if ((interp = adtList->GetScalarInterpolator("mist_settings.depth", 0))) {
+ if (!ipocontr) {
+ ipocontr = new KX_WorldIpoController();
+ }
+ interpolator = new KX_ScalarInterpolator(&ipocontr->m_mist_dist, interp);
ipocontr->AddInterpolator(interpolator);
ipocontr->SetModifyMistDist(true);
}
- if ((interp = adtList->GetScalarInterpolator("mist.start", 0))) {
- interpolator= new KX_ScalarInterpolator(&ipocontr->m_mist_start, interp);
+ if ((interp = adtList->GetScalarInterpolator("mist_settings.intensity", 0))) {
+ if (!ipocontr) {
+ ipocontr = new KX_WorldIpoController();
+ }
+ interpolator = new KX_ScalarInterpolator(&ipocontr->m_mist_intensity, interp);
ipocontr->AddInterpolator(interpolator);
- ipocontr->SetModifyMistStart(true);
+ ipocontr->SetModifyMistIntensity(true);
+ }
+
+ if (ipocontr) {
+ ipocontr->m_mist_start = blenderworld->miststa;
+ ipocontr->m_mist_dist = blenderworld->mistdist;
+ ipocontr->m_mist_intensity = blenderworld->misi;
+ ipocontr->m_hori_rgb[0] = blenderworld->horr;
+ ipocontr->m_hori_rgb[1] = blenderworld->horg;
+ ipocontr->m_hori_rgb[2] = blenderworld->horb;
+ ipocontr->m_ambi_rgb[0] = blenderworld->ambr;
+ ipocontr->m_ambi_rgb[1] = blenderworld->ambg;
+ ipocontr->m_ambi_rgb[2] = blenderworld->ambb;
}
}
+ return ipocontr;
}
SG_Controller *BL_CreateMaterialIpo(
@@ -368,7 +396,7 @@ SG_Controller *BL_CreateMaterialIpo(
ipocontr->AddInterpolator(interpolator);
}
- if ((sinterp = adtList->GetScalarInterpolator("specularity", 0))) {
+ if ((sinterp = adtList->GetScalarInterpolator("specular_intensity", 0))) {
if (!ipocontr) {
ipocontr = new KX_MaterialIpoController(matname_hash);
}
@@ -376,7 +404,7 @@ SG_Controller *BL_CreateMaterialIpo(
ipocontr->AddInterpolator(interpolator);
}
- if ((sinterp = adtList->GetScalarInterpolator("diffuse_reflection", 0))) {
+ if ((sinterp = adtList->GetScalarInterpolator("diffuse_intensity", 0))) {
if (!ipocontr) {
ipocontr = new KX_MaterialIpoController(matname_hash);
}
diff --git a/source/gameengine/Ketsji/KX_IpoConvert.h b/source/gameengine/Ketsji/KX_IpoConvert.h
index a653e4e110b..6db43552811 100644
--- a/source/gameengine/Ketsji/KX_IpoConvert.h
+++ b/source/gameengine/Ketsji/KX_IpoConvert.h
@@ -50,7 +50,8 @@ SG_Controller *BL_CreateLampIPO(bAction *action,
KX_GameObject* lightobj,
KX_BlenderSceneConverter *converter);
-void BL_ConvertWorldIpos(struct World* blenderworld,
+SG_Controller *BL_CreateWorldIPO(bAction *action,
+ struct World *blenderworld,
KX_BlenderSceneConverter *converter);
SG_Controller *BL_CreateCameraIPO(bAction *action,
diff --git a/source/gameengine/Ketsji/KX_KetsjiEngine.cpp b/source/gameengine/Ketsji/KX_KetsjiEngine.cpp
index 14772cda113..72c512589a4 100644
--- a/source/gameengine/Ketsji/KX_KetsjiEngine.cpp
+++ b/source/gameengine/Ketsji/KX_KetsjiEngine.cpp
@@ -41,11 +41,11 @@
#include "KX_KetsjiEngine.h"
-#include "ListValue.h"
-#include "IntValue.h"
-#include "VectorValue.h"
-#include "BoolValue.h"
-#include "FloatValue.h"
+#include "EXP_ListValue.h"
+#include "EXP_IntValue.h"
+#include "EXP_VectorValue.h"
+#include "EXP_BoolValue.h"
+#include "EXP_FloatValue.h"
#include "RAS_BucketManager.h"
#include "RAS_Rect.h"
@@ -62,11 +62,6 @@
#include "KX_PyConstraintBinding.h"
#include "PHY_IPhysicsEnvironment.h"
-#ifdef WITH_AUDASPACE
-# include "AUD_C-API.h"
-# include "AUD_I3DDevice.h"
-#endif
-
#include "NG_NetworkScene.h"
#include "NG_NetworkDeviceInterface.h"
@@ -80,9 +75,6 @@
#include "KX_NavMeshObject.h"
-// If define: little test for Nzc: guarded drawing. If the canvas is
-// not valid, skip rendering this frame.
-//#define NZC_GUARDED_OUTPUT
#define DEFAULT_LOGIC_TIC_RATE 60.0
//#define DEFAULT_PHYSICS_TIC_RATE 60.0
@@ -140,6 +132,7 @@ KX_KetsjiEngine::KX_KetsjiEngine(KX_ISystem* system)
m_frameTime(0.f),
m_clockTime(0.f),
m_previousClockTime(0.f),
+ m_previousAnimTime(0.f),
m_exitcode(KX_EXIT_REQUEST_NO_REQUEST),
@@ -314,10 +307,11 @@ void KX_KetsjiEngine::RenderDome()
// for each scene, call the proceed functions
{
scene = *sceneit;
+ KX_SetActiveScene(scene);
KX_Camera* cam = scene->GetActiveCamera();
// pass the scene's worldsettings to the rasterizer
- SetWorldSettings(scene->GetWorldInfo());
+ scene->GetWorldInfo()->UpdateWorldSettings();
// shadow buffers
if (i == 0) {
@@ -391,8 +385,10 @@ void KX_KetsjiEngine::RenderDome()
);
}
m_dome->Draw();
+
// Draw Callback for the last scene
#ifdef WITH_PYTHON
+ PHY_SetActiveEnvironment(scene->GetPhysicsEnvironment());
scene->RunDrawingCallbacks(scene->GetPostDrawCB());
#endif
EndFrame();
@@ -477,7 +473,7 @@ void KX_KetsjiEngine::ClearFrame()
if (doclear) {
KX_Scene* firstscene = *m_scenes.begin();
- SetBackGround(firstscene->GetWorldInfo());
+ firstscene->GetWorldInfo()->UpdateBackGround();
m_canvas->SetViewPort(clearvp.GetLeft(), clearvp.GetBottom(),
clearvp.GetRight(), clearvp.GetTop());
@@ -686,6 +682,9 @@ bool KX_KetsjiEngine::NextFrame()
SG_SetActiveStage(SG_STAGE_ACTUATOR_UPDATE);
scene->UpdateParents(m_frameTime);
+ // update levels of detail
+ scene->UpdateObjectLods();
+
m_logger->StartLog(tc_physics, m_kxsystem->GetTimeInSeconds(), true);
SG_SetActiveStage(SG_STAGE_PHYSICS2);
scene->GetPhysicsEnvironment()->BeginFrame();
@@ -730,64 +729,6 @@ bool KX_KetsjiEngine::NextFrame()
frames--;
}
- bool bUseAsyncLogicBricks= false;//true;
-
- if (bUseAsyncLogicBricks)
- {
- // Logic update sub frame: this will let some logic bricks run at the
- // full frame rate.
- for (sceneit = m_scenes.begin();sceneit != m_scenes.end(); ++sceneit)
- // for each scene, call the proceed functions
- {
- KX_Scene* scene = *sceneit;
-
- if (!scene->IsSuspended())
- {
- // if the scene was suspended recalcutlate the delta tu "curtime"
- m_suspendedtime = scene->getSuspendedTime();
- if (scene->getSuspendedTime()!=0.0)
- scene->setSuspendedDelta(scene->getSuspendedDelta()+m_clockTime-scene->getSuspendedTime());
- m_suspendeddelta = scene->getSuspendedDelta();
-
- // set Python hooks for each scene
-#ifdef WITH_PYTHON
- PHY_SetActiveEnvironment(scene->GetPhysicsEnvironment());
-#endif
- KX_SetActiveScene(scene);
-
- m_logger->StartLog(tc_scenegraph, m_kxsystem->GetTimeInSeconds(), true);
- SG_SetActiveStage(SG_STAGE_PHYSICS1);
- scene->UpdateParents(m_clockTime);
-
- // Perform physics calculations on the scene. This can involve
- // many iterations of the physics solver.
- m_logger->StartLog(tc_physics, m_kxsystem->GetTimeInSeconds(), true);
- scene->GetPhysicsEnvironment()->ProceedDeltaTime(m_clockTime,timestep,timestep);
- // Update scenegraph after physics step. This maps physics calculations
- // into node positions.
- m_logger->StartLog(tc_scenegraph, m_kxsystem->GetTimeInSeconds(), true);
- SG_SetActiveStage(SG_STAGE_PHYSICS2);
- scene->UpdateParents(m_clockTime);
-
- // Do some cleanup work for this logic frame
- m_logger->StartLog(tc_logic, m_kxsystem->GetTimeInSeconds(), true);
- scene->LogicUpdateFrame(m_clockTime, false);
-
- // Actuators can affect the scenegraph
- m_logger->StartLog(tc_scenegraph, m_kxsystem->GetTimeInSeconds(), true);
- SG_SetActiveStage(SG_STAGE_ACTUATOR);
- scene->UpdateParents(m_clockTime);
-
- scene->setSuspendedTime(0.0);
- } // suspended
- else
- if (scene->getSuspendedTime()==0.0)
- scene->setSuspendedTime(m_clockTime);
-
- m_logger->StartLog(tc_services, m_kxsystem->GetTimeInSeconds(), true);
- }
- }
-
// Start logging time spend outside main loop
m_logger->StartLog(tc_outside, m_kxsystem->GetTimeInSeconds(), true);
@@ -855,7 +796,7 @@ void KX_KetsjiEngine::Render()
KX_Scene* scene = *sceneit;
KX_Camera* cam = scene->GetActiveCamera();
// pass the scene's worldsettings to the rasterizer
- SetWorldSettings(scene->GetWorldInfo());
+ scene->GetWorldInfo()->UpdateWorldSettings();
// this is now done incrementatlly in KX_Scene::CalculateVisibleMeshes
//scene->UpdateMeshTransformations();
@@ -912,7 +853,7 @@ void KX_KetsjiEngine::Render()
KX_Camera* cam = scene->GetActiveCamera();
// pass the scene's worldsettings to the rasterizer
- SetWorldSettings(scene->GetWorldInfo());
+ scene->GetWorldInfo()->UpdateWorldSettings();
if (scene->IsClearingZBuffer())
m_rasterizer->ClearDepthBuffer();
@@ -992,54 +933,6 @@ const STR_String& KX_KetsjiEngine::GetExitString()
return m_exitstring;
}
-
-void KX_KetsjiEngine::SetBackGround(KX_WorldInfo* wi)
-{
- if (wi->hasWorld())
- {
- if (m_rasterizer->GetDrawingMode() == RAS_IRasterizer::KX_TEXTURED)
- {
- m_rasterizer->SetBackColor(
- wi->getBackColorRed(),
- wi->getBackColorGreen(),
- wi->getBackColorBlue(),
- 0.0
- );
- }
- }
-}
-
-
-
-void KX_KetsjiEngine::SetWorldSettings(KX_WorldInfo* wi)
-{
- if (wi->hasWorld())
- {
- // ...
- m_rasterizer->SetAmbientColor(
- wi->getAmbientColorRed(),
- wi->getAmbientColorGreen(),
- wi->getAmbientColorBlue()
- );
-
- if (m_rasterizer->GetDrawingMode() >= RAS_IRasterizer::KX_SOLID)
- {
- if (wi->hasMist())
- {
- m_rasterizer->SetFog(
- wi->getMistStart(),
- wi->getMistDistance(),
- wi->getMistColorRed(),
- wi->getMistColorGreen(),
- wi->getMistColorBlue()
- );
- }
- }
- }
-}
-
-
-
void KX_KetsjiEngine::EnableCameraOverride(const STR_String& forscene)
{
m_overrideCam = true;
@@ -1124,6 +1017,23 @@ void KX_KetsjiEngine::GetSceneViewport(KX_Scene *scene, KX_Camera* cam, RAS_Rect
}
}
+void KX_KetsjiEngine::UpdateAnimations(KX_Scene *scene)
+{
+ // Handle the animations independently of the logic time step
+ if (GetRestrictAnimationFPS()) {
+ double anim_timestep = 1.0 / KX_GetActiveScene()->GetAnimationFPS();
+ if (m_frameTime - m_previousAnimTime > anim_timestep || m_frameTime == m_previousAnimTime) {
+ // Sanity/debug print to make sure we're actually going at the fps we want (should be close to anim_timestep)
+ // printf("Anim fps: %f\n", 1.0/(m_frameTime - m_previousAnimTime));
+ m_previousAnimTime = m_frameTime;
+ for (KX_SceneList::iterator sceneit = m_scenes.begin(); sceneit != m_scenes.end(); ++sceneit)
+ (*sceneit)->UpdateAnimations(m_frameTime);
+ }
+ }
+ else
+ scene->UpdateAnimations(m_frameTime);
+}
+
void KX_KetsjiEngine::RenderShadowBuffers(KX_Scene *scene)
{
CListValue *lightlist = scene->GetLightList();
@@ -1155,14 +1065,13 @@ void KX_KetsjiEngine::RenderShadowBuffers(KX_Scene *scene)
raslight->BindShadowBuffer(m_canvas, cam, camtrans);
/* update scene */
- m_logger->StartLog(tc_scenegraph, m_kxsystem->GetTimeInSeconds(), true);
scene->CalculateVisibleMeshes(m_rasterizer, cam, raslight->GetShadowLayer());
m_logger->StartLog(tc_animations, m_kxsystem->GetTimeInSeconds(), true);
- scene->UpdateAnimations(GetFrameTime());
-
+ SG_SetActiveStage(SG_STAGE_ANIMATION_UPDATE);
+ UpdateAnimations(scene);
m_logger->StartLog(tc_rasterizer, m_kxsystem->GetTimeInSeconds(), true);
-
+ SG_SetActiveStage(SG_STAGE_RENDER);
/* render */
m_rasterizer->ClearDepthBuffer();
@@ -1187,6 +1096,13 @@ void KX_KetsjiEngine::RenderFrame(KX_Scene* scene, KX_Camera* cam)
if (!cam)
return;
+
+ KX_SetActiveScene(scene);
+
+#ifdef WITH_PYTHON
+ scene->RunDrawingCallbacks(scene->GetPreDrawSetupCB());
+#endif
+
GetSceneViewport(scene, cam, area, viewport);
// store the computed viewport in the scene
@@ -1238,6 +1154,8 @@ void KX_KetsjiEngine::RenderFrame(KX_Scene* scene, KX_Camera* cam)
nearfrust,
farfrust,
cam->GetSensorFit(),
+ cam->GetShiftHorizontal(),
+ cam->GetShiftVertical(),
frustum
);
if (!cam->GetViewport()) {
@@ -1258,6 +1176,8 @@ void KX_KetsjiEngine::RenderFrame(KX_Scene* scene, KX_Camera* cam)
cam->GetSensorWidth(),
cam->GetSensorHeight(),
cam->GetSensorFit(),
+ cam->GetShiftHorizontal(),
+ cam->GetShiftVertical(),
nearfrust,
farfrust,
frustum
@@ -1297,13 +1217,13 @@ void KX_KetsjiEngine::RenderFrame(KX_Scene* scene, KX_Camera* cam)
m_logger->StartLog(tc_animations, m_kxsystem->GetTimeInSeconds(), true);
SG_SetActiveStage(SG_STAGE_ANIMATION_UPDATE);
-
- scene->UpdateAnimations(GetFrameTime());
+ UpdateAnimations(scene);
m_logger->StartLog(tc_rasterizer, m_kxsystem->GetTimeInSeconds(), true);
SG_SetActiveStage(SG_STAGE_RENDER);
#ifdef WITH_PYTHON
+ PHY_SetActiveEnvironment(scene->GetPhysicsEnvironment());
// Run any pre-drawing python callbacks
scene->RunDrawingCallbacks(scene->GetPreDrawCB());
#endif
@@ -1322,13 +1242,20 @@ void KX_KetsjiEngine::RenderFrame(KX_Scene* scene, KX_Camera* cam)
*/
void KX_KetsjiEngine::PostRenderScene(KX_Scene* scene)
{
+ KX_SetActiveScene(scene);
+
// We need to first make sure our viewport is correct (enabling multiple viewports can mess this up)
m_canvas->SetViewPort(0, 0, m_canvas->GetWidth(), m_canvas->GetHeight());
- m_rasterizer->FlushDebugShapes();
+ m_rasterizer->FlushDebugShapes(scene);
scene->Render2DFilters(m_canvas);
+
#ifdef WITH_PYTHON
+ PHY_SetActiveEnvironment(scene->GetPhysicsEnvironment());
scene->RunDrawingCallbacks(scene->GetPostDrawCB());
+
+ // Python draw callback can also call debug draw functions, so we have to clear debug shapes.
+ m_rasterizer->FlushDebugShapes(scene);
#endif
}
@@ -1734,18 +1661,17 @@ void KX_KetsjiEngine::AddScheduledScenes()
bool KX_KetsjiEngine::ReplaceScene(const STR_String& oldscene,const STR_String& newscene)
{
- // Don't allow replacement if the new scene doesn't exists.
- // Allows smarter game design (used to have no check here).
- // Note that it creates a small backward compatbility issue
- // for a game that did a replace followed by a lib load with the
- // new scene in the lib => it won't work anymore, the lib
- // must be loaded before doing the replace.
- if (m_sceneconverter->GetBlenderSceneForName(newscene) != NULL)
- {
- m_replace_scenes.push_back(std::make_pair(oldscene,newscene));
- return true;
- }
- return false;
+ // Don't allow replacement if the new scene doesn't exists.
+ // Allows smarter game design (used to have no check here).
+ // Note that it creates a small backward compatbility issue
+ // for a game that did a replace followed by a lib load with the
+ // new scene in the lib => it won't work anymore, the lib
+ // must be loaded before doing the replace.
+ if (m_sceneconverter->GetBlenderSceneForName(newscene) != NULL) {
+ m_replace_scenes.push_back(std::make_pair(oldscene,newscene));
+ return true;
+ }
+ return false;
}
// replace scene is not the same as removing and adding because the
@@ -1767,21 +1693,20 @@ void KX_KetsjiEngine::ReplaceScheduledScenes()
int i=0;
/* Scenes are not supposed to be included twice... I think */
KX_SceneList::iterator sceneit;
- for (sceneit = m_scenes.begin();sceneit != m_scenes.end() ; sceneit++)
- {
- KX_Scene* scene = *sceneit;
- if (scene->GetName() == oldscenename)
- {
- // avoid crash if the new scene doesn't exist, just do nothing
- Scene *blScene = m_sceneconverter->GetBlenderSceneForName(newscenename);
- if (blScene) {
- m_sceneconverter->RemoveScene(scene);
- KX_Scene* tmpscene = CreateScene(blScene);
- m_scenes[i]=tmpscene;
- PostProcessScene(tmpscene);
- } else {
- printf("warning: scene %s could not be found, not replaced!\n",newscenename.ReadPtr());
- }
+ for (sceneit = m_scenes.begin();sceneit != m_scenes.end() ; sceneit++) {
+ KX_Scene* scene = *sceneit;
+ if (scene->GetName() == oldscenename) {
+ // avoid crash if the new scene doesn't exist, just do nothing
+ Scene *blScene = m_sceneconverter->GetBlenderSceneForName(newscenename);
+ if (blScene) {
+ m_sceneconverter->RemoveScene(scene);
+ KX_Scene* tmpscene = CreateScene(blScene);
+ m_scenes[i]=tmpscene;
+ PostProcessScene(tmpscene);
+ }
+ else {
+ printf("warning: scene %s could not be found, not replaced!\n",newscenename.ReadPtr());
+ }
}
i++;
}
@@ -1825,6 +1750,16 @@ void KX_KetsjiEngine::SetAnimRecordMode(bool animation_record, int startFrame)
m_currentFrame = startFrame;
}
+int KX_KetsjiEngine::getAnimRecordFrame() const
+{
+ return m_currentFrame;
+}
+
+void KX_KetsjiEngine::setAnimRecordFrame(int framenr)
+{
+ m_currentFrame = framenr;
+}
+
bool KX_KetsjiEngine::GetUseFixedTime(void) const
{
return m_bFixedTime;
diff --git a/source/gameengine/Ketsji/KX_KetsjiEngine.h b/source/gameengine/Ketsji/KX_KetsjiEngine.h
index 2b80e3bd69a..04e09c8db15 100644
--- a/source/gameengine/Ketsji/KX_KetsjiEngine.h
+++ b/source/gameengine/Ketsji/KX_KetsjiEngine.h
@@ -38,7 +38,7 @@
#include "STR_String.h"
#include "KX_ISystem.h"
#include "KX_Scene.h"
-#include "KX_Python.h"
+#include "EXP_Python.h"
#include "KX_WorldInfo.h"
#include <vector>
@@ -111,6 +111,7 @@ private:
double m_frameTime;//discrete timestamp of the 'game logic frame'
double m_clockTime;//current time
double m_previousClockTime;//previous clock time
+ double m_previousAnimTime; //the last time animations were updated
double m_remainingTime;
static int m_maxLogicFrame; /* maximum number of consecutive logic frame */
@@ -204,14 +205,12 @@ private:
void PostRenderScene(KX_Scene* scene);
void RenderDebugProperties();
void RenderShadowBuffers(KX_Scene *scene);
- void SetBackGround(KX_WorldInfo* worldinfo);
public:
KX_KetsjiEngine(class KX_ISystem* system);
virtual ~KX_KetsjiEngine();
// set the devices and stuff. the client must take care of creating these
- void SetWorldSettings(KX_WorldInfo* worldinfo);
void SetKeyboardDevice(SCA_IInputDevice* keyboarddevice);
void SetMouseDevice(SCA_IInputDevice* mousedevice);
void SetNetworkDevice(NG_NetworkDeviceInterface* networkdevice);
@@ -226,6 +225,9 @@ public:
KX_ISceneConverter* GetSceneConverter() { return m_sceneconverter; }
void SetAnimRecordMode(bool animation_record, int startFrame);
+ int getAnimRecordFrame() const;
+ void setAnimRecordFrame(int framenr);
+
RAS_IRasterizer* GetRasterizer() { return m_rasterizer; }
RAS_ICanvas* GetCanvas() { return m_canvas; }
SCA_IInputDevice* GetKeyboardDevice() { return m_keyboarddevice; }
@@ -258,7 +260,7 @@ public:
void ConvertAndAddScene(const STR_String& scenename,bool overlay);
void RemoveScene(const STR_String& scenename);
- bool ReplaceScene(const STR_String& oldscene,const STR_String& newscene);
+ bool ReplaceScene(const STR_String& oldscene,const STR_String& newscene);
void SuspendScene(const STR_String& scenename);
void ResumeScene(const STR_String& scenename);
@@ -273,6 +275,9 @@ public:
void SetCameraOverrideViewMatrix(const MT_CmMatrix4x4& mat);
void SetCameraOverrideClipping(float near, float far);
void SetCameraOverrideLens(float lens);
+
+ // Update animations for object in this scene
+ void UpdateAnimations(KX_Scene *scene);
/**
* Sets display of all frames.
diff --git a/source/gameengine/Ketsji/KX_Light.cpp b/source/gameengine/Ketsji/KX_Light.cpp
index 33cfec57fc0..0dec5715588 100644
--- a/source/gameengine/Ketsji/KX_Light.cpp
+++ b/source/gameengine/Ketsji/KX_Light.cpp
@@ -108,6 +108,7 @@ void KX_LightObject::UpdateScene(KX_Scene *kxscene)
void KX_LightObject::SetLayer(int layer)
{
+ KX_GameObject::SetLayer(layer);
m_lightobj->m_layer = layer;
}
@@ -166,27 +167,31 @@ PyAttributeDef KX_LightObject::Attributes[] = {
PyObject *KX_LightObject::pyattr_get_layer(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
- KX_LightObject* self = static_cast<KX_LightObject*>(self_v);
+ KX_LightObject *self = static_cast<KX_LightObject *>(self_v);
return PyLong_FromLong(self->m_lightobj->m_layer);
}
int KX_LightObject::pyattr_set_layer(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
{
- KX_LightObject* self = static_cast<KX_LightObject*>(self_v);
+ KX_LightObject *self = static_cast<KX_LightObject *>(self_v);
+ int layer = PyLong_AsLong(value);
- if (PyLong_Check(value)) {
- int val = PyLong_AsLong(value);
- if (val < 1)
- val = 1;
- else if (val > 20)
- val = 20;
+ if (layer == -1 && PyErr_Occurred()) {
+ PyErr_Format(PyExc_TypeError, "expected an integer for attribute \"%s\"", attrdef->m_name);
+ return PY_SET_ATTR_FAIL;
+ }
- self->m_lightobj->m_layer = val;
- return PY_SET_ATTR_SUCCESS;
+ if (layer < 1) {
+ PyErr_Format(PyExc_TypeError, "expected an integer greater than 1 for attribute \"%s\"", attrdef->m_name);
+ return PY_SET_ATTR_FAIL;
+ }
+ else if(layer > MAX_LIGHT_LAYERS) {
+ PyErr_Format(PyExc_TypeError, "expected an integer less than %i for attribute \"%s\"", MAX_LIGHT_LAYERS, attrdef->m_name);
+ return PY_SET_ATTR_FAIL;
}
- PyErr_Format(PyExc_TypeError, "expected an integer for attribute \"%s\"", attrdef->m_name);
- return PY_SET_ATTR_FAIL;
+ self->SetLayer(layer);
+ return PY_SET_ATTR_SUCCESS;
}
PyObject *KX_LightObject::pyattr_get_energy(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
diff --git a/source/gameengine/Ketsji/KX_Light.h b/source/gameengine/Ketsji/KX_Light.h
index 503ed7411e9..3a58584223d 100644
--- a/source/gameengine/Ketsji/KX_Light.h
+++ b/source/gameengine/Ketsji/KX_Light.h
@@ -34,6 +34,8 @@
#include "KX_GameObject.h"
+#define MAX_LIGHT_LAYERS ((1 << 20) - 1)
+
struct GPULamp;
struct Scene;
struct Base;
@@ -58,7 +60,7 @@ public:
RAS_ILightObject* GetLightData() { return m_lightobj;}
void UpdateScene(class KX_Scene *kxscene);
- void SetLayer(int layer);
+ virtual void SetLayer(int layer);
virtual int GetGameObjectType() { return OBJ_LIGHT; }
diff --git a/source/gameengine/Ketsji/KX_MaterialIpoController.cpp b/source/gameengine/Ketsji/KX_MaterialIpoController.cpp
index a9617aa47b8..1faf8f17d54 100644
--- a/source/gameengine/Ketsji/KX_MaterialIpoController.cpp
+++ b/source/gameengine/Ketsji/KX_MaterialIpoController.cpp
@@ -32,21 +32,6 @@ bool KX_MaterialIpoController::Update(double currentTime)
{
if (m_modified)
{
- m_rgba[0]=0;
- m_rgba[1]=0;
- m_rgba[2]=0;
- m_rgba[3]=0;
-
- m_specrgb[0] =0;
- m_specrgb[1] =0;
- m_specrgb[2] =0;
- m_hard =0;
- m_spec=0;
- m_ref=0;
- m_emit=0;
- m_alpha = 0;
-
-
T_InterpolatorList::iterator i;
for (i = m_interpolators.begin(); !(i == m_interpolators.end()); ++i) {
(*i)->Execute(m_ipotime);
diff --git a/source/gameengine/Ketsji/KX_MeshProxy.cpp b/source/gameengine/Ketsji/KX_MeshProxy.cpp
index a6f2f728674..c98766c9c81 100644
--- a/source/gameengine/Ketsji/KX_MeshProxy.cpp
+++ b/source/gameengine/Ketsji/KX_MeshProxy.cpp
@@ -43,7 +43,7 @@
#include "KX_PyMath.h"
-#include "PyObjectPlus.h"
+#include "EXP_PyObjectPlus.h"
PyTypeObject KX_MeshProxy::Type = {
PyVarObject_HEAD_INIT(NULL, 0)
diff --git a/source/gameengine/Ketsji/KX_MouseActuator.cpp b/source/gameengine/Ketsji/KX_MouseActuator.cpp
index aae5d18189a..154ad1da3a1 100644
--- a/source/gameengine/Ketsji/KX_MouseActuator.cpp
+++ b/source/gameengine/Ketsji/KX_MouseActuator.cpp
@@ -126,24 +126,33 @@ bool KX_MouseActuator::Update()
float movement[2];
MT_Vector3 rotation;
float setposition[2] = {0.0};
+ float center_x = 0.5, center_y = 0.5;
getMousePosition(position);
movement[0] = position[0];
movement[1] = position[1];
+ //preventing undesired drifting when resolution is odd
+ if ((m_canvas->GetWidth() % 2) != 0) {
+ center_x = ((m_canvas->GetWidth() - 1.0) / 2.0) / (m_canvas->GetWidth());
+ }
+ if ((m_canvas->GetHeight() % 2) != 0) {
+ center_y = ((m_canvas->GetHeight() - 1.0) / 2.0) / (m_canvas->GetHeight());
+ }
+
//preventing initial skipping.
if ((m_oldposition[0] <= -0.9) && (m_oldposition[1] <= -0.9)) {
if (m_reset_x) {
- m_oldposition[0] = 0.5;
+ m_oldposition[0] = center_x;
}
else {
m_oldposition[0] = position[0];
}
if (m_reset_y) {
- m_oldposition[1] = 0.5;
+ m_oldposition[1] = center_y;
}
else {
m_oldposition[1] = position[1];
@@ -156,8 +165,8 @@ bool KX_MouseActuator::Update()
if (m_use_axis_x) {
if (m_reset_x) {
- setposition[0] = 0.5;
- movement[0] -= 0.5;
+ setposition[0] = center_x;
+ movement[0] -= center_x;
}
else {
setposition[0] = position[0];
@@ -166,12 +175,10 @@ bool KX_MouseActuator::Update()
movement[0] *= -1.0;
- /* Don't apply the rotation when width resolution is odd (+ little movement) to
- avoid undesired drifting or when we are under a certain threshold for mouse
+ /* Don't apply the rotation when we are under a certain threshold for mouse
movement */
- if (!((m_canvas->GetWidth() % 2 != 0) && MT_abs(movement[0]) < 0.01) &&
- ((movement[0] > (m_threshold[0] / 10.0)) ||
+ if (((movement[0] > (m_threshold[0] / 10.0)) ||
((movement[0] * (-1.0)) > (m_threshold[0] / 10.0)))) {
movement[0] *= m_sensitivity[0];
@@ -209,15 +216,15 @@ bool KX_MouseActuator::Update()
}
}
else {
- setposition[0] = 0.5;
+ setposition[0] = center_x;
}
//Calculating Y axis.
if (m_use_axis_y) {
if (m_reset_y) {
- setposition[1] = 0.5;
- movement[1] -= 0.5;
+ setposition[1] = center_y;
+ movement[1] -= center_y;
}
else {
setposition[1] = position[1];
@@ -226,12 +233,10 @@ bool KX_MouseActuator::Update()
movement[1] *= -1.0;
- /* Don't apply the rotation when height resolution is odd (+ little movement) to
- avoid undesired drifting or when we are under a certain threshold for mouse
+ /* Don't apply the rotation when we are under a certain threshold for mouse
movement */
- if (!((m_canvas->GetHeight() % 2 != 0) && MT_abs(movement[1]) < 0.01) &&
- ((movement[1] > (m_threshold[1] / 10.0)) ||
+ if (((movement[1] > (m_threshold[1] / 10.0)) ||
((movement[1] * (-1.0)) > (m_threshold[1] / 10.0)))) {
movement[1] *= m_sensitivity[1];
@@ -270,10 +275,13 @@ bool KX_MouseActuator::Update()
}
}
else {
- setposition[1] = 0.5;
+ setposition[1] = center_y;
}
- setMousePosition(setposition[0], setposition[1]);
+ // only trigger mouse event when it is necessary
+ if (m_oldposition[0] != position[0] || m_oldposition[1] != position[1]) {
+ setMousePosition(setposition[0], setposition[1]);
+ }
m_oldposition[0] = position[0];
m_oldposition[1] = position[1];
@@ -311,7 +319,7 @@ void KX_MouseActuator::ProcessReplica()
void KX_MouseActuator::getMousePosition(float* pos)
{
- MT_assert(!m_mouse);
+ MT_assert(m_mouse);
const SCA_InputEvent & xevent = m_mouse->GetEventValue(SCA_IInputDevice::KX_MOUSEX);
const SCA_InputEvent & yevent = m_mouse->GetEventValue(SCA_IInputDevice::KX_MOUSEY);
@@ -329,7 +337,7 @@ void KX_MouseActuator::setMousePosition(float fx, float fy)
m_canvas->SetMousePosition(x, y);
}
-#ifndef DISABLE_PYTHON
+#ifdef WITH_PYTHON
/* ------------------------------------------------------------------------- */
/* Python functions */
@@ -399,8 +407,8 @@ int KX_MouseActuator::pyattr_set_limit_x(void *self_v, const KX_PYATTRIBUTE_DEF
if (PyList_Size(value) != 2)
return PY_SET_ATTR_FAIL;
- item1 = PyList_GetItem(value, 0);
- item2 = PyList_GetItem(value, 1);
+ item1 = PyList_GET_ITEM(value, 0);
+ item2 = PyList_GET_ITEM(value, 1);
if (!(PyFloat_Check(item1)) || !(PyFloat_Check(item2))) {
return PY_SET_ATTR_FAIL;
@@ -430,8 +438,8 @@ int KX_MouseActuator::pyattr_set_limit_y(void *self_v, const KX_PYATTRIBUTE_DEF
if (PyList_Size(value) != 2)
return PY_SET_ATTR_FAIL;
- item1 = PyList_GetItem(value, 0);
- item2 = PyList_GetItem(value, 1);
+ item1 = PyList_GET_ITEM(value, 0);
+ item2 = PyList_GET_ITEM(value, 1);
if (!(PyFloat_Check(item1)) || !(PyFloat_Check(item2))) {
return PY_SET_ATTR_FAIL;
@@ -461,8 +469,8 @@ int KX_MouseActuator::pyattr_set_angle(void *self_v, const KX_PYATTRIBUTE_DEF *a
if (PyList_Size(value) != 2)
return PY_SET_ATTR_FAIL;
- item1 = PyList_GetItem(value, 0);
- item2 = PyList_GetItem(value, 1);
+ item1 = PyList_GET_ITEM(value, 0);
+ item2 = PyList_GET_ITEM(value, 1);
if (!(PyFloat_Check(item1)) || !(PyFloat_Check(item2))) {
return PY_SET_ATTR_FAIL;
@@ -528,4 +536,4 @@ PyObject* KX_MouseActuator::PyReset()
Py_RETURN_NONE;
}
-#endif
+#endif /* WITH_PYTHON */
diff --git a/source/gameengine/Ketsji/KX_MouseActuator.h b/source/gameengine/Ketsji/KX_MouseActuator.h
index bf90bd21dac..e244e271428 100644
--- a/source/gameengine/Ketsji/KX_MouseActuator.h
+++ b/source/gameengine/Ketsji/KX_MouseActuator.h
@@ -104,6 +104,9 @@ public:
virtual void getMousePosition(float*);
virtual void setMousePosition(float, float);
+
+#ifdef WITH_PYTHON
+
/* --------------------------------------------------------------------- */
/* Python interface ---------------------------------------------------- */
/* --------------------------------------------------------------------- */
@@ -122,6 +125,8 @@ public:
static PyObject* pyattr_get_angle(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
static int pyattr_set_angle(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
+#endif /* WITH_PYTHON */
+
};
#endif //__KX_MOUSEACTUATOR_DOC
diff --git a/source/gameengine/Ketsji/KX_MouseFocusSensor.cpp b/source/gameengine/Ketsji/KX_MouseFocusSensor.cpp
index a9f6bb0d2ff..46f27e1a2df 100644
--- a/source/gameengine/Ketsji/KX_MouseFocusSensor.cpp
+++ b/source/gameengine/Ketsji/KX_MouseFocusSensor.cpp
@@ -36,10 +36,13 @@
# pragma warning(disable:4786)
#endif
+#include <stdio.h>
+
#include "MT_Point3.h"
#include "RAS_FramingManager.h"
#include "RAS_ICanvas.h"
#include "RAS_IRasterizer.h"
+#include "RAS_MeshObject.h"
#include "SCA_IScene.h"
#include "KX_Scene.h"
#include "KX_Camera.h"
@@ -163,15 +166,17 @@ bool KX_MouseFocusSensor::RayHit(KX_ClientObjectInfo *client_info, KX_RayCast *r
}
else
{
- if (m_bFindMaterial)
- {
- if (client_info->m_auxilary_info)
- {
- bFound = (m_propertyname== ((char*)client_info->m_auxilary_info));
+ if (m_bFindMaterial) {
+ for (unsigned int i = 0; i < hitKXObj->GetMeshCount(); ++i) {
+ RAS_MeshObject *meshObj = hitKXObj->GetMesh(i);
+ for (unsigned int j = 0; j < meshObj->NumMaterials(); ++j) {
+ bFound = strcmp(m_propertyname.ReadPtr(), meshObj->GetMaterialName(j).ReadPtr() + 2) == 0;
+ if (bFound)
+ break;
+ }
}
}
- else
- {
+ else {
bFound = hitKXObj->GetProperty(m_propertyname) != NULL;
}
}
@@ -195,6 +200,8 @@ bool KX_MouseFocusSensor::RayHit(KX_ClientObjectInfo *client_info, KX_RayCast *r
*/
bool KX_MouseFocusSensor::NeedRayCast(KX_ClientObjectInfo* client)
{
+ KX_GameObject *hitKXObj = client->m_gameobject;
+
if (client->m_type > KX_ClientObjectInfo::ACTOR)
{
// Unknown type of object, skip it.
@@ -206,14 +213,21 @@ bool KX_MouseFocusSensor::NeedRayCast(KX_ClientObjectInfo* client)
{
if (m_bFindMaterial)
{
- // not quite correct: an object may have multiple material
- // should check all the material and not only the first one
- if (!client->m_auxilary_info || (m_propertyname != ((char*)client->m_auxilary_info)))
+ bool found = false;
+ for (unsigned int i = 0; i < hitKXObj->GetMeshCount(); ++i) {
+ RAS_MeshObject *meshObj = hitKXObj->GetMesh(i);
+ for (unsigned int j = 0; j < meshObj->NumMaterials(); ++j) {
+ found = strcmp(m_propertyname.ReadPtr(), meshObj->GetMaterialName(j).ReadPtr() + 2) == 0;
+ if (found)
+ break;
+ }
+ }
+ if (!found)
return false;
}
else
{
- if (client->m_gameobject->GetProperty(m_propertyname) == NULL)
+ if (hitKXObj->GetProperty(m_propertyname) == NULL)
return false;
}
}
@@ -269,8 +283,8 @@ bool KX_MouseFocusSensor::ParentObjectHasFocusCamera(KX_Camera *cam)
m_kxengine->GetSceneViewport(m_kxscene, cam, area, viewport);
/* Check if the mouse is in the viewport */
- if (( m_x < viewport.m_x2 && // less then right
- m_x > viewport.m_x1 && // more then then left
+ if (( m_x < viewport.m_x2 && // less than right
+ m_x > viewport.m_x1 && // more than then left
m_y_inv < viewport.m_y2 && // below top
m_y_inv > viewport.m_y1) == 0) // above bottom
{
diff --git a/source/gameengine/Ketsji/KX_NavMeshObject.cpp b/source/gameengine/Ketsji/KX_NavMeshObject.cpp
index 8360681759a..b8907ca5c6b 100644
--- a/source/gameengine/Ketsji/KX_NavMeshObject.cpp
+++ b/source/gameengine/Ketsji/KX_NavMeshObject.cpp
@@ -45,7 +45,7 @@ extern "C" {
#include "KX_PythonInit.h"
#include "KX_PyMath.h"
-#include "Value.h"
+#include "EXP_Value.h"
#include "Recast.h"
#include "DetourStatNavMeshBuilder.h"
#include "KX_ObstacleSimulation.h"
@@ -98,12 +98,14 @@ void KX_NavMeshObject::ProcessReplica()
{
KX_GameObject::ProcessReplica();
m_navMesh = NULL; /* without this, building frees the navmesh we copied from */
- BuildNavMesh();
+ if (!BuildNavMesh()) {
+ std::cout << "Error in " << __func__ << ": unable to build navigation mesh" << std::endl;
+ return;
+ }
KX_Scene* scene = KX_GetActiveScene();
KX_ObstacleSimulation* obssimulation = scene->GetObstacleSimulation();
if (obssimulation)
obssimulation->AddObstaclesForNavMesh(this);
-
}
bool KX_NavMeshObject::BuildVertIndArrays(float *&vertices, int& nverts,
@@ -321,7 +323,11 @@ bool KX_NavMeshObject::BuildNavMesh()
}
}
- buildMeshAdjacency(polys, npolys, nverts, vertsPerPoly);
+ if (!buildMeshAdjacency(polys, npolys, nverts, vertsPerPoly)) {
+ std::cout << __func__ << ": unable to build mesh adjacency information." << std::endl;
+ delete[] vertices;
+ return false;
+ }
float cs = 0.2f;
diff --git a/source/gameengine/Ketsji/KX_NavMeshObject.h b/source/gameengine/Ketsji/KX_NavMeshObject.h
index 1599361b334..af178f9aaee 100644
--- a/source/gameengine/Ketsji/KX_NavMeshObject.h
+++ b/source/gameengine/Ketsji/KX_NavMeshObject.h
@@ -28,7 +28,7 @@
#define __KX_NAVMESHOBJECT_H__
#include "DetourStatNavMesh.h"
#include "KX_GameObject.h"
-#include "PyObjectPlus.h"
+#include "EXP_PyObjectPlus.h"
#include <vector>
class RAS_MeshObject;
diff --git a/source/gameengine/Ketsji/KX_ObjectActuator.cpp b/source/gameengine/Ketsji/KX_ObjectActuator.cpp
index 0eec86987be..12abcb250a7 100644
--- a/source/gameengine/Ketsji/KX_ObjectActuator.cpp
+++ b/source/gameengine/Ketsji/KX_ObjectActuator.cpp
@@ -75,7 +75,8 @@ KX_ObjectActuator(
m_reference(refobj),
m_active_combined_velocity (false),
m_linear_damping_active(false),
- m_angular_damping_active(false)
+ m_angular_damping_active(false),
+ m_jumping(false)
{
if (m_bitLocalFlag.ServoControl)
{
@@ -140,6 +141,7 @@ bool KX_ObjectActuator::Update()
m_angular_damping_active = false;
m_error_accumulator.setValue(0.0,0.0,0.0);
m_previous_error.setValue(0.0,0.0,0.0);
+ m_jumping = false;
return false;
} else if (parent)
@@ -223,6 +225,11 @@ bool KX_ObjectActuator::Update()
else if (m_bitLocalFlag.CharacterMotion) {
MT_Vector3 dir = m_dloc;
+ if (m_bitLocalFlag.DLoc) {
+ MT_Matrix3x3 basis = parent->GetPhysicsController()->GetOrientation();
+ dir = basis * dir;
+ }
+
if (m_bitLocalFlag.AddOrSetCharLoc) {
MT_Vector3 old_dir = character->GetWalkDirection();
@@ -236,21 +243,20 @@ bool KX_ObjectActuator::Update()
}
// We always want to set the walk direction since a walk direction of (0, 0, 0) should stop the character
- if (m_bitLocalFlag.DLoc)
- {
- MT_Matrix3x3 basis = parent->GetPhysicsController()->GetOrientation();
- dir = basis*dir;
- }
character->SetWalkDirection(dir/parent->GetScene()->GetPhysicsEnvironment()->GetNumTimeSubSteps());
if (!m_bitLocalFlag.ZeroDRot)
{
parent->ApplyRotation(m_drot,(m_bitLocalFlag.DRot) != 0);
}
- if (m_bitLocalFlag.CharacterJump)
- {
- character->Jump();
+ if (m_bitLocalFlag.CharacterJump) {
+ if (!m_jumping) {
+ character->Jump();
+ m_jumping = true;
+ }
+ else if (character->OnGround())
+ m_jumping = false;
}
}
else {
@@ -516,7 +522,9 @@ static Mathutils_Callback mathutils_obactu_vector_cb = {
PyObject *KX_ObjectActuator::pyattr_get_linV(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
- return Vector_CreatePyObject_cb(BGE_PROXY_FROM_REF(self_v), 3, mathutils_kxobactu_vector_cb_index, MATHUTILS_VEC_CB_LINV);
+ return Vector_CreatePyObject_cb(
+ BGE_PROXY_FROM_REF_BORROW(self_v), 3,
+ mathutils_kxobactu_vector_cb_index, MATHUTILS_VEC_CB_LINV);
}
int KX_ObjectActuator::pyattr_set_linV(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
@@ -532,7 +540,9 @@ int KX_ObjectActuator::pyattr_set_linV(void *self_v, const KX_PYATTRIBUTE_DEF *a
PyObject *KX_ObjectActuator::pyattr_get_angV(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
- return Vector_CreatePyObject_cb(BGE_PROXY_FROM_REF(self_v), 3, mathutils_kxobactu_vector_cb_index, MATHUTILS_VEC_CB_ANGV);
+ return Vector_CreatePyObject_cb(
+ BGE_PROXY_FROM_REF_BORROW(self_v), 3,
+ mathutils_kxobactu_vector_cb_index, MATHUTILS_VEC_CB_ANGV);
}
int KX_ObjectActuator::pyattr_set_angV(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
diff --git a/source/gameengine/Ketsji/KX_ObjectActuator.h b/source/gameengine/Ketsji/KX_ObjectActuator.h
index 1f2453e3700..b5622d97611 100644
--- a/source/gameengine/Ketsji/KX_ObjectActuator.h
+++ b/source/gameengine/Ketsji/KX_ObjectActuator.h
@@ -116,7 +116,8 @@ class KX_ObjectActuator : public SCA_IActuator
bool m_active_combined_velocity;
bool m_linear_damping_active;
bool m_angular_damping_active;
-
+ bool m_jumping;
+
public:
enum KX_OBJECT_ACT_VEC_TYPE {
KX_OBJECT_ACT_NODEF = 0,
diff --git a/source/gameengine/Ketsji/KX_ParentActuator.cpp b/source/gameengine/Ketsji/KX_ParentActuator.cpp
index 6926fdb1d4c..6ffa2593792 100644
--- a/source/gameengine/Ketsji/KX_ParentActuator.cpp
+++ b/source/gameengine/Ketsji/KX_ParentActuator.cpp
@@ -37,7 +37,7 @@
#include "KX_GameObject.h"
#include "KX_PythonInit.h"
-#include "PyObjectPlus.h"
+#include "EXP_PyObjectPlus.h"
/* ------------------------------------------------------------------------- */
/* Native functions */
diff --git a/source/gameengine/Ketsji/KX_PolyProxy.cpp b/source/gameengine/Ketsji/KX_PolyProxy.cpp
index ccc10eb06e3..4454543161b 100644
--- a/source/gameengine/Ketsji/KX_PolyProxy.cpp
+++ b/source/gameengine/Ketsji/KX_PolyProxy.cpp
@@ -140,21 +140,21 @@ PyObject *KX_PolyProxy::pyattr_get_v1(void *self_v, const KX_PYATTRIBUTE_DEF *at
{
KX_PolyProxy* self = static_cast<KX_PolyProxy*>(self_v);
- return PyLong_FromLong(self->m_polygon->GetVertexOffset(0));
+ return PyLong_FromLong(self->m_polygon->GetVertexOffsetAbsolute(0));
}
PyObject *KX_PolyProxy::pyattr_get_v2(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
KX_PolyProxy* self = static_cast<KX_PolyProxy*>(self_v);
- return PyLong_FromLong(self->m_polygon->GetVertexOffset(1));
+ return PyLong_FromLong(self->m_polygon->GetVertexOffsetAbsolute(1));
}
PyObject *KX_PolyProxy::pyattr_get_v3(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
KX_PolyProxy* self = static_cast<KX_PolyProxy*>(self_v);
- return PyLong_FromLong(self->m_polygon->GetVertexOffset(2));
+ return PyLong_FromLong(self->m_polygon->GetVertexOffsetAbsolute(2));
}
PyObject *KX_PolyProxy::pyattr_get_v4(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
@@ -163,7 +163,7 @@ PyObject *KX_PolyProxy::pyattr_get_v4(void *self_v, const KX_PYATTRIBUTE_DEF *at
if (3 < self->m_polygon->VertexCount())
{
- return PyLong_FromLong(self->m_polygon->GetVertexOffset(3));
+ return PyLong_FromLong(self->m_polygon->GetVertexOffsetAbsolute(3));
}
return PyLong_FromLong(0);
}
@@ -243,7 +243,7 @@ KX_PYMETHODDEF_DOC(KX_PolyProxy, getVertexIndex,
}
if (index < m_polygon->VertexCount())
{
- return PyLong_FromLong(m_polygon->GetVertexOffset(index));
+ return PyLong_FromLong(m_polygon->GetVertexOffsetAbsolute(index));
}
return PyLong_FromLong(0);
}
diff --git a/source/gameengine/Ketsji/KX_PyConstraintBinding.cpp b/source/gameengine/Ketsji/KX_PyConstraintBinding.cpp
index ebf1b9ec577..a0084662490 100644
--- a/source/gameengine/Ketsji/KX_PyConstraintBinding.cpp
+++ b/source/gameengine/Ketsji/KX_PyConstraintBinding.cpp
@@ -41,7 +41,7 @@
#include "KX_GameObject.h" // ConvertPythonToGameObject()
-#include "PyObjectPlus.h"
+#include "EXP_PyObjectPlus.h"
#ifdef WITH_BULLET
# include "LinearMath/btIDebugDraw.h"
@@ -56,38 +56,95 @@
// if there is a better way (without global), please do so!
static PHY_IPhysicsEnvironment* g_CurrentActivePhysicsEnvironment = NULL;
-static char PhysicsConstraints_module_documentation[] =
-"This is the Python API for the Physics Constraints";
-
-
-static char gPySetGravity__doc__[] = "setGravity(float x,float y,float z)";
-static char gPySetDebugMode__doc__[] = "setDebugMode(int mode)";
-
-static char gPySetNumIterations__doc__[] = "setNumIterations(int numiter) This sets the number of iterations for an iterative constraint solver";
-static char gPySetNumTimeSubSteps__doc__[] = "setNumTimeSubSteps(int numsubstep) This sets the number of substeps for each physics proceed. Tradeoff quality for performance.";
-
-
-static char gPySetDeactivationTime__doc__[] = "setDeactivationTime(float time) This sets the time after which a resting rigidbody gets deactived";
-static char gPySetDeactivationLinearTreshold__doc__[] = "setDeactivationLinearTreshold(float linearTreshold)";
-static char gPySetDeactivationAngularTreshold__doc__[] = "setDeactivationAngularTreshold(float angularTreshold)";
-static char gPySetContactBreakingTreshold__doc__[] = "setContactBreakingTreshold(float breakingTreshold) Reasonable default is 0.02 (if units are meters)";
-
-static char gPySetCcdMode__doc__[] = "setCcdMode(int ccdMode) Very experimental, not recommended";
-static char gPySetSorConstant__doc__[] = "setSorConstant(float sor) Very experimental, not recommended";
-static char gPySetSolverTau__doc__[] = "setTau(float tau) Very experimental, not recommended";
-static char gPySetSolverDamping__doc__[] = "setDamping(float damping) Very experimental, not recommended";
-static char gPySetLinearAirDamping__doc__[] = "setLinearAirDamping(float damping) Very experimental, not recommended";
-static char gPySetUseEpa__doc__[] = "setUseEpa(int epa) Very experimental, not recommended";
-static char gPySetSolverType__doc__[] = "setSolverType(int solverType) Very experimental, not recommended";
-
-
-static char gPyCreateConstraint__doc__[] = "createConstraint(ob1,ob2,float restLength,float restitution,float damping)";
-static char gPyGetVehicleConstraint__doc__[] = "getVehicleConstraint(int constraintId)";
-static char gPyGetCharacter__doc__[] = "getCharacter(KX_GameObject obj)";
-static char gPyRemoveConstraint__doc__[] = "removeConstraint(int constraintId)";
-static char gPyGetAppliedImpulse__doc__[] = "getAppliedImpulse(int constraintId)";
-
+PyDoc_STRVAR(PhysicsConstraints_module_documentation,
+"This is the Python API for the Physics Constraints"
+);
+
+PyDoc_STRVAR(gPySetGravity__doc__,
+"setGravity(float x,float y,float z)\n"
+""
+);
+PyDoc_STRVAR(gPySetDebugMode__doc__,
+"setDebugMode(int mode)\n"
+""
+);
+
+PyDoc_STRVAR(gPySetNumIterations__doc__,
+"setNumIterations(int numiter)\n"
+"This sets the number of iterations for an iterative constraint solver"
+);
+PyDoc_STRVAR(gPySetNumTimeSubSteps__doc__,
+"setNumTimeSubSteps(int numsubstep)\n"
+"This sets the number of substeps for each physics proceed. Tradeoff quality for performance."
+);
+
+PyDoc_STRVAR(gPySetDeactivationTime__doc__,
+"setDeactivationTime(float time)\n"
+"This sets the time after which a resting rigidbody gets deactived"
+);
+PyDoc_STRVAR(gPySetDeactivationLinearTreshold__doc__,
+"setDeactivationLinearTreshold(float linearTreshold)\n"
+""
+);
+PyDoc_STRVAR(gPySetDeactivationAngularTreshold__doc__,
+"setDeactivationAngularTreshold(float angularTreshold)\n"
+""
+);
+PyDoc_STRVAR(gPySetContactBreakingTreshold__doc__,
+"setContactBreakingTreshold(float breakingTreshold)\n"
+"Reasonable default is 0.02 (if units are meters)"
+);
+
+PyDoc_STRVAR(gPySetCcdMode__doc__,
+"setCcdMode(int ccdMode)\n"
+"Very experimental, not recommended"
+);
+PyDoc_STRVAR(gPySetSorConstant__doc__,
+"setSorConstant(float sor)\n"
+"Very experimental, not recommended"
+);
+PyDoc_STRVAR(gPySetSolverTau__doc__,
+"setTau(float tau)\n"
+"Very experimental, not recommended"
+);
+PyDoc_STRVAR(gPySetSolverDamping__doc__,
+"setDamping(float damping)\n"
+"Very experimental, not recommended"
+);
+PyDoc_STRVAR(gPySetLinearAirDamping__doc__,
+"setLinearAirDamping(float damping)\n"
+"Very experimental, not recommended"
+);
+PyDoc_STRVAR(gPySetUseEpa__doc__,
+"setUseEpa(int epa)\n"
+"Very experimental, not recommended"
+);
+PyDoc_STRVAR(gPySetSolverType__doc__,
+"setSolverType(int solverType)\n"
+"Very experimental, not recommended"
+);
+
+PyDoc_STRVAR(gPyCreateConstraint__doc__,
+"createConstraint(ob1,ob2,float restLength,float restitution,float damping)\n"
+""
+);
+PyDoc_STRVAR(gPyGetVehicleConstraint__doc__,
+"getVehicleConstraint(int constraintId)\n"
+""
+);
+PyDoc_STRVAR(gPyGetCharacter__doc__,
+"getCharacter(KX_GameObject obj)\n"
+""
+);
+PyDoc_STRVAR(gPyRemoveConstraint__doc__,
+"removeConstraint(int constraintId)\n"
+""
+);
+PyDoc_STRVAR(gPyGetAppliedImpulse__doc__,
+"getAppliedImpulse(int constraintId)\n"
+""
+);
@@ -438,113 +495,47 @@ static PyObject *gPyCreateConstraint(PyObject *self,
PyObject *kwds)
{
/* FIXME - physicsid is a long being cast to a pointer, should at least use PyCapsule */
-#if defined(_WIN64)
- __int64 physicsid=0,physicsid2 = 0;
-#else
- long physicsid=0,physicsid2 = 0;
-#endif
- int constrainttype=0, extrainfo=0;
- int len = PyTuple_Size(args);
- int success = 1;
+ unsigned long long physicsid = 0, physicsid2 = 0;
+ int constrainttype = 0;
int flag = 0;
+ float pivotX = 0.0f, pivotY = 0.0f, pivotZ = 0.0f, axisX = 0.0f, axisY = 0.0f, axisZ = 0.0f;
- float pivotX=1,pivotY=1,pivotZ=1,axisX=0,axisY=0,axisZ=1;
- if (len == 3)
- {
-#if defined(_WIN64)
- success = PyArg_ParseTuple(args,"LLi",&physicsid,&physicsid2,&constrainttype);
-#else
- success = PyArg_ParseTuple(args,"lli",&physicsid,&physicsid2,&constrainttype);
-#endif
- }
- else if (len == 6)
- {
-#if defined(_WIN64)
- success = PyArg_ParseTuple(args,"LLifff",&physicsid,&physicsid2,&constrainttype,
- &pivotX,&pivotY,&pivotZ);
-#else
- success = PyArg_ParseTuple(args,"llifff",&physicsid,&physicsid2,&constrainttype,
- &pivotX,&pivotY,&pivotZ);
-#endif
- }
- else if (len == 9)
- {
-#if defined(_WIN64)
- success = PyArg_ParseTuple(args,"LLiffffff",&physicsid,&physicsid2,&constrainttype,
- &pivotX,&pivotY,&pivotZ,&axisX,&axisY,&axisZ);
-#else
- success = PyArg_ParseTuple(args,"lliffffff",&physicsid,&physicsid2,&constrainttype,
- &pivotX,&pivotY,&pivotZ,&axisX,&axisY,&axisZ);
-#endif
- }
- else if (len == 10)
- {
-#if defined(_WIN64)
- success = PyArg_ParseTuple(args,"LLiffffffi",&physicsid,&physicsid2,&constrainttype,
- &pivotX,&pivotY,&pivotZ,&axisX,&axisY,&axisZ,&flag);
-#else
- success = PyArg_ParseTuple(args,"lliffffffi",&physicsid,&physicsid2,&constrainttype,
- &pivotX,&pivotY,&pivotZ,&axisX,&axisY,&axisZ,&flag);
-#endif
- }
+ static const char *kwlist[] = {"physicsid_1", "physicsid_2", "constraint_type", "pivot_x", "pivot_y", "pivot_z",
+ "axis_x", "axis_y", "axis_z", "flag", NULL};
- /* XXX extrainfo seems to be nothing implemented. right now it works as a pivot with [X,0,0] */
- else if (len == 4)
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "KKi|ffffffi:createConstraint", (char **)kwlist,
+ &physicsid, &physicsid2, &constrainttype,
+ &pivotX, &pivotY, &pivotZ, &axisX, &axisY, &axisZ, &flag))
{
-#if defined(_WIN64)
- success = PyArg_ParseTuple(args,"LLii",&physicsid,&physicsid2,&constrainttype,&extrainfo);
-#else
- success = PyArg_ParseTuple(args,"llii",&physicsid,&physicsid2,&constrainttype,&extrainfo);
-#endif
- pivotX=extrainfo;
+ return NULL;
}
- if (success)
- {
- if (PHY_GetActiveEnvironment())
- {
-
- PHY_IPhysicsController* physctrl = (PHY_IPhysicsController*) physicsid;
- PHY_IPhysicsController* physctrl2 = (PHY_IPhysicsController*) physicsid2;
- if (physctrl) //TODO:check for existence of this pointer!
- {
- PHY_ConstraintType ct = (PHY_ConstraintType) constrainttype;
- int constraintid =0;
-
- if (ct == PHY_GENERIC_6DOF_CONSTRAINT)
- {
- //convert from euler angle into axis
- float radsPerDeg = 6.283185307179586232f / 360.f;
-
- //we need to pass a full constraint frame, not just axis
- //localConstraintFrameBasis
- MT_Matrix3x3 localCFrame(MT_Vector3(radsPerDeg*axisX,radsPerDeg*axisY,radsPerDeg*axisZ));
- MT_Vector3 axis0 = localCFrame.getColumn(0);
- MT_Vector3 axis1 = localCFrame.getColumn(1);
- MT_Vector3 axis2 = localCFrame.getColumn(2);
-
- constraintid = PHY_GetActiveEnvironment()->CreateConstraint(physctrl,physctrl2,(enum PHY_ConstraintType)constrainttype,
- pivotX,pivotY,pivotZ,
- (float)axis0.x(),(float)axis0.y(),(float)axis0.z(),
- (float)axis1.x(),(float)axis1.y(),(float)axis1.z(),
- (float)axis2.x(),(float)axis2.y(),(float)axis2.z(),flag);
- }
- else {
- constraintid = PHY_GetActiveEnvironment()->CreateConstraint(physctrl,physctrl2,(enum PHY_ConstraintType)constrainttype,pivotX,pivotY,pivotZ,axisX,axisY,axisZ,0);
- }
-
- KX_ConstraintWrapper* wrap = new KX_ConstraintWrapper((enum PHY_ConstraintType)constrainttype,constraintid,PHY_GetActiveEnvironment());
-
- return wrap->NewProxy(true);
- }
-
-
+ if (PHY_GetActiveEnvironment()) {
+ PHY_IPhysicsController *physctrl = (PHY_IPhysicsController*)physicsid;
+ PHY_IPhysicsController *physctrl2 = (PHY_IPhysicsController*)physicsid2;
+ if (physctrl) { //TODO:check for existence of this pointer!
+ //convert from euler angle into axis
+ const float deg2rad = 0.017453292f;
+
+ //we need to pass a full constraint frame, not just axis
+ //localConstraintFrameBasis
+ MT_Matrix3x3 localCFrame(MT_Vector3(deg2rad*axisX, deg2rad*axisY, deg2rad*axisZ));
+ MT_Vector3 axis0 = localCFrame.getColumn(0);
+ MT_Vector3 axis1 = localCFrame.getColumn(1);
+ MT_Vector3 axis2 = localCFrame.getColumn(2);
+
+ int constraintid = PHY_GetActiveEnvironment()->CreateConstraint(
+ physctrl, physctrl2, (enum PHY_ConstraintType)constrainttype, pivotX, pivotY, pivotZ,
+ (float)axis0.x(), (float)axis0.y(), (float)axis0.z(),
+ (float)axis1.x(), (float)axis1.y(), (float)axis1.z(),
+ (float)axis2.x(), (float)axis2.y(), (float)axis2.z(), flag);
+
+ KX_ConstraintWrapper *wrap = new KX_ConstraintWrapper(
+ (enum PHY_ConstraintType)constrainttype, constraintid, PHY_GetActiveEnvironment());
+
+ return wrap->NewProxy(true);
}
}
- else {
- return NULL;
- }
-
Py_RETURN_NONE;
}
@@ -592,7 +583,7 @@ static PyObject *gPyRemoveConstraint(PyObject *self,
{
if (PHY_GetActiveEnvironment())
{
- PHY_GetActiveEnvironment()->RemoveConstraint(constraintid);
+ PHY_GetActiveEnvironment()->RemoveConstraintById(constraintid);
}
}
else {
@@ -657,7 +648,7 @@ static struct PyMethodDef physicsconstraints_methods[] = {
{"createConstraint",(PyCFunction) gPyCreateConstraint,
- METH_VARARGS, (const char *)gPyCreateConstraint__doc__},
+ METH_VARARGS|METH_KEYWORDS, (const char *)gPyCreateConstraint__doc__},
{"getVehicleConstraint",(PyCFunction) gPyGetVehicleConstraint,
METH_VARARGS, (const char *)gPyGetVehicleConstraint__doc__},
@@ -677,7 +668,7 @@ static struct PyMethodDef physicsconstraints_methods[] = {
};
static struct PyModuleDef PhysicsConstraints_module_def = {
- {}, /* m_base */
+ PyModuleDef_HEAD_INIT,
"PhysicsConstraints", /* m_name */
PhysicsConstraints_module_documentation, /* m_doc */
0, /* m_size */
@@ -688,7 +679,7 @@ static struct PyModuleDef PhysicsConstraints_module_def = {
0, /* m_free */
};
-PyObject *initPythonConstraintBinding()
+PyMODINIT_FUNC initConstraintPythonBinding()
{
PyObject *ErrorObject;
@@ -696,19 +687,8 @@ PyObject *initPythonConstraintBinding()
PyObject *d;
PyObject *item;
- /* Use existing module where possible
- * be careful not to init any runtime vars after this */
- m = PyImport_ImportModule( "PhysicsConstraints" );
- if (m) {
- Py_DECREF(m);
- return m;
- }
- else {
- PyErr_Clear();
-
- m = PyModule_Create(&PhysicsConstraints_module_def);
- PyDict_SetItemString(PySys_GetObject("modules"), PhysicsConstraints_module_def.m_name, m);
- }
+ m = PyModule_Create(&PhysicsConstraints_module_def);
+ PyDict_SetItemString(PySys_GetObject("modules"), PhysicsConstraints_module_def.m_name, m);
// Add some symbolic constants to the module
d = PyModule_GetDict(m);
@@ -747,7 +727,7 @@ PyObject *initPythonConstraintBinding()
Py_FatalError("can't initialize module PhysicsConstraints");
}
- return d;
+ return m;
}
#if 0
diff --git a/source/gameengine/Ketsji/KX_PyConstraintBinding.h b/source/gameengine/Ketsji/KX_PyConstraintBinding.h
index b4a520ce71b..2bf9f7e197d 100644
--- a/source/gameengine/Ketsji/KX_PyConstraintBinding.h
+++ b/source/gameengine/Ketsji/KX_PyConstraintBinding.h
@@ -36,7 +36,8 @@
#include <Python.h>
-PyObject* initPythonConstraintBinding();
+PyMODINIT_FUNC initConstraintPythonBinding();
+
void PHY_SetActiveEnvironment(class PHY_IPhysicsEnvironment* env);
PHY_IPhysicsEnvironment* PHY_GetActiveEnvironment();
#endif /* WITH_PYTHON */
diff --git a/source/gameengine/Ketsji/KX_PyMath.cpp b/source/gameengine/Ketsji/KX_PyMath.cpp
index 804e8de2ad1..ee05fd442ab 100644
--- a/source/gameengine/Ketsji/KX_PyMath.cpp
+++ b/source/gameengine/Ketsji/KX_PyMath.cpp
@@ -42,9 +42,9 @@
#include "MT_Matrix4x4.h"
#include "MT_Point2.h"
-#include "ListValue.h"
+#include "EXP_ListValue.h"
-#include "KX_Python.h"
+#include "EXP_Python.h"
#include "KX_PyMath.h"
bool PyOrientationTo(PyObject *pyval, MT_Matrix3x3 &rot, const char *error_prefix)
@@ -100,7 +100,7 @@ PyObject *PyObjectFrom(const MT_Matrix4x4 &mat)
#ifdef USE_MATHUTILS
float fmat[16];
mat.getValue(fmat);
- return Matrix_CreatePyObject(fmat, 4, 4, Py_NEW, NULL);
+ return Matrix_CreatePyObject(fmat, 4, 4, NULL);
#else
PyObject *collist = PyList_New(4);
PyObject *col;
@@ -124,7 +124,7 @@ PyObject *PyObjectFrom(const MT_Matrix3x3 &mat)
#ifdef USE_MATHUTILS
float fmat[9];
mat.getValue3x3(fmat);
- return Matrix_CreatePyObject(fmat, 3, 3, Py_NEW, NULL);
+ return Matrix_CreatePyObject(fmat, 3, 3, NULL);
#else
PyObject *collist = PyList_New(3);
PyObject *col;
@@ -148,7 +148,7 @@ PyObject *PyObjectFrom(const MT_Quaternion &qrot)
/* NOTE, were re-ordering here for Mathutils compat */
float fvec[4];
qrot.getValue(fvec);
- return Quaternion_CreatePyObject(fvec, Py_NEW, NULL);
+ return Quaternion_CreatePyObject(fvec, NULL);
}
#endif
@@ -157,7 +157,7 @@ PyObject *PyObjectFrom(const MT_Tuple4 &vec)
#ifdef USE_MATHUTILS
float fvec[4];
vec.getValue(fvec);
- return Vector_CreatePyObject(fvec, 4, Py_NEW, NULL);
+ return Vector_CreatePyObject(fvec, 4, NULL);
#else
PyObject *list = PyList_New(4);
PyList_SET_ITEM(list, 0, PyFloat_FromDouble(vec[0]));
@@ -173,7 +173,7 @@ PyObject *PyObjectFrom(const MT_Tuple3 &vec)
#ifdef USE_MATHUTILS
float fvec[3];
vec.getValue(fvec);
- return Vector_CreatePyObject(fvec, 3, Py_NEW, NULL);
+ return Vector_CreatePyObject(fvec, 3, NULL);
#else
PyObject *list = PyList_New(3);
PyList_SET_ITEM(list, 0, PyFloat_FromDouble(vec[0]));
@@ -188,7 +188,7 @@ PyObject *PyObjectFrom(const MT_Tuple2 &vec)
#ifdef USE_MATHUTILS
float fvec[2];
vec.getValue(fvec);
- return Vector_CreatePyObject(fvec, 2, Py_NEW, NULL);
+ return Vector_CreatePyObject(fvec, 2, NULL);
#else
PyObject *list = PyList_New(2);
PyList_SET_ITEM(list, 0, PyFloat_FromDouble(vec[0]));
@@ -197,4 +197,19 @@ PyObject *PyObjectFrom(const MT_Tuple2 &vec)
#endif
}
+PyObject *PyColorFromVector(const MT_Vector3 &vec)
+{
+#ifdef USE_MATHUTILS
+ float fvec[3];
+ vec.getValue(fvec);
+ return Color_CreatePyObject(fvec, NULL);
+#else
+ PyObject *list = PyList_New(3);
+ PyList_SET_ITEM(list, 0, PyFloat_FromDouble(vec[0]));
+ PyList_SET_ITEM(list, 1, PyFloat_FromDouble(vec[1]));
+ PyList_SET_ITEM(list, 2, PyFloat_FromDouble(vec[2]));
+ return list;
+#endif
+}
+
#endif // WITH_PYTHON
diff --git a/source/gameengine/Ketsji/KX_PyMath.h b/source/gameengine/Ketsji/KX_PyMath.h
index 159506946e8..917fd0fcda6 100644
--- a/source/gameengine/Ketsji/KX_PyMath.h
+++ b/source/gameengine/Ketsji/KX_PyMath.h
@@ -41,8 +41,8 @@
#include "MT_Matrix3x3.h"
#include "MT_Matrix4x4.h"
-#include "KX_Python.h"
-#include "PyObjectPlus.h"
+#include "EXP_Python.h"
+#include "EXP_PyObjectPlus.h"
#ifdef WITH_PYTHON
#ifdef USE_MATHUTILS
@@ -273,4 +273,9 @@ PyObject *PyObjectFrom(const MT_Tuple4 &pos);
#endif
+/**
+ * Converts an MT_Vector3 to a python color object.
+ */
+PyObject *PyColorFromVector(const MT_Vector3 &vec);
+
#endif /* WITH_PYTHON */
diff --git a/source/gameengine/Ketsji/KX_PythonInit.cpp b/source/gameengine/Ketsji/KX_PythonInit.cpp
index da8a0c0844e..2fef74ca33d 100644
--- a/source/gameengine/Ketsji/KX_PythonInit.cpp
+++ b/source/gameengine/Ketsji/KX_PythonInit.cpp
@@ -30,7 +30,7 @@
* \ingroup ketsji
*/
-#include "GL/glew.h"
+#include "glew-mx.h"
#ifdef _MSC_VER
# pragma warning (disable:4786)
@@ -51,6 +51,8 @@
# include <Python.h>
extern "C" {
+ # include "BLI_utildefines.h"
+ # include "python_utildefines.h"
# include "bpy_internal_import.h" /* from the blender python api, but we want to import text too! */
# include "py_capi_utils.h"
# include "mathutils.h" // 'mathutils' module copied here so the blenderlayer can use.
@@ -59,7 +61,7 @@ extern "C" {
# include "marshal.h" /* python header for loading/saving dicts */
}
-#include "AUD_PyInit.h"
+#include "../../../../intern/audaspace/intern/AUD_PyInit.h"
#endif /* WITH_PYTHON */
@@ -110,8 +112,8 @@ extern "C" {
#include "RAS_2DFilterManager.h"
#include "MT_Vector3.h"
#include "MT_Point3.h"
-#include "ListValue.h"
-#include "InputParser.h"
+#include "EXP_ListValue.h"
+#include "EXP_InputParser.h"
#include "KX_Scene.h"
#include "NG_NetworkScene.h" //Needed for sendMessage()
@@ -121,7 +123,7 @@ extern "C" {
#include "KX_PyMath.h"
-#include "PyObjectPlus.h"
+#include "EXP_PyObjectPlus.h"
#include "KX_PythonInitTypes.h"
@@ -130,12 +132,17 @@ extern "C" {
#include "DNA_scene_types.h"
#include "PHY_IPhysicsEnvironment.h"
+
+extern "C" {
#include "BKE_main.h"
#include "BKE_global.h"
#include "BKE_library.h"
+#include "BKE_appdir.h"
+#include "BKE_blender.h"
#include "BLI_blenlib.h"
#include "GPU_material.h"
#include "MEM_guardedalloc.h"
+}
/* for converting new scenes */
#include "KX_BlenderSceneConverter.h"
@@ -179,17 +186,17 @@ class KX_KetsjiEngine* KX_GetActiveEngine()
}
/* why is this in python? */
-void KX_RasterizerDrawDebugLine(const MT_Vector3& from,const MT_Vector3& to,const MT_Vector3& color)
+void KX_RasterizerDrawDebugLine(const MT_Vector3& from,const MT_Vector3& to,const MT_Vector3& color)
{
if (gp_Rasterizer)
- gp_Rasterizer->DrawDebugLine(from,to,color);
+ gp_Rasterizer->DrawDebugLine(gp_KetsjiScene, from, to, color);
}
void KX_RasterizerDrawDebugCircle(const MT_Vector3& center, const MT_Scalar radius, const MT_Vector3& color,
const MT_Vector3& normal, int nsector)
{
if (gp_Rasterizer)
- gp_Rasterizer->DrawDebugCircle(center, radius, color, normal, nsector);
+ gp_Rasterizer->DrawDebugCircle(gp_KetsjiScene, center, radius, color, normal, nsector);
}
#ifdef WITH_PYTHON
@@ -214,13 +221,16 @@ static void KX_MACRO_addTypesToDict_fn(PyObject *dict, const char *name, long va
// temporarily python stuff, will be put in another place later !
-#include "KX_Python.h"
+#include "EXP_Python.h"
#include "SCA_PythonController.h"
// List of methods defined in the module
static PyObject *ErrorObject;
-static const char *gPyGetRandomFloat_doc="getRandomFloat returns a random floating point value in the range [0..1]";
+PyDoc_STRVAR(gPyGetRandomFloat_doc,
+"getRandomFloat()\n"
+"returns a random floating point value in the range [0..1]"
+);
static PyObject *gPyGetRandomFloat(PyObject *)
{
return PyFloat_FromDouble(MT_random());
@@ -238,15 +248,15 @@ static PyObject *gPySetGravity(PyObject *, PyObject *value)
Py_RETURN_NONE;
}
-static char gPyExpandPath_doc[] =
-"(path) - Converts a blender internal path into a proper file system path.\n\
-path - the string path to convert.\n\n\
-Use / as directory separator in path\n\
-You can use '//' at the start of the string to define a relative path;\n\
-Blender replaces that string by the directory of the current .blend or runtime\n\
-file to make a full path name.\n\
-The function also converts the directory separator to the local file system format.";
-
+PyDoc_STRVAR(gPyExpandPath_doc,
+"expandPath(path)\n"
+"Converts a blender internal path into a proper file system path.\n"
+" path - the string path to convert.\n"
+"Use / as directory separator in path\n"
+"You can use '//' at the start of the string to define a relative path."
+"Blender replaces that string by the directory of the current .blend or runtime file to make a full path name.\n"
+"The function also converts the directory separator to the local file system format."
+);
static PyObject *gPyExpandPath(PyObject *, PyObject *args)
{
char expanded[FILE_MAX];
@@ -260,10 +270,10 @@ static PyObject *gPyExpandPath(PyObject *, PyObject *args)
return PyC_UnicodeFromByte(expanded);
}
-static char gPyStartGame_doc[] =
-"startGame(blend)\n\
-Loads the blend file";
-
+PyDoc_STRVAR(gPyStartGame_doc,
+"startGame(blend)\n"
+"Loads the blend file"
+);
static PyObject *gPyStartGame(PyObject *, PyObject *args)
{
char* blendfile;
@@ -277,10 +287,10 @@ static PyObject *gPyStartGame(PyObject *, PyObject *args)
Py_RETURN_NONE;
}
-static char gPyEndGame_doc[] =
-"endGame()\n\
-Ends the current game";
-
+PyDoc_STRVAR(gPyEndGame_doc,
+"endGame()\n"
+"Ends the current game"
+);
static PyObject *gPyEndGame(PyObject *)
{
gp_KetsjiEngine->RequestExit(KX_EXIT_REQUEST_QUIT_GAME);
@@ -290,10 +300,10 @@ static PyObject *gPyEndGame(PyObject *)
Py_RETURN_NONE;
}
-static char gPyRestartGame_doc[] =
-"restartGame()\n\
-Restarts the current game by reloading the .blend file";
-
+PyDoc_STRVAR(gPyRestartGame_doc,
+"restartGame()\n"
+"Restarts the current game by reloading the .blend file"
+);
static PyObject *gPyRestartGame(PyObject *)
{
gp_KetsjiEngine->RequestExit(KX_EXIT_REQUEST_RESTART_GAME);
@@ -302,10 +312,10 @@ static PyObject *gPyRestartGame(PyObject *)
Py_RETURN_NONE;
}
-static char gPySaveGlobalDict_doc[] =
- "saveGlobalDict()\n"
- "Saves bge.logic.globalDict to a file";
-
+PyDoc_STRVAR(gPySaveGlobalDict_doc,
+"saveGlobalDict()\n"
+"Saves bge.logic.globalDict to a file"
+);
static PyObject *gPySaveGlobalDict(PyObject *)
{
char marshal_path[512];
@@ -339,15 +349,15 @@ static PyObject *gPySaveGlobalDict(PyObject *)
Py_RETURN_NONE;
}
-static char gPyLoadGlobalDict_doc[] =
- "LoadGlobalDict()\n"
- "Loads bge.logic.globalDict from a file";
-
+PyDoc_STRVAR(gPyLoadGlobalDict_doc,
+"LoadGlobalDict()\n"
+"Loads bge.logic.globalDict from a file"
+);
static PyObject *gPyLoadGlobalDict(PyObject *)
{
char marshal_path[512];
char *marshal_buffer = NULL;
- size_t marshal_length;
+ int marshal_length;
FILE *fp = NULL;
int result;
@@ -358,7 +368,12 @@ static PyObject *gPyLoadGlobalDict(PyObject *)
if (fp) {
// obtain file size:
fseek (fp, 0, SEEK_END);
- marshal_length = (size_t)ftell(fp);
+ marshal_length = ftell(fp);
+ if (marshal_length == -1) {
+ printf("Warning: could not read position of '%s'\n", marshal_path);
+ fclose(fp);
+ Py_RETURN_NONE;
+ }
rewind(fp);
marshal_buffer = (char*)malloc (sizeof(char)*marshal_length);
@@ -380,23 +395,23 @@ static PyObject *gPyLoadGlobalDict(PyObject *)
Py_RETURN_NONE;
}
-static char gPyGetProfileInfo_doc[] =
+PyDoc_STRVAR(gPyGetProfileInfo_doc,
"getProfileInfo()\n"
-"returns a dictionary with profiling information";
-
+"returns a dictionary with profiling information"
+);
static PyObject *gPyGetProfileInfo(PyObject *)
{
return gp_KetsjiEngine->GetPyProfileDict();
}
-static char gPySendMessage_doc[] =
-"sendMessage(subject, [body, to, from])\n\
-sends a message in same manner as a message actuator\
-subject = Subject of the message\
-body = Message body\
-to = Name of object to send the message to\
-from = Name of object to send the string from";
-
+PyDoc_STRVAR(gPySendMessage_doc,
+"sendMessage(subject, [body, to, from])\n"
+"sends a message in same manner as a message actuator"
+" subject = Subject of the message"
+" body = Message body"
+" to = Name of object to send the message to"
+" from = Name of object to send the string from"
+);
static PyObject *gPySendMessage(PyObject *, PyObject *args)
{
char* subject;
@@ -511,6 +526,27 @@ static PyObject *gPyGetPhysicsTicRate(PyObject *)
return PyFloat_FromDouble(PHY_GetActiveEnvironment()->GetFixedTimeStep());
}
+static PyObject *gPySetAnimRecordFrame(PyObject *, PyObject *args)
+{
+ int anim_record_frame;
+
+ if (!PyArg_ParseTuple(args, "i:setAnimRecordFrame", &anim_record_frame))
+ return NULL;
+
+ if (anim_record_frame < 0 && (U.flag & USER_NONEGFRAMES)) {
+ PyErr_Format(PyExc_ValueError, "Frame number must be non-negative (was %i).", anim_record_frame);
+ return NULL;
+ }
+
+ gp_KetsjiEngine->setAnimRecordFrame(anim_record_frame);
+ Py_RETURN_NONE;
+}
+
+static PyObject *gPyGetAnimRecordFrame(PyObject *)
+{
+ return PyLong_FromLong(gp_KetsjiEngine->getAnimRecordFrame());
+}
+
static PyObject *gPyGetAverageFrameRate(PyObject *)
{
return PyFloat_FromDouble(KX_KetsjiEngine::GetAverageFrameRate());
@@ -556,11 +592,12 @@ static PyObject *gPyGetBlendFileList(PyObject *, PyObject *args)
return list;
}
-static char gPyAddScene_doc[] =
-"addScene(name, [overlay])\n\
-adds a scene to the game engine\n\
-name = Name of the scene\n\
-overlay = Overlay or underlay";
+PyDoc_STRVAR(gPyAddScene_doc,
+"addScene(name, [overlay])\n"
+"Adds a scene to the game engine.\n"
+" name = Name of the scene\n"
+" overlay = Overlay or underlay"
+);
static PyObject *gPyAddScene(PyObject *, PyObject *args)
{
char* name;
@@ -574,17 +611,19 @@ static PyObject *gPyAddScene(PyObject *, PyObject *args)
Py_RETURN_NONE;
}
-static const char *gPyGetCurrentScene_doc =
+PyDoc_STRVAR(gPyGetCurrentScene_doc,
"getCurrentScene()\n"
-"Gets a reference to the current scene.\n";
+"Gets a reference to the current scene."
+);
static PyObject *gPyGetCurrentScene(PyObject *self)
{
return gp_KetsjiScene->GetProxy();
}
-static const char *gPyGetSceneList_doc =
+PyDoc_STRVAR(gPyGetSceneList_doc,
"getSceneList()\n"
-"Return a list of converted scenes.\n";
+"Return a list of converted scenes."
+);
static PyObject *gPyGetSceneList(PyObject *self)
{
KX_KetsjiEngine* m_engine = KX_GetActiveEngine();
@@ -869,6 +908,8 @@ static struct PyMethodDef game_methods[] = {
{"setLogicTicRate", (PyCFunction) gPySetLogicTicRate, METH_VARARGS, (const char *)"Sets the logic tic rate"},
{"getPhysicsTicRate", (PyCFunction) gPyGetPhysicsTicRate, METH_NOARGS, (const char *)"Gets the physics tic rate"},
{"setPhysicsTicRate", (PyCFunction) gPySetPhysicsTicRate, METH_VARARGS, (const char *)"Sets the physics tic rate"},
+ {"getAnimRecordFrame", (PyCFunction) gPyGetAnimRecordFrame, METH_NOARGS, (const char *)"Gets the current frame number used for animation recording"},
+ {"setAnimRecordFrame", (PyCFunction) gPySetAnimRecordFrame, METH_VARARGS, (const char *)"Sets the current frame number used for animation recording"},
{"getExitKey", (PyCFunction) gPyGetExitKey, METH_NOARGS, (const char *)"Gets the key used to exit the game engine"},
{"setExitKey", (PyCFunction) gPySetExitKey, METH_VARARGS, (const char *)"Sets the key used to exit the game engine"},
{"getAverageFrameRate", (PyCFunction) gPyGetAverageFrameRate, METH_NOARGS, (const char *)"Gets the estimated average frame rate"},
@@ -1002,111 +1043,39 @@ static PyObject *gPyGetFocalLength(PyObject *, PyObject *, PyObject *)
Py_RETURN_NONE;
}
-static PyObject *gPySetBackgroundColor(PyObject *, PyObject *value)
+static PyObject *gPyGetStereoEye(PyObject *, PyObject *, PyObject *)
{
-
- MT_Vector4 vec;
- if (!PyVecTo(value, vec))
- return NULL;
-
- if (gp_Canvas)
- {
- gp_Rasterizer->SetBackColor((float)vec[0], (float)vec[1], (float)vec[2], (float)vec[3]);
- }
-
- KX_WorldInfo *wi = gp_KetsjiScene->GetWorldInfo();
- if (wi->hasWorld())
- wi->setBackColor((float)vec[0], (float)vec[1], (float)vec[2]);
+ int flag = RAS_IRasterizer::RAS_STEREO_LEFTEYE;
- Py_RETURN_NONE;
-}
-
-
-
-static PyObject *gPySetMistColor(PyObject *, PyObject *value)
-{
-
- MT_Vector3 vec;
- if (!PyVecTo(value, vec))
- return NULL;
-
if (!gp_Rasterizer) {
- PyErr_SetString(PyExc_RuntimeError, "Rasterizer.setMistColor(color), Rasterizer not available");
+ PyErr_SetString(PyExc_RuntimeError, "Rasterizer.getStereoEye(), Rasterizer not available");
return NULL;
}
- gp_Rasterizer->SetFogColor((float)vec[0], (float)vec[1], (float)vec[2]);
-
- Py_RETURN_NONE;
-}
-static PyObject *gPyDisableMist(PyObject *)
-{
-
- if (!gp_Rasterizer) {
- PyErr_SetString(PyExc_RuntimeError, "Rasterizer.setMistColor(color), Rasterizer not available");
- return NULL;
- }
- gp_Rasterizer->DisableFog();
-
- Py_RETURN_NONE;
-}
+ if (gp_Rasterizer->Stereo())
+ flag = gp_Rasterizer->GetEye();
-static PyObject *gPySetMistStart(PyObject *, PyObject *args)
-{
-
- float miststart;
- if (!PyArg_ParseTuple(args,"f:setMistStart",&miststart))
- return NULL;
-
- if (!gp_Rasterizer) {
- PyErr_SetString(PyExc_RuntimeError, "Rasterizer.setMistStart(float), Rasterizer not available");
- return NULL;
- }
-
- gp_Rasterizer->SetFogStart(miststart);
-
- Py_RETURN_NONE;
+ return PyLong_FromLong(flag);
}
-
-
-static PyObject *gPySetMistEnd(PyObject *, PyObject *args)
+static PyObject *gPySetBackgroundColor(PyObject *, PyObject *value)
{
-
- float mistend;
- if (!PyArg_ParseTuple(args,"f:setMistEnd",&mistend))
+ MT_Vector4 vec;
+ if (!PyVecTo(value, vec))
return NULL;
-
- if (!gp_Rasterizer) {
- PyErr_SetString(PyExc_RuntimeError, "Rasterizer.setMistEnd(float), Rasterizer not available");
+
+ KX_WorldInfo *wi = gp_KetsjiScene->GetWorldInfo();
+ if (!wi->hasWorld()) {
+ PyErr_SetString(PyExc_RuntimeError, "bge.render.SetBackgroundColor(color), World not available");
return NULL;
}
-
- gp_Rasterizer->SetFogEnd(mistend);
-
- Py_RETURN_NONE;
-}
+ ShowDeprecationWarning("setBackgroundColor()", "KX_WorldInfo.background_color");
+ wi->setBackColor((float)vec[0], (float)vec[1], (float)vec[2]);
-static PyObject *gPySetAmbientColor(PyObject *, PyObject *value)
-{
-
- MT_Vector3 vec;
- if (!PyVecTo(value, vec))
- return NULL;
-
- if (!gp_Rasterizer) {
- PyErr_SetString(PyExc_RuntimeError, "Rasterizer.setAmbientColor(color), Rasterizer not available");
- return NULL;
- }
- gp_Rasterizer->SetAmbientColor((float)vec[0], (float)vec[1], (float)vec[2]);
-
Py_RETURN_NONE;
}
-
-
-
static PyObject *gPyMakeScreenshot(PyObject *, PyObject *args)
{
char* filename;
@@ -1192,10 +1161,6 @@ static PyObject *gPySetGLSLMaterialSetting(PyObject *,
else
gs->glslflag |= flag;
- /* temporarily store the glsl settings in the scene for the GLSL materials */
- GameData *gm= &(gp_KetsjiScene->GetBlenderScene()->gm);
- gm->flag = gs->glslflag;
-
/* display lists and GLSL materials need to be remade */
if (sceneflag != gs->glslflag) {
GPU_materials_free();
@@ -1203,11 +1168,14 @@ static PyObject *gPySetGLSLMaterialSetting(PyObject *,
KX_SceneList *scenes = gp_KetsjiEngine->CurrentScenes();
KX_SceneList::iterator it;
- for (it=scenes->begin(); it!=scenes->end(); it++)
+ for (it=scenes->begin(); it!=scenes->end(); it++) {
+ // temporarily store the glsl settings in the scene for the GLSL materials
+ (*it)->GetBlenderScene()->gm.flag = gs->glslflag;
if ((*it)->GetBucketManager()) {
(*it)->GetBucketManager()->ReleaseDisplayLists();
(*it)->GetBucketManager()->ReleaseMaterials();
}
+ }
}
}
@@ -1320,7 +1288,7 @@ static PyObject *gPyDrawLine(PyObject *, PyObject *args)
if (!PyVecTo(ob_color, color))
return NULL;
- gp_Rasterizer->DrawDebugLine(from,to,color);
+ gp_Rasterizer->DrawDebugLine(gp_KetsjiScene, from, to, color);
Py_RETURN_NONE;
}
@@ -1396,7 +1364,9 @@ static PyObject *gPySetVsync(PyObject *, PyObject *args)
static PyObject *gPyGetVsync(PyObject *)
{
- return PyLong_FromLong(gp_Canvas->GetSwapInterval());
+ int interval = 0;
+ gp_Canvas->GetSwapInterval(interval);
+ return PyLong_FromLong(interval);
}
static PyObject *gPyShowFramerate(PyObject *, PyObject *args)
@@ -1463,6 +1433,24 @@ static PyObject *gPyClearDebugList(PyObject *)
Py_RETURN_NONE;
}
+static PyObject *gPyGetDisplayDimensions(PyObject *)
+{
+ PyObject *result;
+ int width, height;
+
+ gp_Canvas->GetDisplayDimensions(width, height);
+
+ result = PyTuple_New(2);
+ PyTuple_SET_ITEMS(result,
+ PyLong_FromLong(width),
+ PyLong_FromLong(height));
+
+ return result;
+}
+
+PyDoc_STRVAR(Rasterizer_module_documentation,
+"This is the Python API for the game engine of Rasterizer"
+);
static struct PyMethodDef rasterizer_methods[] = {
{"getWindowWidth",(PyCFunction) gPyGetWindowWidth,
@@ -1478,11 +1466,6 @@ static struct PyMethodDef rasterizer_methods[] = {
{"setMousePosition",(PyCFunction) gPySetMousePosition,
METH_VARARGS, "setMousePosition(int x,int y)"},
{"setBackgroundColor",(PyCFunction)gPySetBackgroundColor,METH_O,"set Background Color (rgb)"},
- {"setAmbientColor",(PyCFunction)gPySetAmbientColor,METH_O,"set Ambient Color (rgb)"},
- {"disableMist",(PyCFunction)gPyDisableMist,METH_NOARGS,"turn off mist"},
- {"setMistColor",(PyCFunction)gPySetMistColor,METH_O,"set Mist Color (rgb)"},
- {"setMistStart",(PyCFunction)gPySetMistStart,METH_VARARGS,"set Mist Start(rgb)"},
- {"setMistEnd",(PyCFunction)gPySetMistEnd,METH_VARARGS,"set Mist End(rgb)"},
{"enableMotionBlur",(PyCFunction)gPyEnableMotionBlur,METH_VARARGS,"enable motion blur"},
{"disableMotionBlur",(PyCFunction)gPyDisableMotionBlur,METH_NOARGS,"disable motion blur"},
@@ -1490,6 +1473,7 @@ static struct PyMethodDef rasterizer_methods[] = {
{"getEyeSeparation", (PyCFunction) gPyGetEyeSeparation, METH_NOARGS, "get the eye separation for stereo mode"},
{"setFocalLength", (PyCFunction) gPySetFocalLength, METH_VARARGS, "set the focal length for stereo mode"},
{"getFocalLength", (PyCFunction) gPyGetFocalLength, METH_VARARGS, "get the focal length for stereo mode"},
+ {"getStereoEye", (PyCFunction) gPyGetStereoEye, METH_VARARGS, "get the current stereoscopy eye being rendered"},
{"setMaterialMode",(PyCFunction) gPySetMaterialType,
METH_VARARGS, "set the material mode to use for OpenGL rendering"},
{"getMaterialMode",(PyCFunction) gPyGetMaterialType,
@@ -1507,6 +1491,8 @@ static struct PyMethodDef rasterizer_methods[] = {
{"setWindowSize", (PyCFunction) gPySetWindowSize, METH_VARARGS, ""},
{"setFullScreen", (PyCFunction) gPySetFullScreen, METH_O, ""},
{"getFullScreen", (PyCFunction) gPyGetFullScreen, METH_NOARGS, ""},
+ {"getDisplayDimensions", (PyCFunction) gPyGetDisplayDimensions, METH_NOARGS,
+ "Get the actual dimensions, in pixels, of the physical display (e.g., the monitor)."},
{"setMipmapping", (PyCFunction) gPySetMipmapping, METH_VARARGS, ""},
{"getMipmapping", (PyCFunction) gPyGetMipmapping, METH_NOARGS, ""},
{"setVsync", (PyCFunction) gPySetVsync, METH_VARARGS, ""},
@@ -1519,15 +1505,11 @@ static struct PyMethodDef rasterizer_methods[] = {
{ NULL, (PyCFunction) NULL, 0, NULL }
};
-// Initialization function for the module (*must* be called initGameLogic)
-static char GameLogic_module_documentation[] =
-"This is the Python API for the game engine of bge.logic"
-;
-static char Rasterizer_module_documentation[] =
-"This is the Python API for the game engine of Rasterizer"
-;
+PyDoc_STRVAR(GameLogic_module_documentation,
+"This is the Python API for the game engine of bge.logic"
+);
static struct PyModuleDef GameLogic_module_def = {
{}, /* m_base */
@@ -1541,33 +1523,20 @@ static struct PyModuleDef GameLogic_module_def = {
0, /* m_free */
};
-PyObject *initGameLogic(KX_KetsjiEngine *engine, KX_Scene* scene) // quick hack to get gravity hook
+PyMODINIT_FUNC initGameLogicPythonBinding()
{
PyObject *m;
PyObject *d;
PyObject *item; /* temp PyObject *storage */
-
- gp_KetsjiEngine = engine;
- gp_KetsjiScene = scene;
gUseVisibilityTemp=false;
-
+
PyObjectPlus::ClearDeprecationWarning(); /* Not that nice to call here but makes sure warnings are reset between loading scenes */
-
- /* Use existing module where possible
- * be careful not to init any runtime vars after this */
- m = PyImport_ImportModule( "GameLogic" );
- if (m) {
- Py_DECREF(m);
- return m;
- }
- else {
- PyErr_Clear();
- // Create the module and add the functions
- m = PyModule_Create(&GameLogic_module_def);
- PyDict_SetItemString(PySys_GetObject("modules"), GameLogic_module_def.m_name, m);
- }
-
+
+ m = PyModule_Create(&GameLogic_module_def);
+ PyDict_SetItemString(PySys_GetObject("modules"), GameLogic_module_def.m_name, m);
+
+
// Add some symbolic constants to the module
d = PyModule_GetDict(m);
@@ -1587,17 +1556,22 @@ PyObject *initGameLogic(KX_KetsjiEngine *engine, KX_Scene* scene) // quick hack
PyObject* joylist = PyList_New(JOYINDEX_MAX);
for (int i=0; i<JOYINDEX_MAX; ++i) {
- SCA_Joystick* joy = SCA_Joystick::GetInstance(i);
+ SCA_Joystick *joy = SCA_Joystick::GetInstance(i);
+ PyObject *item;
+
if (joy && joy->Connected()) {
gp_PythonJoysticks[i] = new SCA_PythonJoystick(joy);
- PyObject* tmp = gp_PythonJoysticks[i]->NewProxy(true);
- Py_INCREF(tmp);
- PyList_SET_ITEM(joylist, i, tmp);
- } else {
- joy->ReleaseInstance();
- Py_INCREF(Py_None);
- PyList_SET_ITEM(joylist, i, Py_None);
+ item = gp_PythonJoysticks[i]->NewProxy(true);
}
+ else {
+ if (joy) {
+ joy->ReleaseInstance();
+ }
+ item = Py_None;
+ }
+
+ Py_INCREF(item);
+ PyList_SET_ITEM(joylist, i, item);
}
PyDict_SetItemString(d, "joysticks", joylist);
@@ -2047,7 +2021,77 @@ void removeImportMain(struct Main *maggie)
bpy_import_main_extra_remove(maggie);
}
-// Copied from bpy_interface.c
+
+PyDoc_STRVAR(BGE_module_documentation,
+ "This module contains submodules for the Blender Game Engine.\n"
+);
+
+static struct PyModuleDef BGE_module_def = {
+ PyModuleDef_HEAD_INIT,
+ "bge", /* m_name */
+ BGE_module_documentation, /* m_doc */
+ 0, /* m_size */
+ NULL, /* m_methods */
+ NULL, /* m_reload */
+ NULL, /* m_traverse */
+ NULL, /* m_clear */
+ NULL, /* m_free */
+};
+
+PyMODINIT_FUNC initBGE(void)
+{
+ PyObject *mod;
+ PyObject *submodule;
+ PyObject *sys_modules = PyThreadState_GET()->interp->modules;
+ const char *mod_full;
+
+ mod = PyModule_Create(&BGE_module_def);
+
+ /* skip "bge." */
+#define SUBMOD (mod_full + 4)
+
+ mod_full = "bge.app";
+ PyModule_AddObject(mod, SUBMOD, (submodule = initApplicationPythonBinding()));
+ PyDict_SetItemString(sys_modules, mod_full, submodule);
+ Py_INCREF(submodule);
+
+ mod_full = "bge.constraints";
+ PyModule_AddObject(mod, SUBMOD, (submodule = initConstraintPythonBinding()));
+ PyDict_SetItemString(sys_modules, mod_full, submodule);
+ Py_INCREF(submodule);
+
+ mod_full = "bge.events";
+ PyModule_AddObject(mod, SUBMOD, (submodule = initGameKeysPythonBinding()));
+ PyDict_SetItemString(sys_modules, mod_full, submodule);
+ Py_INCREF(submodule);
+
+ mod_full = "bge.logic";
+ PyModule_AddObject(mod, SUBMOD, (submodule = initGameLogicPythonBinding()));
+ PyDict_SetItemString(sys_modules, mod_full, submodule);
+ Py_INCREF(submodule);
+
+ mod_full = "bge.render";
+ PyModule_AddObject(mod, SUBMOD, (submodule = initRasterizerPythonBinding()));
+ PyDict_SetItemString(sys_modules, mod_full, submodule);
+ Py_INCREF(submodule);
+
+ mod_full = "bge.texture";
+ PyModule_AddObject(mod, SUBMOD, (submodule = initVideoTexturePythonBinding()));
+ PyDict_SetItemString(sys_modules, mod_full, submodule);
+ Py_INCREF(submodule);
+
+ mod_full = "bge.types";
+ PyModule_AddObject(mod, SUBMOD, (submodule = initGameTypesPythonBinding()));
+ PyDict_SetItemString(sys_modules, mod_full, submodule);
+ Py_INCREF(submodule);
+
+#undef SUBMOD
+
+ return mod;
+}
+
+
+/* minimal required blender modules to run blenderplayer */
static struct _inittab bge_internal_modules[] = {
{"mathutils", PyInit_mathutils},
{"bgl", BPyInit_bgl},
@@ -2060,7 +2104,7 @@ static struct _inittab bge_internal_modules[] = {
* Python is not initialized.
* see bpy_interface.c's BPY_python_start() which shares the same functionality in blender.
*/
-PyObject *initGamePlayerPythonScripting(const STR_String& progname, TPythonSecurityLevel level, Main *maggie, int argc, char** argv)
+PyObject *initGamePlayerPythonScripting(Main *maggie, int argc, char** argv)
{
/* Yet another gotcha in the py api
* Cant run PySys_SetArgv more than once because this adds the
@@ -2069,16 +2113,22 @@ PyObject *initGamePlayerPythonScripting(const STR_String& progname, TPythonSecur
* somehow it remembers the sys.path - Campbell
*/
static bool first_time = true;
- const char * const py_path_bundle = BLI_get_folder(BLENDER_SYSTEM_PYTHON, NULL);
-
-#if 0 // TODO - py3
- STR_String pname = progname;
- Py_SetProgramName(pname.Ptr());
-#endif
-
+ const char * const py_path_bundle = BKE_appdir_folder_id(BLENDER_SYSTEM_PYTHON, NULL);
+
+ /* not essential but nice to set our name */
+ static wchar_t program_path_wchar[FILE_MAX]; /* python holds a reference */
+ BLI_strncpy_wchar_from_utf8(program_path_wchar, BKE_appdir_program_path(), ARRAY_SIZE(program_path_wchar));
+ Py_SetProgramName(program_path_wchar);
+
+ /* Update, Py3.3 resolves attempting to parse non-existing header */
+#if 0
+ /* Python 3.2 now looks for '2.xx/python/include/python3.2d/pyconfig.h' to
+ * parse from the 'sysconfig' module which is used by 'site',
+ * so for now disable site. alternatively we could copy the file. */
if (py_path_bundle != NULL) {
- Py_NoSiteFlag = 1;
+ Py_NoSiteFlag = 1; /* inhibits the automatic importing of 'site' */
}
+#endif
Py_FrozenFlag = 1;
@@ -2102,12 +2152,16 @@ PyObject *initGamePlayerPythonScripting(const STR_String& progname, TPythonSecur
PySys_SetObject("argv", py_argv);
Py_DECREF(py_argv);
}
-
+
/* Initialize thread support (also acquires lock) */
PyEval_InitThreads();
bpy_import_init(PyEval_GetBuiltins());
+ bpy_import_main_set(maggie);
+
+ initPySysObjects(maggie);
+
/* mathutils types are used by the BGE even if we don't import them */
{
PyObject *mod = PyImport_ImportModuleLevel("mathutils", NULL, NULL, NULL, 0);
@@ -2122,12 +2176,8 @@ PyObject *initGamePlayerPythonScripting(const STR_String& progname, TPythonSecur
}
#endif
- initPyTypes();
-
- bpy_import_main_set(maggie);
-
- initPySysObjects(maggie);
-
+ PyDict_SetItemString(PyImport_GetModuleDict(), "bge", initBGE());
+
first_time = false;
PyObjectPlus::ClearDeprecationWarning();
@@ -2164,12 +2214,13 @@ void exitGamePlayerPythonScripting()
/**
* Python is already initialized.
*/
-PyObject *initGamePythonScripting(const STR_String& progname, TPythonSecurityLevel level, Main *maggie)
+PyObject *initGamePythonScripting(Main *maggie)
{
-#if 0 // XXX TODO Py3
- STR_String pname = progname;
- Py_SetProgramName(pname.Ptr());
-#endif
+ /* no need to Py_SetProgramName, it was already taken care of in BPY_python_start */
+
+ bpy_import_main_set(maggie);
+
+ initPySysObjects(maggie);
#ifdef WITH_AUDASPACE
/* accessing a SoundActuator's sound results in a crash if aud is not initialized... */
@@ -2179,11 +2230,7 @@ PyObject *initGamePythonScripting(const STR_String& progname, TPythonSecurityLev
}
#endif
- initPyTypes();
-
- bpy_import_main_set(maggie);
-
- initPySysObjects(maggie);
+ PyDict_SetItemString(PyImport_GetModuleDict(), "bge", initBGE());
PyObjectPlus::NullDeprecationWarning();
@@ -2216,51 +2263,32 @@ void exitGamePythonScripting()
void setupGamePython(KX_KetsjiEngine* ketsjiengine, KX_Scene *startscene, Main *blenderdata,
PyObject *pyGlobalDict, PyObject **gameLogic, PyObject **gameLogic_keys, int argc, char** argv)
{
- PyObject *dictionaryobject;
+ PyObject *modules, *dictionaryobject;
+
+ gp_Canvas = ketsjiengine->GetCanvas();
+ gp_Rasterizer = ketsjiengine->GetRasterizer();
+ gp_KetsjiEngine = ketsjiengine;
+ gp_KetsjiScene = startscene;
if (argv) /* player only */
- dictionaryobject= initGamePlayerPythonScripting("Ketsji", psl_Lowest, blenderdata, argc, argv);
+ dictionaryobject= initGamePlayerPythonScripting(blenderdata, argc, argv);
else
- dictionaryobject= initGamePythonScripting("Ketsji", psl_Lowest, blenderdata);
+ dictionaryobject= initGamePythonScripting(blenderdata);
ketsjiengine->SetPyNamespace(dictionaryobject);
- initRasterizer(ketsjiengine->GetRasterizer(), ketsjiengine->GetCanvas());
- *gameLogic = initGameLogic(ketsjiengine, startscene);
- /* is set in initGameLogic so only set here if we want it to persist between scenes */
+ modules = PyImport_GetModuleDict();
+
+ *gameLogic = PyDict_GetItemString(modules, "GameLogic");
+ /* is set in initGameLogicPythonBinding so only set here if we want it to persist between scenes */
if (pyGlobalDict)
PyDict_SetItemString(PyModule_GetDict(*gameLogic), "globalDict", pyGlobalDict); // Same as importing the module.
*gameLogic_keys = PyDict_Keys(PyModule_GetDict(*gameLogic));
-
- initGameKeys();
- initPythonConstraintBinding();
- initVideoTexture();
-
- /* could be done a lot more nicely, but for now a quick way to get bge.* working */
- PyRun_SimpleString("sys = __import__('sys');"
- "bge = type(sys)('bge');"
- "bge.__dict__.update({'logic':__import__('GameLogic'), "
- "'render':__import__('Rasterizer'), "
- "'events':__import__('GameKeys'), "
- "'constraints':__import__('PhysicsConstraints'), "
- "'physics':__import__('PhysicsConstraints'),"
- "'types':__import__('GameTypes'), "
- "'texture':__import__('VideoTexture')});"
- /* so we can do 'import bge.foo as bar' */
- "sys.modules.update({'bge': bge, "
- "'bge.logic':bge.logic, "
- "'bge.render':bge.render, "
- "'bge.events':bge.events, "
- "'bge.constraints':bge.constraints, "
- "'bge.physics':bge.physics,"
- "'bge.types':bge.types, "
- "'bge.texture':bge.texture})"
- );
}
static struct PyModuleDef Rasterizer_module_def = {
- {}, /* m_base */
+ PyModuleDef_HEAD_INIT,
"Rasterizer", /* m_name */
Rasterizer_module_documentation, /* m_doc */
0, /* m_size */
@@ -2271,29 +2299,14 @@ static struct PyModuleDef Rasterizer_module_def = {
0, /* m_free */
};
-PyObject *initRasterizer(RAS_IRasterizer* rasty,RAS_ICanvas* canvas)
+PyMODINIT_FUNC initRasterizerPythonBinding()
{
- gp_Canvas = canvas;
- gp_Rasterizer = rasty;
-
-
PyObject *m;
PyObject *d;
- /* Use existing module where possible
- * be careful not to init any runtime vars after this */
- m = PyImport_ImportModule( "Rasterizer" );
- if (m) {
- Py_DECREF(m);
- return m;
- }
- else {
- PyErr_Clear();
+ m = PyModule_Create(&Rasterizer_module_def);
+ PyDict_SetItemString(PySys_GetObject("modules"), Rasterizer_module_def.m_name, m);
- // Create the module and add the functions
- m = PyModule_Create(&Rasterizer_module_def);
- PyDict_SetItemString(PySys_GetObject("modules"), Rasterizer_module_def.m_name, m);
- }
// Add some symbolic constants to the module
d = PyModule_GetDict(m);
@@ -2314,6 +2327,10 @@ PyObject *initRasterizer(RAS_IRasterizer* rasty,RAS_ICanvas* canvas)
KX_MACRO_addTypesToDict(d, VSYNC_ON, VSYNC_ON);
KX_MACRO_addTypesToDict(d, VSYNC_ADAPTIVE, VSYNC_ADAPTIVE);
+ /* stereoscopy */
+ KX_MACRO_addTypesToDict(d, LEFT_EYE, RAS_IRasterizer::RAS_STEREO_LEFTEYE);
+ KX_MACRO_addTypesToDict(d, RIGHT_EYE, RAS_IRasterizer::RAS_STEREO_RIGHTEYE);
+
// XXXX Add constants here
// Check for errors
@@ -2322,7 +2339,7 @@ PyObject *initRasterizer(RAS_IRasterizer* rasty,RAS_ICanvas* canvas)
Py_FatalError("can't initialize module Rasterizer");
}
- return d;
+ return m;
}
@@ -2331,13 +2348,14 @@ PyObject *initRasterizer(RAS_IRasterizer* rasty,RAS_ICanvas* canvas)
/* GameKeys: symbolic constants for key mapping */
/* ------------------------------------------------------------------------- */
-static char GameKeys_module_documentation[] =
+PyDoc_STRVAR(GameKeys_module_documentation,
"This modules provides defines for key-codes"
-;
+);
-static char gPyEventToString_doc[] =
-"EventToString(event) - Take a valid event from the GameKeys module or Keyboard Sensor and return a name"
-;
+PyDoc_STRVAR(gPyEventToString_doc,
+"EventToString(event)\n"
+"Take a valid event from the GameKeys module or Keyboard Sensor and return a name"
+);
static PyObject *gPyEventToString(PyObject *, PyObject *value)
{
@@ -2365,9 +2383,11 @@ static PyObject *gPyEventToString(PyObject *, PyObject *value)
return ret;
}
-static char gPyEventToCharacter_doc[] =
-"EventToCharacter(event, is_shift) - Take a valid event from the GameKeys module or Keyboard Sensor and return a character"
-;
+
+PyDoc_STRVAR(gPyEventToCharacter_doc,
+"EventToCharacter(event, is_shift)\n"
+"Take a valid event from the GameKeys module or Keyboard Sensor and return a character"
+);
static PyObject *gPyEventToCharacter(PyObject *, PyObject *args)
{
@@ -2393,7 +2413,7 @@ static struct PyMethodDef gamekeys_methods[] = {
};
static struct PyModuleDef GameKeys_module_def = {
- {}, /* m_base */
+ PyModuleDef_HEAD_INIT,
"GameKeys", /* m_name */
GameKeys_module_documentation, /* m_doc */
0, /* m_size */
@@ -2404,24 +2424,13 @@ static struct PyModuleDef GameKeys_module_def = {
0, /* m_free */
};
-PyObject *initGameKeys()
+PyMODINIT_FUNC initGameKeysPythonBinding()
{
PyObject *m;
PyObject *d;
-
- /* Use existing module where possible */
- m = PyImport_ImportModule( "GameKeys" );
- if (m) {
- Py_DECREF(m);
- return m;
- }
- else {
- PyErr_Clear();
-
- // Create the module and add the functions
- m = PyModule_Create(&GameKeys_module_def);
- PyDict_SetItemString(PySys_GetObject("modules"), GameKeys_module_def.m_name, m);
- }
+
+ m = PyModule_Create(&GameKeys_module_def);
+ PyDict_SetItemString(PySys_GetObject("modules"), GameKeys_module_def.m_name, m);
// Add some symbolic constants to the module
d = PyModule_GetDict(m);
@@ -2566,9 +2575,80 @@ PyObject *initGameKeys()
Py_FatalError("can't initialize module GameKeys");
}
- return d;
+ return m;
+}
+
+
+
+/* ------------------------------------------------------------------------- */
+/* Application: application values that remain unchanged during runtime */
+/* ------------------------------------------------------------------------- */
+
+PyDoc_STRVAR(Application_module_documentation,
+ "This module contains application values that remain unchanged during runtime."
+ );
+
+static struct PyModuleDef Application_module_def = {
+ PyModuleDef_HEAD_INIT,
+ "bge.app", /* m_name */
+ Application_module_documentation, /* m_doc */
+ 0, /* m_size */
+ NULL, /* m_methods */
+ 0, /* m_reload */
+ 0, /* m_traverse */
+ 0, /* m_clear */
+ 0, /* m_free */
+};
+
+PyMODINIT_FUNC initApplicationPythonBinding()
+{
+ PyObject *m;
+ PyObject *d;
+
+ m = PyModule_Create(&Application_module_def);
+
+ // Add some symbolic constants to the module
+ d = PyModule_GetDict(m);
+
+ PyDict_SetItemString(d, "version", Py_BuildValue("(iii)",
+ BLENDER_VERSION / 100, BLENDER_VERSION % 100, BLENDER_SUBVERSION));
+ PyDict_SetItemString(d, "version_string", PyUnicode_FromFormat("%d.%02d (sub %d)",
+ BLENDER_VERSION / 100, BLENDER_VERSION % 100, BLENDER_SUBVERSION));
+ PyDict_SetItemString(d, "version_char", PyUnicode_FromString(
+ STRINGIFY(BLENDER_VERSION_CHAR)));
+
+ PyDict_SetItemString(d, "has_texture_ffmpeg",
+#ifdef WITH_FFMPEG
+ Py_True
+#else
+ Py_False
+#endif
+ );
+ PyDict_SetItemString(d, "has_joystick",
+#ifdef WITH_SDL
+ Py_True
+#else
+ Py_False
+#endif
+ );
+ PyDict_SetItemString(d, "has_physics",
+#ifdef WITH_BULLET
+ Py_True
+#else
+ Py_False
+#endif
+ );
+
+ // Check for errors
+ if (PyErr_Occurred()) {
+ PyErr_Print();
+ PyErr_Clear();
+ }
+
+ return m;
}
+
// utility function for loading and saving the globalDict
int saveGamePythonConfig( char **marshal_buffer)
{
diff --git a/source/gameengine/Ketsji/KX_PythonInit.h b/source/gameengine/Ketsji/KX_PythonInit.h
index 719a74ee219..6550934a916 100644
--- a/source/gameengine/Ketsji/KX_PythonInit.h
+++ b/source/gameengine/Ketsji/KX_PythonInit.h
@@ -32,10 +32,13 @@
#ifndef __KX_PYTHONINIT_H__
#define __KX_PYTHONINIT_H__
-#include "KX_Python.h"
+#include "EXP_Python.h"
#include "STR_String.h"
#include "MT_Vector3.h"
+class KX_KetsjiEngine;
+class KX_Scene;
+
typedef enum {
psl_Lowest = 0,
psl_Highest,
@@ -44,13 +47,14 @@ typedef enum {
extern bool gUseVisibilityTemp;
#ifdef WITH_PYTHON
-PyObject *initGameLogic(class KX_KetsjiEngine *engine, class KX_Scene *ketsjiscene);
-PyObject *initGameKeys();
-PyObject *initRasterizer(class RAS_IRasterizer *rasty,class RAS_ICanvas *canvas);
-PyObject *initGamePlayerPythonScripting(const STR_String &progname, TPythonSecurityLevel level,
- struct Main *maggie, int argc, char **argv);
-PyObject *initVideoTexture(void);
-PyObject *initGamePythonScripting(const STR_String &progname, TPythonSecurityLevel level, struct Main *maggie);
+PyMODINIT_FUNC initBGE(void);
+PyMODINIT_FUNC initApplicationPythonBinding(void);
+PyMODINIT_FUNC initGameLogicPythonBinding(void);
+PyMODINIT_FUNC initGameKeysPythonBinding(void);
+PyMODINIT_FUNC initRasterizerPythonBinding(void);
+PyMODINIT_FUNC initVideoTexturePythonBinding(void);
+PyObject *initGamePlayerPythonScripting(struct Main *maggie, int argc, char **argv);
+PyObject *initGamePythonScripting(struct Main *maggie);
void exitGamePlayerPythonScripting();
void exitGamePythonScripting();
@@ -69,9 +73,9 @@ void removeImportMain(struct Main *maggie);
class KX_KetsjiEngine;
class KX_Scene;
-void KX_SetActiveScene(class KX_Scene *scene);
-class KX_Scene *KX_GetActiveScene();
-class KX_KetsjiEngine *KX_GetActiveEngine();
+void KX_SetActiveScene(KX_Scene *scene);
+KX_Scene *KX_GetActiveScene();
+KX_KetsjiEngine *KX_GetActiveEngine();
typedef int (*PyNextFrameFunc)(void *);
diff --git a/source/gameengine/Ketsji/KX_PythonInitTypes.cpp b/source/gameengine/Ketsji/KX_PythonInitTypes.cpp
index 7d38ce58eee..ef6ad4712a5 100644
--- a/source/gameengine/Ketsji/KX_PythonInitTypes.cpp
+++ b/source/gameengine/Ketsji/KX_PythonInitTypes.cpp
@@ -40,6 +40,7 @@
#include "BL_ArmatureConstraint.h"
#include "BL_ArmatureObject.h"
#include "BL_ArmatureChannel.h"
+#include "KX_WorldInfo.h"
#include "KX_ArmatureSensor.h"
#include "KX_BlenderMaterial.h"
#include "KX_CameraActuator.h"
@@ -163,21 +164,34 @@ static void PyType_Ready_ADD(PyObject *dict, PyTypeObject *tp, PyAttributeDef *a
#define PyType_Ready_Attr(d, n, i) PyType_Ready_ADD(d, &n::Type, n::Attributes, NULL, i)
#define PyType_Ready_AttrPtr(d, n, i) PyType_Ready_ADD(d, &n::Type, n::Attributes, n::AttributesPtr, i)
-void initPyTypes(void)
+
+
+PyDoc_STRVAR(GameTypes_module_documentation,
+"This module provides access to the game engine data types."
+);
+static struct PyModuleDef GameTypes_module_def = {
+ PyModuleDef_HEAD_INIT,
+ "GameTypes", /* m_name */
+ GameTypes_module_documentation, /* m_doc */
+ 0, /* m_size */
+ NULL, /* m_methods */
+ NULL, /* m_reload */
+ NULL, /* m_traverse */
+ NULL, /* m_clear */
+ NULL, /* m_free */
+};
+
+
+PyMODINIT_FUNC initGameTypesPythonBinding(void)
{
+ PyObject *m;
+ PyObject *dict;
-/*
- * initPyObjectPlusType(BL_ActionActuator::Parents);
- * .....
- */
+ m = PyModule_Create(&GameTypes_module_def);
+ PyDict_SetItemString(PySys_GetObject("modules"), GameTypes_module_def.m_name, m);
+
+ dict = PyModule_GetDict(m);
- /* For now just do PyType_Ready */
- PyObject *mod = PyModule_New("GameTypes");
- PyObject *dict = PyModule_GetDict(mod);
- PyDict_SetItemString(PySys_GetObject("modules"), "GameTypes", mod);
- Py_DECREF(mod);
-
-
for (int init_getset= 1; init_getset > -1; init_getset--) { /* run twice, once to init the getsets another to run PyType_Ready */
PyType_Ready_Attr(dict, BL_ActionActuator, init_getset);
PyType_Ready_Attr(dict, BL_Shader, init_getset);
@@ -218,6 +232,7 @@ void initPyTypes(void)
PyType_Ready_Attr(dict, KX_SCA_EndObjectActuator, init_getset);
PyType_Ready_Attr(dict, KX_SCA_ReplaceMeshActuator, init_getset);
PyType_Ready_Attr(dict, KX_Scene, init_getset);
+ PyType_Ready_Attr(dict, KX_WorldInfo, init_getset);
PyType_Ready_Attr(dict, KX_NavMeshObject, init_getset);
PyType_Ready_Attr(dict, KX_SceneActuator, init_getset);
PyType_Ready_Attr(dict, KX_SoundActuator, init_getset);
@@ -266,7 +281,11 @@ void initPyTypes(void)
/* Init mathutils callbacks */
KX_GameObject_Mathutils_Callback_Init();
KX_ObjectActuator_Mathutils_Callback_Init();
+ KX_WorldInfo_Mathutils_Callback_Init();
+ KX_BlenderMaterial_Mathutils_Callback_Init();
#endif
+
+ return m;
}
#endif // WITH_PYTHON
diff --git a/source/gameengine/Ketsji/KX_PythonInitTypes.h b/source/gameengine/Ketsji/KX_PythonInitTypes.h
index d8ee4f75fdd..cfc49a1dc93 100644
--- a/source/gameengine/Ketsji/KX_PythonInitTypes.h
+++ b/source/gameengine/Ketsji/KX_PythonInitTypes.h
@@ -33,7 +33,8 @@
#define __KX_PYTHON_INIT_TYPES__
#ifdef WITH_PYTHON
-void initPyTypes(void);
+#include <Python.h>
+PyMODINIT_FUNC initGameTypesPythonBinding(void);
#endif
#endif /* __KX_PYTHON_INIT_TYPES__ */
diff --git a/source/gameengine/Ketsji/KX_PythonSeq.h b/source/gameengine/Ketsji/KX_PythonSeq.h
index 568d59119c0..33b5335ddf4 100644
--- a/source/gameengine/Ketsji/KX_PythonSeq.h
+++ b/source/gameengine/Ketsji/KX_PythonSeq.h
@@ -35,7 +35,7 @@
#ifdef WITH_PYTHON
-#include "PyObjectPlus.h"
+#include "EXP_PyObjectPlus.h"
// -------------------------
enum KX_PYGENSEQ_TYPE {
diff --git a/source/gameengine/Ketsji/KX_RaySensor.cpp b/source/gameengine/Ketsji/KX_RaySensor.cpp
index 0f47dfd922b..c97d233a67b 100644
--- a/source/gameengine/Ketsji/KX_RaySensor.cpp
+++ b/source/gameengine/Ketsji/KX_RaySensor.cpp
@@ -46,6 +46,7 @@
#include "PHY_IPhysicsEnvironment.h"
#include "PHY_IPhysicsController.h"
#include "DNA_sensor_types.h"
+#include "RAS_MeshObject.h"
#include <stdio.h>
@@ -111,6 +112,7 @@ bool KX_RaySensor::RayHit(KX_ClientObjectInfo *client, KX_RayCast *result, void
KX_GameObject* hitKXObj = client->m_gameobject;
bool bFound = false;
+ bool hitMaterial = false;
if (m_propertyname.Length() == 0)
{
@@ -118,15 +120,19 @@ bool KX_RaySensor::RayHit(KX_ClientObjectInfo *client, KX_RayCast *result, void
}
else
{
- if (m_bFindMaterial)
- {
- if (client->m_auxilary_info)
- {
- bFound = (m_propertyname== ((char*)client->m_auxilary_info));
+ if (m_bFindMaterial) {
+ for (unsigned int i = 0; i < hitKXObj->GetMeshCount(); ++i) {
+ RAS_MeshObject *meshObj = hitKXObj->GetMesh(i);
+ for (unsigned int j = 0; j < meshObj->NumMaterials(); ++j) {
+ bFound = strcmp(m_propertyname.ReadPtr(), meshObj->GetMaterialName(j).ReadPtr() + 2) == 0;
+ if (bFound) {
+ hitMaterial = true;
+ break;
+ }
+ }
}
}
- else
- {
+ else {
bFound = hitKXObj->GetProperty(m_propertyname) != NULL;
}
}
@@ -143,7 +149,7 @@ bool KX_RaySensor::RayHit(KX_ClientObjectInfo *client, KX_RayCast *result, void
m_hitNormal[1] = result->m_hitNormal[1];
m_hitNormal[2] = result->m_hitNormal[2];
- m_hitMaterial = (client->m_auxilary_info ? (char*)client->m_auxilary_info : "");
+ m_hitMaterial = hitMaterial;
}
// no multi-hit search yet
return true;
@@ -154,6 +160,8 @@ bool KX_RaySensor::RayHit(KX_ClientObjectInfo *client, KX_RayCast *result, void
*/
bool KX_RaySensor::NeedRayCast(KX_ClientObjectInfo *client)
{
+ KX_GameObject *hitKXObj = client->m_gameobject;
+
if (client->m_type > KX_ClientObjectInfo::ACTOR)
{
// Unknown type of object, skip it.
@@ -163,16 +171,21 @@ bool KX_RaySensor::NeedRayCast(KX_ClientObjectInfo *client)
}
if (m_bXRay && m_propertyname.Length() != 0)
{
- if (m_bFindMaterial)
- {
- // not quite correct: an object may have multiple material
- // should check all the material and not only the first one
- if (!client->m_auxilary_info || (m_propertyname != ((char*)client->m_auxilary_info)))
+ if (m_bFindMaterial) {
+ bool found = false;
+ for (unsigned int i = 0; i < hitKXObj->GetMeshCount(); ++i) {
+ RAS_MeshObject *meshObj = hitKXObj->GetMesh(i);
+ for (unsigned int j = 0; j < meshObj->NumMaterials(); ++j) {
+ found = strcmp(m_propertyname.ReadPtr(), meshObj->GetMaterialName(j).ReadPtr() + 2) == 0;
+ if (found)
+ break;
+ }
+ }
+ if (!found)
return false;
}
- else
- {
- if (client->m_gameobject->GetProperty(m_propertyname) == NULL)
+ else {
+ if (hitKXObj->GetProperty(m_propertyname) == NULL)
return false;
}
}
diff --git a/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.cpp b/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.cpp
index f8f79269eaa..fdcfd22270b 100644
--- a/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.cpp
+++ b/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.cpp
@@ -38,7 +38,7 @@
#include "KX_SCA_AddObjectActuator.h"
#include "SCA_IScene.h"
#include "KX_GameObject.h"
-#include "PyObjectPlus.h"
+#include "EXP_PyObjectPlus.h"
/* ------------------------------------------------------------------------- */
/* Native functions */
diff --git a/source/gameengine/Ketsji/KX_SCA_DynamicActuator.cpp b/source/gameengine/Ketsji/KX_SCA_DynamicActuator.cpp
index e02eca3db63..96e1cc29de3 100644
--- a/source/gameengine/Ketsji/KX_SCA_DynamicActuator.cpp
+++ b/source/gameengine/Ketsji/KX_SCA_DynamicActuator.cpp
@@ -121,7 +121,9 @@ bool KX_SCA_DynamicActuator::Update()
switch (m_dyn_operation)
{
case 0:
- controller->RestoreDynamics();
+ // Child objects must be static, so we block changing to dynamic
+ if (!obj->GetParent())
+ controller->RestoreDynamics();
break;
case 1:
controller->SuspendDynamics();
diff --git a/source/gameengine/Ketsji/KX_SCA_ReplaceMeshActuator.cpp b/source/gameengine/Ketsji/KX_SCA_ReplaceMeshActuator.cpp
index b105256836b..6b6b090c1c4 100644
--- a/source/gameengine/Ketsji/KX_SCA_ReplaceMeshActuator.cpp
+++ b/source/gameengine/Ketsji/KX_SCA_ReplaceMeshActuator.cpp
@@ -43,7 +43,7 @@
#include "KX_SCA_ReplaceMeshActuator.h"
#include "KX_MeshProxy.h"
-#include "PyObjectPlus.h"
+#include "EXP_PyObjectPlus.h"
#ifdef WITH_PYTHON
diff --git a/source/gameengine/Ketsji/KX_Scene.cpp b/source/gameengine/Ketsji/KX_Scene.cpp
index d0eab9de1c1..723736906a9 100644
--- a/source/gameengine/Ketsji/KX_Scene.cpp
+++ b/source/gameengine/Ketsji/KX_Scene.cpp
@@ -35,6 +35,8 @@
# pragma warning (disable:4786)
#endif
+#include <stdio.h>
+
#include "KX_Scene.h"
#include "KX_PythonInit.h"
#include "MT_assert.h"
@@ -42,7 +44,7 @@
#include "KX_BlenderMaterial.h"
#include "KX_FontObject.h"
#include "RAS_IPolygonMaterial.h"
-#include "ListValue.h"
+#include "EXP_ListValue.h"
#include "SCA_LogicManager.h"
#include "SCA_TimeEventManager.h"
//#include "SCA_AlwaysEventManager.h"
@@ -66,7 +68,7 @@
#include "RAS_ICanvas.h"
#include "RAS_BucketManager.h"
-#include "FloatValue.h"
+#include "EXP_FloatValue.h"
#include "SCA_IController.h"
#include "SCA_IActuator.h"
#include "SG_Node.h"
@@ -94,12 +96,14 @@
#include "KX_ObstacleSimulation.h"
#ifdef WITH_BULLET
-#include "KX_SoftBodyDeformer.h"
+# include "KX_SoftBodyDeformer.h"
#endif
-#include "KX_Light.h"
+#ifdef WITH_PYTHON
+# include "EXP_PythonCallBack.h"
+#endif
-#include <stdio.h>
+#include "KX_Light.h"
#include "BLI_task.h"
@@ -156,7 +160,9 @@ KX_Scene::KX_Scene(class SCA_IInputDevice* keyboarddevice,
m_networkDeviceInterface(ndi),
m_active_camera(NULL),
m_ueberExecutionPriority(0),
- m_blenderScene(scene)
+ m_blenderScene(scene),
+ m_isActivedHysteresis(false),
+ m_lodHysteresisValue(0)
{
m_suspendedtime = 0.0;
m_suspendeddelta = 0.0;
@@ -218,7 +224,7 @@ KX_Scene::KX_Scene(class SCA_IInputDevice* keyboarddevice,
m_bucketmanager=new RAS_BucketManager();
- bool showObstacleSimulation = scene->gm.flag & GAME_SHOW_OBSTACLE_SIMULATION;
+ bool showObstacleSimulation = (scene->gm.flag & GAME_SHOW_OBSTACLE_SIMULATION) != 0;
switch (scene->gm.obstacleSimulation)
{
case OBSTSIMULATION_TOI_rays:
@@ -235,6 +241,7 @@ KX_Scene::KX_Scene(class SCA_IInputDevice* keyboarddevice,
m_attr_dict = NULL;
m_draw_call_pre = NULL;
m_draw_call_post = NULL;
+ m_draw_setup_call_pre = NULL;
#endif
}
@@ -532,6 +539,8 @@ KX_GameObject* KX_Scene::AddNodeReplicaObject(class SG_IObject* node, class CVal
m_objectlist->Add(newobj->AddRef());
if (newobj->GetGameObjectType()==SCA_IObject::OBJ_LIGHT)
m_lightlist->Add(newobj->AddRef());
+ else if (newobj->GetGameObjectType()==SCA_IObject::OBJ_TEXT)
+ AddFont((KX_FontObject*)newobj);
newobj->AddMeshUser();
// logic cannot be replicated, until the whole hierarchy is replicated.
@@ -575,6 +584,10 @@ KX_GameObject* KX_Scene::AddNodeReplicaObject(class SG_IObject* node, class CVal
newctrl->SetNewClientInfo(newobj->getClientInfo());
newobj->SetPhysicsController(newctrl, newobj->IsDynamic());
newctrl->PostProcessReplica(motionstate, parentctrl);
+
+ // Child objects must be static
+ if (parent)
+ newctrl->SuspendDynamics();
}
return newobj;
@@ -803,13 +816,6 @@ void KX_Scene::DupliGroupRecurse(CValue* obj, int level)
// we can now add the graphic controller to the physic engine
replica->ActivateGraphicController(true);
- // set references for dupli-group
- // groupobj holds a list of all objects, that belongs to this group
- groupobj->AddInstanceObjects(replica);
-
- // every object gets the reference to its dupli-group object
- replica->SetDupliGroupObject(groupobj);
-
// done with replica
replica->Release();
}
@@ -829,12 +835,6 @@ void KX_Scene::DupliGroupRecurse(CValue* obj, int level)
(*git)->Relink(&m_map_gameobject_to_replica);
// add the object in the layer of the parent
(*git)->SetLayer(groupobj->GetLayer());
- // If the object was a light, we need to update it's RAS_LightObject as well
- if ((*git)->GetGameObjectType()==SCA_IObject::OBJ_LIGHT)
- {
- KX_LightObject* lightobj = static_cast<KX_LightObject*>(*git);
- lightobj->SetLayer(groupobj->GetLayer());
- }
}
// replicate crosslinks etc. between logic bricks
@@ -846,9 +846,24 @@ void KX_Scene::DupliGroupRecurse(CValue* obj, int level)
// now look if object in the hierarchy have dupli group and recurse
for (git = m_logicHierarchicalGameObjects.begin();!(git==m_logicHierarchicalGameObjects.end());++git)
{
+ /* Replicate all constraints. */
+ if ((*git)->GetPhysicsController()) {
+ (*git)->GetPhysicsController()->ReplicateConstraints((*git), m_logicHierarchicalGameObjects);
+ (*git)->ClearConstraints();
+ }
+
if ((*git) != groupobj && (*git)->IsDupliGroup())
// can't instantiate group immediately as it destroys m_logicHierarchicalGameObjects
duplilist.push_back((*git));
+
+ if ((*git)->GetBlenderGroupObject() == blgroupobj) {
+ // set references for dupli-group
+ // groupobj holds a list of all objects, that belongs to this group
+ groupobj->AddInstanceObjects((*git));
+
+ // every object gets the reference to its dupli-group object
+ (*git)->SetDupliGroupObject(groupobj);
+ }
}
for (git = duplilist.begin(); !(git == duplilist.end()); ++git)
@@ -859,7 +874,7 @@ void KX_Scene::DupliGroupRecurse(CValue* obj, int level)
SCA_IObject* KX_Scene::AddReplicaObject(class CValue* originalobject,
- class CValue* parentobject,
+ class CValue* referenceobject,
int lifespan)
{
@@ -867,19 +882,18 @@ SCA_IObject* KX_Scene::AddReplicaObject(class CValue* originalobject,
m_map_gameobject_to_replica.clear();
m_groupGameObjects.clear();
- // todo: place a timebomb in the object, for temporarily objects :)
- // lifespan of zero means 'this object lives forever'
KX_GameObject* originalobj = (KX_GameObject*) originalobject;
- KX_GameObject* parentobj = (KX_GameObject*) parentobject;
+ KX_GameObject* referenceobj = (KX_GameObject*) referenceobject;
m_ueberExecutionPriority++;
// lets create a replica
KX_GameObject* replica = (KX_GameObject*) AddNodeReplicaObject(NULL,originalobj);
+ // add a timebomb to this object
+ // lifespan of zero means 'this object lives forever'
if (lifespan > 0)
{
- // add a timebomb to this object
// for now, convert between so called frames and realtime
m_tempObjectList->Add(replica->AddRef());
// this convert the life from frames to sort-of seconds, hard coded 0.02 that assumes we have 50 frames per second
@@ -905,19 +919,20 @@ SCA_IObject* KX_Scene::AddReplicaObject(class CValue* originalobject,
replica->GetSGNode()->AddChild(childreplicanode);
}
- // At this stage all the objects in the hierarchy have been duplicated,
- // we can update the scenegraph, we need it for the duplication of logic
- MT_Point3 newpos = ((KX_GameObject*) parentobject)->NodeGetWorldPosition();
- replica->NodeSetLocalPosition(newpos);
+ if (referenceobj) {
+ // At this stage all the objects in the hierarchy have been duplicated,
+ // we can update the scenegraph, we need it for the duplication of logic
+ MT_Point3 newpos = referenceobj->NodeGetWorldPosition();
+ replica->NodeSetLocalPosition(newpos);
- MT_Matrix3x3 newori = ((KX_GameObject*) parentobject)->NodeGetWorldOrientation();
- replica->NodeSetLocalOrientation(newori);
-
- // get the rootnode's scale
- MT_Vector3 newscale = parentobj->GetSGNode()->GetRootSGParent()->GetLocalScale();
+ MT_Matrix3x3 newori = referenceobj->NodeGetWorldOrientation();
+ replica->NodeSetLocalOrientation(newori);
- // set the replica's relative scale with the rootnode's scale
- replica->NodeSetRelativeScale(newscale);
+ // get the rootnode's scale
+ MT_Vector3 newscale = referenceobj->GetSGNode()->GetRootSGParent()->GetLocalScale();
+ // set the replica's relative scale with the rootnode's scale
+ replica->NodeSetRelativeScale(newscale);
+ }
replica->GetSGNode()->UpdateWorldData(0);
replica->GetSGNode()->SetBBox(originalobj->GetSGNode()->BBox());
@@ -937,13 +952,13 @@ SCA_IObject* KX_Scene::AddReplicaObject(class CValue* originalobject,
{
// this will also relink the actuators in the hierarchy
(*git)->Relink(&m_map_gameobject_to_replica);
- // add the object in the layer of the parent
- (*git)->SetLayer(parentobj->GetLayer());
- // If the object was a light, we need to update it's RAS_LightObject as well
- if ((*git)->GetGameObjectType()==SCA_IObject::OBJ_LIGHT)
- {
- KX_LightObject* lightobj = static_cast<KX_LightObject*>(*git);
- lightobj->SetLayer(parentobj->GetLayer());
+ if (referenceobj) {
+ // add the object in the layer of the reference object
+ (*git)->SetLayer(referenceobj->GetLayer());
+ }
+ else {
+ // We don't know what layer set, so we set all visible layers in the blender scene.
+ (*git)->SetLayer(m_blenderScene->lay);
}
}
@@ -1078,6 +1093,16 @@ int KX_Scene::NewRemoveObject(class CValue* gameobj)
group->RemoveInstanceObject(newobj);
newobj->RemoveMeshes();
+
+ switch (newobj->GetGameObjectType()) {
+ case SCA_IObject::OBJ_CAMERA:
+ m_cameras.remove((KX_Camera *)newobj);
+ break;
+ case SCA_IObject::OBJ_TEXT:
+ m_fonts.remove((KX_FontObject *)newobj);
+ break;
+ }
+
ret = 1;
if (newobj->GetGameObjectType()==SCA_IObject::OBJ_LIGHT && m_lightlist->RemoveValue(newobj))
ret = newobj->Release();
@@ -1093,7 +1118,10 @@ int KX_Scene::NewRemoveObject(class CValue* gameobj)
ret = newobj->Release();
if (m_animatedlist->RemoveValue(newobj))
ret = newobj->Release();
-
+
+ /* Warning 'newobj' maye be freed now, only compare, don't access */
+
+
if (newobj == m_active_camera)
{
//no AddRef done on m_active_camera so no Release
@@ -1101,12 +1129,6 @@ int KX_Scene::NewRemoveObject(class CValue* gameobj)
m_active_camera = NULL;
}
- // in case this is a camera
- m_cameras.remove((KX_Camera*)newobj);
-
- // in case this is a font
- m_fonts.remove((KX_FontObject*)newobj);
-
/* currently does nothing, keep in case we need to Unregister something */
#if 0
if (m_sceneConverter)
@@ -1502,6 +1524,15 @@ void KX_Scene::CalculateVisibleMeshes(RAS_IRasterizer* rasty,KX_Camera* cam, int
bool dbvt_culling = false;
if (m_dbvt_culling)
{
+ /* Reset KX_GameObject m_bCulled to true before doing culling
+ * since DBVT culling will only set it to false.
+ * This is similar to what RAS_BucketManager does for RAS_MeshSlot culling.
+ */
+ for (int i = 0; i < m_objectlist->GetCount(); i++) {
+ KX_GameObject *gameobj = static_cast<KX_GameObject*>(m_objectlist->GetValue(i));
+ gameobj->SetCulled(true);
+ }
+
// test culling through Bullet
MT_Vector4 planes[6];
// get the clip planes
@@ -1531,9 +1562,6 @@ void KX_Scene::CalculateVisibleMeshes(RAS_IRasterizer* rasty,KX_Camera* cam, int
MarkVisible(rasty, static_cast<KX_GameObject*>(m_objectlist->GetValue(i)), cam, layer);
}
}
-
- // Now that we know visible meshes, update LoDs
- UpdateObjectLods();
}
// logic stuff
@@ -1642,20 +1670,6 @@ static void update_anim_thread_func(TaskPool *pool, void *taskdata, int UNUSED(t
void KX_Scene::UpdateAnimations(double curtime)
{
- KX_KetsjiEngine *engine = KX_GetActiveEngine();
-
- if (engine->GetRestrictAnimationFPS())
- {
- // Handle the animations independently of the logic time step
- double anim_timestep = 1.0 / GetAnimationFPS();
- if (curtime - m_previousAnimTime < anim_timestep)
- return;
-
- // Sanity/debug print to make sure we're actually going at the fps we want (should be close to anim_timestep)
- // printf("Anim fps: %f\n", 1.0/(m_clockTime - m_previousAnimTime));
- m_previousAnimTime = curtime;
- }
-
TaskPool *pool = BLI_task_pool_create(KX_GetActiveEngine()->GetTaskScheduler(), &curtime);
for (int i=0; i<m_animatedlist->GetCount(); ++i) {
@@ -1755,6 +1769,10 @@ void KX_Scene::RenderFonts()
void KX_Scene::UpdateObjectLods(void)
{
KX_GameObject* gameobj;
+
+ if (!this->m_active_camera)
+ return;
+
MT_Vector3 cam_pos = this->m_active_camera->NodeGetWorldPosition();
for (int i = 0; i < this->GetObjectList()->GetCount(); i++) {
@@ -1765,6 +1783,26 @@ void KX_Scene::UpdateObjectLods(void)
}
}
+void KX_Scene::SetLodHysteresis(bool active)
+{
+ m_isActivedHysteresis = active;
+}
+
+bool KX_Scene::IsActivedLodHysteresis(void)
+{
+ return m_isActivedHysteresis;
+}
+
+void KX_Scene::SetLodHysteresisValue(int hysteresisvalue)
+{
+ m_lodHysteresisValue = hysteresisvalue;
+}
+
+int KX_Scene::GetLodHysteresisValue(void)
+{
+ return m_lodHysteresisValue;
+}
+
void KX_Scene::UpdateObjectActivity(void)
{
if (m_activity_culling) {
@@ -1881,15 +1919,6 @@ static void MergeScene_LogicBrick(SCA_ILogicBrick* brick, KX_Scene *from, KX_Sce
brick->Replace_IScene(to);
brick->Replace_NetworkScene(to->GetNetworkScene());
- /* near sensors have physics controllers */
- KX_TouchSensor *touch_sensor = dynamic_cast<class KX_TouchSensor *>(brick);
- if (touch_sensor) {
- KX_TouchEventManager *tmgr = (KX_TouchEventManager*)from->GetLogicManager()->FindEventManager(SCA_EventManager::TOUCH_EVENTMGR);
- touch_sensor->UnregisterSumo(tmgr);
- touch_sensor->GetPhysicsController()->SetPhysicsEnvironment(to->GetPhysicsEnvironment());
- touch_sensor->RegisterSumo(tmgr);
- }
-
// If we end up replacing a KX_TouchEventManager, we need to make sure
// physics controllers are properly in place. In other words, do this
// after merging physics controllers!
@@ -1948,17 +1977,6 @@ static void MergeScene_GameObject(KX_GameObject* gameobj, KX_Scene *to, KX_Scene
{
SCA_IController *cont= *itc;
MergeScene_LogicBrick(cont, from, to);
-
- vector<SCA_ISensor*> linkedsensors = cont->GetLinkedSensors();
- vector<SCA_IActuator*> linkedactuators = cont->GetLinkedActuators();
-
- for (vector<SCA_IActuator*>::iterator ita = linkedactuators.begin();!(ita==linkedactuators.end());++ita) {
- MergeScene_LogicBrick(*ita, from, to);
- }
-
- for (vector<SCA_ISensor*>::iterator its = linkedsensors.begin();!(its==linkedsensors.end());++its) {
- MergeScene_LogicBrick(*its, from, to);
- }
}
}
@@ -1993,12 +2011,20 @@ static void MergeScene_GameObject(KX_GameObject* gameobj, KX_Scene *to, KX_Scene
if (gameobj->GetGameObjectType() == SCA_IObject::OBJ_CAMERA)
to->AddCamera((KX_Camera*)gameobj);
+ // All armatures should be in the animated object list to be umpdated.
+ if (gameobj->GetGameObjectType() == SCA_IObject::OBJ_ARMATURE)
+ to->AddAnimatedObject(gameobj);
+
/* Add the object to the scene's logic manager */
to->GetLogicManager()->RegisterGameObjectName(gameobj->GetName(), gameobj);
to->GetLogicManager()->RegisterGameObj(gameobj->GetBlenderObject(), gameobj);
- for (int i=0; i<gameobj->GetMeshCount(); ++i)
- to->GetLogicManager()->RegisterGameMeshName(gameobj->GetMesh(i)->GetName(), gameobj->GetBlenderObject());
+ for (int i = 0; i < gameobj->GetMeshCount(); ++i) {
+ RAS_MeshObject *meshobj = gameobj->GetMesh(i);
+ // Register the mesh object by name and blender object.
+ to->GetLogicManager()->RegisterGameMeshName(meshobj->GetName(), gameobj->GetBlenderObject());
+ to->GetLogicManager()->RegisterMeshName(meshobj->GetName(), meshobj);
+ }
}
bool KX_Scene::MergeScene(KX_Scene *other)
@@ -2042,6 +2068,28 @@ bool KX_Scene::MergeScene(KX_Scene *other)
MergeScene_GameObject(gameobj, this, other);
}
+ if (env) {
+ env->MergeEnvironment(env_other);
+ CListValue *otherObjects = other->GetObjectList();
+
+ // List of all physics objects to merge (needed by ReplicateConstraints).
+ std::vector<KX_GameObject *> physicsObjects;
+ for (unsigned int i = 0; i < otherObjects->GetCount(); ++i) {
+ KX_GameObject *gameobj = (KX_GameObject *)otherObjects->GetValue(i);
+ if (gameobj->GetPhysicsController()) {
+ physicsObjects.push_back(gameobj);
+ }
+ }
+
+ for (unsigned int i = 0; i < physicsObjects.size(); ++i) {
+ KX_GameObject *gameobj = physicsObjects[i];
+ // Replicate all constraints in the right physics environment.
+ gameobj->GetPhysicsController()->ReplicateConstraints(gameobj, physicsObjects);
+ gameobj->ClearConstraints();
+ }
+ }
+
+
GetTempObjectList()->MergeList(other->GetTempObjectList());
other->GetTempObjectList()->ReleaseAndRemoveAll();
@@ -2057,9 +2105,6 @@ bool KX_Scene::MergeScene(KX_Scene *other)
GetLightList()->MergeList(other->GetLightList());
other->GetLightList()->ReleaseAndRemoveAll();
- if (env)
- env->MergeEnvironment(env_other);
-
/* move materials across, assume they both use the same scene-converters
* Do this after lights are merged so materials can use the lights in shaders
*/
@@ -2112,30 +2157,10 @@ void KX_Scene::Render2DFilters(RAS_ICanvas* canvas)
void KX_Scene::RunDrawingCallbacks(PyObject *cb_list)
{
- Py_ssize_t len;
-
- if (cb_list && (len=PyList_GET_SIZE(cb_list)))
- {
- PyObject *args = PyTuple_New(0); // save python creating each call
- PyObject *func;
- PyObject *ret;
-
- // Iterate the list and run the callbacks
- for (Py_ssize_t pos=0; pos < len; pos++)
- {
- func= PyList_GET_ITEM(cb_list, pos);
- ret= PyObject_Call(func, args, NULL);
- if (ret==NULL) {
- PyErr_Print();
- PyErr_Clear();
- }
- else {
- Py_DECREF(ret);
- }
- }
+ if (!cb_list || PyList_GET_SIZE(cb_list) == 0)
+ return;
- Py_DECREF(args);
- }
+ RunPythonCallBackList(cb_list, NULL, 0, 0);
}
//----------------------------------------------------------------------------
@@ -2321,6 +2346,19 @@ PyObject *KX_Scene::pyattr_get_lights(void *self_v, const KX_PYATTRIBUTE_DEF *at
return self->GetLightList()->GetProxy();
}
+PyObject *KX_Scene::pyattr_get_world(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+{
+ KX_Scene* self = static_cast<KX_Scene*>(self_v);
+ KX_WorldInfo *world = self->GetWorldInfo();
+
+ if (world->GetName() != "") {
+ return world->GetProxy();
+ }
+ else {
+ Py_RETURN_NONE;
+ }
+}
+
PyObject *KX_Scene::pyattr_get_cameras(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
/* With refcounts in this case...
@@ -2385,6 +2423,17 @@ PyObject *KX_Scene::pyattr_get_drawing_callback_post(void *self_v, const KX_PYAT
return self->m_draw_call_post;
}
+PyObject *KX_Scene::pyattr_get_drawing_setup_callback_pre(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+{
+ KX_Scene* self = static_cast<KX_Scene*>(self_v);
+
+ if (self->m_draw_setup_call_pre == NULL)
+ self->m_draw_setup_call_pre = PyList_New(0);
+
+ Py_INCREF(self->m_draw_setup_call_pre);
+ return self->m_draw_setup_call_pre;
+}
+
int KX_Scene::pyattr_set_drawing_callback_pre(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
{
KX_Scene* self = static_cast<KX_Scene*>(self_v);
@@ -2419,6 +2468,22 @@ int KX_Scene::pyattr_set_drawing_callback_post(void *self_v, const KX_PYATTRIBUT
return PY_SET_ATTR_SUCCESS;
}
+int KX_Scene::pyattr_set_drawing_setup_callback_pre(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
+{
+ KX_Scene* self = static_cast<KX_Scene*>(self_v);
+
+ if (!PyList_CheckExact(value)) {
+ PyErr_SetString(PyExc_ValueError, "Expected a list");
+ return PY_SET_ATTR_FAIL;
+ }
+
+ Py_XDECREF(self->m_draw_setup_call_pre);
+ Py_INCREF(value);
+
+ self->m_draw_setup_call_pre = value;
+ return PY_SET_ATTR_SUCCESS;
+}
+
PyObject *KX_Scene::pyattr_get_gravity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
KX_Scene* self = static_cast<KX_Scene*>(self_v);
@@ -2444,9 +2509,11 @@ 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("world", KX_Scene, pyattr_get_world),
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),
+ KX_PYATTRIBUTE_RW_FUNCTION("pre_draw_setup", KX_Scene, pyattr_get_drawing_setup_callback_pre, pyattr_set_drawing_setup_callback_pre),
KX_PYATTRIBUTE_RW_FUNCTION("gravity", KX_Scene, pyattr_get_gravity, pyattr_set_gravity),
KX_PYATTRIBUTE_BOOL_RO("suspended", KX_Scene, m_suspend),
KX_PYATTRIBUTE_BOOL_RO("activity_culling", KX_Scene, m_activity_culling),
@@ -2459,23 +2526,23 @@ KX_PYMETHODDEF_DOC(KX_Scene, addObject,
"addObject(object, other, time=0)\n"
"Returns the added object.\n")
{
- PyObject *pyob, *pyother;
- KX_GameObject *ob, *other;
+ PyObject *pyob, *pyreference = Py_None;
+ KX_GameObject *ob, *reference;
int time = 0;
- if (!PyArg_ParseTuple(args, "OO|i:addObject", &pyob, &pyother, &time))
+ if (!PyArg_ParseTuple(args, "O|Oi:addObject", &pyob, &pyreference, &time))
return NULL;
- if ( !ConvertPythonToGameObject(pyob, &ob, false, "scene.addObject(object, other, time): KX_Scene (first argument)") ||
- !ConvertPythonToGameObject(pyother, &other, false, "scene.addObject(object, other, time): KX_Scene (second argument)") )
+ if (!ConvertPythonToGameObject(pyob, &ob, false, "scene.addObject(object, reference, time): KX_Scene (first argument)") ||
+ !ConvertPythonToGameObject(pyreference, &reference, true, "scene.addObject(object, reference, time): KX_Scene (second argument)"))
return NULL;
if (!m_inactivelist->SearchValue(ob)) {
- PyErr_Format(PyExc_ValueError, "scene.addObject(object, other, time): KX_Scene (first argument): object must be in an inactive layer");
+ PyErr_Format(PyExc_ValueError, "scene.addObject(object, reference, time): KX_Scene (first argument): object must be in an inactive layer");
return NULL;
}
- SCA_IObject* replica = AddReplicaObject((SCA_IObject*)ob, other, time);
+ SCA_IObject *replica = AddReplicaObject((SCA_IObject*)ob, reference, time);
// release here because AddReplicaObject AddRef's
// the object is added to the scene so we don't want python to own a reference
diff --git a/source/gameengine/Ketsji/KX_Scene.h b/source/gameengine/Ketsji/KX_Scene.h
index c5840c28041..4f7ad98f30d 100644
--- a/source/gameengine/Ketsji/KX_Scene.h
+++ b/source/gameengine/Ketsji/KX_Scene.h
@@ -49,7 +49,7 @@
#include "RAS_Rect.h"
-#include "PyObjectPlus.h"
+#include "EXP_PyObjectPlus.h"
#include "RAS_2DFilterManager.h"
/**
@@ -107,6 +107,7 @@ class KX_Scene : public PyObjectPlus, public SCA_IScene
PyObject* m_attr_dict;
PyObject* m_draw_call_pre;
PyObject* m_draw_call_post;
+ PyObject* m_draw_setup_call_pre;
#endif
struct CullingInfo {
@@ -289,14 +290,18 @@ protected:
double m_suspendedtime;
double m_suspendeddelta;
- double m_previousAnimTime; //the last time animations were updated
-
struct Scene* m_blenderScene;
RAS_2DFilterManager m_filtermanager;
KX_ObstacleSimulation* m_obstacleSimulation;
+ /**
+ * LOD Hysteresis settings
+ */
+ bool m_isActivedHysteresis;
+ int m_lodHysteresisValue;
+
public:
KX_Scene(class SCA_IInputDevice* keyboarddevice,
class SCA_IInputDevice* mousedevice,
@@ -548,6 +553,12 @@ public:
// Update the mesh for objects based on level of detail settings
void UpdateObjectLods(void);
+
+ // LoD Hysteresis functions
+ void SetLodHysteresis(bool active);
+ bool IsActivedLodHysteresis();
+ void SetLodHysteresisValue(int hysteresisvalue);
+ int GetLodHysteresisValue();
// Update the activity box settings for objects in this scene, if needed.
void UpdateObjectActivity(void);
@@ -614,12 +625,15 @@ public:
static PyObject* pyattr_get_objects_inactive(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef);
static PyObject* pyattr_get_lights(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef);
static PyObject* pyattr_get_cameras(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+ static PyObject* pyattr_get_world(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef);
static PyObject* pyattr_get_active_camera(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef);
static int pyattr_set_active_camera(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
static PyObject* pyattr_get_drawing_callback_pre(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
static int pyattr_set_drawing_callback_pre(void *selv_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
static PyObject* pyattr_get_drawing_callback_post(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
static int pyattr_set_drawing_callback_post(void *selv_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
+ static PyObject* pyattr_get_drawing_setup_callback_pre(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+ static int pyattr_set_drawing_setup_callback_pre(void *selv_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
static PyObject* pyattr_get_gravity(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef);
static int pyattr_set_gravity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
@@ -636,6 +650,7 @@ public:
PyObject *GetPreDrawCB() { return m_draw_call_pre; }
PyObject *GetPostDrawCB() { return m_draw_call_post; }
+ PyObject *GetPreDrawSetupCB() { return m_draw_setup_call_pre; }
#endif
/**
diff --git a/source/gameengine/Ketsji/KX_SoundActuator.cpp b/source/gameengine/Ketsji/KX_SoundActuator.cpp
index 4e5cd0ac5e1..02b1071e267 100644
--- a/source/gameengine/Ketsji/KX_SoundActuator.cpp
+++ b/source/gameengine/Ketsji/KX_SoundActuator.cpp
@@ -37,10 +37,14 @@
#include "KX_SoundActuator.h"
#ifdef WITH_AUDASPACE
-# include "AUD_C-API.h"
-# include "AUD_PingPongFactory.h"
-# include "AUD_IDevice.h"
-# include "AUD_I3DHandle.h"
+# ifdef WITH_SYSTEM_AUDASPACE
+typedef float sample_t;
+# include AUD_PYTHON_H
+# endif
+# include AUD_SOUND_H
+# include AUD_SPECIAL_H
+# include AUD_DEVICE_H
+# include AUD_HANDLE_H
#endif
#include "KX_GameObject.h"
@@ -53,7 +57,7 @@
/* Native functions */
/* ------------------------------------------------------------------------- */
KX_SoundActuator::KX_SoundActuator(SCA_IObject* gameobj,
- boost::shared_ptr<AUD_IFactory> sound,
+ AUD_Sound* sound,
float volume,
float pitch,
bool is3d,
@@ -61,7 +65,8 @@ KX_SoundActuator::KX_SoundActuator(SCA_IObject* gameobj,
KX_SOUNDACT_TYPE type)//,
: SCA_IActuator(gameobj, KX_ACT_SOUND)
{
- m_sound = sound;
+ m_sound = AUD_Sound_copy(sound);
+ m_handle = NULL;
m_volume = volume;
m_pitch = pitch;
m_is3d = is3d;
@@ -74,20 +79,30 @@ KX_SoundActuator::KX_SoundActuator(SCA_IObject* gameobj,
KX_SoundActuator::~KX_SoundActuator()
{
- if (m_handle.get())
- m_handle->stop();
+ if(m_handle)
+ {
+ AUD_Handle_stop(m_handle);
+ }
+
+ if(m_sound)
+ {
+ AUD_Sound_free(m_sound);
+ }
}
void KX_SoundActuator::play()
{
- if (m_handle.get())
- m_handle->stop();
+ if(m_handle)
+ {
+ AUD_Handle_stop(m_handle);
+ m_handle = NULL;
+ }
- if (!m_sound.get())
+ if (!m_sound)
return;
// this is the sound that will be played and not deleted afterwards
- boost::shared_ptr<AUD_IFactory> sound = m_sound;
+ AUD_Sound* sound = m_sound;
bool loop = false;
@@ -95,7 +110,7 @@ void KX_SoundActuator::play()
{
case KX_SOUNDACT_LOOPBIDIRECTIONAL:
case KX_SOUNDACT_LOOPBIDIRECTIONAL_STOP:
- sound = boost::shared_ptr<AUD_IFactory>(new AUD_PingPongFactory(sound));
+ sound = AUD_Sound_pingpong(sound);
// fall through
case KX_SOUNDACT_LOOPEND:
case KX_SOUNDACT_LOOPSTOP:
@@ -107,36 +122,33 @@ void KX_SoundActuator::play()
break;
}
- try
- {
- m_handle = AUD_getDevice()->play(sound);
- }
- catch(AUD_Exception&)
- {
- // cannot play back, ignore
- return;
- }
+ AUD_Device* device = AUD_Device_getCurrent();
+ m_handle = AUD_Device_play(device, sound, false);
+ AUD_Device_free(device);
- boost::shared_ptr<AUD_I3DHandle> handle3d = boost::dynamic_pointer_cast<AUD_I3DHandle>(m_handle);
+ // in case of pingpong, we have to free the sound
+ if(sound != m_sound)
+ AUD_Sound_free(sound);
- if (m_is3d && handle3d.get())
+ if (m_handle != NULL)
{
- handle3d->setRelative(true);
- handle3d->setVolumeMaximum(m_3d.max_gain);
- handle3d->setVolumeMinimum(m_3d.min_gain);
- handle3d->setDistanceReference(m_3d.reference_distance);
- handle3d->setDistanceMaximum(m_3d.max_distance);
- handle3d->setAttenuation(m_3d.rolloff_factor);
- handle3d->setConeAngleInner(m_3d.cone_inner_angle);
- handle3d->setConeAngleOuter(m_3d.cone_outer_angle);
- handle3d->setConeVolumeOuter(m_3d.cone_outer_gain);
- }
+ if (m_is3d)
+ {
+ AUD_Handle_setRelative(m_handle, true);
+ AUD_Handle_setVolumeMaximum(m_handle, m_3d.max_gain);
+ AUD_Handle_setVolumeMinimum(m_handle, m_3d.min_gain);
+ AUD_Handle_setDistanceReference(m_handle, m_3d.reference_distance);
+ AUD_Handle_setDistanceMaximum(m_handle, m_3d.max_distance);
+ AUD_Handle_setAttenuation(m_handle, m_3d.rolloff_factor);
+ AUD_Handle_setConeAngleInner(m_handle, m_3d.cone_inner_angle);
+ AUD_Handle_setConeAngleOuter(m_handle, m_3d.cone_outer_angle);
+ AUD_Handle_setConeVolumeOuter(m_handle, m_3d.cone_outer_gain);
+ }
- if (m_handle.get()) {
if (loop)
- m_handle->setLoopCount(-1);
- m_handle->setPitch(m_pitch);
- m_handle->setVolume(m_volume);
+ AUD_Handle_setLoopCount(m_handle, -1);
+ AUD_Handle_setPitch(m_handle, m_pitch);
+ AUD_Handle_setVolume(m_handle, m_volume);
}
m_isplaying = true;
@@ -152,7 +164,8 @@ CValue* KX_SoundActuator::GetReplica()
void KX_SoundActuator::ProcessReplica()
{
SCA_IActuator::ProcessReplica();
- m_handle = boost::shared_ptr<AUD_IHandle>();
+ m_handle = NULL;
+ m_sound = AUD_Sound_copy(m_sound);
}
bool KX_SoundActuator::Update(double curtime, bool frame)
@@ -167,11 +180,11 @@ bool KX_SoundActuator::Update(double curtime, bool frame)
RemoveAllEvents();
- if (!m_sound.get())
+ if (!m_sound)
return false;
// actual audio device playing state
- bool isplaying = m_handle.get() ? (m_handle->getStatus() == AUD_STATUS_PLAYING) : false;
+ bool isplaying = m_handle ? (AUD_Handle_getStatus(m_handle) == AUD_STATUS_PLAYING) : false;
if (bNegativeEvent)
{
@@ -185,9 +198,11 @@ bool KX_SoundActuator::Update(double curtime, bool frame)
case KX_SOUNDACT_LOOPBIDIRECTIONAL_STOP:
{
// stop immediately
- if (m_handle.get())
- m_handle->stop();
- m_handle = boost::shared_ptr<AUD_IHandle>();
+ if (m_handle)
+ {
+ AUD_Handle_stop(m_handle);
+ m_handle = NULL;
+ }
break;
}
case KX_SOUNDACT_PLAYEND:
@@ -199,8 +214,8 @@ bool KX_SoundActuator::Update(double curtime, bool frame)
case KX_SOUNDACT_LOOPBIDIRECTIONAL:
{
// stop the looping so that the sound stops when it finished
- if (m_handle.get())
- m_handle->setLoopCount(0);
+ if (m_handle)
+ AUD_Handle_setLoopCount(m_handle, 0);
break;
}
default:
@@ -227,13 +242,11 @@ bool KX_SoundActuator::Update(double curtime, bool frame)
play();
}
// verify that the sound is still playing
- isplaying = m_handle.get() ? (m_handle->getStatus() == AUD_STATUS_PLAYING) : false;
+ isplaying = m_handle ? (AUD_Handle_getStatus(m_handle) == AUD_STATUS_PLAYING) : false;
if (isplaying)
{
- boost::shared_ptr<AUD_I3DHandle> handle3d = boost::dynamic_pointer_cast<AUD_I3DHandle>(m_handle);
-
- if (m_is3d && handle3d.get())
+ if (m_is3d)
{
KX_Camera* cam = KX_GetActiveScene()->GetActiveCamera();
if (cam)
@@ -241,20 +254,19 @@ bool KX_SoundActuator::Update(double curtime, bool frame)
KX_GameObject* obj = (KX_GameObject*)this->GetParent();
MT_Point3 p;
MT_Matrix3x3 Mo;
- AUD_Vector3 v;
- float q[4];
+ float data[4];
Mo = cam->NodeGetWorldOrientation().inverse();
p = (obj->NodeGetWorldPosition() - cam->NodeGetWorldPosition());
p = Mo * p;
- p.getValue(v.get());
- handle3d->setSourceLocation(v);
+ p.getValue(data);
+ AUD_Handle_setLocation(m_handle, data);
p = (obj->GetLinearVelocity() - cam->GetLinearVelocity());
p = Mo * p;
- p.getValue(v.get());
- handle3d->setSourceVelocity(v);
- (Mo * obj->NodeGetWorldOrientation()).getRotation().getValue(q);
- handle3d->setSourceOrientation(AUD_Quaternion(q[3], q[0], q[1], q[2]));
+ p.getValue(data);
+ AUD_Handle_setVelocity(m_handle, data);
+ (Mo * obj->NodeGetWorldOrientation()).getRotation().getValue(data);
+ AUD_Handle_setOrientation(m_handle, data);
}
}
result = true;
@@ -329,11 +341,11 @@ KX_PYMETHODDEF_DOC_NOARGS(KX_SoundActuator, startSound,
"startSound()\n"
"\tStarts the sound.\n")
{
- switch (m_handle.get() ? m_handle->getStatus() : AUD_STATUS_INVALID) {
+ switch (m_handle ? AUD_Handle_getStatus(m_handle) : AUD_STATUS_INVALID) {
case AUD_STATUS_PLAYING:
break;
case AUD_STATUS_PAUSED:
- m_handle->resume();
+ AUD_Handle_resume(m_handle);
break;
default:
play();
@@ -345,8 +357,8 @@ KX_PYMETHODDEF_DOC_NOARGS(KX_SoundActuator, pauseSound,
"pauseSound()\n"
"\tPauses the sound.\n")
{
- if (m_handle.get())
- m_handle->pause();
+ if (m_handle)
+ AUD_Handle_pause(m_handle);
Py_RETURN_NONE;
}
@@ -354,9 +366,11 @@ KX_PYMETHODDEF_DOC_NOARGS(KX_SoundActuator, stopSound,
"stopSound()\n"
"\tStops the sound.\n")
{
- if (m_handle.get())
- m_handle->stop();
- m_handle = boost::shared_ptr<AUD_IHandle>();
+ if (m_handle)
+ {
+ AUD_Handle_stop(m_handle);
+ m_handle = NULL;
+ }
Py_RETURN_NONE;
}
@@ -404,8 +418,8 @@ PyObject *KX_SoundActuator::pyattr_get_audposition(void *self, const struct KX_P
KX_SoundActuator * actuator = static_cast<KX_SoundActuator *> (self);
float position = 0.0;
- if (actuator->m_handle.get())
- position = actuator->m_handle->getPosition();
+ if (actuator->m_handle)
+ position = AUD_Handle_getPosition(actuator->m_handle);
PyObject *result = PyFloat_FromDouble(position);
@@ -435,8 +449,8 @@ PyObject *KX_SoundActuator::pyattr_get_pitch(void *self, const struct KX_PYATTRI
PyObject *KX_SoundActuator::pyattr_get_sound(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef)
{
KX_SoundActuator * actuator = static_cast<KX_SoundActuator *> (self);
- if (actuator->m_sound.get())
- return (PyObject *)AUD_getPythonFactory(&actuator->m_sound);
+ if (actuator->m_sound)
+ return (PyObject *)AUD_getPythonSound(actuator->m_sound);
else
Py_RETURN_NONE;
}
@@ -450,50 +464,49 @@ int KX_SoundActuator::pyattr_set_3d_property(void *self, const struct KX_PYATTRI
if (!PyArg_Parse(value, "f", &prop_value))
return PY_SET_ATTR_FAIL;
- boost::shared_ptr<AUD_I3DHandle> handle3d = boost::dynamic_pointer_cast<AUD_I3DHandle>(actuator->m_handle);
// if sound is working and 3D, set the new setting
if (!actuator->m_is3d)
return PY_SET_ATTR_FAIL;
if (!strcmp(prop, "volume_maximum")) {
actuator->m_3d.max_gain = prop_value;
- if (handle3d.get())
- handle3d->setVolumeMaximum(prop_value);
+ if (actuator->m_handle)
+ AUD_Handle_setVolumeMaximum(actuator->m_handle, prop_value);
} else if (!strcmp(prop, "volume_minimum")) {
actuator->m_3d.min_gain = prop_value;
- if (handle3d.get())
- handle3d->setVolumeMinimum(prop_value);
+ if (actuator->m_handle)
+ AUD_Handle_setVolumeMinimum(actuator->m_handle, prop_value);
} else if (!strcmp(prop, "distance_reference")) {
actuator->m_3d.reference_distance = prop_value;
- if (handle3d.get())
- handle3d->setDistanceReference(prop_value);
+ if (actuator->m_handle)
+ AUD_Handle_setDistanceReference(actuator->m_handle, prop_value);
} else if (!strcmp(prop, "distance_maximum")) {
actuator->m_3d.max_distance = prop_value;
- if (handle3d.get())
- handle3d->setDistanceMaximum(prop_value);
+ if (actuator->m_handle)
+ AUD_Handle_setDistanceMaximum(actuator->m_handle, prop_value);
} else if (!strcmp(prop, "attenuation")) {
actuator->m_3d.rolloff_factor = prop_value;
- if (handle3d.get())
- handle3d->setAttenuation(prop_value);
+ if (actuator->m_handle)
+ AUD_Handle_setAttenuation(actuator->m_handle, prop_value);
} else if (!!strcmp(prop, "cone_angle_inner")) {
actuator->m_3d.cone_inner_angle = prop_value;
- if (handle3d.get())
- handle3d->setConeAngleInner(prop_value);
+ if (actuator->m_handle)
+ AUD_Handle_setConeAngleInner(actuator->m_handle, prop_value);
} else if (!strcmp(prop, "cone_angle_outer")) {
actuator->m_3d.cone_outer_angle = prop_value;
- if (handle3d.get())
- handle3d->setConeAngleOuter(prop_value);
+ if (actuator->m_handle)
+ AUD_Handle_setConeAngleOuter(actuator->m_handle, prop_value);
} else if (!strcmp(prop, "cone_volume_outer")) {
actuator->m_3d.cone_outer_gain = prop_value;
- if (handle3d.get())
- handle3d->setConeVolumeOuter(prop_value);
+ if (actuator->m_handle)
+ AUD_Handle_setConeVolumeOuter(actuator->m_handle, prop_value);
} else {
return PY_SET_ATTR_FAIL;
@@ -510,8 +523,8 @@ int KX_SoundActuator::pyattr_set_audposition(void *self, const struct KX_PYATTRI
if (!PyArg_Parse(value, "f", &position))
return PY_SET_ATTR_FAIL;
- if (actuator->m_handle.get())
- actuator->m_handle->seek(position);
+ if (actuator->m_handle)
+ AUD_Handle_setPosition(actuator->m_handle, position);
return PY_SET_ATTR_SUCCESS;
}
@@ -523,8 +536,8 @@ int KX_SoundActuator::pyattr_set_gain(void *self, const struct KX_PYATTRIBUTE_DE
return PY_SET_ATTR_FAIL;
actuator->m_volume = gain;
- if (actuator->m_handle.get())
- actuator->m_handle->setVolume(gain);
+ if (actuator->m_handle)
+ AUD_Handle_setVolume(actuator->m_handle, gain);
return PY_SET_ATTR_SUCCESS;
}
@@ -537,8 +550,8 @@ int KX_SoundActuator::pyattr_set_pitch(void *self, const struct KX_PYATTRIBUTE_D
return PY_SET_ATTR_FAIL;
actuator->m_pitch = pitch;
- if (actuator->m_handle.get())
- actuator->m_handle->setPitch(pitch);
+ if (actuator->m_handle)
+ AUD_Handle_setPitch(actuator->m_handle, pitch);
return PY_SET_ATTR_SUCCESS;
}
@@ -550,11 +563,12 @@ int KX_SoundActuator::pyattr_set_sound(void *self, const struct KX_PYATTRIBUTE_D
if (!PyArg_Parse(value, "O", &sound))
return PY_SET_ATTR_FAIL;
- boost::shared_ptr<AUD_IFactory>* snd = reinterpret_cast<boost::shared_ptr<AUD_IFactory>*>(AUD_getPythonSound((void *)sound));
+ AUD_Sound *snd = AUD_getSoundFromPython(sound);
+
if (snd)
{
- actuator->m_sound = *snd;
- delete snd;
+ AUD_Sound_free(actuator->m_sound);
+ actuator->m_sound = snd;
return PY_SET_ATTR_SUCCESS;
}
diff --git a/source/gameengine/Ketsji/KX_SoundActuator.h b/source/gameengine/Ketsji/KX_SoundActuator.h
index 68eff56797b..5ec2fda722f 100644
--- a/source/gameengine/Ketsji/KX_SoundActuator.h
+++ b/source/gameengine/Ketsji/KX_SoundActuator.h
@@ -35,10 +35,8 @@
#include "SCA_IActuator.h"
#ifdef WITH_AUDASPACE
-# include "AUD_C-API.h"
-# include "AUD_IFactory.h"
-# include "AUD_IHandle.h"
-# include <boost/shared_ptr.hpp>
+# include AUD_SOUND_H
+# include AUD_HANDLE_H
#endif
#include "BKE_sound.h"
@@ -58,12 +56,12 @@ class KX_SoundActuator : public SCA_IActuator
{
Py_Header
bool m_isplaying;
- boost::shared_ptr<AUD_IFactory> m_sound;
+ AUD_Sound* m_sound;
float m_volume;
float m_pitch;
bool m_is3d;
KX_3DSoundSettings m_3d;
- boost::shared_ptr<AUD_IHandle> m_handle;
+ AUD_Handle* m_handle;
void play();
@@ -84,7 +82,7 @@ public:
KX_SOUNDACT_TYPE m_type;
KX_SoundActuator(SCA_IObject* gameobj,
- boost::shared_ptr<AUD_IFactory> sound,
+ AUD_Sound *sound,
float volume,
float pitch,
bool is3d,
diff --git a/source/gameengine/Ketsji/KX_SteeringActuator.cpp b/source/gameengine/Ketsji/KX_SteeringActuator.cpp
index ff192299702..cd2cd2bae0b 100644
--- a/source/gameengine/Ketsji/KX_SteeringActuator.cpp
+++ b/source/gameengine/Ketsji/KX_SteeringActuator.cpp
@@ -41,7 +41,7 @@
/* Native functions */
/* ------------------------------------------------------------------------- */
-KX_SteeringActuator::KX_SteeringActuator(SCA_IObject *gameobj,
+KX_SteeringActuator::KX_SteeringActuator(SCA_IObject *gameobj,
int mode,
KX_GameObject *target,
KX_GameObject *navmesh,
@@ -54,7 +54,8 @@ KX_SteeringActuator::KX_SteeringActuator(SCA_IObject *gameobj,
KX_ObstacleSimulation* simulation,
short facingmode,
bool normalup,
- bool enableVisualization)
+ bool enableVisualization,
+ bool lockzvel)
: SCA_IActuator(gameobj, KX_ACT_STEERING),
m_target(target),
m_mode(mode),
@@ -72,6 +73,7 @@ KX_SteeringActuator::KX_SteeringActuator(SCA_IObject *gameobj,
m_normalUp(normalup),
m_pathLen(0),
m_pathUpdatePeriod(pathUpdatePeriod),
+ m_lockzvel(lockzvel),
m_wayPointIdx(-1),
m_steerVec(MT_Vector3(0, 0, 0))
{
@@ -266,14 +268,14 @@ bool KX_SteeringActuator::Update(double curtime, bool frame)
m_steerVec.z() = 0;
if (!m_steerVec.fuzzyZero())
m_steerVec.normalize();
- MT_Vector3 newvel = m_velocity*m_steerVec;
+ MT_Vector3 newvel = m_velocity * m_steerVec;
//adjust velocity to avoid obstacles
if (m_simulation && m_obstacle /*&& !newvel.fuzzyZero()*/)
{
if (m_enableVisualization)
KX_RasterizerDrawDebugLine(mypos, mypos + newvel, MT_Vector3(1.0, 0.0, 0.0));
- m_simulation->AdjustObstacleVelocity(m_obstacle, m_mode!=KX_STEERING_PATHFOLLOWING ? m_navmesh : NULL,
+ m_simulation->AdjustObstacleVelocity(m_obstacle, m_mode!=KX_STEERING_PATHFOLLOWING ? m_navmesh : NULL,
newvel, m_acceleration*delta, m_turnspeed/180.0f*M_PI*delta);
if (m_enableVisualization)
KX_RasterizerDrawDebugLine(mypos, mypos + newvel, MT_Vector3(0.0, 1.0, 0.0));
@@ -285,7 +287,12 @@ bool KX_SteeringActuator::Update(double curtime, bool frame)
//temporary solution: set 2D steering velocity directly to obj
//correct way is to apply physical force
MT_Vector3 curvel = obj->GetLinearVelocity();
- newvel.z() = curvel.z();
+
+ if (m_lockzvel)
+ newvel.z() = 0.0f;
+ else
+ newvel.z() = curvel.z();
+
obj->setLinearVelocity(newvel, false);
}
else
@@ -554,6 +561,7 @@ PyAttributeDef KX_SteeringActuator::Attributes[] = {
KX_PYATTRIBUTE_RO_FUNCTION("steeringVec", KX_SteeringActuator, pyattr_get_steeringVec),
KX_PYATTRIBUTE_SHORT_RW("facingMode", 0, 6, true, KX_SteeringActuator, m_facingMode),
KX_PYATTRIBUTE_INT_RW("pathUpdatePeriod", -1, 100000, true, KX_SteeringActuator, m_pathUpdatePeriod),
+ KX_PYATTRIBUTE_BOOL_RW("lockZVelocity", KX_SteeringActuator, m_lockzvel),
{ NULL } //Sentinel
};
@@ -602,8 +610,7 @@ int KX_SteeringActuator::pyattr_set_navmesh(void *self, const struct KX_PYATTRIB
if (!ConvertPythonToGameObject(value, &gameobj, true, "actuator.object = value: KX_SteeringActuator"))
return PY_SET_ATTR_FAIL; // ConvertPythonToGameObject sets the error
- if (dynamic_cast<KX_NavMeshObject *>(gameobj) == NULL)
- {
+ if (dynamic_cast<KX_NavMeshObject *>(gameobj) == NULL) {
PyErr_Format(PyExc_TypeError, "KX_NavMeshObject is expected");
return PY_SET_ATTR_FAIL;
}
diff --git a/source/gameengine/Ketsji/KX_SteeringActuator.h b/source/gameengine/Ketsji/KX_SteeringActuator.h
index 1e8ac9a54f0..3273471c166 100644
--- a/source/gameengine/Ketsji/KX_SteeringActuator.h
+++ b/source/gameengine/Ketsji/KX_SteeringActuator.h
@@ -62,6 +62,7 @@ class KX_SteeringActuator : public SCA_IActuator
int m_pathLen;
int m_pathUpdatePeriod;
double m_pathUpdateTime;
+ bool m_lockzvel;
int m_wayPointIdx;
MT_Matrix3x3 m_parentlocalmat;
MT_Vector3 m_steerVec;
@@ -89,7 +90,8 @@ public:
KX_ObstacleSimulation* simulation,
short facingmode,
bool normalup,
- bool enableVisualization);
+ bool enableVisualization,
+ bool lockzvel);
virtual ~KX_SteeringActuator();
virtual bool Update(double curtime, bool frame);
diff --git a/source/gameengine/Ketsji/KX_TouchEventManager.cpp b/source/gameengine/Ketsji/KX_TouchEventManager.cpp
index 7ec379eec26..eb774960d41 100644
--- a/source/gameengine/Ketsji/KX_TouchEventManager.cpp
+++ b/source/gameengine/Ketsji/KX_TouchEventManager.cpp
@@ -60,7 +60,7 @@ bool KX_TouchEventManager::NewHandleCollision(void* object1, void* object2, cons
PHY_IPhysicsController* obj1 = static_cast<PHY_IPhysicsController*>(object1);
PHY_IPhysicsController* obj2 = static_cast<PHY_IPhysicsController*>(object2);
- m_newCollisions.insert(std::pair<PHY_IPhysicsController*, PHY_IPhysicsController*>(obj1, obj2));
+ m_newCollisions.insert(NewCollision(obj1, obj2, coll_data));
return false;
}
@@ -209,9 +209,11 @@ void KX_TouchEventManager::NextFrame()
}
}
// Run python callbacks
- kxObj1->RunCollisionCallbacks(kxObj2);
- kxObj2->RunCollisionCallbacks(kxObj1);
+ PHY_CollData *colldata = cit->colldata;
+ kxObj1->RunCollisionCallbacks(kxObj2, colldata->m_point1, colldata->m_normal);
+ kxObj2->RunCollisionCallbacks(kxObj1, colldata->m_point2, -colldata->m_normal);
+ delete cit->colldata;
}
m_newCollisions.clear();
@@ -219,3 +221,19 @@ void KX_TouchEventManager::NextFrame()
for (it.begin();!it.end();++it)
(*it)->Activate(m_logicmgr);
}
+
+
+KX_TouchEventManager::NewCollision::NewCollision(PHY_IPhysicsController *first,
+ PHY_IPhysicsController *second,
+ const PHY_CollData *colldata)
+ : first(first), second(second), colldata(new PHY_CollData(*colldata))
+{}
+
+KX_TouchEventManager::NewCollision::NewCollision(const NewCollision &to_copy)
+ : first(to_copy.first), second(to_copy.second), colldata(to_copy.colldata)
+{}
+
+bool KX_TouchEventManager::NewCollision::operator<(const NewCollision &other) const
+{
+ return first < other.first || second < other.second || colldata < other.colldata;
+}
diff --git a/source/gameengine/Ketsji/KX_TouchEventManager.h b/source/gameengine/Ketsji/KX_TouchEventManager.h
index bd4903c1545..d9c6fdad307 100644
--- a/source/gameengine/Ketsji/KX_TouchEventManager.h
+++ b/source/gameengine/Ketsji/KX_TouchEventManager.h
@@ -45,7 +45,29 @@ class PHY_IPhysicsEnvironment;
class KX_TouchEventManager : public SCA_EventManager
{
- typedef std::pair<PHY_IPhysicsController*, PHY_IPhysicsController*> NewCollision;
+ /**
+ * Contains two colliding objects and the first contact point.
+ */
+ class NewCollision {
+ public:
+ PHY_IPhysicsController *first;
+ PHY_IPhysicsController *second;
+ PHY_CollData *colldata;
+
+ /**
+ * Creates a copy of the given PHY_CollData; freeing that copy should be done by the owner of
+ * the NewCollision object.
+ *
+ * This allows us to efficiently store NewCollision objects in a std::set without creating more
+ * copies of colldata, as the NewCollision copy constructor reuses the pointer and doesn't clone
+ * it again. */
+ NewCollision(PHY_IPhysicsController *first,
+ PHY_IPhysicsController *second,
+ const PHY_CollData *colldata);
+ NewCollision(const NewCollision &to_copy);
+ bool operator<(const NewCollision &other) const;
+ };
+
PHY_IPhysicsEnvironment* m_physEnv;
std::set<NewCollision> m_newCollisions;
diff --git a/source/gameengine/Ketsji/KX_TouchSensor.cpp b/source/gameengine/Ketsji/KX_TouchSensor.cpp
index 5cb1d5f3620..593d3e844e8 100644
--- a/source/gameengine/Ketsji/KX_TouchSensor.cpp
+++ b/source/gameengine/Ketsji/KX_TouchSensor.cpp
@@ -41,6 +41,8 @@
#include "PHY_IPhysicsController.h"
+#include "RAS_MeshObject.h"
+
#include <iostream>
#include "PHY_IPhysicsEnvironment.h"
@@ -219,14 +221,17 @@ bool KX_TouchSensor::BroadPhaseSensorFilterCollision(void*obj1,void*obj2)
bool found = m_touchedpropname.IsEmpty();
if (!found)
{
- if (m_bFindMaterial)
- {
- if (client_info->m_auxilary_info)
- {
- found = (!strcmp(m_touchedpropname.Ptr(), (char*)client_info->m_auxilary_info));
+ if (m_bFindMaterial) {
+ for (unsigned int i = 0; i < otherobj->GetMeshCount(); ++i) {
+ RAS_MeshObject *meshObj = otherobj->GetMesh(i);
+ for (unsigned int j = 0; j < meshObj->NumMaterials(); ++j) {
+ found = strcmp(m_touchedpropname.ReadPtr(), meshObj->GetMaterialName(j).ReadPtr() + 2) == 0;
+ if (found)
+ break;
+ }
}
- } else
- {
+ }
+ else {
found = (otherobj->GetProperty(m_touchedpropname) != NULL);
}
}
@@ -255,16 +260,22 @@ bool KX_TouchSensor::NewHandleCollision(void*object1,void*object2,const PHY_Coll
{
bool found = m_touchedpropname.IsEmpty();
+ bool hitMaterial = false;
if (!found)
{
- if (m_bFindMaterial)
- {
- if (client_info->m_auxilary_info)
- {
- found = (!strcmp(m_touchedpropname.Ptr(), (char*)client_info->m_auxilary_info));
+ if (m_bFindMaterial) {
+ for (unsigned int i = 0; i < gameobj->GetMeshCount(); ++i) {
+ RAS_MeshObject *meshObj = gameobj->GetMesh(i);
+ for (unsigned int j = 0; j < meshObj->NumMaterials(); ++j) {
+ found = strcmp(m_touchedpropname.ReadPtr(), meshObj->GetMaterialName(j).ReadPtr() + 2) == 0;
+ if (found) {
+ hitMaterial = true;
+ break;
+ }
+ }
}
- } else
- {
+ }
+ else {
found = (gameobj->GetProperty(m_touchedpropname) != NULL);
}
}
@@ -278,7 +289,7 @@ bool KX_TouchSensor::NewHandleCollision(void*object1,void*object2,const PHY_Coll
}
m_bTriggered = true;
m_hitObject = gameobj;
- m_hitMaterial = (client_info->m_auxilary_info ? (char*)client_info->m_auxilary_info : "");
+ m_hitMaterial = hitMaterial;
//printf("KX_TouchSensor::HandleCollision\n");
}
diff --git a/source/gameengine/Ketsji/KX_TouchSensor.h b/source/gameengine/Ketsji/KX_TouchSensor.h
index 0edca44296a..e1b5725a32b 100644
--- a/source/gameengine/Ketsji/KX_TouchSensor.h
+++ b/source/gameengine/Ketsji/KX_TouchSensor.h
@@ -34,7 +34,7 @@
#define __KX_TOUCHSENSOR_H__
#include "SCA_ISensor.h"
-#include "ListValue.h"
+#include "EXP_ListValue.h"
struct PHY_CollData;
diff --git a/source/gameengine/Ketsji/KX_TrackToActuator.cpp b/source/gameengine/Ketsji/KX_TrackToActuator.cpp
index 75baf5fac1d..3ed8eba759f 100644
--- a/source/gameengine/Ketsji/KX_TrackToActuator.cpp
+++ b/source/gameengine/Ketsji/KX_TrackToActuator.cpp
@@ -44,7 +44,7 @@
#include <iostream>
#include "KX_GameObject.h"
-#include "PyObjectPlus.h"
+#include "EXP_PyObjectPlus.h"
/* ------------------------------------------------------------------------- */
/* Native functions */
diff --git a/source/gameengine/Ketsji/KX_VehicleWrapper.cpp b/source/gameengine/Ketsji/KX_VehicleWrapper.cpp
index 535ed5ed39a..ee791a44782 100644
--- a/source/gameengine/Ketsji/KX_VehicleWrapper.cpp
+++ b/source/gameengine/Ketsji/KX_VehicleWrapper.cpp
@@ -22,7 +22,7 @@
* \ingroup ketsji
*/
-#include "PyObjectPlus.h"
+#include "EXP_PyObjectPlus.h"
#include "KX_VehicleWrapper.h"
#include "PHY_IPhysicsEnvironment.h"
@@ -53,6 +53,23 @@ KX_VehicleWrapper::~KX_VehicleWrapper()
#ifdef WITH_PYTHON
+
+static bool raise_exc_wheel(PHY_IVehicle *vehicle, int i, const char *method)
+{
+ if (i < 0 || i >= vehicle->GetNumWheels()) {
+ PyErr_Format(PyExc_ValueError,
+ "%s(...): wheel index %d out of range (0 to %d).", method, i, vehicle->GetNumWheels() - 1);
+ return true;
+ }
+ else {
+ return false;
+ }
+}
+
+#define WHEEL_INDEX_CHECK_OR_RETURN(i, method) \
+ if (raise_exc_wheel(m_vehicle, i, method)) {return NULL;} (void)0
+
+
PyObject *KX_VehicleWrapper::PyAddWheel(PyObject *args)
{
@@ -67,22 +84,36 @@ PyObject *KX_VehicleWrapper::PyAddWheel(PyObject *args)
KX_GameObject *gameOb;
if (!ConvertPythonToGameObject(wheelGameObject, &gameOb, false, "vehicle.addWheel(...): KX_VehicleWrapper (first argument)"))
return NULL;
-
if (gameOb->GetSGNode())
{
- PHY_IMotionState* motionState = new KX_MotionState(gameOb->GetSGNode());
-
- /* TODO - no error checking here! - bad juju */
MT_Vector3 attachPos,attachDir,attachAxle;
- PyVecTo(pylistPos,attachPos);
- PyVecTo(pylistDir,attachDir);
- PyVecTo(pylistAxleDir,attachAxle);
+ if(!PyVecTo(pylistPos,attachPos)) {
+ PyErr_SetString(PyExc_AttributeError,
+ "addWheel(...) Unable to add wheel. attachPos must be a vector with 3 elements.");
+ return NULL;
+ }
+ if(!PyVecTo(pylistDir,attachDir)) {
+ PyErr_SetString(PyExc_AttributeError,
+ "addWheel(...) Unable to add wheel. downDir must be a vector with 3 elements.");
+ return NULL;
+ }
+ if(!PyVecTo(pylistAxleDir,attachAxle)) {
+ PyErr_SetString(PyExc_AttributeError,
+ "addWheel(...) Unable to add wheel. axleDir must be a vector with 3 elements.");
+ return NULL;
+ }
//someone reverse some conventions inside Bullet (axle winding)
attachAxle = -attachAxle;
- printf("attempt for addWheel: suspensionRestLength%f wheelRadius %f, hasSteering:%d\n",suspensionRestLength,wheelRadius,hasSteering);
+ if(wheelRadius<=0) {
+ PyErr_SetString(PyExc_AttributeError,
+ "addWheel(...) Unable to add wheel. wheelRadius must be positive.");
+ return NULL;
+ }
+
+ PHY_IMotionState *motionState = new KX_MotionState(gameOb->GetSGNode());
m_vehicle->AddWheel(motionState,attachPos,attachDir,attachAxle,suspensionRestLength,wheelRadius,hasSteering);
}
@@ -93,8 +124,6 @@ PyObject *KX_VehicleWrapper::PyAddWheel(PyObject *args)
}
-
-
PyObject *KX_VehicleWrapper::PyGetWheelPosition(PyObject *args)
{
@@ -103,6 +132,8 @@ PyObject *KX_VehicleWrapper::PyGetWheelPosition(PyObject *args)
if (PyArg_ParseTuple(args,"i:getWheelPosition",&wheelIndex))
{
float position[3];
+ WHEEL_INDEX_CHECK_OR_RETURN(wheelIndex, "getWheelPosition");
+
m_vehicle->GetWheelPosition(wheelIndex,position[0],position[1],position[2]);
MT_Vector3 pos(position[0],position[1],position[2]);
return PyObjectFrom(pos);
@@ -115,6 +146,8 @@ PyObject *KX_VehicleWrapper::PyGetWheelRotation(PyObject *args)
int wheelIndex;
if (PyArg_ParseTuple(args,"i:getWheelRotation",&wheelIndex))
{
+ WHEEL_INDEX_CHECK_OR_RETURN(wheelIndex, "getWheelRotation");
+
return PyFloat_FromDouble(m_vehicle->GetWheelRotation(wheelIndex));
}
return NULL;
@@ -126,6 +159,8 @@ PyObject *KX_VehicleWrapper::PyGetWheelOrientationQuaternion(PyObject *args)
if (PyArg_ParseTuple(args,"i:getWheelOrientationQuaternion",&wheelIndex))
{
float orn[4];
+ WHEEL_INDEX_CHECK_OR_RETURN(wheelIndex, "getWheelOrientationQuaternion");
+
m_vehicle->GetWheelOrientationQuaternion(wheelIndex,orn[0],orn[1],orn[2],orn[3]);
MT_Quaternion quatorn(orn[0],orn[1],orn[2],orn[3]);
MT_Matrix3x3 ornmat(quatorn);
@@ -148,7 +183,6 @@ PyObject *KX_VehicleWrapper::PyGetConstraintId(PyObject *args)
}
-
PyObject *KX_VehicleWrapper::PyApplyEngineForce(PyObject *args)
{
float force;
@@ -156,6 +190,8 @@ PyObject *KX_VehicleWrapper::PyApplyEngineForce(PyObject *args)
if (PyArg_ParseTuple(args,"fi:applyEngineForce",&force,&wheelIndex))
{
+ WHEEL_INDEX_CHECK_OR_RETURN(wheelIndex, "applyEngineForce");
+
force *= -1.f;//someone reverse some conventions inside Bullet (axle winding)
m_vehicle->ApplyEngineForce(force,wheelIndex);
}
@@ -172,6 +208,8 @@ PyObject *KX_VehicleWrapper::PySetTyreFriction(PyObject *args)
if (PyArg_ParseTuple(args,"fi:setTyreFriction",&wheelFriction,&wheelIndex))
{
+ WHEEL_INDEX_CHECK_OR_RETURN(wheelIndex, "setTyreFriction");
+
m_vehicle->SetWheelFriction(wheelFriction,wheelIndex);
}
else {
@@ -187,6 +225,8 @@ PyObject *KX_VehicleWrapper::PySetSuspensionStiffness(PyObject *args)
if (PyArg_ParseTuple(args,"fi:setSuspensionStiffness",&suspensionStiffness,&wheelIndex))
{
+ WHEEL_INDEX_CHECK_OR_RETURN(wheelIndex, "setSuspensionStiffness");
+
m_vehicle->SetSuspensionStiffness(suspensionStiffness,wheelIndex);
}
else {
@@ -202,6 +242,8 @@ PyObject *KX_VehicleWrapper::PySetSuspensionDamping(PyObject *args)
if (PyArg_ParseTuple(args,"fi:setSuspensionDamping",&suspensionDamping,&wheelIndex))
{
+ WHEEL_INDEX_CHECK_OR_RETURN(wheelIndex, "setSuspensionDamping");
+
m_vehicle->SetSuspensionDamping(suspensionDamping,wheelIndex);
} else {
return NULL;
@@ -216,6 +258,8 @@ PyObject *KX_VehicleWrapper::PySetSuspensionCompression(PyObject *args)
if (PyArg_ParseTuple(args,"fi:setSuspensionCompression",&suspensionCompression,&wheelIndex))
{
+ WHEEL_INDEX_CHECK_OR_RETURN(wheelIndex, "setSuspensionCompression");
+
m_vehicle->SetSuspensionCompression(suspensionCompression,wheelIndex);
} else {
return NULL;
@@ -230,6 +274,8 @@ PyObject *KX_VehicleWrapper::PySetRollInfluence(PyObject *args)
if (PyArg_ParseTuple(args,"fi:setRollInfluence",&rollInfluence,&wheelIndex))
{
+ WHEEL_INDEX_CHECK_OR_RETURN(wheelIndex, "setRollInfluence");
+
m_vehicle->SetRollInfluence(rollInfluence,wheelIndex);
}
else {
@@ -246,6 +292,8 @@ PyObject *KX_VehicleWrapper::PyApplyBraking(PyObject *args)
if (PyArg_ParseTuple(args,"fi:applyBraking",&braking,&wheelIndex))
{
+ WHEEL_INDEX_CHECK_OR_RETURN(wheelIndex, "applyBraking");
+
m_vehicle->ApplyBraking(braking,wheelIndex);
}
else {
@@ -255,8 +303,6 @@ PyObject *KX_VehicleWrapper::PyApplyBraking(PyObject *args)
}
-
-
PyObject *KX_VehicleWrapper::PySetSteeringValue(PyObject *args)
{
float steeringValue;
@@ -264,6 +310,8 @@ PyObject *KX_VehicleWrapper::PySetSteeringValue(PyObject *args)
if (PyArg_ParseTuple(args,"fi:setSteeringValue",&steeringValue,&wheelIndex))
{
+ WHEEL_INDEX_CHECK_OR_RETURN(wheelIndex, "setSteeringValue");
+
m_vehicle->SetSteeringValue(steeringValue,wheelIndex);
}
else {
@@ -316,17 +364,11 @@ PyMethodDef KX_VehicleWrapper::Methods[] = {
{"setSteeringValue",(PyCFunction) KX_VehicleWrapper::sPySetSteeringValue, METH_VARARGS},
{"applyEngineForce",(PyCFunction) KX_VehicleWrapper::sPyApplyEngineForce, METH_VARARGS},
{"applyBraking",(PyCFunction) KX_VehicleWrapper::sPyApplyBraking, METH_VARARGS},
-
{"setTyreFriction",(PyCFunction) KX_VehicleWrapper::sPySetTyreFriction, METH_VARARGS},
-
{"setSuspensionStiffness",(PyCFunction) KX_VehicleWrapper::sPySetSuspensionStiffness, METH_VARARGS},
-
{"setSuspensionDamping",(PyCFunction) KX_VehicleWrapper::sPySetSuspensionDamping, METH_VARARGS},
-
{"setSuspensionCompression",(PyCFunction) KX_VehicleWrapper::sPySetSuspensionCompression, METH_VARARGS},
-
{"setRollInfluence",(PyCFunction) KX_VehicleWrapper::sPySetRollInfluence, METH_VARARGS},
-
{NULL,NULL} //Sentinel
};
diff --git a/source/gameengine/Ketsji/KX_VehicleWrapper.h b/source/gameengine/Ketsji/KX_VehicleWrapper.h
index c38f57d8b9f..22b9591f48b 100644
--- a/source/gameengine/Ketsji/KX_VehicleWrapper.h
+++ b/source/gameengine/Ketsji/KX_VehicleWrapper.h
@@ -6,7 +6,7 @@
#ifndef __KX_VEHICLEWRAPPER_H__
#define __KX_VEHICLEWRAPPER_H__
-#include "Value.h"
+#include "EXP_Value.h"
class PHY_IVehicle;
class PHY_IMotionState;
diff --git a/source/gameengine/Ketsji/KX_WorldInfo.cpp b/source/gameengine/Ketsji/KX_WorldInfo.cpp
index 444d6b0771b..111d81cad2e 100644
--- a/source/gameengine/Ketsji/KX_WorldInfo.cpp
+++ b/source/gameengine/Ketsji/KX_WorldInfo.cpp
@@ -31,8 +31,464 @@
#include "KX_WorldInfo.h"
+#include "KX_PythonInit.h"
+#include "KX_PyMath.h"
+#include "RAS_IRasterizer.h"
+#include "GPU_material.h"
+
+/* This little block needed for linking to Blender... */
+#ifdef WIN32
+#include "BLI_winstuff.h"
+#endif
+
+/* This list includes only data type definitions */
+#include "DNA_scene_types.h"
+#include "DNA_world_types.h"
+
+#include "BLI_math.h"
+
+#include "BKE_global.h"
+#include "BKE_scene.h"
+/* end of blender include block */
+
+
+KX_WorldInfo::KX_WorldInfo(Scene *blenderscene, World *blenderworld)
+{
+ if (blenderworld) {
+ m_name = blenderworld->id.name + 2;
+ m_do_color_management = BKE_scene_check_color_management_enabled(blenderscene);
+ m_hasworld = true;
+ m_hasmist = ((blenderworld->mode) & WO_MIST ? true : false);
+ m_misttype = blenderworld->mistype;
+ m_miststart = blenderworld->miststa;
+ m_mistdistance = blenderworld->mistdist;
+ m_mistintensity = blenderworld->misi;
+ setMistColor(blenderworld->horr, blenderworld->horg, blenderworld->horb);
+ setBackColor(blenderworld->horr, blenderworld->horg, blenderworld->horb);
+ setAmbientColor(blenderworld->ambr, blenderworld->ambg, blenderworld->ambb);
+ }
+ else {
+ m_hasworld = false;
+ }
+}
KX_WorldInfo::~KX_WorldInfo()
{
}
+const STR_String& KX_WorldInfo::GetName()
+{
+ return m_name;
+}
+
+bool KX_WorldInfo::hasWorld()
+{
+ return m_hasworld;
+}
+
+void KX_WorldInfo::setBackColor(float r, float g, float b)
+{
+ m_backgroundcolor[0] = r;
+ m_backgroundcolor[1] = g;
+ m_backgroundcolor[2] = b;
+
+ if (m_do_color_management) {
+ linearrgb_to_srgb_v3_v3(m_con_backgroundcolor, m_backgroundcolor);
+ }
+ else {
+ copy_v3_v3(m_con_backgroundcolor, m_backgroundcolor);
+ }
+}
+
+const float *KX_WorldInfo::getBackColorConverted() const
+{
+ return m_con_backgroundcolor;
+}
+
+void KX_WorldInfo::setMistType(short type)
+{
+ m_misttype = type;
+}
+
+void KX_WorldInfo::setUseMist(bool enable)
+{
+ m_hasmist = enable;
+}
+
+void KX_WorldInfo::setMistStart(float d)
+{
+ m_miststart = d;
+}
+
+void KX_WorldInfo::setMistDistance(float d)
+{
+ m_mistdistance = d;
+}
+
+void KX_WorldInfo::setMistIntensity(float intensity)
+{
+ m_mistintensity = intensity;
+}
+void KX_WorldInfo::setMistColor(float r, float g, float b)
+{
+ m_mistcolor[0] = r;
+ m_mistcolor[1] = g;
+ m_mistcolor[2] = b;
+
+ if (m_do_color_management) {
+ linearrgb_to_srgb_v3_v3(m_con_mistcolor, m_mistcolor);
+ }
+ else {
+ copy_v3_v3(m_con_mistcolor, m_mistcolor);
+ }
+}
+
+void KX_WorldInfo::setAmbientColor(float r, float g, float b)
+{
+ m_ambientcolor[0] = r;
+ m_ambientcolor[1] = g;
+ m_ambientcolor[2] = b;
+
+ if (m_do_color_management) {
+ linearrgb_to_srgb_v3_v3(m_con_ambientcolor, m_ambientcolor);
+ }
+ else {
+ copy_v3_v3(m_con_ambientcolor, m_ambientcolor);
+ }
+}
+
+void KX_WorldInfo::UpdateBackGround()
+{
+ if (m_hasworld) {
+ RAS_IRasterizer *m_rasterizer = KX_GetActiveEngine()->GetRasterizer();
+
+ if (m_rasterizer->GetDrawingMode() >= RAS_IRasterizer::KX_SOLID) {
+ m_rasterizer->SetBackColor(m_con_backgroundcolor);
+ GPU_horizon_update_color(m_backgroundcolor);
+ }
+ }
+}
+
+void KX_WorldInfo::UpdateWorldSettings()
+{
+ if (m_hasworld) {
+ RAS_IRasterizer *m_rasterizer = KX_GetActiveEngine()->GetRasterizer();
+
+ if (m_rasterizer->GetDrawingMode() >= RAS_IRasterizer::KX_SOLID) {
+ m_rasterizer->SetAmbientColor(m_con_ambientcolor);
+ GPU_ambient_update_color(m_ambientcolor);
+
+ if (m_hasmist) {
+ m_rasterizer->SetFog(m_misttype, m_miststart, m_mistdistance, m_mistintensity, m_con_mistcolor);
+ GPU_mist_update_values(m_misttype, m_miststart, m_mistdistance, m_mistintensity, m_mistcolor);
+ m_rasterizer->EnableFog(true);
+ GPU_mist_update_enable(true);
+ }
+ else {
+ m_rasterizer->EnableFog(false);
+ GPU_mist_update_enable(false);
+ }
+ }
+ }
+}
+
+#ifdef WITH_PYTHON
+
+/* -------------------------------------------------------------------------
+ * Python functions
+ * ------------------------------------------------------------------------- */
+PyObject *KX_WorldInfo::py_repr(void)
+{
+ return PyUnicode_From_STR_String(GetName());
+}
+
+/* -------------------------------------------------------------------------
+ * Python Integration Hooks
+ * ------------------------------------------------------------------------- */
+PyTypeObject KX_WorldInfo::Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "KX_WorldInfo",
+ sizeof(PyObjectPlus_Proxy),
+ 0,
+ py_base_dealloc,
+ 0,
+ 0,
+ 0,
+ 0,
+ py_base_repr,
+ 0,0,0,0,0,0,0,0,0,
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
+ 0,0,0,0,0,0,0,
+ Methods,
+ 0,
+ 0,
+ &PyObjectPlus::Type,
+ 0,0,0,0,0,0,
+ py_base_new
+};
+
+PyMethodDef KX_WorldInfo::Methods[] = {
+ {NULL,NULL} /* Sentinel */
+};
+
+PyAttributeDef KX_WorldInfo::Attributes[] = {
+ KX_PYATTRIBUTE_BOOL_RW("mistEnable", KX_WorldInfo, m_hasmist),
+ KX_PYATTRIBUTE_FLOAT_RW("mistStart", 0.0f, 10000.0f, KX_WorldInfo, m_miststart),
+ KX_PYATTRIBUTE_FLOAT_RW("mistDistance", 0.001f, 10000.0f, KX_WorldInfo, m_mistdistance),
+ KX_PYATTRIBUTE_FLOAT_RW("mistIntensity", 0.0f, 1.0f, KX_WorldInfo, m_mistintensity),
+ KX_PYATTRIBUTE_SHORT_RW("mistType", 0, 2, true, KX_WorldInfo, m_misttype),
+ KX_PYATTRIBUTE_RO_FUNCTION("KX_MIST_QUADRATIC", KX_WorldInfo, pyattr_get_mist_typeconst),
+ KX_PYATTRIBUTE_RO_FUNCTION("KX_MIST_LINEAR", KX_WorldInfo, pyattr_get_mist_typeconst),
+ KX_PYATTRIBUTE_RO_FUNCTION("KX_MIST_INV_QUADRATIC", KX_WorldInfo, pyattr_get_mist_typeconst),
+ KX_PYATTRIBUTE_RW_FUNCTION("mistColor", KX_WorldInfo, pyattr_get_mist_color, pyattr_set_mist_color),
+ KX_PYATTRIBUTE_RW_FUNCTION("backgroundColor", KX_WorldInfo, pyattr_get_back_color, pyattr_set_back_color),
+ KX_PYATTRIBUTE_RW_FUNCTION("ambientColor", KX_WorldInfo, pyattr_get_ambient_color, pyattr_set_ambient_color),
+ { NULL } /* Sentinel */
+};
+
+/* Attribute get/set functions */
+
+#ifdef USE_MATHUTILS
+
+/*----------------------mathutils callbacks ----------------------------*/
+
+/* subtype */
+#define MATHUTILS_VEC_CB_MIST_COLOR 1
+#define MATHUTILS_VEC_CB_BACK_COLOR 2
+#define MATHUTILS_VEC_CB_AMBIENT_COLOR 3
+
+static unsigned char mathutils_world_vector_cb_index = -1; /* index for our callbacks */
+
+static int mathutils_world_generic_check(BaseMathObject *bmo)
+{
+ KX_WorldInfo *self = static_cast<KX_WorldInfo*>BGE_PROXY_REF(bmo->cb_user);
+ if (self == NULL)
+ return -1;
+
+ return 0;
+}
+
+static int mathutils_world_vector_get(BaseMathObject *bmo, int subtype)
+{
+ KX_WorldInfo *self = static_cast<KX_WorldInfo*>BGE_PROXY_REF(bmo->cb_user);
+ if (self == NULL)
+ return -1;
+
+ switch (subtype) {
+ case MATHUTILS_VEC_CB_MIST_COLOR:
+ copy_v3_v3(bmo->data, self->m_mistcolor);
+ break;
+ case MATHUTILS_VEC_CB_BACK_COLOR:
+ copy_v3_v3(bmo->data, self->m_backgroundcolor);
+ break;
+ case MATHUTILS_VEC_CB_AMBIENT_COLOR:
+ copy_v3_v3(bmo->data, self->m_ambientcolor);
+ break;
+ default:
+ return -1;
+ }
+ return 0;
+}
+
+static int mathutils_world_vector_set(BaseMathObject *bmo, int subtype)
+{
+ KX_WorldInfo *self = static_cast<KX_WorldInfo*>BGE_PROXY_REF(bmo->cb_user);
+
+ if (self == NULL)
+ return -1;
+
+ switch (subtype) {
+ case MATHUTILS_VEC_CB_MIST_COLOR:
+ self->setMistColor(bmo->data[0], bmo->data[1], bmo->data[2]);
+ break;
+ case MATHUTILS_VEC_CB_BACK_COLOR:
+ self->setBackColor(bmo->data[0], bmo->data[1], bmo->data[2]);
+ break;
+ case MATHUTILS_VEC_CB_AMBIENT_COLOR:
+ self->setAmbientColor(bmo->data[0], bmo->data[1], bmo->data[2]);
+ break;
+ default:
+ return -1;
+ }
+ return 0;
+}
+
+static int mathutils_world_vector_get_index(BaseMathObject *bmo, int subtype, int index)
+{
+ KX_WorldInfo *self = static_cast<KX_WorldInfo*>BGE_PROXY_REF(bmo->cb_user);
+
+ if (self == NULL)
+ return -1;
+
+ switch (subtype) {
+ case MATHUTILS_VEC_CB_MIST_COLOR:
+ {
+ const float *color = self->m_mistcolor;
+ bmo->data[index] = color[index];
+ }
+ break;
+ case MATHUTILS_VEC_CB_BACK_COLOR:
+ {
+ const float *color = self->m_backgroundcolor;
+ bmo->data[index] = color[index];
+ }
+ break;
+ case MATHUTILS_VEC_CB_AMBIENT_COLOR:
+ {
+ const float *color = self->m_ambientcolor;
+ bmo->data[index] = color[index];
+ }
+ break;
+ default:
+ return -1;
+ }
+ return 0;
+}
+
+static int mathutils_world_vector_set_index(BaseMathObject *bmo, int subtype, int index)
+{
+ KX_WorldInfo *self = static_cast<KX_WorldInfo*>BGE_PROXY_REF(bmo->cb_user);
+
+ if (self == NULL)
+ return -1;
+
+ float color[4];
+ switch (subtype) {
+ case MATHUTILS_VEC_CB_MIST_COLOR:
+ copy_v3_v3(color, self->m_mistcolor);
+ color[index] = bmo->data[index];
+ self->setMistColor(color[0], color[1], color[2]);
+ break;
+ case MATHUTILS_VEC_CB_BACK_COLOR:
+ copy_v3_v3(color, self->m_backgroundcolor);
+ color[index] = bmo->data[index];
+ self->setBackColor(color[0], color[1], color[2]);
+ break;
+ case MATHUTILS_VEC_CB_AMBIENT_COLOR:
+ copy_v3_v3(color, self->m_ambientcolor);
+ color[index] = bmo->data[index];
+ self->setAmbientColor(color[0], color[1], color[2]);
+ break;
+ default:
+ return -1;
+ }
+ return 0;
+}
+
+static Mathutils_Callback mathutils_world_vector_cb = {
+ mathutils_world_generic_check,
+ mathutils_world_vector_get,
+ mathutils_world_vector_set,
+ mathutils_world_vector_get_index,
+ mathutils_world_vector_set_index
+};
+
+void KX_WorldInfo_Mathutils_Callback_Init()
+{
+ // register mathutils callbacks, ok to run more than once.
+ mathutils_world_vector_cb_index = Mathutils_RegisterCallback(&mathutils_world_vector_cb);
+}
+#endif // USE_MATHUTILS
+
+
+PyObject *KX_WorldInfo::pyattr_get_mist_typeconst(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+{
+ PyObject *retvalue;
+
+ const char* type = attrdef->m_name;
+
+ if (!strcmp(type, "KX_MIST_QUADRATIC")) {
+ retvalue = PyLong_FromLong(KX_MIST_QUADRATIC);
+ }
+ else if (!strcmp(type, "KX_MIST_LINEAR")) {
+ retvalue = PyLong_FromLong(KX_MIST_LINEAR);
+ }
+ else if (!strcmp(type, "KX_MIST_INV_QUADRATIC")) {
+ retvalue = PyLong_FromLong(KX_MIST_INV_QUADRATIC);
+ }
+ else {
+ /* should never happen */
+ PyErr_SetString(PyExc_TypeError, "invalid mist type");
+ retvalue = NULL;
+ }
+
+ return retvalue;
+}
+
+PyObject *KX_WorldInfo::pyattr_get_mist_color(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+{
+#ifdef USE_MATHUTILS
+ return Vector_CreatePyObject_cb(
+ BGE_PROXY_FROM_REF_BORROW(self_v), 3,
+ mathutils_world_vector_cb_index, MATHUTILS_VEC_CB_MIST_COLOR);
+#else
+ KX_WorldInfo *self = static_cast<KX_WorldInfo*>(self_v);
+ return PyObjectFrom(MT_Vector3(self->m_mistcolor));
+#endif
+}
+
+int KX_WorldInfo::pyattr_set_mist_color(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
+{
+ KX_WorldInfo *self = static_cast<KX_WorldInfo*>(self_v);
+
+ MT_Vector3 color;
+ if (PyVecTo(value, color))
+ {
+ self->setMistColor(color[0], color[1], color[2]);
+ return PY_SET_ATTR_SUCCESS;
+ }
+ return PY_SET_ATTR_FAIL;
+}
+
+PyObject *KX_WorldInfo::pyattr_get_back_color(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+{
+
+#ifdef USE_MATHUTILS
+ return Vector_CreatePyObject_cb(
+ BGE_PROXY_FROM_REF_BORROW(self_v), 3,
+ mathutils_world_vector_cb_index, MATHUTILS_VEC_CB_BACK_COLOR);
+#else
+ KX_WorldInfo *self = static_cast<KX_WorldInfo*>(self_v);
+ return PyObjectFrom(MT_Vector3(self->m_backgroundcolor));
+#endif
+}
+
+int KX_WorldInfo::pyattr_set_back_color(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
+{
+ KX_WorldInfo *self = static_cast<KX_WorldInfo*>(self_v);
+
+ MT_Vector3 color;
+ if (PyVecTo(value, color))
+ {
+ self->setBackColor(color[0], color[1], color[2]);
+ return PY_SET_ATTR_SUCCESS;
+ }
+ return PY_SET_ATTR_FAIL;
+}
+
+PyObject *KX_WorldInfo::pyattr_get_ambient_color(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+{
+#ifdef USE_MATHUTILS
+ return Vector_CreatePyObject_cb(
+ BGE_PROXY_FROM_REF_BORROW(self_v), 3,
+ mathutils_world_vector_cb_index, MATHUTILS_VEC_CB_AMBIENT_COLOR);
+#else
+ KX_WorldInfo *self = static_cast<KX_WorldInfo*>(self_v);
+ return PyObjectFrom(MT_Vector3(self->m_ambientcolor));
+#endif
+}
+
+int KX_WorldInfo::pyattr_set_ambient_color(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
+{
+ KX_WorldInfo *self = static_cast<KX_WorldInfo*>(self_v);
+
+ MT_Vector3 color;
+ if (PyVecTo(value, color))
+ {
+ self->setAmbientColor(color[0], color[1], color[2]);
+ return PY_SET_ATTR_SUCCESS;
+ }
+ return PY_SET_ATTR_FAIL;
+}
+
+#endif /* WITH_PYTHON */
diff --git a/source/gameengine/Ketsji/KX_WorldInfo.h b/source/gameengine/Ketsji/KX_WorldInfo.h
index 90b16fe1242..b155faf2837 100644
--- a/source/gameengine/Ketsji/KX_WorldInfo.h
+++ b/source/gameengine/Ketsji/KX_WorldInfo.h
@@ -33,44 +33,72 @@
#define __KX_WORLDINFO_H__
#include "MT_Scalar.h"
+#include "KX_KetsjiEngine.h"
+#include "EXP_PyObjectPlus.h"
-#ifdef WITH_CXX_GUARDEDALLOC
-#include "MEM_guardedalloc.h"
+#ifdef USE_MATHUTILS
+void KX_WorldInfo_Mathutils_Callback_Init(void);
#endif
-class MT_CmMatrix4x4;
+struct Scene;
+struct World;
-class KX_WorldInfo
+class KX_WorldInfo : public PyObjectPlus
{
-public:
- KX_WorldInfo() {}
- virtual ~KX_WorldInfo();
+ Py_Header
- virtual bool hasWorld() = 0;
- virtual bool hasMist() = 0;
- virtual float getBackColorRed() = 0;
- virtual float getBackColorGreen() = 0;
- virtual float getBackColorBlue() = 0;
- virtual float getMistStart() = 0;
- virtual float getMistDistance() = 0;
- virtual float getMistColorRed() = 0;
- virtual float getMistColorGreen() = 0;
- virtual float getMistColorBlue() = 0;
+ STR_String m_name;
+ bool m_do_color_management;
+ bool m_hasworld;
+ bool m_hasmist;
+ short m_misttype;
+ float m_miststart;
+ float m_mistdistance;
+ float m_mistintensity;
+ float m_mistcolor[3];
+ float m_backgroundcolor[3];
+ float m_ambientcolor[3];
+ float m_con_mistcolor[3];
+ float m_con_backgroundcolor[3];
+ float m_con_ambientcolor[3];
- virtual float getAmbientColorRed() = 0;
- virtual float getAmbientColorGreen() = 0;
- virtual float getAmbientColorBlue() = 0;
+public:
+ /**
+ * Mist options
+ */
+ enum MistType {
+ KX_MIST_QUADRATIC,
+ KX_MIST_LINEAR,
+ KX_MIST_INV_QUADRATIC,
+ };
- virtual void setBackColor(float, float, float) = 0;
- virtual void setMistStart(float) = 0;
- virtual void setMistDistance(float) = 0;
- virtual void setMistColorRed(float) = 0;
- virtual void setMistColorGreen(float) = 0;
- virtual void setMistColorBlue(float) = 0;
+ KX_WorldInfo(Scene *blenderscene, World *blenderworld);
+ ~KX_WorldInfo();
+ const STR_String &GetName();
+ bool hasWorld();
+ void setUseMist(bool enable);
+ void setMistType(short type);
+ void setMistStart(float d);
+ void setMistDistance(float d);
+ void setMistIntensity(float intensity);
+ void setMistColor(float r, float g, float b);
+ void setBackColor(float r, float g, float b);
+ const float *getBackColorConverted() const;
+ void setAmbientColor(float r, float g, float b);
+ void UpdateBackGround();
+ void UpdateWorldSettings();
-#ifdef WITH_CXX_GUARDEDALLOC
- MEM_CXX_CLASS_ALLOC_FUNCS("GE:KX_WorldInfo")
+#ifdef WITH_PYTHON
+ /* attributes */
+ static PyObject *pyattr_get_mist_typeconst(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+ static PyObject *pyattr_get_mist_color(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+ static int pyattr_set_mist_color(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
+ static PyObject *pyattr_get_back_color(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+ static int pyattr_set_back_color(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
+ static PyObject *pyattr_get_ambient_color(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+ static int pyattr_set_ambient_color(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
+ virtual PyObject *py_repr(void);
#endif
};
diff --git a/source/gameengine/Ketsji/KX_WorldIpoController.cpp b/source/gameengine/Ketsji/KX_WorldIpoController.cpp
index 7f83a155643..1123e07ebcc 100644
--- a/source/gameengine/Ketsji/KX_WorldIpoController.cpp
+++ b/source/gameengine/Ketsji/KX_WorldIpoController.cpp
@@ -33,6 +33,8 @@
#include "KX_WorldIpoController.h"
#include "KX_ScalarInterpolator.h"
#include "KX_WorldInfo.h"
+#include "KX_PythonInit.h"
+#include "KX_Scene.h"
#if defined(_WIN64)
typedef unsigned __int64 uint_ptr;
@@ -42,31 +44,36 @@ typedef unsigned long uint_ptr;
bool KX_WorldIpoController::Update(double currentTime)
{
- if (m_modified)
- {
+ if (m_modified) {
T_InterpolatorList::iterator i;
for (i = m_interpolators.begin(); !(i == m_interpolators.end()); ++i) {
- (*i)->Execute(m_ipotime);//currentTime);
+ (*i)->Execute(m_ipotime);
}
- /* TODO, this will crash! */
- KX_WorldInfo *world = NULL;
+ KX_WorldInfo *world = KX_GetActiveScene()->GetWorldInfo();
if (m_modify_mist_start) {
world->setMistStart(m_mist_start);
}
- if (m_modify_mist_color) {
- world->setMistColorRed(m_mist_rgb[0]);
- world->setMistColorGreen(m_mist_rgb[1]);
- world->setMistColorBlue(m_mist_rgb[2]);
- }
-
if (m_modify_mist_dist) {
world->setMistDistance(m_mist_dist);
}
- m_modified=false;
+ if (m_modify_mist_intensity) {
+ world->setMistIntensity(m_mist_intensity);
+ }
+
+ if (m_modify_horizon_color) {
+ world->setBackColor(m_hori_rgb[0], m_hori_rgb[1], m_hori_rgb[2]);
+ world->setMistColor(m_hori_rgb[0], m_hori_rgb[1], m_hori_rgb[2]);
+ }
+
+ if (m_modify_ambient_color) {
+ world->setAmbientColor(m_ambi_rgb[0], m_ambi_rgb[1], m_ambi_rgb[2]);
+ }
+
+ m_modified = false;
}
return false;
}
diff --git a/source/gameengine/Ketsji/KX_WorldIpoController.h b/source/gameengine/Ketsji/KX_WorldIpoController.h
index 63983b3129b..704f421573e 100644
--- a/source/gameengine/Ketsji/KX_WorldIpoController.h
+++ b/source/gameengine/Ketsji/KX_WorldIpoController.h
@@ -39,24 +39,30 @@
class KX_WorldIpoController : public SG_Controller
{
public:
- MT_Scalar m_mist_rgb[3];
MT_Scalar m_mist_start;
MT_Scalar m_mist_dist;
+ MT_Scalar m_mist_intensity;
+ MT_Scalar m_hori_rgb[3];
+ MT_Scalar m_ambi_rgb[3];
private:
T_InterpolatorList m_interpolators;
- unsigned short m_modify_mist_color : 1;
unsigned short m_modify_mist_start : 1;
unsigned short m_modify_mist_dist : 1;
+ unsigned short m_modify_mist_intensity : 1;
+ unsigned short m_modify_horizon_color : 1;
+ unsigned short m_modify_ambient_color : 1;
bool m_modified;
double m_ipotime;
public:
KX_WorldIpoController() :
- m_modify_mist_color(false),
m_modify_mist_start(false),
m_modify_mist_dist(false),
+ m_modify_mist_intensity(false),
+ m_modify_horizon_color(false),
+ m_modify_ambient_color(false),
m_modified(true),
m_ipotime(0.0)
{}
@@ -76,14 +82,22 @@ public:
m_modify_mist_start = modify;
}
- void SetModifyMistColor(bool modify) {
- m_modify_mist_color = modify;
- }
-
void SetModifyMistDist(bool modify) {
m_modify_mist_dist = modify;
}
+ void SetModifyMistIntensity(bool modify) {
+ m_modify_mist_intensity = modify;
+ }
+
+ void SetModifyHorizonColor(bool modify) {
+ m_modify_horizon_color = modify;
+ }
+
+ void SetModifyAmbientColor(bool modify) {
+ m_modify_ambient_color = modify;
+ }
+
void
SetOption(
int option,
diff --git a/source/gameengine/Ketsji/SConscript b/source/gameengine/Ketsji/SConscript
index db5474cf2d7..d8dfd3d9bca 100644
--- a/source/gameengine/Ketsji/SConscript
+++ b/source/gameengine/Ketsji/SConscript
@@ -30,7 +30,8 @@ import sys
Import ('env')
sources = env.Glob('*.cpp')
-defs = [ 'GLEW_STATIC' ]
+defs = []
+defs += env['BF_GL_DEFINITIONS']
incs = [
'.',
@@ -38,9 +39,8 @@ incs = [
'#intern/guardedalloc',
'#intern/string',
'#source/blender',
- '#extern/glew/include',
- '#intern/audaspace/FX',
- '#intern/audaspace/intern',
+ env['BF_GLEW_INC'],
+ '#/intern/glew-mx',
'#intern/moto/include',
'#source/blender/blenfont',
'#source/blender/blenkernel',
@@ -85,6 +85,11 @@ if env['WITH_BF_PYTHON']:
incs += ' ' + env['BF_PYTHON_INC']
defs.append('WITH_PYTHON')
+if env['WITH_BF_AUDASPACE']:
+ defs += env['BF_AUDASPACE_DEF']
+ incs += ' ' + env['BF_AUDASPACE_C_INC']
+ incs += ' ' + env['BF_AUDASPACE_PY_INC']
+
if env['WITH_BF_FFMPEG']:
defs.append('WITH_FFMPEG')
diff --git a/source/gameengine/Network/CMakeLists.txt b/source/gameengine/Network/CMakeLists.txt
index bae00c464f2..019fc3e6032 100644
--- a/source/gameengine/Network/CMakeLists.txt
+++ b/source/gameengine/Network/CMakeLists.txt
@@ -27,6 +27,7 @@ set(INC
.
../../../intern/container
../../../intern/string
+ ../../blender/blenlib
)
set(INC_SYS
diff --git a/source/gameengine/Network/SConscript b/source/gameengine/Network/SConscript
index 1d78cdba174..feb14e29552 100644
--- a/source/gameengine/Network/SConscript
+++ b/source/gameengine/Network/SConscript
@@ -31,6 +31,7 @@ sources = env.Glob('*.cpp') #'NG_NetworkMessage.cpp NG_NetworkObject.cpp NG_Netw
incs = [
'.',
+ '../../blender/blenlib',
'#intern/container',
'#intern/string',
'#intern/moto/include',
diff --git a/source/gameengine/Physics/Bullet/CMakeLists.txt b/source/gameengine/Physics/Bullet/CMakeLists.txt
index fbaa7bb59ba..e52dc1ba052 100644
--- a/source/gameengine/Physics/Bullet/CMakeLists.txt
+++ b/source/gameengine/Physics/Bullet/CMakeLists.txt
@@ -40,6 +40,7 @@ set(INC
../../../blender/makesdna
../../../../intern/container
../../../../intern/guardedalloc
+ ../../../../intern/glew-mx
../../../../intern/string
)
@@ -66,4 +67,6 @@ if(WITH_BULLET)
add_definitions(-DWITH_BULLET)
endif()
+add_definitions(${GL_DEFINITIONS})
+
blender_add_lib(ge_phys_bullet "${SRC}" "${INC}" "${INC_SYS}")
diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp b/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp
index 72c3b13e301..dbaa925db08 100644
--- a/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp
+++ b/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp
@@ -39,7 +39,6 @@ subject to the following restrictions:
#include "LinearMath/btConvexHull.h"
#include "BulletCollision/Gimpact/btGImpactShape.h"
-
#include "BulletSoftBody/btSoftRigidDynamicsWorld.h"
#include "DNA_mesh_types.h"
@@ -65,7 +64,6 @@ extern bool gDisableDeactivation;
float gLinearSleepingTreshold;
float gAngularSleepingTreshold;
-
BlenderBulletCharacterController::BlenderBulletCharacterController(btMotionState *motionState, btPairCachingGhostObject *ghost, btConvexShape* shape, float stepHeight)
: btKinematicCharacterController(ghost,shape,stepHeight,2),
m_motionState(motionState),
@@ -118,6 +116,18 @@ const btVector3& BlenderBulletCharacterController::getWalkDirection()
return m_walkDirection;
}
+bool CleanPairCallback::processOverlap(btBroadphasePair &pair)
+{
+ if ((pair.m_pProxy0 == m_cleanProxy) || (pair.m_pProxy1 == m_cleanProxy)) {
+ m_pairCache->cleanOverlappingPair(pair, m_dispatcher);
+ CcdPhysicsController *ctrl0 = (CcdPhysicsController*)(((btCollisionObject*)pair.m_pProxy0->m_clientObject)->getUserPointer());
+ CcdPhysicsController *ctrl1 = (CcdPhysicsController*)(((btCollisionObject*)pair.m_pProxy1->m_clientObject)->getUserPointer());
+ ctrl0->GetCollisionObject()->activate(false);
+ ctrl1->GetCollisionObject()->activate(false);
+ }
+ return false;
+}
+
CcdPhysicsController::CcdPhysicsController (const CcdConstructionInfo& ci)
:m_cci(ci)
{
@@ -148,11 +158,34 @@ CcdPhysicsController::CcdPhysicsController (const CcdConstructionInfo& ci)
m_savedCollisionFilterGroup = 0;
m_savedCollisionFilterMask = 0;
m_savedMass = 0.0;
+ m_savedDyna = false;
m_suspended = false;
CreateRigidbody();
}
+void CcdPhysicsController::addCcdConstraintRef(btTypedConstraint* c)
+{
+ int index = m_ccdConstraintRefs.findLinearSearch(c);
+ if (index == m_ccdConstraintRefs.size())
+ m_ccdConstraintRefs.push_back(c);
+}
+
+void CcdPhysicsController::removeCcdConstraintRef(btTypedConstraint* c)
+{
+ m_ccdConstraintRefs.remove(c);
+}
+
+btTypedConstraint* CcdPhysicsController::getCcdConstraintRef(int index)
+{
+ return m_ccdConstraintRefs[index];
+}
+
+int CcdPhysicsController::getNumCcdConstraintRefs() const
+{
+ return m_ccdConstraintRefs.size();
+}
+
btTransform& CcdPhysicsController::GetTransformFromMotionState(PHY_IMotionState* motionState)
{
static btTransform trans;
@@ -207,6 +240,11 @@ btRigidBody* CcdPhysicsController::GetRigidBody()
{
return btRigidBody::upcast(m_object);
}
+const btRigidBody* CcdPhysicsController::GetRigidBody() const
+{
+ return btRigidBody::upcast(m_object);
+}
+
btCollisionObject* CcdPhysicsController::GetCollisionObject()
{
return m_object;
@@ -560,20 +598,13 @@ void CcdPhysicsController::CreateRigidbody()
static void DeleteBulletShape(btCollisionShape* shape, bool free)
{
- if (shape->getShapeType() == TRIANGLE_MESH_SHAPE_PROXYTYPE)
- {
- // shapes based on meshes use an interface that contains the vertices.
- btTriangleMeshShape* meshShape = static_cast<btTriangleMeshShape*>(shape);
- btStridingMeshInterface* meshInterface = meshShape->getMeshInterface();
- if (meshInterface)
- delete meshInterface;
- }
- else if (shape->getShapeType() == GIMPACT_SHAPE_PROXYTYPE)
- {
- btGImpactMeshShape* meshShape = static_cast<btGImpactMeshShape*>(shape);
- btStridingMeshInterface* meshInterface = meshShape->getMeshInterface();
- if (meshInterface)
- delete meshInterface;
+ if (shape->getShapeType() == SCALED_TRIANGLE_MESH_SHAPE_PROXYTYPE) {
+ /* If we use Bullet scaled shape (btScaledBvhTriangleMeshShape) we have to
+ * free the child of the unscaled shape (btTriangleMeshShape) here.
+ */
+ btTriangleMeshShape *meshShape = ((btScaledBvhTriangleMeshShape *)shape)->getChildShape();
+ if (meshShape)
+ delete meshShape;
}
if (free) {
delete shape;
@@ -606,48 +637,41 @@ bool CcdPhysicsController::DeleteControllerShape( )
bool CcdPhysicsController::ReplaceControllerShape(btCollisionShape *newShape)
{
-
- /* Note, deleting the previous collision shape must be done already */
- /* if (m_collisionShape) DeleteControllerShape(); */
+ if (m_collisionShape)
+ DeleteControllerShape();
+
+ // If newShape is NULL it means to create a new Bullet shape.
+ if (!newShape)
+ newShape = m_shapeInfo->CreateBulletShape(m_cci.m_margin, m_cci.m_bGimpact, !m_cci.m_bSoft);
m_object->setCollisionShape(newShape);
- m_collisionShape= newShape;
- m_cci.m_collisionShape= newShape;
-
- if (GetSoftBody()) {
+ m_collisionShape = newShape;
+ m_cci.m_collisionShape = newShape;
+
+ btSoftBody *softBody = GetSoftBody();
+ if (softBody) {
+ btSoftRigidDynamicsWorld *world = GetPhysicsEnvironment()->GetDynamicsWorld();
+ // remove the old softBody
+ world->removeSoftBody(softBody);
+
// soft body must be recreated
- m_cci.m_physicsEnv->RemoveCcdPhysicsController(this);
delete m_object;
m_object = NULL;
// force complete reinitialization
m_softbodyMappingDone = false;
m_prototypeTransformInitialized = false;
m_softBodyTransformInitialized = false;
+
CreateSoftbody();
assert(m_object);
- // reinsert the new body
- m_cci.m_physicsEnv->AddCcdPhysicsController(this);
- }
-
- /* Copied from CcdPhysicsEnvironment::addCcdPhysicsController() */
-
- /* without this, an object can rest on the old physics mesh
- * and not move to account for the physics mesh, even with 'nosleep' */
- btSoftRigidDynamicsWorld* dw= GetPhysicsEnvironment()->GetDynamicsWorld();
- btCollisionObjectArray &obarr= dw->getCollisionObjectArray();
- btCollisionObject *ob;
- btBroadphaseProxy* proxy;
-
- for (int i= 0; i < obarr.size(); i++) {
- ob= obarr[i];
- if (ob->getCollisionShape() == newShape) {
- proxy = ob->getBroadphaseHandle();
-
- if (proxy)
- dw->getPairCache()->cleanProxyFromPairs(proxy,dw->getDispatcher());
- }
+
+ btSoftBody *newSoftBody = GetSoftBody();
+ // set the user
+ newSoftBody->setUserPointer(this);
+ // add the new softbody
+ world->addSoftBody(newSoftBody);
}
-
+
return true;
}
@@ -673,6 +697,35 @@ CcdPhysicsController::~CcdPhysicsController()
}
}
+void CcdPhysicsController::SimulationTick(float timestep)
+{
+ btRigidBody *body = GetRigidBody();
+ if (!body || body->isStaticObject())
+ return;
+
+ // Clamp linear velocity
+ if (m_cci.m_clamp_vel_max > 0.0f || m_cci.m_clamp_vel_min > 0.0f) {
+ const btVector3 &linvel = body->getLinearVelocity();
+ btScalar len = linvel.length();
+
+ if (m_cci.m_clamp_vel_max > 0.0f && len > m_cci.m_clamp_vel_max)
+ body->setLinearVelocity(linvel * (m_cci.m_clamp_vel_max / len));
+ else if (m_cci.m_clamp_vel_min > 0.0f && !btFuzzyZero(len) && len < m_cci.m_clamp_vel_min)
+ body->setLinearVelocity(linvel * (m_cci.m_clamp_vel_min / len));
+ }
+
+ // Clamp angular velocity
+ if (m_cci.m_clamp_angvel_max > 0.0f || m_cci.m_clamp_angvel_min > 0.0f) {
+ const btVector3 &angvel = body->getAngularVelocity();
+ btScalar len = angvel.length();
+
+ if (m_cci.m_clamp_angvel_max > 0.0f && len > m_cci.m_clamp_angvel_max)
+ body->setAngularVelocity(angvel * (m_cci.m_clamp_angvel_max / len));
+ else if (m_cci.m_clamp_angvel_min > 0.0f && !btFuzzyZero(len) && len < m_cci.m_clamp_angvel_min)
+ body->setAngularVelocity(angvel * (m_cci.m_clamp_angvel_min / len));
+ }
+}
+
/**
* SynchronizeMotionStates ynchronizes dynas, kinematic and deformable entities (and do 'late binding')
@@ -708,19 +761,6 @@ bool CcdPhysicsController::SynchronizeMotionStates(float time)
if (body && !body->isStaticObject())
{
-
- if ((m_cci.m_clamp_vel_max>0.0) || (m_cci.m_clamp_vel_min>0.0))
- {
- const btVector3& linvel = body->getLinearVelocity();
- float len= linvel.length();
-
- if ((m_cci.m_clamp_vel_max>0.0) && (len > m_cci.m_clamp_vel_max))
- body->setLinearVelocity(linvel * (m_cci.m_clamp_vel_max / len));
-
- else if ((m_cci.m_clamp_vel_min>0.0) && btFuzzyZero(len)==0 && (len < m_cci.m_clamp_vel_min))
- body->setLinearVelocity(linvel * (m_cci.m_clamp_vel_min / len));
- }
-
const btTransform& xform = body->getCenterOfMassTransform();
const btMatrix3x3& worldOri = xform.getBasis();
const btVector3& worldPos = xform.getOrigin();
@@ -780,6 +820,9 @@ void CcdPhysicsController::PostProcessReplica(class PHY_IMotionState* motionsta
m_registerCount = 0;
m_collisionShape = NULL;
+ // Clear all old constraints.
+ m_ccdConstraintRefs.clear();
+
// always create a new shape to avoid scaling bug
if (m_shapeInfo)
{
@@ -822,36 +865,6 @@ void CcdPhysicsController::PostProcessReplica(class PHY_IMotionState* motionsta
m_cci.m_physicsEnv->AddCcdPhysicsController(this);
-/* SM_Object* dynaparent=0;
- SumoPhysicsController* sumoparentctrl = (SumoPhysicsController* )parentctrl;
-
- if (sumoparentctrl)
- {
- dynaparent = sumoparentctrl->GetSumoObject();
- }
-
- SM_Object* orgsumoobject = m_sumoObj;
-
-
- m_sumoObj = new SM_Object(
- orgsumoobject->getShapeHandle(),
- orgsumoobject->getMaterialProps(),
- orgsumoobject->getShapeProps(),
- dynaparent);
-
- m_sumoObj->setRigidBody(orgsumoobject->isRigidBody());
-
- m_sumoObj->setMargin(orgsumoobject->getMargin());
- m_sumoObj->setPosition(orgsumoobject->getPosition());
- m_sumoObj->setOrientation(orgsumoobject->getOrientation());
- //if it is a dyna, register for a callback
- m_sumoObj->registerCallback(*this);
-
- m_sumoScene->add(* (m_sumoObj));
- */
-
-
-
}
void CcdPhysicsController::SetPhysicsEnvironment(class PHY_IPhysicsEnvironment *env)
@@ -899,12 +912,6 @@ void CcdPhysicsController::SetCenterOfMassTransform(btTransform& xform)
{
m_object->setInterpolationWorldTransform(xform);
}
- if (body)
- {
- body->setInterpolationLinearVelocity(body->getLinearVelocity());
- body->setInterpolationAngularVelocity(body->getAngularVelocity());
- body->updateInertiaTensor();
- }
m_object->setWorldTransform(xform);
}
}
@@ -1054,15 +1061,35 @@ void CcdPhysicsController::ResolveCombinedVelocities(float linvelX,float linvel
{
}
+void CcdPhysicsController::RefreshCollisions()
+{
+ // the object is in an inactive layer so it's useless to update it and can cause problems
+ if (!GetPhysicsEnvironment()->IsActiveCcdPhysicsController(this))
+ return;
+
+ btSoftRigidDynamicsWorld *dw = GetPhysicsEnvironment()->GetDynamicsWorld();
+ btBroadphaseProxy *proxy = m_object->getBroadphaseHandle();
+ btDispatcher *dispatcher = dw->getDispatcher();
+ btOverlappingPairCache *pairCache = dw->getPairCache();
+
+ CleanPairCallback cleanPairs(proxy, pairCache, dispatcher);
+ pairCache->processAllOverlappingPairs(&cleanPairs, dispatcher);
+
+ // Forcibly recreate the physics object
+ btBroadphaseProxy* handle = m_object->getBroadphaseHandle();
+ GetPhysicsEnvironment()->UpdateCcdPhysicsController(this, GetMass(), m_object->getCollisionFlags(), handle->m_collisionFilterGroup, handle->m_collisionFilterMask);
+}
+
void CcdPhysicsController::SuspendDynamics(bool ghost)
{
btRigidBody *body = GetRigidBody();
- if (body && !m_suspended && !GetConstructionInfo().m_bSensor)
+ if (body && !m_suspended && !GetConstructionInfo().m_bSensor && GetPhysicsEnvironment()->IsActiveCcdPhysicsController(this))
{
btBroadphaseProxy* handle = body->getBroadphaseHandle();
m_savedCollisionFlags = body->getCollisionFlags();
m_savedMass = GetMass();
+ m_savedDyna = m_cci.m_bDyna;
m_savedCollisionFilterGroup = handle->m_collisionFilterGroup;
m_savedCollisionFilterMask = handle->m_collisionFilterMask;
m_suspended = true;
@@ -1071,13 +1098,14 @@ void CcdPhysicsController::SuspendDynamics(bool ghost)
btCollisionObject::CF_STATIC_OBJECT|((ghost)?btCollisionObject::CF_NO_CONTACT_RESPONSE:(m_savedCollisionFlags&btCollisionObject::CF_NO_CONTACT_RESPONSE)),
btBroadphaseProxy::StaticFilter,
btBroadphaseProxy::AllFilter ^ btBroadphaseProxy::StaticFilter);
+ m_cci.m_bDyna = false;
}
}
void CcdPhysicsController::RestoreDynamics()
{
btRigidBody *body = GetRigidBody();
- if (body && m_suspended)
+ if (body && m_suspended && GetPhysicsEnvironment()->IsActiveCcdPhysicsController(this))
{
// before make sure any position change that was done in this logic frame are accounted for
SetTransform();
@@ -1087,6 +1115,7 @@ void CcdPhysicsController::RestoreDynamics()
m_savedCollisionFilterGroup,
m_savedCollisionFilterMask);
body->activate();
+ m_cci.m_bDyna = m_savedDyna;
m_suspended = false;
}
}
@@ -1354,6 +1383,42 @@ void CcdPhysicsController::Jump()
void CcdPhysicsController::SetActive(bool active)
{
}
+
+float CcdPhysicsController::GetLinearDamping() const
+{
+ const btRigidBody* body = GetRigidBody();
+ if (body)
+ return body->getLinearDamping();
+ return 0;
+}
+
+float CcdPhysicsController::GetAngularDamping() const
+{
+ const btRigidBody* body = GetRigidBody();
+ if (body)
+ return body->getAngularDamping();
+ return 0;
+}
+
+void CcdPhysicsController::SetLinearDamping(float damping)
+{
+ SetDamping(damping, GetAngularDamping());
+}
+
+void CcdPhysicsController::SetAngularDamping(float damping)
+{
+ SetDamping(GetLinearDamping(), damping);
+}
+
+void CcdPhysicsController::SetDamping(float linear, float angular)
+{
+ btRigidBody* body = GetRigidBody();
+ if (!body) return;
+
+ body->setDamping(linear, angular);
+}
+
+
// reading out information from physics
MT_Vector3 CcdPhysicsController::GetLinearVelocity()
{
@@ -1479,8 +1544,7 @@ void CcdPhysicsController::AddCompoundChild(PHY_IPhysicsController* child)
const btCollisionShape* childShape = childBody->getCollisionShape();
if (!rootShape ||
!childShape ||
- rootShape->getShapeType() != COMPOUND_SHAPE_PROXYTYPE ||
- childShape->getShapeType() == COMPOUND_SHAPE_PROXYTYPE)
+ rootShape->getShapeType() != COMPOUND_SHAPE_PROXYTYPE)
return;
btCompoundShape* compoundShape = (btCompoundShape*)rootShape;
// compute relative transformation between parent and child
@@ -1530,7 +1594,7 @@ void CcdPhysicsController::AddCompoundChild(PHY_IPhysicsController* child)
// must update the broadphase cache,
GetPhysicsEnvironment()->RefreshCcdPhysicsController(this);
// remove the children
- GetPhysicsEnvironment()->DisableCcdPhysicsController(childCtrl);
+ GetPhysicsEnvironment()->RemoveCcdPhysicsController(childCtrl);
}
/* Reverse function of the above, it will remove a shape from a compound shape
@@ -1586,7 +1650,7 @@ void CcdPhysicsController::RemoveCompoundChild(PHY_IPhysicsController* child)
// must update the broadphase cache,
GetPhysicsEnvironment()->RefreshCcdPhysicsController(this);
// reactivate the children
- GetPhysicsEnvironment()->EnableCcdPhysicsController(childCtrl);
+ GetPhysicsEnvironment()->AddCcdPhysicsController(childCtrl);
}
PHY_IPhysicsController* CcdPhysicsController::GetReplica()
@@ -1646,33 +1710,50 @@ PHY_IPhysicsController* CcdPhysicsController::GetReplicaForSensors()
* 2) from_gameobj - creates the phys mesh from the DerivedMesh where possible, else the RAS_MeshObject
* 3) this - update the phys mesh from DerivedMesh or RAS_MeshObject
*
- * Most of the logic behind this is in shapeInfo->UpdateMesh(...)
+ * Most of the logic behind this is in m_shapeInfo->UpdateMesh(...)
*/
bool CcdPhysicsController::ReinstancePhysicsShape(KX_GameObject *from_gameobj, RAS_MeshObject *from_meshobj)
{
- CcdShapeConstructionInfo *shapeInfo;
-
- shapeInfo = this->GetShapeInfo();
-
- if (shapeInfo->m_shapeType != PHY_SHAPE_MESH/* || spc->GetSoftBody()*/)
+ if (m_shapeInfo->m_shapeType != PHY_SHAPE_MESH)
return false;
- this->DeleteControllerShape();
-
- if (from_gameobj==NULL && from_meshobj==NULL)
- from_gameobj = KX_GameObject::GetClientObject((KX_ClientObjectInfo*)this->GetNewClientInfo());
+ if (!from_gameobj && !from_meshobj)
+ from_gameobj = KX_GameObject::GetClientObject((KX_ClientObjectInfo*)GetNewClientInfo());
/* updates the arrays used for making the new bullet mesh */
- shapeInfo->UpdateMesh(from_gameobj, from_meshobj);
+ m_shapeInfo->UpdateMesh(from_gameobj, from_meshobj);
/* create the new bullet mesh */
- CcdConstructionInfo& cci = this->GetConstructionInfo();
- btCollisionShape* bm= shapeInfo->CreateBulletShape(cci.m_margin, cci.m_bGimpact, !cci.m_bSoft);
+ GetPhysicsEnvironment()->UpdateCcdPhysicsControllerShape(m_shapeInfo);
- this->ReplaceControllerShape(bm);
return true;
}
+void CcdPhysicsController::ReplicateConstraints(KX_GameObject *replica, std::vector<KX_GameObject*> constobj)
+{
+ if (replica->GetConstraints().size() == 0 || !replica->GetPhysicsController())
+ return;
+
+ PHY_IPhysicsEnvironment *physEnv = GetPhysicsEnvironment();
+
+ vector<bRigidBodyJointConstraint*> constraints = replica->GetConstraints();
+ vector<bRigidBodyJointConstraint*>::iterator consit;
+
+ /* Object could have some constraints, iterate over all of theme to ensure that every constraint is recreated. */
+ for (consit = constraints.begin(); consit != constraints.end(); ++consit) {
+ /* Try to find the constraint targets in the list of group objects. */
+ bRigidBodyJointConstraint *dat = (*consit);
+ vector<KX_GameObject*>::iterator memit;
+ for (memit = constobj.begin(); memit != constobj.end(); ++memit) {
+ KX_GameObject *member = (*memit);
+ /* If the group member is the actual target for the constraint. */
+ if (dat->tar->id.name + 2 == member->GetName() && member->GetPhysicsController())
+ physEnv->SetupObjectConstraints(replica, member, dat);
+ }
+ }
+
+}
+
///////////////////////////////////////////////////////////
///A small utility class, DefaultMotionState
///
@@ -1754,7 +1835,7 @@ CcdShapeConstructionInfo* CcdShapeConstructionInfo::FindMesh(RAS_MeshObject* mes
return NULL;
}
-bool CcdShapeConstructionInfo::SetMesh(RAS_MeshObject* meshobj, DerivedMesh* dm, bool polytope)
+bool CcdShapeConstructionInfo::SetMesh(RAS_MeshObject *meshobj, DerivedMesh *dm, bool polytope)
{
int numpolys, numverts;
@@ -1766,7 +1847,7 @@ bool CcdShapeConstructionInfo::SetMesh(RAS_MeshObject* meshobj, DerivedMesh* dm,
bool free_dm = false;
// No mesh object or mesh has no polys
- if (!meshobj || meshobj->HasColliderPolygon()==false) {
+ if (!meshobj || !meshobj->HasColliderPolygon()) {
m_vertexArray.clear();
m_polygonIndexArray.clear();
m_triFaceArray.clear();
@@ -1789,80 +1870,83 @@ bool CcdShapeConstructionInfo::SetMesh(RAS_MeshObject* meshobj, DerivedMesh* dm,
/* double lookup */
const int *index_mf_to_mpoly = (const int *)dm->getTessFaceDataArray(dm, CD_ORIGINDEX);
const int *index_mp_to_orig = (const int *)dm->getPolyDataArray(dm, CD_ORIGINDEX);
- if (index_mf_to_mpoly == NULL) {
+ if (!index_mf_to_mpoly) {
index_mp_to_orig = NULL;
}
m_shapeType = (polytope) ? PHY_SHAPE_POLYTOPE : PHY_SHAPE_MESH;
/* Convert blender geometry into bullet mesh, need these vars for mapping */
- vector<bool> vert_tag_array(numverts, false);
- unsigned int tot_bt_verts= 0;
+ std::vector<bool> vert_tag_array(numverts, false);
+ unsigned int tot_bt_verts = 0;
- if (polytope)
- {
+ if (polytope) {
// Tag verts we're using
- for (int p2=0; p2<numpolys; p2++)
- {
- MFace* mf = &mface[p2];
+ for (int p2 = 0; p2 < numpolys; p2++) {
+ MFace *mf = &mface[p2];
const int origi = index_mf_to_mpoly ? DM_origindex_mface_mpoly(index_mf_to_mpoly, index_mp_to_orig, p2) : p2;
- RAS_Polygon* poly = meshobj->GetPolygon(origi);
+ RAS_Polygon *poly = meshobj->GetPolygon(origi);
// only add polygons that have the collision flag set
- if (poly->IsCollider())
- {
- if (vert_tag_array[mf->v1] == false) {vert_tag_array[mf->v1] = true; tot_bt_verts++;}
- if (vert_tag_array[mf->v2] == false) {vert_tag_array[mf->v2] = true; tot_bt_verts++;}
- if (vert_tag_array[mf->v3] == false) {vert_tag_array[mf->v3] = true; tot_bt_verts++;}
- if (mf->v4 && vert_tag_array[mf->v4] == false) {vert_tag_array[mf->v4] = true; tot_bt_verts++;}
+ if (poly->IsCollider()) {
+ if (!vert_tag_array[mf->v1]) {
+ vert_tag_array[mf->v1] = true;
+ tot_bt_verts++;
+ }
+ if (!vert_tag_array[mf->v2]) {
+ vert_tag_array[mf->v2] = true;
+ tot_bt_verts++;
+ }
+ if (!vert_tag_array[mf->v3]) {
+ vert_tag_array[mf->v3] = true;
+ tot_bt_verts++;
+ }
+ if (mf->v4 && !vert_tag_array[mf->v4]) {
+ vert_tag_array[mf->v4] = true;
+ tot_bt_verts++;
+ }
}
}
-
+
/* Can happen with ngons */
if (!tot_bt_verts) {
goto cleanup_empty_mesh;
}
- m_vertexArray.resize(tot_bt_verts*3);
+ m_vertexArray.resize(tot_bt_verts * 3);
- btScalar *bt= &m_vertexArray[0];
+ btScalar *bt = &m_vertexArray[0];
- for (int p2=0; p2<numpolys; p2++)
- {
- MFace* mf = &mface[p2];
+ for (int p2 = 0; p2 < numpolys; p2++) {
+ MFace *mf = &mface[p2];
const int origi = index_mf_to_mpoly ? DM_origindex_mface_mpoly(index_mf_to_mpoly, index_mp_to_orig, p2) : p2;
- RAS_Polygon* poly= meshobj->GetPolygon(origi);
+ RAS_Polygon *poly = meshobj->GetPolygon(origi);
// only add polygons that have the collisionflag set
- if (poly->IsCollider())
- {
- if (vert_tag_array[mf->v1]==true)
- {
- const float* vtx = mvert[mf->v1].co;
+ if (poly->IsCollider()) {
+ if (vert_tag_array[mf->v1]) {
+ const float *vtx = mvert[mf->v1].co;
vert_tag_array[mf->v1] = false;
*bt++ = vtx[0];
*bt++ = vtx[1];
*bt++ = vtx[2];
}
- if (vert_tag_array[mf->v2]==true)
- {
- const float* vtx = mvert[mf->v2].co;
+ if (vert_tag_array[mf->v2]) {
+ const float *vtx = mvert[mf->v2].co;
vert_tag_array[mf->v2] = false;
*bt++ = vtx[0];
*bt++ = vtx[1];
*bt++ = vtx[2];
}
- if (vert_tag_array[mf->v3]==true)
- {
- const float* vtx = mvert[mf->v3].co;
+ if (vert_tag_array[mf->v3]) {
+ const float *vtx = mvert[mf->v3].co;
vert_tag_array[mf->v3] = false;
*bt++ = vtx[0];
*bt++ = vtx[1];
*bt++ = vtx[2];
}
- if (mf->v4 && vert_tag_array[mf->v4]==true)
- {
- const float* vtx = mvert[mf->v4].co;
+ if (mf->v4 && vert_tag_array[mf->v4]) {
+ const float *vtx = mvert[mf->v4].co;
vert_tag_array[mf->v4] = false;
*bt++ = vtx[0];
*bt++ = vtx[1];
@@ -1872,28 +1956,38 @@ bool CcdShapeConstructionInfo::SetMesh(RAS_MeshObject* meshobj, DerivedMesh* dm,
}
}
else {
- unsigned int tot_bt_tris= 0;
- vector<int> vert_remap_array(numverts, 0);
-
+ unsigned int tot_bt_tris = 0;
+ std::vector<int> vert_remap_array(numverts, 0);
+
// Tag verts we're using
- for (int p2=0; p2<numpolys; p2++)
- {
- MFace* mf = &mface[p2];
+ for (int p2 = 0; p2 < numpolys; p2++) {
+ MFace *mf = &mface[p2];
const int origi = index_mf_to_mpoly ? DM_origindex_mface_mpoly(index_mf_to_mpoly, index_mp_to_orig, p2) : p2;
- RAS_Polygon* poly= meshobj->GetPolygon(origi);
+ RAS_Polygon *poly = meshobj->GetPolygon(origi);
// only add polygons that have the collision flag set
- if (poly->IsCollider())
- {
- if (vert_tag_array[mf->v1]==false)
- {vert_tag_array[mf->v1] = true;vert_remap_array[mf->v1] = tot_bt_verts;tot_bt_verts++;}
- if (vert_tag_array[mf->v2]==false)
- {vert_tag_array[mf->v2] = true;vert_remap_array[mf->v2] = tot_bt_verts;tot_bt_verts++;}
- if (vert_tag_array[mf->v3]==false)
- {vert_tag_array[mf->v3] = true;vert_remap_array[mf->v3] = tot_bt_verts;tot_bt_verts++;}
- if (mf->v4 && vert_tag_array[mf->v4]==false)
- {vert_tag_array[mf->v4] = true;vert_remap_array[mf->v4] = tot_bt_verts;tot_bt_verts++;}
- tot_bt_tris += (mf->v4 ? 2:1); /* a quad or a tri */
+ if (poly->IsCollider()) {
+ if (!vert_tag_array[mf->v1]) {
+ vert_tag_array[mf->v1] = true;
+ vert_remap_array[mf->v1] = tot_bt_verts;
+ tot_bt_verts++;
+ }
+ if (!vert_tag_array[mf->v2]) {
+ vert_tag_array[mf->v2] = true;
+ vert_remap_array[mf->v2] = tot_bt_verts;
+ tot_bt_verts++;
+ }
+ if (!vert_tag_array[mf->v3]) {
+ vert_tag_array[mf->v3] = true;
+ vert_remap_array[mf->v3] = tot_bt_verts;
+ tot_bt_verts++;
+ }
+ if (mf->v4 && !vert_tag_array[mf->v4]) {
+ vert_tag_array[mf->v4] = true;
+ vert_remap_array[mf->v4] = tot_bt_verts;
+ tot_bt_verts++;
+ }
+ tot_bt_tris += (mf->v4 ? 2 : 1); /* a quad or a tri */
}
}
@@ -1902,43 +1996,39 @@ bool CcdShapeConstructionInfo::SetMesh(RAS_MeshObject* meshobj, DerivedMesh* dm,
goto cleanup_empty_mesh;
}
- m_vertexArray.resize(tot_bt_verts*3);
+ m_vertexArray.resize(tot_bt_verts * 3);
m_polygonIndexArray.resize(tot_bt_tris);
- m_triFaceArray.resize(tot_bt_tris*3);
- btScalar *bt= &m_vertexArray[0];
- int *poly_index_pt= &m_polygonIndexArray[0];
- int *tri_pt= &m_triFaceArray[0];
+ m_triFaceArray.resize(tot_bt_tris * 3);
+ btScalar *bt = &m_vertexArray[0];
+ int *poly_index_pt = &m_polygonIndexArray[0];
+ int *tri_pt = &m_triFaceArray[0];
UVco *uv_pt = NULL;
- if (tface)
- {
- m_triFaceUVcoArray.resize(tot_bt_tris*3);
+ if (tface) {
+ m_triFaceUVcoArray.resize(tot_bt_tris * 3);
uv_pt = &m_triFaceUVcoArray[0];
- }
- else
+ }
+ else
m_triFaceUVcoArray.clear();
- for (int p2=0; p2<numpolys; p2++)
- {
- MFace* mf = &mface[p2];
- MTFace* tf = (tface) ? &tface[p2] : NULL;
+ for (int p2 = 0; p2 < numpolys; p2++) {
+ MFace *mf = &mface[p2];
+ MTFace *tf = (tface) ? &tface[p2] : NULL;
const int origi = index_mf_to_mpoly ? DM_origindex_mface_mpoly(index_mf_to_mpoly, index_mp_to_orig, p2) : p2;
- RAS_Polygon* poly= meshobj->GetPolygon(origi);
+ RAS_Polygon *poly = meshobj->GetPolygon(origi);
// only add polygons that have the collisionflag set
- if (poly->IsCollider())
- {
- MVert *v1= &mvert[mf->v1];
- MVert *v2= &mvert[mf->v2];
- MVert *v3= &mvert[mf->v3];
+ if (poly->IsCollider()) {
+ MVert *v1 = &mvert[mf->v1];
+ MVert *v2 = &mvert[mf->v2];
+ MVert *v3 = &mvert[mf->v3];
// the face indices
tri_pt[0] = vert_remap_array[mf->v1];
tri_pt[1] = vert_remap_array[mf->v2];
tri_pt[2] = vert_remap_array[mf->v3];
- tri_pt= tri_pt+3;
- if (tf)
- {
+ tri_pt = tri_pt + 3;
+ if (tf) {
uv_pt[0].uv[0] = tf->uv[0][0];
uv_pt[0].uv[1] = tf->uv[0][1];
uv_pt[1].uv[0] = tf->uv[1][0];
@@ -1953,19 +2043,19 @@ bool CcdShapeConstructionInfo::SetMesh(RAS_MeshObject* meshobj, DerivedMesh* dm,
poly_index_pt++;
// the vertex location
- if (vert_tag_array[mf->v1]==true) { /* *** v1 *** */
+ if (vert_tag_array[mf->v1]) { /* *** v1 *** */
vert_tag_array[mf->v1] = false;
*bt++ = v1->co[0];
*bt++ = v1->co[1];
*bt++ = v1->co[2];
}
- if (vert_tag_array[mf->v2]==true) { /* *** v2 *** */
+ if (vert_tag_array[mf->v2]) { /* *** v2 *** */
vert_tag_array[mf->v2] = false;
*bt++ = v2->co[0];
*bt++ = v2->co[1];
*bt++ = v2->co[2];
}
- if (vert_tag_array[mf->v3]==true) { /* *** v3 *** */
+ if (vert_tag_array[mf->v3]) { /* *** v3 *** */
vert_tag_array[mf->v3] = false;
*bt++ = v3->co[0];
*bt++ = v3->co[1];
@@ -1974,12 +2064,12 @@ bool CcdShapeConstructionInfo::SetMesh(RAS_MeshObject* meshobj, DerivedMesh* dm,
if (mf->v4)
{
- MVert *v4= &mvert[mf->v4];
+ MVert *v4 = &mvert[mf->v4];
tri_pt[0] = vert_remap_array[mf->v1];
tri_pt[1] = vert_remap_array[mf->v3];
tri_pt[2] = vert_remap_array[mf->v4];
- tri_pt= tri_pt+3;
+ tri_pt = tri_pt + 3;
if (tf)
{
uv_pt[0].uv[0] = tf->uv[0][0];
@@ -1996,7 +2086,7 @@ bool CcdShapeConstructionInfo::SetMesh(RAS_MeshObject* meshobj, DerivedMesh* dm,
poly_index_pt++;
// the vertex location
- if (vert_tag_array[mf->v4] == true) { /* *** v4 *** */
+ if (vert_tag_array[mf->v4]) { /* *** v4 *** */
vert_tag_array[mf->v4] = false;
*bt++ = v4->co[0];
*bt++ = v4->co[1];
@@ -2010,27 +2100,27 @@ bool CcdShapeConstructionInfo::SetMesh(RAS_MeshObject* meshobj, DerivedMesh* dm,
/* If this ever gets confusing, print out an OBJ file for debugging */
#if 0
printf("# vert count %d\n", m_vertexArray.size());
- for (i=0; i<m_vertexArray.size(); i+=1) {
+ for (i = 0; i < m_vertexArray.size(); i += 1) {
printf("v %.6f %.6f %.6f\n", m_vertexArray[i].x(), m_vertexArray[i].y(), m_vertexArray[i].z());
}
printf("# face count %d\n", m_triFaceArray.size());
- for (i=0; i<m_triFaceArray.size(); i+=3) {
- printf("f %d %d %d\n", m_triFaceArray[i]+1, m_triFaceArray[i+1]+1, m_triFaceArray[i+2]+1);
+ for (i = 0; i < m_triFaceArray.size(); i += 3) {
+ printf("f %d %d %d\n", m_triFaceArray[i] + 1, m_triFaceArray[i + 1] + 1, m_triFaceArray[i + 2] + 1);
}
#endif
}
#if 0
- if (validpolys==false)
+ if (validpolys == false)
{
// should not happen
m_shapeType = PHY_SHAPE_NONE;
return false;
}
#endif
-
+
m_meshObject = meshobj;
if (free_dm) {
dm->release(dm);
@@ -2038,10 +2128,9 @@ bool CcdShapeConstructionInfo::SetMesh(RAS_MeshObject* meshobj, DerivedMesh* dm,
}
// sharing only on static mesh at present, if you change that, you must also change in FindMesh
- if (!polytope && !dm)
- {
+ if (!polytope && !dm) {
// triangle shape can be shared, store the mesh object in the map
- m_meshShapeMap.insert(std::pair<RAS_MeshObject*,CcdShapeConstructionInfo*>(meshobj,this));
+ m_meshShapeMap.insert(std::pair<RAS_MeshObject *, CcdShapeConstructionInfo *>(meshobj, this));
}
return true;
@@ -2064,51 +2153,50 @@ cleanup_empty_mesh:
/* Updates the arrays used by CreateBulletShape(),
* take care that recalcLocalAabb() runs after CreateBulletShape is called.
* */
-bool CcdShapeConstructionInfo::UpdateMesh(class KX_GameObject* gameobj, class RAS_MeshObject* meshobj)
+bool CcdShapeConstructionInfo::UpdateMesh(class KX_GameObject *gameobj, class RAS_MeshObject *meshobj)
{
int numpolys;
int numverts;
- unsigned int tot_bt_tris= 0;
- unsigned int tot_bt_verts= 0;
+ unsigned int tot_bt_tris = 0;
+ unsigned int tot_bt_verts = 0;
int i, j;
int v_orig;
/* Use for looping over verts in a face as a try or 2 tris */
- const int quad_verts[7]= {0,1,2, 0,2,3, -1};
- const int tri_verts[4]= {0,1,2, -1};
+ const int quad_verts[7] = {0, 1, 2, 0, 2, 3, -1};
+ const int tri_verts[4] = {0, 1, 2, -1};
const int *fv_pt;
- if (gameobj==NULL && meshobj==NULL)
+ if (!gameobj && !meshobj)
return false;
-
+
if (m_shapeType != PHY_SHAPE_MESH)
return false;
- RAS_Deformer *deformer= gameobj ? gameobj->GetDeformer():NULL;
- DerivedMesh* dm = NULL;
+ RAS_Deformer *deformer = gameobj ? gameobj->GetDeformer() : NULL;
+ DerivedMesh *dm = NULL;
if (deformer)
dm = deformer->GetPhysicsMesh();
-
+
/* get the mesh from the object if not defined */
- if (meshobj==NULL) {
-
+ if (!meshobj) {
/* modifier mesh */
if (dm)
- meshobj= deformer->GetRasMesh();
-
+ meshobj = deformer->GetRasMesh();
+
/* game object first mesh */
- if (meshobj==NULL) {
+ if (!meshobj) {
if (gameobj->GetMeshCount() > 0) {
- meshobj= gameobj->GetMesh(0);
+ meshobj = gameobj->GetMesh(0);
}
}
}
-
- if (dm && deformer->GetRasMesh() == meshobj)
- { /*
+
+ if (dm && deformer->GetRasMesh() == meshobj) {
+ /*
* Derived Mesh Update
*
* */
@@ -2120,41 +2208,38 @@ bool CcdShapeConstructionInfo::UpdateMesh(class KX_GameObject* gameobj, class RA
/* double lookup */
const int *index_mf_to_mpoly = (const int *)dm->getTessFaceDataArray(dm, CD_ORIGINDEX);
- const int *index_mp_to_orig = (const int *)dm->getPolyDataArray(dm, CD_ORIGINDEX);
- if (index_mf_to_mpoly == NULL) {
+ const int *index_mp_to_orig = (const int *)dm->getPolyDataArray(dm, CD_ORIGINDEX);
+ if (!index_mf_to_mpoly) {
index_mp_to_orig = NULL;
}
MFace *mf;
MVert *mv;
- int flen;
-
- if (CustomData_has_layer(&dm->faceData, CD_MTFACE))
- {
+ if (CustomData_has_layer(&dm->faceData, CD_MTFACE)) {
MTFace *tface = (MTFace *)dm->getTessFaceDataArray(dm, CD_MTFACE);
MTFace *tf;
- vector<bool> vert_tag_array(numverts, false);
- vector<int> vert_remap_array(numverts, 0);
+ std::vector<bool> vert_tag_array(numverts, false);
+ std::vector<int> vert_remap_array(numverts, 0);
+
+ for (mf = mface, tf = tface, i = 0; i < numpolys; mf++, tf++, i++) {
+ if (tf->mode & TF_DYNAMIC) {
+ int flen;
- for (mf= mface, tf= tface, i=0; i < numpolys; mf++, tf++, i++) {
- if (tf->mode & TF_DYNAMIC)
- {
if (mf->v4) {
- tot_bt_tris+= 2;
- flen= 4;
- } else {
+ tot_bt_tris += 2;
+ flen = 4;
+ }
+ else {
tot_bt_tris++;
- flen= 3;
+ flen = 3;
}
- for (j=0; j<flen; j++)
- {
+ for (j = 0; j < flen; j++) {
v_orig = (*(&mf->v1 + j));
- if (vert_tag_array[v_orig]==false)
- {
+ if (!vert_tag_array[v_orig]) {
vert_tag_array[v_orig] = true;
vert_remap_array[v_orig] = tot_bt_verts;
tot_bt_verts++;
@@ -2163,42 +2248,38 @@ bool CcdShapeConstructionInfo::UpdateMesh(class KX_GameObject* gameobj, class RA
}
}
- m_vertexArray.resize(tot_bt_verts*3);
- btScalar *bt= &m_vertexArray[0];
+ m_vertexArray.resize(tot_bt_verts * 3);
+ btScalar *bt = &m_vertexArray[0];
- m_triFaceArray.resize(tot_bt_tris*3);
- int *tri_pt= &m_triFaceArray[0];
+ m_triFaceArray.resize(tot_bt_tris * 3);
+ int *tri_pt = &m_triFaceArray[0];
- m_triFaceUVcoArray.resize(tot_bt_tris*3);
- UVco *uv_pt= &m_triFaceUVcoArray[0];
+ m_triFaceUVcoArray.resize(tot_bt_tris * 3);
+ UVco *uv_pt = &m_triFaceUVcoArray[0];
m_polygonIndexArray.resize(tot_bt_tris);
- int *poly_index_pt= &m_polygonIndexArray[0];
+ int *poly_index_pt = &m_polygonIndexArray[0];
- for (mf= mface, tf= tface, i=0; i < numpolys; mf++, tf++, i++)
- {
- if (tf->mode & TF_DYNAMIC)
- {
+ for (mf = mface, tf = tface, i = 0; i < numpolys; mf++, tf++, i++) {
+ if (tf->mode & TF_DYNAMIC) {
int origi = index_mf_to_mpoly ? DM_origindex_mface_mpoly(index_mf_to_mpoly, index_mp_to_orig, i) : i;
if (mf->v4) {
- fv_pt= quad_verts;
+ fv_pt = quad_verts;
*poly_index_pt++ = origi;
*poly_index_pt++ = origi;
- flen= 4;
- } else {
- fv_pt= tri_verts;
+ }
+ else {
+ fv_pt = tri_verts;
*poly_index_pt++ = origi;
- flen= 3;
}
- for (; *fv_pt > -1; fv_pt++)
- {
+ for (; *fv_pt > -1; fv_pt++) {
v_orig = (*(&mf->v1 + (*fv_pt)));
if (vert_tag_array[v_orig])
{
- mv= mvert + v_orig;
+ mv = mvert + v_orig;
*bt++ = mv->co[0];
*bt++ = mv->co[1];
*bt++ = mv->co[2];
@@ -2216,37 +2297,37 @@ bool CcdShapeConstructionInfo::UpdateMesh(class KX_GameObject* gameobj, class RA
else {
/* no need for a vertex mapping. simple/fast */
- tot_bt_verts= numverts;
+ tot_bt_verts = numverts;
- for (mf= mface, i=0; i < numpolys; mf++, i++) {
- tot_bt_tris += (mf->v4 ? 2:1);
+ for (mf = mface, i = 0; i < numpolys; mf++, i++) {
+ tot_bt_tris += (mf->v4 ? 2 : 1);
}
- m_vertexArray.resize(tot_bt_verts*3);
- btScalar *bt= &m_vertexArray[0];
+ m_vertexArray.resize(tot_bt_verts * 3);
+ btScalar *bt = &m_vertexArray[0];
- m_triFaceArray.resize(tot_bt_tris*3);
- int *tri_pt= &m_triFaceArray[0];
+ m_triFaceArray.resize(tot_bt_tris * 3);
+ int *tri_pt = &m_triFaceArray[0];
m_polygonIndexArray.resize(tot_bt_tris);
- int *poly_index_pt= &m_polygonIndexArray[0];
+ int *poly_index_pt = &m_polygonIndexArray[0];
m_triFaceUVcoArray.clear();
- for (mv= mvert, i=0; i < numverts; mv++, i++) {
+ for (mv = mvert, i = 0; i < numverts; mv++, i++) {
*bt++ = mv->co[0]; *bt++ = mv->co[1]; *bt++ = mv->co[2];
}
- for (mf= mface, i=0; i < numpolys; mf++, i++) {
+ for (mf = mface, i = 0; i < numpolys; mf++, i++) {
int origi = index_mf_to_mpoly ? DM_origindex_mface_mpoly(index_mf_to_mpoly, index_mp_to_orig, i) : i;
if (mf->v4) {
- fv_pt= quad_verts;
+ fv_pt = quad_verts;
*poly_index_pt++ = origi;
*poly_index_pt++ = origi;
}
else {
- fv_pt= tri_verts;
+ fv_pt = tri_verts;
*poly_index_pt++ = origi;
}
@@ -2255,51 +2336,46 @@ bool CcdShapeConstructionInfo::UpdateMesh(class KX_GameObject* gameobj, class RA
}
}
}
- else { /*
- * RAS Mesh Update
- *
- * */
-
+ else { /*
+ * RAS Mesh Update
+ *
+ * */
/* Note!, gameobj can be NULL here */
/* transverts are only used for deformed RAS_Meshes, the RAS_TexVert data
* is too hard to get at, see below for details */
- float (*transverts)[3] = NULL;
- int transverts_tot= 0; /* with deformed meshes - should always be greater then the max orginal index, or we get crashes */
+ float(*transverts)[3] = NULL;
+ int transverts_tot = 0; /* with deformed meshes - should always be greater than the max orginal index, or we get crashes */
if (deformer) {
/* map locations from the deformed array
*
* Could call deformer->Update(); but rely on redraw updating.
* */
- transverts= deformer->GetTransVerts(&transverts_tot);
+ transverts = deformer->GetTransVerts(&transverts_tot);
}
// Tag verts we're using
- numpolys= meshobj->NumPolygons();
- numverts= meshobj->m_sharedvertex_map.size();
+ numpolys = meshobj->NumPolygons();
+ numverts = meshobj->m_sharedvertex_map.size();
const float *xyz;
- vector<bool> vert_tag_array(numverts, false);
- vector<int> vert_remap_array(numverts, 0);
+ std::vector<bool> vert_tag_array(numverts, false);
+ std::vector<int> vert_remap_array(numverts, 0);
- for (int p=0; p<numpolys; p++)
- {
- RAS_Polygon* poly= meshobj->GetPolygon(p);
- if (poly->IsCollider())
- {
- for (i=0; i < poly->VertexCount(); i++)
- {
- v_orig= poly->GetVertex(i)->getOrigIndex();
- if (vert_tag_array[v_orig]==false)
- {
+ for (int p = 0; p < numpolys; p++) {
+ RAS_Polygon *poly = meshobj->GetPolygon(p);
+ if (poly->IsCollider()) {
+ for (i = 0; i < poly->VertexCount(); i++) {
+ v_orig = poly->GetVertex(i)->getOrigIndex();
+ if (!vert_tag_array[v_orig]) {
vert_tag_array[v_orig] = true;
vert_remap_array[v_orig] = tot_bt_verts;
tot_bt_verts++;
}
}
- tot_bt_tris += (poly->VertexCount()==4 ? 2:1);
+ tot_bt_tris += (poly->VertexCount() == 4 ? 2 : 1);
}
}
@@ -2307,32 +2383,29 @@ bool CcdShapeConstructionInfo::UpdateMesh(class KX_GameObject* gameobj, class RA
if (tot_bt_tris == 0 || tot_bt_verts == 0)
return false;
- m_vertexArray.resize(tot_bt_verts*3);
- btScalar *bt= &m_vertexArray[0];
+ m_vertexArray.resize(tot_bt_verts * 3);
+ btScalar *bt = &m_vertexArray[0];
- m_triFaceArray.resize(tot_bt_tris*3);
- int *tri_pt= &m_triFaceArray[0];
+ m_triFaceArray.resize(tot_bt_tris * 3);
+ int *tri_pt = &m_triFaceArray[0];
/* cant be used for anything useful in this case, since we don't rely on the original mesh
* will just be an array like pythons range(tot_bt_tris) */
m_polygonIndexArray.resize(tot_bt_tris);
- for (int p=0; p<numpolys; p++)
- {
- RAS_Polygon* poly= meshobj->GetPolygon(p);
+ int p = 0;
+ int t = 0;
+ while (t < tot_bt_tris) {
+ RAS_Polygon *poly = meshobj->GetPolygon(p);
- if (poly->IsCollider())
- {
+ if (poly->IsCollider()) {
/* quad or tri loop */
- fv_pt= (poly->VertexCount()==3 ? tri_verts:quad_verts);
-
- for (; *fv_pt > -1; fv_pt++)
- {
- v_orig= poly->GetVertex(*fv_pt)->getOrigIndex();
+ fv_pt = (poly->VertexCount() == 3 ? tri_verts : quad_verts);
- if (vert_tag_array[v_orig])
- {
+ for (; *fv_pt > -1; fv_pt++) {
+ v_orig = poly->GetVertex(*fv_pt)->getOrigIndex();
+ if (vert_tag_array[v_orig]) {
if (transverts) {
/* deformed mesh, using RAS_TexVert locations would be too troublesome
* because they are use the gameob as a hash in the material slot */
@@ -2342,55 +2415,60 @@ bool CcdShapeConstructionInfo::UpdateMesh(class KX_GameObject* gameobj, class RA
}
else {
/* static mesh python may have modified */
- xyz= meshobj->GetVertexLocation( v_orig );
+ xyz = meshobj->GetVertexLocation(v_orig);
*bt++ = xyz[0];
*bt++ = xyz[1];
*bt++ = xyz[2];
}
-
vert_tag_array[v_orig] = false;
}
-
*tri_pt++ = vert_remap_array[v_orig];
}
}
-
- m_polygonIndexArray[p] = p; /* dumb counting */
+ // first triangle
+ m_polygonIndexArray[t] = p;
+
+ // if the poly is a quad we transform it in two triangles
+ if (poly->VertexCount() == 4) {
+ t++;
+ // second triangle
+ m_polygonIndexArray[t] = p;
+ }
+ t++;
+ p++;
}
}
-
+
#if 0
/* needs #include <cstdio> */
printf("# vert count %d\n", m_vertexArray.size());
- for (int i=0; i<m_vertexArray.size(); i+=3) {
- printf("v %.6f %.6f %.6f\n", m_vertexArray[i], m_vertexArray[i+1], m_vertexArray[i+2]);
+ for (int i = 0; i < m_vertexArray.size(); i += 3) {
+ printf("v %.6f %.6f %.6f\n", m_vertexArray[i], m_vertexArray[i + 1], m_vertexArray[i + 2]);
}
printf("# face count %d\n", m_triFaceArray.size());
- for (int i=0; i<m_triFaceArray.size(); i+=3) {
- printf("f %d %d %d\n", m_triFaceArray[i]+1, m_triFaceArray[i+1]+1, m_triFaceArray[i+2]+1);
+ for (int i = 0; i < m_triFaceArray.size(); i += 3) {
+ printf("f %d %d %d\n", m_triFaceArray[i] + 1, m_triFaceArray[i + 1] + 1, m_triFaceArray[i + 2] + 1);
}
#endif
- /* force recreation of the m_unscaledShape.
+ /* force recreation of the m_triangleIndexVertexArray.
* If this has multiple users we cant delete */
- if (m_unscaledShape) {
- // don't free now so it can re-allocate under the same location and not break pointers.
- // DeleteBulletShape(m_unscaledShape);
- m_forceReInstance= true;
+ if (m_triangleIndexVertexArray) {
+ m_forceReInstance = true;
}
// Make sure to also replace the mesh in the shape map! Otherwise we leave dangling references when we free.
// Note, this whole business could cause issues with shared meshes. If we update one mesh, do we replace
// them all?
- std::map<RAS_MeshObject*,CcdShapeConstructionInfo*>::iterator mit = m_meshShapeMap.find(m_meshObject);
+ std::map<RAS_MeshObject *, CcdShapeConstructionInfo *>::iterator mit = m_meshShapeMap.find(m_meshObject);
if (mit != m_meshShapeMap.end()) {
m_meshShapeMap.erase(mit);
m_meshShapeMap[meshobj] = this;
}
- m_meshObject= meshobj;
-
+ m_meshObject = meshobj;
+
if (dm) {
dm->needsFree = 1;
dm->release(dm);
@@ -2398,8 +2476,6 @@ bool CcdShapeConstructionInfo::UpdateMesh(class KX_GameObject* gameobj, class RA
return true;
}
-
-
bool CcdShapeConstructionInfo::SetProxy(CcdShapeConstructionInfo* shapeInfo)
{
if (shapeInfo == NULL)
@@ -2462,74 +2538,61 @@ btCollisionShape* CcdShapeConstructionInfo::CreateBulletShape(btScalar margin, b
// 9 multiplications/additions and one function call for each triangle that passes the mid phase filtering
// One possible optimization is to use directly the btBvhTriangleMeshShape when the scale is 1,1,1
// and btScaledBvhTriangleMeshShape otherwise.
- if (useGimpact)
- {
- btTriangleIndexVertexArray* indexVertexArrays = new btTriangleIndexVertexArray(
+ if (useGimpact) {
+ if (!m_triangleIndexVertexArray || m_forceReInstance) {
+ if (m_triangleIndexVertexArray)
+ delete m_triangleIndexVertexArray;
+
+ m_triangleIndexVertexArray = new btTriangleIndexVertexArray(
m_polygonIndexArray.size(),
- &m_triFaceArray[0],
- 3*sizeof(int),
- m_vertexArray.size()/3,
+ m_triFaceArray.data(),
+ 3 * sizeof(int),
+ m_vertexArray.size() / 3,
&m_vertexArray[0],
- 3*sizeof(btScalar)
- );
- btGImpactMeshShape* gimpactShape = new btGImpactMeshShape(indexVertexArrays);
- gimpactShape->setMargin(margin);
- gimpactShape->updateBound();
- collisionShape = gimpactShape;
-
-
- } else
- {
- if (!m_unscaledShape || m_forceReInstance)
- {
-
- btTriangleIndexVertexArray* indexVertexArrays = 0;
+ 3 * sizeof(btScalar));
+ m_forceReInstance = false;
+ }
+ btGImpactMeshShape *gimpactShape = new btGImpactMeshShape(m_triangleIndexVertexArray);
+ gimpactShape->setMargin(margin);
+ gimpactShape->updateBound();
+ collisionShape = gimpactShape;
+ }
+ else {
+ if (!m_triangleIndexVertexArray || m_forceReInstance) {
///enable welding, only for the objects that need it (such as soft bodies)
- if (0.f != m_weldingThreshold1)
- {
- btTriangleMesh* collisionMeshData = new btTriangleMesh(true,false);
+ if (0.0f != m_weldingThreshold1) {
+ btTriangleMesh *collisionMeshData = new btTriangleMesh(true, false);
collisionMeshData->m_weldingThreshold = m_weldingThreshold1;
- bool removeDuplicateVertices=true;
+ bool removeDuplicateVertices = true;
// m_vertexArray not in multiple of 3 anymore, use m_triFaceArray
- for (unsigned int i=0; i<m_triFaceArray.size(); i+=3) {
- btScalar *bt = &m_vertexArray[3*m_triFaceArray[i]];
+ for (unsigned int i = 0; i < m_triFaceArray.size(); i += 3) {
+ btScalar *bt = &m_vertexArray[3 * m_triFaceArray[i]];
btVector3 v1(bt[0], bt[1], bt[2]);
- bt = &m_vertexArray[3*m_triFaceArray[i+1]];
+ bt = &m_vertexArray[3 * m_triFaceArray[i + 1]];
btVector3 v2(bt[0], bt[1], bt[2]);
- bt = &m_vertexArray[3*m_triFaceArray[i+2]];
+ bt = &m_vertexArray[3 * m_triFaceArray[i + 2]];
btVector3 v3(bt[0], bt[1], bt[2]);
collisionMeshData->addTriangle(v1, v2, v3, removeDuplicateVertices);
}
- indexVertexArrays = collisionMeshData;
-
- } else
- {
- indexVertexArrays = new btTriangleIndexVertexArray(
+ m_triangleIndexVertexArray = collisionMeshData;
+ }
+ else {
+ m_triangleIndexVertexArray = new btTriangleIndexVertexArray(
m_polygonIndexArray.size(),
- &m_triFaceArray[0],
- 3*sizeof(int),
- m_vertexArray.size()/3,
+ m_triFaceArray.data(),
+ 3 * sizeof(int),
+ m_vertexArray.size() / 3,
&m_vertexArray[0],
- 3*sizeof(btScalar));
+ 3 * sizeof(btScalar));
}
-
- // this shape will be shared and not deleted until shapeInfo is deleted
-
- // for UpdateMesh, reuse the last memory location so instancing wont crash.
- if (m_unscaledShape) {
- DeleteBulletShape(m_unscaledShape, false);
- m_unscaledShape->~btBvhTriangleMeshShape();
- m_unscaledShape = new(m_unscaledShape) btBvhTriangleMeshShape( indexVertexArrays, true, useBvh );
- } else {
- m_unscaledShape = new btBvhTriangleMeshShape( indexVertexArrays, true, useBvh );
- }
- m_forceReInstance= false;
- } else if (useBvh && m_unscaledShape->getOptimizedBvh() == NULL) {
- // the existing unscaledShape was not build with Bvh, do it now
- m_unscaledShape->buildOptimizedBvh();
+
+ m_forceReInstance = false;
}
- collisionShape = new btScaledBvhTriangleMeshShape(m_unscaledShape, btVector3(1.0f,1.0f,1.0f));
+
+ btBvhTriangleMeshShape *unscaledShape = new btBvhTriangleMeshShape(m_triangleIndexVertexArray, true, useBvh);
+ unscaledShape->setMargin(margin);
+ collisionShape = new btScaledBvhTriangleMeshShape(unscaledShape, btVector3(1.0f, 1.0f, 1.0f));
collisionShape->setMargin(margin);
}
break;
@@ -2571,10 +2634,9 @@ CcdShapeConstructionInfo::~CcdShapeConstructionInfo()
(*sit)->Release();
}
m_shapeArray.clear();
- if (m_unscaledShape)
- {
- DeleteBulletShape(m_unscaledShape, true);
- }
+
+ if (m_triangleIndexVertexArray)
+ delete m_triangleIndexVertexArray;
m_vertexArray.clear();
if (m_shapeType == PHY_SHAPE_MESH && m_meshObject != NULL)
{
diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsController.h b/source/gameengine/Physics/Bullet/CcdPhysicsController.h
index 4d0d96e07c6..c49ae8d20e1 100644
--- a/source/gameengine/Physics/Bullet/CcdPhysicsController.h
+++ b/source/gameengine/Physics/Bullet/CcdPhysicsController.h
@@ -79,7 +79,7 @@ public:
m_userData(NULL),
m_refCount(1),
m_meshObject(NULL),
- m_unscaledShape(NULL),
+ m_triangleIndexVertexArray(NULL),
m_forceReInstance(false),
m_weldingThreshold1(0.f),
m_shapeProxy(NULL)
@@ -110,10 +110,11 @@ public:
void AddShape(CcdShapeConstructionInfo* shapeInfo);
- btTriangleMeshShape* GetMeshShape(void)
+ btStridingMeshInterface *GetMeshInterface()
{
- return (m_unscaledShape);
+ return m_triangleIndexVertexArray;
}
+
CcdShapeConstructionInfo* GetChildShape(int i)
{
if (i < 0 || i >= (int)m_shapeArray.size())
@@ -195,8 +196,8 @@ protected:
int m_refCount; // this class is shared between replicas
// keep track of users so that we can release it
RAS_MeshObject* m_meshObject; // Keep a pointer to the original mesh
- btBvhTriangleMeshShape* m_unscaledShape;// holds the shared unscale BVH mesh shape,
- // the actual shape is of type btScaledBvhTriangleMeshShape
+ // The list of vertexes and indexes for the triangle mesh, shared between Bullet shape.
+ btTriangleIndexVertexArray *m_triangleIndexVertexArray;
std::vector<CcdShapeConstructionInfo*> m_shapeArray; // for compound shapes
bool m_forceReInstance; //use gimpact for concave dynamic/moving collision detection
float m_weldingThreshold1; //welding closeby vertices together can improve softbody stability etc.
@@ -235,6 +236,8 @@ struct CcdConstructionInfo
m_mass(0.f),
m_clamp_vel_min(-1.f),
m_clamp_vel_max(-1.f),
+ m_clamp_angvel_min(0.0f),
+ m_clamp_angvel_max(0.0f),
m_restitution(0.1f),
m_friction(0.5f),
m_linearDamping(0.1f),
@@ -301,6 +304,8 @@ struct CcdConstructionInfo
btScalar m_mass;
btScalar m_clamp_vel_min;
btScalar m_clamp_vel_max;
+ btScalar m_clamp_angvel_min; // Minimum angular velocity, in radians/sec.
+ btScalar m_clamp_angvel_max; // Maximum angular velocity, in radians/sec.
btScalar m_restitution;
btScalar m_friction;
btScalar m_linearDamping;
@@ -447,6 +452,23 @@ public:
#endif
};
+class CleanPairCallback : public btOverlapCallback
+{
+ btBroadphaseProxy *m_cleanProxy;
+ btOverlappingPairCache *m_pairCache;
+ btDispatcher *m_dispatcher;
+
+public:
+ CleanPairCallback(btBroadphaseProxy *cleanProxy, btOverlappingPairCache *pairCache, btDispatcher *dispatcher)
+ :m_cleanProxy(cleanProxy),
+ m_pairCache(pairCache),
+ m_dispatcher(dispatcher)
+ {
+ }
+
+ virtual bool processOverlap(btBroadphasePair &pair);
+};
+
///CcdPhysicsController is a physics object that supports continuous collision detection and time of impact based physics resolution.
class CcdPhysicsController : public PHY_IPhysicsController
{
@@ -461,6 +483,7 @@ protected:
class CcdShapeConstructionInfo* m_shapeInfo;
btCollisionShape* m_bulletChildShape;
+ btAlignedObjectArray<btTypedConstraint*> m_ccdConstraintRefs; // keep track of typed constraints referencing this rigid body
friend class CcdPhysicsEnvironment; // needed when updating the controller
//some book keeping for replication
@@ -480,6 +503,7 @@ protected:
short m_savedCollisionFilterGroup;
short m_savedCollisionFilterMask;
MT_Scalar m_savedMass;
+ bool m_savedDyna;
bool m_suspended;
@@ -496,6 +520,16 @@ protected:
return (--m_registerCount == 0) ? true : false;
}
+ bool Registered() const
+ {
+ return (m_registerCount != 0);
+ }
+
+ void addCcdConstraintRef(btTypedConstraint* c);
+ void removeCcdConstraintRef(btTypedConstraint* c);
+ btTypedConstraint* getCcdConstraintRef(int index);
+ int getNumCcdConstraintRefs() const;
+
void SetWorldOrientation(const btMatrix3x3& mat);
void ForceWorldTransform(const btMatrix3x3& mat, const btVector3& pos);
@@ -506,7 +540,15 @@ protected:
CcdPhysicsController (const CcdConstructionInfo& ci);
+ /**
+ * Delete the current Bullet shape used in the rigid body.
+ */
bool DeleteControllerShape();
+
+ /**
+ * Delete the old Bullet shape and set the new Bullet shape : newShape
+ * \param newShape The new Bullet shape to set, if is NULL we create a new Bullet shape
+ */
bool ReplaceControllerShape(btCollisionShape *newShape);
virtual ~CcdPhysicsController();
@@ -522,6 +564,7 @@ protected:
btRigidBody* GetRigidBody();
+ const btRigidBody* GetRigidBody() const;
btCollisionObject* GetCollisionObject();
btSoftBody* GetSoftBody();
btKinematicCharacterController* GetCharacterController();
@@ -540,6 +583,13 @@ protected:
* SynchronizeMotionStates ynchronizes dynas, kinematic and deformable entities (and do 'late binding')
*/
virtual bool SynchronizeMotionStates(float time);
+
+ /**
+ * Called for every physics simulation step. Use this method for
+ * things like limiting linear and angular velocity.
+ */
+ void SimulationTick(float timestep);
+
/**
* WriteMotionStateToDynamics ynchronizes dynas, kinematic and deformable entities (and do 'late binding')
*/
@@ -573,6 +623,12 @@ protected:
virtual void Jump();
virtual void SetActive(bool active);
+ virtual float GetLinearDamping() const;
+ virtual float GetAngularDamping() const;
+ virtual void SetLinearDamping(float damping);
+ virtual void SetAngularDamping(float damping);
+ virtual void SetDamping(float linear, float angular);
+
// reading out information from physics
virtual MT_Vector3 GetLinearVelocity();
virtual MT_Vector3 GetAngularVelocity();
@@ -584,7 +640,7 @@ protected:
virtual void ResolveCombinedVelocities(float linvelX,float linvelY,float linvelZ,float angVelX,float angVelY,float angVelZ);
-
+ virtual void RefreshCollisions();
virtual void SuspendDynamics(bool ghost);
virtual void RestoreDynamics();
@@ -612,8 +668,12 @@ protected:
virtual void CalcXform() {}
virtual void SetMargin(float margin)
{
- if (m_collisionShape)
- m_collisionShape->setMargin(btScalar(margin));
+ if (m_collisionShape) {
+ m_collisionShape->setMargin(margin);
+ // if the shape use a unscaled shape we have also to set the correct margin in it
+ if (m_collisionShape->getShapeType() == SCALED_TRIANGLE_MESH_SHAPE_PROXYTYPE)
+ ((btScaledBvhTriangleMeshShape *)m_collisionShape)->getChildShape()->setMargin(margin);
+ }
}
virtual float GetMargin() const
{
@@ -652,6 +712,23 @@ protected:
return m_cci.m_clamp_vel_max;
}
+ virtual void SetAngularVelocityMin(float val)
+ {
+ m_cci.m_clamp_angvel_min = val;
+ }
+ virtual float GetAngularVelocityMin() const
+ {
+ return m_cci.m_clamp_angvel_min;
+ }
+ virtual void SetAngularVelocityMax(float val)
+ {
+ m_cci.m_clamp_angvel_max = val;
+ }
+ virtual float GetAngularVelocityMax() const
+ {
+ return m_cci.m_clamp_angvel_max;
+ }
+
bool WantsSleeping();
void UpdateDeactivation(float timeStep);
@@ -698,6 +775,11 @@ protected:
return GetConstructionInfo().m_bDyna;
}
+ virtual bool IsSuspended() const
+ {
+ return m_suspended;
+ }
+
virtual bool IsCompound()
{
return GetConstructionInfo().m_shapeInfo->m_shapeType == PHY_SHAPE_COMPOUND;
@@ -705,6 +787,9 @@ protected:
virtual bool ReinstancePhysicsShape(KX_GameObject *from_gameobj, RAS_MeshObject* from_meshobj);
+ /* Method to replicate rigid body joint contraints for group instances. */
+ virtual void ReplicateConstraints(KX_GameObject *gameobj, std::vector<KX_GameObject*> constobj);
+
#ifdef WITH_CXX_GUARDEDALLOC
MEM_CXX_CLASS_ALLOC_FUNCS("GE:CcdPhysicsController")
#endif
diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp
index e17d4402556..eec579158cc 100644
--- a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp
+++ b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp
@@ -174,26 +174,27 @@ public:
virtual void GetWheelPosition(int wheelIndex,float& posX,float& posY,float& posZ) const
{
- btTransform trans = m_vehicle->getWheelTransformWS(wheelIndex);
- posX = trans.getOrigin().x();
- posY = trans.getOrigin().y();
- posZ = trans.getOrigin().z();
+ if ((wheelIndex>=0) && (wheelIndex< m_vehicle->getNumWheels()))
+ {
+ btVector3 origin = m_vehicle->getWheelTransformWS(wheelIndex).getOrigin();
+
+ posX = origin.x();
+ posY = origin.y();
+ posZ = origin.z();
+ }
}
+
virtual void GetWheelOrientationQuaternion(int wheelIndex,float& quatX,float& quatY,float& quatZ,float& quatW) const
{
- btTransform trans = m_vehicle->getWheelTransformWS(wheelIndex);
- btQuaternion quat = trans.getRotation();
- btMatrix3x3 orn2(quat);
-
- quatX = trans.getRotation().x();
- quatY = trans.getRotation().y();
- quatZ = trans.getRotation().z();
- quatW = trans.getRotation()[3];
-
-
- //printf("test");
-
+ if ((wheelIndex>=0) && (wheelIndex< m_vehicle->getNumWheels()))
+ {
+ btQuaternion quat = m_vehicle->getWheelTransformWS(wheelIndex).getRotation();
+ quatX = quat.x();
+ quatY = quat.y();
+ quatZ = quat.z();
+ quatW = quat.w();
+ }
}
virtual float GetWheelRotation(int wheelIndex) const
@@ -205,8 +206,8 @@ public:
btWheelInfo& info = m_vehicle->getWheelInfo(wheelIndex);
rotation = info.m_rotation;
}
- return rotation;
+ return rotation;
}
@@ -223,12 +224,16 @@ public:
virtual void SetSteeringValue(float steering,int wheelIndex)
{
- m_vehicle->setSteeringValue(steering,wheelIndex);
+ if ((wheelIndex>=0) && (wheelIndex< m_vehicle->getNumWheels())) {
+ m_vehicle->setSteeringValue(steering,wheelIndex);
+ }
}
virtual void ApplyEngineForce(float force,int wheelIndex)
{
- m_vehicle->applyEngineForce(force,wheelIndex);
+ if ((wheelIndex>=0) && (wheelIndex< m_vehicle->getNumWheels())) {
+ m_vehicle->applyEngineForce(force,wheelIndex);
+ }
}
virtual void ApplyBraking(float braking,int wheelIndex)
@@ -405,6 +410,10 @@ m_ccdMode(0),
m_solverType(-1),
m_profileTimings(0),
m_enableSatCollisionDetection(false),
+m_deactivationTime(2.0f),
+m_linearDeactivationThreshold(0.8f),
+m_angularDeactivationThreshold(1.0f),
+m_contactBreakingThreshold(0.02f),
m_solver(NULL),
m_ownPairCache(NULL),
m_filterCallback(NULL),
@@ -447,6 +456,7 @@ m_scalingPropagated(false)
SetSolverType(1);//issues with quickstep and memory allocations
// m_dynamicsWorld = new btDiscreteDynamicsWorld(dispatcher,m_broadphase,m_solver,m_collisionConfiguration);
m_dynamicsWorld = new btSoftRigidDynamicsWorld(dispatcher,m_broadphase,m_solver,m_collisionConfiguration);
+ m_dynamicsWorld->setInternalTickCallback(&CcdPhysicsEnvironment::StaticSimulationSubtickCallback, this);
//m_dynamicsWorld->getSolverInfo().m_linearSlop = 0.01f;
//m_dynamicsWorld->getSolverInfo().m_solverMode= SOLVER_USE_WARMSTARTING + SOLVER_USE_2_FRICTION_DIRECTIONS + SOLVER_RANDMIZE_ORDER + SOLVER_USE_FRICTION_WARMSTARTING;
@@ -456,15 +466,20 @@ m_scalingPropagated(false)
void CcdPhysicsEnvironment::AddCcdPhysicsController(CcdPhysicsController* ctrl)
{
+ // the controller is already added we do nothing
+ if (!m_controllers.insert(ctrl).second) {
+ return;
+ }
+
btRigidBody* body = ctrl->GetRigidBody();
btCollisionObject* obj = ctrl->GetCollisionObject();
//this m_userPointer is just used for triggers, see CallbackTriggers
obj->setUserPointer(ctrl);
- if (body)
- body->setGravity( m_gravity );
-
- m_controllers.insert(ctrl);
+ if (body) {
+ body->setGravity(m_gravity);
+ body->setSleepingThresholds(m_linearDeactivationThreshold, m_angularDeactivationThreshold);
+ }
if (body)
{
@@ -496,20 +511,49 @@ void CcdPhysicsEnvironment::AddCcdPhysicsController(CcdPhysicsController* ctrl)
assert(obj->getBroadphaseHandle());
}
-
+void CcdPhysicsEnvironment::RemoveConstraint(btTypedConstraint *con)
+{
+ btRigidBody rbA = con->getRigidBodyA();
+ btRigidBody rbB = con->getRigidBodyB();
+ rbA.activate();
+ rbB.activate();
+ m_dynamicsWorld->removeConstraint(con);
+
+ if (rbA.getUserPointer()) {
+ ((CcdPhysicsController *)rbA.getUserPointer())->removeCcdConstraintRef(con);
+ }
+
+ if (rbB.getUserPointer()) {
+ ((CcdPhysicsController *)rbB.getUserPointer())->removeCcdConstraintRef(con);
+ }
+
+ /* Since we remove the constraint in the onwer and the target, we can delete it,
+ * KX_ConstraintWrapper keep the constraint id not the pointer, so no problems. */
+ delete con;
+}
bool CcdPhysicsEnvironment::RemoveCcdPhysicsController(CcdPhysicsController* ctrl)
{
+ // if the physics controller is already removed we do nothing
+ if (!m_controllers.erase(ctrl)) {
+ return false;
+ }
+
//also remove constraint
btRigidBody* body = ctrl->GetRigidBody();
if (body)
{
- for (int i=body->getNumConstraintRefs()-1;i>=0;i--)
+ btBroadphaseProxy *proxy = ctrl->GetCollisionObject()->getBroadphaseHandle();
+ btDispatcher *dispatcher = m_dynamicsWorld->getDispatcher();
+ btOverlappingPairCache *pairCache = m_dynamicsWorld->getPairCache();
+
+ CleanPairCallback cleanPairs(proxy, pairCache, dispatcher);
+ pairCache->processAllOverlappingPairs(&cleanPairs, dispatcher);
+
+ for (int i = ctrl->getNumCcdConstraintRefs() - 1; i >= 0; i--)
{
- btTypedConstraint* con = body->getConstraintRef(i);
- m_dynamicsWorld->removeConstraint(con);
- body->removeConstraintRef(con);
- //delete con; //might be kept by python KX_ConstraintWrapper
+ btTypedConstraint* con = ctrl->getCcdConstraintRef(i);
+ RemoveConstraint(con);
}
m_dynamicsWorld->removeRigidBody(ctrl->GetRigidBody());
@@ -524,7 +568,7 @@ bool CcdPhysicsEnvironment::RemoveCcdPhysicsController(CcdPhysicsController* ctr
}
if (vehicle_constraint > 0)
- RemoveConstraint(vehicle_constraint);
+ RemoveConstraintById(vehicle_constraint);
} else
{
//if a softbody
@@ -541,13 +585,8 @@ bool CcdPhysicsEnvironment::RemoveCcdPhysicsController(CcdPhysicsController* ctr
}
}
}
- if (ctrl->m_registerCount != 0)
- printf("Warning: removing controller with non-zero m_registerCount: %d\n", ctrl->m_registerCount);
- //remove it from the triggers
- m_triggerControllers.erase(ctrl);
-
- return (m_controllers.erase(ctrl) != 0);
+ return true;
}
void CcdPhysicsEnvironment::UpdateCcdPhysicsController(CcdPhysicsController* ctrl, btScalar newMass, int newCollisionFlags, short int newCollisionGroup, short int newCollisionMask)
@@ -555,6 +594,7 @@ void CcdPhysicsEnvironment::UpdateCcdPhysicsController(CcdPhysicsController* ctr
// this function is used when the collisionning group of a controller is changed
// remove and add the collistioning object
btRigidBody* body = ctrl->GetRigidBody();
+ btSoftBody *softBody = ctrl->GetSoftBody();
btCollisionObject* obj = ctrl->GetCollisionObject();
if (obj)
{
@@ -568,6 +608,9 @@ void CcdPhysicsEnvironment::UpdateCcdPhysicsController(CcdPhysicsController* ctr
body->setMassProps(newMass, inertia);
m_dynamicsWorld->addRigidBody(body, newCollisionGroup, newCollisionMask);
}
+ else if (softBody) {
+ m_dynamicsWorld->addSoftBody(softBody);
+ }
else {
m_dynamicsWorld->addCollisionObject(obj, newCollisionGroup, newCollisionMask);
}
@@ -579,43 +622,6 @@ void CcdPhysicsEnvironment::UpdateCcdPhysicsController(CcdPhysicsController* ctr
ctrl->m_cci.m_collisionFlags = newCollisionFlags;
}
-void CcdPhysicsEnvironment::EnableCcdPhysicsController(CcdPhysicsController* ctrl)
-{
- if (m_controllers.insert(ctrl).second)
- {
- btCollisionObject* obj = ctrl->GetCollisionObject();
- obj->setUserPointer(ctrl);
- // update the position of the object from the user
- if (ctrl->GetMotionState())
- {
- btTransform xform = CcdPhysicsController::GetTransformFromMotionState(ctrl->GetMotionState());
- ctrl->SetCenterOfMassTransform(xform);
- }
- m_dynamicsWorld->addCollisionObject(obj,
- ctrl->GetCollisionFilterGroup(), ctrl->GetCollisionFilterMask());
- }
-}
-
-void CcdPhysicsEnvironment::DisableCcdPhysicsController(CcdPhysicsController* ctrl)
-{
- if (m_controllers.erase(ctrl))
- {
- btRigidBody* body = ctrl->GetRigidBody();
- if (body)
- {
- m_dynamicsWorld->removeRigidBody(body);
- } else
- {
- if (ctrl->GetSoftBody())
- {
- } else
- {
- m_dynamicsWorld->removeCollisionObject(ctrl->GetCollisionObject());
- }
- }
- }
-}
-
void CcdPhysicsEnvironment::RefreshCcdPhysicsController(CcdPhysicsController* ctrl)
{
btCollisionObject* obj = ctrl->GetCollisionObject();
@@ -629,6 +635,11 @@ void CcdPhysicsEnvironment::RefreshCcdPhysicsController(CcdPhysicsController* ct
}
}
+bool CcdPhysicsEnvironment::IsActiveCcdPhysicsController(CcdPhysicsController *ctrl)
+{
+ return (m_controllers.find(ctrl) != m_controllers.end());
+}
+
void CcdPhysicsEnvironment::AddCcdGraphicController(CcdGraphicController* ctrl)
{
if (m_cullingTree && !ctrl->GetBroadphaseHandle())
@@ -664,6 +675,19 @@ void CcdPhysicsEnvironment::RemoveCcdGraphicController(CcdGraphicController* ctr
}
}
+void CcdPhysicsEnvironment::UpdateCcdPhysicsControllerShape(CcdShapeConstructionInfo *shapeInfo)
+{
+ for (std::set<CcdPhysicsController *>::iterator it = m_controllers.begin(); it != m_controllers.end(); ++it) {
+ CcdPhysicsController *ctrl = *it;
+
+ if (ctrl->GetShapeInfo() != shapeInfo)
+ continue;
+
+ ctrl->ReplaceControllerShape(NULL);
+ RefreshCcdPhysicsController(ctrl);
+ }
+}
+
void CcdPhysicsEnvironment::BeginFrame()
{
@@ -675,11 +699,31 @@ void CcdPhysicsEnvironment::DebugDrawWorld()
m_dynamicsWorld->debugDrawWorld();
}
+void CcdPhysicsEnvironment::StaticSimulationSubtickCallback(btDynamicsWorld *world, btScalar timeStep)
+{
+ // Get the pointer to the CcdPhysicsEnvironment associated with this Bullet world.
+ CcdPhysicsEnvironment *this_ = static_cast<CcdPhysicsEnvironment*>(world->getWorldUserInfo());
+ this_->SimulationSubtickCallback(timeStep);
+}
+
+void CcdPhysicsEnvironment::SimulationSubtickCallback(btScalar timeStep)
+{
+ std::set<CcdPhysicsController*>::iterator it;
+
+ for (it = m_controllers.begin(); it != m_controllers.end(); it++) {
+ (*it)->SimulationTick(timeStep);
+ }
+}
+
bool CcdPhysicsEnvironment::ProceedDeltaTime(double curTime,float timeStep,float interval)
{
std::set<CcdPhysicsController*>::iterator it;
int i;
+ // Update Bullet global variables.
+ gDeactivationTime = m_deactivationTime;
+ gContactBreakingThreshold = m_contactBreakingThreshold;
+
for (it=m_controllers.begin(); it!=m_controllers.end(); it++)
{
(*it)->SynchronizeMotionStates(timeStep);
@@ -745,8 +789,8 @@ public:
void CcdPhysicsEnvironment::ProcessFhSprings(double curTime,float interval)
{
std::set<CcdPhysicsController*>::iterator it;
- // dynamic of Fh spring is based on a timestep of 1/60
- int numIter = (int)(interval*60.0001f);
+ // Add epsilon to the tick rate for numerical stability
+ int numIter = (int)(interval*(KX_KetsjiEngine::GetTicRate() + 0.001f));
for (it=m_controllers.begin(); it!=m_controllers.end(); it++)
{
@@ -899,21 +943,32 @@ void CcdPhysicsEnvironment::SetNumIterations(int numIter)
}
void CcdPhysicsEnvironment::SetDeactivationTime(float dTime)
{
- gDeactivationTime = dTime;
+ m_deactivationTime = dTime;
}
void CcdPhysicsEnvironment::SetDeactivationLinearTreshold(float linTresh)
{
- gLinearSleepingTreshold = linTresh;
+ m_linearDeactivationThreshold = linTresh;
+
+ // Update from all controllers.
+ for (std::set<CcdPhysicsController*>::iterator it = m_controllers.begin(); it != m_controllers.end(); it++) {
+ if ((*it)->GetRigidBody())
+ (*it)->GetRigidBody()->setSleepingThresholds(m_linearDeactivationThreshold, m_angularDeactivationThreshold);
+ }
}
void CcdPhysicsEnvironment::SetDeactivationAngularTreshold(float angTresh)
{
- gAngularSleepingTreshold = angTresh;
+ m_angularDeactivationThreshold = angTresh;
+
+ // Update from all controllers.
+ for (std::set<CcdPhysicsController*>::iterator it = m_controllers.begin(); it != m_controllers.end(); it++) {
+ if ((*it)->GetRigidBody())
+ (*it)->GetRigidBody()->setSleepingThresholds(m_linearDeactivationThreshold, m_angularDeactivationThreshold);
+ }
}
void CcdPhysicsEnvironment::SetContactBreakingTreshold(float contactBreakingTreshold)
{
- gContactBreakingThreshold = contactBreakingTreshold;
-
+ m_contactBreakingThreshold = contactBreakingTreshold;
}
@@ -1059,11 +1114,12 @@ int CcdPhysicsEnvironment::CreateUniversalD6Constraint(
return 0;
}
-
-
-void CcdPhysicsEnvironment::RemoveConstraint(int constraintId)
+void CcdPhysicsEnvironment::RemoveConstraintById(int constraintId)
{
-
+ // For soft body constraints
+ if (constraintId == 0)
+ return;
+
int i;
int numConstraints = m_dynamicsWorld->getNumConstraints();
for (i=0;i<numConstraints;i++)
@@ -1071,9 +1127,7 @@ void CcdPhysicsEnvironment::RemoveConstraint(int constraintId)
btTypedConstraint* constraint = m_dynamicsWorld->getConstraint(i);
if (constraint->getUserConstraintId() == constraintId)
{
- constraint->getRigidBodyA().activate();
- constraint->getRigidBodyB().activate();
- m_dynamicsWorld->removeConstraint(constraint);
+ RemoveConstraint(constraint);
break;
}
}
@@ -1149,17 +1203,8 @@ static bool GetHitTriangle(btCollisionShape* shape, CcdShapeConstructionInfo* sh
int indexstride;
int numfaces;
PHY_ScalarType indicestype;
- btStridingMeshInterface* meshInterface = NULL;
- btTriangleMeshShape* triangleShape = shapeInfo->GetMeshShape();
+ btStridingMeshInterface* meshInterface = shapeInfo->GetMeshInterface();
- if (triangleShape)
- meshInterface = triangleShape->getMeshInterface();
- else
- {
- // other possibility is gImpact
- if (shape->getShapeType() == GIMPACT_SHAPE_PROXYTYPE)
- meshInterface = (static_cast<btGImpactMeshShape*>(shape))->getMeshInterface();
- }
if (!meshInterface)
return false;
@@ -2016,6 +2061,9 @@ CcdPhysicsEnvironment::~CcdPhysicsEnvironment()
float CcdPhysicsEnvironment::GetConstraintParam(int constraintId,int param)
{
btTypedConstraint* typedConstraint = GetConstraintById(constraintId);
+ if (!typedConstraint)
+ return 0.0f;
+
switch (typedConstraint->getUserConstraintType())
{
case PHY_GENERIC_6DOF_CONSTRAINT:
@@ -2055,6 +2103,9 @@ float CcdPhysicsEnvironment::GetConstraintParam(int constraintId,int param)
void CcdPhysicsEnvironment::SetConstraintParam(int constraintId,int param,float value0,float value1)
{
btTypedConstraint* typedConstraint = GetConstraintById(constraintId);
+ if (!typedConstraint)
+ return;
+
switch (typedConstraint->getUserConstraintType())
{
case PHY_GENERIC_6DOF_CONSTRAINT:
@@ -2164,6 +2215,9 @@ void CcdPhysicsEnvironment::SetConstraintParam(int constraintId,int param,float
btTypedConstraint* CcdPhysicsEnvironment::GetConstraintById(int constraintId)
{
+ // For soft body constraints
+ if (constraintId == 0)
+ return NULL;
int numConstraints = m_dynamicsWorld->getNumConstraints();
int i;
@@ -2181,30 +2235,20 @@ btTypedConstraint* CcdPhysicsEnvironment::GetConstraintById(int constraintId)
void CcdPhysicsEnvironment::AddSensor(PHY_IPhysicsController* ctrl)
{
-
CcdPhysicsController* ctrl1 = (CcdPhysicsController* )ctrl;
- // addSensor() is a "light" function for bullet because it is used
- // dynamically when the sensor is activated. Use enableCcdPhysicsController() instead
- //if (m_controllers.insert(ctrl1).second)
- //{
- // addCcdPhysicsController(ctrl1);
- //}
- EnableCcdPhysicsController(ctrl1);
+ AddCcdPhysicsController(ctrl1);
}
bool CcdPhysicsEnvironment::RemoveCollisionCallback(PHY_IPhysicsController* ctrl)
{
CcdPhysicsController* ccdCtrl = (CcdPhysicsController*)ctrl;
- if (!ccdCtrl->Unregister())
- return false;
- m_triggerControllers.erase(ccdCtrl);
- return true;
+ return ccdCtrl->Unregister();
}
void CcdPhysicsEnvironment::RemoveSensor(PHY_IPhysicsController* ctrl)
{
- DisableCcdPhysicsController((CcdPhysicsController*)ctrl);
+ RemoveCcdPhysicsController((CcdPhysicsController*)ctrl);
}
void CcdPhysicsEnvironment::AddTouchCallback(int response_class, PHY_ResponseCallback callback, void *user)
@@ -2242,73 +2286,83 @@ void CcdPhysicsEnvironment::AddTouchCallback(int response_class, PHY_ResponseCal
bool CcdPhysicsEnvironment::RequestCollisionCallback(PHY_IPhysicsController* ctrl)
{
CcdPhysicsController* ccdCtrl = static_cast<CcdPhysicsController*>(ctrl);
-
- if (!ccdCtrl->Register())
- return false;
- m_triggerControllers.insert(ccdCtrl);
- return true;
+ return ccdCtrl->Register();
}
void CcdPhysicsEnvironment::CallbackTriggers()
{
- if (m_triggerCallbacks[PHY_OBJECT_RESPONSE] || (m_debugDrawer && (m_debugDrawer->getDebugMode() & btIDebugDraw::DBG_DrawContactPoints)))
- {
- //walk over all overlapping pairs, and if one of the involved bodies is registered for trigger callback, perform callback
- btDispatcher* dispatcher = m_dynamicsWorld->getDispatcher();
- int numManifolds = dispatcher->getNumManifolds();
- for (int i=0;i<numManifolds;i++)
- {
- btPersistentManifold* manifold = dispatcher->getManifoldByIndexInternal(i);
- int numContacts = manifold->getNumContacts();
- if (numContacts)
- {
- const btRigidBody* rb0 = static_cast<const btRigidBody*>(manifold->getBody0());
- const btRigidBody* rb1 = static_cast<const btRigidBody*>(manifold->getBody1());
- if (m_debugDrawer && (m_debugDrawer->getDebugMode() & btIDebugDraw::DBG_DrawContactPoints))
- {
- for (int j=0;j<numContacts;j++)
- {
- btVector3 color(1,0,0);
- const btManifoldPoint& cp = manifold->getContactPoint(j);
- if (m_debugDrawer)
- m_debugDrawer->drawContactPoint(cp.m_positionWorldOnB,cp.m_normalWorldOnB,cp.getDistance(),cp.getLifeTime(),color);
- }
- }
- const btRigidBody* obj0 = rb0;
- const btRigidBody* obj1 = rb1;
+ bool draw_contact_points = m_debugDrawer && (m_debugDrawer->getDebugMode() & btIDebugDraw::DBG_DrawContactPoints);
- //m_internalOwner is set in 'addPhysicsController'
- CcdPhysicsController* ctrl0 = static_cast<CcdPhysicsController*>(obj0->getUserPointer());
- CcdPhysicsController* ctrl1 = static_cast<CcdPhysicsController*>(obj1->getUserPointer());
+ if (!m_triggerCallbacks[PHY_OBJECT_RESPONSE] && !draw_contact_points)
+ return;
- std::set<CcdPhysicsController*>::const_iterator i = m_triggerControllers.find(ctrl0);
- if (i == m_triggerControllers.end())
- {
- i = m_triggerControllers.find(ctrl1);
- }
+ //walk over all overlapping pairs, and if one of the involved bodies is registered for trigger callback, perform callback
+ btDispatcher* dispatcher = m_dynamicsWorld->getDispatcher();
+ int numManifolds = dispatcher->getNumManifolds();
+ for (int i=0;i<numManifolds;i++)
+ {
+ bool colliding_ctrl0 = true;
+ btPersistentManifold* manifold = dispatcher->getManifoldByIndexInternal(i);
+ int numContacts = manifold->getNumContacts();
+ if (!numContacts) continue;
- if (!(i == m_triggerControllers.end()))
- {
- m_triggerCallbacks[PHY_OBJECT_RESPONSE](m_triggerCallbacksUserPtrs[PHY_OBJECT_RESPONSE],
- ctrl0,ctrl1,0);
- }
- // Bullet does not refresh the manifold contact point for object without contact response
- // may need to remove this when a newer Bullet version is integrated
- if (!dispatcher->needsResponse(rb0, rb1))
- {
- // Refresh algorithm fails sometimes when there is penetration
- // (usuall the case with ghost and sensor objects)
- // Let's just clear the manifold, in any case, it is recomputed on each frame.
- manifold->clearManifold(); //refreshContactPoints(rb0->getCenterOfMassTransform(),rb1->getCenterOfMassTransform());
- }
+ const btRigidBody* rb0 = static_cast<const btRigidBody*>(manifold->getBody0());
+ const btRigidBody* rb1 = static_cast<const btRigidBody*>(manifold->getBody1());
+ if (draw_contact_points)
+ {
+ for (int j=0;j<numContacts;j++)
+ {
+ btVector3 color(1,1,0);
+ const btManifoldPoint& cp = manifold->getContactPoint(j);
+ m_debugDrawer->drawContactPoint(cp.m_positionWorldOnB,
+ cp.m_normalWorldOnB,
+ cp.getDistance(),
+ cp.getLifeTime(),
+ color);
}
}
+ //m_internalOwner is set in 'addPhysicsController'
+ CcdPhysicsController* ctrl0 = static_cast<CcdPhysicsController*>(rb0->getUserPointer());
+ CcdPhysicsController* ctrl1 = static_cast<CcdPhysicsController*>(rb1->getUserPointer());
+ bool usecallback = false;
+ // Test if one of the controller is registered and use collision callback.
+ if (ctrl0->Registered())
+ usecallback = true;
+ else if (ctrl1->Registered()) {
+ colliding_ctrl0 = false;
+ usecallback = true;
+ }
- }
+ if (usecallback) {
+ static PHY_CollData coll_data;
+ const btManifoldPoint &cp = manifold->getContactPoint(0);
+
+ /* Make sure that "point1" is always on the object we report on, and
+ * "point2" on the other object. Also ensure the normal is oriented
+ * correctly. */
+ btVector3 point1 = colliding_ctrl0 ? cp.m_positionWorldOnA : cp.m_positionWorldOnB;
+ btVector3 point2 = colliding_ctrl0 ? cp.m_positionWorldOnB : cp.m_positionWorldOnA;
+ btVector3 normal = colliding_ctrl0 ? -cp.m_normalWorldOnB : cp.m_normalWorldOnB;
+ coll_data.m_point1 = MT_Vector3(point1.m_floats);
+ coll_data.m_point2 = MT_Vector3(point2.m_floats);
+ coll_data.m_normal = MT_Vector3(normal.m_floats);
+ m_triggerCallbacks[PHY_OBJECT_RESPONSE](m_triggerCallbacksUserPtrs[PHY_OBJECT_RESPONSE],
+ ctrl0, ctrl1, &coll_data);
+ }
+ // Bullet does not refresh the manifold contact point for object without contact response
+ // may need to remove this when a newer Bullet version is integrated
+ if (!dispatcher->needsResponse(rb0, rb1))
+ {
+ // Refresh algorithm fails sometimes when there is penetration
+ // (usuall the case with ghost and sensor objects)
+ // Let's just clear the manifold, in any case, it is recomputed on each frame.
+ manifold->clearManifold(); //refreshContactPoints(rb0->getCenterOfMassTransform(),rb1->getCenterOfMassTransform());
+ }
+ }
}
// This call back is called before a pair is added in the cache
@@ -2624,7 +2678,6 @@ int CcdPhysicsEnvironment::CreateConstraint(class PHY_IPhysicsController* ctrl
if (!rb0)
return 0;
-
btVector3 pivotInB = rb1 ? rb1->getCenterOfMassTransform().inverse()(rb0->getCenterOfMassTransform()(pivotInA)) :
rb0->getCenterOfMassTransform() * pivotInA;
btVector3 axisInA(axisX,axisY,axisZ);
@@ -2636,6 +2689,8 @@ int CcdPhysicsEnvironment::CreateConstraint(class PHY_IPhysicsController* ctrl
{
case PHY_POINT2POINT_CONSTRAINT:
{
+ // If either of the controllers is missing, we can't do anything.
+ if (!c0 || !c1) return 0;
btPoint2PointConstraint* p2p = 0;
@@ -2649,6 +2704,8 @@ int CcdPhysicsEnvironment::CreateConstraint(class PHY_IPhysicsController* ctrl
pivotInA);
}
+ c0->addCcdConstraintRef(p2p);
+ c1->addCcdConstraintRef(p2p);
m_dynamicsWorld->addConstraint(p2p,disableCollisionBetweenLinkedBodies);
// m_constraints.push_back(p2p);
@@ -2662,6 +2719,9 @@ int CcdPhysicsEnvironment::CreateConstraint(class PHY_IPhysicsController* ctrl
case PHY_GENERIC_6DOF_CONSTRAINT:
{
+ // If either of the controllers is missing, we can't do anything.
+ if (!c0 || !c1) return 0;
+
btGeneric6DofConstraint* genericConstraint = 0;
if (rb1)
@@ -2715,10 +2775,12 @@ int CcdPhysicsEnvironment::CreateConstraint(class PHY_IPhysicsController* ctrl
*rb0,s_fixedObject2,
frameInA,frameInB,useReferenceFrameA);
}
-
+
if (genericConstraint)
{
//m_constraints.push_back(genericConstraint);
+ c0->addCcdConstraintRef(genericConstraint);
+ c1->addCcdConstraintRef(genericConstraint);
m_dynamicsWorld->addConstraint(genericConstraint,disableCollisionBetweenLinkedBodies);
genericConstraint->setUserConstraintId(gConstraintUid++);
genericConstraint->setUserConstraintType(type);
@@ -2730,6 +2792,9 @@ int CcdPhysicsEnvironment::CreateConstraint(class PHY_IPhysicsController* ctrl
}
case PHY_CONE_TWIST_CONSTRAINT:
{
+ // If either of the controllers is missing, we can't do anything.
+ if (!c0 || !c1) return 0;
+
btConeTwistConstraint* coneTwistContraint = 0;
@@ -2781,10 +2846,12 @@ int CcdPhysicsEnvironment::CreateConstraint(class PHY_IPhysicsController* ctrl
*rb0,s_fixedObject2,
frameInA,frameInB);
}
-
+
if (coneTwistContraint)
{
//m_constraints.push_back(genericConstraint);
+ c0->addCcdConstraintRef(coneTwistContraint);
+ c1->addCcdConstraintRef(coneTwistContraint);
m_dynamicsWorld->addConstraint(coneTwistContraint,disableCollisionBetweenLinkedBodies);
coneTwistContraint->setUserConstraintId(gConstraintUid++);
coneTwistContraint->setUserConstraintType(type);
@@ -2802,6 +2869,9 @@ int CcdPhysicsEnvironment::CreateConstraint(class PHY_IPhysicsController* ctrl
case PHY_LINEHINGE_CONSTRAINT:
{
+ // If either of the controllers is missing, we can't do anything.
+ if (!c0 || !c1) return 0;
+
btHingeConstraint* hinge = 0;
if (rb1)
@@ -2858,6 +2928,8 @@ int CcdPhysicsEnvironment::CreateConstraint(class PHY_IPhysicsController* ctrl
hinge->setAngularOnly(angularOnly);
//m_constraints.push_back(hinge);
+ c0->addCcdConstraintRef(hinge);
+ c1->addCcdConstraintRef(hinge);
m_dynamicsWorld->addConstraint(hinge,disableCollisionBetweenLinkedBodies);
hinge->setUserConstraintId(gConstraintUid++);
hinge->setUserConstraintType(type);
@@ -2926,6 +2998,10 @@ PHY_IPhysicsController* CcdPhysicsEnvironment::CreateConeController(float conera
float CcdPhysicsEnvironment::getAppliedImpulse(int constraintid)
{
+ // For soft body constraints
+ if (constraintid == 0)
+ return 0.0f;
+
int i;
int numConstraints = m_dynamicsWorld->getNumConstraints();
for (i=0;i<numConstraints;i++)
@@ -2999,7 +3075,8 @@ struct BlenderDebugDraw : public btIDebugDraw
virtual void drawContactPoint(const btVector3& PointOnB,const btVector3& normalOnB,float distance,int lifeTime,const btVector3& color)
{
- //not yet
+ drawLine(PointOnB, PointOnB + normalOnB, color);
+ drawSphere(PointOnB, 0.1, color);
}
virtual void setDebugMode(int debugMode)
@@ -3036,7 +3113,7 @@ void CcdPhysicsEnvironment::ConvertObject(KX_GameObject *gameobj, RAS_MeshObject
{
Object* blenderobject = gameobj->GetBlenderObject();
- bool isbulletdyna = (blenderobject->gameflag & OB_DYNAMIC) != 0;;
+ bool isbulletdyna = (blenderobject->gameflag & OB_DYNAMIC) != 0;
bool isbulletsensor = (blenderobject->gameflag & OB_SENSOR) != 0;
bool isbulletchar = (blenderobject->gameflag & OB_CHARACTER) != 0;
bool isbulletsoftbody = (blenderobject->gameflag & OB_SOFT_BODY) != 0;
@@ -3056,9 +3133,7 @@ void CcdPhysicsEnvironment::ConvertObject(KX_GameObject *gameobj, RAS_MeshObject
{
KX_BlenderSceneConverter *converter = (KX_BlenderSceneConverter*)KX_GetActiveEngine()->GetSceneConverter();
parent = converter->FindGameObject(blenderparent);
- isbulletdyna = false;
isbulletsoftbody = false;
- shapeprops->m_mass = 0.f;
}
if (!isbulletdyna)
@@ -3082,6 +3157,8 @@ void CcdPhysicsEnvironment::ConvertObject(KX_GameObject *gameobj, RAS_MeshObject
ci.m_mass = isbulletdyna ? shapeprops->m_mass : 0.f;
ci.m_clamp_vel_min = shapeprops->m_clamp_vel_min;
ci.m_clamp_vel_max = shapeprops->m_clamp_vel_max;
+ ci.m_clamp_angvel_min = shapeprops->m_clamp_angvel_min;
+ ci.m_clamp_angvel_max = shapeprops->m_clamp_angvel_max;
ci.m_stepHeight = isbulletchar ? shapeprops->m_step_height : 0.f;
ci.m_jumpSpeed = isbulletchar ? shapeprops->m_jump_speed : 0.f;
ci.m_fallSpeed = isbulletchar ? shapeprops->m_fall_speed : 0.f;
@@ -3339,46 +3416,50 @@ void CcdPhysicsEnvironment::ConvertObject(KX_GameObject *gameobj, RAS_MeshObject
//take relative transform into account!
CcdPhysicsController* parentCtrl = (CcdPhysicsController*)parent->GetPhysicsController();
assert(parentCtrl);
- CcdShapeConstructionInfo* parentShapeInfo = parentCtrl->GetShapeInfo();
- btRigidBody* rigidbody = parentCtrl->GetRigidBody();
- btCollisionShape* colShape = rigidbody->getCollisionShape();
- assert(colShape->isCompound());
- btCompoundShape* compoundShape = (btCompoundShape*)colShape;
-
- // compute the local transform from parent, this may include several node in the chain
- SG_Node* gameNode = gameobj->GetSGNode();
- SG_Node* parentNode = parent->GetSGNode();
- // relative transform
- MT_Vector3 parentScale = parentNode->GetWorldScaling();
- parentScale[0] = MT_Scalar(1.0)/parentScale[0];
- parentScale[1] = MT_Scalar(1.0)/parentScale[1];
- parentScale[2] = MT_Scalar(1.0)/parentScale[2];
- MT_Vector3 relativeScale = gameNode->GetWorldScaling() * parentScale;
- MT_Matrix3x3 parentInvRot = parentNode->GetWorldOrientation().transposed();
- MT_Vector3 relativePos = parentInvRot*((gameNode->GetWorldPosition()-parentNode->GetWorldPosition())*parentScale);
- MT_Matrix3x3 relativeRot = parentInvRot*gameNode->GetWorldOrientation();
-
- shapeInfo->m_childScale.setValue(relativeScale[0],relativeScale[1],relativeScale[2]);
- bm->setLocalScaling(shapeInfo->m_childScale);
- shapeInfo->m_childTrans.getOrigin().setValue(relativePos[0],relativePos[1],relativePos[2]);
- float rot[12];
- relativeRot.getValue(rot);
- shapeInfo->m_childTrans.getBasis().setFromOpenGLSubMatrix(rot);
-
- parentShapeInfo->AddShape(shapeInfo);
- compoundShape->addChildShape(shapeInfo->m_childTrans,bm);
- //do some recalc?
- //recalc inertia for rigidbody
- if (!rigidbody->isStaticOrKinematicObject())
- {
- btVector3 localInertia;
- float mass = 1.f/rigidbody->getInvMass();
- compoundShape->calculateLocalInertia(mass,localInertia);
- rigidbody->setMassProps(mass,localInertia);
+
+ // only makes compound shape if parent has a physics controller (i.e not an empty, etc)
+ if (parentCtrl) {
+ CcdShapeConstructionInfo* parentShapeInfo = parentCtrl->GetShapeInfo();
+ btRigidBody* rigidbody = parentCtrl->GetRigidBody();
+ btCollisionShape* colShape = rigidbody->getCollisionShape();
+ assert(colShape->isCompound());
+ btCompoundShape* compoundShape = (btCompoundShape*)colShape;
+
+ // compute the local transform from parent, this may include several node in the chain
+ SG_Node* gameNode = gameobj->GetSGNode();
+ SG_Node* parentNode = parent->GetSGNode();
+ // relative transform
+ MT_Vector3 parentScale = parentNode->GetWorldScaling();
+ parentScale[0] = MT_Scalar(1.0)/parentScale[0];
+ parentScale[1] = MT_Scalar(1.0)/parentScale[1];
+ parentScale[2] = MT_Scalar(1.0)/parentScale[2];
+ MT_Vector3 relativeScale = gameNode->GetWorldScaling() * parentScale;
+ MT_Matrix3x3 parentInvRot = parentNode->GetWorldOrientation().transposed();
+ MT_Vector3 relativePos = parentInvRot*((gameNode->GetWorldPosition()-parentNode->GetWorldPosition())*parentScale);
+ MT_Matrix3x3 relativeRot = parentInvRot*gameNode->GetWorldOrientation();
+
+ shapeInfo->m_childScale.setValue(relativeScale[0],relativeScale[1],relativeScale[2]);
+ bm->setLocalScaling(shapeInfo->m_childScale);
+ shapeInfo->m_childTrans.getOrigin().setValue(relativePos[0],relativePos[1],relativePos[2]);
+ float rot[12];
+ relativeRot.getValue(rot);
+ shapeInfo->m_childTrans.getBasis().setFromOpenGLSubMatrix(rot);
+
+ parentShapeInfo->AddShape(shapeInfo);
+ compoundShape->addChildShape(shapeInfo->m_childTrans,bm);
+ //do some recalc?
+ //recalc inertia for rigidbody
+ if (!rigidbody->isStaticOrKinematicObject())
+ {
+ btVector3 localInertia;
+ float mass = 1.f/rigidbody->getInvMass();
+ compoundShape->calculateLocalInertia(mass,localInertia);
+ rigidbody->setMassProps(mass,localInertia);
+ }
+ shapeInfo->Release();
+ // delete motionstate as it's not used
+ delete motionstate;
}
- shapeInfo->Release();
- // delete motionstate as it's not used
- delete motionstate;
return;
}
@@ -3482,20 +3563,23 @@ void CcdPhysicsEnvironment::ConvertObject(KX_GameObject *gameobj, RAS_MeshObject
if (isbulletdyna)
gameobj->SetRecordAnimation(true);
+ physicscontroller->SetNewClientInfo(gameobj->getClientInfo());
+
// don't add automatically sensor object, they are added when a collision sensor is registered
if (!isbulletsensor && (blenderobject->lay & activeLayerBitInfo) != 0)
{
this->AddCcdPhysicsController( physicscontroller);
}
- physicscontroller->SetNewClientInfo(gameobj->getClientInfo());
+
{
btRigidBody* rbody = physicscontroller->GetRigidBody();
if (rbody)
{
+ rbody->setLinearFactor(ci.m_linearFactor);
+
if (isbulletrigidbody)
{
- rbody->setLinearFactor(ci.m_linearFactor);
rbody->setAngularFactor(ci.m_angularFactor);
}
@@ -3506,6 +3590,9 @@ void CcdPhysicsEnvironment::ConvertObject(KX_GameObject *gameobj, RAS_MeshObject
}
}
+ if (parent)
+ physicscontroller->SuspendDynamics(false);
+
CcdPhysicsController* parentCtrl = parent ? (CcdPhysicsController*)parent->GetPhysicsController() : 0;
physicscontroller->SetParentCtrl(parentCtrl);
@@ -3556,3 +3643,79 @@ void CcdPhysicsEnvironment::ConvertObject(KX_GameObject *gameobj, RAS_MeshObject
}
#endif
}
+
+
+void CcdPhysicsEnvironment::SetupObjectConstraints(KX_GameObject *obj_src, KX_GameObject *obj_dest,
+ bRigidBodyJointConstraint *dat)
+{
+ PHY_IPhysicsController *phy_src = obj_src->GetPhysicsController();
+ PHY_IPhysicsController *phy_dest = obj_dest->GetPhysicsController();
+ PHY_IPhysicsEnvironment *phys_env = obj_src->GetScene()->GetPhysicsEnvironment();
+
+ /* We need to pass a full constraint frame, not just axis. */
+ MT_Matrix3x3 localCFrame(MT_Vector3(dat->axX,dat->axY,dat->axZ));
+ MT_Vector3 axis0 = localCFrame.getColumn(0);
+ MT_Vector3 axis1 = localCFrame.getColumn(1);
+ MT_Vector3 axis2 = localCFrame.getColumn(2);
+ MT_Vector3 scale = obj_src->NodeGetWorldScaling();
+
+ /* Apply not only the pivot and axis values, but also take scale into count
+ * this is not working well, if only one or two axis are scaled, but works ok on
+ * homogeneous scaling. */
+ int constraintId = phys_env->CreateConstraint(
+ phy_src, phy_dest, (PHY_ConstraintType)dat->type,
+ (float)(dat->pivX * scale.x()), (float)(dat->pivY * scale.y()), (float)(dat->pivZ * scale.z()),
+ (float)(axis0.x() * scale.x()), (float)(axis0.y() * scale.y()), (float)(axis0.z() * scale.z()),
+ (float)(axis1.x() * scale.x()), (float)(axis1.y() * scale.y()), (float)(axis1.z() * scale.z()),
+ (float)(axis2.x() * scale.x()), (float)(axis2.y() * scale.y()), (float)(axis2.z() * scale.z()),
+ dat->flag);
+
+ /* PHY_POINT2POINT_CONSTRAINT = 1,
+ * PHY_LINEHINGE_CONSTRAINT = 2,
+ * PHY_ANGULAR_CONSTRAINT = 3,
+ * PHY_CONE_TWIST_CONSTRAINT = 4,
+ * PHY_VEHICLE_CONSTRAINT = 11,
+ * PHY_GENERIC_6DOF_CONSTRAINT = 12 */
+
+ if (!constraintId)
+ return;
+
+ int dof = 0;
+ int dof_max = 0;
+ int dofbit = 0;
+
+ switch (dat->type) {
+ /* Set all the limits for generic 6DOF constraint. */
+ case PHY_GENERIC_6DOF_CONSTRAINT:
+ dof_max = 6;
+ dofbit = 1;
+ break;
+ /* Set XYZ angular limits for cone twist constraint. */
+ case PHY_CONE_TWIST_CONSTRAINT:
+ dof = 3;
+ dof_max = 6;
+ dofbit = 1 << 3;
+ break;
+ /* Set only X angular limits for line hinge and angular constraint. */
+ case PHY_LINEHINGE_CONSTRAINT:
+ case PHY_ANGULAR_CONSTRAINT:
+ dof = 3;
+ dof_max = 4;
+ dofbit = 1 << 3;
+ break;
+ default:
+ break;
+ }
+
+ for (; dof < dof_max; dof++) {
+ if (dat->flag & dofbit) {
+ phys_env->SetConstraintParam(constraintId, dof, dat->minLimit[dof], dat->maxLimit[dof]);
+ }
+ else {
+ /* minLimit > maxLimit means free (no limit) for this degree of freedom. */
+ phys_env->SetConstraintParam(constraintId, dof, 1.0f, -1.0f);
+ }
+ dofbit <<= 1;
+ }
+
+}
diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.h b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.h
index ff8a3f4f9f9..86f663959f1 100644
--- a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.h
+++ b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.h
@@ -22,6 +22,8 @@ subject to the following restrictions:
#define __CCDPHYSICSENVIRONMENT_H__
#include "PHY_IPhysicsEnvironment.h"
+#include "KX_KetsjiEngine.h"
+
#include <vector>
#include <set>
#include <map>
@@ -50,8 +52,10 @@ class btBroadphaseInterface;
struct btDbvtBroadphase;
class btOverlappingPairCache;
class btIDebugDraw;
+class btDynamicsWorld;
class PHY_IVehicle;
class CcdOverlapFilterCallBack;
+class CcdShapeConstructionInfo;
/** CcdPhysicsEnvironment is an experimental mainloop for physics simulation using optional continuous collision detection.
* Physics Environment takes care of stepping the simulation and is a container for physics entities.
@@ -63,6 +67,9 @@ class CcdPhysicsEnvironment : public PHY_IPhysicsEnvironment
friend class CcdOverlapFilterCallBack;
btVector3 m_gravity;
+ // Removes the constraint and his references from the owner and the target.
+ void RemoveConstraint(btTypedConstraint *con);
+
protected:
btIDebugDraw* m_debugDrawer;
@@ -84,6 +91,11 @@ protected:
int m_profileTimings;
bool m_enableSatCollisionDetection;
+ float m_deactivationTime;
+ float m_linearDeactivationThreshold;
+ float m_angularDeactivationThreshold;
+ float m_contactBreakingThreshold;
+
void ProcessFhSprings(double curTime,float timeStep);
public:
@@ -126,13 +138,20 @@ protected:
/// Perform an integration step of duration 'timeStep'.
virtual bool ProceedDeltaTime(double curTime,float timeStep,float interval);
+ /**
+ * Called by Bullet for every physical simulation (sub)tick.
+ * Our constructor registers this callback to Bullet, which stores a pointer to 'this' in
+ * the btDynamicsWorld::getWorldUserInfo() pointer.
+ */
+ static void StaticSimulationSubtickCallback(btDynamicsWorld *world, btScalar timeStep);
+ void SimulationSubtickCallback(btScalar timeStep);
+
virtual void DebugDrawWorld();
// virtual bool proceedDeltaTimeOneStep(float timeStep);
virtual void SetFixedTimeStep(bool useFixedTimeStep,float fixedTimeStep)
{
- //based on DEFAULT_PHYSICS_TIC_RATE of 60 hertz
- SetNumTimeSubSteps((int)(fixedTimeStep / 60.f));
+ SetNumTimeSubSteps((int)(fixedTimeStep / KX_KetsjiEngine::GetTicRate()));
}
//returns 0.f if no fixed timestep is used
@@ -169,7 +188,7 @@ protected:
virtual float GetConstraintParam(int constraintId,int param);
- virtual void RemoveConstraint(int constraintid);
+ virtual void RemoveConstraintById(int constraintid);
virtual float getAppliedImpulse(int constraintid);
@@ -220,16 +239,22 @@ protected:
void UpdateCcdPhysicsController(CcdPhysicsController* ctrl, btScalar newMass, int newCollisionFlags, short int newCollisionGroup, short int newCollisionMask);
- void DisableCcdPhysicsController(CcdPhysicsController* ctrl);
-
- void EnableCcdPhysicsController(CcdPhysicsController* ctrl);
-
void RefreshCcdPhysicsController(CcdPhysicsController* ctrl);
+ bool IsActiveCcdPhysicsController(CcdPhysicsController *ctrl);
+
void AddCcdGraphicController(CcdGraphicController* ctrl);
void RemoveCcdGraphicController(CcdGraphicController* ctrl);
+ /**
+ * Update all physics controllers shape which use the same shape construction info.
+ * Call RecreateControllerShape on controllers which use the same shape
+ * construction info that argument shapeInfo.
+ * You need to call this function when the shape construction info changed.
+ */
+ void UpdateCcdPhysicsControllerShape(CcdShapeConstructionInfo *shapeInfo);
+
btBroadphaseInterface* GetBroadphase();
btDbvtBroadphase* GetCullingTree() { return m_cullingTree; }
@@ -274,12 +299,15 @@ protected:
bool isCompoundChild,
bool hasCompoundChildren);
+ /* Set the rigid body joints constraints values for converted objects and replicated group instances. */
+ virtual void SetupObjectConstraints(KX_GameObject *obj_src, KX_GameObject *obj_dest,
+ bRigidBodyJointConstraint *dat);
+
protected:
std::set<CcdPhysicsController*> m_controllers;
- std::set<CcdPhysicsController*> m_triggerControllers;
PHY_ResponseCallback m_triggerCallbacks[PHY_NUM_RESPONSE];
void* m_triggerCallbacksUserPtrs[PHY_NUM_RESPONSE];
diff --git a/source/gameengine/Physics/Bullet/SConscript b/source/gameengine/Physics/Bullet/SConscript
index 2a8249b9558..5c5b1fe6ea6 100644
--- a/source/gameengine/Physics/Bullet/SConscript
+++ b/source/gameengine/Physics/Bullet/SConscript
@@ -34,7 +34,8 @@ incs = [
'#intern/container',
'#intern/guardedalloc',
'#intern/string',
- '#extern/glew/include',
+ env['BF_GLEW_INC'],
+ '#/intern/glew-mx',
'#intern/moto/include',
'#source/blender/blenkernel',
'#source/blender/blenlib',
@@ -52,6 +53,7 @@ incs = ' '.join(incs)
incs += ' ' + env['BF_BULLET_INC']
defs = []
+defs += env['BF_GL_DEFINITIONS']
if env['WITH_BF_PYTHON']:
incs += ' ' + env['BF_PYTHON_INC']
diff --git a/source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.cpp b/source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.cpp
index 979128370ee..99db56bfcef 100644
--- a/source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.cpp
+++ b/source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.cpp
@@ -106,7 +106,7 @@ int DummyPhysicsEnvironment::CreateConstraint(class PHY_IPhysicsController* ct
}
-void DummyPhysicsEnvironment::RemoveConstraint(int constraintid)
+void DummyPhysicsEnvironment::RemoveConstraintById(int constraintid)
{
if (constraintid)
{
diff --git a/source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.h b/source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.h
index cfc8841cac2..929345d7161 100644
--- a/source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.h
+++ b/source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.h
@@ -68,7 +68,7 @@ public:
float axis2X=0,float axis2Y=0,float axis2Z=0,int flag=0
);
- virtual void RemoveConstraint(int constraintid);
+ virtual void RemoveConstraintById(int constraintid);
//complex constraint for vehicles
virtual PHY_IVehicle* GetVehicleConstraint(int constraintId)
diff --git a/source/gameengine/Physics/common/PHY_IPhysicsController.h b/source/gameengine/Physics/common/PHY_IPhysicsController.h
index f9975484fa7..62b163536dd 100644
--- a/source/gameengine/Physics/common/PHY_IPhysicsController.h
+++ b/source/gameengine/Physics/common/PHY_IPhysicsController.h
@@ -32,6 +32,7 @@
#ifndef __PHY_IPHYSICSCONTROLLER_H__
#define __PHY_IPHYSICSCONTROLLER_H__
+#include <vector>
#include "PHY_IController.h"
class PHY_IMotionState;
@@ -89,6 +90,13 @@ class PHY_IPhysicsController : public PHY_IController
virtual void SetLinearVelocity(const MT_Vector3& lin_vel,bool local)=0;
virtual void ResolveCombinedVelocities(float linvelX,float linvelY,float linvelZ,float angVelX,float angVelY,float angVelZ) = 0;
+ virtual float GetLinearDamping() const=0;
+ virtual float GetAngularDamping() const=0;
+ virtual void SetLinearDamping(float damping)=0;
+ virtual void SetAngularDamping(float damping)=0;
+ virtual void SetDamping(float linear, float angular)=0;
+
+ virtual void RefreshCollisions() = 0;
virtual void SuspendDynamics(bool ghost=false)=0;
virtual void RestoreDynamics()=0;
@@ -117,6 +125,11 @@ class PHY_IPhysicsController : public PHY_IController
virtual float GetLinVelocityMax() const=0;
virtual void SetLinVelocityMax(float val) = 0;
+ virtual void SetAngularVelocityMin(float val) = 0;
+ virtual float GetAngularVelocityMin() const = 0;
+ virtual void SetAngularVelocityMax(float val) = 0;
+ virtual float GetAngularVelocityMax() const = 0;
+
MT_Vector3 GetWorldPosition(MT_Vector3& localpos);
// Shape control
@@ -126,9 +139,12 @@ class PHY_IPhysicsController : public PHY_IController
virtual bool IsDynamic() = 0;
virtual bool IsCompound() = 0;
+ virtual bool IsSuspended() const = 0;
virtual bool ReinstancePhysicsShape(KX_GameObject *from_gameobj, RAS_MeshObject* from_meshobj) = 0;
+ /* Method to replicate rigid body joint contraints for group instances. */
+ virtual void ReplicateConstraints(KX_GameObject *gameobj, std::vector<KX_GameObject*> constobj) = 0;
#ifdef WITH_CXX_GUARDEDALLOC
MEM_CXX_CLASS_ALLOC_FUNCS("GE:PHY_IPhysicsController")
diff --git a/source/gameengine/Physics/common/PHY_IPhysicsEnvironment.h b/source/gameengine/Physics/common/PHY_IPhysicsEnvironment.h
index dd762b02b4e..4b8d36285be 100644
--- a/source/gameengine/Physics/common/PHY_IPhysicsEnvironment.h
+++ b/source/gameengine/Physics/common/PHY_IPhysicsEnvironment.h
@@ -55,6 +55,7 @@ class KX_Scene;
struct PHY_ShapeProps;
struct PHY_MaterialProps;
class PHY_IMotionState;
+struct bRigidBodyJointConstraint;
/**
* pass back information from rayTest
@@ -167,7 +168,7 @@ class PHY_IPhysicsEnvironment
float axis1X=0,float axis1Y=0,float axis1Z=0,
float axis2X=0,float axis2Y=0,float axis2Z=0,int flag=0
)=0;
- virtual void RemoveConstraint(int constraintid)=0;
+ virtual void RemoveConstraintById(int constraintid) = 0;
virtual float GetAppliedImpulse(int constraintid) { return 0.0f; }
@@ -213,6 +214,9 @@ class PHY_IPhysicsEnvironment
bool isCompoundChild,
bool hasCompoundChildren) = 0;
+ /* Set the rigid body joints constraints values for converted objects and replicated group instances. */
+ virtual void SetupObjectConstraints(KX_GameObject *obj_src, KX_GameObject *obj_dest,
+ bRigidBodyJointConstraint *dat) {}
#ifdef WITH_CXX_GUARDEDALLOC
MEM_CXX_CLASS_ALLOC_FUNCS("GE:PHY_IPhysicsEnvironment")
diff --git a/source/gameengine/Physics/common/PHY_Pro.h b/source/gameengine/Physics/common/PHY_Pro.h
index 7c5d9c9638e..c9b91b06a3c 100644
--- a/source/gameengine/Physics/common/PHY_Pro.h
+++ b/source/gameengine/Physics/common/PHY_Pro.h
@@ -43,6 +43,8 @@ struct PHY_ShapeProps {
MT_Scalar m_friction_scaling[3]; // Scaling for anisotropic friction. Component in range [0, 1]
MT_Scalar m_clamp_vel_min; // Clamp the minimum velocity, this ensures an object moves at a minimum speed unless its stationary
MT_Scalar m_clamp_vel_max; // Clamp max velocity
+ MT_Scalar m_clamp_angvel_min; // Clamp the minimum angular velocity.
+ MT_Scalar m_clamp_angvel_max; // Clamp the maximum angular velocity.
bool m_do_anisotropic; // Should I do anisotropic friction?
bool m_do_fh; // Should the object have a linear Fh spring?
bool m_do_rot_fh; // Should the object have an angular Fh spring?
diff --git a/source/gameengine/Rasterizer/CMakeLists.txt b/source/gameengine/Rasterizer/CMakeLists.txt
index e254bf9b1c5..5bc3f22e327 100644
--- a/source/gameengine/Rasterizer/CMakeLists.txt
+++ b/source/gameengine/Rasterizer/CMakeLists.txt
@@ -32,6 +32,7 @@ set(INC
../../blender/blenlib
../../blender/blenkernel
../../../intern/container
+ ../../../intern/glew-mx
../../../intern/guardedalloc
../../../intern/string
)
@@ -81,6 +82,6 @@ set(SRC
RAS_OpenGLFilters/RAS_Sobel2DFilter.h
)
-add_definitions(-DGLEW_STATIC)
+add_definitions(${GL_DEFINITIONS})
blender_add_lib(ge_rasterizer "${SRC}" "${INC}" "${INC_SYS}")
diff --git a/source/gameengine/Rasterizer/RAS_2DFilterManager.cpp b/source/gameengine/Rasterizer/RAS_2DFilterManager.cpp
index abbe65738d4..cedc27c3b92 100644
--- a/source/gameengine/Rasterizer/RAS_2DFilterManager.cpp
+++ b/source/gameengine/Rasterizer/RAS_2DFilterManager.cpp
@@ -43,11 +43,11 @@
#include "RAS_2DFilterManager.h"
#include <iostream>
-#include "GL/glew.h"
+#include "glew-mx.h"
#include <stdio.h>
-#include "Value.h"
+#include "EXP_Value.h"
RAS_2DFilterManager::RAS_2DFilterManager():
texturewidth(-1), textureheight(-1),
@@ -75,6 +75,12 @@ texturewidth(-1), textureheight(-1),
RAS_2DFilterManager::~RAS_2DFilterManager()
{
FreeTextures();
+
+ for (int passindex = 0; passindex < MAX_RENDER_PASS; passindex++) {
+ if (m_filters[passindex]) {
+ glDeleteObjectARB(m_filters[passindex]);
+ }
+ }
}
void RAS_2DFilterManager::PrintShaderErrors(unsigned int shader, const char *task, const char *code)
@@ -119,11 +125,10 @@ unsigned int RAS_2DFilterManager::CreateShaderProgram(const char* shadersource)
glGetObjectParameterivARB(fShader, GL_COMPILE_STATUS, &success);
- if (!success)
- {
+ if (!success) {
/*Shader Comile Error*/
PrintShaderErrors(fShader, "compile", shadersource);
- return 0;
+ goto fail;
}
program = glCreateProgramObjectARB();
@@ -131,23 +136,37 @@ unsigned int RAS_2DFilterManager::CreateShaderProgram(const char* shadersource)
glLinkProgramARB(program);
glGetObjectParameterivARB(program, GL_LINK_STATUS, &success);
- if (!success)
- {
+ if (!success) {
/*Program Link Error*/
PrintShaderErrors(fShader, "link", shadersource);
- return 0;
+ goto fail;
}
glValidateProgramARB(program);
glGetObjectParameterivARB(program, GL_VALIDATE_STATUS, &success);
- if (!success)
- {
+ if (!success) {
/*Program Validation Error*/
PrintShaderErrors(fShader, "validate", shadersource);
- return 0;
+ goto fail;
+ }
+
+ /* owned by 'program' */
+ if (fShader) {
+ glDeleteObjectARB(fShader);
}
return program;
+
+
+fail:
+ if (fShader) {
+ glDeleteObjectARB(fShader);
+ }
+
+ if (program) {
+ glDeleteObjectARB(program);
+ }
+ return 0;
}
unsigned int RAS_2DFilterManager::CreateShaderProgram(int filtermode)
@@ -257,10 +276,24 @@ void RAS_2DFilterManager::StartShaderProgram(int passindex)
for (i=0; i<objProperties; i++)
{
uniformLoc = glGetUniformLocationARB(m_filters[passindex], m_properties[passindex][i]);
- if (uniformLoc != -1)
- {
- float value = ((CValue*)m_gameObjects[passindex])->GetPropertyNumber(m_properties[passindex][i], 0.0);
- glUniform1fARB(uniformLoc,value);
+
+ if (uniformLoc == -1)
+ continue;
+
+ CValue *property = ((CValue *)m_gameObjects[passindex])->GetProperty(m_properties[passindex][i]);
+
+ if (!property)
+ continue;
+
+ switch (property->GetValueType()) {
+ case VALUE_INT_TYPE:
+ glUniform1iARB(uniformLoc, property->GetNumber());
+ break;
+ case VALUE_FLOAT_TYPE:
+ glUniform1fARB(uniformLoc, property->GetNumber());
+ break;
+ default:
+ break;
}
}
}
diff --git a/source/gameengine/Rasterizer/RAS_CameraData.h b/source/gameengine/Rasterizer/RAS_CameraData.h
index 7a6bb541a1a..e2024a4a55d 100644
--- a/source/gameengine/Rasterizer/RAS_CameraData.h
+++ b/source/gameengine/Rasterizer/RAS_CameraData.h
@@ -39,6 +39,8 @@ struct RAS_CameraData
float m_sensor_x;
float m_sensor_y;
short m_sensor_fit;
+ float m_shift_x;
+ float m_shift_y;
float m_clipstart;
float m_clipend;
bool m_perspective;
@@ -50,6 +52,7 @@ struct RAS_CameraData
float m_focallength;
RAS_CameraData(float lens = 35.0, float scale = 6.0, float sensor_x = 32.0, float sensor_y = 18.0, short sensor_fit = 0,
+ float shift_x = 0.0, float shift_y = 0.0,
float clipstart = 0.1, float clipend = 5000.0, bool perspective = true,
float focallength = 3.0, bool viewport = false, int viewportleft = 0, int viewportbottom = 0,
int viewportright = 0, int viewporttop = 0) :
@@ -58,6 +61,8 @@ struct RAS_CameraData
m_sensor_x(sensor_x),
m_sensor_y(sensor_y),
m_sensor_fit(sensor_fit),
+ m_shift_x(shift_x),
+ m_shift_y(shift_y),
m_clipstart(clipstart),
m_clipend(clipend),
m_perspective(perspective),
diff --git a/source/gameengine/Rasterizer/RAS_FramingManager.cpp b/source/gameengine/Rasterizer/RAS_FramingManager.cpp
index d1a801c52f8..c5f15c9ad21 100644
--- a/source/gameengine/Rasterizer/RAS_FramingManager.cpp
+++ b/source/gameengine/Rasterizer/RAS_FramingManager.cpp
@@ -41,15 +41,21 @@ ComputeDefaultFrustum(
const float lens,
const float sensor_x, const float sensor_y,
const short sensor_fit,
+ const float shift_x,
+ const float shift_y,
const float design_aspect_ratio,
RAS_FrameFrustum & frustum
) {
+ float size;
float halfSize;
float sizeX;
float sizeY;
+ float offsetX;
+ float offsetY;
if (sensor_fit==RAS_SENSORFIT_AUTO) {
- halfSize = (sensor_x / 2.f) * camnear / lens;
+ size = sensor_x * camnear / lens;
+ halfSize = size * 0.5f;
if (design_aspect_ratio > 1.f) {
// halfsize defines the width
@@ -62,20 +68,25 @@ ComputeDefaultFrustum(
}
}
else if (sensor_fit==RAS_SENSORFIT_HOR) {
- halfSize = (sensor_x / 2.f) * camnear / lens;
+ size = sensor_x * camnear / lens;
+ halfSize = size * 0.5f;
sizeX = halfSize;
sizeY = halfSize/design_aspect_ratio;
}
else {
- halfSize = (sensor_y / 2.f) * camnear / lens;
+ size = sensor_y * camnear / lens;
+ halfSize = size * 0.5f;
sizeX = halfSize * design_aspect_ratio;
sizeY = halfSize;
}
-
- frustum.x2 = sizeX;
- frustum.x1 = -frustum.x2;
- frustum.y2 = sizeY;
- frustum.y1 = -frustum.y2;
+
+ offsetX = size * shift_x;
+ offsetY = size * shift_y;
+
+ frustum.x2 = sizeX + offsetX;
+ frustum.x1 = -sizeX + offsetX;
+ frustum.y2 = sizeY + offsetY;
+ frustum.y1 = -sizeY + offsetY;
frustum.camnear = camnear;
frustum.camfar = camfar;
}
@@ -88,12 +99,16 @@ ComputeDefaultOrtho(
const float scale,
const float design_aspect_ratio,
const short sensor_fit,
+ const float shift_x,
+ const float shift_y,
RAS_FrameFrustum & frustum
)
{
float halfSize = scale*0.5f;
float sizeX;
float sizeY;
+ float offsetX;
+ float offsetY;
if (sensor_fit==RAS_SENSORFIT_AUTO) {
if (design_aspect_ratio > 1.f) {
@@ -114,11 +129,14 @@ ComputeDefaultOrtho(
sizeX = halfSize * design_aspect_ratio;
sizeY = halfSize;
}
-
- frustum.x2 = sizeX;
- frustum.x1 = -frustum.x2;
- frustum.y2 = sizeY;
- frustum.y1 = -frustum.y2;
+
+ offsetX = scale * shift_x;
+ offsetY = scale * shift_y;
+
+ frustum.x2 = sizeX + offsetX;
+ frustum.x1 = -sizeX + offsetX;
+ frustum.y2 = sizeY + offsetY;
+ frustum.y1 = -sizeY + offsetY;
frustum.camnear = camnear;
frustum.camfar = camfar;
}
@@ -221,6 +239,8 @@ ComputeFrustum(
const RAS_Rect &viewport,
const float lens,
const float sensor_x, const float sensor_y, const short sensor_fit,
+ const float shift_x,
+ const float shift_y,
const float camnear,
const float camfar,
RAS_FrameFrustum &frustum
@@ -249,6 +269,8 @@ ComputeFrustum(
sensor_x,
sensor_y,
sensor_fit,
+ shift_x,
+ shift_y,
design_aspect_ratio,
frustum
);
@@ -315,6 +337,8 @@ RAS_FramingManager::
const float camnear,
const float camfar,
const short sensor_fit,
+ const float shift_x,
+ const float shift_y,
RAS_FrameFrustum &frustum
)
{
@@ -340,6 +364,8 @@ RAS_FramingManager::
scale,
design_aspect_ratio,
sensor_fit,
+ shift_x,
+ shift_y,
frustum
);
diff --git a/source/gameengine/Rasterizer/RAS_FramingManager.h b/source/gameengine/Rasterizer/RAS_FramingManager.h
index 122f0ca46ec..5741a91939e 100644
--- a/source/gameengine/Rasterizer/RAS_FramingManager.h
+++ b/source/gameengine/Rasterizer/RAS_FramingManager.h
@@ -236,6 +236,8 @@ public :
const float camnear,
const float camfar,
const short sensor_fit,
+ const float shift_x,
+ const float shift_y,
RAS_FrameFrustum &frustum
);
@@ -247,6 +249,8 @@ public :
const RAS_Rect &viewport,
const float lens,
const float sensor_x, const float sensor_y, const short sensor_fit,
+ const float shift_x,
+ const float shift_y,
const float camnear,
const float camfar,
RAS_FrameFrustum &frustum
@@ -260,6 +264,8 @@ public :
const float lens,
const float sensor_x, const float sensor_y,
const short sensor_fit,
+ const float shift_x,
+ const float shift_y,
const float design_aspect_ratio,
RAS_FrameFrustum & frustum
);
@@ -272,6 +278,8 @@ public :
const float scale,
const float design_aspect_ratio,
const short sensor_fit,
+ const float shift_x,
+ const float shift_y,
RAS_FrameFrustum & frustum
);
diff --git a/source/gameengine/Rasterizer/RAS_ICanvas.h b/source/gameengine/Rasterizer/RAS_ICanvas.h
index 9e8a6e8ccf6..471c2c97fa1 100644
--- a/source/gameengine/Rasterizer/RAS_ICanvas.h
+++ b/source/gameengine/Rasterizer/RAS_ICanvas.h
@@ -113,8 +113,9 @@ public:
)=0;
virtual
- int
+ bool
GetSwapInterval(
+ int& intervalOut
)=0;
virtual
@@ -236,6 +237,8 @@ public:
const char* filename
)=0;
+ virtual void GetDisplayDimensions(int &width, int &height) = 0;
+
virtual
void
ResizeWindow(
diff --git a/source/gameengine/Rasterizer/RAS_IPolygonMaterial.cpp b/source/gameengine/Rasterizer/RAS_IPolygonMaterial.cpp
index 03f6e567771..d07b4910968 100644
--- a/source/gameengine/Rasterizer/RAS_IPolygonMaterial.cpp
+++ b/source/gameengine/Rasterizer/RAS_IPolygonMaterial.cpp
@@ -233,7 +233,7 @@ Image *RAS_IPolyMaterial::GetBlenderImage() const
{
return NULL;
}
-MTFace *RAS_IPolyMaterial::GetMTFace() const
+MTexPoly *RAS_IPolyMaterial::GetMTexPoly() const
{
return NULL;
}
diff --git a/source/gameengine/Rasterizer/RAS_IPolygonMaterial.h b/source/gameengine/Rasterizer/RAS_IPolygonMaterial.h
index 14223fc59bd..a34f7a9b390 100644
--- a/source/gameengine/Rasterizer/RAS_IPolygonMaterial.h
+++ b/source/gameengine/Rasterizer/RAS_IPolygonMaterial.h
@@ -41,7 +41,7 @@
#endif
class RAS_IRasterizer;
-struct MTFace;
+struct MTexPoly;
struct Material;
struct Image;
struct Scene;
@@ -167,7 +167,7 @@ public:
virtual Material* GetBlenderMaterial() const;
virtual Image* GetBlenderImage() const;
- virtual MTFace* GetMTFace() const;
+ virtual MTexPoly* GetMTexPoly() const;
virtual unsigned int* GetMCol() const;
virtual Scene* GetBlenderScene() const;
virtual void ReleaseMaterial();
diff --git a/source/gameengine/Rasterizer/RAS_IRasterizer.h b/source/gameengine/Rasterizer/RAS_IRasterizer.h
index d7b52213191..7fbaf076d25 100644
--- a/source/gameengine/Rasterizer/RAS_IRasterizer.h
+++ b/source/gameengine/Rasterizer/RAS_IRasterizer.h
@@ -54,6 +54,7 @@ class RAS_ICanvas;
class RAS_IPolyMaterial;
class RAS_MeshSlot;
class RAS_ILightObject;
+class SCA_IScene;
typedef vector<unsigned short> KX_IndexArray;
typedef vector<RAS_TexVert> KX_VertexArray;
@@ -297,15 +298,11 @@ public:
/**
* Fog
*/
- virtual void SetFog(float start, float dist, float r, float g, float b) = 0;
- virtual void SetFogColor(float r, float g,float b) = 0;
- virtual void SetFogStart(float start) = 0;
- virtual void SetFogEnd(float end) = 0;
+ virtual void SetFog(short type, float start, float dist, float intensity, float color[3]) = 0;
virtual void DisplayFog() = 0;
- virtual void DisableFog() = 0;
- virtual bool IsFogEnabled() = 0;
+ virtual void EnableFog(bool enable) = 0;
- virtual void SetBackColor(float red, float green, float blue, float alpha) = 0;
+ virtual void SetBackColor(float color[3]) = 0;
/**
* \param drawingmode = KX_BOUNDINGBOX, KX_WIREFRAME, KX_SOLID, KX_SHADED or KX_TEXTURED.
@@ -380,7 +377,7 @@ public:
*/
virtual void SetEmissive(float eX, float eY, float eZ, float e) = 0;
- virtual void SetAmbientColor(float red, float green, float blue) = 0;
+ virtual void SetAmbientColor(float color[3]) = 0;
virtual void SetAmbient(float factor) = 0;
/**
@@ -388,10 +385,10 @@ public:
*/
virtual void SetPolygonOffset(float mult, float add) = 0;
- virtual void DrawDebugLine(const MT_Vector3 &from, const MT_Vector3 &to, const MT_Vector3& color) = 0;
- virtual void DrawDebugCircle(const MT_Vector3 &center, const MT_Scalar radius, const MT_Vector3 &color,
- const MT_Vector3 &normal, int nsector) = 0;
- virtual void FlushDebugShapes() = 0;
+ virtual void DrawDebugLine(SCA_IScene *scene, const MT_Vector3 &from, const MT_Vector3 &to, const MT_Vector3& color) = 0;
+ virtual void DrawDebugCircle(SCA_IScene *scene, const MT_Vector3 &center, const MT_Scalar radius,
+ const MT_Vector3 &color, const MT_Vector3 &normal, int nsector) = 0;
+ virtual void FlushDebugShapes(SCA_IScene *scene) = 0;
virtual void SetTexCoordNum(int num) = 0;
virtual void SetAttribNum(int num) = 0;
diff --git a/source/gameengine/Rasterizer/RAS_MaterialBucket.cpp b/source/gameengine/Rasterizer/RAS_MaterialBucket.cpp
index 4b5fc6510e0..2078fc99f2e 100644
--- a/source/gameengine/Rasterizer/RAS_MaterialBucket.cpp
+++ b/source/gameengine/Rasterizer/RAS_MaterialBucket.cpp
@@ -287,6 +287,16 @@ void RAS_MeshSlot::AddPolygonVertex(int offset)
m_endindex++;
}
+void RAS_MeshSlot::UpdateDisplayArraysOffset()
+{
+ unsigned int offset = 0;
+ for (unsigned short i = 0; i < m_displayArrays.size(); ++i) {
+ RAS_DisplayArray *darray = m_displayArrays[i];
+ darray->m_offset = offset;
+ offset += darray->m_vertex.size();
+ }
+}
+
void RAS_MeshSlot::SetDeformer(RAS_Deformer* deformer)
{
if (deformer && m_pDeformer != deformer) {
diff --git a/source/gameengine/Rasterizer/RAS_MaterialBucket.h b/source/gameengine/Rasterizer/RAS_MaterialBucket.h
index 007fdf240c4..1eee99f896b 100644
--- a/source/gameengine/Rasterizer/RAS_MaterialBucket.h
+++ b/source/gameengine/Rasterizer/RAS_MaterialBucket.h
@@ -80,6 +80,13 @@ public:
class RAS_DisplayArray
{
public:
+ /** The offset relation to the previous RAS_DisplayArray.
+ * For the user vertex are one big list but in C++ source
+ * it's two different lists if we use quads and triangles.
+ * So to fix that we add an offset.
+ * This value is set in UpdateDisplayArraysOffset().
+ */
+ unsigned int m_offset;
vector<RAS_TexVert> m_vertex;
vector<unsigned short> m_index;
/* LINE currently isn't used */
@@ -165,6 +172,9 @@ public:
int AddVertex(const RAS_TexVert& tv);
void AddPolygonVertex(int offset);
+ /// Update offset of each display array
+ void UpdateDisplayArraysOffset();
+
/* optimization */
bool Split(bool force=false);
bool Join(RAS_MeshSlot *target, MT_Scalar distance);
diff --git a/source/gameengine/Rasterizer/RAS_MeshObject.cpp b/source/gameengine/Rasterizer/RAS_MeshObject.cpp
index 54b15f07896..4360464ed32 100644
--- a/source/gameengine/Rasterizer/RAS_MeshObject.cpp
+++ b/source/gameengine/Rasterizer/RAS_MeshObject.cpp
@@ -465,6 +465,23 @@ void RAS_MeshObject::RemoveFromBuckets(void *clientobj)
}
}
+void RAS_MeshObject::EndConversion()
+{
+#if 0
+ m_sharedvertex_map.clear(); // SharedVertex
+ vector<vector<SharedVertex> > shared_null(0);
+ shared_null.swap( m_sharedvertex_map ); /* really free the memory */
+#endif
+
+ for (std::list<RAS_MeshMaterial>::iterator it = m_materials.begin();
+ it != m_materials.end();
+ ++it)
+ {
+ RAS_MeshSlot *ms = it->m_baseslot;
+ ms->UpdateDisplayArraysOffset();
+ }
+}
+
//void RAS_MeshObject::Transform(const MT_Transform& trans)
//{
//m_trans.translate(MT_Vector3(0,0,1));//.operator *=(trans);
diff --git a/source/gameengine/Rasterizer/RAS_MeshObject.h b/source/gameengine/Rasterizer/RAS_MeshObject.h
index 4f352379d39..a6f1a1cafc6 100644
--- a/source/gameengine/Rasterizer/RAS_MeshObject.h
+++ b/source/gameengine/Rasterizer/RAS_MeshObject.h
@@ -132,13 +132,7 @@ public:
virtual void AddMeshUser(void *clientobj, SG_QList *head, RAS_Deformer* deformer);
void RemoveFromBuckets(void *clientobj);
- void EndConversion() {
-#if 0
- m_sharedvertex_map.clear(); // SharedVertex
- vector<vector<SharedVertex> > shared_null(0);
- shared_null.swap( m_sharedvertex_map ); /* really free the memory */
-#endif
- }
+ void EndConversion();
/* colors */
void DebugColor(unsigned int abgr);
diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/CMakeLists.txt b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/CMakeLists.txt
index f0410ba891d..888a7114f50 100644
--- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/CMakeLists.txt
+++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/CMakeLists.txt
@@ -39,6 +39,7 @@ set(INC
../../../blender/gpu
../../../blender/makesdna
../../../../intern/container
+ ../../../../intern/glew-mx
../../../../intern/string
)
@@ -66,6 +67,6 @@ set(SRC
RAS_StorageVBO.h
)
-add_definitions(-DGLEW_STATIC)
+add_definitions(${GL_DEFINITIONS})
blender_add_lib(ge_oglrasterizer "${SRC}" "${INC}" "${INC_SYS}")
diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_GLExtensionManager.cpp b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_GLExtensionManager.cpp
index 32cc4ba9fea..bc22d68e218 100644
--- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_GLExtensionManager.cpp
+++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_GLExtensionManager.cpp
@@ -32,7 +32,7 @@
#include <iostream>
-#include "GL/glew.h"
+#include "glew-mx.h"
#include "RAS_GLExtensionManager.h"
diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.cpp b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.cpp
index e1dbd6f0a7f..34184f73953 100644
--- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.cpp
+++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.cpp
@@ -30,7 +30,7 @@
#include <windows.h>
#endif // WIN32
-#include "GL/glew.h"
+#include "glew-mx.h"
#include "RAS_MaterialBucket.h"
#include "RAS_TexVert.h"
@@ -79,10 +79,6 @@ void RAS_ListSlot::RemoveList()
void RAS_ListSlot::DrawList()
{
- if (m_flag &LIST_STREAM || m_flag& LIST_NOCREATE) {
- RemoveList();
- return;
- }
if (m_flag &LIST_MODIFY) {
if (m_flag &LIST_CREATE) {
if (m_list == 0) {
@@ -115,7 +111,7 @@ void RAS_ListSlot::SetModified(bool mod)
if (mod && !(m_flag & LIST_MODIFY)) {
spit("Modifying list (" << m_list << ")");
m_flag = m_flag &~ LIST_END;
- m_flag |= LIST_STREAM;
+ m_flag |= LIST_MODIFY;
}
}
diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.h b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.h
index d394c72b2a2..5e1c662bc17 100644
--- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.h
+++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.h
@@ -35,12 +35,9 @@ public:
enum RAS_ListSlotFlags {
LIST_CREATE =1,
LIST_MODIFY =2,
- LIST_STREAM =4,
- LIST_NOCREATE =8,
- LIST_BEGIN =16,
- LIST_END =32,
- LIST_REGEN =64,
- LIST_DERIVEDMESH=128,
+ LIST_BEGIN =4,
+ LIST_END =8,
+ LIST_DERIVEDMESH=16,
};
struct DerivedMesh;
diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLLight.cpp b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLLight.cpp
index e1b7a2151c5..4ac1c9c4ebb 100644
--- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLLight.cpp
+++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLLight.cpp
@@ -25,9 +25,10 @@
* ***** END GPL LICENSE BLOCK *****
*/
+#include "glew-mx.h"
+
#include <stdio.h>
-#include "GL/glew.h"
#include "RAS_OpenGLLight.h"
#include "RAS_OpenGLRasterizer.h"
diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp
index 0960fdaab4f..1758b7abf9f 100644
--- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp
+++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp
@@ -35,7 +35,7 @@
#include "RAS_OpenGLRasterizer.h"
-#include "GL/glew.h"
+#include "glew-mx.h"
#include "RAS_ICanvas.h"
#include "RAS_Rect.h"
@@ -60,7 +60,7 @@ extern "C"{
// XXX Clean these up <<<
-#include "Value.h"
+#include "EXP_Value.h"
#include "KX_Scene.h"
#include "KX_RayCast.h"
#include "KX_GameObject.h"
@@ -99,9 +99,9 @@ RAS_OpenGLRasterizer::RAS_OpenGLRasterizer(RAS_ICanvas* canvas, int storage)
m_motionblur(0),
m_motionblurvalue(-1.0),
m_usingoverrideshader(false),
- m_clientobject(NULL),
- m_auxilaryClientInfo(NULL),
- m_drawingmode(KX_TEXTURED),
+ m_clientobject(NULL),
+ m_auxilaryClientInfo(NULL),
+ m_drawingmode(KX_TEXTURED),
m_texco_num(0),
m_attrib_num(0),
//m_last_alphablend(GPU_BLEND_SOLID),
@@ -194,113 +194,52 @@ bool RAS_OpenGLRasterizer::Init()
}
-void RAS_OpenGLRasterizer::SetAmbientColor(float red, float green, float blue)
+void RAS_OpenGLRasterizer::SetAmbientColor(float color[3])
{
- m_ambr = red;
- m_ambg = green;
- m_ambb = blue;
+ m_ambr = color[0];
+ m_ambg = color[1];
+ m_ambb = color[2];
}
-
void RAS_OpenGLRasterizer::SetAmbient(float factor)
{
- float ambient[] = { m_ambr*factor, m_ambg*factor, m_ambb*factor, 1.0f };
+ float ambient[] = {m_ambr * factor, m_ambg * factor, m_ambb * factor, 1.0f};
glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambient);
}
-
-void RAS_OpenGLRasterizer::SetBackColor(float red,
- float green,
- float blue,
- float alpha)
-{
- m_redback = red;
- m_greenback = green;
- m_blueback = blue;
- m_alphaback = alpha;
-}
-
-
-
-void RAS_OpenGLRasterizer::SetFogColor(float r,
- float g,
- float b)
+void RAS_OpenGLRasterizer::SetBackColor(float color[3])
{
- m_fogr = r;
- m_fogg = g;
- m_fogb = b;
- m_fogenabled = true;
+ m_redback = color[0];
+ m_greenback = color[1];
+ m_blueback = color[2];
+ m_alphaback = 1.0f;
}
-
-
-void RAS_OpenGLRasterizer::SetFogStart(float start)
+void RAS_OpenGLRasterizer::SetFog(short type, float start, float dist, float intensity, float color[3])
{
- m_fogstart = start;
- m_fogenabled = true;
+ float params[4] = {color[0], color[1], color[2], 1.0f};
+ glFogi(GL_FOG_MODE, GL_LINEAR);
+ glFogf(GL_FOG_DENSITY, intensity / 10.0f);
+ glFogf(GL_FOG_START, start);
+ glFogf(GL_FOG_END, start + dist);
+ glFogfv(GL_FOG_COLOR, params);
}
-
-
-void RAS_OpenGLRasterizer::SetFogEnd(float fogend)
+void RAS_OpenGLRasterizer::EnableFog(bool enable)
{
- m_fogdist = fogend;
- m_fogenabled = true;
+ m_fogenabled = enable;
}
-
-
-void RAS_OpenGLRasterizer::SetFog(float start,
- float dist,
- float r,
- float g,
- float b)
-{
- m_fogstart = start;
- m_fogdist = dist;
- m_fogr = r;
- m_fogg = g;
- m_fogb = b;
- m_fogenabled = true;
-}
-
-
-
-void RAS_OpenGLRasterizer::DisableFog()
-{
- m_fogenabled = false;
-}
-
-bool RAS_OpenGLRasterizer::IsFogEnabled()
-{
- return m_fogenabled;
-}
-
-
void RAS_OpenGLRasterizer::DisplayFog()
{
- if ((m_drawingmode >= KX_SOLID) && m_fogenabled)
- {
- float params[5];
- glFogi(GL_FOG_MODE, GL_LINEAR);
- glFogf(GL_FOG_DENSITY, 0.1f);
- glFogf(GL_FOG_START, m_fogstart);
- glFogf(GL_FOG_END, m_fogstart + m_fogdist);
- params[0] = m_fogr;
- params[1] = m_fogg;
- params[2] = m_fogb;
- params[3] = 0.0;
- glFogfv(GL_FOG_COLOR, params);
+ if ((m_drawingmode >= KX_SOLID) && m_fogenabled) {
glEnable(GL_FOG);
- }
- else
- {
+ }
+ else {
glDisable(GL_FOG);
}
}
-
-
bool RAS_OpenGLRasterizer::SetMaterial(const RAS_IPolyMaterial& mat)
{
return mat.Activate(this, m_materialCachingInfo);
@@ -417,9 +356,10 @@ void RAS_OpenGLRasterizer::ClearCachingInfo(void)
m_materialCachingInfo = 0;
}
-void RAS_OpenGLRasterizer::FlushDebugShapes()
+void RAS_OpenGLRasterizer::FlushDebugShapes(SCA_IScene *scene)
{
- if (m_debugShapes.empty())
+ std::vector<OglDebugShape> &debugShapes = m_debugShapes[scene];
+ if (debugShapes.empty())
return;
// DrawDebugLines
@@ -433,28 +373,26 @@ void RAS_OpenGLRasterizer::FlushDebugShapes()
//draw lines
glBegin(GL_LINES);
- for (unsigned int i=0;i<m_debugShapes.size();i++)
- {
- if (m_debugShapes[i].m_type != OglDebugShape::LINE)
+ for (unsigned int i = 0; i < debugShapes.size(); i++) {
+ if (debugShapes[i].m_type != OglDebugShape::LINE)
continue;
- glColor4f(m_debugShapes[i].m_color[0],m_debugShapes[i].m_color[1],m_debugShapes[i].m_color[2],1.f);
- const MT_Scalar* fromPtr = &m_debugShapes[i].m_pos.x();
- const MT_Scalar* toPtr= &m_debugShapes[i].m_param.x();
+ glColor4f(debugShapes[i].m_color[0], debugShapes[i].m_color[1], debugShapes[i].m_color[2], 1.0f);
+ const MT_Scalar *fromPtr = &debugShapes[i].m_pos.x();
+ const MT_Scalar *toPtr= &debugShapes[i].m_param.x();
glVertex3dv(fromPtr);
glVertex3dv(toPtr);
}
glEnd();
//draw circles
- for (unsigned int i=0;i<m_debugShapes.size();i++)
- {
- if (m_debugShapes[i].m_type != OglDebugShape::CIRCLE)
+ for (unsigned int i = 0; i < debugShapes.size(); i++) {
+ if (debugShapes[i].m_type != OglDebugShape::CIRCLE)
continue;
glBegin(GL_LINE_LOOP);
- glColor4f(m_debugShapes[i].m_color[0],m_debugShapes[i].m_color[1],m_debugShapes[i].m_color[2],1.f);
+ glColor4f(debugShapes[i].m_color[0], debugShapes[i].m_color[1], debugShapes[i].m_color[2], 1.0f);
static const MT_Vector3 worldUp(0.0, 0.0, 1.0);
- MT_Vector3 norm = m_debugShapes[i].m_param;
+ MT_Vector3 norm = debugShapes[i].m_param;
MT_Matrix3x3 tr;
if (norm.fuzzyZero() || norm == worldUp)
{
@@ -469,14 +407,14 @@ void RAS_OpenGLRasterizer::FlushDebugShapes()
yaxis.x(), yaxis.y(), yaxis.z(),
norm.x(), norm.y(), norm.z());
}
- MT_Scalar rad = m_debugShapes[i].m_param2.x();
- int n = (int) m_debugShapes[i].m_param2.y();
+ MT_Scalar rad = debugShapes[i].m_param2.x();
+ int n = (int)debugShapes[i].m_param2.y();
for (int j = 0; j<n; j++)
{
MT_Scalar theta = j*M_PI*2/n;
MT_Vector3 pos(cos(theta) * rad, sin(theta) * rad, 0.0);
pos = pos*tr;
- pos += m_debugShapes[i].m_pos;
+ pos += debugShapes[i].m_pos;
const MT_Scalar* posPtr = &pos.x();
glVertex3dv(posPtr);
}
@@ -486,13 +424,11 @@ void RAS_OpenGLRasterizer::FlushDebugShapes()
if (light) glEnable(GL_LIGHTING);
if (tex) glEnable(GL_TEXTURE_2D);
- m_debugShapes.clear();
+ debugShapes.clear();
}
void RAS_OpenGLRasterizer::EndFrame()
{
- FlushDebugShapes();
-
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
glDisable(GL_MULTISAMPLE_ARB);
@@ -731,7 +667,9 @@ void RAS_OpenGLRasterizer::IndexPrimitives_3DText(RAS_MeshSlot& ms,
// triangle and quad text drawing
for (i=0; i<it.totindex; i+=numvert)
{
- float v[4][3];
+ float v[4][3];
+ const float *v_ptr[4] = {NULL};
+ const float *uv_ptr[4] = {NULL};
int glattrib, unit;
for (j=0; j<numvert; j++) {
@@ -740,6 +678,9 @@ void RAS_OpenGLRasterizer::IndexPrimitives_3DText(RAS_MeshSlot& ms,
v[j][0] = vertex->getXYZ()[0];
v[j][1] = vertex->getXYZ()[1];
v[j][2] = vertex->getXYZ()[2];
+ v_ptr[j] = v[j];
+
+ uv_ptr[j] = vertex->getUV(0);
}
// find the right opengl attribute
@@ -749,7 +690,9 @@ void RAS_OpenGLRasterizer::IndexPrimitives_3DText(RAS_MeshSlot& ms,
if (m_attrib[unit] == RAS_TEXCO_UV)
glattrib = unit;
- GPU_render_text(polymat->GetMTFace(), polymat->GetDrawingMode(), mytext, mytext.Length(), polymat->GetMCol(), v[0], v[1], v[2], v[3], glattrib);
+ GPU_render_text(
+ polymat->GetMTexPoly(), polymat->GetDrawingMode(), mytext, mytext.Length(), polymat->GetMCol(),
+ v_ptr, uv_ptr, glattrib);
ClearCachingInfo();
}
@@ -1135,12 +1078,17 @@ void RAS_OpenGLRasterizer::SetMipmapping(MipmapOption val)
RAS_IRasterizer::MipmapOption RAS_OpenGLRasterizer::GetMipmapping()
{
- if (GPU_get_linear_mipmap())
- return RAS_IRasterizer::RAS_MIPMAP_LINEAR;
- else if (GPU_get_mipmap())
- return RAS_IRasterizer::RAS_MIPMAP_NEAREST;
- else
+ if (GPU_get_mipmap()) {
+ if (GPU_get_linear_mipmap()) {
+ return RAS_IRasterizer::RAS_MIPMAP_LINEAR;
+ }
+ else {
+ return RAS_IRasterizer::RAS_MIPMAP_NEAREST;
+ }
+ }
+ else {
return RAS_IRasterizer::RAS_MIPMAP_NONE;
+ }
}
void RAS_OpenGLRasterizer::SetUsingOverrideShader(bool val)
@@ -1269,28 +1217,32 @@ void RAS_OpenGLRasterizer::RemoveLight(RAS_ILightObject* lightobject)
bool RAS_OpenGLRasterizer::RayHit(struct KX_ClientObjectInfo *client, KX_RayCast *result, void * const data)
{
- double* const oglmatrix = (double* const) data;
+ if (result->m_hitMesh) {
+ double* const oglmatrix = (double* const) data;
- RAS_Polygon* poly = result->m_hitMesh->GetPolygon(result->m_hitPolygon);
- if (!poly->IsVisible())
- return false;
+ RAS_Polygon* poly = result->m_hitMesh->GetPolygon(result->m_hitPolygon);
+ if (!poly->IsVisible())
+ return false;
- MT_Point3 resultpoint(result->m_hitPoint);
- MT_Vector3 resultnormal(result->m_hitNormal);
- MT_Vector3 left(oglmatrix[0],oglmatrix[1],oglmatrix[2]);
- MT_Vector3 dir = -(left.cross(resultnormal)).safe_normalized();
- left = (dir.cross(resultnormal)).safe_normalized();
- // for the up vector, we take the 'resultnormal' returned by the physics
-
- double maat[16] = {left[0], left[1], left[2], 0,
- dir[0], dir[1], dir[2], 0,
- resultnormal[0], resultnormal[1], resultnormal[2], 0,
- 0, 0, 0, 1};
-
- glTranslated(resultpoint[0],resultpoint[1],resultpoint[2]);
- //glMultMatrixd(oglmatrix);
- glMultMatrixd(maat);
- return true;
+ MT_Vector3 resultnormal(result->m_hitNormal);
+ MT_Vector3 left(oglmatrix[0],oglmatrix[1],oglmatrix[2]);
+ MT_Vector3 dir = -(left.cross(resultnormal)).safe_normalized();
+ left = (dir.cross(resultnormal)).safe_normalized();
+ // for the up vector, we take the 'resultnormal' returned by the physics
+
+ double maat[16] = {left[0], left[1], left[2], 0,
+ dir[0], dir[1], dir[2], 0,
+ resultnormal[0], resultnormal[1], resultnormal[2], 0,
+ 0, 0, 0, 1};
+
+ glTranslated(oglmatrix[12],oglmatrix[13],oglmatrix[14]);
+ //glMultMatrixd(oglmatrix);
+ glMultMatrixd(maat);
+ return true;
+ }
+ else {
+ return false;
+ }
}
void RAS_OpenGLRasterizer::applyTransform(double* oglmatrix,int objectdrawmode )
@@ -1351,7 +1303,7 @@ void RAS_OpenGLRasterizer::applyTransform(double* oglmatrix,int objectdrawmode )
up[0], up[1], up[2], 0,
0, 0, 0, 1};
- glTranslated(objpos[0],objpos[1],objpos[2]);
+ glTranslatef(objpos[0],objpos[1],objpos[2]);
glMultMatrixd(maat);
}
diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.h b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.h
index 1334ddb2a26..ad49ebe5179 100644
--- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.h
+++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.h
@@ -38,6 +38,7 @@
#include "MT_CmMatrix4x4.h"
#include <vector>
+#include <map>
using namespace std;
#include "RAS_IRasterizer.h"
@@ -80,12 +81,7 @@ class RAS_OpenGLRasterizer : public RAS_IRasterizer
/* fogging vars */
bool m_fogenabled;
- float m_fogstart;
- float m_fogdist;
- float m_fogr;
- float m_fogg;
- float m_fogb;
-
+
float m_redback;
float m_greenback;
float m_blueback;
@@ -198,16 +194,12 @@ public:
virtual const MT_Point3& GetCameraPosition();
virtual bool GetCameraOrtho();
- virtual void SetFog(float start, float dist, float r, float g, float b);
- virtual void SetFogColor(float r, float g, float b);
- virtual void SetFogStart(float fogstart);
- virtual void SetFogEnd(float fogend);
- void DisableFog();
+ virtual void SetFog(short type, float start, float dist, float intensity, float color[3]);
+ virtual void EnableFog(bool enable);
virtual void DisplayFog();
- virtual bool IsFogEnabled();
- virtual void SetBackColor(float red, float green, float blue, float alpha);
-
+ virtual void SetBackColor(float color[3]);
+
virtual void SetDrawingMode(int drawingmode);
virtual int GetDrawingMode();
@@ -227,25 +219,25 @@ public:
virtual void SetDiffuse(float difX, float difY, float difZ, float diffuse);
virtual void SetEmissive(float eX, float eY, float eZ, float e);
- virtual void SetAmbientColor(float red, float green, float blue);
+ virtual void SetAmbientColor(float color[3]);
virtual void SetAmbient(float factor);
virtual void SetPolygonOffset(float mult, float add);
- virtual void FlushDebugShapes();
+ virtual void FlushDebugShapes(SCA_IScene *scene);
- virtual void DrawDebugLine(const MT_Vector3 &from,const MT_Vector3 &to, const MT_Vector3 &color)
+ virtual void DrawDebugLine(SCA_IScene *scene, const MT_Vector3 &from,const MT_Vector3 &to, const MT_Vector3 &color)
{
OglDebugShape line;
line.m_type = OglDebugShape::LINE;
line.m_pos= from;
line.m_param = to;
line.m_color = color;
- m_debugShapes.push_back(line);
+ m_debugShapes[scene].push_back(line);
}
- virtual void DrawDebugCircle(const MT_Vector3 &center, const MT_Scalar radius, const MT_Vector3 &color,
- const MT_Vector3 &normal, int nsector)
+ virtual void DrawDebugCircle(SCA_IScene *scene, const MT_Vector3 &center, const MT_Scalar radius,
+ const MT_Vector3 &color, const MT_Vector3 &normal, int nsector)
{
OglDebugShape line;
line.m_type = OglDebugShape::CIRCLE;
@@ -254,10 +246,11 @@ public:
line.m_color = color;
line.m_param2.x() = radius;
line.m_param2.y() = (float) nsector;
- m_debugShapes.push_back(line);
+ m_debugShapes[scene].push_back(line);
}
- std::vector <OglDebugShape> m_debugShapes;
+ // We store each debug shape by scene.
+ std::map<SCA_IScene *, std::vector<OglDebugShape> > m_debugShapes;
virtual void SetTexCoordNum(int num);
virtual void SetAttribNum(int num);
diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_StorageIM.cpp b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_StorageIM.cpp
index c8975c245cb..2cf6088629a 100644
--- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_StorageIM.cpp
+++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_StorageIM.cpp
@@ -29,7 +29,7 @@
#include "RAS_MaterialBucket.h"
#include "RAS_IPolygonMaterial.h"
-#include "GL/glew.h"
+#include "glew-mx.h"
#include "GPU_draw.h"
#include "GPU_extensions.h"
#include "GPU_material.h"
@@ -179,12 +179,12 @@ static int CheckTexfaceDM(void *mcol, int index)
}
*/
-static DMDrawOption CheckTexDM(MTFace *tface, const bool has_mcol, int matnr)
+static DMDrawOption CheckTexDM(MTexPoly *mtexpoly, const bool has_mcol, int matnr)
{
// index is the original face index, retrieve the polygon
if (matnr == current_blmat_nr &&
- (tface == NULL || tface->tpage == current_image)) {
+ (mtexpoly == NULL || mtexpoly->tpage == current_image)) {
// must handle color.
if (current_wireframe)
return DM_DRAW_OPTION_NO_MCOL;
@@ -236,7 +236,7 @@ void RAS_StorageIM::IndexPrimitivesInternal(RAS_MeshSlot& ms, bool multi)
Material* blmat = current_polymat->GetBlenderMaterial();
Scene* blscene = current_polymat->GetBlenderScene();
if (!wireframe && blscene && blmat)
- GPU_material_vertex_attributes(GPU_material_from_blender(blscene, blmat), &current_gpu_attribs);
+ GPU_material_vertex_attributes(GPU_material_from_blender(blscene, blmat, false), &current_gpu_attribs);
else
memset(&current_gpu_attribs, 0, sizeof(current_gpu_attribs));
// DM draw can mess up blending mode, restore at the end
diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_StorageVA.cpp b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_StorageVA.cpp
index 006c07b0491..c2980a6c15f 100644
--- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_StorageVA.cpp
+++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_StorageVA.cpp
@@ -27,7 +27,7 @@
#include "RAS_StorageVA.h"
-#include "GL/glew.h"
+#include "glew-mx.h"
RAS_StorageVA::RAS_StorageVA(int *texco_num, RAS_IRasterizer::TexCoGen *texco, int *attrib_num, RAS_IRasterizer::TexCoGen *attrib, int *attrib_layer) :
m_drawingmode(RAS_IRasterizer::KX_TEXTURED),
diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_StorageVBO.cpp b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_StorageVBO.cpp
index 6aa90fbd6ef..58f3d4c05da 100644
--- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_StorageVBO.cpp
+++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_StorageVBO.cpp
@@ -28,7 +28,7 @@
#include "RAS_StorageVBO.h"
#include "RAS_MeshObject.h"
-#include "GL/glew.h"
+#include "glew-mx.h"
VBO::VBO(RAS_DisplayArray *data, unsigned int indices)
{
diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_StorageVBO.h b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_StorageVBO.h
index 2fe0c32f399..f156722247c 100644
--- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_StorageVBO.h
+++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_StorageVBO.h
@@ -29,7 +29,7 @@
#define __KX_VERTEXBUFFEROBJECTSTORAGE
#include <map>
-#include "GL/glew.h"
+#include "glew-mx.h"
#include "RAS_IStorage.h"
#include "RAS_IRasterizer.h"
diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/SConscript b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/SConscript
index 0a7417656c6..ce520df2a21 100644
--- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/SConscript
+++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/SConscript
@@ -3,14 +3,16 @@ Import ('env')
sources = env.Glob('*.cpp')
-defs = [ 'GLEW_STATIC' ]
+defs = []
+defs += env['BF_GL_DEFINITIONS']
incs = [
'.',
'#intern/container',
'#intern/guardedalloc',
'#intern/string',
- '#extern/glew/include',
+ env['BF_GLEW_INC'],
+ '#/intern/glew-mx',
'#intern/moto/include',
'#source/blender/blenkernel',
'#source/blender/blenfont',
diff --git a/source/gameengine/Rasterizer/RAS_Polygon.cpp b/source/gameengine/Rasterizer/RAS_Polygon.cpp
index 1f23df90753..3274ded4406 100644
--- a/source/gameengine/Rasterizer/RAS_Polygon.cpp
+++ b/source/gameengine/Rasterizer/RAS_Polygon.cpp
@@ -62,9 +62,9 @@ RAS_TexVert *RAS_Polygon::GetVertex(int i)
return &m_darray->m_vertex[m_offset[i]];
}
-int RAS_Polygon::GetVertexOffset(int i)
+unsigned int RAS_Polygon::GetVertexOffsetAbsolute(unsigned short i)
{
- return m_offset[i];
+ return m_offset[i] + m_darray->m_offset;
}
/*
diff --git a/source/gameengine/Rasterizer/RAS_Polygon.h b/source/gameengine/Rasterizer/RAS_Polygon.h
index b18477a72d2..597e80ffdfb 100644
--- a/source/gameengine/Rasterizer/RAS_Polygon.h
+++ b/source/gameengine/Rasterizer/RAS_Polygon.h
@@ -72,8 +72,8 @@ public:
RAS_TexVert* GetVertex(int i);
void SetVertexOffset(int i, unsigned short offset);
- int GetVertexOffset(int i);
-
+ unsigned int GetVertexOffsetAbsolute(unsigned short i);
+
// each bit is for a visible edge, starting with bit 1 for the first edge, bit 2 for second etc.
// - Not used yet!
/* int GetEdgeCode();
diff --git a/source/gameengine/Rasterizer/RAS_texmatrix.cpp b/source/gameengine/Rasterizer/RAS_texmatrix.cpp
index 3203fcf9d6b..d30a3d3a75d 100644
--- a/source/gameengine/Rasterizer/RAS_texmatrix.cpp
+++ b/source/gameengine/Rasterizer/RAS_texmatrix.cpp
@@ -34,7 +34,7 @@
void RAS_CalcTexMatrix(RAS_TexVert p[3],MT_Point3& origin,MT_Vector3& udir,MT_Vector3& vdir)
{
-// precondition: 3 vertices are non-colinear
+// precondition: 3 vertices are non-collinear
MT_Vector3 vec1 = p[1].xyz()-p[0].xyz();
MT_Vector3 vec2 = p[2].xyz()-p[0].xyz();
diff --git a/source/gameengine/Rasterizer/SConscript b/source/gameengine/Rasterizer/SConscript
index 5c68ce63a3b..a643f46e39a 100644
--- a/source/gameengine/Rasterizer/SConscript
+++ b/source/gameengine/Rasterizer/SConscript
@@ -36,15 +36,18 @@ incs = [
'#intern/moto/include',
'#intern/container',
'#source/gameengine/BlenderRoutines',
- '#extern/glew/include',
+ env['BF_GLEW_INC'],
+ '#/intern/glew-mx',
'#source/gameengine/Expressions',
'#source/gameengine/SceneGraph',
'#source/blender/blenlib',
'#source/blender/blenkernel',
+ '#source/blender/gpu',
'#source/blender/makesdna',
]
-defs = ['GLEW_STATIC']
+defs = []
+defs += env['BF_GL_DEFINITIONS']
if env['WITH_BF_PYTHON']:
incs.extend(Split(env['BF_PYTHON_INC']))
diff --git a/source/gameengine/VideoTexture/CMakeLists.txt b/source/gameengine/VideoTexture/CMakeLists.txt
index 3ca3917cf6d..4be9a9abe5c 100644
--- a/source/gameengine/VideoTexture/CMakeLists.txt
+++ b/source/gameengine/VideoTexture/CMakeLists.txt
@@ -42,6 +42,7 @@ set(INC
../../blender/python/generic
../../../intern/container
../../../intern/ffmpeg
+ ../../../intern/glew-mx
../../../intern/guardedalloc
../../../intern/string
)
@@ -51,7 +52,7 @@ set(INC_SYS
${GLEW_INCLUDE_PATH}
)
-add_definitions(-DGLEW_STATIC)
+add_definitions(${GL_DEFINITIONS})
set(SRC
Exception.cpp
diff --git a/source/gameengine/VideoTexture/Exception.cpp b/source/gameengine/VideoTexture/Exception.cpp
index 804834af4cd..08616e0c41c 100644
--- a/source/gameengine/VideoTexture/Exception.cpp
+++ b/source/gameengine/VideoTexture/Exception.cpp
@@ -31,7 +31,7 @@
#include <sstream>
#include <fstream>
-#include "PyObjectPlus.h"
+#include "EXP_PyObjectPlus.h"
#include "Exception.h"
diff --git a/source/gameengine/VideoTexture/FilterBase.cpp b/source/gameengine/VideoTexture/FilterBase.cpp
index 97abe36bb81..5717a1edbcb 100644
--- a/source/gameengine/VideoTexture/FilterBase.cpp
+++ b/source/gameengine/VideoTexture/FilterBase.cpp
@@ -31,7 +31,7 @@
#include "FilterBase.h"
-#include "PyObjectPlus.h"
+#include "EXP_PyObjectPlus.h"
#include <structmember.h>
diff --git a/source/gameengine/VideoTexture/FilterBase.h b/source/gameengine/VideoTexture/FilterBase.h
index a1d199b1851..498917e2375 100644
--- a/source/gameengine/VideoTexture/FilterBase.h
+++ b/source/gameengine/VideoTexture/FilterBase.h
@@ -33,7 +33,7 @@
#include "Common.h"
-#include "PyObjectPlus.h"
+#include "EXP_PyObjectPlus.h"
#include "PyTypeList.h"
@@ -116,6 +116,10 @@ protected:
// otherwise return converted pixel
return m_previous->m_filter->convert(src, x, y, size, pixSize);
}
+
+#ifdef WITH_CXX_GUARDEDALLOC
+ MEM_CXX_CLASS_ALLOC_FUNCS("GE:FilterBase")
+#endif
};
diff --git a/source/gameengine/VideoTexture/FilterBlueScreen.cpp b/source/gameengine/VideoTexture/FilterBlueScreen.cpp
index 857da12c28d..a25d09e1eee 100644
--- a/source/gameengine/VideoTexture/FilterBlueScreen.cpp
+++ b/source/gameengine/VideoTexture/FilterBlueScreen.cpp
@@ -28,7 +28,7 @@
* \ingroup bgevideotex
*/
-#include "PyObjectPlus.h"
+#include "EXP_PyObjectPlus.h"
#include <structmember.h>
#include "FilterBlueScreen.h"
diff --git a/source/gameengine/VideoTexture/FilterColor.cpp b/source/gameengine/VideoTexture/FilterColor.cpp
index 26b5303e365..eed84a8580c 100644
--- a/source/gameengine/VideoTexture/FilterColor.cpp
+++ b/source/gameengine/VideoTexture/FilterColor.cpp
@@ -28,7 +28,7 @@
* \ingroup bgevideotex
*/
-#include "PyObjectPlus.h"
+#include "EXP_PyObjectPlus.h"
#include <structmember.h>
#include "FilterColor.h"
diff --git a/source/gameengine/VideoTexture/FilterNormal.cpp b/source/gameengine/VideoTexture/FilterNormal.cpp
index 78a09f8afac..3a5333710fd 100644
--- a/source/gameengine/VideoTexture/FilterNormal.cpp
+++ b/source/gameengine/VideoTexture/FilterNormal.cpp
@@ -28,7 +28,7 @@
* \ingroup bgevideotex
*/
-#include "PyObjectPlus.h"
+#include "EXP_PyObjectPlus.h"
#include <structmember.h>
#include "FilterNormal.h"
diff --git a/source/gameengine/VideoTexture/FilterSource.cpp b/source/gameengine/VideoTexture/FilterSource.cpp
index 1fac87f2b04..c8faa1f9f07 100644
--- a/source/gameengine/VideoTexture/FilterSource.cpp
+++ b/source/gameengine/VideoTexture/FilterSource.cpp
@@ -30,7 +30,7 @@
// implementation
-#include "PyObjectPlus.h"
+#include "EXP_PyObjectPlus.h"
#include <structmember.h>
#include "FilterSource.h"
diff --git a/source/gameengine/VideoTexture/ImageBase.cpp b/source/gameengine/VideoTexture/ImageBase.cpp
index 4109981a98c..8be152c7b8e 100644
--- a/source/gameengine/VideoTexture/ImageBase.cpp
+++ b/source/gameengine/VideoTexture/ImageBase.cpp
@@ -32,12 +32,12 @@
extern "C" {
#include "bgl.h"
}
-#include "GL/glew.h"
+#include "glew-mx.h"
#include <vector>
#include <string.h>
-#include "PyObjectPlus.h"
+#include "EXP_PyObjectPlus.h"
#include <structmember.h>
#include "FilterBase.h"
@@ -713,25 +713,18 @@ static int Image_getbuffer(PyImage *self, Py_buffer *view, int flags)
unsigned int * image;
int ret;
- try
- {
+ try {
// can throw in case of resize
image = self->m_image->getImage();
}
- catch (Exception & exp)
- {
- // cannot return -1, this creates a crash in Python, for now we will just return an empty buffer
+ catch (Exception & exp) {
exp.report();
- //return -1;
- goto error;
+ return -1;
}
- if (!image)
- {
- // same remark, see above
- //PyErr_SetString(PyExc_BufferError, "Image buffer is not available");
- //return -1;
- goto error;
+ if (!image) {
+ PyErr_SetString(PyExc_BufferError, "Image buffer is not available");
+ return -1;
}
if (view == NULL)
{
@@ -742,17 +735,6 @@ static int Image_getbuffer(PyImage *self, Py_buffer *view, int flags)
if (ret >= 0)
self->m_image->m_exports++;
return ret;
-
-error:
- // Return a empty buffer to avoid a crash in Python 3.1
- // The bug is fixed in Python SVN 77916, as soon as the python revision used by Blender is
- // updated, you can simply return -1 and set the error
- static char* buf = (char *)"";
- ret = PyBuffer_FillInfo(view, (PyObject *)self, buf, 0, 0, flags);
- if (ret >= 0)
- self->m_image->m_exports++;
- return ret;
-
}
static void Image_releaseBuffer(PyImage *self, Py_buffer *buffer)
diff --git a/source/gameengine/VideoTexture/ImageBase.h b/source/gameengine/VideoTexture/ImageBase.h
index 50dc8c10ec6..f646d145365 100644
--- a/source/gameengine/VideoTexture/ImageBase.h
+++ b/source/gameengine/VideoTexture/ImageBase.h
@@ -34,7 +34,7 @@
#include "Common.h"
#include <vector>
-#include "PyObjectPlus.h"
+#include "EXP_PyObjectPlus.h"
#include "PyTypeList.h"
diff --git a/source/gameengine/VideoTexture/ImageBuff.cpp b/source/gameengine/VideoTexture/ImageBuff.cpp
index 705d9136cbe..77270865b17 100644
--- a/source/gameengine/VideoTexture/ImageBuff.cpp
+++ b/source/gameengine/VideoTexture/ImageBuff.cpp
@@ -30,7 +30,7 @@
// implementation
-#include "PyObjectPlus.h"
+#include "EXP_PyObjectPlus.h"
#include <structmember.h>
#include "ImageBuff.h"
diff --git a/source/gameengine/VideoTexture/ImageMix.cpp b/source/gameengine/VideoTexture/ImageMix.cpp
index dc93bf03423..973be52e0fc 100644
--- a/source/gameengine/VideoTexture/ImageMix.cpp
+++ b/source/gameengine/VideoTexture/ImageMix.cpp
@@ -31,7 +31,7 @@
// implementation
-#include "PyObjectPlus.h"
+#include "EXP_PyObjectPlus.h"
#include <structmember.h>
#include "ImageMix.h"
diff --git a/source/gameengine/VideoTexture/ImageRender.cpp b/source/gameengine/VideoTexture/ImageRender.cpp
index 8c6dcf45d6f..9086b042537 100644
--- a/source/gameengine/VideoTexture/ImageRender.cpp
+++ b/source/gameengine/VideoTexture/ImageRender.cpp
@@ -30,13 +30,13 @@
// implementation
-#include "PyObjectPlus.h"
+#include "EXP_PyObjectPlus.h"
#include <structmember.h>
#include <float.h>
#include <math.h>
-#include "GL/glew.h"
+#include "glew-mx.h"
#include "KX_PythonInit.h"
#include "DNA_scene_types.h"
@@ -75,8 +75,8 @@ ImageRender::ImageRender (KX_Scene *scene, KX_Camera * camera) :
m_mirrorHalfWidth(0.f),
m_mirrorHalfHeight(0.f)
{
- // initialize background color
- setBackground(0, 0, 255, 255);
+ // initialize background color to scene background color as default
+ setBackgroundFromScene(m_scene);
// retrieve rendering objects
m_engine = KX_GetActiveEngine();
m_rasterizer = m_engine->GetRasterizer();
@@ -90,14 +90,33 @@ ImageRender::~ImageRender (void)
m_camera->Release();
}
+// get background color
+float ImageRender::getBackground (int idx)
+{
+ return (idx < 0 || idx > 3) ? 0.0f : m_background[idx] * 255.0f;
+}
// set background color
-void ImageRender::setBackground (int red, int green, int blue, int alpha)
+void ImageRender::setBackground (float red, float green, float blue, float alpha)
+{
+ m_background[0] = (red < 0.0f) ? 0.0f : (red > 255.0f) ? 1.0f : red / 255.0f;
+ m_background[1] = (green < 0.0f) ? 0.0f : (green > 255.0f) ? 1.0f : green / 255.0f;
+ m_background[2] = (blue < 0.0f) ? 0.0f : (blue > 255.0f) ? 1.0f : blue / 255.0f;
+ m_background[3] = (alpha < 0.0f) ? 0.0f : (alpha > 255.0f) ? 1.0f : alpha / 255.0f;
+}
+
+// set background color from scene
+void ImageRender::setBackgroundFromScene (KX_Scene *scene)
{
- m_background[0] = (red < 0) ? 0.f : (red > 255) ? 1.f : float(red)/255.f;
- m_background[1] = (green < 0) ? 0.f : (green > 255) ? 1.f : float(green)/255.f;
- m_background[2] = (blue < 0) ? 0.f : (blue > 255) ? 1.f : float(blue)/255.f;
- m_background[3] = (alpha < 0) ? 0.f : (alpha > 255) ? 1.f : float(alpha)/255.f;
+ if (scene) {
+ const float *background_color = scene->GetWorldInfo()->getBackColorConverted();
+ copy_v3_v3(m_background, background_color);
+ m_background[3] = 1.0f;
+ }
+ else {
+ const float blue_color[] = {0.0f, 0.0f, 1.0f, 1.0f};
+ copy_v4_v4(m_background, blue_color);
+ }
}
@@ -200,7 +219,7 @@ void ImageRender::Render()
m_canvas->ClearColor(m_background[0], m_background[1], m_background[2], m_background[3]);
m_canvas->ClearBuffer(RAS_ICanvas::COLOR_BUFFER|RAS_ICanvas::DEPTH_BUFFER);
m_rasterizer->BeginFrame(m_engine->GetClockTime());
- m_engine->SetWorldSettings(m_scene->GetWorldInfo());
+ m_scene->GetWorldInfo()->UpdateWorldSettings();
m_rasterizer->SetAuxilaryClientInfo(m_scene);
m_rasterizer->DisplayFog();
// matrix calculation, don't apply any of the stereo mode
@@ -221,6 +240,8 @@ void ImageRender::Render()
float lens = m_camera->GetLens();
float sensor_x = m_camera->GetSensorWidth();
float sensor_y = m_camera->GetSensorHeight();
+ float shift_x = m_camera->GetShiftHorizontal();
+ float shift_y = m_camera->GetShiftVertical();
bool orthographic = !m_camera->GetCameraData()->m_perspective;
float nearfrust = m_camera->GetCameraNear();
float farfrust = m_camera->GetCameraFar();
@@ -241,6 +262,8 @@ void ImageRender::Render()
m_camera->GetScale(),
aspect_ratio,
m_camera->GetSensorFit(),
+ shift_x,
+ shift_y,
frustrum
);
@@ -255,6 +278,8 @@ void ImageRender::Render()
sensor_x,
sensor_y,
RAS_SENSORFIT_AUTO,
+ shift_x,
+ shift_y,
aspect_ratio,
frustrum);
@@ -272,9 +297,16 @@ void ImageRender::Render()
// restore the stereo mode now that the matrix is computed
m_rasterizer->SetStereoMode(stereomode);
+ if (stereomode == RAS_IRasterizer::RAS_STEREO_QUADBUFFERED) {
+ // In QUAD buffer stereo mode, the GE render pass ends with the right eye on the right buffer
+ // but we need to draw on the left buffer to capture the render
+ // TODO: implement an explicit function in rasterizer to restore the left buffer.
+ m_rasterizer->SetEye(RAS_IRasterizer::RAS_STEREO_LEFTEYE);
+ }
+
m_scene->CalculateVisibleMeshes(m_rasterizer,m_camera);
- m_scene->UpdateAnimations(m_engine->GetFrameTime());
+ m_engine->UpdateAnimations(m_scene);
m_scene->RenderBuckets(camtrans, m_rasterizer);
@@ -344,7 +376,7 @@ static int ImageRender_init(PyObject *pySelf, PyObject *args, PyObject *kwds)
// get background color
static PyObject *getBackground (PyImage *self, void *closure)
{
- return Py_BuildValue("[BBBB]",
+ return Py_BuildValue("[ffff]",
getImageRender(self)->getBackground(0),
getImageRender(self)->getBackground(1),
getImageRender(self)->getBackground(2),
@@ -356,20 +388,20 @@ static int setBackground(PyImage *self, PyObject *value, void *closure)
{
// check validity of parameter
if (value == NULL || !PySequence_Check(value) || PySequence_Size(value) != 4
- || !PyLong_Check(PySequence_Fast_GET_ITEM(value, 0))
- || !PyLong_Check(PySequence_Fast_GET_ITEM(value, 1))
- || !PyLong_Check(PySequence_Fast_GET_ITEM(value, 2))
- || !PyLong_Check(PySequence_Fast_GET_ITEM(value, 3)))
- {
- PyErr_SetString(PyExc_TypeError, "The value must be a sequence of 4 integer between 0 and 255");
+ || (!PyFloat_Check(PySequence_Fast_GET_ITEM(value, 0)) && !PyLong_Check(PySequence_Fast_GET_ITEM(value, 0)))
+ || (!PyFloat_Check(PySequence_Fast_GET_ITEM(value, 1)) && !PyLong_Check(PySequence_Fast_GET_ITEM(value, 1)))
+ || (!PyFloat_Check(PySequence_Fast_GET_ITEM(value, 2)) && !PyLong_Check(PySequence_Fast_GET_ITEM(value, 2)))
+ || (!PyFloat_Check(PySequence_Fast_GET_ITEM(value, 3)) && !PyLong_Check(PySequence_Fast_GET_ITEM(value, 3)))) {
+
+ PyErr_SetString(PyExc_TypeError, "The value must be a sequence of 4 floats or ints between 0.0 and 255.0");
return -1;
}
// set background color
getImageRender(self)->setBackground(
- (unsigned char)(PyLong_AsLong(PySequence_Fast_GET_ITEM(value, 0))),
- (unsigned char)(PyLong_AsLong(PySequence_Fast_GET_ITEM(value, 1))),
- (unsigned char)(PyLong_AsLong(PySequence_Fast_GET_ITEM(value, 2))),
- (unsigned char)(PyLong_AsLong(PySequence_Fast_GET_ITEM(value, 3))));
+ PyFloat_AsDouble(PySequence_Fast_GET_ITEM(value, 0)),
+ PyFloat_AsDouble(PySequence_Fast_GET_ITEM(value, 1)),
+ PyFloat_AsDouble(PySequence_Fast_GET_ITEM(value, 2)),
+ PyFloat_AsDouble(PySequence_Fast_GET_ITEM(value, 3)));
// success
return 0;
}
@@ -729,7 +761,8 @@ ImageRender::ImageRender (KX_Scene *scene, KX_GameObject *observer, KX_GameObjec
m_mirrorX = m_mirrorY.cross(m_mirrorZ);
m_render = true;
- setBackground(0, 0, 255, 255);
+ // set mirror background color to scene background color as default
+ setBackgroundFromScene(m_scene);
}
diff --git a/source/gameengine/VideoTexture/ImageRender.h b/source/gameengine/VideoTexture/ImageRender.h
index 98dceeaafe1..ef55e4dea84 100644
--- a/source/gameengine/VideoTexture/ImageRender.h
+++ b/source/gameengine/VideoTexture/ImageRender.h
@@ -55,9 +55,9 @@ public:
virtual ~ImageRender (void);
/// get background color
- int getBackground (int idx) { return (idx < 0 || idx > 3) ? 0 : int(m_background[idx]*255.f); }
+ float getBackground (int idx);
/// set background color
- void setBackground (int red, int green, int blue, int alpha);
+ void setBackground (float red, float green, float blue, float alpha);
/// clipping distance
float getClip (void) { return m_clip; }
@@ -100,7 +100,7 @@ protected:
void Render();
void SetupRenderFrame(KX_Scene *scene, KX_Camera* cam);
void RenderFrame(KX_Scene* scene, KX_Camera* cam);
- void SetBackGround(KX_WorldInfo* wi);
+ void setBackgroundFromScene(KX_Scene *scene);
void SetWorldSettings(KX_WorldInfo* wi);
};
diff --git a/source/gameengine/VideoTexture/ImageViewport.cpp b/source/gameengine/VideoTexture/ImageViewport.cpp
index 789b6006f99..820a019832e 100644
--- a/source/gameengine/VideoTexture/ImageViewport.cpp
+++ b/source/gameengine/VideoTexture/ImageViewport.cpp
@@ -30,10 +30,10 @@
// implementation
-#include "PyObjectPlus.h"
+#include "EXP_PyObjectPlus.h"
#include <structmember.h>
-#include "GL/glew.h"
+#include "glew-mx.h"
#include "KX_PythonInit.h"
#include "RAS_ICanvas.h"
diff --git a/source/gameengine/VideoTexture/PyTypeList.cpp b/source/gameengine/VideoTexture/PyTypeList.cpp
index 588a1257d6a..18f477f6178 100644
--- a/source/gameengine/VideoTexture/PyTypeList.cpp
+++ b/source/gameengine/VideoTexture/PyTypeList.cpp
@@ -33,7 +33,7 @@
#include <memory>
#include <vector>
-#include "PyObjectPlus.h"
+#include "EXP_PyObjectPlus.h"
/// destructor
PyTypeList::~PyTypeList()
diff --git a/source/gameengine/VideoTexture/PyTypeList.h b/source/gameengine/VideoTexture/PyTypeList.h
index b36f11ed75a..a8716e72e14 100644
--- a/source/gameengine/VideoTexture/PyTypeList.h
+++ b/source/gameengine/VideoTexture/PyTypeList.h
@@ -36,7 +36,7 @@
#include <memory>
#include <vector>
-#include "PyObjectPlus.h"
+#include "EXP_PyObjectPlus.h"
// forward declaration
class PyTypeListItem;
diff --git a/source/gameengine/VideoTexture/SConscript b/source/gameengine/VideoTexture/SConscript
index f7bf6bd93c1..dc708904309 100644
--- a/source/gameengine/VideoTexture/SConscript
+++ b/source/gameengine/VideoTexture/SConscript
@@ -37,7 +37,8 @@ incs = [
'#intern/ffmpeg',
'#intern/guardedalloc',
'#intern/string',
- '#extern/glew/include',
+ env['BF_GLEW_INC'],
+ '#/intern/glew-mx',
'#intern/moto/include',
'#source/blender/blenkernel',
'#source/blender/blenlib',
@@ -57,7 +58,9 @@ incs = [
]
incs = ' '.join(incs)
-defs = ['GLEW_STATIC']
+defs = []
+defs += env['BF_GL_DEFINITIONS']
+
if env['OURPLATFORM'] in ('win32-vc', 'win64-vc','win32-mingw', 'win64-mingw'):
if env['BF_DEBUG']:
defs.append('_DEBUG')
diff --git a/source/gameengine/VideoTexture/Texture.cpp b/source/gameengine/VideoTexture/Texture.cpp
index 35a73193a24..cc010f08b17 100644
--- a/source/gameengine/VideoTexture/Texture.cpp
+++ b/source/gameengine/VideoTexture/Texture.cpp
@@ -30,7 +30,7 @@
// implementation
-#include "PyObjectPlus.h"
+#include "EXP_PyObjectPlus.h"
#include <structmember.h>
#include "KX_GameObject.h"
@@ -41,6 +41,7 @@
#include "DNA_meshdata_types.h"
#include "DNA_image_types.h"
#include "IMB_imbuf_types.h"
+#include "BKE_image.h"
#include "MEM_guardedalloc.h"
@@ -54,8 +55,11 @@
#include "Exception.h"
#include <memory.h>
-#include "GL/glew.h"
+#include "glew-mx.h"
+extern "C" {
+ #include "IMB_imbuf.h"
+}
// macro for exception handling and logging
#define CATCH_EXCP catch (Exception & exp) \
@@ -75,9 +79,21 @@ void loadTexture(unsigned int texId, unsigned int *texture, short *size,
glBindTexture(GL_TEXTURE_2D, texId);
if (mipmap)
{
+ int i;
+ ImBuf *ibuf;
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGBA, size[0], size[1], GL_RGBA, GL_UNSIGNED_BYTE, texture);
+
+ ibuf = IMB_allocFromBuffer(texture, NULL, size[0], size[1]);
+
+ IMB_makemipmap(ibuf, true);
+
+ for (i = 0; i < ibuf->miptot; i++) {
+ ImBuf *mip = IMB_getmipmap(ibuf, i);
+
+ glTexImage2D(GL_TEXTURE_2D, i, GL_RGBA, mip->x, mip->y, 0, GL_RGBA, GL_UNSIGNED_BYTE, mip->rect);
+ }
+ IMB_freeImBuf(ibuf);
}
else
{
@@ -158,11 +174,11 @@ static PyObject *Texture_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
// initialize object structure
self->m_actTex = 0;
self->m_orgSaved = false;
+ self->m_imgBuf = NULL;
self->m_imgTexture = NULL;
self->m_matTexture = NULL;
self->m_mipmap = false;
- self->m_scaledImg = NULL;
- self->m_scaledImgSize = 0;
+ self->m_scaledImBuf = NULL;
self->m_source = NULL;
self->m_lastClock = 0.0;
// return allocated object
@@ -184,7 +200,7 @@ static void Texture_dealloc(Texture *self)
PyObject *ret = Texture_close(self);
Py_DECREF(ret);
// release scaled image buffer
- delete [] self->m_scaledImg;
+ IMB_freeImBuf(self->m_scaledImBuf);
// release object
Py_TYPE((PyObject *)self)->tp_free((PyObject *)self);
}
@@ -282,7 +298,11 @@ PyObject *Texture_close(Texture * self)
if (self->m_useMatTexture)
self->m_matTexture->swapTexture(self->m_orgTex);
else
+ {
self->m_imgTexture->bindcode = self->m_orgTex;
+ BKE_image_release_ibuf(self->m_imgTexture, self->m_imgBuf, NULL);
+ self->m_imgBuf = NULL;
+ }
// drop actual texture
if (self->m_actTex != 0)
{
@@ -331,6 +351,12 @@ static PyObject *Texture_refresh(Texture *self, PyObject *args)
self->m_orgTex = self->m_matTexture->swapTexture(self->m_actTex);
else
{
+ // Swapping will work only if the GPU has already loaded the image.
+ // If not, it will delete and overwrite our texture on next render.
+ // To avoid that, we acquire the image buffer now.
+ // WARNING: GPU has a ImageUser to pass, we don't. Using NULL
+ // works on image file, not necessarily on other type of image.
+ self->m_imgBuf = BKE_image_acquire_ibuf(self->m_imgTexture, NULL, NULL);
self->m_orgTex = self->m_imgTexture->bindcode;
self->m_imgTexture->bindcode = self->m_actTex;
}
@@ -358,20 +384,12 @@ static PyObject *Texture_refresh(Texture *self, PyObject *args)
// scale texture if needed
if (size[0] != orgSize[0] || size[1] != orgSize[1])
{
- // if scaled image buffer is smaller than needed
- if (self->m_scaledImgSize < (unsigned int)(size[0] * size[1]))
- {
- // new size
- self->m_scaledImgSize = size[0] * size[1];
- // allocate scaling image
- delete [] self->m_scaledImg;
- self->m_scaledImg = new unsigned int[self->m_scaledImgSize];
- }
- // scale texture
- gluScaleImage(GL_RGBA, orgSize[0], orgSize[1], GL_UNSIGNED_BYTE, texture,
- size[0], size[1], GL_UNSIGNED_BYTE, self->m_scaledImg);
+ IMB_freeImBuf(self->m_scaledImBuf);
+ self->m_scaledImBuf = IMB_allocFromBuffer(texture, NULL, orgSize[0], orgSize[1]);
+ IMB_scaleImBuf(self->m_scaledImBuf, size[0], size[1]);
+
// use scaled image instead original
- texture = self->m_scaledImg;
+ texture = self->m_scaledImBuf->rect;
}
// load texture for rendering
loadTexture(self->m_actTex, texture, size, self->m_mipmap);
diff --git a/source/gameengine/VideoTexture/Texture.h b/source/gameengine/VideoTexture/Texture.h
index c85b1228864..dc38b4181bb 100644
--- a/source/gameengine/VideoTexture/Texture.h
+++ b/source/gameengine/VideoTexture/Texture.h
@@ -31,7 +31,7 @@
#ifndef __TEXTURE_H__
#define __TEXTURE_H__
-#include "PyObjectPlus.h"
+#include "EXP_PyObjectPlus.h"
#include <structmember.h>
#include "DNA_image_types.h"
@@ -43,6 +43,8 @@
#include "Exception.h"
+struct ImBuf;
+
// type Texture declaration
struct Texture
{
@@ -58,6 +60,8 @@ struct Texture
// original texture saved
bool m_orgSaved;
+ // kernel image buffer, to make sure the image is loaded before we swap the bindcode
+ struct ImBuf *m_imgBuf;
// texture image for game materials
Image * m_imgTexture;
// texture for blender materials
@@ -67,9 +71,7 @@ struct Texture
bool m_mipmap;
// scaled image buffer
- unsigned int * m_scaledImg;
- // scaled image buffer size
- unsigned int m_scaledImgSize;
+ ImBuf * m_scaledImBuf;
// last refresh
double m_lastClock;
diff --git a/source/gameengine/VideoTexture/VideoBase.h b/source/gameengine/VideoTexture/VideoBase.h
index 51f025909fd..6f35c474300 100644
--- a/source/gameengine/VideoTexture/VideoBase.h
+++ b/source/gameengine/VideoTexture/VideoBase.h
@@ -32,7 +32,7 @@
#define __VIDEOBASE_H__
-#include "PyObjectPlus.h"
+#include "EXP_PyObjectPlus.h"
#include "ImageBase.h"
diff --git a/source/gameengine/VideoTexture/VideoFFmpeg.cpp b/source/gameengine/VideoTexture/VideoFFmpeg.cpp
index edf3c58bcbe..ffe06cff100 100644
--- a/source/gameengine/VideoTexture/VideoFFmpeg.cpp
+++ b/source/gameengine/VideoTexture/VideoFFmpeg.cpp
@@ -86,6 +86,13 @@ VideoFFmpeg::~VideoFFmpeg ()
{
}
+void VideoFFmpeg::refresh(void)
+{
+ // a fixed image will not refresh because it is loaded only once at creation
+ if (m_isImage)
+ return;
+ m_avail = false;
+}
// release components
bool VideoFFmpeg::release()
@@ -1016,19 +1023,14 @@ AVFrame *VideoFFmpeg::grabFrame(long position)
{
if (packet.stream_index == m_videoStream)
{
- if (m_isImage)
- {
- // If we're an image, we're probably not going to be here often,
- // so we don't want to deal with delayed frames from threading.
- // There might be a better way to handle this, but I'll leave that
- // for people more knowledgeable with ffmpeg than myself. We don't
- // need threading for a single image anyways.
- m_codecCtx->thread_count = 1;
- }
+ AVFrame *input = m_frame;
+ short counter = 0;
- avcodec_decode_video2(m_codecCtx,
- m_frame, &frameFinished,
- &packet);
+ /* While the data is not read properly (png, tiffs, etc formats may need several pass)*/
+ while ((input->data[0] == 0 && input->data[1] == 0 && input->data[2] == 0 && input->data[3] == 0) && counter < 10) {
+ avcodec_decode_video2(m_codecCtx, m_frame, &frameFinished, &packet);
+ counter++;
+ }
// remember dts to compute exact frame number
dts = packet.dts;
diff --git a/source/gameengine/VideoTexture/VideoFFmpeg.h b/source/gameengine/VideoTexture/VideoFFmpeg.h
index 4a948fe61de..0a49a0b19bb 100644
--- a/source/gameengine/VideoTexture/VideoFFmpeg.h
+++ b/source/gameengine/VideoTexture/VideoFFmpeg.h
@@ -85,7 +85,8 @@ public:
/// release video source
virtual bool release (void);
-
+ /// overwrite base refresh to handle fixed image
+ virtual void refresh(void);
/// play video
virtual bool play (void);
/// pause video
diff --git a/source/gameengine/VideoTexture/blendVideoTex.cpp b/source/gameengine/VideoTexture/blendVideoTex.cpp
index ab6dca0958f..30a8107b558 100644
--- a/source/gameengine/VideoTexture/blendVideoTex.cpp
+++ b/source/gameengine/VideoTexture/blendVideoTex.cpp
@@ -28,7 +28,7 @@
* \ingroup bgevideotex
*/
-#include "PyObjectPlus.h"
+#include "EXP_PyObjectPlus.h"
#include "KX_PythonInit.h"
@@ -50,6 +50,12 @@
#include "Exception.h"
+// access to IMB_BLEND_* constants
+extern "C"
+{
+#include "IMB_imbuf.h"
+};
+
// get material id
static PyObject *getMaterialID (PyObject *self, PyObject *args)
@@ -157,10 +163,14 @@ static void registerAllTypes(void)
pyFilterTypes.add(&FilterBGR24Type, "FilterBGR24");
}
+PyDoc_STRVAR(VideoTexture_module_documentation,
+"Module that allows to play video files on textures in GameBlender."
+);
+
static struct PyModuleDef VideoTexture_module_def = {
- {}, /* m_base */
+ PyModuleDef_HEAD_INIT,
"VideoTexture", /* m_name */
- "Module that allows to play video files on textures in GameBlender.", /* m_doc */
+ VideoTexture_module_documentation, /* m_doc */
0, /* m_size */
moduleMethods, /* m_methods */
0, /* m_reload */
@@ -169,7 +179,7 @@ static struct PyModuleDef VideoTexture_module_def = {
0, /* m_free */
};
-PyObject *initVideoTexture(void)
+PyMODINIT_FUNC initVideoTexturePythonBinding(void)
{
PyObject *m;
@@ -187,20 +197,9 @@ PyObject *initVideoTexture(void)
if (PyType_Ready(&TextureType) < 0)
return NULL;
- /* Use existing module where possible
- * be careful not to init any runtime vars after this */
- m = PyImport_ImportModule( "VideoTexture" );
- if (m) {
- Py_DECREF(m);
- return m;
- }
- else {
- PyErr_Clear();
-
- m = PyModule_Create(&VideoTexture_module_def);
- PyDict_SetItemString(PySys_GetObject("modules"), VideoTexture_module_def.m_name, m);
- }
-
+ m = PyModule_Create(&VideoTexture_module_def);
+ PyDict_SetItemString(PySys_GetObject("modules"), VideoTexture_module_def.m_name, m);
+
if (m == NULL)
return NULL;
@@ -215,7 +214,36 @@ PyObject *initVideoTexture(void)
PyModule_AddIntConstant(m, "SOURCE_READY", SourceReady);
PyModule_AddIntConstant(m, "SOURCE_PLAYING", SourcePlaying);
PyModule_AddIntConstant(m, "SOURCE_STOPPED", SourceStopped);
-
+
+ PyModule_AddIntConstant(m, "IMB_BLEND_MIX", IMB_BLEND_MIX);
+ PyModule_AddIntConstant(m, "IMB_BLEND_ADD", IMB_BLEND_ADD);
+ PyModule_AddIntConstant(m, "IMB_BLEND_SUB", IMB_BLEND_SUB);
+ PyModule_AddIntConstant(m, "IMB_BLEND_MUL", IMB_BLEND_MUL);
+ PyModule_AddIntConstant(m, "IMB_BLEND_LIGHTEN", IMB_BLEND_LIGHTEN);
+ PyModule_AddIntConstant(m, "IMB_BLEND_DARKEN", IMB_BLEND_DARKEN);
+ PyModule_AddIntConstant(m, "IMB_BLEND_ERASE_ALPHA", IMB_BLEND_ERASE_ALPHA);
+ PyModule_AddIntConstant(m, "IMB_BLEND_ADD_ALPHA", IMB_BLEND_ADD_ALPHA);
+ PyModule_AddIntConstant(m, "IMB_BLEND_OVERLAY", IMB_BLEND_OVERLAY);
+ PyModule_AddIntConstant(m, "IMB_BLEND_HARDLIGHT", IMB_BLEND_HARDLIGHT);
+ PyModule_AddIntConstant(m, "IMB_BLEND_COLORBURN", IMB_BLEND_COLORBURN);
+ PyModule_AddIntConstant(m, "IMB_BLEND_LINEARBURN", IMB_BLEND_LINEARBURN);
+ PyModule_AddIntConstant(m, "IMB_BLEND_COLORDODGE", IMB_BLEND_COLORDODGE);
+ PyModule_AddIntConstant(m, "IMB_BLEND_SCREEN", IMB_BLEND_SCREEN);
+ PyModule_AddIntConstant(m, "IMB_BLEND_SOFTLIGHT", IMB_BLEND_SOFTLIGHT);
+ PyModule_AddIntConstant(m, "IMB_BLEND_PINLIGHT", IMB_BLEND_PINLIGHT);
+ PyModule_AddIntConstant(m, "IMB_BLEND_VIVIDLIGHT", IMB_BLEND_VIVIDLIGHT);
+ PyModule_AddIntConstant(m, "IMB_BLEND_LINEARLIGHT", IMB_BLEND_LINEARLIGHT);
+ PyModule_AddIntConstant(m, "IMB_BLEND_DIFFERENCE", IMB_BLEND_DIFFERENCE);
+ PyModule_AddIntConstant(m, "IMB_BLEND_EXCLUSION", IMB_BLEND_EXCLUSION);
+ PyModule_AddIntConstant(m, "IMB_BLEND_HUE", IMB_BLEND_HUE);
+ PyModule_AddIntConstant(m, "IMB_BLEND_SATURATION", IMB_BLEND_SATURATION);
+ PyModule_AddIntConstant(m, "IMB_BLEND_LUMINOSITY", IMB_BLEND_LUMINOSITY);
+ PyModule_AddIntConstant(m, "IMB_BLEND_COLOR", IMB_BLEND_COLOR);
+
+ PyModule_AddIntConstant(m, "IMB_BLEND_COPY", IMB_BLEND_COPY);
+ PyModule_AddIntConstant(m, "IMB_BLEND_COPY_RGB", IMB_BLEND_COPY_RGB);
+ PyModule_AddIntConstant(m, "IMB_BLEND_COPY_ALPHA", IMB_BLEND_COPY_ALPHA);
+
// init last error description
Exception::m_lastError = "";
diff --git a/tests/gtests/blenlib/BLI_ghash_performance_test.cc b/tests/gtests/blenlib/BLI_ghash_performance_test.cc
new file mode 100644
index 00000000000..fcee72466b7
--- /dev/null
+++ b/tests/gtests/blenlib/BLI_ghash_performance_test.cc
@@ -0,0 +1,415 @@
+/* Apache License, Version 2.0 */
+
+#include "testing/testing.h"
+#include "BLI_ressource_strings.h"
+
+#define GHASH_INTERNAL_API
+
+extern "C" {
+#include "MEM_guardedalloc.h"
+#include "BLI_utildefines.h"
+#include "BLI_ghash.h"
+#include "BLI_rand.h"
+#include "BLI_string.h"
+#include "PIL_time_utildefines.h"
+}
+
+/* Using http://corpora.uni-leipzig.de/downloads/eng_wikipedia_2010_1M-text.tar.gz
+ * (1 million of words, about 122MB of text) from http://corpora.informatik.uni-leipzig.de/download.html */
+//#define TEXT_CORPUS_PATH "/path/to/Téléchargements/eng_wikipedia_2010_1M-text/eng_wikipedia_2010_1M-sentences.txt"
+
+/* Resizing the hash has a huge cost over global filling operation! */
+//#define GHASH_RESERVE
+
+#define PRINTF_GHASH_STATS(_gh) \
+{ \
+ double q, lf, var, pempty, poverloaded; \
+ int bigb; \
+ q = BLI_ghash_calc_quality_ex((_gh), &lf, &var, &pempty, &poverloaded, &bigb); \
+ printf("GHash stats (%u entries):\n\t" \
+ "Quality (the lower the better): %f\n\tVariance (the lower the better): %f\n\tLoad: %f\n\t" \
+ "Empty buckets: %.2f%%\n\tOverloaded buckets: %.2f%% (biggest bucket: %d)\n", \
+ BLI_ghash_size(_gh), q, var, lf, pempty * 100.0, poverloaded * 100.0, bigb); \
+} void (0)
+
+
+/* Str: whole text, lines and words from a 'corpus' text. */
+
+static void str_ghash_tests(GHash *ghash, const char *id)
+{
+ printf("\n========== STARTING %s ==========\n", id);
+
+#ifdef TEXT_CORPUS_PATH
+ size_t sz = 0;
+ char *data;
+ {
+ struct stat st;
+ if (stat(TEXT_CORPUS_PATH, &st) == 0)
+ sz = st.st_size;
+ }
+ if (sz != 0) {
+ FILE *f = fopen(TEXT_CORPUS_PATH, "r");
+
+ data = (char *)MEM_mallocN(sz + 1, __func__);
+ if (fread(data, sizeof(*data), sz, f) != sz) {
+ printf("ERROR in reading file %s!", TEXT_CORPUS_PATH);
+ MEM_freeN(data);
+ data = BLI_strdup(words10k);
+ }
+ data[sz] = '\0';
+ fclose(f);
+ }
+ else {
+ data = BLI_strdup(words10k);
+ }
+#else
+ char *data = BLI_strdup(words10k);
+#endif
+ char *data_p = BLI_strdup(data);
+ char *data_w = BLI_strdup(data);
+ char *data_bis = BLI_strdup(data);
+
+ {
+ char *p, *w, *c_p, *c_w;
+
+ TIMEIT_START(string_insert);
+
+#ifdef GHASH_RESERVE
+ BLI_ghash_reserve(ghash, strlen(data) / 32); /* rough estimation... */
+#endif
+
+ BLI_ghash_insert(ghash, data, SET_INT_IN_POINTER(data[0]));
+
+ for (p = c_p = data_p, w = c_w = data_w; *c_w; c_w++, c_p++) {
+ if (*c_p == '.') {
+ *c_p = *c_w = '\0';
+ if (!BLI_ghash_haskey(ghash, p)) {
+ BLI_ghash_insert(ghash, p, SET_INT_IN_POINTER(p[0]));
+ }
+ if (!BLI_ghash_haskey(ghash, w)) {
+ BLI_ghash_insert(ghash, w, SET_INT_IN_POINTER(w[0]));
+ }
+ p = c_p + 1;
+ w = c_w + 1;
+ }
+ else if (*c_w == ' ') {
+ *c_w = '\0';
+ if (!BLI_ghash_haskey(ghash, w)) {
+ BLI_ghash_insert(ghash, w, SET_INT_IN_POINTER(w[0]));
+ }
+ w = c_w + 1;
+ }
+ }
+
+ TIMEIT_END(string_insert);
+ }
+
+ PRINTF_GHASH_STATS(ghash);
+
+ {
+ char *p, *w, *c;
+ void *v;
+
+ TIMEIT_START(string_lookup);
+
+ v = BLI_ghash_lookup(ghash, data_bis);
+ EXPECT_EQ(data_bis[0], GET_INT_FROM_POINTER(v));
+
+ for (p = w = c = data_bis; *c; c++) {
+ if (*c == '.') {
+ *c = '\0';
+ v = BLI_ghash_lookup(ghash, w);
+ EXPECT_EQ(w[0], GET_INT_FROM_POINTER(v));
+ v = BLI_ghash_lookup(ghash, p);
+ EXPECT_EQ(p[0], GET_INT_FROM_POINTER(v));
+ p = w = c + 1;
+ }
+ else if (*c == ' ') {
+ *c = '\0';
+ v = BLI_ghash_lookup(ghash, w);
+ EXPECT_EQ(w[0], GET_INT_FROM_POINTER(v));
+ w = c + 1;
+ }
+ }
+
+ TIMEIT_END(string_lookup);
+ }
+
+ BLI_ghash_free(ghash, NULL, NULL);
+ MEM_freeN(data);
+ MEM_freeN(data_p);
+ MEM_freeN(data_w);
+ MEM_freeN(data_bis);
+
+ printf("========== ENDED %s ==========\n\n", id);
+}
+
+TEST(ghash, TextGHash)
+{
+ GHash *ghash = BLI_ghash_new(BLI_ghashutil_strhash_p, BLI_ghashutil_strcmp, __func__);
+
+ str_ghash_tests(ghash, "StrGHash - GHash");
+}
+
+TEST(ghash, TextMurmur2a)
+{
+ GHash *ghash = BLI_ghash_new(BLI_ghashutil_strhash_p_murmur, BLI_ghashutil_strcmp, __func__);
+
+ str_ghash_tests(ghash, "StrGHash - Murmur");
+}
+
+
+/* Int: uniform 100M first integers. */
+
+static void int_ghash_tests(GHash *ghash, const char *id, const unsigned int nbr)
+{
+ printf("\n========== STARTING %s ==========\n", id);
+
+ {
+ unsigned int i = nbr;
+
+ TIMEIT_START(int_insert);
+
+#ifdef GHASH_RESERVE
+ BLI_ghash_reserve(ghash, nbr);
+#endif
+
+ while (i--) {
+ BLI_ghash_insert(ghash, SET_UINT_IN_POINTER(i), SET_UINT_IN_POINTER(i));
+ }
+
+ TIMEIT_END(int_insert);
+ }
+
+ PRINTF_GHASH_STATS(ghash);
+
+ {
+ unsigned int i = nbr;
+
+ TIMEIT_START(int_lookup);
+
+ while (i--) {
+ void *v = BLI_ghash_lookup(ghash, SET_UINT_IN_POINTER(i));
+ EXPECT_EQ(i, GET_UINT_FROM_POINTER(v));
+ }
+
+ TIMEIT_END(int_lookup);
+ }
+
+ BLI_ghash_free(ghash, NULL, NULL);
+
+ printf("========== ENDED %s ==========\n\n", id);
+}
+
+TEST(ghash, IntGHash12000)
+{
+ GHash *ghash = BLI_ghash_new(BLI_ghashutil_inthash_p, BLI_ghashutil_intcmp, __func__);
+
+ int_ghash_tests(ghash, "IntGHash - GHash - 12000", 12000);
+}
+
+TEST(ghash, IntGHash100000000)
+{
+ GHash *ghash = BLI_ghash_new(BLI_ghashutil_inthash_p, BLI_ghashutil_intcmp, __func__);
+
+ int_ghash_tests(ghash, "IntGHash - GHash - 100000000", 100000000);
+}
+
+TEST(ghash, IntMurmur2a12000)
+{
+ GHash *ghash = BLI_ghash_new(BLI_ghashutil_inthash_p_murmur, BLI_ghashutil_intcmp, __func__);
+
+ int_ghash_tests(ghash, "IntGHash - Murmur - 12000", 12000);
+}
+
+TEST(ghash, IntMurmur2a100000000)
+{
+ GHash *ghash = BLI_ghash_new(BLI_ghashutil_inthash_p_murmur, BLI_ghashutil_intcmp, __func__);
+
+ int_ghash_tests(ghash, "IntGHash - Murmur - 100000000", 100000000);
+}
+
+
+/* Int: random 50M integers. */
+
+static void randint_ghash_tests(GHash *ghash, const char *id, const unsigned int nbr)
+{
+ printf("\n========== STARTING %s ==========\n", id);
+
+ unsigned int *data = (unsigned int *)MEM_mallocN(sizeof(*data) * (size_t)nbr, __func__);
+ unsigned int *dt;
+ unsigned int i;
+
+ {
+ RNG *rng = BLI_rng_new(0);
+ for (i = nbr, dt = data; i--; dt++) {
+ *dt = BLI_rng_get_uint(rng);
+ }
+ BLI_rng_free(rng);
+ }
+
+ {
+ TIMEIT_START(int_insert);
+
+#ifdef GHASH_RESERVE
+ BLI_ghash_reserve(ghash, nbr);
+#endif
+
+ for (i = nbr, dt = data; i--; dt++) {
+ BLI_ghash_insert(ghash, SET_UINT_IN_POINTER(*dt), SET_UINT_IN_POINTER(*dt));
+ }
+
+ TIMEIT_END(int_insert);
+ }
+
+ PRINTF_GHASH_STATS(ghash);
+
+ {
+ TIMEIT_START(int_lookup);
+
+ for (i = nbr, dt = data; i--; dt++) {
+ void *v = BLI_ghash_lookup(ghash, SET_UINT_IN_POINTER(*dt));
+ EXPECT_EQ(*dt, GET_UINT_FROM_POINTER(v));
+ }
+
+ TIMEIT_END(int_lookup);
+ }
+
+ BLI_ghash_free(ghash, NULL, NULL);
+
+ printf("========== ENDED %s ==========\n\n", id);
+}
+
+TEST(ghash, IntRandGHash12000)
+{
+ GHash *ghash = BLI_ghash_new(BLI_ghashutil_inthash_p, BLI_ghashutil_intcmp, __func__);
+
+ randint_ghash_tests(ghash, "RandIntGHash - GHash - 12000", 12000);
+}
+
+TEST(ghash, IntRandGHash50000000)
+{
+ GHash *ghash = BLI_ghash_new(BLI_ghashutil_inthash_p, BLI_ghashutil_intcmp, __func__);
+
+ randint_ghash_tests(ghash, "RandIntGHash - GHash - 50000000", 50000000);
+}
+
+TEST(ghash, IntRandMurmur2a12000)
+{
+ GHash *ghash = BLI_ghash_new(BLI_ghashutil_inthash_p_murmur, BLI_ghashutil_intcmp, __func__);
+
+ randint_ghash_tests(ghash, "RandIntGHash - Murmur - 12000", 12000);
+}
+
+TEST(ghash, IntRandMurmur2a50000000)
+{
+ GHash *ghash = BLI_ghash_new(BLI_ghashutil_inthash_p_murmur, BLI_ghashutil_intcmp, __func__);
+
+ randint_ghash_tests(ghash, "RandIntGHash - Murmur - 50000000", 50000000);
+}
+
+static unsigned int ghashutil_tests_nohash_p(const void *p)
+{
+ return GET_UINT_FROM_POINTER(p);
+}
+
+static bool ghashutil_tests_cmp_p(const void *a, const void *b)
+{
+ return a != b;
+}
+
+TEST(ghash, Int4NoHash12000)
+{
+ GHash *ghash = BLI_ghash_new(ghashutil_tests_nohash_p, ghashutil_tests_cmp_p, __func__);
+
+ randint_ghash_tests(ghash, "RandIntGHash - No Hash - 12000", 12000);
+}
+
+TEST(ghash, Int4NoHash50000000)
+{
+ GHash *ghash = BLI_ghash_new(ghashutil_tests_nohash_p, ghashutil_tests_cmp_p, __func__);
+
+ randint_ghash_tests(ghash, "RandIntGHash - No Hash - 50000000", 50000000);
+}
+
+
+/* Int_v4: 20M of randomly-generated integer vectors. */
+
+static void int4_ghash_tests(GHash *ghash, const char *id, const unsigned int nbr)
+{
+ printf("\n========== STARTING %s ==========\n", id);
+
+ unsigned int (*data)[4] = (unsigned int (*)[4])MEM_mallocN(sizeof(*data) * (size_t)nbr, __func__);
+ unsigned int (*dt)[4];
+ unsigned int i, j;
+
+ {
+ RNG *rng = BLI_rng_new(0);
+ for (i = nbr, dt = data; i--; dt++) {
+ for (j = 4; j--; ) {
+ (*dt)[j] = BLI_rng_get_uint(rng);
+ }
+ }
+ BLI_rng_free(rng);
+ }
+
+ {
+ TIMEIT_START(int_v4_insert);
+
+#ifdef GHASH_RESERVE
+ BLI_ghash_reserve(ghash, nbr);
+#endif
+
+ for (i = nbr, dt = data; i--; dt++) {
+ BLI_ghash_insert(ghash, *dt, SET_UINT_IN_POINTER(i));
+ }
+
+ TIMEIT_END(int_v4_insert);
+ }
+
+ PRINTF_GHASH_STATS(ghash);
+
+ {
+ TIMEIT_START(int_v4_lookup);
+
+ for (i = nbr, dt = data; i--; dt++) {
+ void *v = BLI_ghash_lookup(ghash, (void *)(*dt));
+ EXPECT_EQ(i, GET_UINT_FROM_POINTER(v));
+ }
+
+ TIMEIT_END(int_v4_lookup);
+ }
+
+ BLI_ghash_free(ghash, NULL, NULL);
+ MEM_freeN(data);
+
+ printf("========== ENDED %s ==========\n\n", id);
+}
+
+TEST(ghash, Int4GHash2000)
+{
+ GHash *ghash = BLI_ghash_new(BLI_ghashutil_uinthash_v4_p, BLI_ghashutil_uinthash_v4_cmp, __func__);
+
+ int4_ghash_tests(ghash, "Int4GHash - GHash - 2000", 2000);
+}
+
+TEST(ghash, Int4GHash20000000)
+{
+ GHash *ghash = BLI_ghash_new(BLI_ghashutil_uinthash_v4_p, BLI_ghashutil_uinthash_v4_cmp, __func__);
+
+ int4_ghash_tests(ghash, "Int4GHash - GHash - 20000000", 20000000);
+}
+
+TEST(ghash, Int4Murmur2a2000)
+{
+ GHash *ghash = BLI_ghash_new(BLI_ghashutil_uinthash_v4_p_murmur, BLI_ghashutil_uinthash_v4_cmp, __func__);
+
+ int4_ghash_tests(ghash, "Int4GHash - Murmur - 2000", 2000);
+}
+
+TEST(ghash, Int4Murmur2a20000000)
+{
+ GHash *ghash = BLI_ghash_new(BLI_ghashutil_uinthash_v4_p_murmur, BLI_ghashutil_uinthash_v4_cmp, __func__);
+
+ int4_ghash_tests(ghash, "Int4GHash - Murmur - 20000000", 20000000);
+}
diff --git a/tests/gtests/blenlib/BLI_ghash_test.cc b/tests/gtests/blenlib/BLI_ghash_test.cc
new file mode 100644
index 00000000000..5fe43d14cbe
--- /dev/null
+++ b/tests/gtests/blenlib/BLI_ghash_test.cc
@@ -0,0 +1,158 @@
+/* Apache License, Version 2.0 */
+
+#include "testing/testing.h"
+
+#define GHASH_INTERNAL_API
+
+extern "C" {
+#include "BLI_utildefines.h"
+#include "BLI_ghash.h"
+#include "BLI_rand.h"
+}
+
+#define TESTCASE_SIZE 10000
+
+/* Only keeping this in case here, for now. */
+#define PRINTF_GHASH_STATS(_gh) \
+{ \
+ double q, lf, var, pempty, poverloaded; \
+ int bigb; \
+ q = BLI_ghash_calc_quality_ex((_gh), &lf, &var, &pempty, &poverloaded, &bigb); \
+ printf("GHash stats (%d entries):\n\t" \
+ "Quality (the lower the better): %f\n\tVariance (the lower the better): %f\n\tLoad: %f\n\t" \
+ "Empty buckets: %.2f%%\n\tOverloaded buckets: %.2f%% (biggest bucket: %d)\n", \
+ BLI_ghash_size(_gh), q, var, lf, pempty * 100.0, poverloaded * 100.0, bigb); \
+} void (0)
+
+/* Note: for pure-ghash testing, nature of the keys and data have absolutely no importance! So here we just use mere
+ * random integers stored in pointers. */
+
+static void init_keys(unsigned int keys[TESTCASE_SIZE], const int seed)
+{
+ RNG *rng = BLI_rng_new(seed);
+ unsigned int *k;
+ int i;
+
+ for (i = 0, k = keys; i < TESTCASE_SIZE; ) {
+ /* Risks of collision are low, but they do exist.
+ * And we cannot use a GSet, since we test that here! */
+ int j, t = BLI_rng_get_uint(rng);
+ for (j = i; j--; ) {
+ if (keys[j] == t) {
+ continue;
+ }
+ }
+ *k = t;
+ i++;
+ k++;
+ }
+ BLI_rng_free(rng);
+}
+
+/* Here we simply insert and then lookup all keys, ensuring we do get back the expected stored 'data'. */
+TEST(ghash, InsertLookup)
+{
+ GHash *ghash = BLI_ghash_new(BLI_ghashutil_inthash_p, BLI_ghashutil_intcmp, __func__);
+ unsigned int keys[TESTCASE_SIZE], *k;
+ int i;
+
+ init_keys(keys, 0);
+
+ for (i = TESTCASE_SIZE, k = keys; i--; k++) {
+ BLI_ghash_insert(ghash, SET_UINT_IN_POINTER(*k), SET_UINT_IN_POINTER(*k));
+ }
+
+ EXPECT_EQ(TESTCASE_SIZE, BLI_ghash_size(ghash));
+
+ for (i = TESTCASE_SIZE, k = keys; i--; k++) {
+ void *v = BLI_ghash_lookup(ghash, SET_UINT_IN_POINTER(*k));
+ EXPECT_EQ(*k, GET_UINT_FROM_POINTER(v));
+ }
+
+ BLI_ghash_free(ghash, NULL, NULL);
+}
+
+/* Here we simply insert and then remove all keys, ensuring we do get an empty, unshrinked ghash. */
+TEST(ghash, InsertRemove)
+{
+ GHash *ghash = BLI_ghash_new(BLI_ghashutil_inthash_p, BLI_ghashutil_intcmp, __func__);
+ unsigned int keys[TESTCASE_SIZE], *k;
+ int i, bkt_size;
+
+ init_keys(keys, 10);
+
+ for (i = TESTCASE_SIZE, k = keys; i--; k++) {
+ BLI_ghash_insert(ghash, SET_UINT_IN_POINTER(*k), SET_UINT_IN_POINTER(*k));
+ }
+
+ EXPECT_EQ(TESTCASE_SIZE, BLI_ghash_size(ghash));
+ bkt_size = BLI_ghash_buckets_size(ghash);
+
+ for (i = TESTCASE_SIZE, k = keys; i--; k++) {
+ void *v = BLI_ghash_popkey(ghash, SET_UINT_IN_POINTER(*k), NULL);
+ EXPECT_EQ(*k, GET_UINT_FROM_POINTER(v));
+ }
+
+ EXPECT_EQ(0, BLI_ghash_size(ghash));
+ EXPECT_EQ(bkt_size, BLI_ghash_buckets_size(ghash));
+
+ BLI_ghash_free(ghash, NULL, NULL);
+}
+
+/* Same as above, but this time we allow ghash to shrink. */
+TEST(ghash, InsertRemoveShrink)
+{
+ GHash *ghash = BLI_ghash_new(BLI_ghashutil_inthash_p, BLI_ghashutil_intcmp, __func__);
+ unsigned int keys[TESTCASE_SIZE], *k;
+ int i, bkt_size;
+
+ BLI_ghash_flag_set(ghash, GHASH_FLAG_ALLOW_SHRINK);
+ init_keys(keys, 20);
+
+ for (i = TESTCASE_SIZE, k = keys; i--; k++) {
+ BLI_ghash_insert(ghash, SET_UINT_IN_POINTER(*k), SET_UINT_IN_POINTER(*k));
+ }
+
+ EXPECT_EQ(TESTCASE_SIZE, BLI_ghash_size(ghash));
+ bkt_size = BLI_ghash_buckets_size(ghash);
+
+ for (i = TESTCASE_SIZE, k = keys; i--; k++) {
+ void *v = BLI_ghash_popkey(ghash, SET_UINT_IN_POINTER(*k), NULL);
+ EXPECT_EQ(*k, GET_UINT_FROM_POINTER(v));
+ }
+
+ EXPECT_EQ(0, BLI_ghash_size(ghash));
+ EXPECT_LT(BLI_ghash_buckets_size(ghash), bkt_size);
+
+ BLI_ghash_free(ghash, NULL, NULL);
+}
+
+/* Check copy. */
+TEST(ghash, Copy)
+{
+ GHash *ghash = BLI_ghash_new(BLI_ghashutil_inthash_p, BLI_ghashutil_intcmp, __func__);
+ GHash *ghash_copy;
+ unsigned int keys[TESTCASE_SIZE], *k;
+ int i;
+
+ init_keys(keys, 30);
+
+ for (i = TESTCASE_SIZE, k = keys; i--; k++) {
+ BLI_ghash_insert(ghash, SET_UINT_IN_POINTER(*k), SET_UINT_IN_POINTER(*k));
+ }
+
+ EXPECT_EQ(TESTCASE_SIZE, BLI_ghash_size(ghash));
+
+ ghash_copy = BLI_ghash_copy(ghash, NULL, NULL);
+
+ EXPECT_EQ(TESTCASE_SIZE, BLI_ghash_size(ghash_copy));
+ EXPECT_EQ(BLI_ghash_buckets_size(ghash), BLI_ghash_buckets_size(ghash_copy));
+
+ for (i = TESTCASE_SIZE, k = keys; i--; k++) {
+ void *v = BLI_ghash_lookup(ghash_copy, SET_UINT_IN_POINTER(*k));
+ EXPECT_EQ(*k, GET_UINT_FROM_POINTER(v));
+ }
+
+ BLI_ghash_free(ghash, NULL, NULL);
+ BLI_ghash_free(ghash_copy, NULL, NULL);
+}
diff --git a/tests/gtests/blenlib/BLI_hash_mm2a_test.cc b/tests/gtests/blenlib/BLI_hash_mm2a_test.cc
new file mode 100644
index 00000000000..b35a1a809d6
--- /dev/null
+++ b/tests/gtests/blenlib/BLI_hash_mm2a_test.cc
@@ -0,0 +1,75 @@
+/* Apache License, Version 2.0 */
+
+#include "testing/testing.h"
+
+extern "C" {
+#include "BLI_hash_mm2a.h"
+}
+
+/* Note: Reference results are taken from reference implementation (cpp code, CMurmurHash2A variant):
+ * https://smhasher.googlecode.com/svn-history/r130/trunk/MurmurHash2.cpp
+ */
+
+TEST(hash_mm2a, MM2ABasic)
+{
+ BLI_HashMurmur2A mm2;
+
+ const char *data = "Blender";
+
+ BLI_hash_mm2a_init(&mm2, 0);
+ BLI_hash_mm2a_add(&mm2, (const unsigned char *)data, strlen(data));
+#ifdef __LITTLE_ENDIAN__
+ EXPECT_EQ(1633988145, BLI_hash_mm2a_end(&mm2));
+#else
+ EXPECT_EQ(959283772, BLI_hash_mm2a_end(&mm2));
+#endif
+}
+
+TEST(hash_mm2a, MM2AConcatenateStrings)
+{
+ BLI_HashMurmur2A mm2;
+ uint32_t hash;
+
+ const char *data1 = "Blender";
+ const char *data2 = " is ";
+ const char *data3 = "FaNtAsTiC";
+ const char *data123 = "Blender is FaNtAsTiC";
+
+ BLI_hash_mm2a_init(&mm2, 0);
+ BLI_hash_mm2a_add(&mm2, (const unsigned char *)data1, strlen(data1));
+ BLI_hash_mm2a_add(&mm2, (const unsigned char *)data2, strlen(data2));
+ BLI_hash_mm2a_add(&mm2, (const unsigned char *)data3, strlen(data3));
+ hash = BLI_hash_mm2a_end(&mm2);
+ BLI_hash_mm2a_init(&mm2, 0);
+ BLI_hash_mm2a_add(&mm2, (const unsigned char *)data123, strlen(data123));
+#ifdef __LITTLE_ENDIAN__
+ EXPECT_EQ(1545105348, hash);
+#else
+ EXPECT_EQ(2604964730, hash);
+#endif
+ EXPECT_EQ(hash, BLI_hash_mm2a_end(&mm2));
+}
+
+TEST(hash_mm2a, MM2AIntegers)
+{
+ BLI_HashMurmur2A mm2;
+ uint32_t hash;
+
+ const int ints[4] = {1, 2, 3, 4};
+
+ BLI_hash_mm2a_init(&mm2, 0);
+ BLI_hash_mm2a_add_int(&mm2, ints[0]);
+ BLI_hash_mm2a_add_int(&mm2, ints[1]);
+ BLI_hash_mm2a_add_int(&mm2, ints[2]);
+ BLI_hash_mm2a_add_int(&mm2, ints[3]);
+ hash = BLI_hash_mm2a_end(&mm2);
+ BLI_hash_mm2a_init(&mm2, 0);
+ BLI_hash_mm2a_add(&mm2, (const unsigned char *)ints, sizeof(ints));
+ /* Yes, same hash here on little and big endian. */
+#ifdef __LITTLE_ENDIAN__
+ EXPECT_EQ(405493096, hash);
+#else
+ EXPECT_EQ(405493096, hash);
+#endif
+ EXPECT_EQ(hash, BLI_hash_mm2a_end(&mm2));
+}
diff --git a/tests/gtests/blenlib/BLI_listbase_test.cc b/tests/gtests/blenlib/BLI_listbase_test.cc
index 4b4d5d80a43..994b8f74541 100644
--- a/tests/gtests/blenlib/BLI_listbase_test.cc
+++ b/tests/gtests/blenlib/BLI_listbase_test.cc
@@ -3,10 +3,69 @@
#include "testing/testing.h"
extern "C" {
+#include "BLI_array_utils.h"
#include "BLI_listbase.h"
#include "MEM_guardedalloc.h"
+
+#include "BLI_string.h"
+#include "BLI_path_util.h"
+#include "BLI_ressource_strings.h"
+}
+
+
+/* local validation function */
+static bool listbase_is_valid(const ListBase *listbase)
+{
+#define TESTFAIL(test) \
+ if (!(test)) goto fail;
+
+ if (listbase->first) {
+ const Link *prev, *link;
+ link = (Link *)listbase->first;
+ TESTFAIL(link->prev == NULL);
+
+ link = (Link *)listbase->last;
+ TESTFAIL(link->next == NULL);
+
+ prev = NULL;
+ link = (Link *)listbase->first;
+ do {
+ TESTFAIL(link->prev == prev);
+ } while ((prev = link), (link = link->next));
+ TESTFAIL(prev == listbase->last);
+
+ prev = NULL;
+ link = (Link *)listbase->last;
+ do {
+ TESTFAIL(link->next == prev);
+ } while ((prev = link), (link = link->prev));
+ TESTFAIL(prev == listbase->first);
+ }
+ else {
+ TESTFAIL(listbase->last == NULL);
+ }
+#undef TESTFAIL
+
+ return true;
+
+fail:
+ return false;
+}
+
+static int char_switch(char *string, char ch_src, char ch_dst)
+{
+ int tot = 0;
+ while (*string != 0) {
+ if (*string == ch_src) {
+ *string = ch_dst;
+ tot++;
+ }
+ string++;
+ }
+ return tot;
}
+
TEST(listbase, FindLinkOrIndex)
{
ListBase lb;
@@ -37,3 +96,162 @@ TEST(listbase, FindLinkOrIndex)
BLI_freelistN(&lb);
}
+
+
+/* -------------------------------------------------------------------- */
+/* Sort utilities & test */
+
+static int testsort_array_str_cmp(const void *a, const void *b)
+{
+ int i = strcmp(*(const char **)a, *(const char **)b);
+ return (i > 0) ? 1 : (i < 0) ? -1 : 0;
+}
+
+static int testsort_listbase_str_cmp(const void *a, const void *b)
+{
+ const LinkData *link_a = (LinkData *)a;
+ const LinkData *link_b = (LinkData *)b;
+ int i = strcmp((const char *)link_a->data, (const char *)link_b->data);
+ return (i > 0) ? 1 : (i < 0) ? -1 : 0;
+}
+
+static int testsort_array_str_cmp_reverse(const void *a, const void *b)
+{
+ return -testsort_array_str_cmp(a, b);
+}
+
+static int testsort_listbase_str_cmp_reverse(const void *a, const void *b)
+{
+ return -testsort_listbase_str_cmp(a, b);
+}
+
+/* check array and listbase compare */
+static bool testsort_listbase_array_str_cmp(ListBase *lb, char **arr, int arr_tot)
+{
+ LinkData *link_step;
+ int i;
+
+ link_step = (LinkData *)lb->first;
+ for (i = 0; i < arr_tot; i++) {
+ if (strcmp(arr[i], (char *)link_step->data) != 0) {
+ return false;
+ }
+ link_step = link_step->next;
+ }
+ if (link_step) {
+ return false;
+ }
+
+ return true;
+}
+
+/* assumes nodes are allocated in-order */
+static bool testsort_listbase_sort_is_stable(ListBase *lb, bool forward)
+{
+ LinkData *link_step;
+
+ link_step = (LinkData *)lb->first;
+ while (link_step && link_step->next) {
+ if (strcmp((const char *)link_step->data, (const char *)link_step->next->data) == 0) {
+ if ((link_step < link_step->next) != forward) {
+ return false;
+ }
+ }
+ link_step = link_step->next;
+ }
+ return true;
+}
+
+TEST(listbase, Sort)
+{
+ const int words_len = sizeof(words10k) - 1;
+ char *words = BLI_strdupn(words10k, words_len);
+ int words_tot;
+ char **words_arr; /* qsort for comparison */
+ int i;
+ char *w_step;
+ ListBase words_lb;
+ LinkData *words_linkdata_arr;
+
+ /* delimit words */
+ words_tot = 1 + char_switch(words, ' ', '\0');
+
+ words_arr = (char **)MEM_mallocN(sizeof(*words_arr) * words_tot, __func__);
+
+ words_linkdata_arr = (LinkData *)MEM_mallocN(sizeof(*words_linkdata_arr) * words_tot, __func__);
+
+ /* create array */
+ w_step = words;
+ for (i = 0; i < words_tot; i++) {
+ words_arr[i] = w_step;
+ w_step += strlen(w_step) + 1;
+ }
+
+ /* sort empty list */
+ {
+ BLI_listbase_clear(&words_lb);
+ BLI_listbase_sort(&words_lb, testsort_listbase_str_cmp);
+ EXPECT_TRUE(listbase_is_valid(&words_lb));
+ }
+
+ /* sort single single */
+ {
+ LinkData link;
+ link.data = words;
+ BLI_addtail(&words_lb, &link);
+ BLI_listbase_sort(&words_lb, testsort_listbase_str_cmp);
+ EXPECT_TRUE(listbase_is_valid(&words_lb));
+ BLI_listbase_clear(&words_lb);
+ }
+
+ /* create listbase */
+ BLI_listbase_clear(&words_lb);
+ w_step = words;
+ for (i = 0; i < words_tot; i++) {
+ LinkData *link = &words_linkdata_arr[i];
+ link->data = w_step;
+ BLI_addtail(&words_lb, link);
+ w_step += strlen(w_step) + 1;
+ }
+ EXPECT_TRUE(listbase_is_valid(&words_lb));
+
+ /* sort (forward) */
+ {
+ qsort(words_arr, words_tot, sizeof(*words_arr), testsort_array_str_cmp);
+
+ BLI_listbase_sort(&words_lb, testsort_listbase_str_cmp);
+ EXPECT_TRUE(listbase_is_valid(&words_lb));
+ EXPECT_TRUE(testsort_listbase_array_str_cmp(&words_lb, words_arr, words_tot));
+ EXPECT_TRUE(testsort_listbase_sort_is_stable(&words_lb, true));
+ }
+
+ /* sort (reverse) */
+ {
+ qsort(words_arr, words_tot, sizeof(*words_arr), testsort_array_str_cmp_reverse);
+
+ BLI_listbase_sort(&words_lb, testsort_listbase_str_cmp_reverse);
+ EXPECT_TRUE(listbase_is_valid(&words_lb));
+ EXPECT_TRUE(testsort_listbase_array_str_cmp(&words_lb, words_arr, words_tot));
+ EXPECT_TRUE(testsort_listbase_sort_is_stable(&words_lb, true));
+ }
+
+ /* sort (forward but after reversing, test stability in alternate direction) */
+ {
+ BLI_array_reverse(words_arr, words_tot);
+ BLI_listbase_reverse(&words_lb);
+
+ EXPECT_TRUE(listbase_is_valid(&words_lb));
+ EXPECT_TRUE(testsort_listbase_array_str_cmp(&words_lb, words_arr, words_tot));
+ EXPECT_TRUE(testsort_listbase_sort_is_stable(&words_lb, false));
+
+ /* and again */
+ BLI_array_reverse(words_arr, words_tot);
+ BLI_listbase_sort(&words_lb, testsort_listbase_str_cmp_reverse);
+ EXPECT_TRUE(testsort_listbase_array_str_cmp(&words_lb, words_arr, words_tot));
+ EXPECT_TRUE(testsort_listbase_sort_is_stable(&words_lb, false));
+ }
+
+ MEM_freeN(words);
+ MEM_freeN(words_arr);
+ MEM_freeN(words_linkdata_arr);
+}
diff --git a/tests/gtests/blenlib/BLI_math_base_test.cc b/tests/gtests/blenlib/BLI_math_base_test.cc
new file mode 100644
index 00000000000..0059eb54482
--- /dev/null
+++ b/tests/gtests/blenlib/BLI_math_base_test.cc
@@ -0,0 +1,87 @@
+/* Apache License, Version 2.0 */
+
+#include "testing/testing.h"
+
+#include "BLI_math.h"
+
+/* In tests below, when we are using -1.0f as max_diff value, we actually turn the function into a pure-ULP one. */
+
+/* Put this here, since we cannot use BLI_assert() in inline math files it seems... */
+TEST(math_base, CompareFFRelativeValid)
+{
+ EXPECT_TRUE(sizeof(float) == sizeof(int));
+}
+
+TEST(math_base, CompareFFRelativeNormal)
+{
+ float f1 = 1.99999988f; /* *(float *)&(*(int *)&f2 - 1) */
+ float f2 = 2.00000000f;
+ float f3 = 2.00000048f; /* *(float *)&(*(int *)&f2 + 2) */
+ float f4 = 2.10000000f; /* *(float *)&(*(int *)&f2 + 419430) */
+
+ const float max_diff = FLT_EPSILON * 0.1f;
+
+ EXPECT_TRUE(compare_ff_relative(f1, f2, max_diff, 1));
+ EXPECT_TRUE(compare_ff_relative(f2, f1, max_diff, 1));
+
+ EXPECT_TRUE(compare_ff_relative(f3, f2, max_diff, 2));
+ EXPECT_TRUE(compare_ff_relative(f2, f3, max_diff, 2));
+
+ EXPECT_FALSE(compare_ff_relative(f3, f2, max_diff, 1));
+ EXPECT_FALSE(compare_ff_relative(f2, f3, max_diff, 1));
+
+
+ EXPECT_FALSE(compare_ff_relative(f3, f2, -1.0f, 1));
+ EXPECT_FALSE(compare_ff_relative(f2, f3, -1.0f, 1));
+
+ EXPECT_TRUE(compare_ff_relative(f3, f2, -1.0f, 2));
+ EXPECT_TRUE(compare_ff_relative(f2, f3, -1.0f, 2));
+
+
+ EXPECT_FALSE(compare_ff_relative(f4, f2, max_diff, 64));
+ EXPECT_FALSE(compare_ff_relative(f2, f4, max_diff, 64));
+
+ EXPECT_TRUE(compare_ff_relative(f1, f3, max_diff, 64));
+ EXPECT_TRUE(compare_ff_relative(f3, f1, max_diff, 64));
+}
+
+TEST(math_base, CompareFFRelativeZero)
+{
+ float f0 = 0.0f;
+ float f1 = 4.2038954e-045f; /* *(float *)&(*(int *)&f0 + 3) */
+
+ float fn0 = -0.0f;
+ float fn1 = -2.8025969e-045f; /* *(float *)&(*(int *)&fn0 - 2) */
+
+ const float max_diff = FLT_EPSILON * 0.1f;
+
+ EXPECT_TRUE(compare_ff_relative(f0, f1, -1.0f, 3));
+ EXPECT_TRUE(compare_ff_relative(f1, f0, -1.0f, 3));
+
+ EXPECT_FALSE(compare_ff_relative(f0, f1, -1.0f, 1));
+ EXPECT_FALSE(compare_ff_relative(f1, f0, -1.0f, 1));
+
+ EXPECT_TRUE(compare_ff_relative(fn0, fn1, -1.0f, 8));
+ EXPECT_TRUE(compare_ff_relative(fn1, fn0, -1.0f, 8));
+
+
+ EXPECT_TRUE(compare_ff_relative(f0, f1, max_diff, 1));
+ EXPECT_TRUE(compare_ff_relative(f1, f0, max_diff, 1));
+
+ EXPECT_TRUE(compare_ff_relative(fn0, f0, max_diff, 1));
+ EXPECT_TRUE(compare_ff_relative(f0, fn0, max_diff, 1));
+
+ EXPECT_TRUE(compare_ff_relative(f0, fn1, max_diff, 1));
+ EXPECT_TRUE(compare_ff_relative(fn1, f0, max_diff, 1));
+
+
+ /* Note: in theory, this should return false, since 0.0f and -0.0f have 0x80000000 diff,
+ * but overflow in substraction seems to break something here
+ * (abs(*(int *)&fn0 - *(int *)&f0) == 0x80000000 == fn0), probably because int32 cannot hold this abs value.
+ * this is yet another illustration of why one shall never use (near-)zero floats in pure-ULP comparison. */
+// EXPECT_FALSE(compare_ff_relative(fn0, f0, -1.0f, 1024));
+// EXPECT_FALSE(compare_ff_relative(f0, fn0, -1.0f, 1024));
+
+ EXPECT_FALSE(compare_ff_relative(fn0, f1, -1.0f, 1024));
+ EXPECT_FALSE(compare_ff_relative(f1, fn0, -1.0f, 1024));
+}
diff --git a/tests/gtests/blenlib/BLI_path_util_test.cc b/tests/gtests/blenlib/BLI_path_util_test.cc
index ea761bcf32e..c4ef7c2c970 100644
--- a/tests/gtests/blenlib/BLI_path_util_test.cc
+++ b/tests/gtests/blenlib/BLI_path_util_test.cc
@@ -31,6 +31,7 @@ const char *GHOST_getSystemDir(int version, const char *versionstr)
struct ImBuf;
void IMB_freeImBuf(struct ImBuf *ibuf) {}
+struct ImBuf *IMB_dupImBuf(struct ImBuf *ibuf) {return NULL;}
#ifdef __linux__
char *zLhm65070058860608_br_find_exe(const char *default_exe)
diff --git a/tests/gtests/blenlib/BLI_polyfill2d_test.cc b/tests/gtests/blenlib/BLI_polyfill2d_test.cc
new file mode 100644
index 00000000000..8ca19b11632
--- /dev/null
+++ b/tests/gtests/blenlib/BLI_polyfill2d_test.cc
@@ -0,0 +1,518 @@
+/* Apache License, Version 2.0 */
+
+#include "testing/testing.h"
+
+/* Use to write out OBJ files, handy for checking output */
+// #define USE_OBJ_PREVIEW
+
+/* test every possible offset and reverse */
+#define USE_COMBINATIONS_ALL
+#define USE_BEAUTIFY
+
+extern "C" {
+#include "BLI_array_utils.h"
+#include "BLI_polyfill2d.h"
+#include "BLI_math.h"
+#include "BLI_edgehash.h"
+#include "MEM_guardedalloc.h"
+
+#ifdef USE_OBJ_PREVIEW
+# include "BLI_string.h"
+#endif
+
+#ifdef USE_BEAUTIFY
+#include "BLI_polyfill2d_beautify.h"
+#include "BLI_memarena.h"
+#include "BLI_heap.h"
+#endif
+}
+
+static void polyfill_to_obj(
+ const char *id,
+ const float poly[][2], const unsigned int poly_tot,
+ const unsigned int tris[][3], const unsigned int tris_tot);
+
+/* -------------------------------------------------------------------- */
+/* test utility functions */
+
+#define TRI_ERROR_VALUE (unsigned int)-1
+
+static void test_valid_polyfill_prepare(unsigned int tris[][3], unsigned int tris_tot)
+{
+ unsigned int i;
+ for (i = 0; i < tris_tot; i++) {
+ unsigned int j;
+ for (j = 0; j < 3; j++) {
+ tris[i][j] = TRI_ERROR_VALUE;
+ }
+ }
+}
+
+/**
+ * Basic check for face index values:
+ *
+ * - no duplicates.
+ * - all tris set.
+ * - all verts used at least once.
+ */
+static void test_polyfill_simple(
+ const float poly[][2], const unsigned int poly_tot,
+ const unsigned int tris[][3], const unsigned int tris_tot)
+{
+ unsigned int i;
+ int *tot_used = (int *)MEM_callocN(poly_tot * sizeof(int), __func__);
+ for (i = 0; i < tris_tot; i++) {
+ unsigned int j;
+ for (j = 0; j < 3; j++) {
+ EXPECT_NE(TRI_ERROR_VALUE, tris[i][j]);
+ tot_used[tris[i][j]] += 1;
+ }
+ EXPECT_NE(tris[i][0], tris[i][1]);
+ EXPECT_NE(tris[i][1], tris[i][2]);
+ EXPECT_NE(tris[i][2], tris[i][0]);
+ }
+ for (i = 0; i < poly_tot; i++) {
+ EXPECT_NE(0, tot_used[i]);
+ }
+ MEM_freeN(tot_used);
+}
+
+static void test_polyfill_topology(
+ const float poly[][2], const unsigned int poly_tot,
+ const unsigned int tris[][3], const unsigned int tris_tot)
+{
+ EdgeHash *edgehash = BLI_edgehash_new(__func__);
+ EdgeHashIterator *ehi;
+ unsigned int i;
+ for (i = 0; i < tris_tot; i++) {
+ unsigned int j;
+ for (j = 0; j < 3; j++) {
+ const unsigned int v1 = tris[i][j];
+ const unsigned int v2 = tris[i][(j + 1) % 3];
+ void **p = BLI_edgehash_lookup_p(edgehash, v1, v2);
+ if (p) {
+ *p = (void *)((intptr_t)*p + (intptr_t)1);
+ }
+ else {
+ BLI_edgehash_insert(edgehash, v1, v2, (void *)(intptr_t)1);
+ }
+ }
+ }
+ EXPECT_EQ(poly_tot + (poly_tot - 3), BLI_edgehash_size(edgehash));
+
+ for (i = 0; i < poly_tot; i++) {
+ const unsigned int v1 = i;
+ const unsigned int v2 = (i + 1) % poly_tot;
+ void **p = BLI_edgehash_lookup_p(edgehash, v1, v2);
+ EXPECT_EQ(1, (void *)p != NULL);
+ EXPECT_EQ(1, (intptr_t)*p);
+ }
+
+ for (ehi = BLI_edgehashIterator_new(edgehash), i = 0;
+ BLI_edgehashIterator_isDone(ehi) == false;
+ BLI_edgehashIterator_step(ehi), i++)
+ {
+ void **p = BLI_edgehashIterator_getValue_p(ehi);
+ EXPECT_EQ(true, ELEM((intptr_t)*p, 1, 2));
+ }
+
+ BLI_edgehash_free(edgehash, NULL);
+}
+
+/**
+ * Check all faces are flipped the same way
+ */
+static void test_polyfill_winding(
+ const float poly[][2], const unsigned int poly_tot,
+ const unsigned int tris[][3], const unsigned int tris_tot)
+{
+ unsigned int i;
+ unsigned int count[2] = {0, 0};
+ for (i = 0; i < tris_tot; i++) {
+ float winding_test = cross_tri_v2(poly[tris[i][0]], poly[tris[i][1]], poly[tris[i][2]]);
+ if (fabsf(winding_test) > FLT_EPSILON) {
+ count[winding_test < 0.0f] += 1;
+ }
+ }
+ EXPECT_EQ(true, ELEM(0, count[0], count[1]));
+}
+
+/**
+ * Check the accumulated triangle area is close to the original area.
+ */
+static void test_polyfill_area(
+ const float poly[][2], const unsigned int poly_tot,
+ const unsigned int tris[][3], const unsigned int tris_tot)
+{
+ unsigned int i;
+ const float area_tot = area_poly_v2(poly, poly_tot);
+ float area_tot_tris = 0.0f;
+ const float eps_abs = 0.00001f;
+ const float eps = area_tot > 1.0f ? (area_tot * eps_abs) : eps_abs;
+ for (i = 0; i < tris_tot; i++) {
+ area_tot_tris += area_tri_v2(poly[tris[i][0]], poly[tris[i][1]], poly[tris[i][2]]);
+ }
+ EXPECT_NEAR(area_tot, area_tot_tris, eps);
+}
+
+
+/* -------------------------------------------------------------------- */
+/* Macro and helpers to manage checking */
+/**
+ * Main template for polyfill testing.
+ */
+static void test_polyfill_template_check(
+ const char *id, bool is_degenerate,
+ const float poly[][2], const unsigned int poly_tot,
+ const unsigned int tris[][3], const unsigned int tris_tot)
+{
+ test_polyfill_simple(poly, poly_tot, tris, tris_tot);
+ test_polyfill_topology(poly, poly_tot, tris, tris_tot);
+ if (!is_degenerate) {
+ test_polyfill_winding(poly, poly_tot, tris, tris_tot);
+
+ test_polyfill_area(poly, poly_tot, tris, tris_tot);
+ }
+ polyfill_to_obj(id, poly, poly_tot, tris, tris_tot);
+}
+
+static void test_polyfill_template(
+ const char *id, bool is_degenerate,
+ const float poly[][2], const unsigned int poly_tot,
+ unsigned int tris[][3], const unsigned int tris_tot)
+{
+ test_valid_polyfill_prepare(tris, tris_tot);
+ BLI_polyfill_calc(poly, poly_tot, 0, tris);
+
+ /* check all went well */
+ test_polyfill_template_check(id, is_degenerate, poly, poly_tot, tris, tris_tot);
+
+#ifdef USE_BEAUTIFY
+ /* check beautify gives good results too */
+ {
+ MemArena *pf_arena = BLI_memarena_new(BLI_POLYFILL_ARENA_SIZE, __func__);
+ Heap *pf_heap = BLI_heap_new_ex(BLI_POLYFILL_ALLOC_NGON_RESERVE);
+ EdgeHash *pf_ehash = BLI_edgehash_new_ex(__func__, BLI_POLYFILL_ALLOC_NGON_RESERVE);
+
+ BLI_polyfill_beautify(
+ poly, poly_tot, tris,
+ pf_arena, pf_heap, pf_ehash);
+
+ test_polyfill_template_check(id, is_degenerate, poly, poly_tot, tris, tris_tot);
+
+ BLI_memarena_free(pf_arena);
+ BLI_heap_free(pf_heap, NULL);
+ BLI_edgehash_free(pf_ehash, NULL);
+ }
+#endif
+}
+
+#ifdef USE_COMBINATIONS_ALL
+static void test_polyfill_template_main(
+ const char *id, bool is_degenerate,
+ const float poly[][2], const unsigned int poly_tot,
+ unsigned int tris[][3], const unsigned int tris_tot)
+{
+ /* overkill? - try at _every_ offset & reverse */
+ unsigned int poly_reverse;
+ float (*poly_copy)[2] = (float (*)[2])MEM_mallocN(sizeof(float[2]) * poly_tot, id);
+ float tmp[2];
+
+ memcpy(poly_copy, poly, sizeof(float[2]) * poly_tot);
+
+ for (poly_reverse = 0; poly_reverse < 2; poly_reverse++) {
+ unsigned int poly_cycle;
+
+ if (poly_reverse) {
+ BLI_array_reverse(poly_copy, poly_tot);
+ }
+
+ for (poly_cycle = 0; poly_cycle < poly_tot; poly_cycle++) {
+ // printf("polytest %s ofs=%d, reverse=%d\n", id, poly_cycle, poly_reverse);
+ test_polyfill_template(id, is_degenerate, poly, poly_tot, tris, tris_tot);
+
+ /* cycle */
+ copy_v2_v2(tmp, poly_copy[0]);
+ memmove(&poly_copy[0], &poly_copy[1], (poly_tot - 1) * sizeof(float[2]));
+ copy_v2_v2(poly_copy[poly_tot - 1], tmp);
+ }
+ }
+
+ MEM_freeN(poly_copy);
+}
+#else /* USE_COMBINATIONS_ALL */
+static void test_polyfill_template_main(
+ const char *id, bool is_degenerate,
+ const float poly[][2], const unsigned int poly_tot,
+ unsigned int tris[][3], const unsigned int tris_tot)
+{
+ test_polyfill_template(id, is_degenerate, poly, poly_tot, tris, tris_tot);
+}
+#endif /* USE_COMBINATIONS_ALL */
+
+#define TEST_POLYFILL_TEMPLATE_STATIC(poly, is_degenerate) \
+{ \
+ unsigned int tris[POLY_TRI_COUNT(ARRAY_SIZE(poly))][3]; \
+ const unsigned int poly_tot = ARRAY_SIZE(poly); \
+ const unsigned int tris_tot = ARRAY_SIZE(tris); \
+ const char *id = typeid(*this).name(); \
+ \
+ test_polyfill_template_main(id, is_degenerate, poly, poly_tot, tris, tris_tot); \
+} (void)0
+
+/* -------------------------------------------------------------------- */
+/* visualisation functions (not needed for testing) */
+
+#ifdef USE_OBJ_PREVIEW
+static void polyfill_to_obj(
+ const char *id,
+ const float poly[][2], const unsigned int poly_tot,
+ const unsigned int tris[][3], const unsigned int tris_tot)
+{
+ char path[1024];
+ FILE *f;
+ unsigned int i;
+
+ BLI_snprintf(path, sizeof(path), "%s.obj", id);
+
+ f = fopen(path, "w");
+ if (!f) {
+ return;
+ }
+
+ for (i = 0; i < poly_tot; i++) {
+ fprintf(f, "v %f %f 0.0\n", UNPACK2(poly[i]));
+ }
+
+ for (i = 0; i < tris_tot; i++) {
+ fprintf(f, "f %u %u %u\n", UNPACK3_EX(1 +, tris[i], ));
+ }
+
+ fclose(f);
+}
+#else
+static void polyfill_to_obj(
+ const char *id,
+ const float poly[][2], const unsigned int poly_tot,
+ const unsigned int tris[][3], const unsigned int tris_tot)
+{
+ (void)id;
+ (void)poly, (void)poly_tot;
+ (void)tris, (void)tris_tot;
+}
+#endif /* USE_OBJ_PREVIEW */
+
+
+/* -------------------------------------------------------------------- */
+/* tests */
+
+#define POLY_TRI_COUNT(len) ((len) - 2)
+
+
+/* A counterclockwise triangle */
+TEST(polyfill2d, TriangleCCW)
+{
+ const float poly[][2] = {{0, 0}, {0, 1}, {1, 0}};
+ TEST_POLYFILL_TEMPLATE_STATIC(poly, false);
+}
+
+/* A counterclockwise square */
+TEST(polyfill2d, SquareCCW)
+{
+ const float poly[][2] = {{0, 0}, {0, 1}, {1, 1}, {1, 0}};
+ TEST_POLYFILL_TEMPLATE_STATIC(poly, false);
+}
+
+/* A clockwise square */
+TEST(polyfill2d, SquareCW)
+{
+ const float poly[][2] = {{0, 0}, {1, 0}, {1, 1}, {0, 1}};
+ TEST_POLYFILL_TEMPLATE_STATIC(poly, false);
+}
+
+/* Starfleet insigna */
+TEST(polyfill2d, Starfleet)
+{
+ const float poly[][2] = {{0, 0}, {0.6f, 0.4f}, {1, 0}, {0.5f, 1}};
+ TEST_POLYFILL_TEMPLATE_STATIC(poly, false);
+}
+
+/* Starfleet insigna with repeated point */
+TEST(polyfill2d, StarfleetDegenerate)
+{
+ const float poly[][2] = {{0, 0}, {0.6f, 0.4f}, {0.6f, 0.4f}, {1, 0}, {0.5f, 1}};
+ TEST_POLYFILL_TEMPLATE_STATIC(poly, false);
+}
+
+/* Three collinear points */
+TEST(polyfill2d, 3Colinear)
+{
+ const float poly[][2] = {{0, 0}, {1, 0}, {2, 0}};
+ TEST_POLYFILL_TEMPLATE_STATIC(poly, false);
+}
+
+/* Four collinear points */
+TEST(polyfill2d, 4Colinear)
+{
+ const float poly[][2] = {{0, 0}, {1, 0}, {2, 0}, {3, 0}};
+ TEST_POLYFILL_TEMPLATE_STATIC(poly, false);
+}
+
+/* Non-consecutive collinear points */
+TEST(polyfill2d, UnorderedColinear)
+{
+ const float poly[][2] = {{0, 0}, {1, 1}, {2, 0}, {3, 1}, {4, 0}};
+ TEST_POLYFILL_TEMPLATE_STATIC(poly, false);
+}
+
+/* Plus shape */
+TEST(polyfill2d, PlusShape)
+{
+ const float poly[][2] = {
+ {1, 0}, {2, 0}, {2, 1}, {3, 1}, {3, 2}, {2, 2}, {2, 3}, {1, 3}, {1, 2}, {0, 2}, {0, 1}, {1, 1}};
+ TEST_POLYFILL_TEMPLATE_STATIC(poly, false);
+}
+
+/* Star shape */
+TEST(polyfill2d, StarShape)
+{
+ const float poly[][2] = {
+ {4, 0}, {5, 3}, {8, 4}, {5, 5}, {4, 8}, {3, 5}, {0, 4}, {3, 3}};
+ TEST_POLYFILL_TEMPLATE_STATIC(poly, false);
+}
+
+/* U shape */
+TEST(polyfill2d, UShape)
+{
+ const float poly[][2] = {
+ {1, 0}, {2, 0}, {3, 1}, {3, 3}, {2, 3}, {2, 1}, {1, 1}, {1, 3}, {0, 3}, {0, 1}};
+ TEST_POLYFILL_TEMPLATE_STATIC(poly, false);
+}
+
+/* Spiral */
+TEST(polyfill2d, Spiral)
+{
+ const float poly[][2] = {
+ {1, 0}, {4, 0}, {5, 1}, {5, 4}, {4, 5}, {1, 5}, {0, 4}, {0, 3},
+ {1, 2}, {2, 2}, {3, 3}, {1, 3}, {1, 4}, {4, 4}, {4, 1}, {0, 1}};
+ TEST_POLYFILL_TEMPLATE_STATIC(poly, false);
+}
+
+/* Test case from http:# www.flipcode.com/archives/Efficient_Polygon_Triangulation.shtml */
+TEST(polyfill2d, TestFlipCode)
+{
+ const float poly[][2] = {
+ {0, 6}, {0, 0}, {3, 0}, {4, 1}, {6, 1}, {8, 0}, {12, 0}, {13, 2},
+ {8, 2}, {8, 4}, {11, 4}, {11, 6}, {6, 6}, {4, 3}, {2, 6}};
+ TEST_POLYFILL_TEMPLATE_STATIC(poly, false);
+}
+
+/* Self-intersection */
+TEST(polyfill2d, SelfIntersect)
+{
+ const float poly[][2] = {{0, 0}, {1, 1}, {2, -1}, {3, 1}, {4, 0}};
+ TEST_POLYFILL_TEMPLATE_STATIC(poly, true);
+}
+
+/* Self-touching */
+TEST(polyfill2d, SelfTouch)
+{
+ const float poly[][2] = {
+ {0, 0}, {4, 0}, {4, 4}, {2, 4}, {2, 3}, {3, 3}, {3, 1}, {1, 1}, {1, 3}, {2, 3}, {2, 4}, {0, 4}};
+ TEST_POLYFILL_TEMPLATE_STATIC(poly, false);
+}
+
+/* Self-overlapping */
+TEST(polyfill2d, SelfOverlap)
+{
+ const float poly[][2] = {
+ {0, 0}, {4, 0}, {4, 4}, {1, 4}, {1, 3}, {3, 3}, {3, 1}, {1, 1}, {1, 3}, {3, 3}, {3, 4}, {0, 4}};
+ TEST_POLYFILL_TEMPLATE_STATIC(poly, true);
+}
+
+/* Test case from http:# www.davdata.nl/math/polygons.html */
+TEST(polyfill2d, TestDavData)
+{
+ const float poly[][2] = {
+ {190, 480}, {140, 180}, {310, 100}, {330, 390}, {290, 390}, {280, 260}, {220, 260}, {220, 430}, {370, 430},
+ {350, 30}, {50, 30}, {160, 560}, {730, 510}, {710, 20}, {410, 30}, {470, 440}, {640, 410}, {630, 140},
+ {590, 140}, {580, 360}, {510, 370}, {510, 60}, {650, 70}, {660, 450}, {190, 480}};
+ TEST_POLYFILL_TEMPLATE_STATIC(poly, false);
+}
+
+/* Issue 815, http:# code.google.com/p/libgdx/issues/detail?id=815 */
+TEST(polyfill2d, Issue815)
+{
+ const float poly[][2] = {
+ {-2.0f, 0.0f}, {-2.0f, 0.5f}, {0.0f, 1.0f}, {0.5f, 2.875f},
+ {1.0f, 0.5f}, {1.5f, 1.0f}, {2.0f, 1.0f}, {2.0f, 0.0f}};
+ TEST_POLYFILL_TEMPLATE_STATIC(poly, false);
+}
+
+/* Issue 207, comment #1, http:# code.google.com/p/libgdx/issues/detail?id=207#c1 */
+TEST(polyfill2d, Issue207_1)
+{
+ const float poly[][2] = {
+ {72.42465f, 197.07095f}, {78.485535f, 189.92776f}, {86.12059f, 180.92929f}, {99.68253f, 164.94557f},
+ {105.24325f, 165.79604f}, {107.21862f, 166.09814f}, {112.41958f, 162.78253f}, {113.73238f, 161.94562f},
+ {123.29477f, 167.93805f}, {126.70667f, 170.07617f}, {73.22717f, 199.51062f}};
+ TEST_POLYFILL_TEMPLATE_STATIC(poly, true);
+}
+
+/* Issue 207, comment #11, http:# code.google.com/p/libgdx/issues/detail?id=207#c11 */
+/* Also on issue 1081, http:# code.google.com/p/libgdx/issues/detail?id=1081 */
+TEST(polyfill2d, Issue207_11)
+{
+ const float poly[][2] = {
+ {2400.0f, 480.0f}, {2400.0f, 176.0f}, {1920.0f, 480.0f}, {1920.0459f, 484.22314f},
+ {1920.1797f, 487.91016f}, {1920.3955f, 491.0874f}, {1920.6875f, 493.78125f}, {1921.0498f, 496.01807f},
+ {1921.4766f, 497.82422f}, {1921.9619f, 499.22607f}, {1922.5f, 500.25f}, {1923.085f, 500.92236f},
+ {1923.7109f, 501.26953f}, {1924.3721f, 501.31787f}, {1925.0625f, 501.09375f}, {1925.7764f, 500.62354f},
+ {1926.5078f, 499.9336f}, {1927.251f, 499.0503f}, {1928.0f, 498.0f}, {1928.749f, 496.80908f},
+ {1929.4922f, 495.5039f}, {1930.2236f, 494.11084f}, {1930.9375f, 492.65625f}, {1931.6279f, 491.1665f},
+ {1932.2891f, 489.66797f}, {1932.915f, 488.187f}, {1933.5f, 486.75f}, {1934.0381f, 485.3833f},
+ {1934.5234f, 484.11328f}, {1934.9502f, 482.9663f}, {1935.3125f, 481.96875f}, {1935.6045f, 481.14697f},
+ {1935.8203f, 480.52734f}, {1935.9541f, 480.13623f}, {1936.0f, 480.0f}};
+ TEST_POLYFILL_TEMPLATE_STATIC(poly, false);
+}
+
+/* Issue 1407, http:# code.google.com/p/libgdx/issues/detail?id=1407 */
+TEST(polyfill2d, Issue1407)
+{
+ const float poly[][2] = {
+ {3.914329f, 1.9008259f}, {4.414321f, 1.903619f}, {4.8973203f, 1.9063174f}, {5.4979978f, 1.9096732f}};
+ TEST_POLYFILL_TEMPLATE_STATIC(poly, false);
+}
+
+/* Issue 1407, http:# code.google.com/p/libgdx/issues/detail?id=1407, */
+/* with an additional point to show what is happening. */
+TEST(polyfill2d, Issue1407_pt)
+{
+ const float poly[][2] = {
+ {3.914329f, 1.9008259f}, {4.414321f, 1.903619f}, {4.8973203f, 1.9063174f}, {5.4979978f, 1.9096732f}, {4, 4}};
+ TEST_POLYFILL_TEMPLATE_STATIC(poly, false);
+}
+
+/* Simplified from Blender bug T40777 */
+TEST(polyfill2d, IssueT40777_colinear)
+{
+ const float poly[][2] = {
+ {0.7, 0.37}, {0.7, 0}, {0.76, 0}, {0.76, 0.4}, {0.83, 0.4}, {0.83, 0}, {0.88, 0}, {0.88, 0.4},
+ {0.94, 0.4}, {0.94, 0}, {1, 0}, {1, 0.4}, {0.03, 0.62}, {0.03, 0.89}, {0.59, 0.89}, {0.03, 1},
+ {0, 1}, {0, 0}, {0.03, 0}, {0.03, 0.37}};
+ TEST_POLYFILL_TEMPLATE_STATIC(poly, false);
+}
+
+/* Blender bug T41986 */
+TEST(polyfill2d, IssueT41986_axis_align)
+{
+ const float poly[][2] = {
+ {-0.25, -0.07}, {-0.25, 0.27}, {-1.19, 0.14}, {-0.06, 0.73}, {0.17, 1.25}, {-0.25, 1.07},
+ {-0.38, 1.02}, {-0.25, 0.94}, {-0.40, 0.90}, {-0.41, 0.86}, {-0.34, 0.83}, {-0.25, 0.82},
+ {-0.66, 0.73}, {-0.56, 1.09}, {-0.25, 1.10}, {0.00, 1.31}, {-0.03, 1.47}, {-0.25, 1.53},
+ {0.12, 1.62}, {0.36, 1.07}, {0.12, 0.67}, {0.29, 0.57}, {0.44, 0.45}, {0.57, 0.29},
+ {0.66, 0.12}, {0.68, 0.06}, {0.57, -0.36}, {-0.25, -0.37}, {0.49, -0.74}, {-0.59, -1.21},
+ {-0.25, -0.15}, {-0.46, -0.52}, {-1.08, -0.83}, {-1.45, -0.33}, {-1.25, -0.04}};
+
+ TEST_POLYFILL_TEMPLATE_STATIC(poly, false);
+}
diff --git a/tests/gtests/blenlib/BLI_ressource_strings.h b/tests/gtests/blenlib/BLI_ressource_strings.h
new file mode 100644
index 00000000000..d7002d748c9
--- /dev/null
+++ b/tests/gtests/blenlib/BLI_ressource_strings.h
@@ -0,0 +1,602 @@
+/* Apache License, Version 2.0 */
+
+#ifndef __BLENDER_TESTING_BLI_RESSOURCE_STRING_H__
+#define __BLENDER_TESTING_BLI_RESSOURCE_STRING_H__
+
+const char words10k[] =
+"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam auctor ultrices purus tincidunt mollis. Vestibulum "
+"tincidunt imperdiet molestie. Vivamus posuere, risus ut mollis rutrum, lacus nulla mollis velit, consectetur auctor "
+"erat est in odio. Proin quis lobortis ex. Ut id quam lacus. Morbi ultrices orci quis sem suscipit tincidunt. Nullam "
+"ut molestie justo, vulputate placerat diam. Nunc tincidunt auctor venenatis. Phasellus placerat, odio ac dictum "
+"pretium, nisi odio tristique sem, sit amet hendrerit odio tortor eu felis. Duis placerat tristique neque, sit amet "
+"ornare nulla fermentum vel. Vivamus vitae rhoncus ante. Sed a dolor mauris. Nullam bibendum vehicula semper. Duis ut "
+"commodo nibh. Nulla sit amet eros feugiat, accumsan nisl a, ornare quam. In non magna orci. Curabitur finibus tempus "
+"semper. Aliquam fringilla arcu consectetur blandit vestibulum. Mauris mollis est arcu. Praesent pellentesque lacus "
+"bibendum massa commodo commodo. Aenean facilisis lobortis varius. Ut semper ullamcorper dui, at pellentesque felis. "
+"Duis accumsan sapien ut malesuada lacinia. Praesent elementum venenatis arcu in mattis. Nunc sagittis mauris risus, "
+"quis rutrum nisi egestas quis. Maecenas pharetra posuere auctor. Suspendisse mollis sollicitudin elit, id cursus "
+"massa bibendum eu. Integer tincidunt dolor non porttitor tempus. Donec lacinia sapien eu enim feugiat suscipit non "
+"malesuada diam. Suspendisse nec convallis elit. Nulla eu augue ultrices, consequat lorem at, malesuada magna. "
+"Aliquam sed tempor ipsum. Sed hendrerit nec lectus et pharetra. In felis sem, cursus at nunc in, tristique convallis "
+"purus. Praesent augue turpis, porttitor consequat risus ornare, laoreet commodo dui. Nulla congue ultrices sapien a "
+"cursus. Nulla facilisi. Integer lacinia enim sodales sem mattis, sit amet egestas lectus tincidunt. Ut quis nisl ut "
+"ex luctus fermentum quis et diam. Maecenas lectus leo, hendrerit eu facilisis et, mattis ut sem. Duis imperdiet nisl "
+"vitae urna consequat suscipit. Suspendisse sed viverra massa, dapibus condimentum sem. Morbi suscipit congue odio. "
+"Nullam eleifend fringilla nisl et semper. Sed eu neque ante. Sed eget viverra urna. Duis tempor laoreet interdum. "
+"Nunc fringilla aliquet urna sit amet commodo. Curabitur non orci nec libero egestas ullamcorper nec nec velit. Nam "
+"vitae ligula lobortis, vehicula nulla id, lacinia urna. Morbi id dignissim eros. Etiam eu risus in sem vestibulum "
+"dapibus ut mollis sem. Quisque ultricies pulvinar maximus. Proin risus turpis, auctor eget molestie nec, molestie a "
+"ipsum. Donec dapibus dui in lorem rhoncus, non rutrum neque convallis. Donec at tincidunt turpis, nec scelerisque "
+"lorem. Donec ac sapien mi. Sed commodo efficitur tempus. Maecenas eu lobortis diam. Phasellus enim nulla, ornare ac "
+"laoreet egestas, vestibulum ac arcu. Pellentesque ultrices mauris sem, a iaculis diam tristique id. Proin sed "
+"facilisis mauris. Aliquam nibh ex, varius in consequat laoreet, sollicitudin id diam. Vivamus semper ultrices sem "
+"non tempor. Sed hendrerit maximus malesuada. In ex orci, elementum non magna eget, congue sagittis tellus. Donec "
+"malesuada sem leo, quis malesuada risus blandit et. Praesent porta malesuada metus eget pretium. Vestibulum "
+"venenatis tempor tellus at varius. Donec mauris arcu, elementum vitae aliquet nec, ullamcorper vitae neque. Nunc eu "
+"viverra justo, sit amet viverra elit. Proin urna elit, luctus ut placerat quis, blandit vitae diam. Vestibulum id "
+"fringilla enim. Ut eleifend augue ante, ac euismod sapien luctus sit amet. Pellentesque mattis tortor ac rutrum "
+"malesuada. Sed et nulla id metus faucibus condimentum. Vestibulum cursus posuere vestibulum. Proin auctor arcu erat, "
+"quis porta sem dignissim a. Donec sed finibus ante. Integer porttitor pretium nunc, eu semper elit. Nam sit amet "
+"ornare urna. Suspendisse porta augue id massa luctus maximus. Fusce tellus ligula, finibus sed lacus eget, tristique "
+"mollis libero. Vivamus velit diam, faucibus vel fringilla vitae, ornare id lacus. Pellentesque vel sem quis nunc "
+"semper porta ut sit amet sapien. Integer nec leo at tortor ullamcorper pulvinar at ut ante. Fusce velit nisl, "
+"fermentum in tempus ac, gravida ac tellus. In aliquet sollicitudin erat, non vestibulum diam aliquam in. Duis purus "
+"justo, aliquet ut libero vel, egestas mollis nibh. Praesent sed tempor mauris, vel tempor augue. Morbi eu eros vel "
+"velit condimentum porttitor nec sit amet odio. Nunc suscipit risus at ex aliquam, in pretium mi maximus. Mauris "
+"sollicitudin sit amet arcu luctus maximus. Curabitur vehicula condimentum porta. Nunc consequat vitae urna vel "
+"gravida. Vivamus vitae mattis augue, sit amet blandit enim. Phasellus odio leo, cursus eget lacus sit amet, "
+"facilisis mattis tortor. Duis venenatis ante libero, eu condimentum urna viverra fermentum. Suspendisse libero leo, "
+"pretium eu leo at, imperdiet ultricies nunc. Fusce ante neque, feugiat id lacus sed, fringilla suscipit ligula. "
+"Phasellus cursus malesuada urna, vel ullamcorper massa suscipit vitae. In eu bibendum augue. Duis auctor posuere "
+"turpis nec vestibulum. Vestibulum nec dui in mi consequat auctor sed at nisl. Suspendisse tellus elit, congue ut "
+"facilisis vel, ornare id mauris. Integer rutrum fermentum neque, vitae pharetra metus consectetur in. Duis vitae "
+"lacus scelerisque, rhoncus nisl id, sagittis elit. Praesent lacinia libero ac ultricies tempus. Etiam ut maximus "
+"sapien. Maecenas sit amet ante auctor, feugiat diam non, vulputate diam. Nulla facilisi. Vestibulum id augue velit. "
+"Donec at elementum urna. Morbi elementum nunc in neque ornare, sit amet tempor mauris vulputate. Nunc mauris mauris, "
+"lobortis non nibh sed, gravida sollicitudin nunc. Nunc vel dolor non augue venenatis semper vitae non turpis. "
+"Praesent mattis elit eu interdum porttitor. Etiam quis magna magna. Praesent a ipsum est. Aenean at ligula vel leo "
+"faucibus pulvinar sed eget mauris. Nam accumsan blandit nibh, nec tincidunt nisl eleifend sit amet. Etiam ornare, "
+"arcu nec dictum volutpat, nulla orci porttitor orci, vel venenatis mi massa at erat. Maecenas eget accumsan nisl, "
+"quis ullamcorper turpis. Pellentesque sit amet mi aliquet, feugiat felis in, dictum urna. Cras nulla leo, congue vel "
+"consequat gravida, aliquet a nulla. Nulla commodo, nisi eu ultricies feugiat, justo velit tempor ligula, a tincidunt "
+"nisi tellus ut sapien. Sed eget ornare magna. Cras ut vehicula sapien. Quisque id malesuada urna, vitae congue ante. "
+"Donec nec leo pretium, finibus nibh a, porta lectus. Fusce arcu tellus, tempor semper sem id, aliquam fringilla "
+"ipsum. Ut massa ante, placerat quis sapien quis, sollicitudin blandit turpis. Aenean posuere ullamcorper massa. Nam "
+"faucibus egestas arcu. Vivamus vehicula auctor diam, eu placerat diam ullamcorper at. Nulla eu consequat elit, vel "
+"semper turpis. Curabitur rhoncus nunc vel vestibulum interdum. Nam augue neque, pharetra vel nisi dignissim, "
+"vehicula dapibus risus. Cras eget mattis nisi. Sed tempor posuere gravida. Proin sagittis a nisl eget gravida. "
+"Curabitur viverra dapibus arcu, sit amet rutrum nibh fringilla euismod. Donec vitae risus non lorem facilisis cursus "
+"eu eu quam. Donec quis lacus blandit, consectetur elit ut, sagittis ligula. Etiam dapibus ex sit amet elit commodo "
+"finibus. Suspendisse non finibus felis, non cursus libero. Vivamus semper aliquet velit vel elementum. Phasellus "
+"dictum, tortor id sagittis ultrices, ex dui porttitor tortor, nec mattis dolor sem nec mi. Ut aliquam consequat eros "
+"sit amet mollis. Nullam mollis venenatis porttitor. Donec sit amet velit at velit luctus auctor dictum in neque. Ut "
+"vulputate ultricies mollis. Pellentesque elementum augue dolor, non varius ligula tristique ac. Nullam eget mauris "
+"urna. Integer elementum eleifend pulvinar. Morbi gravida ante eget ornare faucibus. Mauris pulvinar consequat nunc "
+"vel accumsan. Curabitur egestas urna elit, ut accumsan magna dictum in. Nam neque mi, ornare sed leo at, tempor "
+"vulputate nunc. Nunc dignissim mauris id dui iaculis fringilla. Praesent malesuada tellus in dapibus feugiat. "
+"Vivamus posuere, nisi et consequat euismod, lorem augue iaculis velit, eget iaculis neque quam eu mi. Nullam ac "
+"hendrerit felis, non elementum ipsum. Aliquam erat volutpat. Proin vel molestie felis. Nullam luctus vel ante nec "
+"facilisis. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Duis et metus "
+"justo. Interdum et malesuada fames ac ante ipsum primis in faucibus. Ut tristique sit amet elit et congue. Aenean "
+"quis elementum enim, vitae pharetra sem. Vestibulum vel finibus nisl, at consequat eros. In vitae mollis lacus, et "
+"pharetra elit. Mauris varius sapien quis tincidunt blandit. Proin non semper nibh. Aliquam non elit id felis laoreet "
+"interdum eget a risus. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. "
+"Suspendisse nisl tellus, mollis id erat vel, hendrerit volutpat nunc. Quisque scelerisque cursus tellus, nec "
+"placerat quam imperdiet in. Sed porttitor arcu vel ligula finibus, a vestibulum enim ultrices. Fusce imperdiet augue "
+"eget est vehicula porttitor. Quisque convallis odio vitae lorem porttitor iaculis. Ut dictum velit ac tortor "
+"lobortis ultrices. Vestibulum tincidunt vestibulum mauris, at fermentum elit imperdiet nec. Nunc finibus ornare "
+"lorem vel malesuada. Praesent arcu turpis, pulvinar sit amet accumsan quis, tincidunt vel justo. Pellentesque "
+"volutpat nec enim sit amet pulvinar. Nam eu libero dignissim, volutpat elit ut, semper tortor. Morbi pellentesque "
+"nisl lectus. In vel tellus sed sem luctus lobortis ut nec diam. Phasellus id semper sem. Phasellus in purus "
+"consequat, rhoncus mi mollis, finibus ligula. Fusce feugiat dictum consequat. Mauris egestas, est ut euismod "
+"consequat, arcu dui dignissim quam, pharetra dignissim orci dolor quis nisl. Nunc dapibus blandit urna non feugiat. "
+"Suspendisse non maximus augue. Quisque ut orci aliquet, vulputate massa eget, mattis diam. Etiam efficitur "
+"consectetur viverra. Nulla massa augue, elementum at turpis et, cursus ultricies risus. Suspendisse vel nibh "
+"placerat, imperdiet elit et, viverra ligula. Donec lorem lorem, hendrerit nec aliquam sit amet, scelerisque sit amet "
+"massa. Mauris convallis ullamcorper tortor sed malesuada. Fusce ultricies a turpis eu ornare. Suspendisse potenti. "
+"Sed non nulla condimentum, vulputate nisi nec, tincidunt arcu. Morbi erat leo, lobortis id odio ac, hendrerit "
+"sodales sem. Ut malesuada, lectus at posuere molestie, orci metus vehicula justo, mattis tincidunt arcu risus quis "
+"odio. Fusce non sem sed nisi consectetur finibus vitae quis diam. Vivamus a lacinia nisl. Praesent tempus nunc "
+"gravida, lacinia lacus in, lobortis massa. Aliquam gravida consequat nisi at fringilla. Quisque tortor tortor, "
+"tincidunt cursus lorem eget, ultrices ultricies lacus. Phasellus mattis iaculis elit, eget mattis nisl bibendum sed. "
+"Integer faucibus gravida nisl, ac consequat ex tempor at. Sed tempus elementum vestibulum. Suspendisse vitae enim "
+"semper, pulvinar diam eget, suscipit turpis. Maecenas ultricies, diam sed consectetur sagittis, diam sem cursus "
+"nisl, nec aliquet tellus augue quis ipsum. Cras vel lorem convallis, mattis risus at, placerat massa. Curabitur vel "
+"rutrum ligula. Quisque in nibh libero. Pellentesque diam tellus, consectetur eget quam ac, faucibus imperdiet odio. "
+"Sed tortor nulla, scelerisque non turpis nec, fringilla bibendum est. Etiam a urna eget erat tincidunt ultrices. "
+"Maecenas lorem odio, volutpat nec ligula id, hendrerit aliquam nulla. Aenean congue lacinia fermentum. Suspendisse "
+"sed interdum lacus. Fusce scelerisque posuere sagittis. Ut at semper tellus. Donec condimentum orci nunc, non "
+"fermentum purus volutpat eget. Maecenas elementum dapibus ante, eu suscipit quam imperdiet ut. Integer non congue "
+"elit. Sed venenatis, turpis varius commodo euismod, libero magna fringilla lacus, quis venenatis velit lectus sed "
+"augue. Morbi gravida orci odio, ut ornare massa sollicitudin a. Donec convallis mi et sapien tempor, non dapibus "
+"dolor fringilla. Aenean euismod rutrum turpis, et facilisis orci porttitor eu. Suspendisse in neque leo. Nulla "
+"facilisi. Etiam mollis orci nisl, quis scelerisque metus efficitur vehicula. Nam porta molestie tortor, sit amet "
+"consectetur leo vestibulum vel. Pellentesque a volutpat augue. Maecenas vel elementum ex, eget elementum leo. "
+"Curabitur at maximus metus, quis porttitor orci. Praesent auctor commodo elit, a dapibus tortor volutpat et. "
+"Praesent dictum posuere dolor sit amet molestie. Sed viverra augue nec eros mattis blandit. In quis sodales dolor. "
+"Donec sed purus ex. Fusce erat magna, efficitur ac tempus ac, lacinia quis augue. Aliquam porta efficitur est vel "
+"placerat. Phasellus egestas vel nunc eu consequat. Maecenas ligula arcu, molestie ut dui ut, ornare finibus felis. "
+"Duis condimentum non augue ut posuere. Aenean mattis eros ut ligula ornare finibus. Aliquam feugiat ut turpis a "
+"feugiat. Vestibulum eget sollicitudin orci, nec fermentum justo. Praesent efficitur est a metus bibendum, eget "
+"feugiat diam suscipit. Suspendisse sit amet ipsum ut purus feugiat pretium. Morbi nisl risus, ultricies sit amet "
+"ullamcorper euismod, commodo eu libero. Aenean fringilla ipsum nec orci rutrum aliquet. Aenean lacus ante, eleifend "
+"eu eleifend fringilla, elementum ac justo. Vestibulum tincidunt interdum lectus sit amet fermentum. Etiam rhoncus eu "
+"ante lacinia sagittis. Maecenas iaculis ut erat quis feugiat. Maecenas sed est vel tellus bibendum rutrum volutpat "
+"nec odio. Vivamus euismod augue nec purus euismod, mattis finibus nisi finibus. Donec quis ultrices massa. Quisque "
+"at nisl faucibus, facilisis tellus ut, ultricies dui. Class aptent taciti sociosqu ad litora torquent per conubia "
+"nostra, per inceptos himenaeos. Donec et arcu eros. Etiam dapibus bibendum felis eu viverra. Integer a lacus "
+"venenatis elit lacinia facilisis non non felis. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed "
+"ultricies augue at sapien mattis aliquam. Quisque nec semper purus. Cras auctor aliquet lacus, sed facilisis urna "
+"sollicitudin non. Vivamus eget erat purus. Sed a risus augue. Donec non sem sed sapien accumsan lacinia. Ut mauris "
+"odio, vehicula id accumsan at, tincidunt non odio. Nunc porttitor luctus ante ac cursus. Cras et dapibus ex, id "
+"pretium ligula. Proin volutpat rhoncus ex vitae venenatis. Pellentesque imperdiet, magna non tempus auctor, metus "
+"dolor scelerisque dui, id tempor purus est in risus. Suspendisse vehicula imperdiet sapien, nec pulvinar dolor "
+"ornare ac. Nulla luctus, nisl in aliquam blandit, risus orci placerat nunc, id tempus sem neque vitae leo. Aenean at "
+"elit elit. Suspendisse finibus dictum interdum. Nunc consectetur eget quam vitae egestas. Pellentesque tellus augue, "
+"aliquet at faucibus ac, imperdiet ut nulla. Maecenas quis lorem velit. Donec porta ligula et suscipit luctus. "
+"Aliquam sed pretium nunc. Nunc quis posuere tortor. Fusce in lectus nec turpis rhoncus pellentesque eu at quam. "
+"Nulla facilisi. Sed ante nulla, posuere ac ullamcorper vel, rhoncus vitae nisl. Nam non pellentesque arcu. Vivamus "
+"nibh leo, pellentesque a mollis non, gravida ut erat. Donec purus urna, pulvinar eu iaculis blandit, rutrum eget "
+"nulla. Fusce quis fermentum diam, faucibus volutpat lorem. Maecenas aliquet nisi nisl, eget sollicitudin ipsum "
+"facilisis at. Mauris nec sapien nisi. Duis ac laoreet sapien, a condimentum nisi. Nam vitae sapien sed sem convallis "
+"ornare. Pellentesque neque diam, ullamcorper et dolor sit amet, faucibus venenatis tortor. Nunc vel erat malesuada, "
+"vulputate odio sit amet, aliquam dui. Donec tincidunt arcu ut risus laoreet, id malesuada leo ultrices. Praesent a "
+"scelerisque libero, vitae suscipit massa. Quisque faucibus mauris rhoncus turpis vestibulum rhoncus. Donec vel "
+"molestie magna. Aenean et lorem dui. Nam iaculis ante sapien, semper tincidunt tortor hendrerit id. Nulla sed orci "
+"mi. Aliquam hendrerit libero erat, ac aliquam massa rutrum non. Suspendisse eleifend, elit in aliquet hendrerit, "
+"tellus erat sodales neque, quis rhoncus tellus sem vitae est. Interdum et malesuada fames ac ante ipsum primis in "
+"faucibus. Etiam quis mauris non ipsum tristique interdum sit amet eget mi. Ut velit risus, gravida ut efficitur sit "
+"amet, commodo at diam. Sed consectetur dui porttitor quam feugiat, et auctor mauris maximus. Nullam lobortis ac mi "
+"lacinia egestas. Proin ante massa, malesuada ut nulla elementum, venenatis mollis ante. Cum sociis natoque penatibus "
+"et magnis dis parturient montes, nascetur ridiculus mus. Mauris eget gravida eros, non varius velit. Integer "
+"consectetur lectus nec arcu scelerisque, scelerisque vulputate mauris suscipit. Aliquam orci dui, faucibus et rutrum "
+"in, rhoncus quis dolor. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; "
+"Maecenas ante nunc, placerat id lectus sit amet, luctus cursus ante. Nulla nec placerat arcu. Fusce ac dictum ex. "
+"Vivamus semper nulla vitae neque volutpat, auctor vestibulum arcu tempus. Pellentesque aliquam tincidunt arcu, et "
+"pharetra neque. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Nunc "
+"risus augue, malesuada quis risus a, suscipit semper metus. Suspendisse ac rhoncus felis. Aliquam orci lectus, "
+"elementum at nulla at, ullamcorper pellentesque leo. Quisque nisi tellus, pharetra in pellentesque in, facilisis "
+"vitae velit. In ex ex, sagittis at dolor vel, congue ultricies velit. Duis quis gravida mi. Aenean tempor efficitur "
+"lectus. Fusce sodales, ex eu efficitur iaculis, metus sem eleifend purus, ut commodo arcu tortor eget urna. Etiam "
+"nisi nisl, malesuada convallis ex at, malesuada elementum nunc. Vivamus commodo mi id ligula tincidunt posuere. "
+"Integer eget arcu cursus, sagittis quam eu, aliquam leo. In auctor eget mauris et elementum. Aenean sagittis euismod "
+"tellus sed accumsan. Aliquam erat volutpat. Aliquam erat volutpat. Ut consectetur porta ipsum sit amet porttitor. "
+"Nam ut nunc a turpis auctor finibus. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac "
+"turpis egestas. Donec non nisl condimentum, fermentum augue in, egestas libero. Pellentesque ut odio rhoncus, "
+"sollicitudin felis vitae, pellentesque est. Suspendisse tincidunt eros eget ex vestibulum elementum. Vivamus mollis "
+"scelerisque diam, quis dignissim dolor venenatis at. Ut gravida sapien vitae risus efficitur, ut auctor justo "
+"gravida. Cras arcu elit, interdum vel purus sit amet, venenatis molestie tellus. Integer consectetur tempor velit a "
+"varius. Praesent congue, massa non congue blandit, tortor purus imperdiet elit, sit amet pharetra arcu lacus egestas "
+"neque. Maecenas in erat arcu. In varius, risus vitae mollis sodales, nisi velit bibendum tortor, vitae sagittis "
+"augue tortor quis nunc. Fusce posuere dolor ac tincidunt facilisis. Phasellus in lacus diam. Fusce mattis sapien "
+"tellus, scelerisque pharetra leo eleifend nec. Cras libero diam, convallis in luctus a, iaculis a ipsum. Duis arcu "
+"leo, volutpat non mauris et, scelerisque suscipit diam. Ut vulputate placerat velit quis placerat. Duis commodo non "
+"turpis et convallis. Duis nec pulvinar metus, ac tristique leo. Fusce vehicula augue ac placerat elementum. Nulla "
+"dapibus nisi pretium lectus sodales, ac congue sapien ornare. Vestibulum sagittis orci ut purus efficitur, eu mollis "
+"libero placerat. Vestibulum ullamcorper odio non quam mollis, eget rhoncus metus eleifend. Mauris scelerisque, massa "
+"rutrum sodales malesuada, elit dolor blandit lectus, quis faucibus felis odio feugiat lacus. Nunc bibendum congue "
+"efficitur. Nunc a purus neque. In lobortis metus nisi, vel pellentesque mi facilisis sed. Donec in pretium neque, in "
+"maximus metus. Integer faucibus diam sed tristique sagittis. Nullam eget maximus leo, eget malesuada leo. Vestibulum "
+"ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Aenean porttitor risus eget eros "
+"euismod molestie. Integer tristique tincidunt elit, non posuere libero pretium vel. Fusce dapibus, nisi nec egestas "
+"dapibus, lectus arcu maximus leo, a finibus diam arcu ut mauris. Vivamus tincidunt lectus ut augue ultrices, et "
+"cursus sem cursus. Proin in quam mauris. Maecenas vel magna dapibus, interdum ipsum mattis, posuere tortor. Cras eu "
+"massa ex. Donec eget massa vel dui gravida luctus vel a quam. Etiam eu lobortis neque. Etiam ligula dui, dictum ut "
+"turpis ac, eleifend pretium turpis. Vestibulum convallis finibus commodo. Morbi fermentum ante nunc, a rhoncus lacus "
+"ultricies quis. Suspendisse finibus quam blandit odio elementum, non efficitur diam laoreet. Cras aliquet ligula "
+"eget magna scelerisque, ut ornare nisi elementum. Duis nisl massa, suscipit id nibh a, venenatis auctor risus. Nulla "
+"luctus eget odio quis ultrices. Etiam consequat sapien ut nisl mollis cursus. Pellentesque a lacinia odio, id varius "
+"lorem. Curabitur scelerisque in urna eget pretium. Class aptent taciti sociosqu ad litora torquent per conubia "
+"nostra, per inceptos himenaeos. Sed leo metus, fermentum vitae quam ut, suscipit efficitur purus. Sed facilisis "
+"dapibus pulvinar. Cras sed eleifend mi. Sed quis nibh in sapien venenatis interdum ac nec orci. Sed non tortor urna. "
+"Nam rutrum lacinia diam id vehicula. Quisque vitae lobortis nibh, at tempor purus. Suspendisse dictum interdum nisi, "
+"quis maximus ipsum commodo tempus. Nulla semper congue gravida. Aenean at nibh in eros aliquam egestas. Nulla "
+"fermentum efficitur laoreet. Donec non lorem nec augue porttitor cursus eu in quam. Aenean laoreet quam neque, at "
+"tempus nisi ultrices id. Quisque in diam lacinia nulla scelerisque rhoncus vitae eget nulla. Donec vel est metus. "
+"Nullam suscipit odio eu enim lacinia facilisis eget in tellus. Vestibulum vehicula risus nec odio consectetur, a "
+"cursus massa imperdiet. Duis facilisis felis quis nunc mattis, nec volutpat libero tempor. Nulla nec leo sed tellus "
+"maximus lobortis. Suspendisse at urna nibh. Vestibulum eget turpis nisl. Donec scelerisque neque auctor erat tempor "
+"elementum sed id lacus. Sed metus nulla, dictum non luctus vel, suscipit et ex. Quisque laoreet sapien non neque "
+"iaculis, at aliquam massa viverra. Nullam nibh diam, imperdiet eu nunc sed, congue cursus leo. Morbi tristique diam "
+"metus, at faucibus magna mollis at. Sed eget nibh nunc. Nam nec elementum sem, sit amet tincidunt lorem. In viverra "
+"elit et interdum fermentum. Integer imperdiet orci ac justo molestie ullamcorper. Pellentesque fringilla tortor "
+"erat, scelerisque maximus nisl sollicitudin a. Integer nisi elit, pharetra eget lacinia non, congue sit amet ex. "
+"Phasellus tempus suscipit ultrices. Quisque ac nibh dignissim erat bibendum cursus vel a enim. Curabitur a augue sit "
+"amet lorem pharetra feugiat. Donec euismod, massa at venenatis bibendum, elit libero pellentesque velit, eget congue "
+"metus risus a enim. Aenean pretium vestibulum enim, sit amet vulputate urna auctor vitae. Praesent porttitor erat eu "
+"mi cursus venenatis. Maecenas ut ultrices neque, ac feugiat libero. Nulla finibus sit amet sem in auctor. Nam "
+"fermentum maximus ex, et consequat velit lobortis id. Aliquam eu feugiat est. Donec quis leo ex. Suspendisse "
+"convallis eget nulla eu aliquet. Quisque aliquet tortor vitae ipsum fermentum tristique. Sed convallis rutrum augue, "
+"ac viverra est pharetra quis. Ut porttitor magna massa, placerat maximus lectus scelerisque quis. Sed viverra urna "
+"in neque feugiat rhoncus. Donec ut viverra odio, laoreet dignissim dui. Aenean tristique feugiat diam vel luctus. "
+"Cras sit amet condimentum neque, ut faucibus ante. Aenean vitae elit id est laoreet efficitur in sit amet magna. "
+"Praesent ante felis, blandit id nisl ut, porta fringilla orci. Aenean vel accumsan metus, vel vehicula metus. Nulla "
+"placerat nibh et auctor convallis. Maecenas magna metus, pretium ac sodales ac, eleifend quis eros. Praesent "
+"volutpat quam a pulvinar pharetra. Sed arcu dolor, aliquet nec magna in, faucibus consequat lorem. In tincidunt, ex "
+"a finibus rutrum, metus dui fringilla ex, ac mollis elit leo eget augue. Nunc vehicula facilisis nibh, quis "
+"ultricies sem. Praesent nulla est, finibus in lorem in, mattis placerat urna. Proin hendrerit risus nunc, id congue "
+"ex posuere id. Aenean ullamcorper tortor quis lorem consectetur, et euismod leo fermentum. Praesent vulputate congue "
+"lectus sit amet pulvinar. Vestibulum vel vestibulum quam, in convallis diam. Maecenas sollicitudin magna odio, eget "
+"mollis purus posuere eu. Curabitur molestie mattis ligula, a maximus dui fermentum ut. Fusce justo velit, eleifend "
+"ut tellus vitae, volutpat maximus risus. Pellentesque suscipit mauris non purus placerat porta. Nunc in malesuada "
+"mi, vel bibendum felis. Aenean pretium nunc id efficitur porttitor. Mauris malesuada, tortor sit amet blandit "
+"tincidunt, tellus est ullamcorper diam, sit amet aliquet ex velit interdum quam. In hac habitasse platea dictumst. "
+"Sed vitae est eu elit posuere mattis nec a mauris. Morbi id ligula sed nunc sagittis finibus vitae eu nisi. Cras "
+"dignissim sagittis tellus a suscipit. Nunc semper erat nec libero vestibulum, at mattis purus scelerisque. "
+"Pellentesque egestas volutpat eleifend. Nullam venenatis erat id diam venenatis, sed rhoncus felis hendrerit. Nullam "
+"luctus facilisis risus. Mauris sed urna nisi. Ut tempus feugiat metus. Integer at purus velit. Praesent neque felis, "
+"pellentesque vitae sem nec, tempor commodo urna. Morbi malesuada ante sit amet purus tincidunt pellentesque. Aenean "
+"commodo lectus sit amet dignissim hendrerit. Phasellus auctor tellus ligula, eu ultrices ex egestas non. Mauris eget "
+"nisl dictum, scelerisque sapien et, dapibus felis. Aenean in dignissim leo. Sed semper, ex at euismod molestie, ex "
+"odio ullamcorper nisi, et facilisis lectus eros non magna. In hac habitasse platea dictumst. Pellentesque sed "
+"maximus mauris. Cras luctus dapibus nunc, sit amet suscipit dui viverra nec. Donec gravida tortor porttitor orci "
+"malesuada porttitor. Nunc condimentum eu libero sit amet varius. Curabitur mollis urna eu porta tincidunt. Nullam "
+"ultricies magna libero, et dapibus tellus tempus eu. Nullam pretium lectus nec iaculis pretium. Maecenas at arcu "
+"lobortis, ornare ante nec, euismod metus. Pellentesque volutpat tellus nulla. Aenean mattis efficitur velit vitae "
+"blandit. Duis vel egestas eros. Pellentesque aliquam placerat elit, eu congue sem ullamcorper sit amet. Ut erat "
+"nisl, luctus vitae pellentesque ut, tristique eu odio. Pellentesque nec fermentum ex, rhoncus varius dui. Mauris "
+"lobortis nunc nec dui volutpat consequat. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur "
+"ridiculus mus. Aliquam dignissim purus sed ligula pretium placerat. In vestibulum ultricies mauris. Curabitur "
+"aliquet lorem quis libero auctor, ut rhoncus purus lobortis. Nulla elementum erat nec rhoncus posuere. Integer "
+"faucibus quam sed elementum fringilla. In in lobortis sapien, nec commodo tortor. Aenean euismod ipsum nisi, vitae "
+"fringilla leo imperdiet ut. Donec a semper odio, et tempor magna. Cras cursus vel augue quis egestas. Nam nec tortor "
+"blandit, mattis quam imperdiet, finibus quam. Pellentesque tincidunt eros urna, ut tristique diam faucibus "
+"condimentum. Ut dictum risus mi, non sollicitudin turpis facilisis sit amet. Morbi finibus scelerisque mattis. Fusce "
+"vel tempor purus, nec pharetra augue. Curabitur dapibus, orci eu consectetur ultrices, diam mauris sodales urna, non "
+"euismod diam lacus luctus risus. Mauris commodo accumsan sapien. Proin vel blandit sapien. Donec porta tortor vel "
+"nibh faucibus molestie. Pellentesque placerat justo erat, vitae tristique felis fringilla eget. Quisque facilisis "
+"justo at orci lobortis, ut commodo diam egestas. Etiam non tristique nisl. Cras varius, massa a sollicitudin ornare, "
+"turpis arcu fringilla leo, non euismod ligula arcu id lacus. Suspendisse potenti. Morbi pharetra dolor eget porta "
+"tristique. Nullam sem tortor, lobortis eget hendrerit a, efficitur sit amet sapien. Fusce sit amet condimentum odio, "
+"aliquet rutrum velit. Morbi vel rhoncus ante. In blandit eros ut lectus varius, quis tempor arcu iaculis. In massa "
+"leo, venenatis nec lobortis non, pulvinar non nunc. Nunc vehicula, erat vitae placerat eleifend, eros ipsum "
+"consectetur odio, eu ornare velit mauris nec sapien. Integer a consequat libero. Quisque velit augue, blandit eu "
+"luctus sit amet, laoreet sit amet odio. Etiam in enim lacus. Interdum et malesuada fames ac ante ipsum primis in "
+"faucibus. In rutrum a tortor id pulvinar. Donec pretium lorem sed sem eleifend fringilla. Fusce sollicitudin ac "
+"ligula eget pharetra. Sed cursus diam non sem ullamcorper efficitur. Vivamus congue ligula iaculis justo iaculis "
+"elementum. Integer tempor nisl arcu, ut tincidunt erat vestibulum et. Suspendisse rutrum aliquet eros non "
+"pellentesque. Mauris laoreet, diam id tincidunt faucibus, risus velit venenatis risus, in venenatis justo diam et "
+"orci. Etiam pulvinar pulvinar nisi, id efficitur erat vulputate ut. Sed suscipit sodales ante, a blandit orci "
+"maximus vel. Vestibulum at aliquet orci. Proin tincidunt nisi quis eros consequat consectetur. Praesent congue "
+"lobortis laoreet. Donec imperdiet risus erat, eu volutpat justo posuere id. Fusce placerat sollicitudin eros vitae "
+"tincidunt. Sed orci ante, ultricies sed dapibus vel, sagittis ac massa. Pellentesque vel mauris nec est hendrerit "
+"posuere. Integer sagittis diam sed felis facilisis ultrices. Aliquam erat volutpat. Nulla pharetra justo in ipsum "
+"dapibus, nec viverra nunc euismod. Nulla massa ante, euismod at interdum vel, dapibus ut ex. Etiam consequat mauris "
+"a suscipit lobortis. Donec commodo convallis velit, eget commodo urna vulputate ac. Sed molestie vel dui ut feugiat. "
+"Donec orci purus, placerat vitae egestas sed, sodales nec ex. Sed egestas turpis non malesuada semper. Donec et mi a "
+"nisi volutpat sagittis. Suspendisse potenti. Phasellus mollis sapien ac tellus imperdiet tempus. Praesent nec sapien "
+"sit amet ipsum interdum interdum non eget nunc. Aenean fringilla lorem a viverra rutrum. Donec at maximus nibh. "
+"Phasellus facilisis justo sit amet metus pharetra sagittis. Quisque mollis metus laoreet ipsum tincidunt "
+"sollicitudin. Maecenas sit amet dictum ligula. Fusce molestie iaculis dui, et gravida libero hendrerit in. Praesent "
+"euismod libero metus, vitae rhoncus velit ultrices eget. Vestibulum ac massa bibendum, gravida dolor vel, dapibus "
+"est. Etiam non elit varius, mollis purus eget, placerat velit. Nullam lectus dui, mattis at pulvinar eu, elementum "
+"et lorem. Sed vel auctor orci, nec semper neque. Nullam cursus commodo quam, in ultricies tellus rhoncus vulputate. "
+"Mauris dapibus ipsum ipsum, dapibus euismod purus pellentesque at. Nullam euismod lectus non risus consequat "
+"vulputate. Quisque finibus a turpis eu convallis. Nam magna turpis, feugiat ut urna in, tempus facilisis elit. Duis "
+"dignissim purus sagittis porttitor posuere. Suspendisse varius ligula at egestas scelerisque. Duis placerat sagittis "
+"nisi, et molestie tortor posuere condimentum. Morbi hendrerit, ante ornare tempus finibus, ex ipsum laoreet dui, vel "
+"ornare felis tortor sit amet metus. Vivamus laoreet placerat massa, non suscipit nisl faucibus eget. Vestibulum ante "
+"ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Pellentesque orci lacus, vulputate cursus ex "
+"eu, porta aliquam massa. Proin dolor massa, faucibus vel rhoncus et, venenatis a nisi. Vivamus venenatis enim mi. "
+"Sed viverra augue vitae lectus lobortis vulputate. Phasellus ac ligula congue, sagittis est non, aliquet tortor. "
+"Suspendisse faucibus euismod neque, ac congue felis. Curabitur maximus neque sit amet odio varius gravida. Proin "
+"egestas nulla eget mi bibendum luctus. Ut non mollis mi. Quisque finibus, eros non lobortis interdum, diam nisi "
+"faucibus diam, non imperdiet leo velit et dolor. Nam est massa, vehicula sed diam sed, laoreet convallis nisi. Donec "
+"enim ligula, dignissim non sem ut, pulvinar cursus mi. In at dignissim nulla, ac fringilla neque. In hac habitasse "
+"platea dictumst. Quisque luctus mattis orci, consequat egestas nisi. Vivamus et metus et quam porttitor elementum. "
+"Suspendisse auctor mauris eu sollicitudin sagittis. Vivamus ac ante non augue iaculis consectetur quis quis dui. In "
+"bibendum risus tristique ligula iaculis finibus. Phasellus non ante risus. Maecenas ac leo cursus, molestie purus "
+"sed, tristique purus. Etiam sem nulla, aliquam nec laoreet nec, iaculis quis nulla. Maecenas id dui id neque "
+"venenatis gravida. Etiam vestibulum felis at diam porta ultrices. Ut finibus tortor et augue ornare, et efficitur "
+"purus scelerisque. Phasellus et ultricies arcu, vel lacinia lacus. Aenean tincidunt eleifend nunc, sit amet mattis "
+"purus venenatis sit amet. Curabitur eleifend sem nisl, et feugiat diam pharetra sit amet. Mauris ullamcorper mi vel "
+"condimentum egestas. Nulla pulvinar purus vel sagittis posuere. Nulla quis enim bibendum, iaculis quam in, tincidunt "
+"quam. Vestibulum rhoncus volutpat risus. Nulla ultricies bibendum est non malesuada. Nunc porta erat est, a "
+"tincidunt magna gravida vel. Maecenas sit amet aliquet odio. Vestibulum egestas, tortor scelerisque consectetur "
+"pharetra, nisi tellus feugiat justo, et bibendum libero mi in diam. Aliquam tempus sapien nec tristique convallis. "
+"Nullam congue, lacus quis bibendum dignissim, nisl purus molestie dolor, a tempor dolor nibh pretium tellus. In hac "
+"habitasse platea dictumst. Cras at est turpis. Nam nec lacus posuere, mattis mi eu, viverra ex. Nullam eleifend "
+"ornare orci, vel tempor tellus. Ut nec eros eget tortor tempus tristique commodo sed lorem. Donec quis scelerisque "
+"nibh, non tincidunt velit. Fusce in eleifend sapien. Nunc sodales sem ut nunc pellentesque, eget pharetra justo "
+"tempor. Proin pretium velit et vehicula interdum. Maecenas luctus venenatis tincidunt. Donec hendrerit, ligula non "
+"volutpat porta, dui ante facilisis massa, at congue orci mi sed quam. Donec lorem ipsum, malesuada quis purus in, "
+"commodo malesuada justo. Etiam luctus, lorem vel rutrum tristique, mauris urna volutpat felis, a laoreet urna nunc "
+"et neque. Morbi a diam tincidunt augue cursus commodo nec ut ligula. Maecenas ultrices purus fermentum ullamcorper "
+"aliquet. Maecenas mi enim, semper nec metus at, posuere tristique ligula. Suspendisse est elit, porta quis massa id, "
+"gravida commodo ante. Nullam maximus mauris sit amet dolor tempus posuere. Phasellus purus mi, interdum in ipsum "
+"quis, tristique venenatis dolor. Suspendisse potenti. Phasellus odio erat, varius sed aliquet vestibulum, laoreet "
+"sed mauris. Vivamus sapien erat, maximus tristique elementum ac, eleifend in enim. Morbi accumsan elementum neque, a "
+"facilisis enim laoreet non. Donec auctor condimentum fringilla. Proin id urna nec tellus maximus maximus tincidunt "
+"et libero. Integer ultricies venenatis odio, ut volutpat odio laoreet non. Donec in scelerisque justo. Integer "
+"mauris libero, fringilla vel sapien sit amet, laoreet tincidunt dolor. Nam efficitur sagittis arcu, vel lobortis dui "
+"gravida non. Curabitur lobortis feugiat finibus. Vestibulum dictum tortor nec magna fringilla blandit. Nulla "
+"facilisi. Sed cursus laoreet neque vitae pulvinar. Ut iaculis euismod ullamcorper. Nunc in hendrerit lectus, sed "
+"venenatis mi. Suspendisse et est dui. Sed elementum augue non ornare cursus. Quisque varius facilisis magna nec "
+"laoreet. Suspendisse consequat, risus sed tempus egestas, velit felis faucibus erat, eu pharetra erat nisl sed "
+"turpis. Sed ultricies ac quam id mollis. In consequat et erat vitae interdum. Pellentesque malesuada feugiat ligula "
+"eu consectetur. Vestibulum tempor mi quis purus luctus dictum. Etiam condimentum ac ligula eget imperdiet. Ut "
+"placerat, tortor eu lacinia imperdiet, enim nibh aliquam nibh, quis faucibus enim odio eu arcu. Nullam sagittis, "
+"diam a ornare congue, ipsum eros scelerisque est, sit amet sagittis nisl tellus in felis. Nam eget ornare turpis. "
+"Sed tempor ac enim a vestibulum. Pellentesque eleifend lacus non libero accumsan, ut consectetur sapien lacinia. "
+"Etiam ut arcu non mi feugiat accumsan ut sit amet risus. Donec consequat eros sapien, malesuada imperdiet justo "
+"bibendum sit amet. Nulla pretium varius lectus, in eleifend quam fringilla in. Quisque eu pretium velit. Sed eget "
+"lectus sit amet tortor blandit tempus vel at sapien. Sed at velit porta, venenatis lorem sed, dapibus arcu. Donec "
+"pellentesque tortor id massa interdum pretium. Praesent id diam quis nunc dictum finibus quis quis ipsum. Quisque "
+"consectetur risus eu elit viverra, eget laoreet odio efficitur. In congue turpis iaculis ullamcorper bibendum. Duis "
+"at elit et velit varius vulputate ut ac turpis. Nunc posuere, urna id lobortis ornare, neque ex ultricies erat, id "
+"sollicitudin ante quam sed magna. Nunc ultrices quam erat, eget dictum libero sollicitudin in. Nulla facilisi. "
+"Pellentesque eleifend risus non justo imperdiet aliquet. Donec finibus auctor ornare. Duis in arcu lacinia, "
+"fermentum tellus vel, efficitur justo. Morbi nec nunc leo. Proin lacinia erat vel elementum dapibus. Proin diam "
+"ipsum, mollis eu lobortis a, facilisis consectetur est. Vestibulum rutrum pellentesque urna, a laoreet justo dictum "
+"vitae. Nullam dictum, mi elementum dictum interdum, sem nisl fermentum est, nec mattis enim ante aliquam tortor. "
+"Phasellus eu quam magna. Vivamus augue enim, dictum in nibh non, condimentum tristique lorem. Suspendisse potenti. "
+"Sed nibh lacus, auctor ut arcu sollicitudin, posuere tempor urna. Phasellus at odio euismod ipsum congue auctor. "
+"Fusce vestibulum elementum nunc, vel feugiat nibh bibendum at. Quisque felis ligula, fermentum a metus ac, pulvinar "
+"hendrerit est. Proin vitae tincidunt purus, vestibulum eleifend ipsum. Ut rhoncus et elit ut varius. Praesent eu "
+"pharetra tellus. Suspendisse varius, dui quis efficitur fermentum, est lectus ultricies ex, a fermentum orci nunc eu "
+"lorem. Integer aliquet nunc ullamcorper lacinia elementum. In cursus tortor nisi, ut pharetra tortor venenatis eu. "
+"Duis tincidunt, libero sed varius dictum, neque velit facilisis enim, eget bibendum mi eros et nisl. Nam turpis "
+"neque, lobortis eget ante ac, tristique congue lacus. Aenean dictum vitae tortor sed tristique. Donec sodales in "
+"arcu ut tristique. Curabitur in facilisis nisi, non vulputate odio. Phasellus ut fringilla nunc, nec dapibus turpis. "
+"Sed ut erat tempor sem vulputate gravida at at dui. Aenean id dolor ante. Morbi auctor interdum nisi, id pretium "
+"eros ultrices vel. Nulla eget justo fringilla, finibus quam et, accumsan ex. In nisl neque, pharetra nec volutpat "
+"at, mattis nec odio. Nam et sapien sed libero lacinia tempor sit amet vitae turpis. Praesent vel porta lacus, porta "
+"dignissim nunc. Aenean vitae vulputate purus. Ut at elit arcu. Integer risus neque, varius ac elit maximus, "
+"ultricies sagittis nisi. Pellentesque sapien magna, malesuada tincidunt ornare sed, malesuada tempor odio. Morbi id "
+"neque velit. Pellentesque at velit sed elit eleifend auctor. Quisque tincidunt tempus justo, venenatis dapibus sem "
+"pellentesque quis. Suspendisse finibus feugiat est id consectetur. Nulla commodo, massa auctor vulputate egestas, "
+"arcu massa tincidunt leo, quis ullamcorper sapien augue in nibh. Pellentesque ultrices ligula tincidunt urna "
+"fringilla, ac ultricies eros convallis. Ut nec massa diam. Maecenas justo nulla, dapibus id justo sollicitudin, "
+"fermentum tempor dui. Vivamus laoreet auctor mi non venenatis. Nulla commodo libero ac ex volutpat tincidunt. Donec "
+"vestibulum blandit purus bibendum laoreet. Morbi in porta orci. Nam commodo ex eget diam maximus cursus. Proin "
+"bibendum quis felis eget euismod. Praesent neque neque, pulvinar eu sem non, gravida ornare tortor. Ut tortor nisi, "
+"suscipit in lectus ac, volutpat pretium nisi. Nam rutrum nec dui quis vulputate. Duis in velit enim. Fusce porttitor "
+"vitae nisi a tincidunt. Ut enim purus, venenatis ut purus ut, iaculis dignissim ex. Aliquam erat volutpat. "
+"Suspendisse potenti. Maecenas ut malesuada elit. Maecenas tellus neque, pulvinar non metus ut, viverra finibus diam. "
+"Sed ac porttitor dui. Fusce sit amet ligula metus. Integer id aliquet libero. Sed tempor nisl in porttitor "
+"ultricies. Maecenas molestie orci sed sapien molestie interdum non id felis. Nullam sagittis elementum erat in "
+"pretium. Nunc pellentesque, ex sit amet fringilla dignissim, augue quam dictum leo, eget tristique turpis mauris sed "
+"metus. Praesent vel mauris risus. Etiam eleifend metus ut risus tempor, ac ultrices dolor dictum. Nulla sagittis non "
+"urna vitae feugiat. In venenatis arcu vel finibus volutpat. Nam non bibendum magna, nec eleifend ex. Etiam sit amet "
+"nisl euismod, mattis nisi quis, commodo nisl. Nunc eget mauris vulputate, cursus neque in, hendrerit ante. Cras non "
+"nisl in nisl laoreet aliquam. Sed vestibulum, nunc vitae molestie varius, lectus justo vehicula est, nec placerat "
+"ipsum lectus quis leo. Maecenas efficitur semper eros, sed pretium arcu blandit eu. Aliquam eget purus cursus, "
+"sollicitudin augue quis, cursus purus. Maecenas sed finibus ligula. Curabitur at diam quis eros mollis semper. Nulla "
+"commodo nisi libero, id feugiat nisl tincidunt bibendum. Mauris convallis tincidunt justo eu sodales. Quisque arcu "
+"lacus, finibus sed hendrerit at, convallis ut diam. Nulla enim nulla, efficitur quis tincidunt et, pulvinar sit amet "
+"enim. Aenean mattis urna id mauris maximus tincidunt. In hac habitasse platea dictumst. Morbi ornare porta congue. "
+"Aliquam hendrerit efficitur mi at aliquet. Vivamus rutrum lectus vel turpis volutpat, consectetur congue sem "
+"consectetur. Sed rhoncus elit sed orci tincidunt, ut condimentum diam ornare. Nulla facilisi. Ut placerat et massa "
+"nec malesuada. Praesent dapibus condimentum augue, at imperdiet lacus facilisis sed. Praesent at metus nunc. Morbi "
+"accumsan eros et turpis viverra, nec sagittis odio iaculis. Aenean rhoncus, nibh a consectetur sodales, massa lorem "
+"commodo dui, sit amet consequat ex arcu eget augue. Praesent quis nibh urna. Cras eu congue ligula, in ultricies "
+"ante. Etiam interdum, est tincidunt euismod sollicitudin, lectus felis mollis ex, pretium fringilla magna lorem non "
+"libero. Fusce aliquam tellus eget sodales commodo. Sed sapien lectus, dapibus quis elit at, ultricies tincidunt "
+"eros. Nulla suscipit orci sit amet aliquam pellentesque. Cras sed eleifend ligula, quis vehicula ligula. Integer "
+"quis tortor in mauris dictum malesuada sed non turpis. Nulla faucibus quis arcu molestie vulputate. Proin fermentum "
+"tellus feugiat, imperdiet mi sit amet, tempor sem. Mauris hendrerit augue a vulputate vulputate. Vivamus sagittis at "
+"odio non venenatis. Nunc a molestie dolor. Nunc erat nisi, consequat et tristique in, blandit non tortor. Vivamus "
+"euismod bibendum augue, ut aliquam lorem mattis quis. Duis laoreet odio at justo ultricies, nec scelerisque enim "
+"euismod. Sed eu turpis a lorem cursus feugiat. Duis ultrices molestie nulla non pharetra. Morbi faucibus est auctor "
+"faucibus placerat. Donec blandit quis ex ac pulvinar. Vestibulum a consequat quam. Fusce vitae facilisis ex. Etiam a "
+"risus eu orci tincidunt interdum. Proin interdum eros nec nibh venenatis, sed luctus sapien tincidunt. In cursus, "
+"ante nec dapibus bibendum, augue tortor venenatis felis, eu aliquam erat est vitae diam. Cras lacinia placerat quam, "
+"eu finibus purus. Aenean et augue purus. Praesent efficitur ornare magna in cursus. Nunc quis tempor ante, ac "
+"accumsan ligula. Nullam elit diam, tempus in sollicitudin at, fermentum tincidunt mi. Vestibulum accumsan, nisi at "
+"rutrum scelerisque, justo mauris cursus nulla, finibus cursus nulla elit quis augue. Aliquam lacus ante, ullamcorper "
+"quis varius vitae, ullamcorper eget magna. Phasellus mollis nisl eu nulla eleifend, non tempus tellus faucibus. "
+"Curabitur molestie eros id eleifend accumsan. Suspendisse tristique sem ante, non blandit eros accumsan ac. Ut sit "
+"amet ante justo. Nam condimentum felis quis urna sagittis hendrerit. Cras condimentum est ac massa aliquet finibus. "
+"Donec faucibus malesuada fermentum. Aliquam malesuada augue vitae dolor rutrum pellentesque. Nullam vulputate "
+"rhoncus porta. Quisque vulputate dignissim felis sit amet aliquet. Nam elementum odio velit, eget fringilla mi "
+"dignissim at. Mauris mollis diam orci, vel porta risus tempor a. Nullam quis dolor volutpat, ornare est at, "
+"fermentum urna. Fusce mollis nisl a augue condimentum, eu dictum dolor posuere. Mauris et egestas sem. Sed pretium "
+"lectus laoreet velit feugiat luctus. Nullam sodales at augue vel semper. Pellentesque vehicula dictum augue, eget "
+"tristique orci interdum a. Aenean non est eleifend, tristique urna sed, elementum nunc. Sed consectetur id lorem "
+"quis mollis. Ut et blandit velit, et lobortis dolor. Quisque nec odio sed mi ullamcorper pellentesque. Ut vitae "
+"eleifend nisi, vitae dapibus est. Vivamus ornare eleifend volutpat. Sed et tincidunt nisi. Praesent maximus risus a "
+"bibendum consequat. Vestibulum quis ex vitae ante ultricies ultricies. Maecenas dictum tellus eget enim tincidunt "
+"imperdiet. Quisque vel libero gravida, mollis erat id, placerat dolor. Etiam ante eros, bibendum vitae ultricies in, "
+"rhoncus nec turpis. Pellentesque gravida nunc sit amet iaculis condimentum. Phasellus in ultricies libero, et "
+"maximus justo. Donec ut ultrices elit. Interdum et malesuada fames ac ante ipsum primis in faucibus. Pellentesque "
+"rhoncus, nunc at iaculis dictum, magna lectus rhoncus augue, vel aliquam sem mauris in metus. Morbi commodo purus "
+"mi, ut faucibus dui luctus et. Suspendisse accumsan placerat tortor. Cras dignissim blandit leo, non tincidunt leo. "
+"Nulla euismod turpis ac malesuada aliquam. Ut ultrices bibendum elit sed elementum. Donec auctor aliquam vehicula. "
+"Mauris lacinia dignissim leo, ullamcorper egestas nibh rutrum eget. In semper sit amet libero eget ultricies. Proin "
+"et imperdiet odio. In hac habitasse platea dictumst. In hac habitasse platea dictumst. Integer sed dolor quis tortor "
+"pretium euismod at vel dolor. Donec aliquet et urna at porta. Vestibulum tincidunt eget sapien elementum mattis. "
+"Proin lacinia faucibus orci, sed eleifend augue mollis et. Vestibulum ante ipsum primis in faucibus orci luctus et "
+"ultrices posuere cubilia Curae; Cras pellentesque, dolor eget bibendum tincidunt, turpis ante pharetra tortor, quis "
+"interdum tellus tellus sit amet nisl. Nulla convallis tempus egestas. Curabitur quis condimentum metus, eu placerat "
+"metus. Nunc ligula nunc, posuere at iaculis nec, convallis id tellus. Curabitur pretium libero lorem, quis placerat "
+"nunc fringilla interdum. Vestibulum et finibus ante. Duis quis nisi neque. Curabitur ornare lorem nec ex fringilla, "
+"et porta massa consequat. Nulla malesuada turpis nec eleifend tincidunt. Praesent ultricies dolor vitae mauris "
+"lacinia tempor. Sed blandit sapien a odio scelerisque consequat. Mauris non dictum eros. Vestibulum ante ipsum "
+"primis in faucibus orci luctus et ultrices posuere cubilia Curae; Pellentesque habitant morbi tristique senectus et "
+"netus et malesuada fames ac turpis egestas. In ut sollicitudin tellus. Suspendisse ultrices vitae erat non pharetra. "
+"Nulla pellentesque at diam venenatis sollicitudin. Vestibulum sed finibus sapien. Curabitur a metus convallis, "
+"euismod est id, iaculis nunc. Vestibulum laoreet ornare turpis. Integer rhoncus, felis nec fermentum suscipit, dui "
+"lacus sagittis ligula, vitae vestibulum urna elit aliquam est. Sed sit amet mi tortor. Suspendisse a dapibus velit. "
+"Cras eget imperdiet turpis. Maecenas at lorem condimentum, elementum augue mattis, rutrum purus. Duis imperdiet "
+"pellentesque nunc, eu tristique lectus malesuada commodo. Vivamus aliquet congue eros ac dapibus. Nunc quis "
+"porttitor odio. Nulla quis dui luctus, vestibulum enim malesuada, imperdiet elit. Donec facilisis mollis diam ut "
+"posuere. Nulla facilisi. Duis nec magna lacus. Vestibulum consequat ut tortor ut ornare. Curabitur nec felis sit "
+"amet dui finibus rutrum. Phasellus sit amet lectus nec nisl egestas posuere. Etiam nec euismod magna, vitae "
+"ullamcorper enim. Vestibulum pretium cursus semper. Cras vel lorem ut urna molestie elementum. Mauris luctus vel "
+"arcu quis egestas. Suspendisse potenti. Nullam viverra sollicitudin lacus luctus sodales. Maecenas eget diam cursus "
+"quam tincidunt ultricies vitae nec lacus. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec urna "
+"sapien, porta a efficitur vitae, imperdiet vel ligula. Nulla volutpat massa sit amet est aliquet, ut iaculis tellus "
+"convallis. Sed justo tortor, sodales non nisi quis, laoreet commodo quam. Cras tempus purus a tempor malesuada. "
+"Curabitur enim nibh, viverra in enim eget, viverra euismod nunc. Mauris nunc leo, faucibus blandit condimentum nec, "
+"rutrum sit amet leo. Quisque nec tortor sed felis pretium imperdiet. Morbi lobortis, dolor nec lobortis maximus, "
+"turpis justo aliquet massa, eget aliquet nunc mauris a lectus. Phasellus dignissim, est nec luctus consequat, ex "
+"nisi euismod lacus, a viverra nulla eros et est. Suspendisse in egestas dolor. Etiam non placerat lorem. "
+"Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Aliquam ut enim "
+"tristique, porta nulla quis, placerat eros. Integer eget feugiat mi, ac condimentum felis. Fusce auctor ligula ut "
+"est placerat efficitur. Nam hendrerit condimentum ante eget tincidunt. Phasellus vel convallis neque. Vivamus sit "
+"amet elit eu enim iaculis scelerisque. Donec imperdiet lacus id magna luctus, vitae dapibus quam condimentum. Donec "
+"laoreet vehicula tellus. Nullam nec neque at massa ultricies dignissim. Suspendisse potenti. Cras convallis nunc "
+"urna, a tempor metus volutpat ut. Fusce viverra lorem vitae quam ullamcorper cursus. Mauris maximus et mi eget "
+"tincidunt. Proin molestie suscipit felis at ultricies. Duis varius rhoncus metus vehicula bibendum. Aliquam "
+"consequat non tellus at aliquam. Vivamus nec turpis facilisis, dapibus lacus in, congue tortor. Curabitur at "
+"interdum mi, sed rhoncus nibh. Morbi facilisis purus laoreet, tincidunt justo sit amet, elementum lectus. Vestibulum "
+"pellentesque sem lacus, in condimentum purus consequat at. Integer pharetra rhoncus aliquam. Duis nec sem ac elit "
+"suscipit laoreet. Integer vel est commodo, feugiat sapien eget, cursus quam. Aenean elit leo, interdum a posuere "
+"nec, laoreet eu magna. Nam sit amet felis faucibus, porttitor justo eget, commodo mi. Maecenas a eleifend nibh. "
+"Donec ut ornare augue. Aliquam pellentesque aliquet eros in hendrerit. Nullam consectetur odio id lectus ullamcorper "
+"facilisis. Donec pulvinar, magna non sollicitudin commodo, erat lacus egestas massa, a egestas nibh nulla ac lorem. "
+"Maecenas at mi posuere, fringilla lectus sed, fringilla eros. Vivamus mattis at magna ac suscipit. Proin varius mi a "
+"quam efficitur ullamcorper. Curabitur venenatis turpis lacus, vitae volutpat velit ultricies sed. Sed faucibus id "
+"neque in consequat. Nulla imperdiet fermentum placerat. Donec rutrum libero ac lorem commodo pellentesque in tempor "
+"augue. Maecenas sodales cursus ex, ac elementum felis consectetur vel. Cras ante nulla, porttitor nec ex non, "
+"venenatis consectetur justo. Nam vitae enim eget augue euismod suscipit et in nulla. Morbi eu sollicitudin libero, "
+"ut lobortis purus. Pellentesque sodales tempor diam, a luctus dui vehicula tempus. Cum sociis natoque penatibus et "
+"magnis dis parturient montes, nascetur ridiculus mus. Vestibulum dignissim sagittis diam ac aliquam. Integer iaculis "
+"ac est eu molestie. Vivamus convallis arcu nec rutrum molestie. Vestibulum mollis ipsum neque. Vestibulum "
+"condimentum neque quis tellus elementum, in facilisis neque venenatis. Donec quis ultrices risus. Cras mattis felis "
+"eget erat iaculis, id scelerisque mauris pharetra. Vivamus condimentum tempor ipsum, porta commodo erat dictum ut. "
+"Fusce et ligula sed arcu tincidunt efficitur nec ut felis. Donec eu justo pellentesque, finibus diam quis, iaculis "
+"erat. Fusce a tempus urna, at fermentum est. Sed pretium orci dapibus ante laoreet, a consequat erat scelerisque. "
+"Etiam nisi tortor, vulputate quis sapien sit amet, lobortis blandit felis. Morbi urna purus, pellentesque quis orci "
+"id, suscipit consequat velit. Donec vehicula ipsum felis. Donec at elit ipsum. Fusce purus sapien, convallis quis "
+"faucibus et, tempus at dolor. Vivamus commodo sem ac congue imperdiet. Vivamus convallis eget est eu vulputate. "
+"Aliquam vehicula augue ac urna imperdiet interdum. Praesent euismod arcu quis purus vestibulum, et placerat metus "
+"hendrerit. Fusce semper lacus sit amet ligula scelerisque scelerisque. Vestibulum neque ex, aliquam non lorem a, "
+"aliquam fringilla enim. Aenean consectetur vestibulum tortor. Donec et elit consectetur, tincidunt augue feugiat, "
+"condimentum diam. In luctus tellus at massa euismod faucibus. Ut tempus dui hendrerit, vehicula ex ut, facilisis "
+"lacus. Pellentesque bibendum enim auctor, vulputate justo vel, ultricies est. Praesent interdum turpis in convallis "
+"luctus. Duis vel enim venenatis, mollis elit vitae, mattis velit. In eu posuere nibh. Duis a est est. Nam semper "
+"tincidunt nulla id dignissim. Fusce consectetur maximus eros quis posuere. Sed efficitur, enim quis ultrices "
+"eleifend, est diam commodo dui, nec euismod augue velit sit amet ante. Integer fringilla vehicula faucibus. "
+"Curabitur non placerat turpis. Integer malesuada quam eget sapien tristique aliquet. In hac habitasse platea "
+"dictumst. Cras dignissim mauris neque, in facilisis nulla pulvinar ac. Phasellus sagittis ligula non sem aliquet "
+"iaculis. Integer interdum elit in dolor vehicula, non condimentum justo pretium. Aliquam eget feugiat tellus. "
+"Suspendisse condimentum dui at erat elementum semper. Aliquam vitae cursus lorem. Ut vestibulum porttitor purus ut "
+"dapibus. Curabitur posuere nunc quis nisi rhoncus, ac mollis enim eleifend. Aenean tristique at justo ut tempor. "
+"Proin posuere condimentum arcu ac lobortis. Proin euismod posuere ipsum, nec dignissim velit eleifend gravida. "
+"Quisque quis sem mi. Proin scelerisque consequat lectus nec sodales. Fusce id sapien a erat cursus sodales. Morbi ac "
+"magna vitae lorem dictum luctus in et lacus. Morbi imperdiet mi interdum, molestie sem in, accumsan leo. Sed lacinia "
+"enim et sem egestas, a pulvinar velit ullamcorper. Aenean laoreet, erat eu viverra dictum, eros odio venenatis mi, "
+"tincidunt blandit odio mauris id augue. Donec pretium mauris nibh, ut eleifend velit auctor vitae. Morbi tincidunt "
+"lacus id ullamcorper egestas. Proin vel porttitor purus, eu fermentum dui. Aliquam a interdum mi. Aliquam ut rhoncus "
+"nibh. Morbi nulla libero, commodo quis eros eu, scelerisque gravida ligula. Aliquam sed arcu nunc. Sed egestas "
+"hendrerit orci, nec rhoncus arcu fringilla quis. Pellentesque lobortis nulla arcu. Integer aliquam vel quam sed "
+"tempor. Morbi viverra tempus risus vel convallis. Cras eget neque ex. Mauris porta, risus at rhoncus hendrerit, "
+"libero metus pharetra sapien, quis viverra tortor nunc tincidunt magna. Aenean a tellus ullamcorper, convallis urna "
+"quis, suscipit sem. Vivamus eu eleifend est. Duis venenatis metus eget ex consequat molestie. In ullamcorper a dolor "
+"vitae feugiat. Morbi ultrices vestibulum venenatis. Phasellus luctus enim id aliquet pharetra. Aenean mauris felis, "
+"finibus eu dolor at, tempor sodales diam. Sed nisl nibh, tincidunt quis fringilla vel, congue eu dui. Duis viverra "
+"justo eu sem ultricies dignissim. Morbi et sollicitudin erat. Proin id porttitor odio, et sagittis ex. Aenean "
+"laoreet leo sit amet risus vestibulum, mollis ultrices tortor porttitor. Sed vestibulum varius ligula quis accumsan. "
+"Duis fermentum, dolor iaculis condimentum tincidunt, purus nunc bibendum nibh, ac sodales tortor odio non ante. Sed "
+"leo mauris, consequat molestie quam eu, vulputate volutpat metus. Cras fringilla risus sed arcu consequat luctus. "
+"Nam malesuada, turpis at luctus blandit, velit elit fringilla metus, eu mollis odio felis id tortor. Aliquam erat "
+"tellus, pulvinar nec iaculis et, consequat sit amet diam. Sed vestibulum, leo ut vehicula suscipit, quam justo "
+"maximus lectus, nec lobortis urna tortor nec nisi. Vestibulum eget ornare arcu, sed viverra turpis. Sed posuere "
+"tellus iaculis, scelerisque dui id, convallis lectus. Aliquam sodales at mi consectetur dignissim. In fringilla, "
+"urna id placerat mattis, diam magna commodo dui, at elementum arcu elit et libero. Duis venenatis vulputate nisl "
+"congue pharetra. Fusce sapien velit, cursus a consectetur quis, auctor gravida sem. Maecenas malesuada metus quis "
+"elit congue accumsan. Vivamus scelerisque euismod malesuada. Vestibulum purus metus, tempor eget faucibus a, cursus "
+"eu arcu. Morbi dictum urna vitae velit pellentesque facilisis. Sed arcu est, tempor ac turpis sit amet, ultricies "
+"venenatis augue. Nunc laoreet leo gravida facilisis dapibus. Aliquam convallis ullamcorper felis, sit amet tempor "
+"libero euismod sit amet. Quisque leo augue, finibus et euismod non, venenatis sed libero. Cras pharetra rhoncus "
+"odio, in pharetra lacus porttitor scelerisque. Maecenas eleifend felis vitae diam blandit viverra. Fusce at "
+"ultricies arcu, pharetra finibus enim. Etiam pellentesque semper ligula, sed tincidunt purus. Sed fermentum metus "
+"varius, aliquet libero eget, vehicula erat. Sed ac finibus metus. Pellentesque libero leo, semper et eros nec, "
+"gravida condimentum urna. Cras nec turpis convallis, efficitur lacus at, ultricies ex. Fusce eu neque elementum leo "
+"gravida semper. Duis sed tellus vitae magna fringilla maximus ac ut nisl. Integer id ligula ullamcorper, ultricies "
+"quam sit amet, ullamcorper diam. Maecenas rhoncus nulla eu dui vulputate scelerisque. Vestibulum porttitor eget nibh "
+"a mattis. Mauris tempus at urna blandit dignissim. Proin turpis leo, mattis ut turpis eget, aliquet tempor ante. "
+"Nunc in mollis nunc, et interdum nisi. Cras tristique sollicitudin tortor sit amet ultrices. Proin rhoncus neque "
+"urna. Maecenas bibendum, massa sit amet suscipit suscipit, justo tortor maximus dolor, posuere facilisis nisi tellus "
+"elementum diam. Quisque id eros vel lectus malesuada tincidunt. Donec at orci ac ligula venenatis dignissim sit amet "
+"nec purus. Sed eu neque finibus, tristique ex a, feugiat ante. Pellentesque tincidunt luctus mollis. Nullam blandit "
+"faucibus gravida. Ut sit amet malesuada nibh, vel tincidunt ipsum. Donec suscipit lorem in dui luctus, viverra "
+"imperdiet magna placerat. Pellentesque venenatis eros quis urna efficitur facilisis. Cras ligula magna, tempus "
+"facilisis tincidunt at, varius quis lectus. Sed quam neque, facilisis vel facilisis vel, lobortis ac orci. Nullam "
+"pretium interdum erat ac ultrices. Etiam enim mauris, vehicula nec rhoncus quis, volutpat vel erat. Morbi imperdiet "
+"rhoncus rutrum. Nullam auctor condimentum diam nec faucibus. Etiam sit amet porta nulla, sit amet lobortis enim. "
+"Aenean tincidunt condimentum accumsan. Vestibulum mollis diam risus, vitae ornare enim iaculis non. Nullam vitae "
+"risus tristique, imperdiet augue ut, egestas dolor. Sed sit amet leo eu diam commodo vestibulum id in dolor. Vivamus "
+"tristique molestie faucibus. Duis tempor porttitor turpis ac consectetur. Curabitur condimentum, ipsum eu dignissim "
+"semper, ipsum erat pretium quam, ut maximus erat ligula eu felis. Sed viverra, mauris id tempus tempor, nisi leo "
+"consectetur arcu, ac vulputate lorem mauris non sapien. Maecenas rhoncus magna mauris, in luctus nulla dapibus at. "
+"Sed magna est, ultrices sit amet erat nec, dapibus lacinia massa. Morbi cursus ex in elit auctor egestas. Quisque id "
+"placerat nibh, at mollis tortor. Proin fringilla sodales sapien, ac ullamcorper sem bibendum eget. Donec dui ligula, "
+"viverra eget leo ac, tincidunt fringilla mauris. Quisque vel lectus eget metus feugiat laoreet. Morbi eget "
+"vestibulum enim, ac ultricies lorem. Nam at mollis magna. Etiam vitae orci eu leo facilisis vestibulum. Ut sed "
+"turpis ut nibh iaculis rhoncus. Phasellus sit amet risus pellentesque, gravida eros a, porta nibh. Suspendisse at "
+"tincidunt ligula. Vivamus id libero diam. Morbi viverra ipsum turpis, in ullamcorper enim pellentesque nec. Sed "
+"ultricies, lectus quis pellentesque sodales, arcu diam commodo massa, a vestibulum purus sapien eget risus. Duis "
+"rhoncus in velit in dignissim. Aliquam sit amet metus in quam finibus cursus. Pellentesque eget aliquam justo. Fusce "
+"imperdiet, tellus non venenatis facilisis, diam mi lobortis dolor, at consectetur est massa id elit. Vivamus ante "
+"ex, faucibus et mollis eget, dignissim vel massa. Duis ultricies diam commodo purus facilisis pharetra. Curabitur "
+"pretium massa sed enim vehicula, id vehicula neque vehicula. In quis lectus non mauris pulvinar fermentum. Aliquam "
+"condimentum aliquet dui et congue. Maecenas quis augue eget leo gravida aliquet. Praesent sit amet fermentum odio, "
+"ut placerat nulla. Curabitur sit amet iaculis erat, eu volutpat odio. Ut iaculis ex quis tempus commodo. "
+"Pellentesque cursus eros at velit vulputate, id luctus massa pretium. Morbi ex dui, sodales id finibus id, aliquet a "
+"justo. Maecenas semper leo eget dolor rutrum, at imperdiet nibh eleifend. Aliquam eget purus tortor. Cras rutrum "
+"tortor massa, vel bibendum nunc aliquam vel. Nullam vestibulum, metus vel fermentum elementum, nulla sapien egestas "
+"justo, ac feugiat ex justo nec eros. Donec sit amet nibh mollis, commodo quam sit amet, semper magna. In tortor "
+"magna, elementum nec auctor sed, pellentesque at augue. Sed gravida arcu ac aliquet convallis. Nulla facilisi. Duis "
+"nunc quam, gravida non interdum id, cursus ac leo. Suspendisse vel ipsum nisl. Aliquam at gravida libero. Maecenas "
+"sit amet efficitur orci. Fusce id vehicula sapien. Proin euismod diam non laoreet ultricies. Nunc ullamcorper, nibh "
+"id cursus vehicula, ex purus tempor urna, et euismod orci est sed elit. Duis ut blandit mauris. Ut blandit cursus "
+"eros, sed laoreet nisl efficitur ac. Phasellus dui elit, fringilla sit amet cursus nec, pharetra quis odio. Ut ut "
+"lorem sit amet sem dapibus accumsan. Aenean a laoreet dolor. Donec eu laoreet velit. Etiam id nisi vel nibh dapibus "
+"congue a quis odio. Donec velit risus, semper quis porta non, elementum quis lorem. Interdum et malesuada fames ac "
+"ante ipsum primis in faucibus. Nullam sit amet dolor magna. Maecenas quis sapien sit amet est pulvinar lobortis "
+"efficitur cursus orci. Phasellus tristique mauris lorem, eu ultricies justo ornare condimentum. Integer urna enim, "
+"lobortis id malesuada ut, mattis eget libero. Sed commodo tincidunt eleifend. Fusce sed velit ut dui pellentesque "
+"pellentesque eget vel diam. Aenean nec turpis at tortor consectetur consectetur. Vestibulum ultrices elit at nisl "
+"pellentesque molestie. Maecenas diam dolor, faucibus eget posuere ut, sodales ut eros. Nam vulputate mollis diam nec "
+"gravida. Nam et ullamcorper diam. Aenean non nulla non lorem ullamcorper sagittis non quis erat. Pellentesque "
+"habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. In hac habitasse platea dictumst. "
+"Donec quis mauris ac nibh vestibulum eleifend placerat sed lacus. Suspendisse mi elit, viverra non velit ut, "
+"tincidunt tempus felis. Fusce ullamcorper, arcu nec aliquet porttitor, odio lacus mollis mi, id malesuada tortor "
+"velit aliquet turpis. Sed hendrerit felis nec faucibus ornare. Nulla ut metus eget augue malesuada posuere eget eu "
+"tortor. Cras ultrices odio sit amet porttitor vehicula. Sed vulputate leo vitae justo viverra, nec volutpat eros "
+"consectetur. Nunc nunc tellus, porta in arcu in, vulputate ultricies tellus. Fusce commodo efficitur lorem, sit amet "
+"lacinia sapien sollicitudin at. Etiam aliquet non mi vitae ornare. Cras condimentum imperdiet elit eu dictum. Donec "
+"sed enim sed massa tempor porta et sit amet felis. Nam interdum ornare sem, in tincidunt risus consectetur vel. Ut "
+"convallis purus mauris, in consequat ligula ullamcorper ut. Quisque elit ipsum, accumsan eget ligula vitae, "
+"sollicitudin luctus tellus. Nunc pretium turpis ligula, id dignissim lorem suscipit eu. Nulla facilisi. Sed lectus "
+"odio, vehicula vel vulputate id, ultrices non ipsum. Donec arcu quam, consequat eget aliquet sit amet, ullamcorper "
+"non nibh. Etiam finibus, mi id lobortis sagittis, leo leo lobortis lectus, sit amet aliquam dui odio sit amet massa. "
+"Suspendisse iaculis urna ac lectus gravida, iaculis efficitur tellus hendrerit. Sed tellus enim, condimentum in "
+"augue eget, sagittis ullamcorper sem. Suspendisse vitae aliquet libero. Aenean quis purus in sapien dapibus "
+"suscipit. Sed commodo nunc in lacus bibendum, vel tincidunt ante ornare. Ut tristique luctus volutpat. Class aptent "
+"taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Quisque a ultricies orci, eu porta "
+"odio. Vivamus sapien arcu, ultrices vel dui ut, luctus viverra purus. Praesent fringilla sed odio quis pretium. "
+"Vestibulum ullamcorper nisi tortor, id sollicitudin lectus tempor a. Ut malesuada sapien eu sapien posuere, non "
+"euismod eros porta. Nunc vel tincidunt ligula. Cras dolor ante, tristique tempor metus quis, mollis vulputate orci. "
+"Curabitur vitae nisl euismod, elementum purus vel, dictum lorem. Nunc eu mauris at metus porttitor dignissim ut eu "
+"neque. In tempor rhoncus neque sit amet commodo. Maecenas sed lacus semper, tempus enim ac, fermentum lorem. Nullam "
+"sollicitudin convallis turpis. Curabitur finibus placerat viverra. Pellentesque convallis condimentum tortor id "
+"efficitur. Proin semper pretium est, et vehicula ex cursus a. Nam ut felis purus. Phasellus eget felis eget leo "
+"dapibus vestibulum. Nulla eleifend malesuada turpis, quis faucibus eros. Nam aliquet euismod viverra. Ut quis semper "
+"felis. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Pellentesque at nulla "
+"arcu. Integer ut tellus ac sapien maximus tincidunt sed vitae risus. Nulla viverra, nibh eget eleifend aliquam, quam "
+"quam tempor massa, eu semper ipsum lacus in turpis. Nulla sed purus enim. Nullam sed fermentum ipsum. Sed dui nisi, "
+"elementum a auctor at, ultrices et nibh. Phasellus aliquam nulla ut lacinia accumsan. Phasellus sed arcu ligula. "
+"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam fermentum magna vitae dui sagittis tempor. Vivamus "
+"eu ligula blandit, imperdiet arcu at, rutrum sem. Aliquam erat volutpat. Quisque luctus enim quis volutpat lobortis. "
+"Vestibulum eget sodales libero. Aenean at condimentum est. Proin eget massa vel nulla efficitur tempor eget at enim. "
+"Integer enim sapien, ornare luctus nisl non, pretium facilisis ex. Donec pretium ligula ligula, a facilisis turpis "
+"hendrerit at. Nullam eget malesuada justo, at molestie quam. Sed consequat massa eu faucibus maximus. Curabitur "
+"placerat orci sapien, sit amet semper magna sodales non. Ut fermentum accumsan odio in consectetur. Morbi neque mi, "
+"vulputate nec mi ut, cursus scelerisque lectus. Nulla sapien enim, finibus id ipsum luctus, consequat ullamcorper "
+"lectus. Sed volutpat sed massa in sodales. Morbi lacinia diam eu commodo vulputate. Fusce aliquet pulvinar dolor in "
+"egestas. Fusce molestie commodo leo eu ultricies. Nulla mollis rhoncus pharetra. Pellentesque rutrum mauris ac lorem "
+"posuere, a eleifend mi rutrum. Nulla porta turpis aliquet felis congue rutrum. Fusce quis arcu in sem placerat "
+"condimentum a ut turpis. Quisque quis porttitor nulla. Donec sit amet quam tincidunt, pulvinar erat id, molestie "
+"dolor. Praesent luctus vitae nunc vitae pellentesque. Praesent faucibus sed urna ut lacinia. Vivamus id justo quis "
+"dolor porta rutrum nec nec odio. Cras euismod tortor quis diam ultrices, eu mattis nisi consectetur. Fusce mattis "
+"nisi vel condimentum molestie. Fusce fringilla ut nibh volutpat elementum. Mauris posuere consectetur leo a aliquet. "
+"Donec quis sodales sapien. Maecenas ut felis tempus, eleifend mauris et, faucibus mi. Quisque fringilla orci arcu, "
+"sit amet porta risus hendrerit non. Aenean id sem nisi. Nullam non nisl vestibulum, pellentesque nisl et, imperdiet "
+"ligula. Sed laoreet fringilla felis. Proin ac dolor viverra tellus mollis aliquet eget et neque. Suspendisse mattis "
+"nulla vitae nulla sagittis blandit. Sed at tortor rutrum, ornare magna nec, pellentesque nisi. Etiam non aliquet "
+"tellus. Aliquam at ex suscipit, posuere sem sit amet, tincidunt.";
+
+#endif /* __BLENDER_TESTING_BLI_RESSOURCE_STRING_H__ */
diff --git a/tests/gtests/blenlib/BLI_stack_test.cc b/tests/gtests/blenlib/BLI_stack_test.cc
index c4884cb8940..44956a589dc 100644
--- a/tests/gtests/blenlib/BLI_stack_test.cc
+++ b/tests/gtests/blenlib/BLI_stack_test.cc
@@ -11,6 +11,14 @@ extern "C" {
#define SIZE 1024
+/* number of items per chunk. use a small value to expose bugs */
+#define STACK_CHUNK_SIZE 8
+
+/* Ensure block size is set to #STACK_NEW_EX_ARGS */
+#define BLI_stack_new(esize, descr) \
+ BLI_stack_new_ex(esize, descr, esize * STACK_CHUNK_SIZE)
+
+
TEST(stack, Empty)
{
BLI_Stack *stack;
@@ -88,17 +96,82 @@ TEST(stack, String)
BLI_stack_free(stack);
}
+TEST(stack, Peek)
+{
+ const int tot = SIZE;
+ int i;
+
+ BLI_Stack *stack;
+ const short in[] = {1, 10, 100, 1000};
+
+ stack = BLI_stack_new(sizeof(*in), __func__);
+
+ for (i = 0; i < tot; i++) {
+ BLI_stack_push(stack, &in[i % ARRAY_SIZE(in)]);
+ }
+
+ for (i = tot - 1; i >= 0; i--, BLI_stack_discard(stack)) {
+ short *ret = (short *)BLI_stack_peek(stack);
+ EXPECT_EQ(*ret, in[i % ARRAY_SIZE(in)]);
+ }
+
+ EXPECT_EQ(BLI_stack_is_empty(stack), true);
+}
+
+/* Check that clearing the stack leaves in it a correct state. */
+TEST(stack, Clear)
+{
+ const int tot_rerun = 4;
+ int rerun;
+
+ /* based on range test */
+ int tot = SIZE;
+ BLI_Stack *stack;
+ int in, out;
+
+ /* use a small chunk size to ensure we test */
+ stack = BLI_stack_new(sizeof(in), __func__);
+
+ for (rerun = 0; rerun < tot_rerun; rerun++) {
+ for (in = 0; in < tot; in++) {
+ BLI_stack_push(stack, (void *)&in);
+ }
+
+ BLI_stack_clear(stack);
+ EXPECT_EQ(BLI_stack_is_empty(stack), true);
+
+ /* and again, this time check its valid */
+ for (in = 0; in < tot; in++) {
+ BLI_stack_push(stack, (void *)&in);
+ }
+
+ for (in = tot - 1; in >= 0; in--) {
+ EXPECT_EQ(BLI_stack_is_empty(stack), false);
+ BLI_stack_pop(stack, (void *)&out);
+ EXPECT_EQ(in, out);
+ }
+
+ EXPECT_EQ(BLI_stack_is_empty(stack), true);
+
+ /* without this, we wont test case when mixed free/used */
+ tot /= 2;
+ }
+
+ BLI_stack_free(stack);
+}
+
+
TEST(stack, Reuse)
{
const int sizes[] = {3, 11, 81, 400, 999, 12, 1, 9721, 7, 99, 5, 0};
int sizes_test[ARRAY_SIZE(sizes)];
const int *s;
- int in, out, i;
+ int out, i;
int sum, sum_test;
BLI_Stack *stack;
- stack = BLI_stack_new(sizeof(in), __func__);
+ stack = BLI_stack_new(sizeof(i), __func__);
/* add a bunch of numbers, ensure we get same sum out */
sum = 0;
diff --git a/tests/gtests/blenlib/BLI_string_test.cc b/tests/gtests/blenlib/BLI_string_test.cc
index 4c5c410dcb2..fa10e21730b 100644
--- a/tests/gtests/blenlib/BLI_string_test.cc
+++ b/tests/gtests/blenlib/BLI_string_test.cc
@@ -36,7 +36,7 @@ int mk_wcswidth(const wchar_t *pwcs, size_t n)
TEST(string, StrPartition)
{
const char delim[] = {'-', '.', '_', '~', '\\', '\0'};
- char *sep, *suf;
+ const char *sep, *suf;
size_t pre_ln;
{
@@ -95,7 +95,7 @@ TEST(string, StrPartition)
TEST(string, StrRPartition)
{
const char delim[] = {'-', '.', '_', '~', '\\', '\0'};
- char *sep, *suf;
+ const char *sep, *suf;
size_t pre_ln;
{
@@ -150,11 +150,42 @@ TEST(string, StrRPartition)
}
}
+/* BLI_str_partition_ex */
+TEST(string, StrPartitionEx)
+{
+ const char delim[] = {'-', '.', '_', '~', '\\', '\0'};
+ const char *sep, *suf;
+ size_t pre_ln;
+
+ /* Only considering 'from_right' cases here. */
+
+ {
+ const char *str = "mat.e-r_ia.l";
+
+ /* "mat.e-r_ia.l" over "mat.e-r" -> "mat.e", '.', "r_ia.l", 3 */
+ pre_ln = BLI_str_partition_ex(str, str + 6, delim, &sep, &suf, true);
+ EXPECT_EQ(5, pre_ln);
+ EXPECT_EQ(&str[5], sep);
+ EXPECT_STREQ("r_ia.l", suf);
+ }
+
+ /* Corner cases. */
+ {
+ const char *str = "mate.rial";
+
+ /* "mate.rial" over "mate" -> "mate.rial", NULL, NULL, 4 */
+ pre_ln = BLI_str_partition_ex(str, str + 4, delim, &sep, &suf, true);
+ EXPECT_EQ(4, pre_ln);
+ EXPECT_EQ(NULL, sep);
+ EXPECT_EQ(NULL, suf);
+ }
+}
+
/* BLI_str_partition_utf8 */
TEST(string, StrPartitionUtf8)
{
const unsigned int delim[] = {'-', '.', '_', 0x00F1 /* n tilde */, 0x262F /* ying-yang */, '\0'};
- char *sep, *suf;
+ const char *sep, *suf;
size_t pre_ln;
{
@@ -213,7 +244,7 @@ TEST(string, StrPartitionUtf8)
TEST(string, StrRPartitionUtf8)
{
const unsigned int delim[] = {'-', '.', '_', 0x00F1 /* n tilde */, 0x262F /* ying-yang */, '\0'};
- char *sep, *suf;
+ const char *sep, *suf;
size_t pre_ln;
{
@@ -268,6 +299,37 @@ TEST(string, StrRPartitionUtf8)
}
}
+/* BLI_str_partition_ex_utf8 */
+TEST(string, StrPartitionExUtf8)
+{
+ const unsigned int delim[] = {'-', '.', '_', 0x00F1 /* n tilde */, 0x262F /* ying-yang */, '\0'};
+ const char *sep, *suf;
+ size_t pre_ln;
+
+ /* Only considering 'from_right' cases here. */
+
+ {
+ const char *str = "ma\xc3\xb1te-r\xe2\x98\xafial";
+
+ /* "ma\xc3\xb1te-r\xe2\x98\xafial" over "ma\xc3\xb1te" -> "ma", '\xc3\xb1', "te-r\xe2\x98\xafial", 2 */
+ pre_ln = BLI_str_partition_ex_utf8(str, str + 6, delim, &sep, &suf, true);
+ EXPECT_EQ(2, pre_ln);
+ EXPECT_EQ(&str[2], sep);
+ EXPECT_STREQ("te-r\xe2\x98\xafial", suf);
+ }
+
+ /* Corner cases. */
+ {
+ const char *str = "mate\xe2\x98\xafrial";
+
+ /* "mate\xe2\x98\xafrial" over "mate" -> "mate\xe2\x98\xafrial", NULL, NULL, 4 */
+ pre_ln = BLI_str_partition_ex_utf8(str, str + 4, delim, &sep, &suf, true);
+ EXPECT_EQ(4, pre_ln);
+ EXPECT_EQ(NULL, sep);
+ EXPECT_EQ(NULL, suf);
+ }
+}
+
/* BLI_str_format_int_grouped */
TEST(string, StrFormatIntGrouped)
{
diff --git a/tests/gtests/blenlib/CMakeLists.txt b/tests/gtests/blenlib/CMakeLists.txt
index 07b89a9042e..acd9f944e4c 100644
--- a/tests/gtests/blenlib/CMakeLists.txt
+++ b/tests/gtests/blenlib/CMakeLists.txt
@@ -38,6 +38,12 @@ set(CMAKE_EXE_LINKER_FLAGS_DEBUG "${CMAKE_EXE_LINKER_FLAGS_DEBUG} ${PLATFORM_LIN
BLENDER_TEST(BLI_stack "bf_blenlib")
BLENDER_TEST(BLI_math_color "bf_blenlib")
BLENDER_TEST(BLI_math_geom "bf_blenlib")
+BLENDER_TEST(BLI_math_base "bf_blenlib")
BLENDER_TEST(BLI_string "bf_blenlib")
BLENDER_TEST(BLI_path_util "bf_blenlib;extern_wcwidth;${ZLIB_LIBRARIES}")
+BLENDER_TEST(BLI_polyfill2d "bf_blenlib")
BLENDER_TEST(BLI_listbase "bf_blenlib")
+BLENDER_TEST(BLI_hash_mm2a "bf_blenlib")
+BLENDER_TEST(BLI_ghash "bf_blenlib")
+
+BLENDER_TEST_PERFORMANCE(BLI_ghash_performance "bf_blenlib")
diff --git a/tests/gtests/testing/testing_main.cc b/tests/gtests/testing/testing_main.cc
index ef8e743b642..b2dcc445aca 100644
--- a/tests/gtests/testing/testing_main.cc
+++ b/tests/gtests/testing/testing_main.cc
@@ -28,7 +28,7 @@
int main(int argc, char **argv) {
testing::InitGoogleTest(&argc, argv);
- google::ParseCommandLineFlags(&argc, &argv, true);
+ gflags::ParseCommandLineFlags(&argc, &argv, true);
google::InitGoogleLogging(argv[0]);
return RUN_ALL_TESTS();
diff --git a/tests/python/CMakeLists.txt b/tests/python/CMakeLists.txt
index 85c68693792..fd2176e64d7 100644
--- a/tests/python/CMakeLists.txt
+++ b/tests/python/CMakeLists.txt
@@ -48,6 +48,7 @@ else()
endif()
# for testing with valgrind prefix: valgrind --track-origins=yes --error-limit=no
+set(TEST_BLENDER_EXE_BARE ${TEST_BLENDER_EXE})
set(TEST_BLENDER_EXE ${TEST_BLENDER_EXE} --background -noaudio --factory-startup --env-system-scripts ${CMAKE_SOURCE_DIR}/release/scripts)
@@ -72,6 +73,16 @@ if(USE_EXPERIMENTAL_TESTS)
)
endif()
+# ------------------------------------------------------------------------------
+# PY API TESTS
+add_test(script_pyapi_bpy_path ${TEST_BLENDER_EXE}
+ --python ${CMAKE_CURRENT_LIST_DIR}/bl_pyapi_bpy_path.py
+)
+
+add_test(script_pyapi_bpy_utils_units ${TEST_BLENDER_EXE}
+ --python ${CMAKE_CURRENT_LIST_DIR}/bl_pyapi_bpy_utils_units.py
+)
+
# test running mathutils testing script
add_test(script_pyapi_mathutils ${TEST_BLENDER_EXE}
--python ${CMAKE_CURRENT_LIST_DIR}/bl_pyapi_mathutils.py
@@ -88,6 +99,8 @@ add_test(bevel ${TEST_BLENDER_EXE}
# IO TESTS
# OBJ Import tests
+# disabled until updated & working
+if(FALSE)
add_test(import_obj_cube ${TEST_BLENDER_EXE}
--python ${CMAKE_CURRENT_LIST_DIR}/bl_test.py --
--run={'FINISHED'}&bpy.ops.import_scene.obj\(filepath='${TEST_SRC_DIR}/io_tests/obj/cube.obj'\)
@@ -108,6 +121,7 @@ add_test(import_obj_makehuman ${TEST_BLENDER_EXE}
--md5=c9f78b185e58358daa4ecaecfa75464e --md5_method=SCENE
--write-blend=${TEST_OUT_DIR}/import_obj_makehuman.blend
)
+endif()
# OBJ Export tests
add_test(export_obj_cube ${TEST_BLENDER_EXE}
@@ -116,7 +130,7 @@ add_test(export_obj_cube ${TEST_BLENDER_EXE}
--run={'FINISHED'}&bpy.ops.export_scene.obj\(filepath='${TEST_OUT_DIR}/export_obj_cube.obj',use_selection=False\)
--md5_source=${TEST_OUT_DIR}/export_obj_cube.obj
--md5_source=${TEST_OUT_DIR}/export_obj_cube.mtl
- --md5=70bdc394c2726203ad26c085176e3484 --md5_method=FILE
+ --md5=e776c6f8e9e0afba346e85bcd10b8e99 --md5_method=FILE
)
add_test(export_obj_nurbs ${TEST_BLENDER_EXE}
@@ -128,6 +142,8 @@ add_test(export_obj_nurbs ${TEST_BLENDER_EXE}
--md5=a733ae4fa4a591ea9b0912da3af042de --md5_method=FILE
)
+# disabled until updated & working
+if(FALSE)
add_test(export_obj_all_objects ${TEST_BLENDER_EXE}
${TEST_SRC_DIR}/io_tests/blend_scene/all_objects.blend
--python ${CMAKE_CURRENT_LIST_DIR}/bl_test.py --
@@ -136,6 +152,7 @@ add_test(export_obj_all_objects ${TEST_BLENDER_EXE}
--md5_source=${TEST_OUT_DIR}/export_obj_all_objects.mtl
--md5=04b3ed97cede07a19548fc518ce9f8ca --md5_method=FILE
)
+endif()
@@ -162,6 +179,8 @@ add_test(import_ply_small_holes ${TEST_BLENDER_EXE}
)
# PLY Export
+# disabled until updated & working
+if(FALSE)
add_test(export_ply_cube_all_data ${TEST_BLENDER_EXE}
${TEST_SRC_DIR}/io_tests/blend_geometry/cube_all_data.blend
--python ${CMAKE_CURRENT_LIST_DIR}/bl_test.py --
@@ -177,6 +196,7 @@ add_test(export_ply_suzanne_all_data ${TEST_BLENDER_EXE}
--md5_source=${TEST_OUT_DIR}/export_ply_suzanne_all_data.ply
--md5=68ba23f02efd6511bfd093f45f703221 --md5_method=FILE
)
+endif()
add_test(export_ply_vertices ${TEST_BLENDER_EXE} # lame, add a better one
${TEST_SRC_DIR}/io_tests/blend_geometry/vertices.blend
@@ -188,6 +208,8 @@ add_test(export_ply_vertices ${TEST_BLENDER_EXE} # lame, add a better one
# STL Import tests
+# disabled until updated & working
+if(FALSE)
add_test(import_stl_cube ${TEST_BLENDER_EXE}
--python ${CMAKE_CURRENT_LIST_DIR}/bl_test.py --
--run={'FINISHED'}&bpy.ops.import_mesh.stl\(filepath='${TEST_SRC_DIR}/io_tests/stl/cube.stl'\)
@@ -208,8 +230,11 @@ add_test(import_stl_knot_max_simplified ${TEST_BLENDER_EXE}
--md5=baf82803f45a84ec4ddbad9cef57dd3e --md5_method=SCENE
--write-blend=${TEST_OUT_DIR}/import_stl_knot_max_simplified.blend
)
+endif()
# STL Export
+# disabled until updated & working
+if(FALSE)
add_test(export_stl_cube_all_data ${TEST_BLENDER_EXE}
${TEST_SRC_DIR}/io_tests/blend_geometry/cube_all_data.blend
--python ${CMAKE_CURRENT_LIST_DIR}/bl_test.py --
@@ -233,9 +258,12 @@ add_test(export_stl_vertices ${TEST_BLENDER_EXE} # lame, add a better one
--md5_source=${TEST_OUT_DIR}/export_stl_vertices.stl
--md5=3fd3c877e573beeebc782532cc005820 --md5_method=FILE
)
+endif()
# X3D Import
+# disabled until updated & working
+if(FALSE)
add_test(import_x3d_cube ${TEST_BLENDER_EXE}
--python ${CMAKE_CURRENT_LIST_DIR}/bl_test.py --
--run={'FINISHED'}&bpy.ops.import_scene.x3d\(filepath='${TEST_SRC_DIR}/io_tests/x3d/color_cube.x3d'\)
@@ -281,10 +309,13 @@ add_test(export_x3d_all_objects ${TEST_BLENDER_EXE}
--md5_source=${TEST_OUT_DIR}/export_x3d_all_objects.x3d
--md5=f5f9fa4c5619a0eeab66685aafd2f7f0 --md5_method=FILE
)
+endif()
# 3DS Import
+# disabled until updated & working
+if(FALSE)
add_test(import_3ds_cube ${TEST_BLENDER_EXE}
--python ${CMAKE_CURRENT_LIST_DIR}/bl_test.py --
--run={'FINISHED'}&bpy.ops.import_scene.autodesk_3ds\(filepath='${TEST_SRC_DIR}/io_tests/3ds/cube.3ds'\)
@@ -305,8 +336,11 @@ add_test(import_3ds_hierarchy_greek_trireme ${TEST_BLENDER_EXE}
--md5=b62ee30101e8999cb91ef4f8a8760056 --md5_method=SCENE
--write-blend=${TEST_OUT_DIR}/import_3ds_hierarchy_greek_trireme.blend
)
+endif()
# 3DS Export
+# disabled until updated & working
+if(FALSE)
add_test(export_3ds_cube ${TEST_BLENDER_EXE}
${TEST_SRC_DIR}/io_tests/blend_geometry/all_quads.blend
--python ${CMAKE_CURRENT_LIST_DIR}/bl_test.py --
@@ -330,11 +364,14 @@ add_test(export_3ds_all_objects ${TEST_BLENDER_EXE}
--md5_source=${TEST_OUT_DIR}/export_3ds_all_objects.3ds
--md5=68447761ab0ca38e1e22e7c177ed48a8 --md5_method=FILE
)
+endif()
# FBX Export
# 'use_metadata=False' for reliable md5's
+# disabled until updated & working
+if(FALSE)
add_test(export_fbx_cube ${TEST_BLENDER_EXE}
${TEST_SRC_DIR}/io_tests/blend_geometry/all_quads.blend
--python ${CMAKE_CURRENT_LIST_DIR}/bl_test.py --
@@ -358,3 +395,29 @@ add_test(export_fbx_all_objects ${TEST_BLENDER_EXE}
--md5_source=${TEST_OUT_DIR}/export_fbx_all_objects.fbx
--md5=b35eb2a9d0e73762ecae2278c25a38ac --md5_method=FILE
)
+endif()
+
+if(WITH_CYCLES)
+ if(OPENIMAGEIO_IDIFF AND EXISTS "${TEST_SRC_DIR}/cycles/ctests/shader")
+ add_test(cycles_reports_test
+ ${CMAKE_CURRENT_LIST_DIR}/cycles_render_tests.py
+ -blender "${TEST_BLENDER_EXE_BARE}"
+ -testdir "${TEST_SRC_DIR}/cycles/ctests/reports"
+ -idiff "${OPENIMAGEIO_IDIFF}"
+ )
+ add_test(cycles_render_test
+ ${CMAKE_CURRENT_LIST_DIR}/cycles_render_tests.py
+ -blender "${TEST_BLENDER_EXE_BARE}"
+ -testdir "${TEST_SRC_DIR}/cycles/ctests/render"
+ -idiff "${OPENIMAGEIO_IDIFF}"
+ )
+ add_test(cycles_shaders_test
+ ${CMAKE_CURRENT_LIST_DIR}/cycles_render_tests.py
+ -blender "${TEST_BLENDER_EXE_BARE}"
+ -testdir "${TEST_SRC_DIR}/cycles/ctests/shader"
+ -idiff "${OPENIMAGEIO_IDIFF}"
+ )
+ else()
+ MESSAGE(STATUS "Disabling Cycles tests because tests folder does not exist")
+ endif()
+endif()
diff --git a/tests/python/batch_import.py b/tests/python/batch_import.py
index dea08b45c3a..8fc679a7c15 100644
--- a/tests/python/batch_import.py
+++ b/tests/python/batch_import.py
@@ -78,7 +78,9 @@ def batch_import(operator="",
path = os.path.abspath(path)
match_upper = match.upper()
- pattern_match = lambda a: fnmatch.fnmatchcase(a.upper(), match_upper)
+
+ def pattern_match(a):
+ return fnmatch.fnmatchcase(a.upper(), match_upper)
def file_generator(path):
for dirpath, dirnames, filenames in os.walk(path):
diff --git a/tests/python/bl_load_addons.py b/tests/python/bl_load_addons.py
index f04ae64ee73..29304400005 100644
--- a/tests/python/bl_load_addons.py
+++ b/tests/python/bl_load_addons.py
@@ -20,24 +20,57 @@
# simple script to enable all addons, and disable
+"""
+./blender.bin --background -noaudio --factory-startup --python tests/python/bl_load_addons.py
+"""
+
import bpy
import addon_utils
+import os
import sys
import imp
+BLACKLIST_DIRS = (
+ os.path.join(bpy.utils.resource_path('USER'), "scripts"),
+ ) + tuple(addon_utils.paths()[1:])
+BLACKLIST_ADDONS = set()
+
+
+def _init_addon_blacklist():
+
+ # in case we built without cycles
+ if not bpy.app.build_options.cycles:
+ BLACKLIST_ADDONS.add("cycles")
+
+ # in case we built without freestyle
+ if not bpy.app.build_options.freestyle:
+ BLACKLIST_ADDONS.add("render_freestyle_svg")
+
+ # netrender has known problems re-registering
+ BLACKLIST_ADDONS.add("netrender")
+
+
+def addon_modules_sorted():
+ modules = addon_utils.modules({})
+ modules[:] = [
+ mod for mod in modules
+ if not (mod.__file__.startswith(BLACKLIST_DIRS))
+ if not (mod.__name__ in BLACKLIST_ADDONS)]
+ modules.sort(key=lambda mod: mod.__name__)
+ return modules
+
def disable_addons():
# first disable all
addons = bpy.context.user_preferences.addons
for mod_name in list(addons.keys()):
- addon_utils.disable(mod_name)
+ addon_utils.disable(mod_name, default_set=True)
assert(bool(addons) is False)
def test_load_addons():
- modules = addon_utils.modules({})
- modules.sort(key=lambda mod: mod.__name__)
+ modules = addon_modules_sorted()
disable_addons()
@@ -48,8 +81,8 @@ def test_load_addons():
for mod in modules:
mod_name = mod.__name__
print("\tenabling:", mod_name)
- addon_utils.enable(mod_name)
- if mod_name not in addons:
+ addon_utils.enable(mod_name, default_set=True)
+ if (mod_name not in addons) and (mod_name not in BLACKLIST_ADDONS):
addons_fail.append(mod_name)
if addons_fail:
@@ -62,8 +95,7 @@ def test_load_addons():
def reload_addons(do_reload=True, do_reverse=True):
- modules = addon_utils.modules({})
- modules.sort(key=lambda mod: mod.__name__)
+ modules = addon_modules_sorted()
addons = bpy.context.user_preferences.addons
disable_addons()
@@ -73,25 +105,28 @@ def reload_addons(do_reload=True, do_reverse=True):
for mod in modules:
mod_name = mod.__name__
print("\tenabling:", mod_name)
- addon_utils.enable(mod_name)
+ addon_utils.enable(mod_name, default_set=True)
assert(mod_name in addons)
- for mod in addon_utils.modules({}):
+ for mod in modules:
mod_name = mod.__name__
print("\tdisabling:", mod_name)
- addon_utils.disable(mod_name)
+ addon_utils.disable(mod_name, default_set=True)
assert(not (mod_name in addons))
# now test reloading
if do_reload:
imp.reload(sys.modules[mod_name])
- if do_reverse:
- # in case order matters when it shouldn't
- modules.reverse()
+ if do_reverse:
+ # in case order matters when it shouldn't
+ modules.reverse()
def main():
+
+ _init_addon_blacklist()
+
# first load addons, print a list of all addons that fail
test_load_addons()
diff --git a/tests/python/bl_load_py_modules.py b/tests/python/bl_load_py_modules.py
index 9677397e01d..4256cba0933 100644
--- a/tests/python/bl_load_py_modules.py
+++ b/tests/python/bl_load_py_modules.py
@@ -20,6 +20,10 @@
# simple script to enable all addons, and disable
+"""
+./blender.bin --background -noaudio --factory-startup --python tests/python/bl_load_py_modules.py
+"""
+
import bpy
import addon_utils
@@ -28,10 +32,26 @@ import os
BLACKLIST = {
"bl_i18n_utils",
+ "bl_previews_utils",
"cycles",
"io_export_dxf", # TODO, check on why this fails
+ 'io_import_dxf', # Because of cydxfentity.so dependency
}
+if not bpy.app.build_options.freestyle:
+ BLACKLIST.add("render_freestyle_svg")
+
+BLACKLIST_DIRS = (
+ os.path.join(bpy.utils.resource_path('USER'), "scripts"),
+ ) + tuple(addon_utils.paths()[1:])
+
+
+def addon_modules_sorted():
+ modules = addon_utils.modules({})
+ modules[:] = [mod for mod in modules if not mod.__file__.startswith(BLACKLIST_DIRS)]
+ modules.sort(key=lambda mod: mod.__name__)
+ return modules
+
def source_list(path, filename_check=None):
from os.path import join
@@ -47,20 +67,22 @@ def source_list(path, filename_check=None):
def load_addons():
- modules = addon_utils.modules({})
- modules.sort(key=lambda mod: mod.__name__)
+ modules = addon_modules_sorted()
addons = bpy.context.user_preferences.addons
# first disable all
for mod_name in list(addons.keys()):
- addon_utils.disable(mod_name)
+ addon_utils.disable(mod_name, default_set=True)
assert(bool(addons) is False)
for mod in modules:
mod_name = mod.__name__
- addon_utils.enable(mod_name)
- assert(mod_name in addons)
+ if mod_name in BLACKLIST:
+ continue
+ addon_utils.enable(mod_name, default_set=True)
+ if not (mod_name in addons):
+ raise Exception("'addon_utils.enable(%r)' call failed" % mod_name)
def load_modules():
@@ -79,9 +101,10 @@ def load_modules():
for script_path in paths:
for mod_dir in sys.path:
if mod_dir.startswith(script_path):
- if mod_dir not in module_paths:
- if os.path.exists(mod_dir):
- module_paths.append(mod_dir)
+ if not mod_dir.startswith(BLACKLIST_DIRS):
+ if mod_dir not in module_paths:
+ if os.path.exists(mod_dir):
+ module_paths.append(mod_dir)
#
# collect modules from our paths.
@@ -140,7 +163,8 @@ def load_modules():
ignore_paths = [
os.sep + "presets" + os.sep,
os.sep + "templates" + os.sep,
- ] + [(os.sep + f + os.sep) for f in BLACKLIST]
+ ] + ([(os.sep + f + os.sep) for f in BLACKLIST] +
+ [(os.sep + f + ".py") for f in BLACKLIST])
for f in source_files:
ok = False
diff --git a/tests/python/bl_mesh_modifiers.py b/tests/python/bl_mesh_modifiers.py
index 2db38895f9b..0121be29dd6 100644
--- a/tests/python/bl_mesh_modifiers.py
+++ b/tests/python/bl_mesh_modifiers.py
@@ -197,8 +197,9 @@ def defaults_object(obj):
obj.show_wire = True
if obj.type == 'MESH':
+ obj.show_all_edges = True
+
mesh = obj.data
- mesh.show_all_edges = True
mesh.show_normal_vertex = True
diff --git a/tests/python/bl_pyapi_bpy_path.py b/tests/python/bl_pyapi_bpy_path.py
new file mode 100644
index 00000000000..2d6019fbb07
--- /dev/null
+++ b/tests/python/bl_pyapi_bpy_path.py
@@ -0,0 +1,41 @@
+# Apache License, Version 2.0
+
+# ./blender.bin --background -noaudio --python tests/python/bl_pyapi_bpy_path.py -- --verbose
+import unittest
+
+
+class TestBpyPath(unittest.TestCase):
+ def test_ensure_ext(self):
+ from bpy.path import ensure_ext
+
+ # Should work with both strings and bytes.
+ self.assertEqual(ensure_ext('demo', '.blend'), 'demo.blend')
+ self.assertEqual(ensure_ext(b'demo', b'.blend'), b'demo.blend')
+
+ # Test different cases.
+ self.assertEqual(ensure_ext('demo.blend', '.blend'), 'demo.blend')
+ self.assertEqual(ensure_ext('demo.BLEND', '.blend'), 'demo.BLEND')
+ self.assertEqual(ensure_ext('demo.blend', '.BLEND'), 'demo.blend')
+
+ # Test empty extensions, compound extensions etc.
+ self.assertEqual(ensure_ext('demo', 'blend'), 'demoblend')
+ self.assertEqual(ensure_ext('demo', ''), 'demo')
+ self.assertEqual(ensure_ext('demo', '.json.gz'), 'demo.json.gz')
+ self.assertEqual(ensure_ext('demo.json.gz', '.json.gz'), 'demo.json.gz')
+ self.assertEqual(ensure_ext('demo.json', '.json.gz'), 'demo.json.json.gz')
+ self.assertEqual(ensure_ext('', ''), '')
+ self.assertEqual(ensure_ext('', '.blend'), '.blend')
+
+ # Test case-sensitive behaviour.
+ self.assertEqual(ensure_ext('demo', '.blend', True), 'demo.blend')
+ self.assertEqual(ensure_ext('demo.BLEND', '.blend', True), 'demo.BLEND.blend')
+ self.assertEqual(ensure_ext('demo', 'Blend', True), 'demoBlend')
+ self.assertEqual(ensure_ext('demoBlend', 'blend', True), 'demoBlendblend')
+ self.assertEqual(ensure_ext('demo', '', True), 'demo')
+
+
+if __name__ == '__main__':
+ import sys
+
+ sys.argv = [__file__] + (sys.argv[sys.argv.index("--") + 1:] if "--" in sys.argv else [])
+ unittest.main()
diff --git a/tests/python/bl_pyapi_units.py b/tests/python/bl_pyapi_bpy_utils_units.py
index 128cc100b25..f40dab4b5eb 100644
--- a/tests/python/bl_pyapi_units.py
+++ b/tests/python/bl_pyapi_bpy_utils_units.py
@@ -1,6 +1,6 @@
# Apache License, Version 2.0
-# ./blender.bin --background -noaudio --python tests/python/bl_pyapi_units.py -- --verbose
+# ./blender.bin --background -noaudio --python tests/python/bl_pyapi_bpy_utils_units.py -- --verbose
import unittest
from bpy.utils import units
diff --git a/tests/python/bl_pyapi_mathutils.py b/tests/python/bl_pyapi_mathutils.py
index 85232e465d7..b7f61df0e40 100644
--- a/tests/python/bl_pyapi_mathutils.py
+++ b/tests/python/bl_pyapi_mathutils.py
@@ -2,7 +2,7 @@
# ./blender.bin --background -noaudio --python tests/python/bl_pyapi_mathutils.py -- --verbose
import unittest
-from mathutils import Matrix, Vector
+from mathutils import Matrix, Vector, Quaternion
from mathutils import kdtree
import math
@@ -210,6 +210,35 @@ class VectorTesting(unittest.TestCase):
self.assertAlmostEqual(v.angle(v.orthogonal()), angle_90d)
+class QuaternionTesting(unittest.TestCase):
+
+ def test_to_expmap(self):
+ q = Quaternion((0, 0, 1), math.radians(90))
+
+ e = q.to_exponential_map()
+ self.assertAlmostEqual(e.x, 0)
+ self.assertAlmostEqual(e.y, 0)
+ self.assertAlmostEqual(e.z, math.radians(90), 6)
+
+ def test_expmap_axis_normalization(self):
+ q = Quaternion((1, 1, 0), 2)
+ e = q.to_exponential_map()
+
+ self.assertAlmostEqual(e.x, 2 * math.sqrt(0.5), 6)
+ self.assertAlmostEqual(e.y, 2 * math.sqrt(0.5), 6)
+ self.assertAlmostEqual(e.z, 0)
+
+ def test_from_expmap(self):
+ e = Vector((1, 1, 0))
+ q = Quaternion(e)
+ axis, angle = q.to_axis_angle()
+
+ self.assertAlmostEqual(angle, math.sqrt(2), 6)
+ self.assertAlmostEqual(axis.x, math.sqrt(0.5), 6)
+ self.assertAlmostEqual(axis.y, math.sqrt(0.5), 6)
+ self.assertAlmostEqual(axis.z, 0)
+
+
class KDTreeTesting(unittest.TestCase):
@staticmethod
diff --git a/tests/python/bl_rna_defaults.py b/tests/python/bl_rna_defaults.py
new file mode 100644
index 00000000000..1d6f82b06c2
--- /dev/null
+++ b/tests/python/bl_rna_defaults.py
@@ -0,0 +1,117 @@
+# Apache License, Version 2.0
+
+# ./blender.bin --background -noaudio --factory-startup --python tests/python/bl_rna_defaults.py
+
+import bpy
+
+DUMMY_NAME = "Untitled"
+DUMMY_PATH = __file__
+GLOBALS = {
+ "error_num": 0,
+ }
+
+
+def validate_defaults(test_id, o):
+
+ def warning(prop_id, val_real, val_default):
+ print("Error %s: '%s.%s' is:%r, expected:%r" %
+ (test_id, o.__class__.__name__, prop_id, val_real, val_default))
+ GLOBALS["error_num"] += 1
+
+ properties = type(o).bl_rna.properties.items()
+ for prop_id, prop in properties:
+ if prop_id == "rna_type":
+ continue
+ prop_type = prop.type
+ if prop_type in {'STRING', 'COLLECTION'}:
+ continue
+
+ if prop_type == 'POINTER':
+ # traverse down pointers if they're set
+ val_real = getattr(o, prop_id)
+ if (val_real is not None) and (not isinstance(val_real, bpy.types.ID)):
+ validate_defaults("%s.%s" % (test_id, prop_id), val_real)
+ elif prop_type in {'INT', 'BOOL'}:
+ array_length = prop.array_length
+ if array_length == 0:
+ val_real = getattr(o, prop_id)
+ val_default = prop.default
+ if val_real != val_default:
+ warning(prop_id, val_real, val_default)
+ else:
+ pass # TODO, array defaults
+ elif prop_type == 'FLOAT':
+ array_length = prop.array_length
+ if array_length == 0:
+ val_real = getattr(o, prop_id)
+ val_default = prop.default
+ if val_real != val_default:
+ warning(prop_id, val_real, val_default)
+ else:
+ pass # TODO, array defaults
+ elif prop_type == 'ENUM':
+ val_real = getattr(o, prop_id)
+ if prop.is_enum_flag:
+ val_default = prop.default_flag
+ else:
+ val_default = prop.default
+ if val_real != val_default:
+ warning(prop_id, val_real, val_default)
+
+ # print(prop_id, prop_type)
+
+
+def _test_id_gen(data_attr, args_create=(DUMMY_NAME,), create_method="new"):
+ def test_gen(test_id):
+ id_collection = getattr(bpy.data, data_attr)
+ create_fn = getattr(id_collection, create_method)
+ o = create_fn(*args_create)
+ o.user_clear()
+ validate_defaults(test_id, o)
+ id_collection.remove(o)
+ return test_gen
+
+
+test_Action = _test_id_gen("actions")
+test_Armature = _test_id_gen("armatures")
+test_Camera = _test_id_gen("cameras")
+test_Group = _test_id_gen("groups")
+test_Lattice = _test_id_gen("lattices")
+test_LineStyle = _test_id_gen("linestyles")
+test_Mask = _test_id_gen("masks")
+test_Material = _test_id_gen("materials")
+test_Mesh = _test_id_gen("meshes")
+test_MetaBall = _test_id_gen("metaballs")
+test_MovieClip = _test_id_gen("movieclips", args_create=(DUMMY_PATH,), create_method="load")
+test_Object = _test_id_gen("objects", args_create=(DUMMY_NAME, None))
+test_Palette = _test_id_gen("palettes")
+test_Particle = _test_id_gen("particles")
+test_Scene = _test_id_gen("scenes")
+test_Sound = _test_id_gen("sounds", args_create=(DUMMY_PATH,), create_method="load")
+test_Speaker = _test_id_gen("speakers")
+test_Text = _test_id_gen("texts")
+test_VectorFont = _test_id_gen("fonts", args_create=("<builtin>",), create_method="load")
+test_World = _test_id_gen("worlds")
+
+ns = globals()
+for t in bpy.data.curves.bl_rna.functions["new"].parameters["type"].enum_items.keys():
+ ns["test_Curve_%s" % t] = _test_id_gen("curves", args_create=(DUMMY_NAME, t))
+for t in bpy.data.lamps.bl_rna.functions["new"].parameters["type"].enum_items.keys():
+ ns["test_Lamp_%s" % t] = _test_id_gen("lamps", args_create=(DUMMY_NAME, t))
+# types are a dynamic enum, have to hard-code.
+for t in "ShaderNodeTree", "CompositorNodeTree", "TextureNodeTree":
+ ns["test_NodeGroup_%s" % t] = _test_id_gen("node_groups", args_create=(DUMMY_NAME, t))
+for t in bpy.data.textures.bl_rna.functions["new"].parameters["type"].enum_items.keys():
+ ns["test_Texture_%s" % t] = _test_id_gen("textures", args_create=(DUMMY_NAME, t))
+del ns
+
+
+def main():
+ for fn_id, fn_val in sorted(globals().items()):
+ if fn_id.startswith("test_") and callable(fn_val):
+ fn_val(fn_id)
+
+ print("Error (total): %d" % GLOBALS["error_num"])
+
+if __name__ == "__main__":
+ main()
diff --git a/tests/python/bl_rna_wiki_reference.py b/tests/python/bl_rna_manual_reference.py
index 5781c53c045..c67b6c1532b 100644
--- a/tests/python/bl_rna_wiki_reference.py
+++ b/tests/python/bl_rna_manual_reference.py
@@ -18,8 +18,8 @@
# <pep8 compliant>
-# Use for validating our wiki interlinking.
-# ./blender.bin --background -noaudio --python tests/python/bl_rna_wiki_reference.py
+# Use for validating our manual interlinking.
+# ./blender.bin --background -noaudio --python tests/python/bl_rna_manual_reference.py
#
# 1) test_data() -- ensure the data we have is correct format
# 2) test_lookup_coverage() -- ensure that we have lookups for _every_ RNA path
@@ -31,10 +31,10 @@ import bpy
def test_data():
- import rna_wiki_reference
+ import rna_manual_reference
- assert(isinstance(rna_wiki_reference.url_manual_mapping, tuple))
- for i, value in enumerate(rna_wiki_reference.url_manual_mapping):
+ assert(isinstance(rna_manual_reference.url_manual_mapping, tuple))
+ for i, value in enumerate(rna_manual_reference.url_manual_mapping):
try:
assert(len(value) == 2)
assert(isinstance(value[0], str))
@@ -92,14 +92,19 @@ def test_language_coverage():
def test_urls():
+ import os
import sys
- import rna_wiki_reference
+ import rna_manual_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}
+ # avoid URL lookups if possible
+ LOCAL_PREFIX = os.environ.get("LOCAL_PREFIX")
+ if LOCAL_PREFIX is None:
+ prefix = rna_manual_reference.url_manual_prefix
+
+ urls = {suffix for (rna_id, suffix) in rna_manual_reference.url_manual_mapping}
urls_len = "%d" % len(urls)
print("")
@@ -113,16 +118,26 @@ def test_urls():
urls_fail = []
- for url in sorted(urls):
- url_full = prefix + url
- print(" %s ... " % url_full, end="")
- sys.stdout.flush()
- try:
- urlopen(url_full)
- print(color_green + "OK" + color_normal)
- except urllib.error.HTTPError:
- print(color_red + "FAIL!" + color_normal)
- urls_fail.append(url)
+ if LOCAL_PREFIX:
+ for url in sorted(urls):
+ url_full = os.path.join(LOCAL_PREFIX, url.partition("#")[0])
+ print(" %s ... " % url_full, end="")
+ if os.path.exists(url_full):
+ print(color_green + "OK" + color_normal)
+ else:
+ print(color_red + "FAIL!" + color_normal)
+ urls_fail.append(url)
+ else:
+ for url in sorted(urls):
+ url_full = prefix + url
+ print(" %s ... " % url_full, end="")
+ sys.stdout.flush()
+ try:
+ 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)
diff --git a/tests/python/bl_rst_completeness.py b/tests/python/bl_rst_completeness.py
index d0ba2c552cf..d8dfac66d13 100644
--- a/tests/python/bl_rst_completeness.py
+++ b/tests/python/bl_rst_completeness.py
@@ -62,7 +62,7 @@ def is_directive_pydata(filepath, directive):
return True
elif directive.type in {"module", "note", "warning", "code-block", "hlist", "seealso"}:
return False
- elif directive.type in {"literalinclude"}: # TODO
+ elif directive.type == "literalinclude": # TODO
return False
else:
print(directive_to_str(filepath, directive), end=" ")
diff --git a/tests/python/bl_run_operators.py b/tests/python/bl_run_operators.py
index f7fafe833aa..f3c553cf3ef 100644
--- a/tests/python/bl_run_operators.py
+++ b/tests/python/bl_run_operators.py
@@ -34,6 +34,10 @@ RANDOM_SEED = [1] # so we can redo crashes
RANDOM_RESET = 0.1 # 10% chance of resetting on each new operator
RANDOM_MULTIPLY = 10
+STATE = {
+ "counter": 0,
+ }
+
op_blacklist = (
"script.reload",
@@ -75,6 +79,7 @@ op_blacklist = (
"wm.properties_context_change",
"wm.operator_cheat_sheet",
"wm.interface_theme_*",
+ "wm.previews_ensure", # slow - but harmless
"wm.appconfig_*", # just annoying - but harmless
"wm.keyitem_add", # just annoying - but harmless
"wm.keyconfig_activate", # just annoying - but harmless
@@ -158,7 +163,7 @@ if USE_ATTRSET:
if issubclass(cls, skip_classes):
continue
- ## to support skip-save we cant get all props
+ # # to support skip-save we cant get all props
# properties = cls.bl_rna.properties.keys()
properties = []
for prop_id, prop in cls.bl_rna.properties.items():
@@ -248,7 +253,8 @@ def run_ops(operators, setup_func=None, reset=True):
# first invoke
for op_id, op in operators:
if op.poll():
- print(" operator:", op_id)
+ print(" operator: %4d, %s" % (STATE["counter"], op_id))
+ STATE["counter"] += 1
sys.stdout.flush() # in case of crash
# disable will get blender in a bad state and crash easy!
diff --git a/tests/python/cycles_render_tests.py b/tests/python/cycles_render_tests.py
new file mode 100755
index 00000000000..36fad175cfa
--- /dev/null
+++ b/tests/python/cycles_render_tests.py
@@ -0,0 +1,166 @@
+#!/usr/bin/env python3
+# Apache License, Version 2.0
+
+import argparse
+import os
+import subprocess
+import sys
+import tempfile
+
+
+def render_file(filepath):
+ command = (
+ BLENDER,
+ "--background",
+ "-noaudio",
+ "--factory-startup",
+ filepath,
+ "-E", "CYCLES",
+ "-o", TEMP_FILE_MASK,
+ "-F", "PNG",
+ "-f", "1",
+ )
+ try:
+ output = subprocess.check_output(command)
+ if VERBOSE:
+ print(output.decode("utf-8"))
+ return None
+ except subprocess.CalledProcessError as e:
+ if os.path.exists(TEMP_FILE):
+ os.remove(TEMP_FILE)
+ if VERBOSE:
+ print(e.output.decode("utf-8"))
+ if b"Error: engine not found" in e.output:
+ return "NO_CYCLES"
+ elif b"blender probably wont start" in e.output:
+ return "NO_START"
+ return "CRASH"
+ except:
+ if os.path.exists(TEMP_FILE):
+ os.remove(TEMP_FILE)
+ if VERBOSE:
+ print(e.output.decode("utf-8"))
+ return "CRASH"
+
+
+def test_get_name(filepath):
+ filename = os.path.basename(filepath)
+ return os.path.splitext(filename)[0]
+
+
+def verify_output(filepath):
+ testname = test_get_name(filepath)
+ dirpath = os.path.dirname(filepath)
+ reference_dirpath = os.path.join(dirpath, "reference_renders")
+ reference_image = os.path.join(reference_dirpath, testname + ".png")
+ if not os.path.exists(reference_image):
+ return False
+ command = (
+ IDIFF,
+ "-fail", "0.01",
+ "-failpercent", "1",
+ reference_image,
+ TEMP_FILE,
+ )
+ try:
+ subprocess.check_output(command)
+ return True
+ except subprocess.CalledProcessError as e:
+ if VERBOSE:
+ print(e.output.decode("utf-8"))
+ return e.returncode == 1
+
+
+def run_test(filepath):
+ testname = test_get_name(filepath)
+ spacer = "." * (32 - len(testname))
+ print(testname, spacer, end="")
+ sys.stdout.flush()
+ error = render_file(filepath)
+ if not error:
+ if verify_output(filepath):
+ print("PASS")
+ else:
+ error = "VERIFY"
+ if error:
+ print("FAIL", error)
+ return error
+
+
+def blend_list(path):
+ for dirpath, dirnames, filenames in os.walk(path):
+ for filename in filenames:
+ if filename.lower().endswith(".blend"):
+ filepath = os.path.join(dirpath, filename)
+ yield filepath
+
+
+def run_all_tests(dirpath):
+ failed_tests = []
+ all_files = list(blend_list(dirpath))
+ all_files.sort()
+ for filepath in all_files:
+ error = run_test(filepath)
+ if error:
+ if error == "NO_CYCLES":
+ print("Can't perform tests because Cycles failed to load!")
+ return False
+ elif error == "NO_START":
+ print('Can not perform tests because blender fails to start.',
+ 'Make sure INSTALL target was run.')
+ return False
+ elif error == 'VERIFY':
+ pass
+ else:
+ print("Unknown error %r" % error)
+ testname = test_get_name(filepath)
+ failed_tests.append(testname)
+ if failed_tests:
+ failed_tests.sort()
+ print("\n\nFAILED tests:")
+ for test in failed_tests:
+ print(" ", test)
+ return False
+ return True
+
+
+def create_argparse():
+ parser = argparse.ArgumentParser()
+ parser.add_argument("-blender", nargs="+")
+ parser.add_argument("-testdir", nargs=1)
+ parser.add_argument("-idiff", nargs=1)
+ return parser
+
+
+def main():
+ parser = create_argparse()
+ args = parser.parse_args()
+
+ global BLENDER, ROOT, IDIFF
+ global TEMP_FILE, TEMP_FILE_MASK, TEST_SCRIPT
+ global VERBOSE
+
+ BLENDER = args.blender[0]
+ ROOT = args.testdir[0]
+ IDIFF = args.idiff[0]
+
+ TEMP = tempfile.mkdtemp()
+ TEMP_FILE_MASK = os.path.join(TEMP, "test")
+ TEMP_FILE = TEMP_FILE_MASK + "0001.png"
+
+ TEST_SCRIPT = os.path.join(os.path.dirname(__file__), "runtime_check.py")
+
+ VERBOSE = os.environ.get("BLENDER_VERBOSE") is not None
+
+ ok = run_all_tests(ROOT)
+
+ # Cleanup temp files and folders
+ if os.path.exists(TEMP_FILE):
+ os.remove(TEMP_FILE)
+ os.rmdir(TEMP)
+
+ sys.exit(not ok)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/tests/python/pep8.py b/tests/python/pep8.py
index 7713ffeaaa4..0d6db729767 100644
--- a/tests/python/pep8.py
+++ b/tests/python/pep8.py
@@ -95,19 +95,40 @@ def main():
print(" %s" % f)
# strict imports
- print("\n\n\n# running pep8...")
+ print("\n\n\n# checking imports...")
import re
import_check = re.compile(r"\s*from\s+[A-z\.]+\s+import \*\s*")
for f, pep8_type in files:
for i, l in enumerate(open(f, 'r', encoding='utf8')):
if import_check.match(l):
print("%s:%d:0: global import bad practice" % (f, i + 1))
+ del re, import_check
+
+ print("\n\n\n# checking class definitions...")
+ import re
+ class_check = re.compile(r"\s*class\s+.*\(\):.*")
+ for f, pep8_type in files:
+ for i, l in enumerate(open(f, 'r', encoding='utf8')):
+ if class_check.match(l):
+ print("%s:%d:0: empty class (), remove" % (f, i + 1))
+ del re, class_check
print("\n\n\n# running pep8...")
# these are very picky and often hard to follow
# while keeping common script formatting.
- ignore = "E122", "E123", "E124", "E125", "E126", "E127", "E128"
+ ignore = (
+ "E122",
+ "E123",
+ "E124",
+ "E125",
+ "E126",
+ "E127",
+ "E128",
+ # "imports not at top of file."
+ # prefer to load as needed (lazy load addons etc).
+ "E402",
+ )
for f, pep8_type in files:
diff --git a/tests/python/rst_to_doctree_mini.py b/tests/python/rst_to_doctree_mini.py
index 6a885a108f8..dfc6cd57db6 100644
--- a/tests/python/rst_to_doctree_mini.py
+++ b/tests/python/rst_to_doctree_mini.py
@@ -28,13 +28,14 @@
import collections
-Directive = collections.namedtuple('Directive',
- ("type",
- "value",
- "value_strip",
- "line",
- "indent",
- "members"))
+Directive = collections.namedtuple(
+ "Directive",
+ ("type",
+ "value",
+ "value_strip",
+ "line",
+ "indent",
+ "members"))
def parse_rst_py(filepath):
@@ -80,7 +81,7 @@ def parse_rst_py(filepath):
return tree[0]
-if __name__ == "__main__":
+def main():
# not intended use, but may as well print rst files passed as a test.
import sys
for arg in sys.argv:
@@ -88,3 +89,7 @@ if __name__ == "__main__":
items = parse_rst_py(arg)
for i in items:
print(i)
+
+
+if __name__ == "__main__":
+ main()